diff --git a/CREDITS b/CREDITS
index afaa7ce..206d0fc 100644
--- a/CREDITS
+++ b/CREDITS
@@ -761,6 +761,10 @@ S: Northampton
 S: NN1 3QT
 S: United Kingdom
 
+N: Massimo Dal Zotto
+E: dz@debian.org
+D: i8k Dell laptop SMM driver
+
 N: Uwe Dannowski
 E: Uwe.Dannowski@ira.uka.de
 W: http://i30www.ira.uka.de/~dannowsk/
diff --git a/Documentation/ABI/testing/sysfs-block-bcache b/Documentation/ABI/testing/sysfs-block-bcache
new file mode 100644
index 0000000..9e4bbc5
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-block-bcache
@@ -0,0 +1,156 @@
+What:		/sys/block/<disk>/bcache/unregister
+Date:		November 2010
+Contact:	Kent Overstreet <kent.overstreet@gmail.com>
+Description:
+		A write to this file causes the backing device or cache to be
+		unregistered. If a backing device had dirty data in the cache,
+		writeback mode is automatically disabled and all dirty data is
+		flushed before the device is unregistered. Caches unregister
+		all associated backing devices before unregistering themselves.
+
+What:		/sys/block/<disk>/bcache/clear_stats
+Date:		November 2010
+Contact:	Kent Overstreet <kent.overstreet@gmail.com>
+Description:
+		Writing to this file resets all the statistics for the device.
+
+What:		/sys/block/<disk>/bcache/cache
+Date:		November 2010
+Contact:	Kent Overstreet <kent.overstreet@gmail.com>
+Description:
+		For a backing device that has cache, a symlink to
+		the bcache/ dir of that cache.
+
+What:		/sys/block/<disk>/bcache/cache_hits
+Date:		November 2010
+Contact:	Kent Overstreet <kent.overstreet@gmail.com>
+Description:
+		For backing devices: integer number of full cache hits,
+		counted per bio. A partial cache hit counts as a miss.
+
+What:		/sys/block/<disk>/bcache/cache_misses
+Date:		November 2010
+Contact:	Kent Overstreet <kent.overstreet@gmail.com>
+Description:
+		For backing devices: integer number of cache misses.
+
+What:		/sys/block/<disk>/bcache/cache_hit_ratio
+Date:		November 2010
+Contact:	Kent Overstreet <kent.overstreet@gmail.com>
+Description:
+		For backing devices: cache hits as a percentage.
+
+What:		/sys/block/<disk>/bcache/sequential_cutoff
+Date:		November 2010
+Contact:	Kent Overstreet <kent.overstreet@gmail.com>
+Description:
+		For backing devices: Threshold past which sequential IO will
+		skip the cache. Read and written as bytes in human readable
+		units (i.e. echo 10M > sequntial_cutoff).
+
+What:		/sys/block/<disk>/bcache/bypassed
+Date:		November 2010
+Contact:	Kent Overstreet <kent.overstreet@gmail.com>
+Description:
+		Sum of all reads and writes that have bypassed the cache (due
+		to the sequential cutoff).  Expressed as bytes in human
+		readable units.
+
+What:		/sys/block/<disk>/bcache/writeback
+Date:		November 2010
+Contact:	Kent Overstreet <kent.overstreet@gmail.com>
+Description:
+		For backing devices: When on, writeback caching is enabled and
+		writes will be buffered in the cache. When off, caching is in
+		writethrough mode; reads and writes will be added to the
+		cache but no write buffering will take place.
+
+What:		/sys/block/<disk>/bcache/writeback_running
+Date:		November 2010
+Contact:	Kent Overstreet <kent.overstreet@gmail.com>
+Description:
+		For backing devices: when off, dirty data will not be written
+		from the cache to the backing device. The cache will still be
+		used to buffer writes until it is mostly full, at which point
+		writes transparently revert to writethrough mode. Intended only
+		for benchmarking/testing.
+
+What:		/sys/block/<disk>/bcache/writeback_delay
+Date:		November 2010
+Contact:	Kent Overstreet <kent.overstreet@gmail.com>
+Description:
+		For backing devices: In writeback mode, when dirty data is
+		written to the cache and the cache held no dirty data for that
+		backing device, writeback from cache to backing device starts
+		after this delay, expressed as an integer number of seconds.
+
+What:		/sys/block/<disk>/bcache/writeback_percent
+Date:		November 2010
+Contact:	Kent Overstreet <kent.overstreet@gmail.com>
+Description:
+		For backing devices: If nonzero, writeback from cache to
+		backing device only takes place when more than this percentage
+		of the cache is used, allowing more write coalescing to take
+		place and reducing total number of writes sent to the backing
+		device. Integer between 0 and 40.
+
+What:		/sys/block/<disk>/bcache/synchronous
+Date:		November 2010
+Contact:	Kent Overstreet <kent.overstreet@gmail.com>
+Description:
+		For a cache, a boolean that allows synchronous mode to be
+		switched on and off. In synchronous mode all writes are ordered
+		such that the cache can reliably recover from unclean shutdown;
+		if disabled bcache will not generally wait for writes to
+		complete but if the cache is not shut down cleanly all data
+		will be discarded from the cache. Should not be turned off with
+		writeback caching enabled.
+
+What:		/sys/block/<disk>/bcache/discard
+Date:		November 2010
+Contact:	Kent Overstreet <kent.overstreet@gmail.com>
+Description:
+		For a cache, a boolean allowing discard/TRIM to be turned off
+		or back on if the device supports it.
+
+What:		/sys/block/<disk>/bcache/bucket_size
+Date:		November 2010
+Contact:	Kent Overstreet <kent.overstreet@gmail.com>
+Description:
+		For a cache, bucket size in human readable units, as set at
+		cache creation time; should match the erase block size of the
+		SSD for optimal performance.
+
+What:		/sys/block/<disk>/bcache/nbuckets
+Date:		November 2010
+Contact:	Kent Overstreet <kent.overstreet@gmail.com>
+Description:
+		For a cache, the number of usable buckets.
+
+What:		/sys/block/<disk>/bcache/tree_depth
+Date:		November 2010
+Contact:	Kent Overstreet <kent.overstreet@gmail.com>
+Description:
+		For a cache, height of the btree excluding leaf nodes (i.e. a
+		one node tree will have a depth of 0).
+
+What:		/sys/block/<disk>/bcache/btree_cache_size
+Date:		November 2010
+Contact:	Kent Overstreet <kent.overstreet@gmail.com>
+Description:
+		Number of btree buckets/nodes that are currently cached in
+		memory; cache dynamically grows and shrinks in response to
+		memory pressure from the rest of the system.
+
+What:		/sys/block/<disk>/bcache/written
+Date:		November 2010
+Contact:	Kent Overstreet <kent.overstreet@gmail.com>
+Description:
+		For a cache, total amount of data in human readable units
+		written to the cache, excluding all metadata.
+
+What:		/sys/block/<disk>/bcache/btree_written
+Date:		November 2010
+Contact:	Kent Overstreet <kent.overstreet@gmail.com>
+Description:
+		For a cache, sum of all btree writes in human readable units.
diff --git a/Documentation/ABI/testing/sysfs-bus-mei b/Documentation/ABI/testing/sysfs-bus-mei
new file mode 100644
index 0000000..2066f0b
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-bus-mei
@@ -0,0 +1,7 @@
+What:		/sys/bus/mei/devices/.../modalias
+Date:		March 2013
+KernelVersion:	3.10
+Contact:	Samuel Ortiz <sameo@linux.intel.com>
+		linux-mei@linux.intel.com
+Description:	Stores the same MODALIAS value emitted by uevent
+		Format: mei:<mei device name>
diff --git a/Documentation/ABI/testing/sysfs-bus-usb b/Documentation/ABI/testing/sysfs-bus-usb
index c8baaf5..f093e59 100644
--- a/Documentation/ABI/testing/sysfs-bus-usb
+++ b/Documentation/ABI/testing/sysfs-bus-usb
@@ -32,7 +32,7 @@ Date:		January 2008
 KernelVersion:	2.6.25
 Contact:	Sarah Sharp <sarah.a.sharp@intel.com>
 Description:
-		If CONFIG_PM and CONFIG_USB_SUSPEND are enabled, then this file
+		If CONFIG_PM_RUNTIME is enabled then this file
 		is present.  When read, it returns the total time (in msec)
 		that the USB device has been connected to the machine.  This
 		file is read-only.
@@ -45,7 +45,7 @@ Date:		January 2008
 KernelVersion:	2.6.25
 Contact:	Sarah Sharp <sarah.a.sharp@intel.com>
 Description:
-		If CONFIG_PM and CONFIG_USB_SUSPEND are enabled, then this file
+		If CONFIG_PM_RUNTIME is enabled then this file
 		is present.  When read, it returns the total time (in msec)
 		that the USB device has been active, i.e. not in a suspended
 		state.  This file is read-only.
@@ -187,7 +187,7 @@ What:		/sys/bus/usb/devices/.../power/usb2_hardware_lpm
 Date:		September 2011
 Contact:	Andiry Xu <andiry.xu@amd.com>
 Description:
-		If CONFIG_USB_SUSPEND is set and a USB 2.0 lpm-capable device
+		If CONFIG_PM_RUNTIME is set and a USB 2.0 lpm-capable device
 		is plugged in to a xHCI host which support link PM, it will
 		perform a LPM test; if the test is passed and host supports
 		USB2 hardware LPM (xHCI 1.0 feature), USB2 hardware LPM will
diff --git a/Documentation/ABI/testing/sysfs-class-mtd b/Documentation/ABI/testing/sysfs-class-mtd
index 938ef71..3105644 100644
--- a/Documentation/ABI/testing/sysfs-class-mtd
+++ b/Documentation/ABI/testing/sysfs-class-mtd
@@ -14,8 +14,7 @@ Description:
 		The /sys/class/mtd/mtd{0,1,2,3,...} directories correspond
 		to each /dev/mtdX character device.  These may represent
 		physical/simulated flash devices, partitions on a flash
-		device, or concatenated flash devices.  They exist regardless
-		of whether CONFIG_MTD_CHAR is actually enabled.
+		device, or concatenated flash devices.
 
 What:		/sys/class/mtd/mtdXro/
 Date:		April 2009
@@ -23,8 +22,7 @@ KernelVersion:	2.6.29
 Contact:	linux-mtd@lists.infradead.org
 Description:
 		These directories provide the corresponding read-only device
-		nodes for /sys/class/mtd/mtdX/ .  They are only created
-		(for the benefit of udev) if CONFIG_MTD_CHAR is enabled.
+		nodes for /sys/class/mtd/mtdX/ .
 
 What:		/sys/class/mtd/mtdX/dev
 Date:		April 2009
diff --git a/Documentation/ABI/testing/sysfs-class-net-mesh b/Documentation/ABI/testing/sysfs-class-net-mesh
index bc41da6..bdcd8b4 100644
--- a/Documentation/ABI/testing/sysfs-class-net-mesh
+++ b/Documentation/ABI/testing/sysfs-class-net-mesh
@@ -67,6 +67,14 @@ Description:
                 Defines the penalty which will be applied to an
                 originator message's tq-field on every hop.
 
+What:           /sys/class/net/<mesh_iface>/mesh/network_coding
+Date:           Nov 2012
+Contact:        Martin Hundeboll <martin@hundeboll.net>
+Description:
+                Controls whether Network Coding (using some magic
+                to send fewer wifi packets but still the same
+                content) is enabled or not.
+
 What:           /sys/class/net/<mesh_iface>/mesh/orig_interval
 Date:           May 2010
 Contact:        Marek Lindner <lindner_marek@yahoo.de>
diff --git a/Documentation/ABI/testing/sysfs-devices-lpss_ltr b/Documentation/ABI/testing/sysfs-devices-lpss_ltr
new file mode 100644
index 0000000..ea9298d
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-devices-lpss_ltr
@@ -0,0 +1,44 @@
+What:		/sys/devices/.../lpss_ltr/
+Date:		March 2013
+Contact:	Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Description:
+		The /sys/devices/.../lpss_ltr/ directory is only present for
+		devices included into the Intel Lynxpoint Low Power Subsystem
+		(LPSS).  If present, it contains attributes containing the LTR
+		mode and the values of LTR registers of the device.
+
+What:		/sys/devices/.../lpss_ltr/ltr_mode
+Date:		March 2013
+Contact:	Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Description:
+		The /sys/devices/.../lpss_ltr/ltr_mode attribute contains an
+		integer number (0 or 1) indicating whether or not the devices'
+		LTR functionality is working in the software mode (1).
+
+		This attribute is read-only.  If the device's runtime PM status
+		is not "active", attempts to read from this attribute cause
+		-EAGAIN to be returned.
+
+What:		/sys/devices/.../lpss_ltr/auto_ltr
+Date:		March 2013
+Contact:	Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Description:
+		The /sys/devices/.../lpss_ltr/auto_ltr attribute contains the
+		current value of the device's AUTO_LTR register (raw)
+		represented as an 8-digit hexadecimal number.
+
+		This attribute is read-only.  If the device's runtime PM status
+		is not "active", attempts to read from this attribute cause
+		-EAGAIN to be returned.
+
+What:		/sys/devices/.../lpss_ltr/sw_ltr
+Date:		March 2013
+Contact:	Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Description:
+		The /sys/devices/.../lpss_ltr/auto_ltr attribute contains the
+		current value of the device's SW_LTR register (raw) represented
+		as an 8-digit hexadecimal number.
+
+		This attribute is read-only.  If the device's runtime PM status
+		is not "active", attempts to read from this attribute cause
+		-EAGAIN to be returned.
diff --git a/Documentation/ABI/testing/sysfs-devices-system-cpu b/Documentation/ABI/testing/sysfs-devices-system-cpu
index 9c978dc..2447698 100644
--- a/Documentation/ABI/testing/sysfs-devices-system-cpu
+++ b/Documentation/ABI/testing/sysfs-devices-system-cpu
@@ -173,3 +173,15 @@ Description:	Processor frequency boosting control
 		Boosting allows the CPU and the firmware to run at a frequency
 		beyound it's nominal limit.
 		More details can be found in Documentation/cpu-freq/boost.txt
+
+
+What:		/sys/devices/system/cpu/cpu#/crash_notes
+		/sys/devices/system/cpu/cpu#/crash_notes_size
+Date:		April 2013
+Contact:	kexec@lists.infradead.org
+Description:	address and size of the percpu note.
+
+		crash_notes: the physical address of the memory that holds the
+		note of cpu#.
+
+		crash_notes_size: size of the note of cpu#.
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-isku b/Documentation/ABI/testing/sysfs-driver-hid-roccat-isku
index 9eca5a1..c601d0f 100644
--- a/Documentation/ABI/testing/sysfs-driver-hid-roccat-isku
+++ b/Documentation/ABI/testing/sysfs-driver-hid-roccat-isku
@@ -101,7 +101,8 @@ Date:		June 2011
 Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
 Description:	When written, this file lets one set the backlight intensity for
 		a specific profile. Profile number is included in written data.
-		The data has to be 10 bytes long.
+		The data has to be 10 bytes long for Isku, IskuFX needs	16 bytes
+		of data.
 		Before reading this file, control has to be written to select
 		which profile to read.
 Users:		http://roccat.sourceforge.net
@@ -141,3 +142,12 @@ Description:	When written, this file lets one trigger easyshift functionality
 		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>/isku/roccatisku<minor>/talkfx
+Date:		February 2013
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	When written, this file lets one trigger temporary color schemes
+		from the host.
+		The data has to be 16 bytes long.
+		This file is writeonly.
+Users:		http://roccat.sourceforge.net
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-konepure b/Documentation/ABI/testing/sysfs-driver-hid-roccat-konepure
new file mode 100644
index 0000000..41a9b7f
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-driver-hid-roccat-konepure
@@ -0,0 +1,105 @@
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/konepure/roccatkonepure<minor>/actual_profile
+Date:		December 2012
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	The mouse can store 5 profiles which can be switched by the
+		press of a button. actual_profile holds number of actual profile.
+		This value is persistent, so its value determines the profile
+		that's active when the mouse is powered on next time.
+		When written, the mouse activates the set profile immediately.
+		The data has to be 3 bytes long.
+		The mouse will reject invalid data.
+Users:		http://roccat.sourceforge.net
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/konepure/roccatkonepure<minor>/control
+Date:		December 2012
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	When written, this file lets one select which data from which
+		profile will be	read next. The data has to be 3 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>/konepure/roccatkonepure<minor>/info
+Date:		December 2012
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	When read, this file returns general data like firmware version.
+		When written, the device can be reset.
+		The data is 6 bytes long.
+Users:		http://roccat.sourceforge.net
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/konepure/roccatkonepure<minor>/macro
+Date:		December 2012
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	The mouse can store a macro with max 500 key/button strokes
+		internally.
+		When written, this file lets one set the sequence for a specific
+		button for a specific profile. Button and profile numbers are
+		included in written data. The data has to be 2082 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>/konepure/roccatkonepure<minor>/profile_buttons
+Date:		December 2012
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	The mouse can store 5 profiles which can be switched by the
+		press of a button. A profile is split in settings and buttons.
+		profile_buttons holds information about button layout.
+		When written, this file lets one write the respective profile
+		buttons back to the mouse. The data has to be 59 bytes long.
+		The mouse will reject invalid data.
+		Which profile to write is determined by the profile number
+		contained in the data.
+		Before reading this file, control has to be written to select
+		which profile to read.
+Users:		http://roccat.sourceforge.net
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/konepure/roccatkonepure<minor>/profile_settings
+Date:		December 2012
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	The mouse can store 5 profiles which can be switched by the
+		press of a button. A profile is split in settings and buttons.
+		profile_settings holds information like resolution, sensitivity
+		and light effects.
+		When written, this file lets one write the respective profile
+		settings back to the mouse. The data has to be 31 bytes long.
+		The mouse will reject invalid data.
+		Which profile to write is determined by the profile number
+		contained in the data.
+		Before reading this file, control has to be written to select
+		which profile to read.
+Users:		http://roccat.sourceforge.net
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/konepure/roccatkonepure<minor>/sensor
+Date:		December 2012
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	The mouse has a tracking- and a distance-control-unit. These
+		can be activated/deactivated and the lift-off distance can be
+		set. The data has to be 6 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>/konepure/roccatkonepure<minor>/talk
+Date:		December 2012
+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>/konepure/roccatkonepure<minor>/tcu
+Date:		December 2012
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	When written a calibration process for the tracking control unit
+		can be initiated/cancelled. Also lets one read/write sensor
+		registers.
+		The data has to be 4 bytes long.
+Users:		http://roccat.sourceforge.net
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/konepure/roccatkonepure<minor>/tcu_image
+Date:		December 2012
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	When read the mouse returns a 30x30 pixel image of the
+		sampled underground. This works only in the course of a
+		calibration process initiated with tcu.
+		The returned data is 1028 bytes in size.
+		This file is readonly.
+Users:		http://roccat.sourceforge.net
diff --git a/Documentation/ABI/testing/sysfs-firmware-acpi b/Documentation/ABI/testing/sysfs-firmware-acpi
index dd930c8..ce9bee9 100644
--- a/Documentation/ABI/testing/sysfs-firmware-acpi
+++ b/Documentation/ABI/testing/sysfs-firmware-acpi
@@ -18,6 +18,32 @@ Description:
 		yoffset: The number of pixels between the top of the screen
 			 and the top edge of the image.
 
+What:		/sys/firmware/acpi/hotplug/
+Date:		February 2013
+Contact:	Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Description:
+		There are separate hotplug profiles for different classes of
+		devices supported by ACPI, such as containers, memory modules,
+		processors, PCI root bridges etc.  A hotplug profile for a given
+		class of devices is a collection of settings defining the way
+		that class of devices will be handled by the ACPI core hotplug
+		code.  Those profiles are represented in sysfs as subdirectories
+		of /sys/firmware/acpi/hotplug/.
+
+		The following setting is available to user space for each
+		hotplug profile:
+
+		enabled: If set, the ACPI core will handle notifications of
+			hotplug events associated with the given class of
+			devices and will allow those devices to be ejected with
+			the help of the _EJ0 control method.  Unsetting it
+			effectively disables hotplug for the correspoinding
+			class of devices.
+
+		The value of the above attribute is an integer number: 1 (set)
+		or 0 (unset).  Attempts to write any other values to it will
+		cause -EINVAL to be returned.
+
 What:		/sys/firmware/acpi/interrupts/
 Date:		February 2008
 Contact:	Len Brown <lenb@kernel.org>
diff --git a/Documentation/DocBook/80211.tmpl b/Documentation/DocBook/80211.tmpl
index 284ced7..0f6a3ed 100644
--- a/Documentation/DocBook/80211.tmpl
+++ b/Documentation/DocBook/80211.tmpl
@@ -437,7 +437,7 @@
       </section>
 !Finclude/net/mac80211.h ieee80211_get_buffered_bc
 !Finclude/net/mac80211.h ieee80211_beacon_get
-!Finclude/net/mac80211.h ieee80211_sta_eosp_irqsafe
+!Finclude/net/mac80211.h ieee80211_sta_eosp
 !Finclude/net/mac80211.h ieee80211_frame_release_type
 !Finclude/net/mac80211.h ieee80211_sta_ps_transition
 !Finclude/net/mac80211.h ieee80211_sta_ps_transition_ni
diff --git a/Documentation/DocBook/device-drivers.tmpl b/Documentation/DocBook/device-drivers.tmpl
index 7514dbf..c36892c 100644
--- a/Documentation/DocBook/device-drivers.tmpl
+++ b/Documentation/DocBook/device-drivers.tmpl
@@ -227,7 +227,7 @@ X!Isound/sound_firmware.c
   <chapter id="uart16x50">
      <title>16x50 UART Driver</title>
 !Edrivers/tty/serial/serial_core.c
-!Edrivers/tty/serial/8250/8250.c
+!Edrivers/tty/serial/8250/8250_core.c
   </chapter>
 
   <chapter id="fbdev">
diff --git a/Documentation/DocBook/media/dvb/dvbproperty.xml b/Documentation/DocBook/media/dvb/dvbproperty.xml
index 4a5eaee..a9b15e3 100644
--- a/Documentation/DocBook/media/dvb/dvbproperty.xml
+++ b/Documentation/DocBook/media/dvb/dvbproperty.xml
@@ -1,6 +1,6 @@
 <section id="FE_GET_SET_PROPERTY">
 <title><constant>FE_GET_PROPERTY/FE_SET_PROPERTY</constant></title>
-<para>This section describes the DVB version 5 extention of the DVB-API, also
+<para>This section describes the DVB version 5 extension of the DVB-API, also
 called "S2API", as this API were added to provide support for DVB-S2. It was
 designed to be able to replace the old frontend API. Yet, the DISEQC and
 the capability ioctls weren't implemented yet via the new way.</para>
@@ -903,14 +903,12 @@ enum fe_interleaving {
 			<constant>svalue</constant> is for signed values of the measure (dB measures)
 			and <constant>uvalue</constant> is for unsigned values (counters, relative scale)</para></listitem>
 		<listitem><para><constant>scale</constant> - Scale for the value. It can be:</para>
-			<section id = "fecap-scale-params">
-			<itemizedlist mark='bullet'>
+			<itemizedlist mark='bullet' id="fecap-scale-params">
 				<listitem><para><constant>FE_SCALE_NOT_AVAILABLE</constant> - The parameter is supported by the frontend, but it was not possible to collect it (could be a transitory or permanent condition)</para></listitem>
 				<listitem><para><constant>FE_SCALE_DECIBEL</constant> - parameter is a signed value, measured in 1/1000 dB</para></listitem>
 				<listitem><para><constant>FE_SCALE_RELATIVE</constant> - parameter is a unsigned value, where 0 means 0% and 65535 means 100%.</para></listitem>
 				<listitem><para><constant>FE_SCALE_COUNTER</constant> - parameter is a unsigned value that counts the occurrence of an event, like bit error, block error, or lapsed time.</para></listitem>
 			</itemizedlist>
-			</section>
 		</listitem>
 	</itemizedlist>
 	<section id="DTV-STAT-SIGNAL-STRENGTH">
@@ -918,9 +916,9 @@ enum fe_interleaving {
 		<para>Indicates the signal strength level at the analog part of the tuner or of the demod.</para>
 		<para>Possible scales for this metric are:</para>
 		<itemizedlist mark='bullet'>
-			<listitem><constant>FE_SCALE_NOT_AVAILABLE</constant> - it failed to measure it, or the measurement was not complete yet.</listitem>
-			<listitem><constant>FE_SCALE_DECIBEL</constant> - signal strength is in 0.0001 dBm units, power measured in miliwatts. This value is generally negative.</listitem>
-			<listitem><constant>FE_SCALE_RELATIVE</constant> - The frontend provides a 0% to 100% measurement for power (actually, 0 to 65535).</listitem>
+			<listitem><para><constant>FE_SCALE_NOT_AVAILABLE</constant> - it failed to measure it, or the measurement was not complete yet.</para></listitem>
+			<listitem><para><constant>FE_SCALE_DECIBEL</constant> - signal strength is in 0.0001 dBm units, power measured in miliwatts. This value is generally negative.</para></listitem>
+			<listitem><para><constant>FE_SCALE_RELATIVE</constant> - The frontend provides a 0% to 100% measurement for power (actually, 0 to 65535).</para></listitem>
 		</itemizedlist>
 	</section>
 	<section id="DTV-STAT-CNR">
@@ -928,9 +926,9 @@ enum fe_interleaving {
 		<para>Indicates the Signal to Noise ratio for the main carrier.</para>
 		<para>Possible scales for this metric are:</para>
 		<itemizedlist mark='bullet'>
-			<listitem><constant>FE_SCALE_NOT_AVAILABLE</constant> - it failed to measure it, or the measurement was not complete yet.</listitem>
-			<listitem><constant>FE_SCALE_DECIBEL</constant> - Signal/Noise ratio is in 0.0001 dB units.</listitem>
-			<listitem><constant>FE_SCALE_RELATIVE</constant> - The frontend provides a 0% to 100% measurement for Signal/Noise (actually, 0 to 65535).</listitem>
+			<listitem><para><constant>FE_SCALE_NOT_AVAILABLE</constant> - it failed to measure it, or the measurement was not complete yet.</para></listitem>
+			<listitem><para><constant>FE_SCALE_DECIBEL</constant> - Signal/Noise ratio is in 0.0001 dB units.</para></listitem>
+			<listitem><para><constant>FE_SCALE_RELATIVE</constant> - The frontend provides a 0% to 100% measurement for Signal/Noise (actually, 0 to 65535).</para></listitem>
 		</itemizedlist>
 	</section>
 	<section id="DTV-STAT-PRE-ERROR-BIT-COUNT">
@@ -943,8 +941,8 @@ enum fe_interleaving {
 		      The frontend may reset it when a channel/transponder is tuned.</para>
 		<para>Possible scales for this metric are:</para>
 		<itemizedlist mark='bullet'>
-			<listitem><constant>FE_SCALE_NOT_AVAILABLE</constant> - it failed to measure it, or the measurement was not complete yet.</listitem>
-			<listitem><constant>FE_SCALE_COUNTER</constant> - Number of error bits counted before the inner coding.</listitem>
+			<listitem><para><constant>FE_SCALE_NOT_AVAILABLE</constant> - it failed to measure it, or the measurement was not complete yet.</para></listitem>
+			<listitem><para><constant>FE_SCALE_COUNTER</constant> - Number of error bits counted before the inner coding.</para></listitem>
 		</itemizedlist>
 	</section>
 	<section id="DTV-STAT-PRE-TOTAL-BIT-COUNT">
@@ -952,14 +950,14 @@ enum fe_interleaving {
 		<para>Measures the amount of bits received before the inner code block, during the same period as
 		<link linkend="DTV-STAT-PRE-ERROR-BIT-COUNT"><constant>DTV_STAT_PRE_ERROR_BIT_COUNT</constant></link> measurement was taken.</para>
 		<para>It should be noticed that this measurement can be smaller than the total amount of bits on the transport stream,
-		      as the frontend may need to manually restart the measurement, loosing some data between each measurement interval.</para>
+		      as the frontend may need to manually restart the measurement, losing some data between each measurement interval.</para>
 		<para>This measurement is monotonically increased, as the frontend gets more bit count measurements.
 		      The frontend may reset it when a channel/transponder is tuned.</para>
 		<para>Possible scales for this metric are:</para>
 		<itemizedlist mark='bullet'>
-			<listitem><constant>FE_SCALE_NOT_AVAILABLE</constant> - it failed to measure it, or the measurement was not complete yet.</listitem>
-			<listitem><constant>FE_SCALE_COUNTER</constant> - Number of bits counted while measuring
-				 <link linkend="DTV-STAT-PRE-ERROR-BIT-COUNT"><constant>DTV_STAT_PRE_ERROR_BIT_COUNT</constant></link>.</listitem>
+			<listitem><para><constant>FE_SCALE_NOT_AVAILABLE</constant> - it failed to measure it, or the measurement was not complete yet.</para></listitem>
+			<listitem><para><constant>FE_SCALE_COUNTER</constant> - Number of bits counted while measuring
+				 <link linkend="DTV-STAT-PRE-ERROR-BIT-COUNT"><constant>DTV_STAT_PRE_ERROR_BIT_COUNT</constant></link>.</para></listitem>
 		</itemizedlist>
 	</section>
 	<section id="DTV-STAT-POST-ERROR-BIT-COUNT">
@@ -972,8 +970,8 @@ enum fe_interleaving {
 		      The frontend may reset it when a channel/transponder is tuned.</para>
 		<para>Possible scales for this metric are:</para>
 		<itemizedlist mark='bullet'>
-			<listitem><constant>FE_SCALE_NOT_AVAILABLE</constant> - it failed to measure it, or the measurement was not complete yet.</listitem>
-			<listitem><constant>FE_SCALE_COUNTER</constant> - Number of error bits counted after the inner coding.</listitem>
+			<listitem><para><constant>FE_SCALE_NOT_AVAILABLE</constant> - it failed to measure it, or the measurement was not complete yet.</para></listitem>
+			<listitem><para><constant>FE_SCALE_COUNTER</constant> - Number of error bits counted after the inner coding.</para></listitem>
 		</itemizedlist>
 	</section>
 	<section id="DTV-STAT-POST-TOTAL-BIT-COUNT">
@@ -981,14 +979,14 @@ enum fe_interleaving {
 		<para>Measures the amount of bits received after the inner coding, during the same period as
 		<link linkend="DTV-STAT-POST-ERROR-BIT-COUNT"><constant>DTV_STAT_POST_ERROR_BIT_COUNT</constant></link> measurement was taken.</para>
 		<para>It should be noticed that this measurement can be smaller than the total amount of bits on the transport stream,
-		      as the frontend may need to manually restart the measurement, loosing some data between each measurement interval.</para>
+		      as the frontend may need to manually restart the measurement, losing some data between each measurement interval.</para>
 		<para>This measurement is monotonically increased, as the frontend gets more bit count measurements.
 		      The frontend may reset it when a channel/transponder is tuned.</para>
 		<para>Possible scales for this metric are:</para>
 		<itemizedlist mark='bullet'>
-			<listitem><constant>FE_SCALE_NOT_AVAILABLE</constant> - it failed to measure it, or the measurement was not complete yet.</listitem>
-			<listitem><constant>FE_SCALE_COUNTER</constant> - Number of bits counted while measuring
-				 <link linkend="DTV-STAT-POST-ERROR-BIT-COUNT"><constant>DTV_STAT_POST_ERROR_BIT_COUNT</constant></link>.</listitem>
+			<listitem><para><constant>FE_SCALE_NOT_AVAILABLE</constant> - it failed to measure it, or the measurement was not complete yet.</para></listitem>
+			<listitem><para><constant>FE_SCALE_COUNTER</constant> - Number of bits counted while measuring
+				 <link linkend="DTV-STAT-POST-ERROR-BIT-COUNT"><constant>DTV_STAT_POST_ERROR_BIT_COUNT</constant></link>.</para></listitem>
 		</itemizedlist>
 	</section>
 	<section id="DTV-STAT-ERROR-BLOCK-COUNT">
@@ -998,8 +996,8 @@ enum fe_interleaving {
 		      The frontend may reset it when a channel/transponder is tuned.</para>
 		<para>Possible scales for this metric are:</para>
 		<itemizedlist mark='bullet'>
-			<listitem><constant>FE_SCALE_NOT_AVAILABLE</constant> - it failed to measure it, or the measurement was not complete yet.</listitem>
-			<listitem><constant>FE_SCALE_COUNTER</constant> - Number of error blocks counted after the outer coding.</listitem>
+			<listitem><para><constant>FE_SCALE_NOT_AVAILABLE</constant> - it failed to measure it, or the measurement was not complete yet.</para></listitem>
+			<listitem><para><constant>FE_SCALE_COUNTER</constant> - Number of error blocks counted after the outer coding.</para></listitem>
 		</itemizedlist>
 	</section>
 	<section id="DTV-STAT-TOTAL-BLOCK-COUNT">
@@ -1011,9 +1009,9 @@ enum fe_interleaving {
 		by <link linkend="DTV-STAT-TOTAL-BLOCK-COUNT"><constant>DTV-STAT-TOTAL-BLOCK-COUNT</constant></link>.</para>
 		<para>Possible scales for this metric are:</para>
 		<itemizedlist mark='bullet'>
-			<listitem><constant>FE_SCALE_NOT_AVAILABLE</constant> - it failed to measure it, or the measurement was not complete yet.</listitem>
-			<listitem><constant>FE_SCALE_COUNTER</constant> - Number of blocks counted while measuring
-			<link linkend="DTV-STAT-ERROR-BLOCK-COUNT"><constant>DTV_STAT_ERROR_BLOCK_COUNT</constant></link>.</listitem>
+			<listitem><para><constant>FE_SCALE_NOT_AVAILABLE</constant> - it failed to measure it, or the measurement was not complete yet.</para></listitem>
+			<listitem><para><constant>FE_SCALE_COUNTER</constant> - Number of blocks counted while measuring
+			<link linkend="DTV-STAT-ERROR-BLOCK-COUNT"><constant>DTV_STAT_ERROR_BLOCK_COUNT</constant></link>.</para></listitem>
 		</itemizedlist>
 	</section>
 	</section>
diff --git a/Documentation/DocBook/media/v4l/common.xml b/Documentation/DocBook/media/v4l/common.xml
index ae06afb..1ddf354 100644
--- a/Documentation/DocBook/media/v4l/common.xml
+++ b/Documentation/DocBook/media/v4l/common.xml
@@ -750,15 +750,6 @@ header can be used to get the timings of the formats in the <xref linkend="cea86
 <xref linkend="vesadmt" /> standards.
 	</para>
 	</listitem>
-	<listitem>
-	<para>DV Presets: Digital Video (DV) presets (<emphasis role="bold">deprecated</emphasis>).
-	These are IDs representing a
-video timing at the input/output. Presets are pre-defined timings implemented
-by the hardware according to video standards. A __u32 data type is used to represent
-a preset unlike the bit mask that is used in &v4l2-std-id; allowing future extensions
-to support as many different presets as needed. This API is deprecated in favor of the DV Timings
-API.</para>
-	</listitem>
 	</itemizedlist>
 	<para>To enumerate and query the attributes of the DV timings supported by a device,
 	applications use the &VIDIOC-ENUM-DV-TIMINGS; and &VIDIOC-DV-TIMINGS-CAP; ioctls.
@@ -766,11 +757,6 @@ API.</para>
 &VIDIOC-S-DV-TIMINGS; ioctl and to get current DV timings they use the
 &VIDIOC-G-DV-TIMINGS; ioctl. To detect the DV timings as seen by the video receiver applications
 use the &VIDIOC-QUERY-DV-TIMINGS; ioctl.</para>
-	<para>To enumerate and query the attributes of DV presets supported by a device,
-applications use the &VIDIOC-ENUM-DV-PRESETS; ioctl. To get the current DV preset,
-applications use the &VIDIOC-G-DV-PRESET; ioctl and to set a preset they use the
-&VIDIOC-S-DV-PRESET; ioctl. To detect the preset as seen by the video receiver applications
-use the &VIDIOC-QUERY-DV-PRESET; ioctl.</para>
 	<para>Applications can make use of the <xref linkend="input-capabilities" /> and
 <xref linkend="output-capabilities"/> flags to decide what ioctls are available to set the
 video timings for the device.</para>
diff --git a/Documentation/DocBook/media/v4l/compat.xml b/Documentation/DocBook/media/v4l/compat.xml
index 104a1a2..8c2b368 100644
--- a/Documentation/DocBook/media/v4l/compat.xml
+++ b/Documentation/DocBook/media/v4l/compat.xml
@@ -2493,6 +2493,23 @@ that used it. It was originally scheduled for removal in 2.6.35.
       </orderedlist>
     </section>
 
+    <section>
+      <title>V4L2 in Linux 3.10</title>
+      <orderedlist>
+        <listitem>
+	  <para>Removed obsolete and unused DV_PRESET ioctls
+	  VIDIOC_G_DV_PRESET, VIDIOC_S_DV_PRESET, VIDIOC_QUERY_DV_PRESET and
+	  VIDIOC_ENUM_DV_PRESET. Remove the related v4l2_input/output capability
+	  flags V4L2_IN_CAP_PRESETS and V4L2_OUT_CAP_PRESETS.
+	  </para>
+        </listitem>
+        <listitem>
+	  <para>Added new debugging ioctl &VIDIOC-DBG-G-CHIP-NAME;.
+	  </para>
+        </listitem>
+      </orderedlist>
+    </section>
+
     <section id="other">
       <title>Relation of V4L2 to other Linux multimedia APIs</title>
 
@@ -2625,8 +2642,8 @@ interfaces and should not be implemented in new drivers.</para>
 <xref linkend="extended-controls" />.</para>
         </listitem>
         <listitem>
-	  <para>&VIDIOC-G-DV-PRESET;, &VIDIOC-S-DV-PRESET;, &VIDIOC-ENUM-DV-PRESETS; and
-	  &VIDIOC-QUERY-DV-PRESET; ioctls. Use the DV Timings API (<xref linkend="dv-timings" />).</para>
+	  <para>VIDIOC_G_DV_PRESET, VIDIOC_S_DV_PRESET, VIDIOC_ENUM_DV_PRESETS and
+	  VIDIOC_QUERY_DV_PRESET ioctls. Use the DV Timings API (<xref linkend="dv-timings" />).</para>
         </listitem>
         <listitem>
 	  <para><constant>VIDIOC_SUBDEV_G_CROP</constant> and
diff --git a/Documentation/DocBook/media/v4l/controls.xml b/Documentation/DocBook/media/v4l/controls.xml
index 9e8f854..b4952e2 100644
--- a/Documentation/DocBook/media/v4l/controls.xml
+++ b/Documentation/DocBook/media/v4l/controls.xml
@@ -2300,6 +2300,12 @@ Possible values are:</entry>
 	      </row>
 	      <row><entry></entry></row>
 	      <row>
+		<entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER</constant>&nbsp;</entry>
+		<entry>boolean</entry>
+	      </row><row><entry spanname="descr">Repeat the video sequence headers. Repeating these
+headers makes random access to the video stream easier. Applicable to the MPEG1, 2 and 4 encoder.</entry>
+	      </row>
+	      <row>
 		<entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER</constant>&nbsp;</entry>
 		<entry>boolean</entry>
 	      </row><row><entry spanname="descr">Enabled the deblocking post processing filter for MPEG4 decoder.
diff --git a/Documentation/DocBook/media/v4l/io.xml b/Documentation/DocBook/media/v4l/io.xml
index e6c5855..2c4c068 100644
--- a/Documentation/DocBook/media/v4l/io.xml
+++ b/Documentation/DocBook/media/v4l/io.xml
@@ -1145,6 +1145,12 @@ in which case caches have not been used.</entry>
 	    same clock outside V4L2, use
 	    <function>clock_gettime(2)</function> .</entry>
 	  </row>
+	  <row>
+	    <entry><constant>V4L2_BUF_FLAG_TIMESTAMP_COPY</constant></entry>
+	    <entry>0x4000</entry>
+	    <entry>The CAPTURE buffer timestamp has been taken from the
+	    corresponding OUTPUT buffer. This flag applies only to mem2mem devices.</entry>
+	  </row>
 	</tbody>
       </tgroup>
     </table>
diff --git a/Documentation/DocBook/media/v4l/media-ioc-enum-entities.xml b/Documentation/DocBook/media/v4l/media-ioc-enum-entities.xml
index 576b68b..116c301 100644
--- a/Documentation/DocBook/media/v4l/media-ioc-enum-entities.xml
+++ b/Documentation/DocBook/media/v4l/media-ioc-enum-entities.xml
@@ -272,6 +272,16 @@
 	    <entry><constant>MEDIA_ENT_T_V4L2_SUBDEV_LENS</constant></entry>
 	    <entry>Lens controller</entry>
 	  </row>
+	  <row>
+	    <entry><constant>MEDIA_ENT_T_V4L2_SUBDEV_DECODER</constant></entry>
+	    <entry>Video decoder, the basic function of the video decoder is to
+	    accept analogue video from a wide variety of sources such as
+	    broadcast, DVD players, cameras and video cassette recorders, in
+	    either NTSC, PAL or HD format and still occasionally SECAM, separate
+	    it into its component parts, luminance and chrominance, and output
+	    it in some digital video standard, with appropriate embedded timing
+	    signals.</entry>
+	  </row>
 	</tbody>
       </tgroup>
     </table>
diff --git a/Documentation/DocBook/media/v4l/v4l2.xml b/Documentation/DocBook/media/v4l/v4l2.xml
index a3cce18..c1f3340 100644
--- a/Documentation/DocBook/media/v4l/v4l2.xml
+++ b/Documentation/DocBook/media/v4l/v4l2.xml
@@ -124,6 +124,7 @@ Remote Controller chapter.</contrib>
       <year>2010</year>
       <year>2011</year>
       <year>2012</year>
+      <year>2013</year>
       <holder>Bill Dirks, Michael H. Schimek, Hans Verkuil, Martin
 Rubli, Andy Walls, Muralidharan Karicheri, Mauro Carvalho Chehab,
 	Pawel Osciak</holder>
@@ -140,12 +141,22 @@ structs, ioctls) must be noted in more detail in the history chapter
 applications. -->
 
       <revision>
+	<revnumber>3.10</revnumber>
+	<date>2013-03-25</date>
+	<authorinitials>hv</authorinitials>
+	<revremark>Remove obsolete and unused DV_PRESET ioctls:
+	VIDIOC_G_DV_PRESET, VIDIOC_S_DV_PRESET, VIDIOC_QUERY_DV_PRESET and
+	VIDIOC_ENUM_DV_PRESET. Remove the related v4l2_input/output capability
+	flags V4L2_IN_CAP_PRESETS and V4L2_OUT_CAP_PRESETS. Added VIDIOC_DBG_G_CHIP_NAME.
+	</revremark>
+      </revision>
+
+      <revision>
 	<revnumber>3.9</revnumber>
 	<date>2012-12-03</date>
 	<authorinitials>sa, sn</authorinitials>
 	<revremark>Added timestamp types to v4l2_buffer.
-	Added <constant>V4L2_EVENT_CTRL_CH_RANGE</constant> control
-	event changes flag, see <xref linkend="changes-flags"/>.
+	Added V4L2_EVENT_CTRL_CH_RANGE control event changes flag.
 	</revremark>
       </revision>
 
@@ -537,6 +548,7 @@ and discussions on the V4L mailing list.</revremark>
     &sub-create-bufs;
     &sub-cropcap;
     &sub-dbg-g-chip-ident;
+    &sub-dbg-g-chip-name;
     &sub-dbg-g-register;
     &sub-decoder-cmd;
     &sub-dqevent;
@@ -544,7 +556,6 @@ and discussions on the V4L mailing list.</revremark>
     &sub-encoder-cmd;
     &sub-enumaudio;
     &sub-enumaudioout;
-    &sub-enum-dv-presets;
     &sub-enum-dv-timings;
     &sub-enum-fmt;
     &sub-enum-framesizes;
@@ -558,7 +569,6 @@ and discussions on the V4L mailing list.</revremark>
     &sub-g-audioout;
     &sub-g-crop;
     &sub-g-ctrl;
-    &sub-g-dv-preset;
     &sub-g-dv-timings;
     &sub-g-enc-index;
     &sub-g-ext-ctrls;
@@ -582,7 +592,6 @@ and discussions on the V4L mailing list.</revremark>
     &sub-querybuf;
     &sub-querycap;
     &sub-queryctrl;
-    &sub-query-dv-preset;
     &sub-query-dv-timings;
     &sub-querystd;
     &sub-reqbufs;
diff --git a/Documentation/DocBook/media/v4l/vidioc-dbg-g-chip-ident.xml b/Documentation/DocBook/media/v4l/vidioc-dbg-g-chip-ident.xml
index 4ecd966..82e43c6 100644
--- a/Documentation/DocBook/media/v4l/vidioc-dbg-g-chip-ident.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-dbg-g-chip-ident.xml
@@ -200,10 +200,10 @@ the values from <xref linkend="chip-ids" />.</entry>
 	&cs-def;
 	<tbody valign="top">
 	  <row>
-	    <entry><constant>V4L2_CHIP_MATCH_HOST</constant></entry>
+	    <entry><constant>V4L2_CHIP_MATCH_BRIDGE</constant></entry>
 	    <entry>0</entry>
 	    <entry>Match the nth chip on the card, zero for the
-	    host chip. Does not match &i2c; chips.</entry>
+	    bridge chip. Does not match sub-devices.</entry>
 	  </row>
 	  <row>
 	    <entry><constant>V4L2_CHIP_MATCH_I2C_DRIVER</constant></entry>
@@ -220,6 +220,16 @@ the values from <xref linkend="chip-ids" />.</entry>
 	    <entry>3</entry>
 	    <entry>Match the nth anciliary AC97 chip.</entry>
 	  </row>
+	  <row>
+	    <entry><constant>V4L2_CHIP_MATCH_SUBDEV_NAME</constant></entry>
+	    <entry>4</entry>
+	    <entry>Match the sub-device by name. Can't be used with this ioctl.</entry>
+	  </row>
+	  <row>
+	    <entry><constant>V4L2_CHIP_MATCH_SUBDEV_IDX</constant></entry>
+	    <entry>5</entry>
+	    <entry>Match the nth sub-device. Can't be used with this ioctl.</entry>
+	  </row>
 	</tbody>
       </tgroup>
     </table>
diff --git a/Documentation/DocBook/media/v4l/vidioc-dbg-g-chip-name.xml b/Documentation/DocBook/media/v4l/vidioc-dbg-g-chip-name.xml
new file mode 100644
index 0000000..4921346
--- /dev/null
+++ b/Documentation/DocBook/media/v4l/vidioc-dbg-g-chip-name.xml
@@ -0,0 +1,234 @@
+<refentry id="vidioc-dbg-g-chip-name">
+  <refmeta>
+    <refentrytitle>ioctl VIDIOC_DBG_G_CHIP_NAME</refentrytitle>
+    &manvol;
+  </refmeta>
+
+  <refnamediv>
+    <refname>VIDIOC_DBG_G_CHIP_NAME</refname>
+    <refpurpose>Identify the chips on a TV card</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <funcsynopsis>
+      <funcprototype>
+	<funcdef>int <function>ioctl</function></funcdef>
+	<paramdef>int <parameter>fd</parameter></paramdef>
+	<paramdef>int <parameter>request</parameter></paramdef>
+	<paramdef>struct v4l2_dbg_chip_name
+*<parameter>argp</parameter></paramdef>
+      </funcprototype>
+    </funcsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Arguments</title>
+
+    <variablelist>
+      <varlistentry>
+	<term><parameter>fd</parameter></term>
+	<listitem>
+	  <para>&fd;</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><parameter>request</parameter></term>
+	<listitem>
+	  <para>VIDIOC_DBG_G_CHIP_NAME</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><parameter>argp</parameter></term>
+	<listitem>
+	  <para></para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+
+  <refsect1>
+    <title>Description</title>
+
+    <note>
+      <title>Experimental</title>
+
+      <para>This is an <link
+linkend="experimental">experimental</link> interface and may change in
+the future.</para>
+    </note>
+
+    <para>For driver debugging purposes this ioctl allows test
+applications to query the driver about the chips present on the TV
+card. Regular applications must not use it. When you found a chip
+specific bug, please contact the linux-media mailing list (&v4l-ml;)
+so it can be fixed.</para>
+
+    <para>To query the driver applications must initialize the
+<structfield>match.type</structfield> and
+<structfield>match.addr</structfield> or <structfield>match.name</structfield>
+fields of a &v4l2-dbg-chip-name;
+and call <constant>VIDIOC_DBG_G_CHIP_NAME</constant> with a pointer to
+this structure. On success the driver stores information about the
+selected chip in the <structfield>name</structfield> and
+<structfield>flags</structfield> fields. On failure the structure
+remains unchanged.</para>
+
+    <para>When <structfield>match.type</structfield> is
+<constant>V4L2_CHIP_MATCH_BRIDGE</constant>,
+<structfield>match.addr</structfield> selects the nth bridge 'chip'
+on the TV card. You can enumerate all chips by starting at zero and
+incrementing <structfield>match.addr</structfield> by one until
+<constant>VIDIOC_DBG_G_CHIP_NAME</constant> fails with an &EINVAL;.
+The number zero always selects the bridge chip itself, &eg; the chip
+connected to the PCI or USB bus. Non-zero numbers identify specific
+parts of the bridge chip such as an AC97 register block.</para>
+
+    <para>When <structfield>match.type</structfield> is
+<constant>V4L2_CHIP_MATCH_SUBDEV_NAME</constant>,
+<structfield>match.name</structfield> contains the name of a sub-device.
+For instance
+<constant>"saa7127 6-0044"</constant> will match the saa7127 sub-device
+at the given i2c bus. This match type is not very useful for this ioctl
+and is here only for consistency.
+</para>
+
+    <para>When <structfield>match.type</structfield> is
+<constant>V4L2_CHIP_MATCH_SUBDEV_IDX</constant>,
+<structfield>match.addr</structfield> selects the nth sub-device. This
+allows you to enumerate over all sub-devices.</para>
+
+    <para>On success, the <structfield>name</structfield> field will
+contain a chip name and the <structfield>flags</structfield> field will
+contain <constant>V4L2_CHIP_FL_READABLE</constant> if the driver supports
+reading registers from the device or <constant>V4L2_CHIP_FL_WRITABLE</constant>
+if the driver supports writing registers to the device.</para>
+
+    <para>We recommended the <application>v4l2-dbg</application>
+utility over calling this ioctl directly. It is available from the
+LinuxTV v4l-dvb repository; see <ulink
+url="http://linuxtv.org/repo/">http://linuxtv.org/repo/</ulink> for
+access instructions.</para>
+
+    <!-- Note for convenience vidioc-dbg-g-register.sgml
+	 contains a duplicate of this table. -->
+    <table pgwide="1" frame="none" id="name-v4l2-dbg-match">
+      <title>struct <structname>v4l2_dbg_match</structname></title>
+      <tgroup cols="4">
+	&cs-ustr;
+	<tbody valign="top">
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>type</structfield></entry>
+	    <entry>See <xref linkend="name-chip-match-types" /> for a list of
+possible types.</entry>
+	  </row>
+	  <row>
+	    <entry>union</entry>
+	    <entry>(anonymous)</entry>
+	  </row>
+	  <row>
+	    <entry></entry>
+	    <entry>__u32</entry>
+	    <entry><structfield>addr</structfield></entry>
+	    <entry>Match a chip by this number, interpreted according
+to the <structfield>type</structfield> field.</entry>
+	  </row>
+	  <row>
+	    <entry></entry>
+	    <entry>char</entry>
+	    <entry><structfield>name[32]</structfield></entry>
+	    <entry>Match a chip by this name, interpreted according
+to the <structfield>type</structfield> field.</entry>
+	  </row>
+	</tbody>
+      </tgroup>
+    </table>
+
+    <table pgwide="1" frame="none" id="v4l2-dbg-chip-name">
+      <title>struct <structname>v4l2_dbg_chip_name</structname></title>
+      <tgroup cols="3">
+	&cs-str;
+	<tbody valign="top">
+	  <row>
+	    <entry>struct v4l2_dbg_match</entry>
+	    <entry><structfield>match</structfield></entry>
+	    <entry>How to match the chip, see <xref linkend="name-v4l2-dbg-match" />.</entry>
+	  </row>
+	  <row>
+	    <entry>char</entry>
+	    <entry><structfield>name[32]</structfield></entry>
+	    <entry>The name of the chip.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>flags</structfield></entry>
+	    <entry>Set by the driver. If <constant>V4L2_CHIP_FL_READABLE</constant>
+is set, then the driver supports reading registers from the device. If
+<constant>V4L2_CHIP_FL_WRITABLE</constant> is set, then it supports writing registers.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>reserved[8]</structfield></entry>
+	    <entry>Reserved fields, both application and driver must set these to 0.</entry>
+	  </row>
+	</tbody>
+      </tgroup>
+    </table>
+
+    <!-- Note for convenience vidioc-dbg-g-register.sgml
+	 contains a duplicate of this table. -->
+    <table pgwide="1" frame="none" id="name-chip-match-types">
+      <title>Chip Match Types</title>
+      <tgroup cols="3">
+	&cs-def;
+	<tbody valign="top">
+	  <row>
+	    <entry><constant>V4L2_CHIP_MATCH_BRIDGE</constant></entry>
+	    <entry>0</entry>
+	    <entry>Match the nth chip on the card, zero for the
+	    bridge chip. Does not match sub-devices.</entry>
+	  </row>
+	  <row>
+	    <entry><constant>V4L2_CHIP_MATCH_I2C_DRIVER</constant></entry>
+	    <entry>1</entry>
+	    <entry>Match an &i2c; chip by its driver name. Can't be used with this ioctl.</entry>
+	  </row>
+	  <row>
+	    <entry><constant>V4L2_CHIP_MATCH_I2C_ADDR</constant></entry>
+	    <entry>2</entry>
+	    <entry>Match a chip by its 7 bit &i2c; bus address. Can't be used with this ioctl.</entry>
+	  </row>
+	  <row>
+	    <entry><constant>V4L2_CHIP_MATCH_AC97</constant></entry>
+	    <entry>3</entry>
+	    <entry>Match the nth anciliary AC97 chip. Can't be used with this ioctl.</entry>
+	  </row>
+	  <row>
+	    <entry><constant>V4L2_CHIP_MATCH_SUBDEV_NAME</constant></entry>
+	    <entry>4</entry>
+	    <entry>Match the sub-device by name.</entry>
+	  </row>
+	  <row>
+	    <entry><constant>V4L2_CHIP_MATCH_SUBDEV_IDX</constant></entry>
+	    <entry>5</entry>
+	    <entry>Match the nth sub-device.</entry>
+	  </row>
+	</tbody>
+      </tgroup>
+    </table>
+  </refsect1>
+
+  <refsect1>
+    &return-value;
+
+    <variablelist>
+      <varlistentry>
+	<term><errorcode>EINVAL</errorcode></term>
+	<listitem>
+	  <para>The <structfield>match_type</structfield> is invalid or
+no device could be matched.</para>
+	</listitem>
+      </varlistentry>
+     </variablelist>
+  </refsect1>
+</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-dbg-g-register.xml b/Documentation/DocBook/media/v4l/vidioc-dbg-g-register.xml
index a44aebc..3082b41 100644
--- a/Documentation/DocBook/media/v4l/vidioc-dbg-g-register.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-dbg-g-register.xml
@@ -87,7 +87,7 @@ written into the register.</para>
 
     <para>To read a register applications must initialize the
 <structfield>match.type</structfield>,
-<structfield>match.chip</structfield> or <structfield>match.name</structfield> and
+<structfield>match.addr</structfield> or <structfield>match.name</structfield> and
 <structfield>reg</structfield> fields, and call
 <constant>VIDIOC_DBG_G_REGISTER</constant> with a pointer to this
 structure. On success the driver stores the register value in the
@@ -95,11 +95,11 @@ structure. On success the driver stores the register value in the
 unchanged.</para>
 
     <para>When <structfield>match.type</structfield> is
-<constant>V4L2_CHIP_MATCH_HOST</constant>,
-<structfield>match.addr</structfield> selects the nth non-&i2c; chip
+<constant>V4L2_CHIP_MATCH_BRIDGE</constant>,
+<structfield>match.addr</structfield> selects the nth non-sub-device chip
 on the TV card.  The number zero always selects the host chip, &eg; the
 chip connected to the PCI or USB bus. You can find out which chips are
-present with the &VIDIOC-DBG-G-CHIP-IDENT; ioctl.</para>
+present with the &VIDIOC-DBG-G-CHIP-NAME; ioctl.</para>
 
     <para>When <structfield>match.type</structfield> is
 <constant>V4L2_CHIP_MATCH_I2C_DRIVER</constant>,
@@ -109,7 +109,7 @@ For instance
 supported by the saa7127 driver, regardless of its &i2c; bus address.
 When multiple chips supported by the same driver are present, the
 effect of these ioctls is undefined. Again with the
-&VIDIOC-DBG-G-CHIP-IDENT; ioctl you can find out which &i2c; chips are
+&VIDIOC-DBG-G-CHIP-NAME; ioctl you can find out which &i2c; chips are
 present.</para>
 
     <para>When <structfield>match.type</structfield> is
@@ -122,19 +122,31 @@ bus address.</para>
 <structfield>match.addr</structfield> selects the nth AC97 chip
 on the TV card.</para>
 
+    <para>When <structfield>match.type</structfield> is
+<constant>V4L2_CHIP_MATCH_SUBDEV_NAME</constant>,
+<structfield>match.name</structfield> contains the sub-device name.
+For instance
+<constant>"saa7127 6-0044"</constant> will match this specific saa7127
+sub-device. Again with the &VIDIOC-DBG-G-CHIP-NAME; ioctl you can find
+out which sub-devices are present.</para>
+
+    <para>When <structfield>match.type</structfield> is
+<constant>V4L2_CHIP_MATCH_SUBDEV_IDX</constant>,
+<structfield>match.addr</structfield> selects the nth sub-device.</para>
+
     <note>
       <title>Success not guaranteed</title>
 
       <para>Due to a flaw in the Linux &i2c; bus driver these ioctls may
 return successfully without actually reading or writing a register. To
-catch the most likely failure we recommend a &VIDIOC-DBG-G-CHIP-IDENT;
+catch the most likely failure we recommend a &VIDIOC-DBG-G-CHIP-NAME;
 call confirming the presence of the selected &i2c; chip.</para>
     </note>
 
     <para>These ioctls are optional, not all drivers may support them.
 However when a driver supports these ioctls it must also support
-&VIDIOC-DBG-G-CHIP-IDENT;. Conversely it may support
-<constant>VIDIOC_DBG_G_CHIP_IDENT</constant> but not these ioctls.</para>
+&VIDIOC-DBG-G-CHIP-NAME;. Conversely it may support
+<constant>VIDIOC_DBG_G_CHIP_NAME</constant> but not these ioctls.</para>
 
     <para><constant>VIDIOC_DBG_G_REGISTER</constant> and
 <constant>VIDIOC_DBG_S_REGISTER</constant> were introduced in Linux
@@ -217,10 +229,10 @@ register.</entry>
 	&cs-def;
 	<tbody valign="top">
 	  <row>
-	    <entry><constant>V4L2_CHIP_MATCH_HOST</constant></entry>
+	    <entry><constant>V4L2_CHIP_MATCH_BRIDGE</constant></entry>
 	    <entry>0</entry>
 	    <entry>Match the nth chip on the card, zero for the
-	    host chip. Does not match &i2c; chips.</entry>
+	    bridge chip. Does not match sub-devices.</entry>
 	  </row>
 	  <row>
 	    <entry><constant>V4L2_CHIP_MATCH_I2C_DRIVER</constant></entry>
@@ -237,6 +249,16 @@ register.</entry>
 	    <entry>3</entry>
 	    <entry>Match the nth anciliary AC97 chip.</entry>
 	  </row>
+	  <row>
+	    <entry><constant>V4L2_CHIP_MATCH_SUBDEV_NAME</constant></entry>
+	    <entry>4</entry>
+	    <entry>Match the sub-device by name.</entry>
+	  </row>
+	  <row>
+	    <entry><constant>V4L2_CHIP_MATCH_SUBDEV_IDX</constant></entry>
+	    <entry>5</entry>
+	    <entry>Match the nth sub-device.</entry>
+	  </row>
 	</tbody>
       </tgroup>
     </table>
diff --git a/Documentation/DocBook/media/v4l/vidioc-enum-dv-presets.xml b/Documentation/DocBook/media/v4l/vidioc-enum-dv-presets.xml
deleted file mode 100644
index fced5fb..0000000
--- a/Documentation/DocBook/media/v4l/vidioc-enum-dv-presets.xml
+++ /dev/null
@@ -1,240 +0,0 @@
-<refentry id="vidioc-enum-dv-presets">
-  <refmeta>
-    <refentrytitle>ioctl VIDIOC_ENUM_DV_PRESETS</refentrytitle>
-    &manvol;
-  </refmeta>
-
-  <refnamediv>
-    <refname>VIDIOC_ENUM_DV_PRESETS</refname>
-    <refpurpose>Enumerate supported Digital Video presets</refpurpose>
-  </refnamediv>
-
-  <refsynopsisdiv>
-    <funcsynopsis>
-      <funcprototype>
-	<funcdef>int <function>ioctl</function></funcdef>
-	<paramdef>int <parameter>fd</parameter></paramdef>
-	<paramdef>int <parameter>request</parameter></paramdef>
-	<paramdef>struct v4l2_dv_enum_preset *<parameter>argp</parameter></paramdef>
-      </funcprototype>
-    </funcsynopsis>
-  </refsynopsisdiv>
-
-  <refsect1>
-    <title>Arguments</title>
-
-    <variablelist>
-      <varlistentry>
-	<term><parameter>fd</parameter></term>
-	<listitem>
-	  <para>&fd;</para>
-	</listitem>
-      </varlistentry>
-      <varlistentry>
-	<term><parameter>request</parameter></term>
-	<listitem>
-	  <para>VIDIOC_ENUM_DV_PRESETS</para>
-	</listitem>
-      </varlistentry>
-      <varlistentry>
-	<term><parameter>argp</parameter></term>
-	<listitem>
-	  <para></para>
-	</listitem>
-      </varlistentry>
-    </variablelist>
-  </refsect1>
-
-  <refsect1>
-    <title>Description</title>
-
-    <para>This ioctl is <emphasis role="bold">deprecated</emphasis>.
-    New drivers and applications should use &VIDIOC-ENUM-DV-TIMINGS; instead.
-    </para>
-
-    <para>To query the attributes of a DV preset, applications initialize the
-<structfield>index</structfield> field and zero the reserved array of &v4l2-dv-enum-preset;
-and call the <constant>VIDIOC_ENUM_DV_PRESETS</constant> ioctl with a pointer to this
-structure. Drivers fill the rest of the structure or return an
-&EINVAL; when the index is out of bounds. To enumerate all DV Presets supported,
-applications shall begin at index zero, incrementing by one until the
-driver returns <errorcode>EINVAL</errorcode>. Drivers may enumerate a
-different set of DV presets after switching the video input or
-output.</para>
-
-    <table pgwide="1" frame="none" id="v4l2-dv-enum-preset">
-      <title>struct <structname>v4l2_dv_enum_presets</structname></title>
-      <tgroup cols="3">
-	&cs-str;
-	<tbody valign="top">
-	  <row>
-	    <entry>__u32</entry>
-	    <entry><structfield>index</structfield></entry>
-	    <entry>Number of the DV preset, set by the
-application.</entry>
-	  </row>
-	  <row>
-	    <entry>__u32</entry>
-	    <entry><structfield>preset</structfield></entry>
-	    <entry>This field identifies one of the DV preset values listed in <xref linkend="v4l2-dv-presets-vals"/>.</entry>
-	  </row>
-	  <row>
-	    <entry>__u8</entry>
-	    <entry><structfield>name</structfield>[24]</entry>
-	    <entry>Name of the preset, a NUL-terminated ASCII string, for example: "720P-60", "1080I-60". This information is
-intended for the user.</entry>
-	  </row>
-	  <row>
-	    <entry>__u32</entry>
-	    <entry><structfield>width</structfield></entry>
-	    <entry>Width of the active video in pixels for the DV preset.</entry>
-	  </row>
-	  <row>
-	    <entry>__u32</entry>
-	    <entry><structfield>height</structfield></entry>
-	    <entry>Height of the active video in lines for the DV preset.</entry>
-	  </row>
-	  <row>
-	    <entry>__u32</entry>
-	    <entry><structfield>reserved</structfield>[4]</entry>
-	    <entry>Reserved for future extensions. Drivers must set the array to zero.</entry>
-	  </row>
-	</tbody>
-      </tgroup>
-    </table>
-
-    <table pgwide="1" frame="none" id="v4l2-dv-presets-vals">
-      <title>struct <structname>DV Presets</structname></title>
-      <tgroup cols="3">
-	&cs-str;
-	<tbody valign="top">
-	  <row>
-	    <entry>Preset</entry>
-	    <entry>Preset value</entry>
-	    <entry>Description</entry>
-	  </row>
-	  <row>
-	    <entry></entry>
-	    <entry></entry>
-	    <entry></entry>
-	  </row>
-	  <row>
-	    <entry>V4L2_DV_INVALID</entry>
-	    <entry>0</entry>
-	    <entry>Invalid preset value.</entry>
-	  </row>
-	  <row>
-	    <entry>V4L2_DV_480P59_94</entry>
-	    <entry>1</entry>
-	    <entry>720x480 progressive video at 59.94 fps as per BT.1362.</entry>
-	  </row>
-	  <row>
-	    <entry>V4L2_DV_576P50</entry>
-	    <entry>2</entry>
-	    <entry>720x576 progressive video at 50 fps as per BT.1362.</entry>
-	  </row>
-	  <row>
-	    <entry>V4L2_DV_720P24</entry>
-	    <entry>3</entry>
-	    <entry>1280x720 progressive video at 24 fps as per SMPTE 296M.</entry>
-	  </row>
-	  <row>
-	    <entry>V4L2_DV_720P25</entry>
-	    <entry>4</entry>
-	    <entry>1280x720 progressive video at 25 fps as per SMPTE 296M.</entry>
-	  </row>
-	  <row>
-	    <entry>V4L2_DV_720P30</entry>
-	    <entry>5</entry>
-	    <entry>1280x720 progressive video at 30 fps as per SMPTE 296M.</entry>
-	  </row>
-	  <row>
-	    <entry>V4L2_DV_720P50</entry>
-	    <entry>6</entry>
-	    <entry>1280x720 progressive video at 50 fps as per SMPTE 296M.</entry>
-	  </row>
-	  <row>
-	    <entry>V4L2_DV_720P59_94</entry>
-	    <entry>7</entry>
-	    <entry>1280x720 progressive video at 59.94 fps as per SMPTE 274M.</entry>
-	  </row>
-	  <row>
-	    <entry>V4L2_DV_720P60</entry>
-	    <entry>8</entry>
-	    <entry>1280x720 progressive video at 60 fps as per SMPTE 274M/296M.</entry>
-	  </row>
-	  <row>
-	    <entry>V4L2_DV_1080I29_97</entry>
-	    <entry>9</entry>
-	    <entry>1920x1080 interlaced video at 29.97 fps as per BT.1120/SMPTE 274M.</entry>
-	  </row>
-	  <row>
-	    <entry>V4L2_DV_1080I30</entry>
-	    <entry>10</entry>
-	    <entry>1920x1080 interlaced video at 30 fps as per BT.1120/SMPTE 274M.</entry>
-	  </row>
-	  <row>
-	    <entry>V4L2_DV_1080I25</entry>
-	    <entry>11</entry>
-	    <entry>1920x1080 interlaced video at 25 fps as per BT.1120.</entry>
-	  </row>
-	  <row>
-	    <entry>V4L2_DV_1080I50</entry>
-	    <entry>12</entry>
-	    <entry>1920x1080 interlaced video at 50 fps as per SMPTE 296M.</entry>
-	  </row>
-	  <row>
-	    <entry>V4L2_DV_1080I60</entry>
-	    <entry>13</entry>
-	    <entry>1920x1080 interlaced video at 60 fps as per SMPTE 296M.</entry>
-	  </row>
-	  <row>
-	    <entry>V4L2_DV_1080P24</entry>
-	    <entry>14</entry>
-	    <entry>1920x1080 progressive video at 24 fps as per SMPTE 296M.</entry>
-	  </row>
-	  <row>
-	    <entry>V4L2_DV_1080P25</entry>
-	    <entry>15</entry>
-	    <entry>1920x1080 progressive video at 25 fps as per SMPTE 296M.</entry>
-	  </row>
-	  <row>
-	    <entry>V4L2_DV_1080P30</entry>
-	    <entry>16</entry>
-	    <entry>1920x1080 progressive video at 30 fps as per SMPTE 296M.</entry>
-	  </row>
-	  <row>
-	    <entry>V4L2_DV_1080P50</entry>
-	    <entry>17</entry>
-	    <entry>1920x1080 progressive video at 50 fps as per BT.1120.</entry>
-	  </row>
-	  <row>
-	    <entry>V4L2_DV_1080P60</entry>
-	    <entry>18</entry>
-	    <entry>1920x1080 progressive video at 60 fps as per BT.1120.</entry>
-	  </row>
-	</tbody>
-      </tgroup>
-    </table>
-  </refsect1>
-
-  <refsect1>
-    &return-value;
-
-    <variablelist>
-      <varlistentry>
-	<term><errorcode>EINVAL</errorcode></term>
-	<listitem>
-	  <para>The &v4l2-dv-enum-preset; <structfield>index</structfield>
-is out of bounds.</para>
-	</listitem>
-      </varlistentry>
-      <varlistentry>
-	<term><errorcode>ENODATA</errorcode></term>
-	<listitem>
-	  <para>Digital video presets are not supported for this input or output.</para>
-	</listitem>
-      </varlistentry>
-    </variablelist>
-  </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-enuminput.xml b/Documentation/DocBook/media/v4l/vidioc-enuminput.xml
index 3c9a813..493a39a 100644
--- a/Documentation/DocBook/media/v4l/vidioc-enuminput.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-enuminput.xml
@@ -278,11 +278,6 @@ input/output interface to linux-media@vger.kernel.org on 19 Oct 2009.
 	&cs-def;
 	<tbody valign="top">
 	  <row>
-	    <entry><constant>V4L2_IN_CAP_PRESETS</constant></entry>
-	    <entry>0x00000001</entry>
-	    <entry>This input supports setting DV presets by using VIDIOC_S_DV_PRESET.</entry>
-	  </row>
-	  <row>
 	    <entry><constant>V4L2_IN_CAP_DV_TIMINGS</constant></entry>
 	    <entry>0x00000002</entry>
 	    <entry>This input supports setting video timings by using VIDIOC_S_DV_TIMINGS.</entry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-enumoutput.xml b/Documentation/DocBook/media/v4l/vidioc-enumoutput.xml
index f4ab079..2654e09 100644
--- a/Documentation/DocBook/media/v4l/vidioc-enumoutput.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-enumoutput.xml
@@ -163,11 +163,6 @@ input/output interface to linux-media@vger.kernel.org on 19 Oct 2009.
 	&cs-def;
 	<tbody valign="top">
 	  <row>
-	    <entry><constant>V4L2_OUT_CAP_PRESETS</constant></entry>
-	    <entry>0x00000001</entry>
-	    <entry>This output supports setting DV presets by using VIDIOC_S_DV_PRESET.</entry>
-	  </row>
-	  <row>
 	    <entry><constant>V4L2_OUT_CAP_DV_TIMINGS</constant></entry>
 	    <entry>0x00000002</entry>
 	    <entry>This output supports setting video timings by using VIDIOC_S_DV_TIMINGS.</entry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-g-dv-preset.xml b/Documentation/DocBook/media/v4l/vidioc-g-dv-preset.xml
deleted file mode 100644
index b9ea376..0000000
--- a/Documentation/DocBook/media/v4l/vidioc-g-dv-preset.xml
+++ /dev/null
@@ -1,113 +0,0 @@
-<refentry id="vidioc-g-dv-preset">
-  <refmeta>
-    <refentrytitle>ioctl VIDIOC_G_DV_PRESET, VIDIOC_S_DV_PRESET</refentrytitle>
-    &manvol;
-  </refmeta>
-
-  <refnamediv>
-    <refname>VIDIOC_G_DV_PRESET</refname>
-    <refname>VIDIOC_S_DV_PRESET</refname>
-    <refpurpose>Query or select the DV preset of the current input or output</refpurpose>
-  </refnamediv>
-
-  <refsynopsisdiv>
-    <funcsynopsis>
-      <funcprototype>
-	<funcdef>int <function>ioctl</function></funcdef>
-	<paramdef>int <parameter>fd</parameter></paramdef>
-	<paramdef>int <parameter>request</parameter></paramdef>
-	<paramdef>struct v4l2_dv_preset *<parameter>argp</parameter></paramdef>
-      </funcprototype>
-    </funcsynopsis>
-  </refsynopsisdiv>
-
-  <refsect1>
-    <title>Arguments</title>
-
-    <variablelist>
-      <varlistentry>
-	<term><parameter>fd</parameter></term>
-	<listitem>
-	  <para>&fd;</para>
-	</listitem>
-      </varlistentry>
-      <varlistentry>
-	<term><parameter>request</parameter></term>
-	<listitem>
-	  <para>VIDIOC_G_DV_PRESET, VIDIOC_S_DV_PRESET</para>
-	</listitem>
-      </varlistentry>
-      <varlistentry>
-	<term><parameter>argp</parameter></term>
-	<listitem>
-	  <para></para>
-	</listitem>
-      </varlistentry>
-    </variablelist>
-  </refsect1>
-
-  <refsect1>
-    <title>Description</title>
-
-    <para>These ioctls are <emphasis role="bold">deprecated</emphasis>.
-    New drivers and applications should use &VIDIOC-G-DV-TIMINGS; and &VIDIOC-S-DV-TIMINGS;
-    instead.
-    </para>
-
-    <para>To query and select the current DV preset, applications
-use the <constant>VIDIOC_G_DV_PRESET</constant> and <constant>VIDIOC_S_DV_PRESET</constant>
-ioctls which take a pointer to a &v4l2-dv-preset; type as argument.
-Applications must zero the reserved array in &v4l2-dv-preset;.
-<constant>VIDIOC_G_DV_PRESET</constant> returns a dv preset in the field
-<structfield>preset</structfield> of &v4l2-dv-preset;.</para>
-
-    <para><constant>VIDIOC_S_DV_PRESET</constant> accepts a pointer to a &v4l2-dv-preset;
-that has the preset value to be set. Applications must zero the reserved array in &v4l2-dv-preset;.
-If the preset is not supported, it returns an &EINVAL; </para>
-  </refsect1>
-
-  <refsect1>
-    &return-value;
-
-    <variablelist>
-      <varlistentry>
-	<term><errorcode>EINVAL</errorcode></term>
-	<listitem>
-	  <para>This ioctl is not supported, or the
-<constant>VIDIOC_S_DV_PRESET</constant>,<constant>VIDIOC_S_DV_PRESET</constant> parameter was unsuitable.</para>
-	</listitem>
-      </varlistentry>
-      <varlistentry>
-	<term><errorcode>ENODATA</errorcode></term>
-	<listitem>
-	  <para>Digital video presets are not supported for this input or output.</para>
-	</listitem>
-      </varlistentry>
-      <varlistentry>
-	<term><errorcode>EBUSY</errorcode></term>
-	<listitem>
-	  <para>The device is busy and therefore can not change the preset.</para>
-	</listitem>
-      </varlistentry>
-    </variablelist>
-
-    <table pgwide="1" frame="none" id="v4l2-dv-preset">
-      <title>struct <structname>v4l2_dv_preset</structname></title>
-      <tgroup cols="3">
-	&cs-str;
-	<tbody valign="top">
-	  <row>
-	    <entry>__u32</entry>
-	    <entry><structfield>preset</structfield></entry>
-	    <entry>Preset value to represent the digital video timings</entry>
-	  </row>
-	  <row>
-	    <entry>__u32</entry>
-	    <entry><structfield>reserved[4]</structfield></entry>
-	    <entry>Reserved fields for future use</entry>
-	  </row>
-	</tbody>
-      </tgroup>
-    </table>
-  </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-query-dv-preset.xml b/Documentation/DocBook/media/v4l/vidioc-query-dv-preset.xml
deleted file mode 100644
index 68b49d0..0000000
--- a/Documentation/DocBook/media/v4l/vidioc-query-dv-preset.xml
+++ /dev/null
@@ -1,78 +0,0 @@
-<refentry id="vidioc-query-dv-preset">
-  <refmeta>
-    <refentrytitle>ioctl VIDIOC_QUERY_DV_PRESET</refentrytitle>
-    &manvol;
-  </refmeta>
-
-  <refnamediv>
-    <refname>VIDIOC_QUERY_DV_PRESET</refname>
-    <refpurpose>Sense the DV preset received by the current
-input</refpurpose>
-  </refnamediv>
-
-  <refsynopsisdiv>
-    <funcsynopsis>
-      <funcprototype>
-	<funcdef>int <function>ioctl</function></funcdef>
-	<paramdef>int <parameter>fd</parameter></paramdef>
-	<paramdef>int <parameter>request</parameter></paramdef>
-	<paramdef>struct v4l2_dv_preset *<parameter>argp</parameter></paramdef>
-      </funcprototype>
-    </funcsynopsis>
-  </refsynopsisdiv>
-
-  <refsect1>
-    <title>Arguments</title>
-
-    <variablelist>
-	<varlistentry>
-	<term><parameter>fd</parameter></term>
-	<listitem>
-	  <para>&fd;</para>
-	</listitem>
-      </varlistentry>
-      <varlistentry>
-	<term><parameter>request</parameter></term>
-	<listitem>
-	  <para>VIDIOC_QUERY_DV_PRESET</para>
-	</listitem>
-      </varlistentry>
-      <varlistentry>
-	<term><parameter>argp</parameter></term>
-	<listitem>
-	  <para></para>
-	</listitem>
-      </varlistentry>
-    </variablelist>
-  </refsect1>
-
-  <refsect1>
-    <title>Description</title>
-
-    <para>This ioctl is <emphasis role="bold">deprecated</emphasis>.
-    New drivers and applications should use &VIDIOC-QUERY-DV-TIMINGS; instead.
-    </para>
-
-    <para>The hardware may be able to detect the current DV preset
-automatically, similar to sensing the video standard. To do so, applications
-call <constant> VIDIOC_QUERY_DV_PRESET</constant> with a pointer to a
-&v4l2-dv-preset; type. Once the hardware detects a preset, that preset is
-returned in the preset field of &v4l2-dv-preset;. If the preset could not be
-detected because there was no signal, or the signal was unreliable, or the
-signal did not map to a supported preset, then the value V4L2_DV_INVALID is
-returned.</para>
-  </refsect1>
-
-  <refsect1>
-    &return-value;
-
-    <variablelist>
-      <varlistentry>
-	<term><errorcode>ENODATA</errorcode></term>
-	<listitem>
-	  <para>Digital video presets are not supported for this input or output.</para>
-	</listitem>
-      </varlistentry>
-    </variablelist>
-  </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/writing-an-alsa-driver.tmpl b/Documentation/DocBook/writing-an-alsa-driver.tmpl
index bd6fee2..06741e9 100644
--- a/Documentation/DocBook/writing-an-alsa-driver.tmpl
+++ b/Documentation/DocBook/writing-an-alsa-driver.tmpl
@@ -6164,14 +6164,12 @@ struct _snd_pcm_runtime {
 
       <para>
         The macro takes an conditional expression to evaluate.
-	When <constant>CONFIG_SND_DEBUG</constant>, is set, the
-	expression is actually evaluated. If it's non-zero, it shows
-	the warning message such as
+	When <constant>CONFIG_SND_DEBUG</constant>, is set, if the
+	expression is non-zero, it shows the warning message such as
 	<computeroutput>BUG? (xxx)</computeroutput>
-	normally followed by stack trace.  It returns the evaluated
-	value.
-	When no <constant>CONFIG_SND_DEBUG</constant> is set, this
-	macro always returns zero.
+	normally followed by stack trace.
+
+	In both cases it returns the evaluated value.
       </para>
 
     </section>
diff --git a/Documentation/RCU/checklist.txt b/Documentation/RCU/checklist.txt
index 31ef8fe..79e789b8 100644
--- a/Documentation/RCU/checklist.txt
+++ b/Documentation/RCU/checklist.txt
@@ -217,9 +217,14 @@ over a rather long period of time, but improvements are always welcome!
 	whether the increased speed is worth it.
 
 8.	Although synchronize_rcu() is slower than is call_rcu(), it
-	usually results in simpler code.  So, unless update performance
-	is critically important or the updaters cannot block,
-	synchronize_rcu() should be used in preference to call_rcu().
+	usually results in simpler code.  So, unless update performance is
+	critically important, the updaters cannot block, or the latency of
+	synchronize_rcu() is visible from userspace, synchronize_rcu()
+	should be used in preference to call_rcu().  Furthermore,
+	kfree_rcu() usually results in even simpler code than does
+	synchronize_rcu() without synchronize_rcu()'s multi-millisecond
+	latency.  So please take advantage of kfree_rcu()'s "fire and
+	forget" memory-freeing capabilities where it applies.
 
 	An especially important property of the synchronize_rcu()
 	primitive is that it automatically self-limits: if grace periods
@@ -268,7 +273,8 @@ over a rather long period of time, but improvements are always welcome!
 	e.	Periodically invoke synchronize_rcu(), permitting a limited
 		number of updates per grace period.
 
-	The same cautions apply to call_rcu_bh() and call_rcu_sched().
+	The same cautions apply to call_rcu_bh(), call_rcu_sched(),
+	call_srcu(), and kfree_rcu().
 
 9.	All RCU list-traversal primitives, which include
 	rcu_dereference(), list_for_each_entry_rcu(), and
@@ -296,9 +302,9 @@ over a rather long period of time, but improvements are always welcome!
 	all currently executing rcu_read_lock()-protected RCU read-side
 	critical sections complete.  It does -not- necessarily guarantee
 	that all currently running interrupts, NMIs, preempt_disable()
-	code, or idle loops will complete.  Therefore, if you do not have
-	rcu_read_lock()-protected read-side critical sections, do -not-
-	use synchronize_rcu().
+	code, or idle loops will complete.  Therefore, if your
+	read-side critical sections are protected by something other
+	than rcu_read_lock(), do -not- use synchronize_rcu().
 
 	Similarly, disabling preemption is not an acceptable substitute
 	for rcu_read_lock().  Code that attempts to use preemption
@@ -401,9 +407,9 @@ over a rather long period of time, but improvements are always welcome!
 	read-side critical sections.  It is the responsibility of the
 	RCU update-side primitives to deal with this.
 
-17.	Use CONFIG_PROVE_RCU, CONFIG_DEBUG_OBJECTS_RCU_HEAD, and
-	the __rcu sparse checks to validate your RCU code.  These
-	can help find problems as follows:
+17.	Use CONFIG_PROVE_RCU, CONFIG_DEBUG_OBJECTS_RCU_HEAD, and the
+	__rcu sparse checks (enabled by CONFIG_SPARSE_RCU_POINTER) to
+	validate your RCU code.  These can help find problems as follows:
 
 	CONFIG_PROVE_RCU: check that accesses to RCU-protected data
 		structures are carried out under the proper RCU
diff --git a/Documentation/RCU/lockdep.txt b/Documentation/RCU/lockdep.txt
index a102d4b..cd83d23 100644
--- a/Documentation/RCU/lockdep.txt
+++ b/Documentation/RCU/lockdep.txt
@@ -64,6 +64,11 @@ checking of rcu_dereference() primitives:
 		but retain the compiler constraints that prevent duplicating
 		or coalescsing.  This is useful when when testing the
 		value of the pointer itself, for example, against NULL.
+	rcu_access_index(idx):
+		Return the value of the index and omit all barriers, but
+		retain the compiler constraints that prevent duplicating
+		or coalescsing.  This is useful when when testing the
+		value of the index itself, for example, against -1.
 
 The rcu_dereference_check() check expression can be any boolean
 expression, but would normally include a lockdep expression.  However,
diff --git a/Documentation/RCU/rcubarrier.txt b/Documentation/RCU/rcubarrier.txt
index 38428c1..2e319d1 100644
--- a/Documentation/RCU/rcubarrier.txt
+++ b/Documentation/RCU/rcubarrier.txt
@@ -79,7 +79,20 @@ complete. Pseudo-code using rcu_barrier() is as follows:
    2. Execute rcu_barrier().
    3. Allow the module to be unloaded.
 
-The rcutorture module makes use of rcu_barrier in its exit function
+There are also rcu_barrier_bh(), rcu_barrier_sched(), and srcu_barrier()
+functions for the other flavors of RCU, and you of course must match
+the flavor of rcu_barrier() with that of call_rcu().  If your module
+uses multiple flavors of call_rcu(), then it must also use multiple
+flavors of rcu_barrier() when unloading that module.  For example, if
+it uses call_rcu_bh(), call_srcu() on srcu_struct_1, and call_srcu() on
+srcu_struct_2(), then the following three lines of code will be required
+when unloading:
+
+ 1 rcu_barrier_bh();
+ 2 srcu_barrier(&srcu_struct_1);
+ 3 srcu_barrier(&srcu_struct_2);
+
+The rcutorture module makes use of rcu_barrier() in its exit function
 as follows:
 
  1 static void
diff --git a/Documentation/RCU/stallwarn.txt b/Documentation/RCU/stallwarn.txt
index 1927151..e38b8df 100644
--- a/Documentation/RCU/stallwarn.txt
+++ b/Documentation/RCU/stallwarn.txt
@@ -92,14 +92,14 @@ If the CONFIG_RCU_CPU_STALL_INFO kernel configuration parameter is set,
 more information is printed with the stall-warning message, for example:
 
 	INFO: rcu_preempt detected stall on CPU
-	0: (63959 ticks this GP) idle=241/3fffffffffffffff/0
+	0: (63959 ticks this GP) idle=241/3fffffffffffffff/0 softirq=82/543
 	   (t=65000 jiffies)
 
 In kernels with CONFIG_RCU_FAST_NO_HZ, even more information is
 printed:
 
 	INFO: rcu_preempt detected stall on CPU
-	0: (64628 ticks this GP) idle=dd5/3fffffffffffffff/0 drain=0 . timer not pending
+	0: (64628 ticks this GP) idle=dd5/3fffffffffffffff/0 softirq=82/543 last_accelerate: a345/d342 nonlazy_posted: 25 .D
 	   (t=65000 jiffies)
 
 The "(64628 ticks this GP)" indicates that this CPU has taken more
@@ -116,13 +116,28 @@ number between the two "/"s is the value of the nesting, which will
 be a small positive number if in the idle loop and a very large positive
 number (as shown above) otherwise.
 
-For CONFIG_RCU_FAST_NO_HZ kernels, the "drain=0" indicates that the CPU is
-not in the process of trying to force itself into dyntick-idle state, the
-"." indicates that the CPU has not given up forcing RCU into dyntick-idle
-mode (it would be "H" otherwise), and the "timer not pending" indicates
-that the CPU has not recently forced RCU into dyntick-idle mode (it
-would otherwise indicate the number of microseconds remaining in this
-forced state).
+The "softirq=" portion of the message tracks the number of RCU softirq
+handlers that the stalled CPU has executed.  The number before the "/"
+is the number that had executed since boot at the time that this CPU
+last noted the beginning of a grace period, which might be the current
+(stalled) grace period, or it might be some earlier grace period (for
+example, if the CPU might have been in dyntick-idle mode for an extended
+time period.  The number after the "/" is the number that have executed
+since boot until the current time.  If this latter number stays constant
+across repeated stall-warning messages, it is possible that RCU's softirq
+handlers are no longer able to execute on this CPU.  This can happen if
+the stalled CPU is spinning with interrupts are disabled, or, in -rt
+kernels, if a high-priority process is starving RCU's softirq handler.
+
+For CONFIG_RCU_FAST_NO_HZ kernels, the "last_accelerate:" prints the
+low-order 16 bits (in hex) of the jiffies counter when this CPU last
+invoked rcu_try_advance_all_cbs() from rcu_needs_cpu() or last invoked
+rcu_accelerate_cbs() from rcu_prepare_for_idle().  The "nonlazy_posted:"
+prints the number of non-lazy callbacks posted since the last call to
+rcu_needs_cpu().  Finally, an "L" indicates that there are currently
+no non-lazy callbacks ("." is printed otherwise, as shown above) and
+"D" indicates that dyntick-idle processing is enabled ("." is printed
+otherwise, for example, if disabled via the "nohz=" kernel boot parameter).
 
 
 Multiple Warnings From One Stall
diff --git a/Documentation/RCU/whatisRCU.txt b/Documentation/RCU/whatisRCU.txt
index 0cc7820..10df0b8 100644
--- a/Documentation/RCU/whatisRCU.txt
+++ b/Documentation/RCU/whatisRCU.txt
@@ -265,9 +265,9 @@ rcu_dereference()
 		rcu_read_lock();
 		p = rcu_dereference(head.next);
 		rcu_read_unlock();
-		x = p->address;
+		x = p->address;	/* BUG!!! */
 		rcu_read_lock();
-		y = p->data;
+		y = p->data;	/* BUG!!! */
 		rcu_read_unlock();
 
 	Holding a reference from one RCU read-side critical section
diff --git a/Documentation/arm/firmware.txt b/Documentation/arm/firmware.txt
new file mode 100644
index 0000000..c2e468f
--- /dev/null
+++ b/Documentation/arm/firmware.txt
@@ -0,0 +1,88 @@
+Interface for registering and calling firmware-specific operations for ARM.
+----
+Written by Tomasz Figa <t.figa@samsung.com>
+
+Some boards are running with secure firmware running in TrustZone secure
+world, which changes the way some things have to be initialized. This makes
+a need to provide an interface for such platforms to specify available firmware
+operations and call them when needed.
+
+Firmware operations can be specified using struct firmware_ops
+
+	struct firmware_ops {
+		/*
+		* Enters CPU idle mode
+		*/
+		int (*do_idle)(void);
+		/*
+		* Sets boot address of specified physical CPU
+		*/
+		int (*set_cpu_boot_addr)(int cpu, unsigned long boot_addr);
+		/*
+		* Boots specified physical CPU
+		*/
+		int (*cpu_boot)(int cpu);
+		/*
+		* Initializes L2 cache
+		*/
+		int (*l2x0_init)(void);
+	};
+
+and then registered with register_firmware_ops function
+
+	void register_firmware_ops(const struct firmware_ops *ops)
+
+the ops pointer must be non-NULL.
+
+There is a default, empty set of operations provided, so there is no need to
+set anything if platform does not require firmware operations.
+
+To call a firmware operation, a helper macro is provided
+
+	#define call_firmware_op(op, ...)				\
+		((firmware_ops->op) ? firmware_ops->op(__VA_ARGS__) : (-ENOSYS))
+
+the macro checks if the operation is provided and calls it or otherwise returns
+-ENOSYS to signal that given operation is not available (for example, to allow
+fallback to legacy operation).
+
+Example of registering firmware operations:
+
+	/* board file */
+
+	static int platformX_do_idle(void)
+	{
+		/* tell platformX firmware to enter idle */
+		return 0;
+	}
+
+	static int platformX_cpu_boot(int i)
+	{
+		/* tell platformX firmware to boot CPU i */
+		return 0;
+	}
+
+	static const struct firmware_ops platformX_firmware_ops = {
+		.do_idle        = exynos_do_idle,
+		.cpu_boot       = exynos_cpu_boot,
+		/* other operations not available on platformX */
+	};
+
+	/* init_early callback of machine descriptor */
+	static void __init board_init_early(void)
+	{
+		register_firmware_ops(&platformX_firmware_ops);
+	}
+
+Example of using a firmware operation:
+
+	/* some platform code, e.g. SMP initialization */
+
+	__raw_writel(virt_to_phys(exynos4_secondary_startup),
+		CPU1_BOOT_REG);
+
+	/* Call Exynos specific smc call */
+	if (call_firmware_op(cpu_boot, cpu) == -ENOSYS)
+		cpu_boot_legacy(...); /* Try legacy way */
+
+	gic_raise_softirq(cpumask_of(cpu), 1);
diff --git a/Documentation/arm/sunxi/clocks.txt b/Documentation/arm/sunxi/clocks.txt
new file mode 100644
index 0000000..e09a88a
--- /dev/null
+++ b/Documentation/arm/sunxi/clocks.txt
@@ -0,0 +1,56 @@
+Frequently asked questions about the sunxi clock system
+=======================================================
+
+This document contains useful bits of information that people tend to ask
+about the sunxi clock system, as well as accompanying ASCII art when adequate.
+
+Q: Why is the main 24MHz oscillator gatable? Wouldn't that break the
+   system?
+
+A: The 24MHz oscillator allows gating to save power. Indeed, if gated
+   carelessly the system would stop functioning, but with the right
+   steps, one can gate it and keep the system running. Consider this
+   simplified suspend example:
+
+   While the system is operational, you would see something like
+
+      24MHz         32kHz
+       |
+      PLL1
+       \
+        \_ CPU Mux
+             |
+           [CPU]
+
+   When you are about to suspend, you switch the CPU Mux to the 32kHz
+   oscillator:
+
+      24Mhz         32kHz
+       |              |
+      PLL1            |
+                     /
+           CPU Mux _/
+             |
+           [CPU]
+
+    Finally you can gate the main oscillator
+
+                    32kHz
+                      |
+                      |
+                     /
+           CPU Mux _/
+             |
+           [CPU]
+
+Q: Were can I learn more about the sunxi clocks?
+
+A: The linux-sunxi wiki contains a page documenting the clock registers,
+   you can find it at
+
+        http://linux-sunxi.org/A10/CCM
+
+   The authoritative source for information at this time is the ccmu driver
+   released by Allwinner, you can find it at
+
+        https://github.com/linux-sunxi/linux-sunxi/tree/sunxi-3.0/arch/arm/mach-sun4i/clock/ccmu
diff --git a/Documentation/bcache.txt b/Documentation/bcache.txt
new file mode 100644
index 0000000..533307d
--- /dev/null
+++ b/Documentation/bcache.txt
@@ -0,0 +1,343 @@
+Say you've got a big slow raid 6, and an X-25E or three. Wouldn't it be
+nice if you could use them as cache... Hence bcache.
+
+Wiki and git repositories are at:
+  http://bcache.evilpiepirate.org
+  http://evilpiepirate.org/git/linux-bcache.git
+  http://evilpiepirate.org/git/bcache-tools.git
+
+It's designed around the performance characteristics of SSDs - it only allocates
+in erase block sized buckets, and it uses a hybrid btree/log to track cached
+extants (which can be anywhere from a single sector to the bucket size). It's
+designed to avoid random writes at all costs; it fills up an erase block
+sequentially, then issues a discard before reusing it.
+
+Both writethrough and writeback caching are supported. Writeback defaults to
+off, but can be switched on and off arbitrarily at runtime. Bcache goes to
+great lengths to protect your data - it reliably handles unclean shutdown. (It
+doesn't even have a notion of a clean shutdown; bcache simply doesn't return
+writes as completed until they're on stable storage).
+
+Writeback caching can use most of the cache for buffering writes - writing
+dirty data to the backing device is always done sequentially, scanning from the
+start to the end of the index.
+
+Since random IO is what SSDs excel at, there generally won't be much benefit
+to caching large sequential IO. Bcache detects sequential IO and skips it;
+it also keeps a rolling average of the IO sizes per task, and as long as the
+average is above the cutoff it will skip all IO from that task - instead of
+caching the first 512k after every seek. Backups and large file copies should
+thus entirely bypass the cache.
+
+In the event of a data IO error on the flash it will try to recover by reading
+from disk or invalidating cache entries.  For unrecoverable errors (meta data
+or dirty data), caching is automatically disabled; if dirty data was present
+in the cache it first disables writeback caching and waits for all dirty data
+to be flushed.
+
+Getting started:
+You'll need make-bcache from the bcache-tools repository. Both the cache device
+and backing device must be formatted before use.
+  make-bcache -B /dev/sdb
+  make-bcache -C /dev/sdc
+
+make-bcache has the ability to format multiple devices at the same time - if
+you format your backing devices and cache device at the same time, you won't
+have to manually attach:
+  make-bcache -B /dev/sda /dev/sdb -C /dev/sdc
+
+To make bcache devices known to the kernel, echo them to /sys/fs/bcache/register:
+
+  echo /dev/sdb > /sys/fs/bcache/register
+  echo /dev/sdc > /sys/fs/bcache/register
+
+To register your bcache devices automatically, you could add something like
+this to an init script:
+
+  echo /dev/sd* > /sys/fs/bcache/register_quiet
+
+It'll look for bcache superblocks and ignore everything that doesn't have one.
+
+Registering the backing device makes the bcache show up in /dev; you can now
+format it and use it as normal. But the first time using a new bcache device,
+it'll be running in passthrough mode until you attach it to a cache. See the
+section on attaching.
+
+The devices show up at /dev/bcacheN, and can be controlled via sysfs from
+/sys/block/bcacheN/bcache:
+
+  mkfs.ext4 /dev/bcache0
+  mount /dev/bcache0 /mnt
+
+Cache devices are managed as sets; multiple caches per set isn't supported yet
+but will allow for mirroring of metadata and dirty data in the future. Your new
+cache set shows up as /sys/fs/bcache/<UUID>
+
+ATTACHING:
+
+After your cache device and backing device are registered, the backing device
+must be attached to your cache set to enable caching. Attaching a backing
+device to a cache set is done thusly, with the UUID of the cache set in
+/sys/fs/bcache:
+
+  echo <UUID> > /sys/block/bcache0/bcache/attach
+
+This only has to be done once. The next time you reboot, just reregister all
+your bcache devices. If a backing device has data in a cache somewhere, the
+/dev/bcache# device won't be created until the cache shows up - particularly
+important if you have writeback caching turned on.
+
+If you're booting up and your cache device is gone and never coming back, you
+can force run the backing device:
+
+  echo 1 > /sys/block/sdb/bcache/running
+
+(You need to use /sys/block/sdb (or whatever your backing device is called), not
+/sys/block/bcache0, because bcache0 doesn't exist yet. If you're using a
+partition, the bcache directory would be at /sys/block/sdb/sdb2/bcache)
+
+The backing device will still use that cache set if it shows up in the future,
+but all the cached data will be invalidated. If there was dirty data in the
+cache, don't expect the filesystem to be recoverable - you will have massive
+filesystem corruption, though ext4's fsck does work miracles.
+
+SYSFS - BACKING DEVICE:
+
+attach
+  Echo the UUID of a cache set to this file to enable caching.
+
+cache_mode
+  Can be one of either writethrough, writeback, writearound or none.
+
+clear_stats
+  Writing to this file resets the running total stats (not the day/hour/5 minute
+  decaying versions).
+
+detach
+  Write to this file to detach from a cache set. If there is dirty data in the
+  cache, it will be flushed first.
+
+dirty_data
+  Amount of dirty data for this backing device in the cache. Continuously
+  updated unlike the cache set's version, but may be slightly off.
+
+label
+  Name of underlying device.
+
+readahead
+  Size of readahead that should be performed.  Defaults to 0.  If set to e.g.
+  1M, it will round cache miss reads up to that size, but without overlapping
+  existing cache entries.
+
+running
+  1 if bcache is running (i.e. whether the /dev/bcache device exists, whether
+  it's in passthrough mode or caching).
+
+sequential_cutoff
+  A sequential IO will bypass the cache once it passes this threshhold; the
+  most recent 128 IOs are tracked so sequential IO can be detected even when
+  it isn't all done at once.
+
+sequential_merge
+  If non zero, bcache keeps a list of the last 128 requests submitted to compare
+  against all new requests to determine which new requests are sequential
+  continuations of previous requests for the purpose of determining sequential
+  cutoff. This is necessary if the sequential cutoff value is greater than the
+  maximum acceptable sequential size for any single request. 
+
+state
+  The backing device can be in one of four different states:
+
+  no cache: Has never been attached to a cache set.
+
+  clean: Part of a cache set, and there is no cached dirty data.
+
+  dirty: Part of a cache set, and there is cached dirty data.
+
+  inconsistent: The backing device was forcibly run by the user when there was
+  dirty data cached but the cache set was unavailable; whatever data was on the
+  backing device has likely been corrupted.
+
+stop
+  Write to this file to shut down the bcache device and close the backing
+  device.
+
+writeback_delay
+  When dirty data is written to the cache and it previously did not contain
+  any, waits some number of seconds before initiating writeback. Defaults to
+  30.
+
+writeback_percent
+  If nonzero, bcache tries to keep around this percentage of the cache dirty by
+  throttling background writeback and using a PD controller to smoothly adjust
+  the rate.
+
+writeback_rate
+  Rate in sectors per second - if writeback_percent is nonzero, background
+  writeback is throttled to this rate. Continuously adjusted by bcache but may
+  also be set by the user.
+
+writeback_running
+  If off, writeback of dirty data will not take place at all. Dirty data will
+  still be added to the cache until it is mostly full; only meant for
+  benchmarking. Defaults to on.
+
+SYSFS - BACKING DEVICE STATS:
+
+There are directories with these numbers for a running total, as well as
+versions that decay over the past day, hour and 5 minutes; they're also
+aggregated in the cache set directory as well.
+
+bypassed
+  Amount of IO (both reads and writes) that has bypassed the cache
+
+cache_hits
+cache_misses
+cache_hit_ratio
+  Hits and misses are counted per individual IO as bcache sees them; a
+  partial hit is counted as a miss.
+
+cache_bypass_hits
+cache_bypass_misses
+  Hits and misses for IO that is intended to skip the cache are still counted,
+  but broken out here.
+
+cache_miss_collisions
+  Counts instances where data was going to be inserted into the cache from a
+  cache miss, but raced with a write and data was already present (usually 0
+  since the synchronization for cache misses was rewritten)
+
+cache_readaheads
+  Count of times readahead occured.
+
+SYSFS - CACHE SET:
+
+average_key_size
+  Average data per key in the btree.
+
+bdev<0..n>
+  Symlink to each of the attached backing devices.
+
+block_size
+  Block size of the cache devices.
+
+btree_cache_size
+  Amount of memory currently used by the btree cache
+
+bucket_size
+  Size of buckets
+
+cache<0..n>
+  Symlink to each of the cache devices comprising this cache set. 
+
+cache_available_percent
+  Percentage of cache device free.
+
+clear_stats
+  Clears the statistics associated with this cache
+
+dirty_data
+  Amount of dirty data is in the cache (updated when garbage collection runs).
+
+flash_vol_create
+  Echoing a size to this file (in human readable units, k/M/G) creates a thinly
+  provisioned volume backed by the cache set.
+
+io_error_halflife
+io_error_limit
+  These determines how many errors we accept before disabling the cache.
+  Each error is decayed by the half life (in # ios).  If the decaying count
+  reaches io_error_limit dirty data is written out and the cache is disabled.
+
+journal_delay_ms
+  Journal writes will delay for up to this many milliseconds, unless a cache
+  flush happens sooner. Defaults to 100.
+
+root_usage_percent
+  Percentage of the root btree node in use.  If this gets too high the node
+  will split, increasing the tree depth.
+
+stop
+  Write to this file to shut down the cache set - waits until all attached
+  backing devices have been shut down.
+
+tree_depth
+  Depth of the btree (A single node btree has depth 0).
+
+unregister
+  Detaches all backing devices and closes the cache devices; if dirty data is
+  present it will disable writeback caching and wait for it to be flushed.
+
+SYSFS - CACHE SET INTERNAL:
+
+This directory also exposes timings for a number of internal operations, with
+separate files for average duration, average frequency, last occurence and max
+duration: garbage collection, btree read, btree node sorts and btree splits.
+
+active_journal_entries
+  Number of journal entries that are newer than the index.
+
+btree_nodes
+  Total nodes in the btree.
+
+btree_used_percent
+  Average fraction of btree in use.
+
+bset_tree_stats
+  Statistics about the auxiliary search trees
+
+btree_cache_max_chain
+  Longest chain in the btree node cache's hash table
+
+cache_read_races
+  Counts instances where while data was being read from the cache, the bucket
+  was reused and invalidated - i.e. where the pointer was stale after the read
+  completed. When this occurs the data is reread from the backing device.
+
+trigger_gc
+  Writing to this file forces garbage collection to run.
+
+SYSFS - CACHE DEVICE:
+
+block_size
+  Minimum granularity of writes - should match hardware sector size.
+
+btree_written
+  Sum of all btree writes, in (kilo/mega/giga) bytes
+
+bucket_size
+  Size of buckets
+
+cache_replacement_policy
+  One of either lru, fifo or random.
+
+discard
+  Boolean; if on a discard/TRIM will be issued to each bucket before it is
+  reused. Defaults to off, since SATA TRIM is an unqueued command (and thus
+  slow).
+
+freelist_percent
+  Size of the freelist as a percentage of nbuckets. Can be written to to
+  increase the number of buckets kept on the freelist, which lets you
+  artificially reduce the size of the cache at runtime. Mostly for testing
+  purposes (i.e. testing how different size caches affect your hit rate), but
+  since buckets are discarded when they move on to the freelist will also make
+  the SSD's garbage collection easier by effectively giving it more reserved
+  space.
+
+io_errors
+  Number of errors that have occured, decayed by io_error_halflife.
+
+metadata_written
+  Sum of all non data writes (btree writes and all other metadata).
+
+nbuckets
+  Total buckets in this cache
+
+priority_stats
+  Statistics about how recently data in the cache has been accessed.  This can
+  reveal your working set size.
+
+written
+  Sum of all data that has been written to the cache; comparison with
+  btree_written gives the amount of write inflation in bcache.
diff --git a/Documentation/block/blockconsole.txt b/Documentation/block/blockconsole.txt
new file mode 100644
index 0000000..2b45516
--- /dev/null
+++ b/Documentation/block/blockconsole.txt
@@ -0,0 +1,94 @@
+started by Jörn Engel <joern@logfs.org> 2012.03.17
+
+Blocksonsole for the impatient
+==============================
+
+1. Find an unused USB stick and prepare it for blockconsole by writing
+   the blockconsole signature to it:
+   $ ./mkblockconsole /dev/<usb_stick>
+
+2. USB stick is ready for use, replug it so that the kernel can start
+   logging to it.
+
+3. After you've done logging, read out the logs from it like this:
+   $ ./bcon_tail
+
+   This creates a file called /var/log/bcon.<UUID> which contains the
+   last 16M of the logs.  Open it with a sane editor like vim which
+   can display zeroed gaps as a single line and start staring at the
+   logs.
+   For the really impatient, use:
+   $ vi `./bcon_tail`
+
+Introduction:
+=============
+
+This module logs kernel printk messages to block devices, e.g. usb
+sticks.  It allows after-the-fact debugging when the main
+disk/filesystem fails and serial consoles and netconsole are
+impractical.
+
+It can currently only be used built-in.  Blockconsole hooks into the
+partition scanning code and will bring up configured block devices as
+soon as possible.  While this doesn't allow capture of early kernel
+panics, it does capture most of the boot process.
+
+Block device configuration:
+==================================
+
+Blockconsole has no configuration parameter.  In order to use a block
+device for logging, the blockconsole header has to be written to the
+device in question.  Logging to partitions is not supported.
+
+The example program mkblockconsole can be used to generate such a
+header on a device.
+
+Header format:
+==============
+
+A legal header looks like this:
+
+Linux blockconsole version 1.1
+818cf322
+00000000
+00000000
+
+It consists of a newline, the "Linux blockconsole version 1.1" string
+plus three numbers on separate lines each.  Numbers are all 32bit,
+represented as 8-byte hex strings, with letters in lowercase.  The
+first number is a uuid for this particular console device.  Just pick
+a random number when generating the device.  The second number is a
+wrap counter and unlikely to ever increment.  The third is a tile
+counter, with a tile being one megabyte in size.
+
+Miscellaneous notes:
+====================
+
+Blockconsole will write a new header for every tile or once every
+megabyte.  The header starts with a newline in order to ensure the
+"Linux blockconsole...' string always ends up at the beginning of a
+line if you read the blockconsole in a text editor.
+
+The blockconsole header is constructed such that opening the log
+device in a text editor, ignoring memory constraints due to large
+devices, should just work and be reasonably non-confusing to readers.
+However, the example program bcon_tail can be used to copy the last 16
+tiles of the log device to /var/log/bcon.<uuid>, which should be much
+easier to handle.
+
+The wrap counter is used by blockconsole to determine where to
+continue logging after a reboot.  New logs will be written to the
+first tile that wasn't written to by the last instance of
+blockconsole.  Similarly bcon_tail is doing a binary search to find
+the end of the log.
+
+Writing to the log device is strictly circular.  This should give
+optimal performance and reliability on cheap devices, like usb sticks.
+
+Writing to block devices has to happen in sector granularity, while
+kernel logging happens in byte granularity.  In order not to lose
+messages in important cases like kernel crashes, a timer will write
+out partial sectors if no new messages appear for a while.  The
+unwritten part of the sector will be filled with spaces and a single
+newline.  In a quiet system, these empty lines can make up the bulk of
+the log.
diff --git a/Documentation/block/blockconsole/bcon_tail b/Documentation/block/blockconsole/bcon_tail
new file mode 100755
index 0000000..70926c6
--- /dev/null
+++ b/Documentation/block/blockconsole/bcon_tail
@@ -0,0 +1,82 @@
+#!/bin/bash
+
+TAIL_LEN=16
+TEMPLATE=/tmp/bcon_template
+BUF=/tmp/bcon_buf
+
+if [ $(whoami) != "root" ]; then
+	echo "You need to be root to run this."
+	exit 1
+fi
+
+if [ -z "$(which lsscsi)" ]; then
+	echo "You need to install the lsscsi package on your distro."
+	exit 1
+fi
+
+if [ -z "$(which hdparm)" ]; then
+	echo "You need to install the hdparm package on your distro."
+	exit 1
+fi
+
+end_of_log() {
+	DEV=$1
+	UUID=`head -c40 $DEV|tail -c8`
+	LOGFILE=/var/log/bcon.$UUID
+	SECTORS=`hdparm -g $DEV|grep sectors|sed 's/.*sectors = \([0-9]*\).*/\1/'`
+	#MSIZE=`expr $SECTORS / 2048`
+	dd if=$DEV iflag=direct bs=512 2>/dev/null|head -c50 > $TEMPLATE
+	#START, MIDDLE and END are in sectors
+	START=0
+	MIDDLE=$SECTORS
+	END=$SECTORS
+	while true; do
+		MIDDLE=`expr \( \( $END + $START \) / 4096 \) \* 2048`
+		if [ $MIDDLE -eq $START ]; then
+			break
+		fi
+		dd if=$DEV iflag=direct bs=512 count=1 skip=$MIDDLE 2>/dev/null|head -c50 > $BUF
+		if diff -q $BUF $TEMPLATE > /dev/null; then
+			START=$MIDDLE
+		else
+			END=$MIDDLE
+		fi
+	done
+	#switch to megabytes
+	END=`expr $END / 2048`
+	START=`expr $START / 2048`
+	if [ $START -lt $TAIL_LEN ]; then
+		START=0
+	else
+		START=`expr $START - $TAIL_LEN + 1`
+	fi
+	LEN=`expr $END - $START`
+	dd if=$DEV iflag=direct bs=1M count=$LEN skip=$START >$LOGFILE 2>/dev/null
+	echo $LOGFILE
+}
+
+# HEADER contains a newline, so the funny quoting is necessary
+HEADER='
+Linux blockconsole version 1.1'
+
+DEV="$1"
+if [ -n "$DEV" ]; then
+	if [ ! -b "$DEV" ]; then
+		echo "bcon_tail: No block device file $DEV"
+		exit 1
+	fi
+	if [ "`head -c32 $DEV`" != "$HEADER" ]; then
+		echo "bcon_tail: Invalid device file $DEV"
+		exit 1
+	fi
+	end_of_log $DEV
+	exit 0
+fi
+
+CANDIDATES=`lsscsi |sed 's|.*/dev|/dev|'`
+
+for DEV in $CANDIDATES; do
+	if [ "`head -c32 $DEV`" == "$HEADER" ]; then
+		end_of_log $DEV
+	fi
+done
diff --git a/Documentation/block/blockconsole/mkblockconsole b/Documentation/block/blockconsole/mkblockconsole
new file mode 100755
index 0000000..c48f995
--- /dev/null
+++ b/Documentation/block/blockconsole/mkblockconsole
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+# handle the case when using files for logging instead of
+# real devices (with kvm, for example)
+DD_OPTS="conv=notrunc"
+
+if [ ! $# -eq 1 ]; then
+	echo "Usage: $0 <dev>"
+	exit 1
+elif mount|fgrep -q $1; then
+	echo Device appears to be mounted - aborting
+	exit 1
+else
+	dd if=/dev/zero of=$1 bs=1M count=1 $DD_OPTS
+	# The funky formatting is actually needed!
+	UUID=`head -c4 /dev/urandom |hexdump -e '/4 "%08x"'`
+	echo > /tmp/$UUID
+	echo 'Linux blockconsole version 1.1' >> /tmp/$UUID
+	echo "$UUID" >> /tmp/$UUID
+	echo 00000000 >> /tmp/$UUID
+	echo 00000000 >> /tmp/$UUID
+	for i in `seq 452`; do echo -n " " >> /tmp/$UUID; done
+	echo >> /tmp/$UUID
+
+	dd if=/tmp/$UUID of=$1 $DD_OPTS
+	rm /tmp/$UUID
+	sync
+	exit 0
+fi
diff --git a/Documentation/cgroups/cgroups.txt b/Documentation/cgroups/cgroups.txt
index bcf1a00..0028e88 100644
--- a/Documentation/cgroups/cgroups.txt
+++ b/Documentation/cgroups/cgroups.txt
@@ -580,6 +580,7 @@ propagation along the hierarchy. See the comment on
 cgroup_for_each_descendant_pre() for details.
 
 void css_offline(struct cgroup *cgrp);
+(cgroup_mutex held by caller)
 
 This is the counterpart of css_online() and called iff css_online()
 has succeeded on @cgrp. This signifies the beginning of the end of
diff --git a/Documentation/cgroups/devices.txt b/Documentation/cgroups/devices.txt
index 16624a7f8..3c1095c 100644
--- a/Documentation/cgroups/devices.txt
+++ b/Documentation/cgroups/devices.txt
@@ -13,9 +13,7 @@ either an integer or * for all.  Access is a composition of r
 The root device cgroup starts with rwm to 'all'.  A child device
 cgroup gets a copy of the parent.  Administrators can then remove
 devices from the whitelist or add new entries.  A child cgroup can
-never receive a device access which is denied by its parent.  However
-when a device access is removed from a parent it will not also be
-removed from the child(ren).
+never receive a device access which is denied by its parent.
 
 2. User Interface
 
@@ -50,3 +48,69 @@ task to a new cgroup.  (Again we'll probably want to change that).
 
 A cgroup may not be granted more permissions than the cgroup's
 parent has.
+
+4. Hierarchy
+
+device cgroups maintain hierarchy by making sure a cgroup never has more
+access permissions than its parent.  Every time an entry is written to
+a cgroup's devices.deny file, all its children will have that entry removed
+from their whitelist and all the locally set whitelist entries will be
+re-evaluated.  In case one of the locally set whitelist entries would provide
+more access than the cgroup's parent, it'll be removed from the whitelist.
+
+Example:
+      A
+     / \
+        B
+
+    group        behavior	exceptions
+    A            allow		"b 8:* rwm", "c 116:1 rw"
+    B            deny		"c 1:3 rwm", "c 116:2 rwm", "b 3:* rwm"
+
+If a device is denied in group A:
+	# echo "c 116:* r" > A/devices.deny
+it'll propagate down and after revalidating B's entries, the whitelist entry
+"c 116:2 rwm" will be removed:
+
+    group        whitelist entries                        denied devices
+    A            all                                      "b 8:* rwm", "c 116:* rw"
+    B            "c 1:3 rwm", "b 3:* rwm"                 all the rest
+
+In case parent's exceptions change and local exceptions are not allowed
+anymore, they'll be deleted.
+
+Notice that new whitelist entries will not be propagated:
+      A
+     / \
+        B
+
+    group        whitelist entries                        denied devices
+    A            "c 1:3 rwm", "c 1:5 r"                   all the rest
+    B            "c 1:3 rwm", "c 1:5 r"                   all the rest
+
+when adding "c *:3 rwm":
+	# echo "c *:3 rwm" >A/devices.allow
+
+the result:
+    group        whitelist entries                        denied devices
+    A            "c *:3 rwm", "c 1:5 r"                   all the rest
+    B            "c 1:3 rwm", "c 1:5 r"                   all the rest
+
+but now it'll be possible to add new entries to B:
+	# echo "c 2:3 rwm" >B/devices.allow
+	# echo "c 50:3 r" >B/devices.allow
+or even
+	# echo "c *:3 rwm" >B/devices.allow
+
+Allowing or denying all by writing 'a' to devices.allow or devices.deny will
+not be possible once the device cgroups has children.
+
+4.1 Hierarchy (internal implementation)
+
+device cgroups is implemented internally using a behavior (ALLOW, DENY) and a
+list of exceptions.  The internal state is controlled using the same user
+interface to preserve compatibility with the previous whitelist-only
+implementation.  Removal or addition of exceptions that will reduce the access
+to devices will be propagated down the hierarchy.
+For every propagated exception, the effective rules will be re-evaluated based
+on current parent's access rules.
diff --git a/Documentation/cgroups/memory.txt b/Documentation/cgroups/memory.txt
index 8b8c28b..3aaa984 100644
--- a/Documentation/cgroups/memory.txt
+++ b/Documentation/cgroups/memory.txt
@@ -70,6 +70,7 @@ Brief summary of control files.
  memory.move_charge_at_immigrate # set/show controls of moving charges
  memory.oom_control		 # set/show oom controls.
  memory.numa_stat		 # show the number of memory usage per numa node
+ memory.dangling_memcgs          # show debugging information about dangling groups
 
  memory.kmem.limit_in_bytes      # set/show hard limit for kernel memory
  memory.kmem.usage_in_bytes      # show current kernel memory allocation
@@ -194,7 +195,7 @@ the cgroup that brought it in -- this will happen on memory pressure).
 But see section 8.2: when moving a task to another cgroup, its pages may
 be recharged to the new cgroup, if move_charge_at_immigrate has been chosen.
 
-Exception: If CONFIG_CGROUP_CGROUP_MEMCG_SWAP is not used.
+Exception: If CONFIG_MEMCG_SWAP is not used.
 When you do swapoff and make swapped-out pages of shmem(tmpfs) to
 be backed into memory in force, charges for pages are accounted against the
 caller of swapoff rather than the users of shmem.
@@ -577,6 +578,21 @@ unevictable=<total anon pages> N0=<node 0 pages> N1=<node 1 pages> ...
 
 And we have total = file + anon + unevictable.
 
+5.7 dangling_memcgs
+
+This file will only be ever present in the root cgroup, if the option
+CONFIG_MEMCG_DEBUG_ASYNC_DESTROY is set. When a memcg is destroyed, the memory
+consumed by it may not be immediately freed. This is because when some
+extensions are used, such as swap or kernel memory, objects can outlive the
+group and hold a reference to it.
+
+If this is the case, the dangling_memcgs file will show information about what
+are the memcgs still alive, and which references are still preventing it to be
+freed. There is nothing wrong with that, but it is very useful when debugging,
+to know where this memory is being held. This is a developer-oriented debugging
+facility only, and no guarantees of interface stability will be given. The file
+is read-only, and has the sole purpose of displaying information.
+
 6. Hierarchy support
 
 The memory controller supports a deep hierarchy and hierarchical accounting.
diff --git a/Documentation/clk.txt b/Documentation/clk.txt
index 1943fae..4274a54 100644
--- a/Documentation/clk.txt
+++ b/Documentation/clk.txt
@@ -174,9 +174,9 @@ int clk_foo_enable(struct clk_hw *hw)
 };
 
 Below is a matrix detailing which clk_ops are mandatory based upon the
-hardware capbilities of that clock.  A cell marked as "y" means
+hardware capabilities of that clock.  A cell marked as "y" means
 mandatory, a cell marked as "n" implies that either including that
-callback is invalid or otherwise uneccesary.  Empty cells are either
+callback is invalid or otherwise unnecessary.  Empty cells are either
 optional or must be evaluated on a case-by-case basis.
 
                            clock hardware characteristics
diff --git a/Documentation/cpu-freq/cpu-drivers.txt b/Documentation/cpu-freq/cpu-drivers.txt
index 72f70b1..a3585ea 100644
--- a/Documentation/cpu-freq/cpu-drivers.txt
+++ b/Documentation/cpu-freq/cpu-drivers.txt
@@ -108,8 +108,9 @@ policy->governor		must contain the "default policy" for
 				cpufreq_driver.target is called with
 				these values.
 
-For setting some of these values, the frequency table helpers might be
-helpful. See the section 2 for more information on them.
+For setting some of these values (cpuinfo.min[max]_freq, policy->min[max]), the
+frequency table helpers might be helpful. See the section 2 for more information
+on them.
 
 SMP systems normally have same clock source for a group of cpus. For these the
 .init() would be called only once for the first online cpu. Here the .init()
@@ -184,10 +185,10 @@ the reference implementation in drivers/cpufreq/longrun.c
 As most cpufreq processors only allow for being set to a few specific
 frequencies, a "frequency table" with some functions might assist in
 some work of the processor driver. Such a "frequency table" consists
-of an array of struct cpufreq_freq_table entries, with any value in
+of an array of struct cpufreq_frequency_table entries, with any value in
 "index" you want to use, and the corresponding frequency in
 "frequency". At the end of the table, you need to add a
-cpufreq_freq_table entry with frequency set to CPUFREQ_TABLE_END. And
+cpufreq_frequency_table entry with frequency set to CPUFREQ_TABLE_END. And
 if you want to skip one entry in the table, set the frequency to 
 CPUFREQ_ENTRY_INVALID. The entries don't need to be in ascending
 order.
diff --git a/Documentation/cpu-freq/governors.txt b/Documentation/cpu-freq/governors.txt
index c7a2eb8..4dfed30 100644
--- a/Documentation/cpu-freq/governors.txt
+++ b/Documentation/cpu-freq/governors.txt
@@ -191,6 +191,12 @@ governor but for the opposite direction.  For example when set to its
 default value of '20' it means that if the CPU usage needs to be below
 20% between samples to have the frequency decreased.
 
+sampling_down_factor: similar functionality as in "ondemand" governor.
+But in "conservative", it controls the rate at which the kernel makes
+a decision on when to decrease the frequency while running in any
+speed. Load for frequency increase is still evaluated every
+sampling rate.
+
 3. The Governor Interface in the CPUfreq Core
 =============================================
 
diff --git a/Documentation/device-mapper/dm-raid.txt b/Documentation/device-mapper/dm-raid.txt
index b428556..e919228 100644
--- a/Documentation/device-mapper/dm-raid.txt
+++ b/Documentation/device-mapper/dm-raid.txt
@@ -1,10 +1,13 @@
 dm-raid
--------
+=======
 
 The device-mapper RAID (dm-raid) target provides a bridge from DM to MD.
 It allows the MD RAID drivers to be accessed using a device-mapper
 interface.
 
+
+Mapping Table Interface
+-----------------------
 The target is named "raid" and it accepts the following parameters:
 
   <raid_type> <#raid_params> <raid_params> \
@@ -47,7 +50,7 @@ The target is named "raid" and it accepts the following parameters:
     followed by optional parameters (in any order):
 	[sync|nosync]   Force or prevent RAID initialization.
 
-	[rebuild <idx>]	Rebuild drive number idx (first drive is 0).
+	[rebuild <idx>]	Rebuild drive number 'idx' (first drive is 0).
 
 	[daemon_sleep <ms>]
 		Interval between runs of the bitmap daemon that
@@ -56,9 +59,9 @@ The target is named "raid" and it accepts the following parameters:
 
 	[min_recovery_rate <kB/sec/disk>]  Throttle RAID initialization
 	[max_recovery_rate <kB/sec/disk>]  Throttle RAID initialization
-	[write_mostly <idx>]		   Drive index is write-mostly
-	[max_write_behind <sectors>]       See '-write-behind=' (man mdadm)
-	[stripe_cache <sectors>]           Stripe cache size (higher RAIDs only)
+	[write_mostly <idx>]		   Mark drive index 'idx' write-mostly.
+	[max_write_behind <sectors>]       See '--write-behind=' (man mdadm)
+	[stripe_cache <sectors>]           Stripe cache size (RAID 4/5/6 only)
 	[region_size <sectors>]
 		The region_size multiplied by the number of regions is the
 		logical size of the array.  The bitmap records the device
@@ -122,7 +125,7 @@ The target is named "raid" and it accepts the following parameters:
 	given for both the metadata and data drives for a given position.
 
 
-Example tables
+Example Tables
 --------------
 # RAID4 - 4 data drives, 1 parity (no metadata devices)
 # No metadata devices specified to hold superblock/bitmap info
@@ -141,26 +144,70 @@ Example tables
         raid4 4 2048 sync min_recovery_rate 20 \
         5 8:17 8:18 8:33 8:34 8:49 8:50 8:65 8:66 8:81 8:82
 
+
+Status Output
+-------------
 'dmsetup table' displays the table used to construct the mapping.
 The optional parameters are always printed in the order listed
 above with "sync" or "nosync" always output ahead of the other
 arguments, regardless of the order used when originally loading the table.
 Arguments that can be repeated are ordered by value.
 
-'dmsetup status' yields information on the state and health of the
-array.
-The output is as follows:
+
+'dmsetup status' yields information on the state and health of the array.
+The output is as follows (normally a single line, but expanded here for
+clarity):
 1: <s> <l> raid \
-2:      <raid_type> <#devices> <1 health char for each dev> <resync_ratio>
+2:      <raid_type> <#devices> <health_chars> \
+3:      <sync_ratio> <sync_action> <mismatch_cnt>
 
 Line 1 is the standard output produced by device-mapper.
-Line 2 is produced by the raid target, and best explained by example:
-        0 1960893648 raid raid4 5 AAAAA 2/490221568
+Line 2 & 3 are produced by the raid target and are best explained by example:
+        0 1960893648 raid raid4 5 AAAAA 2/490221568 init 0
 Here we can see the RAID type is raid4, there are 5 devices - all of
-which are 'A'live, and the array is 2/490221568 complete with recovery.
-Faulty or missing devices are marked 'D'.  Devices that are out-of-sync
-are marked 'a'.
-
+which are 'A'live, and the array is 2/490221568 complete with its initial
+recovery.  Here is a fuller description of the individual fields:
+	<raid_type>     Same as the <raid_type> used to create the array.
+	<health_chars>  One char for each device, indicating: 'A' = alive and
+			in-sync, 'a' = alive but not in-sync, 'D' = dead/failed.
+	<sync_ratio>    The ratio indicating how much of the array has undergone
+			the process described by 'sync_action'.  If the
+			'sync_action' is "check" or "repair", then the process
+			of "resync" or "recover" can be considered complete.
+	<sync_action>   One of the following possible states:
+			idle    - No synchronization action is being performed.
+			frozen  - The current action has been halted.
+			resync  - Array is undergoing its initial synchronization
+				  or is resynchronizing after an unclean shutdown
+				  (possibly aided by a bitmap).
+			recover - A device in the array is being rebuilt or
+				  replaced.
+			check   - A user-initiated full check of the array is
+				  being performed.  All blocks are read and
+				  checked for consistency.  The number of
+				  discrepancies found are recorded in
+				  <mismatch_cnt>.  No changes are made to the
+				  array by this action.
+			repair  - The same as "check", but discrepancies are
+				  corrected.
+			reshape - The array is undergoing a reshape.
+	<mismatch_cnt>  The number of discrepancies found between mirror copies
+			in RAID1/10 or wrong parity values found in RAID4/5/6.
+			This value is valid only after a "check" of the array
+			is performed.  A healthy array has a 'mismatch_cnt' of 0.
+
+Message Interface
+-----------------
+The dm-raid target will accept certain actions through the 'message' interface.
+('man dmsetup' for more information on the message interface.)  These actions
+include:
+	"idle"   - Halt the current sync action.
+	"frozen" - Freeze the current sync action.
+	"resync" - Initiate/continue a resync.
+	"recover"- Initiate/continue a recover process.
+	"check"  - Initiate a check (i.e. a "scrub") of the array.
+	"repair" - Initiate a repair of the array.
+	"reshape"- Currently unsupported (-EINVAL).
 
 Version History
 ---------------
@@ -171,4 +218,7 @@ Version History
 1.3.1	Allow device replacement/rebuild for RAID 10
 1.3.2   Fix/improve redundancy checking for RAID10
 1.4.0	Non-functional change.  Removes arg from mapping function.
-1.4.1   Add RAID10 "far" and "offset" algorithm support.
+1.4.1   RAID10 fix redundancy validation checks (commit 55ebbb5).
+1.4.2   Add RAID10 "far" and "offset" algorithm support.
+1.5.0   Add message interface to allow manipulation of the sync_action.
+	New status (STATUSTYPE_INFO) fields: sync_action and mismatch_cnt.
diff --git a/Documentation/devicetree/bindings/arm/atmel-adc.txt b/Documentation/devicetree/bindings/arm/atmel-adc.txt
index c63097d..16769d9 100644
--- a/Documentation/devicetree/bindings/arm/atmel-adc.txt
+++ b/Documentation/devicetree/bindings/arm/atmel-adc.txt
@@ -14,9 +14,19 @@ Required properties:
   - atmel,adc-status-register: Offset of the Interrupt Status Register
   - atmel,adc-trigger-register: Offset of the Trigger Register
   - atmel,adc-vref: Reference voltage in millivolts for the conversions
+  - atmel,adc-res: List of resolution in bits supported by the ADC. List size
+		   must be two at least.
+  - atmel,adc-res-names: Contains one identifier string for each resolution
+			 in atmel,adc-res property. "lowres" and "highres"
+			 identifiers are required.
 
 Optional properties:
   - atmel,adc-use-external: Boolean to enable of external triggers
+  - atmel,adc-use-res: String corresponding to an identifier from
+		       atmel,adc-res-names property. If not specified, the highest
+		       resolution will be used.
+  - atmel,adc-sleep-mode: Boolean to enable sleep mode when no conversion
+  - atmel,adc-sample-hold-time: Sample and Hold Time in microseconds
  
 Optional trigger Nodes:
   - Required properties:
@@ -40,6 +50,9 @@ adc0: adc@fffb0000 {
 	atmel,adc-trigger-register = <0x08>;
 	atmel,adc-use-external;
 	atmel,adc-vref = <3300>;
+	atmel,adc-res = <8 10>;
+	atmel,adc-res-names = "lowres", "highres";
+	atmel,adc-use-res = "lowres";
 
 	trigger@0 {
 		trigger-name = "external-rising";
diff --git a/Documentation/devicetree/bindings/arm/bcm/bcm,kona-timer.txt b/Documentation/devicetree/bindings/arm/bcm/bcm,kona-timer.txt
new file mode 100644
index 0000000..59fa6e6
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/bcm/bcm,kona-timer.txt
@@ -0,0 +1,19 @@
+Broadcom Kona Family timer
+-----------------------------------------------------
+This timer is used in the following Broadcom SoCs:
+ BCM11130, BCM11140, BCM11351, BCM28145, BCM28155
+
+Required properties:
+- compatible : "bcm,kona-timer"
+- reg : Register range for the timer
+- interrupts : interrupt for the timer
+- clock-frequency: frequency that the clock operates
+
+Example:
+	timer@35006000 {
+		compatible = "bcm,kona-timer";
+		reg = <0x35006000 0x1000>;
+		interrupts = <0x0 7 0x4>;
+		clock-frequency = <32768>;
+	};
+
diff --git a/Documentation/devicetree/bindings/arm/msm/ssbi.txt b/Documentation/devicetree/bindings/arm/msm/ssbi.txt
new file mode 100644
index 0000000..54fd5ce
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/ssbi.txt
@@ -0,0 +1,18 @@
+* Qualcomm SSBI
+
+Some Qualcomm MSM devices contain a point-to-point serial bus used to
+communicate with a limited range of devices (mostly power management
+chips).
+
+These require the following properties:
+
+- compatible: "qcom,ssbi"
+
+- qcom,controller-type
+  indicates the SSBI bus variant the controller should use to talk
+  with the slave device.  This should be one of "ssbi", "ssbi2", or
+  "pmic-arbiter".  The type chosen is determined by the attached
+  slave.
+
+The slave device should be the single child node of the ssbi device
+with a compatible field.
diff --git a/Documentation/devicetree/bindings/arm/msm/timer.txt b/Documentation/devicetree/bindings/arm/msm/timer.txt
index 8c5907b..c6ef8f1 100644
--- a/Documentation/devicetree/bindings/arm/msm/timer.txt
+++ b/Documentation/devicetree/bindings/arm/msm/timer.txt
@@ -3,36 +3,35 @@
 Properties:
 
 - compatible : Should at least contain "qcom,msm-timer". More specific
-  properties such as "qcom,msm-gpt" and "qcom,msm-dgt" specify a general
-  purpose timer and a debug timer respectively.
+               properties specify which subsystem the timers are paired with.
 
-- interrupts : Interrupt indicating a match event.
+               "qcom,kpss-timer" - krait subsystem
+               "qcom,scss-timer" - scorpion subsystem
 
-- reg : Specifies the base address of the timer registers. The second region
-  specifies an optional register used to configure the clock divider.
+- interrupts : Interrupts for the the debug timer, the first general purpose
+               timer, and optionally a second general purpose timer in that
+               order.
 
-- clock-frequency : The frequency of the timer in Hz.
+- reg : Specifies the base address of the timer registers.
+
+- clock-frequency : The frequency of the debug timer and the general purpose
+                    timer(s) in Hz in that order.
 
 Optional:
 
 - cpu-offset : per-cpu offset used when the timer is accessed without the
-  CPU remapping facilities. The offset is cpu-offset * cpu-nr.
+               CPU remapping facilities. The offset is
+               cpu-offset + (0x10000 * cpu-nr).
 
 Example:
 
-       timer@200a004 {
-               compatible = "qcom,msm-gpt", "qcom,msm-timer";
-               interrupts = <1 2 0x301>;
-               reg = <0x0200a004 0x10>;
-               clock-frequency = <32768>;
-               cpu-offset = <0x40000>;
-       };
-
-       timer@200a024 {
-               compatible = "qcom,msm-dgt", "qcom,msm-timer";
-               interrupts = <1 3 0x301>;
-               reg = <0x0200a024 0x10>,
-                     <0x0200a034 0x4>;
-               clock-frequency = <6750000>;
+       timer@200a000 {
+               compatible = "qcom,scss-timer", "qcom,msm-timer";
+               interrupts = <1 1 0x301>,
+                            <1 2 0x301>,
+                            <1 3 0x301>;
+               reg = <0x0200a000 0x100>;
+               clock-frequency = <19200000>,
+                                 <32768>;
                cpu-offset = <0x40000>;
        };
diff --git a/Documentation/devicetree/bindings/arm/samsung-boards.txt b/Documentation/devicetree/bindings/arm/samsung-boards.txt
index 0bf68be..2168ed3 100644
--- a/Documentation/devicetree/bindings/arm/samsung-boards.txt
+++ b/Documentation/devicetree/bindings/arm/samsung-boards.txt
@@ -6,3 +6,13 @@ Required root node properties:
     - compatible = should be one or more of the following.
         (a) "samsung,smdkv310" - for Samsung's SMDKV310 eval board.
         (b) "samsung,exynos4210"  - for boards based on Exynos4210 SoC.
+
+Optional:
+    - firmware node, specifying presence and type of secure firmware:
+        - compatible: only "samsung,secure-firmware" is currently supported
+        - reg: address of non-secure SYSRAM used for communication with firmware
+
+	firmware@0203F000 {
+		compatible = "samsung,secure-firmware";
+		reg = <0x0203F000 0x1000>;
+	};
diff --git a/Documentation/devicetree/bindings/arm/samsung/exynos-adc.txt b/Documentation/devicetree/bindings/arm/samsung/exynos-adc.txt
new file mode 100644
index 0000000..47ada1d
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/samsung/exynos-adc.txt
@@ -0,0 +1,60 @@
+Samsung Exynos Analog to Digital Converter bindings
+
+The devicetree bindings are for the new ADC driver written for
+Exynos4 and upward SoCs from Samsung.
+
+New driver handles the following
+1. Supports ADC IF found on EXYNOS4412/EXYNOS5250
+   and future SoCs from Samsung
+2. Add ADC driver under iio/adc framework
+3. Also adds the Documentation for device tree bindings
+
+Required properties:
+- compatible:		Must be "samsung,exynos-adc-v1"
+				for exynos4412/5250 controllers.
+			Must be "samsung,exynos-adc-v2" for
+				future controllers.
+- reg:			Contains ADC register address range (base address and
+			length) and the address of the phy enable register.
+- interrupts: 		Contains the interrupt information for the timer. The
+			format is being dependent on which interrupt controller
+			the Samsung device uses.
+- #io-channel-cells = <1>; As ADC has multiple outputs
+- clocks		From common clock binding: handle to adc clock.
+- clock-names		From common clock binding: Shall be "adc".
+- vdd-supply		VDD input supply.
+
+Note: child nodes can be added for auto probing from device tree.
+
+Example: adding device info in dtsi file
+
+adc: adc@12D10000 {
+	compatible = "samsung,exynos-adc-v1";
+	reg = <0x12D10000 0x100>, <0x10040718 0x4>;
+	interrupts = <0 106 0>;
+	#io-channel-cells = <1>;
+	io-channel-ranges;
+
+	clocks = <&clock 303>;
+	clock-names = "adc";
+
+	vdd-supply = <&buck5_reg>;
+};
+
+
+Example: Adding child nodes in dts file
+
+adc@12D10000 {
+
+	/* NTC thermistor is a hwmon device */
+	ncp15wb473@0 {
+		compatible = "ntc,ncp15wb473";
+		pullup-uV = <1800000>;
+		pullup-ohm = <47000>;
+		pulldown-ohm = <0>;
+		io-channels = <&adc 4>;
+	};
+};
+
+Note: Does not apply to ADC driver under arch/arm/plat-samsung/
+Note: The child node can be added under the adc node or separately.
diff --git a/Documentation/devicetree/bindings/arm/samsung/sysreg.txt b/Documentation/devicetree/bindings/arm/samsung/sysreg.txt
new file mode 100644
index 0000000..5039c0a
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/samsung/sysreg.txt
@@ -0,0 +1,7 @@
+SAMSUNG S5P/Exynos SoC series System Registers (SYSREG)
+
+Properties:
+ - name : should be 'sysreg';
+ - compatible : should contain "samsung,<chip name>-sysreg", "syscon";
+   For Exynos4 SoC series it should be "samsung,exynos4-sysreg", "syscon";
+ - reg : offset and length of the register set.
diff --git a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt
index b5846e2..1608a54 100644
--- a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt
+++ b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt
@@ -1,19 +1,84 @@
 NVIDIA Tegra Power Management Controller (PMC)
 
-Properties:
+The PMC block interacts with an external Power Management Unit. The PMC
+mostly controls the entry and exit of the system from different sleep
+modes. It provides power-gating controllers for SoC and CPU power-islands.
+
+Required properties:
 - name : Should be pmc
 - compatible : Should contain "nvidia,tegra<chip>-pmc".
 - reg : Offset and length of the register set for the device
+- clocks : Must contain an entry for each entry in clock-names.
+- clock-names : Must include the following entries:
+  "pclk" (The Tegra clock of that name),
+  "clk32k_in" (The 32KHz clock input to Tegra).
+
+Optional properties:
 - nvidia,invert-interrupt : If present, inverts the PMU interrupt signal.
   The PMU is an external Power Management Unit, whose interrupt output
   signal is fed into the PMC. This signal is optionally inverted, and then
   fed into the ARM GIC. The PMC is not involved in the detection or
   handling of this interrupt signal, merely its inversion.
+- nvidia,suspend-mode : The suspend mode that the platform should use.
+  Valid values are 0, 1 and 2:
+  0 (LP0): CPU + Core voltage off and DRAM in self-refresh
+  1 (LP1): CPU voltage off and DRAM in self-refresh
+  2 (LP2): CPU voltage off
+- nvidia,core-power-req-active-high : Boolean, core power request active-high
+- nvidia,sys-clock-req-active-high : Boolean, system clock request active-high
+- nvidia,combined-power-req : Boolean, combined power request for CPU & Core
+- nvidia,cpu-pwr-good-en : Boolean, CPU power good signal (from PMIC to PMC)
+			   is enabled.
+
+Required properties when nvidia,suspend-mode is specified:
+- nvidia,cpu-pwr-good-time : CPU power good time in uS.
+- nvidia,cpu-pwr-off-time : CPU power off time in uS.
+- nvidia,core-pwr-good-time : <Oscillator-stable-time Power-stable-time>
+			      Core power good time in uS.
+- nvidia,core-pwr-off-time : Core power off time in uS.
+
+Required properties when nvidia,suspend-mode=<0>:
+- nvidia,lp0-vec : <start length> Starting address and length of LP0 vector
+  The LP0 vector contains the warm boot code that is executed by AVP when
+  resuming from the LP0 state. The AVP (Audio-Video Processor) is an ARM7
+  processor and always being the first boot processor when chip is power on
+  or resume from deep sleep mode. When the system is resumed from the deep
+  sleep mode, the warm boot code will restore some PLLs, clocks and then
+  bring up CPU0 for resuming the system.
 
 Example:
 
+/ SoC dts including file
 pmc@7000f400 {
 	compatible = "nvidia,tegra20-pmc";
 	reg = <0x7000e400 0x400>;
+	clocks = <&tegra_car 110>, <&clk32k_in>;
+	clock-names = "pclk", "clk32k_in";
 	nvidia,invert-interrupt;
+	nvidia,suspend-mode = <1>;
+	nvidia,cpu-pwr-good-time = <2000>;
+	nvidia,cpu-pwr-off-time = <100>;
+	nvidia,core-pwr-good-time = <3845 3845>;
+	nvidia,core-pwr-off-time = <458>;
+	nvidia,core-power-req-active-high;
+	nvidia,sys-clock-req-active-high;
+	nvidia,lp0-vec = <0xbdffd000 0x2000>;
+};
+
+/ Tegra board dts file
+{
+	...
+	clocks {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		clk32k_in: clock {
+			compatible = "fixed-clock";
+			reg=<0>;
+			#clock-cells = <0>;
+			clock-frequency = <32768>;
+		};
+	};
+	...
 };
diff --git a/Documentation/devicetree/bindings/clock/axi-clkgen.txt b/Documentation/devicetree/bindings/clock/axi-clkgen.txt
new file mode 100644
index 0000000..028b493
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/axi-clkgen.txt
@@ -0,0 +1,22 @@
+Binding for the axi-clkgen clock generator
+
+This binding uses the common clock binding[1].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- compatible : shall be "adi,axi-clkgen".
+- #clock-cells : from common clock binding; Should always be set to 0.
+- reg : Address and length of the axi-clkgen register set.
+- clocks : Phandle and clock specifier for the parent clock.
+
+Optional properties:
+- clock-output-names : From common clock binding.
+
+Example:
+	clock@0xff000000 {
+		compatible = "adi,axi-clkgen";
+		#clock-cells = <0>;
+		reg = <0xff000000 0x1000>;
+		clocks = <&osc 1>;
+	};
diff --git a/Documentation/devicetree/bindings/clock/exynos4-clock.txt b/Documentation/devicetree/bindings/clock/exynos4-clock.txt
new file mode 100644
index 0000000..662007e
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/exynos4-clock.txt
@@ -0,0 +1,274 @@
+* Samsung Exynos4 Clock Controller
+
+The Exynos4 clock controller generates and supplies clock to various controllers
+within the Exynos4 SoC. The clock binding described here is applicable to all
+SoC's in the Exynos4 family.
+
+Required Properties:
+
+- comptible: should be one of the following.
+  - "samsung,exynos4210-clock" - controller compatible with Exynos4210 SoC.
+  - "samsung,exynos4412-clock" - controller compatible with Exynos4412 SoC.
+
+- reg: physical base address of the controller and length of memory mapped
+  region.
+
+- #clock-cells: should be 1.
+
+The following is the list of clocks generated by the controller. Each clock is
+assigned an identifier and client nodes use this identifier to specify the
+clock which they consume. Some of the clocks are available only on a particular
+Exynos4 SoC and this is specified where applicable.
+
+
+		 [Core Clocks]
+
+  Clock               ID      SoC (if specific)
+  -----------------------------------------------
+
+  xxti                1
+  xusbxti             2
+  fin_pll             3
+  fout_apll           4
+  fout_mpll           5
+  fout_epll           6
+  fout_vpll           7
+  sclk_apll           8
+  sclk_mpll           9
+  sclk_epll           10
+  sclk_vpll           11
+  arm_clk             12
+  aclk200             13
+  aclk100             14
+  aclk160             15
+  aclk133             16
+  mout_mpll_user_t    17      Exynos4x12
+  mout_mpll_user_c    18      Exynos4x12
+  mout_core           19
+  mout_apll           20
+
+
+            [Clock Gate for Special Clocks]
+
+  Clock               ID      SoC (if specific)
+  -----------------------------------------------
+
+  sclk_fimc0          128
+  sclk_fimc1          129
+  sclk_fimc2          130
+  sclk_fimc3          131
+  sclk_cam0           132
+  sclk_cam1           133
+  sclk_csis0          134
+  sclk_csis1          135
+  sclk_hdmi           136
+  sclk_mixer          137
+  sclk_dac            138
+  sclk_pixel          139
+  sclk_fimd0          140
+  sclk_mdnie0         141     Exynos4412
+  sclk_mdnie_pwm0 12  142     Exynos4412
+  sclk_mipi0          143
+  sclk_audio0         144
+  sclk_mmc0           145
+  sclk_mmc1           146
+  sclk_mmc2           147
+  sclk_mmc3           148
+  sclk_mmc4           149
+  sclk_sata           150     Exynos4210
+  sclk_uart0          151
+  sclk_uart1          152
+  sclk_uart2          153
+  sclk_uart3          154
+  sclk_uart4          155
+  sclk_audio1         156
+  sclk_audio2         157
+  sclk_spdif          158
+  sclk_spi0           159
+  sclk_spi1           160
+  sclk_spi2           161
+  sclk_slimbus        162
+  sclk_fimd1          163     Exynos4210
+  sclk_mipi1          164     Exynos4210
+  sclk_pcm1           165
+  sclk_pcm2           166
+  sclk_i2s1           167
+  sclk_i2s2           168
+  sclk_mipihsi        169     Exynos4412
+  sclk_mfc            170
+  sclk_pcm0           171
+  sclk_g3d            172
+  sclk_pwm_isp        173     Exynos4x12
+  sclk_spi0_isp       174     Exynos4x12
+  sclk_spi1_isp       175     Exynos4x12
+  sclk_uart_isp       176     Exynos4x12
+
+	      [Peripheral Clock Gates]
+
+  Clock               ID      SoC (if specific)
+  -----------------------------------------------
+
+  fimc0               256
+  fimc1               257
+  fimc2               258
+  fimc3               259
+  csis0               260
+  csis1               261
+  jpeg                262
+  smmu_fimc0          263
+  smmu_fimc1          264
+  smmu_fimc2          265
+  smmu_fimc3          266
+  smmu_jpeg           267
+  vp                  268
+  mixer               269
+  tvenc               270     Exynos4210
+  hdmi                271
+  smmu_tv             272
+  mfc                 273
+  smmu_mfcl           274
+  smmu_mfcr           275
+  g3d                 276
+  g2d                 277     Exynos4210
+  rotator             278     Exynos4210
+  mdma                279     Exynos4210
+  smmu_g2d            280     Exynos4210
+  smmu_rotator        281     Exynos4210
+  smmu_mdma           282     Exynos4210
+  fimd0               283
+  mie0                284
+  mdnie0              285     Exynos4412
+  dsim0               286
+  smmu_fimd0          287
+  fimd1               288     Exynos4210
+  mie1                289     Exynos4210
+  dsim1               290     Exynos4210
+  smmu_fimd1          291     Exynos4210
+  pdma0               292
+  pdma1               293
+  pcie_phy            294
+  sata_phy            295     Exynos4210
+  tsi                 296
+  sdmmc0              297
+  sdmmc1              298
+  sdmmc2              299
+  sdmmc3              300
+  sdmmc4              301
+  sata                302     Exynos4210
+  sromc               303
+  usb_host            304
+  usb_device          305
+  pcie                306
+  onenand             307
+  nfcon               308
+  smmu_pcie           309
+  gps                 310
+  smmu_gps            311
+  uart0               312
+  uart1               313
+  uart2               314
+  uart3               315
+  uart4               316
+  i2c0                317
+  i2c1                318
+  i2c2                319
+  i2c3                320
+  i2c4                321
+  i2c5                322
+  i2c6                323
+  i2c7                324
+  i2c_hdmi            325
+  tsadc               326
+  spi0                327
+  spi1                328
+  spi2                329
+  i2s1                330
+  i2s2                331
+  pcm0                332
+  i2s0                333
+  pcm1                334
+  pcm2                335
+  pwm                 336
+  slimbus             337
+  spdif               338
+  ac97                339
+  modemif             340
+  chipid              341
+  sysreg              342
+  hdmi_cec            343
+  mct                 344
+  wdt                 345
+  rtc                 346
+  keyif               347
+  audss               348
+  mipi_hsi            349     Exynos4210
+  mdma2               350     Exynos4210
+  pixelasyncm0        351
+  pixelasyncm1        352
+  fimc_lite0          353     Exynos4x12
+  fimc_lite1          354     Exynos4x12
+  ppmuispx            355     Exynos4x12
+  ppmuispmx           356     Exynos4x12
+  fimc_isp            357     Exynos4x12
+  fimc_drc            358     Exynos4x12
+  fimc_fd             359     Exynos4x12
+  mcuisp              360     Exynos4x12
+  gicisp              361     Exynos4x12
+  smmu_isp            362     Exynos4x12
+  smmu_drc            363     Exynos4x12
+  smmu_fd             364     Exynos4x12
+  smmu_lite0          365     Exynos4x12
+  smmu_lite1          366     Exynos4x12
+  mcuctl_isp          367     Exynos4x12
+  mpwm_isp            368     Exynos4x12
+  i2c0_isp            369     Exynos4x12
+  i2c1_isp            370     Exynos4x12
+  mtcadc_isp          371     Exynos4x12
+  pwm_isp             372     Exynos4x12
+  wdt_isp             373     Exynos4x12
+  uart_isp            374     Exynos4x12
+  asyncaxim           375     Exynos4x12
+  smmu_ispcx          376     Exynos4x12
+  spi0_isp            377     Exynos4x12
+  spi1_isp            378     Exynos4x12
+  pwm_isp_sclk        379     Exynos4x12
+  spi0_isp_sclk       380     Exynos4x12
+  spi1_isp_sclk       381     Exynos4x12
+  uart_isp_sclk       382     Exynos4x12
+
+			[Mux Clocks]
+
+	Clock		ID	SoC (if specific)
+	-----------------------------------------------
+
+	mout_fimc0	384
+	mout_fimc1	385
+	mout_fimc2	386
+	mout_fimc3	387
+	mout_cam0	388
+	mout_cam1	389
+	mout_csis0	390
+	mout_csis1	391
+	mout_g3d0	392
+	mout_g3d1	393
+	mout_g3d	394
+
+Example 1: An example of a clock controller node is listed below.
+
+	clock: clock-controller@0x10030000 {
+		compatible = "samsung,exynos4210-clock";
+		reg = <0x10030000 0x20000>;
+		#clock-cells = <1>;
+	};
+
+Example 2: UART controller node that consumes the clock generated by the clock
+	   controller. Refer to the standard clock bindings for information
+	   about 'clocks' and 'clock-names' property.
+
+	serial@13820000 {
+		compatible = "samsung,exynos4210-uart";
+		reg = <0x13820000 0x100>;
+		interrupts = <0 54 0>;
+		clocks = <&clock 314>, <&clock 153>;
+		clock-names = "uart", "clk_uart_baud0";
+	};
diff --git a/Documentation/devicetree/bindings/clock/exynos5250-clock.txt b/Documentation/devicetree/bindings/clock/exynos5250-clock.txt
new file mode 100644
index 0000000..781a627
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/exynos5250-clock.txt
@@ -0,0 +1,177 @@
+* Samsung Exynos5250 Clock Controller
+
+The Exynos5250 clock controller generates and supplies clock to various
+controllers within the Exynos5250 SoC.
+
+Required Properties:
+
+- comptible: should be one of the following.
+  - "samsung,exynos5250-clock" - controller compatible with Exynos5250 SoC.
+
+- reg: physical base address of the controller and length of memory mapped
+  region.
+
+- #clock-cells: should be 1.
+
+The following is the list of clocks generated by the controller. Each clock is
+assigned an identifier and client nodes use this identifier to specify the
+clock which they consume.
+
+
+       [Core Clocks]
+
+  Clock			ID
+  ----------------------------
+
+  fin_pll		1
+
+  [Clock Gate for Special Clocks]
+
+  Clock			ID
+  ----------------------------
+
+  sclk_cam_bayer	128
+  sclk_cam0		129
+  sclk_cam1		130
+  sclk_gscl_wa		131
+  sclk_gscl_wb		132
+  sclk_fimd1		133
+  sclk_mipi1		134
+  sclk_dp		135
+  sclk_hdmi		136
+  sclk_pixel		137
+  sclk_audio0		138
+  sclk_mmc0		139
+  sclk_mmc1		140
+  sclk_mmc2		141
+  sclk_mmc3		142
+  sclk_sata		143
+  sclk_usb3		144
+  sclk_jpeg		145
+  sclk_uart0		146
+  sclk_uart1		147
+  sclk_uart2		148
+  sclk_uart3		149
+  sclk_pwm		150
+  sclk_audio1		151
+  sclk_audio2		152
+  sclk_spdif		153
+  sclk_spi0		154
+  sclk_spi1		155
+  sclk_spi2		156
+
+
+   [Peripheral Clock Gates]
+
+  Clock			ID
+  ----------------------------
+
+  gscl0			256
+  gscl1			257
+  gscl2			258
+  gscl3			259
+  gscl_wa		260
+  gscl_wb		261
+  smmu_gscl0		262
+  smmu_gscl1		263
+  smmu_gscl2		264
+  smmu_gscl3		265
+  mfc			266
+  smmu_mfcl		267
+  smmu_mfcr		268
+  rotator		269
+  jpeg			270
+  mdma1			271
+  smmu_rotator		272
+  smmu_jpeg		273
+  smmu_mdma1		274
+  pdma0			275
+  pdma1			276
+  sata			277
+  usbotg		278
+  mipi_hsi		279
+  sdmmc0		280
+  sdmmc1		281
+  sdmmc2		282
+  sdmmc3		283
+  sromc			284
+  usb2			285
+  usb3			286
+  sata_phyctrl		287
+  sata_phyi2c		288
+  uart0			289
+  uart1			290
+  uart2			291
+  uart3			292
+  uart4			293
+  i2c0			294
+  i2c1			295
+  i2c2			296
+  i2c3			297
+  i2c4			298
+  i2c5			299
+  i2c6			300
+  i2c7			301
+  i2c_hdmi		302
+  adc			303
+  spi0			304
+  spi1			305
+  spi2			306
+  i2s1			307
+  i2s2			308
+  pcm1			309
+  pcm2			310
+  pwm			311
+  spdif			312
+  ac97			313
+  hsi2c0		314
+  hsi2c1		315
+  hs12c2		316
+  hs12c3		317
+  chipid		318
+  sysreg		319
+  pmu			320
+  cmu_top		321
+  cmu_core		322
+  cmu_mem		323
+  tzpc0			324
+  tzpc1			325
+  tzpc2			326
+  tzpc3			327
+  tzpc4			328
+  tzpc5			329
+  tzpc6			330
+  tzpc7			331
+  tzpc8			332
+  tzpc9			333
+  hdmi_cec		334
+  mct			335
+  wdt			336
+  rtc			337
+  tmu			338
+  fimd1			339
+  mie1			340
+  dsim0			341
+  dp			342
+  mixer			343
+  hdmi			345
+
+Example 1: An example of a clock controller node is listed below.
+
+	clock: clock-controller@0x10010000 {
+		compatible = "samsung,exynos5250-clock";
+		reg = <0x10010000 0x30000>;
+		#clock-cells = <1>;
+	};
+
+Example 2: UART controller node that consumes the clock generated by the clock
+	   controller. Refer to the standard clock bindings for information
+	   about 'clocks' and 'clock-names' property.
+
+	serial@13820000 {
+		compatible = "samsung,exynos4210-uart";
+		reg = <0x13820000 0x100>;
+		interrupts = <0 54 0>;
+		clocks = <&clock 314>, <&clock 153>;
+		clock-names = "uart", "clk_uart_baud0";
+	};
diff --git a/Documentation/devicetree/bindings/clock/exynos5440-clock.txt b/Documentation/devicetree/bindings/clock/exynos5440-clock.txt
new file mode 100644
index 0000000..4499e99
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/exynos5440-clock.txt
@@ -0,0 +1,61 @@
+* Samsung Exynos5440 Clock Controller
+
+The Exynos5440 clock controller generates and supplies clock to various
+controllers within the Exynos5440 SoC.
+
+Required Properties:
+
+- comptible: should be "samsung,exynos5440-clock".
+
+- reg: physical base address of the controller and length of memory mapped
+  region.
+
+- #clock-cells: should be 1.
+
+The following is the list of clocks generated by the controller. Each clock is
+assigned an identifier and client nodes use this identifier to specify the
+clock which they consume.
+
+
+       [Core Clocks]
+
+  Clock			ID
+  ----------------------------
+
+  xtal			1
+  arm_clk		2
+
+   [Peripheral Clock Gates]
+
+  Clock			ID
+  ----------------------------
+
+  spi_baud		16
+  pb0_250		17
+  pr0_250		18
+  pr1_250		19
+  b_250			20
+  b_125			21
+  b_200			22
+  sata			23
+  usb			24
+  gmac0			25
+  cs250			26
+  pb0_250_o		27
+  pr0_250_o		28
+  pr1_250_o		29
+  b_250_o		30
+  b_125_o		31
+  b_200_o		32
+  sata_o		33
+  usb_o			34
+  gmac0_o		35
+  cs250_o		36
+
+Example: An example of a clock controller node is listed below.
+
+	clock: clock-controller@0x10010000 {
+		compatible = "samsung,exynos5440-clock";
+		reg = <0x160000 0x10000>;
+		#clock-cells = <1>;
+	};
diff --git a/Documentation/devicetree/bindings/clock/imx27-clock.txt b/Documentation/devicetree/bindings/clock/imx27-clock.txt
new file mode 100644
index 0000000..ab1a56e
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/imx27-clock.txt
@@ -0,0 +1,117 @@
+* Clock bindings for Freescale i.MX27
+
+Required properties:
+- compatible: Should be "fsl,imx27-ccm"
+- reg: Address and length of the register set
+- interrupts: Should contain CCM interrupt
+- #clock-cells: Should be <1>
+
+The clock consumer should specify the desired clock by having the clock
+ID in its "clocks" phandle cell.  The following is a full list of i.MX27
+clocks and IDs.
+
+	Clock		    ID
+	-----------------------
+	dummy                0
+	ckih                 1
+	ckil                 2
+	mpll                 3
+	spll                 4
+	mpll_main2           5
+	ahb                  6
+	ipg                  7
+	nfc_div              8
+	per1_div             9
+	per2_div             10
+	per3_div             11
+	per4_div             12
+	vpu_sel              13
+	vpu_div              14
+	usb_div              15
+	cpu_sel              16
+	clko_sel             17
+	cpu_div              18
+	clko_div             19
+	ssi1_sel             20
+	ssi2_sel             21
+	ssi1_div             22
+	ssi2_div             23
+	clko_en              24
+	ssi2_ipg_gate        25
+	ssi1_ipg_gate        26
+	slcdc_ipg_gate       27
+	sdhc3_ipg_gate       28
+	sdhc2_ipg_gate       29
+	sdhc1_ipg_gate       30
+	scc_ipg_gate         31
+	sahara_ipg_gate      32
+	rtc_ipg_gate         33
+	pwm_ipg_gate         34
+	owire_ipg_gate       35
+	lcdc_ipg_gate        36
+	kpp_ipg_gate         37
+	iim_ipg_gate         38
+	i2c2_ipg_gate        39
+	i2c1_ipg_gate        40
+	gpt6_ipg_gate        41
+	gpt5_ipg_gate        42
+	gpt4_ipg_gate        43
+	gpt3_ipg_gate        44
+	gpt2_ipg_gate        45
+	gpt1_ipg_gate        46
+	gpio_ipg_gate        47
+	fec_ipg_gate         48
+	emma_ipg_gate        49
+	dma_ipg_gate         50
+	cspi3_ipg_gate       51
+	cspi2_ipg_gate       52
+	cspi1_ipg_gate       53
+	nfc_baud_gate        54
+	ssi2_baud_gate       55
+	ssi1_baud_gate       56
+	vpu_baud_gate        57
+	per4_gate            58
+	per3_gate            59
+	per2_gate            60
+	per1_gate            61
+	usb_ahb_gate         62
+	slcdc_ahb_gate       63
+	sahara_ahb_gate      64
+	lcdc_ahb_gate        65
+	vpu_ahb_gate         66
+	fec_ahb_gate         67
+	emma_ahb_gate        68
+	emi_ahb_gate         69
+	dma_ahb_gate         70
+	csi_ahb_gate         71
+	brom_ahb_gate        72
+	ata_ahb_gate         73
+	wdog_ipg_gate        74
+	usb_ipg_gate         75
+	uart6_ipg_gate       76
+	uart5_ipg_gate       77
+	uart4_ipg_gate       78
+	uart3_ipg_gate       79
+	uart2_ipg_gate       80
+	uart1_ipg_gate       81
+	ckih_div1p5          82
+	fpm                  83
+	mpll_osc_sel         84
+	mpll_sel             85
+
+Examples:
+
+clks: ccm@10027000{
+	compatible = "fsl,imx27-ccm";
+	reg = <0x10027000 0x1000>;
+	#clock-cells = <1>;
+};
+
+uart1: serial@1000a000 {
+	compatible = "fsl,imx27-uart", "fsl,imx21-uart";
+	reg = <0x1000a000 0x1000>;
+	interrupts = <20>;
+	clocks = <&clks 81>, <&clks 61>;
+	clock-names = "ipg", "per";
+	status = "disabled";
+};
diff --git a/Documentation/devicetree/bindings/clock/imx5-clock.txt b/Documentation/devicetree/bindings/clock/imx5-clock.txt
index 2a0c904..84cae1f 100644
--- a/Documentation/devicetree/bindings/clock/imx5-clock.txt
+++ b/Documentation/devicetree/bindings/clock/imx5-clock.txt
@@ -172,6 +172,19 @@ clocks and IDs.
 	can1_serial_gate	157
 	can1_ipg_gate		158
 	owire_gate		159
+	gpu3d_s			160
+	gpu2d_s			161
+	gpu3d_gate		162
+	gpu2d_gate		163
+	garb_gate		164
+	cko1_sel		165
+	cko1_podf		166
+	cko1			167
+	cko2_sel		168
+	cko2_podf		169
+	cko2			170
+	srtc_gate		171
+	pata_gate		172
 
 Examples (for mx53):
 
diff --git a/Documentation/devicetree/bindings/clock/imx6q-clock.txt b/Documentation/devicetree/bindings/clock/imx6q-clock.txt
index 969b38e..6deb6fd 100644
--- a/Documentation/devicetree/bindings/clock/imx6q-clock.txt
+++ b/Documentation/devicetree/bindings/clock/imx6q-clock.txt
@@ -205,6 +205,9 @@ clocks and IDs.
 	enet_ref		190
 	usbphy1_gate		191
 	usbphy2_gate		192
+	pll4_post_div		193
+	pll5_post_div		194
+	pll5_video_div		195
 
 Examples:
 
diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt
new file mode 100644
index 0000000..729f524
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/sunxi.txt
@@ -0,0 +1,151 @@
+Device Tree Clock bindings for arch-sunxi
+
+This binding uses the common clock binding[1].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- compatible : shall be one of the following:
+	"allwinner,sun4i-osc-clk" - for a gatable oscillator
+	"allwinner,sun4i-pll1-clk" - for the main PLL clock
+	"allwinner,sun4i-cpu-clk" - for the CPU multiplexer clock
+	"allwinner,sun4i-axi-clk" - for the AXI clock
+	"allwinner,sun4i-axi-gates-clk" - for the AXI gates
+	"allwinner,sun4i-ahb-clk" - for the AHB clock
+	"allwinner,sun4i-ahb-gates-clk" - for the AHB gates
+	"allwinner,sun4i-apb0-clk" - for the APB0 clock
+	"allwinner,sun4i-apb0-gates-clk" - for the APB0 gates
+	"allwinner,sun4i-apb1-clk" - for the APB1 clock
+	"allwinner,sun4i-apb1-mux-clk" - for the APB1 clock muxing
+	"allwinner,sun4i-apb1-gates-clk" - for the APB1 gates
+
+Required properties for all clocks:
+- reg : shall be the control register address for the clock.
+- clocks : shall be the input parent clock(s) phandle for the clock
+- #clock-cells : from common clock binding; shall be set to 0 except for
+	"allwinner,sun4i-*-gates-clk" where it shall be set to 1
+
+Additionally, "allwinner,sun4i-*-gates-clk" clocks require:
+- clock-output-names : the corresponding gate names that the clock controls
+
+For example:
+
+osc24M: osc24M@01c20050 {
+	#clock-cells = <0>;
+	compatible = "allwinner,sun4i-osc-clk";
+	reg = <0x01c20050 0x4>;
+	clocks = <&osc24M_fixed>;
+};
+
+pll1: pll1@01c20000 {
+	#clock-cells = <0>;
+	compatible = "allwinner,sun4i-pll1-clk";
+	reg = <0x01c20000 0x4>;
+	clocks = <&osc24M>;
+};
+
+cpu: cpu@01c20054 {
+	#clock-cells = <0>;
+	compatible = "allwinner,sun4i-cpu-clk";
+	reg = <0x01c20054 0x4>;
+	clocks = <&osc32k>, <&osc24M>, <&pll1>;
+};
+
+
+
+Gate clock outputs
+
+The "allwinner,sun4i-*-gates-clk" clocks provide several gatable outputs;
+their corresponding offsets as present on sun4i are listed below. Note that
+some of these gates are not present on sun5i.
+
+  * AXI gates ("allwinner,sun4i-axi-gates-clk")
+
+    DRAM                                                                0
+
+  * AHB gates ("allwinner,sun4i-ahb-gates-clk")
+
+    USB0                                                                0
+    EHCI0                                                               1
+    OHCI0                                                               2*
+    EHCI1                                                               3
+    OHCI1                                                               4*
+    SS                                                                  5
+    DMA                                                                 6
+    BIST                                                                7
+    MMC0                                                                8
+    MMC1                                                                9
+    MMC2                                                                10
+    MMC3                                                                11
+    MS                                                                  12**
+    NAND                                                                13
+    SDRAM                                                               14
+
+    ACE                                                                 16
+    EMAC                                                                17
+    TS                                                                  18
+
+    SPI0                                                                20
+    SPI1                                                                21
+    SPI2                                                                22
+    SPI3                                                                23
+    PATA                                                                24
+    SATA                                                                25**
+    GPS                                                                 26*
+
+    VE                                                                  32
+    TVD                                                                 33
+    TVE0                                                                34
+    TVE1                                                                35
+    LCD0                                                                36
+    LCD1                                                                37
+
+    CSI0                                                                40
+    CSI1                                                                41
+
+    HDMI                                                                43
+    DE_BE0                                                              44
+    DE_BE1                                                              45
+    DE_FE0                                                              46
+    DE_FE1                                                              47
+
+    MP                                                                  50
+
+    MALI400                                                             52
+
+  * APB0 gates ("allwinner,sun4i-apb0-gates-clk")
+
+    CODEC                                                               0
+    SPDIF                                                               1*
+    AC97                                                                2
+    IIS                                                                 3
+
+    PIO                                                                 5
+    IR0                                                                 6
+    IR1                                                                 7
+
+    KEYPAD                                                              10
+
+  * APB1 gates ("allwinner,sun4i-apb1-gates-clk")
+
+    I2C0                                                                0
+    I2C1                                                                1
+    I2C2                                                                2
+
+    CAN                                                                 4
+    SCR                                                                 5
+    PS20                                                                6
+    PS21                                                                7
+
+    UART0                                                               16
+    UART1                                                               17
+    UART2                                                               18
+    UART3                                                               19
+    UART4                                                               20
+    UART5                                                               21
+    UART6                                                               22
+    UART7                                                               23
+
+Notation:
+ [*]:  The datasheet didn't mention these, but they are present on AW code
+ [**]: The datasheet had this marked as "NC" but they are used on AW code
diff --git a/Documentation/devicetree/bindings/cpufreq/arm_big_little_dt.txt b/Documentation/devicetree/bindings/cpufreq/arm_big_little_dt.txt
new file mode 100644
index 0000000..0715695
--- /dev/null
+++ b/Documentation/devicetree/bindings/cpufreq/arm_big_little_dt.txt
@@ -0,0 +1,65 @@
+Generic ARM big LITTLE cpufreq driver's DT glue
+-----------------------------------------------
+
+This is DT specific glue layer for generic cpufreq driver for big LITTLE
+systems.
+
+Both required and optional properties listed below must be defined
+under node /cpus/cpu@x. Where x is the first cpu inside a cluster.
+
+FIXME: Cpus should boot in the order specified in DT and all cpus for a cluster
+must be present contiguously. Generic DT driver will check only node 'x' for
+cpu:x.
+
+Required properties:
+- operating-points: Refer to Documentation/devicetree/bindings/power/opp.txt
+  for details
+
+Optional properties:
+- clock-latency: Specify the possible maximum transition latency for clock,
+  in unit of nanoseconds.
+
+Examples:
+
+cpus {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	cpu@0 {
+		compatible = "arm,cortex-a15";
+		reg = <0>;
+		next-level-cache = <&L2>;
+		operating-points = <
+			/* kHz    uV */
+			792000  1100000
+			396000  950000
+			198000  850000
+		>;
+		clock-latency = <61036>; /* two CLK32 periods */
+	};
+
+	cpu@1 {
+		compatible = "arm,cortex-a15";
+		reg = <1>;
+		next-level-cache = <&L2>;
+	};
+
+	cpu@100 {
+		compatible = "arm,cortex-a7";
+		reg = <100>;
+		next-level-cache = <&L2>;
+		operating-points = <
+			/* kHz    uV */
+			792000  950000
+			396000  750000
+			198000  450000
+		>;
+		clock-latency = <61036>; /* two CLK32 periods */
+	};
+
+	cpu@101 {
+		compatible = "arm,cortex-a7";
+		reg = <101>;
+		next-level-cache = <&L2>;
+	};
+};
diff --git a/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt b/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt
index 4416ccc..051f764 100644
--- a/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt
+++ b/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt
@@ -32,7 +32,7 @@ cpus {
 			396000  950000
 			198000  850000
 		>;
-		transition-latency = <61036>; /* two CLK32 periods */
+		clock-latency = <61036>; /* two CLK32 periods */
 	};
 
 	cpu@1 {
diff --git a/Documentation/devicetree/bindings/crypto/fsl-imx-sahara.txt b/Documentation/devicetree/bindings/crypto/fsl-imx-sahara.txt
new file mode 100644
index 0000000..5c65ecc
--- /dev/null
+++ b/Documentation/devicetree/bindings/crypto/fsl-imx-sahara.txt
@@ -0,0 +1,15 @@
+Freescale SAHARA Cryptographic Accelerator included in some i.MX chips.
+Currently only i.MX27 is supported.
+
+Required properties:
+- compatible : Should be "fsl,<soc>-sahara"
+- reg : Should contain SAHARA registers location and length
+- interrupts : Should contain SAHARA interrupt number
+
+Example:
+
+sah@10025000 {
+	compatible = "fsl,imx27-sahara";
+	reg = <	0x10025000 0x800>;
+	interrupts = <75>;
+};
diff --git a/Documentation/devicetree/bindings/dma/fsl-mxs-dma.txt b/Documentation/devicetree/bindings/dma/fsl-mxs-dma.txt
index ded0398..a4873e5 100644
--- a/Documentation/devicetree/bindings/dma/fsl-mxs-dma.txt
+++ b/Documentation/devicetree/bindings/dma/fsl-mxs-dma.txt
@@ -3,17 +3,58 @@
 Required properties:
 - compatible : Should be "fsl,<chip>-dma-apbh" or "fsl,<chip>-dma-apbx"
 - reg : Should contain registers location and length
+- interrupts : Should contain the interrupt numbers of DMA channels.
+  If a channel is empty/reserved, 0 should be filled in place.
+- #dma-cells : Must be <1>.  The number cell specifies the channel ID.
+- dma-channels : Number of channels supported by the DMA controller
+
+Optional properties:
+- interrupt-names : Name of DMA channel interrupts
 
 Supported chips:
 imx23, imx28.
 
 Examples:
-dma-apbh@80004000 {
+
+dma_apbh: dma-apbh@80004000 {
 	compatible = "fsl,imx28-dma-apbh";
-	reg = <0x80004000 2000>;
+	reg = <0x80004000 0x2000>;
+	interrupts = <82 83 84 85
+		      88 88 88 88
+		      88 88 88 88
+		      87 86 0 0>;
+	interrupt-names = "ssp0", "ssp1", "ssp2", "ssp3",
+			  "gpmi0", "gmpi1", "gpmi2", "gmpi3",
+			  "gpmi4", "gmpi5", "gpmi6", "gmpi7",
+			  "hsadc", "lcdif", "empty", "empty";
+	#dma-cells = <1>;
+	dma-channels = <16>;
 };
 
-dma-apbx@80024000 {
+dma_apbx: dma-apbx@80024000 {
 	compatible = "fsl,imx28-dma-apbx";
-	reg = <0x80024000 2000>;
+	reg = <0x80024000 0x2000>;
+	interrupts = <78 79 66 0
+		      80 81 68 69
+		      70 71 72 73
+		      74 75 76 77>;
+	interrupt-names = "auart4-rx", "aurat4-tx", "spdif-tx", "empty",
+			  "saif0", "saif1", "i2c0", "i2c1",
+			  "auart0-rx", "auart0-tx", "auart1-rx", "auart1-tx",
+			  "auart2-rx", "auart2-tx", "auart3-rx", "auart3-tx";
+	#dma-cells = <1>;
+	dma-channels = <16>;
+};
+
+DMA clients connected to the MXS DMA controller must use the format
+described in the dma.txt file.
+
+Examples:
+
+auart0: serial@8006a000 {
+	compatible = "fsl,imx28-auart", "fsl,imx23-auart";
+	reg = <0x8006a000 0x2000>;
+	interrupts = <112>;
+	dmas = <&dma_apbx 8>, <&dma_apbx 9>;
+	dma-names = "rx", "tx";
 };
diff --git a/Documentation/devicetree/bindings/fb/mxsfb.txt b/Documentation/devicetree/bindings/fb/mxsfb.txt
index b41e5e52..7ba3b76 100644
--- a/Documentation/devicetree/bindings/fb/mxsfb.txt
+++ b/Documentation/devicetree/bindings/fb/mxsfb.txt
@@ -5,10 +5,20 @@ Required properties:
   imx23 and imx28.
 - reg: Address and length of the register set for lcdif
 - interrupts: Should contain lcdif interrupts
+- display : phandle to display node (see below for details)
 
 Optional properties:
 - panel-enable-gpios : Should specify the gpio for panel enable
 
+* display node
+
+Required properties:
+- bits-per-pixel : <16> for RGB565, <32> for RGB888/666.
+- bus-width : number of data lines.  Could be <8>, <16>, <18> or <24>.
+
+Required sub-node:
+- display-timings : Refer to binding doc display-timing.txt for details.
+
 Examples:
 
 lcdif@80030000 {
@@ -16,4 +26,28 @@ lcdif@80030000 {
 	reg = <0x80030000 2000>;
 	interrupts = <38 86>;
 	panel-enable-gpios = <&gpio3 30 0>;
+
+	display: display {
+		bits-per-pixel = <32>;
+		bus-width = <24>;
+
+		display-timings {
+			native-mode = <&timing0>;
+			timing0: timing0 {
+				clock-frequency = <33500000>;
+				hactive = <800>;
+				vactive = <480>;
+				hfront-porch = <164>;
+				hback-porch = <89>;
+				hsync-len = <10>;
+				vback-porch = <23>;
+				vfront-porch = <10>;
+				vsync-len = <10>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+		};
+	};
 };
diff --git a/Documentation/devicetree/bindings/gpio/gpio.txt b/Documentation/devicetree/bindings/gpio/gpio.txt
index a336287..d933af3 100644
--- a/Documentation/devicetree/bindings/gpio/gpio.txt
+++ b/Documentation/devicetree/bindings/gpio/gpio.txt
@@ -98,7 +98,7 @@ announce the pinrange to the pin ctrl subsystem. For example,
 		compatible = "fsl,qe-pario-bank-e", "fsl,qe-pario-bank";
 		reg = <0x1460 0x18>;
 		gpio-controller;
-		gpio-ranges = <&pinctrl1 20 10>, <&pinctrl2 50 20>;
+		gpio-ranges = <&pinctrl1 0 20 10>, <&pinctrl2 10 50 20>;
 
     }
 
@@ -107,8 +107,8 @@ where,
 
    Next values specify the base pin and number of pins for the range
    handled by 'qe_pio_e' gpio. In the given example from base pin 20 to
-   pin 29 under pinctrl1 and pin 50 to pin 69 under pinctrl2 is handled
-   by this gpio controller.
+   pin 29 under pinctrl1 with gpio offset 0 and pin 50 to pin 69 under
+   pinctrl2 with gpio offset 10 is handled by this gpio controller.
 
 The pinctrl node must have "#gpio-range-cells" property to show number of
 arguments to pass with phandle from gpio controllers node.
diff --git a/Documentation/devicetree/bindings/gpu/samsung-g2d.txt b/Documentation/devicetree/bindings/gpu/samsung-g2d.txt
new file mode 100644
index 0000000..2b14a94
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpu/samsung-g2d.txt
@@ -0,0 +1,20 @@
+* Samsung 2D Graphics Accelerator
+
+Required properties:
+  - compatible : value should be one among the following:
+	(a) "samsung,s5pv210-g2d" for G2D IP present in S5PV210 & Exynos4210 SoC
+	(b) "samsung,exynos4212-g2d" for G2D IP present in Exynos4x12 SoCs
+	(c) "samsung,exynos5250-g2d" for G2D IP present in Exynos5250 SoC
+
+  - reg : Physical base address of the IP registers and length of memory
+	  mapped region.
+
+  - interrupts : G2D interrupt number to the CPU.
+
+Example:
+	g2d@12800000 {
+		compatible = "samsung,s5pv210-g2d";
+		reg = <0x12800000 0x1000>;
+		interrupts = <0 89 0>;
+		status = "disabled";
+	};
diff --git a/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt b/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt
new file mode 100644
index 0000000..c6f6667
--- /dev/null
+++ b/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt
@@ -0,0 +1,29 @@
+NTC Thermistor hwmon sensors
+-------------------------------
+
+Requires node properties:
+- "compatible" value : one of
+	"ntc,ncp15wb473"
+	"ntc,ncp18wb473"
+	"ntc,ncp21wb473"
+	"ntc,ncp03wb473"
+	"ntc,ncp15wl333"
+- "pullup-uv"	Pull up voltage in micro volts
+- "pullup-ohm"	Pull up resistor value in ohms
+- "pulldown-ohm" Pull down resistor value in ohms
+- "connected-positive" Always ON, If not specified.
+		Status change is possible.
+- "io-channels"	Channel node of ADC to be used for
+		conversion.
+
+Read more about iio bindings at
+	Documentation/devicetree/bindings/iio/iio-bindings.txt
+
+Example:
+	ncp15wb473@0 {
+		compatible = "ntc,ncp15wb473";
+		pullup-uv = <1800000>;
+		pullup-ohm = <47000>;
+		pulldown-ohm = <0>;
+		io-channels = <&adc 3>;
+	};
diff --git a/Documentation/devicetree/bindings/hwrng/timeriomem_rng.txt b/Documentation/devicetree/bindings/hwrng/timeriomem_rng.txt
new file mode 100644
index 0000000..6616d15
--- /dev/null
+++ b/Documentation/devicetree/bindings/hwrng/timeriomem_rng.txt
@@ -0,0 +1,18 @@
+HWRNG support for the timeriomem_rng driver
+
+Required properties:
+- compatible : "timeriomem_rng"
+- reg : base address to sample from
+- period : wait time in microseconds to use between samples
+
+N.B. currently 'reg' must be four bytes wide and aligned
+
+Example:
+
+hwrng@44 {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	compatible = "timeriomem_rng";
+	reg = <0x44 0x04>;
+	period = <1000000>;
+};
diff --git a/Documentation/devicetree/bindings/i2c/i2c-mxs.txt b/Documentation/devicetree/bindings/i2c/i2c-mxs.txt
index 7a3fe9e..4e1c8ac 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-mxs.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-mxs.txt
@@ -3,10 +3,13 @@
 Required properties:
 - compatible: Should be "fsl,<chip>-i2c"
 - reg: Should contain registers location and length
-- interrupts: Should contain ERROR and DMA interrupts
+- interrupts: Should contain ERROR interrupt number
 - clock-frequency: Desired I2C bus clock frequency in Hz.
                    Only 100000Hz and 400000Hz modes are supported.
-- fsl,i2c-dma-channel: APBX DMA channel for the I2C
+- dmas: DMA specifier, consisting of a phandle to DMA controller node
+  and I2C DMA channel ID.
+  Refer to dma.txt and fsl-mxs-dma.txt for details.
+- dma-names: Must be "rx-tx".
 
 Examples:
 
@@ -15,7 +18,8 @@ i2c0: i2c@80058000 {
 	#size-cells = <0>;
 	compatible = "fsl,imx28-i2c";
 	reg = <0x80058000 2000>;
-	interrupts = <111 68>;
+	interrupts = <111>;
 	clock-frequency = <100000>;
-	fsl,i2c-dma-channel = <6>;
+	dmas = <&dma_apbx 6>;
+	dma-names = "rx-tx";
 };
diff --git a/Documentation/devicetree/bindings/i2c/nvidia,tegra20-i2c.txt b/Documentation/devicetree/bindings/i2c/nvidia,tegra20-i2c.txt
new file mode 100644
index 0000000..ef77cc7
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/nvidia,tegra20-i2c.txt
@@ -0,0 +1,60 @@
+NVIDIA Tegra20/Tegra30/Tegra114 I2C controller driver.
+
+Required properties:
+- compatible : should be:
+	"nvidia,tegra114-i2c"
+	"nvidia,tegra30-i2c"
+	"nvidia,tegra20-i2c"
+	"nvidia,tegra20-i2c-dvc"
+  Details of compatible are as follows:
+  nvidia,tegra20-i2c-dvc: Tegra20 has specific I2C controller called as DVC I2C
+	controller. This only support master mode of I2C communication. Register
+	interface/offset and interrupts handling are different than generic I2C
+	controller. Driver of DVC I2C controller is only compatible with
+	"nvidia,tegra20-i2c-dvc".
+  nvidia,tegra20-i2c: Tegra20 has 4 generic I2C controller. This can support
+	master and slave mode of I2C communication. The i2c-tegra driver only
+	support master mode of I2C communication. Driver of I2C controller is
+	only compatible with "nvidia,tegra20-i2c".
+  nvidia,tegra30-i2c: Tegra30 has 5 generic I2C controller. This controller is
+	very much similar to Tegra20 I2C controller with additional feature:
+	Continue Transfer Support. This feature helps to implement M_NO_START
+	as per I2C core API transfer flags. Driver of I2C controller is
+	compatible with "nvidia,tegra30-i2c" to enable the continue transfer
+	support. This is also compatible with "nvidia,tegra20-i2c" without
+	continue transfer support.
+  nvidia,tegra114-i2c: Tegra114 has 5 generic I2C controller. This controller is
+	very much similar to Tegra30 I2C controller with some hardware
+	modification:
+	 - Tegra30/Tegra20 I2C controller has 2 clock source called div-clk and
+	   fast-clk. Tegra114 has only one clock source called as div-clk and
+	   hence clock mechanism is changed in I2C controller.
+	 - Tegra30/Tegra20 I2C controller has enabled per packet transfer by
+	   default and there is no way to disable it. Tegra114 has this
+	   interrupt disable by default and SW need to enable explicitly.
+	Due to above changes, Tegra114 I2C driver makes incompatible with
+	previous hardware driver. Hence, tegra114 I2C controller is compatible
+	with "nvidia,tegra114-i2c".
+- reg: Should contain I2C controller registers physical address and length.
+- interrupts: Should contain I2C controller interrupts.
+- address-cells: Address cells for I2C device address.
+- size-cells: Size of the I2C device address.
+- clocks: Clock ID as per
+		Documentation/devicetree/bindings/clock/tegra<chip-id>.txt
+	for I2C controller.
+- clock-names: Name of the clock:
+	Tegra20/Tegra30 I2C controller: "div-clk and "fast-clk".
+	Tegra114 I2C controller: "div-clk".
+
+Example:
+
+	i2c@7000c000 {
+		compatible = "nvidia,tegra20-i2c";
+		reg = <0x7000c000 0x100>;
+		interrupts = <0 38 0x04>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&tegra_car 12>, <&tegra_car 124>;
+		clock-names = "div-clk", "fast-clk";
+		status = "disabled";
+	};
diff --git a/Documentation/devicetree/bindings/iio/iio-bindings.txt b/Documentation/devicetree/bindings/iio/iio-bindings.txt
new file mode 100644
index 0000000..0b447d9
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/iio-bindings.txt
@@ -0,0 +1,97 @@
+This binding is derived from clock bindings, and based on suggestions
+from Lars-Peter Clausen [1].
+
+Sources of IIO channels can be represented by any node in the device
+tree. Those nodes are designated as IIO providers. IIO consumer
+nodes use a phandle and IIO specifier pair to connect IIO provider
+outputs to IIO inputs. Similar to the gpio specifiers, an IIO
+specifier is an array of one or more cells identifying the IIO
+output on a device. The length of an IIO specifier is defined by the
+value of a #io-channel-cells property in the IIO provider node.
+
+[1] http://marc.info/?l=linux-iio&m=135902119507483&w=2
+
+==IIO providers==
+
+Required properties:
+#io-channel-cells: Number of cells in an IIO specifier; Typically 0 for nodes
+		   with a single IIO output and 1 for nodes with multiple
+		   IIO outputs.
+
+Example for a simple configuration with no trigger:
+
+	adc: voltage-sensor@35 {
+		compatible = "maxim,max1139";
+		reg = <0x35>;
+		#io-channel-cells = <1>;
+	};
+
+Example for a configuration with trigger:
+
+	adc@35 {
+		compatible = "some-vendor,some-adc";
+		reg = <0x35>;
+
+		adc1: iio-device@0 {
+			#io-channel-cells = <1>;
+			/* other properties */
+		};
+		adc2: iio-device@1 {
+			#io-channel-cells = <1>;
+			/* other properties */
+		};
+	};
+
+==IIO consumers==
+
+Required properties:
+io-channels:	List of phandle and IIO specifier pairs, one pair
+		for each IIO input to the device. Note: if the
+		IIO provider specifies '0' for #io-channel-cells,
+		then only the phandle portion of the pair will appear.
+
+Optional properties:
+io-channel-names:
+		List of IIO input name strings sorted in the same
+		order as the io-channels property. Consumers drivers
+		will use io-channel-names to match IIO input names
+		with IIO specifiers.
+io-channel-ranges:
+		Empty property indicating that child nodes can inherit named
+		IIO channels from this node. Useful for bus nodes to provide
+		and IIO channel to their children.
+
+For example:
+
+	device {
+		io-channels = <&adc 1>, <&ref 0>;
+		io-channel-names = "vcc", "vdd";
+	};
+
+This represents a device with two IIO inputs, named "vcc" and "vdd".
+The vcc channel is connected to output 1 of the &adc device, and the
+vdd channel is connected to output 0 of the &ref device.
+
+==Example==
+
+	adc: max1139@35 {
+		compatible = "maxim,max1139";
+		reg = <0x35>;
+		#io-channel-cells = <1>;
+	};
+
+	...
+
+	iio_hwmon {
+		compatible = "iio-hwmon";
+		io-channels = <&adc 0>, <&adc 1>, <&adc 2>,
+			<&adc 3>, <&adc 4>, <&adc 5>,
+			<&adc 6>, <&adc 7>, <&adc 8>,
+			<&adc 9>;
+	};
+
+	some_consumer {
+		compatible = "some-consumer";
+		io-channels = <&adc 10>, <&adc 11>;
+		io-channel-names = "adc1", "adc2";
+	};
diff --git a/Documentation/devicetree/bindings/input/cros-ec-keyb.txt b/Documentation/devicetree/bindings/input/cros-ec-keyb.txt
new file mode 100644
index 0000000..0f6355c
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/cros-ec-keyb.txt
@@ -0,0 +1,72 @@
+ChromeOS EC Keyboard
+
+Google's ChromeOS EC Keyboard is a simple matrix keyboard implemented on
+a separate EC (Embedded Controller) device. It provides a message for reading
+key scans from the EC. These are then converted into keycodes for processing
+by the kernel.
+
+This binding is based on matrix-keymap.txt and extends/modifies it as follows:
+
+Required properties:
+- compatible: "google,cros-ec-keyb"
+
+Optional properties:
+- google,needs-ghost-filter: True to enable a ghost filter for the matrix
+keyboard. This is recommended if the EC does not have its own logic or
+hardware for this.
+
+
+Example:
+
+cros-ec-keyb {
+	compatible = "google,cros-ec-keyb";
+	keypad,num-rows = <8>;
+	keypad,num-columns = <13>;
+	google,needs-ghost-filter;
+	/*
+	 * Keymap entries take the form of 0xRRCCKKKK where
+	 * RR=Row CC=Column KKKK=Key Code
+	 * The values below are for a US keyboard layout and
+	 * are taken from the Linux driver. Note that the
+	 * 102ND key is not used for US keyboards.
+	 */
+	linux,keymap = <
+		/* CAPSLCK F1         B          F10     */
+		0x0001003a 0x0002003b 0x00030030 0x00040044
+		/* N       =          R_ALT      ESC     */
+		0x00060031 0x0008000d 0x000a0064 0x01010001
+		/* F4      G          F7         H       */
+		0x0102003e 0x01030022 0x01040041 0x01060023
+		/* '       F9         BKSPACE    L_CTRL  */
+		0x01080028 0x01090043 0x010b000e 0x0200001d
+		/* TAB     F3         T          F6      */
+		0x0201000f 0x0202003d 0x02030014 0x02040040
+		/* ]       Y          102ND      [       */
+		0x0205001b 0x02060015 0x02070056 0x0208001a
+		/* F8      GRAVE      F2         5       */
+		0x02090042 0x03010029 0x0302003c 0x03030006
+		/* F5      6          -          \       */
+		0x0304003f 0x03060007 0x0308000c 0x030b002b
+		/* R_CTRL  A          D          F       */
+		0x04000061 0x0401001e 0x04020020 0x04030021
+		/* S       K          J          ;       */
+		0x0404001f 0x04050025 0x04060024 0x04080027
+		/* L       ENTER      Z          C       */
+		0x04090026 0x040b001c 0x0501002c 0x0502002e
+		/* V       X          ,          M       */
+		0x0503002f 0x0504002d 0x05050033 0x05060032
+		/* L_SHIFT /          .          SPACE   */
+		0x0507002a 0x05080035 0x05090034 0x050B0039
+		/* 1       3          4          2       */
+		0x06010002 0x06020004 0x06030005 0x06040003
+		/* 8       7          0          9       */
+		0x06050009 0x06060008 0x0608000b 0x0609000a
+		/* L_ALT   DOWN       RIGHT      Q       */
+		0x060a0038 0x060b006c 0x060c006a 0x07010010
+		/* E       R          W          I       */
+		0x07020012 0x07030013 0x07040011 0x07050017
+		/* U       R_SHIFT    P          O       */
+		0x07060016 0x07070036 0x07080019 0x07090018
+		/* UP      LEFT    */
+		0x070b0067 0x070c0069>;
+};
diff --git a/Documentation/devicetree/bindings/input/ps2keyb-mouse-apbps2.txt b/Documentation/devicetree/bindings/input/ps2keyb-mouse-apbps2.txt
new file mode 100644
index 0000000..3029c56
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/ps2keyb-mouse-apbps2.txt
@@ -0,0 +1,16 @@
+Aeroflex Gaisler APBPS2 PS/2 Core, supporting Keyboard or Mouse.
+
+The APBPS2 PS/2 core is available in the GRLIB VHDL IP core library.
+
+Note: In the ordinary environment for the APBPS2 core, a LEON SPARC system,
+these properties are built from information in the AMBA plug&play and from
+bootloader settings.
+
+Required properties:
+
+- name : Should be "GAISLER_APBPS2" or "01_060"
+- reg : Address and length of the register set for the device
+- interrupts : Interrupt numbers for this device
+
+For further information look in the documentation for the GLIB IP core library:
+http://www.gaisler.com/products/grlib/grip.pdf
diff --git a/Documentation/devicetree/bindings/input/touchscreen/auo_pixcir_ts.txt b/Documentation/devicetree/bindings/input/touchscreen/auo_pixcir_ts.txt
new file mode 100644
index 0000000..f40f21c
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/auo_pixcir_ts.txt
@@ -0,0 +1,30 @@
+* AUO in-cell touchscreen controller using Pixcir sensors
+
+Required properties:
+- compatible: must be "auo,auo_pixcir_ts"
+- reg: I2C address of the chip
+- interrupts: interrupt to which the chip is connected
+- gpios: gpios the chip is connected to
+  first one is the interrupt gpio and second one the reset gpio
+- x-size: horizontal resolution of touchscreen
+- y-size: vertical resolution of touchscreen
+
+Example:
+
+	i2c@00000000 {
+		/* ... */
+
+		auo_pixcir_ts@5c {
+			compatible = "auo,auo_pixcir_ts";
+			reg = <0x5c>;
+			interrupts = <2 0>;
+
+			gpios = <&gpf 2 0 2>, /* INT */
+				<&gpf 5 1 0>; /* RST */
+
+			x-size = <800>;
+			y-size = <600>;
+		};
+
+		/* ... */
+	};
diff --git a/Documentation/devicetree/bindings/interrupt-controller/samsung,s3c24xx-irq.txt b/Documentation/devicetree/bindings/interrupt-controller/samsung,s3c24xx-irq.txt
new file mode 100644
index 0000000..c54c5a9
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/samsung,s3c24xx-irq.txt
@@ -0,0 +1,53 @@
+Samsung S3C24XX Interrupt Controllers
+
+The S3C24XX SoCs contain a custom set of interrupt controllers providing a
+varying number of interrupt sources. The set consists of a main- and sub-
+controller and on newer SoCs even a second main controller.
+
+Required properties:
+- compatible: Compatible property value should be "samsung,s3c2410-irq"
+  for machines before s3c2416 and "samsung,s3c2416-irq" for s3c2416 and later.
+
+- reg: Physical base address of the controller and length of memory mapped
+  region.
+
+- interrupt-controller : Identifies the node as an interrupt controller
+
+- #interrupt-cells : Specifies the number of cells needed to encode an
+  interrupt source. The value shall be 4 and interrupt descriptor shall
+  have the following format:
+      <ctrl_num parent_irq ctrl_irq type>
+
+  ctrl_num contains the controller to use:
+      - 0 ... main controller
+      - 1 ... sub controller
+      - 2 ... second main controller on s3c2416 and s3c2450
+  parent_irq contains the parent bit in the main controller and will be
+             ignored in main controllers
+  ctrl_irq contains the interrupt bit of the controller
+  type contains the trigger type to use
+
+Example:
+
+	interrupt-controller@4a000000 {
+		compatible = "samsung,s3c2410-irq";
+		reg = <0x4a000000 0x100>;
+		interrupt-controller;
+		#interrupt-cells=<4>;
+	};
+
+	[...]
+
+	serial@50000000 {
+		compatible = "samsung,s3c2410-uart";
+		reg = <0x50000000 0x4000>;
+		interrupt-parent = <&subintc>;
+		interrupts = <1 28 0 4>, <1 28 1 4>;
+	};
+
+	rtc@57000000 {
+		compatible = "samsung,s3c2410-rtc";
+		reg = <0x57000000 0x100>;
+		interrupt-parent = <&intc>;
+		interrupts = <0 30 0 3>, <0 8 0 3>;
+	};
diff --git a/Documentation/devicetree/bindings/mailbox/dbx500-mailbox.txt b/Documentation/devicetree/bindings/mailbox/dbx500-mailbox.txt
new file mode 100644
index 0000000..df0f594
--- /dev/null
+++ b/Documentation/devicetree/bindings/mailbox/dbx500-mailbox.txt
@@ -0,0 +1,27 @@
+ST-Ericsson DBx500 PRCM Mailbox Driver
+
+Required properties:
+- compatible		: Should be
+			  "stericsson,db8500-mailbox" for db8500 and db9500
+			  "stericsson,db9540-mailbox" for db9540
+- reg			: Physical base address and length of mailbox's
+			  registers and shared memory
+- reg-names		: Should contain the reg names "prcm-reg" and
+			  "prcmu-tcdm"
+- interrupts		: contains the IRQ line for the PRCM mailbox
+- interrupt-names	: Should contain the interrupt name "irq"
+- legacy-offset		: Memory offset in shared mem for legacy mailboxes
+
+Optional properties:
+- upap-offset		: Memory offset in shared mem for upap mailboxes
+
+Examples:
+
+mailbox {
+	compatible = "stericsson,db8500-mailbox";
+	reg = <0x80157000 0x1000>, <0x801B8000 0x2000>;
+	reg-names = "prcm-reg", "prcmu-tcdm";
+	interrupts = <0 47 0x4>;
+	interrupt-names = "irq";
+	legacy-offset = <0xdd4>;
+};
diff --git a/Documentation/devicetree/bindings/media/s5p-mfc.txt b/Documentation/devicetree/bindings/media/s5p-mfc.txt
index 67ec3d4..bf0182d 100644
--- a/Documentation/devicetree/bindings/media/s5p-mfc.txt
+++ b/Documentation/devicetree/bindings/media/s5p-mfc.txt
@@ -21,3 +21,24 @@ Required properties:
 
   - samsung,mfc-l : Base address of the second memory bank used by MFC
 		    for DMA contiguous memory allocation and its size.
+
+Optional properties:
+  - samsung,power-domain : power-domain property defined with a phandle
+			   to respective power domain.
+
+Example:
+SoC specific DT entry:
+
+mfc: codec@13400000 {
+	compatible = "samsung,mfc-v5";
+	reg = <0x13400000 0x10000>;
+	interrupts = <0 94 0>;
+	samsung,power-domain = <&pd_mfc>;
+};
+
+Board specific DT entry:
+
+codec@13400000 {
+	samsung,mfc-r = <0x43000000 0x800000>;
+	samsung,mfc-l = <0x51000000 0x800000>;
+};
diff --git a/Documentation/devicetree/bindings/mfd/as3711.txt b/Documentation/devicetree/bindings/mfd/as3711.txt
new file mode 100644
index 0000000..d98cf18
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/as3711.txt
@@ -0,0 +1,73 @@
+AS3711 is an I2C PMIC from Austria MicroSystems with multiple DCDC and LDO power
+supplies, a battery charger and an RTC. So far only bindings for the two stepup
+DCDC converters are defined. Other DCDC and LDO supplies are configured, using
+standard regulator properties, they must belong to a sub-node, called
+"regulators" and be called "sd1" to "sd4" and "ldo1" to "ldo8." Stepup converter
+configuration should be placed in a subnode, called "backlight."
+
+Compulsory properties:
+- compatible		: must be "ams,as3711"
+- reg			: specifies the I2C address
+
+To use the SU1 converter as a backlight source the following two properties must
+be provided:
+- su1-dev		: framebuffer phandle
+- su1-max-uA		: maximum current
+
+To use the SU2 converter as a backlight source the following two properties must
+be provided:
+- su2-dev		: framebuffer phandle
+- su1-max-uA		: maximum current
+
+Additionally one of these properties must be provided to select the type of
+feedback used:
+- su2-feedback-voltage	: voltage feedback is used
+- su2-feedback-curr1	: CURR1 input used for current feedback
+- su2-feedback-curr2	: CURR2 input used for current feedback
+- su2-feedback-curr3	: CURR3 input used for current feedback
+- su2-feedback-curr-auto: automatic current feedback selection
+
+and one of these to select the over-voltage protection pin
+- su2-fbprot-lx-sd4	: LX_SD4 is used for over-voltage protection
+- su2-fbprot-gpio2	: GPIO2 is used for over-voltage protection
+- su2-fbprot-gpio3	: GPIO3 is used for over-voltage protection
+- su2-fbprot-gpio4	: GPIO4 is used for over-voltage protection
+
+If "su2-feedback-curr-auto" is selected, one or more of the following properties
+have to be specified:
+- su2-auto-curr1	: use CURR1 input for current feedback
+- su2-auto-curr2	: use CURR2 input for current feedback
+- su2-auto-curr3	: use CURR3 input for current feedback
+
+Example:
+
+as3711@40 {
+	compatible = "ams,as3711";
+	reg = <0x40>;
+
+	regulators {
+		sd4 {
+			regulator-name = "1.215V";
+			regulator-min-microvolt = <1215000>;
+			regulator-max-microvolt = <1235000>;
+		};
+		ldo2 {
+			regulator-name = "2.8V CPU";
+			regulator-min-microvolt = <2800000>;
+			regulator-max-microvolt = <2800000>;
+			regulator-always-on;
+			regulator-boot-on;
+		};
+	};
+
+	backlight {
+		compatible = "ams,as3711-bl";
+		su2-dev = <&lcdc>;
+		su2-max-uA = <36000>;
+		su2-feedback-curr-auto;
+		su2-fbprot-gpio4;
+		su2-auto-curr1;
+		su2-auto-curr2;
+		su2-auto-curr3;
+	};
+};
diff --git a/Documentation/devicetree/bindings/mfd/cros-ec.txt b/Documentation/devicetree/bindings/mfd/cros-ec.txt
new file mode 100644
index 0000000..e0e59c5
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/cros-ec.txt
@@ -0,0 +1,56 @@
+ChromeOS Embedded Controller
+
+Google's ChromeOS EC is a Cortex-M device which talks to the AP and
+implements various function such as keyboard and battery charging.
+
+The EC can be connect through various means (I2C, SPI, LPC) and the
+compatible string used depends on the inteface. Each connection method has
+its own driver which connects to the top level interface-agnostic EC driver.
+Other Linux driver (such as cros-ec-keyb for the matrix keyboard) connect to
+the top-level driver.
+
+Required properties (I2C):
+- compatible: "google,cros-ec-i2c"
+- reg: I2C slave address
+
+Required properties (SPI):
+- compatible: "google,cros-ec-spi"
+- reg: SPI chip select
+
+Required properties (LPC):
+- compatible: "google,cros-ec-lpc"
+- reg: List of (IO address, size) pairs defining the interface uses
+
+
+Example for I2C:
+
+i2c@12CA0000 {
+	cros-ec@1e {
+		reg = <0x1e>;
+		compatible = "google,cros-ec-i2c";
+		interrupts = <14 0>;
+		interrupt-parent = <&wakeup_eint>;
+		wakeup-source;
+	};
+
+
+Example for SPI:
+
+spi@131b0000 {
+	ec@0 {
+		compatible = "google,cros-ec-spi";
+		reg = <0x0>;
+		interrupts = <14 0>;
+		interrupt-parent = <&wakeup_eint>;
+		wakeup-source;
+		spi-max-frequency = <5000000>;
+		controller-data {
+		cs-gpio = <&gpf0 3 4 3 0>;
+		samsung,spi-cs;
+		samsung,spi-feedback-delay = <2>;
+		};
+	};
+};
+
+
+Example for LPC is not supplied as it is not yet implemented.
diff --git a/Documentation/devicetree/bindings/mmc/mxs-mmc.txt b/Documentation/devicetree/bindings/mmc/mxs-mmc.txt
index 54949f6..515addc 100644
--- a/Documentation/devicetree/bindings/mmc/mxs-mmc.txt
+++ b/Documentation/devicetree/bindings/mmc/mxs-mmc.txt
@@ -9,15 +9,19 @@ and the properties used by the mxsmmc driver.
 Required properties:
 - compatible: Should be "fsl,<chip>-mmc".  The supported chips include
   imx23 and imx28.
-- interrupts: Should contain ERROR and DMA interrupts
-- fsl,ssp-dma-channel: APBH DMA channel for the SSP
+- interrupts: Should contain ERROR interrupt number
+- dmas: DMA specifier, consisting of a phandle to DMA controller node
+  and SSP DMA channel ID.
+  Refer to dma.txt and fsl-mxs-dma.txt for details.
+- dma-names: Must be "rx-tx".
 
 Examples:
 
 ssp0: ssp@80010000 {
 	compatible = "fsl,imx28-mmc";
 	reg = <0x80010000 2000>;
-	interrupts = <96 82>;
-	fsl,ssp-dma-channel = <0>;
+	interrupts = <96>;
+	dmas = <&dma_apbh 0>;
+	dma-names = "rx-tx";
 	bus-width = <8>;
 };
diff --git a/Documentation/devicetree/bindings/mmc/samsung-sdhci.txt b/Documentation/devicetree/bindings/mmc/samsung-sdhci.txt
index 3b3a1ee..328e990 100644
--- a/Documentation/devicetree/bindings/mmc/samsung-sdhci.txt
+++ b/Documentation/devicetree/bindings/mmc/samsung-sdhci.txt
@@ -5,13 +5,6 @@ MMC, SD and eMMC storage mediums. This file documents differences between the
 core mmc properties described by mmc.txt and the properties used by the
 Samsung implmentation of the SDHCI controller.
 
-Note: The mmc core bindings documentation states that if none of the core
-card-detect bindings are used, then the standard sdhci card detect mechanism
-is used. The Samsung's SDHCI controller bindings extends this as listed below.
-
-[A] The property "samsung,cd-pinmux-gpio" can be used as stated in the
-    "Optional Board Specific Properties" section below.
-
 Required SoC Specific Properties:
 - compatible: should be one of the following
   - "samsung,s3c6410-sdhci": For controllers compatible with s3c6410 sdhci
@@ -20,18 +13,8 @@ Required SoC Specific Properties:
     controller.
 
 Required Board Specific Properties:
-- Samsung GPIO variant (will be completely replaced by pinctrl):
-  - gpios: Should specify the gpios used for clock, command and data lines. The
-    gpio specifier format depends on the gpio controller.
-- Pinctrl variant (preferred if available):
-  - pinctrl-0: Should specify pin control groups used for this controller.
-  - pinctrl-names: Should contain only one value - "default".
-
-Optional Board Specific Properties:
-- samsung,cd-pinmux-gpio: Specifies the card detect line that is routed
-  through a pinmux to the card-detect pin of the card slot. This property
-  should be used only if none of the mmc core card-detect properties are
-  used. Only for Samsung GPIO variant.
+- pinctrl-0: Should specify pin control groups used for this controller.
+- pinctrl-names: Should contain only one value - "default".
 
 Example:
 	sdhci@12530000 {
@@ -39,19 +22,9 @@ Example:
 		reg = <0x12530000 0x100>;
 		interrupts = <0 75 0>;
 		bus-width = <4>;
-		cd-gpios = <&gpk2 2 2 3 3>;
-
-		/* Samsung GPIO variant */
-		gpios = <&gpk2 0 2 0 3>,  /* clock line */
-			<&gpk2 1 2 0 3>,  /* command line */
-			<&gpk2 3 2 3 3>,  /* data line 0 */
-			<&gpk2 4 2 3 3>,  /* data line 1 */
-			<&gpk2 5 2 3 3>,  /* data line 2 */
-			<&gpk2 6 2 3 3>;  /* data line 3 */
-
-		/* Pinctrl variant */
-		pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4>;
+		cd-gpios = <&gpk2 2 0>;
 		pinctrl-names = "default";
+		pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4>;
 	};
 
 	Note: This example shows both SoC specific and board specific properties
diff --git a/Documentation/devicetree/bindings/mmc/sdhci-sirf.txt b/Documentation/devicetree/bindings/mmc/sdhci-sirf.txt
new file mode 100644
index 0000000..dd6ed46
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/sdhci-sirf.txt
@@ -0,0 +1,18 @@
+* SiRFprimII/marco/atlas6 SDHCI Controller
+
+This file documents differences between the core properties in mmc.txt
+and the properties used by the sdhci-sirf driver.
+
+Required properties:
+- compatible: sirf,prima2-sdhc
+
+Optional properties:
+- cd-gpios: card detect gpio, with zero flags.
+
+Example:
+
+	sd0: sdhci@56000000 {
+		compatible = "sirf,prima2-sdhc";
+		reg = <0xcd000000 0x100000>;
+		cd-gpios = <&gpio 6 0>;
+	};
diff --git a/Documentation/devicetree/bindings/mtd/gpmi-nand.txt b/Documentation/devicetree/bindings/mtd/gpmi-nand.txt
index 3fb3f901..551b2a1 100644
--- a/Documentation/devicetree/bindings/mtd/gpmi-nand.txt
+++ b/Documentation/devicetree/bindings/mtd/gpmi-nand.txt
@@ -7,10 +7,12 @@ Required properties:
   - compatible : should be "fsl,<chip>-gpmi-nand"
   - reg : should contain registers location and length for gpmi and bch.
   - reg-names: Should contain the reg names "gpmi-nand" and "bch"
-  - interrupts : The first is the DMA interrupt number for GPMI.
-                 The second is the BCH interrupt number.
-  - interrupt-names : The interrupt names "gpmi-dma", "bch";
-  - fsl,gpmi-dma-channel : Should contain the dma channel it uses.
+  - interrupts : BCH interrupt number.
+  - interrupt-names : Should be "bch".
+  - dmas: DMA specifier, consisting of a phandle to DMA controller node
+    and GPMI DMA channel ID.
+    Refer to dma.txt and fsl-mxs-dma.txt for details.
+  - dma-names: Must be "rx-tx".
 
 Optional properties:
   - nand-on-flash-bbt: boolean to enable on flash bbt option if not
@@ -27,9 +29,10 @@ gpmi-nand@8000c000 {
 	#size-cells = <1>;
 	reg = <0x8000c000 2000>, <0x8000a000 2000>;
 	reg-names = "gpmi-nand", "bch";
-	interrupts = <88>, <41>;
-	interrupt-names = "gpmi-dma", "bch";
-	fsl,gpmi-dma-channel = <4>;
+	interrupts = <41>;
+	interrupt-names = "bch";
+	dmas = <&dma_apbh 4>;
+	dma-names = "rx-tx";
 
 	partition@0 {
 	...
diff --git a/Documentation/devicetree/bindings/mtd/partition.txt b/Documentation/devicetree/bindings/mtd/partition.txt
index 6e1f61f..8f354bc 100644
--- a/Documentation/devicetree/bindings/mtd/partition.txt
+++ b/Documentation/devicetree/bindings/mtd/partition.txt
@@ -5,8 +5,12 @@ on platforms which have strong conventions about which portions of a flash are
 used for what purposes, but which don't use an on-flash partition table such
 as RedBoot.
 
-#address-cells & #size-cells must both be present in the mtd device and be
-equal to 1.
+#address-cells & #size-cells must both be present in the mtd device. There are
+two valid values for both:
+<1>: for partitions that require a single 32-bit cell to represent their
+     size/address (aka the value is below 4 GB)
+<2>: for partitions that require two 32-bit cells to represent their
+     size/address (aka the value is 4 GB or greater).
 
 Required properties:
 - reg : The partition's offset and size within the mtd bank.
@@ -36,3 +40,31 @@ flash@0 {
 		reg = <0x0100000 0x200000>;
 	};
 };
+
+flash@1 {
+	#address-cells = <1>;
+	#size-cells = <2>;
+
+	/* a 4 GB partition */
+	partition@0 {
+		label = "filesystem";
+		reg = <0x00000000 0x1 0x00000000>;
+	};
+};
+
+flash@2 {
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	/* an 8 GB partition */
+	partition@0 {
+		label = "filesystem #1";
+		reg = <0x0 0x00000000 0x2 0x00000000>;
+	};
+
+	/* a 4 GB partition */
+	partition@200000000 {
+		label = "filesystem #2";
+		reg = <0x2 0x00000000 0x1 0x00000000>;
+	};
+};
diff --git a/Documentation/devicetree/bindings/net/can/atmel-can.txt b/Documentation/devicetree/bindings/net/can/atmel-can.txt
new file mode 100644
index 0000000..72cf0c5
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/can/atmel-can.txt
@@ -0,0 +1,14 @@
+* AT91 CAN *
+
+Required properties:
+  - compatible: Should be "atmel,at91sam9263-can" or "atmel,at91sam9x5-can"
+  - reg: Should contain CAN controller registers location and length
+  - interrupts: Should contain IRQ line for the CAN controller
+
+Example:
+
+	can0: can@f000c000 {
+		compatbile = "atmel,at91sam9x5-can";
+		reg = <0xf000c000 0x300>;
+		interrupts = <40 4 5>
+	};
diff --git a/Documentation/devicetree/bindings/net/cpsw.txt b/Documentation/devicetree/bindings/net/cpsw.txt
index ecfdf75..4f2ca6b 100644
--- a/Documentation/devicetree/bindings/net/cpsw.txt
+++ b/Documentation/devicetree/bindings/net/cpsw.txt
@@ -15,16 +15,22 @@ Required properties:
 - mac_control		: Specifies Default MAC control register content
 			  for the specific platform
 - slaves		: Specifies number for slaves
-- cpts_active_slave	: Specifies the slave to use for time stamping
+- active_slave		: Specifies the slave to use for time stamping,
+			  ethtool and SIOCGMIIPHY
 - cpts_clock_mult	: Numerator to convert input clock ticks into nanoseconds
 - cpts_clock_shift	: Denominator to convert input clock ticks into nanoseconds
-- phy_id		: Specifies slave phy id
-- mac-address		: Specifies slave MAC address
 
 Optional properties:
 - ti,hwmods		: Must be "cpgmac0"
 - no_bd_ram		: Must be 0 or 1
 - dual_emac		: Specifies Switch to act as Dual EMAC
+
+Slave Properties:
+Required properties:
+- phy_id		: Specifies slave phy id
+- mac-address		: Specifies slave MAC address
+
+Optional properties:
 - dual_emac_res_vlan	: Specifies VID to be used to segregate the ports
 
 Note: "ti,hwmods" field is used to fetch the base address and irq
@@ -47,7 +53,7 @@ Examples:
 		rx_descs = <64>;
 		mac_control = <0x20>;
 		slaves = <2>;
-		cpts_active_slave = <0>;
+		active_slave = <0>;
 		cpts_clock_mult = <0x80000000>;
 		cpts_clock_shift = <29>;
 		cpsw_emac0: slave@0 {
@@ -73,7 +79,7 @@ Examples:
 		rx_descs = <64>;
 		mac_control = <0x20>;
 		slaves = <2>;
-		cpts_active_slave = <0>;
+		active_slave = <0>;
 		cpts_clock_mult = <0x80000000>;
 		cpts_clock_shift = <29>;
 		cpsw_emac0: slave@0 {
diff --git a/Documentation/devicetree/bindings/net/dsa/dsa.txt b/Documentation/devicetree/bindings/net/dsa/dsa.txt
new file mode 100644
index 0000000..49f4f7a
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/dsa/dsa.txt
@@ -0,0 +1,91 @@
+Marvell Distributed Switch Architecture Device Tree Bindings
+------------------------------------------------------------
+
+Required properties:
+- compatible		: Should be "marvell,dsa"
+- #address-cells	: Must be 2, first cell is the address on the MDIO bus
+			  and second cell is the address in the switch tree.
+			  Second cell is used only when cascading/chaining.
+- #size-cells		: Must be 0
+- dsa,ethernet		: Should be a phandle to a valid Ethernet device node
+- dsa,mii-bus		: Should be a phandle to a valid MDIO bus device node
+
+Optionnal properties:
+- interrupts		: property with a value describing the switch
+			  interrupt number (not supported by the driver)
+
+A DSA node can contain multiple switch chips which are therefore child nodes of
+the parent DSA node. The maximum number of allowed child nodes is 4
+(DSA_MAX_SWITCHES).
+Each of these switch child nodes should have the following required properties:
+
+- reg			: Describes the switch address on the MII bus
+- #address-cells	: Must be 1
+- #size-cells		: Must be 0
+
+A switch may have multiple "port" children nodes
+
+Each port children node must have the following mandatory properties:
+- reg			: Describes the port address in the switch
+- label			: Describes the label associated with this port, special
+			  labels are "cpu" to indicate a CPU port and "dsa" to
+			  indicate an uplink/downlink port.
+
+Note that a port labelled "dsa" will imply checking for the uplink phandle
+described below.
+
+Optionnal property:
+- link			: Should be a phandle to another switch's DSA port.
+			  This property is only used when switches are being
+			  chained/cascaded together.
+
+Example:
+
+	dsa@0 {
+		compatible = "marvell,dsa";
+		#address-cells = <2>;
+		#size-cells = <0>;
+
+		interrupts = <10>;
+		dsa,ethernet = <&ethernet0>;
+		dsa,mii-bus = <&mii_bus0>;
+
+		switch@0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <16 0>;	/* MDIO address 16, switch 0 in tree */
+
+			port@0 {
+				reg = <0>;
+				label = "lan1";
+			};
+
+			port@1 {
+				reg = <1>;
+				label = "lan2";
+			};
+
+			port@5 {
+				reg = <5>;
+				label = "cpu";
+			};
+
+			switch0uplink: port@6 {
+				reg = <6>;
+				label = "dsa";
+				link = <&switch1uplink>;
+			};
+		};
+
+		switch@1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <17 1>;	/* MDIO address 17, switch 1 in tree */
+
+			switch1uplink: port@0 {
+				reg = <0>;
+				label = "dsa";
+				link = <&switch0uplink>;
+			};
+		};
+	};
diff --git a/Documentation/devicetree/bindings/net/marvell-orion-mdio.txt b/Documentation/devicetree/bindings/net/marvell-orion-mdio.txt
index 34e7aaf..052b5f2 100644
--- a/Documentation/devicetree/bindings/net/marvell-orion-mdio.txt
+++ b/Documentation/devicetree/bindings/net/marvell-orion-mdio.txt
@@ -9,6 +9,9 @@ Required properties:
 - compatible: "marvell,orion-mdio"
 - reg: address and length of the SMI register
 
+Optional properties:
+- interrupts: interrupt line number for the SMI error/done interrupt
+
 The child nodes of the MDIO driver are the individual PHY devices
 connected to this MDIO bus. They must have a "reg" property given the
 PHY address on the MDIO bus.
diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,imx-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/fsl,imx-pinctrl.txt
index ab19e6b..bcfdab5 100644
--- a/Documentation/devicetree/bindings/pinctrl/fsl,imx-pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/fsl,imx-pinctrl.txt
@@ -24,9 +24,9 @@ Required properties for iomux controller:
 Required properties for pin configuration node:
 - fsl,pins: two integers array, represents a group of pins mux and config
   setting. The format is fsl,pins = <PIN_FUNC_ID CONFIG>, PIN_FUNC_ID is a
-  pin working on a specific function, CONFIG is the pad setting value like
-  pull-up on this pin. Please refer to fsl,<soc>-pinctrl.txt for the valid
-  pins and functions of each SoC.
+  pin working on a specific function, which consists of a tuple of
+  <mux_reg conf_reg input_reg mux_val input_val>.  CONFIG is the pad setting
+  value like pull-up on this pin.
 
 Bits used for CONFIG:
 NO_PAD_CTL(1 << 31): indicate this pin does not need config.
diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,imx35-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/fsl,imx35-pinctrl.txt
index 1183f1a..c083dfd 100644
--- a/Documentation/devicetree/bindings/pinctrl/fsl,imx35-pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/fsl,imx35-pinctrl.txt
@@ -29,956 +29,5 @@ PAD_CTL_DSE_MAX			(2 << 1)
 PAD_CTL_SRE_FAST		(1 << 0)
 PAD_CTL_SRE_SLOW		(0 << 0)
 
-See below for available PIN_FUNC_ID for imx35:
-0 MX35_PAD_CAPTURE__GPT_CAPIN1
-1 MX35_PAD_CAPTURE__GPT_CMPOUT2
-2 MX35_PAD_CAPTURE__CSPI2_SS1
-3 MX35_PAD_CAPTURE__EPIT1_EPITO
-4 MX35_PAD_CAPTURE__CCM_CLK32K
-5 MX35_PAD_CAPTURE__GPIO1_4
-6 MX35_PAD_COMPARE__GPT_CMPOUT1
-7 MX35_PAD_COMPARE__GPT_CAPIN2
-8 MX35_PAD_COMPARE__GPT_CMPOUT3
-9 MX35_PAD_COMPARE__EPIT2_EPITO
-10 MX35_PAD_COMPARE__GPIO1_5
-11 MX35_PAD_COMPARE__SDMA_EXTDMA_2
-12 MX35_PAD_WDOG_RST__WDOG_WDOG_B
-13 MX35_PAD_WDOG_RST__IPU_FLASH_STROBE
-14 MX35_PAD_WDOG_RST__GPIO1_6
-15 MX35_PAD_GPIO1_0__GPIO1_0
-16 MX35_PAD_GPIO1_0__CCM_PMIC_RDY
-17 MX35_PAD_GPIO1_0__OWIRE_LINE
-18 MX35_PAD_GPIO1_0__SDMA_EXTDMA_0
-19 MX35_PAD_GPIO1_1__GPIO1_1
-20 MX35_PAD_GPIO1_1__PWM_PWMO
-21 MX35_PAD_GPIO1_1__CSPI1_SS2
-22 MX35_PAD_GPIO1_1__SCC_TAMPER_DETECT
-23 MX35_PAD_GPIO1_1__SDMA_EXTDMA_1
-24 MX35_PAD_GPIO2_0__GPIO2_0
-25 MX35_PAD_GPIO2_0__USB_TOP_USBOTG_CLK
-26 MX35_PAD_GPIO3_0__GPIO3_0
-27 MX35_PAD_GPIO3_0__USB_TOP_USBH2_CLK
-28 MX35_PAD_RESET_IN_B__CCM_RESET_IN_B
-29 MX35_PAD_POR_B__CCM_POR_B
-30 MX35_PAD_CLKO__CCM_CLKO
-31 MX35_PAD_CLKO__GPIO1_8
-32 MX35_PAD_BOOT_MODE0__CCM_BOOT_MODE_0
-33 MX35_PAD_BOOT_MODE1__CCM_BOOT_MODE_1
-34 MX35_PAD_CLK_MODE0__CCM_CLK_MODE_0
-35 MX35_PAD_CLK_MODE1__CCM_CLK_MODE_1
-36 MX35_PAD_POWER_FAIL__CCM_DSM_WAKEUP_INT_26
-37 MX35_PAD_VSTBY__CCM_VSTBY
-38 MX35_PAD_VSTBY__GPIO1_7
-39 MX35_PAD_A0__EMI_EIM_DA_L_0
-40 MX35_PAD_A1__EMI_EIM_DA_L_1
-41 MX35_PAD_A2__EMI_EIM_DA_L_2
-42 MX35_PAD_A3__EMI_EIM_DA_L_3
-43 MX35_PAD_A4__EMI_EIM_DA_L_4
-44 MX35_PAD_A5__EMI_EIM_DA_L_5
-45 MX35_PAD_A6__EMI_EIM_DA_L_6
-46 MX35_PAD_A7__EMI_EIM_DA_L_7
-47 MX35_PAD_A8__EMI_EIM_DA_H_8
-48 MX35_PAD_A9__EMI_EIM_DA_H_9
-49 MX35_PAD_A10__EMI_EIM_DA_H_10
-50 MX35_PAD_MA10__EMI_MA10
-51 MX35_PAD_A11__EMI_EIM_DA_H_11
-52 MX35_PAD_A12__EMI_EIM_DA_H_12
-53 MX35_PAD_A13__EMI_EIM_DA_H_13
-54 MX35_PAD_A14__EMI_EIM_DA_H2_14
-55 MX35_PAD_A15__EMI_EIM_DA_H2_15
-56 MX35_PAD_A16__EMI_EIM_A_16
-57 MX35_PAD_A17__EMI_EIM_A_17
-58 MX35_PAD_A18__EMI_EIM_A_18
-59 MX35_PAD_A19__EMI_EIM_A_19
-60 MX35_PAD_A20__EMI_EIM_A_20
-61 MX35_PAD_A21__EMI_EIM_A_21
-62 MX35_PAD_A22__EMI_EIM_A_22
-63 MX35_PAD_A23__EMI_EIM_A_23
-64 MX35_PAD_A24__EMI_EIM_A_24
-65 MX35_PAD_A25__EMI_EIM_A_25
-66 MX35_PAD_SDBA1__EMI_EIM_SDBA1
-67 MX35_PAD_SDBA0__EMI_EIM_SDBA0
-68 MX35_PAD_SD0__EMI_DRAM_D_0
-69 MX35_PAD_SD1__EMI_DRAM_D_1
-70 MX35_PAD_SD2__EMI_DRAM_D_2
-71 MX35_PAD_SD3__EMI_DRAM_D_3
-72 MX35_PAD_SD4__EMI_DRAM_D_4
-73 MX35_PAD_SD5__EMI_DRAM_D_5
-74 MX35_PAD_SD6__EMI_DRAM_D_6
-75 MX35_PAD_SD7__EMI_DRAM_D_7
-76 MX35_PAD_SD8__EMI_DRAM_D_8
-77 MX35_PAD_SD9__EMI_DRAM_D_9
-78 MX35_PAD_SD10__EMI_DRAM_D_10
-79 MX35_PAD_SD11__EMI_DRAM_D_11
-80 MX35_PAD_SD12__EMI_DRAM_D_12
-81 MX35_PAD_SD13__EMI_DRAM_D_13
-82 MX35_PAD_SD14__EMI_DRAM_D_14
-83 MX35_PAD_SD15__EMI_DRAM_D_15
-84 MX35_PAD_SD16__EMI_DRAM_D_16
-85 MX35_PAD_SD17__EMI_DRAM_D_17
-86 MX35_PAD_SD18__EMI_DRAM_D_18
-87 MX35_PAD_SD19__EMI_DRAM_D_19
-88 MX35_PAD_SD20__EMI_DRAM_D_20
-89 MX35_PAD_SD21__EMI_DRAM_D_21
-90 MX35_PAD_SD22__EMI_DRAM_D_22
-91 MX35_PAD_SD23__EMI_DRAM_D_23
-92 MX35_PAD_SD24__EMI_DRAM_D_24
-93 MX35_PAD_SD25__EMI_DRAM_D_25
-94 MX35_PAD_SD26__EMI_DRAM_D_26
-95 MX35_PAD_SD27__EMI_DRAM_D_27
-96 MX35_PAD_SD28__EMI_DRAM_D_28
-97 MX35_PAD_SD29__EMI_DRAM_D_29
-98 MX35_PAD_SD30__EMI_DRAM_D_30
-99 MX35_PAD_SD31__EMI_DRAM_D_31
-100 MX35_PAD_DQM0__EMI_DRAM_DQM_0
-101 MX35_PAD_DQM1__EMI_DRAM_DQM_1
-102 MX35_PAD_DQM2__EMI_DRAM_DQM_2
-103 MX35_PAD_DQM3__EMI_DRAM_DQM_3
-104 MX35_PAD_EB0__EMI_EIM_EB0_B
-105 MX35_PAD_EB1__EMI_EIM_EB1_B
-106 MX35_PAD_OE__EMI_EIM_OE
-107 MX35_PAD_CS0__EMI_EIM_CS0
-108 MX35_PAD_CS1__EMI_EIM_CS1
-109 MX35_PAD_CS1__EMI_NANDF_CE3
-110 MX35_PAD_CS2__EMI_EIM_CS2
-111 MX35_PAD_CS3__EMI_EIM_CS3
-112 MX35_PAD_CS4__EMI_EIM_CS4
-113 MX35_PAD_CS4__EMI_DTACK_B
-114 MX35_PAD_CS4__EMI_NANDF_CE1
-115 MX35_PAD_CS4__GPIO1_20
-116 MX35_PAD_CS5__EMI_EIM_CS5
-117 MX35_PAD_CS5__CSPI2_SS2
-118 MX35_PAD_CS5__CSPI1_SS2
-119 MX35_PAD_CS5__EMI_NANDF_CE2
-120 MX35_PAD_CS5__GPIO1_21
-121 MX35_PAD_NF_CE0__EMI_NANDF_CE0
-122 MX35_PAD_NF_CE0__GPIO1_22
-123 MX35_PAD_ECB__EMI_EIM_ECB
-124 MX35_PAD_LBA__EMI_EIM_LBA
-125 MX35_PAD_BCLK__EMI_EIM_BCLK
-126 MX35_PAD_RW__EMI_EIM_RW
-127 MX35_PAD_RAS__EMI_DRAM_RAS
-128 MX35_PAD_CAS__EMI_DRAM_CAS
-129 MX35_PAD_SDWE__EMI_DRAM_SDWE
-130 MX35_PAD_SDCKE0__EMI_DRAM_SDCKE_0
-131 MX35_PAD_SDCKE1__EMI_DRAM_SDCKE_1
-132 MX35_PAD_SDCLK__EMI_DRAM_SDCLK
-133 MX35_PAD_SDQS0__EMI_DRAM_SDQS_0
-134 MX35_PAD_SDQS1__EMI_DRAM_SDQS_1
-135 MX35_PAD_SDQS2__EMI_DRAM_SDQS_2
-136 MX35_PAD_SDQS3__EMI_DRAM_SDQS_3
-137 MX35_PAD_NFWE_B__EMI_NANDF_WE_B
-138 MX35_PAD_NFWE_B__USB_TOP_USBH2_DATA_3
-139 MX35_PAD_NFWE_B__IPU_DISPB_D0_VSYNC
-140 MX35_PAD_NFWE_B__GPIO2_18
-141 MX35_PAD_NFWE_B__ARM11P_TOP_TRACE_0
-142 MX35_PAD_NFRE_B__EMI_NANDF_RE_B
-143 MX35_PAD_NFRE_B__USB_TOP_USBH2_DIR
-144 MX35_PAD_NFRE_B__IPU_DISPB_BCLK
-145 MX35_PAD_NFRE_B__GPIO2_19
-146 MX35_PAD_NFRE_B__ARM11P_TOP_TRACE_1
-147 MX35_PAD_NFALE__EMI_NANDF_ALE
-148 MX35_PAD_NFALE__USB_TOP_USBH2_STP
-149 MX35_PAD_NFALE__IPU_DISPB_CS0
-150 MX35_PAD_NFALE__GPIO2_20
-151 MX35_PAD_NFALE__ARM11P_TOP_TRACE_2
-152 MX35_PAD_NFCLE__EMI_NANDF_CLE
-153 MX35_PAD_NFCLE__USB_TOP_USBH2_NXT
-154 MX35_PAD_NFCLE__IPU_DISPB_PAR_RS
-155 MX35_PAD_NFCLE__GPIO2_21
-156 MX35_PAD_NFCLE__ARM11P_TOP_TRACE_3
-157 MX35_PAD_NFWP_B__EMI_NANDF_WP_B
-158 MX35_PAD_NFWP_B__USB_TOP_USBH2_DATA_7
-159 MX35_PAD_NFWP_B__IPU_DISPB_WR
-160 MX35_PAD_NFWP_B__GPIO2_22
-161 MX35_PAD_NFWP_B__ARM11P_TOP_TRCTL
-162 MX35_PAD_NFRB__EMI_NANDF_RB
-163 MX35_PAD_NFRB__IPU_DISPB_RD
-164 MX35_PAD_NFRB__GPIO2_23
-165 MX35_PAD_NFRB__ARM11P_TOP_TRCLK
-166 MX35_PAD_D15__EMI_EIM_D_15
-167 MX35_PAD_D14__EMI_EIM_D_14
-168 MX35_PAD_D13__EMI_EIM_D_13
-169 MX35_PAD_D12__EMI_EIM_D_12
-170 MX35_PAD_D11__EMI_EIM_D_11
-171 MX35_PAD_D10__EMI_EIM_D_10
-172 MX35_PAD_D9__EMI_EIM_D_9
-173 MX35_PAD_D8__EMI_EIM_D_8
-174 MX35_PAD_D7__EMI_EIM_D_7
-175 MX35_PAD_D6__EMI_EIM_D_6
-176 MX35_PAD_D5__EMI_EIM_D_5
-177 MX35_PAD_D4__EMI_EIM_D_4
-178 MX35_PAD_D3__EMI_EIM_D_3
-179 MX35_PAD_D2__EMI_EIM_D_2
-180 MX35_PAD_D1__EMI_EIM_D_1
-181 MX35_PAD_D0__EMI_EIM_D_0
-182 MX35_PAD_CSI_D8__IPU_CSI_D_8
-183 MX35_PAD_CSI_D8__KPP_COL_0
-184 MX35_PAD_CSI_D8__GPIO1_20
-185 MX35_PAD_CSI_D8__ARM11P_TOP_EVNTBUS_13
-186 MX35_PAD_CSI_D9__IPU_CSI_D_9
-187 MX35_PAD_CSI_D9__KPP_COL_1
-188 MX35_PAD_CSI_D9__GPIO1_21
-189 MX35_PAD_CSI_D9__ARM11P_TOP_EVNTBUS_14
-190 MX35_PAD_CSI_D10__IPU_CSI_D_10
-191 MX35_PAD_CSI_D10__KPP_COL_2
-192 MX35_PAD_CSI_D10__GPIO1_22
-193 MX35_PAD_CSI_D10__ARM11P_TOP_EVNTBUS_15
-194 MX35_PAD_CSI_D11__IPU_CSI_D_11
-195 MX35_PAD_CSI_D11__KPP_COL_3
-196 MX35_PAD_CSI_D11__GPIO1_23
-197 MX35_PAD_CSI_D12__IPU_CSI_D_12
-198 MX35_PAD_CSI_D12__KPP_ROW_0
-199 MX35_PAD_CSI_D12__GPIO1_24
-200 MX35_PAD_CSI_D13__IPU_CSI_D_13
-201 MX35_PAD_CSI_D13__KPP_ROW_1
-202 MX35_PAD_CSI_D13__GPIO1_25
-203 MX35_PAD_CSI_D14__IPU_CSI_D_14
-204 MX35_PAD_CSI_D14__KPP_ROW_2
-205 MX35_PAD_CSI_D14__GPIO1_26
-206 MX35_PAD_CSI_D15__IPU_CSI_D_15
-207 MX35_PAD_CSI_D15__KPP_ROW_3
-208 MX35_PAD_CSI_D15__GPIO1_27
-209 MX35_PAD_CSI_MCLK__IPU_CSI_MCLK
-210 MX35_PAD_CSI_MCLK__GPIO1_28
-211 MX35_PAD_CSI_VSYNC__IPU_CSI_VSYNC
-212 MX35_PAD_CSI_VSYNC__GPIO1_29
-213 MX35_PAD_CSI_HSYNC__IPU_CSI_HSYNC
-214 MX35_PAD_CSI_HSYNC__GPIO1_30
-215 MX35_PAD_CSI_PIXCLK__IPU_CSI_PIXCLK
-216 MX35_PAD_CSI_PIXCLK__GPIO1_31
-217 MX35_PAD_I2C1_CLK__I2C1_SCL
-218 MX35_PAD_I2C1_CLK__GPIO2_24
-219 MX35_PAD_I2C1_CLK__CCM_USB_BYP_CLK
-220 MX35_PAD_I2C1_DAT__I2C1_SDA
-221 MX35_PAD_I2C1_DAT__GPIO2_25
-222 MX35_PAD_I2C2_CLK__I2C2_SCL
-223 MX35_PAD_I2C2_CLK__CAN1_TXCAN
-224 MX35_PAD_I2C2_CLK__USB_TOP_USBH2_PWR
-225 MX35_PAD_I2C2_CLK__GPIO2_26
-226 MX35_PAD_I2C2_CLK__SDMA_DEBUG_BUS_DEVICE_2
-227 MX35_PAD_I2C2_DAT__I2C2_SDA
-228 MX35_PAD_I2C2_DAT__CAN1_RXCAN
-229 MX35_PAD_I2C2_DAT__USB_TOP_USBH2_OC
-230 MX35_PAD_I2C2_DAT__GPIO2_27
-231 MX35_PAD_I2C2_DAT__SDMA_DEBUG_BUS_DEVICE_3
-232 MX35_PAD_STXD4__AUDMUX_AUD4_TXD
-233 MX35_PAD_STXD4__GPIO2_28
-234 MX35_PAD_STXD4__ARM11P_TOP_ARM_COREASID0
-235 MX35_PAD_SRXD4__AUDMUX_AUD4_RXD
-236 MX35_PAD_SRXD4__GPIO2_29
-237 MX35_PAD_SRXD4__ARM11P_TOP_ARM_COREASID1
-238 MX35_PAD_SCK4__AUDMUX_AUD4_TXC
-239 MX35_PAD_SCK4__GPIO2_30
-240 MX35_PAD_SCK4__ARM11P_TOP_ARM_COREASID2
-241 MX35_PAD_STXFS4__AUDMUX_AUD4_TXFS
-242 MX35_PAD_STXFS4__GPIO2_31
-243 MX35_PAD_STXFS4__ARM11P_TOP_ARM_COREASID3
-244 MX35_PAD_STXD5__AUDMUX_AUD5_TXD
-245 MX35_PAD_STXD5__SPDIF_SPDIF_OUT1
-246 MX35_PAD_STXD5__CSPI2_MOSI
-247 MX35_PAD_STXD5__GPIO1_0
-248 MX35_PAD_STXD5__ARM11P_TOP_ARM_COREASID4
-249 MX35_PAD_SRXD5__AUDMUX_AUD5_RXD
-250 MX35_PAD_SRXD5__SPDIF_SPDIF_IN1
-251 MX35_PAD_SRXD5__CSPI2_MISO
-252 MX35_PAD_SRXD5__GPIO1_1
-253 MX35_PAD_SRXD5__ARM11P_TOP_ARM_COREASID5
-254 MX35_PAD_SCK5__AUDMUX_AUD5_TXC
-255 MX35_PAD_SCK5__SPDIF_SPDIF_EXTCLK
-256 MX35_PAD_SCK5__CSPI2_SCLK
-257 MX35_PAD_SCK5__GPIO1_2
-258 MX35_PAD_SCK5__ARM11P_TOP_ARM_COREASID6
-259 MX35_PAD_STXFS5__AUDMUX_AUD5_TXFS
-260 MX35_PAD_STXFS5__CSPI2_RDY
-261 MX35_PAD_STXFS5__GPIO1_3
-262 MX35_PAD_STXFS5__ARM11P_TOP_ARM_COREASID7
-263 MX35_PAD_SCKR__ESAI_SCKR
-264 MX35_PAD_SCKR__GPIO1_4
-265 MX35_PAD_SCKR__ARM11P_TOP_EVNTBUS_10
-266 MX35_PAD_FSR__ESAI_FSR
-267 MX35_PAD_FSR__GPIO1_5
-268 MX35_PAD_FSR__ARM11P_TOP_EVNTBUS_11
-269 MX35_PAD_HCKR__ESAI_HCKR
-270 MX35_PAD_HCKR__AUDMUX_AUD5_RXFS
-271 MX35_PAD_HCKR__CSPI2_SS0
-272 MX35_PAD_HCKR__IPU_FLASH_STROBE
-273 MX35_PAD_HCKR__GPIO1_6
-274 MX35_PAD_HCKR__ARM11P_TOP_EVNTBUS_12
-275 MX35_PAD_SCKT__ESAI_SCKT
-276 MX35_PAD_SCKT__GPIO1_7
-277 MX35_PAD_SCKT__IPU_CSI_D_0
-278 MX35_PAD_SCKT__KPP_ROW_2
-279 MX35_PAD_FST__ESAI_FST
-280 MX35_PAD_FST__GPIO1_8
-281 MX35_PAD_FST__IPU_CSI_D_1
-282 MX35_PAD_FST__KPP_ROW_3
-283 MX35_PAD_HCKT__ESAI_HCKT
-284 MX35_PAD_HCKT__AUDMUX_AUD5_RXC
-285 MX35_PAD_HCKT__GPIO1_9
-286 MX35_PAD_HCKT__IPU_CSI_D_2
-287 MX35_PAD_HCKT__KPP_COL_3
-288 MX35_PAD_TX5_RX0__ESAI_TX5_RX0
-289 MX35_PAD_TX5_RX0__AUDMUX_AUD4_RXC
-290 MX35_PAD_TX5_RX0__CSPI2_SS2
-291 MX35_PAD_TX5_RX0__CAN2_TXCAN
-292 MX35_PAD_TX5_RX0__UART2_DTR
-293 MX35_PAD_TX5_RX0__GPIO1_10
-294 MX35_PAD_TX5_RX0__EMI_M3IF_CHOSEN_MASTER_0
-295 MX35_PAD_TX4_RX1__ESAI_TX4_RX1
-296 MX35_PAD_TX4_RX1__AUDMUX_AUD4_RXFS
-297 MX35_PAD_TX4_RX1__CSPI2_SS3
-298 MX35_PAD_TX4_RX1__CAN2_RXCAN
-299 MX35_PAD_TX4_RX1__UART2_DSR
-300 MX35_PAD_TX4_RX1__GPIO1_11
-301 MX35_PAD_TX4_RX1__IPU_CSI_D_3
-302 MX35_PAD_TX4_RX1__KPP_ROW_0
-303 MX35_PAD_TX3_RX2__ESAI_TX3_RX2
-304 MX35_PAD_TX3_RX2__I2C3_SCL
-305 MX35_PAD_TX3_RX2__EMI_NANDF_CE1
-306 MX35_PAD_TX3_RX2__GPIO1_12
-307 MX35_PAD_TX3_RX2__IPU_CSI_D_4
-308 MX35_PAD_TX3_RX2__KPP_ROW_1
-309 MX35_PAD_TX2_RX3__ESAI_TX2_RX3
-310 MX35_PAD_TX2_RX3__I2C3_SDA
-311 MX35_PAD_TX2_RX3__EMI_NANDF_CE2
-312 MX35_PAD_TX2_RX3__GPIO1_13
-313 MX35_PAD_TX2_RX3__IPU_CSI_D_5
-314 MX35_PAD_TX2_RX3__KPP_COL_0
-315 MX35_PAD_TX1__ESAI_TX1
-316 MX35_PAD_TX1__CCM_PMIC_RDY
-317 MX35_PAD_TX1__CSPI1_SS2
-318 MX35_PAD_TX1__EMI_NANDF_CE3
-319 MX35_PAD_TX1__UART2_RI
-320 MX35_PAD_TX1__GPIO1_14
-321 MX35_PAD_TX1__IPU_CSI_D_6
-322 MX35_PAD_TX1__KPP_COL_1
-323 MX35_PAD_TX0__ESAI_TX0
-324 MX35_PAD_TX0__SPDIF_SPDIF_EXTCLK
-325 MX35_PAD_TX0__CSPI1_SS3
-326 MX35_PAD_TX0__EMI_DTACK_B
-327 MX35_PAD_TX0__UART2_DCD
-328 MX35_PAD_TX0__GPIO1_15
-329 MX35_PAD_TX0__IPU_CSI_D_7
-330 MX35_PAD_TX0__KPP_COL_2
-331 MX35_PAD_CSPI1_MOSI__CSPI1_MOSI
-332 MX35_PAD_CSPI1_MOSI__GPIO1_16
-333 MX35_PAD_CSPI1_MOSI__ECT_CTI_TRIG_OUT1_2
-334 MX35_PAD_CSPI1_MISO__CSPI1_MISO
-335 MX35_PAD_CSPI1_MISO__GPIO1_17
-336 MX35_PAD_CSPI1_MISO__ECT_CTI_TRIG_OUT1_3
-337 MX35_PAD_CSPI1_SS0__CSPI1_SS0
-338 MX35_PAD_CSPI1_SS0__OWIRE_LINE
-339 MX35_PAD_CSPI1_SS0__CSPI2_SS3
-340 MX35_PAD_CSPI1_SS0__GPIO1_18
-341 MX35_PAD_CSPI1_SS0__ECT_CTI_TRIG_OUT1_4
-342 MX35_PAD_CSPI1_SS1__CSPI1_SS1
-343 MX35_PAD_CSPI1_SS1__PWM_PWMO
-344 MX35_PAD_CSPI1_SS1__CCM_CLK32K
-345 MX35_PAD_CSPI1_SS1__GPIO1_19
-346 MX35_PAD_CSPI1_SS1__IPU_DIAGB_29
-347 MX35_PAD_CSPI1_SS1__ECT_CTI_TRIG_OUT1_5
-348 MX35_PAD_CSPI1_SCLK__CSPI1_SCLK
-349 MX35_PAD_CSPI1_SCLK__GPIO3_4
-350 MX35_PAD_CSPI1_SCLK__IPU_DIAGB_30
-351 MX35_PAD_CSPI1_SCLK__EMI_M3IF_CHOSEN_MASTER_1
-352 MX35_PAD_CSPI1_SPI_RDY__CSPI1_RDY
-353 MX35_PAD_CSPI1_SPI_RDY__GPIO3_5
-354 MX35_PAD_CSPI1_SPI_RDY__IPU_DIAGB_31
-355 MX35_PAD_CSPI1_SPI_RDY__EMI_M3IF_CHOSEN_MASTER_2
-356 MX35_PAD_RXD1__UART1_RXD_MUX
-357 MX35_PAD_RXD1__CSPI2_MOSI
-358 MX35_PAD_RXD1__KPP_COL_4
-359 MX35_PAD_RXD1__GPIO3_6
-360 MX35_PAD_RXD1__ARM11P_TOP_EVNTBUS_16
-361 MX35_PAD_TXD1__UART1_TXD_MUX
-362 MX35_PAD_TXD1__CSPI2_MISO
-363 MX35_PAD_TXD1__KPP_COL_5
-364 MX35_PAD_TXD1__GPIO3_7
-365 MX35_PAD_TXD1__ARM11P_TOP_EVNTBUS_17
-366 MX35_PAD_RTS1__UART1_RTS
-367 MX35_PAD_RTS1__CSPI2_SCLK
-368 MX35_PAD_RTS1__I2C3_SCL
-369 MX35_PAD_RTS1__IPU_CSI_D_0
-370 MX35_PAD_RTS1__KPP_COL_6
-371 MX35_PAD_RTS1__GPIO3_8
-372 MX35_PAD_RTS1__EMI_NANDF_CE1
-373 MX35_PAD_RTS1__ARM11P_TOP_EVNTBUS_18
-374 MX35_PAD_CTS1__UART1_CTS
-375 MX35_PAD_CTS1__CSPI2_RDY
-376 MX35_PAD_CTS1__I2C3_SDA
-377 MX35_PAD_CTS1__IPU_CSI_D_1
-378 MX35_PAD_CTS1__KPP_COL_7
-379 MX35_PAD_CTS1__GPIO3_9
-380 MX35_PAD_CTS1__EMI_NANDF_CE2
-381 MX35_PAD_CTS1__ARM11P_TOP_EVNTBUS_19
-382 MX35_PAD_RXD2__UART2_RXD_MUX
-383 MX35_PAD_RXD2__KPP_ROW_4
-384 MX35_PAD_RXD2__GPIO3_10
-385 MX35_PAD_TXD2__UART2_TXD_MUX
-386 MX35_PAD_TXD2__SPDIF_SPDIF_EXTCLK
-387 MX35_PAD_TXD2__KPP_ROW_5
-388 MX35_PAD_TXD2__GPIO3_11
-389 MX35_PAD_RTS2__UART2_RTS
-390 MX35_PAD_RTS2__SPDIF_SPDIF_IN1
-391 MX35_PAD_RTS2__CAN2_RXCAN
-392 MX35_PAD_RTS2__IPU_CSI_D_2
-393 MX35_PAD_RTS2__KPP_ROW_6
-394 MX35_PAD_RTS2__GPIO3_12
-395 MX35_PAD_RTS2__AUDMUX_AUD5_RXC
-396 MX35_PAD_RTS2__UART3_RXD_MUX
-397 MX35_PAD_CTS2__UART2_CTS
-398 MX35_PAD_CTS2__SPDIF_SPDIF_OUT1
-399 MX35_PAD_CTS2__CAN2_TXCAN
-400 MX35_PAD_CTS2__IPU_CSI_D_3
-401 MX35_PAD_CTS2__KPP_ROW_7
-402 MX35_PAD_CTS2__GPIO3_13
-403 MX35_PAD_CTS2__AUDMUX_AUD5_RXFS
-404 MX35_PAD_CTS2__UART3_TXD_MUX
-405 MX35_PAD_RTCK__ARM11P_TOP_RTCK
-406 MX35_PAD_TCK__SJC_TCK
-407 MX35_PAD_TMS__SJC_TMS
-408 MX35_PAD_TDI__SJC_TDI
-409 MX35_PAD_TDO__SJC_TDO
-410 MX35_PAD_TRSTB__SJC_TRSTB
-411 MX35_PAD_DE_B__SJC_DE_B
-412 MX35_PAD_SJC_MOD__SJC_MOD
-413 MX35_PAD_USBOTG_PWR__USB_TOP_USBOTG_PWR
-414 MX35_PAD_USBOTG_PWR__USB_TOP_USBH2_PWR
-415 MX35_PAD_USBOTG_PWR__GPIO3_14
-416 MX35_PAD_USBOTG_OC__USB_TOP_USBOTG_OC
-417 MX35_PAD_USBOTG_OC__USB_TOP_USBH2_OC
-418 MX35_PAD_USBOTG_OC__GPIO3_15
-419 MX35_PAD_LD0__IPU_DISPB_DAT_0
-420 MX35_PAD_LD0__GPIO2_0
-421 MX35_PAD_LD0__SDMA_SDMA_DEBUG_PC_0
-422 MX35_PAD_LD1__IPU_DISPB_DAT_1
-423 MX35_PAD_LD1__GPIO2_1
-424 MX35_PAD_LD1__SDMA_SDMA_DEBUG_PC_1
-425 MX35_PAD_LD2__IPU_DISPB_DAT_2
-426 MX35_PAD_LD2__GPIO2_2
-427 MX35_PAD_LD2__SDMA_SDMA_DEBUG_PC_2
-428 MX35_PAD_LD3__IPU_DISPB_DAT_3
-429 MX35_PAD_LD3__GPIO2_3
-430 MX35_PAD_LD3__SDMA_SDMA_DEBUG_PC_3
-431 MX35_PAD_LD4__IPU_DISPB_DAT_4
-432 MX35_PAD_LD4__GPIO2_4
-433 MX35_PAD_LD4__SDMA_SDMA_DEBUG_PC_4
-434 MX35_PAD_LD5__IPU_DISPB_DAT_5
-435 MX35_PAD_LD5__GPIO2_5
-436 MX35_PAD_LD5__SDMA_SDMA_DEBUG_PC_5
-437 MX35_PAD_LD6__IPU_DISPB_DAT_6
-438 MX35_PAD_LD6__GPIO2_6
-439 MX35_PAD_LD6__SDMA_SDMA_DEBUG_PC_6
-440 MX35_PAD_LD7__IPU_DISPB_DAT_7
-441 MX35_PAD_LD7__GPIO2_7
-442 MX35_PAD_LD7__SDMA_SDMA_DEBUG_PC_7
-443 MX35_PAD_LD8__IPU_DISPB_DAT_8
-444 MX35_PAD_LD8__GPIO2_8
-445 MX35_PAD_LD8__SDMA_SDMA_DEBUG_PC_8
-446 MX35_PAD_LD9__IPU_DISPB_DAT_9
-447 MX35_PAD_LD9__GPIO2_9
-448 MX35_PAD_LD9__SDMA_SDMA_DEBUG_PC_9
-449 MX35_PAD_LD10__IPU_DISPB_DAT_10
-450 MX35_PAD_LD10__GPIO2_10
-451 MX35_PAD_LD10__SDMA_SDMA_DEBUG_PC_10
-452 MX35_PAD_LD11__IPU_DISPB_DAT_11
-453 MX35_PAD_LD11__GPIO2_11
-454 MX35_PAD_LD11__SDMA_SDMA_DEBUG_PC_11
-455 MX35_PAD_LD11__ARM11P_TOP_TRACE_4
-456 MX35_PAD_LD12__IPU_DISPB_DAT_12
-457 MX35_PAD_LD12__GPIO2_12
-458 MX35_PAD_LD12__SDMA_SDMA_DEBUG_PC_12
-459 MX35_PAD_LD12__ARM11P_TOP_TRACE_5
-460 MX35_PAD_LD13__IPU_DISPB_DAT_13
-461 MX35_PAD_LD13__GPIO2_13
-462 MX35_PAD_LD13__SDMA_SDMA_DEBUG_PC_13
-463 MX35_PAD_LD13__ARM11P_TOP_TRACE_6
-464 MX35_PAD_LD14__IPU_DISPB_DAT_14
-465 MX35_PAD_LD14__GPIO2_14
-466 MX35_PAD_LD14__SDMA_SDMA_DEBUG_EVENT_CHANNEL_0
-467 MX35_PAD_LD14__ARM11P_TOP_TRACE_7
-468 MX35_PAD_LD15__IPU_DISPB_DAT_15
-469 MX35_PAD_LD15__GPIO2_15
-470 MX35_PAD_LD15__SDMA_SDMA_DEBUG_EVENT_CHANNEL_1
-471 MX35_PAD_LD15__ARM11P_TOP_TRACE_8
-472 MX35_PAD_LD16__IPU_DISPB_DAT_16
-473 MX35_PAD_LD16__IPU_DISPB_D12_VSYNC
-474 MX35_PAD_LD16__GPIO2_16
-475 MX35_PAD_LD16__SDMA_SDMA_DEBUG_EVENT_CHANNEL_2
-476 MX35_PAD_LD16__ARM11P_TOP_TRACE_9
-477 MX35_PAD_LD17__IPU_DISPB_DAT_17
-478 MX35_PAD_LD17__IPU_DISPB_CS2
-479 MX35_PAD_LD17__GPIO2_17
-480 MX35_PAD_LD17__SDMA_SDMA_DEBUG_EVENT_CHANNEL_3
-481 MX35_PAD_LD17__ARM11P_TOP_TRACE_10
-482 MX35_PAD_LD18__IPU_DISPB_DAT_18
-483 MX35_PAD_LD18__IPU_DISPB_D0_VSYNC
-484 MX35_PAD_LD18__IPU_DISPB_D12_VSYNC
-485 MX35_PAD_LD18__ESDHC3_CMD
-486 MX35_PAD_LD18__USB_TOP_USBOTG_DATA_3
-487 MX35_PAD_LD18__GPIO3_24
-488 MX35_PAD_LD18__SDMA_SDMA_DEBUG_EVENT_CHANNEL_4
-489 MX35_PAD_LD18__ARM11P_TOP_TRACE_11
-490 MX35_PAD_LD19__IPU_DISPB_DAT_19
-491 MX35_PAD_LD19__IPU_DISPB_BCLK
-492 MX35_PAD_LD19__IPU_DISPB_CS1
-493 MX35_PAD_LD19__ESDHC3_CLK
-494 MX35_PAD_LD19__USB_TOP_USBOTG_DIR
-495 MX35_PAD_LD19__GPIO3_25
-496 MX35_PAD_LD19__SDMA_SDMA_DEBUG_EVENT_CHANNEL_5
-497 MX35_PAD_LD19__ARM11P_TOP_TRACE_12
-498 MX35_PAD_LD20__IPU_DISPB_DAT_20
-499 MX35_PAD_LD20__IPU_DISPB_CS0
-500 MX35_PAD_LD20__IPU_DISPB_SD_CLK
-501 MX35_PAD_LD20__ESDHC3_DAT0
-502 MX35_PAD_LD20__GPIO3_26
-503 MX35_PAD_LD20__SDMA_SDMA_DEBUG_CORE_STATUS_3
-504 MX35_PAD_LD20__ARM11P_TOP_TRACE_13
-505 MX35_PAD_LD21__IPU_DISPB_DAT_21
-506 MX35_PAD_LD21__IPU_DISPB_PAR_RS
-507 MX35_PAD_LD21__IPU_DISPB_SER_RS
-508 MX35_PAD_LD21__ESDHC3_DAT1
-509 MX35_PAD_LD21__USB_TOP_USBOTG_STP
-510 MX35_PAD_LD21__GPIO3_27
-511 MX35_PAD_LD21__SDMA_DEBUG_EVENT_CHANNEL_SEL
-512 MX35_PAD_LD21__ARM11P_TOP_TRACE_14
-513 MX35_PAD_LD22__IPU_DISPB_DAT_22
-514 MX35_PAD_LD22__IPU_DISPB_WR
-515 MX35_PAD_LD22__IPU_DISPB_SD_D_I
-516 MX35_PAD_LD22__ESDHC3_DAT2
-517 MX35_PAD_LD22__USB_TOP_USBOTG_NXT
-518 MX35_PAD_LD22__GPIO3_28
-519 MX35_PAD_LD22__SDMA_DEBUG_BUS_ERROR
-520 MX35_PAD_LD22__ARM11P_TOP_TRCTL
-521 MX35_PAD_LD23__IPU_DISPB_DAT_23
-522 MX35_PAD_LD23__IPU_DISPB_RD
-523 MX35_PAD_LD23__IPU_DISPB_SD_D_IO
-524 MX35_PAD_LD23__ESDHC3_DAT3
-525 MX35_PAD_LD23__USB_TOP_USBOTG_DATA_7
-526 MX35_PAD_LD23__GPIO3_29
-527 MX35_PAD_LD23__SDMA_DEBUG_MATCHED_DMBUS
-528 MX35_PAD_LD23__ARM11P_TOP_TRCLK
-529 MX35_PAD_D3_HSYNC__IPU_DISPB_D3_HSYNC
-530 MX35_PAD_D3_HSYNC__IPU_DISPB_SD_D_IO
-531 MX35_PAD_D3_HSYNC__GPIO3_30
-532 MX35_PAD_D3_HSYNC__SDMA_DEBUG_RTBUFFER_WRITE
-533 MX35_PAD_D3_HSYNC__ARM11P_TOP_TRACE_15
-534 MX35_PAD_D3_FPSHIFT__IPU_DISPB_D3_CLK
-535 MX35_PAD_D3_FPSHIFT__IPU_DISPB_SD_CLK
-536 MX35_PAD_D3_FPSHIFT__GPIO3_31
-537 MX35_PAD_D3_FPSHIFT__SDMA_SDMA_DEBUG_CORE_STATUS_0
-538 MX35_PAD_D3_FPSHIFT__ARM11P_TOP_TRACE_16
-539 MX35_PAD_D3_DRDY__IPU_DISPB_D3_DRDY
-540 MX35_PAD_D3_DRDY__IPU_DISPB_SD_D_O
-541 MX35_PAD_D3_DRDY__GPIO1_0
-542 MX35_PAD_D3_DRDY__SDMA_SDMA_DEBUG_CORE_STATUS_1
-543 MX35_PAD_D3_DRDY__ARM11P_TOP_TRACE_17
-544 MX35_PAD_CONTRAST__IPU_DISPB_CONTR
-545 MX35_PAD_CONTRAST__GPIO1_1
-546 MX35_PAD_CONTRAST__SDMA_SDMA_DEBUG_CORE_STATUS_2
-547 MX35_PAD_CONTRAST__ARM11P_TOP_TRACE_18
-548 MX35_PAD_D3_VSYNC__IPU_DISPB_D3_VSYNC
-549 MX35_PAD_D3_VSYNC__IPU_DISPB_CS1
-550 MX35_PAD_D3_VSYNC__GPIO1_2
-551 MX35_PAD_D3_VSYNC__SDMA_DEBUG_YIELD
-552 MX35_PAD_D3_VSYNC__ARM11P_TOP_TRACE_19
-553 MX35_PAD_D3_REV__IPU_DISPB_D3_REV
-554 MX35_PAD_D3_REV__IPU_DISPB_SER_RS
-555 MX35_PAD_D3_REV__GPIO1_3
-556 MX35_PAD_D3_REV__SDMA_DEBUG_BUS_RWB
-557 MX35_PAD_D3_REV__ARM11P_TOP_TRACE_20
-558 MX35_PAD_D3_CLS__IPU_DISPB_D3_CLS
-559 MX35_PAD_D3_CLS__IPU_DISPB_CS2
-560 MX35_PAD_D3_CLS__GPIO1_4
-561 MX35_PAD_D3_CLS__SDMA_DEBUG_BUS_DEVICE_0
-562 MX35_PAD_D3_CLS__ARM11P_TOP_TRACE_21
-563 MX35_PAD_D3_SPL__IPU_DISPB_D3_SPL
-564 MX35_PAD_D3_SPL__IPU_DISPB_D12_VSYNC
-565 MX35_PAD_D3_SPL__GPIO1_5
-566 MX35_PAD_D3_SPL__SDMA_DEBUG_BUS_DEVICE_1
-567 MX35_PAD_D3_SPL__ARM11P_TOP_TRACE_22
-568 MX35_PAD_SD1_CMD__ESDHC1_CMD
-569 MX35_PAD_SD1_CMD__MSHC_SCLK
-570 MX35_PAD_SD1_CMD__IPU_DISPB_D0_VSYNC
-571 MX35_PAD_SD1_CMD__USB_TOP_USBOTG_DATA_4
-572 MX35_PAD_SD1_CMD__GPIO1_6
-573 MX35_PAD_SD1_CMD__ARM11P_TOP_TRCTL
-574 MX35_PAD_SD1_CLK__ESDHC1_CLK
-575 MX35_PAD_SD1_CLK__MSHC_BS
-576 MX35_PAD_SD1_CLK__IPU_DISPB_BCLK
-577 MX35_PAD_SD1_CLK__USB_TOP_USBOTG_DATA_5
-578 MX35_PAD_SD1_CLK__GPIO1_7
-579 MX35_PAD_SD1_CLK__ARM11P_TOP_TRCLK
-580 MX35_PAD_SD1_DATA0__ESDHC1_DAT0
-581 MX35_PAD_SD1_DATA0__MSHC_DATA_0
-582 MX35_PAD_SD1_DATA0__IPU_DISPB_CS0
-583 MX35_PAD_SD1_DATA0__USB_TOP_USBOTG_DATA_6
-584 MX35_PAD_SD1_DATA0__GPIO1_8
-585 MX35_PAD_SD1_DATA0__ARM11P_TOP_TRACE_23
-586 MX35_PAD_SD1_DATA1__ESDHC1_DAT1
-587 MX35_PAD_SD1_DATA1__MSHC_DATA_1
-588 MX35_PAD_SD1_DATA1__IPU_DISPB_PAR_RS
-589 MX35_PAD_SD1_DATA1__USB_TOP_USBOTG_DATA_0
-590 MX35_PAD_SD1_DATA1__GPIO1_9
-591 MX35_PAD_SD1_DATA1__ARM11P_TOP_TRACE_24
-592 MX35_PAD_SD1_DATA2__ESDHC1_DAT2
-593 MX35_PAD_SD1_DATA2__MSHC_DATA_2
-594 MX35_PAD_SD1_DATA2__IPU_DISPB_WR
-595 MX35_PAD_SD1_DATA2__USB_TOP_USBOTG_DATA_1
-596 MX35_PAD_SD1_DATA2__GPIO1_10
-597 MX35_PAD_SD1_DATA2__ARM11P_TOP_TRACE_25
-598 MX35_PAD_SD1_DATA3__ESDHC1_DAT3
-599 MX35_PAD_SD1_DATA3__MSHC_DATA_3
-600 MX35_PAD_SD1_DATA3__IPU_DISPB_RD
-601 MX35_PAD_SD1_DATA3__USB_TOP_USBOTG_DATA_2
-602 MX35_PAD_SD1_DATA3__GPIO1_11
-603 MX35_PAD_SD1_DATA3__ARM11P_TOP_TRACE_26
-604 MX35_PAD_SD2_CMD__ESDHC2_CMD
-605 MX35_PAD_SD2_CMD__I2C3_SCL
-606 MX35_PAD_SD2_CMD__ESDHC1_DAT4
-607 MX35_PAD_SD2_CMD__IPU_CSI_D_2
-608 MX35_PAD_SD2_CMD__USB_TOP_USBH2_DATA_4
-609 MX35_PAD_SD2_CMD__GPIO2_0
-610 MX35_PAD_SD2_CMD__SPDIF_SPDIF_OUT1
-611 MX35_PAD_SD2_CMD__IPU_DISPB_D12_VSYNC
-612 MX35_PAD_SD2_CLK__ESDHC2_CLK
-613 MX35_PAD_SD2_CLK__I2C3_SDA
-614 MX35_PAD_SD2_CLK__ESDHC1_DAT5
-615 MX35_PAD_SD2_CLK__IPU_CSI_D_3
-616 MX35_PAD_SD2_CLK__USB_TOP_USBH2_DATA_5
-617 MX35_PAD_SD2_CLK__GPIO2_1
-618 MX35_PAD_SD2_CLK__SPDIF_SPDIF_IN1
-619 MX35_PAD_SD2_CLK__IPU_DISPB_CS2
-620 MX35_PAD_SD2_DATA0__ESDHC2_DAT0
-621 MX35_PAD_SD2_DATA0__UART3_RXD_MUX
-622 MX35_PAD_SD2_DATA0__ESDHC1_DAT6
-623 MX35_PAD_SD2_DATA0__IPU_CSI_D_4
-624 MX35_PAD_SD2_DATA0__USB_TOP_USBH2_DATA_6
-625 MX35_PAD_SD2_DATA0__GPIO2_2
-626 MX35_PAD_SD2_DATA0__SPDIF_SPDIF_EXTCLK
-627 MX35_PAD_SD2_DATA1__ESDHC2_DAT1
-628 MX35_PAD_SD2_DATA1__UART3_TXD_MUX
-629 MX35_PAD_SD2_DATA1__ESDHC1_DAT7
-630 MX35_PAD_SD2_DATA1__IPU_CSI_D_5
-631 MX35_PAD_SD2_DATA1__USB_TOP_USBH2_DATA_0
-632 MX35_PAD_SD2_DATA1__GPIO2_3
-633 MX35_PAD_SD2_DATA2__ESDHC2_DAT2
-634 MX35_PAD_SD2_DATA2__UART3_RTS
-635 MX35_PAD_SD2_DATA2__CAN1_RXCAN
-636 MX35_PAD_SD2_DATA2__IPU_CSI_D_6
-637 MX35_PAD_SD2_DATA2__USB_TOP_USBH2_DATA_1
-638 MX35_PAD_SD2_DATA2__GPIO2_4
-639 MX35_PAD_SD2_DATA3__ESDHC2_DAT3
-640 MX35_PAD_SD2_DATA3__UART3_CTS
-641 MX35_PAD_SD2_DATA3__CAN1_TXCAN
-642 MX35_PAD_SD2_DATA3__IPU_CSI_D_7
-643 MX35_PAD_SD2_DATA3__USB_TOP_USBH2_DATA_2
-644 MX35_PAD_SD2_DATA3__GPIO2_5
-645 MX35_PAD_ATA_CS0__ATA_CS0
-646 MX35_PAD_ATA_CS0__CSPI1_SS3
-647 MX35_PAD_ATA_CS0__IPU_DISPB_CS1
-648 MX35_PAD_ATA_CS0__GPIO2_6
-649 MX35_PAD_ATA_CS0__IPU_DIAGB_0
-650 MX35_PAD_ATA_CS0__ARM11P_TOP_MAX1_HMASTER_0
-651 MX35_PAD_ATA_CS1__ATA_CS1
-652 MX35_PAD_ATA_CS1__IPU_DISPB_CS2
-653 MX35_PAD_ATA_CS1__CSPI2_SS0
-654 MX35_PAD_ATA_CS1__GPIO2_7
-655 MX35_PAD_ATA_CS1__IPU_DIAGB_1
-656 MX35_PAD_ATA_CS1__ARM11P_TOP_MAX1_HMASTER_1
-657 MX35_PAD_ATA_DIOR__ATA_DIOR
-658 MX35_PAD_ATA_DIOR__ESDHC3_DAT0
-659 MX35_PAD_ATA_DIOR__USB_TOP_USBOTG_DIR
-660 MX35_PAD_ATA_DIOR__IPU_DISPB_BE0
-661 MX35_PAD_ATA_DIOR__CSPI2_SS1
-662 MX35_PAD_ATA_DIOR__GPIO2_8
-663 MX35_PAD_ATA_DIOR__IPU_DIAGB_2
-664 MX35_PAD_ATA_DIOR__ARM11P_TOP_MAX1_HMASTER_2
-665 MX35_PAD_ATA_DIOW__ATA_DIOW
-666 MX35_PAD_ATA_DIOW__ESDHC3_DAT1
-667 MX35_PAD_ATA_DIOW__USB_TOP_USBOTG_STP
-668 MX35_PAD_ATA_DIOW__IPU_DISPB_BE1
-669 MX35_PAD_ATA_DIOW__CSPI2_MOSI
-670 MX35_PAD_ATA_DIOW__GPIO2_9
-671 MX35_PAD_ATA_DIOW__IPU_DIAGB_3
-672 MX35_PAD_ATA_DIOW__ARM11P_TOP_MAX1_HMASTER_3
-673 MX35_PAD_ATA_DMACK__ATA_DMACK
-674 MX35_PAD_ATA_DMACK__ESDHC3_DAT2
-675 MX35_PAD_ATA_DMACK__USB_TOP_USBOTG_NXT
-676 MX35_PAD_ATA_DMACK__CSPI2_MISO
-677 MX35_PAD_ATA_DMACK__GPIO2_10
-678 MX35_PAD_ATA_DMACK__IPU_DIAGB_4
-679 MX35_PAD_ATA_DMACK__ARM11P_TOP_MAX0_HMASTER_0
-680 MX35_PAD_ATA_RESET_B__ATA_RESET_B
-681 MX35_PAD_ATA_RESET_B__ESDHC3_DAT3
-682 MX35_PAD_ATA_RESET_B__USB_TOP_USBOTG_DATA_0
-683 MX35_PAD_ATA_RESET_B__IPU_DISPB_SD_D_O
-684 MX35_PAD_ATA_RESET_B__CSPI2_RDY
-685 MX35_PAD_ATA_RESET_B__GPIO2_11
-686 MX35_PAD_ATA_RESET_B__IPU_DIAGB_5
-687 MX35_PAD_ATA_RESET_B__ARM11P_TOP_MAX0_HMASTER_1
-688 MX35_PAD_ATA_IORDY__ATA_IORDY
-689 MX35_PAD_ATA_IORDY__ESDHC3_DAT4
-690 MX35_PAD_ATA_IORDY__USB_TOP_USBOTG_DATA_1
-691 MX35_PAD_ATA_IORDY__IPU_DISPB_SD_D_IO
-692 MX35_PAD_ATA_IORDY__ESDHC2_DAT4
-693 MX35_PAD_ATA_IORDY__GPIO2_12
-694 MX35_PAD_ATA_IORDY__IPU_DIAGB_6
-695 MX35_PAD_ATA_IORDY__ARM11P_TOP_MAX0_HMASTER_2
-696 MX35_PAD_ATA_DATA0__ATA_DATA_0
-697 MX35_PAD_ATA_DATA0__ESDHC3_DAT5
-698 MX35_PAD_ATA_DATA0__USB_TOP_USBOTG_DATA_2
-699 MX35_PAD_ATA_DATA0__IPU_DISPB_D12_VSYNC
-700 MX35_PAD_ATA_DATA0__ESDHC2_DAT5
-701 MX35_PAD_ATA_DATA0__GPIO2_13
-702 MX35_PAD_ATA_DATA0__IPU_DIAGB_7
-703 MX35_PAD_ATA_DATA0__ARM11P_TOP_MAX0_HMASTER_3
-704 MX35_PAD_ATA_DATA1__ATA_DATA_1
-705 MX35_PAD_ATA_DATA1__ESDHC3_DAT6
-706 MX35_PAD_ATA_DATA1__USB_TOP_USBOTG_DATA_3
-707 MX35_PAD_ATA_DATA1__IPU_DISPB_SD_CLK
-708 MX35_PAD_ATA_DATA1__ESDHC2_DAT6
-709 MX35_PAD_ATA_DATA1__GPIO2_14
-710 MX35_PAD_ATA_DATA1__IPU_DIAGB_8
-711 MX35_PAD_ATA_DATA1__ARM11P_TOP_TRACE_27
-712 MX35_PAD_ATA_DATA2__ATA_DATA_2
-713 MX35_PAD_ATA_DATA2__ESDHC3_DAT7
-714 MX35_PAD_ATA_DATA2__USB_TOP_USBOTG_DATA_4
-715 MX35_PAD_ATA_DATA2__IPU_DISPB_SER_RS
-716 MX35_PAD_ATA_DATA2__ESDHC2_DAT7
-717 MX35_PAD_ATA_DATA2__GPIO2_15
-718 MX35_PAD_ATA_DATA2__IPU_DIAGB_9
-719 MX35_PAD_ATA_DATA2__ARM11P_TOP_TRACE_28
-720 MX35_PAD_ATA_DATA3__ATA_DATA_3
-721 MX35_PAD_ATA_DATA3__ESDHC3_CLK
-722 MX35_PAD_ATA_DATA3__USB_TOP_USBOTG_DATA_5
-723 MX35_PAD_ATA_DATA3__CSPI2_SCLK
-724 MX35_PAD_ATA_DATA3__GPIO2_16
-725 MX35_PAD_ATA_DATA3__IPU_DIAGB_10
-726 MX35_PAD_ATA_DATA3__ARM11P_TOP_TRACE_29
-727 MX35_PAD_ATA_DATA4__ATA_DATA_4
-728 MX35_PAD_ATA_DATA4__ESDHC3_CMD
-729 MX35_PAD_ATA_DATA4__USB_TOP_USBOTG_DATA_6
-730 MX35_PAD_ATA_DATA4__GPIO2_17
-731 MX35_PAD_ATA_DATA4__IPU_DIAGB_11
-732 MX35_PAD_ATA_DATA4__ARM11P_TOP_TRACE_30
-733 MX35_PAD_ATA_DATA5__ATA_DATA_5
-734 MX35_PAD_ATA_DATA5__USB_TOP_USBOTG_DATA_7
-735 MX35_PAD_ATA_DATA5__GPIO2_18
-736 MX35_PAD_ATA_DATA5__IPU_DIAGB_12
-737 MX35_PAD_ATA_DATA5__ARM11P_TOP_TRACE_31
-738 MX35_PAD_ATA_DATA6__ATA_DATA_6
-739 MX35_PAD_ATA_DATA6__CAN1_TXCAN
-740 MX35_PAD_ATA_DATA6__UART1_DTR
-741 MX35_PAD_ATA_DATA6__AUDMUX_AUD6_TXD
-742 MX35_PAD_ATA_DATA6__GPIO2_19
-743 MX35_PAD_ATA_DATA6__IPU_DIAGB_13
-744 MX35_PAD_ATA_DATA7__ATA_DATA_7
-745 MX35_PAD_ATA_DATA7__CAN1_RXCAN
-746 MX35_PAD_ATA_DATA7__UART1_DSR
-747 MX35_PAD_ATA_DATA7__AUDMUX_AUD6_RXD
-748 MX35_PAD_ATA_DATA7__GPIO2_20
-749 MX35_PAD_ATA_DATA7__IPU_DIAGB_14
-750 MX35_PAD_ATA_DATA8__ATA_DATA_8
-751 MX35_PAD_ATA_DATA8__UART3_RTS
-752 MX35_PAD_ATA_DATA8__UART1_RI
-753 MX35_PAD_ATA_DATA8__AUDMUX_AUD6_TXC
-754 MX35_PAD_ATA_DATA8__GPIO2_21
-755 MX35_PAD_ATA_DATA8__IPU_DIAGB_15
-756 MX35_PAD_ATA_DATA9__ATA_DATA_9
-757 MX35_PAD_ATA_DATA9__UART3_CTS
-758 MX35_PAD_ATA_DATA9__UART1_DCD
-759 MX35_PAD_ATA_DATA9__AUDMUX_AUD6_TXFS
-760 MX35_PAD_ATA_DATA9__GPIO2_22
-761 MX35_PAD_ATA_DATA9__IPU_DIAGB_16
-762 MX35_PAD_ATA_DATA10__ATA_DATA_10
-763 MX35_PAD_ATA_DATA10__UART3_RXD_MUX
-764 MX35_PAD_ATA_DATA10__AUDMUX_AUD6_RXC
-765 MX35_PAD_ATA_DATA10__GPIO2_23
-766 MX35_PAD_ATA_DATA10__IPU_DIAGB_17
-767 MX35_PAD_ATA_DATA11__ATA_DATA_11
-768 MX35_PAD_ATA_DATA11__UART3_TXD_MUX
-769 MX35_PAD_ATA_DATA11__AUDMUX_AUD6_RXFS
-770 MX35_PAD_ATA_DATA11__GPIO2_24
-771 MX35_PAD_ATA_DATA11__IPU_DIAGB_18
-772 MX35_PAD_ATA_DATA12__ATA_DATA_12
-773 MX35_PAD_ATA_DATA12__I2C3_SCL
-774 MX35_PAD_ATA_DATA12__GPIO2_25
-775 MX35_PAD_ATA_DATA12__IPU_DIAGB_19
-776 MX35_PAD_ATA_DATA13__ATA_DATA_13
-777 MX35_PAD_ATA_DATA13__I2C3_SDA
-778 MX35_PAD_ATA_DATA13__GPIO2_26
-779 MX35_PAD_ATA_DATA13__IPU_DIAGB_20
-780 MX35_PAD_ATA_DATA14__ATA_DATA_14
-781 MX35_PAD_ATA_DATA14__IPU_CSI_D_0
-782 MX35_PAD_ATA_DATA14__KPP_ROW_0
-783 MX35_PAD_ATA_DATA14__GPIO2_27
-784 MX35_PAD_ATA_DATA14__IPU_DIAGB_21
-785 MX35_PAD_ATA_DATA15__ATA_DATA_15
-786 MX35_PAD_ATA_DATA15__IPU_CSI_D_1
-787 MX35_PAD_ATA_DATA15__KPP_ROW_1
-788 MX35_PAD_ATA_DATA15__GPIO2_28
-789 MX35_PAD_ATA_DATA15__IPU_DIAGB_22
-790 MX35_PAD_ATA_INTRQ__ATA_INTRQ
-791 MX35_PAD_ATA_INTRQ__IPU_CSI_D_2
-792 MX35_PAD_ATA_INTRQ__KPP_ROW_2
-793 MX35_PAD_ATA_INTRQ__GPIO2_29
-794 MX35_PAD_ATA_INTRQ__IPU_DIAGB_23
-795 MX35_PAD_ATA_BUFF_EN__ATA_BUFFER_EN
-796 MX35_PAD_ATA_BUFF_EN__IPU_CSI_D_3
-797 MX35_PAD_ATA_BUFF_EN__KPP_ROW_3
-798 MX35_PAD_ATA_BUFF_EN__GPIO2_30
-799 MX35_PAD_ATA_BUFF_EN__IPU_DIAGB_24
-800 MX35_PAD_ATA_DMARQ__ATA_DMARQ
-801 MX35_PAD_ATA_DMARQ__IPU_CSI_D_4
-802 MX35_PAD_ATA_DMARQ__KPP_COL_0
-803 MX35_PAD_ATA_DMARQ__GPIO2_31
-804 MX35_PAD_ATA_DMARQ__IPU_DIAGB_25
-805 MX35_PAD_ATA_DMARQ__ECT_CTI_TRIG_IN1_4
-806 MX35_PAD_ATA_DA0__ATA_DA_0
-807 MX35_PAD_ATA_DA0__IPU_CSI_D_5
-808 MX35_PAD_ATA_DA0__KPP_COL_1
-809 MX35_PAD_ATA_DA0__GPIO3_0
-810 MX35_PAD_ATA_DA0__IPU_DIAGB_26
-811 MX35_PAD_ATA_DA0__ECT_CTI_TRIG_IN1_5
-812 MX35_PAD_ATA_DA1__ATA_DA_1
-813 MX35_PAD_ATA_DA1__IPU_CSI_D_6
-814 MX35_PAD_ATA_DA1__KPP_COL_2
-815 MX35_PAD_ATA_DA1__GPIO3_1
-816 MX35_PAD_ATA_DA1__IPU_DIAGB_27
-817 MX35_PAD_ATA_DA1__ECT_CTI_TRIG_IN1_6
-818 MX35_PAD_ATA_DA2__ATA_DA_2
-819 MX35_PAD_ATA_DA2__IPU_CSI_D_7
-820 MX35_PAD_ATA_DA2__KPP_COL_3
-821 MX35_PAD_ATA_DA2__GPIO3_2
-822 MX35_PAD_ATA_DA2__IPU_DIAGB_28
-823 MX35_PAD_ATA_DA2__ECT_CTI_TRIG_IN1_7
-824 MX35_PAD_MLB_CLK__MLB_MLBCLK
-825 MX35_PAD_MLB_CLK__GPIO3_3
-826 MX35_PAD_MLB_DAT__MLB_MLBDAT
-827 MX35_PAD_MLB_DAT__GPIO3_4
-828 MX35_PAD_MLB_SIG__MLB_MLBSIG
-829 MX35_PAD_MLB_SIG__GPIO3_5
-830 MX35_PAD_FEC_TX_CLK__FEC_TX_CLK
-831 MX35_PAD_FEC_TX_CLK__ESDHC1_DAT4
-832 MX35_PAD_FEC_TX_CLK__UART3_RXD_MUX
-833 MX35_PAD_FEC_TX_CLK__USB_TOP_USBH2_DIR
-834 MX35_PAD_FEC_TX_CLK__CSPI2_MOSI
-835 MX35_PAD_FEC_TX_CLK__GPIO3_6
-836 MX35_PAD_FEC_TX_CLK__IPU_DISPB_D12_VSYNC
-837 MX35_PAD_FEC_TX_CLK__ARM11P_TOP_EVNTBUS_0
-838 MX35_PAD_FEC_RX_CLK__FEC_RX_CLK
-839 MX35_PAD_FEC_RX_CLK__ESDHC1_DAT5
-840 MX35_PAD_FEC_RX_CLK__UART3_TXD_MUX
-841 MX35_PAD_FEC_RX_CLK__USB_TOP_USBH2_STP
-842 MX35_PAD_FEC_RX_CLK__CSPI2_MISO
-843 MX35_PAD_FEC_RX_CLK__GPIO3_7
-844 MX35_PAD_FEC_RX_CLK__IPU_DISPB_SD_D_I
-845 MX35_PAD_FEC_RX_CLK__ARM11P_TOP_EVNTBUS_1
-846 MX35_PAD_FEC_RX_DV__FEC_RX_DV
-847 MX35_PAD_FEC_RX_DV__ESDHC1_DAT6
-848 MX35_PAD_FEC_RX_DV__UART3_RTS
-849 MX35_PAD_FEC_RX_DV__USB_TOP_USBH2_NXT
-850 MX35_PAD_FEC_RX_DV__CSPI2_SCLK
-851 MX35_PAD_FEC_RX_DV__GPIO3_8
-852 MX35_PAD_FEC_RX_DV__IPU_DISPB_SD_CLK
-853 MX35_PAD_FEC_RX_DV__ARM11P_TOP_EVNTBUS_2
-854 MX35_PAD_FEC_COL__FEC_COL
-855 MX35_PAD_FEC_COL__ESDHC1_DAT7
-856 MX35_PAD_FEC_COL__UART3_CTS
-857 MX35_PAD_FEC_COL__USB_TOP_USBH2_DATA_0
-858 MX35_PAD_FEC_COL__CSPI2_RDY
-859 MX35_PAD_FEC_COL__GPIO3_9
-860 MX35_PAD_FEC_COL__IPU_DISPB_SER_RS
-861 MX35_PAD_FEC_COL__ARM11P_TOP_EVNTBUS_3
-862 MX35_PAD_FEC_RDATA0__FEC_RDATA_0
-863 MX35_PAD_FEC_RDATA0__PWM_PWMO
-864 MX35_PAD_FEC_RDATA0__UART3_DTR
-865 MX35_PAD_FEC_RDATA0__USB_TOP_USBH2_DATA_1
-866 MX35_PAD_FEC_RDATA0__CSPI2_SS0
-867 MX35_PAD_FEC_RDATA0__GPIO3_10
-868 MX35_PAD_FEC_RDATA0__IPU_DISPB_CS1
-869 MX35_PAD_FEC_RDATA0__ARM11P_TOP_EVNTBUS_4
-870 MX35_PAD_FEC_TDATA0__FEC_TDATA_0
-871 MX35_PAD_FEC_TDATA0__SPDIF_SPDIF_OUT1
-872 MX35_PAD_FEC_TDATA0__UART3_DSR
-873 MX35_PAD_FEC_TDATA0__USB_TOP_USBH2_DATA_2
-874 MX35_PAD_FEC_TDATA0__CSPI2_SS1
-875 MX35_PAD_FEC_TDATA0__GPIO3_11
-876 MX35_PAD_FEC_TDATA0__IPU_DISPB_CS0
-877 MX35_PAD_FEC_TDATA0__ARM11P_TOP_EVNTBUS_5
-878 MX35_PAD_FEC_TX_EN__FEC_TX_EN
-879 MX35_PAD_FEC_TX_EN__SPDIF_SPDIF_IN1
-880 MX35_PAD_FEC_TX_EN__UART3_RI
-881 MX35_PAD_FEC_TX_EN__USB_TOP_USBH2_DATA_3
-882 MX35_PAD_FEC_TX_EN__GPIO3_12
-883 MX35_PAD_FEC_TX_EN__IPU_DISPB_PAR_RS
-884 MX35_PAD_FEC_TX_EN__ARM11P_TOP_EVNTBUS_6
-885 MX35_PAD_FEC_MDC__FEC_MDC
-886 MX35_PAD_FEC_MDC__CAN2_TXCAN
-887 MX35_PAD_FEC_MDC__UART3_DCD
-888 MX35_PAD_FEC_MDC__USB_TOP_USBH2_DATA_4
-889 MX35_PAD_FEC_MDC__GPIO3_13
-890 MX35_PAD_FEC_MDC__IPU_DISPB_WR
-891 MX35_PAD_FEC_MDC__ARM11P_TOP_EVNTBUS_7
-892 MX35_PAD_FEC_MDIO__FEC_MDIO
-893 MX35_PAD_FEC_MDIO__CAN2_RXCAN
-894 MX35_PAD_FEC_MDIO__USB_TOP_USBH2_DATA_5
-895 MX35_PAD_FEC_MDIO__GPIO3_14
-896 MX35_PAD_FEC_MDIO__IPU_DISPB_RD
-897 MX35_PAD_FEC_MDIO__ARM11P_TOP_EVNTBUS_8
-898 MX35_PAD_FEC_TX_ERR__FEC_TX_ERR
-899 MX35_PAD_FEC_TX_ERR__OWIRE_LINE
-900 MX35_PAD_FEC_TX_ERR__SPDIF_SPDIF_EXTCLK
-901 MX35_PAD_FEC_TX_ERR__USB_TOP_USBH2_DATA_6
-902 MX35_PAD_FEC_TX_ERR__GPIO3_15
-903 MX35_PAD_FEC_TX_ERR__IPU_DISPB_D0_VSYNC
-904 MX35_PAD_FEC_TX_ERR__ARM11P_TOP_EVNTBUS_9
-905 MX35_PAD_FEC_RX_ERR__FEC_RX_ERR
-906 MX35_PAD_FEC_RX_ERR__IPU_CSI_D_0
-907 MX35_PAD_FEC_RX_ERR__USB_TOP_USBH2_DATA_7
-908 MX35_PAD_FEC_RX_ERR__KPP_COL_4
-909 MX35_PAD_FEC_RX_ERR__GPIO3_16
-910 MX35_PAD_FEC_RX_ERR__IPU_DISPB_SD_D_IO
-911 MX35_PAD_FEC_CRS__FEC_CRS
-912 MX35_PAD_FEC_CRS__IPU_CSI_D_1
-913 MX35_PAD_FEC_CRS__USB_TOP_USBH2_PWR
-914 MX35_PAD_FEC_CRS__KPP_COL_5
-915 MX35_PAD_FEC_CRS__GPIO3_17
-916 MX35_PAD_FEC_CRS__IPU_FLASH_STROBE
-917 MX35_PAD_FEC_RDATA1__FEC_RDATA_1
-918 MX35_PAD_FEC_RDATA1__IPU_CSI_D_2
-919 MX35_PAD_FEC_RDATA1__AUDMUX_AUD6_RXC
-920 MX35_PAD_FEC_RDATA1__USB_TOP_USBH2_OC
-921 MX35_PAD_FEC_RDATA1__KPP_COL_6
-922 MX35_PAD_FEC_RDATA1__GPIO3_18
-923 MX35_PAD_FEC_RDATA1__IPU_DISPB_BE0
-924 MX35_PAD_FEC_TDATA1__FEC_TDATA_1
-925 MX35_PAD_FEC_TDATA1__IPU_CSI_D_3
-926 MX35_PAD_FEC_TDATA1__AUDMUX_AUD6_RXFS
-927 MX35_PAD_FEC_TDATA1__KPP_COL_7
-928 MX35_PAD_FEC_TDATA1__GPIO3_19
-929 MX35_PAD_FEC_TDATA1__IPU_DISPB_BE1
-930 MX35_PAD_FEC_RDATA2__FEC_RDATA_2
-931 MX35_PAD_FEC_RDATA2__IPU_CSI_D_4
-932 MX35_PAD_FEC_RDATA2__AUDMUX_AUD6_TXD
-933 MX35_PAD_FEC_RDATA2__KPP_ROW_4
-934 MX35_PAD_FEC_RDATA2__GPIO3_20
-935 MX35_PAD_FEC_TDATA2__FEC_TDATA_2
-936 MX35_PAD_FEC_TDATA2__IPU_CSI_D_5
-937 MX35_PAD_FEC_TDATA2__AUDMUX_AUD6_RXD
-938 MX35_PAD_FEC_TDATA2__KPP_ROW_5
-939 MX35_PAD_FEC_TDATA2__GPIO3_21
-940 MX35_PAD_FEC_RDATA3__FEC_RDATA_3
-941 MX35_PAD_FEC_RDATA3__IPU_CSI_D_6
-942 MX35_PAD_FEC_RDATA3__AUDMUX_AUD6_TXC
-943 MX35_PAD_FEC_RDATA3__KPP_ROW_6
-944 MX35_PAD_FEC_RDATA3__GPIO3_22
-945 MX35_PAD_FEC_TDATA3__FEC_TDATA_3
-946 MX35_PAD_FEC_TDATA3__IPU_CSI_D_7
-947 MX35_PAD_FEC_TDATA3__AUDMUX_AUD6_TXFS
-948 MX35_PAD_FEC_TDATA3__KPP_ROW_7
-949 MX35_PAD_FEC_TDATA3__GPIO3_23
-950 MX35_PAD_EXT_ARMCLK__CCM_EXT_ARMCLK
-951 MX35_PAD_TEST_MODE__TCU_TEST_MODE
+Refer to imx35-pinfunc.h in device tree source folder for all available
+imx35 PIN_FUNC_ID.
diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,imx51-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/fsl,imx51-pinctrl.txt
index b96fa4c..4d1408f 100644
--- a/Documentation/devicetree/bindings/pinctrl/fsl,imx51-pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/fsl,imx51-pinctrl.txt
@@ -28,760 +28,5 @@ PAD_CTL_DSE_MAX			(3 << 1)
 PAD_CTL_SRE_FAST		(1 << 0)
 PAD_CTL_SRE_SLOW		(0 << 0)
 
-See below for available PIN_FUNC_ID for imx51:
-MX51_PAD_EIM_D16__AUD4_RXFS			0
-MX51_PAD_EIM_D16__AUD5_TXD			1
-MX51_PAD_EIM_D16__EIM_D16			2
-MX51_PAD_EIM_D16__GPIO2_0			3
-MX51_PAD_EIM_D16__I2C1_SDA			4
-MX51_PAD_EIM_D16__UART2_CTS			5
-MX51_PAD_EIM_D16__USBH2_DATA0			6
-MX51_PAD_EIM_D17__AUD5_RXD			7
-MX51_PAD_EIM_D17__EIM_D17			8
-MX51_PAD_EIM_D17__GPIO2_1			9
-MX51_PAD_EIM_D17__UART2_RXD			10
-MX51_PAD_EIM_D17__UART3_CTS			11
-MX51_PAD_EIM_D17__USBH2_DATA1			12
-MX51_PAD_EIM_D18__AUD5_TXC			13
-MX51_PAD_EIM_D18__EIM_D18			14
-MX51_PAD_EIM_D18__GPIO2_2			15
-MX51_PAD_EIM_D18__UART2_TXD			16
-MX51_PAD_EIM_D18__UART3_RTS			17
-MX51_PAD_EIM_D18__USBH2_DATA2			18
-MX51_PAD_EIM_D19__AUD4_RXC			19
-MX51_PAD_EIM_D19__AUD5_TXFS			20
-MX51_PAD_EIM_D19__EIM_D19			21
-MX51_PAD_EIM_D19__GPIO2_3			22
-MX51_PAD_EIM_D19__I2C1_SCL			23
-MX51_PAD_EIM_D19__UART2_RTS			24
-MX51_PAD_EIM_D19__USBH2_DATA3			25
-MX51_PAD_EIM_D20__AUD4_TXD			26
-MX51_PAD_EIM_D20__EIM_D20			27
-MX51_PAD_EIM_D20__GPIO2_4			28
-MX51_PAD_EIM_D20__SRTC_ALARM_DEB		29
-MX51_PAD_EIM_D20__USBH2_DATA4			30
-MX51_PAD_EIM_D21__AUD4_RXD			31
-MX51_PAD_EIM_D21__EIM_D21			32
-MX51_PAD_EIM_D21__GPIO2_5			33
-MX51_PAD_EIM_D21__SRTC_ALARM_DEB		34
-MX51_PAD_EIM_D21__USBH2_DATA5			35
-MX51_PAD_EIM_D22__AUD4_TXC			36
-MX51_PAD_EIM_D22__EIM_D22			37
-MX51_PAD_EIM_D22__GPIO2_6			38
-MX51_PAD_EIM_D22__USBH2_DATA6			39
-MX51_PAD_EIM_D23__AUD4_TXFS			40
-MX51_PAD_EIM_D23__EIM_D23			41
-MX51_PAD_EIM_D23__GPIO2_7			42
-MX51_PAD_EIM_D23__SPDIF_OUT1			43
-MX51_PAD_EIM_D23__USBH2_DATA7			44
-MX51_PAD_EIM_D24__AUD6_RXFS			45
-MX51_PAD_EIM_D24__EIM_D24			46
-MX51_PAD_EIM_D24__GPIO2_8			47
-MX51_PAD_EIM_D24__I2C2_SDA			48
-MX51_PAD_EIM_D24__UART3_CTS			49
-MX51_PAD_EIM_D24__USBOTG_DATA0			50
-MX51_PAD_EIM_D25__EIM_D25			51
-MX51_PAD_EIM_D25__KEY_COL6			52
-MX51_PAD_EIM_D25__UART2_CTS			53
-MX51_PAD_EIM_D25__UART3_RXD			54
-MX51_PAD_EIM_D25__USBOTG_DATA1			55
-MX51_PAD_EIM_D26__EIM_D26			56
-MX51_PAD_EIM_D26__KEY_COL7			57
-MX51_PAD_EIM_D26__UART2_RTS			58
-MX51_PAD_EIM_D26__UART3_TXD			59
-MX51_PAD_EIM_D26__USBOTG_DATA2			60
-MX51_PAD_EIM_D27__AUD6_RXC			61
-MX51_PAD_EIM_D27__EIM_D27			62
-MX51_PAD_EIM_D27__GPIO2_9			63
-MX51_PAD_EIM_D27__I2C2_SCL			64
-MX51_PAD_EIM_D27__UART3_RTS			65
-MX51_PAD_EIM_D27__USBOTG_DATA3			66
-MX51_PAD_EIM_D28__AUD6_TXD			67
-MX51_PAD_EIM_D28__EIM_D28			68
-MX51_PAD_EIM_D28__KEY_ROW4			69
-MX51_PAD_EIM_D28__USBOTG_DATA4			70
-MX51_PAD_EIM_D29__AUD6_RXD			71
-MX51_PAD_EIM_D29__EIM_D29			72
-MX51_PAD_EIM_D29__KEY_ROW5			73
-MX51_PAD_EIM_D29__USBOTG_DATA5			74
-MX51_PAD_EIM_D30__AUD6_TXC			75
-MX51_PAD_EIM_D30__EIM_D30			76
-MX51_PAD_EIM_D30__KEY_ROW6			77
-MX51_PAD_EIM_D30__USBOTG_DATA6			78
-MX51_PAD_EIM_D31__AUD6_TXFS			79
-MX51_PAD_EIM_D31__EIM_D31			80
-MX51_PAD_EIM_D31__KEY_ROW7			81
-MX51_PAD_EIM_D31__USBOTG_DATA7			82
-MX51_PAD_EIM_A16__EIM_A16			83
-MX51_PAD_EIM_A16__GPIO2_10			84
-MX51_PAD_EIM_A16__OSC_FREQ_SEL0			85
-MX51_PAD_EIM_A17__EIM_A17			86
-MX51_PAD_EIM_A17__GPIO2_11			87
-MX51_PAD_EIM_A17__OSC_FREQ_SEL1			88
-MX51_PAD_EIM_A18__BOOT_LPB0			89
-MX51_PAD_EIM_A18__EIM_A18			90
-MX51_PAD_EIM_A18__GPIO2_12			91
-MX51_PAD_EIM_A19__BOOT_LPB1			92
-MX51_PAD_EIM_A19__EIM_A19			93
-MX51_PAD_EIM_A19__GPIO2_13			94
-MX51_PAD_EIM_A20__BOOT_UART_SRC0		95
-MX51_PAD_EIM_A20__EIM_A20			96
-MX51_PAD_EIM_A20__GPIO2_14			97
-MX51_PAD_EIM_A21__BOOT_UART_SRC1		98
-MX51_PAD_EIM_A21__EIM_A21			99
-MX51_PAD_EIM_A21__GPIO2_15			100
-MX51_PAD_EIM_A22__EIM_A22			101
-MX51_PAD_EIM_A22__GPIO2_16			102
-MX51_PAD_EIM_A23__BOOT_HPN_EN			103
-MX51_PAD_EIM_A23__EIM_A23			104
-MX51_PAD_EIM_A23__GPIO2_17			105
-MX51_PAD_EIM_A24__EIM_A24			106
-MX51_PAD_EIM_A24__GPIO2_18			107
-MX51_PAD_EIM_A24__USBH2_CLK			108
-MX51_PAD_EIM_A25__DISP1_PIN4			109
-MX51_PAD_EIM_A25__EIM_A25			110
-MX51_PAD_EIM_A25__GPIO2_19			111
-MX51_PAD_EIM_A25__USBH2_DIR			112
-MX51_PAD_EIM_A26__CSI1_DATA_EN			113
-MX51_PAD_EIM_A26__DISP2_EXT_CLK			114
-MX51_PAD_EIM_A26__EIM_A26			115
-MX51_PAD_EIM_A26__GPIO2_20			116
-MX51_PAD_EIM_A26__USBH2_STP			117
-MX51_PAD_EIM_A27__CSI2_DATA_EN			118
-MX51_PAD_EIM_A27__DISP1_PIN1			119
-MX51_PAD_EIM_A27__EIM_A27			120
-MX51_PAD_EIM_A27__GPIO2_21			121
-MX51_PAD_EIM_A27__USBH2_NXT			122
-MX51_PAD_EIM_EB0__EIM_EB0			123
-MX51_PAD_EIM_EB1__EIM_EB1			124
-MX51_PAD_EIM_EB2__AUD5_RXFS			125
-MX51_PAD_EIM_EB2__CSI1_D2			126
-MX51_PAD_EIM_EB2__EIM_EB2			127
-MX51_PAD_EIM_EB2__FEC_MDIO			128
-MX51_PAD_EIM_EB2__GPIO2_22			129
-MX51_PAD_EIM_EB2__GPT_CMPOUT1			130
-MX51_PAD_EIM_EB3__AUD5_RXC			131
-MX51_PAD_EIM_EB3__CSI1_D3			132
-MX51_PAD_EIM_EB3__EIM_EB3			133
-MX51_PAD_EIM_EB3__FEC_RDATA1			134
-MX51_PAD_EIM_EB3__GPIO2_23			135
-MX51_PAD_EIM_EB3__GPT_CMPOUT2			136
-MX51_PAD_EIM_OE__EIM_OE				137
-MX51_PAD_EIM_OE__GPIO2_24			138
-MX51_PAD_EIM_CS0__EIM_CS0			139
-MX51_PAD_EIM_CS0__GPIO2_25			140
-MX51_PAD_EIM_CS1__EIM_CS1			141
-MX51_PAD_EIM_CS1__GPIO2_26			142
-MX51_PAD_EIM_CS2__AUD5_TXD			143
-MX51_PAD_EIM_CS2__CSI1_D4			144
-MX51_PAD_EIM_CS2__EIM_CS2			145
-MX51_PAD_EIM_CS2__FEC_RDATA2			146
-MX51_PAD_EIM_CS2__GPIO2_27			147
-MX51_PAD_EIM_CS2__USBOTG_STP			148
-MX51_PAD_EIM_CS3__AUD5_RXD			149
-MX51_PAD_EIM_CS3__CSI1_D5			150
-MX51_PAD_EIM_CS3__EIM_CS3			151
-MX51_PAD_EIM_CS3__FEC_RDATA3			152
-MX51_PAD_EIM_CS3__GPIO2_28			153
-MX51_PAD_EIM_CS3__USBOTG_NXT			154
-MX51_PAD_EIM_CS4__AUD5_TXC			155
-MX51_PAD_EIM_CS4__CSI1_D6			156
-MX51_PAD_EIM_CS4__EIM_CS4			157
-MX51_PAD_EIM_CS4__FEC_RX_ER			158
-MX51_PAD_EIM_CS4__GPIO2_29			159
-MX51_PAD_EIM_CS4__USBOTG_CLK			160
-MX51_PAD_EIM_CS5__AUD5_TXFS			161
-MX51_PAD_EIM_CS5__CSI1_D7			162
-MX51_PAD_EIM_CS5__DISP1_EXT_CLK			163
-MX51_PAD_EIM_CS5__EIM_CS5			164
-MX51_PAD_EIM_CS5__FEC_CRS			165
-MX51_PAD_EIM_CS5__GPIO2_30			166
-MX51_PAD_EIM_CS5__USBOTG_DIR			167
-MX51_PAD_EIM_DTACK__EIM_DTACK			168
-MX51_PAD_EIM_DTACK__GPIO2_31			169
-MX51_PAD_EIM_LBA__EIM_LBA			170
-MX51_PAD_EIM_LBA__GPIO3_1			171
-MX51_PAD_EIM_CRE__EIM_CRE			172
-MX51_PAD_EIM_CRE__GPIO3_2			173
-MX51_PAD_DRAM_CS1__DRAM_CS1			174
-MX51_PAD_NANDF_WE_B__GPIO3_3			175
-MX51_PAD_NANDF_WE_B__NANDF_WE_B			176
-MX51_PAD_NANDF_WE_B__PATA_DIOW			177
-MX51_PAD_NANDF_WE_B__SD3_DATA0			178
-MX51_PAD_NANDF_RE_B__GPIO3_4			179
-MX51_PAD_NANDF_RE_B__NANDF_RE_B			180
-MX51_PAD_NANDF_RE_B__PATA_DIOR			181
-MX51_PAD_NANDF_RE_B__SD3_DATA1			182
-MX51_PAD_NANDF_ALE__GPIO3_5			183
-MX51_PAD_NANDF_ALE__NANDF_ALE			184
-MX51_PAD_NANDF_ALE__PATA_BUFFER_EN		185
-MX51_PAD_NANDF_CLE__GPIO3_6			186
-MX51_PAD_NANDF_CLE__NANDF_CLE			187
-MX51_PAD_NANDF_CLE__PATA_RESET_B		188
-MX51_PAD_NANDF_WP_B__GPIO3_7			189
-MX51_PAD_NANDF_WP_B__NANDF_WP_B			190
-MX51_PAD_NANDF_WP_B__PATA_DMACK			191
-MX51_PAD_NANDF_WP_B__SD3_DATA2			192
-MX51_PAD_NANDF_RB0__ECSPI2_SS1			193
-MX51_PAD_NANDF_RB0__GPIO3_8			194
-MX51_PAD_NANDF_RB0__NANDF_RB0			195
-MX51_PAD_NANDF_RB0__PATA_DMARQ			196
-MX51_PAD_NANDF_RB0__SD3_DATA3			197
-MX51_PAD_NANDF_RB1__CSPI_MOSI			198
-MX51_PAD_NANDF_RB1__ECSPI2_RDY			199
-MX51_PAD_NANDF_RB1__GPIO3_9			200
-MX51_PAD_NANDF_RB1__NANDF_RB1			201
-MX51_PAD_NANDF_RB1__PATA_IORDY			202
-MX51_PAD_NANDF_RB1__SD4_CMD			203
-MX51_PAD_NANDF_RB2__DISP2_WAIT			204
-MX51_PAD_NANDF_RB2__ECSPI2_SCLK			205
-MX51_PAD_NANDF_RB2__FEC_COL			206
-MX51_PAD_NANDF_RB2__GPIO3_10			207
-MX51_PAD_NANDF_RB2__NANDF_RB2			208
-MX51_PAD_NANDF_RB2__USBH3_H3_DP			209
-MX51_PAD_NANDF_RB2__USBH3_NXT			210
-MX51_PAD_NANDF_RB3__DISP1_WAIT			211
-MX51_PAD_NANDF_RB3__ECSPI2_MISO			212
-MX51_PAD_NANDF_RB3__FEC_RX_CLK			213
-MX51_PAD_NANDF_RB3__GPIO3_11			214
-MX51_PAD_NANDF_RB3__NANDF_RB3			215
-MX51_PAD_NANDF_RB3__USBH3_CLK			216
-MX51_PAD_NANDF_RB3__USBH3_H3_DM			217
-MX51_PAD_GPIO_NAND__GPIO_NAND			218
-MX51_PAD_GPIO_NAND__PATA_INTRQ			219
-MX51_PAD_NANDF_CS0__GPIO3_16			220
-MX51_PAD_NANDF_CS0__NANDF_CS0			221
-MX51_PAD_NANDF_CS1__GPIO3_17			222
-MX51_PAD_NANDF_CS1__NANDF_CS1			223
-MX51_PAD_NANDF_CS2__CSPI_SCLK			224
-MX51_PAD_NANDF_CS2__FEC_TX_ER			225
-MX51_PAD_NANDF_CS2__GPIO3_18			226
-MX51_PAD_NANDF_CS2__NANDF_CS2			227
-MX51_PAD_NANDF_CS2__PATA_CS_0			228
-MX51_PAD_NANDF_CS2__SD4_CLK			229
-MX51_PAD_NANDF_CS2__USBH3_H1_DP			230
-MX51_PAD_NANDF_CS3__FEC_MDC			231
-MX51_PAD_NANDF_CS3__GPIO3_19			232
-MX51_PAD_NANDF_CS3__NANDF_CS3			233
-MX51_PAD_NANDF_CS3__PATA_CS_1			234
-MX51_PAD_NANDF_CS3__SD4_DAT0			235
-MX51_PAD_NANDF_CS3__USBH3_H1_DM			236
-MX51_PAD_NANDF_CS4__FEC_TDATA1			237
-MX51_PAD_NANDF_CS4__GPIO3_20			238
-MX51_PAD_NANDF_CS4__NANDF_CS4			239
-MX51_PAD_NANDF_CS4__PATA_DA_0			240
-MX51_PAD_NANDF_CS4__SD4_DAT1			241
-MX51_PAD_NANDF_CS4__USBH3_STP			242
-MX51_PAD_NANDF_CS5__FEC_TDATA2			243
-MX51_PAD_NANDF_CS5__GPIO3_21			244
-MX51_PAD_NANDF_CS5__NANDF_CS5			245
-MX51_PAD_NANDF_CS5__PATA_DA_1			246
-MX51_PAD_NANDF_CS5__SD4_DAT2			247
-MX51_PAD_NANDF_CS5__USBH3_DIR			248
-MX51_PAD_NANDF_CS6__CSPI_SS3			249
-MX51_PAD_NANDF_CS6__FEC_TDATA3			250
-MX51_PAD_NANDF_CS6__GPIO3_22			251
-MX51_PAD_NANDF_CS6__NANDF_CS6			252
-MX51_PAD_NANDF_CS6__PATA_DA_2			253
-MX51_PAD_NANDF_CS6__SD4_DAT3			254
-MX51_PAD_NANDF_CS7__FEC_TX_EN			255
-MX51_PAD_NANDF_CS7__GPIO3_23			256
-MX51_PAD_NANDF_CS7__NANDF_CS7			257
-MX51_PAD_NANDF_CS7__SD3_CLK			258
-MX51_PAD_NANDF_RDY_INT__ECSPI2_SS0		259
-MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK		260
-MX51_PAD_NANDF_RDY_INT__GPIO3_24		261
-MX51_PAD_NANDF_RDY_INT__NANDF_RDY_INT		262
-MX51_PAD_NANDF_RDY_INT__SD3_CMD			263
-MX51_PAD_NANDF_D15__ECSPI2_MOSI			264
-MX51_PAD_NANDF_D15__GPIO3_25			265
-MX51_PAD_NANDF_D15__NANDF_D15			266
-MX51_PAD_NANDF_D15__PATA_DATA15			267
-MX51_PAD_NANDF_D15__SD3_DAT7			268
-MX51_PAD_NANDF_D14__ECSPI2_SS3			269
-MX51_PAD_NANDF_D14__GPIO3_26			270
-MX51_PAD_NANDF_D14__NANDF_D14			271
-MX51_PAD_NANDF_D14__PATA_DATA14			272
-MX51_PAD_NANDF_D14__SD3_DAT6			273
-MX51_PAD_NANDF_D13__ECSPI2_SS2			274
-MX51_PAD_NANDF_D13__GPIO3_27			275
-MX51_PAD_NANDF_D13__NANDF_D13			276
-MX51_PAD_NANDF_D13__PATA_DATA13			277
-MX51_PAD_NANDF_D13__SD3_DAT5			278
-MX51_PAD_NANDF_D12__ECSPI2_SS1			279
-MX51_PAD_NANDF_D12__GPIO3_28			280
-MX51_PAD_NANDF_D12__NANDF_D12			281
-MX51_PAD_NANDF_D12__PATA_DATA12			282
-MX51_PAD_NANDF_D12__SD3_DAT4			283
-MX51_PAD_NANDF_D11__FEC_RX_DV			284
-MX51_PAD_NANDF_D11__GPIO3_29			285
-MX51_PAD_NANDF_D11__NANDF_D11			286
-MX51_PAD_NANDF_D11__PATA_DATA11			287
-MX51_PAD_NANDF_D11__SD3_DATA3			288
-MX51_PAD_NANDF_D10__GPIO3_30			289
-MX51_PAD_NANDF_D10__NANDF_D10			290
-MX51_PAD_NANDF_D10__PATA_DATA10			291
-MX51_PAD_NANDF_D10__SD3_DATA2			292
-MX51_PAD_NANDF_D9__FEC_RDATA0			293
-MX51_PAD_NANDF_D9__GPIO3_31			294
-MX51_PAD_NANDF_D9__NANDF_D9			295
-MX51_PAD_NANDF_D9__PATA_DATA9			296
-MX51_PAD_NANDF_D9__SD3_DATA1			297
-MX51_PAD_NANDF_D8__FEC_TDATA0			298
-MX51_PAD_NANDF_D8__GPIO4_0			299
-MX51_PAD_NANDF_D8__NANDF_D8			300
-MX51_PAD_NANDF_D8__PATA_DATA8			301
-MX51_PAD_NANDF_D8__SD3_DATA0			302
-MX51_PAD_NANDF_D7__GPIO4_1			303
-MX51_PAD_NANDF_D7__NANDF_D7			304
-MX51_PAD_NANDF_D7__PATA_DATA7			305
-MX51_PAD_NANDF_D7__USBH3_DATA0			306
-MX51_PAD_NANDF_D6__GPIO4_2			307
-MX51_PAD_NANDF_D6__NANDF_D6			308
-MX51_PAD_NANDF_D6__PATA_DATA6			309
-MX51_PAD_NANDF_D6__SD4_LCTL			310
-MX51_PAD_NANDF_D6__USBH3_DATA1			311
-MX51_PAD_NANDF_D5__GPIO4_3			312
-MX51_PAD_NANDF_D5__NANDF_D5			313
-MX51_PAD_NANDF_D5__PATA_DATA5			314
-MX51_PAD_NANDF_D5__SD4_WP			315
-MX51_PAD_NANDF_D5__USBH3_DATA2			316
-MX51_PAD_NANDF_D4__GPIO4_4			317
-MX51_PAD_NANDF_D4__NANDF_D4			318
-MX51_PAD_NANDF_D4__PATA_DATA4			319
-MX51_PAD_NANDF_D4__SD4_CD			320
-MX51_PAD_NANDF_D4__USBH3_DATA3			321
-MX51_PAD_NANDF_D3__GPIO4_5			322
-MX51_PAD_NANDF_D3__NANDF_D3			323
-MX51_PAD_NANDF_D3__PATA_DATA3			324
-MX51_PAD_NANDF_D3__SD4_DAT4			325
-MX51_PAD_NANDF_D3__USBH3_DATA4			326
-MX51_PAD_NANDF_D2__GPIO4_6			327
-MX51_PAD_NANDF_D2__NANDF_D2			328
-MX51_PAD_NANDF_D2__PATA_DATA2			329
-MX51_PAD_NANDF_D2__SD4_DAT5			330
-MX51_PAD_NANDF_D2__USBH3_DATA5			331
-MX51_PAD_NANDF_D1__GPIO4_7			332
-MX51_PAD_NANDF_D1__NANDF_D1			333
-MX51_PAD_NANDF_D1__PATA_DATA1			334
-MX51_PAD_NANDF_D1__SD4_DAT6			335
-MX51_PAD_NANDF_D1__USBH3_DATA6			336
-MX51_PAD_NANDF_D0__GPIO4_8			337
-MX51_PAD_NANDF_D0__NANDF_D0			338
-MX51_PAD_NANDF_D0__PATA_DATA0			339
-MX51_PAD_NANDF_D0__SD4_DAT7			340
-MX51_PAD_NANDF_D0__USBH3_DATA7			341
-MX51_PAD_CSI1_D8__CSI1_D8			342
-MX51_PAD_CSI1_D8__GPIO3_12			343
-MX51_PAD_CSI1_D9__CSI1_D9			344
-MX51_PAD_CSI1_D9__GPIO3_13			345
-MX51_PAD_CSI1_D10__CSI1_D10			346
-MX51_PAD_CSI1_D11__CSI1_D11			347
-MX51_PAD_CSI1_D12__CSI1_D12			348
-MX51_PAD_CSI1_D13__CSI1_D13			349
-MX51_PAD_CSI1_D14__CSI1_D14			350
-MX51_PAD_CSI1_D15__CSI1_D15			351
-MX51_PAD_CSI1_D16__CSI1_D16			352
-MX51_PAD_CSI1_D17__CSI1_D17			353
-MX51_PAD_CSI1_D18__CSI1_D18			354
-MX51_PAD_CSI1_D19__CSI1_D19			355
-MX51_PAD_CSI1_VSYNC__CSI1_VSYNC			356
-MX51_PAD_CSI1_VSYNC__GPIO3_14			357
-MX51_PAD_CSI1_HSYNC__CSI1_HSYNC			358
-MX51_PAD_CSI1_HSYNC__GPIO3_15			359
-MX51_PAD_CSI1_PIXCLK__CSI1_PIXCLK		360
-MX51_PAD_CSI1_MCLK__CSI1_MCLK			361
-MX51_PAD_CSI2_D12__CSI2_D12			362
-MX51_PAD_CSI2_D12__GPIO4_9			363
-MX51_PAD_CSI2_D13__CSI2_D13			364
-MX51_PAD_CSI2_D13__GPIO4_10			365
-MX51_PAD_CSI2_D14__CSI2_D14			366
-MX51_PAD_CSI2_D15__CSI2_D15			367
-MX51_PAD_CSI2_D16__CSI2_D16			368
-MX51_PAD_CSI2_D17__CSI2_D17			369
-MX51_PAD_CSI2_D18__CSI2_D18			370
-MX51_PAD_CSI2_D18__GPIO4_11			371
-MX51_PAD_CSI2_D19__CSI2_D19			372
-MX51_PAD_CSI2_D19__GPIO4_12			373
-MX51_PAD_CSI2_VSYNC__CSI2_VSYNC			374
-MX51_PAD_CSI2_VSYNC__GPIO4_13			375
-MX51_PAD_CSI2_HSYNC__CSI2_HSYNC			376
-MX51_PAD_CSI2_HSYNC__GPIO4_14			377
-MX51_PAD_CSI2_PIXCLK__CSI2_PIXCLK		378
-MX51_PAD_CSI2_PIXCLK__GPIO4_15			379
-MX51_PAD_I2C1_CLK__GPIO4_16			380
-MX51_PAD_I2C1_CLK__I2C1_CLK			381
-MX51_PAD_I2C1_DAT__GPIO4_17			382
-MX51_PAD_I2C1_DAT__I2C1_DAT			383
-MX51_PAD_AUD3_BB_TXD__AUD3_TXD			384
-MX51_PAD_AUD3_BB_TXD__GPIO4_18			385
-MX51_PAD_AUD3_BB_RXD__AUD3_RXD			386
-MX51_PAD_AUD3_BB_RXD__GPIO4_19			387
-MX51_PAD_AUD3_BB_RXD__UART3_RXD			388
-MX51_PAD_AUD3_BB_CK__AUD3_TXC			389
-MX51_PAD_AUD3_BB_CK__GPIO4_20			390
-MX51_PAD_AUD3_BB_FS__AUD3_TXFS			391
-MX51_PAD_AUD3_BB_FS__GPIO4_21			392
-MX51_PAD_AUD3_BB_FS__UART3_TXD			393
-MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI		394
-MX51_PAD_CSPI1_MOSI__GPIO4_22			395
-MX51_PAD_CSPI1_MOSI__I2C1_SDA			396
-MX51_PAD_CSPI1_MISO__AUD4_RXD			397
-MX51_PAD_CSPI1_MISO__ECSPI1_MISO		398
-MX51_PAD_CSPI1_MISO__GPIO4_23			399
-MX51_PAD_CSPI1_SS0__AUD4_TXC			400
-MX51_PAD_CSPI1_SS0__ECSPI1_SS0			401
-MX51_PAD_CSPI1_SS0__GPIO4_24			402
-MX51_PAD_CSPI1_SS1__AUD4_TXD			403
-MX51_PAD_CSPI1_SS1__ECSPI1_SS1			404
-MX51_PAD_CSPI1_SS1__GPIO4_25			405
-MX51_PAD_CSPI1_RDY__AUD4_TXFS			406
-MX51_PAD_CSPI1_RDY__ECSPI1_RDY			407
-MX51_PAD_CSPI1_RDY__GPIO4_26			408
-MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK		409
-MX51_PAD_CSPI1_SCLK__GPIO4_27			410
-MX51_PAD_CSPI1_SCLK__I2C1_SCL			411
-MX51_PAD_UART1_RXD__GPIO4_28			412
-MX51_PAD_UART1_RXD__UART1_RXD			413
-MX51_PAD_UART1_TXD__GPIO4_29			414
-MX51_PAD_UART1_TXD__PWM2_PWMO			415
-MX51_PAD_UART1_TXD__UART1_TXD			416
-MX51_PAD_UART1_RTS__GPIO4_30			417
-MX51_PAD_UART1_RTS__UART1_RTS			418
-MX51_PAD_UART1_CTS__GPIO4_31			419
-MX51_PAD_UART1_CTS__UART1_CTS			420
-MX51_PAD_UART2_RXD__FIRI_TXD			421
-MX51_PAD_UART2_RXD__GPIO1_20			422
-MX51_PAD_UART2_RXD__UART2_RXD			423
-MX51_PAD_UART2_TXD__FIRI_RXD			424
-MX51_PAD_UART2_TXD__GPIO1_21			425
-MX51_PAD_UART2_TXD__UART2_TXD			426
-MX51_PAD_UART3_RXD__CSI1_D0			427
-MX51_PAD_UART3_RXD__GPIO1_22			428
-MX51_PAD_UART3_RXD__UART1_DTR			429
-MX51_PAD_UART3_RXD__UART3_RXD			430
-MX51_PAD_UART3_TXD__CSI1_D1			431
-MX51_PAD_UART3_TXD__GPIO1_23			432
-MX51_PAD_UART3_TXD__UART1_DSR			433
-MX51_PAD_UART3_TXD__UART3_TXD			434
-MX51_PAD_OWIRE_LINE__GPIO1_24			435
-MX51_PAD_OWIRE_LINE__OWIRE_LINE			436
-MX51_PAD_OWIRE_LINE__SPDIF_OUT			437
-MX51_PAD_KEY_ROW0__KEY_ROW0			438
-MX51_PAD_KEY_ROW1__KEY_ROW1			439
-MX51_PAD_KEY_ROW2__KEY_ROW2			440
-MX51_PAD_KEY_ROW3__KEY_ROW3			441
-MX51_PAD_KEY_COL0__KEY_COL0			442
-MX51_PAD_KEY_COL0__PLL1_BYP			443
-MX51_PAD_KEY_COL1__KEY_COL1			444
-MX51_PAD_KEY_COL1__PLL2_BYP			445
-MX51_PAD_KEY_COL2__KEY_COL2			446
-MX51_PAD_KEY_COL2__PLL3_BYP			447
-MX51_PAD_KEY_COL3__KEY_COL3			448
-MX51_PAD_KEY_COL4__I2C2_SCL			449
-MX51_PAD_KEY_COL4__KEY_COL4			450
-MX51_PAD_KEY_COL4__SPDIF_OUT1			451
-MX51_PAD_KEY_COL4__UART1_RI			452
-MX51_PAD_KEY_COL4__UART3_RTS			453
-MX51_PAD_KEY_COL5__I2C2_SDA			454
-MX51_PAD_KEY_COL5__KEY_COL5			455
-MX51_PAD_KEY_COL5__UART1_DCD			456
-MX51_PAD_KEY_COL5__UART3_CTS			457
-MX51_PAD_USBH1_CLK__CSPI_SCLK			458
-MX51_PAD_USBH1_CLK__GPIO1_25			459
-MX51_PAD_USBH1_CLK__I2C2_SCL			460
-MX51_PAD_USBH1_CLK__USBH1_CLK			461
-MX51_PAD_USBH1_DIR__CSPI_MOSI			462
-MX51_PAD_USBH1_DIR__GPIO1_26			463
-MX51_PAD_USBH1_DIR__I2C2_SDA			464
-MX51_PAD_USBH1_DIR__USBH1_DIR			465
-MX51_PAD_USBH1_STP__CSPI_RDY			466
-MX51_PAD_USBH1_STP__GPIO1_27			467
-MX51_PAD_USBH1_STP__UART3_RXD			468
-MX51_PAD_USBH1_STP__USBH1_STP			469
-MX51_PAD_USBH1_NXT__CSPI_MISO			470
-MX51_PAD_USBH1_NXT__GPIO1_28			471
-MX51_PAD_USBH1_NXT__UART3_TXD			472
-MX51_PAD_USBH1_NXT__USBH1_NXT			473
-MX51_PAD_USBH1_DATA0__GPIO1_11			474
-MX51_PAD_USBH1_DATA0__UART2_CTS			475
-MX51_PAD_USBH1_DATA0__USBH1_DATA0		476
-MX51_PAD_USBH1_DATA1__GPIO1_12			477
-MX51_PAD_USBH1_DATA1__UART2_RXD			478
-MX51_PAD_USBH1_DATA1__USBH1_DATA1		479
-MX51_PAD_USBH1_DATA2__GPIO1_13			480
-MX51_PAD_USBH1_DATA2__UART2_TXD			481
-MX51_PAD_USBH1_DATA2__USBH1_DATA2		482
-MX51_PAD_USBH1_DATA3__GPIO1_14			483
-MX51_PAD_USBH1_DATA3__UART2_RTS			484
-MX51_PAD_USBH1_DATA3__USBH1_DATA3		485
-MX51_PAD_USBH1_DATA4__CSPI_SS0			486
-MX51_PAD_USBH1_DATA4__GPIO1_15			487
-MX51_PAD_USBH1_DATA4__USBH1_DATA4		488
-MX51_PAD_USBH1_DATA5__CSPI_SS1			489
-MX51_PAD_USBH1_DATA5__GPIO1_16			490
-MX51_PAD_USBH1_DATA5__USBH1_DATA5		491
-MX51_PAD_USBH1_DATA6__CSPI_SS3			492
-MX51_PAD_USBH1_DATA6__GPIO1_17			493
-MX51_PAD_USBH1_DATA6__USBH1_DATA6		494
-MX51_PAD_USBH1_DATA7__ECSPI1_SS3		495
-MX51_PAD_USBH1_DATA7__ECSPI2_SS3		496
-MX51_PAD_USBH1_DATA7__GPIO1_18			497
-MX51_PAD_USBH1_DATA7__USBH1_DATA7		498
-MX51_PAD_DI1_PIN11__DI1_PIN11			499
-MX51_PAD_DI1_PIN11__ECSPI1_SS2			500
-MX51_PAD_DI1_PIN11__GPIO3_0			501
-MX51_PAD_DI1_PIN12__DI1_PIN12			502
-MX51_PAD_DI1_PIN12__GPIO3_1			503
-MX51_PAD_DI1_PIN13__DI1_PIN13			504
-MX51_PAD_DI1_PIN13__GPIO3_2			505
-MX51_PAD_DI1_D0_CS__DI1_D0_CS			506
-MX51_PAD_DI1_D0_CS__GPIO3_3			507
-MX51_PAD_DI1_D1_CS__DI1_D1_CS			508
-MX51_PAD_DI1_D1_CS__DISP1_PIN14			509
-MX51_PAD_DI1_D1_CS__DISP1_PIN5			510
-MX51_PAD_DI1_D1_CS__GPIO3_4			511
-MX51_PAD_DISPB2_SER_DIN__DISP1_PIN1		512
-MX51_PAD_DISPB2_SER_DIN__DISPB2_SER_DIN		513
-MX51_PAD_DISPB2_SER_DIN__GPIO3_5		514
-MX51_PAD_DISPB2_SER_DIO__DISP1_PIN6		515
-MX51_PAD_DISPB2_SER_DIO__DISPB2_SER_DIO		516
-MX51_PAD_DISPB2_SER_DIO__GPIO3_6		517
-MX51_PAD_DISPB2_SER_CLK__DISP1_PIN17		518
-MX51_PAD_DISPB2_SER_CLK__DISP1_PIN7		519
-MX51_PAD_DISPB2_SER_CLK__DISPB2_SER_CLK		520
-MX51_PAD_DISPB2_SER_CLK__GPIO3_7		521
-MX51_PAD_DISPB2_SER_RS__DISP1_EXT_CLK		522
-MX51_PAD_DISPB2_SER_RS__DISP1_PIN16		523
-MX51_PAD_DISPB2_SER_RS__DISP1_PIN8		524
-MX51_PAD_DISPB2_SER_RS__DISPB2_SER_RS		525
-MX51_PAD_DISPB2_SER_RS__DISPB2_SER_RS		526
-MX51_PAD_DISPB2_SER_RS__GPIO3_8			527
-MX51_PAD_DISP1_DAT0__DISP1_DAT0			528
-MX51_PAD_DISP1_DAT1__DISP1_DAT1			529
-MX51_PAD_DISP1_DAT2__DISP1_DAT2			530
-MX51_PAD_DISP1_DAT3__DISP1_DAT3			531
-MX51_PAD_DISP1_DAT4__DISP1_DAT4			532
-MX51_PAD_DISP1_DAT5__DISP1_DAT5			533
-MX51_PAD_DISP1_DAT6__BOOT_USB_SRC		534
-MX51_PAD_DISP1_DAT6__DISP1_DAT6			535
-MX51_PAD_DISP1_DAT7__BOOT_EEPROM_CFG		536
-MX51_PAD_DISP1_DAT7__DISP1_DAT7			537
-MX51_PAD_DISP1_DAT8__BOOT_SRC0			538
-MX51_PAD_DISP1_DAT8__DISP1_DAT8			539
-MX51_PAD_DISP1_DAT9__BOOT_SRC1			540
-MX51_PAD_DISP1_DAT9__DISP1_DAT9			541
-MX51_PAD_DISP1_DAT10__BOOT_SPARE_SIZE		542
-MX51_PAD_DISP1_DAT10__DISP1_DAT10		543
-MX51_PAD_DISP1_DAT11__BOOT_LPB_FREQ2		544
-MX51_PAD_DISP1_DAT11__DISP1_DAT11		545
-MX51_PAD_DISP1_DAT12__BOOT_MLC_SEL		546
-MX51_PAD_DISP1_DAT12__DISP1_DAT12		547
-MX51_PAD_DISP1_DAT13__BOOT_MEM_CTL0		548
-MX51_PAD_DISP1_DAT13__DISP1_DAT13		549
-MX51_PAD_DISP1_DAT14__BOOT_MEM_CTL1		550
-MX51_PAD_DISP1_DAT14__DISP1_DAT14		551
-MX51_PAD_DISP1_DAT15__BOOT_BUS_WIDTH		552
-MX51_PAD_DISP1_DAT15__DISP1_DAT15		553
-MX51_PAD_DISP1_DAT16__BOOT_PAGE_SIZE0		554
-MX51_PAD_DISP1_DAT16__DISP1_DAT16		555
-MX51_PAD_DISP1_DAT17__BOOT_PAGE_SIZE1		556
-MX51_PAD_DISP1_DAT17__DISP1_DAT17		557
-MX51_PAD_DISP1_DAT18__BOOT_WEIM_MUXED0		558
-MX51_PAD_DISP1_DAT18__DISP1_DAT18		559
-MX51_PAD_DISP1_DAT18__DISP2_PIN11		560
-MX51_PAD_DISP1_DAT18__DISP2_PIN5		561
-MX51_PAD_DISP1_DAT19__BOOT_WEIM_MUXED1		562
-MX51_PAD_DISP1_DAT19__DISP1_DAT19		563
-MX51_PAD_DISP1_DAT19__DISP2_PIN12		564
-MX51_PAD_DISP1_DAT19__DISP2_PIN6		565
-MX51_PAD_DISP1_DAT20__BOOT_MEM_TYPE0		566
-MX51_PAD_DISP1_DAT20__DISP1_DAT20		567
-MX51_PAD_DISP1_DAT20__DISP2_PIN13		568
-MX51_PAD_DISP1_DAT20__DISP2_PIN7		569
-MX51_PAD_DISP1_DAT21__BOOT_MEM_TYPE1		570
-MX51_PAD_DISP1_DAT21__DISP1_DAT21		571
-MX51_PAD_DISP1_DAT21__DISP2_PIN14		572
-MX51_PAD_DISP1_DAT21__DISP2_PIN8		573
-MX51_PAD_DISP1_DAT22__BOOT_LPB_FREQ0		574
-MX51_PAD_DISP1_DAT22__DISP1_DAT22		575
-MX51_PAD_DISP1_DAT22__DISP2_D0_CS		576
-MX51_PAD_DISP1_DAT22__DISP2_DAT16		577
-MX51_PAD_DISP1_DAT23__BOOT_LPB_FREQ1		578
-MX51_PAD_DISP1_DAT23__DISP1_DAT23		579
-MX51_PAD_DISP1_DAT23__DISP2_D1_CS		580
-MX51_PAD_DISP1_DAT23__DISP2_DAT17		581
-MX51_PAD_DISP1_DAT23__DISP2_SER_CS		582
-MX51_PAD_DI1_PIN3__DI1_PIN3			583
-MX51_PAD_DI1_PIN2__DI1_PIN2			584
-MX51_PAD_DI_GP2__DISP1_SER_CLK			585
-MX51_PAD_DI_GP2__DISP2_WAIT			586
-MX51_PAD_DI_GP3__CSI1_DATA_EN			587
-MX51_PAD_DI_GP3__DISP1_SER_DIO			588
-MX51_PAD_DI_GP3__FEC_TX_ER			589
-MX51_PAD_DI2_PIN4__CSI2_DATA_EN			590
-MX51_PAD_DI2_PIN4__DI2_PIN4			591
-MX51_PAD_DI2_PIN4__FEC_CRS			592
-MX51_PAD_DI2_PIN2__DI2_PIN2			593
-MX51_PAD_DI2_PIN2__FEC_MDC			594
-MX51_PAD_DI2_PIN3__DI2_PIN3			595
-MX51_PAD_DI2_PIN3__FEC_MDIO			596
-MX51_PAD_DI2_DISP_CLK__DI2_DISP_CLK		597
-MX51_PAD_DI2_DISP_CLK__FEC_RDATA1		598
-MX51_PAD_DI_GP4__DI2_PIN15			599
-MX51_PAD_DI_GP4__DISP1_SER_DIN			600
-MX51_PAD_DI_GP4__DISP2_PIN1			601
-MX51_PAD_DI_GP4__FEC_RDATA2			602
-MX51_PAD_DISP2_DAT0__DISP2_DAT0			603
-MX51_PAD_DISP2_DAT0__FEC_RDATA3			604
-MX51_PAD_DISP2_DAT0__KEY_COL6			605
-MX51_PAD_DISP2_DAT0__UART3_RXD			606
-MX51_PAD_DISP2_DAT0__USBH3_CLK			607
-MX51_PAD_DISP2_DAT1__DISP2_DAT1			608
-MX51_PAD_DISP2_DAT1__FEC_RX_ER			609
-MX51_PAD_DISP2_DAT1__KEY_COL7			610
-MX51_PAD_DISP2_DAT1__UART3_TXD			611
-MX51_PAD_DISP2_DAT1__USBH3_DIR			612
-MX51_PAD_DISP2_DAT2__DISP2_DAT2			613
-MX51_PAD_DISP2_DAT3__DISP2_DAT3			614
-MX51_PAD_DISP2_DAT4__DISP2_DAT4			615
-MX51_PAD_DISP2_DAT5__DISP2_DAT5			616
-MX51_PAD_DISP2_DAT6__DISP2_DAT6			617
-MX51_PAD_DISP2_DAT6__FEC_TDATA1			618
-MX51_PAD_DISP2_DAT6__GPIO1_19			619
-MX51_PAD_DISP2_DAT6__KEY_ROW4			620
-MX51_PAD_DISP2_DAT6__USBH3_STP			621
-MX51_PAD_DISP2_DAT7__DISP2_DAT7			622
-MX51_PAD_DISP2_DAT7__FEC_TDATA2			623
-MX51_PAD_DISP2_DAT7__GPIO1_29			624
-MX51_PAD_DISP2_DAT7__KEY_ROW5			625
-MX51_PAD_DISP2_DAT7__USBH3_NXT			626
-MX51_PAD_DISP2_DAT8__DISP2_DAT8			627
-MX51_PAD_DISP2_DAT8__FEC_TDATA3			628
-MX51_PAD_DISP2_DAT8__GPIO1_30			629
-MX51_PAD_DISP2_DAT8__KEY_ROW6			630
-MX51_PAD_DISP2_DAT8__USBH3_DATA0		631
-MX51_PAD_DISP2_DAT9__AUD6_RXC			632
-MX51_PAD_DISP2_DAT9__DISP2_DAT9			633
-MX51_PAD_DISP2_DAT9__FEC_TX_EN			634
-MX51_PAD_DISP2_DAT9__GPIO1_31			635
-MX51_PAD_DISP2_DAT9__USBH3_DATA1		636
-MX51_PAD_DISP2_DAT10__DISP2_DAT10		637
-MX51_PAD_DISP2_DAT10__DISP2_SER_CS		638
-MX51_PAD_DISP2_DAT10__FEC_COL			639
-MX51_PAD_DISP2_DAT10__KEY_ROW7			640
-MX51_PAD_DISP2_DAT10__USBH3_DATA2		641
-MX51_PAD_DISP2_DAT11__AUD6_TXD			642
-MX51_PAD_DISP2_DAT11__DISP2_DAT11		643
-MX51_PAD_DISP2_DAT11__FEC_RX_CLK		644
-MX51_PAD_DISP2_DAT11__GPIO1_10			645
-MX51_PAD_DISP2_DAT11__USBH3_DATA3		646
-MX51_PAD_DISP2_DAT12__AUD6_RXD			647
-MX51_PAD_DISP2_DAT12__DISP2_DAT12		648
-MX51_PAD_DISP2_DAT12__FEC_RX_DV			649
-MX51_PAD_DISP2_DAT12__USBH3_DATA4		650
-MX51_PAD_DISP2_DAT13__AUD6_TXC			651
-MX51_PAD_DISP2_DAT13__DISP2_DAT13		652
-MX51_PAD_DISP2_DAT13__FEC_TX_CLK		653
-MX51_PAD_DISP2_DAT13__USBH3_DATA5		654
-MX51_PAD_DISP2_DAT14__AUD6_TXFS			655
-MX51_PAD_DISP2_DAT14__DISP2_DAT14		656
-MX51_PAD_DISP2_DAT14__FEC_RDATA0		657
-MX51_PAD_DISP2_DAT14__USBH3_DATA6		658
-MX51_PAD_DISP2_DAT15__AUD6_RXFS			659
-MX51_PAD_DISP2_DAT15__DISP1_SER_CS		660
-MX51_PAD_DISP2_DAT15__DISP2_DAT15		661
-MX51_PAD_DISP2_DAT15__FEC_TDATA0		662
-MX51_PAD_DISP2_DAT15__USBH3_DATA7		663
-MX51_PAD_SD1_CMD__AUD5_RXFS			664
-MX51_PAD_SD1_CMD__CSPI_MOSI			665
-MX51_PAD_SD1_CMD__SD1_CMD			666
-MX51_PAD_SD1_CLK__AUD5_RXC			667
-MX51_PAD_SD1_CLK__CSPI_SCLK			668
-MX51_PAD_SD1_CLK__SD1_CLK			669
-MX51_PAD_SD1_DATA0__AUD5_TXD			670
-MX51_PAD_SD1_DATA0__CSPI_MISO			671
-MX51_PAD_SD1_DATA0__SD1_DATA0			672
-MX51_PAD_EIM_DA0__EIM_DA0			673
-MX51_PAD_EIM_DA1__EIM_DA1			674
-MX51_PAD_EIM_DA2__EIM_DA2			675
-MX51_PAD_EIM_DA3__EIM_DA3			676
-MX51_PAD_SD1_DATA1__AUD5_RXD			677
-MX51_PAD_SD1_DATA1__SD1_DATA1			678
-MX51_PAD_EIM_DA4__EIM_DA4			679
-MX51_PAD_EIM_DA5__EIM_DA5			680
-MX51_PAD_EIM_DA6__EIM_DA6			681
-MX51_PAD_EIM_DA7__EIM_DA7			682
-MX51_PAD_SD1_DATA2__AUD5_TXC			683
-MX51_PAD_SD1_DATA2__SD1_DATA2			684
-MX51_PAD_EIM_DA10__EIM_DA10			685
-MX51_PAD_EIM_DA11__EIM_DA11			686
-MX51_PAD_EIM_DA8__EIM_DA8			687
-MX51_PAD_EIM_DA9__EIM_DA9			688
-MX51_PAD_SD1_DATA3__AUD5_TXFS			689
-MX51_PAD_SD1_DATA3__CSPI_SS1			690
-MX51_PAD_SD1_DATA3__SD1_DATA3			691
-MX51_PAD_GPIO1_0__CSPI_SS2			692
-MX51_PAD_GPIO1_0__GPIO1_0			693
-MX51_PAD_GPIO1_0__SD1_CD			694
-MX51_PAD_GPIO1_1__CSPI_MISO			695
-MX51_PAD_GPIO1_1__GPIO1_1			696
-MX51_PAD_GPIO1_1__SD1_WP			697
-MX51_PAD_EIM_DA12__EIM_DA12			698
-MX51_PAD_EIM_DA13__EIM_DA13			699
-MX51_PAD_EIM_DA14__EIM_DA14			700
-MX51_PAD_EIM_DA15__EIM_DA15			701
-MX51_PAD_SD2_CMD__CSPI_MOSI			702
-MX51_PAD_SD2_CMD__I2C1_SCL			703
-MX51_PAD_SD2_CMD__SD2_CMD			704
-MX51_PAD_SD2_CLK__CSPI_SCLK			705
-MX51_PAD_SD2_CLK__I2C1_SDA			706
-MX51_PAD_SD2_CLK__SD2_CLK			707
-MX51_PAD_SD2_DATA0__CSPI_MISO			708
-MX51_PAD_SD2_DATA0__SD1_DAT4			709
-MX51_PAD_SD2_DATA0__SD2_DATA0			710
-MX51_PAD_SD2_DATA1__SD1_DAT5			711
-MX51_PAD_SD2_DATA1__SD2_DATA1			712
-MX51_PAD_SD2_DATA1__USBH3_H2_DP			713
-MX51_PAD_SD2_DATA2__SD1_DAT6			714
-MX51_PAD_SD2_DATA2__SD2_DATA2			715
-MX51_PAD_SD2_DATA2__USBH3_H2_DM			716
-MX51_PAD_SD2_DATA3__CSPI_SS2			717
-MX51_PAD_SD2_DATA3__SD1_DAT7			718
-MX51_PAD_SD2_DATA3__SD2_DATA3			719
-MX51_PAD_GPIO1_2__CCM_OUT_2			720
-MX51_PAD_GPIO1_2__GPIO1_2			721
-MX51_PAD_GPIO1_2__I2C2_SCL			722
-MX51_PAD_GPIO1_2__PLL1_BYP			723
-MX51_PAD_GPIO1_2__PWM1_PWMO			724
-MX51_PAD_GPIO1_3__GPIO1_3			725
-MX51_PAD_GPIO1_3__I2C2_SDA			726
-MX51_PAD_GPIO1_3__PLL2_BYP			727
-MX51_PAD_GPIO1_3__PWM2_PWMO			728
-MX51_PAD_PMIC_INT_REQ__PMIC_INT_REQ		729
-MX51_PAD_PMIC_INT_REQ__PMIC_PMU_IRQ_B		730
-MX51_PAD_GPIO1_4__DISP2_EXT_CLK			731
-MX51_PAD_GPIO1_4__EIM_RDY			732
-MX51_PAD_GPIO1_4__GPIO1_4			733
-MX51_PAD_GPIO1_4__WDOG1_WDOG_B			734
-MX51_PAD_GPIO1_5__CSI2_MCLK			735
-MX51_PAD_GPIO1_5__DISP2_PIN16			736
-MX51_PAD_GPIO1_5__GPIO1_5			737
-MX51_PAD_GPIO1_5__WDOG2_WDOG_B			738
-MX51_PAD_GPIO1_6__DISP2_PIN17			739
-MX51_PAD_GPIO1_6__GPIO1_6			740
-MX51_PAD_GPIO1_6__REF_EN_B			741
-MX51_PAD_GPIO1_7__CCM_OUT_0			742
-MX51_PAD_GPIO1_7__GPIO1_7			743
-MX51_PAD_GPIO1_7__SD2_WP			744
-MX51_PAD_GPIO1_7__SPDIF_OUT1			745
-MX51_PAD_GPIO1_8__CSI2_DATA_EN			746
-MX51_PAD_GPIO1_8__GPIO1_8			747
-MX51_PAD_GPIO1_8__SD2_CD			748
-MX51_PAD_GPIO1_8__USBH3_PWR			749
-MX51_PAD_GPIO1_9__CCM_OUT_1			750
-MX51_PAD_GPIO1_9__DISP2_D1_CS			751
-MX51_PAD_GPIO1_9__DISP2_SER_CS			752
-MX51_PAD_GPIO1_9__GPIO1_9			753
-MX51_PAD_GPIO1_9__SD2_LCTL			754
-MX51_PAD_GPIO1_9__USBH3_OC			755
+Refer to imx51-pinfunc.h in device tree source folder for all available
+imx51 PIN_FUNC_ID.
diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,imx53-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/fsl,imx53-pinctrl.txt
index ca85ca4..25dcb77 100644
--- a/Documentation/devicetree/bindings/pinctrl/fsl,imx53-pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/fsl,imx53-pinctrl.txt
@@ -28,1175 +28,5 @@ PAD_CTL_DSE_MAX			(3 << 1)
 PAD_CTL_SRE_FAST		(1 << 0)
 PAD_CTL_SRE_SLOW		(0 << 0)
 
-See below for available PIN_FUNC_ID for imx53:
-MX53_PAD_GPIO_19__KPP_COL_5				0
-MX53_PAD_GPIO_19__GPIO4_5				1
-MX53_PAD_GPIO_19__CCM_CLKO				2
-MX53_PAD_GPIO_19__SPDIF_OUT1				3
-MX53_PAD_GPIO_19__RTC_CE_RTC_EXT_TRIG2			4
-MX53_PAD_GPIO_19__ECSPI1_RDY				5
-MX53_PAD_GPIO_19__FEC_TDATA_3				6
-MX53_PAD_GPIO_19__SRC_INT_BOOT				7
-MX53_PAD_KEY_COL0__KPP_COL_0				8
-MX53_PAD_KEY_COL0__GPIO4_6				9
-MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC			10
-MX53_PAD_KEY_COL0__UART4_TXD_MUX			11
-MX53_PAD_KEY_COL0__ECSPI1_SCLK				12
-MX53_PAD_KEY_COL0__FEC_RDATA_3				13
-MX53_PAD_KEY_COL0__SRC_ANY_PU_RST			14
-MX53_PAD_KEY_ROW0__KPP_ROW_0				15
-MX53_PAD_KEY_ROW0__GPIO4_7				16
-MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD			17
-MX53_PAD_KEY_ROW0__UART4_RXD_MUX			18
-MX53_PAD_KEY_ROW0__ECSPI1_MOSI				19
-MX53_PAD_KEY_ROW0__FEC_TX_ER				20
-MX53_PAD_KEY_COL1__KPP_COL_1				21
-MX53_PAD_KEY_COL1__GPIO4_8				22
-MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS			23
-MX53_PAD_KEY_COL1__UART5_TXD_MUX			24
-MX53_PAD_KEY_COL1__ECSPI1_MISO				25
-MX53_PAD_KEY_COL1__FEC_RX_CLK				26
-MX53_PAD_KEY_COL1__USBPHY1_TXREADY			27
-MX53_PAD_KEY_ROW1__KPP_ROW_1				28
-MX53_PAD_KEY_ROW1__GPIO4_9				29
-MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD			30
-MX53_PAD_KEY_ROW1__UART5_RXD_MUX			31
-MX53_PAD_KEY_ROW1__ECSPI1_SS0				32
-MX53_PAD_KEY_ROW1__FEC_COL				33
-MX53_PAD_KEY_ROW1__USBPHY1_RXVALID			34
-MX53_PAD_KEY_COL2__KPP_COL_2				35
-MX53_PAD_KEY_COL2__GPIO4_10				36
-MX53_PAD_KEY_COL2__CAN1_TXCAN				37
-MX53_PAD_KEY_COL2__FEC_MDIO				38
-MX53_PAD_KEY_COL2__ECSPI1_SS1				39
-MX53_PAD_KEY_COL2__FEC_RDATA_2				40
-MX53_PAD_KEY_COL2__USBPHY1_RXACTIVE			41
-MX53_PAD_KEY_ROW2__KPP_ROW_2				42
-MX53_PAD_KEY_ROW2__GPIO4_11				43
-MX53_PAD_KEY_ROW2__CAN1_RXCAN				44
-MX53_PAD_KEY_ROW2__FEC_MDC				45
-MX53_PAD_KEY_ROW2__ECSPI1_SS2				46
-MX53_PAD_KEY_ROW2__FEC_TDATA_2				47
-MX53_PAD_KEY_ROW2__USBPHY1_RXERROR			48
-MX53_PAD_KEY_COL3__KPP_COL_3				49
-MX53_PAD_KEY_COL3__GPIO4_12				50
-MX53_PAD_KEY_COL3__USBOH3_H2_DP				51
-MX53_PAD_KEY_COL3__SPDIF_IN1				52
-MX53_PAD_KEY_COL3__I2C2_SCL				53
-MX53_PAD_KEY_COL3__ECSPI1_SS3				54
-MX53_PAD_KEY_COL3__FEC_CRS				55
-MX53_PAD_KEY_COL3__USBPHY1_SIECLOCK			56
-MX53_PAD_KEY_ROW3__KPP_ROW_3				57
-MX53_PAD_KEY_ROW3__GPIO4_13				58
-MX53_PAD_KEY_ROW3__USBOH3_H2_DM				59
-MX53_PAD_KEY_ROW3__CCM_ASRC_EXT_CLK			60
-MX53_PAD_KEY_ROW3__I2C2_SDA				61
-MX53_PAD_KEY_ROW3__OSC32K_32K_OUT			62
-MX53_PAD_KEY_ROW3__CCM_PLL4_BYP				63
-MX53_PAD_KEY_ROW3__USBPHY1_LINESTATE_0			64
-MX53_PAD_KEY_COL4__KPP_COL_4				65
-MX53_PAD_KEY_COL4__GPIO4_14				66
-MX53_PAD_KEY_COL4__CAN2_TXCAN				67
-MX53_PAD_KEY_COL4__IPU_SISG_4				68
-MX53_PAD_KEY_COL4__UART5_RTS				69
-MX53_PAD_KEY_COL4__USBOH3_USBOTG_OC			70
-MX53_PAD_KEY_COL4__USBPHY1_LINESTATE_1			71
-MX53_PAD_KEY_ROW4__KPP_ROW_4				72
-MX53_PAD_KEY_ROW4__GPIO4_15				73
-MX53_PAD_KEY_ROW4__CAN2_RXCAN				74
-MX53_PAD_KEY_ROW4__IPU_SISG_5				75
-MX53_PAD_KEY_ROW4__UART5_CTS				76
-MX53_PAD_KEY_ROW4__USBOH3_USBOTG_PWR			77
-MX53_PAD_KEY_ROW4__USBPHY1_VBUSVALID			78
-MX53_PAD_DI0_DISP_CLK__IPU_DI0_DISP_CLK			79
-MX53_PAD_DI0_DISP_CLK__GPIO4_16				80
-MX53_PAD_DI0_DISP_CLK__USBOH3_USBH2_DIR			81
-MX53_PAD_DI0_DISP_CLK__SDMA_DEBUG_CORE_STATE_0		82
-MX53_PAD_DI0_DISP_CLK__EMI_EMI_DEBUG_0			83
-MX53_PAD_DI0_DISP_CLK__USBPHY1_AVALID			84
-MX53_PAD_DI0_PIN15__IPU_DI0_PIN15			85
-MX53_PAD_DI0_PIN15__GPIO4_17				86
-MX53_PAD_DI0_PIN15__AUDMUX_AUD6_TXC			87
-MX53_PAD_DI0_PIN15__SDMA_DEBUG_CORE_STATE_1		88
-MX53_PAD_DI0_PIN15__EMI_EMI_DEBUG_1			89
-MX53_PAD_DI0_PIN15__USBPHY1_BVALID			90
-MX53_PAD_DI0_PIN2__IPU_DI0_PIN2				91
-MX53_PAD_DI0_PIN2__GPIO4_18				92
-MX53_PAD_DI0_PIN2__AUDMUX_AUD6_TXD			93
-MX53_PAD_DI0_PIN2__SDMA_DEBUG_CORE_STATE_2		94
-MX53_PAD_DI0_PIN2__EMI_EMI_DEBUG_2			95
-MX53_PAD_DI0_PIN2__USBPHY1_ENDSESSION			96
-MX53_PAD_DI0_PIN3__IPU_DI0_PIN3				97
-MX53_PAD_DI0_PIN3__GPIO4_19				98
-MX53_PAD_DI0_PIN3__AUDMUX_AUD6_TXFS			99
-MX53_PAD_DI0_PIN3__SDMA_DEBUG_CORE_STATE_3		100
-MX53_PAD_DI0_PIN3__EMI_EMI_DEBUG_3			101
-MX53_PAD_DI0_PIN3__USBPHY1_IDDIG			102
-MX53_PAD_DI0_PIN4__IPU_DI0_PIN4				103
-MX53_PAD_DI0_PIN4__GPIO4_20				104
-MX53_PAD_DI0_PIN4__AUDMUX_AUD6_RXD			105
-MX53_PAD_DI0_PIN4__ESDHC1_WP				106
-MX53_PAD_DI0_PIN4__SDMA_DEBUG_YIELD			107
-MX53_PAD_DI0_PIN4__EMI_EMI_DEBUG_4			108
-MX53_PAD_DI0_PIN4__USBPHY1_HOSTDISCONNECT		109
-MX53_PAD_DISP0_DAT0__IPU_DISP0_DAT_0			110
-MX53_PAD_DISP0_DAT0__GPIO4_21				111
-MX53_PAD_DISP0_DAT0__CSPI_SCLK				112
-MX53_PAD_DISP0_DAT0__USBOH3_USBH2_DATA_0		113
-MX53_PAD_DISP0_DAT0__SDMA_DEBUG_CORE_RUN		114
-MX53_PAD_DISP0_DAT0__EMI_EMI_DEBUG_5			115
-MX53_PAD_DISP0_DAT0__USBPHY2_TXREADY			116
-MX53_PAD_DISP0_DAT1__IPU_DISP0_DAT_1			117
-MX53_PAD_DISP0_DAT1__GPIO4_22				118
-MX53_PAD_DISP0_DAT1__CSPI_MOSI				119
-MX53_PAD_DISP0_DAT1__USBOH3_USBH2_DATA_1		120
-MX53_PAD_DISP0_DAT1__SDMA_DEBUG_EVENT_CHANNEL_SEL	121
-MX53_PAD_DISP0_DAT1__EMI_EMI_DEBUG_6			122
-MX53_PAD_DISP0_DAT1__USBPHY2_RXVALID			123
-MX53_PAD_DISP0_DAT2__IPU_DISP0_DAT_2			124
-MX53_PAD_DISP0_DAT2__GPIO4_23				125
-MX53_PAD_DISP0_DAT2__CSPI_MISO				126
-MX53_PAD_DISP0_DAT2__USBOH3_USBH2_DATA_2		127
-MX53_PAD_DISP0_DAT2__SDMA_DEBUG_MODE			128
-MX53_PAD_DISP0_DAT2__EMI_EMI_DEBUG_7			129
-MX53_PAD_DISP0_DAT2__USBPHY2_RXACTIVE			130
-MX53_PAD_DISP0_DAT3__IPU_DISP0_DAT_3			131
-MX53_PAD_DISP0_DAT3__GPIO4_24				132
-MX53_PAD_DISP0_DAT3__CSPI_SS0				133
-MX53_PAD_DISP0_DAT3__USBOH3_USBH2_DATA_3		134
-MX53_PAD_DISP0_DAT3__SDMA_DEBUG_BUS_ERROR		135
-MX53_PAD_DISP0_DAT3__EMI_EMI_DEBUG_8			136
-MX53_PAD_DISP0_DAT3__USBPHY2_RXERROR			137
-MX53_PAD_DISP0_DAT4__IPU_DISP0_DAT_4			138
-MX53_PAD_DISP0_DAT4__GPIO4_25				139
-MX53_PAD_DISP0_DAT4__CSPI_SS1				140
-MX53_PAD_DISP0_DAT4__USBOH3_USBH2_DATA_4		141
-MX53_PAD_DISP0_DAT4__SDMA_DEBUG_BUS_RWB			142
-MX53_PAD_DISP0_DAT4__EMI_EMI_DEBUG_9			143
-MX53_PAD_DISP0_DAT4__USBPHY2_SIECLOCK			144
-MX53_PAD_DISP0_DAT5__IPU_DISP0_DAT_5			145
-MX53_PAD_DISP0_DAT5__GPIO4_26				146
-MX53_PAD_DISP0_DAT5__CSPI_SS2				147
-MX53_PAD_DISP0_DAT5__USBOH3_USBH2_DATA_5		148
-MX53_PAD_DISP0_DAT5__SDMA_DEBUG_MATCHED_DMBUS		149
-MX53_PAD_DISP0_DAT5__EMI_EMI_DEBUG_10			150
-MX53_PAD_DISP0_DAT5__USBPHY2_LINESTATE_0		151
-MX53_PAD_DISP0_DAT6__IPU_DISP0_DAT_6			152
-MX53_PAD_DISP0_DAT6__GPIO4_27				153
-MX53_PAD_DISP0_DAT6__CSPI_SS3				154
-MX53_PAD_DISP0_DAT6__USBOH3_USBH2_DATA_6		155
-MX53_PAD_DISP0_DAT6__SDMA_DEBUG_RTBUFFER_WRITE		156
-MX53_PAD_DISP0_DAT6__EMI_EMI_DEBUG_11			157
-MX53_PAD_DISP0_DAT6__USBPHY2_LINESTATE_1		158
-MX53_PAD_DISP0_DAT7__IPU_DISP0_DAT_7			159
-MX53_PAD_DISP0_DAT7__GPIO4_28				160
-MX53_PAD_DISP0_DAT7__CSPI_RDY				161
-MX53_PAD_DISP0_DAT7__USBOH3_USBH2_DATA_7		162
-MX53_PAD_DISP0_DAT7__SDMA_DEBUG_EVENT_CHANNEL_0		163
-MX53_PAD_DISP0_DAT7__EMI_EMI_DEBUG_12			164
-MX53_PAD_DISP0_DAT7__USBPHY2_VBUSVALID			165
-MX53_PAD_DISP0_DAT8__IPU_DISP0_DAT_8			166
-MX53_PAD_DISP0_DAT8__GPIO4_29				167
-MX53_PAD_DISP0_DAT8__PWM1_PWMO				168
-MX53_PAD_DISP0_DAT8__WDOG1_WDOG_B			169
-MX53_PAD_DISP0_DAT8__SDMA_DEBUG_EVENT_CHANNEL_1		170
-MX53_PAD_DISP0_DAT8__EMI_EMI_DEBUG_13			171
-MX53_PAD_DISP0_DAT8__USBPHY2_AVALID			172
-MX53_PAD_DISP0_DAT9__IPU_DISP0_DAT_9			173
-MX53_PAD_DISP0_DAT9__GPIO4_30				174
-MX53_PAD_DISP0_DAT9__PWM2_PWMO				175
-MX53_PAD_DISP0_DAT9__WDOG2_WDOG_B			176
-MX53_PAD_DISP0_DAT9__SDMA_DEBUG_EVENT_CHANNEL_2		177
-MX53_PAD_DISP0_DAT9__EMI_EMI_DEBUG_14			178
-MX53_PAD_DISP0_DAT9__USBPHY2_VSTATUS_0			179
-MX53_PAD_DISP0_DAT10__IPU_DISP0_DAT_10			180
-MX53_PAD_DISP0_DAT10__GPIO4_31				181
-MX53_PAD_DISP0_DAT10__USBOH3_USBH2_STP			182
-MX53_PAD_DISP0_DAT10__SDMA_DEBUG_EVENT_CHANNEL_3	183
-MX53_PAD_DISP0_DAT10__EMI_EMI_DEBUG_15			184
-MX53_PAD_DISP0_DAT10__USBPHY2_VSTATUS_1			185
-MX53_PAD_DISP0_DAT11__IPU_DISP0_DAT_11			186
-MX53_PAD_DISP0_DAT11__GPIO5_5				187
-MX53_PAD_DISP0_DAT11__USBOH3_USBH2_NXT			188
-MX53_PAD_DISP0_DAT11__SDMA_DEBUG_EVENT_CHANNEL_4	189
-MX53_PAD_DISP0_DAT11__EMI_EMI_DEBUG_16			190
-MX53_PAD_DISP0_DAT11__USBPHY2_VSTATUS_2			191
-MX53_PAD_DISP0_DAT12__IPU_DISP0_DAT_12			192
-MX53_PAD_DISP0_DAT12__GPIO5_6				193
-MX53_PAD_DISP0_DAT12__USBOH3_USBH2_CLK			194
-MX53_PAD_DISP0_DAT12__SDMA_DEBUG_EVENT_CHANNEL_5	195
-MX53_PAD_DISP0_DAT12__EMI_EMI_DEBUG_17			196
-MX53_PAD_DISP0_DAT12__USBPHY2_VSTATUS_3			197
-MX53_PAD_DISP0_DAT13__IPU_DISP0_DAT_13			198
-MX53_PAD_DISP0_DAT13__GPIO5_7				199
-MX53_PAD_DISP0_DAT13__AUDMUX_AUD5_RXFS			200
-MX53_PAD_DISP0_DAT13__SDMA_DEBUG_EVT_CHN_LINES_0	201
-MX53_PAD_DISP0_DAT13__EMI_EMI_DEBUG_18			202
-MX53_PAD_DISP0_DAT13__USBPHY2_VSTATUS_4			203
-MX53_PAD_DISP0_DAT14__IPU_DISP0_DAT_14			204
-MX53_PAD_DISP0_DAT14__GPIO5_8				205
-MX53_PAD_DISP0_DAT14__AUDMUX_AUD5_RXC			206
-MX53_PAD_DISP0_DAT14__SDMA_DEBUG_EVT_CHN_LINES_1	207
-MX53_PAD_DISP0_DAT14__EMI_EMI_DEBUG_19			208
-MX53_PAD_DISP0_DAT14__USBPHY2_VSTATUS_5			209
-MX53_PAD_DISP0_DAT15__IPU_DISP0_DAT_15			210
-MX53_PAD_DISP0_DAT15__GPIO5_9				211
-MX53_PAD_DISP0_DAT15__ECSPI1_SS1			212
-MX53_PAD_DISP0_DAT15__ECSPI2_SS1			213
-MX53_PAD_DISP0_DAT15__SDMA_DEBUG_EVT_CHN_LINES_2	214
-MX53_PAD_DISP0_DAT15__EMI_EMI_DEBUG_20			215
-MX53_PAD_DISP0_DAT15__USBPHY2_VSTATUS_6			216
-MX53_PAD_DISP0_DAT16__IPU_DISP0_DAT_16			217
-MX53_PAD_DISP0_DAT16__GPIO5_10				218
-MX53_PAD_DISP0_DAT16__ECSPI2_MOSI			219
-MX53_PAD_DISP0_DAT16__AUDMUX_AUD5_TXC			220
-MX53_PAD_DISP0_DAT16__SDMA_EXT_EVENT_0			221
-MX53_PAD_DISP0_DAT16__SDMA_DEBUG_EVT_CHN_LINES_3	222
-MX53_PAD_DISP0_DAT16__EMI_EMI_DEBUG_21			223
-MX53_PAD_DISP0_DAT16__USBPHY2_VSTATUS_7			224
-MX53_PAD_DISP0_DAT17__IPU_DISP0_DAT_17			225
-MX53_PAD_DISP0_DAT17__GPIO5_11				226
-MX53_PAD_DISP0_DAT17__ECSPI2_MISO			227
-MX53_PAD_DISP0_DAT17__AUDMUX_AUD5_TXD			228
-MX53_PAD_DISP0_DAT17__SDMA_EXT_EVENT_1			229
-MX53_PAD_DISP0_DAT17__SDMA_DEBUG_EVT_CHN_LINES_4	230
-MX53_PAD_DISP0_DAT17__EMI_EMI_DEBUG_22			231
-MX53_PAD_DISP0_DAT18__IPU_DISP0_DAT_18			232
-MX53_PAD_DISP0_DAT18__GPIO5_12				233
-MX53_PAD_DISP0_DAT18__ECSPI2_SS0			234
-MX53_PAD_DISP0_DAT18__AUDMUX_AUD5_TXFS			235
-MX53_PAD_DISP0_DAT18__AUDMUX_AUD4_RXFS			236
-MX53_PAD_DISP0_DAT18__SDMA_DEBUG_EVT_CHN_LINES_5	237
-MX53_PAD_DISP0_DAT18__EMI_EMI_DEBUG_23			238
-MX53_PAD_DISP0_DAT18__EMI_WEIM_CS_2			239
-MX53_PAD_DISP0_DAT19__IPU_DISP0_DAT_19			240
-MX53_PAD_DISP0_DAT19__GPIO5_13				241
-MX53_PAD_DISP0_DAT19__ECSPI2_SCLK			242
-MX53_PAD_DISP0_DAT19__AUDMUX_AUD5_RXD			243
-MX53_PAD_DISP0_DAT19__AUDMUX_AUD4_RXC			244
-MX53_PAD_DISP0_DAT19__SDMA_DEBUG_EVT_CHN_LINES_6	245
-MX53_PAD_DISP0_DAT19__EMI_EMI_DEBUG_24			246
-MX53_PAD_DISP0_DAT19__EMI_WEIM_CS_3			247
-MX53_PAD_DISP0_DAT20__IPU_DISP0_DAT_20			248
-MX53_PAD_DISP0_DAT20__GPIO5_14				249
-MX53_PAD_DISP0_DAT20__ECSPI1_SCLK			250
-MX53_PAD_DISP0_DAT20__AUDMUX_AUD4_TXC			251
-MX53_PAD_DISP0_DAT20__SDMA_DEBUG_EVT_CHN_LINES_7	252
-MX53_PAD_DISP0_DAT20__EMI_EMI_DEBUG_25			253
-MX53_PAD_DISP0_DAT20__SATA_PHY_TDI			254
-MX53_PAD_DISP0_DAT21__IPU_DISP0_DAT_21			255
-MX53_PAD_DISP0_DAT21__GPIO5_15				256
-MX53_PAD_DISP0_DAT21__ECSPI1_MOSI			257
-MX53_PAD_DISP0_DAT21__AUDMUX_AUD4_TXD			258
-MX53_PAD_DISP0_DAT21__SDMA_DEBUG_BUS_DEVICE_0		259
-MX53_PAD_DISP0_DAT21__EMI_EMI_DEBUG_26			260
-MX53_PAD_DISP0_DAT21__SATA_PHY_TDO			261
-MX53_PAD_DISP0_DAT22__IPU_DISP0_DAT_22			262
-MX53_PAD_DISP0_DAT22__GPIO5_16				263
-MX53_PAD_DISP0_DAT22__ECSPI1_MISO			264
-MX53_PAD_DISP0_DAT22__AUDMUX_AUD4_TXFS			265
-MX53_PAD_DISP0_DAT22__SDMA_DEBUG_BUS_DEVICE_1		266
-MX53_PAD_DISP0_DAT22__EMI_EMI_DEBUG_27			267
-MX53_PAD_DISP0_DAT22__SATA_PHY_TCK			268
-MX53_PAD_DISP0_DAT23__IPU_DISP0_DAT_23			269
-MX53_PAD_DISP0_DAT23__GPIO5_17				270
-MX53_PAD_DISP0_DAT23__ECSPI1_SS0			271
-MX53_PAD_DISP0_DAT23__AUDMUX_AUD4_RXD			272
-MX53_PAD_DISP0_DAT23__SDMA_DEBUG_BUS_DEVICE_2		273
-MX53_PAD_DISP0_DAT23__EMI_EMI_DEBUG_28			274
-MX53_PAD_DISP0_DAT23__SATA_PHY_TMS			275
-MX53_PAD_CSI0_PIXCLK__IPU_CSI0_PIXCLK			276
-MX53_PAD_CSI0_PIXCLK__GPIO5_18				277
-MX53_PAD_CSI0_PIXCLK__SDMA_DEBUG_PC_0			278
-MX53_PAD_CSI0_PIXCLK__EMI_EMI_DEBUG_29			279
-MX53_PAD_CSI0_MCLK__IPU_CSI0_HSYNC			280
-MX53_PAD_CSI0_MCLK__GPIO5_19				281
-MX53_PAD_CSI0_MCLK__CCM_CSI0_MCLK			282
-MX53_PAD_CSI0_MCLK__SDMA_DEBUG_PC_1			283
-MX53_PAD_CSI0_MCLK__EMI_EMI_DEBUG_30			284
-MX53_PAD_CSI0_MCLK__TPIU_TRCTL				285
-MX53_PAD_CSI0_DATA_EN__IPU_CSI0_DATA_EN			286
-MX53_PAD_CSI0_DATA_EN__GPIO5_20				287
-MX53_PAD_CSI0_DATA_EN__SDMA_DEBUG_PC_2			288
-MX53_PAD_CSI0_DATA_EN__EMI_EMI_DEBUG_31			289
-MX53_PAD_CSI0_DATA_EN__TPIU_TRCLK			290
-MX53_PAD_CSI0_VSYNC__IPU_CSI0_VSYNC			291
-MX53_PAD_CSI0_VSYNC__GPIO5_21				292
-MX53_PAD_CSI0_VSYNC__SDMA_DEBUG_PC_3			293
-MX53_PAD_CSI0_VSYNC__EMI_EMI_DEBUG_32			294
-MX53_PAD_CSI0_VSYNC__TPIU_TRACE_0			295
-MX53_PAD_CSI0_DAT4__IPU_CSI0_D_4			296
-MX53_PAD_CSI0_DAT4__GPIO5_22				297
-MX53_PAD_CSI0_DAT4__KPP_COL_5				298
-MX53_PAD_CSI0_DAT4__ECSPI1_SCLK				299
-MX53_PAD_CSI0_DAT4__USBOH3_USBH3_STP			300
-MX53_PAD_CSI0_DAT4__AUDMUX_AUD3_TXC			301
-MX53_PAD_CSI0_DAT4__EMI_EMI_DEBUG_33			302
-MX53_PAD_CSI0_DAT4__TPIU_TRACE_1			303
-MX53_PAD_CSI0_DAT5__IPU_CSI0_D_5			304
-MX53_PAD_CSI0_DAT5__GPIO5_23				305
-MX53_PAD_CSI0_DAT5__KPP_ROW_5				306
-MX53_PAD_CSI0_DAT5__ECSPI1_MOSI				307
-MX53_PAD_CSI0_DAT5__USBOH3_USBH3_NXT			308
-MX53_PAD_CSI0_DAT5__AUDMUX_AUD3_TXD			309
-MX53_PAD_CSI0_DAT5__EMI_EMI_DEBUG_34			310
-MX53_PAD_CSI0_DAT5__TPIU_TRACE_2			311
-MX53_PAD_CSI0_DAT6__IPU_CSI0_D_6			312
-MX53_PAD_CSI0_DAT6__GPIO5_24				313
-MX53_PAD_CSI0_DAT6__KPP_COL_6				314
-MX53_PAD_CSI0_DAT6__ECSPI1_MISO				315
-MX53_PAD_CSI0_DAT6__USBOH3_USBH3_CLK			316
-MX53_PAD_CSI0_DAT6__AUDMUX_AUD3_TXFS			317
-MX53_PAD_CSI0_DAT6__EMI_EMI_DEBUG_35			318
-MX53_PAD_CSI0_DAT6__TPIU_TRACE_3			319
-MX53_PAD_CSI0_DAT7__IPU_CSI0_D_7			320
-MX53_PAD_CSI0_DAT7__GPIO5_25				321
-MX53_PAD_CSI0_DAT7__KPP_ROW_6				322
-MX53_PAD_CSI0_DAT7__ECSPI1_SS0				323
-MX53_PAD_CSI0_DAT7__USBOH3_USBH3_DIR			324
-MX53_PAD_CSI0_DAT7__AUDMUX_AUD3_RXD			325
-MX53_PAD_CSI0_DAT7__EMI_EMI_DEBUG_36			326
-MX53_PAD_CSI0_DAT7__TPIU_TRACE_4			327
-MX53_PAD_CSI0_DAT8__IPU_CSI0_D_8			328
-MX53_PAD_CSI0_DAT8__GPIO5_26				329
-MX53_PAD_CSI0_DAT8__KPP_COL_7				330
-MX53_PAD_CSI0_DAT8__ECSPI2_SCLK				331
-MX53_PAD_CSI0_DAT8__USBOH3_USBH3_OC			332
-MX53_PAD_CSI0_DAT8__I2C1_SDA				333
-MX53_PAD_CSI0_DAT8__EMI_EMI_DEBUG_37			334
-MX53_PAD_CSI0_DAT8__TPIU_TRACE_5			335
-MX53_PAD_CSI0_DAT9__IPU_CSI0_D_9			336
-MX53_PAD_CSI0_DAT9__GPIO5_27				337
-MX53_PAD_CSI0_DAT9__KPP_ROW_7				338
-MX53_PAD_CSI0_DAT9__ECSPI2_MOSI				339
-MX53_PAD_CSI0_DAT9__USBOH3_USBH3_PWR			340
-MX53_PAD_CSI0_DAT9__I2C1_SCL				341
-MX53_PAD_CSI0_DAT9__EMI_EMI_DEBUG_38			342
-MX53_PAD_CSI0_DAT9__TPIU_TRACE_6			343
-MX53_PAD_CSI0_DAT10__IPU_CSI0_D_10			344
-MX53_PAD_CSI0_DAT10__GPIO5_28				345
-MX53_PAD_CSI0_DAT10__UART1_TXD_MUX			346
-MX53_PAD_CSI0_DAT10__ECSPI2_MISO			347
-MX53_PAD_CSI0_DAT10__AUDMUX_AUD3_RXC			348
-MX53_PAD_CSI0_DAT10__SDMA_DEBUG_PC_4			349
-MX53_PAD_CSI0_DAT10__EMI_EMI_DEBUG_39			350
-MX53_PAD_CSI0_DAT10__TPIU_TRACE_7			351
-MX53_PAD_CSI0_DAT11__IPU_CSI0_D_11			352
-MX53_PAD_CSI0_DAT11__GPIO5_29				353
-MX53_PAD_CSI0_DAT11__UART1_RXD_MUX			354
-MX53_PAD_CSI0_DAT11__ECSPI2_SS0				355
-MX53_PAD_CSI0_DAT11__AUDMUX_AUD3_RXFS			356
-MX53_PAD_CSI0_DAT11__SDMA_DEBUG_PC_5			357
-MX53_PAD_CSI0_DAT11__EMI_EMI_DEBUG_40			358
-MX53_PAD_CSI0_DAT11__TPIU_TRACE_8			359
-MX53_PAD_CSI0_DAT12__IPU_CSI0_D_12			360
-MX53_PAD_CSI0_DAT12__GPIO5_30				361
-MX53_PAD_CSI0_DAT12__UART4_TXD_MUX			362
-MX53_PAD_CSI0_DAT12__USBOH3_USBH3_DATA_0		363
-MX53_PAD_CSI0_DAT12__SDMA_DEBUG_PC_6			364
-MX53_PAD_CSI0_DAT12__EMI_EMI_DEBUG_41			365
-MX53_PAD_CSI0_DAT12__TPIU_TRACE_9			366
-MX53_PAD_CSI0_DAT13__IPU_CSI0_D_13			367
-MX53_PAD_CSI0_DAT13__GPIO5_31				368
-MX53_PAD_CSI0_DAT13__UART4_RXD_MUX			369
-MX53_PAD_CSI0_DAT13__USBOH3_USBH3_DATA_1		370
-MX53_PAD_CSI0_DAT13__SDMA_DEBUG_PC_7			371
-MX53_PAD_CSI0_DAT13__EMI_EMI_DEBUG_42			372
-MX53_PAD_CSI0_DAT13__TPIU_TRACE_10			373
-MX53_PAD_CSI0_DAT14__IPU_CSI0_D_14			374
-MX53_PAD_CSI0_DAT14__GPIO6_0				375
-MX53_PAD_CSI0_DAT14__UART5_TXD_MUX			376
-MX53_PAD_CSI0_DAT14__USBOH3_USBH3_DATA_2		377
-MX53_PAD_CSI0_DAT14__SDMA_DEBUG_PC_8			378
-MX53_PAD_CSI0_DAT14__EMI_EMI_DEBUG_43			379
-MX53_PAD_CSI0_DAT14__TPIU_TRACE_11			380
-MX53_PAD_CSI0_DAT15__IPU_CSI0_D_15			381
-MX53_PAD_CSI0_DAT15__GPIO6_1				382
-MX53_PAD_CSI0_DAT15__UART5_RXD_MUX			383
-MX53_PAD_CSI0_DAT15__USBOH3_USBH3_DATA_3		384
-MX53_PAD_CSI0_DAT15__SDMA_DEBUG_PC_9			385
-MX53_PAD_CSI0_DAT15__EMI_EMI_DEBUG_44			386
-MX53_PAD_CSI0_DAT15__TPIU_TRACE_12			387
-MX53_PAD_CSI0_DAT16__IPU_CSI0_D_16			388
-MX53_PAD_CSI0_DAT16__GPIO6_2				389
-MX53_PAD_CSI0_DAT16__UART4_RTS				390
-MX53_PAD_CSI0_DAT16__USBOH3_USBH3_DATA_4		391
-MX53_PAD_CSI0_DAT16__SDMA_DEBUG_PC_10			392
-MX53_PAD_CSI0_DAT16__EMI_EMI_DEBUG_45			393
-MX53_PAD_CSI0_DAT16__TPIU_TRACE_13			394
-MX53_PAD_CSI0_DAT17__IPU_CSI0_D_17			395
-MX53_PAD_CSI0_DAT17__GPIO6_3				396
-MX53_PAD_CSI0_DAT17__UART4_CTS				397
-MX53_PAD_CSI0_DAT17__USBOH3_USBH3_DATA_5		398
-MX53_PAD_CSI0_DAT17__SDMA_DEBUG_PC_11			399
-MX53_PAD_CSI0_DAT17__EMI_EMI_DEBUG_46			400
-MX53_PAD_CSI0_DAT17__TPIU_TRACE_14			401
-MX53_PAD_CSI0_DAT18__IPU_CSI0_D_18			402
-MX53_PAD_CSI0_DAT18__GPIO6_4				403
-MX53_PAD_CSI0_DAT18__UART5_RTS				404
-MX53_PAD_CSI0_DAT18__USBOH3_USBH3_DATA_6		405
-MX53_PAD_CSI0_DAT18__SDMA_DEBUG_PC_12			406
-MX53_PAD_CSI0_DAT18__EMI_EMI_DEBUG_47			407
-MX53_PAD_CSI0_DAT18__TPIU_TRACE_15			408
-MX53_PAD_CSI0_DAT19__IPU_CSI0_D_19			409
-MX53_PAD_CSI0_DAT19__GPIO6_5				410
-MX53_PAD_CSI0_DAT19__UART5_CTS				411
-MX53_PAD_CSI0_DAT19__USBOH3_USBH3_DATA_7		412
-MX53_PAD_CSI0_DAT19__SDMA_DEBUG_PC_13			413
-MX53_PAD_CSI0_DAT19__EMI_EMI_DEBUG_48			414
-MX53_PAD_CSI0_DAT19__USBPHY2_BISTOK			415
-MX53_PAD_EIM_A25__EMI_WEIM_A_25				416
-MX53_PAD_EIM_A25__GPIO5_2				417
-MX53_PAD_EIM_A25__ECSPI2_RDY				418
-MX53_PAD_EIM_A25__IPU_DI1_PIN12				419
-MX53_PAD_EIM_A25__CSPI_SS1				420
-MX53_PAD_EIM_A25__IPU_DI0_D1_CS				421
-MX53_PAD_EIM_A25__USBPHY1_BISTOK			422
-MX53_PAD_EIM_EB2__EMI_WEIM_EB_2				423
-MX53_PAD_EIM_EB2__GPIO2_30				424
-MX53_PAD_EIM_EB2__CCM_DI1_EXT_CLK			425
-MX53_PAD_EIM_EB2__IPU_SER_DISP1_CS			426
-MX53_PAD_EIM_EB2__ECSPI1_SS0				427
-MX53_PAD_EIM_EB2__I2C2_SCL				428
-MX53_PAD_EIM_D16__EMI_WEIM_D_16				429
-MX53_PAD_EIM_D16__GPIO3_16				430
-MX53_PAD_EIM_D16__IPU_DI0_PIN5				431
-MX53_PAD_EIM_D16__IPU_DISPB1_SER_CLK			432
-MX53_PAD_EIM_D16__ECSPI1_SCLK				433
-MX53_PAD_EIM_D16__I2C2_SDA				434
-MX53_PAD_EIM_D17__EMI_WEIM_D_17				435
-MX53_PAD_EIM_D17__GPIO3_17				436
-MX53_PAD_EIM_D17__IPU_DI0_PIN6				437
-MX53_PAD_EIM_D17__IPU_DISPB1_SER_DIN			438
-MX53_PAD_EIM_D17__ECSPI1_MISO				439
-MX53_PAD_EIM_D17__I2C3_SCL				440
-MX53_PAD_EIM_D18__EMI_WEIM_D_18				441
-MX53_PAD_EIM_D18__GPIO3_18				442
-MX53_PAD_EIM_D18__IPU_DI0_PIN7				443
-MX53_PAD_EIM_D18__IPU_DISPB1_SER_DIO			444
-MX53_PAD_EIM_D18__ECSPI1_MOSI				445
-MX53_PAD_EIM_D18__I2C3_SDA				446
-MX53_PAD_EIM_D18__IPU_DI1_D0_CS				447
-MX53_PAD_EIM_D19__EMI_WEIM_D_19				448
-MX53_PAD_EIM_D19__GPIO3_19				449
-MX53_PAD_EIM_D19__IPU_DI0_PIN8				450
-MX53_PAD_EIM_D19__IPU_DISPB1_SER_RS			451
-MX53_PAD_EIM_D19__ECSPI1_SS1				452
-MX53_PAD_EIM_D19__EPIT1_EPITO				453
-MX53_PAD_EIM_D19__UART1_CTS				454
-MX53_PAD_EIM_D19__USBOH3_USBH2_OC			455
-MX53_PAD_EIM_D20__EMI_WEIM_D_20				456
-MX53_PAD_EIM_D20__GPIO3_20				457
-MX53_PAD_EIM_D20__IPU_DI0_PIN16				458
-MX53_PAD_EIM_D20__IPU_SER_DISP0_CS			459
-MX53_PAD_EIM_D20__CSPI_SS0				460
-MX53_PAD_EIM_D20__EPIT2_EPITO				461
-MX53_PAD_EIM_D20__UART1_RTS				462
-MX53_PAD_EIM_D20__USBOH3_USBH2_PWR			463
-MX53_PAD_EIM_D21__EMI_WEIM_D_21				464
-MX53_PAD_EIM_D21__GPIO3_21				465
-MX53_PAD_EIM_D21__IPU_DI0_PIN17				466
-MX53_PAD_EIM_D21__IPU_DISPB0_SER_CLK			467
-MX53_PAD_EIM_D21__CSPI_SCLK				468
-MX53_PAD_EIM_D21__I2C1_SCL				469
-MX53_PAD_EIM_D21__USBOH3_USBOTG_OC			470
-MX53_PAD_EIM_D22__EMI_WEIM_D_22				471
-MX53_PAD_EIM_D22__GPIO3_22				472
-MX53_PAD_EIM_D22__IPU_DI0_PIN1				473
-MX53_PAD_EIM_D22__IPU_DISPB0_SER_DIN			474
-MX53_PAD_EIM_D22__CSPI_MISO				475
-MX53_PAD_EIM_D22__USBOH3_USBOTG_PWR			476
-MX53_PAD_EIM_D23__EMI_WEIM_D_23				477
-MX53_PAD_EIM_D23__GPIO3_23				478
-MX53_PAD_EIM_D23__UART3_CTS				479
-MX53_PAD_EIM_D23__UART1_DCD				480
-MX53_PAD_EIM_D23__IPU_DI0_D0_CS				481
-MX53_PAD_EIM_D23__IPU_DI1_PIN2				482
-MX53_PAD_EIM_D23__IPU_CSI1_DATA_EN			483
-MX53_PAD_EIM_D23__IPU_DI1_PIN14				484
-MX53_PAD_EIM_EB3__EMI_WEIM_EB_3				485
-MX53_PAD_EIM_EB3__GPIO2_31				486
-MX53_PAD_EIM_EB3__UART3_RTS				487
-MX53_PAD_EIM_EB3__UART1_RI				488
-MX53_PAD_EIM_EB3__IPU_DI1_PIN3				489
-MX53_PAD_EIM_EB3__IPU_CSI1_HSYNC			490
-MX53_PAD_EIM_EB3__IPU_DI1_PIN16				491
-MX53_PAD_EIM_D24__EMI_WEIM_D_24				492
-MX53_PAD_EIM_D24__GPIO3_24				493
-MX53_PAD_EIM_D24__UART3_TXD_MUX				494
-MX53_PAD_EIM_D24__ECSPI1_SS2				495
-MX53_PAD_EIM_D24__CSPI_SS2				496
-MX53_PAD_EIM_D24__AUDMUX_AUD5_RXFS			497
-MX53_PAD_EIM_D24__ECSPI2_SS2				498
-MX53_PAD_EIM_D24__UART1_DTR				499
-MX53_PAD_EIM_D25__EMI_WEIM_D_25				500
-MX53_PAD_EIM_D25__GPIO3_25				501
-MX53_PAD_EIM_D25__UART3_RXD_MUX				502
-MX53_PAD_EIM_D25__ECSPI1_SS3				503
-MX53_PAD_EIM_D25__CSPI_SS3				504
-MX53_PAD_EIM_D25__AUDMUX_AUD5_RXC			505
-MX53_PAD_EIM_D25__ECSPI2_SS3				506
-MX53_PAD_EIM_D25__UART1_DSR				507
-MX53_PAD_EIM_D26__EMI_WEIM_D_26				508
-MX53_PAD_EIM_D26__GPIO3_26				509
-MX53_PAD_EIM_D26__UART2_TXD_MUX				510
-MX53_PAD_EIM_D26__FIRI_RXD				511
-MX53_PAD_EIM_D26__IPU_CSI0_D_1				512
-MX53_PAD_EIM_D26__IPU_DI1_PIN11				513
-MX53_PAD_EIM_D26__IPU_SISG_2				514
-MX53_PAD_EIM_D26__IPU_DISP1_DAT_22			515
-MX53_PAD_EIM_D27__EMI_WEIM_D_27				516
-MX53_PAD_EIM_D27__GPIO3_27				517
-MX53_PAD_EIM_D27__UART2_RXD_MUX				518
-MX53_PAD_EIM_D27__FIRI_TXD				519
-MX53_PAD_EIM_D27__IPU_CSI0_D_0				520
-MX53_PAD_EIM_D27__IPU_DI1_PIN13				521
-MX53_PAD_EIM_D27__IPU_SISG_3				522
-MX53_PAD_EIM_D27__IPU_DISP1_DAT_23			523
-MX53_PAD_EIM_D28__EMI_WEIM_D_28				524
-MX53_PAD_EIM_D28__GPIO3_28				525
-MX53_PAD_EIM_D28__UART2_CTS				526
-MX53_PAD_EIM_D28__IPU_DISPB0_SER_DIO			527
-MX53_PAD_EIM_D28__CSPI_MOSI				528
-MX53_PAD_EIM_D28__I2C1_SDA				529
-MX53_PAD_EIM_D28__IPU_EXT_TRIG				530
-MX53_PAD_EIM_D28__IPU_DI0_PIN13				531
-MX53_PAD_EIM_D29__EMI_WEIM_D_29				532
-MX53_PAD_EIM_D29__GPIO3_29				533
-MX53_PAD_EIM_D29__UART2_RTS				534
-MX53_PAD_EIM_D29__IPU_DISPB0_SER_RS			535
-MX53_PAD_EIM_D29__CSPI_SS0				536
-MX53_PAD_EIM_D29__IPU_DI1_PIN15				537
-MX53_PAD_EIM_D29__IPU_CSI1_VSYNC			538
-MX53_PAD_EIM_D29__IPU_DI0_PIN14				539
-MX53_PAD_EIM_D30__EMI_WEIM_D_30				540
-MX53_PAD_EIM_D30__GPIO3_30				541
-MX53_PAD_EIM_D30__UART3_CTS				542
-MX53_PAD_EIM_D30__IPU_CSI0_D_3				543
-MX53_PAD_EIM_D30__IPU_DI0_PIN11				544
-MX53_PAD_EIM_D30__IPU_DISP1_DAT_21			545
-MX53_PAD_EIM_D30__USBOH3_USBH1_OC			546
-MX53_PAD_EIM_D30__USBOH3_USBH2_OC			547
-MX53_PAD_EIM_D31__EMI_WEIM_D_31				548
-MX53_PAD_EIM_D31__GPIO3_31				549
-MX53_PAD_EIM_D31__UART3_RTS				550
-MX53_PAD_EIM_D31__IPU_CSI0_D_2				551
-MX53_PAD_EIM_D31__IPU_DI0_PIN12				552
-MX53_PAD_EIM_D31__IPU_DISP1_DAT_20			553
-MX53_PAD_EIM_D31__USBOH3_USBH1_PWR			554
-MX53_PAD_EIM_D31__USBOH3_USBH2_PWR			555
-MX53_PAD_EIM_A24__EMI_WEIM_A_24				556
-MX53_PAD_EIM_A24__GPIO5_4				557
-MX53_PAD_EIM_A24__IPU_DISP1_DAT_19			558
-MX53_PAD_EIM_A24__IPU_CSI1_D_19				559
-MX53_PAD_EIM_A24__IPU_SISG_2				560
-MX53_PAD_EIM_A24__USBPHY2_BVALID			561
-MX53_PAD_EIM_A23__EMI_WEIM_A_23				562
-MX53_PAD_EIM_A23__GPIO6_6				563
-MX53_PAD_EIM_A23__IPU_DISP1_DAT_18			564
-MX53_PAD_EIM_A23__IPU_CSI1_D_18				565
-MX53_PAD_EIM_A23__IPU_SISG_3				566
-MX53_PAD_EIM_A23__USBPHY2_ENDSESSION			567
-MX53_PAD_EIM_A22__EMI_WEIM_A_22				568
-MX53_PAD_EIM_A22__GPIO2_16				569
-MX53_PAD_EIM_A22__IPU_DISP1_DAT_17			570
-MX53_PAD_EIM_A22__IPU_CSI1_D_17				571
-MX53_PAD_EIM_A22__SRC_BT_CFG1_7				572
-MX53_PAD_EIM_A21__EMI_WEIM_A_21				573
-MX53_PAD_EIM_A21__GPIO2_17				574
-MX53_PAD_EIM_A21__IPU_DISP1_DAT_16			575
-MX53_PAD_EIM_A21__IPU_CSI1_D_16				576
-MX53_PAD_EIM_A21__SRC_BT_CFG1_6				577
-MX53_PAD_EIM_A20__EMI_WEIM_A_20				578
-MX53_PAD_EIM_A20__GPIO2_18				579
-MX53_PAD_EIM_A20__IPU_DISP1_DAT_15			580
-MX53_PAD_EIM_A20__IPU_CSI1_D_15				581
-MX53_PAD_EIM_A20__SRC_BT_CFG1_5				582
-MX53_PAD_EIM_A19__EMI_WEIM_A_19				583
-MX53_PAD_EIM_A19__GPIO2_19				584
-MX53_PAD_EIM_A19__IPU_DISP1_DAT_14			585
-MX53_PAD_EIM_A19__IPU_CSI1_D_14				586
-MX53_PAD_EIM_A19__SRC_BT_CFG1_4				587
-MX53_PAD_EIM_A18__EMI_WEIM_A_18				588
-MX53_PAD_EIM_A18__GPIO2_20				589
-MX53_PAD_EIM_A18__IPU_DISP1_DAT_13			590
-MX53_PAD_EIM_A18__IPU_CSI1_D_13				591
-MX53_PAD_EIM_A18__SRC_BT_CFG1_3				592
-MX53_PAD_EIM_A17__EMI_WEIM_A_17				593
-MX53_PAD_EIM_A17__GPIO2_21				594
-MX53_PAD_EIM_A17__IPU_DISP1_DAT_12			595
-MX53_PAD_EIM_A17__IPU_CSI1_D_12				596
-MX53_PAD_EIM_A17__SRC_BT_CFG1_2				597
-MX53_PAD_EIM_A16__EMI_WEIM_A_16				598
-MX53_PAD_EIM_A16__GPIO2_22				599
-MX53_PAD_EIM_A16__IPU_DI1_DISP_CLK			600
-MX53_PAD_EIM_A16__IPU_CSI1_PIXCLK			601
-MX53_PAD_EIM_A16__SRC_BT_CFG1_1				602
-MX53_PAD_EIM_CS0__EMI_WEIM_CS_0				603
-MX53_PAD_EIM_CS0__GPIO2_23				604
-MX53_PAD_EIM_CS0__ECSPI2_SCLK				605
-MX53_PAD_EIM_CS0__IPU_DI1_PIN5				606
-MX53_PAD_EIM_CS1__EMI_WEIM_CS_1				607
-MX53_PAD_EIM_CS1__GPIO2_24				608
-MX53_PAD_EIM_CS1__ECSPI2_MOSI				609
-MX53_PAD_EIM_CS1__IPU_DI1_PIN6				610
-MX53_PAD_EIM_OE__EMI_WEIM_OE				611
-MX53_PAD_EIM_OE__GPIO2_25				612
-MX53_PAD_EIM_OE__ECSPI2_MISO				613
-MX53_PAD_EIM_OE__IPU_DI1_PIN7				614
-MX53_PAD_EIM_OE__USBPHY2_IDDIG				615
-MX53_PAD_EIM_RW__EMI_WEIM_RW				616
-MX53_PAD_EIM_RW__GPIO2_26				617
-MX53_PAD_EIM_RW__ECSPI2_SS0				618
-MX53_PAD_EIM_RW__IPU_DI1_PIN8				619
-MX53_PAD_EIM_RW__USBPHY2_HOSTDISCONNECT			620
-MX53_PAD_EIM_LBA__EMI_WEIM_LBA				621
-MX53_PAD_EIM_LBA__GPIO2_27				622
-MX53_PAD_EIM_LBA__ECSPI2_SS1				623
-MX53_PAD_EIM_LBA__IPU_DI1_PIN17				624
-MX53_PAD_EIM_LBA__SRC_BT_CFG1_0				625
-MX53_PAD_EIM_EB0__EMI_WEIM_EB_0				626
-MX53_PAD_EIM_EB0__GPIO2_28				627
-MX53_PAD_EIM_EB0__IPU_DISP1_DAT_11			628
-MX53_PAD_EIM_EB0__IPU_CSI1_D_11				629
-MX53_PAD_EIM_EB0__GPC_PMIC_RDY				630
-MX53_PAD_EIM_EB0__SRC_BT_CFG2_7				631
-MX53_PAD_EIM_EB1__EMI_WEIM_EB_1				632
-MX53_PAD_EIM_EB1__GPIO2_29				633
-MX53_PAD_EIM_EB1__IPU_DISP1_DAT_10			634
-MX53_PAD_EIM_EB1__IPU_CSI1_D_10				635
-MX53_PAD_EIM_EB1__SRC_BT_CFG2_6				636
-MX53_PAD_EIM_DA0__EMI_NAND_WEIM_DA_0			637
-MX53_PAD_EIM_DA0__GPIO3_0				638
-MX53_PAD_EIM_DA0__IPU_DISP1_DAT_9			639
-MX53_PAD_EIM_DA0__IPU_CSI1_D_9				640
-MX53_PAD_EIM_DA0__SRC_BT_CFG2_5				641
-MX53_PAD_EIM_DA1__EMI_NAND_WEIM_DA_1			642
-MX53_PAD_EIM_DA1__GPIO3_1				643
-MX53_PAD_EIM_DA1__IPU_DISP1_DAT_8			644
-MX53_PAD_EIM_DA1__IPU_CSI1_D_8				645
-MX53_PAD_EIM_DA1__SRC_BT_CFG2_4				646
-MX53_PAD_EIM_DA2__EMI_NAND_WEIM_DA_2			647
-MX53_PAD_EIM_DA2__GPIO3_2				648
-MX53_PAD_EIM_DA2__IPU_DISP1_DAT_7			649
-MX53_PAD_EIM_DA2__IPU_CSI1_D_7				650
-MX53_PAD_EIM_DA2__SRC_BT_CFG2_3				651
-MX53_PAD_EIM_DA3__EMI_NAND_WEIM_DA_3			652
-MX53_PAD_EIM_DA3__GPIO3_3				653
-MX53_PAD_EIM_DA3__IPU_DISP1_DAT_6			654
-MX53_PAD_EIM_DA3__IPU_CSI1_D_6				655
-MX53_PAD_EIM_DA3__SRC_BT_CFG2_2				656
-MX53_PAD_EIM_DA4__EMI_NAND_WEIM_DA_4			657
-MX53_PAD_EIM_DA4__GPIO3_4				658
-MX53_PAD_EIM_DA4__IPU_DISP1_DAT_5			659
-MX53_PAD_EIM_DA4__IPU_CSI1_D_5				660
-MX53_PAD_EIM_DA4__SRC_BT_CFG3_7				661
-MX53_PAD_EIM_DA5__EMI_NAND_WEIM_DA_5			662
-MX53_PAD_EIM_DA5__GPIO3_5				663
-MX53_PAD_EIM_DA5__IPU_DISP1_DAT_4			664
-MX53_PAD_EIM_DA5__IPU_CSI1_D_4				665
-MX53_PAD_EIM_DA5__SRC_BT_CFG3_6				666
-MX53_PAD_EIM_DA6__EMI_NAND_WEIM_DA_6			667
-MX53_PAD_EIM_DA6__GPIO3_6				668
-MX53_PAD_EIM_DA6__IPU_DISP1_DAT_3			669
-MX53_PAD_EIM_DA6__IPU_CSI1_D_3				670
-MX53_PAD_EIM_DA6__SRC_BT_CFG3_5				671
-MX53_PAD_EIM_DA7__EMI_NAND_WEIM_DA_7			672
-MX53_PAD_EIM_DA7__GPIO3_7				673
-MX53_PAD_EIM_DA7__IPU_DISP1_DAT_2			674
-MX53_PAD_EIM_DA7__IPU_CSI1_D_2				675
-MX53_PAD_EIM_DA7__SRC_BT_CFG3_4				676
-MX53_PAD_EIM_DA8__EMI_NAND_WEIM_DA_8			677
-MX53_PAD_EIM_DA8__GPIO3_8				678
-MX53_PAD_EIM_DA8__IPU_DISP1_DAT_1			679
-MX53_PAD_EIM_DA8__IPU_CSI1_D_1				680
-MX53_PAD_EIM_DA8__SRC_BT_CFG3_3				681
-MX53_PAD_EIM_DA9__EMI_NAND_WEIM_DA_9			682
-MX53_PAD_EIM_DA9__GPIO3_9				683
-MX53_PAD_EIM_DA9__IPU_DISP1_DAT_0			684
-MX53_PAD_EIM_DA9__IPU_CSI1_D_0				685
-MX53_PAD_EIM_DA9__SRC_BT_CFG3_2				686
-MX53_PAD_EIM_DA10__EMI_NAND_WEIM_DA_10			687
-MX53_PAD_EIM_DA10__GPIO3_10				688
-MX53_PAD_EIM_DA10__IPU_DI1_PIN15			689
-MX53_PAD_EIM_DA10__IPU_CSI1_DATA_EN			690
-MX53_PAD_EIM_DA10__SRC_BT_CFG3_1			691
-MX53_PAD_EIM_DA11__EMI_NAND_WEIM_DA_11			692
-MX53_PAD_EIM_DA11__GPIO3_11				693
-MX53_PAD_EIM_DA11__IPU_DI1_PIN2				694
-MX53_PAD_EIM_DA11__IPU_CSI1_HSYNC			695
-MX53_PAD_EIM_DA12__EMI_NAND_WEIM_DA_12			696
-MX53_PAD_EIM_DA12__GPIO3_12				697
-MX53_PAD_EIM_DA12__IPU_DI1_PIN3				698
-MX53_PAD_EIM_DA12__IPU_CSI1_VSYNC			699
-MX53_PAD_EIM_DA13__EMI_NAND_WEIM_DA_13			700
-MX53_PAD_EIM_DA13__GPIO3_13				701
-MX53_PAD_EIM_DA13__IPU_DI1_D0_CS			702
-MX53_PAD_EIM_DA13__CCM_DI1_EXT_CLK			703
-MX53_PAD_EIM_DA14__EMI_NAND_WEIM_DA_14			704
-MX53_PAD_EIM_DA14__GPIO3_14				705
-MX53_PAD_EIM_DA14__IPU_DI1_D1_CS			706
-MX53_PAD_EIM_DA14__CCM_DI0_EXT_CLK			707
-MX53_PAD_EIM_DA15__EMI_NAND_WEIM_DA_15			708
-MX53_PAD_EIM_DA15__GPIO3_15				709
-MX53_PAD_EIM_DA15__IPU_DI1_PIN1				710
-MX53_PAD_EIM_DA15__IPU_DI1_PIN4				711
-MX53_PAD_NANDF_WE_B__EMI_NANDF_WE_B			712
-MX53_PAD_NANDF_WE_B__GPIO6_12				713
-MX53_PAD_NANDF_RE_B__EMI_NANDF_RE_B			714
-MX53_PAD_NANDF_RE_B__GPIO6_13				715
-MX53_PAD_EIM_WAIT__EMI_WEIM_WAIT			716
-MX53_PAD_EIM_WAIT__GPIO5_0				717
-MX53_PAD_EIM_WAIT__EMI_WEIM_DTACK_B			718
-MX53_PAD_LVDS1_TX3_P__GPIO6_22				719
-MX53_PAD_LVDS1_TX3_P__LDB_LVDS1_TX3			720
-MX53_PAD_LVDS1_TX2_P__GPIO6_24				721
-MX53_PAD_LVDS1_TX2_P__LDB_LVDS1_TX2			722
-MX53_PAD_LVDS1_CLK_P__GPIO6_26				723
-MX53_PAD_LVDS1_CLK_P__LDB_LVDS1_CLK			724
-MX53_PAD_LVDS1_TX1_P__GPIO6_28				725
-MX53_PAD_LVDS1_TX1_P__LDB_LVDS1_TX1			726
-MX53_PAD_LVDS1_TX0_P__GPIO6_30				727
-MX53_PAD_LVDS1_TX0_P__LDB_LVDS1_TX0			728
-MX53_PAD_LVDS0_TX3_P__GPIO7_22				729
-MX53_PAD_LVDS0_TX3_P__LDB_LVDS0_TX3			730
-MX53_PAD_LVDS0_CLK_P__GPIO7_24				731
-MX53_PAD_LVDS0_CLK_P__LDB_LVDS0_CLK			732
-MX53_PAD_LVDS0_TX2_P__GPIO7_26				733
-MX53_PAD_LVDS0_TX2_P__LDB_LVDS0_TX2			734
-MX53_PAD_LVDS0_TX1_P__GPIO7_28				735
-MX53_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1			736
-MX53_PAD_LVDS0_TX0_P__GPIO7_30				737
-MX53_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0			738
-MX53_PAD_GPIO_10__GPIO4_0				739
-MX53_PAD_GPIO_10__OSC32k_32K_OUT			740
-MX53_PAD_GPIO_11__GPIO4_1				741
-MX53_PAD_GPIO_12__GPIO4_2				742
-MX53_PAD_GPIO_13__GPIO4_3				743
-MX53_PAD_GPIO_14__GPIO4_4				744
-MX53_PAD_NANDF_CLE__EMI_NANDF_CLE			745
-MX53_PAD_NANDF_CLE__GPIO6_7				746
-MX53_PAD_NANDF_CLE__USBPHY1_VSTATUS_0			747
-MX53_PAD_NANDF_ALE__EMI_NANDF_ALE			748
-MX53_PAD_NANDF_ALE__GPIO6_8				749
-MX53_PAD_NANDF_ALE__USBPHY1_VSTATUS_1			750
-MX53_PAD_NANDF_WP_B__EMI_NANDF_WP_B			751
-MX53_PAD_NANDF_WP_B__GPIO6_9				752
-MX53_PAD_NANDF_WP_B__USBPHY1_VSTATUS_2			753
-MX53_PAD_NANDF_RB0__EMI_NANDF_RB_0			754
-MX53_PAD_NANDF_RB0__GPIO6_10				755
-MX53_PAD_NANDF_RB0__USBPHY1_VSTATUS_3			756
-MX53_PAD_NANDF_CS0__EMI_NANDF_CS_0			757
-MX53_PAD_NANDF_CS0__GPIO6_11				758
-MX53_PAD_NANDF_CS0__USBPHY1_VSTATUS_4			759
-MX53_PAD_NANDF_CS1__EMI_NANDF_CS_1			760
-MX53_PAD_NANDF_CS1__GPIO6_14				761
-MX53_PAD_NANDF_CS1__MLB_MLBCLK				762
-MX53_PAD_NANDF_CS1__USBPHY1_VSTATUS_5			763
-MX53_PAD_NANDF_CS2__EMI_NANDF_CS_2			764
-MX53_PAD_NANDF_CS2__GPIO6_15				765
-MX53_PAD_NANDF_CS2__IPU_SISG_0				766
-MX53_PAD_NANDF_CS2__ESAI1_TX0				767
-MX53_PAD_NANDF_CS2__EMI_WEIM_CRE			768
-MX53_PAD_NANDF_CS2__CCM_CSI0_MCLK			769
-MX53_PAD_NANDF_CS2__MLB_MLBSIG				770
-MX53_PAD_NANDF_CS2__USBPHY1_VSTATUS_6			771
-MX53_PAD_NANDF_CS3__EMI_NANDF_CS_3			772
-MX53_PAD_NANDF_CS3__GPIO6_16				773
-MX53_PAD_NANDF_CS3__IPU_SISG_1				774
-MX53_PAD_NANDF_CS3__ESAI1_TX1				775
-MX53_PAD_NANDF_CS3__EMI_WEIM_A_26			776
-MX53_PAD_NANDF_CS3__MLB_MLBDAT				777
-MX53_PAD_NANDF_CS3__USBPHY1_VSTATUS_7			778
-MX53_PAD_FEC_MDIO__FEC_MDIO				779
-MX53_PAD_FEC_MDIO__GPIO1_22				780
-MX53_PAD_FEC_MDIO__ESAI1_SCKR				781
-MX53_PAD_FEC_MDIO__FEC_COL				782
-MX53_PAD_FEC_MDIO__RTC_CE_RTC_PS2			783
-MX53_PAD_FEC_MDIO__SDMA_DEBUG_BUS_DEVICE_3		784
-MX53_PAD_FEC_MDIO__EMI_EMI_DEBUG_49			785
-MX53_PAD_FEC_REF_CLK__FEC_TX_CLK			786
-MX53_PAD_FEC_REF_CLK__GPIO1_23				787
-MX53_PAD_FEC_REF_CLK__ESAI1_FSR				788
-MX53_PAD_FEC_REF_CLK__SDMA_DEBUG_BUS_DEVICE_4		789
-MX53_PAD_FEC_REF_CLK__EMI_EMI_DEBUG_50			790
-MX53_PAD_FEC_RX_ER__FEC_RX_ER				791
-MX53_PAD_FEC_RX_ER__GPIO1_24				792
-MX53_PAD_FEC_RX_ER__ESAI1_HCKR				793
-MX53_PAD_FEC_RX_ER__FEC_RX_CLK				794
-MX53_PAD_FEC_RX_ER__RTC_CE_RTC_PS3			795
-MX53_PAD_FEC_CRS_DV__FEC_RX_DV				796
-MX53_PAD_FEC_CRS_DV__GPIO1_25				797
-MX53_PAD_FEC_CRS_DV__ESAI1_SCKT				798
-MX53_PAD_FEC_RXD1__FEC_RDATA_1				799
-MX53_PAD_FEC_RXD1__GPIO1_26				800
-MX53_PAD_FEC_RXD1__ESAI1_FST				801
-MX53_PAD_FEC_RXD1__MLB_MLBSIG				802
-MX53_PAD_FEC_RXD1__RTC_CE_RTC_PS1			803
-MX53_PAD_FEC_RXD0__FEC_RDATA_0				804
-MX53_PAD_FEC_RXD0__GPIO1_27				805
-MX53_PAD_FEC_RXD0__ESAI1_HCKT				806
-MX53_PAD_FEC_RXD0__OSC32k_32K_OUT			807
-MX53_PAD_FEC_TX_EN__FEC_TX_EN				808
-MX53_PAD_FEC_TX_EN__GPIO1_28				809
-MX53_PAD_FEC_TX_EN__ESAI1_TX3_RX2			810
-MX53_PAD_FEC_TXD1__FEC_TDATA_1				811
-MX53_PAD_FEC_TXD1__GPIO1_29				812
-MX53_PAD_FEC_TXD1__ESAI1_TX2_RX3			813
-MX53_PAD_FEC_TXD1__MLB_MLBCLK				814
-MX53_PAD_FEC_TXD1__RTC_CE_RTC_PRSC_CLK			815
-MX53_PAD_FEC_TXD0__FEC_TDATA_0				816
-MX53_PAD_FEC_TXD0__GPIO1_30				817
-MX53_PAD_FEC_TXD0__ESAI1_TX4_RX1			818
-MX53_PAD_FEC_TXD0__USBPHY2_DATAOUT_0			819
-MX53_PAD_FEC_MDC__FEC_MDC				820
-MX53_PAD_FEC_MDC__GPIO1_31				821
-MX53_PAD_FEC_MDC__ESAI1_TX5_RX0				822
-MX53_PAD_FEC_MDC__MLB_MLBDAT				823
-MX53_PAD_FEC_MDC__RTC_CE_RTC_ALARM1_TRIG		824
-MX53_PAD_FEC_MDC__USBPHY2_DATAOUT_1			825
-MX53_PAD_PATA_DIOW__PATA_DIOW				826
-MX53_PAD_PATA_DIOW__GPIO6_17				827
-MX53_PAD_PATA_DIOW__UART1_TXD_MUX			828
-MX53_PAD_PATA_DIOW__USBPHY2_DATAOUT_2			829
-MX53_PAD_PATA_DMACK__PATA_DMACK				830
-MX53_PAD_PATA_DMACK__GPIO6_18				831
-MX53_PAD_PATA_DMACK__UART1_RXD_MUX			832
-MX53_PAD_PATA_DMACK__USBPHY2_DATAOUT_3			833
-MX53_PAD_PATA_DMARQ__PATA_DMARQ				834
-MX53_PAD_PATA_DMARQ__GPIO7_0				835
-MX53_PAD_PATA_DMARQ__UART2_TXD_MUX			836
-MX53_PAD_PATA_DMARQ__CCM_CCM_OUT_0			837
-MX53_PAD_PATA_DMARQ__USBPHY2_DATAOUT_4			838
-MX53_PAD_PATA_BUFFER_EN__PATA_BUFFER_EN			839
-MX53_PAD_PATA_BUFFER_EN__GPIO7_1			840
-MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX			841
-MX53_PAD_PATA_BUFFER_EN__CCM_CCM_OUT_1			842
-MX53_PAD_PATA_BUFFER_EN__USBPHY2_DATAOUT_5		843
-MX53_PAD_PATA_INTRQ__PATA_INTRQ				844
-MX53_PAD_PATA_INTRQ__GPIO7_2				845
-MX53_PAD_PATA_INTRQ__UART2_CTS				846
-MX53_PAD_PATA_INTRQ__CAN1_TXCAN				847
-MX53_PAD_PATA_INTRQ__CCM_CCM_OUT_2			848
-MX53_PAD_PATA_INTRQ__USBPHY2_DATAOUT_6			849
-MX53_PAD_PATA_DIOR__PATA_DIOR				850
-MX53_PAD_PATA_DIOR__GPIO7_3				851
-MX53_PAD_PATA_DIOR__UART2_RTS				852
-MX53_PAD_PATA_DIOR__CAN1_RXCAN				853
-MX53_PAD_PATA_DIOR__USBPHY2_DATAOUT_7			854
-MX53_PAD_PATA_RESET_B__PATA_PATA_RESET_B		855
-MX53_PAD_PATA_RESET_B__GPIO7_4				856
-MX53_PAD_PATA_RESET_B__ESDHC3_CMD			857
-MX53_PAD_PATA_RESET_B__UART1_CTS			858
-MX53_PAD_PATA_RESET_B__CAN2_TXCAN			859
-MX53_PAD_PATA_RESET_B__USBPHY1_DATAOUT_0		860
-MX53_PAD_PATA_IORDY__PATA_IORDY				861
-MX53_PAD_PATA_IORDY__GPIO7_5				862
-MX53_PAD_PATA_IORDY__ESDHC3_CLK				863
-MX53_PAD_PATA_IORDY__UART1_RTS				864
-MX53_PAD_PATA_IORDY__CAN2_RXCAN				865
-MX53_PAD_PATA_IORDY__USBPHY1_DATAOUT_1			866
-MX53_PAD_PATA_DA_0__PATA_DA_0				867
-MX53_PAD_PATA_DA_0__GPIO7_6				868
-MX53_PAD_PATA_DA_0__ESDHC3_RST				869
-MX53_PAD_PATA_DA_0__OWIRE_LINE				870
-MX53_PAD_PATA_DA_0__USBPHY1_DATAOUT_2			871
-MX53_PAD_PATA_DA_1__PATA_DA_1				872
-MX53_PAD_PATA_DA_1__GPIO7_7				873
-MX53_PAD_PATA_DA_1__ESDHC4_CMD				874
-MX53_PAD_PATA_DA_1__UART3_CTS				875
-MX53_PAD_PATA_DA_1__USBPHY1_DATAOUT_3			876
-MX53_PAD_PATA_DA_2__PATA_DA_2				877
-MX53_PAD_PATA_DA_2__GPIO7_8				878
-MX53_PAD_PATA_DA_2__ESDHC4_CLK				879
-MX53_PAD_PATA_DA_2__UART3_RTS				880
-MX53_PAD_PATA_DA_2__USBPHY1_DATAOUT_4			881
-MX53_PAD_PATA_CS_0__PATA_CS_0				882
-MX53_PAD_PATA_CS_0__GPIO7_9				883
-MX53_PAD_PATA_CS_0__UART3_TXD_MUX			884
-MX53_PAD_PATA_CS_0__USBPHY1_DATAOUT_5			885
-MX53_PAD_PATA_CS_1__PATA_CS_1				886
-MX53_PAD_PATA_CS_1__GPIO7_10				887
-MX53_PAD_PATA_CS_1__UART3_RXD_MUX			888
-MX53_PAD_PATA_CS_1__USBPHY1_DATAOUT_6			889
-MX53_PAD_PATA_DATA0__PATA_DATA_0			890
-MX53_PAD_PATA_DATA0__GPIO2_0				891
-MX53_PAD_PATA_DATA0__EMI_NANDF_D_0			892
-MX53_PAD_PATA_DATA0__ESDHC3_DAT4			893
-MX53_PAD_PATA_DATA0__GPU3d_GPU_DEBUG_OUT_0		894
-MX53_PAD_PATA_DATA0__IPU_DIAG_BUS_0			895
-MX53_PAD_PATA_DATA0__USBPHY1_DATAOUT_7			896
-MX53_PAD_PATA_DATA1__PATA_DATA_1			897
-MX53_PAD_PATA_DATA1__GPIO2_1				898
-MX53_PAD_PATA_DATA1__EMI_NANDF_D_1			899
-MX53_PAD_PATA_DATA1__ESDHC3_DAT5			900
-MX53_PAD_PATA_DATA1__GPU3d_GPU_DEBUG_OUT_1		901
-MX53_PAD_PATA_DATA1__IPU_DIAG_BUS_1			902
-MX53_PAD_PATA_DATA2__PATA_DATA_2			903
-MX53_PAD_PATA_DATA2__GPIO2_2				904
-MX53_PAD_PATA_DATA2__EMI_NANDF_D_2			905
-MX53_PAD_PATA_DATA2__ESDHC3_DAT6			906
-MX53_PAD_PATA_DATA2__GPU3d_GPU_DEBUG_OUT_2		907
-MX53_PAD_PATA_DATA2__IPU_DIAG_BUS_2			908
-MX53_PAD_PATA_DATA3__PATA_DATA_3			909
-MX53_PAD_PATA_DATA3__GPIO2_3				910
-MX53_PAD_PATA_DATA3__EMI_NANDF_D_3			911
-MX53_PAD_PATA_DATA3__ESDHC3_DAT7			912
-MX53_PAD_PATA_DATA3__GPU3d_GPU_DEBUG_OUT_3		913
-MX53_PAD_PATA_DATA3__IPU_DIAG_BUS_3			914
-MX53_PAD_PATA_DATA4__PATA_DATA_4			915
-MX53_PAD_PATA_DATA4__GPIO2_4				916
-MX53_PAD_PATA_DATA4__EMI_NANDF_D_4			917
-MX53_PAD_PATA_DATA4__ESDHC4_DAT4			918
-MX53_PAD_PATA_DATA4__GPU3d_GPU_DEBUG_OUT_4		919
-MX53_PAD_PATA_DATA4__IPU_DIAG_BUS_4			920
-MX53_PAD_PATA_DATA5__PATA_DATA_5			921
-MX53_PAD_PATA_DATA5__GPIO2_5				922
-MX53_PAD_PATA_DATA5__EMI_NANDF_D_5			923
-MX53_PAD_PATA_DATA5__ESDHC4_DAT5			924
-MX53_PAD_PATA_DATA5__GPU3d_GPU_DEBUG_OUT_5		925
-MX53_PAD_PATA_DATA5__IPU_DIAG_BUS_5			926
-MX53_PAD_PATA_DATA6__PATA_DATA_6			927
-MX53_PAD_PATA_DATA6__GPIO2_6				928
-MX53_PAD_PATA_DATA6__EMI_NANDF_D_6			929
-MX53_PAD_PATA_DATA6__ESDHC4_DAT6			930
-MX53_PAD_PATA_DATA6__GPU3d_GPU_DEBUG_OUT_6		931
-MX53_PAD_PATA_DATA6__IPU_DIAG_BUS_6			932
-MX53_PAD_PATA_DATA7__PATA_DATA_7			933
-MX53_PAD_PATA_DATA7__GPIO2_7				934
-MX53_PAD_PATA_DATA7__EMI_NANDF_D_7			935
-MX53_PAD_PATA_DATA7__ESDHC4_DAT7			936
-MX53_PAD_PATA_DATA7__GPU3d_GPU_DEBUG_OUT_7		937
-MX53_PAD_PATA_DATA7__IPU_DIAG_BUS_7			938
-MX53_PAD_PATA_DATA8__PATA_DATA_8			939
-MX53_PAD_PATA_DATA8__GPIO2_8				940
-MX53_PAD_PATA_DATA8__ESDHC1_DAT4			941
-MX53_PAD_PATA_DATA8__EMI_NANDF_D_8			942
-MX53_PAD_PATA_DATA8__ESDHC3_DAT0			943
-MX53_PAD_PATA_DATA8__GPU3d_GPU_DEBUG_OUT_8		944
-MX53_PAD_PATA_DATA8__IPU_DIAG_BUS_8			945
-MX53_PAD_PATA_DATA9__PATA_DATA_9			946
-MX53_PAD_PATA_DATA9__GPIO2_9				947
-MX53_PAD_PATA_DATA9__ESDHC1_DAT5			948
-MX53_PAD_PATA_DATA9__EMI_NANDF_D_9			949
-MX53_PAD_PATA_DATA9__ESDHC3_DAT1			950
-MX53_PAD_PATA_DATA9__GPU3d_GPU_DEBUG_OUT_9		951
-MX53_PAD_PATA_DATA9__IPU_DIAG_BUS_9			952
-MX53_PAD_PATA_DATA10__PATA_DATA_10			953
-MX53_PAD_PATA_DATA10__GPIO2_10				954
-MX53_PAD_PATA_DATA10__ESDHC1_DAT6			955
-MX53_PAD_PATA_DATA10__EMI_NANDF_D_10			956
-MX53_PAD_PATA_DATA10__ESDHC3_DAT2			957
-MX53_PAD_PATA_DATA10__GPU3d_GPU_DEBUG_OUT_10		958
-MX53_PAD_PATA_DATA10__IPU_DIAG_BUS_10			959
-MX53_PAD_PATA_DATA11__PATA_DATA_11			960
-MX53_PAD_PATA_DATA11__GPIO2_11				961
-MX53_PAD_PATA_DATA11__ESDHC1_DAT7			962
-MX53_PAD_PATA_DATA11__EMI_NANDF_D_11			963
-MX53_PAD_PATA_DATA11__ESDHC3_DAT3			964
-MX53_PAD_PATA_DATA11__GPU3d_GPU_DEBUG_OUT_11		965
-MX53_PAD_PATA_DATA11__IPU_DIAG_BUS_11			966
-MX53_PAD_PATA_DATA12__PATA_DATA_12			967
-MX53_PAD_PATA_DATA12__GPIO2_12				968
-MX53_PAD_PATA_DATA12__ESDHC2_DAT4			969
-MX53_PAD_PATA_DATA12__EMI_NANDF_D_12			970
-MX53_PAD_PATA_DATA12__ESDHC4_DAT0			971
-MX53_PAD_PATA_DATA12__GPU3d_GPU_DEBUG_OUT_12		972
-MX53_PAD_PATA_DATA12__IPU_DIAG_BUS_12			973
-MX53_PAD_PATA_DATA13__PATA_DATA_13			974
-MX53_PAD_PATA_DATA13__GPIO2_13				975
-MX53_PAD_PATA_DATA13__ESDHC2_DAT5			976
-MX53_PAD_PATA_DATA13__EMI_NANDF_D_13			977
-MX53_PAD_PATA_DATA13__ESDHC4_DAT1			978
-MX53_PAD_PATA_DATA13__GPU3d_GPU_DEBUG_OUT_13		979
-MX53_PAD_PATA_DATA13__IPU_DIAG_BUS_13			980
-MX53_PAD_PATA_DATA14__PATA_DATA_14			981
-MX53_PAD_PATA_DATA14__GPIO2_14				982
-MX53_PAD_PATA_DATA14__ESDHC2_DAT6			983
-MX53_PAD_PATA_DATA14__EMI_NANDF_D_14			984
-MX53_PAD_PATA_DATA14__ESDHC4_DAT2			985
-MX53_PAD_PATA_DATA14__GPU3d_GPU_DEBUG_OUT_14		986
-MX53_PAD_PATA_DATA14__IPU_DIAG_BUS_14			987
-MX53_PAD_PATA_DATA15__PATA_DATA_15			988
-MX53_PAD_PATA_DATA15__GPIO2_15				989
-MX53_PAD_PATA_DATA15__ESDHC2_DAT7			990
-MX53_PAD_PATA_DATA15__EMI_NANDF_D_15			991
-MX53_PAD_PATA_DATA15__ESDHC4_DAT3			992
-MX53_PAD_PATA_DATA15__GPU3d_GPU_DEBUG_OUT_15		993
-MX53_PAD_PATA_DATA15__IPU_DIAG_BUS_15			994
-MX53_PAD_SD1_DATA0__ESDHC1_DAT0				995
-MX53_PAD_SD1_DATA0__GPIO1_16				996
-MX53_PAD_SD1_DATA0__GPT_CAPIN1				997
-MX53_PAD_SD1_DATA0__CSPI_MISO				998
-MX53_PAD_SD1_DATA0__CCM_PLL3_BYP			999
-MX53_PAD_SD1_DATA1__ESDHC1_DAT1				1000
-MX53_PAD_SD1_DATA1__GPIO1_17				1001
-MX53_PAD_SD1_DATA1__GPT_CAPIN2				1002
-MX53_PAD_SD1_DATA1__CSPI_SS0				1003
-MX53_PAD_SD1_DATA1__CCM_PLL4_BYP			1004
-MX53_PAD_SD1_CMD__ESDHC1_CMD				1005
-MX53_PAD_SD1_CMD__GPIO1_18				1006
-MX53_PAD_SD1_CMD__GPT_CMPOUT1				1007
-MX53_PAD_SD1_CMD__CSPI_MOSI				1008
-MX53_PAD_SD1_CMD__CCM_PLL1_BYP				1009
-MX53_PAD_SD1_DATA2__ESDHC1_DAT2				1010
-MX53_PAD_SD1_DATA2__GPIO1_19				1011
-MX53_PAD_SD1_DATA2__GPT_CMPOUT2				1012
-MX53_PAD_SD1_DATA2__PWM2_PWMO				1013
-MX53_PAD_SD1_DATA2__WDOG1_WDOG_B			1014
-MX53_PAD_SD1_DATA2__CSPI_SS1				1015
-MX53_PAD_SD1_DATA2__WDOG1_WDOG_RST_B_DEB		1016
-MX53_PAD_SD1_DATA2__CCM_PLL2_BYP			1017
-MX53_PAD_SD1_CLK__ESDHC1_CLK				1018
-MX53_PAD_SD1_CLK__GPIO1_20				1019
-MX53_PAD_SD1_CLK__OSC32k_32K_OUT			1020
-MX53_PAD_SD1_CLK__GPT_CLKIN				1021
-MX53_PAD_SD1_CLK__CSPI_SCLK				1022
-MX53_PAD_SD1_CLK__SATA_PHY_DTB_0			1023
-MX53_PAD_SD1_DATA3__ESDHC1_DAT3				1024
-MX53_PAD_SD1_DATA3__GPIO1_21				1025
-MX53_PAD_SD1_DATA3__GPT_CMPOUT3				1026
-MX53_PAD_SD1_DATA3__PWM1_PWMO				1027
-MX53_PAD_SD1_DATA3__WDOG2_WDOG_B			1028
-MX53_PAD_SD1_DATA3__CSPI_SS2				1029
-MX53_PAD_SD1_DATA3__WDOG2_WDOG_RST_B_DEB		1030
-MX53_PAD_SD1_DATA3__SATA_PHY_DTB_1			1031
-MX53_PAD_SD2_CLK__ESDHC2_CLK				1032
-MX53_PAD_SD2_CLK__GPIO1_10				1033
-MX53_PAD_SD2_CLK__KPP_COL_5				1034
-MX53_PAD_SD2_CLK__AUDMUX_AUD4_RXFS			1035
-MX53_PAD_SD2_CLK__CSPI_SCLK				1036
-MX53_PAD_SD2_CLK__SCC_RANDOM_V				1037
-MX53_PAD_SD2_CMD__ESDHC2_CMD				1038
-MX53_PAD_SD2_CMD__GPIO1_11				1039
-MX53_PAD_SD2_CMD__KPP_ROW_5				1040
-MX53_PAD_SD2_CMD__AUDMUX_AUD4_RXC			1041
-MX53_PAD_SD2_CMD__CSPI_MOSI				1042
-MX53_PAD_SD2_CMD__SCC_RANDOM				1043
-MX53_PAD_SD2_DATA3__ESDHC2_DAT3				1044
-MX53_PAD_SD2_DATA3__GPIO1_12				1045
-MX53_PAD_SD2_DATA3__KPP_COL_6				1046
-MX53_PAD_SD2_DATA3__AUDMUX_AUD4_TXC			1047
-MX53_PAD_SD2_DATA3__CSPI_SS2				1048
-MX53_PAD_SD2_DATA3__SJC_DONE				1049
-MX53_PAD_SD2_DATA2__ESDHC2_DAT2				1050
-MX53_PAD_SD2_DATA2__GPIO1_13				1051
-MX53_PAD_SD2_DATA2__KPP_ROW_6				1052
-MX53_PAD_SD2_DATA2__AUDMUX_AUD4_TXD			1053
-MX53_PAD_SD2_DATA2__CSPI_SS1				1054
-MX53_PAD_SD2_DATA2__SJC_FAIL				1055
-MX53_PAD_SD2_DATA1__ESDHC2_DAT1				1056
-MX53_PAD_SD2_DATA1__GPIO1_14				1057
-MX53_PAD_SD2_DATA1__KPP_COL_7				1058
-MX53_PAD_SD2_DATA1__AUDMUX_AUD4_TXFS			1059
-MX53_PAD_SD2_DATA1__CSPI_SS0				1060
-MX53_PAD_SD2_DATA1__RTIC_SEC_VIO			1061
-MX53_PAD_SD2_DATA0__ESDHC2_DAT0				1062
-MX53_PAD_SD2_DATA0__GPIO1_15				1063
-MX53_PAD_SD2_DATA0__KPP_ROW_7				1064
-MX53_PAD_SD2_DATA0__AUDMUX_AUD4_RXD			1065
-MX53_PAD_SD2_DATA0__CSPI_MISO				1066
-MX53_PAD_SD2_DATA0__RTIC_DONE_INT			1067
-MX53_PAD_GPIO_0__CCM_CLKO				1068
-MX53_PAD_GPIO_0__GPIO1_0				1069
-MX53_PAD_GPIO_0__KPP_COL_5				1070
-MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK			1071
-MX53_PAD_GPIO_0__EPIT1_EPITO				1072
-MX53_PAD_GPIO_0__SRTC_ALARM_DEB				1073
-MX53_PAD_GPIO_0__USBOH3_USBH1_PWR			1074
-MX53_PAD_GPIO_0__CSU_TD					1075
-MX53_PAD_GPIO_1__ESAI1_SCKR				1076
-MX53_PAD_GPIO_1__GPIO1_1				1077
-MX53_PAD_GPIO_1__KPP_ROW_5				1078
-MX53_PAD_GPIO_1__CCM_SSI_EXT2_CLK			1079
-MX53_PAD_GPIO_1__PWM2_PWMO				1080
-MX53_PAD_GPIO_1__WDOG2_WDOG_B				1081
-MX53_PAD_GPIO_1__ESDHC1_CD				1082
-MX53_PAD_GPIO_1__SRC_TESTER_ACK				1083
-MX53_PAD_GPIO_9__ESAI1_FSR				1084
-MX53_PAD_GPIO_9__GPIO1_9				1085
-MX53_PAD_GPIO_9__KPP_COL_6				1086
-MX53_PAD_GPIO_9__CCM_REF_EN_B				1087
-MX53_PAD_GPIO_9__PWM1_PWMO				1088
-MX53_PAD_GPIO_9__WDOG1_WDOG_B				1089
-MX53_PAD_GPIO_9__ESDHC1_WP				1090
-MX53_PAD_GPIO_9__SCC_FAIL_STATE				1091
-MX53_PAD_GPIO_3__ESAI1_HCKR				1092
-MX53_PAD_GPIO_3__GPIO1_3				1093
-MX53_PAD_GPIO_3__I2C3_SCL				1094
-MX53_PAD_GPIO_3__DPLLIP1_TOG_EN				1095
-MX53_PAD_GPIO_3__CCM_CLKO2				1096
-MX53_PAD_GPIO_3__OBSERVE_MUX_OBSRV_INT_OUT0		1097
-MX53_PAD_GPIO_3__USBOH3_USBH1_OC			1098
-MX53_PAD_GPIO_3__MLB_MLBCLK				1099
-MX53_PAD_GPIO_6__ESAI1_SCKT				1100
-MX53_PAD_GPIO_6__GPIO1_6				1101
-MX53_PAD_GPIO_6__I2C3_SDA				1102
-MX53_PAD_GPIO_6__CCM_CCM_OUT_0				1103
-MX53_PAD_GPIO_6__CSU_CSU_INT_DEB			1104
-MX53_PAD_GPIO_6__OBSERVE_MUX_OBSRV_INT_OUT1		1105
-MX53_PAD_GPIO_6__ESDHC2_LCTL				1106
-MX53_PAD_GPIO_6__MLB_MLBSIG				1107
-MX53_PAD_GPIO_2__ESAI1_FST				1108
-MX53_PAD_GPIO_2__GPIO1_2				1109
-MX53_PAD_GPIO_2__KPP_ROW_6				1110
-MX53_PAD_GPIO_2__CCM_CCM_OUT_1				1111
-MX53_PAD_GPIO_2__CSU_CSU_ALARM_AUT_0			1112
-MX53_PAD_GPIO_2__OBSERVE_MUX_OBSRV_INT_OUT2		1113
-MX53_PAD_GPIO_2__ESDHC2_WP				1114
-MX53_PAD_GPIO_2__MLB_MLBDAT				1115
-MX53_PAD_GPIO_4__ESAI1_HCKT				1116
-MX53_PAD_GPIO_4__GPIO1_4				1117
-MX53_PAD_GPIO_4__KPP_COL_7				1118
-MX53_PAD_GPIO_4__CCM_CCM_OUT_2				1119
-MX53_PAD_GPIO_4__CSU_CSU_ALARM_AUT_1			1120
-MX53_PAD_GPIO_4__OBSERVE_MUX_OBSRV_INT_OUT3		1121
-MX53_PAD_GPIO_4__ESDHC2_CD				1122
-MX53_PAD_GPIO_4__SCC_SEC_STATE				1123
-MX53_PAD_GPIO_5__ESAI1_TX2_RX3				1124
-MX53_PAD_GPIO_5__GPIO1_5				1125
-MX53_PAD_GPIO_5__KPP_ROW_7				1126
-MX53_PAD_GPIO_5__CCM_CLKO				1127
-MX53_PAD_GPIO_5__CSU_CSU_ALARM_AUT_2			1128
-MX53_PAD_GPIO_5__OBSERVE_MUX_OBSRV_INT_OUT4		1129
-MX53_PAD_GPIO_5__I2C3_SCL				1130
-MX53_PAD_GPIO_5__CCM_PLL1_BYP				1131
-MX53_PAD_GPIO_7__ESAI1_TX4_RX1				1132
-MX53_PAD_GPIO_7__GPIO1_7				1133
-MX53_PAD_GPIO_7__EPIT1_EPITO				1134
-MX53_PAD_GPIO_7__CAN1_TXCAN				1135
-MX53_PAD_GPIO_7__UART2_TXD_MUX				1136
-MX53_PAD_GPIO_7__FIRI_RXD				1137
-MX53_PAD_GPIO_7__SPDIF_PLOCK				1138
-MX53_PAD_GPIO_7__CCM_PLL2_BYP				1139
-MX53_PAD_GPIO_8__ESAI1_TX5_RX0				1140
-MX53_PAD_GPIO_8__GPIO1_8				1141
-MX53_PAD_GPIO_8__EPIT2_EPITO				1142
-MX53_PAD_GPIO_8__CAN1_RXCAN				1143
-MX53_PAD_GPIO_8__UART2_RXD_MUX				1144
-MX53_PAD_GPIO_8__FIRI_TXD				1145
-MX53_PAD_GPIO_8__SPDIF_SRCLK				1146
-MX53_PAD_GPIO_8__CCM_PLL3_BYP				1147
-MX53_PAD_GPIO_16__ESAI1_TX3_RX2				1148
-MX53_PAD_GPIO_16__GPIO7_11				1149
-MX53_PAD_GPIO_16__TZIC_PWRFAIL_INT			1150
-MX53_PAD_GPIO_16__RTC_CE_RTC_EXT_TRIG1			1151
-MX53_PAD_GPIO_16__SPDIF_IN1				1152
-MX53_PAD_GPIO_16__I2C3_SDA				1153
-MX53_PAD_GPIO_16__SJC_DE_B				1154
-MX53_PAD_GPIO_17__ESAI1_TX0				1155
-MX53_PAD_GPIO_17__GPIO7_12				1156
-MX53_PAD_GPIO_17__SDMA_EXT_EVENT_0			1157
-MX53_PAD_GPIO_17__GPC_PMIC_RDY				1158
-MX53_PAD_GPIO_17__RTC_CE_RTC_FSV_TRIG			1159
-MX53_PAD_GPIO_17__SPDIF_OUT1				1160
-MX53_PAD_GPIO_17__IPU_SNOOP2				1161
-MX53_PAD_GPIO_17__SJC_JTAG_ACT				1162
-MX53_PAD_GPIO_18__ESAI1_TX1				1163
-MX53_PAD_GPIO_18__GPIO7_13				1164
-MX53_PAD_GPIO_18__SDMA_EXT_EVENT_1			1165
-MX53_PAD_GPIO_18__OWIRE_LINE				1166
-MX53_PAD_GPIO_18__RTC_CE_RTC_ALARM2_TRIG		1167
-MX53_PAD_GPIO_18__CCM_ASRC_EXT_CLK			1168
-MX53_PAD_GPIO_18__ESDHC1_LCTL				1169
-MX53_PAD_GPIO_18__SRC_SYSTEM_RST			1170
+Refer to imx53-pinfunc.h in device tree source folder for all available
+imx53 PIN_FUNC_ID.
diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,imx6dl-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/fsl,imx6dl-pinctrl.txt
new file mode 100644
index 0000000..0ac5bee
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/fsl,imx6dl-pinctrl.txt
@@ -0,0 +1,38 @@
+* Freescale IMX6 DualLite/Solo IOMUX Controller
+
+Please refer to fsl,imx-pinctrl.txt in this directory for common binding part
+and usage.
+
+Required properties:
+- compatible: "fsl,imx6dl-iomuxc"
+- fsl,pins: two integers array, represents a group of pins mux and config
+  setting. The format is fsl,pins = <PIN_FUNC_ID CONFIG>, PIN_FUNC_ID is a
+  pin working on a specific function, CONFIG is the pad setting value like
+  pull-up for this pin. Please refer to imx6dl datasheet for the valid pad
+  config settings.
+
+CONFIG bits definition:
+PAD_CTL_HYS                     (1 << 16)
+PAD_CTL_PUS_100K_DOWN           (0 << 14)
+PAD_CTL_PUS_47K_UP              (1 << 14)
+PAD_CTL_PUS_100K_UP             (2 << 14)
+PAD_CTL_PUS_22K_UP              (3 << 14)
+PAD_CTL_PUE                     (1 << 13)
+PAD_CTL_PKE                     (1 << 12)
+PAD_CTL_ODE                     (1 << 11)
+PAD_CTL_SPEED_LOW               (1 << 6)
+PAD_CTL_SPEED_MED               (2 << 6)
+PAD_CTL_SPEED_HIGH              (3 << 6)
+PAD_CTL_DSE_DISABLE             (0 << 3)
+PAD_CTL_DSE_240ohm              (1 << 3)
+PAD_CTL_DSE_120ohm              (2 << 3)
+PAD_CTL_DSE_80ohm               (3 << 3)
+PAD_CTL_DSE_60ohm               (4 << 3)
+PAD_CTL_DSE_48ohm               (5 << 3)
+PAD_CTL_DSE_40ohm               (6 << 3)
+PAD_CTL_DSE_34ohm               (7 << 3)
+PAD_CTL_SRE_FAST                (1 << 0)
+PAD_CTL_SRE_SLOW                (0 << 0)
+
+Refer to imx6dl-pinfunc.h in device tree source folder for all available
+imx6dl PIN_FUNC_ID.
diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,imx6q-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/fsl,imx6q-pinctrl.txt
index a4119f6..546610c 100644
--- a/Documentation/devicetree/bindings/pinctrl/fsl,imx6q-pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/fsl,imx6q-pinctrl.txt
@@ -34,1597 +34,5 @@ PAD_CTL_DSE_34ohm               (7 << 3)
 PAD_CTL_SRE_FAST                (1 << 0)
 PAD_CTL_SRE_SLOW                (0 << 0)
 
-See below for available PIN_FUNC_ID for imx6q:
-MX6Q_PAD_SD2_DAT1__USDHC2_DAT1			0
-MX6Q_PAD_SD2_DAT1__ECSPI5_SS0			1
-MX6Q_PAD_SD2_DAT1__WEIM_WEIM_CS_2		2
-MX6Q_PAD_SD2_DAT1__AUDMUX_AUD4_TXFS		3
-MX6Q_PAD_SD2_DAT1__KPP_COL_7			4
-MX6Q_PAD_SD2_DAT1__GPIO_1_14			5
-MX6Q_PAD_SD2_DAT1__CCM_WAIT			6
-MX6Q_PAD_SD2_DAT1__ANATOP_TESTO_0		7
-MX6Q_PAD_SD2_DAT2__USDHC2_DAT2			8
-MX6Q_PAD_SD2_DAT2__ECSPI5_SS1			9
-MX6Q_PAD_SD2_DAT2__WEIM_WEIM_CS_3		10
-MX6Q_PAD_SD2_DAT2__AUDMUX_AUD4_TXD		11
-MX6Q_PAD_SD2_DAT2__KPP_ROW_6			12
-MX6Q_PAD_SD2_DAT2__GPIO_1_13			13
-MX6Q_PAD_SD2_DAT2__CCM_STOP			14
-MX6Q_PAD_SD2_DAT2__ANATOP_TESTO_1		15
-MX6Q_PAD_SD2_DAT0__USDHC2_DAT0			16
-MX6Q_PAD_SD2_DAT0__ECSPI5_MISO			17
-MX6Q_PAD_SD2_DAT0__AUDMUX_AUD4_RXD		18
-MX6Q_PAD_SD2_DAT0__KPP_ROW_7			19
-MX6Q_PAD_SD2_DAT0__GPIO_1_15			20
-MX6Q_PAD_SD2_DAT0__DCIC2_DCIC_OUT		21
-MX6Q_PAD_SD2_DAT0__TESTO_2			22
-MX6Q_PAD_RGMII_TXC__USBOH3_H2_DATA		23
-MX6Q_PAD_RGMII_TXC__ENET_RGMII_TXC		24
-MX6Q_PAD_RGMII_TXC__SPDIF_SPDIF_EXTCLK		25
-MX6Q_PAD_RGMII_TXC__GPIO_6_19			26
-MX6Q_PAD_RGMII_TXC__MIPI_CORE_DPHY_IN_0		27
-MX6Q_PAD_RGMII_TXC__ANATOP_24M_OUT		28
-MX6Q_PAD_RGMII_TD0__MIPI_HSI_CRL_TX_RDY		29
-MX6Q_PAD_RGMII_TD0__ENET_RGMII_TD0		30
-MX6Q_PAD_RGMII_TD0__GPIO_6_20			31
-MX6Q_PAD_RGMII_TD0__MIPI_CORE_DPHY_IN_1		32
-MX6Q_PAD_RGMII_TD1__MIPI_HSI_CRL_RX_FLG		33
-MX6Q_PAD_RGMII_TD1__ENET_RGMII_TD1		34
-MX6Q_PAD_RGMII_TD1__GPIO_6_21			35
-MX6Q_PAD_RGMII_TD1__MIPI_CORE_DPHY_IN_2		36
-MX6Q_PAD_RGMII_TD1__CCM_PLL3_BYP		37
-MX6Q_PAD_RGMII_TD2__MIPI_HSI_CRL_RX_DTA		38
-MX6Q_PAD_RGMII_TD2__ENET_RGMII_TD2		39
-MX6Q_PAD_RGMII_TD2__GPIO_6_22			40
-MX6Q_PAD_RGMII_TD2__MIPI_CORE_DPHY_IN_3		41
-MX6Q_PAD_RGMII_TD2__CCM_PLL2_BYP		42
-MX6Q_PAD_RGMII_TD3__MIPI_HSI_CRL_RX_WAK		43
-MX6Q_PAD_RGMII_TD3__ENET_RGMII_TD3		44
-MX6Q_PAD_RGMII_TD3__GPIO_6_23			45
-MX6Q_PAD_RGMII_TD3__MIPI_CORE_DPHY_IN_4		46
-MX6Q_PAD_RGMII_RX_CTL__USBOH3_H3_DATA		47
-MX6Q_PAD_RGMII_RX_CTL__RGMII_RX_CTL		48
-MX6Q_PAD_RGMII_RX_CTL__GPIO_6_24		49
-MX6Q_PAD_RGMII_RX_CTL__MIPI_DPHY_IN_5		50
-MX6Q_PAD_RGMII_RD0__MIPI_HSI_CRL_RX_RDY		51
-MX6Q_PAD_RGMII_RD0__ENET_RGMII_RD0		52
-MX6Q_PAD_RGMII_RD0__GPIO_6_25			53
-MX6Q_PAD_RGMII_RD0__MIPI_CORE_DPHY_IN_6		54
-MX6Q_PAD_RGMII_TX_CTL__USBOH3_H2_STROBE		55
-MX6Q_PAD_RGMII_TX_CTL__RGMII_TX_CTL		56
-MX6Q_PAD_RGMII_TX_CTL__GPIO_6_26		57
-MX6Q_PAD_RGMII_TX_CTL__CORE_DPHY_IN_7		58
-MX6Q_PAD_RGMII_TX_CTL__ANATOP_REF_OUT		59
-MX6Q_PAD_RGMII_RD1__MIPI_HSI_CTRL_TX_FL		60
-MX6Q_PAD_RGMII_RD1__ENET_RGMII_RD1		61
-MX6Q_PAD_RGMII_RD1__GPIO_6_27			62
-MX6Q_PAD_RGMII_RD1__CORE_DPHY_TEST_IN_8		63
-MX6Q_PAD_RGMII_RD1__SJC_FAIL			64
-MX6Q_PAD_RGMII_RD2__MIPI_HSI_CRL_TX_DTA		65
-MX6Q_PAD_RGMII_RD2__ENET_RGMII_RD2		66
-MX6Q_PAD_RGMII_RD2__GPIO_6_28			67
-MX6Q_PAD_RGMII_RD2__MIPI_CORE_DPHY_IN_9		68
-MX6Q_PAD_RGMII_RD3__MIPI_HSI_CRL_TX_WAK		69
-MX6Q_PAD_RGMII_RD3__ENET_RGMII_RD3		70
-MX6Q_PAD_RGMII_RD3__GPIO_6_29			71
-MX6Q_PAD_RGMII_RD3__MIPI_CORE_DPHY_IN10		72
-MX6Q_PAD_RGMII_RXC__USBOH3_H3_STROBE		73
-MX6Q_PAD_RGMII_RXC__ENET_RGMII_RXC		74
-MX6Q_PAD_RGMII_RXC__GPIO_6_30			75
-MX6Q_PAD_RGMII_RXC__MIPI_CORE_DPHY_IN11		76
-MX6Q_PAD_EIM_A25__WEIM_WEIM_A_25		77
-MX6Q_PAD_EIM_A25__ECSPI4_SS1			78
-MX6Q_PAD_EIM_A25__ECSPI2_RDY			79
-MX6Q_PAD_EIM_A25__IPU1_DI1_PIN12		80
-MX6Q_PAD_EIM_A25__IPU1_DI0_D1_CS		81
-MX6Q_PAD_EIM_A25__GPIO_5_2			82
-MX6Q_PAD_EIM_A25__HDMI_TX_CEC_LINE		83
-MX6Q_PAD_EIM_A25__PL301_PER1_HBURST_0		84
-MX6Q_PAD_EIM_EB2__WEIM_WEIM_EB_2		85
-MX6Q_PAD_EIM_EB2__ECSPI1_SS0			86
-MX6Q_PAD_EIM_EB2__CCM_DI1_EXT_CLK		87
-MX6Q_PAD_EIM_EB2__IPU2_CSI1_D_19		88
-MX6Q_PAD_EIM_EB2__HDMI_TX_DDC_SCL		89
-MX6Q_PAD_EIM_EB2__GPIO_2_30			90
-MX6Q_PAD_EIM_EB2__I2C2_SCL			91
-MX6Q_PAD_EIM_EB2__SRC_BT_CFG_30			92
-MX6Q_PAD_EIM_D16__WEIM_WEIM_D_16		93
-MX6Q_PAD_EIM_D16__ECSPI1_SCLK			94
-MX6Q_PAD_EIM_D16__IPU1_DI0_PIN5			95
-MX6Q_PAD_EIM_D16__IPU2_CSI1_D_18		96
-MX6Q_PAD_EIM_D16__HDMI_TX_DDC_SDA		97
-MX6Q_PAD_EIM_D16__GPIO_3_16			98
-MX6Q_PAD_EIM_D16__I2C2_SDA			99
-MX6Q_PAD_EIM_D17__WEIM_WEIM_D_17		100
-MX6Q_PAD_EIM_D17__ECSPI1_MISO			101
-MX6Q_PAD_EIM_D17__IPU1_DI0_PIN6			102
-MX6Q_PAD_EIM_D17__IPU2_CSI1_PIXCLK		103
-MX6Q_PAD_EIM_D17__DCIC1_DCIC_OUT		104
-MX6Q_PAD_EIM_D17__GPIO_3_17			105
-MX6Q_PAD_EIM_D17__I2C3_SCL			106
-MX6Q_PAD_EIM_D17__PL301_PER1_HBURST_1		107
-MX6Q_PAD_EIM_D18__WEIM_WEIM_D_18		108
-MX6Q_PAD_EIM_D18__ECSPI1_MOSI			109
-MX6Q_PAD_EIM_D18__IPU1_DI0_PIN7			110
-MX6Q_PAD_EIM_D18__IPU2_CSI1_D_17		111
-MX6Q_PAD_EIM_D18__IPU1_DI1_D0_CS		112
-MX6Q_PAD_EIM_D18__GPIO_3_18			113
-MX6Q_PAD_EIM_D18__I2C3_SDA			114
-MX6Q_PAD_EIM_D18__PL301_PER1_HBURST_2		115
-MX6Q_PAD_EIM_D19__WEIM_WEIM_D_19		116
-MX6Q_PAD_EIM_D19__ECSPI1_SS1			117
-MX6Q_PAD_EIM_D19__IPU1_DI0_PIN8			118
-MX6Q_PAD_EIM_D19__IPU2_CSI1_D_16		119
-MX6Q_PAD_EIM_D19__UART1_CTS			120
-MX6Q_PAD_EIM_D19__GPIO_3_19			121
-MX6Q_PAD_EIM_D19__EPIT1_EPITO			122
-MX6Q_PAD_EIM_D19__PL301_PER1_HRESP		123
-MX6Q_PAD_EIM_D20__WEIM_WEIM_D_20		124
-MX6Q_PAD_EIM_D20__ECSPI4_SS0			125
-MX6Q_PAD_EIM_D20__IPU1_DI0_PIN16		126
-MX6Q_PAD_EIM_D20__IPU2_CSI1_D_15		127
-MX6Q_PAD_EIM_D20__UART1_RTS			128
-MX6Q_PAD_EIM_D20__GPIO_3_20			129
-MX6Q_PAD_EIM_D20__EPIT2_EPITO			130
-MX6Q_PAD_EIM_D21__WEIM_WEIM_D_21		131
-MX6Q_PAD_EIM_D21__ECSPI4_SCLK			132
-MX6Q_PAD_EIM_D21__IPU1_DI0_PIN17		133
-MX6Q_PAD_EIM_D21__IPU2_CSI1_D_11		134
-MX6Q_PAD_EIM_D21__USBOH3_USBOTG_OC		135
-MX6Q_PAD_EIM_D21__GPIO_3_21			136
-MX6Q_PAD_EIM_D21__I2C1_SCL			137
-MX6Q_PAD_EIM_D21__SPDIF_IN1			138
-MX6Q_PAD_EIM_D22__WEIM_WEIM_D_22		139
-MX6Q_PAD_EIM_D22__ECSPI4_MISO			140
-MX6Q_PAD_EIM_D22__IPU1_DI0_PIN1			141
-MX6Q_PAD_EIM_D22__IPU2_CSI1_D_10		142
-MX6Q_PAD_EIM_D22__USBOH3_USBOTG_PWR		143
-MX6Q_PAD_EIM_D22__GPIO_3_22			144
-MX6Q_PAD_EIM_D22__SPDIF_OUT1			145
-MX6Q_PAD_EIM_D22__PL301_PER1_HWRITE		146
-MX6Q_PAD_EIM_D23__WEIM_WEIM_D_23		147
-MX6Q_PAD_EIM_D23__IPU1_DI0_D0_CS		148
-MX6Q_PAD_EIM_D23__UART3_CTS			149
-MX6Q_PAD_EIM_D23__UART1_DCD			150
-MX6Q_PAD_EIM_D23__IPU2_CSI1_DATA_EN		151
-MX6Q_PAD_EIM_D23__GPIO_3_23			152
-MX6Q_PAD_EIM_D23__IPU1_DI1_PIN2			153
-MX6Q_PAD_EIM_D23__IPU1_DI1_PIN14		154
-MX6Q_PAD_EIM_EB3__WEIM_WEIM_EB_3		155
-MX6Q_PAD_EIM_EB3__ECSPI4_RDY			156
-MX6Q_PAD_EIM_EB3__UART3_RTS			157
-MX6Q_PAD_EIM_EB3__UART1_RI			158
-MX6Q_PAD_EIM_EB3__IPU2_CSI1_HSYNC		159
-MX6Q_PAD_EIM_EB3__GPIO_2_31			160
-MX6Q_PAD_EIM_EB3__IPU1_DI1_PIN3			161
-MX6Q_PAD_EIM_EB3__SRC_BT_CFG_31			162
-MX6Q_PAD_EIM_D24__WEIM_WEIM_D_24		163
-MX6Q_PAD_EIM_D24__ECSPI4_SS2			164
-MX6Q_PAD_EIM_D24__UART3_TXD			165
-MX6Q_PAD_EIM_D24__ECSPI1_SS2			166
-MX6Q_PAD_EIM_D24__ECSPI2_SS2			167
-MX6Q_PAD_EIM_D24__GPIO_3_24			168
-MX6Q_PAD_EIM_D24__AUDMUX_AUD5_RXFS		169
-MX6Q_PAD_EIM_D24__UART1_DTR			170
-MX6Q_PAD_EIM_D25__WEIM_WEIM_D_25		171
-MX6Q_PAD_EIM_D25__ECSPI4_SS3			172
-MX6Q_PAD_EIM_D25__UART3_RXD			173
-MX6Q_PAD_EIM_D25__ECSPI1_SS3			174
-MX6Q_PAD_EIM_D25__ECSPI2_SS3			175
-MX6Q_PAD_EIM_D25__GPIO_3_25			176
-MX6Q_PAD_EIM_D25__AUDMUX_AUD5_RXC		177
-MX6Q_PAD_EIM_D25__UART1_DSR			178
-MX6Q_PAD_EIM_D26__WEIM_WEIM_D_26		179
-MX6Q_PAD_EIM_D26__IPU1_DI1_PIN11		180
-MX6Q_PAD_EIM_D26__IPU1_CSI0_D_1			181
-MX6Q_PAD_EIM_D26__IPU2_CSI1_D_14		182
-MX6Q_PAD_EIM_D26__UART2_TXD			183
-MX6Q_PAD_EIM_D26__GPIO_3_26			184
-MX6Q_PAD_EIM_D26__IPU1_SISG_2			185
-MX6Q_PAD_EIM_D26__IPU1_DISP1_DAT_22		186
-MX6Q_PAD_EIM_D27__WEIM_WEIM_D_27		187
-MX6Q_PAD_EIM_D27__IPU1_DI1_PIN13		188
-MX6Q_PAD_EIM_D27__IPU1_CSI0_D_0			189
-MX6Q_PAD_EIM_D27__IPU2_CSI1_D_13		190
-MX6Q_PAD_EIM_D27__UART2_RXD			191
-MX6Q_PAD_EIM_D27__GPIO_3_27			192
-MX6Q_PAD_EIM_D27__IPU1_SISG_3			193
-MX6Q_PAD_EIM_D27__IPU1_DISP1_DAT_23		194
-MX6Q_PAD_EIM_D28__WEIM_WEIM_D_28		195
-MX6Q_PAD_EIM_D28__I2C1_SDA			196
-MX6Q_PAD_EIM_D28__ECSPI4_MOSI			197
-MX6Q_PAD_EIM_D28__IPU2_CSI1_D_12		198
-MX6Q_PAD_EIM_D28__UART2_CTS			199
-MX6Q_PAD_EIM_D28__GPIO_3_28			200
-MX6Q_PAD_EIM_D28__IPU1_EXT_TRIG			201
-MX6Q_PAD_EIM_D28__IPU1_DI0_PIN13		202
-MX6Q_PAD_EIM_D29__WEIM_WEIM_D_29		203
-MX6Q_PAD_EIM_D29__IPU1_DI1_PIN15		204
-MX6Q_PAD_EIM_D29__ECSPI4_SS0			205
-MX6Q_PAD_EIM_D29__UART2_RTS			206
-MX6Q_PAD_EIM_D29__GPIO_3_29			207
-MX6Q_PAD_EIM_D29__IPU2_CSI1_VSYNC		208
-MX6Q_PAD_EIM_D29__IPU1_DI0_PIN14		209
-MX6Q_PAD_EIM_D30__WEIM_WEIM_D_30		210
-MX6Q_PAD_EIM_D30__IPU1_DISP1_DAT_21		211
-MX6Q_PAD_EIM_D30__IPU1_DI0_PIN11		212
-MX6Q_PAD_EIM_D30__IPU1_CSI0_D_3			213
-MX6Q_PAD_EIM_D30__UART3_CTS			214
-MX6Q_PAD_EIM_D30__GPIO_3_30			215
-MX6Q_PAD_EIM_D30__USBOH3_USBH1_OC		216
-MX6Q_PAD_EIM_D30__PL301_PER1_HPROT_0		217
-MX6Q_PAD_EIM_D31__WEIM_WEIM_D_31		218
-MX6Q_PAD_EIM_D31__IPU1_DISP1_DAT_20		219
-MX6Q_PAD_EIM_D31__IPU1_DI0_PIN12		220
-MX6Q_PAD_EIM_D31__IPU1_CSI0_D_2			221
-MX6Q_PAD_EIM_D31__UART3_RTS			222
-MX6Q_PAD_EIM_D31__GPIO_3_31			223
-MX6Q_PAD_EIM_D31__USBOH3_USBH1_PWR		224
-MX6Q_PAD_EIM_D31__PL301_PER1_HPROT_1		225
-MX6Q_PAD_EIM_A24__WEIM_WEIM_A_24		226
-MX6Q_PAD_EIM_A24__IPU1_DISP1_DAT_19		227
-MX6Q_PAD_EIM_A24__IPU2_CSI1_D_19		228
-MX6Q_PAD_EIM_A24__IPU2_SISG_2			229
-MX6Q_PAD_EIM_A24__IPU1_SISG_2			230
-MX6Q_PAD_EIM_A24__GPIO_5_4			231
-MX6Q_PAD_EIM_A24__PL301_PER1_HPROT_2		232
-MX6Q_PAD_EIM_A24__SRC_BT_CFG_24			233
-MX6Q_PAD_EIM_A23__WEIM_WEIM_A_23		234
-MX6Q_PAD_EIM_A23__IPU1_DISP1_DAT_18		235
-MX6Q_PAD_EIM_A23__IPU2_CSI1_D_18		236
-MX6Q_PAD_EIM_A23__IPU2_SISG_3			237
-MX6Q_PAD_EIM_A23__IPU1_SISG_3			238
-MX6Q_PAD_EIM_A23__GPIO_6_6			239
-MX6Q_PAD_EIM_A23__PL301_PER1_HPROT_3		240
-MX6Q_PAD_EIM_A23__SRC_BT_CFG_23			241
-MX6Q_PAD_EIM_A22__WEIM_WEIM_A_22		242
-MX6Q_PAD_EIM_A22__IPU1_DISP1_DAT_17		243
-MX6Q_PAD_EIM_A22__IPU2_CSI1_D_17		244
-MX6Q_PAD_EIM_A22__GPIO_2_16			245
-MX6Q_PAD_EIM_A22__TPSMP_HDATA_0			246
-MX6Q_PAD_EIM_A22__SRC_BT_CFG_22			247
-MX6Q_PAD_EIM_A21__WEIM_WEIM_A_21		248
-MX6Q_PAD_EIM_A21__IPU1_DISP1_DAT_16		249
-MX6Q_PAD_EIM_A21__IPU2_CSI1_D_16		250
-MX6Q_PAD_EIM_A21__RESERVED_RESERVED		251
-MX6Q_PAD_EIM_A21__MIPI_CORE_DPHY_OUT_18		252
-MX6Q_PAD_EIM_A21__GPIO_2_17			253
-MX6Q_PAD_EIM_A21__TPSMP_HDATA_1			254
-MX6Q_PAD_EIM_A21__SRC_BT_CFG_21			255
-MX6Q_PAD_EIM_A20__WEIM_WEIM_A_20		256
-MX6Q_PAD_EIM_A20__IPU1_DISP1_DAT_15		257
-MX6Q_PAD_EIM_A20__IPU2_CSI1_D_15		258
-MX6Q_PAD_EIM_A20__RESERVED_RESERVED		259
-MX6Q_PAD_EIM_A20__MIPI_CORE_DPHY_OUT_19		260
-MX6Q_PAD_EIM_A20__GPIO_2_18			261
-MX6Q_PAD_EIM_A20__TPSMP_HDATA_2			262
-MX6Q_PAD_EIM_A20__SRC_BT_CFG_20			263
-MX6Q_PAD_EIM_A19__WEIM_WEIM_A_19		264
-MX6Q_PAD_EIM_A19__IPU1_DISP1_DAT_14		265
-MX6Q_PAD_EIM_A19__IPU2_CSI1_D_14		266
-MX6Q_PAD_EIM_A19__RESERVED_RESERVED		267
-MX6Q_PAD_EIM_A19__MIPI_CORE_DPHY_OUT_20		268
-MX6Q_PAD_EIM_A19__GPIO_2_19			269
-MX6Q_PAD_EIM_A19__TPSMP_HDATA_3			270
-MX6Q_PAD_EIM_A19__SRC_BT_CFG_19			271
-MX6Q_PAD_EIM_A18__WEIM_WEIM_A_18		272
-MX6Q_PAD_EIM_A18__IPU1_DISP1_DAT_13		273
-MX6Q_PAD_EIM_A18__IPU2_CSI1_D_13		274
-MX6Q_PAD_EIM_A18__RESERVED_RESERVED		275
-MX6Q_PAD_EIM_A18__MIPI_CORE_DPHY_OUT_21		276
-MX6Q_PAD_EIM_A18__GPIO_2_20			277
-MX6Q_PAD_EIM_A18__TPSMP_HDATA_4			278
-MX6Q_PAD_EIM_A18__SRC_BT_CFG_18			279
-MX6Q_PAD_EIM_A17__WEIM_WEIM_A_17		280
-MX6Q_PAD_EIM_A17__IPU1_DISP1_DAT_12		281
-MX6Q_PAD_EIM_A17__IPU2_CSI1_D_12		282
-MX6Q_PAD_EIM_A17__RESERVED_RESERVED		283
-MX6Q_PAD_EIM_A17__MIPI_CORE_DPHY_OUT_22		284
-MX6Q_PAD_EIM_A17__GPIO_2_21			285
-MX6Q_PAD_EIM_A17__TPSMP_HDATA_5			286
-MX6Q_PAD_EIM_A17__SRC_BT_CFG_17			287
-MX6Q_PAD_EIM_A16__WEIM_WEIM_A_16		288
-MX6Q_PAD_EIM_A16__IPU1_DI1_DISP_CLK		289
-MX6Q_PAD_EIM_A16__IPU2_CSI1_PIXCLK		290
-MX6Q_PAD_EIM_A16__MIPI_CORE_DPHY_OUT_23		291
-MX6Q_PAD_EIM_A16__GPIO_2_22			292
-MX6Q_PAD_EIM_A16__TPSMP_HDATA_6			293
-MX6Q_PAD_EIM_A16__SRC_BT_CFG_16			294
-MX6Q_PAD_EIM_CS0__WEIM_WEIM_CS_0		295
-MX6Q_PAD_EIM_CS0__IPU1_DI1_PIN5			296
-MX6Q_PAD_EIM_CS0__ECSPI2_SCLK			297
-MX6Q_PAD_EIM_CS0__MIPI_CORE_DPHY_OUT_24		298
-MX6Q_PAD_EIM_CS0__GPIO_2_23			299
-MX6Q_PAD_EIM_CS0__TPSMP_HDATA_7			300
-MX6Q_PAD_EIM_CS1__WEIM_WEIM_CS_1		301
-MX6Q_PAD_EIM_CS1__IPU1_DI1_PIN6			302
-MX6Q_PAD_EIM_CS1__ECSPI2_MOSI			303
-MX6Q_PAD_EIM_CS1__MIPI_CORE_DPHY_OUT_25		304
-MX6Q_PAD_EIM_CS1__GPIO_2_24			305
-MX6Q_PAD_EIM_CS1__TPSMP_HDATA_8			306
-MX6Q_PAD_EIM_OE__WEIM_WEIM_OE			307
-MX6Q_PAD_EIM_OE__IPU1_DI1_PIN7			308
-MX6Q_PAD_EIM_OE__ECSPI2_MISO			309
-MX6Q_PAD_EIM_OE__MIPI_CORE_DPHY_OUT_26		310
-MX6Q_PAD_EIM_OE__GPIO_2_25			311
-MX6Q_PAD_EIM_OE__TPSMP_HDATA_9			312
-MX6Q_PAD_EIM_RW__WEIM_WEIM_RW			313
-MX6Q_PAD_EIM_RW__IPU1_DI1_PIN8			314
-MX6Q_PAD_EIM_RW__ECSPI2_SS0			315
-MX6Q_PAD_EIM_RW__MIPI_CORE_DPHY_OUT_27		316
-MX6Q_PAD_EIM_RW__GPIO_2_26			317
-MX6Q_PAD_EIM_RW__TPSMP_HDATA_10			318
-MX6Q_PAD_EIM_RW__SRC_BT_CFG_29			319
-MX6Q_PAD_EIM_LBA__WEIM_WEIM_LBA			320
-MX6Q_PAD_EIM_LBA__IPU1_DI1_PIN17		321
-MX6Q_PAD_EIM_LBA__ECSPI2_SS1			322
-MX6Q_PAD_EIM_LBA__GPIO_2_27			323
-MX6Q_PAD_EIM_LBA__TPSMP_HDATA_11		324
-MX6Q_PAD_EIM_LBA__SRC_BT_CFG_26			325
-MX6Q_PAD_EIM_EB0__WEIM_WEIM_EB_0		326
-MX6Q_PAD_EIM_EB0__IPU1_DISP1_DAT_11		327
-MX6Q_PAD_EIM_EB0__IPU2_CSI1_D_11		328
-MX6Q_PAD_EIM_EB0__MIPI_CORE_DPHY_OUT_0		329
-MX6Q_PAD_EIM_EB0__CCM_PMIC_RDY			330
-MX6Q_PAD_EIM_EB0__GPIO_2_28			331
-MX6Q_PAD_EIM_EB0__TPSMP_HDATA_12		332
-MX6Q_PAD_EIM_EB0__SRC_BT_CFG_27			333
-MX6Q_PAD_EIM_EB1__WEIM_WEIM_EB_1		334
-MX6Q_PAD_EIM_EB1__IPU1_DISP1_DAT_10		335
-MX6Q_PAD_EIM_EB1__IPU2_CSI1_D_10		336
-MX6Q_PAD_EIM_EB1__MIPI_CORE_DPHY__OUT_1		337
-MX6Q_PAD_EIM_EB1__GPIO_2_29			338
-MX6Q_PAD_EIM_EB1__TPSMP_HDATA_13		339
-MX6Q_PAD_EIM_EB1__SRC_BT_CFG_28			340
-MX6Q_PAD_EIM_DA0__WEIM_WEIM_DA_A_0		341
-MX6Q_PAD_EIM_DA0__IPU1_DISP1_DAT_9		342
-MX6Q_PAD_EIM_DA0__IPU2_CSI1_D_9			343
-MX6Q_PAD_EIM_DA0__MIPI_CORE_DPHY__OUT_2		344
-MX6Q_PAD_EIM_DA0__GPIO_3_0			345
-MX6Q_PAD_EIM_DA0__TPSMP_HDATA_14		346
-MX6Q_PAD_EIM_DA0__SRC_BT_CFG_0			347
-MX6Q_PAD_EIM_DA1__WEIM_WEIM_DA_A_1		348
-MX6Q_PAD_EIM_DA1__IPU1_DISP1_DAT_8		349
-MX6Q_PAD_EIM_DA1__IPU2_CSI1_D_8			350
-MX6Q_PAD_EIM_DA1__MIPI_CORE_DPHY_OUT_3		351
-MX6Q_PAD_EIM_DA1__USBPHY1_TX_LS_MODE		352
-MX6Q_PAD_EIM_DA1__GPIO_3_1			353
-MX6Q_PAD_EIM_DA1__TPSMP_HDATA_15		354
-MX6Q_PAD_EIM_DA1__SRC_BT_CFG_1			355
-MX6Q_PAD_EIM_DA2__WEIM_WEIM_DA_A_2		356
-MX6Q_PAD_EIM_DA2__IPU1_DISP1_DAT_7		357
-MX6Q_PAD_EIM_DA2__IPU2_CSI1_D_7			358
-MX6Q_PAD_EIM_DA2__MIPI_CORE_DPHY_OUT_4		359
-MX6Q_PAD_EIM_DA2__USBPHY1_TX_HS_MODE		360
-MX6Q_PAD_EIM_DA2__GPIO_3_2			361
-MX6Q_PAD_EIM_DA2__TPSMP_HDATA_16		362
-MX6Q_PAD_EIM_DA2__SRC_BT_CFG_2			363
-MX6Q_PAD_EIM_DA3__WEIM_WEIM_DA_A_3		364
-MX6Q_PAD_EIM_DA3__IPU1_DISP1_DAT_6		365
-MX6Q_PAD_EIM_DA3__IPU2_CSI1_D_6			366
-MX6Q_PAD_EIM_DA3__MIPI_CORE_DPHY_OUT_5		367
-MX6Q_PAD_EIM_DA3__USBPHY1_TX_HIZ		368
-MX6Q_PAD_EIM_DA3__GPIO_3_3			369
-MX6Q_PAD_EIM_DA3__TPSMP_HDATA_17		370
-MX6Q_PAD_EIM_DA3__SRC_BT_CFG_3			371
-MX6Q_PAD_EIM_DA4__WEIM_WEIM_DA_A_4		372
-MX6Q_PAD_EIM_DA4__IPU1_DISP1_DAT_5		373
-MX6Q_PAD_EIM_DA4__IPU2_CSI1_D_5			374
-MX6Q_PAD_EIM_DA4__MIPI_CORE_DPHY_OUT_6		375
-MX6Q_PAD_EIM_DA4__ANATOP_USBPHY1_TX_EN		376
-MX6Q_PAD_EIM_DA4__GPIO_3_4			377
-MX6Q_PAD_EIM_DA4__TPSMP_HDATA_18		378
-MX6Q_PAD_EIM_DA4__SRC_BT_CFG_4			379
-MX6Q_PAD_EIM_DA5__WEIM_WEIM_DA_A_5		380
-MX6Q_PAD_EIM_DA5__IPU1_DISP1_DAT_4		381
-MX6Q_PAD_EIM_DA5__IPU2_CSI1_D_4			382
-MX6Q_PAD_EIM_DA5__MIPI_CORE_DPHY_OUT_7		383
-MX6Q_PAD_EIM_DA5__ANATOP_USBPHY1_TX_DP		384
-MX6Q_PAD_EIM_DA5__GPIO_3_5			385
-MX6Q_PAD_EIM_DA5__TPSMP_HDATA_19		386
-MX6Q_PAD_EIM_DA5__SRC_BT_CFG_5			387
-MX6Q_PAD_EIM_DA6__WEIM_WEIM_DA_A_6		388
-MX6Q_PAD_EIM_DA6__IPU1_DISP1_DAT_3		389
-MX6Q_PAD_EIM_DA6__IPU2_CSI1_D_3			390
-MX6Q_PAD_EIM_DA6__MIPI_CORE_DPHY_OUT_8		391
-MX6Q_PAD_EIM_DA6__ANATOP_USBPHY1_TX_DN		392
-MX6Q_PAD_EIM_DA6__GPIO_3_6			393
-MX6Q_PAD_EIM_DA6__TPSMP_HDATA_20		394
-MX6Q_PAD_EIM_DA6__SRC_BT_CFG_6			395
-MX6Q_PAD_EIM_DA7__WEIM_WEIM_DA_A_7		396
-MX6Q_PAD_EIM_DA7__IPU1_DISP1_DAT_2		397
-MX6Q_PAD_EIM_DA7__IPU2_CSI1_D_2			398
-MX6Q_PAD_EIM_DA7__MIPI_CORE_DPHY_OUT_9		399
-MX6Q_PAD_EIM_DA7__GPIO_3_7			400
-MX6Q_PAD_EIM_DA7__TPSMP_HDATA_21		401
-MX6Q_PAD_EIM_DA7__SRC_BT_CFG_7			402
-MX6Q_PAD_EIM_DA8__WEIM_WEIM_DA_A_8		403
-MX6Q_PAD_EIM_DA8__IPU1_DISP1_DAT_1		404
-MX6Q_PAD_EIM_DA8__IPU2_CSI1_D_1			405
-MX6Q_PAD_EIM_DA8__MIPI_CORE_DPHY_OUT_10		406
-MX6Q_PAD_EIM_DA8__GPIO_3_8			407
-MX6Q_PAD_EIM_DA8__TPSMP_HDATA_22		408
-MX6Q_PAD_EIM_DA8__SRC_BT_CFG_8			409
-MX6Q_PAD_EIM_DA9__WEIM_WEIM_DA_A_9		410
-MX6Q_PAD_EIM_DA9__IPU1_DISP1_DAT_0		411
-MX6Q_PAD_EIM_DA9__IPU2_CSI1_D_0			412
-MX6Q_PAD_EIM_DA9__MIPI_CORE_DPHY_OUT_11		413
-MX6Q_PAD_EIM_DA9__GPIO_3_9			414
-MX6Q_PAD_EIM_DA9__TPSMP_HDATA_23		415
-MX6Q_PAD_EIM_DA9__SRC_BT_CFG_9			416
-MX6Q_PAD_EIM_DA10__WEIM_WEIM_DA_A_10		417
-MX6Q_PAD_EIM_DA10__IPU1_DI1_PIN15		418
-MX6Q_PAD_EIM_DA10__IPU2_CSI1_DATA_EN		419
-MX6Q_PAD_EIM_DA10__MIPI_CORE_DPHY_OUT12		420
-MX6Q_PAD_EIM_DA10__GPIO_3_10			421
-MX6Q_PAD_EIM_DA10__TPSMP_HDATA_24		422
-MX6Q_PAD_EIM_DA10__SRC_BT_CFG_10		423
-MX6Q_PAD_EIM_DA11__WEIM_WEIM_DA_A_11		424
-MX6Q_PAD_EIM_DA11__IPU1_DI1_PIN2		425
-MX6Q_PAD_EIM_DA11__IPU2_CSI1_HSYNC		426
-MX6Q_PAD_EIM_DA11__MIPI_CORE_DPHY_OUT13		427
-MX6Q_PAD_EIM_DA11__SDMA_DBG_EVT_CHN_6		428
-MX6Q_PAD_EIM_DA11__GPIO_3_11			429
-MX6Q_PAD_EIM_DA11__TPSMP_HDATA_25		430
-MX6Q_PAD_EIM_DA11__SRC_BT_CFG_11		431
-MX6Q_PAD_EIM_DA12__WEIM_WEIM_DA_A_12		432
-MX6Q_PAD_EIM_DA12__IPU1_DI1_PIN3		433
-MX6Q_PAD_EIM_DA12__IPU2_CSI1_VSYNC		434
-MX6Q_PAD_EIM_DA12__MIPI_CORE_DPHY_OUT14		435
-MX6Q_PAD_EIM_DA12__SDMA_DEBUG_EVT_CHN_3		436
-MX6Q_PAD_EIM_DA12__GPIO_3_12			437
-MX6Q_PAD_EIM_DA12__TPSMP_HDATA_26		438
-MX6Q_PAD_EIM_DA12__SRC_BT_CFG_12		439
-MX6Q_PAD_EIM_DA13__WEIM_WEIM_DA_A_13		440
-MX6Q_PAD_EIM_DA13__IPU1_DI1_D0_CS		441
-MX6Q_PAD_EIM_DA13__CCM_DI1_EXT_CLK		442
-MX6Q_PAD_EIM_DA13__MIPI_CORE_DPHY_OUT15		443
-MX6Q_PAD_EIM_DA13__SDMA_DEBUG_EVT_CHN_4		444
-MX6Q_PAD_EIM_DA13__GPIO_3_13			445
-MX6Q_PAD_EIM_DA13__TPSMP_HDATA_27		446
-MX6Q_PAD_EIM_DA13__SRC_BT_CFG_13		447
-MX6Q_PAD_EIM_DA14__WEIM_WEIM_DA_A_14		448
-MX6Q_PAD_EIM_DA14__IPU1_DI1_D1_CS		449
-MX6Q_PAD_EIM_DA14__CCM_DI0_EXT_CLK		450
-MX6Q_PAD_EIM_DA14__MIPI_CORE_DPHY_OUT16		451
-MX6Q_PAD_EIM_DA14__SDMA_DEBUG_EVT_CHN_5		452
-MX6Q_PAD_EIM_DA14__GPIO_3_14			453
-MX6Q_PAD_EIM_DA14__TPSMP_HDATA_28		454
-MX6Q_PAD_EIM_DA14__SRC_BT_CFG_14		455
-MX6Q_PAD_EIM_DA15__WEIM_WEIM_DA_A_15		456
-MX6Q_PAD_EIM_DA15__IPU1_DI1_PIN1		457
-MX6Q_PAD_EIM_DA15__IPU1_DI1_PIN4		458
-MX6Q_PAD_EIM_DA15__MIPI_CORE_DPHY_OUT17		459
-MX6Q_PAD_EIM_DA15__GPIO_3_15			460
-MX6Q_PAD_EIM_DA15__TPSMP_HDATA_29		461
-MX6Q_PAD_EIM_DA15__SRC_BT_CFG_15		462
-MX6Q_PAD_EIM_WAIT__WEIM_WEIM_WAIT		463
-MX6Q_PAD_EIM_WAIT__WEIM_WEIM_DTACK_B		464
-MX6Q_PAD_EIM_WAIT__GPIO_5_0			465
-MX6Q_PAD_EIM_WAIT__TPSMP_HDATA_30		466
-MX6Q_PAD_EIM_WAIT__SRC_BT_CFG_25		467
-MX6Q_PAD_EIM_BCLK__WEIM_WEIM_BCLK		468
-MX6Q_PAD_EIM_BCLK__IPU1_DI1_PIN16		469
-MX6Q_PAD_EIM_BCLK__GPIO_6_31			470
-MX6Q_PAD_EIM_BCLK__TPSMP_HDATA_31		471
-MX6Q_PAD_DI0_DISP_CLK__IPU1_DI0_DSP_CLK		472
-MX6Q_PAD_DI0_DISP_CLK__IPU2_DI0_DSP_CLK		473
-MX6Q_PAD_DI0_DISP_CLK__MIPI_CR_DPY_OT28		474
-MX6Q_PAD_DI0_DISP_CLK__SDMA_DBG_CR_STA0		475
-MX6Q_PAD_DI0_DISP_CLK__GPIO_4_16		476
-MX6Q_PAD_DI0_DISP_CLK__MMDC_DEBUG_0		477
-MX6Q_PAD_DI0_PIN15__IPU1_DI0_PIN15		478
-MX6Q_PAD_DI0_PIN15__IPU2_DI0_PIN15		479
-MX6Q_PAD_DI0_PIN15__AUDMUX_AUD6_TXC		480
-MX6Q_PAD_DI0_PIN15__MIPI_CR_DPHY_OUT_29		481
-MX6Q_PAD_DI0_PIN15__SDMA_DBG_CORE_STA_1		482
-MX6Q_PAD_DI0_PIN15__GPIO_4_17			483
-MX6Q_PAD_DI0_PIN15__MMDC_MMDC_DEBUG_1		484
-MX6Q_PAD_DI0_PIN2__IPU1_DI0_PIN2		485
-MX6Q_PAD_DI0_PIN2__IPU2_DI0_PIN2		486
-MX6Q_PAD_DI0_PIN2__AUDMUX_AUD6_TXD		487
-MX6Q_PAD_DI0_PIN2__MIPI_CR_DPHY_OUT_30		488
-MX6Q_PAD_DI0_PIN2__SDMA_DBG_CORE_STA_2		489
-MX6Q_PAD_DI0_PIN2__GPIO_4_18			490
-MX6Q_PAD_DI0_PIN2__MMDC_DEBUG_2			491
-MX6Q_PAD_DI0_PIN2__PL301_PER1_HADDR_9		492
-MX6Q_PAD_DI0_PIN3__IPU1_DI0_PIN3		493
-MX6Q_PAD_DI0_PIN3__IPU2_DI0_PIN3		494
-MX6Q_PAD_DI0_PIN3__AUDMUX_AUD6_TXFS		495
-MX6Q_PAD_DI0_PIN3__MIPI_CORE_DPHY_OUT31		496
-MX6Q_PAD_DI0_PIN3__SDMA_DBG_CORE_STA_3		497
-MX6Q_PAD_DI0_PIN3__GPIO_4_19			498
-MX6Q_PAD_DI0_PIN3__MMDC_MMDC_DEBUG_3		499
-MX6Q_PAD_DI0_PIN3__PL301_PER1_HADDR_10		500
-MX6Q_PAD_DI0_PIN4__IPU1_DI0_PIN4		501
-MX6Q_PAD_DI0_PIN4__IPU2_DI0_PIN4		502
-MX6Q_PAD_DI0_PIN4__AUDMUX_AUD6_RXD		503
-MX6Q_PAD_DI0_PIN4__USDHC1_WP			504
-MX6Q_PAD_DI0_PIN4__SDMA_DEBUG_YIELD		505
-MX6Q_PAD_DI0_PIN4__GPIO_4_20			506
-MX6Q_PAD_DI0_PIN4__MMDC_MMDC_DEBUG_4		507
-MX6Q_PAD_DI0_PIN4__PL301_PER1_HADDR_11		508
-MX6Q_PAD_DISP0_DAT0__IPU1_DISP0_DAT_0		509
-MX6Q_PAD_DISP0_DAT0__IPU2_DISP0_DAT_0		510
-MX6Q_PAD_DISP0_DAT0__ECSPI3_SCLK		511
-MX6Q_PAD_DISP0_DAT0__USDHC1_USDHC_DBG_0		512
-MX6Q_PAD_DISP0_DAT0__SDMA_DBG_CORE_RUN		513
-MX6Q_PAD_DISP0_DAT0__GPIO_4_21			514
-MX6Q_PAD_DISP0_DAT0__MMDC_MMDC_DEBUG_5		515
-MX6Q_PAD_DISP0_DAT1__IPU1_DISP0_DAT_1		516
-MX6Q_PAD_DISP0_DAT1__IPU2_DISP0_DAT_1		517
-MX6Q_PAD_DISP0_DAT1__ECSPI3_MOSI		518
-MX6Q_PAD_DISP0_DAT1__USDHC1_USDHC_DBG_1		519
-MX6Q_PAD_DISP0_DAT1__SDMA_DBG_EVT_CHNSL		520
-MX6Q_PAD_DISP0_DAT1__GPIO_4_22			521
-MX6Q_PAD_DISP0_DAT1__MMDC_DEBUG_6		522
-MX6Q_PAD_DISP0_DAT1__PL301_PER1_HADR_12		523
-MX6Q_PAD_DISP0_DAT2__IPU1_DISP0_DAT_2		524
-MX6Q_PAD_DISP0_DAT2__IPU2_DISP0_DAT_2		525
-MX6Q_PAD_DISP0_DAT2__ECSPI3_MISO		526
-MX6Q_PAD_DISP0_DAT2__USDHC1_USDHC_DBG_2		527
-MX6Q_PAD_DISP0_DAT2__SDMA_DEBUG_MODE		528
-MX6Q_PAD_DISP0_DAT2__GPIO_4_23			529
-MX6Q_PAD_DISP0_DAT2__MMDC_DEBUG_7		530
-MX6Q_PAD_DISP0_DAT2__PL301_PER1_HADR_13		531
-MX6Q_PAD_DISP0_DAT3__IPU1_DISP0_DAT_3		532
-MX6Q_PAD_DISP0_DAT3__IPU2_DISP0_DAT_3		533
-MX6Q_PAD_DISP0_DAT3__ECSPI3_SS0			534
-MX6Q_PAD_DISP0_DAT3__USDHC1_USDHC_DBG_3		535
-MX6Q_PAD_DISP0_DAT3__SDMA_DBG_BUS_ERROR		536
-MX6Q_PAD_DISP0_DAT3__GPIO_4_24			537
-MX6Q_PAD_DISP0_DAT3__MMDC_MMDC_DBG_8		538
-MX6Q_PAD_DISP0_DAT3__PL301_PER1_HADR_14		539
-MX6Q_PAD_DISP0_DAT4__IPU1_DISP0_DAT_4		540
-MX6Q_PAD_DISP0_DAT4__IPU2_DISP0_DAT_4		541
-MX6Q_PAD_DISP0_DAT4__ECSPI3_SS1			542
-MX6Q_PAD_DISP0_DAT4__USDHC1_USDHC_DBG_4		543
-MX6Q_PAD_DISP0_DAT4__SDMA_DEBUG_BUS_RWB		544
-MX6Q_PAD_DISP0_DAT4__GPIO_4_25			545
-MX6Q_PAD_DISP0_DAT4__MMDC_MMDC_DEBUG_9		546
-MX6Q_PAD_DISP0_DAT4__PL301_PER1_HADR_15		547
-MX6Q_PAD_DISP0_DAT5__IPU1_DISP0_DAT_5		548
-MX6Q_PAD_DISP0_DAT5__IPU2_DISP0_DAT_5		549
-MX6Q_PAD_DISP0_DAT5__ECSPI3_SS2			550
-MX6Q_PAD_DISP0_DAT5__AUDMUX_AUD6_RXFS		551
-MX6Q_PAD_DISP0_DAT5__SDMA_DBG_MCH_DMBUS		552
-MX6Q_PAD_DISP0_DAT5__GPIO_4_26			553
-MX6Q_PAD_DISP0_DAT5__MMDC_DEBUG_10		554
-MX6Q_PAD_DISP0_DAT5__PL301_PER1_HADR_16		555
-MX6Q_PAD_DISP0_DAT6__IPU1_DISP0_DAT_6		556
-MX6Q_PAD_DISP0_DAT6__IPU2_DISP0_DAT_6		557
-MX6Q_PAD_DISP0_DAT6__ECSPI3_SS3			558
-MX6Q_PAD_DISP0_DAT6__AUDMUX_AUD6_RXC		559
-MX6Q_PAD_DISP0_DAT6__SDMA_DBG_RTBUF_WRT		560
-MX6Q_PAD_DISP0_DAT6__GPIO_4_27			561
-MX6Q_PAD_DISP0_DAT6__MMDC_DEBUG_11		562
-MX6Q_PAD_DISP0_DAT6__PL301_PER1_HADR_17		563
-MX6Q_PAD_DISP0_DAT7__IPU1_DISP0_DAT_7		564
-MX6Q_PAD_DISP0_DAT7__IPU2_DISP0_DAT_7		565
-MX6Q_PAD_DISP0_DAT7__ECSPI3_RDY			566
-MX6Q_PAD_DISP0_DAT7__USDHC1_USDHC_DBG_5		567
-MX6Q_PAD_DISP0_DAT7__SDMA_DBG_EVT_CHN_0		568
-MX6Q_PAD_DISP0_DAT7__GPIO_4_28			569
-MX6Q_PAD_DISP0_DAT7__MMDC_DEBUG_12		570
-MX6Q_PAD_DISP0_DAT7__PL301_PER1_HADR_18		571
-MX6Q_PAD_DISP0_DAT8__IPU1_DISP0_DAT_8		572
-MX6Q_PAD_DISP0_DAT8__IPU2_DISP0_DAT_8		573
-MX6Q_PAD_DISP0_DAT8__PWM1_PWMO			574
-MX6Q_PAD_DISP0_DAT8__WDOG1_WDOG_B		575
-MX6Q_PAD_DISP0_DAT8__SDMA_DBG_EVT_CHN_1		576
-MX6Q_PAD_DISP0_DAT8__GPIO_4_29			577
-MX6Q_PAD_DISP0_DAT8__MMDC_DEBUG_13		578
-MX6Q_PAD_DISP0_DAT8__PL301_PER1_HADR_19		579
-MX6Q_PAD_DISP0_DAT9__IPU1_DISP0_DAT_9		580
-MX6Q_PAD_DISP0_DAT9__IPU2_DISP0_DAT_9		581
-MX6Q_PAD_DISP0_DAT9__PWM2_PWMO			582
-MX6Q_PAD_DISP0_DAT9__WDOG2_WDOG_B		583
-MX6Q_PAD_DISP0_DAT9__SDMA_DBG_EVT_CHN_2		584
-MX6Q_PAD_DISP0_DAT9__GPIO_4_30			585
-MX6Q_PAD_DISP0_DAT9__MMDC_DEBUG_14		586
-MX6Q_PAD_DISP0_DAT9__PL301_PER1_HADR_20		587
-MX6Q_PAD_DISP0_DAT10__IPU1_DISP0_DAT_10		588
-MX6Q_PAD_DISP0_DAT10__IPU2_DISP0_DAT_10		589
-MX6Q_PAD_DISP0_DAT10__USDHC1_DBG_6		590
-MX6Q_PAD_DISP0_DAT10__SDMA_DBG_EVT_CHN3		591
-MX6Q_PAD_DISP0_DAT10__GPIO_4_31			592
-MX6Q_PAD_DISP0_DAT10__MMDC_DEBUG_15		593
-MX6Q_PAD_DISP0_DAT10__PL301_PER1_HADR21		594
-MX6Q_PAD_DISP0_DAT11__IPU1_DISP0_DAT_11		595
-MX6Q_PAD_DISP0_DAT11__IPU2_DISP0_DAT_11		596
-MX6Q_PAD_DISP0_DAT11__USDHC1_USDHC_DBG7		597
-MX6Q_PAD_DISP0_DAT11__SDMA_DBG_EVT_CHN4		598
-MX6Q_PAD_DISP0_DAT11__GPIO_5_5			599
-MX6Q_PAD_DISP0_DAT11__MMDC_DEBUG_16		600
-MX6Q_PAD_DISP0_DAT11__PL301_PER1_HADR22		601
-MX6Q_PAD_DISP0_DAT12__IPU1_DISP0_DAT_12		602
-MX6Q_PAD_DISP0_DAT12__IPU2_DISP0_DAT_12		603
-MX6Q_PAD_DISP0_DAT12__RESERVED_RESERVED		604
-MX6Q_PAD_DISP0_DAT12__SDMA_DBG_EVT_CHN5		605
-MX6Q_PAD_DISP0_DAT12__GPIO_5_6			606
-MX6Q_PAD_DISP0_DAT12__MMDC_DEBUG_17		607
-MX6Q_PAD_DISP0_DAT12__PL301_PER1_HADR23		608
-MX6Q_PAD_DISP0_DAT13__IPU1_DISP0_DAT_13		609
-MX6Q_PAD_DISP0_DAT13__IPU2_DISP0_DAT_13		610
-MX6Q_PAD_DISP0_DAT13__AUDMUX_AUD5_RXFS		611
-MX6Q_PAD_DISP0_DAT13__SDMA_DBG_EVT_CHN0		612
-MX6Q_PAD_DISP0_DAT13__GPIO_5_7			613
-MX6Q_PAD_DISP0_DAT13__MMDC_DEBUG_18		614
-MX6Q_PAD_DISP0_DAT13__PL301_PER1_HADR24		615
-MX6Q_PAD_DISP0_DAT14__IPU1_DISP0_DAT_14		616
-MX6Q_PAD_DISP0_DAT14__IPU2_DISP0_DAT_14		617
-MX6Q_PAD_DISP0_DAT14__AUDMUX_AUD5_RXC		618
-MX6Q_PAD_DISP0_DAT14__SDMA_DBG_EVT_CHN1		619
-MX6Q_PAD_DISP0_DAT14__GPIO_5_8			620
-MX6Q_PAD_DISP0_DAT14__MMDC_DEBUG_19		621
-MX6Q_PAD_DISP0_DAT15__IPU1_DISP0_DAT_15		622
-MX6Q_PAD_DISP0_DAT15__IPU2_DISP0_DAT_15		623
-MX6Q_PAD_DISP0_DAT15__ECSPI1_SS1		624
-MX6Q_PAD_DISP0_DAT15__ECSPI2_SS1		625
-MX6Q_PAD_DISP0_DAT15__SDMA_DBG_EVT_CHN2		626
-MX6Q_PAD_DISP0_DAT15__GPIO_5_9			627
-MX6Q_PAD_DISP0_DAT15__MMDC_DEBUG_20		628
-MX6Q_PAD_DISP0_DAT15__PL301_PER1_HADR25		629
-MX6Q_PAD_DISP0_DAT16__IPU1_DISP0_DAT_16		630
-MX6Q_PAD_DISP0_DAT16__IPU2_DISP0_DAT_16		631
-MX6Q_PAD_DISP0_DAT16__ECSPI2_MOSI		632
-MX6Q_PAD_DISP0_DAT16__AUDMUX_AUD5_TXC		633
-MX6Q_PAD_DISP0_DAT16__SDMA_EXT_EVENT_0		634
-MX6Q_PAD_DISP0_DAT16__GPIO_5_10			635
-MX6Q_PAD_DISP0_DAT16__MMDC_DEBUG_21		636
-MX6Q_PAD_DISP0_DAT16__PL301_PER1_HADR26		637
-MX6Q_PAD_DISP0_DAT17__IPU1_DISP0_DAT_17		638
-MX6Q_PAD_DISP0_DAT17__IPU2_DISP0_DAT_17		639
-MX6Q_PAD_DISP0_DAT17__ECSPI2_MISO		640
-MX6Q_PAD_DISP0_DAT17__AUDMUX_AUD5_TXD		641
-MX6Q_PAD_DISP0_DAT17__SDMA_EXT_EVENT_1		642
-MX6Q_PAD_DISP0_DAT17__GPIO_5_11			643
-MX6Q_PAD_DISP0_DAT17__MMDC_DEBUG_22		644
-MX6Q_PAD_DISP0_DAT17__PL301_PER1_HADR27		645
-MX6Q_PAD_DISP0_DAT18__IPU1_DISP0_DAT_18		646
-MX6Q_PAD_DISP0_DAT18__IPU2_DISP0_DAT_18		647
-MX6Q_PAD_DISP0_DAT18__ECSPI2_SS0		648
-MX6Q_PAD_DISP0_DAT18__AUDMUX_AUD5_TXFS		649
-MX6Q_PAD_DISP0_DAT18__AUDMUX_AUD4_RXFS		650
-MX6Q_PAD_DISP0_DAT18__GPIO_5_12			651
-MX6Q_PAD_DISP0_DAT18__MMDC_DEBUG_23		652
-MX6Q_PAD_DISP0_DAT18__WEIM_WEIM_CS_2		653
-MX6Q_PAD_DISP0_DAT19__IPU1_DISP0_DAT_19		654
-MX6Q_PAD_DISP0_DAT19__IPU2_DISP0_DAT_19		655
-MX6Q_PAD_DISP0_DAT19__ECSPI2_SCLK		656
-MX6Q_PAD_DISP0_DAT19__AUDMUX_AUD5_RXD		657
-MX6Q_PAD_DISP0_DAT19__AUDMUX_AUD4_RXC		658
-MX6Q_PAD_DISP0_DAT19__GPIO_5_13			659
-MX6Q_PAD_DISP0_DAT19__MMDC_DEBUG_24		660
-MX6Q_PAD_DISP0_DAT19__WEIM_WEIM_CS_3		661
-MX6Q_PAD_DISP0_DAT20__IPU1_DISP0_DAT_20		662
-MX6Q_PAD_DISP0_DAT20__IPU2_DISP0_DAT_20		663
-MX6Q_PAD_DISP0_DAT20__ECSPI1_SCLK		664
-MX6Q_PAD_DISP0_DAT20__AUDMUX_AUD4_TXC		665
-MX6Q_PAD_DISP0_DAT20__SDMA_DBG_EVT_CHN7		666
-MX6Q_PAD_DISP0_DAT20__GPIO_5_14			667
-MX6Q_PAD_DISP0_DAT20__MMDC_DEBUG_25		668
-MX6Q_PAD_DISP0_DAT20__PL301_PER1_HADR28		669
-MX6Q_PAD_DISP0_DAT21__IPU1_DISP0_DAT_21		670
-MX6Q_PAD_DISP0_DAT21__IPU2_DISP0_DAT_21		671
-MX6Q_PAD_DISP0_DAT21__ECSPI1_MOSI		672
-MX6Q_PAD_DISP0_DAT21__AUDMUX_AUD4_TXD		673
-MX6Q_PAD_DISP0_DAT21__SDMA_DBG_BUS_DEV0		674
-MX6Q_PAD_DISP0_DAT21__GPIO_5_15			675
-MX6Q_PAD_DISP0_DAT21__MMDC_DEBUG_26		676
-MX6Q_PAD_DISP0_DAT21__PL301_PER1_HADR29		677
-MX6Q_PAD_DISP0_DAT22__IPU1_DISP0_DAT_22		678
-MX6Q_PAD_DISP0_DAT22__IPU2_DISP0_DAT_22		679
-MX6Q_PAD_DISP0_DAT22__ECSPI1_MISO		680
-MX6Q_PAD_DISP0_DAT22__AUDMUX_AUD4_TXFS		681
-MX6Q_PAD_DISP0_DAT22__SDMA_DBG_BUS_DEV1		682
-MX6Q_PAD_DISP0_DAT22__GPIO_5_16			683
-MX6Q_PAD_DISP0_DAT22__MMDC_DEBUG_27		684
-MX6Q_PAD_DISP0_DAT22__PL301_PER1_HADR30		685
-MX6Q_PAD_DISP0_DAT23__IPU1_DISP0_DAT_23		686
-MX6Q_PAD_DISP0_DAT23__IPU2_DISP0_DAT_23		687
-MX6Q_PAD_DISP0_DAT23__ECSPI1_SS0		688
-MX6Q_PAD_DISP0_DAT23__AUDMUX_AUD4_RXD		689
-MX6Q_PAD_DISP0_DAT23__SDMA_DBG_BUS_DEV2		690
-MX6Q_PAD_DISP0_DAT23__GPIO_5_17			691
-MX6Q_PAD_DISP0_DAT23__MMDC_DEBUG_28		692
-MX6Q_PAD_DISP0_DAT23__PL301_PER1_HADR31		693
-MX6Q_PAD_ENET_MDIO__RESERVED_RESERVED		694
-MX6Q_PAD_ENET_MDIO__ENET_MDIO			695
-MX6Q_PAD_ENET_MDIO__ESAI1_SCKR			696
-MX6Q_PAD_ENET_MDIO__SDMA_DEBUG_BUS_DEV3		697
-MX6Q_PAD_ENET_MDIO__ENET_1588_EVT1_OUT		698
-MX6Q_PAD_ENET_MDIO__GPIO_1_22			699
-MX6Q_PAD_ENET_MDIO__SPDIF_PLOCK			700
-MX6Q_PAD_ENET_REF_CLK__RESERVED_RSRVED		701
-MX6Q_PAD_ENET_REF_CLK__ENET_TX_CLK		702
-MX6Q_PAD_ENET_REF_CLK__ESAI1_FSR		703
-MX6Q_PAD_ENET_REF_CLK__SDMA_DBGBUS_DEV4		704
-MX6Q_PAD_ENET_REF_CLK__GPIO_1_23		705
-MX6Q_PAD_ENET_REF_CLK__SPDIF_SRCLK		706
-MX6Q_PAD_ENET_REF_CLK__USBPHY1_RX_SQH		707
-MX6Q_PAD_ENET_RX_ER__ENET_RX_ER			708
-MX6Q_PAD_ENET_RX_ER__ESAI1_HCKR			709
-MX6Q_PAD_ENET_RX_ER__SPDIF_IN1			710
-MX6Q_PAD_ENET_RX_ER__ENET_1588_EVT2_OUT		711
-MX6Q_PAD_ENET_RX_ER__GPIO_1_24			712
-MX6Q_PAD_ENET_RX_ER__PHY_TDI			713
-MX6Q_PAD_ENET_RX_ER__USBPHY1_RX_HS_RXD		714
-MX6Q_PAD_ENET_CRS_DV__RESERVED_RSRVED		715
-MX6Q_PAD_ENET_CRS_DV__ENET_RX_EN		716
-MX6Q_PAD_ENET_CRS_DV__ESAI1_SCKT		717
-MX6Q_PAD_ENET_CRS_DV__SPDIF_EXTCLK		718
-MX6Q_PAD_ENET_CRS_DV__GPIO_1_25			719
-MX6Q_PAD_ENET_CRS_DV__PHY_TDO			720
-MX6Q_PAD_ENET_CRS_DV__USBPHY1_RX_FS_RXD		721
-MX6Q_PAD_ENET_RXD1__MLB_MLBSIG			722
-MX6Q_PAD_ENET_RXD1__ENET_RDATA_1		723
-MX6Q_PAD_ENET_RXD1__ESAI1_FST			724
-MX6Q_PAD_ENET_RXD1__ENET_1588_EVT3_OUT		725
-MX6Q_PAD_ENET_RXD1__GPIO_1_26			726
-MX6Q_PAD_ENET_RXD1__PHY_TCK			727
-MX6Q_PAD_ENET_RXD1__USBPHY1_RX_DISCON		728
-MX6Q_PAD_ENET_RXD0__OSC32K_32K_OUT		729
-MX6Q_PAD_ENET_RXD0__ENET_RDATA_0		730
-MX6Q_PAD_ENET_RXD0__ESAI1_HCKT			731
-MX6Q_PAD_ENET_RXD0__SPDIF_OUT1			732
-MX6Q_PAD_ENET_RXD0__GPIO_1_27			733
-MX6Q_PAD_ENET_RXD0__PHY_TMS			734
-MX6Q_PAD_ENET_RXD0__USBPHY1_PLL_CK20DIV		735
-MX6Q_PAD_ENET_TX_EN__RESERVED_RSRVED		736
-MX6Q_PAD_ENET_TX_EN__ENET_TX_EN			737
-MX6Q_PAD_ENET_TX_EN__ESAI1_TX3_RX2		738
-MX6Q_PAD_ENET_TX_EN__GPIO_1_28			739
-MX6Q_PAD_ENET_TX_EN__SATA_PHY_TDI		740
-MX6Q_PAD_ENET_TX_EN__USBPHY2_RX_SQH		741
-MX6Q_PAD_ENET_TXD1__MLB_MLBCLK			742
-MX6Q_PAD_ENET_TXD1__ENET_TDATA_1		743
-MX6Q_PAD_ENET_TXD1__ESAI1_TX2_RX3		744
-MX6Q_PAD_ENET_TXD1__ENET_1588_EVENT0_IN		745
-MX6Q_PAD_ENET_TXD1__GPIO_1_29			746
-MX6Q_PAD_ENET_TXD1__SATA_PHY_TDO		747
-MX6Q_PAD_ENET_TXD1__USBPHY2_RX_HS_RXD		748
-MX6Q_PAD_ENET_TXD0__RESERVED_RSRVED		749
-MX6Q_PAD_ENET_TXD0__ENET_TDATA_0		750
-MX6Q_PAD_ENET_TXD0__ESAI1_TX4_RX1		751
-MX6Q_PAD_ENET_TXD0__GPIO_1_30			752
-MX6Q_PAD_ENET_TXD0__SATA_PHY_TCK		753
-MX6Q_PAD_ENET_TXD0__USBPHY2_RX_FS_RXD		754
-MX6Q_PAD_ENET_MDC__MLB_MLBDAT			755
-MX6Q_PAD_ENET_MDC__ENET_MDC			756
-MX6Q_PAD_ENET_MDC__ESAI1_TX5_RX0		757
-MX6Q_PAD_ENET_MDC__ENET_1588_EVENT1_IN		758
-MX6Q_PAD_ENET_MDC__GPIO_1_31			759
-MX6Q_PAD_ENET_MDC__SATA_PHY_TMS			760
-MX6Q_PAD_ENET_MDC__USBPHY2_RX_DISCON		761
-MX6Q_PAD_DRAM_D40__MMDC_DRAM_D_40		762
-MX6Q_PAD_DRAM_D41__MMDC_DRAM_D_41		763
-MX6Q_PAD_DRAM_D42__MMDC_DRAM_D_42		764
-MX6Q_PAD_DRAM_D43__MMDC_DRAM_D_43		765
-MX6Q_PAD_DRAM_D44__MMDC_DRAM_D_44		766
-MX6Q_PAD_DRAM_D45__MMDC_DRAM_D_45		767
-MX6Q_PAD_DRAM_D46__MMDC_DRAM_D_46		768
-MX6Q_PAD_DRAM_D47__MMDC_DRAM_D_47		769
-MX6Q_PAD_DRAM_SDQS5__MMDC_DRAM_SDQS_5		770
-MX6Q_PAD_DRAM_DQM5__MMDC_DRAM_DQM_5		771
-MX6Q_PAD_DRAM_D32__MMDC_DRAM_D_32		772
-MX6Q_PAD_DRAM_D33__MMDC_DRAM_D_33		773
-MX6Q_PAD_DRAM_D34__MMDC_DRAM_D_34		774
-MX6Q_PAD_DRAM_D35__MMDC_DRAM_D_35		775
-MX6Q_PAD_DRAM_D36__MMDC_DRAM_D_36		776
-MX6Q_PAD_DRAM_D37__MMDC_DRAM_D_37		777
-MX6Q_PAD_DRAM_D38__MMDC_DRAM_D_38		778
-MX6Q_PAD_DRAM_D39__MMDC_DRAM_D_39		779
-MX6Q_PAD_DRAM_DQM4__MMDC_DRAM_DQM_4		780
-MX6Q_PAD_DRAM_SDQS4__MMDC_DRAM_SDQS_4		781
-MX6Q_PAD_DRAM_D24__MMDC_DRAM_D_24		782
-MX6Q_PAD_DRAM_D25__MMDC_DRAM_D_25		783
-MX6Q_PAD_DRAM_D26__MMDC_DRAM_D_26		784
-MX6Q_PAD_DRAM_D27__MMDC_DRAM_D_27		785
-MX6Q_PAD_DRAM_D28__MMDC_DRAM_D_28		786
-MX6Q_PAD_DRAM_D29__MMDC_DRAM_D_29		787
-MX6Q_PAD_DRAM_SDQS3__MMDC_DRAM_SDQS_3		788
-MX6Q_PAD_DRAM_D30__MMDC_DRAM_D_30		789
-MX6Q_PAD_DRAM_D31__MMDC_DRAM_D_31		790
-MX6Q_PAD_DRAM_DQM3__MMDC_DRAM_DQM_3		791
-MX6Q_PAD_DRAM_D16__MMDC_DRAM_D_16		792
-MX6Q_PAD_DRAM_D17__MMDC_DRAM_D_17		793
-MX6Q_PAD_DRAM_D18__MMDC_DRAM_D_18		794
-MX6Q_PAD_DRAM_D19__MMDC_DRAM_D_19		795
-MX6Q_PAD_DRAM_D20__MMDC_DRAM_D_20		796
-MX6Q_PAD_DRAM_D21__MMDC_DRAM_D_21		797
-MX6Q_PAD_DRAM_D22__MMDC_DRAM_D_22		798
-MX6Q_PAD_DRAM_SDQS2__MMDC_DRAM_SDQS_2		799
-MX6Q_PAD_DRAM_D23__MMDC_DRAM_D_23		800
-MX6Q_PAD_DRAM_DQM2__MMDC_DRAM_DQM_2		801
-MX6Q_PAD_DRAM_A0__MMDC_DRAM_A_0			802
-MX6Q_PAD_DRAM_A1__MMDC_DRAM_A_1			803
-MX6Q_PAD_DRAM_A2__MMDC_DRAM_A_2			804
-MX6Q_PAD_DRAM_A3__MMDC_DRAM_A_3			805
-MX6Q_PAD_DRAM_A4__MMDC_DRAM_A_4			806
-MX6Q_PAD_DRAM_A5__MMDC_DRAM_A_5			807
-MX6Q_PAD_DRAM_A6__MMDC_DRAM_A_6			808
-MX6Q_PAD_DRAM_A7__MMDC_DRAM_A_7			809
-MX6Q_PAD_DRAM_A8__MMDC_DRAM_A_8			810
-MX6Q_PAD_DRAM_A9__MMDC_DRAM_A_9			811
-MX6Q_PAD_DRAM_A10__MMDC_DRAM_A_10		812
-MX6Q_PAD_DRAM_A11__MMDC_DRAM_A_11		813
-MX6Q_PAD_DRAM_A12__MMDC_DRAM_A_12		814
-MX6Q_PAD_DRAM_A13__MMDC_DRAM_A_13		815
-MX6Q_PAD_DRAM_A14__MMDC_DRAM_A_14		816
-MX6Q_PAD_DRAM_A15__MMDC_DRAM_A_15		817
-MX6Q_PAD_DRAM_CAS__MMDC_DRAM_CAS		818
-MX6Q_PAD_DRAM_CS0__MMDC_DRAM_CS_0		819
-MX6Q_PAD_DRAM_CS1__MMDC_DRAM_CS_1		820
-MX6Q_PAD_DRAM_RAS__MMDC_DRAM_RAS		821
-MX6Q_PAD_DRAM_RESET__MMDC_DRAM_RESET		822
-MX6Q_PAD_DRAM_SDBA0__MMDC_DRAM_SDBA_0		823
-MX6Q_PAD_DRAM_SDBA1__MMDC_DRAM_SDBA_1		824
-MX6Q_PAD_DRAM_SDCLK_0__MMDC_DRAM_SDCLK0		825
-MX6Q_PAD_DRAM_SDBA2__MMDC_DRAM_SDBA_2		826
-MX6Q_PAD_DRAM_SDCKE0__MMDC_DRAM_SDCKE_0		827
-MX6Q_PAD_DRAM_SDCLK_1__MMDC_DRAM_SDCLK1		828
-MX6Q_PAD_DRAM_SDCKE1__MMDC_DRAM_SDCKE_1		829
-MX6Q_PAD_DRAM_SDODT0__MMDC_DRAM_ODT_0		830
-MX6Q_PAD_DRAM_SDODT1__MMDC_DRAM_ODT_1		831
-MX6Q_PAD_DRAM_SDWE__MMDC_DRAM_SDWE		832
-MX6Q_PAD_DRAM_D0__MMDC_DRAM_D_0			833
-MX6Q_PAD_DRAM_D1__MMDC_DRAM_D_1			834
-MX6Q_PAD_DRAM_D2__MMDC_DRAM_D_2			835
-MX6Q_PAD_DRAM_D3__MMDC_DRAM_D_3			836
-MX6Q_PAD_DRAM_D4__MMDC_DRAM_D_4			837
-MX6Q_PAD_DRAM_D5__MMDC_DRAM_D_5			838
-MX6Q_PAD_DRAM_SDQS0__MMDC_DRAM_SDQS_0		839
-MX6Q_PAD_DRAM_D6__MMDC_DRAM_D_6			840
-MX6Q_PAD_DRAM_D7__MMDC_DRAM_D_7			841
-MX6Q_PAD_DRAM_DQM0__MMDC_DRAM_DQM_0		842
-MX6Q_PAD_DRAM_D8__MMDC_DRAM_D_8			843
-MX6Q_PAD_DRAM_D9__MMDC_DRAM_D_9			844
-MX6Q_PAD_DRAM_D10__MMDC_DRAM_D_10		845
-MX6Q_PAD_DRAM_D11__MMDC_DRAM_D_11		846
-MX6Q_PAD_DRAM_D12__MMDC_DRAM_D_12		847
-MX6Q_PAD_DRAM_D13__MMDC_DRAM_D_13		848
-MX6Q_PAD_DRAM_D14__MMDC_DRAM_D_14		849
-MX6Q_PAD_DRAM_SDQS1__MMDC_DRAM_SDQS_1		850
-MX6Q_PAD_DRAM_D15__MMDC_DRAM_D_15		851
-MX6Q_PAD_DRAM_DQM1__MMDC_DRAM_DQM_1		852
-MX6Q_PAD_DRAM_D48__MMDC_DRAM_D_48		853
-MX6Q_PAD_DRAM_D49__MMDC_DRAM_D_49		854
-MX6Q_PAD_DRAM_D50__MMDC_DRAM_D_50		855
-MX6Q_PAD_DRAM_D51__MMDC_DRAM_D_51		856
-MX6Q_PAD_DRAM_D52__MMDC_DRAM_D_52		857
-MX6Q_PAD_DRAM_D53__MMDC_DRAM_D_53		858
-MX6Q_PAD_DRAM_D54__MMDC_DRAM_D_54		859
-MX6Q_PAD_DRAM_D55__MMDC_DRAM_D_55		860
-MX6Q_PAD_DRAM_SDQS6__MMDC_DRAM_SDQS_6		861
-MX6Q_PAD_DRAM_DQM6__MMDC_DRAM_DQM_6		862
-MX6Q_PAD_DRAM_D56__MMDC_DRAM_D_56		863
-MX6Q_PAD_DRAM_SDQS7__MMDC_DRAM_SDQS_7		864
-MX6Q_PAD_DRAM_D57__MMDC_DRAM_D_57		865
-MX6Q_PAD_DRAM_D58__MMDC_DRAM_D_58		866
-MX6Q_PAD_DRAM_D59__MMDC_DRAM_D_59		867
-MX6Q_PAD_DRAM_D60__MMDC_DRAM_D_60		868
-MX6Q_PAD_DRAM_DQM7__MMDC_DRAM_DQM_7		869
-MX6Q_PAD_DRAM_D61__MMDC_DRAM_D_61		870
-MX6Q_PAD_DRAM_D62__MMDC_DRAM_D_62		871
-MX6Q_PAD_DRAM_D63__MMDC_DRAM_D_63		872
-MX6Q_PAD_KEY_COL0__ECSPI1_SCLK			873
-MX6Q_PAD_KEY_COL0__ENET_RDATA_3			874
-MX6Q_PAD_KEY_COL0__AUDMUX_AUD5_TXC		875
-MX6Q_PAD_KEY_COL0__KPP_COL_0			876
-MX6Q_PAD_KEY_COL0__UART4_TXD			877
-MX6Q_PAD_KEY_COL0__GPIO_4_6			878
-MX6Q_PAD_KEY_COL0__DCIC1_DCIC_OUT		879
-MX6Q_PAD_KEY_COL0__SRC_ANY_PU_RST		880
-MX6Q_PAD_KEY_ROW0__ECSPI1_MOSI			881
-MX6Q_PAD_KEY_ROW0__ENET_TDATA_3			882
-MX6Q_PAD_KEY_ROW0__AUDMUX_AUD5_TXD		883
-MX6Q_PAD_KEY_ROW0__KPP_ROW_0			884
-MX6Q_PAD_KEY_ROW0__UART4_RXD			885
-MX6Q_PAD_KEY_ROW0__GPIO_4_7			886
-MX6Q_PAD_KEY_ROW0__DCIC2_DCIC_OUT		887
-MX6Q_PAD_KEY_ROW0__PL301_PER1_HADR_0		888
-MX6Q_PAD_KEY_COL1__ECSPI1_MISO			889
-MX6Q_PAD_KEY_COL1__ENET_MDIO			890
-MX6Q_PAD_KEY_COL1__AUDMUX_AUD5_TXFS		891
-MX6Q_PAD_KEY_COL1__KPP_COL_1			892
-MX6Q_PAD_KEY_COL1__UART5_TXD			893
-MX6Q_PAD_KEY_COL1__GPIO_4_8			894
-MX6Q_PAD_KEY_COL1__USDHC1_VSELECT		895
-MX6Q_PAD_KEY_COL1__PL301MX_PER1_HADR_1		896
-MX6Q_PAD_KEY_ROW1__ECSPI1_SS0			897
-MX6Q_PAD_KEY_ROW1__ENET_COL			898
-MX6Q_PAD_KEY_ROW1__AUDMUX_AUD5_RXD		899
-MX6Q_PAD_KEY_ROW1__KPP_ROW_1			900
-MX6Q_PAD_KEY_ROW1__UART5_RXD			901
-MX6Q_PAD_KEY_ROW1__GPIO_4_9			902
-MX6Q_PAD_KEY_ROW1__USDHC2_VSELECT		903
-MX6Q_PAD_KEY_ROW1__PL301_PER1_HADDR_2		904
-MX6Q_PAD_KEY_COL2__ECSPI1_SS1			905
-MX6Q_PAD_KEY_COL2__ENET_RDATA_2			906
-MX6Q_PAD_KEY_COL2__CAN1_TXCAN			907
-MX6Q_PAD_KEY_COL2__KPP_COL_2			908
-MX6Q_PAD_KEY_COL2__ENET_MDC			909
-MX6Q_PAD_KEY_COL2__GPIO_4_10			910
-MX6Q_PAD_KEY_COL2__USBOH3_H1_PWRCTL_WKP		911
-MX6Q_PAD_KEY_COL2__PL301_PER1_HADDR_3		912
-MX6Q_PAD_KEY_ROW2__ECSPI1_SS2			913
-MX6Q_PAD_KEY_ROW2__ENET_TDATA_2			914
-MX6Q_PAD_KEY_ROW2__CAN1_RXCAN			915
-MX6Q_PAD_KEY_ROW2__KPP_ROW_2			916
-MX6Q_PAD_KEY_ROW2__USDHC2_VSELECT		917
-MX6Q_PAD_KEY_ROW2__GPIO_4_11			918
-MX6Q_PAD_KEY_ROW2__HDMI_TX_CEC_LINE		919
-MX6Q_PAD_KEY_ROW2__PL301_PER1_HADR_4		920
-MX6Q_PAD_KEY_COL3__ECSPI1_SS3			921
-MX6Q_PAD_KEY_COL3__ENET_CRS			922
-MX6Q_PAD_KEY_COL3__HDMI_TX_DDC_SCL		923
-MX6Q_PAD_KEY_COL3__KPP_COL_3			924
-MX6Q_PAD_KEY_COL3__I2C2_SCL			925
-MX6Q_PAD_KEY_COL3__GPIO_4_12			926
-MX6Q_PAD_KEY_COL3__SPDIF_IN1			927
-MX6Q_PAD_KEY_COL3__PL301_PER1_HADR_5		928
-MX6Q_PAD_KEY_ROW3__OSC32K_32K_OUT		929
-MX6Q_PAD_KEY_ROW3__ASRC_ASRC_EXT_CLK		930
-MX6Q_PAD_KEY_ROW3__HDMI_TX_DDC_SDA		931
-MX6Q_PAD_KEY_ROW3__KPP_ROW_3			932
-MX6Q_PAD_KEY_ROW3__I2C2_SDA			933
-MX6Q_PAD_KEY_ROW3__GPIO_4_13			934
-MX6Q_PAD_KEY_ROW3__USDHC1_VSELECT		935
-MX6Q_PAD_KEY_ROW3__PL301_PER1_HADR_6		936
-MX6Q_PAD_KEY_COL4__CAN2_TXCAN			937
-MX6Q_PAD_KEY_COL4__IPU1_SISG_4			938
-MX6Q_PAD_KEY_COL4__USBOH3_USBOTG_OC		939
-MX6Q_PAD_KEY_COL4__KPP_COL_4			940
-MX6Q_PAD_KEY_COL4__UART5_RTS			941
-MX6Q_PAD_KEY_COL4__GPIO_4_14			942
-MX6Q_PAD_KEY_COL4__MMDC_DEBUG_49		943
-MX6Q_PAD_KEY_COL4__PL301_PER1_HADDR_7		944
-MX6Q_PAD_KEY_ROW4__CAN2_RXCAN			945
-MX6Q_PAD_KEY_ROW4__IPU1_SISG_5			946
-MX6Q_PAD_KEY_ROW4__USBOH3_USBOTG_PWR		947
-MX6Q_PAD_KEY_ROW4__KPP_ROW_4			948
-MX6Q_PAD_KEY_ROW4__UART5_CTS			949
-MX6Q_PAD_KEY_ROW4__GPIO_4_15			950
-MX6Q_PAD_KEY_ROW4__MMDC_DEBUG_50		951
-MX6Q_PAD_KEY_ROW4__PL301_PER1_HADR_8		952
-MX6Q_PAD_GPIO_0__CCM_CLKO			953
-MX6Q_PAD_GPIO_0__KPP_COL_5			954
-MX6Q_PAD_GPIO_0__ASRC_ASRC_EXT_CLK		955
-MX6Q_PAD_GPIO_0__EPIT1_EPITO			956
-MX6Q_PAD_GPIO_0__GPIO_1_0			957
-MX6Q_PAD_GPIO_0__USBOH3_USBH1_PWR		958
-MX6Q_PAD_GPIO_0__SNVS_HP_WRAP_SNVS_VIO5		959
-MX6Q_PAD_GPIO_1__ESAI1_SCKR			960
-MX6Q_PAD_GPIO_1__WDOG2_WDOG_B			961
-MX6Q_PAD_GPIO_1__KPP_ROW_5			962
-MX6Q_PAD_GPIO_1__PWM2_PWMO			963
-MX6Q_PAD_GPIO_1__GPIO_1_1			964
-MX6Q_PAD_GPIO_1__USDHC1_CD			965
-MX6Q_PAD_GPIO_1__SRC_TESTER_ACK			966
-MX6Q_PAD_GPIO_9__ESAI1_FSR			967
-MX6Q_PAD_GPIO_9__WDOG1_WDOG_B			968
-MX6Q_PAD_GPIO_9__KPP_COL_6			969
-MX6Q_PAD_GPIO_9__CCM_REF_EN_B			970
-MX6Q_PAD_GPIO_9__PWM1_PWMO			971
-MX6Q_PAD_GPIO_9__GPIO_1_9			972
-MX6Q_PAD_GPIO_9__USDHC1_WP			973
-MX6Q_PAD_GPIO_9__SRC_EARLY_RST			974
-MX6Q_PAD_GPIO_3__ESAI1_HCKR			975
-MX6Q_PAD_GPIO_3__OBSERVE_MUX_INT_OUT0		976
-MX6Q_PAD_GPIO_3__I2C3_SCL			977
-MX6Q_PAD_GPIO_3__ANATOP_24M_OUT			978
-MX6Q_PAD_GPIO_3__CCM_CLKO2			979
-MX6Q_PAD_GPIO_3__GPIO_1_3			980
-MX6Q_PAD_GPIO_3__USBOH3_USBH1_OC		981
-MX6Q_PAD_GPIO_3__MLB_MLBCLK			982
-MX6Q_PAD_GPIO_6__ESAI1_SCKT			983
-MX6Q_PAD_GPIO_6__OBSERVE_MUX_INT_OUT1		984
-MX6Q_PAD_GPIO_6__I2C3_SDA			985
-MX6Q_PAD_GPIO_6__CCM_CCM_OUT_0			986
-MX6Q_PAD_GPIO_6__CSU_CSU_INT_DEB		987
-MX6Q_PAD_GPIO_6__GPIO_1_6			988
-MX6Q_PAD_GPIO_6__USDHC2_LCTL			989
-MX6Q_PAD_GPIO_6__MLB_MLBSIG			990
-MX6Q_PAD_GPIO_2__ESAI1_FST			991
-MX6Q_PAD_GPIO_2__OBSERVE_MUX_INT_OUT2		992
-MX6Q_PAD_GPIO_2__KPP_ROW_6			993
-MX6Q_PAD_GPIO_2__CCM_CCM_OUT_1			994
-MX6Q_PAD_GPIO_2__CSU_CSU_ALARM_AUT_0		995
-MX6Q_PAD_GPIO_2__GPIO_1_2			996
-MX6Q_PAD_GPIO_2__USDHC2_WP			997
-MX6Q_PAD_GPIO_2__MLB_MLBDAT			998
-MX6Q_PAD_GPIO_4__ESAI1_HCKT			999
-MX6Q_PAD_GPIO_4__OBSERVE_MUX_INT_OUT3		1000
-MX6Q_PAD_GPIO_4__KPP_COL_7			1001
-MX6Q_PAD_GPIO_4__CCM_CCM_OUT_2			1002
-MX6Q_PAD_GPIO_4__CSU_CSU_ALARM_AUT_1		1003
-MX6Q_PAD_GPIO_4__GPIO_1_4			1004
-MX6Q_PAD_GPIO_4__USDHC2_CD			1005
-MX6Q_PAD_GPIO_4__OCOTP_CRL_WRAR_FUSE_LA		1006
-MX6Q_PAD_GPIO_5__ESAI1_TX2_RX3			1007
-MX6Q_PAD_GPIO_5__OBSERVE_MUX_INT_OUT4		1008
-MX6Q_PAD_GPIO_5__KPP_ROW_7			1009
-MX6Q_PAD_GPIO_5__CCM_CLKO			1010
-MX6Q_PAD_GPIO_5__CSU_CSU_ALARM_AUT_2		1011
-MX6Q_PAD_GPIO_5__GPIO_1_5			1012
-MX6Q_PAD_GPIO_5__I2C3_SCL			1013
-MX6Q_PAD_GPIO_5__CHEETAH_EVENTI			1014
-MX6Q_PAD_GPIO_7__ESAI1_TX4_RX1			1015
-MX6Q_PAD_GPIO_7__ECSPI5_RDY			1016
-MX6Q_PAD_GPIO_7__EPIT1_EPITO			1017
-MX6Q_PAD_GPIO_7__CAN1_TXCAN			1018
-MX6Q_PAD_GPIO_7__UART2_TXD			1019
-MX6Q_PAD_GPIO_7__GPIO_1_7			1020
-MX6Q_PAD_GPIO_7__SPDIF_PLOCK			1021
-MX6Q_PAD_GPIO_7__USBOH3_OTGUSB_HST_MODE		1022
-MX6Q_PAD_GPIO_8__ESAI1_TX5_RX0			1023
-MX6Q_PAD_GPIO_8__ANATOP_ANATOP_32K_OUT		1024
-MX6Q_PAD_GPIO_8__EPIT2_EPITO			1025
-MX6Q_PAD_GPIO_8__CAN1_RXCAN			1026
-MX6Q_PAD_GPIO_8__UART2_RXD			1027
-MX6Q_PAD_GPIO_8__GPIO_1_8			1028
-MX6Q_PAD_GPIO_8__SPDIF_SRCLK			1029
-MX6Q_PAD_GPIO_8__USBOH3_OTG_PWRCTL_WAK		1030
-MX6Q_PAD_GPIO_16__ESAI1_TX3_RX2			1031
-MX6Q_PAD_GPIO_16__ENET_1588_EVENT2_IN		1032
-MX6Q_PAD_GPIO_16__ENET_ETHERNET_REF_OUT		1033
-MX6Q_PAD_GPIO_16__USDHC1_LCTL			1034
-MX6Q_PAD_GPIO_16__SPDIF_IN1			1035
-MX6Q_PAD_GPIO_16__GPIO_7_11			1036
-MX6Q_PAD_GPIO_16__I2C3_SDA			1037
-MX6Q_PAD_GPIO_16__SJC_DE_B			1038
-MX6Q_PAD_GPIO_17__ESAI1_TX0			1039
-MX6Q_PAD_GPIO_17__ENET_1588_EVENT3_IN		1040
-MX6Q_PAD_GPIO_17__CCM_PMIC_RDY			1041
-MX6Q_PAD_GPIO_17__SDMA_SDMA_EXT_EVENT_0		1042
-MX6Q_PAD_GPIO_17__SPDIF_OUT1			1043
-MX6Q_PAD_GPIO_17__GPIO_7_12			1044
-MX6Q_PAD_GPIO_17__SJC_JTAG_ACT			1045
-MX6Q_PAD_GPIO_18__ESAI1_TX1			1046
-MX6Q_PAD_GPIO_18__ENET_RX_CLK			1047
-MX6Q_PAD_GPIO_18__USDHC3_VSELECT		1048
-MX6Q_PAD_GPIO_18__SDMA_SDMA_EXT_EVENT_1		1049
-MX6Q_PAD_GPIO_18__ASRC_ASRC_EXT_CLK		1050
-MX6Q_PAD_GPIO_18__GPIO_7_13			1051
-MX6Q_PAD_GPIO_18__SNVS_HP_WRA_SNVS_VIO5		1052
-MX6Q_PAD_GPIO_18__SRC_SYSTEM_RST		1053
-MX6Q_PAD_GPIO_19__KPP_COL_5			1054
-MX6Q_PAD_GPIO_19__ENET_1588_EVENT0_OUT		1055
-MX6Q_PAD_GPIO_19__SPDIF_OUT1			1056
-MX6Q_PAD_GPIO_19__CCM_CLKO			1057
-MX6Q_PAD_GPIO_19__ECSPI1_RDY			1058
-MX6Q_PAD_GPIO_19__GPIO_4_5			1059
-MX6Q_PAD_GPIO_19__ENET_TX_ER			1060
-MX6Q_PAD_GPIO_19__SRC_INT_BOOT			1061
-MX6Q_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK		1062
-MX6Q_PAD_CSI0_PIXCLK__PCIE_CTRL_MUX_12		1063
-MX6Q_PAD_CSI0_PIXCLK__SDMA_DEBUG_PC_0		1064
-MX6Q_PAD_CSI0_PIXCLK__GPIO_5_18			1065
-MX6Q_PAD_CSI0_PIXCLK___MMDC_DEBUG_29		1066
-MX6Q_PAD_CSI0_PIXCLK__CHEETAH_EVENTO		1067
-MX6Q_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC		1068
-MX6Q_PAD_CSI0_MCLK__PCIE_CTRL_MUX_13		1069
-MX6Q_PAD_CSI0_MCLK__CCM_CLKO			1070
-MX6Q_PAD_CSI0_MCLK__SDMA_DEBUG_PC_1		1071
-MX6Q_PAD_CSI0_MCLK__GPIO_5_19			1072
-MX6Q_PAD_CSI0_MCLK__MMDC_MMDC_DEBUG_30		1073
-MX6Q_PAD_CSI0_MCLK__CHEETAH_TRCTL		1074
-MX6Q_PAD_CSI0_DATA_EN__IPU1_CSI0_DA_EN		1075
-MX6Q_PAD_CSI0_DATA_EN__WEIM_WEIM_D_0		1076
-MX6Q_PAD_CSI0_DATA_EN__PCIE_CTRL_MUX_14		1077
-MX6Q_PAD_CSI0_DATA_EN__SDMA_DEBUG_PC_2		1078
-MX6Q_PAD_CSI0_DATA_EN__GPIO_5_20		1079
-MX6Q_PAD_CSI0_DATA_EN__MMDC_DEBUG_31		1080
-MX6Q_PAD_CSI0_DATA_EN__CHEETAH_TRCLK		1081
-MX6Q_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC		1082
-MX6Q_PAD_CSI0_VSYNC__WEIM_WEIM_D_1		1083
-MX6Q_PAD_CSI0_VSYNC__PCIE_CTRL_MUX_15		1084
-MX6Q_PAD_CSI0_VSYNC__SDMA_DEBUG_PC_3		1085
-MX6Q_PAD_CSI0_VSYNC__GPIO_5_21			1086
-MX6Q_PAD_CSI0_VSYNC__MMDC_DEBUG_32		1087
-MX6Q_PAD_CSI0_VSYNC__CHEETAH_TRACE_0		1088
-MX6Q_PAD_CSI0_DAT4__IPU1_CSI0_D_4		1089
-MX6Q_PAD_CSI0_DAT4__WEIM_WEIM_D_2		1090
-MX6Q_PAD_CSI0_DAT4__ECSPI1_SCLK			1091
-MX6Q_PAD_CSI0_DAT4__KPP_COL_5			1092
-MX6Q_PAD_CSI0_DAT4__AUDMUX_AUD3_TXC		1093
-MX6Q_PAD_CSI0_DAT4__GPIO_5_22			1094
-MX6Q_PAD_CSI0_DAT4__MMDC_DEBUG_43		1095
-MX6Q_PAD_CSI0_DAT4__CHEETAH_TRACE_1		1096
-MX6Q_PAD_CSI0_DAT5__IPU1_CSI0_D_5		1097
-MX6Q_PAD_CSI0_DAT5__WEIM_WEIM_D_3		1098
-MX6Q_PAD_CSI0_DAT5__ECSPI1_MOSI			1099
-MX6Q_PAD_CSI0_DAT5__KPP_ROW_5			1100
-MX6Q_PAD_CSI0_DAT5__AUDMUX_AUD3_TXD		1101
-MX6Q_PAD_CSI0_DAT5__GPIO_5_23			1102
-MX6Q_PAD_CSI0_DAT5__MMDC_MMDC_DEBUG_44		1103
-MX6Q_PAD_CSI0_DAT5__CHEETAH_TRACE_2		1104
-MX6Q_PAD_CSI0_DAT6__IPU1_CSI0_D_6		1105
-MX6Q_PAD_CSI0_DAT6__WEIM_WEIM_D_4		1106
-MX6Q_PAD_CSI0_DAT6__ECSPI1_MISO			1107
-MX6Q_PAD_CSI0_DAT6__KPP_COL_6			1108
-MX6Q_PAD_CSI0_DAT6__AUDMUX_AUD3_TXFS		1109
-MX6Q_PAD_CSI0_DAT6__GPIO_5_24			1110
-MX6Q_PAD_CSI0_DAT6__MMDC_MMDC_DEBUG_45		1111
-MX6Q_PAD_CSI0_DAT6__CHEETAH_TRACE_3		1112
-MX6Q_PAD_CSI0_DAT7__IPU1_CSI0_D_7		1113
-MX6Q_PAD_CSI0_DAT7__WEIM_WEIM_D_5		1114
-MX6Q_PAD_CSI0_DAT7__ECSPI1_SS0			1115
-MX6Q_PAD_CSI0_DAT7__KPP_ROW_6			1116
-MX6Q_PAD_CSI0_DAT7__AUDMUX_AUD3_RXD		1117
-MX6Q_PAD_CSI0_DAT7__GPIO_5_25			1118
-MX6Q_PAD_CSI0_DAT7__MMDC_MMDC_DEBUG_46		1119
-MX6Q_PAD_CSI0_DAT7__CHEETAH_TRACE_4		1120
-MX6Q_PAD_CSI0_DAT8__IPU1_CSI0_D_8		1121
-MX6Q_PAD_CSI0_DAT8__WEIM_WEIM_D_6		1122
-MX6Q_PAD_CSI0_DAT8__ECSPI2_SCLK			1123
-MX6Q_PAD_CSI0_DAT8__KPP_COL_7			1124
-MX6Q_PAD_CSI0_DAT8__I2C1_SDA			1125
-MX6Q_PAD_CSI0_DAT8__GPIO_5_26			1126
-MX6Q_PAD_CSI0_DAT8__MMDC_MMDC_DEBUG_47		1127
-MX6Q_PAD_CSI0_DAT8__CHEETAH_TRACE_5		1128
-MX6Q_PAD_CSI0_DAT9__IPU1_CSI0_D_9		1129
-MX6Q_PAD_CSI0_DAT9__WEIM_WEIM_D_7		1130
-MX6Q_PAD_CSI0_DAT9__ECSPI2_MOSI			1131
-MX6Q_PAD_CSI0_DAT9__KPP_ROW_7			1132
-MX6Q_PAD_CSI0_DAT9__I2C1_SCL			1133
-MX6Q_PAD_CSI0_DAT9__GPIO_5_27			1134
-MX6Q_PAD_CSI0_DAT9__MMDC_MMDC_DEBUG_48		1135
-MX6Q_PAD_CSI0_DAT9__CHEETAH_TRACE_6		1136
-MX6Q_PAD_CSI0_DAT10__IPU1_CSI0_D_10		1137
-MX6Q_PAD_CSI0_DAT10__AUDMUX_AUD3_RXC		1138
-MX6Q_PAD_CSI0_DAT10__ECSPI2_MISO		1139
-MX6Q_PAD_CSI0_DAT10__UART1_TXD			1140
-MX6Q_PAD_CSI0_DAT10__SDMA_DEBUG_PC_4		1141
-MX6Q_PAD_CSI0_DAT10__GPIO_5_28			1142
-MX6Q_PAD_CSI0_DAT10__MMDC_MMDC_DEBUG_33		1143
-MX6Q_PAD_CSI0_DAT10__CHEETAH_TRACE_7		1144
-MX6Q_PAD_CSI0_DAT11__IPU1_CSI0_D_11		1145
-MX6Q_PAD_CSI0_DAT11__AUDMUX_AUD3_RXFS		1146
-MX6Q_PAD_CSI0_DAT11__ECSPI2_SS0			1147
-MX6Q_PAD_CSI0_DAT11__UART1_RXD			1148
-MX6Q_PAD_CSI0_DAT11__SDMA_DEBUG_PC_5		1149
-MX6Q_PAD_CSI0_DAT11__GPIO_5_29			1150
-MX6Q_PAD_CSI0_DAT11__MMDC_MMDC_DEBUG_34		1151
-MX6Q_PAD_CSI0_DAT11__CHEETAH_TRACE_8		1152
-MX6Q_PAD_CSI0_DAT12__IPU1_CSI0_D_12		1153
-MX6Q_PAD_CSI0_DAT12__WEIM_WEIM_D_8		1154
-MX6Q_PAD_CSI0_DAT12__PCIE_CTRL_MUX_16		1155
-MX6Q_PAD_CSI0_DAT12__UART4_TXD			1156
-MX6Q_PAD_CSI0_DAT12__SDMA_DEBUG_PC_6		1157
-MX6Q_PAD_CSI0_DAT12__GPIO_5_30			1158
-MX6Q_PAD_CSI0_DAT12__MMDC_MMDC_DEBUG_35		1159
-MX6Q_PAD_CSI0_DAT12__CHEETAH_TRACE_9		1160
-MX6Q_PAD_CSI0_DAT13__IPU1_CSI0_D_13		1161
-MX6Q_PAD_CSI0_DAT13__WEIM_WEIM_D_9		1162
-MX6Q_PAD_CSI0_DAT13__PCIE_CTRL_MUX_17		1163
-MX6Q_PAD_CSI0_DAT13__UART4_RXD			1164
-MX6Q_PAD_CSI0_DAT13__SDMA_DEBUG_PC_7		1165
-MX6Q_PAD_CSI0_DAT13__GPIO_5_31			1166
-MX6Q_PAD_CSI0_DAT13__MMDC_MMDC_DEBUG_36		1167
-MX6Q_PAD_CSI0_DAT13__CHEETAH_TRACE_10		1168
-MX6Q_PAD_CSI0_DAT14__IPU1_CSI0_D_14		1169
-MX6Q_PAD_CSI0_DAT14__WEIM_WEIM_D_10		1170
-MX6Q_PAD_CSI0_DAT14__PCIE_CTRL_MUX_18		1171
-MX6Q_PAD_CSI0_DAT14__UART5_TXD			1172
-MX6Q_PAD_CSI0_DAT14__SDMA_DEBUG_PC_8		1173
-MX6Q_PAD_CSI0_DAT14__GPIO_6_0			1174
-MX6Q_PAD_CSI0_DAT14__MMDC_MMDC_DEBUG_37		1175
-MX6Q_PAD_CSI0_DAT14__CHEETAH_TRACE_11		1176
-MX6Q_PAD_CSI0_DAT15__IPU1_CSI0_D_15		1177
-MX6Q_PAD_CSI0_DAT15__WEIM_WEIM_D_11		1178
-MX6Q_PAD_CSI0_DAT15__PCIE_CTRL_MUX_19		1179
-MX6Q_PAD_CSI0_DAT15__UART5_RXD			1180
-MX6Q_PAD_CSI0_DAT15__SDMA_DEBUG_PC_9		1181
-MX6Q_PAD_CSI0_DAT15__GPIO_6_1			1182
-MX6Q_PAD_CSI0_DAT15__MMDC_MMDC_DEBUG_38		1183
-MX6Q_PAD_CSI0_DAT15__CHEETAH_TRACE_12		1184
-MX6Q_PAD_CSI0_DAT16__IPU1_CSI0_D_16		1185
-MX6Q_PAD_CSI0_DAT16__WEIM_WEIM_D_12		1186
-MX6Q_PAD_CSI0_DAT16__PCIE_CTRL_MUX_20		1187
-MX6Q_PAD_CSI0_DAT16__UART4_RTS			1188
-MX6Q_PAD_CSI0_DAT16__SDMA_DEBUG_PC_10		1189
-MX6Q_PAD_CSI0_DAT16__GPIO_6_2			1190
-MX6Q_PAD_CSI0_DAT16__MMDC_MMDC_DEBUG_39		1191
-MX6Q_PAD_CSI0_DAT16__CHEETAH_TRACE_13		1192
-MX6Q_PAD_CSI0_DAT17__IPU1_CSI0_D_17		1193
-MX6Q_PAD_CSI0_DAT17__WEIM_WEIM_D_13		1194
-MX6Q_PAD_CSI0_DAT17__PCIE_CTRL_MUX_21		1195
-MX6Q_PAD_CSI0_DAT17__UART4_CTS			1196
-MX6Q_PAD_CSI0_DAT17__SDMA_DEBUG_PC_11		1197
-MX6Q_PAD_CSI0_DAT17__GPIO_6_3			1198
-MX6Q_PAD_CSI0_DAT17__MMDC_MMDC_DEBUG_40		1199
-MX6Q_PAD_CSI0_DAT17__CHEETAH_TRACE_14		1200
-MX6Q_PAD_CSI0_DAT18__IPU1_CSI0_D_18		1201
-MX6Q_PAD_CSI0_DAT18__WEIM_WEIM_D_14		1202
-MX6Q_PAD_CSI0_DAT18__PCIE_CTRL_MUX_22		1203
-MX6Q_PAD_CSI0_DAT18__UART5_RTS			1204
-MX6Q_PAD_CSI0_DAT18__SDMA_DEBUG_PC_12		1205
-MX6Q_PAD_CSI0_DAT18__GPIO_6_4			1206
-MX6Q_PAD_CSI0_DAT18__MMDC_MMDC_DEBUG_41		1207
-MX6Q_PAD_CSI0_DAT18__CHEETAH_TRACE_15		1208
-MX6Q_PAD_CSI0_DAT19__IPU1_CSI0_D_19		1209
-MX6Q_PAD_CSI0_DAT19__WEIM_WEIM_D_15		1210
-MX6Q_PAD_CSI0_DAT19__PCIE_CTRL_MUX_23		1211
-MX6Q_PAD_CSI0_DAT19__UART5_CTS			1212
-MX6Q_PAD_CSI0_DAT19__SDMA_DEBUG_PC_13		1213
-MX6Q_PAD_CSI0_DAT19__GPIO_6_5			1214
-MX6Q_PAD_CSI0_DAT19__MMDC_MMDC_DEBUG_42		1215
-MX6Q_PAD_CSI0_DAT19__ANATOP_TESTO_9		1216
-MX6Q_PAD_JTAG_TMS__SJC_TMS			1217
-MX6Q_PAD_JTAG_MOD__SJC_MOD			1218
-MX6Q_PAD_JTAG_TRSTB__SJC_TRSTB			1219
-MX6Q_PAD_JTAG_TDI__SJC_TDI			1220
-MX6Q_PAD_JTAG_TCK__SJC_TCK			1221
-MX6Q_PAD_JTAG_TDO__SJC_TDO			1222
-MX6Q_PAD_LVDS1_TX3_P__LDB_LVDS1_TX3		1223
-MX6Q_PAD_LVDS1_TX2_P__LDB_LVDS1_TX2		1224
-MX6Q_PAD_LVDS1_CLK_P__LDB_LVDS1_CLK		1225
-MX6Q_PAD_LVDS1_TX1_P__LDB_LVDS1_TX1		1226
-MX6Q_PAD_LVDS1_TX0_P__LDB_LVDS1_TX0		1227
-MX6Q_PAD_LVDS0_TX3_P__LDB_LVDS0_TX3		1228
-MX6Q_PAD_LVDS0_CLK_P__LDB_LVDS0_CLK		1229
-MX6Q_PAD_LVDS0_TX2_P__LDB_LVDS0_TX2		1230
-MX6Q_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1		1231
-MX6Q_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0		1232
-MX6Q_PAD_TAMPER__SNVS_LP_WRAP_SNVS_TD1		1233
-MX6Q_PAD_PMIC_ON_REQ__SNVS_LPWRAP_WKALM		1234
-MX6Q_PAD_PMIC_STBY_REQ__CCM_PMIC_STBYRQ		1235
-MX6Q_PAD_POR_B__SRC_POR_B			1236
-MX6Q_PAD_BOOT_MODE1__SRC_BOOT_MODE_1		1237
-MX6Q_PAD_RESET_IN_B__SRC_RESET_B		1238
-MX6Q_PAD_BOOT_MODE0__SRC_BOOT_MODE_0		1239
-MX6Q_PAD_TEST_MODE__TCU_TEST_MODE		1240
-MX6Q_PAD_SD3_DAT7__USDHC3_DAT7			1241
-MX6Q_PAD_SD3_DAT7__UART1_TXD			1242
-MX6Q_PAD_SD3_DAT7__PCIE_CTRL_MUX_24		1243
-MX6Q_PAD_SD3_DAT7__USBOH3_UH3_DFD_OUT_0		1244
-MX6Q_PAD_SD3_DAT7__USBOH3_UH2_DFD_OUT_0		1245
-MX6Q_PAD_SD3_DAT7__GPIO_6_17			1246
-MX6Q_PAD_SD3_DAT7__MIPI_CORE_DPHY_IN_12		1247
-MX6Q_PAD_SD3_DAT7__USBPHY2_CLK20DIV		1248
-MX6Q_PAD_SD3_DAT6__USDHC3_DAT6			1249
-MX6Q_PAD_SD3_DAT6__UART1_RXD			1250
-MX6Q_PAD_SD3_DAT6__PCIE_CTRL_MUX_25		1251
-MX6Q_PAD_SD3_DAT6__USBOH3_UH3_DFD_OUT_1		1252
-MX6Q_PAD_SD3_DAT6__USBOH3_UH2_DFD_OUT_1		1253
-MX6Q_PAD_SD3_DAT6__GPIO_6_18			1254
-MX6Q_PAD_SD3_DAT6__MIPI_CORE_DPHY_IN_13		1255
-MX6Q_PAD_SD3_DAT6__ANATOP_TESTO_10		1256
-MX6Q_PAD_SD3_DAT5__USDHC3_DAT5			1257
-MX6Q_PAD_SD3_DAT5__UART2_TXD			1258
-MX6Q_PAD_SD3_DAT5__PCIE_CTRL_MUX_26		1259
-MX6Q_PAD_SD3_DAT5__USBOH3_UH3_DFD_OUT_2		1260
-MX6Q_PAD_SD3_DAT5__USBOH3_UH2_DFD_OUT_2		1261
-MX6Q_PAD_SD3_DAT5__GPIO_7_0			1262
-MX6Q_PAD_SD3_DAT5__MIPI_CORE_DPHY_IN_14		1263
-MX6Q_PAD_SD3_DAT5__ANATOP_TESTO_11		1264
-MX6Q_PAD_SD3_DAT4__USDHC3_DAT4			1265
-MX6Q_PAD_SD3_DAT4__UART2_RXD			1266
-MX6Q_PAD_SD3_DAT4__PCIE_CTRL_MUX_27		1267
-MX6Q_PAD_SD3_DAT4__USBOH3_UH3_DFD_OUT_3		1268
-MX6Q_PAD_SD3_DAT4__USBOH3_UH2_DFD_OUT_3		1269
-MX6Q_PAD_SD3_DAT4__GPIO_7_1			1270
-MX6Q_PAD_SD3_DAT4__MIPI_CORE_DPHY_IN_15		1271
-MX6Q_PAD_SD3_DAT4__ANATOP_TESTO_12		1272
-MX6Q_PAD_SD3_CMD__USDHC3_CMD			1273
-MX6Q_PAD_SD3_CMD__UART2_CTS			1274
-MX6Q_PAD_SD3_CMD__CAN1_TXCAN			1275
-MX6Q_PAD_SD3_CMD__USBOH3_UH3_DFD_OUT_4		1276
-MX6Q_PAD_SD3_CMD__USBOH3_UH2_DFD_OUT_4		1277
-MX6Q_PAD_SD3_CMD__GPIO_7_2			1278
-MX6Q_PAD_SD3_CMD__MIPI_CORE_DPHY_IN_16		1279
-MX6Q_PAD_SD3_CMD__ANATOP_TESTO_13		1280
-MX6Q_PAD_SD3_CLK__USDHC3_CLK			1281
-MX6Q_PAD_SD3_CLK__UART2_RTS			1282
-MX6Q_PAD_SD3_CLK__CAN1_RXCAN			1283
-MX6Q_PAD_SD3_CLK__USBOH3_UH3_DFD_OUT_5		1284
-MX6Q_PAD_SD3_CLK__USBOH3_UH2_DFD_OUT_5		1285
-MX6Q_PAD_SD3_CLK__GPIO_7_3			1286
-MX6Q_PAD_SD3_CLK__MIPI_CORE_DPHY_IN_17		1287
-MX6Q_PAD_SD3_CLK__ANATOP_TESTO_14		1288
-MX6Q_PAD_SD3_DAT0__USDHC3_DAT0			1289
-MX6Q_PAD_SD3_DAT0__UART1_CTS			1290
-MX6Q_PAD_SD3_DAT0__CAN2_TXCAN			1291
-MX6Q_PAD_SD3_DAT0__USBOH3_UH3_DFD_OUT_6		1292
-MX6Q_PAD_SD3_DAT0__USBOH3_UH2_DFD_OUT_6		1293
-MX6Q_PAD_SD3_DAT0__GPIO_7_4			1294
-MX6Q_PAD_SD3_DAT0__MIPI_CORE_DPHY_IN_18		1295
-MX6Q_PAD_SD3_DAT0__ANATOP_TESTO_15		1296
-MX6Q_PAD_SD3_DAT1__USDHC3_DAT1			1297
-MX6Q_PAD_SD3_DAT1__UART1_RTS			1298
-MX6Q_PAD_SD3_DAT1__CAN2_RXCAN			1299
-MX6Q_PAD_SD3_DAT1__USBOH3_UH3_DFD_OUT_7		1300
-MX6Q_PAD_SD3_DAT1__USBOH3_UH2_DFD_OUT_7		1301
-MX6Q_PAD_SD3_DAT1__GPIO_7_5			1302
-MX6Q_PAD_SD3_DAT1__MIPI_CORE_DPHY_IN_19		1303
-MX6Q_PAD_SD3_DAT1__ANATOP_TESTI_0		1304
-MX6Q_PAD_SD3_DAT2__USDHC3_DAT2			1305
-MX6Q_PAD_SD3_DAT2__PCIE_CTRL_MUX_28		1306
-MX6Q_PAD_SD3_DAT2__USBOH3_UH3_DFD_OUT_8		1307
-MX6Q_PAD_SD3_DAT2__USBOH3_UH2_DFD_OUT_8		1308
-MX6Q_PAD_SD3_DAT2__GPIO_7_6			1309
-MX6Q_PAD_SD3_DAT2__MIPI_CORE_DPHY_IN_20		1310
-MX6Q_PAD_SD3_DAT2__ANATOP_TESTI_1		1311
-MX6Q_PAD_SD3_DAT3__USDHC3_DAT3			1312
-MX6Q_PAD_SD3_DAT3__UART3_CTS			1313
-MX6Q_PAD_SD3_DAT3__PCIE_CTRL_MUX_29		1314
-MX6Q_PAD_SD3_DAT3__USBOH3_UH3_DFD_OUT_9		1315
-MX6Q_PAD_SD3_DAT3__USBOH3_UH2_DFD_OUT_9		1316
-MX6Q_PAD_SD3_DAT3__GPIO_7_7			1317
-MX6Q_PAD_SD3_DAT3__MIPI_CORE_DPHY_IN_21		1318
-MX6Q_PAD_SD3_DAT3__ANATOP_TESTI_2		1319
-MX6Q_PAD_SD3_RST__USDHC3_RST			1320
-MX6Q_PAD_SD3_RST__UART3_RTS			1321
-MX6Q_PAD_SD3_RST__PCIE_CTRL_MUX_30		1322
-MX6Q_PAD_SD3_RST__USBOH3_UH3_DFD_OUT_10		1323
-MX6Q_PAD_SD3_RST__USBOH3_UH2_DFD_OUT_10		1324
-MX6Q_PAD_SD3_RST__GPIO_7_8			1325
-MX6Q_PAD_SD3_RST__MIPI_CORE_DPHY_IN_22		1326
-MX6Q_PAD_SD3_RST__ANATOP_ANATOP_TESTI_3		1327
-MX6Q_PAD_NANDF_CLE__RAWNAND_CLE			1328
-MX6Q_PAD_NANDF_CLE__IPU2_SISG_4			1329
-MX6Q_PAD_NANDF_CLE__PCIE_CTRL_MUX_31		1330
-MX6Q_PAD_NANDF_CLE__USBOH3_UH3_DFD_OT11		1331
-MX6Q_PAD_NANDF_CLE__USBOH3_UH2_DFD_OT11		1332
-MX6Q_PAD_NANDF_CLE__GPIO_6_7			1333
-MX6Q_PAD_NANDF_CLE__MIPI_CORE_DPHY_IN23		1334
-MX6Q_PAD_NANDF_CLE__TPSMP_HTRANS_0		1335
-MX6Q_PAD_NANDF_ALE__RAWNAND_ALE			1336
-MX6Q_PAD_NANDF_ALE__USDHC4_RST			1337
-MX6Q_PAD_NANDF_ALE__PCIE_CTRL_MUX_0		1338
-MX6Q_PAD_NANDF_ALE__USBOH3_UH3_DFD_OT12		1339
-MX6Q_PAD_NANDF_ALE__USBOH3_UH2_DFD_OT12		1340
-MX6Q_PAD_NANDF_ALE__GPIO_6_8			1341
-MX6Q_PAD_NANDF_ALE__MIPI_CR_DPHY_IN_24		1342
-MX6Q_PAD_NANDF_ALE__TPSMP_HTRANS_1		1343
-MX6Q_PAD_NANDF_WP_B__RAWNAND_RESETN		1344
-MX6Q_PAD_NANDF_WP_B__IPU2_SISG_5		1345
-MX6Q_PAD_NANDF_WP_B__PCIE_CTRL__MUX_1		1346
-MX6Q_PAD_NANDF_WP_B__USBOH3_UH3_DFDOT13		1347
-MX6Q_PAD_NANDF_WP_B__USBOH3_UH2_DFDOT13		1348
-MX6Q_PAD_NANDF_WP_B__GPIO_6_9			1349
-MX6Q_PAD_NANDF_WP_B__MIPI_CR_DPHY_OUT32		1350
-MX6Q_PAD_NANDF_WP_B__PL301_PER1_HSIZE_0		1351
-MX6Q_PAD_NANDF_RB0__RAWNAND_READY0		1352
-MX6Q_PAD_NANDF_RB0__IPU2_DI0_PIN1		1353
-MX6Q_PAD_NANDF_RB0__PCIE_CTRL_MUX_2		1354
-MX6Q_PAD_NANDF_RB0__USBOH3_UH3_DFD_OT14		1355
-MX6Q_PAD_NANDF_RB0__USBOH3_UH2_DFD_OT14		1356
-MX6Q_PAD_NANDF_RB0__GPIO_6_10			1357
-MX6Q_PAD_NANDF_RB0__MIPI_CR_DPHY_OUT_33		1358
-MX6Q_PAD_NANDF_RB0__PL301_PER1_HSIZE_1		1359
-MX6Q_PAD_NANDF_CS0__RAWNAND_CE0N		1360
-MX6Q_PAD_NANDF_CS0__USBOH3_UH3_DFD_OT15		1361
-MX6Q_PAD_NANDF_CS0__USBOH3_UH2_DFD_OT15		1362
-MX6Q_PAD_NANDF_CS0__GPIO_6_11			1363
-MX6Q_PAD_NANDF_CS0__PL301_PER1_HSIZE_2		1364
-MX6Q_PAD_NANDF_CS1__RAWNAND_CE1N		1365
-MX6Q_PAD_NANDF_CS1__USDHC4_VSELECT		1366
-MX6Q_PAD_NANDF_CS1__USDHC3_VSELECT		1367
-MX6Q_PAD_NANDF_CS1__PCIE_CTRL_MUX_3		1368
-MX6Q_PAD_NANDF_CS1__GPIO_6_14			1369
-MX6Q_PAD_NANDF_CS1__PL301_PER1_HRDYOUT		1370
-MX6Q_PAD_NANDF_CS2__RAWNAND_CE2N		1371
-MX6Q_PAD_NANDF_CS2__IPU1_SISG_0			1372
-MX6Q_PAD_NANDF_CS2__ESAI1_TX0			1373
-MX6Q_PAD_NANDF_CS2__WEIM_WEIM_CRE		1374
-MX6Q_PAD_NANDF_CS2__CCM_CLKO2			1375
-MX6Q_PAD_NANDF_CS2__GPIO_6_15			1376
-MX6Q_PAD_NANDF_CS2__IPU2_SISG_0			1377
-MX6Q_PAD_NANDF_CS3__RAWNAND_CE3N		1378
-MX6Q_PAD_NANDF_CS3__IPU1_SISG_1			1379
-MX6Q_PAD_NANDF_CS3__ESAI1_TX1			1380
-MX6Q_PAD_NANDF_CS3__WEIM_WEIM_A_26		1381
-MX6Q_PAD_NANDF_CS3__PCIE_CTRL_MUX_4		1382
-MX6Q_PAD_NANDF_CS3__GPIO_6_16			1383
-MX6Q_PAD_NANDF_CS3__IPU2_SISG_1			1384
-MX6Q_PAD_NANDF_CS3__TPSMP_CLK			1385
-MX6Q_PAD_SD4_CMD__USDHC4_CMD			1386
-MX6Q_PAD_SD4_CMD__RAWNAND_RDN			1387
-MX6Q_PAD_SD4_CMD__UART3_TXD			1388
-MX6Q_PAD_SD4_CMD__PCIE_CTRL_MUX_5		1389
-MX6Q_PAD_SD4_CMD__GPIO_7_9			1390
-MX6Q_PAD_SD4_CMD__TPSMP_HDATA_DIR		1391
-MX6Q_PAD_SD4_CLK__USDHC4_CLK			1392
-MX6Q_PAD_SD4_CLK__RAWNAND_WRN			1393
-MX6Q_PAD_SD4_CLK__UART3_RXD			1394
-MX6Q_PAD_SD4_CLK__PCIE_CTRL_MUX_6		1395
-MX6Q_PAD_SD4_CLK__GPIO_7_10			1396
-MX6Q_PAD_NANDF_D0__RAWNAND_D0			1397
-MX6Q_PAD_NANDF_D0__USDHC1_DAT4			1398
-MX6Q_PAD_NANDF_D0__GPU3D_GPU_DBG_OUT_0		1399
-MX6Q_PAD_NANDF_D0__USBOH3_UH2_DFD_OUT16		1400
-MX6Q_PAD_NANDF_D0__USBOH3_UH3_DFD_OUT16		1401
-MX6Q_PAD_NANDF_D0__GPIO_2_0			1402
-MX6Q_PAD_NANDF_D0__IPU1_IPU_DIAG_BUS_0		1403
-MX6Q_PAD_NANDF_D0__IPU2_IPU_DIAG_BUS_0		1404
-MX6Q_PAD_NANDF_D1__RAWNAND_D1			1405
-MX6Q_PAD_NANDF_D1__USDHC1_DAT5			1406
-MX6Q_PAD_NANDF_D1__GPU3D_GPU_DEBUG_OUT1		1407
-MX6Q_PAD_NANDF_D1__USBOH3_UH2_DFD_OUT17		1408
-MX6Q_PAD_NANDF_D1__USBOH3_UH3_DFD_OUT17		1409
-MX6Q_PAD_NANDF_D1__GPIO_2_1			1410
-MX6Q_PAD_NANDF_D1__IPU1_IPU_DIAG_BUS_1		1411
-MX6Q_PAD_NANDF_D1__IPU2_IPU_DIAG_BUS_1		1412
-MX6Q_PAD_NANDF_D2__RAWNAND_D2			1413
-MX6Q_PAD_NANDF_D2__USDHC1_DAT6			1414
-MX6Q_PAD_NANDF_D2__GPU3D_GPU_DBG_OUT_2		1415
-MX6Q_PAD_NANDF_D2__USBOH3_UH2_DFD_OUT18		1416
-MX6Q_PAD_NANDF_D2__USBOH3_UH3_DFD_OUT18		1417
-MX6Q_PAD_NANDF_D2__GPIO_2_2			1418
-MX6Q_PAD_NANDF_D2__IPU1_IPU_DIAG_BUS_2		1419
-MX6Q_PAD_NANDF_D2__IPU2_IPU_DIAG_BUS_2		1420
-MX6Q_PAD_NANDF_D3__RAWNAND_D3			1421
-MX6Q_PAD_NANDF_D3__USDHC1_DAT7			1422
-MX6Q_PAD_NANDF_D3__GPU3D_GPU_DBG_OUT_3		1423
-MX6Q_PAD_NANDF_D3__USBOH3_UH2_DFD_OUT19		1424
-MX6Q_PAD_NANDF_D3__USBOH3_UH3_DFD_OUT19		1425
-MX6Q_PAD_NANDF_D3__GPIO_2_3			1426
-MX6Q_PAD_NANDF_D3__IPU1_IPU_DIAG_BUS_3		1427
-MX6Q_PAD_NANDF_D3__IPU2_IPU_DIAG_BUS_3		1428
-MX6Q_PAD_NANDF_D4__RAWNAND_D4			1429
-MX6Q_PAD_NANDF_D4__USDHC2_DAT4			1430
-MX6Q_PAD_NANDF_D4__GPU3D_GPU_DBG_OUT_4		1431
-MX6Q_PAD_NANDF_D4__USBOH3_UH2_DFD_OUT20		1432
-MX6Q_PAD_NANDF_D4__USBOH3_UH3_DFD_OUT20		1433
-MX6Q_PAD_NANDF_D4__GPIO_2_4			1434
-MX6Q_PAD_NANDF_D4__IPU1_IPU_DIAG_BUS_4		1435
-MX6Q_PAD_NANDF_D4__IPU2_IPU_DIAG_BUS_4		1436
-MX6Q_PAD_NANDF_D5__RAWNAND_D5			1437
-MX6Q_PAD_NANDF_D5__USDHC2_DAT5			1438
-MX6Q_PAD_NANDF_D5__GPU3D_GPU_DBG_OUT_5		1439
-MX6Q_PAD_NANDF_D5__USBOH3_UH2_DFD_OUT21		1440
-MX6Q_PAD_NANDF_D5__USBOH3_UH3_DFD_OUT21		1441
-MX6Q_PAD_NANDF_D5__GPIO_2_5			1442
-MX6Q_PAD_NANDF_D5__IPU1_IPU_DIAG_BUS_5		1443
-MX6Q_PAD_NANDF_D5__IPU2_IPU_DIAG_BUS_5		1444
-MX6Q_PAD_NANDF_D6__RAWNAND_D6			1445
-MX6Q_PAD_NANDF_D6__USDHC2_DAT6			1446
-MX6Q_PAD_NANDF_D6__GPU3D_GPU_DBG_OUT_6		1447
-MX6Q_PAD_NANDF_D6__USBOH3_UH2_DFD_OUT22		1448
-MX6Q_PAD_NANDF_D6__USBOH3_UH3_DFD_OUT22		1449
-MX6Q_PAD_NANDF_D6__GPIO_2_6			1450
-MX6Q_PAD_NANDF_D6__IPU1_IPU_DIAG_BUS_6		1451
-MX6Q_PAD_NANDF_D6__IPU2_IPU_DIAG_BUS_6		1452
-MX6Q_PAD_NANDF_D7__RAWNAND_D7			1453
-MX6Q_PAD_NANDF_D7__USDHC2_DAT7			1454
-MX6Q_PAD_NANDF_D7__GPU3D_GPU_DBG_OUT_7		1455
-MX6Q_PAD_NANDF_D7__USBOH3_UH2_DFD_OUT23		1456
-MX6Q_PAD_NANDF_D7__USBOH3_UH3_DFD_OUT23		1457
-MX6Q_PAD_NANDF_D7__GPIO_2_7			1458
-MX6Q_PAD_NANDF_D7__IPU1_IPU_DIAG_BUS_7		1459
-MX6Q_PAD_NANDF_D7__IPU2_IPU_DIAG_BUS_7		1460
-MX6Q_PAD_SD4_DAT0__RAWNAND_D8			1461
-MX6Q_PAD_SD4_DAT0__USDHC4_DAT0			1462
-MX6Q_PAD_SD4_DAT0__RAWNAND_DQS			1463
-MX6Q_PAD_SD4_DAT0__USBOH3_UH2_DFD_OUT24		1464
-MX6Q_PAD_SD4_DAT0__USBOH3_UH3_DFD_OUT24		1465
-MX6Q_PAD_SD4_DAT0__GPIO_2_8			1466
-MX6Q_PAD_SD4_DAT0__IPU1_IPU_DIAG_BUS_8		1467
-MX6Q_PAD_SD4_DAT0__IPU2_IPU_DIAG_BUS_8		1468
-MX6Q_PAD_SD4_DAT1__RAWNAND_D9			1469
-MX6Q_PAD_SD4_DAT1__USDHC4_DAT1			1470
-MX6Q_PAD_SD4_DAT1__PWM3_PWMO			1471
-MX6Q_PAD_SD4_DAT1__USBOH3_UH2_DFD_OUT25		1472
-MX6Q_PAD_SD4_DAT1__USBOH3_UH3_DFD_OUT25		1473
-MX6Q_PAD_SD4_DAT1__GPIO_2_9			1474
-MX6Q_PAD_SD4_DAT1__IPU1_IPU_DIAG_BUS_9		1475
-MX6Q_PAD_SD4_DAT1__IPU2_IPU_DIAG_BUS_9		1476
-MX6Q_PAD_SD4_DAT2__RAWNAND_D10			1477
-MX6Q_PAD_SD4_DAT2__USDHC4_DAT2			1478
-MX6Q_PAD_SD4_DAT2__PWM4_PWMO			1479
-MX6Q_PAD_SD4_DAT2__USBOH3_UH2_DFD_OUT26		1480
-MX6Q_PAD_SD4_DAT2__USBOH3_UH3_DFD_OUT26		1481
-MX6Q_PAD_SD4_DAT2__GPIO_2_10			1482
-MX6Q_PAD_SD4_DAT2__IPU1_IPU_DIAG_BUS_10		1483
-MX6Q_PAD_SD4_DAT2__IPU2_IPU_DIAG_BUS_10		1484
-MX6Q_PAD_SD4_DAT3__RAWNAND_D11			1485
-MX6Q_PAD_SD4_DAT3__USDHC4_DAT3			1486
-MX6Q_PAD_SD4_DAT3__USBOH3_UH2_DFD_OUT27		1487
-MX6Q_PAD_SD4_DAT3__USBOH3_UH3_DFD_OUT27		1488
-MX6Q_PAD_SD4_DAT3__GPIO_2_11			1489
-MX6Q_PAD_SD4_DAT3__IPU1_IPU_DIAG_BUS_11		1490
-MX6Q_PAD_SD4_DAT3__IPU2_IPU_DIAG_BUS_11		1491
-MX6Q_PAD_SD4_DAT4__RAWNAND_D12			1492
-MX6Q_PAD_SD4_DAT4__USDHC4_DAT4			1493
-MX6Q_PAD_SD4_DAT4__UART2_RXD			1494
-MX6Q_PAD_SD4_DAT4__USBOH3_UH2_DFD_OUT28		1495
-MX6Q_PAD_SD4_DAT4__USBOH3_UH3_DFD_OUT28		1496
-MX6Q_PAD_SD4_DAT4__GPIO_2_12			1497
-MX6Q_PAD_SD4_DAT4__IPU1_IPU_DIAG_BUS_12		1498
-MX6Q_PAD_SD4_DAT4__IPU2_IPU_DIAG_BUS_12		1499
-MX6Q_PAD_SD4_DAT5__RAWNAND_D13			1500
-MX6Q_PAD_SD4_DAT5__USDHC4_DAT5			1501
-MX6Q_PAD_SD4_DAT5__UART2_RTS			1502
-MX6Q_PAD_SD4_DAT5__USBOH3_UH2_DFD_OUT29		1503
-MX6Q_PAD_SD4_DAT5__USBOH3_UH3_DFD_OUT29		1504
-MX6Q_PAD_SD4_DAT5__GPIO_2_13			1505
-MX6Q_PAD_SD4_DAT5__IPU1_IPU_DIAG_BUS_13		1506
-MX6Q_PAD_SD4_DAT5__IPU2_IPU_DIAG_BUS_13		1507
-MX6Q_PAD_SD4_DAT6__RAWNAND_D14			1508
-MX6Q_PAD_SD4_DAT6__USDHC4_DAT6			1509
-MX6Q_PAD_SD4_DAT6__UART2_CTS			1510
-MX6Q_PAD_SD4_DAT6__USBOH3_UH2_DFD_OUT30		1511
-MX6Q_PAD_SD4_DAT6__USBOH3_UH3_DFD_OUT30		1512
-MX6Q_PAD_SD4_DAT6__GPIO_2_14			1513
-MX6Q_PAD_SD4_DAT6__IPU1_IPU_DIAG_BUS_14		1514
-MX6Q_PAD_SD4_DAT6__IPU2_IPU_DIAG_BUS_14		1515
-MX6Q_PAD_SD4_DAT7__RAWNAND_D15			1516
-MX6Q_PAD_SD4_DAT7__USDHC4_DAT7			1517
-MX6Q_PAD_SD4_DAT7__UART2_TXD			1518
-MX6Q_PAD_SD4_DAT7__USBOH3_UH2_DFD_OUT31		1519
-MX6Q_PAD_SD4_DAT7__USBOH3_UH3_DFD_OUT31		1520
-MX6Q_PAD_SD4_DAT7__GPIO_2_15			1521
-MX6Q_PAD_SD4_DAT7__IPU1_IPU_DIAG_BUS_15		1522
-MX6Q_PAD_SD4_DAT7__IPU2_IPU_DIAG_BUS_15		1523
-MX6Q_PAD_SD1_DAT1__USDHC1_DAT1			1524
-MX6Q_PAD_SD1_DAT1__ECSPI5_SS0			1525
-MX6Q_PAD_SD1_DAT1__PWM3_PWMO			1526
-MX6Q_PAD_SD1_DAT1__GPT_CAPIN2			1527
-MX6Q_PAD_SD1_DAT1__PCIE_CTRL_MUX_7		1528
-MX6Q_PAD_SD1_DAT1__GPIO_1_17			1529
-MX6Q_PAD_SD1_DAT1__HDMI_TX_OPHYDTB_0		1530
-MX6Q_PAD_SD1_DAT1__ANATOP_TESTO_8		1531
-MX6Q_PAD_SD1_DAT0__USDHC1_DAT0			1532
-MX6Q_PAD_SD1_DAT0__ECSPI5_MISO			1533
-MX6Q_PAD_SD1_DAT0__CAAM_WRAP_RNG_OSCOBS		1534
-MX6Q_PAD_SD1_DAT0__GPT_CAPIN1			1535
-MX6Q_PAD_SD1_DAT0__PCIE_CTRL_MUX_8		1536
-MX6Q_PAD_SD1_DAT0__GPIO_1_16			1537
-MX6Q_PAD_SD1_DAT0__HDMI_TX_OPHYDTB_1		1538
-MX6Q_PAD_SD1_DAT0__ANATOP_TESTO_7		1539
-MX6Q_PAD_SD1_DAT3__USDHC1_DAT3			1540
-MX6Q_PAD_SD1_DAT3__ECSPI5_SS2			1541
-MX6Q_PAD_SD1_DAT3__GPT_CMPOUT3			1542
-MX6Q_PAD_SD1_DAT3__PWM1_PWMO			1543
-MX6Q_PAD_SD1_DAT3__WDOG2_WDOG_B			1544
-MX6Q_PAD_SD1_DAT3__GPIO_1_21			1545
-MX6Q_PAD_SD1_DAT3__WDOG2_WDOG_RST_B_DEB		1546
-MX6Q_PAD_SD1_DAT3__ANATOP_TESTO_6		1547
-MX6Q_PAD_SD1_CMD__USDHC1_CMD			1548
-MX6Q_PAD_SD1_CMD__ECSPI5_MOSI			1549
-MX6Q_PAD_SD1_CMD__PWM4_PWMO			1550
-MX6Q_PAD_SD1_CMD__GPT_CMPOUT1			1551
-MX6Q_PAD_SD1_CMD__GPIO_1_18			1552
-MX6Q_PAD_SD1_CMD__ANATOP_TESTO_5		1553
-MX6Q_PAD_SD1_DAT2__USDHC1_DAT2			1554
-MX6Q_PAD_SD1_DAT2__ECSPI5_SS1			1555
-MX6Q_PAD_SD1_DAT2__GPT_CMPOUT2			1556
-MX6Q_PAD_SD1_DAT2__PWM2_PWMO			1557
-MX6Q_PAD_SD1_DAT2__WDOG1_WDOG_B			1558
-MX6Q_PAD_SD1_DAT2__GPIO_1_19			1559
-MX6Q_PAD_SD1_DAT2__WDOG1_WDOG_RST_B_DEB		1560
-MX6Q_PAD_SD1_DAT2__ANATOP_TESTO_4		1561
-MX6Q_PAD_SD1_CLK__USDHC1_CLK			1562
-MX6Q_PAD_SD1_CLK__ECSPI5_SCLK			1563
-MX6Q_PAD_SD1_CLK__OSC32K_32K_OUT		1564
-MX6Q_PAD_SD1_CLK__GPT_CLKIN			1565
-MX6Q_PAD_SD1_CLK__GPIO_1_20			1566
-MX6Q_PAD_SD1_CLK__PHY_DTB_0			1567
-MX6Q_PAD_SD1_CLK__SATA_PHY_DTB_0		1568
-MX6Q_PAD_SD2_CLK__USDHC2_CLK			1569
-MX6Q_PAD_SD2_CLK__ECSPI5_SCLK			1570
-MX6Q_PAD_SD2_CLK__KPP_COL_5			1571
-MX6Q_PAD_SD2_CLK__AUDMUX_AUD4_RXFS		1572
-MX6Q_PAD_SD2_CLK__PCIE_CTRL_MUX_9		1573
-MX6Q_PAD_SD2_CLK__GPIO_1_10			1574
-MX6Q_PAD_SD2_CLK__PHY_DTB_1			1575
-MX6Q_PAD_SD2_CLK__SATA_PHY_DTB_1		1576
-MX6Q_PAD_SD2_CMD__USDHC2_CMD			1577
-MX6Q_PAD_SD2_CMD__ECSPI5_MOSI			1578
-MX6Q_PAD_SD2_CMD__KPP_ROW_5			1579
-MX6Q_PAD_SD2_CMD__AUDMUX_AUD4_RXC		1580
-MX6Q_PAD_SD2_CMD__PCIE_CTRL_MUX_10		1581
-MX6Q_PAD_SD2_CMD__GPIO_1_11			1582
-MX6Q_PAD_SD2_DAT3__USDHC2_DAT3			1583
-MX6Q_PAD_SD2_DAT3__ECSPI5_SS3			1584
-MX6Q_PAD_SD2_DAT3__KPP_COL_6			1585
-MX6Q_PAD_SD2_DAT3__AUDMUX_AUD4_TXC		1586
-MX6Q_PAD_SD2_DAT3__PCIE_CTRL_MUX_11		1587
-MX6Q_PAD_SD2_DAT3__GPIO_1_12			1588
-MX6Q_PAD_SD2_DAT3__SJC_DONE			1589
-MX6Q_PAD_SD2_DAT3__ANATOP_TESTO_3		1590
-MX6Q_PAD_ENET_RX_ER__ANATOP_USBOTG_ID		1591
-MX6Q_PAD_GPIO_1__ANATOP_USBOTG_ID		1592
+Refer to imx6q-pinfunc.h in device tree source folder for all available
+imx6q PIN_FUNC_ID.
diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,imx6sl-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/fsl,imx6sl-pinctrl.txt
new file mode 100644
index 0000000..e5f6d1f
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/fsl,imx6sl-pinctrl.txt
@@ -0,0 +1,39 @@
+* Freescale IMX6 SoloLite IOMUX Controller
+
+Please refer to fsl,imx-pinctrl.txt in this directory for common binding part
+and usage.
+
+Required properties:
+- compatible: "fsl,imx6sl-iomuxc"
+- fsl,pins: two integers array, represents a group of pins mux and config
+  setting. The format is fsl,pins = <PIN_FUNC_ID CONFIG>, PIN_FUNC_ID is a
+  pin working on a specific function, CONFIG is the pad setting value like
+  pull-up for this pin. Please refer to imx6sl datasheet for the valid pad
+  config settings.
+
+CONFIG bits definition:
+PAD_CTL_LVE                     (1 << 22)
+PAD_CTL_HYS                     (1 << 16)
+PAD_CTL_PUS_100K_DOWN           (0 << 14)
+PAD_CTL_PUS_47K_UP              (1 << 14)
+PAD_CTL_PUS_100K_UP             (2 << 14)
+PAD_CTL_PUS_22K_UP              (3 << 14)
+PAD_CTL_PUE                     (1 << 13)
+PAD_CTL_PKE                     (1 << 12)
+PAD_CTL_ODE                     (1 << 11)
+PAD_CTL_SPEED_LOW               (1 << 6)
+PAD_CTL_SPEED_MED               (2 << 6)
+PAD_CTL_SPEED_HIGH              (3 << 6)
+PAD_CTL_DSE_DISABLE             (0 << 3)
+PAD_CTL_DSE_240ohm              (1 << 3)
+PAD_CTL_DSE_120ohm              (2 << 3)
+PAD_CTL_DSE_80ohm               (3 << 3)
+PAD_CTL_DSE_60ohm               (4 << 3)
+PAD_CTL_DSE_48ohm               (5 << 3)
+PAD_CTL_DSE_40ohm               (6 << 3)
+PAD_CTL_DSE_34ohm               (7 << 3)
+PAD_CTL_SRE_FAST                (1 << 0)
+PAD_CTL_SRE_SLOW                (0 << 0)
+
+Refer to imx6sl-pinfunc.h in device tree source folder for all available
+imx6sl PIN_FUNC_ID.
diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,mxs-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/fsl,mxs-pinctrl.txt
index f7e8e8f..3077370 100644
--- a/Documentation/devicetree/bindings/pinctrl/fsl,mxs-pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/fsl,mxs-pinctrl.txt
@@ -70,6 +70,10 @@ Optional subnode-properties:
     0: Disable the internal pull-up
     1: Enable the internal pull-up
 
+Note that when enabling the pull-up, the internal pad keeper gets disabled.
+Also, some pins doesn't have a pull up, in that case, setting the fsl,pull-up
+will only disable the internal pad keeper.
+
 Examples:
 
 pinctrl@80018000 {
diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt
index 2c81e45..fa1746b 100644
--- a/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt
+++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt
@@ -1,7 +1,9 @@
 One-register-per-pin type device tree based pinctrl driver
 
 Required properties:
-- compatible : "pinctrl-single"
+- compatible : "pinctrl-single" or "pinconf-single".
+  "pinctrl-single" means that pinconf isn't supported.
+  "pinconf-single" means that generic pinconf is supported.
 
 - reg : offset and length of the register set for the mux registers
 
@@ -14,9 +16,61 @@ Optional properties:
 - pinctrl-single,function-off : function off mode for disabled state if
   available and same for all registers; if not specified, disabling of
   pin functions is ignored
+
 - pinctrl-single,bit-per-mux : boolean to indicate that one register controls
   more than one pin
 
+- pinctrl-single,drive-strength : array of value that are used to configure
+  drive strength in the pinmux register. They're value of drive strength
+  current and drive strength mask.
+
+		/* drive strength current, mask */
+		pinctrl-single,power-source = <0x30 0xf0>;
+
+- pinctrl-single,bias-pullup : array of value that are used to configure the
+  input bias pullup in the pinmux register.
+
+		/* input, enabled pullup bits, disabled pullup bits, mask */
+		pinctrl-single,bias-pullup = <0 1 0 1>;
+
+- pinctrl-single,bias-pulldown : array of value that are used to configure the
+  input bias pulldown in the pinmux register.
+
+		/* input, enabled pulldown bits, disabled pulldown bits, mask */
+		pinctrl-single,bias-pulldown = <2 2 0 2>;
+
+  * Two bits to control input bias pullup and pulldown: User should use
+    pinctrl-single,bias-pullup & pinctrl-single,bias-pulldown. One bit means
+    pullup, and the other one bit means pulldown.
+  * Three bits to control input bias enable, pullup and pulldown. User should
+    use pinctrl-single,bias-pullup & pinctrl-single,bias-pulldown. Input bias
+    enable bit should be included in pullup or pulldown bits.
+  * Although driver could set PIN_CONFIG_BIAS_DISABLE, there's no property as
+    pinctrl-single,bias-disable. Because pinctrl single driver could implement
+    it by calling pulldown, pullup disabled.
+
+- pinctrl-single,input-schmitt : array of value that are used to configure
+  input schmitt in the pinmux register. In some silicons, there're two input
+  schmitt value (rising-edge & falling-edge) in the pinmux register.
+
+		/* input schmitt value, mask */
+		pinctrl-single,input-schmitt = <0x30 0x70>;
+
+- pinctrl-single,input-schmitt-enable : array of value that are used to
+  configure input schmitt enable or disable in the pinmux register.
+
+		/* input, enable bits, disable bits, mask */
+		pinctrl-single,input-schmitt-enable = <0x30 0x40 0 0x70>;
+
+- pinctrl-single,gpio-range : list of value that are used to configure a GPIO
+  range. They're value of subnode phandle, pin base in pinctrl device, pin
+  number in this range, GPIO function value of this GPIO range.
+  The number of parameters is depend on #pinctrl-single,gpio-range-cells
+  property.
+
+		/* pin base, nr pins & gpio function */
+		pinctrl-single,gpio-range = <&range 0 3 0 &range 3 9 1>;
+
 This driver assumes that there is only one register for each pin (unless the
 pinctrl-single,bit-per-mux is set), and uses the common pinctrl bindings as
 specified in the pinctrl-bindings.txt document in this directory.
@@ -42,6 +96,20 @@ Where 0xdc is the offset from the pinctrl register base address for the
 device pinctrl register, 0x18 is the desired value, and 0xff is the sub mask to
 be used when applying this change to the register.
 
+
+Optional sub-node: In case some pins could be configured as GPIO in the pinmux
+register, those pins could be defined as a GPIO range. This sub-node is required
+by pinctrl-single,gpio-range property.
+
+Required properties in sub-node:
+- #pinctrl-single,gpio-range-cells : the number of parameters after phandle in
+  pinctrl-single,gpio-range property.
+
+	range: gpio-range {
+		#pinctrl-single,gpio-range-cells = <3>;
+	};
+
+
 Example:
 
 /* SoC common file */
@@ -76,6 +144,29 @@ control_devconf0: pinmux@48002274 {
 	pinctrl-single,function-mask = <0x5F>;
 };
 
+/* third controller instance for pins in gpio domain */
+pmx_gpio: pinmux@d401e000 {
+	compatible = "pinconf-single";
+	reg = <0xd401e000 0x0330>;
+	#address-cells = <1>;
+	#size-cells = <1>;
+	ranges;
+
+	pinctrl-single,register-width = <32>;
+	pinctrl-single,function-mask = <7>;
+
+	/* sparse GPIO range could be supported */
+	pinctrl-single,gpio-range = <&range 0 3 0 &range 3 9 1
+				&range 12 1 0 &range 13 29 1
+				&range 43 1 0 &range 44 49 1
+				&range 94 1 1 &range 96 2 1>;
+
+	range: gpio-range {
+		#pinctrl-single,gpio-range-cells = <3>;
+	};
+};
+
+
 /* board specific .dts file */
 
 &pmx_core {
@@ -96,6 +187,15 @@ control_devconf0: pinmux@48002274 {
 		>;
 	};
 
+	uart0_pins: pinmux_uart0_pins {
+		pinctrl-single,pins = <
+			0x208 0		/* UART0_RXD (IOCFG138) */
+			0x20c 0		/* UART0_TXD (IOCFG139) */
+		>;
+		pinctrl-single,bias-pulldown = <0 2 2>;
+		pinctrl-single,bias-pullup = <0 1 1>;
+	};
+
 	/* map uart2 pins */
 	uart2_pins: pinmux_uart2_pins {
 		pinctrl-single,pins = <
@@ -122,6 +222,11 @@ control_devconf0: pinmux@48002274 {
 
 };
 
+&uart1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart0_pins>;
+};
+
 &uart2 {
        pinctrl-names = "default";
        pinctrl-0 = <&uart2_pins>;
diff --git a/Documentation/devicetree/bindings/power_supply/tps65090.txt b/Documentation/devicetree/bindings/power_supply/tps65090.txt
new file mode 100644
index 0000000..8e5e0d3
--- /dev/null
+++ b/Documentation/devicetree/bindings/power_supply/tps65090.txt
@@ -0,0 +1,17 @@
+TPS65090 Frontend PMU with Switchmode Charger
+
+Required Properties:
+-compatible: "ti,tps65090-charger"
+
+Optional Properties:
+-ti,enable-low-current-chrg: Enables charging when a low current is detected
+ while the default logic is to stop charging.
+
+This node is a subnode of the tps65090 PMIC.
+
+Example:
+
+	tps65090-charger {
+		compatible = "ti,tps65090-charger";
+		ti,enable-low-current-chrg;
+	};
diff --git a/Documentation/devicetree/bindings/powerpc/fsl/cpus.txt b/Documentation/devicetree/bindings/powerpc/fsl/cpus.txt
new file mode 100644
index 0000000..922c30a
--- /dev/null
+++ b/Documentation/devicetree/bindings/powerpc/fsl/cpus.txt
@@ -0,0 +1,22 @@
+===================================================================
+Power Architecture CPU Binding
+Copyright 2013 Freescale Semiconductor Inc.
+
+Power Architecture CPUs in Freescale SOCs are represented in device trees as
+per the definition in ePAPR.
+
+In addition to the ePAPR definitions, the properties defined below may be
+present on CPU nodes.
+
+PROPERTIES
+
+   - fsl,eref-*
+        Usage: optional
+        Value type: <empty>
+        Definition: The EREF (EREF: A Programmer.s Reference Manual for
+	Freescale Power Architecture) defines the architecture for Freescale
+	Power CPUs.  The EREF defines some architecture categories not defined
+	by the Power ISA.  For these EREF-specific categories, the existence of
+	a property named fsl,eref-[CAT], where [CAT] is the abbreviated category
+	name with all uppercase letters converted to lowercase, indicates that
+	the category is supported by the implementation.
diff --git a/Documentation/devicetree/bindings/reset/fsl,imx-src.txt b/Documentation/devicetree/bindings/reset/fsl,imx-src.txt
new file mode 100644
index 0000000..1330177
--- /dev/null
+++ b/Documentation/devicetree/bindings/reset/fsl,imx-src.txt
@@ -0,0 +1,49 @@
+Freescale i.MX System Reset Controller
+======================================
+
+Please also refer to reset.txt in this directory for common reset
+controller binding usage.
+
+Required properties:
+- compatible: Should be "fsl,<chip>-src"
+- reg: should be register base and length as documented in the
+  datasheet
+- interrupts: Should contain SRC interrupt and CPU WDOG interrupt,
+  in this order.
+- #reset-cells: 1, see below
+
+example:
+
+src: src@020d8000 {
+        compatible = "fsl,imx6q-src";
+        reg = <0x020d8000 0x4000>;
+        interrupts = <0 91 0x04 0 96 0x04>;
+        #reset-cells = <1>;
+};
+
+Specifying reset lines connected to IP modules
+==============================================
+
+The system reset controller can be used to reset the GPU, VPU,
+IPU, and OpenVG IP modules on i.MX5 and i.MX6 ICs. Those device
+nodes should specify the reset line on the SRC in their resets
+property, containing a phandle to the SRC device node and a
+RESET_INDEX specifying which module to reset, as described in
+reset.txt
+
+example:
+
+        ipu1: ipu@02400000 {
+                resets = <&src 2>;
+        };
+        ipu2: ipu@02800000 {
+                resets = <&src 4>;
+        };
+
+The following RESET_INDEX values are valid for i.MX5:
+GPU_RESET     0
+VPU_RESET     1
+IPU1_RESET    2
+OPEN_VG_RESET 3
+The following additional RESET_INDEX value is valid for i.MX6:
+IPU2_RESET    4
diff --git a/Documentation/devicetree/bindings/reset/gpio-reset.txt b/Documentation/devicetree/bindings/reset/gpio-reset.txt
new file mode 100644
index 0000000..1f203eb
--- /dev/null
+++ b/Documentation/devicetree/bindings/reset/gpio-reset.txt
@@ -0,0 +1,37 @@
+GPIO reset controller
+=====================
+
+A GPIO reset controller controls a number of GPIOs that are connected
+to reset pins of peripheral ICs.
+
+Please also refer to reset.txt in this directory for common reset
+controller binding usage.
+
+Required properties:
+- compatible: Should be "gpio-reset"
+- reset-gpios: List of gpios used as reset lines. The gpio specifier for this
+               property depends on the gpio controller that provides the gpio.
+- #reset-cells: 1, see below
+
+Optional properties:
+- reset-delays: List of delays in microseconds. The corresponding gpio reset
+                line should be asserted for this duration to reset.
+- initially-in-reset: List of integers. Zero if the initial state should be
+                      a deasserted reset line, nonzero if the line should be
+                      kept in reset.
+
+example:
+
+gpio_reset: gpio-reset {
+	compatible = "gpio-reset";
+	reset-gpios = <&gpio5 0 1>; /* active-low */
+	reset-delays = <10000>; /* 10 ms */
+	initially-in-reset: <1>;
+	#reset-cells = <1>;
+};
+
+/* Device with nRESET pin connected to GPIO5_0 */
+sii902x@39 {
+	/* ... */
+	resets = <&gpio_reset 0>; /* active-low GPIO5_0, 10 ms reset delay */
+};
diff --git a/Documentation/devicetree/bindings/reset/reset.txt b/Documentation/devicetree/bindings/reset/reset.txt
new file mode 100644
index 0000000..31db6ff
--- /dev/null
+++ b/Documentation/devicetree/bindings/reset/reset.txt
@@ -0,0 +1,75 @@
+= Reset Signal Device Tree Bindings =
+
+This binding is intended to represent the hardware reset signals present
+internally in most IC (SoC, FPGA, ...) designs. Reset signals for whole
+standalone chips are most likely better represented as GPIOs, although there
+are likely to be exceptions to this rule.
+
+Hardware blocks typically receive a reset signal. This signal is generated by
+a reset provider (e.g. power management or clock module) and received by a
+reset consumer (the module being reset, or a module managing when a sub-
+ordinate module is reset). This binding exists to represent the provider and
+consumer, and provide a way to couple the two together.
+
+A reset signal is represented by the phandle of the provider, plus a reset
+specifier - a list of DT cells that represents the reset signal within the
+provider. The length (number of cells) and semantics of the reset specifier
+are dictated by the binding of the reset provider, although common schemes
+are described below.
+
+A word on where to place reset signal consumers in device tree: It is possible
+in hardware for a reset signal to affect multiple logically separate HW blocks
+at once. In this case, it would be unwise to represent this reset signal in
+the DT node of each affected HW block, since if activated, an unrelated block
+may be reset. Instead, reset signals should be represented in the DT node
+where it makes most sense to control it; this may be a bus node if all
+children of the bus are affected by the reset signal, or an individual HW
+block node for dedicated reset signals. The intent of this binding is to give
+appropriate software access to the reset signals in order to manage the HW,
+rather than to slavishly enumerate the reset signal that affects each HW
+block.
+
+= Reset providers =
+
+Required properties:
+#reset-cells:	Number of cells in a reset specifier; Typically 0 for nodes
+		with a single reset output and 1 for nodes with multiple
+		reset outputs.
+
+For example:
+
+	rst: reset-controller {
+		#reset-cells = <1>;
+	};
+
+= Reset consumers =
+
+Required properties:
+resets:		List of phandle and reset specifier pairs, one pair
+		for each reset signal that affects the device, or that the
+		device manages. Note: if the reset provider specifies '0' for
+		#reset-cells, then only the phandle portion of the pair will
+		appear.
+
+Optional properties:
+reset-names:	List of reset signal name strings sorted in the same order as
+		the resets property. Consumers drivers will use reset-names to
+		match reset signal names with reset specifiers.
+
+For example:
+
+	device {
+		resets = <&rst 20>;
+		reset-names = "reset";
+	};
+
+This represents a device with a single reset signal named "reset".
+
+	bus {
+		resets = <&rst 10> <&rst 11> <&rst 12> <&rst 11>;
+		reset-names = "i2s1", "i2s2", "dma", "mixer";
+	};
+
+This represents a bus that controls the reset signal of each of four sub-
+ordinate devices. Consider for example a bus that fails to operate unless no
+child device has reset asserted.
diff --git a/Documentation/devicetree/bindings/rng/brcm,bcm2835.txt b/Documentation/devicetree/bindings/rng/brcm,bcm2835.txt
new file mode 100644
index 0000000..07ccdaa
--- /dev/null
+++ b/Documentation/devicetree/bindings/rng/brcm,bcm2835.txt
@@ -0,0 +1,13 @@
+BCM2835 Random number generator
+
+Required properties:
+
+- compatible : should be "brcm,bcm2835-rng"
+- reg : Specifies base physical address and size of the registers.
+
+Example:
+
+rng {
+        compatible = "brcm,bcm2835-rng";
+        reg = <0x7e104000 0x10>;
+};
diff --git a/Documentation/devicetree/bindings/serio/snps-arc_ps2.txt b/Documentation/devicetree/bindings/serio/snps-arc_ps2.txt
new file mode 100644
index 0000000..38c2f21
--- /dev/null
+++ b/Documentation/devicetree/bindings/serio/snps-arc_ps2.txt
@@ -0,0 +1,16 @@
+* ARC PS/2 driver: PS/2 block used in some ARC FPGA's & nSIM OSCI model
+
+Required properties:
+- compatible		: "snps,arc_ps2"
+- reg			: offset and length (always 0x14) of registers
+- interrupts		: interrupt
+- interrupt-names	: name of interrupt, must be "arc_ps2_irq"
+
+Example:
+
+serio@c9000400 {
+	compatible = "snps,arc_ps2";
+	reg = <0xc9000400 0x14>;
+	interrupts = <13>;
+	interrupt-names = "arc_ps2_irq";
+}
diff --git a/Documentation/devicetree/bindings/sound/ak5386.txt b/Documentation/devicetree/bindings/sound/ak5386.txt
new file mode 100644
index 0000000..dc3914f
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/ak5386.txt
@@ -0,0 +1,19 @@
+AK5386 Single-ended 24-Bit 192kHz delta-sigma ADC
+
+This device has no control interface.
+
+Required properties:
+
+  - compatible : "asahi-kasei,ak5386"
+
+Optional properties:
+
+  - reset-gpio : a GPIO spec for the reset/power down pin.
+		 If specified, it will be deasserted at probe time.
+
+Example:
+
+spdif: ak5386@0 {
+	compatible = "asahi-kasei,ak5386";
+	reset-gpio = <&gpio0 23>;
+};
diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-alc5632.txt b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-alc5632.txt
index b77a97c..05ffecb 100644
--- a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-alc5632.txt
+++ b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-alc5632.txt
@@ -2,6 +2,11 @@ NVIDIA Tegra audio complex
 
 Required properties:
 - compatible : "nvidia,tegra-audio-alc5632"
+- clocks : Must contain an entry for each entry in clock-names.
+- clock-names : Must include the following entries:
+  "pll_a" (The Tegra clock of that name),
+  "pll_a_out0" (The Tegra clock of that name),
+  "mclk" (The Tegra cdev1/extern1 clock, which feeds the CODEC's mclk)
 - nvidia,model : The user-visible name of this sound complex.
 - nvidia,audio-routing : A list of the connections between audio components.
   Each entry is a pair of strings, the first being the connection's sink,
@@ -56,4 +61,7 @@ sound {
 
 	nvidia,i2s-controller = <&tegra_i2s1>;
 	nvidia,audio-codec = <&alc5632>;
+
+	clocks = <&tegra_car 112>, <&tegra_car 113>, <&tegra_car 93>;
+	clock-names = "pll_a", "pll_a_out0", "mclk";
 };
diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-trimslice.txt b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-trimslice.txt
index 04b14cf..ef1fe73 100644
--- a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-trimslice.txt
+++ b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-trimslice.txt
@@ -2,6 +2,11 @@ NVIDIA Tegra audio complex for TrimSlice
 
 Required properties:
 - compatible : "nvidia,tegra-audio-trimslice"
+- clocks : Must contain an entry for each entry in clock-names.
+- clock-names : Must include the following entries:
+  "pll_a" (The Tegra clock of that name),
+  "pll_a_out0" (The Tegra clock of that name),
+  "mclk" (The Tegra cdev1/extern1 clock, which feeds the CODEC's mclk)
 - nvidia,i2s-controller : The phandle of the Tegra I2S1 controller
 - nvidia,audio-codec : The phandle of the WM8903 audio codec
 
@@ -11,4 +16,6 @@ sound {
 	compatible = "nvidia,tegra-audio-trimslice";
 	nvidia,i2s-controller = <&tegra_i2s1>;
 	nvidia,audio-codec = <&codec>;
+	clocks = <&tegra_car 112>, <&tegra_car 113>, <&tegra_car 93>;
+	clock-names = "pll_a", "pll_a_out0", "mclk";
 };
diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm8753.txt b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm8753.txt
index c4dd39c..d145106 100644
--- a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm8753.txt
+++ b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm8753.txt
@@ -2,6 +2,11 @@ NVIDIA Tegra audio complex
 
 Required properties:
 - compatible : "nvidia,tegra-audio-wm8753"
+- clocks : Must contain an entry for each entry in clock-names.
+- clock-names : Must include the following entries:
+  "pll_a" (The Tegra clock of that name),
+  "pll_a_out0" (The Tegra clock of that name),
+  "mclk" (The Tegra cdev1/extern1 clock, which feeds the CODEC's mclk)
 - nvidia,model : The user-visible name of this sound complex.
 - nvidia,audio-routing : A list of the connections between audio components.
   Each entry is a pair of strings, the first being the connection's sink,
@@ -50,5 +55,8 @@ sound {
 
 	nvidia,i2s-controller = <&i2s1>;
 	nvidia,audio-codec = <&wm8753>;
+
+	clocks = <&tegra_car 112>, <&tegra_car 113>, <&tegra_car 93>;
+	clock-names = "pll_a", "pll_a_out0", "mclk";
 };
 
diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm8903.txt b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm8903.txt
index d5b0da8..3bf722d 100644
--- a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm8903.txt
+++ b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm8903.txt
@@ -2,6 +2,11 @@ NVIDIA Tegra audio complex
 
 Required properties:
 - compatible : "nvidia,tegra-audio-wm8903"
+- clocks : Must contain an entry for each entry in clock-names.
+- clock-names : Must include the following entries:
+  "pll_a" (The Tegra clock of that name),
+  "pll_a_out0" (The Tegra clock of that name),
+  "mclk" (The Tegra cdev1/extern1 clock, which feeds the CODEC's mclk)
 - nvidia,model : The user-visible name of this sound complex.
 - nvidia,audio-routing : A list of the connections between audio components.
   Each entry is a pair of strings, the first being the connection's sink,
@@ -67,5 +72,8 @@ sound {
 	nvidia,hp-det-gpios = <&gpio 178 0>; /* gpio PW2 */
 	nvidia,int-mic-en-gpios = <&gpio 184 0>; /*gpio PX0 */
 	nvidia,ext-mic-en-gpios = <&gpio 185 0>; /* gpio PX1 */
+
+	clocks = <&tegra_car 112>, <&tegra_car 113>, <&tegra_car 93>;
+	clock-names = "pll_a", "pll_a_out0", "mclk";
 };
 
diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm9712.txt b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm9712.txt
index be35d34..ad589b1 100644
--- a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm9712.txt
+++ b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm9712.txt
@@ -2,6 +2,11 @@ NVIDIA Tegra audio complex
 
 Required properties:
 - compatible : "nvidia,tegra-audio-wm9712"
+- clocks : Must contain an entry for each entry in clock-names.
+- clock-names : Must include the following entries:
+  "pll_a" (The Tegra clock of that name),
+  "pll_a_out0" (The Tegra clock of that name),
+  "mclk" (The Tegra cdev1/extern1 clock, which feeds the CODEC's mclk)
 - nvidia,model : The user-visible name of this sound complex.
 - nvidia,audio-routing : A list of the connections between audio components.
   Each entry is a pair of strings, the first being the connection's sink,
@@ -48,4 +53,7 @@ sound {
 		"Mic", "MIC1";
 
 	nvidia,ac97-controller = <&ac97>;
+
+	clocks = <&tegra_car 112>, <&tegra_car 113>, <&tegra_car 93>;
+	clock-names = "pll_a", "pll_a_out0", "mclk";
 };
diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra30-ahub.txt b/Documentation/devicetree/bindings/sound/nvidia,tegra30-ahub.txt
index 1ac7b16..0e5c12c 100644
--- a/Documentation/devicetree/bindings/sound/nvidia,tegra30-ahub.txt
+++ b/Documentation/devicetree/bindings/sound/nvidia,tegra30-ahub.txt
@@ -1,12 +1,22 @@
 NVIDIA Tegra30 AHUB (Audio Hub)
 
 Required properties:
-- compatible : "nvidia,tegra30-ahub"
+- compatible : "nvidia,tegra30-ahub", "nvidia,tegra114-ahub", etc.
 - reg : Should contain the register physical address and length for each of
-  the AHUB's APBIF registers and the AHUB's own registers.
+  the AHUB's register blocks.
+  - Tegra30 requires 2 entries, for the APBIF and AHUB/AUDIO register blocks.
+  - Tegra114 requires an additional entry, for the APBIF2 register block.
 - interrupts : Should contain AHUB interrupt
-- nvidia,dma-request-selector : The Tegra DMA controller's phandle and
-  request selector for the first APBIF channel.
+- nvidia,dma-request-selector : A list of the DMA channel specifiers. Each
+  entry contains the Tegra DMA controller's phandle and request selector.
+  If a single entry is present, the request selectors for the channels are
+  assumed to be contiguous, and increment from this value.
+  If multiple values are given, one value must be given per channel.
+- clocks : Must contain an entry for each required entry in clock-names.
+- clock-names : Must include the following entries:
+  - Tegra30: Requires d_audio, apbif, i2s0, i2s1, i2s2, i2s3, i2s4, dam0,
+    dam1, dam2, spdif_in.
+  - Tegra114: Additionally requires amx, adx.
 - ranges : The bus address mapping for the configlink register bus.
   Can be empty since the mapping is 1:1.
 - #address-cells : For the configlink bus. Should be <1>;
@@ -25,7 +35,13 @@ ahub@70080000 {
 	reg = <0x70080000 0x200 0x70080200 0x100>;
 	interrupts = < 0 103 0x04 >;
 	nvidia,dma-request-selector = <&apbdma 1>;
-
+	clocks = <&tegra_car 106>, <&tegra_car 107>, <&tegra_car 30>,
+		<&tegra_car 11>, <&tegra_car 18>, <&tegra_car 101>,
+		<&tegra_car 102>, <&tegra_car 108>, <&tegra_car 109>,
+		<&tegra_car 110>, <&tegra_car 162>;
+	clock-names = "d_audio", "apbif", "i2s0", "i2s1", "i2s2",
+		"i2s3", "i2s4", "dam0", "dam1", "dam2",
+		"spdif_in";
 	ranges;
 	#address-cells = <1>;
 	#size-cells = <1>;
diff --git a/Documentation/devicetree/bindings/sound/ti,tas5086.txt b/Documentation/devicetree/bindings/sound/ti,tas5086.txt
new file mode 100644
index 0000000..8ea4f5b
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/ti,tas5086.txt
@@ -0,0 +1,32 @@
+Texas Instruments TAS5086 6-channel PWM Processor
+
+Required properties:
+
+ - compatible:		Should contain "ti,tas5086".
+ - reg:			The i2c address. Should contain <0x1b>.
+
+Optional properties:
+
+ - reset-gpio: 		A GPIO spec to define which pin is connected to the
+			chip's !RESET pin. If specified, the driver will
+			assert a hardware reset at probe time.
+
+ - ti,charge-period:	This property should contain the time in microseconds
+			that closely matches the external single-ended
+			split-capacitor charge period. The hardware chip
+			waits for this period of time before starting the
+			PWM signals. This helps reduce pops and clicks.
+
+			When not specified, the hardware default of 1300ms
+			is retained.
+
+Examples:
+
+	i2c_bus {
+		tas5086@1b {
+			compatible = "ti,tas5086";
+			reg = <0x1b>;
+			reset-gpio = <&gpio 23 0>;
+			ti,charge-period = <156000>;
+		};
+	};
diff --git a/Documentation/devicetree/bindings/spi/brcm,bcm2835-spi.txt b/Documentation/devicetree/bindings/spi/brcm,bcm2835-spi.txt
new file mode 100644
index 0000000..8bf89c6
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/brcm,bcm2835-spi.txt
@@ -0,0 +1,22 @@
+Broadcom BCM2835 SPI0 controller
+
+The BCM2835 contains two forms of SPI master controller, one known simply as
+SPI0, and the other known as the "Universal SPI Master"; part of the
+auxilliary block. This binding applies to the SPI0 controller.
+
+Required properties:
+- compatible: Should be "brcm,bcm2835-spi".
+- reg: Should contain register location and length.
+- interrupts: Should contain interrupt.
+- clocks: The clock feeding the SPI controller.
+
+Example:
+
+spi@20204000 {
+	compatible = "brcm,bcm2835-spi";
+	reg = <0x7e204000 0x1000>;
+	interrupts = <2 22>;
+	clocks = <&clk_spi>;
+	#address-cells = <1>;
+	#size-cells = <0>;
+};
diff --git a/Documentation/devicetree/bindings/spi/mxs-spi.txt b/Documentation/devicetree/bindings/spi/mxs-spi.txt
index e2e1395..3499b73 100644
--- a/Documentation/devicetree/bindings/spi/mxs-spi.txt
+++ b/Documentation/devicetree/bindings/spi/mxs-spi.txt
@@ -3,8 +3,11 @@
 Required properties:
 - compatible: Should be "fsl,<soc>-spi", where soc is "imx23" or "imx28"
 - reg: Offset and length of the register set for the device
-- interrupts: Should contain SSP interrupts (error irq first, dma irq second)
-- fsl,ssp-dma-channel: APBX DMA channel for the SSP
+- interrupts: Should contain SSP ERROR interrupt
+- dmas: DMA specifier, consisting of a phandle to DMA controller node
+  and SSP DMA channel ID.
+  Refer to dma.txt and fsl-mxs-dma.txt for details.
+- dma-names: Must be "rx-tx".
 
 Optional properties:
 - clock-frequency : Input clock frequency to the SPI block in Hz.
@@ -17,6 +20,7 @@ ssp0: ssp@80010000 {
 	#size-cells = <0>;
 	compatible = "fsl,imx28-spi";
 	reg = <0x80010000 0x2000>;
-	interrupts = <96 82>;
-	fsl,ssp-dma-channel = <0>;
+	interrupts = <96>;
+	dmas = <&dma_apbh 0>;
+	dma-names = "rx-tx";
 };
diff --git a/Documentation/devicetree/bindings/staging/imx-drm/fsl-imx-drm.txt b/Documentation/devicetree/bindings/staging/imx-drm/fsl-imx-drm.txt
index 07654f0..f769857 100644
--- a/Documentation/devicetree/bindings/staging/imx-drm/fsl-imx-drm.txt
+++ b/Documentation/devicetree/bindings/staging/imx-drm/fsl-imx-drm.txt
@@ -8,6 +8,8 @@ Required properties:
 - interrupts: Should contain sync interrupt and error interrupt,
   in this order.
 - #crtc-cells: 1, See below
+- resets: phandle pointing to the system reset controller and
+          reset line index, see reset/fsl,imx-src.txt for details
 
 example:
 
@@ -16,6 +18,7 @@ ipu: ipu@18000000 {
 	compatible = "fsl,imx53-ipu";
 	reg = <0x18000000 0x080000000>;
 	interrupts = <11 10>;
+	resets = <&src 2>;
 };
 
 Parallel display support
diff --git a/Documentation/devicetree/bindings/timer/cadence,ttc-timer.txt b/Documentation/devicetree/bindings/timer/cadence,ttc-timer.txt
new file mode 100644
index 0000000..993695c
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/cadence,ttc-timer.txt
@@ -0,0 +1,17 @@
+Cadence TTC - Triple Timer Counter
+
+Required properties:
+- compatible : Should be "cdns,ttc".
+- reg : Specifies base physical address and size of the registers.
+- interrupts : A list of 3 interrupts; one per timer channel.
+- clocks: phandle to the source clock
+
+Example:
+
+ttc0: ttc0@f8001000 {
+	interrupt-parent = <&intc>;
+	interrupts = < 0 10 4 0 11 4 0 12 4 >;
+	compatible = "cdns,ttc";
+	reg = <0xF8001000 0x1000>;
+	clocks = <&cpu_clk 3>;
+};
diff --git a/Documentation/devicetree/bindings/timer/fsl,imxgpt.txt b/Documentation/devicetree/bindings/timer/fsl,imxgpt.txt
new file mode 100644
index 0000000..9809b11
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/fsl,imxgpt.txt
@@ -0,0 +1,18 @@
+Freescale i.MX General Purpose Timer (GPT)
+
+Required properties:
+
+- compatible : should be "fsl,<soc>-gpt"
+- reg : Specifies base physical address and size of the registers.
+- interrupts : A list of 4 interrupts; one per timer channel.
+- clocks : The clocks provided by the SoC to drive the timer.
+
+Example:
+
+gpt1: timer@10003000 {
+	compatible = "fsl,imx27-gpt", "fsl,imx1-gpt";
+	reg = <0x10003000 0x1000>;
+	interrupts = <26>;
+	clocks = <&clks 46>, <&clks 61>;
+	clock-names = "ipg", "per";
+};
diff --git a/Documentation/devicetree/bindings/timer/samsung,exynos4210-mct.txt b/Documentation/devicetree/bindings/timer/samsung,exynos4210-mct.txt
new file mode 100644
index 0000000..cb47bfb
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/samsung,exynos4210-mct.txt
@@ -0,0 +1,68 @@
+Samsung's Multi Core Timer (MCT)
+
+The Samsung's Multi Core Timer (MCT) module includes two main blocks, the
+global timer and CPU local timers. The global timer is a 64-bit free running
+up-counter and can generate 4 interrupts when the counter reaches one of the
+four preset counter values. The CPU local timers are 32-bit free running
+down-counters and generate an interrupt when the counter expires. There is
+one CPU local timer instantiated in MCT for every CPU in the system.
+
+Required properties:
+
+- compatible: should be "samsung,exynos4210-mct".
+  (a) "samsung,exynos4210-mct", for mct compatible with Exynos4210 mct.
+  (b) "samsung,exynos4412-mct", for mct compatible with Exynos4412 mct.
+
+- reg: base address of the mct controller and length of the address space
+  it occupies.
+
+- interrupts: the list of interrupts generated by the controller. The following
+  should be the order of the interrupts specified. The local timer interrupts
+  should be specified after the four global timer interrupts have been
+  specified.
+
+	0: Global Timer Interrupt 0
+	1: Global Timer Interrupt 1
+	2: Global Timer Interrupt 2
+	3: Global Timer Interrupt 3
+	4: Local Timer Interrupt 0
+	5: Local Timer Interrupt 1
+	6: ..
+	7: ..
+	i: Local Timer Interrupt n
+
+Example 1: In this example, the system uses only the first global timer
+	   interrupt generated by MCT and the remaining three global timer
+	   interrupts are unused. Two local timer interrupts have been
+	   specified.
+
+	mct@10050000 {
+		compatible = "samsung,exynos4210-mct";
+		reg = <0x10050000 0x800>;
+		interrupts = <0 57 0>, <0 0 0>, <0 0 0>, <0 0 0>,
+			     <0 42 0>, <0 48 0>;
+	};
+
+Example 2: In this example, the MCT global and local timer interrupts are
+	   connected to two seperate interrupt controllers. Hence, an
+	   interrupt-map is created to map the interrupts to the respective
+	   interrupt controllers.
+
+	mct@101C0000 {
+		compatible = "samsung,exynos4210-mct";
+		reg = <0x101C0000 0x800>;
+		interrupt-controller;
+		#interrups-cells = <2>;
+		interrupt-parent = <&mct_map>;
+		interrupts = <0 0>, <1 0>, <2 0>, <3 0>,
+			     <4 0>, <5 0>;
+
+		mct_map: mct-map {
+			#interrupt-cells = <2>;
+			#address-cells = <0>;
+			#size-cells = <0>;
+			interrupt-map = <0x0 0 &combiner 23 3>,
+					<0x4 0 &gic 0 120 0>,
+					<0x5 0 &gic 0 121 0>;
+		};
+	};
diff --git a/Documentation/devicetree/bindings/tty/serial/fsl-mxs-auart.txt b/Documentation/devicetree/bindings/tty/serial/fsl-mxs-auart.txt
index 273a8d5..2c00ec6 100644
--- a/Documentation/devicetree/bindings/tty/serial/fsl-mxs-auart.txt
+++ b/Documentation/devicetree/bindings/tty/serial/fsl-mxs-auart.txt
@@ -5,20 +5,18 @@ Required properties:
   imx23 and imx28.
 - reg : Address and length of the register set for the device
 - interrupts : Should contain the auart interrupt numbers
-
-Optional properties:
-- fsl,auart-dma-channel : The DMA channels, the first is for RX, the other
-		is for TX. If you add this property, it also means that you
-		will enable the DMA support for the auart.
-		Note: due to the hardware bug in imx23(see errata : 2836),
-		only the imx28 can enable the DMA support for the auart.
+- dmas: DMA specifier, consisting of a phandle to DMA controller node
+  and AUART DMA channel ID.
+  Refer to dma.txt and fsl-mxs-dma.txt for details.
+- dma-names: "rx" for RX channel, "tx" for TX channel.
 
 Example:
 auart0: serial@8006a000 {
 	compatible = "fsl,imx28-auart", "fsl,imx23-auart";
 	reg = <0x8006a000 0x2000>;
-	interrupts = <112 70 71>;
-	fsl,auart-dma-channel = <8 9>;
+	interrupts = <112>;
+	dmas = <&dma_apbx 8>, <&dma_apbx 9>;
+	dma-names = "rx", "tx";
 };
 
 Note: Each auart port should have an alias correctly numbered in "aliases"
diff --git a/Documentation/devicetree/bindings/tty/serial/of-serial.txt b/Documentation/devicetree/bindings/tty/serial/of-serial.txt
index 8f01cb1..1928a3e 100644
--- a/Documentation/devicetree/bindings/tty/serial/of-serial.txt
+++ b/Documentation/devicetree/bindings/tty/serial/of-serial.txt
@@ -33,6 +33,10 @@ Optional properties:
   RTAS and should not be registered.
 - no-loopback-test: set to indicate that the port does not implements loopback
   test mode
+- fifo-size: the fifo size of the UART.
+- auto-flow-control: one way to enable automatic flow control support. The
+  driver is allowed to detect support for the capability even without this
+  property.
 
 Example:
 
diff --git a/Documentation/devicetree/bindings/tty/serial/renesas,sci-serial.txt b/Documentation/devicetree/bindings/tty/serial/renesas,sci-serial.txt
new file mode 100644
index 0000000..6ad1adf
--- /dev/null
+++ b/Documentation/devicetree/bindings/tty/serial/renesas,sci-serial.txt
@@ -0,0 +1,53 @@
+* Renesas SH-Mobile Serial Communication Interface
+
+Required properties:
+- compatible : Should be "renesas,sci-<port type>-uart", where <port type> may be
+  SCI, SCIF, IRDA, SCIFA or SCIFB.
+- reg : Address and length of the register set for the device
+- interrupts : Should contain the following IRQs: ERI, RXI, TXI and BRI.
+- cell-index : The device id.
+- renesas,scscr : Should contain a bitfield used by the Serial Control Register.
+  b7 = SCSCR_TIE
+  b6 = SCSCR_RIE
+  b5 = SCSCR_TE
+  b4 = SCSCR_RE
+  b3 = SCSCR_REIE
+  b2 = SCSCR_TOIE
+  b1 = SCSCR_CKE1
+  b0 = SCSCR_CKE0
+- renesas,scbrr-algo-id : Algorithm ID for the Bit Rate Register
+  1 = SCBRR_ALGO_1 ((clk + 16 * bps) / (16 * bps) - 1)
+  2 = SCBRR_ALGO_2 ((clk + 16 * bps) / (32 * bps) - 1)
+  3 = SCBRR_ALGO_3 (((clk * 2) + 16 * bps) / (16 * bps) - 1)
+  4 = SCBRR_ALGO_4 (((clk * 2) + 16 * bps) / (32 * bps) - 1)
+  5 = SCBRR_ALGO_5 (((clk * 1000 / 32) / bps) - 1)
+
+Optional properties:
+- renesas,autoconf : Set if device is capable of auto configuration
+- renesas,regtype : Overwrite the register layout. In most cases you can rely
+  on auto-probing (omit this property or set to 0) but some legacy devices
+  use a non-default register layout. Possible layouts are
+  0 = SCIx_PROBE_REGTYPE (default)
+  1 = SCIx_SCI_REGTYPE
+  2 = SCIx_IRDA_REGTYPE
+  3 = SCIx_SCIFA_REGTYPE
+  4 = SCIx_SCIFB_REGTYPE
+  5 = SCIx_SH2_SCIF_FIFODATA_REGTYPE
+  6 = SCIx_SH3_SCIF_REGTYPE
+  7 = SCIx_SH4_SCIF_REGTYPE
+  8 = SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE
+  9 = SCIx_SH4_SCIF_FIFODATA_REGTYPE
+ 10 = SCIx_SH7705_SCIF_REGTYPE
+
+
+Example:
+	sci@0xe6c50000 {
+		compatible = "renesas,sci-SCIFA-uart";
+		interrupt-parent = <&intca>;
+		reg = <0xe6c50000 0x100>;
+		interrupts = <0x0c20>, <0x0c20>, <0x0c20>, <0x0c20>;
+		cell-index = <1>;
+		renesas,scscr = <0x30>;
+		renesas,scbrr-algo-id = <4>;
+		renesas,autoconf;
+	};
diff --git a/Documentation/devicetree/bindings/usb/ci13xxx-imx.txt b/Documentation/devicetree/bindings/usb/ci13xxx-imx.txt
index 5778b9c..1c04a4c 100644
--- a/Documentation/devicetree/bindings/usb/ci13xxx-imx.txt
+++ b/Documentation/devicetree/bindings/usb/ci13xxx-imx.txt
@@ -11,6 +11,7 @@ Optional properties:
   that indicate usb controller index
 - vbus-supply: regulator for vbus
 - disable-over-current: disable over current detect
+- external-vbus-divider: enables off-chip resistor divider for Vbus
 
 Examples:
 usb@02184000 { /* USB OTG */
@@ -20,4 +21,5 @@ usb@02184000 { /* USB OTG */
 	fsl,usbphy = <&usbphy1>;
 	fsl,usbmisc = <&usbmisc 0>;
 	disable-over-current;
+	external-vbus-divider;
 };
diff --git a/Documentation/devicetree/bindings/usb/ehci-omap.txt b/Documentation/devicetree/bindings/usb/ehci-omap.txt
new file mode 100644
index 0000000..485a9a1
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/ehci-omap.txt
@@ -0,0 +1,32 @@
+OMAP HS USB EHCI controller
+
+This device is usually the child of the omap-usb-host
+Documentation/devicetree/bindings/mfd/omap-usb-host.txt
+
+Required properties:
+
+- compatible: should be "ti,ehci-omap"
+- reg: should contain one register range i.e. start and length
+- interrupts: description of the interrupt line
+
+Optional properties:
+
+- phys: list of phandles to PHY nodes.
+  This property is required if at least one of the ports are in
+  PHY mode i.e. OMAP_EHCI_PORT_MODE_PHY
+
+To specify the port mode, see
+Documentation/devicetree/bindings/mfd/omap-usb-host.txt
+
+Example for OMAP4:
+
+usbhsehci: ehci@4a064c00 {
+	compatible = "ti,ehci-omap", "usb-ehci";
+	reg = <0x4a064c00 0x400>;
+	interrupts = <0 77 0x4>;
+};
+
+&usbhsehci {
+	phys = <&hsusb1_phy 0 &hsusb3_phy>;
+};
+
diff --git a/Documentation/devicetree/bindings/usb/exynos-usb.txt b/Documentation/devicetree/bindings/usb/exynos-usb.txt
new file mode 100644
index 0000000..b3abde7
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/exynos-usb.txt
@@ -0,0 +1,50 @@
+Samsung Exynos SoC USB controller
+
+The USB devices interface with USB controllers on Exynos SOCs.
+The device node has following properties.
+
+EHCI
+Required properties:
+ - compatible: should be "samsung,exynos4210-ehci" for USB 2.0
+   EHCI controller in host mode.
+ - reg: physical base address of the controller and length of memory mapped
+   region.
+ - interrupts: interrupt number to the cpu.
+ - clocks: from common clock binding: handle to usb clock.
+ - clock-names: from common clock binding: Shall be "usbhost".
+
+Optional properties:
+ - samsung,vbus-gpio:  if present, specifies the GPIO that
+   needs to be pulled up for the bus to be powered.
+
+Example:
+
+	usb@12110000 {
+		compatible = "samsung,exynos4210-ehci";
+		reg = <0x12110000 0x100>;
+		interrupts = <0 71 0>;
+		samsung,vbus-gpio = <&gpx2 6 1 3 3>;
+
+		clocks = <&clock 285>;
+		clock-names = "usbhost";
+	};
+
+OHCI
+Required properties:
+ - compatible: should be "samsung,exynos4210-ohci" for USB 2.0
+   OHCI companion controller in host mode.
+ - reg: physical base address of the controller and length of memory mapped
+   region.
+ - interrupts: interrupt number to the cpu.
+ - clocks: from common clock binding: handle to usb clock.
+ - clock-names: from common clock binding: Shall be "usbhost".
+
+Example:
+	usb@12120000 {
+		compatible = "samsung,exynos4210-ohci";
+		reg = <0x12120000 0x100>;
+		interrupts = <0 71 0>;
+
+		clocks = <&clock 285>;
+		clock-names = "usbhost";
+	};
diff --git a/Documentation/devicetree/bindings/usb/ohci-omap3.txt b/Documentation/devicetree/bindings/usb/ohci-omap3.txt
new file mode 100644
index 0000000..14ab428
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/ohci-omap3.txt
@@ -0,0 +1,15 @@
+OMAP HS USB OHCI controller (OMAP3 and later)
+
+Required properties:
+
+- compatible: should be "ti,ohci-omap3"
+- reg: should contain one register range i.e. start and length
+- interrupts: description of the interrupt line
+
+Example for OMAP4:
+
+usbhsohci: ohci@4a064800 {
+	compatible = "ti,ohci-omap3", "usb-ohci";
+	reg = <0x4a064800 0x400>;
+	interrupts = <0 76 0x4>;
+};
diff --git a/Documentation/devicetree/bindings/usb/omap-usb.txt b/Documentation/devicetree/bindings/usb/omap-usb.txt
index 1ef0ce7..662f0f1 100644
--- a/Documentation/devicetree/bindings/usb/omap-usb.txt
+++ b/Documentation/devicetree/bindings/usb/omap-usb.txt
@@ -8,10 +8,10 @@ OMAP MUSB GLUE
    and disconnect.
  - multipoint : Should be "1" indicating the musb controller supports
    multipoint. This is a MUSB configuration-specific setting.
- - num_eps : Specifies the number of endpoints. This is also a
+ - num-eps : Specifies the number of endpoints. This is also a
    MUSB configuration-specific setting. Should be set to "16"
- - ram_bits : Specifies the ram address size. Should be set to "12"
- - interface_type : This is a board specific setting to describe the type of
+ - ram-bits : Specifies the ram address size. Should be set to "12"
+ - interface-type : This is a board specific setting to describe the type of
    interface between the controller and the phy. It should be "0" or "1"
    specifying ULPI and UTMI respectively.
  - mode : Should be "3" to represent OTG. "1" signifies HOST and "2"
@@ -29,18 +29,46 @@ usb_otg_hs: usb_otg_hs@4a0ab000 {
 	ti,hwmods = "usb_otg_hs";
 	ti,has-mailbox;
 	multipoint = <1>;
-	num_eps = <16>;
-	ram_bits = <12>;
+	num-eps = <16>;
+	ram-bits = <12>;
 	ctrl-module = <&omap_control_usb>;
 };
 
 Board specific device node entry
 &usb_otg_hs {
-	interface_type = <1>;
+	interface-type = <1>;
 	mode = <3>;
 	power = <50>;
 };
 
+OMAP DWC3 GLUE
+ - compatible : Should be "ti,dwc3"
+ - ti,hwmods : Should be "usb_otg_ss"
+ - reg : Address and length of the register set for the device.
+ - interrupts : The irq number of this device that is used to interrupt the
+   MPU
+ - #address-cells, #size-cells : Must be present if the device has sub-nodes
+ - utmi-mode : controls the source of UTMI/PIPE status for VBUS and OTG ID.
+   It should be set to "1" for HW mode and "2" for SW mode.
+ - ranges: the child address space are mapped 1:1 onto the parent address space
+
+Sub-nodes:
+The dwc3 core should be added as subnode to omap dwc3 glue.
+- dwc3 :
+   The binding details of dwc3 can be found in:
+   Documentation/devicetree/bindings/usb/dwc3.txt
+
+omap_dwc3 {
+	compatible = "ti,dwc3";
+	ti,hwmods = "usb_otg_ss";
+	reg = <0x4a020000 0x1ff>;
+	interrupts = <0 93 4>;
+	#address-cells = <1>;
+	#size-cells = <1>;
+	utmi-mode = <2>;
+	ranges;
+};
+
 OMAP CONTROL USB
 
 Required properties:
diff --git a/Documentation/devicetree/bindings/usb/samsung-usbphy.txt b/Documentation/devicetree/bindings/usb/samsung-usbphy.txt
index 0331949..f575302 100644
--- a/Documentation/devicetree/bindings/usb/samsung-usbphy.txt
+++ b/Documentation/devicetree/bindings/usb/samsung-usbphy.txt
@@ -1,20 +1,25 @@
-* Samsung's usb phy transceiver
+SAMSUNG USB-PHY controllers
 
-The Samsung's phy transceiver is used for controlling usb phy for
-s3c-hsotg as well as ehci-s5p and ohci-exynos usb controllers
-across Samsung SOCs.
+** Samsung's usb 2.0 phy transceiver
+
+The Samsung's usb 2.0 phy transceiver is used for controlling
+usb 2.0 phy for s3c-hsotg as well as ehci-s5p and ohci-exynos
+usb controllers across Samsung SOCs.
 TODO: Adding the PHY binding with controller(s) according to the under
 developement generic PHY driver.
 
 Required properties:
 
 Exynos4210:
-- compatible : should be "samsung,exynos4210-usbphy"
+- compatible : should be "samsung,exynos4210-usb2phy"
 - reg : base physical address of the phy registers and length of memory mapped
 	region.
+- clocks: Clock IDs array as required by the controller.
+- clock-names: names of clock correseponding IDs clock property as requested
+	       by the controller driver.
 
 Exynos5250:
-- compatible : should be "samsung,exynos5250-usbphy"
+- compatible : should be "samsung,exynos5250-usb2phy"
 - reg : base physical address of the phy registers and length of memory mapped
 	region.
 
@@ -44,12 +49,69 @@ Example:
 	usbphy@125B0000 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "samsung,exynos4210-usbphy";
+		compatible = "samsung,exynos4210-usb2phy";
 		reg = <0x125B0000 0x100>;
 		ranges;
 
+		clocks = <&clock 2>, <&clock 305>;
+		clock-names = "xusbxti", "otg";
+
 		usbphy-sys {
 			/* USB device and host PHY_CONTROL registers */
 			reg = <0x10020704 0x8>;
 		};
 	};
+
+
+** Samsung's usb 3.0 phy transceiver
+
+Starting exynso5250, Samsung's SoC have usb 3.0 phy transceiver
+which is used for controlling usb 3.0 phy for dwc3-exynos usb 3.0
+controllers across Samsung SOCs.
+
+Required properties:
+
+Exynos5250:
+- compatible : should be "samsung,exynos5250-usb3phy"
+- reg : base physical address of the phy registers and length of memory mapped
+	region.
+- clocks: Clock IDs array as required by the controller.
+- clock-names: names of clocks correseponding to IDs in the clock property
+	       as requested by the controller driver.
+
+Optional properties:
+- #address-cells: should be '1' when usbphy node has a child node with 'reg'
+		  property.
+- #size-cells: should be '1' when usbphy node has a child node with 'reg'
+	       property.
+- ranges: allows valid translation between child's address space and parent's
+	  address space.
+
+- The child node 'usbphy-sys' to the node 'usbphy' is for the system controller
+  interface for usb-phy. It should provide the following information required by
+  usb-phy controller to control phy.
+  - reg : base physical address of PHY_CONTROL registers.
+	  The size of this register is the total sum of size of all PHY_CONTROL
+	  registers that the SoC has. For example, the size will be
+	  '0x4' in case we have only one PHY_CONTROL register (e.g.
+	  OTHERS register in S3C64XX or USB_PHY_CONTROL register in S5PV210)
+	  and, '0x8' in case we have two PHY_CONTROL registers (e.g.
+	  USBDEVICE_PHY_CONTROL and USBHOST_PHY_CONTROL registers in exynos4x).
+	  and so on.
+
+Example:
+	usbphy@12100000 {
+		compatible = "samsung,exynos5250-usb3phy";
+		reg = <0x12100000 0x100>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		clocks = <&clock 1>, <&clock 286>;
+		clock-names = "ext_xtal", "usbdrd30";
+
+		usbphy-sys {
+			/* USB device and host PHY_CONTROL registers */
+			reg = <0x10040704 0x8>;
+		};
+	};
diff --git a/Documentation/devicetree/bindings/usb/usb-nop-xceiv.txt b/Documentation/devicetree/bindings/usb/usb-nop-xceiv.txt
new file mode 100644
index 0000000..d7e2726
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/usb-nop-xceiv.txt
@@ -0,0 +1,34 @@
+USB NOP PHY
+
+Required properties:
+- compatible: should be usb-nop-xceiv
+
+Optional properties:
+- clocks: phandle to the PHY clock. Use as per Documentation/devicetree
+  /bindings/clock/clock-bindings.txt
+  This property is required if clock-frequency is specified.
+
+- clock-names: Should be "main_clk"
+
+- clock-frequency: the clock frequency (in Hz) that the PHY clock must
+  be configured to.
+
+- vcc-supply: phandle to the regulator that provides RESET to the PHY.
+
+- reset-supply: phandle to the regulator that provides power to the PHY.
+
+Example:
+
+	hsusb1_phy {
+		compatible = "usb-nop-xceiv";
+		clock-frequency = <19200000>;
+		clocks = <&osc 0>;
+		clock-names = "main_clk";
+		vcc-supply = <&hsusb1_vcc_regulator>;
+		reset-supply = <&hsusb1_reset_regulator>;
+	};
+
+hsusb1_phy is a NOP USB PHY device that gets its clock from an oscillator
+and expects that clock to be configured to 19.2MHz by the NOP PHY driver.
+hsusb1_vcc_regulator provides power to the PHY and hsusb1_reset_regulator
+controls RESET.
diff --git a/Documentation/devicetree/bindings/video/via,vt8500-fb.txt b/Documentation/devicetree/bindings/video/via,vt8500-fb.txt
index c870b64..2871e21 100644
--- a/Documentation/devicetree/bindings/video/via,vt8500-fb.txt
+++ b/Documentation/devicetree/bindings/video/via,vt8500-fb.txt
@@ -5,58 +5,32 @@ Required properties:
 - compatible : "via,vt8500-fb"
 - reg : Should contain 1 register ranges(address and length)
 - interrupts : framebuffer controller interrupt
-- display: a phandle pointing to the display node
+- bits-per-pixel : bit depth of framebuffer (16 or 32)
 
-Required nodes:
-- display: a display node is required to initialize the lcd panel
-	This should be in the board dts.
-- default-mode: a videomode within the display with timing parameters
-	as specified below.
+Required subnodes:
+- display-timings: see display-timing.txt for information
 
 Example:
 
-	fb@d800e400 {
+	fb@d8050800 {
 		compatible = "via,vt8500-fb";
 		reg = <0xd800e400 0x400>;
 		interrupts = <12>;
-		display = <&display>;
-		default-mode = <&mode0>;
-	};
-
-VIA VT8500 Display
------------------------------------------------------
-Required properties (as per of_videomode_helper):
-
- - hactive, vactive: Display resolution
- - hfront-porch, hback-porch, hsync-len: Horizontal Display timing parameters
-   in pixels
-   vfront-porch, vback-porch, vsync-len: Vertical display timing parameters in
-   lines
- - clock: displayclock in Hz
- - bpp: lcd panel bit-depth.
-	<16> for RGB565, <32> for RGB888
-
-Optional properties (as per of_videomode_helper):
- - width-mm, height-mm: Display dimensions in mm
- - hsync-active-high (bool): Hsync pulse is active high
- - vsync-active-high (bool): Vsync pulse is active high
- - interlaced (bool): This is an interlaced mode
- - doublescan (bool): This is a doublescan mode
+		bits-per-pixel = <16>;
 
-Example:
-	display: display@0 {
-		modes {
-			mode0: mode@0 {
+		display-timings {
+			native-mode = <&timing0>;
+			timing0: 800x480 {
+				clock-frequency = <0>; /* unused but required */
 				hactive = <800>;
 				vactive = <480>;
-				hback-porch = <88>;
 				hfront-porch = <40>;
+				hback-porch = <88>;
 				hsync-len = <0>;
 				vback-porch = <32>;
 				vfront-porch = <11>;
 				vsync-len = <1>;
-				clock = <0>;	/* unused but required */
-				bpp = <16>;	/* non-standard but required */
 			};
 		};
 	};
+
diff --git a/Documentation/devicetree/bindings/video/wm,wm8505-fb.txt b/Documentation/devicetree/bindings/video/wm,wm8505-fb.txt
index 3d325e1..0bcadb2 100644
--- a/Documentation/devicetree/bindings/video/wm,wm8505-fb.txt
+++ b/Documentation/devicetree/bindings/video/wm,wm8505-fb.txt
@@ -4,20 +4,30 @@ Wondermedia WM8505 Framebuffer
 Required properties:
 - compatible : "wm,wm8505-fb"
 - reg : Should contain 1 register ranges(address and length)
-- via,display: a phandle pointing to the display node
+- bits-per-pixel : bit depth of framebuffer (16 or 32)
 
-Required nodes:
-- display: a display node is required to initialize the lcd panel
-	This should be in the board dts. See definition in
-	Documentation/devicetree/bindings/video/via,vt8500-fb.txt
-- default-mode: a videomode node as specified in
-	Documentation/devicetree/bindings/video/via,vt8500-fb.txt
+Required subnodes:
+- display-timings: see display-timing.txt for information
 
 Example:
 
-	fb@d8050800 {
+	fb@d8051700 {
 		compatible = "wm,wm8505-fb";
-		reg = <0xd8050800 0x200>;
-		display = <&display>;
-		default-mode = <&mode0>;
+		reg = <0xd8051700 0x200>;
+		bits-per-pixel = <16>;
+
+		display-timings {
+			native-mode = <&timing0>;
+			timing0: 800x480 {
+				clock-frequency = <0>; /* unused but required */
+				hactive = <800>;
+				vactive = <480>;
+				hfront-porch = <40>;
+				hback-porch = <88>;
+				hsync-len = <0>;
+				vback-porch = <32>;
+				vfront-porch = <11>;
+				vsync-len = <1>;
+			};
+		};
 	};
diff --git a/Documentation/dmatest.txt b/Documentation/dmatest.txt
new file mode 100644
index 0000000..279ac0a
--- /dev/null
+++ b/Documentation/dmatest.txt
@@ -0,0 +1,81 @@
+				DMA Test Guide
+				==============
+
+		Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+
+This small document introduces how to test DMA drivers using dmatest module.
+
+	Part 1 - How to build the test module
+
+The menuconfig contains an option that could be found by following path:
+	Device Drivers -> DMA Engine support -> DMA Test client
+
+In the configuration file the option called CONFIG_DMATEST. The dmatest could
+be built as module or inside kernel. Let's consider those cases.
+
+	Part 2 - When dmatest is built as a module...
+
+After mounting debugfs and loading the module, the /sys/kernel/debug/dmatest
+folder with nodes will be created. They are the same as module parameters with
+addition of the 'run' node that controls run and stop phases of the test.
+
+Note that in this case test will not run on load automatically.
+
+Example of usage:
+	% echo dma0chan0 > /sys/kernel/debug/dmatest/channel
+	% echo 2000 > /sys/kernel/debug/dmatest/timeout
+	% echo 1 > /sys/kernel/debug/dmatest/iterations
+	% echo 1 > /sys/kernel/debug/dmatest/run
+
+Hint: available channel list could be extracted by running the following
+command:
+	% ls -1 /sys/class/dma/
+
+After a while you will start to get messages about current status or error like
+in the original code.
+
+Note that running a new test will stop any in progress test.
+
+The following command should return actual state of the test.
+	% cat /sys/kernel/debug/dmatest/run
+
+To wait for test done the user may perform a busy loop that checks the state.
+
+	% while [ $(cat /sys/kernel/debug/dmatest/run) = "Y" ]
+	> do
+	> 	echo -n "."
+	> 	sleep 1
+	> done
+	> echo
+
+	Part 3 - When built-in in the kernel...
+
+The module parameters that is supplied to the kernel command line will be used
+for the first performed test. After user gets a control, the test could be
+interrupted or re-run with same or different parameters. For the details see
+the above section "Part 2 - When dmatest is built as a module..."
+
+In both cases the module parameters are used as initial values for the test case.
+You always could check them at run-time by running
+	% grep -H . /sys/module/dmatest/parameters/*
+
+	Part 4 - Gathering the test results
+
+The module provides a storage for the test results in the memory. The gathered
+data could be used after test is done.
+
+The special file 'results' in the debugfs represents gathered data of the in
+progress test. The messages collected are printed to the kernel log as well.
+
+Example of output:
+	% cat /sys/kernel/debug/dmatest/results
+	dma0chan0-copy0: #1: No errors with src_off=0x7bf dst_off=0x8ad len=0x3fea (0)
+
+The message format is unified across the different types of errors. A number in
+the parens represents additional information, e.g. error code, error counter,
+or status.
+
+Comparison between buffers is stored to the dedicated structure.
+
+Note that the verify result is now accessible only via file 'results' in the
+debugfs.
diff --git a/Documentation/filesystems/vfat.txt b/Documentation/filesystems/vfat.txt
index d230dd9..4a93e98 100644
--- a/Documentation/filesystems/vfat.txt
+++ b/Documentation/filesystems/vfat.txt
@@ -150,12 +150,28 @@ discard       -- If set, issues discard/TRIM commands to the block
 		 device when blocks are freed. This is useful for SSD devices
 		 and sparse/thinly-provisoned LUNs.
 
-nfs           -- This option maintains an index (cache) of directory
-		 inodes by i_logstart which is used by the nfs-related code to
-		 improve look-ups.
+nfs=stale_rw|nostale_ro
+		Enable this only if you want to export the FAT filesystem
+		over NFS.
+
+		stale_rw: This option maintains an index (cache) of directory
+		inodes by i_logstart which is used by the nfs-related code to
+		improve look-ups. Full file operations (read/write) over NFS is
+		supported but with cache eviction at NFS server, this could
+		result in ESTALE issues.
+
+		nostale_ro: This option bases the inode number and filehandle
+		on the on-disk location of a file in the MS-DOS directory entry.
+		This ensures that ESTALE will not be returned after a file is
+		evicted from the inode cache. However, it means that operations
+		such as rename, create and unlink could cause filehandles that
+		previously pointed at one file to point at a different file,
+		potentially causing data corruption. For this reason, this
+		option also mounts the filesystem readonly.
+
+		To maintain backward compatibility, '-o nfs' is also accepted,
+		defaulting to stale_rw
 
-		 Enable this only if you want to export the FAT filesystem
-		 over NFS
 
 <bool>: 0,1,yes,no,true,false
 
diff --git a/Documentation/hw_random.txt b/Documentation/hw_random.txt
index 690f525..026e237 100644
--- a/Documentation/hw_random.txt
+++ b/Documentation/hw_random.txt
@@ -63,7 +63,7 @@ Intel RNG Driver notes:
 
 	* FIXME: support poll(2)
 
-	NOTE: request_mem_region was removed, for two reasons:
+	NOTE: request_mem_region was removed, for three reasons:
 	1) Only one RNG is supported by this driver, 2) The location
 	used by the RNG is a fixed location in MMIO-addressable memory,
 	3) users with properly working BIOS e820 handling will always
diff --git a/Documentation/hwmon/adt7410 b/Documentation/hwmon/adt7410
index 58150c4..9817941 100644
--- a/Documentation/hwmon/adt7410
+++ b/Documentation/hwmon/adt7410
@@ -12,29 +12,42 @@ Supported chips:
     Addresses scanned: None
     Datasheet: Publicly available at the Analog Devices website
                http://www.analog.com/static/imported-files/data_sheets/ADT7420.pdf
+  * Analog Devices ADT7310
+    Prefix: 'adt7310'
+    Addresses scanned: None
+    Datasheet: Publicly available at the Analog Devices website
+               http://www.analog.com/static/imported-files/data_sheets/ADT7310.pdf
+  * Analog Devices ADT7320
+    Prefix: 'adt7320'
+    Addresses scanned: None
+    Datasheet: Publicly available at the Analog Devices website
+               http://www.analog.com/static/imported-files/data_sheets/ADT7320.pdf
 
 Author: Hartmut Knaack <knaack.h@gmx.de>
 
 Description
 -----------
 
-The ADT7410 is a temperature sensor with rated temperature range of -55°C to
-+150°C. It has a high accuracy of +/-0.5°C and can be operated at a resolution
-of 13 bits (0.0625°C) or 16 bits (0.0078°C). The sensor provides an INT pin to
-indicate that a minimum or maximum temperature set point has been exceeded, as
-well as a critical temperature (CT) pin to indicate that the critical
-temperature set point has been exceeded. Both pins can be set up with a common
-hysteresis of 0°C - 15°C and a fault queue, ranging from 1 to 4 events. Both
-pins can individually set to be active-low or active-high, while the whole
-device can either run in comparator mode or interrupt mode. The ADT7410
-supports continous temperature sampling, as well as sampling one temperature
-value per second or even justget one sample on demand for power saving.
-Besides, it can completely power down its ADC, if power management is
-required.
-
-The ADT7420 is register compatible, the only differences being the package,
-a slightly narrower operating temperature range (-40°C to +150°C), and a
-better accuracy (0.25°C instead of 0.50°C.)
+The ADT7310/ADT7410 is a temperature sensor with rated temperature range of
+-55°C to +150°C. It has a high accuracy of +/-0.5°C and can be operated at a
+resolution of 13 bits (0.0625°C) or 16 bits (0.0078°C). The sensor provides an
+INT pin to indicate that a minimum or maximum temperature set point has been
+exceeded, as well as a critical temperature (CT) pin to indicate that the
+critical temperature set point has been exceeded. Both pins can be set up with a
+common hysteresis of 0°C - 15°C and a fault queue, ranging from 1 to 4 events.
+Both pins can individually set to be active-low or active-high, while the whole
+device can either run in comparator mode or interrupt mode. The ADT7410 supports
+continuous temperature sampling, as well as sampling one temperature value per
+second or even just get one sample on demand for power saving. Besides, it can
+completely power down its ADC, if power management is required.
+
+The ADT7320/ADT7420 is register compatible, the only differences being the
+package, a slightly narrower operating temperature range (-40°C to +150°C), and
+a better accuracy (0.25°C instead of 0.50°C.)
+
+The difference between the ADT7310/ADT7320 and ADT7410/ADT7420 is the control
+interface, the ADT7310 and ADT7320 use SPI while the ADT7410 and ADT7420 use
+I2C.
 
 Configuration Notes
 -------------------
diff --git a/Documentation/hwmon/lm25066 b/Documentation/hwmon/lm25066
index 26025e4..c1b57d7 100644
--- a/Documentation/hwmon/lm25066
+++ b/Documentation/hwmon/lm25066
@@ -1,7 +1,13 @@
-Kernel driver max8688
+Kernel driver lm25066
 =====================
 
 Supported chips:
+  * TI LM25056
+    Prefix: 'lm25056'
+    Addresses scanned: -
+    Datasheets:
+	http://www.ti.com/lit/gpn/lm25056
+	http://www.ti.com/lit/gpn/lm25056a
   * National Semiconductor LM25066
     Prefix: 'lm25066'
     Addresses scanned: -
@@ -25,8 +31,9 @@ Author: Guenter Roeck <linux@roeck-us.net>
 Description
 -----------
 
-This driver supports hardware montoring for National Semiconductor LM25066,
-LM5064, and LM5064 Power Management, Monitoring, Control, and Protection ICs.
+This driver supports hardware montoring for National Semiconductor / TI LM25056,
+LM25066, LM5064, and LM5064 Power Management, Monitoring, Control, and
+Protection ICs.
 
 The driver is a client driver to the core PMBus driver. Please see
 Documentation/hwmon/pmbus for details on PMBus client drivers.
@@ -60,14 +67,19 @@ in1_max			Maximum input voltage.
 in1_min_alarm		Input voltage low alarm.
 in1_max_alarm		Input voltage high alarm.
 
-in2_label		"vout1"
-in2_input		Measured output voltage.
-in2_average		Average measured output voltage.
-in2_min			Minimum output voltage.
-in2_min_alarm		Output voltage low alarm.
-
-in3_label		"vout2"
-in3_input		Measured voltage on vaux pin
+in2_label		"vmon"
+in2_input		Measured voltage on VAUX pin
+in2_min			Minimum VAUX voltage (LM25056 only).
+in2_max			Maximum VAUX voltage (LM25056 only).
+in2_min_alarm		VAUX voltage low alarm (LM25056 only).
+in2_max_alarm		VAUX voltage high alarm (LM25056 only).
+
+in3_label		"vout1"
+			Not supported on LM25056.
+in3_input		Measured output voltage.
+in3_average		Average measured output voltage.
+in3_min			Minimum output voltage.
+in3_min_alarm		Output voltage low alarm.
 
 curr1_label		"iin"
 curr1_input		Measured input current.
diff --git a/Documentation/hwmon/lm75 b/Documentation/hwmon/lm75
index 69af1c7..2560a9c 100644
--- a/Documentation/hwmon/lm75
+++ b/Documentation/hwmon/lm75
@@ -12,11 +12,11 @@ Supported chips:
     Addresses scanned: I2C 0x48 - 0x4f
     Datasheet: Publicly available at the National Semiconductor website
                http://www.national.com/
-  * Dallas Semiconductor DS75, DS1775
-    Prefixes: 'ds75', 'ds1775'
+  * Dallas Semiconductor (now Maxim) DS75, DS1775, DS7505
+    Prefixes: 'ds75', 'ds1775', 'ds7505'
     Addresses scanned: none
-    Datasheet: Publicly available at the Dallas Semiconductor website
-               http://www.maxim-ic.com/
+    Datasheet: Publicly available at the Maxim website
+               http://www.maximintegrated.com/
   * Maxim MAX6625, MAX6626
     Prefixes: 'max6625', 'max6626'
     Addresses scanned: none
@@ -67,7 +67,8 @@ the temperature falls below the Hysteresis value.
 All temperatures are in degrees Celsius, and are guaranteed within a
 range of -55 to +125 degrees.
 
-The LM75 only updates its values each 1.5 seconds; reading it more often
+The driver caches the values for a period varying between 1 second for the
+slowest chips and 125 ms for the fastest chips; reading it more often
 will do no harm, but will return 'old' values.
 
 The original LM75 was typically used in combination with LM78-like chips
@@ -78,8 +79,8 @@ The LM75 is essentially an industry standard; there may be other
 LM75 clones not listed here, with or without various enhancements,
 that are supported. The clones are not detected by the driver, unless
 they reproduce the exact register tricks of the original LM75, and must
-therefore be instantiated explicitly. The specific enhancements (such as
-higher resolution) are not currently supported by the driver.
+therefore be instantiated explicitly. Higher resolution up to 12-bit
+is supported by this driver, other specific enhancements are not.
 
 The LM77 is not supported, contrary to what we pretended for a long time.
 Both chips are simply not compatible, value encoding differs.
diff --git a/Documentation/hwmon/lm95234 b/Documentation/hwmon/lm95234
new file mode 100644
index 0000000..a0e95dd
--- /dev/null
+++ b/Documentation/hwmon/lm95234
@@ -0,0 +1,36 @@
+Kernel driver lm95234
+=====================
+
+Supported chips:
+  * National Semiconductor / Texas Instruments LM95234
+    Addresses scanned: I2C 0x18, 0x4d, 0x4e
+    Datasheet: Publicly available at the Texas Instruments website
+               http://www.ti.com/product/lm95234
+
+
+Author: Guenter Roeck <linux@roeck-us.net>
+
+Description
+-----------
+
+LM95234 is an 11-bit digital temperature sensor with a 2-wire System Management
+Bus (SMBus) interface and TrueTherm technology that can very accurately monitor
+the temperature of four remote diodes as well as its own temperature.
+The four remote diodes can be external devices such as microprocessors,
+graphics processors or diode-connected 2N3904s. The LM95234's TruTherm
+beta compensation technology allows sensing of 90 nm or 65 nm process
+thermal diodes accurately.
+
+All temperature values are given in millidegrees Celsius. Temperature
+is provided within a range of -127 to +255 degrees (+127.875 degrees for
+the internal sensor). Resolution depends on temperature input and range.
+
+Each sensor has its own maximum limit, but the hysteresis is common to all
+channels. The hysteresis is configurable with the tem1_max_hyst attribute and
+affects the hysteresis on all channels. The first two external sensors also
+have a critical limit.
+
+The lm95234 driver can change its update interval to a fixed set of values.
+It will round up to the next selectable interval. See the datasheet for exact
+values. Reading sensor values more often will do no harm, but will return
+'old' values.
diff --git a/Documentation/hwmon/ltc2978 b/Documentation/hwmon/ltc2978
index e4d75c6..dc0d08c 100644
--- a/Documentation/hwmon/ltc2978
+++ b/Documentation/hwmon/ltc2978
@@ -2,6 +2,10 @@ Kernel driver ltc2978
 =====================
 
 Supported chips:
+  * Linear Technology LTC2974
+    Prefix: 'ltc2974'
+    Addresses scanned: -
+    Datasheet: http://www.linear.com/product/ltc2974
   * Linear Technology LTC2978
     Prefix: 'ltc2978'
     Addresses scanned: -
@@ -10,6 +14,10 @@ Supported chips:
     Prefix: 'ltc3880'
     Addresses scanned: -
     Datasheet: http://www.linear.com/product/ltc3880
+  * Linear Technology LTC3883
+    Prefix: 'ltc3883'
+    Addresses scanned: -
+    Datasheet: http://www.linear.com/product/ltc3883
 
 Author: Guenter Roeck <linux@roeck-us.net>
 
@@ -17,9 +25,9 @@ Author: Guenter Roeck <linux@roeck-us.net>
 Description
 -----------
 
-The LTC2978 is an octal power supply monitor, supervisor, sequencer and
-margin controller. The LTC3880 is a dual, PolyPhase DC/DC synchronous
-step-down switching regulator controller.
+LTC2974 is a quad digital power supply manager. LTC2978 is an octal power supply
+monitor. LTC3880 is a dual output poly-phase step-down DC/DC controller. LTC3883
+is a single phase step-down DC/DC controller.
 
 
 Usage Notes
@@ -41,63 +49,90 @@ Sysfs attributes
 in1_label		"vin"
 in1_input		Measured input voltage.
 in1_min			Minimum input voltage.
-in1_max			Maximum input voltage.
-in1_lcrit		Critical minimum input voltage.
+in1_max			Maximum input voltage. LTC2974 and LTC2978 only.
+in1_lcrit		Critical minimum input voltage. LTC2974 and LTC2978
+			only.
 in1_crit		Critical maximum input voltage.
 in1_min_alarm		Input voltage low alarm.
-in1_max_alarm		Input voltage high alarm.
-in1_lcrit_alarm		Input voltage critical low alarm.
+in1_max_alarm		Input voltage high alarm. LTC2974 and LTC2978 only.
+in1_lcrit_alarm		Input voltage critical low alarm. LTC2974 and LTC2978
+			only.
 in1_crit_alarm		Input voltage critical high alarm.
-in1_lowest		Lowest input voltage. LTC2978 only.
+in1_lowest		Lowest input voltage. LTC2974 and LTC2978 only.
 in1_highest		Highest input voltage.
-in1_reset_history	Reset history. Writing into this attribute will reset
-			history for all attributes.
-
-in[2-9]_label		"vout[1-8]". Channels 3 to 9 on LTC2978 only.
-in[2-9]_input		Measured output voltage.
-in[2-9]_min		Minimum output voltage.
-in[2-9]_max		Maximum output voltage.
-in[2-9]_lcrit		Critical minimum output voltage.
-in[2-9]_crit		Critical maximum output voltage.
-in[2-9]_min_alarm	Output voltage low alarm.
-in[2-9]_max_alarm	Output voltage high alarm.
-in[2-9]_lcrit_alarm	Output voltage critical low alarm.
-in[2-9]_crit_alarm	Output voltage critical high alarm.
-in[2-9]_lowest		Lowest output voltage. LTC2978 only.
-in[2-9]_highest		Lowest output voltage.
-in[2-9]_reset_history	Reset history. Writing into this attribute will reset
-			history for all attributes.
-
-temp[1-3]_input		Measured temperature.
+in1_reset_history	Reset input voltage history.
+
+in[N]_label		"vout[1-8]".
+			LTC2974: N=2-5
+			LTC2978: N=2-9
+			LTC3880: N=2-3
+			LTC3883: N=2
+in[N]_input		Measured output voltage.
+in[N]_min		Minimum output voltage.
+in[N]_max		Maximum output voltage.
+in[N]_lcrit		Critical minimum output voltage.
+in[N]_crit		Critical maximum output voltage.
+in[N]_min_alarm		Output voltage low alarm.
+in[N]_max_alarm		Output voltage high alarm.
+in[N]_lcrit_alarm	Output voltage critical low alarm.
+in[N]_crit_alarm	Output voltage critical high alarm.
+in[N]_lowest		Lowest output voltage. LTC2974 and LTC2978 only.
+in[N]_highest		Highest output voltage.
+in[N]_reset_history	Reset output voltage history.
+
+temp[N]_input		Measured temperature.
+			On LTC2974, temp[1-4] report external temperatures,
+			and temp5 reports the chip temperature.
 			On LTC2978, only one temperature measurement is
-			supported and reflects the internal temperature.
+			supported and reports the chip temperature.
 			On LTC3880, temp1 and temp2 report external
-			temperatures, and temp3 reports the internal
-			temperature.
-temp[1-3]_min		Mimimum temperature.
-temp[1-3]_max		Maximum temperature.
-temp[1-3]_lcrit		Critical low temperature.
-temp[1-3]_crit		Critical high temperature.
-temp[1-3]_min_alarm	Chip temperature low alarm.
-temp[1-3]_max_alarm	Chip temperature high alarm.
-temp[1-3]_lcrit_alarm	Chip temperature critical low alarm.
-temp[1-3]_crit_alarm	Chip temperature critical high alarm.
-temp[1-3]_lowest	Lowest measured temperature. LTC2978 only.
-temp[1-3]_highest	Highest measured temperature.
-temp[1-3]_reset_history	Reset history. Writing into this attribute will reset
-			history for all attributes.
-
-power[1-2]_label	"pout[1-2]". LTC3880 only.
-power[1-2]_input	Measured power.
-
-curr1_label		"iin". LTC3880 only.
+			temperatures, and temp3 reports the chip temperature.
+			On LTC3883, temp1 reports an external temperature,
+			and temp2 reports the chip temperature.
+temp[N]_min		Mimimum temperature. LTC2974 and LTC2978 only.
+temp[N]_max		Maximum temperature.
+temp[N]_lcrit		Critical low temperature.
+temp[N]_crit		Critical high temperature.
+temp[N]_min_alarm	Temperature low alarm. LTC2974 and LTC2978 only.
+temp[N]_max_alarm	Temperature high alarm.
+temp[N]_lcrit_alarm	Temperature critical low alarm.
+temp[N]_crit_alarm	Temperature critical high alarm.
+temp[N]_lowest		Lowest measured temperature. LTC2974 and LTC2978 only.
+			Not supported for chip temperature sensor on LTC2974.
+temp[N]_highest		Highest measured temperature. Not supported for chip
+			temperature sensor on LTC2974.
+temp[N]_reset_history	Reset temperature history. Not supported for chip
+			temperature sensor on LTC2974.
+
+power1_label		"pin". LTC3883 only.
+power1_input		Measured input power.
+
+power[N]_label		"pout[1-4]".
+			LTC2974: N=1-4
+			LTC2978: Not supported
+			LTC3880: N=1-2
+			LTC3883: N=2
+power[N]_input		Measured output power.
+
+curr1_label		"iin". LTC3880 and LTC3883 only.
 curr1_input		Measured input current.
 curr1_max		Maximum input current.
 curr1_max_alarm		Input current high alarm.
-
-curr[2-3]_label		"iout[1-2]". LTC3880 only.
-curr[2-3]_input		Measured input current.
-curr[2-3]_max		Maximum input current.
-curr[2-3]_crit		Critical input current.
-curr[2-3]_max_alarm	Input current high alarm.
-curr[2-3]_crit_alarm	Input current critical high alarm.
+curr1_highest		Highest input current. LTC3883 only.
+curr1_reset_history	Reset input current history. LTC3883 only.
+
+curr[N]_label		"iout[1-4]".
+			LTC2974: N=1-4
+			LTC2978: not supported
+			LTC3880: N=2-3
+			LTC3883: N=2
+curr[N]_input		Measured output current.
+curr[N]_max		Maximum output current.
+curr[N]_crit		Critical high output current.
+curr[N]_lcrit		Critical low output current. LTC2974 only.
+curr[N]_max_alarm	Output current high alarm.
+curr[N]_crit_alarm	Output current critical high alarm.
+curr[N]_lcrit_alarm	Output current critical low alarm. LTC2974 only.
+curr[N]_lowest		Lowest output current. LTC2974 only.
+curr[N]_highest		Highest output current.
+curr[N]_reset_history	Reset output current history.
diff --git a/Documentation/hwmon/nct6775 b/Documentation/hwmon/nct6775
new file mode 100644
index 0000000..4e9ef60
--- /dev/null
+++ b/Documentation/hwmon/nct6775
@@ -0,0 +1,188 @@
+Note
+====
+
+This driver supersedes the NCT6775F and NCT6776F support in the W83627EHF
+driver.
+
+Kernel driver NCT6775
+=====================
+
+Supported chips:
+  * Nuvoton NCT5572D/NCT6771F/NCT6772F/NCT6775F/W83677HG-I
+    Prefix: 'nct6775'
+    Addresses scanned: ISA address retrieved from Super I/O registers
+    Datasheet: Available from Nuvoton upon request
+  * Nuvoton NCT5577D/NCT6776D/NCT6776F
+    Prefix: 'nct6776'
+    Addresses scanned: ISA address retrieved from Super I/O registers
+    Datasheet: Available from Nuvoton upon request
+  * Nuvoton NCT5532D/NCT6779D
+    Prefix: 'nct6779'
+    Addresses scanned: ISA address retrieved from Super I/O registers
+    Datasheet: Available from Nuvoton upon request
+
+Authors:
+        Guenter Roeck <linux@roeck-us.net>
+
+Description
+-----------
+
+This driver implements support for the Nuvoton NCT6775F, NCT6776F, and NCT6779D
+and compatible super I/O chips.
+
+The chips support up to 25 temperature monitoring sources. Up to 6 of those are
+direct temperature sensor inputs, the others are special sources such as PECI,
+PCH, and SMBUS. Depending on the chip type, 2 to 6 of the temperature sources
+can be monitored and compared against minimum, maximum, and critical
+temperatures. The driver reports up to 10 of the temperatures to the user.
+There are 4 to 5 fan rotation speed sensors, 8 to 15 analog voltage sensors,
+one VID, alarms with beep warnings (control unimplemented), and some automatic
+fan regulation strategies (plus manual fan control mode).
+
+The temperature sensor sources on all chips are configurable. The configured
+source for each of the temperature sensors is provided in tempX_label.
+
+Temperatures are measured in degrees Celsius and measurement resolution is
+either 1 degC or 0.5 degC, depending on the temperature source and
+configuration. An alarm is triggered when the temperature gets higher than
+the high limit; it stays on until the temperature falls below the hysteresis
+value. Alarms are only supported for temp1 to temp6, depending on the chip type.
+
+Fan rotation speeds are reported in RPM (rotations per minute). An alarm is
+triggered if the rotation speed has dropped below a programmable limit. On
+NCT6775F, fan readings can be divided by a programmable divider (1, 2, 4, 8,
+16, 32, 64 or 128) to give the readings more range or accuracy; the other chips
+do not have a fan speed divider. The driver sets the most suitable fan divisor
+itself; specifically, it increases the divider value each time a fan speed
+reading returns an invalid value, and it reduces it if the fan speed reading
+is lower than optimal. Some fans might not be present because they share pins
+with other functions.
+
+Voltage sensors (also known as IN sensors) report their values in millivolts.
+An alarm is triggered if the voltage has crossed a programmable minimum
+or maximum limit.
+
+The driver supports automatic fan control mode known as Thermal Cruise.
+In this mode, the chip attempts to keep the measured temperature in a
+predefined temperature range. If the temperature goes out of range, fan
+is driven slower/faster to reach the predefined range again.
+
+The mode works for fan1-fan5.
+
+sysfs attributes
+----------------
+
+pwm[1-5] - this file stores PWM duty cycle or DC value (fan speed) in range:
+	   0 (lowest speed) to 255 (full)
+
+pwm[1-5]_enable - this file controls mode of fan/temperature control:
+	* 0 Fan control disabled (fans set to maximum speed)
+	* 1 Manual mode, write to pwm[0-5] any value 0-255
+	* 2 "Thermal Cruise" mode
+	* 3 "Fan Speed Cruise" mode
+	* 4 "Smart Fan III" mode (NCT6775F only)
+	* 5 "Smart Fan IV" mode
+
+pwm[1-5]_mode - controls if output is PWM or DC level
+        * 0 DC output
+        * 1 PWM output
+
+Common fan control attributes
+-----------------------------
+
+pwm[1-5]_temp_sel	Temperature source. Value is temperature sensor index.
+			For example, select '1' for temp1_input.
+pwm[1-5]_weight_temp_sel
+			Secondary temperature source. Value is temperature
+			sensor index. For example, select '1' for temp1_input.
+			Set to 0 to disable secondary temperature control.
+
+If secondary temperature functionality is enabled, it is controlled with the
+following attributes.
+
+pwm[1-5]_weight_duty_step
+			Duty step size.
+pwm[1-5]_weight_temp_step
+			Temperature step size. With each step over
+			temp_step_base, the value of weight_duty_step is added
+			to the current pwm value.
+pwm[1-5]_weight_temp_step_base
+			Temperature at which secondary temperature control kicks
+			in.
+pwm[1-5]_weight_temp_step_tol
+			Temperature step tolerance.
+
+Thermal Cruise mode (2)
+-----------------------
+
+If the temperature is in the range defined by:
+
+pwm[1-5]_target_temp	Target temperature, unit millidegree Celsius
+			(range 0 - 127000)
+pwm[1-5]_temp_tolerance
+			Target temperature tolerance, unit millidegree Celsius
+
+there are no changes to fan speed. Once the temperature leaves the interval, fan
+speed increases (if temperature is higher that desired) or decreases (if
+temperature is lower than desired), using the following limits and time
+intervals.
+
+pwm[1-5]_start		fan pwm start value (range 1 - 255), to start fan
+			when the temperature is above defined range.
+pwm[1-5]_floor		lowest fan pwm (range 0 - 255) if temperature is below
+			the defined range. If set to 0, the fan is expected to
+			stop if the temperature is below the defined range.
+pwm[1-5]_step_up_time	milliseconds before fan speed is increased
+pwm[1-5]_step_down_time	milliseconds before fan speed is decreased
+pwm[1-5]_stop_time	how many milliseconds must elapse to switch
+			corresponding fan off (when the temperature was below
+			defined range).
+
+Speed Cruise mode (3)
+---------------------
+
+This modes tries to keep the fan speed constant.
+
+fan[1-5]_target		Target fan speed
+fan[1-5]_tolerance
+			Target speed tolerance
+
+
+Untested; use at your own risk.
+
+Smart Fan IV mode (5)
+---------------------
+
+This mode offers multiple slopes to control the fan speed. The slopes can be
+controlled by setting the pwm and temperature attributes. When the temperature
+rises, the chip will calculate the DC/PWM output based on the current slope.
+There are up to seven data points depending on the chip type. Subsequent data
+points should be set to higher temperatures and higher pwm values to achieve
+higher fan speeds with increasing temperature. The last data point reflects
+critical temperature mode, in which the fans should run at full speed.
+
+pwm[1-5]_auto_point[1-7]_pwm
+			pwm value to be set if temperature reaches matching
+			temperature range.
+pwm[1-5]_auto_point[1-7]_temp
+			Temperature over which the matching pwm is enabled.
+pwm[1-5]_temp_tolerance
+			Temperature tolerance, unit millidegree Celsius
+pwm[1-5]_crit_temp_tolerance
+			Temperature tolerance for critical temperature,
+			unit millidegree Celsius
+
+pwm[1-5]_step_up_time	milliseconds before fan speed is increased
+pwm[1-5]_step_down_time	milliseconds before fan speed is decreased
+
+Usage Notes
+-----------
+
+On various ASUS boards with NCT6776F, it appears that CPUTIN is not really
+connected to anything and floats, or that it is connected to some non-standard
+temperature measurement device. As a result, the temperature reported on CPUTIN
+will not reflect a usable value. It often reports unreasonably high
+temperatures, and in some cases the reported temperature declines if the actual
+temperature increases (similar to the raw PECI temperature value - see PECI
+specification for details). CPUTIN should therefore be be ignored on ASUS
+boards. The CPU temperature on ASUS boards is reported from PECI 0.
diff --git a/Documentation/hwmon/tmp401 b/Documentation/hwmon/tmp401
index 9fc4472..12e4781 100644
--- a/Documentation/hwmon/tmp401
+++ b/Documentation/hwmon/tmp401
@@ -8,8 +8,12 @@ Supported chips:
     Datasheet: http://focus.ti.com/docs/prod/folders/print/tmp401.html
   * Texas Instruments TMP411
     Prefix: 'tmp411'
-    Addresses scanned: I2C 0x4c
+    Addresses scanned: I2C 0x4c, 0x4d, 0x4e
     Datasheet: http://focus.ti.com/docs/prod/folders/print/tmp411.html
+  * Texas Instruments TMP431
+    Prefix: 'tmp431'
+    Addresses scanned: I2C 0x4c, 0x4d
+    Datasheet: http://focus.ti.com/docs/prod/folders/print/tmp431.html
 
 Authors:
          Hans de Goede <hdegoede@redhat.com>
@@ -18,8 +22,8 @@ Authors:
 Description
 -----------
 
-This driver implements support for Texas Instruments TMP401 and
-TMP411 chips. These chips implements one remote and one local
+This driver implements support for Texas Instruments TMP401, TMP411,
+and TMP431 chips. These chips implement one remote and one local
 temperature sensor. Temperature is measured in degrees
 Celsius. Resolution of the remote sensor is 0.0625 degree. Local
 sensor resolution can be set to 0.5, 0.25, 0.125 or 0.0625 degree (not
@@ -27,10 +31,10 @@ supported by the driver so far, so using the default resolution of 0.5
 degree).
 
 The driver provides the common sysfs-interface for temperatures (see
-/Documentation/hwmon/sysfs-interface under Temperatures).
+Documentation/hwmon/sysfs-interface under Temperatures).
 
-The TMP411 chip is compatible with TMP401. It provides some additional
-features.
+The TMP411 and TMP431 chips are compatible with TMP401. TMP411 provides
+some additional features.
 
 * Minimum and Maximum temperature measured since power-on, chip-reset
 
diff --git a/Documentation/ia64/err_inject.txt b/Documentation/ia64/err_inject.txt
index 223e4f0..9f651c1 100644
--- a/Documentation/ia64/err_inject.txt
+++ b/Documentation/ia64/err_inject.txt
@@ -882,7 +882,7 @@ int err_inj()
 			cpu=parameters[i].cpu;
 			k = cpu%64;
 			j = cpu/64;
-			mask[j]=1<<k;
+			mask[j] = 1UL << k;
 
 			if (sched_setaffinity(0, MASK_SIZE*8, mask)==-1) {
 				perror("Error sched_setaffinity:");
diff --git a/Documentation/ioctl/ioctl-number.txt b/Documentation/ioctl/ioctl-number.txt
index 3210540..237acab 100644
--- a/Documentation/ioctl/ioctl-number.txt
+++ b/Documentation/ioctl/ioctl-number.txt
@@ -131,6 +131,7 @@ Code  Seq#(hex)	Include File		Comments
 'H'	40-4F	sound/hdspm.h		conflict!
 'H'	40-4F	sound/hdsp.h		conflict!
 'H'	90	sound/usb/usx2y/usb_stream.h
+'H'	A0	uapi/linux/usb/cdc-wdm.h
 'H'	C0-F0	net/bluetooth/hci.h	conflict!
 'H'	C0-DF	net/bluetooth/hidp/hidp.h	conflict!
 'H'	C0-DF	net/bluetooth/cmtp/cmtp.h	conflict!
diff --git a/Documentation/kdump/kdump.txt b/Documentation/kdump/kdump.txt
index 13f1aa0..9c7fd988 100644
--- a/Documentation/kdump/kdump.txt
+++ b/Documentation/kdump/kdump.txt
@@ -297,6 +297,7 @@ Boot into System Kernel
    On ia64, 256M@256M is a generous value that typically works.
    The region may be automatically placed on ia64, see the
    dump-capture kernel config option notes above.
+   If use sparse memory, the size should be rounded to GRANULE boundaries.
 
    On s390x, typically use "crashkernel=xxM". The value of xx is dependent
    on the memory consumption of the kdump system. In general this is not
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 4609e81..12c42a5 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -320,6 +320,13 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 			on: enable for both 32- and 64-bit processes
 			off: disable for both 32- and 64-bit processes
 
+	alloc_snapshot	[FTRACE]
+			Allocate the ftrace snapshot buffer on boot up when the
+			main buffer is allocated. This is handy if debugging
+			and you need to use tracing_snapshot() on boot up, and
+			do not want to use tracing_snapshot_alloc() as it needs
+			to be done where GFP_KERNEL allocations are allowed.
+
 	amd_iommu=	[HW,X86-64]
 			Pass parameters to the AMD IOMMU driver in the system.
 			Possible values are:
@@ -1625,7 +1632,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 	module.sig_enforce
 			[KNL] When CONFIG_MODULE_SIG is set, this means that
 			modules without (valid) signatures will fail to load.
-			Note that if CONFIG_MODULE_SIG_ENFORCE is set, that
+			Note that if CONFIG_MODULE_SIG_FORCE is set, that
 			is always true, so this option does nothing.
 
 	mousedev.tap_time=
@@ -1974,8 +1981,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 	noreplace-smp	[X86-32,SMP] Don't replace SMP instructions
 			with UP alternatives
 
-	noresidual	[PPC] Don't use residual data on PReP machines.
-
 	nordrand	[X86] Disable the direct use of the RDRAND
 			instruction even if it is supported by the
 			processor.  RDRAND is still available to user
@@ -2461,9 +2466,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 			In kernels built with CONFIG_RCU_NOCB_CPU=y, set
 			the specified list of CPUs to be no-callback CPUs.
 			Invocation of these CPUs' RCU callbacks will
-			be offloaded to "rcuoN" kthreads created for
-			that purpose.  This reduces OS jitter on the
+			be offloaded to "rcuox/N" kthreads created for
+			that purpose, where "x" is "b" for RCU-bh, "p"
+			for RCU-preempt, and "s" for RCU-sched, and "N"
+			is the CPU number.  This reduces OS jitter on the
 			offloaded CPUs, which can be useful for HPC and
+
 			real-time workloads.  It can also improve energy
 			efficiency for asymmetric multiprocessors.
 
@@ -2487,6 +2495,17 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 			leaf rcu_node structure.  Useful for very large
 			systems.
 
+	rcutree.jiffies_till_first_fqs= [KNL,BOOT]
+			Set delay from grace-period initialization to
+			first attempt to force quiescent states.
+			Units are jiffies, minimum value is zero,
+			and maximum value is HZ.
+
+	rcutree.jiffies_till_next_fqs= [KNL,BOOT]
+			Set delay between subsequent attempts to force
+			quiescent states.  Units are jiffies, minimum
+			value is one, and maximum value is HZ.
+
 	rcutree.qhimark=	[KNL,BOOT]
 			Set threshold of queued
 			RCU callbacks over which batch limiting is disabled.
@@ -2501,16 +2520,15 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 	rcutree.rcu_cpu_stall_timeout= [KNL,BOOT]
 			Set timeout for RCU CPU stall warning messages.
 
-	rcutree.jiffies_till_first_fqs= [KNL,BOOT]
-			Set delay from grace-period initialization to
-			first attempt to force quiescent states.
-			Units are jiffies, minimum value is zero,
-			and maximum value is HZ.
+	rcutree.rcu_idle_gp_delay=	[KNL,BOOT]
+			Set wakeup interval for idle CPUs that have
+			RCU callbacks (RCU_FAST_NO_HZ=y).
 
-	rcutree.jiffies_till_next_fqs= [KNL,BOOT]
-			Set delay between subsequent attempts to force
-			quiescent states.  Units are jiffies, minimum
-			value is one, and maximum value is HZ.
+	rcutree.rcu_idle_lazy_gp_delay=	[KNL,BOOT]
+			Set wakeup interval for idle CPUs that have
+			only "lazy" RCU callbacks (RCU_FAST_NO_HZ=y).
+			Lazy RCU callbacks are those which RCU can
+			prove do nothing more than free memory.
 
 	rcutorture.fqs_duration= [KNL,BOOT]
 			Set duration of force_quiescent_state bursts.
@@ -3222,6 +3240,15 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 			or other driver-specific files in the
 			Documentation/watchdog/ directory.
 
+	workqueue.disable_numa
+			By default, all work items queued to unbound
+			workqueues are affine to the NUMA nodes they're
+			issued on, which results in better behavior in
+			general.  If NUMA affinity needs to be disabled for
+			whatever reason, this option can be used.  Note
+			that this also can be controlled per-workqueue for
+			workqueues visible under /sys/bus/workqueue/.
+
 	x2apic_phys	[X86-64,APIC] Use x2apic physical mode instead of
 			default x2apic cluster mode on platforms
 			supporting x2apic.
diff --git a/Documentation/leds/00-INDEX b/Documentation/leds/00-INDEX
index 5246090..1ecd159 100644
--- a/Documentation/leds/00-INDEX
+++ b/Documentation/leds/00-INDEX
@@ -6,6 +6,8 @@ leds-lp5521.txt
 	- notes on how to use the leds-lp5521 driver.
 leds-lp5523.txt
 	- notes on how to use the leds-lp5523 driver.
+leds-lp5562.txt
+	- notes on how to use the leds-lp5562 driver.
 leds-lp55xx.txt
 	- description about lp55xx common driver.
 leds-lm3556.txt
diff --git a/Documentation/leds/leds-lp5521.txt b/Documentation/leds/leds-lp5521.txt
index 270f571..79e4c2e 100644
--- a/Documentation/leds/leds-lp5521.txt
+++ b/Documentation/leds/leds-lp5521.txt
@@ -81,22 +81,3 @@ static struct lp55xx_platform_data lp5521_platform_data = {
 
 If the current is set to 0 in the platform data, that channel is
 disabled and it is not visible in the sysfs.
-
-The 'update_config' : CONFIG register (ADDR 08h)
-This value is platform-specific data.
-If update_config is not defined, the CONFIG register is set with
-'LP5521_PWRSAVE_EN | LP5521_CP_MODE_AUTO | LP5521_R_TO_BATT'.
-(Enable auto-powersave, set charge pump to auto, red to battery)
-
-example of update_config :
-
-#define LP5521_CONFIGS	(LP5521_PWM_HF | LP5521_PWRSAVE_EN | \
-			LP5521_CP_MODE_AUTO | LP5521_R_TO_BATT | \
-			LP5521_CLK_INT)
-
-static struct lp55xx_platform_data lp5521_pdata = {
-	.led_config = lp5521_led_config,
-	.num_channels = ARRAY_SIZE(lp5521_led_config),
-	.clock_mode = LP55XX_CLOCK_INT,
-	.update_config = LP5521_CONFIGS,
-};
diff --git a/Documentation/leds/leds-lp5562.txt b/Documentation/leds/leds-lp5562.txt
new file mode 100644
index 0000000..5a823ff
--- /dev/null
+++ b/Documentation/leds/leds-lp5562.txt
@@ -0,0 +1,120 @@
+Kernel driver for LP5562
+========================
+
+* TI LP5562 LED Driver
+
+Author: Milo(Woogyom) Kim <milo.kim@ti.com>
+
+Description
+
+  LP5562 can drive up to 4 channels. R/G/B and White.
+  LEDs can be controlled directly via the led class control interface.
+
+  All four channels can be also controlled using the engine micro programs.
+  LP5562 has the internal program memory for running various LED patterns.
+  For the details, please refer to 'firmware' section in leds-lp55xx.txt
+
+Device attribute: engine_mux
+
+  3 Engines are allocated in LP5562, but the number of channel is 4.
+  Therefore each channel should be mapped to the engine number.
+  Value : RGB or W
+
+  This attribute is used for programming LED data with the firmware interface.
+  Unlike the LP5521/LP5523/55231, LP5562 has unique feature for the engine mux,
+  so additional sysfs is required.
+
+  LED Map
+  Red   ... Engine 1 (fixed)
+  Green ... Engine 2 (fixed)
+  Blue  ... Engine 3 (fixed)
+  White ... Engine 1 or 2 or 3 (selective)
+
+How to load the program data using engine_mux
+
+  Before loading the LP5562 program data, engine_mux should be written between
+  the engine selection and loading the firmware.
+  Engine mux has two different mode, RGB and W.
+  RGB is used for loading RGB program data, W is used for W program data.
+
+  For example, run blinking green channel pattern,
+  echo 2 > /sys/bus/i2c/devices/xxxx/select_engine     # 2 is for green channel
+  echo "RGB" > /sys/bus/i2c/devices/xxxx/engine_mux    # engine mux for RGB
+  echo 1 > /sys/class/firmware/lp5562/loading
+  echo "4000600040FF6000" > /sys/class/firmware/lp5562/data
+  echo 0 > /sys/class/firmware/lp5562/loading
+  echo 1 > /sys/bus/i2c/devices/xxxx/run_engine
+
+  To run a blinking white pattern,
+  echo 1 or 2 or 3 > /sys/bus/i2c/devices/xxxx/select_engine
+  echo "W" > /sys/bus/i2c/devices/xxxx/engine_mux
+  echo 1 > /sys/class/firmware/lp5562/loading
+  echo "4000600040FF6000" > /sys/class/firmware/lp5562/data
+  echo 0 > /sys/class/firmware/lp5562/loading
+  echo 1 > /sys/bus/i2c/devices/xxxx/run_engine
+
+How to load the predefined patterns
+
+  Please refer to 'leds-lp55xx.txt"
+
+Setting Current of Each Channel
+
+  Like LP5521 and LP5523/55231, LP5562 provides LED current settings.
+  The 'led_current' and 'max_current' are used.
+
+(Example of Platform data)
+
+To configure the platform specific data, lp55xx_platform_data structure is used.
+
+static struct lp55xx_led_config lp5562_led_config[] = {
+	{
+		.name 		= "R",
+		.chan_nr	= 0,
+		.led_current	= 20,
+		.max_current	= 40,
+	},
+	{
+		.name 		= "G",
+		.chan_nr	= 1,
+		.led_current	= 20,
+		.max_current	= 40,
+	},
+	{
+		.name 		= "B",
+		.chan_nr	= 2,
+		.led_current	= 20,
+		.max_current	= 40,
+	},
+	{
+		.name 		= "W",
+		.chan_nr	= 3,
+		.led_current	= 20,
+		.max_current	= 40,
+	},
+};
+
+static int lp5562_setup(void)
+{
+	/* setup HW resources */
+}
+
+static void lp5562_release(void)
+{
+	/* Release HW resources */
+}
+
+static void lp5562_enable(bool state)
+{
+	/* Control of chip enable signal */
+}
+
+static struct lp55xx_platform_data lp5562_platform_data = {
+        .led_config     = lp5562_led_config,
+        .num_channels   = ARRAY_SIZE(lp5562_led_config),
+        .setup_resources   = lp5562_setup,
+        .release_resources = lp5562_release,
+        .enable            = lp5562_enable,
+};
+
+If the current is set to 0 in the platform data, that channel is
+disabled and it is not visible in the sysfs.
diff --git a/Documentation/leds/leds-lp55xx.txt b/Documentation/leds/leds-lp55xx.txt
index ced4186..eec8fa2 100644
--- a/Documentation/leds/leds-lp55xx.txt
+++ b/Documentation/leds/leds-lp55xx.txt
@@ -5,7 +5,7 @@ Authors: Milo(Woogyom) Kim <milo.kim@ti.com>
 
 Description
 -----------
-LP5521, LP5523/55231 have common features as below.
+LP5521, LP5523/55231 and LP5562 have common features as below.
 
   Register access via the I2C
   Device initialization/deinitialization
@@ -116,3 +116,47 @@ To support this, 'run_engine' and 'firmware_cb' are configurable in each driver.
 run_engine  : Control the selected engine
 firmware_cb : The callback function after loading the firmware is done.
               Chip specific commands for loading and updating program memory.
+
+( Predefined pattern data )
+
+Without the firmware interface, LP55xx driver provides another method for
+loading a LED pattern. That is 'predefined' pattern.
+A predefined pattern is defined in the platform data and load it(or them)
+via the sysfs if needed.
+To use the predefined pattern concept, 'patterns' and 'num_patterns' should be
+configured.
+
+  Example of predefined pattern data:
+
+  /* mode_1: blinking data */
+  static const u8 mode_1[] = {
+		0x40, 0x00, 0x60, 0x00, 0x40, 0xFF, 0x60, 0x00,
+		};
+
+  /* mode_2: always on */
+  static const u8 mode_2[] = { 0x40, 0xFF, };
+
+  struct lp55xx_predef_pattern board_led_patterns[] = {
+	{
+		.r = mode_1,
+		.size_r = ARRAY_SIZE(mode_1),
+	},
+	{
+		.b = mode_2,
+		.size_b = ARRAY_SIZE(mode_2),
+	},
+  }
+
+  struct lp55xx_platform_data lp5562_pdata = {
+  ...
+	.patterns      = board_led_patterns,
+	.num_patterns  = ARRAY_SIZE(board_led_patterns),
+  };
+
+Then, mode_1 and mode_2 can be run via through the sysfs.
+
+  echo 1 > /sys/bus/i2c/devices/xxxx/led_pattern    # red blinking LED pattern
+  echo 2 > /sys/bus/i2c/devices/xxxx/led_pattern    # blue LED always on
+
+To stop running pattern,
+  echo 0 > /sys/bus/i2c/devices/xxxx/led_pattern
diff --git a/Documentation/md.txt b/Documentation/md.txt
index 993fba3..e0ddd32 100644
--- a/Documentation/md.txt
+++ b/Documentation/md.txt
@@ -119,7 +119,7 @@ device to add.
 The array is started with the RUN_ARRAY ioctl.
 
 Once started, new devices can be added.  They should have an
-appropriate superblock written to them, and then passed be in with
+appropriate superblock written to them, and then be passed in with
 ADD_NEW_DISK.
 
 Devices that have failed or are not yet active can be detached from an
@@ -131,7 +131,7 @@ Specific Rules that apply to format-0 super block arrays, and
 -------------------------------------------------------------
 
 An array can be 'created' by describing the array (level, chunksize
-etc) in a SET_ARRAY_INFO ioctl.  This must has major_version==0 and
+etc) in a SET_ARRAY_INFO ioctl.  This must have major_version==0 and
 raid_disks != 0.
 
 Then uninitialized devices can be added with ADD_NEW_DISK.  The
@@ -426,7 +426,7 @@ Each directory contains:
       offset
         This gives the location in the device (in sectors from the
         start) where data from the array will be stored.  Any part of
-        the device before this offset us not touched, unless it is
+        the device before this offset is not touched, unless it is
         used for storing metadata (Formats 1.1 and 1.2).
 
       size
@@ -440,7 +440,7 @@ Each directory contains:
         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
-	operation is will steadily increase, and if the recovery is
+	operation it will steadily increase, and if the recovery is
 	interrupted, restoring this value can cause recovery to
 	avoid repeating the earlier blocks.  With v1.x metadata, this
 	value is saved and restored automatically.
@@ -468,7 +468,7 @@ Each directory contains:
 
 
 
-An active md device will also contain and entry for each active device
+An active md device will also contain an entry for each active device
 in the array.  These are named
 
     rdNN
@@ -482,7 +482,7 @@ will show 'in_sync' on every line.
 
 
 
-Active md devices for levels that support data redundancy (1,4,5,6)
+Active md devices for levels that support data redundancy (1,4,5,6,10)
 also have
 
    sync_action
@@ -494,7 +494,7 @@ also have
                        failed/missing device
        idle          - nothing is happening
        check         - A full check of redundancy was requested and is
-                       happening.  This reads all block and checks
+                       happening.  This reads all blocks and checks
                        them. A repair may also happen for some raid
                        levels.
        repair        - A full check and repair is happening.  This is
@@ -522,7 +522,7 @@ also have
 
    degraded
       This contains a count of the number of devices by which the
-      arrays is degraded.  So an optimal array with show '0'.  A
+      arrays is degraded.  So an optimal array will show '0'.  A
       single failed/missing drive will show '1', etc.
       This file responds to select/poll, any increase or decrease
       in the count of missing devices will trigger an event.
diff --git a/Documentation/misc-devices/mei/mei-client-bus.txt b/Documentation/misc-devices/mei/mei-client-bus.txt
new file mode 100644
index 0000000..9dc5ebf
--- /dev/null
+++ b/Documentation/misc-devices/mei/mei-client-bus.txt
@@ -0,0 +1,135 @@
+Intel(R) Management Engine (ME) Client bus API
+===============================================
+
+
+Rationale
+=========
+MEI misc character device is useful for dedicated applications to send and receive
+data to the many FW appliance found in Intel's ME from the user space.
+However for some of the ME functionalities it make sense to leverage existing software
+stack and expose them through existing kernel subsystems.
+
+In order to plug seamlessly into the kernel device driver model we add kernel virtual
+bus abstraction on top of the MEI driver. This allows implementing linux kernel drivers
+for the various MEI features as a stand alone entities found in their respective subsystem.
+Existing device drivers can even potentially be re-used by adding an MEI CL bus layer to
+the existing code.
+
+
+MEI CL bus API
+===========
+A driver implementation for an MEI Client is very similar to existing bus
+based device drivers. The driver registers itself as an MEI CL bus driver through
+the mei_cl_driver structure:
+
+struct mei_cl_driver {
+	struct device_driver driver;
+	const char *name;
+
+	const struct mei_cl_device_id *id_table;
+
+	int (*probe)(struct mei_cl_device *dev, const struct mei_cl_id *id);
+	int (*remove)(struct mei_cl_device *dev);
+};
+
+struct mei_cl_id {
+	char name[MEI_NAME_SIZE];
+	kernel_ulong_t driver_info;
+};
+
+The mei_cl_id structure allows the driver to bind itself against a device name.
+
+To actually register a driver on the ME Client bus one must call the mei_cl_add_driver()
+API. This is typically called at module init time.
+
+Once registered on the ME Client bus, a driver will typically try to do some I/O on
+this bus and this should be done through the mei_cl_send() and mei_cl_recv()
+routines. The latter is synchronous (blocks and sleeps until data shows up).
+In order for drivers to be notified of pending events waiting for them (e.g.
+an Rx event) they can register an event handler through the
+mei_cl_register_event_cb() routine. Currently only the MEI_EVENT_RX event
+will trigger an event handler call and the driver implementation is supposed
+to call mei_recv() from the event handler in order to fetch the pending
+received buffers.
+
+
+Example
+=======
+As a theoretical example let's pretend the ME comes with a "contact" NFC IP.
+The driver init and exit routines for this device would look like:
+
+#define CONTACT_DRIVER_NAME "contact"
+
+static struct mei_cl_device_id contact_mei_cl_tbl[] = {
+	{ CONTACT_DRIVER_NAME, },
+
+	/* required last entry */
+	{ }
+};
+MODULE_DEVICE_TABLE(mei_cl, contact_mei_cl_tbl);
+
+static struct mei_cl_driver contact_driver = {
+       .id_table = contact_mei_tbl,
+       .name = CONTACT_DRIVER_NAME,
+
+       .probe = contact_probe,
+       .remove = contact_remove,
+};
+
+static int contact_init(void)
+{
+	int r;
+
+	r = mei_cl_driver_register(&contact_driver);
+	if (r) {
+		pr_err(CONTACT_DRIVER_NAME ": driver registration failed\n");
+		return r;
+	}
+
+	return 0;
+}
+
+static void __exit contact_exit(void)
+{
+	mei_cl_driver_unregister(&contact_driver);
+}
+
+module_init(contact_init);
+module_exit(contact_exit);
+
+And the driver's simplified probe routine would look like that:
+
+int contact_probe(struct mei_cl_device *dev, struct mei_cl_device_id *id)
+{
+	struct contact_driver *contact;
+
+	[...]
+	mei_cl_register_event_cb(dev, contact_event_cb, contact);
+
+	return 0;
+ }
+
+In the probe routine the driver basically registers an ME bus event handler
+which is as close as it can get to registering a threaded IRQ handler.
+The handler implementation will typically call some I/O routine depending on
+the pending events:
+
+#define MAX_NFC_PAYLOAD 128
+
+static void contact_event_cb(struct mei_cl_device *dev, u32 events,
+			     void *context)
+{
+	struct contact_driver *contact = context;
+
+	if (events & BIT(MEI_EVENT_RX)) {
+		u8 payload[MAX_NFC_PAYLOAD];
+		int payload_size;
+
+		payload_size = mei_recv(dev, payload, MAX_NFC_PAYLOAD);
+		if (payload_size <= 0)
+			return;
+
+		/* Hook to the NFC subsystem */
+		nfc_hci_recv_frame(contact->hdev, payload, payload_size);
+	}
+}
diff --git a/Documentation/mmc/mmc-dev-attrs.txt b/Documentation/mmc/mmc-dev-attrs.txt
index 0d98fac..189bab0 100644
--- a/Documentation/mmc/mmc-dev-attrs.txt
+++ b/Documentation/mmc/mmc-dev-attrs.txt
@@ -22,6 +22,7 @@ All attributes are read-only.
 	manfid			Manufacturer ID (from CID Register)
 	name			Product Name (from CID Register)
 	oemid			OEM/Application ID (from CID Register)
+	prv			Product Revision (from CID Register) (SD and MMCv4 only)
 	serial			Product Serial Number (from CID Register)
 	erase_size		Erase group size
 	preferred_erase_size	Preferred erase size
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index dc2dc87..f98ca63 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -29,7 +29,7 @@ route/max_size - INTEGER
 neigh/default/gc_thresh1 - INTEGER
 	Minimum number of entries to keep.  Garbage collector will not
 	purge entries if there are fewer than this number.
-	Default: 256
+	Default: 128
 
 neigh/default/gc_thresh3 - INTEGER
 	Maximum number of neighbor entries allowed.  Increase this
@@ -175,14 +175,6 @@ tcp_congestion_control - STRING
 	is inherited.
 	[see setsockopt(listenfd, SOL_TCP, TCP_CONGESTION, "name" ...) ]
 
-tcp_cookie_size - INTEGER
-	Default size of TCP Cookie Transactions (TCPCT) option, that may be
-	overridden on a per socket basis by the TCPCT socket option.
-	Values greater than the maximum (16) are interpreted as the maximum.
-	Values greater than zero and less than the minimum (8) are interpreted
-	as the minimum.  Odd values are interpreted as the next even value.
-	Default: 0 (off).
-
 tcp_dsack - BOOLEAN
 	Allows TCP to send "duplicate" SACKs.
 
@@ -190,7 +182,9 @@ tcp_early_retrans - INTEGER
 	Enable Early Retransmit (ER), per RFC 5827. ER lowers the threshold
 	for triggering fast retransmit when the amount of outstanding data is
 	small and when no previously unsent data can be transmitted (such
-	that limited transmit could be used).
+	that limited transmit could be used). Also controls the use of
+	Tail loss probe (TLP) that converts RTOs occuring due to tail
+	losses into fast recovery (draft-dukkipati-tcpm-tcp-loss-probe-01).
 	Possible values:
 		0 disables ER
 		1 enables ER
@@ -198,7 +192,9 @@ tcp_early_retrans - INTEGER
 		  by a fourth of RTT. This mitigates connection falsely
 		  recovers when network has a small degree of reordering
 		  (less than 3 packets).
-	Default: 2
+		3 enables delayed ER and TLP.
+		4 enables TLP only.
+	Default: 3
 
 tcp_ecn - INTEGER
 	Control use of Explicit Congestion Notification (ECN) by TCP.
@@ -229,36 +225,13 @@ tcp_fin_timeout - INTEGER
 	Default: 60 seconds
 
 tcp_frto - INTEGER
-	Enables Forward RTO-Recovery (F-RTO) defined in RFC4138.
+	Enables Forward RTO-Recovery (F-RTO) defined in RFC5682.
 	F-RTO is an enhanced recovery algorithm for TCP retransmission
-	timeouts.  It is particularly beneficial in wireless environments
-	where packet loss is typically due to random radio interference
-	rather than intermediate router congestion.  F-RTO is sender-side
-	only modification. Therefore it does not require any support from
-	the peer.
-
-	If set to 1, basic version is enabled.  2 enables SACK enhanced
-	F-RTO if flow uses SACK.  The basic version can be used also when
-	SACK is in use though scenario(s) with it exists where F-RTO
-	interacts badly with the packet counting of the SACK enabled TCP
-	flow.
-
-tcp_frto_response - INTEGER
-	When F-RTO has detected that a TCP retransmission timeout was
-	spurious (i.e, the timeout would have been avoided had TCP set a
-	longer retransmission timeout), TCP has several options what to do
-	next. Possible values are:
-		0 Rate halving based; a smooth and conservative response,
-		  results in halved cwnd and ssthresh after one RTT
-		1 Very conservative response; not recommended because even
-		  though being valid, it interacts poorly with the rest of
-		  Linux TCP, halves cwnd and ssthresh immediately
-		2 Aggressive response; undoes congestion control measures
-		  that are now known to be unnecessary (ignoring the
-		  possibility of a lost retransmission that would require
-		  TCP to be more cautious), cwnd and ssthresh are restored
-		  to the values prior timeout
-	Default: 0 (rate halving based)
+	timeouts.  It is particularly beneficial in networks where the
+	RTT fluctuates (e.g., wireless). F-RTO is sender-side only
+	modification. It does not require any support from the peer.
+
+	By default it's enabled with a non-zero value. 0 disables F-RTO.
 
 tcp_keepalive_time - INTEGER
 	How often TCP sends out keepalive messages when keepalive is enabled.
diff --git a/Documentation/networking/packet_mmap.txt b/Documentation/networking/packet_mmap.txt
index 94444b1..65efb85 100644
--- a/Documentation/networking/packet_mmap.txt
+++ b/Documentation/networking/packet_mmap.txt
@@ -685,6 +685,333 @@ int main(int argc, char **argp)
 }
 
 -------------------------------------------------------------------------------
++ AF_PACKET TPACKET_V3 example
+-------------------------------------------------------------------------------
+
+AF_PACKET's TPACKET_V3 ring buffer can be configured to use non-static frame
+sizes by doing it's own memory management. It is based on blocks where polling
+works on a per block basis instead of per ring as in TPACKET_V2 and predecessor.
+
+It is said that TPACKET_V3 brings the following benefits:
+ *) ~15 - 20% reduction in CPU-usage
+ *) ~20% increase in packet capture rate
+ *) ~2x increase in packet density
+ *) Port aggregation analysis
+ *) Non static frame size to capture entire packet payload
+
+So it seems to be a good candidate to be used with packet fanout.
+
+Minimal example code by Daniel Borkmann based on Chetan Loke's lolpcap (compile
+it with gcc -Wall -O2 blob.c, and try things like "./a.out eth0", etc.):
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <assert.h>
+#include <net/if.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <poll.h>
+#include <unistd.h>
+#include <signal.h>
+#include <inttypes.h>
+#include <sys/socket.h>
+#include <sys/mman.h>
+#include <linux/if_packet.h>
+#include <linux/if_ether.h>
+#include <linux/ip.h>
+
+#define BLOCK_SIZE		(1 << 22)
+#define FRAME_SIZE		2048
+
+#define NUM_BLOCKS		64
+#define NUM_FRAMES		((BLOCK_SIZE * NUM_BLOCKS) / FRAME_SIZE)
+
+#define BLOCK_RETIRE_TOV_IN_MS	64
+#define BLOCK_PRIV_AREA_SZ	13
+
+#define ALIGN_8(x)		(((x) + 8 - 1) & ~(8 - 1))
+
+#define BLOCK_STATUS(x)		((x)->h1.block_status)
+#define BLOCK_NUM_PKTS(x)	((x)->h1.num_pkts)
+#define BLOCK_O2FP(x)		((x)->h1.offset_to_first_pkt)
+#define BLOCK_LEN(x)		((x)->h1.blk_len)
+#define BLOCK_SNUM(x)		((x)->h1.seq_num)
+#define BLOCK_O2PRIV(x)		((x)->offset_to_priv)
+#define BLOCK_PRIV(x)		((void *) ((uint8_t *) (x) + BLOCK_O2PRIV(x)))
+#define BLOCK_HDR_LEN		(ALIGN_8(sizeof(struct block_desc)))
+#define BLOCK_PLUS_PRIV(sz_pri)	(BLOCK_HDR_LEN + ALIGN_8((sz_pri)))
+
+#ifndef likely
+# define likely(x)		__builtin_expect(!!(x), 1)
+#endif
+#ifndef unlikely
+# define unlikely(x)		__builtin_expect(!!(x), 0)
+#endif
+
+struct block_desc {
+	uint32_t version;
+	uint32_t offset_to_priv;
+	struct tpacket_hdr_v1 h1;
+};
+
+struct ring {
+	struct iovec *rd;
+	uint8_t *map;
+	struct tpacket_req3 req;
+};
+
+static unsigned long packets_total = 0, bytes_total = 0;
+static sig_atomic_t sigint = 0;
+
+void sighandler(int num)
+{
+	sigint = 1;
+}
+
+static int setup_socket(struct ring *ring, char *netdev)
+{
+	int err, i, fd, v = TPACKET_V3;
+	struct sockaddr_ll ll;
+
+	fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
+	if (fd < 0) {
+		perror("socket");
+		exit(1);
+	}
+
+	err = setsockopt(fd, SOL_PACKET, PACKET_VERSION, &v, sizeof(v));
+	if (err < 0) {
+		perror("setsockopt");
+		exit(1);
+	}
+
+	memset(&ring->req, 0, sizeof(ring->req));
+	ring->req.tp_block_size = BLOCK_SIZE;
+	ring->req.tp_frame_size = FRAME_SIZE;
+	ring->req.tp_block_nr = NUM_BLOCKS;
+	ring->req.tp_frame_nr = NUM_FRAMES;
+	ring->req.tp_retire_blk_tov = BLOCK_RETIRE_TOV_IN_MS;
+	ring->req.tp_sizeof_priv = BLOCK_PRIV_AREA_SZ;
+	ring->req.tp_feature_req_word |= TP_FT_REQ_FILL_RXHASH;
+
+	err = setsockopt(fd, SOL_PACKET, PACKET_RX_RING, &ring->req,
+			 sizeof(ring->req));
+	if (err < 0) {
+		perror("setsockopt");
+		exit(1);
+	}
+
+	ring->map = mmap(NULL, ring->req.tp_block_size * ring->req.tp_block_nr,
+			 PROT_READ | PROT_WRITE, MAP_SHARED | MAP_LOCKED,
+			 fd, 0);
+	if (ring->map == MAP_FAILED) {
+		perror("mmap");
+		exit(1);
+	}
+
+	ring->rd = malloc(ring->req.tp_block_nr * sizeof(*ring->rd));
+	assert(ring->rd);
+	for (i = 0; i < ring->req.tp_block_nr; ++i) {
+		ring->rd[i].iov_base = ring->map + (i * ring->req.tp_block_size);
+		ring->rd[i].iov_len = ring->req.tp_block_size;
+	}
+
+	memset(&ll, 0, sizeof(ll));
+	ll.sll_family = PF_PACKET;
+	ll.sll_protocol = htons(ETH_P_ALL);
+	ll.sll_ifindex = if_nametoindex(netdev);
+	ll.sll_hatype = 0;
+	ll.sll_pkttype = 0;
+	ll.sll_halen = 0;
+
+	err = bind(fd, (struct sockaddr *) &ll, sizeof(ll));
+	if (err < 0) {
+		perror("bind");
+		exit(1);
+	}
+
+	return fd;
+}
+
+#ifdef __checked
+static uint64_t prev_block_seq_num = 0;
+
+void assert_block_seq_num(struct block_desc *pbd)
+{
+	if (unlikely(prev_block_seq_num + 1 != BLOCK_SNUM(pbd))) {
+		printf("prev_block_seq_num:%"PRIu64", expected seq:%"PRIu64" != "
+		       "actual seq:%"PRIu64"\n", prev_block_seq_num,
+		       prev_block_seq_num + 1, (uint64_t) BLOCK_SNUM(pbd));
+		exit(1);
+	}
+
+	prev_block_seq_num = BLOCK_SNUM(pbd);
+}
+
+static void assert_block_len(struct block_desc *pbd, uint32_t bytes, int block_num)
+{
+	if (BLOCK_NUM_PKTS(pbd)) {
+		if (unlikely(bytes != BLOCK_LEN(pbd))) {
+			printf("block:%u with %upackets, expected len:%u != actual len:%u\n",
+			       block_num, BLOCK_NUM_PKTS(pbd), bytes, BLOCK_LEN(pbd));
+			exit(1);
+		}
+	} else {
+		if (unlikely(BLOCK_LEN(pbd) != BLOCK_PLUS_PRIV(BLOCK_PRIV_AREA_SZ))) {
+			printf("block:%u, expected len:%lu != actual len:%u\n",
+			       block_num, BLOCK_HDR_LEN, BLOCK_LEN(pbd));
+			exit(1);
+		}
+	}
+}
+
+static void assert_block_header(struct block_desc *pbd, const int block_num)
+{
+	uint32_t block_status = BLOCK_STATUS(pbd);
+
+	if (unlikely((block_status & TP_STATUS_USER) == 0)) {
+		printf("block:%u, not in TP_STATUS_USER\n", block_num);
+		exit(1);
+	}
+
+	assert_block_seq_num(pbd);
+}
+#else
+static inline void assert_block_header(struct block_desc *pbd, const int block_num)
+{
+}
+static void assert_block_len(struct block_desc *pbd, uint32_t bytes, int block_num)
+{
+}
+#endif
+
+static void display(struct tpacket3_hdr *ppd)
+{
+	struct ethhdr *eth = (struct ethhdr *) ((uint8_t *) ppd + ppd->tp_mac);
+	struct iphdr *ip = (struct iphdr *) ((uint8_t *) eth + ETH_HLEN);
+
+	if (eth->h_proto == htons(ETH_P_IP)) {
+		struct sockaddr_in ss, sd;
+		char sbuff[NI_MAXHOST], dbuff[NI_MAXHOST];
+
+		memset(&ss, 0, sizeof(ss));
+		ss.sin_family = PF_INET;
+		ss.sin_addr.s_addr = ip->saddr;
+		getnameinfo((struct sockaddr *) &ss, sizeof(ss),
+			    sbuff, sizeof(sbuff), NULL, 0, NI_NUMERICHOST);
+
+		memset(&sd, 0, sizeof(sd));
+		sd.sin_family = PF_INET;
+		sd.sin_addr.s_addr = ip->daddr;
+		getnameinfo((struct sockaddr *) &sd, sizeof(sd),
+			    dbuff, sizeof(dbuff), NULL, 0, NI_NUMERICHOST);
+
+		printf("%s -> %s, ", sbuff, dbuff);
+	}
+
+	printf("rxhash: 0x%x\n", ppd->hv1.tp_rxhash);
+}
+
+static void walk_block(struct block_desc *pbd, const int block_num)
+{
+	int num_pkts = BLOCK_NUM_PKTS(pbd), i;
+	unsigned long bytes = 0;
+	unsigned long bytes_with_padding = BLOCK_PLUS_PRIV(BLOCK_PRIV_AREA_SZ);
+	struct tpacket3_hdr *ppd;
+
+	assert_block_header(pbd, block_num);
+
+	ppd = (struct tpacket3_hdr *) ((uint8_t *) pbd + BLOCK_O2FP(pbd));
+	for (i = 0; i < num_pkts; ++i) {
+		bytes += ppd->tp_snaplen;
+		if (ppd->tp_next_offset)
+			bytes_with_padding += ppd->tp_next_offset;
+		else
+			bytes_with_padding += ALIGN_8(ppd->tp_snaplen + ppd->tp_mac);
+
+		display(ppd);
+
+		ppd = (struct tpacket3_hdr *) ((uint8_t *) ppd + ppd->tp_next_offset);
+		__sync_synchronize();
+	}
+
+	assert_block_len(pbd, bytes_with_padding, block_num);
+
+	packets_total += num_pkts;
+	bytes_total += bytes;
+}
+
+void flush_block(struct block_desc *pbd)
+{
+	BLOCK_STATUS(pbd) = TP_STATUS_KERNEL;
+	__sync_synchronize();
+}
+
+static void teardown_socket(struct ring *ring, int fd)
+{
+	munmap(ring->map, ring->req.tp_block_size * ring->req.tp_block_nr);
+	free(ring->rd);
+	close(fd);
+}
+
+int main(int argc, char **argp)
+{
+	int fd, err;
+	socklen_t len;
+	struct ring ring;
+	struct pollfd pfd;
+	unsigned int block_num = 0;
+	struct block_desc *pbd;
+	struct tpacket_stats_v3 stats;
+
+	if (argc != 2) {
+		fprintf(stderr, "Usage: %s INTERFACE\n", argp[0]);
+		return EXIT_FAILURE;
+	}
+
+	signal(SIGINT, sighandler);
+
+	memset(&ring, 0, sizeof(ring));
+	fd = setup_socket(&ring, argp[argc - 1]);
+	assert(fd > 0);
+
+	memset(&pfd, 0, sizeof(pfd));
+	pfd.fd = fd;
+	pfd.events = POLLIN | POLLERR;
+	pfd.revents = 0;
+
+	while (likely(!sigint)) {
+		pbd = (struct block_desc *) ring.rd[block_num].iov_base;
+retry_block:
+		if ((BLOCK_STATUS(pbd) & TP_STATUS_USER) == 0) {
+			poll(&pfd, 1, -1);
+			goto retry_block;
+		}
+
+		walk_block(pbd, block_num);
+		flush_block(pbd);
+		block_num = (block_num + 1) % NUM_BLOCKS;
+	}
+
+	len = sizeof(stats);
+	err = getsockopt(fd, SOL_PACKET, PACKET_STATISTICS, &stats, &len);
+	if (err < 0) {
+		perror("getsockopt");
+		exit(1);
+	}
+
+	fflush(stdout);
+	printf("\nReceived %u packets, %lu bytes, %u dropped, freeze_q_cnt: %u\n",
+	       stats.tp_packets, bytes_total, stats.tp_drops,
+	       stats.tp_freeze_q_cnt);
+
+	teardown_socket(&ring, fd);
+	return 0;
+}
+
+-------------------------------------------------------------------------------
 + PACKET_TIMESTAMP
 -------------------------------------------------------------------------------
 
diff --git a/Documentation/networking/stmmac.txt b/Documentation/networking/stmmac.txt
index f9fa6db..8efe0b3 100644
--- a/Documentation/networking/stmmac.txt
+++ b/Documentation/networking/stmmac.txt
@@ -326,6 +326,35 @@ To enter in Tx LPI mode the driver needs to have a software timer
 that enable and disable the LPI mode when there is nothing to be
 transmitted.
 
-7) TODO:
+7) Extended descriptors
+The extended descriptors give us information about the receive Ethernet payload
+when it is carrying PTP packets or TCP/UDP/ICMP over IP.
+These are not available on GMAC Synopsys chips older than the 3.50.
+At probe time the driver will decide if these can be actually used.
+This support also is mandatory for PTPv2 because the extra descriptors 6 and 7
+are used for saving the hardware timestamps.
+
+8) Precision Time Protocol (PTP)
+The driver supports the IEEE 1588-2002, Precision Time Protocol (PTP),
+which enables precise synchronization of clocks in measurement and
+control systems implemented with technologies such as network
+communication.
+
+In addition to the basic timestamp features mentioned in IEEE 1588-2002
+Timestamps, new GMAC cores support the advanced timestamp features.
+IEEE 1588-2008 that can be enabled when configure the Kernel.
+
+9) SGMII/RGMII supports
+New GMAC devices provide own way to manage RGMII/SGMII.
+This information is available at run-time by looking at the
+HW capability register. This means that the stmmac can manage
+auto-negotiation and link status w/o using the PHYLIB stuff
+In fact, the HW provides a subset of extended registers to
+restart the ANE, verify Full/Half duplex mode and Speed.
+Also thanks to these registers it is possible to look at the
+Auto-negotiated Link Parter Ability.
+
+10) TODO:
  o XGMAC is not supported.
- o Add the PTP - precision time protocol
+ o Complete the TBI & RTBI support.
+ o extened VLAN support for 3.70a SYNP GMAC.
diff --git a/Documentation/pinctrl.txt b/Documentation/pinctrl.txt
index a2b57e0..447fd4c 100644
--- a/Documentation/pinctrl.txt
+++ b/Documentation/pinctrl.txt
@@ -736,6 +736,13 @@ All the above functions are mandatory to implement for a pinmux driver.
 Pin control interaction with the GPIO subsystem
 ===============================================
 
+Note that the following implies that the use case is to use a certain pin
+from the Linux kernel using the API in <linux/gpio.h> with gpio_request()
+and similar functions. There are cases where you may be using something
+that your datasheet calls "GPIO mode" but actually is just an electrical
+configuration for a certain device. See the section below named
+"GPIO mode pitfalls" for more details on this scenario.
+
 The public pinmux API contains two functions named pinctrl_request_gpio()
 and pinctrl_free_gpio(). These two functions shall *ONLY* be called from
 gpiolib-based drivers as part of their gpio_request() and
@@ -774,6 +781,111 @@ obtain the function "gpioN" where "N" is the global GPIO pin number if no
 special GPIO-handler is registered.
 
 
+GPIO mode pitfalls
+==================
+
+Sometime the developer may be confused by a datasheet talking about a pin
+being possible to set into "GPIO mode". It appears that what hardware
+engineers mean with "GPIO mode" is not necessarily the use case that is
+implied in the kernel interface <linux/gpio.h>: a pin that you grab from
+kernel code and then either listen for input or drive high/low to
+assert/deassert some external line.
+
+Rather hardware engineers think that "GPIO mode" means that you can
+software-control a few electrical properties of the pin that you would
+not be able to control if the pin was in some other mode, such as muxed in
+for a device.
+
+Example: a pin is usually muxed in to be used as a UART TX line. But during
+system sleep, we need to put this pin into "GPIO mode" and ground it.
+
+If you make a 1-to-1 map to the GPIO subsystem for this pin, you may start
+to think that you need to come up with something real complex, that the
+pin shall be used for UART TX and GPIO at the same time, that you will grab
+a pin control handle and set it to a certain state to enable UART TX to be
+muxed in, then twist it over to GPIO mode and use gpio_direction_output()
+to drive it low during sleep, then mux it over to UART TX again when you
+wake up and maybe even gpio_request/gpio_free as part of this cycle. This
+all gets very complicated.
+
+The solution is to not think that what the datasheet calls "GPIO mode"
+has to be handled by the <linux/gpio.h> interface. Instead view this as
+a certain pin config setting. Look in e.g. <linux/pinctrl/pinconf-generic.h>
+and you find this in the documentation:
+
+  PIN_CONFIG_OUTPUT: this will configure the pin in output, use argument
+     1 to indicate high level, argument 0 to indicate low level.
+
+So it is perfectly possible to push a pin into "GPIO mode" and drive the
+line low as part of the usual pin control map. So for example your UART
+driver may look like this:
+
+#include <linux/pinctrl/consumer.h>
+
+struct pinctrl          *pinctrl;
+struct pinctrl_state    *pins_default;
+struct pinctrl_state    *pins_sleep;
+
+pins_default = pinctrl_lookup_state(uap->pinctrl, PINCTRL_STATE_DEFAULT);
+pins_sleep = pinctrl_lookup_state(uap->pinctrl, PINCTRL_STATE_SLEEP);
+
+/* Normal mode */
+retval = pinctrl_select_state(pinctrl, pins_default);
+/* Sleep mode */
+retval = pinctrl_select_state(pinctrl, pins_sleep);
+
+And your machine configuration may look like this:
+--------------------------------------------------
+
+static unsigned long uart_default_mode[] = {
+    PIN_CONF_PACKED(PIN_CONFIG_DRIVE_PUSH_PULL, 0),
+};
+
+static unsigned long uart_sleep_mode[] = {
+    PIN_CONF_PACKED(PIN_CONFIG_OUTPUT, 0),
+};
+
+static struct pinctrl_map __initdata pinmap[] = {
+    PIN_MAP_MUX_GROUP("uart", PINCTRL_STATE_DEFAULT, "pinctrl-foo",
+                      "u0_group", "u0"),
+    PIN_MAP_CONFIGS_PIN("uart", PINCTRL_STATE_DEFAULT, "pinctrl-foo",
+                        "UART_TX_PIN", uart_default_mode),
+    PIN_MAP_MUX_GROUP("uart", PINCTRL_STATE_SLEEP, "pinctrl-foo",
+                      "u0_group", "gpio-mode"),
+    PIN_MAP_CONFIGS_PIN("uart", PINCTRL_STATE_SLEEP, "pinctrl-foo",
+                        "UART_TX_PIN", uart_sleep_mode),
+};
+
+foo_init(void) {
+    pinctrl_register_mappings(pinmap, ARRAY_SIZE(pinmap));
+}
+
+Here the pins we want to control are in the "u0_group" and there is some
+function called "u0" that can be enabled on this group of pins, and then
+everything is UART business as usual. But there is also some function
+named "gpio-mode" that can be mapped onto the same pins to move them into
+GPIO mode.
+
+This will give the desired effect without any bogus interaction with the
+GPIO subsystem. It is just an electrical configuration used by that device
+when going to sleep, it might imply that the pin is set into something the
+datasheet calls "GPIO mode" but that is not the point: it is still used
+by that UART device to control the pins that pertain to that very UART
+driver, putting them into modes needed by the UART. GPIO in the Linux
+kernel sense are just some 1-bit line, and is a different use case.
+
+How the registers are poked to attain the push/pull and output low
+configuration and the muxing of the "u0" or "gpio-mode" group onto these
+pins is a question for the driver.
+
+Some datasheets will be more helpful and refer to the "GPIO mode" as
+"low power mode" rather than anything to do with GPIO. This often means
+the same thing electrically speaking, but in this latter case the
+software engineers will usually quickly identify that this is some
+specific muxing/configuration rather than anything related to the GPIO
+API.
+
+
 Board/machine configuration
 ==================================
 
diff --git a/Documentation/s390/s390dbf.txt b/Documentation/s390/s390dbf.txt
index ae66f9b..fcaf0b4 100644
--- a/Documentation/s390/s390dbf.txt
+++ b/Documentation/s390/s390dbf.txt
@@ -143,7 +143,8 @@ Parameter:     id:   handle for debug log
 
 Return Value:  none 
 
-Description:   frees memory for a debug log     
+Description:   frees memory for a debug log and removes all registered debug
+	       views.
                Must not be called within an interrupt handler 
 
 ---------------------------------------------------------------------------
diff --git a/Documentation/security/Smack.txt b/Documentation/security/Smack.txt
index 8a177e4..7a2d30c 100644
--- a/Documentation/security/Smack.txt
+++ b/Documentation/security/Smack.txt
@@ -117,6 +117,17 @@ access2
 ambient
 	This contains the Smack label applied to unlabeled network
 	packets.
+change-rule
+	This interface allows modification of existing access control rules.
+	The format accepted on write is:
+		"%s %s %s %s"
+	where the first string is the subject label, the second the
+	object label, the third the access to allow and the fourth the
+	access to deny. The access strings may contain only the characters
+	"rwxat-". If a rule for a given subject and object exists it will be
+	modified by enabling the permissions in the third string and disabling
+	those in the fourth string. If there is no such rule it will be
+	created using the access specified in the third and the fourth strings.
 cipso
 	This interface allows a specific CIPSO header to be assigned
 	to a Smack label. The format accepted on write is:
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index 4499bd9..95731a0 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -890,9 +890,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
     enable_msi	- Enable Message Signaled Interrupt (MSI) (default = off)
     power_save	- Automatic power-saving timeout (in second, 0 =
 		disable)
-    power_save_controller - Support runtime D3 of HD-audio controller
-		(-1 = on for supported chip (default), false = off,
-		 true = force to on even for unsupported hardware)
+    power_save_controller - Reset HD-audio controller in power-saving mode
+		(default = on)
     align_buffer_size - Force rounding of buffer/period sizes to multiples
     		      of 128 bytes. This is more efficient in terms of memory
 		      access but isn't required by the HDA spec and prevents
diff --git a/Documentation/sound/alsa/HD-Audio.txt b/Documentation/sound/alsa/HD-Audio.txt
index d4faa63..c3c912d 100644
--- a/Documentation/sound/alsa/HD-Audio.txt
+++ b/Documentation/sound/alsa/HD-Audio.txt
@@ -461,11 +461,13 @@ The generic parser supports the following hints:
   the corresponding mixer control, if available
 - add_stereo_mix_input (bool): add the stereo mix (analog-loopback
   mix) to the input mux if available
-- add_out_jack_modes (bool): add "xxx Jack Mode" enum controls to each
-  output jack for allowing to change the headphone amp capability
-- add_in_jack_modes (bool): add "xxx Jack Mode" enum controls to each
-  input jack for allowing to change the mic bias vref
+- add_jack_modes (bool): add "xxx Jack Mode" enum controls to each
+  I/O jack for allowing to change the headphone amp and mic bias VREF
+  capabilities
 - power_down_unused (bool): power down the unused widgets
+- add_hp_mic (bool): add the headphone to capture source if possible
+- hp_mic_detect (bool): enable/disable the hp/mic shared input for a
+  single built-in mic case; default true
 - mixer_nid (int): specifies the widget NID of the analog-loopback
   mixer
 
diff --git a/Documentation/sysctl/vm.txt b/Documentation/sysctl/vm.txt
index 078701f..21ad181 100644
--- a/Documentation/sysctl/vm.txt
+++ b/Documentation/sysctl/vm.txt
@@ -138,18 +138,39 @@ Setting this to zero disables periodic writeback altogether.
 
 drop_caches
 
-Writing to this will cause the kernel to drop clean caches, dentries and
-inodes from memory, causing that memory to become free.
+Writing to this will cause the kernel to drop clean caches, as well as
+reclaimable slab objects like dentries and inodes.  Once dropped, their
+memory becomes free.
 
 To free pagecache:
 	echo 1 > /proc/sys/vm/drop_caches
-To free dentries and inodes:
+To free reclaimable slab objects (includes dentries and inodes):
 	echo 2 > /proc/sys/vm/drop_caches
-To free pagecache, dentries and inodes:
+To free slab objects and pagecache:
 	echo 3 > /proc/sys/vm/drop_caches
 
-As this is a non-destructive operation and dirty objects are not freeable, the
-user should run `sync' first.
+This is a non-destructive operation and will not free any dirty objects.
+To increase the number of objects freed by this operation, the user may run
+`sync' prior to writing to /proc/sys/vm/drop_caches.  This will minimize the
+number of dirty objects on the system and create more candidates to be
+dropped.
+
+This file is not a means to control the growth of the various kernel caches
+(inodes, dentries, pagecache, etc...)  These objects are automatically
+reclaimed by the kernel when memory is needed elsewhere on the system.
+
+Use of this file can cause performance problems.  Since it discards cached
+objects, it may cost a significant amount of I/O and CPU to recreate the
+dropped objects, especially if they were under heavy use.  Because of this,
+use outside of a testing or debugging environment is not recommended.
+
+You may see informational messages in your kernel log when this file is
+used:
+
+	cat (1234): dropped kernel caches: 3
+
+These are informational only.  They do not mean that anything is wrong
+with your system.
 
 ==============================================================
 
diff --git a/Documentation/this_cpu_ops.txt b/Documentation/this_cpu_ops.txt
new file mode 100644
index 0000000..1a4ce7e
--- /dev/null
+++ b/Documentation/this_cpu_ops.txt
@@ -0,0 +1,205 @@
+this_cpu operations
+-------------------
+
+this_cpu operations are a way of optimizing access to per cpu
+variables associated with the *currently* executing processor through
+the use of segment registers (or a dedicated register where the cpu
+permanently stored the beginning of the per cpu area for a specific
+processor).
+
+The this_cpu operations add a per cpu variable offset to the processor
+specific percpu base and encode that operation in the instruction
+operating on the per cpu variable.
+
+This means there are no atomicity issues between the calculation of
+the offset and the operation on the data. Therefore it is not
+necessary to disable preempt or interrupts to ensure that the
+processor is not changed between the calculation of the address and
+the operation on the data.
+
+Read-modify-write operations are of particular interest. Frequently
+processors have special lower latency instructions that can operate
+without the typical synchronization overhead but still provide some
+sort of relaxed atomicity guarantee. The x86 for example can execute
+RMV (Read Modify Write) instructions like inc/dec/cmpxchg without the
+lock prefix and the associated latency penalty.
+
+Access to the variable without the lock prefix is not synchronized but
+synchronization is not necessary since we are dealing with per cpu
+data specific to the currently executing processor. Only the current
+processor should be accessing that variable and therefore there are no
+concurrency issues with other processors in the system.
+
+On x86 the fs: or the gs: segment registers contain the base of the
+per cpu area. It is then possible to simply use the segment override
+to relocate a per cpu relative address to the proper per cpu area for
+the processor. So the relocation to the per cpu base is encoded in the
+instruction via a segment register prefix.
+
+For example:
+
+	DEFINE_PER_CPU(int, x);
+	int z;
+
+	z = this_cpu_read(x);
+
+results in a single instruction
+
+	mov ax, gs:[x]
+
+instead of a sequence of calculation of the address and then a fetch
+from that address which occurs with the percpu operations. Before
+this_cpu_ops such sequence also required preempt disable/enable to
+prevent the kernel from moving the thread to a different processor
+while the calculation is performed.
+
+The main use of the this_cpu operations has been to optimize counter
+operations.
+
+	this_cpu_inc(x)
+
+results in the following single instruction (no lock prefix!)
+
+	inc gs:[x]
+
+instead of the following operations required if there is no segment
+register.
+
+	int *y;
+	int cpu;
+
+	cpu = get_cpu();
+	y = per_cpu_ptr(&x, cpu);
+	(*y)++;
+	put_cpu();
+
+Note that these operations can only be used on percpu data that is
+reserved for a specific processor. Without disabling preemption in the
+surrounding code this_cpu_inc() will only guarantee that one of the
+percpu counters is correctly incremented. However, there is no
+guarantee that the OS will not move the process directly before or
+after the this_cpu instruction is executed. In general this means that
+the value of the individual counters for each processor are
+meaningless. The sum of all the per cpu counters is the only value
+that is of interest.
+
+Per cpu variables are used for performance reasons. Bouncing cache
+lines can be avoided if multiple processors concurrently go through
+the same code paths.  Since each processor has its own per cpu
+variables no concurrent cacheline updates take place. The price that
+has to be paid for this optimization is the need to add up the per cpu
+counters when the value of the counter is needed.
+
+
+Special operations:
+-------------------
+
+	y = this_cpu_ptr(&x)
+
+Takes the offset of a per cpu variable (&x !) and returns the address
+of the per cpu variable that belongs to the currently executing
+processor.  this_cpu_ptr avoids multiple steps that the common
+get_cpu/put_cpu sequence requires. No processor number is
+available. Instead the offset of the local per cpu area is simply
+added to the percpu offset.
+
+
+
+Per cpu variables and offsets
+-----------------------------
+
+Per cpu variables have *offsets* to the beginning of the percpu
+area. They do not have addresses although they look like that in the
+code. Offsets cannot be directly dereferenced. The offset must be
+added to a base pointer of a percpu area of a processor in order to
+form a valid address.
+
+Therefore the use of x or &x outside of the context of per cpu
+operations is invalid and will generally be treated like a NULL
+pointer dereference.
+
+In the context of per cpu operations
+
+	x is a per cpu variable. Most this_cpu operations take a cpu
+	variable.
+
+	&x is the *offset* a per cpu variable. this_cpu_ptr() takes
+	the offset of a per cpu variable which makes this look a bit
+	strange.
+
+
+
+Operations on a field of a per cpu structure
+--------------------------------------------
+
+Let's say we have a percpu structure
+
+	struct s {
+		int n,m;
+	};
+
+	DEFINE_PER_CPU(struct s, p);
+
+
+Operations on these fields are straightforward
+
+	this_cpu_inc(p.m)
+
+	z = this_cpu_cmpxchg(p.m, 0, 1);
+
+
+If we have an offset to struct s:
+
+	struct s __percpu *ps = &p;
+
+	z = this_cpu_dec(ps->m);
+
+	z = this_cpu_inc_return(ps->n);
+
+
+The calculation of the pointer may require the use of this_cpu_ptr()
+if we do not make use of this_cpu ops later to manipulate fields:
+
+	struct s *pp;
+
+	pp = this_cpu_ptr(&p);
+
+	pp->m--;
+
+	z = pp->n++;
+
+
+Variants of this_cpu ops
+-------------------------
+
+this_cpu ops are interrupt safe. Some architecture do not support
+these per cpu local operations. In that case the operation must be
+replaced by code that disables interrupts, then does the operations
+that are guaranteed to be atomic and then reenable interrupts. Doing
+so is expensive. If there are other reasons why the scheduler cannot
+change the processor we are executing on then there is no reason to
+disable interrupts. For that purpose the __this_cpu operations are
+provided. For example.
+
+	__this_cpu_inc(x);
+
+Will increment x and will not fallback to code that disables
+interrupts on platforms that cannot accomplish atomicity through
+address relocation and a Read-Modify-Write operation in the same
+instruction.
+
+
+
+&this_cpu_ptr(pp)->n vs this_cpu_ptr(&pp->n)
+--------------------------------------------
+
+The first operation takes the offset and forms an address and then
+adds the offset of the n field.
+
+The second one first adds the two offsets and then does the
+relocation.  IMHO the second form looks cleaner and has an easier time
+with (). The second form also is consistent with the way
+this_cpu_read() and friends are used.
+
+
+Christoph Lameter, April 3rd, 2013
diff --git a/Documentation/trace/ftrace.txt b/Documentation/trace/ftrace.txt
index a372304..bfe8c29 100644
--- a/Documentation/trace/ftrace.txt
+++ b/Documentation/trace/ftrace.txt
@@ -8,6 +8,7 @@ Copyright 2008 Red Hat Inc.
 Reviewers:   Elias Oltmanns, Randy Dunlap, Andrew Morton,
 	     John Kacur, and David Teigland.
 Written for: 2.6.28-rc2
+Updated for: 3.10
 
 Introduction
 ------------
@@ -17,13 +18,16 @@ designers of systems to find what is going on inside the kernel.
 It can be used for debugging or analyzing latencies and
 performance issues that take place outside of user-space.
 
-Although ftrace is the function tracer, it also includes an
-infrastructure that allows for other types of tracing. Some of
-the tracers that are currently in ftrace include a tracer to
-trace context switches, the time it takes for a high priority
-task to run after it was woken up, the time interrupts are
-disabled, and more (ftrace allows for tracer plugins, which
-means that the list of tracers can always grow).
+Although ftrace is typically considered the function tracer, it
+is really a frame work of several assorted tracing utilities.
+There's latency tracing to examine what occurs between interrupts
+disabled and enabled, as well as for preemption and from a time
+a task is woken to the task is actually scheduled in.
+
+One of the most common uses of ftrace is the event tracing.
+Through out the kernel is hundreds of static event points that
+can be enabled via the debugfs file system to see what is
+going on in certain parts of the kernel.
 
 
 Implementation Details
@@ -61,7 +65,7 @@ the extended "/sys/kernel/debug/tracing" path name.
 
 That's it! (assuming that you have ftrace configured into your kernel)
 
-After mounting the debugfs, you can see a directory called
+After mounting debugfs, you can see a directory called
 "tracing".  This directory contains the control and output files
 of ftrace. Here is a list of some of the key files:
 
@@ -84,7 +88,9 @@ of ftrace. Here is a list of some of the key files:
 
 	This sets or displays whether writing to the trace
 	ring buffer is enabled. Echo 0 into this file to disable
-	the tracer or 1 to enable it.
+	the tracer or 1 to enable it. Note, this only disables
+	writing to the ring buffer, the tracing overhead may
+	still be occurring.
 
   trace:
 
@@ -109,7 +115,15 @@ of ftrace. Here is a list of some of the key files:
 
 	This file lets the user control the amount of data
 	that is displayed in one of the above output
-	files.
+	files. Options also exist to modify how a tracer
+	or events work (stack traces, timestamps, etc).
+
+  options:
+
+	This is a directory that has a file for every available
+	trace option (also in trace_options). Options may also be set
+	or cleared by writing a "1" or "0" respectively into the
+	corresponding file with the option name.
 
   tracing_max_latency:
 
@@ -121,10 +135,17 @@ of ftrace. Here is a list of some of the key files:
 	latency is greater than the value in this
 	file. (in microseconds)
 
+  tracing_thresh:
+
+	Some latency tracers will record a trace whenever the
+	latency is greater than the number in this file.
+	Only active when the file contains a number greater than 0.
+	(in microseconds)
+
   buffer_size_kb:
 
 	This sets or displays the number of kilobytes each CPU
-	buffer can hold. The tracer buffers are the same size
+	buffer holds. By default, the trace buffers are the same size
 	for each CPU. The displayed number is the size of the
 	CPU buffer and not total size of all buffers. The
 	trace buffers are allocated in pages (blocks of memory
@@ -133,16 +154,30 @@ of ftrace. Here is a list of some of the key files:
 	than requested, the rest of the page will be used,
 	making the actual allocation bigger than requested.
 	( Note, the size may not be a multiple of the page size
-	  due to buffer management overhead. )
+	  due to buffer management meta-data. )
 
-	This can only be updated when the current_tracer
-	is set to "nop".
+  buffer_total_size_kb:
+
+	This displays the total combined size of all the trace buffers.
+
+  free_buffer:
+
+	If a process is performing the tracing, and the ring buffer
+	should be shrunk "freed" when the process is finished, even
+	if it were to be killed by a signal, this file can be used
+	for that purpose. On close of this file, the ring buffer will
+	be resized to its minimum size. Having a process that is tracing
+	also open this file, when the process exits its file descriptor
+	for this file will be closed, and in doing so, the ring buffer
+	will be "freed".
+
+	It may also stop tracing if disable_on_free option is set.
 
   tracing_cpumask:
 
 	This is a mask that lets the user only trace
-	on specified CPUS. The format is a hex string
-	representing the CPUS.
+	on specified CPUs. The format is a hex string
+	representing the CPUs.
 
   set_ftrace_filter:
 
@@ -183,6 +218,261 @@ of ftrace. Here is a list of some of the key files:
 	"set_ftrace_notrace". (See the section "dynamic ftrace"
 	below for more details.)
 
+  enabled_functions:
+
+	This file is more for debugging ftrace, but can also be useful
+	in seeing if any function has a callback attached to it.
+	Not only does the trace infrastructure use ftrace function
+	trace utility, but other subsystems might too. This file
+	displays all functions that have a callback attached to them
+	as well as the number of callbacks that have been attached.
+	Note, a callback may also call multiple functions which will
+	not be listed in this count.
+
+	If the callback registered to be traced by a function with
+	the "save regs" attribute (thus even more overhead), a 'R'
+	will be displayed on the same line as the function that
+	is returning registers.
+
+  function_profile_enabled:
+
+	When set it will enable all functions with either the function
+	tracer, or if enabled, the function graph tracer. It will
+	keep a histogram of the number of functions that were called
+	and if run with the function graph tracer, it will also keep
+	track of the time spent in those functions. The histogram
+	content can be displayed in the files:
+
+	trace_stats/function<cpu> ( function0, function1, etc).
+
+  trace_stats:
+
+	A directory that holds different tracing stats.
+
+  kprobe_events:
+ 
+	Enable dynamic trace points. See kprobetrace.txt.
+
+  kprobe_profile:
+
+	Dynamic trace points stats. See kprobetrace.txt.
+
+  max_graph_depth:
+
+	Used with the function graph tracer. This is the max depth
+	it will trace into a function. Setting this to a value of
+	one will show only the first kernel function that is called
+	from user space.
+
+  printk_formats:
+
+	This is for tools that read the raw format files. If an event in
+	the ring buffer references a string (currently only trace_printk()
+	does this), only a pointer to the string is recorded into the buffer
+	and not the string itself. This prevents tools from knowing what
+	that string was. This file displays the string and address for
+	the string allowing tools to map the pointers to what the
+	strings were.
+
+  saved_cmdlines:
+
+	Only the pid of the task is recorded in a trace event unless
+	the event specifically saves the task comm as well. Ftrace
+	makes a cache of pid mappings to comms to try to display
+	comms for events. If a pid for a comm is not listed, then
+	"<...>" is displayed in the output.
+
+  snapshot:
+
+	This displays the "snapshot" buffer and also lets the user
+	take a snapshot of the current running trace.
+	See the "Snapshot" section below for more details.
+
+  stack_max_size:
+
+	When the stack tracer is activated, this will display the
+	maximum stack size it has encountered.
+	See the "Stack Trace" section below.
+
+  stack_trace:
+
+	This displays the stack back trace of the largest stack
+	that was encountered when the stack tracer is activated.
+	See the "Stack Trace" section below.
+
+  stack_trace_filter:
+
+	This is similar to "set_ftrace_filter" but it limits what
+	functions the stack tracer will check.
+
+  trace_clock:
+
+	Whenever an event is recorded into the ring buffer, a
+	"timestamp" is added. This stamp comes from a specified
+	clock. By default, ftrace uses the "local" clock. This
+	clock is very fast and strictly per cpu, but on some
+	systems it may not be monotonic with respect to other
+	CPUs. In other words, the local clocks may not be in sync
+	with local clocks on other CPUs.
+
+	Usual clocks for tracing:
+
+	  # cat trace_clock
+	  [local] global counter x86-tsc
+
+	  local: Default clock, but may not be in sync across CPUs
+
+	  global: This clock is in sync with all CPUs but may
+	  	  be a bit slower than the local clock.
+
+	  counter: This is not a clock at all, but literally an atomic
+	  	   counter. It counts up one by one, but is in sync
+		   with all CPUs. This is useful when you need to
+		   know exactly the order events occurred with respect to
+		   each other on different CPUs.
+
+	  uptime: This uses the jiffies counter and the time stamp
+	  	  is relative to the time since boot up.
+
+	  perf: This makes ftrace use the same clock that perf uses.
+	  	Eventually perf will be able to read ftrace buffers
+		and this will help out in interleaving the data.
+
+	  x86-tsc: Architectures may define their own clocks. For
+	  	   example, x86 uses its own TSC cycle clock here.
+
+	To set a clock, simply echo the clock name into this file.
+
+	  echo global > trace_clock
+
+  trace_marker:
+
+	This is a very useful file for synchronizing user space
+	with events happening in the kernel. Writing strings into
+	this file will be written into the ftrace buffer.
+
+	It is useful in applications to open this file at the start
+	of the application and just reference the file descriptor
+	for the file.
+
+	void trace_write(const char *fmt, ...)
+	{
+		va_list ap;
+		char buf[256];
+		int n;
+
+		if (trace_fd < 0)
+			return;
+
+		va_start(ap, fmt);
+		n = vsnprintf(buf, 256, fmt, ap);
+		va_end(ap);
+
+		write(trace_fd, buf, n);
+	}
+
+	start:
+
+		trace_fd = open("trace_marker", WR_ONLY);
+
+  uprobe_events:
+ 
+	Add dynamic tracepoints in programs.
+	See uprobetracer.txt
+
+  uprobe_profile:
+
+	Uprobe statistics. See uprobetrace.txt
+
+  instances:
+
+	This is a way to make multiple trace buffers where different
+	events can be recorded in different buffers.
+	See "Instances" section below.
+
+  events:
+
+	This is the trace event directory. It holds event tracepoints
+	(also known as static tracepoints) that have been compiled
+	into the kernel. It shows what event tracepoints exist
+	and how they are grouped by system. There are "enable"
+	files at various levels that can enable the tracepoints
+	when a "1" is written to them.
+
+	See events.txt for more information.
+
+  per_cpu:
+
+	This is a directory that contains the trace per_cpu information.
+
+  per_cpu/cpu0/buffer_size_kb:
+
+	The ftrace buffer is defined per_cpu. That is, there's a separate
+	buffer for each CPU to allow writes to be done atomically,
+	and free from cache bouncing. These buffers may have different
+	size buffers. This file is similar to the buffer_size_kb
+	file, but it only displays or sets the buffer size for the
+	specific CPU. (here cpu0).
+
+  per_cpu/cpu0/trace:
+
+	This is similar to the "trace" file, but it will only display
+	the data specific for the CPU. If written to, it only clears
+	the specific CPU buffer.
+
+  per_cpu/cpu0/trace_pipe
+
+	This is similar to the "trace_pipe" file, and is a consuming
+	read, but it will only display (and consume) the data specific
+	for the CPU.
+
+  per_cpu/cpu0/trace_pipe_raw
+
+	For tools that can parse the ftrace ring buffer binary format,
+	the trace_pipe_raw file can be used to extract the data
+	from the ring buffer directly. With the use of the splice()
+	system call, the buffer data can be quickly transferred to
+	a file or to the network where a server is collecting the
+	data.
+
+	Like trace_pipe, this is a consuming reader, where multiple
+	reads will always produce different data.
+
+  per_cpu/cpu0/snapshot:
+
+	This is similar to the main "snapshot" file, but will only
+	snapshot the current CPU (if supported). It only displays
+	the content of the snapshot for a given CPU, and if
+	written to, only clears this CPU buffer.
+
+  per_cpu/cpu0/snapshot_raw:
+
+	Similar to the trace_pipe_raw, but will read the binary format
+	from the snapshot buffer for the given CPU.
+
+  per_cpu/cpu0/stats:
+
+	This displays certain stats about the ring buffer:
+
+	 entries: The number of events that are still in the buffer.
+
+	 overrun: The number of lost events due to overwriting when
+	 	  the buffer was full.
+
+	 commit overrun: Should always be zero.
+	 	This gets set if so many events happened within a nested
+		event (ring buffer is re-entrant), that it fills the
+		buffer and starts dropping events.
+
+	 bytes: Bytes actually read (not overwritten).
+
+	 oldest event ts: The oldest timestamp in the buffer
+
+	 now ts: The current timestamp
+
+	 dropped events: Events lost due to overwrite option being off.
+
+	 read events: The number of events read.
 
 The Tracers
 -----------
@@ -234,11 +524,6 @@ Here is the list of current tracers that may be configured.
         RT tasks (as the current "wakeup" does). This is useful
         for those interested in wake up timings of RT tasks.
 
-  "hw-branch-tracer"
-
-	Uses the BTS CPU feature on x86 CPUs to traces all
-	branches executed.
-
   "nop"
 
 	This is the "trace nothing" tracer. To remove all
@@ -261,70 +546,100 @@ Here is an example of the output format of the file "trace"
                              --------
 # tracer: function
 #
-#           TASK-PID   CPU#    TIMESTAMP  FUNCTION
-#              | |      |          |         |
-            bash-4251  [01] 10152.583854: path_put <-path_walk
-            bash-4251  [01] 10152.583855: dput <-path_put
-            bash-4251  [01] 10152.583855: _atomic_dec_and_lock <-dput
+# entries-in-buffer/entries-written: 140080/250280   #P:4
+#
+#                              _-----=> irqs-off
+#                             / _----=> need-resched
+#                            | / _---=> hardirq/softirq
+#                            || / _--=> preempt-depth
+#                            ||| /     delay
+#           TASK-PID   CPU#  ||||    TIMESTAMP  FUNCTION
+#              | |       |   ||||       |         |
+            bash-1977  [000] .... 17284.993652: sys_close <-system_call_fastpath
+            bash-1977  [000] .... 17284.993653: __close_fd <-sys_close
+            bash-1977  [000] .... 17284.993653: _raw_spin_lock <-__close_fd
+            sshd-1974  [003] .... 17284.993653: __srcu_read_unlock <-fsnotify
+            bash-1977  [000] .... 17284.993654: add_preempt_count <-_raw_spin_lock
+            bash-1977  [000] ...1 17284.993655: _raw_spin_unlock <-__close_fd
+            bash-1977  [000] ...1 17284.993656: sub_preempt_count <-_raw_spin_unlock
+            bash-1977  [000] .... 17284.993657: filp_close <-__close_fd
+            bash-1977  [000] .... 17284.993657: dnotify_flush <-filp_close
+            sshd-1974  [003] .... 17284.993658: sys_select <-system_call_fastpath
                              --------
 
 A header is printed with the tracer name that is represented by
-the trace. In this case the tracer is "function". Then a header
-showing the format. Task name "bash", the task PID "4251", the
-CPU that it was running on "01", the timestamp in <secs>.<usecs>
-format, the function name that was traced "path_put" and the
-parent function that called this function "path_walk". The
-timestamp is the time at which the function was entered.
+the trace. In this case the tracer is "function". Then it shows the
+number of events in the buffer as well as the total number of entries
+that were written. The difference is the number of entries that were
+lost due to the buffer filling up (250280 - 140080 = 110200 events
+lost).
+
+The header explains the content of the events. Task name "bash", the task
+PID "1977", the CPU that it was running on "000", the latency format
+(explained below), the timestamp in <secs>.<usecs> format, the
+function name that was traced "sys_close" and the parent function that
+called this function "system_call_fastpath". The timestamp is the time
+at which the function was entered.
 
 Latency trace format
 --------------------
 
-When the latency-format option is enabled, the trace file gives
-somewhat more information to see why a latency happened.
-Here is a typical trace.
+When the latency-format option is enabled or when one of the latency
+tracers is set, the trace file gives somewhat more information to see
+why a latency happened. Here is a typical trace.
 
 # tracer: irqsoff
 #
-irqsoff latency trace v1.1.5 on 2.6.26-rc8
---------------------------------------------------------------------
- latency: 97 us, #3/3, CPU#0 | (M:preempt VP:0, KP:0, SP:0 HP:0 #P:2)
-    -----------------
-    | task: swapper-0 (uid:0 nice:0 policy:0 rt_prio:0)
-    -----------------
- => started at: apic_timer_interrupt
- => ended at:   do_softirq
-
-#                _------=> CPU#
-#               / _-----=> irqs-off
-#              | / _----=> need-resched
-#              || / _---=> hardirq/softirq
-#              ||| / _--=> preempt-depth
-#              |||| /
-#              |||||     delay
-#  cmd     pid ||||| time  |   caller
-#     \   /    |||||   \   |   /
-  <idle>-0     0d..1    0us+: trace_hardirqs_off_thunk (apic_timer_interrupt)
-  <idle>-0     0d.s.   97us : __do_softirq (do_softirq)
-  <idle>-0     0d.s1   98us : trace_hardirqs_on (do_softirq)
+# irqsoff latency trace v1.1.5 on 3.8.0-test+
+# --------------------------------------------------------------------
+# latency: 259 us, #4/4, CPU#2 | (M:preempt VP:0, KP:0, SP:0 HP:0 #P:4)
+#    -----------------
+#    | task: ps-6143 (uid:0 nice:0 policy:0 rt_prio:0)
+#    -----------------
+#  => started at: __lock_task_sighand
+#  => ended at:   _raw_spin_unlock_irqrestore
+#
+#
+#                  _------=> CPU#            
+#                 / _-----=> irqs-off        
+#                | / _----=> need-resched    
+#                || / _---=> hardirq/softirq 
+#                ||| / _--=> preempt-depth   
+#                |||| /     delay             
+#  cmd     pid   ||||| time  |   caller      
+#     \   /      |||||  \    |   /           
+      ps-6143    2d...    0us!: trace_hardirqs_off <-__lock_task_sighand
+      ps-6143    2d..1  259us+: trace_hardirqs_on <-_raw_spin_unlock_irqrestore
+      ps-6143    2d..1  263us+: time_hardirqs_on <-_raw_spin_unlock_irqrestore
+      ps-6143    2d..1  306us : <stack trace>
+ => trace_hardirqs_on_caller
+ => trace_hardirqs_on
+ => _raw_spin_unlock_irqrestore
+ => do_task_stat
+ => proc_tgid_stat
+ => proc_single_show
+ => seq_read
+ => vfs_read
+ => sys_read
+ => system_call_fastpath
 
 
 This shows that the current tracer is "irqsoff" tracing the time
-for which interrupts were disabled. It gives the trace version
-and the version of the kernel upon which this was executed on
-(2.6.26-rc8). Then it displays the max latency in microsecs (97
-us). The number of trace entries displayed and the total number
-recorded (both are three: #3/3). The type of preemption that was
-used (PREEMPT). VP, KP, SP, and HP are always zero and are
-reserved for later use. #P is the number of online CPUS (#P:2).
+for which interrupts were disabled. It gives the trace version (which
+never changes) and the version of the kernel upon which this was executed on
+(3.10). Then it displays the max latency in microseconds (259 us). The number
+of trace entries displayed and the total number (both are four: #4/4).
+VP, KP, SP, and HP are always zero and are reserved for later use.
+#P is the number of online CPUs (#P:4).
 
 The task is the process that was running when the latency
-occurred. (swapper pid: 0).
+occurred. (ps pid: 6143).
 
 The start and stop (the functions in which the interrupts were
 disabled and enabled respectively) that caused the latencies:
 
-  apic_timer_interrupt is where the interrupts were disabled.
-  do_softirq is where they were enabled again.
+ __lock_task_sighand is where the interrupts were disabled.
+ _raw_spin_unlock_irqrestore is where they were enabled again.
 
 The next lines after the header are the trace itself. The header
 explains which is which.
@@ -367,16 +682,43 @@ The above is mostly meaningful for kernel developers.
 
   The rest is the same as the 'trace' file.
 
+  Note, the latency tracers will usually end with a back trace
+  to easily find where the latency occurred.
 
 trace_options
 -------------
 
-The trace_options file is used to control what gets printed in
-the trace output. To see what is available, simply cat the file:
+The trace_options file (or the options directory) is used to control
+what gets printed in the trace output, or manipulate the tracers.
+To see what is available, simply cat the file:
 
   cat trace_options
-  print-parent nosym-offset nosym-addr noverbose noraw nohex nobin \
-  noblock nostacktrace nosched-tree nouserstacktrace nosym-userobj
+print-parent
+nosym-offset
+nosym-addr
+noverbose
+noraw
+nohex
+nobin
+noblock
+nostacktrace
+trace_printk
+noftrace_preempt
+nobranch
+annotate
+nouserstacktrace
+nosym-userobj
+noprintk-msg-only
+context-info
+latency-format
+sleep-time
+graph-time
+record-cmd
+overwrite
+nodisable_on_free
+irq-info
+markers
+function-trace
 
 To disable one of the options, echo in the option prepended with
 "no".
@@ -428,13 +770,34 @@ Here are the available options:
 
   bin - This will print out the formats in raw binary.
 
-  block - TBD (needs update)
+  block - When set, reading trace_pipe will not block when polled.
 
   stacktrace - This is one of the options that changes the trace
 	       itself. When a trace is recorded, so is the stack
 	       of functions. This allows for back traces of
 	       trace sites.
 
+  trace_printk - Can disable trace_printk() from writing into the buffer.
+
+  branch - Enable branch tracing with the tracer.
+
+  annotate - It is sometimes confusing when the CPU buffers are full
+  	     and one CPU buffer had a lot of events recently, thus
+	     a shorter time frame, were another CPU may have only had
+	     a few events, which lets it have older events. When
+	     the trace is reported, it shows the oldest events first,
+	     and it may look like only one CPU ran (the one with the
+	     oldest events). When the annotate option is set, it will
+	     display when a new CPU buffer started:
+
+          <idle>-0     [001] dNs4 21169.031481: wake_up_idle_cpu <-add_timer_on
+          <idle>-0     [001] dNs4 21169.031482: _raw_spin_unlock_irqrestore <-add_timer_on
+          <idle>-0     [001] .Ns4 21169.031484: sub_preempt_count <-_raw_spin_unlock_irqrestore
+##### CPU 2 buffer started ####
+          <idle>-0     [002] .N.1 21169.031484: rcu_idle_exit <-cpu_idle
+          <idle>-0     [001] .Ns3 21169.031484: _raw_spin_unlock <-clocksource_watchdog
+          <idle>-0     [001] .Ns3 21169.031485: sub_preempt_count <-_raw_spin_unlock
+
   userstacktrace - This option changes the trace. It records a
 		   stacktrace of the current userspace thread.
 
@@ -451,9 +814,13 @@ Here are the available options:
 		a.out-1623  [000] 40874.465068: /root/a.out[+0x480] <-/root/a.out[+0
 x494] <- /root/a.out[+0x4a8] <- /lib/libc-2.7.so[+0x1e1a6]
 
-  sched-tree - trace all tasks that are on the runqueue, at
-	       every scheduling event. Will add overhead if
-	       there's a lot of tasks running at once.
+
+  printk-msg-only - When set, trace_printk()s will only show the format
+  		    and not their parameters (if trace_bprintk() or
+		    trace_bputs() was used to save the trace_printk()).
+
+  context-info - Show only the event data. Hides the comm, PID,
+  	         timestamp, CPU, and other useful data.
 
   latency-format - This option changes the trace. When
                    it is enabled, the trace displays
@@ -461,31 +828,61 @@ x494] <- /root/a.out[+0x4a8] <- /lib/libc-2.7.so[+0x1e1a6]
                    latencies, as described in "Latency
                    trace format".
 
+  sleep-time - When running function graph tracer, to include
+  	       the time a task schedules out in its function.
+	       When enabled, it will account time the task has been
+	       scheduled out as part of the function call.
+
+  graph-time - When running function graph tracer, to include the
+  	       time to call nested functions. When this is not set,
+	       the time reported for the function will only include
+	       the time the function itself executed for, not the time
+	       for functions that it called.
+
+  record-cmd - When any event or tracer is enabled, a hook is enabled
+  	       in the sched_switch trace point to fill comm cache
+	       with mapped pids and comms. But this may cause some
+	       overhead, and if you only care about pids, and not the
+	       name of the task, disabling this option can lower the
+	       impact of tracing.
+
   overwrite - This controls what happens when the trace buffer is
               full. If "1" (default), the oldest events are
               discarded and overwritten. If "0", then the newest
               events are discarded.
+	        (see per_cpu/cpu0/stats for overrun and dropped)
 
-ftrace_enabled
---------------
+  disable_on_free - When the free_buffer is closed, tracing will
+  		    stop (tracing_on set to 0).
 
-The following tracers (listed below) give different output
-depending on whether or not the sysctl ftrace_enabled is set. To
-set ftrace_enabled, one can either use the sysctl function or
-set it via the proc file system interface.
+  irq-info - Shows the interrupt, preempt count, need resched data.
+  	     When disabled, the trace looks like:
 
-  sysctl kernel.ftrace_enabled=1
+# tracer: function
+#
+# entries-in-buffer/entries-written: 144405/9452052   #P:4
+#
+#           TASK-PID   CPU#      TIMESTAMP  FUNCTION
+#              | |       |          |         |
+          <idle>-0     [002]  23636.756054: ttwu_do_activate.constprop.89 <-try_to_wake_up
+          <idle>-0     [002]  23636.756054: activate_task <-ttwu_do_activate.constprop.89
+          <idle>-0     [002]  23636.756055: enqueue_task <-activate_task
 
- or
 
-  echo 1 > /proc/sys/kernel/ftrace_enabled
+  markers - When set, the trace_marker is writable (only by root).
+  	    When disabled, the trace_marker will error with EINVAL
+	    on write.
+
+
+  function-trace - The latency tracers will enable function tracing
+  	    if this option is enabled (default it is). When
+	    it is disabled, the latency tracers do not trace
+	    functions. This keeps the overhead of the tracer down
+	    when performing latency tests.
 
-To disable ftrace_enabled simply replace the '1' with '0' in the
-above commands.
+ Note: Some tracers have their own options. They only appear
+       when the tracer is active.
 
-When ftrace_enabled is set the tracers will also record the
-functions that are within the trace. The descriptions of the
-tracers will also show an example with ftrace enabled.
 
 
 irqsoff
@@ -506,95 +903,133 @@ new trace is saved.
 To reset the maximum, echo 0 into tracing_max_latency. Here is
 an example:
 
+ # echo 0 > options/function-trace
  # echo irqsoff > current_tracer
- # echo latency-format > trace_options
- # echo 0 > tracing_max_latency
  # echo 1 > tracing_on
+ # echo 0 > tracing_max_latency
  # ls -ltr
  [...]
  # echo 0 > tracing_on
  # cat trace
 # tracer: irqsoff
 #
-irqsoff latency trace v1.1.5 on 2.6.26
---------------------------------------------------------------------
- latency: 12 us, #3/3, CPU#1 | (M:preempt VP:0, KP:0, SP:0 HP:0 #P:2)
-    -----------------
-    | task: bash-3730 (uid:0 nice:0 policy:0 rt_prio:0)
-    -----------------
- => started at: sys_setpgid
- => ended at:   sys_setpgid
-
-#                _------=> CPU#
-#               / _-----=> irqs-off
-#              | / _----=> need-resched
-#              || / _---=> hardirq/softirq
-#              ||| / _--=> preempt-depth
-#              |||| /
-#              |||||     delay
-#  cmd     pid ||||| time  |   caller
-#     \   /    |||||   \   |   /
-    bash-3730  1d...    0us : _write_lock_irq (sys_setpgid)
-    bash-3730  1d..1    1us+: _write_unlock_irq (sys_setpgid)
-    bash-3730  1d..2   14us : trace_hardirqs_on (sys_setpgid)
-
-
-Here we see that that we had a latency of 12 microsecs (which is
-very good). The _write_lock_irq in sys_setpgid disabled
-interrupts. The difference between the 12 and the displayed
-timestamp 14us occurred because the clock was incremented
+# irqsoff latency trace v1.1.5 on 3.8.0-test+
+# --------------------------------------------------------------------
+# latency: 16 us, #4/4, CPU#0 | (M:preempt VP:0, KP:0, SP:0 HP:0 #P:4)
+#    -----------------
+#    | task: swapper/0-0 (uid:0 nice:0 policy:0 rt_prio:0)
+#    -----------------
+#  => started at: run_timer_softirq
+#  => ended at:   run_timer_softirq
+#
+#
+#                  _------=> CPU#            
+#                 / _-----=> irqs-off        
+#                | / _----=> need-resched    
+#                || / _---=> hardirq/softirq 
+#                ||| / _--=> preempt-depth   
+#                |||| /     delay             
+#  cmd     pid   ||||| time  |   caller      
+#     \   /      |||||  \    |   /           
+  <idle>-0       0d.s2    0us+: _raw_spin_lock_irq <-run_timer_softirq
+  <idle>-0       0dNs3   17us : _raw_spin_unlock_irq <-run_timer_softirq
+  <idle>-0       0dNs3   17us+: trace_hardirqs_on <-run_timer_softirq
+  <idle>-0       0dNs3   25us : <stack trace>
+ => _raw_spin_unlock_irq
+ => run_timer_softirq
+ => __do_softirq
+ => call_softirq
+ => do_softirq
+ => irq_exit
+ => smp_apic_timer_interrupt
+ => apic_timer_interrupt
+ => rcu_idle_exit
+ => cpu_idle
+ => rest_init
+ => start_kernel
+ => x86_64_start_reservations
+ => x86_64_start_kernel
+
+Here we see that that we had a latency of 16 microseconds (which is
+very good). The _raw_spin_lock_irq in run_timer_softirq disabled
+interrupts. The difference between the 16 and the displayed
+timestamp 25us occurred because the clock was incremented
 between the time of recording the max latency and the time of
 recording the function that had that latency.
 
-Note the above example had ftrace_enabled not set. If we set the
-ftrace_enabled, we get a much larger output:
+Note the above example had function-trace not set. If we set
+function-trace, we get a much larger output:
+
+ with echo 1 > options/function-trace
 
 # tracer: irqsoff
 #
-irqsoff latency trace v1.1.5 on 2.6.26-rc8
---------------------------------------------------------------------
- latency: 50 us, #101/101, CPU#0 | (M:preempt VP:0, KP:0, SP:0 HP:0 #P:2)
-    -----------------
-    | task: ls-4339 (uid:0 nice:0 policy:0 rt_prio:0)
-    -----------------
- => started at: __alloc_pages_internal
- => ended at:   __alloc_pages_internal
-
-#                _------=> CPU#
-#               / _-----=> irqs-off
-#              | / _----=> need-resched
-#              || / _---=> hardirq/softirq
-#              ||| / _--=> preempt-depth
-#              |||| /
-#              |||||     delay
-#  cmd     pid ||||| time  |   caller
-#     \   /    |||||   \   |   /
-      ls-4339  0...1    0us+: get_page_from_freelist (__alloc_pages_internal)
-      ls-4339  0d..1    3us : rmqueue_bulk (get_page_from_freelist)
-      ls-4339  0d..1    3us : _spin_lock (rmqueue_bulk)
-      ls-4339  0d..1    4us : add_preempt_count (_spin_lock)
-      ls-4339  0d..2    4us : __rmqueue (rmqueue_bulk)
-      ls-4339  0d..2    5us : __rmqueue_smallest (__rmqueue)
-      ls-4339  0d..2    5us : __mod_zone_page_state (__rmqueue_smallest)
-      ls-4339  0d..2    6us : __rmqueue (rmqueue_bulk)
-      ls-4339  0d..2    6us : __rmqueue_smallest (__rmqueue)
-      ls-4339  0d..2    7us : __mod_zone_page_state (__rmqueue_smallest)
-      ls-4339  0d..2    7us : __rmqueue (rmqueue_bulk)
-      ls-4339  0d..2    8us : __rmqueue_smallest (__rmqueue)
+# irqsoff latency trace v1.1.5 on 3.8.0-test+
+# --------------------------------------------------------------------
+# latency: 71 us, #168/168, CPU#3 | (M:preempt VP:0, KP:0, SP:0 HP:0 #P:4)
+#    -----------------
+#    | task: bash-2042 (uid:0 nice:0 policy:0 rt_prio:0)
+#    -----------------
+#  => started at: ata_scsi_queuecmd
+#  => ended at:   ata_scsi_queuecmd
+#
+#
+#                  _------=> CPU#            
+#                 / _-----=> irqs-off        
+#                | / _----=> need-resched    
+#                || / _---=> hardirq/softirq 
+#                ||| / _--=> preempt-depth   
+#                |||| /     delay             
+#  cmd     pid   ||||| time  |   caller      
+#     \   /      |||||  \    |   /           
+    bash-2042    3d...    0us : _raw_spin_lock_irqsave <-ata_scsi_queuecmd
+    bash-2042    3d...    0us : add_preempt_count <-_raw_spin_lock_irqsave
+    bash-2042    3d..1    1us : ata_scsi_find_dev <-ata_scsi_queuecmd
+    bash-2042    3d..1    1us : __ata_scsi_find_dev <-ata_scsi_find_dev
+    bash-2042    3d..1    2us : ata_find_dev.part.14 <-__ata_scsi_find_dev
+    bash-2042    3d..1    2us : ata_qc_new_init <-__ata_scsi_queuecmd
+    bash-2042    3d..1    3us : ata_sg_init <-__ata_scsi_queuecmd
+    bash-2042    3d..1    4us : ata_scsi_rw_xlat <-__ata_scsi_queuecmd
+    bash-2042    3d..1    4us : ata_build_rw_tf <-ata_scsi_rw_xlat
 [...]
-      ls-4339  0d..2   46us : __rmqueue_smallest (__rmqueue)
-      ls-4339  0d..2   47us : __mod_zone_page_state (__rmqueue_smallest)
-      ls-4339  0d..2   47us : __rmqueue (rmqueue_bulk)
-      ls-4339  0d..2   48us : __rmqueue_smallest (__rmqueue)
-      ls-4339  0d..2   48us : __mod_zone_page_state (__rmqueue_smallest)
-      ls-4339  0d..2   49us : _spin_unlock (rmqueue_bulk)
-      ls-4339  0d..2   49us : sub_preempt_count (_spin_unlock)
-      ls-4339  0d..1   50us : get_page_from_freelist (__alloc_pages_internal)
-      ls-4339  0d..2   51us : trace_hardirqs_on (__alloc_pages_internal)
-
-
-
-Here we traced a 50 microsecond latency. But we also see all the
+    bash-2042    3d..1   67us : delay_tsc <-__delay
+    bash-2042    3d..1   67us : add_preempt_count <-delay_tsc
+    bash-2042    3d..2   67us : sub_preempt_count <-delay_tsc
+    bash-2042    3d..1   67us : add_preempt_count <-delay_tsc
+    bash-2042    3d..2   68us : sub_preempt_count <-delay_tsc
+    bash-2042    3d..1   68us+: ata_bmdma_start <-ata_bmdma_qc_issue
+    bash-2042    3d..1   71us : _raw_spin_unlock_irqrestore <-ata_scsi_queuecmd
+    bash-2042    3d..1   71us : _raw_spin_unlock_irqrestore <-ata_scsi_queuecmd
+    bash-2042    3d..1   72us+: trace_hardirqs_on <-ata_scsi_queuecmd
+    bash-2042    3d..1  120us : <stack trace>
+ => _raw_spin_unlock_irqrestore
+ => ata_scsi_queuecmd
+ => scsi_dispatch_cmd
+ => scsi_request_fn
+ => __blk_run_queue_uncond
+ => __blk_run_queue
+ => blk_queue_bio
+ => generic_make_request
+ => submit_bio
+ => submit_bh
+ => __ext3_get_inode_loc
+ => ext3_iget
+ => ext3_lookup
+ => lookup_real
+ => __lookup_hash
+ => walk_component
+ => lookup_last
+ => path_lookupat
+ => filename_lookup
+ => user_path_at_empty
+ => user_path_at
+ => vfs_fstatat
+ => vfs_stat
+ => sys_newstat
+ => system_call_fastpath
+
+
+Here we traced a 71 microsecond latency. But we also see all the
 functions that were called during that time. Note that by
 enabling function tracing, we incur an added overhead. This
 overhead may extend the latency times. But nevertheless, this
@@ -614,120 +1049,122 @@ Like the irqsoff tracer, it records the maximum latency for
 which preemption was disabled. The control of preemptoff tracer
 is much like the irqsoff tracer.
 
+ # echo 0 > options/function-trace
  # echo preemptoff > current_tracer
- # echo latency-format > trace_options
- # echo 0 > tracing_max_latency
  # echo 1 > tracing_on
+ # echo 0 > tracing_max_latency
  # ls -ltr
  [...]
  # echo 0 > tracing_on
  # cat trace
 # tracer: preemptoff
 #
-preemptoff latency trace v1.1.5 on 2.6.26-rc8
---------------------------------------------------------------------
- latency: 29 us, #3/3, CPU#0 | (M:preempt VP:0, KP:0, SP:0 HP:0 #P:2)
-    -----------------
-    | task: sshd-4261 (uid:0 nice:0 policy:0 rt_prio:0)
-    -----------------
- => started at: do_IRQ
- => ended at:   __do_softirq
-
-#                _------=> CPU#
-#               / _-----=> irqs-off
-#              | / _----=> need-resched
-#              || / _---=> hardirq/softirq
-#              ||| / _--=> preempt-depth
-#              |||| /
-#              |||||     delay
-#  cmd     pid ||||| time  |   caller
-#     \   /    |||||   \   |   /
-    sshd-4261  0d.h.    0us+: irq_enter (do_IRQ)
-    sshd-4261  0d.s.   29us : _local_bh_enable (__do_softirq)
-    sshd-4261  0d.s1   30us : trace_preempt_on (__do_softirq)
+# preemptoff latency trace v1.1.5 on 3.8.0-test+
+# --------------------------------------------------------------------
+# latency: 46 us, #4/4, CPU#1 | (M:preempt VP:0, KP:0, SP:0 HP:0 #P:4)
+#    -----------------
+#    | task: sshd-1991 (uid:0 nice:0 policy:0 rt_prio:0)
+#    -----------------
+#  => started at: do_IRQ
+#  => ended at:   do_IRQ
+#
+#
+#                  _------=> CPU#            
+#                 / _-----=> irqs-off        
+#                | / _----=> need-resched    
+#                || / _---=> hardirq/softirq 
+#                ||| / _--=> preempt-depth   
+#                |||| /     delay             
+#  cmd     pid   ||||| time  |   caller      
+#     \   /      |||||  \    |   /           
+    sshd-1991    1d.h.    0us+: irq_enter <-do_IRQ
+    sshd-1991    1d..1   46us : irq_exit <-do_IRQ
+    sshd-1991    1d..1   47us+: trace_preempt_on <-do_IRQ
+    sshd-1991    1d..1   52us : <stack trace>
+ => sub_preempt_count
+ => irq_exit
+ => do_IRQ
+ => ret_from_intr
 
 
 This has some more changes. Preemption was disabled when an
-interrupt came in (notice the 'h'), and was enabled while doing
-a softirq. (notice the 's'). But we also see that interrupts
-have been disabled when entering the preempt off section and
-leaving it (the 'd'). We do not know if interrupts were enabled
-in the mean time.
+interrupt came in (notice the 'h'), and was enabled on exit.
+But we also see that interrupts have been disabled when entering
+the preempt off section and leaving it (the 'd'). We do not know if
+interrupts were enabled in the mean time or shortly after this
+was over.
 
 # tracer: preemptoff
 #
-preemptoff latency trace v1.1.5 on 2.6.26-rc8
---------------------------------------------------------------------
- latency: 63 us, #87/87, CPU#0 | (M:preempt VP:0, KP:0, SP:0 HP:0 #P:2)
-    -----------------
-    | task: sshd-4261 (uid:0 nice:0 policy:0 rt_prio:0)
-    -----------------
- => started at: remove_wait_queue
- => ended at:   __do_softirq
-
-#                _------=> CPU#
-#               / _-----=> irqs-off
-#              | / _----=> need-resched
-#              || / _---=> hardirq/softirq
-#              ||| / _--=> preempt-depth
-#              |||| /
-#              |||||     delay
-#  cmd     pid ||||| time  |   caller
-#     \   /    |||||   \   |   /
-    sshd-4261  0d..1    0us : _spin_lock_irqsave (remove_wait_queue)
-    sshd-4261  0d..1    1us : _spin_unlock_irqrestore (remove_wait_queue)
-    sshd-4261  0d..1    2us : do_IRQ (common_interrupt)
-    sshd-4261  0d..1    2us : irq_enter (do_IRQ)
-    sshd-4261  0d..1    2us : idle_cpu (irq_enter)
-    sshd-4261  0d..1    3us : add_preempt_count (irq_enter)
-    sshd-4261  0d.h1    3us : idle_cpu (irq_enter)
-    sshd-4261  0d.h.    4us : handle_fasteoi_irq (do_IRQ)
+# preemptoff latency trace v1.1.5 on 3.8.0-test+
+# --------------------------------------------------------------------
+# latency: 83 us, #241/241, CPU#1 | (M:preempt VP:0, KP:0, SP:0 HP:0 #P:4)
+#    -----------------
+#    | task: bash-1994 (uid:0 nice:0 policy:0 rt_prio:0)
+#    -----------------
+#  => started at: wake_up_new_task
+#  => ended at:   task_rq_unlock
+#
+#
+#                  _------=> CPU#            
+#                 / _-----=> irqs-off        
+#                | / _----=> need-resched    
+#                || / _---=> hardirq/softirq 
+#                ||| / _--=> preempt-depth   
+#                |||| /     delay             
+#  cmd     pid   ||||| time  |   caller      
+#     \   /      |||||  \    |   /           
+    bash-1994    1d..1    0us : _raw_spin_lock_irqsave <-wake_up_new_task
+    bash-1994    1d..1    0us : select_task_rq_fair <-select_task_rq
+    bash-1994    1d..1    1us : __rcu_read_lock <-select_task_rq_fair
+    bash-1994    1d..1    1us : source_load <-select_task_rq_fair
+    bash-1994    1d..1    1us : source_load <-select_task_rq_fair
 [...]
-    sshd-4261  0d.h.   12us : add_preempt_count (_spin_lock)
-    sshd-4261  0d.h1   12us : ack_ioapic_quirk_irq (handle_fasteoi_irq)
-    sshd-4261  0d.h1   13us : move_native_irq (ack_ioapic_quirk_irq)
-    sshd-4261  0d.h1   13us : _spin_unlock (handle_fasteoi_irq)
-    sshd-4261  0d.h1   14us : sub_preempt_count (_spin_unlock)
-    sshd-4261  0d.h1   14us : irq_exit (do_IRQ)
-    sshd-4261  0d.h1   15us : sub_preempt_count (irq_exit)
-    sshd-4261  0d..2   15us : do_softirq (irq_exit)
-    sshd-4261  0d...   15us : __do_softirq (do_softirq)
-    sshd-4261  0d...   16us : __local_bh_disable (__do_softirq)
-    sshd-4261  0d...   16us+: add_preempt_count (__local_bh_disable)
-    sshd-4261  0d.s4   20us : add_preempt_count (__local_bh_disable)
-    sshd-4261  0d.s4   21us : sub_preempt_count (local_bh_enable)
-    sshd-4261  0d.s5   21us : sub_preempt_count (local_bh_enable)
+    bash-1994    1d..1   12us : irq_enter <-smp_apic_timer_interrupt
+    bash-1994    1d..1   12us : rcu_irq_enter <-irq_enter
+    bash-1994    1d..1   13us : add_preempt_count <-irq_enter
+    bash-1994    1d.h1   13us : exit_idle <-smp_apic_timer_interrupt
+    bash-1994    1d.h1   13us : hrtimer_interrupt <-smp_apic_timer_interrupt
+    bash-1994    1d.h1   13us : _raw_spin_lock <-hrtimer_interrupt
+    bash-1994    1d.h1   14us : add_preempt_count <-_raw_spin_lock
+    bash-1994    1d.h2   14us : ktime_get_update_offsets <-hrtimer_interrupt
 [...]
-    sshd-4261  0d.s6   41us : add_preempt_count (__local_bh_disable)
-    sshd-4261  0d.s6   42us : sub_preempt_count (local_bh_enable)
-    sshd-4261  0d.s7   42us : sub_preempt_count (local_bh_enable)
-    sshd-4261  0d.s5   43us : add_preempt_count (__local_bh_disable)
-    sshd-4261  0d.s5   43us : sub_preempt_count (local_bh_enable_ip)
-    sshd-4261  0d.s6   44us : sub_preempt_count (local_bh_enable_ip)
-    sshd-4261  0d.s5   44us : add_preempt_count (__local_bh_disable)
-    sshd-4261  0d.s5   45us : sub_preempt_count (local_bh_enable)
+    bash-1994    1d.h1   35us : lapic_next_event <-clockevents_program_event
+    bash-1994    1d.h1   35us : irq_exit <-smp_apic_timer_interrupt
+    bash-1994    1d.h1   36us : sub_preempt_count <-irq_exit
+    bash-1994    1d..2   36us : do_softirq <-irq_exit
+    bash-1994    1d..2   36us : __do_softirq <-call_softirq
+    bash-1994    1d..2   36us : __local_bh_disable <-__do_softirq
+    bash-1994    1d.s2   37us : add_preempt_count <-_raw_spin_lock_irq
+    bash-1994    1d.s3   38us : _raw_spin_unlock <-run_timer_softirq
+    bash-1994    1d.s3   39us : sub_preempt_count <-_raw_spin_unlock
+    bash-1994    1d.s2   39us : call_timer_fn <-run_timer_softirq
 [...]
-    sshd-4261  0d.s.   63us : _local_bh_enable (__do_softirq)
-    sshd-4261  0d.s1   64us : trace_preempt_on (__do_softirq)
+    bash-1994    1dNs2   81us : cpu_needs_another_gp <-rcu_process_callbacks
+    bash-1994    1dNs2   82us : __local_bh_enable <-__do_softirq
+    bash-1994    1dNs2   82us : sub_preempt_count <-__local_bh_enable
+    bash-1994    1dN.2   82us : idle_cpu <-irq_exit
+    bash-1994    1dN.2   83us : rcu_irq_exit <-irq_exit
+    bash-1994    1dN.2   83us : sub_preempt_count <-irq_exit
+    bash-1994    1.N.1   84us : _raw_spin_unlock_irqrestore <-task_rq_unlock
+    bash-1994    1.N.1   84us+: trace_preempt_on <-task_rq_unlock
+    bash-1994    1.N.1  104us : <stack trace>
+ => sub_preempt_count
+ => _raw_spin_unlock_irqrestore
+ => task_rq_unlock
+ => wake_up_new_task
+ => do_fork
+ => sys_clone
+ => stub_clone
 
 
 The above is an example of the preemptoff trace with
-ftrace_enabled set. Here we see that interrupts were disabled
+function-trace set. Here we see that interrupts were not disabled
 the entire time. The irq_enter code lets us know that we entered
 an interrupt 'h'. Before that, the functions being traced still
 show that it is not in an interrupt, but we can see from the
 functions themselves that this is not the case.
 
-Notice that __do_softirq when called does not have a
-preempt_count. It may seem that we missed a preempt enabling.
-What really happened is that the preempt count is held on the
-thread's stack and we switched to the softirq stack (4K stacks
-in effect). The code does not copy the preempt count, but
-because interrupts are disabled, we do not need to worry about
-it. Having a tracer like this is good for letting people know
-what really happens inside the kernel.
-
-
 preemptirqsoff
 --------------
 
@@ -762,38 +1199,57 @@ tracer.
 Again, using this trace is much like the irqsoff and preemptoff
 tracers.
 
+ # echo 0 > options/function-trace
  # echo preemptirqsoff > current_tracer
- # echo latency-format > trace_options
- # echo 0 > tracing_max_latency
  # echo 1 > tracing_on
+ # echo 0 > tracing_max_latency
  # ls -ltr
  [...]
  # echo 0 > tracing_on
  # cat trace
 # tracer: preemptirqsoff
 #
-preemptirqsoff latency trace v1.1.5 on 2.6.26-rc8
---------------------------------------------------------------------
- latency: 293 us, #3/3, CPU#0 | (M:preempt VP:0, KP:0, SP:0 HP:0 #P:2)
-    -----------------
-    | task: ls-4860 (uid:0 nice:0 policy:0 rt_prio:0)
-    -----------------
- => started at: apic_timer_interrupt
- => ended at:   __do_softirq
-
-#                _------=> CPU#
-#               / _-----=> irqs-off
-#              | / _----=> need-resched
-#              || / _---=> hardirq/softirq
-#              ||| / _--=> preempt-depth
-#              |||| /
-#              |||||     delay
-#  cmd     pid ||||| time  |   caller
-#     \   /    |||||   \   |   /
-      ls-4860  0d...    0us!: trace_hardirqs_off_thunk (apic_timer_interrupt)
-      ls-4860  0d.s.  294us : _local_bh_enable (__do_softirq)
-      ls-4860  0d.s1  294us : trace_preempt_on (__do_softirq)
-
+# preemptirqsoff latency trace v1.1.5 on 3.8.0-test+
+# --------------------------------------------------------------------
+# latency: 100 us, #4/4, CPU#3 | (M:preempt VP:0, KP:0, SP:0 HP:0 #P:4)
+#    -----------------
+#    | task: ls-2230 (uid:0 nice:0 policy:0 rt_prio:0)
+#    -----------------
+#  => started at: ata_scsi_queuecmd
+#  => ended at:   ata_scsi_queuecmd
+#
+#
+#                  _------=> CPU#            
+#                 / _-----=> irqs-off        
+#                | / _----=> need-resched    
+#                || / _---=> hardirq/softirq 
+#                ||| / _--=> preempt-depth   
+#                |||| /     delay             
+#  cmd     pid   ||||| time  |   caller      
+#     \   /      |||||  \    |   /           
+      ls-2230    3d...    0us+: _raw_spin_lock_irqsave <-ata_scsi_queuecmd
+      ls-2230    3...1  100us : _raw_spin_unlock_irqrestore <-ata_scsi_queuecmd
+      ls-2230    3...1  101us+: trace_preempt_on <-ata_scsi_queuecmd
+      ls-2230    3...1  111us : <stack trace>
+ => sub_preempt_count
+ => _raw_spin_unlock_irqrestore
+ => ata_scsi_queuecmd
+ => scsi_dispatch_cmd
+ => scsi_request_fn
+ => __blk_run_queue_uncond
+ => __blk_run_queue
+ => blk_queue_bio
+ => generic_make_request
+ => submit_bio
+ => submit_bh
+ => ext3_bread
+ => ext3_dir_bread
+ => htree_dirblock_to_tree
+ => ext3_htree_fill_tree
+ => ext3_readdir
+ => vfs_readdir
+ => sys_getdents
+ => system_call_fastpath
 
 
 The trace_hardirqs_off_thunk is called from assembly on x86 when
@@ -802,105 +1258,158 @@ function tracing, we do not know if interrupts were enabled
 within the preemption points. We do see that it started with
 preemption enabled.
 
-Here is a trace with ftrace_enabled set:
-
+Here is a trace with function-trace set:
 
 # tracer: preemptirqsoff
 #
-preemptirqsoff latency trace v1.1.5 on 2.6.26-rc8
---------------------------------------------------------------------
- latency: 105 us, #183/183, CPU#0 | (M:preempt VP:0, KP:0, SP:0 HP:0 #P:2)
-    -----------------
-    | task: sshd-4261 (uid:0 nice:0 policy:0 rt_prio:0)
-    -----------------
- => started at: write_chan
- => ended at:   __do_softirq
-
-#                _------=> CPU#
-#               / _-----=> irqs-off
-#              | / _----=> need-resched
-#              || / _---=> hardirq/softirq
-#              ||| / _--=> preempt-depth
-#              |||| /
-#              |||||     delay
-#  cmd     pid ||||| time  |   caller
-#     \   /    |||||   \   |   /
-      ls-4473  0.N..    0us : preempt_schedule (write_chan)
-      ls-4473  0dN.1    1us : _spin_lock (schedule)
-      ls-4473  0dN.1    2us : add_preempt_count (_spin_lock)
-      ls-4473  0d..2    2us : put_prev_task_fair (schedule)
-[...]
-      ls-4473  0d..2   13us : set_normalized_timespec (ktime_get_ts)
-      ls-4473  0d..2   13us : __switch_to (schedule)
-    sshd-4261  0d..2   14us : finish_task_switch (schedule)
-    sshd-4261  0d..2   14us : _spin_unlock_irq (finish_task_switch)
-    sshd-4261  0d..1   15us : add_preempt_count (_spin_lock_irqsave)
-    sshd-4261  0d..2   16us : _spin_unlock_irqrestore (hrtick_set)
-    sshd-4261  0d..2   16us : do_IRQ (common_interrupt)
-    sshd-4261  0d..2   17us : irq_enter (do_IRQ)
-    sshd-4261  0d..2   17us : idle_cpu (irq_enter)
-    sshd-4261  0d..2   18us : add_preempt_count (irq_enter)
-    sshd-4261  0d.h2   18us : idle_cpu (irq_enter)
-    sshd-4261  0d.h.   18us : handle_fasteoi_irq (do_IRQ)
-    sshd-4261  0d.h.   19us : _spin_lock (handle_fasteoi_irq)
-    sshd-4261  0d.h.   19us : add_preempt_count (_spin_lock)
-    sshd-4261  0d.h1   20us : _spin_unlock (handle_fasteoi_irq)
-    sshd-4261  0d.h1   20us : sub_preempt_count (_spin_unlock)
-[...]
-    sshd-4261  0d.h1   28us : _spin_unlock (handle_fasteoi_irq)
-    sshd-4261  0d.h1   29us : sub_preempt_count (_spin_unlock)
-    sshd-4261  0d.h2   29us : irq_exit (do_IRQ)
-    sshd-4261  0d.h2   29us : sub_preempt_count (irq_exit)
-    sshd-4261  0d..3   30us : do_softirq (irq_exit)
-    sshd-4261  0d...   30us : __do_softirq (do_softirq)
-    sshd-4261  0d...   31us : __local_bh_disable (__do_softirq)
-    sshd-4261  0d...   31us+: add_preempt_count (__local_bh_disable)
-    sshd-4261  0d.s4   34us : add_preempt_count (__local_bh_disable)
+# preemptirqsoff latency trace v1.1.5 on 3.8.0-test+
+# --------------------------------------------------------------------
+# latency: 161 us, #339/339, CPU#3 | (M:preempt VP:0, KP:0, SP:0 HP:0 #P:4)
+#    -----------------
+#    | task: ls-2269 (uid:0 nice:0 policy:0 rt_prio:0)
+#    -----------------
+#  => started at: schedule
+#  => ended at:   mutex_unlock
+#
+#
+#                  _------=> CPU#            
+#                 / _-----=> irqs-off        
+#                | / _----=> need-resched    
+#                || / _---=> hardirq/softirq 
+#                ||| / _--=> preempt-depth   
+#                |||| /     delay             
+#  cmd     pid   ||||| time  |   caller      
+#     \   /      |||||  \    |   /           
+kworker/-59      3...1    0us : __schedule <-schedule
+kworker/-59      3d..1    0us : rcu_preempt_qs <-rcu_note_context_switch
+kworker/-59      3d..1    1us : add_preempt_count <-_raw_spin_lock_irq
+kworker/-59      3d..2    1us : deactivate_task <-__schedule
+kworker/-59      3d..2    1us : dequeue_task <-deactivate_task
+kworker/-59      3d..2    2us : update_rq_clock <-dequeue_task
+kworker/-59      3d..2    2us : dequeue_task_fair <-dequeue_task
+kworker/-59      3d..2    2us : update_curr <-dequeue_task_fair
+kworker/-59      3d..2    2us : update_min_vruntime <-update_curr
+kworker/-59      3d..2    3us : cpuacct_charge <-update_curr
+kworker/-59      3d..2    3us : __rcu_read_lock <-cpuacct_charge
+kworker/-59      3d..2    3us : __rcu_read_unlock <-cpuacct_charge
+kworker/-59      3d..2    3us : update_cfs_rq_blocked_load <-dequeue_task_fair
+kworker/-59      3d..2    4us : clear_buddies <-dequeue_task_fair
+kworker/-59      3d..2    4us : account_entity_dequeue <-dequeue_task_fair
+kworker/-59      3d..2    4us : update_min_vruntime <-dequeue_task_fair
+kworker/-59      3d..2    4us : update_cfs_shares <-dequeue_task_fair
+kworker/-59      3d..2    5us : hrtick_update <-dequeue_task_fair
+kworker/-59      3d..2    5us : wq_worker_sleeping <-__schedule
+kworker/-59      3d..2    5us : kthread_data <-wq_worker_sleeping
+kworker/-59      3d..2    5us : put_prev_task_fair <-__schedule
+kworker/-59      3d..2    6us : pick_next_task_fair <-pick_next_task
+kworker/-59      3d..2    6us : clear_buddies <-pick_next_task_fair
+kworker/-59      3d..2    6us : set_next_entity <-pick_next_task_fair
+kworker/-59      3d..2    6us : update_stats_wait_end <-set_next_entity
+      ls-2269    3d..2    7us : finish_task_switch <-__schedule
+      ls-2269    3d..2    7us : _raw_spin_unlock_irq <-finish_task_switch
+      ls-2269    3d..2    8us : do_IRQ <-ret_from_intr
+      ls-2269    3d..2    8us : irq_enter <-do_IRQ
+      ls-2269    3d..2    8us : rcu_irq_enter <-irq_enter
+      ls-2269    3d..2    9us : add_preempt_count <-irq_enter
+      ls-2269    3d.h2    9us : exit_idle <-do_IRQ
 [...]
-    sshd-4261  0d.s3   43us : sub_preempt_count (local_bh_enable_ip)
-    sshd-4261  0d.s4   44us : sub_preempt_count (local_bh_enable_ip)
-    sshd-4261  0d.s3   44us : smp_apic_timer_interrupt (apic_timer_interrupt)
-    sshd-4261  0d.s3   45us : irq_enter (smp_apic_timer_interrupt)
-    sshd-4261  0d.s3   45us : idle_cpu (irq_enter)
-    sshd-4261  0d.s3   46us : add_preempt_count (irq_enter)
-    sshd-4261  0d.H3   46us : idle_cpu (irq_enter)
-    sshd-4261  0d.H3   47us : hrtimer_interrupt (smp_apic_timer_interrupt)
-    sshd-4261  0d.H3   47us : ktime_get (hrtimer_interrupt)
+      ls-2269    3d.h3   20us : sub_preempt_count <-_raw_spin_unlock
+      ls-2269    3d.h2   20us : irq_exit <-do_IRQ
+      ls-2269    3d.h2   21us : sub_preempt_count <-irq_exit
+      ls-2269    3d..3   21us : do_softirq <-irq_exit
+      ls-2269    3d..3   21us : __do_softirq <-call_softirq
+      ls-2269    3d..3   21us+: __local_bh_disable <-__do_softirq
+      ls-2269    3d.s4   29us : sub_preempt_count <-_local_bh_enable_ip
+      ls-2269    3d.s5   29us : sub_preempt_count <-_local_bh_enable_ip
+      ls-2269    3d.s5   31us : do_IRQ <-ret_from_intr
+      ls-2269    3d.s5   31us : irq_enter <-do_IRQ
+      ls-2269    3d.s5   31us : rcu_irq_enter <-irq_enter
 [...]
-    sshd-4261  0d.H3   81us : tick_program_event (hrtimer_interrupt)
-    sshd-4261  0d.H3   82us : ktime_get (tick_program_event)
-    sshd-4261  0d.H3   82us : ktime_get_ts (ktime_get)
-    sshd-4261  0d.H3   83us : getnstimeofday (ktime_get_ts)
-    sshd-4261  0d.H3   83us : set_normalized_timespec (ktime_get_ts)
-    sshd-4261  0d.H3   84us : clockevents_program_event (tick_program_event)
-    sshd-4261  0d.H3   84us : lapic_next_event (clockevents_program_event)
-    sshd-4261  0d.H3   85us : irq_exit (smp_apic_timer_interrupt)
-    sshd-4261  0d.H3   85us : sub_preempt_count (irq_exit)
-    sshd-4261  0d.s4   86us : sub_preempt_count (irq_exit)
-    sshd-4261  0d.s3   86us : add_preempt_count (__local_bh_disable)
+      ls-2269    3d.s5   31us : rcu_irq_enter <-irq_enter
+      ls-2269    3d.s5   32us : add_preempt_count <-irq_enter
+      ls-2269    3d.H5   32us : exit_idle <-do_IRQ
+      ls-2269    3d.H5   32us : handle_irq <-do_IRQ
+      ls-2269    3d.H5   32us : irq_to_desc <-handle_irq
+      ls-2269    3d.H5   33us : handle_fasteoi_irq <-handle_irq
 [...]
-    sshd-4261  0d.s1   98us : sub_preempt_count (net_rx_action)
-    sshd-4261  0d.s.   99us : add_preempt_count (_spin_lock_irq)
-    sshd-4261  0d.s1   99us+: _spin_unlock_irq (run_timer_softirq)
-    sshd-4261  0d.s.  104us : _local_bh_enable (__do_softirq)
-    sshd-4261  0d.s.  104us : sub_preempt_count (_local_bh_enable)
-    sshd-4261  0d.s.  105us : _local_bh_enable (__do_softirq)
-    sshd-4261  0d.s1  105us : trace_preempt_on (__do_softirq)
-
-
-This is a very interesting trace. It started with the preemption
-of the ls task. We see that the task had the "need_resched" bit
-set via the 'N' in the trace.  Interrupts were disabled before
-the spin_lock at the beginning of the trace. We see that a
-schedule took place to run sshd.  When the interrupts were
-enabled, we took an interrupt. On return from the interrupt
-handler, the softirq ran. We took another interrupt while
-running the softirq as we see from the capital 'H'.
+      ls-2269    3d.s5  158us : _raw_spin_unlock_irqrestore <-rtl8139_poll
+      ls-2269    3d.s3  158us : net_rps_action_and_irq_enable.isra.65 <-net_rx_action
+      ls-2269    3d.s3  159us : __local_bh_enable <-__do_softirq
+      ls-2269    3d.s3  159us : sub_preempt_count <-__local_bh_enable
+      ls-2269    3d..3  159us : idle_cpu <-irq_exit
+      ls-2269    3d..3  159us : rcu_irq_exit <-irq_exit
+      ls-2269    3d..3  160us : sub_preempt_count <-irq_exit
+      ls-2269    3d...  161us : __mutex_unlock_slowpath <-mutex_unlock
+      ls-2269    3d...  162us+: trace_hardirqs_on <-mutex_unlock
+      ls-2269    3d...  186us : <stack trace>
+ => __mutex_unlock_slowpath
+ => mutex_unlock
+ => process_output
+ => n_tty_write
+ => tty_write
+ => vfs_write
+ => sys_write
+ => system_call_fastpath
+
+This is an interesting trace. It started with kworker running and
+scheduling out and ls taking over. But as soon as ls released the
+rq lock and enabled interrupts (but not preemption) an interrupt
+triggered. When the interrupt finished, it started running softirqs.
+But while the softirq was running, another interrupt triggered.
+When an interrupt is running inside a softirq, the annotation is 'H'.
 
 
 wakeup
 ------
 
+One common case that people are interested in tracing is the
+time it takes for a task that is woken to actually wake up.
+Now for non Real-Time tasks, this can be arbitrary. But tracing
+it none the less can be interesting. 
+
+Without function tracing:
+
+ # echo 0 > options/function-trace
+ # echo wakeup > current_tracer
+ # echo 1 > tracing_on
+ # echo 0 > tracing_max_latency
+ # chrt -f 5 sleep 1
+ # echo 0 > tracing_on
+ # cat trace
+# tracer: wakeup
+#
+# wakeup latency trace v1.1.5 on 3.8.0-test+
+# --------------------------------------------------------------------
+# latency: 15 us, #4/4, CPU#3 | (M:preempt VP:0, KP:0, SP:0 HP:0 #P:4)
+#    -----------------
+#    | task: kworker/3:1H-312 (uid:0 nice:-20 policy:0 rt_prio:0)
+#    -----------------
+#
+#                  _------=> CPU#            
+#                 / _-----=> irqs-off        
+#                | / _----=> need-resched    
+#                || / _---=> hardirq/softirq 
+#                ||| / _--=> preempt-depth   
+#                |||| /     delay             
+#  cmd     pid   ||||| time  |   caller      
+#     \   /      |||||  \    |   /           
+  <idle>-0       3dNs7    0us :      0:120:R   + [003]   312:100:R kworker/3:1H
+  <idle>-0       3dNs7    1us+: ttwu_do_activate.constprop.87 <-try_to_wake_up
+  <idle>-0       3d..3   15us : __schedule <-schedule
+  <idle>-0       3d..3   15us :      0:120:R ==> [003]   312:100:R kworker/3:1H
+
+The tracer only traces the highest priority task in the system
+to avoid tracing the normal circumstances. Here we see that
+the kworker with a nice priority of -20 (not very nice), took
+just 15 microseconds from the time it woke up, to the time it
+ran.
+
+Non Real-Time tasks are not that interesting. A more interesting
+trace is to concentrate only on Real-Time tasks.
+
+wakeup_rt
+---------
+
 In a Real-Time environment it is very important to know the
 wakeup time it takes for the highest priority task that is woken
 up to the time that it executes. This is also known as "schedule
@@ -914,124 +1423,229 @@ Real-Time environments are interested in the worst case latency.
 That is the longest latency it takes for something to happen,
 and not the average. We can have a very fast scheduler that may
 only have a large latency once in a while, but that would not
-work well with Real-Time tasks.  The wakeup tracer was designed
+work well with Real-Time tasks.  The wakeup_rt tracer was designed
 to record the worst case wakeups of RT tasks. Non-RT tasks are
 not recorded because the tracer only records one worst case and
 tracing non-RT tasks that are unpredictable will overwrite the
-worst case latency of RT tasks.
+worst case latency of RT tasks (just run the normal wakeup
+tracer for a while to see that effect).
 
 Since this tracer only deals with RT tasks, we will run this
 slightly differently than we did with the previous tracers.
 Instead of performing an 'ls', we will run 'sleep 1' under
 'chrt' which changes the priority of the task.
 
- # echo wakeup > current_tracer
- # echo latency-format > trace_options
- # echo 0 > tracing_max_latency
+ # echo 0 > options/function-trace
+ # echo wakeup_rt > current_tracer
  # echo 1 > tracing_on
+ # echo 0 > tracing_max_latency
  # chrt -f 5 sleep 1
  # echo 0 > tracing_on
  # cat trace
 # tracer: wakeup
 #
-wakeup latency trace v1.1.5 on 2.6.26-rc8
---------------------------------------------------------------------
- latency: 4 us, #2/2, CPU#1 | (M:preempt VP:0, KP:0, SP:0 HP:0 #P:2)
-    -----------------
-    | task: sleep-4901 (uid:0 nice:0 policy:1 rt_prio:5)
-    -----------------
-
-#                _------=> CPU#
-#               / _-----=> irqs-off
-#              | / _----=> need-resched
-#              || / _---=> hardirq/softirq
-#              ||| / _--=> preempt-depth
-#              |||| /
-#              |||||     delay
-#  cmd     pid ||||| time  |   caller
-#     \   /    |||||   \   |   /
-  <idle>-0     1d.h4    0us+: try_to_wake_up (wake_up_process)
-  <idle>-0     1d..4    4us : schedule (cpu_idle)
-
-
-Running this on an idle system, we see that it only took 4
-microseconds to perform the task switch.  Note, since the trace
-marker in the schedule is before the actual "switch", we stop
-the tracing when the recorded task is about to schedule in. This
-may change if we add a new marker at the end of the scheduler.
-
-Notice that the recorded task is 'sleep' with the PID of 4901
+# tracer: wakeup_rt
+#
+# wakeup_rt latency trace v1.1.5 on 3.8.0-test+
+# --------------------------------------------------------------------
+# latency: 5 us, #4/4, CPU#3 | (M:preempt VP:0, KP:0, SP:0 HP:0 #P:4)
+#    -----------------
+#    | task: sleep-2389 (uid:0 nice:0 policy:1 rt_prio:5)
+#    -----------------
+#
+#                  _------=> CPU#            
+#                 / _-----=> irqs-off        
+#                | / _----=> need-resched    
+#                || / _---=> hardirq/softirq 
+#                ||| / _--=> preempt-depth   
+#                |||| /     delay             
+#  cmd     pid   ||||| time  |   caller      
+#     \   /      |||||  \    |   /           
+  <idle>-0       3d.h4    0us :      0:120:R   + [003]  2389: 94:R sleep
+  <idle>-0       3d.h4    1us+: ttwu_do_activate.constprop.87 <-try_to_wake_up
+  <idle>-0       3d..3    5us : __schedule <-schedule
+  <idle>-0       3d..3    5us :      0:120:R ==> [003]  2389: 94:R sleep
+
+
+Running this on an idle system, we see that it only took 5 microseconds
+to perform the task switch.  Note, since the trace point in the schedule
+is before the actual "switch", we stop the tracing when the recorded task
+is about to schedule in. This may change if we add a new marker at the
+end of the scheduler.
+
+Notice that the recorded task is 'sleep' with the PID of 2389
 and it has an rt_prio of 5. This priority is user-space priority
 and not the internal kernel priority. The policy is 1 for
 SCHED_FIFO and 2 for SCHED_RR.
 
-Doing the same with chrt -r 5 and ftrace_enabled set.
+Note, that the trace data shows the internal priority (99 - rtprio).
 
-# tracer: wakeup
+  <idle>-0       3d..3    5us :      0:120:R ==> [003]  2389: 94:R sleep
+
+The 0:120:R means idle was running with a nice priority of 0 (120 - 20)
+and in the running state 'R'. The sleep task was scheduled in with
+2389: 94:R. That is the priority is the kernel rtprio (99 - 5 = 94)
+and it too is in the running state.
+
+Doing the same with chrt -r 5 and function-trace set.
+
+  echo 1 > options/function-trace
+
+# tracer: wakeup_rt
 #
-wakeup latency trace v1.1.5 on 2.6.26-rc8
---------------------------------------------------------------------
- latency: 50 us, #60/60, CPU#1 | (M:preempt VP:0, KP:0, SP:0 HP:0 #P:2)
-    -----------------
-    | task: sleep-4068 (uid:0 nice:0 policy:2 rt_prio:5)
-    -----------------
-
-#                _------=> CPU#
-#               / _-----=> irqs-off
-#              | / _----=> need-resched
-#              || / _---=> hardirq/softirq
-#              ||| / _--=> preempt-depth
-#              |||| /
-#              |||||     delay
-#  cmd     pid ||||| time  |   caller
-#     \   /    |||||   \   |   /
-ksoftirq-7     1d.H3    0us : try_to_wake_up (wake_up_process)
-ksoftirq-7     1d.H4    1us : sub_preempt_count (marker_probe_cb)
-ksoftirq-7     1d.H3    2us : check_preempt_wakeup (try_to_wake_up)
-ksoftirq-7     1d.H3    3us : update_curr (check_preempt_wakeup)
-ksoftirq-7     1d.H3    4us : calc_delta_mine (update_curr)
-ksoftirq-7     1d.H3    5us : __resched_task (check_preempt_wakeup)
-ksoftirq-7     1d.H3    6us : task_wake_up_rt (try_to_wake_up)
-ksoftirq-7     1d.H3    7us : _spin_unlock_irqrestore (try_to_wake_up)
-[...]
-ksoftirq-7     1d.H2   17us : irq_exit (smp_apic_timer_interrupt)
-ksoftirq-7     1d.H2   18us : sub_preempt_count (irq_exit)
-ksoftirq-7     1d.s3   19us : sub_preempt_count (irq_exit)
-ksoftirq-7     1..s2   20us : rcu_process_callbacks (__do_softirq)
-[...]
-ksoftirq-7     1..s2   26us : __rcu_process_callbacks (rcu_process_callbacks)
-ksoftirq-7     1d.s2   27us : _local_bh_enable (__do_softirq)
-ksoftirq-7     1d.s2   28us : sub_preempt_count (_local_bh_enable)
-ksoftirq-7     1.N.3   29us : sub_preempt_count (ksoftirqd)
-ksoftirq-7     1.N.2   30us : _cond_resched (ksoftirqd)
-ksoftirq-7     1.N.2   31us : __cond_resched (_cond_resched)
-ksoftirq-7     1.N.2   32us : add_preempt_count (__cond_resched)
-ksoftirq-7     1.N.2   33us : schedule (__cond_resched)
-ksoftirq-7     1.N.2   33us : add_preempt_count (schedule)
-ksoftirq-7     1.N.3   34us : hrtick_clear (schedule)
-ksoftirq-7     1dN.3   35us : _spin_lock (schedule)
-ksoftirq-7     1dN.3   36us : add_preempt_count (_spin_lock)
-ksoftirq-7     1d..4   37us : put_prev_task_fair (schedule)
-ksoftirq-7     1d..4   38us : update_curr (put_prev_task_fair)
-[...]
-ksoftirq-7     1d..5   47us : _spin_trylock (tracing_record_cmdline)
-ksoftirq-7     1d..5   48us : add_preempt_count (_spin_trylock)
-ksoftirq-7     1d..6   49us : _spin_unlock (tracing_record_cmdline)
-ksoftirq-7     1d..6   49us : sub_preempt_count (_spin_unlock)
-ksoftirq-7     1d..4   50us : schedule (__cond_resched)
-
-The interrupt went off while running ksoftirqd. This task runs
-at SCHED_OTHER. Why did not we see the 'N' set early? This may
-be a harmless bug with x86_32 and 4K stacks. On x86_32 with 4K
-stacks configured, the interrupt and softirq run with their own
-stack. Some information is held on the top of the task's stack
-(need_resched and preempt_count are both stored there). The
-setting of the NEED_RESCHED bit is done directly to the task's
-stack, but the reading of the NEED_RESCHED is done by looking at
-the current stack, which in this case is the stack for the hard
-interrupt. This hides the fact that NEED_RESCHED has been set.
-We do not see the 'N' until we switch back to the task's
-assigned stack.
+# wakeup_rt latency trace v1.1.5 on 3.8.0-test+
+# --------------------------------------------------------------------
+# latency: 29 us, #85/85, CPU#3 | (M:preempt VP:0, KP:0, SP:0 HP:0 #P:4)
+#    -----------------
+#    | task: sleep-2448 (uid:0 nice:0 policy:1 rt_prio:5)
+#    -----------------
+#
+#                  _------=> CPU#            
+#                 / _-----=> irqs-off        
+#                | / _----=> need-resched    
+#                || / _---=> hardirq/softirq 
+#                ||| / _--=> preempt-depth   
+#                |||| /     delay             
+#  cmd     pid   ||||| time  |   caller      
+#     \   /      |||||  \    |   /           
+  <idle>-0       3d.h4    1us+:      0:120:R   + [003]  2448: 94:R sleep
+  <idle>-0       3d.h4    2us : ttwu_do_activate.constprop.87 <-try_to_wake_up
+  <idle>-0       3d.h3    3us : check_preempt_curr <-ttwu_do_wakeup
+  <idle>-0       3d.h3    3us : resched_task <-check_preempt_curr
+  <idle>-0       3dNh3    4us : task_woken_rt <-ttwu_do_wakeup
+  <idle>-0       3dNh3    4us : _raw_spin_unlock <-try_to_wake_up
+  <idle>-0       3dNh3    4us : sub_preempt_count <-_raw_spin_unlock
+  <idle>-0       3dNh2    5us : ttwu_stat <-try_to_wake_up
+  <idle>-0       3dNh2    5us : _raw_spin_unlock_irqrestore <-try_to_wake_up
+  <idle>-0       3dNh2    6us : sub_preempt_count <-_raw_spin_unlock_irqrestore
+  <idle>-0       3dNh1    6us : _raw_spin_lock <-__run_hrtimer
+  <idle>-0       3dNh1    6us : add_preempt_count <-_raw_spin_lock
+  <idle>-0       3dNh2    7us : _raw_spin_unlock <-hrtimer_interrupt
+  <idle>-0       3dNh2    7us : sub_preempt_count <-_raw_spin_unlock
+  <idle>-0       3dNh1    7us : tick_program_event <-hrtimer_interrupt
+  <idle>-0       3dNh1    7us : clockevents_program_event <-tick_program_event
+  <idle>-0       3dNh1    8us : ktime_get <-clockevents_program_event
+  <idle>-0       3dNh1    8us : lapic_next_event <-clockevents_program_event
+  <idle>-0       3dNh1    8us : irq_exit <-smp_apic_timer_interrupt
+  <idle>-0       3dNh1    9us : sub_preempt_count <-irq_exit
+  <idle>-0       3dN.2    9us : idle_cpu <-irq_exit
+  <idle>-0       3dN.2    9us : rcu_irq_exit <-irq_exit
+  <idle>-0       3dN.2   10us : rcu_eqs_enter_common.isra.45 <-rcu_irq_exit
+  <idle>-0       3dN.2   10us : sub_preempt_count <-irq_exit
+  <idle>-0       3.N.1   11us : rcu_idle_exit <-cpu_idle
+  <idle>-0       3dN.1   11us : rcu_eqs_exit_common.isra.43 <-rcu_idle_exit
+  <idle>-0       3.N.1   11us : tick_nohz_idle_exit <-cpu_idle
+  <idle>-0       3dN.1   12us : menu_hrtimer_cancel <-tick_nohz_idle_exit
+  <idle>-0       3dN.1   12us : ktime_get <-tick_nohz_idle_exit
+  <idle>-0       3dN.1   12us : tick_do_update_jiffies64 <-tick_nohz_idle_exit
+  <idle>-0       3dN.1   13us : update_cpu_load_nohz <-tick_nohz_idle_exit
+  <idle>-0       3dN.1   13us : _raw_spin_lock <-update_cpu_load_nohz
+  <idle>-0       3dN.1   13us : add_preempt_count <-_raw_spin_lock
+  <idle>-0       3dN.2   13us : __update_cpu_load <-update_cpu_load_nohz
+  <idle>-0       3dN.2   14us : sched_avg_update <-__update_cpu_load
+  <idle>-0       3dN.2   14us : _raw_spin_unlock <-update_cpu_load_nohz
+  <idle>-0       3dN.2   14us : sub_preempt_count <-_raw_spin_unlock
+  <idle>-0       3dN.1   15us : calc_load_exit_idle <-tick_nohz_idle_exit
+  <idle>-0       3dN.1   15us : touch_softlockup_watchdog <-tick_nohz_idle_exit
+  <idle>-0       3dN.1   15us : hrtimer_cancel <-tick_nohz_idle_exit
+  <idle>-0       3dN.1   15us : hrtimer_try_to_cancel <-hrtimer_cancel
+  <idle>-0       3dN.1   16us : lock_hrtimer_base.isra.18 <-hrtimer_try_to_cancel
+  <idle>-0       3dN.1   16us : _raw_spin_lock_irqsave <-lock_hrtimer_base.isra.18
+  <idle>-0       3dN.1   16us : add_preempt_count <-_raw_spin_lock_irqsave
+  <idle>-0       3dN.2   17us : __remove_hrtimer <-remove_hrtimer.part.16
+  <idle>-0       3dN.2   17us : hrtimer_force_reprogram <-__remove_hrtimer
+  <idle>-0       3dN.2   17us : tick_program_event <-hrtimer_force_reprogram
+  <idle>-0       3dN.2   18us : clockevents_program_event <-tick_program_event
+  <idle>-0       3dN.2   18us : ktime_get <-clockevents_program_event
+  <idle>-0       3dN.2   18us : lapic_next_event <-clockevents_program_event
+  <idle>-0       3dN.2   19us : _raw_spin_unlock_irqrestore <-hrtimer_try_to_cancel
+  <idle>-0       3dN.2   19us : sub_preempt_count <-_raw_spin_unlock_irqrestore
+  <idle>-0       3dN.1   19us : hrtimer_forward <-tick_nohz_idle_exit
+  <idle>-0       3dN.1   20us : ktime_add_safe <-hrtimer_forward
+  <idle>-0       3dN.1   20us : ktime_add_safe <-hrtimer_forward
+  <idle>-0       3dN.1   20us : hrtimer_start_range_ns <-hrtimer_start_expires.constprop.11
+  <idle>-0       3dN.1   20us : __hrtimer_start_range_ns <-hrtimer_start_range_ns
+  <idle>-0       3dN.1   21us : lock_hrtimer_base.isra.18 <-__hrtimer_start_range_ns
+  <idle>-0       3dN.1   21us : _raw_spin_lock_irqsave <-lock_hrtimer_base.isra.18
+  <idle>-0       3dN.1   21us : add_preempt_count <-_raw_spin_lock_irqsave
+  <idle>-0       3dN.2   22us : ktime_add_safe <-__hrtimer_start_range_ns
+  <idle>-0       3dN.2   22us : enqueue_hrtimer <-__hrtimer_start_range_ns
+  <idle>-0       3dN.2   22us : tick_program_event <-__hrtimer_start_range_ns
+  <idle>-0       3dN.2   23us : clockevents_program_event <-tick_program_event
+  <idle>-0       3dN.2   23us : ktime_get <-clockevents_program_event
+  <idle>-0       3dN.2   23us : lapic_next_event <-clockevents_program_event
+  <idle>-0       3dN.2   24us : _raw_spin_unlock_irqrestore <-__hrtimer_start_range_ns
+  <idle>-0       3dN.2   24us : sub_preempt_count <-_raw_spin_unlock_irqrestore
+  <idle>-0       3dN.1   24us : account_idle_ticks <-tick_nohz_idle_exit
+  <idle>-0       3dN.1   24us : account_idle_time <-account_idle_ticks
+  <idle>-0       3.N.1   25us : sub_preempt_count <-cpu_idle
+  <idle>-0       3.N..   25us : schedule <-cpu_idle
+  <idle>-0       3.N..   25us : __schedule <-preempt_schedule
+  <idle>-0       3.N..   26us : add_preempt_count <-__schedule
+  <idle>-0       3.N.1   26us : rcu_note_context_switch <-__schedule
+  <idle>-0       3.N.1   26us : rcu_sched_qs <-rcu_note_context_switch
+  <idle>-0       3dN.1   27us : rcu_preempt_qs <-rcu_note_context_switch
+  <idle>-0       3.N.1   27us : _raw_spin_lock_irq <-__schedule
+  <idle>-0       3dN.1   27us : add_preempt_count <-_raw_spin_lock_irq
+  <idle>-0       3dN.2   28us : put_prev_task_idle <-__schedule
+  <idle>-0       3dN.2   28us : pick_next_task_stop <-pick_next_task
+  <idle>-0       3dN.2   28us : pick_next_task_rt <-pick_next_task
+  <idle>-0       3dN.2   29us : dequeue_pushable_task <-pick_next_task_rt
+  <idle>-0       3d..3   29us : __schedule <-preempt_schedule
+  <idle>-0       3d..3   30us :      0:120:R ==> [003]  2448: 94:R sleep
+
+This isn't that big of a trace, even with function tracing enabled,
+so I included the entire trace.
+
+The interrupt went off while when the system was idle. Somewhere
+before task_woken_rt() was called, the NEED_RESCHED flag was set,
+this is indicated by the first occurrence of the 'N' flag.
+
+Latency tracing and events
+--------------------------
+As function tracing can induce a much larger latency, but without
+seeing what happens within the latency it is hard to know what
+caused it. There is a middle ground, and that is with enabling
+events.
+
+ # echo 0 > options/function-trace
+ # echo wakeup_rt > current_tracer
+ # echo 1 > events/enable
+ # echo 1 > tracing_on
+ # echo 0 > tracing_max_latency
+ # chrt -f 5 sleep 1
+ # echo 0 > tracing_on
+ # cat trace
+# tracer: wakeup_rt
+#
+# wakeup_rt latency trace v1.1.5 on 3.8.0-test+
+# --------------------------------------------------------------------
+# latency: 6 us, #12/12, CPU#2 | (M:preempt VP:0, KP:0, SP:0 HP:0 #P:4)
+#    -----------------
+#    | task: sleep-5882 (uid:0 nice:0 policy:1 rt_prio:5)
+#    -----------------
+#
+#                  _------=> CPU#            
+#                 / _-----=> irqs-off        
+#                | / _----=> need-resched    
+#                || / _---=> hardirq/softirq 
+#                ||| / _--=> preempt-depth   
+#                |||| /     delay             
+#  cmd     pid   ||||| time  |   caller      
+#     \   /      |||||  \    |   /           
+  <idle>-0       2d.h4    0us :      0:120:R   + [002]  5882: 94:R sleep
+  <idle>-0       2d.h4    0us : ttwu_do_activate.constprop.87 <-try_to_wake_up
+  <idle>-0       2d.h4    1us : sched_wakeup: comm=sleep pid=5882 prio=94 success=1 target_cpu=002
+  <idle>-0       2dNh2    1us : hrtimer_expire_exit: hrtimer=ffff88007796feb8
+  <idle>-0       2.N.2    2us : power_end: cpu_id=2
+  <idle>-0       2.N.2    3us : cpu_idle: state=4294967295 cpu_id=2
+  <idle>-0       2dN.3    4us : hrtimer_cancel: hrtimer=ffff88007d50d5e0
+  <idle>-0       2dN.3    4us : hrtimer_start: hrtimer=ffff88007d50d5e0 function=tick_sched_timer expires=34311211000000 softexpires=34311211000000
+  <idle>-0       2.N.2    5us : rcu_utilization: Start context switch
+  <idle>-0       2.N.2    5us : rcu_utilization: End context switch
+  <idle>-0       2d..3    6us : __schedule <-schedule
+  <idle>-0       2d..3    6us :      0:120:R ==> [002]  5882: 94:R sleep
+
 
 function
 --------
@@ -1039,6 +1653,7 @@ function
 This tracer is the function tracer. Enabling the function tracer
 can be done from the debug file system. Make sure the
 ftrace_enabled is set; otherwise this tracer is a nop.
+See the "ftrace_enabled" section below.
 
  # sysctl kernel.ftrace_enabled=1
  # echo function > current_tracer
@@ -1048,23 +1663,23 @@ ftrace_enabled is set; otherwise this tracer is a nop.
  # cat trace
 # tracer: function
 #
-#           TASK-PID   CPU#    TIMESTAMP  FUNCTION
-#              | |      |          |         |
-            bash-4003  [00]   123.638713: finish_task_switch <-schedule
-            bash-4003  [00]   123.638714: _spin_unlock_irq <-finish_task_switch
-            bash-4003  [00]   123.638714: sub_preempt_count <-_spin_unlock_irq
-            bash-4003  [00]   123.638715: hrtick_set <-schedule
-            bash-4003  [00]   123.638715: _spin_lock_irqsave <-hrtick_set
-            bash-4003  [00]   123.638716: add_preempt_count <-_spin_lock_irqsave
-            bash-4003  [00]   123.638716: _spin_unlock_irqrestore <-hrtick_set
-            bash-4003  [00]   123.638717: sub_preempt_count <-_spin_unlock_irqrestore
-            bash-4003  [00]   123.638717: hrtick_clear <-hrtick_set
-            bash-4003  [00]   123.638718: sub_preempt_count <-schedule
-            bash-4003  [00]   123.638718: sub_preempt_count <-preempt_schedule
-            bash-4003  [00]   123.638719: wait_for_completion <-__stop_machine_run
-            bash-4003  [00]   123.638719: wait_for_common <-wait_for_completion
-            bash-4003  [00]   123.638720: _spin_lock_irq <-wait_for_common
-            bash-4003  [00]   123.638720: add_preempt_count <-_spin_lock_irq
+# entries-in-buffer/entries-written: 24799/24799   #P:4
+#
+#                              _-----=> irqs-off
+#                             / _----=> need-resched
+#                            | / _---=> hardirq/softirq
+#                            || / _--=> preempt-depth
+#                            ||| /     delay
+#           TASK-PID   CPU#  ||||    TIMESTAMP  FUNCTION
+#              | |       |   ||||       |         |
+            bash-1994  [002] ....  3082.063030: mutex_unlock <-rb_simple_write
+            bash-1994  [002] ....  3082.063031: __mutex_unlock_slowpath <-mutex_unlock
+            bash-1994  [002] ....  3082.063031: __fsnotify_parent <-fsnotify_modify
+            bash-1994  [002] ....  3082.063032: fsnotify <-fsnotify_modify
+            bash-1994  [002] ....  3082.063032: __srcu_read_lock <-fsnotify
+            bash-1994  [002] ....  3082.063032: add_preempt_count <-__srcu_read_lock
+            bash-1994  [002] ...1  3082.063032: sub_preempt_count <-__srcu_read_lock
+            bash-1994  [002] ....  3082.063033: __srcu_read_unlock <-fsnotify
 [...]
 
 
@@ -1214,79 +1829,19 @@ int main (int argc, char **argv)
         return 0;
 }
 
+Or this simple script!
 
-hw-branch-tracer (x86 only)
----------------------------
-
-This tracer uses the x86 last branch tracing hardware feature to
-collect a branch trace on all cpus with relatively low overhead.
-
-The tracer uses a fixed-size circular buffer per cpu and only
-traces ring 0 branches. The trace file dumps that buffer in the
-following format:
-
-# tracer: hw-branch-tracer
-#
-# CPU#        TO  <-  FROM
-   0  scheduler_tick+0xb5/0x1bf	  <-  task_tick_idle+0x5/0x6
-   2  run_posix_cpu_timers+0x2b/0x72a	  <-  run_posix_cpu_timers+0x25/0x72a
-   0  scheduler_tick+0x139/0x1bf	  <-  scheduler_tick+0xed/0x1bf
-   0  scheduler_tick+0x17c/0x1bf	  <-  scheduler_tick+0x148/0x1bf
-   2  run_posix_cpu_timers+0x9e/0x72a	  <-  run_posix_cpu_timers+0x5e/0x72a
-   0  scheduler_tick+0x1b6/0x1bf	  <-  scheduler_tick+0x1aa/0x1bf
-
-
-The tracer may be used to dump the trace for the oops'ing cpu on
-a kernel oops into the system log. To enable this,
-ftrace_dump_on_oops must be set. To set ftrace_dump_on_oops, one
-can either use the sysctl function or set it via the proc system
-interface.
-
-  sysctl kernel.ftrace_dump_on_oops=n
-
-or
-
-  echo n > /proc/sys/kernel/ftrace_dump_on_oops
-
-If n = 1, ftrace will dump buffers of all CPUs, if n = 2 ftrace will
-only dump the buffer of the CPU that triggered the oops.
-
-Here's an example of such a dump after a null pointer
-dereference in a kernel module:
-
-[57848.105921] BUG: unable to handle kernel NULL pointer dereference at 0000000000000000
-[57848.106019] IP: [<ffffffffa0000006>] open+0x6/0x14 [oops]
-[57848.106019] PGD 2354e9067 PUD 2375e7067 PMD 0
-[57848.106019] Oops: 0002 [#1] SMP
-[57848.106019] last sysfs file: /sys/devices/pci0000:00/0000:00:1e.0/0000:20:05.0/local_cpus
-[57848.106019] Dumping ftrace buffer:
-[57848.106019] ---------------------------------
-[...]
-[57848.106019]    0  chrdev_open+0xe6/0x165	  <-  cdev_put+0x23/0x24
-[57848.106019]    0  chrdev_open+0x117/0x165	  <-  chrdev_open+0xfa/0x165
-[57848.106019]    0  chrdev_open+0x120/0x165	  <-  chrdev_open+0x11c/0x165
-[57848.106019]    0  chrdev_open+0x134/0x165	  <-  chrdev_open+0x12b/0x165
-[57848.106019]    0  open+0x0/0x14 [oops]	  <-  chrdev_open+0x144/0x165
-[57848.106019]    0  page_fault+0x0/0x30	  <-  open+0x6/0x14 [oops]
-[57848.106019]    0  error_entry+0x0/0x5b	  <-  page_fault+0x4/0x30
-[57848.106019]    0  error_kernelspace+0x0/0x31	  <-  error_entry+0x59/0x5b
-[57848.106019]    0  error_sti+0x0/0x1	  <-  error_kernelspace+0x2d/0x31
-[57848.106019]    0  page_fault+0x9/0x30	  <-  error_sti+0x0/0x1
-[57848.106019]    0  do_page_fault+0x0/0x881	  <-  page_fault+0x1a/0x30
-[...]
-[57848.106019]    0  do_page_fault+0x66b/0x881	  <-  is_prefetch+0x1ee/0x1f2
-[57848.106019]    0  do_page_fault+0x6e0/0x881	  <-  do_page_fault+0x67a/0x881
-[57848.106019]    0  oops_begin+0x0/0x96	  <-  do_page_fault+0x6e0/0x881
-[57848.106019]    0  trace_hw_branch_oops+0x0/0x2d	  <-  oops_begin+0x9/0x96
-[...]
-[57848.106019]    0  ds_suspend_bts+0x2a/0xe3	  <-  ds_suspend_bts+0x1a/0xe3
-[57848.106019] ---------------------------------
-[57848.106019] CPU 0
-[57848.106019] Modules linked in: oops
-[57848.106019] Pid: 5542, comm: cat Tainted: G        W  2.6.28 #23
-[57848.106019] RIP: 0010:[<ffffffffa0000006>]  [<ffffffffa0000006>] open+0x6/0x14 [oops]
-[57848.106019] RSP: 0018:ffff880235457d48  EFLAGS: 00010246
-[...]
+------
+#!/bin/bash
+
+debugfs=`sed -ne 's/^debugfs \(.*\) debugfs.*/\1/p' /proc/mounts`
+echo nop > $debugfs/tracing/current_tracer
+echo 0 > $debugfs/tracing/tracing_on
+echo $$ > $debugfs/tracing/set_ftrace_pid
+echo function > $debugfs/tracing/current_tracer
+echo 1 > $debugfs/tracing/tracing_on
+exec "$@"
+------
 
 
 function graph tracer
@@ -1473,16 +2028,18 @@ starts of pointing to a simple return. (Enabling FTRACE will
 include the -pg switch in the compiling of the kernel.)
 
 At compile time every C file object is run through the
-recordmcount.pl script (located in the scripts directory). This
-script will process the C object using objdump to find all the
-locations in the .text section that call mcount. (Note, only the
-.text section is processed, since processing other sections like
-.init.text may cause races due to those sections being freed).
+recordmcount program (located in the scripts directory). This
+program will parse the ELF headers in the C object to find all
+the locations in the .text section that call mcount. (Note, only
+white listed .text sections are processed, since processing other
+sections like .init.text may cause races due to those sections
+being freed unexpectedly).
 
 A new section called "__mcount_loc" is created that holds
 references to all the mcount call sites in the .text section.
-This section is compiled back into the original object. The
-final linker will add all these references into a single table.
+The recordmcount program re-links this section back into the
+original object. The final linking stage of the kernel will add all these
+references into a single table.
 
 On boot up, before SMP is initialized, the dynamic ftrace code
 scans this table and updates all the locations into nops. It
@@ -1493,13 +2050,25 @@ unloaded, it also removes its functions from the ftrace function
 list. This is automatic in the module unload code, and the
 module author does not need to worry about it.
 
-When tracing is enabled, kstop_machine is called to prevent
-races with the CPUS executing code being modified (which can
-cause the CPU to do undesirable things), and the nops are
+When tracing is enabled, the process of modifying the function
+tracepoints is dependent on architecture. The old method is to use
+kstop_machine to prevent races with the CPUs executing code being
+modified (which can cause the CPU to do undesirable things, especially
+if the modified code crosses cache (or page) boundaries), and the nops are
 patched back to calls. But this time, they do not call mcount
 (which is just a function stub). They now call into the ftrace
 infrastructure.
 
+The new method of modifying the function tracepoints is to place
+a breakpoint at the location to be modified, sync all CPUs, modify
+the rest of the instruction not covered by the breakpoint. Sync
+all CPUs again, and then remove the breakpoint with the finished
+version to the ftrace call site.
+
+Some archs do not even need to monkey around with the synchronization,
+and can just slap the new code on top of the old without any
+problems with other CPUs executing it at the same time.
+
 One special side-effect to the recording of the functions being
 traced is that we can now selectively choose which functions we
 wish to trace and which ones we want the mcount calls to remain
@@ -1530,20 +2099,28 @@ mutex_lock
 
 If I am only interested in sys_nanosleep and hrtimer_interrupt:
 
- # echo sys_nanosleep hrtimer_interrupt \
-		> set_ftrace_filter
+ # echo sys_nanosleep hrtimer_interrupt > set_ftrace_filter
  # echo function > current_tracer
  # echo 1 > tracing_on
  # usleep 1
  # echo 0 > tracing_on
  # cat trace
-# tracer: ftrace
+# tracer: function
+#
+# entries-in-buffer/entries-written: 5/5   #P:4
 #
-#           TASK-PID   CPU#    TIMESTAMP  FUNCTION
-#              | |      |          |         |
-          usleep-4134  [00]  1317.070017: hrtimer_interrupt <-smp_apic_timer_interrupt
-          usleep-4134  [00]  1317.070111: sys_nanosleep <-syscall_call
-          <idle>-0     [00]  1317.070115: hrtimer_interrupt <-smp_apic_timer_interrupt
+#                              _-----=> irqs-off
+#                             / _----=> need-resched
+#                            | / _---=> hardirq/softirq
+#                            || / _--=> preempt-depth
+#                            ||| /     delay
+#           TASK-PID   CPU#  ||||    TIMESTAMP  FUNCTION
+#              | |       |   ||||       |         |
+          usleep-2665  [001] ....  4186.475355: sys_nanosleep <-system_call_fastpath
+          <idle>-0     [001] d.h1  4186.475409: hrtimer_interrupt <-smp_apic_timer_interrupt
+          usleep-2665  [001] d.h1  4186.475426: hrtimer_interrupt <-smp_apic_timer_interrupt
+          <idle>-0     [003] d.h1  4186.475426: hrtimer_interrupt <-smp_apic_timer_interrupt
+          <idle>-0     [002] d.h1  4186.475427: hrtimer_interrupt <-smp_apic_timer_interrupt
 
 To see which functions are being traced, you can cat the file:
 
@@ -1571,20 +2148,25 @@ Note: It is better to use quotes to enclose the wild cards,
 
 Produces:
 
-# tracer: ftrace
+# tracer: function
 #
-#           TASK-PID   CPU#    TIMESTAMP  FUNCTION
-#              | |      |          |         |
-            bash-4003  [00]  1480.611794: hrtimer_init <-copy_process
-            bash-4003  [00]  1480.611941: hrtimer_start <-hrtick_set
-            bash-4003  [00]  1480.611956: hrtimer_cancel <-hrtick_clear
-            bash-4003  [00]  1480.611956: hrtimer_try_to_cancel <-hrtimer_cancel
-          <idle>-0     [00]  1480.612019: hrtimer_get_next_event <-get_next_timer_interrupt
-          <idle>-0     [00]  1480.612025: hrtimer_get_next_event <-get_next_timer_interrupt
-          <idle>-0     [00]  1480.612032: hrtimer_get_next_event <-get_next_timer_interrupt
-          <idle>-0     [00]  1480.612037: hrtimer_get_next_event <-get_next_timer_interrupt
-          <idle>-0     [00]  1480.612382: hrtimer_get_next_event <-get_next_timer_interrupt
-
+# entries-in-buffer/entries-written: 897/897   #P:4
+#
+#                              _-----=> irqs-off
+#                             / _----=> need-resched
+#                            | / _---=> hardirq/softirq
+#                            || / _--=> preempt-depth
+#                            ||| /     delay
+#           TASK-PID   CPU#  ||||    TIMESTAMP  FUNCTION
+#              | |       |   ||||       |         |
+          <idle>-0     [003] dN.1  4228.547803: hrtimer_cancel <-tick_nohz_idle_exit
+          <idle>-0     [003] dN.1  4228.547804: hrtimer_try_to_cancel <-hrtimer_cancel
+          <idle>-0     [003] dN.2  4228.547805: hrtimer_force_reprogram <-__remove_hrtimer
+          <idle>-0     [003] dN.1  4228.547805: hrtimer_forward <-tick_nohz_idle_exit
+          <idle>-0     [003] dN.1  4228.547805: hrtimer_start_range_ns <-hrtimer_start_expires.constprop.11
+          <idle>-0     [003] d..1  4228.547858: hrtimer_get_next_event <-get_next_timer_interrupt
+          <idle>-0     [003] d..1  4228.547859: hrtimer_start <-__tick_nohz_idle_enter
+          <idle>-0     [003] d..2  4228.547860: hrtimer_force_reprogram <-__rem
 
 Notice that we lost the sys_nanosleep.
 
@@ -1651,19 +2233,29 @@ traced.
 
 Produces:
 
-# tracer: ftrace
+# tracer: function
+#
+# entries-in-buffer/entries-written: 39608/39608   #P:4
 #
-#           TASK-PID   CPU#    TIMESTAMP  FUNCTION
-#              | |      |          |         |
-            bash-4043  [01]   115.281644: finish_task_switch <-schedule
-            bash-4043  [01]   115.281645: hrtick_set <-schedule
-            bash-4043  [01]   115.281645: hrtick_clear <-hrtick_set
-            bash-4043  [01]   115.281646: wait_for_completion <-__stop_machine_run
-            bash-4043  [01]   115.281647: wait_for_common <-wait_for_completion
-            bash-4043  [01]   115.281647: kthread_stop <-stop_machine_run
-            bash-4043  [01]   115.281648: init_waitqueue_head <-kthread_stop
-            bash-4043  [01]   115.281648: wake_up_process <-kthread_stop
-            bash-4043  [01]   115.281649: try_to_wake_up <-wake_up_process
+#                              _-----=> irqs-off
+#                             / _----=> need-resched
+#                            | / _---=> hardirq/softirq
+#                            || / _--=> preempt-depth
+#                            ||| /     delay
+#           TASK-PID   CPU#  ||||    TIMESTAMP  FUNCTION
+#              | |       |   ||||       |         |
+            bash-1994  [000] ....  4342.324896: file_ra_state_init <-do_dentry_open
+            bash-1994  [000] ....  4342.324897: open_check_o_direct <-do_last
+            bash-1994  [000] ....  4342.324897: ima_file_check <-do_last
+            bash-1994  [000] ....  4342.324898: process_measurement <-ima_file_check
+            bash-1994  [000] ....  4342.324898: ima_get_action <-process_measurement
+            bash-1994  [000] ....  4342.324898: ima_match_policy <-ima_get_action
+            bash-1994  [000] ....  4342.324899: do_truncate <-do_last
+            bash-1994  [000] ....  4342.324899: should_remove_suid <-do_truncate
+            bash-1994  [000] ....  4342.324899: notify_change <-do_truncate
+            bash-1994  [000] ....  4342.324900: current_fs_time <-notify_change
+            bash-1994  [000] ....  4342.324900: current_kernel_time <-current_fs_time
+            bash-1994  [000] ....  4342.324900: timespec_trunc <-current_fs_time
 
 We can see that there's no more lock or preempt tracing.
 
@@ -1729,6 +2321,28 @@ this special filter via:
  echo > set_graph_function
 
 
+ftrace_enabled
+--------------
+
+Note, the proc sysctl ftrace_enable is a big on/off switch for the
+function tracer. By default it is enabled (when function tracing is
+enabled in the kernel). If it is disabled, all function tracing is
+disabled. This includes not only the function tracers for ftrace, but
+also for any other uses (perf, kprobes, stack tracing, profiling, etc).
+
+Please disable this with care.
+
+This can be disable (and enabled) with:
+
+  sysctl kernel.ftrace_enabled=0
+  sysctl kernel.ftrace_enabled=1
+
+ or
+
+  echo 0 > /proc/sys/kernel/ftrace_enabled
+  echo 1 > /proc/sys/kernel/ftrace_enabled
+
+
 Filter commands
 ---------------
 
@@ -1763,12 +2377,58 @@ The following commands are supported:
 
    echo '__schedule_bug:traceoff:5' > set_ftrace_filter
 
+  To always disable tracing when __schedule_bug is hit:
+
+   echo '__schedule_bug:traceoff' > set_ftrace_filter
+
   These commands are cumulative whether or not they are appended
   to set_ftrace_filter. To remove a command, prepend it by '!'
   and drop the parameter:
 
+   echo '!__schedule_bug:traceoff:0' > set_ftrace_filter
+
+    The above removes the traceoff command for __schedule_bug
+    that have a counter. To remove commands without counters:
+
    echo '!__schedule_bug:traceoff' > set_ftrace_filter
 
+- snapshot
+  Will cause a snapshot to be triggered when the function is hit.
+
+   echo 'native_flush_tlb_others:snapshot' > set_ftrace_filter
+
+  To only snapshot once:
+
+   echo 'native_flush_tlb_others:snapshot:1' > set_ftrace_filter
+
+  To remove the above commands:
+
+   echo '!native_flush_tlb_others:snapshot' > set_ftrace_filter
+   echo '!native_flush_tlb_others:snapshot:0' > set_ftrace_filter
+
+- enable_event/disable_event
+  These commands can enable or disable a trace event. Note, because
+  function tracing callbacks are very sensitive, when these commands
+  are registered, the trace point is activated, but disabled in
+  a "soft" mode. That is, the tracepoint will be called, but
+  just will not be traced. The event tracepoint stays in this mode
+  as long as there's a command that triggers it.
+
+   echo 'try_to_wake_up:enable_event:sched:sched_switch:2' > \
+   	 set_ftrace_filter
+
+  The format is:
+
+    <function>:enable_event:<system>:<event>[:count]
+    <function>:disable_event:<system>:<event>[:count]
+
+  To remove the events commands:
+
+
+   echo '!try_to_wake_up:enable_event:sched:sched_switch:0' > \
+   	 set_ftrace_filter
+   echo '!schedule:disable_event:sched:sched_switch' > \
+   	 set_ftrace_filter
 
 trace_pipe
 ----------
@@ -1787,28 +2447,31 @@ different. The trace is live.
  # cat trace
 # tracer: function
 #
-#           TASK-PID   CPU#    TIMESTAMP  FUNCTION
-#              | |      |          |         |
+# entries-in-buffer/entries-written: 0/0   #P:4
+#
+#                              _-----=> irqs-off
+#                             / _----=> need-resched
+#                            | / _---=> hardirq/softirq
+#                            || / _--=> preempt-depth
+#                            ||| /     delay
+#           TASK-PID   CPU#  ||||    TIMESTAMP  FUNCTION
+#              | |       |   ||||       |         |
 
  #
  # cat /tmp/trace.out
-            bash-4043  [00] 41.267106: finish_task_switch <-schedule
-            bash-4043  [00] 41.267106: hrtick_set <-schedule
-            bash-4043  [00] 41.267107: hrtick_clear <-hrtick_set
-            bash-4043  [00] 41.267108: wait_for_completion <-__stop_machine_run
-            bash-4043  [00] 41.267108: wait_for_common <-wait_for_completion
-            bash-4043  [00] 41.267109: kthread_stop <-stop_machine_run
-            bash-4043  [00] 41.267109: init_waitqueue_head <-kthread_stop
-            bash-4043  [00] 41.267110: wake_up_process <-kthread_stop
-            bash-4043  [00] 41.267110: try_to_wake_up <-wake_up_process
-            bash-4043  [00] 41.267111: select_task_rq_rt <-try_to_wake_up
+            bash-1994  [000] ....  5281.568961: mutex_unlock <-rb_simple_write
+            bash-1994  [000] ....  5281.568963: __mutex_unlock_slowpath <-mutex_unlock
+            bash-1994  [000] ....  5281.568963: __fsnotify_parent <-fsnotify_modify
+            bash-1994  [000] ....  5281.568964: fsnotify <-fsnotify_modify
+            bash-1994  [000] ....  5281.568964: __srcu_read_lock <-fsnotify
+            bash-1994  [000] ....  5281.568964: add_preempt_count <-__srcu_read_lock
+            bash-1994  [000] ...1  5281.568965: sub_preempt_count <-__srcu_read_lock
+            bash-1994  [000] ....  5281.568965: __srcu_read_unlock <-fsnotify
+            bash-1994  [000] ....  5281.568967: sys_dup2 <-system_call_fastpath
 
 
 Note, reading the trace_pipe file will block until more input is
-added. By changing the tracer, trace_pipe will issue an EOF. We
-needed to set the function tracer _before_ we "cat" the
-trace_pipe file.
-
+added.
 
 trace entries
 -------------
@@ -1817,31 +2480,50 @@ Having too much or not enough data can be troublesome in
 diagnosing an issue in the kernel. The file buffer_size_kb is
 used to modify the size of the internal trace buffers. The
 number listed is the number of entries that can be recorded per
-CPU. To know the full size, multiply the number of possible CPUS
+CPU. To know the full size, multiply the number of possible CPUs
 with the number of entries.
 
  # cat buffer_size_kb
 1408 (units kilobytes)
 
-Note, to modify this, you must have tracing completely disabled.
-To do that, echo "nop" into the current_tracer. If the
-current_tracer is not set to "nop", an EINVAL error will be
-returned.
+Or simply read buffer_total_size_kb
+
+ # cat buffer_total_size_kb 
+5632
+
+To modify the buffer, simple echo in a number (in 1024 byte segments).
 
- # echo nop > current_tracer
  # echo 10000 > buffer_size_kb
  # cat buffer_size_kb
 10000 (units kilobytes)
 
-The number of pages which will be allocated is limited to a
-percentage of available memory. Allocating too much will produce
-an error.
+It will try to allocate as much as possible. If you allocate too
+much, it can cause Out-Of-Memory to trigger.
 
  # echo 1000000000000 > buffer_size_kb
 -bash: echo: write error: Cannot allocate memory
  # cat buffer_size_kb
 85
 
+The per_cpu buffers can be changed individually as well:
+
+ # echo 10000 > per_cpu/cpu0/buffer_size_kb
+ # echo 100 > per_cpu/cpu1/buffer_size_kb
+
+When the per_cpu buffers are not the same, the buffer_size_kb
+at the top level will just show an X
+
+ # cat buffer_size_kb
+X
+
+This is where the buffer_total_size_kb is useful:
+
+ # cat buffer_total_size_kb 
+12916
+
+Writing to the top level buffer_size_kb will reset all the buffers
+to be the same again.
+
 Snapshot
 --------
 CONFIG_TRACER_SNAPSHOT makes a generic snapshot feature
@@ -1925,7 +2607,188 @@ bash: echo: write error: Device or resource busy
  # cat snapshot
 cat: snapshot: Device or resource busy
 
+
+Instances
+---------
+In the debugfs tracing directory is a directory called "instances".
+This directory can have new directories created inside of it using
+mkdir, and removing directories with rmdir. The directory created
+with mkdir in this directory will already contain files and other
+directories after it is created.
+
+ # mkdir instances/foo
+ # ls instances/foo
+buffer_size_kb  buffer_total_size_kb  events  free_buffer  per_cpu
+set_event  snapshot  trace  trace_clock  trace_marker  trace_options
+trace_pipe  tracing_on
+
+As you can see, the new directory looks similar to the tracing directory
+itself. In fact, it is very similar, except that the buffer and
+events are agnostic from the main director, or from any other
+instances that are created.
+
+The files in the new directory work just like the files with the
+same name in the tracing directory except the buffer that is used
+is a separate and new buffer. The files affect that buffer but do not
+affect the main buffer with the exception of trace_options. Currently,
+the trace_options affect all instances and the top level buffer
+the same, but this may change in future releases. That is, options
+may become specific to the instance they reside in.
+
+Notice that none of the function tracer files are there, nor is
+current_tracer and available_tracers. This is because the buffers
+can currently only have events enabled for them.
+
+ # mkdir instances/foo
+ # mkdir instances/bar
+ # mkdir instances/zoot
+ # echo 100000 > buffer_size_kb
+ # echo 1000 > instances/foo/buffer_size_kb
+ # echo 5000 > instances/bar/per_cpu/cpu1/buffer_size_kb
+ # echo function > current_trace
+ # echo 1 > instances/foo/events/sched/sched_wakeup/enable
+ # echo 1 > instances/foo/events/sched/sched_wakeup_new/enable
+ # echo 1 > instances/foo/events/sched/sched_switch/enable
+ # echo 1 > instances/bar/events/irq/enable
+ # echo 1 > instances/zoot/events/syscalls/enable
+ # cat trace_pipe
+CPU:2 [LOST 11745 EVENTS]
+            bash-2044  [002] .... 10594.481032: _raw_spin_lock_irqsave <-get_page_from_freelist
+            bash-2044  [002] d... 10594.481032: add_preempt_count <-_raw_spin_lock_irqsave
+            bash-2044  [002] d..1 10594.481032: __rmqueue <-get_page_from_freelist
+            bash-2044  [002] d..1 10594.481033: _raw_spin_unlock <-get_page_from_freelist
+            bash-2044  [002] d..1 10594.481033: sub_preempt_count <-_raw_spin_unlock
+            bash-2044  [002] d... 10594.481033: get_pageblock_flags_group <-get_pageblock_migratetype
+            bash-2044  [002] d... 10594.481034: __mod_zone_page_state <-get_page_from_freelist
+            bash-2044  [002] d... 10594.481034: zone_statistics <-get_page_from_freelist
+            bash-2044  [002] d... 10594.481034: __inc_zone_state <-zone_statistics
+            bash-2044  [002] d... 10594.481034: __inc_zone_state <-zone_statistics
+            bash-2044  [002] .... 10594.481035: arch_dup_task_struct <-copy_process
+[...]
+
+ # cat instances/foo/trace_pipe
+            bash-1998  [000] d..4   136.676759: sched_wakeup: comm=kworker/0:1 pid=59 prio=120 success=1 target_cpu=000
+            bash-1998  [000] dN.4   136.676760: sched_wakeup: comm=bash pid=1998 prio=120 success=1 target_cpu=000
+          <idle>-0     [003] d.h3   136.676906: sched_wakeup: comm=rcu_preempt pid=9 prio=120 success=1 target_cpu=003
+          <idle>-0     [003] d..3   136.676909: sched_switch: prev_comm=swapper/3 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=rcu_preempt next_pid=9 next_prio=120
+     rcu_preempt-9     [003] d..3   136.676916: sched_switch: prev_comm=rcu_preempt prev_pid=9 prev_prio=120 prev_state=S ==> next_comm=swapper/3 next_pid=0 next_prio=120
+            bash-1998  [000] d..4   136.677014: sched_wakeup: comm=kworker/0:1 pid=59 prio=120 success=1 target_cpu=000
+            bash-1998  [000] dN.4   136.677016: sched_wakeup: comm=bash pid=1998 prio=120 success=1 target_cpu=000
+            bash-1998  [000] d..3   136.677018: sched_switch: prev_comm=bash prev_pid=1998 prev_prio=120 prev_state=R+ ==> next_comm=kworker/0:1 next_pid=59 next_prio=120
+     kworker/0:1-59    [000] d..4   136.677022: sched_wakeup: comm=sshd pid=1995 prio=120 success=1 target_cpu=001
+     kworker/0:1-59    [000] d..3   136.677025: sched_switch: prev_comm=kworker/0:1 prev_pid=59 prev_prio=120 prev_state=S ==> next_comm=bash next_pid=1998 next_prio=120
+[...]
+
+ # cat instances/bar/trace_pipe
+     migration/1-14    [001] d.h3   138.732674: softirq_raise: vec=3 [action=NET_RX]
+          <idle>-0     [001] dNh3   138.732725: softirq_raise: vec=3 [action=NET_RX]
+            bash-1998  [000] d.h1   138.733101: softirq_raise: vec=1 [action=TIMER]
+            bash-1998  [000] d.h1   138.733102: softirq_raise: vec=9 [action=RCU]
+            bash-1998  [000] ..s2   138.733105: softirq_entry: vec=1 [action=TIMER]
+            bash-1998  [000] ..s2   138.733106: softirq_exit: vec=1 [action=TIMER]
+            bash-1998  [000] ..s2   138.733106: softirq_entry: vec=9 [action=RCU]
+            bash-1998  [000] ..s2   138.733109: softirq_exit: vec=9 [action=RCU]
+            sshd-1995  [001] d.h1   138.733278: irq_handler_entry: irq=21 name=uhci_hcd:usb4
+            sshd-1995  [001] d.h1   138.733280: irq_handler_exit: irq=21 ret=unhandled
+            sshd-1995  [001] d.h1   138.733281: irq_handler_entry: irq=21 name=eth0
+            sshd-1995  [001] d.h1   138.733283: irq_handler_exit: irq=21 ret=handled
+[...]
+
+ # cat instances/zoot/trace
+# tracer: nop
+#
+# entries-in-buffer/entries-written: 18996/18996   #P:4
+#
+#                              _-----=> irqs-off
+#                             / _----=> need-resched
+#                            | / _---=> hardirq/softirq
+#                            || / _--=> preempt-depth
+#                            ||| /     delay
+#           TASK-PID   CPU#  ||||    TIMESTAMP  FUNCTION
+#              | |       |   ||||       |         |
+            bash-1998  [000] d...   140.733501: sys_write -> 0x2
+            bash-1998  [000] d...   140.733504: sys_dup2(oldfd: a, newfd: 1)
+            bash-1998  [000] d...   140.733506: sys_dup2 -> 0x1
+            bash-1998  [000] d...   140.733508: sys_fcntl(fd: a, cmd: 1, arg: 0)
+            bash-1998  [000] d...   140.733509: sys_fcntl -> 0x1
+            bash-1998  [000] d...   140.733510: sys_close(fd: a)
+            bash-1998  [000] d...   140.733510: sys_close -> 0x0
+            bash-1998  [000] d...   140.733514: sys_rt_sigprocmask(how: 0, nset: 0, oset: 6e2768, sigsetsize: 8)
+            bash-1998  [000] d...   140.733515: sys_rt_sigprocmask -> 0x0
+            bash-1998  [000] d...   140.733516: sys_rt_sigaction(sig: 2, act: 7fff718846f0, oact: 7fff71884650, sigsetsize: 8)
+            bash-1998  [000] d...   140.733516: sys_rt_sigaction -> 0x0
+
+You can see that the trace of the top most trace buffer shows only
+the function tracing. The foo instance displays wakeups and task
+switches.
+
+To remove the instances, simply delete their directories:
+
+ # rmdir instances/foo
+ # rmdir instances/bar
+ # rmdir instances/zoot
+
+Note, if a process has a trace file open in one of the instance
+directories, the rmdir will fail with EBUSY.
+
+
+Stack trace
 -----------
+Since the kernel has a fixed sized stack, it is important not to
+waste it in functions. A kernel developer must be conscience of
+what they allocate on the stack. If they add too much, the system
+can be in danger of a stack overflow, and corruption will occur,
+usually leading to a system panic.
+
+There are some tools that check this, usually with interrupts
+periodically checking usage. But if you can perform a check
+at every function call that will become very useful. As ftrace provides
+a function tracer, it makes it convenient to check the stack size
+at every function call. This is enabled via the stack tracer.
+
+CONFIG_STACK_TRACER enables the ftrace stack tracing functionality.
+To enable it, write a '1' into /proc/sys/kernel/stack_tracer_enabled.
+
+ # echo 1 > /proc/sys/kernel/stack_tracer_enabled
+
+You can also enable it from the kernel command line to trace
+the stack size of the kernel during boot up, by adding "stacktrace"
+to the kernel command line parameter.
+
+After running it for a few minutes, the output looks like:
+
+ # cat stack_max_size
+2928
+
+ # cat stack_trace
+        Depth    Size   Location    (18 entries)
+        -----    ----   --------
+  0)     2928     224   update_sd_lb_stats+0xbc/0x4ac
+  1)     2704     160   find_busiest_group+0x31/0x1f1
+  2)     2544     256   load_balance+0xd9/0x662
+  3)     2288      80   idle_balance+0xbb/0x130
+  4)     2208     128   __schedule+0x26e/0x5b9
+  5)     2080      16   schedule+0x64/0x66
+  6)     2064     128   schedule_timeout+0x34/0xe0
+  7)     1936     112   wait_for_common+0x97/0xf1
+  8)     1824      16   wait_for_completion+0x1d/0x1f
+  9)     1808     128   flush_work+0xfe/0x119
+ 10)     1680      16   tty_flush_to_ldisc+0x1e/0x20
+ 11)     1664      48   input_available_p+0x1d/0x5c
+ 12)     1616      48   n_tty_poll+0x6d/0x134
+ 13)     1568      64   tty_poll+0x64/0x7f
+ 14)     1504     880   do_select+0x31e/0x511
+ 15)      624     400   core_sys_select+0x177/0x216
+ 16)      224      96   sys_select+0x91/0xb9
+ 17)      128     128   system_call_fastpath+0x16/0x1b
+
+Note, if -mfentry is being used by gcc, functions get traced before
+they set up the stack frame. This means that leaf level functions
+are not tested by the stack tracer when -mfentry is used.
+
+Currently, -mfentry is used by gcc 4.6.0 and above on x86 only.
+
+---------
 
 More details can be found in the source code, in the
 kernel/trace/*.c files.
diff --git a/Documentation/trace/tracepoints.txt b/Documentation/trace/tracepoints.txt
index c0e1cee..da49437 100644
--- a/Documentation/trace/tracepoints.txt
+++ b/Documentation/trace/tracepoints.txt
@@ -81,7 +81,6 @@ tracepoint_synchronize_unregister() must be called before the end of
 the module exit function to make sure there is no caller left using
 the probe. This, and the fact that preemption is disabled around the
 probe call, make sure that probe removal and module unload are safe.
-See the "Probe example" section below for a sample probe module.
 
 The tracepoint mechanism supports inserting multiple instances of the
 same tracepoint, but a single definition must be made of a given
@@ -100,17 +99,3 @@ core kernel image or in modules.
 If the tracepoint has to be used in kernel modules, an
 EXPORT_TRACEPOINT_SYMBOL_GPL() or EXPORT_TRACEPOINT_SYMBOL() can be
 used to export the defined tracepoints.
-
-* Probe / tracepoint example
-
-See the example provided in samples/tracepoints
-
-Compile them with your kernel.  They are built during 'make' (not
-'make modules') when CONFIG_SAMPLE_TRACEPOINTS=m.
-
-Run, as root :
-modprobe tracepoint-sample (insmod order is not important)
-modprobe tracepoint-probe-sample
-cat /proc/tracepoint-sample (returns an expected error)
-rmmod tracepoint-sample tracepoint-probe-sample
-dmesg
diff --git a/Documentation/usb/power-management.txt b/Documentation/usb/power-management.txt
index 4204eb0..1392b61 100644
--- a/Documentation/usb/power-management.txt
+++ b/Documentation/usb/power-management.txt
@@ -33,6 +33,10 @@ built with CONFIG_USB_SUSPEND enabled (which depends on
 CONFIG_PM_RUNTIME).  System PM support is present only if the kernel
 was built with CONFIG_SUSPEND or CONFIG_HIBERNATION enabled.
 
+(Starting with the 3.10 kernel release, dynamic PM support for USB is
+present whenever the kernel was built with CONFIG_PM_RUNTIME enabled.
+The CONFIG_USB_SUSPEND option has been eliminated.)
+
 
 	What is Remote Wakeup?
 	----------------------
@@ -206,10 +210,8 @@ initialized to 5.  (The idle-delay values for already existing devices
 will not be affected.)
 
 Setting the initial default idle-delay to -1 will prevent any
-autosuspend of any USB device.  This is a simple alternative to
-disabling CONFIG_USB_SUSPEND and rebuilding the kernel, and it has the
-added benefit of allowing you to enable autosuspend for selected
-devices.
+autosuspend of any USB device.  This has the benefit of allowing you
+then to enable autosuspend for selected devices.
 
 
 	Warnings
diff --git a/Documentation/video4linux/CARDLIST.em28xx b/Documentation/video4linux/CARDLIST.em28xx
index 3f12865..e818644 100644
--- a/Documentation/video4linux/CARDLIST.em28xx
+++ b/Documentation/video4linux/CARDLIST.em28xx
@@ -76,7 +76,7 @@
  76 -> KWorld PlusTV 340U or UB435-Q (ATSC)     (em2870)        [1b80:a340]
  77 -> EM2874 Leadership ISDBT                  (em2874)
  78 -> PCTV nanoStick T2 290e                   (em28174)
- 79 -> Terratec Cinergy H5                      (em2884)        [0ccd:10a2,0ccd:10ad]
+ 79 -> Terratec Cinergy H5                      (em2884)        [0ccd:10a2,0ccd:10ad,0ccd:10b6]
  80 -> PCTV DVB-S2 Stick (460e)                 (em28174)
  81 -> Hauppauge WinTV HVR 930C                 (em2884)        [2040:1605]
  82 -> Terratec Cinergy HTC Stick               (em2884)        [0ccd:00b2]
@@ -85,3 +85,4 @@
  85 -> PCTV QuatroStick (510e)                  (em2884)        [2304:0242]
  86 -> PCTV QuatroStick nano (520e)             (em2884)        [2013:0251]
  87 -> Terratec Cinergy HTC USB XS              (em2884)        [0ccd:008e,0ccd:00ac]
+ 88 -> C3 Tech Digital Duo HDTV/SDTV USB        (em2884)        [1b80:e755]
diff --git a/Documentation/video4linux/CARDLIST.tuner b/Documentation/video4linux/CARDLIST.tuner
index c83f6e4..5b83a3f 100644
--- a/Documentation/video4linux/CARDLIST.tuner
+++ b/Documentation/video4linux/CARDLIST.tuner
@@ -86,3 +86,6 @@ tuner=85 - Philips FQ1236 MK5
 tuner=86 - Tena TNF5337 MFD
 tuner=87 - Xceive 4000 tuner
 tuner=88 - Xceive 5000C tuner
+tuner=89 - Sony PAL+SECAM (BTF-PG472Z)
+tuner=90 - Sony NTSC-M-JP (BTF-PK467Z)
+tuner=91 - Sony NTSC-M (BTF-PB463Z)
diff --git a/Documentation/virtual/00-INDEX b/Documentation/virtual/00-INDEX
index 924bd46..e952d30 100644
--- a/Documentation/virtual/00-INDEX
+++ b/Documentation/virtual/00-INDEX
@@ -6,6 +6,3 @@ kvm/
 	- Kernel Virtual Machine.  See also http://linux-kvm.org
 uml/
 	- User Mode Linux, builds/runs Linux kernel as a userspace program.
-virtio.txt
-	- Text version of draft virtio spec.
-          See http://ozlabs.org/~rusty/virtio-spec
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index 119358d..976eb65 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -1486,15 +1486,23 @@ struct kvm_ioeventfd {
 	__u8  pad[36];
 };
 
+For the special case of virtio-ccw devices on s390, the ioevent is matched
+to a subchannel/virtqueue tuple instead.
+
 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)
+#define KVM_IOEVENTFD_FLAG_VIRTIO_CCW_NOTIFY \
+	(1 << kvm_ioeventfd_flag_nr_virtio_ccw_notify)
 
 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.
 
+For virtio-ccw devices, addr contains the subchannel id and datamatch the
+virtqueue index.
+
 
 4.60 KVM_DIRTY_TLB
 
@@ -1780,6 +1788,10 @@ registers, find a list below:
   PPC   | KVM_REG_PPC_VPA_DTL   | 128
   PPC   | KVM_REG_PPC_EPCR	| 32
   PPC   | KVM_REG_PPC_EPR	| 32
+  PPC   | KVM_REG_PPC_TCR	| 32
+  PPC   | KVM_REG_PPC_TSR	| 32
+  PPC   | KVM_REG_PPC_OR_TSR	| 32
+  PPC   | KVM_REG_PPC_CLEAR_TSR	| 32
 
 ARM registers are mapped using the lower 32 bits.  The upper 16 of that
 is the register group type, or coprocessor number:
diff --git a/Documentation/virtual/virtio-spec.txt b/Documentation/virtual/virtio-spec.txt
deleted file mode 100644
index 0d6ec85..0000000
--- a/Documentation/virtual/virtio-spec.txt
+++ /dev/null
@@ -1,3210 +0,0 @@
-[Generated file: see http://ozlabs.org/~rusty/virtio-spec/]
-Virtio PCI Card Specification
-v0.9.5 DRAFT
--
-
-Rusty Russell <rusty@rustcorp.com.au> IBM Corporation (Editor)
-
-2012 May 7.
-
-Purpose and Description
-
-This document describes the specifications of the “virtio” family
-of PCI[LaTeX Command: nomenclature] devices. These are devices
-are found in virtual environments[LaTeX Command: nomenclature],
-yet by design they are not all that different from physical PCI
-devices, and this document treats them as such. This allows the
-guest to use standard PCI drivers and discovery mechanisms.
-
-The purpose of virtio and this specification is that virtual
-environments and guests should have a straightforward, efficient,
-standard and extensible mechanism for virtual devices, rather
-than boutique per-environment or per-OS mechanisms.
-
-  Straightforward: Virtio PCI devices use normal PCI mechanisms
-  of interrupts and DMA which should be familiar to any device
-  driver author. There is no exotic page-flipping or COW
-  mechanism: it's just a PCI device.[footnote:
-This lack of page-sharing implies that the implementation of the
-device (e.g. the hypervisor or host) needs full access to the
-guest memory. Communication with untrusted parties (i.e.
-inter-guest communication) requires copying.
-]
-
-  Efficient: Virtio PCI devices consist of rings of descriptors
-  for input and output, which are neatly separated to avoid cache
-  effects from both guest and device writing to the same cache
-  lines.
-
-  Standard: Virtio PCI makes no assumptions about the environment
-  in which it operates, beyond supporting PCI. In fact the virtio
-  devices specified in the appendices do not require PCI at all:
-  they have been implemented on non-PCI buses.[footnote:
-The Linux implementation further separates the PCI virtio code
-from the specific virtio drivers: these drivers are shared with
-the non-PCI implementations (currently lguest and S/390).
-]
-
-  Extensible: Virtio PCI devices contain feature bits which are
-  acknowledged by the guest operating system during device setup.
-  This allows forwards and backwards compatibility: the device
-  offers all the features it knows about, and the driver
-  acknowledges those it understands and wishes to use.
-
-  Virtqueues
-
-The mechanism for bulk data transport on virtio PCI devices is
-pretentiously called a virtqueue. Each device can have zero or
-more virtqueues: for example, the network device has one for
-transmit and one for receive.
-
-Each virtqueue occupies two or more physically-contiguous pages
-(defined, for the purposes of this specification, as 4096 bytes),
-and consists of three parts:
-
-
-+-------------------+-----------------------------------+-----------+
-| Descriptor Table  |   Available Ring     (padding)    | Used Ring |
-+-------------------+-----------------------------------+-----------+
-
-
-When the driver wants to send a buffer to the device, it fills in
-a slot in the descriptor table (or chains several together), and
-writes the descriptor index into the available ring. It then
-notifies the device. When the device has finished a buffer, it
-writes the descriptor into the used ring, and sends an interrupt.
-
-Specification
-
-  PCI Discovery
-
-Any PCI device with Vendor ID 0x1AF4, and Device ID 0x1000
-through 0x103F inclusive is a virtio device[footnote:
-The actual value within this range is ignored
-]. The device must also have a Revision ID of 0 to match this
-specification.
-
-The Subsystem Device ID indicates which virtio device is
-supported by the device. The Subsystem Vendor ID should reflect
-the PCI Vendor ID of the environment (it's currently only used
-for informational purposes by the guest).
-
-
-+----------------------+--------------------+---------------+
-| Subsystem Device ID  |   Virtio Device    | Specification |
-+----------------------+--------------------+---------------+
-+----------------------+--------------------+---------------+
-|          1           |   network card     |  Appendix C   |
-+----------------------+--------------------+---------------+
-|          2           |   block device     |  Appendix D   |
-+----------------------+--------------------+---------------+
-|          3           |      console       |  Appendix E   |
-+----------------------+--------------------+---------------+
-|          4           |  entropy source    |  Appendix F   |
-+----------------------+--------------------+---------------+
-|          5           | memory ballooning  |  Appendix G   |
-+----------------------+--------------------+---------------+
-|          6           |     ioMemory       |       -       |
-+----------------------+--------------------+---------------+
-|          7           |       rpmsg        |  Appendix H   |
-+----------------------+--------------------+---------------+
-|          8           |     SCSI host      |  Appendix I   |
-+----------------------+--------------------+---------------+
-|          9           |   9P transport     |       -       |
-+----------------------+--------------------+---------------+
-|         10           |   mac80211 wlan    |       -       |
-+----------------------+--------------------+---------------+
-
-
-  Device Configuration
-
-To configure the device, we use the first I/O region of the PCI
-device. This contains a virtio header followed by a
-device-specific region.
-
-There may be different widths of accesses to the I/O region; the “
-natural” access method for each field in the virtio header must
-be used (i.e. 32-bit accesses for 32-bit fields, etc), but the
-device-specific region can be accessed using any width accesses,
-and should obtain the same results.
-
-Note that this is possible because while the virtio header is PCI
-(i.e. little) endian, the device-specific region is encoded in
-the native endian of the guest (where such distinction is
-applicable).
-
-  Device Initialization Sequence<sub:Device-Initialization-Sequence>
-
-We start with an overview of device initialization, then expand
-on the details of the device and how each step is preformed.
-
-  Reset the device. This is not required on initial start up.
-
-  The ACKNOWLEDGE status bit is set: we have noticed the device.
-
-  The DRIVER status bit is set: we know how to drive the device.
-
-  Device-specific setup, including reading the Device Feature
-  Bits, discovery of virtqueues for the device, optional MSI-X
-  setup, and reading and possibly writing the virtio
-  configuration space.
-
-  The subset of Device Feature Bits understood by the driver is
-  written to the device.
-
-  The DRIVER_OK status bit is set.
-
-  The device can now be used (ie. buffers added to the
-  virtqueues)[footnote:
-Historically, drivers have used the device before steps 5 and 6.
-This is only allowed if the driver does not use any features
-which would alter this early use of the device.
-]
-
-If any of these steps go irrecoverably wrong, the guest should
-set the FAILED status bit to indicate that it has given up on the
-device (it can reset the device later to restart if desired).
-
-We now cover the fields required for general setup in detail.
-
-  Virtio Header
-
-The virtio header looks as follows:
-
-
-+------------++---------------------+---------------------+----------+--------+---------+---------+---------+--------+
-| Bits       || 32                  | 32                  | 32       | 16     | 16      | 16      | 8       | 8      |
-+------------++---------------------+---------------------+----------+--------+---------+---------+---------+--------+
-| Read/Write || R                   | R+W                 | R+W      | R      | R+W     | R+W     | R+W     | R      |
-+------------++---------------------+---------------------+----------+--------+---------+---------+---------+--------+
-| Purpose    || Device              | Guest               | Queue    | Queue  | Queue   | Queue   | Device  | ISR    |
-|            || Features bits 0:31  | Features bits 0:31  | Address  | Size   | Select  | Notify  | Status  | Status |
-+------------++---------------------+---------------------+----------+--------+---------+---------+---------+--------+
-
-
-If MSI-X is enabled for the device, two additional fields
-immediately follow this header:[footnote:
-ie. once you enable MSI-X on the device, the other fields move.
-If you turn it off again, they move back!
-]
-
-
-+------------++----------------+--------+
-| Bits       || 16             | 16     |
-              +----------------+--------+
-+------------++----------------+--------+
-| Read/Write || R+W            | R+W    |
-+------------++----------------+--------+
-| Purpose    || Configuration  | Queue  |
-| (MSI-X)    || Vector         | Vector |
-+------------++----------------+--------+
-
-
-Immediately following these general headers, there may be
-device-specific headers:
-
-
-+------------++--------------------+
-| Bits       || Device Specific    |
-              +--------------------+
-+------------++--------------------+
-| Read/Write || Device Specific    |
-+------------++--------------------+
-| Purpose    || Device Specific... |
-|            ||                    |
-+------------++--------------------+
-
-
-  Device Status
-
-The Device Status field is updated by the guest to indicate its
-progress. This provides a simple low-level diagnostic: it's most
-useful to imagine them hooked up to traffic lights on the console
-indicating the status of each device.
-
-The device can be reset by writing a 0 to this field, otherwise
-at least one bit should be set:
-
-  ACKNOWLEDGE (1) Indicates that the guest OS has found the
-  device and recognized it as a valid virtio device.
-
-  DRIVER (2) Indicates that the guest OS knows how to drive the
-  device. Under Linux, drivers can be loadable modules so there
-  may be a significant (or infinite) delay before setting this
-  bit.
-
-  DRIVER_OK (4) Indicates that the driver is set up and ready to
-  drive the device.
-
-  FAILED (128) Indicates that something went wrong in the guest,
-  and it has given up on the device. This could be an internal
-  error, or the driver didn't like the device for some reason, or
-  even a fatal error during device operation. The device must be
-  reset before attempting to re-initialize.
-
-  Feature Bits<sub:Feature-Bits>
-
-Thefirst configuration field indicates the features that the
-device supports. The bits are allocated as follows:
-
-  0 to 23 Feature bits for the specific device type
-
-  24 to 32 Feature bits reserved for extensions to the queue and
-  feature negotiation mechanisms
-
-For example, feature bit 0 for a network device (i.e. Subsystem
-Device ID 1) indicates that the device supports checksumming of
-packets.
-
-The feature bits are negotiated: the device lists all the
-features it understands in the Device Features field, and the
-guest writes the subset that it understands into the Guest
-Features field. The only way to renegotiate is to reset the
-device.
-
-In particular, new fields in the device configuration header are
-indicated by offering a feature bit, so the guest can check
-before accessing that part of the configuration space.
-
-This allows for forwards and backwards compatibility: if the
-device is enhanced with a new feature bit, older guests will not
-write that feature bit back to the Guest Features field and it
-can go into backwards compatibility mode. Similarly, if a guest
-is enhanced with a feature that the device doesn't support, it
-will not see that feature bit in the Device Features field and
-can go into backwards compatibility mode (or, for poor
-implementations, set the FAILED Device Status bit).
-
-  Configuration/Queue Vectors
-
-When MSI-X capability is present and enabled in the device
-(through standard PCI configuration space) 4 bytes at byte offset
-20 are used to map configuration change and queue interrupts to
-MSI-X vectors. In this case, the ISR Status field is unused, and
-device specific configuration starts at byte offset 24 in virtio
-header structure. When MSI-X capability is not enabled, device
-specific configuration starts at byte offset 20 in virtio header.
-
-Writing a valid MSI-X Table entry number, 0 to 0x7FF, to one of
-Configuration/Queue Vector registers, maps interrupts triggered
-by the configuration change/selected queue events respectively to
-the corresponding MSI-X vector. To disable interrupts for a
-specific event type, unmap it by writing a special NO_VECTOR
-value:
-
-/* Vector value used to disable MSI for queue */
-
-#define VIRTIO_MSI_NO_VECTOR            0xffff
-
-Reading these registers returns vector mapped to a given event,
-or NO_VECTOR if unmapped. All queue and configuration change
-events are unmapped by default.
-
-Note that mapping an event to vector might require allocating
-internal device resources, and might fail. Devices report such
-failures by returning the NO_VECTOR value when the relevant
-Vector field is read. After mapping an event to vector, the
-driver must verify success by reading the Vector field value: on
-success, the previously written value is returned, and on
-failure, NO_VECTOR is returned. If a mapping failure is detected,
-the driver can retry mapping with fewervectors, or disable MSI-X.
-
-  Virtqueue Configuration<sec:Virtqueue-Configuration>
-
-As a device can have zero or more virtqueues for bulk data
-transport (for example, the network driver has two), the driver
-needs to configure them as part of the device-specific
-configuration.
-
-This is done as follows, for each virtqueue a device has:
-
-  Write the virtqueue index (first queue is 0) to the Queue
-  Select field.
-
-  Read the virtqueue size from the Queue Size field, which is
-  always a power of 2. This controls how big the virtqueue is
-  (see below). If this field is 0, the virtqueue does not exist.
-
-  Allocate and zero virtqueue in contiguous physical memory, on a
-  4096 byte alignment. Write the physical address, divided by
-  4096 to the Queue Address field.[footnote:
-The 4096 is based on the x86 page size, but it's also large
-enough to ensure that the separate parts of the virtqueue are on
-separate cache lines.
-]
-
-  Optionally, if MSI-X capability is present and enabled on the
-  device, select a vector to use to request interrupts triggered
-  by virtqueue events. Write the MSI-X Table entry number
-  corresponding to this vector in Queue Vector field. Read the
-  Queue Vector field: on success, previously written value is
-  returned; on failure, NO_VECTOR value is returned.
-
-The Queue Size field controls the total number of bytes required
-for the virtqueue according to the following formula:
-
-#define ALIGN(x) (((x) + 4095) & ~4095)
-
-static inline unsigned vring_size(unsigned int qsz)
-
-{
-
-     return ALIGN(sizeof(struct vring_desc)*qsz + sizeof(u16)*(2
-+ qsz))
-
-          + ALIGN(sizeof(struct vring_used_elem)*qsz);
-
-}
-
-This currently wastes some space with padding, but also allows
-future extensions. The virtqueue layout structure looks like this
-(qsz is the Queue Size field, which is a variable, so this code
-won't compile):
-
-struct vring {
-
-    /* The actual descriptors (16 bytes each) */
-
-    struct vring_desc desc[qsz];
-
-
-
-    /* A ring of available descriptor heads with free-running
-index. */
-
-    struct vring_avail avail;
-
-
-
-    // Padding to the next 4096 boundary.
-
-    char pad[];
-
-
-
-    // A ring of used descriptor heads with free-running index.
-
-    struct vring_used used;
-
-};
-
-  A Note on Virtqueue Endianness
-
-Note that the endian of these fields and everything else in the
-virtqueue is the native endian of the guest, not little-endian as
-PCI normally is. This makes for simpler guest code, and it is
-assumed that the host already has to be deeply aware of the guest
-endian so such an “endian-aware” device is not a significant
-issue.
-
-  Descriptor Table
-
-The descriptor table refers to the buffers the guest is using for
-the device. The addresses are physical addresses, and the buffers
-can be chained via the next field. Each descriptor describes a
-buffer which is read-only or write-only, but a chain of
-descriptors can contain both read-only and write-only buffers.
-
-No descriptor chain may be more than 2^32 bytes long in total.struct vring_desc {
-
-    /* Address (guest-physical). */
-
-    u64 addr;
-
-    /* Length. */
-
-    u32 len;
-
-/* This marks a buffer as continuing via the next field. */
-
-#define VRING_DESC_F_NEXT   1
-
-/* This marks a buffer as write-only (otherwise read-only). */
-
-#define VRING_DESC_F_WRITE     2
-
-/* This means the buffer contains a list of buffer descriptors.
-*/
-
-#define VRING_DESC_F_INDIRECT   4
-
-    /* The flags as indicated above. */
-
-    u16 flags;
-
-    /* Next field if flags & NEXT */
-
-    u16 next;
-
-};
-
-The number of descriptors in the table is specified by the Queue
-Size field for this virtqueue.
-
-  <sub:Indirect-Descriptors>Indirect Descriptors
-
-Some devices benefit by concurrently dispatching a large number
-of large requests. The VIRTIO_RING_F_INDIRECT_DESC feature can be
-used to allow this (see [cha:Reserved-Feature-Bits]). To increase
-ring capacity it is possible to store a table of indirect
-descriptors anywhere in memory, and insert a descriptor in main
-virtqueue (with flags&INDIRECT on) that refers to memory buffer
-containing this indirect descriptor table; fields addr and len
-refer to the indirect table address and length in bytes,
-respectively. The indirect table layout structure looks like this
-(len is the length of the descriptor that refers to this table,
-which is a variable, so this code won't compile):
-
-struct indirect_descriptor_table {
-
-    /* The actual descriptors (16 bytes each) */
-
-    struct vring_desc desc[len / 16];
-
-};
-
-The first indirect descriptor is located at start of the indirect
-descriptor table (index 0), additional indirect descriptors are
-chained by next field. An indirect descriptor without next field
-(with flags&NEXT off) signals the end of the indirect descriptor
-table, and transfers control back to the main virtqueue. An
-indirect descriptor can not refer to another indirect descriptor
-table (flags&INDIRECT must be off). A single indirect descriptor
-table can include both read-only and write-only descriptors;
-write-only flag (flags&WRITE) in the descriptor that refers to it
-is ignored.
-
-  Available Ring
-
-The available ring refers to what descriptors we are offering the
-device: it refers to the head of a descriptor chain. The “flags”
-field is currently 0 or 1: 1 indicating that we do not need an
-interrupt when the device consumes a descriptor from the
-available ring. Alternatively, the guest can ask the device to
-delay interrupts until an entry with an index specified by the “
-used_event” field is written in the used ring (equivalently,
-until the idx field in the used ring will reach the value
-used_event + 1). The method employed by the device is controlled
-by the VIRTIO_RING_F_EVENT_IDX feature bit (see [cha:Reserved-Feature-Bits]
-). This interrupt suppression is merely an optimization; it may
-not suppress interrupts entirely.
-
-The “idx” field indicates where we would put the next descriptor
-entry (modulo the ring size). This starts at 0, and increases.
-
-struct vring_avail {
-
-#define VRING_AVAIL_F_NO_INTERRUPT      1
-
-   u16 flags;
-
-   u16 idx;
-
-   u16 ring[qsz]; /* qsz is the Queue Size field read from device
-*/
-
-   u16 used_event;
-
-};
-
-  Used Ring
-
-The used ring is where the device returns buffers once it is done
-with them. The flags field can be used by the device to hint that
-no notification is necessary when the guest adds to the available
-ring. Alternatively, the “avail_event” field can be used by the
-device to hint that no notification is necessary until an entry
-with an index specified by the “avail_event” is written in the
-available ring (equivalently, until the idx field in the
-available ring will reach the value avail_event + 1). The method
-employed by the device is controlled by the guest through the
-VIRTIO_RING_F_EVENT_IDX feature bit (see [cha:Reserved-Feature-Bits]
-). [footnote:
-These fields are kept here because this is the only part of the
-virtqueue written by the device
-].
-
-Each entry in the ring is a pair: the head entry of the
-descriptor chain describing the buffer (this matches an entry
-placed in the available ring by the guest earlier), and the total
-of bytes written into the buffer. The latter is extremely useful
-for guests using untrusted buffers: if you do not know exactly
-how much has been written by the device, you usually have to zero
-the buffer to ensure no data leakage occurs.
-
-/* u32 is used here for ids for padding reasons. */
-
-struct vring_used_elem {
-
-    /* Index of start of used descriptor chain. */
-
-    u32 id;
-
-    /* Total length of the descriptor chain which was used
-(written to) */
-
-    u32 len;
-
-};
-
-
-
-struct vring_used {
-
-#define VRING_USED_F_NO_NOTIFY  1
-
-    u16 flags;
-
-    u16 idx;
-
-    struct vring_used_elem ring[qsz];
-
-    u16 avail_event;
-
-};
-
-  Helpers for Managing Virtqueues
-
-The Linux Kernel Source code contains the definitions above and
-helper routines in a more usable form, in
-include/linux/virtio_ring.h. This was explicitly licensed by IBM
-and Red Hat under the (3-clause) BSD license so that it can be
-freely used by all other projects, and is reproduced (with slight
-variation to remove Linux assumptions) in Appendix A.
-
-  Device Operation<sec:Device-Operation>
-
-There are two parts to device operation: supplying new buffers to
-the device, and processing used buffers from the device. As an
-example, the virtio network device has two virtqueues: the
-transmit virtqueue and the receive virtqueue. The driver adds
-outgoing (read-only) packets to the transmit virtqueue, and then
-frees them after they are used. Similarly, incoming (write-only)
-buffers are added to the receive virtqueue, and processed after
-they are used.
-
-  Supplying Buffers to The Device
-
-Actual transfer of buffers from the guest OS to the device
-operates as follows:
-
-  Place the buffer(s) into free descriptor(s).
-
-  If there are no free descriptors, the guest may choose to
-    notify the device even if notifications are suppressed (to
-    reduce latency).[footnote:
-The Linux drivers do this only for read-only buffers: for
-write-only buffers, it is assumed that the driver is merely
-trying to keep the receive buffer ring full, and no notification
-of this expected condition is necessary.
-]
-
-  Place the id of the buffer in the next ring entry of the
-  available ring.
-
-  The steps (1) and (2) may be performed repeatedly if batching
-  is possible.
-
-  A memory barrier should be executed to ensure the device sees
-  the updated descriptor table and available ring before the next
-  step.
-
-  The available “idx” field should be increased by the number of
-  entries added to the available ring.
-
-  A memory barrier should be executed to ensure that we update
-  the idx field before checking for notification suppression.
-
-  If notifications are not suppressed, the device should be
-  notified of the new buffers.
-
-Note that the above code does not take precautions against the
-available ring buffer wrapping around: this is not possible since
-the ring buffer is the same size as the descriptor table, so step
-(1) will prevent such a condition.
-
-In addition, the maximum queue size is 32768 (it must be a power
-of 2 which fits in 16 bits), so the 16-bit “idx” value can always
-distinguish between a full and empty buffer.
-
-Here is a description of each stage in more detail.
-
-  Placing Buffers Into The Descriptor Table
-
-A buffer consists of zero or more read-only physically-contiguous
-elements followed by zero or more physically-contiguous
-write-only elements (it must have at least one element). This
-algorithm maps it into the descriptor table:
-
-  for each buffer element, b:
-
-  Get the next free descriptor table entry, d
-
-  Set d.addr to the physical address of the start of b
-
-  Set d.len to the length of b.
-
-  If b is write-only, set d.flags to VRING_DESC_F_WRITE,
-    otherwise 0.
-
-  If there is a buffer element after this:
-
-    Set d.next to the index of the next free descriptor element.
-
-    Set the VRING_DESC_F_NEXT bit in d.flags.
-
-In practice, the d.next fields are usually used to chain free
-descriptors, and a separate count kept to check there are enough
-free descriptors before beginning the mappings.
-
-  Updating The Available Ring
-
-The head of the buffer we mapped is the first d in the algorithm
-above. A naive implementation would do the following:
-
-avail->ring[avail->idx % qsz] = head;
-
-However, in general we can add many descriptors before we update
-the “idx” field (at which point they become visible to the
-device), so we keep a counter of how many we've added:
-
-avail->ring[(avail->idx + added++) % qsz] = head;
-
-  Updating The Index Field
-
-Once the idx field of the virtqueue is updated, the device will
-be able to access the descriptor entries we've created and the
-memory they refer to. This is why a memory barrier is generally
-used before the idx update, to ensure it sees the most up-to-date
-copy.
-
-The idx field always increments, and we let it wrap naturally at
-65536:
-
-avail->idx += added;
-
-  <sub:Notifying-The-Device>Notifying The Device
-
-Device notification occurs by writing the 16-bit virtqueue index
-of this virtqueue to the Queue Notify field of the virtio header
-in the first I/O region of the PCI device. This can be expensive,
-however, so the device can suppress such notifications if it
-doesn't need them. We have to be careful to expose the new idx
-value before checking the suppression flag: it's OK to notify
-gratuitously, but not to omit a required notification. So again,
-we use a memory barrier here before reading the flags or the
-avail_event field.
-
-If the VIRTIO_F_RING_EVENT_IDX feature is not negotiated, and if
-the VRING_USED_F_NOTIFY flag is not set, we go ahead and write to
-the PCI configuration space.
-
-If the VIRTIO_F_RING_EVENT_IDX feature is negotiated, we read the
-avail_event field in the available ring structure. If the
-available index crossed_the avail_event field value since the
-last notification, we go ahead and write to the PCI configuration
-space. The avail_event field wraps naturally at 65536 as well:
-
-(u16)(new_idx - avail_event - 1) < (u16)(new_idx - old_idx)
-
-  <sub:Receiving-Used-Buffers>Receiving Used Buffers From The
-  Device
-
-Once the device has used a buffer (read from or written to it, or
-parts of both, depending on the nature of the virtqueue and the
-device), it sends an interrupt, following an algorithm very
-similar to the algorithm used for the driver to send the device a
-buffer:
-
-  Write the head descriptor number to the next field in the used
-  ring.
-
-  Update the used ring idx.
-
-  Determine whether an interrupt is necessary:
-
-  If the VIRTIO_F_RING_EVENT_IDX feature is not negotiated: check
-    if f the VRING_AVAIL_F_NO_INTERRUPT flag is not set in avail-
-    >flags
-
-  If the VIRTIO_F_RING_EVENT_IDX feature is negotiated: check
-    whether the used index crossed the used_event field value
-    since the last update. The used_event field wraps naturally
-    at 65536 as well:(u16)(new_idx - used_event - 1) < (u16)(new_idx - old_idx)
-
-  If an interrupt is necessary:
-
-  If MSI-X capability is disabled:
-
-    Set the lower bit of the ISR Status field for the device.
-
-    Send the appropriate PCI interrupt for the device.
-
-  If MSI-X capability is enabled:
-
-    Request the appropriate MSI-X interrupt message for the
-      device, Queue Vector field sets the MSI-X Table entry
-      number.
-
-    If Queue Vector field value is NO_VECTOR, no interrupt
-      message is requested for this event.
-
-The guest interrupt handler should:
-
-  If MSI-X capability is disabled: read the ISR Status field,
-  which will reset it to zero. If the lower bit is zero, the
-  interrupt was not for this device. Otherwise, the guest driver
-  should look through the used rings of each virtqueue for the
-  device, to see if any progress has been made by the device
-  which requires servicing.
-
-  If MSI-X capability is enabled: look through the used rings of
-  each virtqueue mapped to the specific MSI-X vector for the
-  device, to see if any progress has been made by the device
-  which requires servicing.
-
-For each ring, guest should then disable interrupts by writing
-VRING_AVAIL_F_NO_INTERRUPT flag in avail structure, if required.
-It can then process used ring entries finally enabling interrupts
-by clearing the VRING_AVAIL_F_NO_INTERRUPT flag or updating the
-EVENT_IDX field in the available structure, Guest should then
-execute a memory barrier, and then recheck the ring empty
-condition. This is necessary to handle the case where, after the
-last check and before enabling interrupts, an interrupt has been
-suppressed by the device:
-
-vring_disable_interrupts(vq);
-
-for (;;) {
-
-    if (vq->last_seen_used != vring->used.idx) {
-
-		vring_enable_interrupts(vq);
-
-		mb();
-
-		if (vq->last_seen_used != vring->used.idx)
-
-			break;
-
-    }
-
-    struct vring_used_elem *e =
-vring.used->ring[vq->last_seen_used%vsz];
-
-    process_buffer(e);
-
-    vq->last_seen_used++;
-
-}
-
-  Dealing With Configuration Changes<sub:Dealing-With-Configuration>
-
-Some virtio PCI devices can change the device configuration
-state, as reflected in the virtio header in the PCI configuration
-space. In this case:
-
-  If MSI-X capability is disabled: an interrupt is delivered and
-  the second highest bit is set in the ISR Status field to
-  indicate that the driver should re-examine the configuration
-  space.Note that a single interrupt can indicate both that one
-  or more virtqueue has been used and that the configuration
-  space has changed: even if the config bit is set, virtqueues
-  must be scanned.
-
-  If MSI-X capability is enabled: an interrupt message is
-  requested. The Configuration Vector field sets the MSI-X Table
-  entry number to use. If Configuration Vector field value is
-  NO_VECTOR, no interrupt message is requested for this event.
-
-Creating New Device Types
-
-Various considerations are necessary when creating a new device
-type:
-
-  How Many Virtqueues?
-
-It is possible that a very simple device will operate entirely
-through its configuration space, but most will need at least one
-virtqueue in which it will place requests. A device with both
-input and output (eg. console and network devices described here)
-need two queues: one which the driver fills with buffers to
-receive input, and one which the driver places buffers to
-transmit output.
-
-  What Configuration Space Layout?
-
-Configuration space is generally used for rarely-changing or
-initialization-time parameters. But it is a limited resource, so
-it might be better to use a virtqueue to update configuration
-information (the network device does this for filtering,
-otherwise the table in the config space could potentially be very
-large).
-
-Note that this space is generally the guest's native endian,
-rather than PCI's little-endian.
-
-  What Device Number?
-
-Currently device numbers are assigned quite freely: a simple
-request mail to the author of this document or the Linux
-virtualization mailing list[footnote:
-
-https://lists.linux-foundation.org/mailman/listinfo/virtualization
-] will be sufficient to secure a unique one.
-
-Meanwhile for experimental drivers, use 65535 and work backwards.
-
-  How many MSI-X vectors?
-
-Using the optional MSI-X capability devices can speed up
-interrupt processing by removing the need to read ISR Status
-register by guest driver (which might be an expensive operation),
-reducing interrupt sharing between devices and queues within the
-device, and handling interrupts from multiple CPUs. However, some
-systems impose a limit (which might be as low as 256) on the
-total number of MSI-X vectors that can be allocated to all
-devices. Devices and/or device drivers should take this into
-account, limiting the number of vectors used unless the device is
-expected to cause a high volume of interrupts. Devices can
-control the number of vectors used by limiting the MSI-X Table
-Size or not presenting MSI-X capability in PCI configuration
-space. Drivers can control this by mapping events to as small
-number of vectors as possible, or disabling MSI-X capability
-altogether.
-
-  Message Framing
-
-The descriptors used for a buffer should not effect the semantics
-of the message, except for the total length of the buffer. For
-example, a network buffer consists of a 10 byte header followed
-by the network packet. Whether this is presented in the ring
-descriptor chain as (say) a 10 byte buffer and a 1514 byte
-buffer, or a single 1524 byte buffer, or even three buffers,
-should have no effect.
-
-In particular, no implementation should use the descriptor
-boundaries to determine the size of any header in a request.[footnote:
-The current qemu device implementations mistakenly insist that
-the first descriptor cover the header in these cases exactly, so
-a cautious driver should arrange it so.
-]
-
-  Device Improvements
-
-Any change to configuration space, or new virtqueues, or
-behavioural changes, should be indicated by negotiation of a new
-feature bit. This establishes clarity[footnote:
-Even if it does mean documenting design or implementation
-mistakes!
-] and avoids future expansion problems.
-
-Clusters of functionality which are always implemented together
-can use a single bit, but if one feature makes sense without the
-others they should not be gratuitously grouped together to
-conserve feature bits. We can always extend the spec when the
-first person needs more than 24 feature bits for their device.
-
-[LaTeX Command: printnomenclature]
-
-Appendix A: virtio_ring.h
-
-#ifndef VIRTIO_RING_H
-
-#define VIRTIO_RING_H
-
-/* An interface for efficient virtio implementation.
-
- *
-
- * This header is BSD licensed so anyone can use the definitions
-
- * to implement compatible drivers/servers.
-
- *
-
- * Copyright 2007, 2009, IBM Corporation
-
- * Copyright 2011, Red Hat, Inc
-
- * 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, this list of conditions and the following
-disclaimer.
-
- * 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. Neither the name of IBM 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 IBM 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.
-
- */
-
-
-
-/* This marks a buffer as continuing via the next field. */
-
-#define VRING_DESC_F_NEXT       1
-
-/* This marks a buffer as write-only (otherwise read-only). */
-
-#define VRING_DESC_F_WRITE      2
-
-
-
-/* The Host uses this in used->flags to advise the Guest: don't
-kick me
-
- * when you add a buffer.  It's unreliable, so it's simply an
-
- * optimization.  Guest will still kick if it's out of buffers.
-*/
-
-#define VRING_USED_F_NO_NOTIFY  1
-
-/* The Guest uses this in avail->flags to advise the Host: don't
-
- * interrupt me when you consume a buffer.  It's unreliable, so
-it's
-
- * simply an optimization.  */
-
-#define VRING_AVAIL_F_NO_INTERRUPT      1
-
-
-
-/* Virtio ring descriptors: 16 bytes.
-
- * These can chain together via "next". */
-
-struct vring_desc {
-
-        /* Address (guest-physical). */
-
-        uint64_t addr;
-
-        /* Length. */
-
-        uint32_t len;
-
-        /* The flags as indicated above. */
-
-        uint16_t flags;
-
-        /* We chain unused descriptors via this, too */
-
-        uint16_t next;
-
-};
-
-
-
-struct vring_avail {
-
-        uint16_t flags;
-
-        uint16_t idx;
-
-        uint16_t ring[];
-
-        uint16_t used_event;
-
-};
-
-
-
-/* u32 is used here for ids for padding reasons. */
-
-struct vring_used_elem {
-
-        /* Index of start of used descriptor chain. */
-
-        uint32_t id;
-
-        /* Total length of the descriptor chain which was written
-to. */
-
-        uint32_t len;
-
-};
-
-
-
-struct vring_used {
-
-        uint16_t flags;
-
-        uint16_t idx;
-
-        struct vring_used_elem ring[];
-
-        uint16_t avail_event;
-
-};
-
-
-
-struct vring {
-
-        unsigned int num;
-
-
-
-        struct vring_desc *desc;
-
-        struct vring_avail *avail;
-
-        struct vring_used *used;
-
-};
-
-
-
-/* The standard layout for the ring is a continuous chunk of
-memory which
-
- * looks like this.  We assume num is a power of 2.
-
- *
-
- * struct vring {
-
- *      // The actual descriptors (16 bytes each)
-
- *      struct vring_desc desc[num];
-
- *
-
- *      // A ring of available descriptor heads with free-running
-index.
-
- *      __u16 avail_flags;
-
- *      __u16 avail_idx;
-
- *      __u16 available[num];
-
- *
-
- *      // Padding to the next align boundary.
-
- *      char pad[];
-
- *
-
- *      // A ring of used descriptor heads with free-running
-index.
-
- *      __u16 used_flags;
-
- *      __u16 EVENT_IDX;
-
- *      struct vring_used_elem used[num];
-
- * };
-
- * Note: for virtio PCI, align is 4096.
-
- */
-
-static inline void vring_init(struct vring *vr, unsigned int num,
-void *p,
-
-                              unsigned long align)
-
-{
-
-        vr->num = num;
-
-        vr->desc = p;
-
-        vr->avail = p + num*sizeof(struct vring_desc);
-
-        vr->used = (void *)(((unsigned long)&vr->avail->ring[num]
-
-                              + align-1)
-
-                            & ~(align - 1));
-
-}
-
-
-
-static inline unsigned vring_size(unsigned int num, unsigned long
-align)
-
-{
-
-        return ((sizeof(struct vring_desc)*num +
-sizeof(uint16_t)*(2+num)
-
-                 + align - 1) & ~(align - 1))
-
-                + sizeof(uint16_t)*3 + sizeof(struct
-vring_used_elem)*num;
-
-}
-
-
-
-static inline int vring_need_event(uint16_t event_idx, uint16_t
-new_idx, uint16_t old_idx)
-
-{
-
-         return (uint16_t)(new_idx - event_idx - 1) <
-(uint16_t)(new_idx - old_idx);
-
-}
-
-#endif /* VIRTIO_RING_H */
-
-<cha:Reserved-Feature-Bits>Appendix B: Reserved Feature Bits
-
-Currently there are five device-independent feature bits defined:
-
-  VIRTIO_F_NOTIFY_ON_EMPTY (24) Negotiating this feature
-  indicates that the driver wants an interrupt if the device runs
-  out of available descriptors on a virtqueue, even though
-  interrupts are suppressed using the VRING_AVAIL_F_NO_INTERRUPT
-  flag or the used_event field. An example of this is the
-  networking driver: it doesn't need to know every time a packet
-  is transmitted, but it does need to free the transmitted
-  packets a finite time after they are transmitted. It can avoid
-  using a timer if the device interrupts it when all the packets
-  are transmitted.
-
-  VIRTIO_F_RING_INDIRECT_DESC (28) Negotiating this feature
-  indicates that the driver can use descriptors with the
-  VRING_DESC_F_INDIRECT flag set, as described in [sub:Indirect-Descriptors]
-  .
-
-  VIRTIO_F_RING_EVENT_IDX(29) This feature enables the used_event
-  and the avail_event fields. If set, it indicates that the
-  device should ignore the flags field in the available ring
-  structure. Instead, the used_event field in this structure is
-  used by guest to suppress device interrupts. Further, the
-  driver should ignore the flags field in the used ring
-  structure. Instead, the avail_event field in this structure is
-  used by the device to suppress notifications. If unset, the
-  driver should ignore the used_event field; the device should
-  ignore the avail_event field; the flags field is used
-
-Appendix C: Network Device
-
-The virtio network device is a virtual ethernet card, and is the
-most complex of the devices supported so far by virtio. It has
-enhanced rapidly and demonstrates clearly how support for new
-features should be added to an existing device. Empty buffers are
-placed in one virtqueue for receiving packets, and outgoing
-packets are enqueued into another for transmission in that order.
-A third command queue is used to control advanced filtering
-features.
-
-  Configuration
-
-  Subsystem Device ID 1
-
-  Virtqueues 0:receiveq. 1:transmitq. 2:controlq[footnote:
-Only if VIRTIO_NET_F_CTRL_VQ set
-]
-
-  Feature bits
-
-  VIRTIO_NET_F_CSUM (0) Device handles packets with partial
-    checksum
-
-  VIRTIO_NET_F_GUEST_CSUM (1) Guest handles packets with partial
-    checksum
-
-  VIRTIO_NET_F_MAC (5) Device has given MAC address.
-
-  VIRTIO_NET_F_GSO (6) (Deprecated) device handles packets with
-    any GSO type.[footnote:
-It was supposed to indicate segmentation offload support, but
-upon further investigation it became clear that multiple bits
-were required.
-]
-
-  VIRTIO_NET_F_GUEST_TSO4 (7) Guest can receive TSOv4.
-
-  VIRTIO_NET_F_GUEST_TSO6 (8) Guest can receive TSOv6.
-
-  VIRTIO_NET_F_GUEST_ECN (9) Guest can receive TSO with ECN.
-
-  VIRTIO_NET_F_GUEST_UFO (10) Guest can receive UFO.
-
-  VIRTIO_NET_F_HOST_TSO4 (11) Device can receive TSOv4.
-
-  VIRTIO_NET_F_HOST_TSO6 (12) Device can receive TSOv6.
-
-  VIRTIO_NET_F_HOST_ECN (13) Device can receive TSO with ECN.
-
-  VIRTIO_NET_F_HOST_UFO (14) Device can receive UFO.
-
-  VIRTIO_NET_F_MRG_RXBUF (15) Guest can merge receive buffers.
-
-  VIRTIO_NET_F_STATUS (16) Configuration status field is
-    available.
-
-  VIRTIO_NET_F_CTRL_VQ (17) Control channel is available.
-
-  VIRTIO_NET_F_CTRL_RX (18) Control channel RX mode support.
-
-  VIRTIO_NET_F_CTRL_VLAN (19) Control channel VLAN filtering.
-
-  VIRTIO_NET_F_GUEST_ANNOUNCE(21) Guest can send gratuitous
-    packets.
-
-  Device configuration layout Two configuration fields are
-  currently defined. The mac address field always exists (though
-  is only valid if VIRTIO_NET_F_MAC is set), and the status field
-  only exists if VIRTIO_NET_F_STATUS is set. Two read-only bits
-  are currently defined for the status field:
-  VIRTIO_NET_S_LINK_UP and VIRTIO_NET_S_ANNOUNCE. #define VIRTIO_NET_S_LINK_UP	1
-
-#define VIRTIO_NET_S_ANNOUNCE	2
-
-
-
-struct virtio_net_config {
-
-    u8 mac[6];
-
-    u16 status;
-
-};
-
-  Device Initialization
-
-  The initialization routine should identify the receive and
-  transmission virtqueues.
-
-  If the VIRTIO_NET_F_MAC feature bit is set, the configuration
-  space “mac” entry indicates the “physical” address of the the
-  network card, otherwise a private MAC address should be
-  assigned. All guests are expected to negotiate this feature if
-  it is set.
-
-  If the VIRTIO_NET_F_CTRL_VQ feature bit is negotiated, identify
-  the control virtqueue.
-
-  If the VIRTIO_NET_F_STATUS feature bit is negotiated, the link
-  status can be read from the bottom bit of the “status” config
-  field. Otherwise, the link should be assumed active.
-
-  The receive virtqueue should be filled with receive buffers.
-  This is described in detail below in “Setting Up Receive
-  Buffers”.
-
-  A driver can indicate that it will generate checksumless
-  packets by negotating the VIRTIO_NET_F_CSUM feature. This “
-  checksum offload” is a common feature on modern network cards.
-
-  If that feature is negotiated[footnote:
-ie. VIRTIO_NET_F_HOST_TSO* and VIRTIO_NET_F_HOST_UFO are
-dependent on VIRTIO_NET_F_CSUM; a dvice which offers the offload
-features must offer the checksum feature, and a driver which
-accepts the offload features must accept the checksum feature.
-Similar logic applies to the VIRTIO_NET_F_GUEST_TSO4 features
-depending on VIRTIO_NET_F_GUEST_CSUM.
-], a driver can use TCP or UDP segmentation offload by
-  negotiating the VIRTIO_NET_F_HOST_TSO4 (IPv4 TCP),
-  VIRTIO_NET_F_HOST_TSO6 (IPv6 TCP) and VIRTIO_NET_F_HOST_UFO
-  (UDP fragmentation) features. It should not send TCP packets
-  requiring segmentation offload which have the Explicit
-  Congestion Notification bit set, unless the
-  VIRTIO_NET_F_HOST_ECN feature is negotiated.[footnote:
-This is a common restriction in real, older network cards.
-]
-
-  The converse features are also available: a driver can save the
-  virtual device some work by negotiating these features.[footnote:
-For example, a network packet transported between two guests on
-the same system may not require checksumming at all, nor
-segmentation, if both guests are amenable.
-] The VIRTIO_NET_F_GUEST_CSUM feature indicates that partially
-  checksummed packets can be received, and if it can do that then
-  the VIRTIO_NET_F_GUEST_TSO4, VIRTIO_NET_F_GUEST_TSO6,
-  VIRTIO_NET_F_GUEST_UFO and VIRTIO_NET_F_GUEST_ECN are the input
-  equivalents of the features described above. See “Receiving
-  Packets” below.
-
-  Device Operation
-
-Packets are transmitted by placing them in the transmitq, and
-buffers for incoming packets are placed in the receiveq. In each
-case, the packet itself is preceeded by a header:
-
-struct virtio_net_hdr {
-
-#define VIRTIO_NET_HDR_F_NEEDS_CSUM    1
-
-	u8 flags;
-
-#define VIRTIO_NET_HDR_GSO_NONE        0
-
-#define VIRTIO_NET_HDR_GSO_TCPV4       1
-
-#define VIRTIO_NET_HDR_GSO_UDP		 3
-
-#define VIRTIO_NET_HDR_GSO_TCPV6       4
-
-#define VIRTIO_NET_HDR_GSO_ECN      0x80
-
-	u8 gso_type;
-
-	u16 hdr_len;
-
-	u16 gso_size;
-
-	u16 csum_start;
-
-	u16 csum_offset;
-
-/* Only if VIRTIO_NET_F_MRG_RXBUF: */
-
-	u16 num_buffers
-
-};
-
-The controlq is used to control device features such as
-filtering.
-
-  Packet Transmission
-
-Transmitting a single packet is simple, but varies depending on
-the different features the driver negotiated.
-
-  If the driver negotiated VIRTIO_NET_F_CSUM, and the packet has
-  not been fully checksummed, then the virtio_net_hdr's fields
-  are set as follows. Otherwise, the packet must be fully
-  checksummed, and flags is zero.
-
-  flags has the VIRTIO_NET_HDR_F_NEEDS_CSUM set,
-
-  <ite:csum_start-is-set>csum_start is set to the offset within
-    the packet to begin checksumming, and
-
-  csum_offset indicates how many bytes after the csum_start the
-    new (16 bit ones' complement) checksum should be placed.[footnote:
-For example, consider a partially checksummed TCP (IPv4) packet.
-It will have a 14 byte ethernet header and 20 byte IP header
-followed by the TCP header (with the TCP checksum field 16 bytes
-into that header). csum_start will be 14+20 = 34 (the TCP
-checksum includes the header), and csum_offset will be 16. The
-value in the TCP checksum field should be initialized to the sum
-of the TCP pseudo header, so that replacing it by the ones'
-complement checksum of the TCP header and body will give the
-correct result.
-]
-
-  <enu:If-the-driver>If the driver negotiated
-  VIRTIO_NET_F_HOST_TSO4, TSO6 or UFO, and the packet requires
-  TCP segmentation or UDP fragmentation, then the “gso_type”
-  field is set to VIRTIO_NET_HDR_GSO_TCPV4, TCPV6 or UDP.
-  (Otherwise, it is set to VIRTIO_NET_HDR_GSO_NONE). In this
-  case, packets larger than 1514 bytes can be transmitted: the
-  metadata indicates how to replicate the packet header to cut it
-  into smaller packets. The other gso fields are set:
-
-  hdr_len is a hint to the device as to how much of the header
-    needs to be kept to copy into each packet, usually set to the
-    length of the headers, including the transport header.[footnote:
-Due to various bugs in implementations, this field is not useful
-as a guarantee of the transport header size.
-]
-
-  gso_size is the maximum size of each packet beyond that header
-    (ie. MSS).
-
-  If the driver negotiated the VIRTIO_NET_F_HOST_ECN feature, the
-    VIRTIO_NET_HDR_GSO_ECN bit may be set in “gso_type” as well,
-    indicating that the TCP packet has the ECN bit set.[footnote:
-This case is not handled by some older hardware, so is called out
-specifically in the protocol.
-]
-
-  If the driver negotiated the VIRTIO_NET_F_MRG_RXBUF feature,
-  the num_buffers field is set to zero.
-
-  The header and packet are added as one output buffer to the
-  transmitq, and the device is notified of the new entry (see [sub:Notifying-The-Device]
-  ).[footnote:
-Note that the header will be two bytes longer for the
-VIRTIO_NET_F_MRG_RXBUF case.
-]
-
-  Packet Transmission Interrupt
-
-Often a driver will suppress transmission interrupts using the
-VRING_AVAIL_F_NO_INTERRUPT flag (see [sub:Receiving-Used-Buffers]
-) and check for used packets in the transmit path of following
-packets. However, it will still receive interrupts if the
-VIRTIO_F_NOTIFY_ON_EMPTY feature is negotiated, indicating that
-the transmission queue is completely emptied.
-
-The normal behavior in this interrupt handler is to retrieve and
-new descriptors from the used ring and free the corresponding
-headers and packets.
-
-  Setting Up Receive Buffers
-
-It is generally a good idea to keep the receive virtqueue as
-fully populated as possible: if it runs out, network performance
-will suffer.
-
-If the VIRTIO_NET_F_GUEST_TSO4, VIRTIO_NET_F_GUEST_TSO6 or
-VIRTIO_NET_F_GUEST_UFO features are used, the Guest will need to
-accept packets of up to 65550 bytes long (the maximum size of a
-TCP or UDP packet, plus the 14 byte ethernet header), otherwise
-1514 bytes. So unless VIRTIO_NET_F_MRG_RXBUF is negotiated, every
-buffer in the receive queue needs to be at least this length [footnote:
-Obviously each one can be split across multiple descriptor
-elements.
-].
-
-If VIRTIO_NET_F_MRG_RXBUF is negotiated, each buffer must be at
-least the size of the struct virtio_net_hdr.
-
-  Packet Receive Interrupt
-
-When a packet is copied into a buffer in the receiveq, the
-optimal path is to disable further interrupts for the receiveq
-(see [sub:Receiving-Used-Buffers]) and process packets until no
-more are found, then re-enable them.
-
-Processing packet involves:
-
-  If the driver negotiated the VIRTIO_NET_F_MRG_RXBUF feature,
-  then the “num_buffers” field indicates how many descriptors
-  this packet is spread over (including this one). This allows
-  receipt of large packets without having to allocate large
-  buffers. In this case, there will be at least “num_buffers” in
-  the used ring, and they should be chained together to form a
-  single packet. The other buffers will not begin with a struct
-  virtio_net_hdr.
-
-  If the VIRTIO_NET_F_MRG_RXBUF feature was not negotiated, or
-  the “num_buffers” field is one, then the entire packet will be
-  contained within this buffer, immediately following the struct
-  virtio_net_hdr.
-
-  If the VIRTIO_NET_F_GUEST_CSUM feature was negotiated, the
-  VIRTIO_NET_HDR_F_NEEDS_CSUM bit in the “flags” field may be
-  set: if so, the checksum on the packet is incomplete and the “
-  csum_start” and “csum_offset” fields indicate how to calculate
-  it (see [ite:csum_start-is-set]).
-
-  If the VIRTIO_NET_F_GUEST_TSO4, TSO6 or UFO options were
-  negotiated, then the “gso_type” may be something other than
-  VIRTIO_NET_HDR_GSO_NONE, and the “gso_size” field indicates the
-  desired MSS (see [enu:If-the-driver]).
-
-  Control Virtqueue
-
-The driver uses the control virtqueue (if VIRTIO_NET_F_VTRL_VQ is
-negotiated) to send commands to manipulate various features of
-the device which would not easily map into the configuration
-space.
-
-All commands are of the following form:
-
-struct virtio_net_ctrl {
-
-	u8 class;
-
-	u8 command;
-
-	u8 command-specific-data[];
-
-	u8 ack;
-
-};
-
-
-
-/* ack values */
-
-#define VIRTIO_NET_OK     0
-
-#define VIRTIO_NET_ERR    1
-
-The class, command and command-specific-data are set by the
-driver, and the device sets the ack byte. There is little it can
-do except issue a diagnostic if the ack byte is not
-VIRTIO_NET_OK.
-
-  Packet Receive Filtering
-
-If the VIRTIO_NET_F_CTRL_RX feature is negotiated, the driver can
-send control commands for promiscuous mode, multicast receiving,
-and filtering of MAC addresses.
-
-Note that in general, these commands are best-effort: unwanted
-packets may still arrive.
-
-  Setting Promiscuous Mode
-
-#define VIRTIO_NET_CTRL_RX    0
-
- #define VIRTIO_NET_CTRL_RX_PROMISC      0
-
- #define VIRTIO_NET_CTRL_RX_ALLMULTI     1
-
-The class VIRTIO_NET_CTRL_RX has two commands:
-VIRTIO_NET_CTRL_RX_PROMISC turns promiscuous mode on and off, and
-VIRTIO_NET_CTRL_RX_ALLMULTI turns all-multicast receive on and
-off. The command-specific-data is one byte containing 0 (off) or
-1 (on).
-
-  Setting MAC Address Filtering
-
-struct virtio_net_ctrl_mac {
-
-	u32 entries;
-
-	u8 macs[entries][ETH_ALEN];
-
-};
-
-
-
-#define VIRTIO_NET_CTRL_MAC    1
-
- #define VIRTIO_NET_CTRL_MAC_TABLE_SET        0
-
-The device can filter incoming packets by any number of
-destination MAC addresses.[footnote:
-Since there are no guarentees, it can use a hash filter
-orsilently switch to allmulti or promiscuous mode if it is given
-too many addresses.
-] This table is set using the class VIRTIO_NET_CTRL_MAC and the
-command VIRTIO_NET_CTRL_MAC_TABLE_SET. The command-specific-data
-is two variable length tables of 6-byte MAC addresses. The first
-table contains unicast addresses, and the second contains
-multicast addresses.
-
-  VLAN Filtering
-
-If the driver negotiates the VIRTION_NET_F_CTRL_VLAN feature, it
-can control a VLAN filter table in the device.
-
-#define VIRTIO_NET_CTRL_VLAN       2
-
- #define VIRTIO_NET_CTRL_VLAN_ADD             0
-
- #define VIRTIO_NET_CTRL_VLAN_DEL             1
-
-Both the VIRTIO_NET_CTRL_VLAN_ADD and VIRTIO_NET_CTRL_VLAN_DEL
-command take a 16-bit VLAN id as the command-specific-data.
-
-  Gratuitous Packet Sending
-
-If the driver negotiates the VIRTIO_NET_F_GUEST_ANNOUNCE (depends
-on VIRTIO_NET_F_CTRL_VQ), it can ask the guest to send gratuitous
-packets; this is usually done after the guest has been physically
-migrated, and needs to announce its presence on the new network
-links. (As hypervisor does not have the knowledge of guest
-network configuration (eg. tagged vlan) it is simplest to prod
-the guest in this way).
-
-#define VIRTIO_NET_CTRL_ANNOUNCE       3
-
- #define VIRTIO_NET_CTRL_ANNOUNCE_ACK             0
-
-The Guest needs to check VIRTIO_NET_S_ANNOUNCE bit in status
-field when it notices the changes of device configuration. The
-command VIRTIO_NET_CTRL_ANNOUNCE_ACK is used to indicate that
-driver has recevied the notification and device would clear the
-VIRTIO_NET_S_ANNOUNCE bit in the status filed after it received
-this command.
-
-Processing this notification involves:
-
-  Sending the gratuitous packets or marking there are pending
-  gratuitous packets to be sent and letting deferred routine to
-  send them.
-
-  Sending VIRTIO_NET_CTRL_ANNOUNCE_ACK command through control
-  vq.
-
-  .
-
-Appendix D: Block Device
-
-The virtio block device is a simple virtual block device (ie.
-disk). Read and write requests (and other exotic requests) are
-placed in the queue, and serviced (probably out of order) by the
-device except where noted.
-
-  Configuration
-
-  Subsystem Device ID 2
-
-  Virtqueues 0:requestq.
-
-  Feature bits
-
-  VIRTIO_BLK_F_BARRIER (0) Host supports request barriers.
-
-  VIRTIO_BLK_F_SIZE_MAX (1) Maximum size of any single segment is
-    in “size_max”.
-
-  VIRTIO_BLK_F_SEG_MAX (2) Maximum number of segments in a
-    request is in “seg_max”.
-
-  VIRTIO_BLK_F_GEOMETRY (4) Disk-style geometry specified in “
-    geometry”.
-
-  VIRTIO_BLK_F_RO (5) Device is read-only.
-
-  VIRTIO_BLK_F_BLK_SIZE (6) Block size of disk is in “blk_size”.
-
-  VIRTIO_BLK_F_SCSI (7) Device supports scsi packet commands.
-
-  VIRTIO_BLK_F_FLUSH (9) Cache flush command support.
-
-  Device configuration layout The capacity of the device
-  (expressed in 512-byte sectors) is always present. The
-  availability of the others all depend on various feature bits
-  as indicated above. struct virtio_blk_config {
-
-	u64 capacity;
-
-	u32 size_max;
-
-	u32 seg_max;
-
-	struct virtio_blk_geometry {
-
-		u16 cylinders;
-
-		u8 heads;
-
-		u8 sectors;
-
-	} geometry;
-
-	u32 blk_size;
-
-
-
-};
-
-  Device Initialization
-
-  The device size should be read from the “capacity”
-  configuration field. No requests should be submitted which goes
-  beyond this limit.
-
-  If the VIRTIO_BLK_F_BLK_SIZE feature is negotiated, the
-  blk_size field can be read to determine the optimal sector size
-  for the driver to use. This does not effect the units used in
-  the protocol (always 512 bytes), but awareness of the correct
-  value can effect performance.
-
-  If the VIRTIO_BLK_F_RO feature is set by the device, any write
-  requests will fail.
-
-  Device Operation
-
-The driver queues requests to the virtqueue, and they are used by
-the device (not necessarily in order). Each request is of form:
-
-struct virtio_blk_req {
-
-
-
-	u32 type;
-
-	u32 ioprio;
-
-	u64 sector;
-
-	char data[][512];
-
-	u8 status;
-
-};
-
-If the device has VIRTIO_BLK_F_SCSI feature, it can also support
-scsi packet command requests, each of these requests is of form:struct virtio_scsi_pc_req {
-
-	u32 type;
-
-	u32 ioprio;
-
-	u64 sector;
-
-    char cmd[];
-
-	char data[][512];
-
-#define SCSI_SENSE_BUFFERSIZE   96
-
-    u8 sense[SCSI_SENSE_BUFFERSIZE];
-
-    u32 errors;
-
-    u32 data_len;
-
-    u32 sense_len;
-
-    u32 residual;
-
-	u8 status;
-
-};
-
-The type of the request is either a read (VIRTIO_BLK_T_IN), a
-write (VIRTIO_BLK_T_OUT), a scsi packet command
-(VIRTIO_BLK_T_SCSI_CMD or VIRTIO_BLK_T_SCSI_CMD_OUT[footnote:
-the SCSI_CMD and SCSI_CMD_OUT types are equivalent, the device
-does not distinguish between them
-]) or a flush (VIRTIO_BLK_T_FLUSH or VIRTIO_BLK_T_FLUSH_OUT[footnote:
-the FLUSH and FLUSH_OUT types are equivalent, the device does not
-distinguish between them
-]). If the device has VIRTIO_BLK_F_BARRIER feature the high bit
-(VIRTIO_BLK_T_BARRIER) indicates that this request acts as a
-barrier and that all preceeding requests must be complete before
-this one, and all following requests must not be started until
-this is complete. Note that a barrier does not flush caches in
-the underlying backend device in host, and thus does not serve as
-data consistency guarantee. Driver must use FLUSH request to
-flush the host cache.
-
-#define VIRTIO_BLK_T_IN           0
-
-#define VIRTIO_BLK_T_OUT          1
-
-#define VIRTIO_BLK_T_SCSI_CMD     2
-
-#define VIRTIO_BLK_T_SCSI_CMD_OUT 3
-
-#define VIRTIO_BLK_T_FLUSH        4
-
-#define VIRTIO_BLK_T_FLUSH_OUT    5
-
-#define VIRTIO_BLK_T_BARRIER	 0x80000000
-
-The ioprio field is a hint about the relative priorities of
-requests to the device: higher numbers indicate more important
-requests.
-
-The sector number indicates the offset (multiplied by 512) where
-the read or write is to occur. This field is unused and set to 0
-for scsi packet commands and for flush commands.
-
-The cmd field is only present for scsi packet command requests,
-and indicates the command to perform. This field must reside in a
-single, separate read-only buffer; command length can be derived
-from the length of this buffer.
-
-Note that these first three (four for scsi packet commands)
-fields are always read-only: the data field is either read-only
-or write-only, depending on the request. The size of the read or
-write can be derived from the total size of the request buffers.
-
-The sense field is only present for scsi packet command requests,
-and indicates the buffer for scsi sense data.
-
-The data_len field is only present for scsi packet command
-requests, this field is deprecated, and should be ignored by the
-driver. Historically, devices copied data length there.
-
-The sense_len field is only present for scsi packet command
-requests and indicates the number of bytes actually written to
-the sense buffer.
-
-The residual field is only present for scsi packet command
-requests and indicates the residual size, calculated as data
-length - number of bytes actually transferred.
-
-The final status byte is written by the device: either
-VIRTIO_BLK_S_OK for success, VIRTIO_BLK_S_IOERR for host or guest
-error or VIRTIO_BLK_S_UNSUPP for a request unsupported by host:#define VIRTIO_BLK_S_OK        0
-
-#define VIRTIO_BLK_S_IOERR     1
-
-#define VIRTIO_BLK_S_UNSUPP    2
-
-Historically, devices assumed that the fields type, ioprio and
-sector reside in a single, separate read-only buffer; the fields
-errors, data_len, sense_len and residual reside in a single,
-separate write-only buffer; the sense field in a separate
-write-only buffer of size 96 bytes, by itself; the fields errors,
-data_len, sense_len and residual in a single write-only buffer;
-and the status field is a separate read-only buffer of size 1
-byte, by itself.
-
-Appendix E: Console Device
-
-The virtio console device is a simple device for data input and
-output. A device may have one or more ports. Each port has a pair
-of input and output virtqueues. Moreover, a device has a pair of
-control IO virtqueues. The control virtqueues are used to
-communicate information between the device and the driver about
-ports being opened and closed on either side of the connection,
-indication from the host about whether a particular port is a
-console port, adding new ports, port hot-plug/unplug, etc., and
-indication from the guest about whether a port or a device was
-successfully added, port open/close, etc.. For data IO, one or
-more empty buffers are placed in the receive queue for incoming
-data and outgoing characters are placed in the transmit queue.
-
-  Configuration
-
-  Subsystem Device ID 3
-
-  Virtqueues 0:receiveq(port0). 1:transmitq(port0), 2:control
-  receiveq[footnote:
-Ports 2 onwards only if VIRTIO_CONSOLE_F_MULTIPORT is set
-], 3:control transmitq, 4:receiveq(port1), 5:transmitq(port1),
-  ...
-
-  Feature bits
-
-  VIRTIO_CONSOLE_F_SIZE (0) Configuration cols and rows fields
-    are valid.
-
-  VIRTIO_CONSOLE_F_MULTIPORT(1) Device has support for multiple
-    ports; configuration fields nr_ports and max_nr_ports are
-    valid and control virtqueues will be used.
-
-  Device configuration layout The size of the console is supplied
-  in the configuration space if the VIRTIO_CONSOLE_F_SIZE feature
-  is set. Furthermore, if the VIRTIO_CONSOLE_F_MULTIPORT feature
-  is set, the maximum number of ports supported by the device can
-  be fetched.struct virtio_console_config {
-
-	u16 cols;
-
-	u16 rows;
-
-
-
-	u32 max_nr_ports;
-
-};
-
-  Device Initialization
-
-  If the VIRTIO_CONSOLE_F_SIZE feature is negotiated, the driver
-  can read the console dimensions from the configuration fields.
-
-  If the VIRTIO_CONSOLE_F_MULTIPORT feature is negotiated, the
-  driver can spawn multiple ports, not all of which may be
-  attached to a console. Some could be generic ports. In this
-  case, the control virtqueues are enabled and according to the
-  max_nr_ports configuration-space value, the appropriate number
-  of virtqueues are created. A control message indicating the
-  driver is ready is sent to the host. The host can then send
-  control messages for adding new ports to the device. After
-  creating and initializing each port, a
-  VIRTIO_CONSOLE_PORT_READY control message is sent to the host
-  for that port so the host can let us know of any additional
-  configuration options set for that port.
-
-  The receiveq for each port is populated with one or more
-  receive buffers.
-
-  Device Operation
-
-  For output, a buffer containing the characters is placed in the
-  port's transmitq.[footnote:
-Because this is high importance and low bandwidth, the current
-Linux implementation polls for the buffer to be used, rather than
-waiting for an interrupt, simplifying the implementation
-significantly. However, for generic serial ports with the
-O_NONBLOCK flag set, the polling limitation is relaxed and the
-consumed buffers are freed upon the next write or poll call or
-when a port is closed or hot-unplugged.
-]
-
-  When a buffer is used in the receiveq (signalled by an
-  interrupt), the contents is the input to the port associated
-  with the virtqueue for which the notification was received.
-
-  If the driver negotiated the VIRTIO_CONSOLE_F_SIZE feature, a
-  configuration change interrupt may occur. The updated size can
-  be read from the configuration fields.
-
-  If the driver negotiated the VIRTIO_CONSOLE_F_MULTIPORT
-  feature, active ports are announced by the host using the
-  VIRTIO_CONSOLE_PORT_ADD control message. The same message is
-  used for port hot-plug as well.
-
-  If the host specified a port `name', a sysfs attribute is
-  created with the name filled in, so that udev rules can be
-  written that can create a symlink from the port's name to the
-  char device for port discovery by applications in the guest.
-
-  Changes to ports' state are effected by control messages.
-  Appropriate action is taken on the port indicated in the
-  control message. The layout of the structure of the control
-  buffer and the events associated are:struct virtio_console_control {
-
-	uint32_t id;    /* Port number */
-
-	uint16_t event; /* The kind of control event */
-
-	uint16_t value; /* Extra information for the event */
-
-};
-
-
-
-/* Some events for the internal messages (control packets) */
-
-
-
-#define VIRTIO_CONSOLE_DEVICE_READY     0
-
-#define VIRTIO_CONSOLE_PORT_ADD         1
-
-#define VIRTIO_CONSOLE_PORT_REMOVE      2
-
-#define VIRTIO_CONSOLE_PORT_READY       3
-
-#define VIRTIO_CONSOLE_CONSOLE_PORT     4
-
-#define VIRTIO_CONSOLE_RESIZE           5
-
-#define VIRTIO_CONSOLE_PORT_OPEN        6
-
-#define VIRTIO_CONSOLE_PORT_NAME        7
-
-Appendix F: Entropy Device
-
-The virtio entropy device supplies high-quality randomness for
-guest use.
-
-  Configuration
-
-  Subsystem Device ID 4
-
-  Virtqueues 0:requestq.
-
-  Feature bits None currently defined
-
-  Device configuration layout None currently defined.
-
-  Device Initialization
-
-  The virtqueue is initialized
-
-  Device Operation
-
-When the driver requires random bytes, it places the descriptor
-of one or more buffers in the queue. It will be completely filled
-by random data by the device.
-
-Appendix G: Memory Balloon Device
-
-The virtio memory balloon device is a primitive device for
-managing guest memory: the device asks for a certain amount of
-memory, and the guest supplies it (or withdraws it, if the device
-has more than it asks for). This allows the guest to adapt to
-changes in allowance of underlying physical memory. If the
-feature is negotiated, the device can also be used to communicate
-guest memory statistics to the host.
-
-  Configuration
-
-  Subsystem Device ID 5
-
-  Virtqueues 0:inflateq. 1:deflateq. 2:statsq.[footnote:
-Only if VIRTIO_BALLON_F_STATS_VQ set
-]
-
-  Feature bits
-
-  VIRTIO_BALLOON_F_MUST_TELL_HOST (0) Host must be told before
-    pages from the balloon are used.
-
-  VIRTIO_BALLOON_F_STATS_VQ (1) A virtqueue for reporting guest
-    memory statistics is present.
-
-  Device configuration layout Both fields of this configuration
-  are always available. Note that they are little endian, despite
-  convention that device fields are guest endian:struct virtio_balloon_config {
-
-	u32 num_pages;
-
-	u32 actual;
-
-};
-
-  Device Initialization
-
-  The inflate and deflate virtqueues are identified.
-
-  If the VIRTIO_BALLOON_F_STATS_VQ feature bit is negotiated:
-
-  Identify the stats virtqueue.
-
-  Add one empty buffer to the stats virtqueue and notify the
-    host.
-
-Device operation begins immediately.
-
-  Device Operation
-
-  Memory Ballooning The device is driven by the receipt of a
-  configuration change interrupt.
-
-  The “num_pages” configuration field is examined. If this is
-  greater than the “actual” number of pages, memory must be given
-  to the balloon. If it is less than the “actual” number of
-  pages, memory may be taken back from the balloon for general
-  use.
-
-  To supply memory to the balloon (aka. inflate):
-
-  The driver constructs an array of addresses of unused memory
-    pages. These addresses are divided by 4096[footnote:
-This is historical, and independent of the guest page size
-] and the descriptor describing the resulting 32-bit array is
-    added to the inflateq.
-
-  To remove memory from the balloon (aka. deflate):
-
-  The driver constructs an array of addresses of memory pages it
-    has previously given to the balloon, as described above. This
-    descriptor is added to the deflateq.
-
-  If the VIRTIO_BALLOON_F_MUST_TELL_HOST feature is set, the
-    guest may not use these requested pages until that descriptor
-    in the deflateq has been used by the device.
-
-  Otherwise, the guest may begin to re-use pages previously given
-    to the balloon before the device has acknowledged their
-    withdrawl. [footnote:
-In this case, deflation advice is merely a courtesy
-]
-
-  In either case, once the device has completed the inflation or
-  deflation, the “actual” field of the configuration should be
-  updated to reflect the new number of pages in the balloon.[footnote:
-As updates to configuration space are not atomic, this field
-isn't particularly reliable, but can be used to diagnose buggy
-guests.
-]
-
-  Memory Statistics
-
-The stats virtqueue is atypical because communication is driven
-by the device (not the driver). The channel becomes active at
-driver initialization time when the driver adds an empty buffer
-and notifies the device. A request for memory statistics proceeds
-as follows:
-
-  The device pushes the buffer onto the used ring and sends an
-  interrupt.
-
-  The driver pops the used buffer and discards it.
-
-  The driver collects memory statistics and writes them into a
-  new buffer.
-
-  The driver adds the buffer to the virtqueue and notifies the
-  device.
-
-  The device pops the buffer (retaining it to initiate a
-  subsequent request) and consumes the statistics.
-
-  Memory Statistics Format Each statistic consists of a 16 bit
-  tag and a 64 bit value. Both quantities are represented in the
-  native endian of the guest. All statistics are optional and the
-  driver may choose which ones to supply. To guarantee backwards
-  compatibility, unsupported statistics should be omitted.
-
-  struct virtio_balloon_stat {
-
-#define VIRTIO_BALLOON_S_SWAP_IN  0
-
-#define VIRTIO_BALLOON_S_SWAP_OUT 1
-
-#define VIRTIO_BALLOON_S_MAJFLT   2
-
-#define VIRTIO_BALLOON_S_MINFLT   3
-
-#define VIRTIO_BALLOON_S_MEMFREE  4
-
-#define VIRTIO_BALLOON_S_MEMTOT   5
-
-	u16 tag;
-
-	u64 val;
-
-} __attribute__((packed));
-
-  Tags
-
-  VIRTIO_BALLOON_S_SWAP_IN The amount of memory that has been
-  swapped in (in bytes).
-
-  VIRTIO_BALLOON_S_SWAP_OUT The amount of memory that has been
-  swapped out to disk (in bytes).
-
-  VIRTIO_BALLOON_S_MAJFLT The number of major page faults that
-  have occurred.
-
-  VIRTIO_BALLOON_S_MINFLT The number of minor page faults that
-  have occurred.
-
-  VIRTIO_BALLOON_S_MEMFREE The amount of memory not being used
-  for any purpose (in bytes).
-
-  VIRTIO_BALLOON_S_MEMTOT The total amount of memory available
-  (in bytes).
-
-Appendix H: Rpmsg: Remote Processor Messaging
-
-Virtio rpmsg devices represent remote processors on the system
-which run in asymmetric multi-processing (AMP) configuration, and
-which are usually used to offload cpu-intensive tasks from the
-main application processor (a typical SoC methodology).
-
-Virtio is being used to communicate with those remote processors;
-empty buffers are placed in one virtqueue for receiving messages,
-and non-empty buffers, containing outbound messages, are enqueued
-in a second virtqueue for transmission.
-
-Numerous communication channels can be multiplexed over those two
-virtqueues, so different entities, running on the application and
-remote processor, can directly communicate in a point-to-point
-fashion.
-
-  Configuration
-
-  Subsystem Device ID 7
-
-  Virtqueues 0:receiveq. 1:transmitq.
-
-  Feature bits
-
-  VIRTIO_RPMSG_F_NS (0) Device sends (and capable of receiving)
-    name service messages announcing the creation (or
-    destruction) of a channel:/**
-
- * struct rpmsg_ns_msg - dynamic name service announcement
-message
-
- * @name: name of remote service that is published
-
- * @addr: address of remote service that is published
-
- * @flags: indicates whether service is created or destroyed
-
- *
-
- * This message is sent across to publish a new service (or
-announce
-
- * about its removal). When we receives these messages, an
-appropriate
-
- * rpmsg channel (i.e device) is created/destroyed.
-
- */
-
-struct rpmsg_ns_msgoon_config {
-
-	char name[RPMSG_NAME_SIZE];
-
-	u32 addr;
-
-	u32 flags;
-
-} __packed;
-
-
-
-/**
-
- * enum rpmsg_ns_flags - dynamic name service announcement flags
-
- *
-
- * @RPMSG_NS_CREATE: a new remote service was just created
-
- * @RPMSG_NS_DESTROY: a remote service was just destroyed
-
- */
-
-enum rpmsg_ns_flags {
-
-	RPMSG_NS_CREATE = 0,
-
-	RPMSG_NS_DESTROY = 1,
-
-};
-
-  Device configuration layout
-
-At his point none currently defined.
-
-  Device Initialization
-
-  The initialization routine should identify the receive and
-  transmission virtqueues.
-
-  The receive virtqueue should be filled with receive buffers.
-
-  Device Operation
-
-Messages are transmitted by placing them in the transmitq, and
-buffers for inbound messages are placed in the receiveq. In any
-case, messages are always preceded by the following header: /**
-
- * struct rpmsg_hdr - common header for all rpmsg messages
-
- * @src: source address
-
- * @dst: destination address
-
- * @reserved: reserved for future use
-
- * @len: length of payload (in bytes)
-
- * @flags: message flags
-
- * @data: @len bytes of message payload data
-
- *
-
- * Every message sent(/received) on the rpmsg bus begins with
-this header.
-
- */
-
-struct rpmsg_hdr {
-
-	u32 src;
-
-	u32 dst;
-
-	u32 reserved;
-
-	u16 len;
-
-	u16 flags;
-
-	u8 data[0];
-
-} __packed;
-
-Appendix I: SCSI Host Device
-
-The virtio SCSI host device groups together one or more virtual
-logical units (such as disks), and allows communicating to them
-using the SCSI protocol. An instance of the device represents a
-SCSI host to which many targets and LUNs are attached.
-
-The virtio SCSI device services two kinds of requests:
-
-  command requests for a logical unit;
-
-  task management functions related to a logical unit, target or
-  command.
-
-The device is also able to send out notifications about added and
-removed logical units. Together, these capabilities provide a
-SCSI transport protocol that uses virtqueues as the transfer
-medium. In the transport protocol, the virtio driver acts as the
-initiator, while the virtio SCSI host provides one or more
-targets that receive and process the requests.
-
-  Configuration
-
-  Subsystem Device ID 8
-
-  Virtqueues 0:controlq; 1:eventq; 2..n:request queues.
-
-  Feature bits
-
-  VIRTIO_SCSI_F_INOUT (0) A single request can include both
-    read-only and write-only data buffers.
-
-  VIRTIO_SCSI_F_HOTPLUG (1) The host should enable
-    hot-plug/hot-unplug of new LUNs and targets on the SCSI bus.
-
-  Device configuration layout All fields of this configuration
-  are always available. sense_size and cdb_size are writable by
-  the guest.struct virtio_scsi_config {
-
-    u32 num_queues;
-
-    u32 seg_max;
-
-    u32 max_sectors;
-
-    u32 cmd_per_lun;
-
-    u32 event_info_size;
-
-    u32 sense_size;
-
-    u32 cdb_size;
-
-    u16 max_channel;
-
-    u16 max_target;
-
-    u32 max_lun;
-
-};
-
-  num_queues is the total number of request virtqueues exposed by
-    the device. The driver is free to use only one request queue,
-    or it can use more to achieve better performance.
-
-  seg_max is the maximum number of segments that can be in a
-    command. A bidirectional command can include seg_max input
-    segments and seg_max output segments.
-
-  max_sectors is a hint to the guest about the maximum transfer
-    size it should use.
-
-  cmd_per_lun is a hint to the guest about the maximum number of
-    linked commands it should send to one LUN. The actual value
-    to be used is the minimum of cmd_per_lun and the virtqueue
-    size.
-
-  event_info_size is the maximum size that the device will fill
-    for buffers that the driver places in the eventq. The driver
-    should always put buffers at least of this size. It is
-    written by the device depending on the set of negotated
-    features.
-
-  sense_size is the maximum size of the sense data that the
-    device will write. The default value is written by the device
-    and will always be 96, but the driver can modify it. It is
-    restored to the default when the device is reset.
-
-  cdb_size is the maximum size of the CDB that the driver will
-    write. The default value is written by the device and will
-    always be 32, but the driver can likewise modify it. It is
-    restored to the default when the device is reset.
-
-  max_channel, max_target and max_lun can be used by the driver
-    as hints to constrain scanning the logical units on the
-    host.h
-
-  Device Initialization
-
-The initialization routine should first of all discover the
-device's virtqueues.
-
-If the driver uses the eventq, it should then place at least a
-buffer in the eventq.
-
-The driver can immediately issue requests (for example, INQUIRY
-or REPORT LUNS) or task management functions (for example, I_T
-RESET).
-
-  Device Operation: request queues
-
-The driver queues requests to an arbitrary request queue, and
-they are used by the device on that same queue. It is the
-responsibility of the driver to ensure strict request ordering
-for commands placed on different queues, because they will be
-consumed with no order constraints.
-
-Requests have the following format:
-
-struct virtio_scsi_req_cmd {
-
-    // Read-only
-
-    u8 lun[8];
-
-    u64 id;
-
-    u8 task_attr;
-
-    u8 prio;
-
-    u8 crn;
-
-    char cdb[cdb_size];
-
-    char dataout[];
-
-    // Write-only part
-
-    u32 sense_len;
-
-    u32 residual;
-
-    u16 status_qualifier;
-
-    u8 status;
-
-    u8 response;
-
-    u8 sense[sense_size];
-
-    char datain[];
-
-};
-
-
-
-/* command-specific response values */
-
-#define VIRTIO_SCSI_S_OK                0
-
-#define VIRTIO_SCSI_S_OVERRUN           1
-
-#define VIRTIO_SCSI_S_ABORTED           2
-
-#define VIRTIO_SCSI_S_BAD_TARGET        3
-
-#define VIRTIO_SCSI_S_RESET             4
-
-#define VIRTIO_SCSI_S_BUSY              5
-
-#define VIRTIO_SCSI_S_TRANSPORT_FAILURE 6
-
-#define VIRTIO_SCSI_S_TARGET_FAILURE    7
-
-#define VIRTIO_SCSI_S_NEXUS_FAILURE     8
-
-#define VIRTIO_SCSI_S_FAILURE           9
-
-
-
-/* task_attr */
-
-#define VIRTIO_SCSI_S_SIMPLE            0
-
-#define VIRTIO_SCSI_S_ORDERED           1
-
-#define VIRTIO_SCSI_S_HEAD              2
-
-#define VIRTIO_SCSI_S_ACA               3
-
-The lun field addresses a target and logical unit in the
-virtio-scsi device's SCSI domain. The only supported format for
-the LUN field is: first byte set to 1, second byte set to target,
-third and fourth byte representing a single level LUN structure,
-followed by four zero bytes. With this representation, a
-virtio-scsi device can serve up to 256 targets and 16384 LUNs per
-target.
-
-The id field is the command identifier (“tag”).
-
-task_attr, prio and crn should be left to zero. task_attr defines
-the task attribute as in the table above, but all task attributes
-may be mapped to SIMPLE by the device; crn may also be provided
-by clients, but is generally expected to be 0. The maximum CRN
-value defined by the protocol is 255, since CRN is stored in an
-8-bit integer.
-
-All of these fields are defined in SAM. They are always
-read-only, as are the cdb and dataout field. The cdb_size is
-taken from the configuration space.
-
-sense and subsequent fields are always write-only. The sense_len
-field indicates the number of bytes actually written to the sense
-buffer. The residual field indicates the residual size,
-calculated as “data_length - number_of_transferred_bytes”, for
-read or write operations. For bidirectional commands, the
-number_of_transferred_bytes includes both read and written bytes.
-A residual field that is less than the size of datain means that
-the dataout field was processed entirely. A residual field that
-exceeds the size of datain means that the dataout field was
-processed partially and the datain field was not processed at
-all.
-
-The status byte is written by the device to be the status code as
-defined in SAM.
-
-The response byte is written by the device to be one of the
-following:
-
-  VIRTIO_SCSI_S_OK when the request was completed and the status
-  byte is filled with a SCSI status code (not necessarily
-  "GOOD").
-
-  VIRTIO_SCSI_S_OVERRUN if the content of the CDB requires
-  transferring more data than is available in the data buffers.
-
-  VIRTIO_SCSI_S_ABORTED if the request was cancelled due to an
-  ABORT TASK or ABORT TASK SET task management function.
-
-  VIRTIO_SCSI_S_BAD_TARGET if the request was never processed
-  because the target indicated by the lun field does not exist.
-
-  VIRTIO_SCSI_S_RESET if the request was cancelled due to a bus
-  or device reset (including a task management function).
-
-  VIRTIO_SCSI_S_TRANSPORT_FAILURE if the request failed due to a
-  problem in the connection between the host and the target
-  (severed link).
-
-  VIRTIO_SCSI_S_TARGET_FAILURE if the target is suffering a
-  failure and the guest should not retry on other paths.
-
-  VIRTIO_SCSI_S_NEXUS_FAILURE if the nexus is suffering a failure
-  but retrying on other paths might yield a different result.
-
-  VIRTIO_SCSI_S_BUSY if the request failed but retrying on the
-  same path should work.
-
-  VIRTIO_SCSI_S_FAILURE for other host or guest error. In
-  particular, if neither dataout nor datain is empty, and the
-  VIRTIO_SCSI_F_INOUT feature has not been negotiated, the
-  request will be immediately returned with a response equal to
-  VIRTIO_SCSI_S_FAILURE.
-
-  Device Operation: controlq
-
-The controlq is used for other SCSI transport operations.
-Requests have the following format:
-
-struct virtio_scsi_ctrl {
-
-    u32 type;
-
-    ...
-
-    u8 response;
-
-};
-
-
-
-/* response values valid for all commands */
-
-#define VIRTIO_SCSI_S_OK                       0
-
-#define VIRTIO_SCSI_S_BAD_TARGET               3
-
-#define VIRTIO_SCSI_S_BUSY                     5
-
-#define VIRTIO_SCSI_S_TRANSPORT_FAILURE        6
-
-#define VIRTIO_SCSI_S_TARGET_FAILURE           7
-
-#define VIRTIO_SCSI_S_NEXUS_FAILURE            8
-
-#define VIRTIO_SCSI_S_FAILURE                  9
-
-#define VIRTIO_SCSI_S_INCORRECT_LUN            12
-
-The type identifies the remaining fields.
-
-The following commands are defined:
-
-  Task management function
-#define VIRTIO_SCSI_T_TMF                      0
-
-
-
-#define VIRTIO_SCSI_T_TMF_ABORT_TASK           0
-
-#define VIRTIO_SCSI_T_TMF_ABORT_TASK_SET       1
-
-#define VIRTIO_SCSI_T_TMF_CLEAR_ACA            2
-
-#define VIRTIO_SCSI_T_TMF_CLEAR_TASK_SET       3
-
-#define VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET      4
-
-#define VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET   5
-
-#define VIRTIO_SCSI_T_TMF_QUERY_TASK           6
-
-#define VIRTIO_SCSI_T_TMF_QUERY_TASK_SET       7
-
-
-
-struct virtio_scsi_ctrl_tmf
-
-{
-
-    // Read-only part
-
-    u32 type;
-
-    u32 subtype;
-
-    u8 lun[8];
-
-    u64 id;
-
-    // Write-only part
-
-    u8 response;
-
-}
-
-
-
-/* command-specific response values */
-
-#define VIRTIO_SCSI_S_FUNCTION_COMPLETE        0
-
-#define VIRTIO_SCSI_S_FUNCTION_SUCCEEDED       10
-
-#define VIRTIO_SCSI_S_FUNCTION_REJECTED        11
-
-  The type is VIRTIO_SCSI_T_TMF; the subtype field defines. All
-  fields except response are filled by the driver. The subtype
-  field must always be specified and identifies the requested
-  task management function.
-
-  Other fields may be irrelevant for the requested TMF; if so,
-  they are ignored but they should still be present. The lun
-  field is in the same format specified for request queues; the
-  single level LUN is ignored when the task management function
-  addresses a whole I_T nexus. When relevant, the value of the id
-  field is matched against the id values passed on the requestq.
-
-  The outcome of the task management function is written by the
-  device in the response field. The command-specific response
-  values map 1-to-1 with those defined in SAM.
-
-  Asynchronous notification query
-#define VIRTIO_SCSI_T_AN_QUERY                    1
-
-
-
-struct virtio_scsi_ctrl_an {
-
-    // Read-only part
-
-    u32 type;
-
-    u8  lun[8];
-
-    u32 event_requested;
-
-    // Write-only part
-
-    u32 event_actual;
-
-    u8  response;
-
-}
-
-
-
-#define VIRTIO_SCSI_EVT_ASYNC_OPERATIONAL_CHANGE  2
-
-#define VIRTIO_SCSI_EVT_ASYNC_POWER_MGMT          4
-
-#define VIRTIO_SCSI_EVT_ASYNC_EXTERNAL_REQUEST    8
-
-#define VIRTIO_SCSI_EVT_ASYNC_MEDIA_CHANGE        16
-
-#define VIRTIO_SCSI_EVT_ASYNC_MULTI_HOST          32
-
-#define VIRTIO_SCSI_EVT_ASYNC_DEVICE_BUSY         64
-
-  By sending this command, the driver asks the device which
-  events the given LUN can report, as described in paragraphs 6.6
-  and A.6 of the SCSI MMC specification. The driver writes the
-  events it is interested in into the event_requested; the device
-  responds by writing the events that it supports into
-  event_actual.
-
-  The type is VIRTIO_SCSI_T_AN_QUERY. The lun and event_requested
-  fields are written by the driver. The event_actual and response
-  fields are written by the device.
-
-  No command-specific values are defined for the response byte.
-
-  Asynchronous notification subscription
-#define VIRTIO_SCSI_T_AN_SUBSCRIBE                2
-
-
-
-struct virtio_scsi_ctrl_an {
-
-    // Read-only part
-
-    u32 type;
-
-    u8  lun[8];
-
-    u32 event_requested;
-
-    // Write-only part
-
-    u32 event_actual;
-
-    u8  response;
-
-}
-
-  By sending this command, the driver asks the specified LUN to
-  report events for its physical interface, again as described in
-  the SCSI MMC specification. The driver writes the events it is
-  interested in into the event_requested; the device responds by
-  writing the events that it supports into event_actual.
-
-  Event types are the same as for the asynchronous notification
-  query message.
-
-  The type is VIRTIO_SCSI_T_AN_SUBSCRIBE. The lun and
-  event_requested fields are written by the driver. The
-  event_actual and response fields are written by the device.
-
-  No command-specific values are defined for the response byte.
-
-  Device Operation: eventq
-
-The eventq is used by the device to report information on logical
-units that are attached to it. The driver should always leave a
-few buffers ready in the eventq. In general, the device will not
-queue events to cope with an empty eventq, and will end up
-dropping events if it finds no buffer ready. However, when
-reporting events for many LUNs (e.g. when a whole target
-disappears), the device can throttle events to avoid dropping
-them. For this reason, placing 10-15 buffers on the event queue
-should be enough.
-
-Buffers are placed in the eventq and filled by the device when
-interesting events occur. The buffers should be strictly
-write-only (device-filled) and the size of the buffers should be
-at least the value given in the device's configuration
-information.
-
-Buffers returned by the device on the eventq will be referred to
-as "events" in the rest of this section. Events have the
-following format:
-
-#define VIRTIO_SCSI_T_EVENTS_MISSED   0x80000000
-
-
-
-struct virtio_scsi_event {
-
-    // Write-only part
-
-    u32 event;
-
-    ...
-
-}
-
-If bit 31 is set in the event field, the device failed to report
-an event due to missing buffers. In this case, the driver should
-poll the logical units for unit attention conditions, and/or do
-whatever form of bus scan is appropriate for the guest operating
-system.
-
-Other data that the device writes to the buffer depends on the
-contents of the event field. The following events are defined:
-
-  No event
-#define VIRTIO_SCSI_T_NO_EVENT         0
-
-  This event is fired in the following cases:
-
-  When the device detects in the eventq a buffer that is shorter
-    than what is indicated in the configuration field, it might
-    use it immediately and put this dummy value in the event
-    field. A well-written driver will never observe this
-    situation.
-
-  When events are dropped, the device may signal this event as
-    soon as the drivers makes a buffer available, in order to
-    request action from the driver. In this case, of course, this
-    event will be reported with the VIRTIO_SCSI_T_EVENTS_MISSED
-    flag.
-
-  Transport reset
-#define VIRTIO_SCSI_T_TRANSPORT_RESET  1
-
-
-
-struct virtio_scsi_event_reset {
-
-    // Write-only part
-
-    u32 event;
-
-    u8  lun[8];
-
-    u32 reason;
-
-}
-
-
-
-#define VIRTIO_SCSI_EVT_RESET_HARD         0
-
-#define VIRTIO_SCSI_EVT_RESET_RESCAN       1
-
-#define VIRTIO_SCSI_EVT_RESET_REMOVED      2
-
-  By sending this event, the device signals that a logical unit
-  on a target has been reset, including the case of a new device
-  appearing or disappearing on the bus.The device fills in all
-  fields. The event field is set to
-  VIRTIO_SCSI_T_TRANSPORT_RESET. The lun field addresses a
-  logical unit in the SCSI host.
-
-  The reason value is one of the three #define values appearing
-  above:
-
-  VIRTIO_SCSI_EVT_RESET_REMOVED (“LUN/target removed”) is used if
-    the target or logical unit is no longer able to receive
-    commands.
-
-  VIRTIO_SCSI_EVT_RESET_HARD (“LUN hard reset”) is used if the
-    logical unit has been reset, but is still present.
-
-  VIRTIO_SCSI_EVT_RESET_RESCAN (“rescan LUN/target”) is used if a
-    target or logical unit has just appeared on the device.
-
-  The “removed” and “rescan” events, when sent for LUN 0, may
-  apply to the entire target. After receiving them the driver
-  should ask the initiator to rescan the target, in order to
-  detect the case when an entire target has appeared or
-  disappeared. These two events will never be reported unless the
-  VIRTIO_SCSI_F_HOTPLUG feature was negotiated between the host
-  and the guest.
-
-  Events will also be reported via sense codes (this obviously
-  does not apply to newly appeared buses or targets, since the
-  application has never discovered them):
-
-  “LUN/target removed” maps to sense key ILLEGAL REQUEST, asc
-    0x25, ascq 0x00 (LOGICAL UNIT NOT SUPPORTED)
-
-  “LUN hard reset” maps to sense key UNIT ATTENTION, asc 0x29
-    (POWER ON, RESET OR BUS DEVICE RESET OCCURRED)
-
-  “rescan LUN/target” maps to sense key UNIT ATTENTION, asc 0x3f,
-    ascq 0x0e (REPORTED LUNS DATA HAS CHANGED)
-
-  The preferred way to detect transport reset is always to use
-  events, because sense codes are only seen by the driver when it
-  sends a SCSI command to the logical unit or target. However, in
-  case events are dropped, the initiator will still be able to
-  synchronize with the actual state of the controller if the
-  driver asks the initiator to rescan of the SCSI bus. During the
-  rescan, the initiator will be able to observe the above sense
-  codes, and it will process them as if it the driver had
-  received the equivalent event.
-
-  Asynchronous notification
-#define VIRTIO_SCSI_T_ASYNC_NOTIFY     2
-
-
-
-struct virtio_scsi_event_an {
-
-    // Write-only part
-
-    u32 event;
-
-    u8  lun[8];
-
-    u32 reason;
-
-}
-
-  By sending this event, the device signals that an asynchronous
-  event was fired from a physical interface.
-
-  All fields are written by the device. The event field is set to
-  VIRTIO_SCSI_T_ASYNC_NOTIFY. The lun field addresses a logical
-  unit in the SCSI host. The reason field is a subset of the
-  events that the driver has subscribed to via the "Asynchronous
-  notification subscription" command.
-
-  When dropped events are reported, the driver should poll for
-  asynchronous events manually using SCSI commands.
-
-Appendix X: virtio-mmio
-
-Virtual environments without PCI support (a common situation in
-embedded devices models) might use simple memory mapped device (“
-virtio-mmio”) instead of the PCI device.
-
-The memory mapped virtio device behaviour is based on the PCI
-device specification. Therefore most of operations like device
-initialization, queues configuration and buffer transfers are
-nearly identical. Existing differences are described in the
-following sections.
-
-  Device Initialization
-
-Instead of using the PCI IO space for virtio header, the “
-virtio-mmio” device provides a set of memory mapped control
-registers, all 32 bits wide, followed by device-specific
-configuration space. The following list presents their layout:
-
-  Offset from the device base address | Direction | Name
- Description
-
-  0x000 | R | MagicValue
- “virt” string.
-
-  0x004 | R | Version
- Device version number. Currently must be 1.
-
-  0x008 | R | DeviceID
- Virtio Subsystem Device ID (ie. 1 for network card).
-
-  0x00c | R | VendorID
- Virtio Subsystem Vendor ID.
-
-  0x010 | R | HostFeatures
- Flags representing features the device supports.
- Reading from this register returns 32 consecutive flag bits,
-  first bit depending on the last value written to
-  HostFeaturesSel register. Access to this register returns bits HostFeaturesSel*32
-
-   to (HostFeaturesSel*32)+31
-, eg. feature bits 0 to 31 if
-  HostFeaturesSel is set to 0 and features bits 32 to 63 if
-  HostFeaturesSel is set to 1. Also see [sub:Feature-Bits]
-
-  0x014 | W | HostFeaturesSel
- Device (Host) features word selection.
- Writing to this register selects a set of 32 device feature bits
-  accessible by reading from HostFeatures register. Device driver
-  must write a value to the HostFeaturesSel register before
-  reading from the HostFeatures register.
-
-  0x020 | W | GuestFeatures
- Flags representing device features understood and activated by
-  the driver.
- Writing to this register sets 32 consecutive flag bits, first
-  bit depending on the last value written to GuestFeaturesSel
-  register. Access to this register sets bits GuestFeaturesSel*32
-
-   to (GuestFeaturesSel*32)+31
-, eg. feature bits 0 to 31 if
-  GuestFeaturesSel is set to 0 and features bits 32 to 63 if
-  GuestFeaturesSel is set to 1. Also see [sub:Feature-Bits]
-
-  0x024 | W | GuestFeaturesSel
- Activated (Guest) features word selection.
- Writing to this register selects a set of 32 activated feature
-  bits accessible by writing to the GuestFeatures register.
-  Device driver must write a value to the GuestFeaturesSel
-  register before writing to the GuestFeatures register.
-
-  0x028 | W | GuestPageSize
- Guest page size.
- Device driver must write the guest page size in bytes to the
-  register during initialization, before any queues are used.
-  This value must be a power of 2 and is used by the Host to
-  calculate Guest address of the first queue page (see QueuePFN).
-
-  0x030 | W | QueueSel
- Virtual queue index (first queue is 0).
- Writing to this register selects the virtual queue that the
-  following operations on QueueNum, QueueAlign and QueuePFN apply
-  to.
-
-  0x034 | R | QueueNumMax
- Maximum virtual queue size.
- Reading from the register returns the maximum size of the queue
-  the Host is ready to process or zero (0x0) if the queue is not
-  available. This applies to the queue selected by writing to
-  QueueSel and is allowed only when QueuePFN is set to zero
-  (0x0), so when the queue is not actively used.
-
-  0x038 | W | QueueNum
- Virtual queue size.
- Queue size is a number of elements in the queue, therefore size
-  of the descriptor table and both available and used rings.
- Writing to this register notifies the Host what size of the
-  queue the Guest will use. This applies to the queue selected by
-  writing to QueueSel.
-
-  0x03c | W | QueueAlign
- Used Ring alignment in the virtual queue.
- Writing to this register notifies the Host about alignment
-  boundary of the Used Ring in bytes. This value must be a power
-  of 2 and applies to the queue selected by writing to QueueSel.
-
-  0x040 | RW | QueuePFN
- Guest physical page number of the virtual queue.
- Writing to this register notifies the host about location of the
-  virtual queue in the Guest's physical address space. This value
-  is the index number of a page starting with the queue
-  Descriptor Table. Value zero (0x0) means physical address zero
-  (0x00000000) and is illegal. When the Guest stops using the
-  queue it must write zero (0x0) to this register.
- Reading from this register returns the currently used page
-  number of the queue, therefore a value other than zero (0x0)
-  means that the queue is in use.
- Both read and write accesses apply to the queue selected by
-  writing to QueueSel.
-
-  0x050 | W | QueueNotify
- Queue notifier.
- Writing a queue index to this register notifies the Host that
-  there are new buffers to process in the queue.
-
-  0x60 | R | InterruptStatus
-Interrupt status.
-Reading from this register returns a bit mask of interrupts
-  asserted by the device. An interrupt is asserted if the
-  corresponding bit is set, ie. equals one (1).
-
-  Bit 0 | Used Ring Update
-This interrupt is asserted when the Host has updated the Used
-    Ring in at least one of the active virtual queues.
-
-  Bit 1 | Configuration change
-This interrupt is asserted when configuration of the device has
-    changed.
-
-  0x064 | W | InterruptACK
- Interrupt acknowledge.
- Writing to this register notifies the Host that the Guest
-  finished handling interrupts. Set bits in the value clear the
-  corresponding bits of the InterruptStatus register.
-
-  0x070 | RW | Status
- Device status.
- Reading from this register returns the current device status
-  flags.
- Writing non-zero values to this register sets the status flags,
-  indicating the Guest progress. Writing zero (0x0) to this
-  register triggers a device reset.
- Also see [sub:Device-Initialization-Sequence]
-
-  0x100+ | RW | Config
- Device-specific configuration space starts at an offset 0x100
-  and is accessed with byte alignment. Its meaning and size
-  depends on the device and the driver.
-
-Virtual queue size is a number of elements in the queue,
-therefore size of the descriptor table and both available and
-used rings.
-
-The endianness of the registers follows the native endianness of
-the Guest. Writing to registers described as “R” and reading from
-registers described as “W” is not permitted and can cause
-undefined behavior.
-
-The device initialization is performed as described in [sub:Device-Initialization-Sequence]
- with one exception: the Guest must notify the Host about its
-page size, writing the size in bytes to GuestPageSize register
-before the initialization is finished.
-
-The memory mapped virtio devices generate single interrupt only,
-therefore no special configuration is required.
-
-  Virtqueue Configuration
-
-The virtual queue configuration is performed in a similar way to
-the one described in [sec:Virtqueue-Configuration] with a few
-additional operations:
-
-  Select the queue writing its index (first queue is 0) to the
-  QueueSel register.
-
-  Check if the queue is not already in use: read QueuePFN
-  register, returned value should be zero (0x0).
-
-  Read maximum queue size (number of elements) from the
-  QueueNumMax register. If the returned value is zero (0x0) the
-  queue is not available.
-
-  Allocate and zero the queue pages in contiguous virtual memory,
-  aligning the Used Ring to an optimal boundary (usually page
-  size). Size of the allocated queue may be smaller than or equal
-  to the maximum size returned by the Host.
-
-  Notify the Host about the queue size by writing the size to
-  QueueNum register.
-
-  Notify the Host about the used alignment by writing its value
-  in bytes to QueueAlign register.
-
-  Write the physical number of the first page of the queue to the
-  QueuePFN register.
-
-The queue and the device are ready to begin normal operations
-now.
-
-  Device Operation
-
-The memory mapped virtio device behaves in the same way as
-described in [sec:Device-Operation], with the following
-exceptions:
-
-  The device is notified about new buffers available in a queue
-  by writing the queue index to register QueueNum instead of the
-  virtio header in PCI I/O space ([sub:Notifying-The-Device]).
-
-  The memory mapped virtio device is using single, dedicated
-  interrupt signal, which is raised when at least one of the
-  interrupts described in the InterruptStatus register
-  description is asserted. After receiving an interrupt, the
-  driver must read the InterruptStatus register to check what
-  caused the interrupt (see the register description). After the
-  interrupt is handled, the driver must acknowledge it by writing
-  a bit mask corresponding to the serviced interrupt to the
-  InterruptACK register.
-
diff --git a/Documentation/xtensa/mmu.txt b/Documentation/xtensa/mmu.txt
new file mode 100644
index 0000000..2b1af76
--- /dev/null
+++ b/Documentation/xtensa/mmu.txt
@@ -0,0 +1,46 @@
+MMUv3 initialization sequence.
+
+The code in the initialize_mmu macro sets up MMUv3 memory mapping
+identically to MMUv2 fixed memory mapping. Depending on
+CONFIG_INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX symbol this code is
+located in one of the following address ranges:
+
+    0xF0000000..0xFFFFFFFF (will keep same address in MMU v2 layout;
+    			 typically ROM)
+    0x00000000..0x07FFFFFF (system RAM; this code is actually linked
+    			 at 0xD0000000..0xD7FFFFFF [cached]
+    			 or 0xD8000000..0xDFFFFFFF [uncached];
+    			 in any case, initially runs elsewhere
+    			 than linked, so have to be careful)
+
+The code has the following assumptions:
+  This code fragment is run only on an MMU v3.
+  TLBs are in their reset state.
+  ITLBCFG and DTLBCFG are zero (reset state).
+  RASID is 0x04030201 (reset state).
+  PS.RING is zero (reset state).
+  LITBASE is zero (reset state, PC-relative literals); required to be PIC.
+
+TLB setup proceeds along the following steps.
+
+  Legend:
+    VA = virtual address (two upper nibbles of it);
+    PA = physical address (two upper nibbles of it);
+    pc = physical range that contains this code;
+
+After step 2, we jump to virtual address in 0x40000000..0x5fffffff
+that corresponds to next instruction to execute in this code.
+After step 4, we jump to intended (linked) address of this code.
+
+    Step 0     Step1     Step 2     Step3     Step 4     Step5
+ ============  =====  ============  =====  ============  =====
+   VA      PA     PA    VA      PA     PA    VA      PA     PA
+ ------    --     --  ------    --     --  ------    --     --
+ E0..FF -> E0  -> E0  E0..FF -> E0         F0..FF -> F0  -> F0
+ C0..DF -> C0  -> C0  C0..DF -> C0         E0..EF -> F0  -> F0
+ A0..BF -> A0  -> A0  A0..BF -> A0         D8..DF -> 00  -> 00
+ 80..9F -> 80  -> 80  80..9F -> 80         D0..D7 -> 00  -> 00
+ 60..7F -> 60  -> 60  60..7F -> 60
+ 40..5F -> 40         40..5F -> pc  -> pc  40..5F -> pc
+ 20..3F -> 20  -> 20  20..3F -> 20
+ 00..1F -> 00  -> 00  00..1F -> 00
diff --git a/MAINTAINERS b/MAINTAINERS
index 74e58a4..25364e0 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -90,6 +90,9 @@ Descriptions of section entries:
 	   F:	drivers/net/*	all files in drivers/net, but not below
 	   F:	*/net/*		all files in "any top level directory"/net
 	   One pattern per line.  Multiple F: lines acceptable.
+	N: Files and directories with regex patterns.
+	   N:	[^a-z]tegra	all files whose path contains the word tegra
+	   One pattern per line.  Multiple N: lines acceptable.
 	X: Files and directories that are NOT maintained, same rules as F:
 	   Files exclusions are tested before file matches.
 	   Can be useful for excluding a specific subdirectory, for instance:
@@ -97,13 +100,12 @@ Descriptions of section entries:
 	   X:	net/ipv6/
 	   matches all files in and below net excluding net/ipv6/
 	K: Keyword perl extended regex pattern to match content in a
-	   patch or file, or an affected filename.  For instance:
+	   patch or file.  For instance:
 	   K: of_get_profile
-	      matches patch or file content, or filenames, that contain
-	      "of_get_profile"
+	      matches patches or files that contain "of_get_profile"
 	   K: \b(printk|pr_(info|err))\b
-	      matches patch or file content, or filenames, that contain one or
-	      more of the words printk, pr_info or pr_err
+	      matches patches or files that contain one or more of the words
+	      printk, pr_info or pr_err
 	   One regex pattern per line.  Multiple K: lines acceptable.
 
 Note: For the hard of thinking, this list is meant to remain in alphabetical
@@ -799,6 +801,7 @@ S:	Maintained
 F:	arch/arm/mach-prima2/
 F:	drivers/dma/sirf-dma.c
 F:	drivers/i2c/busses/i2c-sirf.c
+F:	drivers/mmc/host/sdhci-sirf.c
 F:	drivers/pinctrl/pinctrl-sirf.c
 F:	drivers/spi/spi-sirf.c
 
@@ -1031,6 +1034,7 @@ F:	drivers/mmc/host/msm_sdcc.h
 F:	drivers/tty/serial/msm_serial.h
 F:	drivers/tty/serial/msm_serial.c
 F:	drivers/*/pm8???-*
+F:	drivers/ssbi/
 F:	include/linux/mfd/pm8xxx/
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/davidb/linux-msm.git
 S:	Maintained
@@ -1616,6 +1620,13 @@ W:	http://www.baycom.org/~tom/ham/ham.html
 S:	Maintained
 F:	drivers/net/hamradio/baycom*
 
+BCACHE (BLOCK LAYER CACHE)
+M:	Kent Overstreet <koverstreet@google.com>
+L:	linux-bcache@vger.kernel.org
+W:	http://bcache.evilpiepirate.org
+S:	Maintained:
+F:	drivers/md/bcache/
+
 BEFS FILE SYSTEM
 S:	Orphan
 F:	Documentation/filesystems/befs.txt
@@ -2206,6 +2217,17 @@ S:	Maintained
 F:	drivers/cpufreq/
 F:	include/linux/cpufreq.h
 
+CPU FREQUENCY DRIVERS - ARM BIG LITTLE
+M:	Viresh Kumar <viresh.kumar@linaro.org>
+M:	Sudeep KarkadaNagesha <sudeep.karkadanagesha@arm.com>
+L:	cpufreq@vger.kernel.org
+L:	linux-pm@vger.kernel.org
+W:	http://www.arm.com/products/processors/technologies/biglittleprocessing.php
+S:	Maintained
+F:	drivers/cpufreq/arm_big_little.h
+F:	drivers/cpufreq/arm_big_little.c
+F:	drivers/cpufreq/arm_big_little_dt.c
+
 CPUID/MSR DRIVER
 M:	"H. Peter Anvin" <hpa@zytor.com>
 S:	Maintained
@@ -2284,7 +2306,7 @@ L:	linux-media@vger.kernel.org
 T:	git git://linuxtv.org/media_tree.git
 W:	http://linuxtv.org
 S:	Maintained
-F:	drivers/media/i2c/cx2341x*
+F:	drivers/media/common/cx2341x*
 F:	include/media/cx2341x*
 
 CX88 VIDEO4LINUX DRIVER
@@ -2441,9 +2463,7 @@ S:	Maintained
 F:	drivers/platform/x86/dell-laptop.c
 
 DELL LAPTOP SMM DRIVER
-M:	Massimo Dal Zotto <dz@debian.org>
-W:	http://www.debian.org/~dz/i8k/
-S:	Maintained
+S:	Orphan
 F:	drivers/char/i8k.c
 F:	include/uapi/linux/i8k.h
 
@@ -2458,6 +2478,12 @@ M:	Matthew Garrett <mjg59@srcf.ucam.org>
 S:	Maintained
 F:	drivers/platform/x86/dell-wmi.c
 
+DESIGNWARE USB2 DRD IP DRIVER
+M:	Paul Zimmerman <paulz@synopsys.com>
+L:	linux-usb@vger.kernel.org
+S:	Maintained
+F:	drivers/staging/dwc2/
+
 DESIGNWARE USB3 DRD IP DRIVER
 M:	Felipe Balbi <balbi@ti.com>
 L:	linux-usb@vger.kernel.org
@@ -4422,6 +4448,16 @@ Q:	http://patchwork.linuxtv.org/project/linux-media/list/
 S:	Maintained
 F:	drivers/media/dvb-frontends/it913x-fe*
 
+IT913X MEDIA DRIVER
+M:	Antti Palosaari <crope@iki.fi>
+L:	linux-media@vger.kernel.org
+W:	http://linuxtv.org/
+W:	http://palosaari.fi/linux/
+Q:	http://patchwork.linuxtv.org/project/linux-media/list/
+T:	git git://linuxtv.org/anttip/media_tree.git
+S:	Maintained
+F:	drivers/media/tuners/it913x*
+
 IVTV VIDEO4LINUX DRIVER
 M:	Andy Walls <awalls@md.metrocast.net>
 L:	ivtv-devel@ivtvdriver.org (moderated for non-subscribers)
@@ -5065,9 +5101,8 @@ S:	Maintained
 F:	drivers/net/ethernet/marvell/sk*
 
 MARVELL LIBERTAS WIRELESS DRIVER
-M:	Dan Williams <dcbw@redhat.com>
 L:	libertas-dev@lists.infradead.org
-S:	Maintained
+S:	Orphan
 F:	drivers/net/wireless/libertas/
 
 MARVELL MV643XX ETHERNET DRIVER
@@ -5407,6 +5442,13 @@ L:	linux-scsi@vger.kernel.org
 S:	Maintained
 F:	drivers/scsi/NCR_D700.*
 
+NCT6775 HARDWARE MONITOR DRIVER
+M:	Guenter Roeck <linux@roeck-us.net>
+L:	lm-sensors@lm-sensors.org
+S:	Maintained
+F:	Documentation/hwmon/nct6775
+F:	drivers/hwmon/nct6775.c
+
 NETEFFECT IWARP RNIC DRIVER (IW_NES)
 M:	Faisal Latif <faisal.latif@intel.com>
 L:	linux-rdma@vger.kernel.org
@@ -5569,6 +5611,7 @@ F:	include/uapi/linux/if_*
 F:	include/uapi/linux/netdevice.h
 
 NETXEN (1/10) GbE SUPPORT
+M:	Manish Chopra <manish.chopra@qlogic.com>
 M:	Sony Chacko <sony.chacko@qlogic.com>
 M:	Rajesh Borundia <rajesh.borundia@qlogic.com>
 L:	netdev@vger.kernel.org
@@ -6330,6 +6373,7 @@ F:	drivers/acpi/apei/erst.c
 
 PTP HARDWARE CLOCK SUPPORT
 M:	Richard Cochran <richardcochran@gmail.com>
+L:	netdev@vger.kernel.org
 S:	Maintained
 W:	http://linuxptp.sourceforge.net/
 F:	Documentation/ABI/testing/sysfs-ptp
@@ -6461,6 +6505,7 @@ S:	Supported
 F:	drivers/net/ethernet/qlogic/qlcnic/
 
 QLOGIC QLGE 10Gb ETHERNET DRIVER
+M:	Shahed Shaikh <shahed.shaikh@qlogic.com>
 M:	Jitendra Kalsaria <jitendra.kalsaria@qlogic.com>
 M:	Ron Mercer <ron.mercer@qlogic.com>
 M:	linux-driver@qlogic.com
@@ -6788,7 +6833,7 @@ L:	linux-media@vger.kernel.org
 W:	http://linuxtv.org
 T:	git git://linuxtv.org/media_tree.git
 S:	Odd fixes
-F:	Documentation/video4linux/saa7134/
+F:	Documentation/video4linux/*.saa7134
 F:	drivers/media/pci/saa7134/
 
 SAA7146 VIDEO4LINUX-2 DRIVER
@@ -6881,9 +6926,8 @@ F:	drivers/clocksource
 
 TLG2300 VIDEO4LINUX-2 DRIVER
 M:	Huang Shijie <shijie8@gmail.com>
-M:	Kang Yong <kangyong@telegent.com>
-M:	Zhang Xiaobing <xbzhang@telegent.com>
-S:	Supported
+M:	Hans Verkuil <hverkuil@xs4all.nl>
+S:	Odd Fixes
 F:	drivers/media/usb/tlg2300
 
 SC1200 WDT DRIVER
@@ -7130,12 +7174,38 @@ F:	drivers/media/radio/si470x/radio-si470x-common.c
 F:	drivers/media/radio/si470x/radio-si470x.h
 F:	drivers/media/radio/si470x/radio-si470x-usb.c
 
+SI4713 FM RADIO TRANSMITTER I2C DRIVER
+M:	Eduardo Valentin <edubezval@gmail.com>
+L:	linux-media@vger.kernel.org
+T:	git git://linuxtv.org/media_tree.git
+W:	http://linuxtv.org
+S:	Odd Fixes
+F:	drivers/media/radio/si4713-i2c.?
+
+SI4713 FM RADIO TRANSMITTER PLATFORM DRIVER
+M:	Eduardo Valentin <edubezval@gmail.com>
+L:	linux-media@vger.kernel.org
+T:	git git://linuxtv.org/media_tree.git
+W:	http://linuxtv.org
+S:	Odd Fixes
+F:	drivers/media/radio/radio-si4713.h
+
+SIANO DVB DRIVER
+M:	Mauro Carvalho Chehab <mchehab@redhat.com>
+L:	linux-media@vger.kernel.org
+W:	http://linuxtv.org
+T:	git git://linuxtv.org/media_tree.git
+S:	Odd fixes
+F:	drivers/media/common/siano/
+F:	drivers/media/dvb/siano/
+F:	drivers/media/usb/siano/
+F:	drivers/media/mmc/siano
+
 SH_VEU V4L2 MEM2MEM DRIVER
 M:	Guennadi Liakhovetski <g.liakhovetski@gmx.de>
 L:	linux-media@vger.kernel.org
 S:	Maintained
 F:	drivers/media/platform/sh_veu.c
-F:	include/media/sh_veu.h
 
 SH_VOU V4L2 OUTPUT DRIVER
 M:	Guennadi Liakhovetski <g.liakhovetski@gmx.de>
@@ -7561,6 +7631,11 @@ M:	David Täht <d@teklibre.com>
 S:	Odd Fixes
 F:	drivers/staging/frontier/
 
+STAGING - GO7007 MPEG CODEC
+M:	Hans Verkuil <hans.verkuil@cisco.com>
+S:	Maintained
+F:	drivers/staging/media/go7007/
+
 STAGING - INDUSTRIAL IO
 M:	Jonathan Cameron <jic23@cam.ac.uk>
 L:	linux-iio@vger.kernel.org
@@ -7611,8 +7686,8 @@ S:	Odd Fixes
 F:	drivers/staging/sm7xxfb/
 
 STAGING - SOFTLOGIC 6x10 MPEG CODEC
-M:	Ben Collins <bcollins@bluecherry.net>
-S:	Odd Fixes
+M:	Ismael Luceno <ismael.luceno@corp.bluecherry.net>
+S:	Supported
 F:	drivers/staging/media/solo6x10/
 
 STAGING - SPEAKUP CONSOLE SPEECH DRIVER
@@ -7877,7 +7952,7 @@ L:	linux-tegra@vger.kernel.org
 Q:	http://patchwork.ozlabs.org/project/linux-tegra/list/
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-tegra.git
 S:	Supported
-K:	(?i)[^a-z]tegra
+N:	[^a-z]tegra
 
 TEHUTI ETHERNET DRIVER
 M:	Andy Gospodarek <andy@greyhouse.net>
@@ -7920,6 +7995,12 @@ T:	git git://repo.or.cz/linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git
 S:	Maintained
 F:	drivers/platform/x86/thinkpad_acpi.c
 
+TI BANDGAP AND THERMAL DRIVER
+M:	Eduardo Valentin <eduardo.valentin@ti.com>
+L:	linux-pm@vger.kernel.org
+S:	Maintained
+F:	drivers/staging/omap-thermal/
+
 TI FLASH MEDIA INTERFACE DRIVER
 M:	Alex Dubov <oakad@yahoo.com>
 S:	Maintained
@@ -8515,7 +8596,7 @@ F:	drivers/usb/gadget/*uvc*.c
 F:	drivers/usb/gadget/webcam.c
 
 USB WIRELESS RNDIS DRIVER (rndis_wlan)
-M:	Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
+M:	Jussi Kivilinna <jussi.kivilinna@iki.fi>
 L:	linux-wireless@vger.kernel.org
 S:	Maintained
 F:	drivers/net/wireless/rndis_wlan.c
@@ -8620,6 +8701,7 @@ F:	drivers/virtio/
 F:	drivers/net/virtio_net.c
 F:	drivers/block/virtio_blk.c
 F:	include/linux/virtio_*.h
+F:	include/uapi/linux/virtio_*.h
 
 VIRTIO HOST (VHOST)
 M:	"Michael S. Tsirkin" <mst@redhat.com>
@@ -8707,7 +8789,7 @@ F:	drivers/scsi/vmw_pvscsi.c
 F:	drivers/scsi/vmw_pvscsi.h
 
 VOLTAGE AND CURRENT REGULATOR FRAMEWORK
-M:	Liam Girdwood <lrg@ti.com>
+M:	Liam Girdwood <lgirdwood@gmail.com>
 M:	Mark Brown <broonie@opensource.wolfsonmicro.com>
 W:	http://opensource.wolfsonmicro.com/node/15
 W:	http://www.slimlogic.co.uk/?p=48
diff --git a/Makefile b/Makefile
index 58a165b..4947d71 100644
--- a/Makefile
+++ b/Makefile
@@ -1398,7 +1398,7 @@ quiet_cmd_rmfiles = $(if $(wildcard $(rm-files)),CLEAN   $(wildcard $(rm-files))
 # Run depmod only if we have System.map and depmod is executable
 quiet_cmd_depmod = DEPMOD  $(KERNELRELEASE)
       cmd_depmod = $(CONFIG_SHELL) $(srctree)/scripts/depmod.sh $(DEPMOD) \
-                   $(KERNELRELEASE) "$(patsubst "%",%,$(CONFIG_SYMBOL_PREFIX))"
+                   $(KERNELRELEASE) "$(patsubst y,_,$(CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX))"
 
 # Create temporary dir for module support files
 # clean it up only when building all modules
diff --git a/Next/SHA1s b/Next/SHA1s
new file mode 100644
index 0000000..a8b197b
--- /dev/null
+++ b/Next/SHA1s
@@ -0,0 +1,224 @@
+Name		SHA1
+----		----
+origin		b6a9b7f6b1f21735a7456d534dc0e68e61359d2c
+fixes		9064171268d838b8f283fe111ef086b9479d059a
+kbuild-current	6dbe51c251a327e012439c4772097a13df43c5b8
+arc-current	07961ac7c0ee8b546658717034fe692fd12eefa9
+arm-current	4e1db26a0b42e2b6e27c05d68adcc01709c2eed2
+m68k-current	561839598e61f03c9175183ea066b2b7fa58ce85
+powerpc-merge	af81d7878c641629f2693ae3fdaf74b4af14dfca
+sparc		cbf1ef6b3345d2cc7e62407eec6a6f72a8b1346f
+net		e2409d83434d77874b461b78af6a19cd6e6a1280
+ipsec		da241efcd9c3da2af6ba20055c7e158ec725005c
+sound-current	8fc24426f15d967d585af7062b7be3c46bbce571
+pci-current	de7d5f729c72638f41d7c17487bccb1c570ff144
+wireless	69a2bac8984c4e6dba78b330ed183fd580c65e99
+driver-core.current	07961ac7c0ee8b546658717034fe692fd12eefa9
+tty.current	1f66396682a0be92e1c141bff4b006d7654832e1
+usb.current	07961ac7c0ee8b546658717034fe692fd12eefa9
+staging.current	07961ac7c0ee8b546658717034fe692fd12eefa9
+char-misc.current	6d4f0139d642c45411a47879325891ce2a7c164a
+input-current	4b7d293c64fde133cc2b669d0d7637b8a4c6d62f
+md-current	238f5908bd48f9e2f4668e0289e88cba969d710c
+audit-current	c158a35c8a681cf68d36f22f058f9f5466386c71
+crypto-current	d3dde52209ab571e4e2ec26c66f85ad1355f7475
+ide		bf6b4388c61cf88c6faa19cc45390fd36be8fb66
+dwmw2		63662139e519ce06090b2759cf4a1d291b9cc0e2
+sh-current	44033109e99cf584d6285226ed521098f5ef7250
+irqdomain-current	a0d271cbfed1dd50278c6b06bead3d00ba0a88f9
+devicetree-current	ab28698d33af05abab0bcf8021eafe38f7434f24
+spi-current	d3601e56cf64a3f2df6f6380cccb3644274406e2
+gpio-current	e97f9b5277afeabb54892ebc6f68500098467ba1
+rr-fixes	9ba5c80b1aea8648a3efe5f22dc1f7cacdfbeeb8
+mfd-fixes	037154105e3767324db7c34bf8f540a12cb61d70
+vfio-fixes	904c680c7bf016a8619a045850937427f8d7368c
+asm-generic	fb9de7ebc3a2eb7ddb83c92e288447a0c313bced
+arc		3917dbf861c8f9d727e22db71793e53bfb315e26
+arm		8e65f7865abefd1c5374b2695ca4674a2e980ae0
+arm-perf	a937536b868b8369b98967929045f1df54234323
+davinci		fe0d42203cb5616eeff68b14576a0f7e2dd56625
+xilinx		64e3fd3c96fe3416879c8ea985e606f80a28dea5
+arm64		d4784be3b20ed0dd19bbde3b2d58df023ae1dc86
+blackfin	f656c240ae07c48ddf8552e83b64692121044c42
+c6x		93bbd0c087eb299e0fe11c59d340932180c082b5
+cris		ae0b1055b612c8a910342f1b147e3ecc687720f6
+hexagon		411d53d55792caf2ca6e6fd59442904f43ab102a
+ia64		797f6a684f28dbb00f9e9719315574e344fcbf53
+m68k		561839598e61f03c9175183ea066b2b7fa58ce85
+m68knommu	b46ab88da333642ab0da7f2fd0ac968876adbc9d
+metag		82bbb8325a232e29e1c2ae09200384ddb989c0d5
+microblaze	01cc2cb1c9ee0eb0b813cc3a4404220d11160493
+mips		306d20eb3162dc437cdb291e217b41db26dccc4e
+openrisc	6af609515d788bd4c94116344f00601b058f75a6
+parisc		6c700d71f7faecb540b3fa4303edb5323a2768c1
+powerpc		9e2d59ad580d590134285f361a0e80f0e98c0207
+4xx		2074b1d9d53ae696dd3f49482bad43254f40f01d
+mpc5xxx		b9e7196ecdf6d7cd7a41b560e596c9af94413c05
+galak		ddb487dca347956ed3bedda1f5a00ab62d05ebff
+s390		875ea53d3311ff05088f23c832bd1547ce549070
+sh		37284bd93103ae36b5ea274a985d688fb16f7a38
+sparc-next	d6d88bae97d2e1c44ef9e2ae3f22de82fa6e11c5
+tile		39e8202bb3b83a826e5825b1a07bbbf30ae9a140
+unicore32	c284464658acab50c67ff65ff3dc9215a0231ad2
+xtensa		4e34bf689fa23122f3d90bf0f92e6239e4b1d9e0
+btrfs		6aec51f7d1db54c0e4c36f051dc77b52edadda85
+ceph		6e2a4505dba0cae8faa701426185dfb7b49f537c
+cifs		bf0fce1e010131c64fb912fc17bc250ae29917b5
+configfs	b930c26416c4ea6855726fd977145ccea9afbdda
+ecryptfs	f6161aa153581da4a3867a2d1a7caf4be19b6ec9
+ext3		e678a4f0f50d4fa4f7aaa6de8eb3f071513356a0
+ext4		f78ee70db40040e6f38a5134527d4760254d6683
+f2fs		9078af8f2b6056d070afe6075d01a1a56e08338d
+fuse		634734b63ac39e137a1c623ba74f3e062b6577db
+gfs2		19875660d8c2b40dce0fc7c2695b857f3c655add
+jfs		9d48017bce890b19e3bba649850bdbc8a6f95903
+logfs		339466142b3f58fe0ee4dea7e8c5f3d33099e89c
+nfs		95883eb1d299f43241de4058dbe2f149940094bc
+nfsd		a7823c797b4d29727499f0a75ddf3ed07af8ad0a
+ocfs2		4538df64655dcfe17b33080b219dc783161a262e
+omfs		976d167615b64e14bc1491ca51d424e2ba9a5e84
+squashfs	4b0180a49f08dd1c681cdc99edc9e0cec0a833fa
+v9fs		b6f4bee02f682d1c86ece297871b78ae01afaaf4
+ubifs		67e753ca41782913d805ff4a8a2b0f60b26b7915
+xfs		ff9a28f6c25d18a635abcab1f49db68108203dfb
+vfs		0f647aca294e83d26ee0ed9d7e48b2f2bc56b70e
+pci		833260631178aa26c70a0b05eabc953f5e47167d
+hid		bf79571a0c6e8c2de52907a07a2e57e4311c22b0
+i2c		51d95709dddf7fdf6769a547de37a9c98edf8df9
+jdelvare-hwmon	c662b7afe9c164955bad44706e642c720d62f994
+hwmon-staging	17b66094368ab04e8afdf5cc4154726c7ccd8525
+v4l-dvb		7307913f936323f3e119e929125a70c340833a10
+kbuild		d1fc91690da5a31425c8bafa594dd080980b9630
+kconfig		4eae518d4b01b0cbf2f0d8edb5a6f3d6245ee8fb
+libata		7551c40d908b2f6c08eb13571be1f9cfd7228689
+infiniband	4e73a54f95d1aff66cece06e5e40641094993996
+pstore		bd08ec33b5c23833581e5a36b2a69ccae6b39a28
+pm		33da2f70a63a09a8d23664238497db659cff2f85
+idle		e6bfd82e54f36553d177cec1bce4ad1e73ce5967
+apm		fb9d78aca709b7a6389c79d6211fb384c69bb79f
+cpuidle		817c876374a090391e7f2873a8b6076537f42253
+cpupowerutils	f16603386b38c28979f4df1cafdc2fe73fa87d37
+thermal		2fd1db8819fbf73b5f74b4b4a205ab7be0957944
+ieee1394	6dbe51c251a327e012439c4772097a13df43c5b8
+ubi		f6161aa153581da4a3867a2d1a7caf4be19b6ec9
+dlm		f11722834605a155022a8098ad7d8adacf44b22f
+swiotlb		af51a9f1848ff50079a10def56a2c064f326af22
+scsi		6dbe51c251a327e012439c4772097a13df43c5b8
+target-updates	aa010cb782e3a2bac8dbbd6c196da09c30019979
+target-merge	a937536b868b8369b98967929045f1df54234323
+ibft		935a9fee51c945b8942be2d7b4bae069167b4886
+isci		6734092e66011def7875bd67beef889d0fee1cc9
+slave-dma	a2a1a6d9ce7e3c70972ed7d070efc2f3c03d3ac3
+dmaengine	7f3498666c7b44f979720404d9ba883c309e60ad
+net-next	19952cc4f8f572493293a8caed27c4be89c5fc9d
+ipsec-next	05600a799f6c67b139f2bc565e358b913b230cf5
+wireless-next	84bcc0c3c4b8ca4c0abed2d2dd63b7ce04f8be0e
+bluetooth	5afff03815e26abf34702ec10422535224cdfe38
+mtd		35f8c769aa5f3d9a81d50e9bdcbfd4151e72a0c9
+l2-mtd		f6da0c30828f91625384ca69e8b4f8a4eee52f63
+crypto		30975d22b8f8b1cb1721ce617e56494d1c4ce621
+drm		be88298b0a3f771a4802f20c5e66af74bfd1dff1
+drm-intel	ea0dc8ca925786fc3d40aca7d8e9d55eee68746f
+sound		1dc669fed61a4ec4270a89e5fb3535802cc45668
+sound-asoc	5c0f5550320cc2b27b081b463ef39cee7bbd3f39
+modules		d70f82acf32affa78ae4957caa0fb2a550d2c6ea
+virtio		1aef76e9c4c616c91233ece9850e89c91f3fd92a
+input		3c2b901003b4c152e19e6578c1705ce2c90edd4a
+input-mt	043ac7362956bce69aace43c5c996cbf550faa02
+cgroup		081aa458c38ba576bdd4265fc807fa95b48b9e79
+block		fbf8bf240f7851408fbbde1a011be746e2a80353
+device-mapper	c9bfbecd7999d9c448ccb8ba00dd70065c304dd1
+embedded	4744b43431e8613f920c5cba88346756f53c5165
+firmware	6e03a201bbe8137487f340d26aa662110e324b20
+pcmcia		80af9e6d7ae633309cc5bca96aee6a45117e7c98
+mmc		8e1c4e4d732666ace4c5e0cd122e7217ded910aa
+kgdb		6bedf31c25dd93c4f70a28e9ab94a239a5fb592c
+slab		338b2642290ef3193229ece8cfc776ac4fe8869d
+uclinux		6dbe51c251a327e012439c4772097a13df43c5b8
+md		023a4ef1fc49d060ab6f5e69146e56ef885375dc
+mfd		e8ea76bb8f63cff7534f2748fd4d42efce618fb5
+battery		a92d4c7d02d0af85b0edbf1d3c12b9e09bf1846d
+fbdev		a49f0d1ea3ec94fc7cf33a7c36a16343b74bd565
+viafb		838ac785d521e091bd8b5f6a2b545166f5f32b77
+omap_dss2	5955e3b177dce8a502d6f0abdadfef2383bf9f28
+regulator	c9215401cbdcd2d5f93ffa1b544485c7dbbae56a
+security	958d2c2f4ad905e3ffa1711d19184d21d9b00cc1
+selinux		c2d7b247f0c028d325a5da5b9611b60ba160f237
+lblnet		7e27d6e778cd87b6f2415515d7127eba53fe5d02
+watchdog	112b55a999f44cad763cde2d72138168bb1d4b72
+dwmw2-iommu	6491d4d02893d9787ba67279595990217177b351
+iommu		fbe973eb5b3ec06167bb5d86cfe8299c0c1eb56f
+vfio		a7d1ea1c11b33bda2691f3294b4d735ed635535a
+osd		861d66601acda6d7a2038fb3c95f68009128003a
+jc_docs		5c050fb96380a87a85aad9084b68fdcd2b84c193
+trivial		1051e9b33bbf550be52bdd674b519f3dc99f0dd9
+audit		dcd6c92267155e70a94b3927bce681ce74b80d1f
+fsnotify	1ca39ab9d21ac93f94b9e3eb364ea9a5cf2aba06
+edac		b0769891ba7baa53f270dc70d71934748beb4c5b
+edac-amd	9713faecff3d071de1208b081d4943b002e9cb1c
+devicetree	02bbde7849e68e193cefaa1885fe0df0f03c9fcd
+dt-rh		1421954bf9b967d819db23c911f950a2ccd60eff
+spi		095c3752e673c0ba039a2f67fd867297fde75ae7
+spi-mb		58ad60bbb2abada33fbeae88943ab038e2fcc0ef
+tip		a2d66a370b34e6937961e6ae7fdf553bed40837a
+ftrace		22f45649ce08642ad7df238d5c25fa5c86bfdd31
+rcu		6d87669357936bffa1e8fea7a4e7743e76905736
+cputime		c3e0ef9a298e028a82ada28101ccd5cf64d209ee
+uprobes		0326f5a94ddea33fa331b2519f4172f4fb387baa
+kvm		81f4f76bbc712a2dff8bb020057c554e285370e1
+kvm-ppc		fbfba342a719b49d9cd0837202cf5365ba46ca9b
+oprofile	44009105081b51417f311f4c3be0061870b6b8ed
+fw-nohz		74876a98a87a115254b3a66a14b27320b7f0acaa
+xen		af3a3ab2966112c0d0a44df7eeb1e95fe32d4495
+xen-two		562eb8e39e3f872588824bc36bd972480f72ad02
+xen-pvhvm	b056b6a0144de90707cd22cf7b4f60bf69c86d59
+percpu		a1b2a555d6375f1ed34d0a1761b540de3a8727c6
+workqueues	24c288b49077731def178796c1973b4a9d872dc1
+drivers-x86	e6e522461d358891050522ddb4fbfe9c253947b4
+hwpoison	46e387bbd82d438b9131e237e6e2cb55a825da49
+sysctl		4e474a00d7ff746ed177ddae14fa8b2d4bad7a00
+regmap		833d040693daa9347b3668badd0e14a9cc01e75e
+hsi		43139a61fc68f4b0af7327a0e63f340a7c81c69a
+leds		df92d5ff5e70999274f53884cc2c40ae620a109a
+driver-core	bcfb87fb75fa3a9b96c8a73d19166897d167fe3f
+tty		89fa28dbe0395ee06f3aacfe27655323ebad43d1
+usb		369a9a9d2af702bac3ccd2ade86ddcb2594eb3b1
+usb-gadget	9b192de60b5a584ee4ed967fb6758773c75e4643
+staging		e9e7023c992103f71bfd4f02eeae44879bb2175d
+char-misc	2638953fcd6eeea27b4975c1cdd5e62e32758f8f
+bcon		06c6942645eb82a7f69ed0759e23b272c253cd3c
+tmem		8f0d8163b50e01f398b14bcd4dc039ac5ab18d64
+writeback	ed84825b785ceb932af7dd5aa08614801721320b
+arm-dt		ede338f4ce2fb5ee99d18751df32fbd3b10df268
+hwspinlock	8b37fcfc9b3400b647748783a2cafff67793e0ad
+pinctrl		bdbe59f3120c899a9eacc8288162283c189cd4fd
+vhost		4697e2cddfe6960fd951c5c80b9ddf4043af2198
+memblock	7bd0b0f0da3b1ec11cbcc798eb0ef747a1184077
+remoteproc	6f0c0580b70c89094b3422ba81118c7b959c7556
+irqdomain	560aa5394d2db5437b2deb3bb897655f0fd99f61
+gpio		753c5983ddd38022a680a36f5d66b23b185c9b62
+gpio-lw		290722b03ac032b4369fea4e6280511ebb8c8ec7
+gen-gpio	a2523d3cdab76fbda28414fd82743815f3cc3df7
+mailbox		c497eba5247728c67ba0e0de0907723dd114134a
+arm-soc		0be783decaa100d35829ca731617369eb6130d41
+bcm2835		d1a77074f97841544f64e56d45102b14f4bc3e37
+cortex		6ebd4d038dbb626a43d87db3007e71f92f49d7b3
+ep93xx		7ec44295ef66efcac08433298661a18008883885
+imx-mxs		21f4fc447ec25b758413c6fbed422d5404915f49
+ixp4xx		19f949f52599ba7c3f67a5897ac6be14bfcb1200
+msm		d0f6e5096b0a29a64443524d1a89a0871a95e918
+renesas		88105d4adcce13cadad3d28cf3de09423a3344db
+samsung		9cc97cecd06d3a23f6b6080b13138a92a99677ea
+tegra		fe98dc2d8f75d0f6153edc5d612b485c3e260004
+dma-mapping	a937536b868b8369b98967929045f1df54234323
+pwm		a46ef4d5723aca785e6b03b7972dd83e43e73977
+dma-buf		6dbe51c251a327e012439c4772097a13df43c5b8
+userns		78008c404acd8e731d1e06618cc5995961e847a6
+ktest		7328735cbf68b7cd4d7ef16e172013743cdc2bc4
+signal		99e621f796d7f0341a51e8cdf32b81663b10b448
+clk		918d7f6f68620e0721bb31402ebf87e15f826831
+random		b980955236922ae6106774511c5c05003d3ad225
+lzo-update	42b775abafafdf811ef300e869a4e1480ef1cf95
+scsi-post-merge	65112dccf8a113737684366349d7f9ec373ddc47
+akpm-current	a12183c62717ac4579319189a00f5883a18dff08
+akpm		0641ec487d4d4e2b759b2e8625434567b12324cd
diff --git a/Next/Trees b/Next/Trees
new file mode 100644
index 0000000..17f933f
--- /dev/null
+++ b/Next/Trees
@@ -0,0 +1,226 @@
+Trees included into this release:
+
+Name		Type	URL
+----		----	---
+origin		git	git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git#master
+fixes		git	git://git.kernel.org/pub/scm/linux/kernel/git/sfr/next-fixes.git#master
+kbuild-current	git	git://git.kernel.org/pub/scm/linux/kernel/git/mmarek/kbuild.git#rc-fixes
+arc-current	git	git://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc.git#for-curr
+arm-current	git	git://ftp.arm.linux.org.uk/pub/linux/arm/kernel/git-cur/linux-arm.git#fixes
+m68k-current	git	git://git.kernel.org/pub/scm/linux/kernel/git/geert/linux-m68k.git#for-linus
+powerpc-merge	git	git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc.git#merge
+sparc		git	git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc.git#master
+net		git	git://git.kernel.org/pub/scm/linux/kernel/git/davem/net.git#master
+ipsec		git	git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec.git#master
+sound-current	git	git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git#for-linus
+pci-current	git	git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git#for-linus
+wireless	git	git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless.git#master
+driver-core.current	git	git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core.git#driver-core-linus
+tty.current	git	git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git#tty-linus
+usb.current	git	git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git#usb-linus
+staging.current	git	git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git#staging-linus
+char-misc.current	git	git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git#char-misc-linus
+input-current	git	git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git#for-linus
+md-current	git	git://neil.brown.name/md#for-linus
+audit-current	git	git://git.kernel.org/pub/scm/linux/kernel/git/viro/audit.git#for-linus
+crypto-current	git	git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6.git#master
+ide		git	git://git.kernel.org/pub/scm/linux/kernel/git/davem/ide.git#master
+dwmw2		git	git://git.infradead.org/users/dwmw2/random-2.6.git#master
+sh-current	git	git://github.com/pmundt/linux-sh.git#sh-fixes-for-linus
+irqdomain-current	git	git://git.secretlab.ca/git/linux-2.6.git#irqdomain/merge
+devicetree-current	git	git://git.secretlab.ca/git/linux-2.6#devicetree/merge
+spi-current	git	git://git.secretlab.ca/git/linux-2.6#spi/merge
+gpio-current	git	git://git.secretlab.ca/git/linux-2.6#gpio/merge
+rr-fixes	git	git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux.git#fixes
+mfd-fixes	git	git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-fixes.git#master
+vfio-fixes	git	git://github.com/awilliam/linux-vfio.git#for-linus
+asm-generic	git	git://git.kernel.org/pub/scm/linux/kernel/git/arnd/asm-generic.git#master
+arc		git	git://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc.git#for-next
+arm		git	git://ftp.arm.linux.org.uk/pub/linux/arm/kernel/git-cur/linux-arm.git#for-next
+arm-perf	git	git://git.kernel.org/pub/scm/linux/kernel/git/will/linux.git#for-next/perf
+davinci		git	git://gitorious.org/linux-davinci/linux-davinci.git#davinci-next
+xilinx		git	git://git.xilinx.com/linux-xlnx.git#arm-next
+arm64		git	git://git.kernel.org/pub/scm/linux/kernel/git/cmarinas/linux-aarch64.git#upstream
+blackfin	git	git://git.kernel.org/pub/scm/linux/kernel/git/lliubbo/blackfin.git#for-linus
+c6x		git	git://linux-c6x.org/git/projects/linux-c6x-upstreaming.git#for-linux-next
+cris		git	git://www.jni.nu/cris.git#for-next
+hexagon		git	git://git.kernel.org/pub/scm/linux/kernel/git/rkuo/linux-hexagon-kernel.git#linux-next
+ia64		git	git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux.git#next
+m68k		git	git://git.kernel.org/pub/scm/linux/kernel/git/geert/linux-m68k.git#for-next
+m68knommu	git	git://git.kernel.org/pub/scm/linux/kernel/git/gerg/m68knommu.git#for-next
+metag		git	git://git.kernel.org/pub/scm/linux/kernel/git/jhogan/metag.git#for-next
+microblaze	git	git://git.monstr.eu/linux-2.6-microblaze.git#next
+mips		git	git://git.linux-mips.org/pub/scm/ralf/upstream-sfr.git#mips-for-linux-next
+openrisc	git	git://openrisc.net/jonas/linux#for-upstream
+parisc		git	git://git.kernel.org/pub/scm/linux/kernel/git/jejb/parisc-2.6.git#for-next
+powerpc		git	git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc.git#next
+4xx		git	git://git.kernel.org/pub/scm/linux/kernel/git/jwboyer/powerpc-4xx.git#next
+mpc5xxx		git	git://git.denx.de/linux-2.6-agust.git#next
+galak		git	git://git.kernel.org/pub/scm/linux/kernel/git/galak/powerpc.git#next
+s390		git	git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux.git#features
+sh		git	git://github.com/pmundt/linux-sh.git#sh-latest
+sparc-next	git	git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-next.git#master
+tile		git	git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux-tile.git#master
+unicore32	git	git://github.com/gxt/linux.git#unicore32
+xtensa		git	git://github.com/czankel/xtensa-linux.git#for_next
+btrfs		git	git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs.git#next
+ceph		git	git://github.com/ceph/ceph-client.git#master
+cifs		git	git://git.samba.org/sfrench/cifs-2.6.git#for-next
+configfs	git	git://git.kernel.org/pub/scm/linux/kernel/git/jlbec/configfs.git#linux-next
+ecryptfs	git	git://git.kernel.org/pub/scm/linux/kernel/git/tyhicks/ecryptfs.git#next
+ext3		git	git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs.git#for_next
+ext4		git	git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4.git#dev
+f2fs		git	git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs.git#dev
+fuse		git	git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse.git#for-next
+gfs2		git	git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-3.0-nmw.git#master
+jfs		git	git://github.com/kleikamp/linux-shaggy.git#jfs-next
+logfs		git	git://github.com/prasad-joshi/logfs_upstream.git#master
+nfs		git	git://git.linux-nfs.org/projects/trondmy/nfs-2.6.git#linux-next
+nfsd		git	git://git.linux-nfs.org/~bfields/linux.git#nfsd-next
+ocfs2		git	git://git.kernel.org/pub/scm/linux/kernel/git/jlbec/ocfs2.git#linux-next
+omfs		git	git://github.com/bcopeland/omfs.git#for-next
+squashfs	git	git://git.kernel.org/pub/scm/linux/kernel/git/pkl/squashfs-next.git#master
+v9fs		git	git://git.kernel.org/pub/scm/linux/kernel/git/ericvh/v9fs.git#for-next
+ubifs		git	git://git.infradead.org/ubifs-2.6.git#linux-next
+xfs		git	git://oss.sgi.com/xfs/xfs.git#for-next
+vfs		git	git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6.git#for-next
+pci		git	git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git#next
+hid		git	git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid.git#for-next
+i2c		git	git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux.git#i2c/for-next
+jdelvare-hwmon	quilt	http://khali.linux-fr.org/devel/linux-3/jdelvare-hwmon/
+hwmon-staging	git	git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging.git#hwmon-next
+v4l-dvb		git	git://linuxtv.org/mchehab/media-next.git#master
+kbuild		git	git://git.kernel.org/pub/scm/linux/kernel/git/mmarek/kbuild.git#for-next
+kconfig		git	git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-kconfig.git#for-next
+libata		git	git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev.git#NEXT
+infiniband	git	git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband.git#for-next
+pstore		git	git://git.infradead.org/users/cbou/linux-pstore.git#master
+pm		git	git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git#linux-next
+idle		git	git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux.git#next
+apm		git	git://git.kernel.org/pub/scm/linux/kernel/git/jikos/apm.git#for-next
+cpuidle		git	git://git.linaro.org/people/dlezcano/cpuidle-next.git#cpuidle-next
+cpupowerutils	git	git://git.kernel.org/pub/scm/linux/kernel/git/brodo/cpupowerutils.git#master
+thermal		git	git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux.git#next
+ieee1394	git	git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394.git#for-next
+ubi		git	git://git.infradead.org/ubi-2.6.git#linux-next
+dlm		git	git://git.kernel.org/pub/scm/linux/kernel/git/teigland/linux-dlm.git#next
+swiotlb		git	git://git.kernel.org/pub/scm/linux/kernel/git/konrad/swiotlb.git#linux-next
+scsi		git	git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git#for-next
+target-updates	git	git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending.git#for-next
+target-merge	git	git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending.git#for-next-merge
+ibft		git	git://git.kernel.org/pub/scm/linux/kernel/git/konrad/ibft.git#linux-next
+isci		git	git://git.kernel.org/pub/scm/linux/kernel/git/djbw/isci.git#all
+slave-dma	git	git://git.infradead.org/users/vkoul/slave-dma.git#next
+dmaengine	git	git://git.kernel.org/pub/scm/linux/kernel/git/djbw/dmaengine.git#next
+net-next	git	git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git#master
+ipsec-next	git	git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec-next.git#master
+wireless-next	git	git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next.git#master
+bluetooth	git	git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git#master
+mtd		git	git://git.infradead.org/mtd-2.6.git#master
+l2-mtd		git	git://git.infradead.org/users/dedekind/l2-mtd-2.6.git#master
+crypto		git	git://git.kernel.org/pub/scm/linux/kernel/git/herbert/cryptodev-2.6.git#master
+drm		git	git://people.freedesktop.org/~airlied/linux.git#drm-next
+drm-intel	git	git://people.freedesktop.org/~danvet/drm-intel#drm-intel-next-queued
+sound		git	git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git#for-next
+sound-asoc	git	git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git#for-next
+modules		git	git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux.git#modules-next
+virtio		git	git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux.git#virtio-next
+input		git	git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git#next
+input-mt	git	git://github.com/rydberg/linux.git#for-next
+cgroup		git	git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup.git#for-next
+block		git	git://git.kernel.dk/linux-block.git#for-next
+device-mapper	quilt	http://people.redhat.com/agk/patches/linux/editing/
+embedded	git	git://git.infradead.org/embedded-2.6.git#master
+firmware	git	git://git.infradead.org/users/dwmw2/firmware-2.6.git#master
+pcmcia		git	git://git.kernel.org/pub/scm/linux/kernel/git/brodo/pcmcia.git#master
+mmc		git	git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc.git#mmc-next
+kgdb		git	git://git.kernel.org/pub/scm/linux/kernel/git/jwessel/kgdb.git#kgdb-next
+slab		git	git://github.com/penberg/linux.git#for-next
+uclinux		git	git://git.kernel.org/pub/scm/linux/kernel/git/gerg/uclinux.git#for-next
+md		git	git://neil.brown.name/md#for-next
+mfd		git	git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-next.git#master
+battery		git	git://git.infradead.org/battery-2.6.git#master
+fbdev		git	git://github.com/schandinat/linux-2.6.git#fbdev-next
+viafb		git	git://github.com/schandinat/linux-2.6.git#viafb-next
+omap_dss2	git	git://gitorious.org/linux-omap-dss2/linux.git#for-next
+regulator	git	git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator.git#for-next
+security	git	git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security.git#next
+selinux		git	git://git.infradead.org/users/eparis/selinux.git#master
+lblnet		git	git://git.infradead.org/users/pcmoore/lblnet-2.6_next#master
+watchdog	git	git://www.linux-watchdog.org/linux-watchdog-next.git#master
+dwmw2-iommu	git	git://git.infradead.org/iommu-2.6.git#master
+iommu		git	git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git#next
+vfio		git	git://github.com/awilliam/linux-vfio.git#next
+osd		git	git://git.open-osd.org/linux-open-osd.git#linux-next
+jc_docs		git	git://git.lwn.net/linux-2.6.git#docs-next
+trivial		git	git://git.kernel.org/pub/scm/linux/kernel/git/jikos/trivial.git#for-next
+audit		git	git://git.kernel.org/pub/scm/linux/kernel/git/viro/audit.git#for-next
+fsnotify	git	git://git.infradead.org/users/eparis/notify.git#for-next
+edac		git	git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-edac.git#linux_next
+edac-amd	git	git://git.kernel.org/pub/scm/linux/kernel/git/bp/bp.git#for-next
+devicetree	git	git://git.secretlab.ca/git/linux-2.6#devicetree/next
+dt-rh		git	git://sources.calxeda.com/kernel/linux.git#for-next
+spi		git	git://git.secretlab.ca/git/linux-2.6#spi/next
+spi-mb		git	git://git.kernel.org/pub/scm/linux/kernel/git/broonie/misc.git#spi-next
+tip		git	git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git#auto-latest
+ftrace		git	git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace.git#for-next
+rcu		git	git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu.git#rcu/next
+cputime		git	git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux.git#cputime
+uprobes		git	git://github.com/srikard/linux.git#for-next
+kvm		git	git://git.kernel.org/pub/scm/virt/kvm/kvm.git#linux-next
+kvm-ppc		git	git://github.com/agraf/linux-2.6.git#kvm-ppc-next
+oprofile	git	git://git.kernel.org/pub/scm/linux/kernel/git/rric/oprofile.git#for-next
+fw-nohz		git	git://git.kernel.org/pub/scm/linux/kernel/git/frederic/linux-dynticks.git#nohz/next
+xen		git	git://git.kernel.org/pub/scm/linux/kernel/git/jeremy/xen.git#upstream/xen
+xen-two		git	git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen.git#linux-next
+xen-pvhvm	git	git://xenbits.xen.org/people/sstabellini/linux-pvhvm.git#linux-next
+percpu		git	git://git.kernel.org/pub/scm/linux/kernel/git/tj/percpu.git#for-next
+workqueues	git	git://git.kernel.org/pub/scm/linux/kernel/git/tj/wq.git#for-next
+drivers-x86	git	git://cavan.codon.org.uk/platform-drivers-x86.git#linux-next
+hwpoison	git	git://git.kernel.org/pub/scm/linux/kernel/git/ak/linux-mce-2.6.git#hwpoison
+sysctl		git	git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/sysctl.git#master
+regmap		git	git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap.git#for-next
+hsi		git	git://gitorious.org/kernel-hsi/kernel-hsi.git#for-next
+leds		git	git://git.kernel.org/pub/scm/linux/kernel/git/cooloney/linux-leds.git#for-next
+driver-core	git	git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core.git#driver-core-next
+tty		git	git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git#tty-next
+usb		git	git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git#usb-next
+usb-gadget	git	git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git#next
+staging		git	git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git#staging-next
+char-misc	git	git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git#char-misc-next
+bcon		git	git://git.kernel.org/pub/scm/linux/kernel/git/joern/bcon2.git#master
+tmem		git	git://git.kernel.org/pub/scm/linux/kernel/git/konrad/mm.git#linux-next
+writeback	git	git://git.kernel.org/pub/scm/linux/kernel/git/wfg/linux.git#writeback-for-next
+arm-dt		git	git://git.secretlab.ca/git/linux-2.6#devicetree/arm-next
+hwspinlock	git	git://github.com/ohadbc/hwspinlock-next.git#linux-next
+pinctrl		git	git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl.git#for-next
+vhost		git	git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost.git#linux-next
+memblock	git	git://git.kernel.org/pub/scm/linux/kernel/git/tj/misc.git#memblock-kill-early_node_map
+remoteproc	git	git://git.kernel.org/pub/scm/linux/kernel/git/ohad/remoteproc.git#for-next
+irqdomain	git	git://git.secretlab.ca/git/linux-2.6.git#irqdomain/next
+gpio		git	git://git.secretlab.ca/git/linux-2.6#gpio/next
+gpio-lw		git	git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio.git#for-next
+gen-gpio	git	git://github.com/Gnurou/linux.git#for_next
+mailbox		git	git://github.com/sumananna/mailbox.git#dbx500-prcmu-mailbox
+arm-soc		git	git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc.git#for-next
+bcm2835		git	git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-rpi.git#for-next
+cortex		git	git://git.pengutronix.de/git/ukl/linux-2.6.git#for-next
+ep93xx		git	git://github.com/RyanMallon/linux-ep93xx.git#ep93xx-for-next
+imx-mxs		git	git://git.linaro.org/people/shawnguo/linux-2.6.git#for-next
+ixp4xx		git	git://git.kernel.org/pub/scm/linux/kernel/git/chris/linux.git#next
+msm		git	git://git.kernel.org/pub/scm/linux/kernel/git/davidb/linux-msm.git#for-next
+renesas		git	git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git#next
+samsung		git	git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git#for-next
+tegra		git	git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-tegra.git#for-next
+dma-mapping	git	git://git.linaro.org/people/mszyprowski/linux-dma-mapping.git#dma-mapping-next
+pwm		git	git://gitorious.org/linux-pwm/linux-pwm.git#for-next
+dma-buf		git	git://git.linaro.org/people/sumitsemwal/linux-dma-buf.git#for-next
+userns		git	git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace.git#for-next
+ktest		git	git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-ktest.git#for-next
+signal		git	git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal.git#for-next
+clk		git	git://git.linaro.org/people/mturquette/linux.git#clk-next
+random		git	git://git.kernel.org/pub/scm/linux/kernel/git/tytso/random.git#dev
+lzo-update	git	git://github.com/markus-oberhumer/linux.git#lzo-update
+scsi-post-merge	git	git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-post-merge-2.6.git#master
+akpm-current	mmotm	http://www.ozlabs.org/~akpm/mmotm/
+akpm		mmotm	http://www.ozlabs.org/~akpm/mmotm/
diff --git a/Next/merge.log b/Next/merge.log
new file mode 100644
index 0000000..70bc82b
--- /dev/null
+++ b/Next/merge.log
@@ -0,0 +1,9912 @@
+$ date
+Friday 5 April  10:23:57 EST 2013
+$ git checkout master
+Already on 'master'
+$ git reset --hard stable
+HEAD is now at da241ef Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
+Merging origin/master (b6a9b7f mm: prevent mmap_cache race in find_vma())
+$ git merge origin/master
+Updating da241ef..b6a9b7f
+Fast-forward
+ arch/arm/Kconfig                   | 14 ++++++-
+ arch/arm/include/asm/delay.h       |  2 +-
+ arch/arm/include/asm/highmem.h     |  7 ++++
+ arch/arm/include/asm/mmu_context.h |  2 +
+ arch/arm/include/asm/tlbflush.h    | 15 +++++++
+ arch/arm/kernel/entry-common.S     | 12 ++++++
+ arch/arm/kernel/head.S             |  2 +-
+ arch/arm/kernel/hw_breakpoint.c    |  6 +--
+ arch/arm/kernel/setup.c            | 24 ++++++++++-
+ arch/arm/kernel/smp.c              |  3 --
+ arch/arm/kernel/smp_tlb.c          | 66 ++++++++++++++++++++++++++++++
+ arch/arm/kvm/vgic.c                | 35 +++++++---------
+ arch/arm/lib/delay.c               |  8 ++--
+ arch/arm/mm/cache-l2x0.c           | 11 ++---
+ arch/arm/mm/context.c              |  3 +-
+ arch/arm/mm/mmu.c                  | 73 +++++++++++++++++++++------------
+ arch/arm/mm/proc-v7.S              | 19 ++++++++-
+ arch/s390/include/asm/pgtable.h    |  4 +-
+ arch/s390/lib/uaccess_pt.c         | 83 +++++++++++++++++++++++++-------------
+ drivers/dma/Kconfig                |  1 +
+ drivers/gpio/gpio-ich.c            |  2 +-
+ drivers/gpio/gpio-stmpe.c          | 15 +++++--
+ drivers/hid/hid-core.c             | 13 +++++-
+ drivers/hid/hid-ids.h              |  5 +--
+ drivers/hid/hid-magicmouse.c       | 29 ++++++++-----
+ drivers/media/platform/Kconfig     |  2 +-
+ drivers/media/radio/radio-ma901.c  | 11 +++++
+ drivers/s390/block/scm_blk.c       | 11 +++--
+ drivers/s390/block/scm_drv.c       |  2 +-
+ drivers/s390/char/tty3270.c        | 16 ++++----
+ drivers/spi/Kconfig                |  3 +-
+ fs/ext4/extents.c                  | 11 +++--
+ fs/ext4/indirect.c                 |  4 +-
+ fs/reiserfs/xattr.c                |  4 +-
+ fs/ubifs/super.c                   | 12 +++---
+ mm/mmap.c                          |  2 +-
+ mm/nommu.c                         |  2 +-
+ 37 files changed, 385 insertions(+), 149 deletions(-)
+Merging fixes/master (9064171 Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sfr/next-fixes)
+$ git merge fixes/master
+Already up-to-date.
+Merging kbuild-current/rc-fixes (6dbe51c Linux 3.9-rc1)
+$ git merge kbuild-current/rc-fixes
+Already up-to-date.
+Merging arc-current/for-curr (07961ac Linux 3.9-rc5)
+$ git merge arc-current/for-curr
+Already up-to-date.
+Merging arm-current/fixes (4e1db26 ARM: 7690/1: mm: fix CONFIG_LPAE typos)
+$ git merge arm-current/fixes
+Already up-to-date.
+Merging m68k-current/for-linus (5618395 m68k: Sort out !CONFIG_MMU_SUN3 vs. CONFIG_HAS_DMA)
+$ git merge m68k-current/for-linus
+Already up-to-date.
+Merging powerpc-merge/merge (af81d78 powerpc: Rename USER_ESID_BITS* to ESID_BITS*)
+$ git merge powerpc-merge/merge
+Already up-to-date.
+Merging sparc/master (cbf1ef6 sparc: use asm-generic version of types.h)
+$ git merge sparc/master
+Removing arch/sparc/include/uapi/asm/types.h
+Removing arch/sparc/include/asm/serial.h
+Removing arch/sparc/include/asm/mutex.h
+Removing arch/sparc/include/asm/emergency-restart.h
+Removing arch/sparc/include/asm/cputime.h
+Merge made by the 'recursive' strategy.
+ arch/sparc/include/asm/Kbuild              |  5 +++++
+ arch/sparc/include/asm/cputime.h           |  6 ------
+ arch/sparc/include/asm/emergency-restart.h |  6 ------
+ arch/sparc/include/asm/mutex.h             |  9 ---------
+ arch/sparc/include/asm/serial.h            |  6 ------
+ arch/sparc/include/asm/smp_32.h            |  5 -----
+ arch/sparc/include/uapi/asm/Kbuild         |  1 -
+ arch/sparc/include/uapi/asm/types.h        | 17 -----------------
+ arch/sparc/lib/bitext.c                    |  6 +-----
+ arch/sparc/mm/iommu.c                      |  2 +-
+ arch/sparc/mm/srmmu.c                      |  4 +++-
+ drivers/sbus/char/bbc_i2c.c                |  4 ++--
+ 12 files changed, 12 insertions(+), 59 deletions(-)
+ delete mode 100644 arch/sparc/include/asm/cputime.h
+ delete mode 100644 arch/sparc/include/asm/emergency-restart.h
+ delete mode 100644 arch/sparc/include/asm/mutex.h
+ delete mode 100644 arch/sparc/include/asm/serial.h
+ delete mode 100644 arch/sparc/include/uapi/asm/types.h
+Merging net/master (e2409d8 r8169: fix auto speed down issue)
+$ git merge net/master
+Merge made by the 'recursive' strategy.
+ drivers/net/ethernet/realtek/r8169.c    | 28 +++++++++++++++++++++---
+ drivers/net/wireless/iwlwifi/dvm/rxon.c | 18 +++++++---------
+ drivers/net/wireless/iwlwifi/dvm/tx.c   |  2 +-
+ drivers/net/wireless/mwifiex/cfg80211.c |  3 ++-
+ drivers/nfc/microread/mei.c             | 38 +++++++++++++++------------------
+ include/linux/skbuff.h                  |  3 +++
+ net/ipv6/netfilter/ip6t_NPT.c           |  2 +-
+ net/mac80211/cfg.c                      |  6 ++++--
+ net/mac80211/chan.c                     | 17 ++++++++++++---
+ net/mac80211/ieee80211_i.h              |  4 +++-
+ net/mac80211/iface.c                    |  2 +-
+ net/mac80211/offchannel.c               | 23 ++++++++++++++------
+ net/netfilter/nf_conntrack_standalone.c |  1 +
+ net/netfilter/nfnetlink_acct.c          |  2 ++
+ net/netfilter/nfnetlink_queue_core.c    |  4 +++-
+ net/nfc/llcp/llcp.c                     |  8 -------
+ net/nfc/llcp/sock.c                     |  6 +++---
+ 17 files changed, 105 insertions(+), 62 deletions(-)
+Merging ipsec/master (da241ef Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net)
+$ git merge ipsec/master
+Already up-to-date.
+Merging sound-current/for-linus (8fc2442 Revert "ALSA: hda - Allow power_save_controller option override DCAPS")
+$ git merge sound-current/for-linus
+Merge made by the 'recursive' strategy.
+ Documentation/sound/alsa/ALSA-Configuration.txt |  5 ++-
+ include/sound/max98090.h                        |  0
+ include/sound/soc-dapm.h                        |  1 +
+ sound/pci/hda/hda_codec.c                       |  2 +-
+ sound/pci/hda/hda_eld.c                         |  2 +-
+ sound/pci/hda/hda_intel.c                       |  6 ++--
+ sound/pci/hda/patch_hdmi.c                      |  2 +-
+ sound/pci/hda/patch_realtek.c                   |  4 ++-
+ sound/soc/codecs/max98090.c                     |  0
+ sound/soc/codecs/max98090.h                     |  0
+ sound/soc/codecs/si476x.c                       |  1 +
+ sound/soc/codecs/wm_adsp.c                      |  5 +--
+ sound/soc/fsl/imx-ssi.c                         |  5 +++
+ sound/soc/fsl/pcm030-audio-fabric.c             |  2 +-
+ sound/soc/sh/dma-sh7760.c                       |  4 +--
+ sound/soc/soc-core.c                            |  8 ++---
+ sound/soc/soc-dapm.c                            | 14 ++++++++
+ sound/soc/spear/spear_pcm.c                     | 12 +++----
+ sound/usb/clock.c                               | 45 +++++++++++++++++++------
+ 19 files changed, 82 insertions(+), 36 deletions(-)
+ mode change 100755 => 100644 include/sound/max98090.h
+ mode change 100755 => 100644 sound/soc/codecs/max98090.c
+ mode change 100755 => 100644 sound/soc/codecs/max98090.h
+Merging pci-current/for-linus (de7d5f7 PCI/PM: Disable runtime PM of PCIe ports)
+$ git merge pci-current/for-linus
+Auto-merging drivers/acpi/pci_root.c
+Merge made by the 'recursive' strategy.
+ drivers/acpi/pci_root.c                         | 76 ++++++++++++-------------
+ drivers/eisa/pci_eisa.c                         | 67 +++++++++++++++-------
+ drivers/gpu/drm/nouveau/core/subdev/bios/base.c | 17 ++++++
+ drivers/gpu/drm/radeon/radeon_bios.c            | 26 +++++++++
+ drivers/pci/pci-acpi.c                          | 15 ++---
+ drivers/pci/pci-driver.c                        |  5 +-
+ drivers/pci/pcie/portdrv_pci.c                  | 13 -----
+ drivers/pci/rom.c                               | 67 ++++++++++------------
+ include/linux/pci.h                             |  1 +
+ 9 files changed, 169 insertions(+), 118 deletions(-)
+Merging wireless/master (69a2bac rt2x00: rt2x00pci: fix build error on Ralink RT3x5x SoCs)
+$ git merge wireless/master
+Merge made by the 'recursive' strategy.
+ drivers/net/wireless/ath/ath9k/main.c              |   4 +
+ drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c |   6 +-
+ .../net/wireless/brcm80211/brcmfmac/wl_cfg80211.c  |  46 +++--
+ drivers/net/wireless/mwifiex/scan.c                |  11 +-
+ drivers/net/wireless/rt2x00/Kconfig                |   7 +
+ drivers/net/wireless/rt2x00/Makefile               |   1 +
+ drivers/net/wireless/rt2x00/rt2400pci.c            |   1 +
+ drivers/net/wireless/rt2x00/rt2500pci.c            |   1 +
+ drivers/net/wireless/rt2x00/rt2800pci.c            |   1 +
+ drivers/net/wireless/rt2x00/rt2x00mmio.c           | 216 +++++++++++++++++++++
+ drivers/net/wireless/rt2x00/rt2x00mmio.h           | 119 ++++++++++++
+ drivers/net/wireless/rt2x00/rt2x00pci.c            | 176 -----------------
+ drivers/net/wireless/rt2x00/rt2x00pci.h            |  88 ---------
+ drivers/net/wireless/rt2x00/rt61pci.c              |   1 +
+ net/wireless/sme.c                                 |   2 +
+ 15 files changed, 390 insertions(+), 290 deletions(-)
+ create mode 100644 drivers/net/wireless/rt2x00/rt2x00mmio.c
+ create mode 100644 drivers/net/wireless/rt2x00/rt2x00mmio.h
+Merging driver-core.current/driver-core-linus (07961ac Linux 3.9-rc5)
+$ git merge driver-core.current/driver-core-linus
+Already up-to-date.
+Merging tty.current/tty-linus (1f66396 OMAP/serial: Revert bad fix of Rx FIFO threshold granularity)
+$ git merge tty.current/tty-linus
+Merge made by the 'recursive' strategy.
+ Documentation/DocBook/device-drivers.tmpl |  2 +-
+ drivers/tty/serial/omap-serial.c          | 11 +++++++++++
+ 2 files changed, 12 insertions(+), 1 deletion(-)
+Merging usb.current/usb-linus (07961ac Linux 3.9-rc5)
+$ git merge usb.current/usb-linus
+Already up-to-date.
+Merging staging.current/staging-linus (07961ac Linux 3.9-rc5)
+$ git merge staging.current/staging-linus
+Already up-to-date.
+Merging char-misc.current/char-misc-linus (6d4f013 misc/vmw_vmci: Add dependency on CONFIG_NET)
+$ git merge char-misc.current/char-misc-linus
+Merge made by the 'recursive' strategy.
+ drivers/misc/vmw_vmci/Kconfig | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+Merging input-current/for-linus (4b7d293 Input: mms114 - Fix regulator enable and disable paths)
+$ git merge input-current/for-linus
+Already up-to-date.
+Merging md-current/for-linus (238f590 md: remove CONFIG_MULTICORE_RAID456 entirely)
+$ git merge md-current/for-linus
+Already up-to-date.
+Merging audit-current/for-linus (c158a35 audit: no leading space in audit_log_d_path prefix)
+$ git merge audit-current/for-linus
+Already up-to-date.
+Merging crypto-current/master (d3dde52 crypto: gcm - fix assumption that assoc has one segment)
+$ git merge crypto-current/master
+Merge made by the 'recursive' strategy.
+ crypto/gcm.c | 17 ++++++++++++++---
+ 1 file changed, 14 insertions(+), 3 deletions(-)
+Merging ide/master (bf6b438 ide: gayle: use module_platform_driver_probe())
+$ git merge ide/master
+Merge made by the 'recursive' strategy.
+ drivers/ide/gayle.c     | 15 +--------------
+ drivers/ide/tx4938ide.c | 13 +------------
+ drivers/ide/tx4939ide.c | 13 +------------
+ 3 files changed, 3 insertions(+), 38 deletions(-)
+Merging dwmw2/master (63662139 params: Fix potential memory leak in add_sysfs_param())
+$ git merge dwmw2/master
+Merge made by the 'recursive' strategy.
+ drivers/platform/x86/dell-laptop.c | 10 ++++++----
+ kernel/params.c                    |  5 ++++-
+ 2 files changed, 10 insertions(+), 5 deletions(-)
+Merging sh-current/sh-fixes-for-linus (4403310 SH: Convert out[bwl] macros to inline functions)
+$ git merge sh-current/sh-fixes-for-linus
+Already up-to-date.
+Merging irqdomain-current/irqdomain/merge (a0d271c Linux 3.6)
+$ git merge irqdomain-current/irqdomain/merge
+Already up-to-date.
+Merging devicetree-current/devicetree/merge (ab28698 of: define struct device in of_platform.h if !OF_DEVICE and !OF_ADDRESS)
+$ git merge devicetree-current/devicetree/merge
+Already up-to-date.
+Merging spi-current/spi/merge (d3601e5 spi/sh-hspi: fix return value check in hspi_probe().)
+$ git merge spi-current/spi/merge
+Already up-to-date.
+Merging gpio-current/gpio/merge (e97f9b5 gpio/gpio-ich: fix ichx_gpio_check_available() return what callers expect)
+$ git merge gpio-current/gpio/merge
+Already up-to-date.
+Merging rr-fixes/fixes (9ba5c80 virtio: console: add locking around c_ovq operations)
+$ git merge rr-fixes/fixes
+Already up-to-date.
+Merging mfd-fixes/master (0371541 mfd: twl4030-madc: Remove __exit_p annotation)
+$ git merge mfd-fixes/master
+Already up-to-date.
+Merging vfio-fixes/for-linus (904c680 vfio-pci: Fix possible integer overflow)
+$ git merge vfio-fixes/for-linus
+Merge made by the 'recursive' strategy.
+ drivers/vfio/pci/vfio_pci.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+Merging asm-generic/master (fb9de7e xtensa: Use generic asm/mmu.h for nommu)
+$ git merge asm-generic/master
+Already up-to-date.
+Merging arc/for-next (3917dbf ARC: de-uglify the reg file dumping)
+$ git merge arc/for-next
+Merge made by the 'recursive' strategy.
+ arch/arc/Kconfig               | 10 ++++------
+ arch/arc/Makefile              | 14 ++++++++++----
+ arch/arc/boot/Makefile         | 19 ++++++++++++++-----
+ arch/arc/kernel/asm-offsets.c  |  2 +-
+ arch/arc/kernel/clk.c          |  2 +-
+ arch/arc/kernel/disasm.c       |  2 +-
+ arch/arc/kernel/irq.c          |  2 +-
+ arch/arc/kernel/kprobes.c      |  1 -
+ arch/arc/kernel/module.c       |  4 ++--
+ arch/arc/kernel/setup.c        |  3 +--
+ arch/arc/kernel/time.c         |  1 -
+ arch/arc/kernel/traps.c        |  6 +++---
+ arch/arc/kernel/troubleshoot.c |  6 +++++-
+ arch/arc/mm/extable.c          |  4 ++--
+ arch/arc/mm/fault.c            |  1 -
+ arch/arc/mm/init.c             |  3 ---
+ arch/arc/mm/ioremap.c          |  2 +-
+ arch/arc/mm/tlb.c              |  2 +-
+ 18 files changed, 47 insertions(+), 37 deletions(-)
+Merging arm/for-next (8e65f78 Merge branches 'devel-stable', 'entry', 'fixes', 'mach-types' and 'misc' into for-next)
+$ git merge arm/for-next
+Auto-merging arch/arm/mach-omap2/timer.c
+Auto-merging arch/arm/mach-omap2/omap_hwmod.c
+Merge made by the 'recursive' strategy.
+ arch/arm/Kconfig                         |   4 +-
+ arch/arm/Kconfig.debug                   |  11 +
+ arch/arm/boot/compressed/Makefile        |   3 +
+ arch/arm/boot/compressed/debug.S         |  12 +
+ arch/arm/boot/compressed/misc.c          |   8 +-
+ arch/arm/include/asm/atomic.h            |  24 +
+ arch/arm/include/asm/cp15.h              |  16 +-
+ arch/arm/include/asm/cputype.h           |  61 +-
+ arch/arm/include/asm/glue-df.h           |  20 +-
+ arch/arm/include/asm/kvm_arm.h           |   4 +
+ arch/arm/include/asm/kvm_asm.h           |   2 +-
+ arch/arm/include/asm/kvm_emulate.h       | 107 +++-
+ arch/arm/include/asm/kvm_host.h          |  42 +-
+ arch/arm/include/asm/kvm_mmu.h           |  67 +++
+ arch/arm/include/asm/kvm_vgic.h          |   1 -
+ arch/arm/include/asm/mach/pci.h          |  11 +
+ arch/arm/include/asm/thread_info.h       |   1 +
+ arch/arm/include/asm/tlbflush.h          |   2 +-
+ arch/arm/include/debug/uncompress.h      |   7 +
+ arch/arm/include/uapi/asm/kvm.h          |  12 +-
+ arch/arm/kernel/asm-offsets.c            |   8 +-
+ arch/arm/kernel/bios32.c                 |   6 +
+ arch/arm/kernel/entry-armv.S             |  59 +-
+ arch/arm/kernel/entry-common.S           |   8 +-
+ arch/arm/kernel/entry-header.S           |  66 +-
+ arch/arm/kernel/head-common.S            |   9 +-
+ arch/arm/kernel/head-nommu.S             |   8 +-
+ arch/arm/kernel/process.c                |  13 +-
+ arch/arm/kernel/return_address.c         |   5 +-
+ arch/arm/kernel/setup.c                  |   2 +-
+ arch/arm/kernel/smp_scu.c                |   2 +-
+ arch/arm/kvm/Makefile                    |   2 +-
+ arch/arm/kvm/arm.c                       | 194 +-----
+ arch/arm/kvm/coproc.c                    |  28 +-
+ arch/arm/kvm/coproc.h                    |   4 +-
+ arch/arm/kvm/emulate.c                   |  75 ++-
+ arch/arm/kvm/guest.c                     |  17 +
+ arch/arm/kvm/handle_exit.c               | 164 +++++
+ arch/arm/kvm/interrupts.S                |  13 +-
+ arch/arm/kvm/mmio.c                      |  46 +-
+ arch/arm/kvm/mmu.c                       | 184 +++---
+ arch/arm/kvm/vgic.c                      |   2 +-
+ arch/arm/mach-exynos/mach-nuri.c         |   2 +-
+ arch/arm/mach-imx/devices/devices.c      |   2 +-
+ arch/arm/mach-integrator/integrator_ap.c |   6 +-
+ arch/arm/mach-integrator/integrator_cp.c |   7 +-
+ arch/arm/mach-omap2/board-omap3beagle.c  |   2 +-
+ arch/arm/mach-omap2/clock.c              |   2 +-
+ arch/arm/mach-omap2/gpmc-onenand.c       |   4 +-
+ arch/arm/mach-omap2/gpmc.c               |   8 +-
+ arch/arm/mach-omap2/id.c                 |   4 +-
+ arch/arm/mach-omap2/omap-smp.c           |   2 +-
+ arch/arm/mach-omap2/omap_device.c        |  13 +-
+ arch/arm/mach-omap2/omap_hwmod.c         |   4 +-
+ arch/arm/mach-omap2/pm-debug.c           |   6 +-
+ arch/arm/mach-omap2/powerdomain.c        |   2 +-
+ arch/arm/mach-omap2/timer.c              |   2 +-
+ arch/arm/mach-tegra/board-harmony-pcie.c |   6 +-
+ arch/arm/mach-tegra/tegra2_emc.c         |   2 +-
+ arch/arm/mach-ux500/cpu.c                |   5 +-
+ arch/arm/mm/Kconfig                      |   9 +-
+ arch/arm/mm/alignment.c                  |   2 +
+ arch/arm/mm/mmu.c                        |  17 +
+ arch/arm/mm/proc-v6.S                    |   2 -
+ arch/arm/mm/proc-v7-2level.S             |   3 +-
+ arch/arm/mm/proc-v7-3level.S             |   3 +-
+ arch/arm/mm/proc-v7.S                    |   4 +-
+ arch/arm/plat-omap/dmtimer.c             |  12 +-
+ arch/arm/tools/mach-types                | 991 +++++++++++++------------------
+ 69 files changed, 1305 insertions(+), 1147 deletions(-)
+ create mode 100644 arch/arm/boot/compressed/debug.S
+ create mode 100644 arch/arm/include/debug/uncompress.h
+ create mode 100644 arch/arm/kvm/handle_exit.c
+Merging arm-perf/for-next/perf (a937536 Linux 3.9-rc3)
+$ git merge arm-perf/for-next/perf
+Already up-to-date.
+Merging davinci/davinci-next (fe0d422 Linux 3.0-rc6)
+$ git merge davinci/davinci-next
+Already up-to-date.
+Merging xilinx/arm-next (64e3fd3 arm: zynq: Add support for pmu)
+$ git merge xilinx/arm-next
+Removing arch/arm/mach-zynq/timer.c
+Auto-merging arch/arm/mach-omap2/timer.c
+Auto-merging arch/arm/Kconfig
+Merge made by the 'recursive' strategy.
+ .../bindings/timer/cadence,ttc-timer.txt           |  17 +
+ arch/arm/Kconfig                                   |   1 +
+ arch/arm/boot/dts/zynq-7000.dtsi                   |  59 +--
+ arch/arm/boot/dts/zynq-zc702.dts                   |  10 -
+ arch/arm/include/asm/smp_twd.h                     |   8 -
+ arch/arm/kernel/smp_twd.c                          |  17 +-
+ arch/arm/mach-highbank/highbank.c                  |   5 +-
+ arch/arm/mach-imx/mach-imx6q.c                     |   5 +-
+ arch/arm/mach-omap2/timer.c                        |   2 +-
+ arch/arm/mach-spear13xx/spear13xx.c                |   4 +-
+ arch/arm/mach-ux500/timer.c                        |   3 +-
+ arch/arm/mach-vexpress/v2m.c                       |   6 +-
+ arch/arm/mach-zynq/Kconfig                         |   2 +
+ arch/arm/mach-zynq/Makefile                        |   6 +-
+ arch/arm/mach-zynq/common.c                        |  68 ++--
+ arch/arm/mach-zynq/common.h                        |  20 +-
+ arch/arm/mach-zynq/headsmp.S                       |  24 ++
+ arch/arm/mach-zynq/hotplug.c                       | 104 +++++
+ arch/arm/mach-zynq/platsmp.c                       | 152 +++++++
+ arch/arm/mach-zynq/slcr.c                          | 125 ++++++
+ arch/arm/mach-zynq/timer.c                         | 324 ---------------
+ drivers/clocksource/Kconfig                        |   3 +
+ drivers/clocksource/Makefile                       |   1 +
+ drivers/clocksource/bcm2835_timer.c                |  12 +-
+ drivers/clocksource/cadence_ttc_timer.c            | 436 +++++++++++++++++++++
+ drivers/clocksource/clksrc-of.c                    |   5 +-
+ drivers/clocksource/tegra20_timer.c                |  73 ++--
+ drivers/clocksource/vt8500_timer.c                 |  16 +-
+ include/linux/clocksource.h                        |  12 +-
+ 29 files changed, 1007 insertions(+), 513 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/timer/cadence,ttc-timer.txt
+ create mode 100644 arch/arm/mach-zynq/headsmp.S
+ create mode 100644 arch/arm/mach-zynq/hotplug.c
+ create mode 100644 arch/arm/mach-zynq/platsmp.c
+ create mode 100644 arch/arm/mach-zynq/slcr.c
+ delete mode 100644 arch/arm/mach-zynq/timer.c
+ create mode 100644 drivers/clocksource/cadence_ttc_timer.c
+Merging arm64/upstream (d4784be Merge branch 'arm64-klib' into upstream)
+$ git merge arm64/upstream
+Auto-merging arch/arm64/include/asm/smp_plat.h
+Merge made by the 'recursive' strategy.
+ arch/arm64/include/asm/Kbuild                      |   1 -
+ arch/arm64/include/asm/bitops.h                    |  18 +++-
+ arch/arm64/include/asm/cputype.h                   |  30 ++++++
+ arch/arm64/include/asm/exception.h                 |   1 +
+ arch/arm64/include/asm/hardirq.h                   |   5 +
+ arch/arm64/include/asm/irq.h                       |   1 +
+ .../arm64/{lib/bitops.c => include/asm/smp_plat.h} |  25 +++--
+ arch/arm64/include/asm/string.h                    |  37 ++++++++
+ arch/arm64/kernel/arm64ksyms.c                     |  21 ++++-
+ arch/arm64/kernel/early_printk.c                   |  35 +++++++
+ arch/arm64/kernel/head.S                           |   4 +-
+ arch/arm64/kernel/irq.c                            |  19 ++--
+ arch/arm64/kernel/setup.c                          |  12 +++
+ arch/arm64/kernel/smp.c                            | 102 ++++++++++++++++++---
+ arch/arm64/kernel/smp_psci.c                       |   5 +-
+ arch/arm64/lib/Makefile                            |   4 +-
+ arch/arm64/lib/bitops.S                            |  70 ++++++++++++++
+ arch/arm64/lib/memchr.S                            |  44 +++++++++
+ arch/arm64/lib/memcpy.S                            |  53 +++++++++++
+ arch/arm64/lib/memmove.S                           |  57 ++++++++++++
+ arch/arm64/lib/memset.S                            |  53 +++++++++++
+ arch/arm64/lib/strchr.S                            |  42 +++++++++
+ arch/arm64/lib/strrchr.S                           |  43 +++++++++
+ 23 files changed, 638 insertions(+), 44 deletions(-)
+ rename arch/arm64/{lib/bitops.c => include/asm/smp_plat.h} (58%)
+ create mode 100644 arch/arm64/include/asm/string.h
+ create mode 100644 arch/arm64/lib/bitops.S
+ create mode 100644 arch/arm64/lib/memchr.S
+ create mode 100644 arch/arm64/lib/memcpy.S
+ create mode 100644 arch/arm64/lib/memmove.S
+ create mode 100644 arch/arm64/lib/memset.S
+ create mode 100644 arch/arm64/lib/strchr.S
+ create mode 100644 arch/arm64/lib/strrchr.S
+Merging blackfin/for-linus (f656c24 blackfin: time-ts: Remove duplicate assignment)
+$ git merge blackfin/for-linus
+Already up-to-date.
+Merging c6x/for-linux-next (93bbd0c c6x: use generic kvm_para.h)
+$ git merge c6x/for-linux-next
+Already up-to-date.
+Merging cris/for-next (ae0b105 CRIS: Remove last traces of legacy RTC drivers)
+$ git merge cris/for-next
+Auto-merging arch/cris/Kconfig
+Merge made by the 'recursive' strategy.
+ arch/cris/Kconfig                   | 35 ---------------------------
+ arch/cris/arch-v10/drivers/Kconfig  | 47 -------------------------------------
+ arch/cris/arch-v10/drivers/Makefile |  2 --
+ 3 files changed, 84 deletions(-)
+Merging hexagon/linux-next (411d53d Hexagon: remove two Kconfig entries)
+$ git merge hexagon/linux-next
+Removing arch/hexagon/kernel/topology.c
+Merge made by the 'recursive' strategy.
+ arch/hexagon/Kconfig                      |  33 ++--
+ arch/hexagon/Makefile                     |  17 +-
+ arch/hexagon/include/asm/Kbuild           |   2 +-
+ arch/hexagon/include/asm/atomic.h         |  22 +--
+ arch/hexagon/include/asm/elf.h            |   8 +-
+ arch/hexagon/include/asm/hexagon_vm.h     |  56 +++---
+ arch/hexagon/include/asm/io.h             |  16 +-
+ arch/hexagon/include/asm/mem-layout.h     |  25 ++-
+ arch/hexagon/include/asm/page.h           |   7 +-
+ arch/hexagon/include/asm/processor.h      |  51 +++++-
+ arch/hexagon/include/asm/vm_mmu.h         |  11 +-
+ arch/hexagon/include/uapi/asm/ptrace.h    |   5 +
+ arch/hexagon/include/uapi/asm/registers.h |  17 +-
+ arch/hexagon/include/uapi/asm/signal.h    |   4 +
+ arch/hexagon/include/uapi/asm/unistd.h    |   3 +
+ arch/hexagon/include/uapi/asm/user.h      |   6 +
+ arch/hexagon/kernel/Makefile              |   2 +-
+ arch/hexagon/kernel/asm-offsets.c         |   5 +-
+ arch/hexagon/kernel/head.S                | 107 ++++++++++--
+ arch/hexagon/kernel/kgdb.c                |   4 +-
+ arch/hexagon/kernel/process.c             |  41 ++++-
+ arch/hexagon/kernel/ptrace.c              |  26 ++-
+ arch/hexagon/kernel/setup.c               |   9 +-
+ arch/hexagon/kernel/signal.c              |  45 ++---
+ arch/hexagon/kernel/topology.c            |  52 ------
+ arch/hexagon/kernel/traps.c               |  36 ++--
+ arch/hexagon/kernel/vm_entry.S            | 282 +++++++++++++++++++++---------
+ arch/hexagon/kernel/vm_events.c           |   4 +-
+ arch/hexagon/kernel/vm_vectors.S          |   4 +-
+ arch/hexagon/kernel/vmlinux.lds.S         |  12 +-
+ arch/hexagon/mm/init.c                    |  35 ++--
+ arch/openrisc/Kconfig                     |   3 -
+ 32 files changed, 621 insertions(+), 329 deletions(-)
+ delete mode 100644 arch/hexagon/kernel/topology.c
+Merging ia64/next (797f6a6 Add size restriction to the kdump documentation)
+$ git merge ia64/next
+Merge made by the 'recursive' strategy.
+ Documentation/ia64/err_inject.txt |  2 +-
+ Documentation/kdump/kdump.txt     |  1 +
+ arch/ia64/Kconfig                 |  2 +-
+ arch/ia64/include/asm/futex.h     |  5 ++--
+ arch/ia64/include/asm/mca.h       |  1 +
+ arch/ia64/include/asm/numa.h      |  5 ++--
+ arch/ia64/kernel/fsys.S           | 49 +--------------------------------------
+ arch/ia64/kernel/iosapic.c        | 34 +++++++++++++++++++++++++--
+ arch/ia64/kernel/irq.c            |  8 +++++++
+ arch/ia64/kernel/mca.c            | 37 ++++++++++++++++++-----------
+ arch/ia64/kernel/mca_drv.c        |  2 +-
+ arch/ia64/kvm/vtlb.c              |  2 +-
+ arch/ia64/mm/ioremap.c            | 14 +++++++----
+ arch/ia64/mm/numa.c               |  5 ++++
+ arch/ia64/sn/kernel/tiocx.c       |  5 +++-
+ 15 files changed, 93 insertions(+), 79 deletions(-)
+Merging m68k/for-next (5618395 m68k: Sort out !CONFIG_MMU_SUN3 vs. CONFIG_HAS_DMA)
+$ git merge m68k/for-next
+Already up-to-date.
+Merging m68knommu/for-next (b46ab88 m68k: clean up unused "config ROMVECSIZE")
+$ git merge m68knommu/for-next
+Merge made by the 'recursive' strategy.
+ arch/m68k/Kconfig.machine | 9 ---------
+ 1 file changed, 9 deletions(-)
+Merging metag/for-next (82bbb83 metag: add exported <asm/ech.h> for extended context handling)
+$ git merge metag/for-next
+Auto-merging arch/microblaze/Kconfig
+Merge made by the 'recursive' strategy.
+ arch/metag/Kconfig                  |   4 ++
+ arch/metag/Makefile                 |   2 +
+ arch/metag/include/asm/metag_mem.h  |   3 +
+ arch/metag/include/uapi/asm/Kbuild  |   1 +
+ arch/metag/include/uapi/asm/ech.h   |  15 +++++
+ arch/metag/kernel/cachepart.c       |  16 +++--
+ arch/metag/kernel/da.c              |   2 +
+ arch/metag/kernel/head.S            |   8 +++
+ arch/metag/kernel/perf/perf_event.c |  74 +++++++++++++++--------
+ arch/metag/kernel/ptrace.c          |  34 +++++++++++
+ arch/metag/kernel/setup.c           |   1 +
+ arch/metag/kernel/smp.c             | 115 ++++++++++++++++++++++++++++++++++++
+ arch/metag/mm/Kconfig               |   3 -
+ arch/metag/oprofile/Makefile        |  17 ++++++
+ arch/metag/oprofile/backtrace.c     |  63 ++++++++++++++++++++
+ arch/metag/oprofile/backtrace.h     |   6 ++
+ arch/metag/oprofile/common.c        |  66 +++++++++++++++++++++
+ arch/microblaze/Kconfig             |   3 -
+ include/uapi/linux/elf.h            |   1 +
+ 19 files changed, 400 insertions(+), 34 deletions(-)
+ create mode 100644 arch/metag/include/uapi/asm/ech.h
+ create mode 100644 arch/metag/oprofile/Makefile
+ create mode 100644 arch/metag/oprofile/backtrace.c
+ create mode 100644 arch/metag/oprofile/backtrace.h
+ create mode 100644 arch/metag/oprofile/common.c
+Merging microblaze/next (01cc2cb microblaze: intc: set the default irq_domain)
+$ git merge microblaze/next
+Merge made by the 'recursive' strategy.
+ arch/microblaze/kernel/intc.c    | 2 ++
+ arch/microblaze/pci/pci-common.c | 1 -
+ 2 files changed, 2 insertions(+), 1 deletion(-)
+Merging mips/mips-for-linux-next (306d20e Merge branches 'next/3.9-fixes', 'next/kvm' and 'next/micromips' into mips-for-linux-next)
+$ git merge mips/mips-for-linux-next
+Auto-merging arch/mips/Kconfig
+Merge made by the 'recursive' strategy.
+ arch/mips/Kbuild                            |    4 +
+ arch/mips/Kconfig                           |   22 +
+ arch/mips/configs/malta_kvm_defconfig       | 2267 +++++++++++++++++++++++++++
+ arch/mips/configs/malta_kvm_guest_defconfig | 2237 ++++++++++++++++++++++++++
+ arch/mips/include/asm/kvm.h                 |   55 +
+ arch/mips/include/asm/kvm_host.h            |  667 ++++++++
+ arch/mips/include/asm/mach-generic/spaces.h |    9 +-
+ arch/mips/include/asm/mipsregs.h            |   18 +
+ arch/mips/include/asm/mmu_context.h         |    6 +
+ arch/mips/include/asm/processor.h           |    5 +
+ arch/mips/include/asm/uaccess.h             |   11 +-
+ arch/mips/include/asm/uasm.h                |   66 +-
+ arch/mips/include/uapi/asm/inst.h           |  449 ++++++
+ arch/mips/kernel/asm-offsets.c              |   66 +
+ arch/mips/kernel/binfmt_elfo32.c            |    4 +
+ arch/mips/kernel/cevt-r4k.c                 |    4 +
+ arch/mips/kernel/smp.c                      |    1 +
+ arch/mips/kernel/traps.c                    |    7 +-
+ arch/mips/kvm/00README.txt                  |   31 +
+ arch/mips/kvm/Kconfig                       |   49 +
+ arch/mips/kvm/Makefile                      |   13 +
+ arch/mips/kvm/kvm_cb.c                      |   14 +
+ arch/mips/kvm/kvm_locore.S                  |  650 ++++++++
+ arch/mips/kvm/kvm_mips.c                    |  966 ++++++++++++
+ arch/mips/kvm/kvm_mips_comm.h               |   23 +
+ arch/mips/kvm/kvm_mips_commpage.c           |   37 +
+ arch/mips/kvm/kvm_mips_dyntrans.c           |  149 ++
+ arch/mips/kvm/kvm_mips_emul.c               | 1829 +++++++++++++++++++++
+ arch/mips/kvm/kvm_mips_int.c                |  243 +++
+ arch/mips/kvm/kvm_mips_int.h                |   49 +
+ arch/mips/kvm/kvm_mips_opcode.h             |   24 +
+ arch/mips/kvm/kvm_mips_stats.c              |   82 +
+ arch/mips/kvm/kvm_tlb.c                     |  932 +++++++++++
+ arch/mips/kvm/kvm_trap_emul.c               |  482 ++++++
+ arch/mips/kvm/trace.h                       |   46 +
+ arch/mips/mm/Makefile                       |    4 +-
+ arch/mips/mm/c-r4k.c                        |    6 +-
+ arch/mips/mm/cache.c                        |    1 +
+ arch/mips/mm/tlb-r4k.c                      |    2 +
+ arch/mips/mm/uasm-micromips.c               |  220 +++
+ arch/mips/mm/uasm-mips.c                    |  196 +++
+ arch/mips/mm/uasm.c                         |  326 +---
+ arch/mips/mti-malta/Platform                |    6 +-
+ arch/mips/mti-malta/malta-time.c            |   13 +
+ mm/bootmem.c                                |    1 +
+ virt/kvm/kvm_main.c                         |    2 +-
+ 46 files changed, 12014 insertions(+), 280 deletions(-)
+ create mode 100644 arch/mips/configs/malta_kvm_defconfig
+ create mode 100644 arch/mips/configs/malta_kvm_guest_defconfig
+ create mode 100644 arch/mips/include/asm/kvm.h
+ create mode 100644 arch/mips/include/asm/kvm_host.h
+ create mode 100644 arch/mips/kvm/00README.txt
+ create mode 100644 arch/mips/kvm/Kconfig
+ create mode 100644 arch/mips/kvm/Makefile
+ create mode 100644 arch/mips/kvm/kvm_cb.c
+ create mode 100644 arch/mips/kvm/kvm_locore.S
+ create mode 100644 arch/mips/kvm/kvm_mips.c
+ create mode 100644 arch/mips/kvm/kvm_mips_comm.h
+ create mode 100644 arch/mips/kvm/kvm_mips_commpage.c
+ create mode 100644 arch/mips/kvm/kvm_mips_dyntrans.c
+ create mode 100644 arch/mips/kvm/kvm_mips_emul.c
+ create mode 100644 arch/mips/kvm/kvm_mips_int.c
+ create mode 100644 arch/mips/kvm/kvm_mips_int.h
+ create mode 100644 arch/mips/kvm/kvm_mips_opcode.h
+ create mode 100644 arch/mips/kvm/kvm_mips_stats.c
+ create mode 100644 arch/mips/kvm/kvm_tlb.c
+ create mode 100644 arch/mips/kvm/kvm_trap_emul.c
+ create mode 100644 arch/mips/kvm/trace.h
+ create mode 100644 arch/mips/mm/uasm-micromips.c
+ create mode 100644 arch/mips/mm/uasm-mips.c
+Merging openrisc/for-upstream (6af6095 openrisc: remove HAVE_VIRT_TO_BUS)
+$ git merge openrisc/for-upstream
+Already up-to-date.
+Merging parisc/for-next (6c700d7 [PARISC] hpux: Remove obsolete regs parameter from do_execve() in hpux_execve())
+$ git merge parisc/for-next
+Already up-to-date.
+Merging powerpc/next (9e2d59a Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal)
+$ git merge powerpc/next
+Already up-to-date.
+Merging 4xx/next (2074b1d powerpc: Fix irq distribution)
+$ git merge 4xx/next
+Already up-to-date.
+Merging mpc5xxx/next (b9e7196 powerpc/512x: move mpc5121_generic platform to mpc512x_generic.)
+$ git merge mpc5xxx/next
+Auto-merging arch/powerpc/platforms/512x/mpc512x_generic.c
+Merge made by the 'recursive' strategy.
+ arch/powerpc/configs/mpc512x_defconfig                      |  2 +-
+ arch/powerpc/platforms/512x/Kconfig                         |  8 ++++----
+ arch/powerpc/platforms/512x/Makefile                        |  2 +-
+ .../platforms/512x/{mpc5121_generic.c => mpc512x_generic.c} | 10 +++++-----
+ arch/powerpc/platforms/512x/mpc512x_shared.c                | 13 +++++--------
+ 5 files changed, 16 insertions(+), 19 deletions(-)
+ rename arch/powerpc/platforms/512x/{mpc5121_generic.c => mpc512x_generic.c} (86%)
+Merging galak/next (ddb487d powerpc/85xx: fix a bug with the parameter of mpic_reset_core())
+$ git merge galak/next
+Auto-merging arch/powerpc/platforms/Kconfig.cputype
+Auto-merging arch/powerpc/kernel/cputable.c
+Auto-merging arch/powerpc/Kconfig
+Merge made by the 'recursive' strategy.
+ .../devicetree/bindings/powerpc/fsl/cpus.txt       |  22 ++
+ arch/powerpc/Kconfig                               |   6 -
+ arch/powerpc/boot/dts/fsl/e500mc_power_isa.dtsi    |   1 +
+ arch/powerpc/boot/dts/fsl/e5500_power_isa.dtsi     |   1 +
+ arch/powerpc/boot/dts/fsl/e6500_power_isa.dtsi     |  65 +++
+ arch/powerpc/boot/dts/fsl/p2041si-post.dtsi        |   2 +-
+ arch/powerpc/boot/dts/fsl/p3041si-post.dtsi        |   2 +-
+ arch/powerpc/boot/dts/fsl/p4080si-post.dtsi        |   2 +-
+ arch/powerpc/boot/dts/fsl/p5020si-post.dtsi        |   2 +-
+ arch/powerpc/boot/dts/fsl/p5040si-post.dtsi        |   2 +-
+ arch/powerpc/boot/dts/fsl/qonverge-usb2-dr-0.dtsi  |  41 ++
+ arch/powerpc/boot/dts/fsl/qoriq-gpio-1.dtsi        |  41 ++
+ arch/powerpc/boot/dts/fsl/qoriq-gpio-2.dtsi        |  41 ++
+ arch/powerpc/boot/dts/fsl/qoriq-gpio-3.dtsi        |  41 ++
+ arch/powerpc/boot/dts/fsl/qoriq-sec5.0-0.dtsi      | 109 +++++
+ arch/powerpc/boot/dts/fsl/qoriq-sec5.3-0.dtsi      | 118 ++++++
+ arch/powerpc/boot/dts/fsl/t4240si-post.dtsi        | 438 +++++++++++++++++++++
+ arch/powerpc/boot/dts/fsl/t4240si-pre.dtsi         | 128 ++++++
+ arch/powerpc/boot/dts/p1021rdb-pc.dtsi             |  12 +-
+ arch/powerpc/boot/dts/t4240qds.dts                 | 224 +++++++++++
+ arch/powerpc/configs/corenet64_smp_defconfig       |  45 ++-
+ arch/powerpc/configs/mpc85xx_defconfig             |  39 +-
+ arch/powerpc/configs/mpc85xx_smp_defconfig         |  31 ++
+ arch/powerpc/include/asm/cputable.h                |   2 +-
+ arch/powerpc/include/asm/kvm_asm.h                 |   4 +
+ arch/powerpc/kernel/cpu_setup_fsl_booke.S          |  16 +
+ arch/powerpc/kernel/cputable.c                     |   9 +-
+ arch/powerpc/kernel/epapr_hcalls.S                 |   2 +
+ arch/powerpc/kernel/exceptions-64e.S               |  47 +++
+ arch/powerpc/kernel/idle_book3e.S                  |  32 +-
+ arch/powerpc/mm/tlb_nohash.c                       |  18 +-
+ arch/powerpc/platforms/85xx/Kconfig                |  17 +
+ arch/powerpc/platforms/85xx/Makefile               |   1 +
+ arch/powerpc/platforms/85xx/corenet_ds.c           |   5 +-
+ arch/powerpc/platforms/85xx/smp.c                  |   2 +-
+ arch/powerpc/platforms/85xx/t4240_qds.c            |  98 +++++
+ arch/powerpc/platforms/Kconfig                     |   1 -
+ arch/powerpc/platforms/Kconfig.cputype             |   2 +-
+ arch/powerpc/sysdev/fsl_msi.c                      |   4 +-
+ arch/powerpc/sysdev/fsl_pci.c                      |  39 +-
+ arch/powerpc/sysdev/fsl_pci.h                      |  13 +
+ arch/powerpc/sysdev/qe_lib/Kconfig                 |   2 +-
+ 42 files changed, 1682 insertions(+), 45 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/powerpc/fsl/cpus.txt
+ create mode 100644 arch/powerpc/boot/dts/fsl/e6500_power_isa.dtsi
+ create mode 100644 arch/powerpc/boot/dts/fsl/qonverge-usb2-dr-0.dtsi
+ create mode 100644 arch/powerpc/boot/dts/fsl/qoriq-gpio-1.dtsi
+ create mode 100644 arch/powerpc/boot/dts/fsl/qoriq-gpio-2.dtsi
+ create mode 100644 arch/powerpc/boot/dts/fsl/qoriq-gpio-3.dtsi
+ create mode 100644 arch/powerpc/boot/dts/fsl/qoriq-sec5.0-0.dtsi
+ create mode 100644 arch/powerpc/boot/dts/fsl/qoriq-sec5.3-0.dtsi
+ create mode 100644 arch/powerpc/boot/dts/fsl/t4240si-post.dtsi
+ create mode 100644 arch/powerpc/boot/dts/fsl/t4240si-pre.dtsi
+ create mode 100644 arch/powerpc/boot/dts/t4240qds.dts
+ create mode 100644 arch/powerpc/platforms/85xx/t4240_qds.c
+Merging s390/features (875ea53 s390/bitops: get rid of __BITOPS_BARRIER())
+$ git merge s390/features
+Merge made by the 'recursive' strategy.
+ Documentation/s390/s390dbf.txt    |   3 +-
+ arch/s390/hypfs/hypfs_dbfs.c      |   4 +-
+ arch/s390/include/asm/bitops.h    | 117 +++++++++---------
+ arch/s390/include/asm/processor.h |   3 +-
+ arch/s390/kernel/Makefile         |  17 ++-
+ arch/s390/kernel/dis.c            |   9 +-
+ arch/s390/kernel/dumpstack.c      | 236 +++++++++++++++++++++++++++++++++++
+ arch/s390/kernel/traps.c          | 250 +-------------------------------------
+ arch/s390/kvm/trace.h             |   2 +-
+ arch/s390/mm/cmm.c                |   8 +-
+ arch/s390/mm/init.c               |  10 +-
+ arch/s390/mm/pageattr.c           |  24 ++--
+ arch/s390/net/bpf_jit_comp.c      |   3 +-
+ arch/s390/pci/pci.c               |   3 +-
+ drivers/s390/block/dasd_devmap.c  |   3 +-
+ drivers/s390/char/monreader.c     |   3 +-
+ drivers/s390/cio/chp.c            |  22 +++-
+ drivers/s390/cio/chp.h            |   2 +
+ drivers/s390/cio/chsc.c           |  11 +-
+ drivers/s390/cio/css.c            |   5 +-
+ drivers/s390/cio/device_ops.c     |  22 ++--
+ drivers/s390/cio/idset.c          |   2 +-
+ 22 files changed, 391 insertions(+), 368 deletions(-)
+ create mode 100644 arch/s390/kernel/dumpstack.c
+Merging sh/sh-latest (37284bd Merge branches 'sh/hw-breakpoints' and 'sh/serial-of' into sh-latest)
+$ git merge sh/sh-latest
+Merge made by the 'recursive' strategy.
+ .../bindings/tty/serial/renesas,sci-serial.txt     |  53 +++++++
+ arch/sh/include/asm/hw_breakpoint.h                |  12 +-
+ arch/sh/include/cpu-common/cpu/ubc.h               |  17 +++
+ arch/sh/include/cpu-sh2a/cpu/ubc.h                 |  14 ++
+ arch/sh/kernel/cpu/sh2a/Makefile                   |   3 +-
+ arch/sh/kernel/cpu/sh2a/ubc.c                      | 154 +++++++++++++++++++++
+ arch/sh/kernel/hw_breakpoint.c                     |   8 ++
+ drivers/tty/serial/sh-sci.c                        | 127 ++++++++++++++++-
+ include/linux/serial_sci.h                         |   4 +
+ 9 files changed, 376 insertions(+), 16 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/tty/serial/renesas,sci-serial.txt
+ create mode 100644 arch/sh/include/cpu-common/cpu/ubc.h
+ create mode 100644 arch/sh/include/cpu-sh2a/cpu/ubc.h
+ create mode 100644 arch/sh/kernel/cpu/sh2a/ubc.c
+Merging sparc-next/master (d6d88ba sparc64: Kill __ARCH_WANT_UNLOCKED_CTXSW)
+$ git merge sparc-next/master
+Merge made by the 'recursive' strategy.
+ arch/sparc/Kconfig                    |  20 +-
+ arch/sparc/Makefile                   |   1 +
+ arch/sparc/include/asm/cmpxchg_64.h   |   1 +
+ arch/sparc/include/asm/hibernate.h    |  23 ++
+ arch/sparc/include/asm/leon_pci.h     |   1 +
+ arch/sparc/include/asm/processor_64.h |   3 -
+ arch/sparc/kernel/Makefile            |   3 +-
+ arch/sparc/kernel/asm-offsets.c       |  15 +
+ arch/sparc/kernel/leon_pci.c          |   2 +
+ arch/sparc/kernel/leon_pci_grpci1.c   | 724 ++++++++++++++++++++++++++++++++++
+ arch/sparc/kernel/leon_pci_grpci2.c   |   5 +
+ arch/sparc/mm/init_64.c               |   2 -
+ arch/sparc/power/Makefile             |   3 +
+ arch/sparc/power/hibernate.c          |  42 ++
+ arch/sparc/power/hibernate_asm.S      | 131 ++++++
+ 15 files changed, 969 insertions(+), 7 deletions(-)
+ create mode 100644 arch/sparc/include/asm/hibernate.h
+ create mode 100644 arch/sparc/kernel/leon_pci_grpci1.c
+ create mode 100644 arch/sparc/power/Makefile
+ create mode 100644 arch/sparc/power/hibernate.c
+ create mode 100644 arch/sparc/power/hibernate_asm.S
+Merging tile/master (39e8202 tile: ns2cycles should use __raw_get_cpu_var)
+$ git merge tile/master
+Merge made by the 'recursive' strategy.
+ arch/tile/Kconfig                   | 17 +++-------------
+ arch/tile/include/asm/atomic.h      | 21 ++++++++++++++++++++
+ arch/tile/include/asm/ptrace.h      |  3 ++-
+ arch/tile/include/asm/syscall.h     |  6 ++++++
+ arch/tile/include/asm/syscalls.h    |  6 ------
+ arch/tile/include/asm/thread_info.h |  8 ++++++++
+ arch/tile/include/uapi/asm/unistd.h |  2 ++
+ arch/tile/kernel/intvec_32.S        | 10 ++++++++--
+ arch/tile/kernel/intvec_64.S        | 24 +++++++++++++++++------
+ arch/tile/kernel/ptrace.c           | 39 +++++++++++++++++++------------------
+ arch/tile/kernel/time.c             |  6 +++++-
+ 11 files changed, 93 insertions(+), 49 deletions(-)
+Merging unicore32/unicore32 (c284464 arch/unicore32: remove CONFIG_EXPERIMENTAL)
+$ git merge unicore32/unicore32
+Already up-to-date.
+Merging xtensa/for_next (4e34bf6 xtensa: provide default platform_pcibios_init implementation)
+$ git merge xtensa/for_next
+Merge made by the 'recursive' strategy.
+ Documentation/xtensa/mmu.txt             |  46 ++++++++++++
+ arch/xtensa/Kconfig                      |  44 +++++++----
+ arch/xtensa/boot/boot-elf/Makefile       |   1 +
+ arch/xtensa/boot/boot-elf/boot.lds.S     |  64 +++++++---------
+ arch/xtensa/boot/boot-elf/bootstrap.S    | 101 +++++++++++++++++++++----
+ arch/xtensa/boot/boot-uboot/Makefile     |   6 +-
+ arch/xtensa/include/asm/initialize_mmu.h | 107 ++++++++++++++++++++++++++
+ arch/xtensa/include/asm/vectors.h        | 125 +++++++++++++++++++++++++++++++
+ arch/xtensa/kernel/Makefile              |   2 +
+ arch/xtensa/kernel/head.S                |  39 +++++++---
+ arch/xtensa/kernel/platform.c            |   1 +
+ arch/xtensa/kernel/vectors.S             |   3 +-
+ arch/xtensa/kernel/vmlinux.lds.S         |  48 ++++++++----
+ arch/xtensa/kernel/xtensa_ksyms.c        |   5 ++
+ arch/xtensa/mm/mmu.c                     |  14 ++--
+ arch/xtensa/oprofile/backtrace.c         |   4 +-
+ arch/xtensa/platforms/iss/setup.c        |   8 +-
+ arch/xtensa/platforms/xt2000/setup.c     |   2 +
+ arch/xtensa/platforms/xtfpga/setup.c     |   2 +
+ 19 files changed, 512 insertions(+), 110 deletions(-)
+ create mode 100644 Documentation/xtensa/mmu.txt
+ create mode 100644 arch/xtensa/include/asm/vectors.h
+Merging btrfs/next (6aec51f Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux into for-linus-3.9)
+$ git merge btrfs/next
+Already up-to-date!
+Merge made by the 'recursive' strategy.
+Merging ceph/master (6e2a450 rbd: don't zero-fill non-image object requests)
+$ git merge ceph/master
+Already up-to-date.
+Merging cifs/for-next (bf0fce1 cifs: store the real expected sequence number in the mid)
+$ git merge cifs/for-next
+Merge made by the 'recursive' strategy.
+ fs/cifs/asn1.c          |  40 ++--
+ fs/cifs/cache.c         |   6 +-
+ fs/cifs/cifs_debug.c    |  67 ++++---
+ fs/cifs/cifs_debug.h    |  70 +++----
+ fs/cifs/cifs_dfs_ref.c  |  41 ++--
+ fs/cifs/cifs_spnego.c   |   5 +-
+ fs/cifs/cifs_unicode.c  |   4 +-
+ fs/cifs/cifsacl.c       | 130 ++++++-------
+ fs/cifs/cifsencrypt.c   | 106 +++++------
+ fs/cifs/cifsfs.c        |  36 ++--
+ fs/cifs/cifsproto.h     |  10 +-
+ fs/cifs/cifssmb.c       | 488 ++++++++++++++++++++++++------------------------
+ fs/cifs/connect.c       | 366 +++++++++++++++---------------------
+ fs/cifs/dir.c           |  44 ++---
+ fs/cifs/dns_resolve.c   |  17 +-
+ fs/cifs/export.c        |   2 +-
+ fs/cifs/file.c          | 166 ++++++++--------
+ fs/cifs/fscache.c       |  58 +++---
+ fs/cifs/inode.c         | 109 +++++------
+ fs/cifs/ioctl.c         |   6 +-
+ fs/cifs/link.c          |  24 +--
+ fs/cifs/misc.c          |  78 ++++----
+ fs/cifs/netmisc.c       |  16 +-
+ fs/cifs/readdir.c       |  77 ++++----
+ fs/cifs/sess.c          |  77 ++++----
+ fs/cifs/smb1ops.c       |  50 ++---
+ fs/cifs/smb2file.c      |   8 +-
+ fs/cifs/smb2inode.c     |   2 +-
+ fs/cifs/smb2maperror.c  |   2 +-
+ fs/cifs/smb2misc.c      |  96 +++++-----
+ fs/cifs/smb2ops.c       |  16 +-
+ fs/cifs/smb2pdu.c       | 161 ++++++++--------
+ fs/cifs/smb2transport.c |  26 +--
+ fs/cifs/smbencrypt.c    |  17 +-
+ fs/cifs/transport.c     |  84 +++++----
+ fs/cifs/xattr.c         |  54 +++---
+ 36 files changed, 1257 insertions(+), 1302 deletions(-)
+Merging configfs/linux-next (b930c26 Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs)
+$ git merge configfs/linux-next
+Already up-to-date.
+Merging ecryptfs/next (f6161aa Linux 3.9-rc2)
+$ git merge ecryptfs/next
+Already up-to-date.
+Merging ext3/for_next (e678a4f jbd: don't wait (forever) for stale tid caused by wraparound)
+$ git merge ext3/for_next
+Merge made by the 'recursive' strategy.
+ fs/ext3/inode.c  |  3 ++-
+ fs/jbd/journal.c | 11 +++++++++++
+ 2 files changed, 13 insertions(+), 1 deletion(-)
+Merging ext4/dev (f78ee70 ext4: print more info in ext4_print_free_blocks())
+$ git merge ext4/dev
+Merge made by the 'recursive' strategy.
+ fs/ext4/balloc.c            |  33 ++-
+ fs/ext4/ext4.h              |  35 ++-
+ fs/ext4/ext4_jbd2.c         |   6 +
+ fs/ext4/ext4_jbd2.h         |   6 +-
+ fs/ext4/extents.c           | 547 +++++++++++++++++++-------------------------
+ fs/ext4/fsync.c             |   3 +-
+ fs/ext4/indirect.c          | 473 +++++---------------------------------
+ fs/ext4/inode.c             | 439 ++++++++++++++++++++++++-----------
+ fs/ext4/ioctl.c             |  20 +-
+ fs/ext4/mballoc.c           |  18 +-
+ fs/ext4/resize.c            |  10 +-
+ fs/ext4/super.c             |  18 +-
+ fs/jbd2/commit.c            |  50 ++--
+ fs/jbd2/journal.c           |  31 +++
+ include/linux/jbd2.h        |   2 +
+ include/trace/events/ext4.h |  10 +-
+ 16 files changed, 754 insertions(+), 947 deletions(-)
+Merging f2fs/dev (9078af8 f2fs: fix the bitmap consistency of dirty segments)
+$ git merge f2fs/dev
+Auto-merging fs/f2fs/super.c
+Merge made by the 'recursive' strategy.
+ fs/f2fs/checkpoint.c    |  14 ++--
+ fs/f2fs/data.c          |  75 ++++++++++----------
+ fs/f2fs/debug.c         |   9 ++-
+ fs/f2fs/dir.c           |   3 +
+ fs/f2fs/f2fs.h          |  28 +++++---
+ fs/f2fs/file.c          |  42 +++--------
+ fs/f2fs/gc.c            |  98 ++++++++++++++++----------
+ fs/f2fs/inode.c         |   7 +-
+ fs/f2fs/namei.c         |  16 +++--
+ fs/f2fs/node.c          | 184 ++++++++++++++++++++++++++----------------------
+ fs/f2fs/node.h          |  15 ++++
+ fs/f2fs/recovery.c      |  69 +++++++++++-------
+ fs/f2fs/segment.c       | 127 +++++++++++++++++++--------------
+ fs/f2fs/segment.h       |  29 +++++---
+ fs/f2fs/super.c         |  42 ++++++++---
+ fs/f2fs/xattr.c         |  18 ++---
+ include/linux/f2fs_fs.h |  17 ++---
+ 17 files changed, 451 insertions(+), 342 deletions(-)
+Merging fuse/for-next (634734b fuse: allow control of adaptive readdirplus use)
+$ git merge fuse/for-next
+Already up-to-date.
+Merging gfs2/master (1987566 GFS2: Issue discards in 512b sectors)
+$ git merge gfs2/master
+Merge made by the 'recursive' strategy.
+ fs/dlm/plock.c     |  18 ++++-
+ fs/gfs2/bmap.c     |   2 +-
+ fs/gfs2/file.c     |   5 +-
+ fs/gfs2/glock.c    |  13 ----
+ fs/gfs2/glock.h    |   1 -
+ fs/gfs2/incore.h   |   1 +
+ fs/gfs2/inode.c    | 188 ++++++++++++++++++-----------------------------------
+ fs/gfs2/lock_dlm.c |  39 +++++------
+ fs/gfs2/rgrp.c     |  56 +++++++---------
+ fs/gfs2/rgrp.h     |   2 +-
+ fs/gfs2/super.c    |   2 +-
+ 11 files changed, 130 insertions(+), 197 deletions(-)
+Merging jfs/jfs-next (9d48017 jfs: avoid undefined behavior from left-shifting by 32 bits)
+$ git merge jfs/jfs-next
+Merge made by the 'recursive' strategy.
+ fs/jfs/jfs_imap.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+Merging logfs/master (3394661 Fix the call to BUG() caused by no free segment found)
+$ git merge logfs/master
+Auto-merging fs/logfs/super.c
+Merge made by the 'recursive' strategy.
+ fs/logfs/dev_mtd.c | 2 +-
+ fs/logfs/super.c   | 6 +++---
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+Merging nfs/linux-next (95883eb Merge RPCSEC_GSS changes from Chuck Lever)
+$ git merge nfs/linux-next
+Auto-merging net/sunrpc/xprtsock.c
+Auto-merging net/sunrpc/auth_gss/svcauth_gss.c
+Auto-merging fs/nfsd/nfs4xdr.c
+Auto-merging fs/nfs/super.c
+Merge made by the 'recursive' strategy.
+ fs/nfs/callback.c                     |   3 +
+ fs/nfs/callback_proc.c                |   2 +-
+ fs/nfs/delegation.c                   | 117 ++++++---
+ fs/nfs/delegation.h                   |   5 +-
+ fs/nfs/dir.c                          |   2 +
+ fs/nfs/inode.c                        |   7 +-
+ fs/nfs/nfs4_fs.h                      |  15 +-
+ fs/nfs/nfs4client.c                   |  28 +-
+ fs/nfs/nfs4filelayout.c               |  34 ++-
+ fs/nfs/nfs4namespace.c                |  43 ++--
+ fs/nfs/nfs4proc.c                     | 465 ++++++++++++++++++++++------------
+ fs/nfs/nfs4state.c                    | 116 +++++----
+ fs/nfs/nfs4super.c                    |   2 +
+ fs/nfs/nfs4xdr.c                      | 133 +++++-----
+ fs/nfs/pagelist.c                     |   2 +
+ fs/nfs/pnfs.c                         |   2 +
+ fs/nfs/read.c                         |   2 +
+ fs/nfs/super.c                        |  80 +++---
+ fs/nfs/write.c                        |   2 +
+ fs/nfsd/nfs4xdr.c                     |  24 +-
+ include/linux/nfs_fs.h                |   1 +
+ include/linux/nfs_fs_sb.h             |   2 +
+ include/linux/nfs_xdr.h               |  26 +-
+ include/linux/sunrpc/auth.h           |   9 +
+ include/linux/sunrpc/gss_api.h        |  30 ++-
+ net/sunrpc/Kconfig                    |   2 +-
+ net/sunrpc/auth.c                     |  75 +++++-
+ net/sunrpc/auth_gss/auth_gss.c        |   3 +
+ net/sunrpc/auth_gss/gss_krb5_mech.c   |   6 +-
+ net/sunrpc/auth_gss/gss_mech_switch.c | 119 ++++++---
+ net/sunrpc/auth_gss/svcauth_gss.c     |   4 +-
+ net/sunrpc/clnt.c                     |  28 +-
+ net/sunrpc/xprtsock.c                 |   8 +-
+ 33 files changed, 904 insertions(+), 493 deletions(-)
+Merging nfsd/nfsd-next (a7823c7 SUNRPC/cache: add module_put() on error path in cache_open())
+$ git merge nfsd/nfsd-next
+Auto-merging fs/nfsd/nfs4xdr.c
+Merge made by the 'recursive' strategy.
+ fs/nfsd/cache.h     |   1 +
+ fs/nfsd/nfs4proc.c  |  44 ++++--
+ fs/nfsd/nfs4state.c | 398 ++++++++++++++++++++++++++++------------------------
+ fs/nfsd/nfs4xdr.c   |   3 +-
+ fs/nfsd/nfscache.c  | 195 ++++++++++++++++++-------
+ fs/nfsd/nfsctl.c    |  13 +-
+ fs/nfsd/state.h     |  20 +--
+ fs/nfsd/xdr4.h      |   2 +-
+ net/sunrpc/cache.c  |   4 +-
+ 9 files changed, 413 insertions(+), 267 deletions(-)
+Merging ocfs2/linux-next (4538df6 ocfs2: Don't spam on -EDQUOT.)
+$ git merge ocfs2/linux-next
+Auto-merging fs/ocfs2/dlm/dlmrecovery.c
+Auto-merging fs/ocfs2/dlm/dlmmaster.c
+Auto-merging fs/ocfs2/cluster/heartbeat.c
+Merge made by the 'recursive' strategy.
+ fs/ocfs2/cluster/heartbeat.c | 40 +++++++++-------------------------------
+ fs/ocfs2/cluster/masklog.h   |  3 ++-
+ fs/ocfs2/dlm/dlmmaster.c     |  8 +++++++-
+ fs/ocfs2/dlm/dlmrecovery.c   |  7 +++++++
+ 4 files changed, 25 insertions(+), 33 deletions(-)
+Merging omfs/for-next (976d167 Linux 3.1-rc9)
+$ git merge omfs/for-next
+Already up-to-date.
+Merging squashfs/master (4b0180a Squashfs: add mount time sanity check for block_size and block_log match)
+$ git merge squashfs/master
+Already up-to-date.
+Merging v9fs/for-next (b6f4bee fs/9p: Fix atomic_open)
+$ git merge v9fs/for-next
+Already up-to-date.
+Merging ubifs/linux-next (67e753c UBIFS: make space fixup work in the remount case)
+$ git merge ubifs/linux-next
+Already up-to-date.
+Merging xfs/for-next (ff9a28f xfs: Fix WARN_ON(delalloc) in xfs_vm_releasepage())
+$ git merge xfs/for-next
+Resolved 'fs/xfs/xfs_iomap.c' using previous resolution.
+Auto-merging fs/xfs/xfs_iomap.c
+CONFLICT (content): Merge conflict in fs/xfs/xfs_iomap.c
+Auto-merging fs/xfs/xfs_buf.c
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master 1f2fbf8] Merge remote-tracking branch 'xfs/for-next'
+$ git diff -M --stat --summary HEAD^..
+ fs/xfs/xfs_alloc.c       |     2 +-
+ fs/xfs/xfs_aops.c        |    12 +-
+ fs/xfs/xfs_attr_leaf.c   |     6 +-
+ fs/xfs/xfs_bmap.c        | 10679 ++++++++++++++++++++++-----------------------
+ fs/xfs/xfs_buf.c         |     4 +-
+ fs/xfs/xfs_dinode.h      |     6 +-
+ fs/xfs/xfs_dquot.c       |    48 +-
+ fs/xfs/xfs_dquot.h       |    16 +-
+ fs/xfs/xfs_error.c       |     2 +-
+ fs/xfs/xfs_ialloc.c      |     2 +-
+ fs/xfs/xfs_inode.h       |     5 +-
+ fs/xfs/xfs_iomap.c       |   163 +-
+ fs/xfs/xfs_log.c         |     2 +-
+ fs/xfs/xfs_mount.h       |     1 -
+ fs/xfs/xfs_qm.c          |     2 +-
+ fs/xfs/xfs_qm.h          |     2 +-
+ fs/xfs/xfs_qm_syscalls.c |     9 +-
+ fs/xfs/xfs_trace.h       |    24 +
+ fs/xfs/xfs_trans_dquot.c |    10 +-
+ fs/xfs/xfs_vnodeops.c    |     2 +-
+ 20 files changed, 5520 insertions(+), 5477 deletions(-)
+Merging vfs/for-next (0f647ac create_proc_cpu_mask() doesn't need an argument...)
+$ git merge vfs/for-next
+Auto-merging net/sunrpc/cache.c
+Auto-merging kernel/exit.c
+Auto-merging fs/read_write.c
+Auto-merging fs/proc/root.c
+Auto-merging fs/pnode.h
+Auto-merging fs/pnode.c
+Auto-merging fs/namespace.c
+Auto-merging fs/jbd2/journal.c
+Removing fs/fifo.c
+Auto-merging fs/f2fs/file.c
+Auto-merging fs/f2fs/dir.c
+Auto-merging fs/ext4/super.c
+Auto-merging fs/ext4/mballoc.c
+Auto-merging fs/cifs/file.c
+Auto-merging fs/btrfs/file.c
+Auto-merging drivers/block/loop.c
+Auto-merging drivers/block/cciss.c
+Merge made by the 'recursive' strategy.
+ arch/alpha/kernel/srm_env.c                        |   93 +-
+ arch/arm/kernel/atags_proc.c                       |   28 +-
+ arch/arm/kernel/swp_emulate.c                      |    5 +-
+ arch/arm/mach-msm/last_radio_log.c                 |   20 +-
+ arch/blackfin/kernel/cplbinfo.c                    |    4 +-
+ arch/cris/arch-v10/kernel/fasttimer.c              |    4 +-
+ arch/cris/arch-v32/kernel/fasttimer.c              |    5 +-
+ arch/h8300/kernel/gpio.c                           |    5 +-
+ arch/ia64/kernel/palinfo.c                         |   77 +-
+ arch/ia64/kernel/salinfo.c                         |   18 +-
+ arch/ia64/sn/kernel/sn2/prominfo_proc.c            |   42 +-
+ arch/mips/lasat/picvue_proc.c                      |    4 +-
+ arch/powerpc/kernel/lparcfg.c                      |   11 +-
+ arch/powerpc/kernel/proc_powerpc.c                 |   19 +-
+ arch/powerpc/platforms/cell/spufs/file.c           |    2 -
+ arch/powerpc/platforms/pseries/scanlog.c           |    9 +-
+ arch/s390/kernel/compat_wrapper.S                  |   16 -
+ arch/s390/kernel/irq.c                             |    6 +-
+ arch/s390/kernel/syscalls.S                        |    4 +-
+ arch/sh/mm/alignment.c                             |    2 +-
+ arch/sparc/kernel/ioport.c                         |    2 +-
+ arch/tile/kernel/hardwall.c                        |    2 +-
+ arch/xtensa/platforms/iss/simdisk.c                |   36 +-
+ drivers/acpi/ac.c                                  |    2 +-
+ drivers/acpi/battery.c                             |    2 +-
+ drivers/acpi/button.c                              |    2 +-
+ drivers/acpi/proc.c                                |    4 +-
+ drivers/acpi/sbs.c                                 |    8 +-
+ drivers/ata/sata_svw.c                             |   29 +-
+ drivers/block/DAC960.c                             |    8 +-
+ drivers/block/cciss.c                              |    2 +-
+ drivers/block/cciss_scsi.c                         |   96 +-
+ drivers/block/cpqarray.c                           |    2 +-
+ drivers/block/drbd/drbd_proc.c                     |    2 +-
+ drivers/block/loop.c                               |    2 +
+ drivers/block/pktcdvd.c                            |    2 +-
+ drivers/block/ps3vram.c                            |    2 +-
+ drivers/char/ds1620.c                              |    7 +-
+ drivers/char/ipmi/ipmi_msghandler.c                |    6 +-
+ drivers/char/ipmi/ipmi_si_intf.c                   |    6 +-
+ drivers/gpu/drm/drm_proc.c                         |    2 +-
+ drivers/ide/ide-cd.c                               |    2 +-
+ drivers/ide/ide-disk_proc.c                        |    8 +-
+ drivers/ide/ide-floppy_proc.c                      |    2 +-
+ drivers/ide/ide-proc.c                             |   22 +-
+ drivers/ide/ide-tape.c                             |    2 +-
+ drivers/isdn/gigaset/capi.c                        |    2 +-
+ drivers/isdn/hardware/avm/b1.c                     |    2 +-
+ drivers/isdn/hardware/avm/b1dma.c                  |    2 +-
+ drivers/isdn/hardware/avm/c4.c                     |    2 +-
+ drivers/isdn/hardware/eicon/divasproc.c            |   12 +-
+ drivers/isdn/hysdn/hycapi.c                        |    2 +-
+ drivers/isdn/hysdn/hysdn_procconf.c                |   32 +-
+ drivers/isdn/hysdn/hysdn_proclog.c                 |   71 +-
+ drivers/macintosh/via-pmu.c                        |    2 +-
+ drivers/media/pci/zoran/zoran_procfs.c             |    4 +-
+ drivers/message/fusion/mptbase.c                   |    4 +-
+ drivers/message/fusion/mptfc.c                     |    2 +-
+ drivers/message/fusion/mptsas.c                    |    2 +-
+ drivers/message/fusion/mptscsih.c                  |   98 +-
+ drivers/message/fusion/mptscsih.h                  |    2 +-
+ drivers/message/fusion/mptspi.c                    |    2 +-
+ drivers/message/i2o/i2o_proc.c                     |   89 +-
+ drivers/net/bonding/bond_procfs.c                  |    4 +-
+ drivers/net/irda/vlsi_ir.c                         |    2 +-
+ drivers/net/wireless/airo.c                        |   33 +-
+ drivers/net/wireless/ath/wil6210/debugfs.c         |    4 +-
+ drivers/net/wireless/ray_cs.c                      |    2 +-
+ drivers/parisc/led.c                               |    4 +-
+ drivers/pci/proc.c                                 |   20 +-
+ drivers/platform/x86/thinkpad_acpi.c               |    4 +-
+ drivers/platform/x86/toshiba_acpi.c                |   18 +-
+ drivers/pnp/isapnp/proc.c                          |    4 +-
+ drivers/pnp/pnpbios/proc.c                         |    4 +-
+ drivers/rtc/rtc-proc.c                             |    2 +-
+ drivers/scsi/BusLogic.c                            |   83 +-
+ drivers/scsi/BusLogic.h                            |    1 -
+ drivers/scsi/NCR5380.c                             |   61 +-
+ drivers/scsi/NCR5380.h                             |    6 +-
+ drivers/scsi/a2091.c                               |    3 +-
+ drivers/scsi/a3000.c                               |    3 +-
+ drivers/scsi/advansys.c                            | 1164 ++++--------
+ drivers/scsi/aha152x.c                             |   61 +-
+ drivers/scsi/aha1740.c                             |   29 +-
+ drivers/scsi/aic7xxx/aic79xx_osm.c                 |    9 +-
+ drivers/scsi/aic7xxx/aic79xx_osm.h                 |   12 +-
+ drivers/scsi/aic7xxx/aic79xx_proc.c                |  163 +-
+ drivers/scsi/aic7xxx/aic7xxx_osm.c                 |    9 +-
+ drivers/scsi/aic7xxx/aic7xxx_osm.h                 |   12 +-
+ drivers/scsi/aic7xxx/aic7xxx_proc.c                |  153 +-
+ drivers/scsi/aic7xxx_old.c                         |    2 +-
+ drivers/scsi/aic7xxx_old/aic7xxx_proc.c            |  221 +--
+ drivers/scsi/arm/acornscsi.c                       |   58 +-
+ drivers/scsi/arm/arxescsi.c                        |   40 +-
+ drivers/scsi/arm/cumana_1.c                        |    1 -
+ drivers/scsi/arm/cumana_2.c                        |   43 +-
+ drivers/scsi/arm/eesox.c                           |   42 +-
+ drivers/scsi/arm/fas216.c                          |   31 +-
+ drivers/scsi/arm/fas216.h                          |    6 +-
+ drivers/scsi/arm/oak.c                             |    6 +-
+ drivers/scsi/arm/powertec.c                        |   29 +-
+ drivers/scsi/atari_NCR5380.c                       |  145 +-
+ drivers/scsi/atari_scsi.c                          |    2 +-
+ drivers/scsi/atari_scsi.h                          |    2 +-
+ drivers/scsi/atp870u.c                             |   40 +-
+ drivers/scsi/dc395x.c                              |   20 +-
+ drivers/scsi/dpt_i2o.c                             |  102 +-
+ drivers/scsi/dtc.c                                 |    3 +-
+ drivers/scsi/dtc.h                                 |    3 +-
+ drivers/scsi/eata_pio.c                            |   56 +-
+ drivers/scsi/g_NCR5380.c                           |   51 +-
+ drivers/scsi/gdth.c                                |    3 +-
+ drivers/scsi/gdth.h                                |    3 +-
+ drivers/scsi/gdth_proc.c                           |  211 +--
+ drivers/scsi/gdth_proc.h                           |    5 -
+ drivers/scsi/gvp11.c                               |    3 +-
+ drivers/scsi/imm.c                                 |   40 +-
+ drivers/scsi/in2000.c                              |  178 +-
+ drivers/scsi/ips.c                                 |  238 +--
+ drivers/scsi/ips.h                                 |    9 -
+ drivers/scsi/mac_scsi.c                            |    3 +-
+ drivers/scsi/mac_scsi.h                            |    3 +-
+ drivers/scsi/mvme147.c                             |    3 +-
+ drivers/scsi/nsp32.c                               |   39 +-
+ drivers/scsi/pas16.c                               |    3 +-
+ drivers/scsi/pas16.h                               |    3 +-
+ drivers/scsi/pcmcia/nsp_cs.c                       |   36 +-
+ drivers/scsi/pcmcia/nsp_cs.h                       |    9 +-
+ drivers/scsi/ppa.c                                 |   36 +-
+ drivers/scsi/scsi_debug.c                          |   53 +-
+ drivers/scsi/scsi_proc.c                           |   74 +-
+ drivers/scsi/sym53c8xx_2/sym_glue.c                |  115 +-
+ drivers/scsi/t128.c                                |    3 +-
+ drivers/scsi/t128.h                                |    3 +-
+ drivers/scsi/wd33c93.c                             |  194 +-
+ drivers/scsi/wd33c93.h                             |    3 +-
+ drivers/scsi/wd7000.c                              |   31 +-
+ drivers/staging/ccg/f_fs.c                         |    2 -
+ drivers/staging/ccg/rndis.c                        |    4 +-
+ drivers/staging/comedi/proc.c                      |    7 +-
+ drivers/staging/dgrp/dgrp_common.c                 |   31 -
+ drivers/staging/dgrp/dgrp_common.h                 |   65 +-
+ drivers/staging/dgrp/dgrp_dpa_ops.c                |   28 +-
+ drivers/staging/dgrp/dgrp_mon_ops.c                |   25 +-
+ drivers/staging/dgrp/dgrp_net_ops.c                |   28 +-
+ drivers/staging/dgrp/dgrp_ports_ops.c              |   18 +-
+ drivers/staging/dgrp/dgrp_specproc.c               |  390 +---
+ drivers/staging/keucr/scsiglue.c                   |   45 +-
+ drivers/staging/rtl8192e/rtl8192e/rtl_debug.c      |    6 +-
+ drivers/staging/rtl8192e/rtllib_module.c           |   54 +-
+ .../staging/rtl8192u/ieee80211/ieee80211_module.c  |   53 +-
+ drivers/staging/rtl8192u/ieee80211/proc.c          |    6 +-
+ drivers/staging/rts5139/rts51x_scsi.c              |   30 +-
+ drivers/staging/rts5139/rts51x_scsi.h              |    2 -
+ drivers/staging/silicom/bp_mod.c                   | 1899 ++++++--------------
+ drivers/staging/silicom/bp_proc.c                  |  266 +--
+ drivers/target/loopback/tcm_loop.c                 |    9 +-
+ drivers/tty/serial/serial_core.c                   |    2 +-
+ drivers/usb/gadget/at91_udc.c                      |    2 +-
+ drivers/usb/gadget/f_fs.c                          |    2 -
+ drivers/usb/gadget/inode.c                         |    2 -
+ drivers/usb/gadget/lpc32xx_udc.c                   |    2 +-
+ drivers/usb/gadget/rndis.c                         |    4 +-
+ drivers/usb/host/isp1362-hcd.c                     |    7 +-
+ drivers/usb/host/sl811-hcd.c                       |    2 +-
+ drivers/usb/storage/scsiglue.c                     |   42 +-
+ drivers/video/bfin_adv7393fb.c                     |   43 +-
+ drivers/zorro/proc.c                               |    4 +-
+ fs/Makefile                                        |    2 +-
+ fs/afs/proc.c                                      |    8 +-
+ fs/aio.c                                           |    4 +
+ fs/btrfs/file.c                                    |    3 -
+ fs/cachefiles/rdwr.c                               |    2 +
+ fs/cifs/file.c                                     |    3 -
+ fs/coda/file.c                                     |    2 +
+ fs/compat.c                                        |  184 --
+ fs/coredump.c                                      |    6 +-
+ fs/ecryptfs/miscdev.c                              |   14 +-
+ fs/ext4/mballoc.c                                  |    2 +-
+ fs/ext4/super.c                                    |    2 +-
+ fs/f2fs/acl.c                                      |    2 +-
+ fs/f2fs/dir.c                                      |    2 +-
+ fs/f2fs/file.c                                     |    4 +-
+ fs/fifo.c                                          |  153 --
+ fs/fuse/dev.c                                      |    2 +-
+ fs/fuse/file.c                                     |    2 -
+ fs/hpfs/file.c                                     |   36 +-
+ fs/inode.c                                         |    2 +-
+ fs/internal.h                                      |    5 +
+ fs/jbd2/journal.c                                  |    2 +-
+ fs/mount.h                                         |    7 +
+ fs/namespace.c                                     |  334 ++--
+ fs/ntfs/file.c                                     |    2 -
+ fs/ocfs2/file.c                                    |    9 +-
+ fs/pipe.c                                          |  457 ++---
+ fs/pnode.c                                         |   10 +-
+ fs/pnode.h                                         |    7 +-
+ fs/proc/base.c                                     |   16 +-
+ fs/proc/generic.c                                  |  203 ++-
+ fs/proc/inode.c                                    |    6 +-
+ fs/proc/internal.h                                 |    1 +
+ fs/proc/proc_devtree.c                             |    2 +-
+ fs/proc/root.c                                     |    2 +
+ fs/proc/self.c                                     |   46 +-
+ fs/read_write.c                                    |  205 ++-
+ fs/read_write.h                                    |    4 -
+ fs/reiserfs/file.c                                 |   61 +-
+ fs/reiserfs/procfs.c                               |   30 +-
+ fs/seq_file.c                                      |   18 +
+ fs/splice.c                                        |   14 +-
+ fs/xfs/xfs_file.c                                  |    3 -
+ include/linux/fs.h                                 |   19 +-
+ include/linux/pid_namespace.h                      |    1 +
+ include/linux/pipe_fs_i.h                          |   11 +-
+ include/linux/proc_fs.h                            |    8 +-
+ include/linux/profile.h                            |    4 +-
+ include/linux/seq_file.h                           |    1 +
+ include/scsi/scsi_host.h                           |    6 +-
+ ipc/util.c                                         |    2 +-
+ kernel/acct.c                                      |    2 +
+ kernel/exit.c                                      |    2 +-
+ kernel/irq/proc.c                                  |   14 +-
+ kernel/profile.c                                   |    4 +-
+ lib/notifier-error-inject.c                        |    4 +-
+ mm/filemap.c                                       |    2 -
+ mm/filemap_xip.c                                   |    3 -
+ net/8021q/vlanproc.c                               |    2 +-
+ net/atm/proc.c                                     |    2 +-
+ net/bluetooth/af_bluetooth.c                       |    2 +-
+ net/bluetooth/cmtp/capi.c                          |    2 +-
+ net/can/bcm.c                                      |    2 +-
+ net/can/proc.c                                     |    2 +-
+ net/core/neighbour.c                               |    2 +-
+ net/core/pktgen.c                                  |    6 +-
+ net/ipv4/netfilter/ipt_CLUSTERIP.c                 |    6 +-
+ net/ipv4/tcp_ipv4.c                                |    2 +-
+ net/ipv4/udp.c                                     |    2 +-
+ net/ipv6/proc.c                                    |    2 +-
+ net/netfilter/x_tables.c                           |    6 +-
+ net/netfilter/xt_hashlimit.c                       |    2 +-
+ net/netfilter/xt_recent.c                          |    6 +-
+ net/sunrpc/cache.c                                 |   24 +-
+ net/sunrpc/stats.c                                 |    2 +-
+ sound/core/info.c                                  |   26 +-
+ 244 files changed, 3290 insertions(+), 6888 deletions(-)
+ delete mode 100644 fs/fifo.c
+Merging pci/next (8332606 Merge branch 'pci/shuah-defines' into next)
+$ git merge pci/next
+Auto-merging include/linux/pci.h
+Auto-merging drivers/iommu/amd_iommu_init.c
+Auto-merging drivers/iommu/amd_iommu.c
+Merge made by the 'recursive' strategy.
+ drivers/iommu/amd_iommu.c          | 14 ++++++-------
+ drivers/iommu/amd_iommu_init.c     | 40 +++++++++++++++++++-------------------
+ drivers/iommu/amd_iommu_types.h    | 11 +----------
+ drivers/pci/pcie/aer/aerdrv_core.c |  4 +---
+ include/linux/pci.h                | 15 ++++++++++++++
+ 5 files changed, 44 insertions(+), 40 deletions(-)
+Merging hid/for-next (bf79571 Merge branch 'for-3.10/upstream' into for-next)
+$ git merge hid/for-next
+Auto-merging drivers/hid/hid-magicmouse.c
+Auto-merging drivers/hid/hid-ids.h
+Auto-merging drivers/hid/hid-core.c
+Merge made by the 'recursive' strategy.
+ .../ABI/testing/sysfs-driver-hid-roccat-isku       |  12 +-
+ .../ABI/testing/sysfs-driver-hid-roccat-konepure   | 105 +++++++
+ drivers/hid/Kconfig                                | 100 +++----
+ drivers/hid/Makefile                               |   4 +-
+ drivers/hid/hid-apple.c                            |   1 -
+ drivers/hid/hid-axff.c                             |   6 +-
+ drivers/hid/hid-core.c                             |  29 +-
+ drivers/hid/hid-dr.c                               |   8 +-
+ drivers/hid/hid-emsff.c                            |   6 +-
+ drivers/hid/hid-gaff.c                             |  10 +-
+ drivers/hid/hid-holtekff.c                         |   4 +-
+ drivers/hid/hid-ids.h                              |   3 +
+ drivers/hid/hid-input.c                            |  77 ++++++
+ drivers/hid/hid-kye.c                              |   4 +-
+ drivers/hid/hid-lenovo-tpkbd.c                     |   6 +-
+ drivers/hid/hid-lg2ff.c                            |   6 +-
+ drivers/hid/hid-lg3ff.c                            |   6 +-
+ drivers/hid/hid-lg4ff.c                            |  18 +-
+ drivers/hid/hid-lgff.c                             |   8 +-
+ drivers/hid/hid-logitech-dj.c                      |  53 +---
+ drivers/hid/hid-logitech-dj.h                      |   1 -
+ drivers/hid/hid-magicmouse.c                       |   1 -
+ drivers/hid/hid-multitouch.c                       | 273 ++++++++++++------
+ drivers/hid/hid-ntrig.c                            |  10 +-
+ drivers/hid/hid-picolcd.h                          |   6 +-
+ drivers/hid/hid-picolcd_backlight.c                |   4 +-
+ drivers/hid/hid-picolcd_cir.c                      |   2 -
+ drivers/hid/hid-picolcd_core.c                     |   8 +-
+ drivers/hid/hid-picolcd_debugfs.c                  |   2 -
+ drivers/hid/hid-picolcd_fb.c                       |  12 +-
+ drivers/hid/hid-picolcd_lcd.c                      |   4 +-
+ drivers/hid/hid-picolcd_leds.c                     |   4 +-
+ drivers/hid/hid-pl.c                               |   6 +-
+ drivers/hid/hid-prodikeys.c                        |   3 +-
+ drivers/hid/hid-roccat-isku.c                      |  17 +-
+ drivers/hid/hid-roccat-isku.h                      |   4 +-
+ drivers/hid/hid-roccat-konepure.c                  | 304 +++++++++++++++++++++
+ drivers/hid/hid-roccat-konepure.h                  |  72 +++++
+ drivers/hid/hid-roccat.c                           |   2 +-
+ drivers/hid/hid-sensor-hub.c                       |  12 +-
+ drivers/hid/hid-sjoy.c                             |   6 +-
+ drivers/hid/hid-speedlink.c                        |   2 -
+ drivers/hid/hid-steelseries.c                      |  16 +-
+ drivers/hid/hid-thingm.c                           |   1 -
+ drivers/hid/hid-tmff.c                             |   6 +-
+ drivers/hid/hid-wiimote-core.c                     |  43 ++-
+ drivers/hid/hid-zpff.c                             |   6 +-
+ drivers/hid/i2c-hid/i2c-hid.c                      |  31 +++
+ drivers/hid/usbhid/hid-core.c                      |  35 ++-
+ drivers/hid/usbhid/hid-pidff.c                     |  80 +++---
+ drivers/hid/usbhid/hiddev.c                        |   8 +-
+ drivers/hid/usbhid/usbhid.h                        |   3 -
+ include/linux/hid.h                                | 100 ++++++-
+ samples/hidraw/hid-example.c                       |   3 +-
+ 54 files changed, 1170 insertions(+), 383 deletions(-)
+ create mode 100644 Documentation/ABI/testing/sysfs-driver-hid-roccat-konepure
+ create mode 100644 drivers/hid/hid-roccat-konepure.c
+ create mode 100644 drivers/hid/hid-roccat-konepure.h
+Merging i2c/i2c/for-next (51d9570 i2c: Make the return type of i2c_del_mux_adapter() void)
+$ git merge i2c/i2c/for-next
+Removing include/linux/i2c-tegra.h
+Removing arch/arm/plat-samsung/include/plat/regs-iic.h
+Merge made by the 'recursive' strategy.
+ arch/arm/mach-s3c24xx/mach-rx1950.c           |   1 -
+ arch/arm/mach-tegra/board-dt-tegra20.c        |   2 -
+ arch/arm/plat-samsung/devs.c                  |   1 -
+ arch/arm/plat-samsung/include/plat/regs-iic.h |  56 ------
+ drivers/gpu/drm/gma500/oaktrail_hdmi_i2c.c    |   3 +-
+ drivers/i2c/busses/i2c-amd756-s4882.c         |   6 +-
+ drivers/i2c/busses/i2c-at91.c                 |   9 +-
+ drivers/i2c/busses/i2c-cbus-gpio.c            |   4 +-
+ drivers/i2c/busses/i2c-davinci.c              |  58 ++----
+ drivers/i2c/busses/i2c-gpio.c                 |  75 +++++---
+ drivers/i2c/busses/i2c-intel-mid.c            |   3 +-
+ drivers/i2c/busses/i2c-ismt.c                 |   2 +-
+ drivers/i2c/busses/i2c-mv64xxx.c              |   5 +-
+ drivers/i2c/busses/i2c-mxs.c                  |   5 +-
+ drivers/i2c/busses/i2c-nforce2-s4985.c        |   6 +-
+ drivers/i2c/busses/i2c-powermac.c             |  10 +-
+ drivers/i2c/busses/i2c-puv3.c                 |  10 +-
+ drivers/i2c/busses/i2c-pxa.c                  |  20 +--
+ drivers/i2c/busses/i2c-s3c2410.c              |  39 ++++-
+ drivers/i2c/busses/i2c-tegra.c                |  26 +--
+ drivers/i2c/busses/i2c-viperboard.c           |   5 +-
+ drivers/i2c/i2c-core.c                        | 243 ++++++++++++++++++++++----
+ drivers/i2c/i2c-mux.c                         |   9 +-
+ drivers/i2c/muxes/i2c-mux-gpio.c              |  17 +-
+ drivers/i2c/muxes/i2c-mux-pca954x.c           |   6 +-
+ drivers/media/pci/bt8xx/bttv-input.c          |   6 +-
+ drivers/media/pci/mantis/mantis_i2c.c         |   4 +-
+ drivers/net/ethernet/sfc/falcon.c             |   6 +-
+ drivers/staging/media/go7007/go7007-driver.c  |   7 +-
+ include/linux/i2c-mux.h                       |   2 +-
+ include/linux/i2c-tegra.h                     |  25 ---
+ include/linux/i2c.h                           |  50 +++++-
+ 32 files changed, 421 insertions(+), 300 deletions(-)
+ delete mode 100644 arch/arm/plat-samsung/include/plat/regs-iic.h
+ delete mode 100644 include/linux/i2c-tegra.h
+Merging jdelvare-hwmon/master (c662b7a hwmon: (lm75) Add support for the Dallas/Maxim DS7505)
+$ git merge jdelvare-hwmon/master
+Merge made by the 'recursive' strategy.
+ Documentation/hwmon/lm75 | 15 ++++----
+ drivers/hwmon/Kconfig    |  2 +-
+ drivers/hwmon/lm75.c     | 92 ++++++++++++++++++++++++++++++++++++++++++++----
+ 3 files changed, 94 insertions(+), 15 deletions(-)
+Merging hwmon-staging/hwmon-next (17b6609 MAINTAINERS: Add myself as maintainer for the NCT6775 driver)
+$ git merge hwmon-staging/hwmon-next
+Auto-merging drivers/hwmon/Kconfig
+Merge made by the 'recursive' strategy.
+ .../devicetree/bindings/hwmon/ntc_thermistor.txt   |   29 +
+ Documentation/hwmon/adt7410                        |   47 +-
+ Documentation/hwmon/lm25066                        |   34 +-
+ Documentation/hwmon/lm95234                        |   36 +
+ Documentation/hwmon/ltc2978                        |  143 +-
+ Documentation/hwmon/nct6775                        |  188 +
+ Documentation/hwmon/tmp401                         |   16 +-
+ MAINTAINERS                                        |    7 +
+ drivers/hwmon/Kconfig                              |   48 +-
+ drivers/hwmon/Makefile                             |    4 +
+ drivers/hwmon/abituguru.c                          |   11 +-
+ drivers/hwmon/abituguru3.c                         |   10 +-
+ drivers/hwmon/ad7314.c                             |    3 +-
+ drivers/hwmon/adm1021.c                            |   11 +-
+ drivers/hwmon/adm1026.c                            |   53 +-
+ drivers/hwmon/adm1029.c                            |    9 +-
+ drivers/hwmon/adm9240.c                            |    9 +-
+ drivers/hwmon/ads7871.c                            |   42 +-
+ drivers/hwmon/adt7310.c                            |  123 +
+ drivers/hwmon/adt7410.c                            |  442 +-
+ drivers/hwmon/adt7411.c                            |   10 +-
+ drivers/hwmon/adt7x10.c                            |  511 +++
+ drivers/hwmon/adt7x10.h                            |   37 +
+ drivers/hwmon/applesmc.c                           |    2 +-
+ drivers/hwmon/asb100.c                             |   23 +-
+ drivers/hwmon/asc7621.c                            |   56 +-
+ drivers/hwmon/coretemp.c                           |    3 +-
+ drivers/hwmon/da9052-hwmon.c                       |   14 +-
+ drivers/hwmon/da9055-hwmon.c                       |    4 +-
+ drivers/hwmon/dme1737.c                            |   68 +-
+ drivers/hwmon/f71805f.c                            |    3 +-
+ drivers/hwmon/fam15h_power.c                       |    4 +-
+ drivers/hwmon/fschmd.c                             |    9 +-
+ drivers/hwmon/gl518sm.c                            |    5 +-
+ drivers/hwmon/gpio-fan.c                           |  106 +-
+ drivers/hwmon/ibmaem.c                             |   21 +-
+ drivers/hwmon/ibmpex.c                             |   17 +-
+ drivers/hwmon/ina2xx.c                             |   16 +-
+ drivers/hwmon/it87.c                               |   24 +-
+ drivers/hwmon/k8temp.c                             |    4 +-
+ drivers/hwmon/lm78.c                               |   10 +-
+ drivers/hwmon/lm80.c                               |    5 +-
+ drivers/hwmon/lm85.c                               |    4 +-
+ drivers/hwmon/lm93.c                               |   74 +-
+ drivers/hwmon/lm95234.c                            |  769 ++++
+ drivers/hwmon/ltc4151.c                            |   12 +-
+ drivers/hwmon/ltc4215.c                            |   46 +-
+ drivers/hwmon/ltc4245.c                            |  116 +-
+ drivers/hwmon/ltc4261.c                            |   38 +-
+ drivers/hwmon/max6697.c                            |  209 +-
+ drivers/hwmon/mc13783-adc.c                        |   13 +-
+ drivers/hwmon/nct6775.c                            | 4228 ++++++++++++++++++++
+ drivers/hwmon/ntc_thermistor.c                     |  353 +-
+ drivers/hwmon/pc87360.c                            |   25 +-
+ drivers/hwmon/pc87427.c                            |   13 +-
+ drivers/hwmon/pmbus/Kconfig                        |    6 +-
+ drivers/hwmon/pmbus/lm25066.c                      |  414 +-
+ drivers/hwmon/pmbus/ltc2978.c                      |  170 +-
+ drivers/hwmon/s3c-hwmon.c                          |   19 +-
+ drivers/hwmon/sch56xx-common.c                     |   12 +-
+ drivers/hwmon/sis5595.c                            |    5 +-
+ drivers/hwmon/thmc50.c                             |    7 +-
+ drivers/hwmon/tmp102.c                             |    4 +-
+ drivers/hwmon/tmp401.c                             |   38 +-
+ drivers/hwmon/tmp421.c                             |    7 +-
+ drivers/hwmon/via686a.c                            |   47 +-
+ drivers/hwmon/vt1211.c                             |   23 +-
+ drivers/hwmon/vt8231.c                             |    5 +-
+ drivers/hwmon/w83627ehf.c                          |   31 +-
+ drivers/hwmon/w83781d.c                            |   36 +-
+ drivers/hwmon/w83791d.c                            |    4 +-
+ drivers/hwmon/w83792d.c                            |   13 +-
+ drivers/hwmon/w83793.c                             |    8 +-
+ drivers/hwmon/w83795.c                             |    9 +-
+ include/linux/platform_data/ntc_thermistor.h       |   10 +-
+ 75 files changed, 7490 insertions(+), 1495 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt
+ create mode 100644 Documentation/hwmon/lm95234
+ create mode 100644 Documentation/hwmon/nct6775
+ create mode 100644 drivers/hwmon/adt7310.c
+ create mode 100644 drivers/hwmon/adt7x10.c
+ create mode 100644 drivers/hwmon/adt7x10.h
+ create mode 100644 drivers/hwmon/lm95234.c
+ create mode 100644 drivers/hwmon/nct6775.c
+Merging v4l-dvb/master (7307913 Merge /home/v4l/v4l/patchwork)
+$ git merge v4l-dvb/master
+Resolved 'drivers/media/pci/bt8xx/bttv-input.c' using previous resolution.
+Resolved 'drivers/media/platform/Kconfig' using previous resolution.
+Resolved 'drivers/staging/media/go7007/go7007-driver.c' using previous resolution.
+Removing drivers/staging/media/solo6x10/v4l2.c
+Removing drivers/staging/media/solo6x10/v4l2-enc.c
+Auto-merging drivers/staging/media/solo6x10/solo6x10-tw28.h
+Auto-merging drivers/staging/media/solo6x10/solo6x10-tw28.c
+Auto-merging drivers/staging/media/solo6x10/solo6x10-regs.h
+Auto-merging drivers/staging/media/solo6x10/solo6x10-i2c.c
+Auto-merging drivers/staging/media/solo6x10/solo6x10-gpio.c
+Auto-merging drivers/staging/media/solo6x10/solo6x10-g723.c
+Auto-merging drivers/staging/media/solo6x10/solo6x10-enc.c
+Auto-merging drivers/staging/media/solo6x10/solo6x10-disp.c
+Removing drivers/staging/media/solo6x10/p2m.c
+Removing drivers/staging/media/solo6x10/osd-font.h
+Removing drivers/staging/media/solo6x10/offsets.h
+Removing drivers/staging/media/solo6x10/core.c
+Removing drivers/staging/media/go7007/wis-tw9903.c
+Removing drivers/staging/media/go7007/wis-tw2804.c
+Removing drivers/staging/media/go7007/wis-sony-tuner.c
+Removing drivers/staging/media/go7007/wis-saa7115.c
+Removing drivers/staging/media/go7007/wis-saa7113.c
+Removing drivers/staging/media/go7007/wis-i2c.h
+Removing drivers/staging/media/go7007/s2250-loader.h
+Removing drivers/staging/media/go7007/s2250-loader.c
+Auto-merging drivers/staging/media/go7007/go7007-driver.c
+CONFLICT (content): Merge conflict in drivers/staging/media/go7007/go7007-driver.c
+Removing drivers/media/usb/gspca/autogain_functions.h
+Auto-merging drivers/media/radio/radio-ma901.c
+Auto-merging drivers/media/platform/Kconfig
+CONFLICT (content): Merge conflict in drivers/media/platform/Kconfig
+Auto-merging drivers/media/pci/bt8xx/bttv-input.c
+CONFLICT (content): Merge conflict in drivers/media/pci/bt8xx/bttv-input.c
+Auto-merging drivers/media/i2c/uda1342.c
+Auto-merging drivers/media/i2c/ov7640.c
+Removing drivers/media/common/siano/smsdvb.c
+Auto-merging MAINTAINERS
+Removing Documentation/DocBook/media/v4l/vidioc-query-dv-preset.xml
+Removing Documentation/DocBook/media/v4l/vidioc-g-dv-preset.xml
+Removing Documentation/DocBook/media/v4l/vidioc-enum-dv-presets.xml
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master feb9f21] Merge remote-tracking branch 'v4l-dvb/master'
+$ git diff -M --stat --summary HEAD^..
+ Documentation/DocBook/media/dvb/dvbproperty.xml    |   52 +-
+ Documentation/DocBook/media/v4l/common.xml         |   14 -
+ Documentation/DocBook/media/v4l/compat.xml         |   21 +-
+ Documentation/DocBook/media/v4l/controls.xml       |    6 +
+ Documentation/DocBook/media/v4l/io.xml             |    6 +
+ .../DocBook/media/v4l/media-ioc-enum-entities.xml  |   10 +
+ Documentation/DocBook/media/v4l/v4l2.xml           |   19 +-
+ .../DocBook/media/v4l/vidioc-dbg-g-chip-ident.xml  |   14 +-
+ .../DocBook/media/v4l/vidioc-dbg-g-chip-name.xml   |  234 +++
+ .../DocBook/media/v4l/vidioc-dbg-g-register.xml    |   42 +-
+ .../DocBook/media/v4l/vidioc-enum-dv-presets.xml   |  240 ---
+ .../DocBook/media/v4l/vidioc-enuminput.xml         |    5 -
+ .../DocBook/media/v4l/vidioc-enumoutput.xml        |    5 -
+ .../DocBook/media/v4l/vidioc-g-dv-preset.xml       |  113 --
+ .../DocBook/media/v4l/vidioc-query-dv-preset.xml   |   78 -
+ Documentation/video4linux/CARDLIST.em28xx          |    3 +-
+ Documentation/video4linux/CARDLIST.tuner           |    3 +
+ MAINTAINERS                                        |   56 +-
+ arch/arm/mach-davinci/board-dm644x-evm.c           |    4 +-
+ arch/arm/mach-davinci/board-dm646x-evm.c           |    2 +-
+ arch/arm/mach-davinci/dm644x.c                     |    2 +-
+ arch/blackfin/mach-bf609/boards/ezkit.c            |    8 +-
+ drivers/media/common/saa7146/saa7146_video.c       |    4 +-
+ drivers/media/common/siano/Kconfig                 |   12 +
+ drivers/media/common/siano/Makefile                |    5 +
+ drivers/media/common/siano/sms-cards.c             |  115 +-
+ drivers/media/common/siano/sms-cards.h             |   14 +
+ drivers/media/common/siano/smscoreapi.c            | 1298 ++++++++++----
+ drivers/media/common/siano/smscoreapi.h            | 1007 +++++++----
+ drivers/media/common/siano/smsdvb-debugfs.c        |  551 ++++++
+ drivers/media/common/siano/smsdvb-main.c           | 1230 +++++++++++++
+ drivers/media/common/siano/smsdvb.c                | 1078 ------------
+ drivers/media/common/siano/smsdvb.h                |  130 ++
+ drivers/media/common/siano/smsendian.c             |   44 +-
+ drivers/media/common/siano/smsir.h                 |    1 -
+ drivers/media/dvb-core/dmxdev.c                    |    3 +-
+ drivers/media/dvb-core/dvb_demux.c                 |   24 +-
+ drivers/media/dvb-core/dvb_frontend.c              |  333 ++--
+ drivers/media/dvb-frontends/Kconfig                |    2 +-
+ drivers/media/dvb-frontends/a8293.h                |    5 +-
+ drivers/media/dvb-frontends/af9013.h               |    4 +-
+ drivers/media/dvb-frontends/af9033.c               |  138 +-
+ drivers/media/dvb-frontends/af9033.h               |   20 +-
+ drivers/media/dvb-frontends/af9033_priv.h          | 1506 +++++++++++++++-
+ drivers/media/dvb-frontends/atbm8830.h             |    4 +-
+ drivers/media/dvb-frontends/au8522.h               |    4 +-
+ drivers/media/dvb-frontends/au8522_decoder.c       |  125 +-
+ drivers/media/dvb-frontends/au8522_priv.h          |    6 +-
+ drivers/media/dvb-frontends/cx22702.h              |    4 +-
+ drivers/media/dvb-frontends/cx24113.h              |    5 +-
+ drivers/media/dvb-frontends/cx24116.h              |    4 +-
+ drivers/media/dvb-frontends/cx24123.h              |    4 +-
+ drivers/media/dvb-frontends/cxd2820r.h             |    4 +-
+ drivers/media/dvb-frontends/dib3000mc.h            |    5 +-
+ drivers/media/dvb-frontends/dib7000m.h             |    5 +-
+ drivers/media/dvb-frontends/dib7000p.h             |    5 +-
+ drivers/media/dvb-frontends/drxd.h                 |    4 +-
+ drivers/media/dvb-frontends/drxk.h                 |    4 +-
+ drivers/media/dvb-frontends/drxk_hard.c            |  309 +++-
+ drivers/media/dvb-frontends/drxk_hard.h            |    2 +
+ drivers/media/dvb-frontends/drxk_map.h             |    3 +
+ drivers/media/dvb-frontends/ds3000.h               |    4 +-
+ drivers/media/dvb-frontends/dvb_dummy_fe.h         |    4 +-
+ drivers/media/dvb-frontends/ec100.h                |    4 +-
+ drivers/media/dvb-frontends/hd29l2.h               |    4 +-
+ drivers/media/dvb-frontends/it913x-fe.h            |    4 +-
+ drivers/media/dvb-frontends/ix2505v.h              |    4 +-
+ drivers/media/dvb-frontends/lg2160.h               |    4 +-
+ drivers/media/dvb-frontends/lgdt3305.h             |    4 +-
+ drivers/media/dvb-frontends/lgs8gl5.h              |    4 +-
+ drivers/media/dvb-frontends/lgs8gxx.h              |    4 +-
+ drivers/media/dvb-frontends/lnbh24.h               |    5 +-
+ drivers/media/dvb-frontends/lnbp21.h               |    5 +-
+ drivers/media/dvb-frontends/lnbp22.h               |    5 +-
+ drivers/media/dvb-frontends/m88rs2000.h            |    4 +-
+ drivers/media/dvb-frontends/mb86a20s.c             |  296 +++-
+ drivers/media/dvb-frontends/mb86a20s.h             |   12 +-
+ drivers/media/dvb-frontends/rtl2830.h              |    4 +-
+ drivers/media/dvb-frontends/rtl2832.h              |    4 +-
+ drivers/media/dvb-frontends/s5h1409.h              |    4 +-
+ drivers/media/dvb-frontends/s5h1411.h              |    4 +-
+ drivers/media/dvb-frontends/s5h1432.h              |    4 +-
+ drivers/media/dvb-frontends/s921.h                 |    4 +-
+ drivers/media/dvb-frontends/si21xx.h               |    4 +-
+ drivers/media/dvb-frontends/stb6000.h              |    4 +-
+ drivers/media/dvb-frontends/stv0288.h              |    4 +-
+ drivers/media/dvb-frontends/stv0367.h              |    4 +-
+ drivers/media/dvb-frontends/stv0900.h              |    4 +-
+ drivers/media/dvb-frontends/stv090x.c              |   22 +-
+ drivers/media/dvb-frontends/stv6110.h              |    4 +-
+ drivers/media/dvb-frontends/tda10048.h             |    4 +-
+ drivers/media/dvb-frontends/tda10071.h             |    4 +-
+ drivers/media/dvb-frontends/tda18271c2dd.h         |    6 +-
+ drivers/media/dvb-frontends/ts2020.h               |    4 +-
+ drivers/media/dvb-frontends/zl10036.h              |    4 +-
+ drivers/media/dvb-frontends/zl10039.h              |    5 +-
+ drivers/media/i2c/Kconfig                          |   66 +-
+ drivers/media/i2c/Makefile                         |    8 +-
+ drivers/media/i2c/ad9389b.c                        |    2 +-
+ drivers/media/i2c/adp1653.c                        |    4 +-
+ drivers/media/i2c/adv7183.c                        |    2 +-
+ drivers/media/i2c/adv7604.c                        |    2 +-
+ drivers/media/i2c/ak881x.c                         |    2 +-
+ drivers/media/i2c/cs5345.c                         |    2 +-
+ drivers/media/i2c/cx25840/cx25840-core.c           |    6 +-
+ drivers/media/i2c/ir-kbd-i2c.c                     |    1 +
+ drivers/media/i2c/m52790.c                         |    2 +-
+ drivers/media/i2c/msp3400-driver.c                 |    4 +-
+ drivers/media/i2c/mt9m032.c                        |    2 +-
+ drivers/media/i2c/mt9v011.c                        |    2 +-
+ .../go7007/wis-ov7640.c => media/i2c/ov7640.c}     |   70 +-
+ drivers/media/i2c/ov7670.c                         |    2 +-
+ drivers/media/i2c/saa6588.c                        |    2 +-
+ drivers/media/i2c/saa7115.c                        |   80 +-
+ drivers/media/i2c/saa7127.c                        |    2 +-
+ drivers/media/i2c/saa717x.c                        |    4 +-
+ drivers/media/i2c/smiapp/smiapp-core.c             |    4 +-
+ drivers/media/i2c/soc_camera/Kconfig               |    2 -
+ drivers/media/i2c/soc_camera/mt9m001.c             |    2 +-
+ drivers/media/i2c/soc_camera/mt9m111.c             |   11 +-
+ drivers/media/i2c/soc_camera/mt9t031.c             |    2 +-
+ drivers/media/i2c/soc_camera/mt9t112.c             |    2 +-
+ drivers/media/i2c/soc_camera/mt9v022.c             |   21 +-
+ drivers/media/i2c/soc_camera/ov2640.c              |    2 +-
+ drivers/media/i2c/soc_camera/ov5642.c              |    2 +-
+ drivers/media/i2c/soc_camera/ov6650.c              |    2 +-
+ drivers/media/i2c/soc_camera/ov772x.c              |    2 +-
+ drivers/media/i2c/soc_camera/ov9640.c              |    2 +-
+ drivers/media/i2c/soc_camera/ov9740.c              |    2 +-
+ drivers/media/i2c/soc_camera/rj54n1cb0c.c          |    2 +-
+ drivers/media/i2c/soc_camera/tw9910.c              |    2 +-
+ drivers/media/i2c/sony-btf-mpx.c                   |  399 +++++
+ drivers/media/i2c/tda7432.c                        |  276 ++-
+ drivers/media/i2c/tda9840.c                        |    2 +-
+ drivers/media/i2c/ths7303.c                        |  351 +++-
+ drivers/media/i2c/tvaudio.c                        |    6 +-
+ drivers/media/i2c/tvp514x.c                        |  163 +-
+ drivers/media/i2c/tvp5150.c                        |    2 +-
+ drivers/media/i2c/tvp7002.c                        |  184 +-
+ drivers/media/i2c/tw2804.c                         |  453 +++++
+ drivers/media/i2c/tw9903.c                         |  279 +++
+ drivers/media/i2c/tw9906.c                         |  247 +++
+ .../go7007/wis-uda1342.c => media/i2c/uda1342.c}   |   83 +-
+ drivers/media/i2c/upd64031a.c                      |    4 +-
+ drivers/media/i2c/upd64083.c                       |    2 +-
+ drivers/media/i2c/vp27smpx.c                       |    2 +-
+ drivers/media/i2c/vs6624.c                         |    2 +-
+ drivers/media/i2c/wm8775.c                         |    2 +-
+ drivers/media/media-device.c                       |  102 +-
+ drivers/media/media-devnode.c                      |   31 +-
+ drivers/media/mmc/siano/smssdio.c                  |   27 +-
+ drivers/media/parport/pms.c                        |    4 +-
+ drivers/media/pci/bt8xx/bttv-cards.c               |   21 +-
+ drivers/media/pci/bt8xx/bttv-driver.c              | 1226 ++++++-------
+ drivers/media/pci/bt8xx/bttv-i2c.c                 |    8 +
+ drivers/media/pci/bt8xx/bttv-input.c               |   30 +-
+ drivers/media/pci/bt8xx/bttv.h                     |    3 +
+ drivers/media/pci/bt8xx/bttvp.h                    |   38 +-
+ drivers/media/pci/cx18/cx18-av-core.c              |    6 +-
+ drivers/media/pci/cx18/cx18-driver.c               |    2 +-
+ drivers/media/pci/cx18/cx18-ioctl.c                |   52 +-
+ drivers/media/pci/cx18/cx18-ioctl.h                |    4 +-
+ drivers/media/pci/cx23885/altera-ci.h              |    5 +-
+ drivers/media/pci/cx23885/cx23885-417.c            |   10 +-
+ drivers/media/pci/cx23885/cx23885-ioctl.c          |    9 +-
+ drivers/media/pci/cx23885/cx23885-ioctl.h          |    2 +-
+ drivers/media/pci/cx23885/cx23885-video.c          |   14 +-
+ drivers/media/pci/cx23885/cx23885.h                |    2 +-
+ drivers/media/pci/cx23885/cx23888-ir.c             |    2 +-
+ drivers/media/pci/cx25821/cx25821-audio-upstream.c |   21 +-
+ drivers/media/pci/cx25821/cx25821-video.c          |   14 +-
+ drivers/media/pci/cx25821/cx25821-video.h          |   10 +-
+ drivers/media/pci/cx88/cx88-blackbird.c            |    8 +-
+ drivers/media/pci/cx88/cx88-video.c                |   25 +-
+ drivers/media/pci/cx88/cx88.h                      |    2 +-
+ drivers/media/pci/ivtv/ivtv-driver.c               |    4 +-
+ drivers/media/pci/ivtv/ivtv-firmware.c             |    4 +-
+ drivers/media/pci/ivtv/ivtv-gpio.c                 |    2 +-
+ drivers/media/pci/ivtv/ivtv-ioctl.c                |   57 +-
+ drivers/media/pci/ivtv/ivtv-ioctl.h                |    6 +-
+ drivers/media/pci/ivtv/ivtvfb.c                    |    3 +-
+ drivers/media/pci/meye/meye.c                      |    2 +-
+ drivers/media/pci/saa7134/saa7134-empress.c        |    2 +-
+ drivers/media/pci/saa7134/saa7134-video.c          |   22 +-
+ drivers/media/pci/saa7134/saa7134.h                |    2 +-
+ drivers/media/pci/saa7146/mxb.c                    |    9 +-
+ drivers/media/pci/saa7164/saa7164-encoder.c        |   14 +-
+ drivers/media/pci/saa7164/saa7164-vbi.c            |   12 +-
+ drivers/media/pci/sta2x11/sta2x11_vip.c            |   18 +-
+ drivers/media/pci/ttpci/av7110_v4l.c               |    4 +-
+ drivers/media/pci/zoran/zoran_driver.c             |    4 +-
+ drivers/media/platform/Kconfig                     |    2 +-
+ drivers/media/platform/blackfin/bfin_capture.c     |   13 +-
+ drivers/media/platform/davinci/dm355_ccdc.c        |   10 +-
+ drivers/media/platform/davinci/dm355_ccdc_regs.h   |    2 +-
+ drivers/media/platform/davinci/dm644x_ccdc.c       |   13 +-
+ drivers/media/platform/davinci/dm644x_ccdc_regs.h  |    2 +-
+ drivers/media/platform/davinci/isif.c              |    2 +-
+ drivers/media/platform/davinci/isif_regs.h         |    4 +-
+ drivers/media/platform/davinci/vpbe.c              |   16 +-
+ drivers/media/platform/davinci/vpbe_display.c      |   17 +-
+ drivers/media/platform/davinci/vpbe_osd.c          |    3 +
+ drivers/media/platform/davinci/vpbe_venc.c         |   11 +-
+ drivers/media/platform/davinci/vpfe_capture.c      |   62 +-
+ drivers/media/platform/davinci/vpif.c              |   10 +-
+ drivers/media/platform/davinci/vpif.h              |    2 +-
+ drivers/media/platform/davinci/vpif_capture.c      |   12 +-
+ drivers/media/platform/davinci/vpif_display.c      |   16 +-
+ drivers/media/platform/fsl-viu.c                   |    6 +-
+ drivers/media/platform/marvell-ccic/mcam-core.c    |    4 +-
+ drivers/media/platform/omap/omap_vout.c            |   14 +-
+ drivers/media/platform/s3c-camif/camif-capture.c   |   16 +-
+ drivers/media/platform/s5p-fimc/fimc-capture.c     |    1 +
+ drivers/media/platform/s5p-fimc/fimc-lite.c        |    1 +
+ drivers/media/platform/s5p-g2d/g2d.c               |   31 +-
+ drivers/media/platform/s5p-mfc/s5p_mfc.c           |    2 +
+ drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c    |   12 +-
+ drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c    |   12 +-
+ drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c    |  103 +-
+ drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c    |  112 +-
+ drivers/media/platform/s5p-tv/hdmi_drv.c           |  129 +-
+ drivers/media/platform/s5p-tv/hdmiphy_drv.c        |   55 +-
+ drivers/media/platform/s5p-tv/mixer_video.c        |   52 +-
+ drivers/media/platform/sh_veu.c                    |   20 +-
+ drivers/media/platform/sh_vou.c                    |   27 +-
+ drivers/media/platform/soc_camera/atmel-isi.c      |    1 +
+ drivers/media/platform/soc_camera/mx1_camera.c     |   13 +-
+ drivers/media/platform/soc_camera/mx2_camera.c     |    1 +
+ drivers/media/platform/soc_camera/mx3_camera.c     |    1 +
+ drivers/media/platform/soc_camera/omap1_camera.c   |    6 +-
+ drivers/media/platform/soc_camera/pxa_camera.c     |    8 +-
+ .../platform/soc_camera/sh_mobile_ceu_camera.c     |   10 +-
+ drivers/media/platform/soc_camera/sh_mobile_csi2.c |    9 +-
+ drivers/media/platform/soc_camera/soc_camera.c     |    6 +-
+ drivers/media/platform/timblogiw.c                 |    8 +-
+ drivers/media/platform/via-camera.c                |    2 +-
+ drivers/media/platform/vino.c                      |   10 +-
+ drivers/media/platform/vivi.c                      |   10 +
+ drivers/media/radio/dsbr100.c                      |    4 +-
+ drivers/media/radio/radio-cadet.c                  |   48 +-
+ drivers/media/radio/radio-isa.c                    |   15 +-
+ drivers/media/radio/radio-keene.c                  |    8 +-
+ drivers/media/radio/radio-ma901.c                  |    4 +-
+ drivers/media/radio/radio-miropcm20.c              |   12 +-
+ drivers/media/radio/radio-mr800.c                  |   14 +-
+ drivers/media/radio/radio-rtrack2.c                |    5 +-
+ drivers/media/radio/radio-sf16fmi.c                |    4 +-
+ drivers/media/radio/radio-si4713.c                 |   61 +-
+ drivers/media/radio/radio-tea5764.c                |    4 +-
+ drivers/media/radio/radio-tea5777.c                |    9 +-
+ drivers/media/radio/radio-timb.c                   |    4 +-
+ drivers/media/radio/radio-wl1273.c                 |    4 +-
+ drivers/media/radio/si470x/radio-si470x-common.c   |    4 +-
+ drivers/media/radio/si4713-i2c.c                   |    5 +-
+ drivers/media/radio/tef6862.c                      |    4 +-
+ drivers/media/radio/wl128x/fmdrv_v4l2.c            |    8 +-
+ drivers/media/rc/imon.c                            |   28 +-
+ drivers/media/rc/ir-jvc-decoder.c                  |    2 +-
+ drivers/media/rc/ir-lirc-codec.c                   |    2 +-
+ drivers/media/rc/ir-mce_kbd-decoder.c              |    2 +-
+ drivers/media/rc/ir-nec-decoder.c                  |    2 +-
+ drivers/media/rc/ir-raw.c                          |    2 +-
+ drivers/media/rc/ir-rc5-decoder.c                  |    6 +-
+ drivers/media/rc/ir-rc5-sz-decoder.c               |    2 +-
+ drivers/media/rc/ir-rc6-decoder.c                  |    2 +-
+ drivers/media/rc/ir-rx51.c                         |    4 +-
+ drivers/media/rc/ir-sanyo-decoder.c                |    2 +-
+ drivers/media/rc/ir-sony-decoder.c                 |    8 +-
+ drivers/media/rc/rc-core-priv.h                    |    1 -
+ drivers/media/rc/rc-main.c                         |   46 +-
+ drivers/media/rc/redrat3.c                         |  457 ++---
+ drivers/media/tuners/Kconfig                       |    7 +
+ drivers/media/tuners/Makefile                      |    1 +
+ drivers/media/tuners/e4000.h                       |    4 +-
+ drivers/media/tuners/fc0011.h                      |    4 +-
+ drivers/media/tuners/fc0012.h                      |    4 +-
+ drivers/media/tuners/fc0013.h                      |    4 +-
+ drivers/media/tuners/fc2580.h                      |    4 +-
+ drivers/media/tuners/it913x.c                      |  447 +++++
+ drivers/media/tuners/it913x.h                      |   45 +
+ drivers/media/tuners/it913x_priv.h                 |   78 +
+ drivers/media/tuners/max2165.h                     |    5 +-
+ drivers/media/tuners/mc44s803.h                    |    5 +-
+ drivers/media/tuners/mxl5005s.h                    |    5 +-
+ drivers/media/tuners/tda18212.h                    |    4 +-
+ drivers/media/tuners/tda18218.h                    |    4 +-
+ drivers/media/tuners/tua9001.h                     |    4 +-
+ drivers/media/tuners/tuner-types.c                 |   69 +
+ drivers/media/tuners/tuner-xc2028.c                |    3 +-
+ drivers/media/tuners/xc5000.c                      |   20 +-
+ drivers/media/tuners/xc5000.h                      |    4 +-
+ drivers/media/usb/au0828/au0828-core.c             |   61 +-
+ drivers/media/usb/au0828/au0828-video.c            |  299 ++--
+ drivers/media/usb/au0828/au0828.h                  |    7 +
+ drivers/media/usb/cx231xx/cx231xx-417.c            | 1182 ++++++-------
+ drivers/media/usb/cx231xx/cx231xx-audio.c          |    8 +-
+ drivers/media/usb/cx231xx/cx231xx-avcore.c         |   85 +-
+ drivers/media/usb/cx231xx/cx231xx-cards.c          |   59 +-
+ drivers/media/usb/cx231xx/cx231xx-core.c           |    2 +-
+ drivers/media/usb/cx231xx/cx231xx-dvb.c            |    4 +-
+ drivers/media/usb/cx231xx/cx231xx-pcb-cfg.c        |    2 +-
+ drivers/media/usb/cx231xx/cx231xx-pcb-cfg.h        |    5 -
+ drivers/media/usb/cx231xx/cx231xx-vbi.c            |   25 +-
+ drivers/media/usb/cx231xx/cx231xx-video.c          |  601 ++-----
+ drivers/media/usb/cx231xx/cx231xx.h                |   55 +-
+ drivers/media/usb/dvb-usb-v2/Kconfig               |    1 +
+ drivers/media/usb/dvb-usb-v2/af9015.c              |   79 +-
+ drivers/media/usb/dvb-usb-v2/af9015.h              |    2 +
+ drivers/media/usb/dvb-usb-v2/af9035.c              |  600 ++++---
+ drivers/media/usb/dvb-usb-v2/af9035.h              |   49 +-
+ drivers/media/usb/dvb-usb-v2/anysee.c              |   46 +-
+ drivers/media/usb/dvb-usb-v2/anysee.h              |    3 +-
+ drivers/media/usb/dvb-usb-v2/cypress_firmware.c    |    5 +-
+ drivers/media/usb/dvb-usb-v2/dvb_usb.h             |    9 +-
+ drivers/media/usb/dvb-usb-v2/dvb_usb_core.c        |  311 ++--
+ drivers/media/usb/dvb-usb-v2/dvb_usb_urb.c         |   43 +-
+ drivers/media/usb/dvb-usb-v2/it913x.c              |    1 +
+ drivers/media/usb/dvb-usb-v2/lmedm04.c             |    8 +-
+ drivers/media/usb/dvb-usb-v2/mxl111sf-demod.h      |    4 +-
+ drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.h      |    5 +-
+ drivers/media/usb/dvb-usb-v2/rtl28xxu.c            |    2 +
+ drivers/media/usb/dvb-usb-v2/usb_urb.c             |   36 +-
+ drivers/media/usb/dvb-usb/cinergyT2-fe.c           |    3 +-
+ drivers/media/usb/dvb-usb/dibusb-common.c          |    5 +-
+ drivers/media/usb/dvb-usb/dw2102.c                 |   19 +-
+ drivers/media/usb/dvb-usb/m920x.c                  |    4 +-
+ drivers/media/usb/em28xx/Kconfig                   |    1 +
+ drivers/media/usb/em28xx/Makefile                  |    2 +-
+ drivers/media/usb/em28xx/em28xx-camera.c           |  434 +++++
+ drivers/media/usb/em28xx/em28xx-cards.c            |  343 ++--
+ drivers/media/usb/em28xx/em28xx-core.c             |   45 +-
+ drivers/media/usb/em28xx/em28xx-dvb.c              |  114 +-
+ drivers/media/usb/em28xx/em28xx-i2c.c              |  691 +++++---
+ drivers/media/usb/em28xx/em28xx-input.c            |    5 +-
+ drivers/media/usb/em28xx/em28xx-reg.h              |   35 +-
+ drivers/media/usb/em28xx/em28xx-video.c            |  415 +++--
+ drivers/media/usb/em28xx/em28xx.h                  |  231 +--
+ drivers/media/usb/gspca/autogain_functions.h       |  183 --
+ drivers/media/usb/gspca/benq.c                     |    2 +-
+ drivers/media/usb/gspca/conex.c                    |   12 +-
+ drivers/media/usb/gspca/cpia1.c                    |   33 +-
+ drivers/media/usb/gspca/etoms.c                    |   12 +-
+ drivers/media/usb/gspca/gl860/gl860.c              |  224 +--
+ drivers/media/usb/gspca/gspca.c                    |  240 +--
+ drivers/media/usb/gspca/gspca.h                    |   70 +-
+ drivers/media/usb/gspca/jeilinj.c                  |    2 +-
+ drivers/media/usb/gspca/konica.c                   |   28 +-
+ drivers/media/usb/gspca/m5602/m5602_bridge.h       |   27 +-
+ drivers/media/usb/gspca/m5602/m5602_core.c         |   22 +-
+ drivers/media/usb/gspca/m5602/m5602_mt9m111.c      |  404 ++---
+ drivers/media/usb/gspca/m5602/m5602_mt9m111.h      |    2 +
+ drivers/media/usb/gspca/m5602/m5602_ov7660.c       |  312 +---
+ drivers/media/usb/gspca/m5602/m5602_ov7660.h       |    3 +
+ drivers/media/usb/gspca/m5602/m5602_ov9650.c       |  469 ++---
+ drivers/media/usb/gspca/m5602/m5602_ov9650.h       |    2 +
+ drivers/media/usb/gspca/m5602/m5602_po1030.c       |  471 ++---
+ drivers/media/usb/gspca/m5602/m5602_po1030.h       |    2 +
+ drivers/media/usb/gspca/m5602/m5602_s5k4aa.c       |  352 +---
+ drivers/media/usb/gspca/m5602/m5602_s5k4aa.h       |    2 +
+ drivers/media/usb/gspca/m5602/m5602_s5k83a.c       |  291 +---
+ drivers/media/usb/gspca/m5602/m5602_s5k83a.h       |    9 +-
+ drivers/media/usb/gspca/m5602/m5602_sensor.h       |    3 +
+ drivers/media/usb/gspca/mr97310a.c                 |    8 +-
+ drivers/media/usb/gspca/ov519.c                    |   81 +-
+ drivers/media/usb/gspca/ov534.c                    |    2 +-
+ drivers/media/usb/gspca/pac207.c                   |    2 +-
+ drivers/media/usb/gspca/pac7302.c                  |    9 +-
+ drivers/media/usb/gspca/pac7311.c                  |    5 +-
+ drivers/media/usb/gspca/pac_common.h               |    2 +-
+ drivers/media/usb/gspca/sn9c2028.c                 |    4 +-
+ drivers/media/usb/gspca/sn9c20x.c                  |    2 +-
+ drivers/media/usb/gspca/sonixb.c                   |   22 -
+ drivers/media/usb/gspca/sonixj.c                   |  556 ++----
+ drivers/media/usb/gspca/spca1528.c                 |    4 +-
+ drivers/media/usb/gspca/spca500.c                  |   36 +-
+ drivers/media/usb/gspca/spca501.c                  |   44 +-
+ drivers/media/usb/gspca/spca505.c                  |   42 +-
+ drivers/media/usb/gspca/spca508.c                  |   41 +-
+ drivers/media/usb/gspca/spca561.c                  |   70 +-
+ drivers/media/usb/gspca/sq905.c                    |    2 +-
+ drivers/media/usb/gspca/sq905c.c                   |    6 +-
+ drivers/media/usb/gspca/sq930x.c                   |    4 +-
+ drivers/media/usb/gspca/stv0680.c                  |   14 +-
+ drivers/media/usb/gspca/stv06xx/stv06xx.c          |   17 +-
+ drivers/media/usb/gspca/stv06xx/stv06xx_hdcs.c     |    8 +-
+ drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.c   |   14 +-
+ drivers/media/usb/gspca/stv06xx/stv06xx_st6422.c   |    2 +
+ drivers/media/usb/gspca/stv06xx/stv06xx_vv6410.c   |   10 +-
+ drivers/media/usb/gspca/sunplus.c                  |   27 +-
+ drivers/media/usb/gspca/vc032x.c                   |    9 +-
+ drivers/media/usb/gspca/w996Xcf.c                  |    5 +-
+ drivers/media/usb/gspca/zc3xx.c                    |    3 +-
+ drivers/media/usb/hdpvr/hdpvr-core.c               |    1 +
+ drivers/media/usb/hdpvr/hdpvr-video.c              |    7 +-
+ drivers/media/usb/pvrusb2/pvrusb2-hdw.c            |    2 +-
+ drivers/media/usb/pvrusb2/pvrusb2-hdw.h            |    2 +-
+ drivers/media/usb/pvrusb2/pvrusb2-v4l2.c           |   10 +-
+ drivers/media/usb/pwc/pwc-if.c                     |    1 +
+ drivers/media/usb/s2255/s2255drv.c                 |  441 +++--
+ drivers/media/usb/siano/smsusb.c                   |  158 +-
+ drivers/media/usb/stk1160/stk1160-v4l.c            |   14 +-
+ drivers/media/usb/stkwebcam/stk-webcam.c           |  309 ++--
+ drivers/media/usb/stkwebcam/stk-webcam.h           |    8 +-
+ drivers/media/usb/tlg2300/pd-common.h              |   26 +-
+ drivers/media/usb/tlg2300/pd-main.c                |   16 +-
+ drivers/media/usb/tlg2300/pd-radio.c               |  229 +--
+ drivers/media/usb/tlg2300/pd-video.c               |  303 ++--
+ drivers/media/usb/tm6000/tm6000-video.c            |   16 +-
+ drivers/media/usb/usbvision/usbvision-video.c      |   10 +-
+ drivers/media/usb/uvc/uvc_ctrl.c                   |    2 +-
+ drivers/media/usb/uvc/uvc_queue.c                  |    1 +
+ drivers/media/v4l2-core/Kconfig                    |    1 +
+ drivers/media/v4l2-core/tuner-core.c               |   27 +-
+ drivers/media/v4l2-core/v4l2-common.c              |   55 +-
+ drivers/media/v4l2-core/v4l2-compat-ioctl32.c      |    4 -
+ drivers/media/v4l2-core/v4l2-ctrls.c               |   10 +-
+ drivers/media/v4l2-core/v4l2-dev.c                 |    9 +-
+ drivers/media/v4l2-core/v4l2-ioctl.c               |  240 ++-
+ drivers/media/v4l2-core/v4l2-mem2mem.c             |   34 +-
+ drivers/media/v4l2-core/videobuf2-core.c           |   12 +-
+ drivers/media/v4l2-core/videobuf2-dma-contig.c     |    5 +-
+ drivers/media/v4l2-core/videobuf2-dma-sg.c         |   22 +-
+ drivers/media/v4l2-core/videobuf2-vmalloc.c        |    4 +-
+ drivers/staging/media/as102/Makefile               |    2 +-
+ .../staging/media/davinci_vpfe/davinci-vpfe-mc.txt |    2 +-
+ drivers/staging/media/davinci_vpfe/dm365_ipipe.c   |    2 +-
+ drivers/staging/media/davinci_vpfe/dm365_ipipeif.c |    3 +-
+ drivers/staging/media/davinci_vpfe/dm365_isif.c    |   10 +-
+ drivers/staging/media/davinci_vpfe/dm365_resizer.c |    2 +-
+ .../staging/media/davinci_vpfe/vpfe_mc_capture.c   |   24 +-
+ drivers/staging/media/davinci_vpfe/vpfe_video.c    |   26 +-
+ drivers/staging/media/davinci_vpfe/vpfe_video.h    |    2 +-
+ drivers/staging/media/dt3155v4l/dt3155v4l.c        |    4 +-
+ drivers/staging/media/go7007/Kconfig               |  102 +-
+ drivers/staging/media/go7007/Makefile              |   21 +-
+ drivers/staging/media/go7007/README                |  142 +-
+ drivers/staging/media/go7007/go7007-driver.c       |  384 ++--
+ drivers/staging/media/go7007/go7007-fw.c           |   88 +-
+ drivers/staging/media/go7007/go7007-i2c.c          |   21 +-
+ drivers/staging/media/go7007/go7007-loader.c       |  144 ++
+ drivers/staging/media/go7007/go7007-priv.h         |  104 +-
+ drivers/staging/media/go7007/go7007-usb.c          |  394 +++--
+ drivers/staging/media/go7007/go7007-v4l2.c         | 1747 +++++--------------
+ drivers/staging/media/go7007/go7007.h              |   74 -
+ drivers/staging/media/go7007/s2250-board.c         |  171 +-
+ drivers/staging/media/go7007/s2250-loader.c        |  169 --
+ drivers/staging/media/go7007/s2250-loader.h        |   24 -
+ drivers/staging/media/go7007/saa7134-go7007.c      |  171 +-
+ drivers/staging/media/go7007/snd-go7007.c          |   11 +-
+ drivers/staging/media/go7007/wis-i2c.h             |   42 -
+ drivers/staging/media/go7007/wis-saa7113.c         |  324 ----
+ drivers/staging/media/go7007/wis-saa7115.c         |  457 -----
+ drivers/staging/media/go7007/wis-sony-tuner.c      |  707 --------
+ drivers/staging/media/go7007/wis-tw2804.c          |  348 ----
+ drivers/staging/media/go7007/wis-tw9903.c          |  328 ----
+ drivers/staging/media/lirc/lirc_sir.c              |   10 -
+ drivers/staging/media/solo6x10/Kconfig             |    3 +-
+ drivers/staging/media/solo6x10/Makefile            |    4 +-
+ drivers/staging/media/solo6x10/TODO                |   39 +-
+ drivers/staging/media/solo6x10/core.c              |  321 ----
+ drivers/staging/media/solo6x10/offsets.h           |   74 -
+ drivers/staging/media/solo6x10/osd-font.h          |  154 --
+ drivers/staging/media/solo6x10/p2m.c               |  306 ----
+ drivers/staging/media/solo6x10/solo6x10-core.c     |  709 ++++++++
+ .../media/solo6x10/{disp.c => solo6x10-disp.c}     |  129 +-
+ drivers/staging/media/solo6x10/solo6x10-eeprom.c   |  154 ++
+ .../media/solo6x10/{enc.c => solo6x10-enc.c}       |  239 ++-
+ .../media/solo6x10/{g723.c => solo6x10-g723.c}     |   94 +-
+ .../media/solo6x10/{gpio.c => solo6x10-gpio.c}     |   13 +-
+ .../media/solo6x10/{i2c.c => solo6x10-i2c.c}       |   26 +-
+ drivers/staging/media/solo6x10/solo6x10-jpeg.h     |   94 +-
+ drivers/staging/media/solo6x10/solo6x10-offsets.h  |   85 +
+ drivers/staging/media/solo6x10/solo6x10-p2m.c      |  333 ++++
+ .../solo6x10/{registers.h => solo6x10-regs.h}      |   88 +-
+ .../media/solo6x10/{tw28.c => solo6x10-tw28.c}     |  187 +-
+ .../media/solo6x10/{tw28.h => solo6x10-tw28.h}     |   12 +-
+ drivers/staging/media/solo6x10/solo6x10-v4l2-enc.c | 1363 +++++++++++++++
+ drivers/staging/media/solo6x10/solo6x10-v4l2.c     |  734 ++++++++
+ drivers/staging/media/solo6x10/solo6x10.h          |  265 ++-
+ drivers/staging/media/solo6x10/v4l2-enc.c          | 1829 --------------------
+ drivers/staging/media/solo6x10/v4l2.c              |  961 ----------
+ include/media/davinci/dm355_ccdc.h                 |    6 +-
+ include/media/davinci/dm644x_ccdc.h                |   24 +-
+ include/media/davinci/vpbe.h                       |    2 +-
+ include/media/davinci/vpbe_types.h                 |    3 +-
+ include/media/media-devnode.h                      |    1 +
+ include/media/rc-core.h                            |    2 +
+ include/media/saa7115.h                            |   32 +-
+ include/media/ths7303.h                            |   42 +
+ include/media/tuner.h                              |    4 +
+ include/media/uda1342.h                            |   29 +
+ include/media/v4l2-chip-ident.h                    |   11 +
+ include/media/v4l2-common.h                        |    1 -
+ include/media/v4l2-ctrls.h                         |   29 +-
+ include/media/v4l2-device.h                        |   13 +
+ include/media/v4l2-ioctl.h                         |   22 +-
+ include/media/v4l2-subdev.h                        |   25 +-
+ include/media/videobuf2-core.h                     |   11 +-
+ include/uapi/linux/media.h                         |    2 +
+ include/uapi/linux/v4l2-controls.h                 |   10 +
+ include/uapi/linux/videodev2.h                     |   89 +-
+ sound/i2c/other/tea575x-tuner.c                    |    6 +-
+ 502 files changed, 22670 insertions(+), 20553 deletions(-)
+ create mode 100644 Documentation/DocBook/media/v4l/vidioc-dbg-g-chip-name.xml
+ delete mode 100644 Documentation/DocBook/media/v4l/vidioc-enum-dv-presets.xml
+ delete mode 100644 Documentation/DocBook/media/v4l/vidioc-g-dv-preset.xml
+ delete mode 100644 Documentation/DocBook/media/v4l/vidioc-query-dv-preset.xml
+ create mode 100644 drivers/media/common/siano/smsdvb-debugfs.c
+ create mode 100644 drivers/media/common/siano/smsdvb-main.c
+ delete mode 100644 drivers/media/common/siano/smsdvb.c
+ create mode 100644 drivers/media/common/siano/smsdvb.h
+ rename drivers/{staging/media/go7007/wis-ov7640.c => media/i2c/ov7640.c} (53%)
+ create mode 100644 drivers/media/i2c/sony-btf-mpx.c
+ create mode 100644 drivers/media/i2c/tw2804.c
+ create mode 100644 drivers/media/i2c/tw9903.c
+ create mode 100644 drivers/media/i2c/tw9906.c
+ rename drivers/{staging/media/go7007/wis-uda1342.c => media/i2c/uda1342.c} (52%)
+ create mode 100644 drivers/media/tuners/it913x.c
+ create mode 100644 drivers/media/tuners/it913x.h
+ create mode 100644 drivers/media/tuners/it913x_priv.h
+ create mode 100644 drivers/media/usb/em28xx/em28xx-camera.c
+ delete mode 100644 drivers/media/usb/gspca/autogain_functions.h
+ create mode 100644 drivers/staging/media/go7007/go7007-loader.c
+ delete mode 100644 drivers/staging/media/go7007/s2250-loader.c
+ delete mode 100644 drivers/staging/media/go7007/s2250-loader.h
+ delete mode 100644 drivers/staging/media/go7007/wis-i2c.h
+ delete mode 100644 drivers/staging/media/go7007/wis-saa7113.c
+ delete mode 100644 drivers/staging/media/go7007/wis-saa7115.c
+ delete mode 100644 drivers/staging/media/go7007/wis-sony-tuner.c
+ delete mode 100644 drivers/staging/media/go7007/wis-tw2804.c
+ delete mode 100644 drivers/staging/media/go7007/wis-tw9903.c
+ delete mode 100644 drivers/staging/media/solo6x10/core.c
+ delete mode 100644 drivers/staging/media/solo6x10/offsets.h
+ delete mode 100644 drivers/staging/media/solo6x10/osd-font.h
+ delete mode 100644 drivers/staging/media/solo6x10/p2m.c
+ create mode 100644 drivers/staging/media/solo6x10/solo6x10-core.c
+ rename drivers/staging/media/solo6x10/{disp.c => solo6x10-disp.c} (74%)
+ create mode 100644 drivers/staging/media/solo6x10/solo6x10-eeprom.c
+ rename drivers/staging/media/solo6x10/{enc.c => solo6x10-enc.c} (50%)
+ rename drivers/staging/media/solo6x10/{g723.c => solo6x10-g723.c} (83%)
+ rename drivers/staging/media/solo6x10/{gpio.c => solo6x10-gpio.c} (91%)
+ rename drivers/staging/media/solo6x10/{i2c.c => solo6x10-i2c.c} (92%)
+ create mode 100644 drivers/staging/media/solo6x10/solo6x10-offsets.h
+ create mode 100644 drivers/staging/media/solo6x10/solo6x10-p2m.c
+ rename drivers/staging/media/solo6x10/{registers.h => solo6x10-regs.h} (90%)
+ rename drivers/staging/media/solo6x10/{tw28.c => solo6x10-tw28.c} (84%)
+ rename drivers/staging/media/solo6x10/{tw28.h => solo6x10-tw28.h} (88%)
+ create mode 100644 drivers/staging/media/solo6x10/solo6x10-v4l2-enc.c
+ create mode 100644 drivers/staging/media/solo6x10/solo6x10-v4l2.c
+ delete mode 100644 drivers/staging/media/solo6x10/v4l2-enc.c
+ delete mode 100644 drivers/staging/media/solo6x10/v4l2.c
+ create mode 100644 include/media/ths7303.h
+ create mode 100644 include/media/uda1342.h
+$ git am -3 ../patches/0001-i2c-fixup-for-code-movement-from-bttv_input.c.patch
+Applying: i2c: fixup for code movement from bttv_input.c
+$ git reset HEAD^
+Unstaged changes after reset:
+M	drivers/media/pci/bt8xx/bttv-i2c.c
+$ git add -A .
+$ git commit -v -a --amend
+[master 92a2d2f] Merge remote-tracking branch 'v4l-dvb/master'
+Merging kbuild/for-next (d1fc916 Merge branch 'kbuild/misc' into kbuild/for-next)
+$ git merge kbuild/for-next
+Merge made by the 'recursive' strategy.
+ scripts/kconfig/Makefile                   | 4 +++-
+ scripts/kconfig/lxdialog/check-lxdialog.sh | 2 ++
+ scripts/tags.sh                            | 4 +++-
+ 3 files changed, 8 insertions(+), 2 deletions(-)
+Merging kconfig/for-next (4eae518 localmodconfig: Fix localyesconfig to set to 'y' not 'm')
+$ git merge kconfig/for-next
+Already up-to-date.
+Merging libata/NEXT (7551c40 fsl/sata: create a sysfs entry for rx water mark)
+$ git merge libata/NEXT
+Merge made by the 'recursive' strategy.
+ drivers/ata/ata_piix.c       | 14 ++++++++++-
+ drivers/ata/libata-acpi.c    | 33 --------------------------
+ drivers/ata/libata-core.c    |  6 ++++-
+ drivers/ata/libata-scsi.c    | 14 ++++++-----
+ drivers/ata/pata_at32.c      | 13 +----------
+ drivers/ata/pata_legacy.c    |  2 +-
+ drivers/ata/pata_octeon_cf.c |  2 +-
+ drivers/ata/sata_fsl.c       | 55 ++++++++++++++++++++++++++++++++++++++++++++
+ drivers/ata/sata_highbank.c  |  2 +-
+ include/linux/ata.h          |  2 +-
+ include/linux/libata.h       |  1 +
+ 11 files changed, 87 insertions(+), 57 deletions(-)
+Merging infiniband/for-next (4e73a54 Merge branches 'cxgb4', 'ipoib' and 'qib' into for-next)
+$ git merge infiniband/for-next
+Already up-to-date.
+Merging pstore/master (bd08ec3 pstore/ram: Restore ecc information block)
+$ git merge pstore/master
+Merge made by the 'recursive' strategy.
+ fs/pstore/ram.c            | 26 +++++++++++-------
+ fs/pstore/ram_core.c       | 66 ++++++++++++++++++++++++++--------------------
+ include/linux/pstore_ram.h | 14 +++++++---
+ 3 files changed, 64 insertions(+), 42 deletions(-)
+Merging pm/linux-next (33da2f7 Merge branch 'pm-cpufreq-next' into linux-next)
+$ git merge pm/linux-next
+Removing drivers/clk/x86/clk-lpss.h
+Removing drivers/clk/x86/clk-lpss.c
+Auto-merging drivers/acpi/pci_root.c
+Auto-merging drivers/acpi/button.c
+Auto-merging drivers/acpi/battery.c
+Auto-merging MAINTAINERS
+Merge made by the 'recursive' strategy.
+ Documentation/ABI/testing/sysfs-devices-lpss_ltr   |  44 ++
+ Documentation/ABI/testing/sysfs-firmware-acpi      |  26 +
+ Documentation/cpu-freq/cpu-drivers.txt             |   9 +-
+ Documentation/cpu-freq/governors.txt               |   6 +
+ .../bindings/cpufreq/arm_big_little_dt.txt         |  65 +++
+ .../devicetree/bindings/cpufreq/cpufreq-cpu0.txt   |   2 +-
+ MAINTAINERS                                        |  11 +
+ arch/arm/configs/kirkwood_defconfig                |   1 -
+ arch/arm/mach-davinci/cpufreq.c                    |  33 +-
+ arch/arm/mach-imx/cpufreq.c                        |   8 +-
+ arch/arm/mach-imx/cpuidle-imx6q.c                  |  23 +-
+ arch/arm/mach-integrator/cpu.c                     |   6 +-
+ arch/arm/mach-omap2/cpuidle44xx.c                  |  25 +-
+ arch/arm/mach-pxa/cpufreq-pxa2xx.c                 |   5 +-
+ arch/arm/mach-pxa/cpufreq-pxa3xx.c                 |   5 +-
+ arch/arm/mach-s3c24xx/cpufreq.c                    |   8 +-
+ arch/arm/mach-sa1100/cpu-sa1100.c                  |   5 +-
+ arch/arm/mach-sa1100/cpu-sa1110.c                  |   5 +-
+ arch/arm/mach-tegra/cpu-tegra.c                    |  15 +-
+ arch/arm/mach-ux500/cpuidle.c                      |  25 +-
+ arch/avr32/mach-at32ap/cpufreq.c                   |   5 +-
+ arch/blackfin/mach-common/cpufreq.c                |  79 ++-
+ arch/cris/arch-v32/mach-a3/cpufreq.c               |  20 +-
+ arch/cris/arch-v32/mach-fs/cpufreq.c               |  17 +-
+ arch/ia64/kernel/cpufreq/acpi-cpufreq.c            |  22 +-
+ arch/mips/kernel/cpufreq/loongson2_cpufreq.c       |  11 +-
+ arch/powerpc/platforms/cell/cbe_cpufreq.c          |   5 +-
+ arch/powerpc/platforms/pasemi/cpufreq.c            |   5 +-
+ arch/powerpc/platforms/powermac/cpufreq_32.c       |  14 +-
+ arch/powerpc/platforms/powermac/cpufreq_64.c       |   5 +-
+ arch/sh/kernel/cpufreq.c                           |  20 +-
+ arch/sparc/kernel/us2e_cpufreq.c                   |  19 +-
+ arch/sparc/kernel/us3_cpufreq.c                    |  19 +-
+ arch/unicore32/kernel/cpu-ucv2.c                   |   5 +-
+ drivers/acpi/Kconfig                               |   7 +-
+ drivers/acpi/Makefile                              |   1 +
+ drivers/acpi/acpi_i2c.c                            |   2 +-
+ drivers/acpi/acpi_lpss.c                           | 292 +++++++++++
+ drivers/acpi/acpi_memhotplug.c                     | 328 ++-----------
+ drivers/acpi/acpi_pad.c                            |   2 +-
+ drivers/acpi/acpi_platform.c                       |  40 +-
+ drivers/acpi/acpica/Makefile                       |   1 +
+ drivers/acpi/acpica/acglobal.h                     |   4 +-
+ drivers/acpi/acpica/aclocal.h                      |  16 +
+ drivers/acpi/acpica/acmacros.h                     |   6 +-
+ drivers/acpi/acpica/acnamesp.h                     |  25 +-
+ drivers/acpi/acpica/acutils.h                      |   3 +-
+ drivers/acpi/acpica/dsutils.c                      |  10 +-
+ drivers/acpi/acpica/evevent.c                      |  12 +-
+ drivers/acpi/acpica/evgpe.c                        |   6 +-
+ drivers/acpi/acpica/evsci.c                        |   4 +-
+ drivers/acpi/acpica/evxface.c                      |  21 +-
+ drivers/acpi/acpica/evxfevnt.c                     |  12 +
+ drivers/acpi/acpica/exprep.c                       |   4 +-
+ drivers/acpi/acpica/exutils.c                      |   4 +-
+ drivers/acpi/acpica/hwacpi.c                       |  20 +-
+ drivers/acpi/acpica/nsconvert.c                    | 443 +++++++++++++++++
+ drivers/acpi/acpica/nspredef.c                     | 141 +++---
+ drivers/acpi/acpica/nsprepkg.c                     |  10 +-
+ drivers/acpi/acpica/nsrepair.c                     | 381 ++++++---------
+ drivers/acpi/acpica/nsrepair2.c                    |  16 +-
+ drivers/acpi/acpica/nsutils.c                      |   8 +-
+ drivers/acpi/acpica/psargs.c                       |   2 +-
+ drivers/acpi/acpica/rscalc.c                       |   6 +
+ drivers/acpi/acpica/rsdump.c                       |   8 +
+ drivers/acpi/acpica/rslist.c                       |   8 +
+ drivers/acpi/acpica/rsxface.c                      |   8 +-
+ drivers/acpi/acpica/utaddress.c                    |   4 +-
+ drivers/acpi/acpica/utcache.c                      |  18 +-
+ drivers/acpi/acpica/utexcep.c                      |  26 +-
+ drivers/acpi/acpica/utglobal.c                     |   2 +
+ drivers/acpi/battery.c                             |   2 +-
+ drivers/acpi/bus.c                                 |   5 +-
+ drivers/acpi/button.c                              |   1 +
+ drivers/acpi/container.c                           | 152 +-----
+ drivers/acpi/device_pm.c                           |  39 +-
+ drivers/acpi/fan.c                                 |   8 +-
+ drivers/acpi/internal.h                            |  21 +-
+ drivers/acpi/osl.c                                 |   2 +-
+ drivers/acpi/pci_link.c                            |   1 +
+ drivers/acpi/pci_root.c                            |   4 +-
+ drivers/acpi/power.c                               |   2 +-
+ drivers/acpi/processor_idle.c                      |  13 +-
+ drivers/acpi/processor_thermal.c                   |  24 +-
+ drivers/acpi/processor_throttling.c                |   3 +-
+ drivers/acpi/scan.c                                | 531 +++++++++++++++------
+ drivers/acpi/sysfs.c                               |  66 +++
+ drivers/acpi/video.c                               | 110 +++--
+ drivers/acpi/video_detect.c                        |  25 +-
+ drivers/base/power/qos.c                           |  60 ++-
+ drivers/clk/x86/Makefile                           |   2 +-
+ drivers/clk/x86/clk-lpss.c                         |  99 ----
+ drivers/clk/x86/clk-lpss.h                         |  36 --
+ drivers/clk/x86/clk-lpt.c                          |  40 +-
+ drivers/cpufreq/Kconfig.arm                        |  12 +
+ drivers/cpufreq/Makefile                           |   5 +
+ drivers/cpufreq/acpi-cpufreq.c                     |  11 +-
+ drivers/cpufreq/arm_big_little.c                   | 282 +++++++++++
+ drivers/cpufreq/arm_big_little.h                   |  40 ++
+ drivers/cpufreq/arm_big_little_dt.c                |  92 ++++
+ drivers/cpufreq/cpufreq-cpu0.c                     |  41 +-
+ drivers/cpufreq/cpufreq-nforce2.c                  |  11 +-
+ drivers/cpufreq/cpufreq.c                          | 129 +++--
+ drivers/cpufreq/cpufreq_conservative.c             | 244 ++++++----
+ drivers/cpufreq/cpufreq_governor.c                 | 291 ++++++-----
+ drivers/cpufreq/cpufreq_governor.h                 | 130 ++++-
+ drivers/cpufreq/cpufreq_ondemand.c                 | 302 +++++++-----
+ drivers/cpufreq/dbx500-cpufreq.c                   |  12 +-
+ drivers/cpufreq/e_powersaver.c                     |  11 +-
+ drivers/cpufreq/elanfreq.c                         |  10 +-
+ drivers/cpufreq/exynos-cpufreq.c                   |   7 +-
+ drivers/cpufreq/gx-suspmod.c                       |  11 +-
+ drivers/cpufreq/imx6q-cpufreq.c                    |  12 +-
+ drivers/cpufreq/kirkwood-cpufreq.c                 |  18 +-
+ drivers/cpufreq/longhaul.c                         |  18 +-
+ drivers/cpufreq/maple-cpufreq.c                    |   5 +-
+ drivers/cpufreq/omap-cpufreq.c                     |  15 +-
+ drivers/cpufreq/p4-clockmod.c                      |  13 +-
+ drivers/cpufreq/pcc-cpufreq.c                      |   5 +-
+ drivers/cpufreq/powernow-k6.c                      |  12 +-
+ drivers/cpufreq/powernow-k7.c                      |  10 +-
+ drivers/cpufreq/powernow-k8.c                      |  19 +-
+ drivers/cpufreq/s3c2416-cpufreq.c                  |   5 +-
+ drivers/cpufreq/s3c64xx-cpufreq.c                  |   7 +-
+ drivers/cpufreq/s5pv210-cpufreq.c                  |   5 +-
+ drivers/cpufreq/sc520_freq.c                       |  10 +-
+ drivers/cpufreq/spear-cpufreq.c                    |   7 +-
+ drivers/cpufreq/speedstep-centrino.c               |  28 +-
+ drivers/cpufreq/speedstep-ich.c                    |  12 +-
+ drivers/cpufreq/speedstep-smi.c                    |   5 +-
+ drivers/cpuidle/Kconfig                            |   6 -
+ drivers/cpuidle/Makefile                           |   2 +-
+ drivers/cpuidle/cpuidle-kirkwood.c                 |   6 +-
+ drivers/cpuidle/cpuidle.c                          |   9 +
+ drivers/cpuidle/driver.c                           |  31 +-
+ drivers/gpu/drm/i915/intel_opregion.c              |   4 +-
+ drivers/i2c/busses/i2c-designware-platdrv.c        |   1 -
+ drivers/platform/x86/sony-laptop.c                 |   3 +-
+ drivers/pnp/pnpacpi/rsparser.c                     |   1 +
+ drivers/spi/spi-pxa2xx.c                           |   1 -
+ drivers/spi/spi.c                                  |   2 +-
+ drivers/usb/core/port.c                            |   1 -
+ include/acpi/acexcep.h                             | 461 ++++++++++--------
+ include/acpi/acoutput.h                            |  53 +-
+ include/acpi/acpi_bus.h                            |  33 +-
+ include/acpi/acpi_drivers.h                        |   1 -
+ include/acpi/acpixf.h                              |   2 +-
+ include/acpi/actbl2.h                              |  47 ++
+ include/acpi/actbl3.h                              |  55 ++-
+ include/acpi/actypes.h                             |   1 -
+ include/linux/acpi.h                               |   4 +-
+ include/linux/clockchips.h                         |  32 +-
+ include/linux/cpufreq.h                            |  21 +-
+ include/linux/cpuidle.h                            |   3 +
+ include/linux/devfreq.h                            |  16 +-
+ include/linux/platform_data/clk-lpss.h             |  18 +
+ 156 files changed, 3945 insertions(+), 2436 deletions(-)
+ create mode 100644 Documentation/ABI/testing/sysfs-devices-lpss_ltr
+ create mode 100644 Documentation/devicetree/bindings/cpufreq/arm_big_little_dt.txt
+ create mode 100644 drivers/acpi/acpi_lpss.c
+ create mode 100644 drivers/acpi/acpica/nsconvert.c
+ delete mode 100644 drivers/clk/x86/clk-lpss.c
+ delete mode 100644 drivers/clk/x86/clk-lpss.h
+ create mode 100644 drivers/cpufreq/arm_big_little.c
+ create mode 100644 drivers/cpufreq/arm_big_little.h
+ create mode 100644 drivers/cpufreq/arm_big_little_dt.c
+ create mode 100644 include/linux/platform_data/clk-lpss.h
+Merging idle/next (e6bfd82 Merge branch 'ia64-idle-regression-fix' into next)
+$ git merge idle/next
+Merge made by the 'recursive' strategy.
+ drivers/idle/intel_idle.c             | 1 +
+ tools/power/x86/turbostat/turbostat.c | 3 +++
+ 2 files changed, 4 insertions(+)
+Merging apm/for-next (fb9d78a Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/apm)
+$ git merge apm/for-next
+Already up-to-date.
+Merging cpuidle/cpuidle-next (817c876 Merge branch 'pm-fixes-next' into fixes-next)
+$ git merge cpuidle/cpuidle-next
+Resolved 'drivers/base/power/qos.c' using previous resolution.
+Auto-merging drivers/base/power/qos.c
+CONFLICT (content): Merge conflict in drivers/base/power/qos.c
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master 5ab0542] Merge remote-tracking branch 'cpuidle/cpuidle-next'
+$ git diff -M --stat --summary HEAD^..
+Merging cpupowerutils/master (f166033 cpupower tools: add install target to the debug tools' makefiles)
+$ git merge cpupowerutils/master
+Already up-to-date.
+Merging thermal/next (2fd1db8 thermal: dove: Fix thermal sensor formula)
+$ git merge thermal/next
+Auto-merging include/linux/thermal.h
+Merge made by the 'recursive' strategy.
+ drivers/thermal/cpu_cooling.c      | 10 +++++-----
+ drivers/thermal/db8500_thermal.c   | 19 ++++++++++++-------
+ drivers/thermal/dove_thermal.c     |  7 ++++---
+ drivers/thermal/kirkwood_thermal.c | 12 ++++++------
+ include/linux/thermal.h            |  2 +-
+ 5 files changed, 28 insertions(+), 22 deletions(-)
+Merging ieee1394/for-next (6dbe51c Linux 3.9-rc1)
+$ git merge ieee1394/for-next
+Already up-to-date.
+Merging ubi/linux-next (f6161aa Linux 3.9-rc2)
+$ git merge ubi/linux-next
+Already up-to-date.
+Merging dlm/next (f117228 dlm: avoid scanning unchanged toss lists)
+$ git merge dlm/next
+Already up-to-date.
+Merging swiotlb/linux-next (af51a9f swiotlb: Do not export swiotlb_bounce since there are no external consumers)
+$ git merge swiotlb/linux-next
+Already up-to-date.
+Merging scsi/for-next (6dbe51c Linux 3.9-rc1)
+$ git merge scsi/for-next
+Already up-to-date.
+Merging target-updates/for-next (aa010cb iscsi-target: Add iser network portal attribute)
+$ git merge target-updates/for-next
+Merge made by the 'recursive' strategy.
+ drivers/scsi/qla2xxx/qla_target.c              |   19 -
+ drivers/scsi/qla2xxx/qla_target.h              |    1 -
+ drivers/target/iscsi/Makefile                  |    3 +-
+ drivers/target/iscsi/iscsi_target.c            | 1169 ++++++++++++++----------
+ drivers/target/iscsi/iscsi_target.h            |    3 +-
+ drivers/target/iscsi/iscsi_target_auth.c       |   28 +-
+ drivers/target/iscsi/iscsi_target_configfs.c   |   94 +-
+ drivers/target/iscsi/iscsi_target_core.h       |   26 +-
+ drivers/target/iscsi/iscsi_target_device.c     |    7 +-
+ drivers/target/iscsi/iscsi_target_erl1.c       |   13 +-
+ drivers/target/iscsi/iscsi_target_login.c      |  470 +++++++---
+ drivers/target/iscsi/iscsi_target_login.h      |    6 +
+ drivers/target/iscsi/iscsi_target_nego.c       |  194 +---
+ drivers/target/iscsi/iscsi_target_nego.h       |   11 +-
+ drivers/target/iscsi/iscsi_target_parameters.c |   87 +-
+ drivers/target/iscsi/iscsi_target_parameters.h |   16 +-
+ drivers/target/iscsi/iscsi_target_tmr.c        |    4 +-
+ drivers/target/iscsi/iscsi_target_tpg.c        |    6 +-
+ drivers/target/iscsi/iscsi_target_transport.c  |   55 ++
+ drivers/target/iscsi/iscsi_target_util.c       |   53 +-
+ drivers/target/iscsi/iscsi_target_util.h       |    1 +
+ drivers/target/target_core_transport.c         |   13 +-
+ drivers/target/tcm_fc/tfc_sess.c               |    9 +-
+ drivers/vhost/tcm_vhost.c                      |   47 +-
+ include/target/iscsi/iscsi_transport.h         |   83 ++
+ include/target/target_core_fabric.h            |    2 +-
+ 26 files changed, 1524 insertions(+), 896 deletions(-)
+ create mode 100644 drivers/target/iscsi/iscsi_target_transport.c
+ create mode 100644 include/target/iscsi/iscsi_transport.h
+Merging target-merge/for-next-merge (a937536 Linux 3.9-rc3)
+$ git merge target-merge/for-next-merge
+Already up-to-date.
+Merging ibft/linux-next (935a9fe ibft: Fix finding IBFT ACPI table on UEFI)
+$ git merge ibft/linux-next
+Already up-to-date.
+Merging isci/all (6734092 isci: add a couple __iomem annotations)
+$ git merge isci/all
+Already up-to-date.
+Merging slave-dma/next (a2a1a6d Merge branch 'fixes' into next)
+$ git merge slave-dma/next
+Merge made by the 'recursive' strategy.
+ Documentation/dmatest.txt     |  81 ++++
+ arch/arm/mach-omap2/dma.c     |   4 +
+ drivers/dma/at_hdmac.c        |   4 +-
+ drivers/dma/coh901318.c       |   4 +-
+ drivers/dma/dmaengine.c       |  11 +-
+ drivers/dma/dmatest.c         | 887 +++++++++++++++++++++++++++++++++++-------
+ drivers/dma/dw_dmac.c         | 135 +++----
+ drivers/dma/dw_dmac_regs.h    |   5 +-
+ drivers/dma/imx-dma.c         |   7 +-
+ drivers/dma/imx-sdma.c        |   4 +-
+ drivers/dma/ioat/dma.h        |   2 +-
+ drivers/dma/ioat/dma_v3.c     |  15 +-
+ drivers/dma/ipu/ipu_idmac.c   |   6 +-
+ drivers/dma/of-dma.c          |  19 +-
+ drivers/dma/omap-dma.c        |  38 +-
+ drivers/dma/pch_dma.c         |   2 +-
+ drivers/dma/pl330.c           |  48 ++-
+ drivers/dma/sirf-dma.c        |  11 +
+ drivers/dma/tegra20-apb-dma.c |  22 +-
+ drivers/dma/timb_dma.c        |   2 +-
+ drivers/dma/txx9dmac.c        |   8 +-
+ include/linux/dmaengine.h     |  15 +-
+ include/linux/of_dma.h        |   4 +-
+ 23 files changed, 1036 insertions(+), 298 deletions(-)
+ create mode 100644 Documentation/dmatest.txt
+Merging dmaengine/next (7f34986 dma: ipu: Drop unused spinlock)
+$ git merge dmaengine/next
+Resolved 'drivers/dma/ioat/dma_v3.c' using previous resolution.
+Auto-merging drivers/dma/ioat/dma_v3.c
+CONFLICT (content): Merge conflict in drivers/dma/ioat/dma_v3.c
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master a45f782] Merge remote-tracking branch 'dmaengine/next'
+$ git diff -M --stat --summary HEAD^..
+Merging net-next/master (19952cc net: frag queue per hash bucket locking)
+$ git merge net-next/master
+Resolved 'drivers/net/wireless/rt2x00/rt2x00pci.c' using previous resolution.
+Resolved 'drivers/nfc/microread/mei.c' using previous resolution.
+Auto-merging net/wireless/sme.c
+Auto-merging net/nfc/llcp/sock.c
+Auto-merging net/nfc/llcp/llcp.c
+Auto-merging net/netfilter/nfnetlink_queue_core.c
+Auto-merging net/netfilter/nf_conntrack_standalone.c
+Auto-merging net/mac80211/offchannel.c
+Auto-merging net/mac80211/iface.c
+Auto-merging net/mac80211/ieee80211_i.h
+Auto-merging net/mac80211/cfg.c
+Auto-merging net/ipv6/netfilter/ip6t_NPT.c
+Auto-merging net/ipv4/udp.c
+Auto-merging net/ipv4/tcp_ipv4.c
+Auto-merging net/core/neighbour.c
+Auto-merging net/bluetooth/af_bluetooth.c
+Removing include/net/ipip.h
+Removing include/net/caif/caif_shm.h
+Auto-merging include/linux/skbuff.h
+Auto-merging drivers/nfc/microread/mei.c
+CONFLICT (content): Merge conflict in drivers/nfc/microread/mei.c
+Auto-merging drivers/net/wireless/rt2x00/rt2x00pci.c
+CONFLICT (content): Merge conflict in drivers/net/wireless/rt2x00/rt2x00pci.c
+Auto-merging drivers/net/wireless/rt2x00/rt2800pci.c
+Auto-merging drivers/net/wireless/rt2x00/Kconfig
+Auto-merging drivers/net/wireless/ray_cs.c
+Auto-merging drivers/net/wireless/mwifiex/cfg80211.c
+Removing drivers/net/wireless/iwlwifi/pcie/cfg.h
+Auto-merging drivers/net/wireless/iwlwifi/iwl-7000.c
+Auto-merging drivers/net/wireless/iwlwifi/iwl-6000.c
+Auto-merging drivers/net/wireless/iwlwifi/iwl-5000.c
+Auto-merging drivers/net/wireless/iwlwifi/iwl-2000.c
+Auto-merging drivers/net/wireless/iwlwifi/iwl-1000.c
+Auto-merging drivers/net/wireless/iwlwifi/dvm/tx.c
+Auto-merging drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
+Auto-merging drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+Auto-merging drivers/net/wireless/ath/wil6210/debugfs.c
+Removing drivers/net/wireless/ath/wil6210/dbg_hexdump.h
+Auto-merging drivers/net/ethernet/sfc/falcon.c
+Auto-merging drivers/net/ethernet/freescale/fec_main.c
+Removing drivers/net/caif/caif_shmcore.c
+Removing drivers/net/caif/caif_shm_u5500.c
+Auto-merging MAINTAINERS
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master d6c1d04] Merge remote-tracking branch 'net-next/master'
+$ git diff -M --stat --summary HEAD^..
+ Documentation/ABI/testing/sysfs-class-net-mesh     |    8 +
+ .../devicetree/bindings/net/can/atmel-can.txt      |   14 +
+ Documentation/devicetree/bindings/net/cpsw.txt     |   16 +-
+ Documentation/devicetree/bindings/net/dsa/dsa.txt  |   91 +
+ .../devicetree/bindings/net/marvell-orion-mdio.txt |    3 +
+ Documentation/networking/ip-sysctl.txt             |   53 +-
+ Documentation/networking/packet_mmap.txt           |  327 ++++
+ Documentation/networking/stmmac.txt                |   33 +-
+ MAINTAINERS                                        |    4 +-
+ arch/alpha/include/uapi/asm/socket.h               |    2 +
+ arch/arm/boot/dts/am33xx.dtsi                      |    2 +-
+ arch/arm/net/bpf_jit_32.c                          |    5 +-
+ arch/arm/plat-orion/common.c                       |   54 +-
+ arch/avr32/include/uapi/asm/socket.h               |    2 +
+ arch/cris/include/uapi/asm/socket.h                |    2 +
+ arch/frv/include/uapi/asm/socket.h                 |    2 +
+ arch/h8300/include/uapi/asm/socket.h               |    2 +
+ arch/ia64/include/uapi/asm/socket.h                |    2 +
+ arch/m32r/include/uapi/asm/socket.h                |    2 +
+ arch/mips/include/uapi/asm/socket.h                |    2 +
+ arch/mn10300/include/uapi/asm/socket.h             |    2 +
+ arch/parisc/include/uapi/asm/socket.h              |    2 +
+ arch/powerpc/include/uapi/asm/socket.h             |    2 +
+ arch/powerpc/net/bpf_jit_comp.c                    |   12 +-
+ arch/powerpc/platforms/chrp/pegasos_eth.c          |   20 +
+ arch/powerpc/sysdev/mv64x60_dev.c                  |   16 +-
+ arch/s390/include/uapi/asm/socket.h                |    2 +
+ arch/sparc/include/uapi/asm/socket.h               |    2 +
+ arch/sparc/net/bpf_jit_comp.c                      |    6 +-
+ arch/x86/net/bpf_jit_comp.c                        |    9 +-
+ arch/xtensa/include/uapi/asm/socket.h              |    2 +
+ drivers/bcma/core.c                                |    8 +-
+ drivers/bcma/main.c                                |    5 +
+ drivers/connector/cn_proc.c                        |   25 +
+ drivers/connector/connector.c                      |   12 +-
+ drivers/dma/ioat/dca.c                             |   11 +-
+ drivers/firewire/Kconfig                           |    6 +-
+ drivers/firewire/net.c                             |  462 ++---
+ drivers/infiniband/hw/cxgb4/cm.c                   |   68 +-
+ drivers/infiniband/hw/cxgb4/device.c               |   34 +-
+ drivers/infiniband/hw/cxgb4/iw_cxgb4.h             |   14 +-
+ drivers/infiniband/hw/cxgb4/mem.c                  |  155 +-
+ drivers/infiniband/hw/cxgb4/provider.c             |   15 +-
+ drivers/infiniband/hw/cxgb4/qp.c                   |  113 +-
+ drivers/infiniband/hw/cxgb4/t4.h                   |   11 +-
+ drivers/isdn/capi/capidrv.c                        |    3 +-
+ drivers/isdn/divert/isdn_divert.c                  |    8 +-
+ drivers/isdn/hisax/fsm.c                           |    2 +-
+ drivers/isdn/hisax/hfc_sx.c                        |    2 +-
+ drivers/isdn/i4l/isdn_net.c                        |    2 +-
+ drivers/media/dvb-core/dvb_net.c                   |   10 +-
+ drivers/net/Kconfig                                |    1 +
+ drivers/net/appletalk/Kconfig                      |   18 +-
+ drivers/net/bonding/bond_main.c                    |    3 +-
+ drivers/net/caif/Kconfig                           |    7 -
+ drivers/net/caif/Makefile                          |    4 -
+ drivers/net/caif/caif_shm_u5500.c                  |  128 --
+ drivers/net/caif/caif_shmcore.c                    |  747 --------
+ drivers/net/can/Kconfig                            |    2 +-
+ drivers/net/can/at91_can.c                         |   76 +-
+ drivers/net/can/bfin_can.c                         |    4 +-
+ drivers/net/can/mcp251x.c                          |   35 +-
+ drivers/net/ethernet/adi/bfin_mac.c                |    6 +-
+ drivers/net/ethernet/aeroflex/greth.c              |   24 +-
+ drivers/net/ethernet/amd/7990.c                    |    2 -
+ drivers/net/ethernet/amd/a2065.c                   |    1 -
+ drivers/net/ethernet/amd/am79c961a.c               |    1 -
+ drivers/net/ethernet/amd/ariadne.c                 |    1 -
+ drivers/net/ethernet/amd/atarilance.c              |    6 +-
+ drivers/net/ethernet/amd/au1000_eth.c              |    1 -
+ drivers/net/ethernet/amd/declance.c                |    2 -
+ drivers/net/ethernet/amd/mvme147.c                 |    4 +-
+ drivers/net/ethernet/amd/ni65.c                    |    2 +-
+ drivers/net/ethernet/amd/pcnet32.c                 |    1 -
+ drivers/net/ethernet/amd/sun3lance.c               |    7 +-
+ drivers/net/ethernet/amd/sunlance.c                |    9 +-
+ drivers/net/ethernet/apple/macmace.c               |   16 +-
+ drivers/net/ethernet/atheros/atl1e/atl1e_main.c    |    6 +-
+ drivers/net/ethernet/atheros/atlx/atl1.c           |    2 +-
+ drivers/net/ethernet/atheros/atlx/atl2.c           |    3 -
+ drivers/net/ethernet/broadcom/bcm63xx_enet.c       |   73 +-
+ drivers/net/ethernet/broadcom/bgmac.c              |   84 +-
+ drivers/net/ethernet/broadcom/bgmac.h              |    1 +
+ drivers/net/ethernet/broadcom/bnx2.c               |    5 +-
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x.h        |   47 +-
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c    |  327 +++-
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h    |   28 +-
+ .../net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c    |  127 +-
+ .../net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h    |   87 +-
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h    |  252 ++-
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c   |  226 ++-
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h   |   16 +-
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c   |  278 ++-
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h    |    6 +-
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c     |   79 +-
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h     |   21 +-
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c  |  351 +++-
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h  |   22 +-
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c  |   77 +-
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h  |    2 +-
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c   |  107 +-
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h   |    9 +-
+ drivers/net/ethernet/broadcom/sb1250-mac.c         |    5 +-
+ drivers/net/ethernet/broadcom/tg3.c                |  389 ++--
+ drivers/net/ethernet/broadcom/tg3.h                |   18 +-
+ drivers/net/ethernet/brocade/bna/bfa_ioc.c         |    2 +-
+ drivers/net/ethernet/brocade/bna/bnad.c            |    5 +-
+ drivers/net/ethernet/cadence/at91_ether.c          |   77 +-
+ drivers/net/ethernet/cadence/macb.c                |   80 +-
+ drivers/net/ethernet/cadence/macb.h                |    2 +
+ drivers/net/ethernet/chelsio/cxgb/sge.c            |    5 +-
+ drivers/net/ethernet/chelsio/cxgb4/cxgb4.h         |   55 +-
+ drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c    |  778 +++++++-
+ drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h     |    3 +
+ drivers/net/ethernet/chelsio/cxgb4/sge.c           |   89 +-
+ drivers/net/ethernet/chelsio/cxgb4/t4_hw.c         |  256 ++-
+ drivers/net/ethernet/chelsio/cxgb4/t4_hw.h         |    1 -
+ drivers/net/ethernet/chelsio/cxgb4/t4_msg.h        |   53 +
+ drivers/net/ethernet/chelsio/cxgb4/t4_regs.h       |   98 +
+ drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h      |    2 +-
+ drivers/net/ethernet/chelsio/cxgb4vf/adapter.h     |    1 +
+ .../net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c    |   35 +-
+ drivers/net/ethernet/chelsio/cxgb4vf/sge.c         |    8 +-
+ drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h |   24 +
+ drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c     |   14 +-
+ drivers/net/ethernet/cirrus/cs89x0.c               |   74 +-
+ drivers/net/ethernet/cirrus/ep93xx_eth.c           |   13 +-
+ drivers/net/ethernet/davicom/dm9000.c              |   17 +-
+ drivers/net/ethernet/dec/tulip/xircom_cb.c         |    9 +-
+ drivers/net/ethernet/dlink/dl2k.c                  |    7 +-
+ drivers/net/ethernet/emulex/benet/be.h             |    2 +-
+ drivers/net/ethernet/emulex/benet/be_cmds.c        |   31 +-
+ drivers/net/ethernet/emulex/benet/be_cmds.h        |   10 +-
+ drivers/net/ethernet/emulex/benet/be_ethtool.c     |   11 +-
+ drivers/net/ethernet/emulex/benet/be_hw.h          |    2 +-
+ drivers/net/ethernet/emulex/benet/be_main.c        |   60 +-
+ drivers/net/ethernet/emulex/benet/be_roce.c        |    2 +-
+ drivers/net/ethernet/emulex/benet/be_roce.h        |    2 +-
+ drivers/net/ethernet/faraday/ftgmac100.c           |   22 +-
+ drivers/net/ethernet/faraday/ftmac100.c            |    8 +-
+ drivers/net/ethernet/freescale/Makefile            |    3 +-
+ .../net/ethernet/freescale/{fec.c => fec_main.c}   |   53 +-
+ drivers/net/ethernet/freescale/fec_ptp.c           |    3 -
+ .../net/ethernet/freescale/fs_enet/fs_enet-main.c  |   17 +-
+ drivers/net/ethernet/freescale/gianfar.c           |  159 +-
+ drivers/net/ethernet/freescale/gianfar.h           |    8 +-
+ drivers/net/ethernet/freescale/gianfar_ethtool.c   |    3 +-
+ drivers/net/ethernet/fujitsu/fmvj18x_cs.c          |    2 -
+ drivers/net/ethernet/i825xx/82596.c                |    8 +-
+ drivers/net/ethernet/i825xx/lib82596.c             |    6 +-
+ drivers/net/ethernet/ibm/ehea/ehea_main.c          |    9 +-
+ drivers/net/ethernet/ibm/emac/mal.c                |    9 +-
+ drivers/net/ethernet/ibm/ibmveth.c                 |    6 +-
+ drivers/net/ethernet/intel/e1000/e1000_ethtool.c   |    6 +-
+ drivers/net/ethernet/intel/e1000/e1000_main.c      |    7 -
+ drivers/net/ethernet/intel/e1000e/80003es2lan.c    |  131 +-
+ drivers/net/ethernet/intel/e1000e/82571.c          |   38 +-
+ drivers/net/ethernet/intel/e1000e/82571.h          |    2 +
+ drivers/net/ethernet/intel/e1000e/defines.h        |   27 +-
+ drivers/net/ethernet/intel/e1000e/e1000.h          |   21 +-
+ drivers/net/ethernet/intel/e1000e/ethtool.c        |  240 ++-
+ drivers/net/ethernet/intel/e1000e/hw.h             |    4 +-
+ drivers/net/ethernet/intel/e1000e/ich8lan.c        |  408 +++--
+ drivers/net/ethernet/intel/e1000e/ich8lan.h        |   11 +-
+ drivers/net/ethernet/intel/e1000e/mac.c            |   37 +-
+ drivers/net/ethernet/intel/e1000e/netdev.c         |  306 ++--
+ drivers/net/ethernet/intel/e1000e/nvm.c            |    2 +-
+ drivers/net/ethernet/intel/e1000e/param.c          |   62 +-
+ drivers/net/ethernet/intel/e1000e/phy.c            |  134 +-
+ drivers/net/ethernet/intel/igbvf/netdev.c          |    2 -
+ drivers/net/ethernet/intel/ixgb/ixgb_main.c        |    7 +-
+ drivers/net/ethernet/intel/ixgbe/ixgbe_main.c      |   42 +-
+ drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c     |   23 +-
+ drivers/net/ethernet/intel/ixgbevf/ixgbevf.h       |    2 +-
+ drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c  |  104 +-
+ drivers/net/ethernet/intel/ixgbevf/vf.c            |    7 +-
+ drivers/net/ethernet/marvell/Kconfig               |    5 +-
+ drivers/net/ethernet/marvell/Makefile              |    2 +-
+ drivers/net/ethernet/marvell/mv643xx_eth.c         |  239 +--
+ drivers/net/ethernet/marvell/mvmdio.c              |  131 +-
+ drivers/net/ethernet/marvell/mvneta.c              |   14 +-
+ drivers/net/ethernet/marvell/pxa168_eth.c          |   27 +-
+ drivers/net/ethernet/mellanox/mlx4/cmd.c           |    4 +-
+ drivers/net/ethernet/mellanox/mlx4/en_netdev.c     |   76 -
+ drivers/net/ethernet/mellanox/mlx4/en_selftest.c   |    5 +-
+ drivers/net/ethernet/micrel/ks8695net.c            |   20 +-
+ drivers/net/ethernet/micrel/ks8851_mll.c           |   32 +-
+ drivers/net/ethernet/myricom/myri10ge/myri10ge.c   |    3 +-
+ drivers/net/ethernet/natsemi/jazzsonic.c           |   12 +-
+ drivers/net/ethernet/natsemi/macsonic.c            |   12 +-
+ drivers/net/ethernet/natsemi/sonic.c               |    1 -
+ drivers/net/ethernet/natsemi/xtsonic.c             |   12 +-
+ drivers/net/ethernet/neterion/s2io.c               |    6 +-
+ drivers/net/ethernet/netx-eth.c                    |    2 -
+ drivers/net/ethernet/nuvoton/w90p910_ether.c       |   20 +-
+ drivers/net/ethernet/nvidia/forcedeth.c            |   42 +-
+ drivers/net/ethernet/nxp/lpc_eth.c                 |    4 -
+ .../net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c   |   21 +-
+ drivers/net/ethernet/pasemi/pasemi_mac.c           |    5 +-
+ drivers/net/ethernet/qlogic/Kconfig                |   10 +
+ drivers/net/ethernet/qlogic/netxen/netxen_nic.h    |    5 +-
+ .../net/ethernet/qlogic/netxen/netxen_nic_init.c   |    4 +-
+ .../net/ethernet/qlogic/netxen/netxen_nic_main.c   |  220 ++-
+ drivers/net/ethernet/qlogic/qla3xxx.c              |    1 -
+ drivers/net/ethernet/qlogic/qlcnic/Makefile        |    4 +-
+ drivers/net/ethernet/qlogic/qlcnic/qlcnic.h        |   81 +-
+ .../net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c    |  379 ++--
+ .../net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h    |  181 +-
+ .../net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c  |   55 +-
+ drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c    |   75 +-
+ .../net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c    |   14 +-
+ drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h    |    4 +-
+ drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c     |   49 +-
+ drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h     |    6 +
+ drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c     |   68 +-
+ drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c   |  107 +-
+ .../net/ethernet/qlogic/qlcnic/qlcnic_minidump.c   |    5 +-
+ drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h  |  214 +++
+ .../ethernet/qlogic/qlcnic/qlcnic_sriov_common.c   | 1297 ++++++++++++++
+ .../net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c   | 1175 ++++++++++++
+ drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c  |  255 ++-
+ drivers/net/ethernet/qlogic/qlge/qlge_main.c       |    6 -
+ drivers/net/ethernet/rdc/r6040.c                   |   12 +-
+ drivers/net/ethernet/realtek/8139too.c             |    2 -
+ drivers/net/ethernet/realtek/atp.c                 |    2 -
+ drivers/net/ethernet/renesas/sh_eth.c              |  397 ++++-
+ drivers/net/ethernet/renesas/sh_eth.h              |  220 ---
+ drivers/net/ethernet/s6gmac.c                      |   16 +-
+ drivers/net/ethernet/seeq/ether3.c                 |   22 +-
+ drivers/net/ethernet/seeq/sgiseeq.c                |    2 -
+ drivers/net/ethernet/sfc/efx.c                     |  267 ++-
+ drivers/net/ethernet/sfc/efx.h                     |   14 +-
+ drivers/net/ethernet/sfc/enum.h                    |   12 +-
+ drivers/net/ethernet/sfc/ethtool.c                 |    4 +-
+ drivers/net/ethernet/sfc/falcon.c                  |   17 +-
+ drivers/net/ethernet/sfc/filter.c                  |  249 ++-
+ drivers/net/ethernet/sfc/mcdi_pcol.h               |    1 +
+ drivers/net/ethernet/sfc/net_driver.h              |   97 +-
+ drivers/net/ethernet/sfc/nic.c                     |   94 +-
+ drivers/net/ethernet/sfc/ptp.c                     |  116 +-
+ drivers/net/ethernet/sfc/rx.c                      |  793 ++++----
+ drivers/net/ethernet/sfc/siena.c                   |   25 +-
+ drivers/net/ethernet/sgi/meth.c                    |    5 +-
+ drivers/net/ethernet/sis/sis900.c                  |    7 +-
+ drivers/net/ethernet/smsc/smc9194.c                |    2 -
+ drivers/net/ethernet/smsc/smc91x.c                 |    2 -
+ drivers/net/ethernet/smsc/smsc911x.c               |    2 +-
+ drivers/net/ethernet/smsc/smsc9420.c               |    4 +-
+ drivers/net/ethernet/stmicro/stmmac/Kconfig        |   19 +-
+ drivers/net/ethernet/stmicro/stmmac/Makefile       |    8 +-
+ drivers/net/ethernet/stmicro/stmmac/chain_mode.c   |   90 +-
+ drivers/net/ethernet/stmicro/stmmac/common.h       |  122 +-
+ drivers/net/ethernet/stmicro/stmmac/descs.h        |   51 +-
+ drivers/net/ethernet/stmicro/stmmac/descs_com.h    |   44 +-
+ drivers/net/ethernet/stmicro/stmmac/dwmac1000.h    |   40 +-
+ .../net/ethernet/stmicro/stmmac/dwmac1000_core.c   |  104 +-
+ .../net/ethernet/stmicro/stmmac/dwmac1000_dma.c    |    8 +-
+ .../net/ethernet/stmicro/stmmac/dwmac100_core.c    |    3 +-
+ drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c |    4 +-
+ drivers/net/ethernet/stmicro/stmmac/enh_desc.c     |  151 +-
+ drivers/net/ethernet/stmicro/stmmac/norm_desc.c    |   85 +-
+ drivers/net/ethernet/stmicro/stmmac/ring_mode.c    |   38 +-
+ drivers/net/ethernet/stmicro/stmmac/stmmac.h       |   23 +-
+ .../net/ethernet/stmicro/stmmac/stmmac_ethtool.c   |  156 +-
+ .../net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c  |  148 ++
+ drivers/net/ethernet/stmicro/stmmac/stmmac_main.c  |  998 ++++++++---
+ drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c   |  215 +++
+ drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h   |   74 +
+ drivers/net/ethernet/sun/niu.c                     |    2 +-
+ drivers/net/ethernet/sun/sunbmac.c                 |    4 +-
+ drivers/net/ethernet/sun/sunhme.c                  |   13 +-
+ drivers/net/ethernet/sun/sunqe.c                   |    5 +-
+ drivers/net/ethernet/tehuti/tehuti.c               |    5 +-
+ drivers/net/ethernet/ti/cpsw.c                     |  159 +-
+ drivers/net/ethernet/ti/davinci_emac.c             |   48 +-
+ drivers/net/ethernet/ti/tlan.c                     |    4 +-
+ drivers/net/ethernet/toshiba/ps3_gelic_net.c       |  240 ++-
+ drivers/net/ethernet/toshiba/spider_net.c          |    3 +-
+ drivers/net/ethernet/tundra/tsi108_eth.c           |   21 +-
+ drivers/net/ethernet/wiznet/w5100.c                |    4 +-
+ drivers/net/ethernet/wiznet/w5300.c                |    4 +-
+ drivers/net/ethernet/xilinx/ll_temac_main.c        |   27 +-
+ drivers/net/ethernet/xilinx/xilinx_axienet_main.c  |   25 +-
+ drivers/net/ethernet/xircom/xirc2ps_cs.c           |    1 -
+ drivers/net/fddi/defxx.c                           |    9 +-
+ drivers/net/hamradio/yam.c                         |    2 +-
+ drivers/net/ieee802154/at86rf230.c                 |   51 +-
+ drivers/net/ieee802154/mrf24j40.c                  |   15 +-
+ drivers/net/irda/ali-ircc.c                        |    6 +-
+ drivers/net/irda/au1k_ir.c                         |   18 +-
+ drivers/net/irda/bfin_sir.c                        |    3 +-
+ drivers/net/irda/nsc-ircc.c                        |    6 +-
+ drivers/net/irda/pxaficp_ir.c                      |    4 +-
+ drivers/net/irda/smsc-ircc2.c                      |   17 +-
+ drivers/net/irda/via-ircc.c                        |    6 +-
+ drivers/net/irda/w83977af_ir.c                     |    7 +-
+ drivers/net/macvlan.c                              |   19 +-
+ drivers/net/macvtap.c                              |    2 +
+ drivers/net/phy/lxt.c                              |    2 +-
+ drivers/net/phy/marvell.c                          |  127 ++
+ drivers/net/phy/mdio-gpio.c                        |   12 +-
+ drivers/net/phy/mdio-octeon.c                      |   13 +-
+ drivers/net/phy/micrel.c                           |   41 +-
+ drivers/net/phy/phy.c                              |   66 +-
+ drivers/net/phy/vitesse.c                          |    3 +-
+ drivers/net/plip/plip.c                            |    2 +-
+ drivers/net/ppp/ppp_synctty.c                      |   53 +-
+ drivers/net/team/Kconfig                           |   12 +
+ drivers/net/team/Makefile                          |    1 +
+ drivers/net/team/team.c                            |   25 +-
+ drivers/net/team/team_mode_broadcast.c             |   14 +-
+ drivers/net/team/team_mode_random.c                |   71 +
+ drivers/net/team/team_mode_roundrobin.c            |   36 +-
+ drivers/net/tun.c                                  |    4 +-
+ drivers/net/usb/cdc_ncm.c                          |    4 +-
+ drivers/net/virtio_net.c                           |    4 +-
+ drivers/net/vxlan.c                                |  399 +++--
+ drivers/net/wireless/ath/ath5k/ath5k.h             |    3 +-
+ drivers/net/wireless/ath/ath5k/eeprom.c            |    6 +-
+ drivers/net/wireless/ath/ath5k/eeprom.h            |    3 -
+ drivers/net/wireless/ath/ath5k/phy.c               |   20 +-
+ drivers/net/wireless/ath/ath5k/reset.c             |    4 +-
+ drivers/net/wireless/ath/ath6kl/Kconfig            |    9 +
+ drivers/net/wireless/ath/ath6kl/Makefile           |    5 +
+ drivers/net/wireless/ath/ath6kl/cfg80211.c         |   15 +-
+ drivers/net/wireless/ath/ath6kl/core.h             |    3 -
+ drivers/net/wireless/ath/ath6kl/debug.c            |   72 +-
+ drivers/net/wireless/ath/ath6kl/debug.h            |   11 +-
+ drivers/net/wireless/ath/ath6kl/hif.c              |    3 +
+ drivers/net/wireless/ath/ath6kl/htc_mbox.c         |   21 +-
+ drivers/net/wireless/ath/ath6kl/htc_pipe.c         |   15 +-
+ drivers/net/wireless/ath/ath6kl/init.c             |  116 +-
+ drivers/net/wireless/ath/ath6kl/main.c             |   41 +-
+ drivers/net/wireless/ath/ath6kl/sdio.c             |   16 +-
+ drivers/net/wireless/ath/ath6kl/target.h           |    2 +-
+ drivers/net/wireless/ath/ath6kl/trace.c            |   23 +
+ drivers/net/wireless/ath/ath6kl/trace.h            |  332 ++++
+ drivers/net/wireless/ath/ath6kl/txrx.c             |    5 +-
+ drivers/net/wireless/ath/ath6kl/usb.c              |   38 +-
+ drivers/net/wireless/ath/ath6kl/wmi.c              |    6 +
+ drivers/net/wireless/ath/ath9k/ar9003_eeprom.c     |   17 +
+ .../net/wireless/ath/ath9k/ar9462_2p0_initvals.h   |   49 +-
+ drivers/net/wireless/ath/ath9k/calib.c             |    4 +-
+ drivers/net/wireless/ath/ath9k/common.h            |    2 +-
+ drivers/net/wireless/ath/ath9k/debug.c             |    5 +
+ drivers/net/wireless/ath/ath9k/debug.h             |    2 +
+ drivers/net/wireless/ath/ath9k/hw.c                |  188 +-
+ drivers/net/wireless/ath/ath9k/hw.h                |    1 -
+ drivers/net/wireless/ath/carl9170/tx.c             |   69 +-
+ drivers/net/wireless/ath/wil6210/Makefile          |    4 +-
+ drivers/net/wireless/ath/wil6210/cfg80211.c        |   33 +-
+ drivers/net/wireless/ath/wil6210/dbg_hexdump.h     |   20 -
+ drivers/net/wireless/ath/wil6210/debugfs.c         |   58 +-
+ drivers/net/wireless/ath/wil6210/interrupt.c       |   25 +-
+ drivers/net/wireless/ath/wil6210/main.c            |   60 +-
+ drivers/net/wireless/ath/wil6210/netdev.c          |    3 -
+ drivers/net/wireless/ath/wil6210/pcie_bus.c        |    3 -
+ drivers/net/wireless/ath/wil6210/txrx.c            |    7 +-
+ drivers/net/wireless/ath/wil6210/wil6210.h         |   17 +-
+ drivers/net/wireless/ath/wil6210/wmi.c             |  154 +-
+ drivers/net/wireless/ath/wil6210/wmi.h             |  363 +++-
+ drivers/net/wireless/b43/Kconfig                   |    6 +-
+ drivers/net/wireless/b43/b43.h                     |    6 +
+ drivers/net/wireless/b43/dma.c                     |    9 +-
+ drivers/net/wireless/b43/main.c                    |    7 +-
+ drivers/net/wireless/b43/phy_ht.c                  |  610 ++++++-
+ drivers/net/wireless/b43/phy_ht.h                  |   77 +-
+ drivers/net/wireless/b43legacy/dma.c               |    8 +-
+ drivers/net/wireless/brcm80211/Kconfig             |    5 +-
+ drivers/net/wireless/brcm80211/brcmfmac/Makefile   |    3 +
+ drivers/net/wireless/brcm80211/brcmfmac/dhd.h      |    7 +-
+ drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h  |    2 +-
+ drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c  |   30 +-
+ .../net/wireless/brcm80211/brcmfmac/dhd_common.c   |   33 +
+ drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c  |   42 +
+ drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h  |   34 +-
+ .../net/wireless/brcm80211/brcmfmac/dhd_linux.c    |   39 +-
+ .../net/wireless/brcm80211/brcmfmac/dhd_proto.h    |    2 +-
+ drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c |   28 +-
+ drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c |  382 ++++
+ drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h |   25 +
+ .../net/wireless/brcm80211/brcmfmac/tracepoint.c   |   22 +
+ .../net/wireless/brcm80211/brcmfmac/tracepoint.h   |   87 +
+ drivers/net/wireless/brcm80211/brcmfmac/usb.c      |   37 +-
+ .../net/wireless/brcm80211/brcmfmac/wl_cfg80211.c  |    6 +-
+ drivers/net/wireless/brcm80211/brcmsmac/Makefile   |    4 +
+ drivers/net/wireless/brcm80211/brcmsmac/led.c      |  126 ++
+ drivers/net/wireless/brcm80211/brcmsmac/led.h      |   36 +
+ .../net/wireless/brcm80211/brcmsmac/mac80211_if.c  |    4 +
+ .../net/wireless/brcm80211/brcmsmac/mac80211_if.h  |    4 +
+ drivers/net/wireless/brcm80211/brcmsmac/main.c     |   11 +-
+ drivers/net/wireless/brcm80211/brcmutil/utils.c    |   25 +
+ .../net/wireless/brcm80211/include/brcmu_utils.h   |   27 +
+ drivers/net/wireless/iwlegacy/3945-mac.c           |    2 +-
+ drivers/net/wireless/iwlegacy/3945.c               |    4 +-
+ drivers/net/wireless/iwlegacy/3945.h               |    4 -
+ drivers/net/wireless/iwlegacy/4965-mac.c           |   33 +-
+ drivers/net/wireless/iwlegacy/common.c             |   21 +-
+ drivers/net/wireless/iwlegacy/common.h             |    9 +-
+ drivers/net/wireless/iwlwifi/Kconfig               |   11 +-
+ drivers/net/wireless/iwlwifi/Makefile              |    3 +-
+ drivers/net/wireless/iwlwifi/dvm/agn.h             |    2 +-
+ drivers/net/wireless/iwlwifi/dvm/calib.c           |    2 +-
+ drivers/net/wireless/iwlwifi/dvm/calib.h           |    2 +-
+ drivers/net/wireless/iwlwifi/dvm/commands.h        |    3 +-
+ drivers/net/wireless/iwlwifi/dvm/debugfs.c         |   26 +-
+ drivers/net/wireless/iwlwifi/dvm/lib.c             |    2 +-
+ drivers/net/wireless/iwlwifi/dvm/mac80211.c        |    3 +-
+ drivers/net/wireless/iwlwifi/dvm/scan.c            |    2 +-
+ drivers/net/wireless/iwlwifi/dvm/testmode.c        |    2 +-
+ drivers/net/wireless/iwlwifi/dvm/tx.c              |   13 +-
+ drivers/net/wireless/iwlwifi/dvm/ucode.c           |    2 +-
+ .../wireless/iwlwifi/{pcie/1000.c => iwl-1000.c}   |    1 -
+ .../wireless/iwlwifi/{pcie/2000.c => iwl-2000.c}   |    1 -
+ .../wireless/iwlwifi/{pcie/5000.c => iwl-5000.c}   |    1 -
+ .../wireless/iwlwifi/{pcie/6000.c => iwl-6000.c}   |    1 -
+ .../wireless/iwlwifi/{pcie/7000.c => iwl-7000.c}   |   63 +-
+ drivers/net/wireless/iwlwifi/iwl-agn-hw.h          |    2 +-
+ drivers/net/wireless/iwlwifi/iwl-config.h          |   49 +-
+ drivers/net/wireless/iwlwifi/iwl-csr.h             |    2 +-
+ drivers/net/wireless/iwlwifi/iwl-debug.c           |   13 +-
+ drivers/net/wireless/iwlwifi/iwl-devtrace.h        |    2 +-
+ drivers/net/wireless/iwlwifi/iwl-drv.c             |   14 +-
+ drivers/net/wireless/iwlwifi/iwl-drv.h             |   17 +-
+ drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c    |    9 +-
+ drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h    |    2 +-
+ drivers/net/wireless/iwlwifi/iwl-eeprom-read.c     |    5 +-
+ drivers/net/wireless/iwlwifi/iwl-eeprom-read.h     |    2 +-
+ drivers/net/wireless/iwlwifi/iwl-fh.h              |    2 +-
+ drivers/net/wireless/iwlwifi/iwl-fw-file.h         |    2 +-
+ drivers/net/wireless/iwlwifi/iwl-fw.h              |    4 +-
+ drivers/net/wireless/iwlwifi/iwl-io.c              |   19 +-
+ drivers/net/wireless/iwlwifi/iwl-modparams.h       |    4 +-
+ drivers/net/wireless/iwlwifi/iwl-notif-wait.c      |   15 +-
+ drivers/net/wireless/iwlwifi/iwl-notif-wait.h      |    2 +-
+ drivers/net/wireless/iwlwifi/iwl-nvm-parse.c       |   51 +-
+ drivers/net/wireless/iwlwifi/iwl-nvm-parse.h       |    2 +-
+ drivers/net/wireless/iwlwifi/iwl-op-mode.h         |    2 +-
+ drivers/net/wireless/iwlwifi/iwl-phy-db.c          |   11 +-
+ drivers/net/wireless/iwlwifi/iwl-phy-db.h          |    2 +-
+ drivers/net/wireless/iwlwifi/iwl-prph.h            |    2 +-
+ drivers/net/wireless/iwlwifi/iwl-test.c            |   11 +-
+ drivers/net/wireless/iwlwifi/iwl-test.h            |    2 +-
+ drivers/net/wireless/iwlwifi/iwl-testmode.h        |    2 +-
+ drivers/net/wireless/iwlwifi/iwl-trans.h           |    5 +-
+ drivers/net/wireless/iwlwifi/mvm/Makefile          |    2 +-
+ drivers/net/wireless/iwlwifi/mvm/binding.c         |    2 +-
+ drivers/net/wireless/iwlwifi/mvm/bt-coex.c         |  347 ++++
+ drivers/net/wireless/iwlwifi/mvm/d3.c              |  260 ++-
+ drivers/net/wireless/iwlwifi/mvm/debugfs.c         |  138 +-
+ drivers/net/wireless/iwlwifi/mvm/fw-api-bt-coex.h  |  319 ++++
+ drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h       |   53 +-
+ drivers/net/wireless/iwlwifi/mvm/fw-api-mac.h      |    2 +-
+ drivers/net/wireless/iwlwifi/mvm/fw-api-power.h    |    2 +-
+ drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h       |    2 +-
+ drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h     |    2 +-
+ drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h      |    2 +-
+ drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h       |    2 +-
+ drivers/net/wireless/iwlwifi/mvm/fw-api.h          |   12 +-
+ drivers/net/wireless/iwlwifi/mvm/fw.c              |   14 +-
+ drivers/net/wireless/iwlwifi/mvm/led.c             |    2 +-
+ drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c        |   45 +-
+ drivers/net/wireless/iwlwifi/mvm/mac80211.c        |   57 +-
+ drivers/net/wireless/iwlwifi/mvm/mvm.h             |   17 +-
+ drivers/net/wireless/iwlwifi/mvm/nvm.c             |   11 +-
+ drivers/net/wireless/iwlwifi/mvm/ops.c             |   12 +-
+ drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c        |    2 +-
+ drivers/net/wireless/iwlwifi/mvm/power.c           |    2 +-
+ drivers/net/wireless/iwlwifi/mvm/quota.c           |    2 +-
+ drivers/net/wireless/iwlwifi/mvm/rs.c              |   14 +-
+ drivers/net/wireless/iwlwifi/mvm/rx.c              |    2 +-
+ drivers/net/wireless/iwlwifi/mvm/scan.c            |    2 +-
+ drivers/net/wireless/iwlwifi/mvm/sta.c             |   91 +-
+ drivers/net/wireless/iwlwifi/mvm/sta.h             |    4 +-
+ drivers/net/wireless/iwlwifi/mvm/time-event.c      |    2 +-
+ drivers/net/wireless/iwlwifi/mvm/time-event.h      |    2 +-
+ drivers/net/wireless/iwlwifi/mvm/tx.c              |    4 +-
+ drivers/net/wireless/iwlwifi/mvm/utils.c           |    2 +-
+ drivers/net/wireless/iwlwifi/pcie/cfg.h            |  115 --
+ drivers/net/wireless/iwlwifi/pcie/drv.c            |    4 +-
+ drivers/net/wireless/iwlwifi/pcie/trans.c          |   25 +-
+ drivers/net/wireless/iwlwifi/pcie/tx.c             |    6 +-
+ drivers/net/wireless/mac80211_hwsim.c              |    3 +-
+ drivers/net/wireless/mwifiex/Makefile              |    1 +
+ drivers/net/wireless/mwifiex/cfg80211.c            |  218 ++-
+ drivers/net/wireless/mwifiex/cmdevt.c              |    2 +-
+ drivers/net/wireless/mwifiex/ethtool.c             |   70 +
+ drivers/net/wireless/mwifiex/fw.h                  |   72 +-
+ drivers/net/wireless/mwifiex/init.c                |    6 +-
+ drivers/net/wireless/mwifiex/ioctl.h               |   23 +
+ drivers/net/wireless/mwifiex/main.c                |   15 +-
+ drivers/net/wireless/mwifiex/main.h                |    9 +
+ drivers/net/wireless/mwifiex/pcie.c                |  156 +-
+ drivers/net/wireless/mwifiex/sta_cmd.c             |   79 +-
+ drivers/net/wireless/mwifiex/sta_cmdresp.c         |    2 +
+ drivers/net/wireless/mwifiex/sta_ioctl.c           |   10 +-
+ drivers/net/wireless/mwifiex/txrx.c                |    2 +
+ drivers/net/wireless/mwifiex/util.c                |    5 +-
+ drivers/net/wireless/mwl8k.c                       |  111 +-
+ drivers/net/wireless/orinoco/orinoco_usb.c         |    2 +-
+ drivers/net/wireless/ray_cs.c                      |    8 +-
+ drivers/net/wireless/rndis_wlan.c                  |    5 +-
+ drivers/net/wireless/rt2x00/Kconfig                |    7 +
+ drivers/net/wireless/rt2x00/rt2800.h               |  103 +-
+ drivers/net/wireless/rt2x00/rt2800lib.c            |  857 ++++++++-
+ drivers/net/wireless/rt2x00/rt2800pci.c            |  116 +-
+ drivers/net/wireless/rt2x00/rt2800usb.c            |   63 +-
+ drivers/net/wireless/rt2x00/rt2x00.h               |   10 +-
+ drivers/net/wireless/rt2x00/rt2x00queue.c          |   10 +-
+ drivers/net/wireless/rt2x00/rt2x00queue.h          |    9 +-
+ drivers/net/wireless/rt2x00/rt2x00usb.c            |   20 +-
+ drivers/net/wireless/rtlwifi/usb.c                 |    3 +-
+ drivers/net/wireless/rtlwifi/wifi.h                |    3 -
+ drivers/net/wireless/ti/wlcore/main.c              |    3 +-
+ drivers/net/xen-netback/netback.c                  |    9 +-
+ drivers/net/xen-netfront.c                         |   26 +-
+ drivers/ptp/ptp_pch.c                              |   29 +-
+ drivers/s390/kvm/virtio_ccw.c                      |    6 +-
+ drivers/scsi/csiostor/Makefile                     |    3 +-
+ drivers/scsi/csiostor/csio_hw.c                    |  559 ++----
+ drivers/scsi/csiostor/csio_hw.h                    |   47 +-
+ drivers/scsi/csiostor/csio_hw_chip.h               |  175 ++
+ drivers/scsi/csiostor/csio_hw_t4.c                 |  403 +++++
+ drivers/scsi/csiostor/csio_hw_t5.c                 |  397 +++++
+ drivers/scsi/csiostor/csio_init.c                  |   48 +-
+ drivers/scsi/csiostor/csio_init.h                  |   29 +-
+ drivers/scsi/csiostor/csio_lnode.h                 |    2 +-
+ drivers/scsi/csiostor/csio_rnode.c                 |   10 +-
+ drivers/scsi/csiostor/csio_rnode.h                 |    2 +-
+ drivers/scsi/csiostor/csio_wr.c                    |   60 +-
+ drivers/scsi/scsi_netlink.c                        |    4 +-
+ drivers/scsi/scsi_transport_fc.c                   |   21 +-
+ drivers/scsi/scsi_transport_iscsi.c                |   70 +-
+ drivers/ssb/driver_chipcommon.c                    |    2 +-
+ drivers/ssb/driver_chipcommon_pmu.c                |   41 +-
+ drivers/ssb/driver_mipscore.c                      |   25 +-
+ drivers/ssb/driver_pcicore.c                       |   15 +-
+ drivers/ssb/embedded.c                             |    5 +-
+ drivers/ssb/main.c                                 |   51 +-
+ drivers/ssb/pci.c                                  |   97 +-
+ drivers/ssb/pcmcia.c                               |   46 +-
+ drivers/ssb/scan.c                                 |   31 +-
+ drivers/ssb/sprom.c                                |    4 +-
+ drivers/ssb/ssb_private.h                          |   19 +-
+ drivers/staging/gdm72xx/netlink_k.c                |   12 +-
+ include/linux/cn_proc.h                            |    4 +
+ include/linux/filter.h                             |   14 +
+ include/linux/ieee80211.h                          |   52 +-
+ include/linux/if_arp.h                             |   12 +-
+ include/linux/if_team.h                            |   25 +-
+ include/linux/if_vlan.h                            |    2 +-
+ include/linux/micrel_phy.h                         |    1 +
+ include/linux/mv643xx_eth.h                        |    1 -
+ include/linux/netdev_features.h                    |    9 +-
+ include/linux/netdevice.h                          |   62 +-
+ include/linux/of_net.h                             |   10 +
+ include/linux/openvswitch.h                        |   13 +-
+ include/linux/phy.h                                |   10 +
+ include/linux/platform_data/cpsw.h                 |    2 +-
+ include/linux/rtnetlink.h                          |    9 +
+ include/linux/sh_eth.h                             |    1 +
+ include/linux/skbuff.h                             |   52 +
+ include/linux/socket.h                             |    1 +
+ include/linux/ssb/ssb.h                            |    6 +-
+ include/linux/tcp.h                                |   21 +-
+ include/linux/virtio.h                             |    6 -
+ include/linux/vm_sockets.h                         |   23 +
+ include/net/caif/caif_shm.h                        |   26 -
+ include/net/cfg80211.h                             |  126 +-
+ include/net/dn_fib.h                               |   28 +-
+ include/net/firewire.h                             |   25 +
+ include/net/gre.h                                  |   51 +
+ include/net/inet_connection_sock.h                 |    5 +-
+ include/net/inet_frag.h                            |   22 +-
+ include/net/ip6_tunnel.h                           |   21 +
+ include/net/ip_tunnels.h                           |  177 ++
+ include/net/ip_vs.h                                |    2 +-
+ include/net/ipip.h                                 |   87 -
+ include/net/ipv6.h                                 |   22 +-
+ include/net/mac80211.h                             |   29 +-
+ include/net/netfilter/nf_conntrack_core.h          |    1 +
+ include/net/netns/ipv6.h                           |    1 +
+ include/net/request_sock.h                         |    8 +-
+ include/net/rtnetlink.h                            |    2 +-
+ include/net/sock.h                                 |    1 +
+ include/net/tcp.h                                  |  145 +-
+ include/uapi/asm-generic/socket.h                  |    2 +
+ include/uapi/linux/cn_proc.h                       |   10 +-
+ include/uapi/linux/filter.h                        |    3 +-
+ include/uapi/linux/if_ether.h                      |    3 +
+ include/uapi/linux/if_packet.h                     |    2 +
+ include/uapi/linux/neighbour.h                     |    3 +
+ include/uapi/linux/netlink.h                       |    2 +-
+ include/uapi/linux/netlink_diag.h                  |   42 +
+ include/uapi/linux/nfc.h                           |   16 +
+ include/uapi/linux/nl80211.h                       |  117 +-
+ include/uapi/linux/pkt_sched.h                     |    1 +
+ include/uapi/linux/snmp.h                          |    2 +
+ include/uapi/linux/tcp.h                           |   26 -
+ include/uapi/linux/vm_sockets.h                    |   23 +-
+ kernel/audit.c                                     |   10 +-
+ kernel/signal.c                                    |    2 +
+ net/Kconfig                                        |    1 +
+ net/atm/lec.h                                      |    2 +-
+ net/batman-adv/Kconfig                             |   14 +
+ net/batman-adv/Makefile                            |    3 +-
+ net/batman-adv/bat_iv_ogm.c                        |    5 +
+ net/batman-adv/debugfs.c                           |   18 +
+ net/batman-adv/distributed-arp-table.c             |   22 +-
+ net/batman-adv/gateway_client.c                    |    2 +-
+ net/batman-adv/hard-interface.c                    |   66 +-
+ net/batman-adv/hard-interface.h                    |   13 +-
+ net/batman-adv/main.c                              |   10 +-
+ net/batman-adv/main.h                              |   15 +-
+ net/batman-adv/network-coding.c                    | 1821 +++++++++++++++++++
+ net/batman-adv/network-coding.h                    |  123 ++
+ net/batman-adv/originator.c                        |   10 +-
+ net/batman-adv/packet.h                            |   33 +
+ net/batman-adv/routing.c                           |   49 +-
+ net/batman-adv/send.c                              |    5 +
+ net/batman-adv/soft-interface.c                    |  281 ++-
+ net/batman-adv/soft-interface.h                    |    3 +-
+ net/batman-adv/sysfs.c                             |   22 +-
+ net/batman-adv/translation-table.c                 |   29 +-
+ net/batman-adv/types.h                             |  136 ++
+ net/batman-adv/unicast.c                           |    6 +-
+ net/batman-adv/vis.c                               |    4 +-
+ net/bluetooth/af_bluetooth.c                       |    3 +-
+ net/bluetooth/bnep/netdev.c                        |    2 +-
+ net/bridge/br_fdb.c                                |   14 +-
+ net/bridge/br_if.c                                 |    1 -
+ net/bridge/br_mdb.c                                |    4 +-
+ net/bridge/br_multicast.c                          |    2 +-
+ net/bridge/br_netlink.c                            |   21 +-
+ net/bridge/netfilter/ebt_ulog.c                    |    7 +-
+ net/bridge/netfilter/ebtable_broute.c              |    4 +-
+ net/bridge/netfilter/ebtables.c                    |    2 +-
+ net/caif/caif_dev.c                                |    9 +-
+ net/caif/caif_socket.c                             |   22 +-
+ net/caif/caif_usb.c                                |    4 +-
+ net/caif/cfcnfg.c                                  |   19 +-
+ net/caif/cfctrl.c                                  |   14 +-
+ net/caif/cffrml.c                                  |    4 +-
+ net/caif/cfmuxl.c                                  |    4 +-
+ net/caif/cfpkt_skbuff.c                            |    8 +-
+ net/caif/cfrfml.c                                  |    4 +-
+ net/caif/cfserl.c                                  |    4 +-
+ net/caif/cfsrvl.c                                  |   13 +-
+ net/caif/chnl_net.c                                |    6 +-
+ net/can/af_can.c                                   |   30 +-
+ net/can/gw.c                                       |    5 +-
+ net/core/datagram.c                                |    4 +-
+ net/core/dev.c                                     |   80 +-
+ net/core/ethtool.c                                 |    1 +
+ net/core/fib_rules.c                               |    4 +-
+ net/core/filter.c                                  |    5 +
+ net/core/flow.c                                    |   42 +-
+ net/core/flow_dissector.c                          |   68 +
+ net/core/neighbour.c                               |    6 +-
+ net/core/net-procfs.c                              |    2 +-
+ net/core/netpoll.c                                 |    3 +-
+ net/core/rtnetlink.c                               |  176 +-
+ net/core/skbuff.c                                  |   50 +-
+ net/core/sock.c                                    |   10 +-
+ net/core/utils.c                                   |    5 +-
+ net/dcb/dcbevent.c                                 |    1 +
+ net/dcb/dcbnl.c                                    |    2 +-
+ net/dccp/ipv4.c                                    |    5 +-
+ net/dccp/ipv6.c                                    |    5 +-
+ net/decnet/dn_dev.c                                |    4 +-
+ net/decnet/dn_fib.c                                |  203 ++-
+ net/decnet/dn_route.c                              |   43 +-
+ net/decnet/dn_table.c                              |   46 +-
+ net/decnet/netfilter/dn_rtmsg.c                    |   12 +-
+ net/dsa/dsa.c                                      |  233 ++-
+ net/ethernet/eth.c                                 |    2 +-
+ net/ieee802154/6lowpan.c                           |  138 +-
+ net/ieee802154/6lowpan.h                           |    7 +-
+ net/ieee802154/dgram.c                             |   10 +
+ net/ieee802154/netlink.c                           |    8 +-
+ net/ipv4/Kconfig                                   |    7 +
+ net/ipv4/Makefile                                  |    1 +
+ net/ipv4/af_inet.c                                 |   10 +-
+ net/ipv4/arp.c                                     |   27 +-
+ net/ipv4/devinet.c                                 |   83 +-
+ net/ipv4/fib_frontend.c                            |   10 +-
+ net/ipv4/gre.c                                     |    5 -
+ net/ipv4/inet_connection_sock.c                    |    2 +-
+ net/ipv4/inet_diag.c                               |    4 +-
+ net/ipv4/inet_fragment.c                           |   84 +-
+ net/ipv4/inet_lro.c                                |    5 +-
+ net/ipv4/ip_fragment.c                             |   31 +-
+ net/ipv4/ip_gre.c                                  | 1517 ++++------------
+ net/ipv4/ip_tunnel.c                               | 1035 +++++++++++
+ net/ipv4/ip_vti.c                                  |   42 +-
+ net/ipv4/ipconfig.c                                |   13 +-
+ net/ipv4/ipip.c                                    |  748 +-------
+ net/ipv4/ipmr.c                                    |   12 +-
+ net/ipv4/netfilter/arptable_filter.c               |    4 +-
+ net/ipv4/netfilter/ipt_ULOG.c                      |    4 +-
+ net/ipv4/proc.c                                    |    2 +
+ net/ipv4/route.c                                   |    2 +-
+ net/ipv4/syncookies.c                              |    3 +-
+ net/ipv4/sysctl_net_ipv4.c                         |   18 +-
+ net/ipv4/tcp.c                                     |  268 +--
+ net/ipv4/tcp_input.c                               |  606 ++-----
+ net/ipv4/tcp_ipv4.c                                |  108 +-
+ net/ipv4/tcp_minisocks.c                           |   44 +-
+ net/ipv4/tcp_output.c                              |  367 ++--
+ net/ipv4/tcp_timer.c                               |   21 +-
+ net/ipv4/tcp_westwood.c                            |    2 +-
+ net/ipv4/udp.c                                     |  115 +-
+ net/ipv4/udp_diag.c                                |    6 +-
+ net/ipv6/Kconfig                                   |    2 +
+ net/ipv6/addrconf.c                                |  108 +-
+ net/ipv6/addrlabel.c                               |   12 +-
+ net/ipv6/af_inet6.c                                |    7 +-
+ net/ipv6/datagram.c                                |   20 +-
+ net/ipv6/icmp.c                                    |    2 +-
+ net/ipv6/inet6_connection_sock.c                   |   10 +-
+ net/ipv6/ip6_flowlabel.c                           |   11 +-
+ net/ipv6/ip6_gre.c                                 |   62 +-
+ net/ipv6/ip6_offload.c                             |    4 +-
+ net/ipv6/ip6_tunnel.c                              |   16 +-
+ net/ipv6/ip6mr.c                                   |   10 +-
+ net/ipv6/ndisc.c                                   |    2 -
+ net/ipv6/netfilter/ip6t_NPT.c                      |   11 +-
+ net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c     |    8 +-
+ net/ipv6/raw.c                                     |    9 +-
+ net/ipv6/reassembly.c                              |   23 +-
+ net/ipv6/route.c                                   |    6 +-
+ net/ipv6/sit.c                                     |   41 +-
+ net/ipv6/syncookies.c                              |    3 +-
+ net/ipv6/tcp_ipv6.c                                |   56 +-
+ net/ipv6/udp.c                                     |   13 +-
+ net/ipv6/udp_offload.c                             |    8 +-
+ net/iucv/af_iucv.c                                 |    3 +-
+ net/l2tp/l2tp_core.c                               |    2 +-
+ net/mac80211/cfg.c                                 |  151 +-
+ net/mac80211/debugfs_sta.c                         |   31 +
+ net/mac80211/driver-ops.h                          |    7 +-
+ net/mac80211/ht.c                                  |   52 +-
+ net/mac80211/ibss.c                                |   29 +-
+ net/mac80211/ieee80211_i.h                         |   26 +-
+ net/mac80211/iface.c                               |   14 +-
+ net/mac80211/key.c                                 |  103 +-
+ net/mac80211/key.h                                 |    5 +-
+ net/mac80211/main.c                                |   55 +-
+ net/mac80211/mesh.c                                |   59 +-
+ net/mac80211/mesh.h                                |   12 -
+ net/mac80211/mesh_plink.c                          |   37 +-
+ net/mac80211/mlme.c                                |  100 +-
+ net/mac80211/offchannel.c                          |    2 +-
+ net/mac80211/pm.c                                  |  117 +-
+ net/mac80211/rc80211_minstrel.c                    |  204 ++-
+ net/mac80211/rc80211_minstrel.h                    |   31 +-
+ net/mac80211/rc80211_minstrel_debugfs.c            |   12 +-
+ net/mac80211/rc80211_minstrel_ht.c                 |   79 +-
+ net/mac80211/rc80211_minstrel_ht.h                 |    6 +-
+ net/mac80211/rx.c                                  |   61 +-
+ net/mac80211/sta_info.c                            |   12 +-
+ net/mac80211/sta_info.h                            |    2 -
+ net/mac80211/trace.h                               |   11 +-
+ net/mac80211/tx.c                                  |    2 +-
+ net/mac80211/util.c                                |   73 +-
+ net/mac80211/vht.c                                 |  212 ++-
+ net/mac802154/mac802154.h                          |    1 +
+ net/mac802154/mac_cmd.c                            |    1 +
+ net/mac802154/mib.c                                |    9 +
+ net/mac802154/wpan.c                               |    2 +
+ net/netfilter/ipset/ip_set_core.c                  |    5 +-
+ net/netfilter/ipvs/ip_vs_core.c                    |    8 +-
+ net/netfilter/ipvs/ip_vs_ctl.c                     |    8 +-
+ net/netfilter/ipvs/ip_vs_est.c                     |    2 +-
+ net/netfilter/nf_conntrack_core.c                  |   47 +-
+ net/netfilter/nf_conntrack_netlink.c               |  100 +-
+ net/netfilter/nf_conntrack_standalone.c            |   16 +-
+ net/netfilter/nfnetlink.c                          |    7 +-
+ net/netfilter/nfnetlink_log.c                      |    4 +-
+ net/netfilter/nfnetlink_queue_core.c               |   98 +-
+ net/netlink/Kconfig                                |   10 +
+ net/netlink/Makefile                               |    3 +
+ net/netlink/af_netlink.c                           |   63 +-
+ net/netlink/af_netlink.h                           |   62 +
+ net/netlink/diag.c                                 |  188 ++
+ net/nfc/llcp/commands.c                            |  205 ++-
+ net/nfc/llcp/llcp.c                                |  112 +-
+ net/nfc/llcp/llcp.h                                |   36 +-
+ net/nfc/llcp/sock.c                                |  133 +-
+ net/nfc/netlink.c                                  |  172 ++
+ net/nfc/nfc.h                                      |   14 +
+ net/openvswitch/datapath.c                         |   15 +-
+ net/openvswitch/datapath.h                         |    2 +-
+ net/openvswitch/flow.c                             |    6 +-
+ net/openvswitch/vport-internal_dev.c               |   13 +-
+ net/openvswitch/vport.h                            |    4 +-
+ net/packet/af_packet.c                             |  114 +-
+ net/packet/internal.h                              |    3 +-
+ net/phonet/pn_netlink.c                            |    4 +-
+ net/rfkill/rfkill-regulator.c                      |    2 +-
+ net/sched/act_api.c                                |    2 +-
+ net/sched/cls_api.c                                |   15 +-
+ net/sched/sch_api.c                                |   44 +-
+ net/sched/sch_htb.c                                |   31 +-
+ net/sctp/socket.c                                  |    3 +-
+ net/tipc/netlink.c                                 |    6 +-
+ net/unix/af_unix.c                                 |    4 +-
+ net/vmw_vsock/vmci_transport.c                     |   16 +-
+ net/vmw_vsock/vmci_transport.h                     |    3 +
+ net/wireless/ap.c                                  |   62 -
+ net/wireless/core.c                                |   73 +-
+ net/wireless/core.h                                |   24 +-
+ net/wireless/mesh.c                                |   15 +-
+ net/wireless/mlme.c                                |  230 +--
+ net/wireless/nl80211.c                             | 1885 +++++++++++++-------
+ net/wireless/nl80211.h                             |   68 -
+ net/wireless/rdev-ops.h                            |   20 +-
+ net/wireless/reg.c                                 |    6 +-
+ net/wireless/sme.c                                 |   26 +-
+ net/wireless/sysfs.c                               |   25 +-
+ net/wireless/trace.h                               |   46 +
+ net/wireless/util.c                                |    2 +-
+ net/xfrm/xfrm_policy.c                             |   23 +-
+ security/selinux/hooks.c                           |    4 +-
+ security/selinux/netlink.c                         |    3 +-
+ tools/Makefile                                     |   11 +-
+ tools/net/Makefile                                 |   15 +
+ tools/net/bpf_jit_disasm.c                         |  199 +++
+ tools/testing/selftests/Makefile                   |    1 +
+ tools/testing/selftests/net/Makefile               |   19 +
+ tools/testing/selftests/net/psock_fanout.c         |  394 ++++
+ tools/testing/selftests/net/run_afpackettests      |   16 +
+ tools/testing/selftests/net/run_netsocktests       |   12 +
+ tools/testing/selftests/net/socket.c               |   92 +
+ 834 files changed, 32819 insertions(+), 15040 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/net/can/atmel-can.txt
+ create mode 100644 Documentation/devicetree/bindings/net/dsa/dsa.txt
+ delete mode 100644 drivers/net/caif/caif_shm_u5500.c
+ delete mode 100644 drivers/net/caif/caif_shmcore.c
+ rename drivers/net/ethernet/freescale/{fec.c => fec_main.c} (97%)
+ create mode 100644 drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h
+ create mode 100644 drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c
+ create mode 100644 drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c
+ create mode 100644 drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c
+ create mode 100644 drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c
+ create mode 100644 drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h
+ create mode 100644 drivers/net/team/team_mode_random.c
+ create mode 100644 drivers/net/wireless/ath/ath6kl/trace.c
+ create mode 100644 drivers/net/wireless/ath/ath6kl/trace.h
+ delete mode 100644 drivers/net/wireless/ath/wil6210/dbg_hexdump.h
+ create mode 100644 drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
+ create mode 100644 drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h
+ create mode 100644 drivers/net/wireless/brcm80211/brcmfmac/tracepoint.c
+ create mode 100644 drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h
+ create mode 100644 drivers/net/wireless/brcm80211/brcmsmac/led.c
+ create mode 100644 drivers/net/wireless/brcm80211/brcmsmac/led.h
+ rename drivers/net/wireless/iwlwifi/{pcie/1000.c => iwl-1000.c} (99%)
+ rename drivers/net/wireless/iwlwifi/{pcie/2000.c => iwl-2000.c} (99%)
+ rename drivers/net/wireless/iwlwifi/{pcie/5000.c => iwl-5000.c} (99%)
+ rename drivers/net/wireless/iwlwifi/{pcie/6000.c => iwl-6000.c} (99%)
+ rename drivers/net/wireless/iwlwifi/{pcie/7000.c => iwl-7000.c} (58%)
+ create mode 100644 drivers/net/wireless/iwlwifi/mvm/bt-coex.c
+ create mode 100644 drivers/net/wireless/iwlwifi/mvm/fw-api-bt-coex.h
+ delete mode 100644 drivers/net/wireless/iwlwifi/pcie/cfg.h
+ create mode 100644 drivers/net/wireless/mwifiex/ethtool.c
+ create mode 100644 drivers/scsi/csiostor/csio_hw_chip.h
+ create mode 100644 drivers/scsi/csiostor/csio_hw_t4.c
+ create mode 100644 drivers/scsi/csiostor/csio_hw_t5.c
+ create mode 100644 include/linux/vm_sockets.h
+ delete mode 100644 include/net/caif/caif_shm.h
+ create mode 100644 include/net/firewire.h
+ create mode 100644 include/net/ip_tunnels.h
+ delete mode 100644 include/net/ipip.h
+ create mode 100644 include/uapi/linux/netlink_diag.h
+ create mode 100644 net/batman-adv/network-coding.c
+ create mode 100644 net/batman-adv/network-coding.h
+ create mode 100644 net/ipv4/ip_tunnel.c
+ create mode 100644 net/netlink/Kconfig
+ create mode 100644 net/netlink/af_netlink.h
+ create mode 100644 net/netlink/diag.c
+ create mode 100644 tools/net/Makefile
+ create mode 100644 tools/net/bpf_jit_disasm.c
+ create mode 100644 tools/testing/selftests/net/Makefile
+ create mode 100644 tools/testing/selftests/net/psock_fanout.c
+ create mode 100644 tools/testing/selftests/net/run_afpackettests
+ create mode 100644 tools/testing/selftests/net/run_netsocktests
+ create mode 100644 tools/testing/selftests/net/socket.c
+$ git am -3 ../patches/0001-drivers-net-fix-up-for-code-movement-from-rt2x00pci..patch
+Applying: drivers:net: fix up for code movement from rt2x00pci.c
+$ git reset HEAD^
+Unstaged changes after reset:
+M	drivers/net/wireless/rt2x00/rt2x00mmio.c
+$ git add -A .
+$ git commit -v -a --amend
+[master 30ab952] Merge remote-tracking branch 'net-next/master'
+Merging ipsec-next/master (05600a7 xfrm_user: constify netlink dispatch table)
+$ git merge ipsec-next/master
+Merge made by the 'recursive' strategy.
+ include/net/xfrm.h           |  1 +
+ include/uapi/linux/xfrm.h    |  3 +++
+ net/ipv4/ipcomp.c            |  1 +
+ net/ipv4/xfrm4_mode_tunnel.c |  8 ++++++--
+ net/ipv6/xfrm6_mode_tunnel.c |  7 +++++--
+ net/xfrm/xfrm_state.c        |  1 +
+ net/xfrm/xfrm_user.c         | 17 +++++++++++++++--
+ 7 files changed, 32 insertions(+), 6 deletions(-)
+Merging wireless-next/master (84bcc0c brcmfmac: enable sk_buff queueing when credits deplete)
+$ git merge wireless-next/master
+Resolved 'drivers/nfc/microread/mei.c' using previous resolution.
+Resolved 'net/mac80211/sta_info.c' using previous resolution.
+Resolved 'net/wireless/core.h' using previous resolution.
+Auto-merging net/wireless/sme.c
+Auto-merging net/wireless/core.h
+CONFLICT (content): Merge conflict in net/wireless/core.h
+Auto-merging net/mac80211/tx.c
+Auto-merging net/mac80211/sta_info.c
+CONFLICT (content): Merge conflict in net/mac80211/sta_info.c
+Auto-merging net/mac80211/offchannel.c
+Auto-merging net/mac80211/iface.c
+Auto-merging net/mac80211/ieee80211_i.h
+Auto-merging net/mac80211/cfg.c
+Auto-merging net/bluetooth/af_bluetooth.c
+Auto-merging drivers/nfc/microread/mei.c
+CONFLICT (content): Merge conflict in drivers/nfc/microread/mei.c
+Auto-merging drivers/net/wireless/mwifiex/cfg80211.c
+Auto-merging drivers/net/wireless/iwlwifi/pcie/tx.c
+Auto-merging drivers/net/wireless/iwlegacy/common.h
+Auto-merging drivers/net/wireless/iwlegacy/common.c
+Auto-merging drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
+Auto-merging drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+Auto-merging drivers/net/wireless/ath/ath9k/main.c
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master afbcb63] Merge remote-tracking branch 'wireless-next/master'
+$ git diff -M --stat --summary HEAD^..
+ Documentation/DocBook/80211.tmpl                   |    2 +-
+ drivers/bcma/driver_chipcommon.c                   |    5 +-
+ drivers/bcma/driver_chipcommon_pmu.c               |   34 +-
+ drivers/bcma/scan.c                                |   16 +-
+ drivers/bcma/sprom.c                               |    1 +
+ drivers/bluetooth/btmrvl_sdio.c                    |    8 +-
+ drivers/net/wireless/ath/ar5523/ar5523.c           |    2 +-
+ drivers/net/wireless/ath/ath9k/ar9002_calib.c      |    9 +-
+ drivers/net/wireless/ath/ath9k/ar9003_calib.c      |    3 +-
+ drivers/net/wireless/ath/ath9k/debug.c             |    2 +-
+ drivers/net/wireless/ath/ath9k/main.c              |    2 +-
+ drivers/net/wireless/ath/carl9170/carl9170.h       |    8 +-
+ drivers/net/wireless/ath/carl9170/debug.c          |    2 +-
+ drivers/net/wireless/ath/carl9170/main.c           |    4 +-
+ drivers/net/wireless/ath/carl9170/phy.c            |   81 +-
+ drivers/net/wireless/b43/b43.h                     |    2 +
+ drivers/net/wireless/b43/main.c                    |   23 +-
+ drivers/net/wireless/b43/phy_lp.c                  |   12 +-
+ drivers/net/wireless/b43/phy_n.c                   |    6 +-
+ drivers/net/wireless/b43/radio_2056.c              |    6 +-
+ drivers/net/wireless/b43/sdio.h                    |    4 +-
+ drivers/net/wireless/b43/tables_nphy.c             |    4 +-
+ drivers/net/wireless/b43/tables_phy_lcn.c          |    6 +-
+ drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c   |   30 +-
+ .../net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c |   60 +-
+ drivers/net/wireless/brcm80211/brcmfmac/dhd.h      |   32 +-
+ drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h  |   13 +-
+ drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c  |    4 +-
+ drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c  |   46 +-
+ drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h  |   16 +
+ .../net/wireless/brcm80211/brcmfmac/dhd_linux.c    |   79 +-
+ drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c |   76 +-
+ drivers/net/wireless/brcm80211/brcmfmac/fweh.c     |   10 +-
+ drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c | 1714 ++++++++++++-
+ drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h |    8 +
+ .../net/wireless/brcm80211/brcmfmac/wl_cfg80211.c  |  326 ++-
+ drivers/net/wireless/brcm80211/brcmsmac/aiutils.c  |    6 -
+ drivers/net/wireless/brcm80211/brcmsmac/d11.h      |    1 +
+ .../net/wireless/brcm80211/brcmsmac/mac80211_if.c  |   87 +-
+ drivers/net/wireless/brcm80211/brcmsmac/main.c     |  362 ++-
+ drivers/net/wireless/brcm80211/brcmsmac/main.h     |   25 +-
+ .../net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c  |   40 +-
+ .../net/wireless/brcm80211/brcmsmac/phy/phy_int.h  |    1 -
+ .../net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c  |   35 +-
+ .../net/wireless/brcm80211/brcmsmac/phy/phy_n.c    |   14 +-
+ drivers/net/wireless/brcm80211/brcmsmac/pmu.c      |   54 -
+ drivers/net/wireless/brcm80211/brcmsmac/pmu.h      |    6 -
+ drivers/net/wireless/brcm80211/brcmsmac/pub.h      |   17 +-
+ .../net/wireless/brcm80211/include/brcmu_wifi.h    |   28 +-
+ drivers/net/wireless/iwlegacy/common.c             |    3 +-
+ drivers/net/wireless/iwlegacy/common.h             |    2 +-
+ drivers/net/wireless/iwlwifi/dvm/mac80211.c        |    2 +-
+ drivers/net/wireless/iwlwifi/iwl-drv.c             |    4 -
+ drivers/net/wireless/iwlwifi/iwl-fw.h              |   25 +
+ drivers/net/wireless/iwlwifi/iwl-modparams.h       |    2 -
+ drivers/net/wireless/iwlwifi/iwl-test.c            |    3 +-
+ drivers/net/wireless/iwlwifi/mvm/bt-coex.c         |   21 +-
+ drivers/net/wireless/iwlwifi/mvm/d3.c              |   10 +-
+ drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h       |    6 +
+ drivers/net/wireless/iwlwifi/mvm/fw-api.h          |   38 +-
+ drivers/net/wireless/iwlwifi/mvm/fw.c              |   23 +-
+ drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c        |   30 +-
+ drivers/net/wireless/iwlwifi/mvm/mac80211.c        |   29 +-
+ drivers/net/wireless/iwlwifi/mvm/mvm.h             |   15 +-
+ drivers/net/wireless/iwlwifi/mvm/nvm.c             |  136 +-
+ drivers/net/wireless/iwlwifi/mvm/ops.c             |   36 +-
+ drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c        |    7 +-
+ drivers/net/wireless/iwlwifi/mvm/quota.c           |    3 +-
+ drivers/net/wireless/iwlwifi/mvm/scan.c            |    4 +-
+ drivers/net/wireless/iwlwifi/mvm/time-event.c      |   38 +-
+ drivers/net/wireless/iwlwifi/mvm/time-event.h      |    3 +-
+ drivers/net/wireless/iwlwifi/mvm/tx.c              |   10 +-
+ drivers/net/wireless/iwlwifi/pcie/tx.c             |    5 +-
+ drivers/net/wireless/mac80211_hwsim.c              |    8 +-
+ drivers/net/wireless/mwifiex/11ac.c                |   41 +
+ drivers/net/wireless/mwifiex/11ac.h                |   17 +
+ drivers/net/wireless/mwifiex/11n.c                 |   22 +
+ drivers/net/wireless/mwifiex/cfg80211.c            |   12 +
+ drivers/net/wireless/mwifiex/decl.h                |   11 +-
+ drivers/net/wireless/mwifiex/fw.h                  |   11 +
+ drivers/net/wireless/mwifiex/ioctl.h               |    8 +
+ drivers/net/wireless/mwifiex/join.c                |   23 +
+ drivers/net/wireless/mwifiex/main.h                |    8 +
+ drivers/net/wireless/mwifiex/pcie.c                |   47 +-
+ drivers/net/wireless/mwifiex/sta_cmd.c             |    4 +
+ drivers/net/wireless/mwifiex/sta_cmdresp.c         |    2 +
+ drivers/net/wireless/mwifiex/uap_cmd.c             |   55 +
+ drivers/net/wireless/mwifiex/wmm.c                 |    5 +-
+ drivers/net/wireless/mwl8k.c                       |   10 +-
+ drivers/net/wireless/p54/main.c                    |    2 +-
+ drivers/net/wireless/rt2x00/rt2800lib.c            |   92 +-
+ drivers/net/wireless/rt2x00/rt2x00.h               |   19 +-
+ drivers/net/wireless/rt2x00/rt2x00mac.c            |    2 +-
+ drivers/net/wireless/rtlwifi/Kconfig               |    9 +
+ drivers/net/wireless/rtlwifi/Makefile              |    1 +
+ drivers/net/wireless/rtlwifi/base.c                |  379 ++-
+ drivers/net/wireless/rtlwifi/base.h                |   14 +-
+ drivers/net/wireless/rtlwifi/core.c                |  215 +-
+ drivers/net/wireless/rtlwifi/debug.c               |    5 +-
+ drivers/net/wireless/rtlwifi/debug.h               |   13 +-
+ drivers/net/wireless/rtlwifi/efuse.c               |   53 +-
+ drivers/net/wireless/rtlwifi/efuse.h               |    1 -
+ drivers/net/wireless/rtlwifi/pci.c                 |  150 +-
+ drivers/net/wireless/rtlwifi/pci.h                 |    2 +
+ drivers/net/wireless/rtlwifi/ps.c                  |  330 ++-
+ drivers/net/wireless/rtlwifi/ps.h                  |    2 +
+ drivers/net/wireless/rtlwifi/rtl8188ee/Makefile    |   16 +
+ drivers/net/wireless/rtlwifi/rtl8188ee/def.h       |  324 +++
+ drivers/net/wireless/rtlwifi/rtl8188ee/dm.c        | 1794 ++++++++++++++
+ drivers/net/wireless/rtlwifi/rtl8188ee/dm.h        |  326 +++
+ drivers/net/wireless/rtlwifi/rtl8188ee/fw.c        |  830 +++++++
+ drivers/net/wireless/rtlwifi/rtl8188ee/fw.h        |  301 +++
+ drivers/net/wireless/rtlwifi/rtl8188ee/hw.c        | 2529 ++++++++++++++++++++
+ drivers/net/wireless/rtlwifi/rtl8188ee/hw.h        |   68 +
+ drivers/net/wireless/rtlwifi/rtl8188ee/led.c       |  157 ++
+ drivers/net/wireless/rtlwifi/rtl8188ee/led.h       |   38 +
+ drivers/net/wireless/rtlwifi/rtl8188ee/phy.c       | 2212 +++++++++++++++++
+ drivers/net/wireless/rtlwifi/rtl8188ee/phy.h       |  237 ++
+ drivers/net/wireless/rtlwifi/rtl8188ee/pwrseq.c    |  109 +
+ drivers/net/wireless/rtlwifi/rtl8188ee/pwrseq.h    |  327 +++
+ drivers/net/wireless/rtlwifi/rtl8188ee/pwrseqcmd.c |  140 ++
+ drivers/net/wireless/rtlwifi/rtl8188ee/pwrseqcmd.h |   97 +
+ drivers/net/wireless/rtlwifi/rtl8188ee/reg.h       | 2258 +++++++++++++++++
+ drivers/net/wireless/rtlwifi/rtl8188ee/rf.c        |  467 ++++
+ drivers/net/wireless/rtlwifi/rtl8188ee/rf.h        |   46 +
+ drivers/net/wireless/rtlwifi/rtl8188ee/sw.c        |  400 ++++
+ drivers/net/wireless/rtlwifi/rtl8188ee/sw.h        |   36 +
+ drivers/net/wireless/rtlwifi/rtl8188ee/table.c     |  643 +++++
+ drivers/net/wireless/rtlwifi/rtl8188ee/table.h     |   47 +
+ drivers/net/wireless/rtlwifi/rtl8188ee/trx.c       |  817 +++++++
+ drivers/net/wireless/rtlwifi/rtl8188ee/trx.h       |  795 ++++++
+ drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c  |  101 +-
+ drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c  |   99 +-
+ drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h  |    4 +
+ drivers/net/wireless/rtlwifi/rtl8192ce/hw.c        |  118 +-
+ drivers/net/wireless/rtlwifi/rtl8192ce/hw.h        |    4 +
+ drivers/net/wireless/rtlwifi/rtl8192ce/reg.h       |    1 +
+ drivers/net/wireless/rtlwifi/rtl8192ce/sw.c        |    4 +-
+ drivers/net/wireless/rtlwifi/rtl8192ce/trx.c       |  324 +--
+ drivers/net/wireless/rtlwifi/rtl8192cu/hw.c        |   20 +-
+ drivers/net/wireless/rtlwifi/rtl8192cu/sw.c        |    2 +-
+ drivers/net/wireless/rtlwifi/rtl8192cu/trx.c       |    2 +-
+ drivers/net/wireless/rtlwifi/rtl8192de/dm.c        |   32 +-
+ drivers/net/wireless/rtlwifi/rtl8192de/hw.c        |    2 +-
+ drivers/net/wireless/rtlwifi/rtl8192de/phy.c       |   40 +-
+ drivers/net/wireless/rtlwifi/rtl8192de/reg.h       |    2 +-
+ drivers/net/wireless/rtlwifi/rtl8192de/sw.c        |    6 +-
+ drivers/net/wireless/rtlwifi/rtl8192se/def.h       |    7 -
+ drivers/net/wireless/rtlwifi/rtl8192se/dm.c        |   49 +-
+ drivers/net/wireless/rtlwifi/rtl8192se/hw.c        |  150 +-
+ drivers/net/wireless/rtlwifi/rtl8192se/hw.h        |    3 +-
+ drivers/net/wireless/rtlwifi/rtl8192se/phy.c       |   61 +-
+ drivers/net/wireless/rtlwifi/rtl8192se/phy.h       |    1 +
+ drivers/net/wireless/rtlwifi/rtl8192se/sw.c        |    3 +-
+ drivers/net/wireless/rtlwifi/rtl8192se/trx.c       |  296 +--
+ drivers/net/wireless/rtlwifi/rtl8723ae/dm.c        |   88 +-
+ drivers/net/wireless/rtlwifi/rtl8723ae/dm.h        |    6 +
+ drivers/net/wireless/rtlwifi/rtl8723ae/fw.c        |   97 +-
+ drivers/net/wireless/rtlwifi/rtl8723ae/fw.h        |    7 +-
+ drivers/net/wireless/rtlwifi/rtl8723ae/hw.c        |   70 +-
+ drivers/net/wireless/rtlwifi/rtl8723ae/led.c       |   22 +-
+ drivers/net/wireless/rtlwifi/rtl8723ae/sw.c        |    2 +-
+ drivers/net/wireless/rtlwifi/rtl8723ae/trx.c       |   10 +-
+ drivers/net/wireless/rtlwifi/usb.c                 |  220 +-
+ drivers/net/wireless/rtlwifi/usb.h                 |    5 +-
+ drivers/net/wireless/rtlwifi/wifi.h                |  221 +-
+ drivers/net/wireless/ti/wl1251/sdio.c              |    4 +-
+ drivers/net/wireless/ti/wl12xx/main.c              |    1 +
+ drivers/net/wireless/ti/wl12xx/wl12xx.h            |    2 +
+ drivers/net/wireless/ti/wl18xx/main.c              |   25 +-
+ drivers/net/wireless/ti/wl18xx/reg.h               |   29 +
+ drivers/net/wireless/ti/wl18xx/wl18xx.h            |    4 +-
+ drivers/net/wireless/ti/wlcore/acx.c               |   29 +
+ drivers/net/wireless/ti/wlcore/acx.h               |   16 +-
+ drivers/net/wireless/ti/wlcore/cmd.c               |   32 +
+ drivers/net/wireless/ti/wlcore/debug.h             |   33 +-
+ drivers/net/wireless/ti/wlcore/debugfs.c           |    3 +-
+ drivers/net/wireless/ti/wlcore/event.c             |    9 +-
+ drivers/net/wireless/ti/wlcore/main.c              |  200 +-
+ drivers/net/wireless/ti/wlcore/ps.c                |    4 +-
+ drivers/net/wireless/ti/wlcore/tx.c                |   39 +-
+ drivers/net/wireless/ti/wlcore/wlcore.h            |    3 +
+ drivers/net/wireless/ti/wlcore/wlcore_i.h          |   29 +-
+ drivers/ssb/pci.c                                  |   23 +-
+ include/linux/bcma/bcma.h                          |   54 +
+ include/linux/bcma/bcma_driver_chipcommon.h        |    3 +
+ include/linux/ssb/ssb.h                            |   54 +-
+ include/linux/ssb/ssb_regs.h                       |   10 +-
+ include/net/bluetooth/bluetooth.h                  |   12 +-
+ include/net/bluetooth/hci.h                        |   21 +-
+ include/net/bluetooth/hci_core.h                   |   28 +-
+ include/net/bluetooth/rfcomm.h                     |    6 -
+ include/net/mac80211.h                             |   68 +-
+ net/bluetooth/a2mp.c                               |    6 +-
+ net/bluetooth/af_bluetooth.c                       |   15 +-
+ net/bluetooth/bnep/sock.c                          |    4 +-
+ net/bluetooth/cmtp/sock.c                          |    4 +-
+ net/bluetooth/hci_conn.c                           |    4 +-
+ net/bluetooth/hci_core.c                           |  727 +++++-
+ net/bluetooth/hci_event.c                          |  605 +----
+ net/bluetooth/hci_sock.c                           |    9 +-
+ net/bluetooth/hci_sysfs.c                          |    4 +-
+ net/bluetooth/hidp/core.c                          |    4 +
+ net/bluetooth/hidp/sock.c                          |    4 +-
+ net/bluetooth/l2cap_sock.c                         |    4 +-
+ net/bluetooth/mgmt.c                               |  680 ++++--
+ net/bluetooth/rfcomm/core.c                        |  167 +-
+ net/bluetooth/rfcomm/sock.c                        |    3 +-
+ net/bluetooth/sco.c                                |    3 +-
+ net/mac80211/cfg.c                                 |   29 +-
+ net/mac80211/debugfs_key.c                         |   10 +-
+ net/mac80211/debugfs_netdev.c                      |   22 +-
+ net/mac80211/driver-ops.h                          |   60 +-
+ net/mac80211/ieee80211_i.h                         |   11 +-
+ net/mac80211/iface.c                               |   17 +-
+ net/mac80211/key.c                                 |  129 +-
+ net/mac80211/key.h                                 |   15 +-
+ net/mac80211/main.c                                |   22 +-
+ net/mac80211/mesh.c                                |    5 +-
+ net/mac80211/mlme.c                                |   12 +-
+ net/mac80211/offchannel.c                          |    8 +-
+ net/mac80211/pm.c                                  |    6 +-
+ net/mac80211/rc80211_minstrel_ht.c                 |   24 +-
+ net/mac80211/scan.c                                |    7 +-
+ net/mac80211/sta_info.c                            |   54 +-
+ net/mac80211/sta_info.h                            |    9 +-
+ net/mac80211/trace.h                               |   35 +-
+ net/mac80211/tx.c                                  |    8 +-
+ net/mac80211/util.c                                |   48 +-
+ net/wireless/core.c                                |    4 +-
+ net/wireless/sme.c                                 |    2 +-
+ 231 files changed, 22518 insertions(+), 3456 deletions(-)
+ create mode 100644 drivers/net/wireless/rtlwifi/rtl8188ee/Makefile
+ create mode 100644 drivers/net/wireless/rtlwifi/rtl8188ee/def.h
+ create mode 100644 drivers/net/wireless/rtlwifi/rtl8188ee/dm.c
+ create mode 100644 drivers/net/wireless/rtlwifi/rtl8188ee/dm.h
+ create mode 100644 drivers/net/wireless/rtlwifi/rtl8188ee/fw.c
+ create mode 100644 drivers/net/wireless/rtlwifi/rtl8188ee/fw.h
+ create mode 100644 drivers/net/wireless/rtlwifi/rtl8188ee/hw.c
+ create mode 100644 drivers/net/wireless/rtlwifi/rtl8188ee/hw.h
+ create mode 100644 drivers/net/wireless/rtlwifi/rtl8188ee/led.c
+ create mode 100644 drivers/net/wireless/rtlwifi/rtl8188ee/led.h
+ create mode 100644 drivers/net/wireless/rtlwifi/rtl8188ee/phy.c
+ create mode 100644 drivers/net/wireless/rtlwifi/rtl8188ee/phy.h
+ create mode 100644 drivers/net/wireless/rtlwifi/rtl8188ee/pwrseq.c
+ create mode 100644 drivers/net/wireless/rtlwifi/rtl8188ee/pwrseq.h
+ create mode 100644 drivers/net/wireless/rtlwifi/rtl8188ee/pwrseqcmd.c
+ create mode 100644 drivers/net/wireless/rtlwifi/rtl8188ee/pwrseqcmd.h
+ create mode 100644 drivers/net/wireless/rtlwifi/rtl8188ee/reg.h
+ create mode 100644 drivers/net/wireless/rtlwifi/rtl8188ee/rf.c
+ create mode 100644 drivers/net/wireless/rtlwifi/rtl8188ee/rf.h
+ create mode 100644 drivers/net/wireless/rtlwifi/rtl8188ee/sw.c
+ create mode 100644 drivers/net/wireless/rtlwifi/rtl8188ee/sw.h
+ create mode 100644 drivers/net/wireless/rtlwifi/rtl8188ee/table.c
+ create mode 100644 drivers/net/wireless/rtlwifi/rtl8188ee/table.h
+ create mode 100644 drivers/net/wireless/rtlwifi/rtl8188ee/trx.c
+ create mode 100644 drivers/net/wireless/rtlwifi/rtl8188ee/trx.h
+$ git am -3 ../patches/rtlwifi__rtl8188ee__Fix_allyesconfig_build_failures.patch
+Applying: rtlwifi: rtl8188ee: Fix allyesconfig build failures
+$ git reset HEAD^
+Unstaged changes after reset:
+M	drivers/net/wireless/rtlwifi/rtl8188ee/hw.c
+M	drivers/net/wireless/rtlwifi/rtl8188ee/phy.c
+M	drivers/net/wireless/rtlwifi/rtl8188ee/phy.h
+M	drivers/net/wireless/rtlwifi/rtl8188ee/pwrseqcmd.c
+M	drivers/net/wireless/rtlwifi/rtl8188ee/pwrseqcmd.h
+$ git add -A .
+$ git commit -v -a --amend
+[master 2701471] Merge remote-tracking branch 'wireless-next/master'
+Merging bluetooth/master (5afff03 Bluetooth: Remove driver init queue from core)
+$ git merge bluetooth/master
+Merge made by the 'recursive' strategy.
+ drivers/bluetooth/ath3k.c         |   2 +
+ drivers/bluetooth/btusb.c         |  35 ++++--
+ drivers/bluetooth/hci_h4.c        |   3 +
+ drivers/bluetooth/hci_ldisc.c     |  15 ++-
+ include/net/bluetooth/bluetooth.h |   1 +
+ include/net/bluetooth/hci_core.h  |  12 +-
+ net/bluetooth/hci_core.c          | 223 +++++++++++++++++++++++++++-----------
+ net/bluetooth/hci_event.c         |  32 +++++-
+ 8 files changed, 235 insertions(+), 88 deletions(-)
+Merging mtd/master (35f8c76 Merge tag 'for-linus-20130318' of git://git.infradead.org/linux-mtd)
+$ git merge mtd/master
+Already up-to-date.
+Merging l2-mtd/master (f6da0c3 mtd: omap2: fix IOERR)
+$ git merge l2-mtd/master
+Auto-merging drivers/ssb/driver_mipscore.c
+Removing drivers/mtd/onenand/onenand_sim.c
+Removing drivers/mtd/nand/rtc_from4.c
+Removing drivers/mtd/nand/ppchameleonevb.c
+Removing drivers/mtd/nand/h1910.c
+Removing drivers/mtd/maps/tqm8xxl.c
+Removing drivers/mtd/maps/rpxlite.c
+Removing drivers/mtd/maps/mbx860.c
+Removing drivers/mtd/maps/ixp2000.c
+Removing drivers/mtd/maps/h720x-flash.c
+Removing drivers/mtd/maps/dmv182.c
+Removing drivers/mtd/maps/dilnetpc.c
+Removing drivers/mtd/maps/dbox2-flash.c
+Removing drivers/mtd/devices/docprobe.c
+Removing drivers/mtd/devices/docecc.c
+Removing drivers/mtd/devices/doc2001plus.c
+Removing drivers/mtd/devices/doc2001.c
+Removing drivers/mtd/devices/doc2000.c
+Auto-merging arch/cris/Kconfig
+Merge made by the 'recursive' strategy.
+ Documentation/ABI/testing/sysfs-class-mtd          |    6 +-
+ .../devicetree/bindings/mtd/partition.txt          |   36 +-
+ arch/arm/configs/lpc32xx_defconfig                 |    1 -
+ arch/arm/mach-pxa/Kconfig                          |    1 -
+ arch/cris/Kconfig                                  |    1 -
+ arch/cris/arch-v32/drivers/Kconfig                 |    1 -
+ arch/m68k/include/asm/commproc.h                   |   17 -
+ drivers/bcma/driver_mips.c                         |    2 +-
+ drivers/mtd/Kconfig                                |   13 -
+ drivers/mtd/Makefile                               |    3 +-
+ drivers/mtd/chips/Kconfig                          |    1 -
+ drivers/mtd/devices/Kconfig                        |   64 --
+ drivers/mtd/devices/Makefile                       |    5 -
+ drivers/mtd/devices/bcm47xxsflash.c                |   13 +-
+ drivers/mtd/devices/bcm47xxsflash.h                |   59 +
+ drivers/mtd/devices/doc2000.c                      | 1178 --------------------
+ drivers/mtd/devices/doc2001.c                      |  824 --------------
+ drivers/mtd/devices/doc2001plus.c                  | 1080 ------------------
+ drivers/mtd/devices/docecc.c                       |  521 ---------
+ drivers/mtd/devices/docg3.c                        |   15 +-
+ drivers/mtd/devices/docprobe.c                     |  325 ------
+ drivers/mtd/devices/elm.c                          |    9 +-
+ drivers/mtd/devices/m25p80.c                       |   25 +-
+ drivers/mtd/devices/mtd_dataflash.c                |    4 +-
+ drivers/mtd/maps/Kconfig                           |   77 --
+ drivers/mtd/maps/Makefile                          |    8 -
+ drivers/mtd/maps/bfin-async-flash.c                |    3 +-
+ drivers/mtd/maps/ck804xrom.c                       |    3 +-
+ drivers/mtd/maps/dbox2-flash.c                     |  123 --
+ drivers/mtd/maps/dc21285.c                         |    3 +-
+ drivers/mtd/maps/dilnetpc.c                        |  496 ---------
+ drivers/mtd/maps/dmv182.c                          |  146 ---
+ drivers/mtd/maps/gpio-addr-flash.c                 |    3 +-
+ drivers/mtd/maps/h720x-flash.c                     |  120 --
+ drivers/mtd/maps/impa7.c                           |    7 +-
+ drivers/mtd/maps/intel_vr_nor.c                    |    4 +-
+ drivers/mtd/maps/ixp2000.c                         |  253 -----
+ drivers/mtd/maps/ixp4xx.c                          |    2 +-
+ drivers/mtd/maps/lantiq-flash.c                    |    3 +-
+ drivers/mtd/maps/mbx860.c                          |   98 --
+ drivers/mtd/maps/pci.c                             |    3 +-
+ drivers/mtd/maps/physmap.c                         |   17 +-
+ drivers/mtd/maps/physmap_of.c                      |   16 +-
+ drivers/mtd/maps/plat-ram.c                        |    2 +-
+ drivers/mtd/maps/pxa2xx-flash.c                    |    4 +-
+ drivers/mtd/maps/rbtx4939-flash.c                  |    5 +-
+ drivers/mtd/maps/rpxlite.c                         |   64 --
+ drivers/mtd/maps/sa1100-flash.c                    |    2 +-
+ drivers/mtd/maps/solutionengine.c                  |    2 +-
+ drivers/mtd/maps/tqm8xxl.c                         |  249 -----
+ drivers/mtd/maps/tsunami_flash.c                   |    5 +-
+ drivers/mtd/mtdchar.c                              |   52 +-
+ drivers/mtd/mtdcore.c                              |   26 +-
+ drivers/mtd/mtdcore.h                              |   30 +-
+ drivers/mtd/mtdpart.c                              |    4 +-
+ drivers/mtd/nand/Kconfig                           |   30 -
+ drivers/mtd/nand/Makefile                          |    3 -
+ drivers/mtd/nand/atmel_nand.c                      |   15 +-
+ drivers/mtd/nand/cafe_nand.c                       |    6 -
+ drivers/mtd/nand/davinci_nand.c                    |   16 +-
+ drivers/mtd/nand/docg4.c                           |   13 +-
+ drivers/mtd/nand/fsmc_nand.c                       |   13 +-
+ drivers/mtd/nand/gpio.c                            |    8 +-
+ drivers/mtd/nand/h1910.c                           |  167 ---
+ drivers/mtd/nand/nand_base.c                       |  194 ++--
+ drivers/mtd/nand/nand_bbt.c                        |   25 -
+ drivers/mtd/nand/nand_ids.c                        |  242 ++--
+ drivers/mtd/nand/nandsim.c                         |   24 +-
+ drivers/mtd/nand/nuc900_nand.c                     |    9 -
+ drivers/mtd/nand/omap2.c                           |    9 +-
+ drivers/mtd/nand/orion_nand.c                      |   13 +-
+ drivers/mtd/nand/ppchameleonevb.c                  |  403 -------
+ drivers/mtd/nand/pxa3xx_nand.c                     |    2 +-
+ drivers/mtd/nand/rtc_from4.c                       |  624 -----------
+ drivers/mtd/nand/sh_flctl.c                        |   16 +-
+ drivers/mtd/nand/sm_common.c                       |   62 +-
+ drivers/mtd/nand/txx9ndfmc.c                       |   13 +-
+ drivers/mtd/ofpart.c                               |    7 +-
+ drivers/mtd/onenand/Kconfig                        |    7 -
+ drivers/mtd/onenand/Makefile                       |    3 -
+ drivers/mtd/onenand/onenand_sim.c                  |  564 ----------
+ drivers/pcmcia/m8xx_pcmcia.c                       |  140 ---
+ drivers/ssb/driver_mipscore.c                      |    2 +-
+ include/linux/mtd/mtd.h                            |    8 +-
+ include/linux/mtd/nand.h                           |  116 +-
+ include/linux/mtd/physmap.h                        |    2 +-
+ include/linux/mtd/plat-ram.h                       |    4 +-
+ include/linux/platform_data/elm.h                  |    2 +-
+ 88 files changed, 559 insertions(+), 8237 deletions(-)
+ delete mode 100644 drivers/mtd/devices/doc2000.c
+ delete mode 100644 drivers/mtd/devices/doc2001.c
+ delete mode 100644 drivers/mtd/devices/doc2001plus.c
+ delete mode 100644 drivers/mtd/devices/docecc.c
+ delete mode 100644 drivers/mtd/devices/docprobe.c
+ delete mode 100644 drivers/mtd/maps/dbox2-flash.c
+ delete mode 100644 drivers/mtd/maps/dilnetpc.c
+ delete mode 100644 drivers/mtd/maps/dmv182.c
+ delete mode 100644 drivers/mtd/maps/h720x-flash.c
+ delete mode 100644 drivers/mtd/maps/ixp2000.c
+ delete mode 100644 drivers/mtd/maps/mbx860.c
+ delete mode 100644 drivers/mtd/maps/rpxlite.c
+ delete mode 100644 drivers/mtd/maps/tqm8xxl.c
+ delete mode 100644 drivers/mtd/nand/h1910.c
+ delete mode 100644 drivers/mtd/nand/ppchameleonevb.c
+ delete mode 100644 drivers/mtd/nand/rtc_from4.c
+ delete mode 100644 drivers/mtd/onenand/onenand_sim.c
+Merging crypto/master (30975d2 hwrng: timeriomem - added devicetree hooks)
+$ git merge crypto/master
+Removing include/linux/platform_data/atmel-aes.h
+Auto-merging drivers/crypto/caam/caamalg.c
+Merge made by the 'recursive' strategy.
+ .../devicetree/bindings/crypto/fsl-imx-sahara.txt  |   15 +
+ .../devicetree/bindings/hwrng/timeriomem_rng.txt   |   18 +
+ .../devicetree/bindings/rng/brcm,bcm2835.txt       |   13 +
+ Documentation/hw_random.txt                        |    2 +-
+ arch/arm/mach-at91/at91sam9g45_devices.c           |   14 +-
+ arch/x86/crypto/Makefile                           |   40 +-
+ arch/x86/crypto/crc32-pclmul_asm.S                 |    6 +-
+ arch/x86/crypto/crc32c-pcl-intel-asm_64.S          |   10 +-
+ arch/x86/crypto/sha256-avx-asm.S                   |  496 +++++++++
+ arch/x86/crypto/sha256-avx2-asm.S                  |  772 ++++++++++++++
+ arch/x86/crypto/sha256-ssse3-asm.S                 |  506 +++++++++
+ arch/x86/crypto/sha256_ssse3_glue.c                |  275 +++++
+ arch/x86/crypto/sha512-avx-asm.S                   |  423 ++++++++
+ arch/x86/crypto/sha512-avx2-asm.S                  |  743 ++++++++++++++
+ arch/x86/crypto/sha512-ssse3-asm.S                 |  421 ++++++++
+ arch/x86/crypto/sha512_ssse3_glue.c                |  282 ++++++
+ crypto/Kconfig                                     |   32 +-
+ crypto/crypto_user.c                               |    4 +-
+ crypto/sha256_generic.c                            |   11 +-
+ crypto/sha512_generic.c                            |   13 +-
+ drivers/char/hw_random/Kconfig                     |   12 +
+ drivers/char/hw_random/Makefile                    |    1 +
+ drivers/char/hw_random/bcm2835-rng.c               |  113 +++
+ drivers/char/hw_random/exynos-rng.c                |    3 +-
+ drivers/char/hw_random/mxc-rnga.c                  |   21 +-
+ drivers/char/hw_random/timeriomem-rng.c            |  190 +++-
+ drivers/crypto/Kconfig                             |   18 +-
+ drivers/crypto/Makefile                            |    1 +
+ drivers/crypto/atmel-aes.c                         |  471 ++++++---
+ drivers/crypto/atmel-sha-regs.h                    |    7 +-
+ drivers/crypto/atmel-sha.c                         |  586 +++++++++--
+ drivers/crypto/atmel-tdes-regs.h                   |    2 +
+ drivers/crypto/atmel-tdes.c                        |  394 ++++++-
+ drivers/crypto/bfin_crc.c                          |    6 +-
+ drivers/crypto/caam/Kconfig                        |    2 +-
+ drivers/crypto/caam/caamalg.c                      |    6 +
+ drivers/crypto/caam/caamhash.c                     |    4 +-
+ drivers/crypto/caam/ctrl.c                         |    3 +
+ drivers/crypto/caam/error.c                        |   10 +-
+ drivers/crypto/caam/key_gen.c                      |    2 +-
+ drivers/crypto/caam/key_gen.h                      |    2 +-
+ drivers/crypto/caam/regs.h                         |    4 +-
+ drivers/crypto/omap-aes.c                          |   15 +-
+ drivers/crypto/omap-sham.c                         |   15 +-
+ drivers/crypto/picoxcell_crypto.c                  |    4 +-
+ drivers/crypto/sahara.c                            | 1070 ++++++++++++++++++++
+ drivers/crypto/ux500/hash/hash_core.c              |    6 +-
+ include/crypto/sha.h                               |    5 +
+ include/linux/platform_data/atmel-aes.h            |   22 -
+ include/linux/platform_data/crypto-atmel.h         |   22 +
+ include/linux/timeriomem-rng.h                     |    5 -
+ 51 files changed, 6647 insertions(+), 471 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/crypto/fsl-imx-sahara.txt
+ create mode 100644 Documentation/devicetree/bindings/hwrng/timeriomem_rng.txt
+ create mode 100644 Documentation/devicetree/bindings/rng/brcm,bcm2835.txt
+ create mode 100644 arch/x86/crypto/sha256-avx-asm.S
+ create mode 100644 arch/x86/crypto/sha256-avx2-asm.S
+ create mode 100644 arch/x86/crypto/sha256-ssse3-asm.S
+ create mode 100644 arch/x86/crypto/sha256_ssse3_glue.c
+ create mode 100644 arch/x86/crypto/sha512-avx-asm.S
+ create mode 100644 arch/x86/crypto/sha512-avx2-asm.S
+ create mode 100644 arch/x86/crypto/sha512-ssse3-asm.S
+ create mode 100644 arch/x86/crypto/sha512_ssse3_glue.c
+ create mode 100644 drivers/char/hw_random/bcm2835-rng.c
+ create mode 100644 drivers/crypto/sahara.c
+ delete mode 100644 include/linux/platform_data/atmel-aes.h
+ create mode 100644 include/linux/platform_data/crypto-atmel.h
+Merging drm/drm-next (be88298 drm/tilcdc: only build on arm)
+$ git merge drm/drm-next
+Already up-to-date.
+Merging drm-intel/drm-intel-next-queued (ea0dc8c drm/i915: revert eDP bpp clamping code changes)
+$ git merge drm-intel/drm-intel-next-queued
+Auto-merging drivers/gpu/drm/i915/intel_dp.c
+Auto-merging drivers/gpu/drm/i915/intel_crt.c
+Auto-merging drivers/gpu/drm/i915/i915_gem_execbuffer.c
+Merge made by the 'recursive' strategy.
+ drivers/gpu/drm/drm_cache.c                |    7 +-
+ drivers/gpu/drm/drm_fb_helper.c            |   23 +-
+ drivers/gpu/drm/drm_prime.c                |    8 +-
+ drivers/gpu/drm/i915/i915_debugfs.c        |  423 +++-----
+ drivers/gpu/drm/i915/i915_dma.c            |   29 +-
+ drivers/gpu/drm/i915/i915_drv.c            |  168 ++--
+ drivers/gpu/drm/i915/i915_drv.h            |   72 +-
+ drivers/gpu/drm/i915/i915_gem.c            |   89 +-
+ drivers/gpu/drm/i915/i915_gem_dmabuf.c     |   13 +-
+ drivers/gpu/drm/i915/i915_gem_execbuffer.c |   36 +-
+ drivers/gpu/drm/i915/i915_gem_gtt.c        |   77 +-
+ drivers/gpu/drm/i915/i915_gem_stolen.c     |   65 ++
+ drivers/gpu/drm/i915/i915_gem_tiling.c     |   18 +-
+ drivers/gpu/drm/i915/i915_irq.c            |  457 +++++----
+ drivers/gpu/drm/i915/i915_reg.h            |  260 +++--
+ drivers/gpu/drm/i915/i915_suspend.c        |   15 +-
+ drivers/gpu/drm/i915/i915_sysfs.c          |   16 +-
+ drivers/gpu/drm/i915/intel_crt.c           |   16 +-
+ drivers/gpu/drm/i915/intel_ddi.c           |   62 +-
+ drivers/gpu/drm/i915/intel_display.c       | 1452 +++++++++++++++-------------
+ drivers/gpu/drm/i915/intel_dp.c            |  547 ++++++-----
+ drivers/gpu/drm/i915/intel_drv.h           |  145 +--
+ drivers/gpu/drm/i915/intel_fb.c            |    5 +-
+ drivers/gpu/drm/i915/intel_hdmi.c          |  157 +--
+ drivers/gpu/drm/i915/intel_lvds.c          |   48 +-
+ drivers/gpu/drm/i915/intel_panel.c         |   44 +-
+ drivers/gpu/drm/i915/intel_pm.c            |  164 +++-
+ drivers/gpu/drm/i915/intel_sdvo.c          |  119 +--
+ drivers/gpu/drm/i915/intel_sprite.c        |  243 ++++-
+ drivers/gpu/drm/i915/intel_tv.c            |   14 +-
+ drivers/video/fbmem.c                      |    7 +
+ include/drm/drm_fb_helper.h                |    4 +
+ include/linux/fb.h                         |    2 +
+ include/linux/pm.h                         |   13 +
+ include/linux/scatterlist.h                |   28 +-
+ kernel/power/console.c                     |  116 +++
+ lib/scatterlist.c                          |    4 +-
+ 37 files changed, 2897 insertions(+), 2069 deletions(-)
+Merging sound/for-next (1dc669f ALSA: usb-audio: UAC2: support read-only freq control)
+$ git merge sound/for-next
+Auto-merging sound/pci/hda/patch_realtek.c
+Auto-merging sound/pci/hda/hda_codec.c
+Auto-merging sound/core/info.c
+Merge made by the 'recursive' strategy.
+ Documentation/DocBook/writing-an-alsa-driver.tmpl |  12 +-
+ Documentation/sound/alsa/HD-Audio.txt             |  10 +-
+ include/linux/usb/audio-v2.h                      |   2 +
+ include/sound/control.h                           |   5 +-
+ include/sound/core.h                              |  26 +-
+ include/sound/pcm.h                               |  23 +-
+ sound/core/control.c                              |  41 +-
+ sound/core/device.c                               |   8 +-
+ sound/core/hwdep.c                                |   2 +-
+ sound/core/info.c                                 |  41 +-
+ sound/core/init.c                                 |  16 +-
+ sound/core/isadma.c                               |   2 +-
+ sound/core/jack.c                                 |   6 +-
+ sound/core/memalloc.c                             |  20 +-
+ sound/core/memory.c                               |   4 +-
+ sound/core/pcm.c                                  |   6 +-
+ sound/core/pcm_lib.c                              |  54 ++-
+ sound/core/pcm_memory.c                           |  19 +-
+ sound/core/pcm_misc.c                             |  28 +-
+ sound/core/pcm_native.c                           |  13 +
+ sound/core/rawmidi.c                              |  14 +-
+ sound/core/sound.c                                |   7 +-
+ sound/core/vmaster.c                              |   7 +-
+ sound/drivers/mpu401/mpu401_uart.c                |   6 +-
+ sound/oss/sb_common.c                             |   3 +-
+ sound/oss/uart401.c                               |  11 +-
+ sound/pci/ac97/ac97_codec.c                       |  16 +-
+ sound/pci/ac97/ac97_pcm.c                         |  10 +-
+ sound/pci/hda/hda_auto_parser.c                   |  24 +-
+ sound/pci/hda/hda_auto_parser.h                   |   2 +
+ sound/pci/hda/hda_beep.c                          |  39 +-
+ sound/pci/hda/hda_beep.h                          |   1 +
+ sound/pci/hda/hda_codec.c                         |  17 +-
+ sound/pci/hda/hda_generic.c                       | 392 +++++++++++++-----
+ sound/pci/hda/hda_generic.h                       |  30 +-
+ sound/pci/hda/hda_local.h                         |   4 +
+ sound/pci/hda/patch_analog.c                      |  33 +-
+ sound/pci/hda/patch_ca0132.c                      |  27 +-
+ sound/pci/hda/patch_conexant.c                    |  19 +-
+ sound/pci/hda/patch_hdmi.c                        | 198 ++++++----
+ sound/pci/hda/patch_realtek.c                     | 204 ++++++----
+ sound/pci/hda/patch_sigmatel.c                    |  39 +-
+ sound/pci/hda/patch_via.c                         |  20 +
+ sound/pci/rme9652/hdspm.c                         | 382 +++++++++++-------
+ sound/sound_core.c                                |  22 +-
+ sound/usb/caiaq/audio.c                           | 459 +++++++++++-----------
+ sound/usb/caiaq/audio.h                           |   4 +-
+ sound/usb/caiaq/control.c                         |  67 ++--
+ sound/usb/caiaq/control.h                         |   2 +-
+ sound/usb/caiaq/device.c                          | 248 ++++++------
+ sound/usb/caiaq/device.h                          |  18 +-
+ sound/usb/caiaq/input.c                           | 328 ++++++++--------
+ sound/usb/caiaq/input.h                           |   6 +-
+ sound/usb/caiaq/midi.c                            |  63 +--
+ sound/usb/caiaq/midi.h                            |   5 +-
+ sound/usb/card.c                                  |  11 +-
+ sound/usb/clock.c                                 | 186 ++++++---
+ sound/usb/clock.h                                 |   3 +-
+ sound/usb/endpoint.c                              |  18 +-
+ sound/usb/endpoint.h                              |   2 +-
+ sound/usb/format.c                                |  22 +-
+ sound/usb/format.h                                |   2 +-
+ sound/usb/midi.c                                  |  12 +-
+ sound/usb/pcm.c                                   |  39 +-
+ sound/usb/proc.c                                  |   7 +-
+ sound/usb/quirks-table.h                          |  43 +-
+ sound/usb/quirks.c                                |  21 +-
+ sound/usb/stream.c                                |  14 +-
+ sound/usb/usbaudio.h                              |   1 +
+ 69 files changed, 2068 insertions(+), 1378 deletions(-)
+Merging sound-asoc/for-next (5c0f555 Merge remote-tracking branch 'asoc/topic/wm8994' into asoc-next)
+$ git merge sound-asoc/for-next
+Removing sound/soc/omap/omap-pcm.h
+Removing sound/soc/cirrus/ep93xx-pcm.h
+Removing include/sound/tegra_wm8903.h
+Merge made by the 'recursive' strategy.
+ Documentation/devicetree/bindings/sound/ak5386.txt |  19 +
+ .../bindings/sound/nvidia,tegra30-ahub.txt         |  26 +-
+ .../devicetree/bindings/sound/ti,tas5086.txt       |  32 ++
+ drivers/extcon/extcon-arizona.c                    | 107 ++--
+ drivers/mfd/wm5102-tables.c                        |  10 +
+ include/linux/mfd/arizona/core.h                   |   3 +
+ include/linux/mfd/arizona/registers.h              |  42 ++
+ include/linux/mfd/wm8994/pdata.h                   |   8 +
+ include/sound/dmaengine_pcm.h                      |  27 +-
+ include/sound/soc-dai.h                            |   8 -
+ include/sound/soc-dapm.h                           |   1 -
+ include/sound/soc.h                                |  29 +-
+ include/sound/tas5086.h                            |   7 +
+ include/sound/tegra_wm8903.h                       |  26 -
+ sound/soc/atmel/atmel-pcm-dma.c                    |  25 +-
+ sound/soc/atmel/atmel_ssc_dai.c                    |  54 +-
+ sound/soc/au1x/ac97c.c                             |   9 +-
+ sound/soc/au1x/i2sc.c                              |   9 +-
+ sound/soc/au1x/psc-ac97.c                          |   9 +-
+ sound/soc/au1x/psc-i2s.c                           |   9 +-
+ sound/soc/blackfin/bf5xx-ac97.c                    |   9 +-
+ sound/soc/blackfin/bf5xx-i2s.c                     |   9 +-
+ sound/soc/blackfin/bf5xx-tdm.c                     |   9 +-
+ sound/soc/blackfin/bf6xx-i2s.c                     |   9 +-
+ sound/soc/cirrus/edb93xx.c                         |   1 -
+ sound/soc/cirrus/ep93xx-ac97.c                     |  18 +-
+ sound/soc/cirrus/ep93xx-i2s.c                      |  21 +-
+ sound/soc/cirrus/ep93xx-pcm.c                      |  37 +-
+ sound/soc/cirrus/ep93xx-pcm.h                      |  20 -
+ sound/soc/cirrus/simone.c                          |   2 -
+ sound/soc/cirrus/snappercl15.c                     |   1 -
+ sound/soc/codecs/Kconfig                           |  10 +-
+ sound/soc/codecs/Makefile                          |   4 +
+ sound/soc/codecs/adau1373.c                        |   5 +-
+ sound/soc/codecs/ak4104.c                          |  55 +-
+ sound/soc/codecs/ak5386.c                          | 152 ++++++
+ sound/soc/codecs/arizona.c                         | 530 +++++++++++++++---
+ sound/soc/codecs/arizona.h                         |  34 +-
+ sound/soc/codecs/cs4271.c                          | 166 +++---
+ sound/soc/codecs/cs42l73.c                         |   6 +-
+ sound/soc/codecs/max98088.c                        |  30 +-
+ sound/soc/codecs/max98090.c                        |  45 +-
+ sound/soc/codecs/si476x.c                          |  47 +-
+ sound/soc/codecs/tas5086.c                         | 591 +++++++++++++++++++++
+ sound/soc/codecs/wm0010.c                          |   6 +-
+ sound/soc/codecs/wm2000.c                          |   4 +-
+ sound/soc/codecs/wm2000.h                          |   2 +
+ sound/soc/codecs/wm2200.c                          |   2 +-
+ sound/soc/codecs/wm5102.c                          | 129 +++--
+ sound/soc/codecs/wm5102.h                          |   6 +-
+ sound/soc/codecs/wm5110.c                          |  54 +-
+ sound/soc/codecs/wm5110.h                          |   6 +-
+ sound/soc/codecs/wm8903.c                          |   4 +
+ sound/soc/codecs/wm8960.c                          |  10 +
+ sound/soc/codecs/wm8994.c                          |  45 +-
+ sound/soc/codecs/wm8994.h                          |   1 +
+ sound/soc/codecs/wm_adsp.c                         |  84 ++-
+ sound/soc/codecs/wm_adsp.h                         |   5 +-
+ sound/soc/codecs/wm_hubs.c                         |   9 +-
+ sound/soc/davinci/davinci-i2s.c                    |  15 +-
+ sound/soc/davinci/davinci-mcasp.c                  |  69 ++-
+ sound/soc/davinci/davinci-pcm.c                    |  16 +-
+ sound/soc/davinci/davinci-pcm.h                    |   1 +
+ sound/soc/davinci/davinci-vcif.c                   |  11 +-
+ sound/soc/dwc/designware_i2s.c                     |   9 +-
+ sound/soc/fsl/fsl_ssi.c                            |  26 +-
+ sound/soc/fsl/imx-audmux.c                         |   3 +-
+ sound/soc/fsl/imx-pcm-dma.c                        |  37 +-
+ sound/soc/fsl/imx-pcm-fiq.c                        |   2 +-
+ sound/soc/fsl/imx-pcm.h                            |  17 +-
+ sound/soc/fsl/imx-sgtl5000.c                       |   2 +-
+ sound/soc/fsl/imx-ssi.c                            |  25 +-
+ sound/soc/fsl/mpc5200_psc_ac97.c                   |   8 +-
+ sound/soc/fsl/mpc5200_psc_i2s.c                    |   9 +-
+ sound/soc/jz4740/jz4740-i2s.c                      |   9 +-
+ sound/soc/kirkwood/kirkwood-i2s.c                  |  11 +-
+ sound/soc/mid-x86/sst_platform.c                   |  20 +-
+ sound/soc/mid-x86/sst_platform.h                   |   2 +
+ sound/soc/mxs/mxs-pcm.c                            |  43 +-
+ sound/soc/mxs/mxs-pcm.h                            |   4 +-
+ sound/soc/mxs/mxs-saif.c                           |  17 +-
+ sound/soc/nuc900/nuc900-ac97.c                     |   9 +-
+ sound/soc/omap/am3517evm.c                         |   1 -
+ sound/soc/omap/ams-delta.c                         |   1 -
+ sound/soc/omap/mcbsp.c                             |  14 +-
+ sound/soc/omap/mcbsp.h                             |   7 +-
+ sound/soc/omap/n810.c                              |   1 -
+ sound/soc/omap/omap-abe-twl6040.c                  |   1 -
+ sound/soc/omap/omap-dmic.c                         |  47 +-
+ sound/soc/omap/omap-hdmi.c                         |  33 +-
+ sound/soc/omap/omap-mcbsp.c                        |  27 +-
+ sound/soc/omap/omap-mcpdm.c                        | 118 ++--
+ sound/soc/omap/omap-pcm.c                          |  83 +--
+ sound/soc/omap/omap-pcm.h                          |  40 --
+ sound/soc/omap/omap-twl4030.c                      |   1 -
+ sound/soc/omap/omap3pandora.c                      |   9 +-
+ sound/soc/omap/osk5912.c                           |   1 -
+ sound/soc/omap/rx51.c                              |   1 -
+ sound/soc/pxa/mmp-pcm.c                            |  33 +-
+ sound/soc/pxa/mmp-sspa.c                           |   9 +-
+ sound/soc/pxa/pxa-ssp.c                            |   9 +-
+ sound/soc/pxa/pxa2xx-ac97.c                        |  11 +-
+ sound/soc/pxa/pxa2xx-i2s.c                         |   9 +-
+ sound/soc/s6000/s6000-i2s.c                        |   9 +-
+ sound/soc/samsung/Kconfig                          |   5 +-
+ sound/soc/samsung/ac97.c                           |  12 +-
+ sound/soc/samsung/goni_wm8994.c                    |  11 +-
+ sound/soc/samsung/i2s.c                            |  31 +-
+ sound/soc/samsung/pcm.c                            |  11 +-
+ sound/soc/samsung/s3c-i2s-v2.c                     |   9 +-
+ sound/soc/samsung/s3c-i2s-v2.h                     |   7 +-
+ sound/soc/samsung/s3c2412-i2s.c                    |  12 +-
+ sound/soc/samsung/s3c24xx-i2s.c                    |  11 +-
+ sound/soc/samsung/spdif.c                          |  11 +-
+ sound/soc/sh/fsi.c                                 |  14 +-
+ sound/soc/sh/hac.c                                 |  10 +-
+ sound/soc/sh/migor.c                               |   2 +-
+ sound/soc/sh/siu_dai.c                             |  11 +-
+ sound/soc/sh/ssi.c                                 |  10 +-
+ sound/soc/soc-compress.c                           |  41 +-
+ sound/soc/soc-core.c                               | 130 ++++-
+ sound/soc/soc-dapm.c                               | 320 +++++------
+ sound/soc/soc-dmaengine-pcm.c                      |  68 ++-
+ sound/soc/soc-io.c                                 |   5 +-
+ sound/soc/spear/spdif_in.c                         |   9 +-
+ sound/soc/spear/spdif_out.c                        |   9 +-
+ sound/soc/spear/spear_pcm.c                        |  22 +-
+ sound/soc/tegra/tegra20_ac97.c                     |  28 +-
+ sound/soc/tegra/tegra20_ac97.h                     |   4 +-
+ sound/soc/tegra/tegra20_i2s.c                      |  28 +-
+ sound/soc/tegra/tegra20_i2s.h                      |   4 +-
+ sound/soc/tegra/tegra20_spdif.c                    |  22 +-
+ sound/soc/tegra/tegra20_spdif.h                    |   4 +-
+ sound/soc/tegra/tegra30_ahub.c                     |  72 ++-
+ sound/soc/tegra/tegra30_ahub.h                     |  24 +-
+ sound/soc/tegra/tegra30_i2s.c                      |  28 +-
+ sound/soc/tegra/tegra30_i2s.h                      |   4 +-
+ sound/soc/tegra/tegra_alc5632.c                    |  15 +-
+ sound/soc/tegra/tegra_asoc_utils.c                 |  34 +-
+ sound/soc/tegra/tegra_asoc_utils.h                 |   1 +
+ sound/soc/tegra/tegra_pcm.c                        |  48 +-
+ sound/soc/tegra/tegra_pcm.h                        |   7 -
+ sound/soc/tegra/tegra_wm8753.c                     |  15 +-
+ sound/soc/tegra/tegra_wm8903.c                     | 179 +++----
+ sound/soc/tegra/tegra_wm9712.c                     |   7 +-
+ sound/soc/tegra/trimslice.c                        |  56 +-
+ sound/soc/txx9/txx9aclc-ac97.c                     |   9 +-
+ sound/soc/ux500/ux500_msp_dai.c                    |  13 +-
+ sound/soc/ux500/ux500_pcm.c                        |  25 +-
+ 149 files changed, 3296 insertions(+), 1570 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/sound/ak5386.txt
+ create mode 100644 Documentation/devicetree/bindings/sound/ti,tas5086.txt
+ create mode 100644 include/sound/tas5086.h
+ delete mode 100644 include/sound/tegra_wm8903.h
+ delete mode 100644 sound/soc/cirrus/ep93xx-pcm.h
+ create mode 100644 sound/soc/codecs/ak5386.c
+ create mode 100644 sound/soc/codecs/tas5086.c
+ delete mode 100644 sound/soc/omap/omap-pcm.h
+Merging modules/modules-next (d70f82a genksyms: pass symbol-prefix instead of arch)
+$ git merge modules/modules-next
+Auto-merging include/linux/kernel.h
+Auto-merging arch/metag/Kconfig
+Auto-merging Makefile
+Merge made by the 'recursive' strategy.
+ Makefile                          |  2 +-
+ arch/Kconfig                      |  6 ++++++
+ arch/blackfin/Kconfig             |  5 +----
+ arch/h8300/Kconfig                |  5 +----
+ arch/metag/Kconfig                |  5 +----
+ drivers/mtd/chips/gen_probe.c     |  8 +++++---
+ include/asm-generic/unistd.h      | 12 ++++--------
+ include/asm-generic/vmlinux.lds.h |  8 +-------
+ include/linux/export.h            | 20 ++++++++++++++------
+ include/linux/kernel.h            |  7 -------
+ include/linux/module.h            |  4 ++--
+ kernel/modsign_certificate.S      | 13 +++----------
+ kernel/module.c                   |  5 +++--
+ scripts/Makefile.build            |  3 ++-
+ scripts/Makefile.lib              |  7 -------
+ scripts/genksyms/genksyms.c       | 18 +++++++-----------
+ scripts/link-vmlinux.sh           |  5 ++---
+ scripts/mod/modpost.c             | 39 +++++++++++++++++----------------------
+ 18 files changed, 70 insertions(+), 102 deletions(-)
+Merging virtio/virtio-next (1aef76e caif_virtio: fix error return code in cfv_create_genpool())
+$ git merge virtio/virtio-next
+Resolved 'drivers/char/virtio_console.c' using previous resolution.
+Auto-merging net/9p/trans_virtio.c
+Auto-merging include/linux/virtio.h
+Auto-merging include/linux/scatterlist.h
+Auto-merging drivers/net/virtio_net.c
+Auto-merging drivers/net/caif/Makefile
+Auto-merging drivers/net/caif/Kconfig
+Auto-merging drivers/char/virtio_console.c
+CONFLICT (content): Merge conflict in drivers/char/virtio_console.c
+Auto-merging drivers/char/hw_random/virtio-rng.c
+Auto-merging MAINTAINERS
+Removing Documentation/virtual/virtio-spec.txt
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master afa6e28] Merge remote-tracking branch 'virtio/virtio-next'
+$ git diff -M --stat --summary HEAD^..
+ Documentation/virtual/00-INDEX          |    3 -
+ Documentation/virtual/virtio-spec.txt   | 3210 -------------------------------
+ MAINTAINERS                             |    1 +
+ block/blk-integrity.c                   |    2 +-
+ block/blk-merge.c                       |    2 +-
+ drivers/Makefile                        |    2 +-
+ drivers/block/virtio_blk.c              |  148 +-
+ drivers/char/hw_random/virtio-rng.c     |    2 +-
+ drivers/char/virtio_console.c           |    6 +-
+ drivers/lguest/Kconfig                  |    5 +-
+ drivers/net/caif/Kconfig                |   14 +
+ drivers/net/caif/Makefile               |    3 +
+ drivers/net/caif/caif_virtio.c          |  790 ++++++++
+ drivers/net/virtio_net.c                |   62 +-
+ drivers/rpmsg/virtio_rpmsg_bus.c        |    8 +-
+ drivers/scsi/virtio_scsi.c              |  112 +-
+ drivers/vhost/Kconfig                   |    8 +
+ drivers/vhost/Kconfig.tcm               |    1 +
+ drivers/vhost/Makefile                  |    2 +
+ drivers/vhost/test.c                    |    4 +-
+ drivers/vhost/vringh.c                  | 1007 ++++++++++
+ drivers/virtio/virtio_balloon.c         |    6 +-
+ drivers/virtio/virtio_ring.c            |  297 ++-
+ include/linux/scatterlist.h             |   16 +
+ include/linux/virtio.h                  |   20 +
+ include/linux/virtio_caif.h             |   24 +
+ include/linux/virtio_ring.h             |   57 +
+ include/linux/vringh.h                  |  225 +++
+ include/uapi/linux/virtio_balloon.h     |    4 +-
+ include/uapi/linux/virtio_ids.h         |    1 +
+ net/9p/trans_virtio.c                   |   48 +-
+ tools/lguest/lguest.txt                 |    2 +-
+ tools/virtio/Makefile                   |   10 +-
+ tools/virtio/asm/barrier.h              |   14 +
+ tools/virtio/linux/bug.h                |   10 +
+ tools/virtio/linux/err.h                |   26 +
+ tools/virtio/linux/export.h             |    5 +
+ tools/virtio/linux/irqreturn.h          |    1 +
+ tools/virtio/linux/kernel.h             |  112 ++
+ tools/virtio/linux/module.h             |    1 +
+ tools/virtio/linux/printk.h             |    4 +
+ tools/virtio/linux/ratelimit.h          |    4 +
+ tools/virtio/linux/scatterlist.h        |  189 ++
+ tools/virtio/linux/types.h              |   28 +
+ tools/virtio/linux/uaccess.h            |   50 +
+ tools/virtio/linux/uio.h                |    3 +
+ tools/virtio/linux/virtio.h             |  171 +-
+ tools/virtio/linux/virtio_config.h      |    6 +
+ tools/virtio/linux/virtio_ring.h        |    1 +
+ tools/virtio/linux/vringh.h             |    1 +
+ tools/virtio/uapi/linux/uio.h           |    1 +
+ tools/virtio/uapi/linux/virtio_config.h |    1 +
+ tools/virtio/uapi/linux/virtio_ring.h   |    4 +
+ tools/virtio/virtio_test.c              |   13 +-
+ tools/virtio/vringh_test.c              |  741 +++++++
+ 55 files changed, 3815 insertions(+), 3673 deletions(-)
+ delete mode 100644 Documentation/virtual/virtio-spec.txt
+ create mode 100644 drivers/net/caif/caif_virtio.c
+ create mode 100644 drivers/vhost/vringh.c
+ create mode 100644 include/linux/virtio_caif.h
+ create mode 100644 include/linux/vringh.h
+ create mode 100644 tools/virtio/asm/barrier.h
+ create mode 100644 tools/virtio/linux/bug.h
+ create mode 100644 tools/virtio/linux/err.h
+ create mode 100644 tools/virtio/linux/export.h
+ create mode 100644 tools/virtio/linux/irqreturn.h
+ create mode 100644 tools/virtio/linux/kernel.h
+ create mode 100644 tools/virtio/linux/printk.h
+ create mode 100644 tools/virtio/linux/ratelimit.h
+ create mode 100644 tools/virtio/linux/scatterlist.h
+ create mode 100644 tools/virtio/linux/types.h
+ create mode 100644 tools/virtio/linux/uaccess.h
+ create mode 100644 tools/virtio/linux/uio.h
+ create mode 100644 tools/virtio/linux/virtio_config.h
+ create mode 100644 tools/virtio/linux/virtio_ring.h
+ create mode 100644 tools/virtio/linux/vringh.h
+ create mode 100644 tools/virtio/uapi/linux/uio.h
+ create mode 100644 tools/virtio/uapi/linux/virtio_config.h
+ create mode 100644 tools/virtio/uapi/linux/virtio_ring.h
+ create mode 100644 tools/virtio/vringh_test.c
+Merging input/next (3c2b901 Input: ims-pcu - fix a memory leak on error)
+$ git merge input/next
+Auto-merging drivers/usb/class/cdc-acm.c
+Merge made by the 'recursive' strategy.
+ .../bindings/input/ps2keyb-mouse-apbps2.txt        |   16 +
+ .../bindings/input/touchscreen/auo_pixcir_ts.txt   |   30 +
+ .../devicetree/bindings/serio/snps-arc_ps2.txt     |   16 +
+ drivers/base/devres.c                              |   74 +
+ drivers/input/keyboard/amikbd.c                    |   14 +-
+ drivers/input/keyboard/davinci_keyscan.c           |   12 +-
+ drivers/input/keyboard/imx_keypad.c                |   77 +-
+ drivers/input/keyboard/nomadik-ske-keypad.c        |   12 +-
+ drivers/input/keyboard/tegra-kbc.c                 |   89 +-
+ drivers/input/misc/Kconfig                         |   10 +
+ drivers/input/misc/Makefile                        |    1 +
+ drivers/input/misc/ad714x-i2c.c                    |    2 +-
+ drivers/input/misc/ad714x-spi.c                    |    2 +-
+ drivers/input/misc/adxl34x-i2c.c                   |    2 +-
+ drivers/input/misc/adxl34x-spi.c                   |    2 +-
+ drivers/input/misc/ims-pcu.c                       | 1901 ++++++++++++++++++++
+ drivers/input/misc/mma8450.c                       |    6 +-
+ drivers/input/misc/twl4030-pwrbutton.c             |   12 +-
+ drivers/input/mouse/amimouse.c                     |   14 +-
+ drivers/input/serio/Kconfig                        |   10 +
+ drivers/input/serio/Makefile                       |    1 +
+ drivers/input/serio/apbps2.c                       |  230 +++
+ drivers/input/serio/arc_ps2.c                      |   14 +-
+ drivers/input/serio/at32psif.c                     |   13 +-
+ drivers/input/serio/q40kbd.c                       |   13 +-
+ drivers/input/touchscreen/atmel-wm97xx.c           |   12 +-
+ drivers/input/touchscreen/auo-pixcir-ts.c          |  226 ++-
+ drivers/input/touchscreen/edt-ft5x06.c             |    3 +-
+ drivers/input/touchscreen/eeti_ts.c                |    3 +-
+ drivers/input/touchscreen/mc13783_ts.c             |   12 +-
+ drivers/input/touchscreen/wm9712.c                 |   28 +-
+ drivers/input/touchscreen/wm97xx-core.c            |   11 +
+ drivers/tty/sysrq.c                                |   53 +-
+ drivers/usb/class/cdc-acm.c                        |   13 +
+ drivers/usb/class/cdc-acm.h                        |    1 +
+ include/linux/device.h                             |    4 +
+ include/linux/input/auo-pixcir-ts.h                |    4 +-
+ include/uapi/linux/input.h                         |    5 +
+ 38 files changed, 2634 insertions(+), 314 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/input/ps2keyb-mouse-apbps2.txt
+ create mode 100644 Documentation/devicetree/bindings/input/touchscreen/auo_pixcir_ts.txt
+ create mode 100644 Documentation/devicetree/bindings/serio/snps-arc_ps2.txt
+ create mode 100644 drivers/input/misc/ims-pcu.c
+ create mode 100644 drivers/input/serio/apbps2.c
+Merging input-mt/for-next (043ac73 Input: MT - handle semi-mt devices in core)
+$ git merge input-mt/for-next
+Merge made by the 'recursive' strategy.
+ drivers/input/input-mt.c | 8 +++++++-
+ include/linux/input/mt.h | 1 +
+ 2 files changed, 8 insertions(+), 1 deletion(-)
+Merging cgroup/for-next (081aa45 cgroup: consolidate cgroup_attach_task() and cgroup_attach_proc())
+$ git merge cgroup/for-next
+Resolved 'include/linux/res_counter.h' using previous resolution.
+Auto-merging include/linux/res_counter.h
+CONFLICT (content): Merge conflict in include/linux/res_counter.h
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master e2fabcf] Merge remote-tracking branch 'cgroup/for-next'
+$ git diff -M --stat --summary HEAD^..
+ Documentation/cgroups/cgroups.txt |   1 +
+ Documentation/cgroups/devices.txt |  70 ++++++-
+ block/blk-cgroup.h                |   2 -
+ include/linux/cgroup.h            |  47 ++++-
+ include/linux/cpuset.h            |   1 -
+ include/linux/res_counter.h       |   2 +-
+ kernel/cgroup.c                   | 396 ++++++++++++--------------------------
+ kernel/cpuset.c                   |  36 ++--
+ security/device_cgroup.c          | 256 +++++++++++++++++++-----
+ 9 files changed, 455 insertions(+), 356 deletions(-)
+Merging block/for-next (fbf8bf2 Merge branch 'for-linus' into for-next)
+$ git merge block/for-next
+Resolved 'drivers/block/drbd/drbd_proc.c' using previous resolution.
+Auto-merging kernel/cpuset.c
+Auto-merging kernel/cgroup.c
+Auto-merging include/linux/device.h
+Auto-merging drivers/message/fusion/mptsas.c
+Auto-merging drivers/block/pktcdvd.c
+Auto-merging drivers/block/drbd/drbd_proc.c
+CONFLICT (content): Merge conflict in drivers/block/drbd/drbd_proc.c
+Auto-merging drivers/block/aoe/aoecmd.c
+Auto-merging MAINTAINERS
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master 98ccd39] Merge remote-tracking branch 'block/for-next'
+$ git diff -M --stat --summary HEAD^..
+ Documentation/ABI/testing/sysfs-block-bcache |  156 ++
+ Documentation/bcache.txt                     |  343 +++
+ Documentation/kernel-parameters.txt          |    9 +
+ MAINTAINERS                                  |    7 +
+ block/blk-core.c                             |  265 ++-
+ block/blk-sysfs.c                            |    2 +
+ block/cfq-iosched.c                          |    7 +-
+ block/deadline-iosched.c                     |    2 +-
+ block/elevator.c                             |   26 +
+ drivers/base/base.h                          |    2 +
+ drivers/base/bus.c                           |   73 +-
+ drivers/base/core.c                          |    2 +-
+ drivers/block/aoe/aoecmd.c                   |    6 +-
+ drivers/block/brd.c                          |    3 +-
+ drivers/block/drbd/drbd_actlog.c             |  246 ++-
+ drivers/block/drbd/drbd_bitmap.c             |   13 +-
+ drivers/block/drbd/drbd_int.h                |  179 +-
+ drivers/block/drbd/drbd_main.c               |  251 ++-
+ drivers/block/drbd/drbd_nl.c                 |  200 +-
+ drivers/block/drbd/drbd_proc.c               |   10 +-
+ drivers/block/drbd/drbd_receiver.c           |   16 +-
+ drivers/block/drbd/drbd_req.c                |  192 +-
+ drivers/block/drbd/drbd_req.h                |    8 +
+ drivers/block/drbd/drbd_state.c              |   28 +-
+ drivers/block/drbd/drbd_strings.c            |    1 +
+ drivers/block/drbd/drbd_worker.c             |   24 +-
+ drivers/block/floppy.c                       |    1 -
+ drivers/block/mtip32xx/mtip32xx.c            |  327 ++-
+ drivers/block/mtip32xx/mtip32xx.h            |   18 +-
+ drivers/block/pktcdvd.c                      |  102 +-
+ drivers/block/rbd.c                          |    2 +-
+ drivers/char/random.c                        |    1 +
+ drivers/md/Kconfig                           |    2 +
+ drivers/md/Makefile                          |    1 +
+ drivers/md/bcache/Kconfig                    |   42 +
+ drivers/md/bcache/Makefile                   |    7 +
+ drivers/md/bcache/alloc.c                    |  573 +++++
+ drivers/md/bcache/bcache.h                   | 1232 +++++++++++
+ drivers/md/bcache/bset.c                     | 1191 +++++++++++
+ drivers/md/bcache/bset.h                     |  379 ++++
+ drivers/md/bcache/btree.c                    | 2503 ++++++++++++++++++++++
+ drivers/md/bcache/btree.h                    |  405 ++++
+ drivers/md/bcache/closure.c                  |  345 +++
+ drivers/md/bcache/closure.h                  |  672 ++++++
+ drivers/md/bcache/debug.c                    |  563 +++++
+ drivers/md/bcache/debug.h                    |   54 +
+ drivers/md/bcache/io.c                       |  390 ++++
+ drivers/md/bcache/journal.c                  |  785 +++++++
+ drivers/md/bcache/journal.h                  |  215 ++
+ drivers/md/bcache/movinggc.c                 |  254 +++
+ drivers/md/bcache/request.c                  | 1411 ++++++++++++
+ drivers/md/bcache/request.h                  |   62 +
+ drivers/md/bcache/stats.c                    |  246 +++
+ drivers/md/bcache/stats.h                    |   58 +
+ drivers/md/bcache/super.c                    | 1943 +++++++++++++++++
+ drivers/md/bcache/sysfs.c                    |  817 +++++++
+ drivers/md/bcache/sysfs.h                    |  110 +
+ drivers/md/bcache/trace.c                    |   26 +
+ drivers/md/bcache/util.c                     |  377 ++++
+ drivers/md/bcache/util.h                     |  589 +++++
+ drivers/md/bcache/writeback.c                |  414 ++++
+ drivers/md/dm-crypt.c                        |    3 +-
+ drivers/md/dm-raid1.c                        |    2 +-
+ drivers/md/dm-stripe.c                       |    2 +-
+ drivers/md/dm-verity.c                       |    4 +-
+ drivers/md/faulty.c                          |    6 +-
+ drivers/md/linear.c                          |    3 +-
+ drivers/md/md.c                              |   17 +-
+ drivers/md/raid0.c                           |    9 +-
+ drivers/md/raid1.c                           |  133 +-
+ drivers/md/raid10.c                          |   78 +-
+ drivers/md/raid5.c                           |   49 +-
+ drivers/message/fusion/mptsas.c              |    6 +-
+ drivers/s390/block/dcssblk.c                 |    3 +-
+ drivers/scsi/libsas/sas_expander.c           |    6 +-
+ drivers/scsi/mpt2sas/mpt2sas_transport.c     |   10 +-
+ fs/bio-integrity.c                           |  144 +-
+ fs/bio.c                                     |  366 +++-
+ fs/btrfs/extent_io.c                         |    3 +-
+ fs/btrfs/volumes.c                           |    2 +-
+ fs/buffer.c                                  |    1 -
+ fs/direct-io.c                               |    8 +-
+ fs/exofs/ore.c                               |    2 +-
+ fs/exofs/ore_raid.c                          |    2 +-
+ fs/fs-writeback.c                            |  102 +-
+ fs/gfs2/lops.c                               |    2 +-
+ fs/jfs/jfs_logmgr.c                          |    2 -
+ fs/logfs/dev_bdev.c                          |    5 -
+ include/linux/backing-dev.h                  |   16 +-
+ include/linux/bio.h                          |  115 +-
+ include/linux/blk_types.h                    |    5 +
+ include/linux/blkdev.h                       |   27 +
+ include/linux/cgroup_subsys.h                |    6 +
+ include/linux/cpumask.h                      |   15 +
+ include/linux/device.h                       |    2 +
+ include/linux/drbd.h                         |    5 +-
+ include/linux/drbd_limits.h                  |   11 +-
+ include/linux/idr.h                          |   10 +-
+ include/linux/lru_cache.h                    |    1 +
+ include/linux/rwsem.h                        |   10 +
+ include/linux/sched.h                        |    6 +-
+ include/linux/workqueue.h                    |  166 +-
+ include/trace/events/bcache.h                |  271 +++
+ include/trace/events/block.h                 |   12 +-
+ include/trace/events/writeback.h             |    5 -
+ kernel/cgroup.c                              |    4 +-
+ kernel/cpuset.c                              |   16 +-
+ kernel/fork.c                                |    4 +
+ kernel/kthread.c                             |    2 +-
+ kernel/lockdep.c                             |    1 +
+ kernel/rwsem.c                               |   16 +
+ kernel/sched/core.c                          |    9 +-
+ kernel/trace/blktrace.c                      |    1 +
+ kernel/workqueue.c                           | 2946 ++++++++++++++++++--------
+ kernel/workqueue_internal.h                  |    9 +-
+ lib/lru_cache.c                              |   56 +-
+ mm/backing-dev.c                             |  259 +--
+ mm/bounce.c                                  |   75 +-
+ mm/page_io.c                                 |    1 -
+ 119 files changed, 20860 insertions(+), 2380 deletions(-)
+ create mode 100644 Documentation/ABI/testing/sysfs-block-bcache
+ create mode 100644 Documentation/bcache.txt
+ create mode 100644 drivers/md/bcache/Kconfig
+ create mode 100644 drivers/md/bcache/Makefile
+ create mode 100644 drivers/md/bcache/alloc.c
+ create mode 100644 drivers/md/bcache/bcache.h
+ create mode 100644 drivers/md/bcache/bset.c
+ create mode 100644 drivers/md/bcache/bset.h
+ create mode 100644 drivers/md/bcache/btree.c
+ create mode 100644 drivers/md/bcache/btree.h
+ create mode 100644 drivers/md/bcache/closure.c
+ create mode 100644 drivers/md/bcache/closure.h
+ create mode 100644 drivers/md/bcache/debug.c
+ create mode 100644 drivers/md/bcache/debug.h
+ create mode 100644 drivers/md/bcache/io.c
+ create mode 100644 drivers/md/bcache/journal.c
+ create mode 100644 drivers/md/bcache/journal.h
+ create mode 100644 drivers/md/bcache/movinggc.c
+ create mode 100644 drivers/md/bcache/request.c
+ create mode 100644 drivers/md/bcache/request.h
+ create mode 100644 drivers/md/bcache/stats.c
+ create mode 100644 drivers/md/bcache/stats.h
+ create mode 100644 drivers/md/bcache/super.c
+ create mode 100644 drivers/md/bcache/sysfs.c
+ create mode 100644 drivers/md/bcache/sysfs.h
+ create mode 100644 drivers/md/bcache/trace.c
+ create mode 100644 drivers/md/bcache/util.c
+ create mode 100644 drivers/md/bcache/util.h
+ create mode 100644 drivers/md/bcache/writeback.c
+ create mode 100644 include/trace/events/bcache.h
+Merging device-mapper/master (c9bfbec Correct the documented requirement on the return code from dm cache policy lookup functions stated in the policy module header file.)
+$ git merge device-mapper/master
+Merge made by the 'recursive' strategy.
+ drivers/md/dm-cache-policy.h |  4 ++--
+ drivers/md/dm-cache-target.c | 51 +++++++++++++++++++++++++++++++++-----------
+ drivers/md/dm-mpath.c        | 13 +++++------
+ 3 files changed, 47 insertions(+), 21 deletions(-)
+Merging embedded/master (4744b43 embedded: fix vc_translate operator precedence)
+$ git merge embedded/master
+Already up-to-date.
+Merging firmware/master (6e03a20 firmware: speed up request_firmware(), v3)
+$ git merge firmware/master
+Already up-to-date.
+Merging pcmcia/master (80af9e6 pcmcia at91_cf: fix raw gpio number usage)
+$ git merge pcmcia/master
+Already up-to-date.
+Merging mmc/mmc-next (8e1c4e4 mmc: dw_mmc: Use pr_info instead of printk)
+$ git merge mmc/mmc-next
+Auto-merging MAINTAINERS
+Merge made by the 'recursive' strategy.
+ .../devicetree/bindings/mmc/samsung-sdhci.txt      |  35 +---
+ .../devicetree/bindings/mmc/sdhci-sirf.txt         |  18 ++
+ Documentation/mmc/mmc-dev-attrs.txt                |   1 +
+ MAINTAINERS                                        |   1 +
+ arch/arm/boot/dts/tegra20-colibri-512.dtsi         |   2 +-
+ arch/arm/boot/dts/tegra20-harmony.dts              |   4 +-
+ arch/arm/boot/dts/tegra20-paz00.dts                |   2 +-
+ arch/arm/boot/dts/tegra20-seaboard.dts             |   2 +-
+ arch/arm/boot/dts/tegra20-tamonten.dtsi            |   2 +-
+ arch/arm/boot/dts/tegra20-trimslice.dts            |   2 +-
+ arch/arm/boot/dts/tegra20-ventana.dts              |   2 +-
+ arch/arm/boot/dts/tegra20-whistler.dts             |   1 +
+ arch/arm/boot/dts/tegra30-beaver.dts               |   2 +-
+ arch/arm/boot/dts/tegra30-cardhu.dtsi              |   2 +-
+ arch/arm/configs/at91sam9g45_defconfig             |   1 -
+ arch/avr32/configs/favr-32_defconfig               |   1 -
+ arch/avr32/configs/merisc_defconfig                |   1 -
+ drivers/mmc/card/block.c                           |  10 +-
+ drivers/mmc/card/queue.c                           |   3 -
+ drivers/mmc/card/queue.h                           |   2 +
+ drivers/mmc/core/core.c                            |  14 ++
+ drivers/mmc/core/mmc.c                             |   3 +
+ drivers/mmc/core/sdio_bus.c                        |  20 ++-
+ drivers/mmc/host/Kconfig                           |  21 +--
+ drivers/mmc/host/Makefile                          |   1 +
+ drivers/mmc/host/android-goldfish.c                |   2 +-
+ drivers/mmc/host/atmel-mci.c                       |   2 -
+ drivers/mmc/host/davinci_mmc.c                     |  23 +--
+ drivers/mmc/host/dw_mmc-exynos.c                   |  16 +-
+ drivers/mmc/host/dw_mmc.c                          | 145 ++++++++++------
+ drivers/mmc/host/mvsdio.c                          |  54 ++----
+ drivers/mmc/host/omap_hsmmc.c                      |  14 +-
+ drivers/mmc/host/rtsx_pci_sdmmc.c                  |  10 ++
+ drivers/mmc/host/sdhci-bcm2835.c                   |   4 +-
+ drivers/mmc/host/sdhci-cns3xxx.c                   |   4 +-
+ drivers/mmc/host/sdhci-dove.c                      |   4 +-
+ drivers/mmc/host/sdhci-esdhc-imx.c                 |   4 +-
+ drivers/mmc/host/sdhci-of-esdhc.c                  |   4 +-
+ drivers/mmc/host/sdhci-of-hlwd.c                   |   4 +-
+ drivers/mmc/host/sdhci-pci.c                       |   3 +-
+ drivers/mmc/host/sdhci-pltfm.c                     |   7 +-
+ drivers/mmc/host/sdhci-pltfm.h                     |   6 +-
+ drivers/mmc/host/sdhci-pxav2.c                     |   2 +-
+ drivers/mmc/host/sdhci-pxav3.c                     |  49 ++----
+ drivers/mmc/host/sdhci-s3c.c                       |  88 ++--------
+ drivers/mmc/host/sdhci-sirf.c                      | 193 +++++++++++++++++++++
+ drivers/mmc/host/sdhci-spear.c                     |   4 +-
+ drivers/mmc/host/sdhci-tegra.c                     | 122 +++----------
+ drivers/mmc/host/sdhci.c                           |  39 ++++-
+ drivers/mmc/host/wmt-sdmmc.c                       |   4 +-
+ include/linux/mmc/card.h                           |   1 +
+ include/linux/mmc/host.h                           |   2 +
+ 52 files changed, 552 insertions(+), 411 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/mmc/sdhci-sirf.txt
+ create mode 100644 drivers/mmc/host/sdhci-sirf.c
+Merging kgdb/kgdb-next (6bedf31 kdb: Remove unhandled ssb command)
+$ git merge kgdb/kgdb-next
+Merge made by the 'recursive' strategy.
+Merging slab/for-next (338b264 slub: add 'likely' macro to inc_slabs_node())
+$ git merge slab/for-next
+Auto-merging mm/slub.c
+Auto-merging mm/slab.c
+Removing include/linux/kmalloc_sizes.h
+Merge made by the 'recursive' strategy.
+ fs/proc/stat.c                |   2 +-
+ include/linux/kmalloc_sizes.h |  45 ---
+ include/linux/slab.h          | 231 +++++++++----
+ include/linux/slab_def.h      |  48 +--
+ include/linux/slub_def.h      | 136 +-------
+ mm/slab.c                     | 789 ++++++++++++++++++------------------------
+ mm/slab.h                     |  43 ++-
+ mm/slab_common.c              | 165 ++++++++-
+ mm/slub.c                     | 207 ++---------
+ 9 files changed, 755 insertions(+), 911 deletions(-)
+ delete mode 100644 include/linux/kmalloc_sizes.h
+Merging uclinux/for-next (6dbe51c Linux 3.9-rc1)
+$ git merge uclinux/for-next
+Already up-to-date.
+Merging md/for-next (023a4ef raid5: make release_stripe lockless)
+$ git merge md/for-next
+Auto-merging drivers/md/raid5.c
+Auto-merging drivers/md/raid10.c
+Auto-merging drivers/md/md.c
+Merge made by the 'recursive' strategy.
+ Documentation/device-mapper/dm-raid.txt |  84 ++++--
+ Documentation/md.txt                    |  16 +-
+ drivers/md/bitmap.c                     |   4 +-
+ drivers/md/dm-raid.c                    | 111 +++++++-
+ drivers/md/md.c                         | 234 +++++++++-------
+ drivers/md/md.h                         |   9 +
+ drivers/md/raid10.c                     |  16 ++
+ drivers/md/raid5.c                      | 474 ++++++++++++++++++++++++++++++--
+ drivers/md/raid5.h                      |  22 ++
+ 9 files changed, 820 insertions(+), 150 deletions(-)
+Merging mfd/master (e8ea76b mfd: as3711: Add OF support)
+$ git merge mfd/master
+Merge made by the 'recursive' strategy.
+ .../devicetree/bindings/input/cros-ec-keyb.txt     |   72 +
+ Documentation/devicetree/bindings/mfd/as3711.txt   |   73 ++
+ Documentation/devicetree/bindings/mfd/cros-ec.txt  |   56 +
+ drivers/input/keyboard/Kconfig                     |   12 +
+ drivers/input/keyboard/Makefile                    |    1 +
+ drivers/input/keyboard/cros_ec_keyb.c              |  334 +++++
+ drivers/input/keyboard/lpc32xx-keys.c              |   11 +-
+ drivers/input/keyboard/omap4-keypad.c              |   16 +-
+ drivers/input/keyboard/tca8418_keypad.c            |    7 +-
+ drivers/input/matrix-keymap.c                      |   19 +
+ drivers/mfd/Kconfig                                |   29 +
+ drivers/mfd/Makefile                               |    3 +
+ drivers/mfd/as3711.c                               |   27 +-
+ drivers/mfd/cros_ec.c                              |  196 +++
+ drivers/mfd/cros_ec_i2c.c                          |  201 +++
+ drivers/mfd/cros_ec_spi.c                          |  375 ++++++
+ include/linux/input/matrix_keypad.h                |   19 +
+ include/linux/mfd/cros_ec.h                        |  170 +++
+ include/linux/mfd/cros_ec_commands.h               | 1369 ++++++++++++++++++++
+ 19 files changed, 2968 insertions(+), 22 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/input/cros-ec-keyb.txt
+ create mode 100644 Documentation/devicetree/bindings/mfd/as3711.txt
+ create mode 100644 Documentation/devicetree/bindings/mfd/cros-ec.txt
+ create mode 100644 drivers/input/keyboard/cros_ec_keyb.c
+ create mode 100644 drivers/mfd/cros_ec.c
+ create mode 100644 drivers/mfd/cros_ec_i2c.c
+ create mode 100644 drivers/mfd/cros_ec_spi.c
+ create mode 100644 include/linux/mfd/cros_ec.h
+ create mode 100644 include/linux/mfd/cros_ec_commands.h
+Merging battery/master (a92d4c7 goldfish_battery: Use resource_size())
+$ git merge battery/master
+Auto-merging drivers/power/reset/vexpress-poweroff.c
+Auto-merging arch/arm/mach-vexpress/v2m.c
+Merge made by the 'recursive' strategy.
+ .../devicetree/bindings/power_supply/tps65090.txt  |   17 +
+ arch/arm/mach-vexpress/Kconfig                     |    3 +
+ arch/arm/mach-vexpress/Makefile                    |    2 +-
+ arch/arm/mach-vexpress/v2m.c                       |    5 -
+ drivers/mfd/ab8500-core.c                          |  544 +++--
+ drivers/mfd/ab8500-debugfs.c                       | 2559 +++++++++++++++-----
+ drivers/mfd/ab8500-gpadc.c                         |  559 ++++-
+ drivers/mfd/ab8500-sysctrl.c                       |   98 +-
+ drivers/power/88pm860x_charger.c                   |    2 -
+ drivers/power/Kconfig                              |   14 +-
+ drivers/power/Makefile                             |    4 +-
+ drivers/power/ab8500_bmdata.c                      |   96 +-
+ drivers/power/ab8500_btemp.c                       |   75 +-
+ drivers/power/ab8500_charger.c                     |  699 ++++--
+ drivers/power/ab8500_fg.c                          |  497 +++-
+ drivers/power/abx500_chargalg.c                    |  455 +++-
+ drivers/power/da9030_battery.c                     |    6 +-
+ drivers/power/da9052-battery.c                     |    5 +-
+ drivers/power/ds2760_battery.c                     |    4 +-
+ drivers/power/ds2780_battery.c                     |    7 +-
+ drivers/power/ds2782_battery.c                     |   23 +-
+ drivers/power/goldfish_battery.c                   |    2 +-
+ drivers/power/gpio-charger.c                       |    5 +-
+ drivers/power/isp1704_charger.c                    |    5 +-
+ drivers/power/lp8788-charger.c                     |    8 +-
+ drivers/power/max17040_battery.c                   |   20 +-
+ drivers/power/max8903_charger.c                    |    4 +-
+ drivers/power/max8925_power.c                      |    5 +-
+ drivers/power/max8997_charger.c                    |    9 +-
+ drivers/power/max8998_charger.c                    |    5 +-
+ drivers/power/pcf50633-charger.c                   |    7 +-
+ drivers/power/pm2301_charger.c                     |  371 ++-
+ drivers/power/pm2301_charger.h                     |   23 +-
+ drivers/power/reset/Kconfig                        |    7 +
+ drivers/power/reset/Makefile                       |    3 +-
+ .../power/reset/vexpress-poweroff.c                |    9 +-
+ drivers/power/rx51_battery.c                       |    4 +-
+ drivers/power/s3c_adc_battery.c                    |    7 +-
+ drivers/power/sbs-battery.c                        |   22 +-
+ drivers/power/test_power.c                         |   31 +-
+ drivers/power/tps65090-charger.c                   |  320 +++
+ drivers/power/twl4030_charger.c                    |   12 +-
+ drivers/power/wm831x_backup.c                      |   10 +-
+ include/linux/mfd/abx500.h                         |   21 +-
+ include/linux/mfd/abx500/ab8500-bm.h               |   60 +-
+ include/linux/mfd/abx500/ab8500-gpadc.h            |   74 +-
+ include/linux/mfd/abx500/ab8500-sysctrl.h          |    6 +
+ include/linux/mfd/abx500/ab8500.h                  |    3 +
+ include/linux/mfd/abx500/ux500_chargalg.h          |    7 +
+ include/linux/mfd/tps65090.h                       |    5 +
+ include/linux/pm2301_charger.h                     |    2 +-
+ include/linux/vexpress.h                           |    3 -
+ 52 files changed, 5290 insertions(+), 1454 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/power_supply/tps65090.txt
+ rename arch/arm/mach-vexpress/reset.c => drivers/power/reset/vexpress-poweroff.c (93%)
+ create mode 100644 drivers/power/tps65090-charger.c
+Merging fbdev/fbdev-next (a49f0d1 Linux 3.8-rc1)
+$ git merge fbdev/fbdev-next
+Already up-to-date.
+Merging viafb/viafb-next (838ac78 viafb: avoid refresh and mode lookup in set_par)
+$ git merge viafb/viafb-next
+Already up-to-date.
+Merging omap_dss2/for-next (5955e3b Merge branches '3.10/1-panel-cleanup', '3.10/2-dsi-video-mode', '3.10/misc', '3.10/auo-k190x', '3.10/vt8500' and '3.10-lo/board-cleanup' into for-next)
+$ git merge omap_dss2/for-next
+Removing include/video/omap-panel-tfp410.h
+Removing include/video/omap-panel-picodlp.h
+Removing include/video/omap-panel-nokia-dsi.h
+Removing include/video/omap-panel-n8x0.h
+Removing include/video/omap-panel-generic-dpi.h
+Removing include/linux/platform_data/video-vt8500lcdfb.h
+Auto-merging arch/arm/mach-omap2/board-omap3beagle.c
+Merge made by the 'recursive' strategy.
+ .../devicetree/bindings/video/via,vt8500-fb.txt    |   48 +-
+ .../devicetree/bindings/video/wm,wm8505-fb.txt     |   32 +-
+ arch/arm/boot/dts/vt8500-bv07.dts                  |   34 +-
+ arch/arm/boot/dts/vt8500.dtsi                      |    4 +-
+ arch/arm/boot/dts/wm8505-ref.dts                   |   34 +-
+ arch/arm/boot/dts/wm8505.dtsi                      |    4 +-
+ arch/arm/boot/dts/wm8650-mid.dts                   |   36 +-
+ arch/arm/boot/dts/wm8650.dtsi                      |    4 +-
+ arch/arm/boot/dts/wm8850-w70v2.dts                 |   40 +-
+ arch/arm/boot/dts/wm8850.dtsi                      |    4 +-
+ arch/arm/mach-omap2/board-2430sdp.c                |   45 +-
+ arch/arm/mach-omap2/board-3430sdp.c                |   55 +-
+ arch/arm/mach-omap2/board-am3517evm.c              |   77 +-
+ arch/arm/mach-omap2/board-cm-t35.c                 |   63 +-
+ arch/arm/mach-omap2/board-devkit8000.c             |   30 +-
+ arch/arm/mach-omap2/board-h4.c                     |    2 +-
+ arch/arm/mach-omap2/board-igep0020.c               |    2 +-
+ arch/arm/mach-omap2/board-ldp.c                    |   63 +-
+ arch/arm/mach-omap2/board-omap3beagle.c            |    2 +-
+ arch/arm/mach-omap2/board-omap3evm.c               |   72 +-
+ arch/arm/mach-omap2/board-omap3pandora.c           |    7 +-
+ arch/arm/mach-omap2/board-omap3stalker.c           |   14 +-
+ arch/arm/mach-omap2/board-overo.c                  |   61 +-
+ arch/arm/mach-omap2/board-rx51-video.c             |   26 +-
+ arch/arm/mach-omap2/board-zoom-display.c           |   94 +-
+ arch/arm/mach-omap2/board-zoom-peripherals.c       |   53 +-
+ arch/arm/mach-omap2/dss-common.c                   |   58 +-
+ drivers/video/Kconfig                              |   37 +-
+ drivers/video/amifb.c                              |   14 +-
+ drivers/video/atmel_lcdfb.c                        |   13 +-
+ drivers/video/auo_k1900fb.c                        |   11 +-
+ drivers/video/auo_k1901fb.c                        |   11 +-
+ drivers/video/auo_k190x.c                          |  235 +++-
+ drivers/video/fsl-diu-fb.c                         |  157 ++-
+ drivers/video/omap/Kconfig                         |   11 -
+ drivers/video/omap2/displays/panel-acx565akm.c     |   59 +-
+ drivers/video/omap2/displays/panel-generic-dpi.c   |   39 +-
+ .../omap2/displays/panel-lgphilips-lb035q02.c      |   58 +-
+ drivers/video/omap2/displays/panel-n8x0.c          |   95 +-
+ .../omap2/displays/panel-nec-nl8048hl11-01b.c      |  115 +-
+ drivers/video/omap2/displays/panel-picodlp.c       |   49 +-
+ .../video/omap2/displays/panel-sharp-ls037v7dw01.c |  126 +-
+ drivers/video/omap2/displays/panel-taal.c          |  300 +----
+ drivers/video/omap2/displays/panel-tfp410.c        |    2 +-
+ .../video/omap2/displays/panel-tpo-td043mtea1.c    |   45 +-
+ drivers/video/omap2/dss/apply.c                    |   15 +-
+ drivers/video/omap2/dss/core.c                     |    5 +-
+ drivers/video/omap2/dss/dispc.c                    |  124 +-
+ drivers/video/omap2/dss/dpi.c                      |  316 +++--
+ drivers/video/omap2/dss/dsi.c                      | 1221 ++++++++++++--------
+ drivers/video/omap2/dss/dss.c                      |  154 +--
+ drivers/video/omap2/dss/dss.h                      |   36 +-
+ drivers/video/omap2/dss/hdmi.c                     |   19 +-
+ drivers/video/omap2/dss/output.c                   |    1 +
+ drivers/video/omap2/dss/rfbi.c                     |    2 +
+ drivers/video/omap2/dss/sdi.c                      |   70 +-
+ drivers/video/omap2/dss/venc.c                     |   13 +-
+ drivers/video/omap2/omapfb/omapfb-main.c           |    2 +-
+ drivers/video/omap2/vrfb.c                         |   13 +-
+ drivers/video/sh_mipi_dsi.c                        |   12 +-
+ drivers/video/sh_mobile_hdmi.c                     |   12 +-
+ drivers/video/vt8500lcdfb.c                        |   55 +-
+ drivers/video/wm8505fb.c                           |  144 +--
+ drivers/video/wmt_ge_rops.h                        |   23 +
+ include/linux/platform_data/video-vt8500lcdfb.h    |   31 -
+ include/video/auo_k190xfb.h                        |    3 +-
+ include/video/omap-panel-data.h                    |  150 +++
+ include/video/omap-panel-generic-dpi.h             |   37 -
+ include/video/omap-panel-n8x0.h                    |   15 -
+ include/video/omap-panel-nokia-dsi.h               |   32 -
+ include/video/omap-panel-picodlp.h                 |   23 -
+ include/video/omap-panel-tfp410.h                  |   35 -
+ include/video/omapdss.h                            |   86 +-
+ 73 files changed, 2440 insertions(+), 2550 deletions(-)
+ delete mode 100644 include/linux/platform_data/video-vt8500lcdfb.h
+ create mode 100644 include/video/omap-panel-data.h
+ delete mode 100644 include/video/omap-panel-generic-dpi.h
+ delete mode 100644 include/video/omap-panel-n8x0.h
+ delete mode 100644 include/video/omap-panel-nokia-dsi.h
+ delete mode 100644 include/video/omap-panel-picodlp.h
+ delete mode 100644 include/video/omap-panel-tfp410.h
+Merging regulator/for-next (c921540 Merge remote-tracking branch 'regulator/topic/tps6586x' into regulator-next)
+$ git merge regulator/for-next
+Auto-merging include/linux/mfd/abx500/ab8500.h
+Auto-merging arch/arm/mach-ux500/board-mop500.c
+Auto-merging MAINTAINERS
+Merge made by the 'recursive' strategy.
+ MAINTAINERS                                   |    2 +-
+ arch/arm/mach-ux500/board-mop500-regulators.c |  774 ++++++-
+ arch/arm/mach-ux500/board-mop500-regulators.h |    7 +-
+ arch/arm/mach-ux500/board-mop500.c            |    5 +-
+ drivers/regulator/88pm8607.c                  |   36 +-
+ drivers/regulator/Makefile                    |    2 +-
+ drivers/regulator/ab8500-ext.c                |  448 ++++
+ drivers/regulator/ab8500.c                    | 2762 +++++++++++++++++++++++--
+ drivers/regulator/arizona-ldo1.c              |    2 +-
+ drivers/regulator/as3711-regulator.c          |   74 +-
+ drivers/regulator/core.c                      |  168 +-
+ drivers/regulator/dbx500-prcmu.h              |    2 -
+ drivers/regulator/fan53555.c                  |    4 +-
+ drivers/regulator/lp8788-ldo.c                |  157 +-
+ drivers/regulator/max1586.c                   |    2 +-
+ drivers/regulator/max8649.c                   |   39 +-
+ drivers/regulator/max8925-regulator.c         |    5 +-
+ drivers/regulator/max8998.c                   |    9 +-
+ drivers/regulator/palmas-regulator.c          |   69 +-
+ drivers/regulator/s5m8767.c                   |    2 +-
+ drivers/regulator/tps6586x-regulator.c        |    6 +-
+ include/linux/mfd/abx500/ab8500.h             |   11 +-
+ include/linux/regulator/ab8500.h              |  217 +-
+ include/linux/regulator/consumer.h            |   14 +-
+ include/linux/regulator/driver.h              |    7 +-
+ 25 files changed, 4286 insertions(+), 538 deletions(-)
+ create mode 100644 drivers/regulator/ab8500-ext.c
+Merging security/next (958d2c2 Smack: include magic.h in smackfs.c)
+$ git merge security/next
+Auto-merging security/selinux/hooks.c
+Auto-merging fs/nfs/super.c
+Merge made by the 'recursive' strategy.
+ Documentation/security/Smack.txt |  11 ++
+ fs/nfs/super.c                   |   3 +-
+ include/linux/security.h         |  10 +-
+ include/uapi/linux/magic.h       |   1 +
+ kernel/seccomp.c                 |   2 +
+ security/capability.c            |   3 +-
+ security/security.c              |   4 +-
+ security/selinux/hooks.c         |  39 +++++-
+ security/smack/smack.h           |   5 -
+ security/smack/smack_access.c    |   2 +
+ security/smack/smack_lsm.c       |   4 +-
+ security/smack/smackfs.c         | 254 ++++++++++++++++++++++++++-------------
+ security/tomoyo/tomoyo.c         |   5 +-
+ 13 files changed, 238 insertions(+), 105 deletions(-)
+Merging selinux/master (c2d7b24 Merge tag 'v3.4' into 20120409)
+$ git merge selinux/master
+Already up-to-date!
+Merge made by the 'recursive' strategy.
+Merging lblnet/master (7e27d6e Linux 2.6.35-rc3)
+$ git merge lblnet/master
+Already up-to-date.
+Merging watchdog/master (112b55a watchdog: Convert to devm_ioremap_resource())
+$ git merge watchdog/master
+Merge made by the 'recursive' strategy.
+ drivers/watchdog/ath79_wdt.c   | 8 +++-----
+ drivers/watchdog/davinci_wdt.c | 9 ++++-----
+ drivers/watchdog/s3c2410_wdt.c | 7 +++----
+ drivers/watchdog/shwdt.c       | 7 ++++---
+ 4 files changed, 14 insertions(+), 17 deletions(-)
+Merging dwmw2-iommu/master (6491d4d intel-iommu: Free old page tables before creating superpage)
+$ git merge dwmw2-iommu/master
+Already up-to-date.
+Merging iommu/next (fbe973e Merge branches 'iommu/fixes' and 'x86/vt-d' into next)
+$ git merge iommu/next
+Merge made by the 'recursive' strategy.
+ drivers/iommu/dmar.c | 12 +++++++-----
+ 1 file changed, 7 insertions(+), 5 deletions(-)
+Merging vfio/next (a7d1ea1 vfio-pci: Enable raw access to unassigned config space)
+$ git merge vfio/next
+Auto-merging drivers/vfio/pci/vfio_pci_intrs.c
+Auto-merging drivers/vfio/pci/vfio_pci_config.c
+Auto-merging drivers/vfio/pci/vfio_pci.c
+Merge made by the 'recursive' strategy.
+ drivers/vfio/pci/vfio_pci.c         |  44 +++++++++-
+ drivers/vfio/pci/vfio_pci_config.c  | 166 ++++++++++++++++++++----------------
+ drivers/vfio/pci/vfio_pci_intrs.c   |  67 ++++++++++++++-
+ drivers/vfio/pci/vfio_pci_private.h |   1 +
+ drivers/vfio/vfio.c                 |  30 ++++++-
+ include/linux/vfio.h                |   3 +
+ include/uapi/linux/vfio.h           |   1 +
+ 7 files changed, 236 insertions(+), 76 deletions(-)
+Merging osd/linux-next (861d666 exofs: don't leak io_state and pages on read error)
+$ git merge osd/linux-next
+Already up-to-date.
+Merging jc_docs/docs-next (5c050fb docs: update the development process document)
+$ git merge jc_docs/docs-next
+Already up-to-date.
+Merging trivial/for-next (1051e9b treewide: Fix typos in kernel messages)
+$ git merge trivial/for-next
+Auto-merging mm/hugetlb.c
+Auto-merging include/linux/mmzone.h
+Auto-merging drivers/power/pm2301_charger.c
+Auto-merging drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
+Auto-merging drivers/isdn/i4l/isdn_tty.c
+Auto-merging drivers/i2c/busses/i2c-puv3.c
+Auto-merging drivers/gpu/drm/radeon/radeon_irq_kms.c
+Auto-merging drivers/gpu/drm/i915/intel_dp.c
+Auto-merging drivers/crypto/caam/ctrl.c
+Auto-merging drivers/ata/sata_fsl.c
+Auto-merging arch/s390/kvm/trace.h
+Auto-merging arch/s390/kernel/irq.c
+Auto-merging arch/arm/mach-mvebu/irq-armada-370-xp.c
+Auto-merging arch/arc/kernel/disasm.c
+CONFLICT (modify/delete): Documentation/virtual/virtio-spec.txt deleted in HEAD and modified in trivial/for-next. Version trivial/for-next of Documentation/virtual/virtio-spec.txt left in tree.
+Auto-merging Documentation/kernel-parameters.txt
+Automatic merge failed; fix conflicts and then commit the result.
+$ git rm -f Documentation/virtual/virtio-spec.txt
+Documentation/virtual/virtio-spec.txt: needs merge
+rm 'Documentation/virtual/virtio-spec.txt'
+$ git commit -v -a
+[master cd0e88a] Merge remote-tracking branch 'trivial/for-next'
+$ git diff -M --stat --summary HEAD^..
+ Documentation/cgroups/memory.txt                |  2 +-
+ Documentation/kernel-parameters.txt             |  4 +---
+ Documentation/trace/tracepoints.txt             | 15 ---------------
+ arch/arc/kernel/disasm.c                        |  2 +-
+ arch/arc/plat-arcfpga/Kconfig                   |  2 +-
+ arch/arm/kernel/topology.c                      |  2 +-
+ arch/arm/mach-mvebu/irq-armada-370-xp.c         |  2 +-
+ arch/arm/mach-omap2/pm44xx.c                    |  4 ++--
+ arch/blackfin/include/asm/bfin_sport3.h         |  2 +-
+ arch/powerpc/kernel/nvram_64.c                  |  3 +--
+ arch/powerpc/kvm/book3s_pr.c                    |  2 +-
+ arch/s390/kernel/irq.c                          |  2 +-
+ arch/s390/kvm/trace.h                           |  2 +-
+ drivers/ata/sata_fsl.c                          |  2 +-
+ drivers/clk/mvebu/clk-core.c                    |  4 ++--
+ drivers/crypto/caam/ctrl.c                      |  2 +-
+ drivers/gpu/drm/i915/intel_dp.c                 |  2 +-
+ drivers/gpu/drm/radeon/radeon_irq_kms.c         |  2 +-
+ drivers/hv/hv.c                                 |  5 ++---
+ drivers/i2c/busses/i2c-puv3.c                   |  2 +-
+ drivers/irqchip/irq-versatile-fpga.c            |  2 +-
+ drivers/isdn/i4l/isdn_tty.c                     |  1 -
+ drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c |  2 +-
+ drivers/media/radio/radio-shark.c               |  2 +-
+ drivers/media/radio/radio-shark2.c              |  2 +-
+ drivers/media/usb/dvb-usb/opera1.c              |  2 +-
+ drivers/net/ethernet/atheros/atl1c/atl1c_hw.c   |  2 +-
+ drivers/net/ethernet/sfc/Kconfig                |  2 +-
+ drivers/net/ethernet/ti/cpts.c                  |  2 +-
+ drivers/power/pm2301_charger.c                  |  2 +-
+ drivers/scsi/lpfc/lpfc_bsg.c                    |  2 +-
+ drivers/scsi/mpt3sas/mpt3sas_config.c           |  2 +-
+ drivers/scsi/osd/osd_initiator.c                |  2 +-
+ drivers/scsi/qla4xxx/ql4_nx.c                   |  2 +-
+ drivers/tty/serial/icom.c                       |  3 +--
+ drivers/tty/vt/consolemap.c                     |  3 +--
+ drivers/usb/misc/uss720.c                       |  2 +-
+ drivers/usb/storage/isd200.c                    |  3 +--
+ drivers/video/exynos/exynos_dp_core.c           |  4 ++--
+ drivers/video/goldfishfb.c                      |  2 +-
+ fs/befs/btree.c                                 |  3 +--
+ fs/ufs/util.c                                   |  3 +--
+ include/linux/evm.h                             |  2 +-
+ include/linux/iio/gyro/itg3200.h                |  2 +-
+ include/linux/ima.h                             |  4 ++--
+ include/linux/integrity.h                       |  2 +-
+ include/linux/mmzone.h                          |  2 +-
+ include/net/sctp/sctp.h                         |  2 +-
+ include/trace/events/timer.h                    | 10 +++++-----
+ kernel/.gitignore                               |  1 +
+ mm/hugetlb.c                                    |  4 ++--
+ net/sctp/protocol.c                             |  2 +-
+ sound/pci/mixart/mixart.c                       |  2 +-
+ sound/soc/ux500/Kconfig                         |  4 ++--
+ tools/power/cpupower/debug/i386/intel_gsic.c    |  2 +-
+ 55 files changed, 64 insertions(+), 88 deletions(-)
+Merging audit/for-next (dcd6c92 Linux 3.3-rc1)
+$ git merge audit/for-next
+Already up-to-date.
+Merging fsnotify/for-next (1ca39ab inotify: automatically restart syscalls)
+$ git merge fsnotify/for-next
+Already up-to-date.
+Merging edac/linux_next (b076989 i5100_edac: convert to use simple_open())
+$ git merge edac/linux_next
+Already up-to-date.
+Merging edac-amd/for-next (9713fae EDAC: Merge mci.mem_is_per_rank with mci.csbased)
+$ git merge edac-amd/for-next
+Already up-to-date.
+Merging devicetree/devicetree/next (02bbde7 Revert "of: use platform_device_add")
+$ git merge devicetree/devicetree/next
+Already up-to-date.
+Merging dt-rh/for-next (1421954 documentation/devicetree: Fix a typo in exynos-dw-mshc.txt)
+$ git merge dt-rh/for-next
+Already up-to-date.
+Merging spi/spi/next (095c375 spi: Document cs_gpios and cs_gpio in kernel-doc)
+$ git merge spi/spi/next
+Already up-to-date.
+Merging spi-mb/spi-next (58ad60b mxs/spi: fix error return code in mxs_spi_probe())
+$ git merge spi-mb/spi-next
+Auto-merging drivers/spi/spi.c
+Auto-merging drivers/spi/spi-pxa2xx.c
+Auto-merging drivers/spi/Kconfig
+Merge made by the 'recursive' strategy.
+ .../devicetree/bindings/spi/brcm,bcm2835-spi.txt   |  22 ++
+ drivers/spi/Kconfig                                |  11 +
+ drivers/spi/Makefile                               |   1 +
+ drivers/spi/spi-atmel.c                            | 106 ++++--
+ drivers/spi/spi-bcm2835.c                          | 422 +++++++++++++++++++++
+ drivers/spi/spi-bcm63xx.c                          |  79 +---
+ drivers/spi/spi-fsl-spi.c                          |   4 +-
+ drivers/spi/spi-mpc512x-psc.c                      |   2 +-
+ drivers/spi/spi-mxs.c                              |   1 +
+ drivers/spi/spi-oc-tiny.c                          |   4 +-
+ drivers/spi/spi-omap2-mcspi.c                      |   8 +-
+ drivers/spi/spi-pxa2xx-pci.c                       |   6 +-
+ drivers/spi/spi-pxa2xx.c                           |   5 +
+ drivers/spi/spi-s3c64xx.c                          |  58 +--
+ drivers/spi/spi-sh-msiof.c                         |   4 +-
+ drivers/spi/spi-tegra20-slink.c                    |  28 +-
+ drivers/spi/spi.c                                  |  23 +-
+ drivers/spi/spidev.c                               |   2 +-
+ include/linux/spi/spi.h                            |   8 +
+ 19 files changed, 627 insertions(+), 167 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/spi/brcm,bcm2835-spi.txt
+ create mode 100644 drivers/spi/spi-bcm2835.c
+Merging tip/auto-latest (a2d66a370 Merge branch 'x86/platform')
+$ git merge tip/auto-latest
+Auto-merging kernel/sched/core.c
+Auto-merging kernel/printk.c
+Auto-merging kernel/fork.c
+Auto-merging kernel/events/core.c
+Auto-merging init/Kconfig
+Auto-merging include/linux/sched.h
+Auto-merging include/linux/perf_event.h
+Auto-merging include/linux/clockchips.h
+Auto-merging arch/x86/Kconfig
+Merge made by the 'recursive' strategy.
+ arch/x86/Kconfig                        |  89 +++++++-------
+ arch/x86/boot/compressed/head_64.S      |   2 +-
+ arch/x86/include/asm/context_tracking.h |  21 ----
+ arch/x86/include/asm/hypervisor.h       |  16 ++-
+ arch/x86/kernel/cpu/Makefile            |   3 +-
+ arch/x86/kernel/kvm.c                   |   8 +-
+ arch/x86/kernel/traps.c                 |  68 ++++++-----
+ arch/x86/lguest/Kconfig                 |   3 +-
+ arch/x86/mm/fault.c                     |   8 +-
+ arch/x86/platform/uv/uv_time.c          |   3 +-
+ arch/x86/xen/Kconfig                    |   2 +-
+ drivers/hv/Kconfig                      |   2 +-
+ drivers/misc/Kconfig                    |   2 +-
+ include/linux/clockchips.h              |   5 +
+ include/linux/context_tracking.h        |  24 +++-
+ include/linux/perf_event.h              |  18 +--
+ include/linux/sched.h                   | 198 +-------------------------------
+ init/Kconfig                            |   1 +
+ init/main.c                             |   2 +-
+ kernel/events/core.c                    |  15 +++
+ kernel/fork.c                           |   2 +-
+ kernel/printk.c                         |   2 +-
+ kernel/sched/core.c                     |  20 +++-
+ kernel/sched/cputime.c                  | 154 +++++++++++++------------
+ kernel/sched/fair.c                     |   6 +-
+ kernel/sched/sched.h                    | 162 +++++++++++++++++++++++++-
+ kernel/time/tick-broadcast.c            | 126 +++++++++++---------
+ kernel/time/tick-common.c               |   1 +
+ kernel/time/tick-internal.h             |   3 +-
+ 29 files changed, 497 insertions(+), 469 deletions(-)
+Merging ftrace/for-next (22f4564 tracing: Update debugfs README file)
+$ git merge ftrace/for-next
+Resolved 'kernel/trace/ftrace.c' using previous resolution.
+Auto-merging kernel/trace/trace_output.c
+Auto-merging kernel/trace/ring_buffer.c
+Auto-merging kernel/trace/ftrace.c
+CONFLICT (content): Merge conflict in kernel/trace/ftrace.c
+Auto-merging kernel/trace/blktrace.c
+Auto-merging kernel/trace/Kconfig
+Auto-merging include/linux/kernel.h
+Auto-merging Documentation/kernel-parameters.txt
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master b3196c4] Merge remote-tracking branch 'ftrace/for-next'
+$ git diff -M --stat --summary HEAD^..
+ Documentation/kernel-parameters.txt  |    7 +
+ Documentation/trace/ftrace.txt       | 2097 ++++++++++++++++++++++----------
+ include/linux/ftrace.h               |    6 +-
+ include/linux/ftrace_event.h         |  109 +-
+ include/linux/kernel.h               |   70 +-
+ include/linux/ring_buffer.h          |    6 +
+ include/linux/trace_clock.h          |    1 +
+ include/trace/ftrace.h               |   47 +-
+ kernel/trace/Kconfig                 |   49 +
+ kernel/trace/blktrace.c              |    4 +-
+ kernel/trace/ftrace.c                |   73 +-
+ kernel/trace/ring_buffer.c           |  500 +++++++-
+ kernel/trace/trace.c                 | 2204 ++++++++++++++++++++++++----------
+ kernel/trace/trace.h                 |  144 ++-
+ kernel/trace/trace_branch.c          |    8 +-
+ kernel/trace/trace_clock.c           |   10 +
+ kernel/trace/trace_entries.h         |   23 +-
+ kernel/trace/trace_events.c          | 1421 +++++++++++++++++-----
+ kernel/trace/trace_events_filter.c   |   34 +-
+ kernel/trace/trace_export.c          |    4 +-
+ kernel/trace/trace_functions.c       |  207 +++-
+ kernel/trace/trace_functions_graph.c |   12 +-
+ kernel/trace/trace_irqsoff.c         |   85 +-
+ kernel/trace/trace_kdb.c             |   12 +-
+ kernel/trace/trace_mmiotrace.c       |   12 +-
+ kernel/trace/trace_output.c          |  119 +-
+ kernel/trace/trace_output.h          |    4 +-
+ kernel/trace/trace_sched_switch.c    |    8 +-
+ kernel/trace/trace_sched_wakeup.c    |   87 +-
+ kernel/trace/trace_selftest.c        |   51 +-
+ kernel/trace/trace_stack.c           |   74 +-
+ kernel/trace/trace_syscalls.c        |   90 +-
+ 32 files changed, 5672 insertions(+), 1906 deletions(-)
+Merging rcu/rcu/next (6d87669 Merge branches 'doc.2013.03.12a', 'fixes.2013.03.13a' and 'idlenocb.2013.03.26b' into HEAD)
+$ git merge rcu/rcu/next
+Auto-merging init/Kconfig
+Auto-merging Documentation/kernel-parameters.txt
+Merge made by the 'recursive' strategy.
+ Documentation/RCU/checklist.txt     |  26 +-
+ Documentation/RCU/lockdep.txt       |   5 +
+ Documentation/RCU/rcubarrier.txt    |  15 +-
+ Documentation/RCU/stallwarn.txt     |  33 +-
+ Documentation/RCU/whatisRCU.txt     |   4 +-
+ Documentation/kernel-parameters.txt |  35 ++-
+ include/linux/list_bl.h             |   5 +
+ include/linux/rculist_bl.h          |   2 +-
+ include/linux/rcupdate.h            |   1 +
+ include/trace/events/rcu.h          |  55 ++++
+ init/Kconfig                        |  73 ++++-
+ kernel/rcutree.c                    | 260 ++++++++++++----
+ kernel/rcutree.h                    |  41 ++-
+ kernel/rcutree_plugin.h             | 601 +++++++++++++-----------------------
+ kernel/rcutree_trace.c              |   2 -
+ 15 files changed, 640 insertions(+), 518 deletions(-)
+Merging cputime/cputime (c3e0ef9 [S390] fix cputime overflow in uptime_proc_show)
+$ git merge cputime/cputime
+Already up-to-date.
+Merging uprobes/for-next (0326f5a uprobes/core: Handle breakpoint and singlestep exceptions)
+$ git merge uprobes/for-next
+Already up-to-date.
+Merging kvm/linux-next (81f4f76 KVM: MMU: Rename kvm_mmu_free_some_pages() to make_mmu_pages_available())
+$ git merge kvm/linux-next
+Resolved 'drivers/s390/kvm/virtio_ccw.c' using previous resolution.
+Auto-merging virt/kvm/kvm_main.c
+Auto-merging include/linux/kvm_host.h
+Auto-merging drivers/s390/kvm/virtio_ccw.c
+CONFLICT (content): Merge conflict in drivers/s390/kvm/virtio_ccw.c
+Auto-merging arch/s390/include/asm/pgtable.h
+Auto-merging arch/powerpc/kvm/book3s_pr.c
+Auto-merging arch/arm/kvm/arm.c
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master 0fea82a] Merge remote-tracking branch 'kvm/linux-next'
+$ git diff -M --stat --summary HEAD^..
+ Documentation/virtual/kvm/api.txt       |   8 +
+ arch/arm/kvm/arm.c                      |  15 +-
+ arch/ia64/kvm/kvm-ia64.c                |  25 +-
+ arch/powerpc/include/asm/kvm_ppc.h      |   2 +-
+ arch/powerpc/kvm/book3s_hv.c            |   4 +-
+ arch/powerpc/kvm/book3s_pr.c            |   2 +-
+ arch/powerpc/kvm/booke.c                |   2 +-
+ arch/powerpc/kvm/powerpc.c              |  13 +-
+ arch/s390/include/asm/pgtable.h         |   2 +
+ arch/s390/include/uapi/asm/Kbuild       |   1 +
+ arch/s390/include/uapi/asm/virtio-ccw.h |  21 ++
+ arch/s390/kvm/Kconfig                   |   1 +
+ arch/s390/kvm/Makefile                  |   2 +-
+ arch/s390/kvm/diag.c                    |  26 ++
+ arch/s390/kvm/gaccess.h                 | 429 ++++++--------------------------
+ arch/s390/kvm/intercept.c               |  10 +-
+ arch/s390/kvm/interrupt.c               | 245 ++++++------------
+ arch/s390/kvm/kvm-s390.c                |  11 +-
+ arch/s390/kvm/priv.c                    |  89 +++----
+ arch/s390/mm/pgtable.c                  | 107 ++++++--
+ arch/x86/include/asm/kvm_host.h         |   7 +-
+ arch/x86/include/asm/vmx.h              |  11 +
+ arch/x86/include/uapi/asm/vmx.h         |   5 +-
+ arch/x86/kernel/kvmclock.c              |   9 +-
+ arch/x86/kvm/lapic.c                    |  48 +++-
+ arch/x86/kvm/lapic.h                    |  11 +
+ arch/x86/kvm/mmu.c                      | 105 ++++----
+ arch/x86/kvm/mmu.h                      |  11 +-
+ arch/x86/kvm/paging_tmpl.h              |   1 -
+ arch/x86/kvm/svm.c                      |  18 +-
+ arch/x86/kvm/vmx.c                      | 265 ++++++++++++--------
+ arch/x86/kvm/x86.c                      | 125 ++++++----
+ drivers/s390/kvm/virtio_ccw.c           |  15 +-
+ include/linux/kvm_host.h                |  50 +++-
+ include/uapi/linux/kvm.h                |   3 +
+ virt/kvm/eventfd.c                      |  24 +-
+ virt/kvm/kvm_main.c                     |  53 ++--
+ 37 files changed, 830 insertions(+), 946 deletions(-)
+ create mode 100644 arch/s390/include/uapi/asm/virtio-ccw.h
+Merging kvm-ppc/kvm-ppc-next (fbfba34 Merge commit 'origin/next' into kvm-ppc-next)
+$ git merge kvm-ppc/kvm-ppc-next
+Merge made by the 'recursive' strategy.
+ Documentation/virtual/kvm/api.txt   |  4 ++
+ arch/powerpc/include/asm/kvm_host.h |  1 +
+ arch/powerpc/include/asm/kvm_ppc.h  |  3 +-
+ arch/powerpc/include/uapi/asm/kvm.h |  5 +++
+ arch/powerpc/kernel/asm-offsets.c   |  1 +
+ arch/powerpc/kvm/book3s.c           |  3 +-
+ arch/powerpc/kvm/booke.c            | 57 +++++++++++++++++++------
+ arch/powerpc/kvm/booke_interrupts.S | 42 +++++++++++++++++--
+ arch/powerpc/kvm/e500.h             | 24 ++++-------
+ arch/powerpc/kvm/e500_mmu_host.c    | 84 ++++++++++++-------------------------
+ arch/powerpc/kvm/powerpc.c          |  2 +-
+ 11 files changed, 133 insertions(+), 93 deletions(-)
+Merging oprofile/for-next (4400910 oprofile, x86: Fix wrapping bug in op_x86_get_ctrl())
+$ git merge oprofile/for-next
+Already up-to-date.
+Merging fw-nohz/nohz/next (74876a9 printk: Wake up klogd using irq_work)
+$ git merge fw-nohz/nohz/next
+Already up-to-date.
+Merging xen/upstream/xen (af3a3ab Merge git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-3.0-fixes)
+$ git merge xen/upstream/xen
+Already up-to-date.
+Merging xen-two/linux-next (562eb8e Merge branch 'stable/for-linus-3.9-take-two' into linux-next)
+$ git merge xen-two/linux-next
+Auto-merging arch/x86/xen/Kconfig
+Merge made by the 'recursive' strategy.
+ arch/x86/include/asm/xen/interface.h |  11 ++-
+ arch/x86/include/asm/xen/page.h      |   3 +
+ arch/x86/xen/Kconfig                 |   8 ++
+ arch/x86/xen/enlighten.c             |  76 ++++++++++++----
+ arch/x86/xen/irq.c                   |   5 +-
+ arch/x86/xen/mmu.c                   | 170 +++++++++++++++++++++++++++++++----
+ arch/x86/xen/mmu.h                   |   2 +
+ arch/x86/xen/p2m.c                   |   2 +-
+ arch/x86/xen/setup.c                 |  59 +++++++++---
+ arch/x86/xen/smp.c                   |  39 +++++---
+ arch/x86/xen/xen-head.S              |  10 ++-
+ drivers/xen/balloon.c                |  14 +--
+ drivers/xen/cpu_hotplug.c            |   4 +-
+ drivers/xen/events.c                 |  28 ++++--
+ drivers/xen/gntdev.c                 |   3 +-
+ drivers/xen/grant-table.c            |  64 ++++++++++++-
+ drivers/xen/privcmd.c                |   2 +-
+ drivers/xen/xenbus/xenbus_client.c   |   3 +-
+ 18 files changed, 424 insertions(+), 79 deletions(-)
+Merging xen-pvhvm/linux-next (b056b6a xen: suspend: remove xen_hvm_suspend)
+$ git merge xen-pvhvm/linux-next
+Already up-to-date.
+Merging percpu/for-next (a1b2a55 percpu: add documentation on this_cpu operations)
+$ git merge percpu/for-next
+Merge made by the 'recursive' strategy.
+ Documentation/this_cpu_ops.txt | 205 +++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 205 insertions(+)
+ create mode 100644 Documentation/this_cpu_ops.txt
+Merging workqueues/for-next (24c288b Merge branch 'for-3.10' into for-next)
+$ git merge workqueues/for-next
+Merge made by the 'recursive' strategy.
+ arch/sh/drivers/pci/pcie-sh7786.c |  2 +-
+ include/linux/async.h             | 13 +++++--------
+ kernel/async.c                    | 40 ++++++++++++++++++---------------------
+ kernel/workqueue.c                |  2 +-
+ 4 files changed, 25 insertions(+), 32 deletions(-)
+Merging drivers-x86/linux-next (e6e5224 ideapad-laptop: Depend on BACKLIGHT_CLASS_DEVICE instead of selecting it)
+$ git merge drivers-x86/linux-next
+Resolved 'drivers/platform/x86/chromeos_laptop.c' using previous resolution.
+Auto-merging drivers/platform/x86/chromeos_laptop.c
+CONFLICT (content): Merge conflict in drivers/platform/x86/chromeos_laptop.c
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master c881318] Merge remote-tracking branch 'drivers-x86/linux-next'
+$ git diff -M --stat --summary HEAD^..
+Merging hwpoison/hwpoison (46e387b Merge branch 'hwpoison-hugepages' into hwpoison)
+$ git merge hwpoison/hwpoison
+Already up-to-date.
+Merging sysctl/master (4e474a0 sysctl: protect poll() in entries that may go away)
+$ git merge sysctl/master
+Already up-to-date.
+Merging regmap/for-next (833d040 Merge remote-tracking branch 'regmap/topic/range' into regmap-next)
+$ git merge regmap/for-next
+Merge made by the 'recursive' strategy.
+ drivers/base/regmap/internal.h        |  40 +++++--
+ drivers/base/regmap/regcache-lzo.c    |   6 +-
+ drivers/base/regmap/regcache-rbtree.c | 100 ++++++++---------
+ drivers/base/regmap/regcache.c        | 196 ++++++++++++++++++++++++++++++----
+ drivers/base/regmap/regmap-debugfs.c  |  94 ++++++++++++++--
+ drivers/base/regmap/regmap-irq.c      |   3 +-
+ drivers/base/regmap/regmap.c          |  89 ++++++++++-----
+ include/linux/regmap.h                |   1 +
+ include/trace/events/regmap.h         |  48 +++++++++
+ 9 files changed, 461 insertions(+), 116 deletions(-)
+Merging hsi/for-next (43139a6 HSI: hsi_char: Update ioctl-number.txt)
+$ git merge hsi/for-next
+Already up-to-date.
+Merging leds/for-next (df92d5f leds: leds-asic3: switch to using SIMPLE_DEV_PM_OPS)
+$ git merge leds/for-next
+Auto-merging include/linux/mmc/host.h
+Auto-merging drivers/leds/trigger/ledtrig-transient.c
+Auto-merging drivers/leds/trigger/ledtrig-timer.c
+Auto-merging drivers/leds/trigger/ledtrig-oneshot.c
+Auto-merging drivers/leds/trigger/ledtrig-heartbeat.c
+Auto-merging drivers/leds/trigger/ledtrig-gpio.c
+Auto-merging drivers/leds/trigger/ledtrig-default-on.c
+Auto-merging drivers/leds/trigger/ledtrig-cpu.c
+Auto-merging drivers/leds/trigger/ledtrig-backlight.c
+Merge made by the 'recursive' strategy.
+ Documentation/leds/00-INDEX                     |   2 +
+ Documentation/leds/leds-lp5521.txt              |  19 -
+ Documentation/leds/leds-lp5562.txt              | 120 +++++
+ Documentation/leds/leds-lp55xx.txt              |  46 +-
+ drivers/leds/Kconfig                            | 115 +----
+ drivers/leds/Makefile                           |  11 +-
+ drivers/leds/leds-asic3.c                       |   7 +-
+ drivers/leds/leds-atmel-pwm.c                   |   4 +-
+ drivers/leds/leds-bd2802.c                      |  14 +-
+ drivers/leds/leds-lm355x.c                      |   2 +
+ drivers/leds/leds-lm3642.c                      |   2 +
+ drivers/leds/leds-lp5521.c                      |  22 +-
+ drivers/leds/leds-lp5562.c                      | 599 ++++++++++++++++++++++++
+ drivers/leds/leds-lp55xx-common.c               |  42 +-
+ drivers/leds/leds-lp55xx-common.h               |   4 +
+ drivers/leds/leds-lt3593.c                      |   5 +-
+ drivers/leds/leds-ns2.c                         |  44 +-
+ drivers/leds/leds-pwm.c                         |  50 +-
+ drivers/leds/leds-renesas-tpu.c                 |   3 +-
+ drivers/leds/leds-tca6507.c                     |   4 +-
+ drivers/leds/leds-wm8350.c                      |   5 +-
+ drivers/leds/trigger/Kconfig                    | 111 +++++
+ drivers/leds/trigger/Makefile                   |  10 +
+ drivers/leds/{ => trigger}/ledtrig-backlight.c  |   2 +-
+ drivers/leds/trigger/ledtrig-camera.c           |  57 +++
+ drivers/leds/{ => trigger}/ledtrig-cpu.c        |   2 +-
+ drivers/leds/{ => trigger}/ledtrig-default-on.c |   2 +-
+ drivers/leds/{ => trigger}/ledtrig-gpio.c       |   2 +-
+ drivers/leds/{ => trigger}/ledtrig-heartbeat.c  |   2 +-
+ drivers/leds/{ => trigger}/ledtrig-ide-disk.c   |   0
+ drivers/leds/{ => trigger}/ledtrig-oneshot.c    |   2 +-
+ drivers/leds/{ => trigger}/ledtrig-timer.c      |   1 -
+ drivers/leds/{ => trigger}/ledtrig-transient.c  |   2 +-
+ include/linux/leds.h                            |  33 +-
+ include/linux/mmc/host.h                        |   2 -
+ include/linux/platform_data/leds-lp55xx.h       |  21 +-
+ 36 files changed, 1149 insertions(+), 220 deletions(-)
+ create mode 100644 Documentation/leds/leds-lp5562.txt
+ create mode 100644 drivers/leds/leds-lp5562.c
+ create mode 100644 drivers/leds/trigger/Kconfig
+ create mode 100644 drivers/leds/trigger/Makefile
+ rename drivers/leds/{ => trigger}/ledtrig-backlight.c (99%)
+ create mode 100644 drivers/leds/trigger/ledtrig-camera.c
+ rename drivers/leds/{ => trigger}/ledtrig-cpu.c (99%)
+ rename drivers/leds/{ => trigger}/ledtrig-default-on.c (98%)
+ rename drivers/leds/{ => trigger}/ledtrig-gpio.c (99%)
+ rename drivers/leds/{ => trigger}/ledtrig-heartbeat.c (99%)
+ rename drivers/leds/{ => trigger}/ledtrig-ide-disk.c (100%)
+ rename drivers/leds/{ => trigger}/ledtrig-oneshot.c (99%)
+ rename drivers/leds/{ => trigger}/ledtrig-timer.c (99%)
+ rename drivers/leds/{ => trigger}/ledtrig-transient.c (99%)
+Merging driver-core/driver-core-next (bcfb87f sysfs: fix crash_notes_size build warning)
+$ git merge driver-core/driver-core-next
+Auto-merging include/linux/device.h
+Auto-merging drivers/base/core.c
+Auto-merging drivers/base/bus.c
+Merge made by the 'recursive' strategy.
+ Documentation/ABI/testing/sysfs-devices-system-cpu | 12 ++++++++
+ drivers/base/bus.c                                 |  8 +++---
+ drivers/base/core.c                                |  9 +++++-
+ drivers/base/cpu.c                                 | 14 ++++++++++
+ drivers/base/platform.c                            | 24 ++++++++--------
+ fs/sysfs/dir.c                                     | 32 +++++++++-------------
+ include/linux/device.h                             | 12 ++------
+ include/linux/platform_device.h                    | 25 ++++++++++-------
+ kernel/rtmutex-tester.c                            |  4 +--
+ 9 files changed, 84 insertions(+), 56 deletions(-)
+Merging tty/tty-next (89fa28d amba-pl011: fix build error if CONFIG_DMA_ENGINE is not enabled)
+$ git merge tty/tty-next
+Auto-merging drivers/usb/class/cdc-acm.c
+Auto-merging drivers/tty/sysrq.c
+Auto-merging drivers/net/ppp/ppp_synctty.c
+Auto-merging drivers/isdn/i4l/isdn_tty.c
+Merge made by the 'recursive' strategy.
+ .../devicetree/bindings/tty/serial/of-serial.txt   |   4 +
+ arch/ia64/hp/sim/simserial.c                       |  16 +-
+ arch/um/drivers/chan_kern.c                        |   6 +-
+ arch/um/drivers/line.c                             |   8 +-
+ drivers/isdn/capi/capi.c                           |   7 +-
+ drivers/isdn/gigaset/interface.c                   |   6 +-
+ drivers/isdn/i4l/isdn_tty.c                        |   3 -
+ drivers/mmc/card/sdio_uart.c                       |  13 +-
+ drivers/net/caif/caif_serial.c                     |   4 +-
+ drivers/net/ppp/ppp_async.c                        |   2 +-
+ drivers/net/ppp/ppp_synctty.c                      |   2 +-
+ drivers/net/usb/hso.c                              |  20 +-
+ drivers/s390/char/sclp_tty.c                       |   9 +-
+ drivers/s390/char/sclp_vt220.c                     |   8 +-
+ drivers/staging/fwserial/fwserial.c                |  10 +-
+ drivers/staging/serqt_usb2/serqt_usb2.c            |   7 +-
+ drivers/tty/amiserial.c                            |  14 +-
+ drivers/tty/cyclades.c                             |  10 +-
+ drivers/tty/ehv_bytechan.c                         |   6 +-
+ drivers/tty/hvc/hvsi.c                             |   7 +-
+ drivers/tty/ipwireless/hardware.c                  |   3 +-
+ drivers/tty/moxa.c                                 |  19 +-
+ drivers/tty/mxser.c                                |   4 +
+ drivers/tty/n_gsm.c                                |  10 +-
+ drivers/tty/n_tty.c                                | 172 ++++++-----
+ drivers/tty/nozomi.c                               |  15 +-
+ drivers/tty/pty.c                                  |   1 -
+ drivers/tty/rocket.c                               |  26 +-
+ drivers/tty/serial/68328serial.c                   |   9 +-
+ drivers/tty/serial/8250/8250.h                     |   7 -
+ drivers/tty/serial/8250/8250_core.c                |  18 +-
+ drivers/tty/serial/8250/8250_dw.c                  |  33 ++-
+ drivers/tty/serial/amba-pl011.c                    | 161 ++++++++--
+ drivers/tty/serial/arc_uart.c                      |   2 +-
+ drivers/tty/serial/bfin_uart.c                     |  23 --
+ drivers/tty/serial/crisv10.c                       | 168 +++++------
+ drivers/tty/serial/crisv10.h                       |  14 -
+ drivers/tty/serial/ifx6x60.c                       |  80 +----
+ drivers/tty/serial/jsm/jsm_tty.c                   |   6 -
+ drivers/tty/serial/max3100.c                       |  20 +-
+ drivers/tty/serial/max310x.c                       |  24 +-
+ drivers/tty/serial/mrst_max3110.c                  |  19 +-
+ drivers/tty/serial/msm_serial_hs.c                 |   2 -
+ drivers/tty/serial/msm_smd_tty.c                   |  14 +-
+ drivers/tty/serial/of_serial.c                     |  17 +-
+ drivers/tty/serial/pch_uart.c                      | 103 +++++--
+ drivers/tty/serial/samsung.c                       |  46 ++-
+ drivers/tty/serial/serial-tegra.c                  |   9 +-
+ drivers/tty/serial/sh-sci.h                        |   2 -
+ drivers/tty/serial/sunsab.c                        |   2 +-
+ drivers/tty/serial/sunzilog.c                      |   2 +-
+ drivers/tty/serial/vt8500_serial.c                 |   7 +-
+ drivers/tty/serial/xilinx_uartps.c                 |   3 -
+ drivers/tty/synclink.c                             |   3 -
+ drivers/tty/sysrq.c                                |  38 +--
+ drivers/tty/tty_io.c                               | 170 +++++++----
+ drivers/tty/tty_ioctl.c                            | 120 +++++---
+ drivers/tty/tty_ldisc.c                            | 326 ++++++++++-----------
+ drivers/tty/tty_port.c                             | 111 +++++--
+ drivers/usb/class/cdc-acm.c                        |  31 +-
+ drivers/usb/serial/digi_acceleport.c               |  17 +-
+ drivers/usb/serial/io_edgeport.c                   |  28 +-
+ drivers/usb/serial/keyspan.c                       |  43 +--
+ drivers/usb/serial/keyspan_pda.c                   |   6 +-
+ drivers/usb/serial/mos7720.c                       |   8 +-
+ drivers/usb/serial/mos7840.c                       |   7 +-
+ drivers/usb/serial/option.c                        |   9 +-
+ drivers/usb/serial/quatech2.c                      |  17 +-
+ drivers/usb/serial/sierra.c                        |   8 +-
+ drivers/usb/serial/ti_usb_3410_5052.c              |   7 +-
+ drivers/usb/serial/usb-serial.c                    |  10 +-
+ include/linux/amba/serial.h                        |   3 +
+ include/linux/tty.h                                |  41 ++-
+ include/linux/tty_ldisc.h                          | 132 ++++-----
+ net/irda/ircomm/ircomm_tty_attach.c                |   6 +-
+ 75 files changed, 1196 insertions(+), 1148 deletions(-)
+Merging usb/usb-next (369a9a9 usb: host: ehci-tegra: Fix oops in error cleanup)
+$ git merge usb/usb-next
+Resolved 'drivers/usb/serial/usb-serial.c' using previous resolution.
+Auto-merging drivers/usb/serial/usb-serial.c
+CONFLICT (content): Merge conflict in drivers/usb/serial/usb-serial.c
+Auto-merging drivers/usb/serial/ti_usb_3410_5052.c
+Auto-merging drivers/usb/serial/sierra.c
+Auto-merging drivers/usb/serial/quatech2.c
+Auto-merging drivers/usb/serial/mos7840.c
+Auto-merging drivers/usb/serial/mos7720.c
+Auto-merging drivers/usb/serial/keyspan_pda.c
+Auto-merging drivers/usb/serial/keyspan.c
+Auto-merging drivers/usb/serial/io_edgeport.c
+Auto-merging drivers/usb/serial/digi_acceleport.c
+Auto-merging drivers/usb/host/sl811-hcd.c
+Removing drivers/usb/host/ehci-vt8500.c
+Auto-merging drivers/usb/core/port.c
+Auto-merging drivers/usb/class/cdc-acm.c
+Removing drivers/usb/chipidea/usbmisc_imx6q.c
+Auto-merging drivers/net/usb/smsc75xx.c
+Auto-merging drivers/hid/usbhid/hid-core.c
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master 25b98c8] Merge remote-tracking branch 'usb/usb-next'
+$ git diff -M --stat --summary HEAD^..
+ Documentation/ABI/testing/sysfs-bus-usb            |   6 +-
+ .../devicetree/bindings/usb/ci13xxx-imx.txt        |   2 +
+ .../devicetree/bindings/usb/ehci-omap.txt          |  32 +
+ .../devicetree/bindings/usb/ohci-omap3.txt         |  15 +
+ Documentation/ioctl/ioctl-number.txt               |   1 +
+ Documentation/usb/power-management.txt             |  10 +-
+ drivers/hid/usbhid/hid-core.c                      |  14 +-
+ drivers/net/usb/cdc_mbim.c                         |   5 +
+ drivers/net/usb/qmi_wwan.c                         |   5 +
+ drivers/net/usb/smsc75xx.c                         |   6 +-
+ drivers/net/usb/smsc95xx.c                         |   6 +-
+ drivers/staging/Kconfig                            |   2 -
+ drivers/staging/Makefile                           |   1 -
+ drivers/usb/chipidea/Makefile                      |   2 +-
+ drivers/usb/chipidea/ci.h                          |  19 +-
+ drivers/usb/chipidea/ci13xxx_imx.c                 |  12 +
+ drivers/usb/chipidea/ci13xxx_imx.h                 |   3 +
+ drivers/usb/chipidea/ci13xxx_pci.c                 |   6 +-
+ drivers/usb/chipidea/core.c                        |  66 +-
+ drivers/usb/chipidea/debug.c                       | 888 +++++----------------
+ drivers/usb/chipidea/debug.h                       |  34 +-
+ drivers/usb/chipidea/udc.c                         | 266 +++---
+ drivers/usb/chipidea/usbmisc_imx.c                 | 261 ++++++
+ drivers/usb/chipidea/usbmisc_imx6q.c               | 162 ----
+ drivers/usb/class/cdc-acm.c                        |   8 -
+ drivers/usb/class/cdc-wdm.c                        |  19 +
+ drivers/usb/core/Kconfig                           |  32 +-
+ drivers/usb/core/driver.c                          |  25 +-
+ drivers/usb/core/generic.c                         |   2 +-
+ drivers/usb/core/hcd-pci.c                         | 214 +++--
+ drivers/usb/core/hcd.c                             |  10 +-
+ drivers/usb/core/hub.c                             | 136 ++--
+ drivers/usb/core/port.c                            |   4 +-
+ drivers/usb/core/quirks.c                          |  16 +-
+ drivers/usb/core/sysfs.c                           |   4 +-
+ drivers/usb/core/urb.c                             |   5 +-
+ drivers/usb/core/usb.c                             |   4 +-
+ drivers/usb/core/usb.h                             |   2 +-
+ drivers/usb/host/Kconfig                           |   3 +-
+ drivers/usb/host/Makefile                          |   1 +
+ drivers/usb/host/ehci-dbg.c                        |  15 +-
+ drivers/usb/host/ehci-fsl.c                        |   9 +
+ drivers/usb/host/ehci-hcd.c                        |  74 +-
+ drivers/usb/host/ehci-hub.c                        |  23 +-
+ drivers/usb/host/ehci-mv.c                         |   2 +-
+ drivers/usb/host/ehci-mxc.c                        |   8 +-
+ drivers/usb/host/ehci-omap.c                       | 331 ++++----
+ drivers/usb/host/ehci-orion.c                      |   4 +-
+ drivers/usb/host/ehci-pci.c                        |  12 +-
+ drivers/usb/host/ehci-platform.c                   |  34 +-
+ drivers/usb/host/ehci-ps3.c                        |   1 -
+ drivers/usb/host/ehci-q.c                          | 241 +++---
+ drivers/usb/host/ehci-s5p.c                        |  11 +-
+ drivers/usb/host/ehci-sched.c                      |  40 +-
+ drivers/usb/host/ehci-sh.c                         |   5 +-
+ drivers/usb/host/ehci-spear.c                      |   4 +-
+ drivers/usb/host/ehci-tegra.c                      |  12 +-
+ drivers/usb/host/ehci-timer.c                      |  72 +-
+ drivers/usb/host/ehci-vt8500.c                     | 150 ----
+ drivers/usb/host/ehci.h                            |  16 +-
+ drivers/usb/host/ohci-hub.c                        |   6 -
+ drivers/usb/host/ohci-omap3.c                      |  24 +-
+ drivers/usb/host/sl811-hcd.c                       |   2 +-
+ drivers/usb/host/u132-hcd.c                        |   9 +-
+ drivers/usb/host/xhci-hub.c                        |   2 +-
+ drivers/usb/host/xhci.c                            |   4 +-
+ drivers/usb/misc/appledisplay.c                    |   1 +
+ drivers/usb/misc/sisusbvga/sisusb.c                |   2 +-
+ drivers/usb/misc/usb3503.c                         |  13 +-
+ drivers/usb/otg/isp1301_omap.c                     |   4 +-
+ drivers/usb/otg/twl4030-usb.c                      |   4 +-
+ drivers/usb/otg/twl6030-usb.c                      |   4 +-
+ drivers/usb/phy/mv_u3d_phy.c                       |   2 +-
+ drivers/usb/serial/ark3116.c                       |  87 +-
+ drivers/usb/serial/bus.c                           |   5 +-
+ drivers/usb/serial/ch341.c                         |  30 +-
+ drivers/usb/serial/cp210x.c                        |   6 +-
+ drivers/usb/serial/cyberjack.c                     |  19 +-
+ drivers/usb/serial/cypress_m8.c                    |  94 +--
+ drivers/usb/serial/digi_acceleport.c               |  95 ++-
+ drivers/usb/serial/f81232.c                        |  13 +-
+ drivers/usb/serial/ftdi_sio.c                      | 121 +--
+ drivers/usb/serial/garmin_gps.c                    |  10 -
+ drivers/usb/serial/generic.c                       | 144 +++-
+ drivers/usb/serial/io_edgeport.c                   |  76 +-
+ drivers/usb/serial/io_tables.h                     |  12 +-
+ drivers/usb/serial/io_ti.c                         |  85 +-
+ drivers/usb/serial/iuu_phoenix.c                   |  21 +-
+ drivers/usb/serial/keyspan.c                       |  26 +-
+ drivers/usb/serial/keyspan_pda.c                   |  19 +-
+ drivers/usb/serial/kl5kusb105.c                    |  30 +-
+ drivers/usb/serial/mct_u232.c                      |  94 +--
+ drivers/usb/serial/metro-usb.c                     |   5 +-
+ drivers/usb/serial/mos7720.c                       |  68 +-
+ drivers/usb/serial/mos7840.c                       | 157 +---
+ drivers/usb/serial/opticon.c                       |  18 +-
+ drivers/usb/serial/oti6858.c                       |  30 +-
+ drivers/usb/serial/pl2303.c                        |  39 +-
+ drivers/usb/serial/quatech2.c                      |  97 +--
+ drivers/usb/serial/sierra.c                        |  39 +-
+ drivers/usb/serial/spcp8x5.c                       | 301 ++-----
+ drivers/usb/serial/ssu100.c                        | 100 +--
+ drivers/usb/serial/ti_usb_3410_5052.c              |  69 +-
+ drivers/usb/serial/usb-serial.c                    | 230 +++---
+ drivers/usb/serial/usb_wwan.c                      |  25 +-
+ drivers/usb/serial/visor.c                         |  16 +-
+ drivers/usb/storage/onetouch.c                     |   4 +-
+ drivers/usb/usb-skeleton.c                         |  32 +-
+ include/linux/usb.h                                |  13 +-
+ include/linux/usb/cdc-wdm.h                        |   2 +
+ include/linux/usb/hcd.h                            |   6 +-
+ include/linux/usb/serial.h                         |  12 +-
+ include/uapi/linux/usb/cdc-wdm.h                   |  21 +
+ 113 files changed, 2056 insertions(+), 3665 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/usb/ehci-omap.txt
+ create mode 100644 Documentation/devicetree/bindings/usb/ohci-omap3.txt
+ create mode 100644 drivers/usb/chipidea/usbmisc_imx.c
+ delete mode 100644 drivers/usb/chipidea/usbmisc_imx6q.c
+ delete mode 100644 drivers/usb/host/ehci-vt8500.c
+ create mode 100644 include/uapi/linux/usb/cdc-wdm.h
+Merging usb-gadget/next (9b192de usb: gadget: nokia: include f_ecm.c)
+$ git merge usb-gadget/next
+Resolved 'drivers/usb/chipidea/udc.c' using previous resolution.
+Resolved 'drivers/usb/gadget/net2272.c' using previous resolution.
+Resolved 'drivers/usb/gadget/net2280.c' using previous resolution.
+Resolved 'drivers/usb/host/ehci-tegra.c' using previous resolution.
+Removing drivers/usb/phy/samsung-usbphy.c
+Auto-merging drivers/usb/phy/phy.c
+Auto-merging drivers/usb/phy/phy-twl6030-usb.c
+Auto-merging drivers/usb/phy/phy-twl4030-usb.c
+Auto-merging drivers/usb/phy/phy-nop.c
+Auto-merging drivers/usb/phy/phy-mxs-usb.c
+Auto-merging drivers/usb/phy/phy-mv-usb.h
+Auto-merging drivers/usb/phy/phy-mv-usb.c
+Auto-merging drivers/usb/phy/phy-mv-u3d-usb.c
+Auto-merging drivers/usb/phy/phy-isp1301-omap.c
+Auto-merging drivers/usb/phy/phy-gpio-vbus-usb.c
+Auto-merging drivers/usb/phy/phy-fsm-usb.c
+Auto-merging drivers/usb/phy/phy-fsl-usb.c
+Removing drivers/usb/phy/isp1301.c
+Auto-merging drivers/usb/phy/Kconfig
+Removing drivers/usb/otg/ab8500-usb.c
+Removing drivers/usb/otg/Makefile
+Removing drivers/usb/otg/Kconfig
+Auto-merging drivers/usb/musb/musb_gadget.c
+Auto-merging drivers/usb/musb/da8xx.c
+Auto-merging drivers/usb/host/ehci-tegra.c
+CONFLICT (content): Merge conflict in drivers/usb/host/ehci-tegra.c
+Auto-merging drivers/usb/host/ehci-s5p.c
+Auto-merging drivers/usb/host/ehci-mv.c
+Auto-merging drivers/usb/host/Kconfig
+Auto-merging drivers/usb/gadget/udc-core.c
+Auto-merging drivers/usb/gadget/net2280.c
+CONFLICT (content): Merge conflict in drivers/usb/gadget/net2280.c
+Auto-merging drivers/usb/gadget/net2272.c
+CONFLICT (content): Merge conflict in drivers/usb/gadget/net2272.c
+Auto-merging drivers/usb/gadget/lpc32xx_udc.c
+Auto-merging drivers/usb/gadget/g_ffs.c
+Auto-merging drivers/usb/gadget/f_rndis.c
+Auto-merging drivers/usb/gadget/at91_udc.c
+Auto-merging drivers/usb/gadget/Kconfig
+Auto-merging drivers/usb/chipidea/udc.c
+CONFLICT (content): Merge conflict in drivers/usb/chipidea/udc.c
+Auto-merging drivers/power/Kconfig
+Auto-merging drivers/Makefile
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master bc7987c] Merge remote-tracking branch 'usb-gadget/next'
+$ git diff -M --stat --summary HEAD^..
+ Documentation/devicetree/bindings/usb/omap-usb.txt |   40 +-
+ .../devicetree/bindings/usb/samsung-usbphy.txt     |   76 +-
+ .../devicetree/bindings/usb/usb-nop-xceiv.txt      |   34 +
+ arch/arm/mach-mmp/aspenite.c                       |    6 -
+ arch/arm/mach-mmp/ttc_dkb.c                        |    6 -
+ arch/arm/mach-shmobile/board-armadillo800eva.c     |    8 +-
+ arch/arm/mach-shmobile/board-kzm9g.c               |    8 +-
+ arch/arm/mach-shmobile/board-mackerel.c            |   12 +-
+ arch/arm/mach-tegra/Kconfig                        |    8 +-
+ arch/sh/boards/mach-ecovec24/setup.c               |    4 +-
+ drivers/Makefile                                   |    2 +-
+ drivers/power/Kconfig                              |    2 +-
+ drivers/power/pda_power.c                          |   14 +-
+ drivers/usb/Kconfig                                |    2 -
+ drivers/usb/Makefile                               |    4 +-
+ drivers/usb/chipidea/udc.c                         |   27 +-
+ drivers/usb/dwc3/Kconfig                           |    1 -
+ drivers/usb/dwc3/core.c                            |  201 +++-
+ drivers/usb/dwc3/core.h                            |   72 +-
+ drivers/usb/dwc3/debugfs.c                         |   52 +-
+ drivers/usb/dwc3/dwc3-exynos.c                     |   98 +-
+ drivers/usb/dwc3/dwc3-omap.c                       |  245 +++--
+ drivers/usb/dwc3/dwc3-pci.c                        |   38 +
+ drivers/usb/dwc3/ep0.c                             |   33 +-
+ drivers/usb/dwc3/gadget.c                          |  321 +++++--
+ drivers/usb/gadget/Kconfig                         |   18 +-
+ drivers/usb/gadget/Makefile                        |   13 +-
+ drivers/usb/gadget/acm_ms.c                        |   15 +-
+ drivers/usb/gadget/amd5536udc.c                    |   16 +-
+ drivers/usb/gadget/amd5536udc.h                    |    1 -
+ drivers/usb/gadget/at91_udc.c                      |   14 +-
+ drivers/usb/gadget/atmel_usba_udc.c                |   44 +-
+ drivers/usb/gadget/atmel_usba_udc.h                |    6 -
+ drivers/usb/gadget/bcm63xx_udc.c                   |   23 -
+ drivers/usb/gadget/cdc2.c                          |   27 +-
+ drivers/usb/gadget/composite.c                     |    1 +
+ drivers/usb/gadget/configfs.c                      | 1003 ++++++++++++++++++++
+ drivers/usb/gadget/dummy_hcd.c                     |   19 +-
+ drivers/usb/gadget/ether.c                         |   20 +-
+ drivers/usb/gadget/f_acm.c                         |  137 +--
+ drivers/usb/gadget/f_ecm.c                         |    4 +-
+ drivers/usb/gadget/f_eem.c                         |    3 +-
+ drivers/usb/gadget/f_ncm.c                         |    4 +-
+ drivers/usb/gadget/f_obex.c                        |  226 ++++-
+ drivers/usb/gadget/f_rndis.c                       |    3 +-
+ drivers/usb/gadget/f_serial.c                      |  174 +++-
+ drivers/usb/gadget/f_subset.c                      |    4 +-
+ drivers/usb/gadget/f_uvc.c                         |  262 +++--
+ drivers/usb/gadget/f_uvc.h                         |   12 +-
+ drivers/usb/gadget/fsl_qe_udc.c                    |   18 +-
+ drivers/usb/gadget/fsl_udc_core.c                  |   83 +-
+ drivers/usb/gadget/fusb300_udc.c                   |   46 +-
+ drivers/usb/gadget/fusb300_udc.h                   |    2 +-
+ drivers/usb/gadget/g_ffs.c                         |   35 +-
+ drivers/usb/gadget/goku_udc.c                      |   20 +-
+ drivers/usb/gadget/goku_udc.h                      |    3 +-
+ drivers/usb/gadget/imx_udc.c                       |   16 +-
+ drivers/usb/gadget/lpc32xx_udc.c                   |   51 +-
+ drivers/usb/gadget/m66592-udc.c                    |   17 -
+ drivers/usb/gadget/multi.c                         |   29 +-
+ drivers/usb/gadget/mv_u3d_core.c                   |   65 +-
+ drivers/usb/gadget/mv_udc.h                        |    3 +-
+ drivers/usb/gadget/mv_udc_core.c                   |  117 +--
+ drivers/usb/gadget/ncm.c                           |   13 +-
+ drivers/usb/gadget/net2272.c                       |   25 +-
+ drivers/usb/gadget/net2280.c                       |   25 +-
+ drivers/usb/gadget/nokia.c                         |   95 +-
+ drivers/usb/gadget/omap_udc.c                      |   21 +-
+ drivers/usb/gadget/pch_udc.c                       |   21 +-
+ drivers/usb/gadget/pxa25x_udc.c                    |   16 -
+ drivers/usb/gadget/pxa27x_udc.c                    |   51 +-
+ drivers/usb/gadget/r8a66597-udc.c                  |   14 +-
+ drivers/usb/gadget/s3c-hsotg.c                     |   78 +-
+ drivers/usb/gadget/s3c-hsudc.c                     |   16 -
+ drivers/usb/gadget/s3c2410_udc.c                   |   15 -
+ drivers/usb/gadget/serial.c                        |   59 +-
+ drivers/usb/gadget/u_ether.c                       |   32 +-
+ drivers/usb/gadget/u_ether.h                       |   27 +-
+ drivers/usb/gadget/u_serial.h                      |    1 -
+ drivers/usb/gadget/udc-core.c                      |   90 +-
+ drivers/usb/gadget/uvc.h                           |    3 +-
+ drivers/usb/gadget/uvc_queue.c                     |  538 ++++-------
+ drivers/usb/gadget/uvc_queue.h                     |   32 +-
+ drivers/usb/gadget/uvc_v4l2.c                      |   71 +-
+ drivers/usb/gadget/uvc_video.c                     |   31 +-
+ drivers/usb/host/Kconfig                           |    2 +-
+ drivers/usb/host/ehci-msm.c                        |    2 +-
+ drivers/usb/host/ehci-mv.c                         |   54 +-
+ drivers/usb/host/ehci-s5p.c                        |    2 +-
+ drivers/usb/host/ehci-tegra.c                      |   12 +-
+ drivers/usb/host/ohci-exynos.c                     |    2 +-
+ drivers/usb/musb/Kconfig                           |    6 +-
+ drivers/usb/musb/am35x.c                           |    8 +-
+ drivers/usb/musb/blackfin.c                        |    6 +-
+ drivers/usb/musb/cppi_dma.c                        |   17 +-
+ drivers/usb/musb/da8xx.c                           |    8 +-
+ drivers/usb/musb/davinci.c                         |    4 +-
+ drivers/usb/musb/musb_core.c                       |   71 +-
+ drivers/usb/musb/musb_dsps.c                       |   14 +-
+ drivers/usb/musb/musb_gadget.c                     |  156 +--
+ drivers/usb/musb/musb_gadget_ep0.c                 |    6 +-
+ drivers/usb/musb/musb_host.c                       |  119 ++-
+ drivers/usb/musb/musb_virthub.c                    |    4 +-
+ drivers/usb/musb/omap2430.c                        |   32 +-
+ drivers/usb/musb/tusb6010.c                        |   14 +-
+ drivers/usb/musb/ux500.c                           |  106 +++
+ drivers/usb/musb/ux500_dma.c                       |   24 +-
+ drivers/usb/otg/Kconfig                            |  141 ---
+ drivers/usb/otg/Makefile                           |   24 -
+ drivers/usb/otg/ab8500-usb.c                       |  596 ------------
+ drivers/usb/phy/Kconfig                            |  180 +++-
+ drivers/usb/phy/Makefile                           |   35 +-
+ drivers/usb/phy/isp1301.c                          |   71 --
+ drivers/usb/phy/phy-ab8500-usb.c                   |  924 ++++++++++++++++++
+ drivers/usb/{otg/fsl_otg.c => phy/phy-fsl-usb.c}   |   34 +-
+ drivers/usb/{otg/fsl_otg.h => phy/phy-fsl-usb.h}   |    0
+ drivers/usb/{otg/otg_fsm.c => phy/phy-fsm-usb.c}   |    4 +-
+ drivers/usb/{otg/otg_fsm.h => phy/phy-fsm-usb.h}   |    0
+ .../{otg/gpio_vbus.c => phy/phy-gpio-vbus-usb.c}   |    9 +-
+ .../{otg/isp1301_omap.c => phy/phy-isp1301-omap.c} |    6 +-
+ drivers/usb/phy/phy-isp1301.c                      |  162 ++++
+ drivers/usb/{otg/msm_otg.c => phy/phy-msm-usb.c}   |    0
+ drivers/usb/phy/{mv_u3d_phy.c => phy-mv-u3d-usb.c} |    2 +-
+ drivers/usb/phy/{mv_u3d_phy.h => phy-mv-u3d-usb.h} |    0
+ drivers/usb/{otg/mv_otg.c => phy/phy-mv-usb.c}     |   30 +-
+ drivers/usb/{otg/mv_otg.h => phy/phy-mv-usb.h}     |    3 +-
+ drivers/usb/{otg/mxs-phy.c => phy/phy-mxs-usb.c}   |   41 +-
+ drivers/usb/{otg/nop-usb-xceiv.c => phy/phy-nop.c} |  143 ++-
+ .../phy/{omap-control-usb.c => phy-omap-control.c} |    0
+ drivers/usb/phy/{omap-usb2.c => phy-omap-usb2.c}   |    0
+ drivers/usb/phy/{omap-usb3.c => phy-omap-usb3.c}   |    0
+ drivers/usb/phy/{rcar-phy.c => phy-rcar-usb.c}     |    0
+ drivers/usb/phy/phy-samsung-usb.c                  |  236 +++++
+ drivers/usb/phy/phy-samsung-usb.h                  |  327 +++++++
+ drivers/usb/phy/phy-samsung-usb2.c                 |  509 ++++++++++
+ drivers/usb/phy/phy-samsung-usb3.c                 |  347 +++++++
+ .../usb/phy/{tegra_usb_phy.c => phy-tegra-usb.c}   |    0
+ .../{otg/twl4030-usb.c => phy/phy-twl4030-usb.c}   |  174 ++--
+ .../{otg/twl6030-usb.c => phy/phy-twl6030-usb.c}   |   11 +-
+ .../ulpi_viewport.c => phy/phy-ulpi-viewport.c}    |    0
+ drivers/usb/{otg/ulpi.c => phy/phy-ulpi.c}         |    0
+ drivers/usb/{otg/otg.c => phy/phy.c}               |   62 +-
+ drivers/usb/phy/samsung-usbphy.c                   |  928 ------------------
+ drivers/usb/renesas_usbhs/fifo.c                   |    1 -
+ drivers/usb/renesas_usbhs/fifo.h                   |    2 -
+ drivers/usb/renesas_usbhs/mod_gadget.c             |   24 +-
+ drivers/usb/usb-common.c                           |   47 +
+ include/linux/platform_data/dwc3-omap.h            |    4 -
+ include/linux/platform_data/mv_usb.h               |    2 -
+ include/linux/usb/ch9.h                            |    9 +
+ include/linux/usb/composite.h                      |    3 +
+ include/linux/usb/dwc3-omap.h                      |    6 +-
+ include/linux/usb/gadget.h                         |   11 +
+ include/linux/usb/gadget_configfs.h                |  110 +++
+ include/linux/usb/musb-ux500.h                     |   31 +
+ include/linux/usb/nop-usb-xceiv.h                  |    5 +
+ include/linux/usb/otg.h                            |    9 +-
+ include/linux/usb/phy.h                            |   33 +-
+ include/linux/usb/renesas_usbhs.h                  |    6 +-
+ 159 files changed, 6741 insertions(+), 4372 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/usb/usb-nop-xceiv.txt
+ create mode 100644 drivers/usb/gadget/configfs.c
+ delete mode 100644 drivers/usb/otg/Kconfig
+ delete mode 100644 drivers/usb/otg/Makefile
+ delete mode 100644 drivers/usb/otg/ab8500-usb.c
+ delete mode 100644 drivers/usb/phy/isp1301.c
+ create mode 100644 drivers/usb/phy/phy-ab8500-usb.c
+ rename drivers/usb/{otg/fsl_otg.c => phy/phy-fsl-usb.c} (97%)
+ rename drivers/usb/{otg/fsl_otg.h => phy/phy-fsl-usb.h} (100%)
+ rename drivers/usb/{otg/otg_fsm.c => phy/phy-fsm-usb.c} (99%)
+ rename drivers/usb/{otg/otg_fsm.h => phy/phy-fsm-usb.h} (100%)
+ rename drivers/usb/{otg/gpio_vbus.c => phy/phy-gpio-vbus-usb.c} (98%)
+ rename drivers/usb/{otg/isp1301_omap.c => phy/phy-isp1301-omap.c} (99%)
+ create mode 100644 drivers/usb/phy/phy-isp1301.c
+ rename drivers/usb/{otg/msm_otg.c => phy/phy-msm-usb.c} (100%)
+ rename drivers/usb/phy/{mv_u3d_phy.c => phy-mv-u3d-usb.c} (99%)
+ rename drivers/usb/phy/{mv_u3d_phy.h => phy-mv-u3d-usb.h} (100%)
+ rename drivers/usb/{otg/mv_otg.c => phy/phy-mv-usb.c} (97%)
+ rename drivers/usb/{otg/mv_otg.h => phy/phy-mv-usb.h} (99%)
+ rename drivers/usb/{otg/mxs-phy.c => phy/phy-mxs-usb.c} (84%)
+ rename drivers/usb/{otg/nop-usb-xceiv.c => phy/phy-nop.c} (55%)
+ rename drivers/usb/phy/{omap-control-usb.c => phy-omap-control.c} (100%)
+ rename drivers/usb/phy/{omap-usb2.c => phy-omap-usb2.c} (100%)
+ rename drivers/usb/phy/{omap-usb3.c => phy-omap-usb3.c} (100%)
+ rename drivers/usb/phy/{rcar-phy.c => phy-rcar-usb.c} (100%)
+ create mode 100644 drivers/usb/phy/phy-samsung-usb.c
+ create mode 100644 drivers/usb/phy/phy-samsung-usb.h
+ create mode 100644 drivers/usb/phy/phy-samsung-usb2.c
+ create mode 100644 drivers/usb/phy/phy-samsung-usb3.c
+ rename drivers/usb/phy/{tegra_usb_phy.c => phy-tegra-usb.c} (100%)
+ rename drivers/usb/{otg/twl4030-usb.c => phy/phy-twl4030-usb.c} (85%)
+ rename drivers/usb/{otg/twl6030-usb.c => phy/phy-twl6030-usb.c} (98%)
+ rename drivers/usb/{otg/ulpi_viewport.c => phy/phy-ulpi-viewport.c} (100%)
+ rename drivers/usb/{otg/ulpi.c => phy/phy-ulpi.c} (100%)
+ rename drivers/usb/{otg/otg.c => phy/phy.c} (89%)
+ delete mode 100644 drivers/usb/phy/samsung-usbphy.c
+ create mode 100644 include/linux/usb/gadget_configfs.h
+ create mode 100644 include/linux/usb/musb-ux500.h
+Merging staging/staging-next (e9e7023 staging: comedi: rtd520: rename thisboard variable)
+$ git merge staging/staging-next
+Resolved 'drivers/staging/dgrp/dgrp_dpa_ops.c' using previous resolution.
+Resolved 'drivers/staging/dgrp/dgrp_mon_ops.c' using previous resolution.
+Resolved 'drivers/staging/dgrp/dgrp_net_ops.c' using previous resolution.
+Resolved 'drivers/staging/dgrp/dgrp_ports_ops.c' using previous resolution.
+Resolved 'drivers/staging/dgrp/dgrp_specproc.c' using previous resolution.
+Removing drivers/staging/vt6656/ttype.h
+Auto-merging drivers/staging/ti-soc-thermal/ti_soc_thermal.txt
+Auto-merging drivers/staging/ti-soc-thermal/ti-thermal.h
+Auto-merging drivers/staging/ti-soc-thermal/omap4-thermal-data.c
+Auto-merging drivers/staging/ti-soc-thermal/TODO
+Auto-merging drivers/staging/ti-soc-thermal/Kconfig
+Auto-merging drivers/staging/silicom/bp_mod.c
+Auto-merging drivers/staging/rts5139/rts51x_scsi.h
+Auto-merging drivers/staging/rts5139/rts51x_scsi.c
+Removing drivers/staging/omap-thermal/omap5-thermal.c
+Removing drivers/staging/omap-thermal/omap-thermal-common.c
+Removing drivers/staging/omap-thermal/omap-bandgap.h
+Removing drivers/staging/omap-thermal/omap-bandgap.c
+Removing drivers/staging/omap-thermal/Makefile
+Removing drivers/staging/iio/adc/adt7410.c
+Auto-merging drivers/staging/gdm72xx/netlink_k.c
+Auto-merging drivers/staging/dgrp/dgrp_specproc.c
+CONFLICT (content): Merge conflict in drivers/staging/dgrp/dgrp_specproc.c
+Auto-merging drivers/staging/dgrp/dgrp_ports_ops.c
+CONFLICT (content): Merge conflict in drivers/staging/dgrp/dgrp_ports_ops.c
+Auto-merging drivers/staging/dgrp/dgrp_net_ops.c
+CONFLICT (content): Merge conflict in drivers/staging/dgrp/dgrp_net_ops.c
+Auto-merging drivers/staging/dgrp/dgrp_mon_ops.c
+CONFLICT (content): Merge conflict in drivers/staging/dgrp/dgrp_mon_ops.c
+Auto-merging drivers/staging/dgrp/dgrp_dpa_ops.c
+CONFLICT (content): Merge conflict in drivers/staging/dgrp/dgrp_dpa_ops.c
+Removing drivers/staging/comedi/drivers/rtd520.h
+Removing drivers/staging/ccg/usbstring.c
+Removing drivers/staging/ccg/u_serial.h
+Removing drivers/staging/ccg/u_serial.c
+Removing drivers/staging/ccg/u_ether.h
+Removing drivers/staging/ccg/u_ether.c
+Removing drivers/staging/ccg/sysfs-class-ccg_usb
+Removing drivers/staging/ccg/storage_common.c
+Removing drivers/staging/ccg/rndis.h
+CONFLICT (modify/delete): drivers/staging/ccg/rndis.c deleted in staging/staging-next and modified in HEAD. Version HEAD of drivers/staging/ccg/rndis.c left in tree.
+Removing drivers/staging/ccg/ndis.h
+Removing drivers/staging/ccg/gadget_chips.h
+Removing drivers/staging/ccg/f_rndis.c
+Removing drivers/staging/ccg/f_mass_storage.c
+CONFLICT (modify/delete): drivers/staging/ccg/f_fs.c deleted in staging/staging-next and modified in HEAD. Version HEAD of drivers/staging/ccg/f_fs.c left in tree.
+Removing drivers/staging/ccg/f_acm.c
+Removing drivers/staging/ccg/epautoconf.c
+Removing drivers/staging/ccg/config.c
+Removing drivers/staging/ccg/composite.h
+Removing drivers/staging/ccg/composite.c
+Removing drivers/staging/ccg/ccg.c
+Removing drivers/staging/ccg/TODO
+Removing drivers/staging/ccg/Makefile
+Removing drivers/staging/ccg/Kconfig
+Auto-merging drivers/staging/Makefile
+Auto-merging drivers/staging/Kconfig
+Auto-merging drivers/iio/magnetometer/ak8975.c
+Auto-merging drivers/hwmon/iio_hwmon.c
+Auto-merging drivers/hwmon/Makefile
+Auto-merging drivers/hwmon/Kconfig
+Auto-merging MAINTAINERS
+Automatic merge failed; fix conflicts and then commit the result.
+$ git rm -f drivers/staging/ccg/f_fs.c drivers/staging/ccg/rndis.c
+drivers/staging/ccg/f_fs.c: needs merge
+drivers/staging/ccg/rndis.c: needs merge
+rm 'drivers/staging/ccg/f_fs.c'
+rm 'drivers/staging/ccg/rndis.c'
+$ git commit -v -a
+[master f5ca597] Merge remote-tracking branch 'staging/staging-next'
+$ git diff -M --stat --summary HEAD^..
+ .../devicetree/bindings/arm/atmel-adc.txt          |   13 +
+ .../devicetree/bindings/arm/samsung/exynos-adc.txt |   60 +
+ .../devicetree/bindings/iio/iio-bindings.txt       |   97 +
+ MAINTAINERS                                        |   12 +
+ drivers/hwmon/Kconfig                              |    9 +
+ drivers/hwmon/Makefile                             |    1 +
+ drivers/{staging/iio => hwmon}/iio_hwmon.c         |    8 +-
+ drivers/iio/accel/hid-sensor-accel-3d.c            |   24 +-
+ drivers/iio/accel/kxsd9.c                          |    6 +-
+ drivers/iio/accel/st_accel_buffer.c                |    2 +-
+ drivers/iio/adc/Kconfig                            |   20 +
+ drivers/iio/adc/Makefile                           |    2 +
+ drivers/iio/adc/ad7266.c                           |   12 +-
+ drivers/iio/adc/ad7298.c                           |   10 +-
+ drivers/iio/adc/ad7476.c                           |   10 +-
+ drivers/iio/adc/ad7887.c                           |    8 +-
+ drivers/iio/adc/ad7923.c                           |  383 +
+ drivers/iio/adc/ad_sigma_delta.c                   |    2 +-
+ drivers/iio/adc/at91_adc.c                         |   98 +-
+ drivers/iio/adc/exynos_adc.c                       |  452 ++
+ drivers/iio/adc/lp8788_adc.c                       |    4 +-
+ drivers/iio/adc/max1363.c                          |    9 +-
+ drivers/iio/adc/ti-adc081c.c                       |    4 +-
+ drivers/iio/adc/ti_am335x_adc.c                    |    2 +-
+ drivers/iio/adc/viperboard_adc.c                   |    2 +-
+ drivers/iio/amplifiers/ad8366.c                    |    2 +-
+ .../iio/common/hid-sensors/hid-sensor-trigger.c    |    4 +-
+ drivers/iio/common/st_sensors/st_sensors_spi.c     |   11 +-
+ drivers/iio/common/st_sensors/st_sensors_trigger.c |    2 +-
+ drivers/iio/dac/ad5064.c                           |    4 +-
+ drivers/iio/dac/ad5360.c                           |   10 +-
+ drivers/iio/dac/ad5380.c                           |    8 +-
+ drivers/iio/dac/ad5421.c                           |   10 +-
+ drivers/iio/dac/ad5446.c                           |    4 +-
+ drivers/iio/dac/ad5449.c                           |    4 +-
+ drivers/iio/dac/ad5504.c                           |    4 +-
+ drivers/iio/dac/ad5624r_spi.c                      |    4 +-
+ drivers/iio/dac/ad5686.c                           |    6 +-
+ drivers/iio/dac/ad5755.c                           |   10 +-
+ drivers/iio/dac/ad5764.c                           |   10 +-
+ drivers/iio/dac/ad5791.c                           |    6 +-
+ drivers/iio/dac/max517.c                           |    4 +-
+ drivers/iio/dac/mcp4725.c                          |    4 +-
+ drivers/iio/frequency/ad9523.c                     |    8 +-
+ drivers/iio/gyro/adis16080.c                       |   22 +-
+ drivers/iio/gyro/adis16136.c                       |   13 +-
+ drivers/iio/gyro/adxrs450.c                        |   22 +-
+ drivers/iio/gyro/hid-sensor-gyro-3d.c              |   24 +-
+ drivers/iio/gyro/itg3200_buffer.c                  |    4 +-
+ drivers/iio/gyro/itg3200_core.c                    |   13 +-
+ drivers/iio/gyro/st_gyro_buffer.c                  |    2 +-
+ drivers/iio/iio_core.h                             |    1 +
+ drivers/iio/imu/adis16400_core.c                   |   49 +-
+ drivers/iio/imu/adis16480.c                        |   32 +-
+ drivers/iio/imu/adis_trigger.c                     |    4 +-
+ drivers/iio/imu/inv_mpu6050/inv_mpu_core.c         |   10 +-
+ drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c         |    5 +-
+ drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c      |    4 +-
+ drivers/iio/industrialio-core.c                    |   35 +-
+ drivers/iio/industrialio-event.c                   |   29 +-
+ drivers/iio/inkern.c                               |  171 +
+ drivers/iio/light/adjd_s311.c                      |    4 +-
+ drivers/iio/light/hid-sensor-als.c                 |    8 +-
+ drivers/iio/light/lm3533-als.c                     |    6 +-
+ drivers/iio/light/tsl2563.c                        |   10 +-
+ drivers/iio/light/vcnl4000.c                       |    6 +-
+ drivers/iio/magnetometer/Kconfig                   |   11 +
+ drivers/iio/magnetometer/Makefile                  |    1 +
+ drivers/{staging => }/iio/magnetometer/ak8975.c    |   73 +-
+ drivers/iio/magnetometer/hid-sensor-magn-3d.c      |   24 +-
+ drivers/staging/Kconfig                            |    6 +-
+ drivers/staging/Makefile                           |    4 +-
+ drivers/staging/android/Kconfig                    |   29 +-
+ drivers/staging/android/Makefile                   |    2 +
+ drivers/staging/android/ashmem.c                   |   66 +-
+ drivers/staging/android/ashmem.h                   |    7 +
+ drivers/staging/android/binder.c                   |  138 +-
+ drivers/staging/android/logger.c                   |  196 +-
+ drivers/staging/android/logger.h                   |   40 +-
+ drivers/staging/android/lowmemorykiller.c          |    9 +-
+ drivers/staging/android/sw_sync.c                  |  264 +
+ drivers/staging/android/sw_sync.h                  |   58 +
+ drivers/staging/android/sync.c                     | 1017 +++
+ drivers/staging/android/sync.h                     |  426 ++
+ drivers/staging/android/trace/sync.h               |   82 +
+ drivers/staging/bcm/Bcmchar.c                      |    2 +-
+ drivers/staging/bcm/InterfaceDld.c                 |   32 +-
+ drivers/staging/bcm/PHSModule.c                    | 1906 +++--
+ drivers/staging/bcm/nvm.c                          |   14 +-
+ drivers/staging/ccg/Kconfig                        |   25 -
+ drivers/staging/ccg/Makefile                       |    2 -
+ drivers/staging/ccg/TODO                           |    6 -
+ drivers/staging/ccg/ccg.c                          | 1292 ----
+ drivers/staging/ccg/composite.c                    | 1688 -----
+ drivers/staging/ccg/composite.h                    |  395 -
+ drivers/staging/ccg/config.c                       |  158 -
+ drivers/staging/ccg/epautoconf.c                   |  393 -
+ drivers/staging/ccg/f_acm.c                        |  814 --
+ drivers/staging/ccg/f_fs.c                         | 2454 ------
+ drivers/staging/ccg/f_mass_storage.c               | 3135 --------
+ drivers/staging/ccg/f_rndis.c                      |  918 ---
+ drivers/staging/ccg/gadget_chips.h                 |  150 -
+ drivers/staging/ccg/ndis.h                         |   47 -
+ drivers/staging/ccg/rndis.c                        | 1175 ---
+ drivers/staging/ccg/rndis.h                        |  222 -
+ drivers/staging/ccg/storage_common.c               |  893 ---
+ drivers/staging/ccg/sysfs-class-ccg_usb            |  158 -
+ drivers/staging/ccg/u_ether.c                      |  986 ---
+ drivers/staging/ccg/u_ether.h                      |  154 -
+ drivers/staging/ccg/u_serial.c                     | 1339 ----
+ drivers/staging/ccg/u_serial.h                     |   65 -
+ drivers/staging/ccg/usbstring.c                    |   71 -
+ drivers/staging/comedi/Kconfig                     |   14 +-
+ drivers/staging/comedi/comedi_fops.c               |   12 +-
+ drivers/staging/comedi/comedi_pci.c                |   36 +-
+ drivers/staging/comedi/comedidev.h                 |   16 +-
+ drivers/staging/comedi/drivers.c                   |    5 +-
+ drivers/staging/comedi/drivers/8255_pci.c          |  172 +-
+ drivers/staging/comedi/drivers/Makefile            |    5 +-
+ .../comedi/drivers/addi-data/APCI1710_Ssi.c        |    4 +-
+ .../staging/comedi/drivers/addi-data/addi_common.c |   31 +-
+ .../staging/comedi/drivers/addi-data/addi_common.h |    2 -
+ drivers/staging/comedi/drivers/addi_apci_035.c     |   19 +-
+ drivers/staging/comedi/drivers/addi_apci_1032.c    |   13 +-
+ drivers/staging/comedi/drivers/addi_apci_1500.c    |   19 +-
+ drivers/staging/comedi/drivers/addi_apci_1516.c    |   63 +-
+ drivers/staging/comedi/drivers/addi_apci_1564.c    |   19 +-
+ drivers/staging/comedi/drivers/addi_apci_16xx.c    |   69 +-
+ drivers/staging/comedi/drivers/addi_apci_1710.c    |   62 +-
+ drivers/staging/comedi/drivers/addi_apci_2032.c    |   13 +-
+ drivers/staging/comedi/drivers/addi_apci_2200.c    |   13 +-
+ drivers/staging/comedi/drivers/addi_apci_3120.c    |   52 +-
+ drivers/staging/comedi/drivers/addi_apci_3200.c    |   49 +-
+ drivers/staging/comedi/drivers/addi_apci_3501.c    |   13 +-
+ drivers/staging/comedi/drivers/addi_apci_3xxx.c    |  225 +-
+ drivers/staging/comedi/drivers/adl_pci6208.c       |   63 +-
+ drivers/staging/comedi/drivers/adl_pci7x3x.c       |   95 +-
+ drivers/staging/comedi/drivers/adl_pci8164.c       |  344 +-
+ drivers/staging/comedi/drivers/adl_pci9111.c       |   14 +-
+ drivers/staging/comedi/drivers/adl_pci9118.c       |   19 +-
+ drivers/staging/comedi/drivers/adv_pci1710.c       |  142 +-
+ drivers/staging/comedi/drivers/adv_pci1723.c       |   18 +-
+ drivers/staging/comedi/drivers/adv_pci1724.c       |  411 +
+ drivers/staging/comedi/drivers/adv_pci_dio.c       |  166 +-
+ drivers/staging/comedi/drivers/amplc_dio200.c      | 1967 +----
+ drivers/staging/comedi/drivers/amplc_dio200.h      |   95 +
+ .../staging/comedi/drivers/amplc_dio200_common.c   | 1320 ++++
+ drivers/staging/comedi/drivers/amplc_dio200_pci.c  |  492 ++
+ drivers/staging/comedi/drivers/amplc_pc236.c       |   19 +-
+ drivers/staging/comedi/drivers/amplc_pc263.c       |   20 +-
+ drivers/staging/comedi/drivers/amplc_pci224.c      |   21 +-
+ drivers/staging/comedi/drivers/amplc_pci230.c      |   22 +-
+ drivers/staging/comedi/drivers/cb_pcidas.c         |   95 +-
+ drivers/staging/comedi/drivers/cb_pcidas64.c       |  928 ++-
+ drivers/staging/comedi/drivers/cb_pcidda.c         |   90 +-
+ drivers/staging/comedi/drivers/cb_pcimdas.c        |   14 +-
+ drivers/staging/comedi/drivers/cb_pcimdda.c        |   14 +-
+ drivers/staging/comedi/drivers/contec_pci_dio.c    |   19 +-
+ drivers/staging/comedi/drivers/daqboard2000.c      |   17 +-
+ drivers/staging/comedi/drivers/das08.h             |    1 -
+ drivers/staging/comedi/drivers/das08_cs.c          |    1 -
+ drivers/staging/comedi/drivers/das08_pci.c         |   13 +-
+ drivers/staging/comedi/drivers/das16.c             |    2 +-
+ drivers/staging/comedi/drivers/das16m1.c           |    2 +-
+ drivers/staging/comedi/drivers/das1800.c           |    2 +-
+ drivers/staging/comedi/drivers/dt3000.c            |   97 +-
+ drivers/staging/comedi/drivers/dyna_pci10xx.c      |   13 +-
+ drivers/staging/comedi/drivers/gsc_hpdi.c          |   16 +-
+ drivers/staging/comedi/drivers/icp_multi.c         |   14 +-
+ drivers/staging/comedi/drivers/jr3_pci.c           |   13 +-
+ drivers/staging/comedi/drivers/ke_counter.c        |   19 +-
+ drivers/staging/comedi/drivers/me4000.c            |  148 +-
+ drivers/staging/comedi/drivers/me_daq.c            |   62 +-
+ drivers/staging/comedi/drivers/mite.c              |    9 +-
+ drivers/staging/comedi/drivers/ni_6527.c           |   82 +-
+ drivers/staging/comedi/drivers/ni_65xx.c           |  383 +-
+ drivers/staging/comedi/drivers/ni_660x.c           |  144 +-
+ drivers/staging/comedi/drivers/ni_670x.c           |   62 +-
+ drivers/staging/comedi/drivers/ni_at_a2150.c       |    2 +-
+ drivers/staging/comedi/drivers/ni_atmio.c          |   12 +-
+ drivers/staging/comedi/drivers/ni_labpc.c          | 2635 +++----
+ drivers/staging/comedi/drivers/ni_labpc.h          |   24 +-
+ drivers/staging/comedi/drivers/ni_labpc_cs.c       |    3 +-
+ drivers/staging/comedi/drivers/ni_mio_common.c     |  345 +-
+ drivers/staging/comedi/drivers/ni_pcidio.c         |   68 +-
+ drivers/staging/comedi/drivers/ni_pcimio.c         | 2055 +++--
+ drivers/staging/comedi/drivers/ni_stc.h            |    4 -
+ drivers/staging/comedi/drivers/pcl816.c            |    2 +-
+ drivers/staging/comedi/drivers/rtd520.c            |  716 +-
+ drivers/staging/comedi/drivers/rtd520.h            |  381 -
+ drivers/staging/comedi/drivers/s626.c              | 1208 ++-
+ drivers/staging/comedi/drivers/s626.h              |  101 +-
+ drivers/staging/comedi/drivers/skel.c              |  117 +-
+ drivers/staging/comedi/drivers/usbdux.c            |  406 +-
+ drivers/staging/comedi/drivers/usbduxsigma.c       |    2 +-
+ drivers/staging/csr/csr_time.c                     |    8 +-
+ drivers/staging/csr/csr_wifi_fsm.h                 |    6 +-
+ drivers/staging/csr/csr_wifi_hip_card_sdio.c       |    8 +-
+ drivers/staging/csr/csr_wifi_hip_card_sdio_intr.c  |   10 +-
+ drivers/staging/csr/csr_wifi_hip_chiphelper.h      |    4 +-
+ drivers/staging/csr/csr_wifi_hip_unifi.h           |   20 +-
+ drivers/staging/csr/drv.c                          |    4 +-
+ drivers/staging/csr/netdev.c                       |    2 +-
+ drivers/staging/csr/sdio_mmc.c                     |    3 +-
+ drivers/staging/csr/sme_native.c                   |    2 +-
+ drivers/staging/csr/sme_wext.c                     |    3 -
+ drivers/staging/csr/unifi_pdu_processing.c         |   20 +-
+ drivers/staging/dgrp/dgrp_net_ops.c                |    2 +-
+ drivers/staging/dwc2/Kconfig                       |   42 +
+ drivers/staging/dwc2/Makefile                      |   23 +
+ drivers/staging/dwc2/core.c                        | 2678 +++++++
+ drivers/staging/dwc2/core.h                        |  658 ++
+ drivers/staging/dwc2/core_intr.c                   |  505 ++
+ drivers/staging/dwc2/hcd.c                         | 2962 ++++++++
+ drivers/staging/dwc2/hcd.h                         |  737 ++
+ drivers/staging/dwc2/hcd_ddma.c                    | 1196 +++
+ drivers/staging/dwc2/hcd_intr.c                    | 2104 +++++
+ drivers/staging/dwc2/hcd_queue.c                   |  675 ++
+ drivers/staging/dwc2/hw.h                          |  811 ++
+ drivers/staging/dwc2/pci.c                         |  187 +
+ drivers/staging/et131x/et131x.c                    |    4 +-
+ drivers/staging/gdm72xx/gdm_qos.c                  |   47 +-
+ drivers/staging/gdm72xx/netlink_k.c                |    1 +
+ drivers/staging/gdm72xx/sdio_boot.c                |    1 +
+ drivers/staging/iio/Documentation/trigger.txt      |    3 -
+ drivers/staging/iio/Kconfig                        |    8 -
+ drivers/staging/iio/Makefile                       |    2 -
+ drivers/staging/iio/accel/adis16201_core.c         |    8 +-
+ drivers/staging/iio/accel/adis16203_core.c         |    2 +-
+ drivers/staging/iio/accel/adis16204_core.c         |    8 +-
+ drivers/staging/iio/accel/adis16209_core.c         |    4 +-
+ drivers/staging/iio/accel/adis16220_core.c         |   26 +-
+ drivers/staging/iio/accel/adis16240_core.c         |    9 +-
+ drivers/staging/iio/accel/lis3l02dq_core.c         |   11 +-
+ drivers/staging/iio/accel/lis3l02dq_ring.c         |    6 +-
+ drivers/staging/iio/accel/sca3000_core.c           |    5 +-
+ drivers/staging/iio/adc/Kconfig                    |    7 -
+ drivers/staging/iio/adc/Makefile                   |    1 -
+ drivers/staging/iio/adc/ad7280a.c                  |   12 +-
+ drivers/staging/iio/adc/ad7291.c                   |   10 +-
+ drivers/staging/iio/adc/ad7606_core.c              |    4 +-
+ drivers/staging/iio/adc/ad799x.h                   |    7 +-
+ drivers/staging/iio/adc/ad799x_core.c              |  417 +-
+ drivers/staging/iio/adc/ad799x_ring.c              |   16 +-
+ drivers/staging/iio/adc/adt7410.c                  | 1102 ---
+ drivers/staging/iio/adc/lpc32xx_adc.c              |    2 +-
+ drivers/staging/iio/adc/mxs-lradc.c                |   12 +-
+ drivers/staging/iio/adc/spear_adc.c                |    4 +-
+ drivers/staging/iio/cdc/ad7150.c                   |    8 +-
+ drivers/staging/iio/cdc/ad7152.c                   |   32 +-
+ drivers/staging/iio/cdc/ad7746.c                   |   48 +-
+ drivers/staging/iio/gyro/adis16060_core.c          |   11 +-
+ drivers/staging/iio/gyro/adis16130_core.c          |    4 +-
+ drivers/staging/iio/gyro/adis16260_core.c          |    4 +-
+ drivers/staging/iio/iio_simple_dummy.c             |   33 +-
+ drivers/staging/iio/impedance-analyzer/ad5933.c    |   10 +-
+ drivers/staging/iio/light/isl29018.c               |    8 +-
+ drivers/staging/iio/light/isl29028.c               |   10 +-
+ drivers/staging/iio/light/tsl2x7x_core.c           |   40 +-
+ drivers/staging/iio/magnetometer/Kconfig           |   11 -
+ drivers/staging/iio/magnetometer/Makefile          |    1 -
+ drivers/staging/iio/magnetometer/hmc5843.c         |    4 +-
+ drivers/staging/iio/meter/ade7758_core.c           |   60 +-
+ drivers/staging/iio/meter/ade7758_trigger.c        |    6 +-
+ drivers/staging/iio/resolver/ad2s1200.c            |    4 +-
+ drivers/staging/iio/resolver/ad2s1210.c            |    4 +-
+ drivers/staging/iio/resolver/ad2s90.c              |    2 +-
+ drivers/staging/iio/trigger/iio-trig-bfin-timer.c  |    8 +-
+ drivers/staging/iio/trigger/iio-trig-gpio.c        |    6 +-
+ .../staging/iio/trigger/iio-trig-periodic-rtc.c    |   12 +-
+ drivers/staging/iio/trigger/iio-trig-sysfs.c       |    4 +-
+ drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h        |    3 +-
+ drivers/staging/imx-drm/ipu-v3/ipu-common.c        |    3 +-
+ drivers/staging/imx-drm/ipu-v3/ipu-dp.c            |    1 -
+ drivers/staging/imx-drm/parallel-display.c         |   10 +
+ drivers/staging/line6/pod.c                        |    3 +-
+ drivers/staging/netlogic/Kconfig                   |    7 +
+ drivers/staging/netlogic/Makefile                  |    1 +
+ drivers/staging/netlogic/TODO                      |   12 +
+ drivers/staging/netlogic/platform_net.c            |  223 +
+ drivers/staging/netlogic/platform_net.h            |   46 +
+ drivers/staging/netlogic/xlr_net.c                 | 1114 +++
+ drivers/staging/netlogic/xlr_net.h                 | 1099 +++
+ drivers/staging/nvec/nvec.c                        |    8 +-
+ drivers/staging/olpc_dcon/olpc_dcon.c              |    4 +-
+ drivers/staging/omap-thermal/Makefile              |    5 -
+ drivers/staging/omap-thermal/omap-bandgap.c        | 1174 ---
+ drivers/staging/omap-thermal/omap-bandgap.h        |  432 --
+ drivers/staging/omap-thermal/omap-thermal-common.c |  338 -
+ drivers/staging/omap-thermal/omap5-thermal.c       |  297 -
+ drivers/staging/rtl8192u/r8192U_dm.h               |   77 +-
+ drivers/staging/rtl8712/rtl8712_led.c              |    8 +-
+ drivers/staging/rtl8712/rtl871x_recv.h             |  108 -
+ drivers/staging/rts5139/rts51x_scsi.c              |    2 +-
+ drivers/staging/rts5139/rts51x_scsi.h              |    1 -
+ drivers/staging/sb105x/sb_mp_register.h            |    4 +-
+ drivers/staging/sb105x/sb_pci_mp.c                 |    4 +-
+ drivers/staging/sb105x/sb_pci_mp.h                 |    2 +-
+ drivers/staging/sep/sep_crypto.c                   |    4 +-
+ drivers/staging/sep/sep_driver_config.h            |    2 +-
+ drivers/staging/sep/sep_main.c                     |    9 +-
+ drivers/staging/sep/sep_trace_events.h             |   11 +-
+ drivers/staging/silicom/bp_mod.c                   |   10 +-
+ drivers/staging/silicom/bypasslib/bypass.c         |   94 +-
+ drivers/staging/slicoss/slicoss.c                  |  132 +-
+ drivers/staging/sm7xxfb/sm7xxfb.c                  |   10 +-
+ drivers/staging/speakup/kobjects.c                 |    8 +-
+ drivers/staging/speakup/main.c                     |    2 +-
+ drivers/staging/speakup/speakup.h                  |    6 -
+ drivers/staging/speakup/varhandlers.c              |   56 +-
+ drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c      |    2 +-
+ .../{omap-thermal => ti-soc-thermal}/Kconfig       |   22 +-
+ drivers/staging/ti-soc-thermal/Makefile            |    5 +
+ .../staging/{omap-thermal => ti-soc-thermal}/TODO  |    8 +-
+ .../omap4-thermal-data.c}                          |   78 +-
+ drivers/staging/ti-soc-thermal/omap4xxx-bandgap.h  |  175 +
+ .../staging/ti-soc-thermal/omap5-thermal-data.c    |  360 +
+ drivers/staging/ti-soc-thermal/omap5xxx-bandgap.h  |  200 +
+ drivers/staging/ti-soc-thermal/ti-bandgap.c        | 1529 ++++
+ drivers/staging/ti-soc-thermal/ti-bandgap.h        |  403 +
+ drivers/staging/ti-soc-thermal/ti-thermal-common.c |  363 +
+ .../omap-thermal.h => ti-soc-thermal/ti-thermal.h} |   41 +-
+ .../ti_soc_thermal.txt}                            |   36 +-
+ drivers/staging/tidspbridge/rmgr/proc.c            |   12 +-
+ drivers/staging/tidspbridge/rmgr/strm.c            |    6 +-
+ drivers/staging/usbip/stub_dev.c                   |    6 +-
+ drivers/staging/usbip/userspace/libsrc/names.c     |  532 +-
+ drivers/staging/usbip/userspace/libsrc/names.h     |    3 +-
+ .../staging/usbip/userspace/libsrc/usbip_common.c  |   28 +-
+ .../staging/usbip/userspace/libsrc/usbip_common.h  |   11 +-
+ .../staging/usbip/userspace/libsrc/vhci_driver.c   |   40 +-
+ drivers/staging/usbip/userspace/src/usbip_detach.c |    2 +-
+ .../staging/usbip/userspace/src/usbip_network.c    |    2 +-
+ .../staging/usbip/userspace/src/usbip_network.h    |    4 +-
+ drivers/staging/usbip/userspace/src/usbipd.c       |    4 +-
+ drivers/staging/usbip/vhci_hcd.c                   |    5 +-
+ drivers/staging/vme/devices/vme_user.c             |    4 +
+ drivers/staging/vt6655/80211hdr.h                  |   71 +-
+ drivers/staging/vt6655/80211mgr.c                  | 1166 ++-
+ drivers/staging/vt6655/80211mgr.h                  |  698 +-
+ drivers/staging/vt6655/IEEE11h.c                   |  115 +-
+ drivers/staging/vt6655/IEEE11h.h                   |    6 +-
+ drivers/staging/vt6655/aes_ccmp.c                  |  563 +-
+ drivers/staging/vt6655/baseband.c                  | 4855 ++++++------
+ drivers/staging/vt6655/baseband.h                  |   56 +-
+ drivers/staging/vt6655/bssdb.c                     | 2665 ++++---
+ drivers/staging/vt6655/bssdb.h                     |  411 +-
+ drivers/staging/vt6655/card.c                      | 2842 ++++---
+ drivers/staging/vt6655/card.h                      |  137 +-
+ drivers/staging/vt6655/channel.c                   |  767 +-
+ drivers/staging/vt6655/channel.h                   |   16 +-
+ drivers/staging/vt6655/country.h                   |  238 +-
+ drivers/staging/vt6655/datarate.c                  |  469 +-
+ drivers/staging/vt6655/datarate.h                  |   49 +-
+ drivers/staging/vt6655/desc.h                      |  504 +-
+ drivers/staging/vt6655/device.h                    |  999 ++-
+ drivers/staging/vt6655/device_cfg.h                |   31 +-
+ drivers/staging/vt6655/device_main.c               | 4931 ++++++------
+ drivers/staging/vt6655/dpc.c                       | 2425 +++---
+ drivers/staging/vt6655/dpc.h                       |   11 +-
+ drivers/staging/vt6655/hostap.c                    |  690 +-
+ drivers/staging/vt6655/hostap.h                    |    4 -
+ drivers/staging/vt6655/iocmd.h                     |  246 +-
+ drivers/staging/vt6655/ioctl.c                     |   16 +-
+ drivers/staging/vt6655/ioctl.h                     |   16 +-
+ drivers/staging/vt6655/iowpa.h                     |   54 +-
+ drivers/staging/vt6655/iwctl.c                     | 2213 +++---
+ drivers/staging/vt6655/iwctl.h                     |  208 +-
+ drivers/staging/vt6655/key.c                       | 1150 ++-
+ drivers/staging/vt6655/key.h                       |  171 +-
+ drivers/staging/vt6655/mac.c                       | 1657 ++--
+ drivers/staging/vt6655/mac.h                       |  773 +-
+ drivers/staging/vt6655/mib.c                       |  698 +-
+ drivers/staging/vt6655/mib.h                       |  507 +-
+ drivers/staging/vt6655/michael.c                   |  164 +-
+ drivers/staging/vt6655/michael.h                   |    8 +-
+ drivers/staging/vt6655/power.c                     |  484 +-
+ drivers/staging/vt6655/power.h                     |   33 +-
+ drivers/staging/vt6655/rc4.c                       |   78 +-
+ drivers/staging/vt6655/rc4.h                       |    6 +-
+ drivers/staging/vt6655/rf.c                        | 1480 ++--
+ drivers/staging/vt6655/rf.h                        |   26 +-
+ drivers/staging/vt6655/rxtx.c                      | 5545 +++++++-------
+ drivers/staging/vt6655/rxtx.h                      |   56 +-
+ drivers/staging/vt6655/srom.c                      |  269 +-
+ drivers/staging/vt6655/srom.h                      |   60 +-
+ drivers/staging/vt6655/tcrc.c                      |  163 +-
+ drivers/staging/vt6655/tcrc.h                      |    3 -
+ drivers/staging/vt6655/tether.c                    |   50 +-
+ drivers/staging/vt6655/tether.h                    |   42 +-
+ drivers/staging/vt6655/tkip.c                      |  331 +-
+ drivers/staging/vt6655/tkip.h                      |   15 +-
+ drivers/staging/vt6655/tmacro.h                    |    2 -
+ drivers/staging/vt6655/ttype.h                     |   14 +-
+ drivers/staging/vt6655/upc.h                       |  187 +-
+ drivers/staging/vt6655/vntwifi.c                   |  925 ++-
+ drivers/staging/vt6655/vntwifi.h                   |  278 +-
+ drivers/staging/vt6655/wcmd.c                      | 1747 ++---
+ drivers/staging/vt6655/wcmd.h                      |  118 +-
+ drivers/staging/vt6655/wctl.c                      |  244 +-
+ drivers/staging/vt6655/wctl.h                      |   76 +-
+ drivers/staging/vt6655/wmgr.c                      | 8006 ++++++++++----------
+ drivers/staging/vt6655/wmgr.h                      |  552 +-
+ drivers/staging/vt6655/wpa.c                       |  340 +-
+ drivers/staging/vt6655/wpa.h                       |   23 +-
+ drivers/staging/vt6655/wpa2.c                      |  504 +-
+ drivers/staging/vt6655/wpa2.h                      |   29 +-
+ drivers/staging/vt6655/wpactl.c                    |  903 ++-
+ drivers/staging/vt6655/wpactl.h                    |    8 +-
+ drivers/staging/vt6655/wroute.c                    |  257 +-
+ drivers/staging/vt6655/wroute.h                    |    5 +-
+ drivers/staging/vt6656/80211hdr.h                  |  130 +-
+ drivers/staging/vt6656/80211mgr.c                  |  224 +-
+ drivers/staging/vt6656/80211mgr.h                  |  335 +-
+ drivers/staging/vt6656/TODO                        |    2 +-
+ drivers/staging/vt6656/aes_ccmp.c                  |  131 +-
+ drivers/staging/vt6656/aes_ccmp.h                  |   13 +-
+ drivers/staging/vt6656/baseband.c                  |  183 +-
+ drivers/staging/vt6656/baseband.h                  |   23 +-
+ drivers/staging/vt6656/bssdb.c                     |   70 +-
+ drivers/staging/vt6656/bssdb.h                     |  124 +-
+ drivers/staging/vt6656/card.c                      |  127 +-
+ drivers/staging/vt6656/card.h                      |   18 +-
+ drivers/staging/vt6656/channel.c                   |   53 +-
+ drivers/staging/vt6656/channel.h                   |   14 +-
+ drivers/staging/vt6656/control.c                   |   10 -
+ drivers/staging/vt6656/control.h                   |   10 -
+ drivers/staging/vt6656/country.h                   |    1 -
+ drivers/staging/vt6656/datarate.c                  |   85 +-
+ drivers/staging/vt6656/datarate.h                  |   27 +-
+ drivers/staging/vt6656/desc.h                      |  230 +-
+ drivers/staging/vt6656/device.h                    |   56 +-
+ drivers/staging/vt6656/device_cfg.h                |    2 -
+ drivers/staging/vt6656/dpc.c                       |  262 +-
+ drivers/staging/vt6656/dpc.h                       |    9 -
+ drivers/staging/vt6656/firmware.c                  |   17 +-
+ drivers/staging/vt6656/firmware.h                  |    9 -
+ drivers/staging/vt6656/hostap.c                    |   29 +-
+ drivers/staging/vt6656/hostap.h                    |    9 -
+ drivers/staging/vt6656/int.c                       |   27 +-
+ drivers/staging/vt6656/int.h                       |   46 +-
+ drivers/staging/vt6656/iocmd.h                     |   18 -
+ drivers/staging/vt6656/iowpa.h                     |   13 -
+ drivers/staging/vt6656/iwctl.c                     |   27 +-
+ drivers/staging/vt6656/iwctl.h                     |    8 -
+ drivers/staging/vt6656/key.c                       |  111 +-
+ drivers/staging/vt6656/key.h                       |   43 +-
+ drivers/staging/vt6656/mac.c                       |  132 +-
+ drivers/staging/vt6656/mac.h                       |   19 -
+ drivers/staging/vt6656/main_usb.c                  |   63 +-
+ drivers/staging/vt6656/mib.c                       |  131 +-
+ drivers/staging/vt6656/mib.h                       |  294 +-
+ drivers/staging/vt6656/michael.c                   |   49 +-
+ drivers/staging/vt6656/michael.h                   |   12 +-
+ drivers/staging/vt6656/power.c                     |   13 +-
+ drivers/staging/vt6656/power.h                     |   12 -
+ drivers/staging/vt6656/rc4.c                       |   22 +-
+ drivers/staging/vt6656/rc4.h                       |   10 +-
+ drivers/staging/vt6656/rf.c                        |   49 +-
+ drivers/staging/vt6656/rf.h                        |   10 -
+ drivers/staging/vt6656/rndis.h                     |   90 +-
+ drivers/staging/vt6656/rxtx.c                      |  610 +-
+ drivers/staging/vt6656/rxtx.h                      |  691 +-
+ drivers/staging/vt6656/srom.h                      |   71 +-
+ drivers/staging/vt6656/tcrc.c                      |   28 +-
+ drivers/staging/vt6656/tcrc.h                      |   20 +-
+ drivers/staging/vt6656/tether.c                    |   53 +-
+ drivers/staging/vt6656/tether.h                    |   61 +-
+ drivers/staging/vt6656/tkip.c                      |   37 +-
+ drivers/staging/vt6656/tkip.h                      |   22 +-
+ drivers/staging/vt6656/tmacro.h                    |   14 +-
+ drivers/staging/vt6656/ttype.h                     |   55 -
+ drivers/staging/vt6656/usbpipe.c                   |   29 -
+ drivers/staging/vt6656/usbpipe.h                   |    9 -
+ drivers/staging/vt6656/wcmd.c                      |   63 +-
+ drivers/staging/vt6656/wcmd.h                      |   18 +-
+ drivers/staging/vt6656/wctl.c                      |   56 +-
+ drivers/staging/vt6656/wctl.h                      |   49 +-
+ drivers/staging/vt6656/wmgr.c                      |  228 +-
+ drivers/staging/vt6656/wmgr.h                      |   35 -
+ drivers/staging/vt6656/wpa.c                       |   32 +-
+ drivers/staging/vt6656/wpa.h                       |   16 +-
+ drivers/staging/vt6656/wpa2.c                      |  165 +-
+ drivers/staging/vt6656/wpa2.h                      |   17 +-
+ drivers/staging/vt6656/wpactl.c                    |   33 +-
+ drivers/staging/vt6656/wpactl.h                    |   10 -
+ drivers/staging/wlan-ng/prism2sta.c                |   51 +-
+ drivers/staging/wlan-ng/prism2usb.c                |   12 +-
+ drivers/staging/xgifb/vb_def.h                     |    4 -
+ drivers/staging/xgifb/vb_init.c                    |   64 +-
+ drivers/staging/xgifb/vb_setmode.c                 |    4 +-
+ drivers/staging/xgifb/vb_struct.h                  |   16 +-
+ drivers/staging/xgifb/vb_table.h                   |   98 +-
+ drivers/staging/zcache/Kconfig                     |    8 +
+ drivers/staging/zcache/Makefile                    |    1 +
+ drivers/staging/zcache/TODO                        |    9 +-
+ drivers/staging/zcache/debug.c                     |  107 +
+ drivers/staging/zcache/debug.h                     |  248 +
+ drivers/staging/zcache/ramster/ramster.c           |    5 +
+ drivers/staging/zcache/zbud.c                      |    7 +-
+ drivers/staging/zcache/zcache-main.c               |  518 +-
+ drivers/staging/zram/zram_drv.c                    |    5 +-
+ drivers/staging/zsmalloc/Kconfig                   |    2 +-
+ drivers/staging/zsmalloc/zsmalloc-main.c           |    5 +-
+ include/linux/iio/adc/ad_sigma_delta.h             |    6 +-
+ include/linux/iio/common/st_sensors.h              |    5 +-
+ include/linux/iio/iio.h                            |   79 +-
+ include/linux/iio/imu/adis.h                       |   34 +-
+ include/linux/iio/trigger.h                        |   26 +-
+ 509 files changed, 61004 insertions(+), 64824 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/arm/samsung/exynos-adc.txt
+ create mode 100644 Documentation/devicetree/bindings/iio/iio-bindings.txt
+ rename drivers/{staging/iio => hwmon}/iio_hwmon.c (96%)
+ create mode 100644 drivers/iio/adc/ad7923.c
+ create mode 100644 drivers/iio/adc/exynos_adc.c
+ rename drivers/{staging => }/iio/magnetometer/ak8975.c (89%)
+ create mode 100644 drivers/staging/android/sw_sync.c
+ create mode 100644 drivers/staging/android/sw_sync.h
+ create mode 100644 drivers/staging/android/sync.c
+ create mode 100644 drivers/staging/android/sync.h
+ create mode 100644 drivers/staging/android/trace/sync.h
+ delete mode 100644 drivers/staging/ccg/Kconfig
+ delete mode 100644 drivers/staging/ccg/Makefile
+ delete mode 100644 drivers/staging/ccg/TODO
+ delete mode 100644 drivers/staging/ccg/ccg.c
+ delete mode 100644 drivers/staging/ccg/composite.c
+ delete mode 100644 drivers/staging/ccg/composite.h
+ delete mode 100644 drivers/staging/ccg/config.c
+ delete mode 100644 drivers/staging/ccg/epautoconf.c
+ delete mode 100644 drivers/staging/ccg/f_acm.c
+ delete mode 100644 drivers/staging/ccg/f_fs.c
+ delete mode 100644 drivers/staging/ccg/f_mass_storage.c
+ delete mode 100644 drivers/staging/ccg/f_rndis.c
+ delete mode 100644 drivers/staging/ccg/gadget_chips.h
+ delete mode 100644 drivers/staging/ccg/ndis.h
+ delete mode 100644 drivers/staging/ccg/rndis.c
+ delete mode 100644 drivers/staging/ccg/rndis.h
+ delete mode 100644 drivers/staging/ccg/storage_common.c
+ delete mode 100644 drivers/staging/ccg/sysfs-class-ccg_usb
+ delete mode 100644 drivers/staging/ccg/u_ether.c
+ delete mode 100644 drivers/staging/ccg/u_ether.h
+ delete mode 100644 drivers/staging/ccg/u_serial.c
+ delete mode 100644 drivers/staging/ccg/u_serial.h
+ delete mode 100644 drivers/staging/ccg/usbstring.c
+ create mode 100644 drivers/staging/comedi/drivers/adv_pci1724.c
+ create mode 100644 drivers/staging/comedi/drivers/amplc_dio200.h
+ create mode 100644 drivers/staging/comedi/drivers/amplc_dio200_common.c
+ create mode 100644 drivers/staging/comedi/drivers/amplc_dio200_pci.c
+ delete mode 100644 drivers/staging/comedi/drivers/rtd520.h
+ create mode 100644 drivers/staging/dwc2/Kconfig
+ create mode 100644 drivers/staging/dwc2/Makefile
+ create mode 100644 drivers/staging/dwc2/core.c
+ create mode 100644 drivers/staging/dwc2/core.h
+ create mode 100644 drivers/staging/dwc2/core_intr.c
+ create mode 100644 drivers/staging/dwc2/hcd.c
+ create mode 100644 drivers/staging/dwc2/hcd.h
+ create mode 100644 drivers/staging/dwc2/hcd_ddma.c
+ create mode 100644 drivers/staging/dwc2/hcd_intr.c
+ create mode 100644 drivers/staging/dwc2/hcd_queue.c
+ create mode 100644 drivers/staging/dwc2/hw.h
+ create mode 100644 drivers/staging/dwc2/pci.c
+ delete mode 100644 drivers/staging/iio/adc/adt7410.c
+ create mode 100644 drivers/staging/netlogic/Kconfig
+ create mode 100644 drivers/staging/netlogic/Makefile
+ create mode 100644 drivers/staging/netlogic/TODO
+ create mode 100644 drivers/staging/netlogic/platform_net.c
+ create mode 100644 drivers/staging/netlogic/platform_net.h
+ create mode 100644 drivers/staging/netlogic/xlr_net.c
+ create mode 100644 drivers/staging/netlogic/xlr_net.h
+ delete mode 100644 drivers/staging/omap-thermal/Makefile
+ delete mode 100644 drivers/staging/omap-thermal/omap-bandgap.c
+ delete mode 100644 drivers/staging/omap-thermal/omap-bandgap.h
+ delete mode 100644 drivers/staging/omap-thermal/omap-thermal-common.c
+ delete mode 100644 drivers/staging/omap-thermal/omap5-thermal.c
+ rename drivers/staging/{omap-thermal => ti-soc-thermal}/Kconfig (70%)
+ create mode 100644 drivers/staging/ti-soc-thermal/Makefile
+ rename drivers/staging/{omap-thermal => ti-soc-thermal}/TODO (72%)
+ rename drivers/staging/{omap-thermal/omap4-thermal.c => ti-soc-thermal/omap4-thermal-data.c} (84%)
+ create mode 100644 drivers/staging/ti-soc-thermal/omap4xxx-bandgap.h
+ create mode 100644 drivers/staging/ti-soc-thermal/omap5-thermal-data.c
+ create mode 100644 drivers/staging/ti-soc-thermal/omap5xxx-bandgap.h
+ create mode 100644 drivers/staging/ti-soc-thermal/ti-bandgap.c
+ create mode 100644 drivers/staging/ti-soc-thermal/ti-bandgap.h
+ create mode 100644 drivers/staging/ti-soc-thermal/ti-thermal-common.c
+ rename drivers/staging/{omap-thermal/omap-thermal.h => ti-soc-thermal/ti-thermal.h} (69%)
+ rename drivers/staging/{omap-thermal/omap_bandgap.txt => ti-soc-thermal/ti_soc_thermal.txt} (50%)
+ delete mode 100644 drivers/staging/vt6656/ttype.h
+ create mode 100644 drivers/staging/zcache/debug.c
+ create mode 100644 drivers/staging/zcache/debug.h
+Merging char-misc/char-misc-next (2638953 Merge tag 'extcon-arizona-v3.10' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/misc into char-misc-next)
+$ git merge char-misc/char-misc-next
+Auto-merging include/linux/mfd/arizona/registers.h
+Auto-merging drivers/scsi/pcmcia/nsp_cs.c
+Auto-merging drivers/net/ethernet/xircom/xirc2ps_cs.c
+Auto-merging drivers/net/ethernet/fujitsu/fmvj18x_cs.c
+Auto-merging drivers/misc/Kconfig
+Auto-merging drivers/mfd/wm5102-tables.c
+Auto-merging drivers/mfd/Kconfig
+Auto-merging drivers/char/hw_random/mxc-rnga.c
+Auto-merging drivers/Makefile
+Auto-merging MAINTAINERS
+Merge made by the 'recursive' strategy.
+ Documentation/ABI/testing/sysfs-bus-mei            |   7 +
+ Documentation/devicetree/bindings/arm/msm/ssbi.txt |  18 +
+ Documentation/misc-devices/mei/mei-client-bus.txt  | 135 +++++
+ MAINTAINERS                                        |   1 +
+ arch/arm/boot/dts/msm8660-surf.dts                 |   6 +
+ arch/arm/boot/dts/msm8960-cdp.dts                  |   6 +
+ drivers/Kconfig                                    |   2 +
+ drivers/Makefile                                   |   1 +
+ drivers/ata/pata_pcmcia.c                          |  14 +-
+ drivers/bluetooth/bluecard_cs.c                    |  15 +-
+ drivers/bluetooth/bt3c_cs.c                        |  15 +-
+ drivers/bluetooth/btuart_cs.c                      |  15 +-
+ drivers/bluetooth/dtl1_cs.c                        |  15 +-
+ drivers/char/applicom.c                            |   4 +-
+ drivers/char/hw_random/mxc-rnga.c                  |  13 +-
+ drivers/char/hw_random/tx4939-rng.c                |  13 +-
+ drivers/char/tile-srom.c                           |   2 +-
+ drivers/extcon/extcon-arizona.c                    | 391 +++++++++++----
+ drivers/hv/Makefile                                |   2 +-
+ drivers/hv/channel_mgmt.c                          |  11 +
+ drivers/hv/hv_balloon.c                            | 544 ++++++++++++++++++---
+ drivers/hv/hv_snapshot.c                           | 287 +++++++++++
+ drivers/hv/hv_util.c                               |  10 +
+ drivers/hv/ring_buffer.c                           |   1 +
+ drivers/ipack/carriers/tpci200.c                   |  14 +-
+ drivers/ipack/ipack.c                              |  36 +-
+ drivers/isdn/hardware/avm/avm_cs.c                 |  14 +-
+ drivers/isdn/hisax/avma1_cs.c                      |  14 +-
+ drivers/isdn/hisax/elsa_cs.c                       |  14 +-
+ drivers/isdn/hisax/sedlbauer_cs.c                  |  14 +-
+ drivers/isdn/hisax/teles_cs.c                      |  14 +-
+ drivers/memory/emif.c                              | 141 +++++-
+ drivers/memory/tegra30-mc.c                        |   2 +
+ drivers/mfd/Kconfig                                |   2 +-
+ drivers/mfd/pm8921-core.c                          |  14 +-
+ drivers/mfd/wm5102-tables.c                        |   8 +
+ drivers/misc/Kconfig                               |   8 +
+ drivers/misc/Makefile                              |   2 +-
+ drivers/misc/apds990x.c                            |   9 +-
+ drivers/misc/arm-charlcd.c                         |  13 +-
+ drivers/misc/atmel_pwm.c                           |  12 +-
+ drivers/misc/bh1770glc.c                           |   7 +-
+ drivers/misc/bh1780gli.c                           |  10 +-
+ drivers/misc/cs5535-mfgpt.c                        |  41 +-
+ drivers/misc/dummy-irq.c                           |  59 +++
+ drivers/misc/ep93xx_pwm.c                          |  13 +-
+ drivers/misc/mei/Kconfig                           |   5 +-
+ drivers/misc/mei/Makefile                          |   7 +-
+ drivers/misc/mei/amthif.c                          |  11 +-
+ drivers/misc/mei/bus.c                             | 496 +++++++++++++++++++
+ drivers/misc/mei/client.c                          |   1 +
+ drivers/misc/mei/hw-me.c                           | 110 +++--
+ drivers/misc/mei/hw-me.h                           |   6 -
+ drivers/misc/mei/init.c                            |  42 +-
+ drivers/misc/mei/interrupt.c                       |  95 ++--
+ drivers/misc/mei/main.c                            |  17 +
+ drivers/misc/mei/mei_dev.h                         | 102 +++-
+ drivers/misc/mei/pci-me.c                          |  41 +-
+ drivers/mmc/host/sdricoh_cs.c                      |  20 +-
+ drivers/net/arcnet/com20020_cs.c                   |  14 +-
+ drivers/net/can/sja1000/ems_pcmcia.c               |  13 +-
+ drivers/net/can/sja1000/peak_pcmcia.c              |  13 +-
+ drivers/net/can/softing/softing_cs.c               |  16 +-
+ drivers/net/ethernet/3com/3c574_cs.c               |  14 +-
+ drivers/net/ethernet/3com/3c589_cs.c               |  14 +-
+ drivers/net/ethernet/8390/axnet_cs.c               |  14 +-
+ drivers/net/ethernet/8390/pcnet_cs.c               |  14 +-
+ drivers/net/ethernet/amd/nmclan_cs.c               |  14 +-
+ drivers/net/ethernet/fujitsu/fmvj18x_cs.c          |  14 +-
+ drivers/net/ethernet/smsc/smc91c92_cs.c            |  14 +-
+ drivers/net/ethernet/xircom/xirc2ps_cs.c           |  16 +-
+ drivers/net/wireless/airo_cs.c                     |  14 +-
+ drivers/net/wireless/atmel_cs.c                    |  14 +-
+ drivers/net/wireless/b43/pcmcia.c                  |   4 +
+ drivers/net/wireless/hostap/hostap_cs.c            |  15 +-
+ drivers/net/wireless/libertas/if_cs.c              |  25 +-
+ drivers/net/wireless/orinoco/orinoco_cs.c          |  16 +-
+ drivers/net/wireless/orinoco/spectrum_cs.c         |  16 +-
+ drivers/net/wireless/wl3501_cs.c                   |  14 +-
+ drivers/parport/parport_amiga.c                    |  15 +-
+ drivers/parport/parport_cs.c                       |  14 +-
+ drivers/parport/parport_gsc.c                      |   4 +-
+ drivers/parport/parport_sunbpp.c                   |   5 +-
+ drivers/parport/procfs.c                           |   6 +-
+ drivers/scsi/pcmcia/aha152x_stub.c                 |  14 +-
+ drivers/scsi/pcmcia/fdomain_stub.c                 |  14 +-
+ drivers/scsi/pcmcia/nsp_cs.c                       |  17 +-
+ drivers/scsi/pcmcia/qlogic_stub.c                  |  13 +-
+ drivers/scsi/pcmcia/sym53c500_cs.c                 |  16 +-
+ drivers/ssbi/Kconfig                               |  16 +
+ drivers/ssbi/Makefile                              |   1 +
+ drivers/ssbi/ssbi.c                                | 379 ++++++++++++++
+ drivers/tty/serial/8250/serial_cs.c                |  14 +-
+ drivers/uio/uio.c                                  |   1 +
+ drivers/usb/host/sl811_cs.c                        |  15 +-
+ drivers/w1/masters/mxc_w1.c                        |   6 +-
+ drivers/w1/slaves/Kconfig                          |  10 +
+ drivers/w1/slaves/w1_ds2408.c                      |  25 +-
+ include/linux/hyperv.h                             |  69 +++
+ include/linux/ipack.h                              |  42 +-
+ include/linux/mei_cl_bus.h                         |  41 ++
+ include/linux/mfd/arizona/pdata.h                  |  21 +
+ include/linux/mfd/arizona/registers.h              |   4 +
+ include/linux/mod_devicetable.h                    |   9 +
+ include/linux/platform_data/emif_plat.h            |   1 +
+ include/linux/ssbi.h                               |  38 ++
+ include/pcmcia/ds.h                                |  12 +
+ include/uapi/linux/connector.h                     |   5 +-
+ mm/page_alloc.c                                    |   1 +
+ scripts/mod/devicetable-offsets.c                  |   3 +
+ scripts/mod/file2alias.c                           |  12 +
+ sound/pcmcia/pdaudiocf/pdaudiocf.c                 |  15 +-
+ sound/pcmcia/vx/vxpocket.c                         |  14 +-
+ tools/hv/hv_kvp_daemon.c                           |  16 +-
+ tools/hv/hv_vss_daemon.c                           | 220 +++++++++
+ 115 files changed, 3303 insertions(+), 1035 deletions(-)
+ create mode 100644 Documentation/ABI/testing/sysfs-bus-mei
+ create mode 100644 Documentation/devicetree/bindings/arm/msm/ssbi.txt
+ create mode 100644 Documentation/misc-devices/mei/mei-client-bus.txt
+ create mode 100644 drivers/hv/hv_snapshot.c
+ create mode 100644 drivers/misc/dummy-irq.c
+ create mode 100644 drivers/misc/mei/bus.c
+ create mode 100644 drivers/ssbi/Kconfig
+ create mode 100644 drivers/ssbi/Makefile
+ create mode 100644 drivers/ssbi/ssbi.c
+ create mode 100644 include/linux/mei_cl_bus.h
+ create mode 100644 include/linux/ssbi.h
+ create mode 100644 tools/hv/hv_vss_daemon.c
+Merging bcon/master (06c6942 blockconsole: Mark a local work struct static)
+$ git merge bcon/master
+Resolved 'drivers/block/Kconfig' using previous resolution.
+Auto-merging kernel/printk.c
+Auto-merging init/do_mounts.c
+Auto-merging include/linux/mount.h
+Auto-merging include/linux/console.h
+Auto-merging drivers/net/netconsole.c
+Auto-merging drivers/block/Makefile
+Auto-merging drivers/block/Kconfig
+CONFLICT (content): Merge conflict in drivers/block/Kconfig
+Auto-merging block/partitions/check.h
+Auto-merging block/partitions/check.c
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master ad18b62] Merge remote-tracking branch 'bcon/master'
+$ git diff -M --stat --summary HEAD^..
+ Documentation/block/blockconsole.txt            |  94 ++++
+ Documentation/block/blockconsole/bcon_tail      |  82 ++++
+ Documentation/block/blockconsole/mkblockconsole |  29 ++
+ block/partitions/Makefile                       |   1 +
+ block/partitions/blockconsole.c                 |  22 +
+ block/partitions/check.c                        |   3 +
+ block/partitions/check.h                        |   3 +
+ drivers/block/Kconfig                           |   6 +
+ drivers/block/Makefile                          |   1 +
+ drivers/block/blockconsole.c                    | 618 ++++++++++++++++++++++++
+ drivers/net/netconsole.c                        |   2 +-
+ include/linux/blockconsole.h                    |   7 +
+ include/linux/console.h                         |   1 +
+ include/linux/mount.h                           |   2 +-
+ init/do_mounts.c                                |   2 +-
+ kernel/printk.c                                 |   5 +-
+ 16 files changed, 873 insertions(+), 5 deletions(-)
+ create mode 100644 Documentation/block/blockconsole.txt
+ create mode 100755 Documentation/block/blockconsole/bcon_tail
+ create mode 100755 Documentation/block/blockconsole/mkblockconsole
+ create mode 100644 block/partitions/blockconsole.c
+ create mode 100644 drivers/block/blockconsole.c
+ create mode 100644 include/linux/blockconsole.h
+Merging tmem/linux-next (8f0d816 Linux 3.7-rc3)
+$ git merge tmem/linux-next
+Already up-to-date.
+Merging writeback/writeback-for-next (ed84825 Negative (setpoint-dirty) in bdi_position_ratio())
+$ git merge writeback/writeback-for-next
+Already up-to-date.
+Merging arm-dt/devicetree/arm-next (ede338f dt: add documentation of ARM dt boot interface)
+$ git merge arm-dt/devicetree/arm-next
+Already up-to-date.
+Merging hwspinlock/linux-next (8b37fcf hwspinlock: add MAINTAINERS entries)
+$ git merge hwspinlock/linux-next
+Already up-to-date.
+Merging pinctrl/for-next (bdbe59f Merge branch 'devel' into for-next)
+$ git merge pinctrl/for-next
+Removing drivers/pinctrl/pinctrl-pxa910.c
+Removing drivers/pinctrl/pinctrl-pxa3xx.h
+Removing drivers/pinctrl/pinctrl-pxa3xx.c
+Removing drivers/pinctrl/pinctrl-pxa168.c
+Removing drivers/pinctrl/pinctrl-mmp2.c
+Merge made by the 'recursive' strategy.
+ Documentation/devicetree/bindings/gpio/gpio.txt    |    6 +-
+ .../devicetree/bindings/pinctrl/pinctrl-single.txt |  107 ++-
+ Documentation/pinctrl.txt                          |  112 +++
+ arch/arm/boot/dts/spear1310.dtsi                   |    4 +-
+ arch/arm/boot/dts/spear1340.dtsi                   |    4 +-
+ arch/arm/boot/dts/spear310.dtsi                    |    4 +-
+ arch/arm/boot/dts/spear320.dtsi                    |    4 +-
+ drivers/gpio/gpio-pl061.c                          |  125 ++-
+ drivers/gpio/gpiolib-of.c                          |   15 +-
+ drivers/pinctrl/Kconfig                            |   20 +-
+ drivers/pinctrl/Makefile                           |    4 -
+ drivers/pinctrl/core.c                             |  114 ++-
+ drivers/pinctrl/core.h                             |    2 +-
+ drivers/pinctrl/devicetree.c                       |    4 +-
+ drivers/pinctrl/mvebu/pinctrl-mvebu.c              |   39 +-
+ drivers/pinctrl/pinconf-generic.c                  |   20 +-
+ drivers/pinctrl/pinconf.c                          |  207 ----
+ drivers/pinctrl/pinconf.h                          |    8 +
+ drivers/pinctrl/pinctrl-ab8505.c                   |    2 +-
+ drivers/pinctrl/pinctrl-ab9540.c                   |    2 +-
+ drivers/pinctrl/pinctrl-abx500.c                   |    7 +-
+ drivers/pinctrl/pinctrl-at91.c                     |   27 +-
+ drivers/pinctrl/pinctrl-bcm2835.c                  |    6 +-
+ drivers/pinctrl/pinctrl-coh901.c                   |    9 +-
+ drivers/pinctrl/pinctrl-exynos5440.c               |    8 +-
+ drivers/pinctrl/pinctrl-falcon.c                   |    2 +-
+ drivers/pinctrl/pinctrl-imx.c                      |    6 +-
+ drivers/pinctrl/pinctrl-lantiq.c                   |    4 +-
+ drivers/pinctrl/pinctrl-mmp2.c                     |  722 --------------
+ drivers/pinctrl/pinctrl-mxs.c                      |    6 +-
+ drivers/pinctrl/pinctrl-nomadik-db8500.c           |    4 +-
+ drivers/pinctrl/pinctrl-nomadik-stn8815.c          |    2 +-
+ drivers/pinctrl/pinctrl-nomadik.c                  |   16 +-
+ drivers/pinctrl/pinctrl-pxa168.c                   |  651 -------------
+ drivers/pinctrl/pinctrl-pxa3xx.c                   |  227 -----
+ drivers/pinctrl/pinctrl-pxa3xx.h                   |  262 -----
+ drivers/pinctrl/pinctrl-pxa910.c                   | 1007 --------------------
+ drivers/pinctrl/pinctrl-samsung.c                  |    6 +-
+ drivers/pinctrl/pinctrl-single.c                   |  515 +++++++++-
+ drivers/pinctrl/pinctrl-sirf.c                     |   14 +-
+ drivers/pinctrl/pinctrl-sunxi.c                    |  986 ++++++++++++++-----
+ drivers/pinctrl/pinctrl-tegra.c                    |    6 +-
+ drivers/pinctrl/pinctrl-u300.c                     |    6 +-
+ drivers/pinctrl/pinctrl-xway.c                     |    2 +-
+ drivers/pinctrl/spear/pinctrl-plgpio.c             |    6 +-
+ drivers/pinctrl/spear/pinctrl-spear.c              |    4 +-
+ include/linux/pinctrl/pinctrl.h                    |    6 +-
+ 47 files changed, 1790 insertions(+), 3530 deletions(-)
+ delete mode 100644 drivers/pinctrl/pinctrl-mmp2.c
+ delete mode 100644 drivers/pinctrl/pinctrl-pxa168.c
+ delete mode 100644 drivers/pinctrl/pinctrl-pxa3xx.c
+ delete mode 100644 drivers/pinctrl/pinctrl-pxa3xx.h
+ delete mode 100644 drivers/pinctrl/pinctrl-pxa910.c
+Merging vhost/linux-next (4697e2c kvm: add PV MMIO EVENTFD)
+$ git merge vhost/linux-next
+Recorded preimage for 'include/linux/kvm_host.h'
+Recorded preimage for 'include/uapi/linux/kvm.h'
+Auto-merging virt/kvm/kvm_main.c
+Auto-merging virt/kvm/eventfd.c
+Auto-merging include/uapi/linux/kvm.h
+CONFLICT (content): Merge conflict in include/uapi/linux/kvm.h
+Auto-merging include/linux/kvm_host.h
+CONFLICT (content): Merge conflict in include/linux/kvm_host.h
+Auto-merging arch/x86/kvm/x86.c
+Auto-merging arch/x86/kvm/vmx.c
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+Recorded resolution for 'include/linux/kvm_host.h'.
+Recorded resolution for 'include/uapi/linux/kvm.h'.
+[master ff1abf8] Merge remote-tracking branch 'vhost/linux-next'
+$ git diff -M --stat --summary HEAD^..
+ arch/x86/kvm/vmx.c             |  4 ++++
+ arch/x86/kvm/x86.c             |  1 +
+ drivers/infiniband/core/umem.c | 21 ++++++++++-------
+ include/linux/kvm_host.h       |  1 +
+ include/rdma/ib_verbs.h        |  9 ++++++-
+ include/uapi/linux/kvm.h       |  9 +++++++
+ virt/kvm/eventfd.c             | 53 +++++++++++++++++++++++++++++++++++++-----
+ virt/kvm/kvm_main.c            |  1 +
+ 8 files changed, 83 insertions(+), 16 deletions(-)
+Merging memblock/memblock-kill-early_node_map (7bd0b0f memblock: Reimplement memblock allocation using reverse free area iterator)
+$ git merge memblock/memblock-kill-early_node_map
+Already up-to-date.
+Merging remoteproc/for-next (6f0c058 Linux 3.7-rc2)
+$ git merge remoteproc/for-next
+Already up-to-date.
+Merging irqdomain/irqdomain/next (560aa53 irqdomain: document the simple domain first_irq)
+$ git merge irqdomain/irqdomain/next
+Merge made by the 'recursive' strategy.
+ kernel/irq/irqdomain.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+Merging gpio/gpio/next (753c598 gpio/em: Add Device Tree support)
+$ git merge gpio/gpio/next
+Merge made by the 'recursive' strategy.
+ drivers/gpio/gpio-em.c    | 45 ++++++++++++++++++++++++++--
+ drivers/gpio/gpio-omap.c  | 75 +++++++++++++++++++++--------------------------
+ drivers/gpio/gpio-tegra.c | 11 ++++---
+ 3 files changed, 81 insertions(+), 50 deletions(-)
+Merging gpio-lw/for-next (290722b Merge branch 'next' into for-next)
+$ git merge gpio-lw/for-next
+Auto-merging drivers/gpio/gpiolib-of.c
+Merge made by the 'recursive' strategy.
+ drivers/gpio/Kconfig           |   2 +-
+ drivers/gpio/gpio-74x164.c     |   8 +--
+ drivers/gpio/gpio-adp5520.c    |   4 +-
+ drivers/gpio/gpio-em.c         |  53 +++++++-------------
+ drivers/gpio/gpio-ich.c        |  17 ++-----
+ drivers/gpio/gpio-lynxpoint.c  |   1 +
+ drivers/gpio/gpio-max7300.c    |   4 +-
+ drivers/gpio/gpio-max7301.c    |   7 ++-
+ drivers/gpio/gpio-max732x.c    |   5 +-
+ drivers/gpio/gpio-mc33880.c    |  19 ++++---
+ drivers/gpio/gpio-mvebu.c      |  85 ++++++++++++++++++++++++++-----
+ drivers/gpio/gpio-omap.c       |   2 +-
+ drivers/gpio/gpio-pca953x.c    |   3 +-
+ drivers/gpio/gpio-pcf857x.c    |   8 ++-
+ drivers/gpio/gpio-pxa.c        |   4 +-
+ drivers/gpio/gpio-samsung.c    |   1 +
+ drivers/gpio/gpio-sch.c        | 111 +++++++++++++++++++++++------------------
+ drivers/gpio/gpio-stp-xway.c   |   2 +-
+ drivers/gpio/gpio-tc3589x.c    |   8 +--
+ drivers/gpio/gpio-timberdale.c |   3 +-
+ drivers/gpio/gpio-tps65910.c   |   2 +-
+ drivers/gpio/gpio-viperboard.c |   4 --
+ drivers/gpio/gpio-vt8500.c     |   8 ++-
+ drivers/gpio/gpiolib-of.c      |   2 +-
+ 24 files changed, 198 insertions(+), 165 deletions(-)
+Merging gen-gpio/for_next (a2523d3 blackfin: force use of gpiolib)
+$ git merge gen-gpio/for_next
+Resolved 'arch/sh/kernel/cpu/sh2a/Makefile' using previous resolution.
+Auto-merging arch/sh/kernel/cpu/sh2a/Makefile
+CONFLICT (content): Merge conflict in arch/sh/kernel/cpu/sh2a/Makefile
+Auto-merging arch/powerpc/platforms/Kconfig
+Auto-merging arch/powerpc/platforms/85xx/Kconfig
+Auto-merging arch/openrisc/Kconfig
+Auto-merging arch/mips/Kconfig
+Auto-merging arch/blackfin/Kconfig
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master 37a4383] Merge remote-tracking branch 'gen-gpio/for_next'
+$ git diff -M --stat --summary HEAD^..
+ arch/arm/plat-orion/Makefile         | 2 +-
+ arch/avr32/Kconfig                   | 2 +-
+ arch/blackfin/Kconfig                | 4 ++--
+ arch/m68k/Kconfig.cpu                | 3 +--
+ arch/mips/Kconfig                    | 7 +------
+ arch/mips/loongson/common/Makefile   | 2 +-
+ arch/mips/txx9/generic/setup.c       | 2 +-
+ arch/openrisc/Kconfig                | 2 +-
+ arch/powerpc/platforms/40x/Kconfig   | 1 -
+ arch/powerpc/platforms/44x/Kconfig   | 1 -
+ arch/powerpc/platforms/85xx/Kconfig  | 1 -
+ arch/powerpc/platforms/86xx/Kconfig  | 3 ---
+ arch/powerpc/platforms/8xx/Kconfig   | 1 -
+ arch/powerpc/platforms/Kconfig       | 4 ----
+ arch/sh/boards/mach-sdk7786/Makefile | 2 +-
+ arch/sh/boards/mach-x3proto/Makefile | 2 +-
+ arch/sh/kernel/cpu/sh2a/Makefile     | 2 +-
+ arch/sh/kernel/cpu/sh3/Makefile      | 2 +-
+ arch/sh/kernel/cpu/sh4a/Makefile     | 2 +-
+ arch/unicore32/Kconfig               | 3 +--
+ arch/xtensa/configs/iss_defconfig    | 1 -
+ arch/xtensa/configs/s6105_defconfig  | 1 -
+ 22 files changed, 15 insertions(+), 35 deletions(-)
+Merging mailbox/dbx500-prcmu-mailbox (c497eba mailbox: fix invalid use of sizeof in mailbox_msg_send())
+$ git merge mailbox/dbx500-prcmu-mailbox
+Auto-merging drivers/mailbox/mailbox-omap2.c
+Auto-merging drivers/mailbox/mailbox-omap1.c
+Removing arch/arm/plat-omap/mailbox.c
+Removing arch/arm/plat-omap/include/plat/mailbox.h
+Auto-merging arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+Auto-merging arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+Merge made by the 'recursive' strategy.
+ .../devicetree/bindings/mailbox/dbx500-mailbox.txt |  27 +
+ arch/arm/configs/omap1_defconfig                   |   3 +-
+ arch/arm/mach-omap1/Makefile                       |   4 -
+ arch/arm/mach-omap2/Makefile                       |   3 -
+ arch/arm/mach-omap2/devices.c                      |  13 +-
+ arch/arm/mach-omap2/omap_hwmod_2420_data.c         |  12 +
+ arch/arm/mach-omap2/omap_hwmod_2430_data.c         |  11 +
+ arch/arm/mach-omap2/omap_hwmod_3xxx_data.c         |  11 +
+ arch/arm/mach-omap2/omap_hwmod_44xx_data.c         |  13 +
+ arch/arm/plat-omap/Kconfig                         |  16 -
+ arch/arm/plat-omap/Makefile                        |   3 -
+ arch/arm/plat-omap/include/plat/mailbox.h          | 105 ----
+ arch/arm/plat-omap/mailbox.c                       | 435 --------------
+ drivers/cpufreq/highbank-cpufreq.c                 |   2 +-
+ drivers/mailbox/Kconfig                            |  41 ++
+ drivers/mailbox/Makefile                           |   5 +
+ drivers/mailbox/mailbox-dbx500.c                   | 648 +++++++++++++++++++++
+ .../mailbox.c => drivers/mailbox/mailbox-omap1.c   |  90 ++-
+ .../mailbox.c => drivers/mailbox/mailbox-omap2.c   | 330 +++++------
+ drivers/mailbox/mailbox.c                          | 552 ++++++++++++++++++
+ drivers/mailbox/mailbox_internal.h                 |  70 +++
+ drivers/mailbox/pl320-ipc.c                        |   2 +-
+ drivers/remoteproc/Kconfig                         |   3 +-
+ drivers/remoteproc/omap_remoteproc.c               |  36 +-
+ drivers/staging/tidspbridge/Kconfig                |   3 +-
+ drivers/staging/tidspbridge/core/_tiomap.h         |   2 +-
+ drivers/staging/tidspbridge/core/chnl_sm.c         |   8 +-
+ drivers/staging/tidspbridge/core/io_sm.c           |   5 +-
+ drivers/staging/tidspbridge/core/tiomap3430.c      |   6 +-
+ drivers/staging/tidspbridge/core/tiomap3430_pwr.c  |   6 +-
+ drivers/staging/tidspbridge/core/tiomap_io.c       |   9 +-
+ .../tidspbridge/include/dspbridge/host_os.h        |   2 +-
+ include/linux/mailbox.h                            |  52 +-
+ include/linux/pl320-ipc.h                          |  17 +
+ include/linux/platform_data/mailbox-dbx500.h       |  12 +
+ include/linux/platform_data/mailbox-omap.h         |  53 ++
+ 36 files changed, 1766 insertions(+), 844 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/mailbox/dbx500-mailbox.txt
+ delete mode 100644 arch/arm/plat-omap/include/plat/mailbox.h
+ delete mode 100644 arch/arm/plat-omap/mailbox.c
+ create mode 100644 drivers/mailbox/mailbox-dbx500.c
+ rename arch/arm/mach-omap1/mailbox.c => drivers/mailbox/mailbox-omap1.c (64%)
+ rename arch/arm/mach-omap2/mailbox.c => drivers/mailbox/mailbox-omap2.c (50%)
+ create mode 100644 drivers/mailbox/mailbox.c
+ create mode 100644 drivers/mailbox/mailbox_internal.h
+ create mode 100644 include/linux/pl320-ipc.h
+ create mode 100644 include/linux/platform_data/mailbox-dbx500.h
+ create mode 100644 include/linux/platform_data/mailbox-omap.h
+Merging arm-soc/for-next (0be783d Merge branch 'next/boards2' into for-next)
+$ git merge arm-soc/for-next
+Auto-merging drivers/video/atmel_lcdfb.c
+Auto-merging drivers/staging/imx-drm/ipu-v3/ipu-common.c
+Auto-merging drivers/pinctrl/spear/pinctrl-plgpio.c
+Auto-merging drivers/pinctrl/pinctrl-sirf.c
+Auto-merging drivers/pinctrl/pinctrl-nomadik.c
+Auto-merging drivers/pinctrl/pinctrl-at91.c
+Auto-merging drivers/net/ethernet/smsc/smsc911x.c
+Auto-merging drivers/mmc/host/sdhci-cns3xxx.c
+Auto-merging drivers/gpio/gpio-tegra.c
+Auto-merging drivers/gpio/gpio-samsung.c
+Auto-merging drivers/gpio/gpio-pxa.c
+Auto-merging drivers/gpio/gpio-pl061.c
+Auto-merging drivers/gpio/gpio-omap.c
+Auto-merging drivers/gpio/Kconfig
+Auto-merging drivers/clocksource/timer-prima2.c
+Auto-merging drivers/clocksource/timer-marco.c
+Auto-merging drivers/clocksource/Makefile
+Removing arch/arm/plat-spear/Makefile
+Removing arch/arm/plat-spear/Kconfig
+Removing arch/arm/plat-samsung/time.c
+Auto-merging arch/arm/plat-samsung/samsung-time.c
+Removing arch/arm/plat-samsung/include/plat/s5p-time.h
+Removing arch/arm/plat-samsung/include/plat/s3c244x.h
+Removing arch/arm/plat-samsung/include/plat/s3c2443.h
+Removing arch/arm/plat-samsung/include/plat/s3c2416.h
+Removing arch/arm/plat-samsung/include/plat/s3c2412.h
+Removing arch/arm/plat-samsung/include/plat/s3c2410.h
+Removing arch/arm/plat-samsung/include/plat/irq.h
+Auto-merging arch/arm/plat-orion/Makefile
+Auto-merging arch/arm/mach-ux500/board-mop500.c
+Auto-merging arch/arm/mach-ux500/board-mop500-regulators.h
+Auto-merging arch/arm/mach-ux500/board-mop500-regulators.c
+Removing arch/arm/mach-spear6xx/include/mach/uncompress.h
+Removing arch/arm/mach-spear6xx/include/mach/timex.h
+Removing arch/arm/mach-spear6xx/include/mach/spear.h
+Removing arch/arm/mach-spear6xx/include/mach/misc_regs.h
+Removing arch/arm/mach-spear6xx/include/mach/hardware.h
+Removing arch/arm/mach-spear6xx/include/mach/generic.h
+Removing arch/arm/mach-spear6xx/include/mach/debug-macro.S
+Removing arch/arm/mach-spear6xx/Makefile.boot
+Removing arch/arm/mach-spear6xx/Makefile
+Removing arch/arm/mach-spear6xx/Kconfig
+Removing arch/arm/mach-spear3xx/include/mach/uncompress.h
+Removing arch/arm/mach-spear3xx/include/mach/timex.h
+Removing arch/arm/mach-spear3xx/include/mach/spear.h
+Removing arch/arm/mach-spear3xx/include/mach/irqs.h
+Removing arch/arm/mach-spear3xx/include/mach/hardware.h
+Removing arch/arm/mach-spear3xx/include/mach/generic.h
+Removing arch/arm/mach-spear3xx/include/mach/debug-macro.S
+Removing arch/arm/mach-spear3xx/Makefile.boot
+Removing arch/arm/mach-spear3xx/Makefile
+Removing arch/arm/mach-spear3xx/Kconfig
+Removing arch/arm/mach-spear13xx/include/mach/uncompress.h
+Removing arch/arm/mach-spear13xx/include/mach/timex.h
+Removing arch/arm/mach-spear13xx/include/mach/spear.h
+Removing arch/arm/mach-spear13xx/include/mach/irqs.h
+Removing arch/arm/mach-spear13xx/include/mach/hardware.h
+Removing arch/arm/mach-spear13xx/include/mach/debug-macro.S
+Removing arch/arm/mach-spear13xx/Makefile
+Removing arch/arm/mach-spear13xx/Kconfig
+Auto-merging arch/arm/mach-spear/time.c
+Auto-merging arch/arm/mach-spear/spear6xx.c
+Auto-merging arch/arm/mach-spear/spear3xx.c
+Auto-merging arch/arm/mach-spear/spear320.c
+Auto-merging arch/arm/mach-spear/spear310.c
+Auto-merging arch/arm/mach-spear/spear300.c
+Auto-merging arch/arm/mach-spear/spear13xx.c
+CONFLICT (content): Merge conflict in arch/arm/mach-spear/spear13xx.c
+Auto-merging arch/arm/mach-spear/spear1340.c
+Auto-merging arch/arm/mach-spear/spear1310.c
+Auto-merging arch/arm/mach-spear/restart.c
+Auto-merging arch/arm/mach-spear/platsmp.c
+Auto-merging arch/arm/mach-spear/include/mach/misc_regs.h
+Auto-merging arch/arm/mach-spear/include/mach/irqs.h
+Auto-merging arch/arm/mach-spear/generic.h
+Removing arch/arm/mach-shmobile/hotplug.c
+Auto-merging arch/arm/mach-shmobile/headsmp-scu.S
+Auto-merging arch/arm/mach-shmobile/board-mackerel.c
+Auto-merging arch/arm/mach-shmobile/board-kzm9g.c
+Auto-merging arch/arm/mach-shmobile/board-armadillo800eva.c
+Auto-merging arch/arm/mach-s3c24xx/mach-rx1950.c
+Removing arch/arm/mach-s3c24xx/irq-s3c244x.c
+Removing arch/arm/mach-s3c24xx/irq-s3c2440.c
+Removing arch/arm/mach-s3c24xx/irq-s3c2412.c
+Removing arch/arm/mach-s3c24xx/include/mach/regs-sdi.h
+Recorded preimage for 'arch/arm/mach-spear/spear13xx.c'
+Auto-merging arch/arm/mach-s3c24xx/common-smdk.h
+Removing arch/arm/mach-prima2/irq.c
+Removing arch/arm/mach-prima2/include/mach/uncompress.h
+Removing arch/arm/mach-prima2/include/mach/timex.h
+Removing arch/arm/mach-prima2/include/mach/map.h
+Removing arch/arm/mach-prima2/include/mach/irqs.h
+Removing arch/arm/mach-prima2/include/mach/hardware.h
+Removing arch/arm/mach-prima2/include/mach/entry-macro.S
+Removing arch/arm/mach-prima2/include/mach/debug-macro.S
+Removing arch/arm/mach-prima2/include/mach/clkdev.h
+Auto-merging arch/arm/mach-omap2/omap-smp.c
+Removing arch/arm/mach-nomadik/include/mach/uncompress.h
+Removing arch/arm/mach-nomadik/include/mach/timex.h
+Removing arch/arm/mach-nomadik/include/mach/irqs.h
+Removing arch/arm/mach-nomadik/Makefile.boot
+Removing arch/arm/mach-l7200/include/mach/debug-macro.S
+Removing arch/arm/mach-h720x/include/mach/uncompress.h
+Removing arch/arm/mach-h720x/include/mach/timex.h
+Removing arch/arm/mach-h720x/include/mach/isa-dma.h
+Removing arch/arm/mach-h720x/include/mach/irqs.h
+Removing arch/arm/mach-h720x/include/mach/hardware.h
+Removing arch/arm/mach-h720x/include/mach/h7202-regs.h
+Removing arch/arm/mach-h720x/include/mach/h7201-regs.h
+Removing arch/arm/mach-h720x/include/mach/entry-macro.S
+Removing arch/arm/mach-h720x/include/mach/debug-macro.S
+Removing arch/arm/mach-h720x/include/mach/boards.h
+Removing arch/arm/mach-h720x/h7202-eval.c
+Removing arch/arm/mach-h720x/h7201-eval.c
+Removing arch/arm/mach-h720x/cpu-h7202.c
+Removing arch/arm/mach-h720x/cpu-h7201.c
+Removing arch/arm/mach-h720x/common.h
+Removing arch/arm/mach-h720x/common.c
+Removing arch/arm/mach-h720x/Makefile.boot
+Removing arch/arm/mach-h720x/Makefile
+Removing arch/arm/mach-h720x/Kconfig
+Auto-merging arch/arm/mach-gemini/reset.c
+Removing arch/arm/mach-cns3xxx/include/mach/uncompress.h
+Removing arch/arm/mach-cns3xxx/include/mach/timex.h
+Removing arch/arm/mach-cns3xxx/include/mach/irqs.h
+Auto-merging arch/arm/mach-cns3xxx/core.c
+Auto-merging arch/arm/mach-cns3xxx/cns3xxx.h
+Auto-merging arch/arm/mach-at91/at91sam9g45_devices.c
+Auto-merging arch/arm/include/debug/sirf.S
+Auto-merging arch/arm/configs/lpc32xx_defconfig
+Auto-merging arch/arm/configs/kirkwood_defconfig
+Removing arch/arm/configs/h7202_defconfig
+Removing arch/arm/configs/h7201_defconfig
+Auto-merging arch/arm/configs/at91sam9g45_defconfig
+Removing arch/arm/boot/dts/sh73a0-reference.dtsi
+Auto-merging arch/arm/boot/dts/armada-370-mirabox.dts
+Auto-merging arch/arm/Kconfig.debug
+Auto-merging arch/arm/Kconfig
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+Recorded resolution for 'arch/arm/mach-spear/spear13xx.c'.
+[master 881ed78] Merge remote-tracking branch 'arm-soc/for-next'
+$ git diff -M --stat --summary HEAD^..
+ .../devicetree/bindings/arm/bcm/bcm,kona-timer.txt |   19 +
+ arch/arm/Kconfig                                   |   83 +-
+ arch/arm/Kconfig.debug                             |   17 +
+ arch/arm/Makefile                                  |    6 +-
+ arch/arm/arm-soc-for-next-contents.txt             |  112 +
+ arch/arm/boot/dts/Makefile                         |   11 +
+ arch/arm/boot/dts/armada-370-mirabox.dts           |   11 +
+ arch/arm/boot/dts/at91rm9200.dtsi                  |   28 +
+ arch/arm/boot/dts/at91sam9263ek.dts                |    2 -
+ arch/arm/boot/dts/at91sam9g20ek_common.dtsi        |    2 -
+ arch/arm/boot/dts/at91sam9m10g45ek.dts             |    2 -
+ arch/arm/boot/dts/at91sam9n12ek.dts                |    2 -
+ arch/arm/boot/dts/at91sam9x5.dtsi                  |   60 +
+ arch/arm/boot/dts/at91sam9x5cm.dtsi                |   20 +
+ arch/arm/boot/dts/at91sam9x5ek.dtsi                |    8 -
+ arch/arm/boot/dts/atlas6-evb.dts                   |   78 +
+ arch/arm/boot/dts/atlas6.dtsi                      |  668 +++++
+ arch/arm/boot/dts/bcm11351.dtsi                    |    8 +
+ arch/arm/boot/dts/dbx5x0.dtsi                      |    7 +-
+ arch/arm/boot/dts/dove.dtsi                        |    5 +
+ arch/arm/boot/dts/href.dtsi                        |    1 +
+ arch/arm/boot/dts/hrefprev60.dts                   |   10 +-
+ arch/arm/boot/dts/kirkwood-6282.dtsi               |    6 +
+ arch/arm/boot/dts/mpa1600.dts                      |   69 +
+ arch/arm/boot/dts/r8a73a4-ape6evm.dts              |   52 +
+ arch/arm/boot/dts/r8a73a4.dtsi                     |   94 +
+ arch/arm/boot/dts/r8a7778-bockw.dts                |   32 +
+ arch/arm/boot/dts/r8a7778.dtsi                     |   35 +
+ arch/arm/boot/dts/r8a7779-marzen-reference.dts     |   47 +
+ arch/arm/boot/dts/r8a7779.dtsi                     |   98 +
+ arch/arm/boot/dts/r8a7790-lager.dts                |   31 +
+ arch/arm/boot/dts/r8a7790.dtsi                     |   63 +
+ arch/arm/boot/dts/sama5d3.dtsi                     | 1031 ++++++++
+ arch/arm/boot/dts/sama5d31ek.dts                   |   51 +
+ arch/arm/boot/dts/sama5d33ek.dts                   |   44 +
+ arch/arm/boot/dts/sama5d34ek.dts                   |   61 +
+ arch/arm/boot/dts/sama5d35ek.dts                   |   56 +
+ arch/arm/boot/dts/sama5d3xcm.dtsi                  |   91 +
+ arch/arm/boot/dts/sama5d3xdm.dtsi                  |   42 +
+ arch/arm/boot/dts/sama5d3xmb.dtsi                  |  166 ++
+ arch/arm/boot/dts/sh73a0-kzm9g-reference.dts       |   79 +
+ arch/arm/boot/dts/sh73a0-reference.dtsi            |   24 -
+ arch/arm/boot/dts/sh73a0.dtsi                      |  125 +
+ arch/arm/boot/dts/snowball.dts                     |    4 +
+ arch/arm/boot/dts/stuib.dtsi                       |    2 +-
+ arch/arm/boot/dts/sun4i-a10-cubieboard.dts         |   26 +
+ arch/arm/boot/dts/sun4i-a10-mini-xplus.dts         |   32 +
+ arch/arm/boot/dts/sun4i-a10.dtsi                   |    4 +-
+ arch/arm/boot/dts/sun5i-a13-olinuxino.dts          |   20 +
+ arch/arm/boot/dts/sun5i-a13.dtsi                   |    4 +-
+ arch/arm/boot/dts/sunxi.dtsi                       |   83 +-
+ arch/arm/configs/ape6evm_defconfig                 |   95 +
+ arch/arm/configs/armadillo800eva_defconfig         |    8 +-
+ arch/arm/configs/at91_dt_defconfig                 |    2 +-
+ arch/arm/configs/at91sam9260_defconfig             |    2 +-
+ arch/arm/configs/at91sam9g20_defconfig             |    2 +-
+ arch/arm/configs/at91sam9g45_defconfig             |    2 +-
+ arch/arm/configs/bockw_defconfig                   |   66 +
+ arch/arm/configs/cns3420vb_defconfig               |    3 +
+ arch/arm/configs/dove_defconfig                    |    2 +
+ arch/arm/configs/h7201_defconfig                   |   27 -
+ arch/arm/configs/h7202_defconfig                   |   47 -
+ arch/arm/configs/kirkwood_defconfig                |    2 +
+ arch/arm/configs/kzm9g_defconfig                   |    2 -
+ arch/arm/configs/lpc32xx_defconfig                 |   20 +-
+ arch/arm/configs/mackerel_defconfig                |    4 +
+ arch/arm/configs/marzen_defconfig                  |    8 +
+ arch/arm/configs/multi_v7_defconfig                |   23 +
+ arch/arm/configs/nhk8815_defconfig                 |   42 +-
+ arch/arm/configs/sama5_defconfig                   |  181 ++
+ arch/arm/configs/spear3xx_defconfig                |    2 +
+ arch/arm/configs/spear6xx_defconfig                |    1 +
+ arch/arm/configs/u8500_defconfig                   |    4 +-
+ arch/arm/include/asm/irq.h                         |    5 +
+ arch/arm/include/asm/mach/irq.h                    |   36 -
+ .../mach/debug-macro.S => include/debug/cns3xxx.S} |    0
+ .../mach/debug-macro.S => include/debug/nomadik.S} |    0
+ .../include/mach/uart.h => include/debug/sirf.S}   |   29 +-
+ arch/arm/kernel/irq.c                              |    6 +-
+ arch/arm/mach-at91/Kconfig                         |  453 +---
+ arch/arm/mach-at91/Kconfig.non_dt                  |  399 +++
+ arch/arm/mach-at91/Makefile                        |   11 +-
+ arch/arm/mach-at91/at91rm9200.c                    |    3 +-
+ arch/arm/mach-at91/at91sam9260.c                   |    2 +-
+ arch/arm/mach-at91/at91sam9261.c                   |    4 +-
+ arch/arm/mach-at91/at91sam9261_devices.c           |    6 +-
+ arch/arm/mach-at91/at91sam9263.c                   |    3 +-
+ arch/arm/mach-at91/at91sam9263_devices.c           |    2 +-
+ arch/arm/mach-at91/at91sam9g45.c                   |    4 +-
+ arch/arm/mach-at91/at91sam9g45_devices.c           |    6 +-
+ arch/arm/mach-at91/at91sam9n12.c                   |    2 +-
+ arch/arm/mach-at91/at91sam9rl.c                    |    3 +-
+ arch/arm/mach-at91/at91sam9rl_devices.c            |    2 +-
+ arch/arm/mach-at91/at91sam9x5.c                    |    2 +-
+ .../{board-rm9200-dt.c => board-dt-rm9200.c}       |    0
+ arch/arm/mach-at91/{board-dt.c => board-dt-sam9.c} |    0
+ arch/arm/mach-at91/board-dt-sama5.c                |   86 +
+ arch/arm/mach-at91/clock.c                         |  109 +-
+ arch/arm/mach-at91/clock.h                         |    2 +
+ arch/arm/mach-at91/gpio.c                          |    3 +-
+ arch/arm/mach-at91/include/mach/at91_pmc.h         |   18 +-
+ arch/arm/mach-at91/include/mach/cpu.h              |   20 +
+ arch/arm/mach-at91/include/mach/sama5d3.h          |   73 +
+ arch/arm/mach-at91/sama5d3.c                       |  377 +++
+ arch/arm/mach-at91/setup.c                         |   29 +-
+ arch/arm/mach-at91/soc.h                           |    7 +-
+ arch/arm/mach-cns3xxx/Kconfig                      |   12 +
+ arch/arm/mach-cns3xxx/Makefile                     |    8 +-
+ arch/arm/mach-cns3xxx/cns3420vb.c                  |    6 +-
+ arch/arm/mach-cns3xxx/{include/mach => }/cns3xxx.h |    7 +-
+ arch/arm/mach-cns3xxx/core.c                       |  121 +-
+ arch/arm/mach-cns3xxx/devices.c                    |    5 +-
+ arch/arm/mach-cns3xxx/include/mach/irqs.h          |   24 -
+ arch/arm/mach-cns3xxx/include/mach/timex.h         |   12 -
+ arch/arm/mach-cns3xxx/include/mach/uncompress.h    |   53 -
+ arch/arm/mach-cns3xxx/pcie.c                       |    2 +-
+ arch/arm/mach-cns3xxx/pm.c                         |    4 +-
+ arch/arm/mach-cns3xxx/{include/mach => }/pm.h      |    0
+ arch/arm/mach-exynos/Kconfig                       |    2 +-
+ arch/arm/mach-exynos/common.c                      |    2 +
+ arch/arm/mach-exynos/mach-universal_c210.c         |    6 +-
+ arch/arm/mach-exynos/platsmp.c                     |    8 -
+ arch/arm/mach-gemini/Makefile                      |    2 +-
+ arch/arm/mach-gemini/board-nas4220b.c              |    1 +
+ arch/arm/mach-gemini/board-rut1xx.c                |    2 +
+ arch/arm/mach-gemini/board-wbd111.c                |    1 +
+ arch/arm/mach-gemini/board-wbd222.c                |    1 +
+ arch/arm/mach-gemini/common.h                      |    2 +
+ arch/arm/mach-gemini/gpio.c                        |   19 +-
+ arch/arm/mach-gemini/include/mach/hardware.h       |    2 +-
+ arch/arm/mach-gemini/irq.c                         |    4 +-
+ arch/arm/mach-gemini/mm.c                          |   22 +-
+ .../mach-gemini/{include/mach/system.h => reset.c} |    2 +-
+ arch/arm/mach-h720x/Kconfig                        |   40 -
+ arch/arm/mach-h720x/Makefile                       |   16 -
+ arch/arm/mach-h720x/Makefile.boot                  |    2 -
+ arch/arm/mach-h720x/common.c                       |  268 --
+ arch/arm/mach-h720x/common.h                       |   30 -
+ arch/arm/mach-h720x/cpu-h7201.c                    |   57 -
+ arch/arm/mach-h720x/cpu-h7202.c                    |  225 --
+ arch/arm/mach-h720x/h7201-eval.c                   |   38 -
+ arch/arm/mach-h720x/h7202-eval.c                   |   81 -
+ arch/arm/mach-h720x/include/mach/boards.h          |   53 -
+ arch/arm/mach-h720x/include/mach/debug-macro.S     |   40 -
+ arch/arm/mach-h720x/include/mach/entry-macro.S     |   57 -
+ arch/arm/mach-h720x/include/mach/h7201-regs.h      |   67 -
+ arch/arm/mach-h720x/include/mach/h7202-regs.h      |  155 --
+ arch/arm/mach-h720x/include/mach/hardware.h        |  190 --
+ arch/arm/mach-h720x/include/mach/irqs.h            |  116 -
+ arch/arm/mach-h720x/include/mach/isa-dma.h         |   19 -
+ arch/arm/mach-h720x/include/mach/timex.h           |   15 -
+ arch/arm/mach-h720x/include/mach/uncompress.h      |   36 -
+ arch/arm/mach-highbank/platsmp.c                   |    7 -
+ arch/arm/mach-imx/platsmp.c                        |   12 -
+ arch/arm/mach-l7200/include/mach/debug-macro.S     |   38 -
+ arch/arm/mach-msm/platsmp.c                        |    8 -
+ arch/arm/mach-nomadik/Kconfig                      |   24 +-
+ arch/arm/mach-nomadik/Makefile.boot                |    4 -
+ arch/arm/mach-nomadik/cpu-8815.c                   |    1 -
+ arch/arm/mach-nomadik/include/mach/irqs.h          |   79 -
+ arch/arm/mach-nomadik/include/mach/timex.h         |    6 -
+ arch/arm/mach-nomadik/include/mach/uncompress.h    |   60 -
+ arch/arm/mach-omap2/omap-smp.c                     |    7 -
+ arch/arm/mach-orion5x/pci.c                        |    7 +-
+ arch/arm/mach-prima2/Kconfig                       |   22 +-
+ arch/arm/mach-prima2/Makefile                      |    5 +-
+ arch/arm/mach-prima2/common.c                      |   37 +-
+ arch/arm/mach-prima2/common.h                      |    4 +-
+ arch/arm/mach-prima2/include/mach/clkdev.h         |   15 -
+ arch/arm/mach-prima2/include/mach/debug-macro.S    |   29 -
+ arch/arm/mach-prima2/include/mach/entry-macro.S    |   22 -
+ arch/arm/mach-prima2/include/mach/hardware.h       |   15 -
+ arch/arm/mach-prima2/include/mach/irqs.h           |   17 -
+ arch/arm/mach-prima2/include/mach/map.h            |   18 -
+ arch/arm/mach-prima2/include/mach/timex.h          |   14 -
+ arch/arm/mach-prima2/include/mach/uncompress.h     |   41 -
+ arch/arm/mach-prima2/irq.c                         |  129 -
+ arch/arm/mach-prima2/lluart.c                      |   14 +-
+ arch/arm/mach-prima2/platsmp.c                     |    9 -
+ arch/arm/mach-s3c24xx/Kconfig                      |    7 +
+ arch/arm/mach-s3c24xx/Makefile                     |    6 +-
+ arch/arm/mach-s3c24xx/bast-irq.c                   |    2 -
+ arch/arm/mach-s3c24xx/clock-s3c2410.c              |    1 -
+ arch/arm/mach-s3c24xx/clock-s3c2412.c              |    1 -
+ arch/arm/mach-s3c24xx/clock-s3c2416.c              |    1 -
+ arch/arm/mach-s3c24xx/clock-s3c2443.c              |    1 -
+ arch/arm/mach-s3c24xx/common-smdk.c                |    3 +-
+ .../include/plat => mach-s3c24xx}/common-smdk.h    |    3 +-
+ arch/arm/mach-s3c24xx/common.c                     |    7 +-
+ arch/arm/mach-s3c24xx/common.h                     |   93 +-
+ arch/arm/mach-s3c24xx/dma-s3c2410.c                |    1 -
+ arch/arm/mach-s3c24xx/dma-s3c2412.c                |    1 -
+ arch/arm/mach-s3c24xx/dma-s3c2440.c                |    1 -
+ arch/arm/mach-s3c24xx/dma-s3c2443.c                |    1 -
+ arch/arm/mach-s3c24xx/include/mach/irqs.h          |   58 +-
+ arch/arm/mach-s3c24xx/include/mach/regs-sdi.h      |  127 -
+ arch/arm/mach-s3c24xx/irq-pm.c                     |    7 +-
+ arch/arm/mach-s3c24xx/irq-s3c2412.c                |  215 --
+ arch/arm/mach-s3c24xx/irq-s3c2440.c                |  128 -
+ arch/arm/mach-s3c24xx/irq-s3c244x.c                |  142 --
+ arch/arm/mach-s3c24xx/irq.c                        |  273 +-
+ arch/arm/mach-s3c24xx/mach-amlm5900.c              |    5 +-
+ arch/arm/mach-s3c24xx/mach-anubis.c                |    6 +-
+ arch/arm/mach-s3c24xx/mach-at2440evb.c             |    6 +-
+ arch/arm/mach-s3c24xx/mach-bast.c                  |    4 +-
+ arch/arm/mach-s3c24xx/mach-gta02.c                 |    6 +-
+ arch/arm/mach-s3c24xx/mach-h1940.c                 |    5 +-
+ arch/arm/mach-s3c24xx/mach-jive.c                  |    8 +-
+ arch/arm/mach-s3c24xx/mach-mini2440.c              |    6 +-
+ arch/arm/mach-s3c24xx/mach-n30.c                   |    7 +-
+ arch/arm/mach-s3c24xx/mach-nexcoder.c              |    8 +-
+ arch/arm/mach-s3c24xx/mach-osiris.c                |    6 +-
+ arch/arm/mach-s3c24xx/mach-otom.c                  |    5 +-
+ arch/arm/mach-s3c24xx/mach-qt2410.c                |    6 +-
+ arch/arm/mach-s3c24xx/mach-rx1950.c                |    6 +-
+ arch/arm/mach-s3c24xx/mach-rx3715.c                |   11 +-
+ arch/arm/mach-s3c24xx/mach-smdk2410.c              |    7 +-
+ arch/arm/mach-s3c24xx/mach-smdk2413.c              |   19 +-
+ arch/arm/mach-s3c24xx/mach-smdk2416.c              |    8 +-
+ arch/arm/mach-s3c24xx/mach-smdk2440.c              |   11 +-
+ arch/arm/mach-s3c24xx/mach-smdk2443.c              |    9 +-
+ arch/arm/mach-s3c24xx/mach-tct_hammer.c            |    4 +-
+ arch/arm/mach-s3c24xx/mach-vr1000.c                |    4 +-
+ arch/arm/mach-s3c24xx/mach-vstms.c                 |    9 +-
+ arch/arm/mach-s3c24xx/pm-s3c2412.c                 |    9 +-
+ arch/arm/mach-s3c24xx/s3c2410.c                    |    1 -
+ arch/arm/mach-s3c24xx/s3c2412.c                    |    1 -
+ arch/arm/mach-s3c24xx/s3c2416.c                    |    1 -
+ arch/arm/mach-s3c24xx/s3c2440.c                    |    1 -
+ arch/arm/mach-s3c24xx/s3c2442.c                    |    1 -
+ arch/arm/mach-s3c24xx/s3c2443.c                    |    1 -
+ arch/arm/mach-s3c24xx/s3c244x.c                    |    2 -
+ arch/arm/mach-s3c64xx/Kconfig                      |    2 +
+ arch/arm/mach-s3c64xx/mach-anw6410.c               |    4 +-
+ arch/arm/mach-s3c64xx/mach-crag6410.c              |    4 +-
+ arch/arm/mach-s3c64xx/mach-hmt.c                   |    4 +-
+ arch/arm/mach-s3c64xx/mach-mini6410.c              |    4 +-
+ arch/arm/mach-s3c64xx/mach-ncp.c                   |    4 +-
+ arch/arm/mach-s3c64xx/mach-real6410.c              |    4 +-
+ arch/arm/mach-s3c64xx/mach-smartq.c                |    2 +
+ arch/arm/mach-s3c64xx/mach-smartq5.c               |    3 +-
+ arch/arm/mach-s3c64xx/mach-smartq7.c               |    3 +-
+ arch/arm/mach-s3c64xx/mach-smdk6400.c              |    4 +-
+ arch/arm/mach-s3c64xx/mach-smdk6410.c              |    4 +-
+ arch/arm/mach-s5p64x0/Kconfig                      |    4 +-
+ arch/arm/mach-s5p64x0/mach-smdk6440.c              |    6 +-
+ arch/arm/mach-s5p64x0/mach-smdk6450.c              |    6 +-
+ arch/arm/mach-s5pc100/Kconfig                      |    1 +
+ arch/arm/mach-s5pc100/common.h                     |    9 -
+ arch/arm/mach-s5pc100/mach-smdkc100.c              |    4 +-
+ arch/arm/mach-s5pv210/Kconfig                      |    2 +-
+ arch/arm/mach-s5pv210/common.h                     |    9 -
+ arch/arm/mach-s5pv210/mach-aquila.c                |    6 +-
+ arch/arm/mach-s5pv210/mach-goni.c                  |    6 +-
+ arch/arm/mach-s5pv210/mach-smdkc110.c              |    6 +-
+ arch/arm/mach-s5pv210/mach-smdkv210.c              |    6 +-
+ arch/arm/mach-s5pv210/mach-torbreck.c              |    6 +-
+ arch/arm/mach-shmobile/Kconfig                     |   76 +-
+ arch/arm/mach-shmobile/Makefile                    |   15 +-
+ arch/arm/mach-shmobile/board-ag5evm.c              |  172 +-
+ arch/arm/mach-shmobile/board-ap4evb.c              |   91 +-
+ arch/arm/mach-shmobile/board-ape6evm.c             |   94 +
+ arch/arm/mach-shmobile/board-armadillo800eva.c     |  335 ++-
+ arch/arm/mach-shmobile/board-bockw.c               |   43 +
+ arch/arm/mach-shmobile/board-bonito.c              |   52 +-
+ arch/arm/mach-shmobile/board-kota2.c               |  208 +-
+ arch/arm/mach-shmobile/board-kzm9g-reference.c     |  107 +
+ arch/arm/mach-shmobile/board-kzm9g.c               |  244 +-
+ arch/arm/mach-shmobile/board-lager.c               |   46 +
+ arch/arm/mach-shmobile/board-mackerel.c            |  187 +-
+ arch/arm/mach-shmobile/board-marzen-reference.c    |   75 +
+ arch/arm/mach-shmobile/board-marzen.c              |  119 +-
+ arch/arm/mach-shmobile/clock-r8a73a4.c             |  115 +
+ arch/arm/mach-shmobile/clock-r8a7740.c             |  127 +-
+ arch/arm/mach-shmobile/clock-r8a7778.c             |  104 +
+ arch/arm/mach-shmobile/clock-r8a7779.c             |  200 +-
+ arch/arm/mach-shmobile/clock-r8a7790.c             |   93 +
+ arch/arm/mach-shmobile/clock-sh7372.c              |   50 +-
+ arch/arm/mach-shmobile/clock-sh73a0.c              |  122 +-
+ arch/arm/mach-shmobile/clock.c                     |   13 +
+ .../{headsmp-sh73a0.S => headsmp-scu.S}            |   15 +-
+ arch/arm/mach-shmobile/hotplug.c                   |   68 -
+ arch/arm/mach-shmobile/include/mach/clock.h        |   39 +
+ arch/arm/mach-shmobile/include/mach/common.h       |   64 +-
+ arch/arm/mach-shmobile/include/mach/irqs.h         |    5 +
+ arch/arm/mach-shmobile/include/mach/r8a73a4.h      |    8 +
+ arch/arm/mach-shmobile/include/mach/r8a7740.h      |   83 +-
+ arch/arm/mach-shmobile/include/mach/r8a7778.h      |   28 +
+ arch/arm/mach-shmobile/include/mach/r8a7779.h      |  334 +--
+ arch/arm/mach-shmobile/include/mach/r8a7790.h      |    8 +
+ arch/arm/mach-shmobile/include/mach/sh7372.h       |   41 +-
+ arch/arm/mach-shmobile/include/mach/sh73a0.h       |  378 +--
+ arch/arm/mach-shmobile/intc-r8a7740.c              |  641 +----
+ arch/arm/mach-shmobile/intc-r8a7779.c              |   78 +-
+ arch/arm/mach-shmobile/intc-sh73a0.c               |  125 -
+ arch/arm/mach-shmobile/setup-emev2.c               |    4 +-
+ arch/arm/mach-shmobile/setup-r8a73a4.c             |  202 ++
+ arch/arm/mach-shmobile/setup-r8a7740.c             |  192 +-
+ arch/arm/mach-shmobile/setup-r8a7778.c             |  193 ++
+ arch/arm/mach-shmobile/setup-r8a7779.c             |  162 +-
+ arch/arm/mach-shmobile/setup-r8a7790.c             |  137 +
+ arch/arm/mach-shmobile/setup-sh73a0.c              |  162 +-
+ arch/arm/mach-shmobile/smp-emev2.c                 |   75 +-
+ arch/arm/mach-shmobile/smp-r8a7779.c               |  136 +-
+ arch/arm/mach-shmobile/smp-sh73a0.c                |   43 +-
+ arch/arm/mach-socfpga/platsmp.c                    |   12 -
+ arch/arm/mach-spear/Kconfig                        |  103 +
+ arch/arm/mach-spear/Makefile                       |   26 +
+ .../{mach-spear13xx => mach-spear}/Makefile.boot   |    0
+ .../include/mach => mach-spear}/generic.h          |   30 +-
+ arch/arm/{mach-spear13xx => mach-spear}/headsmp.S  |    0
+ arch/arm/{mach-spear13xx => mach-spear}/hotplug.c  |    0
+ .../plat => mach-spear/include/mach}/debug-macro.S |    0
+ .../include/mach/irqs.h                            |   22 +-
+ .../include/mach/misc_regs.h                       |    2 +-
+ arch/arm/mach-spear/include/mach/spear.h           |   95 +
+ .../plat => mach-spear/include/mach}/timex.h       |    0
+ .../plat => mach-spear/include/mach}/uncompress.h  |    0
+ arch/arm/{plat-spear => mach-spear}/pl080.c        |    0
+ .../include/plat => mach-spear}/pl080.h            |    0
+ arch/arm/{mach-spear13xx => mach-spear}/platsmp.c  |   10 +-
+ arch/arm/{plat-spear => mach-spear}/restart.c      |    5 +-
+ .../arm/{mach-spear13xx => mach-spear}/spear1310.c |    4 +-
+ .../arm/{mach-spear13xx => mach-spear}/spear1340.c |    5 +-
+ .../mach/dma.h => mach-spear/spear13xx-dma.h}      |    0
+ .../arm/{mach-spear13xx => mach-spear}/spear13xx.c |    9 +-
+ arch/arm/{mach-spear3xx => mach-spear}/spear300.c  |    4 +-
+ arch/arm/{mach-spear3xx => mach-spear}/spear310.c  |    4 +-
+ arch/arm/{mach-spear3xx => mach-spear}/spear320.c  |    7 +-
+ arch/arm/{mach-spear3xx => mach-spear}/spear3xx.c  |   17 +-
+ arch/arm/{mach-spear6xx => mach-spear}/spear6xx.c  |   25 +-
+ arch/arm/{plat-spear => mach-spear}/time.c         |    2 +-
+ arch/arm/mach-spear13xx/Kconfig                    |   20 -
+ arch/arm/mach-spear13xx/Makefile                   |   10 -
+ arch/arm/mach-spear13xx/include/mach/debug-macro.S |   14 -
+ arch/arm/mach-spear13xx/include/mach/hardware.h    |    1 -
+ arch/arm/mach-spear13xx/include/mach/irqs.h        |   20 -
+ arch/arm/mach-spear13xx/include/mach/spear.h       |   54 -
+ arch/arm/mach-spear13xx/include/mach/timex.h       |   19 -
+ arch/arm/mach-spear13xx/include/mach/uncompress.h  |   19 -
+ arch/arm/mach-spear3xx/Kconfig                     |   26 -
+ arch/arm/mach-spear3xx/Makefile                    |   15 -
+ arch/arm/mach-spear3xx/Makefile.boot               |    3 -
+ arch/arm/mach-spear3xx/include/mach/debug-macro.S  |   14 -
+ arch/arm/mach-spear3xx/include/mach/generic.h      |   36 -
+ arch/arm/mach-spear3xx/include/mach/hardware.h     |    1 -
+ arch/arm/mach-spear3xx/include/mach/irqs.h         |   19 -
+ arch/arm/mach-spear3xx/include/mach/spear.h        |   60 -
+ arch/arm/mach-spear3xx/include/mach/timex.h        |   19 -
+ arch/arm/mach-spear3xx/include/mach/uncompress.h   |   19 -
+ arch/arm/mach-spear6xx/Kconfig                     |   10 -
+ arch/arm/mach-spear6xx/Makefile                    |    6 -
+ arch/arm/mach-spear6xx/Makefile.boot               |    3 -
+ arch/arm/mach-spear6xx/include/mach/debug-macro.S  |   14 -
+ arch/arm/mach-spear6xx/include/mach/generic.h      |   23 -
+ arch/arm/mach-spear6xx/include/mach/hardware.h     |    1 -
+ arch/arm/mach-spear6xx/include/mach/misc_regs.h    |   22 -
+ arch/arm/mach-spear6xx/include/mach/spear.h        |   46 -
+ arch/arm/mach-spear6xx/include/mach/timex.h        |   19 -
+ arch/arm/mach-spear6xx/include/mach/uncompress.h   |   19 -
+ arch/arm/mach-tegra/platsmp.c                      |    8 -
+ arch/arm/mach-ux500/board-mop500-regulators.c      |   14 +
+ arch/arm/mach-ux500/board-mop500-regulators.h      |    1 +
+ arch/arm/mach-ux500/board-mop500-sdi.c             |   51 -
+ arch/arm/mach-ux500/board-mop500.c                 |   45 +
+ arch/arm/mach-ux500/cache-l2x0.c                   |    4 +-
+ arch/arm/mach-ux500/cpu-db8500.c                   |    1 +
+ arch/arm/mach-ux500/platsmp.c                      |    8 -
+ arch/arm/mach-virt/platsmp.c                       |    8 -
+ arch/arm/plat-orion/Makefile                       |    6 +-
+ arch/arm/plat-orion/pcie.c                         |   10 +-
+ arch/arm/plat-samsung/Kconfig                      |    2 +-
+ arch/arm/plat-samsung/Makefile                     |    3 +-
+ arch/arm/plat-samsung/include/plat/cpu.h           |   14 +-
+ arch/arm/plat-samsung/include/plat/irq.h           |  116 -
+ arch/arm/plat-samsung/include/plat/s3c2410.h       |   31 -
+ arch/arm/plat-samsung/include/plat/s3c2412.h       |   32 -
+ arch/arm/plat-samsung/include/plat/s3c2416.h       |   37 -
+ arch/arm/plat-samsung/include/plat/s3c2443.h       |   36 -
+ arch/arm/plat-samsung/include/plat/s3c244x.h       |   42 -
+ arch/arm/plat-samsung/include/plat/s5p-time.h      |   40 -
+ arch/arm/plat-samsung/include/plat/samsung-time.h  |   53 +
+ arch/arm/plat-samsung/irq-vic-timer.c              |    3 +-
+ arch/arm/plat-samsung/s5p-irq-gpioint.c            |    3 +-
+ .../plat-samsung/{s5p-time.c => samsung-time.c}    |  138 +-
+ arch/arm/plat-samsung/time.c                       |  287 ---
+ arch/arm/plat-spear/Kconfig                        |   47 -
+ arch/arm/plat-spear/Makefile                       |    9 -
+ arch/arm/plat-versatile/platsmp.c                  |    8 -
+ arch/avr32/mach-at32ap/at32ap700x.c                |    6 +-
+ arch/sh/kernel/cpu/sh2a/pinmux-sh7203.c            |   13 +-
+ arch/sh/kernel/cpu/sh2a/pinmux-sh7264.c            |   13 +-
+ arch/sh/kernel/cpu/sh2a/pinmux-sh7269.c            |   13 +-
+ arch/sh/kernel/cpu/sh3/pinmux-sh7720.c             |   14 +-
+ arch/sh/kernel/cpu/sh4a/pinmux-sh7722.c            |   14 +-
+ arch/sh/kernel/cpu/sh4a/pinmux-sh7723.c            |   14 +-
+ arch/sh/kernel/cpu/sh4a/pinmux-sh7724.c            |   13 +-
+ arch/sh/kernel/cpu/sh4a/pinmux-sh7757.c            |   13 +-
+ arch/sh/kernel/cpu/sh4a/pinmux-sh7785.c            |   14 +-
+ arch/sh/kernel/cpu/sh4a/pinmux-sh7786.c            |   14 +-
+ arch/sh/kernel/cpu/sh4a/pinmux-shx3.c              |   17 +-
+ drivers/clk/spear/spear1310_clock.c                |   64 +-
+ drivers/clk/spear/spear1340_clock.c                |   63 +-
+ drivers/clk/spear/spear3xx_clock.c                 |   60 +-
+ drivers/clk/spear/spear6xx_clock.c                 |   31 +-
+ drivers/clk/ux500/u8500_clk.c                      |    3 +-
+ drivers/clocksource/Makefile                       |    2 +
+ drivers/clocksource/em_sti.c                       |   13 +-
+ drivers/clocksource/sh_cmt.c                       |  189 +-
+ drivers/clocksource/sh_mtu2.c                      |    2 +-
+ drivers/clocksource/sh_tmu.c                       |    2 +-
+ .../clocksource}/timer-marco.c                     |   25 +-
+ .../clocksource}/timer-prima2.c                    |   42 +-
+ drivers/gpio/Kconfig                               |    6 +
+ drivers/gpio/Makefile                              |    1 +
+ drivers/gpio/gpio-msm-v2.c                         |    3 +-
+ drivers/gpio/gpio-mxc.c                            |    2 +-
+ drivers/gpio/gpio-omap.c                           |    3 +-
+ drivers/gpio/gpio-pl061.c                          |    2 +-
+ drivers/gpio/gpio-pxa.c                            |    3 +-
+ drivers/gpio/gpio-rcar.c                           |  396 +++
+ drivers/gpio/gpio-samsung.c                        |    9 +-
+ drivers/gpio/gpio-tegra.c                          |    3 +-
+ drivers/irqchip/Kconfig                            |    8 +
+ drivers/irqchip/Makefile                           |    3 +
+ drivers/irqchip/exynos-combiner.c                  |    1 +
+ drivers/irqchip/irq-gic.c                          |   36 +-
+ drivers/irqchip/irq-renesas-intc-irqpin.c          |  547 ++++
+ drivers/irqchip/irq-renesas-irqc.c                 |  307 +++
+ drivers/irqchip/irq-sirfsoc.c                      |  126 +
+ drivers/irqchip/irq-vic.c                          |    3 +-
+ drivers/mmc/host/mmci.c                            |    9 +
+ drivers/mmc/host/s3cmci.c                          |   83 +-
+ drivers/mmc/host/sdhci-cns3xxx.c                   |    1 -
+ drivers/net/ethernet/smsc/smsc911x.c               |   29 +-
+ drivers/pinctrl/pinctrl-at91.c                     |    3 +-
+ drivers/pinctrl/pinctrl-exynos.c                   |  111 +-
+ drivers/pinctrl/pinctrl-nomadik.c                  |    2 +-
+ drivers/pinctrl/pinctrl-samsung.c                  |    2 +
+ drivers/pinctrl/pinctrl-samsung.h                  |    1 +
+ drivers/pinctrl/pinctrl-sirf.c                     |   14 +-
+ drivers/pinctrl/sh-pfc/Kconfig                     |    6 +
+ drivers/pinctrl/sh-pfc/Makefile                    |    1 +
+ drivers/pinctrl/sh-pfc/core.c                      |  302 +--
+ drivers/pinctrl/sh-pfc/core.h                      |   55 +-
+ drivers/pinctrl/sh-pfc/gpio.c                      |  372 ++-
+ drivers/pinctrl/sh-pfc/pfc-r8a73a4.c               | 2587 +++++++++++++++++++
+ drivers/pinctrl/sh-pfc/pfc-r8a7740.c               |  694 ++++-
+ drivers/pinctrl/sh-pfc/pfc-r8a7779.c               | 1695 ++++++++++---
+ drivers/pinctrl/sh-pfc/pfc-sh7203.c                |  488 ++--
+ drivers/pinctrl/sh-pfc/pfc-sh7264.c                |  460 ++--
+ drivers/pinctrl/sh-pfc/pfc-sh7269.c                |  624 ++---
+ drivers/pinctrl/sh-pfc/pfc-sh7372.c                |  323 ++-
+ drivers/pinctrl/sh-pfc/pfc-sh73a0.c                | 2664 ++++++++++++++------
+ drivers/pinctrl/sh-pfc/pfc-sh7720.c                |  333 +--
+ drivers/pinctrl/sh-pfc/pfc-sh7722.c                |  480 ++--
+ drivers/pinctrl/sh-pfc/pfc-sh7723.c                |  642 ++---
+ drivers/pinctrl/sh-pfc/pfc-sh7724.c                |  638 ++---
+ drivers/pinctrl/sh-pfc/pfc-sh7734.c                |   55 +-
+ drivers/pinctrl/sh-pfc/pfc-sh7757.c                |  620 ++---
+ drivers/pinctrl/sh-pfc/pfc-sh7785.c                |  354 +--
+ drivers/pinctrl/sh-pfc/pfc-sh7786.c                |  296 +--
+ drivers/pinctrl/sh-pfc/pfc-shx3.c                  |  148 +-
+ drivers/pinctrl/sh-pfc/pinctrl.c                   |  491 ++--
+ drivers/pinctrl/sh-pfc/sh_pfc.h                    |  135 +-
+ drivers/pinctrl/spear/pinctrl-plgpio.c             |    2 +-
+ drivers/staging/imx-drm/ipu-v3/ipu-common.c        |    2 +-
+ drivers/video/atmel_lcdfb.c                        |  120 +-
+ include/linux/irqchip/arm-gic.h                    |    1 -
+ include/linux/irqchip/chained_irq.h                |   52 +
+ include/linux/platform_data/gpio-rcar.h            |   26 +
+ .../linux/platform_data/irq-renesas-intc-irqpin.h  |   29 +
+ include/linux/platform_data/irq-renesas-irqc.h     |   27 +
+ include/video/atmel_lcdc.h                         |    4 +-
+ 474 files changed, 22004 insertions(+), 12703 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/arm/bcm/bcm,kona-timer.txt
+ create mode 100644 arch/arm/arm-soc-for-next-contents.txt
+ create mode 100644 arch/arm/boot/dts/atlas6-evb.dts
+ create mode 100644 arch/arm/boot/dts/atlas6.dtsi
+ create mode 100644 arch/arm/boot/dts/mpa1600.dts
+ create mode 100644 arch/arm/boot/dts/r8a73a4-ape6evm.dts
+ create mode 100644 arch/arm/boot/dts/r8a73a4.dtsi
+ create mode 100644 arch/arm/boot/dts/r8a7778-bockw.dts
+ create mode 100644 arch/arm/boot/dts/r8a7778.dtsi
+ create mode 100644 arch/arm/boot/dts/r8a7779-marzen-reference.dts
+ create mode 100644 arch/arm/boot/dts/r8a7779.dtsi
+ create mode 100644 arch/arm/boot/dts/r8a7790-lager.dts
+ create mode 100644 arch/arm/boot/dts/r8a7790.dtsi
+ create mode 100644 arch/arm/boot/dts/sama5d3.dtsi
+ create mode 100644 arch/arm/boot/dts/sama5d31ek.dts
+ create mode 100644 arch/arm/boot/dts/sama5d33ek.dts
+ create mode 100644 arch/arm/boot/dts/sama5d34ek.dts
+ create mode 100644 arch/arm/boot/dts/sama5d35ek.dts
+ create mode 100644 arch/arm/boot/dts/sama5d3xcm.dtsi
+ create mode 100644 arch/arm/boot/dts/sama5d3xdm.dtsi
+ create mode 100644 arch/arm/boot/dts/sama5d3xmb.dtsi
+ create mode 100644 arch/arm/boot/dts/sh73a0-kzm9g-reference.dts
+ delete mode 100644 arch/arm/boot/dts/sh73a0-reference.dtsi
+ create mode 100644 arch/arm/boot/dts/sun4i-a10-mini-xplus.dts
+ create mode 100644 arch/arm/configs/ape6evm_defconfig
+ create mode 100644 arch/arm/configs/bockw_defconfig
+ delete mode 100644 arch/arm/configs/h7201_defconfig
+ delete mode 100644 arch/arm/configs/h7202_defconfig
+ create mode 100644 arch/arm/configs/sama5_defconfig
+ rename arch/arm/{mach-cns3xxx/include/mach/debug-macro.S => include/debug/cns3xxx.S} (100%)
+ rename arch/arm/{mach-nomadik/include/mach/debug-macro.S => include/debug/nomadik.S} (100%)
+ rename arch/arm/{mach-prima2/include/mach/uart.h => include/debug/sirf.S} (55%)
+ create mode 100644 arch/arm/mach-at91/Kconfig.non_dt
+ rename arch/arm/mach-at91/{board-rm9200-dt.c => board-dt-rm9200.c} (100%)
+ rename arch/arm/mach-at91/{board-dt.c => board-dt-sam9.c} (100%)
+ create mode 100644 arch/arm/mach-at91/board-dt-sama5.c
+ create mode 100644 arch/arm/mach-at91/include/mach/sama5d3.h
+ create mode 100644 arch/arm/mach-at91/sama5d3.c
+ rename arch/arm/mach-cns3xxx/{include/mach => }/cns3xxx.h (99%)
+ delete mode 100644 arch/arm/mach-cns3xxx/include/mach/irqs.h
+ delete mode 100644 arch/arm/mach-cns3xxx/include/mach/timex.h
+ delete mode 100644 arch/arm/mach-cns3xxx/include/mach/uncompress.h
+ rename arch/arm/mach-cns3xxx/{include/mach => }/pm.h (100%)
+ rename arch/arm/mach-gemini/{include/mach/system.h => reset.c} (91%)
+ delete mode 100644 arch/arm/mach-h720x/Kconfig
+ delete mode 100644 arch/arm/mach-h720x/Makefile
+ delete mode 100644 arch/arm/mach-h720x/Makefile.boot
+ delete mode 100644 arch/arm/mach-h720x/common.c
+ delete mode 100644 arch/arm/mach-h720x/common.h
+ delete mode 100644 arch/arm/mach-h720x/cpu-h7201.c
+ delete mode 100644 arch/arm/mach-h720x/cpu-h7202.c
+ delete mode 100644 arch/arm/mach-h720x/h7201-eval.c
+ delete mode 100644 arch/arm/mach-h720x/h7202-eval.c
+ delete mode 100644 arch/arm/mach-h720x/include/mach/boards.h
+ delete mode 100644 arch/arm/mach-h720x/include/mach/debug-macro.S
+ delete mode 100644 arch/arm/mach-h720x/include/mach/entry-macro.S
+ delete mode 100644 arch/arm/mach-h720x/include/mach/h7201-regs.h
+ delete mode 100644 arch/arm/mach-h720x/include/mach/h7202-regs.h
+ delete mode 100644 arch/arm/mach-h720x/include/mach/hardware.h
+ delete mode 100644 arch/arm/mach-h720x/include/mach/irqs.h
+ delete mode 100644 arch/arm/mach-h720x/include/mach/isa-dma.h
+ delete mode 100644 arch/arm/mach-h720x/include/mach/timex.h
+ delete mode 100644 arch/arm/mach-h720x/include/mach/uncompress.h
+ delete mode 100644 arch/arm/mach-l7200/include/mach/debug-macro.S
+ delete mode 100644 arch/arm/mach-nomadik/Makefile.boot
+ delete mode 100644 arch/arm/mach-nomadik/include/mach/irqs.h
+ delete mode 100644 arch/arm/mach-nomadik/include/mach/timex.h
+ delete mode 100644 arch/arm/mach-nomadik/include/mach/uncompress.h
+ delete mode 100644 arch/arm/mach-prima2/include/mach/clkdev.h
+ delete mode 100644 arch/arm/mach-prima2/include/mach/debug-macro.S
+ delete mode 100644 arch/arm/mach-prima2/include/mach/entry-macro.S
+ delete mode 100644 arch/arm/mach-prima2/include/mach/hardware.h
+ delete mode 100644 arch/arm/mach-prima2/include/mach/irqs.h
+ delete mode 100644 arch/arm/mach-prima2/include/mach/map.h
+ delete mode 100644 arch/arm/mach-prima2/include/mach/timex.h
+ delete mode 100644 arch/arm/mach-prima2/include/mach/uncompress.h
+ delete mode 100644 arch/arm/mach-prima2/irq.c
+ rename arch/arm/{plat-samsung/include/plat => mach-s3c24xx}/common-smdk.h (86%)
+ delete mode 100644 arch/arm/mach-s3c24xx/include/mach/regs-sdi.h
+ delete mode 100644 arch/arm/mach-s3c24xx/irq-s3c2412.c
+ delete mode 100644 arch/arm/mach-s3c24xx/irq-s3c2440.c
+ delete mode 100644 arch/arm/mach-s3c24xx/irq-s3c244x.c
+ create mode 100644 arch/arm/mach-shmobile/board-ape6evm.c
+ create mode 100644 arch/arm/mach-shmobile/board-bockw.c
+ create mode 100644 arch/arm/mach-shmobile/board-kzm9g-reference.c
+ create mode 100644 arch/arm/mach-shmobile/board-lager.c
+ create mode 100644 arch/arm/mach-shmobile/board-marzen-reference.c
+ create mode 100644 arch/arm/mach-shmobile/clock-r8a73a4.c
+ create mode 100644 arch/arm/mach-shmobile/clock-r8a7778.c
+ create mode 100644 arch/arm/mach-shmobile/clock-r8a7790.c
+ rename arch/arm/mach-shmobile/{headsmp-sh73a0.S => headsmp-scu.S} (85%)
+ delete mode 100644 arch/arm/mach-shmobile/hotplug.c
+ create mode 100644 arch/arm/mach-shmobile/include/mach/clock.h
+ create mode 100644 arch/arm/mach-shmobile/include/mach/r8a73a4.h
+ create mode 100644 arch/arm/mach-shmobile/include/mach/r8a7778.h
+ create mode 100644 arch/arm/mach-shmobile/include/mach/r8a7790.h
+ create mode 100644 arch/arm/mach-shmobile/setup-r8a73a4.c
+ create mode 100644 arch/arm/mach-shmobile/setup-r8a7778.c
+ create mode 100644 arch/arm/mach-shmobile/setup-r8a7790.c
+ create mode 100644 arch/arm/mach-spear/Kconfig
+ create mode 100644 arch/arm/mach-spear/Makefile
+ rename arch/arm/{mach-spear13xx => mach-spear}/Makefile.boot (100%)
+ rename arch/arm/{mach-spear13xx/include/mach => mach-spear}/generic.h (57%)
+ rename arch/arm/{mach-spear13xx => mach-spear}/headsmp.S (100%)
+ rename arch/arm/{mach-spear13xx => mach-spear}/hotplug.c (100%)
+ rename arch/arm/{plat-spear/include/plat => mach-spear/include/mach}/debug-macro.S (100%)
+ rename arch/arm/{mach-spear6xx => mach-spear}/include/mach/irqs.h (51%)
+ rename arch/arm/{mach-spear3xx => mach-spear}/include/mach/misc_regs.h (90%)
+ create mode 100644 arch/arm/mach-spear/include/mach/spear.h
+ rename arch/arm/{plat-spear/include/plat => mach-spear/include/mach}/timex.h (100%)
+ rename arch/arm/{plat-spear/include/plat => mach-spear/include/mach}/uncompress.h (100%)
+ rename arch/arm/{plat-spear => mach-spear}/pl080.c (100%)
+ rename arch/arm/{plat-spear/include/plat => mach-spear}/pl080.h (100%)
+ rename arch/arm/{mach-spear13xx => mach-spear}/platsmp.c (92%)
+ rename arch/arm/{plat-spear => mach-spear}/restart.c (90%)
+ rename arch/arm/{mach-spear13xx => mach-spear}/spear1310.c (95%)
+ rename arch/arm/{mach-spear13xx => mach-spear}/spear1340.c (99%)
+ rename arch/arm/{mach-spear13xx/include/mach/dma.h => mach-spear/spear13xx-dma.h} (100%)
+ rename arch/arm/{mach-spear13xx => mach-spear}/spear13xx.c (96%)
+ rename arch/arm/{mach-spear3xx => mach-spear}/spear300.c (98%)
+ rename arch/arm/{mach-spear3xx => mach-spear}/spear310.c (98%)
+ rename arch/arm/{mach-spear3xx => mach-spear}/spear320.c (97%)
+ rename arch/arm/{mach-spear3xx => mach-spear}/spear3xx.c (88%)
+ rename arch/arm/{mach-spear6xx => mach-spear}/spear6xx.c (93%)
+ rename arch/arm/{plat-spear => mach-spear}/time.c (99%)
+ delete mode 100644 arch/arm/mach-spear13xx/Kconfig
+ delete mode 100644 arch/arm/mach-spear13xx/Makefile
+ delete mode 100644 arch/arm/mach-spear13xx/include/mach/debug-macro.S
+ delete mode 100644 arch/arm/mach-spear13xx/include/mach/hardware.h
+ delete mode 100644 arch/arm/mach-spear13xx/include/mach/irqs.h
+ delete mode 100644 arch/arm/mach-spear13xx/include/mach/spear.h
+ delete mode 100644 arch/arm/mach-spear13xx/include/mach/timex.h
+ delete mode 100644 arch/arm/mach-spear13xx/include/mach/uncompress.h
+ delete mode 100644 arch/arm/mach-spear3xx/Kconfig
+ delete mode 100644 arch/arm/mach-spear3xx/Makefile
+ delete mode 100644 arch/arm/mach-spear3xx/Makefile.boot
+ delete mode 100644 arch/arm/mach-spear3xx/include/mach/debug-macro.S
+ delete mode 100644 arch/arm/mach-spear3xx/include/mach/generic.h
+ delete mode 100644 arch/arm/mach-spear3xx/include/mach/hardware.h
+ delete mode 100644 arch/arm/mach-spear3xx/include/mach/irqs.h
+ delete mode 100644 arch/arm/mach-spear3xx/include/mach/spear.h
+ delete mode 100644 arch/arm/mach-spear3xx/include/mach/timex.h
+ delete mode 100644 arch/arm/mach-spear3xx/include/mach/uncompress.h
+ delete mode 100644 arch/arm/mach-spear6xx/Kconfig
+ delete mode 100644 arch/arm/mach-spear6xx/Makefile
+ delete mode 100644 arch/arm/mach-spear6xx/Makefile.boot
+ delete mode 100644 arch/arm/mach-spear6xx/include/mach/debug-macro.S
+ delete mode 100644 arch/arm/mach-spear6xx/include/mach/generic.h
+ delete mode 100644 arch/arm/mach-spear6xx/include/mach/hardware.h
+ delete mode 100644 arch/arm/mach-spear6xx/include/mach/misc_regs.h
+ delete mode 100644 arch/arm/mach-spear6xx/include/mach/spear.h
+ delete mode 100644 arch/arm/mach-spear6xx/include/mach/timex.h
+ delete mode 100644 arch/arm/mach-spear6xx/include/mach/uncompress.h
+ delete mode 100644 arch/arm/plat-samsung/include/plat/irq.h
+ delete mode 100644 arch/arm/plat-samsung/include/plat/s3c2410.h
+ delete mode 100644 arch/arm/plat-samsung/include/plat/s3c2412.h
+ delete mode 100644 arch/arm/plat-samsung/include/plat/s3c2416.h
+ delete mode 100644 arch/arm/plat-samsung/include/plat/s3c2443.h
+ delete mode 100644 arch/arm/plat-samsung/include/plat/s3c244x.h
+ delete mode 100644 arch/arm/plat-samsung/include/plat/s5p-time.h
+ create mode 100644 arch/arm/plat-samsung/include/plat/samsung-time.h
+ rename arch/arm/plat-samsung/{s5p-time.c => samsung-time.c} (68%)
+ delete mode 100644 arch/arm/plat-samsung/time.c
+ delete mode 100644 arch/arm/plat-spear/Kconfig
+ delete mode 100644 arch/arm/plat-spear/Makefile
+ rename {arch/arm/mach-prima2 => drivers/clocksource}/timer-marco.c (94%)
+ rename {arch/arm/mach-prima2 => drivers/clocksource}/timer-prima2.c (90%)
+ create mode 100644 drivers/gpio/gpio-rcar.c
+ create mode 100644 drivers/irqchip/irq-renesas-intc-irqpin.c
+ create mode 100644 drivers/irqchip/irq-renesas-irqc.c
+ create mode 100644 drivers/irqchip/irq-sirfsoc.c
+ create mode 100644 drivers/pinctrl/sh-pfc/pfc-r8a73a4.c
+ create mode 100644 include/linux/irqchip/chained_irq.h
+ create mode 100644 include/linux/platform_data/gpio-rcar.h
+ create mode 100644 include/linux/platform_data/irq-renesas-intc-irqpin.h
+ create mode 100644 include/linux/platform_data/irq-renesas-irqc.h
+Merging bcm2835/for-next (d1a7707 Merge branch 'for-3.10/defconfig' into for-next)
+$ git merge bcm2835/for-next
+Resolved 'arch/arm/Kconfig' using previous resolution.
+Resolved 'arch/arm/Kconfig.debug' using previous resolution.
+Removing arch/arm/mach-bcm2835/include/mach/uncompress.h
+Removing arch/arm/mach-bcm2835/include/mach/timex.h
+Removing arch/arm/mach-bcm2835/include/mach/gpio.h
+Removing arch/arm/mach-bcm2835/include/mach/bcm2835_soc.h
+Removing arch/arm/mach-bcm2835/Makefile.boot
+Auto-merging arch/arm/include/debug/bcm2835.S
+Auto-merging arch/arm/boot/dts/bcm2835.dtsi
+Auto-merging arch/arm/Kconfig.debug
+CONFLICT (content): Merge conflict in arch/arm/Kconfig.debug
+Auto-merging arch/arm/Kconfig
+CONFLICT (content): Merge conflict in arch/arm/Kconfig
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master 0fb38b0] Merge remote-tracking branch 'bcm2835/for-next'
+$ git diff -M --stat --summary HEAD^..
+ arch/arm/Kconfig                                   | 22 +----------
+ arch/arm/Kconfig.debug                             |  5 +++
+ arch/arm/boot/dts/bcm2835.dtsi                     | 22 +++++++++++
+ arch/arm/configs/bcm2835_defconfig                 | 11 +++---
+ .../mach/debug-macro.S => include/debug/bcm2835.S} |  3 +-
+ arch/arm/mach-bcm2835/Kconfig                      | 15 ++++++++
+ arch/arm/mach-bcm2835/Makefile.boot                |  1 -
+ arch/arm/mach-bcm2835/bcm2835.c                    |  6 ++-
+ arch/arm/mach-bcm2835/include/mach/bcm2835_soc.h   | 29 --------------
+ arch/arm/mach-bcm2835/include/mach/gpio.h          |  1 -
+ arch/arm/mach-bcm2835/include/mach/timex.h         | 26 -------------
+ arch/arm/mach-bcm2835/include/mach/uncompress.h    | 44 ----------------------
+ 12 files changed, 56 insertions(+), 129 deletions(-)
+ rename arch/arm/{mach-bcm2835/include/mach/debug-macro.S => include/debug/bcm2835.S} (86%)
+ create mode 100644 arch/arm/mach-bcm2835/Kconfig
+ delete mode 100644 arch/arm/mach-bcm2835/Makefile.boot
+ delete mode 100644 arch/arm/mach-bcm2835/include/mach/bcm2835_soc.h
+ delete mode 100644 arch/arm/mach-bcm2835/include/mach/gpio.h
+ delete mode 100644 arch/arm/mach-bcm2835/include/mach/timex.h
+ delete mode 100644 arch/arm/mach-bcm2835/include/mach/uncompress.h
+Merging cortex/for-next (6ebd4d0 ARM: stub out read_cpuid and read_cpuid_ext for CPU_CP15=n)
+$ git merge cortex/for-next
+Already up-to-date.
+Merging ep93xx/ep93xx-for-next (7ec4429 Merge branch 'ep93xx-fixes' into ep93xx-for-next)
+$ git merge ep93xx/ep93xx-for-next
+Already up-to-date!
+Merge made by the 'recursive' strategy.
+Merging imx-mxs/for-next (21f4fc4 Merge branch 'imx/dt' into for-next)
+$ git merge imx-mxs/for-next
+Recorded preimage for 'drivers/pinctrl/Makefile'
+Resolved 'arch/arm/Kconfig.debug' using previous resolution.
+Resolved 'drivers/clocksource/Makefile' using previous resolution.
+Auto-merging sound/soc/mxs/mxs-saif.c
+Removing include/linux/mxsfb.h
+Auto-merging drivers/video/Kconfig
+Auto-merging drivers/staging/imx-drm/ipu-v3/ipu-common.c
+Auto-merging drivers/staging/iio/adc/mxs-lradc.c
+Auto-merging drivers/spi/spi-mxs.c
+Auto-merging drivers/pinctrl/pinctrl-imx.c
+Auto-merging drivers/pinctrl/Makefile
+CONFLICT (content): Merge conflict in drivers/pinctrl/Makefile
+Auto-merging drivers/pinctrl/Kconfig
+Auto-merging drivers/net/ethernet/freescale/fec_main.c
+Auto-merging drivers/irqchip/irq-mxs.c
+Auto-merging drivers/irqchip/Makefile
+Auto-merging drivers/i2c/busses/i2c-mxs.c
+Auto-merging drivers/clocksource/mxs_timer.c
+Auto-merging drivers/clocksource/Makefile
+CONFLICT (content): Merge conflict in drivers/clocksource/Makefile
+Auto-merging drivers/Makefile
+Auto-merging drivers/Kconfig
+Removing arch/arm/mach-mxs/system.c
+Removing arch/arm/mach-mxs/ocotp.c
+Removing arch/arm/mach-mxs/mm.c
+Removing arch/arm/mach-mxs/include/mach/uncompress.h
+Removing arch/arm/mach-mxs/include/mach/timex.h
+Removing arch/arm/mach-mxs/include/mach/mxs.h
+Removing arch/arm/mach-mxs/include/mach/mx28.h
+Removing arch/arm/mach-mxs/include/mach/mx23.h
+Removing arch/arm/mach-mxs/include/mach/hardware.h
+Removing arch/arm/mach-mxs/include/mach/digctl.h
+Removing arch/arm/mach-mxs/include/mach/common.h
+Removing arch/arm/mach-mxs/Makefile.boot
+Auto-merging arch/arm/mach-imx/src.c
+Auto-merging arch/arm/mach-imx/platsmp.c
+Removing arch/arm/mach-imx/mx6q.h
+CONFLICT (modify/delete): arch/arm/mach-imx/cpufreq.c deleted in imx-mxs/for-next and modified in HEAD. Version HEAD of arch/arm/mach-imx/cpufreq.c left in tree.
+Removing arch/arm/mach-imx/cpu_op-mx51.h
+Removing arch/arm/mach-imx/cpu_op-mx51.c
+Auto-merging arch/arm/mach-imx/common.h
+Removing arch/arm/mach-imx/Makefile.boot
+Auto-merging arch/arm/include/debug/mxs.S
+Auto-merging arch/arm/boot/dts/imx6qdl.dtsip
+Auto-merging arch/arm/boot/dts/imx6qdl-sabresd.dtsip
+Auto-merging arch/arm/boot/dts/imx6qdl-sabreauto.dtsip
+Removing arch/arm/boot/dts/imx6q.dtsi
+Auto-merging arch/arm/boot/dts/imx6q-sabrelite.dtsp
+Auto-merging arch/arm/boot/dts/imx6q-arm2.dtsp
+Removing arch/arm/boot/dts/imx6dl.dtsi
+Auto-merging arch/arm/boot/dts/imx53.dtsip
+Auto-merging arch/arm/boot/dts/imx53-tqma53.dtsip
+Auto-merging arch/arm/boot/dts/imx53-smd.dtsp
+Auto-merging arch/arm/boot/dts/imx53-qsb.dtsp
+Removing arch/arm/boot/dts/imx53-mba53.dts
+Auto-merging arch/arm/boot/dts/imx53-evk.dtsp
+Auto-merging arch/arm/boot/dts/imx53-ard.dtsp
+Auto-merging arch/arm/boot/dts/imx51.dtsip
+Auto-merging arch/arm/boot/dts/imx51-babbage.dtsp
+Auto-merging arch/arm/boot/dts/imx51-apf51.dtsp
+Auto-merging arch/arm/boot/dts/imx31.dtsip
+Auto-merging arch/arm/boot/dts/imx31-bug.dtsp
+Auto-merging arch/arm/boot/dts/imx27.dtsip
+Auto-merging arch/arm/boot/dts/imx27-phytec-phycore.dtsp
+Auto-merging arch/arm/boot/dts/imx27-pdk.dtsp
+Auto-merging arch/arm/boot/dts/imx27-apf27.dtsp
+Auto-merging arch/arm/boot/dts/imx25.dtsip
+Auto-merging arch/arm/boot/dts/imx25-pdk.dtsp
+Auto-merging arch/arm/boot/dts/imx25-karo-tx25.dtsp
+Auto-merging arch/arm/boot/dts/Makefile
+Auto-merging arch/arm/Kconfig.debug
+CONFLICT (content): Merge conflict in arch/arm/Kconfig.debug
+Auto-merging arch/arm/Kconfig
+Automatic merge failed; fix conflicts and then commit the result.
+$ git rm -f arch/arm/mach-imx/cpufreq.c
+arch/arm/mach-imx/cpufreq.c: needs merge
+rm 'arch/arm/mach-imx/cpufreq.c'
+$ git commit -v -a
+Recorded resolution for 'drivers/pinctrl/Makefile'.
+[master 0c12472] Merge remote-tracking branch 'imx-mxs/for-next'
+$ git diff -M --stat --summary HEAD^..
+ .../devicetree/bindings/clock/imx27-clock.txt      |  117 +
+ .../devicetree/bindings/clock/imx5-clock.txt       |   13 +
+ .../devicetree/bindings/clock/imx6q-clock.txt      |    3 +
+ .../devicetree/bindings/dma/fsl-mxs-dma.txt        |   49 +-
+ Documentation/devicetree/bindings/fb/mxsfb.txt     |   34 +
+ Documentation/devicetree/bindings/i2c/i2c-mxs.txt  |   12 +-
+ Documentation/devicetree/bindings/mmc/mxs-mmc.txt  |   12 +-
+ .../devicetree/bindings/mtd/gpmi-nand.txt          |   17 +-
+ .../bindings/pinctrl/fsl,imx-pinctrl.txt           |    6 +-
+ .../bindings/pinctrl/fsl,imx35-pinctrl.txt         |  955 +--------
+ .../bindings/pinctrl/fsl,imx51-pinctrl.txt         |  759 +------
+ .../bindings/pinctrl/fsl,imx53-pinctrl.txt         | 1174 +---------
+ .../bindings/pinctrl/fsl,imx6dl-pinctrl.txt        |   38 +
+ .../bindings/pinctrl/fsl,imx6q-pinctrl.txt         | 1596 +-------------
+ .../bindings/pinctrl/fsl,imx6sl-pinctrl.txt        |   39 +
+ .../bindings/pinctrl/fsl,mxs-pinctrl.txt           |    4 +
+ .../devicetree/bindings/reset/fsl,imx-src.txt      |   49 +
+ .../devicetree/bindings/reset/gpio-reset.txt       |   37 +
+ Documentation/devicetree/bindings/reset/reset.txt  |   75 +
+ Documentation/devicetree/bindings/spi/mxs-spi.txt  |   12 +-
+ .../bindings/staging/imx-drm/fsl-imx-drm.txt       |    3 +
+ .../devicetree/bindings/timer/fsl,imxgpt.txt       |   18 +
+ .../bindings/tty/serial/fsl-mxs-auart.txt          |   16 +-
+ arch/arm/Kconfig                                   |   22 -
+ arch/arm/Kconfig.debug                             |    5 +-
+ arch/arm/boot/dts/Makefile                         |    8 +-
+ arch/arm/boot/dts/imx23-evk.dts                    |   25 +
+ arch/arm/boot/dts/imx23.dtsi                       |   47 +-
+ .../{imx25-karo-tx25.dts => imx25-karo-tx25.dtsp}  |    2 +-
+ .../arm/boot/dts/{imx25-pdk.dts => imx25-pdk.dtsp} |    2 +-
+ arch/arm/boot/dts/{imx25.dtsi => imx25.dtsip}      |    2 +-
+ .../boot/dts/{imx27-apf27.dts => imx27-apf27.dtsp} |    2 +-
+ arch/arm/boot/dts/imx27-apf27dev.dtsp              |   60 +
+ .../arm/boot/dts/{imx27-pdk.dts => imx27-pdk.dtsp} |    2 +-
+ ...hytec-phycore.dts => imx27-phytec-phycore.dtsp} |    2 +-
+ arch/arm/boot/dts/{imx27.dtsi => imx27.dtsip}      |   82 +-
+ arch/arm/boot/dts/imx28-apf28dev.dts               |   25 +
+ arch/arm/boot/dts/imx28-apx4devkit.dts             |   25 +
+ arch/arm/boot/dts/imx28-cfa10049.dts               |   45 +-
+ arch/arm/boot/dts/imx28-evk.dts                    |   25 +
+ arch/arm/boot/dts/imx28-m28evk.dts                 |   27 +
+ arch/arm/boot/dts/imx28.dtsi                       |   67 +-
+ .../arm/boot/dts/{imx31-bug.dts => imx31-bug.dtsp} |    2 +-
+ arch/arm/boot/dts/{imx31.dtsi => imx31.dtsip}      |   18 +-
+ arch/arm/boot/dts/imx35-pinfunc.h                  |  970 +++++++++
+ .../boot/dts/{imx51-apf51.dts => imx51-apf51.dtsp} |    2 +-
+ arch/arm/boot/dts/imx51-apf51dev.dtsp              |   97 +
+ .../dts/{imx51-babbage.dts => imx51-babbage.dtsp}  |   16 +-
+ arch/arm/boot/dts/imx51-pinfunc.h                  |  773 +++++++
+ arch/arm/boot/dts/{imx51.dtsi => imx51.dtsip}      |  325 +--
+ .../arm/boot/dts/{imx53-ard.dts => imx53-ard.dtsp} |   70 +-
+ .../arm/boot/dts/{imx53-evk.dts => imx53-evk.dtsp} |   18 +-
+ arch/arm/boot/dts/imx53-mba53.dts                  |  129 --
+ arch/arm/boot/dts/imx53-mba53.dtsp                 |  135 ++
+ arch/arm/boot/dts/imx53-pinfunc.h                  | 1189 ++++++++++
+ .../arm/boot/dts/{imx53-qsb.dts => imx53-qsb.dtsp} |   22 +-
+ .../arm/boot/dts/{imx53-smd.dts => imx53-smd.dtsp} |   16 +-
+ .../dts/{imx53-tqma53.dtsi => imx53-tqma53.dtsip}  |   32 +-
+ arch/arm/boot/dts/{imx53.dtsi => imx53.dtsip}      |  256 ++-
+ arch/arm/boot/dts/imx6dl-pinfunc.h                 | 1085 ++++++++++
+ arch/arm/boot/dts/imx6dl-sabreauto.dtsp            |   31 +
+ arch/arm/boot/dts/imx6dl-sabresd.dtsp              |   35 +
+ arch/arm/boot/dts/imx6dl-wandboard.dtsp            |   40 +
+ arch/arm/boot/dts/imx6dl.dtsi                      |   59 -
+ arch/arm/boot/dts/imx6dl.dtsip                     |  182 ++
+ .../boot/dts/{imx6q-arm2.dts => imx6q-arm2.dtsp}   |    8 +-
+ arch/arm/boot/dts/imx6q-pinfunc.h                  | 1529 +++++++++++++
+ arch/arm/boot/dts/imx6q-sabreauto.dtsp             |   35 +
+ .../{imx6q-sabrelite.dts => imx6q-sabrelite.dtsp}  |   18 +-
+ arch/arm/boot/dts/imx6q-sabresd.dtsp               |   39 +
+ arch/arm/boot/dts/imx6q-sbc6x.dtsp                 |   44 +
+ arch/arm/boot/dts/imx6q.dtsi                       |  296 ---
+ arch/arm/boot/dts/imx6q.dtsip                      |  358 ++++
+ ...imx6q-sabreauto.dts => imx6qdl-sabreauto.dtsip} |   28 +-
+ .../{imx6q-sabresd.dts => imx6qdl-sabresd.dtsip}   |   51 +-
+ arch/arm/boot/dts/{imx6qdl.dtsi => imx6qdl.dtsip}  |   41 +-
+ arch/arm/boot/dts/imx6sl-pinfunc.h                 | 1077 ++++++++++
+ arch/arm/configs/imx_v4_v5_defconfig               |    1 +
+ arch/arm/configs/imx_v6_v7_defconfig               |    1 +
+ arch/arm/configs/mxs_defconfig                     |    7 +-
+ .../mach/debug-macro.S => include/debug/mxs.S}     |    9 +-
+ arch/arm/mach-imx/Kconfig                          |   12 +-
+ arch/arm/mach-imx/Makefile                         |    4 +-
+ arch/arm/mach-imx/Makefile.boot                    |   35 -
+ arch/arm/mach-imx/anatop.c                         |  103 +
+ arch/arm/mach-imx/avic.c                           |    6 +-
+ arch/arm/mach-imx/clk-busy.c                       |    2 +-
+ arch/arm/mach-imx/clk-gate2.c                      |    1 +
+ arch/arm/mach-imx/clk-imx27.c                      |   13 +-
+ arch/arm/mach-imx/clk-imx51-imx53.c                |   67 +-
+ arch/arm/mach-imx/clk-imx6q.c                      |  128 +-
+ arch/arm/mach-imx/clk-pllv1.c                      |    2 +-
+ arch/arm/mach-imx/clk-pllv2.c                      |    2 +-
+ arch/arm/mach-imx/clk.c                            |    1 +
+ arch/arm/mach-imx/clk.h                            |   17 +
+ arch/arm/mach-imx/common.h                         |   13 +-
+ arch/arm/mach-imx/cpu-imx5.c                       |    1 +
+ arch/arm/mach-imx/cpu.c                            |    1 +
+ arch/arm/mach-imx/cpu_op-mx51.c                    |   31 -
+ arch/arm/mach-imx/cpu_op-mx51.h                    |   14 -
+ arch/arm/mach-imx/cpufreq.c                        |  202 --
+ arch/arm/mach-imx/eukrea_mbimx27-baseboard.c       |    4 +-
+ arch/arm/mach-imx/gpc.c                            |   24 +-
+ arch/arm/mach-imx/hardware.h                       |    1 -
+ arch/arm/mach-imx/imx27-dt.c                       |   22 +-
+ arch/arm/mach-imx/imx51-dt.c                       |    3 +
+ arch/arm/mach-imx/iomux-imx31.c                    |    2 +-
+ arch/arm/mach-imx/irq-common.c                     |   19 -
+ arch/arm/mach-imx/mach-cpuimx27.c                  |    4 +-
+ arch/arm/mach-imx/mach-cpuimx51sd.c                |    5 -
+ arch/arm/mach-imx/mach-imx6q.c                     |   78 +-
+ arch/arm/mach-imx/mach-mx51_babbage.c              |    4 -
+ arch/arm/mach-imx/mm-imx1.c                        |    2 +
+ arch/arm/mach-imx/mm-imx3.c                        |    2 +-
+ arch/arm/mach-imx/mm-imx5.c                        |    2 +
+ arch/arm/mach-imx/mx6q.h                           |   31 -
+ arch/arm/mach-imx/mxc.h                            |   11 +
+ arch/arm/mach-imx/platsmp.c                        |    4 +-
+ arch/arm/mach-imx/pm-imx6q.c                       |    4 +-
+ arch/arm/mach-imx/src.c                            |   70 +-
+ arch/arm/mach-imx/tzic.c                           |    2 +-
+ arch/arm/mach-mxs/Kconfig                          |   24 +-
+ arch/arm/mach-mxs/Makefile                         |    6 +-
+ arch/arm/mach-mxs/Makefile.boot                    |    1 -
+ arch/arm/mach-mxs/include/mach/common.h            |   29 -
+ arch/arm/mach-mxs/include/mach/digctl.h            |   22 -
+ arch/arm/mach-mxs/include/mach/hardware.h          |   23 -
+ arch/arm/mach-mxs/include/mach/mx23.h              |  169 --
+ arch/arm/mach-mxs/include/mach/mx28.h              |  225 --
+ arch/arm/mach-mxs/include/mach/mxs.h               |  117 -
+ arch/arm/mach-mxs/include/mach/timex.h             |   21 -
+ arch/arm/mach-mxs/include/mach/uncompress.h        |   76 -
+ arch/arm/mach-mxs/mach-mxs.c                       |  346 ++-
+ arch/arm/mach-mxs/mm.c                             |   52 -
+ arch/arm/mach-mxs/ocotp.c                          |   93 -
+ arch/arm/mach-mxs/pm.c                             |    4 +-
+ arch/arm/mach-mxs/pm.h                             |   14 +
+ arch/arm/mach-mxs/system.c                         |  139 --
+ drivers/Kconfig                                    |    2 +
+ drivers/Makefile                                   |    3 +
+ drivers/clk/mxs/clk-imx23.c                        |   42 +-
+ drivers/clk/mxs/clk-imx28.c                        |   42 +-
+ drivers/clocksource/Makefile                       |    1 +
+ .../timer.c => drivers/clocksource/mxs_timer.c     |   36 +-
+ drivers/dma/mxs-dma.c                              |  109 +-
+ drivers/i2c/busses/i2c-mxs.c                       |   40 +-
+ drivers/irqchip/Makefile                           |    1 +
+ .../mach-mxs/icoll.c => drivers/irqchip/irq-mxs.c  |   24 +-
+ drivers/mmc/host/mxs-mmc.c                         |   48 +-
+ drivers/mtd/nand/gpmi-nand/gpmi-nand.c             |   51 +-
+ drivers/mtd/nand/gpmi-nand/gpmi-nand.h             |    3 +-
+ drivers/net/ethernet/freescale/fec.h               |    1 +
+ drivers/net/ethernet/freescale/fec_main.c          |   18 +-
+ drivers/pinctrl/Kconfig                            |   12 +-
+ drivers/pinctrl/Makefile                           |    1 +
+ drivers/pinctrl/pinctrl-imx.c                      |  120 +-
+ drivers/pinctrl/pinctrl-imx.h                      |   13 +-
+ drivers/pinctrl/pinctrl-imx35.c                    | 1524 +++----------
+ drivers/pinctrl/pinctrl-imx51.c                    | 1252 +++--------
+ drivers/pinctrl/pinctrl-imx53.c                    | 1579 ++------------
+ drivers/pinctrl/pinctrl-imx6dl.c                   |  459 ++++
+ drivers/pinctrl/pinctrl-imx6q.c                    | 2263 +++-----------------
+ drivers/pinctrl/pinctrl-imx6sl.c                   |  365 ++++
+ drivers/reset/Kconfig                              |   26 +
+ drivers/reset/Makefile                             |    2 +
+ drivers/reset/core.c                               |  297 +++
+ drivers/reset/gpio-reset.c                         |  208 ++
+ drivers/rtc/rtc-stmp3xxx.c                         |    6 +-
+ drivers/spi/spi-mxs.c                              |   60 +-
+ drivers/staging/iio/adc/mxs-lradc.c                |    3 -
+ drivers/staging/imx-drm/ipu-v3/ipu-common.c        |   12 +-
+ drivers/tty/serial/mxs-auart.c                     |   52 +-
+ drivers/video/Kconfig                              |    2 +
+ drivers/video/mxsfb.c                              |  221 +-
+ include/linux/clk/mxs.h                            |   16 +
+ include/linux/irqchip/mxs.h                        |   14 +
+ include/linux/mxsfb.h                              |   52 -
+ include/linux/reset-controller.h                   |   51 +
+ include/linux/reset.h                              |   17 +
+ include/linux/spi/mxs-spi.h                        |    4 +-
+ sound/soc/mxs/mxs-saif.c                           |    5 +-
+ 181 files changed, 12632 insertions(+), 13292 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/clock/imx27-clock.txt
+ create mode 100644 Documentation/devicetree/bindings/pinctrl/fsl,imx6dl-pinctrl.txt
+ create mode 100644 Documentation/devicetree/bindings/pinctrl/fsl,imx6sl-pinctrl.txt
+ create mode 100644 Documentation/devicetree/bindings/reset/fsl,imx-src.txt
+ create mode 100644 Documentation/devicetree/bindings/reset/gpio-reset.txt
+ create mode 100644 Documentation/devicetree/bindings/reset/reset.txt
+ create mode 100644 Documentation/devicetree/bindings/timer/fsl,imxgpt.txt
+ rename arch/arm/boot/dts/{imx25-karo-tx25.dts => imx25-karo-tx25.dtsp} (96%)
+ rename arch/arm/boot/dts/{imx25-pdk.dts => imx25-pdk.dtsp} (96%)
+ rename arch/arm/boot/dts/{imx25.dtsi => imx25.dtsip} (99%)
+ rename arch/arm/boot/dts/{imx27-apf27.dts => imx27-apf27.dtsp} (98%)
+ create mode 100644 arch/arm/boot/dts/imx27-apf27dev.dtsp
+ rename arch/arm/boot/dts/{imx27-pdk.dts => imx27-pdk.dtsp} (96%)
+ rename arch/arm/boot/dts/{imx27-phytec-phycore.dts => imx27-phytec-phycore.dtsp} (98%)
+ rename arch/arm/boot/dts/{imx27.dtsi => imx27.dtsip} (70%)
+ rename arch/arm/boot/dts/{imx31-bug.dts => imx31-bug.dtsp} (96%)
+ rename arch/arm/boot/dts/{imx31.dtsi => imx31.dtsip} (86%)
+ create mode 100644 arch/arm/boot/dts/imx35-pinfunc.h
+ rename arch/arm/boot/dts/{imx51-apf51.dts => imx51-apf51.dtsp} (97%)
+ create mode 100644 arch/arm/boot/dts/imx51-apf51dev.dtsp
+ rename arch/arm/boot/dts/{imx51-babbage.dts => imx51-babbage.dtsp} (94%)
+ create mode 100644 arch/arm/boot/dts/imx51-pinfunc.h
+ rename arch/arm/boot/dts/{imx51.dtsi => imx51.dtsip} (56%)
+ rename arch/arm/boot/dts/{imx53-ard.dts => imx53-ard.dtsp} (55%)
+ rename arch/arm/boot/dts/{imx53-evk.dts => imx53-evk.dtsp} (82%)
+ delete mode 100644 arch/arm/boot/dts/imx53-mba53.dts
+ create mode 100644 arch/arm/boot/dts/imx53-mba53.dtsp
+ create mode 100644 arch/arm/boot/dts/imx53-pinfunc.h
+ rename arch/arm/boot/dts/{imx53-qsb.dts => imx53-qsb.dtsp} (89%)
+ rename arch/arm/boot/dts/{imx53-smd.dts => imx53-smd.dtsp} (88%)
+ rename arch/arm/boot/dts/{imx53-tqma53.dtsi => imx53-tqma53.dtsip} (75%)
+ rename arch/arm/boot/dts/{imx53.dtsi => imx53.dtsip} (69%)
+ create mode 100644 arch/arm/boot/dts/imx6dl-pinfunc.h
+ create mode 100644 arch/arm/boot/dts/imx6dl-sabreauto.dtsp
+ create mode 100644 arch/arm/boot/dts/imx6dl-sabresd.dtsp
+ create mode 100644 arch/arm/boot/dts/imx6dl-wandboard.dtsp
+ delete mode 100644 arch/arm/boot/dts/imx6dl.dtsi
+ create mode 100644 arch/arm/boot/dts/imx6dl.dtsip
+ rename arch/arm/boot/dts/{imx6q-arm2.dts => imx6q-arm2.dtsp} (90%)
+ create mode 100644 arch/arm/boot/dts/imx6q-pinfunc.h
+ create mode 100644 arch/arm/boot/dts/imx6q-sabreauto.dtsp
+ rename arch/arm/boot/dts/{imx6q-sabrelite.dts => imx6q-sabrelite.dtsp} (87%)
+ create mode 100644 arch/arm/boot/dts/imx6q-sabresd.dtsp
+ create mode 100644 arch/arm/boot/dts/imx6q-sbc6x.dtsp
+ delete mode 100644 arch/arm/boot/dts/imx6q.dtsi
+ create mode 100644 arch/arm/boot/dts/imx6q.dtsip
+ rename arch/arm/boot/dts/{imx6q-sabreauto.dts => imx6qdl-sabreauto.dtsip} (66%)
+ rename arch/arm/boot/dts/{imx6q-sabresd.dts => imx6qdl-sabresd.dtsip} (69%)
+ rename arch/arm/boot/dts/{imx6qdl.dtsi => imx6qdl.dtsip} (95%)
+ create mode 100644 arch/arm/boot/dts/imx6sl-pinfunc.h
+ rename arch/arm/{mach-mxs/include/mach/debug-macro.S => include/debug/mxs.S} (77%)
+ delete mode 100644 arch/arm/mach-imx/Makefile.boot
+ create mode 100644 arch/arm/mach-imx/anatop.c
+ delete mode 100644 arch/arm/mach-imx/cpu_op-mx51.c
+ delete mode 100644 arch/arm/mach-imx/cpu_op-mx51.h
+ delete mode 100644 arch/arm/mach-imx/cpufreq.c
+ delete mode 100644 arch/arm/mach-imx/mx6q.h
+ delete mode 100644 arch/arm/mach-mxs/Makefile.boot
+ delete mode 100644 arch/arm/mach-mxs/include/mach/common.h
+ delete mode 100644 arch/arm/mach-mxs/include/mach/digctl.h
+ delete mode 100644 arch/arm/mach-mxs/include/mach/hardware.h
+ delete mode 100644 arch/arm/mach-mxs/include/mach/mx23.h
+ delete mode 100644 arch/arm/mach-mxs/include/mach/mx28.h
+ delete mode 100644 arch/arm/mach-mxs/include/mach/mxs.h
+ delete mode 100644 arch/arm/mach-mxs/include/mach/timex.h
+ delete mode 100644 arch/arm/mach-mxs/include/mach/uncompress.h
+ delete mode 100644 arch/arm/mach-mxs/mm.c
+ delete mode 100644 arch/arm/mach-mxs/ocotp.c
+ create mode 100644 arch/arm/mach-mxs/pm.h
+ delete mode 100644 arch/arm/mach-mxs/system.c
+ rename arch/arm/mach-mxs/timer.c => drivers/clocksource/mxs_timer.c (91%)
+ rename arch/arm/mach-mxs/icoll.c => drivers/irqchip/irq-mxs.c (89%)
+ create mode 100644 drivers/pinctrl/pinctrl-imx6dl.c
+ create mode 100644 drivers/pinctrl/pinctrl-imx6sl.c
+ create mode 100644 drivers/reset/Kconfig
+ create mode 100644 drivers/reset/Makefile
+ create mode 100644 drivers/reset/core.c
+ create mode 100644 drivers/reset/gpio-reset.c
+ create mode 100644 include/linux/clk/mxs.h
+ create mode 100644 include/linux/irqchip/mxs.h
+ delete mode 100644 include/linux/mxsfb.h
+ create mode 100644 include/linux/reset-controller.h
+ create mode 100644 include/linux/reset.h
+Merging ixp4xx/next (19f949f Linux 3.8)
+$ git merge ixp4xx/next
+Already up-to-date.
+Merging msm/for-next (d0f6e50 Merge branch 'msm-defconfig' into for-next)
+$ git merge msm/for-next
+Removing arch/arm/mach-msm/include/mach/cpu.h
+Auto-merging arch/arm/boot/dts/msm8960-cdp.dts
+Auto-merging arch/arm/boot/dts/msm8660-surf.dts
+Merge made by the 'recursive' strategy.
+ .../devicetree/bindings/arm/msm/timer.txt          |  41 ++--
+ arch/arm/boot/dts/msm8660-surf.dts                 |  20 +-
+ arch/arm/boot/dts/msm8960-cdp.dts                  |  22 +--
+ arch/arm/configs/msm_defconfig                     | 154 ++++++++++-----
+ arch/arm/mach-msm/board-halibut.c                  |   1 +
+ arch/arm/mach-msm/board-msm7x30.c                  |   1 +
+ arch/arm/mach-msm/board-qsd8x50.c                  |   1 +
+ arch/arm/mach-msm/board-trout.c                    |   1 +
+ arch/arm/mach-msm/devices-msm7x00.c                |  31 +++
+ arch/arm/mach-msm/devices-msm7x30.c                |  31 +++
+ arch/arm/mach-msm/devices-qsd8x50.c                |  31 +++
+ arch/arm/mach-msm/devices.h                        |   4 +
+ arch/arm/mach-msm/dma.c                            |  26 +++
+ arch/arm/mach-msm/include/mach/cpu.h               |  54 -----
+ arch/arm/mach-msm/include/mach/dma.h               |  26 ---
+ arch/arm/mach-msm/timer.c                          | 110 +++++------
+ drivers/gpio/gpio-msm-v1.c                         | 220 ++++++++++++++-------
+ drivers/mmc/host/msm_sdcc.c                        |   1 -
+ 18 files changed, 471 insertions(+), 304 deletions(-)
+ delete mode 100644 arch/arm/mach-msm/include/mach/cpu.h
+Merging renesas/next (88105d4 Merge branches 'heads/soc', 'heads/soc-r8a7779', 'heads/defconfig-kzm9g', 'heads/defconfig-bockw', 'heads/boards-bockw', 'heads/clocksource' and 'heads/fbdev-fixes' into next)
+$ git merge renesas/next
+Merge made by the 'recursive' strategy.
+ arch/arm/boot/dts/r8a7778-bockw.dts           |  2 +-
+ arch/arm/configs/bockw_defconfig              | 34 +++++++++++--
+ arch/arm/configs/kzm9g_defconfig              |  3 ++
+ arch/arm/mach-shmobile/Kconfig                |  1 +
+ arch/arm/mach-shmobile/board-bockw.c          | 38 +++++++++++++++
+ arch/arm/mach-shmobile/clock-r8a7779.c        | 19 ++++++++
+ arch/arm/mach-shmobile/include/mach/clock.h   |  4 +-
+ arch/arm/mach-shmobile/include/mach/r8a7778.h |  1 +
+ arch/arm/mach-shmobile/setup-r8a7778.c        | 70 ++++++++++++++++++++-------
+ 9 files changed, 149 insertions(+), 23 deletions(-)
+Merging samsung/for-next (9cc97ce Merge branch 'next/mct-exynos' into for-next)
+$ git merge samsung/for-next
+Recorded preimage for 'drivers/clocksource/Makefile'
+Recorded preimage for 'drivers/irqchip/Makefile'
+Recorded preimage for 'drivers/irqchip/irq-s3c24xx.c'
+Auto-merging drivers/irqchip/irq-s3c24xx.c
+CONFLICT (content): Merge conflict in drivers/irqchip/irq-s3c24xx.c
+Auto-merging drivers/irqchip/exynos-combiner.c
+Auto-merging drivers/irqchip/Makefile
+CONFLICT (content): Merge conflict in drivers/irqchip/Makefile
+Auto-merging drivers/clocksource/exynos_mct.c
+Auto-merging drivers/clocksource/Makefile
+CONFLICT (content): Merge conflict in drivers/clocksource/Makefile
+Auto-merging drivers/clocksource/Kconfig
+Auto-merging arch/arm/plat-samsung/devs.c
+Removing arch/arm/mach-s3c24xx/include/mach/entry-macro.S
+Auto-merging arch/arm/mach-exynos/platsmp.c
+Auto-merging arch/arm/mach-exynos/mach-nuri.c
+Removing arch/arm/mach-exynos/include/mach/regs-mct.h
+Auto-merging arch/arm/mach-exynos/common.c
+Removing arch/arm/mach-exynos/clock-exynos5.c
+Removing arch/arm/mach-exynos/clock-exynos4212.c
+Removing arch/arm/mach-exynos/clock-exynos4210.c
+Removing arch/arm/mach-exynos/clock-exynos4.h
+Removing arch/arm/mach-exynos/clock-exynos4.c
+Auto-merging arch/arm/boot/dts/Makefile
+Auto-merging arch/arm/Kconfig
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+Recorded resolution for 'drivers/clocksource/Makefile'.
+Recorded resolution for 'drivers/irqchip/Makefile'.
+Recorded resolution for 'drivers/irqchip/irq-s3c24xx.c'.
+[master 0e6a28e] Merge remote-tracking branch 'samsung/for-next'
+$ git diff -M --stat --summary HEAD^..
+ Documentation/arm/firmware.txt                     |   88 ++
+ .../devicetree/bindings/arm/samsung-boards.txt     |   10 +
+ .../devicetree/bindings/arm/samsung/sysreg.txt     |    7 +
+ .../devicetree/bindings/clock/exynos4-clock.txt    |  274 ++++
+ .../devicetree/bindings/clock/exynos5250-clock.txt |  177 +++
+ .../devicetree/bindings/clock/exynos5440-clock.txt |   61 +
+ .../devicetree/bindings/gpu/samsung-g2d.txt        |   20 +
+ .../interrupt-controller/samsung,s3c24xx-irq.txt   |   53 +
+ .../devicetree/bindings/media/s5p-mfc.txt          |   21 +
+ .../bindings/timer/samsung,exynos4210-mct.txt      |   68 +
+ .../devicetree/bindings/usb/exynos-usb.txt         |   50 +
+ arch/arm/Kconfig                                   |    9 +-
+ arch/arm/boot/dts/Makefile                         |    3 +
+ arch/arm/boot/dts/cros5250-common.dtsi             |  189 ++-
+ arch/arm/boot/dts/exynos4.dtsi                     |   73 +
+ arch/arm/boot/dts/exynos4210-origen.dts            |   22 +
+ arch/arm/boot/dts/exynos4210-smdkv310.dts          |   75 +-
+ arch/arm/boot/dts/exynos4210-trats.dts             |   12 +
+ arch/arm/boot/dts/exynos4210.dtsi                  |   43 +
+ arch/arm/boot/dts/exynos4212.dtsi                  |   22 +
+ arch/arm/boot/dts/exynos4412-odroidx.dts           |  109 ++
+ arch/arm/boot/dts/exynos4412-origen.dts            |  430 +++++
+ arch/arm/boot/dts/exynos4412-smdk4412.dts          |   33 +
+ arch/arm/boot/dts/exynos4412.dtsi                  |   26 +
+ arch/arm/boot/dts/exynos4x12.dtsi                  |   13 +
+ arch/arm/boot/dts/exynos5250-arndale.dts           |  452 ++++++
+ arch/arm/boot/dts/exynos5250-pinctrl.dtsi          |  783 ++++++++++
+ arch/arm/boot/dts/exynos5250-smdk5250.dts          |   68 +-
+ arch/arm/boot/dts/exynos5250-snow.dts              |   33 +-
+ arch/arm/boot/dts/exynos5250.dtsi                  |  489 +++---
+ arch/arm/boot/dts/exynos5440-ssdk5440.dts          |   19 +-
+ arch/arm/boot/dts/exynos5440.dtsi                  |   72 +-
+ arch/arm/common/Makefile                           |    2 +
+ arch/arm/common/firmware.c                         |   18 +
+ arch/arm/include/asm/firmware.h                    |   66 +
+ arch/arm/mach-exynos/Kconfig                       |   13 +-
+ arch/arm/mach-exynos/Makefile                      |   12 +-
+ arch/arm/mach-exynos/clock-exynos4.c               | 1601 -------------------
+ arch/arm/mach-exynos/clock-exynos4.h               |   35 -
+ arch/arm/mach-exynos/clock-exynos4210.c            |  187 ---
+ arch/arm/mach-exynos/clock-exynos4212.c            |  201 ---
+ arch/arm/mach-exynos/clock-exynos5.c               | 1645 --------------------
+ arch/arm/mach-exynos/common.c                      |  121 +-
+ arch/arm/mach-exynos/common.h                      |   12 +-
+ arch/arm/mach-exynos/cpuidle.c                     |   58 +-
+ arch/arm/mach-exynos/exynos-smc.S                  |   22 +
+ arch/arm/mach-exynos/firmware.c                    |   70 +
+ arch/arm/mach-exynos/include/mach/irqs.h           |   19 +-
+ arch/arm/mach-exynos/include/mach/map.h            |    4 +-
+ arch/arm/mach-exynos/include/mach/pm-core.h        |    9 +-
+ arch/arm/mach-exynos/include/mach/regs-clock.h     |  107 --
+ arch/arm/mach-exynos/include/mach/regs-mct.h       |   53 -
+ arch/arm/mach-exynos/mach-armlex4210.c             |    3 +-
+ arch/arm/mach-exynos/mach-exynos4-dt.c             |  123 +-
+ arch/arm/mach-exynos/mach-exynos5-dt.c             |  141 +-
+ arch/arm/mach-exynos/mach-nuri.c                   |    5 +-
+ arch/arm/mach-exynos/mach-origen.c                 |    5 +-
+ arch/arm/mach-exynos/mach-smdk4x12.c               |    5 +-
+ arch/arm/mach-exynos/mach-smdkv310.c               |    7 +-
+ arch/arm/mach-exynos/mach-universal_c210.c         |    3 +-
+ arch/arm/mach-exynos/platsmp.c                     |   32 +-
+ arch/arm/mach-exynos/smc.h                         |   31 +
+ arch/arm/mach-s3c24xx/Kconfig                      |   22 +-
+ arch/arm/mach-s3c24xx/Makefile                     |    2 +-
+ arch/arm/mach-s3c24xx/common.h                     |    1 +
+ arch/arm/mach-s3c24xx/include/mach/entry-macro.S   |   70 -
+ arch/arm/mach-s3c24xx/mach-amlm5900.c              |    2 +-
+ arch/arm/mach-s3c24xx/mach-bast.c                  |    2 +-
+ arch/arm/mach-s3c24xx/mach-h1940.c                 |    7 +-
+ arch/arm/mach-s3c24xx/mach-n30.c                   |    4 +-
+ arch/arm/mach-s3c24xx/mach-otom.c                  |    2 +-
+ arch/arm/mach-s3c24xx/mach-qt2410.c                |    2 +-
+ arch/arm/mach-s3c24xx/mach-smdk2410.c              |    2 +-
+ arch/arm/mach-s3c24xx/mach-tct_hammer.c            |    2 +-
+ arch/arm/mach-s3c24xx/mach-vr1000.c                |    2 +-
+ arch/arm/mach-s3c64xx/Makefile                     |    1 -
+ arch/arm/mach-s3c64xx/dma.c                        |    1 +
+ arch/arm/mach-s3c64xx/mach-crag6410-module.c       |    1 +
+ arch/arm/plat-samsung/Kconfig                      |   18 +-
+ arch/arm/plat-samsung/devs.c                       |    2 +-
+ arch/arm/plat-samsung/include/plat/cpu.h           |    1 -
+ arch/arm/plat-samsung/include/plat/map-s5p.h       |    1 +
+ arch/arm/plat-samsung/include/plat/rtc-core.h      |    2 +-
+ arch/arm/plat-samsung/include/plat/sdhci.h         |    4 +-
+ arch/arm/plat-samsung/s5p-sleep.S                  |    9 +
+ arch/arm/plat-samsung/setup-mipiphy.c              |    3 +
+ drivers/clk/Makefile                               |    1 +
+ drivers/clk/samsung/Makefile                       |    8 +
+ drivers/clk/samsung/clk-exynos4.c                  | 1085 +++++++++++++
+ drivers/clk/samsung/clk-exynos5250.c               |  523 +++++++
+ drivers/clk/samsung/clk-exynos5440.c               |  139 ++
+ drivers/clk/samsung/clk-pll.c                      |  419 +++++
+ drivers/clk/samsung/clk-pll.h                      |   41 +
+ drivers/clk/samsung/clk.c                          |  318 ++++
+ drivers/clk/samsung/clk.h                          |  289 ++++
+ drivers/clocksource/Kconfig                        |    5 +
+ drivers/clocksource/Makefile                       |    1 +
+ .../mct.c => drivers/clocksource/exynos_mct.c      |  210 ++-
+ drivers/irqchip/Makefile                           |    1 +
+ drivers/irqchip/exynos-combiner.c                  |   80 +-
+ .../irq.c => drivers/irqchip/irq-s3c24xx.c         |  523 +++++--
+ 101 files changed, 7314 insertions(+), 4906 deletions(-)
+ create mode 100644 Documentation/arm/firmware.txt
+ create mode 100644 Documentation/devicetree/bindings/arm/samsung/sysreg.txt
+ create mode 100644 Documentation/devicetree/bindings/clock/exynos4-clock.txt
+ create mode 100644 Documentation/devicetree/bindings/clock/exynos5250-clock.txt
+ create mode 100644 Documentation/devicetree/bindings/clock/exynos5440-clock.txt
+ create mode 100644 Documentation/devicetree/bindings/gpu/samsung-g2d.txt
+ create mode 100644 Documentation/devicetree/bindings/interrupt-controller/samsung,s3c24xx-irq.txt
+ create mode 100644 Documentation/devicetree/bindings/timer/samsung,exynos4210-mct.txt
+ create mode 100644 Documentation/devicetree/bindings/usb/exynos-usb.txt
+ create mode 100644 arch/arm/boot/dts/exynos4412-odroidx.dts
+ create mode 100644 arch/arm/boot/dts/exynos4412-origen.dts
+ create mode 100644 arch/arm/boot/dts/exynos5250-arndale.dts
+ create mode 100644 arch/arm/boot/dts/exynos5250-pinctrl.dtsi
+ create mode 100644 arch/arm/common/firmware.c
+ create mode 100644 arch/arm/include/asm/firmware.h
+ delete mode 100644 arch/arm/mach-exynos/clock-exynos4.c
+ delete mode 100644 arch/arm/mach-exynos/clock-exynos4.h
+ delete mode 100644 arch/arm/mach-exynos/clock-exynos4210.c
+ delete mode 100644 arch/arm/mach-exynos/clock-exynos4212.c
+ delete mode 100644 arch/arm/mach-exynos/clock-exynos5.c
+ create mode 100644 arch/arm/mach-exynos/exynos-smc.S
+ create mode 100644 arch/arm/mach-exynos/firmware.c
+ delete mode 100644 arch/arm/mach-exynos/include/mach/regs-mct.h
+ create mode 100644 arch/arm/mach-exynos/smc.h
+ delete mode 100644 arch/arm/mach-s3c24xx/include/mach/entry-macro.S
+ create mode 100644 drivers/clk/samsung/Makefile
+ create mode 100644 drivers/clk/samsung/clk-exynos4.c
+ create mode 100644 drivers/clk/samsung/clk-exynos5250.c
+ create mode 100644 drivers/clk/samsung/clk-exynos5440.c
+ create mode 100644 drivers/clk/samsung/clk-pll.c
+ create mode 100644 drivers/clk/samsung/clk-pll.h
+ create mode 100644 drivers/clk/samsung/clk.c
+ create mode 100644 drivers/clk/samsung/clk.h
+ rename arch/arm/mach-exynos/mct.c => drivers/clocksource/exynos_mct.c (64%)
+ rename arch/arm/mach-s3c24xx/irq.c => drivers/irqchip/irq-s3c24xx.c (75%)
+Merging tegra/for-next (fe98dc2 Merge branch 'for-3.10/defconfig' into for-next)
+$ git merge tegra/for-next
+Resolved 'arch/arm/mach-tegra/tegra.c' using previous resolution.
+Resolved 'drivers/clocksource/tegra20_timer.c' using previous resolution.
+Auto-merging include/linux/tegra-powergate.h
+Auto-merging drivers/gpio/gpio-tegra.c
+Auto-merging drivers/clocksource/tegra20_timer.c
+CONFLICT (content): Merge conflict in drivers/clocksource/tegra20_timer.c
+Auto-merging drivers/clk/tegra/clk-tegra30.c
+Auto-merging drivers/clk/tegra/clk-tegra20.c
+Auto-merging arch/arm/mach-tegra/tegra.c
+CONFLICT (content): Merge conflict in arch/arm/mach-tegra/tegra.c
+Auto-merging arch/arm/mach-tegra/platsmp.c
+Removing arch/arm/mach-tegra/include/mach/uncompress.h
+Removing arch/arm/mach-tegra/include/mach/timex.h
+Auto-merging arch/arm/mach-tegra/board-harmony-pcie.c
+Removing arch/arm/mach-tegra/board-dt-tegra30.c
+Removing arch/arm/mach-tegra/board-dt-tegra114.c
+Removing arch/arm/mach-tegra/Makefile.boot
+Auto-merging arch/arm/mach-tegra/Kconfig
+Auto-merging arch/arm/boot/dts/tegra30.dtsi
+Auto-merging arch/arm/boot/dts/tegra20.dtsi
+Auto-merging arch/arm/Kconfig
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master bde98e8] Merge remote-tracking branch 'tegra/for-next'
+$ git diff -M --stat --summary HEAD^..
+ .../bindings/arm/tegra/nvidia,tegra20-pmc.txt      |  67 +-
+ .../devicetree/bindings/i2c/nvidia,tegra20-i2c.txt |  60 ++
+ .../bindings/sound/nvidia,tegra-audio-alc5632.txt  |   8 +
+ .../sound/nvidia,tegra-audio-trimslice.txt         |   7 +
+ .../bindings/sound/nvidia,tegra-audio-wm8753.txt   |   8 +
+ .../bindings/sound/nvidia,tegra-audio-wm8903.txt   |   8 +
+ .../bindings/sound/nvidia,tegra-audio-wm9712.txt   |   8 +
+ arch/arm/Kconfig                                   |  18 -
+ arch/arm/boot/dts/tegra114-dalmore.dts             | 904 +++++++++++++++++++++
+ arch/arm/boot/dts/tegra114-pluto.dts               |  13 +
+ arch/arm/boot/dts/tegra114.dtsi                    | 244 +++++-
+ arch/arm/boot/dts/tegra20-colibri-512.dtsi         |  25 +
+ arch/arm/boot/dts/tegra20-harmony.dts              |  33 +
+ arch/arm/boot/dts/tegra20-medcom-wide.dts          |   7 +
+ arch/arm/boot/dts/tegra20-paz00.dts                |  23 +
+ arch/arm/boot/dts/tegra20-plutux.dts               |   3 +
+ arch/arm/boot/dts/tegra20-seaboard.dts             |  24 +
+ arch/arm/boot/dts/tegra20-tamonten.dtsi            |  19 +
+ arch/arm/boot/dts/tegra20-tec.dts                  |   3 +
+ arch/arm/boot/dts/tegra20-trimslice.dts            |  36 +
+ arch/arm/boot/dts/tegra20-ventana.dts              |  35 +
+ arch/arm/boot/dts/tegra20-whistler.dts             |  26 +
+ arch/arm/boot/dts/tegra20.dtsi                     |  57 +-
+ arch/arm/boot/dts/tegra30-beaver.dts               |  21 +
+ arch/arm/boot/dts/tegra30-cardhu-a02.dts           |   1 +
+ arch/arm/boot/dts/tegra30-cardhu-a04.dts           |   1 +
+ arch/arm/boot/dts/tegra30-cardhu.dtsi              |  24 +
+ arch/arm/boot/dts/tegra30.dtsi                     |   7 +-
+ arch/arm/configs/tegra_defconfig                   |  18 +-
+ arch/arm/mach-tegra/Kconfig                        |  27 +-
+ arch/arm/mach-tegra/Makefile                       |   5 +-
+ arch/arm/mach-tegra/Makefile.boot                  |   3 -
+ arch/arm/mach-tegra/board-dt-tegra114.c            |  46 --
+ arch/arm/mach-tegra/board-dt-tegra30.c             |  60 --
+ arch/arm/mach-tegra/board-harmony-pcie.c           |   7 +-
+ arch/arm/mach-tegra/board.h                        |   5 +-
+ arch/arm/mach-tegra/common.c                       |  33 +-
+ arch/arm/mach-tegra/cpuidle-tegra20.c              |   6 +-
+ arch/arm/mach-tegra/cpuidle-tegra30.c              |  10 +-
+ arch/arm/mach-tegra/fuse.c                         |   4 +
+ arch/arm/mach-tegra/fuse.h                         |   7 +
+ arch/arm/mach-tegra/headsmp.S                      |   3 -
+ arch/arm/mach-tegra/hotplug.c                      |  23 +-
+ arch/arm/mach-tegra/include/mach/timex.h           |  26 -
+ arch/arm/mach-tegra/include/mach/uncompress.h      | 175 ----
+ arch/arm/mach-tegra/irq.c                          |  96 ++-
+ arch/arm/mach-tegra/irq.h                          |   6 +
+ arch/arm/mach-tegra/pcie.c                         |   3 +-
+ arch/arm/mach-tegra/platsmp.c                      | 119 ++-
+ arch/arm/mach-tegra/pm.c                           | 158 ++--
+ arch/arm/mach-tegra/pm.h                           |  17 +-
+ arch/arm/mach-tegra/pmc.c                          | 310 ++++++-
+ arch/arm/mach-tegra/pmc.h                          |  18 +
+ arch/arm/mach-tegra/powergate.c                    |   7 +-
+ arch/arm/mach-tegra/reset-handler.S                |  48 +-
+ arch/arm/mach-tegra/sleep.h                        |  10 +-
+ .../arm/mach-tegra/{board-dt-tegra20.c => tegra.c} |  45 +-
+ arch/arm/mach-tegra/tegra114_speedo.c              | 104 +++
+ drivers/clk/tegra/clk-periph-gate.c                |   2 +-
+ drivers/clk/tegra/clk-periph.c                     |   3 +
+ drivers/clk/tegra/clk-tegra20.c                    |  38 +-
+ drivers/clk/tegra/clk-tegra30.c                    |   5 +-
+ drivers/clocksource/tegra20_timer.c                |   4 +-
+ drivers/gpio/gpio-tegra.c                          |  21 +-
+ .../powergate.h => include/linux/tegra-powergate.h |   5 -
+ 65 files changed, 2484 insertions(+), 683 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/i2c/nvidia,tegra20-i2c.txt
+ delete mode 100644 arch/arm/mach-tegra/Makefile.boot
+ delete mode 100644 arch/arm/mach-tegra/board-dt-tegra114.c
+ delete mode 100644 arch/arm/mach-tegra/board-dt-tegra30.c
+ delete mode 100644 arch/arm/mach-tegra/include/mach/timex.h
+ delete mode 100644 arch/arm/mach-tegra/include/mach/uncompress.h
+ rename arch/arm/mach-tegra/{board-dt-tegra20.c => tegra.c} (75%)
+ create mode 100644 arch/arm/mach-tegra/tegra114_speedo.c
+ rename arch/arm/mach-tegra/include/mach/powergate.h => include/linux/tegra-powergate.h (92%)
+Merging dma-mapping/dma-mapping-next (a937536 Linux 3.9-rc3)
+$ git merge dma-mapping/dma-mapping-next
+Already up-to-date.
+Merging pwm/for-next (a46ef4d pwm: puv3: Remove unused enabled filed from struct puv3_pwm_chip)
+$ git merge pwm/for-next
+Merge made by the 'recursive' strategy.
+ drivers/pwm/Kconfig              |  8 +++-----
+ drivers/pwm/pwm-ab8500.c         | 10 ++++------
+ drivers/pwm/pwm-atmel-tcb.c      |  1 +
+ drivers/pwm/pwm-imx.c            |  6 +-----
+ drivers/pwm/pwm-mxs.c            |  2 --
+ drivers/pwm/pwm-puv3.c           |  1 -
+ drivers/pwm/pwm-pxa.c            | 23 +++++------------------
+ drivers/pwm/pwm-samsung.c        | 20 +++++++++-----------
+ drivers/pwm/pwm-spear.c          |  9 +++------
+ drivers/pwm/pwm-tiecap.c         |  6 ++++--
+ drivers/pwm/pwm-tiehrpwm.c       |  6 ++++--
+ drivers/pwm/pwm-tipwmss.c        |  2 ++
+ drivers/pwm/pwm-tipwmss.h        |  2 +-
+ drivers/pwm/pwm-twl-led.c        |  2 ++
+ drivers/pwm/pwm-twl.c            |  4 +++-
+ drivers/video/backlight/pwm_bl.c |  7 ++-----
+ 16 files changed, 44 insertions(+), 65 deletions(-)
+Merging dma-buf/for-next (6dbe51c Linux 3.9-rc1)
+$ git merge dma-buf/for-next
+Already up-to-date.
+Merging userns/for-next (78008c4 proc: Restrict mounting the proc filesystem)
+$ git merge userns/for-next
+Auto-merging fs/proc/root.c
+Merge made by the 'recursive' strategy.
+ fs/proc/root.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+Merging ktest/for-next (7328735 ktest: Remove indexes from warnings check)
+$ git merge ktest/for-next
+Already up-to-date.
+Merging signal/for-next (99e621f syscalls.h: slightly reduce the jungles of macros)
+$ git merge signal/for-next
+Resolved 'arch/mips/kernel/linux32.c' using previous resolution.
+Resolved 'arch/tile/Kconfig' using previous resolution.
+Resolved 'arch/tile/kernel/compat.c' using previous resolution.
+Resolved 'fs/compat.c' using previous resolution.
+Resolved 'fs/read_write.c' using previous resolution.
+Resolved 'fs/read_write.h' using previous resolution.
+Resolved 'fs/splice.c' using previous resolution.
+Resolved 'include/asm-generic/unistd.h' using previous resolution.
+Auto-merging mm/nommu.c
+Auto-merging kernel/sys.c
+Auto-merging kernel/fork.c
+Auto-merging kernel/exit.c
+Auto-merging include/linux/mm.h
+Auto-merging include/linux/compat.h
+Auto-merging include/asm-generic/unistd.h
+CONFLICT (content): Merge conflict in include/asm-generic/unistd.h
+Auto-merging fs/splice.c
+CONFLICT (content): Merge conflict in fs/splice.c
+Auto-merging fs/read_write.h
+CONFLICT (content): Merge conflict in fs/read_write.h
+Auto-merging fs/read_write.c
+CONFLICT (content): Merge conflict in fs/read_write.c
+Auto-merging fs/compat.c
+CONFLICT (content): Merge conflict in fs/compat.c
+Auto-merging fs/aio.c
+Removing arch/x86/ia32/ipc32.c
+Auto-merging arch/tile/kernel/compat.c
+CONFLICT (content): Merge conflict in arch/tile/kernel/compat.c
+Auto-merging arch/tile/Kconfig
+CONFLICT (content): Merge conflict in arch/tile/Kconfig
+Auto-merging arch/sparc/Kconfig
+Auto-merging arch/s390/kernel/syscalls.S
+Auto-merging arch/s390/kernel/compat_wrapper.S
+Auto-merging arch/s390/Kconfig
+Removing arch/powerpc/include/uapi/asm/linkage.h
+Auto-merging arch/powerpc/include/asm/unistd.h
+Auto-merging arch/powerpc/include/asm/systbl.h
+Auto-merging arch/powerpc/Kconfig
+Auto-merging arch/mips/kernel/linux32.c
+CONFLICT (content): Merge conflict in arch/mips/kernel/linux32.c
+Auto-merging arch/mips/Kconfig
+Auto-merging arch/alpha/Kconfig
+Auto-merging arch/Kconfig
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master a67a634] Merge remote-tracking branch 'signal/for-next'
+$ git diff -M --stat --summary HEAD^..
+ arch/Kconfig                            |   3 -
+ arch/alpha/Kconfig                      |   1 -
+ arch/alpha/include/asm/linkage.h        |   4 +-
+ arch/alpha/include/asm/unistd.h         |  12 ---
+ arch/arm/include/asm/unistd.h           |   8 --
+ arch/arm64/kernel/sys32.S               |   7 --
+ arch/avr32/include/asm/unistd.h         |   8 --
+ arch/blackfin/include/asm/unistd.h      |   8 --
+ arch/cris/include/asm/unistd.h          |   8 --
+ arch/frv/include/asm/unistd.h           |  10 --
+ arch/h8300/include/asm/linkage.h        |   2 -
+ arch/h8300/include/asm/unistd.h         |   7 --
+ arch/ia64/include/asm/linkage.h         |   4 +
+ arch/ia64/include/asm/unistd.h          |  10 --
+ arch/m32r/include/asm/unistd.h          |  10 --
+ arch/m68k/include/asm/unistd.h          |   8 --
+ arch/microblaze/include/asm/unistd.h    |   8 --
+ arch/mips/Kconfig                       |   1 -
+ arch/mips/include/asm/linkage.h         |   3 +
+ arch/mips/include/asm/unistd.h          |   8 --
+ arch/mips/kernel/linux32.c              | 119 ----------------------
+ arch/mips/kernel/scall64-n32.S          |   8 +-
+ arch/mips/kernel/scall64-o32.S          |   6 +-
+ arch/mn10300/include/asm/unistd.h       |  10 --
+ arch/parisc/include/asm/unistd.h        |   8 --
+ arch/parisc/kernel/sys_parisc32.c       |  41 --------
+ arch/parisc/kernel/syscall_table.S      |   8 +-
+ arch/powerpc/Kconfig                    |   1 -
+ arch/powerpc/include/asm/linkage.h      |  13 +++
+ arch/powerpc/include/asm/systbl.h       |  10 +-
+ arch/powerpc/include/asm/unistd.h       |   6 --
+ arch/powerpc/include/uapi/asm/linkage.h |   6 --
+ arch/powerpc/kernel/sys_ppc32.c         | 109 --------------------
+ arch/s390/Kconfig                       |   1 -
+ arch/s390/include/asm/unistd.h          |   8 --
+ arch/s390/kernel/compat_linux.c         |  86 +---------------
+ arch/s390/kernel/compat_linux.h         |   5 -
+ arch/s390/kernel/compat_wrapper.S       |  64 ------------
+ arch/s390/kernel/sys_s390.c             |  14 +--
+ arch/s390/kernel/syscalls.S             |  18 ++--
+ arch/sh/include/asm/unistd.h            |   8 --
+ arch/sparc/Kconfig                      |   1 -
+ arch/sparc/include/asm/unistd.h         |   8 --
+ arch/sparc/kernel/sys32.S               |   4 -
+ arch/sparc/kernel/sys_sparc32.c         |  75 +-------------
+ arch/sparc/kernel/sys_sparc_64.c        |   6 +-
+ arch/sparc/kernel/systbls_64.S          |   8 +-
+ arch/tile/Kconfig                       |   1 -
+ arch/tile/kernel/compat.c               |   6 --
+ arch/x86/ia32/Makefile                  |   3 -
+ arch/x86/ia32/ipc32.c                   |  54 ----------
+ arch/x86/ia32/sys_ia32.c                |  37 -------
+ arch/x86/include/asm/sys_ia32.h         |  12 ---
+ arch/x86/include/asm/syscalls.h         |   4 +-
+ arch/x86/include/asm/unistd.h           |   8 --
+ arch/x86/kernel/tls.c                   |  14 +--
+ arch/x86/syscalls/syscall_32.tbl        |  10 +-
+ arch/x86/um/tls_32.c                    |   5 +-
+ arch/xtensa/include/asm/unistd.h        |   8 --
+ fs/aio.c                                |   2 -
+ fs/compat.c                             | 121 ----------------------
+ fs/dcookies.c                           |  15 ++-
+ fs/eventpoll.c                          |  47 +++++++++
+ fs/notify/fanotify/fanotify_user.c      |  17 +---
+ fs/open.c                               |  52 ++--------
+ fs/read_write.c                         |  68 +++++++++----
+ fs/read_write.h                         |   2 -
+ fs/signalfd.c                           |  31 ++++++
+ fs/splice.c                             |  22 ++++
+ fs/sync.c                               |  26 +----
+ include/asm-generic/unistd.h            |  12 ---
+ include/linux/compat.h                  |  51 +++-------
+ include/linux/linkage.h                 |  21 ++++
+ include/linux/mm.h                      |   3 -
+ include/linux/syscalls.h                | 156 +++++++++-------------------
+ ipc/compat.c                            | 174 ++++++++++++++++++--------------
+ ipc/sem.c                               | 123 +++++++++++++---------
+ ipc/syscall.c                           |   6 +-
+ kernel/compat.c                         |  19 ----
+ kernel/exit.c                           |   5 -
+ kernel/fork.c                           |   5 +-
+ kernel/sys.c                            |  14 +++
+ kernel/sys_ni.c                         |   3 +-
+ kernel/uid16.c                          |  55 ++--------
+ mm/fadvise.c                            |  18 +---
+ mm/nommu.c                              |   3 +-
+ mm/readahead.c                          |   9 +-
+ 87 files changed, 539 insertions(+), 1484 deletions(-)
+ create mode 100644 arch/powerpc/include/asm/linkage.h
+ delete mode 100644 arch/powerpc/include/uapi/asm/linkage.h
+ delete mode 100644 arch/x86/ia32/ipc32.c
+$ git am -3 ../patches/0001-cond_syscall-and-SYSCALL_ALIAS-merge-fixup.patch
+Applying: cond_syscall and SYSCALL_ALIAS merge fixup
+$ git reset HEAD^
+Unstaged changes after reset:
+M	include/linux/linkage.h
+$ git add -A .
+$ git commit -v -a --amend
+[master 67d75b5] Merge remote-tracking branch 'signal/for-next'
+Merging clk/clk-next (918d7f6 clk: sunxi: drop an unnecesary kmalloc)
+$ git merge clk/clk-next
+Auto-merging drivers/clk/spear/spear1340_clock.c
+Removing drivers/clk/mvebu/clk-cpu.h
+Auto-merging drivers/clk/Makefile
+Auto-merging arch/arm/mach-imx/clk-busy.c
+Merge made by the 'recursive' strategy.
+ Documentation/arm/sunxi/clocks.txt                 |  56 +++
+ Documentation/clk.txt                              |   4 +-
+ .../devicetree/bindings/clock/axi-clkgen.txt       |  22 +
+ Documentation/devicetree/bindings/clock/sunxi.txt  | 151 +++++++
+ arch/arm/mach-imx/clk-busy.c                       |   2 +-
+ drivers/clk/Kconfig                                |   8 +
+ drivers/clk/Makefile                               |   3 +
+ drivers/clk/clk-axi-clkgen.c                       | 331 +++++++++++++++
+ drivers/clk/clk-composite.c                        | 201 +++++++++
+ drivers/clk/clk-divider.c                          |   5 +-
+ drivers/clk/clk-mux.c                              |  50 ++-
+ drivers/clk/clk-prima2.c                           |   2 +-
+ drivers/clk/clk-zynq.c                             |   1 +
+ drivers/clk/clk.c                                  | 193 +++++++--
+ drivers/clk/mvebu/clk-cpu.c                        |  17 +-
+ drivers/clk/mvebu/clk-cpu.h                        |  22 -
+ drivers/clk/mvebu/clk.c                            |   6 +-
+ drivers/clk/mxs/clk.c                              |   1 +
+ drivers/clk/spear/spear1340_clock.c                |  18 +-
+ drivers/clk/sunxi/Makefile                         |   5 +
+ drivers/clk/sunxi/clk-factors.c                    | 180 +++++++++
+ drivers/clk/sunxi/clk-factors.h                    |  27 ++
+ drivers/clk/sunxi/clk-sunxi.c                      | 450 +++++++++++++++++++++
+ drivers/clk/tegra/clk.h                            |  27 +-
+ drivers/clk/ux500/clk-prcmu.c                      | 136 ++++---
+ drivers/clocksource/sunxi_timer.c                  |   4 +-
+ include/linux/clk-private.h                        |   2 +-
+ include/linux/clk-provider.h                       |  61 ++-
+ include/linux/clk/sunxi.h                          |  22 +
+ 29 files changed, 1831 insertions(+), 176 deletions(-)
+ create mode 100644 Documentation/arm/sunxi/clocks.txt
+ create mode 100644 Documentation/devicetree/bindings/clock/axi-clkgen.txt
+ create mode 100644 Documentation/devicetree/bindings/clock/sunxi.txt
+ create mode 100644 drivers/clk/clk-axi-clkgen.c
+ create mode 100644 drivers/clk/clk-composite.c
+ delete mode 100644 drivers/clk/mvebu/clk-cpu.h
+ create mode 100644 drivers/clk/sunxi/Makefile
+ create mode 100644 drivers/clk/sunxi/clk-factors.c
+ create mode 100644 drivers/clk/sunxi/clk-factors.h
+ create mode 100644 drivers/clk/sunxi/clk-sunxi.c
+ create mode 100644 include/linux/clk/sunxi.h
+Merging random/dev (b980955 random: fix locking dependency with the tasklist_lock)
+$ git merge random/dev
+Already up-to-date.
+Merging lzo-update/lzo-update (42b775a lib/lzo: huge LZO decompression speedup on ARM by using unaligned access)
+$ git merge lzo-update/lzo-update
+Merge made by the 'recursive' strategy.
+ lib/lzo/lzo1x_decompress_safe.c | 4 ++++
+ lib/lzo/lzodefs.h               | 6 ++++++
+ 2 files changed, 10 insertions(+)
+Merging scsi-post-merge/merge-base:master (65112dc Merge git://git.samba.org/sfrench/cifs-2.6)
+Merging akpm-current/current (a12183c Merge branch 'timers-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip)
+$ git merge akpm-current/current
+Already up-to-date.
+$ git clone -s -l -n -q . ../rebase-tmp
+$ cd ../rebase-tmp
+$ git checkout -b akpm remotes/origin/akpm/master
+Switched to a new branch 'akpm'
+$ git rebase --onto master remotes/origin/akpm/master-base
+First, rewinding head to replay your work on top of it...
+Applying: revert "ipc: don't allocate a copy larger than max"
+Applying: thinkpad-acpi: kill hotkey_thread_mutex
+Applying: mips: define KVM_USER_MEM_SLOTS
+Applying: drivers/char/random.c: fix priming of last_data
+Applying: kthread: introduce to_live_kthread()
+Applying: kthread: kill task_get_live_kthread()
+Applying: arch/x86/mm/init_64.c: fix build warning when CONFIG_MEMORY_HOTREMOVE=n
+Applying: x86: make 'mem=' option to work for efi platform
+Applying: mm: remove free_area_cache use in powerpc architecture
+Applying: mm: use vm_unmapped_area() on powerpc architecture
+Applying: drm/fb-helper: don't sleep for screen unblank when an oops is in progress
+Applying: matroxfb: convert struct i2c_msg initialization to C99 format
+Applying: drivers/video/console/fbcon_cw.c: fix compiler warning in cw_update_attr
+Applying: drivers/video: add Hyper-V Synthetic Video Frame Buffer Driver
+Applying: video: fix a type warning in hyperv_fb.c
+Applying: drivers/video/exynos/exynos_mipi_dsi.c: convert to devm_ioremap_resource()
+Applying: drivers/video/ep93xx-fb.c: fix section mismatch and use module_platform_driver
+Applying: drivers/video/mmp: remove legacy hw definitions
+Applying: cyber2000fb: avoid palette corruption at higher clocks
+Applying: timer_list: split timer_list_show_tickdevices()
+Applying: timer_list-split-timer_list_show_tickdevices-v4
+Applying: timer_list: convert timer list to be a proper seq_file
+Applying: timer_list-convert-timer-list-to-be-a-proper-seq_file-v3
+Applying: timer_list-convert-timer-list-to-be-a-proper-seq_file-v3-fix
+Applying: posix_cpu_timer: consolidate expiry time type
+Applying: posix_cpu_timers: consolidate timer list cleanups
+Applying: posix_cpu_timers: consolidate expired timers check
+Applying: selftests: add basic posix timers selftests
+Applying: ktime_add_ns() may overflow on 32bit architectures
+Applying: mkcapflags.pl: convert to mkcapflags.sh
+Applying: headers_install.pl: convert to headers_install.sh
+Applying: scripts/decodecode: make faulting insn ptr more robust
+Applying: ipvs: change type of netns_ipvs->sysctl_sync_qlen_max
+Applying: ocfs2: delay inode update transactions after verifying the input flags
+Applying: debug_locks.h: make warning more verbose
+Applying: lockdep: introduce lock_acquire_exclusive/shared helper macros
+Applying: lglock: update lockdep annotations to report recursive local locks
+Applying: drivers/block/mg_disk.c: add CONFIG_PM_SLEEP to suspend/resume functions
+Applying: block: restore /proc/partitions to not display non-partitionable removable devices
+Applying: fs/block_dev.c: no need to check inode->i_bdev in bd_forget()
+Applying: watchdog: trigger all-cpu backtrace when locked up and going to panic
+Applying: HWPOISON: check dirty flag to match against clean page
+Applying: mm: trace filemap add and del
+Applying: mm-trace-filemap-add-and-del-v2
+Applying: mm, show_mem: suppress page counts in non-blockable contexts
+Applying: mm/shmem.c: remove an ifdef
+Applying: vm: adjust ifdef for TINY_RCU
+Applying: mm: frontswap: lazy initialization to allow tmem backends to build/run as modules
+Applying: frontswap: make frontswap_init use a pointer for the ops
+Applying: mm: frontswap: cleanup code
+Applying: frontswap: get rid of swap_lock dependency
+Applying: mm: cleancache: lazy initialization to allow tmem backends to build/run as modules
+Applying: cleancache: Make cleancache_init use a pointer for the ops
+Applying: mm: cleancache: clean up cleancache_enabled
+Applying: xen: tmem: enable Xen tmem shim to be built/loaded as a module
+Applying: xen-tmem-enable-xen-tmem-shim-to-be-built-loaded-as-a-module-fix
+Applying: zcache/tmem: Better error checking on frontswap_register_ops return value.
+Applying: staging: zcache: enable ramster to be built/loaded as a module
+Applying: staging: zcache: enable zcache to be built/loaded as a module
+Applying: rmap: recompute pgoff for unmapping huge page
+Applying: memblock: add assertion for zero allocation alignment
+Applying: mm: walk_memory_range(): fix typo in comment
+Applying: direct-io: Fix boundary block handling
+Applying: mm/vmscan.c: minor cleanup for kswapd
+Applying: mm: introduce common help functions to deal with reserved/managed pages
+Applying: mm/alpha: use common help functions to free reserved pages
+Applying: mm/ARM: use common help functions to free reserved pages
+Applying: mm/avr32: use common help functions to free reserved pages
+Applying: mm/blackfin: use common help functions to free reserved pages
+Applying: mm/c6x: use common help functions to free reserved pages
+Applying: mm/cris: use common help functions to free reserved pages
+Applying: mm/FRV: use common help functions to free reserved pages
+Applying: mm/h8300: use common help functions to free reserved pages
+Applying: mm/IA64: use common help functions to free reserved pages
+Applying: mm/m32r: use common help functions to free reserved pages
+Applying: mm/m68k: use common help functions to free reserved pages
+Applying: mm/microblaze: use common help functions to free reserved pages
+Applying: mm/MIPS: use common help functions to free reserved pages
+Applying: mm/mn10300: use common help functions to free reserved pages
+Applying: mm/openrisc: use common help functions to free reserved pages
+Applying: mm/parisc: use common help functions to free reserved pages
+Applying: mm/ppc: use common help functions to free reserved pages
+Applying: mm/s390: use common help functions to free reserved pages
+Applying: mm/score: use common help functions to free reserved pages
+Applying: mm/SH: use common help functions to free reserved pages
+Applying: mm/SPARC: use common help functions to free reserved pages
+Applying: mm/um: use common help functions to free reserved pages
+Applying: mm/unicore32: use common help functions to free reserved pages
+Applying: mm/x86: use common help functions to free reserved pages
+Applying: mm/xtensa: use common help functions to free reserved pages
+Applying: mm/arc: use common help functions to free reserved pages
+Applying: mm/metag: use common help functions to free reserved pages
+Applying: mm,kexec: use common help functions to free reserved pages
+Applying: mm: introduce free_highmem_page() helper to free highmem pages into buddy system
+Applying: mm/ARM: use free_highmem_page() to free highmem pages into buddy system
+Applying: mm/FRV: use free_highmem_page() to free highmem pages into buddy system
+Applying: mm/metag: use free_highmem_page() to free highmem pages into buddy system
+Applying: mm/microblaze: use free_highmem_page() to free highmem pages into buddy system
+Applying: mm/MIPS: use free_highmem_page() to free highmem pages into buddy system
+Applying: mm/PPC: use free_highmem_page() to free highmem pages into buddy system
+Applying: mm/SPARC: use free_highmem_page() to free highmem pages into buddy system
+Applying: mm/um: use free_highmem_page() to free highmem pages into buddy system
+Applying: mm/x86: use free_highmem_page() to free highmem pages into buddy system
+Applying: memcg: keep prev's css alive for the whole mem_cgroup_iter
+Applying: memcg: rework mem_cgroup_iter to use cgroup iterators
+Applying: memcg: relax memcg iter caching
+Applying: memcg-relax-memcg-iter-caching-checkpatch-fixes
+Applying: memcg: simplify mem_cgroup_iter
+Applying: memcg: further simplify mem_cgroup_iter
+Applying: cgroup: remove css_get_next
+Applying: fs: don't compile in drop_caches.c when CONFIG_SYSCTL=n
+Applying: mm/hugetlb: add more arch-defined huge_pte functions
+Applying: mm: make snapshotting pages for stable writes a per-bio operation
+Applying: mm-make-snapshotting-pages-for-stable-writes-a-per-bio-operation-fix
+Applying: mm-make-snapshotting-pages-for-stable-writes-a-per-bio-operation-fix-fix
+Applying: mm, vmalloc: change iterating a vmlist to find_vm_area()
+Applying: mm, vmalloc: move get_vmalloc_info() to vmalloc.c
+Applying: mm, vmalloc: protect va->vm by vmap_area_lock
+Applying: mm, vmalloc: iterate vmap_area_list, instead of vmlist in vread/vwrite()
+Applying: mm, vmalloc: iterate vmap_area_list in get_vmalloc_info()
+Applying: mm, vmalloc: iterate vmap_area_list, instead of vmlist, in vmallocinfo()
+Applying: mm, vmalloc: export vmap_area_list, instead of vmlist
+Applying: mm, vmalloc: remove list management of vmlist after initializing vmalloc
+Applying: kexec, vmalloc: export additional vmalloc layer information
+Applying: kexec-vmalloc-export-additional-vmalloc-layer-information-fix
+Applying: mmap: find_vma: remove the WARN_ON_ONCE(!mm) check
+Using index info to reconstruct a base tree...
+M	mm/mmap.c
+Falling back to patching base and 3-way merge...
+Auto-merging mm/mmap.c
+Applying: memcg: do not check for do_swap_account in mem_cgroup_{read,write,reset}
+Applying: mm: allow arch code to control the user page table ceiling
+Applying: arm: set the page table freeing ceiling to TASK_SIZE
+Applying: mm: merging memory blocks resets mempolicy
+Applying: mm, hugetlb: include hugepages in meminfo
+Applying: mm-hugetlb-include-hugepages-in-meminfo-checkpatch-fixes
+Applying: mm: try harder to allocate vmemmap blocks
+Applying: sparse-vmemmap: specify vmemmap population range in bytes
+Applying: sparse-vmemmap-specify-vmemmap-population-range-in-bytes-fix
+Applying: x86-64: remove dead debugging code for !pse setups
+Applying: x86-64: use vmemmap_populate_basepages() for !pse setups
+Applying: x86-64: use vmemmap_populate_basepages() for !pse setups fix
+Applying: x86-64: fall back to regular page vmemmap on allocation failure
+Applying: mm: page_alloc: avoid marking zones full prematurely after zone_reclaim()
+Applying: mm/migrate: fix comment typo syncronous->synchronous
+Applying: mm: speedup in __early_pfn_to_nid
+Applying: mm-speedup-in-__early_pfn_to_nid-fix
+Applying: page_alloc: make setup_nr_node_ids() usable for arch init code
+Applying: x86/mm/numa: use setup_nr_node_ids() instead of opencoding.
+Applying: powerpc/mm/numa: use setup_nr_node_ids() instead of opencoding.
+Applying: powerpc/mm/numa: use setup_nr_node_ids() fix
+Applying: mm: remove free_area_cache
+Applying: include/linux/mmzone.h: cleanups
+Applying: include-linux-mmzoneh-cleanups-fix
+Applying: mm: memmap_init_zone() performance improvement
+Applying: drop_caches: add some documentation and info message
+Applying: drivers/usb/gadget/amd5536udc.c: avoid calling dma_pool_create() with NULL dev
+Applying: mm/dmapool.c: fix null dev in dma_pool_create()
+Applying: memcg: debugging facility to access dangling memcgs
+Applying: memcg-debugging-facility-to-access-dangling-memcgs-fix
+Applying: mm: add vm event counters for balloon pages compaction
+Applying: drivers/rpmsg/virtio_rpmsg_bus.c: fix error return code in rpmsg_probe()
+Applying: kernel/watchdog.c: add comments to explain watchdog_disabled variable
+Applying: kernel/range.c: subtract_range: fix the broken phrase issued by printk
+Applying: smp: Give WARN()ing when calling smp_call_function_many()/single() in serving irq
+Applying: include/linux/fs.h: disable preempt when acquire i_size_seqcount write lock
+Applying: kernel/smp.c: cleanups
+Applying: printk/tracing: rework console tracing
+Applying: early_printk: consolidate random copies of identical code
+Applying: early_printk: consolidate random copies of identical code
+Applying: early_printk-consolidate-random-copies-of-identical-code-v3-fix
+Applying: include/linux/printk.h: include stdarg.h
+Applying: get_maintainer: use filename-only regex match for Tegra
+Applying: get_maintainer-use-filename-only-regex-match-for-tegra-fix
+Applying: MAINTAINERS: i8k driver is orphan
+Applying: drivers/video/backlight/ams369fg06.c: convert ams369fg06 to dev_pm_ops
+Applying: drivers-video-backlight-ams369fg06c-convert-ams369fg06-to-dev_pm_ops-fix
+Applying: drivers/video/backlight/platform_lcd.c: remove unnecessary ifdefs
+Applying: drivers/video/backlight/ep93xx_bl.c: remove incorrect __init annotation
+Applying: drivers/video/backlight/atmel-pwm-bl.c: use module_platform_driver_probe()
+Applying: drivers/video/backlight/atmel-pwm-bl.c: add __init annotation
+Applying: drivers/video/backlight/lp855x_bl.c: fix compiler warning in lp855x_probe
+Applying: drivers/video/backlight/jornada720_*.c: use dev_err()/dev_info() instead of pr_err()/pr_info()
+Applying: drivers/video/backlight/omap1_bl.c: use dev_info() instead of pr_info()
+Applying: drivers/video/backlight/generic_bl.c: use dev_info() instead of pr_info()
+Applying: drivers/video/backlight/adp8870_bl.c: add missing braces
+Applying: drivers/video/backlight/l4f00242t03.c: check return value of regulator_enable()
+Applying: drivers-video-backlight-l4f00242t03c-check-return-value-of-regulator_enable-fix
+Applying: backlight: ld9040: convert ld9040 to dev_pm_ops
+Applying: backlight: lms501kf03: convert lms501kf03 to dev_pm_ops
+Applying: backlight: s6e63m0: convert s6e63m0 to dev_pm_ops
+Applying: backlight: adp5520: convert adp5520_bl to dev_pm_ops
+Applying: backlight: adp8860: convert adp8860 to dev_pm_ops
+Applying: backlight: adp8870: convert adp8870 to dev_pm_ops
+Applying: backlight: corgi_lcd: convert corgi_lcd to dev_pm_ops
+Applying: backlight: ep93xx: convert ep93xx to dev_pm_ops
+Applying: backlight: hp680_bl: convert hp680bl to dev_pm_ops
+Applying: backlight: kb3886_bl: convert kb3886bl to dev_pm_ops
+Applying: backlight: lm3533_bl: convert lm3533_bl to dev_pm_ops
+Applying: backlight: locomolcd: convert locomolcd to dev_pm_ops
+Applying: backlight: ltv350qv: convert ltv350qv to dev_pm_ops
+Applying: backlight: tdo24m: convert tdo24m to dev_pm_ops
+Applying: drivers/video/backlight/Kconfig: fix typo "MACH_SAM9...EK" three times
+Applying: drivers/video/backlight/adp5520_bl.c: fix compiler warning in adp5520_show()
+Applying: video: backlight: add ili922x lcd driver
+Applying: backlight: da903x_bl: use BL_CORE_SUSPENDRESUME option
+Applying: drivers/video/backlight/lp855x_bl.c: use PAGE_SIZE for the sysfs read operation
+Applying: drivers/video/backlight/adp8860_bl.c: fix error return code in adp8860_led_probe()
+Applying: drivers/video/backlight/adp8870_bl.c: fix error return code in adp8870_led_probe()
+Applying: drivers/video/backlight/as3711_bl.c: add OF support
+Applying: drivers/leds/leds-ot200.c: fix error caused by shifted mask
+Applying: lib/int_sqrt.c: optimize square root algorithm
+Applying: argv_split(): teach it to handle mutable strings
+Applying: argv_split-teach-it-to-handle-mutable-strings-fix
+Applying: argv_split-teach-it-to-handle-mutable-strings-fix-2
+Applying: checkpatch: add check for reuse of krealloc arg
+Applying: checkpatch: Prefer seq_puts to seq_printf
+Applying: checkpatch: Complain about executable files
+Applying: epoll: trim epitem by one cache line
+Applying: epoll-trim-epitem-by-one-cache-line-on-x86_64-fix
+Applying: epoll: comment + BUILD_BUG_ON to prevent epitem bloat
+Applying: epoll: support for disabling items, and a self-test app
+Applying: epoll: stop comparing pointers with 0 in self-test app
+Applying: epoll: use RCU to protect wakeup_source in epitem
+Applying: epoll: fix suspicious RCU usage in ep_poll_callback
+Applying: epoll: lock ep->mtx in ep_free to silence lockdep
+Applying: epoll: cleanup: hoist out f_op->poll calls
+Applying: fs: make binfmt support for #! scripts modular and removable
+Applying: binfmt_elf.c: use get_random_int() to fix entropy depleting
+Applying: init: scream bloody murder if interrupts are enabled too early
+Applying: init: raise log level
+Applying: init/main.c: convert to pr_foo()
+Applying: dmi_scan: refactor dmi_scan_machine(), {smbios,dmi}_present()
+Applying: dmi_scan: proper buf type in dmi_present()
+Applying: i2o: check copy_from_user() size parameter
+Applying: rtc: rtc-mv: add __init annotation
+Applying: rtc: rtc-davinci: add __exit annotation
+Applying: rtc: rtc-ds1302: add __exit annotation
+Applying: rtc: rtc-imxdi: add __init/__exit annotation
+Applying: rtc: rtc-nuc900: add __init/__exit annotation
+Applying: rtc: rtc-pcap: add __init/__exit annotation
+Applying: rtc: rtc-tegra: add __init/__exit annotation
+Applying: rtc: add devm_rtc_device_{register,unregister}()
+Applying: drivers/rtc/rtc-max77686.c: use module_platform_driver()
+Applying: drivers/rtc/rtc-max77686.c: add missing module author name
+Applying: drivers/rtc/rtc-max77686.c: use devm_kzalloc()
+Applying: drivers/rtc/rtc-max77686.c: fix indentation of bit definitions
+Applying: drivers/rtc/rtc-max77686.c: use dev_info()/dev_emerg() instead of pr_info()/pr_emerg()
+Applying: drivers/rtc/rtc-v3020.c: use gpio_request_array()
+Applying: drivers/rtc/class.c: use struct device as the first argument for devm_rtc_device_register()
+Applying: rtc: rtc-ab3100: use module_platform_driver_probe()
+Applying: rtc: rtc-at32ap700x: use module_platform_driver_probe()
+Applying: rtc: rtc-at91rm9200: use module_platform_driver_probe()
+Applying: rtc: rtc-au1xxx: use module_platform_driver_probe()
+Applying: rtc: rtc-coh901331: use module_platform_driver_probe()
+Applying: rtc: rtc-davinci: use module_platform_driver_probe()
+Applying: rtc: rtc-ds1302: use module_platform_driver_probe()
+Applying: rtc: rtc-efi: use module_platform_driver_probe()
+Applying: rtc: rtc-generic: use module_platform_driver_probe()
+Applying: rtc: rtc-imxdi: use module_platform_driver_probe()
+Applying: rtc: rtc-mc13xxx: use module_platform_driver_probe()
+Applying: rtc: rtc-msm6242: use module_platform_driver_probe()
+Applying: rtc: rtc-mv: use module_platform_driver_probe()
+Applying: rtc: rtc-nuc900: use module_platform_driver_probe()
+Applying: rtc: rtc-omap: use module_platform_driver_probe()
+Applying: rtc: rtc-pcap: use module_platform_driver_probe()
+Applying: rtc: rtc-ps3: use module_platform_driver_probe()
+Applying: rtc: rtc-pxa: use module_platform_driver_probe()
+Applying: rtc: rtc-rp5c01: use module_platform_driver_probe()
+Applying: rtc: rtc-sh: use module_platform_driver_probe()
+Applying: rtc: rtc-starfire: use module_platform_driver_probe()
+Applying: rtc: rtc-sun4v: use module_platform_driver_probe()
+Applying: rtc: rtc-tegra: use module_platform_driver_probe()
+Applying: rtc: rtc-tx4939: use module_platform_driver_probe()
+Applying: rtc: rtc-88pm80x: use devm_rtc_device_register()
+Applying: rtc: rtc-coh90133: use devm_rtc_device_register()
+Applying: rtc: rtc-da9052: use devm_rtc_device_register()
+Applying: rtc: rtc-da9055: use devm_rtc_device_register()
+Applying: rtc: rtc-davinci: use devm_rtc_device_register()
+Applying: rtc: rtc-ds1511: use devm_rtc_device_register()
+Applying: rtc: rtc-ds1553: use devm_rtc_device_register()
+Applying: rtc: rtc-ds1742: use devm_rtc_device_register()
+Applying: rtc: rtc-ep93xx: use devm_rtc_device_register()
+Applying: rtc: rtc-imxdi: use devm_rtc_device_register()
+Applying: rtc: rtc-lp8788: use devm_rtc_device_register()
+Applying: rtc: rtc-lpc32xx: use devm_rtc_device_register()
+Applying: rtc: rtc-max77686: use devm_rtc_device_register()
+Applying: rtc: rtc-max8907: use devm_rtc_device_register()
+Applying: rtc: rtc-max8997: use devm_rtc_device_register()
+Applying: rtc: rtc-mv: use devm_rtc_device_register()
+Applying: rtc: rtc-mxc: use devm_rtc_device_register()
+Applying: rtc: rtc-palmas: use devm_rtc_device_register()
+Applying: rtc: rtc-pcf8523: use devm_rtc_device_register()
+Applying: rtc: rtc-s3c: use devm_rtc_device_register()
+Applying: rtc: rtc-snvs: use devm_rtc_device_register()
+Applying: rtc: rtc-spear: use devm_rtc_device_register()
+Applying: rtc: rtc-stk17ta8: use devm_rtc_device_register()
+Applying: rtc: rtc-tps6586x: use devm_rtc_device_register()
+Applying: rtc: rtc-tps65910: use devm_rtc_device_register()
+Applying: rtc: rtc-tps80031: use devm_rtc_device_register()
+Applying: rtc: rtc-tx4939: use devm_rtc_device_register()
+Applying: rtc: rtc-vt8500: use devm_rtc_device_register()
+Applying: rtc: rtc-wm831x: use devm_rtc_device_register()
+Applying: below is the warning reported with the gcc (gcc (GCC) 4.7.2 20121109 (Red
+Applying: drivers/rtc/rtc-pxa.c: fix set time sync time issue
+Applying: drivers-rtc-rtc-pxac-fix-set-time-sync-time-issue-fix
+Applying: drivers/rtc/rtc-tegra.c: protect suspend/resume callbacks with CONFIG_PM_SLEEP
+Applying: drivers/rtc/rtc-tegra.c: use struct dev_pm_ops for power management
+Applying: drivers/rtc/rtc-tegra.c: set irq name as device name
+Applying: drivers/rtc/rtc-tegra.c: use managed rtc_device_register()
+Applying: drivers/rtc/rtc-tegra.c: fix build warning
+Applying: drivers/rtc/rtc-ds1307.c: long block operations bugfix
+Applying: rtc: rtc-palmas: use devm_request_threaded_irq()
+Applying: drivers/rtc/rtc-s3c.c: convert s3c_rtc to dev_pm_ops
+Applying: rtc: rtc-ds1307: use dev_dbg() instead of pr_debug()
+Applying: rtc: rtc-fm3130: use dev_dbg() instead of pr_debug()
+Applying: rtc: rtc-ab3100: use devm_rtc_device_register()
+Applying: rtc: rtc-au1xxx: use devm_rtc_device_register()
+Applying: rtc: rtc-bq32k: use devm_rtc_device_register()
+Applying: rtc: rtc-dm355evm: use devm_rtc_device_register()
+Applying: rtc: rtc-ds1302: use devm_rtc_device_register()
+Applying: rtc: rtc-ds1672: use devm_rtc_device_register()
+Applying: rtc: rtc-ds3234: use devm_rtc_device_register()
+Applying: rtc: rtc-efi: use devm_rtc_device_register()
+Applying: rtc: rtc-em3027: use devm_rtc_device_register()
+Applying: rtc: rtc-generic: use devm_rtc_device_register()
+Applying: rtc: hid-sensor-time: use devm_rtc_device_register()
+Applying: rtc: rtc-ls1x: use devm_rtc_device_register()
+Applying: rtc: rtc-m41t93: use devm_rtc_device_register()
+Applying: rtc: rtc-m41t94: use devm_rtc_device_register()
+Applying: rtc: rtc-m48t86: use devm_rtc_device_register()
+Applying: rtc: rtc-max6900: use devm_rtc_device_register()
+Applying: rtc: rtc-max6902: use devm_rtc_device_register()
+Applying: rtc: rtc-ps3: use devm_rtc_device_register()
+Applying: rtc: rtc-r9701: use devm_rtc_device_register()
+Applying: rtc: rtc-rc5t583: use devm_rtc_device_register()
+Applying: rtc: rtc-rs5c313: use devm_rtc_device_register()
+Applying: rtc: rtc-rv3029c2: use devm_rtc_device_register()
+Applying: rtc: rtc-rx4581: use devm_rtc_device_register()
+Applying: rtc: rtc-rx8581: use devm_rtc_device_register()
+Applying: rtc: rtc-starfire: use devm_rtc_device_register()
+Applying: rtc: rtc-sun4v: use devm_rtc_device_register()
+Applying: rtc: rtc-test: use devm_rtc_device_register()
+Applying: rtc: rtc-tile: use devm_rtc_device_register()
+Applying: rtc: rtc-wm8350: use devm_rtc_device_register()
+Applying: rtc: rtc-x1205: use devm_rtc_device_register()
+Applying: rtc: rtc-at91rm9200: switch to using SIMPLE_DEV_PM_OPS
+Applying: rtc: rtc-mxc: switch to using SIMPLE_DEV_PM_OPS
+Applying: rtc: rtc-pxa: switch to using SIMPLE_DEV_PM_OPS
+Applying: rtc: rtc-rc5t583: switch to using SIMPLE_DEV_PM_OPS
+Applying: rtc: rtc-sa1100: switch to using SIMPLE_DEV_PM_OPS
+Applying: rtc: rtc-sh: switch to using SIMPLE_DEV_PM_OPS
+Applying: rtc: rtc-wm8350: switch to using SIMPLE_DEV_PM_OPS
+Applying: rtc: rtc-tps6586x: switch to using SIMPLE_DEV_PM_OPS
+Applying: rtc: rtc-tps65910: switch to using SIMPLE_DEV_PM_OPS
+Applying: rtc: rtc-tps80031: switch to using SIMPLE_DEV_PM_OPS
+Applying: drivers/rtc/rtc-omap.c: update to devm_* API
+Applying: drivers/rtc/rtc-palmas.c: add dt support
+Applying: drivers/rtc/rtc-ds1374.c: add CONFIG_PM_SLEEP to suspend/resume functions
+Applying: drivers/rtc/rtc-88pm80x.c: add CONFIG_PM_SLEEP to suspend/resume functions
+Applying: drivers/rtc/rtc-tps6586x.c: remove incorrect use of rtc_device_unregister
+Applying: drivers/rtc/rtc-tps65910.c: fix incorrect return value on error
+Applying: drivers/rtc/rtc-max8997.c: fix incorrect return value on error
+Applying: drivers/rtc/rtc-max77686.c: fix incorrect return value on error
+Applying: drivers/rtc/rtc-max8907.c: remove redundant code
+Applying: hfsplus: fix warnings in fs/hfsplus/bfind.c
+Applying: hfsplus-fix-warnings-in-fs-hfsplus-bfindc-in-function-hfs_find_1st_rec_by_cnid-fix
+Applying: fat: introduce 2 new values for the -o nfs mount option
+Applying: fat: move fat_i_pos_read to fat.h
+Applying: fat: introduce a helper fat_get_blknr_offset()
+Applying: fat: restructure export_operations
+Applying: fat (exportfs): rebuild inode if ilookup() fails
+Applying: fat (exportfs): rebuild directory-inode if fat_dget()
+Applying: Documentation: update nfs option in filesystem/vfat.txt
+Applying: ptrace: add ability to retrieve signals without removing from a queue (v4)
+Applying: selftest: add a test case for PTRACE_PEEKSIGINFO
+Applying: usermodehelper: export call_usermodehelper_exec() and call_usermodehelper_setup()
+Applying: usermodehelper-export-_exec-and-_setup-functions-fix
+Applying: kmod: split call to call_usermodehelper_fns()
+Applying: KEYS: split call to call_usermodehelper_fns()
+Applying: coredump: remove trailling whitespace
+Applying: usermodehelper: split remaining calls to call_usermodehelper_fns()
+Applying: kmod: remove call_usermodehelper_fns()
+Applying: coredump: only SIGKILL should interrupt the coredumping task
+Applying: coredump: ensure that SIGKILL always kills the dumping thread
+Applying: coredump: sanitize the setting of signal->group_exit_code
+Applying: coredump: introduce dump_interrupted()
+Applying: coredump: factor out the setting of PF_DUMPCORE
+Applying: coredump: change wait_for_dump_helpers() to use wait_event_interruptible()
+Applying: set_task_comm: kill the pointless memset() + wmb()
+Applying: exec: do not abuse ->cred_guard_mutex in threadgroup_lock()
+Applying: kexec: fix wrong types of some local variables
+Applying: kexec: Use min() and min_t() to simplify logic
+Applying: kexec-use-min_t-to-simplify-logic-fix
+Applying: ipc: clamp with min()
+Applying: ipc: separate msg allocation from userspace copy
+Applying: ipc: tighten msg copy loops
+Applying: ipc: set EFAULT as default error in load_msg()
+Applying: ipc: remove msg handling from queue scan
+Applying: ipc: implement MSG_COPY as a new receive mode
+Applying: ipc: simplify msg list search
+Applying: ipc: refactor msg list search into separate function
+Applying: ipc: find_msg can be static
+Applying: ipc/msgutil.c: use linux/uaccess.h
+Applying: ipc: remove bogus lock comment for ipc_checkid
+Applying: ipc: introduce obtaining a lockless ipc object
+Applying: ipc-introduce-obtaining-a-lockless-ipc-object-fix
+Applying: ipc: introduce lockless pre_down ipcctl
+Applying: ipc,sem: do not hold ipc lock more than necessary
+Applying: ipc,sem: open code and rename sem_lock
+Applying: ipcsem-open-code-and-rename-sem_lock-fix
+Applying: ipc,sem: have only one list in struct sem_queue
+Applying: ipc,sem: fine grained locking for semtimedop
+Applying: fix for sem_lock
+Applying: ipc, sem: prevent possible deadlock
+Applying: ipc/sem.c: alternatives to preempt_disable()
+Applying: kernel/pid.c: improve flow of a loop inside alloc_pidmap.
+Applying: kernel-pidc-improve-flow-of-a-loop-inside-alloc_pidmap-fix
+Applying: pid_namespace.c/.h: simplify defines
+Applying: pid_namespacec-h-simplify-defines-fix
+Applying: aoe: replace kmalloc and then memcpy with kmemdup
+Applying: raid6test: use prandom_bytes()
+Applying: uuid: use prandom_bytes()
+Applying: x86: pageattr-test: remove srandom32 call
+Applying: x86: rename random32() to prandom_u32()
+Applying: lib/: rename random32() to prandom_u32()
+Applying: mm/: rename random32() to prandom_u32()
+Applying: kernel/: rename random32() to prandom_u32()
+Applying: drbd: rename random32() to prandom_u32()
+Applying: infiniband: rename random32() to prandom_u32()
+Applying: mmc: rename random32() to prandom_u32()
+Applying: video/uvesafb: rename random32() to prandom_u32()
+Applying: uwb: rename random32() to prandom_u32()
+Applying: lguest: rename random32() to prandom_u32()
+Applying: scsi: rename random32() to prandom_u32()
+Applying: scsi: fix the wrong position of the comment
+Applying: drivers/net: rename random32() to prandom_u32()
+Applying: drivers-net-rename-random32-to-prandom_u32-fix
+Applying: net/sunrpc: rename random32() to prandom_u32()
+Applying: net/sched: rename random32() to prandom_u32()
+Applying: net/netfilter: rename random32() to prandom_u32()
+Applying: net/core: rename random32() to prandom_u32()
+Applying: net/core: remove duplicate statements by do-while loop
+Applying: net: rename random32 to prandom
+Applying: remove unused random32() and srandom32()
+Applying: semaphore: use unlikely() for down's timeout
+Applying: semaphore: use `bool' type for semaphore_waiter's up
+Applying: drivers/memstick/host/r592.c: make r592_pm_ops static
+Applying: kernel/relay.c: remove unused function argument actor
+Applying: kernel/relay.c: move FIX_SIZE macro into relay.c
+Applying: relay: use macro PAGE_ALIGN instead of FIX_SIZE
+Applying: mm: remove old aio use_mm() comment
+Applying: aio: remove dead code from aio.h
+Applying: gadget: remove only user of aio retry
+Applying: gadget-remove-only-user-of-aio-retry-checkpatch-fixes
+Applying: aio: remove retry-based AIO
+Applying: aio-remove-retry-based-aio-checkpatch-fixes
+Applying: char: add aio_{read,write} to /dev/{null,zero}
+Applying: aio: kill return value of aio_complete()
+Applying: aio: add kiocb_cancel()
+Applying: aio: move private stuff out of aio.h
+Applying: aio: dprintk() -> pr_debug()
+Applying: aio: do fget() after aio_get_req()
+Applying: aio: make aio_put_req() lockless
+Applying: aio-make-aio_put_req-lockless-checkpatch-fixes
+Applying: aio: refcounting cleanup
+Applying: aio-refcounting-cleanup-checkpatch-fixes
+Applying: wait: add wait_event_hrtimeout()
+Applying: aio: make aio_read_evt() more efficient, convert to hrtimers
+Applying: aio-make-aio_read_evt-more-efficient-convert-to-hrtimers-checkpatch-fixes
+Applying: aio: use flush_dcache_page()
+Applying: aio: use cancellation list lazily
+Applying: aio: change reqs_active to include unreaped completions
+Applying: aio: kill batch allocation
+Applying: aio: kill struct aio_ring_info
+Applying: aio: give shared kioctx fields their own cachelines
+Applying: aio: reqs_active -> reqs_available
+Applying: aio: percpu reqs_available
+Applying: generic dynamic per cpu refcounting
+Applying: generic-dynamic-per-cpu-refcounting-checkpatch-fixes
+Applying: aio: percpu ioctx refcount
+Applying: aio: use xchg() instead of completion_lock
+Applying: aio: don't include aio.h in sched.h
+Applying: aio-dont-include-aioh-in-schedh-fix
+Applying: aio: kill ki_key
+Applying: aio: kill ki_retry
+Applying: aio: kill ki_retry merge fix
+Applying: aio-kill-ki_retry-checkpatch-fixes
+Applying: block: prep work for batch completion
+Applying: block-prep-work-for-batch-completion-checkpatch-fixes
+Applying: block-prep-work-for-batch-completion-checkpatch merge fixes
+Applying: block-prep-work-for-batch-completion-fix-2
+Applying: block-prep-work-for-batch-completion-fix-3
+Applying: block, aio: batch completion for bios/kiocbs
+Applying: block-aio-batch-completion-for-bios-kiocbs-checkpatch-fixes
+Applying: block-aio-batch-completion-for-bios-kiocbs-fix
+Applying: virtio-blk: convert to batch completion
+Applying: mtip32xx: convert to batch completion
+Applying: aio: fix kioctx not being freed after cancellation at exit time
+Applying: Kconfig: consolidate CONFIG_DEBUG_STRICT_USER_COPY_CHECKS
+Applying: kconfig-consolidate-config_debug_strict_user_copy_checks-fix
+Applying: kconfig menu: move Virtualization drivers near other virtualization options
+Applying: init/Kconfig: make EXPERT as config instead of menuconfig
+Applying: UAPI: Remove empty Kbuild files
+Applying: kernel/sys.c: make prctl(PR_SET_MM) generally available
+Applying: decompressor: add LZ4 decompressor module
+Applying: lib: add support for LZ4-compressed kernel
+Applying: arm: add support for LZ4-compressed kernel
+Applying: x86: add support for LZ4-compressed kernel
+Applying: lib: add lz4 compressor module
+Applying: lib-add-lz4-compressor-module-fix
+Applying: crypto: add lz4 Cryptographic API
+Applying: crypto-add-lz4-cryptographic-api-fix
+$ cd ../next
+$ git fetch -f ../rebase-tmp akpm:akpm/master
+From ../rebase-tmp
+ + d4f6640...0641ec4 akpm       -> akpm/master  (forced update)
+$ rm -rf ../rebase-tmp
+Merging akpm/master (0641ec4 crypto-add-lz4-cryptographic-api-fix)
+$ git merge --no-ff akpm/master
+Removing scripts/headers_install.pl
+Auto-merging lib/usercopy.c
+Removing include/scsi/Kbuild
+Removing fs/proc/mmu.c
+Removing arch/x86/kernel/cpu/mkcapflags.pl
+Removing arch/sparc/lib/usercopy.c
+Merge made by the 'recursive' strategy.
+ CREDITS                                            |    4 +
+ Documentation/cgroups/memory.txt                   |   16 +
+ Documentation/filesystems/vfat.txt                 |   26 +-
+ Documentation/sysctl/vm.txt                        |   33 +-
+ MAINTAINERS                                        |   18 +-
+ arch/alpha/kernel/sys_nautilus.c                   |    5 +-
+ arch/alpha/mm/init.c                               |   24 +-
+ arch/alpha/mm/numa.c                               |    3 +-
+ arch/arc/mm/init.c                                 |   23 +-
+ arch/arm/Kconfig                                   |    1 +
+ arch/arm/boot/compressed/.gitignore                |    1 +
+ arch/arm/boot/compressed/Makefile                  |    6 +-
+ arch/arm/boot/compressed/decompress.c              |    4 +
+ arch/arm/boot/compressed/piggy.lz4.S               |    6 +
+ arch/arm/include/asm/pgtable.h                     |    9 +
+ arch/arm/kernel/early_printk.c                     |   17 +-
+ arch/arm/mm/init.c                                 |   50 +-
+ arch/arm/mm/mmap.c                                 |    2 -
+ arch/arm64/mm/init.c                               |   26 +-
+ arch/arm64/mm/mmap.c                               |    2 -
+ arch/arm64/mm/mmu.c                                |   13 +-
+ arch/avr32/mm/init.c                               |   24 +-
+ arch/blackfin/kernel/early_printk.c                |    2 -
+ arch/blackfin/mm/init.c                            |   22 +-
+ arch/c6x/mm/init.c                                 |   30 +-
+ arch/cris/mm/init.c                                |   16 +-
+ arch/frv/mm/init.c                                 |   38 +-
+ arch/h8300/mm/init.c                               |   30 +-
+ arch/ia64/include/asm/hugetlb.h                    |    1 +
+ arch/ia64/mm/contig.c                              |    2 +
+ arch/ia64/mm/discontig.c                           |    9 +-
+ arch/ia64/mm/init.c                                |   23 +-
+ arch/ia64/mm/numa.c                                |   15 +-
+ arch/m32r/mm/init.c                                |   26 +-
+ arch/m68k/mm/init.c                                |   24 +-
+ arch/metag/mm/init.c                               |   31 +-
+ arch/microblaze/include/asm/setup.h                |    1 -
+ arch/microblaze/kernel/early_printk.c              |   26 +-
+ arch/microblaze/mm/init.c                          |   34 +-
+ arch/mips/include/asm/hugetlb.h                    |    1 +
+ arch/mips/include/asm/kvm_host.h                   |    2 +-
+ arch/mips/kernel/early_printk.c                    |   12 +-
+ arch/mips/mm/init.c                                |   37 +-
+ arch/mips/mm/mmap.c                                |    2 -
+ arch/mips/sgi-ip27/ip27-memory.c                   |    4 +-
+ arch/mn10300/mm/init.c                             |   23 +-
+ arch/openrisc/mm/init.c                            |   27 +-
+ arch/parisc/Kconfig                                |    1 +
+ arch/parisc/Kconfig.debug                          |   14 -
+ arch/parisc/mm/init.c                              |   25 +-
+ arch/powerpc/include/asm/hugetlb.h                 |    1 +
+ arch/powerpc/include/asm/page_64.h                 |    3 +-
+ arch/powerpc/kernel/crash_dump.c                   |    5 +-
+ arch/powerpc/kernel/fadump.c                       |    5 +-
+ arch/powerpc/kernel/kvm.c                          |    7 +-
+ arch/powerpc/kernel/udbg.c                         |    6 +-
+ arch/powerpc/mm/hugetlbpage.c                      |    2 +-
+ arch/powerpc/mm/init_64.c                          |   11 +-
+ arch/powerpc/mm/mem.c                              |   35 +-
+ arch/powerpc/mm/mmap_64.c                          |    2 -
+ arch/powerpc/mm/numa.c                             |    9 +-
+ arch/powerpc/mm/slice.c                            |  223 +--
+ arch/powerpc/platforms/512x/mpc512x_shared.c       |    5 +-
+ arch/powerpc/platforms/cell/spufs/file.c           |    2 +-
+ arch/s390/Kconfig                                  |    1 +
+ arch/s390/Kconfig.debug                            |   14 -
+ arch/s390/hypfs/inode.c                            |    1 +
+ arch/s390/include/asm/hugetlb.h                    |   56 +-
+ arch/s390/include/asm/pgtable.h                    |   95 +-
+ arch/s390/lib/Makefile                             |    1 -
+ arch/s390/mm/hugetlbpage.c                         |    2 +-
+ arch/s390/mm/init.c                                |   35 +-
+ arch/s390/mm/mmap.c                                |    4 -
+ arch/s390/mm/vmem.c                                |   15 +-
+ arch/score/mm/init.c                               |   33 +-
+ arch/sh/include/asm/hugetlb.h                      |    1 +
+ arch/sh/kernel/sh_bios.c                           |    2 -
+ arch/sh/mm/init.c                                  |   26 +-
+ arch/sparc/include/asm/hugetlb.h                   |    1 +
+ arch/sparc/kernel/leon_smp.c                       |   15 +-
+ arch/sparc/kernel/sys_sparc_64.c                   |    2 -
+ arch/sparc/lib/Makefile                            |    1 -
+ arch/sparc/lib/usercopy.c                          |    9 -
+ arch/sparc/mm/init_32.c                            |   49 +-
+ arch/sparc/mm/init_64.c                            |   35 +-
+ arch/tile/Kconfig                                  |    8 +-
+ arch/tile/include/asm/hugetlb.h                    |    1 +
+ arch/tile/include/asm/uaccess.h                    |    7 +-
+ arch/tile/kernel/early_printk.c                    |   27 +-
+ arch/tile/lib/uaccess.c                            |    8 -
+ arch/tile/mm/mmap.c                                |    2 -
+ arch/tile/mm/pgtable.c                             |    7 +-
+ arch/um/kernel/early_printk.c                      |    8 +-
+ arch/um/kernel/mem.c                               |   26 +-
+ arch/unicore32/kernel/early_printk.c               |   12 +-
+ arch/unicore32/mm/init.c                           |   31 +-
+ arch/unicore32/mm/ioremap.c                        |   17 +-
+ arch/x86/Kconfig                                   |    2 +
+ arch/x86/Kconfig.debug                             |   14 -
+ arch/x86/boot/compressed/Makefile                  |    5 +-
+ arch/x86/boot/compressed/misc.c                    |    4 +
+ arch/x86/ia32/ia32_aout.c                          |    3 -
+ arch/x86/include/asm/e820.h                        |    2 +
+ arch/x86/include/asm/hugetlb.h                     |    1 +
+ arch/x86/kernel/cpu/Makefile                       |    4 +-
+ arch/x86/kernel/cpu/mkcapflags.pl                  |   48 -
+ arch/x86/kernel/cpu/mkcapflags.sh                  |   41 +
+ arch/x86/kernel/e820.c                             |   72 +-
+ arch/x86/kernel/early_printk.c                     |   21 +-
+ arch/x86/lib/usercopy_32.c                         |    6 -
+ arch/x86/mm/highmem_32.c                           |    1 -
+ arch/x86/mm/init.c                                 |    5 +-
+ arch/x86/mm/init_32.c                              |   10 +-
+ arch/x86/mm/init_64.c                              |   75 +-
+ arch/x86/mm/ioremap.c                              |    7 +-
+ arch/x86/mm/mmap.c                                 |    2 -
+ arch/x86/mm/numa.c                                 |    9 +-
+ arch/x86/mm/pageattr-test.c                        |    5 +-
+ arch/x86/platform/efi/efi.c                        |   15 +-
+ arch/xtensa/mm/init.c                              |   21 +-
+ block/blk-core.c                                   |   35 +-
+ block/blk-flush.c                                  |    5 +-
+ block/blk-lib.c                                    |    3 +-
+ block/blk.h                                        |    3 +-
+ block/genhd.c                                      |    2 +-
+ block/scsi_ioctl.c                                 |    1 +
+ crypto/Kconfig                                     |   16 +
+ crypto/Makefile                                    |    2 +
+ crypto/async_tx/raid6test.c                        |    9 +-
+ crypto/lz4.c                                       |  106 ++
+ crypto/lz4hc.c                                     |  106 ++
+ drivers/Kconfig                                    |    4 +-
+ drivers/block/aoe/aoechr.c                         |    3 +-
+ drivers/block/blockconsole.c                       |    5 +-
+ drivers/block/drbd/drbd_bitmap.c                   |    3 +-
+ drivers/block/drbd/drbd_receiver.c                 |    5 +-
+ drivers/block/drbd/drbd_worker.c                   |    9 +-
+ drivers/block/drbd/drbd_wrappers.h                 |    9 +-
+ drivers/block/floppy.c                             |    3 +-
+ drivers/block/mg_disk.c                            |    2 +
+ drivers/block/mtip32xx/mtip32xx.c                  |   86 +-
+ drivers/block/mtip32xx/mtip32xx.h                  |    8 +-
+ drivers/block/pktcdvd.c                            |    9 +-
+ drivers/block/swim3.c                              |    2 +-
+ drivers/block/virtio_blk.c                         |   31 +-
+ drivers/block/xen-blkback/blkback.c                |    3 +-
+ drivers/char/mem.c                                 |   36 +
+ drivers/char/random.c                              |   30 +-
+ drivers/firmware/dmi_scan.c                        |   80 +-
+ drivers/gpu/drm/drm_fb_helper.c                    |    8 +
+ drivers/infiniband/hw/cxgb3/cxio_resource.c        |    4 +-
+ drivers/infiniband/hw/cxgb4/id_table.c             |    4 +-
+ drivers/infiniband/hw/ipath/ipath_file_ops.c       |    1 +
+ drivers/infiniband/hw/mlx4/mad.c                   |    2 +-
+ drivers/infiniband/hw/qib/qib_file_ops.c           |    2 +-
+ drivers/infiniband/ulp/ipoib/ipoib_cm.c            |    2 +-
+ drivers/leds/leds-ot200.c                          |   14 +-
+ drivers/lguest/page_tables.c                       |    2 +-
+ drivers/md/bcache/btree.c                          |    3 +-
+ drivers/md/bcache/io.c                             |    6 +-
+ drivers/md/bcache/journal.c                        |    9 +-
+ drivers/md/bcache/movinggc.c                       |    3 +-
+ drivers/md/bcache/request.c                        |    9 +-
+ drivers/md/bcache/request.h                        |    3 +-
+ drivers/md/bcache/super.c                          |   11 +-
+ drivers/md/bcache/writeback.c                      |    8 +-
+ drivers/md/dm-bufio.c                              |    9 +-
+ drivers/md/dm-cache-target.c                       |    3 +-
+ drivers/md/dm-crypt.c                              |    3 +-
+ drivers/md/dm-io.c                                 |    2 +-
+ drivers/md/dm-snap.c                               |    3 +-
+ drivers/md/dm-thin.c                               |    3 +-
+ drivers/md/dm-verity.c                             |    3 +-
+ drivers/md/dm.c                                    |    8 +-
+ drivers/md/faulty.c                                |    3 +-
+ drivers/md/md.c                                    |    9 +-
+ drivers/md/multipath.c                             |    3 +-
+ drivers/md/raid1.c                                 |   12 +-
+ drivers/md/raid10.c                                |   18 +-
+ drivers/md/raid5.c                                 |   15 +-
+ drivers/memstick/host/r592.c                       |    8 +-
+ drivers/message/i2o/i2o_config.c                   |   10 +
+ drivers/mmc/core/core.c                            |    4 +-
+ drivers/net/ethernet/broadcom/cnic.c               |    4 +-
+ drivers/net/hamradio/baycom_epp.c                  |    2 +-
+ drivers/net/hamradio/hdlcdrv.c                     |    2 +-
+ drivers/net/hamradio/yam.c                         |    2 +-
+ drivers/net/team/team_mode_random.c                |    2 +-
+ drivers/net/wireless/brcm80211/brcmfmac/p2p.c      |    2 +-
+ drivers/net/wireless/mwifiex/cfg80211.c            |    4 +-
+ drivers/platform/x86/thinkpad_acpi.c               |   10 -
+ drivers/rpmsg/virtio_rpmsg_bus.c                   |    4 +-
+ drivers/rtc/class.c                                |   70 +
+ drivers/rtc/rtc-88pm80x.c                          |    5 +-
+ drivers/rtc/rtc-ab3100.c                           |   21 +-
+ drivers/rtc/rtc-at32ap700x.c                       |   12 +-
+ drivers/rtc/rtc-at91rm9200.c                       |   29 +-
+ drivers/rtc/rtc-au1xxx.c                           |   18 +-
+ drivers/rtc/rtc-bq32k.c                            |    5 +-
+ drivers/rtc/rtc-coh901331.c                        |   18 +-
+ drivers/rtc/rtc-da9052.c                           |    5 +-
+ drivers/rtc/rtc-da9055.c                           |    5 +-
+ drivers/rtc/rtc-davinci.c                          |   24 +-
+ drivers/rtc/rtc-dm355evm.c                         |    7 +-
+ drivers/rtc/rtc-ds1286.c                           |    3 +-
+ drivers/rtc/rtc-ds1302.c                           |   22 +-
+ drivers/rtc/rtc-ds1307.c                           |   70 +-
+ drivers/rtc/rtc-ds1374.c                           |   10 +-
+ drivers/rtc/rtc-ds1511.c                           |    8 +-
+ drivers/rtc/rtc-ds1553.c                           |    6 +-
+ drivers/rtc/rtc-ds1672.c                           |    8 +-
+ drivers/rtc/rtc-ds1742.c                           |    8 +-
+ drivers/rtc/rtc-ds3234.c                           |    7 +-
+ drivers/rtc/rtc-efi.c                              |   19 +-
+ drivers/rtc/rtc-em3027.c                           |    7 +-
+ drivers/rtc/rtc-ep93xx.c                           |   11 +-
+ drivers/rtc/rtc-fm3130.c                           |    2 +-
+ drivers/rtc/rtc-generic.c                          |   21 +-
+ drivers/rtc/rtc-hid-sensor-time.c                  |    7 +-
+ drivers/rtc/rtc-imxdi.c                            |   23 +-
+ drivers/rtc/rtc-lp8788.c                           |    5 +-
+ drivers/rtc/rtc-lpc32xx.c                          |    5 +-
+ drivers/rtc/rtc-ls1x.c                             |    5 +-
+ drivers/rtc/rtc-m41t93.c                           |    9 +-
+ drivers/rtc/rtc-m41t94.c                           |    9 +-
+ drivers/rtc/rtc-m48t86.c                           |   11 +-
+ drivers/rtc/rtc-max6900.c                          |    9 +-
+ drivers/rtc/rtc-max6902.c                          |    7 +-
+ drivers/rtc/rtc-max77686.c                         |   71 +-
+ drivers/rtc/rtc-max8907.c                          |   20 +-
+ drivers/rtc/rtc-max8997.c                          |   17 +-
+ drivers/rtc/rtc-mc13xxx.c                          |   12 +-
+ drivers/rtc/rtc-msm6242.c                          |   13 +-
+ drivers/rtc/rtc-mv.c                               |   23 +-
+ drivers/rtc/rtc-mxc.c                              |   15 +-
+ drivers/rtc/rtc-nuc900.c                           |   19 +-
+ drivers/rtc/rtc-omap.c                             |   57 +-
+ drivers/rtc/rtc-palmas.c                           |   19 +-
+ drivers/rtc/rtc-pcap.c                             |   19 +-
+ drivers/rtc/rtc-pcf8523.c                          |    6 +-
+ drivers/rtc/rtc-ps3.c                              |   16 +-
+ drivers/rtc/rtc-pxa.c                              |   88 +-
+ drivers/rtc/rtc-r9701.c                            |    7 +-
+ drivers/rtc/rtc-rc5t583.c                          |   19 +-
+ drivers/rtc/rtc-rp5c01.c                           |   13 +-
+ drivers/rtc/rtc-rs5c313.c                          |    6 +-
+ drivers/rtc/rtc-rv3029c2.c                         |   16 +-
+ drivers/rtc/rtc-rx4581.c                           |    7 +-
+ drivers/rtc/rtc-rx8581.c                           |    8 +-
+ drivers/rtc/rtc-s3c.c                              |   32 +-
+ drivers/rtc/rtc-sa1100.c                           |   12 +-
+ drivers/rtc/rtc-sh.c                               |   22 +-
+ drivers/rtc/rtc-snvs.c                             |    6 +-
+ drivers/rtc/rtc-spear.c                            |    5 +-
+ drivers/rtc/rtc-starfire.c                         |   23 +-
+ drivers/rtc/rtc-stk17ta8.c                         |    6 +-
+ drivers/rtc/rtc-sun4v.c                            |   22 +-
+ drivers/rtc/rtc-tegra.c                            |   64 +-
+ drivers/rtc/rtc-test.c                             |   10 +-
+ drivers/rtc/rtc-tile.c                             |    9 +-
+ drivers/rtc/rtc-tps6586x.c                         |   14 +-
+ drivers/rtc/rtc-tps65910.c                         |   13 +-
+ drivers/rtc/rtc-tps80031.c                         |   11 +-
+ drivers/rtc/rtc-tx4939.c                           |   19 +-
+ drivers/rtc/rtc-v3020.c                            |   37 +-
+ drivers/rtc/rtc-vt8500.c                           |    8 +-
+ drivers/rtc/rtc-wm831x.c                           |    6 +-
+ drivers/rtc/rtc-wm8350.c                           |   19 +-
+ drivers/rtc/rtc-x1205.c                            |   14 +-
+ drivers/scsi/fcoe/fcoe_ctlr.c                      |    4 +-
+ drivers/scsi/lpfc/lpfc_hbadisc.c                   |    6 +-
+ drivers/scsi/qla2xxx/qla_attr.c                    |   11 +-
+ drivers/scsi/sg.c                                  |    1 +
+ drivers/staging/android/logger.c                   |    1 +
+ drivers/staging/zcache/Kconfig                     |    6 +-
+ drivers/staging/zcache/ramster.h                   |    6 +-
+ drivers/staging/zcache/ramster/nodemanager.c       |    9 +-
+ drivers/staging/zcache/ramster/ramster.c           |   29 +-
+ drivers/staging/zcache/ramster/ramster.h           |    2 +-
+ .../staging/zcache/ramster/ramster_nodemanager.h   |    2 +
+ drivers/staging/zcache/tmem.c                      |    6 +-
+ drivers/staging/zcache/tmem.h                      |    8 +-
+ drivers/staging/zcache/zcache-main.c               |   64 +-
+ drivers/staging/zcache/zcache.h                    |    2 +-
+ drivers/target/target_core_iblock.c                |    6 +-
+ drivers/target/target_core_pscsi.c                 |    3 +-
+ drivers/usb/gadget/amd5536udc.c                    |    4 +-
+ drivers/usb/gadget/inode.c                         |   42 +-
+ drivers/uwb/rsv.c                                  |    4 +-
+ drivers/video/Kconfig                              |    9 +
+ drivers/video/Makefile                             |    1 +
+ drivers/video/backlight/Kconfig                    |    9 +-
+ drivers/video/backlight/Makefile                   |    1 +
+ drivers/video/backlight/adp5520_bl.c               |   28 +-
+ drivers/video/backlight/adp8860_bl.c               |   23 +-
+ drivers/video/backlight/adp8870_bl.c               |   33 +-
+ drivers/video/backlight/ams369fg06.c               |   21 +-
+ drivers/video/backlight/as3711_bl.c                |  118 +-
+ drivers/video/backlight/atmel-pwm-bl.c             |   14 +-
+ drivers/video/backlight/corgi_lcd.c                |   18 +-
+ drivers/video/backlight/da903x_bl.c                |   30 +-
+ drivers/video/backlight/ep93xx_bl.c                |   20 +-
+ drivers/video/backlight/generic_bl.c               |    6 +-
+ drivers/video/backlight/hp680_bl.c                 |   18 +-
+ drivers/video/backlight/ili922x.c                  |  555 ++++++
+ drivers/video/backlight/jornada720_bl.c            |   18 +-
+ drivers/video/backlight/jornada720_lcd.c           |   21 +-
+ drivers/video/backlight/kb3886_bl.c                |   18 +-
+ drivers/video/backlight/l4f00242t03.c              |   27 +-
+ drivers/video/backlight/ld9040.c                   |   20 +-
+ drivers/video/backlight/lm3533_bl.c                |   22 +-
+ drivers/video/backlight/lms501kf03.c               |   22 +-
+ drivers/video/backlight/locomolcd.c                |   16 +-
+ drivers/video/backlight/lp855x_bl.c                |    7 +-
+ drivers/video/backlight/ltv350qv.c                 |   18 +-
+ drivers/video/backlight/omap1_bl.c                 |    4 +-
+ drivers/video/backlight/platform_lcd.c             |    6 +-
+ drivers/video/backlight/s6e63m0.c                  |   20 +-
+ drivers/video/backlight/tdo24m.c                   |   18 +-
+ drivers/video/console/fbcon_cw.c                   |    3 +-
+ drivers/video/cyber2000fb.c                        |    3 +
+ drivers/video/ep93xx-fb.c                          |   18 +-
+ drivers/video/exynos/exynos_mipi_dsi.c             |    8 +-
+ drivers/video/hyperv_fb.c                          |  829 +++++++++
+ drivers/video/matrox/matroxfb_maven.c              |   16 +-
+ drivers/video/mmp/hw/mmp_ctrl.h                    |  479 +-----
+ drivers/video/uvesafb.c                            |    2 +-
+ drivers/xen/Kconfig                                |    4 +-
+ drivers/xen/tmem.c                                 |   55 +-
+ drivers/xen/xen-selfballoon.c                      |   13 +-
+ fs/9p/vfs_addr.c                                   |    1 +
+ fs/Kconfig.binfmt                                  |   14 +
+ fs/Makefile                                        |    8 +-
+ fs/afs/write.c                                     |    1 +
+ fs/aio.c                                           | 1820 ++++++++------------
+ fs/binfmt_aout.c                                   |    3 -
+ fs/binfmt_elf.c                                    |   26 +-
+ fs/binfmt_elf_fdpic.c                              |    2 -
+ fs/bio-integrity.c                                 |    3 +-
+ fs/bio.c                                           |   66 +-
+ fs/block_dev.c                                     |    9 +-
+ fs/btrfs/check-integrity.c                         |   14 +-
+ fs/btrfs/compression.c                             |    6 +-
+ fs/btrfs/disk-io.c                                 |    6 +-
+ fs/btrfs/extent_io.c                               |   12 +-
+ fs/btrfs/file.c                                    |    1 +
+ fs/btrfs/inode.c                                   |   14 +-
+ fs/btrfs/raid56.c                                  |    9 +-
+ fs/btrfs/scrub.c                                   |   18 +-
+ fs/btrfs/volumes.c                                 |    5 +-
+ fs/buffer.c                                        |   12 +-
+ fs/ceph/file.c                                     |    1 +
+ fs/compat.c                                        |    1 +
+ fs/coredump.c                                      |   85 +-
+ fs/direct-io.c                                     |   25 +-
+ fs/drop_caches.c                                   |    2 +
+ fs/ecryptfs/file.c                                 |    1 +
+ fs/eventpoll.c                                     |  168 +-
+ fs/exec.c                                          |   17 +-
+ fs/ext2/inode.c                                    |    1 +
+ fs/ext3/inode.c                                    |    1 +
+ fs/ext3/super.c                                    |    1 -
+ fs/ext4/file.c                                     |    1 +
+ fs/ext4/indirect.c                                 |    1 +
+ fs/ext4/inode.c                                    |    1 +
+ fs/ext4/page-io.c                                  |    4 +-
+ fs/f2fs/data.c                                     |    3 +-
+ fs/f2fs/segment.c                                  |    3 +-
+ fs/fat/dir.c                                       |   23 +
+ fs/fat/fat.h                                       |   40 +-
+ fs/fat/file.c                                      |    5 +
+ fs/fat/inode.c                                     |   75 +-
+ fs/fat/nfs.c                                       |  221 ++-
+ fs/fuse/cuse.c                                     |    1 +
+ fs/fuse/dev.c                                      |    1 +
+ fs/fuse/file.c                                     |    1 +
+ fs/gfs2/aops.c                                     |    1 +
+ fs/gfs2/file.c                                     |    1 +
+ fs/gfs2/lops.c                                     |    3 +-
+ fs/gfs2/ops_fstype.c                               |    3 +-
+ fs/hfs/inode.c                                     |    1 +
+ fs/hfsplus/bfind.c                                 |    8 +-
+ fs/hfsplus/inode.c                                 |    1 +
+ fs/hfsplus/wrapper.c                               |    3 +-
+ fs/jbd/commit.c                                    |    4 +-
+ fs/jfs/inode.c                                     |    1 +
+ fs/jfs/jfs_logmgr.c                                |    4 +-
+ fs/jfs/jfs_metapage.c                              |    6 +-
+ fs/logfs/dev_bdev.c                                |    8 +-
+ fs/mpage.c                                         |    2 +-
+ fs/nfs/blocklayout/blocklayout.c                   |   17 +-
+ fs/nilfs2/inode.c                                  |    2 +-
+ fs/nilfs2/segbuf.c                                 |    3 +-
+ fs/ntfs/file.c                                     |    1 +
+ fs/ntfs/inode.c                                    |    1 +
+ fs/ocfs2/aops.h                                    |    2 +
+ fs/ocfs2/cluster/heartbeat.c                       |    4 +-
+ fs/ocfs2/dlmglue.c                                 |    2 +-
+ fs/ocfs2/inode.h                                   |    2 +
+ fs/ocfs2/ioctl.c                                   |   18 +-
+ fs/pipe.c                                          |    1 +
+ fs/proc/Makefile                                   |    2 +-
+ fs/proc/internal.h                                 |   18 -
+ fs/proc/meminfo.c                                  |    1 +
+ fs/proc/mmu.c                                      |   60 -
+ fs/read_write.c                                    |   35 +-
+ fs/reiserfs/inode.c                                |    1 +
+ fs/ubifs/file.c                                    |    1 +
+ fs/udf/inode.c                                     |    1 +
+ fs/xfs/xfs_aops.c                                  |    4 +-
+ fs/xfs/xfs_buf.c                                   |    3 +-
+ fs/xfs/xfs_file.c                                  |    1 +
+ include/Kbuild                                     |    3 -
+ include/asm-generic/hugetlb.h                      |   40 +
+ include/asm-generic/pgtable.h                      |   10 +
+ include/linux/aio.h                                |  199 +--
+ include/linux/balloon_compaction.h                 |    7 +
+ include/linux/batch_complete.h                     |   23 +
+ include/linux/bio.h                                |   38 +-
+ include/linux/blk_types.h                          |   10 +-
+ include/linux/blkdev.h                             |   12 +-
+ include/linux/buffer_head.h                        |    1 +
+ include/linux/cgroup.h                             |    8 +-
+ include/linux/cleancache.h                         |    4 +-
+ include/linux/console.h                            |    1 +
+ include/linux/debug_locks.h                        |    2 +-
+ include/linux/decompress/unlz4.h                   |   10 +
+ include/linux/errno.h                              |    1 -
+ include/linux/exportfs.h                           |   11 +
+ include/linux/frontswap.h                          |   36 +-
+ include/linux/fs.h                                 |    4 +-
+ include/linux/hardirq.h                            |    5 +
+ include/linux/hugetlb.h                            |    4 +
+ include/linux/hyperv.h                             |   11 +
+ include/linux/kmod.h                               |   17 +-
+ include/linux/lockdep.h                            |   92 +-
+ include/linux/lz4.h                                |   87 +
+ include/linux/mm.h                                 |   76 +-
+ include/linux/mm_types.h                           |    3 -
+ include/linux/mmzone.h                             |   20 +-
+ include/linux/net.h                                |    4 +-
+ include/linux/pagemap.h                            |    2 +-
+ include/linux/percpu-refcount.h                    |  114 ++
+ include/linux/pid_namespace.h                      |    5 +-
+ include/linux/posix-timers.h                       |   16 +-
+ include/linux/printk.h                             |    7 +
+ include/linux/ramfs.h                              |    8 +-
+ include/linux/random.h                             |    7 -
+ include/linux/relay.h                              |    3 -
+ include/linux/rtc-pxa.h                            |   18 +
+ include/linux/rtc.h                                |    6 +
+ include/linux/sched.h                              |   23 +-
+ include/linux/swap.h                               |    3 +-
+ include/linux/vm_event_item.h                      |    7 +-
+ include/linux/vmalloc.h                            |   34 +-
+ include/linux/wait.h                               |   86 +
+ include/linux/writeback.h                          |    1 +
+ include/net/ip_vs.h                                |    8 +-
+ include/scsi/Kbuild                                |    1 -
+ include/trace/events/filemap.h                     |   58 +
+ include/trace/events/printk.h                      |   25 +-
+ include/uapi/linux/eventpoll.h                     |    1 +
+ include/uapi/linux/fs.h                            |    1 -
+ include/uapi/linux/ptrace.h                        |   12 +
+ include/xen/tmem.h                                 |    8 +
+ init/Kconfig                                       |   36 +-
+ init/do_mounts_initrd.c                            |    8 +-
+ init/main.c                                        |   42 +-
+ ipc/msg.c                                          |   85 +-
+ ipc/msgutil.c                                      |  110 +-
+ ipc/sem.c                                          |  654 ++++---
+ ipc/util.c                                         |  102 +-
+ ipc/util.h                                         |   17 +-
+ kernel/cgroup.c                                    |   49 -
+ kernel/fork.c                                      |    5 +-
+ kernel/hrtimer.c                                   |    4 +
+ kernel/kexec.c                                     |   43 +-
+ kernel/kmod.c                                      |   98 +-
+ kernel/kthread.c                                   |   44 +-
+ kernel/lglock.c                                    |   12 +-
+ kernel/pid.c                                       |   11 +-
+ kernel/pid_namespace.c                             |    2 -
+ kernel/posix-cpu-timers.c                          |  390 ++---
+ kernel/printk.c                                    |   33 +-
+ kernel/ptrace.c                                    |   81 +
+ kernel/range.c                                     |    3 +-
+ kernel/rcutree.c                                   |    2 +-
+ kernel/relay.c                                     |   14 +-
+ kernel/semaphore.c                                 |    8 +-
+ kernel/signal.c                                    |    6 +-
+ kernel/smp.c                                       |  102 +-
+ kernel/sys.c                                       |   10 +-
+ kernel/sysctl.c                                    |    1 -
+ kernel/test_kprobes.c                              |    2 +-
+ kernel/time/timer_list.c                           |  112 +-
+ kernel/watchdog.c                                  |   15 +-
+ lib/Kconfig                                        |   13 +
+ lib/Kconfig.debug                                  |   18 +
+ lib/Makefile                                       |    7 +-
+ lib/argv_split.c                                   |   87 +-
+ lib/decompress.c                                   |    5 +
+ lib/decompress_unlz4.c                             |  187 ++
+ lib/fault-inject.c                                 |    2 +-
+ lib/int_sqrt.c                                     |   32 +-
+ lib/list_sort.c                                    |    2 +-
+ lib/lz4/Makefile                                   |    3 +
+ lib/lz4/lz4_compress.c                             |  443 +++++
+ lib/lz4/lz4_decompress.c                           |  326 ++++
+ lib/lz4/lz4defs.h                                  |  156 ++
+ lib/lz4/lz4hc_compress.c                           |  539 ++++++
+ lib/percpu-refcount.c                              |  244 +++
+ lib/show_mem.c                                     |    3 +
+ {arch/s390/lib => lib}/usercopy.c                  |    3 +-
+ lib/uuid.c                                         |    8 +-
+ mm/balloon_compaction.c                            |    2 +
+ mm/bounce.c                                        |   33 +-
+ mm/cleancache.c                                    |  265 ++-
+ mm/dmapool.c                                       |    5 +-
+ mm/filemap.c                                       |    5 +
+ mm/frontswap.c                                     |  156 +-
+ mm/hugetlb.c                                       |   38 +-
+ mm/memblock.c                                      |    3 +
+ mm/memcontrol.c                                    |  346 +++-
+ mm/memory-failure.c                                |    4 +-
+ mm/memory_hotplug.c                                |    2 +-
+ mm/migrate.c                                       |    3 +-
+ mm/mmap.c                                          |   37 +-
+ mm/mmu_context.c                                   |    3 -
+ mm/nommu.c                                         |    7 +-
+ mm/page-writeback.c                                |    4 -
+ mm/page_alloc.c                                    |   82 +-
+ mm/page_io.c                                       |    6 +-
+ mm/rmap.c                                          |    3 +
+ mm/shmem.c                                         |    6 +-
+ mm/sparse-vmemmap.c                                |   27 +-
+ mm/sparse.c                                        |   10 +-
+ mm/swap.c                                          |    1 +
+ mm/swapfile.c                                      |   19 +-
+ mm/util.c                                          |    1 -
+ mm/vmalloc.c                                       |  218 ++-
+ mm/vmscan.c                                        |    4 -
+ mm/vmstat.c                                        |    9 +-
+ net/core/pktgen.c                                  |   42 +-
+ net/netfilter/ipvs/ip_vs_ctl.c                     |    4 +-
+ net/netfilter/nf_conntrack_core.c                  |    4 +-
+ net/sched/sch_choke.c                              |    2 +-
+ net/sunrpc/auth_gss/gss_krb5_wrap.c                |    4 +-
+ scripts/Makefile.headersinst                       |    4 +-
+ scripts/Makefile.lib                               |    5 +
+ scripts/checkpatch.pl                              |   26 +-
+ scripts/decodecode                                 |    8 +-
+ scripts/get_maintainer.pl                          |    2 +-
+ scripts/headers_install.pl                         |   63 -
+ scripts/headers_install.sh                         |   43 +
+ security/keys/internal.h                           |    2 +
+ security/keys/keyctl.c                             |    1 +
+ security/keys/request_key.c                        |   13 +-
+ sound/core/pcm_native.c                            |    2 +-
+ tools/testing/selftests/Makefile                   |    3 +
+ tools/testing/selftests/epoll/Makefile             |   11 +
+ tools/testing/selftests/epoll/test_epoll.c         |  364 ++++
+ tools/testing/selftests/ptrace/Makefile            |   10 +
+ tools/testing/selftests/ptrace/peeksiginfo.c       |  214 +++
+ tools/testing/selftests/timers/Makefile            |    8 +
+ tools/testing/selftests/timers/posix_timers.c      |  221 +++
+ usr/Kconfig                                        |    9 +
+ 566 files changed, 11235 insertions(+), 6468 deletions(-)
+ create mode 100644 arch/arm/boot/compressed/piggy.lz4.S
+ delete mode 100644 arch/sparc/lib/usercopy.c
+ delete mode 100644 arch/x86/kernel/cpu/mkcapflags.pl
+ create mode 100644 arch/x86/kernel/cpu/mkcapflags.sh
+ create mode 100644 crypto/lz4.c
+ create mode 100644 crypto/lz4hc.c
+ create mode 100644 drivers/video/backlight/ili922x.c
+ create mode 100644 drivers/video/hyperv_fb.c
+ delete mode 100644 fs/proc/mmu.c
+ create mode 100644 include/asm-generic/hugetlb.h
+ create mode 100644 include/linux/batch_complete.h
+ create mode 100644 include/linux/decompress/unlz4.h
+ create mode 100644 include/linux/lz4.h
+ create mode 100644 include/linux/percpu-refcount.h
+ create mode 100644 include/linux/rtc-pxa.h
+ delete mode 100644 include/scsi/Kbuild
+ create mode 100644 include/trace/events/filemap.h
+ create mode 100644 lib/decompress_unlz4.c
+ create mode 100644 lib/lz4/Makefile
+ create mode 100644 lib/lz4/lz4_compress.c
+ create mode 100644 lib/lz4/lz4_decompress.c
+ create mode 100644 lib/lz4/lz4defs.h
+ create mode 100644 lib/lz4/lz4hc_compress.c
+ create mode 100644 lib/percpu-refcount.c
+ rename {arch/s390/lib => lib}/usercopy.c (73%)
+ delete mode 100644 scripts/headers_install.pl
+ create mode 100644 scripts/headers_install.sh
+ create mode 100644 tools/testing/selftests/epoll/Makefile
+ create mode 100644 tools/testing/selftests/epoll/test_epoll.c
+ create mode 100644 tools/testing/selftests/ptrace/Makefile
+ create mode 100644 tools/testing/selftests/ptrace/peeksiginfo.c
+ create mode 100644 tools/testing/selftests/timers/Makefile
+ create mode 100644 tools/testing/selftests/timers/posix_timers.c
diff --git a/Next/quilt-import.log b/Next/quilt-import.log
new file mode 100644
index 0000000..00d6c73
--- /dev/null
+++ b/Next/quilt-import.log
@@ -0,0 +1,4 @@
+Importing jdelvare-hwmon based on 10b38669d64c757cfd927e3820292c580ed70aae
+Unchanged quilt series jdelvare-hwmon
+Importing device-mapper based on v3.9-rc4
+Unchanged quilt series device-mapper
diff --git a/arch/Kconfig b/arch/Kconfig
index 1455579..dd0e8eb 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -157,9 +157,6 @@ config ARCH_USE_BUILTIN_BSWAP
 	 instructions should set this. And it shouldn't hurt to set it
 	 on architectures that don't have such instructions.
 
-config HAVE_SYSCALL_WRAPPERS
-	bool
-
 config KRETPROBES
 	def_bool y
 	depends on KPROBES && HAVE_KRETPROBES
@@ -384,6 +381,12 @@ config MODULES_USE_ELF_REL
 	  Modules only use ELF REL relocations.  Modules with ELF RELA
 	  relocations will give an error.
 
+config HAVE_UNDERSCORE_SYMBOL_PREFIX
+	bool
+	help
+	  Some architectures generate an _ in front of C symbols; things like
+	  module loading and assembly files need to know about this.
+
 #
 # ABI hall of shame
 #
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig
index 8a33ba0..8629127 100644
--- a/arch/alpha/Kconfig
+++ b/arch/alpha/Kconfig
@@ -4,7 +4,6 @@ config ALPHA
 	select HAVE_AOUT
 	select HAVE_IDE
 	select HAVE_OPROFILE
-	select HAVE_SYSCALL_WRAPPERS
 	select HAVE_PCSPKR_PLATFORM
 	select HAVE_PERF_EVENTS
 	select HAVE_DMA_ATTRS
diff --git a/arch/alpha/include/asm/linkage.h b/arch/alpha/include/asm/linkage.h
index 291c2d0..7cfd06e 100644
--- a/arch/alpha/include/asm/linkage.h
+++ b/arch/alpha/include/asm/linkage.h
@@ -1,6 +1,8 @@
 #ifndef __ASM_LINKAGE_H
 #define __ASM_LINKAGE_H
 
-/* Nothing to see here... */
+#define cond_syscall(x)  asm(".weak\t" #x "\n" #x " = sys_ni_syscall")
+#define SYSCALL_ALIAS(alias, name)					\
+	asm ( #alias " = " #name "\n\t.globl " #alias)
 
 #endif
diff --git a/arch/alpha/include/asm/unistd.h b/arch/alpha/include/asm/unistd.h
index 6d6fe7a..43baee1 100644
--- a/arch/alpha/include/asm/unistd.h
+++ b/arch/alpha/include/asm/unistd.h
@@ -18,16 +18,4 @@
 #define __ARCH_WANT_SYS_VFORK
 #define __ARCH_WANT_SYS_CLONE
 
-/* "Conditional" syscalls.  What we want is
-
-	__attribute__((weak,alias("sys_ni_syscall")))
-
-   but that raises the problem of what type to give the symbol.  If we use
-   a prototype, it'll conflict with the definition given in this file and
-   others.  If we use __typeof, we discover that not all symbols actually
-   have declarations.  If we use no prototype, then we get warnings from
-   -Wstrict-prototypes.  Ho hum.  */
-
-#define cond_syscall(x)  asm(".weak\t" #x "\n" #x " = sys_ni_syscall")
-
 #endif /* _ALPHA_UNISTD_H */
diff --git a/arch/alpha/include/uapi/asm/socket.h b/arch/alpha/include/uapi/asm/socket.h
index c519552..eee6ea7 100644
--- a/arch/alpha/include/uapi/asm/socket.h
+++ b/arch/alpha/include/uapi/asm/socket.h
@@ -79,4 +79,6 @@
 
 #define SO_LOCK_FILTER		44
 
+#define SO_SELECT_ERR_QUEUE	45
+
 #endif /* _UAPI_ASM_SOCKET_H */
diff --git a/arch/alpha/kernel/srm_env.c b/arch/alpha/kernel/srm_env.c
index e64559f..ffe996a 100644
--- a/arch/alpha/kernel/srm_env.c
+++ b/arch/alpha/kernel/srm_env.c
@@ -51,13 +51,11 @@ MODULE_LICENSE("GPL");
 typedef struct _srm_env {
 	char			*name;
 	unsigned long		id;
-	struct proc_dir_entry	*proc_entry;
 } srm_env_t;
 
 static struct proc_dir_entry	*base_dir;
 static struct proc_dir_entry	*named_dir;
 static struct proc_dir_entry	*numbered_dir;
-static char			number[256][4];
 
 static srm_env_t	srm_named_entries[] = {
 	{ "auto_action",	ENV_AUTO_ACTION		},
@@ -77,21 +75,18 @@ static srm_env_t	srm_named_entries[] = {
 	{ "tty_dev",		ENV_TTY_DEV		},
 	{ NULL,			0			},
 };
-static srm_env_t	srm_numbered_entries[256];
-
 
 static int srm_env_proc_show(struct seq_file *m, void *v)
 {
 	unsigned long	ret;
-	srm_env_t	*entry;
+	unsigned long	id = (unsigned long)m->private;
 	char		*page;
 
-	entry = m->private;
 	page = (char *)__get_free_page(GFP_USER);
 	if (!page)
 		return -ENOMEM;
 
-	ret = callback_getenv(entry->id, page, PAGE_SIZE);
+	ret = callback_getenv(id, page, PAGE_SIZE);
 
 	if ((ret >> 61) == 0) {
 		seq_write(m, page, ret);
@@ -104,14 +99,14 @@ static int srm_env_proc_show(struct seq_file *m, void *v)
 
 static int srm_env_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, srm_env_proc_show, PDE(inode)->data);
+	return single_open(file, srm_env_proc_show, PDE_DATA(inode));
 }
 
 static ssize_t srm_env_proc_write(struct file *file, const char __user *buffer,
 				  size_t count, loff_t *pos)
 {
 	int res;
-	srm_env_t	*entry = PDE(file_inode(file))->data;
+	unsigned long	id = (unsigned long)PDE_DATA(file_inode(file));
 	char		*buf = (char *) __get_free_page(GFP_USER);
 	unsigned long	ret1, ret2;
 
@@ -127,7 +122,7 @@ static ssize_t srm_env_proc_write(struct file *file, const char __user *buffer,
 		goto out;
 	buf[count] = '\0';
 
-	ret1 = callback_setenv(entry->id, buf, count);
+	ret1 = callback_setenv(id, buf, count);
 	if ((ret1 >> 61) == 0) {
 		do
 			ret2 = callback_save_env();
@@ -149,52 +144,6 @@ static const struct file_operations srm_env_proc_fops = {
 	.write		= srm_env_proc_write,
 };
 
-static void
-srm_env_cleanup(void)
-{
-	srm_env_t	*entry;
-	unsigned long	var_num;
-
-	if (base_dir) {
-		/*
-		 * Remove named entries
-		 */
-		if (named_dir) {
-			entry = srm_named_entries;
-			while (entry->name != NULL && entry->id != 0) {
-				if (entry->proc_entry) {
-					remove_proc_entry(entry->name,
-							named_dir);
-					entry->proc_entry = NULL;
-				}
-				entry++;
-			}
-			remove_proc_entry(NAMED_DIR, base_dir);
-		}
-
-		/*
-		 * Remove numbered entries
-		 */
-		if (numbered_dir) {
-			for (var_num = 0; var_num <= 255; var_num++) {
-				entry =	&srm_numbered_entries[var_num];
-
-				if (entry->proc_entry) {
-					remove_proc_entry(entry->name,
-							numbered_dir);
-					entry->proc_entry	= NULL;
-					entry->name		= NULL;
-				}
-			}
-			remove_proc_entry(NUMBERED_DIR, base_dir);
-		}
-
-		remove_proc_entry(BASE_DIR, NULL);
-	}
-
-	return;
-}
-
 static int __init
 srm_env_init(void)
 {
@@ -213,19 +162,13 @@ srm_env_init(void)
 	}
 
 	/*
-	 * Init numbers
-	 */
-	for (var_num = 0; var_num <= 255; var_num++)
-		sprintf(number[var_num], "%ld", var_num);
-
-	/*
 	 * Create base directory
 	 */
 	base_dir = proc_mkdir(BASE_DIR, NULL);
 	if (!base_dir) {
 		printk(KERN_ERR "Couldn't create base dir /proc/%s\n",
 				BASE_DIR);
-		goto cleanup;
+		return -ENOMEM;
 	}
 
 	/*
@@ -254,9 +197,8 @@ srm_env_init(void)
 	 */
 	entry = srm_named_entries;
 	while (entry->name && entry->id) {
-		entry->proc_entry = proc_create_data(entry->name, 0644, named_dir,
-						     &srm_env_proc_fops, entry);
-		if (!entry->proc_entry)
+		if (!proc_create_data(entry->name, 0644, named_dir,
+			     &srm_env_proc_fops, (void *)entry->id))
 			goto cleanup;
 		entry++;
 	}
@@ -265,15 +207,11 @@ srm_env_init(void)
 	 * Create all numbered nodes
 	 */
 	for (var_num = 0; var_num <= 255; var_num++) {
-		entry = &srm_numbered_entries[var_num];
-		entry->name = number[var_num];
-
-		entry->proc_entry = proc_create_data(entry->name, 0644, numbered_dir,
-						     &srm_env_proc_fops, entry);
-		if (!entry->proc_entry)
+		char name[4];
+		sprintf(name, "%ld", var_num);
+		if (!proc_create_data(name, 0644, numbered_dir,
+			     &srm_env_proc_fops, (void *)var_num))
 			goto cleanup;
-
-		entry->id			= var_num;
 	}
 
 	printk(KERN_INFO "%s: version %s loaded successfully\n", NAME,
@@ -282,18 +220,15 @@ srm_env_init(void)
 	return 0;
 
 cleanup:
-	srm_env_cleanup();
-
+	remove_proc_subtree(BASE_DIR, NULL);
 	return -ENOMEM;
 }
 
 static void __exit
 srm_env_exit(void)
 {
-	srm_env_cleanup();
+	remove_proc_subtree(BASE_DIR, NULL);
 	printk(KERN_INFO "%s: unloaded successfully\n", NAME);
-
-	return;
 }
 
 module_init(srm_env_init);
diff --git a/arch/alpha/kernel/sys_nautilus.c b/arch/alpha/kernel/sys_nautilus.c
index 4d4c046..a8b9d66 100644
--- a/arch/alpha/kernel/sys_nautilus.c
+++ b/arch/alpha/kernel/sys_nautilus.c
@@ -185,7 +185,6 @@ nautilus_machine_check(unsigned long vector, unsigned long la_ptr)
 	mb();
 }
 
-extern void free_reserved_mem(void *, void *);
 extern void pcibios_claim_one_bus(struct pci_bus *);
 
 static struct resource irongate_mem = {
@@ -234,8 +233,8 @@ nautilus_init_pci(void)
 	if (pci_mem < memtop)
 		memtop = pci_mem;
 	if (memtop > alpha_mv.min_mem_address) {
-		free_reserved_mem(__va(alpha_mv.min_mem_address),
-				  __va(memtop));
+		free_reserved_area((unsigned long)__va(alpha_mv.min_mem_address),
+				   (unsigned long)__va(memtop), 0, NULL);
 		printk("nautilus_init_pci: %ldk freed\n",
 			(memtop - alpha_mv.min_mem_address) >> 10);
 	}
diff --git a/arch/alpha/mm/init.c b/arch/alpha/mm/init.c
index 1ad6ca7..0ba85ee 100644
--- a/arch/alpha/mm/init.c
+++ b/arch/alpha/mm/init.c
@@ -31,6 +31,7 @@
 #include <asm/console.h>
 #include <asm/tlb.h>
 #include <asm/setup.h>
+#include <asm/sections.h>
 
 extern void die_if_kernel(char *,struct pt_regs *,long);
 
@@ -281,8 +282,6 @@ printk_memory_info(void)
 {
 	unsigned long codesize, reservedpages, datasize, initsize, tmp;
 	extern int page_is_ram(unsigned long) __init;
-	extern char _text, _etext, _data, _edata;
-	extern char __init_begin, __init_end;
 
 	/* printk all informations */
 	reservedpages = 0;
@@ -318,32 +317,15 @@ mem_init(void)
 #endif /* CONFIG_DISCONTIGMEM */
 
 void
-free_reserved_mem(void *start, void *end)
-{
-	void *__start = start;
-	for (; __start < end; __start += PAGE_SIZE) {
-		ClearPageReserved(virt_to_page(__start));
-		init_page_count(virt_to_page(__start));
-		free_page((long)__start);
-		totalram_pages++;
-	}
-}
-
-void
 free_initmem(void)
 {
-	extern char __init_begin, __init_end;
-
-	free_reserved_mem(&__init_begin, &__init_end);
-	printk ("Freeing unused kernel memory: %ldk freed\n",
-		(&__init_end - &__init_begin) >> 10);
+	free_initmem_default(0);
 }
 
 #ifdef CONFIG_BLK_DEV_INITRD
 void
 free_initrd_mem(unsigned long start, unsigned long end)
 {
-	free_reserved_mem((void *)start, (void *)end);
-	printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
+	free_reserved_area(start, end, 0, "initrd");
 }
 #endif
diff --git a/arch/alpha/mm/numa.c b/arch/alpha/mm/numa.c
index 3973ae3..3388504 100644
--- a/arch/alpha/mm/numa.c
+++ b/arch/alpha/mm/numa.c
@@ -17,6 +17,7 @@
 
 #include <asm/hwrpb.h>
 #include <asm/pgalloc.h>
+#include <asm/sections.h>
 
 pg_data_t node_data[MAX_NUMNODES];
 EXPORT_SYMBOL(node_data);
@@ -325,8 +326,6 @@ void __init mem_init(void)
 {
 	unsigned long codesize, reservedpages, datasize, initsize, pfn;
 	extern int page_is_ram(unsigned long) __init;
-	extern char _text, _etext, _data, _edata;
-	extern char __init_begin, __init_end;
 	unsigned long nid, i;
 	high_memory = (void *) __va(max_low_pfn << PAGE_SHIFT);
 
diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
index e6f4eca..44541f1 100644
--- a/arch/arc/Kconfig
+++ b/arch/arc/Kconfig
@@ -134,9 +134,6 @@ if SMP
 config ARC_HAS_COH_CACHES
 	def_bool n
 
-config ARC_HAS_COH_LLSC
-	def_bool n
-
 config ARC_HAS_COH_RTSC
 	def_bool n
 
@@ -304,6 +301,9 @@ config ARC_FPU_SAVE_RESTORE
 	  based on actual usage of FPU by a task. Thus our implemn does
 	  this for all tasks in system.
 
+config ARC_CANT_LLSC
+	def_bool n
+
 menuconfig ARC_CPU_REL_4_10
 	bool "Enable support for Rel 4.10 features"
 	default n
@@ -314,9 +314,7 @@ menuconfig ARC_CPU_REL_4_10
 config ARC_HAS_LLSC
 	bool "Insn: LLOCK/SCOND (efficient atomic ops)"
 	default y
-	depends on ARC_CPU_770
-	# if SMP, enable LLSC ONLY if ARC implementation has coherent atomics
-	depends on !SMP || ARC_HAS_COH_LLSC
+	depends on ARC_CPU_770 && !ARC_CANT_LLSC
 
 config ARC_HAS_SWAPE
 	bool "Insn: SWAPE (endian-swap)"
diff --git a/arch/arc/Makefile b/arch/arc/Makefile
index 92379c7..f30e0a1 100644
--- a/arch/arc/Makefile
+++ b/arch/arc/Makefile
@@ -8,6 +8,10 @@
 
 UTS_MACHINE := arc
 
+ifeq ($(CROSS_COMPILE),)
+CROSS_COMPILE := arc-elf32-
+endif
+
 KBUILD_DEFCONFIG := fpga_defconfig
 
 cflags-y	+= -mA7 -fno-common -pipe -fno-builtin -D__linux__
@@ -92,15 +96,17 @@ drivers-$(CONFIG_OPROFILE)	+= arch/arc/oprofile/
 
 libs-y		+= arch/arc/lib/ $(LIBGCC)
 
+boot		:= arch/arc/boot
+
 #default target for make without any arguements.
-KBUILD_IMAGE := bootpImage
+KBUILD_IMAGE	:= bootpImage
 
 all:	$(KBUILD_IMAGE)
-boot	:= arch/arc/boot
-
 bootpImage: vmlinux
 
-uImage: vmlinux
+boot_targets += uImage uImage.bin uImage.gz
+
+$(boot_targets): vmlinux
 	$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
 
 %.dtb %.dtb.S %.dtb.o: scripts
diff --git a/arch/arc/boot/Makefile b/arch/arc/boot/Makefile
index 7d514c2..e597cb34 100644
--- a/arch/arc/boot/Makefile
+++ b/arch/arc/boot/Makefile
@@ -3,7 +3,6 @@ targets := vmlinux.bin vmlinux.bin.gz uImage
 # uImage build relies on mkimage being availble on your host for ARC target
 # You will need to build u-boot for ARC, rename mkimage to arc-elf32-mkimage
 # and make sure it's reacable from your PATH
-MKIMAGE := $(srctree)/scripts/mkuboot.sh
 
 OBJCOPYFLAGS= -O binary -R .note -R .note.gnu.build-id -R .comment -S
 
@@ -12,7 +11,12 @@ LINUX_START_TEXT = $$(readelf -h vmlinux | \
 
 UIMAGE_LOADADDR    = $(CONFIG_LINUX_LINK_BASE)
 UIMAGE_ENTRYADDR   = $(LINUX_START_TEXT)
-UIMAGE_COMPRESSION = gzip
+
+suffix-y := bin
+suffix-$(CONFIG_KERNEL_GZIP)	:= gz
+
+targets += uImage uImage.bin uImage.gz
+extra-y += vmlinux.bin vmlinux.bin.gz
 
 $(obj)/vmlinux.bin: vmlinux FORCE
 	$(call if_changed,objcopy)
@@ -20,7 +24,12 @@ $(obj)/vmlinux.bin: vmlinux FORCE
 $(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
 	$(call if_changed,gzip)
 
-$(obj)/uImage: $(obj)/vmlinux.bin.gz FORCE
-	$(call if_changed,uimage)
+$(obj)/uImage.bin: $(obj)/vmlinux.bin FORCE
+	$(call if_changed,uimage,none)
+
+$(obj)/uImage.gz: $(obj)/vmlinux.bin.gz FORCE
+	$(call if_changed,uimage,gzip)
 
-PHONY += FORCE
+$(obj)/uImage: $(obj)/uImage.$(suffix-y)
+	@ln -sf $(notdir $<) $@
+	@echo '  Image $@ is ready'
diff --git a/arch/arc/kernel/asm-offsets.c b/arch/arc/kernel/asm-offsets.c
index 0dc148e..7dcda70 100644
--- a/arch/arc/kernel/asm-offsets.c
+++ b/arch/arc/kernel/asm-offsets.c
@@ -11,9 +11,9 @@
 #include <linux/interrupt.h>
 #include <linux/thread_info.h>
 #include <linux/kbuild.h>
+#include <linux/ptrace.h>
 #include <asm/hardirq.h>
 #include <asm/page.h>
-#include <asm/ptrace.h>
 
 int main(void)
 {
diff --git a/arch/arc/kernel/clk.c b/arch/arc/kernel/clk.c
index 66ce0dc..10c7b0b 100644
--- a/arch/arc/kernel/clk.c
+++ b/arch/arc/kernel/clk.c
@@ -8,7 +8,7 @@
 
 #include <asm/clk.h>
 
-unsigned long core_freq = 800000000;
+unsigned long core_freq = 80000000;
 
 /*
  * As of now we default to device-tree provided clock
diff --git a/arch/arc/kernel/disasm.c b/arch/arc/kernel/disasm.c
index 2f39028..b8a549c 100644
--- a/arch/arc/kernel/disasm.c
+++ b/arch/arc/kernel/disasm.c
@@ -12,8 +12,8 @@
 #include <linux/types.h>
 #include <linux/kprobes.h>
 #include <linux/slab.h>
+#include <linux/uaccess.h>
 #include <asm/disasm.h>
-#include <asm/uaccess.h>
 
 #if defined(CONFIG_KGDB) || defined(CONFIG_ARC_MISALIGN_ACCESS) || \
 	defined(CONFIG_KPROBES)
@@ -535,4 +535,4 @@ int __kprobes disasm_next_pc(unsigned long pc, struct pt_regs *regs,
 	return instr.is_branch;
 }
 
-#endif /* CONFIG_KGDB || CONFIG_MISALIGN_ACCESS || CONFIG_KPROBES */
+#endif /* CONFIG_KGDB || CONFIG_ARC_MISALIGN_ACCESS || CONFIG_KPROBES */
diff --git a/arch/arc/kernel/irq.c b/arch/arc/kernel/irq.c
index 551c10d..d32c050 100644
--- a/arch/arc/kernel/irq.c
+++ b/arch/arc/kernel/irq.c
@@ -102,7 +102,7 @@ void __init init_onchip_IRQ(void)
 	struct device_node *intc = NULL;
 
 	intc = of_find_compatible_node(NULL, NULL, "snps,arc700-intc");
-	if(!intc)
+	if (!intc)
 		panic("DeviceTree Missing incore intc\n");
 
 	root_domain = irq_domain_add_legacy(intc, NR_IRQS, 0, 0,
diff --git a/arch/arc/kernel/kprobes.c b/arch/arc/kernel/kprobes.c
index 3bfeacb..5a7b80e 100644
--- a/arch/arc/kernel/kprobes.c
+++ b/arch/arc/kernel/kprobes.c
@@ -10,7 +10,6 @@
 #include <linux/kprobes.h>
 #include <linux/slab.h>
 #include <linux/module.h>
-#include <linux/kprobes.h>
 #include <linux/kdebug.h>
 #include <linux/sched.h>
 #include <linux/uaccess.h>
diff --git a/arch/arc/kernel/module.c b/arch/arc/kernel/module.c
index cdd3593..376e046 100644
--- a/arch/arc/kernel/module.c
+++ b/arch/arc/kernel/module.c
@@ -47,7 +47,7 @@ int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
 		}
 	}
 #endif
-    return 0;
+	return 0;
 }
 
 void module_arch_cleanup(struct module *mod)
@@ -141,5 +141,5 @@ int module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs,
 		mod->arch.unw_info = unw;
 	}
 #endif
-    return 0;
+	return 0;
 }
diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c
index 2d95ac0..694bbd4 100644
--- a/arch/arc/kernel/setup.c
+++ b/arch/arc/kernel/setup.c
@@ -14,14 +14,13 @@
 #include <linux/module.h>
 #include <linux/cpu.h>
 #include <linux/of_fdt.h>
+#include <linux/cache.h>
 #include <asm/sections.h>
 #include <asm/arcregs.h>
 #include <asm/tlb.h>
-#include <asm/cache.h>
 #include <asm/setup.h>
 #include <asm/page.h>
 #include <asm/irq.h>
-#include <asm/arcregs.h>
 #include <asm/prom.h>
 #include <asm/unwind.h>
 #include <asm/clk.h>
diff --git a/arch/arc/kernel/time.c b/arch/arc/kernel/time.c
index f13f728..09f4309 100644
--- a/arch/arc/kernel/time.c
+++ b/arch/arc/kernel/time.c
@@ -33,7 +33,6 @@
 #include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
-#include <linux/interrupt.h>
 #include <linux/time.h>
 #include <linux/init.h>
 #include <linux/timex.h>
diff --git a/arch/arc/kernel/traps.c b/arch/arc/kernel/traps.c
index 7496995..1d902f4 100644
--- a/arch/arc/kernel/traps.c
+++ b/arch/arc/kernel/traps.c
@@ -16,11 +16,11 @@
 #include <linux/sched.h>
 #include <linux/kdebug.h>
 #include <linux/uaccess.h>
-#include <asm/ptrace.h>
+#include <linux/ptrace.h>
+#include <linux/kprobes.h>
+#include <linux/kgdb.h>
 #include <asm/setup.h>
-#include <asm/kprobes.h>
 #include <asm/unaligned.h>
-#include <asm/kgdb.h>
 
 void __init trap_init(void)
 {
diff --git a/arch/arc/kernel/troubleshoot.c b/arch/arc/kernel/troubleshoot.c
index 7c10873..dd7c0b7 100644
--- a/arch/arc/kernel/troubleshoot.c
+++ b/arch/arc/kernel/troubleshoot.c
@@ -40,7 +40,11 @@ static noinline void print_reg_file(long *reg_rev, int start_num)
 	if (start_num != 0)
 		n += scnprintf(buf + n, len - n, "\n\n");
 
-	pr_info("%s", buf);
+	/* To continue printing callee regs on same line as scratch regs */
+	if (start_num == 0)
+		pr_info("%s", buf);
+	else
+		pr_cont("%s\n", buf);
 }
 
 static void show_callee_regs(struct callee_regs *cregs)
diff --git a/arch/arc/mm/extable.c b/arch/arc/mm/extable.c
index 014172b..aa652e2 100644
--- a/arch/arc/mm/extable.c
+++ b/arch/arc/mm/extable.c
@@ -27,7 +27,7 @@ int fixup_exception(struct pt_regs *regs)
 
 #ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
 
-long arc_copy_from_user_noinline(void *to, const void __user * from,
+long arc_copy_from_user_noinline(void *to, const void __user *from,
 		unsigned long n)
 {
 	return __arc_copy_from_user(to, from, n);
@@ -48,7 +48,7 @@ unsigned long arc_clear_user_noinline(void __user *to,
 }
 EXPORT_SYMBOL(arc_clear_user_noinline);
 
-long arc_strncpy_from_user_noinline (char *dst, const char __user *src,
+long arc_strncpy_from_user_noinline(char *dst, const char __user *src,
 		long count)
 {
 	return __arc_strncpy_from_user(dst, src, count);
diff --git a/arch/arc/mm/fault.c b/arch/arc/mm/fault.c
index af55aab..689ffd8 100644
--- a/arch/arc/mm/fault.c
+++ b/arch/arc/mm/fault.c
@@ -12,7 +12,6 @@
 #include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/ptrace.h>
-#include <linux/version.h>
 #include <linux/uaccess.h>
 #include <linux/kdebug.h>
 #include <asm/pgalloc.h>
diff --git a/arch/arc/mm/init.c b/arch/arc/mm/init.c
index caf797d..4a17736 100644
--- a/arch/arc/mm/init.c
+++ b/arch/arc/mm/init.c
@@ -10,9 +10,6 @@
 #include <linux/mm.h>
 #include <linux/bootmem.h>
 #include <linux/memblock.h>
-#ifdef CONFIG_BLOCK_DEV_RAM
-#include <linux/blk.h>
-#endif
 #include <linux/swap.h>
 #include <linux/module.h>
 #include <asm/page.h>
@@ -144,37 +141,18 @@ void __init mem_init(void)
 		PAGES_TO_KB(reserved_pages));
 }
 
-static void __init free_init_pages(const char *what, unsigned long begin,
-				   unsigned long end)
-{
-	unsigned long addr;
-
-	pr_info("Freeing %s: %ldk [%lx] to [%lx]\n",
-		what, TO_KB(end - begin), begin, end);
-
-	/* need to check that the page we free is not a partial page */
-	for (addr = begin; addr + PAGE_SIZE <= end; addr += PAGE_SIZE) {
-		ClearPageReserved(virt_to_page(addr));
-		init_page_count(virt_to_page(addr));
-		free_page(addr);
-		totalram_pages++;
-	}
-}
-
 /*
  * free_initmem: Free all the __init memory.
  */
 void __init_refok free_initmem(void)
 {
-	free_init_pages("unused kernel memory",
-			(unsigned long)__init_begin,
-			(unsigned long)__init_end);
+	free_initmem_default(0);
 }
 
 #ifdef CONFIG_BLK_DEV_INITRD
 void __init free_initrd_mem(unsigned long start, unsigned long end)
 {
-	free_init_pages("initrd memory", start, end);
+	free_reserved_area(start, end, 0, "initrd");
 }
 #endif
 
diff --git a/arch/arc/mm/ioremap.c b/arch/arc/mm/ioremap.c
index 3e5c92c..739e65f 100644
--- a/arch/arc/mm/ioremap.c
+++ b/arch/arc/mm/ioremap.c
@@ -12,7 +12,7 @@
 #include <linux/io.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
-#include <asm/cache.h>
+#include <linux/cache.h>
 
 void __iomem *ioremap(unsigned long paddr, unsigned long size)
 {
diff --git a/arch/arc/mm/tlb.c b/arch/arc/mm/tlb.c
index 9b9ce23..8cf5f23 100644
--- a/arch/arc/mm/tlb.c
+++ b/arch/arc/mm/tlb.c
@@ -466,7 +466,7 @@ void __init read_decode_mmu_bcr(void)
 char *arc_mmu_mumbojumbo(int cpu_id, char *buf, int len)
 {
 	int n = 0;
-	struct cpuinfo_arc_mmu *p_mmu = &cpuinfo_arc700[smp_processor_id()].mmu;
+	struct cpuinfo_arc_mmu *p_mmu = &cpuinfo_arc700[cpu_id].mmu;
 
 	n += scnprintf(buf + n, len - n, "ARC700 MMU [v%x]\t: %dk PAGE, ",
 		       p_mmu->ver, TO_KB(p_mmu->pg_sz));
diff --git a/arch/arc/plat-arcfpga/Kconfig b/arch/arc/plat-arcfpga/Kconfig
index b41e786..295cefe 100644
--- a/arch/arc/plat-arcfpga/Kconfig
+++ b/arch/arc/plat-arcfpga/Kconfig
@@ -53,7 +53,7 @@ menuconfig ARC_HAS_BVCI_LAT_UNIT
 	bool "BVCI Bus Latency Unit"
 	depends on ARC_BOARD_ML509 || ARC_BOARD_ANGEL4
 	help
-	  IP to add artifical latency to BVCI Bus Based FPGA builds.
+	  IP to add artificial latency to BVCI Bus Based FPGA builds.
 	  The default latency (even worst case) for FPGA is non-realistic
 	  (~10 SDRAM, ~5 SSRAM).
 
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 13b7394..946b518 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -38,6 +38,7 @@ config ARM
 	select HAVE_HW_BREAKPOINT if (PERF_EVENTS && (CPU_V6 || CPU_V6K || CPU_V7))
 	select HAVE_IDE if PCI || ISA || PCMCIA
 	select HAVE_KERNEL_GZIP
+	select HAVE_KERNEL_LZ4
 	select HAVE_KERNEL_LZMA
 	select HAVE_KERNEL_LZO
 	select HAVE_KERNEL_XZ
@@ -58,6 +59,7 @@ config ARM
 	select CLONE_BACKWARDS
 	select OLD_SIGSUSPEND3
 	select OLD_SIGACTION
+	select HAVE_CONTEXT_TRACKING
 	help
 	  The ARM series is a line of low-power-consumption RISC chip designs
 	  licensed by ARM Ltd and targeted at embedded applications and
@@ -361,37 +363,6 @@ config ARCH_AT91
 	  This enables support for systems based on Atmel
 	  AT91RM9200 and AT91SAM9* processors.
 
-config ARCH_BCM2835
-	bool "Broadcom BCM2835 family"
-	select ARCH_REQUIRE_GPIOLIB
-	select ARM_AMBA
-	select ARM_ERRATA_411920
-	select ARM_TIMER_SP804
-	select CLKDEV_LOOKUP
-	select CLKSRC_OF
-	select COMMON_CLK
-	select CPU_V6
-	select GENERIC_CLOCKEVENTS
-	select MULTI_IRQ_HANDLER
-	select PINCTRL
-	select PINCTRL_BCM2835
-	select SPARSE_IRQ
-	select USE_OF
-	help
-	  This enables support for the Broadcom BCM2835 SoC. This SoC is
-	  use in the Raspberry Pi, and Roku 2 devices.
-
-config ARCH_CNS3XXX
-	bool "Cavium Networks CNS3XXX family"
-	select ARM_GIC
-	select CPU_V6K
-	select GENERIC_CLOCKEVENTS
-	select MIGHT_HAVE_CACHE_L2X0
-	select MIGHT_HAVE_PCI
-	select PCI_DOMAINS if PCI
-	help
-	  Support for Cavium Networks CNS3XXX platform.
-
 config ARCH_CLPS711X
 	bool "Cirrus Logic CLPS711x/EP721x/EP731x-based"
 	select ARCH_REQUIRE_GPIOLIB
@@ -410,25 +381,11 @@ config ARCH_GEMINI
 	bool "Cortina Systems Gemini"
 	select ARCH_REQUIRE_GPIOLIB
 	select ARCH_USES_GETTIMEOFFSET
+	select NEED_MACH_GPIO_H
 	select CPU_FA526
 	help
 	  Support for the Cortina Systems Gemini family SoCs
 
-config ARCH_SIRF
-	bool "CSR SiRF"
-	select ARCH_REQUIRE_GPIOLIB
-	select AUTO_ZRELADDR
-	select COMMON_CLK
-	select GENERIC_CLOCKEVENTS
-	select GENERIC_IRQ_CHIP
-	select MIGHT_HAVE_CACHE_L2X0
-	select NO_IOPORT
-	select PINCTRL
-	select PINCTRL_SIRF
-	select USE_OF
-	help
-	  Support for CSR SiRFprimaII/Marco/Polo platforms
-
 config ARCH_EBSA110
 	bool "EBSA-110"
 	select ARCH_USES_GETTIMEOFFSET
@@ -468,21 +425,6 @@ config ARCH_FOOTBRIDGE
 	  Support for systems based on the DC21285 companion chip
 	  ("FootBridge"), such as the Simtec CATS and the Rebel NetWinder.
 
-config ARCH_MXS
-	bool "Freescale MXS-based"
-	select ARCH_REQUIRE_GPIOLIB
-	select CLKDEV_LOOKUP
-	select CLKSRC_MMIO
-	select COMMON_CLK
-	select GENERIC_CLOCKEVENTS
-	select HAVE_CLK_PREPARE
-	select MULTI_IRQ_HANDLER
-	select PINCTRL
-	select SPARSE_IRQ
-	select USE_OF
-	help
-	  Support for Freescale MXS-based family of processors
-
 config ARCH_NETX
 	bool "Hilscher NetX based"
 	select ARM_VIC
@@ -492,14 +434,6 @@ config ARCH_NETX
 	help
 	  This enables support for systems based on the Hilscher NetX Soc
 
-config ARCH_H720X
-	bool "Hynix HMS720x-based"
-	select ARCH_USES_GETTIMEOFFSET
-	select CPU_ARM720T
-	select ISA_DMA_API
-	help
-	  This enables support for systems based on the Hynix HMS720x
-
 config ARCH_IOP13XX
 	bool "IOP13xx-based"
 	depends on MMU
@@ -661,24 +595,6 @@ config ARCH_LPC32XX
 	help
 	  Support for the NXP LPC32XX family of processors
 
-config ARCH_TEGRA
-	bool "NVIDIA Tegra"
-	select ARCH_HAS_CPUFREQ
-	select ARCH_REQUIRE_GPIOLIB
-	select CLKDEV_LOOKUP
-	select CLKSRC_MMIO
-	select CLKSRC_OF
-	select COMMON_CLK
-	select GENERIC_CLOCKEVENTS
-	select HAVE_CLK
-	select HAVE_SMP
-	select MIGHT_HAVE_CACHE_L2X0
-	select SPARSE_IRQ
-	select USE_OF
-	help
-	  This enables support for NVIDIA Tegra based systems (Tegra APX,
-	  Tegra 6xx and Tegra 2 series).
-
 config ARCH_PXA
 	bool "PXA2xx/PXA3xx-based"
 	depends on MMU
@@ -723,7 +639,7 @@ config ARCH_SHMOBILE
 	select MULTI_IRQ_HANDLER
 	select NEED_MACH_MEMORY_H
 	select NO_IOPORT
-	select PINCTRL
+	select PINCTRL if ARCH_WANT_OPTIONAL_GPIOLIB
 	select PM_GENERIC_DOMAINS if PM
 	select SPARSE_IRQ
 	help
@@ -769,12 +685,15 @@ config ARCH_SA1100
 config ARCH_S3C24XX
 	bool "Samsung S3C24XX SoCs"
 	select ARCH_HAS_CPUFREQ
-	select ARCH_USES_GETTIMEOFFSET
+	select ARCH_REQUIRE_GPIOLIB
 	select CLKDEV_LOOKUP
+	select CLKSRC_MMIO
+	select GENERIC_CLOCKEVENTS
 	select HAVE_CLK
 	select HAVE_S3C2410_I2C if I2C
 	select HAVE_S3C2410_WATCHDOG if WATCHDOG
 	select HAVE_S3C_RTC if RTC_CLASS
+	select MULTI_IRQ_HANDLER
 	select NEED_MACH_GPIO_H
 	select NEED_MACH_IO_H
 	help
@@ -787,10 +706,11 @@ config ARCH_S3C64XX
 	bool "Samsung S3C64XX"
 	select ARCH_HAS_CPUFREQ
 	select ARCH_REQUIRE_GPIOLIB
-	select ARCH_USES_GETTIMEOFFSET
 	select ARM_VIC
 	select CLKDEV_LOOKUP
+	select CLKSRC_MMIO
 	select CPU_V6
+	select GENERIC_CLOCKEVENTS
 	select HAVE_CLK
 	select HAVE_S3C2410_I2C if I2C
 	select HAVE_S3C2410_WATCHDOG if WATCHDOG
@@ -824,9 +744,11 @@ config ARCH_S5P64X0
 
 config ARCH_S5PC100
 	bool "Samsung S5PC100"
-	select ARCH_USES_GETTIMEOFFSET
+	select ARCH_REQUIRE_GPIOLIB
 	select CLKDEV_LOOKUP
+	select CLKSRC_MMIO
 	select CPU_V7
+	select GENERIC_CLOCKEVENTS
 	select HAVE_CLK
 	select HAVE_S3C2410_I2C if I2C
 	select HAVE_S3C2410_WATCHDOG if WATCHDOG
@@ -859,6 +781,7 @@ config ARCH_EXYNOS
 	select ARCH_HAS_HOLES_MEMORYMODEL
 	select ARCH_SPARSEMEM_ENABLE
 	select CLKDEV_LOOKUP
+	select COMMON_CLK
 	select CPU_V7
 	select GENERIC_CLOCKEVENTS
 	select HAVE_CLK
@@ -916,35 +839,6 @@ config ARCH_U8500
 	help
 	  Support for ST-Ericsson's Ux500 architecture
 
-config ARCH_NOMADIK
-	bool "STMicroelectronics Nomadik"
-	select ARCH_REQUIRE_GPIOLIB
-	select ARM_AMBA
-	select ARM_VIC
-	select CLKSRC_NOMADIK_MTU
-	select COMMON_CLK
-	select CPU_ARM926T
-	select GENERIC_CLOCKEVENTS
-	select MIGHT_HAVE_CACHE_L2X0
-	select USE_OF
-	select PINCTRL
-	select PINCTRL_STN8815
-	select SPARSE_IRQ
-	help
-	  Support for the Nomadik platform by ST-Ericsson
-
-config PLAT_SPEAR
-	bool "ST SPEAr"
-	select ARCH_HAS_CPUFREQ
-	select ARCH_REQUIRE_GPIOLIB
-	select ARM_AMBA
-	select CLKDEV_LOOKUP
-	select CLKSRC_MMIO
-	select COMMON_CLK
-	select GENERIC_CLOCKEVENTS
-	select HAVE_CLK
-	help
-	  Support for ST's SPEAr platform (SPEAr3xx, SPEAr6xx and SPEAr13xx).
 
 config ARCH_DAVINCI
 	bool "TI DaVinci"
@@ -1037,6 +931,8 @@ source "arch/arm/mach-at91/Kconfig"
 
 source "arch/arm/mach-bcm/Kconfig"
 
+source "arch/arm/mach-bcm2835/Kconfig"
+
 source "arch/arm/mach-clps711x/Kconfig"
 
 source "arch/arm/mach-cns3xxx/Kconfig"
@@ -1051,8 +947,6 @@ source "arch/arm/mach-footbridge/Kconfig"
 
 source "arch/arm/mach-gemini/Kconfig"
 
-source "arch/arm/mach-h720x/Kconfig"
-
 source "arch/arm/mach-highbank/Kconfig"
 
 source "arch/arm/mach-integrator/Kconfig"
@@ -1104,7 +998,7 @@ source "arch/arm/plat-samsung/Kconfig"
 
 source "arch/arm/mach-socfpga/Kconfig"
 
-source "arch/arm/plat-spear/Kconfig"
+source "arch/arm/mach-spear/Kconfig"
 
 source "arch/arm/mach-s3c24xx/Kconfig"
 
@@ -1173,7 +1067,6 @@ config PLAT_VERSATILE
 config ARM_TIMER_SP804
 	bool
 	select CLKSRC_MMIO
-	select HAVE_SCHED_CLOCK
 
 source arch/arm/mm/Kconfig
 
@@ -1183,9 +1076,9 @@ config ARM_NR_BANKS
 	default 8
 
 config IWMMXT
-	bool "Enable iWMMXt support"
+	bool "Enable iWMMXt support" if !CPU_PJ4
 	depends on CPU_XSCALE || CPU_XSC3 || CPU_MOHAWK || CPU_PJ4
-	default y if PXA27x || PXA3xx || ARCH_MMP
+	default y if PXA27x || PXA3xx || ARCH_MMP || CPU_PJ4
 	help
 	  Enable support for iWMMXt context switching at run time if
 	  running on a CPU that supports it.
@@ -1439,6 +1332,16 @@ config ARM_ERRATA_775420
 	 to deadlock. This workaround puts DSB before executing ISB if
 	 an abort may occur on cache maintenance.
 
+config ARM_ERRATA_798181
+	bool "ARM errata: TLBI/DSB failure on Cortex-A15"
+	depends on CPU_V7 && SMP
+	help
+	  On Cortex-A15 (r0p0..r3p2) the TLBI*IS/DSB operations are not
+	  adequately shooting down all use of the old entries. This
+	  option enables the Linux kernel workaround for this erratum
+	  which sends an IPI to the CPUs that are running the same ASID
+	  as the one being invalidated.
+
 endmenu
 
 source "arch/arm/common/Kconfig"
@@ -1593,6 +1496,7 @@ config HAVE_ARM_ARCH_TIMER
 config HAVE_ARM_TWD
 	bool
 	depends on SMP
+	select CLKSRC_OF if OF
 	help
 	  This options enables support for the ARM timer and watchdog unit
 
@@ -1646,7 +1550,7 @@ config LOCAL_TIMERS
 	bool "Use local timer interrupts"
 	depends on SMP
 	default y
-	select HAVE_ARM_TWD if (!ARCH_MSM_SCORPIONMP && !EXYNOS4_MCT)
+	select HAVE_ARM_TWD if (!ARCH_MSM_SCORPIONMP && !CLKSRC_EXYNOS_MCT)
 	help
 	  Enable support for local timers on SMP platforms, rather then the
 	  legacy IPI broadcast method.  Local timers allows the system
@@ -1660,7 +1564,7 @@ config ARCH_NR_GPIO
 	int
 	default 1024 if ARCH_SHMOBILE || ARCH_TEGRA
 	default 512 if SOC_OMAP5
-	default 355 if ARCH_U8500
+	default 392 if ARCH_U8500
 	default 288 if ARCH_VT8500 || ARCH_SUNXI
 	default 264 if MACH_H4700
 	default 0
@@ -1683,8 +1587,9 @@ config SCHED_HRTICK
 	def_bool HIGH_RES_TIMERS
 
 config THUMB2_KERNEL
-	bool "Compile the kernel in Thumb-2 mode"
+	bool "Compile the kernel in Thumb-2 mode" if !CPU_THUMBONLY
 	depends on CPU_V7 && !CPU_V6 && !CPU_V6K
+	default y if CPU_THUMBONLY
 	select AEABI
 	select ARM_ASM_UNIFIED
 	select ARM_UNWIND
@@ -2153,13 +2058,6 @@ if ARCH_HAS_CPUFREQ
 
 source "drivers/cpufreq/Kconfig"
 
-config CPU_FREQ_IMX
-	tristate "CPUfreq driver for i.MX CPUs"
-	depends on ARCH_MXC && CPU_FREQ
-	select CPU_FREQ_TABLE
-	help
-	  This enables the CPUfreq driver for i.MX CPUs.
-
 config CPU_FREQ_SA1100
 	bool
 
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index 9b31f43..2bf1973 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -89,6 +89,10 @@ choice
 		bool "Kernel low-level debugging on 9263 and 9g45"
 		depends on HAVE_AT91_DBGU1
 
+	config DEBUG_BCM2835
+		bool "Kernel low-level debugging on BCM2835 PL011 UART"
+		depends on ARCH_BCM2835
+
 	config DEBUG_CLPS711X_UART1
 		bool "Kernel low-level debugging messages via UART1"
 		depends on ARCH_CLPS711X
@@ -103,6 +107,13 @@ choice
 		  Say Y here if you want the debug print routines to direct
 		  their output to the second serial port on these devices.
 
+	config DEBUG_CNS3XXX
+		bool "Kernel Kernel low-level debugging on Cavium Networks CNS3xxx"
+		depends on ARCH_CNS3XXX
+		help
+		  Say Y here if you want the debug print routines to direct
+                  their output to the CNS3xxx UART0.
+
 	config DEBUG_DAVINCI_DA8XX_UART1
 		bool "Kernel low-level debugging on DaVinci DA8XX using UART1"
 		depends on ARCH_DAVINCI_DA8XX
@@ -234,11 +245,11 @@ choice
 		  on i.MX53.
 
 	config DEBUG_IMX6Q_UART
-		bool "i.MX6Q Debug UART"
+		bool "i.MX6Q/DL Debug UART"
 		depends on SOC_IMX6Q
 		help
 		  Say Y here if you want kernel low-level debugging support
-		  on i.MX6Q.
+		  on i.MX6Q/DL.
 
 	config DEBUG_MMP_UART2
 		bool "Kernel low-level debugging message via MMP UART2"
@@ -298,6 +309,13 @@ choice
 		  Say Y here if you want kernel low-level debugging support
 		  on MVEBU based platforms.
 
+	config DEBUG_NOMADIK_UART
+		bool "Kernel low-level debugging messages via NOMADIK UART"
+		depends on ARCH_NOMADIK
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on NOMADIK based platforms.
+
 	config DEBUG_OMAP2PLUS_UART
 		bool "Kernel low-level debugging messages via OMAP2PLUS UART"
 		depends on ARCH_OMAP2PLUS
@@ -580,6 +598,8 @@ endchoice
 
 config DEBUG_LL_INCLUDE
 	string
+	default "debug/bcm2835.S" if DEBUG_BCM2835
+	default "debug/cns3xxx.S" if DEBUG_CNS3XXX
 	default "debug/icedcc.S" if DEBUG_ICEDCC
 	default "debug/imx.S" if DEBUG_IMX1_UART || \
 				 DEBUG_IMX25_UART || \
@@ -591,8 +611,11 @@ config DEBUG_LL_INCLUDE
 				 DEBUG_IMX6Q_UART
 	default "debug/highbank.S" if DEBUG_HIGHBANK_UART
 	default "debug/mvebu.S" if DEBUG_MVEBU_UART
+	default "debug/nomadik.S" if DEBUG_NOMADIK_UART
+	default "debug/mxs.S" if DEBUG_IMX23_UART || DEBUG_IMX28_UART
 	default "debug/omap2plus.S" if DEBUG_OMAP2PLUS_UART
 	default "debug/picoxcell.S" if DEBUG_PICOXCELL_UART
+	default "debug/sirf.S" if DEBUG_SIRFPRIMA2_UART1 || DEBUG_SIRFMARCO_UART1
 	default "debug/socfpga.S" if DEBUG_SOCFPGA_UART
 	default "debug/sunxi.S" if DEBUG_SUNXI_UART0 || DEBUG_SUNXI_UART1
 	default "debug/vexpress.S" if DEBUG_VEXPRESS_UART0_DETECT || \
@@ -602,6 +625,17 @@ config DEBUG_LL_INCLUDE
 	default "debug/zynq.S" if DEBUG_ZYNQ_UART0 || DEBUG_ZYNQ_UART1
 	default "mach/debug-macro.S"
 
+config DEBUG_UNCOMPRESS
+	bool
+	default y if ARCH_MULTIPLATFORM && DEBUG_LL && \
+		     !DEBUG_OMAP2PLUS_UART && \
+		     !DEBUG_TEGRA_UART
+
+config UNCOMPRESS_INCLUDE
+	string
+	default "debug/uncompress.h" if ARCH_MULTIPLATFORM
+	default "mach/uncompress.h"
+
 config EARLY_PRINTK
 	bool "Early printk"
 	depends on DEBUG_LL
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index ee4605f..4737408 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -147,7 +147,6 @@ machine-$(CONFIG_ARCH_DOVE)		+= dove
 machine-$(CONFIG_ARCH_EBSA110)		+= ebsa110
 machine-$(CONFIG_ARCH_EP93XX)		+= ep93xx
 machine-$(CONFIG_ARCH_GEMINI)		+= gemini
-machine-$(CONFIG_ARCH_H720X)		+= h720x
 machine-$(CONFIG_ARCH_HIGHBANK)		+= highbank
 machine-$(CONFIG_ARCH_INTEGRATOR)	+= integrator
 machine-$(CONFIG_ARCH_IOP13XX)		+= iop13xx
@@ -191,9 +190,7 @@ machine-$(CONFIG_ARCH_VT8500)		+= vt8500
 machine-$(CONFIG_ARCH_W90X900)		+= w90x900
 machine-$(CONFIG_FOOTBRIDGE)		+= footbridge
 machine-$(CONFIG_ARCH_SOCFPGA)		+= socfpga
-machine-$(CONFIG_ARCH_SPEAR13XX)	+= spear13xx
-machine-$(CONFIG_ARCH_SPEAR3XX)		+= spear3xx
-machine-$(CONFIG_MACH_SPEAR600)		+= spear6xx
+machine-$(CONFIG_PLAT_SPEAR)		+= spear
 machine-$(CONFIG_ARCH_VIRT)		+= virt
 machine-$(CONFIG_ARCH_ZYNQ)		+= zynq
 machine-$(CONFIG_ARCH_SUNXI)		+= sunxi
@@ -207,7 +204,6 @@ plat-$(CONFIG_PLAT_ORION)	+= orion
 plat-$(CONFIG_PLAT_PXA)		+= pxa
 plat-$(CONFIG_PLAT_S3C24XX)	+= samsung
 plat-$(CONFIG_PLAT_S5P)		+= samsung
-plat-$(CONFIG_PLAT_SPEAR)	+= spear
 plat-$(CONFIG_PLAT_VERSATILE)	+= versatile
 
 ifeq ($(CONFIG_ARCH_EBSA110),y)
diff --git a/arch/arm/arm-soc-for-next-contents.txt b/arch/arm/arm-soc-for-next-contents.txt
new file mode 100644
index 0000000..a8864e4
--- /dev/null
+++ b/arch/arm/arm-soc-for-next-contents.txt
@@ -0,0 +1,112 @@
+for-next contents for 3.10: 
+Format is a little different from before in an attempt to make it easier to read:
+
+<next/* branch>
+	<topic branch>
+		<contents>
+		<...>
+	<...>
+
+next/fixes-non-critical
+	ux500/dt-fixes
+		  git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson.git tags/ux500-dt-fixes
+
+next/cleanup
+	samsung/cleanup-s3c
+		  git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git next/cleanup-s3c
+	samsung/cleanup-s5p
+		  git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git next/cleanup-s5p
+	clksrc/cleanup
+		  git://sources.calxeda.com/kernel/linux.git tags/clksrc-cleanup-for-3.10
+	at91/cleanup
+		  git://github.com/at91linux/linux-at91.git tags/at91-soc
+	patch
+		"irqchip: irq-gic: Fix checkpatch errors"
+	gic/cleanup
+		  git://git.kernel.org/pub/scm/linux/kernel/git/cmarinas/linux-aarch64.git gic
+		  + patch "irqchip: vic: add include of linux/irq.h"
+	patch
+		"ARM: irq: Call irqchip_init if no init_irq function is specified"
+	at91/cleanup2
+		  git://github.com/at91linux/linux-at91.git tags/at91-cleanup
+		 (minus the topmost patch "ARM: at91: make ATAGS support conditional on CONFIG_ATAGS")
+
+next/multiplatform
+	nomadik/multiplatform
+		git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-nomadik.git tags/nomadik-multiplatform
+	spear/multiplatform
+		patches <1363106816-9603-1-git-send-email-arnd@arndb.de>
+	cns3xxx/multiplatform
+		patches <1363299271-8283-1-git-send-email-arnd@arndb.de>
+	prima2/multiplatform
+		patches <1363779679-16880-1-git-send-email-arnd@arndb.de>
+	patch
+		"arm: vt8500: Add wm8850 config options to multi_v7_defconfig"
+
+next/dt
+	mvebu/dt
+		git://git.infradead.org/users/jcooper/linux.git tags/mvebu_dt_for_v3.10
+	at91/dt
+		  git://github.com/at91linux/linux-at91.git tags/at91-dt
+	sunxi/dt
+		  git://github.com/mripard/linux.git tags/sunxi-dt-for-3.10
+
+next/soc
+	prima2/soc
+		patches <1363590279-5656-1-git-send-email-Barry.Song@csr.com>
+	ux500/defconfig
+		http://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson.git tags/ux500-defconfig-v3.10
+	ux500/core
+		http://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson.git tags/ux500-core-v3.10
+	renesas/defconfig
+		  git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git tags/renesas-defconfig-for-v3.10
+	renesas/soc
+		  git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git tags/renesas-soc-for-v3.10
+	at91/soc
+		  git://github.com/at91linux/linux-at91.git tags/at91-soc
+	renesas/defconfig2
+		  git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git tags/renesas-defconfig2-for-v3.10
+	patch
+		"ARM: bcm281xx: Add timer driver (DT portion)"
+	lpc32xx/defconfig
+		  git://git.antcom.de/linux-2.6.git lpc32xx/defconfig
+
+next/drivers
+	samsung/timer
+		git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git next/timer-samsung
+		depends on samsung/cleanup-s3c
+	samsung/irq-s3c24xx
+		git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git next/irq-s3c24xx
+	samsung/pinctrl-exynos
+		git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git next/pinctrl-exynos
+	at91/lcdfb
+		git://github.com/at91linux/linux-at91.git tags/at91-driversLCD
+	renesas/intc-external-irq
+		git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git tags/renesas-intc-external-irq-for-v3.10
+		depends on renesas/soc
+	renesas/clocksource
+		git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git tags/renesas-clocksource-for-v3.10
+
+next/soc2
+	renesas/soc2
+		  git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git tags/renesas-soc2-for-v3.10
+		  depends on renesas/soc
+		  depends on renesas/intc-eternal-irq
+	renesas/pinmux2
+		  git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git tags/renesas-pinmux2-for-v3.10
+		  depends on renesas/soc2
+
+next/boards2
+	renesas/boards2
+		  git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git tags/renesas-boards3-for-v3.10
+		  depends on renesas/soc2
+		  depends on renesas/pinmux2
+
+next/renesas-pinctrl
+	renesas/pinctrl
+		  git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git tags/renesas-pinmux-for-v3.10
+
+next/boards
+	renesas/boards
+		git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git tags/renesas-boards-for-v3.10
+		depends on renesas/pinctrl and renesas/soc
diff --git a/arch/arm/boot/compressed/.gitignore b/arch/arm/boot/compressed/.gitignore
index f79a08e..47279aa 100644
--- a/arch/arm/boot/compressed/.gitignore
+++ b/arch/arm/boot/compressed/.gitignore
@@ -6,6 +6,7 @@ piggy.gzip
 piggy.lzo
 piggy.lzma
 piggy.xzkern
+piggy.lz4
 vmlinux
 vmlinux.lds
 
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index afed28e..001a13a 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -24,6 +24,12 @@ endif
 AFLAGS_head.o += -DTEXT_OFFSET=$(TEXT_OFFSET)
 HEAD	= head.o
 OBJS	+= misc.o decompress.o
+ifeq ($(CONFIG_DEBUG_UNCOMPRESS),y)
+OBJS	+= debug.o
+endif
+ifeq ($(CONFIG_KERNEL_LZ4),y)
+CFLAGS_decompress.o := -Os
+endif
 FONTC	= $(srctree)/drivers/video/console/font_acorn_8x8.c
 
 # string library code (-Os is enforced to keep it much smaller)
@@ -88,6 +94,7 @@ suffix_$(CONFIG_KERNEL_GZIP) = gzip
 suffix_$(CONFIG_KERNEL_LZO)  = lzo
 suffix_$(CONFIG_KERNEL_LZMA) = lzma
 suffix_$(CONFIG_KERNEL_XZ)   = xzkern
+suffix_$(CONFIG_KERNEL_LZ4)  = lz4
 
 # Borrowed libfdt files for the ATAG compatibility mode
 
@@ -112,7 +119,7 @@ targets       := vmlinux vmlinux.lds \
 		 font.o font.c head.o misc.o $(OBJS)
 
 # Make sure files are removed during clean
-extra-y       += piggy.gzip piggy.lzo piggy.lzma piggy.xzkern \
+extra-y       += piggy.gzip piggy.lzo piggy.lzma piggy.xzkern piggy.lz4 \
 		 lib1funcs.S ashldi3.S $(libfdt) $(libfdt_hdrs)
 
 ifeq ($(CONFIG_FUNCTION_TRACER),y)
diff --git a/arch/arm/boot/compressed/debug.S b/arch/arm/boot/compressed/debug.S
new file mode 100644
index 0000000..6e8382d
--- /dev/null
+++ b/arch/arm/boot/compressed/debug.S
@@ -0,0 +1,12 @@
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+
+#include CONFIG_DEBUG_LL_INCLUDE
+
+ENTRY(putc)
+	addruart r1, r2, r3
+	waituart r3, r1
+	senduart r0, r1
+	busyuart r3, r1
+	mov	 pc, lr
+ENDPROC(putc)
diff --git a/arch/arm/boot/compressed/decompress.c b/arch/arm/boot/compressed/decompress.c
index 24b0475..bd245d3 100644
--- a/arch/arm/boot/compressed/decompress.c
+++ b/arch/arm/boot/compressed/decompress.c
@@ -51,6 +51,10 @@ extern char * strstr(const char * s1, const char *s2);
 #include "../../../../lib/decompress_unxz.c"
 #endif
 
+#ifdef CONFIG_KERNEL_LZ4
+#include "../../../../lib/decompress_unlz4.c"
+#endif
+
 int do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x))
 {
 	return decompress(input, len, NULL, NULL, output, NULL, error);
diff --git a/arch/arm/boot/compressed/misc.c b/arch/arm/boot/compressed/misc.c
index df89983..31bd43b 100644
--- a/arch/arm/boot/compressed/misc.c
+++ b/arch/arm/boot/compressed/misc.c
@@ -25,13 +25,7 @@ unsigned int __machine_arch_type;
 static void putstr(const char *ptr);
 extern void error(char *x);
 
-#ifdef CONFIG_ARCH_MULTIPLATFORM
-static inline void putc(int c) {}
-static inline void flush(void) {}
-static inline void arch_decomp_setup(void) {}
-#else
-#include <mach/uncompress.h>
-#endif
+#include CONFIG_UNCOMPRESS_INCLUDE
 
 #ifdef CONFIG_DEBUG_ICEDCC
 
diff --git a/arch/arm/boot/compressed/piggy.lz4.S b/arch/arm/boot/compressed/piggy.lz4.S
new file mode 100644
index 0000000..3d9a575
--- /dev/null
+++ b/arch/arm/boot/compressed/piggy.lz4.S
@@ -0,0 +1,6 @@
+	.section .piggydata,#alloc
+	.globl	input_data
+input_data:
+	.incbin	"arch/arm/boot/compressed/piggy.lz4"
+	.globl	input_data_end
+input_data_end:
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 9c62558..35976f0 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -3,6 +3,7 @@ ifeq ($(CONFIG_OF),y)
 # Keep at91 dtb files sorted alphabetically for each SoC
 # rm9200
 dtb-$(CONFIG_ARCH_AT91) += at91rm9200ek.dtb
+dtb-$(CONFIG_ARCH_AT91) += mpa1600.dtb
 # sam9260
 dtb-$(CONFIG_ARCH_AT91) += animeo_ip.dtb
 dtb-$(CONFIG_ARCH_AT91) += aks-cdu.dtb
@@ -31,6 +32,11 @@ dtb-$(CONFIG_ARCH_AT91) += at91sam9g25ek.dtb
 dtb-$(CONFIG_ARCH_AT91) += at91sam9g35ek.dtb
 dtb-$(CONFIG_ARCH_AT91) += at91sam9x25ek.dtb
 dtb-$(CONFIG_ARCH_AT91) += at91sam9x35ek.dtb
+# sama5d3
+dtb-$(CONFIG_ARCH_AT91)	+= sama5d31ek.dtb
+dtb-$(CONFIG_ARCH_AT91)	+= sama5d33ek.dtb
+dtb-$(CONFIG_ARCH_AT91)	+= sama5d34ek.dtb
+dtb-$(CONFIG_ARCH_AT91)	+= sama5d35ek.dtb
 
 dtb-$(CONFIG_ARCH_BCM2835) += bcm2835-rpi-b.dtb
 dtb-$(CONFIG_ARCH_BCM) += bcm11351-brt.dtb
@@ -42,7 +48,10 @@ dtb-$(CONFIG_ARCH_DOVE) += dove-cm-a510.dtb \
 dtb-$(CONFIG_ARCH_EXYNOS) += exynos4210-origen.dtb \
 	exynos4210-smdkv310.dtb \
 	exynos4210-trats.dtb \
+	exynos4412-odroidx.dtb \
 	exynos4412-smdk4412.dtb \
+	exynos4412-origen.dtb \
+	exynos5250-arndale.dtb \
 	exynos5250-smdk5250.dtb \
 	exynos5250-snow.dtb \
 	exynos5440-ssdk5440.dtb
@@ -87,19 +96,25 @@ dtb-$(CONFIG_ARCH_MXC) += \
 	imx25-karo-tx25.dtb \
 	imx25-pdk.dtb \
 	imx27-apf27.dtb \
+	imx27-apf27dev.dtb \
 	imx27-pdk.dtb \
 	imx31-bug.dtb \
 	imx51-apf51.dtb \
+	imx51-apf51dev.dtb \
 	imx51-babbage.dtb \
 	imx53-ard.dtb \
 	imx53-evk.dtb \
 	imx53-mba53.dtb \
 	imx53-qsb.dtb \
 	imx53-smd.dtb \
+	imx6dl-sabreauto.dtb \
+	imx6dl-sabresd.dtb \
+	imx6dl-wandboard.dtb \
 	imx6q-arm2.dtb \
 	imx6q-sabreauto.dtb \
 	imx6q-sabrelite.dtb \
-	imx6q-sabresd.dtb
+	imx6q-sabresd.dtb \
+	imx6q-sbc6x.dtb
 dtb-$(CONFIG_ARCH_MXS) += imx23-evk.dtb \
 	imx23-olinuxino.dtb \
 	imx23-stmp378x_devb.dtb \
@@ -136,7 +151,12 @@ dtb-$(CONFIG_ARCH_U8500) += snowball.dtb \
 	ccu9540.dtb
 dtb-$(CONFIG_ARCH_SHMOBILE) += emev2-kzm9d.dtb \
 	r8a7740-armadillo800eva.dtb \
+	r8a7778-bockw.dtb \
+	r8a7779-marzen-reference.dtb \
+	r8a7790-lager.dtb \
 	sh73a0-kzm9g.dtb \
+	sh73a0-kzm9g-reference.dtb \
+	r8a73a4-ape6evm.dtb \
 	sh7372-mackerel.dtb
 dtb-$(CONFIG_ARCH_SOCFPGA) += socfpga_cyclone5.dtb \
 	socfpga_vt.dtb
diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
index 0957645..91fe4f1 100644
--- a/arch/arm/boot/dts/am33xx.dtsi
+++ b/arch/arm/boot/dts/am33xx.dtsi
@@ -349,7 +349,7 @@
 			rx_descs = <64>;
 			mac_control = <0x20>;
 			slaves = <2>;
-			cpts_active_slave = <0>;
+			active_slave = <0>;
 			cpts_clock_mult = <0x80000000>;
 			cpts_clock_shift = <29>;
 			reg = <0x4a100000 0x800
diff --git a/arch/arm/boot/dts/armada-370-mirabox.dts b/arch/arm/boot/dts/armada-370-mirabox.dts
index dd0c57d..228452c 100644
--- a/arch/arm/boot/dts/armada-370-mirabox.dts
+++ b/arch/arm/boot/dts/armada-370-mirabox.dts
@@ -54,7 +54,7 @@
 		};
 
 		mvsdio@d00d4000 {
-			pinctrl-0 = <&sdio_pins2>;
+			pinctrl-0 = <&sdio_pins3>;
 			pinctrl-names = "default";
 			status = "okay";
 			/*
@@ -70,5 +70,16 @@
 		usb@d0051000 {
 			status = "okay";
 		};
+
+		i2c@d0011000 {
+			status = "okay";
+			clock-frequency = <100000>;
+			pca9505: pca9505@25 {
+				compatible = "nxp,pca9505";
+				gpio-controller;
+				#gpio-cells = <2>;
+				reg = <0x25>;
+			};
+		};
 	};
 };
diff --git a/arch/arm/boot/dts/armada-370.dtsi b/arch/arm/boot/dts/armada-370.dtsi
index 8188d13..a195deb 100644
--- a/arch/arm/boot/dts/armada-370.dtsi
+++ b/arch/arm/boot/dts/armada-370.dtsi
@@ -59,6 +59,12 @@
 					     "mpp50", "mpp51", "mpp52";
 			      marvell,function = "sd0";
 			};
+
+			sdio_pins3: sdio-pins3 {
+			      marvell,pins = "mpp48", "mpp49", "mpp50",
+					     "mpp51", "mpp52", "mpp53";
+			      marvell,function = "sd0";
+			};
 	        };
 
 		gpio0: gpio@d0018100 {
diff --git a/arch/arm/boot/dts/at91rm9200.dtsi b/arch/arm/boot/dts/at91rm9200.dtsi
index b0268a5..5d3ed5a 100644
--- a/arch/arm/boot/dts/at91rm9200.dtsi
+++ b/arch/arm/boot/dts/at91rm9200.dtsi
@@ -29,6 +29,7 @@
 		gpio3 = &pioD;
 		tcb0 = &tcb0;
 		tcb1 = &tcb1;
+		i2c0 = &i2c0;
 		ssc0 = &ssc0;
 		ssc1 = &ssc1;
 		ssc2 = &ssc2;
@@ -91,6 +92,17 @@
 				interrupts = <20 4 0 21 4 0 22 4 0>;
 			};
 
+			i2c0: i2c@fffb8000 {
+				compatible = "atmel,at91rm9200-i2c";
+				reg = <0xfffb8000 0x4000>;
+				interrupts = <12 4 6>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_twi>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				status = "disabled";
+			};
+
 			mmc0: mmc@fffb4000 {
 				compatible = "atmel,hsmci";
 				reg = <0xfffb4000 0x4000>;
@@ -365,6 +377,20 @@
 					};
 				};
 
+				twi {
+					pinctrl_twi: twi-0 {
+						atmel,pins =
+							<0 25 0x1 0x2	/* PA25 periph A with multi drive */
+							 0 26 0x1 0x2>;	/* PA26 periph A with multi drive */
+					};
+
+					pinctrl_twi_gpio: twi_gpio-0 {
+						atmel,pins =
+							<0 25 0x0 0x2	/* PA25 GPIO with multi drive */
+							 0 26 0x0 0x2>;	/* PA26 GPIO with multi drive */
+					};
+				};
+
 				pioA: gpio@fffff400 {
 					compatible = "atmel,at91rm9200-gpio";
 					reg = <0xfffff400 0x200>;
@@ -500,6 +526,8 @@
 		i2c-gpio,sda-open-drain;
 		i2c-gpio,scl-open-drain;
 		i2c-gpio,delay-us = <2>;	/* ~100 kHz */
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_twi_gpio>;
 		#address-cells = <1>;
 		#size-cells = <0>;
 		status = "disabled";
diff --git a/arch/arm/boot/dts/at91sam9263ek.dts b/arch/arm/boot/dts/at91sam9263ek.dts
index 1eb0872..aa0e184 100644
--- a/arch/arm/boot/dts/at91sam9263ek.dts
+++ b/arch/arm/boot/dts/at91sam9263ek.dts
@@ -155,8 +155,6 @@
 
 	gpio_keys {
 		compatible = "gpio-keys";
-		#address-cells = <1>;
-		#size-cells = <0>;
 
 		left_click {
 			label = "left_click";
diff --git a/arch/arm/boot/dts/at91sam9g20ek_common.dtsi b/arch/arm/boot/dts/at91sam9g20ek_common.dtsi
index da15e83..e041b72 100644
--- a/arch/arm/boot/dts/at91sam9g20ek_common.dtsi
+++ b/arch/arm/boot/dts/at91sam9g20ek_common.dtsi
@@ -167,8 +167,6 @@
 
 	gpio_keys {
 		compatible = "gpio-keys";
-		#address-cells = <1>;
-		#size-cells = <0>;
 
 		btn3 {
 			label = "Button 3";
diff --git a/arch/arm/boot/dts/at91sam9m10g45ek.dts b/arch/arm/boot/dts/at91sam9m10g45ek.dts
index 20c3191..c795bfb 100644
--- a/arch/arm/boot/dts/at91sam9m10g45ek.dts
+++ b/arch/arm/boot/dts/at91sam9m10g45ek.dts
@@ -162,8 +162,6 @@
 
 	gpio_keys {
 		compatible = "gpio-keys";
-		#address-cells = <1>;
-		#size-cells = <0>;
 
 		left_click {
 			label = "left_click";
diff --git a/arch/arm/boot/dts/at91sam9n12ek.dts b/arch/arm/boot/dts/at91sam9n12ek.dts
index d400f8d..7117c05 100644
--- a/arch/arm/boot/dts/at91sam9n12ek.dts
+++ b/arch/arm/boot/dts/at91sam9n12ek.dts
@@ -104,8 +104,6 @@
 
 	gpio_keys {
 		compatible = "gpio-keys";
-		#address-cells = <1>;
-		#size-cells = <0>;
 
 		enter {
 			label = "Enter";
diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi
index a98c0d5..3870322 100644
--- a/arch/arm/boot/dts/at91sam9x5.dtsi
+++ b/arch/arm/boot/dts/at91sam9x5.dtsi
@@ -343,6 +343,54 @@
 					};
 				};
 
+				i2c0 {
+					pinctrl_i2c0: i2c0-0 {
+						atmel,pins =
+							<0 30 0x1 0x0	/* PA30 periph A I2C0 data */
+							 0 31 0x1 0x0>;	/* PA31 periph A I2C0 clock */
+					};
+				};
+
+				i2c1 {
+					pinctrl_i2c1: i2c1-0 {
+						atmel,pins =
+							<2 0 0x3 0x0	/* PC0 periph C I2C1 data */
+							 2 1 0x3 0x0>;	/* PC1 periph C I2C1 clock */
+					};
+				};
+
+				i2c2 {
+					pinctrl_i2c2: i2c2-0 {
+						atmel,pins =
+							<1 4 0x2 0x0	/* PB4 periph B I2C2 data */
+							 1 5 0x2 0x0>;	/* PB5 periph B I2C2 clock */
+					};
+				};
+
+				i2c_gpio0 {
+					pinctrl_i2c_gpio0: i2c_gpio0-0 {
+						atmel,pins =
+							<0 30 0x0 0x2	/* PA30 gpio multidrive I2C0 data */
+							 0 31 0x0 0x2>;	/* PA31 gpio multidrive I2C0 clock */
+					};
+				};
+
+				i2c_gpio1 {
+					pinctrl_i2c_gpio1: i2c_gpio1-0 {
+						atmel,pins =
+							<2 0 0x0 0x2	/* PC0 gpio multidrive I2C1 data */
+							 2 1 0x0 0x2>;	/* PC1 gpio multidrive I2C1 clock */
+					};
+				};
+
+				i2c_gpio2 {
+					pinctrl_i2c_gpio2: i2c_gpio2-0 {
+						atmel,pins =
+							<1 4 0x0 0x2	/* PB4 gpio multidrive I2C2 data */
+							 1 5 0x0 0x2>;	/* PB5 gpio multidrive I2C2 clock */
+					};
+				};
+
 				pioA: gpio@fffff400 {
 					compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
 					reg = <0xfffff400 0x200>;
@@ -471,6 +519,8 @@
 				interrupts = <9 4 6>;
 				#address-cells = <1>;
 				#size-cells = <0>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_i2c0>;
 				status = "disabled";
 			};
 
@@ -480,6 +530,8 @@
 				interrupts = <10 4 6>;
 				#address-cells = <1>;
 				#size-cells = <0>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_i2c1>;
 				status = "disabled";
 			};
 
@@ -489,6 +541,8 @@
 				interrupts = <11 4 6>;
 				#address-cells = <1>;
 				#size-cells = <0>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_i2c2>;
 				status = "disabled";
 			};
 
@@ -577,6 +631,8 @@
 		i2c-gpio,delay-us = <2>;	/* ~100 kHz */
 		#address-cells = <1>;
 		#size-cells = <0>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_i2c_gpio0>;
 		status = "disabled";
 	};
 
@@ -590,6 +646,8 @@
 		i2c-gpio,delay-us = <2>;	/* ~100 kHz */
 		#address-cells = <1>;
 		#size-cells = <0>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_i2c_gpio1>;
 		status = "disabled";
 	};
 
@@ -603,6 +661,8 @@
 		i2c-gpio,delay-us = <2>;	/* ~100 kHz */
 		#address-cells = <1>;
 		#size-cells = <0>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_i2c_gpio2>;
 		status = "disabled";
 	};
 };
diff --git a/arch/arm/boot/dts/at91sam9x5cm.dtsi b/arch/arm/boot/dts/at91sam9x5cm.dtsi
index 4027ac7..347a74a 100644
--- a/arch/arm/boot/dts/at91sam9x5cm.dtsi
+++ b/arch/arm/boot/dts/at91sam9x5cm.dtsi
@@ -24,6 +24,16 @@
 	};
 
 	ahb {
+		apb {
+			pinctrl@fffff400 {
+				1wire_cm {
+					pinctrl_1wire_cm: 1wire_cm-0 {
+						atmel,pins = <1 18 0x0 0x2>; /* PB18 multidrive, conflicts with led */
+					};
+				};
+			};
+		};
+
 		nand0: nand@40000000 {
 			nand-bus-width = <8>;
 			nand-ecc-mode = "hw";
@@ -74,4 +84,14 @@
 			gpios = <&pioD 21 0>;
 		};
 	};
+
+	1wire_cm {
+		compatible = "w1-gpio";
+		gpios = <&pioB 18 0>;
+		linux,open-drain;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_1wire_cm>;
+		status = "okay";
+	};
+
 };
diff --git a/arch/arm/boot/dts/at91sam9x5ek.dtsi b/arch/arm/boot/dts/at91sam9x5ek.dtsi
index 8a7cf1d..1128565 100644
--- a/arch/arm/boot/dts/at91sam9x5ek.dtsi
+++ b/arch/arm/boot/dts/at91sam9x5ek.dtsi
@@ -61,14 +61,6 @@
 				status = "okay";
 			};
 
-			i2c1: i2c@f8014000 {
-				status = "okay";
-			};
-
-			i2c2: i2c@f8018000 {
-				status = "okay";
-			};
-
 			pinctrl@fffff400 {
 				mmc0 {
 					pinctrl_board_mmc0: mmc0-board {
diff --git a/arch/arm/boot/dts/atlas6-evb.dts b/arch/arm/boot/dts/atlas6-evb.dts
new file mode 100644
index 0000000..ab042ca
--- /dev/null
+++ b/arch/arm/boot/dts/atlas6-evb.dts
@@ -0,0 +1,78 @@
+/*
+ * DTS file for CSR SiRFatlas6 Evaluation Board
+ *
+ * Copyright (c) 2012 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+/dts-v1/;
+
+/include/ "atlas6.dtsi"
+
+/ {
+	model = "CSR SiRFatlas6 Evaluation Board";
+	compatible = "sirf,atlas6-cb", "sirf,atlas6";
+
+	memory {
+		reg = <0x00000000 0x20000000>;
+	};
+
+	axi {
+		peri-iobg {
+			uart@b0060000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&uart1_pins_a>;
+			};
+			spi@b00d0000 {
+				status = "okay";
+				pinctrl-names = "default";
+				pinctrl-0 = <&spi0_pins_a>;
+				spi@0 {
+					compatible = "spidev";
+					reg = <0>;
+					spi-max-frequency = <1000000>;
+				};
+			};
+			spi@b0170000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&spi1_pins_a>;
+			};
+			i2c0: i2c@b00e0000 {
+				status = "okay";
+				pinctrl-names = "default";
+				pinctrl-0 = <&i2c0_pins_a>;
+				lcd@40 {
+					compatible = "sirf,lcd";
+					reg = <0x40>;
+				};
+			};
+
+		};
+		disp-iobg {
+			lcd@90010000 {
+				status = "okay";
+				pinctrl-names = "default";
+				pinctrl-0 = <&lcd_24pins_a>;
+			};
+		};
+	};
+	display: display@0 {
+	    panels {
+		panel0: panel@0 {
+			panel-name = "Innolux TFT";
+			hactive = <800>;
+			vactive = <480>;
+			left_margin = <20>;
+			right_margin = <234>;
+			upper_margin = <3>;
+			lower_margin = <41>;
+			hsync_len = <3>;
+			vsync_len = <2>;
+			pixclock = <33264000>;
+			sync = <3>;
+			timing = <0x88>;
+			};
+	    };
+	};
+};
diff --git a/arch/arm/boot/dts/atlas6.dtsi b/arch/arm/boot/dts/atlas6.dtsi
new file mode 100644
index 0000000..7d1a279
--- /dev/null
+++ b/arch/arm/boot/dts/atlas6.dtsi
@@ -0,0 +1,668 @@
+/*
+ * DTS file for CSR SiRFatlas6 SoC
+ *
+ * Copyright (c) 2012 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+/include/ "skeleton.dtsi"
+/ {
+	compatible = "sirf,atlas6";
+	#address-cells = <1>;
+	#size-cells = <1>;
+	interrupt-parent = <&intc>;
+
+	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>;
+
+		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>;
+
+			clks: clock-controller@88000000 {
+				compatible = "sirf,atlas6-clkc";
+				reg = <0x88000000 0x1000>;
+				interrupts = <3>;
+				#clock-cells = <1>;
+			};
+
+			reset-controller@88010000 {
+				compatible = "sirf,prima2-rstc";
+				reg = <0x88010000 0x1000>;
+			};
+
+			rsc-controller@88020000 {
+				compatible = "sirf,prima2-rsc";
+				reg = <0x88020000 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>;
+				clocks = <&clks 5>;
+			};
+		};
+
+		disp-iobg {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0x90010000 0x90010000 0x30000>;
+
+			lcd@90010000 {
+				compatible = "sirf,prima2-lcd";
+				reg = <0x90010000 0x20000>;
+				interrupts = <30>;
+				clocks = <&clks 34>;
+				display=<&display>;
+				/* later transfer to pwm */
+				bl-gpio = <&gpio 7 0>;
+				default-panel = <&panel0>;
+			};
+
+			vpp@90020000 {
+				compatible = "sirf,prima2-vpp";
+				reg = <0x90020000 0x10000>;
+				interrupts = <31>;
+				clocks = <&clks 35>;
+			};
+		};
+
+		graphics-iobg {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0x98000000 0x98000000 0x8000000>;
+
+			graphics@98000000 {
+				compatible = "powervr,sgx510";
+				reg = <0x98000000 0x8000000>;
+				interrupts = <6>;
+				clocks = <&clks 32>;
+			};
+		};
+
+		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>;
+				clocks = <&clks 9>;
+			};
+
+			dsp@a9000000 {
+				compatible = "sirf,prima2-dsp";
+				reg = <0xa9000000 0x1000000>;
+				interrupts = <8>;
+				clocks = <&clks 8>;
+			};
+		};
+
+		peri-iobg {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0xb0000000 0xb0000000 0x180000>,
+			       <0x56000000 0x56000000 0x1b00000>;
+
+			timer@b0020000 {
+				compatible = "sirf,prima2-tick";
+				reg = <0xb0020000 0x1000>;
+				interrupts = <0>;
+			};
+
+			nand@b0030000 {
+				compatible = "sirf,prima2-nand";
+				reg = <0xb0030000 0x10000>;
+				interrupts = <41>;
+				clocks = <&clks 26>;
+			};
+
+			audio@b0040000 {
+				compatible = "sirf,prima2-audio";
+				reg = <0xb0040000 0x10000>;
+				interrupts = <35>;
+				clocks = <&clks 27>;
+			};
+
+			uart0: uart@b0050000 {
+				cell-index = <0>;
+				compatible = "sirf,prima2-uart";
+				reg = <0xb0050000 0x1000>;
+				interrupts = <17>;
+				fifosize = <128>;
+				clocks = <&clks 13>;
+			};
+
+			uart1: uart@b0060000 {
+				cell-index = <1>;
+				compatible = "sirf,prima2-uart";
+				reg = <0xb0060000 0x1000>;
+				interrupts = <18>;
+				fifosize = <32>;
+				clocks = <&clks 14>;
+			};
+
+			uart2: uart@b0070000 {
+				cell-index = <2>;
+				compatible = "sirf,prima2-uart";
+				reg = <0xb0070000 0x1000>;
+				interrupts = <19>;
+				fifosize = <128>;
+				clocks = <&clks 15>;
+			};
+
+			usp0: usp@b0080000 {
+				cell-index = <0>;
+				compatible = "sirf,prima2-usp";
+				reg = <0xb0080000 0x10000>;
+				interrupts = <20>;
+				clocks = <&clks 28>;
+			};
+
+			usp1: usp@b0090000 {
+				cell-index = <1>;
+				compatible = "sirf,prima2-usp";
+				reg = <0xb0090000 0x10000>;
+				interrupts = <21>;
+				clocks = <&clks 29>;
+			};
+
+			dmac0: dma-controller@b00b0000 {
+				cell-index = <0>;
+				compatible = "sirf,prima2-dmac";
+				reg = <0xb00b0000 0x10000>;
+				interrupts = <12>;
+				clocks = <&clks 24>;
+			};
+
+			dmac1: dma-controller@b0160000 {
+				cell-index = <1>;
+				compatible = "sirf,prima2-dmac";
+				reg = <0xb0160000 0x10000>;
+				interrupts = <13>;
+				clocks = <&clks 25>;
+			};
+
+			vip@b00C0000 {
+				compatible = "sirf,prima2-vip";
+				reg = <0xb00C0000 0x10000>;
+				clocks = <&clks 31>;
+			};
+
+			spi0: spi@b00d0000 {
+				cell-index = <0>;
+				compatible = "sirf,prima2-spi";
+				reg = <0xb00d0000 0x10000>;
+				interrupts = <15>;
+				sirf,spi-num-chipselects = <1>;
+				cs-gpios = <&gpio 0 0>;
+				sirf,spi-dma-rx-channel = <25>;
+				sirf,spi-dma-tx-channel = <20>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				clocks = <&clks 19>;
+				status = "disabled";
+			};
+
+			spi1: spi@b0170000 {
+				cell-index = <1>;
+				compatible = "sirf,prima2-spi";
+				reg = <0xb0170000 0x10000>;
+				interrupts = <16>;
+				clocks = <&clks 20>;
+				status = "disabled";
+			};
+
+			i2c0: i2c@b00e0000 {
+				cell-index = <0>;
+				compatible = "sirf,prima2-i2c";
+				reg = <0xb00e0000 0x10000>;
+				interrupts = <24>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				clocks = <&clks 17>;
+			};
+
+			i2c1: i2c@b00f0000 {
+				cell-index = <1>;
+				compatible = "sirf,prima2-i2c";
+				reg = <0xb00f0000 0x10000>;
+				interrupts = <25>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				clocks = <&clks 18>;
+			};
+
+			tsc@b0110000 {
+				compatible = "sirf,prima2-tsc";
+				reg = <0xb0110000 0x10000>;
+				interrupts = <33>;
+				clocks = <&clks 16>;
+			};
+
+			gpio: pinctrl@b0120000 {
+				#gpio-cells = <2>;
+				#interrupt-cells = <2>;
+				compatible = "sirf,atlas6-pinctrl";
+				reg = <0xb0120000 0x10000>;
+				interrupts = <43 44 45 46 47>;
+				gpio-controller;
+				interrupt-controller;
+
+				lcd_16pins_a: lcd0@0 {
+					lcd {
+						sirf,pins = "lcd_16bitsgrp";
+						sirf,function = "lcd_16bits";
+					};
+				};
+				lcd_18pins_a: lcd0@1 {
+					lcd {
+						sirf,pins = "lcd_18bitsgrp";
+						sirf,function = "lcd_18bits";
+					};
+				};
+				lcd_24pins_a: lcd0@2 {
+					lcd {
+						sirf,pins = "lcd_24bitsgrp";
+						sirf,function = "lcd_24bits";
+					};
+				};
+				lcdrom_pins_a: lcdrom0@0 {
+					lcd {
+						sirf,pins = "lcdromgrp";
+						sirf,function = "lcdrom";
+					};
+				};
+				uart0_pins_a: uart0@0 {
+					uart {
+						sirf,pins = "uart0grp";
+						sirf,function = "uart0";
+					};
+				};
+				uart1_pins_a: uart1@0 {
+					uart {
+						sirf,pins = "uart1grp";
+						sirf,function = "uart1";
+					};
+				};
+				uart2_pins_a: uart2@0 {
+					uart {
+						sirf,pins = "uart2grp";
+						sirf,function = "uart2";
+					};
+				};
+				uart2_noflow_pins_a: uart2@1 {
+					uart {
+						sirf,pins = "uart2_nostreamctrlgrp";
+						sirf,function = "uart2_nostreamctrl";
+					};
+				};
+				spi0_pins_a: spi0@0 {
+					spi {
+						sirf,pins = "spi0grp";
+						sirf,function = "spi0";
+					};
+				};
+				spi1_pins_a: spi1@0 {
+					spi {
+						sirf,pins = "spi1grp";
+						sirf,function = "spi1";
+					};
+				};
+				i2c0_pins_a: i2c0@0 {
+					i2c {
+						sirf,pins = "i2c0grp";
+						sirf,function = "i2c0";
+					};
+				};
+				i2c1_pins_a: i2c1@0 {
+					i2c {
+						sirf,pins = "i2c1grp";
+						sirf,function = "i2c1";
+					};
+				};
+                                pwm0_pins_a: pwm0@0 {
+                                        pwm {
+                                                sirf,pins = "pwm0grp";
+                                                sirf,function = "pwm0";
+                                        };
+                                };
+                                pwm1_pins_a: pwm1@0 {
+                                        pwm {
+                                                sirf,pins = "pwm1grp";
+                                                sirf,function = "pwm1";
+                                        };
+                                };
+                                pwm2_pins_a: pwm2@0 {
+                                        pwm {
+                                                sirf,pins = "pwm2grp";
+                                                sirf,function = "pwm2";
+                                        };
+                                };
+                                pwm3_pins_a: pwm3@0 {
+                                        pwm {
+                                                sirf,pins = "pwm3grp";
+                                                sirf,function = "pwm3";
+                                        };
+                                };
+				pwm4_pins_a: pwm4@0 {
+                                        pwm {
+                                                sirf,pins = "pwm4grp";
+                                                sirf,function = "pwm4";
+                                        };
+                                };
+                                gps_pins_a: gps@0 {
+                                        gps {
+                                                sirf,pins = "gpsgrp";
+                                                sirf,function = "gps";
+                                        };
+                                };
+                                vip_pins_a: vip@0 {
+                                        vip {
+                                                sirf,pins = "vipgrp";
+                                                sirf,function = "vip";
+                                        };
+                                };
+                                sdmmc0_pins_a: sdmmc0@0 {
+                                        sdmmc0 {
+                                                sirf,pins = "sdmmc0grp";
+                                                sirf,function = "sdmmc0";
+                                        };
+                                };
+                                sdmmc1_pins_a: sdmmc1@0 {
+                                        sdmmc1 {
+                                                sirf,pins = "sdmmc1grp";
+                                                sirf,function = "sdmmc1";
+                                        };
+                                };
+                                sdmmc2_pins_a: sdmmc2@0 {
+                                        sdmmc2 {
+                                                sirf,pins = "sdmmc2grp";
+                                                sirf,function = "sdmmc2";
+                                        };
+                                };
+				sdmmc2_nowp_pins_a: sdmmc2_nowp@0 {
+                                        sdmmc2_nowp {
+                                                sirf,pins = "sdmmc2_nowpgrp";
+                                                sirf,function = "sdmmc2_nowp";
+                                        };
+                                };
+                                sdmmc3_pins_a: sdmmc3@0 {
+                                        sdmmc3 {
+                                                sirf,pins = "sdmmc3grp";
+                                                sirf,function = "sdmmc3";
+                                        };
+                                };
+                                sdmmc5_pins_a: sdmmc5@0 {
+                                        sdmmc5 {
+                                                sirf,pins = "sdmmc5grp";
+                                                sirf,function = "sdmmc5";
+                                        };
+                                };
+                                i2s_pins_a: i2s@0 {
+                                        i2s {
+                                                sirf,pins = "i2sgrp";
+                                                sirf,function = "i2s";
+                                        };
+                                };
+				i2s_no_din_pins_a: i2s_no_din@0 {
+                                        i2s_no_din {
+                                                sirf,pins = "i2s_no_dingrp";
+                                                sirf,function = "i2s_no_din";
+                                        };
+                                };
+				i2s_6chn_pins_a: i2s_6chn@0 {
+                                        i2s_6chn {
+                                                sirf,pins = "i2s_6chngrp";
+                                                sirf,function = "i2s_6chn";
+                                        };
+                                };
+                                ac97_pins_a: ac97@0 {
+                                        ac97 {
+                                                sirf,pins = "ac97grp";
+                                                sirf,function = "ac97";
+                                        };
+                                };
+                                nand_pins_a: nand@0 {
+                                        nand {
+                                                sirf,pins = "nandgrp";
+                                                sirf,function = "nand";
+                                        };
+                                };
+                                usp0_pins_a: usp0@0 {
+                                        usp0 {
+                                                sirf,pins = "usp0grp";
+                                                sirf,function = "usp0";
+                                        };
+                                };
+                                usp1_pins_a: usp1@0 {
+                                        usp1 {
+                                                sirf,pins = "usp1grp";
+                                                sirf,function = "usp1";
+                                        };
+                                };
+                                usb0_upli_drvbus_pins_a: usb0_upli_drvbus@0 {
+                                        usb0_upli_drvbus {
+                                                sirf,pins = "usb0_upli_drvbusgrp";
+                                                sirf,function = "usb0_upli_drvbus";
+                                        };
+                                };
+                                usb1_utmi_drvbus_pins_a: usb1_utmi_drvbus@0 {
+                                        usb1_utmi_drvbus {
+                                                sirf,pins = "usb1_utmi_drvbusgrp";
+                                                sirf,function = "usb1_utmi_drvbus";
+                                        };
+                                };
+                                warm_rst_pins_a: warm_rst@0 {
+                                        warm_rst {
+                                                sirf,pins = "warm_rstgrp";
+                                                sirf,function = "warm_rst";
+                                        };
+                                };
+                                pulse_count_pins_a: pulse_count@0 {
+                                        pulse_count {
+                                                sirf,pins = "pulse_countgrp";
+                                                sirf,function = "pulse_count";
+                                        };
+                                };
+                                cko0_rst_pins_a: cko0_rst@0 {
+                                        cko0_rst {
+                                                sirf,pins = "cko0_rstgrp";
+                                                sirf,function = "cko0_rst";
+                                        };
+                                };
+                                cko1_rst_pins_a: cko1_rst@0 {
+                                        cko1_rst {
+                                                sirf,pins = "cko1_rstgrp";
+                                                sirf,function = "cko1_rst";
+                                        };
+                                };
+			};
+
+			pwm@b0130000 {
+				compatible = "sirf,prima2-pwm";
+				reg = <0xb0130000 0x10000>;
+				clocks = <&clks 21>;
+			};
+
+			efusesys@b0140000 {
+				compatible = "sirf,prima2-efuse";
+				reg = <0xb0140000 0x10000>;
+				clocks = <&clks 22>;
+			};
+
+			pulsec@b0150000 {
+				compatible = "sirf,prima2-pulsec";
+				reg = <0xb0150000 0x10000>;
+				interrupts = <48>;
+				clocks = <&clks 23>;
+			};
+
+			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>;
+					bus-width = <8>;
+					clocks = <&clks 36>;
+				};
+
+				sd1: sdhci@56100000 {
+					cell-index = <1>;
+					compatible = "sirf,prima2-sdhc";
+					reg = <0x56100000 0x100000>;
+					interrupts = <38>;
+					status = "disabled";
+					clocks = <&clks 36>;
+				};
+
+				sd2: sdhci@56200000 {
+					cell-index = <2>;
+					compatible = "sirf,prima2-sdhc";
+					reg = <0x56200000 0x100000>;
+					interrupts = <23>;
+					status = "disabled";
+					clocks = <&clks 37>;
+				};
+
+				sd3: sdhci@56300000 {
+					cell-index = <3>;
+					compatible = "sirf,prima2-sdhc";
+					reg = <0x56300000 0x100000>;
+					interrupts = <23>;
+					status = "disabled";
+					clocks = <&clks 37>;
+				};
+
+				sd5: sdhci@56500000 {
+					cell-index = <5>;
+					compatible = "sirf,prima2-sdhc";
+					reg = <0x56500000 0x100000>;
+					interrupts = <39>;
+					status = "disabled";
+					clocks = <&clks 38>;
+				};
+
+				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", "sirf-prima2-rtciobg-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>;
+				clocks = <&clks 40>;
+			};
+
+			usb1: usb@b00f0000 {
+				compatible = "chipidea,ci13611a-prima2";
+				reg = <0xb8010000 0x10000>;
+				interrupts = <11>;
+				clocks = <&clks 41>;
+			};
+
+			security@b00f0000 {
+				compatible = "sirf,prima2-security";
+				reg = <0xb8030000 0x10000>;
+				interrupts = <42>;
+				clocks = <&clks 7>;
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/bcm11351.dtsi b/arch/arm/boot/dts/bcm11351.dtsi
index ad13588..8f71f40 100644
--- a/arch/arm/boot/dts/bcm11351.dtsi
+++ b/arch/arm/boot/dts/bcm11351.dtsi
@@ -47,4 +47,12 @@
 		    cache-unified;
 		    cache-level = <2>;
 	};
+
+	timer@35006000 {
+		compatible = "bcm,kona-timer";
+		reg = <0x35006000 0x1000>;
+		interrupts = <0x0 7 0x4>;
+		clock-frequency = <32768>;
+	};
+
 };
diff --git a/arch/arm/boot/dts/bcm2835.dtsi b/arch/arm/boot/dts/bcm2835.dtsi
index 7e0481e..f0052dc 100644
--- a/arch/arm/boot/dts/bcm2835.dtsi
+++ b/arch/arm/boot/dts/bcm2835.dtsi
@@ -34,6 +34,11 @@
 			reg = <0x7e100000 0x28>;
 		};
 
+		rng {
+			compatible = "brcm,bcm2835-rng";
+			reg = <0x7e104000 0x10>;
+		};
+
 		uart@20201000 {
 			compatible = "brcm,bcm2835-pl011", "arm,pl011", "arm,primecell";
 			reg = <0x7e201000 0x1000>;
@@ -64,6 +69,16 @@
 			#interrupt-cells = <2>;
 		};
 
+		spi: spi@20204000 {
+			compatible = "brcm,bcm2835-spi";
+			reg = <0x7e204000 0x1000>;
+			interrupts = <2 22>;
+			clocks = <&clk_spi>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
 		i2c0: i2c@20205000 {
 			compatible = "brcm,bcm2835-i2c";
 			reg = <0x7e205000 0x1000>;
@@ -107,5 +122,12 @@
 			#clock-cells = <0>;
 			clock-frequency = <250000000>;
 		};
+
+		clk_spi: spi {
+			compatible = "fixed-clock";
+			reg = <2>;
+			#clock-cells = <0>;
+			clock-frequency = <250000000>;
+		};
 	};
 };
diff --git a/arch/arm/boot/dts/cros5250-common.dtsi b/arch/arm/boot/dts/cros5250-common.dtsi
index 46c0980..8a5b3a6 100644
--- a/arch/arm/boot/dts/cros5250-common.dtsi
+++ b/arch/arm/boot/dts/cros5250-common.dtsi
@@ -19,31 +19,168 @@
 	chosen {
 	};
 
+	pinctrl@11400000 {
+		/*
+		 * Disabled pullups since external part has its own pullups and
+		 * double-pulling gets us out of spec in some cases.
+		 */
+		i2c2_bus: i2c2-bus {
+			samsung,pin-pud = <0>;
+		};
+	};
+
 	i2c@12C60000 {
 		samsung,i2c-sda-delay = <100>;
 		samsung,i2c-max-bus-freq = <378000>;
-		gpios = <&gpb3 0 2 3 0>,
-			<&gpb3 1 2 3 0>;
+
+		max77686@09 {
+			compatible = "maxim,max77686";
+			reg = <0x09>;
+
+			voltage-regulators {
+				ldo1_reg: LDO1 {
+					regulator-name = "P1.0V_LDO_OUT1";
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1000000>;
+					regulator-always-on;
+				};
+
+				ldo2_reg: LDO2 {
+					regulator-name = "P1.8V_LDO_OUT2";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+				};
+
+				ldo3_reg: LDO3 {
+					regulator-name = "P1.8V_LDO_OUT3";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+				};
+
+				ldo7_reg: LDO7 {
+					regulator-name = "P1.1V_LDO_OUT7";
+					regulator-min-microvolt = <1100000>;
+					regulator-max-microvolt = <1100000>;
+					regulator-always-on;
+				};
+
+				ldo8_reg: LDO8 {
+					regulator-name = "P1.0V_LDO_OUT8";
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1000000>;
+					regulator-always-on;
+				};
+
+				ldo10_reg: LDO10 {
+					regulator-name = "P1.8V_LDO_OUT10";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+				};
+
+				ldo12_reg: LDO12 {
+					regulator-name = "P3.0V_LDO_OUT12";
+					regulator-min-microvolt = <3000000>;
+					regulator-max-microvolt = <3000000>;
+					regulator-always-on;
+				};
+
+				ldo14_reg: LDO14 {
+					regulator-name = "P1.8V_LDO_OUT14";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+				};
+
+				ldo15_reg: LDO15 {
+					regulator-name = "P1.0V_LDO_OUT15";
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1000000>;
+					regulator-always-on;
+				};
+
+				ldo16_reg: LDO16 {
+					regulator-name = "P1.8V_LDO_OUT16";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+				};
+
+				buck1_reg: BUCK1 {
+					regulator-name = "vdd_mif";
+					regulator-min-microvolt = <950000>;
+					regulator-max-microvolt = <1300000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				buck2_reg: BUCK2 {
+					regulator-name = "vdd_arm";
+					regulator-min-microvolt = <850000>;
+					regulator-max-microvolt = <1350000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				buck3_reg: BUCK3 {
+					regulator-name = "vdd_int";
+					regulator-min-microvolt = <900000>;
+					regulator-max-microvolt = <1200000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				buck4_reg: BUCK4 {
+					regulator-name = "vdd_g3d";
+					regulator-min-microvolt = <850000>;
+					regulator-max-microvolt = <1300000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				buck5_reg: BUCK5 {
+					regulator-name = "P1.8V_BUCK_OUT5";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				buck6_reg: BUCK6 {
+					regulator-name = "P1.35V_BUCK_OUT6";
+					regulator-min-microvolt = <1350000>;
+					regulator-max-microvolt = <1350000>;
+					regulator-always-on;
+				};
+
+				buck7_reg: BUCK7 {
+					regulator-name = "P2.0V_BUCK_OUT7";
+					regulator-min-microvolt = <2000000>;
+					regulator-max-microvolt = <2000000>;
+					regulator-always-on;
+				};
+
+				buck8_reg: BUCK8 {
+					regulator-name = "P2.85V_BUCK_OUT8";
+					regulator-min-microvolt = <2850000>;
+					regulator-max-microvolt = <2850000>;
+					regulator-always-on;
+				};
+			};
+		};
 	};
 
 	i2c@12C70000 {
 		samsung,i2c-sda-delay = <100>;
 		samsung,i2c-max-bus-freq = <378000>;
-		gpios = <&gpb3 2 2 3 0>,
-			<&gpb3 3 2 3 0>;
 	};
 
 	i2c@12C80000 {
 		samsung,i2c-sda-delay = <100>;
 		samsung,i2c-max-bus-freq = <66000>;
 
-		/*
-		 * Disabled pullups since external part has its own pullups and
-		 * double-pulling gets us out of spec in some cases.
-		 */
-		gpios = <&gpa0 6 3 0 0>,
-			<&gpa0 7 3 0 0>;
-
 		hdmiddc@50 {
 			compatible = "samsung,exynos5-hdmiddc";
 			reg = <0x50>;
@@ -53,8 +190,6 @@
 	i2c@12C90000 {
 		samsung,i2c-sda-delay = <100>;
 		samsung,i2c-max-bus-freq = <66000>;
-		gpios = <&gpa1 2 3 3 0>,
-			<&gpa1 3 3 3 0>;
 	};
 
 	i2c@12CA0000 {
@@ -64,8 +199,6 @@
 	i2c@12CB0000 {
 		samsung,i2c-sda-delay = <100>;
 		samsung,i2c-max-bus-freq = <66000>;
-		gpios = <&gpa2 2 3 3 0>,
-			<&gpa2 3 3 3 0>;
 	};
 
 	i2c@12CC0000 {
@@ -75,8 +208,6 @@
 	i2c@12CD0000 {
 		samsung,i2c-sda-delay = <100>;
 		samsung,i2c-max-bus-freq = <66000>;
-		gpios = <&gpb2 2 3 3 0>,
-			<&gpb2 3 3 3 0>;
 	};
 
 	i2c@12CE0000 {
@@ -98,15 +229,12 @@
 		samsung,dw-mshc-ciu-div = <3>;
 		samsung,dw-mshc-sdr-timing = <2 3>;
 		samsung,dw-mshc-ddr-timing = <1 2>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_cd &sd0_bus4 &sd0_bus8>;
 
 		slot@0 {
 			reg = <0>;
 			bus-width = <8>;
-			gpios = <&gpc0 0 2 0 3>, <&gpc0 1 2 0 3>,
-				<&gpc1 0 2 3 3>, <&gpc1 1 2 3 3>,
-				<&gpc1 2 2 3 3>, <&gpc1 3 2 3 3>,
-				<&gpc0 3 2 3 3>, <&gpc0 4 2 3 3>,
-				<&gpc0 5 2 3 3>, <&gpc0 6 2 3 3>;
 		};
 	};
 
@@ -122,15 +250,13 @@
 		samsung,dw-mshc-ciu-div = <3>;
 		samsung,dw-mshc-sdr-timing = <2 3>;
 		samsung,dw-mshc-ddr-timing = <1 2>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_cd &sd2_bus4>;
 
 		slot@0 {
 			reg = <0>;
 			bus-width = <4>;
-			samsung,cd-pinmux-gpio = <&gpc3 2 2 3 3>;
-			wp-gpios = <&gpc2 1 0 0 3>;
-			gpios = <&gpc3 0 2 0 3>, <&gpc3 1 2 0 3>,
-				<&gpc3 3 2 3 3>, <&gpc3 4 2 3 3>,
-				<&gpc3 5 2 3 3>, <&gpc3 6 2 3 3>;
+			wp-gpios = <&gpc2 1 0>;
 		};
 	};
 
@@ -143,11 +269,11 @@
 		samsung,dw-mshc-ciu-div = <3>;
 		samsung,dw-mshc-sdr-timing = <2 3>;
 		samsung,dw-mshc-ddr-timing = <1 2>;
+		/* See board-specific dts files for pin setup */
 
 		slot@0 {
 			reg = <0>;
 			bus-width = <4>;
-			/* See board-specific dts files for GPIOs */
 		};
 	};
 
@@ -156,9 +282,6 @@
 	};
 
 	spi_1: spi@12d30000 {
-		gpios = <&gpa2 4 2 3 0>,
-			<&gpa2 6 2 3 0>,
-			<&gpa2 7 2 3 0>;
 		samsung,spi-src-clk = <0>;
 		num-cs = <1>;
 	};
@@ -168,7 +291,7 @@
 	};
 
 	hdmi {
-		hpd-gpio = <&gpx3 7 0xf 1 3>;
+		hpd-gpio = <&gpx3 7 0>;
 	};
 
 	gpio-keys {
@@ -176,7 +299,7 @@
 
 		power {
 			label = "Power";
-			gpios = <&gpx1 3 0 0x10000 0>;
+			gpios = <&gpx1 3 1>;
 			linux,code = <116>; /* KEY_POWER */
 			gpio-key,wakeup;
 		};
diff --git a/arch/arm/boot/dts/dbx5x0.dtsi b/arch/arm/boot/dts/dbx5x0.dtsi
index 9de9309..b6bc4ff 100644
--- a/arch/arm/boot/dts/dbx5x0.dtsi
+++ b/arch/arm/boot/dts/dbx5x0.dtsi
@@ -191,8 +191,8 @@
 
 		prcmu: prcmu@80157000 {
 			compatible = "stericsson,db8500-prcmu";
-			reg = <0x80157000 0x1000>;
-			reg-names = "prcmu";
+			reg = <0x80157000 0x2000>, <0x801b0000 0x8000>, <0x801b8000 0x1000>;
+			reg-names = "prcmu", "prcmu-tcpm", "prcmu-tcdm";
 			interrupts = <0 47 0x4>;
 			#address-cells = <1>;
 			#size-cells = <1>;
@@ -674,10 +674,13 @@
 			compatible = "regulator-gpio";
 
 			regulator-min-microvolt = <1800000>;
-			regulator-max-microvolt = <2600000>;
+			regulator-max-microvolt = <2900000>;
 			regulator-name = "mmci-reg";
 			regulator-type = "voltage";
 
+			startup-delay-us = <100>;
+			enable-active-high;
+
 			states = <1800000 0x1
 				  2900000 0x0>;
 
diff --git a/arch/arm/boot/dts/dove.dtsi b/arch/arm/boot/dts/dove.dtsi
index f7509ca..6cab468 100644
--- a/arch/arm/boot/dts/dove.dtsi
+++ b/arch/arm/boot/dts/dove.dtsi
@@ -50,6 +50,11 @@
 			#clock-cells = <1>;
 		};
 
+		thermal: thermal@d001c {
+			compatible = "marvell,dove-thermal";
+			reg = <0xd001c 0x0c>, <0xd005c 0x08>;
+		};
+
 		uart0: serial@12000 {
 			compatible = "ns16550a";
 			reg = <0x12000 0x100>;
diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi
index 1a62bcf..800ff11 100644
--- a/arch/arm/boot/dts/exynos4.dtsi
+++ b/arch/arm/boot/dts/exynos4.dtsi
@@ -82,10 +82,17 @@
 		reg = <0x10440000 0x1000>;
 	};
 
+	sys_reg: sysreg {
+		compatible = "samsung,exynos4-sysreg", "syscon";
+		reg = <0x10010000 0x400>;
+	};
+
 	watchdog@10060000 {
 		compatible = "samsung,s3c2410-wdt";
 		reg = <0x10060000 0x100>;
 		interrupts = <0 43 0>;
+		clocks = <&clock 345>;
+		clock-names = "watchdog";
 		status = "disabled";
 	};
 
@@ -93,6 +100,8 @@
 		compatible = "samsung,s3c6410-rtc";
 		reg = <0x10070000 0x100>;
 		interrupts = <0 44 0>, <0 45 0>;
+		clocks = <&clock 346>;
+		clock-names = "rtc";
 		status = "disabled";
 	};
 
@@ -100,6 +109,8 @@
 		compatible = "samsung,s5pv210-keypad";
 		reg = <0x100A0000 0x100>;
 		interrupts = <0 109 0>;
+		clocks = <&clock 347>;
+		clock-names = "keypad";
 		status = "disabled";
 	};
 
@@ -107,6 +118,8 @@
 		compatible = "samsung,exynos4210-sdhci";
 		reg = <0x12510000 0x100>;
 		interrupts = <0 73 0>;
+		clocks = <&clock 297>, <&clock 145>;
+		clock-names = "hsmmc", "mmc_busclk.2";
 		status = "disabled";
 	};
 
@@ -114,6 +127,8 @@
 		compatible = "samsung,exynos4210-sdhci";
 		reg = <0x12520000 0x100>;
 		interrupts = <0 74 0>;
+		clocks = <&clock 298>, <&clock 146>;
+		clock-names = "hsmmc", "mmc_busclk.2";
 		status = "disabled";
 	};
 
@@ -121,6 +136,8 @@
 		compatible = "samsung,exynos4210-sdhci";
 		reg = <0x12530000 0x100>;
 		interrupts = <0 75 0>;
+		clocks = <&clock 299>, <&clock 147>;
+		clock-names = "hsmmc", "mmc_busclk.2";
 		status = "disabled";
 	};
 
@@ -128,6 +145,16 @@
 		compatible = "samsung,exynos4210-sdhci";
 		reg = <0x12540000 0x100>;
 		interrupts = <0 76 0>;
+		clocks = <&clock 300>, <&clock 148>;
+		clock-names = "hsmmc", "mmc_busclk.2";
+		status = "disabled";
+	};
+
+	mfc: codec@13400000 {
+		compatible = "samsung,mfc-v5";
+		reg = <0x13400000 0x10000>;
+		interrupts = <0 94 0>;
+		samsung,power-domain = <&pd_mfc>;
 		status = "disabled";
 	};
 
@@ -135,6 +162,8 @@
 		compatible = "samsung,exynos4210-uart";
 		reg = <0x13800000 0x100>;
 		interrupts = <0 52 0>;
+		clocks = <&clock 312>, <&clock 151>;
+		clock-names = "uart", "clk_uart_baud0";
 		status = "disabled";
 	};
 
@@ -142,6 +171,8 @@
 		compatible = "samsung,exynos4210-uart";
 		reg = <0x13810000 0x100>;
 		interrupts = <0 53 0>;
+		clocks = <&clock 313>, <&clock 152>;
+		clock-names = "uart", "clk_uart_baud0";
 		status = "disabled";
 	};
 
@@ -149,6 +180,8 @@
 		compatible = "samsung,exynos4210-uart";
 		reg = <0x13820000 0x100>;
 		interrupts = <0 54 0>;
+		clocks = <&clock 314>, <&clock 153>;
+		clock-names = "uart", "clk_uart_baud0";
 		status = "disabled";
 	};
 
@@ -156,6 +189,8 @@
 		compatible = "samsung,exynos4210-uart";
 		reg = <0x13830000 0x100>;
 		interrupts = <0 55 0>;
+		clocks = <&clock 315>, <&clock 154>;
+		clock-names = "uart", "clk_uart_baud0";
 		status = "disabled";
 	};
 
@@ -165,6 +200,10 @@
 		compatible = "samsung,s3c2440-i2c";
 		reg = <0x13860000 0x100>;
 		interrupts = <0 58 0>;
+		clocks = <&clock 317>;
+		clock-names = "i2c";
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c0_bus>;
 		status = "disabled";
 	};
 
@@ -174,6 +213,10 @@
 		compatible = "samsung,s3c2440-i2c";
 		reg = <0x13870000 0x100>;
 		interrupts = <0 59 0>;
+		clocks = <&clock 318>;
+		clock-names = "i2c";
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c1_bus>;
 		status = "disabled";
 	};
 
@@ -183,6 +226,8 @@
 		compatible = "samsung,s3c2440-i2c";
 		reg = <0x13880000 0x100>;
 		interrupts = <0 60 0>;
+		clocks = <&clock 319>;
+		clock-names = "i2c";
 		status = "disabled";
 	};
 
@@ -192,6 +237,8 @@
 		compatible = "samsung,s3c2440-i2c";
 		reg = <0x13890000 0x100>;
 		interrupts = <0 61 0>;
+		clocks = <&clock 320>;
+		clock-names = "i2c";
 		status = "disabled";
 	};
 
@@ -201,6 +248,8 @@
 		compatible = "samsung,s3c2440-i2c";
 		reg = <0x138A0000 0x100>;
 		interrupts = <0 62 0>;
+		clocks = <&clock 321>;
+		clock-names = "i2c";
 		status = "disabled";
 	};
 
@@ -210,6 +259,8 @@
 		compatible = "samsung,s3c2440-i2c";
 		reg = <0x138B0000 0x100>;
 		interrupts = <0 63 0>;
+		clocks = <&clock 322>;
+		clock-names = "i2c";
 		status = "disabled";
 	};
 
@@ -219,6 +270,8 @@
 		compatible = "samsung,s3c2440-i2c";
 		reg = <0x138C0000 0x100>;
 		interrupts = <0 64 0>;
+		clocks = <&clock 323>;
+		clock-names = "i2c";
 		status = "disabled";
 	};
 
@@ -228,6 +281,8 @@
 		compatible = "samsung,s3c2440-i2c";
 		reg = <0x138D0000 0x100>;
 		interrupts = <0 65 0>;
+		clocks = <&clock 324>;
+		clock-names = "i2c";
 		status = "disabled";
 	};
 
@@ -239,6 +294,10 @@
 		rx-dma-channel = <&pdma0 6>; /* preliminary */
 		#address-cells = <1>;
 		#size-cells = <0>;
+		clocks = <&clock 327>, <&clock 159>;
+		clock-names = "spi", "spi_busclk0";
+		pinctrl-names = "default";
+		pinctrl-0 = <&spi0_bus>;
 		status = "disabled";
 	};
 
@@ -250,6 +309,10 @@
 		rx-dma-channel = <&pdma1 6>; /* preliminary */
 		#address-cells = <1>;
 		#size-cells = <0>;
+		clocks = <&clock 328>, <&clock 160>;
+		clock-names = "spi", "spi_busclk0";
+		pinctrl-names = "default";
+		pinctrl-0 = <&spi1_bus>;
 		status = "disabled";
 	};
 
@@ -261,6 +324,10 @@
 		rx-dma-channel = <&pdma0 8>; /* preliminary */
 		#address-cells = <1>;
 		#size-cells = <0>;
+		clocks = <&clock 329>, <&clock 161>;
+		clock-names = "spi", "spi_busclk0";
+		pinctrl-names = "default";
+		pinctrl-0 = <&spi2_bus>;
 		status = "disabled";
 	};
 
@@ -275,6 +342,8 @@
 			compatible = "arm,pl330", "arm,primecell";
 			reg = <0x12680000 0x1000>;
 			interrupts = <0 35 0>;
+			clocks = <&clock 292>;
+			clock-names = "apb_pclk";
 			#dma-cells = <1>;
 			#dma-channels = <8>;
 			#dma-requests = <32>;
@@ -284,6 +353,8 @@
 			compatible = "arm,pl330", "arm,primecell";
 			reg = <0x12690000 0x1000>;
 			interrupts = <0 36 0>;
+			clocks = <&clock 293>;
+			clock-names = "apb_pclk";
 			#dma-cells = <1>;
 			#dma-channels = <8>;
 			#dma-requests = <32>;
@@ -293,6 +364,8 @@
 			compatible = "arm,pl330", "arm,primecell";
 			reg = <0x12850000 0x1000>;
 			interrupts = <0 34 0>;
+			clocks = <&clock 279>;
+			clock-names = "apb_pclk";
 			#dma-cells = <1>;
 			#dma-channels = <8>;
 			#dma-requests = <1>;
diff --git a/arch/arm/boot/dts/exynos4210-origen.dts b/arch/arm/boot/dts/exynos4210-origen.dts
index f271001..524b908 100644
--- a/arch/arm/boot/dts/exynos4210-origen.dts
+++ b/arch/arm/boot/dts/exynos4210-origen.dts
@@ -57,6 +57,16 @@
 		status = "okay";
 	};
 
+	g2d@12800000 {
+		status = "okay";
+	};
+
+	codec@13400000 {
+		samsung,mfc-r = <0x43000000 0x800000>;
+		samsung,mfc-l = <0x51000000 0x800000>;
+		status = "okay";
+	};
+
 	serial@13800000 {
 		status = "okay";
 	};
@@ -121,4 +131,16 @@
 			linux,default-trigger = "heartbeat";
 		};
 	};
+
+	fixed-rate-clocks {
+		xxti {
+			compatible = "samsung,clock-xxti";
+			clock-frequency = <0>;
+		};
+
+		xusbxti {
+			compatible = "samsung,clock-xusbxti";
+			clock-frequency = <24000000>;
+		};
+	};
 };
diff --git a/arch/arm/boot/dts/exynos4210-smdkv310.dts b/arch/arm/boot/dts/exynos4210-smdkv310.dts
index f634907..91332b7 100644
--- a/arch/arm/boot/dts/exynos4210-smdkv310.dts
+++ b/arch/arm/boot/dts/exynos4210-smdkv310.dts
@@ -30,16 +30,19 @@
 	};
 
 	sdhci@12530000 {
-		samsung,sdhci-bus-width = <4>;
-		linux,mmc_cap_4_bit_data;
-		samsung,sdhci-cd-internal;
-		gpio-cd = <&gpk2 2 2 3 3>;
-		gpios = <&gpk2 0 2 0 3>,
-			<&gpk2 1 2 0 3>,
-			<&gpk2 3 2 3 3>,
-			<&gpk2 4 2 3 3>,
-			<&gpk2 5 2 3 3>,
-			<&gpk2 6 2 3 3>;
+		bus-width = <4>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_cd &sd2_bus4>;
+		status = "okay";
+	};
+
+	g2d@12800000 {
+		status = "okay";
+	};
+
+	codec@13400000 {
+		samsung,mfc-r = <0x43000000 0x800000>;
+		samsung,mfc-l = <0x51000000 0x800000>;
 		status = "okay";
 	};
 
@@ -59,25 +62,32 @@
 		status = "okay";
 	};
 
+	pinctrl@11000000 {
+		keypad_rows: keypad-rows {
+			samsung,pins = "gpx2-0", "gpx2-1";
+			samsung,pin-function = <3>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <0>;
+		};
+
+		keypad_cols: keypad-cols {
+			samsung,pins = "gpx1-0", "gpx1-1", "gpx1-2", "gpx1-3",
+				       "gpx1-4", "gpx1-5", "gpx1-6", "gpx1-7";
+			samsung,pin-function = <3>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+	};
+
 	keypad@100A0000 {
 		samsung,keypad-num-rows = <2>;
 		samsung,keypad-num-columns = <8>;
 		linux,keypad-no-autorepeat;
 		linux,keypad-wakeup;
+		pinctrl-names = "default";
+		pinctrl-0 = <&keypad_rows &keypad_cols>;
 		status = "okay";
 
-		row-gpios = <&gpx2 0 3 3 0>,
-			    <&gpx2 1 3 3 0>;
-
-		col-gpios = <&gpx1 0 3 0 0>,
-			    <&gpx1 1 3 0 0>,
-			    <&gpx1 2 3 0 0>,
-			    <&gpx1 3 3 0 0>,
-			    <&gpx1 4 3 0 0>,
-			    <&gpx1 5 3 0 0>,
-			    <&gpx1 6 3 0 0>,
-			    <&gpx1 7 3 0 0>;
-
 		key_1 {
 			keypad,row = <0>;
 			keypad,column = <3>;
@@ -143,9 +153,7 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 		samsung,i2c-sda-delay = <100>;
-		samsung,i2c-max-bus-freq = <20000>;
-		gpios = <&gpd1 0 2 3 0>,
-			<&gpd1 1 2 3 0>;
+		samsung,i2c-max-bus-freq = <100000>;
 		status = "okay";
 
 		eeprom@50 {
@@ -160,9 +168,6 @@
 	};
 
 	spi_2: spi@13940000 {
-		gpios = <&gpc1 1 5 3 0>,
-			<&gpc1 3 5 3 0>,
-			<&gpc1 4 5 3 0>;
 		status = "okay";
 
 		w25x80@0 {
@@ -173,7 +178,7 @@
 			spi-max-frequency = <1000000>;
 
 			controller-data {
-				cs-gpio = <&gpc1 2 1 0 3>;
+				cs-gpio = <&gpc1 2 0>;
 				samsung,spi-feedback-delay = <0>;
 			};
 
@@ -189,4 +194,16 @@
 			};
 		};
 	};
+
+	fixed-rate-clocks {
+		xxti {
+			compatible = "samsung,clock-xxti";
+			clock-frequency = <12000000>;
+		};
+
+		xusbxti {
+			compatible = "samsung,clock-xusbxti";
+			clock-frequency = <24000000>;
+		};
+	};
 };
diff --git a/arch/arm/boot/dts/exynos4210-trats.dts b/arch/arm/boot/dts/exynos4210-trats.dts
index c346b64..9a14484 100644
--- a/arch/arm/boot/dts/exynos4210-trats.dts
+++ b/arch/arm/boot/dts/exynos4210-trats.dts
@@ -289,4 +289,16 @@
 			};
 		};
 	};
+
+	fixed-rate-clocks {
+		xxti {
+			compatible = "samsung,clock-xxti";
+			clock-frequency = <0>;
+		};
+
+		xusbxti {
+			compatible = "samsung,clock-xusbxti";
+			clock-frequency = <24000000>;
+		};
+	};
 };
diff --git a/arch/arm/boot/dts/exynos4210.dtsi b/arch/arm/boot/dts/exynos4210.dtsi
index 2feffc7..66e6b03 100644
--- a/arch/arm/boot/dts/exynos4210.dtsi
+++ b/arch/arm/boot/dts/exynos4210.dtsi
@@ -47,6 +47,42 @@
 			     <0 12 0>, <0 13 0>, <0 14 0>, <0 15 0>;
 	};
 
+	mct@10050000 {
+		compatible = "samsung,exynos4210-mct";
+		reg = <0x10050000 0x800>;
+		interrupt-controller;
+		#interrups-cells = <2>;
+		interrupt-parent = <&mct_map>;
+		interrupts = <0 0>, <1 0>, <2 0>, <3 0>,
+			     <4 0>, <5 0>;
+		clocks = <&clock 3>, <&clock 344>;
+		clock-names = "fin_pll", "mct";
+
+		mct_map: mct-map {
+			#interrupt-cells = <2>;
+			#address-cells = <0>;
+			#size-cells = <0>;
+			interrupt-map = <0x0 0 &gic 0 57 0>,
+					<0x1 0 &gic 0 69 0>,
+					<0x2 0 &combiner 12 6>,
+					<0x3 0 &combiner 12 7>,
+					<0x4 0 &gic 0 42 0>,
+					<0x5 0 &gic 0 48 0>;
+		};
+	};
+
+	clock: clock-controller@0x10030000 {
+		compatible = "samsung,exynos4210-clock";
+		reg = <0x10030000 0x20000>;
+		#clock-cells = <1>;
+	};
+
+	pmu {
+		compatible = "arm,cortex-a9-pmu";
+		interrupt-parent = <&combiner>;
+		interrupts = <2 2>, <3 2>;
+	};
+
 	pinctrl_0: pinctrl@11400000 {
 		compatible = "samsung,exynos4210-pinctrl";
 		reg = <0x11400000 0x1000>;
@@ -76,4 +112,11 @@
 		reg = <0x100C0000 0x100>;
 		interrupts = <2 4>;
 	};
+
+	g2d@12800000 {
+		compatible = "samsung,s5pv210-g2d";
+		reg = <0x12800000 0x1000>;
+		interrupts = <0 89 0>;
+		status = "disabled";
+	};
 };
diff --git a/arch/arm/boot/dts/exynos4212.dtsi b/arch/arm/boot/dts/exynos4212.dtsi
index c6ae200..36d4299 100644
--- a/arch/arm/boot/dts/exynos4212.dtsi
+++ b/arch/arm/boot/dts/exynos4212.dtsi
@@ -25,4 +25,26 @@
 	gic:interrupt-controller@10490000 {
 		cpu-offset = <0x8000>;
 	};
+
+	mct@10050000 {
+		compatible = "samsung,exynos4412-mct";
+		reg = <0x10050000 0x800>;
+		interrupt-controller;
+		#interrups-cells = <2>;
+		interrupt-parent = <&mct_map>;
+		interrupts = <0 0>, <1 0>, <2 0>, <3 0>,
+			     <4 0>, <5 0>;
+
+		mct_map: mct-map {
+			#interrupt-cells = <2>;
+			#address-cells = <0>;
+			#size-cells = <0>;
+			interrupt-map = <0x0 0 &gic 0 57 0>,
+					<0x1 0 &combiner 12 5>,
+					<0x2 0 &combiner 12 6>,
+					<0x3 0 &combiner 12 7>,
+					<0x4 0 &gic 1 12 0>,
+					<0x5 0 &gic 1 12 0>;
+		};
+	};
 };
diff --git a/arch/arm/boot/dts/exynos4412-odroidx.dts b/arch/arm/boot/dts/exynos4412-odroidx.dts
new file mode 100644
index 0000000..15dc0a3
--- /dev/null
+++ b/arch/arm/boot/dts/exynos4412-odroidx.dts
@@ -0,0 +1,109 @@
+/*
+ * Hardkernel's Exynos4412 based ODROID-X board device tree source
+ *
+ * Copyright (c) 2012 Dongjin Kim <tobetter@gmail.com>
+ *
+ * Device tree source file for Hardkernel's ODROID-X board which is based on
+ * Samsung's Exynos4412 SoC.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/dts-v1/;
+/include/ "exynos4412.dtsi"
+
+/ {
+	model = "Hardkernel ODROID-X board based on Exynos4412";
+	compatible = "hardkernel,odroid-x", "samsung,exynos4412";
+
+	memory {
+		reg = <0x40000000 0x40000000>;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		led1 {
+			label = "led1:heart";
+			gpios = <&gpc1 0 1>;
+			default-state = "on";
+			linux,default-trigger = "heartbeat";
+		};
+		led2 {
+			label = "led2:mmc0";
+			gpios = <&gpc1 2 1>;
+			default-state = "on";
+			linux,default-trigger = "mmc0";
+		};
+	};
+
+	mshc@12550000 {
+		pinctrl-0 = <&sd4_clk &sd4_cmd &sd4_bus4 &sd4_bus8>;
+		pinctrl-names = "default";
+		status = "okay";
+
+		num-slots = <1>;
+		supports-highspeed;
+		broken-cd;
+		fifo-depth = <0x80>;
+		card-detect-delay = <200>;
+		samsung,dw-mshc-ciu-div = <3>;
+		samsung,dw-mshc-sdr-timing = <2 3>;
+		samsung,dw-mshc-ddr-timing = <1 2>;
+
+		slot@0 {
+			reg = <0>;
+			bus-width = <8>;
+		};
+	};
+
+	regulator_p3v3 {
+		compatible = "regulator-fixed";
+		regulator-name = "p3v3_en";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		gpio = <&gpa1 1 1>;
+		enable-active-high;
+		regulator-boot-on;
+	};
+
+	rtc@10070000 {
+		status = "okay";
+	};
+
+	sdhci@12530000 {
+		bus-width = <4>;
+		pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_cd &sd2_bus4>;
+		pinctrl-names = "default";
+		status = "okay";
+	};
+
+	serial@13800000 {
+		status = "okay";
+	};
+
+	serial@13810000 {
+		status = "okay";
+	};
+
+	serial@13820000 {
+		status = "okay";
+	};
+
+	serial@13830000 {
+		status = "okay";
+	};
+
+	fixed-rate-clocks {
+		xxti {
+			compatible = "samsung,clock-xxti";
+			clock-frequency = <0>;
+		};
+
+		xusbxti {
+			compatible = "samsung,clock-xusbxti";
+			clock-frequency = <24000000>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/exynos4412-origen.dts b/arch/arm/boot/dts/exynos4412-origen.dts
new file mode 100644
index 0000000..a5478bd
--- /dev/null
+++ b/arch/arm/boot/dts/exynos4412-origen.dts
@@ -0,0 +1,430 @@
+/*
+ * Insignal's Exynos4412 based Origen board device tree source
+ *
+ * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Device tree source file for Insignal's Origen board which is based on
+ * Samsung's Exynos4412 SoC.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/dts-v1/;
+/include/ "exynos4412.dtsi"
+
+/ {
+	model = "Insignal Origen evaluation board based on Exynos4412";
+	compatible = "insignal,origen4412", "samsung,exynos4412";
+
+	memory {
+		reg = <0x40000000 0x40000000>;
+	};
+
+	chosen {
+		bootargs ="console=ttySAC2,115200";
+	};
+
+	mmc_reg: voltage-regulator {
+		compatible = "regulator-fixed";
+		regulator-name = "VMEM_VDD_2.8V";
+		regulator-min-microvolt = <2800000>;
+		regulator-max-microvolt = <2800000>;
+		gpio = <&gpx1 1 0>;
+		enable-active-high;
+	};
+
+	sdhci@12530000 {
+		bus-width = <4>;
+		pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_bus4 &sd2_cd>;
+		pinctrl-names = "default";
+		vmmc-supply = <&mmc_reg>;
+		status = "okay";
+	};
+
+	mshc@12550000 {
+		pinctrl-0 = <&sd4_clk &sd4_cmd &sd4_bus4 &sd4_bus8>;
+		pinctrl-names = "default";
+		status = "okay";
+
+		num-slots = <1>;
+		supports-highspeed;
+		broken-cd;
+		fifo-depth = <0x80>;
+		card-detect-delay = <200>;
+		samsung,dw-mshc-ciu-div = <3>;
+		samsung,dw-mshc-sdr-timing = <2 3>;
+		samsung,dw-mshc-ddr-timing = <1 2>;
+
+		slot@0 {
+			reg = <0>;
+			bus-width = <8>;
+		};
+	};
+
+	codec@13400000 {
+		samsung,mfc-r = <0x43000000 0x800000>;
+		samsung,mfc-l = <0x51000000 0x800000>;
+		status = "okay";
+	};
+
+	serial@13800000 {
+		status = "okay";
+	};
+
+	serial@13810000 {
+		status = "okay";
+	};
+
+	serial@13820000 {
+		status = "okay";
+	};
+
+	serial@13830000 {
+		status = "okay";
+	};
+
+	i2c@13860000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		samsung,i2c-sda-delay = <100>;
+		samsung,i2c-max-bus-freq = <20000>;
+		pinctrl-0 = <&i2c0_bus>;
+		pinctrl-names = "default";
+		status = "okay";
+
+		s5m8767_pmic@66 {
+			compatible = "samsung,s5m8767-pmic";
+			reg = <0x66>;
+
+			s5m8767,pmic-buck-default-dvs-idx = <3>;
+
+			s5m8767,pmic-buck-dvs-gpios = <&gpx2 3 0>,
+							 <&gpx2 4 0>,
+							 <&gpx2 5 0>;
+
+			s5m8767,pmic-buck-ds-gpios = <&gpm3 5 0>,
+							<&gpm3 6 0>,
+							<&gpm3 7 0>;
+
+			s5m8767,pmic-buck2-dvs-voltage = <1250000>, <1200000>,
+							 <1200000>, <1200000>,
+							 <1200000>, <1200000>,
+							 <1200000>, <1200000>;
+
+			s5m8767,pmic-buck3-dvs-voltage = <1100000>, <1100000>,
+							 <1100000>, <1100000>,
+							 <1100000>, <1100000>,
+							 <1100000>, <1100000>;
+
+			s5m8767,pmic-buck4-dvs-voltage = <1200000>, <1200000>,
+							 <1200000>, <1200000>,
+							 <1200000>, <1200000>,
+							 <1200000>, <1200000>;
+
+			regulators {
+				ldo1_reg: LDO1 {
+					regulator-name = "VDD_ALIVE";
+					regulator-min-microvolt = <1100000>;
+					regulator-max-microvolt = <1100000>;
+					regulator-always-on;
+					regulator-boot-on;
+					op_mode = <1>; /* Normal Mode */
+				};
+
+				ldo2_reg: LDO2 {
+					regulator-name = "VDDQ_M12";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+					regulator-always-on;
+					op_mode = <1>; /* Normal Mode */
+				};
+
+				ldo3_reg: LDO3 {
+					regulator-name = "VDDIOAP_18";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+					op_mode = <1>; /* Normal Mode */
+				};
+
+				ldo4_reg: LDO4 {
+					regulator-name = "VDDQ_PRE";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+					op_mode = <1>; /* Normal Mode */
+				};
+
+				ldo5_reg: LDO5 {
+					regulator-name = "VDD18_2M";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+					op_mode = <1>; /* Normal Mode */
+				};
+
+				ldo6_reg: LDO6 {
+					regulator-name = "VDD10_MPLL";
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1000000>;
+					regulator-always-on;
+					op_mode = <1>; /* Normal Mode */
+				};
+
+				ldo7_reg: LDO7 {
+					regulator-name = "VDD10_XPLL";
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1000000>;
+					regulator-always-on;
+					op_mode = <1>; /* Normal Mode */
+				};
+
+				ldo8_reg: LDO8 {
+					regulator-name = "VDD10_MIPI";
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1000000>;
+					regulator-always-on;
+					op_mode = <1>; /* Normal Mode */
+				};
+
+				ldo9_reg: LDO9 {
+					regulator-name = "VDD33_LCD";
+					regulator-min-microvolt = <3300000>;
+					regulator-max-microvolt = <3300000>;
+					regulator-always-on;
+					op_mode = <1>; /* Normal Mode */
+				};
+
+				ldo10_reg: LDO10 {
+					regulator-name = "VDD18_MIPI";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+					op_mode = <1>; /* Normal Mode */
+				};
+
+				ldo11_reg: LDO11 {
+					regulator-name = "VDD18_ABB1";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+					op_mode = <1>; /* Normal Mode */
+				};
+
+				ldo12_reg: LDO12 {
+					regulator-name = "VDD33_UOTG";
+					regulator-min-microvolt = <3300000>;
+					regulator-max-microvolt = <3300000>;
+					regulator-always-on;
+					op_mode = <1>; /* Normal Mode */
+				};
+
+				ldo13_reg: LDO13 {
+					regulator-name = "VDDIOPERI_18";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+					op_mode = <1>; /* Normal Mode */
+				};
+
+				ldo14_reg: LDO14 {
+					regulator-name = "VDD18_ABB02";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+					op_mode = <1>; /* Normal Mode */
+				};
+
+				ldo15_reg: LDO15 {
+					regulator-name = "VDD10_USH";
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1000000>;
+					regulator-always-on;
+					op_mode = <1>; /* Normal Mode */
+				};
+
+				ldo16_reg: LDO16 {
+					regulator-name = "VDD18_HSIC";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+					op_mode = <1>; /* Normal Mode */
+				};
+
+				ldo17_reg: LDO17 {
+					regulator-name = "VDDIOAP_MMC012_28";
+					regulator-min-microvolt = <2800000>;
+					regulator-max-microvolt = <2800000>;
+					regulator-always-on;
+					op_mode = <1>; /* Normal Mode */
+				};
+
+				ldo18_reg: LDO18 {
+					regulator-name = "VDDIOPERI_28";
+					regulator-min-microvolt = <2800000>;
+					regulator-max-microvolt = <2800000>;
+					regulator-always-on;
+					op_mode = <1>; /* Normal Mode */
+				};
+
+				ldo19_reg: LDO19 {
+					regulator-name = "DVDD25";
+					regulator-min-microvolt = <2500000>;
+					regulator-max-microvolt = <2500000>;
+					regulator-always-on;
+					op_mode = <1>; /* Normal Mode */
+				};
+
+				ldo20_reg: LDO20 {
+					regulator-name = "VDD28_CAM";
+					regulator-min-microvolt = <2800000>;
+					regulator-max-microvolt = <2800000>;
+					regulator-always-on;
+					op_mode = <1>; /* Normal Mode */
+				};
+
+				ldo21_reg: LDO21 {
+					regulator-name = "VDD28_AF";
+					regulator-min-microvolt = <2800000>;
+					regulator-max-microvolt = <2800000>;
+					regulator-always-on;
+					op_mode = <1>; /* Normal Mode */
+				};
+
+				ldo22_reg: LDO22 {
+					regulator-name = "VDDA28_2M";
+					regulator-min-microvolt = <2800000>;
+					regulator-max-microvolt = <2800000>;
+					regulator-always-on;
+					op_mode = <1>; /* Normal Mode */
+				};
+
+				ldo23_reg: LDO23 {
+					regulator-name = "VDD28_TF";
+					regulator-min-microvolt = <2800000>;
+					regulator-max-microvolt = <2800000>;
+					regulator-always-on;
+					op_mode = <1>; /* Normal Mode */
+				};
+
+				ldo24_reg: LDO24 {
+					regulator-name = "VDD33_A31";
+					regulator-min-microvolt = <3300000>;
+					regulator-max-microvolt = <3300000>;
+					regulator-always-on;
+					op_mode = <1>; /* Normal Mode */
+				};
+
+				ldo25_reg: LDO25 {
+					regulator-name = "VDD18_CAM";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+					op_mode = <1>; /* Normal Mode */
+				};
+
+				ldo26_reg: LDO26 {
+					regulator-name = "VDD18_A31";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+					op_mode = <1>; /* Normal Mode */
+				};
+
+				ldo27_reg: LDO27 {
+					regulator-name = "GPS_1V8";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+					op_mode = <1>; /* Normal Mode */
+				};
+
+				ldo28_reg: LDO28 {
+					regulator-name = "DVDD12";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+					regulator-always-on;
+					op_mode = <1>; /* Normal Mode */
+				};
+
+				buck1_reg: BUCK1 {
+					regulator-name = "vdd_mif";
+					regulator-min-microvolt = <950000>;
+					regulator-max-microvolt	= <1100000>;
+					regulator-always-on;
+					regulator-boot-on;
+					op_mode = <1>; /* Normal Mode */
+				};
+
+				buck2_reg: BUCK2 {
+					regulator-name = "vdd_arm";
+					regulator-min-microvolt = <925000>;
+					regulator-max-microvolt	= <1300000>;
+					regulator-always-on;
+					regulator-boot-on;
+					op_mode = <1>; /* Normal Mode */
+				};
+
+				buck3_reg: BUCK3 {
+					regulator-name = "vdd_int";
+					regulator-min-microvolt = <900000>;
+					regulator-max-microvolt	= <1200000>;
+					regulator-always-on;
+					regulator-boot-on;
+					op_mode = <1>; /* Normal Mode */
+				};
+
+				buck4_reg: BUCK4 {
+					regulator-name = "vdd_g3d";
+					regulator-min-microvolt = <750000>;
+					regulator-max-microvolt	= <1500000>;
+					regulator-always-on;
+					regulator-boot-on;
+					op_mode = <1>; /* Normal Mode */
+				};
+
+				buck5_reg: BUCK5 {
+					regulator-name = "vdd_m12";
+					regulator-min-microvolt = <750000>;
+					regulator-max-microvolt	= <1500000>;
+					regulator-always-on;
+					regulator-boot-on;
+					op_mode = <1>; /* Normal Mode */
+				};
+
+				buck6_reg: BUCK6 {
+					regulator-name = "vdd12_5m";
+					regulator-min-microvolt = <750000>;
+					regulator-max-microvolt	= <1500000>;
+					regulator-always-on;
+					regulator-boot-on;
+					op_mode = <1>; /* Normal Mode */
+				};
+
+				buck9_reg: BUCK9 {
+					regulator-name = "vddf28_emmc";
+					regulator-min-microvolt = <750000>;
+					regulator-max-microvolt	= <3000000>;
+					regulator-always-on;
+					regulator-boot-on;
+					op_mode = <1>; /* Normal Mode */
+				};
+			};
+		};
+	};
+
+	fixed-rate-clocks {
+		xxti {
+			compatible = "samsung,clock-xxti";
+			clock-frequency = <0>;
+		};
+
+		xusbxti {
+			compatible = "samsung,clock-xusbxti";
+			clock-frequency = <24000000>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/exynos4412-smdk4412.dts b/arch/arm/boot/dts/exynos4412-smdk4412.dts
index f05bf57..dd56431 100644
--- a/arch/arm/boot/dts/exynos4412-smdk4412.dts
+++ b/arch/arm/boot/dts/exynos4412-smdk4412.dts
@@ -27,6 +27,27 @@
 		bootargs ="root=/dev/ram0 rw ramdisk=8192 initrd=0x41000000,8M console=ttySAC1,115200 init=/linuxrc";
 	};
 
+	g2d@10800000 {
+		status = "okay";
+	};
+
+	g2d@10800000 {
+		status = "okay";
+	};
+
+	sdhci@12530000 {
+		bus-width = <4>;
+		pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_bus4 &sd2_cd>;
+		pinctrl-names = "default";
+		status = "okay";
+	};
+
+	codec@13400000 {
+		samsung,mfc-r = <0x43000000 0x800000>;
+		samsung,mfc-l = <0x51000000 0x800000>;
+		status = "okay";
+	};
+
 	serial@13800000 {
 		status = "okay";
 	};
@@ -42,4 +63,16 @@
 	serial@13830000 {
 		status = "okay";
 	};
+
+	fixed-rate-clocks {
+		xxti {
+			compatible = "samsung,clock-xxti";
+			clock-frequency = <0>;
+		};
+
+		xusbxti {
+			compatible = "samsung,clock-xusbxti";
+			clock-frequency = <24000000>;
+		};
+	};
 };
diff --git a/arch/arm/boot/dts/exynos4412.dtsi b/arch/arm/boot/dts/exynos4412.dtsi
index d7dfe31..d75c047 100644
--- a/arch/arm/boot/dts/exynos4412.dtsi
+++ b/arch/arm/boot/dts/exynos4412.dtsi
@@ -25,4 +25,30 @@
 	gic:interrupt-controller@10490000 {
 		cpu-offset = <0x4000>;
 	};
+
+	mct@10050000 {
+		compatible = "samsung,exynos4412-mct";
+		reg = <0x10050000 0x800>;
+		interrupt-controller;
+		#interrups-cells = <2>;
+		interrupt-parent = <&mct_map>;
+		interrupts = <0 0>, <1 0>, <2 0>, <3 0>,
+			     <4 0>, <5 0>, <6 0>, <7 0>;
+		clocks = <&clock 3>, <&clock 344>;
+		clock-names = "fin_pll", "mct";
+
+		mct_map: mct-map {
+			#interrupt-cells = <2>;
+			#address-cells = <0>;
+			#size-cells = <0>;
+			interrupt-map = <0x0 0 &gic 0 57 0>,
+					<0x1 0 &combiner 12 5>,
+					<0x2 0 &combiner 12 6>,
+					<0x3 0 &combiner 12 7>,
+					<0x4 0 &gic 1 12 0>,
+					<0x5 0 &gic 1 12 0>,
+					<0x6 0 &gic 1 12 0>,
+					<0x7 0 &gic 1 12 0>;
+		};
+	};
 };
diff --git a/arch/arm/boot/dts/exynos4x12.dtsi b/arch/arm/boot/dts/exynos4x12.dtsi
index 9a87806..e3380a7 100644
--- a/arch/arm/boot/dts/exynos4x12.dtsi
+++ b/arch/arm/boot/dts/exynos4x12.dtsi
@@ -36,6 +36,12 @@
 			     <0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>;
 	};
 
+	clock: clock-controller@0x10030000 {
+		compatible = "samsung,exynos4412-clock";
+		reg = <0x10030000 0x20000>;
+		#clock-cells = <1>;
+	};
+
 	pinctrl_0: pinctrl@11400000 {
 		compatible = "samsung,exynos4x12-pinctrl";
 		reg = <0x11400000 0x1000>;
@@ -66,4 +72,11 @@
 		reg = <0x106E0000 0x1000>;
 		interrupts = <0 72 0>;
 	};
+
+	g2d@10800000 {
+		compatible = "samsung,exynos4212-g2d";
+		reg = <0x10800000 0x1000>;
+		interrupts = <0 89 0>;
+		status = "disabled";
+	};
 };
diff --git a/arch/arm/boot/dts/exynos5250-arndale.dts b/arch/arm/boot/dts/exynos5250-arndale.dts
new file mode 100644
index 0000000..02cfc76
--- /dev/null
+++ b/arch/arm/boot/dts/exynos5250-arndale.dts
@@ -0,0 +1,452 @@
+/*
+ * Samsung's Exynos5250 based Arndale board device tree source
+ *
+ * Copyright (c) 2013 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.
+*/
+
+/dts-v1/;
+/include/ "exynos5250.dtsi"
+
+/ {
+	model = "Insignal Arndale evaluation board based on EXYNOS5250";
+	compatible = "insignal,arndale", "samsung,exynos5250";
+
+	memory {
+		reg = <0x40000000 0x80000000>;
+	};
+
+	chosen {
+		bootargs = "console=ttySAC2,115200";
+	};
+
+	codec@11000000 {
+		samsung,mfc-r = <0x43000000 0x800000>;
+		samsung,mfc-l = <0x51000000 0x800000>;
+	};
+
+	i2c@12C60000 {
+		samsung,i2c-sda-delay = <100>;
+		samsung,i2c-max-bus-freq = <20000>;
+		samsung,i2c-slave-addr = <0x66>;
+
+		s5m8767_pmic@66 {
+			compatible = "samsung,s5m8767-pmic";
+			reg = <0x66>;
+
+			s5m8767,pmic-buck2-dvs-voltage = <1300000>;
+			s5m8767,pmic-buck3-dvs-voltage = <1100000>;
+			s5m8767,pmic-buck4-dvs-voltage = <1200000>;
+			s5m8767,pmic-buck-dvs-gpios = <&gpd1 0 0>,
+							<&gpd1 1 0>,
+							<&gpd1 2 0>;
+			s5m8767,pmic-buck-ds-gpios = <&gpx2 3 0>,
+							<&gpx2 4 0>,
+							<&gpx2 5 0>;
+			regulators {
+				ldo1_reg: LDO1 {
+					regulator-name = "VDD_ALIVE_1.0V";
+					regulator-min-microvolt = <1100000>;
+					regulator-max-microvolt = <1100000>;
+					regulator-always-on;
+					regulator-boot-on;
+					op_mode = <1>;
+				};
+
+				ldo2_reg: LDO2 {
+					regulator-name = "VDD_28IO_DP_1.35V";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+					regulator-always-on;
+					regulator-boot-on;
+					op_mode = <1>;
+				};
+
+				ldo3_reg: LDO3 {
+					regulator-name = "VDD_COMMON1_1.8V";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+					regulator-boot-on;
+					op_mode = <1>;
+				};
+
+				ldo4_reg: LDO4 {
+					regulator-name = "VDD_IOPERI_1.8V";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					op_mode = <1>;
+				};
+
+				ldo5_reg: LDO5 {
+					regulator-name = "VDD_EXT_1.8V";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+					regulator-boot-on;
+					op_mode = <1>;
+				};
+
+				ldo6_reg: LDO6 {
+					regulator-name = "VDD_MPLL_1.1V";
+					regulator-min-microvolt = <1100000>;
+					regulator-max-microvolt = <1100000>;
+					regulator-always-on;
+					regulator-boot-on;
+					op_mode = <1>;
+				};
+
+				ldo7_reg: LDO7 {
+					regulator-name = "VDD_XPLL_1.1V";
+					regulator-min-microvolt = <1100000>;
+					regulator-max-microvolt = <1100000>;
+					regulator-always-on;
+					regulator-boot-on;
+					op_mode = <1>;
+				};
+
+				ldo8_reg: LDO8 {
+					regulator-name = "VDD_COMMON2_1.0V";
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1000000>;
+					regulator-always-on;
+					regulator-boot-on;
+					op_mode = <1>;
+				};
+
+				ldo9_reg: LDO9 {
+					regulator-name = "VDD_33ON_3.0V";
+					regulator-min-microvolt = <3000000>;
+					regulator-max-microvolt = <3000000>;
+					op_mode = <1>;
+				};
+
+				ldo10_reg: LDO10 {
+					regulator-name = "VDD_COMMON3_1.8V";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+					regulator-boot-on;
+					op_mode = <1>;
+				};
+
+				ldo11_reg: LDO11 {
+					regulator-name = "VDD_ABB2_1.8V";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+					regulator-boot-on;
+					op_mode = <1>;
+				};
+
+				ldo12_reg: LDO12 {
+					regulator-name = "VDD_USB_3.0V";
+					regulator-min-microvolt = <3000000>;
+					regulator-max-microvolt = <3000000>;
+					regulator-always-on;
+					regulator-boot-on;
+					op_mode = <1>;
+				};
+
+				ldo13_reg: LDO13 {
+					regulator-name = "VDDQ_C2C_W_1.8V";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+					regulator-boot-on;
+					op_mode = <1>;
+				};
+
+				ldo14_reg: LDO14 {
+					regulator-name = "VDD18_ABB0_3_1.8V";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+					regulator-boot-on;
+					op_mode = <1>;
+				};
+
+				ldo15_reg: LDO15 {
+					regulator-name = "VDD10_COMMON4_1.0V";
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1000000>;
+					regulator-always-on;
+					regulator-boot-on;
+					op_mode = <1>;
+				};
+
+				ldo16_reg: LDO16 {
+					regulator-name = "VDD18_HSIC_1.8V";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+					regulator-boot-on;
+					op_mode = <1>;
+				};
+
+				ldo17_reg: LDO17 {
+					regulator-name = "VDDQ_MMC2_3_2.8V";
+					regulator-min-microvolt = <2800000>;
+					regulator-max-microvolt = <2800000>;
+					regulator-always-on;
+					regulator-boot-on;
+					op_mode = <1>;
+				};
+
+				ldo18_reg: LDO18 {
+					regulator-name = "VDD_33ON_2.8V";
+					regulator-min-microvolt = <2800000>;
+					regulator-max-microvolt = <2800000>;
+					op_mode = <1>;
+				};
+
+				ldo22_reg: LDO22 {
+					regulator-name = "EXT_33_OFF";
+					regulator-min-microvolt = <3300000>;
+					regulator-max-microvolt = <3300000>;
+					op_mode = <1>;
+				};
+
+				ldo23_reg: LDO23 {
+					regulator-name = "EXT_28_OFF";
+					regulator-min-microvolt = <2800000>;
+					regulator-max-microvolt = <2800000>;
+					op_mode = <1>;
+				};
+
+				ldo25_reg: LDO25 {
+					regulator-name = "PVDD_LDO25";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+					op_mode = <1>;
+				};
+
+				ldo26_reg: LDO26 {
+					regulator-name = "EXT_18_OFF";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					op_mode = <1>;
+				};
+
+				buck1_reg: BUCK1 {
+					regulator-name = "vdd_mif";
+					regulator-min-microvolt = <950000>;
+					regulator-max-microvolt = <1200000>;
+					regulator-always-on;
+					regulator-boot-on;
+					op_mode = <1>;
+				};
+
+				buck2_reg: BUCK2 {
+					regulator-name = "vdd_arm";
+					regulator-min-microvolt = <925000>;
+					regulator-max-microvolt = <1300000>;
+					regulator-always-on;
+					regulator-boot-on;
+					op_mode = <1>;
+				};
+
+				buck3_reg: BUCK3 {
+					regulator-name = "vdd_int";
+					regulator-min-microvolt = <900000>;
+					regulator-max-microvolt = <1200000>;
+					regulator-always-on;
+					regulator-boot-on;
+					op_mode = <1>;
+				};
+
+				buck4_reg: BUCK4 {
+					regulator-name = "vdd_g3d";
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1000000>;
+					regulator-boot-on;
+					op_mode = <1>;
+				};
+
+				buck5_reg: BUCK5 {
+					regulator-name = "VDD_MEM_1.35V";
+					regulator-min-microvolt = <750000>;
+					regulator-max-microvolt = <1355000>;
+					regulator-always-on;
+					regulator-boot-on;
+					op_mode = <1>;
+				};
+
+				buck9_reg: BUCK9 {
+					regulator-name = "VDD_33_OFF_EXT1";
+					regulator-min-microvolt = <750000>;
+					regulator-max-microvolt = <3000000>;
+					op_mode = <1>;
+				};
+			};
+		};
+	};
+
+	i2c@12C70000 {
+		status = "disabled";
+	};
+
+	i2c@12C80000 {
+		status = "disabled";
+	};
+
+	i2c@12C90000 {
+		status = "disabled";
+	};
+
+	i2c@12CA0000 {
+		status = "disabled";
+	};
+
+	i2c@12CB0000 {
+		status = "disabled";
+	};
+
+	i2c@12CC0000 {
+		status = "disabled";
+	};
+
+	i2c@12CD0000 {
+		status = "disabled";
+	};
+
+	i2c@121D0000 {
+		status = "disabled";
+	};
+
+	dwmmc_0: dwmmc0@12200000 {
+		num-slots = <1>;
+		supports-highspeed;
+		broken-cd;
+		fifo-depth = <0x80>;
+		card-detect-delay = <200>;
+		samsung,dw-mshc-ciu-div = <3>;
+		samsung,dw-mshc-sdr-timing = <2 3>;
+		samsung,dw-mshc-ddr-timing = <1 2>;
+		vmmc-supply = <&mmc_reg>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8>;
+
+		slot@0 {
+			reg = <0>;
+			bus-width = <8>;
+		};
+	};
+
+	dwmmc_1: dwmmc1@12210000 {
+		status = "disabled";
+	};
+
+	dwmmc_2: dwmmc2@12220000 {
+		num-slots = <1>;
+		supports-highspeed;
+		fifo-depth = <0x80>;
+		card-detect-delay = <200>;
+		samsung,dw-mshc-ciu-div = <3>;
+		samsung,dw-mshc-sdr-timing = <2 3>;
+		samsung,dw-mshc-ddr-timing = <1 2>;
+		vmmc-supply = <&mmc_reg>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_cd &sd2_bus4>;
+
+		slot@0 {
+			reg = <0>;
+			bus-width = <4>;
+			disable-wp;
+		};
+	};
+
+	dwmmc_3: dwmmc3@12230000 {
+		status = "disabled";
+	};
+
+	spi_0: spi@12d20000 {
+		status = "disabled";
+	};
+
+	spi_1: spi@12d30000 {
+		status = "disabled";
+	};
+
+	spi_2: spi@12d40000 {
+		status = "disabled";
+	};
+
+	gpio_keys {
+		compatible = "gpio-keys";
+
+		menu {
+			label = "SW-TACT2";
+			gpios = <&gpx1 4 1>;
+			linux,code = <139>;
+			gpio-key,wakeup;
+		};
+
+		home {
+			label = "SW-TACT3";
+			gpios = <&gpx1 5 1>;
+			linux,code = <102>;
+			gpio-key,wakeup;
+		};
+
+		up {
+			label = "SW-TACT4";
+			gpios = <&gpx1 6 1>;
+			linux,code = <103>;
+			gpio-key,wakeup;
+		};
+
+		down {
+			label = "SW-TACT5";
+			gpios = <&gpx1 7 1>;
+			linux,code = <108>;
+			gpio-key,wakeup;
+		};
+
+		back {
+			label = "SW-TACT6";
+			gpios = <&gpx2 0 1>;
+			linux,code = <158>;
+			gpio-key,wakeup;
+		};
+
+		wakeup {
+			label = "SW-TACT7";
+			gpios = <&gpx2 1 1>;
+			linux,code = <143>;
+			gpio-key,wakeup;
+		};
+	};
+
+	hdmi {
+		hpd-gpio = <&gpx3 7 2>;
+		vdd_osc-supply = <&ldo10_reg>;
+		vdd_pll-supply = <&ldo8_reg>;
+		vdd-supply = <&ldo8_reg>;
+	};
+
+	mmc_reg: voltage-regulator {
+		compatible = "regulator-fixed";
+		regulator-name = "VDD_33ON_2.8V";
+		regulator-min-microvolt = <2800000>;
+		regulator-max-microvolt = <2800000>;
+		gpio = <&gpx1 1 1>;
+		enable-active-high;
+	};
+
+	reg_hdmi_en: fixedregulator@0 {
+		compatible = "regulator-fixed";
+		regulator-name = "hdmi-en";
+	};
+
+	fixed-rate-clocks {
+		xxti {
+			compatible = "samsung,clock-xxti";
+			clock-frequency = <24000000>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/exynos5250-pinctrl.dtsi b/arch/arm/boot/dts/exynos5250-pinctrl.dtsi
new file mode 100644
index 0000000..d1650fb
--- /dev/null
+++ b/arch/arm/boot/dts/exynos5250-pinctrl.dtsi
@@ -0,0 +1,783 @@
+/*
+ * Samsung's Exynos5250 SoC pin-mux and pin-config device tree source
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Samsung's Exynos5250 SoC pin-mux and pin-config optiosn are listed as device
+ * tree nodes are listed in this file.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/ {
+	pinctrl@11400000 {
+		gpa0: gpa0 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpa1: gpa1 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpa2: gpa2 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpb0: gpb0 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpb1: gpb1 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpb2: gpb2 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpb3: gpb3 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpc0: gpc0 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpc1: gpc1 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpc2: gpc2 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpc3: gpc3 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpd0: gpd0 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpd1: gpd1 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpy0: gpy0 {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpy1: gpy1 {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpy2: gpy2 {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpy3: gpy3 {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpy4: gpy4 {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpy5: gpy5 {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpy6: gpy6 {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpc4: gpc4 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpx0: gpx0 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			interrupt-parent = <&combiner>;
+			#interrupt-cells = <2>;
+			interrupts = <23 0>, <24 0>, <25 0>, <25 1>,
+				     <26 0>, <26 1>, <27 0>, <27 1>;
+		};
+
+		gpx1: gpx1 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			interrupt-parent = <&combiner>;
+			#interrupt-cells = <2>;
+			interrupts = <28 0>, <28 1>, <29 0>, <29 1>,
+				     <30 0>, <30 1>, <31 0>, <31 1>;
+		};
+
+		gpx2: gpx2 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpx3: gpx3 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		uart0_data: uart0-data {
+			samsung,pins = "gpa0-0", "gpa0-1";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		uart0_fctl: uart0-fctl {
+			samsung,pins = "gpa0-2", "gpa0-3";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samaung,pin-drv = <0>;
+		};
+
+		i2c2_bus: i2c2-bus {
+			samsung,pins = "gpa0-6", "gpa0-7";
+			samsung,pin-function = <3>;
+			samsung,pin-pud = <3>;
+			samaung,pin-drv = <0>;
+		};
+
+		i2c2_hs_bus: i2c2-hs-bus {
+			samsung,pins = "gpa0-6", "gpa0-7";
+			samsung,pin-function = <4>;
+			samsung,pin-pud = <3>;
+			samaung,pin-drv = <0>;
+		};
+
+		uart2_data: uart2-data {
+			samsung,pins = "gpa1-0", "gpa1-1";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		uart2_fctl: uart2-fctl {
+			samsung,pins = "gpa1-2", "gpa1-3";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samaung,pin-drv = <0>;
+		};
+
+		i2c3_bus: i2c3-bus {
+			samsung,pins = "gpa1-2", "gpa1-3";
+			samsung,pin-function = <3>;
+			samsung,pin-pud = <3>;
+			samaung,pin-drv = <0>;
+		};
+
+		i2c3_hs_bus: i2c3-hs-bus {
+			samsung,pins = "gpa1-2", "gpa1-3";
+			samsung,pin-function = <4>;
+			samsung,pin-pud = <3>;
+			samaung,pin-drv = <0>;
+		};
+
+		uart3_data: uart3-data {
+			samsung,pins = "gpa1-4", "gpa1-4";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		spi0_bus: spi0-bus {
+			samsung,pins = "gpa2-0", "gpa2-2", "gpa2-3";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <0>;
+		};
+
+		i2c4_bus: i2c4-bus {
+			samsung,pins = "gpa2-0", "gpa2-1";
+			samsung,pin-function = <3>;
+			samsung,pin-pud = <3>;
+			samaung,pin-drv = <0>;
+		};
+
+		i2c5_bus: i2c5-bus {
+			samsung,pins = "gpa2-2", "gpa2-3";
+			samsung,pin-function = <3>;
+			samsung,pin-pud = <3>;
+			samaung,pin-drv = <0>;
+		};
+
+		spi1_bus: spi1-bus {
+			samsung,pins = "gpa2-4", "gpa2-6", "gpa2-7";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <0>;
+		};
+
+		i2s1_bus: i2s1-bus {
+			samsung,pins = "gpb0-0", "gpb0-1", "gpb0-2", "gpb0-3",
+					"gpb0-4";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		pcm1_bus: pcm1-bus {
+			samsung,pins = "gpb0-0", "gpb0-1", "gpb0-2", "gpb0-3",
+					"gpb0-4";
+			samsung,pin-function = <3>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		ac97_bus: ac97-bus {
+			samsung,pins = "gpb0-0", "gpb0-1", "gpb0-2", "gpb0-3",
+					"gpb0-4";
+			samsung,pin-function = <4>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		i2s2_bus: i2s2-bus {
+			samsung,pins = "gpb1-0", "gpb1-1", "gpb1-2", "gpb1-3",
+					"gpb1-4";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		pcm2_bus: pcm2-bus {
+			samsung,pins = "gpb1-0", "gpb1-1", "gpb1-2", "gpb1-3",
+					"gpb1-4";
+			samsung,pin-function = <3>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		spdif_bus: spdif-bus {
+			samsung,pins = "gpb1-0", "gpb1-1";
+			samsung,pin-function = <4>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		spi2_bus: spi2-bus {
+			samsung,pins = "gpb1-1", "gpb1-3", "gpb1-4";
+			samsung,pin-function = <5>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <0>;
+		};
+
+		i2c6_bus: i2c6-bus {
+			samsung,pins = "gpb1-3", "gpb1-4";
+			samsung,pin-function = <4>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <0>;
+		};
+
+		i2c7_bus: i2c7-bus {
+			samsung,pins = "gpb2-2", "gpb2-3";
+			samsung,pin-function = <3>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <0>;
+		};
+
+		i2c0_bus: i2c0-bus {
+			samsung,pins = "gpb3-0", "gpb3-1";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <0>;
+		};
+
+		i2c1_bus: i2c1-bus {
+			samsung,pins = "gpb3-2", "gpb3-3";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <0>;
+		};
+
+		i2c0_hs_bus: i2c0-hs-bus {
+			samsung,pins = "gpb3-0", "gpb3-1";
+			samsung,pin-function = <4>;
+			samsung,pin-pud = <3>;
+			samaung,pin-drv = <0>;
+		};
+
+		i2c1_hs_bus: i2c1-hs-bus {
+			samsung,pins = "gpb3-2", "gpb3-3";
+			samsung,pin-function = <4>;
+			samsung,pin-pud = <3>;
+			samaung,pin-drv = <0>;
+		};
+
+		sd0_clk: sd0-clk {
+			samsung,pins = "gpc0-0";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <3>;
+		};
+
+		sd0_cmd: sd0-cmd {
+			samsung,pins = "gpc0-1";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <3>;
+		};
+
+		sd0_cd: sd0-cd {
+			samsung,pins = "gpc0-2";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <3>;
+		};
+
+		sd0_bus1: sd0-bus-width1 {
+			samsung,pins = "gpc0-3";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <3>;
+		};
+
+		sd0_bus4: sd0-bus-width4 {
+			samsung,pins = "gpc0-3", "gpc0-4", "gpc0-5", "gpc0-6";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <3>;
+		};
+
+		sd0_bus8: sd0-bus-width8 {
+			samsung,pins = "gpc1-0", "gpc1-1", "gpc1-2", "gpc1-3";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <3>;
+		};
+
+		sd1_clk: sd1-clk {
+			samsung,pins = "gpc2-0";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <3>;
+		};
+
+		sd1_cmd: sd1-cmd {
+			samsung,pins = "gpc2-1";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <3>;
+		};
+
+		sd1_cd: sd1-cd {
+			samsung,pins = "gpc2-2";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <3>;
+		};
+
+		sd1_bus1: sd1-bus-width1 {
+			samsung,pins = "gpc2-3";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <3>;
+		};
+
+		sd1_bus4: sd1-bus-width4 {
+			samsung,pins = "gpc2-3", "gpc2-4", "gpc2-5", "gpc2-6";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <3>;
+		};
+
+		sd2_clk: sd2-clk {
+			samsung,pins = "gpc3-0";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <3>;
+		};
+
+		sd2_cmd: sd2-cmd {
+			samsung,pins = "gpc3-1";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <3>;
+		};
+
+		sd2_cd: sd2-cd {
+			samsung,pins = "gpc3-2";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <3>;
+		};
+
+		sd2_bus1: sd2-bus-width1 {
+			samsung,pins = "gpc3-3";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <3>;
+		};
+
+		sd2_bus4: sd2-bus-width4 {
+			samsung,pins = "gpc3-3", "gpc3-4", "gpc3-5", "gpc3-6";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <3>;
+		};
+
+		sd2_bus8: sd2-bus-width8 {
+			samsung,pins = "gpc4-3", "gpc4-4", "gpc4-5", "gpc4-6";
+			samsung,pin-function = <3>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <3>;
+		};
+
+		sd3_clk: sd3-clk {
+			samsung,pins = "gpc4-0";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <3>;
+		};
+
+		sd3_cmd: sd3-cmd {
+			samsung,pins = "gpc4-1";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <3>;
+		};
+
+		sd3_cd: sd3-cd {
+			samsung,pins = "gpc4-2";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <3>;
+		};
+
+		sd3_bus1: sd3-bus-width1 {
+			samsung,pins = "gpc4-3";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <3>;
+		};
+
+		sd3_bus4: sd3-bus-width4 {
+			samsung,pins = "gpc4-3", "gpc4-4", "gpc4-5", "gpc4-6";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <3>;
+		};
+
+		uart1_data: uart1-data {
+			samsung,pins = "gpd0-0", "gpd0-1";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		uart1_fctl: uart1-fctl {
+			samsung,pins = "gpd0-2", "gpd0-3";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samaung,pin-drv = <0>;
+		};
+	};
+
+	pinctrl@13400000 {
+		gpe0: gpe0 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpe1: gpe1 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpf0: gpf0 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpf1: gpf1 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpg0: gpg0 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpg1: gpg1 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpg2: gpg2 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gph0: gph0 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gph1: gph1 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		cam_gpio_a: cam-gpio-a {
+			samsung,pins = "gpe0-0", "gpe0-1", "gpe0-2", "gpe0-3",
+				       "gpe0-4", "gpe0-5", "gpe0-6", "gpe0-7",
+				       "gpe1-0", "gpe1-1";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		cam_gpio_b: cam-gpio-b {
+			samsung,pins = "gpf0-0", "gpf0-1", "gpf0-2", "gpf0-3",
+				       "gpf1-0", "gpf1-1", "gpf1-2", "gpf1-3";
+			samsung,pin-function = <3>;
+			samsung,pin-pud = <0>;
+			samaung,pin-drv = <0>;
+		};
+
+		cam_i2c2_bus: cam-i2c2-bus {
+			samsung,pins = "gpe0-6", "gpe1-0";
+			samsung,pin-function = <4>;
+			samsung,pin-pud = <3>;
+			samaung,pin-drv = <0>;
+		};
+
+		cam_spi1_bus: cam-spi1-bus {
+			samsung,pins = "gpe0-4", "gpe0-5", "gpf0-2", "gpf0-3";
+			samsung,pin-function = <4>;
+			samsung,pin-pud = <0>;
+			samaung,pin-drv = <0>;
+		};
+
+		cam_i2c1_bus: cam-i2c1-bus {
+			samsung,pins = "gpf0-2", "gpf0-3";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samaung,pin-drv = <0>;
+		};
+
+		cam_i2c0_bus: cam-i2c0-bus {
+			samsung,pins = "gpf0-0", "gpf0-1";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samaung,pin-drv = <0>;
+		};
+
+		cam_spi0_bus: cam-spi0-bus {
+			samsung,pins = "gpf1-0", "gpf1-1", "gpf1-2", "gpf1-3";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samaung,pin-drv = <0>;
+		};
+
+		cam_bayrgb_bus: cam-bayrgb-bus {
+			samsung,pins = "gpg0-0", "gpg0-1", "gpg0-2", "gpg0-3",
+				       "gpg0-4", "gpg0-5", "gpg0-6", "gpg0-7",
+				       "gpg1-0", "gpg1-1", "gpg1-2", "gpg1-3",
+				       "gpg1-4", "gpg1-5", "gpg1-6", "gpg1-7",
+				       "gpg2-0", "gpg2-1";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samaung,pin-drv = <0>;
+		};
+
+		cam_port_a: cam-port-a {
+			samsung,pins = "gph0-0", "gph0-1", "gph0-2", "gph0-3",
+				       "gph1-0", "gph1-1", "gph1-2", "gph1-3",
+				       "gph1-4", "gph1-5", "gph1-6", "gph1-7";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samaung,pin-drv = <0>;
+		};
+	};
+
+	pinctrl@10d10000 {
+		gpv0: gpv0 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpv1: gpv1 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpv2: gpv2 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpv3: gpv3 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpv4: gpv4 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		c2c_rxd: c2c-rxd {
+			samsung,pins = "gpv0-0", "gpv0-1", "gpv0-2", "gpv0-3",
+				       "gpv0-4", "gpv0-5", "gpv0-6", "gpv0-7",
+				       "gpv1-0", "gpv1-1", "gpv1-2", "gpv1-3",
+				       "gpv1-4", "gpv1-5", "gpv1-6", "gpv1-7";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samaung,pin-drv = <0>;
+		};
+
+		c2c_txd: c2c-txd {
+			samsung,pins = "gpv2-0", "gpv2-1", "gpv2-2", "gpv2-3",
+				       "gpv2-4", "gpv2-5", "gpv2-6", "gpv2-7",
+				       "gpv3-0", "gpv3-1", "gpv3-2", "gpv3-3",
+				       "gpv3-4", "gpv3-5", "gpv3-6", "gpv3-7";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samaung,pin-drv = <0>;
+		};
+	};
+
+	pinctrl@03680000 {
+		gpz: gpz {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		i2s0_bus: i2s0-bus {
+			samsung,pins = "gpz-0", "gpz-1", "gpz-2", "gpz-3",
+					"gpz-4", "gpz-5", "gpz-6";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/exynos5250-smdk5250.dts b/arch/arm/boot/dts/exynos5250-smdk5250.dts
index 1b8d410..4be14df 100644
--- a/arch/arm/boot/dts/exynos5250-smdk5250.dts
+++ b/arch/arm/boot/dts/exynos5250-smdk5250.dts
@@ -30,8 +30,6 @@
 	i2c@12C60000 {
 		samsung,i2c-sda-delay = <100>;
 		samsung,i2c-max-bus-freq = <20000>;
-		gpios = <&gpb3 0 2 3 0>,
-			<&gpb3 1 2 3 0>;
 
 		eeprom@50 {
 			compatible = "samsung,s524ad0xd1";
@@ -42,8 +40,6 @@
 	i2c@12C70000 {
 		samsung,i2c-sda-delay = <100>;
 		samsung,i2c-max-bus-freq = <20000>;
-		gpios = <&gpb3 2 2 3 0>,
-			<&gpb3 3 2 3 0>;
 
 		eeprom@51 {
 			compatible = "samsung,s524ad0xd1";
@@ -74,8 +70,6 @@
 	i2c@12C80000 {
 		samsung,i2c-sda-delay = <100>;
 		samsung,i2c-max-bus-freq = <66000>;
-		gpios = <&gpa0 6 3 3 0>,
-			<&gpa0 7 3 3 0>;
 
 		hdmiddc@50 {
 			compatible = "samsung,exynos5-hdmiddc";
@@ -122,15 +116,12 @@
 		samsung,dw-mshc-ciu-div = <3>;
 		samsung,dw-mshc-sdr-timing = <2 3>;
 		samsung,dw-mshc-ddr-timing = <1 2>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8>;
 
 		slot@0 {
 			reg = <0>;
 			bus-width = <8>;
-			gpios = <&gpc0 0 2 0 3>, <&gpc0 1 2 0 3>,
-				<&gpc1 0 2 3 3>, <&gpc1 1 2 3 3>,
-				<&gpc1 2 2 3 3>, <&gpc1 3 2 3 3>,
-				<&gpc0 3 2 3 3>, <&gpc0 4 2 3 3>,
-				<&gpc0 5 2 3 3>, <&gpc0 6 2 3 3>;
 		};
 	};
 
@@ -146,17 +137,13 @@
 		samsung,dw-mshc-ciu-div = <3>;
 		samsung,dw-mshc-sdr-timing = <2 3>;
 		samsung,dw-mshc-ddr-timing = <1 2>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_cd &sd2_bus4>;
 
 		slot@0 {
 			reg = <0>;
 			bus-width = <4>;
-			samsung,cd-pinmux-gpio = <&gpc3 2 2 3 3>;
 			disable-wp;
-			gpios = <&gpc3 0 2 0 3>, <&gpc3 1 2 0 3>,
-				<&gpc3 3 2 3 3>, <&gpc3 4 2 3 3>,
-				<&gpc3 5 2 3 3>, <&gpc3 6 2 3 3>,
-				<&gpc4 3 3 3 3>, <&gpc4 3 3 3 3>,
-				<&gpc4 5 3 3 3>, <&gpc4 6 3 3 3>;
 		};
 	};
 
@@ -169,10 +156,6 @@
 	};
 
 	spi_1: spi@12d30000 {
-		gpios = <&gpa2 4 2 3 0>,
-			<&gpa2 6 2 3 0>,
-			<&gpa2 7 2 3 0>;
-
 		w25q80bw@0 {
 			#address-cells = <1>;
 			#size-cells = <1>;
@@ -181,7 +164,7 @@
 			spi-max-frequency = <1000000>;
 
 			controller-data {
-				cs-gpio = <&gpa2 5 1 0 3>;
+				cs-gpio = <&gpa2 5 0>;
 				samsung,spi-feedback-delay = <0>;
 			};
 
@@ -203,7 +186,7 @@
 	};
 
 	hdmi {
-		hpd-gpio = <&gpx3 7 0xf 1 3>;
+		hpd-gpio = <&gpx3 7 0>;
 	};
 
 	codec@11000000 {
@@ -212,9 +195,7 @@
 	};
 
 	i2s0: i2s@03830000 {
-		gpios = <&gpz 0 2 0 0>, <&gpz 1 2 0 0>, <&gpz 2 2 0 0>,
-			<&gpz 3 2 0 0>, <&gpz 4 2 0 0>, <&gpz 5 2 0 0>,
-			<&gpz 6 2 0 0>;
+		status = "okay";
 	};
 
 	i2s1: i2s@12D60000 {
@@ -231,4 +212,39 @@
 		samsung,i2s-controller = <&i2s0>;
 		samsung,audio-codec = <&wm8994>;
 	};
+
+	usb@12110000 {
+		samsung,vbus-gpio = <&gpx2 6 1 3 3>;
+	};
+
+	dp-controller {
+		samsung,color-space = <0>;
+		samsung,dynamic-range = <0>;
+		samsung,ycbcr-coeff = <0>;
+		samsung,color-depth = <1>;
+		samsung,link-rate = <0x0a>;
+		samsung,lane-count = <4>;
+	};
+
+	display-timings {
+		native-mode = <&timing0>;
+		timing0: timing@0 {
+			/* 1280x800 */
+			clock-frequency = <50000>;
+			hactive = <1280>;
+			vactive = <800>;
+			hfront-porch = <4>;
+			hback-porch = <4>;
+			hsync-len = <4>;
+			vback-porch = <4>;
+			vfront-porch = <4>;
+			vsync-len = <4>;
+	};
+
+	fixed-rate-clocks {
+		xxti {
+			compatible = "samsung,clock-xxti";
+			clock-frequency = <24000000>;
+		};
+	};
 };
diff --git a/arch/arm/boot/dts/exynos5250-snow.dts b/arch/arm/boot/dts/exynos5250-snow.dts
index 17dd951..581ffae 100644
--- a/arch/arm/boot/dts/exynos5250-snow.dts
+++ b/arch/arm/boot/dts/exynos5250-snow.dts
@@ -16,12 +16,27 @@
 	model = "Google Snow";
 	compatible = "google,snow", "samsung,exynos5250";
 
+	pinctrl@11400000 {
+		sd3_clk: sd3-clk {
+			samsung,pin-drv = <0>;
+		};
+
+		sd3_cmd: sd3-cmd {
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <0>;
+		};
+
+		sd3_bus4: sd3-bus-width4 {
+			samsung,pin-drv = <0>;
+		};
+	};
+
 	gpio-keys {
 		compatible = "gpio-keys";
 
 		lid-switch {
 			label = "Lid";
-			gpios = <&gpx3 5 0 0x10000 0>;
+			gpios = <&gpx3 5 1>;
 			linux,input-type = <5>; /* EV_SW */
 			linux,code = <0>; /* SW_LID */
 			debounce-interval = <1>;
@@ -35,9 +50,19 @@
 	 */
 	dwmmc3@12230000 {
 		slot@0 {
-			gpios = <&gpc4 0 2 0 0>, <&gpc4 1 2 3 0>,
-				<&gpc4 3 2 3 0>, <&gpc4 4 2 3 0>,
-				<&gpc4 5 2 3 0>, <&gpc4 6 2 3 0>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&sd3_clk &sd3_cmd &sd3_bus4>;
+		};
+	};
+
+	usb@12110000 {
+		samsung,vbus-gpio = <&gpx1 1 1 3 3>;
+	};
+
+	fixed-rate-clocks {
+		xxti {
+			compatible = "samsung,clock-xxti";
+			clock-frequency = <24000000>;
 		};
 	};
 };
diff --git a/arch/arm/boot/dts/exynos5250.dtsi b/arch/arm/boot/dts/exynos5250.dtsi
index b1ac73e..dc55e33 100644
--- a/arch/arm/boot/dts/exynos5250.dtsi
+++ b/arch/arm/boot/dts/exynos5250.dtsi
@@ -18,6 +18,7 @@
 */
 
 /include/ "skeleton.dtsi"
+/include/ "exynos5250-pinctrl.dtsi"
 
 / {
 	compatible = "samsung,exynos5250";
@@ -44,13 +45,45 @@
 		i2c6 = &i2c_6;
 		i2c7 = &i2c_7;
 		i2c8 = &i2c_8;
+		pinctrl0 = &pinctrl_0;
+		pinctrl1 = &pinctrl_1;
+		pinctrl2 = &pinctrl_2;
+		pinctrl3 = &pinctrl_3;
+	};
+
+	pd_gsc: gsc-power-domain@0x10044000 {
+		compatible = "samsung,exynos4210-pd";
+		reg = <0x10044000 0x20>;
+	};
+
+	pd_mfc: mfc-power-domain@0x10044040 {
+		compatible = "samsung,exynos4210-pd";
+		reg = <0x10044040 0x20>;
+	};
+
+	clock: clock-controller@0x10010000 {
+		compatible = "samsung,exynos5250-clock";
+		reg = <0x10010000 0x30000>;
+		#clock-cells = <1>;
 	};
 
 	gic:interrupt-controller@10481000 {
-		compatible = "arm,cortex-a9-gic";
+		compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic";
 		#interrupt-cells = <3>;
 		interrupt-controller;
-		reg = <0x10481000 0x1000>, <0x10482000 0x2000>;
+		reg = <0x10481000 0x1000>,
+		      <0x10482000 0x1000>,
+		      <0x10484000 0x2000>,
+		      <0x10486000 0x2000>;
+		interrupts = <1 9 0xf04>;
+	};
+
+	timer {
+		compatible = "arm,armv7-timer";
+		interrupts = <1 13 0xf08>,
+			     <1 14 0xf08>,
+			     <1 11 0xf08>,
+			     <1 10 0xf08>;
 	};
 
 	combiner:interrupt-controller@10440000 {
@@ -69,58 +102,135 @@
 			     <0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>;
 	};
 
+	mct@101C0000 {
+		compatible = "samsung,exynos4210-mct";
+		reg = <0x101C0000 0x800>;
+		interrupt-controller;
+		#interrups-cells = <2>;
+		interrupt-parent = <&mct_map>;
+		interrupts = <0 0>, <1 0>, <2 0>, <3 0>,
+			     <4 0>, <5 0>;
+		clocks = <&clock 1>, <&clock 335>;
+		clock-names = "fin_pll", "mct";
+
+		mct_map: mct-map {
+			#interrupt-cells = <2>;
+			#address-cells = <0>;
+			#size-cells = <0>;
+			interrupt-map = <0x0 0 &combiner 23 3>,
+					<0x1 0 &combiner 23 4>,
+					<0x2 0 &combiner 25 2>,
+					<0x3 0 &combiner 25 3>,
+					<0x4 0 &gic 0 120 0>,
+					<0x5 0 &gic 0 121 0>;
+		};
+	};
+
+	pmu {
+		compatible = "arm,cortex-a15-pmu";
+		interrupt-parent = <&combiner>;
+		interrupts = <1 2>, <22 4>;
+	};
+
+	pinctrl_0: pinctrl@11400000 {
+		compatible = "samsung,exynos5250-pinctrl";
+		reg = <0x11400000 0x1000>;
+		interrupts = <0 46 0>;
+
+		wakup_eint: wakeup-interrupt-controller {
+			compatible = "samsung,exynos4210-wakeup-eint";
+			interrupt-parent = <&gic>;
+			interrupts = <0 32 0>;
+		};
+	};
+
+	pinctrl_1: pinctrl@13400000 {
+		compatible = "samsung,exynos5250-pinctrl";
+		reg = <0x13400000 0x1000>;
+		interrupts = <0 45 0>;
+	};
+
+	pinctrl_2: pinctrl@10d10000 {
+		compatible = "samsung,exynos5250-pinctrl";
+		reg = <0x10d10000 0x1000>;
+		interrupts = <0 50 0>;
+	};
+
+	pinctrl_3: pinctrl@03680000 {
+		compatible = "samsung,exynos5250-pinctrl";
+		reg = <0x0368000 0x1000>;
+		interrupts = <0 47 0>;
+	};
+
 	watchdog {
 		compatible = "samsung,s3c2410-wdt";
 		reg = <0x101D0000 0x100>;
 		interrupts = <0 42 0>;
+		clocks = <&clock 336>;
+		clock-names = "watchdog";
 	};
 
 	codec@11000000 {
 		compatible = "samsung,mfc-v6";
 		reg = <0x11000000 0x10000>;
 		interrupts = <0 96 0>;
+		samsung,power-domain = <&pd_mfc>;
 	};
 
 	rtc {
 		compatible = "samsung,s3c6410-rtc";
 		reg = <0x101E0000 0x100>;
 		interrupts = <0 43 0>, <0 44 0>;
+		clocks = <&clock 337>;
+		clock-names = "rtc";
 	};
 
 	tmu@10060000 {
 		compatible = "samsung,exynos5250-tmu";
 		reg = <0x10060000 0x100>;
 		interrupts = <0 65 0>;
+		clocks = <&clock 338>;
+		clock-names = "tmu_apbif";
 	};
 
 	serial@12C00000 {
 		compatible = "samsung,exynos4210-uart";
 		reg = <0x12C00000 0x100>;
 		interrupts = <0 51 0>;
+		clocks = <&clock 289>, <&clock 146>;
+		clock-names = "uart", "clk_uart_baud0";
 	};
 
 	serial@12C10000 {
 		compatible = "samsung,exynos4210-uart";
 		reg = <0x12C10000 0x100>;
 		interrupts = <0 52 0>;
+		clocks = <&clock 290>, <&clock 147>;
+		clock-names = "uart", "clk_uart_baud0";
 	};
 
 	serial@12C20000 {
 		compatible = "samsung,exynos4210-uart";
 		reg = <0x12C20000 0x100>;
 		interrupts = <0 53 0>;
+		clocks = <&clock 291>, <&clock 148>;
+		clock-names = "uart", "clk_uart_baud0";
 	};
 
 	serial@12C30000 {
 		compatible = "samsung,exynos4210-uart";
 		reg = <0x12C30000 0x100>;
 		interrupts = <0 54 0>;
+		clocks = <&clock 292>, <&clock 149>;
+		clock-names = "uart", "clk_uart_baud0";
 	};
 
 	sata@122F0000 {
 		compatible = "samsung,exynos5-sata-ahci";
 		reg = <0x122F0000 0x1ff>;
 		interrupts = <0 115 0>;
+		clocks = <&clock 277>, <&clock 143>;
+		clock-names = "sata", "sclk_sata";
 	};
 
 	sata-phy@12170000 {
@@ -134,6 +244,10 @@
 		interrupts = <0 56 0>;
 		#address-cells = <1>;
 		#size-cells = <0>;
+		clocks = <&clock 294>;
+		clock-names = "i2c";
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c0_bus>;
 	};
 
 	i2c_1: i2c@12C70000 {
@@ -142,6 +256,10 @@
 		interrupts = <0 57 0>;
 		#address-cells = <1>;
 		#size-cells = <0>;
+		clocks = <&clock 295>;
+		clock-names = "i2c";
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c1_bus>;
 	};
 
 	i2c_2: i2c@12C80000 {
@@ -150,6 +268,10 @@
 		interrupts = <0 58 0>;
 		#address-cells = <1>;
 		#size-cells = <0>;
+		clocks = <&clock 296>;
+		clock-names = "i2c";
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c2_bus>;
 	};
 
 	i2c_3: i2c@12C90000 {
@@ -158,6 +280,10 @@
 		interrupts = <0 59 0>;
 		#address-cells = <1>;
 		#size-cells = <0>;
+		clocks = <&clock 297>;
+		clock-names = "i2c";
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c3_bus>;
 	};
 
 	i2c_4: i2c@12CA0000 {
@@ -166,6 +292,10 @@
 		interrupts = <0 60 0>;
 		#address-cells = <1>;
 		#size-cells = <0>;
+		clocks = <&clock 298>;
+		clock-names = "i2c";
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c4_bus>;
 	};
 
 	i2c_5: i2c@12CB0000 {
@@ -174,6 +304,10 @@
 		interrupts = <0 61 0>;
 		#address-cells = <1>;
 		#size-cells = <0>;
+		clocks = <&clock 299>;
+		clock-names = "i2c";
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c5_bus>;
 	};
 
 	i2c_6: i2c@12CC0000 {
@@ -182,6 +316,10 @@
 		interrupts = <0 62 0>;
 		#address-cells = <1>;
 		#size-cells = <0>;
+		clocks = <&clock 300>;
+		clock-names = "i2c";
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c6_bus>;
 	};
 
 	i2c_7: i2c@12CD0000 {
@@ -190,6 +328,10 @@
 		interrupts = <0 63 0>;
 		#address-cells = <1>;
 		#size-cells = <0>;
+		clocks = <&clock 301>;
+		clock-names = "i2c";
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c7_bus>;
 	};
 
 	i2c_8: i2c@12CE0000 {
@@ -198,6 +340,8 @@
 		interrupts = <0 64 0>;
 		#address-cells = <1>;
 		#size-cells = <0>;
+		clocks = <&clock 302>;
+		clock-names = "i2c";
 	};
 
 	i2c@121D0000 {
@@ -205,6 +349,8 @@
                 reg = <0x121D0000 0x100>;
                 #address-cells = <1>;
                 #size-cells = <0>;
+		clocks = <&clock 288>;
+		clock-names = "i2c";
 	};
 
 	spi_0: spi@12d20000 {
@@ -216,6 +362,10 @@
 		dma-names = "tx", "rx";
 		#address-cells = <1>;
 		#size-cells = <0>;
+		clocks = <&clock 304>, <&clock 154>;
+		clock-names = "spi", "spi_busclk0";
+		pinctrl-names = "default";
+		pinctrl-0 = <&spi0_bus>;
 	};
 
 	spi_1: spi@12d30000 {
@@ -227,6 +377,10 @@
 		dma-names = "tx", "rx";
 		#address-cells = <1>;
 		#size-cells = <0>;
+		clocks = <&clock 305>, <&clock 155>;
+		clock-names = "spi", "spi_busclk0";
+		pinctrl-names = "default";
+		pinctrl-0 = <&spi1_bus>;
 	};
 
 	spi_2: spi@12d40000 {
@@ -238,6 +392,10 @@
 		dma-names = "tx", "rx";
 		#address-cells = <1>;
 		#size-cells = <0>;
+		clocks = <&clock 306>, <&clock 156>;
+		clock-names = "spi", "spi_busclk0";
+		pinctrl-names = "default";
+		pinctrl-0 = <&spi2_bus>;
 	};
 
 	dwmmc_0: dwmmc0@12200000 {
@@ -246,6 +404,8 @@
 		interrupts = <0 75 0>;
 		#address-cells = <1>;
 		#size-cells = <0>;
+		clocks = <&clock 280>, <&clock 139>;
+		clock-names = "biu", "ciu";
 	};
 
 	dwmmc_1: dwmmc1@12210000 {
@@ -254,6 +414,8 @@
 		interrupts = <0 76 0>;
 		#address-cells = <1>;
 		#size-cells = <0>;
+		clocks = <&clock 281>, <&clock 140>;
+		clock-names = "biu", "ciu";
 	};
 
 	dwmmc_2: dwmmc2@12220000 {
@@ -262,6 +424,8 @@
 		interrupts = <0 77 0>;
 		#address-cells = <1>;
 		#size-cells = <0>;
+		clocks = <&clock 282>, <&clock 141>;
+		clock-names = "biu", "ciu";
 	};
 
 	dwmmc_3: dwmmc3@12230000 {
@@ -270,6 +434,8 @@
 		interrupts = <0 78 0>;
 		#address-cells = <1>;
 		#size-cells = <0>;
+		clocks = <&clock 283>, <&clock 142>;
+		clock-names = "biu", "ciu";
 	};
 
 	i2s0: i2s@03830000 {
@@ -283,6 +449,8 @@
 		samsung,supports-rstclr;
 		samsung,supports-secdai;
 		samsung,idma-addr = <0x03000000>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2s0_bus>;
 	};
 
 	i2s1: i2s@12D60000 {
@@ -291,6 +459,8 @@
 		dmas = <&pdma1 12
 			&pdma1 11>;
 		dma-names = "tx", "rx";
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2s1_bus>;
 	};
 
 	i2s2: i2s@12D70000 {
@@ -299,6 +469,26 @@
 		dmas = <&pdma0 12
 			&pdma0 11>;
 		dma-names = "tx", "rx";
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2s2_bus>;
+	};
+
+	usb@12110000 {
+		compatible = "samsung,exynos4210-ehci";
+		reg = <0x12110000 0x100>;
+		interrupts = <0 71 0>;
+
+		clocks = <&clock 285>;
+		clock-names = "usbhost";
+	};
+
+	usb@12120000 {
+		compatible = "samsung,exynos4210-ohci";
+		reg = <0x12120000 0x100>;
+		interrupts = <0 71 0>;
+
+		clocks = <&clock 285>;
+		clock-names = "usbhost";
 	};
 
 	amba {
@@ -312,6 +502,8 @@
 			compatible = "arm,pl330", "arm,primecell";
 			reg = <0x121A0000 0x1000>;
 			interrupts = <0 34 0>;
+			clocks = <&clock 275>;
+			clock-names = "apb_pclk";
 			#dma-cells = <1>;
 			#dma-channels = <8>;
 			#dma-requests = <32>;
@@ -321,6 +513,8 @@
 			compatible = "arm,pl330", "arm,primecell";
 			reg = <0x121B0000 0x1000>;
 			interrupts = <0 35 0>;
+			clocks = <&clock 276>;
+			clock-names = "apb_pclk";
 			#dma-cells = <1>;
 			#dma-channels = <8>;
 			#dma-requests = <32>;
@@ -330,6 +524,8 @@
 			compatible = "arm,pl330", "arm,primecell";
 			reg = <0x10800000 0x1000>;
 			interrupts = <0 33 0>;
+			clocks = <&clock 271>;
+			clock-names = "apb_pclk";
 			#dma-cells = <1>;
 			#dma-channels = <8>;
 			#dma-requests = <1>;
@@ -339,287 +535,58 @@
 			compatible = "arm,pl330", "arm,primecell";
 			reg = <0x11C10000 0x1000>;
 			interrupts = <0 124 0>;
+			clocks = <&clock 271>;
+			clock-names = "apb_pclk";
 			#dma-cells = <1>;
 			#dma-channels = <8>;
 			#dma-requests = <1>;
 		};
 	};
 
-	gpio-controllers {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		gpio-controller;
-		ranges;
-
-		gpa0: gpio-controller@11400000 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x11400000 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpa1: gpio-controller@11400020 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x11400020 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpa2: gpio-controller@11400040 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x11400040 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpb0: gpio-controller@11400060 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x11400060 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpb1: gpio-controller@11400080 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x11400080 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpb2: gpio-controller@114000A0 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x114000A0 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpb3: gpio-controller@114000C0 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x114000C0 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpc0: gpio-controller@114000E0 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x114000E0 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpc1: gpio-controller@11400100 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x11400100 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpc2: gpio-controller@11400120 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x11400120 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpc3: gpio-controller@11400140 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x11400140 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpc4: gpio-controller@114002E0 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x114002E0 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpd0: gpio-controller@11400160 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x11400160 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpd1: gpio-controller@11400180 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x11400180 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpy0: gpio-controller@114001A0 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x114001A0 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpy1: gpio-controller@114001C0 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x114001C0 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpy2: gpio-controller@114001E0 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x114001E0 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpy3: gpio-controller@11400200 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x11400200 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpy4: gpio-controller@11400220 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x11400220 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpy5: gpio-controller@11400240 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x11400240 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpy6: gpio-controller@11400260 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x11400260 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpx0: gpio-controller@11400C00 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x11400C00 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpx1: gpio-controller@11400C20 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x11400C20 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpx2: gpio-controller@11400C40 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x11400C40 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpx3: gpio-controller@11400C60 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x11400C60 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpe0: gpio-controller@13400000 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x13400000 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpe1: gpio-controller@13400020 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x13400020 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpf0: gpio-controller@13400040 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x13400040 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpf1: gpio-controller@13400060 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x13400060 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpg0: gpio-controller@13400080 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x13400080 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpg1: gpio-controller@134000A0 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x134000A0 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpg2: gpio-controller@134000C0 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x134000C0 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gph0: gpio-controller@134000E0 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x134000E0 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gph1: gpio-controller@13400100 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x13400100 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpv0: gpio-controller@10D10000 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x10D10000 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpv1: gpio-controller@10D10020 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x10D10020 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpv2: gpio-controller@10D10040 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x10D10060 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpv3: gpio-controller@10D10060 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x10D10080 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpv4: gpio-controller@10D10080 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x10D100C0 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpz: gpio-controller@03860000 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x03860000 0x20>;
-			#gpio-cells = <4>;
-		};
-	};
-
 	gsc_0:  gsc@0x13e00000 {
 		compatible = "samsung,exynos5-gsc";
 		reg = <0x13e00000 0x1000>;
 		interrupts = <0 85 0>;
+		samsung,power-domain = <&pd_gsc>;
+		clocks = <&clock 256>;
+		clock-names = "gscl";
 	};
 
 	gsc_1:  gsc@0x13e10000 {
 		compatible = "samsung,exynos5-gsc";
 		reg = <0x13e10000 0x1000>;
 		interrupts = <0 86 0>;
+		samsung,power-domain = <&pd_gsc>;
+		clocks = <&clock 257>;
+		clock-names = "gscl";
 	};
 
 	gsc_2:  gsc@0x13e20000 {
 		compatible = "samsung,exynos5-gsc";
 		reg = <0x13e20000 0x1000>;
 		interrupts = <0 87 0>;
+		samsung,power-domain = <&pd_gsc>;
+		clocks = <&clock 258>;
+		clock-names = "gscl";
 	};
 
 	gsc_3:  gsc@0x13e30000 {
 		compatible = "samsung,exynos5-gsc";
 		reg = <0x13e30000 0x1000>;
 		interrupts = <0 88 0>;
+		samsung,power-domain = <&pd_gsc>;
+		clocks = <&clock 259>;
+		clock-names = "gscl";
 	};
 
 	hdmi {
 		compatible = "samsung,exynos5-hdmi";
 		reg = <0x14530000 0x70000>;
 		interrupts = <0 95 0>;
+		clocks = <&clock 333>, <&clock 136>, <&clock 137>,
+				<&clock 333>, <&clock 333>;
+		clock-names = "hdmi", "sclk_hdmi", "sclk_pixel",
+				"sclk_hdmiphy", "hdmiphy";
 	};
 
 	mixer {
@@ -627,4 +594,28 @@
 		reg = <0x14450000 0x10000>;
 		interrupts = <0 94 0>;
 	};
+
+	dp-controller {
+		compatible = "samsung,exynos5-dp";
+		reg = <0x145b0000 0x1000>;
+		interrupts = <10 3>;
+		interrupt-parent = <&combiner>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		dptx-phy {
+			reg = <0x10040720>;
+			samsung,enable-mask = <1>;
+		};
+	};
+
+	fimd {
+		compatible = "samsung,exynos5250-fimd";
+		interrupt-parent = <&combiner>;
+		reg = <0x14400000 0x40000>;
+		interrupt-names = "fifo", "vsync", "lcd_sys";
+		interrupts = <18 4>, <18 5>, <18 6>;
+		clocks = <&clock 133>, <&clock 339>;
+		clock-names = "sclk_fimd", "fimd";
+	};
 };
diff --git a/arch/arm/boot/dts/exynos5440-ssdk5440.dts b/arch/arm/boot/dts/exynos5440-ssdk5440.dts
index 81e2c96..a21eb4c 100644
--- a/arch/arm/boot/dts/exynos5440-ssdk5440.dts
+++ b/arch/arm/boot/dts/exynos5440-ssdk5440.dts
@@ -28,19 +28,10 @@
 		status = "disabled";
 	};
 
-	i2c@F0000 {
-		status = "disabled";
-	};
-
-	i2c@100000 {
-		status = "disabled";
-	};
-
-	watchdog {
-		status = "disabled";
-	};
-
-	rtc {
-		status = "disabled";
+	fixed-rate-clocks {
+		xtal {
+			compatible = "samsung,clock-xtal";
+			clock-frequency = <50000000>;
+		};
 	};
 };
diff --git a/arch/arm/boot/dts/exynos5440.dtsi b/arch/arm/boot/dts/exynos5440.dtsi
index 9a99755..25c6134 100644
--- a/arch/arm/boot/dts/exynos5440.dtsi
+++ b/arch/arm/boot/dts/exynos5440.dtsi
@@ -16,63 +16,69 @@
 
 	interrupt-parent = <&gic>;
 
+	clock: clock-controller@0x160000 {
+		compatible = "samsung,exynos5440-clock";
+		reg = <0x160000 0x1000>;
+		#clock-cells = <1>;
+	};
+
 	gic:interrupt-controller@2E0000 {
 		compatible = "arm,cortex-a15-gic";
 		#interrupt-cells = <3>;
 		interrupt-controller;
-		reg = <0x2E1000 0x1000>, <0x2E2000 0x1000>;
+		reg =	<0x2E1000 0x1000>,
+			<0x2E2000 0x1000>,
+			<0x2E4000 0x2000>,
+			<0x2E6000 0x2000>;
+		interrupts = <1 9 0xf04>;
 	};
 
 	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
 		cpu@0 {
 			compatible = "arm,cortex-a15";
-			timer {
-				compatible = "arm,armv7-timer";
-				interrupts = <1 13 0xf08>;
-				clock-frequency = <1000000>;
-			};
+			reg = <0>;
 		};
 		cpu@1 {
 			compatible = "arm,cortex-a15";
-			timer {
-				compatible = "arm,armv7-timer";
-				interrupts = <1 14 0xf08>;
-				clock-frequency = <1000000>;
-			};
+			reg = <1>;
 		};
 		cpu@2 {
 			compatible = "arm,cortex-a15";
-			timer {
-				compatible = "arm,armv7-timer";
-				interrupts = <1 14 0xf08>;
-				clock-frequency = <1000000>;
-			};
+			reg = <2>;
 		};
 		cpu@3 {
 			compatible = "arm,cortex-a15";
-			timer {
-				compatible = "arm,armv7-timer";
-				interrupts = <1 14 0xf08>;
-				clock-frequency = <1000000>;
-			};
+			reg = <3>;
 		};
 	};
 
-	common {
-		compatible = "samsung,exynos5440";
-
+	timer {
+		compatible = "arm,cortex-a15-timer",
+			     "arm,armv7-timer";
+		interrupts = <1 13 0xf08>,
+			     <1 14 0xf08>,
+			     <1 11 0xf08>,
+			     <1 10 0xf08>;
+		clock-frequency = <50000000>;
 	};
 
 	serial@B0000 {
 		compatible = "samsung,exynos4210-uart";
 		reg = <0xB0000 0x1000>;
 		interrupts = <0 2 0>;
+		clocks = <&clock 21>, <&clock 21>;
+		clock-names = "uart", "clk_uart_baud0";
 	};
 
 	serial@C0000 {
 		compatible = "samsung,exynos4210-uart";
 		reg = <0xC0000 0x1000>;
 		interrupts = <0 3 0>;
+		clocks = <&clock 21>, <&clock 21>;
+		clock-names = "uart", "clk_uart_baud0";
 	};
 
 	spi {
@@ -83,6 +89,8 @@
 		rx-dma-channel = <&pdma0 4>; /* preliminary */
 		#address-cells = <1>;
 		#size-cells = <0>;
+		clocks = <&clock 21>, <&clock 16>;
+		clock-names = "spi", "spi_busclk0";
 	};
 
 	pinctrl {
@@ -110,25 +118,31 @@
 	};
 
 	i2c@F0000 {
-		compatible = "samsung,s3c2440-i2c";
+		compatible = "samsung,exynos5440-i2c";
 		reg = <0xF0000 0x1000>;
 		interrupts = <0 5 0>;
 		#address-cells = <1>;
 		#size-cells = <0>;
+		clocks = <&clock 21>;
+		clock-names = "i2c";
 	};
 
 	i2c@100000 {
-		compatible = "samsung,s3c2440-i2c";
+		compatible = "samsung,exynos5440-i2c";
 		reg = <0x100000 0x1000>;
 		interrupts = <0 6 0>;
 		#address-cells = <1>;
 		#size-cells = <0>;
+		clocks = <&clock 21>;
+		clock-names = "i2c";
 	};
 
 	watchdog {
 		compatible = "samsung,s3c2410-wdt";
 		reg = <0x110000 0x1000>;
 		interrupts = <0 1 0>;
+		clocks = <&clock 21>;
+		clock-names = "watchdog";
 	};
 
 	amba {
@@ -142,6 +156,8 @@
 			compatible = "arm,pl330", "arm,primecell";
 			reg = <0x120000 0x1000>;
 			interrupts = <0 34 0>;
+			clocks = <&clock 21>;
+			clock-names = "apb_pclk";
 			#dma-cells = <1>;
 			#dma-channels = <8>;
 			#dma-requests = <32>;
@@ -151,6 +167,8 @@
 			compatible = "arm,pl330", "arm,primecell";
 			reg = <0x121000 0x1000>;
 			interrupts = <0 35 0>;
+			clocks = <&clock 21>;
+			clock-names = "apb_pclk";
 			#dma-cells = <1>;
 			#dma-channels = <8>;
 			#dma-requests = <32>;
@@ -161,5 +179,7 @@
 		compatible = "samsung,s3c6410-rtc";
 		reg = <0x130000 0x1000>;
 		interrupts = <0 17 0>, <0 16 0>;
+		clocks = <&clock 21>;
+		clock-names = "rtc";
 	};
 };
diff --git a/arch/arm/boot/dts/href.dtsi b/arch/arm/boot/dts/href.dtsi
index 379128e..c0bc426 100644
--- a/arch/arm/boot/dts/href.dtsi
+++ b/arch/arm/boot/dts/href.dtsi
@@ -87,6 +87,7 @@
 			mmc-cap-sd-highspeed;
 			mmc-cap-mmc-highspeed;
 			vmmc-supply = <&ab8500_ldo_aux3_reg>;
+			vqmmc-supply = <&vmmci>;
 
 			cd-gpios  = <&tc3589x_gpio 3 0x4>;
 
diff --git a/arch/arm/boot/dts/hrefprev60.dts b/arch/arm/boot/dts/hrefprev60.dts
index eec29c4..c2d2748 100644
--- a/arch/arm/boot/dts/hrefprev60.dts
+++ b/arch/arm/boot/dts/hrefprev60.dts
@@ -25,6 +25,14 @@
 	};
 
 	soc-u9500 {
+		prcmu@80157000 {
+			ab8500@5 {
+				ab8500-gpio {
+					compatible = "stericsson,ab8500-gpio";
+				};
+			};
+		};
+
 		i2c@80004000 {
 			tps61052@33 {
 				compatible = "tps61052";
@@ -40,7 +48,7 @@
 
 		vmmci: regulator-gpio {
 			gpios = <&tc3589x_gpio 18 0x4>;
-			gpio-enable = <&tc3589x_gpio 17 0x4>;
+			enable-gpio = <&tc3589x_gpio 17 0x4>;
 
 			status = "okay";
 		};
diff --git a/arch/arm/boot/dts/imx23-evk.dts b/arch/arm/boot/dts/imx23-evk.dts
index 035c13f..7880e17 100644
--- a/arch/arm/boot/dts/imx23-evk.dts
+++ b/arch/arm/boot/dts/imx23-evk.dts
@@ -60,7 +60,32 @@
 				pinctrl-names = "default";
 				pinctrl-0 = <&lcdif_24bit_pins_a>;
 				panel-enable-gpios = <&gpio1 18 0>;
+				display = <&display>;
 				status = "okay";
+
+				display: display {
+					bits-per-pixel = <32>;
+					bus-width = <24>;
+
+					display-timings {
+						native-mode = <&timing0>;
+						timing0: timing0 {
+							clock-frequency = <9200000>;
+							hactive = <480>;
+							vactive = <272>;
+							hback-porch = <15>;
+							hfront-porch = <8>;
+							vback-porch = <12>;
+							vfront-porch = <4>;
+							hsync-len = <1>;
+							vsync-len = <1>;
+							hsync-active = <0>;
+							vsync-active = <0>;
+							de-active = <1>;
+							pixelclk-active = <0>;
+						};
+					};
+				};
 			};
 		};
 
diff --git a/arch/arm/boot/dts/imx23.dtsi b/arch/arm/boot/dts/imx23.dtsi
index 56afcf4..73fd7d0 100644
--- a/arch/arm/boot/dts/imx23.dtsi
+++ b/arch/arm/boot/dts/imx23.dtsi
@@ -49,9 +49,15 @@
 				reg = <0x80000000 0x2000>;
 			};
 
-			dma-apbh@80004000 {
+			dma_apbh: dma-apbh@80004000 {
 				compatible = "fsl,imx23-dma-apbh";
 				reg = <0x80004000 0x2000>;
+				interrupts = <0 14 20 0
+					      13 13 13 13>;
+				interrupt-names = "empty", "ssp0", "ssp1", "empty",
+						  "gpmi0", "gpmi1", "gpmi2", "gpmi3";
+				#dma-cells = <1>;
+				dma-channels = <8>;
 				clocks = <&clks 15>;
 			};
 
@@ -70,6 +76,8 @@
 				interrupt-names = "gpmi-dma", "bch";
 				clocks = <&clks 34>;
 				clock-names = "gpmi_io";
+				dmas = <&dma_apbh 4>;
+				dma-names = "rx-tx";
 				fsl,gpmi-dma-channel = <4>;
 				status = "disabled";
 			};
@@ -78,6 +86,8 @@
 				reg = <0x80010000 0x2000>;
 				interrupts = <15 14>;
 				clocks = <&clks 33>;
+				dmas = <&dma_apbh 1>;
+				dma-names = "rx-tx";
 				fsl,ssp-dma-channel = <1>;
 				status = "disabled";
 			};
@@ -295,6 +305,7 @@
 			};
 
 			digctl@8001c000 {
+				compatible = "fsl,imx23-digctl";
 				reg = <0x8001c000 2000>;
 				status = "disabled";
 			};
@@ -304,9 +315,19 @@
 				status = "disabled";
 			};
 
-			dma-apbx@80024000 {
+			dma_apbx: dma-apbx@80024000 {
 				compatible = "fsl,imx23-dma-apbx";
 				reg = <0x80024000 0x2000>;
+				interrupts = <7 5 9 26
+					      19 0 25 23
+					      60 58 9 0
+					      0 0 0 0>;
+				interrupt-names = "audio-adc", "audio-dac", "spdif-tx", "i2c",
+						  "saif0", "empty", "auart0-rx", "auart0-tx",
+						  "auart1-rx", "auart1-tx", "saif1", "empty",
+						  "empty", "empty", "empty", "empty";
+				#dma-cells = <1>;
+				dma-channels = <16>;
 				clocks = <&clks 16>;
 			};
 
@@ -321,6 +342,7 @@
 			};
 
 			ocotp@8002c000 {
+				compatible = "fsl,ocotp";
 				reg = <0x8002c000 0x2000>;
 				status = "disabled";
 			};
@@ -342,6 +364,8 @@
 				reg = <0x80034000 0x2000>;
 				interrupts = <2 20>;
 				clocks = <&clks 33>;
+				dmas = <&dma_apbh 2>;
+				dma-names = "rx-tx";
 				fsl,ssp-dma-channel = <2>;
 				status = "disabled";
 			};
@@ -360,13 +384,15 @@
 			ranges;
 
 			clks: clkctrl@80040000 {
-				compatible = "fsl,imx23-clkctrl";
+				compatible = "fsl,imx23-clkctrl", "fsl,clkctrl";
 				reg = <0x80040000 0x2000>;
 				#clock-cells = <1>;
 			};
 
 			saif0: saif@80042000 {
 				reg = <0x80042000 0x2000>;
+				dmas = <&dma_apbx 4>;
+				dma-names = "rx-tx";
 				status = "disabled";
 			};
 
@@ -377,16 +403,22 @@
 
 			saif1: saif@80046000 {
 				reg = <0x80046000 0x2000>;
+				dmas = <&dma_apbx 10>;
+				dma-names = "rx-tx";
 				status = "disabled";
 			};
 
 			audio-out@80048000 {
 				reg = <0x80048000 0x2000>;
+				dmas = <&dma_apbx 1>;
+				dma-names = "tx";
 				status = "disabled";
 			};
 
 			audio-in@8004c000 {
 				reg = <0x8004c000 0x2000>;
+				dmas = <&dma_apbx 0>;
+				dma-names = "rx";
 				status = "disabled";
 			};
 
@@ -399,11 +431,15 @@
 
 			spdif@80054000 {
 				reg = <0x80054000 2000>;
+				dmas = <&dma_apbx 2>;
+				dma-names = "tx";
 				status = "disabled";
 			};
 
 			i2c@80058000 {
 				reg = <0x80058000 0x2000>;
+				dmas = <&dma_apbx 3>;
+				dma-names = "rx-tx";
 				status = "disabled";
 			};
 
@@ -426,6 +462,7 @@
 				compatible = "fsl,imx23-timrot", "fsl,timrot";
 				reg = <0x80068000 0x2000>;
 				interrupts = <28 29 30 31>;
+				clocks = <&clks 28>;
 			};
 
 			auart0: serial@8006c000 {
@@ -433,6 +470,8 @@
 				reg = <0x8006c000 0x2000>;
 				interrupts = <24 25 23>;
 				clocks = <&clks 32>;
+				dmas = <&dma_apbx 6>, <&dma_apbx 7>;
+				dma-names = "rx", "tx";
 				status = "disabled";
 			};
 
@@ -441,6 +480,8 @@
 				reg = <0x8006e000 0x2000>;
 				interrupts = <59 60 58>;
 				clocks = <&clks 32>;
+				dmas = <&dma_apbx 8>, <&dma_apbx 9>;
+				dma-names = "rx", "tx";
 				status = "disabled";
 			};
 
diff --git a/arch/arm/boot/dts/imx25-karo-tx25.dts b/arch/arm/boot/dts/imx25-karo-tx25.dts
deleted file mode 100644
index 1a9d049..0000000
--- a/arch/arm/boot/dts/imx25-karo-tx25.dts
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 2012 Sascha Hauer, Pengutronix
- *
- * 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
- */
-
-/dts-v1/;
-/include/ "imx25.dtsi"
-
-/ {
-	model = "Ka-Ro TX25";
-	compatible = "karo,imx25-tx25", "fsl,imx25";
-
-	memory {
-		reg = <0x80000000 0x02000000 0x90000000 0x02000000>;
-	};
-};
-
-&uart1 {
-	status = "okay";
-};
-
-&fec {
-	phy-mode = "rmii";
-	status = "okay";
-};
-
-&nfc {
-	nand-on-flash-bbt;
-	status = "okay";
-};
diff --git a/arch/arm/boot/dts/imx25-karo-tx25.dtsp b/arch/arm/boot/dts/imx25-karo-tx25.dtsp
new file mode 100644
index 0000000..3dbe775
--- /dev/null
+++ b/arch/arm/boot/dts/imx25-karo-tx25.dtsp
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2012 Sascha Hauer, Pengutronix
+ *
+ * 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
+ */
+
+/dts-v1/;
+#include "imx25.dtsip"
+
+/ {
+	model = "Ka-Ro TX25";
+	compatible = "karo,imx25-tx25", "fsl,imx25";
+
+	memory {
+		reg = <0x80000000 0x02000000 0x90000000 0x02000000>;
+	};
+};
+
+&uart1 {
+	status = "okay";
+};
+
+&fec {
+	phy-mode = "rmii";
+	status = "okay";
+};
+
+&nfc {
+	nand-on-flash-bbt;
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx25-pdk.dts b/arch/arm/boot/dts/imx25-pdk.dts
deleted file mode 100644
index a02a860..0000000
--- a/arch/arm/boot/dts/imx25-pdk.dts
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 2013 Freescale Semiconductor, Inc.
- *
- * 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
- */
-
-/dts-v1/;
-/include/ "imx25.dtsi"
-
-/ {
-	model = "Freescale i.MX25 Product Development Kit";
-	compatible = "fsl,imx25-pdk", "fsl,imx25";
-
-	memory {
-		reg = <0x80000000 0x4000000>;
-	};
-};
-
-&uart1 {
-	status = "okay";
-};
-
-&fec {
-	phy-mode = "rmii";
-	status = "okay";
-};
-
-&nfc {
-	nand-on-flash-bbt;
-	status = "okay";
-};
diff --git a/arch/arm/boot/dts/imx25-pdk.dtsp b/arch/arm/boot/dts/imx25-pdk.dtsp
new file mode 100644
index 0000000..8064b76
--- /dev/null
+++ b/arch/arm/boot/dts/imx25-pdk.dtsp
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * 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
+ */
+
+/dts-v1/;
+#include "imx25.dtsip"
+
+/ {
+	model = "Freescale i.MX25 Product Development Kit";
+	compatible = "fsl,imx25-pdk", "fsl,imx25";
+
+	memory {
+		reg = <0x80000000 0x4000000>;
+	};
+};
+
+&uart1 {
+	status = "okay";
+};
+
+&fec {
+	phy-mode = "rmii";
+	status = "okay";
+};
+
+&nfc {
+	nand-on-flash-bbt;
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx25.dtsi b/arch/arm/boot/dts/imx25.dtsi
deleted file mode 100644
index 94f3305..0000000
--- a/arch/arm/boot/dts/imx25.dtsi
+++ /dev/null
@@ -1,515 +0,0 @@
-/*
- * Copyright 2012 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>
- *
- * 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/ "skeleton.dtsi"
-
-/ {
-	aliases {
-		serial0 = &uart1;
-		serial1 = &uart2;
-		serial2 = &uart3;
-		serial3 = &uart4;
-		serial4 = &uart5;
-		gpio0 = &gpio1;
-		gpio1 = &gpio2;
-		gpio2 = &gpio3;
-		gpio3 = &gpio4;
-		usb0 = &usbotg;
-		usb1 = &usbhost1;
-	};
-
-	asic: asic-interrupt-controller@68000000 {
-		compatible = "fsl,imx25-asic", "fsl,avic";
-		interrupt-controller;
-		#interrupt-cells = <1>;
-		reg = <0x68000000 0x8000000>;
-	};
-
-	clocks {
-		#address-cells = <1>;
-		#size-cells = <0>;
-
-		osc {
-			compatible = "fsl,imx-osc", "fixed-clock";
-			clock-frequency = <24000000>;
-		};
-	};
-
-	soc {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		compatible = "simple-bus";
-		interrupt-parent = <&asic>;
-		ranges;
-
-		aips@43f00000 { /* AIPS1 */
-			compatible = "fsl,aips-bus", "simple-bus";
-			#address-cells = <1>;
-			#size-cells = <1>;
-			reg = <0x43f00000 0x100000>;
-			ranges;
-
-			i2c1: i2c@43f80000 {
-				#address-cells = <1>;
-				#size-cells = <0>;
-				compatible = "fsl,imx25-i2c", "fsl,imx21-i2c";
-				reg = <0x43f80000 0x4000>;
-				clocks = <&clks 48>;
-				clock-names = "";
-				interrupts = <3>;
-				status = "disabled";
-			};
-
-			i2c3: i2c@43f84000 {
-				#address-cells = <1>;
-				#size-cells = <0>;
-				compatible = "fsl,imx25-i2c", "fsl,imx21-i2c";
-				reg = <0x43f84000 0x4000>;
-				clocks = <&clks 48>;
-				clock-names = "";
-				interrupts = <10>;
-				status = "disabled";
-			};
-
-			can1: can@43f88000 {
-				compatible = "fsl,imx25-flexcan", "fsl,p1010-flexcan";
-				reg = <0x43f88000 0x4000>;
-				interrupts = <43>;
-				clocks = <&clks 75>, <&clks 75>;
-				clock-names = "ipg", "per";
-				status = "disabled";
-			};
-
-			can2: can@43f8c000 {
-				compatible = "fsl,imx25-flexcan", "fsl,p1010-flexcan";
-				reg = <0x43f8c000 0x4000>;
-				interrupts = <44>;
-				clocks = <&clks 76>, <&clks 76>;
-				clock-names = "ipg", "per";
-				status = "disabled";
-			};
-
-			uart1: serial@43f90000 {
-				compatible = "fsl,imx25-uart", "fsl,imx21-uart";
-				reg = <0x43f90000 0x4000>;
-				interrupts = <45>;
-				clocks = <&clks 120>, <&clks 57>;
-				clock-names = "ipg", "per";
-				status = "disabled";
-			};
-
-			uart2: serial@43f94000 {
-				compatible = "fsl,imx25-uart", "fsl,imx21-uart";
-				reg = <0x43f94000 0x4000>;
-				interrupts = <32>;
-				clocks = <&clks 121>, <&clks 57>;
-				clock-names = "ipg", "per";
-				status = "disabled";
-			};
-
-			i2c2: i2c@43f98000 {
-				#address-cells = <1>;
-				#size-cells = <0>;
-				compatible = "fsl,imx25-i2c", "fsl,imx21-i2c";
-				reg = <0x43f98000 0x4000>;
-				clocks = <&clks 48>;
-				clock-names = "";
-				interrupts = <4>;
-				status = "disabled";
-			};
-
-			owire@43f9c000 {
-				#address-cells = <1>;
-				#size-cells = <0>;
-				reg = <0x43f9c000 0x4000>;
-				clocks = <&clks 51>;
-				clock-names = "";
-				interrupts = <2>;
-				status = "disabled";
-			};
-
-			spi1: cspi@43fa4000 {
-				#address-cells = <1>;
-				#size-cells = <0>;
-				compatible = "fsl,imx25-cspi", "fsl,imx35-cspi";
-				reg = <0x43fa4000 0x4000>;
-				clocks = <&clks 62>;
-				clock-names = "ipg";
-				interrupts = <14>;
-				status = "disabled";
-			};
-
-			kpp@43fa8000 {
-				#address-cells = <1>;
-				#size-cells = <0>;
-				reg = <0x43fa8000 0x4000>;
-				clocks = <&clks 102>;
-				clock-names = "";
-				interrupts = <24>;
-				status = "disabled";
-			};
-
-			iomuxc@43fac000{
-				compatible = "fsl,imx25-iomuxc";
-				reg = <0x43fac000 0x4000>;
-			};
-
-			audmux@43fb0000 {
-				compatible = "fsl,imx25-audmux", "fsl,imx31-audmux";
-				reg = <0x43fb0000 0x4000>;
-				status = "disabled";
-			};
-		};
-
-		spba@50000000 {
-			compatible = "fsl,spba-bus", "simple-bus";
-			#address-cells = <1>;
-			#size-cells = <1>;
-			reg = <0x50000000 0x40000>;
-			ranges;
-
-			spi3: cspi@50004000 {
-				#address-cells = <1>;
-				#size-cells = <0>;
-				compatible = "fsl,imx25-cspi", "fsl,imx35-cspi";
-				reg = <0x50004000 0x4000>;
-				interrupts = <0>;
-				clocks = <&clks 80>;
-				clock-names = "ipg";
-				status = "disabled";
-			};
-
-			uart4: serial@50008000 {
-				compatible = "fsl,imx25-uart", "fsl,imx21-uart";
-				reg = <0x50008000 0x4000>;
-				interrupts = <5>;
-				clocks = <&clks 123>, <&clks 57>;
-				clock-names = "ipg", "per";
-				status = "disabled";
-			};
-
-			uart3: serial@5000c000 {
-				compatible = "fsl,imx25-uart", "fsl,imx21-uart";
-				reg = <0x5000c000 0x4000>;
-				interrupts = <18>;
-				clocks = <&clks 122>, <&clks 57>;
-				clock-names = "ipg", "per";
-				status = "disabled";
-			};
-
-			spi2: cspi@50010000 {
-				#address-cells = <1>;
-				#size-cells = <0>;
-				compatible = "fsl,imx25-cspi", "fsl,imx35-cspi";
-				reg = <0x50010000 0x4000>;
-				clocks = <&clks 79>;
-				clock-names = "ipg";
-				interrupts = <13>;
-				status = "disabled";
-			};
-
-			ssi2: ssi@50014000 {
-				compatible = "fsl,imx25-ssi", "fsl,imx21-ssi";
-				reg = <0x50014000 0x4000>;
-				interrupts = <11>;
-				status = "disabled";
-			};
-
-			esai@50018000 {
-				reg = <0x50018000 0x4000>;
-				interrupts = <7>;
-			};
-
-			uart5: serial@5002c000 {
-				compatible = "fsl,imx25-uart", "fsl,imx21-uart";
-				reg = <0x5002c000 0x4000>;
-				interrupts = <40>;
-				clocks = <&clks 124>, <&clks 57>;
-				clock-names = "ipg", "per";
-				status = "disabled";
-			};
-
-			tsc: tsc@50030000 {
-				compatible = "fsl,imx25-adc", "fsl,imx21-tsc";
-				reg = <0x50030000 0x4000>;
-				interrupts = <46>;
-				clocks = <&clks 119>;
-				clock-names = "ipg";
-				status = "disabled";
-			};
-
-			ssi1: ssi@50034000 {
-				compatible = "fsl,imx25-ssi", "fsl,imx21-ssi";
-				reg = <0x50034000 0x4000>;
-				interrupts = <12>;
-				status = "disabled";
-			};
-
-			fec: ethernet@50038000 {
-				compatible = "fsl,imx25-fec";
-				reg = <0x50038000 0x4000>;
-				interrupts = <57>;
-				clocks = <&clks 88>, <&clks 65>;
-				clock-names = "ipg", "ahb";
-				status = "disabled";
-			};
-		};
-
-		aips@53f00000 { /* AIPS2 */
-			compatible = "fsl,aips-bus", "simple-bus";
-			#address-cells = <1>;
-			#size-cells = <1>;
-			reg = <0x53f00000 0x100000>;
-			ranges;
-
-			clks: ccm@53f80000 {
-				compatible = "fsl,imx25-ccm";
-				reg = <0x53f80000 0x4000>;
-				interrupts = <31>;
-				#clock-cells = <1>;
-			};
-
-			gpt4: timer@53f84000 {
-				compatible = "fsl,imx25-gpt", "fsl,imx31-gpt";
-				reg = <0x53f84000 0x4000>;
-				clocks = <&clks 9>, <&clks 45>;
-				clock-names = "ipg", "per";
-				interrupts = <1>;
-			};
-
-			gpt3: timer@53f88000 {
-				compatible = "fsl,imx25-gpt", "fsl,imx31-gpt";
-				reg = <0x53f88000 0x4000>;
-				clocks = <&clks 9>, <&clks 47>;
-				clock-names = "ipg", "per";
-				interrupts = <29>;
-			};
-
-			gpt2: timer@53f8c000 {
-				compatible = "fsl,imx25-gpt", "fsl,imx31-gpt";
-				reg = <0x53f8c000 0x4000>;
-				clocks = <&clks 9>, <&clks 47>;
-				clock-names = "ipg", "per";
-				interrupts = <53>;
-			};
-
-			gpt1: timer@53f90000 {
-				compatible = "fsl,imx25-gpt", "fsl,imx31-gpt";
-				reg = <0x53f90000 0x4000>;
-				clocks = <&clks 9>, <&clks 47>;
-				clock-names = "ipg", "per";
-				interrupts = <54>;
-			};
-
-			epit1: timer@53f94000 {
-				compatible = "fsl,imx25-epit";
-				reg = <0x53f94000 0x4000>;
-				interrupts = <28>;
-			};
-
-			epit2: timer@53f98000 {
-				compatible = "fsl,imx25-epit";
-				reg = <0x53f98000 0x4000>;
-				interrupts = <27>;
-			};
-
-			gpio4: gpio@53f9c000 {
-				compatible = "fsl,imx25-gpio", "fsl,imx35-gpio";
-				reg = <0x53f9c000 0x4000>;
-				interrupts = <23>;
-				gpio-controller;
-				#gpio-cells = <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-			};
-
-			pwm2: pwm@53fa0000 {
-				compatible = "fsl,imx25-pwm", "fsl,imx27-pwm";
-				#pwm-cells = <2>;
-				reg = <0x53fa0000 0x4000>;
-				clocks = <&clks 106>, <&clks 36>;
-				clock-names = "ipg", "per";
-				interrupts = <36>;
-			};
-
-			gpio3: gpio@53fa4000 {
-				compatible = "fsl,imx25-gpio", "fsl,imx35-gpio";
-				reg = <0x53fa4000 0x4000>;
-				interrupts = <16>;
-				gpio-controller;
-				#gpio-cells = <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-			};
-
-			pwm3: pwm@53fa8000 {
-				compatible = "fsl,imx25-pwm", "fsl,imx27-pwm";
-				#pwm-cells = <2>;
-				reg = <0x53fa8000 0x4000>;
-				clocks = <&clks 107>, <&clks 36>;
-				clock-names = "ipg", "per";
-				interrupts = <41>;
-			};
-
-			esdhc1: esdhc@53fb4000 {
-				compatible = "fsl,imx25-esdhc";
-				reg = <0x53fb4000 0x4000>;
-				interrupts = <9>;
-				clocks = <&clks 86>, <&clks 63>, <&clks 45>;
-				clock-names = "ipg", "ahb", "per";
-				status = "disabled";
-			};
-
-			esdhc2: esdhc@53fb8000 {
-				compatible = "fsl,imx25-esdhc";
-				reg = <0x53fb8000 0x4000>;
-				interrupts = <8>;
-				clocks = <&clks 87>, <&clks 64>, <&clks 46>;
-				clock-names = "ipg", "ahb", "per";
-				status = "disabled";
-			};
-
-			lcdc@53fbc000 {
-				reg = <0x53fbc000 0x4000>;
-				interrupts = <39>;
-				clocks = <&clks 103>, <&clks 66>, <&clks 49>;
-				clock-names = "ipg", "ahb", "per";
-				status = "disabled";
-			};
-
-			slcdc@53fc0000 {
-				reg = <0x53fc0000 0x4000>;
-				interrupts = <38>;
-				status = "disabled";
-			};
-
-			pwm4: pwm@53fc8000 {
-				compatible = "fsl,imx25-pwm", "fsl,imx27-pwm";
-				reg = <0x53fc8000 0x4000>;
-				clocks = <&clks 108>, <&clks 36>;
-				clock-names = "ipg", "per";
-				interrupts = <42>;
-			};
-
-			gpio1: gpio@53fcc000 {
-				compatible = "fsl,imx25-gpio", "fsl,imx35-gpio";
-				reg = <0x53fcc000 0x4000>;
-				interrupts = <52>;
-				gpio-controller;
-				#gpio-cells = <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-			};
-
-			gpio2: gpio@53fd0000 {
-				compatible = "fsl,imx25-gpio", "fsl,imx35-gpio";
-				reg = <0x53fd0000 0x4000>;
-				interrupts = <51>;
-				gpio-controller;
-				#gpio-cells = <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-			};
-
-			sdma@53fd4000 {
-				compatible = "fsl,imx25-sdma", "fsl,imx35-sdma";
-				reg = <0x53fd4000 0x4000>;
-				clocks = <&clks 112>, <&clks 68>;
-				clock-names = "ipg", "ahb";
-				interrupts = <34>;
-			};
-
-			wdog@53fdc000 {
-				compatible = "fsl,imx25-wdt", "fsl,imx21-wdt";
-				reg = <0x53fdc000 0x4000>;
-				clocks = <&clks 126>;
-				clock-names = "";
-				interrupts = <55>;
-			};
-
-			pwm1: pwm@53fe0000 {
-				compatible = "fsl,imx25-pwm", "fsl,imx27-pwm";
-				#pwm-cells = <2>;
-				reg = <0x53fe0000 0x4000>;
-				clocks = <&clks 105>, <&clks 36>;
-				clock-names = "ipg", "per";
-				interrupts = <26>;
-			};
-
-			usbphy1: usbphy@1 {
-				compatible = "nop-usbphy";
-				status = "disabled";
-			};
-
-			usbphy2: usbphy@2 {
-				compatible = "nop-usbphy";
-				status = "disabled";
-			};
-
-			usbotg: usb@53ff4000 {
-				compatible = "fsl,imx25-usb", "fsl,imx27-usb";
-				reg = <0x53ff4000 0x0200>;
-				interrupts = <37>;
-				clocks = <&clks 9>, <&clks 70>, <&clks 8>;
-				clock-names = "ipg", "ahb", "per";
-				fsl,usbmisc = <&usbmisc 0>;
-				status = "disabled";
-			};
-
-			usbhost1: usb@53ff4400 {
-				compatible = "fsl,imx25-usb", "fsl,imx27-usb";
-				reg = <0x53ff4400 0x0200>;
-				interrupts = <35>;
-				clocks = <&clks 9>, <&clks 70>, <&clks 8>;
-				clock-names = "ipg", "ahb", "per";
-				fsl,usbmisc = <&usbmisc 1>;
-				status = "disabled";
-			};
-
-			usbmisc: usbmisc@53ff4600 {
-				#index-cells = <1>;
-				compatible = "fsl,imx25-usbmisc";
-				clocks = <&clks 9>, <&clks 70>, <&clks 8>;
-				clock-names = "ipg", "ahb", "per";
-				reg = <0x53ff4600 0x00f>;
-				status = "disabled";
-			};
-
-			dryice@53ffc000 {
-				compatible = "fsl,imx25-dryice", "fsl,imx25-rtc";
-				reg = <0x53ffc000 0x4000>;
-				clocks = <&clks 81>;
-				clock-names = "ipg";
-				interrupts = <25>;
-			};
-		};
-
-		emi@80000000 {
-			compatible = "fsl,emi-bus", "simple-bus";
-			#address-cells = <1>;
-			#size-cells = <1>;
-			reg = <0x80000000 0x3b002000>;
-			ranges;
-
-			nfc: nand@bb000000 {
-				#address-cells = <1>;
-				#size-cells = <1>;
-
-				compatible = "fsl,imx25-nand";
-				reg = <0xbb000000 0x2000>;
-				clocks = <&clks 50>;
-				clock-names = "";
-				interrupts = <33>;
-				status = "disabled";
-			};
-		};
-	};
-};
diff --git a/arch/arm/boot/dts/imx25.dtsip b/arch/arm/boot/dts/imx25.dtsip
new file mode 100644
index 0000000..d2550e0
--- /dev/null
+++ b/arch/arm/boot/dts/imx25.dtsip
@@ -0,0 +1,515 @@
+/*
+ * Copyright 2012 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>
+ *
+ * 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 "skeleton.dtsi"
+
+/ {
+	aliases {
+		serial0 = &uart1;
+		serial1 = &uart2;
+		serial2 = &uart3;
+		serial3 = &uart4;
+		serial4 = &uart5;
+		gpio0 = &gpio1;
+		gpio1 = &gpio2;
+		gpio2 = &gpio3;
+		gpio3 = &gpio4;
+		usb0 = &usbotg;
+		usb1 = &usbhost1;
+	};
+
+	asic: asic-interrupt-controller@68000000 {
+		compatible = "fsl,imx25-asic", "fsl,avic";
+		interrupt-controller;
+		#interrupt-cells = <1>;
+		reg = <0x68000000 0x8000000>;
+	};
+
+	clocks {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		osc {
+			compatible = "fsl,imx-osc", "fixed-clock";
+			clock-frequency = <24000000>;
+		};
+	};
+
+	soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		interrupt-parent = <&asic>;
+		ranges;
+
+		aips@43f00000 { /* AIPS1 */
+			compatible = "fsl,aips-bus", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x43f00000 0x100000>;
+			ranges;
+
+			i2c1: i2c@43f80000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx25-i2c", "fsl,imx21-i2c";
+				reg = <0x43f80000 0x4000>;
+				clocks = <&clks 48>;
+				clock-names = "";
+				interrupts = <3>;
+				status = "disabled";
+			};
+
+			i2c3: i2c@43f84000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx25-i2c", "fsl,imx21-i2c";
+				reg = <0x43f84000 0x4000>;
+				clocks = <&clks 48>;
+				clock-names = "";
+				interrupts = <10>;
+				status = "disabled";
+			};
+
+			can1: can@43f88000 {
+				compatible = "fsl,imx25-flexcan", "fsl,p1010-flexcan";
+				reg = <0x43f88000 0x4000>;
+				interrupts = <43>;
+				clocks = <&clks 75>, <&clks 75>;
+				clock-names = "ipg", "per";
+				status = "disabled";
+			};
+
+			can2: can@43f8c000 {
+				compatible = "fsl,imx25-flexcan", "fsl,p1010-flexcan";
+				reg = <0x43f8c000 0x4000>;
+				interrupts = <44>;
+				clocks = <&clks 76>, <&clks 76>;
+				clock-names = "ipg", "per";
+				status = "disabled";
+			};
+
+			uart1: serial@43f90000 {
+				compatible = "fsl,imx25-uart", "fsl,imx21-uart";
+				reg = <0x43f90000 0x4000>;
+				interrupts = <45>;
+				clocks = <&clks 120>, <&clks 57>;
+				clock-names = "ipg", "per";
+				status = "disabled";
+			};
+
+			uart2: serial@43f94000 {
+				compatible = "fsl,imx25-uart", "fsl,imx21-uart";
+				reg = <0x43f94000 0x4000>;
+				interrupts = <32>;
+				clocks = <&clks 121>, <&clks 57>;
+				clock-names = "ipg", "per";
+				status = "disabled";
+			};
+
+			i2c2: i2c@43f98000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx25-i2c", "fsl,imx21-i2c";
+				reg = <0x43f98000 0x4000>;
+				clocks = <&clks 48>;
+				clock-names = "";
+				interrupts = <4>;
+				status = "disabled";
+			};
+
+			owire@43f9c000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <0x43f9c000 0x4000>;
+				clocks = <&clks 51>;
+				clock-names = "";
+				interrupts = <2>;
+				status = "disabled";
+			};
+
+			spi1: cspi@43fa4000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx25-cspi", "fsl,imx35-cspi";
+				reg = <0x43fa4000 0x4000>;
+				clocks = <&clks 62>;
+				clock-names = "ipg";
+				interrupts = <14>;
+				status = "disabled";
+			};
+
+			kpp@43fa8000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <0x43fa8000 0x4000>;
+				clocks = <&clks 102>;
+				clock-names = "";
+				interrupts = <24>;
+				status = "disabled";
+			};
+
+			iomuxc@43fac000{
+				compatible = "fsl,imx25-iomuxc";
+				reg = <0x43fac000 0x4000>;
+			};
+
+			audmux@43fb0000 {
+				compatible = "fsl,imx25-audmux", "fsl,imx31-audmux";
+				reg = <0x43fb0000 0x4000>;
+				status = "disabled";
+			};
+		};
+
+		spba@50000000 {
+			compatible = "fsl,spba-bus", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x50000000 0x40000>;
+			ranges;
+
+			spi3: cspi@50004000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx25-cspi", "fsl,imx35-cspi";
+				reg = <0x50004000 0x4000>;
+				interrupts = <0>;
+				clocks = <&clks 80>;
+				clock-names = "ipg";
+				status = "disabled";
+			};
+
+			uart4: serial@50008000 {
+				compatible = "fsl,imx25-uart", "fsl,imx21-uart";
+				reg = <0x50008000 0x4000>;
+				interrupts = <5>;
+				clocks = <&clks 123>, <&clks 57>;
+				clock-names = "ipg", "per";
+				status = "disabled";
+			};
+
+			uart3: serial@5000c000 {
+				compatible = "fsl,imx25-uart", "fsl,imx21-uart";
+				reg = <0x5000c000 0x4000>;
+				interrupts = <18>;
+				clocks = <&clks 122>, <&clks 57>;
+				clock-names = "ipg", "per";
+				status = "disabled";
+			};
+
+			spi2: cspi@50010000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx25-cspi", "fsl,imx35-cspi";
+				reg = <0x50010000 0x4000>;
+				clocks = <&clks 79>;
+				clock-names = "ipg";
+				interrupts = <13>;
+				status = "disabled";
+			};
+
+			ssi2: ssi@50014000 {
+				compatible = "fsl,imx25-ssi", "fsl,imx21-ssi";
+				reg = <0x50014000 0x4000>;
+				interrupts = <11>;
+				status = "disabled";
+			};
+
+			esai@50018000 {
+				reg = <0x50018000 0x4000>;
+				interrupts = <7>;
+			};
+
+			uart5: serial@5002c000 {
+				compatible = "fsl,imx25-uart", "fsl,imx21-uart";
+				reg = <0x5002c000 0x4000>;
+				interrupts = <40>;
+				clocks = <&clks 124>, <&clks 57>;
+				clock-names = "ipg", "per";
+				status = "disabled";
+			};
+
+			tsc: tsc@50030000 {
+				compatible = "fsl,imx25-adc", "fsl,imx21-tsc";
+				reg = <0x50030000 0x4000>;
+				interrupts = <46>;
+				clocks = <&clks 119>;
+				clock-names = "ipg";
+				status = "disabled";
+			};
+
+			ssi1: ssi@50034000 {
+				compatible = "fsl,imx25-ssi", "fsl,imx21-ssi";
+				reg = <0x50034000 0x4000>;
+				interrupts = <12>;
+				status = "disabled";
+			};
+
+			fec: ethernet@50038000 {
+				compatible = "fsl,imx25-fec";
+				reg = <0x50038000 0x4000>;
+				interrupts = <57>;
+				clocks = <&clks 88>, <&clks 65>;
+				clock-names = "ipg", "ahb";
+				status = "disabled";
+			};
+		};
+
+		aips@53f00000 { /* AIPS2 */
+			compatible = "fsl,aips-bus", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x53f00000 0x100000>;
+			ranges;
+
+			clks: ccm@53f80000 {
+				compatible = "fsl,imx25-ccm";
+				reg = <0x53f80000 0x4000>;
+				interrupts = <31>;
+				#clock-cells = <1>;
+			};
+
+			gpt4: timer@53f84000 {
+				compatible = "fsl,imx25-gpt", "fsl,imx31-gpt";
+				reg = <0x53f84000 0x4000>;
+				clocks = <&clks 9>, <&clks 45>;
+				clock-names = "ipg", "per";
+				interrupts = <1>;
+			};
+
+			gpt3: timer@53f88000 {
+				compatible = "fsl,imx25-gpt", "fsl,imx31-gpt";
+				reg = <0x53f88000 0x4000>;
+				clocks = <&clks 9>, <&clks 47>;
+				clock-names = "ipg", "per";
+				interrupts = <29>;
+			};
+
+			gpt2: timer@53f8c000 {
+				compatible = "fsl,imx25-gpt", "fsl,imx31-gpt";
+				reg = <0x53f8c000 0x4000>;
+				clocks = <&clks 9>, <&clks 47>;
+				clock-names = "ipg", "per";
+				interrupts = <53>;
+			};
+
+			gpt1: timer@53f90000 {
+				compatible = "fsl,imx25-gpt", "fsl,imx31-gpt";
+				reg = <0x53f90000 0x4000>;
+				clocks = <&clks 9>, <&clks 47>;
+				clock-names = "ipg", "per";
+				interrupts = <54>;
+			};
+
+			epit1: timer@53f94000 {
+				compatible = "fsl,imx25-epit";
+				reg = <0x53f94000 0x4000>;
+				interrupts = <28>;
+			};
+
+			epit2: timer@53f98000 {
+				compatible = "fsl,imx25-epit";
+				reg = <0x53f98000 0x4000>;
+				interrupts = <27>;
+			};
+
+			gpio4: gpio@53f9c000 {
+				compatible = "fsl,imx25-gpio", "fsl,imx35-gpio";
+				reg = <0x53f9c000 0x4000>;
+				interrupts = <23>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+			};
+
+			pwm2: pwm@53fa0000 {
+				compatible = "fsl,imx25-pwm", "fsl,imx27-pwm";
+				#pwm-cells = <2>;
+				reg = <0x53fa0000 0x4000>;
+				clocks = <&clks 106>, <&clks 36>;
+				clock-names = "ipg", "per";
+				interrupts = <36>;
+			};
+
+			gpio3: gpio@53fa4000 {
+				compatible = "fsl,imx25-gpio", "fsl,imx35-gpio";
+				reg = <0x53fa4000 0x4000>;
+				interrupts = <16>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+			};
+
+			pwm3: pwm@53fa8000 {
+				compatible = "fsl,imx25-pwm", "fsl,imx27-pwm";
+				#pwm-cells = <2>;
+				reg = <0x53fa8000 0x4000>;
+				clocks = <&clks 107>, <&clks 36>;
+				clock-names = "ipg", "per";
+				interrupts = <41>;
+			};
+
+			esdhc1: esdhc@53fb4000 {
+				compatible = "fsl,imx25-esdhc";
+				reg = <0x53fb4000 0x4000>;
+				interrupts = <9>;
+				clocks = <&clks 86>, <&clks 63>, <&clks 45>;
+				clock-names = "ipg", "ahb", "per";
+				status = "disabled";
+			};
+
+			esdhc2: esdhc@53fb8000 {
+				compatible = "fsl,imx25-esdhc";
+				reg = <0x53fb8000 0x4000>;
+				interrupts = <8>;
+				clocks = <&clks 87>, <&clks 64>, <&clks 46>;
+				clock-names = "ipg", "ahb", "per";
+				status = "disabled";
+			};
+
+			lcdc@53fbc000 {
+				reg = <0x53fbc000 0x4000>;
+				interrupts = <39>;
+				clocks = <&clks 103>, <&clks 66>, <&clks 49>;
+				clock-names = "ipg", "ahb", "per";
+				status = "disabled";
+			};
+
+			slcdc@53fc0000 {
+				reg = <0x53fc0000 0x4000>;
+				interrupts = <38>;
+				status = "disabled";
+			};
+
+			pwm4: pwm@53fc8000 {
+				compatible = "fsl,imx25-pwm", "fsl,imx27-pwm";
+				reg = <0x53fc8000 0x4000>;
+				clocks = <&clks 108>, <&clks 36>;
+				clock-names = "ipg", "per";
+				interrupts = <42>;
+			};
+
+			gpio1: gpio@53fcc000 {
+				compatible = "fsl,imx25-gpio", "fsl,imx35-gpio";
+				reg = <0x53fcc000 0x4000>;
+				interrupts = <52>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+			};
+
+			gpio2: gpio@53fd0000 {
+				compatible = "fsl,imx25-gpio", "fsl,imx35-gpio";
+				reg = <0x53fd0000 0x4000>;
+				interrupts = <51>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+			};
+
+			sdma@53fd4000 {
+				compatible = "fsl,imx25-sdma", "fsl,imx35-sdma";
+				reg = <0x53fd4000 0x4000>;
+				clocks = <&clks 112>, <&clks 68>;
+				clock-names = "ipg", "ahb";
+				interrupts = <34>;
+			};
+
+			wdog@53fdc000 {
+				compatible = "fsl,imx25-wdt", "fsl,imx21-wdt";
+				reg = <0x53fdc000 0x4000>;
+				clocks = <&clks 126>;
+				clock-names = "";
+				interrupts = <55>;
+			};
+
+			pwm1: pwm@53fe0000 {
+				compatible = "fsl,imx25-pwm", "fsl,imx27-pwm";
+				#pwm-cells = <2>;
+				reg = <0x53fe0000 0x4000>;
+				clocks = <&clks 105>, <&clks 36>;
+				clock-names = "ipg", "per";
+				interrupts = <26>;
+			};
+
+			usbphy1: usbphy@1 {
+				compatible = "nop-usbphy";
+				status = "disabled";
+			};
+
+			usbphy2: usbphy@2 {
+				compatible = "nop-usbphy";
+				status = "disabled";
+			};
+
+			usbotg: usb@53ff4000 {
+				compatible = "fsl,imx25-usb", "fsl,imx27-usb";
+				reg = <0x53ff4000 0x0200>;
+				interrupts = <37>;
+				clocks = <&clks 9>, <&clks 70>, <&clks 8>;
+				clock-names = "ipg", "ahb", "per";
+				fsl,usbmisc = <&usbmisc 0>;
+				status = "disabled";
+			};
+
+			usbhost1: usb@53ff4400 {
+				compatible = "fsl,imx25-usb", "fsl,imx27-usb";
+				reg = <0x53ff4400 0x0200>;
+				interrupts = <35>;
+				clocks = <&clks 9>, <&clks 70>, <&clks 8>;
+				clock-names = "ipg", "ahb", "per";
+				fsl,usbmisc = <&usbmisc 1>;
+				status = "disabled";
+			};
+
+			usbmisc: usbmisc@53ff4600 {
+				#index-cells = <1>;
+				compatible = "fsl,imx25-usbmisc";
+				clocks = <&clks 9>, <&clks 70>, <&clks 8>;
+				clock-names = "ipg", "ahb", "per";
+				reg = <0x53ff4600 0x00f>;
+				status = "disabled";
+			};
+
+			dryice@53ffc000 {
+				compatible = "fsl,imx25-dryice", "fsl,imx25-rtc";
+				reg = <0x53ffc000 0x4000>;
+				clocks = <&clks 81>;
+				clock-names = "ipg";
+				interrupts = <25>;
+			};
+		};
+
+		emi@80000000 {
+			compatible = "fsl,emi-bus", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x80000000 0x3b002000>;
+			ranges;
+
+			nfc: nand@bb000000 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+
+				compatible = "fsl,imx25-nand";
+				reg = <0xbb000000 0x2000>;
+				clocks = <&clks 50>;
+				clock-names = "";
+				interrupts = <33>;
+				status = "disabled";
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/imx27-apf27.dts b/arch/arm/boot/dts/imx27-apf27.dts
deleted file mode 100644
index b464c80..0000000
--- a/arch/arm/boot/dts/imx27-apf27.dts
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright 2012 Philippe Reynes <tremyfr@yahoo.fr>
- * Copyright 2012 Armadeus Systems <support@armadeus.com>
- *
- * Based on code which is: Copyright 2012 Sascha Hauer, Pengutronix
- *
- * 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
- */
-
-/dts-v1/;
-/include/ "imx27.dtsi"
-
-/ {
-	model = "Armadeus Systems APF27 module";
-	compatible = "armadeus,imx27-apf27", "fsl,imx27";
-
-	memory {
-		reg = <0xa0000000 0x04000000>;
-	};
-
-	clocks {
-		#address-cells = <1>;
-		#size-cells = <0>;
-
-		osc26m {
-			compatible = "fsl,imx-osc26m", "fixed-clock";
-			clock-frequency = <0>;
-		};
-	};
-};
-
-&uart1 {
-	status = "okay";
-};
-
-&fec {
-	status = "okay";
-};
-
-&nfc {
-	status = "okay";
-	nand-bus-width = <16>;
-	nand-ecc-mode = "hw";
-	nand-on-flash-bbt;
-
-	partition@0 {
-		label = "u-boot";
-		reg = <0x0 0x100000>;
-	};
-
-	partition@100000 {
-		label = "env";
-		reg = <0x100000 0x80000>;
-	};
-
-	partition@180000 {
-		label = "env2";
-		reg = <0x180000 0x80000>;
-	};
-
-	partition@200000 {
-		label = "firmware";
-		reg = <0x200000 0x80000>;
-	};
-
-	partition@280000 {
-		label = "dtb";
-		reg = <0x280000 0x80000>;
-	};
-
-	partition@300000 {
-		label = "kernel";
-		reg = <0x300000 0x500000>;
-	};
-
-	partition@800000 {
-		label = "rootfs";
-		reg = <0x800000 0xf800000>;
-	};
-};
diff --git a/arch/arm/boot/dts/imx27-apf27.dtsp b/arch/arm/boot/dts/imx27-apf27.dtsp
new file mode 100644
index 0000000..59f276f
--- /dev/null
+++ b/arch/arm/boot/dts/imx27-apf27.dtsp
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2012 Philippe Reynes <tremyfr@yahoo.fr>
+ * Copyright 2012 Armadeus Systems <support@armadeus.com>
+ *
+ * Based on code which is: Copyright 2012 Sascha Hauer, Pengutronix
+ *
+ * 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
+ */
+
+/dts-v1/;
+#include "imx27.dtsip"
+
+/ {
+	model = "Armadeus Systems APF27 module";
+	compatible = "armadeus,imx27-apf27", "fsl,imx27";
+
+	memory {
+		reg = <0xa0000000 0x04000000>;
+	};
+
+	clocks {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		osc26m {
+			compatible = "fsl,imx-osc26m", "fixed-clock";
+			clock-frequency = <0>;
+		};
+	};
+};
+
+&uart1 {
+	status = "okay";
+};
+
+&fec {
+	status = "okay";
+};
+
+&nfc {
+	status = "okay";
+	nand-bus-width = <16>;
+	nand-ecc-mode = "hw";
+	nand-on-flash-bbt;
+
+	partition@0 {
+		label = "u-boot";
+		reg = <0x0 0x100000>;
+	};
+
+	partition@100000 {
+		label = "env";
+		reg = <0x100000 0x80000>;
+	};
+
+	partition@180000 {
+		label = "env2";
+		reg = <0x180000 0x80000>;
+	};
+
+	partition@200000 {
+		label = "firmware";
+		reg = <0x200000 0x80000>;
+	};
+
+	partition@280000 {
+		label = "dtb";
+		reg = <0x280000 0x80000>;
+	};
+
+	partition@300000 {
+		label = "kernel";
+		reg = <0x300000 0x500000>;
+	};
+
+	partition@800000 {
+		label = "rootfs";
+		reg = <0x800000 0xf800000>;
+	};
+};
diff --git a/arch/arm/boot/dts/imx27-apf27dev.dtsp b/arch/arm/boot/dts/imx27-apf27dev.dtsp
new file mode 100644
index 0000000..65d1853
--- /dev/null
+++ b/arch/arm/boot/dts/imx27-apf27dev.dtsp
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2013 Armadeus Systems - <support@armadeus.com>
+ *
+ * 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
+ */
+
+/* APF27Dev is a docking board for the APF27 SOM */
+#include "imx27-apf27.dtsp"
+
+/ {
+	model = "Armadeus Systems APF27Dev docking/development board";
+	compatible = "armadeus,imx27-apf27dev", "armadeus,imx27-apf27", "fsl,imx27";
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		user-key {
+			label = "user";
+			gpios = <&gpio6 13 0>;
+			linux,code = <276>; /* BTN_EXTRA */
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		user {
+			label = "Heartbeat";
+			gpios = <&gpio6 14 0>;
+			linux,default-trigger = "heartbeat";
+		};
+	};
+};
+
+&cspi1 {
+	fsl,spi-num-chipselects = <1>;
+	cs-gpios = <&gpio4 28 1>;
+	status = "okay";
+};
+
+&cspi2 {
+	fsl,spi-num-chipselects = <3>;
+	cs-gpios = <&gpio4 21 1>, <&gpio4 27 1>,
+			<&gpio2 17 1>;
+	status = "okay";
+};
+
+&i2c1 {
+	clock-frequency = <400000>;
+	status = "okay";
+};
+
+&i2c2 {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx27-pdk.dts b/arch/arm/boot/dts/imx27-pdk.dts
deleted file mode 100644
index 41cd110..0000000
--- a/arch/arm/boot/dts/imx27-pdk.dts
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2012 Sascha Hauer, Pengutronix
- *
- * 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
- */
-
-/dts-v1/;
-/include/ "imx27.dtsi"
-
-/ {
-	model = "Freescale i.MX27 Product Development Kit";
-	compatible = "fsl,imx27-pdk", "fsl,imx27";
-
-	memory {
-		reg = <0x0 0x0>;
-	};
-};
-
-&uart1 {
-	fsl,uart-has-rtscts;
-	status = "okay";
-};
-
-&fec {
-	status = "okay";
-};
diff --git a/arch/arm/boot/dts/imx27-pdk.dtsp b/arch/arm/boot/dts/imx27-pdk.dtsp
new file mode 100644
index 0000000..fe5f609
--- /dev/null
+++ b/arch/arm/boot/dts/imx27-pdk.dtsp
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2012 Sascha Hauer, Pengutronix
+ *
+ * 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
+ */
+
+/dts-v1/;
+#include "imx27.dtsip"
+
+/ {
+	model = "Freescale i.MX27 Product Development Kit";
+	compatible = "fsl,imx27-pdk", "fsl,imx27";
+
+	memory {
+		reg = <0x0 0x0>;
+	};
+};
+
+&uart1 {
+	fsl,uart-has-rtscts;
+	status = "okay";
+};
+
+&fec {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx27-phytec-phycore.dts b/arch/arm/boot/dts/imx27-phytec-phycore.dts
deleted file mode 100644
index 53b0ec0..0000000
--- a/arch/arm/boot/dts/imx27-phytec-phycore.dts
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright 2012 Sascha Hauer, Pengutronix
- *
- * 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
- */
-
-/dts-v1/;
-/include/ "imx27.dtsi"
-
-/ {
-	model = "Phytec pcm038";
-	compatible = "phytec,imx27-pcm038", "fsl,imx27";
-
-	memory {
-		reg = <0x0 0x0>;
-	};
-
-	soc {
-		aipi@10000000 { /* aipi1 */
-			serial@1000a000 {
-				fsl,uart-has-rtscts;
-				status = "okay";
-			};
-
-			serial@1000b000 {
-				fsl,uart-has-rtscts;
-				status = "okay";
-			};
-
-			serial@1000c000 {
-				fsl,uart-has-rtscts;
-				status = "okay";
-			};
-
-			i2c@1001d000 {
-				clock-frequency = <400000>;
-				status = "okay";
-				at24@52 {
-					compatible = "at,24c32";
-					pagesize = <32>;
-					reg = <0x52>;
-				};
-				pcf8563@51 {
-					compatible = "nxp,pcf8563";
-					reg = <0x51>;
-				};
-				lm75@4a {
-					compatible = "national,lm75";
-					reg = <0x4a>;
-				};
-			};
-		};
-
-		aipi@10020000 { /* aipi2 */
-			ethernet@1002b000 {
-				status = "okay";
-			};
-		};
-	};
-
-	nor_flash@c0000000 {
-		compatible = "cfi-flash";
-		bank-width = <2>;
-		reg = <0xc0000000 0x02000000>;
-		#address-cells = <1>;
-		#size-cells = <1>;
-	};
-};
diff --git a/arch/arm/boot/dts/imx27-phytec-phycore.dtsp b/arch/arm/boot/dts/imx27-phytec-phycore.dtsp
new file mode 100644
index 0000000..924097a
--- /dev/null
+++ b/arch/arm/boot/dts/imx27-phytec-phycore.dtsp
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2012 Sascha Hauer, Pengutronix
+ *
+ * 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
+ */
+
+/dts-v1/;
+#include "imx27.dtsip"
+
+/ {
+	model = "Phytec pcm038";
+	compatible = "phytec,imx27-pcm038", "fsl,imx27";
+
+	memory {
+		reg = <0x0 0x0>;
+	};
+
+	soc {
+		aipi@10000000 { /* aipi1 */
+			serial@1000a000 {
+				fsl,uart-has-rtscts;
+				status = "okay";
+			};
+
+			serial@1000b000 {
+				fsl,uart-has-rtscts;
+				status = "okay";
+			};
+
+			serial@1000c000 {
+				fsl,uart-has-rtscts;
+				status = "okay";
+			};
+
+			i2c@1001d000 {
+				clock-frequency = <400000>;
+				status = "okay";
+				at24@52 {
+					compatible = "at,24c32";
+					pagesize = <32>;
+					reg = <0x52>;
+				};
+				pcf8563@51 {
+					compatible = "nxp,pcf8563";
+					reg = <0x51>;
+				};
+				lm75@4a {
+					compatible = "national,lm75";
+					reg = <0x4a>;
+				};
+			};
+		};
+
+		aipi@10020000 { /* aipi2 */
+			ethernet@1002b000 {
+				status = "okay";
+			};
+		};
+	};
+
+	nor_flash@c0000000 {
+		compatible = "cfi-flash";
+		bank-width = <2>;
+		reg = <0xc0000000 0x02000000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+	};
+};
diff --git a/arch/arm/boot/dts/imx27.dtsi b/arch/arm/boot/dts/imx27.dtsi
deleted file mode 100644
index 5a82cb5..0000000
--- a/arch/arm/boot/dts/imx27.dtsi
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * Copyright 2012 Sascha Hauer, Pengutronix
- *
- * 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/ "skeleton.dtsi"
-
-/ {
-	aliases {
-		serial0 = &uart1;
-		serial1 = &uart2;
-		serial2 = &uart3;
-		serial3 = &uart4;
-		serial4 = &uart5;
-		serial5 = &uart6;
-		gpio0 = &gpio1;
-		gpio1 = &gpio2;
-		gpio2 = &gpio3;
-		gpio3 = &gpio4;
-		gpio4 = &gpio5;
-		gpio5 = &gpio6;
-	};
-
-	avic: avic-interrupt-controller@e0000000 {
-		compatible = "fsl,imx27-avic", "fsl,avic";
-		interrupt-controller;
-		#interrupt-cells = <1>;
-		reg = <0x10040000 0x1000>;
-	};
-
-	clocks {
-		#address-cells = <1>;
-		#size-cells = <0>;
-
-		osc26m {
-			compatible = "fsl,imx-osc26m", "fixed-clock";
-			clock-frequency = <26000000>;
-		};
-	};
-
-	soc {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		compatible = "simple-bus";
-		interrupt-parent = <&avic>;
-		ranges;
-
-		aipi@10000000 { /* AIPI1 */
-			compatible = "fsl,aipi-bus", "simple-bus";
-			#address-cells = <1>;
-			#size-cells = <1>;
-			reg = <0x10000000 0x20000>;
-			ranges;
-
-			wdog: wdog@10002000 {
-				compatible = "fsl,imx27-wdt", "fsl,imx21-wdt";
-				reg = <0x10002000 0x4000>;
-				interrupts = <27>;
-			};
-
-			uart1: serial@1000a000 {
-				compatible = "fsl,imx27-uart", "fsl,imx21-uart";
-				reg = <0x1000a000 0x1000>;
-				interrupts = <20>;
-				status = "disabled";
-			};
-
-			uart2: serial@1000b000 {
-				compatible = "fsl,imx27-uart", "fsl,imx21-uart";
-				reg = <0x1000b000 0x1000>;
-				interrupts = <19>;
-				status = "disabled";
-			};
-
-			uart3: serial@1000c000 {
-				compatible = "fsl,imx27-uart", "fsl,imx21-uart";
-				reg = <0x1000c000 0x1000>;
-				interrupts = <18>;
-				status = "disabled";
-			};
-
-			uart4: serial@1000d000 {
-				compatible = "fsl,imx27-uart", "fsl,imx21-uart";
-				reg = <0x1000d000 0x1000>;
-				interrupts = <17>;
-				status = "disabled";
-			};
-
-			cspi1: cspi@1000e000 {
-				#address-cells = <1>;
-				#size-cells = <0>;
-				compatible = "fsl,imx27-cspi";
-				reg = <0x1000e000 0x1000>;
-				interrupts = <16>;
-				status = "disabled";
-			};
-
-			cspi2: cspi@1000f000 {
-				#address-cells = <1>;
-				#size-cells = <0>;
-				compatible = "fsl,imx27-cspi";
-				reg = <0x1000f000 0x1000>;
-				interrupts = <15>;
-				status = "disabled";
-			};
-
-			i2c1: i2c@10012000 {
-				#address-cells = <1>;
-				#size-cells = <0>;
-				compatible = "fsl,imx27-i2c", "fsl,imx21-i2c";
-				reg = <0x10012000 0x1000>;
-				interrupts = <12>;
-				status = "disabled";
-			};
-
-			gpio1: gpio@10015000 {
-				compatible = "fsl,imx27-gpio", "fsl,imx21-gpio";
-				reg = <0x10015000 0x100>;
-				interrupts = <8>;
-				gpio-controller;
-				#gpio-cells = <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-			};
-
-			gpio2: gpio@10015100 {
-				compatible = "fsl,imx27-gpio", "fsl,imx21-gpio";
-				reg = <0x10015100 0x100>;
-				interrupts = <8>;
-				gpio-controller;
-				#gpio-cells = <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-			};
-
-			gpio3: gpio@10015200 {
-				compatible = "fsl,imx27-gpio", "fsl,imx21-gpio";
-				reg = <0x10015200 0x100>;
-				interrupts = <8>;
-				gpio-controller;
-				#gpio-cells = <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-			};
-
-			gpio4: gpio@10015300 {
-				compatible = "fsl,imx27-gpio", "fsl,imx21-gpio";
-				reg = <0x10015300 0x100>;
-				interrupts = <8>;
-				gpio-controller;
-				#gpio-cells = <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-			};
-
-			gpio5: gpio@10015400 {
-				compatible = "fsl,imx27-gpio", "fsl,imx21-gpio";
-				reg = <0x10015400 0x100>;
-				interrupts = <8>;
-				gpio-controller;
-				#gpio-cells = <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-			};
-
-			gpio6: gpio@10015500 {
-				compatible = "fsl,imx27-gpio", "fsl,imx21-gpio";
-				reg = <0x10015500 0x100>;
-				interrupts = <8>;
-				gpio-controller;
-				#gpio-cells = <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-			};
-
-			cspi3: cspi@10017000 {
-				#address-cells = <1>;
-				#size-cells = <0>;
-				compatible = "fsl,imx27-cspi";
-				reg = <0x10017000 0x1000>;
-				interrupts = <6>;
-				status = "disabled";
-			};
-
-			uart5: serial@1001b000 {
-				compatible = "fsl,imx27-uart", "fsl,imx21-uart";
-				reg = <0x1001b000 0x1000>;
-				interrupts = <49>;
-				status = "disabled";
-			};
-
-			uart6: serial@1001c000 {
-				compatible = "fsl,imx27-uart", "fsl,imx21-uart";
-				reg = <0x1001c000 0x1000>;
-				interrupts = <48>;
-				status = "disabled";
-			};
-
-			i2c2: i2c@1001d000 {
-				#address-cells = <1>;
-				#size-cells = <0>;
-				compatible = "fsl,imx27-i2c", "fsl,imx21-i2c";
-				reg = <0x1001d000 0x1000>;
-				interrupts = <1>;
-				status = "disabled";
-			};
-
-		};
-
-		aipi@10020000 { /* AIPI2 */
-			compatible = "fsl,aipi-bus", "simple-bus";
-			#address-cells = <1>;
-			#size-cells = <1>;
-			reg = <0x10020000 0x20000>;
-			ranges;
-
-			fec: ethernet@1002b000 {
-				compatible = "fsl,imx27-fec";
-				reg = <0x1002b000 0x4000>;
-				interrupts = <50>;
-				status = "disabled";
-			};
-		};
-
-		nfc: nand@d8000000 {
-			#address-cells = <1>;
-			#size-cells = <1>;
-
-			compatible = "fsl,imx27-nand";
-			reg = <0xd8000000 0x1000>;
-			interrupts = <29>;
-			status = "disabled";
-		};
-	};
-};
diff --git a/arch/arm/boot/dts/imx27.dtsip b/arch/arm/boot/dts/imx27.dtsip
new file mode 100644
index 0000000..ff4bd48
--- /dev/null
+++ b/arch/arm/boot/dts/imx27.dtsip
@@ -0,0 +1,319 @@
+/*
+ * Copyright 2012 Sascha Hauer, Pengutronix
+ *
+ * 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 "skeleton.dtsi"
+
+/ {
+	aliases {
+		serial0 = &uart1;
+		serial1 = &uart2;
+		serial2 = &uart3;
+		serial3 = &uart4;
+		serial4 = &uart5;
+		serial5 = &uart6;
+		gpio0 = &gpio1;
+		gpio1 = &gpio2;
+		gpio2 = &gpio3;
+		gpio3 = &gpio4;
+		gpio4 = &gpio5;
+		gpio5 = &gpio6;
+	};
+
+	avic: avic-interrupt-controller@e0000000 {
+		compatible = "fsl,imx27-avic", "fsl,avic";
+		interrupt-controller;
+		#interrupt-cells = <1>;
+		reg = <0x10040000 0x1000>;
+	};
+
+	clocks {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		osc26m {
+			compatible = "fsl,imx-osc26m", "fixed-clock";
+			clock-frequency = <26000000>;
+		};
+	};
+
+	soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		interrupt-parent = <&avic>;
+		ranges;
+
+		aipi@10000000 { /* AIPI1 */
+			compatible = "fsl,aipi-bus", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x10000000 0x20000>;
+			ranges;
+
+			wdog: wdog@10002000 {
+				compatible = "fsl,imx27-wdt", "fsl,imx21-wdt";
+				reg = <0x10002000 0x1000>;
+				interrupts = <27>;
+				clocks = <&clks 0>;
+			};
+
+			gpt1: timer@10003000 {
+				compatible = "fsl,imx27-gpt", "fsl,imx1-gpt";
+				reg = <0x10003000 0x1000>;
+				interrupts = <26>;
+				clocks = <&clks 46>, <&clks 61>;
+				clock-names = "ipg", "per";
+			};
+
+			gpt2: timer@10004000 {
+				compatible = "fsl,imx27-gpt", "fsl,imx1-gpt";
+				reg = <0x10004000 0x1000>;
+				interrupts = <25>;
+				clocks = <&clks 45>, <&clks 61>;
+				clock-names = "ipg", "per";
+			};
+
+			gpt3: timer@10005000 {
+				compatible = "fsl,imx27-gpt", "fsl,imx1-gpt";
+				reg = <0x10005000 0x1000>;
+				interrupts = <24>;
+				clocks = <&clks 44>, <&clks 61>;
+				clock-names = "ipg", "per";
+			};
+
+			uart1: serial@1000a000 {
+				compatible = "fsl,imx27-uart", "fsl,imx21-uart";
+				reg = <0x1000a000 0x1000>;
+				interrupts = <20>;
+				clocks = <&clks 81>, <&clks 61>;
+				clock-names = "ipg", "per";
+				status = "disabled";
+			};
+
+			uart2: serial@1000b000 {
+				compatible = "fsl,imx27-uart", "fsl,imx21-uart";
+				reg = <0x1000b000 0x1000>;
+				interrupts = <19>;
+				clocks = <&clks 80>, <&clks 61>;
+				clock-names = "ipg", "per";
+				status = "disabled";
+			};
+
+			uart3: serial@1000c000 {
+				compatible = "fsl,imx27-uart", "fsl,imx21-uart";
+				reg = <0x1000c000 0x1000>;
+				interrupts = <18>;
+				clocks = <&clks 79>, <&clks 61>;
+				clock-names = "ipg", "per";
+				status = "disabled";
+			};
+
+			uart4: serial@1000d000 {
+				compatible = "fsl,imx27-uart", "fsl,imx21-uart";
+				reg = <0x1000d000 0x1000>;
+				interrupts = <17>;
+				clocks = <&clks 78>, <&clks 61>;
+				clock-names = "ipg", "per";
+				status = "disabled";
+			};
+
+			cspi1: cspi@1000e000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx27-cspi";
+				reg = <0x1000e000 0x1000>;
+				interrupts = <16>;
+				clocks = <&clks 53>, <&clks 0>;
+				clock-names = "ipg", "per";
+				status = "disabled";
+			};
+
+			cspi2: cspi@1000f000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx27-cspi";
+				reg = <0x1000f000 0x1000>;
+				interrupts = <15>;
+				clocks = <&clks 52>, <&clks 0>;
+				clock-names = "ipg", "per";
+				status = "disabled";
+			};
+
+			i2c1: i2c@10012000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx27-i2c", "fsl,imx21-i2c";
+				reg = <0x10012000 0x1000>;
+				interrupts = <12>;
+				clocks = <&clks 40>;
+				status = "disabled";
+			};
+
+			gpio1: gpio@10015000 {
+				compatible = "fsl,imx27-gpio", "fsl,imx21-gpio";
+				reg = <0x10015000 0x100>;
+				interrupts = <8>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+			};
+
+			gpio2: gpio@10015100 {
+				compatible = "fsl,imx27-gpio", "fsl,imx21-gpio";
+				reg = <0x10015100 0x100>;
+				interrupts = <8>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+			};
+
+			gpio3: gpio@10015200 {
+				compatible = "fsl,imx27-gpio", "fsl,imx21-gpio";
+				reg = <0x10015200 0x100>;
+				interrupts = <8>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+			};
+
+			gpio4: gpio@10015300 {
+				compatible = "fsl,imx27-gpio", "fsl,imx21-gpio";
+				reg = <0x10015300 0x100>;
+				interrupts = <8>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+			};
+
+			gpio5: gpio@10015400 {
+				compatible = "fsl,imx27-gpio", "fsl,imx21-gpio";
+				reg = <0x10015400 0x100>;
+				interrupts = <8>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+			};
+
+			gpio6: gpio@10015500 {
+				compatible = "fsl,imx27-gpio", "fsl,imx21-gpio";
+				reg = <0x10015500 0x100>;
+				interrupts = <8>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+			};
+
+			cspi3: cspi@10017000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx27-cspi";
+				reg = <0x10017000 0x1000>;
+				interrupts = <6>;
+				clocks = <&clks 51>, <&clks 0>;
+				clock-names = "ipg", "per";
+				status = "disabled";
+			};
+
+			gpt4: timer@10019000 {
+				compatible = "fsl,imx27-gpt", "fsl,imx1-gpt";
+				reg = <0x10019000 0x1000>;
+				interrupts = <4>;
+				clocks = <&clks 43>, <&clks 61>;
+				clock-names = "ipg", "per";
+			};
+
+			gpt5: timer@1001a000 {
+				compatible = "fsl,imx27-gpt", "fsl,imx1-gpt";
+				reg = <0x1001a000 0x1000>;
+				interrupts = <3>;
+				clocks = <&clks 42>, <&clks 61>;
+				clock-names = "ipg", "per";
+			};
+
+			uart5: serial@1001b000 {
+				compatible = "fsl,imx27-uart", "fsl,imx21-uart";
+				reg = <0x1001b000 0x1000>;
+				interrupts = <49>;
+				clocks = <&clks 77>, <&clks 61>;
+				clock-names = "ipg", "per";
+				status = "disabled";
+			};
+
+			uart6: serial@1001c000 {
+				compatible = "fsl,imx27-uart", "fsl,imx21-uart";
+				reg = <0x1001c000 0x1000>;
+				interrupts = <48>;
+				clocks = <&clks 78>, <&clks 61>;
+				clock-names = "ipg", "per";
+				status = "disabled";
+			};
+
+			i2c2: i2c@1001d000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx27-i2c", "fsl,imx21-i2c";
+				reg = <0x1001d000 0x1000>;
+				interrupts = <1>;
+				clocks = <&clks 39>;
+				status = "disabled";
+			};
+
+			gpt6: timer@1001f000 {
+				compatible = "fsl,imx27-gpt", "fsl,imx1-gpt";
+				reg = <0x1001f000 0x1000>;
+				interrupts = <2>;
+				clocks = <&clks 41>, <&clks 61>;
+				clock-names = "ipg", "per";
+			};
+		};
+
+		aipi@10020000 { /* AIPI2 */
+			compatible = "fsl,aipi-bus", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x10020000 0x20000>;
+			ranges;
+
+			fec: ethernet@1002b000 {
+				compatible = "fsl,imx27-fec";
+				reg = <0x1002b000 0x4000>;
+				interrupts = <50>;
+				clocks = <&clks 48>, <&clks 67>, <&clks 0>;
+				clock-names = "ipg", "ahb", "ptp";
+				status = "disabled";
+			};
+
+			clks: ccm@10027000{
+				compatible = "fsl,imx27-ccm";
+				reg = <0x10027000 0x1000>;
+				#clock-cells = <1>;
+			};
+		};
+
+
+		nfc: nand@d8000000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			compatible = "fsl,imx27-nand";
+			reg = <0xd8000000 0x1000>;
+			interrupts = <29>;
+			clocks = <&clks 54>;
+			status = "disabled";
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/imx28-apf28dev.dts b/arch/arm/boot/dts/imx28-apf28dev.dts
index 6d8865b..3d905d1 100644
--- a/arch/arm/boot/dts/imx28-apf28dev.dts
+++ b/arch/arm/boot/dts/imx28-apf28dev.dts
@@ -72,7 +72,32 @@
 				pinctrl-names = "default";
 				pinctrl-0 = <&lcdif_16bit_pins_a
 						&lcdif_pins_apf28dev>;
+				display = <&display>;
 				status = "okay";
+
+				display: display {
+					bits-per-pixel = <16>;
+					bus-width = <16>;
+
+					display-timings {
+						native-mode = <&timing0>;
+						timing0: timing0 {
+							clock-frequency = <33000033>;
+							hactive = <800>;
+							vactive = <480>;
+							hback-porch = <96>;
+							hfront-porch = <96>;
+							vback-porch = <20>;
+							vfront-porch = <21>;
+							hsync-len = <64>;
+							vsync-len = <4>;
+							hsync-active = <1>;
+							vsync-active = <1>;
+							de-active = <1>;
+							pixelclk-active = <0>;
+						};
+					};
+				};
 			};
 		};
 
diff --git a/arch/arm/boot/dts/imx28-apx4devkit.dts b/arch/arm/boot/dts/imx28-apx4devkit.dts
index 5171667..43bf3c7 100644
--- a/arch/arm/boot/dts/imx28-apx4devkit.dts
+++ b/arch/arm/boot/dts/imx28-apx4devkit.dts
@@ -94,7 +94,32 @@
 				pinctrl-names = "default";
 				pinctrl-0 = <&lcdif_24bit_pins_a
 					     &lcdif_pins_apx4>;
+				display = <&display>;
 				status = "okay";
+
+				display: display {
+					bits-per-pixel = <32>;
+					bus-width = <24>;
+
+					display-timings {
+						native-mode = <&timing0>;
+						timing0: timing0 {
+							clock-frequency = <30000000>;
+							hactive = <800>;
+							vactive = <480>;
+							hback-porch = <88>;
+							hfront-porch = <40>;
+							vback-porch = <32>;
+							vfront-porch = <13>;
+							hsync-len = <48>;
+							vsync-len = <3>;
+							hsync-active = <1>;
+							vsync-active = <1>;
+							de-active = <1>;
+							pixelclk-active = <0>;
+						};
+					};
+				};
 			};
 		};
 
diff --git a/arch/arm/boot/dts/imx28-cfa10049.dts b/arch/arm/boot/dts/imx28-cfa10049.dts
index a0d3e9f..db18cd4 100644
--- a/arch/arm/boot/dts/imx28-cfa10049.dts
+++ b/arch/arm/boot/dts/imx28-cfa10049.dts
@@ -30,7 +30,6 @@
 					reg = <0>;
 					fsl,pinmux-ids = <
 						0x0073 /* MX28_PAD_GPMI_D7__GPIO_0_7 */
-						0x1153 /* MX28_PAD_LCD_D22__GPIO_1_21 */
 						0x1163 /* MX28_PAD_LCD_D22__GPIO_1_22 */
 						0x1173 /* MX28_PAD_LCD_D22__GPIO_1_23 */
 						0x2153 /* MX28_PAD_SSP2_D5__GPIO_2_21 */
@@ -120,13 +119,48 @@
 					fsl,voltage = <1>;
 					fsl,pull-up = <0>;
 				};
+
+				w1_gpio_pins: w1-gpio@0 {
+					reg = <0>;
+					fsl,pinmux-ids = <
+						0x1153 /* MX28_PAD_LCD_D21__GPIO_1_21 */
+					>;
+					fsl,drive-strength = <1>;
+					fsl,voltage = <1>;
+					fsl,pull-up = <0>; /* 0 will enable the keeper */
+				};
 			};
 
 			lcdif@80030000 {
 				pinctrl-names = "default";
 				pinctrl-0 = <&lcdif_18bit_pins_cfa10049
 					     &lcdif_pins_cfa10049>;
+				display = <&display>;
 				status = "okay";
+
+				display: display {
+					bits-per-pixel = <32>;
+					bus-width = <18>;
+
+					display-timings {
+						native-mode = <&timing0>;
+						timing0: timing0 {
+							clock-frequency = <9216000>;
+							hactive = <320>;
+							vactive = <480>;
+							hback-porch = <2>;
+							hfront-porch = <2>;
+							vback-porch = <2>;
+							vfront-porch = <2>;
+							hsync-len = <15>;
+							vsync-len = <15>;
+							hsync-active = <0>;
+							vsync-active = <0>;
+							de-active = <1>;
+							pixelclk-active = <1>;
+						};
+					};
+				};
 			};
 		};
 
@@ -304,5 +338,14 @@
 		pwms = <&pwm 3 5000000>;
 		brightness-levels = <0 4 8 16 32 64 128 255>;
 		default-brightness-level = <6>;
+
+	};
+
+	onewire@0 {
+		compatible = "w1-gpio";
+		pinctrl-names = "default";
+		pinctrl-0 = <&w1_gpio_pins>;
+		status = "okay";
+		gpios = <&gpio1 21 0>;
 	};
 };
diff --git a/arch/arm/boot/dts/imx28-evk.dts b/arch/arm/boot/dts/imx28-evk.dts
index 2da316e..2d4ea3b 100644
--- a/arch/arm/boot/dts/imx28-evk.dts
+++ b/arch/arm/boot/dts/imx28-evk.dts
@@ -124,7 +124,32 @@
 				pinctrl-0 = <&lcdif_24bit_pins_a
 					     &lcdif_pins_evk>;
 				panel-enable-gpios = <&gpio3 30 0>;
+				display = <&display>;
 				status = "okay";
+
+				display: display {
+					bits-per-pixel = <32>;
+					bus-width = <24>;
+
+					display-timings {
+						native-mode = <&timing0>;
+						timing0: timing0 {
+							clock-frequency = <33500000>;
+							hactive = <800>;
+							vactive = <480>;
+							hback-porch = <89>;
+							hfront-porch = <164>;
+							vback-porch = <23>;
+							vfront-porch = <10>;
+							hsync-len = <10>;
+							vsync-len = <10>;
+							hsync-active = <0>;
+							vsync-active = <0>;
+							de-active = <1>;
+							pixelclk-active = <0>;
+						};
+					};
+				};
 			};
 
 			can0: can@80032000 {
diff --git a/arch/arm/boot/dts/imx28-m28evk.dts b/arch/arm/boot/dts/imx28-m28evk.dts
index 6ce3d17..5f0ba99 100644
--- a/arch/arm/boot/dts/imx28-m28evk.dts
+++ b/arch/arm/boot/dts/imx28-m28evk.dts
@@ -119,7 +119,32 @@
 				pinctrl-names = "default";
 				pinctrl-0 = <&lcdif_24bit_pins_a
 					     &lcdif_pins_m28>;
+				display = <&display>;
 				status = "okay";
+
+				display: display {
+					bits-per-pixel = <16>;
+					bus-width = <18>;
+
+					display-timings {
+						native-mode = <&timing0>;
+						timing0: timing0 {
+							clock-frequency = <33260000>;
+							hactive = <800>;
+							vactive = <480>;
+							hback-porch = <0>;
+							hfront-porch = <256>;
+							vback-porch = <0>;
+							vfront-porch = <45>;
+							hsync-len = <1>;
+							vsync-len = <1>;
+							hsync-active = <0>;
+							vsync-active = <0>;
+							de-active = <1>;
+							pixelclk-active = <1>;
+						};
+					};
+				};
 			};
 
 			can0: can@80032000 {
@@ -221,6 +246,8 @@
 			phy-mode = "rmii";
 			pinctrl-names = "default";
 			pinctrl-0 = <&mac0_pins_a>;
+			clocks = <&clks 57>, <&clks 57>;
+			clock-names = "ipg", "ahb";
 			status = "okay";
 		};
 
diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi
index 7ba4966..600f7cb 100644
--- a/arch/arm/boot/dts/imx28.dtsi
+++ b/arch/arm/boot/dts/imx28.dtsi
@@ -61,12 +61,24 @@
 			hsadc@80002000 {
 				reg = <0x80002000 0x2000>;
 				interrupts = <13 87>;
+				dmas = <&dma_apbh 12>;
+				dma-names = "rx";
 				status = "disabled";
 			};
 
-			dma-apbh@80004000 {
+			dma_apbh: dma-apbh@80004000 {
 				compatible = "fsl,imx28-dma-apbh";
 				reg = <0x80004000 0x2000>;
+				interrupts = <82 83 84 85
+					      88 88 88 88
+					      88 88 88 88
+					      87 86 0 0>;
+				interrupt-names = "ssp0", "ssp1", "ssp2", "ssp3",
+						  "gpmi0", "gmpi1", "gpmi2", "gmpi3",
+						  "gpmi4", "gmpi5", "gpmi6", "gmpi7",
+						  "hsadc", "lcdif", "empty", "empty";
+				#dma-cells = <1>;
+				dma-channels = <16>;
 				clocks = <&clks 25>;
 			};
 
@@ -86,6 +98,8 @@
 				interrupt-names = "gpmi-dma", "bch";
 				clocks = <&clks 50>;
 				clock-names = "gpmi_io";
+				dmas = <&dma_apbh 4>;
+				dma-names = "rx-tx";
 				fsl,gpmi-dma-channel = <4>;
 				status = "disabled";
 			};
@@ -96,6 +110,8 @@
 				reg = <0x80010000 0x2000>;
 				interrupts = <96 82>;
 				clocks = <&clks 46>;
+				dmas = <&dma_apbh 0>;
+				dma-names = "rx-tx";
 				fsl,ssp-dma-channel = <0>;
 				status = "disabled";
 			};
@@ -106,6 +122,8 @@
 				reg = <0x80012000 0x2000>;
 				interrupts = <97 83>;
 				clocks = <&clks 47>;
+				dmas = <&dma_apbh 1>;
+				dma-names = "rx-tx";
 				fsl,ssp-dma-channel = <1>;
 				status = "disabled";
 			};
@@ -116,6 +134,8 @@
 				reg = <0x80014000 0x2000>;
 				interrupts = <98 84>;
 				clocks = <&clks 48>;
+				dmas = <&dma_apbh 2>;
+				dma-names = "rx-tx";
 				fsl,ssp-dma-channel = <2>;
 				status = "disabled";
 			};
@@ -126,6 +146,8 @@
 				reg = <0x80016000 0x2000>;
 				interrupts = <99 85>;
 				clocks = <&clks 49>;
+				dmas = <&dma_apbh 3>;
+				dma-names = "rx-tx";
 				fsl,ssp-dma-channel = <3>;
 				status = "disabled";
 			};
@@ -647,6 +669,7 @@
 			};
 
 			digctl@8001c000 {
+				compatible = "fsl,imx28-digctl";
 				reg = <0x8001c000 0x2000>;
 				interrupts = <89>;
 				status = "disabled";
@@ -657,9 +680,19 @@
 				status = "disabled";
 			};
 
-			dma-apbx@80024000 {
+			dma_apbx: dma-apbx@80024000 {
 				compatible = "fsl,imx28-dma-apbx";
 				reg = <0x80024000 0x2000>;
+				interrupts = <78 79 66 0
+					      80 81 68 69
+					      70 71 72 73
+					      74 75 76 77>;
+				interrupt-names = "auart4-rx", "aurat4-tx", "spdif-tx", "empty",
+						  "saif0", "saif1", "i2c0", "i2c1",
+						  "auart0-rx", "auart0-tx", "auart1-rx", "auart1-tx",
+						  "auart2-rx", "auart2-tx", "auart3-rx", "auart3-tx";
+				#dma-cells = <1>;
+				dma-channels = <16>;
 				clocks = <&clks 26>;
 			};
 
@@ -676,6 +709,7 @@
 			};
 
 			ocotp@8002c000 {
+				compatible = "fsl,ocotp";
 				reg = <0x8002c000 0x2000>;
 				status = "disabled";
 			};
@@ -690,6 +724,8 @@
 				reg = <0x80030000 0x2000>;
 				interrupts = <38 86>;
 				clocks = <&clks 55>;
+				dmas = <&dma_apbh 13>;
+				dma-names = "rx";
 				status = "disabled";
 			};
 
@@ -755,7 +791,7 @@
 			ranges;
 
 			clks: clkctrl@80040000 {
-				compatible = "fsl,imx28-clkctrl";
+				compatible = "fsl,imx28-clkctrl", "fsl,clkctrl";
 				reg = <0x80040000 0x2000>;
 				#clock-cells = <1>;
 			};
@@ -765,6 +801,8 @@
 				reg = <0x80042000 0x2000>;
 				interrupts = <59 80>;
 				clocks = <&clks 53>;
+				dmas = <&dma_apbx 4>;
+				dma-names = "rx-tx";
 				fsl,saif-dma-channel = <4>;
 				status = "disabled";
 			};
@@ -779,6 +817,8 @@
 				reg = <0x80046000 0x2000>;
 				interrupts = <58 81>;
 				clocks = <&clks 54>;
+				dmas = <&dma_apbx 5>;
+				dma-names = "rx-tx";
 				fsl,saif-dma-channel = <5>;
 				status = "disabled";
 			};
@@ -794,6 +834,8 @@
 			spdif@80054000 {
 				reg = <0x80054000 0x2000>;
 				interrupts = <45 66>;
+				dmas = <&dma_apbx 2>;
+				dma-names = "tx";
 				status = "disabled";
 			};
 
@@ -810,6 +852,8 @@
 				reg = <0x80058000 0x2000>;
 				interrupts = <111 68>;
 				clock-frequency = <100000>;
+				dmas = <&dma_apbx 6>;
+				dma-names = "rx-tx";
 				fsl,i2c-dma-channel = <6>;
 				status = "disabled";
 			};
@@ -821,6 +865,8 @@
 				reg = <0x8005a000 0x2000>;
 				interrupts = <110 69>;
 				clock-frequency = <100000>;
+				dmas = <&dma_apbx 7>;
+				dma-names = "rx-tx";
 				fsl,i2c-dma-channel = <7>;
 				status = "disabled";
 			};
@@ -838,12 +884,15 @@
 				compatible = "fsl,imx28-timrot", "fsl,timrot";
 				reg = <0x80068000 0x2000>;
 				interrupts = <48 49 50 51>;
+				clocks = <&clks 26>;
 			};
 
 			auart0: serial@8006a000 {
 				compatible = "fsl,imx28-auart", "fsl,imx23-auart";
 				reg = <0x8006a000 0x2000>;
 				interrupts = <112 70 71>;
+				dmas = <&dma_apbx 8>, <&dma_apbx 9>;
+				dma-names = "rx", "tx";
 				fsl,auart-dma-channel = <8 9>;
 				clocks = <&clks 45>;
 				status = "disabled";
@@ -853,6 +902,8 @@
 				compatible = "fsl,imx28-auart", "fsl,imx23-auart";
 				reg = <0x8006c000 0x2000>;
 				interrupts = <113 72 73>;
+				dmas = <&dma_apbx 10>, <&dma_apbx 11>;
+				dma-names = "rx", "tx";
 				clocks = <&clks 45>;
 				status = "disabled";
 			};
@@ -861,6 +912,8 @@
 				compatible = "fsl,imx28-auart", "fsl,imx23-auart";
 				reg = <0x8006e000 0x2000>;
 				interrupts = <114 74 75>;
+				dmas = <&dma_apbx 12>, <&dma_apbx 13>;
+				dma-names = "rx", "tx";
 				clocks = <&clks 45>;
 				status = "disabled";
 			};
@@ -869,6 +922,8 @@
 				compatible = "fsl,imx28-auart", "fsl,imx23-auart";
 				reg = <0x80070000 0x2000>;
 				interrupts = <115 76 77>;
+				dmas = <&dma_apbx 14>, <&dma_apbx 15>;
+				dma-names = "rx", "tx";
 				clocks = <&clks 45>;
 				status = "disabled";
 			};
@@ -877,6 +932,8 @@
 				compatible = "fsl,imx28-auart", "fsl,imx23-auart";
 				reg = <0x80072000 0x2000>;
 				interrupts = <116 78 79>;
+				dmas = <&dma_apbx 0>, <&dma_apbx 1>;
+				dma-names = "rx", "tx";
 				clocks = <&clks 45>;
 				status = "disabled";
 			};
@@ -940,8 +997,8 @@
 			compatible = "fsl,imx28-fec";
 			reg = <0x800f0000 0x4000>;
 			interrupts = <101>;
-			clocks = <&clks 57>, <&clks 57>;
-			clock-names = "ipg", "ahb";
+			clocks = <&clks 57>, <&clks 57>, <&clks 64>;
+			clock-names = "ipg", "ahb", "enet_out";
 			status = "disabled";
 		};
 
diff --git a/arch/arm/boot/dts/imx31-bug.dts b/arch/arm/boot/dts/imx31-bug.dts
deleted file mode 100644
index 9ac6f6b..0000000
--- a/arch/arm/boot/dts/imx31-bug.dts
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2012 Denis 'GNUtoo' Carikli <GNUtoo@no-log.org>
- *
- * 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
- */
-
-/dts-v1/;
-/include/ "imx31.dtsi"
-
-/ {
-	model = "Buglabs i.MX31 Bug 1.x";
-	compatible = "buglabs,imx31-bug", "fsl,imx31";
-
-	memory {
-		reg = <0x80000000 0x8000000>; /* 128M */
-	};
-};
-
-&uart5 {
-	fsl,uart-has-rtscts;
-	status = "okay";
-};
diff --git a/arch/arm/boot/dts/imx31-bug.dtsp b/arch/arm/boot/dts/imx31-bug.dtsp
new file mode 100644
index 0000000..8e26e91
--- /dev/null
+++ b/arch/arm/boot/dts/imx31-bug.dtsp
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2012 Denis 'GNUtoo' Carikli <GNUtoo@no-log.org>
+ *
+ * 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
+ */
+
+/dts-v1/;
+#include "imx31.dtsip"
+
+/ {
+	model = "Buglabs i.MX31 Bug 1.x";
+	compatible = "buglabs,imx31-bug", "fsl,imx31";
+
+	memory {
+		reg = <0x80000000 0x8000000>; /* 128M */
+	};
+};
+
+&uart5 {
+	fsl,uart-has-rtscts;
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx31.dtsi b/arch/arm/boot/dts/imx31.dtsi
deleted file mode 100644
index 454c2d1..0000000
--- a/arch/arm/boot/dts/imx31.dtsi
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright 2012 Denis 'GNUtoo' Carikli <GNUtoo@no-log.org>
- *
- * 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/ "skeleton.dtsi"
-
-/ {
-	aliases {
-		serial0 = &uart1;
-		serial1 = &uart2;
-		serial2 = &uart3;
-		serial3 = &uart4;
-		serial4 = &uart5;
-	};
-
-	avic: avic-interrupt-controller@60000000 {
-		compatible = "fsl,imx31-avic", "fsl,avic";
-		interrupt-controller;
-		#interrupt-cells = <1>;
-		reg = <0x60000000 0x100000>;
-	};
-
-	soc {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		compatible = "simple-bus";
-		interrupt-parent = <&avic>;
-		ranges;
-
-		aips@43f00000 { /* AIPS1 */
-			compatible = "fsl,aips-bus", "simple-bus";
-			#address-cells = <1>;
-			#size-cells = <1>;
-			reg = <0x43f00000 0x100000>;
-			ranges;
-
-			uart1: serial@43f90000 {
-				compatible = "fsl,imx31-uart", "fsl,imx21-uart";
-				reg = <0x43f90000 0x4000>;
-				interrupts = <45>;
-				clocks = <&clks 10>, <&clks 30>;
-				clock-names = "ipg", "per";
-				status = "disabled";
-			};
-
-			uart2: serial@43f94000 {
-				compatible = "fsl,imx31-uart", "fsl,imx21-uart";
-				reg = <0x43f94000 0x4000>;
-				interrupts = <32>;
-				clocks = <&clks 10>, <&clks 31>;
-				clock-names = "ipg", "per";
-				status = "disabled";
-			};
-
-			uart4: serial@43fb0000 {
-				compatible = "fsl,imx31-uart", "fsl,imx21-uart";
-				reg = <0x43fb0000 0x4000>;
-				clocks = <&clks 10>, <&clks 49>;
-				clock-names = "ipg", "per";
-				interrupts = <46>;
-				status = "disabled";
-			};
-
-			uart5: serial@43fb4000 {
-				compatible = "fsl,imx31-uart", "fsl,imx21-uart";
-				reg = <0x43fb4000 0x4000>;
-				interrupts = <47>;
-				clocks = <&clks 10>, <&clks 50>;
-				clock-names = "ipg", "per";
-				status = "disabled";
-			};
-		};
-
-		spba@50000000 {
-			compatible = "fsl,spba-bus", "simple-bus";
-			#address-cells = <1>;
-			#size-cells = <1>;
-			reg = <0x50000000 0x100000>;
-			ranges;
-
-			uart3: serial@5000c000 {
-				compatible = "fsl,imx31-uart", "fsl,imx21-uart";
-				reg = <0x5000c000 0x4000>;
-				interrupts = <18>;
-				clocks = <&clks 10>, <&clks 48>;
-				clock-names = "ipg", "per";
-				status = "disabled";
-			};
-
-			clks: ccm@53f80000{
-				compatible = "fsl,imx31-ccm";
-				reg = <0x53f80000 0x4000>;
-				interrupts = <0 31 0x04 0 53 0x04>;
-				#clock-cells = <1>;
-			};
-		};
-	};
-};
diff --git a/arch/arm/boot/dts/imx31.dtsip b/arch/arm/boot/dts/imx31.dtsip
new file mode 100644
index 0000000..c544925
--- /dev/null
+++ b/arch/arm/boot/dts/imx31.dtsip
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2012 Denis 'GNUtoo' Carikli <GNUtoo@no-log.org>
+ *
+ * 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 "skeleton.dtsi"
+
+/ {
+	aliases {
+		serial0 = &uart1;
+		serial1 = &uart2;
+		serial2 = &uart3;
+		serial3 = &uart4;
+		serial4 = &uart5;
+	};
+
+	avic: avic-interrupt-controller@60000000 {
+		compatible = "fsl,imx31-avic", "fsl,avic";
+		interrupt-controller;
+		#interrupt-cells = <1>;
+		reg = <0x60000000 0x100000>;
+	};
+
+	soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		interrupt-parent = <&avic>;
+		ranges;
+
+		aips@43f00000 { /* AIPS1 */
+			compatible = "fsl,aips-bus", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x43f00000 0x100000>;
+			ranges;
+
+			uart1: serial@43f90000 {
+				compatible = "fsl,imx31-uart", "fsl,imx21-uart";
+				reg = <0x43f90000 0x4000>;
+				interrupts = <45>;
+				clocks = <&clks 10>, <&clks 30>;
+				clock-names = "ipg", "per";
+				status = "disabled";
+			};
+
+			uart2: serial@43f94000 {
+				compatible = "fsl,imx31-uart", "fsl,imx21-uart";
+				reg = <0x43f94000 0x4000>;
+				interrupts = <32>;
+				clocks = <&clks 10>, <&clks 31>;
+				clock-names = "ipg", "per";
+				status = "disabled";
+			};
+
+			uart4: serial@43fb0000 {
+				compatible = "fsl,imx31-uart", "fsl,imx21-uart";
+				reg = <0x43fb0000 0x4000>;
+				clocks = <&clks 10>, <&clks 49>;
+				clock-names = "ipg", "per";
+				interrupts = <46>;
+				status = "disabled";
+			};
+
+			uart5: serial@43fb4000 {
+				compatible = "fsl,imx31-uart", "fsl,imx21-uart";
+				reg = <0x43fb4000 0x4000>;
+				interrupts = <47>;
+				clocks = <&clks 10>, <&clks 50>;
+				clock-names = "ipg", "per";
+				status = "disabled";
+			};
+		};
+
+		spba@50000000 {
+			compatible = "fsl,spba-bus", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x50000000 0x100000>;
+			ranges;
+
+			uart3: serial@5000c000 {
+				compatible = "fsl,imx31-uart", "fsl,imx21-uart";
+				reg = <0x5000c000 0x4000>;
+				interrupts = <18>;
+				clocks = <&clks 10>, <&clks 48>;
+				clock-names = "ipg", "per";
+				status = "disabled";
+			};
+
+			clks: ccm@53f80000{
+				compatible = "fsl,imx31-ccm";
+				reg = <0x53f80000 0x4000>;
+				interrupts = <0 31 0x04 0 53 0x04>;
+				#clock-cells = <1>;
+			};
+		};
+
+		aips@53f00000 { /* AIPS2 */
+			compatible = "fsl,aips-bus", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x53f00000 0x100000>;
+			ranges;
+
+			gpt: timer@53f90000 {
+				compatible = "fsl,imx31-gpt";
+				reg = <0x53f90000 0x4000>;
+				interrupts = <29>;
+				clocks = <&clks 10>, <&clks 22>;
+				clock-names = "ipg", "per";
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/imx35-pinfunc.h b/arch/arm/boot/dts/imx35-pinfunc.h
new file mode 100644
index 0000000..4911f2c
--- /dev/null
+++ b/arch/arm/boot/dts/imx35-pinfunc.h
@@ -0,0 +1,970 @@
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef __DTS_IMX35_PINFUNC_H
+#define __DTS_IMX35_PINFUNC_H
+
+/*
+ * The pin function ID is a tuple of
+ * <mux_reg conf_reg input_reg mux_mode input_val>
+ */
+#define MX35_PAD_CAPTURE__GPT_CAPIN1				0x004 0x328 0x000 0x0 0x0
+#define MX35_PAD_CAPTURE__GPT_CMPOUT2				0x004 0x328 0x000 0x1 0x0
+#define MX35_PAD_CAPTURE__CSPI2_SS1				0x004 0x328 0x7f4 0x2 0x0
+#define MX35_PAD_CAPTURE__EPIT1_EPITO				0x004 0x328 0x000 0x3 0x0
+#define MX35_PAD_CAPTURE__CCM_CLK32K				0x004 0x328 0x7d0 0x4 0x0
+#define MX35_PAD_CAPTURE__GPIO1_4				0x004 0x328 0x850 0x5 0x0
+#define MX35_PAD_COMPARE__GPT_CMPOUT1				0x008 0x32c 0x000 0x0 0x0
+#define MX35_PAD_COMPARE__GPT_CAPIN2				0x008 0x32c 0x000 0x1 0x0
+#define MX35_PAD_COMPARE__GPT_CMPOUT3				0x008 0x32c 0x000 0x2 0x0
+#define MX35_PAD_COMPARE__EPIT2_EPITO				0x008 0x32c 0x000 0x3 0x0
+#define MX35_PAD_COMPARE__GPIO1_5				0x008 0x32c 0x854 0x5 0x0
+#define MX35_PAD_COMPARE__SDMA_EXTDMA_2				0x008 0x32c 0x000 0x7 0x0
+#define MX35_PAD_WDOG_RST__WDOG_WDOG_B				0x00c 0x330 0x000 0x0 0x0
+#define MX35_PAD_WDOG_RST__IPU_FLASH_STROBE			0x00c 0x330 0x000 0x3 0x0
+#define MX35_PAD_WDOG_RST__GPIO1_6				0x00c 0x330 0x858 0x5 0x0
+#define MX35_PAD_GPIO1_0__GPIO1_0				0x010 0x334 0x82c 0x0 0x0
+#define MX35_PAD_GPIO1_0__CCM_PMIC_RDY				0x010 0x334 0x7d4 0x1 0x0
+#define MX35_PAD_GPIO1_0__OWIRE_LINE				0x010 0x334 0x990 0x2 0x0
+#define MX35_PAD_GPIO1_0__SDMA_EXTDMA_0				0x010 0x334 0x000 0x7 0x0
+#define MX35_PAD_GPIO1_1__GPIO1_1				0x014 0x338 0x838 0x0 0x0
+#define MX35_PAD_GPIO1_1__PWM_PWMO				0x014 0x338 0x000 0x2 0x0
+#define MX35_PAD_GPIO1_1__CSPI1_SS2				0x014 0x338 0x7d8 0x3 0x0
+#define MX35_PAD_GPIO1_1__SCC_TAMPER_DETECT			0x014 0x338 0x000 0x6 0x0
+#define MX35_PAD_GPIO1_1__SDMA_EXTDMA_1				0x014 0x338 0x000 0x7 0x0
+#define MX35_PAD_GPIO2_0__GPIO2_0				0x018 0x33c 0x868 0x0 0x0
+#define MX35_PAD_GPIO2_0__USB_TOP_USBOTG_CLK			0x018 0x33c 0x000 0x1 0x0
+#define MX35_PAD_GPIO3_0__GPIO3_0				0x01c 0x340 0x8e8 0x0 0x0
+#define MX35_PAD_GPIO3_0__USB_TOP_USBH2_CLK			0x01c 0x340 0x000 0x1 0x0
+#define MX35_PAD_RESET_IN_B__CCM_RESET_IN_B			0x000 0x344 0x000 0x0 0x0
+#define MX35_PAD_POR_B__CCM_POR_B				0x000 0x348 0x000 0x0 0x0
+#define MX35_PAD_CLKO__CCM_CLKO					0x020 0x34c 0x000 0x0 0x0
+#define MX35_PAD_CLKO__GPIO1_8					0x020 0x34c 0x860 0x5 0x0
+#define MX35_PAD_BOOT_MODE0__CCM_BOOT_MODE_0			0x000 0x350 0x000 0x0 0x0
+#define MX35_PAD_BOOT_MODE1__CCM_BOOT_MODE_1			0x000 0x354 0x000 0x0 0x0
+#define MX35_PAD_CLK_MODE0__CCM_CLK_MODE_0			0x000 0x358 0x000 0x0 0x0
+#define MX35_PAD_CLK_MODE1__CCM_CLK_MODE_1			0x000 0x35c 0x000 0x0 0x0
+#define MX35_PAD_POWER_FAIL__CCM_DSM_WAKEUP_INT_26		0x000 0x360 0x000 0x0 0x0
+#define MX35_PAD_VSTBY__CCM_VSTBY				0x024 0x364 0x000 0x0 0x0
+#define MX35_PAD_VSTBY__GPIO1_7					0x024 0x364 0x85c 0x5 0x0
+#define MX35_PAD_A0__EMI_EIM_DA_L_0				0x028 0x368 0x000 0x0 0x0
+#define MX35_PAD_A1__EMI_EIM_DA_L_1				0x02c 0x36c 0x000 0x0 0x0
+#define MX35_PAD_A2__EMI_EIM_DA_L_2				0x030 0x370 0x000 0x0 0x0
+#define MX35_PAD_A3__EMI_EIM_DA_L_3				0x034 0x374 0x000 0x0 0x0
+#define MX35_PAD_A4__EMI_EIM_DA_L_4				0x038 0x378 0x000 0x0 0x0
+#define MX35_PAD_A5__EMI_EIM_DA_L_5				0x03c 0x37c 0x000 0x0 0x0
+#define MX35_PAD_A6__EMI_EIM_DA_L_6				0x040 0x380 0x000 0x0 0x0
+#define MX35_PAD_A7__EMI_EIM_DA_L_7				0x044 0x384 0x000 0x0 0x0
+#define MX35_PAD_A8__EMI_EIM_DA_H_8				0x048 0x388 0x000 0x0 0x0
+#define MX35_PAD_A9__EMI_EIM_DA_H_9				0x04c 0x38c 0x000 0x0 0x0
+#define MX35_PAD_A10__EMI_EIM_DA_H_10				0x050 0x390 0x000 0x0 0x0
+#define MX35_PAD_MA10__EMI_MA10					0x054 0x394 0x000 0x0 0x0
+#define MX35_PAD_A11__EMI_EIM_DA_H_11				0x058 0x398 0x000 0x0 0x0
+#define MX35_PAD_A12__EMI_EIM_DA_H_12				0x05c 0x39c 0x000 0x0 0x0
+#define MX35_PAD_A13__EMI_EIM_DA_H_13				0x060 0x3a0 0x000 0x0 0x0
+#define MX35_PAD_A14__EMI_EIM_DA_H2_14				0x064 0x3a4 0x000 0x0 0x0
+#define MX35_PAD_A15__EMI_EIM_DA_H2_15				0x068 0x3a8 0x000 0x0 0x0
+#define MX35_PAD_A16__EMI_EIM_A_16				0x06c 0x3ac 0x000 0x0 0x0
+#define MX35_PAD_A17__EMI_EIM_A_17				0x070 0x3b0 0x000 0x0 0x0
+#define MX35_PAD_A18__EMI_EIM_A_18				0x074 0x3b4 0x000 0x0 0x0
+#define MX35_PAD_A19__EMI_EIM_A_19				0x078 0x3b8 0x000 0x0 0x0
+#define MX35_PAD_A20__EMI_EIM_A_20				0x07c 0x3bc 0x000 0x0 0x0
+#define MX35_PAD_A21__EMI_EIM_A_21				0x080 0x3c0 0x000 0x0 0x0
+#define MX35_PAD_A22__EMI_EIM_A_22				0x084 0x3c4 0x000 0x0 0x0
+#define MX35_PAD_A23__EMI_EIM_A_23				0x088 0x3c8 0x000 0x0 0x0
+#define MX35_PAD_A24__EMI_EIM_A_24				0x08c 0x3cc 0x000 0x0 0x0
+#define MX35_PAD_A25__EMI_EIM_A_25				0x090 0x3d0 0x000 0x0 0x0
+#define MX35_PAD_SDBA1__EMI_EIM_SDBA1				0x000 0x3d4 0x000 0x0 0x0
+#define MX35_PAD_SDBA0__EMI_EIM_SDBA0				0x000 0x3d8 0x000 0x0 0x0
+#define MX35_PAD_SD0__EMI_DRAM_D_0				0x000 0x3dc 0x000 0x0 0x0
+#define MX35_PAD_SD1__EMI_DRAM_D_1				0x000 0x3e0 0x000 0x0 0x0
+#define MX35_PAD_SD2__EMI_DRAM_D_2				0x000 0x3e4 0x000 0x0 0x0
+#define MX35_PAD_SD3__EMI_DRAM_D_3				0x000 0x3e8 0x000 0x0 0x0
+#define MX35_PAD_SD4__EMI_DRAM_D_4				0x000 0x3ec 0x000 0x0 0x0
+#define MX35_PAD_SD5__EMI_DRAM_D_5				0x000 0x3f0 0x000 0x0 0x0
+#define MX35_PAD_SD6__EMI_DRAM_D_6				0x000 0x3f4 0x000 0x0 0x0
+#define MX35_PAD_SD7__EMI_DRAM_D_7				0x000 0x3f8 0x000 0x0 0x0
+#define MX35_PAD_SD8__EMI_DRAM_D_8				0x000 0x3fc 0x000 0x0 0x0
+#define MX35_PAD_SD9__EMI_DRAM_D_9				0x000 0x400 0x000 0x0 0x0
+#define MX35_PAD_SD10__EMI_DRAM_D_10				0x000 0x404 0x000 0x0 0x0
+#define MX35_PAD_SD11__EMI_DRAM_D_11				0x000 0x408 0x000 0x0 0x0
+#define MX35_PAD_SD12__EMI_DRAM_D_12				0x000 0x40c 0x000 0x0 0x0
+#define MX35_PAD_SD13__EMI_DRAM_D_13				0x000 0x410 0x000 0x0 0x0
+#define MX35_PAD_SD14__EMI_DRAM_D_14				0x000 0x414 0x000 0x0 0x0
+#define MX35_PAD_SD15__EMI_DRAM_D_15				0x000 0x418 0x000 0x0 0x0
+#define MX35_PAD_SD16__EMI_DRAM_D_16				0x000 0x41c 0x000 0x0 0x0
+#define MX35_PAD_SD17__EMI_DRAM_D_17				0x000 0x420 0x000 0x0 0x0
+#define MX35_PAD_SD18__EMI_DRAM_D_18				0x000 0x424 0x000 0x0 0x0
+#define MX35_PAD_SD19__EMI_DRAM_D_19				0x000 0x428 0x000 0x0 0x0
+#define MX35_PAD_SD20__EMI_DRAM_D_20				0x000 0x42c 0x000 0x0 0x0
+#define MX35_PAD_SD21__EMI_DRAM_D_21				0x000 0x430 0x000 0x0 0x0
+#define MX35_PAD_SD22__EMI_DRAM_D_22				0x000 0x434 0x000 0x0 0x0
+#define MX35_PAD_SD23__EMI_DRAM_D_23				0x000 0x438 0x000 0x0 0x0
+#define MX35_PAD_SD24__EMI_DRAM_D_24				0x000 0x43c 0x000 0x0 0x0
+#define MX35_PAD_SD25__EMI_DRAM_D_25				0x000 0x440 0x000 0x0 0x0
+#define MX35_PAD_SD26__EMI_DRAM_D_26				0x000 0x444 0x000 0x0 0x0
+#define MX35_PAD_SD27__EMI_DRAM_D_27				0x000 0x448 0x000 0x0 0x0
+#define MX35_PAD_SD28__EMI_DRAM_D_28				0x000 0x44c 0x000 0x0 0x0
+#define MX35_PAD_SD29__EMI_DRAM_D_29				0x000 0x450 0x000 0x0 0x0
+#define MX35_PAD_SD30__EMI_DRAM_D_30				0x000 0x454 0x000 0x0 0x0
+#define MX35_PAD_SD31__EMI_DRAM_D_31				0x000 0x458 0x000 0x0 0x0
+#define MX35_PAD_DQM0__EMI_DRAM_DQM_0				0x000 0x45c 0x000 0x0 0x0
+#define MX35_PAD_DQM1__EMI_DRAM_DQM_1				0x000 0x460 0x000 0x0 0x0
+#define MX35_PAD_DQM2__EMI_DRAM_DQM_2				0x000 0x464 0x000 0x0 0x0
+#define MX35_PAD_DQM3__EMI_DRAM_DQM_3				0x000 0x468 0x000 0x0 0x0
+#define MX35_PAD_EB0__EMI_EIM_EB0_B				0x094 0x46c 0x000 0x0 0x0
+#define MX35_PAD_EB1__EMI_EIM_EB1_B				0x098 0x470 0x000 0x0 0x0
+#define MX35_PAD_OE__EMI_EIM_OE					0x09c 0x474 0x000 0x0 0x0
+#define MX35_PAD_CS0__EMI_EIM_CS0				0x0a0 0x478 0x000 0x0 0x0
+#define MX35_PAD_CS1__EMI_EIM_CS1				0x0a4 0x47c 0x000 0x0 0x0
+#define MX35_PAD_CS1__EMI_NANDF_CE3				0x0a4 0x47c 0x000 0x3 0x0
+#define MX35_PAD_CS2__EMI_EIM_CS2				0x0a8 0x480 0x000 0x0 0x0
+#define MX35_PAD_CS3__EMI_EIM_CS3				0x0ac 0x484 0x000 0x0 0x0
+#define MX35_PAD_CS4__EMI_EIM_CS4				0x0b0 0x488 0x000 0x0 0x0
+#define MX35_PAD_CS4__EMI_DTACK_B				0x0b0 0x488 0x800 0x1 0x0
+#define MX35_PAD_CS4__EMI_NANDF_CE1				0x0b0 0x488 0x000 0x3 0x0
+#define MX35_PAD_CS4__GPIO1_20					0x0b0 0x488 0x83c 0x5 0x0
+#define MX35_PAD_CS5__EMI_EIM_CS5				0x0b4 0x48c 0x000 0x0 0x0
+#define MX35_PAD_CS5__CSPI2_SS2					0x0b4 0x48c 0x7f8 0x1 0x0
+#define MX35_PAD_CS5__CSPI1_SS2					0x0b4 0x48c 0x7d8 0x2 0x1
+#define MX35_PAD_CS5__EMI_NANDF_CE2				0x0b4 0x48c 0x000 0x3 0x0
+#define MX35_PAD_CS5__GPIO1_21					0x0b4 0x48c 0x840 0x5 0x0
+#define MX35_PAD_NF_CE0__EMI_NANDF_CE0				0x0b8 0x490 0x000 0x0 0x0
+#define MX35_PAD_NF_CE0__GPIO1_22				0x0b8 0x490 0x844 0x5 0x0
+#define MX35_PAD_ECB__EMI_EIM_ECB				0x000 0x494 0x000 0x0 0x0
+#define MX35_PAD_LBA__EMI_EIM_LBA				0x0bc 0x498 0x000 0x0 0x0
+#define MX35_PAD_BCLK__EMI_EIM_BCLK				0x0c0 0x49c 0x000 0x0 0x0
+#define MX35_PAD_RW__EMI_EIM_RW					0x0c4 0x4a0 0x000 0x0 0x0
+#define MX35_PAD_RAS__EMI_DRAM_RAS				0x000 0x4a4 0x000 0x0 0x0
+#define MX35_PAD_CAS__EMI_DRAM_CAS				0x000 0x4a8 0x000 0x0 0x0
+#define MX35_PAD_SDWE__EMI_DRAM_SDWE				0x000 0x4ac 0x000 0x0 0x0
+#define MX35_PAD_SDCKE0__EMI_DRAM_SDCKE_0			0x000 0x4b0 0x000 0x0 0x0
+#define MX35_PAD_SDCKE1__EMI_DRAM_SDCKE_1			0x000 0x4b4 0x000 0x0 0x0
+#define MX35_PAD_SDCLK__EMI_DRAM_SDCLK				0x000 0x4b8 0x000 0x0 0x0
+#define MX35_PAD_SDQS0__EMI_DRAM_SDQS_0				0x000 0x4bc 0x000 0x0 0x0
+#define MX35_PAD_SDQS1__EMI_DRAM_SDQS_1				0x000 0x4c0 0x000 0x0 0x0
+#define MX35_PAD_SDQS2__EMI_DRAM_SDQS_2				0x000 0x4c4 0x000 0x0 0x0
+#define MX35_PAD_SDQS3__EMI_DRAM_SDQS_3				0x000 0x4c8 0x000 0x0 0x0
+#define MX35_PAD_NFWE_B__EMI_NANDF_WE_B				0x0c8 0x4cc 0x000 0x0 0x0
+#define MX35_PAD_NFWE_B__USB_TOP_USBH2_DATA_3			0x0c8 0x4cc 0x9d8 0x1 0x0
+#define MX35_PAD_NFWE_B__IPU_DISPB_D0_VSYNC			0x0c8 0x4cc 0x924 0x2 0x0
+#define MX35_PAD_NFWE_B__GPIO2_18				0x0c8 0x4cc 0x88c 0x5 0x0
+#define MX35_PAD_NFWE_B__ARM11P_TOP_TRACE_0			0x0c8 0x4cc 0x000 0x7 0x0
+#define MX35_PAD_NFRE_B__EMI_NANDF_RE_B				0x0cc 0x4d0 0x000 0x0 0x0
+#define MX35_PAD_NFRE_B__USB_TOP_USBH2_DIR			0x0cc 0x4d0 0x9ec 0x1 0x0
+#define MX35_PAD_NFRE_B__IPU_DISPB_BCLK				0x0cc 0x4d0 0x000 0x2 0x0
+#define MX35_PAD_NFRE_B__GPIO2_19				0x0cc 0x4d0 0x890 0x5 0x0
+#define MX35_PAD_NFRE_B__ARM11P_TOP_TRACE_1			0x0cc 0x4d0 0x000 0x7 0x0
+#define MX35_PAD_NFALE__EMI_NANDF_ALE				0x0d0 0x4d4 0x000 0x0 0x0
+#define MX35_PAD_NFALE__USB_TOP_USBH2_STP			0x0d0 0x4d4 0x000 0x1 0x0
+#define MX35_PAD_NFALE__IPU_DISPB_CS0				0x0d0 0x4d4 0x000 0x2 0x0
+#define MX35_PAD_NFALE__GPIO2_20				0x0d0 0x4d4 0x898 0x5 0x0
+#define MX35_PAD_NFALE__ARM11P_TOP_TRACE_2			0x0d0 0x4d4 0x000 0x7 0x0
+#define MX35_PAD_NFCLE__EMI_NANDF_CLE				0x0d4 0x4d8 0x000 0x0 0x0
+#define MX35_PAD_NFCLE__USB_TOP_USBH2_NXT			0x0d4 0x4d8 0x9f0 0x1 0x0
+#define MX35_PAD_NFCLE__IPU_DISPB_PAR_RS			0x0d4 0x4d8 0x000 0x2 0x0
+#define MX35_PAD_NFCLE__GPIO2_21				0x0d4 0x4d8 0x89c 0x5 0x0
+#define MX35_PAD_NFCLE__ARM11P_TOP_TRACE_3			0x0d4 0x4d8 0x000 0x7 0x0
+#define MX35_PAD_NFWP_B__EMI_NANDF_WP_B				0x0d8 0x4dc 0x000 0x0 0x0
+#define MX35_PAD_NFWP_B__USB_TOP_USBH2_DATA_7			0x0d8 0x4dc 0x9e8 0x1 0x0
+#define MX35_PAD_NFWP_B__IPU_DISPB_WR				0x0d8 0x4dc 0x000 0x2 0x0
+#define MX35_PAD_NFWP_B__GPIO2_22				0x0d8 0x4dc 0x8a0 0x5 0x0
+#define MX35_PAD_NFWP_B__ARM11P_TOP_TRCTL			0x0d8 0x4dc 0x000 0x7 0x0
+#define MX35_PAD_NFRB__EMI_NANDF_RB				0x0dc 0x4e0 0x000 0x0 0x0
+#define MX35_PAD_NFRB__IPU_DISPB_RD				0x0dc 0x4e0 0x000 0x2 0x0
+#define MX35_PAD_NFRB__GPIO2_23					0x0dc 0x4e0 0x8a4 0x5 0x0
+#define MX35_PAD_NFRB__ARM11P_TOP_TRCLK				0x0dc 0x4e0 0x000 0x7 0x0
+#define MX35_PAD_D15__EMI_EIM_D_15				0x000 0x4e4 0x000 0x0 0x0
+#define MX35_PAD_D14__EMI_EIM_D_14				0x000 0x4e8 0x000 0x0 0x0
+#define MX35_PAD_D13__EMI_EIM_D_13				0x000 0x4ec 0x000 0x0 0x0
+#define MX35_PAD_D12__EMI_EIM_D_12				0x000 0x4f0 0x000 0x0 0x0
+#define MX35_PAD_D11__EMI_EIM_D_11				0x000 0x4f4 0x000 0x0 0x0
+#define MX35_PAD_D10__EMI_EIM_D_10				0x000 0x4f8 0x000 0x0 0x0
+#define MX35_PAD_D9__EMI_EIM_D_9				0x000 0x4fc 0x000 0x0 0x0
+#define MX35_PAD_D8__EMI_EIM_D_8				0x000 0x500 0x000 0x0 0x0
+#define MX35_PAD_D7__EMI_EIM_D_7				0x000 0x504 0x000 0x0 0x0
+#define MX35_PAD_D6__EMI_EIM_D_6				0x000 0x508 0x000 0x0 0x0
+#define MX35_PAD_D5__EMI_EIM_D_5				0x000 0x50c 0x000 0x0 0x0
+#define MX35_PAD_D4__EMI_EIM_D_4				0x000 0x510 0x000 0x0 0x0
+#define MX35_PAD_D3__EMI_EIM_D_3				0x000 0x514 0x000 0x0 0x0
+#define MX35_PAD_D2__EMI_EIM_D_2				0x000 0x518 0x000 0x0 0x0
+#define MX35_PAD_D1__EMI_EIM_D_1				0x000 0x51c 0x000 0x0 0x0
+#define MX35_PAD_D0__EMI_EIM_D_0				0x000 0x520 0x000 0x0 0x0
+#define MX35_PAD_CSI_D8__IPU_CSI_D_8				0x0e0 0x524 0x000 0x0 0x0
+#define MX35_PAD_CSI_D8__KPP_COL_0				0x0e0 0x524 0x950 0x1 0x0
+#define MX35_PAD_CSI_D8__GPIO1_20				0x0e0 0x524 0x83c 0x5 0x1
+#define MX35_PAD_CSI_D8__ARM11P_TOP_EVNTBUS_13			0x0e0 0x524 0x000 0x7 0x0
+#define MX35_PAD_CSI_D9__IPU_CSI_D_9				0x0e4 0x528 0x000 0x0 0x0
+#define MX35_PAD_CSI_D9__KPP_COL_1				0x0e4 0x528 0x954 0x1 0x0
+#define MX35_PAD_CSI_D9__GPIO1_21				0x0e4 0x528 0x840 0x5 0x1
+#define MX35_PAD_CSI_D9__ARM11P_TOP_EVNTBUS_14			0x0e4 0x528 0x000 0x7 0x0
+#define MX35_PAD_CSI_D10__IPU_CSI_D_10				0x0e8 0x52c 0x000 0x0 0x0
+#define MX35_PAD_CSI_D10__KPP_COL_2				0x0e8 0x52c 0x958 0x1 0x0
+#define MX35_PAD_CSI_D10__GPIO1_22				0x0e8 0x52c 0x844 0x5 0x1
+#define MX35_PAD_CSI_D10__ARM11P_TOP_EVNTBUS_15			0x0e8 0x52c 0x000 0x7 0x0
+#define MX35_PAD_CSI_D11__IPU_CSI_D_11				0x0ec 0x530 0x000 0x0 0x0
+#define MX35_PAD_CSI_D11__KPP_COL_3				0x0ec 0x530 0x95c 0x1 0x0
+#define MX35_PAD_CSI_D11__GPIO1_23				0x0ec 0x530 0x000 0x5 0x0
+#define MX35_PAD_CSI_D12__IPU_CSI_D_12				0x0f0 0x534 0x000 0x0 0x0
+#define MX35_PAD_CSI_D12__KPP_ROW_0				0x0f0 0x534 0x970 0x1 0x0
+#define MX35_PAD_CSI_D12__GPIO1_24				0x0f0 0x534 0x000 0x5 0x0
+#define MX35_PAD_CSI_D13__IPU_CSI_D_13				0x0f4 0x538 0x000 0x0 0x0
+#define MX35_PAD_CSI_D13__KPP_ROW_1				0x0f4 0x538 0x974 0x1 0x0
+#define MX35_PAD_CSI_D13__GPIO1_25				0x0f4 0x538 0x000 0x5 0x0
+#define MX35_PAD_CSI_D14__IPU_CSI_D_14				0x0f8 0x53c 0x000 0x0 0x0
+#define MX35_PAD_CSI_D14__KPP_ROW_2				0x0f8 0x53c 0x978 0x1 0x0
+#define MX35_PAD_CSI_D14__GPIO1_26				0x0f8 0x53c 0x000 0x5 0x0
+#define MX35_PAD_CSI_D15__IPU_CSI_D_15				0x0fc 0x540 0x97c 0x0 0x0
+#define MX35_PAD_CSI_D15__KPP_ROW_3				0x0fc 0x540 0x000 0x1 0x0
+#define MX35_PAD_CSI_D15__GPIO1_27				0x0fc 0x540 0x000 0x5 0x0
+#define MX35_PAD_CSI_MCLK__IPU_CSI_MCLK				0x100 0x544 0x000 0x0 0x0
+#define MX35_PAD_CSI_MCLK__GPIO1_28				0x100 0x544 0x000 0x5 0x0
+#define MX35_PAD_CSI_VSYNC__IPU_CSI_VSYNC			0x104 0x548 0x000 0x0 0x0
+#define MX35_PAD_CSI_VSYNC__GPIO1_29				0x104 0x548 0x000 0x5 0x0
+#define MX35_PAD_CSI_HSYNC__IPU_CSI_HSYNC			0x108 0x54c 0x000 0x0 0x0
+#define MX35_PAD_CSI_HSYNC__GPIO1_30				0x108 0x54c 0x000 0x5 0x0
+#define MX35_PAD_CSI_PIXCLK__IPU_CSI_PIXCLK			0x10c 0x550 0x000 0x0 0x0
+#define MX35_PAD_CSI_PIXCLK__GPIO1_31				0x10c 0x550 0x000 0x5 0x0
+#define MX35_PAD_I2C1_CLK__I2C1_SCL				0x110 0x554 0x000 0x0 0x0
+#define MX35_PAD_I2C1_CLK__GPIO2_24				0x110 0x554 0x8a8 0x5 0x0
+#define MX35_PAD_I2C1_CLK__CCM_USB_BYP_CLK			0x110 0x554 0x000 0x6 0x0
+#define MX35_PAD_I2C1_DAT__I2C1_SDA				0x114 0x558 0x000 0x0 0x0
+#define MX35_PAD_I2C1_DAT__GPIO2_25				0x114 0x558 0x8ac 0x5 0x0
+#define MX35_PAD_I2C2_CLK__I2C2_SCL				0x118 0x55c 0x000 0x0 0x0
+#define MX35_PAD_I2C2_CLK__CAN1_TXCAN				0x118 0x55c 0x000 0x1 0x0
+#define MX35_PAD_I2C2_CLK__USB_TOP_USBH2_PWR			0x118 0x55c 0x000 0x2 0x0
+#define MX35_PAD_I2C2_CLK__GPIO2_26				0x118 0x55c 0x8b0 0x5 0x0
+#define MX35_PAD_I2C2_CLK__SDMA_DEBUG_BUS_DEVICE_2		0x118 0x55c 0x000 0x6 0x0
+#define MX35_PAD_I2C2_DAT__I2C2_SDA				0x11c 0x560 0x000 0x0 0x0
+#define MX35_PAD_I2C2_DAT__CAN1_RXCAN				0x11c 0x560 0x7c8 0x1 0x0
+#define MX35_PAD_I2C2_DAT__USB_TOP_USBH2_OC			0x11c 0x560 0x9f4 0x2 0x0
+#define MX35_PAD_I2C2_DAT__GPIO2_27				0x11c 0x560 0x8b4 0x5 0x0
+#define MX35_PAD_I2C2_DAT__SDMA_DEBUG_BUS_DEVICE_3		0x11c 0x560 0x000 0x6 0x0
+#define MX35_PAD_STXD4__AUDMUX_AUD4_TXD				0x120 0x564 0x000 0x0 0x0
+#define MX35_PAD_STXD4__GPIO2_28				0x120 0x564 0x8b8 0x5 0x0
+#define MX35_PAD_STXD4__ARM11P_TOP_ARM_COREASID0		0x120 0x564 0x000 0x7 0x0
+#define MX35_PAD_SRXD4__AUDMUX_AUD4_RXD				0x124 0x568 0x000 0x0 0x0
+#define MX35_PAD_SRXD4__GPIO2_29				0x124 0x568 0x8bc 0x5 0x0
+#define MX35_PAD_SRXD4__ARM11P_TOP_ARM_COREASID1		0x124 0x568 0x000 0x7 0x0
+#define MX35_PAD_SCK4__AUDMUX_AUD4_TXC				0x128 0x56c 0x000 0x0 0x0
+#define MX35_PAD_SCK4__GPIO2_30					0x128 0x56c 0x8c4 0x5 0x0
+#define MX35_PAD_SCK4__ARM11P_TOP_ARM_COREASID2			0x128 0x56c 0x000 0x7 0x0
+#define MX35_PAD_STXFS4__AUDMUX_AUD4_TXFS			0x12c 0x570 0x000 0x0 0x0
+#define MX35_PAD_STXFS4__GPIO2_31				0x12c 0x570 0x8c8 0x5 0x0
+#define MX35_PAD_STXFS4__ARM11P_TOP_ARM_COREASID3		0x12c 0x570 0x000 0x7 0x0
+#define MX35_PAD_STXD5__AUDMUX_AUD5_TXD				0x130 0x574 0x000 0x0 0x0
+#define MX35_PAD_STXD5__SPDIF_SPDIF_OUT1			0x130 0x574 0x000 0x1 0x0
+#define MX35_PAD_STXD5__CSPI2_MOSI				0x130 0x574 0x7ec 0x2 0x0
+#define MX35_PAD_STXD5__GPIO1_0					0x130 0x574 0x82c 0x5 0x1
+#define MX35_PAD_STXD5__ARM11P_TOP_ARM_COREASID4		0x130 0x574 0x000 0x7 0x0
+#define MX35_PAD_SRXD5__AUDMUX_AUD5_RXD				0x134 0x578 0x000 0x0 0x0
+#define MX35_PAD_SRXD5__SPDIF_SPDIF_IN1				0x134 0x578 0x998 0x1 0x0
+#define MX35_PAD_SRXD5__CSPI2_MISO				0x134 0x578 0x7e8 0x2 0x0
+#define MX35_PAD_SRXD5__GPIO1_1					0x134 0x578 0x838 0x5 0x1
+#define MX35_PAD_SRXD5__ARM11P_TOP_ARM_COREASID5		0x134 0x578 0x000 0x7 0x0
+#define MX35_PAD_SCK5__AUDMUX_AUD5_TXC				0x138 0x57c 0x000 0x0 0x0
+#define MX35_PAD_SCK5__SPDIF_SPDIF_EXTCLK			0x138 0x57c 0x994 0x1 0x0
+#define MX35_PAD_SCK5__CSPI2_SCLK				0x138 0x57c 0x7e0 0x2 0x0
+#define MX35_PAD_SCK5__GPIO1_2					0x138 0x57c 0x848 0x5 0x0
+#define MX35_PAD_SCK5__ARM11P_TOP_ARM_COREASID6			0x138 0x57c 0x000 0x7 0x0
+#define MX35_PAD_STXFS5__AUDMUX_AUD5_TXFS			0x13c 0x580 0x000 0x0 0x0
+#define MX35_PAD_STXFS5__CSPI2_RDY				0x13c 0x580 0x7e4 0x2 0x0
+#define MX35_PAD_STXFS5__GPIO1_3				0x13c 0x580 0x84c 0x5 0x0
+#define MX35_PAD_STXFS5__ARM11P_TOP_ARM_COREASID7		0x13c 0x580 0x000 0x7 0x0
+#define MX35_PAD_SCKR__ESAI_SCKR				0x140 0x584 0x000 0x0 0x0
+#define MX35_PAD_SCKR__GPIO1_4					0x140 0x584 0x850 0x5 0x1
+#define MX35_PAD_SCKR__ARM11P_TOP_EVNTBUS_10			0x140 0x584 0x000 0x7 0x0
+#define MX35_PAD_FSR__ESAI_FSR					0x144 0x588 0x000 0x0 0x0
+#define MX35_PAD_FSR__GPIO1_5					0x144 0x588 0x854 0x5 0x1
+#define MX35_PAD_FSR__ARM11P_TOP_EVNTBUS_11			0x144 0x588 0x000 0x7 0x0
+#define MX35_PAD_HCKR__ESAI_HCKR				0x148 0x58c 0x000 0x0 0x0
+#define MX35_PAD_HCKR__AUDMUX_AUD5_RXFS				0x148 0x58c 0x000 0x1 0x0
+#define MX35_PAD_HCKR__CSPI2_SS0				0x148 0x58c 0x7f0 0x2 0x0
+#define MX35_PAD_HCKR__IPU_FLASH_STROBE				0x148 0x58c 0x000 0x3 0x0
+#define MX35_PAD_HCKR__GPIO1_6					0x148 0x58c 0x858 0x5 0x1
+#define MX35_PAD_HCKR__ARM11P_TOP_EVNTBUS_12			0x148 0x58c 0x000 0x7 0x0
+#define MX35_PAD_SCKT__ESAI_SCKT				0x14c 0x590 0x000 0x0 0x0
+#define MX35_PAD_SCKT__GPIO1_7					0x14c 0x590 0x85c 0x5 0x1
+#define MX35_PAD_SCKT__IPU_CSI_D_0				0x14c 0x590 0x930 0x6 0x0
+#define MX35_PAD_SCKT__KPP_ROW_2				0x14c 0x590 0x978 0x7 0x1
+#define MX35_PAD_FST__ESAI_FST					0x150 0x594 0x000 0x0 0x0
+#define MX35_PAD_FST__GPIO1_8					0x150 0x594 0x860 0x5 0x1
+#define MX35_PAD_FST__IPU_CSI_D_1				0x150 0x594 0x934 0x6 0x0
+#define MX35_PAD_FST__KPP_ROW_3					0x150 0x594 0x97c 0x7 0x1
+#define MX35_PAD_HCKT__ESAI_HCKT				0x154 0x598 0x000 0x0 0x0
+#define MX35_PAD_HCKT__AUDMUX_AUD5_RXC				0x154 0x598 0x7a8 0x1 0x0
+#define MX35_PAD_HCKT__GPIO1_9					0x154 0x598 0x864 0x5 0x0
+#define MX35_PAD_HCKT__IPU_CSI_D_2				0x154 0x598 0x938 0x6 0x0
+#define MX35_PAD_HCKT__KPP_COL_3				0x154 0x598 0x95c 0x7 0x1
+#define MX35_PAD_TX5_RX0__ESAI_TX5_RX0				0x158 0x59c 0x000 0x0 0x0
+#define MX35_PAD_TX5_RX0__AUDMUX_AUD4_RXC			0x158 0x59c 0x000 0x1 0x0
+#define MX35_PAD_TX5_RX0__CSPI2_SS2				0x158 0x59c 0x7f8 0x2 0x1
+#define MX35_PAD_TX5_RX0__CAN2_TXCAN				0x158 0x59c 0x000 0x3 0x0
+#define MX35_PAD_TX5_RX0__UART2_DTR				0x158 0x59c 0x000 0x4 0x0
+#define MX35_PAD_TX5_RX0__GPIO1_10				0x158 0x59c 0x830 0x5 0x0
+#define MX35_PAD_TX5_RX0__EMI_M3IF_CHOSEN_MASTER_0		0x158 0x59c 0x000 0x7 0x0
+#define MX35_PAD_TX4_RX1__ESAI_TX4_RX1				0x15c 0x5a0 0x000 0x0 0x0
+#define MX35_PAD_TX4_RX1__AUDMUX_AUD4_RXFS			0x15c 0x5a0 0x000 0x1 0x0
+#define MX35_PAD_TX4_RX1__CSPI2_SS3				0x15c 0x5a0 0x7fc 0x2 0x0
+#define MX35_PAD_TX4_RX1__CAN2_RXCAN				0x15c 0x5a0 0x7cc 0x3 0x0
+#define MX35_PAD_TX4_RX1__UART2_DSR				0x15c 0x5a0 0x000 0x4 0x0
+#define MX35_PAD_TX4_RX1__GPIO1_11				0x15c 0x5a0 0x834 0x5 0x0
+#define MX35_PAD_TX4_RX1__IPU_CSI_D_3				0x15c 0x5a0 0x93c 0x6 0x0
+#define MX35_PAD_TX4_RX1__KPP_ROW_0				0x15c 0x5a0 0x970 0x7 0x1
+#define MX35_PAD_TX3_RX2__ESAI_TX3_RX2				0x160 0x5a4 0x000 0x0 0x0
+#define MX35_PAD_TX3_RX2__I2C3_SCL				0x160 0x5a4 0x91c 0x1 0x0
+#define MX35_PAD_TX3_RX2__EMI_NANDF_CE1				0x160 0x5a4 0x000 0x3 0x0
+#define MX35_PAD_TX3_RX2__GPIO1_12				0x160 0x5a4 0x000 0x5 0x0
+#define MX35_PAD_TX3_RX2__IPU_CSI_D_4				0x160 0x5a4 0x940 0x6 0x0
+#define MX35_PAD_TX3_RX2__KPP_ROW_1				0x160 0x5a4 0x974 0x7 0x1
+#define MX35_PAD_TX2_RX3__ESAI_TX2_RX3				0x164 0x5a8 0x000 0x0 0x0
+#define MX35_PAD_TX2_RX3__I2C3_SDA				0x164 0x5a8 0x920 0x1 0x0
+#define MX35_PAD_TX2_RX3__EMI_NANDF_CE2				0x164 0x5a8 0x000 0x3 0x0
+#define MX35_PAD_TX2_RX3__GPIO1_13				0x164 0x5a8 0x000 0x5 0x0
+#define MX35_PAD_TX2_RX3__IPU_CSI_D_5				0x164 0x5a8 0x944 0x6 0x0
+#define MX35_PAD_TX2_RX3__KPP_COL_0				0x164 0x5a8 0x950 0x7 0x1
+#define MX35_PAD_TX1__ESAI_TX1					0x168 0x5ac 0x000 0x0 0x0
+#define MX35_PAD_TX1__CCM_PMIC_RDY				0x168 0x5ac 0x7d4 0x1 0x1
+#define MX35_PAD_TX1__CSPI1_SS2					0x168 0x5ac 0x7d8 0x2 0x2
+#define MX35_PAD_TX1__EMI_NANDF_CE3				0x168 0x5ac 0x000 0x3 0x0
+#define MX35_PAD_TX1__UART2_RI					0x168 0x5ac 0x000 0x4 0x0
+#define MX35_PAD_TX1__GPIO1_14					0x168 0x5ac 0x000 0x5 0x0
+#define MX35_PAD_TX1__IPU_CSI_D_6				0x168 0x5ac 0x948 0x6 0x0
+#define MX35_PAD_TX1__KPP_COL_1					0x168 0x5ac 0x954 0x7 0x1
+#define MX35_PAD_TX0__ESAI_TX0					0x16c 0x5b0 0x000 0x0 0x0
+#define MX35_PAD_TX0__SPDIF_SPDIF_EXTCLK			0x16c 0x5b0 0x994 0x1 0x1
+#define MX35_PAD_TX0__CSPI1_SS3					0x16c 0x5b0 0x7dc 0x2 0x0
+#define MX35_PAD_TX0__EMI_DTACK_B				0x16c 0x5b0 0x800 0x3 0x1
+#define MX35_PAD_TX0__UART2_DCD					0x16c 0x5b0 0x000 0x4 0x0
+#define MX35_PAD_TX0__GPIO1_15					0x16c 0x5b0 0x000 0x5 0x0
+#define MX35_PAD_TX0__IPU_CSI_D_7				0x16c 0x5b0 0x94c 0x6 0x0
+#define MX35_PAD_TX0__KPP_COL_2					0x16c 0x5b0 0x958 0x7 0x1
+#define MX35_PAD_CSPI1_MOSI__CSPI1_MOSI				0x170 0x5b4 0x000 0x0 0x0
+#define MX35_PAD_CSPI1_MOSI__GPIO1_16				0x170 0x5b4 0x000 0x5 0x0
+#define MX35_PAD_CSPI1_MOSI__ECT_CTI_TRIG_OUT1_2		0x170 0x5b4 0x000 0x7 0x0
+#define MX35_PAD_CSPI1_MISO__CSPI1_MISO				0x174 0x5b8 0x000 0x0 0x0
+#define MX35_PAD_CSPI1_MISO__GPIO1_17				0x174 0x5b8 0x000 0x5 0x0
+#define MX35_PAD_CSPI1_MISO__ECT_CTI_TRIG_OUT1_3		0x174 0x5b8 0x000 0x7 0x0
+#define MX35_PAD_CSPI1_SS0__CSPI1_SS0				0x178 0x5bc 0x000 0x0 0x0
+#define MX35_PAD_CSPI1_SS0__OWIRE_LINE				0x178 0x5bc 0x990 0x1 0x1
+#define MX35_PAD_CSPI1_SS0__CSPI2_SS3				0x178 0x5bc 0x7fc 0x2 0x1
+#define MX35_PAD_CSPI1_SS0__GPIO1_18				0x178 0x5bc 0x000 0x5 0x0
+#define MX35_PAD_CSPI1_SS0__ECT_CTI_TRIG_OUT1_4			0x178 0x5bc 0x000 0x7 0x0
+#define MX35_PAD_CSPI1_SS1__CSPI1_SS1				0x17c 0x5c0 0x000 0x0 0x0
+#define MX35_PAD_CSPI1_SS1__PWM_PWMO				0x17c 0x5c0 0x000 0x1 0x0
+#define MX35_PAD_CSPI1_SS1__CCM_CLK32K				0x17c 0x5c0 0x7d0 0x2 0x1
+#define MX35_PAD_CSPI1_SS1__GPIO1_19				0x17c 0x5c0 0x000 0x5 0x0
+#define MX35_PAD_CSPI1_SS1__IPU_DIAGB_29			0x17c 0x5c0 0x000 0x6 0x0
+#define MX35_PAD_CSPI1_SS1__ECT_CTI_TRIG_OUT1_5			0x17c 0x5c0 0x000 0x7 0x0
+#define MX35_PAD_CSPI1_SCLK__CSPI1_SCLK				0x180 0x5c4 0x000 0x0 0x0
+#define MX35_PAD_CSPI1_SCLK__GPIO3_4				0x180 0x5c4 0x904 0x5 0x0
+#define MX35_PAD_CSPI1_SCLK__IPU_DIAGB_30			0x180 0x5c4 0x000 0x6 0x0
+#define MX35_PAD_CSPI1_SCLK__EMI_M3IF_CHOSEN_MASTER_1		0x180 0x5c4 0x000 0x7 0x0
+#define MX35_PAD_CSPI1_SPI_RDY__CSPI1_RDY			0x184 0x5c8 0x000 0x0 0x0
+#define MX35_PAD_CSPI1_SPI_RDY__GPIO3_5				0x184 0x5c8 0x908 0x5 0x0
+#define MX35_PAD_CSPI1_SPI_RDY__IPU_DIAGB_31			0x184 0x5c8 0x000 0x6 0x0
+#define MX35_PAD_CSPI1_SPI_RDY__EMI_M3IF_CHOSEN_MASTER_2	0x184 0x5c8 0x000 0x7 0x0
+#define MX35_PAD_RXD1__UART1_RXD_MUX				0x188 0x5cc 0x000 0x0 0x0
+#define MX35_PAD_RXD1__CSPI2_MOSI				0x188 0x5cc 0x7ec 0x1 0x1
+#define MX35_PAD_RXD1__KPP_COL_4				0x188 0x5cc 0x960 0x4 0x0
+#define MX35_PAD_RXD1__GPIO3_6					0x188 0x5cc 0x90c 0x5 0x0
+#define MX35_PAD_RXD1__ARM11P_TOP_EVNTBUS_16			0x188 0x5cc 0x000 0x7 0x0
+#define MX35_PAD_TXD1__UART1_TXD_MUX				0x18c 0x5d0 0x000 0x0 0x0
+#define MX35_PAD_TXD1__CSPI2_MISO				0x18c 0x5d0 0x7e8 0x1 0x1
+#define MX35_PAD_TXD1__KPP_COL_5				0x18c 0x5d0 0x964 0x4 0x0
+#define MX35_PAD_TXD1__GPIO3_7					0x18c 0x5d0 0x910 0x5 0x0
+#define MX35_PAD_TXD1__ARM11P_TOP_EVNTBUS_17			0x18c 0x5d0 0x000 0x7 0x0
+#define MX35_PAD_RTS1__UART1_RTS				0x190 0x5d4 0x000 0x0 0x0
+#define MX35_PAD_RTS1__CSPI2_SCLK				0x190 0x5d4 0x7e0 0x1 0x1
+#define MX35_PAD_RTS1__I2C3_SCL					0x190 0x5d4 0x91c 0x2 0x1
+#define MX35_PAD_RTS1__IPU_CSI_D_0				0x190 0x5d4 0x930 0x3 0x1
+#define MX35_PAD_RTS1__KPP_COL_6				0x190 0x5d4 0x968 0x4 0x0
+#define MX35_PAD_RTS1__GPIO3_8					0x190 0x5d4 0x914 0x5 0x0
+#define MX35_PAD_RTS1__EMI_NANDF_CE1				0x190 0x5d4 0x000 0x6 0x0
+#define MX35_PAD_RTS1__ARM11P_TOP_EVNTBUS_18			0x190 0x5d4 0x000 0x7 0x0
+#define MX35_PAD_CTS1__UART1_CTS				0x194 0x5d8 0x000 0x0 0x0
+#define MX35_PAD_CTS1__CSPI2_RDY				0x194 0x5d8 0x7e4 0x1 0x1
+#define MX35_PAD_CTS1__I2C3_SDA					0x194 0x5d8 0x920 0x2 0x1
+#define MX35_PAD_CTS1__IPU_CSI_D_1				0x194 0x5d8 0x934 0x3 0x1
+#define MX35_PAD_CTS1__KPP_COL_7				0x194 0x5d8 0x96c 0x4 0x0
+#define MX35_PAD_CTS1__GPIO3_9					0x194 0x5d8 0x918 0x5 0x0
+#define MX35_PAD_CTS1__EMI_NANDF_CE2				0x194 0x5d8 0x000 0x6 0x0
+#define MX35_PAD_CTS1__ARM11P_TOP_EVNTBUS_19			0x194 0x5d8 0x000 0x7 0x0
+#define MX35_PAD_RXD2__UART2_RXD_MUX				0x198 0x5dc 0x000 0x0 0x0
+#define MX35_PAD_RXD2__KPP_ROW_4				0x198 0x5dc 0x980 0x4 0x0
+#define MX35_PAD_RXD2__GPIO3_10					0x198 0x5dc 0x8ec 0x5 0x0
+#define MX35_PAD_TXD2__UART2_TXD_MUX				0x19c 0x5e0 0x000 0x0 0x0
+#define MX35_PAD_TXD2__SPDIF_SPDIF_EXTCLK			0x19c 0x5e0 0x994 0x1 0x2
+#define MX35_PAD_TXD2__KPP_ROW_5				0x19c 0x5e0 0x984 0x4 0x0
+#define MX35_PAD_TXD2__GPIO3_11					0x19c 0x5e0 0x8f0 0x5 0x0
+#define MX35_PAD_RTS2__UART2_RTS				0x1a0 0x5e4 0x000 0x0 0x0
+#define MX35_PAD_RTS2__SPDIF_SPDIF_IN1				0x1a0 0x5e4 0x998 0x1 0x1
+#define MX35_PAD_RTS2__CAN2_RXCAN				0x1a0 0x5e4 0x7cc 0x2 0x1
+#define MX35_PAD_RTS2__IPU_CSI_D_2				0x1a0 0x5e4 0x938 0x3 0x1
+#define MX35_PAD_RTS2__KPP_ROW_6				0x1a0 0x5e4 0x988 0x4 0x0
+#define MX35_PAD_RTS2__GPIO3_12					0x1a0 0x5e4 0x8f4 0x5 0x0
+#define MX35_PAD_RTS2__AUDMUX_AUD5_RXC				0x1a0 0x5e4 0x000 0x6 0x0
+#define MX35_PAD_RTS2__UART3_RXD_MUX				0x1a0 0x5e4 0x9a0 0x7 0x0
+#define MX35_PAD_CTS2__UART2_CTS				0x1a4 0x5e8 0x000 0x0 0x0
+#define MX35_PAD_CTS2__SPDIF_SPDIF_OUT1				0x1a4 0x5e8 0x000 0x1 0x0
+#define MX35_PAD_CTS2__CAN2_TXCAN				0x1a4 0x5e8 0x000 0x2 0x0
+#define MX35_PAD_CTS2__IPU_CSI_D_3				0x1a4 0x5e8 0x93c 0x3 0x1
+#define MX35_PAD_CTS2__KPP_ROW_7				0x1a4 0x5e8 0x98c 0x4 0x0
+#define MX35_PAD_CTS2__GPIO3_13					0x1a4 0x5e8 0x8f8 0x5 0x0
+#define MX35_PAD_CTS2__AUDMUX_AUD5_RXFS				0x1a4 0x5e8 0x000 0x6 0x0
+#define MX35_PAD_CTS2__UART3_TXD_MUX				0x1a4 0x5e8 0x000 0x7 0x0
+#define MX35_PAD_RTCK__ARM11P_TOP_RTCK				0x000 0x5ec 0x000 0x0 0x0
+#define MX35_PAD_TCK__SJC_TCK					0x000 0x5f0 0x000 0x0 0x0
+#define MX35_PAD_TMS__SJC_TMS					0x000 0x5f4 0x000 0x0 0x0
+#define MX35_PAD_TDI__SJC_TDI					0x000 0x5f8 0x000 0x0 0x0
+#define MX35_PAD_TDO__SJC_TDO					0x000 0x5fc 0x000 0x0 0x0
+#define MX35_PAD_TRSTB__SJC_TRSTB				0x000 0x600 0x000 0x0 0x0
+#define MX35_PAD_DE_B__SJC_DE_B					0x000 0x604 0x000 0x0 0x0
+#define MX35_PAD_SJC_MOD__SJC_MOD				0x000 0x608 0x000 0x0 0x0
+#define MX35_PAD_USBOTG_PWR__USB_TOP_USBOTG_PWR			0x1a8 0x60c 0x000 0x0 0x0
+#define MX35_PAD_USBOTG_PWR__USB_TOP_USBH2_PWR			0x1a8 0x60c 0x000 0x1 0x0
+#define MX35_PAD_USBOTG_PWR__GPIO3_14				0x1a8 0x60c 0x8fc 0x5 0x0
+#define MX35_PAD_USBOTG_OC__USB_TOP_USBOTG_OC			0x1ac 0x610 0x000 0x0 0x0
+#define MX35_PAD_USBOTG_OC__USB_TOP_USBH2_OC			0x1ac 0x610 0x9f4 0x1 0x1
+#define MX35_PAD_USBOTG_OC__GPIO3_15				0x1ac 0x610 0x900 0x5 0x0
+#define MX35_PAD_LD0__IPU_DISPB_DAT_0				0x1b0 0x614 0x000 0x0 0x0
+#define MX35_PAD_LD0__GPIO2_0					0x1b0 0x614 0x868 0x5 0x1
+#define MX35_PAD_LD0__SDMA_SDMA_DEBUG_PC_0			0x1b0 0x614 0x000 0x6 0x0
+#define MX35_PAD_LD1__IPU_DISPB_DAT_1				0x1b4 0x618 0x000 0x0 0x0
+#define MX35_PAD_LD1__GPIO2_1					0x1b4 0x618 0x894 0x5 0x0
+#define MX35_PAD_LD1__SDMA_SDMA_DEBUG_PC_1			0x1b4 0x618 0x000 0x6 0x0
+#define MX35_PAD_LD2__IPU_DISPB_DAT_2				0x1b8 0x61c 0x000 0x0 0x0
+#define MX35_PAD_LD2__GPIO2_2					0x1b8 0x61c 0x8c0 0x5 0x0
+#define MX35_PAD_LD2__SDMA_SDMA_DEBUG_PC_2			0x1b8 0x61c 0x000 0x6 0x0
+#define MX35_PAD_LD3__IPU_DISPB_DAT_3				0x1bc 0x620 0x000 0x0 0x0
+#define MX35_PAD_LD3__GPIO2_3					0x1bc 0x620 0x8cc 0x5 0x0
+#define MX35_PAD_LD3__SDMA_SDMA_DEBUG_PC_3			0x1bc 0x620 0x000 0x6 0x0
+#define MX35_PAD_LD4__IPU_DISPB_DAT_4				0x1c0 0x624 0x000 0x0 0x0
+#define MX35_PAD_LD4__GPIO2_4					0x1c0 0x624 0x8d0 0x5 0x0
+#define MX35_PAD_LD4__SDMA_SDMA_DEBUG_PC_4			0x1c0 0x624 0x000 0x6 0x0
+#define MX35_PAD_LD5__IPU_DISPB_DAT_5				0x1c4 0x628 0x000 0x0 0x0
+#define MX35_PAD_LD5__GPIO2_5					0x1c4 0x628 0x8d4 0x5 0x0
+#define MX35_PAD_LD5__SDMA_SDMA_DEBUG_PC_5			0x1c4 0x628 0x000 0x6 0x0
+#define MX35_PAD_LD6__IPU_DISPB_DAT_6				0x1c8 0x62c 0x000 0x0 0x0
+#define MX35_PAD_LD6__GPIO2_6					0x1c8 0x62c 0x8d8 0x5 0x0
+#define MX35_PAD_LD6__SDMA_SDMA_DEBUG_PC_6			0x1c8 0x62c 0x000 0x6 0x0
+#define MX35_PAD_LD7__IPU_DISPB_DAT_7				0x1cc 0x630 0x000 0x0 0x0
+#define MX35_PAD_LD7__GPIO2_7					0x1cc 0x630 0x8dc 0x5 0x0
+#define MX35_PAD_LD7__SDMA_SDMA_DEBUG_PC_7			0x1cc 0x630 0x000 0x6 0x0
+#define MX35_PAD_LD8__IPU_DISPB_DAT_8				0x1d0 0x634 0x000 0x0 0x0
+#define MX35_PAD_LD8__GPIO2_8					0x1d0 0x634 0x8e0 0x5 0x0
+#define MX35_PAD_LD8__SDMA_SDMA_DEBUG_PC_8			0x1d0 0x634 0x000 0x6 0x0
+#define MX35_PAD_LD9__IPU_DISPB_DAT_9				0x1d4 0x638 0x000 0x0 0x0
+#define MX35_PAD_LD9__GPIO2_9					0x1d4 0x638 0x8e4 0x5 0x0
+#define MX35_PAD_LD9__SDMA_SDMA_DEBUG_PC_9			0x1d4 0x638 0x000 0x6 0x0
+#define MX35_PAD_LD10__IPU_DISPB_DAT_10				0x1d8 0x63c 0x000 0x0 0x0
+#define MX35_PAD_LD10__GPIO2_10					0x1d8 0x63c 0x86c 0x5 0x0
+#define MX35_PAD_LD10__SDMA_SDMA_DEBUG_PC_10			0x1d8 0x63c 0x000 0x6 0x0
+#define MX35_PAD_LD11__IPU_DISPB_DAT_11				0x1dc 0x640 0x000 0x0 0x0
+#define MX35_PAD_LD11__GPIO2_11					0x1dc 0x640 0x870 0x5 0x0
+#define MX35_PAD_LD11__SDMA_SDMA_DEBUG_PC_11			0x1dc 0x640 0x000 0x6 0x0
+#define MX35_PAD_LD11__ARM11P_TOP_TRACE_4			0x1dc 0x640 0x000 0x7 0x0
+#define MX35_PAD_LD12__IPU_DISPB_DAT_12				0x1e0 0x644 0x000 0x0 0x0
+#define MX35_PAD_LD12__GPIO2_12					0x1e0 0x644 0x874 0x5 0x0
+#define MX35_PAD_LD12__SDMA_SDMA_DEBUG_PC_12			0x1e0 0x644 0x000 0x6 0x0
+#define MX35_PAD_LD12__ARM11P_TOP_TRACE_5			0x1e0 0x644 0x000 0x7 0x0
+#define MX35_PAD_LD13__IPU_DISPB_DAT_13				0x1e4 0x648 0x000 0x0 0x0
+#define MX35_PAD_LD13__GPIO2_13					0x1e4 0x648 0x878 0x5 0x0
+#define MX35_PAD_LD13__SDMA_SDMA_DEBUG_PC_13			0x1e4 0x648 0x000 0x6 0x0
+#define MX35_PAD_LD13__ARM11P_TOP_TRACE_6			0x1e4 0x648 0x000 0x7 0x0
+#define MX35_PAD_LD14__IPU_DISPB_DAT_14				0x1e8 0x64c 0x000 0x0 0x0
+#define MX35_PAD_LD14__GPIO2_14					0x1e8 0x64c 0x87c 0x5 0x0
+#define MX35_PAD_LD14__SDMA_SDMA_DEBUG_EVENT_CHANNEL_0		0x1e8 0x64c 0x000 0x6 0x0
+#define MX35_PAD_LD14__ARM11P_TOP_TRACE_7			0x1e8 0x64c 0x000 0x7 0x0
+#define MX35_PAD_LD15__IPU_DISPB_DAT_15				0x1ec 0x650 0x000 0x0 0x0
+#define MX35_PAD_LD15__GPIO2_15					0x1ec 0x650 0x880 0x5 0x0
+#define MX35_PAD_LD15__SDMA_SDMA_DEBUG_EVENT_CHANNEL_1		0x1ec 0x650 0x000 0x6 0x0
+#define MX35_PAD_LD15__ARM11P_TOP_TRACE_8			0x1ec 0x650 0x000 0x7 0x0
+#define MX35_PAD_LD16__IPU_DISPB_DAT_16				0x1f0 0x654 0x000 0x0 0x0
+#define MX35_PAD_LD16__IPU_DISPB_D12_VSYNC			0x1f0 0x654 0x928 0x2 0x0
+#define MX35_PAD_LD16__GPIO2_16					0x1f0 0x654 0x884 0x5 0x0
+#define MX35_PAD_LD16__SDMA_SDMA_DEBUG_EVENT_CHANNEL_2		0x1f0 0x654 0x000 0x6 0x0
+#define MX35_PAD_LD16__ARM11P_TOP_TRACE_9			0x1f0 0x654 0x000 0x7 0x0
+#define MX35_PAD_LD17__IPU_DISPB_DAT_17				0x1f4 0x658 0x000 0x0 0x0
+#define MX35_PAD_LD17__IPU_DISPB_CS2				0x1f4 0x658 0x000 0x2 0x0
+#define MX35_PAD_LD17__GPIO2_17					0x1f4 0x658 0x888 0x5 0x0
+#define MX35_PAD_LD17__SDMA_SDMA_DEBUG_EVENT_CHANNEL_3		0x1f4 0x658 0x000 0x6 0x0
+#define MX35_PAD_LD17__ARM11P_TOP_TRACE_10			0x1f4 0x658 0x000 0x7 0x0
+#define MX35_PAD_LD18__IPU_DISPB_DAT_18				0x1f8 0x65c 0x000 0x0 0x0
+#define MX35_PAD_LD18__IPU_DISPB_D0_VSYNC			0x1f8 0x65c 0x924 0x1 0x1
+#define MX35_PAD_LD18__IPU_DISPB_D12_VSYNC			0x1f8 0x65c 0x928 0x2 0x1
+#define MX35_PAD_LD18__ESDHC3_CMD				0x1f8 0x65c 0x818 0x3 0x0
+#define MX35_PAD_LD18__USB_TOP_USBOTG_DATA_3			0x1f8 0x65c 0x9b0 0x4 0x0
+#define MX35_PAD_LD18__GPIO3_24					0x1f8 0x65c 0x000 0x5 0x0
+#define MX35_PAD_LD18__SDMA_SDMA_DEBUG_EVENT_CHANNEL_4		0x1f8 0x65c 0x000 0x6 0x0
+#define MX35_PAD_LD18__ARM11P_TOP_TRACE_11			0x1f8 0x65c 0x000 0x7 0x0
+#define MX35_PAD_LD19__IPU_DISPB_DAT_19				0x1fc 0x660 0x000 0x0 0x0
+#define MX35_PAD_LD19__IPU_DISPB_BCLK				0x1fc 0x660 0x000 0x1 0x0
+#define MX35_PAD_LD19__IPU_DISPB_CS1				0x1fc 0x660 0x000 0x2 0x0
+#define MX35_PAD_LD19__ESDHC3_CLK				0x1fc 0x660 0x814 0x3 0x0
+#define MX35_PAD_LD19__USB_TOP_USBOTG_DIR			0x1fc 0x660 0x9c4 0x4 0x0
+#define MX35_PAD_LD19__GPIO3_25					0x1fc 0x660 0x000 0x5 0x0
+#define MX35_PAD_LD19__SDMA_SDMA_DEBUG_EVENT_CHANNEL_5		0x1fc 0x660 0x000 0x6 0x0
+#define MX35_PAD_LD19__ARM11P_TOP_TRACE_12			0x1fc 0x660 0x000 0x7 0x0
+#define MX35_PAD_LD20__IPU_DISPB_DAT_20				0x200 0x664 0x000 0x0 0x0
+#define MX35_PAD_LD20__IPU_DISPB_CS0				0x200 0x664 0x000 0x1 0x0
+#define MX35_PAD_LD20__IPU_DISPB_SD_CLK				0x200 0x664 0x000 0x2 0x0
+#define MX35_PAD_LD20__ESDHC3_DAT0				0x200 0x664 0x81c 0x3 0x0
+#define MX35_PAD_LD20__GPIO3_26					0x200 0x664 0x000 0x5 0x0
+#define MX35_PAD_LD20__SDMA_SDMA_DEBUG_CORE_STATUS_3		0x200 0x664 0x000 0x6 0x0
+#define MX35_PAD_LD20__ARM11P_TOP_TRACE_13			0x200 0x664 0x000 0x7 0x0
+#define MX35_PAD_LD21__IPU_DISPB_DAT_21				0x204 0x668 0x000 0x0 0x0
+#define MX35_PAD_LD21__IPU_DISPB_PAR_RS				0x204 0x668 0x000 0x1 0x0
+#define MX35_PAD_LD21__IPU_DISPB_SER_RS				0x204 0x668 0x000 0x2 0x0
+#define MX35_PAD_LD21__ESDHC3_DAT1				0x204 0x668 0x820 0x3 0x0
+#define MX35_PAD_LD21__USB_TOP_USBOTG_STP			0x204 0x668 0x000 0x4 0x0
+#define MX35_PAD_LD21__GPIO3_27					0x204 0x668 0x000 0x5 0x0
+#define MX35_PAD_LD21__SDMA_DEBUG_EVENT_CHANNEL_SEL		0x204 0x668 0x000 0x6 0x0
+#define MX35_PAD_LD21__ARM11P_TOP_TRACE_14			0x204 0x668 0x000 0x7 0x0
+#define MX35_PAD_LD22__IPU_DISPB_DAT_22				0x208 0x66c 0x000 0x0 0x0
+#define MX35_PAD_LD22__IPU_DISPB_WR				0x208 0x66c 0x000 0x1 0x0
+#define MX35_PAD_LD22__IPU_DISPB_SD_D_I				0x208 0x66c 0x92c 0x2 0x0
+#define MX35_PAD_LD22__ESDHC3_DAT2				0x208 0x66c 0x824 0x3 0x0
+#define MX35_PAD_LD22__USB_TOP_USBOTG_NXT			0x208 0x66c 0x9c8 0x4 0x0
+#define MX35_PAD_LD22__GPIO3_28					0x208 0x66c 0x000 0x5 0x0
+#define MX35_PAD_LD22__SDMA_DEBUG_BUS_ERROR			0x208 0x66c 0x000 0x6 0x0
+#define MX35_PAD_LD22__ARM11P_TOP_TRCTL				0x208 0x66c 0x000 0x7 0x0
+#define MX35_PAD_LD23__IPU_DISPB_DAT_23				0x20c 0x670 0x000 0x0 0x0
+#define MX35_PAD_LD23__IPU_DISPB_RD				0x20c 0x670 0x000 0x1 0x0
+#define MX35_PAD_LD23__IPU_DISPB_SD_D_IO			0x20c 0x670 0x92c 0x2 0x1
+#define MX35_PAD_LD23__ESDHC3_DAT3				0x20c 0x670 0x828 0x3 0x0
+#define MX35_PAD_LD23__USB_TOP_USBOTG_DATA_7			0x20c 0x670 0x9c0 0x4 0x0
+#define MX35_PAD_LD23__GPIO3_29					0x20c 0x670 0x000 0x5 0x0
+#define MX35_PAD_LD23__SDMA_DEBUG_MATCHED_DMBUS			0x20c 0x670 0x000 0x6 0x0
+#define MX35_PAD_LD23__ARM11P_TOP_TRCLK				0x20c 0x670 0x000 0x7 0x0
+#define MX35_PAD_D3_HSYNC__IPU_DISPB_D3_HSYNC			0x210 0x674 0x000 0x0 0x0
+#define MX35_PAD_D3_HSYNC__IPU_DISPB_SD_D_IO			0x210 0x674 0x92c 0x2 0x2
+#define MX35_PAD_D3_HSYNC__GPIO3_30				0x210 0x674 0x000 0x5 0x0
+#define MX35_PAD_D3_HSYNC__SDMA_DEBUG_RTBUFFER_WRITE		0x210 0x674 0x000 0x6 0x0
+#define MX35_PAD_D3_HSYNC__ARM11P_TOP_TRACE_15			0x210 0x674 0x000 0x7 0x0
+#define MX35_PAD_D3_FPSHIFT__IPU_DISPB_D3_CLK			0x214 0x678 0x000 0x0 0x0
+#define MX35_PAD_D3_FPSHIFT__IPU_DISPB_SD_CLK			0x214 0x678 0x000 0x2 0x0
+#define MX35_PAD_D3_FPSHIFT__GPIO3_31				0x214 0x678 0x000 0x5 0x0
+#define MX35_PAD_D3_FPSHIFT__SDMA_SDMA_DEBUG_CORE_STATUS_0	0x214 0x678 0x000 0x6 0x0
+#define MX35_PAD_D3_FPSHIFT__ARM11P_TOP_TRACE_16		0x214 0x678 0x000 0x7 0x0
+#define MX35_PAD_D3_DRDY__IPU_DISPB_D3_DRDY			0x218 0x67c 0x000 0x0 0x0
+#define MX35_PAD_D3_DRDY__IPU_DISPB_SD_D_O			0x218 0x67c 0x000 0x2 0x0
+#define MX35_PAD_D3_DRDY__GPIO1_0				0x218 0x67c 0x82c 0x5 0x2
+#define MX35_PAD_D3_DRDY__SDMA_SDMA_DEBUG_CORE_STATUS_1		0x218 0x67c 0x000 0x6 0x0
+#define MX35_PAD_D3_DRDY__ARM11P_TOP_TRACE_17			0x218 0x67c 0x000 0x7 0x0
+#define MX35_PAD_CONTRAST__IPU_DISPB_CONTR			0x21c 0x680 0x000 0x0 0x0
+#define MX35_PAD_CONTRAST__GPIO1_1				0x21c 0x680 0x838 0x5 0x2
+#define MX35_PAD_CONTRAST__SDMA_SDMA_DEBUG_CORE_STATUS_2	0x21c 0x680 0x000 0x6 0x0
+#define MX35_PAD_CONTRAST__ARM11P_TOP_TRACE_18			0x21c 0x680 0x000 0x7 0x0
+#define MX35_PAD_D3_VSYNC__IPU_DISPB_D3_VSYNC			0x220 0x684 0x000 0x0 0x0
+#define MX35_PAD_D3_VSYNC__IPU_DISPB_CS1			0x220 0x684 0x000 0x2 0x0
+#define MX35_PAD_D3_VSYNC__GPIO1_2				0x220 0x684 0x848 0x5 0x1
+#define MX35_PAD_D3_VSYNC__SDMA_DEBUG_YIELD			0x220 0x684 0x000 0x6 0x0
+#define MX35_PAD_D3_VSYNC__ARM11P_TOP_TRACE_19			0x220 0x684 0x000 0x7 0x0
+#define MX35_PAD_D3_REV__IPU_DISPB_D3_REV			0x224 0x688 0x000 0x0 0x0
+#define MX35_PAD_D3_REV__IPU_DISPB_SER_RS			0x224 0x688 0x000 0x2 0x0
+#define MX35_PAD_D3_REV__GPIO1_3				0x224 0x688 0x84c 0x5 0x1
+#define MX35_PAD_D3_REV__SDMA_DEBUG_BUS_RWB			0x224 0x688 0x000 0x6 0x0
+#define MX35_PAD_D3_REV__ARM11P_TOP_TRACE_20			0x224 0x688 0x000 0x7 0x0
+#define MX35_PAD_D3_CLS__IPU_DISPB_D3_CLS			0x228 0x68c 0x000 0x0 0x0
+#define MX35_PAD_D3_CLS__IPU_DISPB_CS2				0x228 0x68c 0x000 0x2 0x0
+#define MX35_PAD_D3_CLS__GPIO1_4				0x228 0x68c 0x850 0x5 0x2
+#define MX35_PAD_D3_CLS__SDMA_DEBUG_BUS_DEVICE_0		0x228 0x68c 0x000 0x6 0x0
+#define MX35_PAD_D3_CLS__ARM11P_TOP_TRACE_21			0x228 0x68c 0x000 0x7 0x0
+#define MX35_PAD_D3_SPL__IPU_DISPB_D3_SPL			0x22c 0x690 0x000 0x0 0x0
+#define MX35_PAD_D3_SPL__IPU_DISPB_D12_VSYNC			0x22c 0x690 0x928 0x2 0x2
+#define MX35_PAD_D3_SPL__GPIO1_5				0x22c 0x690 0x854 0x5 0x2
+#define MX35_PAD_D3_SPL__SDMA_DEBUG_BUS_DEVICE_1		0x22c 0x690 0x000 0x6 0x0
+#define MX35_PAD_D3_SPL__ARM11P_TOP_TRACE_22			0x22c 0x690 0x000 0x7 0x0
+#define MX35_PAD_SD1_CMD__ESDHC1_CMD				0x230 0x694 0x000 0x0 0x0
+#define MX35_PAD_SD1_CMD__MSHC_SCLK				0x230 0x694 0x000 0x1 0x0
+#define MX35_PAD_SD1_CMD__IPU_DISPB_D0_VSYNC			0x230 0x694 0x924 0x3 0x2
+#define MX35_PAD_SD1_CMD__USB_TOP_USBOTG_DATA_4			0x230 0x694 0x9b4 0x4 0x0
+#define MX35_PAD_SD1_CMD__GPIO1_6				0x230 0x694 0x858 0x5 0x2
+#define MX35_PAD_SD1_CMD__ARM11P_TOP_TRCTL			0x230 0x694 0x000 0x7 0x0
+#define MX35_PAD_SD1_CLK__ESDHC1_CLK				0x234 0x698 0x000 0x0 0x0
+#define MX35_PAD_SD1_CLK__MSHC_BS				0x234 0x698 0x000 0x1 0x0
+#define MX35_PAD_SD1_CLK__IPU_DISPB_BCLK			0x234 0x698 0x000 0x3 0x0
+#define MX35_PAD_SD1_CLK__USB_TOP_USBOTG_DATA_5			0x234 0x698 0x9b8 0x4 0x0
+#define MX35_PAD_SD1_CLK__GPIO1_7				0x234 0x698 0x85c 0x5 0x2
+#define MX35_PAD_SD1_CLK__ARM11P_TOP_TRCLK			0x234 0x698 0x000 0x7 0x0
+#define MX35_PAD_SD1_DATA0__ESDHC1_DAT0				0x238 0x69c 0x000 0x0 0x0
+#define MX35_PAD_SD1_DATA0__MSHC_DATA_0				0x238 0x69c 0x000 0x1 0x0
+#define MX35_PAD_SD1_DATA0__IPU_DISPB_CS0			0x238 0x69c 0x000 0x3 0x0
+#define MX35_PAD_SD1_DATA0__USB_TOP_USBOTG_DATA_6		0x238 0x69c 0x9bc 0x4 0x0
+#define MX35_PAD_SD1_DATA0__GPIO1_8				0x238 0x69c 0x860 0x5 0x2
+#define MX35_PAD_SD1_DATA0__ARM11P_TOP_TRACE_23			0x238 0x69c 0x000 0x7 0x0
+#define MX35_PAD_SD1_DATA1__ESDHC1_DAT1				0x23c 0x6a0 0x000 0x0 0x0
+#define MX35_PAD_SD1_DATA1__MSHC_DATA_1				0x23c 0x6a0 0x000 0x1 0x0
+#define MX35_PAD_SD1_DATA1__IPU_DISPB_PAR_RS			0x23c 0x6a0 0x000 0x3 0x0
+#define MX35_PAD_SD1_DATA1__USB_TOP_USBOTG_DATA_0		0x23c 0x6a0 0x9a4 0x4 0x0
+#define MX35_PAD_SD1_DATA1__GPIO1_9				0x23c 0x6a0 0x864 0x5 0x1
+#define MX35_PAD_SD1_DATA1__ARM11P_TOP_TRACE_24			0x23c 0x6a0 0x000 0x7 0x0
+#define MX35_PAD_SD1_DATA2__ESDHC1_DAT2				0x240 0x6a4 0x000 0x0 0x0
+#define MX35_PAD_SD1_DATA2__MSHC_DATA_2				0x240 0x6a4 0x000 0x1 0x0
+#define MX35_PAD_SD1_DATA2__IPU_DISPB_WR			0x240 0x6a4 0x000 0x3 0x0
+#define MX35_PAD_SD1_DATA2__USB_TOP_USBOTG_DATA_1		0x240 0x6a4 0x9a8 0x4 0x0
+#define MX35_PAD_SD1_DATA2__GPIO1_10				0x240 0x6a4 0x830 0x5 0x1
+#define MX35_PAD_SD1_DATA2__ARM11P_TOP_TRACE_25			0x240 0x6a4 0x000 0x7 0x0
+#define MX35_PAD_SD1_DATA3__ESDHC1_DAT3				0x244 0x6a8 0x000 0x0 0x0
+#define MX35_PAD_SD1_DATA3__MSHC_DATA_3				0x244 0x6a8 0x000 0x1 0x0
+#define MX35_PAD_SD1_DATA3__IPU_DISPB_RD			0x244 0x6a8 0x000 0x3 0x0
+#define MX35_PAD_SD1_DATA3__USB_TOP_USBOTG_DATA_2		0x244 0x6a8 0x9ac 0x4 0x0
+#define MX35_PAD_SD1_DATA3__GPIO1_11				0x244 0x6a8 0x834 0x5 0x1
+#define MX35_PAD_SD1_DATA3__ARM11P_TOP_TRACE_26			0x244 0x6a8 0x000 0x7 0x0
+#define MX35_PAD_SD2_CMD__ESDHC2_CMD				0x248 0x6ac 0x000 0x0 0x0
+#define MX35_PAD_SD2_CMD__I2C3_SCL				0x248 0x6ac 0x91c 0x1 0x2
+#define MX35_PAD_SD2_CMD__ESDHC1_DAT4				0x248 0x6ac 0x804 0x2 0x0
+#define MX35_PAD_SD2_CMD__IPU_CSI_D_2				0x248 0x6ac 0x938 0x3 0x2
+#define MX35_PAD_SD2_CMD__USB_TOP_USBH2_DATA_4			0x248 0x6ac 0x9dc 0x4 0x0
+#define MX35_PAD_SD2_CMD__GPIO2_0				0x248 0x6ac 0x868 0x5 0x2
+#define MX35_PAD_SD2_CMD__SPDIF_SPDIF_OUT1			0x248 0x6ac 0x000 0x6 0x0
+#define MX35_PAD_SD2_CMD__IPU_DISPB_D12_VSYNC			0x248 0x6ac 0x928 0x7 0x3
+#define MX35_PAD_SD2_CLK__ESDHC2_CLK				0x24c 0x6b0 0x000 0x0 0x0
+#define MX35_PAD_SD2_CLK__I2C3_SDA				0x24c 0x6b0 0x920 0x1 0x2
+#define MX35_PAD_SD2_CLK__ESDHC1_DAT5				0x24c 0x6b0 0x808 0x2 0x0
+#define MX35_PAD_SD2_CLK__IPU_CSI_D_3				0x24c 0x6b0 0x93c 0x3 0x2
+#define MX35_PAD_SD2_CLK__USB_TOP_USBH2_DATA_5			0x24c 0x6b0 0x9e0 0x4 0x0
+#define MX35_PAD_SD2_CLK__GPIO2_1				0x24c 0x6b0 0x894 0x5 0x1
+#define MX35_PAD_SD2_CLK__SPDIF_SPDIF_IN1			0x24c 0x6b0 0x998 0x6 0x2
+#define MX35_PAD_SD2_CLK__IPU_DISPB_CS2				0x24c 0x6b0 0x000 0x7 0x0
+#define MX35_PAD_SD2_DATA0__ESDHC2_DAT0				0x250 0x6b4 0x000 0x0 0x0
+#define MX35_PAD_SD2_DATA0__UART3_RXD_MUX			0x250 0x6b4 0x9a0 0x1 0x1
+#define MX35_PAD_SD2_DATA0__ESDHC1_DAT6				0x250 0x6b4 0x80c 0x2 0x0
+#define MX35_PAD_SD2_DATA0__IPU_CSI_D_4				0x250 0x6b4 0x940 0x3 0x1
+#define MX35_PAD_SD2_DATA0__USB_TOP_USBH2_DATA_6		0x250 0x6b4 0x9e4 0x4 0x0
+#define MX35_PAD_SD2_DATA0__GPIO2_2				0x250 0x6b4 0x8c0 0x5 0x1
+#define MX35_PAD_SD2_DATA0__SPDIF_SPDIF_EXTCLK			0x250 0x6b4 0x994 0x6 0x3
+#define MX35_PAD_SD2_DATA1__ESDHC2_DAT1				0x254 0x6b8 0x000 0x0 0x0
+#define MX35_PAD_SD2_DATA1__UART3_TXD_MUX			0x254 0x6b8 0x000 0x1 0x0
+#define MX35_PAD_SD2_DATA1__ESDHC1_DAT7				0x254 0x6b8 0x810 0x2 0x0
+#define MX35_PAD_SD2_DATA1__IPU_CSI_D_5				0x254 0x6b8 0x944 0x3 0x1
+#define MX35_PAD_SD2_DATA1__USB_TOP_USBH2_DATA_0		0x254 0x6b8 0x9cc 0x4 0x0
+#define MX35_PAD_SD2_DATA1__GPIO2_3				0x254 0x6b8 0x8cc 0x5 0x1
+#define MX35_PAD_SD2_DATA2__ESDHC2_DAT2				0x258 0x6bc 0x000 0x0 0x0
+#define MX35_PAD_SD2_DATA2__UART3_RTS				0x258 0x6bc 0x99c 0x1 0x0
+#define MX35_PAD_SD2_DATA2__CAN1_RXCAN				0x258 0x6bc 0x7c8 0x2 0x1
+#define MX35_PAD_SD2_DATA2__IPU_CSI_D_6				0x258 0x6bc 0x948 0x3 0x1
+#define MX35_PAD_SD2_DATA2__USB_TOP_USBH2_DATA_1		0x258 0x6bc 0x9d0 0x4 0x0
+#define MX35_PAD_SD2_DATA2__GPIO2_4				0x258 0x6bc 0x8d0 0x5 0x1
+#define MX35_PAD_SD2_DATA3__ESDHC2_DAT3				0x25c 0x6c0 0x000 0x0 0x0
+#define MX35_PAD_SD2_DATA3__UART3_CTS				0x25c 0x6c0 0x000 0x1 0x0
+#define MX35_PAD_SD2_DATA3__CAN1_TXCAN				0x25c 0x6c0 0x000 0x2 0x0
+#define MX35_PAD_SD2_DATA3__IPU_CSI_D_7				0x25c 0x6c0 0x94c 0x3 0x1
+#define MX35_PAD_SD2_DATA3__USB_TOP_USBH2_DATA_2		0x25c 0x6c0 0x9d4 0x4 0x0
+#define MX35_PAD_SD2_DATA3__GPIO2_5				0x25c 0x6c0 0x8d4 0x5 0x1
+#define MX35_PAD_ATA_CS0__ATA_CS0				0x260 0x6c4 0x000 0x0 0x0
+#define MX35_PAD_ATA_CS0__CSPI1_SS3				0x260 0x6c4 0x7dc 0x1 0x1
+#define MX35_PAD_ATA_CS0__IPU_DISPB_CS1				0x260 0x6c4 0x000 0x3 0x0
+#define MX35_PAD_ATA_CS0__GPIO2_6				0x260 0x6c4 0x8d8 0x5 0x1
+#define MX35_PAD_ATA_CS0__IPU_DIAGB_0				0x260 0x6c4 0x000 0x6 0x0
+#define MX35_PAD_ATA_CS0__ARM11P_TOP_MAX1_HMASTER_0		0x260 0x6c4 0x000 0x7 0x0
+#define MX35_PAD_ATA_CS1__ATA_CS1				0x264 0x6c8 0x000 0x0 0x0
+#define MX35_PAD_ATA_CS1__IPU_DISPB_CS2				0x264 0x6c8 0x000 0x3 0x0
+#define MX35_PAD_ATA_CS1__CSPI2_SS0				0x264 0x6c8 0x7f0 0x4 0x1
+#define MX35_PAD_ATA_CS1__GPIO2_7				0x264 0x6c8 0x8dc 0x5 0x1
+#define MX35_PAD_ATA_CS1__IPU_DIAGB_1				0x264 0x6c8 0x000 0x6 0x0
+#define MX35_PAD_ATA_CS1__ARM11P_TOP_MAX1_HMASTER_1		0x264 0x6c8 0x000 0x7 0x0
+#define MX35_PAD_ATA_DIOR__ATA_DIOR				0x268 0x6cc 0x000 0x0 0x0
+#define MX35_PAD_ATA_DIOR__ESDHC3_DAT0				0x268 0x6cc 0x81c 0x1 0x1
+#define MX35_PAD_ATA_DIOR__USB_TOP_USBOTG_DIR			0x268 0x6cc 0x9c4 0x2 0x1
+#define MX35_PAD_ATA_DIOR__IPU_DISPB_BE0			0x268 0x6cc 0x000 0x3 0x0
+#define MX35_PAD_ATA_DIOR__CSPI2_SS1				0x268 0x6cc 0x7f4 0x4 0x1
+#define MX35_PAD_ATA_DIOR__GPIO2_8				0x268 0x6cc 0x8e0 0x5 0x1
+#define MX35_PAD_ATA_DIOR__IPU_DIAGB_2				0x268 0x6cc 0x000 0x6 0x0
+#define MX35_PAD_ATA_DIOR__ARM11P_TOP_MAX1_HMASTER_2		0x268 0x6cc 0x000 0x7 0x0
+#define MX35_PAD_ATA_DIOW__ATA_DIOW				0x26c 0x6d0 0x000 0x0 0x0
+#define MX35_PAD_ATA_DIOW__ESDHC3_DAT1				0x26c 0x6d0 0x820 0x1 0x1
+#define MX35_PAD_ATA_DIOW__USB_TOP_USBOTG_STP			0x26c 0x6d0 0x000 0x2 0x0
+#define MX35_PAD_ATA_DIOW__IPU_DISPB_BE1			0x26c 0x6d0 0x000 0x3 0x0
+#define MX35_PAD_ATA_DIOW__CSPI2_MOSI				0x26c 0x6d0 0x7ec 0x4 0x2
+#define MX35_PAD_ATA_DIOW__GPIO2_9				0x26c 0x6d0 0x8e4 0x5 0x1
+#define MX35_PAD_ATA_DIOW__IPU_DIAGB_3				0x26c 0x6d0 0x000 0x6 0x0
+#define MX35_PAD_ATA_DIOW__ARM11P_TOP_MAX1_HMASTER_3		0x26c 0x6d0 0x000 0x7 0x0
+#define MX35_PAD_ATA_DMACK__ATA_DMACK				0x270 0x6d4 0x000 0x0 0x0
+#define MX35_PAD_ATA_DMACK__ESDHC3_DAT2				0x270 0x6d4 0x824 0x1 0x1
+#define MX35_PAD_ATA_DMACK__USB_TOP_USBOTG_NXT			0x270 0x6d4 0x9c8 0x2 0x1
+#define MX35_PAD_ATA_DMACK__CSPI2_MISO				0x270 0x6d4 0x7e8 0x4 0x2
+#define MX35_PAD_ATA_DMACK__GPIO2_10				0x270 0x6d4 0x86c 0x5 0x1
+#define MX35_PAD_ATA_DMACK__IPU_DIAGB_4				0x270 0x6d4 0x000 0x6 0x0
+#define MX35_PAD_ATA_DMACK__ARM11P_TOP_MAX0_HMASTER_0		0x270 0x6d4 0x000 0x7 0x0
+#define MX35_PAD_ATA_RESET_B__ATA_RESET_B			0x274 0x6d8 0x000 0x0 0x0
+#define MX35_PAD_ATA_RESET_B__ESDHC3_DAT3			0x274 0x6d8 0x828 0x1 0x1
+#define MX35_PAD_ATA_RESET_B__USB_TOP_USBOTG_DATA_0		0x274 0x6d8 0x9a4 0x2 0x1
+#define MX35_PAD_ATA_RESET_B__IPU_DISPB_SD_D_O			0x274 0x6d8 0x000 0x3 0x0
+#define MX35_PAD_ATA_RESET_B__CSPI2_RDY				0x274 0x6d8 0x7e4 0x4 0x2
+#define MX35_PAD_ATA_RESET_B__GPIO2_11				0x274 0x6d8 0x870 0x5 0x1
+#define MX35_PAD_ATA_RESET_B__IPU_DIAGB_5			0x274 0x6d8 0x000 0x6 0x0
+#define MX35_PAD_ATA_RESET_B__ARM11P_TOP_MAX0_HMASTER_1		0x274 0x6d8 0x000 0x7 0x0
+#define MX35_PAD_ATA_IORDY__ATA_IORDY				0x278 0x6dc 0x000 0x0 0x0
+#define MX35_PAD_ATA_IORDY__ESDHC3_DAT4				0x278 0x6dc 0x000 0x1 0x0
+#define MX35_PAD_ATA_IORDY__USB_TOP_USBOTG_DATA_1		0x278 0x6dc 0x9a8 0x2 0x1
+#define MX35_PAD_ATA_IORDY__IPU_DISPB_SD_D_IO			0x278 0x6dc 0x92c 0x3 0x3
+#define MX35_PAD_ATA_IORDY__ESDHC2_DAT4				0x278 0x6dc 0x000 0x4 0x0
+#define MX35_PAD_ATA_IORDY__GPIO2_12				0x278 0x6dc 0x874 0x5 0x1
+#define MX35_PAD_ATA_IORDY__IPU_DIAGB_6				0x278 0x6dc 0x000 0x6 0x0
+#define MX35_PAD_ATA_IORDY__ARM11P_TOP_MAX0_HMASTER_2		0x278 0x6dc 0x000 0x7 0x0
+#define MX35_PAD_ATA_DATA0__ATA_DATA_0				0x27c 0x6e0 0x000 0x0 0x0
+#define MX35_PAD_ATA_DATA0__ESDHC3_DAT5				0x27c 0x6e0 0x000 0x1 0x0
+#define MX35_PAD_ATA_DATA0__USB_TOP_USBOTG_DATA_2		0x27c 0x6e0 0x9ac 0x2 0x1
+#define MX35_PAD_ATA_DATA0__IPU_DISPB_D12_VSYNC			0x27c 0x6e0 0x928 0x3 0x4
+#define MX35_PAD_ATA_DATA0__ESDHC2_DAT5				0x27c 0x6e0 0x000 0x4 0x0
+#define MX35_PAD_ATA_DATA0__GPIO2_13				0x27c 0x6e0 0x878 0x5 0x1
+#define MX35_PAD_ATA_DATA0__IPU_DIAGB_7				0x27c 0x6e0 0x000 0x6 0x0
+#define MX35_PAD_ATA_DATA0__ARM11P_TOP_MAX0_HMASTER_3		0x27c 0x6e0 0x000 0x7 0x0
+#define MX35_PAD_ATA_DATA1__ATA_DATA_1				0x280 0x6e4 0x000 0x0 0x0
+#define MX35_PAD_ATA_DATA1__ESDHC3_DAT6				0x280 0x6e4 0x000 0x1 0x0
+#define MX35_PAD_ATA_DATA1__USB_TOP_USBOTG_DATA_3		0x280 0x6e4 0x9b0 0x2 0x1
+#define MX35_PAD_ATA_DATA1__IPU_DISPB_SD_CLK			0x280 0x6e4 0x000 0x3 0x0
+#define MX35_PAD_ATA_DATA1__ESDHC2_DAT6				0x280 0x6e4 0x000 0x4 0x0
+#define MX35_PAD_ATA_DATA1__GPIO2_14				0x280 0x6e4 0x87c 0x5 0x1
+#define MX35_PAD_ATA_DATA1__IPU_DIAGB_8				0x280 0x6e4 0x000 0x6 0x0
+#define MX35_PAD_ATA_DATA1__ARM11P_TOP_TRACE_27			0x280 0x6e4 0x000 0x7 0x0
+#define MX35_PAD_ATA_DATA2__ATA_DATA_2				0x284 0x6e8 0x000 0x0 0x0
+#define MX35_PAD_ATA_DATA2__ESDHC3_DAT7				0x284 0x6e8 0x000 0x1 0x0
+#define MX35_PAD_ATA_DATA2__USB_TOP_USBOTG_DATA_4		0x284 0x6e8 0x9b4 0x2 0x1
+#define MX35_PAD_ATA_DATA2__IPU_DISPB_SER_RS			0x284 0x6e8 0x000 0x3 0x0
+#define MX35_PAD_ATA_DATA2__ESDHC2_DAT7				0x284 0x6e8 0x000 0x4 0x0
+#define MX35_PAD_ATA_DATA2__GPIO2_15				0x284 0x6e8 0x880 0x5 0x1
+#define MX35_PAD_ATA_DATA2__IPU_DIAGB_9				0x284 0x6e8 0x000 0x6 0x0
+#define MX35_PAD_ATA_DATA2__ARM11P_TOP_TRACE_28			0x284 0x6e8 0x000 0x7 0x0
+#define MX35_PAD_ATA_DATA3__ATA_DATA_3				0x288 0x6ec 0x000 0x0 0x0
+#define MX35_PAD_ATA_DATA3__ESDHC3_CLK				0x288 0x6ec 0x814 0x1 0x1
+#define MX35_PAD_ATA_DATA3__USB_TOP_USBOTG_DATA_5		0x288 0x6ec 0x9b8 0x2 0x1
+#define MX35_PAD_ATA_DATA3__CSPI2_SCLK				0x288 0x6ec 0x7e0 0x4 0x2
+#define MX35_PAD_ATA_DATA3__GPIO2_16				0x288 0x6ec 0x884 0x5 0x1
+#define MX35_PAD_ATA_DATA3__IPU_DIAGB_10			0x288 0x6ec 0x000 0x6 0x0
+#define MX35_PAD_ATA_DATA3__ARM11P_TOP_TRACE_29			0x288 0x6ec 0x000 0x7 0x0
+#define MX35_PAD_ATA_DATA4__ATA_DATA_4				0x28c 0x6f0 0x000 0x0 0x0
+#define MX35_PAD_ATA_DATA4__ESDHC3_CMD				0x28c 0x6f0 0x818 0x1 0x1
+#define MX35_PAD_ATA_DATA4__USB_TOP_USBOTG_DATA_6		0x28c 0x6f0 0x9bc 0x2 0x1
+#define MX35_PAD_ATA_DATA4__GPIO2_17				0x28c 0x6f0 0x888 0x5 0x1
+#define MX35_PAD_ATA_DATA4__IPU_DIAGB_11			0x28c 0x6f0 0x000 0x6 0x0
+#define MX35_PAD_ATA_DATA4__ARM11P_TOP_TRACE_30			0x28c 0x6f0 0x000 0x7 0x0
+#define MX35_PAD_ATA_DATA5__ATA_DATA_5				0x290 0x6f4 0x000 0x0 0x0
+#define MX35_PAD_ATA_DATA5__USB_TOP_USBOTG_DATA_7		0x290 0x6f4 0x9c0 0x2 0x1
+#define MX35_PAD_ATA_DATA5__GPIO2_18				0x290 0x6f4 0x88c 0x5 0x1
+#define MX35_PAD_ATA_DATA5__IPU_DIAGB_12			0x290 0x6f4 0x000 0x6 0x0
+#define MX35_PAD_ATA_DATA5__ARM11P_TOP_TRACE_31			0x290 0x6f4 0x000 0x7 0x0
+#define MX35_PAD_ATA_DATA6__ATA_DATA_6				0x294 0x6f8 0x000 0x0 0x0
+#define MX35_PAD_ATA_DATA6__CAN1_TXCAN				0x294 0x6f8 0x000 0x1 0x0
+#define MX35_PAD_ATA_DATA6__UART1_DTR				0x294 0x6f8 0x000 0x2 0x0
+#define MX35_PAD_ATA_DATA6__AUDMUX_AUD6_TXD			0x294 0x6f8 0x7b4 0x3 0x0
+#define MX35_PAD_ATA_DATA6__GPIO2_19				0x294 0x6f8 0x890 0x5 0x1
+#define MX35_PAD_ATA_DATA6__IPU_DIAGB_13			0x294 0x6f8 0x000 0x6 0x0
+#define MX35_PAD_ATA_DATA7__ATA_DATA_7				0x298 0x6fc 0x000 0x0 0x0
+#define MX35_PAD_ATA_DATA7__CAN1_RXCAN				0x298 0x6fc 0x7c8 0x1 0x2
+#define MX35_PAD_ATA_DATA7__UART1_DSR				0x298 0x6fc 0x000 0x2 0x0
+#define MX35_PAD_ATA_DATA7__AUDMUX_AUD6_RXD			0x298 0x6fc 0x7b0 0x3 0x0
+#define MX35_PAD_ATA_DATA7__GPIO2_20				0x298 0x6fc 0x898 0x5 0x1
+#define MX35_PAD_ATA_DATA7__IPU_DIAGB_14			0x298 0x6fc 0x000 0x6 0x0
+#define MX35_PAD_ATA_DATA8__ATA_DATA_8				0x29c 0x700 0x000 0x0 0x0
+#define MX35_PAD_ATA_DATA8__UART3_RTS				0x29c 0x700 0x99c 0x1 0x1
+#define MX35_PAD_ATA_DATA8__UART1_RI				0x29c 0x700 0x000 0x2 0x0
+#define MX35_PAD_ATA_DATA8__AUDMUX_AUD6_TXC			0x29c 0x700 0x7c0 0x3 0x0
+#define MX35_PAD_ATA_DATA8__GPIO2_21				0x29c 0x700 0x89c 0x5 0x1
+#define MX35_PAD_ATA_DATA8__IPU_DIAGB_15			0x29c 0x700 0x000 0x6 0x0
+#define MX35_PAD_ATA_DATA9__ATA_DATA_9				0x2a0 0x704 0x000 0x0 0x0
+#define MX35_PAD_ATA_DATA9__UART3_CTS				0x2a0 0x704 0x000 0x1 0x0
+#define MX35_PAD_ATA_DATA9__UART1_DCD				0x2a0 0x704 0x000 0x2 0x0
+#define MX35_PAD_ATA_DATA9__AUDMUX_AUD6_TXFS			0x2a0 0x704 0x7c4 0x3 0x0
+#define MX35_PAD_ATA_DATA9__GPIO2_22				0x2a0 0x704 0x8a0 0x5 0x1
+#define MX35_PAD_ATA_DATA9__IPU_DIAGB_16			0x2a0 0x704 0x000 0x6 0x0
+#define MX35_PAD_ATA_DATA10__ATA_DATA_10			0x2a4 0x708 0x000 0x0 0x0
+#define MX35_PAD_ATA_DATA10__UART3_RXD_MUX			0x2a4 0x708 0x9a0 0x1 0x2
+#define MX35_PAD_ATA_DATA10__AUDMUX_AUD6_RXC			0x2a4 0x708 0x7b8 0x3 0x0
+#define MX35_PAD_ATA_DATA10__GPIO2_23				0x2a4 0x708 0x8a4 0x5 0x1
+#define MX35_PAD_ATA_DATA10__IPU_DIAGB_17			0x2a4 0x708 0x000 0x6 0x0
+#define MX35_PAD_ATA_DATA11__ATA_DATA_11			0x2a8 0x70c 0x000 0x0 0x0
+#define MX35_PAD_ATA_DATA11__UART3_TXD_MUX			0x2a8 0x70c 0x000 0x1 0x0
+#define MX35_PAD_ATA_DATA11__AUDMUX_AUD6_RXFS			0x2a8 0x70c 0x7bc 0x3 0x0
+#define MX35_PAD_ATA_DATA11__GPIO2_24				0x2a8 0x70c 0x8a8 0x5 0x1
+#define MX35_PAD_ATA_DATA11__IPU_DIAGB_18			0x2a8 0x70c 0x000 0x6 0x0
+#define MX35_PAD_ATA_DATA12__ATA_DATA_12			0x2ac 0x710 0x000 0x0 0x0
+#define MX35_PAD_ATA_DATA12__I2C3_SCL				0x2ac 0x710 0x91c 0x1 0x3
+#define MX35_PAD_ATA_DATA12__GPIO2_25				0x2ac 0x710 0x8ac 0x5 0x1
+#define MX35_PAD_ATA_DATA12__IPU_DIAGB_19			0x2ac 0x710 0x000 0x6 0x0
+#define MX35_PAD_ATA_DATA13__ATA_DATA_13			0x2b0 0x714 0x000 0x0 0x0
+#define MX35_PAD_ATA_DATA13__I2C3_SDA				0x2b0 0x714 0x920 0x1 0x3
+#define MX35_PAD_ATA_DATA13__GPIO2_26				0x2b0 0x714 0x8b0 0x5 0x1
+#define MX35_PAD_ATA_DATA13__IPU_DIAGB_20			0x2b0 0x714 0x000 0x6 0x0
+#define MX35_PAD_ATA_DATA14__ATA_DATA_14			0x2b4 0x718 0x000 0x0 0x0
+#define MX35_PAD_ATA_DATA14__IPU_CSI_D_0			0x2b4 0x718 0x930 0x1 0x2
+#define MX35_PAD_ATA_DATA14__KPP_ROW_0				0x2b4 0x718 0x970 0x3 0x2
+#define MX35_PAD_ATA_DATA14__GPIO2_27				0x2b4 0x718 0x8b4 0x5 0x1
+#define MX35_PAD_ATA_DATA14__IPU_DIAGB_21			0x2b4 0x718 0x000 0x6 0x0
+#define MX35_PAD_ATA_DATA15__ATA_DATA_15			0x2b8 0x71c 0x000 0x0 0x0
+#define MX35_PAD_ATA_DATA15__IPU_CSI_D_1			0x2b8 0x71c 0x934 0x1 0x2
+#define MX35_PAD_ATA_DATA15__KPP_ROW_1				0x2b8 0x71c 0x974 0x3 0x2
+#define MX35_PAD_ATA_DATA15__GPIO2_28				0x2b8 0x71c 0x8b8 0x5 0x1
+#define MX35_PAD_ATA_DATA15__IPU_DIAGB_22			0x2b8 0x71c 0x000 0x6 0x0
+#define MX35_PAD_ATA_INTRQ__ATA_INTRQ				0x2bc 0x720 0x000 0x0 0x0
+#define MX35_PAD_ATA_INTRQ__IPU_CSI_D_2				0x2bc 0x720 0x938 0x1 0x3
+#define MX35_PAD_ATA_INTRQ__KPP_ROW_2				0x2bc 0x720 0x978 0x3 0x2
+#define MX35_PAD_ATA_INTRQ__GPIO2_29				0x2bc 0x720 0x8bc 0x5 0x1
+#define MX35_PAD_ATA_INTRQ__IPU_DIAGB_23			0x2bc 0x720 0x000 0x6 0x0
+#define MX35_PAD_ATA_BUFF_EN__ATA_BUFFER_EN			0x2c0 0x724 0x000 0x0 0x0
+#define MX35_PAD_ATA_BUFF_EN__IPU_CSI_D_3			0x2c0 0x724 0x93c 0x1 0x3
+#define MX35_PAD_ATA_BUFF_EN__KPP_ROW_3				0x2c0 0x724 0x97c 0x3 0x2
+#define MX35_PAD_ATA_BUFF_EN__GPIO2_30				0x2c0 0x724 0x8c4 0x5 0x1
+#define MX35_PAD_ATA_BUFF_EN__IPU_DIAGB_24			0x2c0 0x724 0x000 0x6 0x0
+#define MX35_PAD_ATA_DMARQ__ATA_DMARQ				0x2c4 0x728 0x000 0x0 0x0
+#define MX35_PAD_ATA_DMARQ__IPU_CSI_D_4				0x2c4 0x728 0x940 0x1 0x2
+#define MX35_PAD_ATA_DMARQ__KPP_COL_0				0x2c4 0x728 0x950 0x3 0x2
+#define MX35_PAD_ATA_DMARQ__GPIO2_31				0x2c4 0x728 0x8c8 0x5 0x1
+#define MX35_PAD_ATA_DMARQ__IPU_DIAGB_25			0x2c4 0x728 0x000 0x6 0x0
+#define MX35_PAD_ATA_DMARQ__ECT_CTI_TRIG_IN1_4			0x2c4 0x728 0x000 0x7 0x0
+#define MX35_PAD_ATA_DA0__ATA_DA_0				0x2c8 0x72c 0x000 0x0 0x0
+#define MX35_PAD_ATA_DA0__IPU_CSI_D_5				0x2c8 0x72c 0x944 0x1 0x2
+#define MX35_PAD_ATA_DA0__KPP_COL_1				0x2c8 0x72c 0x954 0x3 0x2
+#define MX35_PAD_ATA_DA0__GPIO3_0				0x2c8 0x72c 0x8e8 0x5 0x1
+#define MX35_PAD_ATA_DA0__IPU_DIAGB_26				0x2c8 0x72c 0x000 0x6 0x0
+#define MX35_PAD_ATA_DA0__ECT_CTI_TRIG_IN1_5			0x2c8 0x72c 0x000 0x7 0x0
+#define MX35_PAD_ATA_DA1__ATA_DA_1				0x2cc 0x730 0x000 0x0 0x0
+#define MX35_PAD_ATA_DA1__IPU_CSI_D_6				0x2cc 0x730 0x948 0x1 0x2
+#define MX35_PAD_ATA_DA1__KPP_COL_2				0x2cc 0x730 0x958 0x3 0x2
+#define MX35_PAD_ATA_DA1__GPIO3_1				0x2cc 0x730 0x000 0x5 0x0
+#define MX35_PAD_ATA_DA1__IPU_DIAGB_27				0x2cc 0x730 0x000 0x6 0x0
+#define MX35_PAD_ATA_DA1__ECT_CTI_TRIG_IN1_6			0x2cc 0x730 0x000 0x7 0x0
+#define MX35_PAD_ATA_DA2__ATA_DA_2				0x2d0 0x734 0x000 0x0 0x0
+#define MX35_PAD_ATA_DA2__IPU_CSI_D_7				0x2d0 0x734 0x94c 0x1 0x2
+#define MX35_PAD_ATA_DA2__KPP_COL_3				0x2d0 0x734 0x95c 0x3 0x2
+#define MX35_PAD_ATA_DA2__GPIO3_2				0x2d0 0x734 0x000 0x5 0x0
+#define MX35_PAD_ATA_DA2__IPU_DIAGB_28				0x2d0 0x734 0x000 0x6 0x0
+#define MX35_PAD_ATA_DA2__ECT_CTI_TRIG_IN1_7			0x2d0 0x734 0x000 0x7 0x0
+#define MX35_PAD_MLB_CLK__MLB_MLBCLK				0x2d4 0x738 0x000 0x0 0x0
+#define MX35_PAD_MLB_CLK__GPIO3_3				0x2d4 0x738 0x000 0x5 0x0
+#define MX35_PAD_MLB_DAT__MLB_MLBDAT				0x2d8 0x73c 0x000 0x0 0x0
+#define MX35_PAD_MLB_DAT__GPIO3_4				0x2d8 0x73c 0x904 0x5 0x1
+#define MX35_PAD_MLB_SIG__MLB_MLBSIG				0x2dc 0x740 0x000 0x0 0x0
+#define MX35_PAD_MLB_SIG__GPIO3_5				0x2dc 0x740 0x908 0x5 0x1
+#define MX35_PAD_FEC_TX_CLK__FEC_TX_CLK				0x2e0 0x744 0x000 0x0 0x0
+#define MX35_PAD_FEC_TX_CLK__ESDHC1_DAT4			0x2e0 0x744 0x804 0x1 0x1
+#define MX35_PAD_FEC_TX_CLK__UART3_RXD_MUX			0x2e0 0x744 0x9a0 0x2 0x3
+#define MX35_PAD_FEC_TX_CLK__USB_TOP_USBH2_DIR			0x2e0 0x744 0x9ec 0x3 0x1
+#define MX35_PAD_FEC_TX_CLK__CSPI2_MOSI				0x2e0 0x744 0x7ec 0x4 0x3
+#define MX35_PAD_FEC_TX_CLK__GPIO3_6				0x2e0 0x744 0x90c 0x5 0x1
+#define MX35_PAD_FEC_TX_CLK__IPU_DISPB_D12_VSYNC		0x2e0 0x744 0x928 0x6 0x5
+#define MX35_PAD_FEC_TX_CLK__ARM11P_TOP_EVNTBUS_0		0x2e0 0x744 0x000 0x7 0x0
+#define MX35_PAD_FEC_RX_CLK__FEC_RX_CLK				0x2e4 0x748 0x000 0x0 0x0
+#define MX35_PAD_FEC_RX_CLK__ESDHC1_DAT5			0x2e4 0x748 0x808 0x1 0x1
+#define MX35_PAD_FEC_RX_CLK__UART3_TXD_MUX			0x2e4 0x748 0x000 0x2 0x0
+#define MX35_PAD_FEC_RX_CLK__USB_TOP_USBH2_STP			0x2e4 0x748 0x000 0x3 0x0
+#define MX35_PAD_FEC_RX_CLK__CSPI2_MISO				0x2e4 0x748 0x7e8 0x4 0x3
+#define MX35_PAD_FEC_RX_CLK__GPIO3_7				0x2e4 0x748 0x910 0x5 0x1
+#define MX35_PAD_FEC_RX_CLK__IPU_DISPB_SD_D_I			0x2e4 0x748 0x92c 0x6 0x4
+#define MX35_PAD_FEC_RX_CLK__ARM11P_TOP_EVNTBUS_1		0x2e4 0x748 0x000 0x7 0x0
+#define MX35_PAD_FEC_RX_DV__FEC_RX_DV				0x2e8 0x74c 0x000 0x0 0x0
+#define MX35_PAD_FEC_RX_DV__ESDHC1_DAT6				0x2e8 0x74c 0x80c 0x1 0x1
+#define MX35_PAD_FEC_RX_DV__UART3_RTS				0x2e8 0x74c 0x99c 0x2 0x2
+#define MX35_PAD_FEC_RX_DV__USB_TOP_USBH2_NXT			0x2e8 0x74c 0x9f0 0x3 0x1
+#define MX35_PAD_FEC_RX_DV__CSPI2_SCLK				0x2e8 0x74c 0x7e0 0x4 0x3
+#define MX35_PAD_FEC_RX_DV__GPIO3_8				0x2e8 0x74c 0x914 0x5 0x1
+#define MX35_PAD_FEC_RX_DV__IPU_DISPB_SD_CLK			0x2e8 0x74c 0x000 0x6 0x0
+#define MX35_PAD_FEC_RX_DV__ARM11P_TOP_EVNTBUS_2		0x2e8 0x74c 0x000 0x7 0x0
+#define MX35_PAD_FEC_COL__FEC_COL				0x2ec 0x750 0x000 0x0 0x0
+#define MX35_PAD_FEC_COL__ESDHC1_DAT7				0x2ec 0x750 0x810 0x1 0x1
+#define MX35_PAD_FEC_COL__UART3_CTS				0x2ec 0x750 0x000 0x2 0x0
+#define MX35_PAD_FEC_COL__USB_TOP_USBH2_DATA_0			0x2ec 0x750 0x9cc 0x3 0x1
+#define MX35_PAD_FEC_COL__CSPI2_RDY				0x2ec 0x750 0x7e4 0x4 0x3
+#define MX35_PAD_FEC_COL__GPIO3_9				0x2ec 0x750 0x918 0x5 0x1
+#define MX35_PAD_FEC_COL__IPU_DISPB_SER_RS			0x2ec 0x750 0x000 0x6 0x0
+#define MX35_PAD_FEC_COL__ARM11P_TOP_EVNTBUS_3			0x2ec 0x750 0x000 0x7 0x0
+#define MX35_PAD_FEC_RDATA0__FEC_RDATA_0			0x2f0 0x754 0x000 0x0 0x0
+#define MX35_PAD_FEC_RDATA0__PWM_PWMO				0x2f0 0x754 0x000 0x1 0x0
+#define MX35_PAD_FEC_RDATA0__UART3_DTR				0x2f0 0x754 0x000 0x2 0x0
+#define MX35_PAD_FEC_RDATA0__USB_TOP_USBH2_DATA_1		0x2f0 0x754 0x9d0 0x3 0x1
+#define MX35_PAD_FEC_RDATA0__CSPI2_SS0				0x2f0 0x754 0x7f0 0x4 0x2
+#define MX35_PAD_FEC_RDATA0__GPIO3_10				0x2f0 0x754 0x8ec 0x5 0x1
+#define MX35_PAD_FEC_RDATA0__IPU_DISPB_CS1			0x2f0 0x754 0x000 0x6 0x0
+#define MX35_PAD_FEC_RDATA0__ARM11P_TOP_EVNTBUS_4		0x2f0 0x754 0x000 0x7 0x0
+#define MX35_PAD_FEC_TDATA0__FEC_TDATA_0			0x2f4 0x758 0x000 0x0 0x0
+#define MX35_PAD_FEC_TDATA0__SPDIF_SPDIF_OUT1			0x2f4 0x758 0x000 0x1 0x0
+#define MX35_PAD_FEC_TDATA0__UART3_DSR				0x2f4 0x758 0x000 0x2 0x0
+#define MX35_PAD_FEC_TDATA0__USB_TOP_USBH2_DATA_2		0x2f4 0x758 0x9d4 0x3 0x1
+#define MX35_PAD_FEC_TDATA0__CSPI2_SS1				0x2f4 0x758 0x7f4 0x4 0x2
+#define MX35_PAD_FEC_TDATA0__GPIO3_11				0x2f4 0x758 0x8f0 0x5 0x1
+#define MX35_PAD_FEC_TDATA0__IPU_DISPB_CS0			0x2f4 0x758 0x000 0x6 0x0
+#define MX35_PAD_FEC_TDATA0__ARM11P_TOP_EVNTBUS_5		0x2f4 0x758 0x000 0x7 0x0
+#define MX35_PAD_FEC_TX_EN__FEC_TX_EN				0x2f8 0x75c 0x000 0x0 0x0
+#define MX35_PAD_FEC_TX_EN__SPDIF_SPDIF_IN1			0x2f8 0x75c 0x998 0x1 0x3
+#define MX35_PAD_FEC_TX_EN__UART3_RI				0x2f8 0x75c 0x000 0x2 0x0
+#define MX35_PAD_FEC_TX_EN__USB_TOP_USBH2_DATA_3		0x2f8 0x75c 0x9d8 0x3 0x1
+#define MX35_PAD_FEC_TX_EN__GPIO3_12				0x2f8 0x75c 0x8f4 0x5 0x1
+#define MX35_PAD_FEC_TX_EN__IPU_DISPB_PAR_RS			0x2f8 0x75c 0x000 0x6 0x0
+#define MX35_PAD_FEC_TX_EN__ARM11P_TOP_EVNTBUS_6		0x2f8 0x75c 0x000 0x7 0x0
+#define MX35_PAD_FEC_MDC__FEC_MDC				0x2fc 0x760 0x000 0x0 0x0
+#define MX35_PAD_FEC_MDC__CAN2_TXCAN				0x2fc 0x760 0x000 0x1 0x0
+#define MX35_PAD_FEC_MDC__UART3_DCD				0x2fc 0x760 0x000 0x2 0x0
+#define MX35_PAD_FEC_MDC__USB_TOP_USBH2_DATA_4			0x2fc 0x760 0x9dc 0x3 0x1
+#define MX35_PAD_FEC_MDC__GPIO3_13				0x2fc 0x760 0x8f8 0x5 0x1
+#define MX35_PAD_FEC_MDC__IPU_DISPB_WR				0x2fc 0x760 0x000 0x6 0x0
+#define MX35_PAD_FEC_MDC__ARM11P_TOP_EVNTBUS_7			0x2fc 0x760 0x000 0x7 0x0
+#define MX35_PAD_FEC_MDIO__FEC_MDIO				0x300 0x764 0x000 0x0 0x0
+#define MX35_PAD_FEC_MDIO__CAN2_RXCAN				0x300 0x764 0x7cc 0x1 0x2
+#define MX35_PAD_FEC_MDIO__USB_TOP_USBH2_DATA_5			0x300 0x764 0x9e0 0x3 0x1
+#define MX35_PAD_FEC_MDIO__GPIO3_14				0x300 0x764 0x8fc 0x5 0x1
+#define MX35_PAD_FEC_MDIO__IPU_DISPB_RD				0x300 0x764 0x000 0x6 0x0
+#define MX35_PAD_FEC_MDIO__ARM11P_TOP_EVNTBUS_8			0x300 0x764 0x000 0x7 0x0
+#define MX35_PAD_FEC_TX_ERR__FEC_TX_ERR				0x304 0x768 0x000 0x0 0x0
+#define MX35_PAD_FEC_TX_ERR__OWIRE_LINE				0x304 0x768 0x990 0x1 0x2
+#define MX35_PAD_FEC_TX_ERR__SPDIF_SPDIF_EXTCLK			0x304 0x768 0x994 0x2 0x4
+#define MX35_PAD_FEC_TX_ERR__USB_TOP_USBH2_DATA_6		0x304 0x768 0x9e4 0x3 0x1
+#define MX35_PAD_FEC_TX_ERR__GPIO3_15				0x304 0x768 0x900 0x5 0x1
+#define MX35_PAD_FEC_TX_ERR__IPU_DISPB_D0_VSYNC			0x304 0x768 0x924 0x6 0x3
+#define MX35_PAD_FEC_TX_ERR__ARM11P_TOP_EVNTBUS_9		0x304 0x768 0x000 0x7 0x0
+#define MX35_PAD_FEC_RX_ERR__FEC_RX_ERR				0x308 0x76c 0x000 0x0 0x0
+#define MX35_PAD_FEC_RX_ERR__IPU_CSI_D_0			0x308 0x76c 0x930 0x1 0x3
+#define MX35_PAD_FEC_RX_ERR__USB_TOP_USBH2_DATA_7		0x308 0x76c 0x9e8 0x3 0x1
+#define MX35_PAD_FEC_RX_ERR__KPP_COL_4				0x308 0x76c 0x960 0x4 0x1
+#define MX35_PAD_FEC_RX_ERR__GPIO3_16				0x308 0x76c 0x000 0x5 0x0
+#define MX35_PAD_FEC_RX_ERR__IPU_DISPB_SD_D_IO			0x308 0x76c 0x92c 0x6 0x5
+#define MX35_PAD_FEC_CRS__FEC_CRS				0x30c 0x770 0x000 0x0 0x0
+#define MX35_PAD_FEC_CRS__IPU_CSI_D_1				0x30c 0x770 0x934 0x1 0x3
+#define MX35_PAD_FEC_CRS__USB_TOP_USBH2_PWR			0x30c 0x770 0x000 0x3 0x0
+#define MX35_PAD_FEC_CRS__KPP_COL_5				0x30c 0x770 0x964 0x4 0x1
+#define MX35_PAD_FEC_CRS__GPIO3_17				0x30c 0x770 0x000 0x5 0x0
+#define MX35_PAD_FEC_CRS__IPU_FLASH_STROBE			0x30c 0x770 0x000 0x6 0x0
+#define MX35_PAD_FEC_RDATA1__FEC_RDATA_1			0x310 0x774 0x000 0x0 0x0
+#define MX35_PAD_FEC_RDATA1__IPU_CSI_D_2			0x310 0x774 0x938 0x1 0x4
+#define MX35_PAD_FEC_RDATA1__AUDMUX_AUD6_RXC			0x310 0x774 0x000 0x2 0x0
+#define MX35_PAD_FEC_RDATA1__USB_TOP_USBH2_OC			0x310 0x774 0x9f4 0x3 0x2
+#define MX35_PAD_FEC_RDATA1__KPP_COL_6				0x310 0x774 0x968 0x4 0x1
+#define MX35_PAD_FEC_RDATA1__GPIO3_18				0x310 0x774 0x000 0x5 0x0
+#define MX35_PAD_FEC_RDATA1__IPU_DISPB_BE0			0x310 0x774 0x000 0x6 0x0
+#define MX35_PAD_FEC_TDATA1__FEC_TDATA_1			0x314 0x778 0x000 0x0 0x0
+#define MX35_PAD_FEC_TDATA1__IPU_CSI_D_3			0x314 0x778 0x93c 0x1 0x4
+#define MX35_PAD_FEC_TDATA1__AUDMUX_AUD6_RXFS			0x314 0x778 0x7bc 0x2 0x1
+#define MX35_PAD_FEC_TDATA1__KPP_COL_7				0x314 0x778 0x96c 0x4 0x1
+#define MX35_PAD_FEC_TDATA1__GPIO3_19				0x314 0x778 0x000 0x5 0x0
+#define MX35_PAD_FEC_TDATA1__IPU_DISPB_BE1			0x314 0x778 0x000 0x6 0x0
+#define MX35_PAD_FEC_RDATA2__FEC_RDATA_2			0x318 0x77c 0x000 0x0 0x0
+#define MX35_PAD_FEC_RDATA2__IPU_CSI_D_4			0x318 0x77c 0x940 0x1 0x3
+#define MX35_PAD_FEC_RDATA2__AUDMUX_AUD6_TXD			0x318 0x77c 0x7b4 0x2 0x1
+#define MX35_PAD_FEC_RDATA2__KPP_ROW_4				0x318 0x77c 0x980 0x4 0x1
+#define MX35_PAD_FEC_RDATA2__GPIO3_20				0x318 0x77c 0x000 0x5 0x0
+#define MX35_PAD_FEC_TDATA2__FEC_TDATA_2			0x31c 0x780 0x000 0x0 0x0
+#define MX35_PAD_FEC_TDATA2__IPU_CSI_D_5			0x31c 0x780 0x944 0x1 0x3
+#define MX35_PAD_FEC_TDATA2__AUDMUX_AUD6_RXD			0x31c 0x780 0x7b0 0x2 0x1
+#define MX35_PAD_FEC_TDATA2__KPP_ROW_5				0x31c 0x780 0x984 0x4 0x1
+#define MX35_PAD_FEC_TDATA2__GPIO3_21				0x31c 0x780 0x000 0x5 0x0
+#define MX35_PAD_FEC_RDATA3__FEC_RDATA_3			0x320 0x784 0x000 0x0 0x0
+#define MX35_PAD_FEC_RDATA3__IPU_CSI_D_6			0x320 0x784 0x948 0x1 0x3
+#define MX35_PAD_FEC_RDATA3__AUDMUX_AUD6_TXC			0x320 0x784 0x7c0 0x2 0x1
+#define MX35_PAD_FEC_RDATA3__KPP_ROW_6				0x320 0x784 0x988 0x4 0x1
+#define MX35_PAD_FEC_RDATA3__GPIO3_22				0x320 0x784 0x000 0x6 0x0
+#define MX35_PAD_FEC_TDATA3__FEC_TDATA_3			0x324 0x788 0x000 0x0 0x0
+#define MX35_PAD_FEC_TDATA3__IPU_CSI_D_7			0x324 0x788 0x94c 0x1 0x3
+#define MX35_PAD_FEC_TDATA3__AUDMUX_AUD6_TXFS			0x324 0x788 0x7c4 0x2 0x1
+#define MX35_PAD_FEC_TDATA3__KPP_ROW_7				0x324 0x788 0x98c 0x4 0x1
+#define MX35_PAD_FEC_TDATA3__GPIO3_23				0x324 0x788 0x000 0x5 0x0
+#define MX35_PAD_EXT_ARMCLK__CCM_EXT_ARMCLK			0x000 0x78c 0x000 0x0 0x0
+#define MX35_PAD_TEST_MODE__TCU_TEST_MODE			0x000 0x790 0x000 0x0 0x0
+
+#endif /* __DTS_IMX35_PINFUNC_H */
diff --git a/arch/arm/boot/dts/imx51-apf51.dts b/arch/arm/boot/dts/imx51-apf51.dts
deleted file mode 100644
index 92d3a66..0000000
--- a/arch/arm/boot/dts/imx51-apf51.dts
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright 2012 Armadeus Systems - <support@armadeus.com>
- * Copyright 2012 Laurent Cans <laurent.cans@gmail.com>
- *
- * Based on mx51-babbage.dts
- * Copyright 2011 Freescale Semiconductor, Inc.
- * Copyright 2011 Linaro Ltd.
- *
- * 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
- */
-
-/dts-v1/;
-/include/ "imx51.dtsi"
-
-/ {
-	model = "Armadeus Systems APF51 module";
-	compatible = "armadeus,imx51-apf51", "fsl,imx51";
-
-	memory {
-		reg = <0x90000000 0x20000000>;
-	};
-
-	clocks {
-		ckih1 {
-			clock-frequency = <0>;
-		};
-
-		osc {
-			clock-frequency = <33554432>;
-		};
-	};
-};
-
-&fec {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_fec_2>;
-	phy-mode = "mii";
-	phy-reset-gpios = <&gpio3 0 0>;
-	phy-reset-duration = <1>;
-	status = "okay";
-};
-
-&uart3 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart3_2>;
-	status = "okay";
-};
diff --git a/arch/arm/boot/dts/imx51-apf51.dtsp b/arch/arm/boot/dts/imx51-apf51.dtsp
new file mode 100644
index 0000000..4ef88fc
--- /dev/null
+++ b/arch/arm/boot/dts/imx51-apf51.dtsp
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2012 Armadeus Systems - <support@armadeus.com>
+ * Copyright 2012 Laurent Cans <laurent.cans@gmail.com>
+ *
+ * Based on mx51-babbage.dts
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * 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
+ */
+
+/dts-v1/;
+#include "imx51.dtsip"
+
+/ {
+	model = "Armadeus Systems APF51 module";
+	compatible = "armadeus,imx51-apf51", "fsl,imx51";
+
+	memory {
+		reg = <0x90000000 0x20000000>;
+	};
+
+	clocks {
+		ckih1 {
+			clock-frequency = <0>;
+		};
+
+		osc {
+			clock-frequency = <33554432>;
+		};
+	};
+};
+
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_fec_2>;
+	phy-mode = "mii";
+	phy-reset-gpios = <&gpio3 0 0>;
+	phy-reset-duration = <1>;
+	status = "okay";
+};
+
+&uart3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart3_2>;
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx51-apf51dev.dtsp b/arch/arm/boot/dts/imx51-apf51dev.dtsp
new file mode 100644
index 0000000..8eb2995
--- /dev/null
+++ b/arch/arm/boot/dts/imx51-apf51dev.dtsp
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2013 Armadeus Systems - <support@armadeus.com>
+ *
+ * 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
+ */
+
+/* APF51Dev is a docking board for the APF51 SOM */
+#include "imx51-apf51.dtsp"
+
+/ {
+	model = "Armadeus Systems APF51Dev docking/development board";
+	compatible = "armadeus,imx51-apf51dev", "armadeus,imx51-apf51", "fsl,imx51";
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		user-key {
+			label = "user";
+			gpios = <&gpio1 3 0>;
+			linux,code = <256>; /* BTN_0 */
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		user {
+			label = "Heartbeat";
+			gpios = <&gpio1 2 0>;
+			linux,default-trigger = "heartbeat";
+		};
+	};
+};
+
+&ecspi1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ecspi1_1>;
+	fsl,spi-num-chipselects = <2>;
+	cs-gpios = <&gpio4 24 0>, <&gpio4 25 0>;
+	status = "okay";
+};
+
+&ecspi2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ecspi2_1>;
+	fsl,spi-num-chipselects = <2>;
+	cs-gpios = <&gpio3 28 1>, <&gpio3 27 1>;
+	status = "okay";
+};
+
+&esdhc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_esdhc1_1>;
+	cd-gpios = <&gpio2 29 0>;
+	bus-width = <4>;
+	status = "okay";
+};
+
+&esdhc2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_esdhc2_1>;
+	bus-width = <4>;
+	non-removable;
+	status = "okay";
+};
+
+&i2c2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2_2>;
+	status = "okay";
+};
+
+&iomuxc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hog>;
+
+	hog {
+		pinctrl_hog: hoggrp {
+			fsl,pins = <
+				MX51_PAD_EIM_EB2__GPIO2_22   0x0C5
+				MX51_PAD_EIM_EB3__GPIO2_23   0x0C5
+				MX51_PAD_EIM_CS4__GPIO2_29   0x100
+				MX51_PAD_NANDF_D13__GPIO3_27 0x0C5
+				MX51_PAD_NANDF_D12__GPIO3_28 0x0C5
+				MX51_PAD_CSPI1_SS0__GPIO4_24 0x0C5
+				MX51_PAD_CSPI1_SS1__GPIO4_25 0x0C5
+				MX51_PAD_GPIO1_2__GPIO1_2    0x0C5
+				MX51_PAD_GPIO1_3__GPIO1_3    0x0C5
+			>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/imx51-babbage.dts b/arch/arm/boot/dts/imx51-babbage.dts
deleted file mode 100644
index aab6e43..0000000
--- a/arch/arm/boot/dts/imx51-babbage.dts
+++ /dev/null
@@ -1,297 +0,0 @@
-/*
- * Copyright 2011 Freescale Semiconductor, Inc.
- * Copyright 2011 Linaro Ltd.
- *
- * 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
- */
-
-/dts-v1/;
-/include/ "imx51.dtsi"
-
-/ {
-	model = "Freescale i.MX51 Babbage Board";
-	compatible = "fsl,imx51-babbage", "fsl,imx51";
-
-	memory {
-		reg = <0x90000000 0x20000000>;
-	};
-
-	display@di0 {
-		compatible = "fsl,imx-parallel-display";
-		crtcs = <&ipu 0>;
-		interface-pix-fmt = "rgb24";
-		pinctrl-names = "default";
-		pinctrl-0 = <&pinctrl_ipu_disp1_1>;
-	};
-
-	display@di1 {
-		compatible = "fsl,imx-parallel-display";
-		crtcs = <&ipu 1>;
-		interface-pix-fmt = "rgb565";
-		pinctrl-names = "default";
-		pinctrl-0 = <&pinctrl_ipu_disp2_1>;
-	};
-
-	gpio-keys {
-		compatible = "gpio-keys";
-
-		power {
-			label = "Power Button";
-			gpios = <&gpio2 21 0>;
-			linux,code = <116>; /* KEY_POWER */
-			gpio-key,wakeup;
-		};
-	};
-
-	sound {
-		compatible = "fsl,imx51-babbage-sgtl5000",
-			     "fsl,imx-audio-sgtl5000";
-		model = "imx51-babbage-sgtl5000";
-		ssi-controller = <&ssi2>;
-		audio-codec = <&sgtl5000>;
-		audio-routing =
-			"MIC_IN", "Mic Jack",
-			"Mic Jack", "Mic Bias",
-			"Headphone Jack", "HP_OUT";
-		mux-int-port = <2>;
-		mux-ext-port = <3>;
-	};
-};
-
-&esdhc1 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_esdhc1_1>;
-	fsl,cd-controller;
-	fsl,wp-controller;
-	status = "okay";
-};
-
-&esdhc2 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_esdhc2_1>;
-	cd-gpios = <&gpio1 6 0>;
-	wp-gpios = <&gpio1 5 0>;
-	status = "okay";
-};
-
-&uart3 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart3_1>;
-	fsl,uart-has-rtscts;
-	status = "okay";
-};
-
-&ecspi1 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_ecspi1_1>;
-	fsl,spi-num-chipselects = <2>;
-	cs-gpios = <&gpio4 24 0>, <&gpio4 25 0>;
-	status = "okay";
-
-	pmic: mc13892@0 {
-		#address-cells = <1>;
-		#size-cells = <0>;
-		compatible = "fsl,mc13892";
-		spi-max-frequency = <6000000>;
-		reg = <0>;
-		interrupt-parent = <&gpio1>;
-		interrupts = <8 0x4>;
-
-		regulators {
-			sw1_reg: sw1 {
-				regulator-min-microvolt = <600000>;
-				regulator-max-microvolt = <1375000>;
-				regulator-boot-on;
-				regulator-always-on;
-			};
-
-			sw2_reg: sw2 {
-				regulator-min-microvolt = <900000>;
-				regulator-max-microvolt = <1850000>;
-				regulator-boot-on;
-				regulator-always-on;
-			};
-
-			sw3_reg: sw3 {
-				regulator-min-microvolt = <1100000>;
-				regulator-max-microvolt = <1850000>;
-				regulator-boot-on;
-				regulator-always-on;
-			};
-
-			sw4_reg: sw4 {
-				regulator-min-microvolt = <1100000>;
-				regulator-max-microvolt = <1850000>;
-				regulator-boot-on;
-				regulator-always-on;
-			};
-
-			vpll_reg: vpll {
-				regulator-min-microvolt = <1050000>;
-				regulator-max-microvolt = <1800000>;
-				regulator-boot-on;
-				regulator-always-on;
-			};
-
-			vdig_reg: vdig {
-				regulator-min-microvolt = <1650000>;
-				regulator-max-microvolt = <1650000>;
-				regulator-boot-on;
-			};
-
-			vsd_reg: vsd {
-				regulator-min-microvolt = <1800000>;
-				regulator-max-microvolt = <3150000>;
-			};
-
-			vusb2_reg: vusb2 {
-				regulator-min-microvolt = <2400000>;
-				regulator-max-microvolt = <2775000>;
-				regulator-boot-on;
-				regulator-always-on;
-			};
-
-			vvideo_reg: vvideo {
-				regulator-min-microvolt = <2775000>;
-				regulator-max-microvolt = <2775000>;
-			};
-
-			vaudio_reg: vaudio {
-				regulator-min-microvolt = <2300000>;
-				regulator-max-microvolt = <3000000>;
-			};
-
-			vcam_reg: vcam {
-				regulator-min-microvolt = <2500000>;
-				regulator-max-microvolt = <3000000>;
-			};
-
-			vgen1_reg: vgen1 {
-				regulator-min-microvolt = <1200000>;
-				regulator-max-microvolt = <1200000>;
-			};
-
-			vgen2_reg: vgen2 {
-				regulator-min-microvolt = <1200000>;
-				regulator-max-microvolt = <3150000>;
-				regulator-always-on;
-			};
-
-			vgen3_reg: vgen3 {
-				regulator-min-microvolt = <1800000>;
-				regulator-max-microvolt = <2900000>;
-				regulator-always-on;
-			};
-		};
-	};
-
-	flash: at45db321d@1 {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		compatible = "atmel,at45db321d", "atmel,at45", "atmel,dataflash";
-		spi-max-frequency = <25000000>;
-		reg = <1>;
-
-		partition@0 {
-			label = "U-Boot";
-			reg = <0x0 0x40000>;
-			read-only;
-		};
-
-		partition@40000 {
-			label = "Kernel";
-			reg = <0x40000 0x3c0000>;
-		};
-	};
-};
-
-&ssi2 {
-	fsl,mode = "i2s-slave";
-	status = "okay";
-};
-
-&iomuxc {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_hog>;
-
-	hog {
-		pinctrl_hog: hoggrp {
-			fsl,pins = <
-				694  0x20d5	/* MX51_PAD_GPIO1_0__SD1_CD */
-				697  0x20d5	/* MX51_PAD_GPIO1_1__SD1_WP */
-				737  0x100	/* MX51_PAD_GPIO1_5__GPIO1_5 */
-				740  0x100	/* MX51_PAD_GPIO1_6__GPIO1_6 */
-				121  0x5	/* MX51_PAD_EIM_A27__GPIO2_21 */
-				402  0x85	/* MX51_PAD_CSPI1_SS0__GPIO4_24 */
-				405  0x85	/* MX51_PAD_CSPI1_SS1__GPIO4_25 */
-			>;
-		};
-	};
-};
-
-&uart1 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart1_1>;
-	fsl,uart-has-rtscts;
-	status = "okay";
-};
-
-&uart2 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart2_1>;
-	status = "okay";
-};
-
-&i2c2 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_i2c2_1>;
-	status = "okay";
-
-	sgtl5000: codec@0a {
-		compatible = "fsl,sgtl5000";
-		reg = <0x0a>;
-		clock-frequency = <26000000>;
-		VDDA-supply = <&vdig_reg>;
-		VDDIO-supply = <&vvideo_reg>;
-	};
-};
-
-&audmux {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_audmux_1>;
-	status = "okay";
-};
-
-&fec {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_fec_1>;
-	phy-mode = "mii";
-	status = "okay";
-};
-
-&kpp {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_kpp_1>;
-	linux,keymap = <0x00000067	/* KEY_UP */
-			0x0001006c	/* KEY_DOWN */
-			0x00020072	/* KEY_VOLUMEDOWN */
-			0x00030066	/* KEY_HOME */
-			0x0100006a	/* KEY_RIGHT */
-			0x01010069	/* KEY_LEFT */
-			0x0102001c	/* KEY_ENTER */
-			0x01030073	/* KEY_VOLUMEUP */
-			0x02000040	/* KEY_F6 */
-			0x02010042	/* KEY_F8 */
-			0x02020043	/* KEY_F9 */
-			0x02030044	/* KEY_F10 */
-			0x0300003b	/* KEY_F1 */
-			0x0301003c	/* KEY_F2 */
-			0x0302003d	/* KEY_F3 */
-			0x03030074>;	/* KEY_POWER */
-	status = "okay";
-};
diff --git a/arch/arm/boot/dts/imx51-babbage.dtsp b/arch/arm/boot/dts/imx51-babbage.dtsp
new file mode 100644
index 0000000..c7b1630
--- /dev/null
+++ b/arch/arm/boot/dts/imx51-babbage.dtsp
@@ -0,0 +1,297 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * 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
+ */
+
+/dts-v1/;
+#include "imx51.dtsip"
+
+/ {
+	model = "Freescale i.MX51 Babbage Board";
+	compatible = "fsl,imx51-babbage", "fsl,imx51";
+
+	memory {
+		reg = <0x90000000 0x20000000>;
+	};
+
+	display@di0 {
+		compatible = "fsl,imx-parallel-display";
+		crtcs = <&ipu 0>;
+		interface-pix-fmt = "rgb24";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_ipu_disp1_1>;
+	};
+
+	display@di1 {
+		compatible = "fsl,imx-parallel-display";
+		crtcs = <&ipu 1>;
+		interface-pix-fmt = "rgb565";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_ipu_disp2_1>;
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		power {
+			label = "Power Button";
+			gpios = <&gpio2 21 0>;
+			linux,code = <116>; /* KEY_POWER */
+			gpio-key,wakeup;
+		};
+	};
+
+	sound {
+		compatible = "fsl,imx51-babbage-sgtl5000",
+			     "fsl,imx-audio-sgtl5000";
+		model = "imx51-babbage-sgtl5000";
+		ssi-controller = <&ssi2>;
+		audio-codec = <&sgtl5000>;
+		audio-routing =
+			"MIC_IN", "Mic Jack",
+			"Mic Jack", "Mic Bias",
+			"Headphone Jack", "HP_OUT";
+		mux-int-port = <2>;
+		mux-ext-port = <3>;
+	};
+};
+
+&esdhc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_esdhc1_1>;
+	fsl,cd-controller;
+	fsl,wp-controller;
+	status = "okay";
+};
+
+&esdhc2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_esdhc2_1>;
+	cd-gpios = <&gpio1 6 0>;
+	wp-gpios = <&gpio1 5 0>;
+	status = "okay";
+};
+
+&uart3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart3_1>;
+	fsl,uart-has-rtscts;
+	status = "okay";
+};
+
+&ecspi1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ecspi1_1>;
+	fsl,spi-num-chipselects = <2>;
+	cs-gpios = <&gpio4 24 0>, <&gpio4 25 0>;
+	status = "okay";
+
+	pmic: mc13892@0 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "fsl,mc13892";
+		spi-max-frequency = <6000000>;
+		reg = <0>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <8 0x4>;
+
+		regulators {
+			sw1_reg: sw1 {
+				regulator-min-microvolt = <600000>;
+				regulator-max-microvolt = <1375000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw2_reg: sw2 {
+				regulator-min-microvolt = <900000>;
+				regulator-max-microvolt = <1850000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw3_reg: sw3 {
+				regulator-min-microvolt = <1100000>;
+				regulator-max-microvolt = <1850000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw4_reg: sw4 {
+				regulator-min-microvolt = <1100000>;
+				regulator-max-microvolt = <1850000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			vpll_reg: vpll {
+				regulator-min-microvolt = <1050000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			vdig_reg: vdig {
+				regulator-min-microvolt = <1650000>;
+				regulator-max-microvolt = <1650000>;
+				regulator-boot-on;
+			};
+
+			vsd_reg: vsd {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3150000>;
+			};
+
+			vusb2_reg: vusb2 {
+				regulator-min-microvolt = <2400000>;
+				regulator-max-microvolt = <2775000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			vvideo_reg: vvideo {
+				regulator-min-microvolt = <2775000>;
+				regulator-max-microvolt = <2775000>;
+			};
+
+			vaudio_reg: vaudio {
+				regulator-min-microvolt = <2300000>;
+				regulator-max-microvolt = <3000000>;
+			};
+
+			vcam_reg: vcam {
+				regulator-min-microvolt = <2500000>;
+				regulator-max-microvolt = <3000000>;
+			};
+
+			vgen1_reg: vgen1 {
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <1200000>;
+			};
+
+			vgen2_reg: vgen2 {
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <3150000>;
+				regulator-always-on;
+			};
+
+			vgen3_reg: vgen3 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <2900000>;
+				regulator-always-on;
+			};
+		};
+	};
+
+	flash: at45db321d@1 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "atmel,at45db321d", "atmel,at45", "atmel,dataflash";
+		spi-max-frequency = <25000000>;
+		reg = <1>;
+
+		partition@0 {
+			label = "U-Boot";
+			reg = <0x0 0x40000>;
+			read-only;
+		};
+
+		partition@40000 {
+			label = "Kernel";
+			reg = <0x40000 0x3c0000>;
+		};
+	};
+};
+
+&ssi2 {
+	fsl,mode = "i2s-slave";
+	status = "okay";
+};
+
+&iomuxc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hog>;
+
+	hog {
+		pinctrl_hog: hoggrp {
+			fsl,pins = <
+				MX51_PAD_GPIO1_0__SD1_CD     0x20d5
+				MX51_PAD_GPIO1_1__SD1_WP     0x20d5
+				MX51_PAD_GPIO1_5__GPIO1_5    0x100
+				MX51_PAD_GPIO1_6__GPIO1_6    0x100
+				MX51_PAD_EIM_A27__GPIO2_21   0x5
+				MX51_PAD_CSPI1_SS0__GPIO4_24 0x85
+				MX51_PAD_CSPI1_SS1__GPIO4_25 0x85
+			>;
+		};
+	};
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1_1>;
+	fsl,uart-has-rtscts;
+	status = "okay";
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2_1>;
+	status = "okay";
+};
+
+&i2c2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2_1>;
+	status = "okay";
+
+	sgtl5000: codec@0a {
+		compatible = "fsl,sgtl5000";
+		reg = <0x0a>;
+		clock-frequency = <26000000>;
+		VDDA-supply = <&vdig_reg>;
+		VDDIO-supply = <&vvideo_reg>;
+	};
+};
+
+&audmux {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_audmux_1>;
+	status = "okay";
+};
+
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_fec_1>;
+	phy-mode = "mii";
+	status = "okay";
+};
+
+&kpp {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_kpp_1>;
+	linux,keymap = <0x00000067	/* KEY_UP */
+			0x0001006c	/* KEY_DOWN */
+			0x00020072	/* KEY_VOLUMEDOWN */
+			0x00030066	/* KEY_HOME */
+			0x0100006a	/* KEY_RIGHT */
+			0x01010069	/* KEY_LEFT */
+			0x0102001c	/* KEY_ENTER */
+			0x01030073	/* KEY_VOLUMEUP */
+			0x02000040	/* KEY_F6 */
+			0x02010042	/* KEY_F8 */
+			0x02020043	/* KEY_F9 */
+			0x02030044	/* KEY_F10 */
+			0x0300003b	/* KEY_F1 */
+			0x0301003c	/* KEY_F2 */
+			0x0302003d	/* KEY_F3 */
+			0x03030074>;	/* KEY_POWER */
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx51-pinfunc.h b/arch/arm/boot/dts/imx51-pinfunc.h
new file mode 100644
index 0000000..9eb92ab
--- /dev/null
+++ b/arch/arm/boot/dts/imx51-pinfunc.h
@@ -0,0 +1,773 @@
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef __DTS_IMX51_PINFUNC_H
+#define __DTS_IMX51_PINFUNC_H
+
+/*
+ * The pin function ID is a tuple of
+ * <mux_reg conf_reg input_reg mux_mode input_val>
+ */
+#define MX51_PAD_EIM_D16__AUD4_RXFS			0x05c 0x3f0 0x000 0x5 0x0
+#define MX51_PAD_EIM_D16__AUD5_TXD			0x05c 0x3f0 0x8d8 0x7 0x0
+#define MX51_PAD_EIM_D16__EIM_D16			0x05c 0x3f0 0x000 0x0 0x0
+#define MX51_PAD_EIM_D16__GPIO2_0			0x05c 0x3f0 0x000 0x1 0x0
+#define MX51_PAD_EIM_D16__I2C1_SDA			0x05c 0x3f0 0x9b4 0x4 0x0
+#define MX51_PAD_EIM_D16__UART2_CTS			0x05c 0x3f0 0x000 0x3 0x0
+#define MX51_PAD_EIM_D16__USBH2_DATA0			0x05c 0x3f0 0x000 0x2 0x0
+#define MX51_PAD_EIM_D17__AUD5_RXD			0x060 0x3f4 0x8d4 0x7 0x0
+#define MX51_PAD_EIM_D17__EIM_D17			0x060 0x3f4 0x000 0x0 0x0
+#define MX51_PAD_EIM_D17__GPIO2_1			0x060 0x3f4 0x000 0x1 0x0
+#define MX51_PAD_EIM_D17__UART2_RXD			0x060 0x3f4 0x9ec 0x3 0x0
+#define MX51_PAD_EIM_D17__UART3_CTS			0x060 0x3f4 0x000 0x4 0x0
+#define MX51_PAD_EIM_D17__USBH2_DATA1			0x060 0x3f4 0x000 0x2 0x0
+#define MX51_PAD_EIM_D18__AUD5_TXC			0x064 0x3f8 0x8e4 0x7 0x0
+#define MX51_PAD_EIM_D18__EIM_D18			0x064 0x3f8 0x000 0x0 0x0
+#define MX51_PAD_EIM_D18__GPIO2_2			0x064 0x3f8 0x000 0x1 0x0
+#define MX51_PAD_EIM_D18__UART2_TXD			0x064 0x3f8 0x000 0x3 0x0
+#define MX51_PAD_EIM_D18__UART3_RTS			0x064 0x3f8 0x9f0 0x4 0x1
+#define MX51_PAD_EIM_D18__USBH2_DATA2			0x064 0x3f8 0x000 0x2 0x0
+#define MX51_PAD_EIM_D19__AUD4_RXC			0x068 0x3fc 0x000 0x5 0x0
+#define MX51_PAD_EIM_D19__AUD5_TXFS			0x068 0x3fc 0x8e8 0x7 0x0
+#define MX51_PAD_EIM_D19__EIM_D19			0x068 0x3fc 0x000 0x0 0x0
+#define MX51_PAD_EIM_D19__GPIO2_3			0x068 0x3fc 0x000 0x1 0x0
+#define MX51_PAD_EIM_D19__I2C1_SCL			0x068 0x3fc 0x9b0 0x4 0x0
+#define MX51_PAD_EIM_D19__UART2_RTS			0x068 0x3fc 0x9e8 0x3 0x1
+#define MX51_PAD_EIM_D19__USBH2_DATA3			0x068 0x3fc 0x000 0x2 0x0
+#define MX51_PAD_EIM_D20__AUD4_TXD			0x06c 0x400 0x8c8 0x5 0x0
+#define MX51_PAD_EIM_D20__EIM_D20			0x06c 0x400 0x000 0x0 0x0
+#define MX51_PAD_EIM_D20__GPIO2_4			0x06c 0x400 0x000 0x1 0x0
+#define MX51_PAD_EIM_D20__SRTC_ALARM_DEB		0x06c 0x400 0x000 0x4 0x0
+#define MX51_PAD_EIM_D20__USBH2_DATA4			0x06c 0x400 0x000 0x2 0x0
+#define MX51_PAD_EIM_D21__AUD4_RXD			0x070 0x404 0x8c4 0x5 0x0
+#define MX51_PAD_EIM_D21__EIM_D21			0x070 0x404 0x000 0x0 0x0
+#define MX51_PAD_EIM_D21__GPIO2_5			0x070 0x404 0x000 0x1 0x0
+#define MX51_PAD_EIM_D21__SRTC_ALARM_DEB		0x070 0x404 0x000 0x3 0x0
+#define MX51_PAD_EIM_D21__USBH2_DATA5			0x070 0x404 0x000 0x2 0x0
+#define MX51_PAD_EIM_D22__AUD4_TXC			0x074 0x408 0x8cc 0x5 0x0
+#define MX51_PAD_EIM_D22__EIM_D22			0x074 0x408 0x000 0x0 0x0
+#define MX51_PAD_EIM_D22__GPIO2_6			0x074 0x408 0x000 0x1 0x0
+#define MX51_PAD_EIM_D22__USBH2_DATA6			0x074 0x408 0x000 0x2 0x0
+#define MX51_PAD_EIM_D23__AUD4_TXFS			0x078 0x40c 0x8d0 0x5 0x0
+#define MX51_PAD_EIM_D23__EIM_D23			0x078 0x40c 0x000 0x0 0x0
+#define MX51_PAD_EIM_D23__GPIO2_7			0x078 0x40c 0x000 0x1 0x0
+#define MX51_PAD_EIM_D23__SPDIF_OUT1			0x078 0x40c 0x000 0x4 0x0
+#define MX51_PAD_EIM_D23__USBH2_DATA7			0x078 0x40c 0x000 0x2 0x0
+#define MX51_PAD_EIM_D24__AUD6_RXFS			0x07c 0x410 0x8f8 0x5 0x0
+#define MX51_PAD_EIM_D24__EIM_D24			0x07c 0x410 0x000 0x0 0x0
+#define MX51_PAD_EIM_D24__GPIO2_8			0x07c 0x410 0x000 0x1 0x0
+#define MX51_PAD_EIM_D24__I2C2_SDA			0x07c 0x410 0x9bc 0x4 0x0
+#define MX51_PAD_EIM_D24__UART3_CTS			0x07c 0x410 0x000 0x3 0x0
+#define MX51_PAD_EIM_D24__USBOTG_DATA0			0x07c 0x410 0x000 0x2 0x0
+#define MX51_PAD_EIM_D25__EIM_D25			0x080 0x414 0x000 0x0 0x0
+#define MX51_PAD_EIM_D25__KEY_COL6			0x080 0x414 0x9c8 0x1 0x0
+#define MX51_PAD_EIM_D25__UART2_CTS			0x080 0x414 0x000 0x4 0x0
+#define MX51_PAD_EIM_D25__UART3_RXD			0x080 0x414 0x9f4 0x3 0x0
+#define MX51_PAD_EIM_D25__USBOTG_DATA1			0x080 0x414 0x000 0x2 0x0
+#define MX51_PAD_EIM_D26__EIM_D26			0x084 0x418 0x000 0x0 0x0
+#define MX51_PAD_EIM_D26__KEY_COL7			0x084 0x418 0x9cc 0x1 0x0
+#define MX51_PAD_EIM_D26__UART2_RTS			0x084 0x418 0x9e8 0x4 0x3
+#define MX51_PAD_EIM_D26__UART3_TXD			0x084 0x418 0x000 0x3 0x0
+#define MX51_PAD_EIM_D26__USBOTG_DATA2			0x084 0x418 0x000 0x2 0x0
+#define MX51_PAD_EIM_D27__AUD6_RXC			0x088 0x41c 0x8f4 0x5 0x0
+#define MX51_PAD_EIM_D27__EIM_D27			0x088 0x41c 0x000 0x0 0x0
+#define MX51_PAD_EIM_D27__GPIO2_9			0x088 0x41c 0x000 0x1 0x0
+#define MX51_PAD_EIM_D27__I2C2_SCL			0x088 0x41c 0x9b8 0x4 0x0
+#define MX51_PAD_EIM_D27__UART3_RTS			0x088 0x41c 0x9f0 0x3 0x3
+#define MX51_PAD_EIM_D27__USBOTG_DATA3			0x088 0x41c 0x000 0x2 0x0
+#define MX51_PAD_EIM_D28__AUD6_TXD			0x08c 0x420 0x8f0 0x5 0x0
+#define MX51_PAD_EIM_D28__EIM_D28			0x08c 0x420 0x000 0x0 0x0
+#define MX51_PAD_EIM_D28__KEY_ROW4			0x08c 0x420 0x9d0 0x1 0x0
+#define MX51_PAD_EIM_D28__USBOTG_DATA4			0x08c 0x420 0x000 0x2 0x0
+#define MX51_PAD_EIM_D29__AUD6_RXD			0x090 0x424 0x8ec 0x5 0x0
+#define MX51_PAD_EIM_D29__EIM_D29			0x090 0x424 0x000 0x0 0x0
+#define MX51_PAD_EIM_D29__KEY_ROW5			0x090 0x424 0x9d4 0x1 0x0
+#define MX51_PAD_EIM_D29__USBOTG_DATA5			0x090 0x424 0x000 0x2 0x0
+#define MX51_PAD_EIM_D30__AUD6_TXC			0x094 0x428 0x8fc 0x5 0x0
+#define MX51_PAD_EIM_D30__EIM_D30			0x094 0x428 0x000 0x0 0x0
+#define MX51_PAD_EIM_D30__KEY_ROW6			0x094 0x428 0x9d8 0x1 0x0
+#define MX51_PAD_EIM_D30__USBOTG_DATA6			0x094 0x428 0x000 0x2 0x0
+#define MX51_PAD_EIM_D31__AUD6_TXFS			0x098 0x42c 0x900 0x5 0x0
+#define MX51_PAD_EIM_D31__EIM_D31			0x098 0x42c 0x000 0x0 0x0
+#define MX51_PAD_EIM_D31__KEY_ROW7			0x098 0x42c 0x9dc 0x1 0x0
+#define MX51_PAD_EIM_D31__USBOTG_DATA7			0x098 0x42c 0x000 0x2 0x0
+#define MX51_PAD_EIM_A16__EIM_A16			0x09c 0x430 0x000 0x0 0x0
+#define MX51_PAD_EIM_A16__GPIO2_10			0x09c 0x430 0x000 0x1 0x0
+#define MX51_PAD_EIM_A16__OSC_FREQ_SEL0			0x09c 0x430 0x000 0x7 0x0
+#define MX51_PAD_EIM_A17__EIM_A17			0x0a0 0x434 0x000 0x0 0x0
+#define MX51_PAD_EIM_A17__GPIO2_11			0x0a0 0x434 0x000 0x1 0x0
+#define MX51_PAD_EIM_A17__OSC_FREQ_SEL1			0x0a0 0x434 0x000 0x7 0x0
+#define MX51_PAD_EIM_A18__BOOT_LPB0			0x0a4 0x438 0x000 0x7 0x0
+#define MX51_PAD_EIM_A18__EIM_A18			0x0a4 0x438 0x000 0x0 0x0
+#define MX51_PAD_EIM_A18__GPIO2_12			0x0a4 0x438 0x000 0x1 0x0
+#define MX51_PAD_EIM_A19__BOOT_LPB1			0x0a8 0x43c 0x000 0x7 0x0
+#define MX51_PAD_EIM_A19__EIM_A19			0x0a8 0x43c 0x000 0x0 0x0
+#define MX51_PAD_EIM_A19__GPIO2_13			0x0a8 0x43c 0x000 0x1 0x0
+#define MX51_PAD_EIM_A20__BOOT_UART_SRC0		0x0ac 0x440 0x000 0x7 0x0
+#define MX51_PAD_EIM_A20__EIM_A20			0x0ac 0x440 0x000 0x0 0x0
+#define MX51_PAD_EIM_A20__GPIO2_14			0x0ac 0x440 0x000 0x1 0x0
+#define MX51_PAD_EIM_A21__BOOT_UART_SRC1		0x0b0 0x444 0x000 0x7 0x0
+#define MX51_PAD_EIM_A21__EIM_A21			0x0b0 0x444 0x000 0x0 0x0
+#define MX51_PAD_EIM_A21__GPIO2_15			0x0b0 0x444 0x000 0x1 0x0
+#define MX51_PAD_EIM_A22__EIM_A22			0x0b4 0x448 0x000 0x0 0x0
+#define MX51_PAD_EIM_A22__GPIO2_16			0x0b4 0x448 0x000 0x1 0x0
+#define MX51_PAD_EIM_A23__BOOT_HPN_EN			0x0b8 0x44c 0x000 0x7 0x0
+#define MX51_PAD_EIM_A23__EIM_A23			0x0b8 0x44c 0x000 0x0 0x0
+#define MX51_PAD_EIM_A23__GPIO2_17			0x0b8 0x44c 0x000 0x1 0x0
+#define MX51_PAD_EIM_A24__EIM_A24			0x0bc 0x450 0x000 0x0 0x0
+#define MX51_PAD_EIM_A24__GPIO2_18			0x0bc 0x450 0x000 0x1 0x0
+#define MX51_PAD_EIM_A24__USBH2_CLK			0x0bc 0x450 0x000 0x2 0x0
+#define MX51_PAD_EIM_A25__DISP1_PIN4			0x0c0 0x454 0x000 0x6 0x0
+#define MX51_PAD_EIM_A25__EIM_A25			0x0c0 0x454 0x000 0x0 0x0
+#define MX51_PAD_EIM_A25__GPIO2_19			0x0c0 0x454 0x000 0x1 0x0
+#define MX51_PAD_EIM_A25__USBH2_DIR			0x0c0 0x454 0x000 0x2 0x0
+#define MX51_PAD_EIM_A26__CSI1_DATA_EN			0x0c4 0x458 0x9a0 0x5 0x0
+#define MX51_PAD_EIM_A26__DISP2_EXT_CLK			0x0c4 0x458 0x908 0x6 0x0
+#define MX51_PAD_EIM_A26__EIM_A26			0x0c4 0x458 0x000 0x0 0x0
+#define MX51_PAD_EIM_A26__GPIO2_20			0x0c4 0x458 0x000 0x1 0x0
+#define MX51_PAD_EIM_A26__USBH2_STP			0x0c4 0x458 0x000 0x2 0x0
+#define MX51_PAD_EIM_A27__CSI2_DATA_EN			0x0c8 0x45c 0x99c 0x5 0x0
+#define MX51_PAD_EIM_A27__DISP1_PIN1			0x0c8 0x45c 0x9a4 0x6 0x0
+#define MX51_PAD_EIM_A27__EIM_A27			0x0c8 0x45c 0x000 0x0 0x0
+#define MX51_PAD_EIM_A27__GPIO2_21			0x0c8 0x45c 0x000 0x1 0x0
+#define MX51_PAD_EIM_A27__USBH2_NXT			0x0c8 0x45c 0x000 0x2 0x0
+#define MX51_PAD_EIM_EB0__EIM_EB0			0x0cc 0x460 0x000 0x0 0x0
+#define MX51_PAD_EIM_EB1__EIM_EB1			0x0d0 0x464 0x000 0x0 0x0
+#define MX51_PAD_EIM_EB2__AUD5_RXFS			0x0d4 0x468 0x8e0 0x6 0x0
+#define MX51_PAD_EIM_EB2__CSI1_D2			0x0d4 0x468 0x000 0x5 0x0
+#define MX51_PAD_EIM_EB2__EIM_EB2			0x0d4 0x468 0x000 0x0 0x0
+#define MX51_PAD_EIM_EB2__FEC_MDIO			0x0d4 0x468 0x954 0x3 0x0
+#define MX51_PAD_EIM_EB2__GPIO2_22			0x0d4 0x468 0x000 0x1 0x0
+#define MX51_PAD_EIM_EB2__GPT_CMPOUT1			0x0d4 0x468 0x000 0x7 0x0
+#define MX51_PAD_EIM_EB3__AUD5_RXC			0x0d8 0x46c 0x8dc 0x6 0x0
+#define MX51_PAD_EIM_EB3__CSI1_D3			0x0d8 0x46c 0x000 0x5 0x0
+#define MX51_PAD_EIM_EB3__EIM_EB3			0x0d8 0x46c 0x000 0x0 0x0
+#define MX51_PAD_EIM_EB3__FEC_RDATA1			0x0d8 0x46c 0x95c 0x3 0x0
+#define MX51_PAD_EIM_EB3__GPIO2_23			0x0d8 0x46c 0x000 0x1 0x0
+#define MX51_PAD_EIM_EB3__GPT_CMPOUT2			0x0d8 0x46c 0x000 0x7 0x0
+#define MX51_PAD_EIM_OE__EIM_OE				0x0dc 0x470 0x000 0x0 0x0
+#define MX51_PAD_EIM_OE__GPIO2_24			0x0dc 0x470 0x000 0x1 0x0
+#define MX51_PAD_EIM_CS0__EIM_CS0			0x0e0 0x474 0x000 0x0 0x0
+#define MX51_PAD_EIM_CS0__GPIO2_25			0x0e0 0x474 0x000 0x1 0x0
+#define MX51_PAD_EIM_CS1__EIM_CS1			0x0e4 0x478 0x000 0x0 0x0
+#define MX51_PAD_EIM_CS1__GPIO2_26			0x0e4 0x478 0x000 0x1 0x0
+#define MX51_PAD_EIM_CS2__AUD5_TXD			0x0e8 0x47c 0x8d8 0x6 0x1
+#define MX51_PAD_EIM_CS2__CSI1_D4			0x0e8 0x47c 0x000 0x5 0x0
+#define MX51_PAD_EIM_CS2__EIM_CS2			0x0e8 0x47c 0x000 0x0 0x0
+#define MX51_PAD_EIM_CS2__FEC_RDATA2			0x0e8 0x47c 0x960 0x3 0x0
+#define MX51_PAD_EIM_CS2__GPIO2_27			0x0e8 0x47c 0x000 0x1 0x0
+#define MX51_PAD_EIM_CS2__USBOTG_STP			0x0e8 0x47c 0x000 0x2 0x0
+#define MX51_PAD_EIM_CS3__AUD5_RXD			0x0ec 0x480 0x8d4 0x6 0x1
+#define MX51_PAD_EIM_CS3__CSI1_D5			0x0ec 0x480 0x000 0x5 0x0
+#define MX51_PAD_EIM_CS3__EIM_CS3			0x0ec 0x480 0x000 0x0 0x0
+#define MX51_PAD_EIM_CS3__FEC_RDATA3			0x0ec 0x480 0x964 0x3 0x0
+#define MX51_PAD_EIM_CS3__GPIO2_28			0x0ec 0x480 0x000 0x1 0x0
+#define MX51_PAD_EIM_CS3__USBOTG_NXT			0x0ec 0x480 0x000 0x2 0x0
+#define MX51_PAD_EIM_CS4__AUD5_TXC			0x0f0 0x484 0x8e4 0x6 0x1
+#define MX51_PAD_EIM_CS4__CSI1_D6			0x0f0 0x484 0x000 0x5 0x0
+#define MX51_PAD_EIM_CS4__EIM_CS4			0x0f0 0x484 0x000 0x0 0x0
+#define MX51_PAD_EIM_CS4__FEC_RX_ER			0x0f0 0x484 0x970 0x3 0x0
+#define MX51_PAD_EIM_CS4__GPIO2_29			0x0f0 0x484 0x000 0x1 0x0
+#define MX51_PAD_EIM_CS4__USBOTG_CLK			0x0f0 0x484 0x000 0x2 0x0
+#define MX51_PAD_EIM_CS5__AUD5_TXFS			0x0f4 0x488 0x8e8 0x6 0x1
+#define MX51_PAD_EIM_CS5__CSI1_D7			0x0f4 0x488 0x000 0x5 0x0
+#define MX51_PAD_EIM_CS5__DISP1_EXT_CLK			0x0f4 0x488 0x904 0x4 0x0
+#define MX51_PAD_EIM_CS5__EIM_CS5			0x0f4 0x488 0x000 0x0 0x0
+#define MX51_PAD_EIM_CS5__FEC_CRS			0x0f4 0x488 0x950 0x3 0x0
+#define MX51_PAD_EIM_CS5__GPIO2_30			0x0f4 0x488 0x000 0x1 0x0
+#define MX51_PAD_EIM_CS5__USBOTG_DIR			0x0f4 0x488 0x000 0x2 0x0
+#define MX51_PAD_EIM_DTACK__EIM_DTACK			0x0f8 0x48c 0x000 0x0 0x0
+#define MX51_PAD_EIM_DTACK__GPIO2_31			0x0f8 0x48c 0x000 0x1 0x0
+#define MX51_PAD_EIM_LBA__EIM_LBA			0x0fc 0x494 0x000 0x0 0x0
+#define MX51_PAD_EIM_LBA__GPIO3_1			0x0fc 0x494 0x978 0x1 0x0
+#define MX51_PAD_EIM_CRE__EIM_CRE			0x100 0x4a0 0x000 0x0 0x0
+#define MX51_PAD_EIM_CRE__GPIO3_2			0x100 0x4a0 0x97c 0x1 0x0
+#define MX51_PAD_DRAM_CS1__DRAM_CS1			0x104 0x4d0 0x000 0x0 0x0
+#define MX51_PAD_NANDF_WE_B__GPIO3_3			0x108 0x4e4 0x980 0x3 0x0
+#define MX51_PAD_NANDF_WE_B__NANDF_WE_B			0x108 0x4e4 0x000 0x0 0x0
+#define MX51_PAD_NANDF_WE_B__PATA_DIOW			0x108 0x4e4 0x000 0x1 0x0
+#define MX51_PAD_NANDF_WE_B__SD3_DATA0			0x108 0x4e4 0x93c 0x2 0x0
+#define MX51_PAD_NANDF_RE_B__GPIO3_4			0x10c 0x4e8 0x984 0x3 0x0
+#define MX51_PAD_NANDF_RE_B__NANDF_RE_B			0x10c 0x4e8 0x000 0x0 0x0
+#define MX51_PAD_NANDF_RE_B__PATA_DIOR			0x10c 0x4e8 0x000 0x1 0x0
+#define MX51_PAD_NANDF_RE_B__SD3_DATA1			0x10c 0x4e8 0x940 0x2 0x0
+#define MX51_PAD_NANDF_ALE__GPIO3_5			0x110 0x4ec 0x988 0x3 0x0
+#define MX51_PAD_NANDF_ALE__NANDF_ALE			0x110 0x4ec 0x000 0x0 0x0
+#define MX51_PAD_NANDF_ALE__PATA_BUFFER_EN		0x110 0x4ec 0x000 0x1 0x0
+#define MX51_PAD_NANDF_CLE__GPIO3_6			0x114 0x4f0 0x98c 0x3 0x0
+#define MX51_PAD_NANDF_CLE__NANDF_CLE			0x114 0x4f0 0x000 0x0 0x0
+#define MX51_PAD_NANDF_CLE__PATA_RESET_B		0x114 0x4f0 0x000 0x1 0x0
+#define MX51_PAD_NANDF_WP_B__GPIO3_7			0x118 0x4f4 0x990 0x3 0x0
+#define MX51_PAD_NANDF_WP_B__NANDF_WP_B			0x118 0x4f4 0x000 0x0 0x0
+#define MX51_PAD_NANDF_WP_B__PATA_DMACK			0x118 0x4f4 0x000 0x1 0x0
+#define MX51_PAD_NANDF_WP_B__SD3_DATA2			0x118 0x4f4 0x944 0x2 0x0
+#define MX51_PAD_NANDF_RB0__ECSPI2_SS1			0x11c 0x4f8 0x930 0x5 0x0
+#define MX51_PAD_NANDF_RB0__GPIO3_8			0x11c 0x4f8 0x994 0x3 0x0
+#define MX51_PAD_NANDF_RB0__NANDF_RB0			0x11c 0x4f8 0x000 0x0 0x0
+#define MX51_PAD_NANDF_RB0__PATA_DMARQ			0x11c 0x4f8 0x000 0x1 0x0
+#define MX51_PAD_NANDF_RB0__SD3_DATA3			0x11c 0x4f8 0x948 0x2 0x0
+#define MX51_PAD_NANDF_RB1__CSPI_MOSI			0x120 0x4fc 0x91c 0x6 0x0
+#define MX51_PAD_NANDF_RB1__ECSPI2_RDY			0x120 0x4fc 0x000 0x2 0x0
+#define MX51_PAD_NANDF_RB1__GPIO3_9			0x120 0x4fc 0x000 0x3 0x0
+#define MX51_PAD_NANDF_RB1__NANDF_RB1			0x120 0x4fc 0x000 0x0 0x0
+#define MX51_PAD_NANDF_RB1__PATA_IORDY			0x120 0x4fc 0x000 0x1 0x0
+#define MX51_PAD_NANDF_RB1__SD4_CMD			0x120 0x4fc 0x000 0x5 0x0
+#define MX51_PAD_NANDF_RB2__DISP2_WAIT			0x124 0x500 0x9a8 0x5 0x0
+#define MX51_PAD_NANDF_RB2__ECSPI2_SCLK			0x124 0x500 0x000 0x2 0x0
+#define MX51_PAD_NANDF_RB2__FEC_COL			0x124 0x500 0x94c 0x1 0x0
+#define MX51_PAD_NANDF_RB2__GPIO3_10			0x124 0x500 0x000 0x3 0x0
+#define MX51_PAD_NANDF_RB2__NANDF_RB2			0x124 0x500 0x000 0x0 0x0
+#define MX51_PAD_NANDF_RB2__USBH3_H3_DP			0x124 0x500 0x000 0x7 0x0
+#define MX51_PAD_NANDF_RB2__USBH3_NXT			0x124 0x500 0xa20 0x6 0x0
+#define MX51_PAD_NANDF_RB3__DISP1_WAIT			0x128 0x504 0x000 0x5 0x0
+#define MX51_PAD_NANDF_RB3__ECSPI2_MISO			0x128 0x504 0x000 0x2 0x0
+#define MX51_PAD_NANDF_RB3__FEC_RX_CLK			0x128 0x504 0x968 0x1 0x0
+#define MX51_PAD_NANDF_RB3__GPIO3_11			0x128 0x504 0x000 0x3 0x0
+#define MX51_PAD_NANDF_RB3__NANDF_RB3			0x128 0x504 0x000 0x0 0x0
+#define MX51_PAD_NANDF_RB3__USBH3_CLK			0x128 0x504 0x9f8 0x6 0x0
+#define MX51_PAD_NANDF_RB3__USBH3_H3_DM			0x128 0x504 0x000 0x7 0x0
+#define MX51_PAD_GPIO_NAND__GPIO_NAND			0x12c 0x514 0x998 0x0 0x0
+#define MX51_PAD_GPIO_NAND__PATA_INTRQ			0x12c 0x514 0x000 0x1 0x0
+#define MX51_PAD_NANDF_CS0__GPIO3_16			0x130 0x518 0x000 0x3 0x0
+#define MX51_PAD_NANDF_CS0__NANDF_CS0			0x130 0x518 0x000 0x0 0x0
+#define MX51_PAD_NANDF_CS1__GPIO3_17			0x134 0x51c 0x000 0x3 0x0
+#define MX51_PAD_NANDF_CS1__NANDF_CS1			0x134 0x51c 0x000 0x0 0x0
+#define MX51_PAD_NANDF_CS2__CSPI_SCLK			0x138 0x520 0x914 0x6 0x0
+#define MX51_PAD_NANDF_CS2__FEC_TX_ER			0x138 0x520 0x000 0x2 0x0
+#define MX51_PAD_NANDF_CS2__GPIO3_18			0x138 0x520 0x000 0x3 0x0
+#define MX51_PAD_NANDF_CS2__NANDF_CS2			0x138 0x520 0x000 0x0 0x0
+#define MX51_PAD_NANDF_CS2__PATA_CS_0			0x138 0x520 0x000 0x1 0x0
+#define MX51_PAD_NANDF_CS2__SD4_CLK			0x138 0x520 0x000 0x5 0x0
+#define MX51_PAD_NANDF_CS2__USBH3_H1_DP			0x138 0x520 0x000 0x7 0x0
+#define MX51_PAD_NANDF_CS3__FEC_MDC			0x13c 0x524 0x000 0x2 0x0
+#define MX51_PAD_NANDF_CS3__GPIO3_19			0x13c 0x524 0x000 0x3 0x0
+#define MX51_PAD_NANDF_CS3__NANDF_CS3			0x13c 0x524 0x000 0x0 0x0
+#define MX51_PAD_NANDF_CS3__PATA_CS_1			0x13c 0x524 0x000 0x1 0x0
+#define MX51_PAD_NANDF_CS3__SD4_DAT0			0x13c 0x524 0x000 0x5 0x0
+#define MX51_PAD_NANDF_CS3__USBH3_H1_DM			0x13c 0x524 0x000 0x7 0x0
+#define MX51_PAD_NANDF_CS4__FEC_TDATA1			0x140 0x528 0x000 0x2 0x0
+#define MX51_PAD_NANDF_CS4__GPIO3_20			0x140 0x528 0x000 0x3 0x0
+#define MX51_PAD_NANDF_CS4__NANDF_CS4			0x140 0x528 0x000 0x0 0x0
+#define MX51_PAD_NANDF_CS4__PATA_DA_0			0x140 0x528 0x000 0x1 0x0
+#define MX51_PAD_NANDF_CS4__SD4_DAT1			0x140 0x528 0x000 0x5 0x0
+#define MX51_PAD_NANDF_CS4__USBH3_STP			0x140 0x528 0xa24 0x7 0x0
+#define MX51_PAD_NANDF_CS5__FEC_TDATA2			0x144 0x52c 0x000 0x2 0x0
+#define MX51_PAD_NANDF_CS5__GPIO3_21			0x144 0x52c 0x000 0x3 0x0
+#define MX51_PAD_NANDF_CS5__NANDF_CS5			0x144 0x52c 0x000 0x0 0x0
+#define MX51_PAD_NANDF_CS5__PATA_DA_1			0x144 0x52c 0x000 0x1 0x0
+#define MX51_PAD_NANDF_CS5__SD4_DAT2			0x144 0x52c 0x000 0x5 0x0
+#define MX51_PAD_NANDF_CS5__USBH3_DIR			0x144 0x52c 0xa1c 0x7 0x0
+#define MX51_PAD_NANDF_CS6__CSPI_SS3			0x148 0x530 0x928 0x7 0x0
+#define MX51_PAD_NANDF_CS6__FEC_TDATA3			0x148 0x530 0x000 0x2 0x0
+#define MX51_PAD_NANDF_CS6__GPIO3_22			0x148 0x530 0x000 0x3 0x0
+#define MX51_PAD_NANDF_CS6__NANDF_CS6			0x148 0x530 0x000 0x0 0x0
+#define MX51_PAD_NANDF_CS6__PATA_DA_2			0x148 0x530 0x000 0x1 0x0
+#define MX51_PAD_NANDF_CS6__SD4_DAT3			0x148 0x530 0x000 0x5 0x0
+#define MX51_PAD_NANDF_CS7__FEC_TX_EN			0x14c 0x534 0x000 0x1 0x0
+#define MX51_PAD_NANDF_CS7__GPIO3_23			0x14c 0x534 0x000 0x3 0x0
+#define MX51_PAD_NANDF_CS7__NANDF_CS7			0x14c 0x534 0x000 0x0 0x0
+#define MX51_PAD_NANDF_CS7__SD3_CLK			0x14c 0x534 0x000 0x5 0x0
+#define MX51_PAD_NANDF_RDY_INT__ECSPI2_SS0		0x150 0x538 0x000 0x2 0x0
+#define MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK		0x150 0x538 0x974 0x1 0x0
+#define MX51_PAD_NANDF_RDY_INT__GPIO3_24		0x150 0x538 0x000 0x3 0x0
+#define MX51_PAD_NANDF_RDY_INT__NANDF_RDY_INT		0x150 0x538 0x938 0x0 0x0
+#define MX51_PAD_NANDF_RDY_INT__SD3_CMD			0x150 0x538 0x000 0x5 0x0
+#define MX51_PAD_NANDF_D15__ECSPI2_MOSI			0x154 0x53c 0x000 0x2 0x0
+#define MX51_PAD_NANDF_D15__GPIO3_25			0x154 0x53c 0x000 0x3 0x0
+#define MX51_PAD_NANDF_D15__NANDF_D15			0x154 0x53c 0x000 0x0 0x0
+#define MX51_PAD_NANDF_D15__PATA_DATA15			0x154 0x53c 0x000 0x1 0x0
+#define MX51_PAD_NANDF_D15__SD3_DAT7			0x154 0x53c 0x000 0x5 0x0
+#define MX51_PAD_NANDF_D14__ECSPI2_SS3			0x158 0x540 0x934 0x2 0x0
+#define MX51_PAD_NANDF_D14__GPIO3_26			0x158 0x540 0x000 0x3 0x0
+#define MX51_PAD_NANDF_D14__NANDF_D14			0x158 0x540 0x000 0x0 0x0
+#define MX51_PAD_NANDF_D14__PATA_DATA14			0x158 0x540 0x000 0x1 0x0
+#define MX51_PAD_NANDF_D14__SD3_DAT6			0x158 0x540 0x000 0x5 0x0
+#define MX51_PAD_NANDF_D13__ECSPI2_SS2			0x15c 0x544 0x000 0x2 0x0
+#define MX51_PAD_NANDF_D13__GPIO3_27			0x15c 0x544 0x000 0x3 0x0
+#define MX51_PAD_NANDF_D13__NANDF_D13			0x15c 0x544 0x000 0x0 0x0
+#define MX51_PAD_NANDF_D13__PATA_DATA13			0x15c 0x544 0x000 0x1 0x0
+#define MX51_PAD_NANDF_D13__SD3_DAT5			0x15c 0x544 0x000 0x5 0x0
+#define MX51_PAD_NANDF_D12__ECSPI2_SS1			0x160 0x548 0x930 0x2 0x1
+#define MX51_PAD_NANDF_D12__GPIO3_28			0x160 0x548 0x000 0x3 0x0
+#define MX51_PAD_NANDF_D12__NANDF_D12			0x160 0x548 0x000 0x0 0x0
+#define MX51_PAD_NANDF_D12__PATA_DATA12			0x160 0x548 0x000 0x1 0x0
+#define MX51_PAD_NANDF_D12__SD3_DAT4			0x160 0x548 0x000 0x5 0x0
+#define MX51_PAD_NANDF_D11__FEC_RX_DV			0x164 0x54c 0x96c 0x2 0x0
+#define MX51_PAD_NANDF_D11__GPIO3_29			0x164 0x54c 0x000 0x3 0x0
+#define MX51_PAD_NANDF_D11__NANDF_D11			0x164 0x54c 0x000 0x0 0x0
+#define MX51_PAD_NANDF_D11__PATA_DATA11			0x164 0x54c 0x000 0x1 0x0
+#define MX51_PAD_NANDF_D11__SD3_DATA3			0x164 0x54c 0x948 0x5 0x1
+#define MX51_PAD_NANDF_D10__GPIO3_30			0x168 0x550 0x000 0x3 0x0
+#define MX51_PAD_NANDF_D10__NANDF_D10			0x168 0x550 0x000 0x0 0x0
+#define MX51_PAD_NANDF_D10__PATA_DATA10			0x168 0x550 0x000 0x1 0x0
+#define MX51_PAD_NANDF_D10__SD3_DATA2			0x168 0x550 0x944 0x5 0x1
+#define MX51_PAD_NANDF_D9__FEC_RDATA0			0x16c 0x554 0x958 0x2 0x0
+#define MX51_PAD_NANDF_D9__GPIO3_31			0x16c 0x554 0x000 0x3 0x0
+#define MX51_PAD_NANDF_D9__NANDF_D9			0x16c 0x554 0x000 0x0 0x0
+#define MX51_PAD_NANDF_D9__PATA_DATA9			0x16c 0x554 0x000 0x1 0x0
+#define MX51_PAD_NANDF_D9__SD3_DATA1			0x16c 0x554 0x940 0x5 0x1
+#define MX51_PAD_NANDF_D8__FEC_TDATA0			0x170 0x558 0x000 0x2 0x0
+#define MX51_PAD_NANDF_D8__GPIO4_0			0x170 0x558 0x000 0x3 0x0
+#define MX51_PAD_NANDF_D8__NANDF_D8			0x170 0x558 0x000 0x0 0x0
+#define MX51_PAD_NANDF_D8__PATA_DATA8			0x170 0x558 0x000 0x1 0x0
+#define MX51_PAD_NANDF_D8__SD3_DATA0			0x170 0x558 0x93c 0x5 0x1
+#define MX51_PAD_NANDF_D7__GPIO4_1			0x174 0x55c 0x000 0x3 0x0
+#define MX51_PAD_NANDF_D7__NANDF_D7			0x174 0x55c 0x000 0x0 0x0
+#define MX51_PAD_NANDF_D7__PATA_DATA7			0x174 0x55c 0x000 0x1 0x0
+#define MX51_PAD_NANDF_D7__USBH3_DATA0			0x174 0x55c 0x9fc 0x5 0x0
+#define MX51_PAD_NANDF_D6__GPIO4_2			0x178 0x560 0x000 0x3 0x0
+#define MX51_PAD_NANDF_D6__NANDF_D6			0x178 0x560 0x000 0x0 0x0
+#define MX51_PAD_NANDF_D6__PATA_DATA6			0x178 0x560 0x000 0x1 0x0
+#define MX51_PAD_NANDF_D6__SD4_LCTL			0x178 0x560 0x000 0x2 0x0
+#define MX51_PAD_NANDF_D6__USBH3_DATA1			0x178 0x560 0xa00 0x5 0x0
+#define MX51_PAD_NANDF_D5__GPIO4_3			0x17c 0x564 0x000 0x3 0x0
+#define MX51_PAD_NANDF_D5__NANDF_D5			0x17c 0x564 0x000 0x0 0x0
+#define MX51_PAD_NANDF_D5__PATA_DATA5			0x17c 0x564 0x000 0x1 0x0
+#define MX51_PAD_NANDF_D5__SD4_WP			0x17c 0x564 0x000 0x2 0x0
+#define MX51_PAD_NANDF_D5__USBH3_DATA2			0x17c 0x564 0xa04 0x5 0x0
+#define MX51_PAD_NANDF_D4__GPIO4_4			0x180 0x568 0x000 0x3 0x0
+#define MX51_PAD_NANDF_D4__NANDF_D4			0x180 0x568 0x000 0x0 0x0
+#define MX51_PAD_NANDF_D4__PATA_DATA4			0x180 0x568 0x000 0x1 0x0
+#define MX51_PAD_NANDF_D4__SD4_CD			0x180 0x568 0x000 0x2 0x0
+#define MX51_PAD_NANDF_D4__USBH3_DATA3			0x180 0x568 0xa08 0x5 0x0
+#define MX51_PAD_NANDF_D3__GPIO4_5			0x184 0x56c 0x000 0x3 0x0
+#define MX51_PAD_NANDF_D3__NANDF_D3			0x184 0x56c 0x000 0x0 0x0
+#define MX51_PAD_NANDF_D3__PATA_DATA3			0x184 0x56c 0x000 0x1 0x0
+#define MX51_PAD_NANDF_D3__SD4_DAT4			0x184 0x56c 0x000 0x2 0x0
+#define MX51_PAD_NANDF_D3__USBH3_DATA4			0x184 0x56c 0xa0c 0x5 0x0
+#define MX51_PAD_NANDF_D2__GPIO4_6			0x188 0x570 0x000 0x3 0x0
+#define MX51_PAD_NANDF_D2__NANDF_D2			0x188 0x570 0x000 0x0 0x0
+#define MX51_PAD_NANDF_D2__PATA_DATA2			0x188 0x570 0x000 0x1 0x0
+#define MX51_PAD_NANDF_D2__SD4_DAT5			0x188 0x570 0x000 0x2 0x0
+#define MX51_PAD_NANDF_D2__USBH3_DATA5			0x188 0x570 0xa10 0x5 0x0
+#define MX51_PAD_NANDF_D1__GPIO4_7			0x18c 0x574 0x000 0x3 0x0
+#define MX51_PAD_NANDF_D1__NANDF_D1			0x18c 0x574 0x000 0x0 0x0
+#define MX51_PAD_NANDF_D1__PATA_DATA1			0x18c 0x574 0x000 0x1 0x0
+#define MX51_PAD_NANDF_D1__SD4_DAT6			0x18c 0x574 0x000 0x2 0x0
+#define MX51_PAD_NANDF_D1__USBH3_DATA6			0x18c 0x574 0xa14 0x5 0x0
+#define MX51_PAD_NANDF_D0__GPIO4_8			0x190 0x578 0x000 0x3 0x0
+#define MX51_PAD_NANDF_D0__NANDF_D0			0x190 0x578 0x000 0x0 0x0
+#define MX51_PAD_NANDF_D0__PATA_DATA0			0x190 0x578 0x000 0x1 0x0
+#define MX51_PAD_NANDF_D0__SD4_DAT7			0x190 0x578 0x000 0x2 0x0
+#define MX51_PAD_NANDF_D0__USBH3_DATA7			0x190 0x578 0xa18 0x5 0x0
+#define MX51_PAD_CSI1_D8__CSI1_D8			0x194 0x57c 0x000 0x0 0x0
+#define MX51_PAD_CSI1_D8__GPIO3_12			0x194 0x57c 0x998 0x3 0x1
+#define MX51_PAD_CSI1_D9__CSI1_D9			0x198 0x580 0x000 0x0 0x0
+#define MX51_PAD_CSI1_D9__GPIO3_13			0x198 0x580 0x000 0x3 0x0
+#define MX51_PAD_CSI1_D10__CSI1_D10			0x19c 0x584 0x000 0x0 0x0
+#define MX51_PAD_CSI1_D11__CSI1_D11			0x1a0 0x588 0x000 0x0 0x0
+#define MX51_PAD_CSI1_D12__CSI1_D12			0x1a4 0x58c 0x000 0x0 0x0
+#define MX51_PAD_CSI1_D13__CSI1_D13			0x1a8 0x590 0x000 0x0 0x0
+#define MX51_PAD_CSI1_D14__CSI1_D14			0x1ac 0x594 0x000 0x0 0x0
+#define MX51_PAD_CSI1_D15__CSI1_D15			0x1b0 0x598 0x000 0x0 0x0
+#define MX51_PAD_CSI1_D16__CSI1_D16			0x1b4 0x59c 0x000 0x0 0x0
+#define MX51_PAD_CSI1_D17__CSI1_D17			0x1b8 0x5a0 0x000 0x0 0x0
+#define MX51_PAD_CSI1_D18__CSI1_D18			0x1bc 0x5a4 0x000 0x0 0x0
+#define MX51_PAD_CSI1_D19__CSI1_D19			0x1c0 0x5a8 0x000 0x0 0x0
+#define MX51_PAD_CSI1_VSYNC__CSI1_VSYNC			0x1c4 0x5ac 0x000 0x0 0x0
+#define MX51_PAD_CSI1_VSYNC__GPIO3_14			0x1c4 0x5ac 0x000 0x3 0x0
+#define MX51_PAD_CSI1_HSYNC__CSI1_HSYNC			0x1c8 0x5b0 0x000 0x0 0x0
+#define MX51_PAD_CSI1_HSYNC__GPIO3_15			0x1c8 0x5b0 0x000 0x3 0x0
+#define MX51_PAD_CSI1_PIXCLK__CSI1_PIXCLK		0x000 0x5b4 0x000 0x0 0x0
+#define MX51_PAD_CSI1_MCLK__CSI1_MCLK			0x000 0x5b8 0x000 0x0 0x0
+#define MX51_PAD_CSI2_D12__CSI2_D12			0x1cc 0x5bc 0x000 0x0 0x0
+#define MX51_PAD_CSI2_D12__GPIO4_9			0x1cc 0x5bc 0x000 0x3 0x0
+#define MX51_PAD_CSI2_D13__CSI2_D13			0x1d0 0x5c0 0x000 0x0 0x0
+#define MX51_PAD_CSI2_D13__GPIO4_10			0x1d0 0x5c0 0x000 0x3 0x0
+#define MX51_PAD_CSI2_D14__CSI2_D14			0x1d4 0x5c4 0x000 0x0 0x0
+#define MX51_PAD_CSI2_D15__CSI2_D15			0x1d8 0x5c8 0x000 0x0 0x0
+#define MX51_PAD_CSI2_D16__CSI2_D16			0x1dc 0x5cc 0x000 0x0 0x0
+#define MX51_PAD_CSI2_D17__CSI2_D17			0x1e0 0x5d0 0x000 0x0 0x0
+#define MX51_PAD_CSI2_D18__CSI2_D18			0x1e4 0x5d4 0x000 0x0 0x0
+#define MX51_PAD_CSI2_D18__GPIO4_11			0x1e4 0x5d4 0x000 0x3 0x0
+#define MX51_PAD_CSI2_D19__CSI2_D19			0x1e8 0x5d8 0x000 0x0 0x0
+#define MX51_PAD_CSI2_D19__GPIO4_12			0x1e8 0x5d8 0x000 0x3 0x0
+#define MX51_PAD_CSI2_VSYNC__CSI2_VSYNC			0x1ec 0x5dc 0x000 0x0 0x0
+#define MX51_PAD_CSI2_VSYNC__GPIO4_13			0x1ec 0x5dc 0x000 0x3 0x0
+#define MX51_PAD_CSI2_HSYNC__CSI2_HSYNC			0x1f0 0x5e0 0x000 0x0 0x0
+#define MX51_PAD_CSI2_HSYNC__GPIO4_14			0x1f0 0x5e0 0x000 0x3 0x0
+#define MX51_PAD_CSI2_PIXCLK__CSI2_PIXCLK		0x1f4 0x5e4 0x000 0x0 0x0
+#define MX51_PAD_CSI2_PIXCLK__GPIO4_15			0x1f4 0x5e4 0x000 0x3 0x0
+#define MX51_PAD_I2C1_CLK__GPIO4_16			0x1f8 0x5e8 0x000 0x3 0x0
+#define MX51_PAD_I2C1_CLK__I2C1_CLK			0x1f8 0x5e8 0x000 0x0 0x0
+#define MX51_PAD_I2C1_DAT__GPIO4_17			0x1fc 0x5ec 0x000 0x3 0x0
+#define MX51_PAD_I2C1_DAT__I2C1_DAT			0x1fc 0x5ec 0x000 0x0 0x0
+#define MX51_PAD_AUD3_BB_TXD__AUD3_TXD			0x200 0x5f0 0x000 0x0 0x0
+#define MX51_PAD_AUD3_BB_TXD__GPIO4_18			0x200 0x5f0 0x000 0x3 0x0
+#define MX51_PAD_AUD3_BB_RXD__AUD3_RXD			0x204 0x5f4 0x000 0x0 0x0
+#define MX51_PAD_AUD3_BB_RXD__GPIO4_19			0x204 0x5f4 0x000 0x3 0x0
+#define MX51_PAD_AUD3_BB_RXD__UART3_RXD			0x204 0x5f4 0x9f4 0x1 0x2
+#define MX51_PAD_AUD3_BB_CK__AUD3_TXC			0x208 0x5f8 0x000 0x0 0x0
+#define MX51_PAD_AUD3_BB_CK__GPIO4_20			0x208 0x5f8 0x000 0x3 0x0
+#define MX51_PAD_AUD3_BB_FS__AUD3_TXFS			0x20c 0x5fc 0x000 0x0 0x0
+#define MX51_PAD_AUD3_BB_FS__GPIO4_21			0x20c 0x5fc 0x000 0x3 0x0
+#define MX51_PAD_AUD3_BB_FS__UART3_TXD			0x20c 0x5fc 0x000 0x1 0x0
+#define MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI		0x210 0x600 0x000 0x0 0x0
+#define MX51_PAD_CSPI1_MOSI__GPIO4_22			0x210 0x600 0x000 0x3 0x0
+#define MX51_PAD_CSPI1_MOSI__I2C1_SDA			0x210 0x600 0x9b4 0x1 0x1
+#define MX51_PAD_CSPI1_MISO__AUD4_RXD			0x214 0x604 0x8c4 0x1 0x1
+#define MX51_PAD_CSPI1_MISO__ECSPI1_MISO		0x214 0x604 0x000 0x0 0x0
+#define MX51_PAD_CSPI1_MISO__GPIO4_23			0x214 0x604 0x000 0x3 0x0
+#define MX51_PAD_CSPI1_SS0__AUD4_TXC			0x218 0x608 0x8cc 0x1 0x1
+#define MX51_PAD_CSPI1_SS0__ECSPI1_SS0			0x218 0x608 0x000 0x0 0x0
+#define MX51_PAD_CSPI1_SS0__GPIO4_24			0x218 0x608 0x000 0x3 0x0
+#define MX51_PAD_CSPI1_SS1__AUD4_TXD			0x21c 0x60c 0x8c8 0x1 0x1
+#define MX51_PAD_CSPI1_SS1__ECSPI1_SS1			0x21c 0x60c 0x000 0x0 0x0
+#define MX51_PAD_CSPI1_SS1__GPIO4_25			0x21c 0x60c 0x000 0x3 0x0
+#define MX51_PAD_CSPI1_RDY__AUD4_TXFS			0x220 0x610 0x8d0 0x1 0x1
+#define MX51_PAD_CSPI1_RDY__ECSPI1_RDY			0x220 0x610 0x000 0x0 0x0
+#define MX51_PAD_CSPI1_RDY__GPIO4_26			0x220 0x610 0x000 0x3 0x0
+#define MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK		0x224 0x614 0x000 0x0 0x0
+#define MX51_PAD_CSPI1_SCLK__GPIO4_27			0x224 0x614 0x000 0x3 0x0
+#define MX51_PAD_CSPI1_SCLK__I2C1_SCL			0x224 0x614 0x9b0 0x1 0x1
+#define MX51_PAD_UART1_RXD__GPIO4_28			0x228 0x618 0x000 0x3 0x0
+#define MX51_PAD_UART1_RXD__UART1_RXD			0x228 0x618 0x9e4 0x0 0x0
+#define MX51_PAD_UART1_TXD__GPIO4_29			0x22c 0x61c 0x000 0x3 0x0
+#define MX51_PAD_UART1_TXD__PWM2_PWMO			0x22c 0x61c 0x000 0x1 0x0
+#define MX51_PAD_UART1_TXD__UART1_TXD			0x22c 0x61c 0x000 0x0 0x0
+#define MX51_PAD_UART1_RTS__GPIO4_30			0x230 0x620 0x000 0x3 0x0
+#define MX51_PAD_UART1_RTS__UART1_RTS			0x230 0x620 0x9e0 0x0 0x0
+#define MX51_PAD_UART1_CTS__GPIO4_31			0x234 0x624 0x000 0x3 0x0
+#define MX51_PAD_UART1_CTS__UART1_CTS			0x234 0x624 0x000 0x0 0x0
+#define MX51_PAD_UART2_RXD__FIRI_TXD			0x238 0x628 0x000 0x1 0x0
+#define MX51_PAD_UART2_RXD__GPIO1_20			0x238 0x628 0x000 0x3 0x0
+#define MX51_PAD_UART2_RXD__UART2_RXD			0x238 0x628 0x9ec 0x0 0x2
+#define MX51_PAD_UART2_TXD__FIRI_RXD			0x23c 0x62c 0x000 0x1 0x0
+#define MX51_PAD_UART2_TXD__GPIO1_21			0x23c 0x62c 0x000 0x3 0x0
+#define MX51_PAD_UART2_TXD__UART2_TXD			0x23c 0x62c 0x000 0x0 0x0
+#define MX51_PAD_UART3_RXD__CSI1_D0			0x240 0x630 0x000 0x2 0x0
+#define MX51_PAD_UART3_RXD__GPIO1_22			0x240 0x630 0x000 0x3 0x0
+#define MX51_PAD_UART3_RXD__UART1_DTR			0x240 0x630 0x000 0x0 0x0
+#define MX51_PAD_UART3_RXD__UART3_RXD			0x240 0x630 0x9f4 0x1 0x4
+#define MX51_PAD_UART3_TXD__CSI1_D1			0x244 0x634 0x000 0x2 0x0
+#define MX51_PAD_UART3_TXD__GPIO1_23			0x244 0x634 0x000 0x3 0x0
+#define MX51_PAD_UART3_TXD__UART1_DSR			0x244 0x634 0x000 0x0 0x0
+#define MX51_PAD_UART3_TXD__UART3_TXD			0x244 0x634 0x000 0x1 0x0
+#define MX51_PAD_OWIRE_LINE__GPIO1_24			0x248 0x638 0x000 0x3 0x0
+#define MX51_PAD_OWIRE_LINE__OWIRE_LINE			0x248 0x638 0x000 0x0 0x0
+#define MX51_PAD_OWIRE_LINE__SPDIF_OUT			0x248 0x638 0x000 0x6 0x0
+#define MX51_PAD_KEY_ROW0__KEY_ROW0			0x24c 0x63c 0x000 0x0 0x0
+#define MX51_PAD_KEY_ROW1__KEY_ROW1			0x250 0x640 0x000 0x0 0x0
+#define MX51_PAD_KEY_ROW2__KEY_ROW2			0x254 0x644 0x000 0x0 0x0
+#define MX51_PAD_KEY_ROW3__KEY_ROW3			0x258 0x648 0x000 0x0 0x0
+#define MX51_PAD_KEY_COL0__KEY_COL0			0x25c 0x64c 0x000 0x0 0x0
+#define MX51_PAD_KEY_COL0__PLL1_BYP			0x25c 0x64c 0x90c 0x7 0x0
+#define MX51_PAD_KEY_COL1__KEY_COL1			0x260 0x650 0x000 0x0 0x0
+#define MX51_PAD_KEY_COL1__PLL2_BYP			0x260 0x650 0x910 0x7 0x0
+#define MX51_PAD_KEY_COL2__KEY_COL2			0x264 0x654 0x000 0x0 0x0
+#define MX51_PAD_KEY_COL2__PLL3_BYP			0x264 0x654 0x000 0x7 0x0
+#define MX51_PAD_KEY_COL3__KEY_COL3			0x268 0x658 0x000 0x0 0x0
+#define MX51_PAD_KEY_COL4__I2C2_SCL			0x26c 0x65c 0x9b8 0x3 0x1
+#define MX51_PAD_KEY_COL4__KEY_COL4			0x26c 0x65c 0x000 0x0 0x0
+#define MX51_PAD_KEY_COL4__SPDIF_OUT1			0x26c 0x65c 0x000 0x6 0x0
+#define MX51_PAD_KEY_COL4__UART1_RI			0x26c 0x65c 0x000 0x1 0x0
+#define MX51_PAD_KEY_COL4__UART3_RTS			0x26c 0x65c 0x9f0 0x2 0x4
+#define MX51_PAD_KEY_COL5__I2C2_SDA			0x270 0x660 0x9bc 0x3 0x1
+#define MX51_PAD_KEY_COL5__KEY_COL5			0x270 0x660 0x000 0x0 0x0
+#define MX51_PAD_KEY_COL5__UART1_DCD			0x270 0x660 0x000 0x1 0x0
+#define MX51_PAD_KEY_COL5__UART3_CTS			0x270 0x660 0x000 0x2 0x0
+#define MX51_PAD_USBH1_CLK__CSPI_SCLK			0x278 0x678 0x914 0x1 0x1
+#define MX51_PAD_USBH1_CLK__GPIO1_25			0x278 0x678 0x000 0x2 0x0
+#define MX51_PAD_USBH1_CLK__I2C2_SCL			0x278 0x678 0x9b8 0x5 0x2
+#define MX51_PAD_USBH1_CLK__USBH1_CLK			0x278 0x678 0x000 0x0 0x0
+#define MX51_PAD_USBH1_DIR__CSPI_MOSI			0x27c 0x67c 0x91c 0x1 0x1
+#define MX51_PAD_USBH1_DIR__GPIO1_26			0x27c 0x67c 0x000 0x2 0x0
+#define MX51_PAD_USBH1_DIR__I2C2_SDA			0x27c 0x67c 0x9bc 0x5 0x2
+#define MX51_PAD_USBH1_DIR__USBH1_DIR			0x27c 0x67c 0x000 0x0 0x0
+#define MX51_PAD_USBH1_STP__CSPI_RDY			0x280 0x680 0x000 0x1 0x0
+#define MX51_PAD_USBH1_STP__GPIO1_27			0x280 0x680 0x000 0x2 0x0
+#define MX51_PAD_USBH1_STP__UART3_RXD			0x280 0x680 0x9f4 0x5 0x6
+#define MX51_PAD_USBH1_STP__USBH1_STP			0x280 0x680 0x000 0x0 0x0
+#define MX51_PAD_USBH1_NXT__CSPI_MISO			0x284 0x684 0x918 0x1 0x0
+#define MX51_PAD_USBH1_NXT__GPIO1_28			0x284 0x684 0x000 0x2 0x0
+#define MX51_PAD_USBH1_NXT__UART3_TXD			0x284 0x684 0x000 0x5 0x0
+#define MX51_PAD_USBH1_NXT__USBH1_NXT			0x284 0x684 0x000 0x0 0x0
+#define MX51_PAD_USBH1_DATA0__GPIO1_11			0x288 0x688 0x000 0x2 0x0
+#define MX51_PAD_USBH1_DATA0__UART2_CTS			0x288 0x688 0x000 0x1 0x0
+#define MX51_PAD_USBH1_DATA0__USBH1_DATA0		0x288 0x688 0x000 0x0 0x0
+#define MX51_PAD_USBH1_DATA1__GPIO1_12			0x28c 0x68c 0x000 0x2 0x0
+#define MX51_PAD_USBH1_DATA1__UART2_RXD			0x28c 0x68c 0x9ec 0x1 0x4
+#define MX51_PAD_USBH1_DATA1__USBH1_DATA1		0x28c 0x68c 0x000 0x0 0x0
+#define MX51_PAD_USBH1_DATA2__GPIO1_13			0x290 0x690 0x000 0x2 0x0
+#define MX51_PAD_USBH1_DATA2__UART2_TXD			0x290 0x690 0x000 0x1 0x0
+#define MX51_PAD_USBH1_DATA2__USBH1_DATA2		0x290 0x690 0x000 0x0 0x0
+#define MX51_PAD_USBH1_DATA3__GPIO1_14			0x294 0x694 0x000 0x2 0x0
+#define MX51_PAD_USBH1_DATA3__UART2_RTS			0x294 0x694 0x9e8 0x1 0x5
+#define MX51_PAD_USBH1_DATA3__USBH1_DATA3		0x294 0x694 0x000 0x0 0x0
+#define MX51_PAD_USBH1_DATA4__CSPI_SS0			0x298 0x698 0x000 0x1 0x0
+#define MX51_PAD_USBH1_DATA4__GPIO1_15			0x298 0x698 0x000 0x2 0x0
+#define MX51_PAD_USBH1_DATA4__USBH1_DATA4		0x298 0x698 0x000 0x0 0x0
+#define MX51_PAD_USBH1_DATA5__CSPI_SS1			0x29c 0x69c 0x920 0x1 0x0
+#define MX51_PAD_USBH1_DATA5__GPIO1_16			0x29c 0x69c 0x000 0x2 0x0
+#define MX51_PAD_USBH1_DATA5__USBH1_DATA5		0x29c 0x69c 0x000 0x0 0x0
+#define MX51_PAD_USBH1_DATA6__CSPI_SS3			0x2a0 0x6a0 0x928 0x1 0x1
+#define MX51_PAD_USBH1_DATA6__GPIO1_17			0x2a0 0x6a0 0x000 0x2 0x0
+#define MX51_PAD_USBH1_DATA6__USBH1_DATA6		0x2a0 0x6a0 0x000 0x0 0x0
+#define MX51_PAD_USBH1_DATA7__ECSPI1_SS3		0x2a4 0x6a4 0x000 0x1 0x0
+#define MX51_PAD_USBH1_DATA7__ECSPI2_SS3		0x2a4 0x6a4 0x934 0x5 0x1
+#define MX51_PAD_USBH1_DATA7__GPIO1_18			0x2a4 0x6a4 0x000 0x2 0x0
+#define MX51_PAD_USBH1_DATA7__USBH1_DATA7		0x2a4 0x6a4 0x000 0x0 0x0
+#define MX51_PAD_DI1_PIN11__DI1_PIN11			0x2a8 0x6a8 0x000 0x0 0x0
+#define MX51_PAD_DI1_PIN11__ECSPI1_SS2			0x2a8 0x6a8 0x000 0x7 0x0
+#define MX51_PAD_DI1_PIN11__GPIO3_0			0x2a8 0x6a8 0x000 0x4 0x0
+#define MX51_PAD_DI1_PIN12__DI1_PIN12			0x2ac 0x6ac 0x000 0x0 0x0
+#define MX51_PAD_DI1_PIN12__GPIO3_1			0x2ac 0x6ac 0x978 0x4 0x1
+#define MX51_PAD_DI1_PIN13__DI1_PIN13			0x2b0 0x6b0 0x000 0x0 0x0
+#define MX51_PAD_DI1_PIN13__GPIO3_2			0x2b0 0x6b0 0x97c 0x4 0x1
+#define MX51_PAD_DI1_D0_CS__DI1_D0_CS			0x2b4 0x6b4 0x000 0x0 0x0
+#define MX51_PAD_DI1_D0_CS__GPIO3_3			0x2b4 0x6b4 0x980 0x4 0x1
+#define MX51_PAD_DI1_D1_CS__DI1_D1_CS			0x2b8 0x6b8 0x000 0x0 0x0
+#define MX51_PAD_DI1_D1_CS__DISP1_PIN14			0x2b8 0x6b8 0x000 0x2 0x0
+#define MX51_PAD_DI1_D1_CS__DISP1_PIN5			0x2b8 0x6b8 0x000 0x3 0x0
+#define MX51_PAD_DI1_D1_CS__GPIO3_4			0x2b8 0x6b8 0x984 0x4 0x1
+#define MX51_PAD_DISPB2_SER_DIN__DISP1_PIN1		0x2bc 0x6bc 0x9a4 0x2 0x1
+#define MX51_PAD_DISPB2_SER_DIN__DISPB2_SER_DIN		0x2bc 0x6bc 0x9c4 0x0 0x0
+#define MX51_PAD_DISPB2_SER_DIN__GPIO3_5		0x2bc 0x6bc 0x988 0x4 0x1
+#define MX51_PAD_DISPB2_SER_DIO__DISP1_PIN6		0x2c0 0x6c0 0x000 0x3 0x0
+#define MX51_PAD_DISPB2_SER_DIO__DISPB2_SER_DIO		0x2c0 0x6c0 0x9c4 0x0 0x1
+#define MX51_PAD_DISPB2_SER_DIO__GPIO3_6		0x2c0 0x6c0 0x98c 0x4 0x1
+#define MX51_PAD_DISPB2_SER_CLK__DISP1_PIN17		0x2c4 0x6c4 0x000 0x2 0x0
+#define MX51_PAD_DISPB2_SER_CLK__DISP1_PIN7		0x2c4 0x6c4 0x000 0x3 0x0
+#define MX51_PAD_DISPB2_SER_CLK__DISPB2_SER_CLK		0x2c4 0x6c4 0x000 0x0 0x0
+#define MX51_PAD_DISPB2_SER_CLK__GPIO3_7		0x2c4 0x6c4 0x990 0x4 0x1
+#define MX51_PAD_DISPB2_SER_RS__DISP1_EXT_CLK		0x2c8 0x6c8 0x000 0x2 0x0
+#define MX51_PAD_DISPB2_SER_RS__DISP1_PIN16		0x2c8 0x6c8 0x000 0x2 0x0
+#define MX51_PAD_DISPB2_SER_RS__DISP1_PIN8		0x2c8 0x6c8 0x000 0x3 0x0
+#define MX51_PAD_DISPB2_SER_RS__DISPB2_SER_RS		0x2c8 0x6c8 0x000 0x0 0x0
+#define MX51_PAD_DISPB2_SER_RS__GPIO3_8			0x2c8 0x6c8 0x994 0x4 0x1
+#define MX51_PAD_DISP1_DAT0__DISP1_DAT0			0x2cc 0x6cc 0x000 0x0 0x0
+#define MX51_PAD_DISP1_DAT1__DISP1_DAT1			0x2d0 0x6d0 0x000 0x0 0x0
+#define MX51_PAD_DISP1_DAT2__DISP1_DAT2			0x2d4 0x6d4 0x000 0x0 0x0
+#define MX51_PAD_DISP1_DAT3__DISP1_DAT3			0x2d8 0x6d8 0x000 0x0 0x0
+#define MX51_PAD_DISP1_DAT4__DISP1_DAT4			0x2dc 0x6dc 0x000 0x0 0x0
+#define MX51_PAD_DISP1_DAT5__DISP1_DAT5			0x2e0 0x6e0 0x000 0x0 0x0
+#define MX51_PAD_DISP1_DAT6__BOOT_USB_SRC		0x2e4 0x6e4 0x000 0x7 0x0
+#define MX51_PAD_DISP1_DAT6__DISP1_DAT6			0x2e4 0x6e4 0x000 0x0 0x0
+#define MX51_PAD_DISP1_DAT7__BOOT_EEPROM_CFG		0x2e8 0x6e8 0x000 0x7 0x0
+#define MX51_PAD_DISP1_DAT7__DISP1_DAT7			0x2e8 0x6e8 0x000 0x0 0x0
+#define MX51_PAD_DISP1_DAT8__BOOT_SRC0			0x2ec 0x6ec 0x000 0x7 0x0
+#define MX51_PAD_DISP1_DAT8__DISP1_DAT8			0x2ec 0x6ec 0x000 0x0 0x0
+#define MX51_PAD_DISP1_DAT9__BOOT_SRC1			0x2f0 0x6f0 0x000 0x7 0x0
+#define MX51_PAD_DISP1_DAT9__DISP1_DAT9			0x2f0 0x6f0 0x000 0x0 0x0
+#define MX51_PAD_DISP1_DAT10__BOOT_SPARE_SIZE		0x2f4 0x6f4 0x000 0x7 0x0
+#define MX51_PAD_DISP1_DAT10__DISP1_DAT10		0x2f4 0x6f4 0x000 0x0 0x0
+#define MX51_PAD_DISP1_DAT11__BOOT_LPB_FREQ2		0x2f8 0x6f8 0x000 0x7 0x0
+#define MX51_PAD_DISP1_DAT11__DISP1_DAT11		0x2f8 0x6f8 0x000 0x0 0x0
+#define MX51_PAD_DISP1_DAT12__BOOT_MLC_SEL		0x2fc 0x6fc 0x000 0x7 0x0
+#define MX51_PAD_DISP1_DAT12__DISP1_DAT12		0x2fc 0x6fc 0x000 0x0 0x0
+#define MX51_PAD_DISP1_DAT13__BOOT_MEM_CTL0		0x300 0x700 0x000 0x7 0x0
+#define MX51_PAD_DISP1_DAT13__DISP1_DAT13		0x300 0x700 0x000 0x0 0x0
+#define MX51_PAD_DISP1_DAT14__BOOT_MEM_CTL1		0x304 0x704 0x000 0x7 0x0
+#define MX51_PAD_DISP1_DAT14__DISP1_DAT14		0x304 0x704 0x000 0x0 0x0
+#define MX51_PAD_DISP1_DAT15__BOOT_BUS_WIDTH		0x308 0x708 0x000 0x7 0x0
+#define MX51_PAD_DISP1_DAT15__DISP1_DAT15		0x308 0x708 0x000 0x0 0x0
+#define MX51_PAD_DISP1_DAT16__BOOT_PAGE_SIZE0		0x30c 0x70c 0x000 0x7 0x0
+#define MX51_PAD_DISP1_DAT16__DISP1_DAT16		0x30c 0x70c 0x000 0x0 0x0
+#define MX51_PAD_DISP1_DAT17__BOOT_PAGE_SIZE1		0x310 0x710 0x000 0x7 0x0
+#define MX51_PAD_DISP1_DAT17__DISP1_DAT17		0x310 0x710 0x000 0x0 0x0
+#define MX51_PAD_DISP1_DAT18__BOOT_WEIM_MUXED0		0x314 0x714 0x000 0x7 0x0
+#define MX51_PAD_DISP1_DAT18__DISP1_DAT18		0x314 0x714 0x000 0x0 0x0
+#define MX51_PAD_DISP1_DAT18__DISP2_PIN11		0x314 0x714 0x000 0x5 0x0
+#define MX51_PAD_DISP1_DAT18__DISP2_PIN5		0x314 0x714 0x000 0x4 0x0
+#define MX51_PAD_DISP1_DAT19__BOOT_WEIM_MUXED1		0x318 0x718 0x000 0x7 0x0
+#define MX51_PAD_DISP1_DAT19__DISP1_DAT19		0x318 0x718 0x000 0x0 0x0
+#define MX51_PAD_DISP1_DAT19__DISP2_PIN12		0x318 0x718 0x000 0x5 0x0
+#define MX51_PAD_DISP1_DAT19__DISP2_PIN6		0x318 0x718 0x000 0x4 0x0
+#define MX51_PAD_DISP1_DAT20__BOOT_MEM_TYPE0		0x31c 0x71c 0x000 0x7 0x0
+#define MX51_PAD_DISP1_DAT20__DISP1_DAT20		0x31c 0x71c 0x000 0x0 0x0
+#define MX51_PAD_DISP1_DAT20__DISP2_PIN13		0x31c 0x71c 0x000 0x5 0x0
+#define MX51_PAD_DISP1_DAT20__DISP2_PIN7		0x31c 0x71c 0x000 0x4 0x0
+#define MX51_PAD_DISP1_DAT21__BOOT_MEM_TYPE1		0x320 0x720 0x000 0x7 0x0
+#define MX51_PAD_DISP1_DAT21__DISP1_DAT21		0x320 0x720 0x000 0x0 0x0
+#define MX51_PAD_DISP1_DAT21__DISP2_PIN14		0x320 0x720 0x000 0x5 0x0
+#define MX51_PAD_DISP1_DAT21__DISP2_PIN8		0x320 0x720 0x000 0x4 0x0
+#define MX51_PAD_DISP1_DAT22__BOOT_LPB_FREQ0		0x324 0x724 0x000 0x7 0x0
+#define MX51_PAD_DISP1_DAT22__DISP1_DAT22		0x324 0x724 0x000 0x0 0x0
+#define MX51_PAD_DISP1_DAT22__DISP2_D0_CS		0x324 0x724 0x000 0x6 0x0
+#define MX51_PAD_DISP1_DAT22__DISP2_DAT16		0x324 0x724 0x000 0x5 0x0
+#define MX51_PAD_DISP1_DAT23__BOOT_LPB_FREQ1		0x328 0x728 0x000 0x7 0x0
+#define MX51_PAD_DISP1_DAT23__DISP1_DAT23		0x328 0x728 0x000 0x0 0x0
+#define MX51_PAD_DISP1_DAT23__DISP2_D1_CS		0x328 0x728 0x000 0x6 0x0
+#define MX51_PAD_DISP1_DAT23__DISP2_DAT17		0x328 0x728 0x000 0x5 0x0
+#define MX51_PAD_DISP1_DAT23__DISP2_SER_CS		0x328 0x728 0x000 0x4 0x0
+#define MX51_PAD_DI1_PIN3__DI1_PIN3			0x32c 0x72c 0x000 0x0 0x0
+#define MX51_PAD_DI1_PIN2__DI1_PIN2			0x330 0x734 0x000 0x0 0x0
+#define MX51_PAD_DI_GP2__DISP1_SER_CLK			0x338 0x740 0x000 0x0 0x0
+#define MX51_PAD_DI_GP2__DISP2_WAIT			0x338 0x740 0x9a8 0x2 0x1
+#define MX51_PAD_DI_GP3__CSI1_DATA_EN			0x33c 0x744 0x9a0 0x3 0x1
+#define MX51_PAD_DI_GP3__DISP1_SER_DIO			0x33c 0x744 0x9c0 0x0 0x0
+#define MX51_PAD_DI_GP3__FEC_TX_ER			0x33c 0x744 0x000 0x2 0x0
+#define MX51_PAD_DI2_PIN4__CSI2_DATA_EN			0x340 0x748 0x99c 0x3 0x1
+#define MX51_PAD_DI2_PIN4__DI2_PIN4			0x340 0x748 0x000 0x0 0x0
+#define MX51_PAD_DI2_PIN4__FEC_CRS			0x340 0x748 0x950 0x2 0x1
+#define MX51_PAD_DI2_PIN2__DI2_PIN2			0x344 0x74c 0x000 0x0 0x0
+#define MX51_PAD_DI2_PIN2__FEC_MDC			0x344 0x74c 0x000 0x2 0x0
+#define MX51_PAD_DI2_PIN3__DI2_PIN3			0x348 0x750 0x000 0x0 0x0
+#define MX51_PAD_DI2_PIN3__FEC_MDIO			0x348 0x750 0x954 0x2 0x1
+#define MX51_PAD_DI2_DISP_CLK__DI2_DISP_CLK		0x34c 0x754 0x000 0x0 0x0
+#define MX51_PAD_DI2_DISP_CLK__FEC_RDATA1		0x34c 0x754 0x95c 0x2 0x1
+#define MX51_PAD_DI_GP4__DI2_PIN15			0x350 0x758 0x000 0x4 0x0
+#define MX51_PAD_DI_GP4__DISP1_SER_DIN			0x350 0x758 0x9c0 0x0 0x1
+#define MX51_PAD_DI_GP4__DISP2_PIN1			0x350 0x758 0x000 0x3 0x0
+#define MX51_PAD_DI_GP4__FEC_RDATA2			0x350 0x758 0x960 0x2 0x1
+#define MX51_PAD_DISP2_DAT0__DISP2_DAT0			0x354 0x75c 0x000 0x0 0x0
+#define MX51_PAD_DISP2_DAT0__FEC_RDATA3			0x354 0x75c 0x964 0x2 0x1
+#define MX51_PAD_DISP2_DAT0__KEY_COL6			0x354 0x75c 0x9c8 0x4 0x1
+#define MX51_PAD_DISP2_DAT0__UART3_RXD			0x354 0x75c 0x9f4 0x5 0x8
+#define MX51_PAD_DISP2_DAT0__USBH3_CLK			0x354 0x75c 0x9f8 0x3 0x1
+#define MX51_PAD_DISP2_DAT1__DISP2_DAT1			0x358 0x760 0x000 0x0 0x0
+#define MX51_PAD_DISP2_DAT1__FEC_RX_ER			0x358 0x760 0x970 0x2 0x1
+#define MX51_PAD_DISP2_DAT1__KEY_COL7			0x358 0x760 0x9cc 0x4 0x1
+#define MX51_PAD_DISP2_DAT1__UART3_TXD			0x358 0x760 0x000 0x5 0x0
+#define MX51_PAD_DISP2_DAT1__USBH3_DIR			0x358 0x760 0xa1c 0x3 0x1
+#define MX51_PAD_DISP2_DAT2__DISP2_DAT2			0x35c 0x764 0x000 0x0 0x0
+#define MX51_PAD_DISP2_DAT3__DISP2_DAT3			0x360 0x768 0x000 0x0 0x0
+#define MX51_PAD_DISP2_DAT4__DISP2_DAT4			0x364 0x76c 0x000 0x0 0x0
+#define MX51_PAD_DISP2_DAT5__DISP2_DAT5			0x368 0x770 0x000 0x0 0x0
+#define MX51_PAD_DISP2_DAT6__DISP2_DAT6			0x36c 0x774 0x000 0x0 0x0
+#define MX51_PAD_DISP2_DAT6__FEC_TDATA1			0x36c 0x774 0x000 0x2 0x0
+#define MX51_PAD_DISP2_DAT6__GPIO1_19			0x36c 0x774 0x000 0x5 0x0
+#define MX51_PAD_DISP2_DAT6__KEY_ROW4			0x36c 0x774 0x9d0 0x4 0x1
+#define MX51_PAD_DISP2_DAT6__USBH3_STP			0x36c 0x774 0xa24 0x3 0x1
+#define MX51_PAD_DISP2_DAT7__DISP2_DAT7			0x370 0x778 0x000 0x0 0x0
+#define MX51_PAD_DISP2_DAT7__FEC_TDATA2			0x370 0x778 0x000 0x2 0x0
+#define MX51_PAD_DISP2_DAT7__GPIO1_29			0x370 0x778 0x000 0x5 0x0
+#define MX51_PAD_DISP2_DAT7__KEY_ROW5			0x370 0x778 0x9d4 0x4 0x1
+#define MX51_PAD_DISP2_DAT7__USBH3_NXT			0x370 0x778 0xa20 0x3 0x1
+#define MX51_PAD_DISP2_DAT8__DISP2_DAT8			0x374 0x77c 0x000 0x0 0x0
+#define MX51_PAD_DISP2_DAT8__FEC_TDATA3			0x374 0x77c 0x000 0x2 0x0
+#define MX51_PAD_DISP2_DAT8__GPIO1_30			0x374 0x77c 0x000 0x5 0x0
+#define MX51_PAD_DISP2_DAT8__KEY_ROW6			0x374 0x77c 0x9d8 0x4 0x1
+#define MX51_PAD_DISP2_DAT8__USBH3_DATA0		0x374 0x77c 0x9fc 0x3 0x1
+#define MX51_PAD_DISP2_DAT9__AUD6_RXC			0x378 0x780 0x8f4 0x4 0x1
+#define MX51_PAD_DISP2_DAT9__DISP2_DAT9			0x378 0x780 0x000 0x0 0x0
+#define MX51_PAD_DISP2_DAT9__FEC_TX_EN			0x378 0x780 0x000 0x2 0x0
+#define MX51_PAD_DISP2_DAT9__GPIO1_31			0x378 0x780 0x000 0x5 0x0
+#define MX51_PAD_DISP2_DAT9__USBH3_DATA1		0x378 0x780 0xa00 0x3 0x1
+#define MX51_PAD_DISP2_DAT10__DISP2_DAT10		0x37c 0x784 0x000 0x0 0x0
+#define MX51_PAD_DISP2_DAT10__DISP2_SER_CS		0x37c 0x784 0x000 0x5 0x0
+#define MX51_PAD_DISP2_DAT10__FEC_COL			0x37c 0x784 0x94c 0x2 0x1
+#define MX51_PAD_DISP2_DAT10__KEY_ROW7			0x37c 0x784 0x9dc 0x4 0x1
+#define MX51_PAD_DISP2_DAT10__USBH3_DATA2		0x37c 0x784 0xa04 0x3 0x1
+#define MX51_PAD_DISP2_DAT11__AUD6_TXD			0x380 0x788 0x8f0 0x4 0x1
+#define MX51_PAD_DISP2_DAT11__DISP2_DAT11		0x380 0x788 0x000 0x0 0x0
+#define MX51_PAD_DISP2_DAT11__FEC_RX_CLK		0x380 0x788 0x968 0x2 0x1
+#define MX51_PAD_DISP2_DAT11__GPIO1_10			0x380 0x788 0x000 0x7 0x0
+#define MX51_PAD_DISP2_DAT11__USBH3_DATA3		0x380 0x788 0xa08 0x3 0x1
+#define MX51_PAD_DISP2_DAT12__AUD6_RXD			0x384 0x78c 0x8ec 0x4 0x1
+#define MX51_PAD_DISP2_DAT12__DISP2_DAT12		0x384 0x78c 0x000 0x0 0x0
+#define MX51_PAD_DISP2_DAT12__FEC_RX_DV			0x384 0x78c 0x96c 0x2 0x1
+#define MX51_PAD_DISP2_DAT12__USBH3_DATA4		0x384 0x78c 0xa0c 0x3 0x1
+#define MX51_PAD_DISP2_DAT13__AUD6_TXC			0x388 0x790 0x8fc 0x4 0x1
+#define MX51_PAD_DISP2_DAT13__DISP2_DAT13		0x388 0x790 0x000 0x0 0x0
+#define MX51_PAD_DISP2_DAT13__FEC_TX_CLK		0x388 0x790 0x974 0x2 0x1
+#define MX51_PAD_DISP2_DAT13__USBH3_DATA5		0x388 0x790 0xa10 0x3 0x1
+#define MX51_PAD_DISP2_DAT14__AUD6_TXFS			0x38c 0x794 0x900 0x4 0x1
+#define MX51_PAD_DISP2_DAT14__DISP2_DAT14		0x38c 0x794 0x000 0x0 0x0
+#define MX51_PAD_DISP2_DAT14__FEC_RDATA0		0x38c 0x794 0x958 0x2 0x1
+#define MX51_PAD_DISP2_DAT14__USBH3_DATA6		0x38c 0x794 0xa14 0x3 0x1
+#define MX51_PAD_DISP2_DAT15__AUD6_RXFS			0x390 0x798 0x8f8 0x4 0x1
+#define MX51_PAD_DISP2_DAT15__DISP1_SER_CS		0x390 0x798 0x000 0x5 0x0
+#define MX51_PAD_DISP2_DAT15__DISP2_DAT15		0x390 0x798 0x000 0x0 0x0
+#define MX51_PAD_DISP2_DAT15__FEC_TDATA0		0x390 0x798 0x000 0x2 0x0
+#define MX51_PAD_DISP2_DAT15__USBH3_DATA7		0x390 0x798 0xa18 0x3 0x1
+#define MX51_PAD_SD1_CMD__AUD5_RXFS			0x394 0x79c 0x8e0 0x1 0x1
+#define MX51_PAD_SD1_CMD__CSPI_MOSI			0x394 0x79c 0x91c 0x2 0x2
+#define MX51_PAD_SD1_CMD__SD1_CMD			0x394 0x79c 0x000 0x0 0x0
+#define MX51_PAD_SD1_CLK__AUD5_RXC			0x398 0x7a0 0x8dc 0x1 0x1
+#define MX51_PAD_SD1_CLK__CSPI_SCLK			0x398 0x7a0 0x914 0x2 0x2
+#define MX51_PAD_SD1_CLK__SD1_CLK			0x398 0x7a0 0x000 0x0 0x0
+#define MX51_PAD_SD1_DATA0__AUD5_TXD			0x39c 0x7a4 0x8d8 0x1 0x2
+#define MX51_PAD_SD1_DATA0__CSPI_MISO			0x39c 0x7a4 0x918 0x2 0x1
+#define MX51_PAD_SD1_DATA0__SD1_DATA0			0x39c 0x7a4 0x000 0x0 0x0
+#define MX51_PAD_EIM_DA0__EIM_DA0			0x01c 0x000 0x000 0x0 0x0
+#define MX51_PAD_EIM_DA1__EIM_DA1			0x020 0x000 0x000 0x0 0x0
+#define MX51_PAD_EIM_DA2__EIM_DA2			0x024 0x000 0x000 0x0 0x0
+#define MX51_PAD_EIM_DA3__EIM_DA3			0x028 0x000 0x000 0x0 0x0
+#define MX51_PAD_SD1_DATA1__AUD5_RXD			0x3a0 0x7a8 0x8d4 0x1 0x2
+#define MX51_PAD_SD1_DATA1__SD1_DATA1			0x3a0 0x7a8 0x000 0x0 0x0
+#define MX51_PAD_EIM_DA4__EIM_DA4			0x02c 0x000 0x000 0x0 0x0
+#define MX51_PAD_EIM_DA5__EIM_DA5			0x030 0x000 0x000 0x0 0x0
+#define MX51_PAD_EIM_DA6__EIM_DA6			0x034 0x000 0x000 0x0 0x0
+#define MX51_PAD_EIM_DA7__EIM_DA7			0x038 0x000 0x000 0x0 0x0
+#define MX51_PAD_SD1_DATA2__AUD5_TXC			0x3a4 0x7ac 0x8e4 0x1 0x2
+#define MX51_PAD_SD1_DATA2__SD1_DATA2			0x3a4 0x7ac 0x000 0x0 0x0
+#define MX51_PAD_EIM_DA10__EIM_DA10			0x044 0x000 0x000 0x0 0x0
+#define MX51_PAD_EIM_DA11__EIM_DA11			0x048 0x000 0x000 0x0 0x0
+#define MX51_PAD_EIM_DA8__EIM_DA8			0x03c 0x000 0x000 0x0 0x0
+#define MX51_PAD_EIM_DA9__EIM_DA9			0x040 0x000 0x000 0x0 0x0
+#define MX51_PAD_SD1_DATA3__AUD5_TXFS			0x3a8 0x7b0 0x8e8 0x1 0x2
+#define MX51_PAD_SD1_DATA3__CSPI_SS1			0x3a8 0x7b0 0x920 0x2 0x1
+#define MX51_PAD_SD1_DATA3__SD1_DATA3			0x3a8 0x7b0 0x000 0x0 0x0
+#define MX51_PAD_GPIO1_0__CSPI_SS2			0x3ac 0x7b4 0x924 0x2 0x0
+#define MX51_PAD_GPIO1_0__GPIO1_0			0x3ac 0x7b4 0x000 0x1 0x0
+#define MX51_PAD_GPIO1_0__SD1_CD			0x3ac 0x7b4 0x000 0x0 0x0
+#define MX51_PAD_GPIO1_1__CSPI_MISO			0x3b0 0x7b8 0x918 0x2 0x2
+#define MX51_PAD_GPIO1_1__GPIO1_1			0x3b0 0x7b8 0x000 0x1 0x0
+#define MX51_PAD_GPIO1_1__SD1_WP			0x3b0 0x7b8 0x000 0x0 0x0
+#define MX51_PAD_EIM_DA12__EIM_DA12			0x04c 0x000 0x000 0x0 0x0
+#define MX51_PAD_EIM_DA13__EIM_DA13			0x050 0x000 0x000 0x0 0x0
+#define MX51_PAD_EIM_DA14__EIM_DA14			0x054 0x000 0x000 0x0 0x0
+#define MX51_PAD_EIM_DA15__EIM_DA15			0x058 0x000 0x000 0x0 0x0
+#define MX51_PAD_SD2_CMD__CSPI_MOSI			0x3b4 0x7bc 0x91c 0x2 0x3
+#define MX51_PAD_SD2_CMD__I2C1_SCL			0x3b4 0x7bc 0x9b0 0x1 0x2
+#define MX51_PAD_SD2_CMD__SD2_CMD			0x3b4 0x7bc 0x000 0x0 0x0
+#define MX51_PAD_SD2_CLK__CSPI_SCLK			0x3b8 0x7c0 0x914 0x2 0x3
+#define MX51_PAD_SD2_CLK__I2C1_SDA			0x3b8 0x7c0 0x9b4 0x1 0x2
+#define MX51_PAD_SD2_CLK__SD2_CLK			0x3b8 0x7c0 0x000 0x0 0x0
+#define MX51_PAD_SD2_DATA0__CSPI_MISO			0x3bc 0x7c4 0x918 0x2 0x3
+#define MX51_PAD_SD2_DATA0__SD1_DAT4			0x3bc 0x7c4 0x000 0x1 0x0
+#define MX51_PAD_SD2_DATA0__SD2_DATA0			0x3bc 0x7c4 0x000 0x0 0x0
+#define MX51_PAD_SD2_DATA1__SD1_DAT5			0x3c0 0x7c8 0x000 0x1 0x0
+#define MX51_PAD_SD2_DATA1__SD2_DATA1			0x3c0 0x7c8 0x000 0x0 0x0
+#define MX51_PAD_SD2_DATA1__USBH3_H2_DP			0x3c0 0x7c8 0x000 0x2 0x0
+#define MX51_PAD_SD2_DATA2__SD1_DAT6			0x3c4 0x7cc 0x000 0x1 0x0
+#define MX51_PAD_SD2_DATA2__SD2_DATA2			0x3c4 0x7cc 0x000 0x0 0x0
+#define MX51_PAD_SD2_DATA2__USBH3_H2_DM			0x3c4 0x7cc 0x000 0x2 0x0
+#define MX51_PAD_SD2_DATA3__CSPI_SS2			0x3c8 0x7d0 0x924 0x2 0x1
+#define MX51_PAD_SD2_DATA3__SD1_DAT7			0x3c8 0x7d0 0x000 0x1 0x0
+#define MX51_PAD_SD2_DATA3__SD2_DATA3			0x3c8 0x7d0 0x000 0x0 0x0
+#define MX51_PAD_GPIO1_2__CCM_OUT_2			0x3cc 0x7d4 0x000 0x5 0x0
+#define MX51_PAD_GPIO1_2__GPIO1_2			0x3cc 0x7d4 0x000 0x0 0x0
+#define MX51_PAD_GPIO1_2__I2C2_SCL			0x3cc 0x7d4 0x9b8 0x2 0x3
+#define MX51_PAD_GPIO1_2__PLL1_BYP			0x3cc 0x7d4 0x90c 0x7 0x1
+#define MX51_PAD_GPIO1_2__PWM1_PWMO			0x3cc 0x7d4 0x000 0x1 0x0
+#define MX51_PAD_GPIO1_3__GPIO1_3			0x3d0 0x7d8 0x000 0x0 0x0
+#define MX51_PAD_GPIO1_3__I2C2_SDA			0x3d0 0x7d8 0x9bc 0x2 0x3
+#define MX51_PAD_GPIO1_3__PLL2_BYP			0x3d0 0x7d8 0x910 0x7 0x1
+#define MX51_PAD_GPIO1_3__PWM2_PWMO			0x3d0 0x7d8 0x000 0x1 0x0
+#define MX51_PAD_PMIC_INT_REQ__PMIC_INT_REQ		0x3d4 0x7fc 0x000 0x0 0x0
+#define MX51_PAD_PMIC_INT_REQ__PMIC_PMU_IRQ_B		0x3d4 0x7fc 0x000 0x1 0x0
+#define MX51_PAD_GPIO1_4__DISP2_EXT_CLK			0x3d8 0x804 0x908 0x4 0x1
+#define MX51_PAD_GPIO1_4__EIM_RDY			0x3d8 0x804 0x938 0x3 0x1
+#define MX51_PAD_GPIO1_4__GPIO1_4			0x3d8 0x804 0x000 0x0 0x0
+#define MX51_PAD_GPIO1_4__WDOG1_WDOG_B			0x3d8 0x804 0x000 0x2 0x0
+#define MX51_PAD_GPIO1_5__CSI2_MCLK			0x3dc 0x808 0x000 0x6 0x0
+#define MX51_PAD_GPIO1_5__DISP2_PIN16			0x3dc 0x808 0x000 0x3 0x0
+#define MX51_PAD_GPIO1_5__GPIO1_5			0x3dc 0x808 0x000 0x0 0x0
+#define MX51_PAD_GPIO1_5__WDOG2_WDOG_B			0x3dc 0x808 0x000 0x2 0x0
+#define MX51_PAD_GPIO1_6__DISP2_PIN17			0x3e0 0x80c 0x000 0x4 0x0
+#define MX51_PAD_GPIO1_6__GPIO1_6			0x3e0 0x80c 0x000 0x0 0x0
+#define MX51_PAD_GPIO1_6__REF_EN_B			0x3e0 0x80c 0x000 0x3 0x0
+#define MX51_PAD_GPIO1_7__CCM_OUT_0			0x3e4 0x810 0x000 0x3 0x0
+#define MX51_PAD_GPIO1_7__GPIO1_7			0x3e4 0x810 0x000 0x0 0x0
+#define MX51_PAD_GPIO1_7__SD2_WP			0x3e4 0x810 0x000 0x6 0x0
+#define MX51_PAD_GPIO1_7__SPDIF_OUT1			0x3e4 0x810 0x000 0x2 0x0
+#define MX51_PAD_GPIO1_8__CSI2_DATA_EN			0x3e8 0x814 0x99c 0x2 0x2
+#define MX51_PAD_GPIO1_8__GPIO1_8			0x3e8 0x814 0x000 0x0 0x0
+#define MX51_PAD_GPIO1_8__SD2_CD			0x3e8 0x814 0x000 0x6 0x0
+#define MX51_PAD_GPIO1_8__USBH3_PWR			0x3e8 0x814 0x000 0x1 0x0
+#define MX51_PAD_GPIO1_9__CCM_OUT_1			0x3ec 0x818 0x000 0x3 0x0
+#define MX51_PAD_GPIO1_9__DISP2_D1_CS			0x3ec 0x818 0x000 0x2 0x0
+#define MX51_PAD_GPIO1_9__DISP2_SER_CS			0x3ec 0x818 0x000 0x7 0x0
+#define MX51_PAD_GPIO1_9__GPIO1_9			0x3ec 0x818 0x000 0x0 0x0
+#define MX51_PAD_GPIO1_9__SD2_LCTL			0x3ec 0x818 0x000 0x6 0x0
+#define MX51_PAD_GPIO1_9__USBH3_OC			0x3ec 0x818 0x000 0x1 0x0
+
+#endif /* __DTS_IMX51_PINFUNC_H */
diff --git a/arch/arm/boot/dts/imx51.dtsi b/arch/arm/boot/dts/imx51.dtsi
deleted file mode 100644
index fcf035b..0000000
--- a/arch/arm/boot/dts/imx51.dtsi
+++ /dev/null
@@ -1,614 +0,0 @@
-/*
- * Copyright 2011 Freescale Semiconductor, Inc.
- * Copyright 2011 Linaro Ltd.
- *
- * 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/ "skeleton.dtsi"
-
-/ {
-	aliases {
-		serial0 = &uart1;
-		serial1 = &uart2;
-		serial2 = &uart3;
-		gpio0 = &gpio1;
-		gpio1 = &gpio2;
-		gpio2 = &gpio3;
-		gpio3 = &gpio4;
-	};
-
-	tzic: tz-interrupt-controller@e0000000 {
-		compatible = "fsl,imx51-tzic", "fsl,tzic";
-		interrupt-controller;
-		#interrupt-cells = <1>;
-		reg = <0xe0000000 0x4000>;
-	};
-
-	clocks {
-		#address-cells = <1>;
-		#size-cells = <0>;
-
-		ckil {
-			compatible = "fsl,imx-ckil", "fixed-clock";
-			clock-frequency = <32768>;
-		};
-
-		ckih1 {
-			compatible = "fsl,imx-ckih1", "fixed-clock";
-			clock-frequency = <22579200>;
-		};
-
-		ckih2 {
-			compatible = "fsl,imx-ckih2", "fixed-clock";
-			clock-frequency = <0>;
-		};
-
-		osc {
-			compatible = "fsl,imx-osc", "fixed-clock";
-			clock-frequency = <24000000>;
-		};
-	};
-
-	soc {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		compatible = "simple-bus";
-		interrupt-parent = <&tzic>;
-		ranges;
-
-		ipu: ipu@40000000 {
-			#crtc-cells = <1>;
-			compatible = "fsl,imx51-ipu";
-			reg = <0x40000000 0x20000000>;
-			interrupts = <11 10>;
-		};
-
-		aips@70000000 { /* AIPS1 */
-			compatible = "fsl,aips-bus", "simple-bus";
-			#address-cells = <1>;
-			#size-cells = <1>;
-			reg = <0x70000000 0x10000000>;
-			ranges;
-
-			spba@70000000 {
-				compatible = "fsl,spba-bus", "simple-bus";
-				#address-cells = <1>;
-				#size-cells = <1>;
-				reg = <0x70000000 0x40000>;
-				ranges;
-
-				esdhc1: esdhc@70004000 {
-					compatible = "fsl,imx51-esdhc";
-					reg = <0x70004000 0x4000>;
-					interrupts = <1>;
-					clocks = <&clks 44>, <&clks 0>, <&clks 71>;
-					clock-names = "ipg", "ahb", "per";
-					status = "disabled";
-				};
-
-				esdhc2: esdhc@70008000 {
-					compatible = "fsl,imx51-esdhc";
-					reg = <0x70008000 0x4000>;
-					interrupts = <2>;
-					clocks = <&clks 45>, <&clks 0>, <&clks 72>;
-					clock-names = "ipg", "ahb", "per";
-					bus-width = <4>;
-					status = "disabled";
-				};
-
-				uart3: serial@7000c000 {
-					compatible = "fsl,imx51-uart", "fsl,imx21-uart";
-					reg = <0x7000c000 0x4000>;
-					interrupts = <33>;
-					clocks = <&clks 32>, <&clks 33>;
-					clock-names = "ipg", "per";
-					status = "disabled";
-				};
-
-				ecspi1: ecspi@70010000 {
-					#address-cells = <1>;
-					#size-cells = <0>;
-					compatible = "fsl,imx51-ecspi";
-					reg = <0x70010000 0x4000>;
-					interrupts = <36>;
-					clocks = <&clks 51>, <&clks 52>;
-					clock-names = "ipg", "per";
-					status = "disabled";
-				};
-
-				ssi2: ssi@70014000 {
-					compatible = "fsl,imx51-ssi", "fsl,imx21-ssi";
-					reg = <0x70014000 0x4000>;
-					interrupts = <30>;
-					clocks = <&clks 49>;
-					fsl,fifo-depth = <15>;
-					fsl,ssi-dma-events = <25 24 23 22>; /* TX0 RX0 TX1 RX1 */
-					status = "disabled";
-				};
-
-				esdhc3: esdhc@70020000 {
-					compatible = "fsl,imx51-esdhc";
-					reg = <0x70020000 0x4000>;
-					interrupts = <3>;
-					clocks = <&clks 46>, <&clks 0>, <&clks 73>;
-					clock-names = "ipg", "ahb", "per";
-					bus-width = <4>;
-					status = "disabled";
-				};
-
-				esdhc4: esdhc@70024000 {
-					compatible = "fsl,imx51-esdhc";
-					reg = <0x70024000 0x4000>;
-					interrupts = <4>;
-					clocks = <&clks 47>, <&clks 0>, <&clks 74>;
-					clock-names = "ipg", "ahb", "per";
-					bus-width = <4>;
-					status = "disabled";
-				};
-			};
-
-			usbotg: usb@73f80000 {
-				compatible = "fsl,imx51-usb", "fsl,imx27-usb";
-				reg = <0x73f80000 0x0200>;
-				interrupts = <18>;
-				status = "disabled";
-			};
-
-			usbh1: usb@73f80200 {
-				compatible = "fsl,imx51-usb", "fsl,imx27-usb";
-				reg = <0x73f80200 0x0200>;
-				interrupts = <14>;
-				status = "disabled";
-			};
-
-			usbh2: usb@73f80400 {
-				compatible = "fsl,imx51-usb", "fsl,imx27-usb";
-				reg = <0x73f80400 0x0200>;
-				interrupts = <16>;
-				status = "disabled";
-			};
-
-			usbh3: usb@73f80600 {
-				compatible = "fsl,imx51-usb", "fsl,imx27-usb";
-				reg = <0x73f80600 0x0200>;
-				interrupts = <17>;
-				status = "disabled";
-			};
-
-			gpio1: gpio@73f84000 {
-				compatible = "fsl,imx51-gpio", "fsl,imx35-gpio";
-				reg = <0x73f84000 0x4000>;
-				interrupts = <50 51>;
-				gpio-controller;
-				#gpio-cells = <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-			};
-
-			gpio2: gpio@73f88000 {
-				compatible = "fsl,imx51-gpio", "fsl,imx35-gpio";
-				reg = <0x73f88000 0x4000>;
-				interrupts = <52 53>;
-				gpio-controller;
-				#gpio-cells = <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-			};
-
-			gpio3: gpio@73f8c000 {
-				compatible = "fsl,imx51-gpio", "fsl,imx35-gpio";
-				reg = <0x73f8c000 0x4000>;
-				interrupts = <54 55>;
-				gpio-controller;
-				#gpio-cells = <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-			};
-
-			gpio4: gpio@73f90000 {
-				compatible = "fsl,imx51-gpio", "fsl,imx35-gpio";
-				reg = <0x73f90000 0x4000>;
-				interrupts = <56 57>;
-				gpio-controller;
-				#gpio-cells = <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-			};
-
-			kpp: kpp@73f94000 {
-				compatible = "fsl,imx51-kpp", "fsl,imx21-kpp";
-				reg = <0x73f94000 0x4000>;
-				interrupts = <60>;
-				clocks = <&clks 0>;
-				status = "disabled";
-			};
-
-			wdog1: wdog@73f98000 {
-				compatible = "fsl,imx51-wdt", "fsl,imx21-wdt";
-				reg = <0x73f98000 0x4000>;
-				interrupts = <58>;
-				clocks = <&clks 0>;
-			};
-
-			wdog2: wdog@73f9c000 {
-				compatible = "fsl,imx51-wdt", "fsl,imx21-wdt";
-				reg = <0x73f9c000 0x4000>;
-				interrupts = <59>;
-				clocks = <&clks 0>;
-				status = "disabled";
-			};
-
-			iomuxc: iomuxc@73fa8000 {
-				compatible = "fsl,imx51-iomuxc";
-				reg = <0x73fa8000 0x4000>;
-
-				audmux {
-					pinctrl_audmux_1: audmuxgrp-1 {
-						fsl,pins = <
-							384 0x80000000	/* MX51_PAD_AUD3_BB_TXD__AUD3_TXD */
-							386 0x80000000	/* MX51_PAD_AUD3_BB_RXD__AUD3_RXD */
-							389 0x80000000	/* MX51_PAD_AUD3_BB_CK__AUD3_TXC */
-							391 0x80000000	/* MX51_PAD_AUD3_BB_FS__AUD3_TXFS */
-						>;
-					};
-				};
-
-				fec {
-					pinctrl_fec_1: fecgrp-1 {
-						fsl,pins = <
-							128 0x80000000	/* MX51_PAD_EIM_EB2__FEC_MDIO */
-							134 0x80000000	/* MX51_PAD_EIM_EB3__FEC_RDATA1 */
-							146 0x80000000	/* MX51_PAD_EIM_CS2__FEC_RDATA2 */
-							152 0x80000000	/* MX51_PAD_EIM_CS3__FEC_RDATA3 */
-							158 0x80000000	/* MX51_PAD_EIM_CS4__FEC_RX_ER */
-							165 0x80000000	/* MX51_PAD_EIM_CS5__FEC_CRS */
-							206 0x80000000	/* MX51_PAD_NANDF_RB2__FEC_COL */
-							213 0x80000000	/* MX51_PAD_NANDF_RB3__FEC_RX_CLK */
-							293 0x80000000	/* MX51_PAD_NANDF_D9__FEC_RDATA0 */
-							298 0x80000000	/* MX51_PAD_NANDF_D8__FEC_TDATA0 */
-							225 0x80000000	/* MX51_PAD_NANDF_CS2__FEC_TX_ER */
-							231 0x80000000	/* MX51_PAD_NANDF_CS3__FEC_MDC */
-							237 0x80000000	/* MX51_PAD_NANDF_CS4__FEC_TDATA1 */
-							243 0x80000000	/* MX51_PAD_NANDF_CS5__FEC_TDATA2 */
-							250 0x80000000	/* MX51_PAD_NANDF_CS6__FEC_TDATA3 */
-							255 0x80000000	/* MX51_PAD_NANDF_CS7__FEC_TX_EN */
-							260 0x80000000	/* MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK */
-						>;
-					};
-
-					pinctrl_fec_2: fecgrp-2 {
-						fsl,pins = <
-							589 0x80000000 /* MX51_PAD_DI_GP3__FEC_TX_ER */
-							592 0x80000000 /* MX51_PAD_DI2_PIN4__FEC_CRS */
-							594 0x80000000 /* MX51_PAD_DI2_PIN2__FEC_MDC */
-							596 0x80000000 /* MX51_PAD_DI2_PIN3__FEC_MDIO */
-							598 0x80000000 /* MX51_PAD_DI2_DISP_CLK__FEC_RDATA1 */
-							602 0x80000000 /* MX51_PAD_DI_GP4__FEC_RDATA2 */
-							604 0x80000000 /* MX51_PAD_DISP2_DAT0__FEC_RDATA3 */
-							609 0x80000000 /* MX51_PAD_DISP2_DAT1__FEC_RX_ER */
-							618 0x80000000 /* MX51_PAD_DISP2_DAT6__FEC_TDATA1 */
-							623 0x80000000 /* MX51_PAD_DISP2_DAT7__FEC_TDATA2 */
-							628 0x80000000 /* MX51_PAD_DISP2_DAT8__FEC_TDATA3 */
-							634 0x80000000 /* MX51_PAD_DISP2_DAT9__FEC_TX_EN */
-							639 0x80000000 /* MX51_PAD_DISP2_DAT10__FEC_COL */
-							644 0x80000000 /* MX51_PAD_DISP2_DAT11__FEC_RX_CLK */
-							649 0x80000000 /* MX51_PAD_DISP2_DAT12__FEC_RX_DV */
-							653 0x80000000 /* MX51_PAD_DISP2_DAT13__FEC_TX_CLK */
-							657 0x80000000 /* MX51_PAD_DISP2_DAT14__FEC_RDATA0 */
-							662 0x80000000 /* MX51_PAD_DISP2_DAT15__FEC_TDATA0 */
-						>;
-					};
-				};
-
-				ecspi1 {
-					pinctrl_ecspi1_1: ecspi1grp-1 {
-						fsl,pins = <
-							398 0x185	/* MX51_PAD_CSPI1_MISO__ECSPI1_MISO */
-							394 0x185	/* MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI */
-							409 0x185	/* MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK */
-						>;
-					};
-				};
-
-				esdhc1 {
-					pinctrl_esdhc1_1: esdhc1grp-1 {
-						fsl,pins = <
-							666 0x400020d5	/* MX51_PAD_SD1_CMD__SD1_CMD */
-							669 0x20d5	/* MX51_PAD_SD1_CLK__SD1_CLK */
-							672 0x20d5	/* MX51_PAD_SD1_DATA0__SD1_DATA0 */
-							678 0x20d5	/* MX51_PAD_SD1_DATA1__SD1_DATA1 */
-							684 0x20d5	/* MX51_PAD_SD1_DATA2__SD1_DATA2 */
-							691 0x20d5	/* MX51_PAD_SD1_DATA3__SD1_DATA3 */
-						>;
-					};
-				};
-
-				esdhc2 {
-					pinctrl_esdhc2_1: esdhc2grp-1 {
-						fsl,pins = <
-							704 0x400020d5	/* MX51_PAD_SD2_CMD__SD2_CMD */
-							707 0x20d5	/* MX51_PAD_SD2_CLK__SD2_CLK */
-							710 0x20d5	/* MX51_PAD_SD2_DATA0__SD2_DATA0 */
-							712 0x20d5	/* MX51_PAD_SD2_DATA1__SD2_DATA1 */
-							715 0x20d5	/* MX51_PAD_SD2_DATA2__SD2_DATA2 */
-							719 0x20d5	/* MX51_PAD_SD2_DATA3__SD2_DATA3 */
-						>;
-					};
-				};
-
-				i2c2 {
-					pinctrl_i2c2_1: i2c2grp-1 {
-						fsl,pins = <
-							449 0x400001ed	/* MX51_PAD_KEY_COL4__I2C2_SCL */
-							454 0x400001ed	/* MX51_PAD_KEY_COL5__I2C2_SDA */
-						>;
-					};
-				};
-
-				ipu_disp1 {
-					pinctrl_ipu_disp1_1: ipudisp1grp-1 {
-						fsl,pins = <
-							528 0x5 /* MX51_PAD_DISP1_DAT0__DISP1_DAT0 */
-							529 0x5 /* MX51_PAD_DISP1_DAT1__DISP1_DAT1 */
-							530 0x5 /* MX51_PAD_DISP1_DAT2__DISP1_DAT2 */
-							531 0x5 /* MX51_PAD_DISP1_DAT3__DISP1_DAT3 */
-							532 0x5 /* MX51_PAD_DISP1_DAT4__DISP1_DAT4 */
-							533 0x5 /* MX51_PAD_DISP1_DAT5__DISP1_DAT5 */
-							535 0x5 /* MX51_PAD_DISP1_DAT6__DISP1_DAT6 */
-							537 0x5 /* MX51_PAD_DISP1_DAT7__DISP1_DAT7 */
-							539 0x5 /* MX51_PAD_DISP1_DAT8__DISP1_DAT8 */
-							541 0x5 /* MX51_PAD_DISP1_DAT9__DISP1_DAT9 */
-							543 0x5 /* MX51_PAD_DISP1_DAT10__DISP1_DAT10 */
-							545 0x5 /* MX51_PAD_DISP1_DAT11__DISP1_DAT11 */
-							547 0x5 /* MX51_PAD_DISP1_DAT12__DISP1_DAT12 */
-							549 0x5 /* MX51_PAD_DISP1_DAT13__DISP1_DAT13 */
-							551 0x5 /* MX51_PAD_DISP1_DAT14__DISP1_DAT14 */
-							553 0x5 /* MX51_PAD_DISP1_DAT15__DISP1_DAT15 */
-							555 0x5 /* MX51_PAD_DISP1_DAT16__DISP1_DAT16 */
-							557 0x5 /* MX51_PAD_DISP1_DAT17__DISP1_DAT17 */
-							559 0x5 /* MX51_PAD_DISP1_DAT18__DISP1_DAT18 */
-							563 0x5 /* MX51_PAD_DISP1_DAT19__DISP1_DAT19 */
-							567 0x5 /* MX51_PAD_DISP1_DAT20__DISP1_DAT20 */
-							571 0x5 /* MX51_PAD_DISP1_DAT21__DISP1_DAT21 */
-							575 0x5 /* MX51_PAD_DISP1_DAT22__DISP1_DAT22 */
-							579 0x5 /* MX51_PAD_DISP1_DAT23__DISP1_DAT23 */
-							584 0x5 /* MX51_PAD_DI1_PIN2__DI1_PIN2 (hsync) */
-							583 0x5 /* MX51_PAD_DI1_PIN3__DI1_PIN3 (vsync) */
-						>;
-					};
-				};
-
-				ipu_disp2 {
-					pinctrl_ipu_disp2_1: ipudisp2grp-1 {
-						fsl,pins = <
-							603 0x5 /* MX51_PAD_DISP2_DAT0__DISP2_DAT0 */
-							608 0x5 /* MX51_PAD_DISP2_DAT1__DISP2_DAT1 */
-							613 0x5 /* MX51_PAD_DISP2_DAT2__DISP2_DAT2 */
-							614 0x5 /* MX51_PAD_DISP2_DAT3__DISP2_DAT3 */
-							615 0x5 /* MX51_PAD_DISP2_DAT4__DISP2_DAT4 */
-							616 0x5 /* MX51_PAD_DISP2_DAT5__DISP2_DAT5 */
-							617 0x5 /* MX51_PAD_DISP2_DAT6__DISP2_DAT6 */
-							622 0x5 /* MX51_PAD_DISP2_DAT7__DISP2_DAT7 */
-							627 0x5 /* MX51_PAD_DISP2_DAT8__DISP2_DAT8 */
-							633 0x5 /* MX51_PAD_DISP2_DAT9__DISP2_DAT9 */
-							637 0x5 /* MX51_PAD_DISP2_DAT10__DISP2_DAT10 */
-							643 0x5 /* MX51_PAD_DISP2_DAT11__DISP2_DAT11 */
-							648 0x5 /* MX51_PAD_DISP2_DAT12__DISP2_DAT12 */
-							652 0x5 /* MX51_PAD_DISP2_DAT13__DISP2_DAT13 */
-							656 0x5 /* MX51_PAD_DISP2_DAT14__DISP2_DAT14 */
-							661 0x5 /* MX51_PAD_DISP2_DAT15__DISP2_DAT15 */
-							593 0x5 /* MX51_PAD_DI2_PIN2__DI2_PIN2 (hsync) */
-							595 0x5 /* MX51_PAD_DI2_PIN3__DI2_PIN3 (vsync) */
-							597 0x5 /* MX51_PAD_DI2_DISP_CLK__DI2_DISP_CLK */
-							599 0x5 /* MX51_PAD_DI_GP4__DI2_PIN15 */
-						>;
-					};
-				};
-
-				uart1 {
-					pinctrl_uart1_1: uart1grp-1 {
-						fsl,pins = <
-							413 0x1c5	/* MX51_PAD_UART1_RXD__UART1_RXD */
-							416 0x1c5	/* MX51_PAD_UART1_TXD__UART1_TXD */
-							418 0x1c5	/* MX51_PAD_UART1_RTS__UART1_RTS */
-							420 0x1c5	/* MX51_PAD_UART1_CTS__UART1_CTS */
-						>;
-					};
-				};
-
-				uart2 {
-					pinctrl_uart2_1: uart2grp-1 {
-						fsl,pins = <
-							423 0x1c5	/* MX51_PAD_UART2_RXD__UART2_RXD */
-							426 0x1c5	/* MX51_PAD_UART2_TXD__UART2_TXD */
-						>;
-					};
-				};
-
-				uart3 {
-					pinctrl_uart3_1: uart3grp-1 {
-						fsl,pins = <
-							54 0x1c5	/* MX51_PAD_EIM_D25__UART3_RXD */
-							59 0x1c5	/* MX51_PAD_EIM_D26__UART3_TXD */
-							65 0x1c5	/* MX51_PAD_EIM_D27__UART3_RTS */
-							49 0x1c5	/* MX51_PAD_EIM_D24__UART3_CTS */
-						>;
-					};
-
-					pinctrl_uart3_2: uart3grp-2 {
-						fsl,pins = <
-							434 0x1c5	/* MX51_PAD_UART3_RXD__UART3_RXD */
-							430 0x1c5	/* MX51_PAD_UART3_TXD__UART3_TXD */
-						>;
-					};
-				};
-
-				kpp {
-					pinctrl_kpp_1: kppgrp-1 {
-						fsl,pins = <
-							438 0xe0	/* MX51_PAD_KEY_ROW0__KEY_ROW0 */
-							439 0xe0	/* MX51_PAD_KEY_ROW1__KEY_ROW1 */
-							440 0xe0	/* MX51_PAD_KEY_ROW2__KEY_ROW2 */
-							441 0xe0	/* MX51_PAD_KEY_ROW3__KEY_ROW3 */
-							442 0xe8	/* MX51_PAD_KEY_COL0__KEY_COL0 */
-							444 0xe8	/* MX51_PAD_KEY_COL1__KEY_COL1 */
-							446 0xe8	/* MX51_PAD_KEY_COL2__KEY_COL2 */
-							448 0xe8	/* MX51_PAD_KEY_COL3__KEY_COL3 */
-						>;
-					};
-				};
-			};
-
-			pwm1: pwm@73fb4000 {
-				#pwm-cells = <2>;
-				compatible = "fsl,imx51-pwm", "fsl,imx27-pwm";
-				reg = <0x73fb4000 0x4000>;
-				clocks = <&clks 37>, <&clks 38>;
-				clock-names = "ipg", "per";
-				interrupts = <61>;
-			};
-
-			pwm2: pwm@73fb8000 {
-				#pwm-cells = <2>;
-				compatible = "fsl,imx51-pwm", "fsl,imx27-pwm";
-				reg = <0x73fb8000 0x4000>;
-				clocks = <&clks 39>, <&clks 40>;
-				clock-names = "ipg", "per";
-				interrupts = <94>;
-			};
-
-			uart1: serial@73fbc000 {
-				compatible = "fsl,imx51-uart", "fsl,imx21-uart";
-				reg = <0x73fbc000 0x4000>;
-				interrupts = <31>;
-				clocks = <&clks 28>, <&clks 29>;
-				clock-names = "ipg", "per";
-				status = "disabled";
-			};
-
-			uart2: serial@73fc0000 {
-				compatible = "fsl,imx51-uart", "fsl,imx21-uart";
-				reg = <0x73fc0000 0x4000>;
-				interrupts = <32>;
-				clocks = <&clks 30>, <&clks 31>;
-				clock-names = "ipg", "per";
-				status = "disabled";
-			};
-
-			clks: ccm@73fd4000{
-				compatible = "fsl,imx51-ccm";
-				reg = <0x73fd4000 0x4000>;
-				interrupts = <0 71 0x04 0 72 0x04>;
-				#clock-cells = <1>;
-			};
-		};
-
-		aips@80000000 {	/* AIPS2 */
-			compatible = "fsl,aips-bus", "simple-bus";
-			#address-cells = <1>;
-			#size-cells = <1>;
-			reg = <0x80000000 0x10000000>;
-			ranges;
-
-			ecspi2: ecspi@83fac000 {
-				#address-cells = <1>;
-				#size-cells = <0>;
-				compatible = "fsl,imx51-ecspi";
-				reg = <0x83fac000 0x4000>;
-				interrupts = <37>;
-				clocks = <&clks 53>, <&clks 54>;
-				clock-names = "ipg", "per";
-				status = "disabled";
-			};
-
-			sdma: sdma@83fb0000 {
-				compatible = "fsl,imx51-sdma", "fsl,imx35-sdma";
-				reg = <0x83fb0000 0x4000>;
-				interrupts = <6>;
-				clocks = <&clks 56>, <&clks 56>;
-				clock-names = "ipg", "ahb";
-				fsl,sdma-ram-script-name = "imx/sdma/sdma-imx51.bin";
-			};
-
-			cspi: cspi@83fc0000 {
-				#address-cells = <1>;
-				#size-cells = <0>;
-				compatible = "fsl,imx51-cspi", "fsl,imx35-cspi";
-				reg = <0x83fc0000 0x4000>;
-				interrupts = <38>;
-				clocks = <&clks 55>, <&clks 0>;
-				clock-names = "ipg", "per";
-				status = "disabled";
-			};
-
-			i2c2: i2c@83fc4000 {
-				#address-cells = <1>;
-				#size-cells = <0>;
-				compatible = "fsl,imx51-i2c", "fsl,imx21-i2c";
-				reg = <0x83fc4000 0x4000>;
-				interrupts = <63>;
-				clocks = <&clks 35>;
-				status = "disabled";
-			};
-
-			i2c1: i2c@83fc8000 {
-				#address-cells = <1>;
-				#size-cells = <0>;
-				compatible = "fsl,imx51-i2c", "fsl,imx21-i2c";
-				reg = <0x83fc8000 0x4000>;
-				interrupts = <62>;
-				clocks = <&clks 34>;
-				status = "disabled";
-			};
-
-			ssi1: ssi@83fcc000 {
-				compatible = "fsl,imx51-ssi", "fsl,imx21-ssi";
-				reg = <0x83fcc000 0x4000>;
-				interrupts = <29>;
-				clocks = <&clks 48>;
-				fsl,fifo-depth = <15>;
-				fsl,ssi-dma-events = <29 28 27 26>; /* TX0 RX0 TX1 RX1 */
-				status = "disabled";
-			};
-
-			audmux: audmux@83fd0000 {
-				compatible = "fsl,imx51-audmux", "fsl,imx31-audmux";
-				reg = <0x83fd0000 0x4000>;
-				status = "disabled";
-			};
-
-			nfc: nand@83fdb000 {
-				compatible = "fsl,imx51-nand";
-				reg = <0x83fdb000 0x1000 0xcfff0000 0x10000>;
-				interrupts = <8>;
-				clocks = <&clks 60>;
-				status = "disabled";
-			};
-
-			ssi3: ssi@83fe8000 {
-				compatible = "fsl,imx51-ssi", "fsl,imx21-ssi";
-				reg = <0x83fe8000 0x4000>;
-				interrupts = <96>;
-				clocks = <&clks 50>;
-				fsl,fifo-depth = <15>;
-				fsl,ssi-dma-events = <47 46 37 35>; /* TX0 RX0 TX1 RX1 */
-				status = "disabled";
-			};
-
-			fec: ethernet@83fec000 {
-				compatible = "fsl,imx51-fec", "fsl,imx27-fec";
-				reg = <0x83fec000 0x4000>;
-				interrupts = <87>;
-				clocks = <&clks 42>, <&clks 42>, <&clks 42>;
-				clock-names = "ipg", "ahb", "ptp";
-				status = "disabled";
-			};
-		};
-	};
-};
diff --git a/arch/arm/boot/dts/imx51.dtsip b/arch/arm/boot/dts/imx51.dtsip
new file mode 100644
index 0000000..58204ee
--- /dev/null
+++ b/arch/arm/boot/dts/imx51.dtsip
@@ -0,0 +1,693 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * 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 "skeleton.dtsi"
+#include "imx51-pinfunc.h"
+
+/ {
+	aliases {
+		serial0 = &uart1;
+		serial1 = &uart2;
+		serial2 = &uart3;
+		gpio0 = &gpio1;
+		gpio1 = &gpio2;
+		gpio2 = &gpio3;
+		gpio3 = &gpio4;
+	};
+
+	tzic: tz-interrupt-controller@e0000000 {
+		compatible = "fsl,imx51-tzic", "fsl,tzic";
+		interrupt-controller;
+		#interrupt-cells = <1>;
+		reg = <0xe0000000 0x4000>;
+	};
+
+	clocks {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		ckil {
+			compatible = "fsl,imx-ckil", "fixed-clock";
+			clock-frequency = <32768>;
+		};
+
+		ckih1 {
+			compatible = "fsl,imx-ckih1", "fixed-clock";
+			clock-frequency = <22579200>;
+		};
+
+		ckih2 {
+			compatible = "fsl,imx-ckih2", "fixed-clock";
+			clock-frequency = <0>;
+		};
+
+		osc {
+			compatible = "fsl,imx-osc", "fixed-clock";
+			clock-frequency = <24000000>;
+		};
+	};
+
+	soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		interrupt-parent = <&tzic>;
+		ranges;
+
+		ipu: ipu@40000000 {
+			#crtc-cells = <1>;
+			compatible = "fsl,imx51-ipu";
+			reg = <0x40000000 0x20000000>;
+			interrupts = <11 10>;
+			clocks = <&clks 59>, <&clks 110>, <&clks 61>;
+			clock-names = "bus", "di0", "di1";
+			resets = <&src 2>;
+		};
+
+		aips@70000000 { /* AIPS1 */
+			compatible = "fsl,aips-bus", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x70000000 0x10000000>;
+			ranges;
+
+			spba@70000000 {
+				compatible = "fsl,spba-bus", "simple-bus";
+				#address-cells = <1>;
+				#size-cells = <1>;
+				reg = <0x70000000 0x40000>;
+				ranges;
+
+				esdhc1: esdhc@70004000 {
+					compatible = "fsl,imx51-esdhc";
+					reg = <0x70004000 0x4000>;
+					interrupts = <1>;
+					clocks = <&clks 44>, <&clks 0>, <&clks 71>;
+					clock-names = "ipg", "ahb", "per";
+					status = "disabled";
+				};
+
+				esdhc2: esdhc@70008000 {
+					compatible = "fsl,imx51-esdhc";
+					reg = <0x70008000 0x4000>;
+					interrupts = <2>;
+					clocks = <&clks 45>, <&clks 0>, <&clks 72>;
+					clock-names = "ipg", "ahb", "per";
+					bus-width = <4>;
+					status = "disabled";
+				};
+
+				uart3: serial@7000c000 {
+					compatible = "fsl,imx51-uart", "fsl,imx21-uart";
+					reg = <0x7000c000 0x4000>;
+					interrupts = <33>;
+					clocks = <&clks 32>, <&clks 33>;
+					clock-names = "ipg", "per";
+					status = "disabled";
+				};
+
+				ecspi1: ecspi@70010000 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					compatible = "fsl,imx51-ecspi";
+					reg = <0x70010000 0x4000>;
+					interrupts = <36>;
+					clocks = <&clks 51>, <&clks 52>;
+					clock-names = "ipg", "per";
+					status = "disabled";
+				};
+
+				ssi2: ssi@70014000 {
+					compatible = "fsl,imx51-ssi", "fsl,imx21-ssi";
+					reg = <0x70014000 0x4000>;
+					interrupts = <30>;
+					clocks = <&clks 49>;
+					fsl,fifo-depth = <15>;
+					fsl,ssi-dma-events = <25 24 23 22>; /* TX0 RX0 TX1 RX1 */
+					status = "disabled";
+				};
+
+				esdhc3: esdhc@70020000 {
+					compatible = "fsl,imx51-esdhc";
+					reg = <0x70020000 0x4000>;
+					interrupts = <3>;
+					clocks = <&clks 46>, <&clks 0>, <&clks 73>;
+					clock-names = "ipg", "ahb", "per";
+					bus-width = <4>;
+					status = "disabled";
+				};
+
+				esdhc4: esdhc@70024000 {
+					compatible = "fsl,imx51-esdhc";
+					reg = <0x70024000 0x4000>;
+					interrupts = <4>;
+					clocks = <&clks 47>, <&clks 0>, <&clks 74>;
+					clock-names = "ipg", "ahb", "per";
+					bus-width = <4>;
+					status = "disabled";
+				};
+			};
+
+			usbotg: usb@73f80000 {
+				compatible = "fsl,imx51-usb", "fsl,imx27-usb";
+				reg = <0x73f80000 0x0200>;
+				interrupts = <18>;
+				status = "disabled";
+			};
+
+			usbh1: usb@73f80200 {
+				compatible = "fsl,imx51-usb", "fsl,imx27-usb";
+				reg = <0x73f80200 0x0200>;
+				interrupts = <14>;
+				status = "disabled";
+			};
+
+			usbh2: usb@73f80400 {
+				compatible = "fsl,imx51-usb", "fsl,imx27-usb";
+				reg = <0x73f80400 0x0200>;
+				interrupts = <16>;
+				status = "disabled";
+			};
+
+			usbh3: usb@73f80600 {
+				compatible = "fsl,imx51-usb", "fsl,imx27-usb";
+				reg = <0x73f80600 0x0200>;
+				interrupts = <17>;
+				status = "disabled";
+			};
+
+			gpio1: gpio@73f84000 {
+				compatible = "fsl,imx51-gpio", "fsl,imx35-gpio";
+				reg = <0x73f84000 0x4000>;
+				interrupts = <50 51>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+			};
+
+			gpio2: gpio@73f88000 {
+				compatible = "fsl,imx51-gpio", "fsl,imx35-gpio";
+				reg = <0x73f88000 0x4000>;
+				interrupts = <52 53>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+			};
+
+			gpio3: gpio@73f8c000 {
+				compatible = "fsl,imx51-gpio", "fsl,imx35-gpio";
+				reg = <0x73f8c000 0x4000>;
+				interrupts = <54 55>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+			};
+
+			gpio4: gpio@73f90000 {
+				compatible = "fsl,imx51-gpio", "fsl,imx35-gpio";
+				reg = <0x73f90000 0x4000>;
+				interrupts = <56 57>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+			};
+
+			kpp: kpp@73f94000 {
+				compatible = "fsl,imx51-kpp", "fsl,imx21-kpp";
+				reg = <0x73f94000 0x4000>;
+				interrupts = <60>;
+				clocks = <&clks 0>;
+				status = "disabled";
+			};
+
+			wdog1: wdog@73f98000 {
+				compatible = "fsl,imx51-wdt", "fsl,imx21-wdt";
+				reg = <0x73f98000 0x4000>;
+				interrupts = <58>;
+				clocks = <&clks 0>;
+			};
+
+			wdog2: wdog@73f9c000 {
+				compatible = "fsl,imx51-wdt", "fsl,imx21-wdt";
+				reg = <0x73f9c000 0x4000>;
+				interrupts = <59>;
+				clocks = <&clks 0>;
+				status = "disabled";
+			};
+
+			gpt: timer@73fa0000 {
+				compatible = "fsl,imx51-gpt", "fsl,imx31-gpt";
+				reg = <0x73fa0000 0x4000>;
+				interrupts = <39>;
+				clocks = <&clks 36>, <&clks 41>;
+				clock-names = "ipg", "per";
+			};
+
+			iomuxc: iomuxc@73fa8000 {
+				compatible = "fsl,imx51-iomuxc";
+				reg = <0x73fa8000 0x4000>;
+
+				audmux {
+					pinctrl_audmux_1: audmuxgrp-1 {
+						fsl,pins = <
+							MX51_PAD_AUD3_BB_TXD__AUD3_TXD 0x80000000
+							MX51_PAD_AUD3_BB_RXD__AUD3_RXD 0x80000000
+							MX51_PAD_AUD3_BB_CK__AUD3_TXC  0x80000000
+							MX51_PAD_AUD3_BB_FS__AUD3_TXFS 0x80000000
+						>;
+					};
+				};
+
+				fec {
+					pinctrl_fec_1: fecgrp-1 {
+						fsl,pins = <
+							MX51_PAD_EIM_EB2__FEC_MDIO	   0x80000000
+							MX51_PAD_EIM_EB3__FEC_RDATA1	   0x80000000
+							MX51_PAD_EIM_CS2__FEC_RDATA2	   0x80000000
+							MX51_PAD_EIM_CS3__FEC_RDATA3	   0x80000000
+							MX51_PAD_EIM_CS4__FEC_RX_ER	   0x80000000
+							MX51_PAD_EIM_CS5__FEC_CRS	   0x80000000
+							MX51_PAD_NANDF_RB2__FEC_COL	   0x80000000
+							MX51_PAD_NANDF_RB3__FEC_RX_CLK	   0x80000000
+							MX51_PAD_NANDF_D9__FEC_RDATA0	   0x80000000
+							MX51_PAD_NANDF_D8__FEC_TDATA0	   0x80000000
+							MX51_PAD_NANDF_CS2__FEC_TX_ER	   0x80000000
+							MX51_PAD_NANDF_CS3__FEC_MDC	   0x80000000
+							MX51_PAD_NANDF_CS4__FEC_TDATA1	   0x80000000
+							MX51_PAD_NANDF_CS5__FEC_TDATA2	   0x80000000
+							MX51_PAD_NANDF_CS6__FEC_TDATA3	   0x80000000
+							MX51_PAD_NANDF_CS7__FEC_TX_EN	   0x80000000
+							MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK 0x80000000
+						>;
+					};
+
+					pinctrl_fec_2: fecgrp-2 {
+						fsl,pins = <
+							MX51_PAD_DI_GP3__FEC_TX_ER	  0x80000000
+							MX51_PAD_DI2_PIN4__FEC_CRS	  0x80000000
+							MX51_PAD_DI2_PIN2__FEC_MDC	  0x80000000
+							MX51_PAD_DI2_PIN3__FEC_MDIO	  0x80000000
+							MX51_PAD_DI2_DISP_CLK__FEC_RDATA1 0x80000000
+							MX51_PAD_DI_GP4__FEC_RDATA2	  0x80000000
+							MX51_PAD_DISP2_DAT0__FEC_RDATA3   0x80000000
+							MX51_PAD_DISP2_DAT1__FEC_RX_ER	  0x80000000
+							MX51_PAD_DISP2_DAT6__FEC_TDATA1	  0x80000000
+							MX51_PAD_DISP2_DAT7__FEC_TDATA2	  0x80000000
+							MX51_PAD_DISP2_DAT8__FEC_TDATA3	  0x80000000
+							MX51_PAD_DISP2_DAT9__FEC_TX_EN	  0x80000000
+							MX51_PAD_DISP2_DAT10__FEC_COL	  0x80000000
+							MX51_PAD_DISP2_DAT11__FEC_RX_CLK  0x80000000
+							MX51_PAD_DISP2_DAT12__FEC_RX_DV	  0x80000000
+							MX51_PAD_DISP2_DAT13__FEC_TX_CLK  0x80000000
+							MX51_PAD_DISP2_DAT14__FEC_RDATA0  0x80000000
+							MX51_PAD_DISP2_DAT15__FEC_TDATA0  0x80000000
+						>;
+					};
+				};
+
+				ecspi1 {
+					pinctrl_ecspi1_1: ecspi1grp-1 {
+						fsl,pins = <
+							MX51_PAD_CSPI1_MISO__ECSPI1_MISO 0x185
+							MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI 0x185
+							MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK 0x185
+						>;
+					};
+				};
+
+				ecspi2 {
+					pinctrl_ecspi2_1: ecspi2grp-1 {
+						fsl,pins = <
+							MX51_PAD_NANDF_RB3__ECSPI2_MISO 0x185
+							MX51_PAD_NANDF_D15__ECSPI2_MOSI 0x185
+							MX51_PAD_NANDF_RB2__ECSPI2_SCLK 0x185
+						>;
+					};
+				};
+
+				esdhc1 {
+					pinctrl_esdhc1_1: esdhc1grp-1 {
+						fsl,pins = <
+							MX51_PAD_SD1_CMD__SD1_CMD     0x400020d5
+							MX51_PAD_SD1_CLK__SD1_CLK     0x20d5
+							MX51_PAD_SD1_DATA0__SD1_DATA0 0x20d5
+							MX51_PAD_SD1_DATA1__SD1_DATA1 0x20d5
+							MX51_PAD_SD1_DATA2__SD1_DATA2 0x20d5
+							MX51_PAD_SD1_DATA3__SD1_DATA3 0x20d5
+						>;
+					};
+				};
+
+				esdhc2 {
+					pinctrl_esdhc2_1: esdhc2grp-1 {
+						fsl,pins = <
+							MX51_PAD_SD2_CMD__SD2_CMD     0x400020d5
+							MX51_PAD_SD2_CLK__SD2_CLK     0x20d5
+							MX51_PAD_SD2_DATA0__SD2_DATA0 0x20d5
+							MX51_PAD_SD2_DATA1__SD2_DATA1 0x20d5
+							MX51_PAD_SD2_DATA2__SD2_DATA2 0x20d5
+							MX51_PAD_SD2_DATA3__SD2_DATA3 0x20d5
+						>;
+					};
+				};
+
+				i2c2 {
+					pinctrl_i2c2_1: i2c2grp-1 {
+						fsl,pins = <
+							MX51_PAD_KEY_COL4__I2C2_SCL 0x400001ed
+							MX51_PAD_KEY_COL5__I2C2_SDA 0x400001ed
+						>;
+					};
+
+					pinctrl_i2c2_2: i2c2grp-2 {
+						fsl,pins = <
+							MX51_PAD_EIM_D27__I2C2_SCL 0x400001ed
+							MX51_PAD_EIM_D24__I2C2_SDA 0x400001ed
+						>;
+					};
+				};
+
+				ipu_disp1 {
+					pinctrl_ipu_disp1_1: ipudisp1grp-1 {
+						fsl,pins = <
+							MX51_PAD_DISP1_DAT0__DISP1_DAT0	  0x5
+							MX51_PAD_DISP1_DAT1__DISP1_DAT1   0x5
+							MX51_PAD_DISP1_DAT2__DISP1_DAT2   0x5
+							MX51_PAD_DISP1_DAT3__DISP1_DAT3   0x5
+							MX51_PAD_DISP1_DAT4__DISP1_DAT4   0x5
+							MX51_PAD_DISP1_DAT5__DISP1_DAT5   0x5
+							MX51_PAD_DISP1_DAT6__DISP1_DAT6   0x5
+							MX51_PAD_DISP1_DAT7__DISP1_DAT7   0x5
+							MX51_PAD_DISP1_DAT8__DISP1_DAT8   0x5
+							MX51_PAD_DISP1_DAT9__DISP1_DAT9   0x5
+							MX51_PAD_DISP1_DAT10__DISP1_DAT10 0x5
+							MX51_PAD_DISP1_DAT11__DISP1_DAT11 0x5
+							MX51_PAD_DISP1_DAT12__DISP1_DAT12 0x5
+							MX51_PAD_DISP1_DAT13__DISP1_DAT13 0x5
+							MX51_PAD_DISP1_DAT14__DISP1_DAT14 0x5
+							MX51_PAD_DISP1_DAT15__DISP1_DAT15 0x5
+							MX51_PAD_DISP1_DAT16__DISP1_DAT16 0x5
+							MX51_PAD_DISP1_DAT17__DISP1_DAT17 0x5
+							MX51_PAD_DISP1_DAT18__DISP1_DAT18 0x5
+							MX51_PAD_DISP1_DAT19__DISP1_DAT19 0x5
+							MX51_PAD_DISP1_DAT20__DISP1_DAT20 0x5
+							MX51_PAD_DISP1_DAT21__DISP1_DAT21 0x5
+							MX51_PAD_DISP1_DAT22__DISP1_DAT22 0x5
+							MX51_PAD_DISP1_DAT23__DISP1_DAT23 0x5
+							MX51_PAD_DI1_PIN2__DI1_PIN2	  0x5 /* hsync */
+							MX51_PAD_DI1_PIN3__DI1_PIN3	  0x5 /* vsync */
+						>;
+					};
+				};
+
+				ipu_disp2 {
+					pinctrl_ipu_disp2_1: ipudisp2grp-1 {
+						fsl,pins = <
+							MX51_PAD_DISP2_DAT0__DISP2_DAT0     0x5
+							MX51_PAD_DISP2_DAT1__DISP2_DAT1     0x5
+							MX51_PAD_DISP2_DAT2__DISP2_DAT2     0x5
+							MX51_PAD_DISP2_DAT3__DISP2_DAT3     0x5
+							MX51_PAD_DISP2_DAT4__DISP2_DAT4     0x5
+							MX51_PAD_DISP2_DAT5__DISP2_DAT5     0x5
+							MX51_PAD_DISP2_DAT6__DISP2_DAT6     0x5
+							MX51_PAD_DISP2_DAT7__DISP2_DAT7     0x5
+							MX51_PAD_DISP2_DAT8__DISP2_DAT8     0x5
+							MX51_PAD_DISP2_DAT9__DISP2_DAT9     0x5
+							MX51_PAD_DISP2_DAT10__DISP2_DAT10   0x5
+							MX51_PAD_DISP2_DAT11__DISP2_DAT11   0x5
+							MX51_PAD_DISP2_DAT12__DISP2_DAT12   0x5
+							MX51_PAD_DISP2_DAT13__DISP2_DAT13   0x5
+							MX51_PAD_DISP2_DAT14__DISP2_DAT14   0x5
+							MX51_PAD_DISP2_DAT15__DISP2_DAT15   0x5
+							MX51_PAD_DI2_PIN2__DI2_PIN2	    0x5 /* hsync */
+							MX51_PAD_DI2_PIN3__DI2_PIN3	    0x5 /* vsync */
+							MX51_PAD_DI2_DISP_CLK__DI2_DISP_CLK 0x5
+							MX51_PAD_DI_GP4__DI2_PIN15	    0x5
+						>;
+					};
+				};
+
+				pata {
+					pinctrl_pata_1: patagrp-1 {
+						fsl,pins = <
+							MX51_PAD_NANDF_WE_B__PATA_DIOW		0x2004
+							MX51_PAD_NANDF_RE_B__PATA_DIOR		0x2004
+							MX51_PAD_NANDF_ALE__PATA_BUFFER_EN	0x2004
+							MX51_PAD_NANDF_CLE__PATA_RESET_B	0x2004
+							MX51_PAD_NANDF_WP_B__PATA_DMACK		0x2004
+							MX51_PAD_NANDF_RB0__PATA_DMARQ		0x2004
+							MX51_PAD_NANDF_RB1__PATA_IORDY		0x2004
+							MX51_PAD_GPIO_NAND__PATA_INTRQ		0x2004
+							MX51_PAD_NANDF_CS2__PATA_CS_0		0x2004
+							MX51_PAD_NANDF_CS3__PATA_CS_1		0x2004
+							MX51_PAD_NANDF_CS4__PATA_DA_0		0x2004
+							MX51_PAD_NANDF_CS5__PATA_DA_1		0x2004
+							MX51_PAD_NANDF_CS6__PATA_DA_2		0x2004
+							MX51_PAD_NANDF_D15__PATA_DATA15		0x2004
+							MX51_PAD_NANDF_D14__PATA_DATA14		0x2004
+							MX51_PAD_NANDF_D13__PATA_DATA13		0x2004
+							MX51_PAD_NANDF_D12__PATA_DATA12		0x2004
+							MX51_PAD_NANDF_D11__PATA_DATA11		0x2004
+							MX51_PAD_NANDF_D10__PATA_DATA10		0x2004
+							MX51_PAD_NANDF_D9__PATA_DATA9		0x2004
+							MX51_PAD_NANDF_D8__PATA_DATA8		0x2004
+							MX51_PAD_NANDF_D7__PATA_DATA7		0x2004
+							MX51_PAD_NANDF_D6__PATA_DATA6		0x2004
+							MX51_PAD_NANDF_D5__PATA_DATA5		0x2004
+							MX51_PAD_NANDF_D4__PATA_DATA4		0x2004
+							MX51_PAD_NANDF_D3__PATA_DATA3		0x2004
+							MX51_PAD_NANDF_D2__PATA_DATA2		0x2004
+							MX51_PAD_NANDF_D1__PATA_DATA1		0x2004
+							MX51_PAD_NANDF_D0__PATA_DATA0		0x2004
+						>;
+					};
+				};
+
+				uart1 {
+					pinctrl_uart1_1: uart1grp-1 {
+						fsl,pins = <
+							MX51_PAD_UART1_RXD__UART1_RXD 0x1c5
+							MX51_PAD_UART1_TXD__UART1_TXD 0x1c5
+							MX51_PAD_UART1_RTS__UART1_RTS 0x1c5
+							MX51_PAD_UART1_CTS__UART1_CTS 0x1c5
+						>;
+					};
+				};
+
+				uart2 {
+					pinctrl_uart2_1: uart2grp-1 {
+						fsl,pins = <
+							MX51_PAD_UART2_RXD__UART2_RXD 0x1c5
+							MX51_PAD_UART2_TXD__UART2_TXD 0x1c5
+						>;
+					};
+				};
+
+				uart3 {
+					pinctrl_uart3_1: uart3grp-1 {
+						fsl,pins = <
+							MX51_PAD_EIM_D25__UART3_RXD 0x1c5
+							MX51_PAD_EIM_D26__UART3_TXD 0x1c5
+							MX51_PAD_EIM_D27__UART3_RTS 0x1c5
+							MX51_PAD_EIM_D24__UART3_CTS 0x1c5
+						>;
+					};
+
+					pinctrl_uart3_2: uart3grp-2 {
+						fsl,pins = <
+							MX51_PAD_UART3_RXD__UART3_RXD 0x1c5
+							MX51_PAD_UART3_TXD__UART3_TXD 0x1c5
+						>;
+					};
+				};
+
+				kpp {
+					pinctrl_kpp_1: kppgrp-1 {
+						fsl,pins = <
+							MX51_PAD_KEY_ROW0__KEY_ROW0 0xe0
+							MX51_PAD_KEY_ROW1__KEY_ROW1 0xe0
+							MX51_PAD_KEY_ROW2__KEY_ROW2 0xe0
+							MX51_PAD_KEY_ROW3__KEY_ROW3 0xe0
+							MX51_PAD_KEY_COL0__KEY_COL0 0xe8
+							MX51_PAD_KEY_COL1__KEY_COL1 0xe8
+							MX51_PAD_KEY_COL2__KEY_COL2 0xe8
+							MX51_PAD_KEY_COL3__KEY_COL3 0xe8
+						>;
+					};
+				};
+			};
+
+			pwm1: pwm@73fb4000 {
+				#pwm-cells = <2>;
+				compatible = "fsl,imx51-pwm", "fsl,imx27-pwm";
+				reg = <0x73fb4000 0x4000>;
+				clocks = <&clks 37>, <&clks 38>;
+				clock-names = "ipg", "per";
+				interrupts = <61>;
+			};
+
+			pwm2: pwm@73fb8000 {
+				#pwm-cells = <2>;
+				compatible = "fsl,imx51-pwm", "fsl,imx27-pwm";
+				reg = <0x73fb8000 0x4000>;
+				clocks = <&clks 39>, <&clks 40>;
+				clock-names = "ipg", "per";
+				interrupts = <94>;
+			};
+
+			uart1: serial@73fbc000 {
+				compatible = "fsl,imx51-uart", "fsl,imx21-uart";
+				reg = <0x73fbc000 0x4000>;
+				interrupts = <31>;
+				clocks = <&clks 28>, <&clks 29>;
+				clock-names = "ipg", "per";
+				status = "disabled";
+			};
+
+			uart2: serial@73fc0000 {
+				compatible = "fsl,imx51-uart", "fsl,imx21-uart";
+				reg = <0x73fc0000 0x4000>;
+				interrupts = <32>;
+				clocks = <&clks 30>, <&clks 31>;
+				clock-names = "ipg", "per";
+				status = "disabled";
+			};
+
+			src: src@73fd0000 {
+				compatible = "fsl,imx51-src";
+				reg = <0x73fd0000 0x4000>;
+				#reset-cells = <1>;
+			};
+
+			clks: ccm@73fd4000{
+				compatible = "fsl,imx51-ccm";
+				reg = <0x73fd4000 0x4000>;
+				interrupts = <0 71 0x04 0 72 0x04>;
+				#clock-cells = <1>;
+			};
+		};
+
+		aips@80000000 {	/* AIPS2 */
+			compatible = "fsl,aips-bus", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x80000000 0x10000000>;
+			ranges;
+
+			ecspi2: ecspi@83fac000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx51-ecspi";
+				reg = <0x83fac000 0x4000>;
+				interrupts = <37>;
+				clocks = <&clks 53>, <&clks 54>;
+				clock-names = "ipg", "per";
+				status = "disabled";
+			};
+
+			sdma: sdma@83fb0000 {
+				compatible = "fsl,imx51-sdma", "fsl,imx35-sdma";
+				reg = <0x83fb0000 0x4000>;
+				interrupts = <6>;
+				clocks = <&clks 56>, <&clks 56>;
+				clock-names = "ipg", "ahb";
+				fsl,sdma-ram-script-name = "imx/sdma/sdma-imx51.bin";
+			};
+
+			cspi: cspi@83fc0000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx51-cspi", "fsl,imx35-cspi";
+				reg = <0x83fc0000 0x4000>;
+				interrupts = <38>;
+				clocks = <&clks 55>, <&clks 0>;
+				clock-names = "ipg", "per";
+				status = "disabled";
+			};
+
+			i2c2: i2c@83fc4000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx51-i2c", "fsl,imx21-i2c";
+				reg = <0x83fc4000 0x4000>;
+				interrupts = <63>;
+				clocks = <&clks 35>;
+				status = "disabled";
+			};
+
+			i2c1: i2c@83fc8000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx51-i2c", "fsl,imx21-i2c";
+				reg = <0x83fc8000 0x4000>;
+				interrupts = <62>;
+				clocks = <&clks 34>;
+				status = "disabled";
+			};
+
+			ssi1: ssi@83fcc000 {
+				compatible = "fsl,imx51-ssi", "fsl,imx21-ssi";
+				reg = <0x83fcc000 0x4000>;
+				interrupts = <29>;
+				clocks = <&clks 48>;
+				fsl,fifo-depth = <15>;
+				fsl,ssi-dma-events = <29 28 27 26>; /* TX0 RX0 TX1 RX1 */
+				status = "disabled";
+			};
+
+			audmux: audmux@83fd0000 {
+				compatible = "fsl,imx51-audmux", "fsl,imx31-audmux";
+				reg = <0x83fd0000 0x4000>;
+				status = "disabled";
+			};
+
+			nfc: nand@83fdb000 {
+				compatible = "fsl,imx51-nand";
+				reg = <0x83fdb000 0x1000 0xcfff0000 0x10000>;
+				interrupts = <8>;
+				clocks = <&clks 60>;
+				status = "disabled";
+			};
+
+			pata: pata@83fe0000 {
+				compatible = "fsl,imx51-pata", "fsl,imx27-pata";
+				reg = <0x83fe0000 0x4000>;
+				interrupts = <70>;
+				clocks = <&clks 161>;
+				status = "disabled";
+			};
+
+			ssi3: ssi@83fe8000 {
+				compatible = "fsl,imx51-ssi", "fsl,imx21-ssi";
+				reg = <0x83fe8000 0x4000>;
+				interrupts = <96>;
+				clocks = <&clks 50>;
+				fsl,fifo-depth = <15>;
+				fsl,ssi-dma-events = <47 46 37 35>; /* TX0 RX0 TX1 RX1 */
+				status = "disabled";
+			};
+
+			fec: ethernet@83fec000 {
+				compatible = "fsl,imx51-fec", "fsl,imx27-fec";
+				reg = <0x83fec000 0x4000>;
+				interrupts = <87>;
+				clocks = <&clks 42>, <&clks 42>, <&clks 42>;
+				clock-names = "ipg", "ahb", "ptp";
+				status = "disabled";
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/imx53-ard.dts b/arch/arm/boot/dts/imx53-ard.dts
deleted file mode 100644
index e049fd0..0000000
--- a/arch/arm/boot/dts/imx53-ard.dts
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright 2011 Freescale Semiconductor, Inc.
- * Copyright 2011 Linaro Ltd.
- *
- * 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
- */
-
-/dts-v1/;
-/include/ "imx53.dtsi"
-
-/ {
-	model = "Freescale i.MX53 Automotive Reference Design Board";
-	compatible = "fsl,imx53-ard", "fsl,imx53";
-
-	memory {
-		reg = <0x70000000 0x40000000>;
-	};
-
-	eim-cs1@f4000000 {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		compatible = "fsl,eim-bus", "simple-bus";
-		reg = <0xf4000000 0x3ff0000>;
-		ranges;
-
-		lan9220@f4000000 {
-			compatible = "smsc,lan9220", "smsc,lan9115";
-			reg = <0xf4000000 0x2000000>;
-			phy-mode = "mii";
-			interrupt-parent = <&gpio2>;
-			interrupts = <31 0x8>;
-			reg-io-width = <4>;
-			/*
-			 * VDD33A and VDDVARIO of LAN9220 are supplied by
-			 * SW4_3V3 of LTC3589.  Before the regulator driver
-			 * for this PMIC is available, we use a fixed dummy
-			 * 3V3 regulator to get LAN9220 driver probing work.
-			 */
-			vdd33a-supply = <&reg_3p3v>;
-			vddvario-supply = <&reg_3p3v>;
-			smsc,irq-push-pull;
-		};
-	};
-
-	regulators {
-		compatible = "simple-bus";
-
-		reg_3p3v: 3p3v {
-			compatible = "regulator-fixed";
-			regulator-name = "3P3V";
-			regulator-min-microvolt = <3300000>;
-			regulator-max-microvolt = <3300000>;
-			regulator-always-on;
-		};
-	};
-
-	gpio-keys {
-		compatible = "gpio-keys";
-
-		home {
-			label = "Home";
-			gpios = <&gpio5 10 0>;
-			linux,code = <102>; /* KEY_HOME */
-			gpio-key,wakeup;
-		};
-
-		back {
-			label = "Back";
-			gpios = <&gpio5 11 0>;
-			linux,code = <158>; /* KEY_BACK */
-			gpio-key,wakeup;
-		};
-
-		program {
-			label = "Program";
-			gpios = <&gpio5 12 0>;
-			linux,code = <362>; /* KEY_PROGRAM */
-			gpio-key,wakeup;
-		};
-
-		volume-up {
-			label = "Volume Up";
-			gpios = <&gpio5 13 0>;
-			linux,code = <115>; /* KEY_VOLUMEUP */
-		};
-
-		volume-down {
-			label = "Volume Down";
-			gpios = <&gpio4 0 0>;
-			linux,code = <114>; /* KEY_VOLUMEDOWN */
-		};
-	};
-};
-
-&esdhc1 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_esdhc1_2>;
-	cd-gpios = <&gpio1 1 0>;
-	wp-gpios = <&gpio1 9 0>;
-	status = "okay";
-};
-
-&iomuxc {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_hog>;
-
-	hog {
-		pinctrl_hog: hoggrp {
-			fsl,pins = <
-				1077 0x80000000	/* MX53_PAD_GPIO_1__GPIO1_1 */
-				1085 0x80000000	/* MX53_PAD_GPIO_9__GPIO1_9 */
-				486  0x80000000	/* MX53_PAD_EIM_EB3__GPIO2_31 */
-				739  0x80000000	/* MX53_PAD_GPIO_10__GPIO4_0 */
-				218  0x80000000	/* MX53_PAD_DISP0_DAT16__GPIO5_10 */
-				226  0x80000000	/* MX53_PAD_DISP0_DAT17__GPIO5_11 */
-				233  0x80000000	/* MX53_PAD_DISP0_DAT18__GPIO5_12 */
-				241  0x80000000	/* MX53_PAD_DISP0_DAT19__GPIO5_13 */
-				429  0x80000000	/* MX53_PAD_EIM_D16__EMI_WEIM_D_16 */
-				435  0x80000000	/* MX53_PAD_EIM_D17__EMI_WEIM_D_17 */
-				441  0x80000000	/* MX53_PAD_EIM_D18__EMI_WEIM_D_18 */
-				448  0x80000000	/* MX53_PAD_EIM_D19__EMI_WEIM_D_19 */
-				456  0x80000000	/* MX53_PAD_EIM_D20__EMI_WEIM_D_20 */
-				464  0x80000000	/* MX53_PAD_EIM_D21__EMI_WEIM_D_21 */
-				471  0x80000000	/* MX53_PAD_EIM_D22__EMI_WEIM_D_22 */
-				477  0x80000000	/* MX53_PAD_EIM_D23__EMI_WEIM_D_23 */
-				492  0x80000000	/* MX53_PAD_EIM_D24__EMI_WEIM_D_24 */
-				500  0x80000000	/* MX53_PAD_EIM_D25__EMI_WEIM_D_25 */
-				508  0x80000000	/* MX53_PAD_EIM_D26__EMI_WEIM_D_26 */
-				516  0x80000000	/* MX53_PAD_EIM_D27__EMI_WEIM_D_27 */
-				524  0x80000000	/* MX53_PAD_EIM_D28__EMI_WEIM_D_28 */
-				532  0x80000000	/* MX53_PAD_EIM_D29__EMI_WEIM_D_29 */
-				540  0x80000000	/* MX53_PAD_EIM_D30__EMI_WEIM_D_30 */
-				548  0x80000000	/* MX53_PAD_EIM_D31__EMI_WEIM_D_31 */
-				637  0x80000000	/* MX53_PAD_EIM_DA0__EMI_NAND_WEIM_DA_0 */
-				642  0x80000000	/* MX53_PAD_EIM_DA1__EMI_NAND_WEIM_DA_1 */
-				647  0x80000000	/* MX53_PAD_EIM_DA2__EMI_NAND_WEIM_DA_2 */
-				652  0x80000000	/* MX53_PAD_EIM_DA3__EMI_NAND_WEIM_DA_3 */
-				657  0x80000000	/* MX53_PAD_EIM_DA4__EMI_NAND_WEIM_DA_4 */
-				662  0x80000000	/* MX53_PAD_EIM_DA5__EMI_NAND_WEIM_DA_5 */
-				667  0x80000000	/* MX53_PAD_EIM_DA6__EMI_NAND_WEIM_DA_6 */
-				611  0x80000000	/* MX53_PAD_EIM_OE__EMI_WEIM_OE */
-				616  0x80000000	/* MX53_PAD_EIM_RW__EMI_WEIM_RW */
-				607  0x80000000	/* MX53_PAD_EIM_CS1__EMI_WEIM_CS_1 */
-			>;
-		};
-	};
-};
-
-&uart1 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart1_2>;
-	status = "okay";
-};
diff --git a/arch/arm/boot/dts/imx53-ard.dtsp b/arch/arm/boot/dts/imx53-ard.dtsp
new file mode 100644
index 0000000..2ff8e54
--- /dev/null
+++ b/arch/arm/boot/dts/imx53-ard.dtsp
@@ -0,0 +1,158 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * 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
+ */
+
+/dts-v1/;
+#include "imx53.dtsip"
+
+/ {
+	model = "Freescale i.MX53 Automotive Reference Design Board";
+	compatible = "fsl,imx53-ard", "fsl,imx53";
+
+	memory {
+		reg = <0x70000000 0x40000000>;
+	};
+
+	eim-cs1@f4000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "fsl,eim-bus", "simple-bus";
+		reg = <0xf4000000 0x3ff0000>;
+		ranges;
+
+		lan9220@f4000000 {
+			compatible = "smsc,lan9220", "smsc,lan9115";
+			reg = <0xf4000000 0x2000000>;
+			phy-mode = "mii";
+			interrupt-parent = <&gpio2>;
+			interrupts = <31 0x8>;
+			reg-io-width = <4>;
+			/*
+			 * VDD33A and VDDVARIO of LAN9220 are supplied by
+			 * SW4_3V3 of LTC3589.  Before the regulator driver
+			 * for this PMIC is available, we use a fixed dummy
+			 * 3V3 regulator to get LAN9220 driver probing work.
+			 */
+			vdd33a-supply = <&reg_3p3v>;
+			vddvario-supply = <&reg_3p3v>;
+			smsc,irq-push-pull;
+		};
+	};
+
+	regulators {
+		compatible = "simple-bus";
+
+		reg_3p3v: 3p3v {
+			compatible = "regulator-fixed";
+			regulator-name = "3P3V";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		home {
+			label = "Home";
+			gpios = <&gpio5 10 0>;
+			linux,code = <102>; /* KEY_HOME */
+			gpio-key,wakeup;
+		};
+
+		back {
+			label = "Back";
+			gpios = <&gpio5 11 0>;
+			linux,code = <158>; /* KEY_BACK */
+			gpio-key,wakeup;
+		};
+
+		program {
+			label = "Program";
+			gpios = <&gpio5 12 0>;
+			linux,code = <362>; /* KEY_PROGRAM */
+			gpio-key,wakeup;
+		};
+
+		volume-up {
+			label = "Volume Up";
+			gpios = <&gpio5 13 0>;
+			linux,code = <115>; /* KEY_VOLUMEUP */
+		};
+
+		volume-down {
+			label = "Volume Down";
+			gpios = <&gpio4 0 0>;
+			linux,code = <114>; /* KEY_VOLUMEDOWN */
+		};
+	};
+};
+
+&esdhc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_esdhc1_2>;
+	cd-gpios = <&gpio1 1 0>;
+	wp-gpios = <&gpio1 9 0>;
+	status = "okay";
+};
+
+&iomuxc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hog>;
+
+	hog {
+		pinctrl_hog: hoggrp {
+			fsl,pins = <
+				MX53_PAD_GPIO_1__GPIO1_1             0x80000000
+				MX53_PAD_GPIO_9__GPIO1_9             0x80000000
+				MX53_PAD_EIM_EB3__GPIO2_31           0x80000000
+				MX53_PAD_GPIO_10__GPIO4_0            0x80000000
+				MX53_PAD_DISP0_DAT16__GPIO5_10	     0x80000000
+				MX53_PAD_DISP0_DAT17__GPIO5_11       0x80000000
+				MX53_PAD_DISP0_DAT18__GPIO5_12       0x80000000
+				MX53_PAD_DISP0_DAT19__GPIO5_13       0x80000000
+				MX53_PAD_EIM_D16__EMI_WEIM_D_16      0x80000000
+				MX53_PAD_EIM_D17__EMI_WEIM_D_17      0x80000000
+				MX53_PAD_EIM_D18__EMI_WEIM_D_18      0x80000000
+				MX53_PAD_EIM_D19__EMI_WEIM_D_19      0x80000000
+				MX53_PAD_EIM_D20__EMI_WEIM_D_20      0x80000000
+				MX53_PAD_EIM_D21__EMI_WEIM_D_21      0x80000000
+				MX53_PAD_EIM_D22__EMI_WEIM_D_22      0x80000000
+				MX53_PAD_EIM_D23__EMI_WEIM_D_23      0x80000000
+				MX53_PAD_EIM_D24__EMI_WEIM_D_24      0x80000000
+				MX53_PAD_EIM_D25__EMI_WEIM_D_25      0x80000000
+				MX53_PAD_EIM_D26__EMI_WEIM_D_26      0x80000000
+				MX53_PAD_EIM_D27__EMI_WEIM_D_27      0x80000000
+				MX53_PAD_EIM_D28__EMI_WEIM_D_28      0x80000000
+				MX53_PAD_EIM_D29__EMI_WEIM_D_29      0x80000000
+				MX53_PAD_EIM_D30__EMI_WEIM_D_30      0x80000000
+				MX53_PAD_EIM_D31__EMI_WEIM_D_31      0x80000000
+				MX53_PAD_EIM_DA0__EMI_NAND_WEIM_DA_0 0x80000000
+				MX53_PAD_EIM_DA1__EMI_NAND_WEIM_DA_1 0x80000000
+				MX53_PAD_EIM_DA2__EMI_NAND_WEIM_DA_2 0x80000000
+				MX53_PAD_EIM_DA3__EMI_NAND_WEIM_DA_3 0x80000000
+				MX53_PAD_EIM_DA4__EMI_NAND_WEIM_DA_4 0x80000000
+				MX53_PAD_EIM_DA5__EMI_NAND_WEIM_DA_5 0x80000000
+				MX53_PAD_EIM_DA6__EMI_NAND_WEIM_DA_6 0x80000000
+				MX53_PAD_EIM_OE__EMI_WEIM_OE	     0x80000000
+				MX53_PAD_EIM_RW__EMI_WEIM_RW	     0x80000000
+				MX53_PAD_EIM_CS1__EMI_WEIM_CS_1	     0x80000000
+			>;
+		};
+	};
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1_2>;
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx53-evk.dts b/arch/arm/boot/dts/imx53-evk.dts
deleted file mode 100644
index 85a89b5..0000000
--- a/arch/arm/boot/dts/imx53-evk.dts
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright 2011 Freescale Semiconductor, Inc.
- * Copyright 2011 Linaro Ltd.
- *
- * 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
- */
-
-/dts-v1/;
-/include/ "imx53.dtsi"
-
-/ {
-	model = "Freescale i.MX53 Evaluation Kit";
-	compatible = "fsl,imx53-evk", "fsl,imx53";
-
-	memory {
-		reg = <0x70000000 0x80000000>;
-	};
-
-	leds {
-		compatible = "gpio-leds";
-
-		green {
-			label = "Heartbeat";
-			gpios = <&gpio7 7 0>;
-			linux,default-trigger = "heartbeat";
-		};
-	};
-};
-
-&esdhc1 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_esdhc1_1>;
-	cd-gpios = <&gpio3 13 0>;
-	wp-gpios = <&gpio3 14 0>;
-	status = "okay";
-};
-
-&ecspi1 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_ecspi1_1>;
-	fsl,spi-num-chipselects = <2>;
-	cs-gpios = <&gpio2 30 0>, <&gpio3 19 0>;
-	status = "okay";
-
-	flash: at45db321d@1 {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		compatible = "atmel,at45db321d", "atmel,at45", "atmel,dataflash";
-		spi-max-frequency = <25000000>;
-		reg = <1>;
-
-		partition@0 {
-			label = "U-Boot";
-			reg = <0x0 0x40000>;
-			read-only;
-		};
-
-		partition@40000 {
-			label = "Kernel";
-			reg = <0x40000 0x3c0000>;
-		};
-	};
-};
-
-&esdhc3 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_esdhc3_1>;
-	cd-gpios = <&gpio3 11 0>;
-	wp-gpios = <&gpio3 12 0>;
-	status = "okay";
-};
-
-&iomuxc {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_hog>;
-
-	hog {
-		pinctrl_hog: hoggrp {
-			fsl,pins = <
-				424  0x80000000	/* MX53_PAD_EIM_EB2__GPIO2_30 */
-				449  0x80000000	/* MX53_PAD_EIM_D19__GPIO3_19 */
-				693  0x80000000	/* MX53_PAD_EIM_DA11__GPIO3_11 */
-				697  0x80000000	/* MX53_PAD_EIM_DA12__GPIO3_12 */
-				701  0x80000000	/* MX53_PAD_EIM_DA13__GPIO3_13 */
-				705  0x80000000	/* MX53_PAD_EIM_DA14__GPIO3_14 */
-				868  0x80000000	/* MX53_PAD_PATA_DA_0__GPIO7_6 */
-				873  0x80000000	/* MX53_PAD_PATA_DA_1__GPIO7_7 */
-			>;
-		};
-	};
-};
-
-&uart1 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart1_1>;
-	status = "okay";
-};
-
-&i2c2 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_i2c2_1>;
-	status = "okay";
-
-	pmic: mc13892@08 {
-		compatible = "fsl,mc13892", "fsl,mc13xxx";
-		reg = <0x08>;
-	};
-
-	codec: sgtl5000@0a {
-		compatible = "fsl,sgtl5000";
-		reg = <0x0a>;
-	};
-};
-
-&fec {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_fec_1>;
-	phy-mode = "rmii";
-	phy-reset-gpios = <&gpio7 6 0>;
-	status = "okay";
-};
diff --git a/arch/arm/boot/dts/imx53-evk.dtsp b/arch/arm/boot/dts/imx53-evk.dtsp
new file mode 100644
index 0000000..d1952f5
--- /dev/null
+++ b/arch/arm/boot/dts/imx53-evk.dtsp
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * 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
+ */
+
+/dts-v1/;
+#include "imx53.dtsip"
+
+/ {
+	model = "Freescale i.MX53 Evaluation Kit";
+	compatible = "fsl,imx53-evk", "fsl,imx53";
+
+	memory {
+		reg = <0x70000000 0x80000000>;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		green {
+			label = "Heartbeat";
+			gpios = <&gpio7 7 0>;
+			linux,default-trigger = "heartbeat";
+		};
+	};
+};
+
+&esdhc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_esdhc1_1>;
+	cd-gpios = <&gpio3 13 0>;
+	wp-gpios = <&gpio3 14 0>;
+	status = "okay";
+};
+
+&ecspi1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ecspi1_1>;
+	fsl,spi-num-chipselects = <2>;
+	cs-gpios = <&gpio2 30 0>, <&gpio3 19 0>;
+	status = "okay";
+
+	flash: at45db321d@1 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "atmel,at45db321d", "atmel,at45", "atmel,dataflash";
+		spi-max-frequency = <25000000>;
+		reg = <1>;
+
+		partition@0 {
+			label = "U-Boot";
+			reg = <0x0 0x40000>;
+			read-only;
+		};
+
+		partition@40000 {
+			label = "Kernel";
+			reg = <0x40000 0x3c0000>;
+		};
+	};
+};
+
+&esdhc3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_esdhc3_1>;
+	cd-gpios = <&gpio3 11 0>;
+	wp-gpios = <&gpio3 12 0>;
+	status = "okay";
+};
+
+&iomuxc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hog>;
+
+	hog {
+		pinctrl_hog: hoggrp {
+			fsl,pins = <
+				MX53_PAD_EIM_EB2__GPIO2_30  0x80000000
+				MX53_PAD_EIM_D19__GPIO3_19  0x80000000
+				MX53_PAD_EIM_DA11__GPIO3_11 0x80000000
+				MX53_PAD_EIM_DA12__GPIO3_12 0x80000000
+				MX53_PAD_EIM_DA13__GPIO3_13 0x80000000
+				MX53_PAD_EIM_DA14__GPIO3_14 0x80000000
+				MX53_PAD_PATA_DA_0__GPIO7_6 0x80000000
+				MX53_PAD_PATA_DA_1__GPIO7_7 0x80000000
+			>;
+		};
+	};
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1_1>;
+	status = "okay";
+};
+
+&i2c2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2_1>;
+	status = "okay";
+
+	pmic: mc13892@08 {
+		compatible = "fsl,mc13892", "fsl,mc13xxx";
+		reg = <0x08>;
+	};
+
+	codec: sgtl5000@0a {
+		compatible = "fsl,sgtl5000";
+		reg = <0x0a>;
+	};
+};
+
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_fec_1>;
+	phy-mode = "rmii";
+	phy-reset-gpios = <&gpio7 6 0>;
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx53-mba53.dts b/arch/arm/boot/dts/imx53-mba53.dts
deleted file mode 100644
index 468c0a1..0000000
--- a/arch/arm/boot/dts/imx53-mba53.dts
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright 2012 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
- * Copyright 2012 Steffen Trumtrar <s.trumtrar@pengutronix.de>, Pengutronix
- *
- * 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
- */
-
-/dts-v1/;
-/include/ "imx53-tqma53.dtsi"
-
-/ {
-	model = "TQ MBa53 starter kit";
-	compatible = "tq,mba53", "tq,tqma53", "fsl,imx53";
-};
-
-&iomuxc {
-	lvds1 {
-		pinctrl_lvds1_1: lvds1-grp1 {
-			fsl,pins = <730 0x10000		/* LVDS0_TX3 */
-				    732 0x10000		/* LVDS0_CLK */
-				    734 0x10000		/* LVDS0_TX2 */
-				    736 0x10000		/* LVDS0_TX1 */
-				    738 0x10000>;	/* LVDS0_TX0 */
-		};
-
-		pinctrl_lvds1_2: lvds1-grp2 {
-			fsl,pins = <720 0x10000		/* LVDS1_TX3 */
-				    722 0x10000		/* LVDS1_TX2 */
-				    724 0x10000		/* LVDS1_CLK */
-				    726 0x10000		/* LVDS1_TX1 */
-				    728 0x10000>;	/* LVDS1_TX0 */
-		};
-	};
-
-	disp1 {
-		pinctrl_disp1_1: disp1-grp1 {
-			fsl,pins = <689 0x10000		/* DISP1_DRDY	*/
-				    482 0x10000		/* DISP1_HSYNC	*/
-				    489 0x10000		/* DISP1_VSYNC	*/
-				    515 0x10000		/* DISP1_DAT_22	*/
-				    523 0x10000		/* DISP1_DAT_23	*/
-				    545 0x10000		/* DISP1_DAT_21	*/
-				    553 0x10000		/* DISP1_DAT_20	*/
-				    558 0x10000		/* DISP1_DAT_19	*/
-				    564 0x10000		/* DISP1_DAT_18	*/
-				    570 0x10000		/* DISP1_DAT_17	*/
-				    575 0x10000		/* DISP1_DAT_16	*/
-				    580 0x10000		/* DISP1_DAT_15	*/
-				    585 0x10000		/* DISP1_DAT_14	*/
-				    590 0x10000		/* DISP1_DAT_13	*/
-				    595 0x10000		/* DISP1_DAT_12	*/
-				    628 0x10000		/* DISP1_DAT_11	*/
-				    634 0x10000		/* DISP1_DAT_10	*/
-				    639 0x10000		/* DISP1_DAT_9	*/
-				    644 0x10000		/* DISP1_DAT_8	*/
-				    649 0x10000		/* DISP1_DAT_7	*/
-				    654 0x10000		/* DISP1_DAT_6	*/
-				    659 0x10000		/* DISP1_DAT_5	*/
-				    664 0x10000		/* DISP1_DAT_4	*/
-				    669 0x10000		/* DISP1_DAT_3	*/
-				    674 0x10000		/* DISP1_DAT_2	*/
-				    679 0x10000		/* DISP1_DAT_1	*/
-				    684 0x10000>;	/* DISP1_DAT_0	*/
-		};
-	};
-};
-
-&cspi {
-	status = "okay";
-};
-
-&i2c2 {
-	codec: sgtl5000@a {
-		compatible = "fsl,sgtl5000";
-		reg = <0x0a>;
-	};
-
-	expander: pca9554@20 {
-		compatible = "pca9554";
-		reg = <0x20>;
-		interrupts = <109>;
-	};
-
-	sensor2: lm75@49 {
-		compatible = "lm75";
-		reg = <0x49>;
-	};
-};
-
-&fec {
-	status = "okay";
-};
-
-&esdhc2 {
-	status = "okay";
-};
-
-&uart3 {
-	status = "okay";
-};
-
-&ecspi1 {
-	status = "okay";
-};
-
-&uart1 {
-	status = "okay";
-};
-
-&uart2 {
-	status = "okay";
-};
-
-&can1 {
-	status = "okay";
-};
-
-&can2 {
-	status = "okay";
-};
-
-&i2c3 {
-	status = "okay";
-};
diff --git a/arch/arm/boot/dts/imx53-mba53.dtsp b/arch/arm/boot/dts/imx53-mba53.dtsp
new file mode 100644
index 0000000..6bfe92c
--- /dev/null
+++ b/arch/arm/boot/dts/imx53-mba53.dtsp
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2012 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ * Copyright 2012 Steffen Trumtrar <s.trumtrar@pengutronix.de>, Pengutronix
+ *
+ * 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
+ */
+
+/dts-v1/;
+#include "imx53-tqma53.dtsip"
+
+/ {
+	model = "TQ MBa53 starter kit";
+	compatible = "tq,mba53", "tq,tqma53", "fsl,imx53";
+};
+
+&iomuxc {
+	lvds1 {
+		pinctrl_lvds1_1: lvds1-grp1 {
+			fsl,pins = <
+				MX53_PAD_LVDS0_TX3_P__LDB_LVDS0_TX3 0x10000
+				MX53_PAD_LVDS0_CLK_P__LDB_LVDS0_CLK 0x10000
+				MX53_PAD_LVDS0_TX2_P__LDB_LVDS0_TX2 0x10000
+				MX53_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1 0x10000
+				MX53_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0 0x10000
+			>;
+		};
+
+		pinctrl_lvds1_2: lvds1-grp2 {
+			fsl,pins = <
+				MX53_PAD_LVDS1_TX3_P__LDB_LVDS1_TX3 0x10000
+				MX53_PAD_LVDS1_TX2_P__LDB_LVDS1_TX2 0x10000
+				MX53_PAD_LVDS1_CLK_P__LDB_LVDS1_CLK 0x10000
+				MX53_PAD_LVDS1_TX1_P__LDB_LVDS1_TX1 0x10000
+				MX53_PAD_LVDS1_TX0_P__LDB_LVDS1_TX0 0x10000
+			>;
+		};
+	};
+
+	disp1 {
+		pinctrl_disp1_1: disp1-grp1 {
+			fsl,pins = <
+				MX53_PAD_EIM_DA10__IPU_DI1_PIN15   0x10000 /* DISP1_DRDY */
+				MX53_PAD_EIM_D23__IPU_DI1_PIN2     0x10000 /* DISP1_HSYNC */
+				MX53_PAD_EIM_EB3__IPU_DI1_PIN3     0x10000 /* DISP1_VSYNC */
+				MX53_PAD_EIM_D26__IPU_DISP1_DAT_22 0x10000
+				MX53_PAD_EIM_D27__IPU_DISP1_DAT_23 0x10000
+				MX53_PAD_EIM_D30__IPU_DISP1_DAT_21 0x10000
+				MX53_PAD_EIM_D31__IPU_DISP1_DAT_20 0x10000
+				MX53_PAD_EIM_A24__IPU_DISP1_DAT_19 0x10000
+				MX53_PAD_EIM_A23__IPU_DISP1_DAT_18 0x10000
+				MX53_PAD_EIM_A22__IPU_DISP1_DAT_17 0x10000
+				MX53_PAD_EIM_A21__IPU_DISP1_DAT_16 0x10000
+				MX53_PAD_EIM_A20__IPU_DISP1_DAT_15 0x10000
+				MX53_PAD_EIM_A19__IPU_DISP1_DAT_14 0x10000
+				MX53_PAD_EIM_A18__IPU_DISP1_DAT_13 0x10000
+				MX53_PAD_EIM_A17__IPU_DISP1_DAT_12 0x10000
+				MX53_PAD_EIM_EB0__IPU_DISP1_DAT_11 0x10000
+				MX53_PAD_EIM_EB1__IPU_DISP1_DAT_10 0x10000
+				MX53_PAD_EIM_DA0__IPU_DISP1_DAT_9  0x10000
+				MX53_PAD_EIM_DA1__IPU_DISP1_DAT_8  0x10000
+				MX53_PAD_EIM_DA2__IPU_DISP1_DAT_7  0x10000
+				MX53_PAD_EIM_DA3__IPU_DISP1_DAT_6  0x10000
+				MX53_PAD_EIM_DA4__IPU_DISP1_DAT_5  0x10000
+				MX53_PAD_EIM_DA5__IPU_DISP1_DAT_4  0x10000
+				MX53_PAD_EIM_DA6__IPU_DISP1_DAT_3  0x10000
+				MX53_PAD_EIM_DA7__IPU_DISP1_DAT_2  0x10000
+				MX53_PAD_EIM_DA8__IPU_DISP1_DAT_1  0x10000
+				MX53_PAD_EIM_DA9__IPU_DISP1_DAT_0  0x10000
+			>;
+		};
+	};
+};
+
+&cspi {
+	status = "okay";
+};
+
+&i2c2 {
+	codec: sgtl5000@a {
+		compatible = "fsl,sgtl5000";
+		reg = <0x0a>;
+	};
+
+	expander: pca9554@20 {
+		compatible = "pca9554";
+		reg = <0x20>;
+		interrupts = <109>;
+	};
+
+	sensor2: lm75@49 {
+		compatible = "lm75";
+		reg = <0x49>;
+	};
+};
+
+&fec {
+	status = "okay";
+};
+
+&esdhc2 {
+	status = "okay";
+};
+
+&uart3 {
+	status = "okay";
+};
+
+&ecspi1 {
+	status = "okay";
+};
+
+&uart1 {
+	status = "okay";
+};
+
+&uart2 {
+	status = "okay";
+};
+
+&can1 {
+	status = "okay";
+};
+
+&can2 {
+	status = "okay";
+};
+
+&i2c3 {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx53-pinfunc.h b/arch/arm/boot/dts/imx53-pinfunc.h
new file mode 100644
index 0000000..aec406b
--- /dev/null
+++ b/arch/arm/boot/dts/imx53-pinfunc.h
@@ -0,0 +1,1189 @@
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef __DTS_IMX53_PINFUNC_H
+#define __DTS_IMX53_PINFUNC_H
+
+/*
+ * The pin function ID is a tuple of
+ * <mux_reg conf_reg input_reg mux_mode input_val>
+ */
+#define MX53_PAD_GPIO_19__KPP_COL_5				0x020 0x348 0x840 0x0 0x0
+#define MX53_PAD_GPIO_19__GPIO4_5				0x020 0x348 0x000 0x1 0x0
+#define MX53_PAD_GPIO_19__CCM_CLKO				0x020 0x348 0x000 0x2 0x0
+#define MX53_PAD_GPIO_19__SPDIF_OUT1				0x020 0x348 0x000 0x3 0x0
+#define MX53_PAD_GPIO_19__RTC_CE_RTC_EXT_TRIG2			0x020 0x348 0x000 0x4 0x0
+#define MX53_PAD_GPIO_19__ECSPI1_RDY				0x020 0x348 0x000 0x5 0x0
+#define MX53_PAD_GPIO_19__FEC_TDATA_3				0x020 0x348 0x000 0x6 0x0
+#define MX53_PAD_GPIO_19__SRC_INT_BOOT				0x020 0x348 0x000 0x7 0x0
+#define MX53_PAD_KEY_COL0__KPP_COL_0				0x024 0x34c 0x000 0x0 0x0
+#define MX53_PAD_KEY_COL0__GPIO4_6				0x024 0x34c 0x000 0x1 0x0
+#define MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC			0x024 0x34c 0x758 0x2 0x0
+#define MX53_PAD_KEY_COL0__UART4_TXD_MUX			0x024 0x34c 0x000 0x4 0x0
+#define MX53_PAD_KEY_COL0__ECSPI1_SCLK				0x024 0x34c 0x79c 0x5 0x0
+#define MX53_PAD_KEY_COL0__FEC_RDATA_3				0x024 0x34c 0x000 0x6 0x0
+#define MX53_PAD_KEY_COL0__SRC_ANY_PU_RST			0x024 0x34c 0x000 0x7 0x0
+#define MX53_PAD_KEY_ROW0__KPP_ROW_0				0x028 0x350 0x000 0x0 0x0
+#define MX53_PAD_KEY_ROW0__GPIO4_7				0x028 0x350 0x000 0x1 0x0
+#define MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD			0x028 0x350 0x74c 0x2 0x0
+#define MX53_PAD_KEY_ROW0__UART4_RXD_MUX			0x028 0x350 0x890 0x4 0x1
+#define MX53_PAD_KEY_ROW0__ECSPI1_MOSI				0x028 0x350 0x7a4 0x5 0x0
+#define MX53_PAD_KEY_ROW0__FEC_TX_ER				0x028 0x350 0x000 0x6 0x0
+#define MX53_PAD_KEY_COL1__KPP_COL_1				0x02c 0x354 0x000 0x0 0x0
+#define MX53_PAD_KEY_COL1__GPIO4_8				0x02c 0x354 0x000 0x1 0x0
+#define MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS			0x02c 0x354 0x75c 0x2 0x0
+#define MX53_PAD_KEY_COL1__UART5_TXD_MUX			0x02c 0x354 0x000 0x4 0x0
+#define MX53_PAD_KEY_COL1__ECSPI1_MISO				0x02c 0x354 0x7a0 0x5 0x0
+#define MX53_PAD_KEY_COL1__FEC_RX_CLK				0x02c 0x354 0x808 0x6 0x0
+#define MX53_PAD_KEY_COL1__USBPHY1_TXREADY			0x02c 0x354 0x000 0x7 0x0
+#define MX53_PAD_KEY_ROW1__KPP_ROW_1				0x030 0x358 0x000 0x0 0x0
+#define MX53_PAD_KEY_ROW1__GPIO4_9				0x030 0x358 0x000 0x1 0x0
+#define MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD			0x030 0x358 0x748 0x2 0x0
+#define MX53_PAD_KEY_ROW1__UART5_RXD_MUX			0x030 0x358 0x898 0x4 0x1
+#define MX53_PAD_KEY_ROW1__ECSPI1_SS0				0x030 0x358 0x7a8 0x5 0x0
+#define MX53_PAD_KEY_ROW1__FEC_COL				0x030 0x358 0x800 0x6 0x0
+#define MX53_PAD_KEY_ROW1__USBPHY1_RXVALID			0x030 0x358 0x000 0x7 0x0
+#define MX53_PAD_KEY_COL2__KPP_COL_2				0x034 0x35c 0x000 0x0 0x0
+#define MX53_PAD_KEY_COL2__GPIO4_10				0x034 0x35c 0x000 0x1 0x0
+#define MX53_PAD_KEY_COL2__CAN1_TXCAN				0x034 0x35c 0x000 0x2 0x0
+#define MX53_PAD_KEY_COL2__FEC_MDIO				0x034 0x35c 0x804 0x4 0x0
+#define MX53_PAD_KEY_COL2__ECSPI1_SS1				0x034 0x35c 0x7ac 0x5 0x0
+#define MX53_PAD_KEY_COL2__FEC_RDATA_2				0x034 0x35c 0x000 0x6 0x0
+#define MX53_PAD_KEY_COL2__USBPHY1_RXACTIVE			0x034 0x35c 0x000 0x7 0x0
+#define MX53_PAD_KEY_ROW2__KPP_ROW_2				0x038 0x360 0x000 0x0 0x0
+#define MX53_PAD_KEY_ROW2__GPIO4_11				0x038 0x360 0x000 0x1 0x0
+#define MX53_PAD_KEY_ROW2__CAN1_RXCAN				0x038 0x360 0x760 0x2 0x0
+#define MX53_PAD_KEY_ROW2__FEC_MDC				0x038 0x360 0x000 0x4 0x0
+#define MX53_PAD_KEY_ROW2__ECSPI1_SS2				0x038 0x360 0x7b0 0x5 0x0
+#define MX53_PAD_KEY_ROW2__FEC_TDATA_2				0x038 0x360 0x000 0x6 0x0
+#define MX53_PAD_KEY_ROW2__USBPHY1_RXERROR			0x038 0x360 0x000 0x7 0x0
+#define MX53_PAD_KEY_COL3__KPP_COL_3				0x03c 0x364 0x000 0x0 0x0
+#define MX53_PAD_KEY_COL3__GPIO4_12				0x03c 0x364 0x000 0x1 0x0
+#define MX53_PAD_KEY_COL3__USBOH3_H2_DP				0x03c 0x364 0x000 0x2 0x0
+#define MX53_PAD_KEY_COL3__SPDIF_IN1				0x03c 0x364 0x870 0x3 0x0
+#define MX53_PAD_KEY_COL3__I2C2_SCL				0x03c 0x364 0x81c 0x4 0x0
+#define MX53_PAD_KEY_COL3__ECSPI1_SS3				0x03c 0x364 0x7b4 0x5 0x0
+#define MX53_PAD_KEY_COL3__FEC_CRS				0x03c 0x364 0x000 0x6 0x0
+#define MX53_PAD_KEY_COL3__USBPHY1_SIECLOCK			0x03c 0x364 0x000 0x7 0x0
+#define MX53_PAD_KEY_ROW3__KPP_ROW_3				0x040 0x368 0x000 0x0 0x0
+#define MX53_PAD_KEY_ROW3__GPIO4_13				0x040 0x368 0x000 0x1 0x0
+#define MX53_PAD_KEY_ROW3__USBOH3_H2_DM				0x040 0x368 0x000 0x2 0x0
+#define MX53_PAD_KEY_ROW3__CCM_ASRC_EXT_CLK			0x040 0x368 0x768 0x3 0x0
+#define MX53_PAD_KEY_ROW3__I2C2_SDA				0x040 0x368 0x820 0x4 0x0
+#define MX53_PAD_KEY_ROW3__OSC32K_32K_OUT			0x040 0x368 0x000 0x5 0x0
+#define MX53_PAD_KEY_ROW3__CCM_PLL4_BYP				0x040 0x368 0x77c 0x6 0x0
+#define MX53_PAD_KEY_ROW3__USBPHY1_LINESTATE_0			0x040 0x368 0x000 0x7 0x0
+#define MX53_PAD_KEY_COL4__KPP_COL_4				0x044 0x36c 0x000 0x0 0x0
+#define MX53_PAD_KEY_COL4__GPIO4_14				0x044 0x36c 0x000 0x1 0x0
+#define MX53_PAD_KEY_COL4__CAN2_TXCAN				0x044 0x36c 0x000 0x2 0x0
+#define MX53_PAD_KEY_COL4__IPU_SISG_4				0x044 0x36c 0x000 0x3 0x0
+#define MX53_PAD_KEY_COL4__UART5_RTS				0x044 0x36c 0x894 0x4 0x0
+#define MX53_PAD_KEY_COL4__USBOH3_USBOTG_OC			0x044 0x36c 0x89c 0x5 0x0
+#define MX53_PAD_KEY_COL4__USBPHY1_LINESTATE_1			0x044 0x36c 0x000 0x7 0x0
+#define MX53_PAD_KEY_ROW4__KPP_ROW_4				0x048 0x370 0x000 0x0 0x0
+#define MX53_PAD_KEY_ROW4__GPIO4_15				0x048 0x370 0x000 0x1 0x0
+#define MX53_PAD_KEY_ROW4__CAN2_RXCAN				0x048 0x370 0x764 0x2 0x0
+#define MX53_PAD_KEY_ROW4__IPU_SISG_5				0x048 0x370 0x000 0x3 0x0
+#define MX53_PAD_KEY_ROW4__UART5_CTS				0x048 0x370 0x000 0x4 0x0
+#define MX53_PAD_KEY_ROW4__USBOH3_USBOTG_PWR			0x048 0x370 0x000 0x5 0x0
+#define MX53_PAD_KEY_ROW4__USBPHY1_VBUSVALID			0x048 0x370 0x000 0x7 0x0
+#define MX53_PAD_DI0_DISP_CLK__IPU_DI0_DISP_CLK			0x04c 0x378 0x000 0x0 0x0
+#define MX53_PAD_DI0_DISP_CLK__GPIO4_16				0x04c 0x378 0x000 0x1 0x0
+#define MX53_PAD_DI0_DISP_CLK__USBOH3_USBH2_DIR			0x04c 0x378 0x000 0x2 0x0
+#define MX53_PAD_DI0_DISP_CLK__SDMA_DEBUG_CORE_STATE_0		0x04c 0x378 0x000 0x5 0x0
+#define MX53_PAD_DI0_DISP_CLK__EMI_EMI_DEBUG_0			0x04c 0x378 0x000 0x6 0x0
+#define MX53_PAD_DI0_DISP_CLK__USBPHY1_AVALID			0x04c 0x378 0x000 0x7 0x0
+#define MX53_PAD_DI0_PIN15__IPU_DI0_PIN15			0x050 0x37c 0x000 0x0 0x0
+#define MX53_PAD_DI0_PIN15__GPIO4_17				0x050 0x37c 0x000 0x1 0x0
+#define MX53_PAD_DI0_PIN15__AUDMUX_AUD6_TXC			0x050 0x37c 0x000 0x2 0x0
+#define MX53_PAD_DI0_PIN15__SDMA_DEBUG_CORE_STATE_1		0x050 0x37c 0x000 0x5 0x0
+#define MX53_PAD_DI0_PIN15__EMI_EMI_DEBUG_1			0x050 0x37c 0x000 0x6 0x0
+#define MX53_PAD_DI0_PIN15__USBPHY1_BVALID			0x050 0x37c 0x000 0x7 0x0
+#define MX53_PAD_DI0_PIN2__IPU_DI0_PIN2				0x054 0x380 0x000 0x0 0x0
+#define MX53_PAD_DI0_PIN2__GPIO4_18				0x054 0x380 0x000 0x1 0x0
+#define MX53_PAD_DI0_PIN2__AUDMUX_AUD6_TXD			0x054 0x380 0x000 0x2 0x0
+#define MX53_PAD_DI0_PIN2__SDMA_DEBUG_CORE_STATE_2		0x054 0x380 0x000 0x5 0x0
+#define MX53_PAD_DI0_PIN2__EMI_EMI_DEBUG_2			0x054 0x380 0x000 0x6 0x0
+#define MX53_PAD_DI0_PIN2__USBPHY1_ENDSESSION			0x054 0x380 0x000 0x7 0x0
+#define MX53_PAD_DI0_PIN3__IPU_DI0_PIN3				0x058 0x384 0x000 0x0 0x0
+#define MX53_PAD_DI0_PIN3__GPIO4_19				0x058 0x384 0x000 0x1 0x0
+#define MX53_PAD_DI0_PIN3__AUDMUX_AUD6_TXFS			0x058 0x384 0x000 0x2 0x0
+#define MX53_PAD_DI0_PIN3__SDMA_DEBUG_CORE_STATE_3		0x058 0x384 0x000 0x5 0x0
+#define MX53_PAD_DI0_PIN3__EMI_EMI_DEBUG_3			0x058 0x384 0x000 0x6 0x0
+#define MX53_PAD_DI0_PIN3__USBPHY1_IDDIG			0x058 0x384 0x000 0x7 0x0
+#define MX53_PAD_DI0_PIN4__IPU_DI0_PIN4				0x05c 0x388 0x000 0x0 0x0
+#define MX53_PAD_DI0_PIN4__GPIO4_20				0x05c 0x388 0x000 0x1 0x0
+#define MX53_PAD_DI0_PIN4__AUDMUX_AUD6_RXD			0x05c 0x388 0x000 0x2 0x0
+#define MX53_PAD_DI0_PIN4__ESDHC1_WP				0x05c 0x388 0x7fc 0x3 0x0
+#define MX53_PAD_DI0_PIN4__SDMA_DEBUG_YIELD			0x05c 0x388 0x000 0x5 0x0
+#define MX53_PAD_DI0_PIN4__EMI_EMI_DEBUG_4			0x05c 0x388 0x000 0x6 0x0
+#define MX53_PAD_DI0_PIN4__USBPHY1_HOSTDISCONNECT		0x05c 0x388 0x000 0x7 0x0
+#define MX53_PAD_DISP0_DAT0__IPU_DISP0_DAT_0			0x060 0x38c 0x000 0x0 0x0
+#define MX53_PAD_DISP0_DAT0__GPIO4_21				0x060 0x38c 0x000 0x1 0x0
+#define MX53_PAD_DISP0_DAT0__CSPI_SCLK				0x060 0x38c 0x780 0x2 0x0
+#define MX53_PAD_DISP0_DAT0__USBOH3_USBH2_DATA_0		0x060 0x38c 0x000 0x3 0x0
+#define MX53_PAD_DISP0_DAT0__SDMA_DEBUG_CORE_RUN		0x060 0x38c 0x000 0x5 0x0
+#define MX53_PAD_DISP0_DAT0__EMI_EMI_DEBUG_5			0x060 0x38c 0x000 0x6 0x0
+#define MX53_PAD_DISP0_DAT0__USBPHY2_TXREADY			0x060 0x38c 0x000 0x7 0x0
+#define MX53_PAD_DISP0_DAT1__IPU_DISP0_DAT_1			0x064 0x390 0x000 0x0 0x0
+#define MX53_PAD_DISP0_DAT1__GPIO4_22				0x064 0x390 0x000 0x1 0x0
+#define MX53_PAD_DISP0_DAT1__CSPI_MOSI				0x064 0x390 0x788 0x2 0x0
+#define MX53_PAD_DISP0_DAT1__USBOH3_USBH2_DATA_1		0x064 0x390 0x000 0x3 0x0
+#define MX53_PAD_DISP0_DAT1__SDMA_DEBUG_EVENT_CHANNEL_SEL	0x064 0x390 0x000 0x5 0x0
+#define MX53_PAD_DISP0_DAT1__EMI_EMI_DEBUG_6			0x064 0x390 0x000 0x6 0x0
+#define MX53_PAD_DISP0_DAT1__USBPHY2_RXVALID			0x064 0x390 0x000 0x7 0x0
+#define MX53_PAD_DISP0_DAT2__IPU_DISP0_DAT_2			0x068 0x394 0x000 0x0 0x0
+#define MX53_PAD_DISP0_DAT2__GPIO4_23				0x068 0x394 0x000 0x1 0x0
+#define MX53_PAD_DISP0_DAT2__CSPI_MISO				0x068 0x394 0x784 0x2 0x0
+#define MX53_PAD_DISP0_DAT2__USBOH3_USBH2_DATA_2		0x068 0x394 0x000 0x3 0x0
+#define MX53_PAD_DISP0_DAT2__SDMA_DEBUG_MODE			0x068 0x394 0x000 0x5 0x0
+#define MX53_PAD_DISP0_DAT2__EMI_EMI_DEBUG_7			0x068 0x394 0x000 0x6 0x0
+#define MX53_PAD_DISP0_DAT2__USBPHY2_RXACTIVE			0x068 0x394 0x000 0x7 0x0
+#define MX53_PAD_DISP0_DAT3__IPU_DISP0_DAT_3			0x06c 0x398 0x000 0x0 0x0
+#define MX53_PAD_DISP0_DAT3__GPIO4_24				0x06c 0x398 0x000 0x1 0x0
+#define MX53_PAD_DISP0_DAT3__CSPI_SS0				0x06c 0x398 0x78c 0x2 0x0
+#define MX53_PAD_DISP0_DAT3__USBOH3_USBH2_DATA_3		0x06c 0x398 0x000 0x3 0x0
+#define MX53_PAD_DISP0_DAT3__SDMA_DEBUG_BUS_ERROR		0x06c 0x398 0x000 0x5 0x0
+#define MX53_PAD_DISP0_DAT3__EMI_EMI_DEBUG_8			0x06c 0x398 0x000 0x6 0x0
+#define MX53_PAD_DISP0_DAT3__USBPHY2_RXERROR			0x06c 0x398 0x000 0x7 0x0
+#define MX53_PAD_DISP0_DAT4__IPU_DISP0_DAT_4			0x070 0x39c 0x000 0x0 0x0
+#define MX53_PAD_DISP0_DAT4__GPIO4_25				0x070 0x39c 0x000 0x1 0x0
+#define MX53_PAD_DISP0_DAT4__CSPI_SS1				0x070 0x39c 0x790 0x2 0x0
+#define MX53_PAD_DISP0_DAT4__USBOH3_USBH2_DATA_4		0x070 0x39c 0x000 0x3 0x0
+#define MX53_PAD_DISP0_DAT4__SDMA_DEBUG_BUS_RWB			0x070 0x39c 0x000 0x5 0x0
+#define MX53_PAD_DISP0_DAT4__EMI_EMI_DEBUG_9			0x070 0x39c 0x000 0x6 0x0
+#define MX53_PAD_DISP0_DAT4__USBPHY2_SIECLOCK			0x070 0x39c 0x000 0x7 0x0
+#define MX53_PAD_DISP0_DAT5__IPU_DISP0_DAT_5			0x074 0x3a0 0x000 0x0 0x0
+#define MX53_PAD_DISP0_DAT5__GPIO4_26				0x074 0x3a0 0x000 0x1 0x0
+#define MX53_PAD_DISP0_DAT5__CSPI_SS2				0x074 0x3a0 0x794 0x2 0x0
+#define MX53_PAD_DISP0_DAT5__USBOH3_USBH2_DATA_5		0x074 0x3a0 0x000 0x3 0x0
+#define MX53_PAD_DISP0_DAT5__SDMA_DEBUG_MATCHED_DMBUS		0x074 0x3a0 0x000 0x5 0x0
+#define MX53_PAD_DISP0_DAT5__EMI_EMI_DEBUG_10			0x074 0x3a0 0x000 0x6 0x0
+#define MX53_PAD_DISP0_DAT5__USBPHY2_LINESTATE_0		0x074 0x3a0 0x000 0x7 0x0
+#define MX53_PAD_DISP0_DAT6__IPU_DISP0_DAT_6			0x078 0x3a4 0x000 0x0 0x0
+#define MX53_PAD_DISP0_DAT6__GPIO4_27				0x078 0x3a4 0x000 0x1 0x0
+#define MX53_PAD_DISP0_DAT6__CSPI_SS3				0x078 0x3a4 0x798 0x2 0x0
+#define MX53_PAD_DISP0_DAT6__USBOH3_USBH2_DATA_6		0x078 0x3a4 0x000 0x3 0x0
+#define MX53_PAD_DISP0_DAT6__SDMA_DEBUG_RTBUFFER_WRITE		0x078 0x3a4 0x000 0x5 0x0
+#define MX53_PAD_DISP0_DAT6__EMI_EMI_DEBUG_11			0x078 0x3a4 0x000 0x6 0x0
+#define MX53_PAD_DISP0_DAT6__USBPHY2_LINESTATE_1		0x078 0x3a4 0x000 0x7 0x0
+#define MX53_PAD_DISP0_DAT7__IPU_DISP0_DAT_7			0x07c 0x3a8 0x000 0x0 0x0
+#define MX53_PAD_DISP0_DAT7__GPIO4_28				0x07c 0x3a8 0x000 0x1 0x0
+#define MX53_PAD_DISP0_DAT7__CSPI_RDY				0x07c 0x3a8 0x000 0x2 0x0
+#define MX53_PAD_DISP0_DAT7__USBOH3_USBH2_DATA_7		0x07c 0x3a8 0x000 0x3 0x0
+#define MX53_PAD_DISP0_DAT7__SDMA_DEBUG_EVENT_CHANNEL_0		0x07c 0x3a8 0x000 0x5 0x0
+#define MX53_PAD_DISP0_DAT7__EMI_EMI_DEBUG_12			0x07c 0x3a8 0x000 0x6 0x0
+#define MX53_PAD_DISP0_DAT7__USBPHY2_VBUSVALID			0x07c 0x3a8 0x000 0x7 0x0
+#define MX53_PAD_DISP0_DAT8__IPU_DISP0_DAT_8			0x080 0x3ac 0x000 0x0 0x0
+#define MX53_PAD_DISP0_DAT8__GPIO4_29				0x080 0x3ac 0x000 0x1 0x0
+#define MX53_PAD_DISP0_DAT8__PWM1_PWMO				0x080 0x3ac 0x000 0x2 0x0
+#define MX53_PAD_DISP0_DAT8__WDOG1_WDOG_B			0x080 0x3ac 0x000 0x3 0x0
+#define MX53_PAD_DISP0_DAT8__SDMA_DEBUG_EVENT_CHANNEL_1		0x080 0x3ac 0x000 0x5 0x0
+#define MX53_PAD_DISP0_DAT8__EMI_EMI_DEBUG_13			0x080 0x3ac 0x000 0x6 0x0
+#define MX53_PAD_DISP0_DAT8__USBPHY2_AVALID			0x080 0x3ac 0x000 0x7 0x0
+#define MX53_PAD_DISP0_DAT9__IPU_DISP0_DAT_9			0x084 0x3b0 0x000 0x0 0x0
+#define MX53_PAD_DISP0_DAT9__GPIO4_30				0x084 0x3b0 0x000 0x1 0x0
+#define MX53_PAD_DISP0_DAT9__PWM2_PWMO				0x084 0x3b0 0x000 0x2 0x0
+#define MX53_PAD_DISP0_DAT9__WDOG2_WDOG_B			0x084 0x3b0 0x000 0x3 0x0
+#define MX53_PAD_DISP0_DAT9__SDMA_DEBUG_EVENT_CHANNEL_2		0x084 0x3b0 0x000 0x5 0x0
+#define MX53_PAD_DISP0_DAT9__EMI_EMI_DEBUG_14			0x084 0x3b0 0x000 0x6 0x0
+#define MX53_PAD_DISP0_DAT9__USBPHY2_VSTATUS_0			0x084 0x3b0 0x000 0x7 0x0
+#define MX53_PAD_DISP0_DAT10__IPU_DISP0_DAT_10			0x088 0x3b4 0x000 0x0 0x0
+#define MX53_PAD_DISP0_DAT10__GPIO4_31				0x088 0x3b4 0x000 0x1 0x0
+#define MX53_PAD_DISP0_DAT10__USBOH3_USBH2_STP			0x088 0x3b4 0x000 0x2 0x0
+#define MX53_PAD_DISP0_DAT10__SDMA_DEBUG_EVENT_CHANNEL_3	0x088 0x3b4 0x000 0x5 0x0
+#define MX53_PAD_DISP0_DAT10__EMI_EMI_DEBUG_15			0x088 0x3b4 0x000 0x6 0x0
+#define MX53_PAD_DISP0_DAT10__USBPHY2_VSTATUS_1			0x088 0x3b4 0x000 0x7 0x0
+#define MX53_PAD_DISP0_DAT11__IPU_DISP0_DAT_11			0x08c 0x3b8 0x000 0x0 0x0
+#define MX53_PAD_DISP0_DAT11__GPIO5_5				0x08c 0x3b8 0x000 0x1 0x0
+#define MX53_PAD_DISP0_DAT11__USBOH3_USBH2_NXT			0x08c 0x3b8 0x000 0x2 0x0
+#define MX53_PAD_DISP0_DAT11__SDMA_DEBUG_EVENT_CHANNEL_4	0x08c 0x3b8 0x000 0x5 0x0
+#define MX53_PAD_DISP0_DAT11__EMI_EMI_DEBUG_16			0x08c 0x3b8 0x000 0x6 0x0
+#define MX53_PAD_DISP0_DAT11__USBPHY2_VSTATUS_2			0x08c 0x3b8 0x000 0x7 0x0
+#define MX53_PAD_DISP0_DAT12__IPU_DISP0_DAT_12			0x090 0x3bc 0x000 0x0 0x0
+#define MX53_PAD_DISP0_DAT12__GPIO5_6				0x090 0x3bc 0x000 0x1 0x0
+#define MX53_PAD_DISP0_DAT12__USBOH3_USBH2_CLK			0x090 0x3bc 0x000 0x2 0x0
+#define MX53_PAD_DISP0_DAT12__SDMA_DEBUG_EVENT_CHANNEL_5	0x090 0x3bc 0x000 0x5 0x0
+#define MX53_PAD_DISP0_DAT12__EMI_EMI_DEBUG_17			0x090 0x3bc 0x000 0x6 0x0
+#define MX53_PAD_DISP0_DAT12__USBPHY2_VSTATUS_3			0x090 0x3bc 0x000 0x7 0x0
+#define MX53_PAD_DISP0_DAT13__IPU_DISP0_DAT_13			0x094 0x3c0 0x000 0x0 0x0
+#define MX53_PAD_DISP0_DAT13__GPIO5_7				0x094 0x3c0 0x000 0x1 0x0
+#define MX53_PAD_DISP0_DAT13__AUDMUX_AUD5_RXFS			0x094 0x3c0 0x754 0x3 0x0
+#define MX53_PAD_DISP0_DAT13__SDMA_DEBUG_EVT_CHN_LINES_0	0x094 0x3c0 0x000 0x5 0x0
+#define MX53_PAD_DISP0_DAT13__EMI_EMI_DEBUG_18			0x094 0x3c0 0x000 0x6 0x0
+#define MX53_PAD_DISP0_DAT13__USBPHY2_VSTATUS_4			0x094 0x3c0 0x000 0x7 0x0
+#define MX53_PAD_DISP0_DAT14__IPU_DISP0_DAT_14			0x098 0x3c4 0x000 0x0 0x0
+#define MX53_PAD_DISP0_DAT14__GPIO5_8				0x098 0x3c4 0x000 0x1 0x0
+#define MX53_PAD_DISP0_DAT14__AUDMUX_AUD5_RXC			0x098 0x3c4 0x750 0x3 0x0
+#define MX53_PAD_DISP0_DAT14__SDMA_DEBUG_EVT_CHN_LINES_1	0x098 0x3c4 0x000 0x5 0x0
+#define MX53_PAD_DISP0_DAT14__EMI_EMI_DEBUG_19			0x098 0x3c4 0x000 0x6 0x0
+#define MX53_PAD_DISP0_DAT14__USBPHY2_VSTATUS_5			0x098 0x3c4 0x000 0x7 0x0
+#define MX53_PAD_DISP0_DAT15__IPU_DISP0_DAT_15			0x09c 0x3c8 0x000 0x0 0x0
+#define MX53_PAD_DISP0_DAT15__GPIO5_9				0x09c 0x3c8 0x000 0x1 0x0
+#define MX53_PAD_DISP0_DAT15__ECSPI1_SS1			0x09c 0x3c8 0x7ac 0x2 0x1
+#define MX53_PAD_DISP0_DAT15__ECSPI2_SS1			0x09c 0x3c8 0x7c8 0x3 0x0
+#define MX53_PAD_DISP0_DAT15__SDMA_DEBUG_EVT_CHN_LINES_2	0x09c 0x3c8 0x000 0x5 0x0
+#define MX53_PAD_DISP0_DAT15__EMI_EMI_DEBUG_20			0x09c 0x3c8 0x000 0x6 0x0
+#define MX53_PAD_DISP0_DAT15__USBPHY2_VSTATUS_6			0x09c 0x3c8 0x000 0x7 0x0
+#define MX53_PAD_DISP0_DAT16__IPU_DISP0_DAT_16			0x0a0 0x3cc 0x000 0x0 0x0
+#define MX53_PAD_DISP0_DAT16__GPIO5_10				0x0a0 0x3cc 0x000 0x1 0x0
+#define MX53_PAD_DISP0_DAT16__ECSPI2_MOSI			0x0a0 0x3cc 0x7c0 0x2 0x0
+#define MX53_PAD_DISP0_DAT16__AUDMUX_AUD5_TXC			0x0a0 0x3cc 0x758 0x3 0x1
+#define MX53_PAD_DISP0_DAT16__SDMA_EXT_EVENT_0			0x0a0 0x3cc 0x868 0x4 0x0
+#define MX53_PAD_DISP0_DAT16__SDMA_DEBUG_EVT_CHN_LINES_3	0x0a0 0x3cc 0x000 0x5 0x0
+#define MX53_PAD_DISP0_DAT16__EMI_EMI_DEBUG_21			0x0a0 0x3cc 0x000 0x6 0x0
+#define MX53_PAD_DISP0_DAT16__USBPHY2_VSTATUS_7			0x0a0 0x3cc 0x000 0x7 0x0
+#define MX53_PAD_DISP0_DAT17__IPU_DISP0_DAT_17			0x0a4 0x3d0 0x000 0x0 0x0
+#define MX53_PAD_DISP0_DAT17__GPIO5_11				0x0a4 0x3d0 0x000 0x1 0x0
+#define MX53_PAD_DISP0_DAT17__ECSPI2_MISO			0x0a4 0x3d0 0x7bc 0x2 0x0
+#define MX53_PAD_DISP0_DAT17__AUDMUX_AUD5_TXD			0x0a4 0x3d0 0x74c 0x3 0x1
+#define MX53_PAD_DISP0_DAT17__SDMA_EXT_EVENT_1			0x0a4 0x3d0 0x86c 0x4 0x0
+#define MX53_PAD_DISP0_DAT17__SDMA_DEBUG_EVT_CHN_LINES_4	0x0a4 0x3d0 0x000 0x5 0x0
+#define MX53_PAD_DISP0_DAT17__EMI_EMI_DEBUG_22			0x0a4 0x3d0 0x000 0x6 0x0
+#define MX53_PAD_DISP0_DAT18__IPU_DISP0_DAT_18			0x0a8 0x3d4 0x000 0x0 0x0
+#define MX53_PAD_DISP0_DAT18__GPIO5_12				0x0a8 0x3d4 0x000 0x1 0x0
+#define MX53_PAD_DISP0_DAT18__ECSPI2_SS0			0x0a8 0x3d4 0x7c4 0x2 0x0
+#define MX53_PAD_DISP0_DAT18__AUDMUX_AUD5_TXFS			0x0a8 0x3d4 0x75c 0x3 0x1
+#define MX53_PAD_DISP0_DAT18__AUDMUX_AUD4_RXFS			0x0a8 0x3d4 0x73c 0x4 0x0
+#define MX53_PAD_DISP0_DAT18__SDMA_DEBUG_EVT_CHN_LINES_5	0x0a8 0x3d4 0x000 0x5 0x0
+#define MX53_PAD_DISP0_DAT18__EMI_EMI_DEBUG_23			0x0a8 0x3d4 0x000 0x6 0x0
+#define MX53_PAD_DISP0_DAT18__EMI_WEIM_CS_2			0x0a8 0x3d4 0x000 0x7 0x0
+#define MX53_PAD_DISP0_DAT19__IPU_DISP0_DAT_19			0x0ac 0x3d8 0x000 0x0 0x0
+#define MX53_PAD_DISP0_DAT19__GPIO5_13				0x0ac 0x3d8 0x000 0x1 0x0
+#define MX53_PAD_DISP0_DAT19__ECSPI2_SCLK			0x0ac 0x3d8 0x7b8 0x2 0x0
+#define MX53_PAD_DISP0_DAT19__AUDMUX_AUD5_RXD			0x0ac 0x3d8 0x748 0x3 0x1
+#define MX53_PAD_DISP0_DAT19__AUDMUX_AUD4_RXC			0x0ac 0x3d8 0x738 0x4 0x0
+#define MX53_PAD_DISP0_DAT19__SDMA_DEBUG_EVT_CHN_LINES_6	0x0ac 0x3d8 0x000 0x5 0x0
+#define MX53_PAD_DISP0_DAT19__EMI_EMI_DEBUG_24			0x0ac 0x3d8 0x000 0x6 0x0
+#define MX53_PAD_DISP0_DAT19__EMI_WEIM_CS_3			0x0ac 0x3d8 0x000 0x7 0x0
+#define MX53_PAD_DISP0_DAT20__IPU_DISP0_DAT_20			0x0b0 0x3dc 0x000 0x0 0x0
+#define MX53_PAD_DISP0_DAT20__GPIO5_14				0x0b0 0x3dc 0x000 0x1 0x0
+#define MX53_PAD_DISP0_DAT20__ECSPI1_SCLK			0x0b0 0x3dc 0x79c 0x2 0x1
+#define MX53_PAD_DISP0_DAT20__AUDMUX_AUD4_TXC			0x0b0 0x3dc 0x740 0x3 0x0
+#define MX53_PAD_DISP0_DAT20__SDMA_DEBUG_EVT_CHN_LINES_7	0x0b0 0x3dc 0x000 0x5 0x0
+#define MX53_PAD_DISP0_DAT20__EMI_EMI_DEBUG_25			0x0b0 0x3dc 0x000 0x6 0x0
+#define MX53_PAD_DISP0_DAT20__SATA_PHY_TDI			0x0b0 0x3dc 0x000 0x7 0x0
+#define MX53_PAD_DISP0_DAT21__IPU_DISP0_DAT_21			0x0b4 0x3e0 0x000 0x0 0x0
+#define MX53_PAD_DISP0_DAT21__GPIO5_15				0x0b4 0x3e0 0x000 0x1 0x0
+#define MX53_PAD_DISP0_DAT21__ECSPI1_MOSI			0x0b4 0x3e0 0x7a4 0x2 0x1
+#define MX53_PAD_DISP0_DAT21__AUDMUX_AUD4_TXD			0x0b4 0x3e0 0x734 0x3 0x0
+#define MX53_PAD_DISP0_DAT21__SDMA_DEBUG_BUS_DEVICE_0		0x0b4 0x3e0 0x000 0x5 0x0
+#define MX53_PAD_DISP0_DAT21__EMI_EMI_DEBUG_26			0x0b4 0x3e0 0x000 0x6 0x0
+#define MX53_PAD_DISP0_DAT21__SATA_PHY_TDO			0x0b4 0x3e0 0x000 0x7 0x0
+#define MX53_PAD_DISP0_DAT22__IPU_DISP0_DAT_22			0x0b8 0x3e4 0x000 0x0 0x0
+#define MX53_PAD_DISP0_DAT22__GPIO5_16				0x0b8 0x3e4 0x000 0x1 0x0
+#define MX53_PAD_DISP0_DAT22__ECSPI1_MISO			0x0b8 0x3e4 0x7a0 0x2 0x1
+#define MX53_PAD_DISP0_DAT22__AUDMUX_AUD4_TXFS			0x0b8 0x3e4 0x744 0x3 0x0
+#define MX53_PAD_DISP0_DAT22__SDMA_DEBUG_BUS_DEVICE_1		0x0b8 0x3e4 0x000 0x5 0x0
+#define MX53_PAD_DISP0_DAT22__EMI_EMI_DEBUG_27			0x0b8 0x3e4 0x000 0x6 0x0
+#define MX53_PAD_DISP0_DAT22__SATA_PHY_TCK			0x0b8 0x3e4 0x000 0x7 0x0
+#define MX53_PAD_DISP0_DAT23__IPU_DISP0_DAT_23			0x0bc 0x3e8 0x000 0x0 0x0
+#define MX53_PAD_DISP0_DAT23__GPIO5_17				0x0bc 0x3e8 0x000 0x1 0x0
+#define MX53_PAD_DISP0_DAT23__ECSPI1_SS0			0x0bc 0x3e8 0x7a8 0x2 0x1
+#define MX53_PAD_DISP0_DAT23__AUDMUX_AUD4_RXD			0x0bc 0x3e8 0x730 0x3 0x0
+#define MX53_PAD_DISP0_DAT23__SDMA_DEBUG_BUS_DEVICE_2		0x0bc 0x3e8 0x000 0x5 0x0
+#define MX53_PAD_DISP0_DAT23__EMI_EMI_DEBUG_28			0x0bc 0x3e8 0x000 0x6 0x0
+#define MX53_PAD_DISP0_DAT23__SATA_PHY_TMS			0x0bc 0x3e8 0x000 0x7 0x0
+#define MX53_PAD_CSI0_PIXCLK__IPU_CSI0_PIXCLK			0x0c0 0x3ec 0x000 0x0 0x0
+#define MX53_PAD_CSI0_PIXCLK__GPIO5_18				0x0c0 0x3ec 0x000 0x1 0x0
+#define MX53_PAD_CSI0_PIXCLK__SDMA_DEBUG_PC_0			0x0c0 0x3ec 0x000 0x5 0x0
+#define MX53_PAD_CSI0_PIXCLK__EMI_EMI_DEBUG_29			0x0c0 0x3ec 0x000 0x6 0x0
+#define MX53_PAD_CSI0_MCLK__IPU_CSI0_HSYNC			0x0c4 0x3f0 0x000 0x0 0x0
+#define MX53_PAD_CSI0_MCLK__GPIO5_19				0x0c4 0x3f0 0x000 0x1 0x0
+#define MX53_PAD_CSI0_MCLK__CCM_CSI0_MCLK			0x0c4 0x3f0 0x000 0x2 0x0
+#define MX53_PAD_CSI0_MCLK__SDMA_DEBUG_PC_1			0x0c4 0x3f0 0x000 0x5 0x0
+#define MX53_PAD_CSI0_MCLK__EMI_EMI_DEBUG_30			0x0c4 0x3f0 0x000 0x6 0x0
+#define MX53_PAD_CSI0_MCLK__TPIU_TRCTL				0x0c4 0x3f0 0x000 0x7 0x0
+#define MX53_PAD_CSI0_DATA_EN__IPU_CSI0_DATA_EN			0x0c8 0x3f4 0x000 0x0 0x0
+#define MX53_PAD_CSI0_DATA_EN__GPIO5_20				0x0c8 0x3f4 0x000 0x1 0x0
+#define MX53_PAD_CSI0_DATA_EN__SDMA_DEBUG_PC_2			0x0c8 0x3f4 0x000 0x5 0x0
+#define MX53_PAD_CSI0_DATA_EN__EMI_EMI_DEBUG_31			0x0c8 0x3f4 0x000 0x6 0x0
+#define MX53_PAD_CSI0_DATA_EN__TPIU_TRCLK			0x0c8 0x3f4 0x000 0x7 0x0
+#define MX53_PAD_CSI0_VSYNC__IPU_CSI0_VSYNC			0x0cc 0x3f8 0x000 0x0 0x0
+#define MX53_PAD_CSI0_VSYNC__GPIO5_21				0x0cc 0x3f8 0x000 0x1 0x0
+#define MX53_PAD_CSI0_VSYNC__SDMA_DEBUG_PC_3			0x0cc 0x3f8 0x000 0x5 0x0
+#define MX53_PAD_CSI0_VSYNC__EMI_EMI_DEBUG_32			0x0cc 0x3f8 0x000 0x6 0x0
+#define MX53_PAD_CSI0_VSYNC__TPIU_TRACE_0			0x0cc 0x3f8 0x000 0x7 0x0
+#define MX53_PAD_CSI0_DAT4__IPU_CSI0_D_4			0x0d0 0x3fc 0x000 0x0 0x0
+#define MX53_PAD_CSI0_DAT4__GPIO5_22				0x0d0 0x3fc 0x000 0x1 0x0
+#define MX53_PAD_CSI0_DAT4__KPP_COL_5				0x0d0 0x3fc 0x840 0x2 0x1
+#define MX53_PAD_CSI0_DAT4__ECSPI1_SCLK				0x0d0 0x3fc 0x79c 0x3 0x2
+#define MX53_PAD_CSI0_DAT4__USBOH3_USBH3_STP			0x0d0 0x3fc 0x000 0x4 0x0
+#define MX53_PAD_CSI0_DAT4__AUDMUX_AUD3_TXC			0x0d0 0x3fc 0x000 0x5 0x0
+#define MX53_PAD_CSI0_DAT4__EMI_EMI_DEBUG_33			0x0d0 0x3fc 0x000 0x6 0x0
+#define MX53_PAD_CSI0_DAT4__TPIU_TRACE_1			0x0d0 0x3fc 0x000 0x7 0x0
+#define MX53_PAD_CSI0_DAT5__IPU_CSI0_D_5			0x0d4 0x400 0x000 0x0 0x0
+#define MX53_PAD_CSI0_DAT5__GPIO5_23				0x0d4 0x400 0x000 0x1 0x0
+#define MX53_PAD_CSI0_DAT5__KPP_ROW_5				0x0d4 0x400 0x84c 0x2 0x0
+#define MX53_PAD_CSI0_DAT5__ECSPI1_MOSI				0x0d4 0x400 0x7a4 0x3 0x2
+#define MX53_PAD_CSI0_DAT5__USBOH3_USBH3_NXT			0x0d4 0x400 0x000 0x4 0x0
+#define MX53_PAD_CSI0_DAT5__AUDMUX_AUD3_TXD			0x0d4 0x400 0x000 0x5 0x0
+#define MX53_PAD_CSI0_DAT5__EMI_EMI_DEBUG_34			0x0d4 0x400 0x000 0x6 0x0
+#define MX53_PAD_CSI0_DAT5__TPIU_TRACE_2			0x0d4 0x400 0x000 0x7 0x0
+#define MX53_PAD_CSI0_DAT6__IPU_CSI0_D_6			0x0d8 0x404 0x000 0x0 0x0
+#define MX53_PAD_CSI0_DAT6__GPIO5_24				0x0d8 0x404 0x000 0x1 0x0
+#define MX53_PAD_CSI0_DAT6__KPP_COL_6				0x0d8 0x404 0x844 0x2 0x0
+#define MX53_PAD_CSI0_DAT6__ECSPI1_MISO				0x0d8 0x404 0x7a0 0x3 0x2
+#define MX53_PAD_CSI0_DAT6__USBOH3_USBH3_CLK			0x0d8 0x404 0x000 0x4 0x0
+#define MX53_PAD_CSI0_DAT6__AUDMUX_AUD3_TXFS			0x0d8 0x404 0x000 0x5 0x0
+#define MX53_PAD_CSI0_DAT6__EMI_EMI_DEBUG_35			0x0d8 0x404 0x000 0x6 0x0
+#define MX53_PAD_CSI0_DAT6__TPIU_TRACE_3			0x0d8 0x404 0x000 0x7 0x0
+#define MX53_PAD_CSI0_DAT7__IPU_CSI0_D_7			0x0dc 0x408 0x000 0x0 0x0
+#define MX53_PAD_CSI0_DAT7__GPIO5_25				0x0dc 0x408 0x000 0x1 0x0
+#define MX53_PAD_CSI0_DAT7__KPP_ROW_6				0x0dc 0x408 0x850 0x2 0x0
+#define MX53_PAD_CSI0_DAT7__ECSPI1_SS0				0x0dc 0x408 0x7a8 0x3 0x2
+#define MX53_PAD_CSI0_DAT7__USBOH3_USBH3_DIR			0x0dc 0x408 0x000 0x4 0x0
+#define MX53_PAD_CSI0_DAT7__AUDMUX_AUD3_RXD			0x0dc 0x408 0x000 0x5 0x0
+#define MX53_PAD_CSI0_DAT7__EMI_EMI_DEBUG_36			0x0dc 0x408 0x000 0x6 0x0
+#define MX53_PAD_CSI0_DAT7__TPIU_TRACE_4			0x0dc 0x408 0x000 0x7 0x0
+#define MX53_PAD_CSI0_DAT8__IPU_CSI0_D_8			0x0e0 0x40c 0x000 0x0 0x0
+#define MX53_PAD_CSI0_DAT8__GPIO5_26				0x0e0 0x40c 0x000 0x1 0x0
+#define MX53_PAD_CSI0_DAT8__KPP_COL_7				0x0e0 0x40c 0x848 0x2 0x0
+#define MX53_PAD_CSI0_DAT8__ECSPI2_SCLK				0x0e0 0x40c 0x7b8 0x3 0x1
+#define MX53_PAD_CSI0_DAT8__USBOH3_USBH3_OC			0x0e0 0x40c 0x000 0x4 0x0
+#define MX53_PAD_CSI0_DAT8__I2C1_SDA				0x0e0 0x40c 0x818 0x5 0x0
+#define MX53_PAD_CSI0_DAT8__EMI_EMI_DEBUG_37			0x0e0 0x40c 0x000 0x6 0x0
+#define MX53_PAD_CSI0_DAT8__TPIU_TRACE_5			0x0e0 0x40c 0x000 0x7 0x0
+#define MX53_PAD_CSI0_DAT9__IPU_CSI0_D_9			0x0e4 0x410 0x000 0x0 0x0
+#define MX53_PAD_CSI0_DAT9__GPIO5_27				0x0e4 0x410 0x000 0x1 0x0
+#define MX53_PAD_CSI0_DAT9__KPP_ROW_7				0x0e4 0x410 0x854 0x2 0x0
+#define MX53_PAD_CSI0_DAT9__ECSPI2_MOSI				0x0e4 0x410 0x7c0 0x3 0x1
+#define MX53_PAD_CSI0_DAT9__USBOH3_USBH3_PWR			0x0e4 0x410 0x000 0x4 0x0
+#define MX53_PAD_CSI0_DAT9__I2C1_SCL				0x0e4 0x410 0x814 0x5 0x0
+#define MX53_PAD_CSI0_DAT9__EMI_EMI_DEBUG_38			0x0e4 0x410 0x000 0x6 0x0
+#define MX53_PAD_CSI0_DAT9__TPIU_TRACE_6			0x0e4 0x410 0x000 0x7 0x0
+#define MX53_PAD_CSI0_DAT10__IPU_CSI0_D_10			0x0e8 0x414 0x000 0x0 0x0
+#define MX53_PAD_CSI0_DAT10__GPIO5_28				0x0e8 0x414 0x000 0x1 0x0
+#define MX53_PAD_CSI0_DAT10__UART1_TXD_MUX			0x0e8 0x414 0x000 0x2 0x0
+#define MX53_PAD_CSI0_DAT10__ECSPI2_MISO			0x0e8 0x414 0x7bc 0x3 0x1
+#define MX53_PAD_CSI0_DAT10__AUDMUX_AUD3_RXC			0x0e8 0x414 0x000 0x4 0x0
+#define MX53_PAD_CSI0_DAT10__SDMA_DEBUG_PC_4			0x0e8 0x414 0x000 0x5 0x0
+#define MX53_PAD_CSI0_DAT10__EMI_EMI_DEBUG_39			0x0e8 0x414 0x000 0x6 0x0
+#define MX53_PAD_CSI0_DAT10__TPIU_TRACE_7			0x0e8 0x414 0x000 0x7 0x0
+#define MX53_PAD_CSI0_DAT11__IPU_CSI0_D_11			0x0ec 0x418 0x000 0x0 0x0
+#define MX53_PAD_CSI0_DAT11__GPIO5_29				0x0ec 0x418 0x000 0x1 0x0
+#define MX53_PAD_CSI0_DAT11__UART1_RXD_MUX			0x0ec 0x418 0x878 0x2 0x1
+#define MX53_PAD_CSI0_DAT11__ECSPI2_SS0				0x0ec 0x418 0x7c4 0x3 0x1
+#define MX53_PAD_CSI0_DAT11__AUDMUX_AUD3_RXFS			0x0ec 0x418 0x000 0x4 0x0
+#define MX53_PAD_CSI0_DAT11__SDMA_DEBUG_PC_5			0x0ec 0x418 0x000 0x5 0x0
+#define MX53_PAD_CSI0_DAT11__EMI_EMI_DEBUG_40			0x0ec 0x418 0x000 0x6 0x0
+#define MX53_PAD_CSI0_DAT11__TPIU_TRACE_8			0x0ec 0x418 0x000 0x7 0x0
+#define MX53_PAD_CSI0_DAT12__IPU_CSI0_D_12			0x0f0 0x41c 0x000 0x0 0x0
+#define MX53_PAD_CSI0_DAT12__GPIO5_30				0x0f0 0x41c 0x000 0x1 0x0
+#define MX53_PAD_CSI0_DAT12__UART4_TXD_MUX			0x0f0 0x41c 0x000 0x2 0x0
+#define MX53_PAD_CSI0_DAT12__USBOH3_USBH3_DATA_0		0x0f0 0x41c 0x000 0x4 0x0
+#define MX53_PAD_CSI0_DAT12__SDMA_DEBUG_PC_6			0x0f0 0x41c 0x000 0x5 0x0
+#define MX53_PAD_CSI0_DAT12__EMI_EMI_DEBUG_41			0x0f0 0x41c 0x000 0x6 0x0
+#define MX53_PAD_CSI0_DAT12__TPIU_TRACE_9			0x0f0 0x41c 0x000 0x7 0x0
+#define MX53_PAD_CSI0_DAT13__IPU_CSI0_D_13			0x0f4 0x420 0x000 0x0 0x0
+#define MX53_PAD_CSI0_DAT13__GPIO5_31				0x0f4 0x420 0x000 0x1 0x0
+#define MX53_PAD_CSI0_DAT13__UART4_RXD_MUX			0x0f4 0x420 0x890 0x2 0x3
+#define MX53_PAD_CSI0_DAT13__USBOH3_USBH3_DATA_1		0x0f4 0x420 0x000 0x4 0x0
+#define MX53_PAD_CSI0_DAT13__SDMA_DEBUG_PC_7			0x0f4 0x420 0x000 0x5 0x0
+#define MX53_PAD_CSI0_DAT13__EMI_EMI_DEBUG_42			0x0f4 0x420 0x000 0x6 0x0
+#define MX53_PAD_CSI0_DAT13__TPIU_TRACE_10			0x0f4 0x420 0x000 0x7 0x0
+#define MX53_PAD_CSI0_DAT14__IPU_CSI0_D_14			0x0f8 0x424 0x000 0x0 0x0
+#define MX53_PAD_CSI0_DAT14__GPIO6_0				0x0f8 0x424 0x000 0x1 0x0
+#define MX53_PAD_CSI0_DAT14__UART5_TXD_MUX			0x0f8 0x424 0x000 0x2 0x0
+#define MX53_PAD_CSI0_DAT14__USBOH3_USBH3_DATA_2		0x0f8 0x424 0x000 0x4 0x0
+#define MX53_PAD_CSI0_DAT14__SDMA_DEBUG_PC_8			0x0f8 0x424 0x000 0x5 0x0
+#define MX53_PAD_CSI0_DAT14__EMI_EMI_DEBUG_43			0x0f8 0x424 0x000 0x6 0x0
+#define MX53_PAD_CSI0_DAT14__TPIU_TRACE_11			0x0f8 0x424 0x000 0x7 0x0
+#define MX53_PAD_CSI0_DAT15__IPU_CSI0_D_15			0x0fc 0x428 0x000 0x0 0x0
+#define MX53_PAD_CSI0_DAT15__GPIO6_1				0x0fc 0x428 0x000 0x1 0x0
+#define MX53_PAD_CSI0_DAT15__UART5_RXD_MUX			0x0fc 0x428 0x898 0x2 0x3
+#define MX53_PAD_CSI0_DAT15__USBOH3_USBH3_DATA_3		0x0fc 0x428 0x000 0x4 0x0
+#define MX53_PAD_CSI0_DAT15__SDMA_DEBUG_PC_9			0x0fc 0x428 0x000 0x5 0x0
+#define MX53_PAD_CSI0_DAT15__EMI_EMI_DEBUG_44			0x0fc 0x428 0x000 0x6 0x0
+#define MX53_PAD_CSI0_DAT15__TPIU_TRACE_12			0x0fc 0x428 0x000 0x7 0x0
+#define MX53_PAD_CSI0_DAT16__IPU_CSI0_D_16			0x100 0x42c 0x000 0x0 0x0
+#define MX53_PAD_CSI0_DAT16__GPIO6_2				0x100 0x42c 0x000 0x1 0x0
+#define MX53_PAD_CSI0_DAT16__UART4_RTS				0x100 0x42c 0x88c 0x2 0x0
+#define MX53_PAD_CSI0_DAT16__USBOH3_USBH3_DATA_4		0x100 0x42c 0x000 0x4 0x0
+#define MX53_PAD_CSI0_DAT16__SDMA_DEBUG_PC_10			0x100 0x42c 0x000 0x5 0x0
+#define MX53_PAD_CSI0_DAT16__EMI_EMI_DEBUG_45			0x100 0x42c 0x000 0x6 0x0
+#define MX53_PAD_CSI0_DAT16__TPIU_TRACE_13			0x100 0x42c 0x000 0x7 0x0
+#define MX53_PAD_CSI0_DAT17__IPU_CSI0_D_17			0x104 0x430 0x000 0x0 0x0
+#define MX53_PAD_CSI0_DAT17__GPIO6_3				0x104 0x430 0x000 0x1 0x0
+#define MX53_PAD_CSI0_DAT17__UART4_CTS				0x104 0x430 0x000 0x2 0x0
+#define MX53_PAD_CSI0_DAT17__USBOH3_USBH3_DATA_5		0x104 0x430 0x000 0x4 0x0
+#define MX53_PAD_CSI0_DAT17__SDMA_DEBUG_PC_11			0x104 0x430 0x000 0x5 0x0
+#define MX53_PAD_CSI0_DAT17__EMI_EMI_DEBUG_46			0x104 0x430 0x000 0x6 0x0
+#define MX53_PAD_CSI0_DAT17__TPIU_TRACE_14			0x104 0x430 0x000 0x7 0x0
+#define MX53_PAD_CSI0_DAT18__IPU_CSI0_D_18			0x108 0x434 0x000 0x0 0x0
+#define MX53_PAD_CSI0_DAT18__GPIO6_4				0x108 0x434 0x000 0x1 0x0
+#define MX53_PAD_CSI0_DAT18__UART5_RTS				0x108 0x434 0x894 0x2 0x2
+#define MX53_PAD_CSI0_DAT18__USBOH3_USBH3_DATA_6		0x108 0x434 0x000 0x4 0x0
+#define MX53_PAD_CSI0_DAT18__SDMA_DEBUG_PC_12			0x108 0x434 0x000 0x5 0x0
+#define MX53_PAD_CSI0_DAT18__EMI_EMI_DEBUG_47			0x108 0x434 0x000 0x6 0x0
+#define MX53_PAD_CSI0_DAT18__TPIU_TRACE_15			0x108 0x434 0x000 0x7 0x0
+#define MX53_PAD_CSI0_DAT19__IPU_CSI0_D_19			0x10c 0x438 0x000 0x0 0x0
+#define MX53_PAD_CSI0_DAT19__GPIO6_5				0x10c 0x438 0x000 0x1 0x0
+#define MX53_PAD_CSI0_DAT19__UART5_CTS				0x10c 0x438 0x000 0x2 0x0
+#define MX53_PAD_CSI0_DAT19__USBOH3_USBH3_DATA_7		0x10c 0x438 0x000 0x4 0x0
+#define MX53_PAD_CSI0_DAT19__SDMA_DEBUG_PC_13			0x10c 0x438 0x000 0x5 0x0
+#define MX53_PAD_CSI0_DAT19__EMI_EMI_DEBUG_48			0x10c 0x438 0x000 0x6 0x0
+#define MX53_PAD_CSI0_DAT19__USBPHY2_BISTOK			0x10c 0x438 0x000 0x7 0x0
+#define MX53_PAD_EIM_A25__EMI_WEIM_A_25				0x110 0x458 0x000 0x0 0x0
+#define MX53_PAD_EIM_A25__GPIO5_2				0x110 0x458 0x000 0x1 0x0
+#define MX53_PAD_EIM_A25__ECSPI2_RDY				0x110 0x458 0x000 0x2 0x0
+#define MX53_PAD_EIM_A25__IPU_DI1_PIN12				0x110 0x458 0x000 0x3 0x0
+#define MX53_PAD_EIM_A25__CSPI_SS1				0x110 0x458 0x790 0x4 0x1
+#define MX53_PAD_EIM_A25__IPU_DI0_D1_CS				0x110 0x458 0x000 0x6 0x0
+#define MX53_PAD_EIM_A25__USBPHY1_BISTOK			0x110 0x458 0x000 0x7 0x0
+#define MX53_PAD_EIM_EB2__EMI_WEIM_EB_2				0x114 0x45c 0x000 0x0 0x0
+#define MX53_PAD_EIM_EB2__GPIO2_30				0x114 0x45c 0x000 0x1 0x0
+#define MX53_PAD_EIM_EB2__CCM_DI1_EXT_CLK			0x114 0x45c 0x76c 0x2 0x0
+#define MX53_PAD_EIM_EB2__IPU_SER_DISP1_CS			0x114 0x45c 0x000 0x3 0x0
+#define MX53_PAD_EIM_EB2__ECSPI1_SS0				0x114 0x45c 0x7a8 0x4 0x3
+#define MX53_PAD_EIM_EB2__I2C2_SCL				0x114 0x45c 0x81c 0x5 0x1
+#define MX53_PAD_EIM_D16__EMI_WEIM_D_16				0x118 0x460 0x000 0x0 0x0
+#define MX53_PAD_EIM_D16__GPIO3_16				0x118 0x460 0x000 0x1 0x0
+#define MX53_PAD_EIM_D16__IPU_DI0_PIN5				0x118 0x460 0x000 0x2 0x0
+#define MX53_PAD_EIM_D16__IPU_DISPB1_SER_CLK			0x118 0x460 0x000 0x3 0x0
+#define MX53_PAD_EIM_D16__ECSPI1_SCLK				0x118 0x460 0x79c 0x4 0x3
+#define MX53_PAD_EIM_D16__I2C2_SDA				0x118 0x460 0x820 0x5 0x1
+#define MX53_PAD_EIM_D17__EMI_WEIM_D_17				0x11c 0x464 0x000 0x0 0x0
+#define MX53_PAD_EIM_D17__GPIO3_17				0x11c 0x464 0x000 0x1 0x0
+#define MX53_PAD_EIM_D17__IPU_DI0_PIN6				0x11c 0x464 0x000 0x2 0x0
+#define MX53_PAD_EIM_D17__IPU_DISPB1_SER_DIN			0x11c 0x464 0x830 0x3 0x0
+#define MX53_PAD_EIM_D17__ECSPI1_MISO				0x11c 0x464 0x7a0 0x4 0x3
+#define MX53_PAD_EIM_D17__I2C3_SCL				0x11c 0x464 0x824 0x5 0x0
+#define MX53_PAD_EIM_D18__EMI_WEIM_D_18				0x120 0x468 0x000 0x0 0x0
+#define MX53_PAD_EIM_D18__GPIO3_18				0x120 0x468 0x000 0x1 0x0
+#define MX53_PAD_EIM_D18__IPU_DI0_PIN7				0x120 0x468 0x000 0x2 0x0
+#define MX53_PAD_EIM_D18__IPU_DISPB1_SER_DIO			0x120 0x468 0x830 0x3 0x1
+#define MX53_PAD_EIM_D18__ECSPI1_MOSI				0x120 0x468 0x7a4 0x4 0x3
+#define MX53_PAD_EIM_D18__I2C3_SDA				0x120 0x468 0x828 0x5 0x0
+#define MX53_PAD_EIM_D18__IPU_DI1_D0_CS				0x120 0x468 0x000 0x6 0x0
+#define MX53_PAD_EIM_D19__EMI_WEIM_D_19				0x124 0x46c 0x000 0x0 0x0
+#define MX53_PAD_EIM_D19__GPIO3_19				0x124 0x46c 0x000 0x1 0x0
+#define MX53_PAD_EIM_D19__IPU_DI0_PIN8				0x124 0x46c 0x000 0x2 0x0
+#define MX53_PAD_EIM_D19__IPU_DISPB1_SER_RS			0x124 0x46c 0x000 0x3 0x0
+#define MX53_PAD_EIM_D19__ECSPI1_SS1				0x124 0x46c 0x7ac 0x4 0x2
+#define MX53_PAD_EIM_D19__EPIT1_EPITO				0x124 0x46c 0x000 0x5 0x0
+#define MX53_PAD_EIM_D19__UART1_CTS				0x124 0x46c 0x000 0x6 0x0
+#define MX53_PAD_EIM_D19__USBOH3_USBH2_OC			0x124 0x46c 0x8a4 0x7 0x0
+#define MX53_PAD_EIM_D20__EMI_WEIM_D_20				0x128 0x470 0x000 0x0 0x0
+#define MX53_PAD_EIM_D20__GPIO3_20				0x128 0x470 0x000 0x1 0x0
+#define MX53_PAD_EIM_D20__IPU_DI0_PIN16				0x128 0x470 0x000 0x2 0x0
+#define MX53_PAD_EIM_D20__IPU_SER_DISP0_CS			0x128 0x470 0x000 0x3 0x0
+#define MX53_PAD_EIM_D20__CSPI_SS0				0x128 0x470 0x78c 0x4 0x1
+#define MX53_PAD_EIM_D20__EPIT2_EPITO				0x128 0x470 0x000 0x5 0x0
+#define MX53_PAD_EIM_D20__UART1_RTS				0x128 0x470 0x874 0x6 0x1
+#define MX53_PAD_EIM_D20__USBOH3_USBH2_PWR			0x128 0x470 0x000 0x7 0x0
+#define MX53_PAD_EIM_D21__EMI_WEIM_D_21				0x12c 0x474 0x000 0x0 0x0
+#define MX53_PAD_EIM_D21__GPIO3_21				0x12c 0x474 0x000 0x1 0x0
+#define MX53_PAD_EIM_D21__IPU_DI0_PIN17				0x12c 0x474 0x000 0x2 0x0
+#define MX53_PAD_EIM_D21__IPU_DISPB0_SER_CLK			0x12c 0x474 0x000 0x3 0x0
+#define MX53_PAD_EIM_D21__CSPI_SCLK				0x12c 0x474 0x780 0x4 0x1
+#define MX53_PAD_EIM_D21__I2C1_SCL				0x12c 0x474 0x814 0x5 0x1
+#define MX53_PAD_EIM_D21__USBOH3_USBOTG_OC			0x12c 0x474 0x89c 0x6 0x1
+#define MX53_PAD_EIM_D22__EMI_WEIM_D_22				0x130 0x478 0x000 0x0 0x0
+#define MX53_PAD_EIM_D22__GPIO3_22				0x130 0x478 0x000 0x1 0x0
+#define MX53_PAD_EIM_D22__IPU_DI0_PIN1				0x130 0x478 0x000 0x2 0x0
+#define MX53_PAD_EIM_D22__IPU_DISPB0_SER_DIN			0x130 0x478 0x82c 0x3 0x0
+#define MX53_PAD_EIM_D22__CSPI_MISO				0x130 0x478 0x784 0x4 0x1
+#define MX53_PAD_EIM_D22__USBOH3_USBOTG_PWR			0x130 0x478 0x000 0x6 0x0
+#define MX53_PAD_EIM_D23__EMI_WEIM_D_23				0x134 0x47c 0x000 0x0 0x0
+#define MX53_PAD_EIM_D23__GPIO3_23				0x134 0x47c 0x000 0x1 0x0
+#define MX53_PAD_EIM_D23__UART3_CTS				0x134 0x47c 0x000 0x2 0x0
+#define MX53_PAD_EIM_D23__UART1_DCD				0x134 0x47c 0x000 0x3 0x0
+#define MX53_PAD_EIM_D23__IPU_DI0_D0_CS				0x134 0x47c 0x000 0x4 0x0
+#define MX53_PAD_EIM_D23__IPU_DI1_PIN2				0x134 0x47c 0x000 0x5 0x0
+#define MX53_PAD_EIM_D23__IPU_CSI1_DATA_EN			0x134 0x47c 0x834 0x6 0x0
+#define MX53_PAD_EIM_D23__IPU_DI1_PIN14				0x134 0x47c 0x000 0x7 0x0
+#define MX53_PAD_EIM_EB3__EMI_WEIM_EB_3				0x138 0x480 0x000 0x0 0x0
+#define MX53_PAD_EIM_EB3__GPIO2_31				0x138 0x480 0x000 0x1 0x0
+#define MX53_PAD_EIM_EB3__UART3_RTS				0x138 0x480 0x884 0x2 0x1
+#define MX53_PAD_EIM_EB3__UART1_RI				0x138 0x480 0x000 0x3 0x0
+#define MX53_PAD_EIM_EB3__IPU_DI1_PIN3				0x138 0x480 0x000 0x5 0x0
+#define MX53_PAD_EIM_EB3__IPU_CSI1_HSYNC			0x138 0x480 0x838 0x6 0x0
+#define MX53_PAD_EIM_EB3__IPU_DI1_PIN16				0x138 0x480 0x000 0x7 0x0
+#define MX53_PAD_EIM_D24__EMI_WEIM_D_24				0x13c 0x484 0x000 0x0 0x0
+#define MX53_PAD_EIM_D24__GPIO3_24				0x13c 0x484 0x000 0x1 0x0
+#define MX53_PAD_EIM_D24__UART3_TXD_MUX				0x13c 0x484 0x000 0x2 0x0
+#define MX53_PAD_EIM_D24__ECSPI1_SS2				0x13c 0x484 0x7b0 0x3 0x1
+#define MX53_PAD_EIM_D24__CSPI_SS2				0x13c 0x484 0x794 0x4 0x1
+#define MX53_PAD_EIM_D24__AUDMUX_AUD5_RXFS			0x13c 0x484 0x754 0x5 0x1
+#define MX53_PAD_EIM_D24__ECSPI2_SS2				0x13c 0x484 0x000 0x6 0x0
+#define MX53_PAD_EIM_D24__UART1_DTR				0x13c 0x484 0x000 0x7 0x0
+#define MX53_PAD_EIM_D25__EMI_WEIM_D_25				0x140 0x488 0x000 0x0 0x0
+#define MX53_PAD_EIM_D25__GPIO3_25				0x140 0x488 0x000 0x1 0x0
+#define MX53_PAD_EIM_D25__UART3_RXD_MUX				0x140 0x488 0x888 0x2 0x1
+#define MX53_PAD_EIM_D25__ECSPI1_SS3				0x140 0x488 0x7b4 0x3 0x1
+#define MX53_PAD_EIM_D25__CSPI_SS3				0x140 0x488 0x798 0x4 0x1
+#define MX53_PAD_EIM_D25__AUDMUX_AUD5_RXC			0x140 0x488 0x750 0x5 0x1
+#define MX53_PAD_EIM_D25__ECSPI2_SS3				0x140 0x488 0x000 0x6 0x0
+#define MX53_PAD_EIM_D25__UART1_DSR				0x140 0x488 0x000 0x7 0x0
+#define MX53_PAD_EIM_D26__EMI_WEIM_D_26				0x144 0x48c 0x000 0x0 0x0
+#define MX53_PAD_EIM_D26__GPIO3_26				0x144 0x48c 0x000 0x1 0x0
+#define MX53_PAD_EIM_D26__UART2_TXD_MUX				0x144 0x48c 0x000 0x2 0x0
+#define MX53_PAD_EIM_D26__FIRI_RXD				0x144 0x48c 0x80c 0x3 0x0
+#define MX53_PAD_EIM_D26__IPU_CSI0_D_1				0x144 0x48c 0x000 0x4 0x0
+#define MX53_PAD_EIM_D26__IPU_DI1_PIN11				0x144 0x48c 0x000 0x5 0x0
+#define MX53_PAD_EIM_D26__IPU_SISG_2				0x144 0x48c 0x000 0x6 0x0
+#define MX53_PAD_EIM_D26__IPU_DISP1_DAT_22			0x144 0x48c 0x000 0x7 0x0
+#define MX53_PAD_EIM_D27__EMI_WEIM_D_27				0x148 0x490 0x000 0x0 0x0
+#define MX53_PAD_EIM_D27__GPIO3_27				0x148 0x490 0x000 0x1 0x0
+#define MX53_PAD_EIM_D27__UART2_RXD_MUX				0x148 0x490 0x880 0x2 0x1
+#define MX53_PAD_EIM_D27__FIRI_TXD				0x148 0x490 0x000 0x3 0x0
+#define MX53_PAD_EIM_D27__IPU_CSI0_D_0				0x148 0x490 0x000 0x4 0x0
+#define MX53_PAD_EIM_D27__IPU_DI1_PIN13				0x148 0x490 0x000 0x5 0x0
+#define MX53_PAD_EIM_D27__IPU_SISG_3				0x148 0x490 0x000 0x6 0x0
+#define MX53_PAD_EIM_D27__IPU_DISP1_DAT_23			0x148 0x490 0x000 0x7 0x0
+#define MX53_PAD_EIM_D28__EMI_WEIM_D_28				0x14c 0x494 0x000 0x0 0x0
+#define MX53_PAD_EIM_D28__GPIO3_28				0x14c 0x494 0x000 0x1 0x0
+#define MX53_PAD_EIM_D28__UART2_CTS				0x14c 0x494 0x000 0x2 0x0
+#define MX53_PAD_EIM_D28__IPU_DISPB0_SER_DIO			0x14c 0x494 0x82c 0x3 0x1
+#define MX53_PAD_EIM_D28__CSPI_MOSI				0x14c 0x494 0x788 0x4 0x1
+#define MX53_PAD_EIM_D28__I2C1_SDA				0x14c 0x494 0x818 0x5 0x1
+#define MX53_PAD_EIM_D28__IPU_EXT_TRIG				0x14c 0x494 0x000 0x6 0x0
+#define MX53_PAD_EIM_D28__IPU_DI0_PIN13				0x14c 0x494 0x000 0x7 0x0
+#define MX53_PAD_EIM_D29__EMI_WEIM_D_29				0x150 0x498 0x000 0x0 0x0
+#define MX53_PAD_EIM_D29__GPIO3_29				0x150 0x498 0x000 0x1 0x0
+#define MX53_PAD_EIM_D29__UART2_RTS				0x150 0x498 0x87c 0x2 0x1
+#define MX53_PAD_EIM_D29__IPU_DISPB0_SER_RS			0x150 0x498 0x000 0x3 0x0
+#define MX53_PAD_EIM_D29__CSPI_SS0				0x150 0x498 0x78c 0x4 0x2
+#define MX53_PAD_EIM_D29__IPU_DI1_PIN15				0x150 0x498 0x000 0x5 0x0
+#define MX53_PAD_EIM_D29__IPU_CSI1_VSYNC			0x150 0x498 0x83c 0x6 0x0
+#define MX53_PAD_EIM_D29__IPU_DI0_PIN14				0x150 0x498 0x000 0x7 0x0
+#define MX53_PAD_EIM_D30__EMI_WEIM_D_30				0x154 0x49c 0x000 0x0 0x0
+#define MX53_PAD_EIM_D30__GPIO3_30				0x154 0x49c 0x000 0x1 0x0
+#define MX53_PAD_EIM_D30__UART3_CTS				0x154 0x49c 0x000 0x2 0x0
+#define MX53_PAD_EIM_D30__IPU_CSI0_D_3				0x154 0x49c 0x000 0x3 0x0
+#define MX53_PAD_EIM_D30__IPU_DI0_PIN11				0x154 0x49c 0x000 0x4 0x0
+#define MX53_PAD_EIM_D30__IPU_DISP1_DAT_21			0x154 0x49c 0x000 0x5 0x0
+#define MX53_PAD_EIM_D30__USBOH3_USBH1_OC			0x154 0x49c 0x8a0 0x6 0x0
+#define MX53_PAD_EIM_D30__USBOH3_USBH2_OC			0x154 0x49c 0x8a4 0x7 0x1
+#define MX53_PAD_EIM_D31__EMI_WEIM_D_31				0x158 0x4a0 0x000 0x0 0x0
+#define MX53_PAD_EIM_D31__GPIO3_31				0x158 0x4a0 0x000 0x1 0x0
+#define MX53_PAD_EIM_D31__UART3_RTS				0x158 0x4a0 0x884 0x2 0x3
+#define MX53_PAD_EIM_D31__IPU_CSI0_D_2				0x158 0x4a0 0x000 0x3 0x0
+#define MX53_PAD_EIM_D31__IPU_DI0_PIN12				0x158 0x4a0 0x000 0x4 0x0
+#define MX53_PAD_EIM_D31__IPU_DISP1_DAT_20			0x158 0x4a0 0x000 0x5 0x0
+#define MX53_PAD_EIM_D31__USBOH3_USBH1_PWR			0x158 0x4a0 0x000 0x6 0x0
+#define MX53_PAD_EIM_D31__USBOH3_USBH2_PWR			0x158 0x4a0 0x000 0x7 0x0
+#define MX53_PAD_EIM_A24__EMI_WEIM_A_24				0x15c 0x4a8 0x000 0x0 0x0
+#define MX53_PAD_EIM_A24__GPIO5_4				0x15c 0x4a8 0x000 0x1 0x0
+#define MX53_PAD_EIM_A24__IPU_DISP1_DAT_19			0x15c 0x4a8 0x000 0x2 0x0
+#define MX53_PAD_EIM_A24__IPU_CSI1_D_19				0x15c 0x4a8 0x000 0x3 0x0
+#define MX53_PAD_EIM_A24__IPU_SISG_2				0x15c 0x4a8 0x000 0x6 0x0
+#define MX53_PAD_EIM_A24__USBPHY2_BVALID			0x15c 0x4a8 0x000 0x7 0x0
+#define MX53_PAD_EIM_A23__EMI_WEIM_A_23				0x160 0x4ac 0x000 0x0 0x0
+#define MX53_PAD_EIM_A23__GPIO6_6				0x160 0x4ac 0x000 0x1 0x0
+#define MX53_PAD_EIM_A23__IPU_DISP1_DAT_18			0x160 0x4ac 0x000 0x2 0x0
+#define MX53_PAD_EIM_A23__IPU_CSI1_D_18				0x160 0x4ac 0x000 0x3 0x0
+#define MX53_PAD_EIM_A23__IPU_SISG_3				0x160 0x4ac 0x000 0x6 0x0
+#define MX53_PAD_EIM_A23__USBPHY2_ENDSESSION			0x160 0x4ac 0x000 0x7 0x0
+#define MX53_PAD_EIM_A22__EMI_WEIM_A_22				0x164 0x4b0 0x000 0x0 0x0
+#define MX53_PAD_EIM_A22__GPIO2_16				0x164 0x4b0 0x000 0x1 0x0
+#define MX53_PAD_EIM_A22__IPU_DISP1_DAT_17			0x164 0x4b0 0x000 0x2 0x0
+#define MX53_PAD_EIM_A22__IPU_CSI1_D_17				0x164 0x4b0 0x000 0x3 0x0
+#define MX53_PAD_EIM_A22__SRC_BT_CFG1_7				0x164 0x4b0 0x000 0x7 0x0
+#define MX53_PAD_EIM_A21__EMI_WEIM_A_21				0x168 0x4b4 0x000 0x0 0x0
+#define MX53_PAD_EIM_A21__GPIO2_17				0x168 0x4b4 0x000 0x1 0x0
+#define MX53_PAD_EIM_A21__IPU_DISP1_DAT_16			0x168 0x4b4 0x000 0x2 0x0
+#define MX53_PAD_EIM_A21__IPU_CSI1_D_16				0x168 0x4b4 0x000 0x3 0x0
+#define MX53_PAD_EIM_A21__SRC_BT_CFG1_6				0x168 0x4b4 0x000 0x7 0x0
+#define MX53_PAD_EIM_A20__EMI_WEIM_A_20				0x16c 0x4b8 0x000 0x0 0x0
+#define MX53_PAD_EIM_A20__GPIO2_18				0x16c 0x4b8 0x000 0x1 0x0
+#define MX53_PAD_EIM_A20__IPU_DISP1_DAT_15			0x16c 0x4b8 0x000 0x2 0x0
+#define MX53_PAD_EIM_A20__IPU_CSI1_D_15				0x16c 0x4b8 0x000 0x3 0x0
+#define MX53_PAD_EIM_A20__SRC_BT_CFG1_5				0x16c 0x4b8 0x000 0x7 0x0
+#define MX53_PAD_EIM_A19__EMI_WEIM_A_19				0x170 0x4bc 0x000 0x0 0x0
+#define MX53_PAD_EIM_A19__GPIO2_19				0x170 0x4bc 0x000 0x1 0x0
+#define MX53_PAD_EIM_A19__IPU_DISP1_DAT_14			0x170 0x4bc 0x000 0x2 0x0
+#define MX53_PAD_EIM_A19__IPU_CSI1_D_14				0x170 0x4bc 0x000 0x3 0x0
+#define MX53_PAD_EIM_A19__SRC_BT_CFG1_4				0x170 0x4bc 0x000 0x7 0x0
+#define MX53_PAD_EIM_A18__EMI_WEIM_A_18				0x174 0x4c0 0x000 0x0 0x0
+#define MX53_PAD_EIM_A18__GPIO2_20				0x174 0x4c0 0x000 0x1 0x0
+#define MX53_PAD_EIM_A18__IPU_DISP1_DAT_13			0x174 0x4c0 0x000 0x2 0x0
+#define MX53_PAD_EIM_A18__IPU_CSI1_D_13				0x174 0x4c0 0x000 0x3 0x0
+#define MX53_PAD_EIM_A18__SRC_BT_CFG1_3				0x174 0x4c0 0x000 0x7 0x0
+#define MX53_PAD_EIM_A17__EMI_WEIM_A_17				0x178 0x4c4 0x000 0x0 0x0
+#define MX53_PAD_EIM_A17__GPIO2_21				0x178 0x4c4 0x000 0x1 0x0
+#define MX53_PAD_EIM_A17__IPU_DISP1_DAT_12			0x178 0x4c4 0x000 0x2 0x0
+#define MX53_PAD_EIM_A17__IPU_CSI1_D_12				0x178 0x4c4 0x000 0x3 0x0
+#define MX53_PAD_EIM_A17__SRC_BT_CFG1_2				0x178 0x4c4 0x000 0x7 0x0
+#define MX53_PAD_EIM_A16__EMI_WEIM_A_16				0x17c 0x4c8 0x000 0x0 0x0
+#define MX53_PAD_EIM_A16__GPIO2_22				0x17c 0x4c8 0x000 0x1 0x0
+#define MX53_PAD_EIM_A16__IPU_DI1_DISP_CLK			0x17c 0x4c8 0x000 0x2 0x0
+#define MX53_PAD_EIM_A16__IPU_CSI1_PIXCLK			0x17c 0x4c8 0x000 0x3 0x0
+#define MX53_PAD_EIM_A16__SRC_BT_CFG1_1				0x17c 0x4c8 0x000 0x7 0x0
+#define MX53_PAD_EIM_CS0__EMI_WEIM_CS_0				0x180 0x4cc 0x000 0x0 0x0
+#define MX53_PAD_EIM_CS0__GPIO2_23				0x180 0x4cc 0x000 0x1 0x0
+#define MX53_PAD_EIM_CS0__ECSPI2_SCLK				0x180 0x4cc 0x7b8 0x2 0x2
+#define MX53_PAD_EIM_CS0__IPU_DI1_PIN5				0x180 0x4cc 0x000 0x3 0x0
+#define MX53_PAD_EIM_CS1__EMI_WEIM_CS_1				0x184 0x4d0 0x000 0x0 0x0
+#define MX53_PAD_EIM_CS1__GPIO2_24				0x184 0x4d0 0x000 0x1 0x0
+#define MX53_PAD_EIM_CS1__ECSPI2_MOSI				0x184 0x4d0 0x7c0 0x2 0x2
+#define MX53_PAD_EIM_CS1__IPU_DI1_PIN6				0x184 0x4d0 0x000 0x3 0x0
+#define MX53_PAD_EIM_OE__EMI_WEIM_OE				0x188 0x4d4 0x000 0x0 0x0
+#define MX53_PAD_EIM_OE__GPIO2_25				0x188 0x4d4 0x000 0x1 0x0
+#define MX53_PAD_EIM_OE__ECSPI2_MISO				0x188 0x4d4 0x7bc 0x2 0x2
+#define MX53_PAD_EIM_OE__IPU_DI1_PIN7				0x188 0x4d4 0x000 0x3 0x0
+#define MX53_PAD_EIM_OE__USBPHY2_IDDIG				0x188 0x4d4 0x000 0x7 0x0
+#define MX53_PAD_EIM_RW__EMI_WEIM_RW				0x18c 0x4d8 0x000 0x0 0x0
+#define MX53_PAD_EIM_RW__GPIO2_26				0x18c 0x4d8 0x000 0x1 0x0
+#define MX53_PAD_EIM_RW__ECSPI2_SS0				0x18c 0x4d8 0x7c4 0x2 0x2
+#define MX53_PAD_EIM_RW__IPU_DI1_PIN8				0x18c 0x4d8 0x000 0x3 0x0
+#define MX53_PAD_EIM_RW__USBPHY2_HOSTDISCONNECT			0x18c 0x4d8 0x000 0x7 0x0
+#define MX53_PAD_EIM_LBA__EMI_WEIM_LBA				0x190 0x4dc 0x000 0x0 0x0
+#define MX53_PAD_EIM_LBA__GPIO2_27				0x190 0x4dc 0x000 0x1 0x0
+#define MX53_PAD_EIM_LBA__ECSPI2_SS1				0x190 0x4dc 0x7c8 0x2 0x1
+#define MX53_PAD_EIM_LBA__IPU_DI1_PIN17				0x190 0x4dc 0x000 0x3 0x0
+#define MX53_PAD_EIM_LBA__SRC_BT_CFG1_0				0x190 0x4dc 0x000 0x7 0x0
+#define MX53_PAD_EIM_EB0__EMI_WEIM_EB_0				0x194 0x4e4 0x000 0x0 0x0
+#define MX53_PAD_EIM_EB0__GPIO2_28				0x194 0x4e4 0x000 0x1 0x0
+#define MX53_PAD_EIM_EB0__IPU_DISP1_DAT_11			0x194 0x4e4 0x000 0x3 0x0
+#define MX53_PAD_EIM_EB0__IPU_CSI1_D_11				0x194 0x4e4 0x000 0x4 0x0
+#define MX53_PAD_EIM_EB0__GPC_PMIC_RDY				0x194 0x4e4 0x810 0x5 0x0
+#define MX53_PAD_EIM_EB0__SRC_BT_CFG2_7				0x194 0x4e4 0x000 0x7 0x0
+#define MX53_PAD_EIM_EB1__EMI_WEIM_EB_1				0x198 0x4e8 0x000 0x0 0x0
+#define MX53_PAD_EIM_EB1__GPIO2_29				0x198 0x4e8 0x000 0x1 0x0
+#define MX53_PAD_EIM_EB1__IPU_DISP1_DAT_10			0x198 0x4e8 0x000 0x3 0x0
+#define MX53_PAD_EIM_EB1__IPU_CSI1_D_10				0x198 0x4e8 0x000 0x4 0x0
+#define MX53_PAD_EIM_EB1__SRC_BT_CFG2_6				0x198 0x4e8 0x000 0x7 0x0
+#define MX53_PAD_EIM_DA0__EMI_NAND_WEIM_DA_0			0x19c 0x4ec 0x000 0x0 0x0
+#define MX53_PAD_EIM_DA0__GPIO3_0				0x19c 0x4ec 0x000 0x1 0x0
+#define MX53_PAD_EIM_DA0__IPU_DISP1_DAT_9			0x19c 0x4ec 0x000 0x3 0x0
+#define MX53_PAD_EIM_DA0__IPU_CSI1_D_9				0x19c 0x4ec 0x000 0x4 0x0
+#define MX53_PAD_EIM_DA0__SRC_BT_CFG2_5				0x19c 0x4ec 0x000 0x7 0x0
+#define MX53_PAD_EIM_DA1__EMI_NAND_WEIM_DA_1			0x1a0 0x4f0 0x000 0x0 0x0
+#define MX53_PAD_EIM_DA1__GPIO3_1				0x1a0 0x4f0 0x000 0x1 0x0
+#define MX53_PAD_EIM_DA1__IPU_DISP1_DAT_8			0x1a0 0x4f0 0x000 0x3 0x0
+#define MX53_PAD_EIM_DA1__IPU_CSI1_D_8				0x1a0 0x4f0 0x000 0x4 0x0
+#define MX53_PAD_EIM_DA1__SRC_BT_CFG2_4				0x1a0 0x4f0 0x000 0x7 0x0
+#define MX53_PAD_EIM_DA2__EMI_NAND_WEIM_DA_2			0x1a4 0x4f4 0x000 0x0 0x0
+#define MX53_PAD_EIM_DA2__GPIO3_2				0x1a4 0x4f4 0x000 0x1 0x0
+#define MX53_PAD_EIM_DA2__IPU_DISP1_DAT_7			0x1a4 0x4f4 0x000 0x3 0x0
+#define MX53_PAD_EIM_DA2__IPU_CSI1_D_7				0x1a4 0x4f4 0x000 0x4 0x0
+#define MX53_PAD_EIM_DA2__SRC_BT_CFG2_3				0x1a4 0x4f4 0x000 0x7 0x0
+#define MX53_PAD_EIM_DA3__EMI_NAND_WEIM_DA_3			0x1a8 0x4f8 0x000 0x0 0x0
+#define MX53_PAD_EIM_DA3__GPIO3_3				0x1a8 0x4f8 0x000 0x1 0x0
+#define MX53_PAD_EIM_DA3__IPU_DISP1_DAT_6			0x1a8 0x4f8 0x000 0x3 0x0
+#define MX53_PAD_EIM_DA3__IPU_CSI1_D_6				0x1a8 0x4f8 0x000 0x4 0x0
+#define MX53_PAD_EIM_DA3__SRC_BT_CFG2_2				0x1a8 0x4f8 0x000 0x7 0x0
+#define MX53_PAD_EIM_DA4__EMI_NAND_WEIM_DA_4			0x1ac 0x4fc 0x000 0x0 0x0
+#define MX53_PAD_EIM_DA4__GPIO3_4				0x1ac 0x4fc 0x000 0x1 0x0
+#define MX53_PAD_EIM_DA4__IPU_DISP1_DAT_5			0x1ac 0x4fc 0x000 0x3 0x0
+#define MX53_PAD_EIM_DA4__IPU_CSI1_D_5				0x1ac 0x4fc 0x000 0x4 0x0
+#define MX53_PAD_EIM_DA4__SRC_BT_CFG3_7				0x1ac 0x4fc 0x000 0x7 0x0
+#define MX53_PAD_EIM_DA5__EMI_NAND_WEIM_DA_5			0x1b0 0x500 0x000 0x0 0x0
+#define MX53_PAD_EIM_DA5__GPIO3_5				0x1b0 0x500 0x000 0x1 0x0
+#define MX53_PAD_EIM_DA5__IPU_DISP1_DAT_4			0x1b0 0x500 0x000 0x3 0x0
+#define MX53_PAD_EIM_DA5__IPU_CSI1_D_4				0x1b0 0x500 0x000 0x4 0x0
+#define MX53_PAD_EIM_DA5__SRC_BT_CFG3_6				0x1b0 0x500 0x000 0x7 0x0
+#define MX53_PAD_EIM_DA6__EMI_NAND_WEIM_DA_6			0x1b4 0x504 0x000 0x0 0x0
+#define MX53_PAD_EIM_DA6__GPIO3_6				0x1b4 0x504 0x000 0x1 0x0
+#define MX53_PAD_EIM_DA6__IPU_DISP1_DAT_3			0x1b4 0x504 0x000 0x3 0x0
+#define MX53_PAD_EIM_DA6__IPU_CSI1_D_3				0x1b4 0x504 0x000 0x4 0x0
+#define MX53_PAD_EIM_DA6__SRC_BT_CFG3_5				0x1b4 0x504 0x000 0x7 0x0
+#define MX53_PAD_EIM_DA7__EMI_NAND_WEIM_DA_7			0x1b8 0x508 0x000 0x0 0x0
+#define MX53_PAD_EIM_DA7__GPIO3_7				0x1b8 0x508 0x000 0x1 0x0
+#define MX53_PAD_EIM_DA7__IPU_DISP1_DAT_2			0x1b8 0x508 0x000 0x3 0x0
+#define MX53_PAD_EIM_DA7__IPU_CSI1_D_2				0x1b8 0x508 0x000 0x4 0x0
+#define MX53_PAD_EIM_DA7__SRC_BT_CFG3_4				0x1b8 0x508 0x000 0x7 0x0
+#define MX53_PAD_EIM_DA8__EMI_NAND_WEIM_DA_8			0x1bc 0x50c 0x000 0x0 0x0
+#define MX53_PAD_EIM_DA8__GPIO3_8				0x1bc 0x50c 0x000 0x1 0x0
+#define MX53_PAD_EIM_DA8__IPU_DISP1_DAT_1			0x1bc 0x50c 0x000 0x3 0x0
+#define MX53_PAD_EIM_DA8__IPU_CSI1_D_1				0x1bc 0x50c 0x000 0x4 0x0
+#define MX53_PAD_EIM_DA8__SRC_BT_CFG3_3				0x1bc 0x50c 0x000 0x7 0x0
+#define MX53_PAD_EIM_DA9__EMI_NAND_WEIM_DA_9			0x1c0 0x510 0x000 0x0 0x0
+#define MX53_PAD_EIM_DA9__GPIO3_9				0x1c0 0x510 0x000 0x1 0x0
+#define MX53_PAD_EIM_DA9__IPU_DISP1_DAT_0			0x1c0 0x510 0x000 0x3 0x0
+#define MX53_PAD_EIM_DA9__IPU_CSI1_D_0				0x1c0 0x510 0x000 0x4 0x0
+#define MX53_PAD_EIM_DA9__SRC_BT_CFG3_2				0x1c0 0x510 0x000 0x7 0x0
+#define MX53_PAD_EIM_DA10__EMI_NAND_WEIM_DA_10			0x1c4 0x514 0x000 0x0 0x0
+#define MX53_PAD_EIM_DA10__GPIO3_10				0x1c4 0x514 0x000 0x1 0x0
+#define MX53_PAD_EIM_DA10__IPU_DI1_PIN15			0x1c4 0x514 0x000 0x3 0x0
+#define MX53_PAD_EIM_DA10__IPU_CSI1_DATA_EN			0x1c4 0x514 0x834 0x4 0x1
+#define MX53_PAD_EIM_DA10__SRC_BT_CFG3_1			0x1c4 0x514 0x000 0x7 0x0
+#define MX53_PAD_EIM_DA11__EMI_NAND_WEIM_DA_11			0x1c8 0x518 0x000 0x0 0x0
+#define MX53_PAD_EIM_DA11__GPIO3_11				0x1c8 0x518 0x000 0x1 0x0
+#define MX53_PAD_EIM_DA11__IPU_DI1_PIN2				0x1c8 0x518 0x000 0x3 0x0
+#define MX53_PAD_EIM_DA11__IPU_CSI1_HSYNC			0x1c8 0x518 0x838 0x4 0x1
+#define MX53_PAD_EIM_DA12__EMI_NAND_WEIM_DA_12			0x1cc 0x51c 0x000 0x0 0x0
+#define MX53_PAD_EIM_DA12__GPIO3_12				0x1cc 0x51c 0x000 0x1 0x0
+#define MX53_PAD_EIM_DA12__IPU_DI1_PIN3				0x1cc 0x51c 0x000 0x3 0x0
+#define MX53_PAD_EIM_DA12__IPU_CSI1_VSYNC			0x1cc 0x51c 0x83c 0x4 0x1
+#define MX53_PAD_EIM_DA13__EMI_NAND_WEIM_DA_13			0x1d0 0x520 0x000 0x0 0x0
+#define MX53_PAD_EIM_DA13__GPIO3_13				0x1d0 0x520 0x000 0x1 0x0
+#define MX53_PAD_EIM_DA13__IPU_DI1_D0_CS			0x1d0 0x520 0x000 0x3 0x0
+#define MX53_PAD_EIM_DA13__CCM_DI1_EXT_CLK			0x1d0 0x520 0x76c 0x4 0x1
+#define MX53_PAD_EIM_DA14__EMI_NAND_WEIM_DA_14			0x1d4 0x524 0x000 0x0 0x0
+#define MX53_PAD_EIM_DA14__GPIO3_14				0x1d4 0x524 0x000 0x1 0x0
+#define MX53_PAD_EIM_DA14__IPU_DI1_D1_CS			0x1d4 0x524 0x000 0x3 0x0
+#define MX53_PAD_EIM_DA14__CCM_DI0_EXT_CLK			0x1d4 0x524 0x000 0x4 0x0
+#define MX53_PAD_EIM_DA15__EMI_NAND_WEIM_DA_15			0x1d8 0x528 0x000 0x0 0x0
+#define MX53_PAD_EIM_DA15__GPIO3_15				0x1d8 0x528 0x000 0x1 0x0
+#define MX53_PAD_EIM_DA15__IPU_DI1_PIN1				0x1d8 0x528 0x000 0x3 0x0
+#define MX53_PAD_EIM_DA15__IPU_DI1_PIN4				0x1d8 0x528 0x000 0x4 0x0
+#define MX53_PAD_NANDF_WE_B__EMI_NANDF_WE_B			0x1dc 0x52c 0x000 0x0 0x0
+#define MX53_PAD_NANDF_WE_B__GPIO6_12				0x1dc 0x52c 0x000 0x1 0x0
+#define MX53_PAD_NANDF_RE_B__EMI_NANDF_RE_B			0x1e0 0x530 0x000 0x0 0x0
+#define MX53_PAD_NANDF_RE_B__GPIO6_13				0x1e0 0x530 0x000 0x1 0x0
+#define MX53_PAD_EIM_WAIT__EMI_WEIM_WAIT			0x1e4 0x534 0x000 0x0 0x0
+#define MX53_PAD_EIM_WAIT__GPIO5_0				0x1e4 0x534 0x000 0x1 0x0
+#define MX53_PAD_EIM_WAIT__EMI_WEIM_DTACK_B			0x1e4 0x534 0x000 0x2 0x0
+#define MX53_PAD_LVDS1_TX3_P__GPIO6_22				0x1ec 0x000 0x000 0x0 0x0
+#define MX53_PAD_LVDS1_TX3_P__LDB_LVDS1_TX3			0x1ec 0x000 0x000 0x1 0x0
+#define MX53_PAD_LVDS1_TX2_P__GPIO6_24				0x1f0 0x000 0x000 0x0 0x0
+#define MX53_PAD_LVDS1_TX2_P__LDB_LVDS1_TX2			0x1f0 0x000 0x000 0x1 0x0
+#define MX53_PAD_LVDS1_CLK_P__GPIO6_26				0x1f4 0x000 0x000 0x0 0x0
+#define MX53_PAD_LVDS1_CLK_P__LDB_LVDS1_CLK			0x1f4 0x000 0x000 0x1 0x0
+#define MX53_PAD_LVDS1_TX1_P__GPIO6_28				0x1f8 0x000 0x000 0x0 0x0
+#define MX53_PAD_LVDS1_TX1_P__LDB_LVDS1_TX1			0x1f8 0x000 0x000 0x1 0x0
+#define MX53_PAD_LVDS1_TX0_P__GPIO6_30				0x1fc 0x000 0x000 0x0 0x0
+#define MX53_PAD_LVDS1_TX0_P__LDB_LVDS1_TX0			0x1fc 0x000 0x000 0x1 0x0
+#define MX53_PAD_LVDS0_TX3_P__GPIO7_22				0x200 0x000 0x000 0x0 0x0
+#define MX53_PAD_LVDS0_TX3_P__LDB_LVDS0_TX3			0x200 0x000 0x000 0x1 0x0
+#define MX53_PAD_LVDS0_CLK_P__GPIO7_24				0x204 0x000 0x000 0x0 0x0
+#define MX53_PAD_LVDS0_CLK_P__LDB_LVDS0_CLK			0x204 0x000 0x000 0x1 0x0
+#define MX53_PAD_LVDS0_TX2_P__GPIO7_26				0x208 0x000 0x000 0x0 0x0
+#define MX53_PAD_LVDS0_TX2_P__LDB_LVDS0_TX2			0x208 0x000 0x000 0x1 0x0
+#define MX53_PAD_LVDS0_TX1_P__GPIO7_28				0x20c 0x000 0x000 0x0 0x0
+#define MX53_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1			0x20c 0x000 0x000 0x1 0x0
+#define MX53_PAD_LVDS0_TX0_P__GPIO7_30				0x210 0x000 0x000 0x0 0x0
+#define MX53_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0			0x210 0x000 0x000 0x1 0x0
+#define MX53_PAD_GPIO_10__GPIO4_0				0x214 0x540 0x000 0x0 0x0
+#define MX53_PAD_GPIO_10__OSC32k_32K_OUT			0x214 0x540 0x000 0x1 0x0
+#define MX53_PAD_GPIO_11__GPIO4_1				0x218 0x544 0x000 0x0 0x0
+#define MX53_PAD_GPIO_12__GPIO4_2				0x21c 0x548 0x000 0x0 0x0
+#define MX53_PAD_GPIO_13__GPIO4_3				0x220 0x54c 0x000 0x0 0x0
+#define MX53_PAD_GPIO_14__GPIO4_4				0x224 0x550 0x000 0x0 0x0
+#define MX53_PAD_NANDF_CLE__EMI_NANDF_CLE			0x228 0x5a0 0x000 0x0 0x0
+#define MX53_PAD_NANDF_CLE__GPIO6_7				0x228 0x5a0 0x000 0x1 0x0
+#define MX53_PAD_NANDF_CLE__USBPHY1_VSTATUS_0			0x228 0x5a0 0x000 0x7 0x0
+#define MX53_PAD_NANDF_ALE__EMI_NANDF_ALE			0x22c 0x5a4 0x000 0x0 0x0
+#define MX53_PAD_NANDF_ALE__GPIO6_8				0x22c 0x5a4 0x000 0x1 0x0
+#define MX53_PAD_NANDF_ALE__USBPHY1_VSTATUS_1			0x22c 0x5a4 0x000 0x7 0x0
+#define MX53_PAD_NANDF_WP_B__EMI_NANDF_WP_B			0x230 0x5a8 0x000 0x0 0x0
+#define MX53_PAD_NANDF_WP_B__GPIO6_9				0x230 0x5a8 0x000 0x1 0x0
+#define MX53_PAD_NANDF_WP_B__USBPHY1_VSTATUS_2			0x230 0x5a8 0x000 0x7 0x0
+#define MX53_PAD_NANDF_RB0__EMI_NANDF_RB_0			0x234 0x5ac 0x000 0x0 0x0
+#define MX53_PAD_NANDF_RB0__GPIO6_10				0x234 0x5ac 0x000 0x1 0x0
+#define MX53_PAD_NANDF_RB0__USBPHY1_VSTATUS_3			0x234 0x5ac 0x000 0x7 0x0
+#define MX53_PAD_NANDF_CS0__EMI_NANDF_CS_0			0x238 0x5b0 0x000 0x0 0x0
+#define MX53_PAD_NANDF_CS0__GPIO6_11				0x238 0x5b0 0x000 0x1 0x0
+#define MX53_PAD_NANDF_CS0__USBPHY1_VSTATUS_4			0x238 0x5b0 0x000 0x7 0x0
+#define MX53_PAD_NANDF_CS1__EMI_NANDF_CS_1			0x23c 0x5b4 0x000 0x0 0x0
+#define MX53_PAD_NANDF_CS1__GPIO6_14				0x23c 0x5b4 0x000 0x1 0x0
+#define MX53_PAD_NANDF_CS1__MLB_MLBCLK				0x23c 0x5b4 0x858 0x6 0x0
+#define MX53_PAD_NANDF_CS1__USBPHY1_VSTATUS_5			0x23c 0x5b4 0x000 0x7 0x0
+#define MX53_PAD_NANDF_CS2__EMI_NANDF_CS_2			0x240 0x5b8 0x000 0x0 0x0
+#define MX53_PAD_NANDF_CS2__GPIO6_15				0x240 0x5b8 0x000 0x1 0x0
+#define MX53_PAD_NANDF_CS2__IPU_SISG_0				0x240 0x5b8 0x000 0x2 0x0
+#define MX53_PAD_NANDF_CS2__ESAI1_TX0				0x240 0x5b8 0x7e4 0x3 0x0
+#define MX53_PAD_NANDF_CS2__EMI_WEIM_CRE			0x240 0x5b8 0x000 0x4 0x0
+#define MX53_PAD_NANDF_CS2__CCM_CSI0_MCLK			0x240 0x5b8 0x000 0x5 0x0
+#define MX53_PAD_NANDF_CS2__MLB_MLBSIG				0x240 0x5b8 0x860 0x6 0x0
+#define MX53_PAD_NANDF_CS2__USBPHY1_VSTATUS_6			0x240 0x5b8 0x000 0x7 0x0
+#define MX53_PAD_NANDF_CS3__EMI_NANDF_CS_3			0x244 0x5bc 0x000 0x0 0x0
+#define MX53_PAD_NANDF_CS3__GPIO6_16				0x244 0x5bc 0x000 0x1 0x0
+#define MX53_PAD_NANDF_CS3__IPU_SISG_1				0x244 0x5bc 0x000 0x2 0x0
+#define MX53_PAD_NANDF_CS3__ESAI1_TX1				0x244 0x5bc 0x7e8 0x3 0x0
+#define MX53_PAD_NANDF_CS3__EMI_WEIM_A_26			0x244 0x5bc 0x000 0x4 0x0
+#define MX53_PAD_NANDF_CS3__MLB_MLBDAT				0x244 0x5bc 0x85c 0x6 0x0
+#define MX53_PAD_NANDF_CS3__USBPHY1_VSTATUS_7			0x244 0x5bc 0x000 0x7 0x0
+#define MX53_PAD_FEC_MDIO__FEC_MDIO				0x248 0x5c4 0x804 0x0 0x1
+#define MX53_PAD_FEC_MDIO__GPIO1_22				0x248 0x5c4 0x000 0x1 0x0
+#define MX53_PAD_FEC_MDIO__ESAI1_SCKR				0x248 0x5c4 0x7dc 0x2 0x0
+#define MX53_PAD_FEC_MDIO__FEC_COL				0x248 0x5c4 0x800 0x3 0x1
+#define MX53_PAD_FEC_MDIO__RTC_CE_RTC_PS2			0x248 0x5c4 0x000 0x4 0x0
+#define MX53_PAD_FEC_MDIO__SDMA_DEBUG_BUS_DEVICE_3		0x248 0x5c4 0x000 0x5 0x0
+#define MX53_PAD_FEC_MDIO__EMI_EMI_DEBUG_49			0x248 0x5c4 0x000 0x6 0x0
+#define MX53_PAD_FEC_REF_CLK__FEC_TX_CLK			0x24c 0x5c8 0x000 0x0 0x0
+#define MX53_PAD_FEC_REF_CLK__GPIO1_23				0x24c 0x5c8 0x000 0x1 0x0
+#define MX53_PAD_FEC_REF_CLK__ESAI1_FSR				0x24c 0x5c8 0x7cc 0x2 0x0
+#define MX53_PAD_FEC_REF_CLK__SDMA_DEBUG_BUS_DEVICE_4		0x24c 0x5c8 0x000 0x5 0x0
+#define MX53_PAD_FEC_REF_CLK__EMI_EMI_DEBUG_50			0x24c 0x5c8 0x000 0x6 0x0
+#define MX53_PAD_FEC_RX_ER__FEC_RX_ER				0x250 0x5cc 0x000 0x0 0x0
+#define MX53_PAD_FEC_RX_ER__GPIO1_24				0x250 0x5cc 0x000 0x1 0x0
+#define MX53_PAD_FEC_RX_ER__ESAI1_HCKR				0x250 0x5cc 0x7d4 0x2 0x0
+#define MX53_PAD_FEC_RX_ER__FEC_RX_CLK				0x250 0x5cc 0x808 0x3 0x1
+#define MX53_PAD_FEC_RX_ER__RTC_CE_RTC_PS3			0x250 0x5cc 0x000 0x4 0x0
+#define MX53_PAD_FEC_CRS_DV__FEC_RX_DV				0x254 0x5d0 0x000 0x0 0x0
+#define MX53_PAD_FEC_CRS_DV__GPIO1_25				0x254 0x5d0 0x000 0x1 0x0
+#define MX53_PAD_FEC_CRS_DV__ESAI1_SCKT				0x254 0x5d0 0x7e0 0x2 0x0
+#define MX53_PAD_FEC_RXD1__FEC_RDATA_1				0x258 0x5d4 0x000 0x0 0x0
+#define MX53_PAD_FEC_RXD1__GPIO1_26				0x258 0x5d4 0x000 0x1 0x0
+#define MX53_PAD_FEC_RXD1__ESAI1_FST				0x258 0x5d4 0x7d0 0x2 0x0
+#define MX53_PAD_FEC_RXD1__MLB_MLBSIG				0x258 0x5d4 0x860 0x3 0x1
+#define MX53_PAD_FEC_RXD1__RTC_CE_RTC_PS1			0x258 0x5d4 0x000 0x4 0x0
+#define MX53_PAD_FEC_RXD0__FEC_RDATA_0				0x25c 0x5d8 0x000 0x0 0x0
+#define MX53_PAD_FEC_RXD0__GPIO1_27				0x25c 0x5d8 0x000 0x1 0x0
+#define MX53_PAD_FEC_RXD0__ESAI1_HCKT				0x25c 0x5d8 0x7d8 0x2 0x0
+#define MX53_PAD_FEC_RXD0__OSC32k_32K_OUT			0x25c 0x5d8 0x000 0x3 0x0
+#define MX53_PAD_FEC_TX_EN__FEC_TX_EN				0x260 0x5dc 0x000 0x0 0x0
+#define MX53_PAD_FEC_TX_EN__GPIO1_28				0x260 0x5dc 0x000 0x1 0x0
+#define MX53_PAD_FEC_TX_EN__ESAI1_TX3_RX2			0x260 0x5dc 0x7f0 0x2 0x0
+#define MX53_PAD_FEC_TXD1__FEC_TDATA_1				0x264 0x5e0 0x000 0x0 0x0
+#define MX53_PAD_FEC_TXD1__GPIO1_29				0x264 0x5e0 0x000 0x1 0x0
+#define MX53_PAD_FEC_TXD1__ESAI1_TX2_RX3			0x264 0x5e0 0x7ec 0x2 0x0
+#define MX53_PAD_FEC_TXD1__MLB_MLBCLK				0x264 0x5e0 0x858 0x3 0x1
+#define MX53_PAD_FEC_TXD1__RTC_CE_RTC_PRSC_CLK			0x264 0x5e0 0x000 0x4 0x0
+#define MX53_PAD_FEC_TXD0__FEC_TDATA_0				0x268 0x5e4 0x000 0x0 0x0
+#define MX53_PAD_FEC_TXD0__GPIO1_30				0x268 0x5e4 0x000 0x1 0x0
+#define MX53_PAD_FEC_TXD0__ESAI1_TX4_RX1			0x268 0x5e4 0x7f4 0x2 0x0
+#define MX53_PAD_FEC_TXD0__USBPHY2_DATAOUT_0			0x268 0x5e4 0x000 0x7 0x0
+#define MX53_PAD_FEC_MDC__FEC_MDC				0x26c 0x5e8 0x000 0x0 0x0
+#define MX53_PAD_FEC_MDC__GPIO1_31				0x26c 0x5e8 0x000 0x1 0x0
+#define MX53_PAD_FEC_MDC__ESAI1_TX5_RX0				0x26c 0x5e8 0x7f8 0x2 0x0
+#define MX53_PAD_FEC_MDC__MLB_MLBDAT				0x26c 0x5e8 0x85c 0x3 0x1
+#define MX53_PAD_FEC_MDC__RTC_CE_RTC_ALARM1_TRIG		0x26c 0x5e8 0x000 0x4 0x0
+#define MX53_PAD_FEC_MDC__USBPHY2_DATAOUT_1			0x26c 0x5e8 0x000 0x7 0x0
+#define MX53_PAD_PATA_DIOW__PATA_DIOW				0x270 0x5f0 0x000 0x0 0x0
+#define MX53_PAD_PATA_DIOW__GPIO6_17				0x270 0x5f0 0x000 0x1 0x0
+#define MX53_PAD_PATA_DIOW__UART1_TXD_MUX			0x270 0x5f0 0x000 0x3 0x0
+#define MX53_PAD_PATA_DIOW__USBPHY2_DATAOUT_2			0x270 0x5f0 0x000 0x7 0x0
+#define MX53_PAD_PATA_DMACK__PATA_DMACK				0x274 0x5f4 0x000 0x0 0x0
+#define MX53_PAD_PATA_DMACK__GPIO6_18				0x274 0x5f4 0x000 0x1 0x0
+#define MX53_PAD_PATA_DMACK__UART1_RXD_MUX			0x274 0x5f4 0x878 0x3 0x3
+#define MX53_PAD_PATA_DMACK__USBPHY2_DATAOUT_3			0x274 0x5f4 0x000 0x7 0x0
+#define MX53_PAD_PATA_DMARQ__PATA_DMARQ				0x278 0x5f8 0x000 0x0 0x0
+#define MX53_PAD_PATA_DMARQ__GPIO7_0				0x278 0x5f8 0x000 0x1 0x0
+#define MX53_PAD_PATA_DMARQ__UART2_TXD_MUX			0x278 0x5f8 0x000 0x3 0x0
+#define MX53_PAD_PATA_DMARQ__CCM_CCM_OUT_0			0x278 0x5f8 0x000 0x5 0x0
+#define MX53_PAD_PATA_DMARQ__USBPHY2_DATAOUT_4			0x278 0x5f8 0x000 0x7 0x0
+#define MX53_PAD_PATA_BUFFER_EN__PATA_BUFFER_EN			0x27c 0x5fc 0x000 0x0 0x0
+#define MX53_PAD_PATA_BUFFER_EN__GPIO7_1			0x27c 0x5fc 0x000 0x1 0x0
+#define MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX			0x27c 0x5fc 0x880 0x3 0x3
+#define MX53_PAD_PATA_BUFFER_EN__CCM_CCM_OUT_1			0x27c 0x5fc 0x000 0x5 0x0
+#define MX53_PAD_PATA_BUFFER_EN__USBPHY2_DATAOUT_5		0x27c 0x5fc 0x000 0x7 0x0
+#define MX53_PAD_PATA_INTRQ__PATA_INTRQ				0x280 0x600 0x000 0x0 0x0
+#define MX53_PAD_PATA_INTRQ__GPIO7_2				0x280 0x600 0x000 0x1 0x0
+#define MX53_PAD_PATA_INTRQ__UART2_CTS				0x280 0x600 0x000 0x3 0x0
+#define MX53_PAD_PATA_INTRQ__CAN1_TXCAN				0x280 0x600 0x000 0x4 0x0
+#define MX53_PAD_PATA_INTRQ__CCM_CCM_OUT_2			0x280 0x600 0x000 0x5 0x0
+#define MX53_PAD_PATA_INTRQ__USBPHY2_DATAOUT_6			0x280 0x600 0x000 0x7 0x0
+#define MX53_PAD_PATA_DIOR__PATA_DIOR				0x284 0x604 0x000 0x0 0x0
+#define MX53_PAD_PATA_DIOR__GPIO7_3				0x284 0x604 0x000 0x1 0x0
+#define MX53_PAD_PATA_DIOR__UART2_RTS				0x284 0x604 0x87c 0x3 0x3
+#define MX53_PAD_PATA_DIOR__CAN1_RXCAN				0x284 0x604 0x760 0x4 0x1
+#define MX53_PAD_PATA_DIOR__USBPHY2_DATAOUT_7			0x284 0x604 0x000 0x7 0x0
+#define MX53_PAD_PATA_RESET_B__PATA_PATA_RESET_B		0x288 0x608 0x000 0x0 0x0
+#define MX53_PAD_PATA_RESET_B__GPIO7_4				0x288 0x608 0x000 0x1 0x0
+#define MX53_PAD_PATA_RESET_B__ESDHC3_CMD			0x288 0x608 0x000 0x2 0x0
+#define MX53_PAD_PATA_RESET_B__UART1_CTS			0x288 0x608 0x000 0x3 0x0
+#define MX53_PAD_PATA_RESET_B__CAN2_TXCAN			0x288 0x608 0x000 0x4 0x0
+#define MX53_PAD_PATA_RESET_B__USBPHY1_DATAOUT_0		0x288 0x608 0x000 0x7 0x0
+#define MX53_PAD_PATA_IORDY__PATA_IORDY				0x28c 0x60c 0x000 0x0 0x0
+#define MX53_PAD_PATA_IORDY__GPIO7_5				0x28c 0x60c 0x000 0x1 0x0
+#define MX53_PAD_PATA_IORDY__ESDHC3_CLK				0x28c 0x60c 0x000 0x2 0x0
+#define MX53_PAD_PATA_IORDY__UART1_RTS				0x28c 0x60c 0x874 0x3 0x3
+#define MX53_PAD_PATA_IORDY__CAN2_RXCAN				0x28c 0x60c 0x764 0x4 0x1
+#define MX53_PAD_PATA_IORDY__USBPHY1_DATAOUT_1			0x28c 0x60c 0x000 0x7 0x0
+#define MX53_PAD_PATA_DA_0__PATA_DA_0				0x290 0x610 0x000 0x0 0x0
+#define MX53_PAD_PATA_DA_0__GPIO7_6				0x290 0x610 0x000 0x1 0x0
+#define MX53_PAD_PATA_DA_0__ESDHC3_RST				0x290 0x610 0x000 0x2 0x0
+#define MX53_PAD_PATA_DA_0__OWIRE_LINE				0x290 0x610 0x864 0x4 0x0
+#define MX53_PAD_PATA_DA_0__USBPHY1_DATAOUT_2			0x290 0x610 0x000 0x7 0x0
+#define MX53_PAD_PATA_DA_1__PATA_DA_1				0x294 0x614 0x000 0x0 0x0
+#define MX53_PAD_PATA_DA_1__GPIO7_7				0x294 0x614 0x000 0x1 0x0
+#define MX53_PAD_PATA_DA_1__ESDHC4_CMD				0x294 0x614 0x000 0x2 0x0
+#define MX53_PAD_PATA_DA_1__UART3_CTS				0x294 0x614 0x000 0x4 0x0
+#define MX53_PAD_PATA_DA_1__USBPHY1_DATAOUT_3			0x294 0x614 0x000 0x7 0x0
+#define MX53_PAD_PATA_DA_2__PATA_DA_2				0x298 0x618 0x000 0x0 0x0
+#define MX53_PAD_PATA_DA_2__GPIO7_8				0x298 0x618 0x000 0x1 0x0
+#define MX53_PAD_PATA_DA_2__ESDHC4_CLK				0x298 0x618 0x000 0x2 0x0
+#define MX53_PAD_PATA_DA_2__UART3_RTS				0x298 0x618 0x884 0x4 0x5
+#define MX53_PAD_PATA_DA_2__USBPHY1_DATAOUT_4			0x298 0x618 0x000 0x7 0x0
+#define MX53_PAD_PATA_CS_0__PATA_CS_0				0x29c 0x61c 0x000 0x0 0x0
+#define MX53_PAD_PATA_CS_0__GPIO7_9				0x29c 0x61c 0x000 0x1 0x0
+#define MX53_PAD_PATA_CS_0__UART3_TXD_MUX			0x29c 0x61c 0x000 0x4 0x0
+#define MX53_PAD_PATA_CS_0__USBPHY1_DATAOUT_5			0x29c 0x61c 0x000 0x7 0x0
+#define MX53_PAD_PATA_CS_1__PATA_CS_1				0x2a0 0x620 0x000 0x0 0x0
+#define MX53_PAD_PATA_CS_1__GPIO7_10				0x2a0 0x620 0x000 0x1 0x0
+#define MX53_PAD_PATA_CS_1__UART3_RXD_MUX			0x2a0 0x620 0x888 0x4 0x3
+#define MX53_PAD_PATA_CS_1__USBPHY1_DATAOUT_6			0x2a0 0x620 0x000 0x7 0x0
+#define MX53_PAD_PATA_DATA0__PATA_DATA_0			0x2a4 0x628 0x000 0x0 0x0
+#define MX53_PAD_PATA_DATA0__GPIO2_0				0x2a4 0x628 0x000 0x1 0x0
+#define MX53_PAD_PATA_DATA0__EMI_NANDF_D_0			0x2a4 0x628 0x000 0x3 0x0
+#define MX53_PAD_PATA_DATA0__ESDHC3_DAT4			0x2a4 0x628 0x000 0x4 0x0
+#define MX53_PAD_PATA_DATA0__GPU3d_GPU_DEBUG_OUT_0		0x2a4 0x628 0x000 0x5 0x0
+#define MX53_PAD_PATA_DATA0__IPU_DIAG_BUS_0			0x2a4 0x628 0x000 0x6 0x0
+#define MX53_PAD_PATA_DATA0__USBPHY1_DATAOUT_7			0x2a4 0x628 0x000 0x7 0x0
+#define MX53_PAD_PATA_DATA1__PATA_DATA_1			0x2a8 0x62c 0x000 0x0 0x0
+#define MX53_PAD_PATA_DATA1__GPIO2_1				0x2a8 0x62c 0x000 0x1 0x0
+#define MX53_PAD_PATA_DATA1__EMI_NANDF_D_1			0x2a8 0x62c 0x000 0x3 0x0
+#define MX53_PAD_PATA_DATA1__ESDHC3_DAT5			0x2a8 0x62c 0x000 0x4 0x0
+#define MX53_PAD_PATA_DATA1__GPU3d_GPU_DEBUG_OUT_1		0x2a8 0x62c 0x000 0x5 0x0
+#define MX53_PAD_PATA_DATA1__IPU_DIAG_BUS_1			0x2a8 0x62c 0x000 0x6 0x0
+#define MX53_PAD_PATA_DATA2__PATA_DATA_2			0x2ac 0x630 0x000 0x0 0x0
+#define MX53_PAD_PATA_DATA2__GPIO2_2				0x2ac 0x630 0x000 0x1 0x0
+#define MX53_PAD_PATA_DATA2__EMI_NANDF_D_2			0x2ac 0x630 0x000 0x3 0x0
+#define MX53_PAD_PATA_DATA2__ESDHC3_DAT6			0x2ac 0x630 0x000 0x4 0x0
+#define MX53_PAD_PATA_DATA2__GPU3d_GPU_DEBUG_OUT_2		0x2ac 0x630 0x000 0x5 0x0
+#define MX53_PAD_PATA_DATA2__IPU_DIAG_BUS_2			0x2ac 0x630 0x000 0x6 0x0
+#define MX53_PAD_PATA_DATA3__PATA_DATA_3			0x2b0 0x634 0x000 0x0 0x0
+#define MX53_PAD_PATA_DATA3__GPIO2_3				0x2b0 0x634 0x000 0x1 0x0
+#define MX53_PAD_PATA_DATA3__EMI_NANDF_D_3			0x2b0 0x634 0x000 0x3 0x0
+#define MX53_PAD_PATA_DATA3__ESDHC3_DAT7			0x2b0 0x634 0x000 0x4 0x0
+#define MX53_PAD_PATA_DATA3__GPU3d_GPU_DEBUG_OUT_3		0x2b0 0x634 0x000 0x5 0x0
+#define MX53_PAD_PATA_DATA3__IPU_DIAG_BUS_3			0x2b0 0x634 0x000 0x6 0x0
+#define MX53_PAD_PATA_DATA4__PATA_DATA_4			0x2b4 0x638 0x000 0x0 0x0
+#define MX53_PAD_PATA_DATA4__GPIO2_4				0x2b4 0x638 0x000 0x1 0x0
+#define MX53_PAD_PATA_DATA4__EMI_NANDF_D_4			0x2b4 0x638 0x000 0x3 0x0
+#define MX53_PAD_PATA_DATA4__ESDHC4_DAT4			0x2b4 0x638 0x000 0x4 0x0
+#define MX53_PAD_PATA_DATA4__GPU3d_GPU_DEBUG_OUT_4		0x2b4 0x638 0x000 0x5 0x0
+#define MX53_PAD_PATA_DATA4__IPU_DIAG_BUS_4			0x2b4 0x638 0x000 0x6 0x0
+#define MX53_PAD_PATA_DATA5__PATA_DATA_5			0x2b8 0x63c 0x000 0x0 0x0
+#define MX53_PAD_PATA_DATA5__GPIO2_5				0x2b8 0x63c 0x000 0x1 0x0
+#define MX53_PAD_PATA_DATA5__EMI_NANDF_D_5			0x2b8 0x63c 0x000 0x3 0x0
+#define MX53_PAD_PATA_DATA5__ESDHC4_DAT5			0x2b8 0x63c 0x000 0x4 0x0
+#define MX53_PAD_PATA_DATA5__GPU3d_GPU_DEBUG_OUT_5		0x2b8 0x63c 0x000 0x5 0x0
+#define MX53_PAD_PATA_DATA5__IPU_DIAG_BUS_5			0x2b8 0x63c 0x000 0x6 0x0
+#define MX53_PAD_PATA_DATA6__PATA_DATA_6			0x2bc 0x640 0x000 0x0 0x0
+#define MX53_PAD_PATA_DATA6__GPIO2_6				0x2bc 0x640 0x000 0x1 0x0
+#define MX53_PAD_PATA_DATA6__EMI_NANDF_D_6			0x2bc 0x640 0x000 0x3 0x0
+#define MX53_PAD_PATA_DATA6__ESDHC4_DAT6			0x2bc 0x640 0x000 0x4 0x0
+#define MX53_PAD_PATA_DATA6__GPU3d_GPU_DEBUG_OUT_6		0x2bc 0x640 0x000 0x5 0x0
+#define MX53_PAD_PATA_DATA6__IPU_DIAG_BUS_6			0x2bc 0x640 0x000 0x6 0x0
+#define MX53_PAD_PATA_DATA7__PATA_DATA_7			0x2c0 0x644 0x000 0x0 0x0
+#define MX53_PAD_PATA_DATA7__GPIO2_7				0x2c0 0x644 0x000 0x1 0x0
+#define MX53_PAD_PATA_DATA7__EMI_NANDF_D_7			0x2c0 0x644 0x000 0x3 0x0
+#define MX53_PAD_PATA_DATA7__ESDHC4_DAT7			0x2c0 0x644 0x000 0x4 0x0
+#define MX53_PAD_PATA_DATA7__GPU3d_GPU_DEBUG_OUT_7		0x2c0 0x644 0x000 0x5 0x0
+#define MX53_PAD_PATA_DATA7__IPU_DIAG_BUS_7			0x2c0 0x644 0x000 0x6 0x0
+#define MX53_PAD_PATA_DATA8__PATA_DATA_8			0x2c4 0x648 0x000 0x0 0x0
+#define MX53_PAD_PATA_DATA8__GPIO2_8				0x2c4 0x648 0x000 0x1 0x0
+#define MX53_PAD_PATA_DATA8__ESDHC1_DAT4			0x2c4 0x648 0x000 0x2 0x0
+#define MX53_PAD_PATA_DATA8__EMI_NANDF_D_8			0x2c4 0x648 0x000 0x3 0x0
+#define MX53_PAD_PATA_DATA8__ESDHC3_DAT0			0x2c4 0x648 0x000 0x4 0x0
+#define MX53_PAD_PATA_DATA8__GPU3d_GPU_DEBUG_OUT_8		0x2c4 0x648 0x000 0x5 0x0
+#define MX53_PAD_PATA_DATA8__IPU_DIAG_BUS_8			0x2c4 0x648 0x000 0x6 0x0
+#define MX53_PAD_PATA_DATA9__PATA_DATA_9			0x2c8 0x64c 0x000 0x0 0x0
+#define MX53_PAD_PATA_DATA9__GPIO2_9				0x2c8 0x64c 0x000 0x1 0x0
+#define MX53_PAD_PATA_DATA9__ESDHC1_DAT5			0x2c8 0x64c 0x000 0x2 0x0
+#define MX53_PAD_PATA_DATA9__EMI_NANDF_D_9			0x2c8 0x64c 0x000 0x3 0x0
+#define MX53_PAD_PATA_DATA9__ESDHC3_DAT1			0x2c8 0x64c 0x000 0x4 0x0
+#define MX53_PAD_PATA_DATA9__GPU3d_GPU_DEBUG_OUT_9		0x2c8 0x64c 0x000 0x5 0x0
+#define MX53_PAD_PATA_DATA9__IPU_DIAG_BUS_9			0x2c8 0x64c 0x000 0x6 0x0
+#define MX53_PAD_PATA_DATA10__PATA_DATA_10			0x2cc 0x650 0x000 0x0 0x0
+#define MX53_PAD_PATA_DATA10__GPIO2_10				0x2cc 0x650 0x000 0x1 0x0
+#define MX53_PAD_PATA_DATA10__ESDHC1_DAT6			0x2cc 0x650 0x000 0x2 0x0
+#define MX53_PAD_PATA_DATA10__EMI_NANDF_D_10			0x2cc 0x650 0x000 0x3 0x0
+#define MX53_PAD_PATA_DATA10__ESDHC3_DAT2			0x2cc 0x650 0x000 0x4 0x0
+#define MX53_PAD_PATA_DATA10__GPU3d_GPU_DEBUG_OUT_10		0x2cc 0x650 0x000 0x5 0x0
+#define MX53_PAD_PATA_DATA10__IPU_DIAG_BUS_10			0x2cc 0x650 0x000 0x6 0x0
+#define MX53_PAD_PATA_DATA11__PATA_DATA_11			0x2d0 0x654 0x000 0x0 0x0
+#define MX53_PAD_PATA_DATA11__GPIO2_11				0x2d0 0x654 0x000 0x1 0x0
+#define MX53_PAD_PATA_DATA11__ESDHC1_DAT7			0x2d0 0x654 0x000 0x2 0x0
+#define MX53_PAD_PATA_DATA11__EMI_NANDF_D_11			0x2d0 0x654 0x000 0x3 0x0
+#define MX53_PAD_PATA_DATA11__ESDHC3_DAT3			0x2d0 0x654 0x000 0x4 0x0
+#define MX53_PAD_PATA_DATA11__GPU3d_GPU_DEBUG_OUT_11		0x2d0 0x654 0x000 0x5 0x0
+#define MX53_PAD_PATA_DATA11__IPU_DIAG_BUS_11			0x2d0 0x654 0x000 0x6 0x0
+#define MX53_PAD_PATA_DATA12__PATA_DATA_12			0x2d4 0x658 0x000 0x0 0x0
+#define MX53_PAD_PATA_DATA12__GPIO2_12				0x2d4 0x658 0x000 0x1 0x0
+#define MX53_PAD_PATA_DATA12__ESDHC2_DAT4			0x2d4 0x658 0x000 0x2 0x0
+#define MX53_PAD_PATA_DATA12__EMI_NANDF_D_12			0x2d4 0x658 0x000 0x3 0x0
+#define MX53_PAD_PATA_DATA12__ESDHC4_DAT0			0x2d4 0x658 0x000 0x4 0x0
+#define MX53_PAD_PATA_DATA12__GPU3d_GPU_DEBUG_OUT_12		0x2d4 0x658 0x000 0x5 0x0
+#define MX53_PAD_PATA_DATA12__IPU_DIAG_BUS_12			0x2d4 0x658 0x000 0x6 0x0
+#define MX53_PAD_PATA_DATA13__PATA_DATA_13			0x2d8 0x65c 0x000 0x0 0x0
+#define MX53_PAD_PATA_DATA13__GPIO2_13				0x2d8 0x65c 0x000 0x1 0x0
+#define MX53_PAD_PATA_DATA13__ESDHC2_DAT5			0x2d8 0x65c 0x000 0x2 0x0
+#define MX53_PAD_PATA_DATA13__EMI_NANDF_D_13			0x2d8 0x65c 0x000 0x3 0x0
+#define MX53_PAD_PATA_DATA13__ESDHC4_DAT1			0x2d8 0x65c 0x000 0x4 0x0
+#define MX53_PAD_PATA_DATA13__GPU3d_GPU_DEBUG_OUT_13		0x2d8 0x65c 0x000 0x5 0x0
+#define MX53_PAD_PATA_DATA13__IPU_DIAG_BUS_13			0x2d8 0x65c 0x000 0x6 0x0
+#define MX53_PAD_PATA_DATA14__PATA_DATA_14			0x2dc 0x660 0x000 0x0 0x0
+#define MX53_PAD_PATA_DATA14__GPIO2_14				0x2dc 0x660 0x000 0x1 0x0
+#define MX53_PAD_PATA_DATA14__ESDHC2_DAT6			0x2dc 0x660 0x000 0x2 0x0
+#define MX53_PAD_PATA_DATA14__EMI_NANDF_D_14			0x2dc 0x660 0x000 0x3 0x0
+#define MX53_PAD_PATA_DATA14__ESDHC4_DAT2			0x2dc 0x660 0x000 0x4 0x0
+#define MX53_PAD_PATA_DATA14__GPU3d_GPU_DEBUG_OUT_14		0x2dc 0x660 0x000 0x5 0x0
+#define MX53_PAD_PATA_DATA14__IPU_DIAG_BUS_14			0x2dc 0x660 0x000 0x6 0x0
+#define MX53_PAD_PATA_DATA15__PATA_DATA_15			0x2e0 0x664 0x000 0x0 0x0
+#define MX53_PAD_PATA_DATA15__GPIO2_15				0x2e0 0x664 0x000 0x1 0x0
+#define MX53_PAD_PATA_DATA15__ESDHC2_DAT7			0x2e0 0x664 0x000 0x2 0x0
+#define MX53_PAD_PATA_DATA15__EMI_NANDF_D_15			0x2e0 0x664 0x000 0x3 0x0
+#define MX53_PAD_PATA_DATA15__ESDHC4_DAT3			0x2e0 0x664 0x000 0x4 0x0
+#define MX53_PAD_PATA_DATA15__GPU3d_GPU_DEBUG_OUT_15		0x2e0 0x664 0x000 0x5 0x0
+#define MX53_PAD_PATA_DATA15__IPU_DIAG_BUS_15			0x2e0 0x664 0x000 0x6 0x0
+#define MX53_PAD_SD1_DATA0__ESDHC1_DAT0				0x2e4 0x66c 0x000 0x0 0x0
+#define MX53_PAD_SD1_DATA0__GPIO1_16				0x2e4 0x66c 0x000 0x1 0x0
+#define MX53_PAD_SD1_DATA0__GPT_CAPIN1				0x2e4 0x66c 0x000 0x3 0x0
+#define MX53_PAD_SD1_DATA0__CSPI_MISO				0x2e4 0x66c 0x784 0x5 0x2
+#define MX53_PAD_SD1_DATA0__CCM_PLL3_BYP			0x2e4 0x66c 0x778 0x7 0x0
+#define MX53_PAD_SD1_DATA1__ESDHC1_DAT1				0x2e8 0x670 0x000 0x0 0x0
+#define MX53_PAD_SD1_DATA1__GPIO1_17				0x2e8 0x670 0x000 0x1 0x0
+#define MX53_PAD_SD1_DATA1__GPT_CAPIN2				0x2e8 0x670 0x000 0x3 0x0
+#define MX53_PAD_SD1_DATA1__CSPI_SS0				0x2e8 0x670 0x78c 0x5 0x3
+#define MX53_PAD_SD1_DATA1__CCM_PLL4_BYP			0x2e8 0x670 0x77c 0x7 0x1
+#define MX53_PAD_SD1_CMD__ESDHC1_CMD				0x2ec 0x674 0x000 0x0 0x0
+#define MX53_PAD_SD1_CMD__GPIO1_18				0x2ec 0x674 0x000 0x1 0x0
+#define MX53_PAD_SD1_CMD__GPT_CMPOUT1				0x2ec 0x674 0x000 0x3 0x0
+#define MX53_PAD_SD1_CMD__CSPI_MOSI				0x2ec 0x674 0x788 0x5 0x2
+#define MX53_PAD_SD1_CMD__CCM_PLL1_BYP				0x2ec 0x674 0x770 0x7 0x0
+#define MX53_PAD_SD1_DATA2__ESDHC1_DAT2				0x2f0 0x678 0x000 0x0 0x0
+#define MX53_PAD_SD1_DATA2__GPIO1_19				0x2f0 0x678 0x000 0x1 0x0
+#define MX53_PAD_SD1_DATA2__GPT_CMPOUT2				0x2f0 0x678 0x000 0x2 0x0
+#define MX53_PAD_SD1_DATA2__PWM2_PWMO				0x2f0 0x678 0x000 0x3 0x0
+#define MX53_PAD_SD1_DATA2__WDOG1_WDOG_B			0x2f0 0x678 0x000 0x4 0x0
+#define MX53_PAD_SD1_DATA2__CSPI_SS1				0x2f0 0x678 0x790 0x5 0x2
+#define MX53_PAD_SD1_DATA2__WDOG1_WDOG_RST_B_DEB		0x2f0 0x678 0x000 0x6 0x0
+#define MX53_PAD_SD1_DATA2__CCM_PLL2_BYP			0x2f0 0x678 0x774 0x7 0x0
+#define MX53_PAD_SD1_CLK__ESDHC1_CLK				0x2f4 0x67c 0x000 0x0 0x0
+#define MX53_PAD_SD1_CLK__GPIO1_20				0x2f4 0x67c 0x000 0x1 0x0
+#define MX53_PAD_SD1_CLK__OSC32k_32K_OUT			0x2f4 0x67c 0x000 0x2 0x0
+#define MX53_PAD_SD1_CLK__GPT_CLKIN				0x2f4 0x67c 0x000 0x3 0x0
+#define MX53_PAD_SD1_CLK__CSPI_SCLK				0x2f4 0x67c 0x780 0x5 0x2
+#define MX53_PAD_SD1_CLK__SATA_PHY_DTB_0			0x2f4 0x67c 0x000 0x7 0x0
+#define MX53_PAD_SD1_DATA3__ESDHC1_DAT3				0x2f8 0x680 0x000 0x0 0x0
+#define MX53_PAD_SD1_DATA3__GPIO1_21				0x2f8 0x680 0x000 0x1 0x0
+#define MX53_PAD_SD1_DATA3__GPT_CMPOUT3				0x2f8 0x680 0x000 0x2 0x0
+#define MX53_PAD_SD1_DATA3__PWM1_PWMO				0x2f8 0x680 0x000 0x3 0x0
+#define MX53_PAD_SD1_DATA3__WDOG2_WDOG_B			0x2f8 0x680 0x000 0x4 0x0
+#define MX53_PAD_SD1_DATA3__CSPI_SS2				0x2f8 0x680 0x794 0x5 0x2
+#define MX53_PAD_SD1_DATA3__WDOG2_WDOG_RST_B_DEB		0x2f8 0x680 0x000 0x6 0x0
+#define MX53_PAD_SD1_DATA3__SATA_PHY_DTB_1			0x2f8 0x680 0x000 0x7 0x0
+#define MX53_PAD_SD2_CLK__ESDHC2_CLK				0x2fc 0x688 0x000 0x0 0x0
+#define MX53_PAD_SD2_CLK__GPIO1_10				0x2fc 0x688 0x000 0x1 0x0
+#define MX53_PAD_SD2_CLK__KPP_COL_5				0x2fc 0x688 0x840 0x2 0x2
+#define MX53_PAD_SD2_CLK__AUDMUX_AUD4_RXFS			0x2fc 0x688 0x73c 0x3 0x1
+#define MX53_PAD_SD2_CLK__CSPI_SCLK				0x2fc 0x688 0x780 0x5 0x3
+#define MX53_PAD_SD2_CLK__SCC_RANDOM_V				0x2fc 0x688 0x000 0x7 0x0
+#define MX53_PAD_SD2_CMD__ESDHC2_CMD				0x300 0x68c 0x000 0x0 0x0
+#define MX53_PAD_SD2_CMD__GPIO1_11				0x300 0x68c 0x000 0x1 0x0
+#define MX53_PAD_SD2_CMD__KPP_ROW_5				0x300 0x68c 0x84c 0x2 0x1
+#define MX53_PAD_SD2_CMD__AUDMUX_AUD4_RXC			0x300 0x68c 0x738 0x3 0x1
+#define MX53_PAD_SD2_CMD__CSPI_MOSI				0x300 0x68c 0x788 0x5 0x3
+#define MX53_PAD_SD2_CMD__SCC_RANDOM				0x300 0x68c 0x000 0x7 0x0
+#define MX53_PAD_SD2_DATA3__ESDHC2_DAT3				0x304 0x690 0x000 0x0 0x0
+#define MX53_PAD_SD2_DATA3__GPIO1_12				0x304 0x690 0x000 0x1 0x0
+#define MX53_PAD_SD2_DATA3__KPP_COL_6				0x304 0x690 0x844 0x2 0x1
+#define MX53_PAD_SD2_DATA3__AUDMUX_AUD4_TXC			0x304 0x690 0x740 0x3 0x1
+#define MX53_PAD_SD2_DATA3__CSPI_SS2				0x304 0x690 0x794 0x5 0x3
+#define MX53_PAD_SD2_DATA3__SJC_DONE				0x304 0x690 0x000 0x7 0x0
+#define MX53_PAD_SD2_DATA2__ESDHC2_DAT2				0x308 0x694 0x000 0x0 0x0
+#define MX53_PAD_SD2_DATA2__GPIO1_13				0x308 0x694 0x000 0x1 0x0
+#define MX53_PAD_SD2_DATA2__KPP_ROW_6				0x308 0x694 0x850 0x2 0x1
+#define MX53_PAD_SD2_DATA2__AUDMUX_AUD4_TXD			0x308 0x694 0x734 0x3 0x1
+#define MX53_PAD_SD2_DATA2__CSPI_SS1				0x308 0x694 0x790 0x5 0x3
+#define MX53_PAD_SD2_DATA2__SJC_FAIL				0x308 0x694 0x000 0x7 0x0
+#define MX53_PAD_SD2_DATA1__ESDHC2_DAT1				0x30c 0x698 0x000 0x0 0x0
+#define MX53_PAD_SD2_DATA1__GPIO1_14				0x30c 0x698 0x000 0x1 0x0
+#define MX53_PAD_SD2_DATA1__KPP_COL_7				0x30c 0x698 0x848 0x2 0x1
+#define MX53_PAD_SD2_DATA1__AUDMUX_AUD4_TXFS			0x30c 0x698 0x744 0x3 0x1
+#define MX53_PAD_SD2_DATA1__CSPI_SS0				0x30c 0x698 0x78c 0x5 0x4
+#define MX53_PAD_SD2_DATA1__RTIC_SEC_VIO			0x30c 0x698 0x000 0x7 0x0
+#define MX53_PAD_SD2_DATA0__ESDHC2_DAT0				0x310 0x69c 0x000 0x0 0x0
+#define MX53_PAD_SD2_DATA0__GPIO1_15				0x310 0x69c 0x000 0x1 0x0
+#define MX53_PAD_SD2_DATA0__KPP_ROW_7				0x310 0x69c 0x854 0x2 0x1
+#define MX53_PAD_SD2_DATA0__AUDMUX_AUD4_RXD			0x310 0x69c 0x730 0x3 0x1
+#define MX53_PAD_SD2_DATA0__CSPI_MISO				0x310 0x69c 0x784 0x5 0x3
+#define MX53_PAD_SD2_DATA0__RTIC_DONE_INT			0x310 0x69c 0x000 0x7 0x0
+#define MX53_PAD_GPIO_0__CCM_CLKO				0x314 0x6a4 0x000 0x0 0x0
+#define MX53_PAD_GPIO_0__GPIO1_0				0x314 0x6a4 0x000 0x1 0x0
+#define MX53_PAD_GPIO_0__KPP_COL_5				0x314 0x6a4 0x840 0x2 0x3
+#define MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK			0x314 0x6a4 0x000 0x3 0x0
+#define MX53_PAD_GPIO_0__EPIT1_EPITO				0x314 0x6a4 0x000 0x4 0x0
+#define MX53_PAD_GPIO_0__SRTC_ALARM_DEB				0x314 0x6a4 0x000 0x5 0x0
+#define MX53_PAD_GPIO_0__USBOH3_USBH1_PWR			0x314 0x6a4 0x000 0x6 0x0
+#define MX53_PAD_GPIO_0__CSU_TD					0x314 0x6a4 0x000 0x7 0x0
+#define MX53_PAD_GPIO_1__ESAI1_SCKR				0x318 0x6a8 0x7dc 0x0 0x1
+#define MX53_PAD_GPIO_1__GPIO1_1				0x318 0x6a8 0x000 0x1 0x0
+#define MX53_PAD_GPIO_1__KPP_ROW_5				0x318 0x6a8 0x84c 0x2 0x2
+#define MX53_PAD_GPIO_1__CCM_SSI_EXT2_CLK			0x318 0x6a8 0x000 0x3 0x0
+#define MX53_PAD_GPIO_1__PWM2_PWMO				0x318 0x6a8 0x000 0x4 0x0
+#define MX53_PAD_GPIO_1__WDOG2_WDOG_B				0x318 0x6a8 0x000 0x5 0x0
+#define MX53_PAD_GPIO_1__ESDHC1_CD				0x318 0x6a8 0x000 0x6 0x0
+#define MX53_PAD_GPIO_1__SRC_TESTER_ACK				0x318 0x6a8 0x000 0x7 0x0
+#define MX53_PAD_GPIO_9__ESAI1_FSR				0x31c 0x6ac 0x7cc 0x0 0x1
+#define MX53_PAD_GPIO_9__GPIO1_9				0x31c 0x6ac 0x000 0x1 0x0
+#define MX53_PAD_GPIO_9__KPP_COL_6				0x31c 0x6ac 0x844 0x2 0x2
+#define MX53_PAD_GPIO_9__CCM_REF_EN_B				0x31c 0x6ac 0x000 0x3 0x0
+#define MX53_PAD_GPIO_9__PWM1_PWMO				0x31c 0x6ac 0x000 0x4 0x0
+#define MX53_PAD_GPIO_9__WDOG1_WDOG_B				0x31c 0x6ac 0x000 0x5 0x0
+#define MX53_PAD_GPIO_9__ESDHC1_WP				0x31c 0x6ac 0x7fc 0x6 0x1
+#define MX53_PAD_GPIO_9__SCC_FAIL_STATE				0x31c 0x6ac 0x000 0x7 0x0
+#define MX53_PAD_GPIO_3__ESAI1_HCKR				0x320 0x6b0 0x7d4 0x0 0x1
+#define MX53_PAD_GPIO_3__GPIO1_3				0x320 0x6b0 0x000 0x1 0x0
+#define MX53_PAD_GPIO_3__I2C3_SCL				0x320 0x6b0 0x824 0x2 0x1
+#define MX53_PAD_GPIO_3__DPLLIP1_TOG_EN				0x320 0x6b0 0x000 0x3 0x0
+#define MX53_PAD_GPIO_3__CCM_CLKO2				0x320 0x6b0 0x000 0x4 0x0
+#define MX53_PAD_GPIO_3__OBSERVE_MUX_OBSRV_INT_OUT0		0x320 0x6b0 0x000 0x5 0x0
+#define MX53_PAD_GPIO_3__USBOH3_USBH1_OC			0x320 0x6b0 0x8a0 0x6 0x1
+#define MX53_PAD_GPIO_3__MLB_MLBCLK				0x320 0x6b0 0x858 0x7 0x2
+#define MX53_PAD_GPIO_6__ESAI1_SCKT				0x324 0x6b4 0x7e0 0x0 0x1
+#define MX53_PAD_GPIO_6__GPIO1_6				0x324 0x6b4 0x000 0x1 0x0
+#define MX53_PAD_GPIO_6__I2C3_SDA				0x324 0x6b4 0x828 0x2 0x1
+#define MX53_PAD_GPIO_6__CCM_CCM_OUT_0				0x324 0x6b4 0x000 0x3 0x0
+#define MX53_PAD_GPIO_6__CSU_CSU_INT_DEB			0x324 0x6b4 0x000 0x4 0x0
+#define MX53_PAD_GPIO_6__OBSERVE_MUX_OBSRV_INT_OUT1		0x324 0x6b4 0x000 0x5 0x0
+#define MX53_PAD_GPIO_6__ESDHC2_LCTL				0x324 0x6b4 0x000 0x6 0x0
+#define MX53_PAD_GPIO_6__MLB_MLBSIG				0x324 0x6b4 0x860 0x7 0x2
+#define MX53_PAD_GPIO_2__ESAI1_FST				0x328 0x6b8 0x7d0 0x0 0x1
+#define MX53_PAD_GPIO_2__GPIO1_2				0x328 0x6b8 0x000 0x1 0x0
+#define MX53_PAD_GPIO_2__KPP_ROW_6				0x328 0x6b8 0x850 0x2 0x2
+#define MX53_PAD_GPIO_2__CCM_CCM_OUT_1				0x328 0x6b8 0x000 0x3 0x0
+#define MX53_PAD_GPIO_2__CSU_CSU_ALARM_AUT_0			0x328 0x6b8 0x000 0x4 0x0
+#define MX53_PAD_GPIO_2__OBSERVE_MUX_OBSRV_INT_OUT2		0x328 0x6b8 0x000 0x5 0x0
+#define MX53_PAD_GPIO_2__ESDHC2_WP				0x328 0x6b8 0x000 0x6 0x0
+#define MX53_PAD_GPIO_2__MLB_MLBDAT				0x328 0x6b8 0x85c 0x7 0x2
+#define MX53_PAD_GPIO_4__ESAI1_HCKT				0x32c 0x6bc 0x7d8 0x0 0x1
+#define MX53_PAD_GPIO_4__GPIO1_4				0x32c 0x6bc 0x000 0x1 0x0
+#define MX53_PAD_GPIO_4__KPP_COL_7				0x32c 0x6bc 0x848 0x2 0x2
+#define MX53_PAD_GPIO_4__CCM_CCM_OUT_2				0x32c 0x6bc 0x000 0x3 0x0
+#define MX53_PAD_GPIO_4__CSU_CSU_ALARM_AUT_1			0x32c 0x6bc 0x000 0x4 0x0
+#define MX53_PAD_GPIO_4__OBSERVE_MUX_OBSRV_INT_OUT3		0x32c 0x6bc 0x000 0x5 0x0
+#define MX53_PAD_GPIO_4__ESDHC2_CD				0x32c 0x6bc 0x000 0x6 0x0
+#define MX53_PAD_GPIO_4__SCC_SEC_STATE				0x32c 0x6bc 0x000 0x7 0x0
+#define MX53_PAD_GPIO_5__ESAI1_TX2_RX3				0x330 0x6c0 0x7ec 0x0 0x1
+#define MX53_PAD_GPIO_5__GPIO1_5				0x330 0x6c0 0x000 0x1 0x0
+#define MX53_PAD_GPIO_5__KPP_ROW_7				0x330 0x6c0 0x854 0x2 0x2
+#define MX53_PAD_GPIO_5__CCM_CLKO				0x330 0x6c0 0x000 0x3 0x0
+#define MX53_PAD_GPIO_5__CSU_CSU_ALARM_AUT_2			0x330 0x6c0 0x000 0x4 0x0
+#define MX53_PAD_GPIO_5__OBSERVE_MUX_OBSRV_INT_OUT4		0x330 0x6c0 0x000 0x5 0x0
+#define MX53_PAD_GPIO_5__I2C3_SCL				0x330 0x6c0 0x824 0x6 0x2
+#define MX53_PAD_GPIO_5__CCM_PLL1_BYP				0x330 0x6c0 0x770 0x7 0x1
+#define MX53_PAD_GPIO_7__ESAI1_TX4_RX1				0x334 0x6c4 0x7f4 0x0 0x1
+#define MX53_PAD_GPIO_7__GPIO1_7				0x334 0x6c4 0x000 0x1 0x0
+#define MX53_PAD_GPIO_7__EPIT1_EPITO				0x334 0x6c4 0x000 0x2 0x0
+#define MX53_PAD_GPIO_7__CAN1_TXCAN				0x334 0x6c4 0x000 0x3 0x0
+#define MX53_PAD_GPIO_7__UART2_TXD_MUX				0x334 0x6c4 0x000 0x4 0x0
+#define MX53_PAD_GPIO_7__FIRI_RXD				0x334 0x6c4 0x80c 0x5 0x1
+#define MX53_PAD_GPIO_7__SPDIF_PLOCK				0x334 0x6c4 0x000 0x6 0x0
+#define MX53_PAD_GPIO_7__CCM_PLL2_BYP				0x334 0x6c4 0x774 0x7 0x1
+#define MX53_PAD_GPIO_8__ESAI1_TX5_RX0				0x338 0x6c8 0x7f8 0x0 0x1
+#define MX53_PAD_GPIO_8__GPIO1_8				0x338 0x6c8 0x000 0x1 0x0
+#define MX53_PAD_GPIO_8__EPIT2_EPITO				0x338 0x6c8 0x000 0x2 0x0
+#define MX53_PAD_GPIO_8__CAN1_RXCAN				0x338 0x6c8 0x760 0x3 0x2
+#define MX53_PAD_GPIO_8__UART2_RXD_MUX				0x338 0x6c8 0x880 0x4 0x5
+#define MX53_PAD_GPIO_8__FIRI_TXD				0x338 0x6c8 0x000 0x5 0x0
+#define MX53_PAD_GPIO_8__SPDIF_SRCLK				0x338 0x6c8 0x000 0x6 0x0
+#define MX53_PAD_GPIO_8__CCM_PLL3_BYP				0x338 0x6c8 0x778 0x7 0x1
+#define MX53_PAD_GPIO_16__ESAI1_TX3_RX2				0x33c 0x6cc 0x7f0 0x0 0x1
+#define MX53_PAD_GPIO_16__GPIO7_11				0x33c 0x6cc 0x000 0x1 0x0
+#define MX53_PAD_GPIO_16__TZIC_PWRFAIL_INT			0x33c 0x6cc 0x000 0x2 0x0
+#define MX53_PAD_GPIO_16__RTC_CE_RTC_EXT_TRIG1			0x33c 0x6cc 0x000 0x4 0x0
+#define MX53_PAD_GPIO_16__SPDIF_IN1				0x33c 0x6cc 0x870 0x5 0x1
+#define MX53_PAD_GPIO_16__I2C3_SDA				0x33c 0x6cc 0x828 0x6 0x2
+#define MX53_PAD_GPIO_16__SJC_DE_B				0x33c 0x6cc 0x000 0x7 0x0
+#define MX53_PAD_GPIO_17__ESAI1_TX0				0x340 0x6d0 0x7e4 0x0 0x1
+#define MX53_PAD_GPIO_17__GPIO7_12				0x340 0x6d0 0x000 0x1 0x0
+#define MX53_PAD_GPIO_17__SDMA_EXT_EVENT_0			0x340 0x6d0 0x868 0x2 0x1
+#define MX53_PAD_GPIO_17__GPC_PMIC_RDY				0x340 0x6d0 0x810 0x3 0x1
+#define MX53_PAD_GPIO_17__RTC_CE_RTC_FSV_TRIG			0x340 0x6d0 0x000 0x4 0x0
+#define MX53_PAD_GPIO_17__SPDIF_OUT1				0x340 0x6d0 0x000 0x5 0x0
+#define MX53_PAD_GPIO_17__IPU_SNOOP2				0x340 0x6d0 0x000 0x6 0x0
+#define MX53_PAD_GPIO_17__SJC_JTAG_ACT				0x340 0x6d0 0x000 0x7 0x0
+#define MX53_PAD_GPIO_18__ESAI1_TX1				0x344 0x6d4 0x7e8 0x0 0x1
+#define MX53_PAD_GPIO_18__GPIO7_13				0x344 0x6d4 0x000 0x1 0x0
+#define MX53_PAD_GPIO_18__SDMA_EXT_EVENT_1			0x344 0x6d4 0x86c 0x2 0x1
+#define MX53_PAD_GPIO_18__OWIRE_LINE				0x344 0x6d4 0x864 0x3 0x1
+#define MX53_PAD_GPIO_18__RTC_CE_RTC_ALARM2_TRIG		0x344 0x6d4 0x000 0x4 0x0
+#define MX53_PAD_GPIO_18__CCM_ASRC_EXT_CLK			0x344 0x6d4 0x768 0x5 0x1
+#define MX53_PAD_GPIO_18__ESDHC1_LCTL				0x344 0x6d4 0x000 0x6 0x0
+#define MX53_PAD_GPIO_18__SRC_SYSTEM_RST			0x344 0x6d4 0x000 0x7 0x0
+
+#endif /* __DTS_IMX53_PINFUNC_H */
diff --git a/arch/arm/boot/dts/imx53-qsb.dts b/arch/arm/boot/dts/imx53-qsb.dts
deleted file mode 100644
index 05cc562..0000000
--- a/arch/arm/boot/dts/imx53-qsb.dts
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * Copyright 2011 Freescale Semiconductor, Inc.
- * Copyright 2011 Linaro Ltd.
- *
- * 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
- */
-
-/dts-v1/;
-/include/ "imx53.dtsi"
-
-/ {
-	model = "Freescale i.MX53 Quick Start Board";
-	compatible = "fsl,imx53-qsb", "fsl,imx53";
-
-	memory {
-		reg = <0x70000000 0x40000000>;
-	};
-
-	gpio-keys {
-		compatible = "gpio-keys";
-
-		power {
-			label = "Power Button";
-			gpios = <&gpio1 8 0>;
-			linux,code = <116>; /* KEY_POWER */
-			gpio-key,wakeup;
-		};
-
-		volume-up {
-			label = "Volume Up";
-			gpios = <&gpio2 14 0>;
-			linux,code = <115>; /* KEY_VOLUMEUP */
-		};
-
-		volume-down {
-			label = "Volume Down";
-			gpios = <&gpio2 15 0>;
-			linux,code = <114>; /* KEY_VOLUMEDOWN */
-		};
-	};
-
-	leds {
-		compatible = "gpio-leds";
-		pinctrl-names = "default";
-		pinctrl-0 = <&led_pin_gpio7_7>;
-
-		user {
-			label = "Heartbeat";
-			gpios = <&gpio7 7 0>;
-			linux,default-trigger = "heartbeat";
-		};
-	};
-
-	regulators {
-		compatible = "simple-bus";
-
-		reg_3p2v: 3p2v {
-			compatible = "regulator-fixed";
-			regulator-name = "3P2V";
-			regulator-min-microvolt = <3200000>;
-			regulator-max-microvolt = <3200000>;
-			regulator-always-on;
-		};
-	};
-
-	sound {
-		compatible = "fsl,imx53-qsb-sgtl5000",
-			     "fsl,imx-audio-sgtl5000";
-		model = "imx53-qsb-sgtl5000";
-		ssi-controller = <&ssi2>;
-		audio-codec = <&sgtl5000>;
-		audio-routing =
-			"MIC_IN", "Mic Jack",
-			"Mic Jack", "Mic Bias",
-			"Headphone Jack", "HP_OUT";
-		mux-int-port = <2>;
-		mux-ext-port = <5>;
-	};
-};
-
-&esdhc1 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_esdhc1_1>;
-	cd-gpios = <&gpio3 13 0>;
-	status = "okay";
-};
-
-&ssi2 {
-	fsl,mode = "i2s-slave";
-	status = "okay";
-};
-
-&esdhc3 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_esdhc3_1>;
-	cd-gpios = <&gpio3 11 0>;
-	wp-gpios = <&gpio3 12 0>;
-	status = "okay";
-};
-
-&iomuxc {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_hog>;
-
-	hog {
-		pinctrl_hog: hoggrp {
-			fsl,pins = <
-				1071 0x80000000	/* MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK */
-				1141 0x80000000	/* MX53_PAD_GPIO_8__GPIO1_8 */
-				982  0x80000000	/* MX53_PAD_PATA_DATA14__GPIO2_14 */
-				989  0x80000000	/* MX53_PAD_PATA_DATA15__GPIO2_15 */
-				693  0x80000000	/* MX53_PAD_EIM_DA11__GPIO3_11 */
-				697  0x80000000	/* MX53_PAD_EIM_DA12__GPIO3_12 */
-				701  0x80000000	/* MX53_PAD_EIM_DA13__GPIO3_13 */
-				868  0x80000000	/* MX53_PAD_PATA_DA_0__GPIO7_6 */
-				1149 0x80000000 /* MX53_PAD_GPIO_16__GPIO7_11 */
-			>;
-		};
-
-		led_pin_gpio7_7: led_gpio7_7@0 {
-			fsl,pins = <
-				873  0x80000000	/* MX53_PAD_PATA_DA_1__GPIO7_7 */
-			>;
-		};
-	};
-
-};
-
-&uart1 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart1_1>;
-	status = "okay";
-};
-
-&i2c2 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_i2c2_1>;
-	status = "okay";
-
-	sgtl5000: codec@0a {
-		compatible = "fsl,sgtl5000";
-		reg = <0x0a>;
-		VDDA-supply = <&reg_3p2v>;
-		VDDIO-supply = <&reg_3p2v>;
-	};
-};
-
-&i2c1 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_i2c1_1>;
-	status = "okay";
-
-	accelerometer: mma8450@1c {
-		compatible = "fsl,mma8450";
-		reg = <0x1c>;
-	};
-
-	pmic: dialog@48 {
-		compatible = "dlg,da9053-aa", "dlg,da9052";
-		reg = <0x48>;
-		interrupt-parent = <&gpio7>;
-		interrupts = <11 0x8>; /* low-level active IRQ at GPIO7_11 */
-
-		regulators {
-			buck1_reg: buck1 {
-				regulator-min-microvolt = <500000>;
-				regulator-max-microvolt = <2075000>;
-				regulator-always-on;
-			};
-
-			buck2_reg: buck2 {
-				regulator-min-microvolt = <500000>;
-				regulator-max-microvolt = <2075000>;
-				regulator-always-on;
-			};
-
-			buck3_reg: buck3 {
-				regulator-min-microvolt = <925000>;
-				regulator-max-microvolt = <2500000>;
-				regulator-always-on;
-			};
-
-			buck4_reg: buck4 {
-				regulator-min-microvolt = <925000>;
-				regulator-max-microvolt = <2500000>;
-				regulator-always-on;
-			};
-
-			ldo1_reg: ldo1 {
-				regulator-min-microvolt = <600000>;
-				regulator-max-microvolt = <1800000>;
-				regulator-boot-on;
-				regulator-always-on;
-			};
-
-			ldo2_reg: ldo2 {
-				regulator-min-microvolt = <600000>;
-				regulator-max-microvolt = <1800000>;
-				regulator-always-on;
-			};
-
-			ldo3_reg: ldo3 {
-				regulator-min-microvolt = <600000>;
-				regulator-max-microvolt = <1800000>;
-				regulator-always-on;
-			};
-
-			ldo4_reg: ldo4 {
-				regulator-min-microvolt = <1725000>;
-				regulator-max-microvolt = <3300000>;
-				regulator-always-on;
-			};
-
-			ldo5_reg: ldo5 {
-				regulator-min-microvolt = <1725000>;
-				regulator-max-microvolt = <3300000>;
-				regulator-always-on;
-			};
-
-			ldo6_reg: ldo6 {
-				regulator-min-microvolt = <1200000>;
-				regulator-max-microvolt = <3600000>;
-				regulator-always-on;
-			};
-
-			ldo7_reg: ldo7 {
-				regulator-min-microvolt = <1200000>;
-				regulator-max-microvolt = <3600000>;
-				regulator-always-on;
-			};
-
-			ldo8_reg: ldo8 {
-				regulator-min-microvolt = <1200000>;
-				regulator-max-microvolt = <3600000>;
-				regulator-always-on;
-			};
-
-			ldo9_reg: ldo9 {
-				regulator-min-microvolt = <1200000>;
-				regulator-max-microvolt = <3600000>;
-				regulator-always-on;
-			};
-
-			ldo10_reg: ldo10 {
-				regulator-min-microvolt = <1250000>;
-				regulator-max-microvolt = <3650000>;
-				regulator-always-on;
-			};
-		};
-	};
-};
-
-&audmux {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_audmux_1>;
-	status = "okay";
-};
-
-&fec {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_fec_1>;
-	phy-mode = "rmii";
-	phy-reset-gpios = <&gpio7 6 0>;
-	status = "okay";
-};
diff --git a/arch/arm/boot/dts/imx53-qsb.dtsp b/arch/arm/boot/dts/imx53-qsb.dtsp
new file mode 100644
index 0000000..dae8d9f
--- /dev/null
+++ b/arch/arm/boot/dts/imx53-qsb.dtsp
@@ -0,0 +1,270 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * 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
+ */
+
+/dts-v1/;
+#include "imx53.dtsip"
+
+/ {
+	model = "Freescale i.MX53 Quick Start Board";
+	compatible = "fsl,imx53-qsb", "fsl,imx53";
+
+	memory {
+		reg = <0x70000000 0x40000000>;
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		power {
+			label = "Power Button";
+			gpios = <&gpio1 8 0>;
+			linux,code = <116>; /* KEY_POWER */
+			gpio-key,wakeup;
+		};
+
+		volume-up {
+			label = "Volume Up";
+			gpios = <&gpio2 14 0>;
+			linux,code = <115>; /* KEY_VOLUMEUP */
+		};
+
+		volume-down {
+			label = "Volume Down";
+			gpios = <&gpio2 15 0>;
+			linux,code = <114>; /* KEY_VOLUMEDOWN */
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&led_pin_gpio7_7>;
+
+		user {
+			label = "Heartbeat";
+			gpios = <&gpio7 7 0>;
+			linux,default-trigger = "heartbeat";
+		};
+	};
+
+	regulators {
+		compatible = "simple-bus";
+
+		reg_3p2v: 3p2v {
+			compatible = "regulator-fixed";
+			regulator-name = "3P2V";
+			regulator-min-microvolt = <3200000>;
+			regulator-max-microvolt = <3200000>;
+			regulator-always-on;
+		};
+	};
+
+	sound {
+		compatible = "fsl,imx53-qsb-sgtl5000",
+			     "fsl,imx-audio-sgtl5000";
+		model = "imx53-qsb-sgtl5000";
+		ssi-controller = <&ssi2>;
+		audio-codec = <&sgtl5000>;
+		audio-routing =
+			"MIC_IN", "Mic Jack",
+			"Mic Jack", "Mic Bias",
+			"Headphone Jack", "HP_OUT";
+		mux-int-port = <2>;
+		mux-ext-port = <5>;
+	};
+};
+
+&esdhc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_esdhc1_1>;
+	cd-gpios = <&gpio3 13 0>;
+	status = "okay";
+};
+
+&ssi2 {
+	fsl,mode = "i2s-slave";
+	status = "okay";
+};
+
+&esdhc3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_esdhc3_1>;
+	cd-gpios = <&gpio3 11 0>;
+	wp-gpios = <&gpio3 12 0>;
+	status = "okay";
+};
+
+&iomuxc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hog>;
+
+	hog {
+		pinctrl_hog: hoggrp {
+			fsl,pins = <
+				MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK 0x80000000
+				MX53_PAD_GPIO_8__GPIO1_8          0x80000000
+				MX53_PAD_PATA_DATA14__GPIO2_14    0x80000000
+				MX53_PAD_PATA_DATA15__GPIO2_15    0x80000000
+				MX53_PAD_EIM_DA11__GPIO3_11       0x80000000
+				MX53_PAD_EIM_DA12__GPIO3_12       0x80000000
+				MX53_PAD_EIM_DA13__GPIO3_13       0x80000000
+				MX53_PAD_PATA_DA_0__GPIO7_6       0x80000000
+				MX53_PAD_GPIO_16__GPIO7_11        0x80000000
+			>;
+		};
+
+		led_pin_gpio7_7: led_gpio7_7@0 {
+			fsl,pins = <
+				MX53_PAD_PATA_DA_1__GPIO7_7 0x80000000
+			>;
+		};
+	};
+
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1_1>;
+	status = "okay";
+};
+
+&i2c2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2_1>;
+	status = "okay";
+
+	sgtl5000: codec@0a {
+		compatible = "fsl,sgtl5000";
+		reg = <0x0a>;
+		VDDA-supply = <&reg_3p2v>;
+		VDDIO-supply = <&reg_3p2v>;
+	};
+};
+
+&i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1_1>;
+	status = "okay";
+
+	accelerometer: mma8450@1c {
+		compatible = "fsl,mma8450";
+		reg = <0x1c>;
+	};
+
+	pmic: dialog@48 {
+		compatible = "dlg,da9053-aa", "dlg,da9052";
+		reg = <0x48>;
+		interrupt-parent = <&gpio7>;
+		interrupts = <11 0x8>; /* low-level active IRQ at GPIO7_11 */
+
+		regulators {
+			buck1_reg: buck1 {
+				regulator-min-microvolt = <500000>;
+				regulator-max-microvolt = <2075000>;
+				regulator-always-on;
+			};
+
+			buck2_reg: buck2 {
+				regulator-min-microvolt = <500000>;
+				regulator-max-microvolt = <2075000>;
+				regulator-always-on;
+			};
+
+			buck3_reg: buck3 {
+				regulator-min-microvolt = <925000>;
+				regulator-max-microvolt = <2500000>;
+				regulator-always-on;
+			};
+
+			buck4_reg: buck4 {
+				regulator-min-microvolt = <925000>;
+				regulator-max-microvolt = <2500000>;
+				regulator-always-on;
+			};
+
+			ldo1_reg: ldo1 {
+				regulator-min-microvolt = <600000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldo2_reg: ldo2 {
+				regulator-min-microvolt = <600000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-always-on;
+			};
+
+			ldo3_reg: ldo3 {
+				regulator-min-microvolt = <600000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-always-on;
+			};
+
+			ldo4_reg: ldo4 {
+				regulator-min-microvolt = <1725000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			ldo5_reg: ldo5 {
+				regulator-min-microvolt = <1725000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			ldo6_reg: ldo6 {
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <3600000>;
+				regulator-always-on;
+			};
+
+			ldo7_reg: ldo7 {
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <3600000>;
+				regulator-always-on;
+			};
+
+			ldo8_reg: ldo8 {
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <3600000>;
+				regulator-always-on;
+			};
+
+			ldo9_reg: ldo9 {
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <3600000>;
+				regulator-always-on;
+			};
+
+			ldo10_reg: ldo10 {
+				regulator-min-microvolt = <1250000>;
+				regulator-max-microvolt = <3650000>;
+				regulator-always-on;
+			};
+		};
+	};
+};
+
+&audmux {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_audmux_1>;
+	status = "okay";
+};
+
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_fec_1>;
+	phy-mode = "rmii";
+	phy-reset-gpios = <&gpio7 6 0>;
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx53-smd.dts b/arch/arm/boot/dts/imx53-smd.dts
deleted file mode 100644
index 995554c..0000000
--- a/arch/arm/boot/dts/imx53-smd.dts
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright 2011 Freescale Semiconductor, Inc.
- * Copyright 2011 Linaro Ltd.
- *
- * 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
- */
-
-/dts-v1/;
-/include/ "imx53.dtsi"
-
-/ {
-	model = "Freescale i.MX53 Smart Mobile Reference Design Board";
-	compatible = "fsl,imx53-smd", "fsl,imx53";
-
-	memory {
-		reg = <0x70000000 0x40000000>;
-	};
-
-	gpio-keys {
-		compatible = "gpio-keys";
-
-		volume-up {
-			label = "Volume Up";
-			gpios = <&gpio2 14 0>;
-			linux,code = <115>; /* KEY_VOLUMEUP */
-		};
-
-		volume-down {
-			label = "Volume Down";
-			gpios = <&gpio2 15 0>;
-			linux,code = <114>; /* KEY_VOLUMEDOWN */
-		};
-	};
-};
-
-&esdhc1 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_esdhc1_1>;
-	cd-gpios = <&gpio3 13 0>;
-	wp-gpios = <&gpio4 11 0>;
-	status = "okay";
-};
-
-&esdhc2 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_esdhc2_1>;
-	non-removable;
-	status = "okay";
-};
-
-&uart3 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart3_1>;
-	fsl,uart-has-rtscts;
-	status = "okay";
-};
-
-&ecspi1 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_ecspi1_1>;
-	fsl,spi-num-chipselects = <2>;
-	cs-gpios = <&gpio2 30 0>, <&gpio3 19 0>;
-	status = "okay";
-
-	zigbee: mc1323@0 {
-		compatible = "fsl,mc1323";
-		spi-max-frequency = <8000000>;
-		reg = <0>;
-	};
-
-	flash: m25p32@1 {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		compatible = "st,m25p32", "st,m25p";
-		spi-max-frequency = <20000000>;
-		reg = <1>;
-
-		partition@0 {
-			label = "U-Boot";
-			reg = <0x0 0x40000>;
-			read-only;
-		};
-
-		partition@40000 {
-			label = "Kernel";
-			reg = <0x40000 0x3c0000>;
-		};
-	};
-};
-
-&esdhc3 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_esdhc3_1>;
-	non-removable;
-	status = "okay";
-};
-
-&iomuxc {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_hog>;
-
-	hog {
-		pinctrl_hog: hoggrp {
-			fsl,pins = <
-				982  0x80000000	/* MX53_PAD_PATA_DATA14__GPIO2_14 */
-				989  0x80000000	/* MX53_PAD_PATA_DATA15__GPIO2_15 */
-				424  0x80000000	/* MX53_PAD_EIM_EB2__GPIO2_30 */
-				701  0x80000000	/* MX53_PAD_EIM_DA13__GPIO3_13 */
-				449  0x80000000	/* MX53_PAD_EIM_D19__GPIO3_19 */
-				43   0x80000000	/* MX53_PAD_KEY_ROW2__GPIO4_11 */
-				868  0x80000000	/* MX53_PAD_PATA_DA_0__GPIO7_6 */
-			>;
-		};
-	};
-};
-
-&uart1 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart1_1>;
-	status = "okay";
-};
-
-&uart2 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart2_1>;
-	status = "okay";
-};
-
-&i2c2 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_i2c2_1>;
-	status = "okay";
-
-	codec: sgtl5000@0a {
-		compatible = "fsl,sgtl5000";
-		reg = <0x0a>;
-	};
-
-	magnetometer: mag3110@0e {
-		compatible = "fsl,mag3110";
-		reg = <0x0e>;
-	};
-
-	touchkey: mpr121@5a {
-		compatible = "fsl,mpr121";
-		reg = <0x5a>;
-	};
-};
-
-&i2c1 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_i2c1_1>;
-	status = "okay";
-
-	accelerometer: mma8450@1c {
-		compatible = "fsl,mma8450";
-		reg = <0x1c>;
-	};
-
-	camera: ov5642@3c {
-		compatible = "ovti,ov5642";
-		reg = <0x3c>;
-	};
-
-	pmic: dialog@48 {
-		compatible = "dialog,da9053", "dialog,da9052";
-		reg = <0x48>;
-	};
-};
-
-&fec {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_fec_1>;
-	phy-mode = "rmii";
-	phy-reset-gpios = <&gpio7 6 0>;
-	status = "okay";
-};
diff --git a/arch/arm/boot/dts/imx53-smd.dtsp b/arch/arm/boot/dts/imx53-smd.dtsp
new file mode 100644
index 0000000..f2dbc34
--- /dev/null
+++ b/arch/arm/boot/dts/imx53-smd.dtsp
@@ -0,0 +1,182 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * 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
+ */
+
+/dts-v1/;
+#include "imx53.dtsip"
+
+/ {
+	model = "Freescale i.MX53 Smart Mobile Reference Design Board";
+	compatible = "fsl,imx53-smd", "fsl,imx53";
+
+	memory {
+		reg = <0x70000000 0x40000000>;
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		volume-up {
+			label = "Volume Up";
+			gpios = <&gpio2 14 0>;
+			linux,code = <115>; /* KEY_VOLUMEUP */
+		};
+
+		volume-down {
+			label = "Volume Down";
+			gpios = <&gpio2 15 0>;
+			linux,code = <114>; /* KEY_VOLUMEDOWN */
+		};
+	};
+};
+
+&esdhc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_esdhc1_1>;
+	cd-gpios = <&gpio3 13 0>;
+	wp-gpios = <&gpio4 11 0>;
+	status = "okay";
+};
+
+&esdhc2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_esdhc2_1>;
+	non-removable;
+	status = "okay";
+};
+
+&uart3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart3_1>;
+	fsl,uart-has-rtscts;
+	status = "okay";
+};
+
+&ecspi1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ecspi1_1>;
+	fsl,spi-num-chipselects = <2>;
+	cs-gpios = <&gpio2 30 0>, <&gpio3 19 0>;
+	status = "okay";
+
+	zigbee: mc1323@0 {
+		compatible = "fsl,mc1323";
+		spi-max-frequency = <8000000>;
+		reg = <0>;
+	};
+
+	flash: m25p32@1 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "st,m25p32", "st,m25p";
+		spi-max-frequency = <20000000>;
+		reg = <1>;
+
+		partition@0 {
+			label = "U-Boot";
+			reg = <0x0 0x40000>;
+			read-only;
+		};
+
+		partition@40000 {
+			label = "Kernel";
+			reg = <0x40000 0x3c0000>;
+		};
+	};
+};
+
+&esdhc3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_esdhc3_1>;
+	non-removable;
+	status = "okay";
+};
+
+&iomuxc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hog>;
+
+	hog {
+		pinctrl_hog: hoggrp {
+			fsl,pins = <
+				MX53_PAD_PATA_DATA14__GPIO2_14 0x80000000
+				MX53_PAD_PATA_DATA15__GPIO2_15 0x80000000
+				MX53_PAD_EIM_EB2__GPIO2_30     0x80000000
+				MX53_PAD_EIM_DA13__GPIO3_13    0x80000000
+				MX53_PAD_EIM_D19__GPIO3_19     0x80000000
+				MX53_PAD_KEY_ROW2__GPIO4_11    0x80000000
+				MX53_PAD_PATA_DA_0__GPIO7_6    0x80000000
+			>;
+		};
+	};
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1_1>;
+	status = "okay";
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2_1>;
+	status = "okay";
+};
+
+&i2c2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2_1>;
+	status = "okay";
+
+	codec: sgtl5000@0a {
+		compatible = "fsl,sgtl5000";
+		reg = <0x0a>;
+	};
+
+	magnetometer: mag3110@0e {
+		compatible = "fsl,mag3110";
+		reg = <0x0e>;
+	};
+
+	touchkey: mpr121@5a {
+		compatible = "fsl,mpr121";
+		reg = <0x5a>;
+	};
+};
+
+&i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1_1>;
+	status = "okay";
+
+	accelerometer: mma8450@1c {
+		compatible = "fsl,mma8450";
+		reg = <0x1c>;
+	};
+
+	camera: ov5642@3c {
+		compatible = "ovti,ov5642";
+		reg = <0x3c>;
+	};
+
+	pmic: dialog@48 {
+		compatible = "dialog,da9053", "dialog,da9052";
+		reg = <0x48>;
+	};
+};
+
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_fec_1>;
+	phy-mode = "rmii";
+	phy-reset-gpios = <&gpio7 6 0>;
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx53-tqma53.dtsi b/arch/arm/boot/dts/imx53-tqma53.dtsi
deleted file mode 100644
index 8278ec5..0000000
--- a/arch/arm/boot/dts/imx53-tqma53.dtsi
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Copyright 2012 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
- * Copyright 2012 Steffen Trumtrar <s.trumtrar@pengutronix.de>, Pengutronix
- *
- * 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/ "imx53.dtsi"
-
-/ {
-	model = "TQ TQMa53";
-	compatible = "tq,tqma53", "fsl,imx53";
-
-	memory {
-		reg = <0x70000000 0x40000000>; /* Up to 1GiB */
-	};
-
-	regulators {
-		compatible = "simple-bus";
-
-		reg_3p3v: 3p3v {
-			compatible = "regulator-fixed";
-			regulator-name = "3P3V";
-			regulator-min-microvolt = <3300000>;
-			regulator-max-microvolt = <3300000>;
-			regulator-always-on;
-		};
-	};
-};
-
-&esdhc2 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_esdhc2_1>;
-	wp-gpios = <&gpio1 2 0>;
-	cd-gpios = <&gpio1 4 0>;
-	status = "disabled";
-};
-
-&uart3 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart3_2>;
-	status = "disabled";
-};
-
-&ecspi1 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_ecspi1_1>;
-	fsl,spi-num-chipselects = <4>;
-	cs-gpios = <&gpio2 30 0>, <&gpio3 19 0>,
-		   <&gpio3 24 0>, <&gpio3 25 0>;
-	status = "disabled";
-};
-
-&esdhc3 { /* EMMC */
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_esdhc3_1>;
-	vmmc-supply = <&reg_3p3v>;
-	non-removable;
-	bus-width = <8>;
-	status = "okay";
-};
-
-&iomuxc {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_hog>;
-
-	i2s {
-		pinctrl_i2s_1: i2s-grp1 {
-			fsl,pins = <
-				 1   0x10000	/* I2S_MCLK */
-				 10  0x10000	/* I2S_SCLK */
-				 17  0x10000	/* I2S_DOUT */
-				 23  0x10000	/* I2S_LRCLK*/
-				 30  0x10000	/* I2S_DIN  */
-			>;
-		};
-	};
-
-	hog {
-		pinctrl_hog: hoggrp {
-			fsl,pins = <
-				 610  0x10000	/* MX53_PAD_EIM_CS1__IPU_DI1_PIN6 (VSYNC)*/
-				 711  0x10000	/* MX53_PAD_EIM_DA15__IPU_DI1_PIN4 (HSYNC)*/
-				 873  0x10000	/* MX53_PAD_PATA_DA_1__GPIO7_7 (LCD_BLT_EN)*/
-				 878  0x10000	/* MX53_PAD_PATA_DA_2__GPIO7_8 (LCD_RESET)*/
-				 922  0x10000	/* MX53_PAD_PATA_DATA5__GPIO2_5 (LCD_POWER)*/
-				 928  0x10000	/* MX53_PAD_PATA_DATA6__GPIO2_6 (PMIC_INT)*/
-				 982  0x10000	/* MX53_PAD_PATA_DATA14__GPIO2_14 (CSI_RST)*/
-				 989  0x10000	/* MX53_PAD_PATA_DATA15__GPIO2_15 (CSI_PWDN)*/
-				 1069 0x10000	/* MX53_PAD_GPIO_0__GPIO1_0 (SYSTEM_DOWN)*/
-				 1093 0x10000	/* MX53_PAD_GPIO_3__GPIO1_3 */
-			>;
-		};
-	};
-};
-
-&uart1 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart1_2>;
-	fsl,uart-has-rtscts;
-	status = "disabled";
-};
-
-&uart2 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart2_1>;
-	status = "disabled";
-};
-
-&can1 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_can1_2>;
-	status = "disabled";
-};
-
-&can2 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_can2_1>;
-	status = "disabled";
-};
-
-&i2c3 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_i2c3_1>;
-	status = "disabled";
-};
-
-&cspi {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_cspi_1>;
-	fsl,spi-num-chipselects = <3>;
-	cs-gpios = <&gpio1 18 0>, <&gpio1 19 0>,
-		   <&gpio1 21 0>;
-	status = "disabled";
-};
-
-&i2c2 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_i2c2_1>;
-	status = "okay";
-
-	pmic: mc34708@8 {
-		compatible = "fsl,mc34708";
-		reg = <0x8>;
-		fsl,mc13xxx-uses-rtc;
-		interrupt-parent = <&gpio2>;
-		interrupts = <6 8>; /* PDATA_DATA6, low active */
-	};
-
-	sensor1: lm75@48 {
-		compatible = "lm75";
-		reg = <0x48>;
-	};
-
-	eeprom: 24c64@50 {
-		compatible = "at,24c64";
-		pagesize = <32>;
-		reg = <0x50>;
-	};
-};
-
-&fec {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_fec_1>;
-	phy-mode = "rmii";
-	status = "disabled";
-};
diff --git a/arch/arm/boot/dts/imx53-tqma53.dtsip b/arch/arm/boot/dts/imx53-tqma53.dtsip
new file mode 100644
index 0000000..cb1cefb
--- /dev/null
+++ b/arch/arm/boot/dts/imx53-tqma53.dtsip
@@ -0,0 +1,172 @@
+/*
+ * Copyright 2012 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ * Copyright 2012 Steffen Trumtrar <s.trumtrar@pengutronix.de>, Pengutronix
+ *
+ * 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 "imx53.dtsip"
+
+/ {
+	model = "TQ TQMa53";
+	compatible = "tq,tqma53", "fsl,imx53";
+
+	memory {
+		reg = <0x70000000 0x40000000>; /* Up to 1GiB */
+	};
+
+	regulators {
+		compatible = "simple-bus";
+
+		reg_3p3v: 3p3v {
+			compatible = "regulator-fixed";
+			regulator-name = "3P3V";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+	};
+};
+
+&esdhc2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_esdhc2_1>;
+	wp-gpios = <&gpio1 2 0>;
+	cd-gpios = <&gpio1 4 0>;
+	status = "disabled";
+};
+
+&uart3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart3_2>;
+	status = "disabled";
+};
+
+&ecspi1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ecspi1_1>;
+	fsl,spi-num-chipselects = <4>;
+	cs-gpios = <&gpio2 30 0>, <&gpio3 19 0>,
+		   <&gpio3 24 0>, <&gpio3 25 0>;
+	status = "disabled";
+};
+
+&esdhc3 { /* EMMC */
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_esdhc3_1>;
+	vmmc-supply = <&reg_3p3v>;
+	non-removable;
+	bus-width = <8>;
+	status = "okay";
+};
+
+&iomuxc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hog>;
+
+	i2s {
+		pinctrl_i2s_1: i2s-grp1 {
+			fsl,pins = <
+				 MX53_PAD_GPIO_19__GPIO4_5           0x10000 /* I2S_MCLK */
+				 MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC  0x10000 /* I2S_SCLK */
+				 MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD  0x10000 /* I2S_DOUT */
+				 MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS 0x10000 /* I2S_LRCLK */
+				 MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD  0x10000 /* I2S_DIN */
+			>;
+		};
+	};
+
+	hog {
+		pinctrl_hog: hoggrp {
+			fsl,pins = <
+				 MX53_PAD_EIM_CS1__IPU_DI1_PIN6  0x10000 /* VSYNC */
+				 MX53_PAD_EIM_DA15__IPU_DI1_PIN4 0x10000 /* HSYNC */
+				 MX53_PAD_PATA_DA_1__GPIO7_7     0x10000 /* LCD_BLT_EN */
+				 MX53_PAD_PATA_DA_2__GPIO7_8     0x10000 /* LCD_RESET */
+				 MX53_PAD_PATA_DATA5__GPIO2_5    0x10000 /* LCD_POWER */
+				 MX53_PAD_PATA_DATA6__GPIO2_6    0x10000 /* PMIC_INT */
+				 MX53_PAD_PATA_DATA14__GPIO2_14  0x10000 /* CSI_RST */
+				 MX53_PAD_PATA_DATA15__GPIO2_15  0x10000 /* CSI_PWDN */
+				 MX53_PAD_GPIO_0__GPIO1_0        0x10000 /* SYSTEM_DOWN */
+				 MX53_PAD_GPIO_3__GPIO1_3        0x10000
+			>;
+		};
+	};
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1_2>;
+	fsl,uart-has-rtscts;
+	status = "disabled";
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2_1>;
+	status = "disabled";
+};
+
+&can1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_can1_2>;
+	status = "disabled";
+};
+
+&can2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_can2_1>;
+	status = "disabled";
+};
+
+&i2c3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c3_1>;
+	status = "disabled";
+};
+
+&cspi {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_cspi_1>;
+	fsl,spi-num-chipselects = <3>;
+	cs-gpios = <&gpio1 18 0>, <&gpio1 19 0>,
+		   <&gpio1 21 0>;
+	status = "disabled";
+};
+
+&i2c2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2_1>;
+	status = "okay";
+
+	pmic: mc34708@8 {
+		compatible = "fsl,mc34708";
+		reg = <0x8>;
+		fsl,mc13xxx-uses-rtc;
+		interrupt-parent = <&gpio2>;
+		interrupts = <6 8>; /* PDATA_DATA6, low active */
+	};
+
+	sensor1: lm75@48 {
+		compatible = "lm75";
+		reg = <0x48>;
+	};
+
+	eeprom: 24c64@50 {
+		compatible = "at,24c64";
+		pagesize = <32>;
+		reg = <0x50>;
+	};
+};
+
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_fec_1>;
+	phy-mode = "rmii";
+	status = "disabled";
+};
diff --git a/arch/arm/boot/dts/imx53.dtsi b/arch/arm/boot/dts/imx53.dtsi
deleted file mode 100644
index d05aa21..0000000
--- a/arch/arm/boot/dts/imx53.dtsi
+++ /dev/null
@@ -1,736 +0,0 @@
-/*
- * Copyright 2011 Freescale Semiconductor, Inc.
- * Copyright 2011 Linaro Ltd.
- *
- * 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/ "skeleton.dtsi"
-
-/ {
-	aliases {
-		serial0 = &uart1;
-		serial1 = &uart2;
-		serial2 = &uart3;
-		serial3 = &uart4;
-		serial4 = &uart5;
-		gpio0 = &gpio1;
-		gpio1 = &gpio2;
-		gpio2 = &gpio3;
-		gpio3 = &gpio4;
-		gpio4 = &gpio5;
-		gpio5 = &gpio6;
-		gpio6 = &gpio7;
-	};
-
-	tzic: tz-interrupt-controller@0fffc000 {
-		compatible = "fsl,imx53-tzic", "fsl,tzic";
-		interrupt-controller;
-		#interrupt-cells = <1>;
-		reg = <0x0fffc000 0x4000>;
-	};
-
-	clocks {
-		#address-cells = <1>;
-		#size-cells = <0>;
-
-		ckil {
-			compatible = "fsl,imx-ckil", "fixed-clock";
-			clock-frequency = <32768>;
-		};
-
-		ckih1 {
-			compatible = "fsl,imx-ckih1", "fixed-clock";
-			clock-frequency = <22579200>;
-		};
-
-		ckih2 {
-			compatible = "fsl,imx-ckih2", "fixed-clock";
-			clock-frequency = <0>;
-		};
-
-		osc {
-			compatible = "fsl,imx-osc", "fixed-clock";
-			clock-frequency = <24000000>;
-		};
-	};
-
-	soc {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		compatible = "simple-bus";
-		interrupt-parent = <&tzic>;
-		ranges;
-
-		ipu: ipu@18000000 {
-			#crtc-cells = <1>;
-			compatible = "fsl,imx53-ipu";
-			reg = <0x18000000 0x080000000>;
-			interrupts = <11 10>;
-		};
-
-		aips@50000000 { /* AIPS1 */
-			compatible = "fsl,aips-bus", "simple-bus";
-			#address-cells = <1>;
-			#size-cells = <1>;
-			reg = <0x50000000 0x10000000>;
-			ranges;
-
-			spba@50000000 {
-				compatible = "fsl,spba-bus", "simple-bus";
-				#address-cells = <1>;
-				#size-cells = <1>;
-				reg = <0x50000000 0x40000>;
-				ranges;
-
-				esdhc1: esdhc@50004000 {
-					compatible = "fsl,imx53-esdhc";
-					reg = <0x50004000 0x4000>;
-					interrupts = <1>;
-					clocks = <&clks 44>, <&clks 0>, <&clks 71>;
-					clock-names = "ipg", "ahb", "per";
-					bus-width = <4>;
-					status = "disabled";
-				};
-
-				esdhc2: esdhc@50008000 {
-					compatible = "fsl,imx53-esdhc";
-					reg = <0x50008000 0x4000>;
-					interrupts = <2>;
-					clocks = <&clks 45>, <&clks 0>, <&clks 72>;
-					clock-names = "ipg", "ahb", "per";
-					bus-width = <4>;
-					status = "disabled";
-				};
-
-				uart3: serial@5000c000 {
-					compatible = "fsl,imx53-uart", "fsl,imx21-uart";
-					reg = <0x5000c000 0x4000>;
-					interrupts = <33>;
-					clocks = <&clks 32>, <&clks 33>;
-					clock-names = "ipg", "per";
-					status = "disabled";
-				};
-
-				ecspi1: ecspi@50010000 {
-					#address-cells = <1>;
-					#size-cells = <0>;
-					compatible = "fsl,imx53-ecspi", "fsl,imx51-ecspi";
-					reg = <0x50010000 0x4000>;
-					interrupts = <36>;
-					clocks = <&clks 51>, <&clks 52>;
-					clock-names = "ipg", "per";
-					status = "disabled";
-				};
-
-				ssi2: ssi@50014000 {
-					compatible = "fsl,imx53-ssi", "fsl,imx21-ssi";
-					reg = <0x50014000 0x4000>;
-					interrupts = <30>;
-					clocks = <&clks 49>;
-					fsl,fifo-depth = <15>;
-					fsl,ssi-dma-events = <25 24 23 22>; /* TX0 RX0 TX1 RX1 */
-					status = "disabled";
-				};
-
-				esdhc3: esdhc@50020000 {
-					compatible = "fsl,imx53-esdhc";
-					reg = <0x50020000 0x4000>;
-					interrupts = <3>;
-					clocks = <&clks 46>, <&clks 0>, <&clks 73>;
-					clock-names = "ipg", "ahb", "per";
-					bus-width = <4>;
-					status = "disabled";
-				};
-
-				esdhc4: esdhc@50024000 {
-					compatible = "fsl,imx53-esdhc";
-					reg = <0x50024000 0x4000>;
-					interrupts = <4>;
-					clocks = <&clks 47>, <&clks 0>, <&clks 74>;
-					clock-names = "ipg", "ahb", "per";
-					bus-width = <4>;
-					status = "disabled";
-				};
-			};
-
-			usbotg: usb@53f80000 {
-				compatible = "fsl,imx53-usb", "fsl,imx27-usb";
-				reg = <0x53f80000 0x0200>;
-				interrupts = <18>;
-				status = "disabled";
-			};
-
-			usbh1: usb@53f80200 {
-				compatible = "fsl,imx53-usb", "fsl,imx27-usb";
-				reg = <0x53f80200 0x0200>;
-				interrupts = <14>;
-				status = "disabled";
-			};
-
-			usbh2: usb@53f80400 {
-				compatible = "fsl,imx53-usb", "fsl,imx27-usb";
-				reg = <0x53f80400 0x0200>;
-				interrupts = <16>;
-				status = "disabled";
-			};
-
-			usbh3: usb@53f80600 {
-				compatible = "fsl,imx53-usb", "fsl,imx27-usb";
-				reg = <0x53f80600 0x0200>;
-				interrupts = <17>;
-				status = "disabled";
-			};
-
-			gpio1: gpio@53f84000 {
-				compatible = "fsl,imx53-gpio", "fsl,imx35-gpio";
-				reg = <0x53f84000 0x4000>;
-				interrupts = <50 51>;
-				gpio-controller;
-				#gpio-cells = <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-			};
-
-			gpio2: gpio@53f88000 {
-				compatible = "fsl,imx53-gpio", "fsl,imx35-gpio";
-				reg = <0x53f88000 0x4000>;
-				interrupts = <52 53>;
-				gpio-controller;
-				#gpio-cells = <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-			};
-
-			gpio3: gpio@53f8c000 {
-				compatible = "fsl,imx53-gpio", "fsl,imx35-gpio";
-				reg = <0x53f8c000 0x4000>;
-				interrupts = <54 55>;
-				gpio-controller;
-				#gpio-cells = <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-			};
-
-			gpio4: gpio@53f90000 {
-				compatible = "fsl,imx53-gpio", "fsl,imx35-gpio";
-				reg = <0x53f90000 0x4000>;
-				interrupts = <56 57>;
-				gpio-controller;
-				#gpio-cells = <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-			};
-
-			wdog1: wdog@53f98000 {
-				compatible = "fsl,imx53-wdt", "fsl,imx21-wdt";
-				reg = <0x53f98000 0x4000>;
-				interrupts = <58>;
-				clocks = <&clks 0>;
-			};
-
-			wdog2: wdog@53f9c000 {
-				compatible = "fsl,imx53-wdt", "fsl,imx21-wdt";
-				reg = <0x53f9c000 0x4000>;
-				interrupts = <59>;
-				clocks = <&clks 0>;
-				status = "disabled";
-			};
-
-			iomuxc: iomuxc@53fa8000 {
-				compatible = "fsl,imx53-iomuxc";
-				reg = <0x53fa8000 0x4000>;
-
-				audmux {
-					pinctrl_audmux_1: audmuxgrp-1 {
-						fsl,pins = <
-							10 0x80000000	/* MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC */
-							17 0x80000000	/* MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD */
-							23 0x80000000	/* MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS */
-							30 0x80000000	/* MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD */
-						>;
-					};
-				};
-
-				fec {
-					pinctrl_fec_1: fecgrp-1 {
-						fsl,pins = <
-							820 0x80000000	/* MX53_PAD_FEC_MDC__FEC_MDC */
-							779 0x80000000	/* MX53_PAD_FEC_MDIO__FEC_MDIO */
-							786 0x80000000	/* MX53_PAD_FEC_REF_CLK__FEC_TX_CLK */
-							791 0x80000000	/* MX53_PAD_FEC_RX_ER__FEC_RX_ER */
-							796 0x80000000	/* MX53_PAD_FEC_CRS_DV__FEC_RX_DV */
-							799 0x80000000	/* MX53_PAD_FEC_RXD1__FEC_RDATA_1 */
-							804 0x80000000	/* MX53_PAD_FEC_RXD0__FEC_RDATA_0 */
-							808 0x80000000	/* MX53_PAD_FEC_TX_EN__FEC_TX_EN */
-							811 0x80000000	/* MX53_PAD_FEC_TXD1__FEC_TDATA_1 */
-							816 0x80000000	/* MX53_PAD_FEC_TXD0__FEC_TDATA_0 */
-						>;
-					};
-				};
-
-				csi {
-					pinctrl_csi_1: csigrp-1 {
-						fsl,pins = <
-							286 0x1d5	/* MX53_PAD_CSI0_DATA_EN__IPU_CSI0_DATA_EN */
-							291 0x1d5	/* MX53_PAD_CSI0_VSYNC__IPU_CSI0_VSYNC */
-							280 0x1d5	/* MX53_PAD_CSI0_MCLK__IPU_CSI0_HSYNC */
-							276 0x1d5	/* MX53_PAD_CSI0_PIXCLK__IPU_CSI0_PIXCLK */
-							409 0x1d5	/* MX53_PAD_CSI0_DAT19__IPU_CSI0_D_19 */
-							402 0x1d5	/* MX53_PAD_CSI0_DAT18__IPU_CSI0_D_18 */
-							395 0x1d5	/* MX53_PAD_CSI0_DAT17__IPU_CSI0_D_17 */
-							388 0x1d5	/* MX53_PAD_CSI0_DAT16__IPU_CSI0_D_16 */
-							381 0x1d5	/* MX53_PAD_CSI0_DAT15__IPU_CSI0_D_15 */
-							374 0x1d5	/* MX53_PAD_CSI0_DAT14__IPU_CSI0_D_14 */
-							367 0x1d5	/* MX53_PAD_CSI0_DAT13__IPU_CSI0_D_13 */
-							360 0x1d5	/* MX53_PAD_CSI0_DAT12__IPU_CSI0_D_12 */
-							352 0x1d5	/* MX53_PAD_CSI0_DAT11__IPU_CSI0_D_11 */
-							344 0x1d5	/* MX53_PAD_CSI0_DAT10__IPU_CSI0_D_10 */
-							336 0x1d5	/* MX53_PAD_CSI0_DAT9__IPU_CSI0_D_9 */
-							328 0x1d5	/* MX53_PAD_CSI0_DAT8__IPU_CSI0_D_8 */
-							320 0x1d5	/* MX53_PAD_CSI0_DAT7__IPU_CSI0_D_7 */
-							312 0x1d5	/* MX53_PAD_CSI0_DAT6__IPU_CSI0_D_6 */
-							304 0x1d5	/* MX53_PAD_CSI0_DAT5__IPU_CSI0_D_5 */
-							296 0x1d5	/* MX53_PAD_CSI0_DAT4__IPU_CSI0_D_4 */
-							276 0x1d5	/* MX53_PAD_CSI0_PIXCLK__IPU_CSI0_PIXCLK */
-						>;
-					};
-				};
-
-				cspi {
-					pinctrl_cspi_1: cspigrp-1 {
-						fsl,pins = <
-							998  0x1d5	/* MX53_PAD_SD1_DATA0__CSPI_MISO */
-							1008 0x1d5	/* MX53_PAD_SD1_CMD__CSPI_MOSI */
-							1022 0x1d5	/* MX53_PAD_SD1_CLK__CSPI_SCLK */
-						>;
-					};
-				};
-
-				ecspi1 {
-					pinctrl_ecspi1_1: ecspi1grp-1 {
-						fsl,pins = <
-							433 0x80000000	/* MX53_PAD_EIM_D16__ECSPI1_SCLK */
-							439 0x80000000	/* MX53_PAD_EIM_D17__ECSPI1_MISO */
-							445 0x80000000	/* MX53_PAD_EIM_D18__ECSPI1_MOSI */
-						>;
-					};
-				};
-
-				esdhc1 {
-					pinctrl_esdhc1_1: esdhc1grp-1 {
-						fsl,pins = <
-							995  0x1d5	/* MX53_PAD_SD1_DATA0__ESDHC1_DAT0 */
-							1000 0x1d5	/* MX53_PAD_SD1_DATA1__ESDHC1_DAT1 */
-							1010 0x1d5	/* MX53_PAD_SD1_DATA2__ESDHC1_DAT2 */
-							1024 0x1d5	/* MX53_PAD_SD1_DATA3__ESDHC1_DAT3 */
-							1005 0x1d5	/* MX53_PAD_SD1_CMD__ESDHC1_CMD */
-							1018 0x1d5	/* MX53_PAD_SD1_CLK__ESDHC1_CLK */
-						>;
-					};
-
-					pinctrl_esdhc1_2: esdhc1grp-2 {
-						fsl,pins = <
-							995  0x1d5	/* MX53_PAD_SD1_DATA0__ESDHC1_DAT0 */
-							1000 0x1d5	/* MX53_PAD_SD1_DATA1__ESDHC1_DAT1 */
-							1010 0x1d5	/* MX53_PAD_SD1_DATA2__ESDHC1_DAT2 */
-							1024 0x1d5	/* MX53_PAD_SD1_DATA3__ESDHC1_DAT3 */
-							941  0x1d5	/* MX53_PAD_PATA_DATA8__ESDHC1_DAT4 */
-							948  0x1d5	/* MX53_PAD_PATA_DATA9__ESDHC1_DAT5 */
-							955  0x1d5	/* MX53_PAD_PATA_DATA10__ESDHC1_DAT6 */
-							962  0x1d5	/* MX53_PAD_PATA_DATA11__ESDHC1_DAT7 */
-							1005 0x1d5	/* MX53_PAD_SD1_CMD__ESDHC1_CMD */
-							1018 0x1d5	/* MX53_PAD_SD1_CLK__ESDHC1_CLK */
-						>;
-					};
-				};
-
-				esdhc2 {
-					pinctrl_esdhc2_1: esdhc2grp-1 {
-						fsl,pins = <
-							1038 0x1d5	/* MX53_PAD_SD2_CMD__ESDHC2_CMD */
-							1032 0x1d5	/* MX53_PAD_SD2_CLK__ESDHC2_CLK */
-							1062 0x1d5	/* MX53_PAD_SD2_DATA0__ESDHC2_DAT0 */
-							1056 0x1d5	/* MX53_PAD_SD2_DATA1__ESDHC2_DAT1 */
-							1050 0x1d5	/* MX53_PAD_SD2_DATA2__ESDHC2_DAT2 */
-							1044 0x1d5	/* MX53_PAD_SD2_DATA3__ESDHC2_DAT3 */
-						>;
-					};
-				};
-
-				esdhc3 {
-					pinctrl_esdhc3_1: esdhc3grp-1 {
-						fsl,pins = <
-							943 0x1d5	/* MX53_PAD_PATA_DATA8__ESDHC3_DAT0 */
-							950 0x1d5	/* MX53_PAD_PATA_DATA9__ESDHC3_DAT1 */
-							957 0x1d5	/* MX53_PAD_PATA_DATA10__ESDHC3_DAT2 */
-							964 0x1d5	/* MX53_PAD_PATA_DATA11__ESDHC3_DAT3 */
-							893 0x1d5	/* MX53_PAD_PATA_DATA0__ESDHC3_DAT4 */
-							900 0x1d5	/* MX53_PAD_PATA_DATA1__ESDHC3_DAT5 */
-							906 0x1d5	/* MX53_PAD_PATA_DATA2__ESDHC3_DAT6 */
-							912 0x1d5	/* MX53_PAD_PATA_DATA3__ESDHC3_DAT7 */
-							857 0x1d5	/* MX53_PAD_PATA_RESET_B__ESDHC3_CMD */
-							863 0x1d5	/* MX53_PAD_PATA_IORDY__ESDHC3_CLK */
-						>;
-					};
-				};
-
-				can1 {
-					pinctrl_can1_1: can1grp-1 {
-						fsl,pins = <
-							847 0x80000000  /* MX53_PAD_PATA_INTRQ__CAN1_TXCAN */
-							853 0x80000000  /* MX53_PAD_PATA_DIOR__CAN1_RXCAN */
-						>;
-					};
-
-					pinctrl_can1_2: can1grp-2 {
-						fsl,pins = <
-							37  0x80000000  /* MX53_PAD_KEY_COL2__CAN1_TXCAN */
-							44  0x80000000  /* MX53_PAD_KEY_ROW2__CAN1_RXCAN */
-						>;
-					};
-				};
-
-				can2 {
-					pinctrl_can2_1: can2grp-1 {
-						fsl,pins = <
-							67  0x80000000  /* MX53_PAD_KEY_COL4__CAN2_TXCAN */
-							74  0x80000000  /* MX53_PAD_KEY_ROW4__CAN2_RXCAN */
-						>;
-					};
-				};
-
-				i2c1 {
-					pinctrl_i2c1_1: i2c1grp-1 {
-						fsl,pins = <
-							333 0xc0000000	/* MX53_PAD_CSI0_DAT8__I2C1_SDA */
-							341 0xc0000000	/* MX53_PAD_CSI0_DAT9__I2C1_SCL */
-						>;
-					};
-				};
-
-				i2c2 {
-					pinctrl_i2c2_1: i2c2grp-1 {
-						fsl,pins = <
-							61 0xc0000000	/* MX53_PAD_KEY_ROW3__I2C2_SDA */
-							53 0xc0000000	/* MX53_PAD_KEY_COL3__I2C2_SCL */
-						>;
-					};
-				};
-
-				i2c3 {
-					pinctrl_i2c3_1: i2c3grp-1 {
-						fsl,pins = <
-							1102 0xc0000000	/* MX53_PAD_GPIO_6__I2C3_SDA */
-							1130 0xc0000000	/* MX53_PAD_GPIO_5__I2C3_SCL */
-						>;
-					};
-				};
-
-				owire {
-					pinctrl_owire_1: owiregrp-1 {
-						fsl,pins = <
-								1166 0x80000000 /* MX53_PAD_GPIO_18__OWIRE_LINE */
-						>;
-					};
-				};
-
-				uart1 {
-					pinctrl_uart1_1: uart1grp-1 {
-						fsl,pins = <
-							346 0x1c5	/* MX53_PAD_CSI0_DAT10__UART1_TXD_MUX */
-							354 0x1c5	/* MX53_PAD_CSI0_DAT11__UART1_RXD_MUX */
-						>;
-					};
-
-					pinctrl_uart1_2: uart1grp-2 {
-						fsl,pins = <
-							828 0x1c5	/* MX53_PAD_PATA_DIOW__UART1_TXD_MUX */
-							832 0x1c5	/* MX53_PAD_PATA_DMACK__UART1_RXD_MUX */
-						>;
-					};
-				};
-
-				uart2 {
-					pinctrl_uart2_1: uart2grp-1 {
-						fsl,pins = <
-							841 0x1c5	/* MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX */
-							836 0x1c5	/* MX53_PAD_PATA_DMARQ__UART2_TXD_MUX */
-						>;
-					};
-				};
-
-				uart3 {
-					pinctrl_uart3_1: uart3grp-1 {
-						fsl,pins = <
-							884 0x1c5	/* MX53_PAD_PATA_CS_0__UART3_TXD_MUX */
-							888 0x1c5	/* MX53_PAD_PATA_CS_1__UART3_RXD_MUX */
-							875 0x1c5	/* MX53_PAD_PATA_DA_1__UART3_CTS */
-							880 0x1c5	/* MX53_PAD_PATA_DA_2__UART3_RTS */
-						>;
-					};
-
-					pinctrl_uart3_2: uart3grp-2 {
-						fsl,pins = <
-							884 0x1c5	/* MX53_PAD_PATA_CS_0__UART3_TXD_MUX */
-							888 0x1c5	/* MX53_PAD_PATA_CS_1__UART3_RXD_MUX */
-						>;
-					};
-
-				};
-
-				uart4 {
-					pinctrl_uart4_1: uart4grp-1 {
-						fsl,pins = <
-							11 0x1c5	/* MX53_PAD_KEY_COL0__UART4_TXD_MUX */
-							18 0x1c5	/* MX53_PAD_KEY_ROW0__UART4_RXD_MUX */
-						>;
-					};
-				};
-
-				uart5 {
-					pinctrl_uart5_1: uart5grp-1 {
-						fsl,pins = <
-							24 0x1c5	/* MX53_PAD_KEY_COL1__UART5_TXD_MUX */
-							31 0x1c5	/* MX53_PAD_KEY_ROW1__UART5_RXD_MUX */
-						>;
-					};
-				};
-
-			};
-
-			pwm1: pwm@53fb4000 {
-				#pwm-cells = <2>;
-				compatible = "fsl,imx53-pwm", "fsl,imx27-pwm";
-				reg = <0x53fb4000 0x4000>;
-				clocks = <&clks 37>, <&clks 38>;
-				clock-names = "ipg", "per";
-				interrupts = <61>;
-			};
-
-			pwm2: pwm@53fb8000 {
-				#pwm-cells = <2>;
-				compatible = "fsl,imx53-pwm", "fsl,imx27-pwm";
-				reg = <0x53fb8000 0x4000>;
-				clocks = <&clks 39>, <&clks 40>;
-				clock-names = "ipg", "per";
-				interrupts = <94>;
-			};
-
-			uart1: serial@53fbc000 {
-				compatible = "fsl,imx53-uart", "fsl,imx21-uart";
-				reg = <0x53fbc000 0x4000>;
-				interrupts = <31>;
-				clocks = <&clks 28>, <&clks 29>;
-				clock-names = "ipg", "per";
-				status = "disabled";
-			};
-
-			uart2: serial@53fc0000 {
-				compatible = "fsl,imx53-uart", "fsl,imx21-uart";
-				reg = <0x53fc0000 0x4000>;
-				interrupts = <32>;
-				clocks = <&clks 30>, <&clks 31>;
-				clock-names = "ipg", "per";
-				status = "disabled";
-			};
-
-			can1: can@53fc8000 {
-				compatible = "fsl,imx53-flexcan", "fsl,p1010-flexcan";
-				reg = <0x53fc8000 0x4000>;
-				interrupts = <82>;
-				clocks = <&clks 158>, <&clks 157>;
-				clock-names = "ipg", "per";
-				status = "disabled";
-			};
-
-			can2: can@53fcc000 {
-				compatible = "fsl,imx53-flexcan", "fsl,p1010-flexcan";
-				reg = <0x53fcc000 0x4000>;
-				interrupts = <83>;
-				clocks = <&clks 87>, <&clks 86>;
-				clock-names = "ipg", "per";
-				status = "disabled";
-			};
-
-			clks: ccm@53fd4000{
-				compatible = "fsl,imx53-ccm";
-				reg = <0x53fd4000 0x4000>;
-				interrupts = <0 71 0x04 0 72 0x04>;
-				#clock-cells = <1>;
-			};
-
-			gpio5: gpio@53fdc000 {
-				compatible = "fsl,imx53-gpio", "fsl,imx35-gpio";
-				reg = <0x53fdc000 0x4000>;
-				interrupts = <103 104>;
-				gpio-controller;
-				#gpio-cells = <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-			};
-
-			gpio6: gpio@53fe0000 {
-				compatible = "fsl,imx53-gpio", "fsl,imx35-gpio";
-				reg = <0x53fe0000 0x4000>;
-				interrupts = <105 106>;
-				gpio-controller;
-				#gpio-cells = <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-			};
-
-			gpio7: gpio@53fe4000 {
-				compatible = "fsl,imx53-gpio", "fsl,imx35-gpio";
-				reg = <0x53fe4000 0x4000>;
-				interrupts = <107 108>;
-				gpio-controller;
-				#gpio-cells = <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-			};
-
-			i2c3: i2c@53fec000 {
-				#address-cells = <1>;
-				#size-cells = <0>;
-				compatible = "fsl,imx53-i2c", "fsl,imx21-i2c";
-				reg = <0x53fec000 0x4000>;
-				interrupts = <64>;
-				clocks = <&clks 88>;
-				status = "disabled";
-			};
-
-			uart4: serial@53ff0000 {
-				compatible = "fsl,imx53-uart", "fsl,imx21-uart";
-				reg = <0x53ff0000 0x4000>;
-				interrupts = <13>;
-				clocks = <&clks 65>, <&clks 66>;
-				clock-names = "ipg", "per";
-				status = "disabled";
-			};
-		};
-
-		aips@60000000 {	/* AIPS2 */
-			compatible = "fsl,aips-bus", "simple-bus";
-			#address-cells = <1>;
-			#size-cells = <1>;
-			reg = <0x60000000 0x10000000>;
-			ranges;
-
-			uart5: serial@63f90000 {
-				compatible = "fsl,imx53-uart", "fsl,imx21-uart";
-				reg = <0x63f90000 0x4000>;
-				interrupts = <86>;
-				clocks = <&clks 67>, <&clks 68>;
-				clock-names = "ipg", "per";
-				status = "disabled";
-			};
-
-			owire: owire@63fa4000 {
-				compatible = "fsl,imx53-owire", "fsl,imx21-owire";
-				reg = <0x63fa4000 0x4000>;
-				clocks = <&clks 159>;
-				status = "disabled";
-			};
-
-			ecspi2: ecspi@63fac000 {
-				#address-cells = <1>;
-				#size-cells = <0>;
-				compatible = "fsl,imx53-ecspi", "fsl,imx51-ecspi";
-				reg = <0x63fac000 0x4000>;
-				interrupts = <37>;
-				clocks = <&clks 53>, <&clks 54>;
-				clock-names = "ipg", "per";
-				status = "disabled";
-			};
-
-			sdma: sdma@63fb0000 {
-				compatible = "fsl,imx53-sdma", "fsl,imx35-sdma";
-				reg = <0x63fb0000 0x4000>;
-				interrupts = <6>;
-				clocks = <&clks 56>, <&clks 56>;
-				clock-names = "ipg", "ahb";
-				fsl,sdma-ram-script-name = "imx/sdma/sdma-imx53.bin";
-			};
-
-			cspi: cspi@63fc0000 {
-				#address-cells = <1>;
-				#size-cells = <0>;
-				compatible = "fsl,imx53-cspi", "fsl,imx35-cspi";
-				reg = <0x63fc0000 0x4000>;
-				interrupts = <38>;
-				clocks = <&clks 55>, <&clks 0>;
-				clock-names = "ipg", "per";
-				status = "disabled";
-			};
-
-			i2c2: i2c@63fc4000 {
-				#address-cells = <1>;
-				#size-cells = <0>;
-				compatible = "fsl,imx53-i2c", "fsl,imx21-i2c";
-				reg = <0x63fc4000 0x4000>;
-				interrupts = <63>;
-				clocks = <&clks 35>;
-				status = "disabled";
-			};
-
-			i2c1: i2c@63fc8000 {
-				#address-cells = <1>;
-				#size-cells = <0>;
-				compatible = "fsl,imx53-i2c", "fsl,imx21-i2c";
-				reg = <0x63fc8000 0x4000>;
-				interrupts = <62>;
-				clocks = <&clks 34>;
-				status = "disabled";
-			};
-
-			ssi1: ssi@63fcc000 {
-				compatible = "fsl,imx53-ssi", "fsl,imx21-ssi";
-				reg = <0x63fcc000 0x4000>;
-				interrupts = <29>;
-				clocks = <&clks 48>;
-				fsl,fifo-depth = <15>;
-				fsl,ssi-dma-events = <29 28 27 26>; /* TX0 RX0 TX1 RX1 */
-				status = "disabled";
-			};
-
-			audmux: audmux@63fd0000 {
-				compatible = "fsl,imx53-audmux", "fsl,imx31-audmux";
-				reg = <0x63fd0000 0x4000>;
-				status = "disabled";
-			};
-
-			nfc: nand@63fdb000 {
-				compatible = "fsl,imx53-nand";
-				reg = <0x63fdb000 0x1000 0xf7ff0000 0x10000>;
-				interrupts = <8>;
-				clocks = <&clks 60>;
-				status = "disabled";
-			};
-
-			ssi3: ssi@63fe8000 {
-				compatible = "fsl,imx53-ssi", "fsl,imx21-ssi";
-				reg = <0x63fe8000 0x4000>;
-				interrupts = <96>;
-				clocks = <&clks 50>;
-				fsl,fifo-depth = <15>;
-				fsl,ssi-dma-events = <47 46 45 44>; /* TX0 RX0 TX1 RX1 */
-				status = "disabled";
-			};
-
-			fec: ethernet@63fec000 {
-				compatible = "fsl,imx53-fec", "fsl,imx25-fec";
-				reg = <0x63fec000 0x4000>;
-				interrupts = <87>;
-				clocks = <&clks 42>, <&clks 42>, <&clks 42>;
-				clock-names = "ipg", "ahb", "ptp";
-				status = "disabled";
-			};
-		};
-	};
-};
diff --git a/arch/arm/boot/dts/imx53.dtsip b/arch/arm/boot/dts/imx53.dtsip
new file mode 100644
index 0000000..845982e
--- /dev/null
+++ b/arch/arm/boot/dts/imx53.dtsip
@@ -0,0 +1,786 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * 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 "skeleton.dtsi"
+#include "imx53-pinfunc.h"
+
+/ {
+	aliases {
+		serial0 = &uart1;
+		serial1 = &uart2;
+		serial2 = &uart3;
+		serial3 = &uart4;
+		serial4 = &uart5;
+		gpio0 = &gpio1;
+		gpio1 = &gpio2;
+		gpio2 = &gpio3;
+		gpio3 = &gpio4;
+		gpio4 = &gpio5;
+		gpio5 = &gpio6;
+		gpio6 = &gpio7;
+	};
+
+	tzic: tz-interrupt-controller@0fffc000 {
+		compatible = "fsl,imx53-tzic", "fsl,tzic";
+		interrupt-controller;
+		#interrupt-cells = <1>;
+		reg = <0x0fffc000 0x4000>;
+	};
+
+	clocks {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		ckil {
+			compatible = "fsl,imx-ckil", "fixed-clock";
+			clock-frequency = <32768>;
+		};
+
+		ckih1 {
+			compatible = "fsl,imx-ckih1", "fixed-clock";
+			clock-frequency = <22579200>;
+		};
+
+		ckih2 {
+			compatible = "fsl,imx-ckih2", "fixed-clock";
+			clock-frequency = <0>;
+		};
+
+		osc {
+			compatible = "fsl,imx-osc", "fixed-clock";
+			clock-frequency = <24000000>;
+		};
+	};
+
+	soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		interrupt-parent = <&tzic>;
+		ranges;
+
+		ipu: ipu@18000000 {
+			#crtc-cells = <1>;
+			compatible = "fsl,imx53-ipu";
+			reg = <0x18000000 0x080000000>;
+			interrupts = <11 10>;
+			clocks = <&clks 59>, <&clks 110>, <&clks 61>;
+			clock-names = "bus", "di0", "di1";
+			resets = <&src 2>;
+		};
+
+		aips@50000000 { /* AIPS1 */
+			compatible = "fsl,aips-bus", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x50000000 0x10000000>;
+			ranges;
+
+			spba@50000000 {
+				compatible = "fsl,spba-bus", "simple-bus";
+				#address-cells = <1>;
+				#size-cells = <1>;
+				reg = <0x50000000 0x40000>;
+				ranges;
+
+				esdhc1: esdhc@50004000 {
+					compatible = "fsl,imx53-esdhc";
+					reg = <0x50004000 0x4000>;
+					interrupts = <1>;
+					clocks = <&clks 44>, <&clks 0>, <&clks 71>;
+					clock-names = "ipg", "ahb", "per";
+					bus-width = <4>;
+					status = "disabled";
+				};
+
+				esdhc2: esdhc@50008000 {
+					compatible = "fsl,imx53-esdhc";
+					reg = <0x50008000 0x4000>;
+					interrupts = <2>;
+					clocks = <&clks 45>, <&clks 0>, <&clks 72>;
+					clock-names = "ipg", "ahb", "per";
+					bus-width = <4>;
+					status = "disabled";
+				};
+
+				uart3: serial@5000c000 {
+					compatible = "fsl,imx53-uart", "fsl,imx21-uart";
+					reg = <0x5000c000 0x4000>;
+					interrupts = <33>;
+					clocks = <&clks 32>, <&clks 33>;
+					clock-names = "ipg", "per";
+					status = "disabled";
+				};
+
+				ecspi1: ecspi@50010000 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					compatible = "fsl,imx53-ecspi", "fsl,imx51-ecspi";
+					reg = <0x50010000 0x4000>;
+					interrupts = <36>;
+					clocks = <&clks 51>, <&clks 52>;
+					clock-names = "ipg", "per";
+					status = "disabled";
+				};
+
+				ssi2: ssi@50014000 {
+					compatible = "fsl,imx53-ssi", "fsl,imx21-ssi";
+					reg = <0x50014000 0x4000>;
+					interrupts = <30>;
+					clocks = <&clks 49>;
+					fsl,fifo-depth = <15>;
+					fsl,ssi-dma-events = <25 24 23 22>; /* TX0 RX0 TX1 RX1 */
+					status = "disabled";
+				};
+
+				esdhc3: esdhc@50020000 {
+					compatible = "fsl,imx53-esdhc";
+					reg = <0x50020000 0x4000>;
+					interrupts = <3>;
+					clocks = <&clks 46>, <&clks 0>, <&clks 73>;
+					clock-names = "ipg", "ahb", "per";
+					bus-width = <4>;
+					status = "disabled";
+				};
+
+				esdhc4: esdhc@50024000 {
+					compatible = "fsl,imx53-esdhc";
+					reg = <0x50024000 0x4000>;
+					interrupts = <4>;
+					clocks = <&clks 47>, <&clks 0>, <&clks 74>;
+					clock-names = "ipg", "ahb", "per";
+					bus-width = <4>;
+					status = "disabled";
+				};
+			};
+
+			usbotg: usb@53f80000 {
+				compatible = "fsl,imx53-usb", "fsl,imx27-usb";
+				reg = <0x53f80000 0x0200>;
+				interrupts = <18>;
+				status = "disabled";
+			};
+
+			usbh1: usb@53f80200 {
+				compatible = "fsl,imx53-usb", "fsl,imx27-usb";
+				reg = <0x53f80200 0x0200>;
+				interrupts = <14>;
+				status = "disabled";
+			};
+
+			usbh2: usb@53f80400 {
+				compatible = "fsl,imx53-usb", "fsl,imx27-usb";
+				reg = <0x53f80400 0x0200>;
+				interrupts = <16>;
+				status = "disabled";
+			};
+
+			usbh3: usb@53f80600 {
+				compatible = "fsl,imx53-usb", "fsl,imx27-usb";
+				reg = <0x53f80600 0x0200>;
+				interrupts = <17>;
+				status = "disabled";
+			};
+
+			gpio1: gpio@53f84000 {
+				compatible = "fsl,imx53-gpio", "fsl,imx35-gpio";
+				reg = <0x53f84000 0x4000>;
+				interrupts = <50 51>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+			};
+
+			gpio2: gpio@53f88000 {
+				compatible = "fsl,imx53-gpio", "fsl,imx35-gpio";
+				reg = <0x53f88000 0x4000>;
+				interrupts = <52 53>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+			};
+
+			gpio3: gpio@53f8c000 {
+				compatible = "fsl,imx53-gpio", "fsl,imx35-gpio";
+				reg = <0x53f8c000 0x4000>;
+				interrupts = <54 55>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+			};
+
+			gpio4: gpio@53f90000 {
+				compatible = "fsl,imx53-gpio", "fsl,imx35-gpio";
+				reg = <0x53f90000 0x4000>;
+				interrupts = <56 57>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+			};
+
+			wdog1: wdog@53f98000 {
+				compatible = "fsl,imx53-wdt", "fsl,imx21-wdt";
+				reg = <0x53f98000 0x4000>;
+				interrupts = <58>;
+				clocks = <&clks 0>;
+			};
+
+			wdog2: wdog@53f9c000 {
+				compatible = "fsl,imx53-wdt", "fsl,imx21-wdt";
+				reg = <0x53f9c000 0x4000>;
+				interrupts = <59>;
+				clocks = <&clks 0>;
+				status = "disabled";
+			};
+
+			gpt: timer@53fa0000 {
+				compatible = "fsl,imx53-gpt", "fsl,imx31-gpt";
+				reg = <0x53fa0000 0x4000>;
+				interrupts = <39>;
+				clocks = <&clks 36>, <&clks 41>;
+				clock-names = "ipg", "per";
+			};
+
+			iomuxc: iomuxc@53fa8000 {
+				compatible = "fsl,imx53-iomuxc";
+				reg = <0x53fa8000 0x4000>;
+
+				audmux {
+					pinctrl_audmux_1: audmuxgrp-1 {
+						fsl,pins = <
+							MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC  0x80000000
+							MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD  0x80000000
+							MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS 0x80000000
+							MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD  0x80000000
+						>;
+					};
+				};
+
+				fec {
+					pinctrl_fec_1: fecgrp-1 {
+						fsl,pins = <
+							MX53_PAD_FEC_MDC__FEC_MDC	 0x80000000
+							MX53_PAD_FEC_MDIO__FEC_MDIO	 0x80000000
+							MX53_PAD_FEC_REF_CLK__FEC_TX_CLK 0x80000000
+							MX53_PAD_FEC_RX_ER__FEC_RX_ER    0x80000000
+							MX53_PAD_FEC_CRS_DV__FEC_RX_DV   0x80000000
+							MX53_PAD_FEC_RXD1__FEC_RDATA_1   0x80000000
+							MX53_PAD_FEC_RXD0__FEC_RDATA_0   0x80000000
+							MX53_PAD_FEC_TX_EN__FEC_TX_EN    0x80000000
+							MX53_PAD_FEC_TXD1__FEC_TDATA_1   0x80000000
+							MX53_PAD_FEC_TXD0__FEC_TDATA_0   0x80000000
+						>;
+					};
+				};
+
+				csi {
+					pinctrl_csi_1: csigrp-1 {
+						fsl,pins = <
+							MX53_PAD_CSI0_DATA_EN__IPU_CSI0_DATA_EN 0x1d5
+							MX53_PAD_CSI0_VSYNC__IPU_CSI0_VSYNC     0x1d5
+							MX53_PAD_CSI0_MCLK__IPU_CSI0_HSYNC      0x1d5
+							MX53_PAD_CSI0_PIXCLK__IPU_CSI0_PIXCLK   0x1d5
+							MX53_PAD_CSI0_DAT19__IPU_CSI0_D_19      0x1d5
+							MX53_PAD_CSI0_DAT18__IPU_CSI0_D_18      0x1d5
+							MX53_PAD_CSI0_DAT17__IPU_CSI0_D_17      0x1d5
+							MX53_PAD_CSI0_DAT16__IPU_CSI0_D_16      0x1d5
+							MX53_PAD_CSI0_DAT15__IPU_CSI0_D_15      0x1d5
+							MX53_PAD_CSI0_DAT14__IPU_CSI0_D_14      0x1d5
+							MX53_PAD_CSI0_DAT13__IPU_CSI0_D_13      0x1d5
+							MX53_PAD_CSI0_DAT12__IPU_CSI0_D_12      0x1d5
+							MX53_PAD_CSI0_DAT11__IPU_CSI0_D_11      0x1d5
+							MX53_PAD_CSI0_DAT10__IPU_CSI0_D_10      0x1d5
+							MX53_PAD_CSI0_DAT9__IPU_CSI0_D_9	0x1d5
+							MX53_PAD_CSI0_DAT8__IPU_CSI0_D_8	0x1d5
+							MX53_PAD_CSI0_DAT7__IPU_CSI0_D_7	0x1d5
+							MX53_PAD_CSI0_DAT6__IPU_CSI0_D_6	0x1d5
+							MX53_PAD_CSI0_DAT5__IPU_CSI0_D_5	0x1d5
+							MX53_PAD_CSI0_DAT4__IPU_CSI0_D_4	0x1d5
+							MX53_PAD_CSI0_PIXCLK__IPU_CSI0_PIXCLK   0x1d5
+						>;
+					};
+				};
+
+				cspi {
+					pinctrl_cspi_1: cspigrp-1 {
+						fsl,pins = <
+							MX53_PAD_SD1_DATA0__CSPI_MISO 0x1d5
+							MX53_PAD_SD1_CMD__CSPI_MOSI   0x1d5
+							MX53_PAD_SD1_CLK__CSPI_SCLK   0x1d5
+						>;
+					};
+				};
+
+				ecspi1 {
+					pinctrl_ecspi1_1: ecspi1grp-1 {
+						fsl,pins = <
+							MX53_PAD_EIM_D16__ECSPI1_SCLK 0x80000000
+							MX53_PAD_EIM_D17__ECSPI1_MISO 0x80000000
+							MX53_PAD_EIM_D18__ECSPI1_MOSI 0x80000000
+						>;
+					};
+				};
+
+				esdhc1 {
+					pinctrl_esdhc1_1: esdhc1grp-1 {
+						fsl,pins = <
+							MX53_PAD_SD1_DATA0__ESDHC1_DAT0 0x1d5
+							MX53_PAD_SD1_DATA1__ESDHC1_DAT1 0x1d5
+							MX53_PAD_SD1_DATA2__ESDHC1_DAT2 0x1d5
+							MX53_PAD_SD1_DATA3__ESDHC1_DAT3 0x1d5
+							MX53_PAD_SD1_CMD__ESDHC1_CMD	0x1d5
+							MX53_PAD_SD1_CLK__ESDHC1_CLK	0x1d5
+						>;
+					};
+
+					pinctrl_esdhc1_2: esdhc1grp-2 {
+						fsl,pins = <
+							MX53_PAD_SD1_DATA0__ESDHC1_DAT0   0x1d5
+							MX53_PAD_SD1_DATA1__ESDHC1_DAT1   0x1d5
+							MX53_PAD_SD1_DATA2__ESDHC1_DAT2   0x1d5
+							MX53_PAD_SD1_DATA3__ESDHC1_DAT3   0x1d5
+							MX53_PAD_PATA_DATA8__ESDHC1_DAT4  0x1d5
+							MX53_PAD_PATA_DATA9__ESDHC1_DAT5  0x1d5
+							MX53_PAD_PATA_DATA10__ESDHC1_DAT6 0x1d5
+							MX53_PAD_PATA_DATA11__ESDHC1_DAT7 0x1d5
+							MX53_PAD_SD1_CMD__ESDHC1_CMD	  0x1d5
+							MX53_PAD_SD1_CLK__ESDHC1_CLK	  0x1d5
+						>;
+					};
+				};
+
+				esdhc2 {
+					pinctrl_esdhc2_1: esdhc2grp-1 {
+						fsl,pins = <
+							MX53_PAD_SD2_CMD__ESDHC2_CMD	0x1d5
+							MX53_PAD_SD2_CLK__ESDHC2_CLK	0x1d5
+							MX53_PAD_SD2_DATA0__ESDHC2_DAT0 0x1d5
+							MX53_PAD_SD2_DATA1__ESDHC2_DAT1 0x1d5
+							MX53_PAD_SD2_DATA2__ESDHC2_DAT2 0x1d5
+							MX53_PAD_SD2_DATA3__ESDHC2_DAT3 0x1d5
+						>;
+					};
+				};
+
+				esdhc3 {
+					pinctrl_esdhc3_1: esdhc3grp-1 {
+						fsl,pins = <
+							MX53_PAD_PATA_DATA8__ESDHC3_DAT0  0x1d5
+							MX53_PAD_PATA_DATA9__ESDHC3_DAT1  0x1d5
+							MX53_PAD_PATA_DATA10__ESDHC3_DAT2 0x1d5
+							MX53_PAD_PATA_DATA11__ESDHC3_DAT3 0x1d5
+							MX53_PAD_PATA_DATA0__ESDHC3_DAT4  0x1d5
+							MX53_PAD_PATA_DATA1__ESDHC3_DAT5  0x1d5
+							MX53_PAD_PATA_DATA2__ESDHC3_DAT6  0x1d5
+							MX53_PAD_PATA_DATA3__ESDHC3_DAT7  0x1d5
+							MX53_PAD_PATA_RESET_B__ESDHC3_CMD 0x1d5
+							MX53_PAD_PATA_IORDY__ESDHC3_CLK   0x1d5
+						>;
+					};
+				};
+
+				can1 {
+					pinctrl_can1_1: can1grp-1 {
+						fsl,pins = <
+							MX53_PAD_PATA_INTRQ__CAN1_TXCAN 0x80000000
+							MX53_PAD_PATA_DIOR__CAN1_RXCAN  0x80000000
+						>;
+					};
+
+					pinctrl_can1_2: can1grp-2 {
+						fsl,pins = <
+							MX53_PAD_KEY_COL2__CAN1_TXCAN 0x80000000
+							MX53_PAD_KEY_ROW2__CAN1_RXCAN 0x80000000
+						>;
+					};
+				};
+
+				can2 {
+					pinctrl_can2_1: can2grp-1 {
+						fsl,pins = <
+							MX53_PAD_KEY_COL4__CAN2_TXCAN 0x80000000
+							MX53_PAD_KEY_ROW4__CAN2_RXCAN 0x80000000
+						>;
+					};
+				};
+
+				i2c1 {
+					pinctrl_i2c1_1: i2c1grp-1 {
+						fsl,pins = <
+							MX53_PAD_CSI0_DAT8__I2C1_SDA 0xc0000000
+							MX53_PAD_CSI0_DAT9__I2C1_SCL 0xc0000000
+						>;
+					};
+				};
+
+				i2c2 {
+					pinctrl_i2c2_1: i2c2grp-1 {
+						fsl,pins = <
+							MX53_PAD_KEY_ROW3__I2C2_SDA 0xc0000000
+							MX53_PAD_KEY_COL3__I2C2_SCL 0xc0000000
+						>;
+					};
+				};
+
+				i2c3 {
+					pinctrl_i2c3_1: i2c3grp-1 {
+						fsl,pins = <
+							MX53_PAD_GPIO_6__I2C3_SDA 0xc0000000
+							MX53_PAD_GPIO_5__I2C3_SCL 0xc0000000
+						>;
+					};
+				};
+
+				owire {
+					pinctrl_owire_1: owiregrp-1 {
+						fsl,pins = <
+							MX53_PAD_GPIO_18__OWIRE_LINE 0x80000000
+						>;
+					};
+				};
+
+				uart1 {
+					pinctrl_uart1_1: uart1grp-1 {
+						fsl,pins = <
+							MX53_PAD_CSI0_DAT10__UART1_TXD_MUX 0x1c5
+							MX53_PAD_CSI0_DAT11__UART1_RXD_MUX 0x1c5
+						>;
+					};
+
+					pinctrl_uart1_2: uart1grp-2 {
+						fsl,pins = <
+							MX53_PAD_PATA_DIOW__UART1_TXD_MUX  0x1c5
+							MX53_PAD_PATA_DMACK__UART1_RXD_MUX 0x1c5
+						>;
+					};
+				};
+
+				uart2 {
+					pinctrl_uart2_1: uart2grp-1 {
+						fsl,pins = <
+							MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX 0x1c5
+							MX53_PAD_PATA_DMARQ__UART2_TXD_MUX     0x1c5
+						>;
+					};
+				};
+
+				uart3 {
+					pinctrl_uart3_1: uart3grp-1 {
+						fsl,pins = <
+							MX53_PAD_PATA_CS_0__UART3_TXD_MUX 0x1c5
+							MX53_PAD_PATA_CS_1__UART3_RXD_MUX 0x1c5
+							MX53_PAD_PATA_DA_1__UART3_CTS	  0x1c5
+							MX53_PAD_PATA_DA_2__UART3_RTS	  0x1c5
+						>;
+					};
+
+					pinctrl_uart3_2: uart3grp-2 {
+						fsl,pins = <
+							MX53_PAD_PATA_CS_0__UART3_TXD_MUX 0x1c5
+							MX53_PAD_PATA_CS_1__UART3_RXD_MUX 0x1c5
+						>;
+					};
+
+				};
+
+				uart4 {
+					pinctrl_uart4_1: uart4grp-1 {
+						fsl,pins = <
+							MX53_PAD_KEY_COL0__UART4_TXD_MUX 0x1c5
+							MX53_PAD_KEY_ROW0__UART4_RXD_MUX 0x1c5
+						>;
+					};
+				};
+
+				uart5 {
+					pinctrl_uart5_1: uart5grp-1 {
+						fsl,pins = <
+							MX53_PAD_KEY_COL1__UART5_TXD_MUX 0x1c5
+							MX53_PAD_KEY_ROW1__UART5_RXD_MUX 0x1c5
+						>;
+					};
+				};
+
+			};
+
+			gpr: iomuxc-gpr@53fa8000 {
+				compatible = "fsl,imx53-iomuxc-gpr", "syscon";
+				reg = <0x53fa8000 0xc>;
+			};
+
+			ldb: ldb@53fa8008 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx53-ldb";
+				reg = <0x53fa8008 0x4>;
+				gpr = <&gpr>;
+				clocks = <&clks 122>, <&clks 120>,
+					 <&clks 115>, <&clks 116>,
+					 <&clks 123>, <&clks 85>;
+				clock-names = "di0_pll", "di1_pll",
+					      "di0_sel", "di1_sel",
+					      "di0", "di1";
+				status = "disabled";
+
+				lvds-channel@0 {
+					reg = <0>;
+					crtcs = <&ipu 0>;
+					status = "disabled";
+				};
+
+				lvds-channel@1 {
+					reg = <1>;
+					crtcs = <&ipu 1>;
+					status = "disabled";
+				};
+			};
+
+			pwm1: pwm@53fb4000 {
+				#pwm-cells = <2>;
+				compatible = "fsl,imx53-pwm", "fsl,imx27-pwm";
+				reg = <0x53fb4000 0x4000>;
+				clocks = <&clks 37>, <&clks 38>;
+				clock-names = "ipg", "per";
+				interrupts = <61>;
+			};
+
+			pwm2: pwm@53fb8000 {
+				#pwm-cells = <2>;
+				compatible = "fsl,imx53-pwm", "fsl,imx27-pwm";
+				reg = <0x53fb8000 0x4000>;
+				clocks = <&clks 39>, <&clks 40>;
+				clock-names = "ipg", "per";
+				interrupts = <94>;
+			};
+
+			uart1: serial@53fbc000 {
+				compatible = "fsl,imx53-uart", "fsl,imx21-uart";
+				reg = <0x53fbc000 0x4000>;
+				interrupts = <31>;
+				clocks = <&clks 28>, <&clks 29>;
+				clock-names = "ipg", "per";
+				status = "disabled";
+			};
+
+			uart2: serial@53fc0000 {
+				compatible = "fsl,imx53-uart", "fsl,imx21-uart";
+				reg = <0x53fc0000 0x4000>;
+				interrupts = <32>;
+				clocks = <&clks 30>, <&clks 31>;
+				clock-names = "ipg", "per";
+				status = "disabled";
+			};
+
+			can1: can@53fc8000 {
+				compatible = "fsl,imx53-flexcan", "fsl,p1010-flexcan";
+				reg = <0x53fc8000 0x4000>;
+				interrupts = <82>;
+				clocks = <&clks 158>, <&clks 157>;
+				clock-names = "ipg", "per";
+				status = "disabled";
+			};
+
+			can2: can@53fcc000 {
+				compatible = "fsl,imx53-flexcan", "fsl,p1010-flexcan";
+				reg = <0x53fcc000 0x4000>;
+				interrupts = <83>;
+				clocks = <&clks 87>, <&clks 86>;
+				clock-names = "ipg", "per";
+				status = "disabled";
+			};
+
+			src: src@53fd0000 {
+				compatible = "fsl,imx53-src", "fsl,imx51-src";
+				reg = <0x53fd0000 0x4000>;
+				#reset-cells = <1>;
+			};
+
+			clks: ccm@53fd4000{
+				compatible = "fsl,imx53-ccm";
+				reg = <0x53fd4000 0x4000>;
+				interrupts = <0 71 0x04 0 72 0x04>;
+				#clock-cells = <1>;
+			};
+
+			gpio5: gpio@53fdc000 {
+				compatible = "fsl,imx53-gpio", "fsl,imx35-gpio";
+				reg = <0x53fdc000 0x4000>;
+				interrupts = <103 104>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+			};
+
+			gpio6: gpio@53fe0000 {
+				compatible = "fsl,imx53-gpio", "fsl,imx35-gpio";
+				reg = <0x53fe0000 0x4000>;
+				interrupts = <105 106>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+			};
+
+			gpio7: gpio@53fe4000 {
+				compatible = "fsl,imx53-gpio", "fsl,imx35-gpio";
+				reg = <0x53fe4000 0x4000>;
+				interrupts = <107 108>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+			};
+
+			i2c3: i2c@53fec000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx53-i2c", "fsl,imx21-i2c";
+				reg = <0x53fec000 0x4000>;
+				interrupts = <64>;
+				clocks = <&clks 88>;
+				status = "disabled";
+			};
+
+			uart4: serial@53ff0000 {
+				compatible = "fsl,imx53-uart", "fsl,imx21-uart";
+				reg = <0x53ff0000 0x4000>;
+				interrupts = <13>;
+				clocks = <&clks 65>, <&clks 66>;
+				clock-names = "ipg", "per";
+				status = "disabled";
+			};
+		};
+
+		aips@60000000 {	/* AIPS2 */
+			compatible = "fsl,aips-bus", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x60000000 0x10000000>;
+			ranges;
+
+			uart5: serial@63f90000 {
+				compatible = "fsl,imx53-uart", "fsl,imx21-uart";
+				reg = <0x63f90000 0x4000>;
+				interrupts = <86>;
+				clocks = <&clks 67>, <&clks 68>;
+				clock-names = "ipg", "per";
+				status = "disabled";
+			};
+
+			owire: owire@63fa4000 {
+				compatible = "fsl,imx53-owire", "fsl,imx21-owire";
+				reg = <0x63fa4000 0x4000>;
+				clocks = <&clks 159>;
+				status = "disabled";
+			};
+
+			ecspi2: ecspi@63fac000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx53-ecspi", "fsl,imx51-ecspi";
+				reg = <0x63fac000 0x4000>;
+				interrupts = <37>;
+				clocks = <&clks 53>, <&clks 54>;
+				clock-names = "ipg", "per";
+				status = "disabled";
+			};
+
+			sdma: sdma@63fb0000 {
+				compatible = "fsl,imx53-sdma", "fsl,imx35-sdma";
+				reg = <0x63fb0000 0x4000>;
+				interrupts = <6>;
+				clocks = <&clks 56>, <&clks 56>;
+				clock-names = "ipg", "ahb";
+				fsl,sdma-ram-script-name = "imx/sdma/sdma-imx53.bin";
+			};
+
+			cspi: cspi@63fc0000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx53-cspi", "fsl,imx35-cspi";
+				reg = <0x63fc0000 0x4000>;
+				interrupts = <38>;
+				clocks = <&clks 55>, <&clks 0>;
+				clock-names = "ipg", "per";
+				status = "disabled";
+			};
+
+			i2c2: i2c@63fc4000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx53-i2c", "fsl,imx21-i2c";
+				reg = <0x63fc4000 0x4000>;
+				interrupts = <63>;
+				clocks = <&clks 35>;
+				status = "disabled";
+			};
+
+			i2c1: i2c@63fc8000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx53-i2c", "fsl,imx21-i2c";
+				reg = <0x63fc8000 0x4000>;
+				interrupts = <62>;
+				clocks = <&clks 34>;
+				status = "disabled";
+			};
+
+			ssi1: ssi@63fcc000 {
+				compatible = "fsl,imx53-ssi", "fsl,imx21-ssi";
+				reg = <0x63fcc000 0x4000>;
+				interrupts = <29>;
+				clocks = <&clks 48>;
+				fsl,fifo-depth = <15>;
+				fsl,ssi-dma-events = <29 28 27 26>; /* TX0 RX0 TX1 RX1 */
+				status = "disabled";
+			};
+
+			audmux: audmux@63fd0000 {
+				compatible = "fsl,imx53-audmux", "fsl,imx31-audmux";
+				reg = <0x63fd0000 0x4000>;
+				status = "disabled";
+			};
+
+			nfc: nand@63fdb000 {
+				compatible = "fsl,imx53-nand";
+				reg = <0x63fdb000 0x1000 0xf7ff0000 0x10000>;
+				interrupts = <8>;
+				clocks = <&clks 60>;
+				status = "disabled";
+			};
+
+			ssi3: ssi@63fe8000 {
+				compatible = "fsl,imx53-ssi", "fsl,imx21-ssi";
+				reg = <0x63fe8000 0x4000>;
+				interrupts = <96>;
+				clocks = <&clks 50>;
+				fsl,fifo-depth = <15>;
+				fsl,ssi-dma-events = <47 46 45 44>; /* TX0 RX0 TX1 RX1 */
+				status = "disabled";
+			};
+
+			fec: ethernet@63fec000 {
+				compatible = "fsl,imx53-fec", "fsl,imx25-fec";
+				reg = <0x63fec000 0x4000>;
+				interrupts = <87>;
+				clocks = <&clks 42>, <&clks 42>, <&clks 42>;
+				clock-names = "ipg", "ahb", "ptp";
+				status = "disabled";
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/imx6dl-pinfunc.h b/arch/arm/boot/dts/imx6dl-pinfunc.h
new file mode 100644
index 0000000..9aab950
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dl-pinfunc.h
@@ -0,0 +1,1085 @@
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef __DTS_IMX6DL_PINFUNC_H
+#define __DTS_IMX6DL_PINFUNC_H
+
+/*
+ * The pin function ID is a tuple of
+ * <mux_reg conf_reg input_reg mux_mode input_val>
+ */
+#define MX6DL_PAD_CSI0_DAT10__IPU1_CSI0_DATA10     0x04c 0x360 0x000 0x0 0x0
+#define MX6DL_PAD_CSI0_DAT10__AUD3_RXC             0x04c 0x360 0x000 0x1 0x0
+#define MX6DL_PAD_CSI0_DAT10__ECSPI2_MISO          0x04c 0x360 0x7f8 0x2 0x0
+#define MX6DL_PAD_CSI0_DAT10__UART1_TX_DATA        0x04c 0x360 0x000 0x3 0x0
+#define MX6DL_PAD_CSI0_DAT10__UART1_RX_DATA        0x04c 0x360 0x8fc 0x3 0x0
+#define MX6DL_PAD_CSI0_DAT10__GPIO5_IO28           0x04c 0x360 0x000 0x5 0x0
+#define MX6DL_PAD_CSI0_DAT10__ARM_TRACE07          0x04c 0x360 0x000 0x7 0x0
+#define MX6DL_PAD_CSI0_DAT11__IPU1_CSI0_DATA11     0x050 0x364 0x000 0x0 0x0
+#define MX6DL_PAD_CSI0_DAT11__AUD3_RXFS            0x050 0x364 0x000 0x1 0x0
+#define MX6DL_PAD_CSI0_DAT11__ECSPI2_SS0           0x050 0x364 0x800 0x2 0x0
+#define MX6DL_PAD_CSI0_DAT11__UART1_RX_DATA        0x050 0x364 0x8fc 0x3 0x1
+#define MX6DL_PAD_CSI0_DAT11__UART1_TX_DATA        0x050 0x364 0x000 0x3 0x0
+#define MX6DL_PAD_CSI0_DAT11__GPIO5_IO29           0x050 0x364 0x000 0x5 0x0
+#define MX6DL_PAD_CSI0_DAT11__ARM_TRACE08          0x050 0x364 0x000 0x7 0x0
+#define MX6DL_PAD_CSI0_DAT12__IPU1_CSI0_DATA12     0x054 0x368 0x000 0x0 0x0
+#define MX6DL_PAD_CSI0_DAT12__EIM_DATA08           0x054 0x368 0x000 0x1 0x0
+#define MX6DL_PAD_CSI0_DAT12__UART4_TX_DATA        0x054 0x368 0x000 0x3 0x0
+#define MX6DL_PAD_CSI0_DAT12__UART4_RX_DATA        0x054 0x368 0x914 0x3 0x0
+#define MX6DL_PAD_CSI0_DAT12__GPIO5_IO30           0x054 0x368 0x000 0x5 0x0
+#define MX6DL_PAD_CSI0_DAT12__ARM_TRACE09          0x054 0x368 0x000 0x7 0x0
+#define MX6DL_PAD_CSI0_DAT13__IPU1_CSI0_DATA13     0x058 0x36c 0x000 0x0 0x0
+#define MX6DL_PAD_CSI0_DAT13__EIM_DATA09           0x058 0x36c 0x000 0x1 0x0
+#define MX6DL_PAD_CSI0_DAT13__UART4_RX_DATA        0x058 0x36c 0x914 0x3 0x1
+#define MX6DL_PAD_CSI0_DAT13__UART4_TX_DATA        0x058 0x36c 0x000 0x3 0x0
+#define MX6DL_PAD_CSI0_DAT13__GPIO5_IO31           0x058 0x36c 0x000 0x5 0x0
+#define MX6DL_PAD_CSI0_DAT13__ARM_TRACE10          0x058 0x36c 0x000 0x7 0x0
+#define MX6DL_PAD_CSI0_DAT14__IPU1_CSI0_DATA14     0x05c 0x370 0x000 0x0 0x0
+#define MX6DL_PAD_CSI0_DAT14__EIM_DATA10           0x05c 0x370 0x000 0x1 0x0
+#define MX6DL_PAD_CSI0_DAT14__UART5_TX_DATA        0x05c 0x370 0x000 0x3 0x0
+#define MX6DL_PAD_CSI0_DAT14__UART5_RX_DATA        0x05c 0x370 0x91c 0x3 0x0
+#define MX6DL_PAD_CSI0_DAT14__GPIO6_IO00           0x05c 0x370 0x000 0x5 0x0
+#define MX6DL_PAD_CSI0_DAT14__ARM_TRACE11          0x05c 0x370 0x000 0x7 0x0
+#define MX6DL_PAD_CSI0_DAT15__IPU1_CSI0_DATA15     0x060 0x374 0x000 0x0 0x0
+#define MX6DL_PAD_CSI0_DAT15__EIM_DATA11           0x060 0x374 0x000 0x1 0x0
+#define MX6DL_PAD_CSI0_DAT15__UART5_RX_DATA        0x060 0x374 0x91c 0x3 0x1
+#define MX6DL_PAD_CSI0_DAT15__UART5_TX_DATA        0x060 0x374 0x000 0x3 0x0
+#define MX6DL_PAD_CSI0_DAT15__GPIO6_IO01           0x060 0x374 0x000 0x5 0x0
+#define MX6DL_PAD_CSI0_DAT15__ARM_TRACE12          0x060 0x374 0x000 0x7 0x0
+#define MX6DL_PAD_CSI0_DAT16__IPU1_CSI0_DATA16     0x064 0x378 0x000 0x0 0x0
+#define MX6DL_PAD_CSI0_DAT16__EIM_DATA12           0x064 0x378 0x000 0x1 0x0
+#define MX6DL_PAD_CSI0_DAT16__UART4_RTS_B          0x064 0x378 0x910 0x3 0x0
+#define MX6DL_PAD_CSI0_DAT16__UART4_CTS_B          0x064 0x378 0x000 0x3 0x0
+#define MX6DL_PAD_CSI0_DAT16__GPIO6_IO02           0x064 0x378 0x000 0x5 0x0
+#define MX6DL_PAD_CSI0_DAT16__ARM_TRACE13          0x064 0x378 0x000 0x7 0x0
+#define MX6DL_PAD_CSI0_DAT17__IPU1_CSI0_DATA17     0x068 0x37c 0x000 0x0 0x0
+#define MX6DL_PAD_CSI0_DAT17__EIM_DATA13           0x068 0x37c 0x000 0x1 0x0
+#define MX6DL_PAD_CSI0_DAT17__UART4_CTS_B          0x068 0x37c 0x000 0x3 0x0
+#define MX6DL_PAD_CSI0_DAT17__UART4_RTS_B          0x068 0x37c 0x910 0x3 0x1
+#define MX6DL_PAD_CSI0_DAT17__GPIO6_IO03           0x068 0x37c 0x000 0x5 0x0
+#define MX6DL_PAD_CSI0_DAT17__ARM_TRACE14          0x068 0x37c 0x000 0x7 0x0
+#define MX6DL_PAD_CSI0_DAT18__IPU1_CSI0_DATA18     0x06c 0x380 0x000 0x0 0x0
+#define MX6DL_PAD_CSI0_DAT18__EIM_DATA14           0x06c 0x380 0x000 0x1 0x0
+#define MX6DL_PAD_CSI0_DAT18__UART5_RTS_B          0x06c 0x380 0x918 0x3 0x0
+#define MX6DL_PAD_CSI0_DAT18__UART5_CTS_B          0x06c 0x380 0x000 0x3 0x0
+#define MX6DL_PAD_CSI0_DAT18__GPIO6_IO04           0x06c 0x380 0x000 0x5 0x0
+#define MX6DL_PAD_CSI0_DAT18__ARM_TRACE15          0x06c 0x380 0x000 0x7 0x0
+#define MX6DL_PAD_CSI0_DAT19__IPU1_CSI0_DATA19     0x070 0x384 0x000 0x0 0x0
+#define MX6DL_PAD_CSI0_DAT19__EIM_DATA15           0x070 0x384 0x000 0x1 0x0
+#define MX6DL_PAD_CSI0_DAT19__UART5_CTS_B          0x070 0x384 0x000 0x3 0x0
+#define MX6DL_PAD_CSI0_DAT19__UART5_RTS_B          0x070 0x384 0x918 0x3 0x1
+#define MX6DL_PAD_CSI0_DAT19__GPIO6_IO05           0x070 0x384 0x000 0x5 0x0
+#define MX6DL_PAD_CSI0_DAT4__IPU1_CSI0_DATA04      0x074 0x388 0x000 0x0 0x0
+#define MX6DL_PAD_CSI0_DAT4__EIM_DATA02            0x074 0x388 0x000 0x1 0x0
+#define MX6DL_PAD_CSI0_DAT4__ECSPI1_SCLK           0x074 0x388 0x7d8 0x2 0x0
+#define MX6DL_PAD_CSI0_DAT4__KEY_COL5              0x074 0x388 0x8c0 0x3 0x0
+#define MX6DL_PAD_CSI0_DAT4__AUD3_TXC              0x074 0x388 0x000 0x4 0x0
+#define MX6DL_PAD_CSI0_DAT4__GPIO5_IO22            0x074 0x388 0x000 0x5 0x0
+#define MX6DL_PAD_CSI0_DAT4__ARM_TRACE01           0x074 0x388 0x000 0x7 0x0
+#define MX6DL_PAD_CSI0_DAT5__IPU1_CSI0_DATA05      0x078 0x38c 0x000 0x0 0x0
+#define MX6DL_PAD_CSI0_DAT5__EIM_DATA03            0x078 0x38c 0x000 0x1 0x0
+#define MX6DL_PAD_CSI0_DAT5__ECSPI1_MOSI           0x078 0x38c 0x7e0 0x2 0x0
+#define MX6DL_PAD_CSI0_DAT5__KEY_ROW5              0x078 0x38c 0x8cc 0x3 0x0
+#define MX6DL_PAD_CSI0_DAT5__AUD3_TXD              0x078 0x38c 0x000 0x4 0x0
+#define MX6DL_PAD_CSI0_DAT5__GPIO5_IO23            0x078 0x38c 0x000 0x5 0x0
+#define MX6DL_PAD_CSI0_DAT5__ARM_TRACE02           0x078 0x38c 0x000 0x7 0x0
+#define MX6DL_PAD_CSI0_DAT6__IPU1_CSI0_DATA06      0x07c 0x390 0x000 0x0 0x0
+#define MX6DL_PAD_CSI0_DAT6__EIM_DATA04            0x07c 0x390 0x000 0x1 0x0
+#define MX6DL_PAD_CSI0_DAT6__ECSPI1_MISO           0x07c 0x390 0x7dc 0x2 0x0
+#define MX6DL_PAD_CSI0_DAT6__KEY_COL6              0x07c 0x390 0x8c4 0x3 0x0
+#define MX6DL_PAD_CSI0_DAT6__AUD3_TXFS             0x07c 0x390 0x000 0x4 0x0
+#define MX6DL_PAD_CSI0_DAT6__GPIO5_IO24            0x07c 0x390 0x000 0x5 0x0
+#define MX6DL_PAD_CSI0_DAT6__ARM_TRACE03           0x07c 0x390 0x000 0x7 0x0
+#define MX6DL_PAD_CSI0_DAT7__IPU1_CSI0_DATA07      0x080 0x394 0x000 0x0 0x0
+#define MX6DL_PAD_CSI0_DAT7__EIM_DATA05            0x080 0x394 0x000 0x1 0x0
+#define MX6DL_PAD_CSI0_DAT7__ECSPI1_SS0            0x080 0x394 0x7e4 0x2 0x0
+#define MX6DL_PAD_CSI0_DAT7__KEY_ROW6              0x080 0x394 0x8d0 0x3 0x0
+#define MX6DL_PAD_CSI0_DAT7__AUD3_RXD              0x080 0x394 0x000 0x4 0x0
+#define MX6DL_PAD_CSI0_DAT7__GPIO5_IO25            0x080 0x394 0x000 0x5 0x0
+#define MX6DL_PAD_CSI0_DAT7__ARM_TRACE04           0x080 0x394 0x000 0x7 0x0
+#define MX6DL_PAD_CSI0_DAT8__IPU1_CSI0_DATA08      0x084 0x398 0x000 0x0 0x0
+#define MX6DL_PAD_CSI0_DAT8__EIM_DATA06            0x084 0x398 0x000 0x1 0x0
+#define MX6DL_PAD_CSI0_DAT8__ECSPI2_SCLK           0x084 0x398 0x7f4 0x2 0x0
+#define MX6DL_PAD_CSI0_DAT8__KEY_COL7              0x084 0x398 0x8c8 0x3 0x0
+#define MX6DL_PAD_CSI0_DAT8__I2C1_SDA              0x084 0x398 0x86c 0x4 0x0
+#define MX6DL_PAD_CSI0_DAT8__GPIO5_IO26            0x084 0x398 0x000 0x5 0x0
+#define MX6DL_PAD_CSI0_DAT8__ARM_TRACE05           0x084 0x398 0x000 0x7 0x0
+#define MX6DL_PAD_CSI0_DAT9__IPU1_CSI0_DATA09      0x088 0x39c 0x000 0x0 0x0
+#define MX6DL_PAD_CSI0_DAT9__EIM_DATA07            0x088 0x39c 0x000 0x1 0x0
+#define MX6DL_PAD_CSI0_DAT9__ECSPI2_MOSI           0x088 0x39c 0x7fc 0x2 0x0
+#define MX6DL_PAD_CSI0_DAT9__KEY_ROW7              0x088 0x39c 0x8d4 0x3 0x0
+#define MX6DL_PAD_CSI0_DAT9__I2C1_SCL              0x088 0x39c 0x868 0x4 0x0
+#define MX6DL_PAD_CSI0_DAT9__GPIO5_IO27            0x088 0x39c 0x000 0x5 0x0
+#define MX6DL_PAD_CSI0_DAT9__ARM_TRACE06           0x088 0x39c 0x000 0x7 0x0
+#define MX6DL_PAD_CSI0_DATA_EN__IPU1_CSI0_DATA_EN  0x08c 0x3a0 0x000 0x0 0x0
+#define MX6DL_PAD_CSI0_DATA_EN__EIM_DATA00         0x08c 0x3a0 0x000 0x1 0x0
+#define MX6DL_PAD_CSI0_DATA_EN__GPIO5_IO20         0x08c 0x3a0 0x000 0x5 0x0
+#define MX6DL_PAD_CSI0_DATA_EN__ARM_TRACE_CLK      0x08c 0x3a0 0x000 0x7 0x0
+#define MX6DL_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC       0x090 0x3a4 0x000 0x0 0x0
+#define MX6DL_PAD_CSI0_MCLK__CCM_CLKO1             0x090 0x3a4 0x000 0x3 0x0
+#define MX6DL_PAD_CSI0_MCLK__GPIO5_IO19            0x090 0x3a4 0x000 0x5 0x0
+#define MX6DL_PAD_CSI0_MCLK__ARM_TRACE_CTL         0x090 0x3a4 0x000 0x7 0x0
+#define MX6DL_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK    0x094 0x3a8 0x000 0x0 0x0
+#define MX6DL_PAD_CSI0_PIXCLK__GPIO5_IO18          0x094 0x3a8 0x000 0x5 0x0
+#define MX6DL_PAD_CSI0_PIXCLK__ARM_EVENTO          0x094 0x3a8 0x000 0x7 0x0
+#define MX6DL_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC      0x098 0x3ac 0x000 0x0 0x0
+#define MX6DL_PAD_CSI0_VSYNC__EIM_DATA01           0x098 0x3ac 0x000 0x1 0x0
+#define MX6DL_PAD_CSI0_VSYNC__GPIO5_IO21           0x098 0x3ac 0x000 0x5 0x0
+#define MX6DL_PAD_CSI0_VSYNC__ARM_TRACE00          0x098 0x3ac 0x000 0x7 0x0
+#define MX6DL_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK  0x09c 0x3b0 0x000 0x0 0x0
+#define MX6DL_PAD_DI0_DISP_CLK__LCD_CLK            0x09c 0x3b0 0x000 0x1 0x0
+#define MX6DL_PAD_DI0_DISP_CLK__GPIO4_IO16         0x09c 0x3b0 0x000 0x5 0x0
+#define MX6DL_PAD_DI0_DISP_CLK__LCD_WR_RWN         0x09c 0x3b0 0x000 0x8 0x0
+#define MX6DL_PAD_DI0_PIN15__IPU1_DI0_PIN15        0x0a0 0x3b4 0x000 0x0 0x0
+#define MX6DL_PAD_DI0_PIN15__LCD_ENABLE            0x0a0 0x3b4 0x000 0x1 0x0
+#define MX6DL_PAD_DI0_PIN15__AUD6_TXC              0x0a0 0x3b4 0x000 0x2 0x0
+#define MX6DL_PAD_DI0_PIN15__GPIO4_IO17            0x0a0 0x3b4 0x000 0x5 0x0
+#define MX6DL_PAD_DI0_PIN15__LCD_RD_E              0x0a0 0x3b4 0x000 0x8 0x0
+#define MX6DL_PAD_DI0_PIN2__IPU1_DI0_PIN02         0x0a4 0x3b8 0x000 0x0 0x0
+#define MX6DL_PAD_DI0_PIN2__LCD_HSYNC              0x0a4 0x3b8 0x8d8 0x1 0x0
+#define MX6DL_PAD_DI0_PIN2__AUD6_TXD               0x0a4 0x3b8 0x000 0x2 0x0
+#define MX6DL_PAD_DI0_PIN2__GPIO4_IO18             0x0a4 0x3b8 0x000 0x5 0x0
+#define MX6DL_PAD_DI0_PIN2__LCD_RS                 0x0a4 0x3b8 0x000 0x8 0x0
+#define MX6DL_PAD_DI0_PIN3__IPU1_DI0_PIN03         0x0a8 0x3bc 0x000 0x0 0x0
+#define MX6DL_PAD_DI0_PIN3__LCD_VSYNC              0x0a8 0x3bc 0x000 0x1 0x0
+#define MX6DL_PAD_DI0_PIN3__AUD6_TXFS              0x0a8 0x3bc 0x000 0x2 0x0
+#define MX6DL_PAD_DI0_PIN3__GPIO4_IO19             0x0a8 0x3bc 0x000 0x5 0x0
+#define MX6DL_PAD_DI0_PIN3__LCD_CS                 0x0a8 0x3bc 0x000 0x8 0x0
+#define MX6DL_PAD_DI0_PIN4__IPU1_DI0_PIN04         0x0ac 0x3c0 0x000 0x0 0x0
+#define MX6DL_PAD_DI0_PIN4__LCD_BUSY               0x0ac 0x3c0 0x8d8 0x1 0x1
+#define MX6DL_PAD_DI0_PIN4__AUD6_RXD               0x0ac 0x3c0 0x000 0x2 0x0
+#define MX6DL_PAD_DI0_PIN4__SD1_WP                 0x0ac 0x3c0 0x92c 0x3 0x0
+#define MX6DL_PAD_DI0_PIN4__GPIO4_IO20             0x0ac 0x3c0 0x000 0x5 0x0
+#define MX6DL_PAD_DI0_PIN4__LCD_RESET              0x0ac 0x3c0 0x000 0x8 0x0
+#define MX6DL_PAD_DISP0_DAT0__IPU1_DISP0_DATA00    0x0b0 0x3c4 0x000 0x0 0x0
+#define MX6DL_PAD_DISP0_DAT0__LCD_DATA00           0x0b0 0x3c4 0x000 0x1 0x0
+#define MX6DL_PAD_DISP0_DAT0__ECSPI3_SCLK          0x0b0 0x3c4 0x000 0x2 0x0
+#define MX6DL_PAD_DISP0_DAT0__GPIO4_IO21           0x0b0 0x3c4 0x000 0x5 0x0
+#define MX6DL_PAD_DISP0_DAT1__IPU1_DISP0_DATA01    0x0b4 0x3c8 0x000 0x0 0x0
+#define MX6DL_PAD_DISP0_DAT1__LCD_DATA01           0x0b4 0x3c8 0x000 0x1 0x0
+#define MX6DL_PAD_DISP0_DAT1__ECSPI3_MOSI          0x0b4 0x3c8 0x000 0x2 0x0
+#define MX6DL_PAD_DISP0_DAT1__GPIO4_IO22           0x0b4 0x3c8 0x000 0x5 0x0
+#define MX6DL_PAD_DISP0_DAT10__IPU1_DISP0_DATA10   0x0b8 0x3cc 0x000 0x0 0x0
+#define MX6DL_PAD_DISP0_DAT10__LCD_DATA10          0x0b8 0x3cc 0x000 0x1 0x0
+#define MX6DL_PAD_DISP0_DAT10__GPIO4_IO31          0x0b8 0x3cc 0x000 0x5 0x0
+#define MX6DL_PAD_DISP0_DAT11__IPU1_DISP0_DATA11   0x0bc 0x3d0 0x000 0x0 0x0
+#define MX6DL_PAD_DISP0_DAT11__LCD_DATA11          0x0bc 0x3d0 0x000 0x1 0x0
+#define MX6DL_PAD_DISP0_DAT11__GPIO5_IO05          0x0bc 0x3d0 0x000 0x5 0x0
+#define MX6DL_PAD_DISP0_DAT12__IPU1_DISP0_DATA12   0x0c0 0x3d4 0x000 0x0 0x0
+#define MX6DL_PAD_DISP0_DAT12__LCD_DATA12          0x0c0 0x3d4 0x000 0x1 0x0
+#define MX6DL_PAD_DISP0_DAT12__GPIO5_IO06          0x0c0 0x3d4 0x000 0x5 0x0
+#define MX6DL_PAD_DISP0_DAT13__IPU1_DISP0_DATA13   0x0c4 0x3d8 0x000 0x0 0x0
+#define MX6DL_PAD_DISP0_DAT13__LCD_DATA13          0x0c4 0x3d8 0x000 0x1 0x0
+#define MX6DL_PAD_DISP0_DAT13__AUD5_RXFS           0x0c4 0x3d8 0x7bc 0x3 0x0
+#define MX6DL_PAD_DISP0_DAT13__GPIO5_IO07          0x0c4 0x3d8 0x000 0x5 0x0
+#define MX6DL_PAD_DISP0_DAT14__IPU1_DISP0_DATA14   0x0c8 0x3dc 0x000 0x0 0x0
+#define MX6DL_PAD_DISP0_DAT14__LCD_DATA14          0x0c8 0x3dc 0x000 0x1 0x0
+#define MX6DL_PAD_DISP0_DAT14__AUD5_RXC            0x0c8 0x3dc 0x7b8 0x3 0x0
+#define MX6DL_PAD_DISP0_DAT14__GPIO5_IO08          0x0c8 0x3dc 0x000 0x5 0x0
+#define MX6DL_PAD_DISP0_DAT15__IPU1_DISP0_DATA15   0x0cc 0x3e0 0x000 0x0 0x0
+#define MX6DL_PAD_DISP0_DAT15__LCD_DATA15          0x0cc 0x3e0 0x000 0x1 0x0
+#define MX6DL_PAD_DISP0_DAT15__ECSPI1_SS1          0x0cc 0x3e0 0x7e8 0x2 0x0
+#define MX6DL_PAD_DISP0_DAT15__ECSPI2_SS1          0x0cc 0x3e0 0x804 0x3 0x0
+#define MX6DL_PAD_DISP0_DAT15__GPIO5_IO09          0x0cc 0x3e0 0x000 0x5 0x0
+#define MX6DL_PAD_DISP0_DAT16__IPU1_DISP0_DATA16   0x0d0 0x3e4 0x000 0x0 0x0
+#define MX6DL_PAD_DISP0_DAT16__LCD_DATA16          0x0d0 0x3e4 0x000 0x1 0x0
+#define MX6DL_PAD_DISP0_DAT16__ECSPI2_MOSI         0x0d0 0x3e4 0x7fc 0x2 0x1
+#define MX6DL_PAD_DISP0_DAT16__AUD5_TXC            0x0d0 0x3e4 0x7c0 0x3 0x0
+#define MX6DL_PAD_DISP0_DAT16__SDMA_EXT_EVENT0     0x0d0 0x3e4 0x8e8 0x4 0x0
+#define MX6DL_PAD_DISP0_DAT16__GPIO5_IO10          0x0d0 0x3e4 0x000 0x5 0x0
+#define MX6DL_PAD_DISP0_DAT17__IPU1_DISP0_DATA17   0x0d4 0x3e8 0x000 0x0 0x0
+#define MX6DL_PAD_DISP0_DAT17__LCD_DATA17          0x0d4 0x3e8 0x000 0x1 0x0
+#define MX6DL_PAD_DISP0_DAT17__ECSPI2_MISO         0x0d4 0x3e8 0x7f8 0x2 0x1
+#define MX6DL_PAD_DISP0_DAT17__AUD5_TXD            0x0d4 0x3e8 0x7b4 0x3 0x0
+#define MX6DL_PAD_DISP0_DAT17__SDMA_EXT_EVENT1     0x0d4 0x3e8 0x8ec 0x4 0x0
+#define MX6DL_PAD_DISP0_DAT17__GPIO5_IO11          0x0d4 0x3e8 0x000 0x5 0x0
+#define MX6DL_PAD_DISP0_DAT18__IPU1_DISP0_DATA18   0x0d8 0x3ec 0x000 0x0 0x0
+#define MX6DL_PAD_DISP0_DAT18__LCD_DATA18          0x0d8 0x3ec 0x000 0x1 0x0
+#define MX6DL_PAD_DISP0_DAT18__ECSPI2_SS0          0x0d8 0x3ec 0x800 0x2 0x1
+#define MX6DL_PAD_DISP0_DAT18__AUD5_TXFS           0x0d8 0x3ec 0x7c4 0x3 0x0
+#define MX6DL_PAD_DISP0_DAT18__AUD4_RXFS           0x0d8 0x3ec 0x7a4 0x4 0x0
+#define MX6DL_PAD_DISP0_DAT18__GPIO5_IO12          0x0d8 0x3ec 0x000 0x5 0x0
+#define MX6DL_PAD_DISP0_DAT18__EIM_CS2_B           0x0d8 0x3ec 0x000 0x7 0x0
+#define MX6DL_PAD_DISP0_DAT19__IPU1_DISP0_DATA19   0x0dc 0x3f0 0x000 0x0 0x0
+#define MX6DL_PAD_DISP0_DAT19__LCD_DATA19          0x0dc 0x3f0 0x000 0x1 0x0
+#define MX6DL_PAD_DISP0_DAT19__ECSPI2_SCLK         0x0dc 0x3f0 0x7f4 0x2 0x1
+#define MX6DL_PAD_DISP0_DAT19__AUD5_RXD            0x0dc 0x3f0 0x7b0 0x3 0x0
+#define MX6DL_PAD_DISP0_DAT19__AUD4_RXC            0x0dc 0x3f0 0x7a0 0x4 0x0
+#define MX6DL_PAD_DISP0_DAT19__GPIO5_IO13          0x0dc 0x3f0 0x000 0x5 0x0
+#define MX6DL_PAD_DISP0_DAT19__EIM_CS3_B           0x0dc 0x3f0 0x000 0x7 0x0
+#define MX6DL_PAD_DISP0_DAT2__IPU1_DISP0_DATA02    0x0e0 0x3f4 0x000 0x0 0x0
+#define MX6DL_PAD_DISP0_DAT2__LCD_DATA02           0x0e0 0x3f4 0x000 0x1 0x0
+#define MX6DL_PAD_DISP0_DAT2__ECSPI3_MISO          0x0e0 0x3f4 0x000 0x2 0x0
+#define MX6DL_PAD_DISP0_DAT2__GPIO4_IO23           0x0e0 0x3f4 0x000 0x5 0x0
+#define MX6DL_PAD_DISP0_DAT20__IPU1_DISP0_DATA20   0x0e4 0x3f8 0x000 0x0 0x0
+#define MX6DL_PAD_DISP0_DAT20__LCD_DATA20          0x0e4 0x3f8 0x000 0x1 0x0
+#define MX6DL_PAD_DISP0_DAT20__ECSPI1_SCLK         0x0e4 0x3f8 0x7d8 0x2 0x1
+#define MX6DL_PAD_DISP0_DAT20__AUD4_TXC            0x0e4 0x3f8 0x7a8 0x3 0x0
+#define MX6DL_PAD_DISP0_DAT20__GPIO5_IO14          0x0e4 0x3f8 0x000 0x5 0x0
+#define MX6DL_PAD_DISP0_DAT21__IPU1_DISP0_DATA21   0x0e8 0x3fc 0x000 0x0 0x0
+#define MX6DL_PAD_DISP0_DAT21__LCD_DATA21          0x0e8 0x3fc 0x000 0x1 0x0
+#define MX6DL_PAD_DISP0_DAT21__ECSPI1_MOSI         0x0e8 0x3fc 0x7e0 0x2 0x1
+#define MX6DL_PAD_DISP0_DAT21__AUD4_TXD            0x0e8 0x3fc 0x79c 0x3 0x0
+#define MX6DL_PAD_DISP0_DAT21__GPIO5_IO15          0x0e8 0x3fc 0x000 0x5 0x0
+#define MX6DL_PAD_DISP0_DAT22__IPU1_DISP0_DATA22   0x0ec 0x400 0x000 0x0 0x0
+#define MX6DL_PAD_DISP0_DAT22__LCD_DATA22          0x0ec 0x400 0x000 0x1 0x0
+#define MX6DL_PAD_DISP0_DAT22__ECSPI1_MISO         0x0ec 0x400 0x7dc 0x2 0x1
+#define MX6DL_PAD_DISP0_DAT22__AUD4_TXFS           0x0ec 0x400 0x7ac 0x3 0x0
+#define MX6DL_PAD_DISP0_DAT22__GPIO5_IO16          0x0ec 0x400 0x000 0x5 0x0
+#define MX6DL_PAD_DISP0_DAT23__IPU1_DISP0_DATA23   0x0f0 0x404 0x000 0x0 0x0
+#define MX6DL_PAD_DISP0_DAT23__LCD_DATA23          0x0f0 0x404 0x000 0x1 0x0
+#define MX6DL_PAD_DISP0_DAT23__ECSPI1_SS0          0x0f0 0x404 0x7e4 0x2 0x1
+#define MX6DL_PAD_DISP0_DAT23__AUD4_RXD            0x0f0 0x404 0x798 0x3 0x0
+#define MX6DL_PAD_DISP0_DAT23__GPIO5_IO17          0x0f0 0x404 0x000 0x5 0x0
+#define MX6DL_PAD_DISP0_DAT3__IPU1_DISP0_DATA03    0x0f4 0x408 0x000 0x0 0x0
+#define MX6DL_PAD_DISP0_DAT3__LCD_DATA03           0x0f4 0x408 0x000 0x1 0x0
+#define MX6DL_PAD_DISP0_DAT3__ECSPI3_SS0           0x0f4 0x408 0x000 0x2 0x0
+#define MX6DL_PAD_DISP0_DAT3__GPIO4_IO24           0x0f4 0x408 0x000 0x5 0x0
+#define MX6DL_PAD_DISP0_DAT4__IPU1_DISP0_DATA04    0x0f8 0x40c 0x000 0x0 0x0
+#define MX6DL_PAD_DISP0_DAT4__LCD_DATA04           0x0f8 0x40c 0x000 0x1 0x0
+#define MX6DL_PAD_DISP0_DAT4__ECSPI3_SS1           0x0f8 0x40c 0x000 0x2 0x0
+#define MX6DL_PAD_DISP0_DAT4__GPIO4_IO25           0x0f8 0x40c 0x000 0x5 0x0
+#define MX6DL_PAD_DISP0_DAT5__IPU1_DISP0_DATA05    0x0fc 0x410 0x000 0x0 0x0
+#define MX6DL_PAD_DISP0_DAT5__LCD_DATA05           0x0fc 0x410 0x000 0x1 0x0
+#define MX6DL_PAD_DISP0_DAT5__ECSPI3_SS2           0x0fc 0x410 0x000 0x2 0x0
+#define MX6DL_PAD_DISP0_DAT5__AUD6_RXFS            0x0fc 0x410 0x000 0x3 0x0
+#define MX6DL_PAD_DISP0_DAT5__GPIO4_IO26           0x0fc 0x410 0x000 0x5 0x0
+#define MX6DL_PAD_DISP0_DAT6__IPU1_DISP0_DATA06    0x100 0x414 0x000 0x0 0x0
+#define MX6DL_PAD_DISP0_DAT6__LCD_DATA06           0x100 0x414 0x000 0x1 0x0
+#define MX6DL_PAD_DISP0_DAT6__ECSPI3_SS3           0x100 0x414 0x000 0x2 0x0
+#define MX6DL_PAD_DISP0_DAT6__AUD6_RXC             0x100 0x414 0x000 0x3 0x0
+#define MX6DL_PAD_DISP0_DAT6__GPIO4_IO27           0x100 0x414 0x000 0x5 0x0
+#define MX6DL_PAD_DISP0_DAT7__IPU1_DISP0_DATA07    0x104 0x418 0x000 0x0 0x0
+#define MX6DL_PAD_DISP0_DAT7__LCD_DATA07           0x104 0x418 0x000 0x1 0x0
+#define MX6DL_PAD_DISP0_DAT7__ECSPI3_RDY           0x104 0x418 0x000 0x2 0x0
+#define MX6DL_PAD_DISP0_DAT7__GPIO4_IO28           0x104 0x418 0x000 0x5 0x0
+#define MX6DL_PAD_DISP0_DAT8__IPU1_DISP0_DATA08    0x108 0x41c 0x000 0x0 0x0
+#define MX6DL_PAD_DISP0_DAT8__LCD_DATA08           0x108 0x41c 0x000 0x1 0x0
+#define MX6DL_PAD_DISP0_DAT8__PWM1_OUT             0x108 0x41c 0x000 0x2 0x0
+#define MX6DL_PAD_DISP0_DAT8__WDOG1_B              0x108 0x41c 0x000 0x3 0x0
+#define MX6DL_PAD_DISP0_DAT8__GPIO4_IO29           0x108 0x41c 0x000 0x5 0x0
+#define MX6DL_PAD_DISP0_DAT9__IPU1_DISP0_DATA09    0x10c 0x420 0x000 0x0 0x0
+#define MX6DL_PAD_DISP0_DAT9__LCD_DATA09           0x10c 0x420 0x000 0x1 0x0
+#define MX6DL_PAD_DISP0_DAT9__PWM2_OUT             0x10c 0x420 0x000 0x2 0x0
+#define MX6DL_PAD_DISP0_DAT9__WDOG2_B              0x10c 0x420 0x000 0x3 0x0
+#define MX6DL_PAD_DISP0_DAT9__GPIO4_IO30           0x10c 0x420 0x000 0x5 0x0
+#define MX6DL_PAD_EIM_A16__EIM_ADDR16              0x110 0x4e0 0x000 0x0 0x0
+#define MX6DL_PAD_EIM_A16__IPU1_DI1_DISP_CLK       0x110 0x4e0 0x000 0x1 0x0
+#define MX6DL_PAD_EIM_A16__IPU1_CSI1_PIXCLK        0x110 0x4e0 0x8b8 0x2 0x0
+#define MX6DL_PAD_EIM_A16__GPIO2_IO22              0x110 0x4e0 0x000 0x5 0x0
+#define MX6DL_PAD_EIM_A16__SRC_BOOT_CFG16          0x110 0x4e0 0x000 0x7 0x0
+#define MX6DL_PAD_EIM_A16__EPDC_DATA00             0x110 0x4e0 0x000 0x8 0x0
+#define MX6DL_PAD_EIM_A17__EIM_ADDR17              0x114 0x4e4 0x000 0x0 0x0
+#define MX6DL_PAD_EIM_A17__IPU1_DISP1_DATA12       0x114 0x4e4 0x000 0x1 0x0
+#define MX6DL_PAD_EIM_A17__IPU1_CSI1_DATA12        0x114 0x4e4 0x890 0x2 0x0
+#define MX6DL_PAD_EIM_A17__GPIO2_IO21              0x114 0x4e4 0x000 0x5 0x0
+#define MX6DL_PAD_EIM_A17__SRC_BOOT_CFG17          0x114 0x4e4 0x000 0x7 0x0
+#define MX6DL_PAD_EIM_A17__EPDC_PWR_STAT           0x114 0x4e4 0x000 0x8 0x0
+#define MX6DL_PAD_EIM_A18__EIM_ADDR18              0x118 0x4e8 0x000 0x0 0x0
+#define MX6DL_PAD_EIM_A18__IPU1_DISP1_DATA13       0x118 0x4e8 0x000 0x1 0x0
+#define MX6DL_PAD_EIM_A18__IPU1_CSI1_DATA13        0x118 0x4e8 0x894 0x2 0x0
+#define MX6DL_PAD_EIM_A18__GPIO2_IO20              0x118 0x4e8 0x000 0x5 0x0
+#define MX6DL_PAD_EIM_A18__SRC_BOOT_CFG18          0x118 0x4e8 0x000 0x7 0x0
+#define MX6DL_PAD_EIM_A18__EPDC_PWR_CTRL0          0x118 0x4e8 0x000 0x8 0x0
+#define MX6DL_PAD_EIM_A19__EIM_ADDR19              0x11c 0x4ec 0x000 0x0 0x0
+#define MX6DL_PAD_EIM_A19__IPU1_DISP1_DATA14       0x11c 0x4ec 0x000 0x1 0x0
+#define MX6DL_PAD_EIM_A19__IPU1_CSI1_DATA14        0x11c 0x4ec 0x898 0x2 0x0
+#define MX6DL_PAD_EIM_A19__GPIO2_IO19              0x11c 0x4ec 0x000 0x5 0x0
+#define MX6DL_PAD_EIM_A19__SRC_BOOT_CFG19          0x11c 0x4ec 0x000 0x7 0x0
+#define MX6DL_PAD_EIM_A19__EPDC_PWR_CTRL1          0x11c 0x4ec 0x000 0x8 0x0
+#define MX6DL_PAD_EIM_A20__EIM_ADDR20              0x120 0x4f0 0x000 0x0 0x0
+#define MX6DL_PAD_EIM_A20__IPU1_DISP1_DATA15       0x120 0x4f0 0x000 0x1 0x0
+#define MX6DL_PAD_EIM_A20__IPU1_CSI1_DATA15        0x120 0x4f0 0x89c 0x2 0x0
+#define MX6DL_PAD_EIM_A20__GPIO2_IO18              0x120 0x4f0 0x000 0x5 0x0
+#define MX6DL_PAD_EIM_A20__SRC_BOOT_CFG20          0x120 0x4f0 0x000 0x7 0x0
+#define MX6DL_PAD_EIM_A20__EPDC_PWR_CTRL2          0x120 0x4f0 0x000 0x8 0x0
+#define MX6DL_PAD_EIM_A21__EIM_ADDR21              0x124 0x4f4 0x000 0x0 0x0
+#define MX6DL_PAD_EIM_A21__IPU1_DISP1_DATA16       0x124 0x4f4 0x000 0x1 0x0
+#define MX6DL_PAD_EIM_A21__IPU1_CSI1_DATA16        0x124 0x4f4 0x8a0 0x2 0x0
+#define MX6DL_PAD_EIM_A21__GPIO2_IO17              0x124 0x4f4 0x000 0x5 0x0
+#define MX6DL_PAD_EIM_A21__SRC_BOOT_CFG21          0x124 0x4f4 0x000 0x7 0x0
+#define MX6DL_PAD_EIM_A21__EPDC_GDCLK              0x124 0x4f4 0x000 0x8 0x0
+#define MX6DL_PAD_EIM_A22__EIM_ADDR22              0x128 0x4f8 0x000 0x0 0x0
+#define MX6DL_PAD_EIM_A22__IPU1_DISP1_DATA17       0x128 0x4f8 0x000 0x1 0x0
+#define MX6DL_PAD_EIM_A22__IPU1_CSI1_DATA17        0x128 0x4f8 0x8a4 0x2 0x0
+#define MX6DL_PAD_EIM_A22__GPIO2_IO16              0x128 0x4f8 0x000 0x5 0x0
+#define MX6DL_PAD_EIM_A22__SRC_BOOT_CFG22          0x128 0x4f8 0x000 0x7 0x0
+#define MX6DL_PAD_EIM_A22__EPDC_GDSP               0x128 0x4f8 0x000 0x8 0x0
+#define MX6DL_PAD_EIM_A23__EIM_ADDR23              0x12c 0x4fc 0x000 0x0 0x0
+#define MX6DL_PAD_EIM_A23__IPU1_DISP1_DATA18       0x12c 0x4fc 0x000 0x1 0x0
+#define MX6DL_PAD_EIM_A23__IPU1_CSI1_DATA18        0x12c 0x4fc 0x8a8 0x2 0x0
+#define MX6DL_PAD_EIM_A23__IPU1_SISG3              0x12c 0x4fc 0x000 0x4 0x0
+#define MX6DL_PAD_EIM_A23__GPIO6_IO06              0x12c 0x4fc 0x000 0x5 0x0
+#define MX6DL_PAD_EIM_A23__SRC_BOOT_CFG23          0x12c 0x4fc 0x000 0x7 0x0
+#define MX6DL_PAD_EIM_A23__EPDC_GDOE               0x12c 0x4fc 0x000 0x8 0x0
+#define MX6DL_PAD_EIM_A24__EIM_ADDR24              0x130 0x500 0x000 0x0 0x0
+#define MX6DL_PAD_EIM_A24__IPU1_DISP1_DATA19       0x130 0x500 0x000 0x1 0x0
+#define MX6DL_PAD_EIM_A24__IPU1_CSI1_DATA19        0x130 0x500 0x8ac 0x2 0x0
+#define MX6DL_PAD_EIM_A24__IPU1_SISG2              0x130 0x500 0x000 0x4 0x0
+#define MX6DL_PAD_EIM_A24__GPIO5_IO04              0x130 0x500 0x000 0x5 0x0
+#define MX6DL_PAD_EIM_A24__SRC_BOOT_CFG24          0x130 0x500 0x000 0x7 0x0
+#define MX6DL_PAD_EIM_A24__EPDC_GDRL               0x130 0x500 0x000 0x8 0x0
+#define MX6DL_PAD_EIM_A25__EIM_ADDR25              0x134 0x504 0x000 0x0 0x0
+#define MX6DL_PAD_EIM_A25__ECSPI4_SS1              0x134 0x504 0x000 0x1 0x0
+#define MX6DL_PAD_EIM_A25__ECSPI2_RDY              0x134 0x504 0x000 0x2 0x0
+#define MX6DL_PAD_EIM_A25__IPU1_DI1_PIN12          0x134 0x504 0x000 0x3 0x0
+#define MX6DL_PAD_EIM_A25__IPU1_DI0_D1_CS          0x134 0x504 0x000 0x4 0x0
+#define MX6DL_PAD_EIM_A25__GPIO5_IO02              0x134 0x504 0x000 0x5 0x0
+#define MX6DL_PAD_EIM_A25__HDMI_TX_CEC_LINE        0x134 0x504 0x85c 0x6 0x0
+#define MX6DL_PAD_EIM_A25__EPDC_DATA15             0x134 0x504 0x000 0x8 0x0
+#define MX6DL_PAD_EIM_A25__EIM_ACLK_FREERUN        0x134 0x504 0x000 0x9 0x0
+#define MX6DL_PAD_EIM_BCLK__EIM_BCLK               0x138 0x508 0x000 0x0 0x0
+#define MX6DL_PAD_EIM_BCLK__IPU1_DI1_PIN16         0x138 0x508 0x000 0x1 0x0
+#define MX6DL_PAD_EIM_BCLK__GPIO6_IO31             0x138 0x508 0x000 0x5 0x0
+#define MX6DL_PAD_EIM_BCLK__EPDC_SDCE9             0x138 0x508 0x000 0x8 0x0
+#define MX6DL_PAD_EIM_CS0__EIM_CS0_B               0x13c 0x50c 0x000 0x0 0x0
+#define MX6DL_PAD_EIM_CS0__IPU1_DI1_PIN05          0x13c 0x50c 0x000 0x1 0x0
+#define MX6DL_PAD_EIM_CS0__ECSPI2_SCLK             0x13c 0x50c 0x7f4 0x2 0x2
+#define MX6DL_PAD_EIM_CS0__GPIO2_IO23              0x13c 0x50c 0x000 0x5 0x0
+#define MX6DL_PAD_EIM_CS0__EPDC_DATA06             0x13c 0x50c 0x000 0x8 0x0
+#define MX6DL_PAD_EIM_CS1__EIM_CS1_B               0x140 0x510 0x000 0x0 0x0
+#define MX6DL_PAD_EIM_CS1__IPU1_DI1_PIN06          0x140 0x510 0x000 0x1 0x0
+#define MX6DL_PAD_EIM_CS1__ECSPI2_MOSI             0x140 0x510 0x7fc 0x2 0x2
+#define MX6DL_PAD_EIM_CS1__GPIO2_IO24              0x140 0x510 0x000 0x5 0x0
+#define MX6DL_PAD_EIM_CS1__EPDC_DATA08             0x140 0x510 0x000 0x8 0x0
+#define MX6DL_PAD_EIM_D16__EIM_DATA16              0x144 0x514 0x000 0x0 0x0
+#define MX6DL_PAD_EIM_D16__ECSPI1_SCLK             0x144 0x514 0x7d8 0x1 0x2
+#define MX6DL_PAD_EIM_D16__IPU1_DI0_PIN05          0x144 0x514 0x000 0x2 0x0
+#define MX6DL_PAD_EIM_D16__IPU1_CSI1_DATA18        0x144 0x514 0x8a8 0x3 0x1
+#define MX6DL_PAD_EIM_D16__HDMI_TX_DDC_SDA         0x144 0x514 0x864 0x4 0x0
+#define MX6DL_PAD_EIM_D16__GPIO3_IO16              0x144 0x514 0x000 0x5 0x0
+#define MX6DL_PAD_EIM_D16__I2C2_SDA                0x144 0x514 0x874 0x6 0x0
+#define MX6DL_PAD_EIM_D16__EPDC_DATA10             0x144 0x514 0x000 0x8 0x0
+#define MX6DL_PAD_EIM_D17__EIM_DATA17              0x148 0x518 0x000 0x0 0x0
+#define MX6DL_PAD_EIM_D17__ECSPI1_MISO             0x148 0x518 0x7dc 0x1 0x2
+#define MX6DL_PAD_EIM_D17__IPU1_DI0_PIN06          0x148 0x518 0x000 0x2 0x0
+#define MX6DL_PAD_EIM_D17__IPU1_CSI1_PIXCLK        0x148 0x518 0x8b8 0x3 0x1
+#define MX6DL_PAD_EIM_D17__DCIC1_OUT               0x148 0x518 0x000 0x4 0x0
+#define MX6DL_PAD_EIM_D17__GPIO3_IO17              0x148 0x518 0x000 0x5 0x0
+#define MX6DL_PAD_EIM_D17__I2C3_SCL                0x148 0x518 0x878 0x6 0x0
+#define MX6DL_PAD_EIM_D17__EPDC_VCOM0              0x148 0x518 0x000 0x8 0x0
+#define MX6DL_PAD_EIM_D18__EIM_DATA18              0x14c 0x51c 0x000 0x0 0x0
+#define MX6DL_PAD_EIM_D18__ECSPI1_MOSI             0x14c 0x51c 0x7e0 0x1 0x2
+#define MX6DL_PAD_EIM_D18__IPU1_DI0_PIN07          0x14c 0x51c 0x000 0x2 0x0
+#define MX6DL_PAD_EIM_D18__IPU1_CSI1_DATA17        0x14c 0x51c 0x8a4 0x3 0x1
+#define MX6DL_PAD_EIM_D18__IPU1_DI1_D0_CS          0x14c 0x51c 0x000 0x4 0x0
+#define MX6DL_PAD_EIM_D18__GPIO3_IO18              0x14c 0x51c 0x000 0x5 0x0
+#define MX6DL_PAD_EIM_D18__I2C3_SDA                0x14c 0x51c 0x87c 0x6 0x0
+#define MX6DL_PAD_EIM_D18__EPDC_VCOM1              0x14c 0x51c 0x000 0x8 0x0
+#define MX6DL_PAD_EIM_D19__EIM_DATA19              0x150 0x520 0x000 0x0 0x0
+#define MX6DL_PAD_EIM_D19__ECSPI1_SS1              0x150 0x520 0x7e8 0x1 0x1
+#define MX6DL_PAD_EIM_D19__IPU1_DI0_PIN08          0x150 0x520 0x000 0x2 0x0
+#define MX6DL_PAD_EIM_D19__IPU1_CSI1_DATA16        0x150 0x520 0x8a0 0x3 0x1
+#define MX6DL_PAD_EIM_D19__UART1_CTS_B             0x150 0x520 0x000 0x4 0x0
+#define MX6DL_PAD_EIM_D19__UART1_RTS_B             0x150 0x520 0x8f8 0x4 0x0
+#define MX6DL_PAD_EIM_D19__GPIO3_IO19              0x150 0x520 0x000 0x5 0x0
+#define MX6DL_PAD_EIM_D19__EPIT1_OUT               0x150 0x520 0x000 0x6 0x0
+#define MX6DL_PAD_EIM_D19__EPDC_DATA12             0x150 0x520 0x000 0x8 0x0
+#define MX6DL_PAD_EIM_D20__EIM_DATA20              0x154 0x524 0x000 0x0 0x0
+#define MX6DL_PAD_EIM_D20__ECSPI4_SS0              0x154 0x524 0x808 0x1 0x0
+#define MX6DL_PAD_EIM_D20__IPU1_DI0_PIN16          0x154 0x524 0x000 0x2 0x0
+#define MX6DL_PAD_EIM_D20__IPU1_CSI1_DATA15        0x154 0x524 0x89c 0x3 0x1
+#define MX6DL_PAD_EIM_D20__UART1_RTS_B             0x154 0x524 0x8f8 0x4 0x1
+#define MX6DL_PAD_EIM_D20__UART1_CTS_B             0x154 0x524 0x000 0x4 0x0
+#define MX6DL_PAD_EIM_D20__GPIO3_IO20              0x154 0x524 0x000 0x5 0x0
+#define MX6DL_PAD_EIM_D20__EPIT2_OUT               0x154 0x524 0x000 0x6 0x0
+#define MX6DL_PAD_EIM_D21__EIM_DATA21              0x158 0x528 0x000 0x0 0x0
+#define MX6DL_PAD_EIM_D21__ECSPI4_SCLK             0x158 0x528 0x000 0x1 0x0
+#define MX6DL_PAD_EIM_D21__IPU1_DI0_PIN17          0x158 0x528 0x000 0x2 0x0
+#define MX6DL_PAD_EIM_D21__IPU1_CSI1_DATA11        0x158 0x528 0x88c 0x3 0x0
+#define MX6DL_PAD_EIM_D21__USB_OTG_OC              0x158 0x528 0x920 0x4 0x0
+#define MX6DL_PAD_EIM_D21__GPIO3_IO21              0x158 0x528 0x000 0x5 0x0
+#define MX6DL_PAD_EIM_D21__I2C1_SCL                0x158 0x528 0x868 0x6 0x1
+#define MX6DL_PAD_EIM_D21__SPDIF_IN                0x158 0x528 0x8f0 0x7 0x0
+#define MX6DL_PAD_EIM_D22__EIM_DATA22              0x15c 0x52c 0x000 0x0 0x0
+#define MX6DL_PAD_EIM_D22__ECSPI4_MISO             0x15c 0x52c 0x000 0x1 0x0
+#define MX6DL_PAD_EIM_D22__IPU1_DI0_PIN01          0x15c 0x52c 0x000 0x2 0x0
+#define MX6DL_PAD_EIM_D22__IPU1_CSI1_DATA10        0x15c 0x52c 0x888 0x3 0x0
+#define MX6DL_PAD_EIM_D22__USB_OTG_PWR             0x15c 0x52c 0x000 0x4 0x0
+#define MX6DL_PAD_EIM_D22__GPIO3_IO22              0x15c 0x52c 0x000 0x5 0x0
+#define MX6DL_PAD_EIM_D22__SPDIF_OUT               0x15c 0x52c 0x000 0x6 0x0
+#define MX6DL_PAD_EIM_D22__EPDC_SDCE6              0x15c 0x52c 0x000 0x8 0x0
+#define MX6DL_PAD_EIM_D23__EIM_DATA23              0x160 0x530 0x000 0x0 0x0
+#define MX6DL_PAD_EIM_D23__IPU1_DI0_D0_CS          0x160 0x530 0x000 0x1 0x0
+#define MX6DL_PAD_EIM_D23__UART3_CTS_B             0x160 0x530 0x000 0x2 0x0
+#define MX6DL_PAD_EIM_D23__UART3_RTS_B             0x160 0x530 0x908 0x2 0x0
+#define MX6DL_PAD_EIM_D23__UART1_DCD_B             0x160 0x530 0x000 0x3 0x0
+#define MX6DL_PAD_EIM_D23__IPU1_CSI1_DATA_EN       0x160 0x530 0x8b0 0x4 0x0
+#define MX6DL_PAD_EIM_D23__GPIO3_IO23              0x160 0x530 0x000 0x5 0x0
+#define MX6DL_PAD_EIM_D23__IPU1_DI1_PIN02          0x160 0x530 0x000 0x6 0x0
+#define MX6DL_PAD_EIM_D23__IPU1_DI1_PIN14          0x160 0x530 0x000 0x7 0x0
+#define MX6DL_PAD_EIM_D23__EPDC_DATA11             0x160 0x530 0x000 0x8 0x0
+#define MX6DL_PAD_EIM_D24__EIM_DATA24              0x164 0x534 0x000 0x0 0x0
+#define MX6DL_PAD_EIM_D24__ECSPI4_SS2              0x164 0x534 0x000 0x1 0x0
+#define MX6DL_PAD_EIM_D24__UART3_TX_DATA           0x164 0x534 0x000 0x2 0x0
+#define MX6DL_PAD_EIM_D24__UART3_RX_DATA           0x164 0x534 0x90c 0x2 0x0
+#define MX6DL_PAD_EIM_D24__ECSPI1_SS2              0x164 0x534 0x7ec 0x3 0x0
+#define MX6DL_PAD_EIM_D24__ECSPI2_SS2              0x164 0x534 0x000 0x4 0x0
+#define MX6DL_PAD_EIM_D24__GPIO3_IO24              0x164 0x534 0x000 0x5 0x0
+#define MX6DL_PAD_EIM_D24__AUD5_RXFS               0x164 0x534 0x7bc 0x6 0x1
+#define MX6DL_PAD_EIM_D24__UART1_DTR_B             0x164 0x534 0x000 0x7 0x0
+#define MX6DL_PAD_EIM_D24__EPDC_SDCE7              0x164 0x534 0x000 0x8 0x0
+#define MX6DL_PAD_EIM_D25__EIM_DATA25              0x168 0x538 0x000 0x0 0x0
+#define MX6DL_PAD_EIM_D25__ECSPI4_SS3              0x168 0x538 0x000 0x1 0x0
+#define MX6DL_PAD_EIM_D25__UART3_RX_DATA           0x168 0x538 0x90c 0x2 0x1
+#define MX6DL_PAD_EIM_D25__UART3_TX_DATA           0x168 0x538 0x000 0x2 0x0
+#define MX6DL_PAD_EIM_D25__ECSPI1_SS3              0x168 0x538 0x7f0 0x3 0x0
+#define MX6DL_PAD_EIM_D25__ECSPI2_SS3              0x168 0x538 0x000 0x4 0x0
+#define MX6DL_PAD_EIM_D25__GPIO3_IO25              0x168 0x538 0x000 0x5 0x0
+#define MX6DL_PAD_EIM_D25__AUD5_RXC                0x168 0x538 0x7b8 0x6 0x1
+#define MX6DL_PAD_EIM_D25__UART1_DSR_B             0x168 0x538 0x000 0x7 0x0
+#define MX6DL_PAD_EIM_D25__EPDC_SDCE8              0x168 0x538 0x000 0x8 0x0
+#define MX6DL_PAD_EIM_D26__EIM_DATA26              0x16c 0x53c 0x000 0x0 0x0
+#define MX6DL_PAD_EIM_D26__IPU1_DI1_PIN11          0x16c 0x53c 0x000 0x1 0x0
+#define MX6DL_PAD_EIM_D26__IPU1_CSI0_DATA01        0x16c 0x53c 0x000 0x2 0x0
+#define MX6DL_PAD_EIM_D26__IPU1_CSI1_DATA14        0x16c 0x53c 0x898 0x3 0x1
+#define MX6DL_PAD_EIM_D26__UART2_TX_DATA           0x16c 0x53c 0x000 0x4 0x0
+#define MX6DL_PAD_EIM_D26__UART2_RX_DATA           0x16c 0x53c 0x904 0x4 0x0
+#define MX6DL_PAD_EIM_D26__GPIO3_IO26              0x16c 0x53c 0x000 0x5 0x0
+#define MX6DL_PAD_EIM_D26__IPU1_SISG2              0x16c 0x53c 0x000 0x6 0x0
+#define MX6DL_PAD_EIM_D26__IPU1_DISP1_DATA22       0x16c 0x53c 0x000 0x7 0x0
+#define MX6DL_PAD_EIM_D26__EPDC_SDOED              0x16c 0x53c 0x000 0x8 0x0
+#define MX6DL_PAD_EIM_D27__EIM_DATA27              0x170 0x540 0x000 0x0 0x0
+#define MX6DL_PAD_EIM_D27__IPU1_DI1_PIN13          0x170 0x540 0x000 0x1 0x0
+#define MX6DL_PAD_EIM_D27__IPU1_CSI0_DATA00        0x170 0x540 0x000 0x2 0x0
+#define MX6DL_PAD_EIM_D27__IPU1_CSI1_DATA13        0x170 0x540 0x894 0x3 0x1
+#define MX6DL_PAD_EIM_D27__UART2_RX_DATA           0x170 0x540 0x904 0x4 0x1
+#define MX6DL_PAD_EIM_D27__UART2_TX_DATA           0x170 0x540 0x000 0x4 0x0
+#define MX6DL_PAD_EIM_D27__GPIO3_IO27              0x170 0x540 0x000 0x5 0x0
+#define MX6DL_PAD_EIM_D27__IPU1_SISG3              0x170 0x540 0x000 0x6 0x0
+#define MX6DL_PAD_EIM_D27__IPU1_DISP1_DATA23       0x170 0x540 0x000 0x7 0x0
+#define MX6DL_PAD_EIM_D27__EPDC_SDOE               0x170 0x540 0x000 0x8 0x0
+#define MX6DL_PAD_EIM_D28__EIM_DATA28              0x174 0x544 0x000 0x0 0x0
+#define MX6DL_PAD_EIM_D28__I2C1_SDA                0x174 0x544 0x86c 0x1 0x1
+#define MX6DL_PAD_EIM_D28__ECSPI4_MOSI             0x174 0x544 0x000 0x2 0x0
+#define MX6DL_PAD_EIM_D28__IPU1_CSI1_DATA12        0x174 0x544 0x890 0x3 0x1
+#define MX6DL_PAD_EIM_D28__UART2_CTS_B             0x174 0x544 0x000 0x4 0x0
+#define MX6DL_PAD_EIM_D28__UART2_RTS_B             0x174 0x544 0x900 0x4 0x0
+#define MX6DL_PAD_EIM_D28__GPIO3_IO28              0x174 0x544 0x000 0x5 0x0
+#define MX6DL_PAD_EIM_D28__IPU1_EXT_TRIG           0x174 0x544 0x000 0x6 0x0
+#define MX6DL_PAD_EIM_D28__IPU1_DI0_PIN13          0x174 0x544 0x000 0x7 0x0
+#define MX6DL_PAD_EIM_D28__EPDC_PWR_CTRL3          0x174 0x544 0x000 0x8 0x0
+#define MX6DL_PAD_EIM_D29__EIM_DATA29              0x178 0x548 0x000 0x0 0x0
+#define MX6DL_PAD_EIM_D29__IPU1_DI1_PIN15          0x178 0x548 0x000 0x1 0x0
+#define MX6DL_PAD_EIM_D29__ECSPI4_SS0              0x178 0x548 0x808 0x2 0x1
+#define MX6DL_PAD_EIM_D29__UART2_RTS_B             0x178 0x548 0x900 0x4 0x1
+#define MX6DL_PAD_EIM_D29__UART2_CTS_B             0x178 0x548 0x000 0x4 0x0
+#define MX6DL_PAD_EIM_D29__GPIO3_IO29              0x178 0x548 0x000 0x5 0x0
+#define MX6DL_PAD_EIM_D29__IPU1_CSI1_VSYNC         0x178 0x548 0x8bc 0x6 0x0
+#define MX6DL_PAD_EIM_D29__IPU1_DI0_PIN14          0x178 0x548 0x000 0x7 0x0
+#define MX6DL_PAD_EIM_D29__EPDC_PWR_WAKE           0x178 0x548 0x000 0x8 0x0
+#define MX6DL_PAD_EIM_D30__EIM_DATA30              0x17c 0x54c 0x000 0x0 0x0
+#define MX6DL_PAD_EIM_D30__IPU1_DISP1_DATA21       0x17c 0x54c 0x000 0x1 0x0
+#define MX6DL_PAD_EIM_D30__IPU1_DI0_PIN11          0x17c 0x54c 0x000 0x2 0x0
+#define MX6DL_PAD_EIM_D30__IPU1_CSI0_DATA03        0x17c 0x54c 0x000 0x3 0x0
+#define MX6DL_PAD_EIM_D30__UART3_CTS_B             0x17c 0x54c 0x000 0x4 0x0
+#define MX6DL_PAD_EIM_D30__UART3_RTS_B             0x17c 0x54c 0x908 0x4 0x1
+#define MX6DL_PAD_EIM_D30__GPIO3_IO30              0x17c 0x54c 0x000 0x5 0x0
+#define MX6DL_PAD_EIM_D30__USB_H1_OC               0x17c 0x54c 0x924 0x6 0x0
+#define MX6DL_PAD_EIM_D30__EPDC_SDOEZ              0x17c 0x54c 0x000 0x8 0x0
+#define MX6DL_PAD_EIM_D31__EIM_DATA31              0x180 0x550 0x000 0x0 0x0
+#define MX6DL_PAD_EIM_D31__IPU1_DISP1_DATA20       0x180 0x550 0x000 0x1 0x0
+#define MX6DL_PAD_EIM_D31__IPU1_DI0_PIN12          0x180 0x550 0x000 0x2 0x0
+#define MX6DL_PAD_EIM_D31__IPU1_CSI0_DATA02        0x180 0x550 0x000 0x3 0x0
+#define MX6DL_PAD_EIM_D31__UART3_RTS_B             0x180 0x550 0x908 0x4 0x2
+#define MX6DL_PAD_EIM_D31__UART3_CTS_B             0x180 0x550 0x000 0x4 0x0
+#define MX6DL_PAD_EIM_D31__GPIO3_IO31              0x180 0x550 0x000 0x5 0x0
+#define MX6DL_PAD_EIM_D31__USB_H1_PWR              0x180 0x550 0x000 0x6 0x0
+#define MX6DL_PAD_EIM_D31__EPDC_SDCLK_P            0x180 0x550 0x000 0x8 0x0
+#define MX6DL_PAD_EIM_D31__EIM_ACLK_FREERUN        0x180 0x550 0x000 0x9 0x0
+#define MX6DL_PAD_EIM_DA0__EIM_AD00                0x184 0x554 0x000 0x0 0x0
+#define MX6DL_PAD_EIM_DA0__IPU1_DISP1_DATA09       0x184 0x554 0x000 0x1 0x0
+#define MX6DL_PAD_EIM_DA0__IPU1_CSI1_DATA09        0x184 0x554 0x000 0x2 0x0
+#define MX6DL_PAD_EIM_DA0__GPIO3_IO00              0x184 0x554 0x000 0x5 0x0
+#define MX6DL_PAD_EIM_DA0__SRC_BOOT_CFG00          0x184 0x554 0x000 0x7 0x0
+#define MX6DL_PAD_EIM_DA0__EPDC_SDCLK_N            0x184 0x554 0x000 0x8 0x0
+#define MX6DL_PAD_EIM_DA1__EIM_AD01                0x188 0x558 0x000 0x0 0x0
+#define MX6DL_PAD_EIM_DA1__IPU1_DISP1_DATA08       0x188 0x558 0x000 0x1 0x0
+#define MX6DL_PAD_EIM_DA1__IPU1_CSI1_DATA08        0x188 0x558 0x000 0x2 0x0
+#define MX6DL_PAD_EIM_DA1__GPIO3_IO01              0x188 0x558 0x000 0x5 0x0
+#define MX6DL_PAD_EIM_DA1__SRC_BOOT_CFG01          0x188 0x558 0x000 0x7 0x0
+#define MX6DL_PAD_EIM_DA1__EPDC_SDLE               0x188 0x558 0x000 0x8 0x0
+#define MX6DL_PAD_EIM_DA10__EIM_AD10               0x18c 0x55c 0x000 0x0 0x0
+#define MX6DL_PAD_EIM_DA10__IPU1_DI1_PIN15         0x18c 0x55c 0x000 0x1 0x0
+#define MX6DL_PAD_EIM_DA10__IPU1_CSI1_DATA_EN      0x18c 0x55c 0x8b0 0x2 0x1
+#define MX6DL_PAD_EIM_DA10__GPIO3_IO10             0x18c 0x55c 0x000 0x5 0x0
+#define MX6DL_PAD_EIM_DA10__SRC_BOOT_CFG10         0x18c 0x55c 0x000 0x7 0x0
+#define MX6DL_PAD_EIM_DA10__EPDC_DATA01            0x18c 0x55c 0x000 0x8 0x0
+#define MX6DL_PAD_EIM_DA11__EIM_AD11               0x190 0x560 0x000 0x0 0x0
+#define MX6DL_PAD_EIM_DA11__IPU1_DI1_PIN02         0x190 0x560 0x000 0x1 0x0
+#define MX6DL_PAD_EIM_DA11__IPU1_CSI1_HSYNC        0x190 0x560 0x8b4 0x2 0x0
+#define MX6DL_PAD_EIM_DA11__GPIO3_IO11             0x190 0x560 0x000 0x5 0x0
+#define MX6DL_PAD_EIM_DA11__SRC_BOOT_CFG11         0x190 0x560 0x000 0x7 0x0
+#define MX6DL_PAD_EIM_DA11__EPDC_DATA03            0x190 0x560 0x000 0x8 0x0
+#define MX6DL_PAD_EIM_DA12__EIM_AD12               0x194 0x564 0x000 0x0 0x0
+#define MX6DL_PAD_EIM_DA12__IPU1_DI1_PIN03         0x194 0x564 0x000 0x1 0x0
+#define MX6DL_PAD_EIM_DA12__IPU1_CSI1_VSYNC        0x194 0x564 0x8bc 0x2 0x1
+#define MX6DL_PAD_EIM_DA12__GPIO3_IO12             0x194 0x564 0x000 0x5 0x0
+#define MX6DL_PAD_EIM_DA12__SRC_BOOT_CFG12         0x194 0x564 0x000 0x7 0x0
+#define MX6DL_PAD_EIM_DA12__EPDC_DATA02            0x194 0x564 0x000 0x8 0x0
+#define MX6DL_PAD_EIM_DA13__EIM_AD13               0x198 0x568 0x000 0x0 0x0
+#define MX6DL_PAD_EIM_DA13__IPU1_DI1_D0_CS         0x198 0x568 0x000 0x1 0x0
+#define MX6DL_PAD_EIM_DA13__GPIO3_IO13             0x198 0x568 0x000 0x5 0x0
+#define MX6DL_PAD_EIM_DA13__SRC_BOOT_CFG13         0x198 0x568 0x000 0x7 0x0
+#define MX6DL_PAD_EIM_DA13__EPDC_DATA13            0x198 0x568 0x000 0x8 0x0
+#define MX6DL_PAD_EIM_DA14__EIM_AD14               0x19c 0x56c 0x000 0x0 0x0
+#define MX6DL_PAD_EIM_DA14__IPU1_DI1_D1_CS         0x19c 0x56c 0x000 0x1 0x0
+#define MX6DL_PAD_EIM_DA14__GPIO3_IO14             0x19c 0x56c 0x000 0x5 0x0
+#define MX6DL_PAD_EIM_DA14__SRC_BOOT_CFG14         0x19c 0x56c 0x000 0x7 0x0
+#define MX6DL_PAD_EIM_DA14__EPDC_DATA14            0x19c 0x56c 0x000 0x8 0x0
+#define MX6DL_PAD_EIM_DA15__EIM_AD15               0x1a0 0x570 0x000 0x0 0x0
+#define MX6DL_PAD_EIM_DA15__IPU1_DI1_PIN01         0x1a0 0x570 0x000 0x1 0x0
+#define MX6DL_PAD_EIM_DA15__IPU1_DI1_PIN04         0x1a0 0x570 0x000 0x2 0x0
+#define MX6DL_PAD_EIM_DA15__GPIO3_IO15             0x1a0 0x570 0x000 0x5 0x0
+#define MX6DL_PAD_EIM_DA15__SRC_BOOT_CFG15         0x1a0 0x570 0x000 0x7 0x0
+#define MX6DL_PAD_EIM_DA15__EPDC_DATA09            0x1a0 0x570 0x000 0x8 0x0
+#define MX6DL_PAD_EIM_DA2__EIM_AD02                0x1a4 0x574 0x000 0x0 0x0
+#define MX6DL_PAD_EIM_DA2__IPU1_DISP1_DATA07       0x1a4 0x574 0x000 0x1 0x0
+#define MX6DL_PAD_EIM_DA2__IPU1_CSI1_DATA07        0x1a4 0x574 0x000 0x2 0x0
+#define MX6DL_PAD_EIM_DA2__GPIO3_IO02              0x1a4 0x574 0x000 0x5 0x0
+#define MX6DL_PAD_EIM_DA2__SRC_BOOT_CFG02          0x1a4 0x574 0x000 0x7 0x0
+#define MX6DL_PAD_EIM_DA2__EPDC_BDR0               0x1a4 0x574 0x000 0x8 0x0
+#define MX6DL_PAD_EIM_DA3__EIM_AD03                0x1a8 0x578 0x000 0x0 0x0
+#define MX6DL_PAD_EIM_DA3__IPU1_DISP1_DATA06       0x1a8 0x578 0x000 0x1 0x0
+#define MX6DL_PAD_EIM_DA3__IPU1_CSI1_DATA06        0x1a8 0x578 0x000 0x2 0x0
+#define MX6DL_PAD_EIM_DA3__GPIO3_IO03              0x1a8 0x578 0x000 0x5 0x0
+#define MX6DL_PAD_EIM_DA3__SRC_BOOT_CFG03          0x1a8 0x578 0x000 0x7 0x0
+#define MX6DL_PAD_EIM_DA3__EPDC_BDR1               0x1a8 0x578 0x000 0x8 0x0
+#define MX6DL_PAD_EIM_DA4__EIM_AD04                0x1ac 0x57c 0x000 0x0 0x0
+#define MX6DL_PAD_EIM_DA4__IPU1_DISP1_DATA05       0x1ac 0x57c 0x000 0x1 0x0
+#define MX6DL_PAD_EIM_DA4__IPU1_CSI1_DATA05        0x1ac 0x57c 0x000 0x2 0x0
+#define MX6DL_PAD_EIM_DA4__GPIO3_IO04              0x1ac 0x57c 0x000 0x5 0x0
+#define MX6DL_PAD_EIM_DA4__SRC_BOOT_CFG04          0x1ac 0x57c 0x000 0x7 0x0
+#define MX6DL_PAD_EIM_DA4__EPDC_SDCE0              0x1ac 0x57c 0x000 0x8 0x0
+#define MX6DL_PAD_EIM_DA5__EIM_AD05                0x1b0 0x580 0x000 0x0 0x0
+#define MX6DL_PAD_EIM_DA5__IPU1_DISP1_DATA04       0x1b0 0x580 0x000 0x1 0x0
+#define MX6DL_PAD_EIM_DA5__IPU1_CSI1_DATA04        0x1b0 0x580 0x000 0x2 0x0
+#define MX6DL_PAD_EIM_DA5__GPIO3_IO05              0x1b0 0x580 0x000 0x5 0x0
+#define MX6DL_PAD_EIM_DA5__SRC_BOOT_CFG05          0x1b0 0x580 0x000 0x7 0x0
+#define MX6DL_PAD_EIM_DA5__EPDC_SDCE1              0x1b0 0x580 0x000 0x8 0x0
+#define MX6DL_PAD_EIM_DA6__EIM_AD06                0x1b4 0x584 0x000 0x0 0x0
+#define MX6DL_PAD_EIM_DA6__IPU1_DISP1_DATA03       0x1b4 0x584 0x000 0x1 0x0
+#define MX6DL_PAD_EIM_DA6__IPU1_CSI1_DATA03        0x1b4 0x584 0x000 0x2 0x0
+#define MX6DL_PAD_EIM_DA6__GPIO3_IO06              0x1b4 0x584 0x000 0x5 0x0
+#define MX6DL_PAD_EIM_DA6__SRC_BOOT_CFG06          0x1b4 0x584 0x000 0x7 0x0
+#define MX6DL_PAD_EIM_DA6__EPDC_SDCE2              0x1b4 0x584 0x000 0x8 0x0
+#define MX6DL_PAD_EIM_DA7__EIM_AD07                0x1b8 0x588 0x000 0x0 0x0
+#define MX6DL_PAD_EIM_DA7__IPU1_DISP1_DATA02       0x1b8 0x588 0x000 0x1 0x0
+#define MX6DL_PAD_EIM_DA7__IPU1_CSI1_DATA02        0x1b8 0x588 0x000 0x2 0x0
+#define MX6DL_PAD_EIM_DA7__GPIO3_IO07              0x1b8 0x588 0x000 0x5 0x0
+#define MX6DL_PAD_EIM_DA7__SRC_BOOT_CFG07          0x1b8 0x588 0x000 0x7 0x0
+#define MX6DL_PAD_EIM_DA7__EPDC_SDCE3              0x1b8 0x588 0x000 0x8 0x0
+#define MX6DL_PAD_EIM_DA8__EIM_AD08                0x1bc 0x58c 0x000 0x0 0x0
+#define MX6DL_PAD_EIM_DA8__IPU1_DISP1_DATA01       0x1bc 0x58c 0x000 0x1 0x0
+#define MX6DL_PAD_EIM_DA8__IPU1_CSI1_DATA01        0x1bc 0x58c 0x000 0x2 0x0
+#define MX6DL_PAD_EIM_DA8__GPIO3_IO08              0x1bc 0x58c 0x000 0x5 0x0
+#define MX6DL_PAD_EIM_DA8__SRC_BOOT_CFG08          0x1bc 0x58c 0x000 0x7 0x0
+#define MX6DL_PAD_EIM_DA8__EPDC_SDCE4              0x1bc 0x58c 0x000 0x8 0x0
+#define MX6DL_PAD_EIM_DA9__EIM_AD09                0x1c0 0x590 0x000 0x0 0x0
+#define MX6DL_PAD_EIM_DA9__IPU1_DISP1_DATA00       0x1c0 0x590 0x000 0x1 0x0
+#define MX6DL_PAD_EIM_DA9__IPU1_CSI1_DATA00        0x1c0 0x590 0x000 0x2 0x0
+#define MX6DL_PAD_EIM_DA9__GPIO3_IO09              0x1c0 0x590 0x000 0x5 0x0
+#define MX6DL_PAD_EIM_DA9__SRC_BOOT_CFG09          0x1c0 0x590 0x000 0x7 0x0
+#define MX6DL_PAD_EIM_DA9__EPDC_SDCE5              0x1c0 0x590 0x000 0x8 0x0
+#define MX6DL_PAD_EIM_EB0__EIM_EB0_B               0x1c4 0x594 0x000 0x0 0x0
+#define MX6DL_PAD_EIM_EB0__IPU1_DISP1_DATA11       0x1c4 0x594 0x000 0x1 0x0
+#define MX6DL_PAD_EIM_EB0__IPU1_CSI1_DATA11        0x1c4 0x594 0x88c 0x2 0x1
+#define MX6DL_PAD_EIM_EB0__CCM_PMIC_READY          0x1c4 0x594 0x7d4 0x4 0x0
+#define MX6DL_PAD_EIM_EB0__GPIO2_IO28              0x1c4 0x594 0x000 0x5 0x0
+#define MX6DL_PAD_EIM_EB0__SRC_BOOT_CFG27          0x1c4 0x594 0x000 0x7 0x0
+#define MX6DL_PAD_EIM_EB0__EPDC_PWR_COM            0x1c4 0x594 0x000 0x8 0x0
+#define MX6DL_PAD_EIM_EB1__EIM_EB1_B               0x1c8 0x598 0x000 0x0 0x0
+#define MX6DL_PAD_EIM_EB1__IPU1_DISP1_DATA10       0x1c8 0x598 0x000 0x1 0x0
+#define MX6DL_PAD_EIM_EB1__IPU1_CSI1_DATA10        0x1c8 0x598 0x888 0x2 0x1
+#define MX6DL_PAD_EIM_EB1__GPIO2_IO29              0x1c8 0x598 0x000 0x5 0x0
+#define MX6DL_PAD_EIM_EB1__SRC_BOOT_CFG28          0x1c8 0x598 0x000 0x7 0x0
+#define MX6DL_PAD_EIM_EB1__EPDC_SDSHR              0x1c8 0x598 0x000 0x8 0x0
+#define MX6DL_PAD_EIM_EB2__EIM_EB2_B               0x1cc 0x59c 0x000 0x0 0x0
+#define MX6DL_PAD_EIM_EB2__ECSPI1_SS0              0x1cc 0x59c 0x7e4 0x1 0x2
+#define MX6DL_PAD_EIM_EB2__IPU1_CSI1_DATA19        0x1cc 0x59c 0x8ac 0x3 0x1
+#define MX6DL_PAD_EIM_EB2__HDMI_TX_DDC_SCL         0x1cc 0x59c 0x860 0x4 0x0
+#define MX6DL_PAD_EIM_EB2__GPIO2_IO30              0x1cc 0x59c 0x000 0x5 0x0
+#define MX6DL_PAD_EIM_EB2__I2C2_SCL                0x1cc 0x59c 0x870 0x6 0x0
+#define MX6DL_PAD_EIM_EB2__SRC_BOOT_CFG30          0x1cc 0x59c 0x000 0x7 0x0
+#define MX6DL_PAD_EIM_EB2__EPDC_DATA05             0x1cc 0x59c 0x000 0x8 0x0
+#define MX6DL_PAD_EIM_EB3__EIM_EB3_B               0x1d0 0x5a0 0x000 0x0 0x0
+#define MX6DL_PAD_EIM_EB3__ECSPI4_RDY              0x1d0 0x5a0 0x000 0x1 0x0
+#define MX6DL_PAD_EIM_EB3__UART3_RTS_B             0x1d0 0x5a0 0x908 0x2 0x3
+#define MX6DL_PAD_EIM_EB3__UART3_CTS_B             0x1d0 0x5a0 0x000 0x2 0x0
+#define MX6DL_PAD_EIM_EB3__UART1_RI_B              0x1d0 0x5a0 0x000 0x3 0x0
+#define MX6DL_PAD_EIM_EB3__IPU1_CSI1_HSYNC         0x1d0 0x5a0 0x8b4 0x4 0x1
+#define MX6DL_PAD_EIM_EB3__GPIO2_IO31              0x1d0 0x5a0 0x000 0x5 0x0
+#define MX6DL_PAD_EIM_EB3__IPU1_DI1_PIN03          0x1d0 0x5a0 0x000 0x6 0x0
+#define MX6DL_PAD_EIM_EB3__SRC_BOOT_CFG31          0x1d0 0x5a0 0x000 0x7 0x0
+#define MX6DL_PAD_EIM_EB3__EPDC_SDCE0              0x1d0 0x5a0 0x000 0x8 0x0
+#define MX6DL_PAD_EIM_EB3__EIM_ACLK_FREERUN        0x1d0 0x5a0 0x000 0x9 0x0
+#define MX6DL_PAD_EIM_LBA__EIM_LBA_B               0x1d4 0x5a4 0x000 0x0 0x0
+#define MX6DL_PAD_EIM_LBA__IPU1_DI1_PIN17          0x1d4 0x5a4 0x000 0x1 0x0
+#define MX6DL_PAD_EIM_LBA__ECSPI2_SS1              0x1d4 0x5a4 0x804 0x2 0x1
+#define MX6DL_PAD_EIM_LBA__GPIO2_IO27              0x1d4 0x5a4 0x000 0x5 0x0
+#define MX6DL_PAD_EIM_LBA__SRC_BOOT_CFG26          0x1d4 0x5a4 0x000 0x7 0x0
+#define MX6DL_PAD_EIM_LBA__EPDC_DATA04             0x1d4 0x5a4 0x000 0x8 0x0
+#define MX6DL_PAD_EIM_OE__EIM_OE_B                 0x1d8 0x5a8 0x000 0x0 0x0
+#define MX6DL_PAD_EIM_OE__IPU1_DI1_PIN07           0x1d8 0x5a8 0x000 0x1 0x0
+#define MX6DL_PAD_EIM_OE__ECSPI2_MISO              0x1d8 0x5a8 0x7f8 0x2 0x2
+#define MX6DL_PAD_EIM_OE__GPIO2_IO25               0x1d8 0x5a8 0x000 0x5 0x0
+#define MX6DL_PAD_EIM_OE__EPDC_PWR_IRQ             0x1d8 0x5a8 0x000 0x8 0x0
+#define MX6DL_PAD_EIM_RW__EIM_RW                   0x1dc 0x5ac 0x000 0x0 0x0
+#define MX6DL_PAD_EIM_RW__IPU1_DI1_PIN08           0x1dc 0x5ac 0x000 0x1 0x0
+#define MX6DL_PAD_EIM_RW__ECSPI2_SS0               0x1dc 0x5ac 0x800 0x2 0x2
+#define MX6DL_PAD_EIM_RW__GPIO2_IO26               0x1dc 0x5ac 0x000 0x5 0x0
+#define MX6DL_PAD_EIM_RW__SRC_BOOT_CFG29           0x1dc 0x5ac 0x000 0x7 0x0
+#define MX6DL_PAD_EIM_RW__EPDC_DATA07              0x1dc 0x5ac 0x000 0x8 0x0
+#define MX6DL_PAD_EIM_WAIT__EIM_WAIT_B             0x1e0 0x5b0 0x000 0x0 0x0
+#define MX6DL_PAD_EIM_WAIT__EIM_DTACK_B            0x1e0 0x5b0 0x000 0x1 0x0
+#define MX6DL_PAD_EIM_WAIT__GPIO5_IO00             0x1e0 0x5b0 0x000 0x5 0x0
+#define MX6DL_PAD_EIM_WAIT__SRC_BOOT_CFG25         0x1e0 0x5b0 0x000 0x7 0x0
+#define MX6DL_PAD_ENET_CRS_DV__ENET_RX_EN          0x1e4 0x5b4 0x828 0x1 0x0
+#define MX6DL_PAD_ENET_CRS_DV__ESAI_TX_CLK         0x1e4 0x5b4 0x840 0x2 0x0
+#define MX6DL_PAD_ENET_CRS_DV__SPDIF_EXT_CLK       0x1e4 0x5b4 0x8f4 0x3 0x0
+#define MX6DL_PAD_ENET_CRS_DV__GPIO1_IO25          0x1e4 0x5b4 0x000 0x5 0x0
+#define MX6DL_PAD_ENET_MDC__MLB_DATA               0x1e8 0x5b8 0x8e0 0x0 0x0
+#define MX6DL_PAD_ENET_MDC__ENET_MDC               0x1e8 0x5b8 0x000 0x1 0x0
+#define MX6DL_PAD_ENET_MDC__ESAI_TX5_RX0           0x1e8 0x5b8 0x858 0x2 0x0
+#define MX6DL_PAD_ENET_MDC__ENET_1588_EVENT1_IN    0x1e8 0x5b8 0x000 0x4 0x0
+#define MX6DL_PAD_ENET_MDC__GPIO1_IO31             0x1e8 0x5b8 0x000 0x5 0x0
+#define MX6DL_PAD_ENET_MDIO__ENET_MDIO             0x1ec 0x5bc 0x810 0x1 0x0
+#define MX6DL_PAD_ENET_MDIO__ESAI_RX_CLK           0x1ec 0x5bc 0x83c 0x2 0x0
+#define MX6DL_PAD_ENET_MDIO__ENET_1588_EVENT1_OUT  0x1ec 0x5bc 0x000 0x4 0x0
+#define MX6DL_PAD_ENET_MDIO__GPIO1_IO22            0x1ec 0x5bc 0x000 0x5 0x0
+#define MX6DL_PAD_ENET_MDIO__SPDIF_LOCK            0x1ec 0x5bc 0x000 0x6 0x0
+#define MX6DL_PAD_ENET_REF_CLK__ENET_TX_CLK        0x1f0 0x5c0 0x000 0x1 0x0
+#define MX6DL_PAD_ENET_REF_CLK__ESAI_RX_FS         0x1f0 0x5c0 0x82c 0x2 0x0
+#define MX6DL_PAD_ENET_REF_CLK__GPIO1_IO23         0x1f0 0x5c0 0x000 0x5 0x0
+#define MX6DL_PAD_ENET_REF_CLK__SPDIF_SR_CLK       0x1f0 0x5c0 0x000 0x6 0x0
+#define MX6DL_PAD_ENET_RX_ER__USB_OTG_ID           0x1f4 0x5c4 0x790 0x0 0x0
+#define MX6DL_PAD_ENET_RX_ER__ENET_RX_ER           0x1f4 0x5c4 0x000 0x1 0x0
+#define MX6DL_PAD_ENET_RX_ER__ESAI_RX_HF_CLK       0x1f4 0x5c4 0x834 0x2 0x0
+#define MX6DL_PAD_ENET_RX_ER__SPDIF_IN             0x1f4 0x5c4 0x8f0 0x3 0x1
+#define MX6DL_PAD_ENET_RX_ER__ENET_1588_EVENT2_OUT 0x1f4 0x5c4 0x000 0x4 0x0
+#define MX6DL_PAD_ENET_RX_ER__GPIO1_IO24           0x1f4 0x5c4 0x000 0x5 0x0
+#define MX6DL_PAD_ENET_RXD0__ENET_RX_DATA0         0x1f8 0x5c8 0x818 0x1 0x0
+#define MX6DL_PAD_ENET_RXD0__ESAI_TX_HF_CLK        0x1f8 0x5c8 0x838 0x2 0x0
+#define MX6DL_PAD_ENET_RXD0__SPDIF_OUT             0x1f8 0x5c8 0x000 0x3 0x0
+#define MX6DL_PAD_ENET_RXD0__GPIO1_IO27            0x1f8 0x5c8 0x000 0x5 0x0
+#define MX6DL_PAD_ENET_RXD1__MLB_SIG               0x1fc 0x5cc 0x8e4 0x0 0x0
+#define MX6DL_PAD_ENET_RXD1__ENET_RX_DATA1         0x1fc 0x5cc 0x81c 0x1 0x0
+#define MX6DL_PAD_ENET_RXD1__ESAI_TX_FS            0x1fc 0x5cc 0x830 0x2 0x0
+#define MX6DL_PAD_ENET_RXD1__ENET_1588_EVENT3_OUT  0x1fc 0x5cc 0x000 0x4 0x0
+#define MX6DL_PAD_ENET_RXD1__GPIO1_IO26            0x1fc 0x5cc 0x000 0x5 0x0
+#define MX6DL_PAD_ENET_TX_EN__ENET_TX_EN           0x200 0x5d0 0x000 0x1 0x0
+#define MX6DL_PAD_ENET_TX_EN__ESAI_TX3_RX2         0x200 0x5d0 0x850 0x2 0x0
+#define MX6DL_PAD_ENET_TX_EN__GPIO1_IO28           0x200 0x5d0 0x000 0x5 0x0
+#define MX6DL_PAD_ENET_TX_EN__I2C4_SCL             0x200 0x5d0 0x880 0x9 0x0
+#define MX6DL_PAD_ENET_TXD0__ENET_TX_DATA0         0x204 0x5d4 0x000 0x1 0x0
+#define MX6DL_PAD_ENET_TXD0__ESAI_TX4_RX1          0x204 0x5d4 0x854 0x2 0x0
+#define MX6DL_PAD_ENET_TXD0__GPIO1_IO30            0x204 0x5d4 0x000 0x5 0x0
+#define MX6DL_PAD_ENET_TXD1__MLB_CLK               0x208 0x5d8 0x8dc 0x0 0x0
+#define MX6DL_PAD_ENET_TXD1__ENET_TX_DATA1         0x208 0x5d8 0x000 0x1 0x0
+#define MX6DL_PAD_ENET_TXD1__ESAI_TX2_RX3          0x208 0x5d8 0x84c 0x2 0x0
+#define MX6DL_PAD_ENET_TXD1__ENET_1588_EVENT0_IN   0x208 0x5d8 0x000 0x4 0x0
+#define MX6DL_PAD_ENET_TXD1__GPIO1_IO29            0x208 0x5d8 0x000 0x5 0x0
+#define MX6DL_PAD_ENET_TXD1__I2C4_SDA              0x208 0x5d8 0x884 0x9 0x0
+#define MX6DL_PAD_GPIO_0__CCM_CLKO1                0x20c 0x5dc 0x000 0x0 0x0
+#define MX6DL_PAD_GPIO_0__KEY_COL5                 0x20c 0x5dc 0x8c0 0x2 0x1
+#define MX6DL_PAD_GPIO_0__ASRC_EXT_CLK             0x20c 0x5dc 0x794 0x3 0x0
+#define MX6DL_PAD_GPIO_0__EPIT1_OUT                0x20c 0x5dc 0x000 0x4 0x0
+#define MX6DL_PAD_GPIO_0__GPIO1_IO00               0x20c 0x5dc 0x000 0x5 0x0
+#define MX6DL_PAD_GPIO_0__USB_H1_PWR               0x20c 0x5dc 0x000 0x6 0x0
+#define MX6DL_PAD_GPIO_0__SNVS_VIO_5               0x20c 0x5dc 0x000 0x7 0x0
+#define MX6DL_PAD_GPIO_1__ESAI_RX_CLK              0x210 0x5e0 0x83c 0x0 0x1
+#define MX6DL_PAD_GPIO_1__WDOG2_B                  0x210 0x5e0 0x000 0x1 0x0
+#define MX6DL_PAD_GPIO_1__KEY_ROW5                 0x210 0x5e0 0x8cc 0x2 0x1
+#define MX6DL_PAD_GPIO_1__USB_OTG_ID               0x210 0x5e0 0x790 0x3 0x1
+#define MX6DL_PAD_GPIO_1__PWM2_OUT                 0x210 0x5e0 0x000 0x4 0x0
+#define MX6DL_PAD_GPIO_1__GPIO1_IO01               0x210 0x5e0 0x000 0x5 0x0
+#define MX6DL_PAD_GPIO_1__SD1_CD_B                 0x210 0x5e0 0x000 0x6 0x0
+#define MX6DL_PAD_GPIO_16__ESAI_TX3_RX2            0x214 0x5e4 0x850 0x0 0x1
+#define MX6DL_PAD_GPIO_16__ENET_1588_EVENT2_IN     0x214 0x5e4 0x000 0x1 0x0
+#define MX6DL_PAD_GPIO_16__ENET_REF_CLK            0x214 0x5e4 0x80c 0x2 0x0
+#define MX6DL_PAD_GPIO_16__SD1_LCTL                0x214 0x5e4 0x000 0x3 0x0
+#define MX6DL_PAD_GPIO_16__SPDIF_IN                0x214 0x5e4 0x8f0 0x4 0x2
+#define MX6DL_PAD_GPIO_16__GPIO7_IO11              0x214 0x5e4 0x000 0x5 0x0
+#define MX6DL_PAD_GPIO_16__I2C3_SDA                0x214 0x5e4 0x87c 0x6 0x1
+#define MX6DL_PAD_GPIO_16__JTAG_DE_B               0x214 0x5e4 0x000 0x7 0x0
+#define MX6DL_PAD_GPIO_17__ESAI_TX0                0x218 0x5e8 0x844 0x0 0x0
+#define MX6DL_PAD_GPIO_17__ENET_1588_EVENT3_IN     0x218 0x5e8 0x000 0x1 0x0
+#define MX6DL_PAD_GPIO_17__CCM_PMIC_READY          0x218 0x5e8 0x7d4 0x2 0x1
+#define MX6DL_PAD_GPIO_17__SDMA_EXT_EVENT0         0x218 0x5e8 0x8e8 0x3 0x1
+#define MX6DL_PAD_GPIO_17__SPDIF_OUT               0x218 0x5e8 0x000 0x4 0x0
+#define MX6DL_PAD_GPIO_17__GPIO7_IO12              0x218 0x5e8 0x000 0x5 0x0
+#define MX6DL_PAD_GPIO_18__ESAI_TX1                0x21c 0x5ec 0x848 0x0 0x0
+#define MX6DL_PAD_GPIO_18__ENET_RX_CLK             0x21c 0x5ec 0x814 0x1 0x0
+#define MX6DL_PAD_GPIO_18__SD3_VSELECT             0x21c 0x5ec 0x000 0x2 0x0
+#define MX6DL_PAD_GPIO_18__SDMA_EXT_EVENT1         0x21c 0x5ec 0x8ec 0x3 0x1
+#define MX6DL_PAD_GPIO_18__ASRC_EXT_CLK            0x21c 0x5ec 0x794 0x4 0x1
+#define MX6DL_PAD_GPIO_18__GPIO7_IO13              0x21c 0x5ec 0x000 0x5 0x0
+#define MX6DL_PAD_GPIO_18__SNVS_VIO_5_CTL          0x21c 0x5ec 0x000 0x6 0x0
+#define MX6DL_PAD_GPIO_19__KEY_COL5                0x220 0x5f0 0x8c0 0x0 0x2
+#define MX6DL_PAD_GPIO_19__ENET_1588_EVENT0_OUT    0x220 0x5f0 0x000 0x1 0x0
+#define MX6DL_PAD_GPIO_19__SPDIF_OUT               0x220 0x5f0 0x000 0x2 0x0
+#define MX6DL_PAD_GPIO_19__CCM_CLKO1               0x220 0x5f0 0x000 0x3 0x0
+#define MX6DL_PAD_GPIO_19__ECSPI1_RDY              0x220 0x5f0 0x000 0x4 0x0
+#define MX6DL_PAD_GPIO_19__GPIO4_IO05              0x220 0x5f0 0x000 0x5 0x0
+#define MX6DL_PAD_GPIO_19__ENET_TX_ER              0x220 0x5f0 0x000 0x6 0x0
+#define MX6DL_PAD_GPIO_2__ESAI_TX_FS               0x224 0x5f4 0x830 0x0 0x1
+#define MX6DL_PAD_GPIO_2__KEY_ROW6                 0x224 0x5f4 0x8d0 0x2 0x1
+#define MX6DL_PAD_GPIO_2__GPIO1_IO02               0x224 0x5f4 0x000 0x5 0x0
+#define MX6DL_PAD_GPIO_2__SD2_WP                   0x224 0x5f4 0x000 0x6 0x0
+#define MX6DL_PAD_GPIO_2__MLB_DATA                 0x224 0x5f4 0x8e0 0x7 0x1
+#define MX6DL_PAD_GPIO_3__ESAI_RX_HF_CLK           0x228 0x5f8 0x834 0x0 0x1
+#define MX6DL_PAD_GPIO_3__I2C3_SCL                 0x228 0x5f8 0x878 0x2 0x1
+#define MX6DL_PAD_GPIO_3__XTALOSC_REF_CLK_24M      0x228 0x5f8 0x000 0x3 0x0
+#define MX6DL_PAD_GPIO_3__CCM_CLKO2                0x228 0x5f8 0x000 0x4 0x0
+#define MX6DL_PAD_GPIO_3__GPIO1_IO03               0x228 0x5f8 0x000 0x5 0x0
+#define MX6DL_PAD_GPIO_3__USB_H1_OC                0x228 0x5f8 0x924 0x6 0x1
+#define MX6DL_PAD_GPIO_3__MLB_CLK                  0x228 0x5f8 0x8dc 0x7 0x1
+#define MX6DL_PAD_GPIO_4__ESAI_TX_HF_CLK           0x22c 0x5fc 0x838 0x0 0x1
+#define MX6DL_PAD_GPIO_4__KEY_COL7                 0x22c 0x5fc 0x8c8 0x2 0x1
+#define MX6DL_PAD_GPIO_4__GPIO1_IO04               0x22c 0x5fc 0x000 0x5 0x0
+#define MX6DL_PAD_GPIO_4__SD2_CD_B                 0x22c 0x5fc 0x000 0x6 0x0
+#define MX6DL_PAD_GPIO_5__ESAI_TX2_RX3             0x230 0x600 0x84c 0x0 0x1
+#define MX6DL_PAD_GPIO_5__KEY_ROW7                 0x230 0x600 0x8d4 0x2 0x1
+#define MX6DL_PAD_GPIO_5__CCM_CLKO1                0x230 0x600 0x000 0x3 0x0
+#define MX6DL_PAD_GPIO_5__GPIO1_IO05               0x230 0x600 0x000 0x5 0x0
+#define MX6DL_PAD_GPIO_5__I2C3_SCL                 0x230 0x600 0x878 0x6 0x2
+#define MX6DL_PAD_GPIO_5__ARM_EVENTI               0x230 0x600 0x000 0x7 0x0
+#define MX6DL_PAD_GPIO_6__ESAI_TX_CLK              0x234 0x604 0x840 0x0 0x1
+#define MX6DL_PAD_GPIO_6__I2C3_SDA                 0x234 0x604 0x87c 0x2 0x2
+#define MX6DL_PAD_GPIO_6__GPIO1_IO06               0x234 0x604 0x000 0x5 0x0
+#define MX6DL_PAD_GPIO_6__SD2_LCTL                 0x234 0x604 0x000 0x6 0x0
+#define MX6DL_PAD_GPIO_6__MLB_SIG                  0x234 0x604 0x8e4 0x7 0x1
+#define MX6DL_PAD_GPIO_7__ESAI_TX4_RX1             0x238 0x608 0x854 0x0 0x1
+#define MX6DL_PAD_GPIO_7__EPIT1_OUT                0x238 0x608 0x000 0x2 0x0
+#define MX6DL_PAD_GPIO_7__FLEXCAN1_TX              0x238 0x608 0x000 0x3 0x0
+#define MX6DL_PAD_GPIO_7__UART2_TX_DATA            0x238 0x608 0x000 0x4 0x0
+#define MX6DL_PAD_GPIO_7__UART2_RX_DATA            0x238 0x608 0x904 0x4 0x2
+#define MX6DL_PAD_GPIO_7__GPIO1_IO07               0x238 0x608 0x000 0x5 0x0
+#define MX6DL_PAD_GPIO_7__SPDIF_LOCK               0x238 0x608 0x000 0x6 0x0
+#define MX6DL_PAD_GPIO_7__USB_OTG_HOST_MODE        0x238 0x608 0x000 0x7 0x0
+#define MX6DL_PAD_GPIO_7__I2C4_SCL                 0x238 0x608 0x880 0x8 0x1
+#define MX6DL_PAD_GPIO_8__ESAI_TX5_RX0             0x23c 0x60c 0x858 0x0 0x1
+#define MX6DL_PAD_GPIO_8__XTALOSC_REF_CLK_32K      0x23c 0x60c 0x000 0x1 0x0
+#define MX6DL_PAD_GPIO_8__EPIT2_OUT                0x23c 0x60c 0x000 0x2 0x0
+#define MX6DL_PAD_GPIO_8__FLEXCAN1_RX              0x23c 0x60c 0x7c8 0x3 0x0
+#define MX6DL_PAD_GPIO_8__UART2_RX_DATA            0x23c 0x60c 0x904 0x4 0x3
+#define MX6DL_PAD_GPIO_8__UART2_TX_DATA            0x23c 0x60c 0x000 0x4 0x0
+#define MX6DL_PAD_GPIO_8__GPIO1_IO08               0x23c 0x60c 0x000 0x5 0x0
+#define MX6DL_PAD_GPIO_8__SPDIF_SR_CLK             0x23c 0x60c 0x000 0x6 0x0
+#define MX6DL_PAD_GPIO_8__USB_OTG_PWR_CTL_WAKE     0x23c 0x60c 0x000 0x7 0x0
+#define MX6DL_PAD_GPIO_8__I2C4_SDA                 0x23c 0x60c 0x884 0x8 0x1
+#define MX6DL_PAD_GPIO_9__ESAI_RX_FS               0x240 0x610 0x82c 0x0 0x1
+#define MX6DL_PAD_GPIO_9__WDOG1_B                  0x240 0x610 0x000 0x1 0x0
+#define MX6DL_PAD_GPIO_9__KEY_COL6                 0x240 0x610 0x8c4 0x2 0x1
+#define MX6DL_PAD_GPIO_9__CCM_REF_EN_B             0x240 0x610 0x000 0x3 0x0
+#define MX6DL_PAD_GPIO_9__PWM1_OUT                 0x240 0x610 0x000 0x4 0x0
+#define MX6DL_PAD_GPIO_9__GPIO1_IO09               0x240 0x610 0x000 0x5 0x0
+#define MX6DL_PAD_GPIO_9__SD1_WP                   0x240 0x610 0x92c 0x6 0x1
+#define MX6DL_PAD_KEY_COL0__ECSPI1_SCLK            0x244 0x62c 0x7d8 0x0 0x3
+#define MX6DL_PAD_KEY_COL0__ENET_RX_DATA3          0x244 0x62c 0x824 0x1 0x0
+#define MX6DL_PAD_KEY_COL0__AUD5_TXC               0x244 0x62c 0x7c0 0x2 0x1
+#define MX6DL_PAD_KEY_COL0__KEY_COL0               0x244 0x62c 0x000 0x3 0x0
+#define MX6DL_PAD_KEY_COL0__UART4_TX_DATA          0x244 0x62c 0x000 0x4 0x0
+#define MX6DL_PAD_KEY_COL0__UART4_RX_DATA          0x244 0x62c 0x914 0x4 0x2
+#define MX6DL_PAD_KEY_COL0__GPIO4_IO06             0x244 0x62c 0x000 0x5 0x0
+#define MX6DL_PAD_KEY_COL0__DCIC1_OUT              0x244 0x62c 0x000 0x6 0x0
+#define MX6DL_PAD_KEY_COL1__ECSPI1_MISO            0x248 0x630 0x7dc 0x0 0x3
+#define MX6DL_PAD_KEY_COL1__ENET_MDIO              0x248 0x630 0x810 0x1 0x1
+#define MX6DL_PAD_KEY_COL1__AUD5_TXFS              0x248 0x630 0x7c4 0x2 0x1
+#define MX6DL_PAD_KEY_COL1__KEY_COL1               0x248 0x630 0x000 0x3 0x0
+#define MX6DL_PAD_KEY_COL1__UART5_TX_DATA          0x248 0x630 0x000 0x4 0x0
+#define MX6DL_PAD_KEY_COL1__UART5_RX_DATA          0x248 0x630 0x91c 0x4 0x2
+#define MX6DL_PAD_KEY_COL1__GPIO4_IO08             0x248 0x630 0x000 0x5 0x0
+#define MX6DL_PAD_KEY_COL1__SD1_VSELECT            0x248 0x630 0x000 0x6 0x0
+#define MX6DL_PAD_KEY_COL2__ECSPI1_SS1             0x24c 0x634 0x7e8 0x0 0x2
+#define MX6DL_PAD_KEY_COL2__ENET_RX_DATA2          0x24c 0x634 0x820 0x1 0x0
+#define MX6DL_PAD_KEY_COL2__FLEXCAN1_TX            0x24c 0x634 0x000 0x2 0x0
+#define MX6DL_PAD_KEY_COL2__KEY_COL2               0x24c 0x634 0x000 0x3 0x0
+#define MX6DL_PAD_KEY_COL2__ENET_MDC               0x24c 0x634 0x000 0x4 0x0
+#define MX6DL_PAD_KEY_COL2__GPIO4_IO10             0x24c 0x634 0x000 0x5 0x0
+#define MX6DL_PAD_KEY_COL2__USB_H1_PWR_CTL_WAKE    0x24c 0x634 0x000 0x6 0x0
+#define MX6DL_PAD_KEY_COL3__ECSPI1_SS3             0x250 0x638 0x7f0 0x0 0x1
+#define MX6DL_PAD_KEY_COL3__ENET_CRS               0x250 0x638 0x000 0x1 0x0
+#define MX6DL_PAD_KEY_COL3__HDMI_TX_DDC_SCL        0x250 0x638 0x860 0x2 0x1
+#define MX6DL_PAD_KEY_COL3__KEY_COL3               0x250 0x638 0x000 0x3 0x0
+#define MX6DL_PAD_KEY_COL3__I2C2_SCL               0x250 0x638 0x870 0x4 0x1
+#define MX6DL_PAD_KEY_COL3__GPIO4_IO12             0x250 0x638 0x000 0x5 0x0
+#define MX6DL_PAD_KEY_COL3__SPDIF_IN               0x250 0x638 0x8f0 0x6 0x3
+#define MX6DL_PAD_KEY_COL4__FLEXCAN2_TX            0x254 0x63c 0x000 0x0 0x0
+#define MX6DL_PAD_KEY_COL4__IPU1_SISG4             0x254 0x63c 0x000 0x1 0x0
+#define MX6DL_PAD_KEY_COL4__USB_OTG_OC             0x254 0x63c 0x920 0x2 0x1
+#define MX6DL_PAD_KEY_COL4__KEY_COL4               0x254 0x63c 0x000 0x3 0x0
+#define MX6DL_PAD_KEY_COL4__UART5_RTS_B            0x254 0x63c 0x918 0x4 0x2
+#define MX6DL_PAD_KEY_COL4__UART5_CTS_B            0x254 0x63c 0x000 0x4 0x0
+#define MX6DL_PAD_KEY_COL4__GPIO4_IO14             0x254 0x63c 0x000 0x5 0x0
+#define MX6DL_PAD_KEY_ROW0__ECSPI1_MOSI            0x258 0x640 0x7e0 0x0 0x3
+#define MX6DL_PAD_KEY_ROW0__ENET_TX_DATA3          0x258 0x640 0x000 0x1 0x0
+#define MX6DL_PAD_KEY_ROW0__AUD5_TXD               0x258 0x640 0x7b4 0x2 0x1
+#define MX6DL_PAD_KEY_ROW0__KEY_ROW0               0x258 0x640 0x000 0x3 0x0
+#define MX6DL_PAD_KEY_ROW0__UART4_RX_DATA          0x258 0x640 0x914 0x4 0x3
+#define MX6DL_PAD_KEY_ROW0__UART4_TX_DATA          0x258 0x640 0x000 0x4 0x0
+#define MX6DL_PAD_KEY_ROW0__GPIO4_IO07             0x258 0x640 0x000 0x5 0x0
+#define MX6DL_PAD_KEY_ROW0__DCIC2_OUT              0x258 0x640 0x000 0x6 0x0
+#define MX6DL_PAD_KEY_ROW1__ECSPI1_SS0             0x25c 0x644 0x7e4 0x0 0x3
+#define MX6DL_PAD_KEY_ROW1__ENET_COL               0x25c 0x644 0x000 0x1 0x0
+#define MX6DL_PAD_KEY_ROW1__AUD5_RXD               0x25c 0x644 0x7b0 0x2 0x1
+#define MX6DL_PAD_KEY_ROW1__KEY_ROW1               0x25c 0x644 0x000 0x3 0x0
+#define MX6DL_PAD_KEY_ROW1__UART5_RX_DATA          0x25c 0x644 0x91c 0x4 0x3
+#define MX6DL_PAD_KEY_ROW1__UART5_TX_DATA          0x25c 0x644 0x000 0x4 0x0
+#define MX6DL_PAD_KEY_ROW1__GPIO4_IO09             0x25c 0x644 0x000 0x5 0x0
+#define MX6DL_PAD_KEY_ROW1__SD2_VSELECT            0x25c 0x644 0x000 0x6 0x0
+#define MX6DL_PAD_KEY_ROW2__ECSPI1_SS2             0x260 0x648 0x7ec 0x0 0x1
+#define MX6DL_PAD_KEY_ROW2__ENET_TX_DATA2          0x260 0x648 0x000 0x1 0x0
+#define MX6DL_PAD_KEY_ROW2__FLEXCAN1_RX            0x260 0x648 0x7c8 0x2 0x1
+#define MX6DL_PAD_KEY_ROW2__KEY_ROW2               0x260 0x648 0x000 0x3 0x0
+#define MX6DL_PAD_KEY_ROW2__SD2_VSELECT            0x260 0x648 0x000 0x4 0x0
+#define MX6DL_PAD_KEY_ROW2__GPIO4_IO11             0x260 0x648 0x000 0x5 0x0
+#define MX6DL_PAD_KEY_ROW2__HDMI_TX_CEC_LINE       0x260 0x648 0x85c 0x6 0x1
+#define MX6DL_PAD_KEY_ROW3__ASRC_EXT_CLK           0x264 0x64c 0x794 0x1 0x2
+#define MX6DL_PAD_KEY_ROW3__HDMI_TX_DDC_SDA        0x264 0x64c 0x864 0x2 0x1
+#define MX6DL_PAD_KEY_ROW3__KEY_ROW3               0x264 0x64c 0x000 0x3 0x0
+#define MX6DL_PAD_KEY_ROW3__I2C2_SDA               0x264 0x64c 0x874 0x4 0x1
+#define MX6DL_PAD_KEY_ROW3__GPIO4_IO13             0x264 0x64c 0x000 0x5 0x0
+#define MX6DL_PAD_KEY_ROW3__SD1_VSELECT            0x264 0x64c 0x000 0x6 0x0
+#define MX6DL_PAD_KEY_ROW4__FLEXCAN2_RX            0x268 0x650 0x7cc 0x0 0x0
+#define MX6DL_PAD_KEY_ROW4__IPU1_SISG5             0x268 0x650 0x000 0x1 0x0
+#define MX6DL_PAD_KEY_ROW4__USB_OTG_PWR            0x268 0x650 0x000 0x2 0x0
+#define MX6DL_PAD_KEY_ROW4__KEY_ROW4               0x268 0x650 0x000 0x3 0x0
+#define MX6DL_PAD_KEY_ROW4__UART5_CTS_B            0x268 0x650 0x000 0x4 0x0
+#define MX6DL_PAD_KEY_ROW4__UART5_RTS_B            0x268 0x650 0x918 0x4 0x3
+#define MX6DL_PAD_KEY_ROW4__GPIO4_IO15             0x268 0x650 0x000 0x5 0x0
+#define MX6DL_PAD_NANDF_ALE__NAND_ALE              0x26c 0x654 0x000 0x0 0x0
+#define MX6DL_PAD_NANDF_ALE__SD4_RESET             0x26c 0x654 0x000 0x1 0x0
+#define MX6DL_PAD_NANDF_ALE__GPIO6_IO08            0x26c 0x654 0x000 0x5 0x0
+#define MX6DL_PAD_NANDF_CLE__NAND_CLE              0x270 0x658 0x000 0x0 0x0
+#define MX6DL_PAD_NANDF_CLE__GPIO6_IO07            0x270 0x658 0x000 0x5 0x0
+#define MX6DL_PAD_NANDF_CS0__NAND_CE0_B            0x274 0x65c 0x000 0x0 0x0
+#define MX6DL_PAD_NANDF_CS0__GPIO6_IO11            0x274 0x65c 0x000 0x5 0x0
+#define MX6DL_PAD_NANDF_CS1__NAND_CE1_B            0x278 0x660 0x000 0x0 0x0
+#define MX6DL_PAD_NANDF_CS1__SD4_VSELECT           0x278 0x660 0x000 0x1 0x0
+#define MX6DL_PAD_NANDF_CS1__SD3_VSELECT           0x278 0x660 0x000 0x2 0x0
+#define MX6DL_PAD_NANDF_CS1__GPIO6_IO14            0x278 0x660 0x000 0x5 0x0
+#define MX6DL_PAD_NANDF_CS2__NAND_CE2_B            0x27c 0x664 0x000 0x0 0x0
+#define MX6DL_PAD_NANDF_CS2__IPU1_SISG0            0x27c 0x664 0x000 0x1 0x0
+#define MX6DL_PAD_NANDF_CS2__ESAI_TX0              0x27c 0x664 0x844 0x2 0x1
+#define MX6DL_PAD_NANDF_CS2__EIM_CRE               0x27c 0x664 0x000 0x3 0x0
+#define MX6DL_PAD_NANDF_CS2__CCM_CLKO2             0x27c 0x664 0x000 0x4 0x0
+#define MX6DL_PAD_NANDF_CS2__GPIO6_IO15            0x27c 0x664 0x000 0x5 0x0
+#define MX6DL_PAD_NANDF_CS3__NAND_CE3_B            0x280 0x668 0x000 0x0 0x0
+#define MX6DL_PAD_NANDF_CS3__IPU1_SISG1            0x280 0x668 0x000 0x1 0x0
+#define MX6DL_PAD_NANDF_CS3__ESAI_TX1              0x280 0x668 0x848 0x2 0x1
+#define MX6DL_PAD_NANDF_CS3__EIM_ADDR26            0x280 0x668 0x000 0x3 0x0
+#define MX6DL_PAD_NANDF_CS3__GPIO6_IO16            0x280 0x668 0x000 0x5 0x0
+#define MX6DL_PAD_NANDF_CS3__I2C4_SDA              0x280 0x668 0x884 0x9 0x2
+#define MX6DL_PAD_NANDF_D0__NAND_DATA00            0x284 0x66c 0x000 0x0 0x0
+#define MX6DL_PAD_NANDF_D0__SD1_DATA4              0x284 0x66c 0x000 0x1 0x0
+#define MX6DL_PAD_NANDF_D0__GPIO2_IO00             0x284 0x66c 0x000 0x5 0x0
+#define MX6DL_PAD_NANDF_D1__NAND_DATA01            0x288 0x670 0x000 0x0 0x0
+#define MX6DL_PAD_NANDF_D1__SD1_DATA5              0x288 0x670 0x000 0x1 0x0
+#define MX6DL_PAD_NANDF_D1__GPIO2_IO01             0x288 0x670 0x000 0x5 0x0
+#define MX6DL_PAD_NANDF_D2__NAND_DATA02            0x28c 0x674 0x000 0x0 0x0
+#define MX6DL_PAD_NANDF_D2__SD1_DATA6              0x28c 0x674 0x000 0x1 0x0
+#define MX6DL_PAD_NANDF_D2__GPIO2_IO02             0x28c 0x674 0x000 0x5 0x0
+#define MX6DL_PAD_NANDF_D3__NAND_DATA03            0x290 0x678 0x000 0x0 0x0
+#define MX6DL_PAD_NANDF_D3__SD1_DATA7              0x290 0x678 0x000 0x1 0x0
+#define MX6DL_PAD_NANDF_D3__GPIO2_IO03             0x290 0x678 0x000 0x5 0x0
+#define MX6DL_PAD_NANDF_D4__NAND_DATA04            0x294 0x67c 0x000 0x0 0x0
+#define MX6DL_PAD_NANDF_D4__SD2_DATA4              0x294 0x67c 0x000 0x1 0x0
+#define MX6DL_PAD_NANDF_D4__GPIO2_IO04             0x294 0x67c 0x000 0x5 0x0
+#define MX6DL_PAD_NANDF_D5__NAND_DATA05            0x298 0x680 0x000 0x0 0x0
+#define MX6DL_PAD_NANDF_D5__SD2_DATA5              0x298 0x680 0x000 0x1 0x0
+#define MX6DL_PAD_NANDF_D5__GPIO2_IO05             0x298 0x680 0x000 0x5 0x0
+#define MX6DL_PAD_NANDF_D6__NAND_DATA06            0x29c 0x684 0x000 0x0 0x0
+#define MX6DL_PAD_NANDF_D6__SD2_DATA6              0x29c 0x684 0x000 0x1 0x0
+#define MX6DL_PAD_NANDF_D6__GPIO2_IO06             0x29c 0x684 0x000 0x5 0x0
+#define MX6DL_PAD_NANDF_D7__NAND_DATA07            0x2a0 0x688 0x000 0x0 0x0
+#define MX6DL_PAD_NANDF_D7__SD2_DATA7              0x2a0 0x688 0x000 0x1 0x0
+#define MX6DL_PAD_NANDF_D7__GPIO2_IO07             0x2a0 0x688 0x000 0x5 0x0
+#define MX6DL_PAD_NANDF_RB0__NAND_READY_B          0x2a4 0x68c 0x000 0x0 0x0
+#define MX6DL_PAD_NANDF_RB0__GPIO6_IO10            0x2a4 0x68c 0x000 0x5 0x0
+#define MX6DL_PAD_NANDF_WP_B__NAND_WP_B            0x2a8 0x690 0x000 0x0 0x0
+#define MX6DL_PAD_NANDF_WP_B__GPIO6_IO09           0x2a8 0x690 0x000 0x5 0x0
+#define MX6DL_PAD_NANDF_WP_B__I2C4_SCL             0x2a8 0x690 0x880 0x9 0x2
+#define MX6DL_PAD_RGMII_RD0__HSI_RX_READY          0x2ac 0x694 0x000 0x0 0x0
+#define MX6DL_PAD_RGMII_RD0__RGMII_RD0             0x2ac 0x694 0x818 0x1 0x1
+#define MX6DL_PAD_RGMII_RD0__GPIO6_IO25            0x2ac 0x694 0x000 0x5 0x0
+#define MX6DL_PAD_RGMII_RD1__HSI_TX_FLAG           0x2b0 0x698 0x000 0x0 0x0
+#define MX6DL_PAD_RGMII_RD1__RGMII_RD1             0x2b0 0x698 0x81c 0x1 0x1
+#define MX6DL_PAD_RGMII_RD1__GPIO6_IO27            0x2b0 0x698 0x000 0x5 0x0
+#define MX6DL_PAD_RGMII_RD2__HSI_TX_DATA           0x2b4 0x69c 0x000 0x0 0x0
+#define MX6DL_PAD_RGMII_RD2__RGMII_RD2             0x2b4 0x69c 0x820 0x1 0x1
+#define MX6DL_PAD_RGMII_RD2__GPIO6_IO28            0x2b4 0x69c 0x000 0x5 0x0
+#define MX6DL_PAD_RGMII_RD3__HSI_TX_WAKE           0x2b8 0x6a0 0x000 0x0 0x0
+#define MX6DL_PAD_RGMII_RD3__RGMII_RD3             0x2b8 0x6a0 0x824 0x1 0x1
+#define MX6DL_PAD_RGMII_RD3__GPIO6_IO29            0x2b8 0x6a0 0x000 0x5 0x0
+#define MX6DL_PAD_RGMII_RX_CTL__USB_H3_DATA        0x2bc 0x6a4 0x000 0x0 0x0
+#define MX6DL_PAD_RGMII_RX_CTL__RGMII_RX_CTL       0x2bc 0x6a4 0x828 0x1 0x1
+#define MX6DL_PAD_RGMII_RX_CTL__GPIO6_IO24         0x2bc 0x6a4 0x000 0x5 0x0
+#define MX6DL_PAD_RGMII_RXC__USB_H3_STROBE         0x2c0 0x6a8 0x000 0x0 0x0
+#define MX6DL_PAD_RGMII_RXC__RGMII_RXC             0x2c0 0x6a8 0x814 0x1 0x1
+#define MX6DL_PAD_RGMII_RXC__GPIO6_IO30            0x2c0 0x6a8 0x000 0x5 0x0
+#define MX6DL_PAD_RGMII_TD0__HSI_TX_READY          0x2c4 0x6ac 0x000 0x0 0x0
+#define MX6DL_PAD_RGMII_TD0__RGMII_TD0             0x2c4 0x6ac 0x000 0x1 0x0
+#define MX6DL_PAD_RGMII_TD0__GPIO6_IO20            0x2c4 0x6ac 0x000 0x5 0x0
+#define MX6DL_PAD_RGMII_TD1__HSI_RX_FLAG           0x2c8 0x6b0 0x000 0x0 0x0
+#define MX6DL_PAD_RGMII_TD1__RGMII_TD1             0x2c8 0x6b0 0x000 0x1 0x0
+#define MX6DL_PAD_RGMII_TD1__GPIO6_IO21            0x2c8 0x6b0 0x000 0x5 0x0
+#define MX6DL_PAD_RGMII_TD2__HSI_RX_DATA           0x2cc 0x6b4 0x000 0x0 0x0
+#define MX6DL_PAD_RGMII_TD2__RGMII_TD2             0x2cc 0x6b4 0x000 0x1 0x0
+#define MX6DL_PAD_RGMII_TD2__GPIO6_IO22            0x2cc 0x6b4 0x000 0x5 0x0
+#define MX6DL_PAD_RGMII_TD3__HSI_RX_WAKE           0x2d0 0x6b8 0x000 0x0 0x0
+#define MX6DL_PAD_RGMII_TD3__RGMII_TD3             0x2d0 0x6b8 0x000 0x1 0x0
+#define MX6DL_PAD_RGMII_TD3__GPIO6_IO23            0x2d0 0x6b8 0x000 0x5 0x0
+#define MX6DL_PAD_RGMII_TX_CTL__USB_H2_STROBE      0x2d4 0x6bc 0x000 0x0 0x0
+#define MX6DL_PAD_RGMII_TX_CTL__RGMII_TX_CTL       0x2d4 0x6bc 0x000 0x1 0x0
+#define MX6DL_PAD_RGMII_TX_CTL__GPIO6_IO26         0x2d4 0x6bc 0x000 0x5 0x0
+#define MX6DL_PAD_RGMII_TX_CTL__ENET_REF_CLK       0x2d4 0x6bc 0x80c 0x7 0x1
+#define MX6DL_PAD_RGMII_TXC__USB_H2_DATA           0x2d8 0x6c0 0x000 0x0 0x0
+#define MX6DL_PAD_RGMII_TXC__RGMII_TXC             0x2d8 0x6c0 0x000 0x1 0x0
+#define MX6DL_PAD_RGMII_TXC__SPDIF_EXT_CLK         0x2d8 0x6c0 0x8f4 0x2 0x1
+#define MX6DL_PAD_RGMII_TXC__GPIO6_IO19            0x2d8 0x6c0 0x000 0x5 0x0
+#define MX6DL_PAD_RGMII_TXC__XTALOSC_REF_CLK_24M   0x2d8 0x6c0 0x000 0x7 0x0
+#define MX6DL_PAD_SD1_CLK__SD1_CLK                 0x2dc 0x6c4 0x928 0x0 0x1
+#define MX6DL_PAD_SD1_CLK__GPT_CLKIN               0x2dc 0x6c4 0x000 0x3 0x0
+#define MX6DL_PAD_SD1_CLK__GPIO1_IO20              0x2dc 0x6c4 0x000 0x5 0x0
+#define MX6DL_PAD_SD1_CMD__SD1_CMD                 0x2e0 0x6c8 0x000 0x0 0x0
+#define MX6DL_PAD_SD1_CMD__PWM4_OUT                0x2e0 0x6c8 0x000 0x2 0x0
+#define MX6DL_PAD_SD1_CMD__GPT_COMPARE1            0x2e0 0x6c8 0x000 0x3 0x0
+#define MX6DL_PAD_SD1_CMD__GPIO1_IO18              0x2e0 0x6c8 0x000 0x5 0x0
+#define MX6DL_PAD_SD1_DAT0__SD1_DATA0              0x2e4 0x6cc 0x000 0x0 0x0
+#define MX6DL_PAD_SD1_DAT0__GPT_CAPTURE1           0x2e4 0x6cc 0x000 0x3 0x0
+#define MX6DL_PAD_SD1_DAT0__GPIO1_IO16             0x2e4 0x6cc 0x000 0x5 0x0
+#define MX6DL_PAD_SD1_DAT1__SD1_DATA1              0x2e8 0x6d0 0x000 0x0 0x0
+#define MX6DL_PAD_SD1_DAT1__PWM3_OUT               0x2e8 0x6d0 0x000 0x2 0x0
+#define MX6DL_PAD_SD1_DAT1__GPT_CAPTURE2           0x2e8 0x6d0 0x000 0x3 0x0
+#define MX6DL_PAD_SD1_DAT1__GPIO1_IO17             0x2e8 0x6d0 0x000 0x5 0x0
+#define MX6DL_PAD_SD1_DAT2__SD1_DATA2              0x2ec 0x6d4 0x000 0x0 0x0
+#define MX6DL_PAD_SD1_DAT2__GPT_COMPARE2           0x2ec 0x6d4 0x000 0x2 0x0
+#define MX6DL_PAD_SD1_DAT2__PWM2_OUT               0x2ec 0x6d4 0x000 0x3 0x0
+#define MX6DL_PAD_SD1_DAT2__WDOG1_B                0x2ec 0x6d4 0x000 0x4 0x0
+#define MX6DL_PAD_SD1_DAT2__GPIO1_IO19             0x2ec 0x6d4 0x000 0x5 0x0
+#define MX6DL_PAD_SD1_DAT2__WDOG1_RESET_B_DEB      0x2ec 0x6d4 0x000 0x6 0x0
+#define MX6DL_PAD_SD1_DAT3__SD1_DATA3              0x2f0 0x6d8 0x000 0x0 0x0
+#define MX6DL_PAD_SD1_DAT3__GPT_COMPARE3           0x2f0 0x6d8 0x000 0x2 0x0
+#define MX6DL_PAD_SD1_DAT3__PWM1_OUT               0x2f0 0x6d8 0x000 0x3 0x0
+#define MX6DL_PAD_SD1_DAT3__WDOG2_B                0x2f0 0x6d8 0x000 0x4 0x0
+#define MX6DL_PAD_SD1_DAT3__GPIO1_IO21             0x2f0 0x6d8 0x000 0x5 0x0
+#define MX6DL_PAD_SD1_DAT3__WDOG2_RESET_B_DEB      0x2f0 0x6d8 0x000 0x6 0x0
+#define MX6DL_PAD_SD2_CLK__SD2_CLK                 0x2f4 0x6dc 0x930 0x0 0x1
+#define MX6DL_PAD_SD2_CLK__KEY_COL5                0x2f4 0x6dc 0x8c0 0x2 0x3
+#define MX6DL_PAD_SD2_CLK__AUD4_RXFS               0x2f4 0x6dc 0x7a4 0x3 0x1
+#define MX6DL_PAD_SD2_CLK__GPIO1_IO10              0x2f4 0x6dc 0x000 0x5 0x0
+#define MX6DL_PAD_SD2_CMD__SD2_CMD                 0x2f8 0x6e0 0x000 0x0 0x0
+#define MX6DL_PAD_SD2_CMD__KEY_ROW5                0x2f8 0x6e0 0x8cc 0x2 0x2
+#define MX6DL_PAD_SD2_CMD__AUD4_RXC                0x2f8 0x6e0 0x7a0 0x3 0x1
+#define MX6DL_PAD_SD2_CMD__GPIO1_IO11              0x2f8 0x6e0 0x000 0x5 0x0
+#define MX6DL_PAD_SD2_DAT0__SD2_DATA0              0x2fc 0x6e4 0x000 0x0 0x0
+#define MX6DL_PAD_SD2_DAT0__AUD4_RXD               0x2fc 0x6e4 0x798 0x3 0x1
+#define MX6DL_PAD_SD2_DAT0__KEY_ROW7               0x2fc 0x6e4 0x8d4 0x4 0x2
+#define MX6DL_PAD_SD2_DAT0__GPIO1_IO15             0x2fc 0x6e4 0x000 0x5 0x0
+#define MX6DL_PAD_SD2_DAT0__DCIC2_OUT              0x2fc 0x6e4 0x000 0x6 0x0
+#define MX6DL_PAD_SD2_DAT1__SD2_DATA1              0x300 0x6e8 0x000 0x0 0x0
+#define MX6DL_PAD_SD2_DAT1__EIM_CS2_B              0x300 0x6e8 0x000 0x2 0x0
+#define MX6DL_PAD_SD2_DAT1__AUD4_TXFS              0x300 0x6e8 0x7ac 0x3 0x1
+#define MX6DL_PAD_SD2_DAT1__KEY_COL7               0x300 0x6e8 0x8c8 0x4 0x2
+#define MX6DL_PAD_SD2_DAT1__GPIO1_IO14             0x300 0x6e8 0x000 0x5 0x0
+#define MX6DL_PAD_SD2_DAT2__SD2_DATA2              0x304 0x6ec 0x000 0x0 0x0
+#define MX6DL_PAD_SD2_DAT2__EIM_CS3_B              0x304 0x6ec 0x000 0x2 0x0
+#define MX6DL_PAD_SD2_DAT2__AUD4_TXD               0x304 0x6ec 0x79c 0x3 0x1
+#define MX6DL_PAD_SD2_DAT2__KEY_ROW6               0x304 0x6ec 0x8d0 0x4 0x2
+#define MX6DL_PAD_SD2_DAT2__GPIO1_IO13             0x304 0x6ec 0x000 0x5 0x0
+#define MX6DL_PAD_SD2_DAT3__SD2_DATA3              0x308 0x6f0 0x000 0x0 0x0
+#define MX6DL_PAD_SD2_DAT3__KEY_COL6               0x308 0x6f0 0x8c4 0x2 0x2
+#define MX6DL_PAD_SD2_DAT3__AUD4_TXC               0x308 0x6f0 0x7a8 0x3 0x1
+#define MX6DL_PAD_SD2_DAT3__GPIO1_IO12             0x308 0x6f0 0x000 0x5 0x0
+#define MX6DL_PAD_SD3_CLK__SD3_CLK                 0x30c 0x6f4 0x934 0x0 0x1
+#define MX6DL_PAD_SD3_CLK__UART2_RTS_B             0x30c 0x6f4 0x900 0x1 0x2
+#define MX6DL_PAD_SD3_CLK__UART2_CTS_B             0x30c 0x6f4 0x000 0x1 0x0
+#define MX6DL_PAD_SD3_CLK__FLEXCAN1_RX             0x30c 0x6f4 0x7c8 0x2 0x2
+#define MX6DL_PAD_SD3_CLK__GPIO7_IO03              0x30c 0x6f4 0x000 0x5 0x0
+#define MX6DL_PAD_SD3_CMD__SD3_CMD                 0x310 0x6f8 0x000 0x0 0x0
+#define MX6DL_PAD_SD3_CMD__UART2_CTS_B             0x310 0x6f8 0x000 0x1 0x0
+#define MX6DL_PAD_SD3_CMD__UART2_RTS_B             0x310 0x6f8 0x900 0x1 0x3
+#define MX6DL_PAD_SD3_CMD__FLEXCAN1_TX             0x310 0x6f8 0x000 0x2 0x0
+#define MX6DL_PAD_SD3_CMD__GPIO7_IO02              0x310 0x6f8 0x000 0x5 0x0
+#define MX6DL_PAD_SD3_DAT0__SD3_DATA0              0x314 0x6fc 0x000 0x0 0x0
+#define MX6DL_PAD_SD3_DAT0__UART1_CTS_B            0x314 0x6fc 0x000 0x1 0x0
+#define MX6DL_PAD_SD3_DAT0__UART1_RTS_B            0x314 0x6fc 0x8f8 0x1 0x2
+#define MX6DL_PAD_SD3_DAT0__FLEXCAN2_TX            0x314 0x6fc 0x000 0x2 0x0
+#define MX6DL_PAD_SD3_DAT0__GPIO7_IO04             0x314 0x6fc 0x000 0x5 0x0
+#define MX6DL_PAD_SD3_DAT1__SD3_DATA1              0x318 0x700 0x000 0x0 0x0
+#define MX6DL_PAD_SD3_DAT1__UART1_RTS_B            0x318 0x700 0x8f8 0x1 0x3
+#define MX6DL_PAD_SD3_DAT1__UART1_CTS_B            0x318 0x700 0x000 0x1 0x0
+#define MX6DL_PAD_SD3_DAT1__FLEXCAN2_RX            0x318 0x700 0x7cc 0x2 0x1
+#define MX6DL_PAD_SD3_DAT1__GPIO7_IO05             0x318 0x700 0x000 0x5 0x0
+#define MX6DL_PAD_SD3_DAT2__SD3_DATA2              0x31c 0x704 0x000 0x0 0x0
+#define MX6DL_PAD_SD3_DAT2__GPIO7_IO06             0x31c 0x704 0x000 0x5 0x0
+#define MX6DL_PAD_SD3_DAT3__SD3_DATA3              0x320 0x708 0x000 0x0 0x0
+#define MX6DL_PAD_SD3_DAT3__UART3_CTS_B            0x320 0x708 0x000 0x1 0x0
+#define MX6DL_PAD_SD3_DAT3__UART3_RTS_B            0x320 0x708 0x908 0x1 0x4
+#define MX6DL_PAD_SD3_DAT3__GPIO7_IO07             0x320 0x708 0x000 0x5 0x0
+#define MX6DL_PAD_SD3_DAT4__SD3_DATA4              0x324 0x70c 0x000 0x0 0x0
+#define MX6DL_PAD_SD3_DAT4__UART2_RX_DATA          0x324 0x70c 0x904 0x1 0x4
+#define MX6DL_PAD_SD3_DAT4__UART2_TX_DATA          0x324 0x70c 0x000 0x1 0x0
+#define MX6DL_PAD_SD3_DAT4__GPIO7_IO01             0x324 0x70c 0x000 0x5 0x0
+#define MX6DL_PAD_SD3_DAT5__SD3_DATA5              0x328 0x710 0x000 0x0 0x0
+#define MX6DL_PAD_SD3_DAT5__UART2_TX_DATA          0x328 0x710 0x000 0x1 0x0
+#define MX6DL_PAD_SD3_DAT5__UART2_RX_DATA          0x328 0x710 0x904 0x1 0x5
+#define MX6DL_PAD_SD3_DAT5__GPIO7_IO00             0x328 0x710 0x000 0x5 0x0
+#define MX6DL_PAD_SD3_DAT6__SD3_DATA6              0x32c 0x714 0x000 0x0 0x0
+#define MX6DL_PAD_SD3_DAT6__UART1_RX_DATA          0x32c 0x714 0x8fc 0x1 0x2
+#define MX6DL_PAD_SD3_DAT6__UART1_TX_DATA          0x32c 0x714 0x000 0x1 0x0
+#define MX6DL_PAD_SD3_DAT6__GPIO6_IO18             0x32c 0x714 0x000 0x5 0x0
+#define MX6DL_PAD_SD3_DAT7__SD3_DATA7              0x330 0x718 0x000 0x0 0x0
+#define MX6DL_PAD_SD3_DAT7__UART1_TX_DATA          0x330 0x718 0x000 0x1 0x0
+#define MX6DL_PAD_SD3_DAT7__UART1_RX_DATA          0x330 0x718 0x8fc 0x1 0x3
+#define MX6DL_PAD_SD3_DAT7__GPIO6_IO17             0x330 0x718 0x000 0x5 0x0
+#define MX6DL_PAD_SD3_RST__SD3_RESET               0x334 0x71c 0x000 0x0 0x0
+#define MX6DL_PAD_SD3_RST__UART3_RTS_B             0x334 0x71c 0x908 0x1 0x5
+#define MX6DL_PAD_SD3_RST__UART3_CTS_B             0x334 0x71c 0x000 0x1 0x0
+#define MX6DL_PAD_SD3_RST__GPIO7_IO08              0x334 0x71c 0x000 0x5 0x0
+#define MX6DL_PAD_SD4_CLK__SD4_CLK                 0x338 0x720 0x938 0x0 0x1
+#define MX6DL_PAD_SD4_CLK__NAND_WE_B               0x338 0x720 0x000 0x1 0x0
+#define MX6DL_PAD_SD4_CLK__UART3_RX_DATA           0x338 0x720 0x90c 0x2 0x2
+#define MX6DL_PAD_SD4_CLK__UART3_TX_DATA           0x338 0x720 0x000 0x2 0x0
+#define MX6DL_PAD_SD4_CLK__GPIO7_IO10              0x338 0x720 0x000 0x5 0x0
+#define MX6DL_PAD_SD4_CMD__SD4_CMD                 0x33c 0x724 0x000 0x0 0x0
+#define MX6DL_PAD_SD4_CMD__NAND_RE_B               0x33c 0x724 0x000 0x1 0x0
+#define MX6DL_PAD_SD4_CMD__UART3_TX_DATA           0x33c 0x724 0x000 0x2 0x0
+#define MX6DL_PAD_SD4_CMD__UART3_RX_DATA           0x33c 0x724 0x90c 0x2 0x3
+#define MX6DL_PAD_SD4_CMD__GPIO7_IO09              0x33c 0x724 0x000 0x5 0x0
+#define MX6DL_PAD_SD4_DAT0__SD4_DATA0              0x340 0x728 0x000 0x1 0x0
+#define MX6DL_PAD_SD4_DAT0__NAND_DQS               0x340 0x728 0x000 0x2 0x0
+#define MX6DL_PAD_SD4_DAT0__GPIO2_IO08             0x340 0x728 0x000 0x5 0x0
+#define MX6DL_PAD_SD4_DAT1__SD4_DATA1              0x344 0x72c 0x000 0x1 0x0
+#define MX6DL_PAD_SD4_DAT1__PWM3_OUT               0x344 0x72c 0x000 0x2 0x0
+#define MX6DL_PAD_SD4_DAT1__GPIO2_IO09             0x344 0x72c 0x000 0x5 0x0
+#define MX6DL_PAD_SD4_DAT2__SD4_DATA2              0x348 0x730 0x000 0x1 0x0
+#define MX6DL_PAD_SD4_DAT2__PWM4_OUT               0x348 0x730 0x000 0x2 0x0
+#define MX6DL_PAD_SD4_DAT2__GPIO2_IO10             0x348 0x730 0x000 0x5 0x0
+#define MX6DL_PAD_SD4_DAT3__SD4_DATA3              0x34c 0x734 0x000 0x1 0x0
+#define MX6DL_PAD_SD4_DAT3__GPIO2_IO11             0x34c 0x734 0x000 0x5 0x0
+#define MX6DL_PAD_SD4_DAT4__SD4_DATA4              0x350 0x738 0x000 0x1 0x0
+#define MX6DL_PAD_SD4_DAT4__UART2_RX_DATA          0x350 0x738 0x904 0x2 0x6
+#define MX6DL_PAD_SD4_DAT4__UART2_TX_DATA          0x350 0x738 0x000 0x2 0x0
+#define MX6DL_PAD_SD4_DAT4__GPIO2_IO12             0x350 0x738 0x000 0x5 0x0
+#define MX6DL_PAD_SD4_DAT5__SD4_DATA5              0x354 0x73c 0x000 0x1 0x0
+#define MX6DL_PAD_SD4_DAT5__UART2_RTS_B            0x354 0x73c 0x900 0x2 0x4
+#define MX6DL_PAD_SD4_DAT5__UART2_CTS_B            0x354 0x73c 0x000 0x2 0x0
+#define MX6DL_PAD_SD4_DAT5__GPIO2_IO13             0x354 0x73c 0x000 0x5 0x0
+#define MX6DL_PAD_SD4_DAT6__SD4_DATA6              0x358 0x740 0x000 0x1 0x0
+#define MX6DL_PAD_SD4_DAT6__UART2_CTS_B            0x358 0x740 0x000 0x2 0x0
+#define MX6DL_PAD_SD4_DAT6__UART2_RTS_B            0x358 0x740 0x900 0x2 0x5
+#define MX6DL_PAD_SD4_DAT6__GPIO2_IO14             0x358 0x740 0x000 0x5 0x0
+#define MX6DL_PAD_SD4_DAT7__SD4_DATA7              0x35c 0x744 0x000 0x1 0x0
+#define MX6DL_PAD_SD4_DAT7__UART2_TX_DATA          0x35c 0x744 0x000 0x2 0x0
+#define MX6DL_PAD_SD4_DAT7__UART2_RX_DATA          0x35c 0x744 0x904 0x2 0x7
+#define MX6DL_PAD_SD4_DAT7__GPIO2_IO15             0x35c 0x744 0x000 0x5 0x0
+
+#endif /* __DTS_IMX6DL_PINFUNC_H */
diff --git a/arch/arm/boot/dts/imx6dl-sabreauto.dtsp b/arch/arm/boot/dts/imx6dl-sabreauto.dtsp
new file mode 100644
index 0000000..53033be
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dl-sabreauto.dtsp
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2013 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/dts-v1/;
+
+#include "imx6dl.dtsip"
+#include "imx6qdl-sabreauto.dtsip"
+
+/ {
+	model = "Freescale i.MX6 DualLite/Solo SABRE Automotive Board";
+	compatible = "fsl,imx6dl-sabreauto", "fsl,imx6dl";
+};
+
+&iomuxc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hog>;
+
+	hog {
+		pinctrl_hog: hoggrp {
+			fsl,pins = <
+				MX6DL_PAD_NANDF_CS2__GPIO6_IO15 0x80000000
+				MX6DL_PAD_SD2_DAT2__GPIO1_IO13  0x80000000
+			>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/imx6dl-sabresd.dtsp b/arch/arm/boot/dts/imx6dl-sabresd.dtsp
new file mode 100644
index 0000000..77ef55c
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dl-sabresd.dtsp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2013 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/dts-v1/;
+
+#include "imx6dl.dtsip"
+#include "imx6qdl-sabresd.dtsip"
+
+/ {
+	model = "Freescale i.MX6 DualLite SABRE Smart Device Board";
+	compatible = "fsl,imx6dl-sabresd", "fsl,imx6dl";
+};
+
+&iomuxc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hog>;
+
+	hog {
+		pinctrl_hog: hoggrp {
+			fsl,pins = <
+				MX6DL_PAD_GPIO_4__GPIO1_IO04   0x80000000
+				MX6DL_PAD_GPIO_5__GPIO1_IO05   0x80000000
+				MX6DL_PAD_NANDF_D0__GPIO2_IO00 0x80000000
+				MX6DL_PAD_NANDF_D1__GPIO2_IO01 0x80000000
+				MX6DL_PAD_NANDF_D2__GPIO2_IO02 0x80000000
+				MX6DL_PAD_NANDF_D3__GPIO2_IO03 0x80000000
+			>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/imx6dl-wandboard.dtsp b/arch/arm/boot/dts/imx6dl-wandboard.dtsp
new file mode 100644
index 0000000..33556f9
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dl-wandboard.dtsp
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * Author: Fabio Estevam <fabio.estevam@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+/dts-v1/;
+#include "imx6dl.dtsip"
+
+/ {
+	model = "Wandboard i.MX6 Dual Lite Board";
+	compatible = "wand,imx6dl-wandboard", "fsl,imx6dl";
+
+	memory {
+		reg = <0x10000000 0x40000000>;
+	};
+};
+
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet_1>;
+	phy-mode = "rgmii";
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1_1>;
+	status = "okay";
+};
+
+&usdhc3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc3_2>;
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6dl.dtsi b/arch/arm/boot/dts/imx6dl.dtsi
deleted file mode 100644
index 63fafe2..0000000
--- a/arch/arm/boot/dts/imx6dl.dtsi
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2013 Freescale Semiconductor, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-
-/include/ "imx6qdl.dtsi"
-
-/ {
-	cpus {
-		#address-cells = <1>;
-		#size-cells = <0>;
-
-		cpu@0 {
-			compatible = "arm,cortex-a9";
-			reg = <0>;
-			next-level-cache = <&L2>;
-		};
-
-		cpu@1 {
-			compatible = "arm,cortex-a9";
-			reg = <1>;
-			next-level-cache = <&L2>;
-		};
-	};
-
-	soc {
-		aips1: aips-bus@02000000 {
-			pxp: pxp@020f0000 {
-				reg = <0x020f0000 0x4000>;
-				interrupts = <0 98 0x04>;
-			};
-
-			epdc: epdc@020f4000 {
-				reg = <0x020f4000 0x4000>;
-				interrupts = <0 97 0x04>;
-			};
-
-			lcdif: lcdif@020f8000 {
-				reg = <0x020f8000 0x4000>;
-				interrupts = <0 39 0x04>;
-			};
-		};
-
-		aips2: aips-bus@02100000 {
-			i2c4: i2c@021f8000 {
-				#address-cells = <1>;
-				#size-cells = <0>;
-				compatible = "fsl,imx1-i2c";
-				reg = <0x021f8000 0x4000>;
-				interrupts = <0 35 0x04>;
-				status = "disabled";
-			};
-		};
-	};
-};
diff --git a/arch/arm/boot/dts/imx6dl.dtsip b/arch/arm/boot/dts/imx6dl.dtsip
new file mode 100644
index 0000000..83780f5
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dl.dtsip
@@ -0,0 +1,182 @@
+
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include "imx6qdl.dtsip"
+#include "imx6dl-pinfunc.h"
+
+/ {
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			compatible = "arm,cortex-a9";
+			reg = <0>;
+			next-level-cache = <&L2>;
+		};
+
+		cpu@1 {
+			compatible = "arm,cortex-a9";
+			reg = <1>;
+			next-level-cache = <&L2>;
+		};
+	};
+
+	soc {
+		aips1: aips-bus@02000000 {
+			iomuxc: iomuxc@020e0000 {
+				compatible = "fsl,imx6dl-iomuxc";
+				reg = <0x020e0000 0x4000>;
+
+				enet {
+					pinctrl_enet_1: enetgrp-1 {
+						fsl,pins = <
+							MX6DL_PAD_ENET_MDIO__ENET_MDIO       0x1b0b0
+							MX6DL_PAD_ENET_MDC__ENET_MDC         0x1b0b0
+							MX6DL_PAD_RGMII_TXC__RGMII_TXC       0x1b0b0
+							MX6DL_PAD_RGMII_TD0__RGMII_TD0       0x1b0b0
+							MX6DL_PAD_RGMII_TD1__RGMII_TD1       0x1b0b0
+							MX6DL_PAD_RGMII_TD2__RGMII_TD2       0x1b0b0
+							MX6DL_PAD_RGMII_TD3__RGMII_TD3       0x1b0b0
+							MX6DL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0
+							MX6DL_PAD_ENET_REF_CLK__ENET_TX_CLK  0x1b0b0
+							MX6DL_PAD_RGMII_RXC__RGMII_RXC       0x1b0b0
+							MX6DL_PAD_RGMII_RD0__RGMII_RD0       0x1b0b0
+							MX6DL_PAD_RGMII_RD1__RGMII_RD1       0x1b0b0
+							MX6DL_PAD_RGMII_RD2__RGMII_RD2       0x1b0b0
+							MX6DL_PAD_RGMII_RD3__RGMII_RD3       0x1b0b0
+							MX6DL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0
+							MX6DL_PAD_GPIO_16__ENET_REF_CLK      0x4001b0a8
+						>;
+					};
+
+					pinctrl_enet_2: enetgrp-2 {
+						fsl,pins = <
+							MX6DL_PAD_KEY_COL1__ENET_MDIO        0x1b0b0
+							MX6DL_PAD_KEY_COL2__ENET_MDC         0x1b0b0
+							MX6DL_PAD_RGMII_TXC__RGMII_TXC       0x1b0b0
+							MX6DL_PAD_RGMII_TD0__RGMII_TD0       0x1b0b0
+							MX6DL_PAD_RGMII_TD1__RGMII_TD1       0x1b0b0
+							MX6DL_PAD_RGMII_TD2__RGMII_TD2       0x1b0b0
+							MX6DL_PAD_RGMII_TD3__RGMII_TD3       0x1b0b0
+							MX6DL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0
+							MX6DL_PAD_ENET_REF_CLK__ENET_TX_CLK  0x1b0b0
+							MX6DL_PAD_RGMII_RXC__RGMII_RXC       0x1b0b0
+							MX6DL_PAD_RGMII_RD0__RGMII_RD0       0x1b0b0
+							MX6DL_PAD_RGMII_RD1__RGMII_RD1       0x1b0b0
+							MX6DL_PAD_RGMII_RD2__RGMII_RD2       0x1b0b0
+							MX6DL_PAD_RGMII_RD3__RGMII_RD3       0x1b0b0
+							MX6DL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0
+						>;
+					};
+				};
+
+				uart1 {
+					pinctrl_uart1_1: uart1grp-1 {
+						fsl,pins = <
+							MX6DL_PAD_CSI0_DAT10__UART1_TX_DATA 0x1b0b1
+							MX6DL_PAD_CSI0_DAT11__UART1_RX_DATA 0x1b0b1
+						>;
+					};
+				};
+
+				uart4 {
+					pinctrl_uart4_1: uart4grp-1 {
+						fsl,pins = <
+							MX6DL_PAD_KEY_COL0__UART4_TX_DATA 0x1b0b1
+							MX6DL_PAD_KEY_ROW0__UART4_RX_DATA 0x1b0b1
+						>;
+					};
+				};
+
+				usbotg {
+					pinctrl_usbotg_2: usbotggrp-2 {
+						fsl,pins = <
+							MX6DL_PAD_ENET_RX_ER__USB_OTG_ID 0x17059
+						>;
+					};
+				};
+
+				usdhc2 {
+					pinctrl_usdhc2_1: usdhc2grp-1 {
+						fsl,pins = <
+							MX6DL_PAD_SD2_CMD__SD2_CMD    0x17059
+							MX6DL_PAD_SD2_CLK__SD2_CLK    0x10059
+							MX6DL_PAD_SD2_DAT0__SD2_DATA0 0x17059
+							MX6DL_PAD_SD2_DAT1__SD2_DATA1 0x17059
+							MX6DL_PAD_SD2_DAT2__SD2_DATA2 0x17059
+							MX6DL_PAD_SD2_DAT3__SD2_DATA3 0x17059
+							MX6DL_PAD_NANDF_D4__SD2_DATA4 0x17059
+							MX6DL_PAD_NANDF_D5__SD2_DATA5 0x17059
+							MX6DL_PAD_NANDF_D6__SD2_DATA6 0x17059
+							MX6DL_PAD_NANDF_D7__SD2_DATA7 0x17059
+						>;
+					};
+				};
+
+				usdhc3 {
+					pinctrl_usdhc3_1: usdhc3grp-1 {
+						fsl,pins = <
+							MX6DL_PAD_SD3_CMD__SD3_CMD    0x17059
+							MX6DL_PAD_SD3_CLK__SD3_CLK    0x10059
+							MX6DL_PAD_SD3_DAT0__SD3_DATA0 0x17059
+							MX6DL_PAD_SD3_DAT1__SD3_DATA1 0x17059
+							MX6DL_PAD_SD3_DAT2__SD3_DATA2 0x17059
+							MX6DL_PAD_SD3_DAT3__SD3_DATA3 0x17059
+							MX6DL_PAD_SD3_DAT4__SD3_DATA4 0x17059
+							MX6DL_PAD_SD3_DAT5__SD3_DATA5 0x17059
+							MX6DL_PAD_SD3_DAT6__SD3_DATA6 0x17059
+							MX6DL_PAD_SD3_DAT7__SD3_DATA7 0x17059
+						>;
+					};
+
+					pinctrl_usdhc3_2: usdhc3grp_2 {
+						fsl,pins = <
+							MX6DL_PAD_SD3_CMD__SD3_CMD    0x17059
+							MX6DL_PAD_SD3_CLK__SD3_CLK    0x10059
+							MX6DL_PAD_SD3_DAT0__SD3_DATA0 0x17059
+							MX6DL_PAD_SD3_DAT1__SD3_DATA1 0x17059
+							MX6DL_PAD_SD3_DAT2__SD3_DATA2 0x17059
+							MX6DL_PAD_SD3_DAT3__SD3_DATA3 0x17059
+						>;
+					};
+				};
+
+
+			};
+
+			pxp: pxp@020f0000 {
+				reg = <0x020f0000 0x4000>;
+				interrupts = <0 98 0x04>;
+			};
+
+			epdc: epdc@020f4000 {
+				reg = <0x020f4000 0x4000>;
+				interrupts = <0 97 0x04>;
+			};
+
+			lcdif: lcdif@020f8000 {
+				reg = <0x020f8000 0x4000>;
+				interrupts = <0 39 0x04>;
+			};
+		};
+
+		aips2: aips-bus@02100000 {
+			i2c4: i2c@021f8000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx1-i2c";
+				reg = <0x021f8000 0x4000>;
+				interrupts = <0 35 0x04>;
+				status = "disabled";
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/imx6q-arm2.dts b/arch/arm/boot/dts/imx6q-arm2.dts
deleted file mode 100644
index 53eb241..0000000
--- a/arch/arm/boot/dts/imx6q-arm2.dts
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright 2011 Freescale Semiconductor, Inc.
- * Copyright 2011 Linaro Ltd.
- *
- * 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
- */
-
-/dts-v1/;
-/include/ "imx6q.dtsi"
-
-/ {
-	model = "Freescale i.MX6 Quad Armadillo2 Board";
-	compatible = "fsl,imx6q-arm2", "fsl,imx6q";
-
-	memory {
-		reg = <0x10000000 0x80000000>;
-	};
-
-	regulators {
-		compatible = "simple-bus";
-
-		reg_3p3v: 3p3v {
-			compatible = "regulator-fixed";
-			regulator-name = "3P3V";
-			regulator-min-microvolt = <3300000>;
-			regulator-max-microvolt = <3300000>;
-			regulator-always-on;
-		};
-	};
-
-	leds {
-		compatible = "gpio-leds";
-
-		debug-led {
-			label = "Heartbeat";
-			gpios = <&gpio3 25 0>;
-			linux,default-trigger = "heartbeat";
-		};
-	};
-};
-
-&gpmi {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_gpmi_nand_1>;
-	status = "disabled"; /* gpmi nand conflicts with SD */
-};
-
-&iomuxc {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_hog>;
-
-	hog {
-		pinctrl_hog: hoggrp {
-			fsl,pins = <
-				176  0x80000000	/* MX6Q_PAD_EIM_D25__GPIO_3_25 */
-			>;
-		};
-	};
-
-	arm2 {
-		pinctrl_usdhc3_arm2: usdhc3grp-arm2 {
-			fsl,pins = <
-				1363 0x80000000	/* MX6Q_PAD_NANDF_CS0__GPIO_6_11 */
-				1369 0x80000000 /* MX6Q_PAD_NANDF_CS1__GPIO_6_14 */
-			>;
-		};
-	};
-};
-
-&fec {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_enet_2>;
-	phy-mode = "rgmii";
-	status = "okay";
-};
-
-&usdhc3 {
-	cd-gpios = <&gpio6 11 0>;
-	wp-gpios = <&gpio6 14 0>;
-	vmmc-supply = <&reg_3p3v>;
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_usdhc3_1
-		     &pinctrl_usdhc3_arm2>;
-	status = "okay";
-};
-
-&usdhc4 {
-	non-removable;
-	vmmc-supply = <&reg_3p3v>;
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_usdhc4_1>;
-	status = "okay";
-};
-
-&uart4 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart4_1>;
-	status = "okay";
-};
diff --git a/arch/arm/boot/dts/imx6q-arm2.dtsp b/arch/arm/boot/dts/imx6q-arm2.dtsp
new file mode 100644
index 0000000..52319b6
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-arm2.dtsp
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * 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
+ */
+
+/dts-v1/;
+#include "imx6q.dtsip"
+
+/ {
+	model = "Freescale i.MX6 Quad Armadillo2 Board";
+	compatible = "fsl,imx6q-arm2", "fsl,imx6q";
+
+	memory {
+		reg = <0x10000000 0x80000000>;
+	};
+
+	regulators {
+		compatible = "simple-bus";
+
+		reg_3p3v: 3p3v {
+			compatible = "regulator-fixed";
+			regulator-name = "3P3V";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		debug-led {
+			label = "Heartbeat";
+			gpios = <&gpio3 25 0>;
+			linux,default-trigger = "heartbeat";
+		};
+	};
+};
+
+&gpmi {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_gpmi_nand_1>;
+	status = "disabled"; /* gpmi nand conflicts with SD */
+};
+
+&iomuxc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hog>;
+
+	hog {
+		pinctrl_hog: hoggrp {
+			fsl,pins = <
+				MX6Q_PAD_EIM_D25__GPIO_3_25 0x80000000
+			>;
+		};
+	};
+
+	arm2 {
+		pinctrl_usdhc3_arm2: usdhc3grp-arm2 {
+			fsl,pins = <
+				MX6Q_PAD_NANDF_CS0__GPIO_6_11 0x80000000
+				MX6Q_PAD_NANDF_CS1__GPIO_6_14 0x80000000
+			>;
+		};
+	};
+};
+
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet_2>;
+	phy-mode = "rgmii";
+	status = "okay";
+};
+
+&usdhc3 {
+	cd-gpios = <&gpio6 11 0>;
+	wp-gpios = <&gpio6 14 0>;
+	vmmc-supply = <&reg_3p3v>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc3_1
+		     &pinctrl_usdhc3_arm2>;
+	status = "okay";
+};
+
+&usdhc4 {
+	non-removable;
+	vmmc-supply = <&reg_3p3v>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc4_1>;
+	status = "okay";
+};
+
+&uart4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart4_1>;
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6q-pinfunc.h b/arch/arm/boot/dts/imx6q-pinfunc.h
new file mode 100644
index 0000000..133db55
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-pinfunc.h
@@ -0,0 +1,1529 @@
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef __DTS_IMX6Q_PINFUNC_H
+#define __DTS_IMX6Q_PINFUNC_H
+
+/*
+ * The pin function ID is a tuple of
+ * <mux_reg conf_reg input_reg mux_mode input_val>
+ */
+#define MX6Q_PAD_SD2_DAT1__USDHC2_DAT1			0x04c 0x360 0x000 0x0 0x0
+#define MX6Q_PAD_SD2_DAT1__ECSPI5_SS0			0x04c 0x360 0x834 0x1 0x0
+#define MX6Q_PAD_SD2_DAT1__WEIM_WEIM_CS_2		0x04c 0x360 0x000 0x2 0x0
+#define MX6Q_PAD_SD2_DAT1__AUDMUX_AUD4_TXFS		0x04c 0x360 0x7c8 0x3 0x0
+#define MX6Q_PAD_SD2_DAT1__KPP_COL_7			0x04c 0x360 0x8f0 0x4 0x0
+#define MX6Q_PAD_SD2_DAT1__GPIO_1_14			0x04c 0x360 0x000 0x5 0x0
+#define MX6Q_PAD_SD2_DAT1__CCM_WAIT			0x04c 0x360 0x000 0x6 0x0
+#define MX6Q_PAD_SD2_DAT1__ANATOP_TESTO_0		0x04c 0x360 0x000 0x7 0x0
+#define MX6Q_PAD_SD2_DAT2__USDHC2_DAT2			0x050 0x364 0x000 0x0 0x0
+#define MX6Q_PAD_SD2_DAT2__ECSPI5_SS1			0x050 0x364 0x838 0x1 0x0
+#define MX6Q_PAD_SD2_DAT2__WEIM_WEIM_CS_3		0x050 0x364 0x000 0x2 0x0
+#define MX6Q_PAD_SD2_DAT2__AUDMUX_AUD4_TXD		0x050 0x364 0x7b8 0x3 0x0
+#define MX6Q_PAD_SD2_DAT2__KPP_ROW_6			0x050 0x364 0x8f8 0x4 0x0
+#define MX6Q_PAD_SD2_DAT2__GPIO_1_13			0x050 0x364 0x000 0x5 0x0
+#define MX6Q_PAD_SD2_DAT2__CCM_STOP			0x050 0x364 0x000 0x6 0x0
+#define MX6Q_PAD_SD2_DAT2__ANATOP_TESTO_1		0x050 0x364 0x000 0x7 0x0
+#define MX6Q_PAD_SD2_DAT0__USDHC2_DAT0			0x054 0x368 0x000 0x0 0x0
+#define MX6Q_PAD_SD2_DAT0__ECSPI5_MISO			0x054 0x368 0x82c 0x1 0x0
+#define MX6Q_PAD_SD2_DAT0__AUDMUX_AUD4_RXD		0x054 0x368 0x7b4 0x3 0x0
+#define MX6Q_PAD_SD2_DAT0__KPP_ROW_7			0x054 0x368 0x8fc 0x4 0x0
+#define MX6Q_PAD_SD2_DAT0__GPIO_1_15			0x054 0x368 0x000 0x5 0x0
+#define MX6Q_PAD_SD2_DAT0__DCIC2_DCIC_OUT		0x054 0x368 0x000 0x6 0x0
+#define MX6Q_PAD_SD2_DAT0__TESTO_2			0x054 0x368 0x000 0x7 0x0
+#define MX6Q_PAD_RGMII_TXC__USBOH3_H2_DATA		0x058 0x36c 0x000 0x0 0x0
+#define MX6Q_PAD_RGMII_TXC__ENET_RGMII_TXC		0x058 0x36c 0x000 0x1 0x0
+#define MX6Q_PAD_RGMII_TXC__SPDIF_SPDIF_EXTCLK		0x058 0x36c 0x918 0x2 0x0
+#define MX6Q_PAD_RGMII_TXC__GPIO_6_19			0x058 0x36c 0x000 0x5 0x0
+#define MX6Q_PAD_RGMII_TXC__MIPI_CORE_DPHY_IN_0		0x058 0x36c 0x000 0x6 0x0
+#define MX6Q_PAD_RGMII_TXC__ANATOP_24M_OUT		0x058 0x36c 0x000 0x7 0x0
+#define MX6Q_PAD_RGMII_TD0__MIPI_HSI_CRL_TX_RDY		0x05c 0x370 0x000 0x0 0x0
+#define MX6Q_PAD_RGMII_TD0__ENET_RGMII_TD0		0x05c 0x370 0x000 0x1 0x0
+#define MX6Q_PAD_RGMII_TD0__GPIO_6_20			0x05c 0x370 0x000 0x5 0x0
+#define MX6Q_PAD_RGMII_TD0__MIPI_CORE_DPHY_IN_1		0x05c 0x370 0x000 0x6 0x0
+#define MX6Q_PAD_RGMII_TD1__MIPI_HSI_CRL_RX_FLG		0x060 0x374 0x000 0x0 0x0
+#define MX6Q_PAD_RGMII_TD1__ENET_RGMII_TD1		0x060 0x374 0x000 0x1 0x0
+#define MX6Q_PAD_RGMII_TD1__GPIO_6_21			0x060 0x374 0x000 0x5 0x0
+#define MX6Q_PAD_RGMII_TD1__MIPI_CORE_DPHY_IN_2		0x060 0x374 0x000 0x6 0x0
+#define MX6Q_PAD_RGMII_TD1__CCM_PLL3_BYP		0x060 0x374 0x000 0x7 0x0
+#define MX6Q_PAD_RGMII_TD2__MIPI_HSI_CRL_RX_DTA		0x064 0x378 0x000 0x0 0x0
+#define MX6Q_PAD_RGMII_TD2__ENET_RGMII_TD2		0x064 0x378 0x000 0x1 0x0
+#define MX6Q_PAD_RGMII_TD2__GPIO_6_22			0x064 0x378 0x000 0x5 0x0
+#define MX6Q_PAD_RGMII_TD2__MIPI_CORE_DPHY_IN_3		0x064 0x378 0x000 0x6 0x0
+#define MX6Q_PAD_RGMII_TD2__CCM_PLL2_BYP		0x064 0x378 0x000 0x7 0x0
+#define MX6Q_PAD_RGMII_TD3__MIPI_HSI_CRL_RX_WAK		0x068 0x37c 0x000 0x0 0x0
+#define MX6Q_PAD_RGMII_TD3__ENET_RGMII_TD3		0x068 0x37c 0x000 0x1 0x0
+#define MX6Q_PAD_RGMII_TD3__GPIO_6_23			0x068 0x37c 0x000 0x5 0x0
+#define MX6Q_PAD_RGMII_TD3__MIPI_CORE_DPHY_IN_4		0x068 0x37c 0x000 0x6 0x0
+#define MX6Q_PAD_RGMII_RX_CTL__USBOH3_H3_DATA		0x06c 0x380 0x000 0x0 0x0
+#define MX6Q_PAD_RGMII_RX_CTL__RGMII_RX_CTL		0x06c 0x380 0x858 0x1 0x0
+#define MX6Q_PAD_RGMII_RX_CTL__GPIO_6_24		0x06c 0x380 0x000 0x5 0x0
+#define MX6Q_PAD_RGMII_RX_CTL__MIPI_DPHY_IN_5		0x06c 0x380 0x000 0x6 0x0
+#define MX6Q_PAD_RGMII_RD0__MIPI_HSI_CRL_RX_RDY		0x070 0x384 0x000 0x0 0x0
+#define MX6Q_PAD_RGMII_RD0__ENET_RGMII_RD0		0x070 0x384 0x848 0x1 0x0
+#define MX6Q_PAD_RGMII_RD0__GPIO_6_25			0x070 0x384 0x000 0x5 0x0
+#define MX6Q_PAD_RGMII_RD0__MIPI_CORE_DPHY_IN_6		0x070 0x384 0x000 0x6 0x0
+#define MX6Q_PAD_RGMII_TX_CTL__USBOH3_H2_STROBE		0x074 0x388 0x000 0x0 0x0
+#define MX6Q_PAD_RGMII_TX_CTL__RGMII_TX_CTL		0x074 0x388 0x000 0x1 0x0
+#define MX6Q_PAD_RGMII_TX_CTL__GPIO_6_26		0x074 0x388 0x000 0x5 0x0
+#define MX6Q_PAD_RGMII_TX_CTL__CORE_DPHY_IN_7		0x074 0x388 0x000 0x6 0x0
+#define MX6Q_PAD_RGMII_TX_CTL__ANATOP_REF_OUT		0x074 0x388 0x83c 0x7 0x0
+#define MX6Q_PAD_RGMII_RD1__MIPI_HSI_CTRL_TX_FL		0x078 0x38c 0x000 0x0 0x0
+#define MX6Q_PAD_RGMII_RD1__ENET_RGMII_RD1		0x078 0x38c 0x84c 0x1 0x0
+#define MX6Q_PAD_RGMII_RD1__GPIO_6_27			0x078 0x38c 0x000 0x5 0x0
+#define MX6Q_PAD_RGMII_RD1__CORE_DPHY_TEST_IN_8		0x078 0x38c 0x000 0x6 0x0
+#define MX6Q_PAD_RGMII_RD1__SJC_FAIL			0x078 0x38c 0x000 0x7 0x0
+#define MX6Q_PAD_RGMII_RD2__MIPI_HSI_CRL_TX_DTA		0x07c 0x390 0x000 0x0 0x0
+#define MX6Q_PAD_RGMII_RD2__ENET_RGMII_RD2		0x07c 0x390 0x850 0x1 0x0
+#define MX6Q_PAD_RGMII_RD2__GPIO_6_28			0x07c 0x390 0x000 0x5 0x0
+#define MX6Q_PAD_RGMII_RD2__MIPI_CORE_DPHY_IN_9		0x07c 0x390 0x000 0x6 0x0
+#define MX6Q_PAD_RGMII_RD3__MIPI_HSI_CRL_TX_WAK		0x080 0x394 0x000 0x0 0x0
+#define MX6Q_PAD_RGMII_RD3__ENET_RGMII_RD3		0x080 0x394 0x854 0x1 0x0
+#define MX6Q_PAD_RGMII_RD3__GPIO_6_29			0x080 0x394 0x000 0x5 0x0
+#define MX6Q_PAD_RGMII_RD3__MIPI_CORE_DPHY_IN10		0x080 0x394 0x000 0x6 0x0
+#define MX6Q_PAD_RGMII_RXC__USBOH3_H3_STROBE		0x084 0x398 0x000 0x0 0x0
+#define MX6Q_PAD_RGMII_RXC__ENET_RGMII_RXC		0x084 0x398 0x844 0x1 0x0
+#define MX6Q_PAD_RGMII_RXC__GPIO_6_30			0x084 0x398 0x000 0x5 0x0
+#define MX6Q_PAD_RGMII_RXC__MIPI_CORE_DPHY_IN11		0x084 0x398 0x000 0x6 0x0
+#define MX6Q_PAD_EIM_A25__WEIM_WEIM_A_25		0x088 0x39c 0x000 0x0 0x0
+#define MX6Q_PAD_EIM_A25__ECSPI4_SS1			0x088 0x39c 0x000 0x1 0x0
+#define MX6Q_PAD_EIM_A25__ECSPI2_RDY			0x088 0x39c 0x000 0x2 0x0
+#define MX6Q_PAD_EIM_A25__IPU1_DI1_PIN12		0x088 0x39c 0x000 0x3 0x0
+#define MX6Q_PAD_EIM_A25__IPU1_DI0_D1_CS		0x088 0x39c 0x000 0x4 0x0
+#define MX6Q_PAD_EIM_A25__GPIO_5_2			0x088 0x39c 0x000 0x5 0x0
+#define MX6Q_PAD_EIM_A25__HDMI_TX_CEC_LINE		0x088 0x39c 0x88c 0x6 0x0
+#define MX6Q_PAD_EIM_A25__PL301_PER1_HBURST_0		0x088 0x39c 0x000 0x7 0x0
+#define MX6Q_PAD_EIM_EB2__WEIM_WEIM_EB_2		0x08c 0x3a0 0x000 0x0 0x0
+#define MX6Q_PAD_EIM_EB2__ECSPI1_SS0			0x08c 0x3a0 0x800 0x1 0x0
+#define MX6Q_PAD_EIM_EB2__CCM_DI1_EXT_CLK		0x08c 0x3a0 0x7ec 0x2 0x0
+#define MX6Q_PAD_EIM_EB2__IPU2_CSI1_D_19		0x08c 0x3a0 0x8d4 0x3 0x0
+#define MX6Q_PAD_EIM_EB2__HDMI_TX_DDC_SCL		0x08c 0x3a0 0x890 0x4 0x0
+#define MX6Q_PAD_EIM_EB2__GPIO_2_30			0x08c 0x3a0 0x000 0x5 0x0
+#define MX6Q_PAD_EIM_EB2__I2C2_SCL			0x08c 0x3a0 0x8a0 0x6 0x0
+#define MX6Q_PAD_EIM_EB2__SRC_BT_CFG_30			0x08c 0x3a0 0x000 0x7 0x0
+#define MX6Q_PAD_EIM_D16__WEIM_WEIM_D_16		0x090 0x3a4 0x000 0x0 0x0
+#define MX6Q_PAD_EIM_D16__ECSPI1_SCLK			0x090 0x3a4 0x7f4 0x1 0x0
+#define MX6Q_PAD_EIM_D16__IPU1_DI0_PIN5			0x090 0x3a4 0x000 0x2 0x0
+#define MX6Q_PAD_EIM_D16__IPU2_CSI1_D_18		0x090 0x3a4 0x8d0 0x3 0x0
+#define MX6Q_PAD_EIM_D16__HDMI_TX_DDC_SDA		0x090 0x3a4 0x894 0x4 0x0
+#define MX6Q_PAD_EIM_D16__GPIO_3_16			0x090 0x3a4 0x000 0x5 0x0
+#define MX6Q_PAD_EIM_D16__I2C2_SDA			0x090 0x3a4 0x8a4 0x6 0x0
+#define MX6Q_PAD_EIM_D17__WEIM_WEIM_D_17		0x094 0x3a8 0x000 0x0 0x0
+#define MX6Q_PAD_EIM_D17__ECSPI1_MISO			0x094 0x3a8 0x7f8 0x1 0x0
+#define MX6Q_PAD_EIM_D17__IPU1_DI0_PIN6			0x094 0x3a8 0x000 0x2 0x0
+#define MX6Q_PAD_EIM_D17__IPU2_CSI1_PIXCLK		0x094 0x3a8 0x8e0 0x3 0x0
+#define MX6Q_PAD_EIM_D17__DCIC1_DCIC_OUT		0x094 0x3a8 0x000 0x4 0x0
+#define MX6Q_PAD_EIM_D17__GPIO_3_17			0x094 0x3a8 0x000 0x5 0x0
+#define MX6Q_PAD_EIM_D17__I2C3_SCL			0x094 0x3a8 0x8a8 0x6 0x0
+#define MX6Q_PAD_EIM_D17__PL301_PER1_HBURST_1		0x094 0x3a8 0x000 0x7 0x0
+#define MX6Q_PAD_EIM_D18__WEIM_WEIM_D_18		0x098 0x3ac 0x000 0x0 0x0
+#define MX6Q_PAD_EIM_D18__ECSPI1_MOSI			0x098 0x3ac 0x7fc 0x1 0x0
+#define MX6Q_PAD_EIM_D18__IPU1_DI0_PIN7			0x098 0x3ac 0x000 0x2 0x0
+#define MX6Q_PAD_EIM_D18__IPU2_CSI1_D_17		0x098 0x3ac 0x8cc 0x3 0x0
+#define MX6Q_PAD_EIM_D18__IPU1_DI1_D0_CS		0x098 0x3ac 0x000 0x4 0x0
+#define MX6Q_PAD_EIM_D18__GPIO_3_18			0x098 0x3ac 0x000 0x5 0x0
+#define MX6Q_PAD_EIM_D18__I2C3_SDA			0x098 0x3ac 0x8ac 0x6 0x0
+#define MX6Q_PAD_EIM_D18__PL301_PER1_HBURST_2		0x098 0x3ac 0x000 0x7 0x0
+#define MX6Q_PAD_EIM_D19__WEIM_WEIM_D_19		0x09c 0x3b0 0x000 0x0 0x0
+#define MX6Q_PAD_EIM_D19__ECSPI1_SS1			0x09c 0x3b0 0x804 0x1 0x0
+#define MX6Q_PAD_EIM_D19__IPU1_DI0_PIN8			0x09c 0x3b0 0x000 0x2 0x0
+#define MX6Q_PAD_EIM_D19__IPU2_CSI1_D_16		0x09c 0x3b0 0x8c8 0x3 0x0
+#define MX6Q_PAD_EIM_D19__UART1_CTS			0x09c 0x3b0 0x91c 0x4 0x0
+#define MX6Q_PAD_EIM_D19__GPIO_3_19			0x09c 0x3b0 0x000 0x5 0x0
+#define MX6Q_PAD_EIM_D19__EPIT1_EPITO			0x09c 0x3b0 0x000 0x6 0x0
+#define MX6Q_PAD_EIM_D19__PL301_PER1_HRESP		0x09c 0x3b0 0x000 0x7 0x0
+#define MX6Q_PAD_EIM_D20__WEIM_WEIM_D_20		0x0a0 0x3b4 0x000 0x0 0x0
+#define MX6Q_PAD_EIM_D20__ECSPI4_SS0			0x0a0 0x3b4 0x824 0x1 0x0
+#define MX6Q_PAD_EIM_D20__IPU1_DI0_PIN16		0x0a0 0x3b4 0x000 0x2 0x0
+#define MX6Q_PAD_EIM_D20__IPU2_CSI1_D_15		0x0a0 0x3b4 0x8c4 0x3 0x0
+#define MX6Q_PAD_EIM_D20__UART1_RTS			0x0a0 0x3b4 0x91c 0x4 0x1
+#define MX6Q_PAD_EIM_D20__GPIO_3_20			0x0a0 0x3b4 0x000 0x5 0x0
+#define MX6Q_PAD_EIM_D20__EPIT2_EPITO			0x0a0 0x3b4 0x000 0x6 0x0
+#define MX6Q_PAD_EIM_D21__WEIM_WEIM_D_21		0x0a4 0x3b8 0x000 0x0 0x0
+#define MX6Q_PAD_EIM_D21__ECSPI4_SCLK			0x0a4 0x3b8 0x000 0x1 0x0
+#define MX6Q_PAD_EIM_D21__IPU1_DI0_PIN17		0x0a4 0x3b8 0x000 0x2 0x0
+#define MX6Q_PAD_EIM_D21__IPU2_CSI1_D_11		0x0a4 0x3b8 0x8b4 0x3 0x0
+#define MX6Q_PAD_EIM_D21__USBOH3_USBOTG_OC		0x0a4 0x3b8 0x944 0x4 0x0
+#define MX6Q_PAD_EIM_D21__GPIO_3_21			0x0a4 0x3b8 0x000 0x5 0x0
+#define MX6Q_PAD_EIM_D21__I2C1_SCL			0x0a4 0x3b8 0x898 0x6 0x0
+#define MX6Q_PAD_EIM_D21__SPDIF_IN1			0x0a4 0x3b8 0x914 0x7 0x0
+#define MX6Q_PAD_EIM_D22__WEIM_WEIM_D_22		0x0a8 0x3bc 0x000 0x0 0x0
+#define MX6Q_PAD_EIM_D22__ECSPI4_MISO			0x0a8 0x3bc 0x000 0x1 0x0
+#define MX6Q_PAD_EIM_D22__IPU1_DI0_PIN1			0x0a8 0x3bc 0x000 0x2 0x0
+#define MX6Q_PAD_EIM_D22__IPU2_CSI1_D_10		0x0a8 0x3bc 0x8b0 0x3 0x0
+#define MX6Q_PAD_EIM_D22__USBOH3_USBOTG_PWR		0x0a8 0x3bc 0x000 0x4 0x0
+#define MX6Q_PAD_EIM_D22__GPIO_3_22			0x0a8 0x3bc 0x000 0x5 0x0
+#define MX6Q_PAD_EIM_D22__SPDIF_OUT1			0x0a8 0x3bc 0x000 0x6 0x0
+#define MX6Q_PAD_EIM_D22__PL301_PER1_HWRITE		0x0a8 0x3bc 0x000 0x7 0x0
+#define MX6Q_PAD_EIM_D23__WEIM_WEIM_D_23		0x0ac 0x3c0 0x000 0x0 0x0
+#define MX6Q_PAD_EIM_D23__IPU1_DI0_D0_CS		0x0ac 0x3c0 0x000 0x1 0x0
+#define MX6Q_PAD_EIM_D23__UART3_CTS			0x0ac 0x3c0 0x92c 0x2 0x0
+#define MX6Q_PAD_EIM_D23__UART1_DCD			0x0ac 0x3c0 0x000 0x3 0x0
+#define MX6Q_PAD_EIM_D23__IPU2_CSI1_DATA_EN		0x0ac 0x3c0 0x8d8 0x4 0x0
+#define MX6Q_PAD_EIM_D23__GPIO_3_23			0x0ac 0x3c0 0x000 0x5 0x0
+#define MX6Q_PAD_EIM_D23__IPU1_DI1_PIN2			0x0ac 0x3c0 0x000 0x6 0x0
+#define MX6Q_PAD_EIM_D23__IPU1_DI1_PIN14		0x0ac 0x3c0 0x000 0x7 0x0
+#define MX6Q_PAD_EIM_EB3__WEIM_WEIM_EB_3		0x0b0 0x3c4 0x000 0x0 0x0
+#define MX6Q_PAD_EIM_EB3__ECSPI4_RDY			0x0b0 0x3c4 0x000 0x1 0x0
+#define MX6Q_PAD_EIM_EB3__UART3_RTS			0x0b0 0x3c4 0x92c 0x2 0x1
+#define MX6Q_PAD_EIM_EB3__UART1_RI			0x0b0 0x3c4 0x000 0x3 0x0
+#define MX6Q_PAD_EIM_EB3__IPU2_CSI1_HSYNC		0x0b0 0x3c4 0x8dc 0x4 0x0
+#define MX6Q_PAD_EIM_EB3__GPIO_2_31			0x0b0 0x3c4 0x000 0x5 0x0
+#define MX6Q_PAD_EIM_EB3__IPU1_DI1_PIN3			0x0b0 0x3c4 0x000 0x6 0x0
+#define MX6Q_PAD_EIM_EB3__SRC_BT_CFG_31			0x0b0 0x3c4 0x000 0x7 0x0
+#define MX6Q_PAD_EIM_D24__WEIM_WEIM_D_24		0x0b4 0x3c8 0x000 0x0 0x0
+#define MX6Q_PAD_EIM_D24__ECSPI4_SS2			0x0b4 0x3c8 0x000 0x1 0x0
+#define MX6Q_PAD_EIM_D24__UART3_TXD			0x0b4 0x3c8 0x000 0x2 0x0
+#define MX6Q_PAD_EIM_D24__ECSPI1_SS2			0x0b4 0x3c8 0x808 0x3 0x0
+#define MX6Q_PAD_EIM_D24__ECSPI2_SS2			0x0b4 0x3c8 0x000 0x4 0x0
+#define MX6Q_PAD_EIM_D24__GPIO_3_24			0x0b4 0x3c8 0x000 0x5 0x0
+#define MX6Q_PAD_EIM_D24__AUDMUX_AUD5_RXFS		0x0b4 0x3c8 0x7d8 0x6 0x0
+#define MX6Q_PAD_EIM_D24__UART1_DTR			0x0b4 0x3c8 0x000 0x7 0x0
+#define MX6Q_PAD_EIM_D25__WEIM_WEIM_D_25		0x0b8 0x3cc 0x000 0x0 0x0
+#define MX6Q_PAD_EIM_D25__ECSPI4_SS3			0x0b8 0x3cc 0x000 0x1 0x0
+#define MX6Q_PAD_EIM_D25__UART3_RXD			0x0b8 0x3cc 0x930 0x2 0x1
+#define MX6Q_PAD_EIM_D25__ECSPI1_SS3			0x0b8 0x3cc 0x80c 0x3 0x0
+#define MX6Q_PAD_EIM_D25__ECSPI2_SS3			0x0b8 0x3cc 0x000 0x4 0x0
+#define MX6Q_PAD_EIM_D25__GPIO_3_25			0x0b8 0x3cc 0x000 0x5 0x0
+#define MX6Q_PAD_EIM_D25__AUDMUX_AUD5_RXC		0x0b8 0x3cc 0x7d4 0x6 0x0
+#define MX6Q_PAD_EIM_D25__UART1_DSR			0x0b8 0x3cc 0x000 0x7 0x0
+#define MX6Q_PAD_EIM_D26__WEIM_WEIM_D_26		0x0bc 0x3d0 0x000 0x0 0x0
+#define MX6Q_PAD_EIM_D26__IPU1_DI1_PIN11		0x0bc 0x3d0 0x000 0x1 0x0
+#define MX6Q_PAD_EIM_D26__IPU1_CSI0_D_1			0x0bc 0x3d0 0x000 0x2 0x0
+#define MX6Q_PAD_EIM_D26__IPU2_CSI1_D_14		0x0bc 0x3d0 0x8c0 0x3 0x0
+#define MX6Q_PAD_EIM_D26__UART2_TXD			0x0bc 0x3d0 0x000 0x4 0x0
+#define MX6Q_PAD_EIM_D26__GPIO_3_26			0x0bc 0x3d0 0x000 0x5 0x0
+#define MX6Q_PAD_EIM_D26__IPU1_SISG_2			0x0bc 0x3d0 0x000 0x6 0x0
+#define MX6Q_PAD_EIM_D26__IPU1_DISP1_DAT_22		0x0bc 0x3d0 0x000 0x7 0x0
+#define MX6Q_PAD_EIM_D27__WEIM_WEIM_D_27		0x0c0 0x3d4 0x000 0x0 0x0
+#define MX6Q_PAD_EIM_D27__IPU1_DI1_PIN13		0x0c0 0x3d4 0x000 0x1 0x0
+#define MX6Q_PAD_EIM_D27__IPU1_CSI0_D_0			0x0c0 0x3d4 0x000 0x2 0x0
+#define MX6Q_PAD_EIM_D27__IPU2_CSI1_D_13		0x0c0 0x3d4 0x8bc 0x3 0x0
+#define MX6Q_PAD_EIM_D27__UART2_RXD			0x0c0 0x3d4 0x928 0x4 0x1
+#define MX6Q_PAD_EIM_D27__GPIO_3_27			0x0c0 0x3d4 0x000 0x5 0x0
+#define MX6Q_PAD_EIM_D27__IPU1_SISG_3			0x0c0 0x3d4 0x000 0x6 0x0
+#define MX6Q_PAD_EIM_D27__IPU1_DISP1_DAT_23		0x0c0 0x3d4 0x000 0x7 0x0
+#define MX6Q_PAD_EIM_D28__WEIM_WEIM_D_28		0x0c4 0x3d8 0x000 0x0 0x0
+#define MX6Q_PAD_EIM_D28__I2C1_SDA			0x0c4 0x3d8 0x89c 0x1 0x0
+#define MX6Q_PAD_EIM_D28__ECSPI4_MOSI			0x0c4 0x3d8 0x000 0x2 0x0
+#define MX6Q_PAD_EIM_D28__IPU2_CSI1_D_12		0x0c4 0x3d8 0x8b8 0x3 0x0
+#define MX6Q_PAD_EIM_D28__UART2_CTS			0x0c4 0x3d8 0x924 0x4 0x0
+#define MX6Q_PAD_EIM_D28__GPIO_3_28			0x0c4 0x3d8 0x000 0x5 0x0
+#define MX6Q_PAD_EIM_D28__IPU1_EXT_TRIG			0x0c4 0x3d8 0x000 0x6 0x0
+#define MX6Q_PAD_EIM_D28__IPU1_DI0_PIN13		0x0c4 0x3d8 0x000 0x7 0x0
+#define MX6Q_PAD_EIM_D29__WEIM_WEIM_D_29		0x0c8 0x3dc 0x000 0x0 0x0
+#define MX6Q_PAD_EIM_D29__IPU1_DI1_PIN15		0x0c8 0x3dc 0x000 0x1 0x0
+#define MX6Q_PAD_EIM_D29__ECSPI4_SS0			0x0c8 0x3dc 0x824 0x2 0x1
+#define MX6Q_PAD_EIM_D29__UART2_RTS			0x0c8 0x3dc 0x924 0x4 0x1
+#define MX6Q_PAD_EIM_D29__GPIO_3_29			0x0c8 0x3dc 0x000 0x5 0x0
+#define MX6Q_PAD_EIM_D29__IPU2_CSI1_VSYNC		0x0c8 0x3dc 0x8e4 0x6 0x0
+#define MX6Q_PAD_EIM_D29__IPU1_DI0_PIN14		0x0c8 0x3dc 0x000 0x7 0x0
+#define MX6Q_PAD_EIM_D30__WEIM_WEIM_D_30		0x0cc 0x3e0 0x000 0x0 0x0
+#define MX6Q_PAD_EIM_D30__IPU1_DISP1_DAT_21		0x0cc 0x3e0 0x000 0x1 0x0
+#define MX6Q_PAD_EIM_D30__IPU1_DI0_PIN11		0x0cc 0x3e0 0x000 0x2 0x0
+#define MX6Q_PAD_EIM_D30__IPU1_CSI0_D_3			0x0cc 0x3e0 0x000 0x3 0x0
+#define MX6Q_PAD_EIM_D30__UART3_CTS			0x0cc 0x3e0 0x92c 0x4 0x2
+#define MX6Q_PAD_EIM_D30__GPIO_3_30			0x0cc 0x3e0 0x000 0x5 0x0
+#define MX6Q_PAD_EIM_D30__USBOH3_USBH1_OC		0x0cc 0x3e0 0x948 0x6 0x0
+#define MX6Q_PAD_EIM_D30__PL301_PER1_HPROT_0		0x0cc 0x3e0 0x000 0x7 0x0
+#define MX6Q_PAD_EIM_D31__WEIM_WEIM_D_31		0x0d0 0x3e4 0x000 0x0 0x0
+#define MX6Q_PAD_EIM_D31__IPU1_DISP1_DAT_20		0x0d0 0x3e4 0x000 0x1 0x0
+#define MX6Q_PAD_EIM_D31__IPU1_DI0_PIN12		0x0d0 0x3e4 0x000 0x2 0x0
+#define MX6Q_PAD_EIM_D31__IPU1_CSI0_D_2			0x0d0 0x3e4 0x000 0x3 0x0
+#define MX6Q_PAD_EIM_D31__UART3_RTS			0x0d0 0x3e4 0x92c 0x4 0x3
+#define MX6Q_PAD_EIM_D31__GPIO_3_31			0x0d0 0x3e4 0x000 0x5 0x0
+#define MX6Q_PAD_EIM_D31__USBOH3_USBH1_PWR		0x0d0 0x3e4 0x000 0x6 0x0
+#define MX6Q_PAD_EIM_D31__PL301_PER1_HPROT_1		0x0d0 0x3e4 0x000 0x7 0x0
+#define MX6Q_PAD_EIM_A24__WEIM_WEIM_A_24		0x0d4 0x3e8 0x000 0x0 0x0
+#define MX6Q_PAD_EIM_A24__IPU1_DISP1_DAT_19		0x0d4 0x3e8 0x000 0x1 0x0
+#define MX6Q_PAD_EIM_A24__IPU2_CSI1_D_19		0x0d4 0x3e8 0x8d4 0x2 0x1
+#define MX6Q_PAD_EIM_A24__IPU2_SISG_2			0x0d4 0x3e8 0x000 0x3 0x0
+#define MX6Q_PAD_EIM_A24__IPU1_SISG_2			0x0d4 0x3e8 0x000 0x4 0x0
+#define MX6Q_PAD_EIM_A24__GPIO_5_4			0x0d4 0x3e8 0x000 0x5 0x0
+#define MX6Q_PAD_EIM_A24__PL301_PER1_HPROT_2		0x0d4 0x3e8 0x000 0x6 0x0
+#define MX6Q_PAD_EIM_A24__SRC_BT_CFG_24			0x0d4 0x3e8 0x000 0x7 0x0
+#define MX6Q_PAD_EIM_A23__WEIM_WEIM_A_23		0x0d8 0x3ec 0x000 0x0 0x0
+#define MX6Q_PAD_EIM_A23__IPU1_DISP1_DAT_18		0x0d8 0x3ec 0x000 0x1 0x0
+#define MX6Q_PAD_EIM_A23__IPU2_CSI1_D_18		0x0d8 0x3ec 0x8d0 0x2 0x1
+#define MX6Q_PAD_EIM_A23__IPU2_SISG_3			0x0d8 0x3ec 0x000 0x3 0x0
+#define MX6Q_PAD_EIM_A23__IPU1_SISG_3			0x0d8 0x3ec 0x000 0x4 0x0
+#define MX6Q_PAD_EIM_A23__GPIO_6_6			0x0d8 0x3ec 0x000 0x5 0x0
+#define MX6Q_PAD_EIM_A23__PL301_PER1_HPROT_3		0x0d8 0x3ec 0x000 0x6 0x0
+#define MX6Q_PAD_EIM_A23__SRC_BT_CFG_23			0x0d8 0x3ec 0x000 0x7 0x0
+#define MX6Q_PAD_EIM_A22__WEIM_WEIM_A_22		0x0dc 0x3f0 0x000 0x0 0x0
+#define MX6Q_PAD_EIM_A22__IPU1_DISP1_DAT_17		0x0dc 0x3f0 0x000 0x1 0x0
+#define MX6Q_PAD_EIM_A22__IPU2_CSI1_D_17		0x0dc 0x3f0 0x8cc 0x2 0x1
+#define MX6Q_PAD_EIM_A22__GPIO_2_16			0x0dc 0x3f0 0x000 0x5 0x0
+#define MX6Q_PAD_EIM_A22__TPSMP_HDATA_0			0x0dc 0x3f0 0x000 0x6 0x0
+#define MX6Q_PAD_EIM_A22__SRC_BT_CFG_22			0x0dc 0x3f0 0x000 0x7 0x0
+#define MX6Q_PAD_EIM_A21__WEIM_WEIM_A_21		0x0e0 0x3f4 0x000 0x0 0x0
+#define MX6Q_PAD_EIM_A21__IPU1_DISP1_DAT_16		0x0e0 0x3f4 0x000 0x1 0x0
+#define MX6Q_PAD_EIM_A21__IPU2_CSI1_D_16		0x0e0 0x3f4 0x8c8 0x2 0x1
+#define MX6Q_PAD_EIM_A21__RESERVED_RESERVED		0x0e0 0x3f4 0x000 0x3 0x0
+#define MX6Q_PAD_EIM_A21__MIPI_CORE_DPHY_OUT_18		0x0e0 0x3f4 0x000 0x4 0x0
+#define MX6Q_PAD_EIM_A21__GPIO_2_17			0x0e0 0x3f4 0x000 0x5 0x0
+#define MX6Q_PAD_EIM_A21__TPSMP_HDATA_1			0x0e0 0x3f4 0x000 0x6 0x0
+#define MX6Q_PAD_EIM_A21__SRC_BT_CFG_21			0x0e0 0x3f4 0x000 0x7 0x0
+#define MX6Q_PAD_EIM_A20__WEIM_WEIM_A_20		0x0e4 0x3f8 0x000 0x0 0x0
+#define MX6Q_PAD_EIM_A20__IPU1_DISP1_DAT_15		0x0e4 0x3f8 0x000 0x1 0x0
+#define MX6Q_PAD_EIM_A20__IPU2_CSI1_D_15		0x0e4 0x3f8 0x8c4 0x2 0x1
+#define MX6Q_PAD_EIM_A20__RESERVED_RESERVED		0x0e4 0x3f8 0x000 0x3 0x0
+#define MX6Q_PAD_EIM_A20__MIPI_CORE_DPHY_OUT_19		0x0e4 0x3f8 0x000 0x4 0x0
+#define MX6Q_PAD_EIM_A20__GPIO_2_18			0x0e4 0x3f8 0x000 0x5 0x0
+#define MX6Q_PAD_EIM_A20__TPSMP_HDATA_2			0x0e4 0x3f8 0x000 0x6 0x0
+#define MX6Q_PAD_EIM_A20__SRC_BT_CFG_20			0x0e4 0x3f8 0x000 0x7 0x0
+#define MX6Q_PAD_EIM_A19__WEIM_WEIM_A_19		0x0e8 0x3fc 0x000 0x0 0x0
+#define MX6Q_PAD_EIM_A19__IPU1_DISP1_DAT_14		0x0e8 0x3fc 0x000 0x1 0x0
+#define MX6Q_PAD_EIM_A19__IPU2_CSI1_D_14		0x0e8 0x3fc 0x8c0 0x2 0x1
+#define MX6Q_PAD_EIM_A19__RESERVED_RESERVED		0x0e8 0x3fc 0x000 0x3 0x0
+#define MX6Q_PAD_EIM_A19__MIPI_CORE_DPHY_OUT_20		0x0e8 0x3fc 0x000 0x4 0x0
+#define MX6Q_PAD_EIM_A19__GPIO_2_19			0x0e8 0x3fc 0x000 0x5 0x0
+#define MX6Q_PAD_EIM_A19__TPSMP_HDATA_3			0x0e8 0x3fc 0x000 0x6 0x0
+#define MX6Q_PAD_EIM_A19__SRC_BT_CFG_19			0x0e8 0x3fc 0x000 0x7 0x0
+#define MX6Q_PAD_EIM_A18__WEIM_WEIM_A_18		0x0ec 0x400 0x000 0x0 0x0
+#define MX6Q_PAD_EIM_A18__IPU1_DISP1_DAT_13		0x0ec 0x400 0x000 0x1 0x0
+#define MX6Q_PAD_EIM_A18__IPU2_CSI1_D_13		0x0ec 0x400 0x8bc 0x2 0x1
+#define MX6Q_PAD_EIM_A18__RESERVED_RESERVED		0x0ec 0x400 0x000 0x3 0x0
+#define MX6Q_PAD_EIM_A18__MIPI_CORE_DPHY_OUT_21		0x0ec 0x400 0x000 0x4 0x0
+#define MX6Q_PAD_EIM_A18__GPIO_2_20			0x0ec 0x400 0x000 0x5 0x0
+#define MX6Q_PAD_EIM_A18__TPSMP_HDATA_4			0x0ec 0x400 0x000 0x6 0x0
+#define MX6Q_PAD_EIM_A18__SRC_BT_CFG_18			0x0ec 0x400 0x000 0x7 0x0
+#define MX6Q_PAD_EIM_A17__WEIM_WEIM_A_17		0x0f0 0x404 0x000 0x0 0x0
+#define MX6Q_PAD_EIM_A17__IPU1_DISP1_DAT_12		0x0f0 0x404 0x000 0x1 0x0
+#define MX6Q_PAD_EIM_A17__IPU2_CSI1_D_12		0x0f0 0x404 0x8b8 0x2 0x1
+#define MX6Q_PAD_EIM_A17__RESERVED_RESERVED		0x0f0 0x404 0x000 0x3 0x0
+#define MX6Q_PAD_EIM_A17__MIPI_CORE_DPHY_OUT_22		0x0f0 0x404 0x000 0x4 0x0
+#define MX6Q_PAD_EIM_A17__GPIO_2_21			0x0f0 0x404 0x000 0x5 0x0
+#define MX6Q_PAD_EIM_A17__TPSMP_HDATA_5			0x0f0 0x404 0x000 0x6 0x0
+#define MX6Q_PAD_EIM_A17__SRC_BT_CFG_17			0x0f0 0x404 0x000 0x7 0x0
+#define MX6Q_PAD_EIM_A16__WEIM_WEIM_A_16		0x0f4 0x408 0x000 0x0 0x0
+#define MX6Q_PAD_EIM_A16__IPU1_DI1_DISP_CLK		0x0f4 0x408 0x000 0x1 0x0
+#define MX6Q_PAD_EIM_A16__IPU2_CSI1_PIXCLK		0x0f4 0x408 0x8e0 0x2 0x1
+#define MX6Q_PAD_EIM_A16__MIPI_CORE_DPHY_OUT_23		0x0f4 0x408 0x000 0x4 0x0
+#define MX6Q_PAD_EIM_A16__GPIO_2_22			0x0f4 0x408 0x000 0x5 0x0
+#define MX6Q_PAD_EIM_A16__TPSMP_HDATA_6			0x0f4 0x408 0x000 0x6 0x0
+#define MX6Q_PAD_EIM_A16__SRC_BT_CFG_16			0x0f4 0x408 0x000 0x7 0x0
+#define MX6Q_PAD_EIM_CS0__WEIM_WEIM_CS_0		0x0f8 0x40c 0x000 0x0 0x0
+#define MX6Q_PAD_EIM_CS0__IPU1_DI1_PIN5			0x0f8 0x40c 0x000 0x1 0x0
+#define MX6Q_PAD_EIM_CS0__ECSPI2_SCLK			0x0f8 0x40c 0x810 0x2 0x0
+#define MX6Q_PAD_EIM_CS0__MIPI_CORE_DPHY_OUT_24		0x0f8 0x40c 0x000 0x4 0x0
+#define MX6Q_PAD_EIM_CS0__GPIO_2_23			0x0f8 0x40c 0x000 0x5 0x0
+#define MX6Q_PAD_EIM_CS0__TPSMP_HDATA_7			0x0f8 0x40c 0x000 0x6 0x0
+#define MX6Q_PAD_EIM_CS1__WEIM_WEIM_CS_1		0x0fc 0x410 0x000 0x0 0x0
+#define MX6Q_PAD_EIM_CS1__IPU1_DI1_PIN6			0x0fc 0x410 0x000 0x1 0x0
+#define MX6Q_PAD_EIM_CS1__ECSPI2_MOSI			0x0fc 0x410 0x818 0x2 0x0
+#define MX6Q_PAD_EIM_CS1__MIPI_CORE_DPHY_OUT_25		0x0fc 0x410 0x000 0x4 0x0
+#define MX6Q_PAD_EIM_CS1__GPIO_2_24			0x0fc 0x410 0x000 0x5 0x0
+#define MX6Q_PAD_EIM_CS1__TPSMP_HDATA_8			0x0fc 0x410 0x000 0x6 0x0
+#define MX6Q_PAD_EIM_OE__WEIM_WEIM_OE			0x100 0x414 0x000 0x0 0x0
+#define MX6Q_PAD_EIM_OE__IPU1_DI1_PIN7			0x100 0x414 0x000 0x1 0x0
+#define MX6Q_PAD_EIM_OE__ECSPI2_MISO			0x100 0x414 0x814 0x2 0x0
+#define MX6Q_PAD_EIM_OE__MIPI_CORE_DPHY_OUT_26		0x100 0x414 0x000 0x4 0x0
+#define MX6Q_PAD_EIM_OE__GPIO_2_25			0x100 0x414 0x000 0x5 0x0
+#define MX6Q_PAD_EIM_OE__TPSMP_HDATA_9			0x100 0x414 0x000 0x6 0x0
+#define MX6Q_PAD_EIM_RW__WEIM_WEIM_RW			0x104 0x418 0x000 0x0 0x0
+#define MX6Q_PAD_EIM_RW__IPU1_DI1_PIN8			0x104 0x418 0x000 0x1 0x0
+#define MX6Q_PAD_EIM_RW__ECSPI2_SS0			0x104 0x418 0x81c 0x2 0x0
+#define MX6Q_PAD_EIM_RW__MIPI_CORE_DPHY_OUT_27		0x104 0x418 0x000 0x4 0x0
+#define MX6Q_PAD_EIM_RW__GPIO_2_26			0x104 0x418 0x000 0x5 0x0
+#define MX6Q_PAD_EIM_RW__TPSMP_HDATA_10			0x104 0x418 0x000 0x6 0x0
+#define MX6Q_PAD_EIM_RW__SRC_BT_CFG_29			0x104 0x418 0x000 0x7 0x0
+#define MX6Q_PAD_EIM_LBA__WEIM_WEIM_LBA			0x108 0x41c 0x000 0x0 0x0
+#define MX6Q_PAD_EIM_LBA__IPU1_DI1_PIN17		0x108 0x41c 0x000 0x1 0x0
+#define MX6Q_PAD_EIM_LBA__ECSPI2_SS1			0x108 0x41c 0x820 0x2 0x0
+#define MX6Q_PAD_EIM_LBA__GPIO_2_27			0x108 0x41c 0x000 0x5 0x0
+#define MX6Q_PAD_EIM_LBA__TPSMP_HDATA_11		0x108 0x41c 0x000 0x6 0x0
+#define MX6Q_PAD_EIM_LBA__SRC_BT_CFG_26			0x108 0x41c 0x000 0x7 0x0
+#define MX6Q_PAD_EIM_EB0__WEIM_WEIM_EB_0		0x10c 0x420 0x000 0x0 0x0
+#define MX6Q_PAD_EIM_EB0__IPU1_DISP1_DAT_11		0x10c 0x420 0x000 0x1 0x0
+#define MX6Q_PAD_EIM_EB0__IPU2_CSI1_D_11		0x10c 0x420 0x8b4 0x2 0x1
+#define MX6Q_PAD_EIM_EB0__MIPI_CORE_DPHY_OUT_0		0x10c 0x420 0x000 0x3 0x0
+#define MX6Q_PAD_EIM_EB0__CCM_PMIC_RDY			0x10c 0x420 0x7f0 0x4 0x0
+#define MX6Q_PAD_EIM_EB0__GPIO_2_28			0x10c 0x420 0x000 0x5 0x0
+#define MX6Q_PAD_EIM_EB0__TPSMP_HDATA_12		0x10c 0x420 0x000 0x6 0x0
+#define MX6Q_PAD_EIM_EB0__SRC_BT_CFG_27			0x10c 0x420 0x000 0x7 0x0
+#define MX6Q_PAD_EIM_EB1__WEIM_WEIM_EB_1		0x110 0x424 0x000 0x0 0x0
+#define MX6Q_PAD_EIM_EB1__IPU1_DISP1_DAT_10		0x110 0x424 0x000 0x1 0x0
+#define MX6Q_PAD_EIM_EB1__IPU2_CSI1_D_10		0x110 0x424 0x8b0 0x2 0x1
+#define MX6Q_PAD_EIM_EB1__MIPI_CORE_DPHY__OUT_1		0x110 0x424 0x000 0x3 0x0
+#define MX6Q_PAD_EIM_EB1__GPIO_2_29			0x110 0x424 0x000 0x5 0x0
+#define MX6Q_PAD_EIM_EB1__TPSMP_HDATA_13		0x110 0x424 0x000 0x6 0x0
+#define MX6Q_PAD_EIM_EB1__SRC_BT_CFG_28			0x110 0x424 0x000 0x7 0x0
+#define MX6Q_PAD_EIM_DA0__WEIM_WEIM_DA_A_0		0x114 0x428 0x000 0x0 0x0
+#define MX6Q_PAD_EIM_DA0__IPU1_DISP1_DAT_9		0x114 0x428 0x000 0x1 0x0
+#define MX6Q_PAD_EIM_DA0__IPU2_CSI1_D_9			0x114 0x428 0x000 0x2 0x0
+#define MX6Q_PAD_EIM_DA0__MIPI_CORE_DPHY__OUT_2		0x114 0x428 0x000 0x3 0x0
+#define MX6Q_PAD_EIM_DA0__GPIO_3_0			0x114 0x428 0x000 0x5 0x0
+#define MX6Q_PAD_EIM_DA0__TPSMP_HDATA_14		0x114 0x428 0x000 0x6 0x0
+#define MX6Q_PAD_EIM_DA0__SRC_BT_CFG_0			0x114 0x428 0x000 0x7 0x0
+#define MX6Q_PAD_EIM_DA1__WEIM_WEIM_DA_A_1		0x118 0x42c 0x000 0x0 0x0
+#define MX6Q_PAD_EIM_DA1__IPU1_DISP1_DAT_8		0x118 0x42c 0x000 0x1 0x0
+#define MX6Q_PAD_EIM_DA1__IPU2_CSI1_D_8			0x118 0x42c 0x000 0x2 0x0
+#define MX6Q_PAD_EIM_DA1__MIPI_CORE_DPHY_OUT_3		0x118 0x42c 0x000 0x3 0x0
+#define MX6Q_PAD_EIM_DA1__USBPHY1_TX_LS_MODE		0x118 0x42c 0x000 0x4 0x0
+#define MX6Q_PAD_EIM_DA1__GPIO_3_1			0x118 0x42c 0x000 0x5 0x0
+#define MX6Q_PAD_EIM_DA1__TPSMP_HDATA_15		0x118 0x42c 0x000 0x6 0x0
+#define MX6Q_PAD_EIM_DA1__SRC_BT_CFG_1			0x118 0x42c 0x000 0x7 0x0
+#define MX6Q_PAD_EIM_DA2__WEIM_WEIM_DA_A_2		0x11c 0x430 0x000 0x0 0x0
+#define MX6Q_PAD_EIM_DA2__IPU1_DISP1_DAT_7		0x11c 0x430 0x000 0x1 0x0
+#define MX6Q_PAD_EIM_DA2__IPU2_CSI1_D_7			0x11c 0x430 0x000 0x2 0x0
+#define MX6Q_PAD_EIM_DA2__MIPI_CORE_DPHY_OUT_4		0x11c 0x430 0x000 0x3 0x0
+#define MX6Q_PAD_EIM_DA2__USBPHY1_TX_HS_MODE		0x11c 0x430 0x000 0x4 0x0
+#define MX6Q_PAD_EIM_DA2__GPIO_3_2			0x11c 0x430 0x000 0x5 0x0
+#define MX6Q_PAD_EIM_DA2__TPSMP_HDATA_16		0x11c 0x430 0x000 0x6 0x0
+#define MX6Q_PAD_EIM_DA2__SRC_BT_CFG_2			0x11c 0x430 0x000 0x7 0x0
+#define MX6Q_PAD_EIM_DA3__WEIM_WEIM_DA_A_3		0x120 0x434 0x000 0x0 0x0
+#define MX6Q_PAD_EIM_DA3__IPU1_DISP1_DAT_6		0x120 0x434 0x000 0x1 0x0
+#define MX6Q_PAD_EIM_DA3__IPU2_CSI1_D_6			0x120 0x434 0x000 0x2 0x0
+#define MX6Q_PAD_EIM_DA3__MIPI_CORE_DPHY_OUT_5		0x120 0x434 0x000 0x3 0x0
+#define MX6Q_PAD_EIM_DA3__USBPHY1_TX_HIZ		0x120 0x434 0x000 0x4 0x0
+#define MX6Q_PAD_EIM_DA3__GPIO_3_3			0x120 0x434 0x000 0x5 0x0
+#define MX6Q_PAD_EIM_DA3__TPSMP_HDATA_17		0x120 0x434 0x000 0x6 0x0
+#define MX6Q_PAD_EIM_DA3__SRC_BT_CFG_3			0x120 0x434 0x000 0x7 0x0
+#define MX6Q_PAD_EIM_DA4__WEIM_WEIM_DA_A_4		0x124 0x438 0x000 0x0 0x0
+#define MX6Q_PAD_EIM_DA4__IPU1_DISP1_DAT_5		0x124 0x438 0x000 0x1 0x0
+#define MX6Q_PAD_EIM_DA4__IPU2_CSI1_D_5			0x124 0x438 0x000 0x2 0x0
+#define MX6Q_PAD_EIM_DA4__MIPI_CORE_DPHY_OUT_6		0x124 0x438 0x000 0x3 0x0
+#define MX6Q_PAD_EIM_DA4__ANATOP_USBPHY1_TX_EN		0x124 0x438 0x000 0x4 0x0
+#define MX6Q_PAD_EIM_DA4__GPIO_3_4			0x124 0x438 0x000 0x5 0x0
+#define MX6Q_PAD_EIM_DA4__TPSMP_HDATA_18		0x124 0x438 0x000 0x6 0x0
+#define MX6Q_PAD_EIM_DA4__SRC_BT_CFG_4			0x124 0x438 0x000 0x7 0x0
+#define MX6Q_PAD_EIM_DA5__WEIM_WEIM_DA_A_5		0x128 0x43c 0x000 0x0 0x0
+#define MX6Q_PAD_EIM_DA5__IPU1_DISP1_DAT_4		0x128 0x43c 0x000 0x1 0x0
+#define MX6Q_PAD_EIM_DA5__IPU2_CSI1_D_4			0x128 0x43c 0x000 0x2 0x0
+#define MX6Q_PAD_EIM_DA5__MIPI_CORE_DPHY_OUT_7		0x128 0x43c 0x000 0x3 0x0
+#define MX6Q_PAD_EIM_DA5__ANATOP_USBPHY1_TX_DP		0x128 0x43c 0x000 0x4 0x0
+#define MX6Q_PAD_EIM_DA5__GPIO_3_5			0x128 0x43c 0x000 0x5 0x0
+#define MX6Q_PAD_EIM_DA5__TPSMP_HDATA_19		0x128 0x43c 0x000 0x6 0x0
+#define MX6Q_PAD_EIM_DA5__SRC_BT_CFG_5			0x128 0x43c 0x000 0x7 0x0
+#define MX6Q_PAD_EIM_DA6__WEIM_WEIM_DA_A_6		0x12c 0x440 0x000 0x0 0x0
+#define MX6Q_PAD_EIM_DA6__IPU1_DISP1_DAT_3		0x12c 0x440 0x000 0x1 0x0
+#define MX6Q_PAD_EIM_DA6__IPU2_CSI1_D_3			0x12c 0x440 0x000 0x2 0x0
+#define MX6Q_PAD_EIM_DA6__MIPI_CORE_DPHY_OUT_8		0x12c 0x440 0x000 0x3 0x0
+#define MX6Q_PAD_EIM_DA6__ANATOP_USBPHY1_TX_DN		0x12c 0x440 0x000 0x4 0x0
+#define MX6Q_PAD_EIM_DA6__GPIO_3_6			0x12c 0x440 0x000 0x5 0x0
+#define MX6Q_PAD_EIM_DA6__TPSMP_HDATA_20		0x12c 0x440 0x000 0x6 0x0
+#define MX6Q_PAD_EIM_DA6__SRC_BT_CFG_6			0x12c 0x440 0x000 0x7 0x0
+#define MX6Q_PAD_EIM_DA7__WEIM_WEIM_DA_A_7		0x130 0x444 0x000 0x0 0x0
+#define MX6Q_PAD_EIM_DA7__IPU1_DISP1_DAT_2		0x130 0x444 0x000 0x1 0x0
+#define MX6Q_PAD_EIM_DA7__IPU2_CSI1_D_2			0x130 0x444 0x000 0x2 0x0
+#define MX6Q_PAD_EIM_DA7__MIPI_CORE_DPHY_OUT_9		0x130 0x444 0x000 0x3 0x0
+#define MX6Q_PAD_EIM_DA7__GPIO_3_7			0x130 0x444 0x000 0x5 0x0
+#define MX6Q_PAD_EIM_DA7__TPSMP_HDATA_21		0x130 0x444 0x000 0x6 0x0
+#define MX6Q_PAD_EIM_DA7__SRC_BT_CFG_7			0x130 0x444 0x000 0x7 0x0
+#define MX6Q_PAD_EIM_DA8__WEIM_WEIM_DA_A_8		0x134 0x448 0x000 0x0 0x0
+#define MX6Q_PAD_EIM_DA8__IPU1_DISP1_DAT_1		0x134 0x448 0x000 0x1 0x0
+#define MX6Q_PAD_EIM_DA8__IPU2_CSI1_D_1			0x134 0x448 0x000 0x2 0x0
+#define MX6Q_PAD_EIM_DA8__MIPI_CORE_DPHY_OUT_10		0x134 0x448 0x000 0x3 0x0
+#define MX6Q_PAD_EIM_DA8__GPIO_3_8			0x134 0x448 0x000 0x5 0x0
+#define MX6Q_PAD_EIM_DA8__TPSMP_HDATA_22		0x134 0x448 0x000 0x6 0x0
+#define MX6Q_PAD_EIM_DA8__SRC_BT_CFG_8			0x134 0x448 0x000 0x7 0x0
+#define MX6Q_PAD_EIM_DA9__WEIM_WEIM_DA_A_9		0x138 0x44c 0x000 0x0 0x0
+#define MX6Q_PAD_EIM_DA9__IPU1_DISP1_DAT_0		0x138 0x44c 0x000 0x1 0x0
+#define MX6Q_PAD_EIM_DA9__IPU2_CSI1_D_0			0x138 0x44c 0x000 0x2 0x0
+#define MX6Q_PAD_EIM_DA9__MIPI_CORE_DPHY_OUT_11		0x138 0x44c 0x000 0x3 0x0
+#define MX6Q_PAD_EIM_DA9__GPIO_3_9			0x138 0x44c 0x000 0x5 0x0
+#define MX6Q_PAD_EIM_DA9__TPSMP_HDATA_23		0x138 0x44c 0x000 0x6 0x0
+#define MX6Q_PAD_EIM_DA9__SRC_BT_CFG_9			0x138 0x44c 0x000 0x7 0x0
+#define MX6Q_PAD_EIM_DA10__WEIM_WEIM_DA_A_10		0x13c 0x450 0x000 0x0 0x0
+#define MX6Q_PAD_EIM_DA10__IPU1_DI1_PIN15		0x13c 0x450 0x000 0x1 0x0
+#define MX6Q_PAD_EIM_DA10__IPU2_CSI1_DATA_EN		0x13c 0x450 0x8d8 0x2 0x1
+#define MX6Q_PAD_EIM_DA10__MIPI_CORE_DPHY_OUT12		0x13c 0x450 0x000 0x3 0x0
+#define MX6Q_PAD_EIM_DA10__GPIO_3_10			0x13c 0x450 0x000 0x5 0x0
+#define MX6Q_PAD_EIM_DA10__TPSMP_HDATA_24		0x13c 0x450 0x000 0x6 0x0
+#define MX6Q_PAD_EIM_DA10__SRC_BT_CFG_10		0x13c 0x450 0x000 0x7 0x0
+#define MX6Q_PAD_EIM_DA11__WEIM_WEIM_DA_A_11		0x140 0x454 0x000 0x0 0x0
+#define MX6Q_PAD_EIM_DA11__IPU1_DI1_PIN2		0x140 0x454 0x000 0x1 0x0
+#define MX6Q_PAD_EIM_DA11__IPU2_CSI1_HSYNC		0x140 0x454 0x8dc 0x2 0x1
+#define MX6Q_PAD_EIM_DA11__MIPI_CORE_DPHY_OUT13		0x140 0x454 0x000 0x3 0x0
+#define MX6Q_PAD_EIM_DA11__SDMA_DBG_EVT_CHN_6		0x140 0x454 0x000 0x4 0x0
+#define MX6Q_PAD_EIM_DA11__GPIO_3_11			0x140 0x454 0x000 0x5 0x0
+#define MX6Q_PAD_EIM_DA11__TPSMP_HDATA_25		0x140 0x454 0x000 0x6 0x0
+#define MX6Q_PAD_EIM_DA11__SRC_BT_CFG_11		0x140 0x454 0x000 0x7 0x0
+#define MX6Q_PAD_EIM_DA12__WEIM_WEIM_DA_A_12		0x144 0x458 0x000 0x0 0x0
+#define MX6Q_PAD_EIM_DA12__IPU1_DI1_PIN3		0x144 0x458 0x000 0x1 0x0
+#define MX6Q_PAD_EIM_DA12__IPU2_CSI1_VSYNC		0x144 0x458 0x8e4 0x2 0x1
+#define MX6Q_PAD_EIM_DA12__MIPI_CORE_DPHY_OUT14		0x144 0x458 0x000 0x3 0x0
+#define MX6Q_PAD_EIM_DA12__SDMA_DEBUG_EVT_CHN_3		0x144 0x458 0x000 0x4 0x0
+#define MX6Q_PAD_EIM_DA12__GPIO_3_12			0x144 0x458 0x000 0x5 0x0
+#define MX6Q_PAD_EIM_DA12__TPSMP_HDATA_26		0x144 0x458 0x000 0x6 0x0
+#define MX6Q_PAD_EIM_DA12__SRC_BT_CFG_12		0x144 0x458 0x000 0x7 0x0
+#define MX6Q_PAD_EIM_DA13__WEIM_WEIM_DA_A_13		0x148 0x45c 0x000 0x0 0x0
+#define MX6Q_PAD_EIM_DA13__IPU1_DI1_D0_CS		0x148 0x45c 0x000 0x1 0x0
+#define MX6Q_PAD_EIM_DA13__CCM_DI1_EXT_CLK		0x148 0x45c 0x7ec 0x2 0x1
+#define MX6Q_PAD_EIM_DA13__MIPI_CORE_DPHY_OUT15		0x148 0x45c 0x000 0x3 0x0
+#define MX6Q_PAD_EIM_DA13__SDMA_DEBUG_EVT_CHN_4		0x148 0x45c 0x000 0x4 0x0
+#define MX6Q_PAD_EIM_DA13__GPIO_3_13			0x148 0x45c 0x000 0x5 0x0
+#define MX6Q_PAD_EIM_DA13__TPSMP_HDATA_27		0x148 0x45c 0x000 0x6 0x0
+#define MX6Q_PAD_EIM_DA13__SRC_BT_CFG_13		0x148 0x45c 0x000 0x7 0x0
+#define MX6Q_PAD_EIM_DA14__WEIM_WEIM_DA_A_14		0x14c 0x460 0x000 0x0 0x0
+#define MX6Q_PAD_EIM_DA14__IPU1_DI1_D1_CS		0x14c 0x460 0x000 0x1 0x0
+#define MX6Q_PAD_EIM_DA14__CCM_DI0_EXT_CLK		0x14c 0x460 0x000 0x2 0x0
+#define MX6Q_PAD_EIM_DA14__MIPI_CORE_DPHY_OUT16		0x14c 0x460 0x000 0x3 0x0
+#define MX6Q_PAD_EIM_DA14__SDMA_DEBUG_EVT_CHN_5		0x14c 0x460 0x000 0x4 0x0
+#define MX6Q_PAD_EIM_DA14__GPIO_3_14			0x14c 0x460 0x000 0x5 0x0
+#define MX6Q_PAD_EIM_DA14__TPSMP_HDATA_28		0x14c 0x460 0x000 0x6 0x0
+#define MX6Q_PAD_EIM_DA14__SRC_BT_CFG_14		0x14c 0x460 0x000 0x7 0x0
+#define MX6Q_PAD_EIM_DA15__WEIM_WEIM_DA_A_15		0x150 0x464 0x000 0x0 0x0
+#define MX6Q_PAD_EIM_DA15__IPU1_DI1_PIN1		0x150 0x464 0x000 0x1 0x0
+#define MX6Q_PAD_EIM_DA15__IPU1_DI1_PIN4		0x150 0x464 0x000 0x2 0x0
+#define MX6Q_PAD_EIM_DA15__MIPI_CORE_DPHY_OUT17		0x150 0x464 0x000 0x3 0x0
+#define MX6Q_PAD_EIM_DA15__GPIO_3_15			0x150 0x464 0x000 0x5 0x0
+#define MX6Q_PAD_EIM_DA15__TPSMP_HDATA_29		0x150 0x464 0x000 0x6 0x0
+#define MX6Q_PAD_EIM_DA15__SRC_BT_CFG_15		0x150 0x464 0x000 0x7 0x0
+#define MX6Q_PAD_EIM_WAIT__WEIM_WEIM_WAIT		0x154 0x468 0x000 0x0 0x0
+#define MX6Q_PAD_EIM_WAIT__WEIM_WEIM_DTACK_B		0x154 0x468 0x000 0x1 0x0
+#define MX6Q_PAD_EIM_WAIT__GPIO_5_0			0x154 0x468 0x000 0x5 0x0
+#define MX6Q_PAD_EIM_WAIT__TPSMP_HDATA_30		0x154 0x468 0x000 0x6 0x0
+#define MX6Q_PAD_EIM_WAIT__SRC_BT_CFG_25		0x154 0x468 0x000 0x7 0x0
+#define MX6Q_PAD_EIM_BCLK__WEIM_WEIM_BCLK		0x158 0x46c 0x000 0x0 0x0
+#define MX6Q_PAD_EIM_BCLK__IPU1_DI1_PIN16		0x158 0x46c 0x000 0x1 0x0
+#define MX6Q_PAD_EIM_BCLK__GPIO_6_31			0x158 0x46c 0x000 0x5 0x0
+#define MX6Q_PAD_EIM_BCLK__TPSMP_HDATA_31		0x158 0x46c 0x000 0x6 0x0
+#define MX6Q_PAD_DI0_DISP_CLK__IPU1_DI0_DSP_CLK		0x15c 0x470 0x000 0x0 0x0
+#define MX6Q_PAD_DI0_DISP_CLK__IPU2_DI0_DSP_CLK		0x15c 0x470 0x000 0x1 0x0
+#define MX6Q_PAD_DI0_DISP_CLK__MIPI_CR_DPY_OT28		0x15c 0x470 0x000 0x3 0x0
+#define MX6Q_PAD_DI0_DISP_CLK__SDMA_DBG_CR_STA0		0x15c 0x470 0x000 0x4 0x0
+#define MX6Q_PAD_DI0_DISP_CLK__GPIO_4_16		0x15c 0x470 0x000 0x5 0x0
+#define MX6Q_PAD_DI0_DISP_CLK__MMDC_DEBUG_0		0x15c 0x470 0x000 0x6 0x0
+#define MX6Q_PAD_DI0_PIN15__IPU1_DI0_PIN15		0x160 0x474 0x000 0x0 0x0
+#define MX6Q_PAD_DI0_PIN15__IPU2_DI0_PIN15		0x160 0x474 0x000 0x1 0x0
+#define MX6Q_PAD_DI0_PIN15__AUDMUX_AUD6_TXC		0x160 0x474 0x000 0x2 0x0
+#define MX6Q_PAD_DI0_PIN15__MIPI_CR_DPHY_OUT_29		0x160 0x474 0x000 0x3 0x0
+#define MX6Q_PAD_DI0_PIN15__SDMA_DBG_CORE_STA_1		0x160 0x474 0x000 0x4 0x0
+#define MX6Q_PAD_DI0_PIN15__GPIO_4_17			0x160 0x474 0x000 0x5 0x0
+#define MX6Q_PAD_DI0_PIN15__MMDC_MMDC_DEBUG_1		0x160 0x474 0x000 0x6 0x0
+#define MX6Q_PAD_DI0_PIN2__IPU1_DI0_PIN2		0x164 0x478 0x000 0x0 0x0
+#define MX6Q_PAD_DI0_PIN2__IPU2_DI0_PIN2		0x164 0x478 0x000 0x1 0x0
+#define MX6Q_PAD_DI0_PIN2__AUDMUX_AUD6_TXD		0x164 0x478 0x000 0x2 0x0
+#define MX6Q_PAD_DI0_PIN2__MIPI_CR_DPHY_OUT_30		0x164 0x478 0x000 0x3 0x0
+#define MX6Q_PAD_DI0_PIN2__SDMA_DBG_CORE_STA_2		0x164 0x478 0x000 0x4 0x0
+#define MX6Q_PAD_DI0_PIN2__GPIO_4_18			0x164 0x478 0x000 0x5 0x0
+#define MX6Q_PAD_DI0_PIN2__MMDC_DEBUG_2			0x164 0x478 0x000 0x6 0x0
+#define MX6Q_PAD_DI0_PIN2__PL301_PER1_HADDR_9		0x164 0x478 0x000 0x7 0x0
+#define MX6Q_PAD_DI0_PIN3__IPU1_DI0_PIN3		0x168 0x47c 0x000 0x0 0x0
+#define MX6Q_PAD_DI0_PIN3__IPU2_DI0_PIN3		0x168 0x47c 0x000 0x1 0x0
+#define MX6Q_PAD_DI0_PIN3__AUDMUX_AUD6_TXFS		0x168 0x47c 0x000 0x2 0x0
+#define MX6Q_PAD_DI0_PIN3__MIPI_CORE_DPHY_OUT31		0x168 0x47c 0x000 0x3 0x0
+#define MX6Q_PAD_DI0_PIN3__SDMA_DBG_CORE_STA_3		0x168 0x47c 0x000 0x4 0x0
+#define MX6Q_PAD_DI0_PIN3__GPIO_4_19			0x168 0x47c 0x000 0x5 0x0
+#define MX6Q_PAD_DI0_PIN3__MMDC_MMDC_DEBUG_3		0x168 0x47c 0x000 0x6 0x0
+#define MX6Q_PAD_DI0_PIN3__PL301_PER1_HADDR_10		0x168 0x47c 0x000 0x7 0x0
+#define MX6Q_PAD_DI0_PIN4__IPU1_DI0_PIN4		0x16c 0x480 0x000 0x0 0x0
+#define MX6Q_PAD_DI0_PIN4__IPU2_DI0_PIN4		0x16c 0x480 0x000 0x1 0x0
+#define MX6Q_PAD_DI0_PIN4__AUDMUX_AUD6_RXD		0x16c 0x480 0x000 0x2 0x0
+#define MX6Q_PAD_DI0_PIN4__USDHC1_WP			0x16c 0x480 0x94c 0x3 0x0
+#define MX6Q_PAD_DI0_PIN4__SDMA_DEBUG_YIELD		0x16c 0x480 0x000 0x4 0x0
+#define MX6Q_PAD_DI0_PIN4__GPIO_4_20			0x16c 0x480 0x000 0x5 0x0
+#define MX6Q_PAD_DI0_PIN4__MMDC_MMDC_DEBUG_4		0x16c 0x480 0x000 0x6 0x0
+#define MX6Q_PAD_DI0_PIN4__PL301_PER1_HADDR_11		0x16c 0x480 0x000 0x7 0x0
+#define MX6Q_PAD_DISP0_DAT0__IPU1_DISP0_DAT_0		0x170 0x484 0x000 0x0 0x0
+#define MX6Q_PAD_DISP0_DAT0__IPU2_DISP0_DAT_0		0x170 0x484 0x000 0x1 0x0
+#define MX6Q_PAD_DISP0_DAT0__ECSPI3_SCLK		0x170 0x484 0x000 0x2 0x0
+#define MX6Q_PAD_DISP0_DAT0__USDHC1_USDHC_DBG_0		0x170 0x484 0x000 0x3 0x0
+#define MX6Q_PAD_DISP0_DAT0__SDMA_DBG_CORE_RUN		0x170 0x484 0x000 0x4 0x0
+#define MX6Q_PAD_DISP0_DAT0__GPIO_4_21			0x170 0x484 0x000 0x5 0x0
+#define MX6Q_PAD_DISP0_DAT0__MMDC_MMDC_DEBUG_5		0x170 0x484 0x000 0x6 0x0
+#define MX6Q_PAD_DISP0_DAT1__IPU1_DISP0_DAT_1		0x174 0x488 0x000 0x0 0x0
+#define MX6Q_PAD_DISP0_DAT1__IPU2_DISP0_DAT_1		0x174 0x488 0x000 0x1 0x0
+#define MX6Q_PAD_DISP0_DAT1__ECSPI3_MOSI		0x174 0x488 0x000 0x2 0x0
+#define MX6Q_PAD_DISP0_DAT1__USDHC1_USDHC_DBG_1		0x174 0x488 0x000 0x3 0x0
+#define MX6Q_PAD_DISP0_DAT1__SDMA_DBG_EVT_CHNSL		0x174 0x488 0x000 0x4 0x0
+#define MX6Q_PAD_DISP0_DAT1__GPIO_4_22			0x174 0x488 0x000 0x5 0x0
+#define MX6Q_PAD_DISP0_DAT1__MMDC_DEBUG_6		0x174 0x488 0x000 0x6 0x0
+#define MX6Q_PAD_DISP0_DAT1__PL301_PER1_HADR_12		0x174 0x488 0x000 0x7 0x0
+#define MX6Q_PAD_DISP0_DAT2__IPU1_DISP0_DAT_2		0x178 0x48c 0x000 0x0 0x0
+#define MX6Q_PAD_DISP0_DAT2__IPU2_DISP0_DAT_2		0x178 0x48c 0x000 0x1 0x0
+#define MX6Q_PAD_DISP0_DAT2__ECSPI3_MISO		0x178 0x48c 0x000 0x2 0x0
+#define MX6Q_PAD_DISP0_DAT2__USDHC1_USDHC_DBG_2		0x178 0x48c 0x000 0x3 0x0
+#define MX6Q_PAD_DISP0_DAT2__SDMA_DEBUG_MODE		0x178 0x48c 0x000 0x4 0x0
+#define MX6Q_PAD_DISP0_DAT2__GPIO_4_23			0x178 0x48c 0x000 0x5 0x0
+#define MX6Q_PAD_DISP0_DAT2__MMDC_DEBUG_7		0x178 0x48c 0x000 0x6 0x0
+#define MX6Q_PAD_DISP0_DAT2__PL301_PER1_HADR_13		0x178 0x48c 0x000 0x7 0x0
+#define MX6Q_PAD_DISP0_DAT3__IPU1_DISP0_DAT_3		0x17c 0x490 0x000 0x0 0x0
+#define MX6Q_PAD_DISP0_DAT3__IPU2_DISP0_DAT_3		0x17c 0x490 0x000 0x1 0x0
+#define MX6Q_PAD_DISP0_DAT3__ECSPI3_SS0			0x17c 0x490 0x000 0x2 0x0
+#define MX6Q_PAD_DISP0_DAT3__USDHC1_USDHC_DBG_3		0x17c 0x490 0x000 0x3 0x0
+#define MX6Q_PAD_DISP0_DAT3__SDMA_DBG_BUS_ERROR		0x17c 0x490 0x000 0x4 0x0
+#define MX6Q_PAD_DISP0_DAT3__GPIO_4_24			0x17c 0x490 0x000 0x5 0x0
+#define MX6Q_PAD_DISP0_DAT3__MMDC_MMDC_DBG_8		0x17c 0x490 0x000 0x6 0x0
+#define MX6Q_PAD_DISP0_DAT3__PL301_PER1_HADR_14		0x17c 0x490 0x000 0x7 0x0
+#define MX6Q_PAD_DISP0_DAT4__IPU1_DISP0_DAT_4		0x180 0x494 0x000 0x0 0x0
+#define MX6Q_PAD_DISP0_DAT4__IPU2_DISP0_DAT_4		0x180 0x494 0x000 0x1 0x0
+#define MX6Q_PAD_DISP0_DAT4__ECSPI3_SS1			0x180 0x494 0x000 0x2 0x0
+#define MX6Q_PAD_DISP0_DAT4__USDHC1_USDHC_DBG_4		0x180 0x494 0x000 0x3 0x0
+#define MX6Q_PAD_DISP0_DAT4__SDMA_DEBUG_BUS_RWB		0x180 0x494 0x000 0x4 0x0
+#define MX6Q_PAD_DISP0_DAT4__GPIO_4_25			0x180 0x494 0x000 0x5 0x0
+#define MX6Q_PAD_DISP0_DAT4__MMDC_MMDC_DEBUG_9		0x180 0x494 0x000 0x6 0x0
+#define MX6Q_PAD_DISP0_DAT4__PL301_PER1_HADR_15		0x180 0x494 0x000 0x7 0x0
+#define MX6Q_PAD_DISP0_DAT5__IPU1_DISP0_DAT_5		0x184 0x498 0x000 0x0 0x0
+#define MX6Q_PAD_DISP0_DAT5__IPU2_DISP0_DAT_5		0x184 0x498 0x000 0x1 0x0
+#define MX6Q_PAD_DISP0_DAT5__ECSPI3_SS2			0x184 0x498 0x000 0x2 0x0
+#define MX6Q_PAD_DISP0_DAT5__AUDMUX_AUD6_RXFS		0x184 0x498 0x000 0x3 0x0
+#define MX6Q_PAD_DISP0_DAT5__SDMA_DBG_MCH_DMBUS		0x184 0x498 0x000 0x4 0x0
+#define MX6Q_PAD_DISP0_DAT5__GPIO_4_26			0x184 0x498 0x000 0x5 0x0
+#define MX6Q_PAD_DISP0_DAT5__MMDC_DEBUG_10		0x184 0x498 0x000 0x6 0x0
+#define MX6Q_PAD_DISP0_DAT5__PL301_PER1_HADR_16		0x184 0x498 0x000 0x7 0x0
+#define MX6Q_PAD_DISP0_DAT6__IPU1_DISP0_DAT_6		0x188 0x49c 0x000 0x0 0x0
+#define MX6Q_PAD_DISP0_DAT6__IPU2_DISP0_DAT_6		0x188 0x49c 0x000 0x1 0x0
+#define MX6Q_PAD_DISP0_DAT6__ECSPI3_SS3			0x188 0x49c 0x000 0x2 0x0
+#define MX6Q_PAD_DISP0_DAT6__AUDMUX_AUD6_RXC		0x188 0x49c 0x000 0x3 0x0
+#define MX6Q_PAD_DISP0_DAT6__SDMA_DBG_RTBUF_WRT		0x188 0x49c 0x000 0x4 0x0
+#define MX6Q_PAD_DISP0_DAT6__GPIO_4_27			0x188 0x49c 0x000 0x5 0x0
+#define MX6Q_PAD_DISP0_DAT6__MMDC_DEBUG_11		0x188 0x49c 0x000 0x6 0x0
+#define MX6Q_PAD_DISP0_DAT6__PL301_PER1_HADR_17		0x188 0x49c 0x000 0x7 0x0
+#define MX6Q_PAD_DISP0_DAT7__IPU1_DISP0_DAT_7		0x18c 0x4a0 0x000 0x0 0x0
+#define MX6Q_PAD_DISP0_DAT7__IPU2_DISP0_DAT_7		0x18c 0x4a0 0x000 0x1 0x0
+#define MX6Q_PAD_DISP0_DAT7__ECSPI3_RDY			0x18c 0x4a0 0x000 0x2 0x0
+#define MX6Q_PAD_DISP0_DAT7__USDHC1_USDHC_DBG_5		0x18c 0x4a0 0x000 0x3 0x0
+#define MX6Q_PAD_DISP0_DAT7__SDMA_DBG_EVT_CHN_0		0x18c 0x4a0 0x000 0x4 0x0
+#define MX6Q_PAD_DISP0_DAT7__GPIO_4_28			0x18c 0x4a0 0x000 0x5 0x0
+#define MX6Q_PAD_DISP0_DAT7__MMDC_DEBUG_12		0x18c 0x4a0 0x000 0x6 0x0
+#define MX6Q_PAD_DISP0_DAT7__PL301_PER1_HADR_18		0x18c 0x4a0 0x000 0x7 0x0
+#define MX6Q_PAD_DISP0_DAT8__IPU1_DISP0_DAT_8		0x190 0x4a4 0x000 0x0 0x0
+#define MX6Q_PAD_DISP0_DAT8__IPU2_DISP0_DAT_8		0x190 0x4a4 0x000 0x1 0x0
+#define MX6Q_PAD_DISP0_DAT8__PWM1_PWMO			0x190 0x4a4 0x000 0x2 0x0
+#define MX6Q_PAD_DISP0_DAT8__WDOG1_WDOG_B		0x190 0x4a4 0x000 0x3 0x0
+#define MX6Q_PAD_DISP0_DAT8__SDMA_DBG_EVT_CHN_1		0x190 0x4a4 0x000 0x4 0x0
+#define MX6Q_PAD_DISP0_DAT8__GPIO_4_29			0x190 0x4a4 0x000 0x5 0x0
+#define MX6Q_PAD_DISP0_DAT8__MMDC_DEBUG_13		0x190 0x4a4 0x000 0x6 0x0
+#define MX6Q_PAD_DISP0_DAT8__PL301_PER1_HADR_19		0x190 0x4a4 0x000 0x7 0x0
+#define MX6Q_PAD_DISP0_DAT9__IPU1_DISP0_DAT_9		0x194 0x4a8 0x000 0x0 0x0
+#define MX6Q_PAD_DISP0_DAT9__IPU2_DISP0_DAT_9		0x194 0x4a8 0x000 0x1 0x0
+#define MX6Q_PAD_DISP0_DAT9__PWM2_PWMO			0x194 0x4a8 0x000 0x2 0x0
+#define MX6Q_PAD_DISP0_DAT9__WDOG2_WDOG_B		0x194 0x4a8 0x000 0x3 0x0
+#define MX6Q_PAD_DISP0_DAT9__SDMA_DBG_EVT_CHN_2		0x194 0x4a8 0x000 0x4 0x0
+#define MX6Q_PAD_DISP0_DAT9__GPIO_4_30			0x194 0x4a8 0x000 0x5 0x0
+#define MX6Q_PAD_DISP0_DAT9__MMDC_DEBUG_14		0x194 0x4a8 0x000 0x6 0x0
+#define MX6Q_PAD_DISP0_DAT9__PL301_PER1_HADR_20		0x194 0x4a8 0x000 0x7 0x0
+#define MX6Q_PAD_DISP0_DAT10__IPU1_DISP0_DAT_10		0x198 0x4ac 0x000 0x0 0x0
+#define MX6Q_PAD_DISP0_DAT10__IPU2_DISP0_DAT_10		0x198 0x4ac 0x000 0x1 0x0
+#define MX6Q_PAD_DISP0_DAT10__USDHC1_DBG_6		0x198 0x4ac 0x000 0x3 0x0
+#define MX6Q_PAD_DISP0_DAT10__SDMA_DBG_EVT_CHN3		0x198 0x4ac 0x000 0x4 0x0
+#define MX6Q_PAD_DISP0_DAT10__GPIO_4_31			0x198 0x4ac 0x000 0x5 0x0
+#define MX6Q_PAD_DISP0_DAT10__MMDC_DEBUG_15		0x198 0x4ac 0x000 0x6 0x0
+#define MX6Q_PAD_DISP0_DAT10__PL301_PER1_HADR21		0x198 0x4ac 0x000 0x7 0x0
+#define MX6Q_PAD_DISP0_DAT11__IPU1_DISP0_DAT_11		0x19c 0x4b0 0x000 0x0 0x0
+#define MX6Q_PAD_DISP0_DAT11__IPU2_DISP0_DAT_11		0x19c 0x4b0 0x000 0x1 0x0
+#define MX6Q_PAD_DISP0_DAT11__USDHC1_USDHC_DBG7		0x19c 0x4b0 0x000 0x3 0x0
+#define MX6Q_PAD_DISP0_DAT11__SDMA_DBG_EVT_CHN4		0x19c 0x4b0 0x000 0x4 0x0
+#define MX6Q_PAD_DISP0_DAT11__GPIO_5_5			0x19c 0x4b0 0x000 0x5 0x0
+#define MX6Q_PAD_DISP0_DAT11__MMDC_DEBUG_16		0x19c 0x4b0 0x000 0x6 0x0
+#define MX6Q_PAD_DISP0_DAT11__PL301_PER1_HADR22		0x19c 0x4b0 0x000 0x7 0x0
+#define MX6Q_PAD_DISP0_DAT12__IPU1_DISP0_DAT_12		0x1a0 0x4b4 0x000 0x0 0x0
+#define MX6Q_PAD_DISP0_DAT12__IPU2_DISP0_DAT_12		0x1a0 0x4b4 0x000 0x1 0x0
+#define MX6Q_PAD_DISP0_DAT12__RESERVED_RESERVED		0x1a0 0x4b4 0x000 0x3 0x0
+#define MX6Q_PAD_DISP0_DAT12__SDMA_DBG_EVT_CHN5		0x1a0 0x4b4 0x000 0x4 0x0
+#define MX6Q_PAD_DISP0_DAT12__GPIO_5_6			0x1a0 0x4b4 0x000 0x5 0x0
+#define MX6Q_PAD_DISP0_DAT12__MMDC_DEBUG_17		0x1a0 0x4b4 0x000 0x6 0x0
+#define MX6Q_PAD_DISP0_DAT12__PL301_PER1_HADR23		0x1a0 0x4b4 0x000 0x7 0x0
+#define MX6Q_PAD_DISP0_DAT13__IPU1_DISP0_DAT_13		0x1a4 0x4b8 0x000 0x0 0x0
+#define MX6Q_PAD_DISP0_DAT13__IPU2_DISP0_DAT_13		0x1a4 0x4b8 0x000 0x1 0x0
+#define MX6Q_PAD_DISP0_DAT13__AUDMUX_AUD5_RXFS		0x1a4 0x4b8 0x7d8 0x3 0x1
+#define MX6Q_PAD_DISP0_DAT13__SDMA_DBG_EVT_CHN0		0x1a4 0x4b8 0x000 0x4 0x0
+#define MX6Q_PAD_DISP0_DAT13__GPIO_5_7			0x1a4 0x4b8 0x000 0x5 0x0
+#define MX6Q_PAD_DISP0_DAT13__MMDC_DEBUG_18		0x1a4 0x4b8 0x000 0x6 0x0
+#define MX6Q_PAD_DISP0_DAT13__PL301_PER1_HADR24		0x1a4 0x4b8 0x000 0x7 0x0
+#define MX6Q_PAD_DISP0_DAT14__IPU1_DISP0_DAT_14		0x1a8 0x4bc 0x000 0x0 0x0
+#define MX6Q_PAD_DISP0_DAT14__IPU2_DISP0_DAT_14		0x1a8 0x4bc 0x000 0x1 0x0
+#define MX6Q_PAD_DISP0_DAT14__AUDMUX_AUD5_RXC		0x1a8 0x4bc 0x7d4 0x3 0x1
+#define MX6Q_PAD_DISP0_DAT14__SDMA_DBG_EVT_CHN1		0x1a8 0x4bc 0x000 0x4 0x0
+#define MX6Q_PAD_DISP0_DAT14__GPIO_5_8			0x1a8 0x4bc 0x000 0x5 0x0
+#define MX6Q_PAD_DISP0_DAT14__MMDC_DEBUG_19		0x1a8 0x4bc 0x000 0x6 0x0
+#define MX6Q_PAD_DISP0_DAT15__IPU1_DISP0_DAT_15		0x1ac 0x4c0 0x000 0x0 0x0
+#define MX6Q_PAD_DISP0_DAT15__IPU2_DISP0_DAT_15		0x1ac 0x4c0 0x000 0x1 0x0
+#define MX6Q_PAD_DISP0_DAT15__ECSPI1_SS1		0x1ac 0x4c0 0x804 0x2 0x1
+#define MX6Q_PAD_DISP0_DAT15__ECSPI2_SS1		0x1ac 0x4c0 0x820 0x3 0x1
+#define MX6Q_PAD_DISP0_DAT15__SDMA_DBG_EVT_CHN2		0x1ac 0x4c0 0x000 0x4 0x0
+#define MX6Q_PAD_DISP0_DAT15__GPIO_5_9			0x1ac 0x4c0 0x000 0x5 0x0
+#define MX6Q_PAD_DISP0_DAT15__MMDC_DEBUG_20		0x1ac 0x4c0 0x000 0x6 0x0
+#define MX6Q_PAD_DISP0_DAT15__PL301_PER1_HADR25		0x1ac 0x4c0 0x000 0x7 0x0
+#define MX6Q_PAD_DISP0_DAT16__IPU1_DISP0_DAT_16		0x1b0 0x4c4 0x000 0x0 0x0
+#define MX6Q_PAD_DISP0_DAT16__IPU2_DISP0_DAT_16		0x1b0 0x4c4 0x000 0x1 0x0
+#define MX6Q_PAD_DISP0_DAT16__ECSPI2_MOSI		0x1b0 0x4c4 0x818 0x2 0x1
+#define MX6Q_PAD_DISP0_DAT16__AUDMUX_AUD5_TXC		0x1b0 0x4c4 0x7dc 0x3 0x0
+#define MX6Q_PAD_DISP0_DAT16__SDMA_EXT_EVENT_0		0x1b0 0x4c4 0x90c 0x4 0x0
+#define MX6Q_PAD_DISP0_DAT16__GPIO_5_10			0x1b0 0x4c4 0x000 0x5 0x0
+#define MX6Q_PAD_DISP0_DAT16__MMDC_DEBUG_21		0x1b0 0x4c4 0x000 0x6 0x0
+#define MX6Q_PAD_DISP0_DAT16__PL301_PER1_HADR26		0x1b0 0x4c4 0x000 0x7 0x0
+#define MX6Q_PAD_DISP0_DAT17__IPU1_DISP0_DAT_17		0x1b4 0x4c8 0x000 0x0 0x0
+#define MX6Q_PAD_DISP0_DAT17__IPU2_DISP0_DAT_17		0x1b4 0x4c8 0x000 0x1 0x0
+#define MX6Q_PAD_DISP0_DAT17__ECSPI2_MISO		0x1b4 0x4c8 0x814 0x2 0x1
+#define MX6Q_PAD_DISP0_DAT17__AUDMUX_AUD5_TXD		0x1b4 0x4c8 0x7d0 0x3 0x0
+#define MX6Q_PAD_DISP0_DAT17__SDMA_EXT_EVENT_1		0x1b4 0x4c8 0x910 0x4 0x0
+#define MX6Q_PAD_DISP0_DAT17__GPIO_5_11			0x1b4 0x4c8 0x000 0x5 0x0
+#define MX6Q_PAD_DISP0_DAT17__MMDC_DEBUG_22		0x1b4 0x4c8 0x000 0x6 0x0
+#define MX6Q_PAD_DISP0_DAT17__PL301_PER1_HADR27		0x1b4 0x4c8 0x000 0x7 0x0
+#define MX6Q_PAD_DISP0_DAT18__IPU1_DISP0_DAT_18		0x1b8 0x4cc 0x000 0x0 0x0
+#define MX6Q_PAD_DISP0_DAT18__IPU2_DISP0_DAT_18		0x1b8 0x4cc 0x000 0x1 0x0
+#define MX6Q_PAD_DISP0_DAT18__ECSPI2_SS0		0x1b8 0x4cc 0x81c 0x2 0x1
+#define MX6Q_PAD_DISP0_DAT18__AUDMUX_AUD5_TXFS		0x1b8 0x4cc 0x7e0 0x3 0x0
+#define MX6Q_PAD_DISP0_DAT18__AUDMUX_AUD4_RXFS		0x1b8 0x4cc 0x7c0 0x4 0x0
+#define MX6Q_PAD_DISP0_DAT18__GPIO_5_12			0x1b8 0x4cc 0x000 0x5 0x0
+#define MX6Q_PAD_DISP0_DAT18__MMDC_DEBUG_23		0x1b8 0x4cc 0x000 0x6 0x0
+#define MX6Q_PAD_DISP0_DAT18__WEIM_WEIM_CS_2		0x1b8 0x4cc 0x000 0x7 0x0
+#define MX6Q_PAD_DISP0_DAT19__IPU1_DISP0_DAT_19		0x1bc 0x4d0 0x000 0x0 0x0
+#define MX6Q_PAD_DISP0_DAT19__IPU2_DISP0_DAT_19		0x1bc 0x4d0 0x000 0x1 0x0
+#define MX6Q_PAD_DISP0_DAT19__ECSPI2_SCLK		0x1bc 0x4d0 0x810 0x2 0x1
+#define MX6Q_PAD_DISP0_DAT19__AUDMUX_AUD5_RXD		0x1bc 0x4d0 0x7cc 0x3 0x0
+#define MX6Q_PAD_DISP0_DAT19__AUDMUX_AUD4_RXC		0x1bc 0x4d0 0x7bc 0x4 0x0
+#define MX6Q_PAD_DISP0_DAT19__GPIO_5_13			0x1bc 0x4d0 0x000 0x5 0x0
+#define MX6Q_PAD_DISP0_DAT19__MMDC_DEBUG_24		0x1bc 0x4d0 0x000 0x6 0x0
+#define MX6Q_PAD_DISP0_DAT19__WEIM_WEIM_CS_3		0x1bc 0x4d0 0x000 0x7 0x0
+#define MX6Q_PAD_DISP0_DAT20__IPU1_DISP0_DAT_20		0x1c0 0x4d4 0x000 0x0 0x0
+#define MX6Q_PAD_DISP0_DAT20__IPU2_DISP0_DAT_20		0x1c0 0x4d4 0x000 0x1 0x0
+#define MX6Q_PAD_DISP0_DAT20__ECSPI1_SCLK		0x1c0 0x4d4 0x7f4 0x2 0x1
+#define MX6Q_PAD_DISP0_DAT20__AUDMUX_AUD4_TXC		0x1c0 0x4d4 0x7c4 0x3 0x0
+#define MX6Q_PAD_DISP0_DAT20__SDMA_DBG_EVT_CHN7		0x1c0 0x4d4 0x000 0x4 0x0
+#define MX6Q_PAD_DISP0_DAT20__GPIO_5_14			0x1c0 0x4d4 0x000 0x5 0x0
+#define MX6Q_PAD_DISP0_DAT20__MMDC_DEBUG_25		0x1c0 0x4d4 0x000 0x6 0x0
+#define MX6Q_PAD_DISP0_DAT20__PL301_PER1_HADR28		0x1c0 0x4d4 0x000 0x7 0x0
+#define MX6Q_PAD_DISP0_DAT21__IPU1_DISP0_DAT_21		0x1c4 0x4d8 0x000 0x0 0x0
+#define MX6Q_PAD_DISP0_DAT21__IPU2_DISP0_DAT_21		0x1c4 0x4d8 0x000 0x1 0x0
+#define MX6Q_PAD_DISP0_DAT21__ECSPI1_MOSI		0x1c4 0x4d8 0x7fc 0x2 0x1
+#define MX6Q_PAD_DISP0_DAT21__AUDMUX_AUD4_TXD		0x1c4 0x4d8 0x7b8 0x3 0x1
+#define MX6Q_PAD_DISP0_DAT21__SDMA_DBG_BUS_DEV0		0x1c4 0x4d8 0x000 0x4 0x0
+#define MX6Q_PAD_DISP0_DAT21__GPIO_5_15			0x1c4 0x4d8 0x000 0x5 0x0
+#define MX6Q_PAD_DISP0_DAT21__MMDC_DEBUG_26		0x1c4 0x4d8 0x000 0x6 0x0
+#define MX6Q_PAD_DISP0_DAT21__PL301_PER1_HADR29		0x1c4 0x4d8 0x000 0x7 0x0
+#define MX6Q_PAD_DISP0_DAT22__IPU1_DISP0_DAT_22		0x1c8 0x4dc 0x000 0x0 0x0
+#define MX6Q_PAD_DISP0_DAT22__IPU2_DISP0_DAT_22		0x1c8 0x4dc 0x000 0x1 0x0
+#define MX6Q_PAD_DISP0_DAT22__ECSPI1_MISO		0x1c8 0x4dc 0x7f8 0x2 0x1
+#define MX6Q_PAD_DISP0_DAT22__AUDMUX_AUD4_TXFS		0x1c8 0x4dc 0x7c8 0x3 0x1
+#define MX6Q_PAD_DISP0_DAT22__SDMA_DBG_BUS_DEV1		0x1c8 0x4dc 0x000 0x4 0x0
+#define MX6Q_PAD_DISP0_DAT22__GPIO_5_16			0x1c8 0x4dc 0x000 0x5 0x0
+#define MX6Q_PAD_DISP0_DAT22__MMDC_DEBUG_27		0x1c8 0x4dc 0x000 0x6 0x0
+#define MX6Q_PAD_DISP0_DAT22__PL301_PER1_HADR30		0x1c8 0x4dc 0x000 0x7 0x0
+#define MX6Q_PAD_DISP0_DAT23__IPU1_DISP0_DAT_23		0x1cc 0x4e0 0x000 0x0 0x0
+#define MX6Q_PAD_DISP0_DAT23__IPU2_DISP0_DAT_23		0x1cc 0x4e0 0x000 0x1 0x0
+#define MX6Q_PAD_DISP0_DAT23__ECSPI1_SS0		0x1cc 0x4e0 0x800 0x2 0x1
+#define MX6Q_PAD_DISP0_DAT23__AUDMUX_AUD4_RXD		0x1cc 0x4e0 0x7b4 0x3 0x1
+#define MX6Q_PAD_DISP0_DAT23__SDMA_DBG_BUS_DEV2		0x1cc 0x4e0 0x000 0x4 0x0
+#define MX6Q_PAD_DISP0_DAT23__GPIO_5_17			0x1cc 0x4e0 0x000 0x5 0x0
+#define MX6Q_PAD_DISP0_DAT23__MMDC_DEBUG_28		0x1cc 0x4e0 0x000 0x6 0x0
+#define MX6Q_PAD_DISP0_DAT23__PL301_PER1_HADR31		0x1cc 0x4e0 0x000 0x7 0x0
+#define MX6Q_PAD_ENET_MDIO__RESERVED_RESERVED		0x1d0 0x4e4 0x000 0x0 0x0
+#define MX6Q_PAD_ENET_MDIO__ENET_MDIO			0x1d0 0x4e4 0x840 0x1 0x0
+#define MX6Q_PAD_ENET_MDIO__ESAI1_SCKR			0x1d0 0x4e4 0x86c 0x2 0x0
+#define MX6Q_PAD_ENET_MDIO__SDMA_DEBUG_BUS_DEV3		0x1d0 0x4e4 0x000 0x3 0x0
+#define MX6Q_PAD_ENET_MDIO__ENET_1588_EVT1_OUT		0x1d0 0x4e4 0x000 0x4 0x0
+#define MX6Q_PAD_ENET_MDIO__GPIO_1_22			0x1d0 0x4e4 0x000 0x5 0x0
+#define MX6Q_PAD_ENET_MDIO__SPDIF_PLOCK			0x1d0 0x4e4 0x000 0x6 0x0
+#define MX6Q_PAD_ENET_REF_CLK__RESERVED_RSRVED		0x1d4 0x4e8 0x000 0x0 0x0
+#define MX6Q_PAD_ENET_REF_CLK__ENET_TX_CLK		0x1d4 0x4e8 0x000 0x1 0x0
+#define MX6Q_PAD_ENET_REF_CLK__ESAI1_FSR		0x1d4 0x4e8 0x85c 0x2 0x0
+#define MX6Q_PAD_ENET_REF_CLK__SDMA_DBGBUS_DEV4		0x1d4 0x4e8 0x000 0x3 0x0
+#define MX6Q_PAD_ENET_REF_CLK__GPIO_1_23		0x1d4 0x4e8 0x000 0x5 0x0
+#define MX6Q_PAD_ENET_REF_CLK__SPDIF_SRCLK		0x1d4 0x4e8 0x000 0x6 0x0
+#define MX6Q_PAD_ENET_REF_CLK__USBPHY1_RX_SQH		0x1d4 0x4e8 0x000 0x7 0x0
+#define MX6Q_PAD_ENET_RX_ER__ENET_RX_ER			0x1d8 0x4ec 0x000 0x1 0x0
+#define MX6Q_PAD_ENET_RX_ER__ESAI1_HCKR			0x1d8 0x4ec 0x864 0x2 0x0
+#define MX6Q_PAD_ENET_RX_ER__SPDIF_IN1			0x1d8 0x4ec 0x914 0x3 0x1
+#define MX6Q_PAD_ENET_RX_ER__ENET_1588_EVT2_OUT		0x1d8 0x4ec 0x000 0x4 0x0
+#define MX6Q_PAD_ENET_RX_ER__GPIO_1_24			0x1d8 0x4ec 0x000 0x5 0x0
+#define MX6Q_PAD_ENET_RX_ER__PHY_TDI			0x1d8 0x4ec 0x000 0x6 0x0
+#define MX6Q_PAD_ENET_RX_ER__USBPHY1_RX_HS_RXD		0x1d8 0x4ec 0x000 0x7 0x0
+#define MX6Q_PAD_ENET_CRS_DV__RESERVED_RSRVED		0x1dc 0x4f0 0x000 0x0 0x0
+#define MX6Q_PAD_ENET_CRS_DV__ENET_RX_EN		0x1dc 0x4f0 0x858 0x1 0x1
+#define MX6Q_PAD_ENET_CRS_DV__ESAI1_SCKT		0x1dc 0x4f0 0x870 0x2 0x0
+#define MX6Q_PAD_ENET_CRS_DV__SPDIF_EXTCLK		0x1dc 0x4f0 0x918 0x3 0x1
+#define MX6Q_PAD_ENET_CRS_DV__GPIO_1_25			0x1dc 0x4f0 0x000 0x5 0x0
+#define MX6Q_PAD_ENET_CRS_DV__PHY_TDO			0x1dc 0x4f0 0x000 0x6 0x0
+#define MX6Q_PAD_ENET_CRS_DV__USBPHY1_RX_FS_RXD		0x1dc 0x4f0 0x000 0x7 0x0
+#define MX6Q_PAD_ENET_RXD1__MLB_MLBSIG			0x1e0 0x4f4 0x908 0x0 0x0
+#define MX6Q_PAD_ENET_RXD1__ENET_RDATA_1		0x1e0 0x4f4 0x84c 0x1 0x1
+#define MX6Q_PAD_ENET_RXD1__ESAI1_FST			0x1e0 0x4f4 0x860 0x2 0x0
+#define MX6Q_PAD_ENET_RXD1__ENET_1588_EVT3_OUT		0x1e0 0x4f4 0x000 0x4 0x0
+#define MX6Q_PAD_ENET_RXD1__GPIO_1_26			0x1e0 0x4f4 0x000 0x5 0x0
+#define MX6Q_PAD_ENET_RXD1__PHY_TCK			0x1e0 0x4f4 0x000 0x6 0x0
+#define MX6Q_PAD_ENET_RXD1__USBPHY1_RX_DISCON		0x1e0 0x4f4 0x000 0x7 0x0
+#define MX6Q_PAD_ENET_RXD0__OSC32K_32K_OUT		0x1e4 0x4f8 0x000 0x0 0x0
+#define MX6Q_PAD_ENET_RXD0__ENET_RDATA_0		0x1e4 0x4f8 0x848 0x1 0x1
+#define MX6Q_PAD_ENET_RXD0__ESAI1_HCKT			0x1e4 0x4f8 0x868 0x2 0x0
+#define MX6Q_PAD_ENET_RXD0__SPDIF_OUT1			0x1e4 0x4f8 0x000 0x3 0x0
+#define MX6Q_PAD_ENET_RXD0__GPIO_1_27			0x1e4 0x4f8 0x000 0x5 0x0
+#define MX6Q_PAD_ENET_RXD0__PHY_TMS			0x1e4 0x4f8 0x000 0x6 0x0
+#define MX6Q_PAD_ENET_RXD0__USBPHY1_PLL_CK20DIV		0x1e4 0x4f8 0x000 0x7 0x0
+#define MX6Q_PAD_ENET_TX_EN__RESERVED_RSRVED		0x1e8 0x4fc 0x000 0x0 0x0
+#define MX6Q_PAD_ENET_TX_EN__ENET_TX_EN			0x1e8 0x4fc 0x000 0x1 0x0
+#define MX6Q_PAD_ENET_TX_EN__ESAI1_TX3_RX2		0x1e8 0x4fc 0x880 0x2 0x0
+#define MX6Q_PAD_ENET_TX_EN__GPIO_1_28			0x1e8 0x4fc 0x000 0x5 0x0
+#define MX6Q_PAD_ENET_TX_EN__SATA_PHY_TDI		0x1e8 0x4fc 0x000 0x6 0x0
+#define MX6Q_PAD_ENET_TX_EN__USBPHY2_RX_SQH		0x1e8 0x4fc 0x000 0x7 0x0
+#define MX6Q_PAD_ENET_TXD1__MLB_MLBCLK			0x1ec 0x500 0x900 0x0 0x0
+#define MX6Q_PAD_ENET_TXD1__ENET_TDATA_1		0x1ec 0x500 0x000 0x1 0x0
+#define MX6Q_PAD_ENET_TXD1__ESAI1_TX2_RX3		0x1ec 0x500 0x87c 0x2 0x0
+#define MX6Q_PAD_ENET_TXD1__ENET_1588_EVENT0_IN		0x1ec 0x500 0x000 0x4 0x0
+#define MX6Q_PAD_ENET_TXD1__GPIO_1_29			0x1ec 0x500 0x000 0x5 0x0
+#define MX6Q_PAD_ENET_TXD1__SATA_PHY_TDO		0x1ec 0x500 0x000 0x6 0x0
+#define MX6Q_PAD_ENET_TXD1__USBPHY2_RX_HS_RXD		0x1ec 0x500 0x000 0x7 0x0
+#define MX6Q_PAD_ENET_TXD0__RESERVED_RSRVED		0x1f0 0x504 0x000 0x0 0x0
+#define MX6Q_PAD_ENET_TXD0__ENET_TDATA_0		0x1f0 0x504 0x000 0x1 0x0
+#define MX6Q_PAD_ENET_TXD0__ESAI1_TX4_RX1		0x1f0 0x504 0x884 0x2 0x0
+#define MX6Q_PAD_ENET_TXD0__GPIO_1_30			0x1f0 0x504 0x000 0x5 0x0
+#define MX6Q_PAD_ENET_TXD0__SATA_PHY_TCK		0x1f0 0x504 0x000 0x6 0x0
+#define MX6Q_PAD_ENET_TXD0__USBPHY2_RX_FS_RXD		0x1f0 0x504 0x000 0x7 0x0
+#define MX6Q_PAD_ENET_MDC__MLB_MLBDAT			0x1f4 0x508 0x904 0x0 0x0
+#define MX6Q_PAD_ENET_MDC__ENET_MDC			0x1f4 0x508 0x000 0x1 0x0
+#define MX6Q_PAD_ENET_MDC__ESAI1_TX5_RX0		0x1f4 0x508 0x888 0x2 0x0
+#define MX6Q_PAD_ENET_MDC__ENET_1588_EVENT1_IN		0x1f4 0x508 0x000 0x4 0x0
+#define MX6Q_PAD_ENET_MDC__GPIO_1_31			0x1f4 0x508 0x000 0x5 0x0
+#define MX6Q_PAD_ENET_MDC__SATA_PHY_TMS			0x1f4 0x508 0x000 0x6 0x0
+#define MX6Q_PAD_ENET_MDC__USBPHY2_RX_DISCON		0x1f4 0x508 0x000 0x7 0x0
+#define MX6Q_PAD_DRAM_SDQS5__MMDC_DRAM_SDQS_5		0x000 0x50c 0x000 0x0 0x0
+#define MX6Q_PAD_DRAM_DQM5__MMDC_DRAM_DQM_5		0x000 0x510 0x000 0x0 0x0
+#define MX6Q_PAD_DRAM_DQM4__MMDC_DRAM_DQM_4		0x000 0x514 0x000 0x0 0x0
+#define MX6Q_PAD_DRAM_SDQS4__MMDC_DRAM_SDQS_4		0x000 0x518 0x000 0x0 0x0
+#define MX6Q_PAD_DRAM_SDQS3__MMDC_DRAM_SDQS_3		0x000 0x51c 0x000 0x0 0x0
+#define MX6Q_PAD_DRAM_DQM3__MMDC_DRAM_DQM_3		0x000 0x520 0x000 0x0 0x0
+#define MX6Q_PAD_DRAM_SDQS2__MMDC_DRAM_SDQS_2		0x000 0x524 0x000 0x0 0x0
+#define MX6Q_PAD_DRAM_DQM2__MMDC_DRAM_DQM_2		0x000 0x528 0x000 0x0 0x0
+#define MX6Q_PAD_DRAM_A0__MMDC_DRAM_A_0			0x000 0x52c 0x000 0x0 0x0
+#define MX6Q_PAD_DRAM_A1__MMDC_DRAM_A_1			0x000 0x530 0x000 0x0 0x0
+#define MX6Q_PAD_DRAM_A2__MMDC_DRAM_A_2			0x000 0x534 0x000 0x0 0x0
+#define MX6Q_PAD_DRAM_A3__MMDC_DRAM_A_3			0x000 0x538 0x000 0x0 0x0
+#define MX6Q_PAD_DRAM_A4__MMDC_DRAM_A_4			0x000 0x53c 0x000 0x0 0x0
+#define MX6Q_PAD_DRAM_A5__MMDC_DRAM_A_5			0x000 0x540 0x000 0x0 0x0
+#define MX6Q_PAD_DRAM_A6__MMDC_DRAM_A_6			0x000 0x544 0x000 0x0 0x0
+#define MX6Q_PAD_DRAM_A7__MMDC_DRAM_A_7			0x000 0x548 0x000 0x0 0x0
+#define MX6Q_PAD_DRAM_A8__MMDC_DRAM_A_8			0x000 0x54c 0x000 0x0 0x0
+#define MX6Q_PAD_DRAM_A9__MMDC_DRAM_A_9			0x000 0x550 0x000 0x0 0x0
+#define MX6Q_PAD_DRAM_A10__MMDC_DRAM_A_10		0x000 0x554 0x000 0x0 0x0
+#define MX6Q_PAD_DRAM_A11__MMDC_DRAM_A_11		0x000 0x558 0x000 0x0 0x0
+#define MX6Q_PAD_DRAM_A12__MMDC_DRAM_A_12		0x000 0x55c 0x000 0x0 0x0
+#define MX6Q_PAD_DRAM_A13__MMDC_DRAM_A_13		0x000 0x560 0x000 0x0 0x0
+#define MX6Q_PAD_DRAM_A14__MMDC_DRAM_A_14		0x000 0x564 0x000 0x0 0x0
+#define MX6Q_PAD_DRAM_A15__MMDC_DRAM_A_15		0x000 0x568 0x000 0x0 0x0
+#define MX6Q_PAD_DRAM_CAS__MMDC_DRAM_CAS		0x000 0x56c 0x000 0x0 0x0
+#define MX6Q_PAD_DRAM_CS0__MMDC_DRAM_CS_0		0x000 0x570 0x000 0x0 0x0
+#define MX6Q_PAD_DRAM_CS1__MMDC_DRAM_CS_1		0x000 0x574 0x000 0x0 0x0
+#define MX6Q_PAD_DRAM_RAS__MMDC_DRAM_RAS		0x000 0x578 0x000 0x0 0x0
+#define MX6Q_PAD_DRAM_RESET__MMDC_DRAM_RESET		0x000 0x57c 0x000 0x0 0x0
+#define MX6Q_PAD_DRAM_SDBA0__MMDC_DRAM_SDBA_0		0x000 0x580 0x000 0x0 0x0
+#define MX6Q_PAD_DRAM_SDBA1__MMDC_DRAM_SDBA_1		0x000 0x584 0x000 0x0 0x0
+#define MX6Q_PAD_DRAM_SDCLK_0__MMDC_DRAM_SDCLK0		0x000 0x588 0x000 0x0 0x0
+#define MX6Q_PAD_DRAM_SDBA2__MMDC_DRAM_SDBA_2		0x000 0x58c 0x000 0x0 0x0
+#define MX6Q_PAD_DRAM_SDCKE0__MMDC_DRAM_SDCKE_0		0x000 0x590 0x000 0x0 0x0
+#define MX6Q_PAD_DRAM_SDCLK_1__MMDC_DRAM_SDCLK1		0x000 0x594 0x000 0x0 0x0
+#define MX6Q_PAD_DRAM_SDCKE1__MMDC_DRAM_SDCKE_1		0x000 0x598 0x000 0x0 0x0
+#define MX6Q_PAD_DRAM_SDODT0__MMDC_DRAM_ODT_0		0x000 0x59c 0x000 0x0 0x0
+#define MX6Q_PAD_DRAM_SDODT1__MMDC_DRAM_ODT_1		0x000 0x5a0 0x000 0x0 0x0
+#define MX6Q_PAD_DRAM_SDWE__MMDC_DRAM_SDWE		0x000 0x5a4 0x000 0x0 0x0
+#define MX6Q_PAD_DRAM_SDQS0__MMDC_DRAM_SDQS_0		0x000 0x5a8 0x000 0x0 0x0
+#define MX6Q_PAD_DRAM_DQM0__MMDC_DRAM_DQM_0		0x000 0x5ac 0x000 0x0 0x0
+#define MX6Q_PAD_DRAM_SDQS1__MMDC_DRAM_SDQS_1		0x000 0x5b0 0x000 0x0 0x0
+#define MX6Q_PAD_DRAM_DQM1__MMDC_DRAM_DQM_1		0x000 0x5b4 0x000 0x0 0x0
+#define MX6Q_PAD_DRAM_SDQS6__MMDC_DRAM_SDQS_6		0x000 0x5b8 0x000 0x0 0x0
+#define MX6Q_PAD_DRAM_DQM6__MMDC_DRAM_DQM_6		0x000 0x5bc 0x000 0x0 0x0
+#define MX6Q_PAD_DRAM_SDQS7__MMDC_DRAM_SDQS_7		0x000 0x5c0 0x000 0x0 0x0
+#define MX6Q_PAD_DRAM_DQM7__MMDC_DRAM_DQM_7		0x000 0x5c4 0x000 0x0 0x0
+#define MX6Q_PAD_KEY_COL0__ECSPI1_SCLK			0x1f8 0x5c8 0x7f4 0x0 0x2
+#define MX6Q_PAD_KEY_COL0__ENET_RDATA_3			0x1f8 0x5c8 0x854 0x1 0x1
+#define MX6Q_PAD_KEY_COL0__AUDMUX_AUD5_TXC		0x1f8 0x5c8 0x7dc 0x2 0x1
+#define MX6Q_PAD_KEY_COL0__KPP_COL_0			0x1f8 0x5c8 0x000 0x3 0x0
+#define MX6Q_PAD_KEY_COL0__UART4_TXD			0x1f8 0x5c8 0x000 0x4 0x0
+#define MX6Q_PAD_KEY_COL0__GPIO_4_6			0x1f8 0x5c8 0x000 0x5 0x0
+#define MX6Q_PAD_KEY_COL0__DCIC1_DCIC_OUT		0x1f8 0x5c8 0x000 0x6 0x0
+#define MX6Q_PAD_KEY_COL0__SRC_ANY_PU_RST		0x1f8 0x5c8 0x000 0x7 0x0
+#define MX6Q_PAD_KEY_ROW0__ECSPI1_MOSI			0x1fc 0x5cc 0x7fc 0x0 0x2
+#define MX6Q_PAD_KEY_ROW0__ENET_TDATA_3			0x1fc 0x5cc 0x000 0x1 0x0
+#define MX6Q_PAD_KEY_ROW0__AUDMUX_AUD5_TXD		0x1fc 0x5cc 0x7d0 0x2 0x1
+#define MX6Q_PAD_KEY_ROW0__KPP_ROW_0			0x1fc 0x5cc 0x000 0x3 0x0
+#define MX6Q_PAD_KEY_ROW0__UART4_RXD			0x1fc 0x5cc 0x938 0x4 0x1
+#define MX6Q_PAD_KEY_ROW0__GPIO_4_7			0x1fc 0x5cc 0x000 0x5 0x0
+#define MX6Q_PAD_KEY_ROW0__DCIC2_DCIC_OUT		0x1fc 0x5cc 0x000 0x6 0x0
+#define MX6Q_PAD_KEY_ROW0__PL301_PER1_HADR_0		0x1fc 0x5cc 0x000 0x7 0x0
+#define MX6Q_PAD_KEY_COL1__ECSPI1_MISO			0x200 0x5d0 0x7f8 0x0 0x2
+#define MX6Q_PAD_KEY_COL1__ENET_MDIO			0x200 0x5d0 0x840 0x1 0x1
+#define MX6Q_PAD_KEY_COL1__AUDMUX_AUD5_TXFS		0x200 0x5d0 0x7e0 0x2 0x1
+#define MX6Q_PAD_KEY_COL1__KPP_COL_1			0x200 0x5d0 0x000 0x3 0x0
+#define MX6Q_PAD_KEY_COL1__UART5_TXD			0x200 0x5d0 0x000 0x4 0x0
+#define MX6Q_PAD_KEY_COL1__GPIO_4_8			0x200 0x5d0 0x000 0x5 0x0
+#define MX6Q_PAD_KEY_COL1__USDHC1_VSELECT		0x200 0x5d0 0x000 0x6 0x0
+#define MX6Q_PAD_KEY_COL1__PL301MX_PER1_HADR_1		0x200 0x5d0 0x000 0x7 0x0
+#define MX6Q_PAD_KEY_ROW1__ECSPI1_SS0			0x204 0x5d4 0x800 0x0 0x2
+#define MX6Q_PAD_KEY_ROW1__ENET_COL			0x204 0x5d4 0x000 0x1 0x0
+#define MX6Q_PAD_KEY_ROW1__AUDMUX_AUD5_RXD		0x204 0x5d4 0x7cc 0x2 0x1
+#define MX6Q_PAD_KEY_ROW1__KPP_ROW_1			0x204 0x5d4 0x000 0x3 0x0
+#define MX6Q_PAD_KEY_ROW1__UART5_RXD			0x204 0x5d4 0x940 0x4 0x1
+#define MX6Q_PAD_KEY_ROW1__GPIO_4_9			0x204 0x5d4 0x000 0x5 0x0
+#define MX6Q_PAD_KEY_ROW1__USDHC2_VSELECT		0x204 0x5d4 0x000 0x6 0x0
+#define MX6Q_PAD_KEY_ROW1__PL301_PER1_HADDR_2		0x204 0x5d4 0x000 0x7 0x0
+#define MX6Q_PAD_KEY_COL2__ECSPI1_SS1			0x208 0x5d8 0x804 0x0 0x2
+#define MX6Q_PAD_KEY_COL2__ENET_RDATA_2			0x208 0x5d8 0x850 0x1 0x1
+#define MX6Q_PAD_KEY_COL2__CAN1_TXCAN			0x208 0x5d8 0x000 0x2 0x0
+#define MX6Q_PAD_KEY_COL2__KPP_COL_2			0x208 0x5d8 0x000 0x3 0x0
+#define MX6Q_PAD_KEY_COL2__ENET_MDC			0x208 0x5d8 0x000 0x4 0x0
+#define MX6Q_PAD_KEY_COL2__GPIO_4_10			0x208 0x5d8 0x000 0x5 0x0
+#define MX6Q_PAD_KEY_COL2__USBOH3_H1_PWRCTL_WKP		0x208 0x5d8 0x000 0x6 0x0
+#define MX6Q_PAD_KEY_COL2__PL301_PER1_HADDR_3		0x208 0x5d8 0x000 0x7 0x0
+#define MX6Q_PAD_KEY_ROW2__ECSPI1_SS2			0x20c 0x5dc 0x808 0x0 0x1
+#define MX6Q_PAD_KEY_ROW2__ENET_TDATA_2			0x20c 0x5dc 0x000 0x1 0x0
+#define MX6Q_PAD_KEY_ROW2__CAN1_RXCAN			0x20c 0x5dc 0x7e4 0x2 0x0
+#define MX6Q_PAD_KEY_ROW2__KPP_ROW_2			0x20c 0x5dc 0x000 0x3 0x0
+#define MX6Q_PAD_KEY_ROW2__USDHC2_VSELECT		0x20c 0x5dc 0x000 0x4 0x0
+#define MX6Q_PAD_KEY_ROW2__GPIO_4_11			0x20c 0x5dc 0x000 0x5 0x0
+#define MX6Q_PAD_KEY_ROW2__HDMI_TX_CEC_LINE		0x20c 0x5dc 0x88c 0x6 0x1
+#define MX6Q_PAD_KEY_ROW2__PL301_PER1_HADR_4		0x20c 0x5dc 0x000 0x7 0x0
+#define MX6Q_PAD_KEY_COL3__ECSPI1_SS3			0x210 0x5e0 0x80c 0x0 0x1
+#define MX6Q_PAD_KEY_COL3__ENET_CRS			0x210 0x5e0 0x000 0x1 0x0
+#define MX6Q_PAD_KEY_COL3__HDMI_TX_DDC_SCL		0x210 0x5e0 0x890 0x2 0x1
+#define MX6Q_PAD_KEY_COL3__KPP_COL_3			0x210 0x5e0 0x000 0x3 0x0
+#define MX6Q_PAD_KEY_COL3__I2C2_SCL			0x210 0x5e0 0x8a0 0x4 0x1
+#define MX6Q_PAD_KEY_COL3__GPIO_4_12			0x210 0x5e0 0x000 0x5 0x0
+#define MX6Q_PAD_KEY_COL3__SPDIF_IN1			0x210 0x5e0 0x914 0x6 0x2
+#define MX6Q_PAD_KEY_COL3__PL301_PER1_HADR_5		0x210 0x5e0 0x000 0x7 0x0
+#define MX6Q_PAD_KEY_ROW3__OSC32K_32K_OUT		0x214 0x5e4 0x000 0x0 0x0
+#define MX6Q_PAD_KEY_ROW3__ASRC_ASRC_EXT_CLK		0x214 0x5e4 0x7b0 0x1 0x0
+#define MX6Q_PAD_KEY_ROW3__HDMI_TX_DDC_SDA		0x214 0x5e4 0x894 0x2 0x1
+#define MX6Q_PAD_KEY_ROW3__KPP_ROW_3			0x214 0x5e4 0x000 0x3 0x0
+#define MX6Q_PAD_KEY_ROW3__I2C2_SDA			0x214 0x5e4 0x8a4 0x4 0x1
+#define MX6Q_PAD_KEY_ROW3__GPIO_4_13			0x214 0x5e4 0x000 0x5 0x0
+#define MX6Q_PAD_KEY_ROW3__USDHC1_VSELECT		0x214 0x5e4 0x000 0x6 0x0
+#define MX6Q_PAD_KEY_ROW3__PL301_PER1_HADR_6		0x214 0x5e4 0x000 0x7 0x0
+#define MX6Q_PAD_KEY_COL4__CAN2_TXCAN			0x218 0x5e8 0x000 0x0 0x0
+#define MX6Q_PAD_KEY_COL4__IPU1_SISG_4			0x218 0x5e8 0x000 0x1 0x0
+#define MX6Q_PAD_KEY_COL4__USBOH3_USBOTG_OC		0x218 0x5e8 0x944 0x2 0x1
+#define MX6Q_PAD_KEY_COL4__KPP_COL_4			0x218 0x5e8 0x000 0x3 0x0
+#define MX6Q_PAD_KEY_COL4__UART5_RTS			0x218 0x5e8 0x93c 0x4 0x0
+#define MX6Q_PAD_KEY_COL4__GPIO_4_14			0x218 0x5e8 0x000 0x5 0x0
+#define MX6Q_PAD_KEY_COL4__MMDC_DEBUG_49		0x218 0x5e8 0x000 0x6 0x0
+#define MX6Q_PAD_KEY_COL4__PL301_PER1_HADDR_7		0x218 0x5e8 0x000 0x7 0x0
+#define MX6Q_PAD_KEY_ROW4__CAN2_RXCAN			0x21c 0x5ec 0x7e8 0x0 0x0
+#define MX6Q_PAD_KEY_ROW4__IPU1_SISG_5			0x21c 0x5ec 0x000 0x1 0x0
+#define MX6Q_PAD_KEY_ROW4__USBOH3_USBOTG_PWR		0x21c 0x5ec 0x000 0x2 0x0
+#define MX6Q_PAD_KEY_ROW4__KPP_ROW_4			0x21c 0x5ec 0x000 0x3 0x0
+#define MX6Q_PAD_KEY_ROW4__UART5_CTS			0x21c 0x5ec 0x93c 0x4 0x1
+#define MX6Q_PAD_KEY_ROW4__GPIO_4_15			0x21c 0x5ec 0x000 0x5 0x0
+#define MX6Q_PAD_KEY_ROW4__MMDC_DEBUG_50		0x21c 0x5ec 0x000 0x6 0x0
+#define MX6Q_PAD_KEY_ROW4__PL301_PER1_HADR_8		0x21c 0x5ec 0x000 0x7 0x0
+#define MX6Q_PAD_GPIO_0__CCM_CLKO			0x220 0x5f0 0x000 0x0 0x0
+#define MX6Q_PAD_GPIO_0__KPP_COL_5			0x220 0x5f0 0x8e8 0x2 0x0
+#define MX6Q_PAD_GPIO_0__ASRC_ASRC_EXT_CLK		0x220 0x5f0 0x7b0 0x3 0x1
+#define MX6Q_PAD_GPIO_0__EPIT1_EPITO			0x220 0x5f0 0x000 0x4 0x0
+#define MX6Q_PAD_GPIO_0__GPIO_1_0			0x220 0x5f0 0x000 0x5 0x0
+#define MX6Q_PAD_GPIO_0__USBOH3_USBH1_PWR		0x220 0x5f0 0x000 0x6 0x0
+#define MX6Q_PAD_GPIO_0__SNVS_HP_WRAP_SNVS_VIO5		0x220 0x5f0 0x000 0x7 0x0
+#define MX6Q_PAD_GPIO_1__ESAI1_SCKR			0x224 0x5f4 0x86c 0x0 0x1
+#define MX6Q_PAD_GPIO_1__WDOG2_WDOG_B			0x224 0x5f4 0x000 0x1 0x0
+#define MX6Q_PAD_GPIO_1__KPP_ROW_5			0x224 0x5f4 0x8f4 0x2 0x0
+#define MX6Q_PAD_GPIO_1__PWM2_PWMO			0x224 0x5f4 0x000 0x4 0x0
+#define MX6Q_PAD_GPIO_1__GPIO_1_1			0x224 0x5f4 0x000 0x5 0x0
+#define MX6Q_PAD_GPIO_1__USDHC1_CD			0x224 0x5f4 0x000 0x6 0x0
+#define MX6Q_PAD_GPIO_1__SRC_TESTER_ACK			0x224 0x5f4 0x000 0x7 0x0
+#define MX6Q_PAD_GPIO_9__ESAI1_FSR			0x228 0x5f8 0x85c 0x0 0x1
+#define MX6Q_PAD_GPIO_9__WDOG1_WDOG_B			0x228 0x5f8 0x000 0x1 0x0
+#define MX6Q_PAD_GPIO_9__KPP_COL_6			0x228 0x5f8 0x8ec 0x2 0x0
+#define MX6Q_PAD_GPIO_9__CCM_REF_EN_B			0x228 0x5f8 0x000 0x3 0x0
+#define MX6Q_PAD_GPIO_9__PWM1_PWMO			0x228 0x5f8 0x000 0x4 0x0
+#define MX6Q_PAD_GPIO_9__GPIO_1_9			0x228 0x5f8 0x000 0x5 0x0
+#define MX6Q_PAD_GPIO_9__USDHC1_WP			0x228 0x5f8 0x94c 0x6 0x1
+#define MX6Q_PAD_GPIO_9__SRC_EARLY_RST			0x228 0x5f8 0x000 0x7 0x0
+#define MX6Q_PAD_GPIO_3__ESAI1_HCKR			0x22c 0x5fc 0x864 0x0 0x1
+#define MX6Q_PAD_GPIO_3__OBSERVE_MUX_INT_OUT0		0x22c 0x5fc 0x000 0x1 0x0
+#define MX6Q_PAD_GPIO_3__I2C3_SCL			0x22c 0x5fc 0x8a8 0x2 0x1
+#define MX6Q_PAD_GPIO_3__ANATOP_24M_OUT			0x22c 0x5fc 0x000 0x3 0x0
+#define MX6Q_PAD_GPIO_3__CCM_CLKO2			0x22c 0x5fc 0x000 0x4 0x0
+#define MX6Q_PAD_GPIO_3__GPIO_1_3			0x22c 0x5fc 0x000 0x5 0x0
+#define MX6Q_PAD_GPIO_3__USBOH3_USBH1_OC		0x22c 0x5fc 0x948 0x6 0x1
+#define MX6Q_PAD_GPIO_3__MLB_MLBCLK			0x22c 0x5fc 0x900 0x7 0x1
+#define MX6Q_PAD_GPIO_6__ESAI1_SCKT			0x230 0x600 0x870 0x0 0x1
+#define MX6Q_PAD_GPIO_6__OBSERVE_MUX_INT_OUT1		0x230 0x600 0x000 0x1 0x0
+#define MX6Q_PAD_GPIO_6__I2C3_SDA			0x230 0x600 0x8ac 0x2 0x1
+#define MX6Q_PAD_GPIO_6__CCM_CCM_OUT_0			0x230 0x600 0x000 0x3 0x0
+#define MX6Q_PAD_GPIO_6__CSU_CSU_INT_DEB		0x230 0x600 0x000 0x4 0x0
+#define MX6Q_PAD_GPIO_6__GPIO_1_6			0x230 0x600 0x000 0x5 0x0
+#define MX6Q_PAD_GPIO_6__USDHC2_LCTL			0x230 0x600 0x000 0x6 0x0
+#define MX6Q_PAD_GPIO_6__MLB_MLBSIG			0x230 0x600 0x908 0x7 0x1
+#define MX6Q_PAD_GPIO_2__ESAI1_FST			0x234 0x604 0x860 0x0 0x1
+#define MX6Q_PAD_GPIO_2__OBSERVE_MUX_INT_OUT2		0x234 0x604 0x000 0x1 0x0
+#define MX6Q_PAD_GPIO_2__KPP_ROW_6			0x234 0x604 0x8f8 0x2 0x1
+#define MX6Q_PAD_GPIO_2__CCM_CCM_OUT_1			0x234 0x604 0x000 0x3 0x0
+#define MX6Q_PAD_GPIO_2__CSU_CSU_ALARM_AUT_0		0x234 0x604 0x000 0x4 0x0
+#define MX6Q_PAD_GPIO_2__GPIO_1_2			0x234 0x604 0x000 0x5 0x0
+#define MX6Q_PAD_GPIO_2__USDHC2_WP			0x234 0x604 0x000 0x6 0x0
+#define MX6Q_PAD_GPIO_2__MLB_MLBDAT			0x234 0x604 0x904 0x7 0x1
+#define MX6Q_PAD_GPIO_4__ESAI1_HCKT			0x238 0x608 0x868 0x0 0x1
+#define MX6Q_PAD_GPIO_4__OBSERVE_MUX_INT_OUT3		0x238 0x608 0x000 0x1 0x0
+#define MX6Q_PAD_GPIO_4__KPP_COL_7			0x238 0x608 0x8f0 0x2 0x1
+#define MX6Q_PAD_GPIO_4__CCM_CCM_OUT_2			0x238 0x608 0x000 0x3 0x0
+#define MX6Q_PAD_GPIO_4__CSU_CSU_ALARM_AUT_1		0x238 0x608 0x000 0x4 0x0
+#define MX6Q_PAD_GPIO_4__GPIO_1_4			0x238 0x608 0x000 0x5 0x0
+#define MX6Q_PAD_GPIO_4__USDHC2_CD			0x238 0x608 0x000 0x6 0x0
+#define MX6Q_PAD_GPIO_4__OCOTP_CRL_WRAR_FUSE_LA		0x238 0x608 0x000 0x7 0x0
+#define MX6Q_PAD_GPIO_5__ESAI1_TX2_RX3			0x23c 0x60c 0x87c 0x0 0x1
+#define MX6Q_PAD_GPIO_5__OBSERVE_MUX_INT_OUT4		0x23c 0x60c 0x000 0x1 0x0
+#define MX6Q_PAD_GPIO_5__KPP_ROW_7			0x23c 0x60c 0x8fc 0x2 0x1
+#define MX6Q_PAD_GPIO_5__CCM_CLKO			0x23c 0x60c 0x000 0x3 0x0
+#define MX6Q_PAD_GPIO_5__CSU_CSU_ALARM_AUT_2		0x23c 0x60c 0x000 0x4 0x0
+#define MX6Q_PAD_GPIO_5__GPIO_1_5			0x23c 0x60c 0x000 0x5 0x0
+#define MX6Q_PAD_GPIO_5__I2C3_SCL			0x23c 0x60c 0x8a8 0x6 0x2
+#define MX6Q_PAD_GPIO_5__CHEETAH_EVENTI			0x23c 0x60c 0x000 0x7 0x0
+#define MX6Q_PAD_GPIO_7__ESAI1_TX4_RX1			0x240 0x610 0x884 0x0 0x1
+#define MX6Q_PAD_GPIO_7__ECSPI5_RDY			0x240 0x610 0x000 0x1 0x0
+#define MX6Q_PAD_GPIO_7__EPIT1_EPITO			0x240 0x610 0x000 0x2 0x0
+#define MX6Q_PAD_GPIO_7__CAN1_TXCAN			0x240 0x610 0x000 0x3 0x0
+#define MX6Q_PAD_GPIO_7__UART2_TXD			0x240 0x610 0x000 0x4 0x0
+#define MX6Q_PAD_GPIO_7__GPIO_1_7			0x240 0x610 0x000 0x5 0x0
+#define MX6Q_PAD_GPIO_7__SPDIF_PLOCK			0x240 0x610 0x000 0x6 0x0
+#define MX6Q_PAD_GPIO_7__USBOH3_OTGUSB_HST_MODE		0x240 0x610 0x000 0x7 0x0
+#define MX6Q_PAD_GPIO_8__ESAI1_TX5_RX0			0x244 0x614 0x888 0x0 0x1
+#define MX6Q_PAD_GPIO_8__ANATOP_ANATOP_32K_OUT		0x244 0x614 0x000 0x1 0x0
+#define MX6Q_PAD_GPIO_8__EPIT2_EPITO			0x244 0x614 0x000 0x2 0x0
+#define MX6Q_PAD_GPIO_8__CAN1_RXCAN			0x244 0x614 0x7e4 0x3 0x1
+#define MX6Q_PAD_GPIO_8__UART2_RXD			0x244 0x614 0x928 0x4 0x3
+#define MX6Q_PAD_GPIO_8__GPIO_1_8			0x244 0x614 0x000 0x5 0x0
+#define MX6Q_PAD_GPIO_8__SPDIF_SRCLK			0x244 0x614 0x000 0x6 0x0
+#define MX6Q_PAD_GPIO_8__USBOH3_OTG_PWRCTL_WAK		0x244 0x614 0x000 0x7 0x0
+#define MX6Q_PAD_GPIO_16__ESAI1_TX3_RX2			0x248 0x618 0x880 0x0 0x1
+#define MX6Q_PAD_GPIO_16__ENET_1588_EVENT2_IN		0x248 0x618 0x000 0x1 0x0
+#define MX6Q_PAD_GPIO_16__ENET_ETHERNET_REF_OUT		0x248 0x618 0x83c 0x2 0x1
+#define MX6Q_PAD_GPIO_16__USDHC1_LCTL			0x248 0x618 0x000 0x3 0x0
+#define MX6Q_PAD_GPIO_16__SPDIF_IN1			0x248 0x618 0x914 0x4 0x3
+#define MX6Q_PAD_GPIO_16__GPIO_7_11			0x248 0x618 0x000 0x5 0x0
+#define MX6Q_PAD_GPIO_16__I2C3_SDA			0x248 0x618 0x8ac 0x6 0x2
+#define MX6Q_PAD_GPIO_16__SJC_DE_B			0x248 0x618 0x000 0x7 0x0
+#define MX6Q_PAD_GPIO_17__ESAI1_TX0			0x24c 0x61c 0x874 0x0 0x0
+#define MX6Q_PAD_GPIO_17__ENET_1588_EVENT3_IN		0x24c 0x61c 0x000 0x1 0x0
+#define MX6Q_PAD_GPIO_17__CCM_PMIC_RDY			0x24c 0x61c 0x7f0 0x2 0x1
+#define MX6Q_PAD_GPIO_17__SDMA_SDMA_EXT_EVENT_0		0x24c 0x61c 0x90c 0x3 0x1
+#define MX6Q_PAD_GPIO_17__SPDIF_OUT1			0x24c 0x61c 0x000 0x4 0x0
+#define MX6Q_PAD_GPIO_17__GPIO_7_12			0x24c 0x61c 0x000 0x5 0x0
+#define MX6Q_PAD_GPIO_17__SJC_JTAG_ACT			0x24c 0x61c 0x000 0x7 0x0
+#define MX6Q_PAD_GPIO_18__ESAI1_TX1			0x250 0x620 0x878 0x0 0x0
+#define MX6Q_PAD_GPIO_18__ENET_RX_CLK			0x250 0x620 0x844 0x1 0x1
+#define MX6Q_PAD_GPIO_18__USDHC3_VSELECT		0x250 0x620 0x000 0x2 0x0
+#define MX6Q_PAD_GPIO_18__SDMA_SDMA_EXT_EVENT_1		0x250 0x620 0x910 0x3 0x1
+#define MX6Q_PAD_GPIO_18__ASRC_ASRC_EXT_CLK		0x250 0x620 0x7b0 0x4 0x2
+#define MX6Q_PAD_GPIO_18__GPIO_7_13			0x250 0x620 0x000 0x5 0x0
+#define MX6Q_PAD_GPIO_18__SNVS_HP_WRA_SNVS_VIO5		0x250 0x620 0x000 0x6 0x0
+#define MX6Q_PAD_GPIO_18__SRC_SYSTEM_RST		0x250 0x620 0x000 0x7 0x0
+#define MX6Q_PAD_GPIO_19__KPP_COL_5			0x254 0x624 0x8e8 0x0 0x1
+#define MX6Q_PAD_GPIO_19__ENET_1588_EVENT0_OUT		0x254 0x624 0x000 0x1 0x0
+#define MX6Q_PAD_GPIO_19__SPDIF_OUT1			0x254 0x624 0x000 0x2 0x0
+#define MX6Q_PAD_GPIO_19__CCM_CLKO			0x254 0x624 0x000 0x3 0x0
+#define MX6Q_PAD_GPIO_19__ECSPI1_RDY			0x254 0x624 0x000 0x4 0x0
+#define MX6Q_PAD_GPIO_19__GPIO_4_5			0x254 0x624 0x000 0x5 0x0
+#define MX6Q_PAD_GPIO_19__ENET_TX_ER			0x254 0x624 0x000 0x6 0x0
+#define MX6Q_PAD_GPIO_19__SRC_INT_BOOT			0x254 0x624 0x000 0x7 0x0
+#define MX6Q_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK		0x258 0x628 0x000 0x0 0x0
+#define MX6Q_PAD_CSI0_PIXCLK__PCIE_CTRL_MUX_12		0x258 0x628 0x000 0x2 0x0
+#define MX6Q_PAD_CSI0_PIXCLK__SDMA_DEBUG_PC_0		0x258 0x628 0x000 0x4 0x0
+#define MX6Q_PAD_CSI0_PIXCLK__GPIO_5_18			0x258 0x628 0x000 0x5 0x0
+#define MX6Q_PAD_CSI0_PIXCLK___MMDC_DEBUG_29		0x258 0x628 0x000 0x6 0x0
+#define MX6Q_PAD_CSI0_PIXCLK__CHEETAH_EVENTO		0x258 0x628 0x000 0x7 0x0
+#define MX6Q_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC		0x25c 0x62c 0x000 0x0 0x0
+#define MX6Q_PAD_CSI0_MCLK__PCIE_CTRL_MUX_13		0x25c 0x62c 0x000 0x2 0x0
+#define MX6Q_PAD_CSI0_MCLK__CCM_CLKO			0x25c 0x62c 0x000 0x3 0x0
+#define MX6Q_PAD_CSI0_MCLK__SDMA_DEBUG_PC_1		0x25c 0x62c 0x000 0x4 0x0
+#define MX6Q_PAD_CSI0_MCLK__GPIO_5_19			0x25c 0x62c 0x000 0x5 0x0
+#define MX6Q_PAD_CSI0_MCLK__MMDC_MMDC_DEBUG_30		0x25c 0x62c 0x000 0x6 0x0
+#define MX6Q_PAD_CSI0_MCLK__CHEETAH_TRCTL		0x25c 0x62c 0x000 0x7 0x0
+#define MX6Q_PAD_CSI0_DATA_EN__IPU1_CSI0_DA_EN		0x260 0x630 0x000 0x0 0x0
+#define MX6Q_PAD_CSI0_DATA_EN__WEIM_WEIM_D_0		0x260 0x630 0x000 0x1 0x0
+#define MX6Q_PAD_CSI0_DATA_EN__PCIE_CTRL_MUX_14		0x260 0x630 0x000 0x2 0x0
+#define MX6Q_PAD_CSI0_DATA_EN__SDMA_DEBUG_PC_2		0x260 0x630 0x000 0x4 0x0
+#define MX6Q_PAD_CSI0_DATA_EN__GPIO_5_20		0x260 0x630 0x000 0x5 0x0
+#define MX6Q_PAD_CSI0_DATA_EN__MMDC_DEBUG_31		0x260 0x630 0x000 0x6 0x0
+#define MX6Q_PAD_CSI0_DATA_EN__CHEETAH_TRCLK		0x260 0x630 0x000 0x7 0x0
+#define MX6Q_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC		0x264 0x634 0x000 0x0 0x0
+#define MX6Q_PAD_CSI0_VSYNC__WEIM_WEIM_D_1		0x264 0x634 0x000 0x1 0x0
+#define MX6Q_PAD_CSI0_VSYNC__PCIE_CTRL_MUX_15		0x264 0x634 0x000 0x2 0x0
+#define MX6Q_PAD_CSI0_VSYNC__SDMA_DEBUG_PC_3		0x264 0x634 0x000 0x4 0x0
+#define MX6Q_PAD_CSI0_VSYNC__GPIO_5_21			0x264 0x634 0x000 0x5 0x0
+#define MX6Q_PAD_CSI0_VSYNC__MMDC_DEBUG_32		0x264 0x634 0x000 0x6 0x0
+#define MX6Q_PAD_CSI0_VSYNC__CHEETAH_TRACE_0		0x264 0x634 0x000 0x7 0x0
+#define MX6Q_PAD_CSI0_DAT4__IPU1_CSI0_D_4		0x268 0x638 0x000 0x0 0x0
+#define MX6Q_PAD_CSI0_DAT4__WEIM_WEIM_D_2		0x268 0x638 0x000 0x1 0x0
+#define MX6Q_PAD_CSI0_DAT4__ECSPI1_SCLK			0x268 0x638 0x7f4 0x2 0x3
+#define MX6Q_PAD_CSI0_DAT4__KPP_COL_5			0x268 0x638 0x8e8 0x3 0x2
+#define MX6Q_PAD_CSI0_DAT4__AUDMUX_AUD3_TXC		0x268 0x638 0x000 0x4 0x0
+#define MX6Q_PAD_CSI0_DAT4__GPIO_5_22			0x268 0x638 0x000 0x5 0x0
+#define MX6Q_PAD_CSI0_DAT4__MMDC_DEBUG_43		0x268 0x638 0x000 0x6 0x0
+#define MX6Q_PAD_CSI0_DAT4__CHEETAH_TRACE_1		0x268 0x638 0x000 0x7 0x0
+#define MX6Q_PAD_CSI0_DAT5__IPU1_CSI0_D_5		0x26c 0x63c 0x000 0x0 0x0
+#define MX6Q_PAD_CSI0_DAT5__WEIM_WEIM_D_3		0x26c 0x63c 0x000 0x1 0x0
+#define MX6Q_PAD_CSI0_DAT5__ECSPI1_MOSI			0x26c 0x63c 0x7fc 0x2 0x3
+#define MX6Q_PAD_CSI0_DAT5__KPP_ROW_5			0x26c 0x63c 0x8f4 0x3 0x1
+#define MX6Q_PAD_CSI0_DAT5__AUDMUX_AUD3_TXD		0x26c 0x63c 0x000 0x4 0x0
+#define MX6Q_PAD_CSI0_DAT5__GPIO_5_23			0x26c 0x63c 0x000 0x5 0x0
+#define MX6Q_PAD_CSI0_DAT5__MMDC_MMDC_DEBUG_44		0x26c 0x63c 0x000 0x6 0x0
+#define MX6Q_PAD_CSI0_DAT5__CHEETAH_TRACE_2		0x26c 0x63c 0x000 0x7 0x0
+#define MX6Q_PAD_CSI0_DAT6__IPU1_CSI0_D_6		0x270 0x640 0x000 0x0 0x0
+#define MX6Q_PAD_CSI0_DAT6__WEIM_WEIM_D_4		0x270 0x640 0x000 0x1 0x0
+#define MX6Q_PAD_CSI0_DAT6__ECSPI1_MISO			0x270 0x640 0x7f8 0x2 0x3
+#define MX6Q_PAD_CSI0_DAT6__KPP_COL_6			0x270 0x640 0x8ec 0x3 0x1
+#define MX6Q_PAD_CSI0_DAT6__AUDMUX_AUD3_TXFS		0x270 0x640 0x000 0x4 0x0
+#define MX6Q_PAD_CSI0_DAT6__GPIO_5_24			0x270 0x640 0x000 0x5 0x0
+#define MX6Q_PAD_CSI0_DAT6__MMDC_MMDC_DEBUG_45		0x270 0x640 0x000 0x6 0x0
+#define MX6Q_PAD_CSI0_DAT6__CHEETAH_TRACE_3		0x270 0x640 0x000 0x7 0x0
+#define MX6Q_PAD_CSI0_DAT7__IPU1_CSI0_D_7		0x274 0x644 0x000 0x0 0x0
+#define MX6Q_PAD_CSI0_DAT7__WEIM_WEIM_D_5		0x274 0x644 0x000 0x1 0x0
+#define MX6Q_PAD_CSI0_DAT7__ECSPI1_SS0			0x274 0x644 0x800 0x2 0x3
+#define MX6Q_PAD_CSI0_DAT7__KPP_ROW_6			0x274 0x644 0x8f8 0x3 0x2
+#define MX6Q_PAD_CSI0_DAT7__AUDMUX_AUD3_RXD		0x274 0x644 0x000 0x4 0x0
+#define MX6Q_PAD_CSI0_DAT7__GPIO_5_25			0x274 0x644 0x000 0x5 0x0
+#define MX6Q_PAD_CSI0_DAT7__MMDC_MMDC_DEBUG_46		0x274 0x644 0x000 0x6 0x0
+#define MX6Q_PAD_CSI0_DAT7__CHEETAH_TRACE_4		0x274 0x644 0x000 0x7 0x0
+#define MX6Q_PAD_CSI0_DAT8__IPU1_CSI0_D_8		0x278 0x648 0x000 0x0 0x0
+#define MX6Q_PAD_CSI0_DAT8__WEIM_WEIM_D_6		0x278 0x648 0x000 0x1 0x0
+#define MX6Q_PAD_CSI0_DAT8__ECSPI2_SCLK			0x278 0x648 0x810 0x2 0x2
+#define MX6Q_PAD_CSI0_DAT8__KPP_COL_7			0x278 0x648 0x8f0 0x3 0x2
+#define MX6Q_PAD_CSI0_DAT8__I2C1_SDA			0x278 0x648 0x89c 0x4 0x1
+#define MX6Q_PAD_CSI0_DAT8__GPIO_5_26			0x278 0x648 0x000 0x5 0x0
+#define MX6Q_PAD_CSI0_DAT8__MMDC_MMDC_DEBUG_47		0x278 0x648 0x000 0x6 0x0
+#define MX6Q_PAD_CSI0_DAT8__CHEETAH_TRACE_5		0x278 0x648 0x000 0x7 0x0
+#define MX6Q_PAD_CSI0_DAT9__IPU1_CSI0_D_9		0x27c 0x64c 0x000 0x0 0x0
+#define MX6Q_PAD_CSI0_DAT9__WEIM_WEIM_D_7		0x27c 0x64c 0x000 0x1 0x0
+#define MX6Q_PAD_CSI0_DAT9__ECSPI2_MOSI			0x27c 0x64c 0x818 0x2 0x2
+#define MX6Q_PAD_CSI0_DAT9__KPP_ROW_7			0x27c 0x64c 0x8fc 0x3 0x2
+#define MX6Q_PAD_CSI0_DAT9__I2C1_SCL			0x27c 0x64c 0x898 0x4 0x1
+#define MX6Q_PAD_CSI0_DAT9__GPIO_5_27			0x27c 0x64c 0x000 0x5 0x0
+#define MX6Q_PAD_CSI0_DAT9__MMDC_MMDC_DEBUG_48		0x27c 0x64c 0x000 0x6 0x0
+#define MX6Q_PAD_CSI0_DAT9__CHEETAH_TRACE_6		0x27c 0x64c 0x000 0x7 0x0
+#define MX6Q_PAD_CSI0_DAT10__IPU1_CSI0_D_10		0x280 0x650 0x000 0x0 0x0
+#define MX6Q_PAD_CSI0_DAT10__AUDMUX_AUD3_RXC		0x280 0x650 0x000 0x1 0x0
+#define MX6Q_PAD_CSI0_DAT10__ECSPI2_MISO		0x280 0x650 0x814 0x2 0x2
+#define MX6Q_PAD_CSI0_DAT10__UART1_TXD			0x280 0x650 0x000 0x3 0x0
+#define MX6Q_PAD_CSI0_DAT10__SDMA_DEBUG_PC_4		0x280 0x650 0x000 0x4 0x0
+#define MX6Q_PAD_CSI0_DAT10__GPIO_5_28			0x280 0x650 0x000 0x5 0x0
+#define MX6Q_PAD_CSI0_DAT10__MMDC_MMDC_DEBUG_33		0x280 0x650 0x000 0x6 0x0
+#define MX6Q_PAD_CSI0_DAT10__CHEETAH_TRACE_7		0x280 0x650 0x000 0x7 0x0
+#define MX6Q_PAD_CSI0_DAT11__IPU1_CSI0_D_11		0x284 0x654 0x000 0x0 0x0
+#define MX6Q_PAD_CSI0_DAT11__AUDMUX_AUD3_RXFS		0x284 0x654 0x000 0x1 0x0
+#define MX6Q_PAD_CSI0_DAT11__ECSPI2_SS0			0x284 0x654 0x81c 0x2 0x2
+#define MX6Q_PAD_CSI0_DAT11__UART1_RXD			0x284 0x654 0x920 0x3 0x1
+#define MX6Q_PAD_CSI0_DAT11__SDMA_DEBUG_PC_5		0x284 0x654 0x000 0x4 0x0
+#define MX6Q_PAD_CSI0_DAT11__GPIO_5_29			0x284 0x654 0x000 0x5 0x0
+#define MX6Q_PAD_CSI0_DAT11__MMDC_MMDC_DEBUG_34		0x284 0x654 0x000 0x6 0x0
+#define MX6Q_PAD_CSI0_DAT11__CHEETAH_TRACE_8		0x284 0x654 0x000 0x7 0x0
+#define MX6Q_PAD_CSI0_DAT12__IPU1_CSI0_D_12		0x288 0x658 0x000 0x0 0x0
+#define MX6Q_PAD_CSI0_DAT12__WEIM_WEIM_D_8		0x288 0x658 0x000 0x1 0x0
+#define MX6Q_PAD_CSI0_DAT12__PCIE_CTRL_MUX_16		0x288 0x658 0x000 0x2 0x0
+#define MX6Q_PAD_CSI0_DAT12__UART4_TXD			0x288 0x658 0x000 0x3 0x0
+#define MX6Q_PAD_CSI0_DAT12__SDMA_DEBUG_PC_6		0x288 0x658 0x000 0x4 0x0
+#define MX6Q_PAD_CSI0_DAT12__GPIO_5_30			0x288 0x658 0x000 0x5 0x0
+#define MX6Q_PAD_CSI0_DAT12__MMDC_MMDC_DEBUG_35		0x288 0x658 0x000 0x6 0x0
+#define MX6Q_PAD_CSI0_DAT12__CHEETAH_TRACE_9		0x288 0x658 0x000 0x7 0x0
+#define MX6Q_PAD_CSI0_DAT13__IPU1_CSI0_D_13		0x28c 0x65c 0x000 0x0 0x0
+#define MX6Q_PAD_CSI0_DAT13__WEIM_WEIM_D_9		0x28c 0x65c 0x000 0x1 0x0
+#define MX6Q_PAD_CSI0_DAT13__PCIE_CTRL_MUX_17		0x28c 0x65c 0x000 0x2 0x0
+#define MX6Q_PAD_CSI0_DAT13__UART4_RXD			0x28c 0x65c 0x938 0x3 0x3
+#define MX6Q_PAD_CSI0_DAT13__SDMA_DEBUG_PC_7		0x28c 0x65c 0x000 0x4 0x0
+#define MX6Q_PAD_CSI0_DAT13__GPIO_5_31			0x28c 0x65c 0x000 0x5 0x0
+#define MX6Q_PAD_CSI0_DAT13__MMDC_MMDC_DEBUG_36		0x28c 0x65c 0x000 0x6 0x0
+#define MX6Q_PAD_CSI0_DAT13__CHEETAH_TRACE_10		0x28c 0x65c 0x000 0x7 0x0
+#define MX6Q_PAD_CSI0_DAT14__IPU1_CSI0_D_14		0x290 0x660 0x000 0x0 0x0
+#define MX6Q_PAD_CSI0_DAT14__WEIM_WEIM_D_10		0x290 0x660 0x000 0x1 0x0
+#define MX6Q_PAD_CSI0_DAT14__PCIE_CTRL_MUX_18		0x290 0x660 0x000 0x2 0x0
+#define MX6Q_PAD_CSI0_DAT14__UART5_TXD			0x290 0x660 0x000 0x3 0x0
+#define MX6Q_PAD_CSI0_DAT14__SDMA_DEBUG_PC_8		0x290 0x660 0x000 0x4 0x0
+#define MX6Q_PAD_CSI0_DAT14__GPIO_6_0			0x290 0x660 0x000 0x5 0x0
+#define MX6Q_PAD_CSI0_DAT14__MMDC_MMDC_DEBUG_37		0x290 0x660 0x000 0x6 0x0
+#define MX6Q_PAD_CSI0_DAT14__CHEETAH_TRACE_11		0x290 0x660 0x000 0x7 0x0
+#define MX6Q_PAD_CSI0_DAT15__IPU1_CSI0_D_15		0x294 0x664 0x000 0x0 0x0
+#define MX6Q_PAD_CSI0_DAT15__WEIM_WEIM_D_11		0x294 0x664 0x000 0x1 0x0
+#define MX6Q_PAD_CSI0_DAT15__PCIE_CTRL_MUX_19		0x294 0x664 0x000 0x2 0x0
+#define MX6Q_PAD_CSI0_DAT15__UART5_RXD			0x294 0x664 0x940 0x3 0x3
+#define MX6Q_PAD_CSI0_DAT15__SDMA_DEBUG_PC_9		0x294 0x664 0x000 0x4 0x0
+#define MX6Q_PAD_CSI0_DAT15__GPIO_6_1			0x294 0x664 0x000 0x5 0x0
+#define MX6Q_PAD_CSI0_DAT15__MMDC_MMDC_DEBUG_38		0x294 0x664 0x000 0x6 0x0
+#define MX6Q_PAD_CSI0_DAT15__CHEETAH_TRACE_12		0x294 0x664 0x000 0x7 0x0
+#define MX6Q_PAD_CSI0_DAT16__IPU1_CSI0_D_16		0x298 0x668 0x000 0x0 0x0
+#define MX6Q_PAD_CSI0_DAT16__WEIM_WEIM_D_12		0x298 0x668 0x000 0x1 0x0
+#define MX6Q_PAD_CSI0_DAT16__PCIE_CTRL_MUX_20		0x298 0x668 0x000 0x2 0x0
+#define MX6Q_PAD_CSI0_DAT16__UART4_RTS			0x298 0x668 0x934 0x3 0x0
+#define MX6Q_PAD_CSI0_DAT16__SDMA_DEBUG_PC_10		0x298 0x668 0x000 0x4 0x0
+#define MX6Q_PAD_CSI0_DAT16__GPIO_6_2			0x298 0x668 0x000 0x5 0x0
+#define MX6Q_PAD_CSI0_DAT16__MMDC_MMDC_DEBUG_39		0x298 0x668 0x000 0x6 0x0
+#define MX6Q_PAD_CSI0_DAT16__CHEETAH_TRACE_13		0x298 0x668 0x000 0x7 0x0
+#define MX6Q_PAD_CSI0_DAT17__IPU1_CSI0_D_17		0x29c 0x66c 0x000 0x0 0x0
+#define MX6Q_PAD_CSI0_DAT17__WEIM_WEIM_D_13		0x29c 0x66c 0x000 0x1 0x0
+#define MX6Q_PAD_CSI0_DAT17__PCIE_CTRL_MUX_21		0x29c 0x66c 0x000 0x2 0x0
+#define MX6Q_PAD_CSI0_DAT17__UART4_CTS			0x29c 0x66c 0x934 0x3 0x1
+#define MX6Q_PAD_CSI0_DAT17__SDMA_DEBUG_PC_11		0x29c 0x66c 0x000 0x4 0x0
+#define MX6Q_PAD_CSI0_DAT17__GPIO_6_3			0x29c 0x66c 0x000 0x5 0x0
+#define MX6Q_PAD_CSI0_DAT17__MMDC_MMDC_DEBUG_40		0x29c 0x66c 0x000 0x6 0x0
+#define MX6Q_PAD_CSI0_DAT17__CHEETAH_TRACE_14		0x29c 0x66c 0x000 0x7 0x0
+#define MX6Q_PAD_CSI0_DAT18__IPU1_CSI0_D_18		0x2a0 0x670 0x000 0x0 0x0
+#define MX6Q_PAD_CSI0_DAT18__WEIM_WEIM_D_14		0x2a0 0x670 0x000 0x1 0x0
+#define MX6Q_PAD_CSI0_DAT18__PCIE_CTRL_MUX_22		0x2a0 0x670 0x000 0x2 0x0
+#define MX6Q_PAD_CSI0_DAT18__UART5_RTS			0x2a0 0x670 0x93c 0x3 0x2
+#define MX6Q_PAD_CSI0_DAT18__SDMA_DEBUG_PC_12		0x2a0 0x670 0x000 0x4 0x0
+#define MX6Q_PAD_CSI0_DAT18__GPIO_6_4			0x2a0 0x670 0x000 0x5 0x0
+#define MX6Q_PAD_CSI0_DAT18__MMDC_MMDC_DEBUG_41		0x2a0 0x670 0x000 0x6 0x0
+#define MX6Q_PAD_CSI0_DAT18__CHEETAH_TRACE_15		0x2a0 0x670 0x000 0x7 0x0
+#define MX6Q_PAD_CSI0_DAT19__IPU1_CSI0_D_19		0x2a4 0x674 0x000 0x0 0x0
+#define MX6Q_PAD_CSI0_DAT19__WEIM_WEIM_D_15		0x2a4 0x674 0x000 0x1 0x0
+#define MX6Q_PAD_CSI0_DAT19__PCIE_CTRL_MUX_23		0x2a4 0x674 0x000 0x2 0x0
+#define MX6Q_PAD_CSI0_DAT19__UART5_CTS			0x2a4 0x674 0x93c 0x3 0x3
+#define MX6Q_PAD_CSI0_DAT19__SDMA_DEBUG_PC_13		0x2a4 0x674 0x000 0x4 0x0
+#define MX6Q_PAD_CSI0_DAT19__GPIO_6_5			0x2a4 0x674 0x000 0x5 0x0
+#define MX6Q_PAD_CSI0_DAT19__MMDC_MMDC_DEBUG_42		0x2a4 0x674 0x000 0x6 0x0
+#define MX6Q_PAD_CSI0_DAT19__ANATOP_TESTO_9		0x2a4 0x674 0x000 0x7 0x0
+#define MX6Q_PAD_JTAG_TMS__SJC_TMS			0x000 0x678 0x000 0x0 0x0
+#define MX6Q_PAD_JTAG_MOD__SJC_MOD			0x000 0x67c 0x000 0x0 0x0
+#define MX6Q_PAD_JTAG_TRSTB__SJC_TRSTB			0x000 0x680 0x000 0x0 0x0
+#define MX6Q_PAD_JTAG_TDI__SJC_TDI			0x000 0x684 0x000 0x0 0x0
+#define MX6Q_PAD_JTAG_TCK__SJC_TCK			0x000 0x688 0x000 0x0 0x0
+#define MX6Q_PAD_JTAG_TDO__SJC_TDO			0x000 0x68c 0x000 0x0 0x0
+#define MX6Q_PAD_SD3_DAT7__USDHC3_DAT7			0x2a8 0x690 0x000 0x0 0x0
+#define MX6Q_PAD_SD3_DAT7__UART1_TXD			0x2a8 0x690 0x000 0x1 0x0
+#define MX6Q_PAD_SD3_DAT7__PCIE_CTRL_MUX_24		0x2a8 0x690 0x000 0x2 0x0
+#define MX6Q_PAD_SD3_DAT7__USBOH3_UH3_DFD_OUT_0		0x2a8 0x690 0x000 0x3 0x0
+#define MX6Q_PAD_SD3_DAT7__USBOH3_UH2_DFD_OUT_0		0x2a8 0x690 0x000 0x4 0x0
+#define MX6Q_PAD_SD3_DAT7__GPIO_6_17			0x2a8 0x690 0x000 0x5 0x0
+#define MX6Q_PAD_SD3_DAT7__MIPI_CORE_DPHY_IN_12		0x2a8 0x690 0x000 0x6 0x0
+#define MX6Q_PAD_SD3_DAT7__USBPHY2_CLK20DIV		0x2a8 0x690 0x000 0x7 0x0
+#define MX6Q_PAD_SD3_DAT6__USDHC3_DAT6			0x2ac 0x694 0x000 0x0 0x0
+#define MX6Q_PAD_SD3_DAT6__UART1_RXD			0x2ac 0x694 0x920 0x1 0x3
+#define MX6Q_PAD_SD3_DAT6__PCIE_CTRL_MUX_25		0x2ac 0x694 0x000 0x2 0x0
+#define MX6Q_PAD_SD3_DAT6__USBOH3_UH3_DFD_OUT_1		0x2ac 0x694 0x000 0x3 0x0
+#define MX6Q_PAD_SD3_DAT6__USBOH3_UH2_DFD_OUT_1		0x2ac 0x694 0x000 0x4 0x0
+#define MX6Q_PAD_SD3_DAT6__GPIO_6_18			0x2ac 0x694 0x000 0x5 0x0
+#define MX6Q_PAD_SD3_DAT6__MIPI_CORE_DPHY_IN_13		0x2ac 0x694 0x000 0x6 0x0
+#define MX6Q_PAD_SD3_DAT6__ANATOP_TESTO_10		0x2ac 0x694 0x000 0x7 0x0
+#define MX6Q_PAD_SD3_DAT5__USDHC3_DAT5			0x2b0 0x698 0x000 0x0 0x0
+#define MX6Q_PAD_SD3_DAT5__UART2_TXD			0x2b0 0x698 0x000 0x1 0x0
+#define MX6Q_PAD_SD3_DAT5__PCIE_CTRL_MUX_26		0x2b0 0x698 0x000 0x2 0x0
+#define MX6Q_PAD_SD3_DAT5__USBOH3_UH3_DFD_OUT_2		0x2b0 0x698 0x000 0x3 0x0
+#define MX6Q_PAD_SD3_DAT5__USBOH3_UH2_DFD_OUT_2		0x2b0 0x698 0x000 0x4 0x0
+#define MX6Q_PAD_SD3_DAT5__GPIO_7_0			0x2b0 0x698 0x000 0x5 0x0
+#define MX6Q_PAD_SD3_DAT5__MIPI_CORE_DPHY_IN_14		0x2b0 0x698 0x000 0x6 0x0
+#define MX6Q_PAD_SD3_DAT5__ANATOP_TESTO_11		0x2b0 0x698 0x000 0x7 0x0
+#define MX6Q_PAD_SD3_DAT4__USDHC3_DAT4			0x2b4 0x69c 0x000 0x0 0x0
+#define MX6Q_PAD_SD3_DAT4__UART2_RXD			0x2b4 0x69c 0x928 0x1 0x5
+#define MX6Q_PAD_SD3_DAT4__PCIE_CTRL_MUX_27		0x2b4 0x69c 0x000 0x2 0x0
+#define MX6Q_PAD_SD3_DAT4__USBOH3_UH3_DFD_OUT_3		0x2b4 0x69c 0x000 0x3 0x0
+#define MX6Q_PAD_SD3_DAT4__USBOH3_UH2_DFD_OUT_3		0x2b4 0x69c 0x000 0x4 0x0
+#define MX6Q_PAD_SD3_DAT4__GPIO_7_1			0x2b4 0x69c 0x000 0x5 0x0
+#define MX6Q_PAD_SD3_DAT4__MIPI_CORE_DPHY_IN_15		0x2b4 0x69c 0x000 0x6 0x0
+#define MX6Q_PAD_SD3_DAT4__ANATOP_TESTO_12		0x2b4 0x69c 0x000 0x7 0x0
+#define MX6Q_PAD_SD3_CMD__USDHC3_CMD			0x2b8 0x6a0 0x000 0x0 0x0
+#define MX6Q_PAD_SD3_CMD__UART2_CTS			0x2b8 0x6a0 0x924 0x1 0x2
+#define MX6Q_PAD_SD3_CMD__CAN1_TXCAN			0x2b8 0x6a0 0x000 0x2 0x0
+#define MX6Q_PAD_SD3_CMD__USBOH3_UH3_DFD_OUT_4		0x2b8 0x6a0 0x000 0x3 0x0
+#define MX6Q_PAD_SD3_CMD__USBOH3_UH2_DFD_OUT_4		0x2b8 0x6a0 0x000 0x4 0x0
+#define MX6Q_PAD_SD3_CMD__GPIO_7_2			0x2b8 0x6a0 0x000 0x5 0x0
+#define MX6Q_PAD_SD3_CMD__MIPI_CORE_DPHY_IN_16		0x2b8 0x6a0 0x000 0x6 0x0
+#define MX6Q_PAD_SD3_CMD__ANATOP_TESTO_13		0x2b8 0x6a0 0x000 0x7 0x0
+#define MX6Q_PAD_SD3_CLK__USDHC3_CLK			0x2bc 0x6a4 0x000 0x0 0x0
+#define MX6Q_PAD_SD3_CLK__UART2_RTS			0x2bc 0x6a4 0x924 0x1 0x3
+#define MX6Q_PAD_SD3_CLK__CAN1_RXCAN			0x2bc 0x6a4 0x7e4 0x2 0x2
+#define MX6Q_PAD_SD3_CLK__USBOH3_UH3_DFD_OUT_5		0x2bc 0x6a4 0x000 0x3 0x0
+#define MX6Q_PAD_SD3_CLK__USBOH3_UH2_DFD_OUT_5		0x2bc 0x6a4 0x000 0x4 0x0
+#define MX6Q_PAD_SD3_CLK__GPIO_7_3			0x2bc 0x6a4 0x000 0x5 0x0
+#define MX6Q_PAD_SD3_CLK__MIPI_CORE_DPHY_IN_17		0x2bc 0x6a4 0x000 0x6 0x0
+#define MX6Q_PAD_SD3_CLK__ANATOP_TESTO_14		0x2bc 0x6a4 0x000 0x7 0x0
+#define MX6Q_PAD_SD3_DAT0__USDHC3_DAT0			0x2c0 0x6a8 0x000 0x0 0x0
+#define MX6Q_PAD_SD3_DAT0__UART1_CTS			0x2c0 0x6a8 0x91c 0x1 0x2
+#define MX6Q_PAD_SD3_DAT0__CAN2_TXCAN			0x2c0 0x6a8 0x000 0x2 0x0
+#define MX6Q_PAD_SD3_DAT0__USBOH3_UH3_DFD_OUT_6		0x2c0 0x6a8 0x000 0x3 0x0
+#define MX6Q_PAD_SD3_DAT0__USBOH3_UH2_DFD_OUT_6		0x2c0 0x6a8 0x000 0x4 0x0
+#define MX6Q_PAD_SD3_DAT0__GPIO_7_4			0x2c0 0x6a8 0x000 0x5 0x0
+#define MX6Q_PAD_SD3_DAT0__MIPI_CORE_DPHY_IN_18		0x2c0 0x6a8 0x000 0x6 0x0
+#define MX6Q_PAD_SD3_DAT0__ANATOP_TESTO_15		0x2c0 0x6a8 0x000 0x7 0x0
+#define MX6Q_PAD_SD3_DAT1__USDHC3_DAT1			0x2c4 0x6ac 0x000 0x0 0x0
+#define MX6Q_PAD_SD3_DAT1__UART1_RTS			0x2c4 0x6ac 0x91c 0x1 0x3
+#define MX6Q_PAD_SD3_DAT1__CAN2_RXCAN			0x2c4 0x6ac 0x7e8 0x2 0x1
+#define MX6Q_PAD_SD3_DAT1__USBOH3_UH3_DFD_OUT_7		0x2c4 0x6ac 0x000 0x3 0x0
+#define MX6Q_PAD_SD3_DAT1__USBOH3_UH2_DFD_OUT_7		0x2c4 0x6ac 0x000 0x4 0x0
+#define MX6Q_PAD_SD3_DAT1__GPIO_7_5			0x2c4 0x6ac 0x000 0x5 0x0
+#define MX6Q_PAD_SD3_DAT1__MIPI_CORE_DPHY_IN_19		0x2c4 0x6ac 0x000 0x6 0x0
+#define MX6Q_PAD_SD3_DAT1__ANATOP_TESTI_0		0x2c4 0x6ac 0x000 0x7 0x0
+#define MX6Q_PAD_SD3_DAT2__USDHC3_DAT2			0x2c8 0x6b0 0x000 0x0 0x0
+#define MX6Q_PAD_SD3_DAT2__PCIE_CTRL_MUX_28		0x2c8 0x6b0 0x000 0x2 0x0
+#define MX6Q_PAD_SD3_DAT2__USBOH3_UH3_DFD_OUT_8		0x2c8 0x6b0 0x000 0x3 0x0
+#define MX6Q_PAD_SD3_DAT2__USBOH3_UH2_DFD_OUT_8		0x2c8 0x6b0 0x000 0x4 0x0
+#define MX6Q_PAD_SD3_DAT2__GPIO_7_6			0x2c8 0x6b0 0x000 0x5 0x0
+#define MX6Q_PAD_SD3_DAT2__MIPI_CORE_DPHY_IN_20		0x2c8 0x6b0 0x000 0x6 0x0
+#define MX6Q_PAD_SD3_DAT2__ANATOP_TESTI_1		0x2c8 0x6b0 0x000 0x7 0x0
+#define MX6Q_PAD_SD3_DAT3__USDHC3_DAT3			0x2cc 0x6b4 0x000 0x0 0x0
+#define MX6Q_PAD_SD3_DAT3__UART3_CTS			0x2cc 0x6b4 0x92c 0x1 0x4
+#define MX6Q_PAD_SD3_DAT3__PCIE_CTRL_MUX_29		0x2cc 0x6b4 0x000 0x2 0x0
+#define MX6Q_PAD_SD3_DAT3__USBOH3_UH3_DFD_OUT_9		0x2cc 0x6b4 0x000 0x3 0x0
+#define MX6Q_PAD_SD3_DAT3__USBOH3_UH2_DFD_OUT_9		0x2cc 0x6b4 0x000 0x4 0x0
+#define MX6Q_PAD_SD3_DAT3__GPIO_7_7			0x2cc 0x6b4 0x000 0x5 0x0
+#define MX6Q_PAD_SD3_DAT3__MIPI_CORE_DPHY_IN_21		0x2cc 0x6b4 0x000 0x6 0x0
+#define MX6Q_PAD_SD3_DAT3__ANATOP_TESTI_2		0x2cc 0x6b4 0x000 0x7 0x0
+#define MX6Q_PAD_SD3_RST__USDHC3_RST			0x2d0 0x6b8 0x000 0x0 0x0
+#define MX6Q_PAD_SD3_RST__UART3_RTS			0x2d0 0x6b8 0x92c 0x1 0x5
+#define MX6Q_PAD_SD3_RST__PCIE_CTRL_MUX_30		0x2d0 0x6b8 0x000 0x2 0x0
+#define MX6Q_PAD_SD3_RST__USBOH3_UH3_DFD_OUT_10		0x2d0 0x6b8 0x000 0x3 0x0
+#define MX6Q_PAD_SD3_RST__USBOH3_UH2_DFD_OUT_10		0x2d0 0x6b8 0x000 0x4 0x0
+#define MX6Q_PAD_SD3_RST__GPIO_7_8			0x2d0 0x6b8 0x000 0x5 0x0
+#define MX6Q_PAD_SD3_RST__MIPI_CORE_DPHY_IN_22		0x2d0 0x6b8 0x000 0x6 0x0
+#define MX6Q_PAD_SD3_RST__ANATOP_ANATOP_TESTI_3		0x2d0 0x6b8 0x000 0x7 0x0
+#define MX6Q_PAD_NANDF_CLE__RAWNAND_CLE			0x2d4 0x6bc 0x000 0x0 0x0
+#define MX6Q_PAD_NANDF_CLE__IPU2_SISG_4			0x2d4 0x6bc 0x000 0x1 0x0
+#define MX6Q_PAD_NANDF_CLE__PCIE_CTRL_MUX_31		0x2d4 0x6bc 0x000 0x2 0x0
+#define MX6Q_PAD_NANDF_CLE__USBOH3_UH3_DFD_OT11		0x2d4 0x6bc 0x000 0x3 0x0
+#define MX6Q_PAD_NANDF_CLE__USBOH3_UH2_DFD_OT11		0x2d4 0x6bc 0x000 0x4 0x0
+#define MX6Q_PAD_NANDF_CLE__GPIO_6_7			0x2d4 0x6bc 0x000 0x5 0x0
+#define MX6Q_PAD_NANDF_CLE__MIPI_CORE_DPHY_IN23		0x2d4 0x6bc 0x000 0x6 0x0
+#define MX6Q_PAD_NANDF_CLE__TPSMP_HTRANS_0		0x2d4 0x6bc 0x000 0x7 0x0
+#define MX6Q_PAD_NANDF_ALE__RAWNAND_ALE			0x2d8 0x6c0 0x000 0x0 0x0
+#define MX6Q_PAD_NANDF_ALE__USDHC4_RST			0x2d8 0x6c0 0x000 0x1 0x0
+#define MX6Q_PAD_NANDF_ALE__PCIE_CTRL_MUX_0		0x2d8 0x6c0 0x000 0x2 0x0
+#define MX6Q_PAD_NANDF_ALE__USBOH3_UH3_DFD_OT12		0x2d8 0x6c0 0x000 0x3 0x0
+#define MX6Q_PAD_NANDF_ALE__USBOH3_UH2_DFD_OT12		0x2d8 0x6c0 0x000 0x4 0x0
+#define MX6Q_PAD_NANDF_ALE__GPIO_6_8			0x2d8 0x6c0 0x000 0x5 0x0
+#define MX6Q_PAD_NANDF_ALE__MIPI_CR_DPHY_IN_24		0x2d8 0x6c0 0x000 0x6 0x0
+#define MX6Q_PAD_NANDF_ALE__TPSMP_HTRANS_1		0x2d8 0x6c0 0x000 0x7 0x0
+#define MX6Q_PAD_NANDF_WP_B__RAWNAND_RESETN		0x2dc 0x6c4 0x000 0x0 0x0
+#define MX6Q_PAD_NANDF_WP_B__IPU2_SISG_5		0x2dc 0x6c4 0x000 0x1 0x0
+#define MX6Q_PAD_NANDF_WP_B__PCIE_CTRL__MUX_1		0x2dc 0x6c4 0x000 0x2 0x0
+#define MX6Q_PAD_NANDF_WP_B__USBOH3_UH3_DFDOT13		0x2dc 0x6c4 0x000 0x3 0x0
+#define MX6Q_PAD_NANDF_WP_B__USBOH3_UH2_DFDOT13		0x2dc 0x6c4 0x000 0x4 0x0
+#define MX6Q_PAD_NANDF_WP_B__GPIO_6_9			0x2dc 0x6c4 0x000 0x5 0x0
+#define MX6Q_PAD_NANDF_WP_B__MIPI_CR_DPHY_OUT32		0x2dc 0x6c4 0x000 0x6 0x0
+#define MX6Q_PAD_NANDF_WP_B__PL301_PER1_HSIZE_0		0x2dc 0x6c4 0x000 0x7 0x0
+#define MX6Q_PAD_NANDF_RB0__RAWNAND_READY0		0x2e0 0x6c8 0x000 0x0 0x0
+#define MX6Q_PAD_NANDF_RB0__IPU2_DI0_PIN1		0x2e0 0x6c8 0x000 0x1 0x0
+#define MX6Q_PAD_NANDF_RB0__PCIE_CTRL_MUX_2		0x2e0 0x6c8 0x000 0x2 0x0
+#define MX6Q_PAD_NANDF_RB0__USBOH3_UH3_DFD_OT14		0x2e0 0x6c8 0x000 0x3 0x0
+#define MX6Q_PAD_NANDF_RB0__USBOH3_UH2_DFD_OT14		0x2e0 0x6c8 0x000 0x4 0x0
+#define MX6Q_PAD_NANDF_RB0__GPIO_6_10			0x2e0 0x6c8 0x000 0x5 0x0
+#define MX6Q_PAD_NANDF_RB0__MIPI_CR_DPHY_OUT_33		0x2e0 0x6c8 0x000 0x6 0x0
+#define MX6Q_PAD_NANDF_RB0__PL301_PER1_HSIZE_1		0x2e0 0x6c8 0x000 0x7 0x0
+#define MX6Q_PAD_NANDF_CS0__RAWNAND_CE0N		0x2e4 0x6cc 0x000 0x0 0x0
+#define MX6Q_PAD_NANDF_CS0__USBOH3_UH3_DFD_OT15		0x2e4 0x6cc 0x000 0x3 0x0
+#define MX6Q_PAD_NANDF_CS0__USBOH3_UH2_DFD_OT15		0x2e4 0x6cc 0x000 0x4 0x0
+#define MX6Q_PAD_NANDF_CS0__GPIO_6_11			0x2e4 0x6cc 0x000 0x5 0x0
+#define MX6Q_PAD_NANDF_CS0__PL301_PER1_HSIZE_2		0x2e4 0x6cc 0x000 0x7 0x0
+#define MX6Q_PAD_NANDF_CS1__RAWNAND_CE1N		0x2e8 0x6d0 0x000 0x0 0x0
+#define MX6Q_PAD_NANDF_CS1__USDHC4_VSELECT		0x2e8 0x6d0 0x000 0x1 0x0
+#define MX6Q_PAD_NANDF_CS1__USDHC3_VSELECT		0x2e8 0x6d0 0x000 0x2 0x0
+#define MX6Q_PAD_NANDF_CS1__PCIE_CTRL_MUX_3		0x2e8 0x6d0 0x000 0x4 0x0
+#define MX6Q_PAD_NANDF_CS1__GPIO_6_14			0x2e8 0x6d0 0x000 0x5 0x0
+#define MX6Q_PAD_NANDF_CS1__PL301_PER1_HRDYOUT		0x2e8 0x6d0 0x000 0x7 0x0
+#define MX6Q_PAD_NANDF_CS2__RAWNAND_CE2N		0x2ec 0x6d4 0x000 0x0 0x0
+#define MX6Q_PAD_NANDF_CS2__IPU1_SISG_0			0x2ec 0x6d4 0x000 0x1 0x0
+#define MX6Q_PAD_NANDF_CS2__ESAI1_TX0			0x2ec 0x6d4 0x874 0x2 0x1
+#define MX6Q_PAD_NANDF_CS2__WEIM_WEIM_CRE		0x2ec 0x6d4 0x000 0x3 0x0
+#define MX6Q_PAD_NANDF_CS2__CCM_CLKO2			0x2ec 0x6d4 0x000 0x4 0x0
+#define MX6Q_PAD_NANDF_CS2__GPIO_6_15			0x2ec 0x6d4 0x000 0x5 0x0
+#define MX6Q_PAD_NANDF_CS2__IPU2_SISG_0			0x2ec 0x6d4 0x000 0x6 0x0
+#define MX6Q_PAD_NANDF_CS3__RAWNAND_CE3N		0x2f0 0x6d8 0x000 0x0 0x0
+#define MX6Q_PAD_NANDF_CS3__IPU1_SISG_1			0x2f0 0x6d8 0x000 0x1 0x0
+#define MX6Q_PAD_NANDF_CS3__ESAI1_TX1			0x2f0 0x6d8 0x878 0x2 0x1
+#define MX6Q_PAD_NANDF_CS3__WEIM_WEIM_A_26		0x2f0 0x6d8 0x000 0x3 0x0
+#define MX6Q_PAD_NANDF_CS3__PCIE_CTRL_MUX_4		0x2f0 0x6d8 0x000 0x4 0x0
+#define MX6Q_PAD_NANDF_CS3__GPIO_6_16			0x2f0 0x6d8 0x000 0x5 0x0
+#define MX6Q_PAD_NANDF_CS3__IPU2_SISG_1			0x2f0 0x6d8 0x000 0x6 0x0
+#define MX6Q_PAD_NANDF_CS3__TPSMP_CLK			0x2f0 0x6d8 0x000 0x7 0x0
+#define MX6Q_PAD_SD4_CMD__USDHC4_CMD			0x2f4 0x6dc 0x000 0x0 0x0
+#define MX6Q_PAD_SD4_CMD__RAWNAND_RDN			0x2f4 0x6dc 0x000 0x1 0x0
+#define MX6Q_PAD_SD4_CMD__UART3_TXD			0x2f4 0x6dc 0x000 0x2 0x0
+#define MX6Q_PAD_SD4_CMD__PCIE_CTRL_MUX_5		0x2f4 0x6dc 0x000 0x4 0x0
+#define MX6Q_PAD_SD4_CMD__GPIO_7_9			0x2f4 0x6dc 0x000 0x5 0x0
+#define MX6Q_PAD_SD4_CMD__TPSMP_HDATA_DIR		0x2f4 0x6dc 0x000 0x7 0x0
+#define MX6Q_PAD_SD4_CLK__USDHC4_CLK			0x2f8 0x6e0 0x000 0x0 0x0
+#define MX6Q_PAD_SD4_CLK__RAWNAND_WRN			0x2f8 0x6e0 0x000 0x1 0x0
+#define MX6Q_PAD_SD4_CLK__UART3_RXD			0x2f8 0x6e0 0x930 0x2 0x3
+#define MX6Q_PAD_SD4_CLK__PCIE_CTRL_MUX_6		0x2f8 0x6e0 0x000 0x4 0x0
+#define MX6Q_PAD_SD4_CLK__GPIO_7_10			0x2f8 0x6e0 0x000 0x5 0x0
+#define MX6Q_PAD_NANDF_D0__RAWNAND_D0			0x2fc 0x6e4 0x000 0x0 0x0
+#define MX6Q_PAD_NANDF_D0__USDHC1_DAT4			0x2fc 0x6e4 0x000 0x1 0x0
+#define MX6Q_PAD_NANDF_D0__GPU3D_GPU_DBG_OUT_0		0x2fc 0x6e4 0x000 0x2 0x0
+#define MX6Q_PAD_NANDF_D0__USBOH3_UH2_DFD_OUT16		0x2fc 0x6e4 0x000 0x3 0x0
+#define MX6Q_PAD_NANDF_D0__USBOH3_UH3_DFD_OUT16		0x2fc 0x6e4 0x000 0x4 0x0
+#define MX6Q_PAD_NANDF_D0__GPIO_2_0			0x2fc 0x6e4 0x000 0x5 0x0
+#define MX6Q_PAD_NANDF_D0__IPU1_IPU_DIAG_BUS_0		0x2fc 0x6e4 0x000 0x6 0x0
+#define MX6Q_PAD_NANDF_D0__IPU2_IPU_DIAG_BUS_0		0x2fc 0x6e4 0x000 0x7 0x0
+#define MX6Q_PAD_NANDF_D1__RAWNAND_D1			0x300 0x6e8 0x000 0x0 0x0
+#define MX6Q_PAD_NANDF_D1__USDHC1_DAT5			0x300 0x6e8 0x000 0x1 0x0
+#define MX6Q_PAD_NANDF_D1__GPU3D_GPU_DEBUG_OUT1		0x300 0x6e8 0x000 0x2 0x0
+#define MX6Q_PAD_NANDF_D1__USBOH3_UH2_DFD_OUT17		0x300 0x6e8 0x000 0x3 0x0
+#define MX6Q_PAD_NANDF_D1__USBOH3_UH3_DFD_OUT17		0x300 0x6e8 0x000 0x4 0x0
+#define MX6Q_PAD_NANDF_D1__GPIO_2_1			0x300 0x6e8 0x000 0x5 0x0
+#define MX6Q_PAD_NANDF_D1__IPU1_IPU_DIAG_BUS_1		0x300 0x6e8 0x000 0x6 0x0
+#define MX6Q_PAD_NANDF_D1__IPU2_IPU_DIAG_BUS_1		0x300 0x6e8 0x000 0x7 0x0
+#define MX6Q_PAD_NANDF_D2__RAWNAND_D2			0x304 0x6ec 0x000 0x0 0x0
+#define MX6Q_PAD_NANDF_D2__USDHC1_DAT6			0x304 0x6ec 0x000 0x1 0x0
+#define MX6Q_PAD_NANDF_D2__GPU3D_GPU_DBG_OUT_2		0x304 0x6ec 0x000 0x2 0x0
+#define MX6Q_PAD_NANDF_D2__USBOH3_UH2_DFD_OUT18		0x304 0x6ec 0x000 0x3 0x0
+#define MX6Q_PAD_NANDF_D2__USBOH3_UH3_DFD_OUT18		0x304 0x6ec 0x000 0x4 0x0
+#define MX6Q_PAD_NANDF_D2__GPIO_2_2			0x304 0x6ec 0x000 0x5 0x0
+#define MX6Q_PAD_NANDF_D2__IPU1_IPU_DIAG_BUS_2		0x304 0x6ec 0x000 0x6 0x0
+#define MX6Q_PAD_NANDF_D2__IPU2_IPU_DIAG_BUS_2		0x304 0x6ec 0x000 0x7 0x0
+#define MX6Q_PAD_NANDF_D3__RAWNAND_D3			0x308 0x6f0 0x000 0x0 0x0
+#define MX6Q_PAD_NANDF_D3__USDHC1_DAT7			0x308 0x6f0 0x000 0x1 0x0
+#define MX6Q_PAD_NANDF_D3__GPU3D_GPU_DBG_OUT_3		0x308 0x6f0 0x000 0x2 0x0
+#define MX6Q_PAD_NANDF_D3__USBOH3_UH2_DFD_OUT19		0x308 0x6f0 0x000 0x3 0x0
+#define MX6Q_PAD_NANDF_D3__USBOH3_UH3_DFD_OUT19		0x308 0x6f0 0x000 0x4 0x0
+#define MX6Q_PAD_NANDF_D3__GPIO_2_3			0x308 0x6f0 0x000 0x5 0x0
+#define MX6Q_PAD_NANDF_D3__IPU1_IPU_DIAG_BUS_3		0x308 0x6f0 0x000 0x6 0x0
+#define MX6Q_PAD_NANDF_D3__IPU2_IPU_DIAG_BUS_3		0x308 0x6f0 0x000 0x7 0x0
+#define MX6Q_PAD_NANDF_D4__RAWNAND_D4			0x30c 0x6f4 0x000 0x0 0x0
+#define MX6Q_PAD_NANDF_D4__USDHC2_DAT4			0x30c 0x6f4 0x000 0x1 0x0
+#define MX6Q_PAD_NANDF_D4__GPU3D_GPU_DBG_OUT_4		0x30c 0x6f4 0x000 0x2 0x0
+#define MX6Q_PAD_NANDF_D4__USBOH3_UH2_DFD_OUT20		0x30c 0x6f4 0x000 0x3 0x0
+#define MX6Q_PAD_NANDF_D4__USBOH3_UH3_DFD_OUT20		0x30c 0x6f4 0x000 0x4 0x0
+#define MX6Q_PAD_NANDF_D4__GPIO_2_4			0x30c 0x6f4 0x000 0x5 0x0
+#define MX6Q_PAD_NANDF_D4__IPU1_IPU_DIAG_BUS_4		0x30c 0x6f4 0x000 0x6 0x0
+#define MX6Q_PAD_NANDF_D4__IPU2_IPU_DIAG_BUS_4		0x30c 0x6f4 0x000 0x7 0x0
+#define MX6Q_PAD_NANDF_D5__RAWNAND_D5			0x310 0x6f8 0x000 0x0 0x0
+#define MX6Q_PAD_NANDF_D5__USDHC2_DAT5			0x310 0x6f8 0x000 0x1 0x0
+#define MX6Q_PAD_NANDF_D5__GPU3D_GPU_DBG_OUT_5		0x310 0x6f8 0x000 0x2 0x0
+#define MX6Q_PAD_NANDF_D5__USBOH3_UH2_DFD_OUT21		0x310 0x6f8 0x000 0x3 0x0
+#define MX6Q_PAD_NANDF_D5__USBOH3_UH3_DFD_OUT21		0x310 0x6f8 0x000 0x4 0x0
+#define MX6Q_PAD_NANDF_D5__GPIO_2_5			0x310 0x6f8 0x000 0x5 0x0
+#define MX6Q_PAD_NANDF_D5__IPU1_IPU_DIAG_BUS_5		0x310 0x6f8 0x000 0x6 0x0
+#define MX6Q_PAD_NANDF_D5__IPU2_IPU_DIAG_BUS_5		0x310 0x6f8 0x000 0x7 0x0
+#define MX6Q_PAD_NANDF_D6__RAWNAND_D6			0x314 0x6fc 0x000 0x0 0x0
+#define MX6Q_PAD_NANDF_D6__USDHC2_DAT6			0x314 0x6fc 0x000 0x1 0x0
+#define MX6Q_PAD_NANDF_D6__GPU3D_GPU_DBG_OUT_6		0x314 0x6fc 0x000 0x2 0x0
+#define MX6Q_PAD_NANDF_D6__USBOH3_UH2_DFD_OUT22		0x314 0x6fc 0x000 0x3 0x0
+#define MX6Q_PAD_NANDF_D6__USBOH3_UH3_DFD_OUT22		0x314 0x6fc 0x000 0x4 0x0
+#define MX6Q_PAD_NANDF_D6__GPIO_2_6			0x314 0x6fc 0x000 0x5 0x0
+#define MX6Q_PAD_NANDF_D6__IPU1_IPU_DIAG_BUS_6		0x314 0x6fc 0x000 0x6 0x0
+#define MX6Q_PAD_NANDF_D6__IPU2_IPU_DIAG_BUS_6		0x314 0x6fc 0x000 0x7 0x0
+#define MX6Q_PAD_NANDF_D7__RAWNAND_D7			0x318 0x700 0x000 0x0 0x0
+#define MX6Q_PAD_NANDF_D7__USDHC2_DAT7			0x318 0x700 0x000 0x1 0x0
+#define MX6Q_PAD_NANDF_D7__GPU3D_GPU_DBG_OUT_7		0x318 0x700 0x000 0x2 0x0
+#define MX6Q_PAD_NANDF_D7__USBOH3_UH2_DFD_OUT23		0x318 0x700 0x000 0x3 0x0
+#define MX6Q_PAD_NANDF_D7__USBOH3_UH3_DFD_OUT23		0x318 0x700 0x000 0x4 0x0
+#define MX6Q_PAD_NANDF_D7__GPIO_2_7			0x318 0x700 0x000 0x5 0x0
+#define MX6Q_PAD_NANDF_D7__IPU1_IPU_DIAG_BUS_7		0x318 0x700 0x000 0x6 0x0
+#define MX6Q_PAD_NANDF_D7__IPU2_IPU_DIAG_BUS_7		0x318 0x700 0x000 0x7 0x0
+#define MX6Q_PAD_SD4_DAT0__RAWNAND_D8			0x31c 0x704 0x000 0x0 0x0
+#define MX6Q_PAD_SD4_DAT0__USDHC4_DAT0			0x31c 0x704 0x000 0x1 0x0
+#define MX6Q_PAD_SD4_DAT0__RAWNAND_DQS			0x31c 0x704 0x000 0x2 0x0
+#define MX6Q_PAD_SD4_DAT0__USBOH3_UH2_DFD_OUT24		0x31c 0x704 0x000 0x3 0x0
+#define MX6Q_PAD_SD4_DAT0__USBOH3_UH3_DFD_OUT24		0x31c 0x704 0x000 0x4 0x0
+#define MX6Q_PAD_SD4_DAT0__GPIO_2_8			0x31c 0x704 0x000 0x5 0x0
+#define MX6Q_PAD_SD4_DAT0__IPU1_IPU_DIAG_BUS_8		0x31c 0x704 0x000 0x6 0x0
+#define MX6Q_PAD_SD4_DAT0__IPU2_IPU_DIAG_BUS_8		0x31c 0x704 0x000 0x7 0x0
+#define MX6Q_PAD_SD4_DAT1__RAWNAND_D9			0x320 0x708 0x000 0x0 0x0
+#define MX6Q_PAD_SD4_DAT1__USDHC4_DAT1			0x320 0x708 0x000 0x1 0x0
+#define MX6Q_PAD_SD4_DAT1__PWM3_PWMO			0x320 0x708 0x000 0x2 0x0
+#define MX6Q_PAD_SD4_DAT1__USBOH3_UH2_DFD_OUT25		0x320 0x708 0x000 0x3 0x0
+#define MX6Q_PAD_SD4_DAT1__USBOH3_UH3_DFD_OUT25		0x320 0x708 0x000 0x4 0x0
+#define MX6Q_PAD_SD4_DAT1__GPIO_2_9			0x320 0x708 0x000 0x5 0x0
+#define MX6Q_PAD_SD4_DAT1__IPU1_IPU_DIAG_BUS_9		0x320 0x708 0x000 0x6 0x0
+#define MX6Q_PAD_SD4_DAT1__IPU2_IPU_DIAG_BUS_9		0x320 0x708 0x000 0x7 0x0
+#define MX6Q_PAD_SD4_DAT2__RAWNAND_D10			0x324 0x70c 0x000 0x0 0x0
+#define MX6Q_PAD_SD4_DAT2__USDHC4_DAT2			0x324 0x70c 0x000 0x1 0x0
+#define MX6Q_PAD_SD4_DAT2__PWM4_PWMO			0x324 0x70c 0x000 0x2 0x0
+#define MX6Q_PAD_SD4_DAT2__USBOH3_UH2_DFD_OUT26		0x324 0x70c 0x000 0x3 0x0
+#define MX6Q_PAD_SD4_DAT2__USBOH3_UH3_DFD_OUT26		0x324 0x70c 0x000 0x4 0x0
+#define MX6Q_PAD_SD4_DAT2__GPIO_2_10			0x324 0x70c 0x000 0x5 0x0
+#define MX6Q_PAD_SD4_DAT2__IPU1_IPU_DIAG_BUS_10		0x324 0x70c 0x000 0x6 0x0
+#define MX6Q_PAD_SD4_DAT2__IPU2_IPU_DIAG_BUS_10		0x324 0x70c 0x000 0x7 0x0
+#define MX6Q_PAD_SD4_DAT3__RAWNAND_D11			0x328 0x710 0x000 0x0 0x0
+#define MX6Q_PAD_SD4_DAT3__USDHC4_DAT3			0x328 0x710 0x000 0x1 0x0
+#define MX6Q_PAD_SD4_DAT3__USBOH3_UH2_DFD_OUT27		0x328 0x710 0x000 0x3 0x0
+#define MX6Q_PAD_SD4_DAT3__USBOH3_UH3_DFD_OUT27		0x328 0x710 0x000 0x4 0x0
+#define MX6Q_PAD_SD4_DAT3__GPIO_2_11			0x328 0x710 0x000 0x5 0x0
+#define MX6Q_PAD_SD4_DAT3__IPU1_IPU_DIAG_BUS_11		0x328 0x710 0x000 0x6 0x0
+#define MX6Q_PAD_SD4_DAT3__IPU2_IPU_DIAG_BUS_11		0x328 0x710 0x000 0x7 0x0
+#define MX6Q_PAD_SD4_DAT4__RAWNAND_D12			0x32c 0x714 0x000 0x0 0x0
+#define MX6Q_PAD_SD4_DAT4__USDHC4_DAT4			0x32c 0x714 0x000 0x1 0x0
+#define MX6Q_PAD_SD4_DAT4__UART2_RXD			0x32c 0x714 0x928 0x2 0x6
+#define MX6Q_PAD_SD4_DAT4__USBOH3_UH2_DFD_OUT28		0x32c 0x714 0x000 0x3 0x0
+#define MX6Q_PAD_SD4_DAT4__USBOH3_UH3_DFD_OUT28		0x32c 0x714 0x000 0x4 0x0
+#define MX6Q_PAD_SD4_DAT4__GPIO_2_12			0x32c 0x714 0x000 0x5 0x0
+#define MX6Q_PAD_SD4_DAT4__IPU1_IPU_DIAG_BUS_12		0x32c 0x714 0x000 0x6 0x0
+#define MX6Q_PAD_SD4_DAT4__IPU2_IPU_DIAG_BUS_12		0x32c 0x714 0x000 0x7 0x0
+#define MX6Q_PAD_SD4_DAT5__RAWNAND_D13			0x330 0x718 0x000 0x0 0x0
+#define MX6Q_PAD_SD4_DAT5__USDHC4_DAT5			0x330 0x718 0x000 0x1 0x0
+#define MX6Q_PAD_SD4_DAT5__UART2_RTS			0x330 0x718 0x924 0x2 0x4
+#define MX6Q_PAD_SD4_DAT5__USBOH3_UH2_DFD_OUT29		0x330 0x718 0x000 0x3 0x0
+#define MX6Q_PAD_SD4_DAT5__USBOH3_UH3_DFD_OUT29		0x330 0x718 0x000 0x4 0x0
+#define MX6Q_PAD_SD4_DAT5__GPIO_2_13			0x330 0x718 0x000 0x5 0x0
+#define MX6Q_PAD_SD4_DAT5__IPU1_IPU_DIAG_BUS_13		0x330 0x718 0x000 0x6 0x0
+#define MX6Q_PAD_SD4_DAT5__IPU2_IPU_DIAG_BUS_13		0x330 0x718 0x000 0x7 0x0
+#define MX6Q_PAD_SD4_DAT6__RAWNAND_D14			0x334 0x71c 0x000 0x0 0x0
+#define MX6Q_PAD_SD4_DAT6__USDHC4_DAT6			0x334 0x71c 0x000 0x1 0x0
+#define MX6Q_PAD_SD4_DAT6__UART2_CTS			0x334 0x71c 0x924 0x2 0x5
+#define MX6Q_PAD_SD4_DAT6__USBOH3_UH2_DFD_OUT30		0x334 0x71c 0x000 0x3 0x0
+#define MX6Q_PAD_SD4_DAT6__USBOH3_UH3_DFD_OUT30		0x334 0x71c 0x000 0x4 0x0
+#define MX6Q_PAD_SD4_DAT6__GPIO_2_14			0x334 0x71c 0x000 0x5 0x0
+#define MX6Q_PAD_SD4_DAT6__IPU1_IPU_DIAG_BUS_14		0x334 0x71c 0x000 0x6 0x0
+#define MX6Q_PAD_SD4_DAT6__IPU2_IPU_DIAG_BUS_14		0x334 0x71c 0x000 0x7 0x0
+#define MX6Q_PAD_SD4_DAT7__RAWNAND_D15			0x338 0x720 0x000 0x0 0x0
+#define MX6Q_PAD_SD4_DAT7__USDHC4_DAT7			0x338 0x720 0x000 0x1 0x0
+#define MX6Q_PAD_SD4_DAT7__UART2_TXD			0x338 0x720 0x000 0x2 0x0
+#define MX6Q_PAD_SD4_DAT7__USBOH3_UH2_DFD_OUT31		0x338 0x720 0x000 0x3 0x0
+#define MX6Q_PAD_SD4_DAT7__USBOH3_UH3_DFD_OUT31		0x338 0x720 0x000 0x4 0x0
+#define MX6Q_PAD_SD4_DAT7__GPIO_2_15			0x338 0x720 0x000 0x5 0x0
+#define MX6Q_PAD_SD4_DAT7__IPU1_IPU_DIAG_BUS_15		0x338 0x720 0x000 0x6 0x0
+#define MX6Q_PAD_SD4_DAT7__IPU2_IPU_DIAG_BUS_15		0x338 0x720 0x000 0x7 0x0
+#define MX6Q_PAD_SD1_DAT1__USDHC1_DAT1			0x33c 0x724 0x000 0x0 0x0
+#define MX6Q_PAD_SD1_DAT1__ECSPI5_SS0			0x33c 0x724 0x834 0x1 0x1
+#define MX6Q_PAD_SD1_DAT1__PWM3_PWMO			0x33c 0x724 0x000 0x2 0x0
+#define MX6Q_PAD_SD1_DAT1__GPT_CAPIN2			0x33c 0x724 0x000 0x3 0x0
+#define MX6Q_PAD_SD1_DAT1__PCIE_CTRL_MUX_7		0x33c 0x724 0x000 0x4 0x0
+#define MX6Q_PAD_SD1_DAT1__GPIO_1_17			0x33c 0x724 0x000 0x5 0x0
+#define MX6Q_PAD_SD1_DAT1__HDMI_TX_OPHYDTB_0		0x33c 0x724 0x000 0x6 0x0
+#define MX6Q_PAD_SD1_DAT1__ANATOP_TESTO_8		0x33c 0x724 0x000 0x7 0x0
+#define MX6Q_PAD_SD1_DAT0__USDHC1_DAT0			0x340 0x728 0x000 0x0 0x0
+#define MX6Q_PAD_SD1_DAT0__ECSPI5_MISO			0x340 0x728 0x82c 0x1 0x1
+#define MX6Q_PAD_SD1_DAT0__CAAM_WRAP_RNG_OSCOBS		0x340 0x728 0x000 0x2 0x0
+#define MX6Q_PAD_SD1_DAT0__GPT_CAPIN1			0x340 0x728 0x000 0x3 0x0
+#define MX6Q_PAD_SD1_DAT0__PCIE_CTRL_MUX_8		0x340 0x728 0x000 0x4 0x0
+#define MX6Q_PAD_SD1_DAT0__GPIO_1_16			0x340 0x728 0x000 0x5 0x0
+#define MX6Q_PAD_SD1_DAT0__HDMI_TX_OPHYDTB_1		0x340 0x728 0x000 0x6 0x0
+#define MX6Q_PAD_SD1_DAT0__ANATOP_TESTO_7		0x340 0x728 0x000 0x7 0x0
+#define MX6Q_PAD_SD1_DAT3__USDHC1_DAT3			0x344 0x72c 0x000 0x0 0x0
+#define MX6Q_PAD_SD1_DAT3__ECSPI5_SS2			0x344 0x72c 0x000 0x1 0x0
+#define MX6Q_PAD_SD1_DAT3__GPT_CMPOUT3			0x344 0x72c 0x000 0x2 0x0
+#define MX6Q_PAD_SD1_DAT3__PWM1_PWMO			0x344 0x72c 0x000 0x3 0x0
+#define MX6Q_PAD_SD1_DAT3__WDOG2_WDOG_B			0x344 0x72c 0x000 0x4 0x0
+#define MX6Q_PAD_SD1_DAT3__GPIO_1_21			0x344 0x72c 0x000 0x5 0x0
+#define MX6Q_PAD_SD1_DAT3__WDOG2_WDOG_RST_B_DEB		0x344 0x72c 0x000 0x6 0x0
+#define MX6Q_PAD_SD1_DAT3__ANATOP_TESTO_6		0x344 0x72c 0x000 0x7 0x0
+#define MX6Q_PAD_SD1_CMD__USDHC1_CMD			0x348 0x730 0x000 0x0 0x0
+#define MX6Q_PAD_SD1_CMD__ECSPI5_MOSI			0x348 0x730 0x830 0x1 0x0
+#define MX6Q_PAD_SD1_CMD__PWM4_PWMO			0x348 0x730 0x000 0x2 0x0
+#define MX6Q_PAD_SD1_CMD__GPT_CMPOUT1			0x348 0x730 0x000 0x3 0x0
+#define MX6Q_PAD_SD1_CMD__GPIO_1_18			0x348 0x730 0x000 0x5 0x0
+#define MX6Q_PAD_SD1_CMD__ANATOP_TESTO_5		0x348 0x730 0x000 0x7 0x0
+#define MX6Q_PAD_SD1_DAT2__USDHC1_DAT2			0x34c 0x734 0x000 0x0 0x0
+#define MX6Q_PAD_SD1_DAT2__ECSPI5_SS1			0x34c 0x734 0x838 0x1 0x1
+#define MX6Q_PAD_SD1_DAT2__GPT_CMPOUT2			0x34c 0x734 0x000 0x2 0x0
+#define MX6Q_PAD_SD1_DAT2__PWM2_PWMO			0x34c 0x734 0x000 0x3 0x0
+#define MX6Q_PAD_SD1_DAT2__WDOG1_WDOG_B			0x34c 0x734 0x000 0x4 0x0
+#define MX6Q_PAD_SD1_DAT2__GPIO_1_19			0x34c 0x734 0x000 0x5 0x0
+#define MX6Q_PAD_SD1_DAT2__WDOG1_WDOG_RST_B_DEB		0x34c 0x734 0x000 0x6 0x0
+#define MX6Q_PAD_SD1_DAT2__ANATOP_TESTO_4		0x34c 0x734 0x000 0x7 0x0
+#define MX6Q_PAD_SD1_CLK__USDHC1_CLK			0x350 0x738 0x000 0x0 0x0
+#define MX6Q_PAD_SD1_CLK__ECSPI5_SCLK			0x350 0x738 0x828 0x1 0x0
+#define MX6Q_PAD_SD1_CLK__OSC32K_32K_OUT		0x350 0x738 0x000 0x2 0x0
+#define MX6Q_PAD_SD1_CLK__GPT_CLKIN			0x350 0x738 0x000 0x3 0x0
+#define MX6Q_PAD_SD1_CLK__GPIO_1_20			0x350 0x738 0x000 0x5 0x0
+#define MX6Q_PAD_SD1_CLK__PHY_DTB_0			0x350 0x738 0x000 0x6 0x0
+#define MX6Q_PAD_SD1_CLK__SATA_PHY_DTB_0		0x350 0x738 0x000 0x7 0x0
+#define MX6Q_PAD_SD2_CLK__USDHC2_CLK			0x354 0x73c 0x000 0x0 0x0
+#define MX6Q_PAD_SD2_CLK__ECSPI5_SCLK			0x354 0x73c 0x828 0x1 0x1
+#define MX6Q_PAD_SD2_CLK__KPP_COL_5			0x354 0x73c 0x8e8 0x2 0x3
+#define MX6Q_PAD_SD2_CLK__AUDMUX_AUD4_RXFS		0x354 0x73c 0x7c0 0x3 0x1
+#define MX6Q_PAD_SD2_CLK__PCIE_CTRL_MUX_9		0x354 0x73c 0x000 0x4 0x0
+#define MX6Q_PAD_SD2_CLK__GPIO_1_10			0x354 0x73c 0x000 0x5 0x0
+#define MX6Q_PAD_SD2_CLK__PHY_DTB_1			0x354 0x73c 0x000 0x6 0x0
+#define MX6Q_PAD_SD2_CLK__SATA_PHY_DTB_1		0x354 0x73c 0x000 0x7 0x0
+#define MX6Q_PAD_SD2_CMD__USDHC2_CMD			0x358 0x740 0x000 0x0 0x0
+#define MX6Q_PAD_SD2_CMD__ECSPI5_MOSI			0x358 0x740 0x830 0x1 0x1
+#define MX6Q_PAD_SD2_CMD__KPP_ROW_5			0x358 0x740 0x8f4 0x2 0x2
+#define MX6Q_PAD_SD2_CMD__AUDMUX_AUD4_RXC		0x358 0x740 0x7bc 0x3 0x1
+#define MX6Q_PAD_SD2_CMD__PCIE_CTRL_MUX_10		0x358 0x740 0x000 0x4 0x0
+#define MX6Q_PAD_SD2_CMD__GPIO_1_11			0x358 0x740 0x000 0x5 0x0
+#define MX6Q_PAD_SD2_DAT3__USDHC2_DAT3			0x35c 0x744 0x000 0x0 0x0
+#define MX6Q_PAD_SD2_DAT3__ECSPI5_SS3			0x35c 0x744 0x000 0x1 0x0
+#define MX6Q_PAD_SD2_DAT3__KPP_COL_6			0x35c 0x744 0x8ec 0x2 0x2
+#define MX6Q_PAD_SD2_DAT3__AUDMUX_AUD4_TXC		0x35c 0x744 0x7c4 0x3 0x1
+#define MX6Q_PAD_SD2_DAT3__PCIE_CTRL_MUX_11		0x35c 0x744 0x000 0x4 0x0
+#define MX6Q_PAD_SD2_DAT3__GPIO_1_12			0x35c 0x744 0x000 0x5 0x0
+#define MX6Q_PAD_SD2_DAT3__SJC_DONE			0x35c 0x744 0x000 0x6 0x0
+#define MX6Q_PAD_SD2_DAT3__ANATOP_TESTO_3		0x35c 0x744 0x000 0x7 0x0
+#define MX6Q_PAD_ENET_RX_ER__ANATOP_USBOTG_ID		0x1d8 0x4ec 0x000 0x0 0x0
+#define MX6Q_PAD_GPIO_1__ANATOP_USBOTG_ID		0x224 0x5f4 0x000 0x3 0x0
+
+#endif /* __DTS_IMX6Q_PINFUNC_H */
diff --git a/arch/arm/boot/dts/imx6q-sabreauto.dts b/arch/arm/boot/dts/imx6q-sabreauto.dts
deleted file mode 100644
index 656d489..0000000
--- a/arch/arm/boot/dts/imx6q-sabreauto.dts
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright 2012 Freescale Semiconductor, Inc.
- * Copyright 2011 Linaro Ltd.
- *
- * 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
- */
-
-/dts-v1/;
-/include/ "imx6q.dtsi"
-
-/ {
-	model = "Freescale i.MX6 Quad SABRE Automotive Board";
-	compatible = "fsl,imx6q-sabreauto", "fsl,imx6q";
-
-	memory {
-		reg = <0x10000000 0x80000000>;
-	};
-};
-
-&iomuxc {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_hog>;
-
-	hog {
-		pinctrl_hog: hoggrp {
-			fsl,pins = <
-				1376 0x80000000	/* MX6Q_PAD_NANDF_CS2__GPIO_6_15 */
-				13   0x80000000	/* MX6Q_PAD_SD2_DAT2__GPIO_1_13 */
-			>;
-		};
-	};
-};
-
-&uart4 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart4_1>;
-	status = "okay";
-};
-
-&fec {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_enet_2>;
-	phy-mode = "rgmii";
-	status = "okay";
-};
-
-&usdhc3 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_usdhc3_1>;
-	cd-gpios = <&gpio6 15 0>;
-	wp-gpios = <&gpio1 13 0>;
-	status = "okay";
-};
diff --git a/arch/arm/boot/dts/imx6q-sabreauto.dtsp b/arch/arm/boot/dts/imx6q-sabreauto.dtsp
new file mode 100644
index 0000000..99ba364
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-sabreauto.dtsp
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * 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
+ */
+
+/dts-v1/;
+
+#include "imx6q.dtsip"
+#include "imx6qdl-sabreauto.dtsip"
+
+/ {
+	model = "Freescale i.MX6 Quad SABRE Automotive Board";
+	compatible = "fsl,imx6q-sabreauto", "fsl,imx6q";
+};
+
+&iomuxc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hog>;
+
+	hog {
+		pinctrl_hog: hoggrp {
+			fsl,pins = <
+				MX6Q_PAD_NANDF_CS2__GPIO_6_15 0x80000000
+				MX6Q_PAD_SD2_DAT2__GPIO_1_13  0x80000000
+			>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/imx6q-sabrelite.dts b/arch/arm/boot/dts/imx6q-sabrelite.dts
deleted file mode 100644
index 2ce355c..0000000
--- a/arch/arm/boot/dts/imx6q-sabrelite.dts
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * Copyright 2011 Freescale Semiconductor, Inc.
- * Copyright 2011 Linaro Ltd.
- *
- * 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
- */
-
-/dts-v1/;
-/include/ "imx6q.dtsi"
-
-/ {
-	model = "Freescale i.MX6 Quad SABRE Lite Board";
-	compatible = "fsl,imx6q-sabrelite", "fsl,imx6q";
-
-	memory {
-		reg = <0x10000000 0x40000000>;
-	};
-
-	regulators {
-		compatible = "simple-bus";
-
-		reg_2p5v: 2p5v {
-			compatible = "regulator-fixed";
-			regulator-name = "2P5V";
-			regulator-min-microvolt = <2500000>;
-			regulator-max-microvolt = <2500000>;
-			regulator-always-on;
-		};
-
-		reg_3p3v: 3p3v {
-			compatible = "regulator-fixed";
-			regulator-name = "3P3V";
-			regulator-min-microvolt = <3300000>;
-			regulator-max-microvolt = <3300000>;
-			regulator-always-on;
-		};
-
-		reg_usb_otg_vbus: usb_otg_vbus {
-			compatible = "regulator-fixed";
-			regulator-name = "usb_otg_vbus";
-			regulator-min-microvolt = <5000000>;
-			regulator-max-microvolt = <5000000>;
-			gpio = <&gpio3 22 0>;
-			enable-active-high;
-		};
-	};
-
-	sound {
-		compatible = "fsl,imx6q-sabrelite-sgtl5000",
-			     "fsl,imx-audio-sgtl5000";
-		model = "imx6q-sabrelite-sgtl5000";
-		ssi-controller = <&ssi1>;
-		audio-codec = <&codec>;
-		audio-routing =
-			"MIC_IN", "Mic Jack",
-			"Mic Jack", "Mic Bias",
-			"Headphone Jack", "HP_OUT";
-		mux-int-port = <1>;
-		mux-ext-port = <4>;
-	};
-};
-
-&ecspi1 {
-	fsl,spi-num-chipselects = <1>;
-	cs-gpios = <&gpio3 19 0>;
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_ecspi1_1>;
-	status = "okay";
-
-	flash: m25p80@0 {
-		compatible = "sst,sst25vf016b";
-		spi-max-frequency = <20000000>;
-		reg = <0>;
-	};
-};
-
-&ssi1 {
-	fsl,mode = "i2s-slave";
-	status = "okay";
-};
-
-&iomuxc {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_hog>;
-
-	hog {
-		pinctrl_hog: hoggrp {
-			fsl,pins = <
-				1450 0x80000000	/* MX6Q_PAD_NANDF_D6__GPIO_2_6 */
-				1458 0x80000000	/* MX6Q_PAD_NANDF_D7__GPIO_2_7 */
-				121  0x80000000	/* MX6Q_PAD_EIM_D19__GPIO_3_19 */
-				144  0x80000000	/* MX6Q_PAD_EIM_D22__GPIO_3_22 */
-				152  0x80000000	/* MX6Q_PAD_EIM_D23__GPIO_3_23 */
-				1262 0x80000000 /* MX6Q_PAD_SD3_DAT5__GPIO_7_0 */
-				1270 0x1f0b0	/* MX6Q_PAD_SD3_DAT4__GPIO_7_1 */
-				953  0x80000000	/* MX6Q_PAD_GPIO_0__CCM_CLKO */
-			>;
-		};
-	};
-};
-
-&usbotg {
-	vbus-supply = <&reg_usb_otg_vbus>;
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_usbotg_1>;
-	disable-over-current;
-	status = "okay";
-};
-
-&usbh1 {
-	status = "okay";
-};
-
-&fec {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_enet_1>;
-	phy-mode = "rgmii";
-	phy-reset-gpios = <&gpio3 23 0>;
-	status = "okay";
-};
-
-&usdhc3 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_usdhc3_2>;
-	cd-gpios = <&gpio7 0 0>;
-	wp-gpios = <&gpio7 1 0>;
-	vmmc-supply = <&reg_3p3v>;
-	status = "okay";
-};
-
-&usdhc4 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_usdhc4_2>;
-	cd-gpios = <&gpio2 6 0>;
-	wp-gpios = <&gpio2 7 0>;
-	vmmc-supply = <&reg_3p3v>;
-	status = "okay";
-};
-
-&audmux {
-	status = "okay";
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_audmux_1>;
-};
-
-&uart2 {
-	status = "okay";
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart2_1>;
-};
-
-&i2c1 {
-	status = "okay";
-	clock-frequency = <100000>;
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_i2c1_1>;
-
-	codec: sgtl5000@0a {
-		compatible = "fsl,sgtl5000";
-		reg = <0x0a>;
-		clocks = <&clks 169>;
-		VDDA-supply = <&reg_2p5v>;
-		VDDIO-supply = <&reg_3p3v>;
-	};
-};
diff --git a/arch/arm/boot/dts/imx6q-sabrelite.dtsp b/arch/arm/boot/dts/imx6q-sabrelite.dtsp
new file mode 100644
index 0000000..e384f83
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-sabrelite.dtsp
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * 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
+ */
+
+/dts-v1/;
+#include "imx6q.dtsip"
+
+/ {
+	model = "Freescale i.MX6 Quad SABRE Lite Board";
+	compatible = "fsl,imx6q-sabrelite", "fsl,imx6q";
+
+	memory {
+		reg = <0x10000000 0x40000000>;
+	};
+
+	regulators {
+		compatible = "simple-bus";
+
+		reg_2p5v: 2p5v {
+			compatible = "regulator-fixed";
+			regulator-name = "2P5V";
+			regulator-min-microvolt = <2500000>;
+			regulator-max-microvolt = <2500000>;
+			regulator-always-on;
+		};
+
+		reg_3p3v: 3p3v {
+			compatible = "regulator-fixed";
+			regulator-name = "3P3V";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+
+		reg_usb_otg_vbus: usb_otg_vbus {
+			compatible = "regulator-fixed";
+			regulator-name = "usb_otg_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			gpio = <&gpio3 22 0>;
+			enable-active-high;
+		};
+	};
+
+	sound {
+		compatible = "fsl,imx6q-sabrelite-sgtl5000",
+			     "fsl,imx-audio-sgtl5000";
+		model = "imx6q-sabrelite-sgtl5000";
+		ssi-controller = <&ssi1>;
+		audio-codec = <&codec>;
+		audio-routing =
+			"MIC_IN", "Mic Jack",
+			"Mic Jack", "Mic Bias",
+			"Headphone Jack", "HP_OUT";
+		mux-int-port = <1>;
+		mux-ext-port = <4>;
+	};
+};
+
+&ecspi1 {
+	fsl,spi-num-chipselects = <1>;
+	cs-gpios = <&gpio3 19 0>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ecspi1_1>;
+	status = "okay";
+
+	flash: m25p80@0 {
+		compatible = "sst,sst25vf016b";
+		spi-max-frequency = <20000000>;
+		reg = <0>;
+	};
+};
+
+&ssi1 {
+	fsl,mode = "i2s-slave";
+	status = "okay";
+};
+
+&iomuxc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hog>;
+
+	hog {
+		pinctrl_hog: hoggrp {
+			fsl,pins = <
+				MX6Q_PAD_NANDF_D6__GPIO_2_6 0x80000000
+				MX6Q_PAD_NANDF_D7__GPIO_2_7 0x80000000
+				MX6Q_PAD_EIM_D19__GPIO_3_19 0x80000000
+				MX6Q_PAD_EIM_D22__GPIO_3_22 0x80000000
+				MX6Q_PAD_EIM_D23__GPIO_3_23 0x80000000
+				MX6Q_PAD_SD3_DAT5__GPIO_7_0 0x80000000
+				MX6Q_PAD_SD3_DAT4__GPIO_7_1 0x1f0b0
+				MX6Q_PAD_GPIO_0__CCM_CLKO   0x80000000
+			>;
+		};
+	};
+};
+
+&usbotg {
+	vbus-supply = <&reg_usb_otg_vbus>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbotg_1>;
+	disable-over-current;
+	status = "okay";
+};
+
+&usbh1 {
+	status = "okay";
+};
+
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet_1>;
+	phy-mode = "rgmii";
+	phy-reset-gpios = <&gpio3 23 0>;
+	status = "okay";
+};
+
+&usdhc3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc3_2>;
+	cd-gpios = <&gpio7 0 0>;
+	wp-gpios = <&gpio7 1 0>;
+	vmmc-supply = <&reg_3p3v>;
+	status = "okay";
+};
+
+&usdhc4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc4_2>;
+	cd-gpios = <&gpio2 6 0>;
+	wp-gpios = <&gpio2 7 0>;
+	vmmc-supply = <&reg_3p3v>;
+	status = "okay";
+};
+
+&audmux {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_audmux_1>;
+};
+
+&uart2 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2_1>;
+};
+
+&i2c1 {
+	status = "okay";
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1_1>;
+
+	codec: sgtl5000@0a {
+		compatible = "fsl,sgtl5000";
+		reg = <0x0a>;
+		clocks = <&clks 169>;
+		VDDA-supply = <&reg_2p5v>;
+		VDDIO-supply = <&reg_3p3v>;
+	};
+};
diff --git a/arch/arm/boot/dts/imx6q-sabresd.dts b/arch/arm/boot/dts/imx6q-sabresd.dts
deleted file mode 100644
index 2dea304..0000000
--- a/arch/arm/boot/dts/imx6q-sabresd.dts
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright 2012 Freescale Semiconductor, Inc.
- * Copyright 2011 Linaro Ltd.
- *
- * 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
- */
-
-/dts-v1/;
-/include/ "imx6q.dtsi"
-
-/ {
-	model = "Freescale i.MX6Q SABRE Smart Device Board";
-	compatible = "fsl,imx6q-sabresd", "fsl,imx6q";
-
-	memory {
-		reg = <0x10000000 0x40000000>;
-	};
-
-	gpio-keys {
-		compatible = "gpio-keys";
-
-		volume-up {
-			label = "Volume Up";
-			gpios = <&gpio1 4 0>;
-			linux,code = <115>; /* KEY_VOLUMEUP */
-		};
-
-		volume-down {
-			label = "Volume Down";
-			gpios = <&gpio1 5 0>;
-			linux,code = <114>; /* KEY_VOLUMEDOWN */
-		};
-	};
-};
-
-&uart1 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart1_1>;
-	status = "okay";
-};
-
-&iomuxc {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_hog>;
-
-	hog {
-		pinctrl_hog: hoggrp {
-			fsl,pins = <
-				1004 0x80000000 /* MX6Q_PAD_GPIO_4__GPIO_1_4 */
-				1012 0x80000000 /* MX6Q_PAD_GPIO_5__GPIO_1_5 */
-				1402 0x80000000	/* MX6Q_PAD_NANDF_D0__GPIO_2_0 */
-				1410 0x80000000	/* MX6Q_PAD_NANDF_D1__GPIO_2_1 */
-				1418 0x80000000	/* MX6Q_PAD_NANDF_D2__GPIO_2_2 */
-				1426 0x80000000	/* MX6Q_PAD_NANDF_D3__GPIO_2_3 */
-			>;
-		};
-	};
-};
-
-&fec {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_enet_1>;
-	phy-mode = "rgmii";
-	status = "okay";
-};
-
-&usdhc2 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_usdhc2_1>;
-	cd-gpios = <&gpio2 2 0>;
-	wp-gpios = <&gpio2 3 0>;
-	status = "okay";
-};
-
-&usdhc3 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_usdhc3_1>;
-	cd-gpios = <&gpio2 0 0>;
-	wp-gpios = <&gpio2 1 0>;
-	status = "okay";
-};
diff --git a/arch/arm/boot/dts/imx6q-sabresd.dtsp b/arch/arm/boot/dts/imx6q-sabresd.dtsp
new file mode 100644
index 0000000..05f6fbd
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-sabresd.dtsp
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * 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
+ */
+
+/dts-v1/;
+
+#include "imx6q.dtsip"
+#include "imx6qdl-sabresd.dtsip"
+
+/ {
+	model = "Freescale i.MX6 Quad SABRE Smart Device Board";
+	compatible = "fsl,imx6q-sabresd", "fsl,imx6q";
+};
+
+&iomuxc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hog>;
+
+	hog {
+		pinctrl_hog: hoggrp {
+			fsl,pins = <
+				MX6Q_PAD_GPIO_4__GPIO_1_4   0x80000000
+				MX6Q_PAD_GPIO_5__GPIO_1_5   0x80000000
+				MX6Q_PAD_NANDF_D0__GPIO_2_0 0x80000000
+				MX6Q_PAD_NANDF_D1__GPIO_2_1 0x80000000
+				MX6Q_PAD_NANDF_D2__GPIO_2_2 0x80000000
+				MX6Q_PAD_NANDF_D3__GPIO_2_3 0x80000000
+			>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/imx6q-sbc6x.dtsp b/arch/arm/boot/dts/imx6q-sbc6x.dtsp
new file mode 100644
index 0000000..8d68494
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-sbc6x.dtsp
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2013 Pavel Machek <pavel@denx.de>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License V2.
+ */
+
+/dts-v1/;
+#include "imx6q.dtsip"
+
+/ {
+	model = "MicroSys sbc6x board";
+	compatible = "microsys,sbc6x", "fsl,imx6q";
+
+	memory {
+		reg = <0x10000000 0x80000000>;
+	};
+};
+
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet_1>;
+	phy-mode = "rgmii";
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1_1>;
+	status = "okay";
+};
+
+&usbotg {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbotg_1>;
+	disable-over-current;
+	status = "okay";
+};
+
+&usdhc3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc3_2>;
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi
deleted file mode 100644
index cba021e..0000000
--- a/arch/arm/boot/dts/imx6q.dtsi
+++ /dev/null
@@ -1,296 +0,0 @@
-
-/*
- * Copyright 2013 Freescale Semiconductor, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-
-/include/ "imx6qdl.dtsi"
-
-/ {
-	cpus {
-		#address-cells = <1>;
-		#size-cells = <0>;
-
-		cpu@0 {
-			compatible = "arm,cortex-a9";
-			reg = <0>;
-			next-level-cache = <&L2>;
-			operating-points = <
-				/* kHz    uV */
-				1200000 1275000
-				996000  1250000
-				792000  1150000
-				396000  950000
-			>;
-			clock-latency = <61036>; /* two CLK32 periods */
-			clocks = <&clks 104>, <&clks 6>, <&clks 16>,
-				 <&clks 17>, <&clks 170>;
-			clock-names = "arm", "pll2_pfd2_396m", "step",
-				      "pll1_sw", "pll1_sys";
-			arm-supply = <&reg_arm>;
-			pu-supply = <&reg_pu>;
-			soc-supply = <&reg_soc>;
-		};
-
-		cpu@1 {
-			compatible = "arm,cortex-a9";
-			reg = <1>;
-			next-level-cache = <&L2>;
-		};
-
-		cpu@2 {
-			compatible = "arm,cortex-a9";
-			reg = <2>;
-			next-level-cache = <&L2>;
-		};
-
-		cpu@3 {
-			compatible = "arm,cortex-a9";
-			reg = <3>;
-			next-level-cache = <&L2>;
-		};
-	};
-
-	soc {
-		aips-bus@02000000 { /* AIPS1 */
-			spba-bus@02000000 {
-				ecspi5: ecspi@02018000 {
-					#address-cells = <1>;
-					#size-cells = <0>;
-					compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
-					reg = <0x02018000 0x4000>;
-					interrupts = <0 35 0x04>;
-					clocks = <&clks 116>, <&clks 116>;
-					clock-names = "ipg", "per";
-					status = "disabled";
-				};
-			};
-
-			iomuxc: iomuxc@020e0000 {
-				compatible = "fsl,imx6q-iomuxc";
-				reg = <0x020e0000 0x4000>;
-
-				/* shared pinctrl settings */
-				audmux {
-					pinctrl_audmux_1: audmux-1 {
-						fsl,pins = <
-							18   0x80000000	/* MX6Q_PAD_SD2_DAT0__AUDMUX_AUD4_RXD */
-							1586 0x80000000	/* MX6Q_PAD_SD2_DAT3__AUDMUX_AUD4_TXC */
-							11   0x80000000	/* MX6Q_PAD_SD2_DAT2__AUDMUX_AUD4_TXD */
-							3    0x80000000	/* MX6Q_PAD_SD2_DAT1__AUDMUX_AUD4_TXFS */
-						>;
-					};
-				};
-
-				ecspi1 {
-					pinctrl_ecspi1_1: ecspi1grp-1 {
-						fsl,pins = <
-							101 0x100b1	/* MX6Q_PAD_EIM_D17__ECSPI1_MISO */
-							109 0x100b1	/* MX6Q_PAD_EIM_D18__ECSPI1_MOSI */
-							94  0x100b1	/* MX6Q_PAD_EIM_D16__ECSPI1_SCLK */
-						>;
-					};
-				};
-
-				enet {
-					pinctrl_enet_1: enetgrp-1 {
-						fsl,pins = <
-							695 0x1b0b0	/* MX6Q_PAD_ENET_MDIO__ENET_MDIO */
-							756 0x1b0b0	/* MX6Q_PAD_ENET_MDC__ENET_MDC */
-							24  0x1b0b0	/* MX6Q_PAD_RGMII_TXC__ENET_RGMII_TXC */
-							30  0x1b0b0	/* MX6Q_PAD_RGMII_TD0__ENET_RGMII_TD0 */
-							34  0x1b0b0	/* MX6Q_PAD_RGMII_TD1__ENET_RGMII_TD1 */
-							39  0x1b0b0	/* MX6Q_PAD_RGMII_TD2__ENET_RGMII_TD2 */
-							44  0x1b0b0	/* MX6Q_PAD_RGMII_TD3__ENET_RGMII_TD3 */
-							56  0x1b0b0	/* MX6Q_PAD_RGMII_TX_CTL__RGMII_TX_CTL */
-							702 0x1b0b0	/* MX6Q_PAD_ENET_REF_CLK__ENET_TX_CLK */
-							74  0x1b0b0	/* MX6Q_PAD_RGMII_RXC__ENET_RGMII_RXC */
-							52  0x1b0b0	/* MX6Q_PAD_RGMII_RD0__ENET_RGMII_RD0 */
-							61  0x1b0b0	/* MX6Q_PAD_RGMII_RD1__ENET_RGMII_RD1 */
-							66  0x1b0b0	/* MX6Q_PAD_RGMII_RD2__ENET_RGMII_RD2 */
-							70  0x1b0b0	/* MX6Q_PAD_RGMII_RD3__ENET_RGMII_RD3 */
-							48  0x1b0b0	/* MX6Q_PAD_RGMII_RX_CTL__RGMII_RX_CTL */
-							1033 0x4001b0a8	/* MX6Q_PAD_GPIO_16__ENET_ANATOP_ETHERNET_REF_OUT*/
-						>;
-					};
-
-					pinctrl_enet_2: enetgrp-2 {
-						fsl,pins = <
-							890 0x1b0b0	/* MX6Q_PAD_KEY_COL1__ENET_MDIO */
-							909 0x1b0b0	/* MX6Q_PAD_KEY_COL2__ENET_MDC */
-							24  0x1b0b0	/* MX6Q_PAD_RGMII_TXC__ENET_RGMII_TXC */
-							30  0x1b0b0	/* MX6Q_PAD_RGMII_TD0__ENET_RGMII_TD0 */
-							34  0x1b0b0	/* MX6Q_PAD_RGMII_TD1__ENET_RGMII_TD1 */
-							39  0x1b0b0	/* MX6Q_PAD_RGMII_TD2__ENET_RGMII_TD2 */
-							44  0x1b0b0	/* MX6Q_PAD_RGMII_TD3__ENET_RGMII_TD3 */
-							56  0x1b0b0	/* MX6Q_PAD_RGMII_TX_CTL__RGMII_TX_CTL */
-							702 0x1b0b0	/* MX6Q_PAD_ENET_REF_CLK__ENET_TX_CLK */
-							74  0x1b0b0	/* MX6Q_PAD_RGMII_RXC__ENET_RGMII_RXC */
-							52  0x1b0b0	/* MX6Q_PAD_RGMII_RD0__ENET_RGMII_RD0 */
-							61  0x1b0b0	/* MX6Q_PAD_RGMII_RD1__ENET_RGMII_RD1 */
-							66  0x1b0b0	/* MX6Q_PAD_RGMII_RD2__ENET_RGMII_RD2 */
-							70  0x1b0b0	/* MX6Q_PAD_RGMII_RD3__ENET_RGMII_RD3 */
-							48  0x1b0b0	/* MX6Q_PAD_RGMII_RX_CTL__RGMII_RX_CTL */
-						>;
-					};
-				};
-
-				gpmi-nand {
-					pinctrl_gpmi_nand_1: gpmi-nand-1 {
-						fsl,pins = <
-							1328 0xb0b1	/* MX6Q_PAD_NANDF_CLE__RAWNAND_CLE */
-							1336 0xb0b1	/* MX6Q_PAD_NANDF_ALE__RAWNAND_ALE */
-							1344 0xb0b1	/* MX6Q_PAD_NANDF_WP_B__RAWNAND_RESETN */
-							1352 0xb000	/* MX6Q_PAD_NANDF_RB0__RAWNAND_READY0 */
-							1360 0xb0b1	/* MX6Q_PAD_NANDF_CS0__RAWNAND_CE0N */
-							1365 0xb0b1	/* MX6Q_PAD_NANDF_CS1__RAWNAND_CE1N */
-							1371 0xb0b1	/* MX6Q_PAD_NANDF_CS2__RAWNAND_CE2N */
-							1378 0xb0b1	/* MX6Q_PAD_NANDF_CS3__RAWNAND_CE3N */
-							1387 0xb0b1	/* MX6Q_PAD_SD4_CMD__RAWNAND_RDN */
-							1393 0xb0b1	/* MX6Q_PAD_SD4_CLK__RAWNAND_WRN */
-							1397 0xb0b1	/* MX6Q_PAD_NANDF_D0__RAWNAND_D0 */
-							1405 0xb0b1	/* MX6Q_PAD_NANDF_D1__RAWNAND_D1 */
-							1413 0xb0b1	/* MX6Q_PAD_NANDF_D2__RAWNAND_D2 */
-							1421 0xb0b1	/* MX6Q_PAD_NANDF_D3__RAWNAND_D3 */
-							1429 0xb0b1	/* MX6Q_PAD_NANDF_D4__RAWNAND_D4 */
-							1437 0xb0b1	/* MX6Q_PAD_NANDF_D5__RAWNAND_D5 */
-							1445 0xb0b1	/* MX6Q_PAD_NANDF_D6__RAWNAND_D6 */
-							1453 0xb0b1	/* MX6Q_PAD_NANDF_D7__RAWNAND_D7 */
-							1463 0x00b1	/* MX6Q_PAD_SD4_DAT0__RAWNAND_DQS */
-						>;
-					};
-				};
-
-				i2c1 {
-					pinctrl_i2c1_1: i2c1grp-1 {
-						fsl,pins = <
-							137 0x4001b8b1	/* MX6Q_PAD_EIM_D21__I2C1_SCL */
-							196 0x4001b8b1	/* MX6Q_PAD_EIM_D28__I2C1_SDA */
-						>;
-					};
-				};
-
-				uart1 {
-					pinctrl_uart1_1: uart1grp-1 {
-						fsl,pins = <
-							1140 0x1b0b1	/* MX6Q_PAD_CSI0_DAT10__UART1_TXD */
-							1148 0x1b0b1	/* MX6Q_PAD_CSI0_DAT11__UART1_RXD */
-						>;
-					};
-				};
-
-				uart2 {
-					pinctrl_uart2_1: uart2grp-1 {
-						fsl,pins = <
-							183 0x1b0b1	/* MX6Q_PAD_EIM_D26__UART2_TXD */
-							191 0x1b0b1	/* MX6Q_PAD_EIM_D27__UART2_RXD */
-						>;
-					};
-				};
-
-				uart4 {
-					pinctrl_uart4_1: uart4grp-1 {
-						fsl,pins = <
-							877 0x1b0b1	/* MX6Q_PAD_KEY_COL0__UART4_TXD */
-							885 0x1b0b1	/* MX6Q_PAD_KEY_ROW0__UART4_RXD */
-						>;
-					};
-				};
-
-				usbotg {
-					pinctrl_usbotg_1: usbotggrp-1 {
-						fsl,pins = <
-							1592 0x17059	/* MX6Q_PAD_GPIO_1__ANATOP_USBOTG_ID */
-						>;
-					};
-				};
-
-				usdhc2 {
-					pinctrl_usdhc2_1: usdhc2grp-1 {
-						fsl,pins = <
-							1577 0x17059	/* MX6Q_PAD_SD2_CMD__USDHC2_CMD */
-							1569 0x10059	/* MX6Q_PAD_SD2_CLK__USDHC2_CLK */
-							16   0x17059	/* MX6Q_PAD_SD2_DAT0__USDHC2_DAT0 */
-							0    0x17059	/* MX6Q_PAD_SD2_DAT1__USDHC2_DAT1 */
-							8    0x17059	/* MX6Q_PAD_SD2_DAT2__USDHC2_DAT2 */
-							1583 0x17059	/* MX6Q_PAD_SD2_DAT3__USDHC2_DAT3 */
-							1430 0x17059	/* MX6Q_PAD_NANDF_D4__USDHC2_DAT4 */
-							1438 0x17059	/* MX6Q_PAD_NANDF_D5__USDHC2_DAT5 */
-							1446 0x17059	/* MX6Q_PAD_NANDF_D6__USDHC2_DAT6 */
-							1454 0x17059	/* MX6Q_PAD_NANDF_D7__USDHC2_DAT7 */
-						>;
-					};
-				};
-
-				usdhc3 {
-					pinctrl_usdhc3_1: usdhc3grp-1 {
-						fsl,pins = <
-							1273 0x17059	/* MX6Q_PAD_SD3_CMD__USDHC3_CMD */
-							1281 0x10059	/* MX6Q_PAD_SD3_CLK__USDHC3_CLK	*/
-							1289 0x17059	/* MX6Q_PAD_SD3_DAT0__USDHC3_DAT0 */
-							1297 0x17059	/* MX6Q_PAD_SD3_DAT1__USDHC3_DAT1 */
-							1305 0x17059	/* MX6Q_PAD_SD3_DAT2__USDHC3_DAT2 */
-							1312 0x17059	/* MX6Q_PAD_SD3_DAT3__USDHC3_DAT3 */
-							1265 0x17059	/* MX6Q_PAD_SD3_DAT4__USDHC3_DAT4 */
-							1257 0x17059	/* MX6Q_PAD_SD3_DAT5__USDHC3_DAT5 */
-							1249 0x17059	/* MX6Q_PAD_SD3_DAT6__USDHC3_DAT6 */
-							1241 0x17059	/* MX6Q_PAD_SD3_DAT7__USDHC3_DAT7 */
-						>;
-					};
-
-					pinctrl_usdhc3_2: usdhc3grp-2 {
-						fsl,pins = <
-							1273 0x17059	/* MX6Q_PAD_SD3_CMD__USDHC3_CMD */
-							1281 0x10059	/* MX6Q_PAD_SD3_CLK__USDHC3_CLK	*/
-							1289 0x17059	/* MX6Q_PAD_SD3_DAT0__USDHC3_DAT0 */
-							1297 0x17059	/* MX6Q_PAD_SD3_DAT1__USDHC3_DAT1 */
-							1305 0x17059	/* MX6Q_PAD_SD3_DAT2__USDHC3_DAT2 */
-							1312 0x17059	/* MX6Q_PAD_SD3_DAT3__USDHC3_DAT3 */
-						>;
-					};
-				};
-
-				usdhc4 {
-					pinctrl_usdhc4_1: usdhc4grp-1 {
-						fsl,pins = <
-							1386 0x17059	/* MX6Q_PAD_SD4_CMD__USDHC4_CMD */
-							1392 0x10059	/* MX6Q_PAD_SD4_CLK__USDHC4_CLK	*/
-							1462 0x17059	/* MX6Q_PAD_SD4_DAT0__USDHC4_DAT0 */
-							1470 0x17059	/* MX6Q_PAD_SD4_DAT1__USDHC4_DAT1 */
-							1478 0x17059	/* MX6Q_PAD_SD4_DAT2__USDHC4_DAT2 */
-							1486 0x17059	/* MX6Q_PAD_SD4_DAT3__USDHC4_DAT3 */
-							1493 0x17059	/* MX6Q_PAD_SD4_DAT4__USDHC4_DAT4 */
-							1501 0x17059	/* MX6Q_PAD_SD4_DAT5__USDHC4_DAT5 */
-							1509 0x17059	/* MX6Q_PAD_SD4_DAT6__USDHC4_DAT6 */
-							1517 0x17059	/* MX6Q_PAD_SD4_DAT7__USDHC4_DAT7 */
-						>;
-					};
-
-					pinctrl_usdhc4_2: usdhc4grp-2 {
-						fsl,pins = <
-							1386 0x17059	/* MX6Q_PAD_SD4_CMD__USDHC4_CMD */
-							1392 0x10059	/* MX6Q_PAD_SD4_CLK__USDHC4_CLK	*/
-							1462 0x17059	/* MX6Q_PAD_SD4_DAT0__USDHC4_DAT0 */
-							1470 0x17059	/* MX6Q_PAD_SD4_DAT1__USDHC4_DAT1 */
-							1478 0x17059	/* MX6Q_PAD_SD4_DAT2__USDHC4_DAT2 */
-							1486 0x17059	/* MX6Q_PAD_SD4_DAT3__USDHC4_DAT3 */
-						>;
-					};
-				};
-			};
-		};
-
-		ipu2: ipu@02800000 {
-			#crtc-cells = <1>;
-			compatible = "fsl,imx6q-ipu";
-			reg = <0x02800000 0x400000>;
-			interrupts = <0 8 0x4 0 7 0x4>;
-			clocks = <&clks 133>, <&clks 134>, <&clks 137>;
-			clock-names = "bus", "di0", "di1";
-		};
-	};
-};
diff --git a/arch/arm/boot/dts/imx6q.dtsip b/arch/arm/boot/dts/imx6q.dtsip
new file mode 100644
index 0000000..cbc1909
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q.dtsip
@@ -0,0 +1,358 @@
+
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include "imx6qdl.dtsip"
+#include "imx6q-pinfunc.h"
+
+/ {
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			compatible = "arm,cortex-a9";
+			reg = <0>;
+			next-level-cache = <&L2>;
+			operating-points = <
+				/* kHz    uV */
+				1200000 1275000
+				996000  1250000
+				792000  1150000
+				396000  950000
+			>;
+			clock-latency = <61036>; /* two CLK32 periods */
+			clocks = <&clks 104>, <&clks 6>, <&clks 16>,
+				 <&clks 17>, <&clks 170>;
+			clock-names = "arm", "pll2_pfd2_396m", "step",
+				      "pll1_sw", "pll1_sys";
+			arm-supply = <&reg_arm>;
+			pu-supply = <&reg_pu>;
+			soc-supply = <&reg_soc>;
+		};
+
+		cpu@1 {
+			compatible = "arm,cortex-a9";
+			reg = <1>;
+			next-level-cache = <&L2>;
+		};
+
+		cpu@2 {
+			compatible = "arm,cortex-a9";
+			reg = <2>;
+			next-level-cache = <&L2>;
+		};
+
+		cpu@3 {
+			compatible = "arm,cortex-a9";
+			reg = <3>;
+			next-level-cache = <&L2>;
+		};
+	};
+
+	soc {
+		aips-bus@02000000 { /* AIPS1 */
+			spba-bus@02000000 {
+				ecspi5: ecspi@02018000 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
+					reg = <0x02018000 0x4000>;
+					interrupts = <0 35 0x04>;
+					clocks = <&clks 116>, <&clks 116>;
+					clock-names = "ipg", "per";
+					status = "disabled";
+				};
+			};
+
+			iomuxc: iomuxc@020e0000 {
+				compatible = "fsl,imx6q-iomuxc";
+				reg = <0x020e0000 0x4000>;
+
+				/* shared pinctrl settings */
+				audmux {
+					pinctrl_audmux_1: audmux-1 {
+						fsl,pins = <
+							MX6Q_PAD_SD2_DAT0__AUDMUX_AUD4_RXD  0x80000000
+							MX6Q_PAD_SD2_DAT3__AUDMUX_AUD4_TXC  0x80000000
+							MX6Q_PAD_SD2_DAT2__AUDMUX_AUD4_TXD  0x80000000
+							MX6Q_PAD_SD2_DAT1__AUDMUX_AUD4_TXFS 0x80000000
+						>;
+					};
+
+					pinctrl_audmux_2: audmux-2 {
+						fsl,pins = <
+							MX6Q_PAD_CSI0_DAT7__AUDMUX_AUD3_RXD  0x80000000
+							MX6Q_PAD_CSI0_DAT4__AUDMUX_AUD3_TXC  0x80000000
+							MX6Q_PAD_CSI0_DAT5__AUDMUX_AUD3_TXD  0x80000000
+							MX6Q_PAD_CSI0_DAT6__AUDMUX_AUD3_TXFS 0x80000000
+						>;
+					};
+				};
+
+				ecspi1 {
+					pinctrl_ecspi1_1: ecspi1grp-1 {
+						fsl,pins = <
+							MX6Q_PAD_EIM_D17__ECSPI1_MISO 0x100b1
+							MX6Q_PAD_EIM_D18__ECSPI1_MOSI 0x100b1
+							MX6Q_PAD_EIM_D16__ECSPI1_SCLK 0x100b1
+						>;
+					};
+				};
+
+				ecspi3 {
+					pinctrl_ecspi3_1: ecspi3grp-1 {
+						fsl,pins = <
+							MX6Q_PAD_DISP0_DAT2__ECSPI3_MISO 0x100b1
+							MX6Q_PAD_DISP0_DAT1__ECSPI3_MOSI 0x100b1
+							MX6Q_PAD_DISP0_DAT0__ECSPI3_SCLK 0x100b1
+						>;
+					};
+				};
+
+				enet {
+					pinctrl_enet_1: enetgrp-1 {
+						fsl,pins = <
+							MX6Q_PAD_ENET_MDIO__ENET_MDIO           0x1b0b0
+							MX6Q_PAD_ENET_MDC__ENET_MDC             0x1b0b0
+							MX6Q_PAD_RGMII_TXC__ENET_RGMII_TXC      0x1b0b0
+							MX6Q_PAD_RGMII_TD0__ENET_RGMII_TD0      0x1b0b0
+							MX6Q_PAD_RGMII_TD1__ENET_RGMII_TD1      0x1b0b0
+							MX6Q_PAD_RGMII_TD2__ENET_RGMII_TD2      0x1b0b0
+							MX6Q_PAD_RGMII_TD3__ENET_RGMII_TD3      0x1b0b0
+							MX6Q_PAD_RGMII_TX_CTL__RGMII_TX_CTL     0x1b0b0
+							MX6Q_PAD_ENET_REF_CLK__ENET_TX_CLK      0x1b0b0
+							MX6Q_PAD_RGMII_RXC__ENET_RGMII_RXC      0x1b0b0
+							MX6Q_PAD_RGMII_RD0__ENET_RGMII_RD0      0x1b0b0
+							MX6Q_PAD_RGMII_RD1__ENET_RGMII_RD1      0x1b0b0
+							MX6Q_PAD_RGMII_RD2__ENET_RGMII_RD2      0x1b0b0
+							MX6Q_PAD_RGMII_RD3__ENET_RGMII_RD3      0x1b0b0
+							MX6Q_PAD_RGMII_RX_CTL__RGMII_RX_CTL     0x1b0b0
+							MX6Q_PAD_GPIO_16__ENET_ETHERNET_REF_OUT 0x4001b0a8
+						>;
+					};
+
+					pinctrl_enet_2: enetgrp-2 {
+						fsl,pins = <
+							MX6Q_PAD_KEY_COL1__ENET_MDIO        0x1b0b0
+							MX6Q_PAD_KEY_COL2__ENET_MDC         0x1b0b0
+							MX6Q_PAD_RGMII_TXC__ENET_RGMII_TXC  0x1b0b0
+							MX6Q_PAD_RGMII_TD0__ENET_RGMII_TD0  0x1b0b0
+							MX6Q_PAD_RGMII_TD1__ENET_RGMII_TD1  0x1b0b0
+							MX6Q_PAD_RGMII_TD2__ENET_RGMII_TD2  0x1b0b0
+							MX6Q_PAD_RGMII_TD3__ENET_RGMII_TD3  0x1b0b0
+							MX6Q_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0
+							MX6Q_PAD_ENET_REF_CLK__ENET_TX_CLK  0x1b0b0
+							MX6Q_PAD_RGMII_RXC__ENET_RGMII_RXC  0x1b0b0
+							MX6Q_PAD_RGMII_RD0__ENET_RGMII_RD0  0x1b0b0
+							MX6Q_PAD_RGMII_RD1__ENET_RGMII_RD1  0x1b0b0
+							MX6Q_PAD_RGMII_RD2__ENET_RGMII_RD2  0x1b0b0
+							MX6Q_PAD_RGMII_RD3__ENET_RGMII_RD3  0x1b0b0
+							MX6Q_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0
+						>;
+					};
+				};
+
+				gpmi-nand {
+					pinctrl_gpmi_nand_1: gpmi-nand-1 {
+						fsl,pins = <
+							MX6Q_PAD_NANDF_CLE__RAWNAND_CLE     0xb0b1
+							MX6Q_PAD_NANDF_ALE__RAWNAND_ALE     0xb0b1
+							MX6Q_PAD_NANDF_WP_B__RAWNAND_RESETN 0xb0b1
+							MX6Q_PAD_NANDF_RB0__RAWNAND_READY0  0xb000
+							MX6Q_PAD_NANDF_CS0__RAWNAND_CE0N    0xb0b1
+							MX6Q_PAD_NANDF_CS1__RAWNAND_CE1N    0xb0b1
+							MX6Q_PAD_NANDF_CS2__RAWNAND_CE2N    0xb0b1
+							MX6Q_PAD_NANDF_CS3__RAWNAND_CE3N    0xb0b1
+							MX6Q_PAD_SD4_CMD__RAWNAND_RDN       0xb0b1
+							MX6Q_PAD_SD4_CLK__RAWNAND_WRN       0xb0b1
+							MX6Q_PAD_NANDF_D0__RAWNAND_D0       0xb0b1
+							MX6Q_PAD_NANDF_D1__RAWNAND_D1       0xb0b1
+							MX6Q_PAD_NANDF_D2__RAWNAND_D2       0xb0b1
+							MX6Q_PAD_NANDF_D3__RAWNAND_D3       0xb0b1
+							MX6Q_PAD_NANDF_D4__RAWNAND_D4       0xb0b1
+							MX6Q_PAD_NANDF_D5__RAWNAND_D5       0xb0b1
+							MX6Q_PAD_NANDF_D6__RAWNAND_D6       0xb0b1
+							MX6Q_PAD_NANDF_D7__RAWNAND_D7       0xb0b1
+							MX6Q_PAD_SD4_DAT0__RAWNAND_DQS      0x00b1
+						>;
+					};
+				};
+
+				i2c1 {
+					pinctrl_i2c1_1: i2c1grp-1 {
+						fsl,pins = <
+							MX6Q_PAD_EIM_D21__I2C1_SCL 0x4001b8b1
+							MX6Q_PAD_EIM_D28__I2C1_SDA 0x4001b8b1
+						>;
+					};
+				};
+
+				i2c2 {
+					pinctrl_i2c2_1: i2c2grp-1 {
+						fsl,pins = <
+							MX6Q_PAD_EIM_EB2__I2C2_SCL 0x4001b8b1
+							MX6Q_PAD_EIM_D16__I2C2_SDA 0x4001b8b1
+						>;
+					};
+				};
+
+				i2c3 {
+					pinctrl_i2c3_1: i2c3grp-1 {
+						fsl,pins = <
+							MX6Q_PAD_EIM_D17__I2C3_SCL 0x4001b8b1
+							MX6Q_PAD_EIM_D18__I2C3_SDA 0x4001b8b1
+						>;
+					};
+				};
+
+				uart1 {
+					pinctrl_uart1_1: uart1grp-1 {
+						fsl,pins = <
+							MX6Q_PAD_CSI0_DAT10__UART1_TXD 0x1b0b1
+							MX6Q_PAD_CSI0_DAT11__UART1_RXD 0x1b0b1
+						>;
+					};
+				};
+
+				uart2 {
+					pinctrl_uart2_1: uart2grp-1 {
+						fsl,pins = <
+							MX6Q_PAD_EIM_D26__UART2_TXD 0x1b0b1
+							MX6Q_PAD_EIM_D27__UART2_RXD 0x1b0b1
+						>;
+					};
+				};
+
+				uart4 {
+					pinctrl_uart4_1: uart4grp-1 {
+						fsl,pins = <
+							MX6Q_PAD_KEY_COL0__UART4_TXD 0x1b0b1
+							MX6Q_PAD_KEY_ROW0__UART4_RXD 0x1b0b1
+						>;
+					};
+				};
+
+				usbotg {
+					pinctrl_usbotg_1: usbotggrp-1 {
+						fsl,pins = <
+							MX6Q_PAD_GPIO_1__ANATOP_USBOTG_ID 0x17059
+						>;
+					};
+
+					pinctrl_usbotg_2: usbotggrp-2 {
+						fsl,pins = <
+							MX6Q_PAD_ENET_RX_ER__ANATOP_USBOTG_ID 0x17059
+						>;
+					};
+				};
+
+				usdhc2 {
+					pinctrl_usdhc2_1: usdhc2grp-1 {
+						fsl,pins = <
+							MX6Q_PAD_SD2_CMD__USDHC2_CMD   0x17059
+							MX6Q_PAD_SD2_CLK__USDHC2_CLK   0x10059
+							MX6Q_PAD_SD2_DAT0__USDHC2_DAT0 0x17059
+							MX6Q_PAD_SD2_DAT1__USDHC2_DAT1 0x17059
+							MX6Q_PAD_SD2_DAT2__USDHC2_DAT2 0x17059
+							MX6Q_PAD_SD2_DAT3__USDHC2_DAT3 0x17059
+							MX6Q_PAD_NANDF_D4__USDHC2_DAT4 0x17059
+							MX6Q_PAD_NANDF_D5__USDHC2_DAT5 0x17059
+							MX6Q_PAD_NANDF_D6__USDHC2_DAT6 0x17059
+							MX6Q_PAD_NANDF_D7__USDHC2_DAT7 0x17059
+						>;
+					};
+				};
+
+				usdhc3 {
+					pinctrl_usdhc3_1: usdhc3grp-1 {
+						fsl,pins = <
+							MX6Q_PAD_SD3_CMD__USDHC3_CMD   0x17059
+							MX6Q_PAD_SD3_CLK__USDHC3_CLK   0x10059
+							MX6Q_PAD_SD3_DAT0__USDHC3_DAT0 0x17059
+							MX6Q_PAD_SD3_DAT1__USDHC3_DAT1 0x17059
+							MX6Q_PAD_SD3_DAT2__USDHC3_DAT2 0x17059
+							MX6Q_PAD_SD3_DAT3__USDHC3_DAT3 0x17059
+							MX6Q_PAD_SD3_DAT4__USDHC3_DAT4 0x17059
+							MX6Q_PAD_SD3_DAT5__USDHC3_DAT5 0x17059
+							MX6Q_PAD_SD3_DAT6__USDHC3_DAT6 0x17059
+							MX6Q_PAD_SD3_DAT7__USDHC3_DAT7 0x17059
+						>;
+					};
+
+					pinctrl_usdhc3_2: usdhc3grp-2 {
+						fsl,pins = <
+							MX6Q_PAD_SD3_CMD__USDHC3_CMD   0x17059
+							MX6Q_PAD_SD3_CLK__USDHC3_CLK   0x10059
+							MX6Q_PAD_SD3_DAT0__USDHC3_DAT0 0x17059
+							MX6Q_PAD_SD3_DAT1__USDHC3_DAT1 0x17059
+							MX6Q_PAD_SD3_DAT2__USDHC3_DAT2 0x17059
+							MX6Q_PAD_SD3_DAT3__USDHC3_DAT3 0x17059
+						>;
+					};
+				};
+
+				usdhc4 {
+					pinctrl_usdhc4_1: usdhc4grp-1 {
+						fsl,pins = <
+							MX6Q_PAD_SD4_CMD__USDHC4_CMD   0x17059
+							MX6Q_PAD_SD4_CLK__USDHC4_CLK   0x10059
+							MX6Q_PAD_SD4_DAT0__USDHC4_DAT0 0x17059
+							MX6Q_PAD_SD4_DAT1__USDHC4_DAT1 0x17059
+							MX6Q_PAD_SD4_DAT2__USDHC4_DAT2 0x17059
+							MX6Q_PAD_SD4_DAT3__USDHC4_DAT3 0x17059
+							MX6Q_PAD_SD4_DAT4__USDHC4_DAT4 0x17059
+							MX6Q_PAD_SD4_DAT5__USDHC4_DAT5 0x17059
+							MX6Q_PAD_SD4_DAT6__USDHC4_DAT6 0x17059
+							MX6Q_PAD_SD4_DAT7__USDHC4_DAT7 0x17059
+						>;
+					};
+
+					pinctrl_usdhc4_2: usdhc4grp-2 {
+						fsl,pins = <
+							MX6Q_PAD_SD4_CMD__USDHC4_CMD   0x17059
+							MX6Q_PAD_SD4_CLK__USDHC4_CLK   0x10059
+							MX6Q_PAD_SD4_DAT0__USDHC4_DAT0 0x17059
+							MX6Q_PAD_SD4_DAT1__USDHC4_DAT1 0x17059
+							MX6Q_PAD_SD4_DAT2__USDHC4_DAT2 0x17059
+							MX6Q_PAD_SD4_DAT3__USDHC4_DAT3 0x17059
+						>;
+					};
+				};
+			};
+		};
+
+		ipu2: ipu@02800000 {
+			#crtc-cells = <1>;
+			compatible = "fsl,imx6q-ipu";
+			reg = <0x02800000 0x400000>;
+			interrupts = <0 8 0x4 0 7 0x4>;
+			clocks = <&clks 133>, <&clks 134>, <&clks 137>;
+			clock-names = "bus", "di0", "di1";
+			resets = <&src 4>;
+		};
+	};
+};
+
+&ldb {
+	clocks = <&clks 33>, <&clks 34>,
+		 <&clks 39>, <&clks 40>, <&clks 41>, <&clks 42>,
+		 <&clks 135>, <&clks 136>;
+	clock-names = "di0_pll", "di1_pll",
+		      "di0_sel", "di1_sel", "di2_sel", "di3_sel",
+		      "di0", "di1";
+
+	lvds-channel@0 {
+		crtcs = <&ipu1 0>, <&ipu1 1>, <&ipu2 0>, <&ipu2 1>;
+	};
+
+	lvds-channel@1 {
+		crtcs = <&ipu1 0>, <&ipu1 1>, <&ipu2 0>, <&ipu2 1>;
+	};
+};
diff --git a/arch/arm/boot/dts/imx6qdl-sabreauto.dtsip b/arch/arm/boot/dts/imx6qdl-sabreauto.dtsip
new file mode 100644
index 0000000..4d237cf
--- /dev/null
+++ b/arch/arm/boot/dts/imx6qdl-sabreauto.dtsip
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * 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
+ */
+
+/ {
+	memory {
+		reg = <0x10000000 0x80000000>;
+	};
+};
+
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet_2>;
+	phy-mode = "rgmii";
+	status = "okay";
+};
+
+&uart4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart4_1>;
+	status = "okay";
+};
+
+&usdhc3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc3_1>;
+	cd-gpios = <&gpio6 15 0>;
+	wp-gpios = <&gpio1 13 0>;
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6qdl-sabresd.dtsip b/arch/arm/boot/dts/imx6qdl-sabresd.dtsip
new file mode 100644
index 0000000..e21f6a8
--- /dev/null
+++ b/arch/arm/boot/dts/imx6qdl-sabresd.dtsip
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * 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
+ */
+
+/ {
+	memory {
+		reg = <0x10000000 0x40000000>;
+	};
+
+	regulators {
+		compatible = "simple-bus";
+
+		reg_usb_otg_vbus: usb_otg_vbus {
+			compatible = "regulator-fixed";
+			regulator-name = "usb_otg_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			gpio = <&gpio3 22 0>;
+			enable-active-high;
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		volume-up {
+			label = "Volume Up";
+			gpios = <&gpio1 4 0>;
+			linux,code = <115>; /* KEY_VOLUMEUP */
+		};
+
+		volume-down {
+			label = "Volume Down";
+			gpios = <&gpio1 5 0>;
+			linux,code = <114>; /* KEY_VOLUMEDOWN */
+		};
+	};
+};
+
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet_1>;
+	phy-mode = "rgmii";
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1_1>;
+	status = "okay";
+};
+
+&usbh1 {
+	status = "okay";
+};
+
+&usbotg {
+	vbus-supply = <&reg_usb_otg_vbus>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbotg_2>;
+	disable-over-current;
+	status = "okay";
+};
+
+&usdhc2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc2_1>;
+	cd-gpios = <&gpio2 2 0>;
+	wp-gpios = <&gpio2 3 0>;
+	status = "okay";
+};
+
+&usdhc3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc3_1>;
+	cd-gpios = <&gpio2 0 0>;
+	wp-gpios = <&gpio2 1 0>;
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
deleted file mode 100644
index 06ec460..0000000
--- a/arch/arm/boot/dts/imx6qdl.dtsi
+++ /dev/null
@@ -1,800 +0,0 @@
-/*
- * Copyright 2011 Freescale Semiconductor, Inc.
- * Copyright 2011 Linaro Ltd.
- *
- * 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/ "skeleton.dtsi"
-
-/ {
-	aliases {
-		serial0 = &uart1;
-		serial1 = &uart2;
-		serial2 = &uart3;
-		serial3 = &uart4;
-		serial4 = &uart5;
-		gpio0 = &gpio1;
-		gpio1 = &gpio2;
-		gpio2 = &gpio3;
-		gpio3 = &gpio4;
-		gpio4 = &gpio5;
-		gpio5 = &gpio6;
-		gpio6 = &gpio7;
-	};
-
-	intc: interrupt-controller@00a01000 {
-		compatible = "arm,cortex-a9-gic";
-		#interrupt-cells = <3>;
-		#address-cells = <1>;
-		#size-cells = <1>;
-		interrupt-controller;
-		reg = <0x00a01000 0x1000>,
-		      <0x00a00100 0x100>;
-	};
-
-	clocks {
-		#address-cells = <1>;
-		#size-cells = <0>;
-
-		ckil {
-			compatible = "fsl,imx-ckil", "fixed-clock";
-			clock-frequency = <32768>;
-		};
-
-		ckih1 {
-			compatible = "fsl,imx-ckih1", "fixed-clock";
-			clock-frequency = <0>;
-		};
-
-		osc {
-			compatible = "fsl,imx-osc", "fixed-clock";
-			clock-frequency = <24000000>;
-		};
-	};
-
-	soc {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		compatible = "simple-bus";
-		interrupt-parent = <&intc>;
-		ranges;
-
-		dma-apbh@00110000 {
-			compatible = "fsl,imx6q-dma-apbh", "fsl,imx28-dma-apbh";
-			reg = <0x00110000 0x2000>;
-			clocks = <&clks 106>;
-		};
-
-		gpmi: gpmi-nand@00112000 {
-			compatible = "fsl,imx6q-gpmi-nand";
-			#address-cells = <1>;
-			#size-cells = <1>;
-			reg = <0x00112000 0x2000>, <0x00114000 0x2000>;
-			reg-names = "gpmi-nand", "bch";
-			interrupts = <0 13 0x04>, <0 15 0x04>;
-			interrupt-names = "gpmi-dma", "bch";
-			clocks = <&clks 152>, <&clks 153>, <&clks 151>,
-				 <&clks 150>, <&clks 149>;
-			clock-names = "gpmi_io", "gpmi_apb", "gpmi_bch",
-				      "gpmi_bch_apb", "per1_bch";
-			fsl,gpmi-dma-channel = <0>;
-			status = "disabled";
-		};
-
-		timer@00a00600 {
-			compatible = "arm,cortex-a9-twd-timer";
-			reg = <0x00a00600 0x20>;
-			interrupts = <1 13 0xf01>;
-		};
-
-		L2: l2-cache@00a02000 {
-			compatible = "arm,pl310-cache";
-			reg = <0x00a02000 0x1000>;
-			interrupts = <0 92 0x04>;
-			cache-unified;
-			cache-level = <2>;
-		};
-
-		aips-bus@02000000 { /* AIPS1 */
-			compatible = "fsl,aips-bus", "simple-bus";
-			#address-cells = <1>;
-			#size-cells = <1>;
-			reg = <0x02000000 0x100000>;
-			ranges;
-
-			spba-bus@02000000 {
-				compatible = "fsl,spba-bus", "simple-bus";
-				#address-cells = <1>;
-				#size-cells = <1>;
-				reg = <0x02000000 0x40000>;
-				ranges;
-
-				spdif: spdif@02004000 {
-					reg = <0x02004000 0x4000>;
-					interrupts = <0 52 0x04>;
-				};
-
-				ecspi1: ecspi@02008000 {
-					#address-cells = <1>;
-					#size-cells = <0>;
-					compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
-					reg = <0x02008000 0x4000>;
-					interrupts = <0 31 0x04>;
-					clocks = <&clks 112>, <&clks 112>;
-					clock-names = "ipg", "per";
-					status = "disabled";
-				};
-
-				ecspi2: ecspi@0200c000 {
-					#address-cells = <1>;
-					#size-cells = <0>;
-					compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
-					reg = <0x0200c000 0x4000>;
-					interrupts = <0 32 0x04>;
-					clocks = <&clks 113>, <&clks 113>;
-					clock-names = "ipg", "per";
-					status = "disabled";
-				};
-
-				ecspi3: ecspi@02010000 {
-					#address-cells = <1>;
-					#size-cells = <0>;
-					compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
-					reg = <0x02010000 0x4000>;
-					interrupts = <0 33 0x04>;
-					clocks = <&clks 114>, <&clks 114>;
-					clock-names = "ipg", "per";
-					status = "disabled";
-				};
-
-				ecspi4: ecspi@02014000 {
-					#address-cells = <1>;
-					#size-cells = <0>;
-					compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
-					reg = <0x02014000 0x4000>;
-					interrupts = <0 34 0x04>;
-					clocks = <&clks 115>, <&clks 115>;
-					clock-names = "ipg", "per";
-					status = "disabled";
-				};
-
-				uart1: serial@02020000 {
-					compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
-					reg = <0x02020000 0x4000>;
-					interrupts = <0 26 0x04>;
-					clocks = <&clks 160>, <&clks 161>;
-					clock-names = "ipg", "per";
-					status = "disabled";
-				};
-
-				esai: esai@02024000 {
-					reg = <0x02024000 0x4000>;
-					interrupts = <0 51 0x04>;
-				};
-
-				ssi1: ssi@02028000 {
-					compatible = "fsl,imx6q-ssi","fsl,imx21-ssi";
-					reg = <0x02028000 0x4000>;
-					interrupts = <0 46 0x04>;
-					clocks = <&clks 178>;
-					fsl,fifo-depth = <15>;
-					fsl,ssi-dma-events = <38 37>;
-					status = "disabled";
-				};
-
-				ssi2: ssi@0202c000 {
-					compatible = "fsl,imx6q-ssi","fsl,imx21-ssi";
-					reg = <0x0202c000 0x4000>;
-					interrupts = <0 47 0x04>;
-					clocks = <&clks 179>;
-					fsl,fifo-depth = <15>;
-					fsl,ssi-dma-events = <42 41>;
-					status = "disabled";
-				};
-
-				ssi3: ssi@02030000 {
-					compatible = "fsl,imx6q-ssi","fsl,imx21-ssi";
-					reg = <0x02030000 0x4000>;
-					interrupts = <0 48 0x04>;
-					clocks = <&clks 180>;
-					fsl,fifo-depth = <15>;
-					fsl,ssi-dma-events = <46 45>;
-					status = "disabled";
-				};
-
-				asrc: asrc@02034000 {
-					reg = <0x02034000 0x4000>;
-					interrupts = <0 50 0x04>;
-				};
-
-				spba@0203c000 {
-					reg = <0x0203c000 0x4000>;
-				};
-			};
-
-			vpu: vpu@02040000 {
-				reg = <0x02040000 0x3c000>;
-				interrupts = <0 3 0x04 0 12 0x04>;
-			};
-
-			aipstz@0207c000 { /* AIPSTZ1 */
-				reg = <0x0207c000 0x4000>;
-			};
-
-			pwm1: pwm@02080000 {
-				#pwm-cells = <2>;
-				compatible = "fsl,imx6q-pwm", "fsl,imx27-pwm";
-				reg = <0x02080000 0x4000>;
-				interrupts = <0 83 0x04>;
-				clocks = <&clks 62>, <&clks 145>;
-				clock-names = "ipg", "per";
-			};
-
-			pwm2: pwm@02084000 {
-				#pwm-cells = <2>;
-				compatible = "fsl,imx6q-pwm", "fsl,imx27-pwm";
-				reg = <0x02084000 0x4000>;
-				interrupts = <0 84 0x04>;
-				clocks = <&clks 62>, <&clks 146>;
-				clock-names = "ipg", "per";
-			};
-
-			pwm3: pwm@02088000 {
-				#pwm-cells = <2>;
-				compatible = "fsl,imx6q-pwm", "fsl,imx27-pwm";
-				reg = <0x02088000 0x4000>;
-				interrupts = <0 85 0x04>;
-				clocks = <&clks 62>, <&clks 147>;
-				clock-names = "ipg", "per";
-			};
-
-			pwm4: pwm@0208c000 {
-				#pwm-cells = <2>;
-				compatible = "fsl,imx6q-pwm", "fsl,imx27-pwm";
-				reg = <0x0208c000 0x4000>;
-				interrupts = <0 86 0x04>;
-				clocks = <&clks 62>, <&clks 148>;
-				clock-names = "ipg", "per";
-			};
-
-			can1: flexcan@02090000 {
-				reg = <0x02090000 0x4000>;
-				interrupts = <0 110 0x04>;
-			};
-
-			can2: flexcan@02094000 {
-				reg = <0x02094000 0x4000>;
-				interrupts = <0 111 0x04>;
-			};
-
-			gpt: gpt@02098000 {
-				compatible = "fsl,imx6q-gpt";
-				reg = <0x02098000 0x4000>;
-				interrupts = <0 55 0x04>;
-			};
-
-			gpio1: gpio@0209c000 {
-				compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio";
-				reg = <0x0209c000 0x4000>;
-				interrupts = <0 66 0x04 0 67 0x04>;
-				gpio-controller;
-				#gpio-cells = <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-			};
-
-			gpio2: gpio@020a0000 {
-				compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio";
-				reg = <0x020a0000 0x4000>;
-				interrupts = <0 68 0x04 0 69 0x04>;
-				gpio-controller;
-				#gpio-cells = <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-			};
-
-			gpio3: gpio@020a4000 {
-				compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio";
-				reg = <0x020a4000 0x4000>;
-				interrupts = <0 70 0x04 0 71 0x04>;
-				gpio-controller;
-				#gpio-cells = <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-			};
-
-			gpio4: gpio@020a8000 {
-				compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio";
-				reg = <0x020a8000 0x4000>;
-				interrupts = <0 72 0x04 0 73 0x04>;
-				gpio-controller;
-				#gpio-cells = <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-			};
-
-			gpio5: gpio@020ac000 {
-				compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio";
-				reg = <0x020ac000 0x4000>;
-				interrupts = <0 74 0x04 0 75 0x04>;
-				gpio-controller;
-				#gpio-cells = <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-			};
-
-			gpio6: gpio@020b0000 {
-				compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio";
-				reg = <0x020b0000 0x4000>;
-				interrupts = <0 76 0x04 0 77 0x04>;
-				gpio-controller;
-				#gpio-cells = <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-			};
-
-			gpio7: gpio@020b4000 {
-				compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio";
-				reg = <0x020b4000 0x4000>;
-				interrupts = <0 78 0x04 0 79 0x04>;
-				gpio-controller;
-				#gpio-cells = <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-			};
-
-			kpp: kpp@020b8000 {
-				reg = <0x020b8000 0x4000>;
-				interrupts = <0 82 0x04>;
-			};
-
-			wdog1: wdog@020bc000 {
-				compatible = "fsl,imx6q-wdt", "fsl,imx21-wdt";
-				reg = <0x020bc000 0x4000>;
-				interrupts = <0 80 0x04>;
-				clocks = <&clks 0>;
-			};
-
-			wdog2: wdog@020c0000 {
-				compatible = "fsl,imx6q-wdt", "fsl,imx21-wdt";
-				reg = <0x020c0000 0x4000>;
-				interrupts = <0 81 0x04>;
-				clocks = <&clks 0>;
-				status = "disabled";
-			};
-
-			clks: ccm@020c4000 {
-				compatible = "fsl,imx6q-ccm";
-				reg = <0x020c4000 0x4000>;
-				interrupts = <0 87 0x04 0 88 0x04>;
-				#clock-cells = <1>;
-			};
-
-			anatop: anatop@020c8000 {
-				compatible = "fsl,imx6q-anatop", "syscon", "simple-bus";
-				reg = <0x020c8000 0x1000>;
-				interrupts = <0 49 0x04 0 54 0x04 0 127 0x04>;
-
-				regulator-1p1@110 {
-					compatible = "fsl,anatop-regulator";
-					regulator-name = "vdd1p1";
-					regulator-min-microvolt = <800000>;
-					regulator-max-microvolt = <1375000>;
-					regulator-always-on;
-					anatop-reg-offset = <0x110>;
-					anatop-vol-bit-shift = <8>;
-					anatop-vol-bit-width = <5>;
-					anatop-min-bit-val = <4>;
-					anatop-min-voltage = <800000>;
-					anatop-max-voltage = <1375000>;
-				};
-
-				regulator-3p0@120 {
-					compatible = "fsl,anatop-regulator";
-					regulator-name = "vdd3p0";
-					regulator-min-microvolt = <2800000>;
-					regulator-max-microvolt = <3150000>;
-					regulator-always-on;
-					anatop-reg-offset = <0x120>;
-					anatop-vol-bit-shift = <8>;
-					anatop-vol-bit-width = <5>;
-					anatop-min-bit-val = <0>;
-					anatop-min-voltage = <2625000>;
-					anatop-max-voltage = <3400000>;
-				};
-
-				regulator-2p5@130 {
-					compatible = "fsl,anatop-regulator";
-					regulator-name = "vdd2p5";
-					regulator-min-microvolt = <2000000>;
-					regulator-max-microvolt = <2750000>;
-					regulator-always-on;
-					anatop-reg-offset = <0x130>;
-					anatop-vol-bit-shift = <8>;
-					anatop-vol-bit-width = <5>;
-					anatop-min-bit-val = <0>;
-					anatop-min-voltage = <2000000>;
-					anatop-max-voltage = <2750000>;
-				};
-
-				reg_arm: regulator-vddcore@140 {
-					compatible = "fsl,anatop-regulator";
-					regulator-name = "cpu";
-					regulator-min-microvolt = <725000>;
-					regulator-max-microvolt = <1450000>;
-					regulator-always-on;
-					anatop-reg-offset = <0x140>;
-					anatop-vol-bit-shift = <0>;
-					anatop-vol-bit-width = <5>;
-					anatop-delay-reg-offset = <0x170>;
-					anatop-delay-bit-shift = <24>;
-					anatop-delay-bit-width = <2>;
-					anatop-min-bit-val = <1>;
-					anatop-min-voltage = <725000>;
-					anatop-max-voltage = <1450000>;
-				};
-
-				reg_pu: regulator-vddpu@140 {
-					compatible = "fsl,anatop-regulator";
-					regulator-name = "vddpu";
-					regulator-min-microvolt = <725000>;
-					regulator-max-microvolt = <1450000>;
-					regulator-always-on;
-					anatop-reg-offset = <0x140>;
-					anatop-vol-bit-shift = <9>;
-					anatop-vol-bit-width = <5>;
-					anatop-delay-reg-offset = <0x170>;
-					anatop-delay-bit-shift = <26>;
-					anatop-delay-bit-width = <2>;
-					anatop-min-bit-val = <1>;
-					anatop-min-voltage = <725000>;
-					anatop-max-voltage = <1450000>;
-				};
-
-				reg_soc: regulator-vddsoc@140 {
-					compatible = "fsl,anatop-regulator";
-					regulator-name = "vddsoc";
-					regulator-min-microvolt = <725000>;
-					regulator-max-microvolt = <1450000>;
-					regulator-always-on;
-					anatop-reg-offset = <0x140>;
-					anatop-vol-bit-shift = <18>;
-					anatop-vol-bit-width = <5>;
-					anatop-delay-reg-offset = <0x170>;
-					anatop-delay-bit-shift = <28>;
-					anatop-delay-bit-width = <2>;
-					anatop-min-bit-val = <1>;
-					anatop-min-voltage = <725000>;
-					anatop-max-voltage = <1450000>;
-				};
-			};
-
-			usbphy1: usbphy@020c9000 {
-				compatible = "fsl,imx6q-usbphy", "fsl,imx23-usbphy";
-				reg = <0x020c9000 0x1000>;
-				interrupts = <0 44 0x04>;
-				clocks = <&clks 182>;
-			};
-
-			usbphy2: usbphy@020ca000 {
-				compatible = "fsl,imx6q-usbphy", "fsl,imx23-usbphy";
-				reg = <0x020ca000 0x1000>;
-				interrupts = <0 45 0x04>;
-				clocks = <&clks 183>;
-			};
-
-			snvs@020cc000 {
-				compatible = "fsl,sec-v4.0-mon", "simple-bus";
-				#address-cells = <1>;
-				#size-cells = <1>;
-				ranges = <0 0x020cc000 0x4000>;
-
-				snvs-rtc-lp@34 {
-					compatible = "fsl,sec-v4.0-mon-rtc-lp";
-					reg = <0x34 0x58>;
-					interrupts = <0 19 0x04 0 20 0x04>;
-				};
-			};
-
-			epit1: epit@020d0000 { /* EPIT1 */
-				reg = <0x020d0000 0x4000>;
-				interrupts = <0 56 0x04>;
-			};
-
-			epit2: epit@020d4000 { /* EPIT2 */
-				reg = <0x020d4000 0x4000>;
-				interrupts = <0 57 0x04>;
-			};
-
-			src: src@020d8000 {
-				compatible = "fsl,imx6q-src";
-				reg = <0x020d8000 0x4000>;
-				interrupts = <0 91 0x04 0 96 0x04>;
-			};
-
-			gpc: gpc@020dc000 {
-				compatible = "fsl,imx6q-gpc";
-				reg = <0x020dc000 0x4000>;
-				interrupts = <0 89 0x04 0 90 0x04>;
-			};
-
-			gpr: iomuxc-gpr@020e0000 {
-				compatible = "fsl,imx6q-iomuxc-gpr", "syscon";
-				reg = <0x020e0000 0x38>;
-			};
-
-			dcic1: dcic@020e4000 {
-				reg = <0x020e4000 0x4000>;
-				interrupts = <0 124 0x04>;
-			};
-
-			dcic2: dcic@020e8000 {
-				reg = <0x020e8000 0x4000>;
-				interrupts = <0 125 0x04>;
-			};
-
-			sdma: sdma@020ec000 {
-				compatible = "fsl,imx6q-sdma", "fsl,imx35-sdma";
-				reg = <0x020ec000 0x4000>;
-				interrupts = <0 2 0x04>;
-				clocks = <&clks 155>, <&clks 155>;
-				clock-names = "ipg", "ahb";
-				fsl,sdma-ram-script-name = "imx/sdma/sdma-imx6q.bin";
-			};
-		};
-
-		aips-bus@02100000 { /* AIPS2 */
-			compatible = "fsl,aips-bus", "simple-bus";
-			#address-cells = <1>;
-			#size-cells = <1>;
-			reg = <0x02100000 0x100000>;
-			ranges;
-
-			caam@02100000 {
-				reg = <0x02100000 0x40000>;
-				interrupts = <0 105 0x04 0 106 0x04>;
-			};
-
-			aipstz@0217c000 { /* AIPSTZ2 */
-				reg = <0x0217c000 0x4000>;
-			};
-
-			usbotg: usb@02184000 {
-				compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
-				reg = <0x02184000 0x200>;
-				interrupts = <0 43 0x04>;
-				clocks = <&clks 162>;
-				fsl,usbphy = <&usbphy1>;
-				fsl,usbmisc = <&usbmisc 0>;
-				status = "disabled";
-			};
-
-			usbh1: usb@02184200 {
-				compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
-				reg = <0x02184200 0x200>;
-				interrupts = <0 40 0x04>;
-				clocks = <&clks 162>;
-				fsl,usbphy = <&usbphy2>;
-				fsl,usbmisc = <&usbmisc 1>;
-				status = "disabled";
-			};
-
-			usbh2: usb@02184400 {
-				compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
-				reg = <0x02184400 0x200>;
-				interrupts = <0 41 0x04>;
-				clocks = <&clks 162>;
-				fsl,usbmisc = <&usbmisc 2>;
-				status = "disabled";
-			};
-
-			usbh3: usb@02184600 {
-				compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
-				reg = <0x02184600 0x200>;
-				interrupts = <0 42 0x04>;
-				clocks = <&clks 162>;
-				fsl,usbmisc = <&usbmisc 3>;
-				status = "disabled";
-			};
-
-			usbmisc: usbmisc: usbmisc@02184800 {
-				#index-cells = <1>;
-				compatible = "fsl,imx6q-usbmisc";
-				reg = <0x02184800 0x200>;
-				clocks = <&clks 162>;
-			};
-
-			fec: ethernet@02188000 {
-				compatible = "fsl,imx6q-fec";
-				reg = <0x02188000 0x4000>;
-				interrupts = <0 118 0x04 0 119 0x04>;
-				clocks = <&clks 117>, <&clks 117>, <&clks 190>;
-				clock-names = "ipg", "ahb", "ptp";
-				status = "disabled";
-			};
-
-			mlb@0218c000 {
-				reg = <0x0218c000 0x4000>;
-				interrupts = <0 53 0x04 0 117 0x04 0 126 0x04>;
-			};
-
-			usdhc1: usdhc@02190000 {
-				compatible = "fsl,imx6q-usdhc";
-				reg = <0x02190000 0x4000>;
-				interrupts = <0 22 0x04>;
-				clocks = <&clks 163>, <&clks 163>, <&clks 163>;
-				clock-names = "ipg", "ahb", "per";
-				bus-width = <4>;
-				status = "disabled";
-			};
-
-			usdhc2: usdhc@02194000 {
-				compatible = "fsl,imx6q-usdhc";
-				reg = <0x02194000 0x4000>;
-				interrupts = <0 23 0x04>;
-				clocks = <&clks 164>, <&clks 164>, <&clks 164>;
-				clock-names = "ipg", "ahb", "per";
-				bus-width = <4>;
-				status = "disabled";
-			};
-
-			usdhc3: usdhc@02198000 {
-				compatible = "fsl,imx6q-usdhc";
-				reg = <0x02198000 0x4000>;
-				interrupts = <0 24 0x04>;
-				clocks = <&clks 165>, <&clks 165>, <&clks 165>;
-				clock-names = "ipg", "ahb", "per";
-				bus-width = <4>;
-				status = "disabled";
-			};
-
-			usdhc4: usdhc@0219c000 {
-				compatible = "fsl,imx6q-usdhc";
-				reg = <0x0219c000 0x4000>;
-				interrupts = <0 25 0x04>;
-				clocks = <&clks 166>, <&clks 166>, <&clks 166>;
-				clock-names = "ipg", "ahb", "per";
-				bus-width = <4>;
-				status = "disabled";
-			};
-
-			i2c1: i2c@021a0000 {
-				#address-cells = <1>;
-				#size-cells = <0>;
-				compatible = "fsl,imx6q-i2c", "fsl,imx21-i2c";
-				reg = <0x021a0000 0x4000>;
-				interrupts = <0 36 0x04>;
-				clocks = <&clks 125>;
-				status = "disabled";
-			};
-
-			i2c2: i2c@021a4000 {
-				#address-cells = <1>;
-				#size-cells = <0>;
-				compatible = "fsl,imx6q-i2c", "fsl,imx21-i2c";
-				reg = <0x021a4000 0x4000>;
-				interrupts = <0 37 0x04>;
-				clocks = <&clks 126>;
-				status = "disabled";
-			};
-
-			i2c3: i2c@021a8000 {
-				#address-cells = <1>;
-				#size-cells = <0>;
-				compatible = "fsl,imx6q-i2c", "fsl,imx21-i2c";
-				reg = <0x021a8000 0x4000>;
-				interrupts = <0 38 0x04>;
-				clocks = <&clks 127>;
-				status = "disabled";
-			};
-
-			romcp@021ac000 {
-				reg = <0x021ac000 0x4000>;
-			};
-
-			mmdc0: mmdc@021b0000 { /* MMDC0 */
-				compatible = "fsl,imx6q-mmdc";
-				reg = <0x021b0000 0x4000>;
-			};
-
-			mmdc1: mmdc@021b4000 { /* MMDC1 */
-				reg = <0x021b4000 0x4000>;
-			};
-
-			weim@021b8000 {
-				reg = <0x021b8000 0x4000>;
-				interrupts = <0 14 0x04>;
-			};
-
-			ocotp@021bc000 {
-				compatible = "fsl,imx6q-ocotp";
-				reg = <0x021bc000 0x4000>;
-			};
-
-			ocotp@021c0000 {
-				reg = <0x021c0000 0x4000>;
-				interrupts = <0 21 0x04>;
-			};
-
-			tzasc@021d0000 { /* TZASC1 */
-				reg = <0x021d0000 0x4000>;
-				interrupts = <0 108 0x04>;
-			};
-
-			tzasc@021d4000 { /* TZASC2 */
-				reg = <0x021d4000 0x4000>;
-				interrupts = <0 109 0x04>;
-			};
-
-			audmux: audmux@021d8000 {
-				compatible = "fsl,imx6q-audmux", "fsl,imx31-audmux";
-				reg = <0x021d8000 0x4000>;
-				status = "disabled";
-			};
-
-			mipi@021dc000 { /* MIPI-CSI */
-				reg = <0x021dc000 0x4000>;
-			};
-
-			mipi@021e0000 { /* MIPI-DSI */
-				reg = <0x021e0000 0x4000>;
-			};
-
-			vdoa@021e4000 {
-				reg = <0x021e4000 0x4000>;
-				interrupts = <0 18 0x04>;
-			};
-
-			uart2: serial@021e8000 {
-				compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
-				reg = <0x021e8000 0x4000>;
-				interrupts = <0 27 0x04>;
-				clocks = <&clks 160>, <&clks 161>;
-				clock-names = "ipg", "per";
-				status = "disabled";
-			};
-
-			uart3: serial@021ec000 {
-				compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
-				reg = <0x021ec000 0x4000>;
-				interrupts = <0 28 0x04>;
-				clocks = <&clks 160>, <&clks 161>;
-				clock-names = "ipg", "per";
-				status = "disabled";
-			};
-
-			uart4: serial@021f0000 {
-				compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
-				reg = <0x021f0000 0x4000>;
-				interrupts = <0 29 0x04>;
-				clocks = <&clks 160>, <&clks 161>;
-				clock-names = "ipg", "per";
-				status = "disabled";
-			};
-
-			uart5: serial@021f4000 {
-				compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
-				reg = <0x021f4000 0x4000>;
-				interrupts = <0 30 0x04>;
-				clocks = <&clks 160>, <&clks 161>;
-				clock-names = "ipg", "per";
-				status = "disabled";
-			};
-		};
-
-		ipu1: ipu@02400000 {
-			#crtc-cells = <1>;
-			compatible = "fsl,imx6q-ipu";
-			reg = <0x02400000 0x400000>;
-			interrupts = <0 6 0x4 0 5 0x4>;
-			clocks = <&clks 130>, <&clks 131>, <&clks 132>;
-			clock-names = "bus", "di0", "di1";
-		};
-	};
-};
diff --git a/arch/arm/boot/dts/imx6qdl.dtsip b/arch/arm/boot/dts/imx6qdl.dtsip
new file mode 100644
index 0000000..e3dd535
--- /dev/null
+++ b/arch/arm/boot/dts/imx6qdl.dtsip
@@ -0,0 +1,835 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * 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 "skeleton.dtsi"
+
+/ {
+	aliases {
+		serial0 = &uart1;
+		serial1 = &uart2;
+		serial2 = &uart3;
+		serial3 = &uart4;
+		serial4 = &uart5;
+		gpio0 = &gpio1;
+		gpio1 = &gpio2;
+		gpio2 = &gpio3;
+		gpio3 = &gpio4;
+		gpio4 = &gpio5;
+		gpio5 = &gpio6;
+		gpio6 = &gpio7;
+	};
+
+	intc: interrupt-controller@00a01000 {
+		compatible = "arm,cortex-a9-gic";
+		#interrupt-cells = <3>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		interrupt-controller;
+		reg = <0x00a01000 0x1000>,
+		      <0x00a00100 0x100>;
+	};
+
+	clocks {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		ckil {
+			compatible = "fsl,imx-ckil", "fixed-clock";
+			clock-frequency = <32768>;
+		};
+
+		ckih1 {
+			compatible = "fsl,imx-ckih1", "fixed-clock";
+			clock-frequency = <0>;
+		};
+
+		osc {
+			compatible = "fsl,imx-osc", "fixed-clock";
+			clock-frequency = <24000000>;
+		};
+	};
+
+	soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		interrupt-parent = <&intc>;
+		ranges;
+
+		dma_apbh: dma-apbh@00110000 {
+			compatible = "fsl,imx6q-dma-apbh", "fsl,imx28-dma-apbh";
+			reg = <0x00110000 0x2000>;
+			interrupts = <0 13 0x04>, <0 13 0x04>, <0 13 0x04>, <0 13 0x04>;
+			interrupt-names = "gpmi0", "gpmi1", "gpmi2", "gpmi3";
+			#dma-cells = <1>;
+			dma-channels = <4>;
+			clocks = <&clks 106>;
+		};
+
+		gpmi: gpmi-nand@00112000 {
+			compatible = "fsl,imx6q-gpmi-nand";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x00112000 0x2000>, <0x00114000 0x2000>;
+			reg-names = "gpmi-nand", "bch";
+			interrupts = <0 13 0x04>, <0 15 0x04>;
+			interrupt-names = "gpmi-dma", "bch";
+			clocks = <&clks 152>, <&clks 153>, <&clks 151>,
+				 <&clks 150>, <&clks 149>;
+			clock-names = "gpmi_io", "gpmi_apb", "gpmi_bch",
+				      "gpmi_bch_apb", "per1_bch";
+			dmas = <&dma_apbh 0>;
+			dma-names = "rx-tx";
+			fsl,gpmi-dma-channel = <0>;
+			status = "disabled";
+		};
+
+		timer@00a00600 {
+			compatible = "arm,cortex-a9-twd-timer";
+			reg = <0x00a00600 0x20>;
+			interrupts = <1 13 0xf01>;
+		};
+
+		L2: l2-cache@00a02000 {
+			compatible = "arm,pl310-cache";
+			reg = <0x00a02000 0x1000>;
+			interrupts = <0 92 0x04>;
+			cache-unified;
+			cache-level = <2>;
+		};
+
+		pmu {
+			compatible = "arm,cortex-a9-pmu";
+			interrupts = <0 94 0x04>;
+		};
+
+		aips-bus@02000000 { /* AIPS1 */
+			compatible = "fsl,aips-bus", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x02000000 0x100000>;
+			ranges;
+
+			spba-bus@02000000 {
+				compatible = "fsl,spba-bus", "simple-bus";
+				#address-cells = <1>;
+				#size-cells = <1>;
+				reg = <0x02000000 0x40000>;
+				ranges;
+
+				spdif: spdif@02004000 {
+					reg = <0x02004000 0x4000>;
+					interrupts = <0 52 0x04>;
+				};
+
+				ecspi1: ecspi@02008000 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
+					reg = <0x02008000 0x4000>;
+					interrupts = <0 31 0x04>;
+					clocks = <&clks 112>, <&clks 112>;
+					clock-names = "ipg", "per";
+					status = "disabled";
+				};
+
+				ecspi2: ecspi@0200c000 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
+					reg = <0x0200c000 0x4000>;
+					interrupts = <0 32 0x04>;
+					clocks = <&clks 113>, <&clks 113>;
+					clock-names = "ipg", "per";
+					status = "disabled";
+				};
+
+				ecspi3: ecspi@02010000 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
+					reg = <0x02010000 0x4000>;
+					interrupts = <0 33 0x04>;
+					clocks = <&clks 114>, <&clks 114>;
+					clock-names = "ipg", "per";
+					status = "disabled";
+				};
+
+				ecspi4: ecspi@02014000 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
+					reg = <0x02014000 0x4000>;
+					interrupts = <0 34 0x04>;
+					clocks = <&clks 115>, <&clks 115>;
+					clock-names = "ipg", "per";
+					status = "disabled";
+				};
+
+				uart1: serial@02020000 {
+					compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
+					reg = <0x02020000 0x4000>;
+					interrupts = <0 26 0x04>;
+					clocks = <&clks 160>, <&clks 161>;
+					clock-names = "ipg", "per";
+					status = "disabled";
+				};
+
+				esai: esai@02024000 {
+					reg = <0x02024000 0x4000>;
+					interrupts = <0 51 0x04>;
+				};
+
+				ssi1: ssi@02028000 {
+					compatible = "fsl,imx6q-ssi","fsl,imx21-ssi";
+					reg = <0x02028000 0x4000>;
+					interrupts = <0 46 0x04>;
+					clocks = <&clks 178>;
+					fsl,fifo-depth = <15>;
+					fsl,ssi-dma-events = <38 37>;
+					status = "disabled";
+				};
+
+				ssi2: ssi@0202c000 {
+					compatible = "fsl,imx6q-ssi","fsl,imx21-ssi";
+					reg = <0x0202c000 0x4000>;
+					interrupts = <0 47 0x04>;
+					clocks = <&clks 179>;
+					fsl,fifo-depth = <15>;
+					fsl,ssi-dma-events = <42 41>;
+					status = "disabled";
+				};
+
+				ssi3: ssi@02030000 {
+					compatible = "fsl,imx6q-ssi","fsl,imx21-ssi";
+					reg = <0x02030000 0x4000>;
+					interrupts = <0 48 0x04>;
+					clocks = <&clks 180>;
+					fsl,fifo-depth = <15>;
+					fsl,ssi-dma-events = <46 45>;
+					status = "disabled";
+				};
+
+				asrc: asrc@02034000 {
+					reg = <0x02034000 0x4000>;
+					interrupts = <0 50 0x04>;
+				};
+
+				spba@0203c000 {
+					reg = <0x0203c000 0x4000>;
+				};
+			};
+
+			vpu: vpu@02040000 {
+				reg = <0x02040000 0x3c000>;
+				interrupts = <0 3 0x04 0 12 0x04>;
+			};
+
+			aipstz@0207c000 { /* AIPSTZ1 */
+				reg = <0x0207c000 0x4000>;
+			};
+
+			pwm1: pwm@02080000 {
+				#pwm-cells = <2>;
+				compatible = "fsl,imx6q-pwm", "fsl,imx27-pwm";
+				reg = <0x02080000 0x4000>;
+				interrupts = <0 83 0x04>;
+				clocks = <&clks 62>, <&clks 145>;
+				clock-names = "ipg", "per";
+			};
+
+			pwm2: pwm@02084000 {
+				#pwm-cells = <2>;
+				compatible = "fsl,imx6q-pwm", "fsl,imx27-pwm";
+				reg = <0x02084000 0x4000>;
+				interrupts = <0 84 0x04>;
+				clocks = <&clks 62>, <&clks 146>;
+				clock-names = "ipg", "per";
+			};
+
+			pwm3: pwm@02088000 {
+				#pwm-cells = <2>;
+				compatible = "fsl,imx6q-pwm", "fsl,imx27-pwm";
+				reg = <0x02088000 0x4000>;
+				interrupts = <0 85 0x04>;
+				clocks = <&clks 62>, <&clks 147>;
+				clock-names = "ipg", "per";
+			};
+
+			pwm4: pwm@0208c000 {
+				#pwm-cells = <2>;
+				compatible = "fsl,imx6q-pwm", "fsl,imx27-pwm";
+				reg = <0x0208c000 0x4000>;
+				interrupts = <0 86 0x04>;
+				clocks = <&clks 62>, <&clks 148>;
+				clock-names = "ipg", "per";
+			};
+
+			can1: flexcan@02090000 {
+				reg = <0x02090000 0x4000>;
+				interrupts = <0 110 0x04>;
+			};
+
+			can2: flexcan@02094000 {
+				reg = <0x02094000 0x4000>;
+				interrupts = <0 111 0x04>;
+			};
+
+			gpt: gpt@02098000 {
+				compatible = "fsl,imx6q-gpt";
+				reg = <0x02098000 0x4000>;
+				interrupts = <0 55 0x04>;
+				clocks = <&clks 119>, <&clks 120>;
+				clock-names = "ipg", "per";
+			};
+
+			gpio1: gpio@0209c000 {
+				compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio";
+				reg = <0x0209c000 0x4000>;
+				interrupts = <0 66 0x04 0 67 0x04>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+			};
+
+			gpio2: gpio@020a0000 {
+				compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio";
+				reg = <0x020a0000 0x4000>;
+				interrupts = <0 68 0x04 0 69 0x04>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+			};
+
+			gpio3: gpio@020a4000 {
+				compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio";
+				reg = <0x020a4000 0x4000>;
+				interrupts = <0 70 0x04 0 71 0x04>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+			};
+
+			gpio4: gpio@020a8000 {
+				compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio";
+				reg = <0x020a8000 0x4000>;
+				interrupts = <0 72 0x04 0 73 0x04>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+			};
+
+			gpio5: gpio@020ac000 {
+				compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio";
+				reg = <0x020ac000 0x4000>;
+				interrupts = <0 74 0x04 0 75 0x04>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+			};
+
+			gpio6: gpio@020b0000 {
+				compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio";
+				reg = <0x020b0000 0x4000>;
+				interrupts = <0 76 0x04 0 77 0x04>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+			};
+
+			gpio7: gpio@020b4000 {
+				compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio";
+				reg = <0x020b4000 0x4000>;
+				interrupts = <0 78 0x04 0 79 0x04>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+			};
+
+			kpp: kpp@020b8000 {
+				reg = <0x020b8000 0x4000>;
+				interrupts = <0 82 0x04>;
+			};
+
+			wdog1: wdog@020bc000 {
+				compatible = "fsl,imx6q-wdt", "fsl,imx21-wdt";
+				reg = <0x020bc000 0x4000>;
+				interrupts = <0 80 0x04>;
+				clocks = <&clks 0>;
+			};
+
+			wdog2: wdog@020c0000 {
+				compatible = "fsl,imx6q-wdt", "fsl,imx21-wdt";
+				reg = <0x020c0000 0x4000>;
+				interrupts = <0 81 0x04>;
+				clocks = <&clks 0>;
+				status = "disabled";
+			};
+
+			clks: ccm@020c4000 {
+				compatible = "fsl,imx6q-ccm";
+				reg = <0x020c4000 0x4000>;
+				interrupts = <0 87 0x04 0 88 0x04>;
+				#clock-cells = <1>;
+			};
+
+			anatop: anatop@020c8000 {
+				compatible = "fsl,imx6q-anatop", "syscon", "simple-bus";
+				reg = <0x020c8000 0x1000>;
+				interrupts = <0 49 0x04 0 54 0x04 0 127 0x04>;
+
+				regulator-1p1@110 {
+					compatible = "fsl,anatop-regulator";
+					regulator-name = "vdd1p1";
+					regulator-min-microvolt = <800000>;
+					regulator-max-microvolt = <1375000>;
+					regulator-always-on;
+					anatop-reg-offset = <0x110>;
+					anatop-vol-bit-shift = <8>;
+					anatop-vol-bit-width = <5>;
+					anatop-min-bit-val = <4>;
+					anatop-min-voltage = <800000>;
+					anatop-max-voltage = <1375000>;
+				};
+
+				regulator-3p0@120 {
+					compatible = "fsl,anatop-regulator";
+					regulator-name = "vdd3p0";
+					regulator-min-microvolt = <2800000>;
+					regulator-max-microvolt = <3150000>;
+					regulator-always-on;
+					anatop-reg-offset = <0x120>;
+					anatop-vol-bit-shift = <8>;
+					anatop-vol-bit-width = <5>;
+					anatop-min-bit-val = <0>;
+					anatop-min-voltage = <2625000>;
+					anatop-max-voltage = <3400000>;
+				};
+
+				regulator-2p5@130 {
+					compatible = "fsl,anatop-regulator";
+					regulator-name = "vdd2p5";
+					regulator-min-microvolt = <2000000>;
+					regulator-max-microvolt = <2750000>;
+					regulator-always-on;
+					anatop-reg-offset = <0x130>;
+					anatop-vol-bit-shift = <8>;
+					anatop-vol-bit-width = <5>;
+					anatop-min-bit-val = <0>;
+					anatop-min-voltage = <2000000>;
+					anatop-max-voltage = <2750000>;
+				};
+
+				reg_arm: regulator-vddcore@140 {
+					compatible = "fsl,anatop-regulator";
+					regulator-name = "cpu";
+					regulator-min-microvolt = <725000>;
+					regulator-max-microvolt = <1450000>;
+					regulator-always-on;
+					anatop-reg-offset = <0x140>;
+					anatop-vol-bit-shift = <0>;
+					anatop-vol-bit-width = <5>;
+					anatop-delay-reg-offset = <0x170>;
+					anatop-delay-bit-shift = <24>;
+					anatop-delay-bit-width = <2>;
+					anatop-min-bit-val = <1>;
+					anatop-min-voltage = <725000>;
+					anatop-max-voltage = <1450000>;
+				};
+
+				reg_pu: regulator-vddpu@140 {
+					compatible = "fsl,anatop-regulator";
+					regulator-name = "vddpu";
+					regulator-min-microvolt = <725000>;
+					regulator-max-microvolt = <1450000>;
+					regulator-always-on;
+					anatop-reg-offset = <0x140>;
+					anatop-vol-bit-shift = <9>;
+					anatop-vol-bit-width = <5>;
+					anatop-delay-reg-offset = <0x170>;
+					anatop-delay-bit-shift = <26>;
+					anatop-delay-bit-width = <2>;
+					anatop-min-bit-val = <1>;
+					anatop-min-voltage = <725000>;
+					anatop-max-voltage = <1450000>;
+				};
+
+				reg_soc: regulator-vddsoc@140 {
+					compatible = "fsl,anatop-regulator";
+					regulator-name = "vddsoc";
+					regulator-min-microvolt = <725000>;
+					regulator-max-microvolt = <1450000>;
+					regulator-always-on;
+					anatop-reg-offset = <0x140>;
+					anatop-vol-bit-shift = <18>;
+					anatop-vol-bit-width = <5>;
+					anatop-delay-reg-offset = <0x170>;
+					anatop-delay-bit-shift = <28>;
+					anatop-delay-bit-width = <2>;
+					anatop-min-bit-val = <1>;
+					anatop-min-voltage = <725000>;
+					anatop-max-voltage = <1450000>;
+				};
+			};
+
+			usbphy1: usbphy@020c9000 {
+				compatible = "fsl,imx6q-usbphy", "fsl,imx23-usbphy";
+				reg = <0x020c9000 0x1000>;
+				interrupts = <0 44 0x04>;
+				clocks = <&clks 182>;
+			};
+
+			usbphy2: usbphy@020ca000 {
+				compatible = "fsl,imx6q-usbphy", "fsl,imx23-usbphy";
+				reg = <0x020ca000 0x1000>;
+				interrupts = <0 45 0x04>;
+				clocks = <&clks 183>;
+			};
+
+			snvs@020cc000 {
+				compatible = "fsl,sec-v4.0-mon", "simple-bus";
+				#address-cells = <1>;
+				#size-cells = <1>;
+				ranges = <0 0x020cc000 0x4000>;
+
+				snvs-rtc-lp@34 {
+					compatible = "fsl,sec-v4.0-mon-rtc-lp";
+					reg = <0x34 0x58>;
+					interrupts = <0 19 0x04 0 20 0x04>;
+				};
+			};
+
+			epit1: epit@020d0000 { /* EPIT1 */
+				reg = <0x020d0000 0x4000>;
+				interrupts = <0 56 0x04>;
+			};
+
+			epit2: epit@020d4000 { /* EPIT2 */
+				reg = <0x020d4000 0x4000>;
+				interrupts = <0 57 0x04>;
+			};
+
+			src: src@020d8000 {
+				compatible = "fsl,imx6q-src", "fsl,imx51-src";
+				reg = <0x020d8000 0x4000>;
+				interrupts = <0 91 0x04 0 96 0x04>;
+				#reset-cells = <1>;
+			};
+
+			gpc: gpc@020dc000 {
+				compatible = "fsl,imx6q-gpc";
+				reg = <0x020dc000 0x4000>;
+				interrupts = <0 89 0x04 0 90 0x04>;
+			};
+
+			gpr: iomuxc-gpr@020e0000 {
+				compatible = "fsl,imx6q-iomuxc-gpr", "syscon";
+				reg = <0x020e0000 0x38>;
+			};
+
+			ldb: ldb@020e0008 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx6q-ldb", "fsl,imx53-ldb";
+				gpr = <&gpr>;
+				status = "disabled";
+
+				lvds-channel@0 {
+					reg = <0>;
+					crtcs = <&ipu1 0>;
+					status = "disabled";
+				};
+
+				lvds-channel@1 {
+					reg = <1>;
+					crtcs = <&ipu1 1>;
+					status = "disabled";
+				};
+			};
+
+			dcic1: dcic@020e4000 {
+				reg = <0x020e4000 0x4000>;
+				interrupts = <0 124 0x04>;
+			};
+
+			dcic2: dcic@020e8000 {
+				reg = <0x020e8000 0x4000>;
+				interrupts = <0 125 0x04>;
+			};
+
+			sdma: sdma@020ec000 {
+				compatible = "fsl,imx6q-sdma", "fsl,imx35-sdma";
+				reg = <0x020ec000 0x4000>;
+				interrupts = <0 2 0x04>;
+				clocks = <&clks 155>, <&clks 155>;
+				clock-names = "ipg", "ahb";
+				fsl,sdma-ram-script-name = "imx/sdma/sdma-imx6q.bin";
+			};
+		};
+
+		aips-bus@02100000 { /* AIPS2 */
+			compatible = "fsl,aips-bus", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x02100000 0x100000>;
+			ranges;
+
+			caam@02100000 {
+				reg = <0x02100000 0x40000>;
+				interrupts = <0 105 0x04 0 106 0x04>;
+			};
+
+			aipstz@0217c000 { /* AIPSTZ2 */
+				reg = <0x0217c000 0x4000>;
+			};
+
+			usbotg: usb@02184000 {
+				compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
+				reg = <0x02184000 0x200>;
+				interrupts = <0 43 0x04>;
+				clocks = <&clks 162>;
+				fsl,usbphy = <&usbphy1>;
+				fsl,usbmisc = <&usbmisc 0>;
+				status = "disabled";
+			};
+
+			usbh1: usb@02184200 {
+				compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
+				reg = <0x02184200 0x200>;
+				interrupts = <0 40 0x04>;
+				clocks = <&clks 162>;
+				fsl,usbphy = <&usbphy2>;
+				fsl,usbmisc = <&usbmisc 1>;
+				status = "disabled";
+			};
+
+			usbh2: usb@02184400 {
+				compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
+				reg = <0x02184400 0x200>;
+				interrupts = <0 41 0x04>;
+				clocks = <&clks 162>;
+				fsl,usbmisc = <&usbmisc 2>;
+				status = "disabled";
+			};
+
+			usbh3: usb@02184600 {
+				compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
+				reg = <0x02184600 0x200>;
+				interrupts = <0 42 0x04>;
+				clocks = <&clks 162>;
+				fsl,usbmisc = <&usbmisc 3>;
+				status = "disabled";
+			};
+
+			usbmisc: usbmisc: usbmisc@02184800 {
+				#index-cells = <1>;
+				compatible = "fsl,imx6q-usbmisc";
+				reg = <0x02184800 0x200>;
+				clocks = <&clks 162>;
+			};
+
+			fec: ethernet@02188000 {
+				compatible = "fsl,imx6q-fec";
+				reg = <0x02188000 0x4000>;
+				interrupts = <0 118 0x04 0 119 0x04>;
+				clocks = <&clks 117>, <&clks 117>, <&clks 190>;
+				clock-names = "ipg", "ahb", "ptp";
+				status = "disabled";
+			};
+
+			mlb@0218c000 {
+				reg = <0x0218c000 0x4000>;
+				interrupts = <0 53 0x04 0 117 0x04 0 126 0x04>;
+			};
+
+			usdhc1: usdhc@02190000 {
+				compatible = "fsl,imx6q-usdhc";
+				reg = <0x02190000 0x4000>;
+				interrupts = <0 22 0x04>;
+				clocks = <&clks 163>, <&clks 163>, <&clks 163>;
+				clock-names = "ipg", "ahb", "per";
+				bus-width = <4>;
+				status = "disabled";
+			};
+
+			usdhc2: usdhc@02194000 {
+				compatible = "fsl,imx6q-usdhc";
+				reg = <0x02194000 0x4000>;
+				interrupts = <0 23 0x04>;
+				clocks = <&clks 164>, <&clks 164>, <&clks 164>;
+				clock-names = "ipg", "ahb", "per";
+				bus-width = <4>;
+				status = "disabled";
+			};
+
+			usdhc3: usdhc@02198000 {
+				compatible = "fsl,imx6q-usdhc";
+				reg = <0x02198000 0x4000>;
+				interrupts = <0 24 0x04>;
+				clocks = <&clks 165>, <&clks 165>, <&clks 165>;
+				clock-names = "ipg", "ahb", "per";
+				bus-width = <4>;
+				status = "disabled";
+			};
+
+			usdhc4: usdhc@0219c000 {
+				compatible = "fsl,imx6q-usdhc";
+				reg = <0x0219c000 0x4000>;
+				interrupts = <0 25 0x04>;
+				clocks = <&clks 166>, <&clks 166>, <&clks 166>;
+				clock-names = "ipg", "ahb", "per";
+				bus-width = <4>;
+				status = "disabled";
+			};
+
+			i2c1: i2c@021a0000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx6q-i2c", "fsl,imx21-i2c";
+				reg = <0x021a0000 0x4000>;
+				interrupts = <0 36 0x04>;
+				clocks = <&clks 125>;
+				status = "disabled";
+			};
+
+			i2c2: i2c@021a4000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx6q-i2c", "fsl,imx21-i2c";
+				reg = <0x021a4000 0x4000>;
+				interrupts = <0 37 0x04>;
+				clocks = <&clks 126>;
+				status = "disabled";
+			};
+
+			i2c3: i2c@021a8000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx6q-i2c", "fsl,imx21-i2c";
+				reg = <0x021a8000 0x4000>;
+				interrupts = <0 38 0x04>;
+				clocks = <&clks 127>;
+				status = "disabled";
+			};
+
+			romcp@021ac000 {
+				reg = <0x021ac000 0x4000>;
+			};
+
+			mmdc0: mmdc@021b0000 { /* MMDC0 */
+				compatible = "fsl,imx6q-mmdc";
+				reg = <0x021b0000 0x4000>;
+			};
+
+			mmdc1: mmdc@021b4000 { /* MMDC1 */
+				reg = <0x021b4000 0x4000>;
+			};
+
+			weim@021b8000 {
+				reg = <0x021b8000 0x4000>;
+				interrupts = <0 14 0x04>;
+			};
+
+			ocotp@021bc000 {
+				compatible = "fsl,imx6q-ocotp";
+				reg = <0x021bc000 0x4000>;
+			};
+
+			ocotp@021c0000 {
+				reg = <0x021c0000 0x4000>;
+				interrupts = <0 21 0x04>;
+			};
+
+			tzasc@021d0000 { /* TZASC1 */
+				reg = <0x021d0000 0x4000>;
+				interrupts = <0 108 0x04>;
+			};
+
+			tzasc@021d4000 { /* TZASC2 */
+				reg = <0x021d4000 0x4000>;
+				interrupts = <0 109 0x04>;
+			};
+
+			audmux: audmux@021d8000 {
+				compatible = "fsl,imx6q-audmux", "fsl,imx31-audmux";
+				reg = <0x021d8000 0x4000>;
+				status = "disabled";
+			};
+
+			mipi@021dc000 { /* MIPI-CSI */
+				reg = <0x021dc000 0x4000>;
+			};
+
+			mipi@021e0000 { /* MIPI-DSI */
+				reg = <0x021e0000 0x4000>;
+			};
+
+			vdoa@021e4000 {
+				reg = <0x021e4000 0x4000>;
+				interrupts = <0 18 0x04>;
+			};
+
+			uart2: serial@021e8000 {
+				compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
+				reg = <0x021e8000 0x4000>;
+				interrupts = <0 27 0x04>;
+				clocks = <&clks 160>, <&clks 161>;
+				clock-names = "ipg", "per";
+				status = "disabled";
+			};
+
+			uart3: serial@021ec000 {
+				compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
+				reg = <0x021ec000 0x4000>;
+				interrupts = <0 28 0x04>;
+				clocks = <&clks 160>, <&clks 161>;
+				clock-names = "ipg", "per";
+				status = "disabled";
+			};
+
+			uart4: serial@021f0000 {
+				compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
+				reg = <0x021f0000 0x4000>;
+				interrupts = <0 29 0x04>;
+				clocks = <&clks 160>, <&clks 161>;
+				clock-names = "ipg", "per";
+				status = "disabled";
+			};
+
+			uart5: serial@021f4000 {
+				compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
+				reg = <0x021f4000 0x4000>;
+				interrupts = <0 30 0x04>;
+				clocks = <&clks 160>, <&clks 161>;
+				clock-names = "ipg", "per";
+				status = "disabled";
+			};
+		};
+
+		ipu1: ipu@02400000 {
+			#crtc-cells = <1>;
+			compatible = "fsl,imx6q-ipu";
+			reg = <0x02400000 0x400000>;
+			interrupts = <0 6 0x4 0 5 0x4>;
+			clocks = <&clks 130>, <&clks 131>, <&clks 132>;
+			clock-names = "bus", "di0", "di1";
+			resets = <&src 2>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/imx6sl-pinfunc.h b/arch/arm/boot/dts/imx6sl-pinfunc.h
new file mode 100644
index 0000000..77b17bc
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sl-pinfunc.h
@@ -0,0 +1,1077 @@
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef __DTS_IMX6SL_PINFUNC_H
+#define __DTS_IMX6SL_PINFUNC_H
+
+/*
+ * The pin function ID is a tuple of
+ * <mux_reg conf_reg input_reg mux_mode input_val>
+ */
+#define MX6SL_PAD_AUD_MCLK__AUDIO_CLK_OUT          0x04c 0x2a4 0x000 0x0 0x0
+#define MX6SL_PAD_AUD_MCLK__PWM4_OUT               0x04c 0x2a4 0x000 0x1 0x0
+#define MX6SL_PAD_AUD_MCLK__ECSPI3_RDY             0x04c 0x2a4 0x6b4 0x2 0x0
+#define MX6SL_PAD_AUD_MCLK__FEC_MDC                0x04c 0x2a4 0x000 0x3 0x0
+#define MX6SL_PAD_AUD_MCLK__WDOG2_RESET_B_DEB      0x04c 0x2a4 0x000 0x4 0x0
+#define MX6SL_PAD_AUD_MCLK__GPIO1_IO06             0x04c 0x2a4 0x000 0x5 0x0
+#define MX6SL_PAD_AUD_MCLK__SPDIF_EXT_CLK          0x04c 0x2a4 0x7f4 0x6 0x0
+#define MX6SL_PAD_AUD_RXC__AUD3_RXC                0x050 0x2a8 0x000 0x0 0x0
+#define MX6SL_PAD_AUD_RXC__I2C1_SDA                0x050 0x2a8 0x720 0x1 0x0
+#define MX6SL_PAD_AUD_RXC__UART3_TX_DATA           0x050 0x2a8 0x000 0x2 0x0
+#define MX6SL_PAD_AUD_RXC__UART3_RX_DATA           0x050 0x2a8 0x80c 0x2 0x0
+#define MX6SL_PAD_AUD_RXC__FEC_TX_CLK              0x050 0x2a8 0x70c 0x3 0x0
+#define MX6SL_PAD_AUD_RXC__I2C3_SDA                0x050 0x2a8 0x730 0x4 0x0
+#define MX6SL_PAD_AUD_RXC__GPIO1_IO01              0x050 0x2a8 0x000 0x5 0x0
+#define MX6SL_PAD_AUD_RXC__ECSPI3_SS1              0x050 0x2a8 0x6c4 0x6 0x0
+#define MX6SL_PAD_AUD_RXD__AUD3_RXD                0x054 0x2ac 0x000 0x0 0x0
+#define MX6SL_PAD_AUD_RXD__ECSPI3_MOSI             0x054 0x2ac 0x6bc 0x1 0x0
+#define MX6SL_PAD_AUD_RXD__UART4_RX_DATA           0x054 0x2ac 0x814 0x2 0x0
+#define MX6SL_PAD_AUD_RXD__UART4_TX_DATA           0x054 0x2ac 0x000 0x2 0x0
+#define MX6SL_PAD_AUD_RXD__FEC_RX_ER               0x054 0x2ac 0x708 0x3 0x0
+#define MX6SL_PAD_AUD_RXD__SD1_LCTL                0x054 0x2ac 0x000 0x4 0x0
+#define MX6SL_PAD_AUD_RXD__GPIO1_IO02              0x054 0x2ac 0x000 0x5 0x0
+#define MX6SL_PAD_AUD_RXFS__AUD3_RXFS              0x058 0x2b0 0x000 0x0 0x0
+#define MX6SL_PAD_AUD_RXFS__I2C1_SCL               0x058 0x2b0 0x71c 0x1 0x0
+#define MX6SL_PAD_AUD_RXFS__UART3_RX_DATA          0x058 0x2b0 0x80c 0x2 0x1
+#define MX6SL_PAD_AUD_RXFS__UART3_TX_DATA          0x058 0x2b0 0x000 0x2 0x0
+#define MX6SL_PAD_AUD_RXFS__FEC_MDIO               0x058 0x2b0 0x6f4 0x3 0x0
+#define MX6SL_PAD_AUD_RXFS__I2C3_SCL               0x058 0x2b0 0x72c 0x4 0x0
+#define MX6SL_PAD_AUD_RXFS__GPIO1_IO00             0x058 0x2b0 0x000 0x5 0x0
+#define MX6SL_PAD_AUD_RXFS__ECSPI3_SS0             0x058 0x2b0 0x6c0 0x6 0x0
+#define MX6SL_PAD_AUD_TXC__AUD3_TXC                0x05c 0x2b4 0x000 0x0 0x0
+#define MX6SL_PAD_AUD_TXC__ECSPI3_MISO             0x05c 0x2b4 0x6b8 0x1 0x0
+#define MX6SL_PAD_AUD_TXC__UART4_TX_DATA           0x05c 0x2b4 0x000 0x2 0x0
+#define MX6SL_PAD_AUD_TXC__UART4_RX_DATA           0x05c 0x2b4 0x814 0x2 0x1
+#define MX6SL_PAD_AUD_TXC__FEC_RX_DV               0x05c 0x2b4 0x704 0x3 0x0
+#define MX6SL_PAD_AUD_TXC__SD2_LCTL                0x05c 0x2b4 0x000 0x4 0x0
+#define MX6SL_PAD_AUD_TXC__GPIO1_IO03              0x05c 0x2b4 0x000 0x5 0x0
+#define MX6SL_PAD_AUD_TXD__AUD3_TXD                0x060 0x2b8 0x000 0x0 0x0
+#define MX6SL_PAD_AUD_TXD__ECSPI3_SCLK             0x060 0x2b8 0x6b0 0x1 0x0
+#define MX6SL_PAD_AUD_TXD__UART4_CTS_B             0x060 0x2b8 0x000 0x2 0x0
+#define MX6SL_PAD_AUD_TXD__UART4_RTS_B             0x060 0x2b8 0x810 0x2 0x0
+#define MX6SL_PAD_AUD_TXD__FEC_TX_DATA0            0x060 0x2b8 0x000 0x3 0x0
+#define MX6SL_PAD_AUD_TXD__SD4_LCTL                0x060 0x2b8 0x000 0x4 0x0
+#define MX6SL_PAD_AUD_TXD__GPIO1_IO05              0x060 0x2b8 0x000 0x5 0x0
+#define MX6SL_PAD_AUD_TXFS__AUD3_TXFS              0x064 0x2bc 0x000 0x0 0x0
+#define MX6SL_PAD_AUD_TXFS__PWM3_OUT               0x064 0x2bc 0x000 0x1 0x0
+#define MX6SL_PAD_AUD_TXFS__UART4_RTS_B            0x064 0x2bc 0x810 0x2 0x1
+#define MX6SL_PAD_AUD_TXFS__UART4_CTS_B            0x064 0x2bc 0x000 0x2 0x0
+#define MX6SL_PAD_AUD_TXFS__FEC_RX_DATA1           0x064 0x2bc 0x6fc 0x3 0x0
+#define MX6SL_PAD_AUD_TXFS__SD3_LCTL               0x064 0x2bc 0x000 0x4 0x0
+#define MX6SL_PAD_AUD_TXFS__GPIO1_IO04             0x064 0x2bc 0x000 0x5 0x0
+#define MX6SL_PAD_ECSPI1_MISO__ECSPI1_MISO         0x068 0x358 0x684 0x0 0x0
+#define MX6SL_PAD_ECSPI1_MISO__AUD4_TXFS           0x068 0x358 0x5f8 0x1 0x0
+#define MX6SL_PAD_ECSPI1_MISO__UART5_RTS_B         0x068 0x358 0x818 0x2 0x0
+#define MX6SL_PAD_ECSPI1_MISO__UART5_CTS_B         0x068 0x358 0x000 0x2 0x0
+#define MX6SL_PAD_ECSPI1_MISO__EPDC_BDR0           0x068 0x358 0x000 0x3 0x0
+#define MX6SL_PAD_ECSPI1_MISO__SD2_WP              0x068 0x358 0x834 0x4 0x0
+#define MX6SL_PAD_ECSPI1_MISO__GPIO4_IO10          0x068 0x358 0x000 0x5 0x0
+#define MX6SL_PAD_ECSPI1_MOSI__ECSPI1_MOSI         0x06c 0x35c 0x688 0x0 0x0
+#define MX6SL_PAD_ECSPI1_MOSI__AUD4_TXC            0x06c 0x35c 0x5f4 0x1 0x0
+#define MX6SL_PAD_ECSPI1_MOSI__UART5_TX_DATA       0x06c 0x35c 0x000 0x2 0x0
+#define MX6SL_PAD_ECSPI1_MOSI__UART5_RX_DATA       0x06c 0x35c 0x81c 0x2 0x0
+#define MX6SL_PAD_ECSPI1_MOSI__EPDC_VCOM1          0x06c 0x35c 0x000 0x3 0x0
+#define MX6SL_PAD_ECSPI1_MOSI__SD2_VSELECT         0x06c 0x35c 0x000 0x4 0x0
+#define MX6SL_PAD_ECSPI1_MOSI__GPIO4_IO09          0x06c 0x35c 0x000 0x5 0x0
+#define MX6SL_PAD_ECSPI1_SCLK__ECSPI1_SCLK         0x070 0x360 0x67c 0x0 0x0
+#define MX6SL_PAD_ECSPI1_SCLK__AUD4_TXD            0x070 0x360 0x5e8 0x1 0x0
+#define MX6SL_PAD_ECSPI1_SCLK__UART5_RX_DATA       0x070 0x360 0x81c 0x2 0x1
+#define MX6SL_PAD_ECSPI1_SCLK__UART5_TX_DATA       0x070 0x360 0x000 0x2 0x0
+#define MX6SL_PAD_ECSPI1_SCLK__EPDC_VCOM0          0x070 0x360 0x000 0x3 0x0
+#define MX6SL_PAD_ECSPI1_SCLK__SD2_RESET           0x070 0x360 0x000 0x4 0x0
+#define MX6SL_PAD_ECSPI1_SCLK__GPIO4_IO08          0x070 0x360 0x000 0x5 0x0
+#define MX6SL_PAD_ECSPI1_SCLK__USB_OTG2_OC         0x070 0x360 0x820 0x6 0x0
+#define MX6SL_PAD_ECSPI1_SS0__ECSPI1_SS0           0x074 0x364 0x68c 0x0 0x0
+#define MX6SL_PAD_ECSPI1_SS0__AUD4_RXD             0x074 0x364 0x5e4 0x1 0x0
+#define MX6SL_PAD_ECSPI1_SS0__UART5_CTS_B          0x074 0x364 0x000 0x2 0x0
+#define MX6SL_PAD_ECSPI1_SS0__UART5_RTS_B          0x074 0x364 0x818 0x2 0x1
+#define MX6SL_PAD_ECSPI1_SS0__EPDC_BDR1            0x074 0x364 0x000 0x3 0x0
+#define MX6SL_PAD_ECSPI1_SS0__SD2_CD_B             0x074 0x364 0x830 0x4 0x0
+#define MX6SL_PAD_ECSPI1_SS0__GPIO4_IO11           0x074 0x364 0x000 0x5 0x0
+#define MX6SL_PAD_ECSPI1_SS0__USB_OTG2_PWR         0x074 0x364 0x000 0x6 0x0
+#define MX6SL_PAD_ECSPI2_MISO__ECSPI2_MISO         0x078 0x368 0x6a0 0x0 0x0
+#define MX6SL_PAD_ECSPI2_MISO__SDMA_EXT_EVENT0     0x078 0x368 0x000 0x1 0x0
+#define MX6SL_PAD_ECSPI2_MISO__UART3_RTS_B         0x078 0x368 0x808 0x2 0x0
+#define MX6SL_PAD_ECSPI2_MISO__UART3_CTS_B         0x078 0x368 0x000 0x2 0x0
+#define MX6SL_PAD_ECSPI2_MISO__CSI_MCLK            0x078 0x368 0x000 0x3 0x0
+#define MX6SL_PAD_ECSPI2_MISO__SD1_WP              0x078 0x368 0x82c 0x4 0x0
+#define MX6SL_PAD_ECSPI2_MISO__GPIO4_IO14          0x078 0x368 0x000 0x5 0x0
+#define MX6SL_PAD_ECSPI2_MISO__USB_OTG1_OC         0x078 0x368 0x824 0x6 0x0
+#define MX6SL_PAD_ECSPI2_MOSI__ECSPI2_MOSI         0x07c 0x36c 0x6a4 0x0 0x0
+#define MX6SL_PAD_ECSPI2_MOSI__SDMA_EXT_EVENT1     0x07c 0x36c 0x000 0x1 0x0
+#define MX6SL_PAD_ECSPI2_MOSI__UART3_TX_DATA       0x07c 0x36c 0x000 0x2 0x0
+#define MX6SL_PAD_ECSPI2_MOSI__UART3_RX_DATA       0x07c 0x36c 0x80c 0x2 0x2
+#define MX6SL_PAD_ECSPI2_MOSI__CSI_HSYNC           0x07c 0x36c 0x670 0x3 0x0
+#define MX6SL_PAD_ECSPI2_MOSI__SD1_VSELECT         0x07c 0x36c 0x000 0x4 0x0
+#define MX6SL_PAD_ECSPI2_MOSI__GPIO4_IO13          0x07c 0x36c 0x000 0x5 0x0
+#define MX6SL_PAD_ECSPI2_SCLK__ECSPI2_SCLK         0x080 0x370 0x69c 0x0 0x0
+#define MX6SL_PAD_ECSPI2_SCLK__SPDIF_EXT_CLK       0x080 0x370 0x7f4 0x1 0x1
+#define MX6SL_PAD_ECSPI2_SCLK__UART3_RX_DATA       0x080 0x370 0x80c 0x2 0x3
+#define MX6SL_PAD_ECSPI2_SCLK__UART3_TX_DATA       0x080 0x370 0x000 0x2 0x0
+#define MX6SL_PAD_ECSPI2_SCLK__CSI_PIXCLK          0x080 0x370 0x674 0x3 0x0
+#define MX6SL_PAD_ECSPI2_SCLK__SD1_RESET           0x080 0x370 0x000 0x4 0x0
+#define MX6SL_PAD_ECSPI2_SCLK__GPIO4_IO12          0x080 0x370 0x000 0x5 0x0
+#define MX6SL_PAD_ECSPI2_SCLK__USB_OTG2_OC         0x080 0x370 0x820 0x6 0x1
+#define MX6SL_PAD_ECSPI2_SS0__ECSPI2_SS0           0x084 0x374 0x6a8 0x0 0x0
+#define MX6SL_PAD_ECSPI2_SS0__ECSPI1_SS3           0x084 0x374 0x698 0x1 0x0
+#define MX6SL_PAD_ECSPI2_SS0__UART3_CTS_B          0x084 0x374 0x000 0x2 0x0
+#define MX6SL_PAD_ECSPI2_SS0__UART3_RTS_B          0x084 0x374 0x808 0x2 0x1
+#define MX6SL_PAD_ECSPI2_SS0__CSI_VSYNC            0x084 0x374 0x678 0x3 0x0
+#define MX6SL_PAD_ECSPI2_SS0__SD1_CD_B             0x084 0x374 0x828 0x4 0x0
+#define MX6SL_PAD_ECSPI2_SS0__GPIO4_IO15           0x084 0x374 0x000 0x5 0x0
+#define MX6SL_PAD_ECSPI2_SS0__USB_OTG1_PWR         0x084 0x374 0x000 0x6 0x0
+#define MX6SL_PAD_EPDC_BDR0__EPDC_BDR0             0x088 0x378 0x000 0x0 0x0
+#define MX6SL_PAD_EPDC_BDR0__SD4_CLK               0x088 0x378 0x850 0x1 0x0
+#define MX6SL_PAD_EPDC_BDR0__UART3_RTS_B           0x088 0x378 0x808 0x2 0x2
+#define MX6SL_PAD_EPDC_BDR0__UART3_CTS_B           0x088 0x378 0x000 0x2 0x0
+#define MX6SL_PAD_EPDC_BDR0__EIM_ADDR26            0x088 0x378 0x000 0x3 0x0
+#define MX6SL_PAD_EPDC_BDR0__SPDC_RL               0x088 0x378 0x000 0x4 0x0
+#define MX6SL_PAD_EPDC_BDR0__GPIO2_IO05            0x088 0x378 0x000 0x5 0x0
+#define MX6SL_PAD_EPDC_BDR0__EPDC_SDCE7            0x088 0x378 0x000 0x6 0x0
+#define MX6SL_PAD_EPDC_BDR1__EPDC_BDR1             0x08c 0x37c 0x000 0x0 0x0
+#define MX6SL_PAD_EPDC_BDR1__SD4_CMD               0x08c 0x37c 0x858 0x1 0x0
+#define MX6SL_PAD_EPDC_BDR1__UART3_CTS_B           0x08c 0x37c 0x000 0x2 0x0
+#define MX6SL_PAD_EPDC_BDR1__UART3_RTS_B           0x08c 0x37c 0x808 0x2 0x3
+#define MX6SL_PAD_EPDC_BDR1__EIM_CRE               0x08c 0x37c 0x000 0x3 0x0
+#define MX6SL_PAD_EPDC_BDR1__SPDC_UD               0x08c 0x37c 0x000 0x4 0x0
+#define MX6SL_PAD_EPDC_BDR1__GPIO2_IO06            0x08c 0x37c 0x000 0x5 0x0
+#define MX6SL_PAD_EPDC_BDR1__EPDC_SDCE8            0x08c 0x37c 0x000 0x6 0x0
+#define MX6SL_PAD_EPDC_D0__EPDC_DATA00             0x090 0x380 0x000 0x0 0x0
+#define MX6SL_PAD_EPDC_D0__ECSPI4_MOSI             0x090 0x380 0x6d8 0x1 0x0
+#define MX6SL_PAD_EPDC_D0__LCD_DATA24              0x090 0x380 0x000 0x2 0x0
+#define MX6SL_PAD_EPDC_D0__CSI_DATA00              0x090 0x380 0x630 0x3 0x0
+#define MX6SL_PAD_EPDC_D0__SPDC_DATA00             0x090 0x380 0x000 0x4 0x0
+#define MX6SL_PAD_EPDC_D0__GPIO1_IO07              0x090 0x380 0x000 0x5 0x0
+#define MX6SL_PAD_EPDC_D1__EPDC_DATA01             0x094 0x384 0x000 0x0 0x0
+#define MX6SL_PAD_EPDC_D1__ECSPI4_MISO             0x094 0x384 0x6d4 0x1 0x0
+#define MX6SL_PAD_EPDC_D1__LCD_DATA25              0x094 0x384 0x000 0x2 0x0
+#define MX6SL_PAD_EPDC_D1__CSI_DATA01              0x094 0x384 0x634 0x3 0x0
+#define MX6SL_PAD_EPDC_D1__SPDC_DATA01             0x094 0x384 0x000 0x4 0x0
+#define MX6SL_PAD_EPDC_D1__GPIO1_IO08              0x094 0x384 0x000 0x5 0x0
+#define MX6SL_PAD_EPDC_D10__EPDC_DATA10            0x098 0x388 0x000 0x0 0x0
+#define MX6SL_PAD_EPDC_D10__ECSPI3_SS0             0x098 0x388 0x6c0 0x1 0x1
+#define MX6SL_PAD_EPDC_D10__EPDC_PWR_CTRL2         0x098 0x388 0x000 0x2 0x0
+#define MX6SL_PAD_EPDC_D10__EIM_ADDR18             0x098 0x388 0x000 0x3 0x0
+#define MX6SL_PAD_EPDC_D10__SPDC_DATA10            0x098 0x388 0x000 0x4 0x0
+#define MX6SL_PAD_EPDC_D10__GPIO1_IO17             0x098 0x388 0x000 0x5 0x0
+#define MX6SL_PAD_EPDC_D10__SD4_WP                 0x098 0x388 0x87c 0x6 0x0
+#define MX6SL_PAD_EPDC_D11__EPDC_DATA11            0x09c 0x38c 0x000 0x0 0x0
+#define MX6SL_PAD_EPDC_D11__ECSPI3_SCLK            0x09c 0x38c 0x6b0 0x1 0x1
+#define MX6SL_PAD_EPDC_D11__EPDC_PWR_CTRL3         0x09c 0x38c 0x000 0x2 0x0
+#define MX6SL_PAD_EPDC_D11__EIM_ADDR19             0x09c 0x38c 0x000 0x3 0x0
+#define MX6SL_PAD_EPDC_D11__SPDC_DATA11            0x09c 0x38c 0x000 0x4 0x0
+#define MX6SL_PAD_EPDC_D11__GPIO1_IO18             0x09c 0x38c 0x000 0x5 0x0
+#define MX6SL_PAD_EPDC_D11__SD4_CD_B               0x09c 0x38c 0x854 0x6 0x0
+#define MX6SL_PAD_EPDC_D12__EPDC_DATA12            0x0a0 0x390 0x000 0x0 0x0
+#define MX6SL_PAD_EPDC_D12__UART2_RX_DATA          0x0a0 0x390 0x804 0x1 0x0
+#define MX6SL_PAD_EPDC_D12__UART2_TX_DATA          0x0a0 0x390 0x000 0x1 0x0
+#define MX6SL_PAD_EPDC_D12__EPDC_PWR_COM           0x0a0 0x390 0x000 0x2 0x0
+#define MX6SL_PAD_EPDC_D12__EIM_ADDR20             0x0a0 0x390 0x000 0x3 0x0
+#define MX6SL_PAD_EPDC_D12__SPDC_DATA12            0x0a0 0x390 0x000 0x4 0x0
+#define MX6SL_PAD_EPDC_D12__GPIO1_IO19             0x0a0 0x390 0x000 0x5 0x0
+#define MX6SL_PAD_EPDC_D12__ECSPI3_SS1             0x0a0 0x390 0x6c4 0x6 0x1
+#define MX6SL_PAD_EPDC_D13__EPDC_DATA13            0x0a4 0x394 0x000 0x0 0x0
+#define MX6SL_PAD_EPDC_D13__UART2_TX_DATA          0x0a4 0x394 0x000 0x1 0x0
+#define MX6SL_PAD_EPDC_D13__UART2_RX_DATA          0x0a4 0x394 0x804 0x1 0x1
+#define MX6SL_PAD_EPDC_D13__EPDC_PWR_IRQ           0x0a4 0x394 0x6e8 0x2 0x0
+#define MX6SL_PAD_EPDC_D13__EIM_ADDR21             0x0a4 0x394 0x000 0x3 0x0
+#define MX6SL_PAD_EPDC_D13__SPDC_DATA13            0x0a4 0x394 0x000 0x4 0x0
+#define MX6SL_PAD_EPDC_D13__GPIO1_IO20             0x0a4 0x394 0x000 0x5 0x0
+#define MX6SL_PAD_EPDC_D13__ECSPI3_SS2             0x0a4 0x394 0x6c8 0x6 0x0
+#define MX6SL_PAD_EPDC_D14__EPDC_DATA14            0x0a8 0x398 0x000 0x0 0x0
+#define MX6SL_PAD_EPDC_D14__UART2_RTS_B            0x0a8 0x398 0x800 0x1 0x0
+#define MX6SL_PAD_EPDC_D14__UART2_CTS_B            0x0a8 0x398 0x000 0x1 0x0
+#define MX6SL_PAD_EPDC_D14__EPDC_PWR_STAT          0x0a8 0x398 0x6ec 0x2 0x0
+#define MX6SL_PAD_EPDC_D14__EIM_ADDR22             0x0a8 0x398 0x000 0x3 0x0
+#define MX6SL_PAD_EPDC_D14__SPDC_DATA14            0x0a8 0x398 0x000 0x4 0x0
+#define MX6SL_PAD_EPDC_D14__GPIO1_IO21             0x0a8 0x398 0x000 0x5 0x0
+#define MX6SL_PAD_EPDC_D14__ECSPI3_SS3             0x0a8 0x398 0x6cc 0x6 0x0
+#define MX6SL_PAD_EPDC_D15__EPDC_DATA15            0x0ac 0x39c 0x000 0x0 0x0
+#define MX6SL_PAD_EPDC_D15__UART2_CTS_B            0x0ac 0x39c 0x000 0x1 0x0
+#define MX6SL_PAD_EPDC_D15__UART2_RTS_B            0x0ac 0x39c 0x800 0x1 0x1
+#define MX6SL_PAD_EPDC_D15__EPDC_PWR_WAKE          0x0ac 0x39c 0x000 0x2 0x0
+#define MX6SL_PAD_EPDC_D15__EIM_ADDR23             0x0ac 0x39c 0x000 0x3 0x0
+#define MX6SL_PAD_EPDC_D15__SPDC_DATA15            0x0ac 0x39c 0x000 0x4 0x0
+#define MX6SL_PAD_EPDC_D15__GPIO1_IO22             0x0ac 0x39c 0x000 0x5 0x0
+#define MX6SL_PAD_EPDC_D15__ECSPI3_RDY             0x0ac 0x39c 0x6b4 0x6 0x1
+#define MX6SL_PAD_EPDC_D2__EPDC_DATA02             0x0b0 0x3a0 0x000 0x0 0x0
+#define MX6SL_PAD_EPDC_D2__ECSPI4_SS0              0x0b0 0x3a0 0x6dc 0x1 0x0
+#define MX6SL_PAD_EPDC_D2__LCD_DATA26              0x0b0 0x3a0 0x000 0x2 0x0
+#define MX6SL_PAD_EPDC_D2__CSI_DATA02              0x0b0 0x3a0 0x638 0x3 0x0
+#define MX6SL_PAD_EPDC_D2__SPDC_DATA02             0x0b0 0x3a0 0x000 0x4 0x0
+#define MX6SL_PAD_EPDC_D2__GPIO1_IO09              0x0b0 0x3a0 0x000 0x5 0x0
+#define MX6SL_PAD_EPDC_D3__EPDC_DATA03             0x0b4 0x3a4 0x000 0x0 0x0
+#define MX6SL_PAD_EPDC_D3__ECSPI4_SCLK             0x0b4 0x3a4 0x6d0 0x1 0x0
+#define MX6SL_PAD_EPDC_D3__LCD_DATA27              0x0b4 0x3a4 0x000 0x2 0x0
+#define MX6SL_PAD_EPDC_D3__CSI_DATA03              0x0b4 0x3a4 0x63c 0x3 0x0
+#define MX6SL_PAD_EPDC_D3__SPDC_DATA03             0x0b4 0x3a4 0x000 0x4 0x0
+#define MX6SL_PAD_EPDC_D3__GPIO1_IO10              0x0b4 0x3a4 0x000 0x5 0x0
+#define MX6SL_PAD_EPDC_D4__EPDC_DATA04             0x0b8 0x3a8 0x000 0x0 0x0
+#define MX6SL_PAD_EPDC_D4__ECSPI4_SS1              0x0b8 0x3a8 0x6e0 0x1 0x0
+#define MX6SL_PAD_EPDC_D4__LCD_DATA28              0x0b8 0x3a8 0x000 0x2 0x0
+#define MX6SL_PAD_EPDC_D4__CSI_DATA04              0x0b8 0x3a8 0x640 0x3 0x0
+#define MX6SL_PAD_EPDC_D4__SPDC_DATA04             0x0b8 0x3a8 0x000 0x4 0x0
+#define MX6SL_PAD_EPDC_D4__GPIO1_IO11              0x0b8 0x3a8 0x000 0x5 0x0
+#define MX6SL_PAD_EPDC_D5__EPDC_DATA05             0x0bc 0x3ac 0x000 0x0 0x0
+#define MX6SL_PAD_EPDC_D5__ECSPI4_SS2              0x0bc 0x3ac 0x6e4 0x1 0x0
+#define MX6SL_PAD_EPDC_D5__LCD_DATA29              0x0bc 0x3ac 0x000 0x2 0x0
+#define MX6SL_PAD_EPDC_D5__CSI_DATA05              0x0bc 0x3ac 0x644 0x3 0x0
+#define MX6SL_PAD_EPDC_D5__SPDC_DATA05             0x0bc 0x3ac 0x000 0x4 0x0
+#define MX6SL_PAD_EPDC_D5__GPIO1_IO12              0x0bc 0x3ac 0x000 0x5 0x0
+#define MX6SL_PAD_EPDC_D6__EPDC_DATA06             0x0c0 0x3b0 0x000 0x0 0x0
+#define MX6SL_PAD_EPDC_D6__ECSPI4_SS3              0x0c0 0x3b0 0x000 0x1 0x0
+#define MX6SL_PAD_EPDC_D6__LCD_DATA30              0x0c0 0x3b0 0x000 0x2 0x0
+#define MX6SL_PAD_EPDC_D6__CSI_DATA06              0x0c0 0x3b0 0x648 0x3 0x0
+#define MX6SL_PAD_EPDC_D6__SPDC_DATA06             0x0c0 0x3b0 0x000 0x4 0x0
+#define MX6SL_PAD_EPDC_D6__GPIO1_IO13              0x0c0 0x3b0 0x000 0x5 0x0
+#define MX6SL_PAD_EPDC_D7__EPDC_DATA07             0x0c4 0x3b4 0x000 0x0 0x0
+#define MX6SL_PAD_EPDC_D7__ECSPI4_RDY              0x0c4 0x3b4 0x000 0x1 0x0
+#define MX6SL_PAD_EPDC_D7__LCD_DATA31              0x0c4 0x3b4 0x000 0x2 0x0
+#define MX6SL_PAD_EPDC_D7__CSI_DATA07              0x0c4 0x3b4 0x64c 0x3 0x0
+#define MX6SL_PAD_EPDC_D7__SPDC_DATA07             0x0c4 0x3b4 0x000 0x4 0x0
+#define MX6SL_PAD_EPDC_D7__GPIO1_IO14              0x0c4 0x3b4 0x000 0x5 0x0
+#define MX6SL_PAD_EPDC_D8__EPDC_DATA08             0x0c8 0x3b8 0x000 0x0 0x0
+#define MX6SL_PAD_EPDC_D8__ECSPI3_MOSI             0x0c8 0x3b8 0x6bc 0x1 0x1
+#define MX6SL_PAD_EPDC_D8__EPDC_PWR_CTRL0          0x0c8 0x3b8 0x000 0x2 0x0
+#define MX6SL_PAD_EPDC_D8__EIM_ADDR16              0x0c8 0x3b8 0x000 0x3 0x0
+#define MX6SL_PAD_EPDC_D8__SPDC_DATA08             0x0c8 0x3b8 0x000 0x4 0x0
+#define MX6SL_PAD_EPDC_D8__GPIO1_IO15              0x0c8 0x3b8 0x000 0x5 0x0
+#define MX6SL_PAD_EPDC_D8__SD4_RESET               0x0c8 0x3b8 0x000 0x6 0x0
+#define MX6SL_PAD_EPDC_D9__EPDC_DATA09             0x0cc 0x3bc 0x000 0x0 0x0
+#define MX6SL_PAD_EPDC_D9__ECSPI3_MISO             0x0cc 0x3bc 0x6b8 0x1 0x1
+#define MX6SL_PAD_EPDC_D9__EPDC_PWR_CTRL1          0x0cc 0x3bc 0x000 0x2 0x0
+#define MX6SL_PAD_EPDC_D9__EIM_ADDR17              0x0cc 0x3bc 0x000 0x3 0x0
+#define MX6SL_PAD_EPDC_D9__SPDC_DATA09             0x0cc 0x3bc 0x000 0x4 0x0
+#define MX6SL_PAD_EPDC_D9__GPIO1_IO16              0x0cc 0x3bc 0x000 0x5 0x0
+#define MX6SL_PAD_EPDC_D9__SD4_VSELECT             0x0cc 0x3bc 0x000 0x6 0x0
+#define MX6SL_PAD_EPDC_GDCLK__EPDC_GDCLK           0x0d0 0x3c0 0x000 0x0 0x0
+#define MX6SL_PAD_EPDC_GDCLK__ECSPI2_SS2           0x0d0 0x3c0 0x000 0x1 0x0
+#define MX6SL_PAD_EPDC_GDCLK__SPDC_YCKR            0x0d0 0x3c0 0x000 0x2 0x0
+#define MX6SL_PAD_EPDC_GDCLK__CSI_PIXCLK           0x0d0 0x3c0 0x674 0x3 0x1
+#define MX6SL_PAD_EPDC_GDCLK__SPDC_YCKL            0x0d0 0x3c0 0x000 0x4 0x0
+#define MX6SL_PAD_EPDC_GDCLK__GPIO1_IO31           0x0d0 0x3c0 0x000 0x5 0x0
+#define MX6SL_PAD_EPDC_GDCLK__SD2_RESET            0x0d0 0x3c0 0x000 0x6 0x0
+#define MX6SL_PAD_EPDC_GDOE__EPDC_GDOE             0x0d4 0x3c4 0x000 0x0 0x0
+#define MX6SL_PAD_EPDC_GDOE__ECSPI2_SS3            0x0d4 0x3c4 0x000 0x1 0x0
+#define MX6SL_PAD_EPDC_GDOE__SPDC_YOER             0x0d4 0x3c4 0x000 0x2 0x0
+#define MX6SL_PAD_EPDC_GDOE__CSI_HSYNC             0x0d4 0x3c4 0x670 0x3 0x1
+#define MX6SL_PAD_EPDC_GDOE__SPDC_YOEL             0x0d4 0x3c4 0x000 0x4 0x0
+#define MX6SL_PAD_EPDC_GDOE__GPIO2_IO00            0x0d4 0x3c4 0x000 0x5 0x0
+#define MX6SL_PAD_EPDC_GDOE__SD2_VSELECT           0x0d4 0x3c4 0x000 0x6 0x0
+#define MX6SL_PAD_EPDC_GDRL__EPDC_GDRL             0x0d8 0x3c8 0x000 0x0 0x0
+#define MX6SL_PAD_EPDC_GDRL__ECSPI2_RDY            0x0d8 0x3c8 0x000 0x1 0x0
+#define MX6SL_PAD_EPDC_GDRL__SPDC_YDIOUR           0x0d8 0x3c8 0x000 0x2 0x0
+#define MX6SL_PAD_EPDC_GDRL__CSI_MCLK              0x0d8 0x3c8 0x000 0x3 0x0
+#define MX6SL_PAD_EPDC_GDRL__SPDC_YDIOUL           0x0d8 0x3c8 0x000 0x4 0x0
+#define MX6SL_PAD_EPDC_GDRL__GPIO2_IO01            0x0d8 0x3c8 0x000 0x5 0x0
+#define MX6SL_PAD_EPDC_GDRL__SD2_WP                0x0d8 0x3c8 0x834 0x6 0x1
+#define MX6SL_PAD_EPDC_GDSP__EPDC_GDSP             0x0dc 0x3cc 0x000 0x0 0x0
+#define MX6SL_PAD_EPDC_GDSP__PWM4_OUT              0x0dc 0x3cc 0x000 0x1 0x0
+#define MX6SL_PAD_EPDC_GDSP__SPDC_YDIODR           0x0dc 0x3cc 0x000 0x2 0x0
+#define MX6SL_PAD_EPDC_GDSP__CSI_VSYNC             0x0dc 0x3cc 0x678 0x3 0x1
+#define MX6SL_PAD_EPDC_GDSP__SPDC_YDIODL           0x0dc 0x3cc 0x000 0x4 0x0
+#define MX6SL_PAD_EPDC_GDSP__GPIO2_IO02            0x0dc 0x3cc 0x000 0x5 0x0
+#define MX6SL_PAD_EPDC_GDSP__SD2_CD_B              0x0dc 0x3cc 0x830 0x6 0x1
+#define MX6SL_PAD_EPDC_PWRCOM__EPDC_PWR_COM        0x0e0 0x3d0 0x000 0x0 0x0
+#define MX6SL_PAD_EPDC_PWRCOM__SD4_DATA0           0x0e0 0x3d0 0x85c 0x1 0x0
+#define MX6SL_PAD_EPDC_PWRCOM__LCD_DATA20          0x0e0 0x3d0 0x7c8 0x2 0x0
+#define MX6SL_PAD_EPDC_PWRCOM__EIM_BCLK            0x0e0 0x3d0 0x000 0x3 0x0
+#define MX6SL_PAD_EPDC_PWRCOM__USB_OTG1_ID         0x0e0 0x3d0 0x5dc 0x4 0x0
+#define MX6SL_PAD_EPDC_PWRCOM__GPIO2_IO11          0x0e0 0x3d0 0x000 0x5 0x0
+#define MX6SL_PAD_EPDC_PWRCOM__SD3_RESET           0x0e0 0x3d0 0x000 0x6 0x0
+#define MX6SL_PAD_EPDC_PWRCTRL0__EPDC_PWR_CTRL0    0x0e4 0x3d4 0x000 0x0 0x0
+#define MX6SL_PAD_EPDC_PWRCTRL0__AUD5_RXC          0x0e4 0x3d4 0x604 0x1 0x0
+#define MX6SL_PAD_EPDC_PWRCTRL0__LCD_DATA16        0x0e4 0x3d4 0x7b8 0x2 0x0
+#define MX6SL_PAD_EPDC_PWRCTRL0__EIM_RW            0x0e4 0x3d4 0x000 0x3 0x0
+#define MX6SL_PAD_EPDC_PWRCTRL0__SPDC_YCKL         0x0e4 0x3d4 0x000 0x4 0x0
+#define MX6SL_PAD_EPDC_PWRCTRL0__GPIO2_IO07        0x0e4 0x3d4 0x000 0x5 0x0
+#define MX6SL_PAD_EPDC_PWRCTRL0__SD4_RESET         0x0e4 0x3d4 0x000 0x6 0x0
+#define MX6SL_PAD_EPDC_PWRCTRL1__EPDC_PWR_CTRL1    0x0e8 0x3d8 0x000 0x0 0x0
+#define MX6SL_PAD_EPDC_PWRCTRL1__AUD5_TXFS         0x0e8 0x3d8 0x610 0x1 0x0
+#define MX6SL_PAD_EPDC_PWRCTRL1__LCD_DATA17        0x0e8 0x3d8 0x7bc 0x2 0x0
+#define MX6SL_PAD_EPDC_PWRCTRL1__EIM_OE_B          0x0e8 0x3d8 0x000 0x3 0x0
+#define MX6SL_PAD_EPDC_PWRCTRL1__SPDC_YOEL         0x0e8 0x3d8 0x000 0x4 0x0
+#define MX6SL_PAD_EPDC_PWRCTRL1__GPIO2_IO08        0x0e8 0x3d8 0x000 0x5 0x0
+#define MX6SL_PAD_EPDC_PWRCTRL1__SD4_VSELECT       0x0e8 0x3d8 0x000 0x6 0x0
+#define MX6SL_PAD_EPDC_PWRCTRL2__EPDC_PWR_CTRL2    0x0ec 0x3dc 0x000 0x0 0x0
+#define MX6SL_PAD_EPDC_PWRCTRL2__AUD5_TXD          0x0ec 0x3dc 0x600 0x1 0x0
+#define MX6SL_PAD_EPDC_PWRCTRL2__LCD_DATA18        0x0ec 0x3dc 0x7c0 0x2 0x0
+#define MX6SL_PAD_EPDC_PWRCTRL2__EIM_CS0_B         0x0ec 0x3dc 0x000 0x3 0x0
+#define MX6SL_PAD_EPDC_PWRCTRL2__SPDC_YDIOUL       0x0ec 0x3dc 0x000 0x4 0x0
+#define MX6SL_PAD_EPDC_PWRCTRL2__GPIO2_IO09        0x0ec 0x3dc 0x000 0x5 0x0
+#define MX6SL_PAD_EPDC_PWRCTRL2__SD4_WP            0x0ec 0x3dc 0x87c 0x6 0x1
+#define MX6SL_PAD_EPDC_PWRCTRL3__EPDC_PWR_CTRL3    0x0f0 0x3e0 0x000 0x0 0x0
+#define MX6SL_PAD_EPDC_PWRCTRL3__AUD5_TXC          0x0f0 0x3e0 0x60c 0x1 0x0
+#define MX6SL_PAD_EPDC_PWRCTRL3__LCD_DATA19        0x0f0 0x3e0 0x7c4 0x2 0x0
+#define MX6SL_PAD_EPDC_PWRCTRL3__EIM_CS1_B         0x0f0 0x3e0 0x000 0x3 0x0
+#define MX6SL_PAD_EPDC_PWRCTRL3__SPDC_YDIODL       0x0f0 0x3e0 0x000 0x4 0x0
+#define MX6SL_PAD_EPDC_PWRCTRL3__GPIO2_IO10        0x0f0 0x3e0 0x000 0x5 0x0
+#define MX6SL_PAD_EPDC_PWRCTRL3__SD4_CD_B          0x0f0 0x3e0 0x854 0x6 0x1
+#define MX6SL_PAD_EPDC_PWRINT__EPDC_PWR_IRQ        0x0f4 0x3e4 0x6e8 0x0 0x1
+#define MX6SL_PAD_EPDC_PWRINT__SD4_DATA1           0x0f4 0x3e4 0x860 0x1 0x0
+#define MX6SL_PAD_EPDC_PWRINT__LCD_DATA21          0x0f4 0x3e4 0x7cc 0x2 0x0
+#define MX6SL_PAD_EPDC_PWRINT__EIM_ACLK_FREERUN    0x0f4 0x3e4 0x000 0x3 0x0
+#define MX6SL_PAD_EPDC_PWRINT__USB_OTG2_ID         0x0f4 0x3e4 0x5e0 0x4 0x0
+#define MX6SL_PAD_EPDC_PWRINT__GPIO2_IO12          0x0f4 0x3e4 0x000 0x5 0x0
+#define MX6SL_PAD_EPDC_PWRINT__SD3_VSELECT         0x0f4 0x3e4 0x000 0x6 0x0
+#define MX6SL_PAD_EPDC_PWRSTAT__EPDC_PWR_STAT      0x0f8 0x3e8 0x6ec 0x0 0x1
+#define MX6SL_PAD_EPDC_PWRSTAT__SD4_DATA2          0x0f8 0x3e8 0x864 0x1 0x0
+#define MX6SL_PAD_EPDC_PWRSTAT__LCD_DATA22         0x0f8 0x3e8 0x7d0 0x2 0x0
+#define MX6SL_PAD_EPDC_PWRSTAT__EIM_WAIT_B         0x0f8 0x3e8 0x884 0x3 0x0
+#define MX6SL_PAD_EPDC_PWRSTAT__ARM_EVENTI         0x0f8 0x3e8 0x000 0x4 0x0
+#define MX6SL_PAD_EPDC_PWRSTAT__GPIO2_IO13         0x0f8 0x3e8 0x000 0x5 0x0
+#define MX6SL_PAD_EPDC_PWRSTAT__SD3_WP             0x0f8 0x3e8 0x84c 0x6 0x0
+#define MX6SL_PAD_EPDC_PWRWAKEUP__EPDC_PWR_WAKE    0x0fc 0x3ec 0x000 0x0 0x0
+#define MX6SL_PAD_EPDC_PWRWAKEUP__SD4_DATA3        0x0fc 0x3ec 0x868 0x1 0x0
+#define MX6SL_PAD_EPDC_PWRWAKEUP__LCD_DATA23       0x0fc 0x3ec 0x7d4 0x2 0x0
+#define MX6SL_PAD_EPDC_PWRWAKEUP__EIM_DTACK_B      0x0fc 0x3ec 0x880 0x3 0x0
+#define MX6SL_PAD_EPDC_PWRWAKEUP__ARM_EVENTO       0x0fc 0x3ec 0x000 0x4 0x0
+#define MX6SL_PAD_EPDC_PWRWAKEUP__GPIO2_IO14       0x0fc 0x3ec 0x000 0x5 0x0
+#define MX6SL_PAD_EPDC_PWRWAKEUP__SD3_CD_B         0x0fc 0x3ec 0x838 0x6 0x0
+#define MX6SL_PAD_EPDC_SDCE0__EPDC_SDCE0           0x100 0x3f0 0x000 0x0 0x0
+#define MX6SL_PAD_EPDC_SDCE0__ECSPI2_SS1           0x100 0x3f0 0x6ac 0x1 0x0
+#define MX6SL_PAD_EPDC_SDCE0__PWM3_OUT             0x100 0x3f0 0x000 0x2 0x0
+#define MX6SL_PAD_EPDC_SDCE0__EIM_CS2_B            0x100 0x3f0 0x000 0x3 0x0
+#define MX6SL_PAD_EPDC_SDCE0__SPDC_YCKR            0x100 0x3f0 0x000 0x4 0x0
+#define MX6SL_PAD_EPDC_SDCE0__GPIO1_IO27           0x100 0x3f0 0x000 0x5 0x0
+#define MX6SL_PAD_EPDC_SDCE1__EPDC_SDCE1           0x104 0x3f4 0x000 0x0 0x0
+#define MX6SL_PAD_EPDC_SDCE1__WDOG2_B              0x104 0x3f4 0x000 0x1 0x0
+#define MX6SL_PAD_EPDC_SDCE1__PWM4_OUT             0x104 0x3f4 0x000 0x2 0x0
+#define MX6SL_PAD_EPDC_SDCE1__EIM_LBA_B            0x104 0x3f4 0x000 0x3 0x0
+#define MX6SL_PAD_EPDC_SDCE1__SPDC_YOER            0x104 0x3f4 0x000 0x4 0x0
+#define MX6SL_PAD_EPDC_SDCE1__GPIO1_IO28           0x104 0x3f4 0x000 0x5 0x0
+#define MX6SL_PAD_EPDC_SDCE2__EPDC_SDCE2           0x108 0x3f8 0x000 0x0 0x0
+#define MX6SL_PAD_EPDC_SDCE2__I2C3_SCL             0x108 0x3f8 0x72c 0x1 0x1
+#define MX6SL_PAD_EPDC_SDCE2__PWM1_OUT             0x108 0x3f8 0x000 0x2 0x0
+#define MX6SL_PAD_EPDC_SDCE2__EIM_EB0_B            0x108 0x3f8 0x000 0x3 0x0
+#define MX6SL_PAD_EPDC_SDCE2__SPDC_YDIOUR          0x108 0x3f8 0x000 0x4 0x0
+#define MX6SL_PAD_EPDC_SDCE2__GPIO1_IO29           0x108 0x3f8 0x000 0x5 0x0
+#define MX6SL_PAD_EPDC_SDCE3__EPDC_SDCE3           0x10c 0x3fc 0x000 0x0 0x0
+#define MX6SL_PAD_EPDC_SDCE3__I2C3_SDA             0x10c 0x3fc 0x730 0x1 0x1
+#define MX6SL_PAD_EPDC_SDCE3__PWM2_OUT             0x10c 0x3fc 0x000 0x2 0x0
+#define MX6SL_PAD_EPDC_SDCE3__EIM_EB1_B            0x10c 0x3fc 0x000 0x3 0x0
+#define MX6SL_PAD_EPDC_SDCE3__SPDC_YDIODR          0x10c 0x3fc 0x000 0x4 0x0
+#define MX6SL_PAD_EPDC_SDCE3__GPIO1_IO30           0x10c 0x3fc 0x000 0x5 0x0
+#define MX6SL_PAD_EPDC_SDCLK__EPDC_SDCLK_P         0x110 0x400 0x000 0x0 0x0
+#define MX6SL_PAD_EPDC_SDCLK__ECSPI2_MOSI          0x110 0x400 0x6a4 0x1 0x1
+#define MX6SL_PAD_EPDC_SDCLK__I2C2_SCL             0x110 0x400 0x724 0x2 0x0
+#define MX6SL_PAD_EPDC_SDCLK__CSI_DATA08           0x110 0x400 0x650 0x3 0x0
+#define MX6SL_PAD_EPDC_SDCLK__SPDC_CL              0x110 0x400 0x000 0x4 0x0
+#define MX6SL_PAD_EPDC_SDCLK__GPIO1_IO23           0x110 0x400 0x000 0x5 0x0
+#define MX6SL_PAD_EPDC_SDLE__EPDC_SDLE             0x114 0x404 0x000 0x0 0x0
+#define MX6SL_PAD_EPDC_SDLE__ECSPI2_MISO           0x114 0x404 0x6a0 0x1 0x1
+#define MX6SL_PAD_EPDC_SDLE__I2C2_SDA              0x114 0x404 0x728 0x2 0x0
+#define MX6SL_PAD_EPDC_SDLE__CSI_DATA09            0x114 0x404 0x654 0x3 0x0
+#define MX6SL_PAD_EPDC_SDLE__SPDC_LD               0x114 0x404 0x000 0x4 0x0
+#define MX6SL_PAD_EPDC_SDLE__GPIO1_IO24            0x114 0x404 0x000 0x5 0x0
+#define MX6SL_PAD_EPDC_SDOE__EPDC_SDOE             0x118 0x408 0x000 0x0 0x0
+#define MX6SL_PAD_EPDC_SDOE__ECSPI2_SS0            0x118 0x408 0x6a8 0x1 0x1
+#define MX6SL_PAD_EPDC_SDOE__SPDC_XDIOR            0x118 0x408 0x000 0x2 0x0
+#define MX6SL_PAD_EPDC_SDOE__CSI_DATA10            0x118 0x408 0x658 0x3 0x0
+#define MX6SL_PAD_EPDC_SDOE__SPDC_XDIOL            0x118 0x408 0x000 0x4 0x0
+#define MX6SL_PAD_EPDC_SDOE__GPIO1_IO25            0x118 0x408 0x000 0x5 0x0
+#define MX6SL_PAD_EPDC_SDSHR__EPDC_SDSHR           0x11c 0x40c 0x000 0x0 0x0
+#define MX6SL_PAD_EPDC_SDSHR__ECSPI2_SCLK          0x11c 0x40c 0x69c 0x1 0x1
+#define MX6SL_PAD_EPDC_SDSHR__EPDC_SDCE4           0x11c 0x40c 0x000 0x2 0x0
+#define MX6SL_PAD_EPDC_SDSHR__CSI_DATA11           0x11c 0x40c 0x65c 0x3 0x0
+#define MX6SL_PAD_EPDC_SDSHR__SPDC_XDIOR           0x11c 0x40c 0x000 0x4 0x0
+#define MX6SL_PAD_EPDC_SDSHR__GPIO1_IO26           0x11c 0x40c 0x000 0x5 0x0
+#define MX6SL_PAD_EPDC_VCOM0__EPDC_VCOM0           0x120 0x410 0x000 0x0 0x0
+#define MX6SL_PAD_EPDC_VCOM0__AUD5_RXFS            0x120 0x410 0x608 0x1 0x0
+#define MX6SL_PAD_EPDC_VCOM0__UART3_RX_DATA        0x120 0x410 0x80c 0x2 0x4
+#define MX6SL_PAD_EPDC_VCOM0__UART3_TX_DATA        0x120 0x410 0x000 0x2 0x0
+#define MX6SL_PAD_EPDC_VCOM0__EIM_ADDR24           0x120 0x410 0x000 0x3 0x0
+#define MX6SL_PAD_EPDC_VCOM0__SPDC_VCOM0           0x120 0x410 0x000 0x4 0x0
+#define MX6SL_PAD_EPDC_VCOM0__GPIO2_IO03           0x120 0x410 0x000 0x5 0x0
+#define MX6SL_PAD_EPDC_VCOM0__EPDC_SDCE5           0x120 0x410 0x000 0x6 0x0
+#define MX6SL_PAD_EPDC_VCOM1__EPDC_VCOM1           0x124 0x414 0x000 0x0 0x0
+#define MX6SL_PAD_EPDC_VCOM1__AUD5_RXD             0x124 0x414 0x5fc 0x1 0x0
+#define MX6SL_PAD_EPDC_VCOM1__UART3_TX_DATA        0x124 0x414 0x000 0x2 0x0
+#define MX6SL_PAD_EPDC_VCOM1__UART3_RX_DATA        0x124 0x414 0x80c 0x2 0x5
+#define MX6SL_PAD_EPDC_VCOM1__EIM_ADDR25           0x124 0x414 0x000 0x3 0x0
+#define MX6SL_PAD_EPDC_VCOM1__SPDC_VCOM1           0x124 0x414 0x000 0x4 0x0
+#define MX6SL_PAD_EPDC_VCOM1__GPIO2_IO04           0x124 0x414 0x000 0x5 0x0
+#define MX6SL_PAD_EPDC_VCOM1__EPDC_SDCE6           0x124 0x414 0x000 0x6 0x0
+#define MX6SL_PAD_FEC_CRS_DV__FEC_RX_DV            0x128 0x418 0x704 0x0 0x1
+#define MX6SL_PAD_FEC_CRS_DV__SD4_DATA1            0x128 0x418 0x860 0x1 0x1
+#define MX6SL_PAD_FEC_CRS_DV__AUD6_TXC             0x128 0x418 0x624 0x2 0x0
+#define MX6SL_PAD_FEC_CRS_DV__ECSPI4_MISO          0x128 0x418 0x6d4 0x3 0x1
+#define MX6SL_PAD_FEC_CRS_DV__GPT_COMPARE2         0x128 0x418 0x000 0x4 0x0
+#define MX6SL_PAD_FEC_CRS_DV__GPIO4_IO25           0x128 0x418 0x000 0x5 0x0
+#define MX6SL_PAD_FEC_CRS_DV__ARM_TRACE31          0x128 0x418 0x000 0x6 0x0
+#define MX6SL_PAD_FEC_MDC__FEC_MDC                 0x12c 0x41c 0x000 0x0 0x0
+#define MX6SL_PAD_FEC_MDC__SD4_DATA4               0x12c 0x41c 0x86c 0x1 0x0
+#define MX6SL_PAD_FEC_MDC__AUDIO_CLK_OUT           0x12c 0x41c 0x000 0x2 0x0
+#define MX6SL_PAD_FEC_MDC__SD1_RESET               0x12c 0x41c 0x000 0x3 0x0
+#define MX6SL_PAD_FEC_MDC__SD3_RESET               0x12c 0x41c 0x000 0x4 0x0
+#define MX6SL_PAD_FEC_MDC__GPIO4_IO23              0x12c 0x41c 0x000 0x5 0x0
+#define MX6SL_PAD_FEC_MDC__ARM_TRACE29             0x12c 0x41c 0x000 0x6 0x0
+#define MX6SL_PAD_FEC_MDIO__FEC_MDIO               0x130 0x420 0x6f4 0x0 0x1
+#define MX6SL_PAD_FEC_MDIO__SD4_CLK                0x130 0x420 0x850 0x1 0x1
+#define MX6SL_PAD_FEC_MDIO__AUD6_RXFS              0x130 0x420 0x620 0x2 0x0
+#define MX6SL_PAD_FEC_MDIO__ECSPI4_SS0             0x130 0x420 0x6dc 0x3 0x1
+#define MX6SL_PAD_FEC_MDIO__GPT_CAPTURE1           0x130 0x420 0x710 0x4 0x0
+#define MX6SL_PAD_FEC_MDIO__GPIO4_IO20             0x130 0x420 0x000 0x5 0x0
+#define MX6SL_PAD_FEC_MDIO__ARM_TRACE26            0x130 0x420 0x000 0x6 0x0
+#define MX6SL_PAD_FEC_REF_CLK__FEC_REF_OUT         0x134 0x424 0x000 0x0 0x0
+#define MX6SL_PAD_FEC_REF_CLK__SD4_RESET           0x134 0x424 0x000 0x1 0x0
+#define MX6SL_PAD_FEC_REF_CLK__WDOG1_B             0x134 0x424 0x000 0x2 0x0
+#define MX6SL_PAD_FEC_REF_CLK__PWM4_OUT            0x134 0x424 0x000 0x3 0x0
+#define MX6SL_PAD_FEC_REF_CLK__CCM_PMIC_READY      0x134 0x424 0x62c 0x4 0x0
+#define MX6SL_PAD_FEC_REF_CLK__GPIO4_IO26          0x134 0x424 0x000 0x5 0x0
+#define MX6SL_PAD_FEC_REF_CLK__SPDIF_EXT_CLK       0x134 0x424 0x7f4 0x6 0x2
+#define MX6SL_PAD_FEC_RX_ER__FEC_RX_ER             0x138 0x428 0x708 0x0 0x1
+#define MX6SL_PAD_FEC_RX_ER__SD4_DATA0             0x138 0x428 0x85c 0x1 0x1
+#define MX6SL_PAD_FEC_RX_ER__AUD6_RXD              0x138 0x428 0x614 0x2 0x0
+#define MX6SL_PAD_FEC_RX_ER__ECSPI4_MOSI           0x138 0x428 0x6d8 0x3 0x1
+#define MX6SL_PAD_FEC_RX_ER__GPT_COMPARE1          0x138 0x428 0x000 0x4 0x0
+#define MX6SL_PAD_FEC_RX_ER__GPIO4_IO19            0x138 0x428 0x000 0x5 0x0
+#define MX6SL_PAD_FEC_RX_ER__ARM_TRACE25           0x138 0x428 0x000 0x6 0x0
+#define MX6SL_PAD_FEC_RXD0__FEC_RX_DATA0           0x13c 0x42c 0x6f8 0x0 0x0
+#define MX6SL_PAD_FEC_RXD0__SD4_DATA5              0x13c 0x42c 0x870 0x1 0x0
+#define MX6SL_PAD_FEC_RXD0__USB_OTG1_ID            0x13c 0x42c 0x5dc 0x2 0x1
+#define MX6SL_PAD_FEC_RXD0__SD1_VSELECT            0x13c 0x42c 0x000 0x3 0x0
+#define MX6SL_PAD_FEC_RXD0__SD3_VSELECT            0x13c 0x42c 0x000 0x4 0x0
+#define MX6SL_PAD_FEC_RXD0__GPIO4_IO17             0x13c 0x42c 0x000 0x5 0x0
+#define MX6SL_PAD_FEC_RXD0__ARM_TRACE24            0x13c 0x42c 0x000 0x6 0x0
+#define MX6SL_PAD_FEC_RXD1__FEC_RX_DATA1           0x140 0x430 0x6fc 0x0 0x1
+#define MX6SL_PAD_FEC_RXD1__SD4_DATA2              0x140 0x430 0x864 0x1 0x1
+#define MX6SL_PAD_FEC_RXD1__AUD6_TXFS              0x140 0x430 0x628 0x2 0x0
+#define MX6SL_PAD_FEC_RXD1__ECSPI4_SS1             0x140 0x430 0x6e0 0x3 0x1
+#define MX6SL_PAD_FEC_RXD1__GPT_COMPARE3           0x140 0x430 0x000 0x4 0x0
+#define MX6SL_PAD_FEC_RXD1__GPIO4_IO18             0x140 0x430 0x000 0x5 0x0
+#define MX6SL_PAD_FEC_RXD1__FEC_COL                0x140 0x430 0x6f0 0x6 0x0
+#define MX6SL_PAD_FEC_TX_CLK__FEC_TX_CLK           0x144 0x434 0x70c 0x0 0x1
+#define MX6SL_PAD_FEC_TX_CLK__SD4_CMD              0x144 0x434 0x858 0x1 0x1
+#define MX6SL_PAD_FEC_TX_CLK__AUD6_RXC             0x144 0x434 0x61c 0x2 0x0
+#define MX6SL_PAD_FEC_TX_CLK__ECSPI4_SCLK          0x144 0x434 0x6d0 0x3 0x1
+#define MX6SL_PAD_FEC_TX_CLK__GPT_CAPTURE2         0x144 0x434 0x714 0x4 0x0
+#define MX6SL_PAD_FEC_TX_CLK__GPIO4_IO21           0x144 0x434 0x000 0x5 0x0
+#define MX6SL_PAD_FEC_TX_CLK__ARM_TRACE27          0x144 0x434 0x000 0x6 0x0
+#define MX6SL_PAD_FEC_TX_EN__FEC_TX_EN             0x148 0x438 0x000 0x0 0x0
+#define MX6SL_PAD_FEC_TX_EN__SD4_DATA6             0x148 0x438 0x874 0x1 0x0
+#define MX6SL_PAD_FEC_TX_EN__SPDIF_IN              0x148 0x438 0x7f0 0x2 0x0
+#define MX6SL_PAD_FEC_TX_EN__SD1_WP                0x148 0x438 0x82c 0x3 0x1
+#define MX6SL_PAD_FEC_TX_EN__SD3_WP                0x148 0x438 0x84c 0x4 0x1
+#define MX6SL_PAD_FEC_TX_EN__GPIO4_IO22            0x148 0x438 0x000 0x5 0x0
+#define MX6SL_PAD_FEC_TX_EN__ARM_TRACE28           0x148 0x438 0x000 0x6 0x0
+#define MX6SL_PAD_FEC_TXD0__FEC_TX_DATA0           0x14c 0x43c 0x000 0x0 0x0
+#define MX6SL_PAD_FEC_TXD0__SD4_DATA3              0x14c 0x43c 0x868 0x1 0x1
+#define MX6SL_PAD_FEC_TXD0__AUD6_TXD               0x14c 0x43c 0x618 0x2 0x0
+#define MX6SL_PAD_FEC_TXD0__ECSPI4_SS2             0x14c 0x43c 0x6e4 0x3 0x1
+#define MX6SL_PAD_FEC_TXD0__GPT_CLKIN              0x14c 0x43c 0x718 0x4 0x0
+#define MX6SL_PAD_FEC_TXD0__GPIO4_IO24             0x14c 0x43c 0x000 0x5 0x0
+#define MX6SL_PAD_FEC_TXD0__ARM_TRACE30            0x14c 0x43c 0x000 0x6 0x0
+#define MX6SL_PAD_FEC_TXD1__FEC_TX_DATA1           0x150 0x440 0x000 0x0 0x0
+#define MX6SL_PAD_FEC_TXD1__SD4_DATA7              0x150 0x440 0x878 0x1 0x0
+#define MX6SL_PAD_FEC_TXD1__SPDIF_OUT              0x150 0x440 0x000 0x2 0x0
+#define MX6SL_PAD_FEC_TXD1__SD1_CD_B               0x150 0x440 0x828 0x3 0x1
+#define MX6SL_PAD_FEC_TXD1__SD3_CD_B               0x150 0x440 0x838 0x4 0x1
+#define MX6SL_PAD_FEC_TXD1__GPIO4_IO16             0x150 0x440 0x000 0x5 0x0
+#define MX6SL_PAD_FEC_TXD1__FEC_RX_CLK             0x150 0x440 0x700 0x6 0x0
+#define MX6SL_PAD_HSIC_DAT__USB_H_DATA             0x154 0x444 0x000 0x0 0x0
+#define MX6SL_PAD_HSIC_DAT__I2C1_SCL               0x154 0x444 0x71c 0x1 0x1
+#define MX6SL_PAD_HSIC_DAT__PWM1_OUT               0x154 0x444 0x000 0x2 0x0
+#define MX6SL_PAD_HSIC_DAT__XTALOSC_REF_CLK_24M    0x154 0x444 0x000 0x3 0x0
+#define MX6SL_PAD_HSIC_DAT__GPIO3_IO19             0x154 0x444 0x000 0x5 0x0
+#define MX6SL_PAD_HSIC_STROBE__USB_H_STROBE        0x158 0x448 0x000 0x0 0x0
+#define MX6SL_PAD_HSIC_STROBE__I2C1_SDA            0x158 0x448 0x720 0x1 0x1
+#define MX6SL_PAD_HSIC_STROBE__PWM2_OUT            0x158 0x448 0x000 0x2 0x0
+#define MX6SL_PAD_HSIC_STROBE__XTALOSC_REF_CLK_32K 0x158 0x448 0x000 0x3 0x0
+#define MX6SL_PAD_HSIC_STROBE__GPIO3_IO20          0x158 0x448 0x000 0x5 0x0
+#define MX6SL_PAD_I2C1_SCL__I2C1_SCL               0x15c 0x44c 0x71c 0x0 0x2
+#define MX6SL_PAD_I2C1_SCL__UART1_RTS_B            0x15c 0x44c 0x7f8 0x1 0x0
+#define MX6SL_PAD_I2C1_SCL__UART1_CTS_B            0x15c 0x44c 0x000 0x1 0x0
+#define MX6SL_PAD_I2C1_SCL__ECSPI3_SS2             0x15c 0x44c 0x6c8 0x2 0x1
+#define MX6SL_PAD_I2C1_SCL__FEC_RX_DATA0           0x15c 0x44c 0x6f8 0x3 0x1
+#define MX6SL_PAD_I2C1_SCL__SD3_RESET              0x15c 0x44c 0x000 0x4 0x0
+#define MX6SL_PAD_I2C1_SCL__GPIO3_IO12             0x15c 0x44c 0x000 0x5 0x0
+#define MX6SL_PAD_I2C1_SCL__ECSPI1_SS1             0x15c 0x44c 0x690 0x6 0x0
+#define MX6SL_PAD_I2C1_SDA__I2C1_SDA               0x160 0x450 0x720 0x0 0x2
+#define MX6SL_PAD_I2C1_SDA__UART1_CTS_B            0x160 0x450 0x000 0x1 0x0
+#define MX6SL_PAD_I2C1_SDA__UART1_RTS_B            0x160 0x450 0x7f8 0x1 0x1
+#define MX6SL_PAD_I2C1_SDA__ECSPI3_SS3             0x160 0x450 0x6cc 0x2 0x1
+#define MX6SL_PAD_I2C1_SDA__FEC_TX_EN              0x160 0x450 0x000 0x3 0x0
+#define MX6SL_PAD_I2C1_SDA__SD3_VSELECT            0x160 0x450 0x000 0x4 0x0
+#define MX6SL_PAD_I2C1_SDA__GPIO3_IO13             0x160 0x450 0x000 0x5 0x0
+#define MX6SL_PAD_I2C1_SDA__ECSPI1_SS2             0x160 0x450 0x694 0x6 0x0
+#define MX6SL_PAD_I2C2_SCL__I2C2_SCL               0x164 0x454 0x724 0x0 0x1
+#define MX6SL_PAD_I2C2_SCL__AUD4_RXFS              0x164 0x454 0x5f0 0x1 0x0
+#define MX6SL_PAD_I2C2_SCL__SPDIF_IN               0x164 0x454 0x7f0 0x2 0x1
+#define MX6SL_PAD_I2C2_SCL__FEC_TX_DATA1           0x164 0x454 0x000 0x3 0x0
+#define MX6SL_PAD_I2C2_SCL__SD3_WP                 0x164 0x454 0x84c 0x4 0x2
+#define MX6SL_PAD_I2C2_SCL__GPIO3_IO14             0x164 0x454 0x000 0x5 0x0
+#define MX6SL_PAD_I2C2_SCL__ECSPI1_RDY             0x164 0x454 0x680 0x6 0x0
+#define MX6SL_PAD_I2C2_SDA__I2C2_SDA               0x168 0x458 0x728 0x0 0x1
+#define MX6SL_PAD_I2C2_SDA__AUD4_RXC               0x168 0x458 0x5ec 0x1 0x0
+#define MX6SL_PAD_I2C2_SDA__SPDIF_OUT              0x168 0x458 0x000 0x2 0x0
+#define MX6SL_PAD_I2C2_SDA__FEC_REF_OUT            0x168 0x458 0x000 0x3 0x0
+#define MX6SL_PAD_I2C2_SDA__SD3_CD_B               0x168 0x458 0x838 0x4 0x2
+#define MX6SL_PAD_I2C2_SDA__GPIO3_IO15             0x168 0x458 0x000 0x5 0x0
+#define MX6SL_PAD_KEY_COL0__KEY_COL0               0x16c 0x474 0x734 0x0 0x0
+#define MX6SL_PAD_KEY_COL0__I2C2_SCL               0x16c 0x474 0x724 0x1 0x2
+#define MX6SL_PAD_KEY_COL0__LCD_DATA00             0x16c 0x474 0x778 0x2 0x0
+#define MX6SL_PAD_KEY_COL0__EIM_AD00               0x16c 0x474 0x000 0x3 0x0
+#define MX6SL_PAD_KEY_COL0__SD1_CD_B               0x16c 0x474 0x828 0x4 0x2
+#define MX6SL_PAD_KEY_COL0__GPIO3_IO24             0x16c 0x474 0x000 0x5 0x0
+#define MX6SL_PAD_KEY_COL1__KEY_COL1               0x170 0x478 0x738 0x0 0x0
+#define MX6SL_PAD_KEY_COL1__ECSPI4_MOSI            0x170 0x478 0x6d8 0x1 0x2
+#define MX6SL_PAD_KEY_COL1__LCD_DATA02             0x170 0x478 0x780 0x2 0x0
+#define MX6SL_PAD_KEY_COL1__EIM_AD02               0x170 0x478 0x000 0x3 0x0
+#define MX6SL_PAD_KEY_COL1__SD3_DATA4              0x170 0x478 0x83c 0x4 0x0
+#define MX6SL_PAD_KEY_COL1__GPIO3_IO26             0x170 0x478 0x000 0x5 0x0
+#define MX6SL_PAD_KEY_COL2__KEY_COL2               0x174 0x47c 0x73c 0x0 0x0
+#define MX6SL_PAD_KEY_COL2__ECSPI4_SS0             0x174 0x47c 0x6dc 0x1 0x2
+#define MX6SL_PAD_KEY_COL2__LCD_DATA04             0x174 0x47c 0x788 0x2 0x0
+#define MX6SL_PAD_KEY_COL2__EIM_AD04               0x174 0x47c 0x000 0x3 0x0
+#define MX6SL_PAD_KEY_COL2__SD3_DATA6              0x174 0x47c 0x844 0x4 0x0
+#define MX6SL_PAD_KEY_COL2__GPIO3_IO28             0x174 0x47c 0x000 0x5 0x0
+#define MX6SL_PAD_KEY_COL3__KEY_COL3               0x178 0x480 0x740 0x0 0x0
+#define MX6SL_PAD_KEY_COL3__AUD6_RXFS              0x178 0x480 0x620 0x1 0x1
+#define MX6SL_PAD_KEY_COL3__LCD_DATA06             0x178 0x480 0x790 0x2 0x0
+#define MX6SL_PAD_KEY_COL3__EIM_AD06               0x178 0x480 0x000 0x3 0x0
+#define MX6SL_PAD_KEY_COL3__SD4_DATA6              0x178 0x480 0x874 0x4 0x1
+#define MX6SL_PAD_KEY_COL3__GPIO3_IO30             0x178 0x480 0x000 0x5 0x0
+#define MX6SL_PAD_KEY_COL3__SD1_RESET              0x178 0x480 0x000 0x6 0x0
+#define MX6SL_PAD_KEY_COL4__KEY_COL4               0x17c 0x484 0x744 0x0 0x0
+#define MX6SL_PAD_KEY_COL4__AUD6_RXD               0x17c 0x484 0x614 0x1 0x1
+#define MX6SL_PAD_KEY_COL4__LCD_DATA08             0x17c 0x484 0x798 0x2 0x0
+#define MX6SL_PAD_KEY_COL4__EIM_AD08               0x17c 0x484 0x000 0x3 0x0
+#define MX6SL_PAD_KEY_COL4__SD4_CLK                0x17c 0x484 0x850 0x4 0x2
+#define MX6SL_PAD_KEY_COL4__GPIO4_IO00             0x17c 0x484 0x000 0x5 0x0
+#define MX6SL_PAD_KEY_COL4__USB_OTG1_PWR           0x17c 0x484 0x000 0x6 0x0
+#define MX6SL_PAD_KEY_COL5__KEY_COL5               0x180 0x488 0x748 0x0 0x0
+#define MX6SL_PAD_KEY_COL5__AUD6_TXFS              0x180 0x488 0x628 0x1 0x1
+#define MX6SL_PAD_KEY_COL5__LCD_DATA10             0x180 0x488 0x7a0 0x2 0x0
+#define MX6SL_PAD_KEY_COL5__EIM_AD10               0x180 0x488 0x000 0x3 0x0
+#define MX6SL_PAD_KEY_COL5__SD4_DATA0              0x180 0x488 0x85c 0x4 0x2
+#define MX6SL_PAD_KEY_COL5__GPIO4_IO02             0x180 0x488 0x000 0x5 0x0
+#define MX6SL_PAD_KEY_COL5__USB_OTG2_PWR           0x180 0x488 0x000 0x6 0x0
+#define MX6SL_PAD_KEY_COL6__KEY_COL6               0x184 0x48c 0x74c 0x0 0x0
+#define MX6SL_PAD_KEY_COL6__UART4_RX_DATA          0x184 0x48c 0x814 0x1 0x2
+#define MX6SL_PAD_KEY_COL6__UART4_TX_DATA          0x184 0x48c 0x000 0x1 0x0
+#define MX6SL_PAD_KEY_COL6__LCD_DATA12             0x184 0x48c 0x7a8 0x2 0x0
+#define MX6SL_PAD_KEY_COL6__EIM_AD12               0x184 0x48c 0x000 0x3 0x0
+#define MX6SL_PAD_KEY_COL6__SD4_DATA2              0x184 0x48c 0x864 0x4 0x2
+#define MX6SL_PAD_KEY_COL6__GPIO4_IO04             0x184 0x48c 0x000 0x5 0x0
+#define MX6SL_PAD_KEY_COL6__SD3_RESET              0x184 0x48c 0x000 0x6 0x0
+#define MX6SL_PAD_KEY_COL7__KEY_COL7               0x188 0x490 0x750 0x0 0x0
+#define MX6SL_PAD_KEY_COL7__UART4_RTS_B            0x188 0x490 0x810 0x1 0x2
+#define MX6SL_PAD_KEY_COL7__UART4_CTS_B            0x188 0x490 0x000 0x1 0x0
+#define MX6SL_PAD_KEY_COL7__LCD_DATA14             0x188 0x490 0x7b0 0x2 0x0
+#define MX6SL_PAD_KEY_COL7__EIM_AD14               0x188 0x490 0x000 0x3 0x0
+#define MX6SL_PAD_KEY_COL7__SD4_DATA4              0x188 0x490 0x86c 0x4 0x1
+#define MX6SL_PAD_KEY_COL7__GPIO4_IO06             0x188 0x490 0x000 0x5 0x0
+#define MX6SL_PAD_KEY_COL7__SD1_WP                 0x188 0x490 0x82c 0x6 0x2
+#define MX6SL_PAD_KEY_ROW0__KEY_ROW0               0x18c 0x494 0x754 0x0 0x0
+#define MX6SL_PAD_KEY_ROW0__I2C2_SDA               0x18c 0x494 0x728 0x1 0x2
+#define MX6SL_PAD_KEY_ROW0__LCD_DATA01             0x18c 0x494 0x77c 0x2 0x0
+#define MX6SL_PAD_KEY_ROW0__EIM_AD01               0x18c 0x494 0x000 0x3 0x0
+#define MX6SL_PAD_KEY_ROW0__SD1_WP                 0x18c 0x494 0x82c 0x4 0x3
+#define MX6SL_PAD_KEY_ROW0__GPIO3_IO25             0x18c 0x494 0x000 0x5 0x0
+#define MX6SL_PAD_KEY_ROW1__KEY_ROW1               0x190 0x498 0x758 0x0 0x0
+#define MX6SL_PAD_KEY_ROW1__ECSPI4_MISO            0x190 0x498 0x6d4 0x1 0x2
+#define MX6SL_PAD_KEY_ROW1__LCD_DATA03             0x190 0x498 0x784 0x2 0x0
+#define MX6SL_PAD_KEY_ROW1__EIM_AD03               0x190 0x498 0x000 0x3 0x0
+#define MX6SL_PAD_KEY_ROW1__SD3_DATA5              0x190 0x498 0x840 0x4 0x0
+#define MX6SL_PAD_KEY_ROW1__GPIO3_IO27             0x190 0x498 0x000 0x5 0x0
+#define MX6SL_PAD_KEY_ROW2__KEY_ROW2               0x194 0x49c 0x75c 0x0 0x0
+#define MX6SL_PAD_KEY_ROW2__ECSPI4_SCLK            0x194 0x49c 0x6d0 0x1 0x2
+#define MX6SL_PAD_KEY_ROW2__LCD_DATA05             0x194 0x49c 0x78c 0x2 0x0
+#define MX6SL_PAD_KEY_ROW2__EIM_AD05               0x194 0x49c 0x000 0x3 0x0
+#define MX6SL_PAD_KEY_ROW2__SD3_DATA7              0x194 0x49c 0x848 0x4 0x0
+#define MX6SL_PAD_KEY_ROW2__GPIO3_IO29             0x194 0x49c 0x000 0x5 0x0
+#define MX6SL_PAD_KEY_ROW3__KEY_ROW3               0x198 0x4a0 0x760 0x0 0x0
+#define MX6SL_PAD_KEY_ROW3__AUD6_RXC               0x198 0x4a0 0x61c 0x1 0x1
+#define MX6SL_PAD_KEY_ROW3__LCD_DATA07             0x198 0x4a0 0x794 0x2 0x0
+#define MX6SL_PAD_KEY_ROW3__EIM_AD07               0x198 0x4a0 0x000 0x3 0x0
+#define MX6SL_PAD_KEY_ROW3__SD4_DATA7              0x198 0x4a0 0x878 0x4 0x1
+#define MX6SL_PAD_KEY_ROW3__GPIO3_IO31             0x198 0x4a0 0x000 0x5 0x0
+#define MX6SL_PAD_KEY_ROW3__SD1_VSELECT            0x198 0x4a0 0x000 0x6 0x0
+#define MX6SL_PAD_KEY_ROW4__KEY_ROW4               0x19c 0x4a4 0x764 0x0 0x0
+#define MX6SL_PAD_KEY_ROW4__AUD6_TXC               0x19c 0x4a4 0x624 0x1 0x1
+#define MX6SL_PAD_KEY_ROW4__LCD_DATA09             0x19c 0x4a4 0x79c 0x2 0x0
+#define MX6SL_PAD_KEY_ROW4__EIM_AD09               0x19c 0x4a4 0x000 0x3 0x0
+#define MX6SL_PAD_KEY_ROW4__SD4_CMD                0x19c 0x4a4 0x858 0x4 0x2
+#define MX6SL_PAD_KEY_ROW4__GPIO4_IO01             0x19c 0x4a4 0x000 0x5 0x0
+#define MX6SL_PAD_KEY_ROW4__USB_OTG1_OC            0x19c 0x4a4 0x824 0x6 0x1
+#define MX6SL_PAD_KEY_ROW5__KEY_ROW5               0x1a0 0x4a8 0x768 0x0 0x0
+#define MX6SL_PAD_KEY_ROW5__AUD6_TXD               0x1a0 0x4a8 0x618 0x1 0x1
+#define MX6SL_PAD_KEY_ROW5__LCD_DATA11             0x1a0 0x4a8 0x7a4 0x2 0x0
+#define MX6SL_PAD_KEY_ROW5__EIM_AD11               0x1a0 0x4a8 0x000 0x3 0x0
+#define MX6SL_PAD_KEY_ROW5__SD4_DATA1              0x1a0 0x4a8 0x860 0x4 0x2
+#define MX6SL_PAD_KEY_ROW5__GPIO4_IO03             0x1a0 0x4a8 0x000 0x5 0x0
+#define MX6SL_PAD_KEY_ROW5__USB_OTG2_OC            0x1a0 0x4a8 0x820 0x6 0x2
+#define MX6SL_PAD_KEY_ROW6__KEY_ROW6               0x1a4 0x4ac 0x76c 0x0 0x0
+#define MX6SL_PAD_KEY_ROW6__UART4_TX_DATA          0x1a4 0x4ac 0x000 0x1 0x0
+#define MX6SL_PAD_KEY_ROW6__UART4_RX_DATA          0x1a4 0x4ac 0x814 0x1 0x3
+#define MX6SL_PAD_KEY_ROW6__LCD_DATA13             0x1a4 0x4ac 0x7ac 0x2 0x0
+#define MX6SL_PAD_KEY_ROW6__EIM_AD13               0x1a4 0x4ac 0x000 0x3 0x0
+#define MX6SL_PAD_KEY_ROW6__SD4_DATA3              0x1a4 0x4ac 0x868 0x4 0x2
+#define MX6SL_PAD_KEY_ROW6__GPIO4_IO05             0x1a4 0x4ac 0x000 0x5 0x0
+#define MX6SL_PAD_KEY_ROW6__SD3_VSELECT            0x1a4 0x4ac 0x000 0x6 0x0
+#define MX6SL_PAD_KEY_ROW7__KEY_ROW7               0x1a8 0x4b0 0x770 0x0 0x0
+#define MX6SL_PAD_KEY_ROW7__UART4_CTS_B            0x1a8 0x4b0 0x000 0x1 0x0
+#define MX6SL_PAD_KEY_ROW7__UART4_RTS_B            0x1a8 0x4b0 0x810 0x1 0x3
+#define MX6SL_PAD_KEY_ROW7__LCD_DATA15             0x1a8 0x4b0 0x7b4 0x2 0x0
+#define MX6SL_PAD_KEY_ROW7__EIM_AD15               0x1a8 0x4b0 0x000 0x3 0x0
+#define MX6SL_PAD_KEY_ROW7__SD4_DATA5              0x1a8 0x4b0 0x870 0x4 0x1
+#define MX6SL_PAD_KEY_ROW7__GPIO4_IO07             0x1a8 0x4b0 0x000 0x5 0x0
+#define MX6SL_PAD_KEY_ROW7__SD1_CD_B               0x1a8 0x4b0 0x828 0x6 0x3
+#define MX6SL_PAD_LCD_CLK__LCD_CLK                 0x1ac 0x4b4 0x000 0x0 0x0
+#define MX6SL_PAD_LCD_CLK__SD4_DATA4               0x1ac 0x4b4 0x86c 0x1 0x2
+#define MX6SL_PAD_LCD_CLK__LCD_WR_RWN              0x1ac 0x4b4 0x000 0x2 0x0
+#define MX6SL_PAD_LCD_CLK__EIM_RW                  0x1ac 0x4b4 0x000 0x3 0x0
+#define MX6SL_PAD_LCD_CLK__PWM4_OUT                0x1ac 0x4b4 0x000 0x4 0x0
+#define MX6SL_PAD_LCD_CLK__GPIO2_IO15              0x1ac 0x4b4 0x000 0x5 0x0
+#define MX6SL_PAD_LCD_DAT0__LCD_DATA00             0x1b0 0x4b8 0x778 0x0 0x1
+#define MX6SL_PAD_LCD_DAT0__ECSPI1_MOSI            0x1b0 0x4b8 0x688 0x1 0x1
+#define MX6SL_PAD_LCD_DAT0__USB_OTG2_ID            0x1b0 0x4b8 0x5e0 0x2 0x1
+#define MX6SL_PAD_LCD_DAT0__PWM1_OUT               0x1b0 0x4b8 0x000 0x3 0x0
+#define MX6SL_PAD_LCD_DAT0__UART5_DTR_B            0x1b0 0x4b8 0x000 0x4 0x0
+#define MX6SL_PAD_LCD_DAT0__GPIO2_IO20             0x1b0 0x4b8 0x000 0x5 0x0
+#define MX6SL_PAD_LCD_DAT0__ARM_TRACE00            0x1b0 0x4b8 0x000 0x6 0x0
+#define MX6SL_PAD_LCD_DAT0__SRC_BOOT_CFG00         0x1b0 0x4b8 0x000 0x7 0x0
+#define MX6SL_PAD_LCD_DAT1__LCD_DATA01             0x1b4 0x4bc 0x77c 0x0 0x1
+#define MX6SL_PAD_LCD_DAT1__ECSPI1_MISO            0x1b4 0x4bc 0x684 0x1 0x1
+#define MX6SL_PAD_LCD_DAT1__USB_OTG1_ID            0x1b4 0x4bc 0x5dc 0x2 0x2
+#define MX6SL_PAD_LCD_DAT1__PWM2_OUT               0x1b4 0x4bc 0x000 0x3 0x0
+#define MX6SL_PAD_LCD_DAT1__AUD4_RXFS              0x1b4 0x4bc 0x5f0 0x4 0x1
+#define MX6SL_PAD_LCD_DAT1__GPIO2_IO21             0x1b4 0x4bc 0x000 0x5 0x0
+#define MX6SL_PAD_LCD_DAT1__ARM_TRACE01            0x1b4 0x4bc 0x000 0x6 0x0
+#define MX6SL_PAD_LCD_DAT1__SRC_BOOT_CFG01         0x1b4 0x4bc 0x000 0x7 0x0
+#define MX6SL_PAD_LCD_DAT10__LCD_DATA10            0x1b8 0x4c0 0x7a0 0x0 0x1
+#define MX6SL_PAD_LCD_DAT10__KEY_COL1              0x1b8 0x4c0 0x738 0x1 0x1
+#define MX6SL_PAD_LCD_DAT10__CSI_DATA07            0x1b8 0x4c0 0x64c 0x2 0x1
+#define MX6SL_PAD_LCD_DAT10__EIM_DATA04            0x1b8 0x4c0 0x000 0x3 0x0
+#define MX6SL_PAD_LCD_DAT10__ECSPI2_MISO           0x1b8 0x4c0 0x6a0 0x4 0x2
+#define MX6SL_PAD_LCD_DAT10__GPIO2_IO30            0x1b8 0x4c0 0x000 0x5 0x0
+#define MX6SL_PAD_LCD_DAT10__ARM_TRACE10           0x1b8 0x4c0 0x000 0x6 0x0
+#define MX6SL_PAD_LCD_DAT10__SRC_BOOT_CFG10        0x1b8 0x4c0 0x000 0x7 0x0
+#define MX6SL_PAD_LCD_DAT11__LCD_DATA11            0x1bc 0x4c4 0x7a4 0x0 0x1
+#define MX6SL_PAD_LCD_DAT11__KEY_ROW1              0x1bc 0x4c4 0x758 0x1 0x1
+#define MX6SL_PAD_LCD_DAT11__CSI_DATA06            0x1bc 0x4c4 0x648 0x2 0x1
+#define MX6SL_PAD_LCD_DAT11__EIM_DATA05            0x1bc 0x4c4 0x000 0x3 0x0
+#define MX6SL_PAD_LCD_DAT11__ECSPI2_SS1            0x1bc 0x4c4 0x6ac 0x4 0x1
+#define MX6SL_PAD_LCD_DAT11__GPIO2_IO31            0x1bc 0x4c4 0x000 0x5 0x0
+#define MX6SL_PAD_LCD_DAT11__ARM_TRACE11           0x1bc 0x4c4 0x000 0x6 0x0
+#define MX6SL_PAD_LCD_DAT11__SRC_BOOT_CFG11        0x1bc 0x4c4 0x000 0x7 0x0
+#define MX6SL_PAD_LCD_DAT12__LCD_DATA12            0x1c0 0x4c8 0x7a8 0x0 0x1
+#define MX6SL_PAD_LCD_DAT12__KEY_COL2              0x1c0 0x4c8 0x73c 0x1 0x1
+#define MX6SL_PAD_LCD_DAT12__CSI_DATA05            0x1c0 0x4c8 0x644 0x2 0x1
+#define MX6SL_PAD_LCD_DAT12__EIM_DATA06            0x1c0 0x4c8 0x000 0x3 0x0
+#define MX6SL_PAD_LCD_DAT12__UART5_RTS_B           0x1c0 0x4c8 0x818 0x4 0x2
+#define MX6SL_PAD_LCD_DAT12__UART5_CTS_B           0x1c0 0x4c8 0x000 0x4 0x0
+#define MX6SL_PAD_LCD_DAT12__GPIO3_IO00            0x1c0 0x4c8 0x000 0x5 0x0
+#define MX6SL_PAD_LCD_DAT12__ARM_TRACE12           0x1c0 0x4c8 0x000 0x6 0x0
+#define MX6SL_PAD_LCD_DAT12__SRC_BOOT_CFG12        0x1c0 0x4c8 0x000 0x7 0x0
+#define MX6SL_PAD_LCD_DAT13__LCD_DATA13            0x1c4 0x4cc 0x7ac 0x0 0x1
+#define MX6SL_PAD_LCD_DAT13__KEY_ROW2              0x1c4 0x4cc 0x75c 0x1 0x1
+#define MX6SL_PAD_LCD_DAT13__CSI_DATA04            0x1c4 0x4cc 0x640 0x2 0x1
+#define MX6SL_PAD_LCD_DAT13__EIM_DATA07            0x1c4 0x4cc 0x000 0x3 0x0
+#define MX6SL_PAD_LCD_DAT13__UART5_CTS_B           0x1c4 0x4cc 0x000 0x4 0x0
+#define MX6SL_PAD_LCD_DAT13__UART5_RTS_B           0x1c4 0x4cc 0x818 0x4 0x3
+#define MX6SL_PAD_LCD_DAT13__GPIO3_IO01            0x1c4 0x4cc 0x000 0x5 0x0
+#define MX6SL_PAD_LCD_DAT13__ARM_TRACE13           0x1c4 0x4cc 0x000 0x6 0x0
+#define MX6SL_PAD_LCD_DAT13__SRC_BOOT_CFG13        0x1c4 0x4cc 0x000 0x7 0x0
+#define MX6SL_PAD_LCD_DAT14__LCD_DATA14            0x1c8 0x4d0 0x7b0 0x0 0x1
+#define MX6SL_PAD_LCD_DAT14__KEY_COL3              0x1c8 0x4d0 0x740 0x1 0x1
+#define MX6SL_PAD_LCD_DAT14__CSI_DATA03            0x1c8 0x4d0 0x63c 0x2 0x1
+#define MX6SL_PAD_LCD_DAT14__EIM_DATA08            0x1c8 0x4d0 0x000 0x3 0x0
+#define MX6SL_PAD_LCD_DAT14__UART5_RX_DATA         0x1c8 0x4d0 0x81c 0x4 0x2
+#define MX6SL_PAD_LCD_DAT14__UART5_TX_DATA         0x1c8 0x4d0 0x000 0x4 0x0
+#define MX6SL_PAD_LCD_DAT14__GPIO3_IO02            0x1c8 0x4d0 0x000 0x5 0x0
+#define MX6SL_PAD_LCD_DAT14__ARM_TRACE14           0x1c8 0x4d0 0x000 0x6 0x0
+#define MX6SL_PAD_LCD_DAT14__SRC_BOOT_CFG14        0x1c8 0x4d0 0x000 0x7 0x0
+#define MX6SL_PAD_LCD_DAT15__LCD_DATA15            0x1cc 0x4d4 0x7b4 0x0 0x1
+#define MX6SL_PAD_LCD_DAT15__KEY_ROW3              0x1cc 0x4d4 0x760 0x1 0x1
+#define MX6SL_PAD_LCD_DAT15__CSI_DATA02            0x1cc 0x4d4 0x638 0x2 0x1
+#define MX6SL_PAD_LCD_DAT15__EIM_DATA09            0x1cc 0x4d4 0x000 0x3 0x0
+#define MX6SL_PAD_LCD_DAT15__UART5_TX_DATA         0x1cc 0x4d4 0x000 0x4 0x0
+#define MX6SL_PAD_LCD_DAT15__UART5_RX_DATA         0x1cc 0x4d4 0x81c 0x4 0x3
+#define MX6SL_PAD_LCD_DAT15__GPIO3_IO03            0x1cc 0x4d4 0x000 0x5 0x0
+#define MX6SL_PAD_LCD_DAT15__ARM_TRACE15           0x1cc 0x4d4 0x000 0x6 0x0
+#define MX6SL_PAD_LCD_DAT15__SRC_BOOT_CFG15        0x1cc 0x4d4 0x000 0x7 0x0
+#define MX6SL_PAD_LCD_DAT16__LCD_DATA16            0x1d0 0x4d8 0x7b8 0x0 0x1
+#define MX6SL_PAD_LCD_DAT16__KEY_COL4              0x1d0 0x4d8 0x744 0x1 0x1
+#define MX6SL_PAD_LCD_DAT16__CSI_DATA01            0x1d0 0x4d8 0x634 0x2 0x1
+#define MX6SL_PAD_LCD_DAT16__EIM_DATA10            0x1d0 0x4d8 0x000 0x3 0x0
+#define MX6SL_PAD_LCD_DAT16__I2C2_SCL              0x1d0 0x4d8 0x724 0x4 0x3
+#define MX6SL_PAD_LCD_DAT16__GPIO3_IO04            0x1d0 0x4d8 0x000 0x5 0x0
+#define MX6SL_PAD_LCD_DAT16__ARM_TRACE16           0x1d0 0x4d8 0x000 0x6 0x0
+#define MX6SL_PAD_LCD_DAT16__SRC_BOOT_CFG24        0x1d0 0x4d8 0x000 0x7 0x0
+#define MX6SL_PAD_LCD_DAT17__LCD_DATA17            0x1d4 0x4dc 0x7bc 0x0 0x1
+#define MX6SL_PAD_LCD_DAT17__KEY_ROW4              0x1d4 0x4dc 0x764 0x1 0x1
+#define MX6SL_PAD_LCD_DAT17__CSI_DATA00            0x1d4 0x4dc 0x630 0x2 0x1
+#define MX6SL_PAD_LCD_DAT17__EIM_DATA11            0x1d4 0x4dc 0x000 0x3 0x0
+#define MX6SL_PAD_LCD_DAT17__I2C2_SDA              0x1d4 0x4dc 0x728 0x4 0x3
+#define MX6SL_PAD_LCD_DAT17__GPIO3_IO05            0x1d4 0x4dc 0x000 0x5 0x0
+#define MX6SL_PAD_LCD_DAT17__ARM_TRACE17           0x1d4 0x4dc 0x000 0x6 0x0
+#define MX6SL_PAD_LCD_DAT17__SRC_BOOT_CFG25        0x1d4 0x4dc 0x000 0x7 0x0
+#define MX6SL_PAD_LCD_DAT18__LCD_DATA18            0x1d8 0x4e0 0x7c0 0x0 0x1
+#define MX6SL_PAD_LCD_DAT18__KEY_COL5              0x1d8 0x4e0 0x748 0x1 0x1
+#define MX6SL_PAD_LCD_DAT18__CSI_DATA15            0x1d8 0x4e0 0x66c 0x2 0x0
+#define MX6SL_PAD_LCD_DAT18__EIM_DATA12            0x1d8 0x4e0 0x000 0x3 0x0
+#define MX6SL_PAD_LCD_DAT18__GPT_CAPTURE1          0x1d8 0x4e0 0x710 0x4 0x1
+#define MX6SL_PAD_LCD_DAT18__GPIO3_IO06            0x1d8 0x4e0 0x000 0x5 0x0
+#define MX6SL_PAD_LCD_DAT18__ARM_TRACE18           0x1d8 0x4e0 0x000 0x6 0x0
+#define MX6SL_PAD_LCD_DAT18__SRC_BOOT_CFG26        0x1d8 0x4e0 0x000 0x7 0x0
+#define MX6SL_PAD_LCD_DAT19__LCD_DATA19            0x1dc 0x4e4 0x7c4 0x0 0x1
+#define MX6SL_PAD_LCD_DAT19__KEY_ROW5              0x1dc 0x4e4 0x768 0x1 0x1
+#define MX6SL_PAD_LCD_DAT19__CSI_DATA14            0x1dc 0x4e4 0x668 0x2 0x0
+#define MX6SL_PAD_LCD_DAT19__EIM_DATA13            0x1dc 0x4e4 0x000 0x3 0x0
+#define MX6SL_PAD_LCD_DAT19__GPT_CAPTURE2          0x1dc 0x4e4 0x714 0x4 0x1
+#define MX6SL_PAD_LCD_DAT19__GPIO3_IO07            0x1dc 0x4e4 0x000 0x5 0x0
+#define MX6SL_PAD_LCD_DAT19__ARM_TRACE19           0x1dc 0x4e4 0x000 0x6 0x0
+#define MX6SL_PAD_LCD_DAT19__SRC_BOOT_CFG27        0x1dc 0x4e4 0x000 0x7 0x0
+#define MX6SL_PAD_LCD_DAT2__LCD_DATA02             0x1e0 0x4e8 0x780 0x0 0x1
+#define MX6SL_PAD_LCD_DAT2__ECSPI1_SS0             0x1e0 0x4e8 0x68c 0x1 0x1
+#define MX6SL_PAD_LCD_DAT2__EPIT2_OUT              0x1e0 0x4e8 0x000 0x2 0x0
+#define MX6SL_PAD_LCD_DAT2__PWM3_OUT               0x1e0 0x4e8 0x000 0x3 0x0
+#define MX6SL_PAD_LCD_DAT2__AUD4_RXC               0x1e0 0x4e8 0x5ec 0x4 0x1
+#define MX6SL_PAD_LCD_DAT2__GPIO2_IO22             0x1e0 0x4e8 0x000 0x5 0x0
+#define MX6SL_PAD_LCD_DAT2__ARM_TRACE02            0x1e0 0x4e8 0x000 0x6 0x0
+#define MX6SL_PAD_LCD_DAT2__SRC_BOOT_CFG02         0x1e0 0x4e8 0x000 0x7 0x0
+#define MX6SL_PAD_LCD_DAT20__LCD_DATA20            0x1e4 0x4ec 0x7c8 0x0 0x1
+#define MX6SL_PAD_LCD_DAT20__KEY_COL6              0x1e4 0x4ec 0x74c 0x1 0x1
+#define MX6SL_PAD_LCD_DAT20__CSI_DATA13            0x1e4 0x4ec 0x664 0x2 0x0
+#define MX6SL_PAD_LCD_DAT20__EIM_DATA14            0x1e4 0x4ec 0x000 0x3 0x0
+#define MX6SL_PAD_LCD_DAT20__GPT_COMPARE1          0x1e4 0x4ec 0x000 0x4 0x0
+#define MX6SL_PAD_LCD_DAT20__GPIO3_IO08            0x1e4 0x4ec 0x000 0x5 0x0
+#define MX6SL_PAD_LCD_DAT20__ARM_TRACE20           0x1e4 0x4ec 0x000 0x6 0x0
+#define MX6SL_PAD_LCD_DAT20__SRC_BOOT_CFG28        0x1e4 0x4ec 0x000 0x7 0x0
+#define MX6SL_PAD_LCD_DAT21__LCD_DATA21            0x1e8 0x4f0 0x7cc 0x0 0x1
+#define MX6SL_PAD_LCD_DAT21__KEY_ROW6              0x1e8 0x4f0 0x76c 0x1 0x1
+#define MX6SL_PAD_LCD_DAT21__CSI_DATA12            0x1e8 0x4f0 0x660 0x2 0x0
+#define MX6SL_PAD_LCD_DAT21__EIM_DATA15            0x1e8 0x4f0 0x000 0x3 0x0
+#define MX6SL_PAD_LCD_DAT21__GPT_COMPARE2          0x1e8 0x4f0 0x000 0x4 0x0
+#define MX6SL_PAD_LCD_DAT21__GPIO3_IO09            0x1e8 0x4f0 0x000 0x5 0x0
+#define MX6SL_PAD_LCD_DAT21__ARM_TRACE21           0x1e8 0x4f0 0x000 0x6 0x0
+#define MX6SL_PAD_LCD_DAT21__SRC_BOOT_CFG29        0x1e8 0x4f0 0x000 0x7 0x0
+#define MX6SL_PAD_LCD_DAT22__LCD_DATA22            0x1ec 0x4f4 0x7d0 0x0 0x1
+#define MX6SL_PAD_LCD_DAT22__KEY_COL7              0x1ec 0x4f4 0x750 0x1 0x1
+#define MX6SL_PAD_LCD_DAT22__CSI_DATA11            0x1ec 0x4f4 0x65c 0x2 0x1
+#define MX6SL_PAD_LCD_DAT22__EIM_EB3_B             0x1ec 0x4f4 0x000 0x3 0x0
+#define MX6SL_PAD_LCD_DAT22__GPT_COMPARE3          0x1ec 0x4f4 0x000 0x4 0x0
+#define MX6SL_PAD_LCD_DAT22__GPIO3_IO10            0x1ec 0x4f4 0x000 0x5 0x0
+#define MX6SL_PAD_LCD_DAT22__ARM_TRACE22           0x1ec 0x4f4 0x000 0x6 0x0
+#define MX6SL_PAD_LCD_DAT22__SRC_BOOT_CFG30        0x1ec 0x4f4 0x000 0x7 0x0
+#define MX6SL_PAD_LCD_DAT23__LCD_DATA23            0x1f0 0x4f8 0x7d4 0x0 0x1
+#define MX6SL_PAD_LCD_DAT23__KEY_ROW7              0x1f0 0x4f8 0x770 0x1 0x1
+#define MX6SL_PAD_LCD_DAT23__CSI_DATA10            0x1f0 0x4f8 0x658 0x2 0x1
+#define MX6SL_PAD_LCD_DAT23__EIM_EB2_B             0x1f0 0x4f8 0x000 0x3 0x0
+#define MX6SL_PAD_LCD_DAT23__GPT_CLKIN             0x1f0 0x4f8 0x718 0x4 0x1
+#define MX6SL_PAD_LCD_DAT23__GPIO3_IO11            0x1f0 0x4f8 0x000 0x5 0x0
+#define MX6SL_PAD_LCD_DAT23__ARM_TRACE23           0x1f0 0x4f8 0x000 0x6 0x0
+#define MX6SL_PAD_LCD_DAT23__SRC_BOOT_CFG31        0x1f0 0x4f8 0x000 0x7 0x0
+#define MX6SL_PAD_LCD_DAT3__LCD_DATA03             0x1f4 0x4fc 0x784 0x0 0x1
+#define MX6SL_PAD_LCD_DAT3__ECSPI1_SCLK            0x1f4 0x4fc 0x67c 0x1 0x1
+#define MX6SL_PAD_LCD_DAT3__UART5_DSR_B            0x1f4 0x4fc 0x000 0x2 0x0
+#define MX6SL_PAD_LCD_DAT3__PWM4_OUT               0x1f4 0x4fc 0x000 0x3 0x0
+#define MX6SL_PAD_LCD_DAT3__AUD4_RXD               0x1f4 0x4fc 0x5e4 0x4 0x1
+#define MX6SL_PAD_LCD_DAT3__GPIO2_IO23             0x1f4 0x4fc 0x000 0x5 0x0
+#define MX6SL_PAD_LCD_DAT3__ARM_TRACE03            0x1f4 0x4fc 0x000 0x6 0x0
+#define MX6SL_PAD_LCD_DAT3__SRC_BOOT_CFG03         0x1f4 0x4fc 0x000 0x7 0x0
+#define MX6SL_PAD_LCD_DAT4__LCD_DATA04             0x1f8 0x500 0x788 0x0 0x1
+#define MX6SL_PAD_LCD_DAT4__ECSPI1_SS1             0x1f8 0x500 0x690 0x1 0x1
+#define MX6SL_PAD_LCD_DAT4__CSI_VSYNC              0x1f8 0x500 0x678 0x2 0x2
+#define MX6SL_PAD_LCD_DAT4__WDOG2_RESET_B_DEB      0x1f8 0x500 0x000 0x3 0x0
+#define MX6SL_PAD_LCD_DAT4__AUD4_TXC               0x1f8 0x500 0x5f4 0x4 0x1
+#define MX6SL_PAD_LCD_DAT4__GPIO2_IO24             0x1f8 0x500 0x000 0x5 0x0
+#define MX6SL_PAD_LCD_DAT4__ARM_TRACE04            0x1f8 0x500 0x000 0x6 0x0
+#define MX6SL_PAD_LCD_DAT4__SRC_BOOT_CFG04         0x1f8 0x500 0x000 0x7 0x0
+#define MX6SL_PAD_LCD_DAT5__LCD_DATA05             0x1fc 0x504 0x78c 0x0 0x1
+#define MX6SL_PAD_LCD_DAT5__ECSPI1_SS2             0x1fc 0x504 0x694 0x1 0x1
+#define MX6SL_PAD_LCD_DAT5__CSI_HSYNC              0x1fc 0x504 0x670 0x2 0x2
+#define MX6SL_PAD_LCD_DAT5__EIM_CS3_B              0x1fc 0x504 0x000 0x3 0x0
+#define MX6SL_PAD_LCD_DAT5__AUD4_TXFS              0x1fc 0x504 0x5f8 0x4 0x1
+#define MX6SL_PAD_LCD_DAT5__GPIO2_IO25             0x1fc 0x504 0x000 0x5 0x0
+#define MX6SL_PAD_LCD_DAT5__ARM_TRACE05            0x1fc 0x504 0x000 0x6 0x0
+#define MX6SL_PAD_LCD_DAT5__SRC_BOOT_CFG05         0x1fc 0x504 0x000 0x7 0x0
+#define MX6SL_PAD_LCD_DAT6__LCD_DATA06             0x200 0x508 0x790 0x0 0x1
+#define MX6SL_PAD_LCD_DAT6__ECSPI1_SS3             0x200 0x508 0x698 0x1 0x1
+#define MX6SL_PAD_LCD_DAT6__CSI_PIXCLK             0x200 0x508 0x674 0x2 0x2
+#define MX6SL_PAD_LCD_DAT6__EIM_DATA00             0x200 0x508 0x000 0x3 0x0
+#define MX6SL_PAD_LCD_DAT6__AUD4_TXD               0x200 0x508 0x5e8 0x4 0x1
+#define MX6SL_PAD_LCD_DAT6__GPIO2_IO26             0x200 0x508 0x000 0x5 0x0
+#define MX6SL_PAD_LCD_DAT6__ARM_TRACE06            0x200 0x508 0x000 0x6 0x0
+#define MX6SL_PAD_LCD_DAT6__SRC_BOOT_CFG06         0x200 0x508 0x000 0x7 0x0
+#define MX6SL_PAD_LCD_DAT7__LCD_DATA07             0x204 0x50c 0x794 0x0 0x1
+#define MX6SL_PAD_LCD_DAT7__ECSPI1_RDY             0x204 0x50c 0x680 0x1 0x1
+#define MX6SL_PAD_LCD_DAT7__CSI_MCLK               0x204 0x50c 0x000 0x2 0x0
+#define MX6SL_PAD_LCD_DAT7__EIM_DATA01             0x204 0x50c 0x000 0x3 0x0
+#define MX6SL_PAD_LCD_DAT7__AUDIO_CLK_OUT          0x204 0x50c 0x000 0x4 0x0
+#define MX6SL_PAD_LCD_DAT7__GPIO2_IO27             0x204 0x50c 0x000 0x5 0x0
+#define MX6SL_PAD_LCD_DAT7__ARM_TRACE07            0x204 0x50c 0x000 0x6 0x0
+#define MX6SL_PAD_LCD_DAT7__SRC_BOOT_CFG07         0x204 0x50c 0x000 0x7 0x0
+#define MX6SL_PAD_LCD_DAT8__LCD_DATA08             0x208 0x510 0x798 0x0 0x1
+#define MX6SL_PAD_LCD_DAT8__KEY_COL0               0x208 0x510 0x734 0x1 0x1
+#define MX6SL_PAD_LCD_DAT8__CSI_DATA09             0x208 0x510 0x654 0x2 0x1
+#define MX6SL_PAD_LCD_DAT8__EIM_DATA02             0x208 0x510 0x000 0x3 0x0
+#define MX6SL_PAD_LCD_DAT8__ECSPI2_SCLK            0x208 0x510 0x69c 0x4 0x2
+#define MX6SL_PAD_LCD_DAT8__GPIO2_IO28             0x208 0x510 0x000 0x5 0x0
+#define MX6SL_PAD_LCD_DAT8__ARM_TRACE08            0x208 0x510 0x000 0x6 0x0
+#define MX6SL_PAD_LCD_DAT8__SRC_BOOT_CFG08         0x208 0x510 0x000 0x7 0x0
+#define MX6SL_PAD_LCD_DAT9__LCD_DATA09             0x20c 0x514 0x79c 0x0 0x1
+#define MX6SL_PAD_LCD_DAT9__KEY_ROW0               0x20c 0x514 0x754 0x1 0x1
+#define MX6SL_PAD_LCD_DAT9__CSI_DATA08             0x20c 0x514 0x650 0x2 0x1
+#define MX6SL_PAD_LCD_DAT9__EIM_DATA03             0x20c 0x514 0x000 0x3 0x0
+#define MX6SL_PAD_LCD_DAT9__ECSPI2_MOSI            0x20c 0x514 0x6a4 0x4 0x2
+#define MX6SL_PAD_LCD_DAT9__GPIO2_IO29             0x20c 0x514 0x000 0x5 0x0
+#define MX6SL_PAD_LCD_DAT9__ARM_TRACE09            0x20c 0x514 0x000 0x6 0x0
+#define MX6SL_PAD_LCD_DAT9__SRC_BOOT_CFG09         0x20c 0x514 0x000 0x7 0x0
+#define MX6SL_PAD_LCD_ENABLE__LCD_ENABLE           0x210 0x518 0x000 0x0 0x0
+#define MX6SL_PAD_LCD_ENABLE__SD4_DATA5            0x210 0x518 0x870 0x1 0x2
+#define MX6SL_PAD_LCD_ENABLE__LCD_RD_E             0x210 0x518 0x000 0x2 0x0
+#define MX6SL_PAD_LCD_ENABLE__EIM_OE_B             0x210 0x518 0x000 0x3 0x0
+#define MX6SL_PAD_LCD_ENABLE__UART2_RX_DATA        0x210 0x518 0x804 0x4 0x2
+#define MX6SL_PAD_LCD_ENABLE__UART2_TX_DATA        0x210 0x518 0x000 0x4 0x0
+#define MX6SL_PAD_LCD_ENABLE__GPIO2_IO16           0x210 0x518 0x000 0x5 0x0
+#define MX6SL_PAD_LCD_HSYNC__LCD_HSYNC             0x214 0x51c 0x774 0x0 0x0
+#define MX6SL_PAD_LCD_HSYNC__SD4_DATA6             0x214 0x51c 0x874 0x1 0x2
+#define MX6SL_PAD_LCD_HSYNC__LCD_CS                0x214 0x51c 0x000 0x2 0x0
+#define MX6SL_PAD_LCD_HSYNC__EIM_CS0_B             0x214 0x51c 0x000 0x3 0x0
+#define MX6SL_PAD_LCD_HSYNC__UART2_TX_DATA         0x214 0x51c 0x000 0x4 0x0
+#define MX6SL_PAD_LCD_HSYNC__UART2_RX_DATA         0x214 0x51c 0x804 0x4 0x3
+#define MX6SL_PAD_LCD_HSYNC__GPIO2_IO17            0x214 0x51c 0x000 0x5 0x0
+#define MX6SL_PAD_LCD_HSYNC__ARM_TRACE_CLK         0x214 0x51c 0x000 0x6 0x0
+#define MX6SL_PAD_LCD_RESET__LCD_RESET             0x218 0x520 0x000 0x0 0x0
+#define MX6SL_PAD_LCD_RESET__EIM_DTACK_B           0x218 0x520 0x880 0x1 0x1
+#define MX6SL_PAD_LCD_RESET__LCD_BUSY              0x218 0x520 0x774 0x2 0x1
+#define MX6SL_PAD_LCD_RESET__EIM_WAIT_B            0x218 0x520 0x884 0x3 0x1
+#define MX6SL_PAD_LCD_RESET__UART2_CTS_B           0x218 0x520 0x000 0x4 0x0
+#define MX6SL_PAD_LCD_RESET__UART2_RTS_B           0x218 0x520 0x800 0x4 0x2
+#define MX6SL_PAD_LCD_RESET__GPIO2_IO19            0x218 0x520 0x000 0x5 0x0
+#define MX6SL_PAD_LCD_RESET__CCM_PMIC_READY        0x218 0x520 0x62c 0x6 0x1
+#define MX6SL_PAD_LCD_VSYNC__LCD_VSYNC             0x21c 0x524 0x000 0x0 0x0
+#define MX6SL_PAD_LCD_VSYNC__SD4_DATA7             0x21c 0x524 0x878 0x1 0x2
+#define MX6SL_PAD_LCD_VSYNC__LCD_RS                0x21c 0x524 0x000 0x2 0x0
+#define MX6SL_PAD_LCD_VSYNC__EIM_CS1_B             0x21c 0x524 0x000 0x3 0x0
+#define MX6SL_PAD_LCD_VSYNC__UART2_RTS_B           0x21c 0x524 0x800 0x4 0x3
+#define MX6SL_PAD_LCD_VSYNC__UART2_CTS_B           0x21c 0x524 0x000 0x4 0x0
+#define MX6SL_PAD_LCD_VSYNC__GPIO2_IO18            0x21c 0x524 0x000 0x5 0x0
+#define MX6SL_PAD_LCD_VSYNC__ARM_TRACE_CTL         0x21c 0x524 0x000 0x6 0x0
+#define MX6SL_PAD_PWM1__PWM1_OUT                   0x220 0x528 0x000 0x0 0x0
+#define MX6SL_PAD_PWM1__CCM_CLKO                   0x220 0x528 0x000 0x1 0x0
+#define MX6SL_PAD_PWM1__AUDIO_CLK_OUT              0x220 0x528 0x000 0x2 0x0
+#define MX6SL_PAD_PWM1__FEC_REF_OUT                0x220 0x528 0x000 0x3 0x0
+#define MX6SL_PAD_PWM1__CSI_MCLK                   0x220 0x528 0x000 0x4 0x0
+#define MX6SL_PAD_PWM1__GPIO3_IO23                 0x220 0x528 0x000 0x5 0x0
+#define MX6SL_PAD_PWM1__EPIT1_OUT                  0x220 0x528 0x000 0x6 0x0
+#define MX6SL_PAD_REF_CLK_24M__XTALOSC_REF_CLK_24M 0x224 0x52c 0x000 0x0 0x0
+#define MX6SL_PAD_REF_CLK_24M__I2C3_SCL            0x224 0x52c 0x72c 0x1 0x2
+#define MX6SL_PAD_REF_CLK_24M__PWM3_OUT            0x224 0x52c 0x000 0x2 0x0
+#define MX6SL_PAD_REF_CLK_24M__USB_OTG2_ID         0x224 0x52c 0x5e0 0x3 0x2
+#define MX6SL_PAD_REF_CLK_24M__CCM_PMIC_READY      0x224 0x52c 0x62c 0x4 0x2
+#define MX6SL_PAD_REF_CLK_24M__GPIO3_IO21          0x224 0x52c 0x000 0x5 0x0
+#define MX6SL_PAD_REF_CLK_24M__SD3_WP              0x224 0x52c 0x84c 0x6 0x3
+#define MX6SL_PAD_REF_CLK_32K__XTALOSC_REF_CLK_32K 0x228 0x530 0x000 0x0 0x0
+#define MX6SL_PAD_REF_CLK_32K__I2C3_SDA            0x228 0x530 0x730 0x1 0x2
+#define MX6SL_PAD_REF_CLK_32K__PWM4_OUT            0x228 0x530 0x000 0x2 0x0
+#define MX6SL_PAD_REF_CLK_32K__USB_OTG1_ID         0x228 0x530 0x5dc 0x3 0x3
+#define MX6SL_PAD_REF_CLK_32K__SD1_LCTL            0x228 0x530 0x000 0x4 0x0
+#define MX6SL_PAD_REF_CLK_32K__GPIO3_IO22          0x228 0x530 0x000 0x5 0x0
+#define MX6SL_PAD_REF_CLK_32K__SD3_CD_B            0x228 0x530 0x838 0x6 0x3
+#define MX6SL_PAD_SD1_CLK__SD1_CLK                 0x22c 0x534 0x000 0x0 0x0
+#define MX6SL_PAD_SD1_CLK__FEC_MDIO                0x22c 0x534 0x6f4 0x1 0x2
+#define MX6SL_PAD_SD1_CLK__KEY_COL0                0x22c 0x534 0x734 0x2 0x2
+#define MX6SL_PAD_SD1_CLK__EPDC_SDCE4              0x22c 0x534 0x000 0x3 0x0
+#define MX6SL_PAD_SD1_CLK__GPIO5_IO15              0x22c 0x534 0x000 0x5 0x0
+#define MX6SL_PAD_SD1_CMD__SD1_CMD                 0x230 0x538 0x000 0x0 0x0
+#define MX6SL_PAD_SD1_CMD__FEC_TX_CLK              0x230 0x538 0x70c 0x1 0x2
+#define MX6SL_PAD_SD1_CMD__KEY_ROW0                0x230 0x538 0x754 0x2 0x2
+#define MX6SL_PAD_SD1_CMD__EPDC_SDCE5              0x230 0x538 0x000 0x3 0x0
+#define MX6SL_PAD_SD1_CMD__GPIO5_IO14              0x230 0x538 0x000 0x5 0x0
+#define MX6SL_PAD_SD1_DAT0__SD1_DATA0              0x234 0x53c 0x000 0x0 0x0
+#define MX6SL_PAD_SD1_DAT0__FEC_RX_ER              0x234 0x53c 0x708 0x1 0x2
+#define MX6SL_PAD_SD1_DAT0__KEY_COL1               0x234 0x53c 0x738 0x2 0x2
+#define MX6SL_PAD_SD1_DAT0__EPDC_SDCE6             0x234 0x53c 0x000 0x3 0x0
+#define MX6SL_PAD_SD1_DAT0__GPIO5_IO11             0x234 0x53c 0x000 0x5 0x0
+#define MX6SL_PAD_SD1_DAT1__SD1_DATA1              0x238 0x540 0x000 0x0 0x0
+#define MX6SL_PAD_SD1_DAT1__FEC_RX_DV              0x238 0x540 0x704 0x1 0x2
+#define MX6SL_PAD_SD1_DAT1__KEY_ROW1               0x238 0x540 0x758 0x2 0x2
+#define MX6SL_PAD_SD1_DAT1__EPDC_SDCE7             0x238 0x540 0x000 0x3 0x0
+#define MX6SL_PAD_SD1_DAT1__GPIO5_IO08             0x238 0x540 0x000 0x5 0x0
+#define MX6SL_PAD_SD1_DAT2__SD1_DATA2              0x23c 0x544 0x000 0x0 0x0
+#define MX6SL_PAD_SD1_DAT2__FEC_RX_DATA1           0x23c 0x544 0x6fc 0x1 0x2
+#define MX6SL_PAD_SD1_DAT2__KEY_COL2               0x23c 0x544 0x73c 0x2 0x2
+#define MX6SL_PAD_SD1_DAT2__EPDC_SDCE8             0x23c 0x544 0x000 0x3 0x0
+#define MX6SL_PAD_SD1_DAT2__GPIO5_IO13             0x23c 0x544 0x000 0x5 0x0
+#define MX6SL_PAD_SD1_DAT3__SD1_DATA3              0x240 0x548 0x000 0x0 0x0
+#define MX6SL_PAD_SD1_DAT3__FEC_TX_DATA0           0x240 0x548 0x000 0x1 0x0
+#define MX6SL_PAD_SD1_DAT3__KEY_ROW2               0x240 0x548 0x75c 0x2 0x2
+#define MX6SL_PAD_SD1_DAT3__EPDC_SDCE9             0x240 0x548 0x000 0x3 0x0
+#define MX6SL_PAD_SD1_DAT3__GPIO5_IO06             0x240 0x548 0x000 0x5 0x0
+#define MX6SL_PAD_SD1_DAT4__SD1_DATA4              0x244 0x54c 0x000 0x0 0x0
+#define MX6SL_PAD_SD1_DAT4__FEC_MDC                0x244 0x54c 0x000 0x1 0x0
+#define MX6SL_PAD_SD1_DAT4__KEY_COL3               0x244 0x54c 0x740 0x2 0x2
+#define MX6SL_PAD_SD1_DAT4__EPDC_SDCLK_N           0x244 0x54c 0x000 0x3 0x0
+#define MX6SL_PAD_SD1_DAT4__UART4_RX_DATA          0x244 0x54c 0x814 0x4 0x4
+#define MX6SL_PAD_SD1_DAT4__UART4_TX_DATA          0x244 0x54c 0x000 0x4 0x0
+#define MX6SL_PAD_SD1_DAT4__GPIO5_IO12             0x244 0x54c 0x000 0x5 0x0
+#define MX6SL_PAD_SD1_DAT5__SD1_DATA5              0x248 0x550 0x000 0x0 0x0
+#define MX6SL_PAD_SD1_DAT5__FEC_RX_DATA0           0x248 0x550 0x6f8 0x1 0x2
+#define MX6SL_PAD_SD1_DAT5__KEY_ROW3               0x248 0x550 0x760 0x2 0x2
+#define MX6SL_PAD_SD1_DAT5__EPDC_SDOED             0x248 0x550 0x000 0x3 0x0
+#define MX6SL_PAD_SD1_DAT5__UART4_TX_DATA          0x248 0x550 0x000 0x4 0x0
+#define MX6SL_PAD_SD1_DAT5__UART4_RX_DATA          0x248 0x550 0x814 0x4 0x5
+#define MX6SL_PAD_SD1_DAT5__GPIO5_IO09             0x248 0x550 0x000 0x5 0x0
+#define MX6SL_PAD_SD1_DAT6__SD1_DATA6              0x24c 0x554 0x000 0x0 0x0
+#define MX6SL_PAD_SD1_DAT6__FEC_TX_EN              0x24c 0x554 0x000 0x1 0x0
+#define MX6SL_PAD_SD1_DAT6__KEY_COL4               0x24c 0x554 0x744 0x2 0x2
+#define MX6SL_PAD_SD1_DAT6__EPDC_SDOEZ             0x24c 0x554 0x000 0x3 0x0
+#define MX6SL_PAD_SD1_DAT6__UART4_RTS_B            0x24c 0x554 0x810 0x4 0x4
+#define MX6SL_PAD_SD1_DAT6__UART4_CTS_B            0x24c 0x554 0x000 0x4 0x0
+#define MX6SL_PAD_SD1_DAT6__GPIO5_IO07             0x24c 0x554 0x000 0x5 0x0
+#define MX6SL_PAD_SD1_DAT7__SD1_DATA7              0x250 0x558 0x000 0x0 0x0
+#define MX6SL_PAD_SD1_DAT7__FEC_TX_DATA1           0x250 0x558 0x000 0x1 0x0
+#define MX6SL_PAD_SD1_DAT7__KEY_ROW4               0x250 0x558 0x764 0x2 0x2
+#define MX6SL_PAD_SD1_DAT7__CCM_PMIC_READY         0x250 0x558 0x62c 0x3 0x3
+#define MX6SL_PAD_SD1_DAT7__UART4_CTS_B            0x250 0x558 0x000 0x4 0x0
+#define MX6SL_PAD_SD1_DAT7__UART4_RTS_B            0x250 0x558 0x810 0x4 0x5
+#define MX6SL_PAD_SD1_DAT7__GPIO5_IO10             0x250 0x558 0x000 0x5 0x0
+#define MX6SL_PAD_SD2_CLK__SD2_CLK                 0x254 0x55c 0x000 0x0 0x0
+#define MX6SL_PAD_SD2_CLK__AUD4_RXFS               0x254 0x55c 0x5f0 0x1 0x2
+#define MX6SL_PAD_SD2_CLK__ECSPI3_SCLK             0x254 0x55c 0x6b0 0x2 0x2
+#define MX6SL_PAD_SD2_CLK__CSI_DATA00              0x254 0x55c 0x630 0x3 0x2
+#define MX6SL_PAD_SD2_CLK__GPIO5_IO05              0x254 0x55c 0x000 0x5 0x0
+#define MX6SL_PAD_SD2_CMD__SD2_CMD                 0x258 0x560 0x000 0x0 0x0
+#define MX6SL_PAD_SD2_CMD__AUD4_RXC                0x258 0x560 0x5ec 0x1 0x2
+#define MX6SL_PAD_SD2_CMD__ECSPI3_SS0              0x258 0x560 0x6c0 0x2 0x2
+#define MX6SL_PAD_SD2_CMD__CSI_DATA01              0x258 0x560 0x634 0x3 0x2
+#define MX6SL_PAD_SD2_CMD__EPIT1_OUT               0x258 0x560 0x000 0x4 0x0
+#define MX6SL_PAD_SD2_CMD__GPIO5_IO04              0x258 0x560 0x000 0x5 0x0
+#define MX6SL_PAD_SD2_DAT0__SD2_DATA0              0x25c 0x564 0x000 0x0 0x0
+#define MX6SL_PAD_SD2_DAT0__AUD4_RXD               0x25c 0x564 0x5e4 0x1 0x2
+#define MX6SL_PAD_SD2_DAT0__ECSPI3_MOSI            0x25c 0x564 0x6bc 0x2 0x2
+#define MX6SL_PAD_SD2_DAT0__CSI_DATA02             0x25c 0x564 0x638 0x3 0x2
+#define MX6SL_PAD_SD2_DAT0__UART5_RTS_B            0x25c 0x564 0x818 0x4 0x4
+#define MX6SL_PAD_SD2_DAT0__UART5_CTS_B            0x25c 0x564 0x000 0x4 0x0
+#define MX6SL_PAD_SD2_DAT0__GPIO5_IO01             0x25c 0x564 0x000 0x5 0x0
+#define MX6SL_PAD_SD2_DAT1__SD2_DATA1              0x260 0x568 0x000 0x0 0x0
+#define MX6SL_PAD_SD2_DAT1__AUD4_TXC               0x260 0x568 0x5f4 0x1 0x2
+#define MX6SL_PAD_SD2_DAT1__ECSPI3_MISO            0x260 0x568 0x6b8 0x2 0x2
+#define MX6SL_PAD_SD2_DAT1__CSI_DATA03             0x260 0x568 0x63c 0x3 0x2
+#define MX6SL_PAD_SD2_DAT1__UART5_CTS_B            0x260 0x568 0x000 0x4 0x0
+#define MX6SL_PAD_SD2_DAT1__UART5_RTS_B            0x260 0x568 0x818 0x4 0x5
+#define MX6SL_PAD_SD2_DAT1__GPIO4_IO30             0x260 0x568 0x000 0x5 0x0
+#define MX6SL_PAD_SD2_DAT2__SD2_DATA2              0x264 0x56c 0x000 0x0 0x0
+#define MX6SL_PAD_SD2_DAT2__AUD4_TXFS              0x264 0x56c 0x5f8 0x1 0x2
+#define MX6SL_PAD_SD2_DAT2__FEC_COL                0x264 0x56c 0x6f0 0x2 0x1
+#define MX6SL_PAD_SD2_DAT2__CSI_DATA04             0x264 0x56c 0x640 0x3 0x2
+#define MX6SL_PAD_SD2_DAT2__UART5_RX_DATA          0x264 0x56c 0x81c 0x4 0x4
+#define MX6SL_PAD_SD2_DAT2__UART5_TX_DATA          0x264 0x56c 0x000 0x4 0x0
+#define MX6SL_PAD_SD2_DAT2__GPIO5_IO03             0x264 0x56c 0x000 0x5 0x0
+#define MX6SL_PAD_SD2_DAT3__SD2_DATA3              0x268 0x570 0x000 0x0 0x0
+#define MX6SL_PAD_SD2_DAT3__AUD4_TXD               0x268 0x570 0x5e8 0x1 0x2
+#define MX6SL_PAD_SD2_DAT3__FEC_RX_CLK             0x268 0x570 0x700 0x2 0x1
+#define MX6SL_PAD_SD2_DAT3__CSI_DATA05             0x268 0x570 0x644 0x3 0x2
+#define MX6SL_PAD_SD2_DAT3__UART5_TX_DATA          0x268 0x570 0x000 0x4 0x0
+#define MX6SL_PAD_SD2_DAT3__UART5_RX_DATA          0x268 0x570 0x81c 0x4 0x5
+#define MX6SL_PAD_SD2_DAT3__GPIO4_IO28             0x268 0x570 0x000 0x5 0x0
+#define MX6SL_PAD_SD2_DAT4__SD2_DATA4              0x26c 0x574 0x000 0x0 0x0
+#define MX6SL_PAD_SD2_DAT4__SD3_DATA4              0x26c 0x574 0x83c 0x1 0x1
+#define MX6SL_PAD_SD2_DAT4__UART2_RX_DATA          0x26c 0x574 0x804 0x2 0x4
+#define MX6SL_PAD_SD2_DAT4__UART2_TX_DATA          0x26c 0x574 0x000 0x2 0x0
+#define MX6SL_PAD_SD2_DAT4__CSI_DATA06             0x26c 0x574 0x648 0x3 0x2
+#define MX6SL_PAD_SD2_DAT4__SPDIF_OUT              0x26c 0x574 0x000 0x4 0x0
+#define MX6SL_PAD_SD2_DAT4__GPIO5_IO02             0x26c 0x574 0x000 0x5 0x0
+#define MX6SL_PAD_SD2_DAT5__SD2_DATA5              0x270 0x578 0x000 0x0 0x0
+#define MX6SL_PAD_SD2_DAT5__SD3_DATA5              0x270 0x578 0x840 0x1 0x1
+#define MX6SL_PAD_SD2_DAT5__UART2_TX_DATA          0x270 0x578 0x000 0x2 0x0
+#define MX6SL_PAD_SD2_DAT5__UART2_RX_DATA          0x270 0x578 0x804 0x2 0x5
+#define MX6SL_PAD_SD2_DAT5__CSI_DATA07             0x270 0x578 0x64c 0x3 0x2
+#define MX6SL_PAD_SD2_DAT5__SPDIF_IN               0x270 0x578 0x7f0 0x4 0x2
+#define MX6SL_PAD_SD2_DAT5__GPIO4_IO31             0x270 0x578 0x000 0x5 0x0
+#define MX6SL_PAD_SD2_DAT6__SD2_DATA6              0x274 0x57c 0x000 0x0 0x0
+#define MX6SL_PAD_SD2_DAT6__SD3_DATA6              0x274 0x57c 0x844 0x1 0x1
+#define MX6SL_PAD_SD2_DAT6__UART2_RTS_B            0x274 0x57c 0x800 0x2 0x4
+#define MX6SL_PAD_SD2_DAT6__UART2_CTS_B            0x274 0x57c 0x000 0x2 0x0
+#define MX6SL_PAD_SD2_DAT6__CSI_DATA08             0x274 0x57c 0x650 0x3 0x2
+#define MX6SL_PAD_SD2_DAT6__SD2_WP                 0x274 0x57c 0x834 0x4 0x2
+#define MX6SL_PAD_SD2_DAT6__GPIO4_IO29             0x274 0x57c 0x000 0x5 0x0
+#define MX6SL_PAD_SD2_DAT7__SD2_DATA7              0x278 0x580 0x000 0x0 0x0
+#define MX6SL_PAD_SD2_DAT7__SD3_DATA7              0x278 0x580 0x848 0x1 0x1
+#define MX6SL_PAD_SD2_DAT7__UART2_CTS_B            0x278 0x580 0x000 0x2 0x0
+#define MX6SL_PAD_SD2_DAT7__UART2_RTS_B            0x278 0x580 0x800 0x2 0x5
+#define MX6SL_PAD_SD2_DAT7__CSI_DATA09             0x278 0x580 0x654 0x3 0x2
+#define MX6SL_PAD_SD2_DAT7__SD2_CD_B               0x278 0x580 0x830 0x4 0x2
+#define MX6SL_PAD_SD2_DAT7__GPIO5_IO00             0x278 0x580 0x000 0x5 0x0
+#define MX6SL_PAD_SD2_RST__SD2_RESET               0x27c 0x584 0x000 0x0 0x0
+#define MX6SL_PAD_SD2_RST__FEC_REF_OUT             0x27c 0x584 0x000 0x1 0x0
+#define MX6SL_PAD_SD2_RST__WDOG2_B                 0x27c 0x584 0x000 0x2 0x0
+#define MX6SL_PAD_SD2_RST__SPDIF_OUT               0x27c 0x584 0x000 0x3 0x0
+#define MX6SL_PAD_SD2_RST__CSI_MCLK                0x27c 0x584 0x000 0x4 0x0
+#define MX6SL_PAD_SD2_RST__GPIO4_IO27              0x27c 0x584 0x000 0x5 0x0
+#define MX6SL_PAD_SD3_CLK__SD3_CLK                 0x280 0x588 0x000 0x0 0x0
+#define MX6SL_PAD_SD3_CLK__AUD5_RXFS               0x280 0x588 0x608 0x1 0x1
+#define MX6SL_PAD_SD3_CLK__KEY_COL5                0x280 0x588 0x748 0x2 0x2
+#define MX6SL_PAD_SD3_CLK__CSI_DATA10              0x280 0x588 0x658 0x3 0x2
+#define MX6SL_PAD_SD3_CLK__WDOG1_RESET_B_DEB       0x280 0x588 0x000 0x4 0x0
+#define MX6SL_PAD_SD3_CLK__GPIO5_IO18              0x280 0x588 0x000 0x5 0x0
+#define MX6SL_PAD_SD3_CLK__USB_OTG1_PWR            0x280 0x588 0x000 0x6 0x0
+#define MX6SL_PAD_SD3_CMD__SD3_CMD                 0x284 0x58c 0x000 0x0 0x0
+#define MX6SL_PAD_SD3_CMD__AUD5_RXC                0x284 0x58c 0x604 0x1 0x1
+#define MX6SL_PAD_SD3_CMD__KEY_ROW5                0x284 0x58c 0x768 0x2 0x2
+#define MX6SL_PAD_SD3_CMD__CSI_DATA11              0x284 0x58c 0x65c 0x3 0x2
+#define MX6SL_PAD_SD3_CMD__USB_OTG2_ID             0x284 0x58c 0x5e0 0x4 0x3
+#define MX6SL_PAD_SD3_CMD__GPIO5_IO21              0x284 0x58c 0x000 0x5 0x0
+#define MX6SL_PAD_SD3_CMD__USB_OTG2_PWR            0x284 0x58c 0x000 0x6 0x0
+#define MX6SL_PAD_SD3_DAT0__SD3_DATA0              0x288 0x590 0x000 0x0 0x0
+#define MX6SL_PAD_SD3_DAT0__AUD5_RXD               0x288 0x590 0x5fc 0x1 0x1
+#define MX6SL_PAD_SD3_DAT0__KEY_COL6               0x288 0x590 0x74c 0x2 0x2
+#define MX6SL_PAD_SD3_DAT0__CSI_DATA12             0x288 0x590 0x660 0x3 0x1
+#define MX6SL_PAD_SD3_DAT0__USB_OTG1_ID            0x288 0x590 0x5dc 0x4 0x4
+#define MX6SL_PAD_SD3_DAT0__GPIO5_IO19             0x288 0x590 0x000 0x5 0x0
+#define MX6SL_PAD_SD3_DAT1__SD3_DATA1              0x28c 0x594 0x000 0x0 0x0
+#define MX6SL_PAD_SD3_DAT1__AUD5_TXC               0x28c 0x594 0x60c 0x1 0x1
+#define MX6SL_PAD_SD3_DAT1__KEY_ROW6               0x28c 0x594 0x76c 0x2 0x2
+#define MX6SL_PAD_SD3_DAT1__CSI_DATA13             0x28c 0x594 0x664 0x3 0x1
+#define MX6SL_PAD_SD3_DAT1__SD1_VSELECT            0x28c 0x594 0x000 0x4 0x0
+#define MX6SL_PAD_SD3_DAT1__GPIO5_IO20             0x28c 0x594 0x000 0x5 0x0
+#define MX6SL_PAD_SD3_DAT1__JTAG_DE_B              0x28c 0x594 0x000 0x6 0x0
+#define MX6SL_PAD_SD3_DAT2__SD3_DATA2              0x290 0x598 0x000 0x0 0x0
+#define MX6SL_PAD_SD3_DAT2__AUD5_TXFS              0x290 0x598 0x610 0x1 0x1
+#define MX6SL_PAD_SD3_DAT2__KEY_COL7               0x290 0x598 0x750 0x2 0x2
+#define MX6SL_PAD_SD3_DAT2__CSI_DATA14             0x290 0x598 0x668 0x3 0x1
+#define MX6SL_PAD_SD3_DAT2__EPIT1_OUT              0x290 0x598 0x000 0x4 0x0
+#define MX6SL_PAD_SD3_DAT2__GPIO5_IO16             0x290 0x598 0x000 0x5 0x0
+#define MX6SL_PAD_SD3_DAT2__USB_OTG2_OC            0x290 0x598 0x820 0x6 0x3
+#define MX6SL_PAD_SD3_DAT3__SD3_DATA3              0x294 0x59c 0x000 0x0 0x0
+#define MX6SL_PAD_SD3_DAT3__AUD5_TXD               0x294 0x59c 0x600 0x1 0x1
+#define MX6SL_PAD_SD3_DAT3__KEY_ROW7               0x294 0x59c 0x770 0x2 0x2
+#define MX6SL_PAD_SD3_DAT3__CSI_DATA15             0x294 0x59c 0x66c 0x3 0x1
+#define MX6SL_PAD_SD3_DAT3__EPIT2_OUT              0x294 0x59c 0x000 0x4 0x0
+#define MX6SL_PAD_SD3_DAT3__GPIO5_IO17             0x294 0x59c 0x000 0x5 0x0
+#define MX6SL_PAD_SD3_DAT3__USB_OTG1_OC            0x294 0x59c 0x824 0x6 0x2
+#define MX6SL_PAD_UART1_RXD__UART1_RX_DATA         0x298 0x5a0 0x7fc 0x0 0x0
+#define MX6SL_PAD_UART1_RXD__UART1_TX_DATA         0x298 0x5a0 0x000 0x0 0x0
+#define MX6SL_PAD_UART1_RXD__PWM1_OUT              0x298 0x5a0 0x000 0x1 0x0
+#define MX6SL_PAD_UART1_RXD__UART4_RX_DATA         0x298 0x5a0 0x814 0x2 0x6
+#define MX6SL_PAD_UART1_RXD__UART4_TX_DATA         0x298 0x5a0 0x000 0x2 0x0
+#define MX6SL_PAD_UART1_RXD__FEC_COL               0x298 0x5a0 0x6f0 0x3 0x2
+#define MX6SL_PAD_UART1_RXD__UART5_RX_DATA         0x298 0x5a0 0x81c 0x4 0x6
+#define MX6SL_PAD_UART1_RXD__UART5_TX_DATA         0x298 0x5a0 0x000 0x4 0x0
+#define MX6SL_PAD_UART1_RXD__GPIO3_IO16            0x298 0x5a0 0x000 0x5 0x0
+#define MX6SL_PAD_UART1_TXD__UART1_TX_DATA         0x29c 0x5a4 0x000 0x0 0x0
+#define MX6SL_PAD_UART1_TXD__UART1_RX_DATA         0x29c 0x5a4 0x7fc 0x0 0x1
+#define MX6SL_PAD_UART1_TXD__PWM2_OUT              0x29c 0x5a4 0x000 0x1 0x0
+#define MX6SL_PAD_UART1_TXD__UART4_TX_DATA         0x29c 0x5a4 0x000 0x2 0x0
+#define MX6SL_PAD_UART1_TXD__UART4_RX_DATA         0x29c 0x5a4 0x814 0x2 0x7
+#define MX6SL_PAD_UART1_TXD__FEC_RX_CLK            0x29c 0x5a4 0x700 0x3 0x2
+#define MX6SL_PAD_UART1_TXD__UART5_TX_DATA         0x29c 0x5a4 0x000 0x4 0x0
+#define MX6SL_PAD_UART1_TXD__UART5_RX_DATA         0x29c 0x5a4 0x81c 0x4 0x7
+#define MX6SL_PAD_UART1_TXD__GPIO3_IO17            0x29c 0x5a4 0x000 0x5 0x0
+#define MX6SL_PAD_UART1_TXD__UART5_DCD_B           0x29c 0x5a4 0x000 0x7 0x0
+#define MX6SL_PAD_WDOG_B__WDOG1_B                  0x2a0 0x5a8 0x000 0x0 0x0
+#define MX6SL_PAD_WDOG_B__WDOG1_RESET_B_DEB        0x2a0 0x5a8 0x000 0x1 0x0
+#define MX6SL_PAD_WDOG_B__UART5_RI_B               0x2a0 0x5a8 0x000 0x2 0x0
+#define MX6SL_PAD_WDOG_B__GPIO3_IO18               0x2a0 0x5a8 0x000 0x5 0x0
+
+#endif /* __DTS_IMX6SL_PINFUNC_H */
diff --git a/arch/arm/boot/dts/kirkwood-6282.dtsi b/arch/arm/boot/dts/kirkwood-6282.dtsi
index 192cf76..23991e4 100644
--- a/arch/arm/boot/dts/kirkwood-6282.dtsi
+++ b/arch/arm/boot/dts/kirkwood-6282.dtsi
@@ -49,6 +49,12 @@
 			};
 		};
 
+		thermal@10078 {
+			compatible = "marvell,kirkwood-thermal";
+			reg = <0x10078 0x4>;
+			status = "okay";
+		};
+
 		i2c@11100 {
 			compatible = "marvell,mv64xxx-i2c";
 			reg = <0x11100 0x20>;
diff --git a/arch/arm/boot/dts/kirkwood-goflexnet.dts b/arch/arm/boot/dts/kirkwood-goflexnet.dts
index bd83b8f..c3573be 100644
--- a/arch/arm/boot/dts/kirkwood-goflexnet.dts
+++ b/arch/arm/boot/dts/kirkwood-goflexnet.dts
@@ -77,6 +77,7 @@
 		};
 
 		nand@3000000 {
+			chip-delay = <40>;
 			status = "okay";
 
 			partition@0 {
diff --git a/arch/arm/boot/dts/mpa1600.dts b/arch/arm/boot/dts/mpa1600.dts
new file mode 100644
index 0000000..3173008
--- /dev/null
+++ b/arch/arm/boot/dts/mpa1600.dts
@@ -0,0 +1,69 @@
+/*
+ * mpa1600.dts - Device Tree file for Phontech MPA 1600
+ *
+ *  Copyright (C) 2013 Joachim Eastwood <manabian@gmail.com>
+ *
+ * Licensed under GPLv2 only
+ */
+/dts-v1/;
+/include/ "at91rm9200.dtsi"
+
+/ {
+	model = "Phontech MPA 1600";
+	compatible = "phontech,mpa1600", "atmel,at91rm9200";
+
+	memory {
+		reg = <0x20000000 0x4000000>;
+	};
+
+	clocks {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		main_clock: clock@0 {
+			compatible = "atmel,osc", "fixed-clock";
+			clock-frequency = <18432000>;
+		};
+	};
+
+	ahb {
+		apb {
+			dbgu: serial@fffff200 {
+				status = "okay";
+			};
+
+			macb0: ethernet@fffbc000 {
+				phy-mode = "rmii";
+				status = "okay";
+			};
+
+			ssc0: ssc@fffd0000 {
+				status = "okay";
+			};
+
+			ssc1: ssc@fffd4000 {
+				status = "okay";
+			};
+		};
+
+		usb0: ohci@00300000 {
+			num-ports = <1>;
+			status = "okay";
+		};
+	};
+
+	i2c@0 {
+		status = "okay";
+	};
+
+	gpio_keys {
+		compatible = "gpio-keys";
+
+		monitor_mute {
+			label = "Monitor mute";
+			gpios = <&pioC 1 1>;
+			linux,code = <113>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/msm8660-surf.dts b/arch/arm/boot/dts/msm8660-surf.dts
index 31f2157..9bf49b3 100644
--- a/arch/arm/boot/dts/msm8660-surf.dts
+++ b/arch/arm/boot/dts/msm8660-surf.dts
@@ -16,19 +16,13 @@
 	};
 
 	timer@2000004 {
-		compatible = "qcom,msm-gpt", "qcom,msm-timer";
-		interrupts = <1 1 0x301>;
-		reg = <0x02000004 0x10>;
-		clock-frequency = <32768>;
-		cpu-offset = <0x40000>;
-	};
-
-	timer@2000024 {
-		compatible = "qcom,msm-dgt", "qcom,msm-timer";
-		interrupts = <1 0 0x301>;
-		reg = <0x02000024 0x10>,
-		      <0x02000034 0x4>;
-		clock-frequency = <6750000>;
+		compatible = "qcom,scss-timer", "qcom,msm-timer";
+		interrupts = <1 0 0x301>,
+			     <1 1 0x301>,
+			     <1 2 0x301>;
+		reg = <0x02000000 0x100>;
+		clock-frequency = <27000000>,
+				  <32768>;
 		cpu-offset = <0x40000>;
 	};
 
@@ -38,4 +32,10 @@
 		      <0x19c00000 0x1000>;
 		interrupts = <0 195 0x0>;
 	};
+
+	qcom,ssbi@500000 {
+		compatible = "qcom,ssbi";
+		reg = <0x500000 0x1000>;
+		qcom,controller-type = "pmic-arbiter";
+	};
 };
diff --git a/arch/arm/boot/dts/msm8960-cdp.dts b/arch/arm/boot/dts/msm8960-cdp.dts
index 9e621b5..2e4d87a 100644
--- a/arch/arm/boot/dts/msm8960-cdp.dts
+++ b/arch/arm/boot/dts/msm8960-cdp.dts
@@ -15,20 +15,14 @@
 		      < 0x02002000 0x1000 >;
 	};
 
-	timer@200a004 {
-		compatible = "qcom,msm-gpt", "qcom,msm-timer";
-		interrupts = <1 2 0x301>;
-		reg = <0x0200a004 0x10>;
-		clock-frequency = <32768>;
-		cpu-offset = <0x80000>;
-	};
-
-	timer@200a024 {
-		compatible = "qcom,msm-dgt", "qcom,msm-timer";
-		interrupts = <1 1 0x301>;
-		reg = <0x0200a024 0x10>,
-		      <0x0200a034 0x4>;
-		clock-frequency = <6750000>;
+	timer@200a000 {
+		compatible = "qcom,kpss-timer", "qcom,msm-timer";
+		interrupts = <1 1 0x301>,
+			     <1 2 0x301>,
+			     <1 3 0x301>;
+		reg = <0x0200a000 0x100>;
+		clock-frequency = <27000000>,
+				  <32768>;
 		cpu-offset = <0x80000>;
 	};
 
@@ -38,4 +32,10 @@
 		      <0x16400000 0x1000>;
 		interrupts = <0 154 0x0>;
 	};
+
+	qcom,ssbi@500000 {
+		compatible = "qcom,ssbi";
+		reg = <0x500000 0x1000>;
+		qcom,controller-type = "pmic-arbiter";
+	};
 };
diff --git a/arch/arm/boot/dts/orion5x.dtsi b/arch/arm/boot/dts/orion5x.dtsi
index 8aad00f..f7bec3b 100644
--- a/arch/arm/boot/dts/orion5x.dtsi
+++ b/arch/arm/boot/dts/orion5x.dtsi
@@ -13,6 +13,9 @@
 	compatible = "marvell,orion5x";
 	interrupt-parent = <&intc>;
 
+	aliases {
+		gpio0 = &gpio0;
+	};
 	intc: interrupt-controller {
 		compatible = "marvell,orion-intc", "marvell,intc";
 		interrupt-controller;
@@ -32,7 +35,9 @@
 			#gpio-cells = <2>;
 			gpio-controller;
 			reg = <0x10100 0x40>;
-			ngpio = <32>;
+			ngpios = <32>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
 			interrupts = <6>, <7>, <8>, <9>;
 		};
 
@@ -91,7 +96,7 @@
 			reg = <0x90000 0x10000>,
 			      <0xf2200000 0x800>;
 			reg-names = "regs", "sram";
-			interrupts = <22>;
+			interrupts = <28>;
 			status = "okay";
 		};
 	};
diff --git a/arch/arm/boot/dts/r8a73a4-ape6evm.dts b/arch/arm/boot/dts/r8a73a4-ape6evm.dts
new file mode 100644
index 0000000..f603c69
--- /dev/null
+++ b/arch/arm/boot/dts/r8a73a4-ape6evm.dts
@@ -0,0 +1,52 @@
+/*
+ * Device Tree Source for the APE6EVM board
+ *
+ * Copyright (C) 2013 Renesas Solutions Corp.
+ *
+ * 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.
+ */
+
+/dts-v1/;
+/include/ "r8a73a4.dtsi"
+
+/ {
+	model = "APE6EVM";
+	compatible = "renesas,ape6evm", "renesas,r8a73a4";
+
+	chosen {
+		bootargs = "console=ttySC0,115200 ignore_loglevel root=/dev/nfs ip=dhcp";
+	};
+
+	memory@40000000 {
+		device_type = "memory";
+		reg = <0 0x40000000 0 0x40000000>;
+	};
+
+	ape6evm_fixed_3v3: fixedregulator@0 {
+		compatible = "regulator-fixed";
+		regulator-name = "3V3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-always-on;
+	};
+
+	lbsc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		ethernet@8000000 {
+			compatible = "smsc,lan9118", "smsc,lan9115";
+			reg = <0x08000000 0x1000>;
+			interrupt-parent = <&irqc1>;
+			interrupts = <8 0x4>;
+			phy-mode = "mii";
+			reg-io-width = <4>;
+			smsc,irq-active-high;
+			smsc,irq-push-pull;
+			vdd33a-supply = <&ape6evm_fixed_3v3>;
+			vddvario-supply = <&ape6evm_fixed_3v3>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/r8a73a4.dtsi b/arch/arm/boot/dts/r8a73a4.dtsi
new file mode 100644
index 0000000..fde2a33
--- /dev/null
+++ b/arch/arm/boot/dts/r8a73a4.dtsi
@@ -0,0 +1,94 @@
+/*
+ * Device Tree Source for the r8a73a4 SoC
+ *
+ * Copyright (C) 2013 Renesas Solutions Corp.
+ * Copyright (C) 2013 Magnus Damm
+ *
+ * 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.
+ */
+
+/ {
+	compatible = "renesas,r8a73a4";
+	interrupt-parent = <&gic>;
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu0: cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <0>;
+			clock-frequency = <1500000000>;
+		};
+	};
+
+	gic: interrupt-controller@f1001000 {
+		compatible = "arm,cortex-a15-gic";
+		#interrupt-cells = <3>;
+		#address-cells = <0>;
+		interrupt-controller;
+		reg = <0 0xf1001000 0 0x1000>,
+			<0 0xf1002000 0 0x1000>,
+			<0 0xf1004000 0 0x2000>,
+			<0 0xf1006000 0 0x2000>;
+		interrupts = <1 9 0xf04>;
+
+		gic-cpuif@4 {
+			compatible = "arm,gic-cpuif";
+			cpuif-id = <4>;
+			cpu = <&cpu0>;
+		};
+	};
+
+	timer {
+		compatible = "arm,armv7-timer";
+		interrupts = <1 13 0xf08>,
+				<1 14 0xf08>,
+				<1 11 0xf08>,
+				<1 10 0xf08>;
+	};
+
+	irqc0: interrupt-controller@e61c0000 {
+		compatible = "renesas,irqc";
+		#interrupt-cells = <2>;
+		interrupt-controller;
+		reg = <0 0xe61c0000 0 0x200>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 0 4>, <0 1 4>, <0 2 4>,	<0 3 4>,
+				<0 4 4>, <0 5 4>, <0 6 4>, <0 7 4>,
+				<0 8 4>, <0 9 4>, <0 10 4>, <0 11 4>,
+				<0 12 4>, <0 13 4>, <0 14 4>, <0 15 4>,
+				<0 16 4>, <0 17 4>, <0 18 4>, <0 19 4>,
+				<0 20 4>, <0 21 4>, <0 22 4>, <0 23 4>,
+				<0 24 4>, <0 25 4>, <0 26 4>, <0 27 4>,
+				<0 28 4>, <0 29 4>, <0 30 4>, <0 31 4>;
+	};
+
+	irqc1: interrupt-controller@e61c0200 {
+		compatible = "renesas,irqc";
+		#interrupt-cells = <2>;
+		interrupt-controller;
+		reg = <0 0xe61c0200 0 0x200>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 32 4>, <0 33 4>, <0 34 4>, <0 35 4>,
+				<0 36 4>, <0 37 4>, <0 38 4>, <0 39 4>,
+				<0 40 4>, <0 41 4>, <0 42 4>, <0 43 4>,
+				<0 44 4>, <0 45 4>, <0 46 4>, <0 47 4>,
+				<0 48 4>, <0 49 4>, <0 50 4>, <0 51 4>,
+				<0 52 4>, <0 53 4>, <0 54 4>, <0 55 4>,
+				<0 56 4>, <0 57 4>;
+	};
+
+	thermal@e61f0000 {
+		compatible = "renesas,rcar-thermal";
+		reg = <0 0xe61f0000 0 0x14>, <0 0xe61f0100 0 0x38>,
+			 <0 0xe61f0200 0 0x38>, <0 0xe61f0300 0 0x38>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 69 4>;
+	};
+};
diff --git a/arch/arm/boot/dts/r8a7778-bockw.dts b/arch/arm/boot/dts/r8a7778-bockw.dts
new file mode 100644
index 0000000..0076b1e
--- /dev/null
+++ b/arch/arm/boot/dts/r8a7778-bockw.dts
@@ -0,0 +1,32 @@
+/*
+ * Reference Device Tree Source for the Bock-W board
+ *
+ * Copyright (C) 2013  Renesas Solutions Corp.
+ * Copyright (C) 2013  Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+ *
+ * based on r8a7779
+ *
+ * Copyright (C) 2013 Renesas Solutions Corp.
+ * Copyright (C) 2013 Simon Horman
+ *
+ * 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.
+ */
+
+/dts-v1/;
+/include/ "r8a7778.dtsi"
+
+/ {
+	model = "bockw";
+	compatible = "renesas,bockw", "renesas,r8a7778";
+
+	chosen {
+		bootargs = "console=ttySC0,115200 ignore_loglevel ip=dhcp root=/dev/nfs";
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x60000000 0x10000000>;
+	};
+};
diff --git a/arch/arm/boot/dts/r8a7778.dtsi b/arch/arm/boot/dts/r8a7778.dtsi
new file mode 100644
index 0000000..4743735
--- /dev/null
+++ b/arch/arm/boot/dts/r8a7778.dtsi
@@ -0,0 +1,35 @@
+/*
+ * Device Tree Source for Renesas r8a7778
+ *
+ * Copyright (C) 2013  Renesas Solutions Corp.
+ * Copyright (C) 2013  Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+ *
+ * based on r8a7779
+ *
+ * Copyright (C) 2013 Renesas Solutions Corp.
+ * Copyright (C) 2013 Simon Horman
+ *
+ * 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/ "skeleton.dtsi"
+
+/ {
+	compatible = "renesas,r8a7778";
+
+	cpus {
+		cpu@0 {
+			compatible = "arm,cortex-a9";
+		};
+	};
+
+	gic: interrupt-controller@fe438000 {
+		compatible = "arm,cortex-a9-gic";
+		#interrupt-cells = <3>;
+		interrupt-controller;
+		reg = <0xfe438000 0x1000>,
+		      <0xfe430000 0x100>;
+	};
+};
diff --git a/arch/arm/boot/dts/r8a7779-marzen-reference.dts b/arch/arm/boot/dts/r8a7779-marzen-reference.dts
new file mode 100644
index 0000000..72be4c8
--- /dev/null
+++ b/arch/arm/boot/dts/r8a7779-marzen-reference.dts
@@ -0,0 +1,47 @@
+/*
+ * Reference Device Tree Source for the Marzen board
+ *
+ * Copyright (C) 2013 Renesas Solutions Corp.
+ * Copyright (C) 2013 Simon Horman
+ *
+ * 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.
+ */
+
+/dts-v1/;
+/include/ "r8a7779.dtsi"
+
+/ {
+	model = "marzen";
+	compatible = "renesas,marzen-reference", "renesas,r8a7779";
+
+	chosen {
+		bootargs = "console=ttySC2,115200 earlyprintk=sh-sci.2,115200 ignore_loglevel root=/dev/nfs ip=on";
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x60000000 0x40000000>;
+	};
+
+	fixedregulator3v3: fixedregulator@0 {
+		compatible = "regulator-fixed";
+		regulator-name = "fixed-3.3V";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+
+	lan0@18000000 {
+		compatible = "smsc,lan9220", "smsc,lan9115";
+		reg = <0x18000000 0x100>;
+		phy-mode = "mii";
+		interrupt-parent = <&gic>;
+		interrupts = <0 28 0x4>;
+		reg-io-width = <4>;
+		vddvario-supply = <&fixedregulator3v3>;
+		vdd33a-supply = <&fixedregulator3v3>;
+	};
+};
diff --git a/arch/arm/boot/dts/r8a7779.dtsi b/arch/arm/boot/dts/r8a7779.dtsi
new file mode 100644
index 0000000..fe5c6f2
--- /dev/null
+++ b/arch/arm/boot/dts/r8a7779.dtsi
@@ -0,0 +1,98 @@
+/*
+ * Device Tree Source for Renesas r8a7779
+ *
+ * Copyright (C) 2013 Renesas Solutions Corp.
+ * Copyright (C) 2013 Simon Horman
+ *
+ * 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/ "skeleton.dtsi"
+
+/ {
+	compatible = "renesas,r8a7779";
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a9";
+			reg = <0>;
+		};
+		cpu@1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a9";
+			reg = <1>;
+		};
+		cpu@2 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a9";
+			reg = <2>;
+		};
+		cpu@3 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a9";
+			reg = <3>;
+		};
+	};
+
+        gic: interrupt-controller@f0001000 {
+                compatible = "arm,cortex-a9-gic";
+                #interrupt-cells = <3>;
+                interrupt-controller;
+                reg = <0xf0001000 0x1000>,
+                      <0xf0000100 0x100>;
+        };
+
+	i2c0: i2c@0xffc70000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "renesas,rmobile-iic";
+		reg = <0xffc70000 0x1000>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 79 0x4>;
+	};
+
+	i2c1: i2c@0xffc71000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "renesas,rmobile-iic";
+		reg = <0xffc71000 0x1000>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 82 0x4>;
+	};
+
+	i2c2: i2c@0xffc72000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "renesas,rmobile-iic";
+		reg = <0xffc72000 0x1000>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 80 0x4>;
+	};
+
+	i2c3: i2c@0xffc73000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "renesas,rmobile-iic";
+		reg = <0xffc73000 0x1000>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 81 0x4>;
+	};
+
+	thermal@ffc48000 {
+		compatible = "renesas,rcar-thermal";
+		reg = <0xffc48000 0x38>;
+	};
+
+	sata: sata@fc600000 {
+		compatible = "renesas,rcar-sata";
+		reg = <0xfc600000 0x2000>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 100 0x4>;
+	};
+};
diff --git a/arch/arm/boot/dts/r8a7790-lager.dts b/arch/arm/boot/dts/r8a7790-lager.dts
new file mode 100644
index 0000000..09a84fc
--- /dev/null
+++ b/arch/arm/boot/dts/r8a7790-lager.dts
@@ -0,0 +1,31 @@
+/*
+ * Device Tree Source for the Lager board
+ *
+ * Copyright (C) 2013 Renesas Solutions Corp.
+ *
+ * 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.
+ */
+
+/dts-v1/;
+/include/ "r8a7790.dtsi"
+
+/ {
+	model = "Lager";
+	compatible = "renesas,lager", "renesas,r8a7790";
+
+	chosen {
+		bootargs = "console=ttySC6,115200 ignore_loglevel";
+	};
+
+	memory@40000000 {
+		device_type = "memory";
+		reg = <0 0x40000000 0 0x80000000>;
+	};
+
+	lbsc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+	};
+};
diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi
new file mode 100644
index 0000000..7a17110
--- /dev/null
+++ b/arch/arm/boot/dts/r8a7790.dtsi
@@ -0,0 +1,63 @@
+/*
+ * Device Tree Source for the r8a7790 SoC
+ *
+ * Copyright (C) 2013 Renesas Solutions Corp.
+ *
+ * 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.
+ */
+
+/ {
+	compatible = "renesas,r8a7790";
+	interrupt-parent = <&gic>;
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu0: cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <0>;
+			clock-frequency = <1300000000>;
+		};
+	};
+
+	gic: interrupt-controller@f1001000 {
+		compatible = "arm,cortex-a15-gic";
+		#interrupt-cells = <3>;
+		#address-cells = <0>;
+		interrupt-controller;
+		reg = <0 0xf1001000 0 0x1000>,
+			<0 0xf1002000 0 0x1000>,
+			<0 0xf1004000 0 0x2000>,
+			<0 0xf1006000 0 0x2000>;
+		interrupts = <1 9 0xf04>;
+
+		gic-cpuif@4 {
+			compatible = "arm,gic-cpuif";
+			cpuif-id = <4>;
+			cpu = <&cpu0>;
+		};
+	};
+
+	timer {
+		compatible = "arm,armv7-timer";
+		interrupts = <1 13 0xf08>,
+				<1 14 0xf08>,
+				<1 11 0xf08>,
+				<1 10 0xf08>;
+	};
+
+	irqc0: interrupt-controller@e61c0000 {
+		compatible = "renesas,irqc";
+		#interrupt-cells = <2>;
+		interrupt-controller;
+		reg = <0 0xe61c0000 0 0x200>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 0 4>, <0 1 4>, <0 2 4>,	<0 3 4>;
+	};
+};
diff --git a/arch/arm/boot/dts/sama5d3.dtsi b/arch/arm/boot/dts/sama5d3.dtsi
new file mode 100644
index 0000000..39b0458
--- /dev/null
+++ b/arch/arm/boot/dts/sama5d3.dtsi
@@ -0,0 +1,1031 @@
+/*
+ * sama5d3.dtsi - Device Tree Include file for SAMA5D3 family SoC
+ *                applies to SAMA5D31, SAMA5D33, SAMA5D34, SAMA5D35 SoC
+ *
+ *  Copyright (C) 2013 Atmel,
+ *                2013 Ludovic Desroches <ludovic.desroches@atmel.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+	model = "Atmel SAMA5D3 family SoC";
+	compatible = "atmel,sama5d3", "atmel,sama5";
+	interrupt-parent = <&aic>;
+
+	aliases {
+		serial0 = &dbgu;
+		serial1 = &usart0;
+		serial2 = &usart1;
+		serial3 = &usart2;
+		serial4 = &usart3;
+		gpio0 = &pioA;
+		gpio1 = &pioB;
+		gpio2 = &pioC;
+		gpio3 = &pioD;
+		gpio4 = &pioE;
+		tcb0 = &tcb0;
+		tcb1 = &tcb1;
+		i2c0 = &i2c0;
+		i2c1 = &i2c1;
+		i2c2 = &i2c2;
+		ssc0 = &ssc0;
+		ssc1 = &ssc1;
+	};
+	cpus {
+		cpu@0 {
+			compatible = "arm,cortex-a5";
+		};
+	};
+
+	memory {
+		reg = <0x20000000 0x8000000>;
+	};
+
+	ahb {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		apb {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+
+			mmc0: mmc@f0000000 {
+				compatible = "atmel,hsmci";
+				reg = <0xf0000000 0x600>;
+				interrupts = <21 4 0>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_mmc0_clk_cmd_dat0 &pinctrl_mmc0_dat1_3 &pinctrl_mmc0_dat4_7>;
+				status = "disabled";
+				#address-cells = <1>;
+				#size-cells = <0>;
+			};
+
+			spi0: spi@f0004000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "atmel,at91sam9x5-spi";
+				reg = <0xf0004000 0x100>;
+				interrupts = <24 4 3>;
+				cs-gpios = <&pioD 13 0
+					    &pioD 14 0 /* conflicts with SCK0 and CANRX0 */
+					    &pioD 15 0 /* conflicts with CTS0 and CANTX0 */
+					    &pioD 16 0 /* conflicts with RTS0 and PWMFI3 */
+					   >;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_spi0>;
+				status = "disabled";
+			};
+
+			ssc0: ssc@f0008000 {
+				compatible = "atmel,at91sam9g45-ssc";
+				reg = <0xf0008000 0x4000>;
+				interrupts = <38 4 4>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_ssc0_tx &pinctrl_ssc0_rx>;
+				status = "disabled";
+			};
+
+			can0: can@f000c000 {
+				compatible = "atmel,at91sam9x5-can";
+				reg = <0xf000c000 0x300>;
+				interrupts = <40 4 3>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_can0_rx_tx>;
+				status = "disabled";
+			};
+
+			tcb0: timer@f0010000 {
+				compatible = "atmel,at91sam9x5-tcb";
+				reg = <0xf0010000 0x100>;
+				interrupts = <26 4 0>;
+			};
+
+			i2c0: i2c@f0014000 {
+				compatible = "atmel,at91sam9x5-i2c";
+				reg = <0xf0014000 0x4000>;
+				interrupts = <18 4 6>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_i2c0>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				status = "disabled";
+			};
+
+			i2c1: i2c@f0018000 {
+				compatible = "atmel,at91sam9x5-i2c";
+				reg = <0xf0018000 0x4000>;
+				interrupts = <19 4 6>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_i2c1>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				status = "disabled";
+			};
+
+			usart0: serial@f001c000 {
+				compatible = "atmel,at91sam9260-usart";
+				reg = <0xf001c000 0x100>;
+				interrupts = <12 4 5>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_usart0>;
+				status = "disabled";
+			};
+
+			usart1: serial@f0020000 {
+				compatible = "atmel,at91sam9260-usart";
+				reg = <0xf0020000 0x100>;
+				interrupts = <13 4 5>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_usart1>;
+				status = "disabled";
+			};
+
+			macb0: ethernet@f0028000 {
+				compatible = "cnds,pc302-gem", "cdns,gem";
+				reg = <0xf0028000 0x100>;
+				interrupts = <34 4 3>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_macb0_data_rgmii &pinctrl_macb0_signal_rgmii>;
+				status = "disabled";
+			};
+
+			isi: isi@f0034000 {
+				compatible = "atmel,at91sam9g45-isi";
+				reg = <0xf0034000 0x4000>;
+				interrupts = <37 4 5>;
+				status = "disabled";
+			};
+
+			mmc1: mmc@f8000000 {
+				compatible = "atmel,hsmci";
+				reg = <0xf8000000 0x600>;
+				interrupts = <22 4 0>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_mmc1_clk_cmd_dat0 &pinctrl_mmc1_dat1_3>;
+				status = "disabled";
+				#address-cells = <1>;
+				#size-cells = <0>;
+			};
+
+			mmc2: mmc@f8004000 {
+				compatible = "atmel,hsmci";
+				reg = <0xf8004000 0x600>;
+				interrupts = <23 4 0>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_mmc2_clk_cmd_dat0 &pinctrl_mmc2_dat1_3>;
+				status = "disabled";
+				#address-cells = <1>;
+				#size-cells = <0>;
+			};
+
+			spi1: spi@f8008000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "atmel,at91sam9x5-spi";
+				reg = <0xf8008000 0x100>;
+				interrupts = <25 4 3>;
+				cs-gpios = <&pioC 25 0
+					    &pioC 26 0 /* conflitcs with TWD1 and ISI_D11 */
+					    &pioC 27 0 /* conflitcs with TWCK1 and ISI_D10 */
+					    &pioC 28 0 /* conflitcs with PWMFI0 and ISI_D9 */
+					   >;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_spi1>;
+				status = "disabled";
+			};
+
+			ssc1: ssc@f800c000 {
+				compatible = "atmel,at91sam9g45-ssc";
+				reg = <0xf800c000 0x4000>;
+				interrupts = <39 4 4>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_ssc1_tx &pinctrl_ssc1_rx>;
+				status = "disabled";
+			};
+
+			can1: can@f8010000 {
+				compatible = "atmel,at91sam9x5-can";
+				reg = <0xf8010000 0x300>;
+				interrupts = <41 4 3>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_can1_rx_tx>;
+			};
+
+			tcb1: timer@f8014000 {
+				compatible = "atmel,at91sam9x5-tcb";
+				reg = <0xf8014000 0x100>;
+				interrupts = <27 4 0>;
+			};
+
+			adc0: adc@f8018000 {
+				compatible = "atmel,at91sam9260-adc";
+				reg = <0xf8018000 0x100>;
+				interrupts = <29 4 5>;
+				pinctrl-names = "default";
+				pinctrl-0 = <
+					&pinctrl_adc0_adtrg
+					&pinctrl_adc0_ad0
+					&pinctrl_adc0_ad1
+					&pinctrl_adc0_ad2
+					&pinctrl_adc0_ad3
+					&pinctrl_adc0_ad4
+					&pinctrl_adc0_ad5
+					&pinctrl_adc0_ad6
+					&pinctrl_adc0_ad7
+					&pinctrl_adc0_ad8
+					&pinctrl_adc0_ad9
+					&pinctrl_adc0_ad10
+					&pinctrl_adc0_ad11
+					>;
+				atmel,adc-channel-base = <0x50>;
+				atmel,adc-channels-used = <0xfff>;
+				atmel,adc-drdy-mask = <0x1000000>;
+				atmel,adc-num-channels = <12>;
+				atmel,adc-startup-time = <40>;
+				atmel,adc-status-register = <0x30>;
+				atmel,adc-trigger-register = <0xc0>;
+				atmel,adc-use-external;
+				atmel,adc-vref = <3000>;
+				atmel,adc-res = <10 12>;
+				atmel,adc-res-names = "lowres", "highres";
+				status = "disabled";
+
+				trigger@0 {
+					trigger-name = "external-rising";
+					trigger-value = <0x1>;
+					trigger-external;
+				};
+				trigger@1 {
+					trigger-name = "external-falling";
+					trigger-value = <0x2>;
+					trigger-external;
+				};
+				trigger@2 {
+					trigger-name = "external-any";
+					trigger-value = <0x3>;
+					trigger-external;
+				};
+				trigger@3 {
+					trigger-name = "continuous";
+					trigger-value = <0x6>;
+				};
+			};
+
+			tsadcc: tsadcc@f8018000 {
+				compatible = "atmel,at91sam9x5-tsadcc";
+				reg = <0xf8018000 0x4000>;
+				interrupts = <29 4 5>;
+				atmel,tsadcc_clock = <300000>;
+				atmel,filtering_average = <0x03>;
+				atmel,pendet_debounce = <0x08>;
+				atmel,pendet_sensitivity = <0x02>;
+				atmel,ts_sample_hold_time = <0x0a>;
+				status = "disabled";
+			};
+
+			i2c2: i2c@f801c000 {
+				compatible = "atmel,at91sam9x5-i2c";
+				reg = <0xf801c000 0x4000>;
+				interrupts = <20 4 6>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				status = "disabled";
+			};
+
+			usart2: serial@f8020000 {
+				compatible = "atmel,at91sam9260-usart";
+				reg = <0xf8020000 0x100>;
+				interrupts = <14 4 5>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_usart2>;
+				status = "disabled";
+			};
+
+			usart3: serial@f8024000 {
+				compatible = "atmel,at91sam9260-usart";
+				reg = <0xf8024000 0x100>;
+				interrupts = <15 4 5>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_usart3>;
+				status = "disabled";
+			};
+
+			macb1: ethernet@f802c000 {
+				compatible = "cdns,at32ap7000-macb", "cdns,macb";
+				reg = <0xf802c000 0x100>;
+				interrupts = <35 4 3>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_macb1_rmii>;
+				status = "disabled";
+			};
+
+			sha@f8034000 {
+				compatible = "atmel,sam9g46-sha";
+				reg = <0xf8034000 0x100>;
+				interrupts = <42 4 0>;
+			};
+
+			aes@f8038000 {
+				compatible = "atmel,sam9g46-aes";
+				reg = <0xf8038000 0x100>;
+				interrupts = <43 4 0>;
+			};
+
+			tdes@f803c000 {
+				compatible = "atmel,sam9g46-tdes";
+				reg = <0xf803c000 0x100>;
+				interrupts = <44 4 0>;
+			};
+
+			dma0: dma-controller@ffffe600 {
+				compatible = "atmel,at91sam9g45-dma";
+				reg = <0xffffe600 0x200>;
+				interrupts = <30 4 0>;
+				#dma-cells = <1>;
+			};
+
+			dma1: dma-controller@ffffe800 {
+				compatible = "atmel,at91sam9g45-dma";
+				reg = <0xffffe800 0x200>;
+				interrupts = <31 4 0>;
+				#dma-cells = <1>;
+			};
+
+			ramc0: ramc@ffffea00 {
+				compatible = "atmel,at91sam9g45-ddramc";
+				reg = <0xffffea00 0x200>;
+			};
+
+			dbgu: serial@ffffee00 {
+				compatible = "atmel,at91sam9260-usart";
+				reg = <0xffffee00 0x200>;
+				interrupts = <2 4 7>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_dbgu>;
+				status = "disabled";
+			};
+
+			aic: interrupt-controller@fffff000 {
+				#interrupt-cells = <3>;
+				compatible = "atmel,sama5d3-aic";
+				interrupt-controller;
+				reg = <0xfffff000 0x200>;
+				atmel,external-irqs = <47>;
+			};
+
+			pinctrl@fffff200 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "atmel,at91sam9x5-pinctrl", "atmel,at91rm9200-pinctrl", "simple-bus";
+				ranges = <0xfffff200 0xfffff200 0xa00>;
+				atmel,mux-mask = <
+					/*   A          B          C  */
+					0xffffffff 0xc0fc0000 0xc0ff0000	/* pioA */
+					0xffffffff 0x0ff8ffff 0x00000000	/* pioB */
+					0xffffffff 0xbc00f1ff 0x7c00fc00	/* pioC */
+					0xffffffff 0xc001c0e0 0x0001c1e0	/* pioD */
+					0xffffffff 0xbf9f8000 0x18000000	/* pioE */
+					>;
+
+				/* shared pinctrl settings */
+				adc0 {
+					pinctrl_adc0_adtrg: adc0_adtrg {
+						atmel,pins =
+							<3 19 0x1 0x0>;	/* PD19 periph A ADTRG */
+					};
+					pinctrl_adc0_ad0: adc0_ad0 {
+						atmel,pins =
+							<3 20 0x1 0x0>;	/* PD20 periph A AD0 */
+					};
+					pinctrl_adc0_ad1: adc0_ad1 {
+						atmel,pins =
+							<3 21 0x1 0x0>;	/* PD21 periph A AD1 */
+					};
+					pinctrl_adc0_ad2: adc0_ad2 {
+						atmel,pins =
+							<3 22 0x1 0x0>;	/* PD22 periph A AD2 */
+					};
+					pinctrl_adc0_ad3: adc0_ad3 {
+						atmel,pins =
+							<3 23 0x1 0x0>;	/* PD23 periph A AD3 */
+					};
+					pinctrl_adc0_ad4: adc0_ad4 {
+						atmel,pins =
+							<3 24 0x1 0x0>;	/* PD24 periph A AD4 */
+					};
+					pinctrl_adc0_ad5: adc0_ad5 {
+						atmel,pins =
+							<3 25 0x1 0x0>;	/* PD25 periph A AD5 */
+					};
+					pinctrl_adc0_ad6: adc0_ad6 {
+						atmel,pins =
+							<3 26 0x1 0x0>;	/* PD26 periph A AD6 */
+					};
+					pinctrl_adc0_ad7: adc0_ad7 {
+						atmel,pins =
+							<3 27 0x1 0x0>;	/* PD27 periph A AD7 */
+					};
+					pinctrl_adc0_ad8: adc0_ad8 {
+						atmel,pins =
+							<3 28 0x1 0x0>;	/* PD28 periph A AD8 */
+					};
+					pinctrl_adc0_ad9: adc0_ad9 {
+						atmel,pins =
+							<3 29 0x1 0x0>;	/* PD29 periph A AD9 */
+					};
+					pinctrl_adc0_ad10: adc0_ad10 {
+						atmel,pins =
+							<3 30 0x1 0x0>;	/* PD30 periph A AD10, conflicts with PCK0 */
+					};
+					pinctrl_adc0_ad11: adc0_ad11 {
+						atmel,pins =
+							<3 31 0x1 0x0>;	/* PD31 periph A AD11, conflicts with PCK1 */
+					};
+				};
+
+				can0 {
+					pinctrl_can0_rx_tx: can0_rx_tx {
+						atmel,pins =
+							<3 14 0x3 0x0	/* PD14 periph C RX, conflicts with SCK0, SPI0_NPCS1 */
+							 3 15 0x3 0x0>;	/* PD15 periph C TX, conflicts with CTS0, SPI0_NPCS2 */
+					};
+				};
+
+				can1 {
+					pinctrl_can1_rx_tx: can1_rx_tx {
+						atmel,pins =
+							<1 14 0x2 0x0	/* PB14 periph B RX, conflicts with GCRS */
+							 1 15 0x2 0x0>;	/* PB15 periph B TX, conflicts with GCOL */
+					};
+				};
+
+				dbgu {
+					pinctrl_dbgu: dbgu-0 {
+						atmel,pins =
+							<1 30 0x1 0x0	/* PB30 periph A */
+							 1 31 0x1 0x1>;	/* PB31 periph A with pullup */
+					};
+				};
+
+				i2c0 {
+					pinctrl_i2c0: i2c0-0 {
+						atmel,pins =
+							<0 30 0x1 0x0	/* PA30 periph A TWD0 pin, conflicts with URXD1, ISI_VSYNC */
+							 0 31 0x1 0x0>;	/* PA31 periph A TWCK0 pin, conflicts with UTXD1, ISI_HSYNC */
+					};
+				};
+
+				i2c1 {
+					pinctrl_i2c1: i2c1-0 {
+						atmel,pins =
+							<2 26 0x2 0x0	/* PC26 periph B TWD1 pin, conflicts with SPI1_NPCS1, ISI_D11 */
+							 2 27 0x2 0x0>;	/* PC27 periph B TWCK1 pin, conflicts with SPI1_NPCS2, ISI_D10 */
+					};
+				};
+
+				isi {
+					pinctrl_isi: isi-0 {
+						atmel,pins =
+							<0 16 0x3 0x0	/* PA16 periph C ISI_D0, conflicts with LCDDAT16 */
+							 0 17 0x3 0x0	/* PA17 periph C ISI_D1, conflicts with LCDDAT17 */
+							 0 18 0x3 0x0	/* PA18 periph C ISI_D2, conflicts with LCDDAT18, TWD2 */
+							 0 19 0x3 0x0	/* PA19 periph C ISI_D3, conflicts with LCDDAT19, TWCK2 */
+							 0 20 0x3 0x0	/* PA20 periph C ISI_D4, conflicts with LCDDAT20, PWMH0 */
+							 0 21 0x3 0x0	/* PA21 periph C ISI_D5, conflicts with LCDDAT21, PWML0 */
+							 0 22 0x3 0x0	/* PA22 periph C ISI_D6, conflicts with LCDDAT22, PWMH1 */
+							 0 23 0x3 0x0	/* PA23 periph C ISI_D7, conflicts with LCDDAT23, PWML1 */
+							 2 30 0x3 0x0	/* PC30 periph C ISI_PCK, conflicts with UTXD0 */
+							 0 31 0x3 0x0	/* PA31 periph C ISI_HSYNC, conflicts with TWCK0, UTXD1 */
+							 0 30 0x3 0x0	/* PA30 periph C ISI_VSYNC, conflicts with TWD0, URXD1 */
+							 2 29 0x3 0x0	/* PC29 periph C ISI_PD8, conflicts with URXD0, PWMFI2 */
+							 2 28 0x3 0x0>;	/* PC28 periph C ISI_PD9, conflicts with SPI1_NPCS3, PWMFI0 */
+					};
+					pinctrl_isi_pck_as_mck: isi_pck_as_mck-0 {
+						atmel,pins =
+							<3 31 0x2 0x0>;	/* PD31 periph B ISI_MCK */
+					};
+				};
+
+				lcd {
+					pinctrl_lcd: lcd-0 {
+						atmel,pins =
+							<0 24 0x1 0x0	/* PA24 periph A LCDPWM */
+							 0 26 0x1 0x0	/* PA26 periph A LCDVSYNC */
+							 0 27 0x1 0x0	/* PA27 periph A LCDHSYNC */
+							 0 25 0x1 0x0	/* PA25 periph A LCDDISP */
+							 0 29 0x1 0x0	/* PA29 periph A LCDDEN */
+							 0 28 0x1 0x0	/* PA28 periph A LCDPCK */
+							 0 0 0x1 0x0	/* PA0 periph A LCDD0 pin */
+							 0 1 0x1 0x0	/* PA1 periph A LCDD1 pin */
+							 0 2 0x1 0x0	/* PA2 periph A LCDD2 pin */
+							 0 3 0x1 0x0	/* PA3 periph A LCDD3 pin */
+							 0 4 0x1 0x0	/* PA4 periph A LCDD4 pin */
+							 0 5 0x1 0x0	/* PA5 periph A LCDD5 pin */
+							 0 6 0x1 0x0	/* PA6 periph A LCDD6 pin */
+							 0 7 0x1 0x0	/* PA7 periph A LCDD7 pin */
+							 0 8 0x1 0x0	/* PA8 periph A LCDD8 pin */
+							 0 9 0x1 0x0	/* PA9 periph A LCDD9 pin */
+							 0 10 0x1 0x0	/* PA10 periph A LCDD10 pin */
+							 0 11 0x1 0x0	/* PA11 periph A LCDD11 pin */
+							 0 12 0x1 0x0	/* PA12 periph A LCDD12 pin */
+							 0 13 0x1 0x0	/* PA13 periph A LCDD13 pin */
+							 0 14 0x1 0x0	/* PA14 periph A LCDD14 pin */
+							 0 15 0x1 0x0	/* PA15 periph A LCDD15 pin */
+							 2 14 0x3 0x0	/* PC14 periph C LCDD16 pin */
+							 2 13 0x3 0x0	/* PC13 periph C LCDD17 pin */
+							 2 12 0x3 0x0	/* PC12 periph C LCDD18 pin */
+							 2 11 0x3 0x0	/* PC11 periph C LCDD19 pin */
+							 2 10 0x3 0x0	/* PC10 periph C LCDD20 pin */
+							 2 15 0x3 0x0	/* PC15 periph C LCDD21 pin */
+							 4 27 0x3 0x0	/* PE27 periph C LCDD22 pin */
+							 4 28 0x3 0x0>;	/* PE28 periph C LCDD23 pin */
+					};
+				};
+
+				macb0 {
+					pinctrl_macb0_data_rgmii: macb0_data_rgmii {
+						atmel,pins =
+							<1 0 0x1 0x0	/* PB0 periph A GTX0, conflicts with PWMH0 */
+							 1 1 0x1 0x0	/* PB1 periph A GTX1, conflicts with PWML0 */
+							 1 2 0x1 0x0	/* PB2 periph A GTX2, conflicts with TK1 */
+							 1 3 0x1 0x0	/* PB3 periph A GTX3, conflicts with TF1 */
+							 1 4 0x1 0x0	/* PB4 periph A GRX0, conflicts with PWMH1 */
+							 1 5 0x1 0x0	/* PB5 periph A GRX1, conflicts with PWML1 */
+							 1 6 0x1 0x0	/* PB6 periph A GRX2, conflicts with TD1 */
+							 1 7 0x1 0x0>;	/* PB7 periph A GRX3, conflicts with RK1 */
+					};
+					pinctrl_macb0_data_gmii: macb0_data_gmii {
+						atmel,pins =
+							<1 19 0x2 0x0	/* PB19 periph B GTX4, conflicts with MCI1_CDA */
+							 1 20 0x2 0x0	/* PB20 periph B GTX5, conflicts with MCI1_DA0 */
+							 1 21 0x2 0x0	/* PB21 periph B GTX6, conflicts with MCI1_DA1 */
+							 1 22 0x2 0x0	/* PB22 periph B GTX7, conflicts with MCI1_DA2 */
+							 1 23 0x2 0x0	/* PB23 periph B GRX4, conflicts with MCI1_DA3 */
+							 1 24 0x2 0x0	/* PB24 periph B GRX5, conflicts with MCI1_CK */
+							 1 25 0x2 0x0	/* PB25 periph B GRX6, conflicts with SCK1 */
+							 1 26 0x2 0x0>;	/* PB26 periph B GRX7, conflicts with CTS1 */
+					};
+					pinctrl_macb0_signal_rgmii: macb0_signal_rgmii {
+						atmel,pins =
+							<1 8 0x1 0x0	/* PB8 periph A GTXCK, conflicts with PWMH2 */
+							 1 9 0x1 0x0	/* PB9 periph A GTXEN, conflicts with PWML2 */
+							 1 11 0x1 0x0	/* PB11 periph A GRXCK, conflicts with RD1 */
+							 1 13 0x1 0x0	/* PB13 periph A GRXER, conflicts with PWML3 */
+							 1 16 0x1 0x0	/* PB16 periph A GMDC */
+							 1 17 0x1 0x0	/* PB17 periph A GMDIO */
+							 1 18 0x1 0x0>;	/* PB18 periph A G125CK */
+					};
+					pinctrl_macb0_signal_gmii: macb0_signal_gmii {
+						atmel,pins =
+							<1 9 0x1 0x0	/* PB9 periph A GTXEN, conflicts with PWML2 */
+							 1 10 0x1 0x0	/* PB10 periph A GTXER, conflicts with RF1 */
+							 1 11 0x1 0x0	/* PB11 periph A GRXCK, conflicts with RD1 */
+							 1 12 0x1 0x0	/* PB12 periph A GRXDV, conflicts with PWMH3 */
+							 1 13 0x1 0x0	/* PB13 periph A GRXER, conflicts with PWML3 */
+							 1 14 0x1 0x0	/* PB14 periph A GCRS, conflicts with CANRX1 */
+							 1 15 0x1 0x0	/* PB15 periph A GCOL, conflicts with CANTX1 */
+							 1 16 0x1 0x0	/* PB16 periph A GMDC */
+							 1 17 0x1 0x0	/* PB17 periph A GMDIO */
+							 1 27 0x2 0x0>;	/* PB27 periph B G125CKO */
+					};
+
+				};
+
+				macb1 {
+					pinctrl_macb1_rmii: macb1_rmii-0 {
+						atmel,pins =
+							<2 0 0x1 0x0	/* PC0 periph A ETX0, conflicts with TIOA3 */
+							 2 1 0x1 0x0	/* PC1 periph A ETX1, conflicts with TIOB3 */
+							 2 2 0x1 0x0	/* PC2 periph A ERX0, conflicts with TCLK3 */
+							 2 3 0x1 0x0	/* PC3 periph A ERX1, conflicts with TIOA4 */
+							 2 4 0x1 0x0	/* PC4 periph A ETXEN, conflicts with TIOB4 */
+							 2 5 0x1 0x0	/* PC5 periph A ECRSDV,conflicts with TCLK4 */
+							 2 6 0x1 0x0	/* PC6 periph A ERXER, conflicts with TIOA5 */
+							 2 7 0x1 0x0	/* PC7 periph A EREFCK, conflicts with TIOB5 */
+							 2 8 0x1 0x0	/* PC8 periph A EMDC, conflicts with TCLK5 */
+							 2 9 0x1 0x0>;	/* PC9 periph A EMDIO  */
+					};
+				};
+
+				mmc0 {
+					pinctrl_mmc0_clk_cmd_dat0: mmc0_clk_cmd_dat0 {
+						atmel,pins =
+							<3 9 0x1 0x0	/* PD9 periph A MCI0_CK */
+							 3 0 0x1 0x1	/* PD0 periph A MCI0_CDA with pullup */
+							 3 1 0x1 0x1>;	/* PD1 periph A MCI0_DA0 with pullup */
+					};
+					pinctrl_mmc0_dat1_3: mmc0_dat1_3 {
+						atmel,pins =
+							<3 2 0x1 0x1	/* PD2 periph A MCI0_DA1 with pullup */
+							 3 3 0x1 0x1	/* PD3 periph A MCI0_DA2 with pullup */
+							 3 4 0x1 0x1>;	/* PD4 periph A MCI0_DA3 with pullup */
+					};
+					pinctrl_mmc0_dat4_7: mmc0_dat4_7 {
+						atmel,pins =
+							<3 5 0x1 0x1	/* PD5 periph A MCI0_DA4 with pullup, conflicts with TIOA0, PWMH2 */
+							 3 6 0x1 0x1	/* PD6 periph A MCI0_DA5 with pullup, conflicts with TIOB0, PWML2 */
+							 3 7 0x1 0x1	/* PD7 periph A MCI0_DA6 with pullup, conlicts with TCLK0, PWMH3 */
+							 3 8 0x1 0x1>;	/* PD8 periph A MCI0_DA7 with pullup, conflicts with PWML3 */
+					};
+				};
+
+				mmc1 {
+					pinctrl_mmc1_clk_cmd_dat0: mmc1_clk_cmd_dat0 {
+						atmel,pins =
+							<1 24 0x1 0x0	/* PB24 periph A MCI1_CK, conflicts with GRX5 */
+							 1 19 0x1 0x1	/* PB19 periph A MCI1_CDA with pullup, conflicts with GTX4 */
+							 1 20 0x1 0x1>;	/* PB20 periph A MCI1_DA0 with pullup, conflicts with GTX5 */
+					};
+					pinctrl_mmc1_dat1_3: mmc1_dat1_3 {
+						atmel,pins =
+							<1 21 0x1 0x1	/* PB21 periph A MCI1_DA1 with pullup, conflicts with GTX6 */
+							 1 22 0x1 0x1	/* PB22 periph A MCI1_DA2 with pullup, conflicts with GTX7 */
+							 1 23 0x1 0x1>;	/* PB23 periph A MCI1_DA3 with pullup, conflicts with GRX4 */
+					};
+				};
+
+				mmc2 {
+					pinctrl_mmc2_clk_cmd_dat0: mmc2_clk_cmd_dat0 {
+						atmel,pins =
+							<2 15 0x1 0x0	/* PC15 periph A MCI2_CK, conflicts with PCK2 */
+							 2 10 0x1 0x1	/* PC10 periph A MCI2_CDA with pullup */
+							 2 11 0x1 0x1>;	/* PC11 periph A MCI2_DA0 with pullup */
+					};
+					pinctrl_mmc2_dat1_3: mmc2_dat1_3 {
+						atmel,pins =
+							<2 12 0x1 0x0	/* PC12 periph A MCI2_DA1 with pullup, conflicts with TIOA1 */
+							 2 13 0x1 0x0	/* PC13 periph A MCI2_DA2 with pullup, conflicts with TIOB1 */
+							 2 14 0x1 0x0>;	/* PC14 periph A MCI2_DA3 with pullup, conflicts with TCLK1 */
+					};
+				};
+
+				nand0 {
+					pinctrl_nand0_ale_cle: nand0_ale_cle-0 {
+						atmel,pins =
+							<4 21 0x1 0x1	/* PE21 periph A with pullup */
+							 4 22 0x1 0x1>;	/* PE22 periph A with pullup */
+					};
+				};
+
+				pioA: gpio@fffff200 {
+					compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
+					reg = <0xfffff200 0x100>;
+					interrupts = <6 4 1>;
+					#gpio-cells = <2>;
+					gpio-controller;
+					interrupt-controller;
+					#interrupt-cells = <2>;
+				};
+
+				pioB: gpio@fffff400 {
+					compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
+					reg = <0xfffff400 0x100>;
+					interrupts = <7 4 1>;
+					#gpio-cells = <2>;
+					gpio-controller;
+					interrupt-controller;
+					#interrupt-cells = <2>;
+				};
+
+				pioC: gpio@fffff600 {
+					compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
+					reg = <0xfffff600 0x100>;
+					interrupts = <8 4 1>;
+					#gpio-cells = <2>;
+					gpio-controller;
+					interrupt-controller;
+					#interrupt-cells = <2>;
+				};
+
+				pioD: gpio@fffff800 {
+					compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
+					reg = <0xfffff800 0x100>;
+					interrupts = <9 4 1>;
+					#gpio-cells = <2>;
+					gpio-controller;
+					interrupt-controller;
+					#interrupt-cells = <2>;
+				};
+
+				pioE: gpio@fffffa00 {
+					compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
+					reg = <0xfffffa00 0x100>;
+					interrupts = <10 4 1>;
+					#gpio-cells = <2>;
+					gpio-controller;
+					interrupt-controller;
+					#interrupt-cells = <2>;
+				};
+
+				spi0 {
+					pinctrl_spi0: spi0-0 {
+						atmel,pins =
+							<3 10 0x1 0x0	/* PD10 periph A SPI0_MISO pin */
+							 3 11 0x1 0x0	/* PD11 periph A SPI0_MOSI pin */
+							 3 12 0x1 0x0	/* PD12 periph A SPI0_SPCK pin */
+							 3 13 0x0 0x0>;	/* PD13 GPIO SPI0_NPCS0 pin */
+					};
+				};
+
+				spi1 {
+					pinctrl_spi1: spi1-0 {
+						atmel,pins =
+							<2 22 0x1 0x0	/* PC22 periph A SPI1_MISO pin */
+							 2 23 0x1 0x0	/* PC23 periph A SPI1_MOSI pin */
+							 2 24 0x1 0x0	/* PC24 periph A SPI1_SPCK pin */
+							 2 25 0x0 0x0>;	/* PC25 GPIO SPI1_NPCS0 pin */
+					};
+				};
+
+				ssc0 {
+					pinctrl_ssc0_tx: ssc0_tx {
+						atmel,pins =
+							<2 16 0x1 0x0	/* PC16 periph A TK0 */
+							 2 17 0x1 0x0	/* PC17 periph A TF0 */
+							 2 18 0x1 0x0>;	/* PC18 periph A TD0 */
+					};
+
+					pinctrl_ssc0_rx: ssc0_rx {
+						atmel,pins =
+							<2 19 0x1 0x0	/* PC19 periph A RK0 */
+							 2 20 0x1 0x0	/* PC20 periph A RF0 */
+							 2 21 0x1 0x0>;	/* PC21 periph A RD0 */
+					};
+				};
+
+				ssc1 {
+					pinctrl_ssc1_tx: ssc1_tx {
+						atmel,pins =
+							<1 2 0x2 0x0	/* PB2 periph B TK1, conflicts with GTX2 */
+							 1 3 0x2 0x0	/* PB3 periph B TF1, conflicts with GTX3 */
+							 1 6 0x2 0x0>;	/* PB6 periph B TD1, conflicts with TD1 */
+					};
+
+					pinctrl_ssc1_rx: ssc1_rx {
+						atmel,pins =
+							<1 7 0x2 0x0	/* PB7 periph B RK1, conflicts with EREFCK */
+							 1 10 0x2 0x0	/* PB10 periph B RF1, conflicts with GTXER */
+							 1 11 0x2 0x0>;	/* PB11 periph B RD1, conflicts with GRXCK */
+					};
+				};
+
+				uart0 {
+					pinctrl_uart0: uart0-0 {
+						atmel,pins =
+							<2 29 0x1 0x0	/* PC29 periph A, conflicts with PWMFI2, ISI_D8 */
+							 2 30 0x1 0x1>;	/* PC30 periph A with pullup, conflicts with ISI_PCK */
+					};
+				};
+
+				uart1 {
+					pinctrl_uart1: uart1-0 {
+						atmel,pins =
+							<0 30 0x2 0x0	/* PA30 periph B, conflicts with TWD0, ISI_VSYNC */
+							 0 31 0x2 0x1>;	/* PA31 periph B with pullup, conflicts with TWCK0, ISI_HSYNC */
+					};
+				};
+
+				usart0 {
+					pinctrl_usart0: usart0-0 {
+						atmel,pins =
+							<3 17 0x1 0x0	/* PD17 periph A */
+							 3 18 0x1 0x1>;	/* PD18 periph A with pullup */
+					};
+
+					pinctrl_usart0_rts_cts: usart0_rts_cts-0 {
+						atmel,pins =
+							<3 15 0x1 0x0	/* PD15 periph A, conflicts with SPI0_NPCS2, CANTX0 */
+							 3 16 0x1 0x0>;	/* PD16 periph A, conflicts with SPI0_NPCS3, PWMFI3 */
+					};
+				};
+
+				usart1 {
+					pinctrl_usart1: usart1-0 {
+						atmel,pins =
+							<1 28 0x1 0x0	/* PB28 periph A */
+							 1 29 0x1 0x1>;	/* PB29 periph A with pullup */
+					};
+
+					pinctrl_usart1_rts_cts: usart1_rts_cts-0 {
+						atmel,pins =
+							<1 26 0x1 0x0	/* PB26 periph A, conflicts with GRX7 */
+							 1 27 0x1 0x0>;	/* PB27 periph A, conflicts with G125CKO */
+					};
+				};
+
+				usart2 {
+					pinctrl_usart2: usart2-0 {
+						atmel,pins =
+							<4 25 0x2 0x0	/* PE25 periph B, conflicts with A25 */
+							 4 26 0x2 0x1>;	/* PE26 periph B with pullup, conflicts NCS0 */
+					};
+
+					pinctrl_usart2_rts_cts: usart2_rts_cts-0 {
+						atmel,pins =
+							<4 23 0x2 0x0	/* PE23 periph B, conflicts with A23 */
+							 4 24 0x2 0x0>;	/* PE24 periph B, conflicts with A24 */
+					};
+				};
+
+				usart3 {
+					pinctrl_usart3: usart3-0 {
+						atmel,pins =
+							<4 18 0x2 0x0	/* PE18 periph B, conflicts with A18 */
+							 4 19 0x2 0x1>;	/* PE19 periph B with pullup, conflicts with A19 */
+					};
+
+					pinctrl_usart3_rts_cts: usart3_rts_cts-0 {
+						atmel,pins =
+							<4 16 0x2 0x0	/* PE16 periph B, conflicts with A16 */
+							 4 17 0x2 0x0>;	/* PE17 periph B, conflicts with A17 */
+					};
+				};
+			};
+
+			pmc: pmc@fffffc00 {
+				compatible = "atmel,at91rm9200-pmc";
+				reg = <0xfffffc00 0x120>;
+			};
+
+			rstc@fffffe00 {
+				compatible = "atmel,at91sam9g45-rstc";
+				reg = <0xfffffe00 0x10>;
+			};
+
+			pit: timer@fffffe30 {
+				compatible = "atmel,at91sam9260-pit";
+				reg = <0xfffffe30 0xf>;
+				interrupts = <3 4 5>;
+			};
+
+			watchdog@fffffe40 {
+				compatible = "atmel,at91sam9260-wdt";
+				reg = <0xfffffe40 0x10>;
+				status = "disabled";
+			};
+
+			rtc@fffffeb0 {
+				compatible = "atmel,at91rm9200-rtc";
+				reg = <0xfffffeb0 0x30>;
+				interrupts = <1 4 7>;
+			};
+		};
+
+		usb0: gadget@00500000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "atmel,at91sam9rl-udc";
+			reg = <0x00500000 0x100000
+			       0xf8030000 0x4000>;
+			interrupts = <33 4 2>;
+			status = "disabled";
+
+			ep0 {
+				reg = <0>;
+				atmel,fifo-size = <64>;
+				atmel,nb-banks = <1>;
+			};
+
+			ep1 {
+				reg = <1>;
+				atmel,fifo-size = <1024>;
+				atmel,nb-banks = <3>;
+				atmel,can-dma;
+				atmel,can-isoc;
+			};
+
+			ep2 {
+				reg = <2>;
+				atmel,fifo-size = <1024>;
+				atmel,nb-banks = <3>;
+				atmel,can-dma;
+				atmel,can-isoc;
+			};
+
+			ep3 {
+				reg = <3>;
+				atmel,fifo-size = <1024>;
+				atmel,nb-banks = <2>;
+				atmel,can-dma;
+			};
+
+			ep4 {
+				reg = <4>;
+				atmel,fifo-size = <1024>;
+				atmel,nb-banks = <2>;
+				atmel,can-dma;
+			};
+
+			ep5 {
+				reg = <5>;
+				atmel,fifo-size = <1024>;
+				atmel,nb-banks = <2>;
+				atmel,can-dma;
+			};
+
+			ep6 {
+				reg = <6>;
+				atmel,fifo-size = <1024>;
+				atmel,nb-banks = <2>;
+				atmel,can-dma;
+			};
+
+			ep7 {
+				reg = <7>;
+				atmel,fifo-size = <1024>;
+				atmel,nb-banks = <2>;
+				atmel,can-dma;
+			};
+
+			ep8 {
+				reg = <8>;
+				atmel,fifo-size = <1024>;
+				atmel,nb-banks = <2>;
+			};
+
+			ep9 {
+				reg = <9>;
+				atmel,fifo-size = <1024>;
+				atmel,nb-banks = <2>;
+			};
+
+			ep10 {
+				reg = <10>;
+				atmel,fifo-size = <1024>;
+				atmel,nb-banks = <2>;
+			};
+
+			ep11 {
+				reg = <11>;
+				atmel,fifo-size = <1024>;
+				atmel,nb-banks = <2>;
+			};
+
+			ep12 {
+				reg = <12>;
+				atmel,fifo-size = <1024>;
+				atmel,nb-banks = <2>;
+			};
+
+			ep13 {
+				reg = <13>;
+				atmel,fifo-size = <1024>;
+				atmel,nb-banks = <2>;
+			};
+
+			ep14 {
+				reg = <14>;
+				atmel,fifo-size = <1024>;
+				atmel,nb-banks = <2>;
+			};
+
+			ep15 {
+				reg = <15>;
+				atmel,fifo-size = <1024>;
+				atmel,nb-banks = <2>;
+			};
+		};
+
+		usb1: ohci@00600000 {
+			compatible = "atmel,at91rm9200-ohci", "usb-ohci";
+			reg = <0x00600000 0x100000>;
+			interrupts = <32 4 2>;
+			status = "disabled";
+		};
+
+		usb2: ehci@00700000 {
+			compatible = "atmel,at91sam9g45-ehci", "usb-ehci";
+			reg = <0x00700000 0x100000>;
+			interrupts = <32 4 2>;
+			status = "disabled";
+		};
+
+		nand0: nand@60000000 {
+			compatible = "atmel,at91rm9200-nand";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <	0x60000000 0x01000000	/* EBI CS3 */
+				0xffffc070 0x00000490	/* SMC PMECC regs */
+				0xffffc500 0x00000100	/* SMC PMECC Error Location regs */
+				0x00100000 0x00100000	/* ROM code */
+				0x70000000 0x10000000	/* NFC Command Registers */
+				0xffffc000 0x00000070	/* NFC HSMC regs */
+				0x00200000 0x00100000	/* NFC SRAM banks */
+				>;
+			interrupts = <5 4 6>;
+			atmel,nand-addr-offset = <21>;
+			atmel,nand-cmd-offset = <22>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_nand0_ale_cle>;
+			atmel,pmecc-lookup-table-offset = <0x10000 0x18000>;
+			status = "disabled";
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/sama5d31ek.dts b/arch/arm/boot/dts/sama5d31ek.dts
new file mode 100644
index 0000000..fa5d216
--- /dev/null
+++ b/arch/arm/boot/dts/sama5d31ek.dts
@@ -0,0 +1,51 @@
+/*
+ * sama5d31ek.dts - Device Tree file for SAMA5D31-EK board
+ *
+ *  Copyright (C) 2013 Atmel,
+ *                2013 Ludovic Desroches <ludovic.desroches@atmel.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+/dts-v1/;
+/include/ "sama5d3xmb.dtsi"
+/include/ "sama5d3xdm.dtsi"
+
+/ {
+	model = "Atmel SAMA5D31-EK";
+	compatible = "atmel,sama5d31ek", "atmel,sama5d3xmb", "atmel,sama5d3xcm", "atmel,sama5d3", "atmel,sama5";
+
+	ahb {
+		apb {
+			spi0: spi@f0004000 {
+				status = "okay";
+			};
+
+			ssc0: ssc@f0008000 {
+				status = "okay";
+			};
+
+			i2c0: i2c@f0014000 {
+				status = "okay";
+			};
+
+			i2c1: i2c@f0018000 {
+				status = "okay";
+			};
+
+			macb1: ethernet@f802c000 {
+				status = "okay";
+			};
+		};
+	};
+
+	leds {
+		d3 {
+			label = "d3";
+			gpios = <&pioE 24 0>;
+		};
+	};
+
+	sound {
+		status = "okay";
+	};
+};
diff --git a/arch/arm/boot/dts/sama5d33ek.dts b/arch/arm/boot/dts/sama5d33ek.dts
new file mode 100644
index 0000000..c38c943
--- /dev/null
+++ b/arch/arm/boot/dts/sama5d33ek.dts
@@ -0,0 +1,44 @@
+/*
+ * sama5d33ek.dts - Device Tree file for SAMA5D33-EK board
+ *
+ *  Copyright (C) 2013 Atmel,
+ *                2013 Ludovic Desroches <ludovic.desroches@atmel.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+/dts-v1/;
+/include/ "sama5d3xmb.dtsi"
+/include/ "sama5d3xdm.dtsi"
+
+/ {
+	model = "Atmel SAMA5D33-EK";
+	compatible = "atmel,sama5d33ek", "atmel,sama5d3xmb", "atmel,sama5d3xcm", "atmel,sama5d3", "atmel,sama5";
+
+	ahb {
+		apb {
+			spi0: spi@f0004000 {
+				status = "okay";
+			};
+
+			ssc0: ssc@f0008000 {
+				status = "okay";
+			};
+
+			i2c0: i2c@f0014000 {
+				status = "okay";
+			};
+
+			i2c1: i2c@f0018000 {
+				status = "okay";
+			};
+
+			macb0: ethernet@f0028000 {
+				status = "okay";
+			};
+		};
+	};
+
+	sound {
+		status = "okay";
+	};
+};
diff --git a/arch/arm/boot/dts/sama5d34ek.dts b/arch/arm/boot/dts/sama5d34ek.dts
new file mode 100644
index 0000000..d2739f8
--- /dev/null
+++ b/arch/arm/boot/dts/sama5d34ek.dts
@@ -0,0 +1,61 @@
+/*
+ * sama5d34ek.dts - Device Tree file for SAMA5D34-EK board
+ *
+ *  Copyright (C) 2013 Atmel,
+ *                2013 Ludovic Desroches <ludovic.desroches@atmel.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+/dts-v1/;
+/include/ "sama5d3xmb.dtsi"
+/include/ "sama5d3xdm.dtsi"
+
+/ {
+	model = "Atmel SAMA5D34-EK";
+	compatible = "atmel,sama5d34ek", "atmel,sama5ek", "atmel,sama5d3xmb", "atmel,sama5d3xcm", "atmel,sama5d3", "atmel,sama5";
+
+	ahb {
+		apb {
+			spi0: spi@f0004000 {
+				status = "okay";
+			};
+
+			ssc0: ssc@f0008000 {
+				status = "okay";
+			};
+
+			can0: can@f000c000 {
+				status = "okay";
+			};
+
+			i2c0: i2c@f0014000 {
+				status = "okay";
+			};
+
+			i2c1: i2c@f0018000 {
+				status = "okay";
+
+				24c256@50 {
+					compatible = "24c256";
+					reg = <0x50>;
+					pagesize = <64>;
+				};
+			};
+
+			macb0: ethernet@f0028000 {
+				status = "okay";
+			};
+		};
+	};
+
+	leds {
+		d3 {
+			label = "d3";
+			gpios = <&pioE 24 0>;
+		};
+	};
+
+	sound {
+		status = "okay";
+	};
+};
diff --git a/arch/arm/boot/dts/sama5d35ek.dts b/arch/arm/boot/dts/sama5d35ek.dts
new file mode 100644
index 0000000..a488fc4
--- /dev/null
+++ b/arch/arm/boot/dts/sama5d35ek.dts
@@ -0,0 +1,56 @@
+/*
+ * sama5d35ek.dts - Device Tree file for SAMA5D35-EK board
+ *
+ *  Copyright (C) 2013 Atmel,
+ *                2013 Ludovic Desroches <ludovic.desroches@atmel.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+/dts-v1/;
+/include/ "sama5d3xmb.dtsi"
+
+/ {
+	model = "Atmel SAMA5D35-EK";
+	compatible = "atmel,sama5d35ek", "atmel,sama5d3xmb", "atmel,sama5d3xcm", "atmel,sama5d3", "atmel,sama5";
+
+	ahb {
+		apb {
+			spi0: spi@f0004000 {
+				status = "okay";
+			};
+
+			can0: can@f000c000 {
+				status = "okay";
+			};
+
+			i2c1: i2c@f0018000 {
+				status = "okay";
+			};
+
+			macb0: ethernet@f0028000 {
+				status = "okay";
+			};
+
+			isi: isi@f0034000 {
+				status = "okay";
+			};
+
+			macb1: ethernet@f802c000 {
+				status = "okay";
+			};
+		};
+	};
+
+	gpio_keys {
+		compatible = "gpio-keys";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		pb_user1 {
+			label = "pb_user1";
+			gpios = <&pioE 27 0>;
+			linux,code = <0x100>;
+			gpio-key,wakeup;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/sama5d3xcm.dtsi b/arch/arm/boot/dts/sama5d3xcm.dtsi
new file mode 100644
index 0000000..1f8ed40
--- /dev/null
+++ b/arch/arm/boot/dts/sama5d3xcm.dtsi
@@ -0,0 +1,91 @@
+/*
+ * sama5d3xcm.dtsi - Device Tree Include file for SAMA5D3x CPU Module
+ *
+ *  Copyright (C) 2013 Atmel,
+ *                2013 Ludovic Desroches <ludovic.desroches@atmel.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+/include/ "sama5d3.dtsi"
+
+/ {
+	compatible = "atmel,samad3xcm", "atmel,sama5d3", "atmel,sama5";
+
+	chosen {
+		bootargs = "console=ttyS0,115200 rootfstype=ubifs ubi.mtd=5 root=ubi0:rootfs";
+	};
+
+	memory {
+		reg = <0x20000000 0x20000000>;
+	};
+
+	clocks {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		main_clock: clock@0 {
+			compatible = "atmel,osc", "fixed-clock";
+			clock-frequency = <12000000>;
+		};
+	};
+
+	ahb {
+		apb {
+			macb0: ethernet@f0028000 {
+				phy-mode = "rgmii";
+			};
+		};
+
+		nand0: nand@60000000 {
+			nand-bus-width = <8>;
+			nand-ecc-mode = "hw";
+			atmel,has-pmecc;
+			atmel,pmecc-cap = <4>;
+			atmel,pmecc-sector-size = <512>;
+			atmel,has-nfc;
+			atmel,use-nfc-sram;
+			nand-on-flash-bbt;
+			status = "okay";
+
+			at91bootstrap@0 {
+				label = "at91bootstrap";
+				reg = <0x0 0x40000>;
+			};
+
+			bootloader@40000 {
+				label = "bootloader";
+				reg = <0x40000 0x80000>;
+			};
+
+			bootloaderenv@c0000 {
+				label = "bootloader env";
+				reg = <0xc0000 0xc0000>;
+			};
+
+			dtb@180000 {
+				label = "device tree";
+				reg = <0x180000 0x80000>;
+			};
+
+			kernel@200000 {
+				label = "kernel";
+				reg = <0x200000 0x600000>;
+			};
+
+			rootfs@800000 {
+				label = "rootfs";
+				reg = <0x800000 0x0f800000>;
+			};
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		d2 {
+			label = "d2";
+			gpios = <&pioE 25 1>;	/* PE25, conflicts with A25, RXD2 */
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/sama5d3xdm.dtsi b/arch/arm/boot/dts/sama5d3xdm.dtsi
new file mode 100644
index 0000000..4b8830e
--- /dev/null
+++ b/arch/arm/boot/dts/sama5d3xdm.dtsi
@@ -0,0 +1,42 @@
+/*
+ * sama5d3dm.dtsi - Device Tree file for SAMA5 display module
+ *
+ *  Copyright (C) 2013 Atmel,
+ *                2013 Ludovic Desroches <ludovic.desroches@atmel.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+/ {
+	ahb {
+		apb {
+			i2c1: i2c@f0018000 {
+				qt1070: keyboard@1b {
+					compatible = "qt1070";
+					reg = <0x1b>;
+					interrupt-parent = <&pioE>;
+					interrupts = <31 0x0>;
+					pinctrl-names = "default";
+					pinctrl-0 = <&pinctrl_qt1070_irq>;
+				};
+			};
+
+			adc0: adc@f8018000 {
+				status = "disabled";
+			};
+
+			tsadcc: tsadcc@f8018000 {
+				status = "okay";
+			};
+
+			pinctrl@fffff200 {
+				board {
+					pinctrl_qt1070_irq: qt1070_irq {
+						atmel,pins =
+							<4 31 0x0 0x5>; /* PE31 GPIO with pull up deglith */
+					};
+				};
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/sama5d3xmb.dtsi b/arch/arm/boot/dts/sama5d3xmb.dtsi
new file mode 100644
index 0000000..661d7ca
--- /dev/null
+++ b/arch/arm/boot/dts/sama5d3xmb.dtsi
@@ -0,0 +1,166 @@
+/*
+ * sama5d3xmb.dts - Device Tree file for SAMA5D3x mother board
+ *
+ *  Copyright (C) 2013 Atmel,
+ *                2013 Ludovic Desroches <ludovic.desroches@atmel.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+/include/ "sama5d3xcm.dtsi"
+
+/ {
+	compatible = "atmel,sama5d3xmb", "atmel,sama5d3xcm", "atmel,sama5d3", "atmel,sama5";
+
+	ahb {
+		apb {
+			mmc0: mmc@f0000000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_mmc0_clk_cmd_dat0 &pinctrl_mmc0_dat1_3 &pinctrl_mmc0_cd>;
+				status = "okay";
+				slot@0 {
+					reg = <0>;
+					bus-width = <4>;
+					cd-gpios = <&pioD 17 0>;
+				};
+			};
+
+			spi0: spi@f0004000 {
+				m25p80@0 {
+					compatible = "atmel,at25df321a";
+					spi-max-frequency = <50000000>;
+					reg = <0>;
+				};
+			};
+
+			/*
+			 * i2c0 conflicts with ISI:
+			 * disable it to allow the use of ISI
+			 * can not enable audio when i2c0 disabled
+			 */
+			i2c0: i2c@f0014000 {
+				wm8904: wm8904@1a {
+					compatible = "wm8904";
+					reg = <0x1a>;
+				};
+			};
+
+			usart1: serial@f0020000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_usart1 &pinctrl_usart1_rts_cts>;
+				status = "okay";
+			};
+
+			isi: isi@f0034000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_isi &pinctrl_isi_pck_as_mck &pinctrl_isi_power &pinctrl_isi_reset>;
+			};
+
+			mmc1: mmc@f8000000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_mmc1_clk_cmd_dat0 &pinctrl_mmc1_dat1_3 &pinctrl_mmc1_cd>;
+				status = "okay";
+				slot@0 {
+					reg = <0>;
+					bus-width = <4>;
+					cd-gpios = <&pioD 18 0>;
+				};
+			};
+
+			adc0: adc@f8018000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <
+					&pinctrl_adc0_adtrg
+					&pinctrl_adc0_ad0
+					&pinctrl_adc0_ad1
+					&pinctrl_adc0_ad2
+					&pinctrl_adc0_ad3
+					&pinctrl_adc0_ad4
+					>;
+				status = "okay";
+			};
+
+			macb1: ethernet@f802c000 {
+				phy-mode = "rmii";
+			};
+
+			pinctrl@fffff200 {
+				board {
+					pinctrl_mmc0_cd: mmc0_cd {
+						atmel,pins =
+							<3 17 0x0 0x5>; /* PD17 GPIO with pullup deglitch */
+					};
+
+					pinctrl_mmc1_cd: mmc1_cd {
+						atmel,pins =
+							<3 18 0x0 0x5>; /* PD18 GPIO with pullup deglitch */
+					};
+
+					pinctrl_pck0_as_audio_mck: pck0_as_audio_mck {
+						atmel,pins =
+							<3 30 0x2 0x0>;	/* PD30 periph B */
+					};
+
+					pinctrl_isi_reset: isi_reset-0 {
+						atmel,pins =
+							<4 24 0x0 0x0>;   /* PE24 gpio */
+					};
+
+					pinctrl_isi_power: isi_power-0 {
+						atmel,pins =
+							<4 29 0x0 0x0>; /* PE29 gpio */
+					};
+
+					pinctrl_usba_vbus: usba_vbus {
+						atmel,pins =
+							<3 29 0x0 0x4>; /* PD29 GPIO with deglitch */
+					};
+				};
+			};
+
+			dbgu: serial@ffffee00 {
+				status = "okay";
+			};
+
+			watchdog@fffffe40 {
+				status = "okay";
+			};
+		};
+
+		usb0: gadget@00500000 {
+			atmel,vbus-gpio = <&pioD 29 0>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_usba_vbus>;
+			status = "okay";
+		};
+
+		usb1: ohci@00600000 {
+			num-ports = <3>;
+			atmel,vbus-gpio = <&pioD 25 0
+					   &pioD 26 1
+					   &pioD 27 1
+					  >;
+			status = "okay";
+		};
+
+		usb2: ehci@00700000 {
+			status = "okay";
+		};
+	};
+
+	sound {
+		compatible = "atmel,sama5d3ek-wm8904";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_pck0_as_audio_mck>;
+
+		atmel,model = "wm8904 @ SAMA5D3EK";
+		atmel,audio-routing =
+			"Headphone Jack", "HPOUTL",
+			"Headphone Jack", "HPOUTR",
+			"IN2L", "Line In Jack",
+			"IN2R", "Line In Jack",
+			"IN1L", "Mic";
+
+		atmel,ssc-controller = <&ssc0>;
+		atmel,audio-codec = <&wm8904>;
+	};
+};
diff --git a/arch/arm/boot/dts/sh73a0-kzm9g-reference.dts b/arch/arm/boot/dts/sh73a0-kzm9g-reference.dts
new file mode 100644
index 0000000..5972abb
--- /dev/null
+++ b/arch/arm/boot/dts/sh73a0-kzm9g-reference.dts
@@ -0,0 +1,79 @@
+/*
+ * Device Tree Source for the KZM-A9-GT board
+ *
+ * Copyright (C) 2012 Horms Solutions Ltd.
+ *
+ * Based on sh73a0-kzm9g.dts
+ * Copyright (C) 2012 Renesas Solutions Corp.
+ *
+ * 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.
+ */
+
+/dts-v1/;
+/include/ "sh73a0.dtsi"
+
+/ {
+	model = "KZM-A9-GT";
+	compatible = "renesas,kzm9g-reference", "renesas,sh73a0";
+
+	chosen {
+		bootargs = "console=tty0 console=ttySC4,115200 root=/dev/nfs ip=dhcp ignore_loglevel earlyprintk=sh-sci.4,115200";
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x41000000 0x1e800000>;
+	};
+
+	reg_1p8v: regulator@0 {
+		compatible = "regulator-fixed";
+		regulator-name = "fixed-1.8V";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+
+	reg_3p3v: regulator@1 {
+		compatible = "regulator-fixed";
+		regulator-name = "fixed-3.3V";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+
+	lan9220@10000000 {
+		compatible = "smsc,lan9220", "smsc,lan9115";
+		reg = <0x10000000 0x100>;
+		phy-mode = "mii";
+		interrupt-parent = <&irqpin0>;
+		interrupts = <3 0>;	/* active low */
+		reg-io-width = <4>;
+		smsc,irq-push-pull;
+		smsc,save-mac-address;
+		vddvario-supply = <&reg_1p8v>;
+		vdd33a-supply = <&reg_3p3v>;
+	};
+};
+
+&mmcif {
+	bus-width = <8>;
+	vmmc-supply = <&reg_1p8v>;
+	status = "okay";
+};
+
+&sdhi0 {
+	vmmc-supply = <&reg_3p3v>;
+	bus-width = <4>;
+	status = "okay";
+};
+
+&sdhi2 {
+	vmmc-supply = <&reg_3p3v>;
+	bus-width = <4>;
+	broken-cd;
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/sh73a0-reference.dtsi b/arch/arm/boot/dts/sh73a0-reference.dtsi
deleted file mode 100644
index d4bb012..0000000
--- a/arch/arm/boot/dts/sh73a0-reference.dtsi
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Device Tree Source for the SH73A0 SoC
- *
- * Copyright (C) 2012 Renesas Solutions Corp.
- *
- * 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/ "sh73a0.dtsi"
-
-/ {
-	compatible = "renesas,sh73a0";
-
-	mmcif: mmcif@0x10010000 {
-		compatible = "renesas,sh-mmcif";
-		reg = <0xe6bd0000 0x100>;
-		interrupt-parent = <&gic>;
-		interrupts = <0 140 0x4
-			      0 141 0x4>;
-		reg-io-width = <4>;
-	};
-};
diff --git a/arch/arm/boot/dts/sh73a0.dtsi b/arch/arm/boot/dts/sh73a0.dtsi
index 8a59465..ec40bf7 100644
--- a/arch/arm/boot/dts/sh73a0.dtsi
+++ b/arch/arm/boot/dts/sh73a0.dtsi
@@ -38,6 +38,87 @@
 		      <0xf0000100 0x100>;
 	};
 
+	irqpin0: irqpin@e6900000 {
+		compatible = "renesas,intc-irqpin";
+		#interrupt-cells = <2>;
+		interrupt-controller;
+		reg = <0xe6900000 4>,
+			<0xe6900010 4>,
+			<0xe6900020 1>,
+			<0xe6900040 1>,
+			<0xe6900060 1>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 1 0x4
+			      0 2 0x4
+			      0 3 0x4
+			      0 4 0x4
+			      0 5 0x4
+			      0 6 0x4
+			      0 7 0x4
+			      0 8 0x4>;
+	};
+
+	irqpin1: irqpin@e6900004 {
+		compatible = "renesas,intc-irqpin";
+		#interrupt-cells = <2>;
+		interrupt-controller;
+		reg = <0xe6900004 4>,
+			<0xe6900014 4>,
+			<0xe6900024 1>,
+			<0xe6900044 1>,
+			<0xe6900064 1>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 9 0x4
+			      0 10 0x4
+			      0 11 0x4
+			      0 12 0x4
+			      0 13 0x4
+			      0 14 0x4
+			      0 15 0x4
+			      0 16 0x4>;
+		control-parent;
+	};
+
+	irqpin2: irqpin@e6900008 {
+		compatible = "renesas,intc-irqpin";
+		#interrupt-cells = <2>;
+		interrupt-controller;
+		reg = <0xe6900008 4>,
+			<0xe6900018 4>,
+			<0xe6900028 1>,
+			<0xe6900048 1>,
+			<0xe6900068 1>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 17 0x4
+			      0 18 0x4
+			      0 19 0x4
+			      0 20 0x4
+			      0 21 0x4
+			      0 22 0x4
+			      0 23 0x4
+			      0 24 0x4>;
+	};
+
+	irqpin3: irqpin@e690000c {
+		compatible = "renesas,intc-irqpin";
+		#interrupt-cells = <2>;
+		interrupt-controller;
+		reg = <0xe690000c 4>,
+			<0xe690001c 4>,
+			<0xe690002c 1>,
+			<0xe690004c 1>,
+			<0xe690006c 1>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 25 0x4
+			      0 26 0x4
+			      0 27 0x4
+			      0 28 0x4
+			      0 29 0x4
+			      0 30 0x4
+			      0 31 0x4
+			      0 32 0x4>;
+	};
+
 	i2c0: i2c@0xe6820000 {
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -97,4 +178,48 @@
 			      0 189 0x4
 			      0 190 0x4>;
 	};
+
+	mmcif: mmcif@0x10010000 {
+		compatible = "renesas,sh-mmcif";
+		reg = <0xe6bd0000 0x100>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 140 0x4
+			      0 141 0x4>;
+		reg-io-width = <4>;
+		status = "disabled";
+	};
+
+	sdhi0: sdhi@0xee100000 {
+		compatible = "renesas,r8a7740-sdhi";
+		reg = <0xee100000 0x100>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 83 4
+				0 84 4
+				0 85 4>;
+		cap-sd-highspeed;
+		status = "disabled";
+	};
+
+	/* SDHI1 and SDHI2 have no CD pins, no need for CD IRQ */
+	sdhi1: sdhi@0xee120000 {
+		compatible = "renesas,r8a7740-sdhi";
+		reg = <0xee120000 0x100>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 88 4
+				0 89 4>;
+		toshiba,mmc-wrprotect-disable;
+		cap-sd-highspeed;
+		status = "disabled";
+	};
+
+	sdhi2: sdhi@0xee140000 {
+		compatible = "renesas,r8a7740-sdhi";
+		reg = <0xee140000 0x100>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 104 4
+				0 105 4>;
+		toshiba,mmc-wrprotect-disable;
+		cap-sd-highspeed;
+		status = "disabled";
+	};
 };
diff --git a/arch/arm/boot/dts/snowball.dts b/arch/arm/boot/dts/snowball.dts
index d3ec32f..db5db24 100644
--- a/arch/arm/boot/dts/snowball.dts
+++ b/arch/arm/boot/dts/snowball.dts
@@ -299,6 +299,10 @@
 			};
 
 			ab8500 {
+				ab8500-gpio {
+					compatible = "stericsson,ab8500-gpio";
+				};
+
 				ab8500-regulators {
 					ab8500_ldo_aux1_reg: ab8500_ldo_aux1 {
 						regulator-name = "V-DISPLAY";
diff --git a/arch/arm/boot/dts/spear1310.dtsi b/arch/arm/boot/dts/spear1310.dtsi
index 1513c19..122ae94 100644
--- a/arch/arm/boot/dts/spear1310.dtsi
+++ b/arch/arm/boot/dts/spear1310.dtsi
@@ -89,7 +89,7 @@
 		pinmux: pinmux@e0700000 {
 			compatible = "st,spear1310-pinmux";
 			reg = <0xe0700000 0x1000>;
-			#gpio-range-cells = <2>;
+			#gpio-range-cells = <3>;
 		};
 
 		apb {
@@ -212,7 +212,7 @@
 				interrupt-controller;
 				gpio-controller;
 				#gpio-cells = <2>;
-				gpio-ranges = <&pinmux 0 246>;
+				gpio-ranges = <&pinmux 0 0 246>;
 				status = "disabled";
 
 				st-plgpio,ngpio = <246>;
diff --git a/arch/arm/boot/dts/spear1340.dtsi b/arch/arm/boot/dts/spear1340.dtsi
index 34da11a..c511c47 100644
--- a/arch/arm/boot/dts/spear1340.dtsi
+++ b/arch/arm/boot/dts/spear1340.dtsi
@@ -63,7 +63,7 @@
 		pinmux: pinmux@e0700000 {
 			compatible = "st,spear1340-pinmux";
 			reg = <0xe0700000 0x1000>;
-			#gpio-range-cells = <2>;
+			#gpio-range-cells = <3>;
 		};
 
 		pwm: pwm@e0180000 {
@@ -127,7 +127,7 @@
 				interrupt-controller;
 				gpio-controller;
 				#gpio-cells = <2>;
-				gpio-ranges = <&pinmux 0 252>;
+				gpio-ranges = <&pinmux 0 0 252>;
 				status = "disabled";
 
 				st-plgpio,ngpio = <250>;
diff --git a/arch/arm/boot/dts/spear310.dtsi b/arch/arm/boot/dts/spear310.dtsi
index ab45b8c..9537208 100644
--- a/arch/arm/boot/dts/spear310.dtsi
+++ b/arch/arm/boot/dts/spear310.dtsi
@@ -25,7 +25,7 @@
 		pinmux: pinmux@b4000000 {
 			compatible = "st,spear310-pinmux";
 			reg = <0xb4000000 0x1000>;
-			#gpio-range-cells = <2>;
+			#gpio-range-cells = <3>;
 		};
 
 		fsmc: flash@44000000 {
@@ -102,7 +102,7 @@
 				interrupt-controller;
 				gpio-controller;
 				#gpio-cells = <2>;
-				gpio-ranges = <&pinmux 0 102>;
+				gpio-ranges = <&pinmux 0 0 102>;
 				status = "disabled";
 
 				st-plgpio,ngpio = <102>;
diff --git a/arch/arm/boot/dts/spear320.dtsi b/arch/arm/boot/dts/spear320.dtsi
index caa5520..ffea342 100644
--- a/arch/arm/boot/dts/spear320.dtsi
+++ b/arch/arm/boot/dts/spear320.dtsi
@@ -24,7 +24,7 @@
 		pinmux: pinmux@b3000000 {
 			compatible = "st,spear320-pinmux";
 			reg = <0xb3000000 0x1000>;
-			#gpio-range-cells = <2>;
+			#gpio-range-cells = <3>;
 		};
 
 		clcd@90000000 {
@@ -130,7 +130,7 @@
 				interrupt-controller;
 				gpio-controller;
 				#gpio-cells = <2>;
-				gpio-ranges = <&pinmux 0 102>;
+				gpio-ranges = <&pinmux 0 0 102>;
 				status = "disabled";
 
 				st-plgpio,ngpio = <102>;
diff --git a/arch/arm/boot/dts/stuib.dtsi b/arch/arm/boot/dts/stuib.dtsi
index 39446a2..615392a 100644
--- a/arch/arm/boot/dts/stuib.dtsi
+++ b/arch/arm/boot/dts/stuib.dtsi
@@ -15,7 +15,7 @@
 			stmpe1601: stmpe1601@40 {
 				compatible = "st,stmpe1601";
 				reg = <0x40>;
-				interrupts = <26 0x1>;
+				interrupts = <26 0x2>;
 				interrupt-parent = <&gpio6>;
 				interrupt-controller;
 
diff --git a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
index 5cab825..88e2dc1 100644
--- a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
+++ b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
@@ -27,6 +27,15 @@
 	};
 
 	soc {
+		pinctrl@01c20800 {
+			led_pins_cubieboard: led_pins@0 {
+				allwinner,pins = "PH20", "PH21";
+				allwinner,function = "gpio_out";
+				allwinner,drive = <1>;
+				allwinner,pull = <0>;
+			};
+		};
+
 		uart0: uart@01c28000 {
 			status = "okay";
 		};
@@ -35,4 +44,21 @@
 			status = "okay";
 		};
 	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&led_pins_cubieboard>;
+
+		blue {
+			label = "cubieboard::blue";
+			gpios = <&pio 7 21 0>; /* LED1 */
+		};
+
+		green {
+			label = "cubieboard::green";
+			gpios = <&pio 7 20 0>; /* LED2 */
+			linux,default-trigger = "heartbeat";
+		};
+	};
 };
diff --git a/arch/arm/boot/dts/sun4i-a10-mini-xplus.dts b/arch/arm/boot/dts/sun4i-a10-mini-xplus.dts
new file mode 100644
index 0000000..4a7c35d
--- /dev/null
+++ b/arch/arm/boot/dts/sun4i-a10-mini-xplus.dts
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2012 Maxime Ripard
+ *
+ * Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * 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
+ */
+
+/dts-v1/;
+/include/ "sun4i-a10.dtsi"
+
+/ {
+	model = "PineRiver Mini X-Plus";
+	compatible = "pineriver,mini-xplus", "allwinner,sun4i-a10";
+
+	chosen {
+		bootargs = "earlyprintk console=ttyS0,115200";
+	};
+
+	soc {
+		uart0: uart@01c28000 {
+			pinctrl-names = "default";
+			pinctrl-0 = <&uart0_pins_a>;
+			status = "okay";
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi
index f99f60d..03d2b53 100644
--- a/arch/arm/boot/dts/sun4i-a10.dtsi
+++ b/arch/arm/boot/dts/sun4i-a10.dtsi
@@ -18,11 +18,13 @@
 	};
 
 	soc {
-		pinctrl@01c20800 {
+		pio: pinctrl@01c20800 {
 			compatible = "allwinner,sun4i-a10-pinctrl";
 			reg = <0x01c20800 0x400>;
+			gpio-controller;
 			#address-cells = <1>;
 			#size-cells = <0>;
+			#gpio-cells = <3>;
 
 			uart0_pins_a: uart0@0 {
 				allwinner,pins = "PB22", "PB23";
diff --git a/arch/arm/boot/dts/sun5i-a13-olinuxino.dts b/arch/arm/boot/dts/sun5i-a13-olinuxino.dts
index 4a1e45d..33d1c7e 100644
--- a/arch/arm/boot/dts/sun5i-a13-olinuxino.dts
+++ b/arch/arm/boot/dts/sun5i-a13-olinuxino.dts
@@ -23,10 +23,30 @@
 	};
 
 	soc {
+		pinctrl@01c20800 {
+			led_pins_olinuxino: led_pins@0 {
+				allwinner,pins = "PG9";
+				allwinner,function = "gpio_out";
+				allwinner,drive = <1>;
+				allwinner,pull = <0>;
+			};
+		};
+
 		uart1: uart@01c28400 {
 			pinctrl-names = "default";
 			pinctrl-0 = <&uart1_pins_b>;
 			status = "okay";
 		};
 	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&led_pins_olinuxino>;
+
+		power {
+			gpios = <&pio 6 9 0>;
+			default-state = "on";
+		};
+	};
 };
diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi
index e112189..945bfac 100644
--- a/arch/arm/boot/dts/sun5i-a13.dtsi
+++ b/arch/arm/boot/dts/sun5i-a13.dtsi
@@ -19,11 +19,13 @@
 	};
 
 	soc {
-		pinctrl@01c20800 {
+		pio: pinctrl@01c20800 {
 			compatible = "allwinner,sun5i-a13-pinctrl";
 			reg = <0x01c20800 0x400>;
+			gpio-controller;
 			#address-cells = <1>;
 			#size-cells = <0>;
+			#gpio-cells = <3>;
 
 			uart1_pins_a: uart1@0 {
 				allwinner,pins = "PE10", "PE11";
diff --git a/arch/arm/boot/dts/sunxi.dtsi b/arch/arm/boot/dts/sunxi.dtsi
index 8b36abe..acf7777 100644
--- a/arch/arm/boot/dts/sunxi.dtsi
+++ b/arch/arm/boot/dts/sunxi.dtsi
@@ -24,13 +24,90 @@
 
 	clocks {
 		#address-cells = <1>;
-		#size-cells = <0>;
+		#size-cells = <1>;
+		ranges;
 
-		osc: oscillator {
+		/*
+		 * This is a dummy clock, to be used as placeholder on
+		 * other mux clocks when a specific parent clock is not
+		 * yet implemented. It should be dropped when the driver
+		 * is complete.
+		 */
+		dummy: dummy {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <0>;
+		};
+
+		osc24M_fixed: osc24M_fixed {
 			#clock-cells = <0>;
 			compatible = "fixed-clock";
 			clock-frequency = <24000000>;
 		};
+
+		osc24M: osc24M@01c20050 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sunxi-osc-clk";
+			reg = <0x01c20050 0x4>;
+			clocks = <&osc24M_fixed>;
+		};
+
+		osc32k: osc32k {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <32768>;
+		};
+
+		pll1: pll1@01c20000 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sunxi-pll1-clk";
+			reg = <0x01c20000 0x4>;
+			clocks = <&osc24M>;
+		};
+
+		/* dummy is 200M */
+		cpu: cpu@01c20054 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sunxi-cpu-clk";
+			reg = <0x01c20054 0x4>;
+			clocks = <&osc32k>, <&osc24M>, <&pll1>, <&dummy>;
+		};
+
+		axi: axi@01c20054 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sunxi-axi-clk";
+			reg = <0x01c20054 0x4>;
+			clocks = <&cpu>;
+		};
+
+		ahb: ahb@01c20054 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sunxi-ahb-clk";
+			reg = <0x01c20054 0x4>;
+			clocks = <&axi>;
+		};
+
+		apb0: apb0@01c20054 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sunxi-apb0-clk";
+			reg = <0x01c20054 0x4>;
+			clocks = <&ahb>;
+		};
+
+		/* dummy is pll62 */
+		apb1_mux: apb1_mux@01c20058 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sunxi-apb1-mux-clk";
+			reg = <0x01c20058 0x4>;
+			clocks = <&osc24M>, <&dummy>, <&osc32k>;
+		};
+
+		apb1: apb1@01c20058 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sunxi-apb1-clk";
+			reg = <0x01c20058 0x4>;
+			clocks = <&apb1_mux>;
+		};
 	};
 
 	soc {
@@ -44,7 +121,7 @@
 			compatible = "allwinner,sunxi-timer";
 			reg = <0x01c20c00 0x90>;
 			interrupts = <22>;
-			clocks = <&osc>;
+			clocks = <&osc24M>;
 		};
 
 		wdt: watchdog@01c20c90 {
diff --git a/arch/arm/boot/dts/tegra114-dalmore.dts b/arch/arm/boot/dts/tegra114-dalmore.dts
index a30aca6..6b7f0ab 100644
--- a/arch/arm/boot/dts/tegra114-dalmore.dts
+++ b/arch/arm/boot/dts/tegra114-dalmore.dts
@@ -10,12 +10,916 @@
 		reg = <0x80000000 0x40000000>;
 	};
 
+	pinmux {
+		pinctrl-names = "default";
+		pinctrl-0 = <&state_default>;
+
+		state_default: pinmux {
+			clk1_out_pw4 {
+				nvidia,pins = "clk1_out_pw4";
+				nvidia,function = "extperiph1";
+				nvidia,pull = <0>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <0>;
+			};
+			dap1_din_pn1 {
+				nvidia,pins = "dap1_din_pn1";
+				nvidia,function = "i2s0";
+				nvidia,pull = <0>;
+				nvidia,tristate = <1>;
+				nvidia,enable-input = <1>;
+			};
+			dap1_dout_pn2 {
+				nvidia,pins = "dap1_dout_pn2",
+						"dap1_fs_pn0",
+						"dap1_sclk_pn3";
+				nvidia,function = "i2s0";
+				nvidia,pull = <0>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <1>;
+			};
+			dap2_din_pa4 {
+				nvidia,pins = "dap2_din_pa4";
+				nvidia,function = "i2s1";
+				nvidia,pull = <0>;
+				nvidia,tristate = <1>;
+				nvidia,enable-input = <1>;
+			};
+			dap2_dout_pa5 {
+				nvidia,pins = "dap2_dout_pa5",
+						"dap2_fs_pa2",
+						"dap2_sclk_pa3";
+				nvidia,function = "i2s1";
+				nvidia,pull = <0>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <1>;
+			};
+			dap4_din_pp5 {
+				nvidia,pins = "dap4_din_pp5",
+						"dap4_dout_pp6",
+						"dap4_fs_pp4",
+						"dap4_sclk_pp7";
+				nvidia,function = "i2s3";
+				nvidia,pull = <0>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <1>;
+			};
+			dvfs_pwm_px0 {
+				nvidia,pins = "dvfs_pwm_px0",
+						"dvfs_clk_px2";
+				nvidia,function = "cldvfs";
+				nvidia,pull = <0>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <0>;
+			};
+			ulpi_clk_py0 {
+				nvidia,pins = "ulpi_clk_py0",
+						"ulpi_data0_po1",
+						"ulpi_data1_po2",
+						"ulpi_data2_po3",
+						"ulpi_data3_po4",
+						"ulpi_data4_po5",
+						"ulpi_data5_po6",
+						"ulpi_data6_po7",
+						"ulpi_data7_po0";
+				nvidia,function = "ulpi";
+				nvidia,pull = <0>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <1>;
+			};
+			ulpi_dir_py1 {
+				nvidia,pins = "ulpi_dir_py1",
+						"ulpi_nxt_py2";
+				nvidia,function = "ulpi";
+				nvidia,pull = <0>;
+				nvidia,tristate = <1>;
+				nvidia,enable-input = <1>;
+			};
+			ulpi_stp_py3 {
+				nvidia,pins = "ulpi_stp_py3";
+				nvidia,function = "ulpi";
+				nvidia,pull = <0>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <0>;
+			};
+			cam_i2c_scl_pbb1 {
+				nvidia,pins = "cam_i2c_scl_pbb1",
+						"cam_i2c_sda_pbb2";
+				nvidia,function = "i2c3";
+				nvidia,pull = <0>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <1>;
+				nvidia,lock = <0>;
+				nvidia,open-drain = <0>;
+			};
+			cam_mclk_pcc0 {
+				nvidia,pins = "cam_mclk_pcc0",
+						"pbb0";
+				nvidia,function = "vi_alt3";
+				nvidia,pull = <0>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <0>;
+				nvidia,lock = <0>;
+			};
+			gen2_i2c_scl_pt5 {
+				nvidia,pins = "gen2_i2c_scl_pt5",
+						"gen2_i2c_sda_pt6";
+				nvidia,function = "i2c2";
+				nvidia,pull = <0>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <1>;
+				nvidia,lock = <0>;
+				nvidia,open-drain = <0>;
+			};
+			gmi_a16_pj7 {
+				nvidia,pins = "gmi_a16_pj7";
+				nvidia,function = "uartd";
+				nvidia,pull = <0>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <0>;
+			};
+			gmi_a17_pb0 {
+				nvidia,pins = "gmi_a17_pb0",
+						"gmi_a18_pb1";
+				nvidia,function = "uartd";
+				nvidia,pull = <0>;
+				nvidia,tristate = <1>;
+				nvidia,enable-input = <1>;
+			};
+			gmi_a19_pk7 {
+				nvidia,pins = "gmi_a19_pk7";
+				nvidia,function = "uartd";
+				nvidia,pull = <0>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <0>;
+			};
+			gmi_ad5_pg5 {
+				nvidia,pins = "gmi_ad5_pg5",
+						"gmi_cs6_n_pi3",
+						"gmi_wr_n_pi0";
+				nvidia,function = "spi4";
+				nvidia,pull = <0>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <1>;
+			};
+			gmi_ad6_pg6 {
+				nvidia,pins = "gmi_ad6_pg6",
+						"gmi_ad7_pg7";
+				nvidia,function = "spi4";
+				nvidia,pull = <2>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <1>;
+			};
+			gmi_ad12_ph4 {
+				nvidia,pins = "gmi_ad12_ph4";
+				nvidia,function = "rsvd4";
+				nvidia,pull = <0>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <0>;
+			};
+			gmi_ad9_ph1 {
+				nvidia,pins = "gmi_ad9_ph1";
+				nvidia,function = "pwm1";
+				nvidia,pull = <0>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <0>;
+			};
+			gmi_cs1_n_pj2 {
+				nvidia,pins = "gmi_cs1_n_pj2",
+						"gmi_oe_n_pi1";
+				nvidia,function = "soc";
+				nvidia,pull = <0>;
+				nvidia,tristate = <1>;
+				nvidia,enable-input = <1>;
+			};
+			clk2_out_pw5 {
+				nvidia,pins = "clk2_out_pw5";
+				nvidia,function = "extperiph2";
+				nvidia,pull = <0>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <0>;
+			};
+			sdmmc1_clk_pz0 {
+				nvidia,pins = "sdmmc1_clk_pz0";
+				nvidia,function = "sdmmc1";
+				nvidia,pull = <0>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <1>;
+			};
+			sdmmc1_cmd_pz1 {
+				nvidia,pins = "sdmmc1_cmd_pz1",
+						"sdmmc1_dat0_py7",
+						"sdmmc1_dat1_py6",
+						"sdmmc1_dat2_py5",
+						"sdmmc1_dat3_py4";
+				nvidia,function = "sdmmc1";
+				nvidia,pull = <2>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <1>;
+			};
+			sdmmc1_wp_n_pv3 {
+				nvidia,pins = "sdmmc1_wp_n_pv3";
+				nvidia,function = "spi4";
+				nvidia,pull = <2>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <0>;
+			};
+			sdmmc3_clk_pa6 {
+				nvidia,pins = "sdmmc3_clk_pa6";
+				nvidia,function = "sdmmc3";
+				nvidia,pull = <0>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <1>;
+			};
+			sdmmc3_cmd_pa7 {
+				nvidia,pins = "sdmmc3_cmd_pa7",
+						"sdmmc3_dat0_pb7",
+						"sdmmc3_dat1_pb6",
+						"sdmmc3_dat2_pb5",
+						"sdmmc3_dat3_pb4",
+						"kb_col4_pq4",
+						"sdmmc3_clk_lb_out_pee4",
+						"sdmmc3_clk_lb_in_pee5";
+				nvidia,function = "sdmmc3";
+				nvidia,pull = <2>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <1>;
+			};
+			sdmmc4_clk_pcc4 {
+				nvidia,pins = "sdmmc4_clk_pcc4";
+				nvidia,function = "sdmmc4";
+				nvidia,pull = <0>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <1>;
+			};
+			sdmmc4_cmd_pt7 {
+				nvidia,pins = "sdmmc4_cmd_pt7",
+						"sdmmc4_dat0_paa0",
+						"sdmmc4_dat1_paa1",
+						"sdmmc4_dat2_paa2",
+						"sdmmc4_dat3_paa3",
+						"sdmmc4_dat4_paa4",
+						"sdmmc4_dat5_paa5",
+						"sdmmc4_dat6_paa6",
+						"sdmmc4_dat7_paa7";
+				nvidia,function = "sdmmc4";
+				nvidia,pull = <2>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <1>;
+			};
+			clk_32k_out_pa0 {
+				nvidia,pins = "clk_32k_out_pa0";
+				nvidia,function = "blink";
+				nvidia,pull = <0>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <0>;
+			};
+			kb_col0_pq0 {
+				nvidia,pins = "kb_col0_pq0",
+						"kb_col1_pq1",
+						"kb_col2_pq2",
+						"kb_row0_pr0",
+						"kb_row1_pr1",
+						"kb_row2_pr2";
+				nvidia,function = "kbc";
+				nvidia,pull = <2>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <1>;
+			};
+			dap3_din_pp1 {
+				nvidia,pins = "dap3_din_pp1",
+						"dap3_sclk_pp3";
+				nvidia,function = "displayb";
+				nvidia,pull = <0>;
+				nvidia,tristate = <1>;
+				nvidia,enable-input = <0>;
+			};
+			pv0 {
+				nvidia,pins = "pv0";
+				nvidia,function = "rsvd4";
+				nvidia,pull = <0>;
+				nvidia,tristate = <1>;
+				nvidia,enable-input = <0>;
+			};
+			kb_row7_pr7 {
+				nvidia,pins = "kb_row7_pr7";
+				nvidia,function = "rsvd2";
+				nvidia,pull = <2>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <1>;
+			};
+			kb_row10_ps2 {
+				nvidia,pins = "kb_row10_ps2";
+				nvidia,function = "uarta";
+				nvidia,pull = <0>;
+				nvidia,tristate = <1>;
+				nvidia,enable-input = <1>;
+			};
+			kb_row9_ps1 {
+				nvidia,pins = "kb_row9_ps1";
+				nvidia,function = "uarta";
+				nvidia,pull = <0>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <0>;
+			};
+			pwr_i2c_scl_pz6 {
+				nvidia,pins = "pwr_i2c_scl_pz6",
+						"pwr_i2c_sda_pz7";
+				nvidia,function = "i2cpwr";
+				nvidia,pull = <0>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <1>;
+				nvidia,lock = <0>;
+				nvidia,open-drain = <0>;
+			};
+			sys_clk_req_pz5 {
+				nvidia,pins = "sys_clk_req_pz5";
+				nvidia,function = "sysclk";
+				nvidia,pull = <0>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <0>;
+			};
+			core_pwr_req {
+				nvidia,pins = "core_pwr_req";
+				nvidia,function = "pwron";
+				nvidia,pull = <0>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <0>;
+			};
+			cpu_pwr_req {
+				nvidia,pins = "cpu_pwr_req";
+				nvidia,function = "cpu";
+				nvidia,pull = <0>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <0>;
+			};
+			pwr_int_n {
+				nvidia,pins = "pwr_int_n";
+				nvidia,function = "pmi";
+				nvidia,pull = <0>;
+				nvidia,tristate = <1>;
+				nvidia,enable-input = <1>;
+			};
+			reset_out_n {
+				nvidia,pins = "reset_out_n";
+				nvidia,function = "reset_out_n";
+				nvidia,pull = <0>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <0>;
+			};
+			clk3_out_pee0 {
+				nvidia,pins = "clk3_out_pee0";
+				nvidia,function = "extperiph3";
+				nvidia,pull = <0>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <0>;
+			};
+			gen1_i2c_scl_pc4 {
+				nvidia,pins = "gen1_i2c_scl_pc4",
+						"gen1_i2c_sda_pc5";
+				nvidia,function = "i2c1";
+				nvidia,pull = <0>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <1>;
+				nvidia,lock = <0>;
+				nvidia,open-drain = <0>;
+			};
+			uart2_cts_n_pj5 {
+				nvidia,pins = "uart2_cts_n_pj5";
+				nvidia,function = "uartb";
+				nvidia,pull = <0>;
+				nvidia,tristate = <1>;
+				nvidia,enable-input = <1>;
+			};
+			uart2_rts_n_pj6 {
+				nvidia,pins = "uart2_rts_n_pj6";
+				nvidia,function = "uartb";
+				nvidia,pull = <0>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <0>;
+			};
+			uart2_rxd_pc3 {
+				nvidia,pins = "uart2_rxd_pc3";
+				nvidia,function = "irda";
+				nvidia,pull = <0>;
+				nvidia,tristate = <1>;
+				nvidia,enable-input = <1>;
+			};
+			uart2_txd_pc2 {
+				nvidia,pins = "uart2_txd_pc2";
+				nvidia,function = "irda";
+				nvidia,pull = <0>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <0>;
+			};
+			uart3_cts_n_pa1 {
+				nvidia,pins = "uart3_cts_n_pa1",
+						"uart3_rxd_pw7";
+				nvidia,function = "uartc";
+				nvidia,pull = <0>;
+				nvidia,tristate = <1>;
+				nvidia,enable-input = <1>;
+			};
+			uart3_rts_n_pc0 {
+				nvidia,pins = "uart3_rts_n_pc0",
+						"uart3_txd_pw6";
+				nvidia,function = "uartc";
+				nvidia,pull = <0>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <0>;
+			};
+			owr {
+				nvidia,pins = "owr";
+				nvidia,function = "owr";
+				nvidia,pull = <0>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <1>;
+			};
+			hdmi_cec_pee3 {
+				nvidia,pins = "hdmi_cec_pee3";
+				nvidia,function = "cec";
+				nvidia,pull = <0>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <1>;
+				nvidia,lock = <0>;
+				nvidia,open-drain = <0>;
+			};
+			ddc_scl_pv4 {
+				nvidia,pins = "ddc_scl_pv4",
+						"ddc_sda_pv5";
+				nvidia,function = "i2c4";
+				nvidia,pull = <0>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <1>;
+				nvidia,lock = <0>;
+				nvidia,rcv-sel = <1>;
+			};
+			spdif_in_pk6 {
+				nvidia,pins = "spdif_in_pk6";
+				nvidia,function = "usb";
+				nvidia,pull = <2>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <1>;
+				nvidia,lock = <0>;
+			};
+			usb_vbus_en0_pn4 {
+				nvidia,pins = "usb_vbus_en0_pn4";
+				nvidia,function = "usb";
+				nvidia,pull = <2>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <1>;
+				nvidia,lock = <0>;
+				nvidia,open-drain = <1>;
+			};
+			gpio_x6_aud_px6 {
+				nvidia,pins = "gpio_x6_aud_px6";
+				nvidia,function = "spi6";
+				nvidia,pull = <2>;
+				nvidia,tristate = <1>;
+				nvidia,enable-input = <1>;
+			};
+			gpio_x4_aud_px4 {
+				nvidia,pins = "gpio_x4_aud_px4",
+						"gpio_x7_aud_px7";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <1>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <0>;
+			};
+			gpio_x5_aud_px5 {
+				nvidia,pins = "gpio_x5_aud_px5";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <2>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <1>;
+			};
+			gpio_w2_aud_pw2 {
+				nvidia,pins = "gpio_w2_aud_pw2";
+				nvidia,function = "rsvd2";
+				nvidia,pull = <2>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <1>;
+			};
+			gpio_w3_aud_pw3 {
+				nvidia,pins = "gpio_w3_aud_pw3";
+				nvidia,function = "spi6";
+				nvidia,pull = <2>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <1>;
+			};
+			gpio_x1_aud_px1 {
+				nvidia,pins = "gpio_x1_aud_px1";
+				nvidia,function = "rsvd4";
+				nvidia,pull = <1>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <1>;
+			};
+			gpio_x3_aud_px3 {
+				nvidia,pins = "gpio_x3_aud_px3";
+				nvidia,function = "rsvd4";
+				nvidia,pull = <2>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <1>;
+			};
+			dap3_fs_pp0 {
+				nvidia,pins = "dap3_fs_pp0";
+				nvidia,function = "i2s2";
+				nvidia,pull = <1>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <0>;
+			};
+			dap3_dout_pp2 {
+				nvidia,pins = "dap3_dout_pp2";
+				nvidia,function = "i2s2";
+				nvidia,pull = <1>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <0>;
+			};
+			pv1 {
+				nvidia,pins = "pv1";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <0>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <1>;
+			};
+			pbb3 {
+				nvidia,pins = "pbb3",
+						"pbb5",
+						"pbb6",
+						"pbb7";
+				nvidia,function = "rsvd4";
+				nvidia,pull = <1>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <0>;
+			};
+			pcc1 {
+				nvidia,pins = "pcc1",
+						"pcc2";
+				nvidia,function = "rsvd4";
+				nvidia,pull = <1>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <1>;
+			};
+			gmi_ad0_pg0 {
+				nvidia,pins = "gmi_ad0_pg0",
+						"gmi_ad1_pg1";
+				nvidia,function = "gmi";
+				nvidia,pull = <0>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <0>;
+			};
+			gmi_ad10_ph2 {
+				nvidia,pins = "gmi_ad10_ph2",
+						"gmi_ad11_ph3",
+						"gmi_ad13_ph5",
+						"gmi_ad8_ph0",
+						"gmi_clk_pk1";
+				nvidia,function = "gmi";
+				nvidia,pull = <1>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <0>;
+			};
+			gmi_ad2_pg2 {
+				nvidia,pins = "gmi_ad2_pg2",
+						"gmi_ad3_pg3";
+				nvidia,function = "gmi";
+				nvidia,pull = <0>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <1>;
+			};
+			gmi_adv_n_pk0 {
+				nvidia,pins = "gmi_adv_n_pk0",
+						"gmi_cs0_n_pj0",
+						"gmi_cs2_n_pk3",
+						"gmi_cs4_n_pk2",
+						"gmi_cs7_n_pi6",
+						"gmi_dqs_p_pj3",
+						"gmi_iordy_pi5",
+						"gmi_wp_n_pc7";
+				nvidia,function = "gmi";
+				nvidia,pull = <2>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <1>;
+			};
+			gmi_cs3_n_pk4 {
+				nvidia,pins = "gmi_cs3_n_pk4";
+				nvidia,function = "gmi";
+				nvidia,pull = <2>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <0>;
+			};
+			clk2_req_pcc5 {
+				nvidia,pins = "clk2_req_pcc5";
+				nvidia,function = "rsvd4";
+				nvidia,pull = <0>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <0>;
+			};
+			kb_col3_pq3 {
+				nvidia,pins = "kb_col3_pq3",
+						"kb_col6_pq6",
+						"kb_col7_pq7";
+				nvidia,function = "kbc";
+				nvidia,pull = <2>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <0>;
+			};
+			kb_col5_pq5 {
+				nvidia,pins = "kb_col5_pq5";
+				nvidia,function = "kbc";
+				nvidia,pull = <2>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <1>;
+			};
+			kb_row3_pr3 {
+				nvidia,pins = "kb_row3_pr3",
+						"kb_row4_pr4",
+						"kb_row6_pr6",
+						"kb_row8_ps0";
+				nvidia,function = "kbc";
+				nvidia,pull = <1>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <1>;
+			};
+			clk3_req_pee1 {
+				nvidia,pins = "clk3_req_pee1";
+				nvidia,function = "rsvd4";
+				nvidia,pull = <0>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <0>;
+			};
+			pu4 {
+				nvidia,pins = "pu4";
+				nvidia,function = "displayb";
+				nvidia,pull = <0>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <0>;
+			};
+			pu5 {
+				nvidia,pins = "pu5",
+						"pu6";
+				nvidia,function = "displayb";
+				nvidia,pull = <0>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <1>;
+			};
+			hdmi_int_pn7 {
+				nvidia,pins = "hdmi_int_pn7";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <1>;
+				nvidia,tristate = <0>;
+				nvidia,enable-input = <1>;
+			};
+			clk1_req_pee2 {
+				nvidia,pins = "clk1_req_pee2",
+						"usb_vbus_en1_pn5";
+				nvidia,function = "rsvd4";
+				nvidia,pull = <1>;
+				nvidia,tristate = <1>;
+				nvidia,enable-input = <0>;
+			};
+
+			drive_sdio1 {
+				nvidia,pins = "drive_sdio1";
+				nvidia,high-speed-mode = <1>;
+				nvidia,schmitt = <0>;
+				nvidia,low-power-mode = <3>;
+				nvidia,pull-down-strength = <36>;
+				nvidia,pull-up-strength = <20>;
+				nvidia,slew-rate-rising = <2>;
+				nvidia,slew-rate-falling = <2>;
+			};
+			drive_sdio3 {
+				nvidia,pins = "drive_sdio3";
+				nvidia,high-speed-mode = <1>;
+				nvidia,schmitt = <0>;
+				nvidia,low-power-mode = <3>;
+				nvidia,pull-down-strength = <22>;
+				nvidia,pull-up-strength = <36>;
+				nvidia,slew-rate-rising = <0>;
+				nvidia,slew-rate-falling = <0>;
+			};
+			drive_gma {
+				nvidia,pins = "drive_gma";
+				nvidia,high-speed-mode = <1>;
+				nvidia,schmitt = <0>;
+				nvidia,low-power-mode = <3>;
+				nvidia,pull-down-strength = <2>;
+				nvidia,pull-up-strength = <1>;
+				nvidia,slew-rate-rising = <0>;
+				nvidia,slew-rate-falling = <0>;
+				nvidia,drive-type = <1>;
+			};
+		};
+	};
+
 	serial@70006300 {
 		status = "okay";
 		clock-frequency = <408000000>;
 	};
 
+	i2c@7000c000 {
+		status = "okay";
+		clock-frequency = <100000>;
+
+		battery: smart-battery {
+			compatible = "ti,bq20z45", "sbs,sbs-battery";
+			reg = <0xb>;
+			battery-name = "battery";
+			sbs,i2c-retry-count = <2>;
+			sbs,poll-retry-count = <100>;
+		};
+	};
+
+	i2c@7000d000 {
+		status = "okay";
+		clock-frequency = <400000>;
+
+		tps51632 {
+			compatible = "ti,tps51632";
+			reg = <0x43>;
+			regulator-name = "vdd-cpu";
+			regulator-min-microvolt = <500000>;
+			regulator-max-microvolt = <1520000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		tps65090 {
+			compatible = "ti,tps65090";
+			reg = <0x48>;
+			interrupt-parent = <&gpio>;
+			interrupts = <72 0x04>; /* gpio PJ0 */
+
+			vsys1-supply = <&vdd_ac_bat_reg>;
+			vsys2-supply = <&vdd_ac_bat_reg>;
+			vsys3-supply = <&vdd_ac_bat_reg>;
+			infet1-supply = <&vdd_ac_bat_reg>;
+			infet2-supply = <&vdd_ac_bat_reg>;
+			infet3-supply = <&tps65090_dcdc2_reg>;
+			infet4-supply = <&tps65090_dcdc2_reg>;
+			infet5-supply = <&tps65090_dcdc2_reg>;
+			infet6-supply = <&tps65090_dcdc2_reg>;
+			infet7-supply = <&tps65090_dcdc2_reg>;
+			vsys-l1-supply = <&vdd_ac_bat_reg>;
+			vsys-l2-supply = <&vdd_ac_bat_reg>;
+
+			regulators {
+				tps65090_dcdc1_reg: dcdc1 {
+					regulator-name = "vdd-sys-5v0";
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				tps65090_dcdc2_reg: dcdc2 {
+					regulator-name = "vdd-sys-3v3";
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				dcdc3 {
+					regulator-name = "vdd-ao";
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				fet1 {
+					regulator-name = "vdd-lcd-bl";
+				};
+
+				fet3 {
+					regulator-name = "vdd-modem-3v3";
+				};
+
+				fet4 {
+					regulator-name = "avdd-lcd";
+				};
+
+				fet5 {
+					regulator-name = "vdd-lvds";
+				};
+
+				fet6 {
+					regulator-name = "vdd-sd-slot";
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				fet7 {
+					regulator-name = "vdd-com-3v3";
+				};
+
+				ldo1 {
+					regulator-name = "vdd-sby-5v0";
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				ldo2 {
+					regulator-name = "vdd-sby-3v3";
+					regulator-always-on;
+					regulator-boot-on;
+				};
+			};
+		};
+	};
+
 	pmc {
 		nvidia,invert-interrupt;
 	};
+
+	sdhci@78000400 {
+		cd-gpios = <&gpio 170 1>; /* gpio PV2 */
+		bus-width = <4>;
+		status = "okay";
+	};
+
+	sdhci@78000600 {
+		bus-width = <8>;
+		status = "okay";
+		non-removable;
+	};
+
+	clocks {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		clk32k_in: clock {
+			compatible = "fixed-clock";
+			reg=<0>;
+			#clock-cells = <0>;
+			clock-frequency = <32768>;
+		};
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		vdd_ac_bat_reg: regulator@0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "vdd_ac_bat";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			regulator-always-on;
+		};
+
+		dvdd_ts_reg: regulator@1 {
+			compatible = "regulator-fixed";
+			reg = <1>;
+			regulator-name = "dvdd_ts";
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			enable-active-high;
+			gpio = <&gpio 61 0>; /* GPIO PH5 */
+		};
+
+		lcd_bl_en_reg: regulator@2 {
+			compatible = "regulator-fixed";
+			reg = <2>;
+			regulator-name = "lcd_bl_en";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			enable-active-high;
+			gpio = <&gpio 58 0>; /* GPIO PH2 */
+		};
+
+		usb1_vbus_reg: regulator@3 {
+			compatible = "regulator-fixed";
+			reg = <3>;
+			regulator-name = "usb1_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			enable-active-high;
+			gpio = <&gpio 108 0>; /* GPIO PN4 */
+			gpio-open-drain;
+			vin-supply = <&tps65090_dcdc1_reg>;
+		};
+
+		usb3_vbus_reg: regulator@4 {
+			compatible = "regulator-fixed";
+			reg = <4>;
+			regulator-name = "usb2_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			enable-active-high;
+			gpio = <&gpio 86 0>; /* GPIO PK6 */
+			gpio-open-drain;
+			vin-supply = <&tps65090_dcdc1_reg>;
+		};
+
+		vdd_hdmi_reg: regulator@5 {
+			compatible = "regulator-fixed";
+			reg = <5>;
+			regulator-name = "vdd_hdmi_5v0";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			enable-active-high;
+			gpio = <&gpio 81 0>; /* GPIO PK1 */
+			vin-supply = <&tps65090_dcdc1_reg>;
+		};
+	};
 };
diff --git a/arch/arm/boot/dts/tegra114-pluto.dts b/arch/arm/boot/dts/tegra114-pluto.dts
index 9bea8f5..5deb869 100644
--- a/arch/arm/boot/dts/tegra114-pluto.dts
+++ b/arch/arm/boot/dts/tegra114-pluto.dts
@@ -18,4 +18,17 @@
 	pmc {
 		nvidia,invert-interrupt;
 	};
+
+	clocks {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		clk32k_in: clock {
+			compatible = "fixed-clock";
+			reg=<0>;
+			#clock-cells = <0>;
+			clock-frequency = <32768>;
+		};
+	};
 };
diff --git a/arch/arm/boot/dts/tegra114.dtsi b/arch/arm/boot/dts/tegra114.dtsi
index 1dfaf28..4eb87b8 100644
--- a/arch/arm/boot/dts/tegra114.dtsi
+++ b/arch/arm/boot/dts/tegra114.dtsi
@@ -4,6 +4,13 @@
 	compatible = "nvidia,tegra114";
 	interrupt-parent = <&gic>;
 
+	aliases {
+		serial0 = &uarta;
+		serial1 = &uartb;
+		serial2 = &uartc;
+		serial3 = &uartd;
+	};
+
 	gic: interrupt-controller {
 		compatible = "arm,cortex-a15-gic";
 		#interrupt-cells = <3>;
@@ -32,6 +39,44 @@
 		#clock-cells = <1>;
 	};
 
+	apbdma: dma {
+		compatible = "nvidia,tegra114-apbdma";
+		reg = <0x6000a000 0x1400>;
+		interrupts = <0 104 0x04
+			      0 105 0x04
+			      0 106 0x04
+			      0 107 0x04
+			      0 108 0x04
+			      0 109 0x04
+			      0 110 0x04
+			      0 111 0x04
+			      0 112 0x04
+			      0 113 0x04
+			      0 114 0x04
+			      0 115 0x04
+			      0 116 0x04
+			      0 117 0x04
+			      0 118 0x04
+			      0 119 0x04
+			      0 128 0x04
+			      0 129 0x04
+			      0 130 0x04
+			      0 131 0x04
+			      0 132 0x04
+			      0 133 0x04
+			      0 134 0x04
+			      0 135 0x04
+			      0 136 0x04
+			      0 137 0x04
+			      0 138 0x04
+			      0 139 0x04
+			      0 140 0x04
+			      0 141 0x04
+			      0 142 0x04
+			      0 143 0x04>;
+		clocks = <&tegra_car 34>;
+	};
+
 	ahb: ahb {
 		compatible = "nvidia,tegra114-ahb", "nvidia,tegra30-ahb";
 		reg = <0x6000c004 0x14c>;
@@ -60,35 +105,182 @@
 		       0x70003000 0x40c>;	/* Mux registers */
 	};
 
-	serial@70006000 {
+	/*
+	 * There are two serial driver i.e. 8250 based simple serial
+	 * driver and APB DMA based serial driver for higher baudrate
+	 * and performace. To enable the 8250 based driver, the compatible
+	 * is "nvidia,tegra114-uart", "nvidia,tegra20-uart" and to enable
+	 * the APB DMA based serial driver, the comptible is
+	 * "nvidia,tegra114-hsuart", "nvidia,tegra30-hsuart".
+	 */
+	uarta: serial@70006000 {
 		compatible = "nvidia,tegra114-uart", "nvidia,tegra20-uart";
 		reg = <0x70006000 0x40>;
 		reg-shift = <2>;
 		interrupts = <0 36 0x04>;
+		nvidia,dma-request-selector = <&apbdma 8>;
 		status = "disabled";
 	};
 
-	serial@70006040 {
+	uartb: serial@70006040 {
 		compatible = "nvidia,tegra114-uart", "nvidia,tegra20-uart";
 		reg = <0x70006040 0x40>;
 		reg-shift = <2>;
 		interrupts = <0 37 0x04>;
+		nvidia,dma-request-selector = <&apbdma 9>;
 		status = "disabled";
 	};
 
-	serial@70006200 {
+	uartc: serial@70006200 {
 		compatible = "nvidia,tegra114-uart", "nvidia,tegra20-uart";
 		reg = <0x70006200 0x100>;
 		reg-shift = <2>;
 		interrupts = <0 46 0x04>;
+		nvidia,dma-request-selector = <&apbdma 10>;
 		status = "disabled";
 	};
 
-	serial@70006300 {
+	uartd: serial@70006300 {
 		compatible = "nvidia,tegra114-uart", "nvidia,tegra20-uart";
 		reg = <0x70006300 0x100>;
 		reg-shift = <2>;
 		interrupts = <0 90 0x04>;
+		nvidia,dma-request-selector = <&apbdma 19>;
+		status = "disabled";
+	};
+
+	pwm: pwm {
+		compatible = "nvidia,tegra114-pwm", "nvidia,tegra20-pwm";
+		reg = <0x7000a000 0x100>;
+		#pwm-cells = <2>;
+		clocks = <&tegra_car 17>;
+		status = "disabled";
+	};
+
+	i2c@7000c000 {
+		compatible = "nvidia,tegra114-i2c";
+		reg = <0x7000c000 0x100>;
+		interrupts = <0 38 0x04>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&tegra_car 12>;
+		clock-names = "div-clk";
+		status = "disabled";
+	};
+
+	i2c@7000c400 {
+		compatible = "nvidia,tegra114-i2c";
+		reg = <0x7000c400 0x100>;
+		interrupts = <0 84 0x04>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&tegra_car 54>;
+		clock-names = "div-clk";
+		status = "disabled";
+	};
+
+	i2c@7000c500 {
+		compatible = "nvidia,tegra114-i2c";
+		reg = <0x7000c500 0x100>;
+		interrupts = <0 92 0x04>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&tegra_car 67>;
+		clock-names = "div-clk";
+		status = "disabled";
+	};
+
+	i2c@7000c700 {
+		compatible = "nvidia,tegra114-i2c";
+		reg = <0x7000c700 0x100>;
+		interrupts = <0 120 0x04>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&tegra_car 103>;
+		clock-names = "div-clk";
+		status = "disabled";
+	};
+
+	i2c@7000d000 {
+		compatible = "nvidia,tegra114-i2c";
+		reg = <0x7000d000 0x100>;
+		interrupts = <0 53 0x04>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&tegra_car 47>;
+		clock-names = "div-clk";
+		status = "disabled";
+	};
+
+	spi@7000d400 {
+		compatible = "nvidia,tegra114-spi";
+		reg = <0x7000d400 0x200>;
+		interrupts = <0 59 0x04>;
+		nvidia,dma-request-selector = <&apbdma 15>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&tegra_car 41>;
+		clock-names = "spi";
+		status = "disabled";
+	};
+
+	spi@7000d600 {
+		compatible = "nvidia,tegra114-spi";
+		reg = <0x7000d600 0x200>;
+		interrupts = <0 82 0x04>;
+		nvidia,dma-request-selector = <&apbdma 16>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&tegra_car 44>;
+		clock-names = "spi";
+		status = "disabled";
+	};
+
+	spi@7000d800 {
+		compatible = "nvidia,tegra114-spi";
+		reg = <0x7000d800 0x200>;
+		interrupts = <0 83 0x04>;
+		nvidia,dma-request-selector = <&apbdma 17>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&tegra_car 46>;
+		clock-names = "spi";
+		status = "disabled";
+	};
+
+	spi@7000da00 {
+		compatible = "nvidia,tegra114-spi";
+		reg = <0x7000da00 0x200>;
+		interrupts = <0 93 0x04>;
+		nvidia,dma-request-selector = <&apbdma 18>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&tegra_car 68>;
+		clock-names = "spi";
+		status = "disabled";
+	};
+
+	spi@7000dc00 {
+		compatible = "nvidia,tegra114-spi";
+		reg = <0x7000dc00 0x200>;
+		interrupts = <0 94 0x04>;
+		nvidia,dma-request-selector = <&apbdma 27>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&tegra_car 104>;
+		clock-names = "spi";
+		status = "disabled";
+	};
+
+	spi@7000de00 {
+		compatible = "nvidia,tegra114-spi";
+		reg = <0x7000de00 0x200>;
+		interrupts = <0 79 0x04>;
+		nvidia,dma-request-selector = <&apbdma 28>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&tegra_car 105>;
+		clock-names = "spi";
 		status = "disabled";
 	};
 
@@ -98,9 +290,19 @@
 		interrupts = <0 2 0x04>;
 	};
 
+	kbc {
+		compatible = "nvidia,tegra114-kbc";
+		reg = <0x7000e200 0x100>;
+		interrupts = <0 85 0x04>;
+		clocks = <&tegra_car 36>;
+		status = "disabled";
+	};
+
 	pmc {
-		compatible = "nvidia,tegra114-pmc", "nvidia,tegra30-pmc";
+		compatible = "nvidia,tegra114-pmc";
 		reg = <0x7000e400 0x400>;
+		clocks = <&tegra_car 261>, <&clk32k_in>;
+		clock-names = "pclk", "clk32k_in";
 	};
 
 	iommu {
@@ -114,6 +316,38 @@
 		nvidia,ahb = <&ahb>;
 	};
 
+	sdhci@78000000 {
+		compatible = "nvidia,tegra114-sdhci", "nvidia,tegra30-sdhci";
+		reg = <0x78000000 0x200>;
+		interrupts = <0 14 0x04>;
+		clocks = <&tegra_car 14>;
+		status = "disable";
+	};
+
+	sdhci@78000200 {
+		compatible = "nvidia,tegra114-sdhci", "nvidia,tegra30-sdhci";
+		reg = <0x78000200 0x200>;
+		interrupts = <0 15 0x04>;
+		clocks = <&tegra_car 9>;
+		status = "disable";
+	};
+
+	sdhci@78000400 {
+		compatible = "nvidia,tegra114-sdhci", "nvidia,tegra30-sdhci";
+		reg = <0x78000400 0x200>;
+		interrupts = <0 19 0x04>;
+		clocks = <&tegra_car 69>;
+		status = "disable";
+	};
+
+	sdhci@78000600 {
+		compatible = "nvidia,tegra114-sdhci", "nvidia,tegra30-sdhci";
+		reg = <0x78000600 0x200>;
+		interrupts = <0 31 0x04>;
+		clocks = <&tegra_car 15>;
+		status = "disable";
+	};
+
 	cpus {
 		#address-cells = <1>;
 		#size-cells = <0>;
diff --git a/arch/arm/boot/dts/tegra20-colibri-512.dtsi b/arch/arm/boot/dts/tegra20-colibri-512.dtsi
index 4441620..a094787 100644
--- a/arch/arm/boot/dts/tegra20-colibri-512.dtsi
+++ b/arch/arm/boot/dts/tegra20-colibri-512.dtsi
@@ -361,6 +361,15 @@
 		};
 	};
 
+	pmc {
+		nvidia,suspend-mode = <2>;
+		nvidia,cpu-pwr-good-time = <5000>;
+		nvidia,cpu-pwr-off-time = <5000>;
+		nvidia,core-pwr-good-time = <3845 3845>;
+		nvidia,core-pwr-off-time = <3875>;
+		nvidia,sys-clock-req-active-high;
+	};
+
 	memory-controller@7000f400 {
 		emc-table@83250 {
 			reg = <83250>;
@@ -444,7 +453,20 @@
 	};
 
 	sdhci@c8000600 {
-		cd-gpios = <&gpio 23 0>; /* gpio PC7 */
+		cd-gpios = <&gpio 23 1>; /* gpio PC7 */
+	};
+
+	clocks {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		clk32k_in: clock {
+			compatible = "fixed-clock";
+			reg=<0>;
+			#clock-cells = <0>;
+			clock-frequency = <32768>;
+		};
 	};
 
 	sound {
@@ -460,6 +482,9 @@
 			"Mic", "MIC1";
 
 		nvidia,ac97-controller = <&ac97>;
+
+		clocks = <&tegra_car 112>, <&tegra_car 113>, <&tegra_car 93>;
+		clock-names = "pll_a", "pll_a_out0", "mclk";
 	};
 
 	regulators {
diff --git a/arch/arm/boot/dts/tegra20-harmony.dts b/arch/arm/boot/dts/tegra20-harmony.dts
index 61d027f..a44b54e 100644
--- a/arch/arm/boot/dts/tegra20-harmony.dts
+++ b/arch/arm/boot/dts/tegra20-harmony.dts
@@ -416,6 +416,12 @@
 
 	pmc {
 		nvidia,invert-interrupt;
+		nvidia,suspend-mode = <2>;
+		nvidia,cpu-pwr-good-time = <5000>;
+		nvidia,cpu-pwr-off-time = <5000>;
+		nvidia,core-pwr-good-time = <3845 3845>;
+		nvidia,core-pwr-off-time = <3875>;
+		nvidia,sys-clock-req-active-high;
 	};
 
 	usb@c5000000 {
@@ -437,7 +443,7 @@
 
 	sdhci@c8000200 {
 		status = "okay";
-		cd-gpios = <&gpio 69 0>; /* gpio PI5 */
+		cd-gpios = <&gpio 69 1>; /* gpio PI5 */
 		wp-gpios = <&gpio 57 0>; /* gpio PH1 */
 		power-gpios = <&gpio 155 0>; /* gpio PT3 */
 		bus-width = <4>;
@@ -445,12 +451,36 @@
 
 	sdhci@c8000600 {
 		status = "okay";
-		cd-gpios = <&gpio 58 0>; /* gpio PH2 */
+		cd-gpios = <&gpio 58 1>; /* gpio PH2 */
 		wp-gpios = <&gpio 59 0>; /* gpio PH3 */
 		power-gpios = <&gpio 70 0>; /* gpio PI6 */
 		bus-width = <8>;
 	};
 
+	clocks {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		clk32k_in: clock {
+			compatible = "fixed-clock";
+			reg=<0>;
+			#clock-cells = <0>;
+			clock-frequency = <32768>;
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		power {
+			label = "Power";
+			gpios = <&gpio 170 1>; /* gpio PV2, active low */
+			linux,code = <116>; /* KEY_POWER */
+			gpio-key,wakeup;
+		};
+	};
+
 	kbc {
 		status = "okay";
 		nvidia,debounce-delay-ms = <2>;
@@ -656,5 +686,8 @@
 		nvidia,hp-det-gpios = <&gpio 178 0>; /* gpio PW2 */
 		nvidia,int-mic-en-gpios = <&gpio 184 0>; /*gpio PX0 */
 		nvidia,ext-mic-en-gpios = <&gpio 185 0>; /* gpio PX1 */
+
+		clocks = <&tegra_car 112>, <&tegra_car 113>, <&tegra_car 93>;
+		clock-names = "pll_a", "pll_a_out0", "mclk";
 	};
 };
diff --git a/arch/arm/boot/dts/tegra20-medcom-wide.dts b/arch/arm/boot/dts/tegra20-medcom-wide.dts
index a2d6d65..740ba7c 100644
--- a/arch/arm/boot/dts/tegra20-medcom-wide.dts
+++ b/arch/arm/boot/dts/tegra20-medcom-wide.dts
@@ -6,6 +6,10 @@
 	model = "Avionic Design Medcom-Wide board";
 	compatible = "ad,medcom-wide", "ad,tamonten", "nvidia,tegra20";
 
+	pwm {
+		status = "okay";
+	};
+
 	i2c@7000c000 {
 		wm8903: wm8903@1a {
 			compatible = "wlf,wm8903";
@@ -54,5 +58,8 @@
 
 		nvidia,spkr-en-gpios = <&wm8903 2 0>;
 		nvidia,hp-det-gpios = <&gpio 178 0>; /* gpio PW2 */
+
+		clocks = <&tegra_car 112>, <&tegra_car 113>, <&tegra_car 93>;
+		clock-names = "pll_a", "pll_a_out0", "mclk";
 	};
 };
diff --git a/arch/arm/boot/dts/tegra20-paz00.dts b/arch/arm/boot/dts/tegra20-paz00.dts
index 54d6fce..8c0e9a2 100644
--- a/arch/arm/boot/dts/tegra20-paz00.dts
+++ b/arch/arm/boot/dts/tegra20-paz00.dts
@@ -415,6 +415,12 @@
 
 	pmc {
 		nvidia,invert-interrupt;
+		nvidia,suspend-mode = <2>;
+		nvidia,cpu-pwr-good-time = <2000>;
+		nvidia,cpu-pwr-off-time = <0>;
+		nvidia,core-pwr-good-time = <3845 3845>;
+		nvidia,core-pwr-off-time = <0>;
+		nvidia,sys-clock-req-active-high;
 	};
 
 	usb@c5000000 {
@@ -436,7 +442,7 @@
 
 	sdhci@c8000000 {
 		status = "okay";
-		cd-gpios = <&gpio 173 0>; /* gpio PV5 */
+		cd-gpios = <&gpio 173 1>; /* gpio PV5 */
 		wp-gpios = <&gpio 57 0>;  /* gpio PH1 */
 		power-gpios = <&gpio 169 0>; /* gpio PV1 */
 		bus-width = <4>;
@@ -445,6 +451,20 @@
 	sdhci@c8000600 {
 		status = "okay";
 		bus-width = <8>;
+		non-removable;
+	};
+
+	clocks {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		clk32k_in: clock {
+			compatible = "fixed-clock";
+			reg=<0>;
+			#clock-cells = <0>;
+			clock-frequency = <32768>;
+		};
 	};
 
 	gpio-keys {
@@ -501,5 +521,8 @@
 		nvidia,audio-codec = <&alc5632>;
 		nvidia,i2s-controller = <&tegra_i2s1>;
 		nvidia,hp-det-gpios = <&gpio 178 0>; /* gpio PW2 */
+
+		clocks = <&tegra_car 112>, <&tegra_car 113>, <&tegra_car 93>;
+		clock-names = "pll_a", "pll_a_out0", "mclk";
 	};
 };
diff --git a/arch/arm/boot/dts/tegra20-plutux.dts b/arch/arm/boot/dts/tegra20-plutux.dts
index 2894800..7085ae5 100644
--- a/arch/arm/boot/dts/tegra20-plutux.dts
+++ b/arch/arm/boot/dts/tegra20-plutux.dts
@@ -52,5 +52,8 @@
 
 		nvidia,spkr-en-gpios = <&wm8903 2 0>;
 		nvidia,hp-det-gpios = <&gpio 178 0>; /* gpio PW2 */
+
+		clocks = <&tegra_car 112>, <&tegra_car 113>, <&tegra_car 93>;
+		clock-names = "pll_a", "pll_a_out0", "mclk";
 	};
 };
diff --git a/arch/arm/boot/dts/tegra20-seaboard.dts b/arch/arm/boot/dts/tegra20-seaboard.dts
index 37b3a57..c45b698 100644
--- a/arch/arm/boot/dts/tegra20-seaboard.dts
+++ b/arch/arm/boot/dts/tegra20-seaboard.dts
@@ -517,6 +517,12 @@
 
 	pmc {
 		nvidia,invert-interrupt;
+		nvidia,suspend-mode = <2>;
+		nvidia,cpu-pwr-good-time = <5000>;
+		nvidia,cpu-pwr-off-time = <5000>;
+		nvidia,core-pwr-good-time = <3845 3845>;
+		nvidia,core-pwr-off-time = <3875>;
+		nvidia,sys-clock-req-active-high;
 	};
 
 	memory-controller@7000f400 {
@@ -580,11 +586,12 @@
 		status = "okay";
 		power-gpios = <&gpio 86 0>; /* gpio PK6 */
 		bus-width = <4>;
+		keep-power-in-suspend;
 	};
 
 	sdhci@c8000400 {
 		status = "okay";
-		cd-gpios = <&gpio 69 0>; /* gpio PI5 */
+		cd-gpios = <&gpio 69 1>; /* gpio PI5 */
 		wp-gpios = <&gpio 57 0>; /* gpio PH1 */
 		power-gpios = <&gpio 70 0>; /* gpio PI6 */
 		bus-width = <4>;
@@ -593,6 +600,20 @@
 	sdhci@c8000600 {
 		status = "okay";
 		bus-width = <8>;
+		non-removable;
+	};
+
+	clocks {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		clk32k_in: clock {
+			compatible = "fixed-clock";
+			reg=<0>;
+			#clock-cells = <0>;
+			clock-frequency = <32768>;
+		};
 	};
 
 	gpio-keys {
@@ -808,5 +829,8 @@
 
 		nvidia,spkr-en-gpios = <&wm8903 2 0>;
 		nvidia,hp-det-gpios = <&gpio 185 0>; /* gpio PX1 */
+
+		clocks = <&tegra_car 112>, <&tegra_car 113>, <&tegra_car 93>;
+		clock-names = "pll_a", "pll_a_out0", "mclk";
 	};
 };
diff --git a/arch/arm/boot/dts/tegra20-tamonten.dtsi b/arch/arm/boot/dts/tegra20-tamonten.dtsi
index 4766aba..50b3ec1 100644
--- a/arch/arm/boot/dts/tegra20-tamonten.dtsi
+++ b/arch/arm/boot/dts/tegra20-tamonten.dtsi
@@ -458,6 +458,12 @@
 
 	pmc {
 		nvidia,invert-interrupt;
+		nvidia,suspend-mode = <2>;
+		nvidia,cpu-pwr-good-time = <5000>;
+		nvidia,cpu-pwr-off-time = <5000>;
+		nvidia,core-pwr-good-time = <3845 3845>;
+		nvidia,core-pwr-off-time = <3875>;
+		nvidia,sys-clock-req-active-high;
 	};
 
 	usb@c5008000 {
@@ -465,12 +471,25 @@
 	};
 
 	sdhci@c8000600 {
-		cd-gpios = <&gpio 58 0>; /* gpio PH2 */
+		cd-gpios = <&gpio 58 1>; /* gpio PH2 */
 		wp-gpios = <&gpio 59 0>; /* gpio PH3 */
 		bus-width = <4>;
 		status = "okay";
 	};
 
+	clocks {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		clk32k_in: clock {
+			compatible = "fixed-clock";
+			reg=<0>;
+			#clock-cells = <0>;
+			clock-frequency = <32768>;
+		};
+	};
+
 	regulators {
 		compatible = "simple-bus";
 
diff --git a/arch/arm/boot/dts/tegra20-tec.dts b/arch/arm/boot/dts/tegra20-tec.dts
index 402b210..9be175d 100644
--- a/arch/arm/boot/dts/tegra20-tec.dts
+++ b/arch/arm/boot/dts/tegra20-tec.dts
@@ -52,5 +52,8 @@
 
 		nvidia,spkr-en-gpios = <&wm8903 2 0>;
 		nvidia,hp-det-gpios = <&gpio 178 0>; /* gpio PW2 */
+
+		clocks = <&tegra_car 112>, <&tegra_car 113>, <&tegra_car 93>;
+		clock-names = "pll_a", "pll_a_out0", "mclk";
 	};
 };
diff --git a/arch/arm/boot/dts/tegra20-trimslice.dts b/arch/arm/boot/dts/tegra20-trimslice.dts
index 5d79e4f..f2fbc38 100644
--- a/arch/arm/boot/dts/tegra20-trimslice.dts
+++ b/arch/arm/boot/dts/tegra20-trimslice.dts
@@ -300,6 +300,15 @@
 		};
 	};
 
+	pmc {
+		nvidia,suspend-mode = <2>;
+		nvidia,cpu-pwr-good-time = <5000>;
+		nvidia,cpu-pwr-off-time = <5000>;
+		nvidia,core-pwr-good-time = <3845 3845>;
+		nvidia,core-pwr-off-time = <3875>;
+		nvidia,sys-clock-req-active-high;
+	};
+
 	usb@c5000000 {
 		status = "okay";
 		nvidia,vbus-gpio = <&gpio 170 0>; /* gpio PV2 */
@@ -325,11 +334,35 @@
 
 	sdhci@c8000600 {
 		status = "okay";
-		cd-gpios = <&gpio 121 0>; /* gpio PP1 */
+		cd-gpios = <&gpio 121 1>; /* gpio PP1 */
 		wp-gpios = <&gpio 122 0>; /* gpio PP2 */
 		bus-width = <4>;
 	};
 
+	clocks {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		clk32k_in: clock {
+			compatible = "fixed-clock";
+			reg=<0>;
+			#clock-cells = <0>;
+			clock-frequency = <32768>;
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		power {
+			label = "Power";
+			gpios = <&gpio 190 1>; /* gpio PX6, active low */
+			linux,code = <116>; /* KEY_POWER */
+			gpio-key,wakeup;
+		};
+	};
+
 	poweroff {
 		compatible = "gpio-poweroff";
 		gpios = <&gpio 191 1>; /* gpio PX7, active low */
@@ -363,5 +396,8 @@
 		compatible = "nvidia,tegra-audio-trimslice";
 		nvidia,i2s-controller = <&tegra_i2s1>;
 		nvidia,audio-codec = <&codec>;
+
+		clocks = <&tegra_car 112>, <&tegra_car 113>, <&tegra_car 93>;
+		clock-names = "pll_a", "pll_a_out0", "mclk";
 	};
 };
diff --git a/arch/arm/boot/dts/tegra20-ventana.dts b/arch/arm/boot/dts/tegra20-ventana.dts
index 425c890..395df48 100644
--- a/arch/arm/boot/dts/tegra20-ventana.dts
+++ b/arch/arm/boot/dts/tegra20-ventana.dts
@@ -493,6 +493,12 @@
 
 	pmc {
 		nvidia,invert-interrupt;
+		nvidia,suspend-mode = <2>;
+		nvidia,cpu-pwr-good-time = <2000>;
+		nvidia,cpu-pwr-off-time = <100>;
+		nvidia,core-pwr-good-time = <3845 3845>;
+		nvidia,core-pwr-off-time = <458>;
+		nvidia,sys-clock-req-active-high;
 	};
 
 	usb@c5000000 {
@@ -516,11 +522,12 @@
 		status = "okay";
 		power-gpios = <&gpio 86 0>; /* gpio PK6 */
 		bus-width = <4>;
+		keep-power-in-suspend;
 	};
 
 	sdhci@c8000400 {
 		status = "okay";
-		cd-gpios = <&gpio 69 0>; /* gpio PI5 */
+		cd-gpios = <&gpio 69 1>; /* gpio PI5 */
 		wp-gpios = <&gpio 57 0>; /* gpio PH1 */
 		power-gpios = <&gpio 70 0>; /* gpio PI6 */
 		bus-width = <4>;
@@ -529,6 +536,31 @@
 	sdhci@c8000600 {
 		status = "okay";
 		bus-width = <8>;
+		non-removable;
+	};
+
+	clocks {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		clk32k_in: clock {
+			compatible = "fixed-clock";
+			reg=<0>;
+			#clock-cells = <0>;
+			clock-frequency = <32768>;
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		power {
+			label = "Power";
+			gpios = <&gpio 170 1>; /* gpio PV2, active low */
+			linux,code = <116>; /* KEY_POWER */
+			gpio-key,wakeup;
+		};
 	};
 
 	regulators {
@@ -607,5 +639,8 @@
 		nvidia,hp-det-gpios = <&gpio 178 0>; /* gpio PW2 */
 		nvidia,int-mic-en-gpios = <&gpio 184 0>; /* gpio PX0 */
 		nvidia,ext-mic-en-gpios = <&gpio 185 0>; /* gpio PX1 */
+
+		clocks = <&tegra_car 112>, <&tegra_car 113>, <&tegra_car 93>;
+		clock-names = "pll_a", "pll_a_out0", "mclk";
 	};
 };
diff --git a/arch/arm/boot/dts/tegra20-whistler.dts b/arch/arm/boot/dts/tegra20-whistler.dts
index ea57c0f..2ed6bb8 100644
--- a/arch/arm/boot/dts/tegra20-whistler.dts
+++ b/arch/arm/boot/dts/tegra20-whistler.dts
@@ -496,6 +496,14 @@
 
 	pmc {
 		nvidia,invert-interrupt;
+		nvidia,suspend-mode = <2>;
+		nvidia,cpu-pwr-good-time = <2000>;
+		nvidia,cpu-pwr-off-time = <1000>;
+		nvidia,core-pwr-good-time = <0 3845>;
+		nvidia,core-pwr-off-time = <93727>;
+		nvidia,core-power-req-active-high;
+		nvidia,sys-clock-req-active-high;
+		nvidia,combined-power-req;
 	};
 
 	usb@c5000000 {
@@ -510,6 +518,7 @@
 
 	sdhci@c8000400 {
 		status = "okay";
+		cd-gpios = <&gpio 69 1>; /* gpio PI5 */
 		wp-gpios = <&gpio 173 0>; /* gpio PV5 */
 		bus-width = <8>;
 	};
@@ -517,6 +526,20 @@
 	sdhci@c8000600 {
 		status = "okay";
 		bus-width = <8>;
+		non-removable;
+	};
+
+	clocks {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		clk32k_in: clock {
+			compatible = "fixed-clock";
+			reg=<0>;
+			#clock-cells = <0>;
+			clock-frequency = <32768>;
+		};
 	};
 
 	kbc {
@@ -525,6 +548,7 @@
 		nvidia,repeat-delay-ms = <160>;
 		nvidia,kbc-row-pins = <0 1 2>;
 		nvidia,kbc-col-pins = <16 17>;
+		nvidia,wakeup-source;
 		linux,keymap = <0x00000074	/* KEY_POWER */
 				0x01000066	/* KEY_HOME */
 				0x0101009E	/* KEY_BACK */
@@ -559,5 +583,8 @@
 
 		nvidia,i2s-controller = <&tegra_i2s1>;
 		nvidia,audio-codec = <&codec>;
+
+		clocks = <&tegra_car 112>, <&tegra_car 113>, <&tegra_car 93>;
+		clock-names = "pll_a", "pll_a_out0", "mclk";
 	};
 };
diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi
index 3d3f64d..5fc661d 100644
--- a/arch/arm/boot/dts/tegra20.dtsi
+++ b/arch/arm/boot/dts/tegra20.dtsi
@@ -145,6 +145,7 @@
 			      0 1 0x04
 			      0 41 0x04
 			      0 42 0x04>;
+		clocks = <&tegra_car 5>;
 	};
 
 	tegra_car: clock {
@@ -208,7 +209,7 @@
 		compatible = "nvidia,tegra20-das";
 		reg = <0x70000c00 0x80>;
 	};
-	
+
 	tegra_ac97: ac97 {
 		compatible = "nvidia,tegra20-ac97";
 		reg = <0x70002000 0x200>;
@@ -298,12 +299,14 @@
 		reg = <0x7000a000 0x100>;
 		#pwm-cells = <2>;
 		clocks = <&tegra_car 17>;
+		status = "disabled";
 	};
 
 	rtc {
 		compatible = "nvidia,tegra20-rtc";
 		reg = <0x7000e000 0x100>;
 		interrupts = <0 2 0x04>;
+		clocks = <&tegra_car 4>;
 	};
 
 	i2c@7000c000 {
@@ -416,6 +419,8 @@
 	pmc {
 		compatible = "nvidia,tegra20-pmc";
 		reg = <0x7000e400 0x400>;
+		clocks = <&tegra_car 110>, <&clk32k_in>;
+		clock-names = "pclk", "clk32k_in";
 	};
 
 	memory-controller@7000f000 {
@@ -438,31 +443,6 @@
 		#size-cells = <0>;
 	};
 
-	phy1: usb-phy@c5000400 {
-		compatible = "nvidia,tegra20-usb-phy";
-		reg = <0xc5000400 0x3c00>;
-		phy_type = "utmi";
-		nvidia,has-legacy-mode;
-		clocks = <&tegra_car 22>, <&tegra_car 127>;
-		clock-names = "phy", "pll_u";
-	};
-
-	phy2: usb-phy@c5004400 {
-		compatible = "nvidia,tegra20-usb-phy";
-		reg = <0xc5004400 0x3c00>;
-		phy_type = "ulpi";
-		clocks = <&tegra_car 94>, <&tegra_car 127>;
-		clock-names = "phy", "pll_u";
-	};
-
-	phy3: usb-phy@c5008400 {
-		compatible = "nvidia,tegra20-usb-phy";
-		reg = <0xc5008400 0x3C00>;
-		phy_type = "utmi";
-		clocks = <&tegra_car 22>, <&tegra_car 127>;
-		clock-names = "phy", "pll_u";
-	};
-
 	usb@c5000000 {
 		compatible = "nvidia,tegra20-ehci", "usb-ehci";
 		reg = <0xc5000000 0x4000>;
@@ -475,6 +455,15 @@
 		status = "disabled";
 	};
 
+	phy1: usb-phy@c5000400 {
+		compatible = "nvidia,tegra20-usb-phy";
+		reg = <0xc5000400 0x3c00>;
+		phy_type = "utmi";
+		nvidia,has-legacy-mode;
+		clocks = <&tegra_car 22>, <&tegra_car 127>;
+		clock-names = "phy", "pll_u";
+	};
+
 	usb@c5004000 {
 		compatible = "nvidia,tegra20-ehci", "usb-ehci";
 		reg = <0xc5004000 0x4000>;
@@ -485,6 +474,14 @@
 		status = "disabled";
 	};
 
+	phy2: usb-phy@c5004400 {
+		compatible = "nvidia,tegra20-usb-phy";
+		reg = <0xc5004400 0x3c00>;
+		phy_type = "ulpi";
+		clocks = <&tegra_car 94>, <&tegra_car 127>;
+		clock-names = "phy", "pll_u";
+	};
+
 	usb@c5008000 {
 		compatible = "nvidia,tegra20-ehci", "usb-ehci";
 		reg = <0xc5008000 0x4000>;
@@ -495,6 +492,14 @@
 		status = "disabled";
 	};
 
+	phy3: usb-phy@c5008400 {
+		compatible = "nvidia,tegra20-usb-phy";
+		reg = <0xc5008400 0x3c00>;
+		phy_type = "utmi";
+		clocks = <&tegra_car 22>, <&tegra_car 127>;
+		clock-names = "phy", "pll_u";
+	};
+
 	sdhci@c8000000 {
 		compatible = "nvidia,tegra20-sdhci";
 		reg = <0xc8000000 0x200>;
diff --git a/arch/arm/boot/dts/tegra30-beaver.dts b/arch/arm/boot/dts/tegra30-beaver.dts
index 8ff2ff2..b732f7c 100644
--- a/arch/arm/boot/dts/tegra30-beaver.dts
+++ b/arch/arm/boot/dts/tegra30-beaver.dts
@@ -253,11 +253,18 @@
 	pmc {
 		status = "okay";
 		nvidia,invert-interrupt;
+		nvidia,suspend-mode = <2>;
+		nvidia,cpu-pwr-good-time = <2000>;
+		nvidia,cpu-pwr-off-time = <200>;
+		nvidia,core-pwr-good-time = <3845 3845>;
+		nvidia,core-pwr-off-time = <0>;
+		nvidia,core-power-req-active-high;
+		nvidia,sys-clock-req-active-high;
 	};
 
 	sdhci@78000000 {
 		status = "okay";
-		cd-gpios = <&gpio 69 0>; /* gpio PI5 */
+		cd-gpios = <&gpio 69 1>; /* gpio PI5 */
 		wp-gpios = <&gpio 155 0>; /* gpio PT3 */
 		power-gpios = <&gpio 31 0>; /* gpio PD7 */
 		bus-width = <4>;
@@ -266,6 +273,20 @@
 	sdhci@78000600 {
 		status = "okay";
 		bus-width = <8>;
+		non-removable;
+	};
+
+	clocks {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		clk32k_in: clock {
+			compatible = "fixed-clock";
+			reg=<0>;
+			#clock-cells = <0>;
+			clock-frequency = <32768>;
+		};
 	};
 
 	regulators {
diff --git a/arch/arm/boot/dts/tegra30-cardhu-a02.dts b/arch/arm/boot/dts/tegra30-cardhu-a02.dts
index adc88aa..e392bd2 100644
--- a/arch/arm/boot/dts/tegra30-cardhu-a02.dts
+++ b/arch/arm/boot/dts/tegra30-cardhu-a02.dts
@@ -88,6 +88,7 @@
 		status = "okay";
 		power-gpios = <&gpio 28 0>; /* gpio PD4 */
 		bus-width = <4>;
+		keep-power-in-suspend;
 	};
 };
 
diff --git a/arch/arm/boot/dts/tegra30-cardhu-a04.dts b/arch/arm/boot/dts/tegra30-cardhu-a04.dts
index 08163e1..d0db6c7 100644
--- a/arch/arm/boot/dts/tegra30-cardhu-a04.dts
+++ b/arch/arm/boot/dts/tegra30-cardhu-a04.dts
@@ -100,5 +100,6 @@
 		status = "okay";
 		power-gpios = <&gpio 27 0>; /* gpio PD3 */
 		bus-width = <4>;
+		keep-power-in-suspend;
 	};
 };
diff --git a/arch/arm/boot/dts/tegra30-cardhu.dtsi b/arch/arm/boot/dts/tegra30-cardhu.dtsi
index 1749927..01b4c26 100644
--- a/arch/arm/boot/dts/tegra30-cardhu.dtsi
+++ b/arch/arm/boot/dts/tegra30-cardhu.dtsi
@@ -307,11 +307,18 @@
 	pmc {
 		status = "okay";
 		nvidia,invert-interrupt;
+		nvidia,suspend-mode = <2>;
+		nvidia,cpu-pwr-good-time = <2000>;
+		nvidia,cpu-pwr-off-time = <200>;
+		nvidia,core-pwr-good-time = <3845 3845>;
+		nvidia,core-pwr-off-time = <0>;
+		nvidia,core-power-req-active-high;
+		nvidia,sys-clock-req-active-high;
 	};
 
 	sdhci@78000000 {
 		status = "okay";
-		cd-gpios = <&gpio 69 0>; /* gpio PI5 */
+		cd-gpios = <&gpio 69 1>; /* gpio PI5 */
 		wp-gpios = <&gpio 155 0>; /* gpio PT3 */
 		power-gpios = <&gpio 31 0>; /* gpio PD7 */
 		bus-width = <4>;
@@ -320,6 +327,20 @@
 	sdhci@78000600 {
 		status = "okay";
 		bus-width = <8>;
+		non-removable;
+	};
+
+	clocks {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		clk32k_in: clock {
+			compatible = "fixed-clock";
+			reg=<0>;
+			#clock-cells = <0>;
+			clock-frequency = <32768>;
+		};
 	};
 
 	regulators {
@@ -496,5 +517,8 @@
 
 		nvidia,spkr-en-gpios = <&wm8903 2 0>;
 		nvidia,hp-det-gpios = <&gpio 178 0>; /* gpio PW2 */
+
+		clocks = <&tegra_car 184>, <&tegra_car 185>, <&tegra_car 120>;
+		clock-names = "pll_a", "pll_a_out0", "mclk";
 	};
 };
diff --git a/arch/arm/boot/dts/tegra30.dtsi b/arch/arm/boot/dts/tegra30.dtsi
index dbf46c2..15ded60 100644
--- a/arch/arm/boot/dts/tegra30.dtsi
+++ b/arch/arm/boot/dts/tegra30.dtsi
@@ -148,6 +148,7 @@
 			      0 42 0x04
 			      0 121 0x04
 			      0 122 0x04>;
+		clocks = <&tegra_car 5>;
 	};
 
 	tegra_car: clock {
@@ -285,12 +286,14 @@
 		reg = <0x7000a000 0x100>;
 		#pwm-cells = <2>;
 		clocks = <&tegra_car 17>;
+		status = "disabled";
 	};
 
 	rtc {
 		compatible = "nvidia,tegra30-rtc", "nvidia,tegra20-rtc";
 		reg = <0x7000e000 0x100>;
 		interrupts = <0 2 0x04>;
+		clocks = <&tegra_car 4>;
 	};
 
 	i2c@7000c000 {
@@ -423,8 +426,10 @@
 	};
 
 	pmc {
-		compatible = "nvidia,tegra20-pmc", "nvidia,tegra30-pmc";
+		compatible = "nvidia,tegra30-pmc";
 		reg = <0x7000e400 0x400>;
+		clocks = <&tegra_car 218>, <&clk32k_in>;
+		clock-names = "pclk", "clk32k_in";
 	};
 
 	memory-controller {
diff --git a/arch/arm/boot/dts/vt8500-bv07.dts b/arch/arm/boot/dts/vt8500-bv07.dts
index 567cf4e..877b33a 100644
--- a/arch/arm/boot/dts/vt8500-bv07.dts
+++ b/arch/arm/boot/dts/vt8500-bv07.dts
@@ -11,26 +11,22 @@
 
 / {
 	model = "Benign BV07 Netbook";
+};
 
-	/*
-	 * Display node is based on Sascha Hauer's patch on dri-devel.
-	 * Added a bpp property to calculate the size of the framebuffer
-	 * until the binding is formalized.
-	 */
-	display: display@0 {
-		modes {
-			mode0: mode@0 {
-				hactive = <800>;
-				vactive = <480>;
-				hback-porch = <88>;
-				hfront-porch = <40>;
-				hsync-len = <0>;
-				vback-porch = <32>;
-				vfront-porch = <11>;
-				vsync-len = <1>;
-				clock = <0>;	/* unused but required */
-				bpp = <16>;	/* non-standard but required */
-			};
+&fb {
+	bits-per-pixel = <16>;
+	display-timings {
+		native-mode = <&timing0>;
+		timing0: 800x480 {
+			clock-frequency = <0>; /* unused but required */
+			hactive = <800>;
+			vactive = <480>;
+			hfront-porch = <40>;
+			hback-porch = <88>;
+			hsync-len = <0>;
+			vback-porch = <32>;
+			vfront-porch = <11>;
+			vsync-len = <1>;
 		};
 	};
 };
diff --git a/arch/arm/boot/dts/vt8500.dtsi b/arch/arm/boot/dts/vt8500.dtsi
index cf31ced..68c8dc6 100644
--- a/arch/arm/boot/dts/vt8500.dtsi
+++ b/arch/arm/boot/dts/vt8500.dtsi
@@ -98,12 +98,10 @@
 			interrupts = <43>;
 		};
 
-		fb@d800e400 {
+		fb: fb@d8050800 {
 			compatible = "via,vt8500-fb";
 			reg = <0xd800e400 0x400>;
 			interrupts = <12>;
-			display = <&display>;
-			default-mode = <&mode0>;
 		};
 
 		ge_rops@d8050400 {
diff --git a/arch/arm/boot/dts/wm8505-ref.dts b/arch/arm/boot/dts/wm8505-ref.dts
index fd4e248..edd2cec 100644
--- a/arch/arm/boot/dts/wm8505-ref.dts
+++ b/arch/arm/boot/dts/wm8505-ref.dts
@@ -11,26 +11,22 @@
 
 / {
 	model = "Wondermedia WM8505 Netbook";
+};
 
-	/*
-	 * Display node is based on Sascha Hauer's patch on dri-devel.
-	 * Added a bpp property to calculate the size of the framebuffer
-	 * until the binding is formalized.
-	 */
-	display: display@0 {
-		modes {
-			mode0: mode@0 {
-				hactive = <800>;
-				vactive = <480>;
-				hback-porch = <88>;
-				hfront-porch = <40>;
-				hsync-len = <0>;
-				vback-porch = <32>;
-				vfront-porch = <11>;
-				vsync-len = <1>;
-				clock = <0>;	/* unused but required */
-				bpp = <32>;	/* non-standard but required */
-			};
+&fb {
+	bits-per-pixel = <32>;
+	display-timings {
+		native-mode = <&timing0>;
+		timing0: 800x480 {
+			clock-frequency = <0>; /* unused but required */
+			hactive = <800>;
+			vactive = <480>;
+			hfront-porch = <40>;
+			hback-porch = <88>;
+			hsync-len = <0>;
+			vback-porch = <32>;
+			vfront-porch = <11>;
+			vsync-len = <1>;
 		};
 	};
 };
diff --git a/arch/arm/boot/dts/wm8505.dtsi b/arch/arm/boot/dts/wm8505.dtsi
index e74a1c0..bcf668d 100644
--- a/arch/arm/boot/dts/wm8505.dtsi
+++ b/arch/arm/boot/dts/wm8505.dtsi
@@ -128,11 +128,9 @@
 			interrupts = <0>;
 		};
 
-		fb@d8050800 {
+		fb: fb@d8050800 {
 			compatible = "wm,wm8505-fb";
 			reg = <0xd8050800 0x200>;
-			display = <&display>;
-			default-mode = <&mode0>;
 		};
 
 		ge_rops@d8050400 {
diff --git a/arch/arm/boot/dts/wm8650-mid.dts b/arch/arm/boot/dts/wm8650-mid.dts
index cefd938..61671a0 100644
--- a/arch/arm/boot/dts/wm8650-mid.dts
+++ b/arch/arm/boot/dts/wm8650-mid.dts
@@ -11,26 +11,24 @@
 
 / {
 	model = "Wondermedia WM8650-MID Tablet";
+};
+
+&fb {
+	bits-per-pixel = <16>;
 
-	/*
-	 * Display node is based on Sascha Hauer's patch on dri-devel.
-	 * Added a bpp property to calculate the size of the framebuffer
-	 * until the binding is formalized.
-	 */
-	display: display@0 {
-		modes {
-			mode0: mode@0 {
-				hactive = <800>;
-				vactive = <480>;
-				hback-porch = <88>;
-				hfront-porch = <40>;
-				hsync-len = <0>;
-				vback-porch = <32>;
-				vfront-porch = <11>;
-				vsync-len = <1>;
-				clock = <0>;	/* unused but required */
-				bpp = <16>;	/* non-standard but required */
-			};
+	display-timings {
+		native-mode = <&timing0>;
+		timing0: 800x480 {
+			clock-frequency = <0>; /* unused but required */
+			hactive = <800>;
+			vactive = <480>;
+			hfront-porch = <40>;
+			hback-porch = <88>;
+			hsync-len = <0>;
+			vback-porch = <32>;
+			vfront-porch = <11>;
+			vsync-len = <1>;
 		};
 	};
 };
+
diff --git a/arch/arm/boot/dts/wm8650.dtsi b/arch/arm/boot/dts/wm8650.dtsi
index db3c0a1..9313407 100644
--- a/arch/arm/boot/dts/wm8650.dtsi
+++ b/arch/arm/boot/dts/wm8650.dtsi
@@ -128,11 +128,9 @@
 			interrupts = <43>;
 		};
 
-		fb@d8050800 {
+		fb: fb@d8050800 {
 			compatible = "wm,wm8505-fb";
 			reg = <0xd8050800 0x200>;
-			display = <&display>;
-			default-mode = <&mode0>;
 		};
 
 		ge_rops@d8050400 {
diff --git a/arch/arm/boot/dts/wm8850-w70v2.dts b/arch/arm/boot/dts/wm8850-w70v2.dts
index fcc660c..32d2253 100644
--- a/arch/arm/boot/dts/wm8850-w70v2.dts
+++ b/arch/arm/boot/dts/wm8850-w70v2.dts
@@ -15,28 +15,6 @@
 / {
 	model = "Wondermedia WM8850-W70v2 Tablet";
 
-	/*
-	 * Display node is based on Sascha Hauer's patch on dri-devel.
-	 * Added a bpp property to calculate the size of the framebuffer
-	 * until the binding is formalized.
-	 */
-	display: display@0 {
-		modes {
-			mode0: mode@0 {
-				hactive = <800>;
-				vactive = <480>;
-				hback-porch = <88>;
-				hfront-porch = <40>;
-				hsync-len = <0>;
-				vback-porch = <32>;
-				vfront-porch = <11>;
-				vsync-len = <1>;
-				clock = <0>;	/* unused but required */
-				bpp = <16>;	/* non-standard but required */
-			};
-		};
-	};
-
 	backlight {
 		compatible = "pwm-backlight";
 		pwms = <&pwm 0 50000 1>;	/* duty inverted */
@@ -45,3 +23,21 @@
 		default-brightness-level = <5>;
 	};
 };
+
+&fb {
+	bits-per-pixel = <16>;
+	display-timings {
+		native-mode = <&timing0>;
+		timing0: 800x480 {
+			clock-frequency = <0>; /* unused but required */
+			hactive = <800>;
+			vactive = <480>;
+			hfront-porch = <40>;
+			hback-porch = <88>;
+			hsync-len = <0>;
+			vback-porch = <32>;
+			vfront-porch = <11>;
+			vsync-len = <1>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/wm8850.dtsi b/arch/arm/boot/dts/wm8850.dtsi
index e8cbfdc..7149cd1 100644
--- a/arch/arm/boot/dts/wm8850.dtsi
+++ b/arch/arm/boot/dts/wm8850.dtsi
@@ -135,11 +135,9 @@
 			};
 		};
 
-		fb@d8051700 {
+		fb: fb@d8051700 {
 			compatible = "wm,wm8505-fb";
 			reg = <0xd8051700 0x200>;
-			display = <&display>;
-			default-mode = <&mode0>;
 		};
 
 		ge_rops@d8050400 {
diff --git a/arch/arm/boot/dts/zynq-7000.dtsi b/arch/arm/boot/dts/zynq-7000.dtsi
index 5914b56..14fb2e6 100644
--- a/arch/arm/boot/dts/zynq-7000.dtsi
+++ b/arch/arm/boot/dts/zynq-7000.dtsi
@@ -15,6 +15,13 @@
 / {
 	compatible = "xlnx,zynq-7000";
 
+	pmu {
+		compatible = "arm,cortex-a9-pmu";
+		interrupts = <0 5 4>, <0 6 4>;
+		interrupt-parent = <&intc>;
+		reg = < 0xf8891000 0x1000 0xf8893000 0x1000 >;
+	};
+
 	amba {
 		compatible = "simple-bus";
 		#address-cells = <1>;
@@ -111,56 +118,30 @@
 		};
 
 		ttc0: ttc0@f8001000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "xlnx,ttc";
+			interrupt-parent = <&intc>;
+			interrupts = < 0 10 4 0 11 4 0 12 4 >;
+			compatible = "cdns,ttc";
 			reg = <0xF8001000 0x1000>;
 			clocks = <&cpu_clk 3>;
 			clock-names = "cpu_1x";
 			clock-ranges;
-
-			ttc0_0: ttc0.0 {
-				status = "disabled";
-				reg = <0>;
-				interrupts = <0 10 4>;
-			};
-			ttc0_1: ttc0.1 {
-				status = "disabled";
-				reg = <1>;
-				interrupts = <0 11 4>;
-			};
-			ttc0_2: ttc0.2 {
-				status = "disabled";
-				reg = <2>;
-				interrupts = <0 12 4>;
-			};
 		};
 
 		ttc1: ttc1@f8002000 {
-			#interrupt-parent = <&intc>;
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "xlnx,ttc";
+			interrupt-parent = <&intc>;
+			interrupts = < 0 37 4 0 38 4 0 39 4 >;
+			compatible = "cdns,ttc";
 			reg = <0xF8002000 0x1000>;
 			clocks = <&cpu_clk 3>;
 			clock-names = "cpu_1x";
 			clock-ranges;
-
-			ttc1_0: ttc1.0 {
-				status = "disabled";
-				reg = <0>;
-				interrupts = <0 37 4>;
-			};
-			ttc1_1: ttc1.1 {
-				status = "disabled";
-				reg = <1>;
-				interrupts = <0 38 4>;
-			};
-			ttc1_2: ttc1.2 {
-				status = "disabled";
-				reg = <2>;
-				interrupts = <0 39 4>;
-			};
 		};
+		scutimer: scutimer@f8f00600 {
+			interrupt-parent = <&intc>;
+			interrupts = < 1 13 0x301 >;
+			compatible = "arm,cortex-a9-twd-timer";
+			reg = < 0xf8f00600 0x20 >;
+			clocks = <&cpu_clk 1>;
+		} ;
 	};
 };
diff --git a/arch/arm/boot/dts/zynq-zc702.dts b/arch/arm/boot/dts/zynq-zc702.dts
index c772942..86f44d5 100644
--- a/arch/arm/boot/dts/zynq-zc702.dts
+++ b/arch/arm/boot/dts/zynq-zc702.dts
@@ -32,13 +32,3 @@
 &ps_clk {
 	clock-frequency = <33333330>;
 };
-
-&ttc0_0 {
-	status = "ok";
-	compatible = "xlnx,ttc-counter-clocksource";
-};
-
-&ttc0_1 {
-	status = "ok";
-	compatible = "xlnx,ttc-counter-clockevent";
-};
diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile
index dc8dd0d..45f7eae 100644
--- a/arch/arm/common/Makefile
+++ b/arch/arm/common/Makefile
@@ -2,6 +2,8 @@
 # Makefile for the linux kernel.
 #
 
+obj-y				+= firmware.o
+
 obj-$(CONFIG_ICST)		+= icst.o
 obj-$(CONFIG_SA1111)		+= sa1111.o
 obj-$(CONFIG_PCI_HOST_VIA82C505) += via82c505.o
diff --git a/arch/arm/common/firmware.c b/arch/arm/common/firmware.c
new file mode 100644
index 0000000..27ddccb
--- /dev/null
+++ b/arch/arm/common/firmware.c
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2012 Samsung Electronics.
+ * Kyungmin Park <kyungmin.park@samsung.com>
+ * Tomasz Figa <t.figa@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/suspend.h>
+
+#include <asm/firmware.h>
+
+static const struct firmware_ops default_firmware_ops;
+
+const struct firmware_ops *firmware_ops = &default_firmware_ops;
diff --git a/arch/arm/configs/ape6evm_defconfig b/arch/arm/configs/ape6evm_defconfig
new file mode 100644
index 0000000..dab5a7d
--- /dev/null
+++ b/arch/arm/configs/ape6evm_defconfig
@@ -0,0 +1,95 @@
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_CGROUPS=y
+CONFIG_CGROUP_SCHED=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_EMBEDDED=y
+CONFIG_PERF_EVENTS=y
+CONFIG_SLAB=y
+# CONFIG_BLOCK is not set
+CONFIG_ARCH_SHMOBILE=y
+CONFIG_ARCH_R8A73A4=y
+CONFIG_MACH_APE6EVM=y
+# CONFIG_ARM_THUMB is not set
+CONFIG_CPU_BPREDICT_DISABLE=y
+CONFIG_PL310_ERRATA_588369=y
+CONFIG_ARM_ERRATA_754322=y
+CONFIG_SMP=y
+CONFIG_SCHED_MC=y
+CONFIG_HAVE_ARM_ARCH_TIMER=y
+CONFIG_NR_CPUS=8
+CONFIG_AEABI=y
+CONFIG_HIGHMEM=y
+CONFIG_HIGHPTE=y
+# CONFIG_HW_PERF_EVENTS is not set
+# CONFIG_COMPACTION is not set
+# CONFIG_CROSS_MEMORY_ATTACH is not set
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+CONFIG_BINFMT_MISC=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=y
+CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_INET_LRO is not set
+# CONFIG_IPV6_SIT is not set
+CONFIG_NETFILTER=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_FW_LOADER_USER_HELPER is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NET_CADENCE is not set
+CONFIG_SMC91X=y
+CONFIG_SMSC911X=y
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+CONFIG_SERIAL_NONSTANDARD=y
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_NR_UARTS=12
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_GPIO_SH_PFC=y
+CONFIG_GPIOLIB=y
+# CONFIG_HWMON is not set
+CONFIG_THERMAL=y
+CONFIG_RCAR_THERMAL=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_GPIO=y
+# CONFIG_HID is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_IOMMU_SUPPORT is not set
+# CONFIG_DNOTIFY is not set
+CONFIG_TMPFS=y
+# CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_V4_1=y
+CONFIG_ROOT_NFS=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_ENABLE_DEFAULT_TRACERS=y
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRC_CCITT=y
+CONFIG_CRC16=y
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC_ITU_T=y
+CONFIG_CRC7=y
+CONFIG_LIBCRC32C=y
diff --git a/arch/arm/configs/armadillo800eva_defconfig b/arch/arm/configs/armadillo800eva_defconfig
index 0b98100..0f2d80d 100644
--- a/arch/arm/configs/armadillo800eva_defconfig
+++ b/arch/arm/configs/armadillo800eva_defconfig
@@ -20,15 +20,19 @@ CONFIG_ARCH_R8A7740=y
 CONFIG_MACH_ARMADILLO800EVA=y
 # CONFIG_SH_TIMER_TMU is not set
 CONFIG_ARM_THUMB=y
-CONFIG_CPU_BPREDICT_DISABLE=y
 CONFIG_CACHE_L2X0=y
 CONFIG_ARM_ERRATA_430973=y
 CONFIG_ARM_ERRATA_458693=y
 CONFIG_ARM_ERRATA_460075=y
+CONFIG_PL310_ERRATA_588369=y
 CONFIG_ARM_ERRATA_720789=y
+CONFIG_PL310_ERRATA_727915=y
 CONFIG_ARM_ERRATA_743622=y
 CONFIG_ARM_ERRATA_751472=y
+CONFIG_PL310_ERRATA_753970=y
 CONFIG_ARM_ERRATA_754322=y
+CONFIG_PL310_ERRATA_769419=y
+CONFIG_ARM_ERRATA_775420=y
 CONFIG_AEABI=y
 # CONFIG_OABI_COMPAT is not set
 CONFIG_FORCE_MAX_ZONEORDER=13
@@ -37,6 +41,7 @@ CONFIG_ZBOOT_ROM_BSS=0x0
 CONFIG_ARM_APPENDED_DTB=y
 CONFIG_KEXEC=y
 CONFIG_VFP=y
+CONFIG_NEON=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 CONFIG_PM_RUNTIME=y
 CONFIG_NET=y
@@ -88,6 +93,7 @@ CONFIG_I2C=y
 CONFIG_I2C_GPIO=y
 CONFIG_I2C_SH_MOBILE=y
 # CONFIG_HWMON is not set
+CONFIG_REGULATOR=y
 CONFIG_MEDIA_SUPPORT=y
 CONFIG_VIDEO_DEV=y
 CONFIG_MEDIA_CAMERA_SUPPORT=y
diff --git a/arch/arm/configs/at91_dt_defconfig b/arch/arm/configs/at91_dt_defconfig
index 1ea9590..047f2a4 100644
--- a/arch/arm/configs/at91_dt_defconfig
+++ b/arch/arm/configs/at91_dt_defconfig
@@ -20,7 +20,7 @@ CONFIG_SOC_AT91SAM9263=y
 CONFIG_SOC_AT91SAM9G45=y
 CONFIG_SOC_AT91SAM9X5=y
 CONFIG_SOC_AT91SAM9N12=y
-CONFIG_MACH_AT91SAM_DT=y
+CONFIG_MACH_AT91SAM9_DT=y
 CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
 CONFIG_AT91_TIMER_HZ=128
 CONFIG_AEABI=y
diff --git a/arch/arm/configs/at91sam9260_defconfig b/arch/arm/configs/at91sam9260_defconfig
index 0ea5d2c..05618eb 100644
--- a/arch/arm/configs/at91sam9260_defconfig
+++ b/arch/arm/configs/at91sam9260_defconfig
@@ -22,7 +22,7 @@ CONFIG_MACH_QIL_A9260=y
 CONFIG_MACH_CPU9260=y
 CONFIG_MACH_FLEXIBITY=y
 CONFIG_MACH_SNAPPER_9260=y
-CONFIG_MACH_AT91SAM_DT=y
+CONFIG_MACH_AT91SAM9_DT=y
 CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
 # CONFIG_ARM_THUMB is not set
 CONFIG_ZBOOT_ROM_TEXT=0x0
diff --git a/arch/arm/configs/at91sam9g20_defconfig b/arch/arm/configs/at91sam9g20_defconfig
index 3b18810..892e828 100644
--- a/arch/arm/configs/at91sam9g20_defconfig
+++ b/arch/arm/configs/at91sam9g20_defconfig
@@ -22,7 +22,7 @@ CONFIG_MACH_PCONTROL_G20=y
 CONFIG_MACH_GSIA18S=y
 CONFIG_MACH_USB_A9G20=y
 CONFIG_MACH_SNAPPER_9260=y
-CONFIG_MACH_AT91SAM_DT=y
+CONFIG_MACH_AT91SAM9_DT=y
 CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
 # CONFIG_ARM_THUMB is not set
 CONFIG_AEABI=y
diff --git a/arch/arm/configs/at91sam9g45_defconfig b/arch/arm/configs/at91sam9g45_defconfig
index 606d48f..18964cd 100644
--- a/arch/arm/configs/at91sam9g45_defconfig
+++ b/arch/arm/configs/at91sam9g45_defconfig
@@ -18,7 +18,7 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_ARCH_AT91=y
 CONFIG_ARCH_AT91SAM9G45=y
 CONFIG_MACH_AT91SAM9M10G45EK=y
-CONFIG_MACH_AT91SAM_DT=y
+CONFIG_MACH_AT91SAM9_DT=y
 CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
 CONFIG_AT91_SLOW_CLOCK=y
 CONFIG_AEABI=y
@@ -173,7 +173,6 @@ CONFIG_MMC=y
 # CONFIG_MMC_BLOCK_BOUNCE is not set
 CONFIG_SDIO_UART=m
 CONFIG_MMC_ATMELMCI=y
-CONFIG_MMC_ATMELMCI_DMA=y
 CONFIG_LEDS_ATMEL_PWM=y
 CONFIG_LEDS_GPIO=y
 CONFIG_LEDS_TRIGGER_TIMER=y
diff --git a/arch/arm/configs/bcm2835_defconfig b/arch/arm/configs/bcm2835_defconfig
index af472e4..ce98721 100644
--- a/arch/arm/configs/bcm2835_defconfig
+++ b/arch/arm/configs/bcm2835_defconfig
@@ -29,6 +29,8 @@ CONFIG_EMBEDDED=y
 CONFIG_PROFILING=y
 CONFIG_OPROFILE=y
 CONFIG_JUMP_LABEL=y
+CONFIG_ARCH_MULTI_V6=y
+# CONFIG_ARCH_MULTI_V7 is not set
 CONFIG_ARCH_BCM2835=y
 CONFIG_PREEMPT_VOLUNTARY=y
 CONFIG_AEABI=y
@@ -59,10 +61,13 @@ CONFIG_DEVTMPFS_MOUNT=y
 CONFIG_SERIAL_AMBA_PL011=y
 CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
 CONFIG_TTY_PRINTK=y
-# CONFIG_HW_RANDOM is not set
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_BCM2835=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_BCM2835=y
+CONFIG_SPI=y
+CONFIG_SPI_BCM2835=y
 CONFIG_GPIO_SYSFS=y
 # CONFIG_HWMON is not set
 # CONFIG_USB_SUPPORT is not set
@@ -108,9 +113,5 @@ CONFIG_TEST_KSTRTOX=y
 CONFIG_STRICT_DEVMEM=y
 CONFIG_DEBUG_LL=y
 CONFIG_EARLY_PRINTK=y
-# CONFIG_XZ_DEC_X86 is not set
-# CONFIG_XZ_DEC_POWERPC is not set
-# CONFIG_XZ_DEC_IA64 is not set
 # CONFIG_XZ_DEC_ARM is not set
 # CONFIG_XZ_DEC_ARMTHUMB is not set
-# CONFIG_XZ_DEC_SPARC is not set
diff --git a/arch/arm/configs/bockw_defconfig b/arch/arm/configs/bockw_defconfig
new file mode 100644
index 0000000..6524cdf
--- /dev/null
+++ b/arch/arm/configs/bockw_defconfig
@@ -0,0 +1,94 @@
+# CONFIG_ARM_PATCH_PHYS_VIRT is not set
+CONFIG_KERNEL_LZMA=y
+CONFIG_NO_HZ=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_EMBEDDED=y
+CONFIG_SLAB=y
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_ARCH_SHMOBILE=y
+CONFIG_ARCH_R8A7778=y
+CONFIG_MACH_BOCKW=y
+CONFIG_MEMORY_START=0x60000000
+CONFIG_MEMORY_SIZE=0x10000000
+CONFIG_SHMOBILE_TIMER_HZ=1024
+# CONFIG_SH_TIMER_CMT is not set
+# CONFIG_EM_TIMER_STI is not set
+CONFIG_ARM_ERRATA_430973=y
+CONFIG_ARM_ERRATA_458693=y
+CONFIG_ARM_ERRATA_460075=y
+CONFIG_ARM_ERRATA_743622=y
+CONFIG_ARM_ERRATA_754322=y
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+CONFIG_HIGHMEM=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_CMDLINE="console=ttySC0,115200 ignore_loglevel root=/dev/nfs ip=dhcp"
+CONFIG_CMDLINE_FORCE=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_SUSPEND is not set
+CONFIG_NET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=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_IPV6 is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_STANDALONE is not set
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_FW_LOADER is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+CONFIG_SMSC911X=y
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_WIZNET 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_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_NR_UARTS=6
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+# CONFIG_HW_RANDOM is not set
+# CONFIG_HWMON is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_UIO=y
+CONFIG_UIO_PDRV_GENIRQ=y
+# CONFIG_IOMMU_SUPPORT is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_INOTIFY_USER is not set
+CONFIG_TMPFS=y
+# CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_SWAP=y
+CONFIG_NFS_V4_1=y
+CONFIG_ROOT_NFS=y
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_FTRACE is not set
+# CONFIG_ARM_UNWIND is not set
+CONFIG_AVERAGE=y
diff --git a/arch/arm/configs/cns3420vb_defconfig b/arch/arm/configs/cns3420vb_defconfig
index 313627a..b1ff5cd 100644
--- a/arch/arm/configs/cns3420vb_defconfig
+++ b/arch/arm/configs/cns3420vb_defconfig
@@ -19,8 +19,11 @@ CONFIG_MODULE_FORCE_UNLOAD=y
 CONFIG_MODVERSIONS=y
 # CONFIG_BLK_DEV_BSG is not set
 CONFIG_IOSCHED_CFQ=m
+CONFIG_ARCH_MULTI_V6=y
+#CONFIG_ARCH_MULTI_V7 is not set
 CONFIG_ARCH_CNS3XXX=y
 CONFIG_MACH_CNS3420VB=y
+CONFIG_DEBUG_CNS3XXX=y
 CONFIG_AEABI=y
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
diff --git a/arch/arm/configs/dove_defconfig b/arch/arm/configs/dove_defconfig
index 3fe8dae..4364eff 100644
--- a/arch/arm/configs/dove_defconfig
+++ b/arch/arm/configs/dove_defconfig
@@ -75,6 +75,8 @@ CONFIG_I2C_MV64XXX=y
 CONFIG_SPI=y
 CONFIG_SPI_ORION=y
 # CONFIG_HWMON is not set
+CONFIG_THERMAL=y
+CONFIG_DOVE_THERMAL=y
 CONFIG_USB=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_ROOT_HUB_TT=y
diff --git a/arch/arm/configs/h7201_defconfig b/arch/arm/configs/h7201_defconfig
deleted file mode 100644
index bee94d2..0000000
--- a/arch/arm/configs/h7201_defconfig
+++ /dev/null
@@ -1,27 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_MODULES=y
-CONFIG_ARCH_H720X=y
-CONFIG_ARCH_H7201=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_FPE_NWFPE=y
-CONFIG_MTD=y
-CONFIG_MTD_DEBUG=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_CFI_ADV_OPTIONS=y
-CONFIG_MTD_CFI_INTELEXT=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=8192
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_SOUND=m
-CONFIG_EXT2_FS=y
-CONFIG_JFFS2_FS=y
-CONFIG_DEBUG_USER=y
diff --git a/arch/arm/configs/h7202_defconfig b/arch/arm/configs/h7202_defconfig
deleted file mode 100644
index e16d3f3..0000000
--- a/arch/arm/configs/h7202_defconfig
+++ /dev/null
@@ -1,47 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_MODULES=y
-CONFIG_ARCH_H720X=y
-CONFIG_ARCH_H7202=y
-# CONFIG_ARM_THUMB is not set
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="console=ttyS0,19200"
-CONFIG_FPE_NWFPE=y
-CONFIG_FPE_NWFPE_XP=y
-CONFIG_NET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IPV6 is not set
-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_INTELEXT=y
-CONFIG_MTD_H720X=y
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_FB=y
-CONFIG_FB_MODE_HELPERS=y
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_USB_GADGET=m
-CONFIG_USB_ZERO=m
-CONFIG_USB_GADGETFS=m
-CONFIG_USB_MASS_STORAGE=m
-CONFIG_USB_G_SERIAL=m
-CONFIG_EXT2_FS=y
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_INFO=y
-CONFIG_DEBUG_USER=y
diff --git a/arch/arm/configs/imx_v4_v5_defconfig b/arch/arm/configs/imx_v4_v5_defconfig
index 02c657a..f07a847 100644
--- a/arch/arm/configs/imx_v4_v5_defconfig
+++ b/arch/arm/configs/imx_v4_v5_defconfig
@@ -109,6 +109,7 @@ CONFIG_I2C_IMX=y
 CONFIG_SPI=y
 CONFIG_SPI_IMX=y
 CONFIG_SPI_SPIDEV=y
+CONFIG_GPIO_SYSFS=y
 CONFIG_W1=y
 CONFIG_W1_MASTER_MXC=y
 CONFIG_W1_SLAVE_THERM=y
diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig
index e36b010..12f50c7 100644
--- a/arch/arm/configs/imx_v6_v7_defconfig
+++ b/arch/arm/configs/imx_v6_v7_defconfig
@@ -9,6 +9,7 @@ CONFIG_CGROUPS=y
 CONFIG_RELAY=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_EXPERT=y
+CONFIG_PERF_EVENTS=y
 # CONFIG_SLUB_DEBUG is not set
 # CONFIG_COMPAT_BRK is not set
 CONFIG_MODULES=y
diff --git a/arch/arm/configs/kirkwood_defconfig b/arch/arm/configs/kirkwood_defconfig
index 13482ea..3d8667f 100644
--- a/arch/arm/configs/kirkwood_defconfig
+++ b/arch/arm/configs/kirkwood_defconfig
@@ -56,7 +56,6 @@ CONFIG_AEABI=y
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
 CONFIG_CPU_IDLE=y
-CONFIG_CPU_IDLE_KIRKWOOD=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -119,6 +118,8 @@ CONFIG_SPI=y
 CONFIG_SPI_ORION=y
 CONFIG_GPIO_SYSFS=y
 # CONFIG_HWMON is not set
+CONFIG_THERMAL=y
+CONFIG_KIRKWOOD_THERMAL=y
 CONFIG_WATCHDOG=y
 CONFIG_ORION_WATCHDOG=y
 CONFIG_HID_DRAGONRISE=y
diff --git a/arch/arm/configs/kzm9g_defconfig b/arch/arm/configs/kzm9g_defconfig
index 670c3b6..1ad0280 100644
--- a/arch/arm/configs/kzm9g_defconfig
+++ b/arch/arm/configs/kzm9g_defconfig
@@ -33,7 +33,6 @@ CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_SMP=y
 CONFIG_SCHED_MC=y
-CONFIG_PREEMPT=y
 CONFIG_AEABI=y
 # CONFIG_OABI_COMPAT is not set
 CONFIG_HIGHMEM=y
@@ -85,10 +84,12 @@ CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_SH_MOBILE=y
 CONFIG_GPIO_PCF857X=y
 # CONFIG_HWMON is not set
+CONFIG_MFD_AS3711=y
 CONFIG_REGULATOR=y
-CONFIG_REGULATOR_DUMMY=y
+CONFIG_REGULATOR_AS3711=y
 CONFIG_FB=y
 CONFIG_FB_SH_MOBILE_LCDC=y
+CONFIG_BACKLIGHT_AS3711=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_LOGO=y
 CONFIG_FB_SH_MOBILE_MERAM=y
diff --git a/arch/arm/configs/lpc32xx_defconfig b/arch/arm/configs/lpc32xx_defconfig
index 92386b2..8fee514 100644
--- a/arch/arm/configs/lpc32xx_defconfig
+++ b/arch/arm/configs/lpc32xx_defconfig
@@ -1,4 +1,3 @@
-CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
@@ -18,6 +17,7 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
 CONFIG_PARTITION_ADVANCED=y
 CONFIG_ARCH_LPC32XX=y
+CONFIG_GPIO_PCA953X=y
 CONFIG_KEYBOARD_GPIO_POLLED=y
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
@@ -48,6 +48,8 @@ CONFIG_IPV6=y
 CONFIG_IPV6_PRIVACY=y
 # CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
 CONFIG_MTD_CMDLINE_PARTS=y
@@ -55,7 +57,6 @@ CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_M25P80=y
 CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_MUSEUM_IDS=y
 CONFIG_MTD_NAND_SLC_LPC32XX=y
 CONFIG_MTD_NAND_MLC_LPC32XX=y
 CONFIG_BLK_DEV_LOOP=y
@@ -70,7 +71,6 @@ CONFIG_BLK_DEV_SD=y
 CONFIG_NETDEVICES=y
 CONFIG_MII=y
 # CONFIG_NET_VENDOR_BROADCOM is not set
-# CONFIG_NET_VENDOR_CHELSIO is not set
 # CONFIG_NET_VENDOR_CIRRUS is not set
 # CONFIG_NET_VENDOR_FARADAY is not set
 # CONFIG_NET_VENDOR_INTEL is not set
@@ -84,7 +84,6 @@ CONFIG_LPC_ENET=y
 # CONFIG_NET_VENDOR_STMICRO is not set
 CONFIG_SMSC_PHY=y
 # CONFIG_WLAN is not set
-CONFIG_INPUT_MATRIXKMAP=y
 # CONFIG_INPUT_MOUSEDEV_PSAUX is not set
 CONFIG_INPUT_MOUSEDEV_SCREEN_X=240
 CONFIG_INPUT_MOUSEDEV_SCREEN_Y=320
@@ -108,6 +107,19 @@ CONFIG_I2C_PNX=y
 CONFIG_SPI=y
 CONFIG_SPI_PL022=y
 CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_GENERIC_PLATFORM=y
+CONFIG_GPIO_EM=y
+CONFIG_GPIO_PL061=y
+CONFIG_GPIO_MAX7300=y
+CONFIG_GPIO_MAX732X=y
+CONFIG_GPIO_PCF857X=y
+CONFIG_GPIO_SX150X=y
+CONFIG_GPIO_ADP5588=y
+CONFIG_GPIO_ADNP=y
+CONFIG_GPIO_MAX7301=y
+CONFIG_GPIO_MCP23S08=y
+CONFIG_GPIO_MC33880=y
+CONFIG_GPIO_74X164=y
 CONFIG_SENSORS_DS620=y
 CONFIG_SENSORS_MAX6639=y
 CONFIG_WATCHDOG=y
@@ -143,6 +155,7 @@ CONFIG_USB_G_SERIAL=m
 CONFIG_MMC=y
 # CONFIG_MMC_BLOCK_BOUNCE is not set
 CONFIG_MMC_ARMMMCI=y
+CONFIG_MMC_SPI=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
 CONFIG_LEDS_PCA9532=y
diff --git a/arch/arm/configs/mackerel_defconfig b/arch/arm/configs/mackerel_defconfig
index 7594b3a..9fb1189 100644
--- a/arch/arm/configs/mackerel_defconfig
+++ b/arch/arm/configs/mackerel_defconfig
@@ -75,6 +75,7 @@ CONFIG_I2C=y
 CONFIG_I2C_SH_MOBILE=y
 # CONFIG_HWMON is not set
 # CONFIG_MFD_SUPPORT is not set
+CONFIG_REGULATOR=y
 CONFIG_FB=y
 CONFIG_FB_MODE_HELPERS=y
 CONFIG_FB_SH_MOBILE_LCDC=y
@@ -94,6 +95,9 @@ CONFIG_USB_RENESAS_USBHS=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_RENESAS_USBHS_UDC=y
+CONFIG_MMC=y
+CONFIG_MMC_SDHI=y
+CONFIG_MMC_SH_MMCIF=y
 CONFIG_DMADEVICES=y
 CONFIG_SH_DMAE=y
 CONFIG_EXT2_FS=y
diff --git a/arch/arm/configs/marzen_defconfig b/arch/arm/configs/marzen_defconfig
index afb17d6..494e70a 100644
--- a/arch/arm/configs/marzen_defconfig
+++ b/arch/arm/configs/marzen_defconfig
@@ -49,6 +49,10 @@ CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_FW_LOADER is not set
 CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
+CONFIG_ATA=y
+CONFIG_ATA_SFF=y
+CONFIG_ATA_BMDMA=y
+CONFIG_SATA_RCAR=y
 CONFIG_NETDEVICES=y
 # CONFIG_NET_VENDOR_BROADCOM is not set
 # CONFIG_NET_VENDOR_FARADAY is not set
@@ -75,6 +79,7 @@ CONFIG_I2C_RCAR=y
 CONFIG_SPI=y
 CONFIG_SPI_SH_HSPI=y
 CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_RCAR=y
 # CONFIG_HWMON is not set
 CONFIG_THERMAL=y
 CONFIG_RCAR_THERMAL=y
@@ -88,6 +93,9 @@ CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_OHCI_HCD_PLATFORM=y
 CONFIG_USB_EHCI_HCD_PLATFORM=y
 CONFIG_USB_STORAGE=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
 CONFIG_UIO=y
 CONFIG_UIO_PDRV_GENIRQ=y
 # CONFIG_IOMMU_SUPPORT is not set
diff --git a/arch/arm/configs/msm_defconfig b/arch/arm/configs/msm_defconfig
index 2b8f7af..44f9291 100644
--- a/arch/arm/configs/msm_defconfig
+++ b/arch/arm/configs/msm_defconfig
@@ -1,72 +1,136 @@
-CONFIG_EXPERIMENTAL=y
+CONFIG_SYSVIPC=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_BLK_DEV_INITRD=y
-CONFIG_SLAB=y
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_EMBEDDED=y
+# CONFIG_SLUB_DEBUG is not set
+# CONFIG_COMPAT_BRK is not set
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=y
+CONFIG_KPROBES=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_PARTITION_ADVANCED=y
 CONFIG_ARCH_MSM=y
-CONFIG_MACH_HALIBUT=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
+CONFIG_ARCH_MSM8X60=y
+CONFIG_ARCH_MSM8960=y
+CONFIG_SMP=y
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
-# CONFIG_OABI_COMPAT is not set
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="mem=64M console=ttyMSM,115200n8"
-CONFIG_PM=y
+CONFIG_HIGHMEM=y
+CONFIG_HIGHPTE=y
+CONFIG_CLEANCACHE=y
+CONFIG_CC_STACKPROTECTOR=y
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_ARM_ATAG_DTB_COMPAT=y
+CONFIG_AUTO_ZRELADDR=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 CONFIG_NET=y
+CONFIG_PACKET=y
 CONFIG_UNIX=y
 CONFIG_INET=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=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_DIAG is not set
+# CONFIG_INET_LRO is not set
 # CONFIG_IPV6 is not set
-CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
+CONFIG_CFG80211=y
+CONFIG_RFKILL=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_SCSI=y
+CONFIG_SCSI_TGT=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=y
-CONFIG_NET_ETHERNET=y
-CONFIG_SMC91X=y
-CONFIG_PPP=y
-CONFIG_PPP_ASYNC=y
-CONFIG_PPP_DEFLATE=y
-CONFIG_PPP_BSDCOMP=y
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_PHYLIB=y
+CONFIG_SLIP=y
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_MODE_SLIP6=y
+CONFIG_USB_USBNET=y
+# CONFIG_USB_NET_AX8817X is not set
+# CONFIG_USB_NET_ZAURUS is not set
 CONFIG_INPUT_EVDEV=y
 # CONFIG_KEYBOARD_ATKBD is not set
-# CONFIG_INPUT_MOUSE is not set
+# CONFIG_MOUSE_PS2 is not set
+CONFIG_INPUT_JOYSTICK=y
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_INPUT_MISC=y
-# CONFIG_SERIO is not set
-CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_INPUT_UINPUT=y
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_LEGACY_PTYS is not set
 CONFIG_SERIAL_MSM=y
 CONFIG_SERIAL_MSM_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
-# CONFIG_HW_RANDOM is not set
+CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
-# CONFIG_HWMON is not set
-CONFIG_VIDEO_OUTPUT_CONTROL=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_SPI=y
+CONFIG_SSBI=y
+CONFIG_DEBUG_GPIO=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_THERMAL=y
+CONFIG_REGULATOR=y
+CONFIG_MEDIA_SUPPORT=y
 CONFIG_FB=y
-CONFIG_FB_MODE_HELPERS=y
-CONFIG_FB_TILEBLITTING=y
-CONFIG_FB_MSM=y
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_DYNAMIC_MINORS=y
+# CONFIG_SND_ARM is not set
+# CONFIG_SND_SPI is not set
+# CONFIG_SND_USB is not set
+CONFIG_SND_SOC=y
+CONFIG_HID_BATTERY_STRENGTH=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_MON=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_MSM=y
+CONFIG_USB_ACM=y
+CONFIG_USB_SERIAL=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_DEBUG_FILES=y
+CONFIG_USB_GADGET_VBUS_DRAW=500
 CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
-CONFIG_INOTIFY=y
+CONFIG_RTC_CLASS=y
+CONFIG_STAGING=y
+CONFIG_MSM_IOMMU=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_EXT4_FS=y
+CONFIG_FUSE_FS=y
+CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_CIFS=y
+CONFIG_PRINTK_TIME=y
 CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_SCHEDSTATS=y
-CONFIG_DEBUG_MUTEXES=y
-CONFIG_DEBUG_SPINLOCK_SLEEP=y
+CONFIG_LOCKUP_DETECTOR=y
+# CONFIG_DETECT_HUNG_TASK is not set
+# CONFIG_SCHED_DEBUG is not set
+CONFIG_TIMER_STATS=y
 CONFIG_DEBUG_INFO=y
-CONFIG_DEBUG_LL=y
+CONFIG_DYNAMIC_DEBUG=y
diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index e31d442..2e67a27 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -3,13 +3,19 @@ CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_ARCH_MVEBU=y
 CONFIG_MACH_ARMADA_370=y
+CONFIG_ARCH_SIRF=y
 CONFIG_MACH_ARMADA_XP=y
 CONFIG_ARCH_HIGHBANK=y
 CONFIG_ARCH_SOCFPGA=y
 CONFIG_ARCH_SUNXI=y
+CONFIG_ARCH_WM8850=y
 # CONFIG_ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA is not set
 CONFIG_ARCH_ZYNQ=y
 CONFIG_ARM_ERRATA_754322=y
+CONFIG_PLAT_SPEAR=y
+CONFIG_ARCH_SPEAR13XX=y
+CONFIG_MACH_SPEAR1310=y
+CONFIG_MACH_SPEAR1340=y
 CONFIG_SMP=y
 CONFIG_ARM_ARCH_TIMER=y
 CONFIG_AEABI=y
@@ -23,6 +29,7 @@ CONFIG_BLK_DEV_SD=y
 CONFIG_ATA=y
 CONFIG_SATA_HIGHBANK=y
 CONFIG_SATA_MV=y
+CONFIG_SATA_AHCI_PLATFORM=y
 CONFIG_NETDEVICES=y
 CONFIG_NET_CALXEDA_XGMAC=y
 CONFIG_SMSC911X=y
@@ -31,17 +38,26 @@ CONFIG_SERIO_AMBAKMI=y
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_DW=y
+CONFIG_KEYBOARD_SPEAR=y
 CONFIG_SERIAL_AMBA_PL011=y
 CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
 CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_SERIAL_SIRFSOC=y
+CONFIG_SERIAL_SIRFSOC_CONSOLE=y
+CONFIG_SERIAL_VT8500=y
+CONFIG_SERIAL_VT8500_CONSOLE=y
 CONFIG_IPMI_HANDLER=y
 CONFIG_IPMI_SI=y
 CONFIG_I2C=y
 CONFIG_I2C_DESIGNWARE_PLATFORM=y
+CONFIG_I2C_SIRF=y
 CONFIG_SPI=y
 CONFIG_SPI_PL022=y
+CONFIG_SPI_SIRF=y
+CONFIG_GPIO_PL061=y
 CONFIG_FB=y
 CONFIG_FB_ARMCLCD=y
+CONFIG_FB_WM8505=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_USB=y
 CONFIG_USB_ISP1760_HCD=y
@@ -50,11 +66,18 @@ CONFIG_MMC=y
 CONFIG_MMC_ARMMMCI=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_SPEAR=y
+CONFIG_MMC_WMT=y
 CONFIG_EDAC=y
 CONFIG_EDAC_MM_EDAC=y
 CONFIG_EDAC_HIGHBANK_MC=y
 CONFIG_EDAC_HIGHBANK_L2=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_PL031=y
+CONFIG_RTC_DRV_VT8500=y
+CONFIG_PWM=y
+CONFIG_PWM_VT8500=y
 CONFIG_DMADEVICES=y
 CONFIG_PL330_DMA=y
+CONFIG_SIRF_DMA=y
+CONFIG_DW_DMAC=y
diff --git a/arch/arm/configs/mxs_defconfig b/arch/arm/configs/mxs_defconfig
index 6a99e30..b5f6e55 100644
--- a/arch/arm/configs/mxs_defconfig
+++ b/arch/arm/configs/mxs_defconfig
@@ -22,8 +22,8 @@ CONFIG_MODVERSIONS=y
 CONFIG_BLK_DEV_INTEGRITY=y
 # CONFIG_IOSCHED_DEADLINE is not set
 # CONFIG_IOSCHED_CFQ is not set
+# CONFIG_ARCH_MULTI_V7 is not set
 CONFIG_ARCH_MXS=y
-CONFIG_MACH_MXS_DT=y
 # CONFIG_ARM_THUMB is not set
 CONFIG_PREEMPT_VOLUNTARY=y
 CONFIG_AEABI=y
@@ -75,7 +75,7 @@ CONFIG_REALTEK_PHY=y
 CONFIG_MICREL_PHY=y
 # CONFIG_WLAN is not set
 # CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-CONFIG_INPUT_EVDEV=m
+CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_INPUT_TOUCHSCREEN=y
@@ -99,6 +99,8 @@ CONFIG_SPI_MXS=y
 CONFIG_DEBUG_GPIO=y
 CONFIG_GPIO_SYSFS=y
 # CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_STMP3XXX_RTC_WATCHDOG=y
 CONFIG_REGULATOR=y
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
 CONFIG_FB=y
@@ -122,6 +124,7 @@ CONFIG_USB_CHIPIDEA_HOST=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_MXS_PHY=y
 CONFIG_MMC=y
+CONFIG_MMC_UNSAFE_RESUME=y
 CONFIG_MMC_MXS=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
diff --git a/arch/arm/configs/nhk8815_defconfig b/arch/arm/configs/nhk8815_defconfig
index 86cfd29..b01e763 100644
--- a/arch/arm/configs/nhk8815_defconfig
+++ b/arch/arm/configs/nhk8815_defconfig
@@ -1,11 +1,9 @@
-CONFIG_EXPERIMENTAL=y
 # CONFIG_LOCALVERSION_AUTO is not set
 # CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_EXPERT=y
 CONFIG_KALLSYMS_ALL=y
@@ -13,6 +11,7 @@ CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
+# CONFIG_ARCH_MULTI_V7 is not set
 CONFIG_ARCH_NOMADIK=y
 CONFIG_MACH_NOMADIK_8815NHK=y
 CONFIG_PREEMPT=y
@@ -20,7 +19,6 @@ CONFIG_AEABI=y
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
 CONFIG_FPE_NWFPE=y
-CONFIG_PM=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -32,14 +30,10 @@ CONFIG_IP_PNP=y
 CONFIG_IP_PNP_DHCP=y
 CONFIG_IP_PNP_BOOTP=y
 CONFIG_NET_IPIP=y
-CONFIG_NET_IPGRE=y
-CONFIG_NET_IPGRE_BROADCAST=y
 CONFIG_IP_MROUTE=y
 # CONFIG_INET_LRO is not set
 # CONFIG_IPV6 is not set
 CONFIG_BT=m
-CONFIG_BT_L2CAP=m
-CONFIG_BT_SCO=m
 CONFIG_BT_RFCOMM=m
 CONFIG_BT_RFCOMM_TTY=y
 CONFIG_BT_BNEP=m
@@ -53,14 +47,16 @@ CONFIG_BT_HCIVHCI=m
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_MTD=y
 CONFIG_MTD_TESTS=m
+CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
-CONFIG_MTD_NAND=y
 CONFIG_MTD_NAND_ECC_SMC=y
+CONFIG_MTD_NAND=y
 CONFIG_MTD_NAND_FSMC=y
 CONFIG_MTD_ONENAND=y
 CONFIG_MTD_ONENAND_VERIFY_WRITE=y
 CONFIG_MTD_ONENAND_GENERIC=y
+CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_CRYPTOLOOP=y
 CONFIG_BLK_DEV_RAM=y
@@ -72,47 +68,48 @@ CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_LOGGING=y
 CONFIG_SCSI_SCAN_ASYNC=y
 CONFIG_NETDEVICES=y
+CONFIG_NETCONSOLE=m
 CONFIG_TUN=y
-CONFIG_NET_ETHERNET=y
 CONFIG_SMC91X=y
 CONFIG_PPP=m
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_PPP_DEFLATE=m
 CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_DEFLATE=m
 CONFIG_PPP_MPPE=m
 CONFIG_PPPOE=m
-CONFIG_NETCONSOLE=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
 # CONFIG_INPUT_MOUSEDEV is not set
 CONFIG_INPUT_EVDEV=y
 # CONFIG_KEYBOARD_ATKBD is not set
 # CONFIG_MOUSE_PS2 is not set
 # CONFIG_SERIO is not set
+# 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 is not set
-CONFIG_I2C=y
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_NOMADIK=y
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_GPIO=y
+CONFIG_I2C_NOMADIK=y
 CONFIG_DEBUG_GPIO=y
-CONFIG_PINCTRL_NOMADIK=y
 # CONFIG_HWMON is not set
-# CONFIG_VGA_CONSOLE is not set
+CONFIG_MMC=y
+CONFIG_MMC_CLKGATE=y
+CONFIG_MMC_ARMMMCI=y
 CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_PL031=y
+CONFIG_DMADEVICES=y
+CONFIG_AMBA_PL08X=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
-CONFIG_INOTIFY=y
 CONFIG_FUSE_FS=y
 CONFIG_MSDOS_FS=y
 CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
 CONFIG_JFFS2_FS=y
 CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
 CONFIG_NFS_V3_ACL=y
 CONFIG_ROOT_NFS=y
-CONFIG_SMB_FS=m
 CONFIG_CIFS=m
 CONFIG_CIFS_WEAK_PW_HASH=y
 CONFIG_NLS_CODEPAGE_437=y
@@ -120,12 +117,11 @@ CONFIG_NLS_ASCII=y
 CONFIG_NLS_ISO8859_1=y
 CONFIG_NLS_ISO8859_15=y
 # CONFIG_ENABLE_MUST_CHECK is not set
-CONFIG_DEBUG_KERNEL=y
+CONFIG_DEBUG_FS=y
 # CONFIG_SCHED_DEBUG is not set
 # CONFIG_DEBUG_PREEMPT is not set
 # CONFIG_DEBUG_BUGVERBOSE is not set
 CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
 CONFIG_CRYPTO_MD5=y
 CONFIG_CRYPTO_SHA1=y
 CONFIG_CRYPTO_DES=y
diff --git a/arch/arm/configs/omap1_defconfig b/arch/arm/configs/omap1_defconfig
index 42eab9a..2280d9d 100644
--- a/arch/arm/configs/omap1_defconfig
+++ b/arch/arm/configs/omap1_defconfig
@@ -26,7 +26,8 @@ CONFIG_ARCH_OMAP=y
 CONFIG_ARCH_OMAP1=y
 CONFIG_OMAP_RESET_CLOCKS=y
 # CONFIG_OMAP_MUX is not set
-CONFIG_OMAP_MBOX_FWK=y
+CONFIG_MAILBOX=y
+CONFIG_OMAP1_MBOX=y
 CONFIG_OMAP_32K_TIMER=y
 CONFIG_OMAP_DM_TIMER=y
 CONFIG_ARCH_OMAP730=y
diff --git a/arch/arm/configs/sama5_defconfig b/arch/arm/configs/sama5_defconfig
new file mode 100644
index 0000000..4d0dc3c
--- /dev/null
+++ b/arch/arm/configs/sama5_defconfig
@@ -0,0 +1,181 @@
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_IRQ_DOMAIN_DEBUG=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_EMBEDDED=y
+CONFIG_SLAB=y
+CONFIG_MODULES=y
+CONFIG_MODULE_FORCE_LOAD=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_ARCH_AT91=y
+CONFIG_SOC_SAM_V7=y
+CONFIG_SOC_SAMA5D3=y
+CONFIG_MACH_SAMA5_DT=y
+CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+CONFIG_UACCESS_WITH_MEMCPY=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=ttyS0,115200 initrd=0x21100000,25165824 root=/dev/ram0 rw"
+CONFIG_AUTO_ZRELADDR=y
+CONFIG_VFP=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_PM_RUNTIME=y
+CONFIG_PM_DEBUG=y
+CONFIG_PM_ADVANCED_DEBUG=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_PNP=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_IPV6=y
+# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET6_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET6_XFRM_MODE_BEET is not set
+CONFIG_IPV6_SIT_6RD=y
+CONFIG_CAN=y
+CONFIG_CAN_AT91=y
+CONFIG_CFG80211=y
+CONFIG_MAC80211=y
+CONFIG_MAC80211_LEDS=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_STANDALONE is not set
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_M25P80=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_ATMEL=y
+CONFIG_MTD_UBI=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=4
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_ATMEL_TCLIB=y
+CONFIG_ATMEL_SSC=y
+CONFIG_EEPROM_AT24=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
+CONFIG_MII=y
+CONFIG_MACB=y
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_MICROCHIP is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_MICREL_PHY=y
+# CONFIG_WLAN is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_QT1070=y
+CONFIG_KEYBOARD_GPIO=y
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ATMEL_MXT=y
+CONFIG_TOUCHSCREEN_ATMEL_TSADCC=y
+# CONFIG_SERIO is not set
+CONFIG_LEGACY_PTY_COUNT=4
+CONFIG_SERIAL_ATMEL=y
+CONFIG_SERIAL_ATMEL_CONSOLE=y
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_AT91=y
+CONFIG_I2C_GPIO=y
+CONFIG_SPI=y
+CONFIG_SPI_ATMEL=y
+CONFIG_SPI_GPIO=y
+CONFIG_GPIO_SYSFS=y
+# CONFIG_HWMON is not set
+CONFIG_SSB=m
+CONFIG_FB=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+# CONFIG_LCD_CLASS_DEVICE is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+# CONFIG_BACKLIGHT_GENERIC is not set
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_HID_GENERIC is not set
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_ACM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_AT91=y
+CONFIG_USB_MASS_STORAGE=m
+CONFIG_MMC=y
+# CONFIG_MMC_BLOCK_BOUNCE is not set
+CONFIG_MMC_ATMELMCI=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_GPIO=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_AT91RM9200=y
+CONFIG_DMADEVICES=y
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_IIO=y
+CONFIG_AT91_ADC=y
+CONFIG_EXT2_FS=y
+CONFIG_FANOTIFY=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_UBIFS_FS=y
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_850=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_STRIP_ASM_SYMS=y
+CONFIG_DEBUG_FS=y
+# CONFIG_SCHED_DEBUG is not set
+CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_FTRACE is not set
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_LL=y
+CONFIG_EARLY_PRINTK=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_USER_API_HASH=m
+CONFIG_CRYPTO_USER_API_SKCIPHER=m
+CONFIG_CRYPTO_DEV_ATMEL_AES=y
+CONFIG_CRYPTO_DEV_ATMEL_TDES=y
+CONFIG_CRYPTO_DEV_ATMEL_SHA=y
+CONFIG_CRC_CCITT=m
+CONFIG_CRC_ITU_T=m
diff --git a/arch/arm/configs/spear3xx_defconfig b/arch/arm/configs/spear3xx_defconfig
index 865980c..7ff23a0 100644
--- a/arch/arm/configs/spear3xx_defconfig
+++ b/arch/arm/configs/spear3xx_defconfig
@@ -6,7 +6,9 @@ CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODVERSIONS=y
 CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ARCH_MULTI_V7 is not set
 CONFIG_PLAT_SPEAR=y
+CONFIG_ARCH_SPEAR3XX=y
 CONFIG_MACH_SPEAR300=y
 CONFIG_MACH_SPEAR310=y
 CONFIG_MACH_SPEAR320=y
diff --git a/arch/arm/configs/spear6xx_defconfig b/arch/arm/configs/spear6xx_defconfig
index a2a1265..7822980 100644
--- a/arch/arm/configs/spear6xx_defconfig
+++ b/arch/arm/configs/spear6xx_defconfig
@@ -6,6 +6,7 @@ CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODVERSIONS=y
 CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ARCH_MULTI_V7 is not set
 CONFIG_PLAT_SPEAR=y
 CONFIG_ARCH_SPEAR6XX=y
 CONFIG_BINFMT_MISC=y
diff --git a/arch/arm/configs/tegra_defconfig b/arch/arm/configs/tegra_defconfig
index aba4881..a5f0485 100644
--- a/arch/arm/configs/tegra_defconfig
+++ b/arch/arm/configs/tegra_defconfig
@@ -1,4 +1,3 @@
-CONFIG_EXPERIMENTAL=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_IKCONFIG=y
@@ -20,15 +19,14 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
 CONFIG_PARTITION_ADVANCED=y
-CONFIG_EFI_PARTITION=y
 # CONFIG_IOSCHED_DEADLINE is not set
 # CONFIG_IOSCHED_CFQ is not set
 CONFIG_ARCH_TEGRA=y
 CONFIG_GPIO_PCA953X=y
 CONFIG_ARCH_TEGRA_2x_SOC=y
 CONFIG_ARCH_TEGRA_3x_SOC=y
+CONFIG_ARCH_TEGRA_114_SOC=y
 CONFIG_TEGRA_PCI=y
-CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA=y
 CONFIG_TEGRA_EMC_SCALING_ENABLE=y
 CONFIG_SMP=y
 CONFIG_PREEMPT=y
@@ -37,8 +35,8 @@ CONFIG_AEABI=y
 CONFIG_HIGHMEM=y
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_AUTO_ZRELADDR=y
 CONFIG_KEXEC=y
+CONFIG_AUTO_ZRELADDR=y
 CONFIG_CPU_FREQ=y
 CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
 CONFIG_CPU_IDLE=y
@@ -108,6 +106,7 @@ CONFIG_RT2X00=y
 CONFIG_RT2800USB=m
 CONFIG_INPUT_EVDEV=y
 CONFIG_KEYBOARD_TEGRA=y
+CONFIG_KEYBOARD_GPIO=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_MPU3050=y
 # CONFIG_LEGACY_PTYS is not set
@@ -117,7 +116,6 @@ CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_TEGRA=y
 CONFIG_SERIAL_OF_PLATFORM=y
 # CONFIG_HW_RANDOM is not set
-CONFIG_I2C=y
 # CONFIG_I2C_COMPAT is not set
 CONFIG_I2C_MUX=y
 CONFIG_I2C_MUX_PINCTRL=y
@@ -126,6 +124,7 @@ CONFIG_SPI=y
 CONFIG_SPI_TEGRA20_SFLASH=y
 CONFIG_SPI_TEGRA20_SLINK=y
 CONFIG_GPIO_PCA953X_IRQ=y
+CONFIG_GPIO_PALMAS=y
 CONFIG_GPIO_TPS6586X=y
 CONFIG_GPIO_TPS65910=y
 CONFIG_POWER_SUPPLY=y
@@ -136,12 +135,17 @@ CONFIG_SENSORS_LM90=y
 CONFIG_MFD_TPS6586X=y
 CONFIG_MFD_TPS65910=y
 CONFIG_MFD_MAX8907=y
+CONFIG_MFD_TPS65090=y
+CONFIG_MFD_PALMAS=y
 CONFIG_REGULATOR=y
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
 CONFIG_REGULATOR_VIRTUAL_CONSUMER=y
 CONFIG_REGULATOR_GPIO=y
 CONFIG_REGULATOR_MAX8907=y
+CONFIG_REGULATOR_PALMAS=y
+CONFIG_REGULATOR_TPS51632=y
 CONFIG_REGULATOR_TPS62360=y
+CONFIG_REGULATOR_TPS65090=y
 CONFIG_REGULATOR_TPS6586X=y
 CONFIG_REGULATOR_TPS65910=y
 CONFIG_MEDIA_SUPPORT=y
@@ -187,10 +191,8 @@ CONFIG_LEDS_GPIO=y
 CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_GPIO=y
 CONFIG_RTC_CLASS=y
-CONFIG_RTC_INTF_SYSFS=y
-CONFIG_RTC_INTF_PROC=y
-CONFIG_RTC_INTF_DEV=y
 CONFIG_RTC_DRV_MAX8907=y
+CONFIG_RTC_DRV_PALMAS=y
 CONFIG_RTC_DRV_TPS6586X=y
 CONFIG_RTC_DRV_TPS65910=y
 CONFIG_RTC_DRV_EM3027=y
diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig
index 426270f..c037aa1 100644
--- a/arch/arm/configs/u8500_defconfig
+++ b/arch/arm/configs/u8500_defconfig
@@ -5,7 +5,6 @@ CONFIG_BLK_DEV_INITRD=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
-# CONFIG_LBDAF is not set
 # CONFIG_BLK_DEV_BSG is not set
 CONFIG_ARCH_U8500=y
 CONFIG_MACH_HREFV60=y
@@ -90,6 +89,8 @@ CONFIG_LEDS_CLASS=y
 CONFIG_LEDS_LM3530=y
 CONFIG_LEDS_LP5521=y
 CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_AB8500=y
 CONFIG_RTC_DRV_PL031=y
@@ -103,6 +104,7 @@ CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
 CONFIG_EXT2_FS_SECURITY=y
 CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS=y
 CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
 CONFIG_TMPFS_POSIX_ACL=y
diff --git a/arch/arm/include/asm/atomic.h b/arch/arm/include/asm/atomic.h
index c79f61f..da1c77d 100644
--- a/arch/arm/include/asm/atomic.h
+++ b/arch/arm/include/asm/atomic.h
@@ -243,6 +243,29 @@ typedef struct {
 
 #define ATOMIC64_INIT(i) { (i) }
 
+#ifdef CONFIG_ARM_LPAE
+static inline u64 atomic64_read(const atomic64_t *v)
+{
+	u64 result;
+
+	__asm__ __volatile__("@ atomic64_read\n"
+"	ldrd	%0, %H0, [%1]"
+	: "=&r" (result)
+	: "r" (&v->counter), "Qo" (v->counter)
+	);
+
+	return result;
+}
+
+static inline void atomic64_set(atomic64_t *v, u64 i)
+{
+	__asm__ __volatile__("@ atomic64_set\n"
+"	strd	%2, %H2, [%1]"
+	: "=Qo" (v->counter)
+	: "r" (&v->counter), "r" (i)
+	);
+}
+#else
 static inline u64 atomic64_read(const atomic64_t *v)
 {
 	u64 result;
@@ -269,6 +292,7 @@ static inline void atomic64_set(atomic64_t *v, u64 i)
 	: "r" (&v->counter), "r" (i)
 	: "cc");
 }
+#endif
 
 static inline void atomic64_add(u64 i, atomic64_t *v)
 {
diff --git a/arch/arm/include/asm/cp15.h b/arch/arm/include/asm/cp15.h
index 5ef4d80..1f3262e 100644
--- a/arch/arm/include/asm/cp15.h
+++ b/arch/arm/include/asm/cp15.h
@@ -42,6 +42,8 @@
 #define vectors_high()	(0)
 #endif
 
+#ifdef CONFIG_CPU_CP15
+
 extern unsigned long cr_no_alignment;	/* defined in entry-armv.S */
 extern unsigned long cr_alignment;	/* defined in entry-armv.S */
 
@@ -82,6 +84,18 @@ static inline void set_copro_access(unsigned int val)
 	isb();
 }
 
-#endif
+#else /* ifdef CONFIG_CPU_CP15 */
+
+/*
+ * cr_alignment and cr_no_alignment are tightly coupled to cp15 (at least in the
+ * minds of the developers). Yielding 0 for machines without a cp15 (and making
+ * it read-only) is fine for most cases and saves quite some #ifdeffery.
+ */
+#define cr_no_alignment	UL(0)
+#define cr_alignment	UL(0)
+
+#endif /* ifdef CONFIG_CPU_CP15 / else */
+
+#endif /* ifndef __ASSEMBLY__ */
 
 #endif
diff --git a/arch/arm/include/asm/cputype.h b/arch/arm/include/asm/cputype.h
index ad41ec2..7652712 100644
--- a/arch/arm/include/asm/cputype.h
+++ b/arch/arm/include/asm/cputype.h
@@ -38,6 +38,24 @@
 #define MPIDR_AFFINITY_LEVEL(mpidr, level) \
 	((mpidr >> (MPIDR_LEVEL_BITS * level)) & MPIDR_LEVEL_MASK)
 
+#define ARM_CPU_IMP_ARM			0x41
+#define ARM_CPU_IMP_INTEL		0x69
+
+#define ARM_CPU_PART_ARM1136		0xB360
+#define ARM_CPU_PART_ARM1156		0xB560
+#define ARM_CPU_PART_ARM1176		0xB760
+#define ARM_CPU_PART_ARM11MPCORE	0xB020
+#define ARM_CPU_PART_CORTEX_A8		0xC080
+#define ARM_CPU_PART_CORTEX_A9		0xC090
+#define ARM_CPU_PART_CORTEX_A5		0xC050
+#define ARM_CPU_PART_CORTEX_A15		0xC0F0
+#define ARM_CPU_PART_CORTEX_A7		0xC070
+
+#define ARM_CPU_XSCALE_ARCH_MASK	0xe000
+#define ARM_CPU_XSCALE_ARCH_V1		0x2000
+#define ARM_CPU_XSCALE_ARCH_V2		0x4000
+#define ARM_CPU_XSCALE_ARCH_V3		0x6000
+
 extern unsigned int processor_id;
 
 #ifdef CONFIG_CPU_CP15
@@ -50,6 +68,7 @@ extern unsigned int processor_id;
 		    : "cc");						\
 		__val;							\
 	})
+
 #define read_cpuid_ext(ext_reg)						\
 	({								\
 		unsigned int __val;					\
@@ -59,29 +78,24 @@ extern unsigned int processor_id;
 		    : "cc");						\
 		__val;							\
 	})
-#else
-#define read_cpuid(reg) (processor_id)
-#define read_cpuid_ext(reg) 0
-#endif
 
-#define ARM_CPU_IMP_ARM			0x41
-#define ARM_CPU_IMP_INTEL		0x69
+#else /* ifdef CONFIG_CPU_CP15 */
 
-#define ARM_CPU_PART_ARM1136		0xB360
-#define ARM_CPU_PART_ARM1156		0xB560
-#define ARM_CPU_PART_ARM1176		0xB760
-#define ARM_CPU_PART_ARM11MPCORE	0xB020
-#define ARM_CPU_PART_CORTEX_A8		0xC080
-#define ARM_CPU_PART_CORTEX_A9		0xC090
-#define ARM_CPU_PART_CORTEX_A5		0xC050
-#define ARM_CPU_PART_CORTEX_A15		0xC0F0
-#define ARM_CPU_PART_CORTEX_A7		0xC070
+/*
+ * read_cpuid and read_cpuid_ext should only ever be called on machines that
+ * have cp15 so warn on other usages.
+ */
+#define read_cpuid(reg)							\
+	({								\
+		WARN_ON_ONCE(1);					\
+		0;							\
+	})
 
-#define ARM_CPU_XSCALE_ARCH_MASK	0xe000
-#define ARM_CPU_XSCALE_ARCH_V1		0x2000
-#define ARM_CPU_XSCALE_ARCH_V2		0x4000
-#define ARM_CPU_XSCALE_ARCH_V3		0x6000
+#define read_cpuid_ext(reg) read_cpuid(reg)
+
+#endif /* ifdef CONFIG_CPU_CP15 / else */
 
+#ifdef CONFIG_CPU_CP15
 /*
  * The CPU ID never changes at run time, so we might as well tell the
  * compiler that it's constant.  Use this function to read the CPU ID
@@ -92,6 +106,15 @@ static inline unsigned int __attribute_const__ read_cpuid_id(void)
 	return read_cpuid(CPUID_ID);
 }
 
+#else /* ifdef CONFIG_CPU_CP15 */
+
+static inline unsigned int __attribute_const__ read_cpuid_id(void)
+{
+	return processor_id;
+}
+
+#endif /* ifdef CONFIG_CPU_CP15 / else */
+
 static inline unsigned int __attribute_const__ read_cpuid_implementor(void)
 {
 	return (read_cpuid_id() & 0xFF000000) >> 24;
diff --git a/arch/arm/include/asm/delay.h b/arch/arm/include/asm/delay.h
index 720799f..dff714d 100644
--- a/arch/arm/include/asm/delay.h
+++ b/arch/arm/include/asm/delay.h
@@ -24,7 +24,7 @@ extern struct arm_delay_ops {
 	void (*delay)(unsigned long);
 	void (*const_udelay)(unsigned long);
 	void (*udelay)(unsigned long);
-	bool const_clock;
+	unsigned long ticks_per_jiffy;
 } arm_delay_ops;
 
 #define __delay(n)		arm_delay_ops.delay(n)
diff --git a/arch/arm/include/asm/firmware.h b/arch/arm/include/asm/firmware.h
new file mode 100644
index 0000000..1563130
--- /dev/null
+++ b/arch/arm/include/asm/firmware.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2012 Samsung Electronics.
+ * Kyungmin Park <kyungmin.park@samsung.com>
+ * Tomasz Figa <t.figa@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_ARM_FIRMWARE_H
+#define __ASM_ARM_FIRMWARE_H
+
+#include <linux/bug.h>
+
+/*
+ * struct firmware_ops
+ *
+ * A structure to specify available firmware operations.
+ *
+ * A filled up structure can be registered with register_firmware_ops().
+ */
+struct firmware_ops {
+	/*
+	 * Enters CPU idle mode
+	 */
+	int (*do_idle)(void);
+	/*
+	 * Sets boot address of specified physical CPU
+	 */
+	int (*set_cpu_boot_addr)(int cpu, unsigned long boot_addr);
+	/*
+	 * Boots specified physical CPU
+	 */
+	int (*cpu_boot)(int cpu);
+	/*
+	 * Initializes L2 cache
+	 */
+	int (*l2x0_init)(void);
+};
+
+/* Global pointer for current firmware_ops structure, can't be NULL. */
+extern const struct firmware_ops *firmware_ops;
+
+/*
+ * call_firmware_op(op, ...)
+ *
+ * Checks if firmware operation is present and calls it,
+ * otherwise returns -ENOSYS
+ */
+#define call_firmware_op(op, ...)					\
+	((firmware_ops->op) ? firmware_ops->op(__VA_ARGS__) : (-ENOSYS))
+
+/*
+ * register_firmware_ops(ops)
+ *
+ * A function to register platform firmware_ops struct.
+ */
+static inline void register_firmware_ops(const struct firmware_ops *ops)
+{
+	BUG_ON(!ops);
+
+	firmware_ops = ops;
+}
+
+#endif
diff --git a/arch/arm/include/asm/glue-df.h b/arch/arm/include/asm/glue-df.h
index 8cacbcd..b6e9f2c 100644
--- a/arch/arm/include/asm/glue-df.h
+++ b/arch/arm/include/asm/glue-df.h
@@ -18,12 +18,12 @@
  *	================
  *
  *	We have the following to choose from:
- *	  arm6          - ARM6 style
  *	  arm7		- ARM7 style
  *	  v4_early	- ARMv4 without Thumb early abort handler
  *	  v4t_late	- ARMv4 with Thumb late abort handler
  *	  v4t_early	- ARMv4 with Thumb early abort handler
- *	  v5tej_early	- ARMv5 with Thumb and Java early abort handler
+ *	  v5t_early	- ARMv5 with Thumb early abort handler
+ *	  v5tj_early	- ARMv5 with Thumb and Java early abort handler
  *	  xscale	- ARMv5 with Thumb with Xscale extensions
  *	  v6_early	- ARMv6 generic early abort handler
  *	  v7_early	- ARMv7 generic early abort handler
@@ -39,19 +39,19 @@
 # endif
 #endif
 
-#ifdef CONFIG_CPU_ABRT_LV4T
+#ifdef CONFIG_CPU_ABRT_EV4
 # ifdef CPU_DABORT_HANDLER
 #  define MULTI_DABORT 1
 # else
-#  define CPU_DABORT_HANDLER v4t_late_abort
+#  define CPU_DABORT_HANDLER v4_early_abort
 # endif
 #endif
 
-#ifdef CONFIG_CPU_ABRT_EV4
+#ifdef CONFIG_CPU_ABRT_LV4T
 # ifdef CPU_DABORT_HANDLER
 #  define MULTI_DABORT 1
 # else
-#  define CPU_DABORT_HANDLER v4_early_abort
+#  define CPU_DABORT_HANDLER v4t_late_abort
 # endif
 #endif
 
@@ -63,19 +63,19 @@
 # endif
 #endif
 
-#ifdef CONFIG_CPU_ABRT_EV5TJ
+#ifdef CONFIG_CPU_ABRT_EV5T
 # ifdef CPU_DABORT_HANDLER
 #  define MULTI_DABORT 1
 # else
-#  define CPU_DABORT_HANDLER v5tj_early_abort
+#  define CPU_DABORT_HANDLER v5t_early_abort
 # endif
 #endif
 
-#ifdef CONFIG_CPU_ABRT_EV5T
+#ifdef CONFIG_CPU_ABRT_EV5TJ
 # ifdef CPU_DABORT_HANDLER
 #  define MULTI_DABORT 1
 # else
-#  define CPU_DABORT_HANDLER v5t_early_abort
+#  define CPU_DABORT_HANDLER v5tj_early_abort
 # endif
 #endif
 
diff --git a/arch/arm/include/asm/highmem.h b/arch/arm/include/asm/highmem.h
index 8c5e828..91b99ab 100644
--- a/arch/arm/include/asm/highmem.h
+++ b/arch/arm/include/asm/highmem.h
@@ -41,6 +41,13 @@ extern void kunmap_high(struct page *page);
 #endif
 #endif
 
+/*
+ * Needed to be able to broadcast the TLB invalidation for kmap.
+ */
+#ifdef CONFIG_ARM_ERRATA_798181
+#undef ARCH_NEEDS_KMAP_HIGH_GET
+#endif
+
 #ifdef ARCH_NEEDS_KMAP_HIGH_GET
 extern void *kmap_high_get(struct page *page);
 #else
diff --git a/arch/arm/include/asm/irq.h b/arch/arm/include/asm/irq.h
index 35c21c3..53c15de 100644
--- a/arch/arm/include/asm/irq.h
+++ b/arch/arm/include/asm/irq.h
@@ -30,6 +30,11 @@ extern void asm_do_IRQ(unsigned int, struct pt_regs *);
 void handle_IRQ(unsigned int, struct pt_regs *);
 void init_IRQ(void);
 
+#ifdef CONFIG_MULTI_IRQ_HANDLER
+extern void (*handle_arch_irq)(struct pt_regs *);
+extern void set_handle_irq(void (*handle_irq)(struct pt_regs *));
+#endif
+
 #endif
 
 #endif
diff --git a/arch/arm/include/asm/kvm_arm.h b/arch/arm/include/asm/kvm_arm.h
index 7c3d813..124623e 100644
--- a/arch/arm/include/asm/kvm_arm.h
+++ b/arch/arm/include/asm/kvm_arm.h
@@ -211,4 +211,8 @@
 
 #define HSR_HVC_IMM_MASK	((1UL << 16) - 1)
 
+#define HSR_DABT_S1PTW		(1U << 7)
+#define HSR_DABT_CM		(1U << 8)
+#define HSR_DABT_EA		(1U << 9)
+
 #endif /* __ARM_KVM_ARM_H__ */
diff --git a/arch/arm/include/asm/kvm_asm.h b/arch/arm/include/asm/kvm_asm.h
index e4956f4..18d5032 100644
--- a/arch/arm/include/asm/kvm_asm.h
+++ b/arch/arm/include/asm/kvm_asm.h
@@ -75,7 +75,7 @@ extern char __kvm_hyp_code_end[];
 extern void __kvm_tlb_flush_vmid(struct kvm *kvm);
 
 extern void __kvm_flush_vm_context(void);
-extern void __kvm_tlb_flush_vmid(struct kvm *kvm);
+extern void __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa);
 
 extern int __kvm_vcpu_run(struct kvm_vcpu *vcpu);
 #endif
diff --git a/arch/arm/include/asm/kvm_emulate.h b/arch/arm/include/asm/kvm_emulate.h
index fd61199..82b4bab 100644
--- a/arch/arm/include/asm/kvm_emulate.h
+++ b/arch/arm/include/asm/kvm_emulate.h
@@ -22,11 +22,12 @@
 #include <linux/kvm_host.h>
 #include <asm/kvm_asm.h>
 #include <asm/kvm_mmio.h>
+#include <asm/kvm_arm.h>
 
-u32 *vcpu_reg(struct kvm_vcpu *vcpu, u8 reg_num);
-u32 *vcpu_spsr(struct kvm_vcpu *vcpu);
+unsigned long *vcpu_reg(struct kvm_vcpu *vcpu, u8 reg_num);
+unsigned long *vcpu_spsr(struct kvm_vcpu *vcpu);
 
-int kvm_handle_wfi(struct kvm_vcpu *vcpu, struct kvm_run *run);
+bool kvm_condition_valid(struct kvm_vcpu *vcpu);
 void kvm_skip_instr(struct kvm_vcpu *vcpu, bool is_wide_instr);
 void kvm_inject_undefined(struct kvm_vcpu *vcpu);
 void kvm_inject_dabt(struct kvm_vcpu *vcpu, unsigned long addr);
@@ -37,14 +38,14 @@ static inline bool vcpu_mode_is_32bit(struct kvm_vcpu *vcpu)
 	return 1;
 }
 
-static inline u32 *vcpu_pc(struct kvm_vcpu *vcpu)
+static inline unsigned long *vcpu_pc(struct kvm_vcpu *vcpu)
 {
-	return (u32 *)&vcpu->arch.regs.usr_regs.ARM_pc;
+	return &vcpu->arch.regs.usr_regs.ARM_pc;
 }
 
-static inline u32 *vcpu_cpsr(struct kvm_vcpu *vcpu)
+static inline unsigned long *vcpu_cpsr(struct kvm_vcpu *vcpu)
 {
-	return (u32 *)&vcpu->arch.regs.usr_regs.ARM_cpsr;
+	return &vcpu->arch.regs.usr_regs.ARM_cpsr;
 }
 
 static inline void vcpu_set_thumb(struct kvm_vcpu *vcpu)
@@ -69,4 +70,96 @@ static inline bool kvm_vcpu_reg_is_pc(struct kvm_vcpu *vcpu, int reg)
 	return reg == 15;
 }
 
+static inline u32 kvm_vcpu_get_hsr(struct kvm_vcpu *vcpu)
+{
+	return vcpu->arch.fault.hsr;
+}
+
+static inline unsigned long kvm_vcpu_get_hfar(struct kvm_vcpu *vcpu)
+{
+	return vcpu->arch.fault.hxfar;
+}
+
+static inline phys_addr_t kvm_vcpu_get_fault_ipa(struct kvm_vcpu *vcpu)
+{
+	return ((phys_addr_t)vcpu->arch.fault.hpfar & HPFAR_MASK) << 8;
+}
+
+static inline unsigned long kvm_vcpu_get_hyp_pc(struct kvm_vcpu *vcpu)
+{
+	return vcpu->arch.fault.hyp_pc;
+}
+
+static inline bool kvm_vcpu_dabt_isvalid(struct kvm_vcpu *vcpu)
+{
+	return kvm_vcpu_get_hsr(vcpu) & HSR_ISV;
+}
+
+static inline bool kvm_vcpu_dabt_iswrite(struct kvm_vcpu *vcpu)
+{
+	return kvm_vcpu_get_hsr(vcpu) & HSR_WNR;
+}
+
+static inline bool kvm_vcpu_dabt_issext(struct kvm_vcpu *vcpu)
+{
+	return kvm_vcpu_get_hsr(vcpu) & HSR_SSE;
+}
+
+static inline int kvm_vcpu_dabt_get_rd(struct kvm_vcpu *vcpu)
+{
+	return (kvm_vcpu_get_hsr(vcpu) & HSR_SRT_MASK) >> HSR_SRT_SHIFT;
+}
+
+static inline bool kvm_vcpu_dabt_isextabt(struct kvm_vcpu *vcpu)
+{
+	return kvm_vcpu_get_hsr(vcpu) & HSR_DABT_EA;
+}
+
+static inline bool kvm_vcpu_dabt_iss1tw(struct kvm_vcpu *vcpu)
+{
+	return kvm_vcpu_get_hsr(vcpu) & HSR_DABT_S1PTW;
+}
+
+/* Get Access Size from a data abort */
+static inline int kvm_vcpu_dabt_get_as(struct kvm_vcpu *vcpu)
+{
+	switch ((kvm_vcpu_get_hsr(vcpu) >> 22) & 0x3) {
+	case 0:
+		return 1;
+	case 1:
+		return 2;
+	case 2:
+		return 4;
+	default:
+		kvm_err("Hardware is weird: SAS 0b11 is reserved\n");
+		return -EFAULT;
+	}
+}
+
+/* This one is not specific to Data Abort */
+static inline bool kvm_vcpu_trap_il_is32bit(struct kvm_vcpu *vcpu)
+{
+	return kvm_vcpu_get_hsr(vcpu) & HSR_IL;
+}
+
+static inline u8 kvm_vcpu_trap_get_class(struct kvm_vcpu *vcpu)
+{
+	return kvm_vcpu_get_hsr(vcpu) >> HSR_EC_SHIFT;
+}
+
+static inline bool kvm_vcpu_trap_is_iabt(struct kvm_vcpu *vcpu)
+{
+	return kvm_vcpu_trap_get_class(vcpu) == HSR_EC_IABT;
+}
+
+static inline u8 kvm_vcpu_trap_get_fault(struct kvm_vcpu *vcpu)
+{
+	return kvm_vcpu_get_hsr(vcpu) & HSR_FSC_TYPE;
+}
+
+static inline u32 kvm_vcpu_hvc_get_imm(struct kvm_vcpu *vcpu)
+{
+	return kvm_vcpu_get_hsr(vcpu) & HSR_HVC_IMM_MASK;
+}
+
 #endif /* __ARM_KVM_EMULATE_H__ */
diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
index d1736a5..0c4e643 100644
--- a/arch/arm/include/asm/kvm_host.h
+++ b/arch/arm/include/asm/kvm_host.h
@@ -80,6 +80,15 @@ struct kvm_mmu_memory_cache {
 	void *objects[KVM_NR_MEM_OBJS];
 };
 
+struct kvm_vcpu_fault_info {
+	u32 hsr;		/* Hyp Syndrome Register */
+	u32 hxfar;		/* Hyp Data/Inst. Fault Address Register */
+	u32 hpfar;		/* Hyp IPA Fault Address Register */
+	u32 hyp_pc;		/* PC when exception was taken from Hyp mode */
+};
+
+typedef struct vfp_hard_struct kvm_kernel_vfp_t;
+
 struct kvm_vcpu_arch {
 	struct kvm_regs regs;
 
@@ -93,13 +102,11 @@ struct kvm_vcpu_arch {
 	u32 midr;
 
 	/* Exception Information */
-	u32 hsr;		/* Hyp Syndrome Register */
-	u32 hxfar;		/* Hyp Data/Inst Fault Address Register */
-	u32 hpfar;		/* Hyp IPA Fault Address Register */
+	struct kvm_vcpu_fault_info fault;
 
 	/* Floating point registers (VFP and Advanced SIMD/NEON) */
-	struct vfp_hard_struct vfp_guest;
-	struct vfp_hard_struct *vfp_host;
+	kvm_kernel_vfp_t vfp_guest;
+	kvm_kernel_vfp_t *vfp_host;
 
 	/* VGIC state */
 	struct vgic_cpu vgic_cpu;
@@ -122,9 +129,6 @@ struct kvm_vcpu_arch {
 	/* Interrupt related fields */
 	u32 irq_lines;		/* IRQ and FIQ levels */
 
-	/* Hyp exception information */
-	u32 hyp_pc;		/* PC when exception was taken from Hyp mode */
-
 	/* Cache some mmu pages needed inside spinlock regions */
 	struct kvm_mmu_memory_cache mmu_page_cache;
 
@@ -181,4 +185,26 @@ struct kvm_one_reg;
 int kvm_arm_coproc_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *);
 int kvm_arm_coproc_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *);
 
+int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *run,
+		int exception_index);
+
+static inline void __cpu_init_hyp_mode(unsigned long long pgd_ptr,
+				       unsigned long hyp_stack_ptr,
+				       unsigned long vector_ptr)
+{
+	unsigned long pgd_low, pgd_high;
+
+	pgd_low = (pgd_ptr & ((1ULL << 32) - 1));
+	pgd_high = (pgd_ptr >> 32ULL);
+
+	/*
+	 * Call initialization code, and switch to the full blown
+	 * HYP code. The init code doesn't need to preserve these registers as
+	 * r1-r3 and r12 are already callee save according to the AAPCS.
+	 * Note that we slightly misuse the prototype by casing the pgd_low to
+	 * a void *.
+	 */
+	kvm_call_hyp((void *)pgd_low, pgd_high, hyp_stack_ptr, vector_ptr);
+}
+
 #endif /* __ARM_KVM_HOST_H__ */
diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h
index 421a20b..970f3b5 100644
--- a/arch/arm/include/asm/kvm_mmu.h
+++ b/arch/arm/include/asm/kvm_mmu.h
@@ -19,6 +19,18 @@
 #ifndef __ARM_KVM_MMU_H__
 #define __ARM_KVM_MMU_H__
 
+#include <asm/cacheflush.h>
+#include <asm/pgalloc.h>
+#include <asm/idmap.h>
+
+/*
+ * We directly use the kernel VA for the HYP, as we can directly share
+ * the mapping (HTTBR "covers" TTBR1).
+ */
+#define HYP_PAGE_OFFSET_MASK	(~0UL)
+#define HYP_PAGE_OFFSET		PAGE_OFFSET
+#define KERN_TO_HYP(kva)	(kva)
+
 int create_hyp_mappings(void *from, void *to);
 int create_hyp_io_mappings(void *from, void *to, phys_addr_t);
 void free_hyp_pmds(void);
@@ -36,6 +48,16 @@ phys_addr_t kvm_mmu_get_httbr(void);
 int kvm_mmu_init(void);
 void kvm_clear_hyp_idmap(void);
 
+static inline void kvm_set_pte(pte_t *pte, pte_t new_pte)
+{
+	pte_val(*pte) = new_pte;
+	/*
+	 * flush_pmd_entry just takes a void pointer and cleans the necessary
+	 * cache entries, so we can reuse the function for ptes.
+	 */
+	flush_pmd_entry(pte);
+}
+
 static inline bool kvm_is_write_fault(unsigned long hsr)
 {
 	unsigned long hsr_ec = hsr >> HSR_EC_SHIFT;
@@ -47,4 +69,49 @@ static inline bool kvm_is_write_fault(unsigned long hsr)
 		return true;
 }
 
+static inline void kvm_clean_pgd(pgd_t *pgd)
+{
+	clean_dcache_area(pgd, PTRS_PER_S2_PGD * sizeof(pgd_t));
+}
+
+static inline void kvm_clean_pmd_entry(pmd_t *pmd)
+{
+	clean_pmd_entry(pmd);
+}
+
+static inline void kvm_clean_pte(pte_t *pte)
+{
+	clean_pte_table(pte);
+}
+
+static inline void kvm_set_s2pte_writable(pte_t *pte)
+{
+	pte_val(*pte) |= L_PTE_S2_RDWR;
+}
+
+struct kvm;
+
+static inline void coherent_icache_guest_page(struct kvm *kvm, gfn_t gfn)
+{
+	/*
+	 * If we are going to insert an instruction page and the icache is
+	 * either VIPT or PIPT, there is a potential problem where the host
+	 * (or another VM) may have used the same page as this guest, and we
+	 * read incorrect data from the icache.  If we're using a PIPT cache,
+	 * we can invalidate just that page, but if we are using a VIPT cache
+	 * we need to invalidate the entire icache - damn shame - as written
+	 * in the ARM ARM (DDI 0406C.b - Page B3-1393).
+	 *
+	 * VIVT caches are tagged using both the ASID and the VMID and doesn't
+	 * need any kind of flushing (DDI 0406C.b - Page B3-1392).
+	 */
+	if (icache_is_pipt()) {
+		unsigned long hva = gfn_to_hva(kvm, gfn);
+		__cpuc_coherent_user_range(hva, hva + PAGE_SIZE);
+	} else if (!icache_is_vivt_asid_tagged()) {
+		/* any kind of VIPT cache */
+		__flush_icache_all();
+	}
+}
+
 #endif /* __ARM_KVM_MMU_H__ */
diff --git a/arch/arm/include/asm/kvm_vgic.h b/arch/arm/include/asm/kvm_vgic.h
index ab97207..343744e 100644
--- a/arch/arm/include/asm/kvm_vgic.h
+++ b/arch/arm/include/asm/kvm_vgic.h
@@ -21,7 +21,6 @@
 
 #include <linux/kernel.h>
 #include <linux/kvm.h>
-#include <linux/kvm_host.h>
 #include <linux/irqreturn.h>
 #include <linux/spinlock.h>
 #include <linux/types.h>
diff --git a/arch/arm/include/asm/mach/irq.h b/arch/arm/include/asm/mach/irq.h
index 18c8830..2092ee1 100644
--- a/arch/arm/include/asm/mach/irq.h
+++ b/arch/arm/include/asm/mach/irq.h
@@ -20,11 +20,6 @@ struct seq_file;
 extern void init_FIQ(int);
 extern int show_fiq_list(struct seq_file *, int);
 
-#ifdef CONFIG_MULTI_IRQ_HANDLER
-extern void (*handle_arch_irq)(struct pt_regs *);
-extern void set_handle_irq(void (*handle_irq)(struct pt_regs *));
-#endif
-
 /*
  * This is for easy migration, but should be changed in the source
  */
@@ -35,35 +30,4 @@ do {							\
 	raw_spin_unlock(&desc->lock);			\
 } while(0)
 
-#ifndef __ASSEMBLY__
-/*
- * Entry/exit functions for chained handlers where the primary IRQ chip
- * may implement either fasteoi or level-trigger flow control.
- */
-static inline void chained_irq_enter(struct irq_chip *chip,
-				     struct irq_desc *desc)
-{
-	/* FastEOI controllers require no action on entry. */
-	if (chip->irq_eoi)
-		return;
-
-	if (chip->irq_mask_ack) {
-		chip->irq_mask_ack(&desc->irq_data);
-	} else {
-		chip->irq_mask(&desc->irq_data);
-		if (chip->irq_ack)
-			chip->irq_ack(&desc->irq_data);
-	}
-}
-
-static inline void chained_irq_exit(struct irq_chip *chip,
-				    struct irq_desc *desc)
-{
-	if (chip->irq_eoi)
-		chip->irq_eoi(&desc->irq_data);
-	else
-		chip->irq_unmask(&desc->irq_data);
-}
-#endif
-
 #endif
diff --git a/arch/arm/include/asm/mach/pci.h b/arch/arm/include/asm/mach/pci.h
index 5cf2e97..7d2c3c8 100644
--- a/arch/arm/include/asm/mach/pci.h
+++ b/arch/arm/include/asm/mach/pci.h
@@ -30,6 +30,11 @@ struct hw_pci {
 	void		(*postinit)(void);
 	u8		(*swizzle)(struct pci_dev *dev, u8 *pin);
 	int		(*map_irq)(const struct pci_dev *dev, u8 slot, u8 pin);
+	resource_size_t (*align_resource)(struct pci_dev *dev,
+					  const struct resource *res,
+					  resource_size_t start,
+					  resource_size_t size,
+					  resource_size_t align);
 };
 
 /*
@@ -51,6 +56,12 @@ struct pci_sys_data {
 	u8		(*swizzle)(struct pci_dev *, u8 *);
 					/* IRQ mapping				*/
 	int		(*map_irq)(const struct pci_dev *, u8, u8);
+					/* Resource alignement requirements	*/
+	resource_size_t (*align_resource)(struct pci_dev *dev,
+					  const struct resource *res,
+					  resource_size_t start,
+					  resource_size_t size,
+					  resource_size_t align);
 	void		*private_data;	/* platform controller private data	*/
 };
 
diff --git a/arch/arm/include/asm/mmu_context.h b/arch/arm/include/asm/mmu_context.h
index 863a661..a7b85e0 100644
--- a/arch/arm/include/asm/mmu_context.h
+++ b/arch/arm/include/asm/mmu_context.h
@@ -27,6 +27,8 @@ void __check_vmalloc_seq(struct mm_struct *mm);
 void check_and_switch_context(struct mm_struct *mm, struct task_struct *tsk);
 #define init_new_context(tsk,mm)	({ atomic64_set(&mm->context.id, 0); 0; })
 
+DECLARE_PER_CPU(atomic64_t, active_asids);
+
 #else	/* !CONFIG_CPU_HAS_ASID */
 
 #ifdef CONFIG_MMU
diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h
index 80d6fc4..9bcd262 100644
--- a/arch/arm/include/asm/pgtable.h
+++ b/arch/arm/include/asm/pgtable.h
@@ -61,6 +61,15 @@ extern void __pgd_error(const char *file, int line, pgd_t);
 #define FIRST_USER_ADDRESS	PAGE_SIZE
 
 /*
+ * Use TASK_SIZE as the ceiling argument for free_pgtables() and
+ * free_pgd_range() to avoid freeing the modules pmd when LPAE is enabled (pmd
+ * page shared between user and kernel).
+ */
+#ifdef CONFIG_ARM_LPAE
+#define USER_PGTABLES_CEILING	TASK_SIZE
+#endif
+
+/*
  * The pgprot_* and protection_map entries will be fixed up in runtime
  * to include the cachable and bufferable bits based on memory policy,
  * as well as any architecture dependent bits like global/ASID and SMP
diff --git a/arch/arm/include/asm/smp_twd.h b/arch/arm/include/asm/smp_twd.h
index 0f01f46..7b2899c 100644
--- a/arch/arm/include/asm/smp_twd.h
+++ b/arch/arm/include/asm/smp_twd.h
@@ -34,12 +34,4 @@ struct twd_local_timer name __initdata = {	\
 
 int twd_local_timer_register(struct twd_local_timer *);
 
-#ifdef CONFIG_HAVE_ARM_TWD
-void twd_local_timer_of_register(void);
-#else
-static inline void twd_local_timer_of_register(void)
-{
-}
-#endif
-
 #endif
diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h
index cddda1f..1995d1a 100644
--- a/arch/arm/include/asm/thread_info.h
+++ b/arch/arm/include/asm/thread_info.h
@@ -152,6 +152,7 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *,
 #define TIF_SYSCALL_AUDIT	9
 #define TIF_SYSCALL_TRACEPOINT	10
 #define TIF_SECCOMP		11	/* seccomp syscall filtering active */
+#define TIF_NOHZ		12	/* in adaptive nohz mode */
 #define TIF_USING_IWMMXT	17
 #define TIF_MEMDIE		18	/* is terminating due to OOM killer */
 #define TIF_RESTORE_SIGMASK	20
diff --git a/arch/arm/include/asm/tlbflush.h b/arch/arm/include/asm/tlbflush.h
index 4db8c88..bc50104 100644
--- a/arch/arm/include/asm/tlbflush.h
+++ b/arch/arm/include/asm/tlbflush.h
@@ -169,7 +169,7 @@
 # define v6wbi_always_flags	(-1UL)
 #endif
 
-#define v7wbi_tlb_flags_smp	(TLB_WB | TLB_DCLEAN | TLB_BARRIER | \
+#define v7wbi_tlb_flags_smp	(TLB_WB | TLB_BARRIER | \
 				 TLB_V7_UIS_FULL | TLB_V7_UIS_PAGE | \
 				 TLB_V7_UIS_ASID | TLB_V7_UIS_BP)
 #define v7wbi_tlb_flags_up	(TLB_WB | TLB_DCLEAN | TLB_BARRIER | \
@@ -450,6 +450,21 @@ static inline void local_flush_bp_all(void)
 		isb();
 }
 
+#ifdef CONFIG_ARM_ERRATA_798181
+static inline void dummy_flush_tlb_a15_erratum(void)
+{
+	/*
+	 * Dummy TLBIMVAIS. Using the unmapped address 0 and ASID 0.
+	 */
+	asm("mcr p15, 0, %0, c8, c3, 1" : : "r" (0));
+	dsb();
+}
+#else
+static inline void dummy_flush_tlb_a15_erratum(void)
+{
+}
+#endif
+
 /*
  *	flush_pmd_entry
  *
diff --git a/arch/arm/include/asm/unistd.h b/arch/arm/include/asm/unistd.h
index e4ddfb3..141baa3 100644
--- a/arch/arm/include/asm/unistd.h
+++ b/arch/arm/include/asm/unistd.h
@@ -44,14 +44,6 @@
 #define __ARCH_WANT_SYS_CLONE
 
 /*
- * "Conditional" syscalls
- *
- * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
- * but it doesn't work on all toolchains, so we just do it by hand
- */
-#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
-
-/*
  * Unimplemented (or alternatively implemented) syscalls
  */
 #define __IGNORE_fadvise64_64
diff --git a/arch/arm/include/debug/bcm2835.S b/arch/arm/include/debug/bcm2835.S
new file mode 100644
index 0000000..aed9199
--- /dev/null
+++ b/arch/arm/include/debug/bcm2835.S
@@ -0,0 +1,22 @@
+/*
+ * Debugging macro include header
+ *
+ * Copyright (C) 2010 Broadcom
+ * Copyright (C) 1994-1999 Russell King
+ * Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#define BCM2835_DEBUG_PHYS 0x20201000
+#define BCM2835_DEBUG_VIRT 0xf0201000
+
+	.macro	addruart, rp, rv, tmp
+	ldr	\rp, =BCM2835_DEBUG_PHYS
+	ldr	\rv, =BCM2835_DEBUG_VIRT
+	.endm
+
+#include <asm/hardware/debug-pl01x.S>
diff --git a/arch/arm/include/debug/cns3xxx.S b/arch/arm/include/debug/cns3xxx.S
new file mode 100644
index 0000000..d04c150
--- /dev/null
+++ b/arch/arm/include/debug/cns3xxx.S
@@ -0,0 +1,19 @@
+/*
+ * Debugging macro include header
+ *
+ * Copyright 1994-1999 Russell King
+ * Copyright 2008 Cavium Networks
+ * Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
+ *
+ * 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.
+ */
+
+		.macro	addruart,rp,rv,tmp
+		mov	\rp, #0x00009000
+		orr	\rv, \rp, #0xf0000000	@ virtual base
+		orr	\rp, \rp, #0x10000000
+		.endm
+
+#include <asm/hardware/debug-pl01x.S>
diff --git a/arch/arm/include/debug/mxs.S b/arch/arm/include/debug/mxs.S
new file mode 100644
index 0000000..d869515
--- /dev/null
+++ b/arch/arm/include/debug/mxs.S
@@ -0,0 +1,27 @@
+/* arch/arm/mach-mxs/include/mach/debug-macro.S
+ *
+ * Debugging macro include header
+ *
+ *  Copyright (C) 1994-1999 Russell King
+ *  Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifdef CONFIG_DEBUG_IMX23_UART
+#define UART_PADDR	0x80070000
+#elif defined (CONFIG_DEBUG_IMX28_UART)
+#define UART_PADDR	0x80074000
+#endif
+
+#define UART_VADDR	0xfe100000
+
+		.macro	addruart, rp, rv, tmp
+		ldr	\rp, =UART_PADDR	@ physical
+		ldr	\rv, =UART_VADDR	@ virtual
+		.endm
+
+#include <asm/hardware/debug-pl01x.S>
diff --git a/arch/arm/include/debug/nomadik.S b/arch/arm/include/debug/nomadik.S
new file mode 100644
index 0000000..7354179
--- /dev/null
+++ b/arch/arm/include/debug/nomadik.S
@@ -0,0 +1,20 @@
+/*
+ * Debugging macro include header
+ *
+ *  Copyright (C) 1994-1999 Russell King
+ *  Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+*/
+
+		.macro	addruart, rp, rv, tmp
+		mov	\rp, #0x00100000
+		add	\rp, \rp, #0x000fb000
+		add	\rv, \rp, #0xf0000000	@ virtual base
+		add	\rp, \rp, #0x10000000	@ physical base address
+		.endm
+
+#include <asm/hardware/debug-pl01x.S>
diff --git a/arch/arm/include/debug/sirf.S b/arch/arm/include/debug/sirf.S
new file mode 100644
index 0000000..dbf250c
--- /dev/null
+++ b/arch/arm/include/debug/sirf.S
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+#if defined(CONFIG_DEBUG_SIRFPRIMA2_UART1)
+#define SIRFSOC_UART1_PA_BASE          0xb0060000
+#elif defined(CONFIG_DEBUG_SIRFMARCO_UART1)
+#define SIRFSOC_UART1_PA_BASE          0xcc060000
+#else
+#define SIRFSOC_UART1_PA_BASE          0
+#endif
+
+#define SIRFSOC_UART1_VA_BASE		0xFEC60000
+
+#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)
+
+	.macro	addruart, rp, rv, tmp
+	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/include/debug/uncompress.h b/arch/arm/include/debug/uncompress.h
new file mode 100644
index 0000000..0e2949b
--- /dev/null
+++ b/arch/arm/include/debug/uncompress.h
@@ -0,0 +1,7 @@
+#ifdef CONFIG_DEBUG_UNCOMPRESS
+extern void putc(int c);
+#else
+static inline void putc(int c) {}
+#endif
+static inline void flush(void) {}
+static inline void arch_decomp_setup(void) {}
diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h
index 023bfeb..c1ee007 100644
--- a/arch/arm/include/uapi/asm/kvm.h
+++ b/arch/arm/include/uapi/asm/kvm.h
@@ -53,12 +53,12 @@
 #define KVM_ARM_FIQ_spsr	fiq_regs[7]
 
 struct kvm_regs {
-	struct pt_regs usr_regs;/* R0_usr - R14_usr, PC, CPSR */
-	__u32 svc_regs[3];	/* SP_svc, LR_svc, SPSR_svc */
-	__u32 abt_regs[3];	/* SP_abt, LR_abt, SPSR_abt */
-	__u32 und_regs[3];	/* SP_und, LR_und, SPSR_und */
-	__u32 irq_regs[3];	/* SP_irq, LR_irq, SPSR_irq */
-	__u32 fiq_regs[8];	/* R8_fiq - R14_fiq, SPSR_fiq */
+	struct pt_regs usr_regs;	/* R0_usr - R14_usr, PC, CPSR */
+	unsigned long svc_regs[3];	/* SP_svc, LR_svc, SPSR_svc */
+	unsigned long abt_regs[3];	/* SP_abt, LR_abt, SPSR_abt */
+	unsigned long und_regs[3];	/* SP_und, LR_und, SPSR_und */
+	unsigned long irq_regs[3];	/* SP_irq, LR_irq, SPSR_irq */
+	unsigned long fiq_regs[8];	/* R8_fiq - R14_fiq, SPSR_fiq */
 };
 
 /* Supported Processor Types */
diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
index 923eec7..ee1ac39 100644
--- a/arch/arm/kernel/asm-offsets.c
+++ b/arch/arm/kernel/asm-offsets.c
@@ -165,10 +165,10 @@ int main(void)
   DEFINE(VCPU_PC,		offsetof(struct kvm_vcpu, arch.regs.usr_regs.ARM_pc));
   DEFINE(VCPU_CPSR,		offsetof(struct kvm_vcpu, arch.regs.usr_regs.ARM_cpsr));
   DEFINE(VCPU_IRQ_LINES,	offsetof(struct kvm_vcpu, arch.irq_lines));
-  DEFINE(VCPU_HSR,		offsetof(struct kvm_vcpu, arch.hsr));
-  DEFINE(VCPU_HxFAR,		offsetof(struct kvm_vcpu, arch.hxfar));
-  DEFINE(VCPU_HPFAR,		offsetof(struct kvm_vcpu, arch.hpfar));
-  DEFINE(VCPU_HYP_PC,		offsetof(struct kvm_vcpu, arch.hyp_pc));
+  DEFINE(VCPU_HSR,		offsetof(struct kvm_vcpu, arch.fault.hsr));
+  DEFINE(VCPU_HxFAR,		offsetof(struct kvm_vcpu, arch.fault.hxfar));
+  DEFINE(VCPU_HPFAR,		offsetof(struct kvm_vcpu, arch.fault.hpfar));
+  DEFINE(VCPU_HYP_PC,		offsetof(struct kvm_vcpu, arch.fault.hyp_pc));
 #ifdef CONFIG_KVM_ARM_VGIC
   DEFINE(VCPU_VGIC_CPU,		offsetof(struct kvm_vcpu, arch.vgic_cpu));
   DEFINE(VGIC_CPU_HCR,		offsetof(struct vgic_cpu, vgic_hcr));
diff --git a/arch/arm/kernel/atags_proc.c b/arch/arm/kernel/atags_proc.c
index 42a1a14..c7ff807 100644
--- a/arch/arm/kernel/atags_proc.c
+++ b/arch/arm/kernel/atags_proc.c
@@ -9,24 +9,18 @@ struct buffer {
 	char data[];
 };
 
-static int
-read_buffer(char* page, char** start, off_t off, int count,
-	int* eof, void* data)
+static ssize_t atags_read(struct file *file, char __user *buf,
+			  size_t count, loff_t *ppos)
 {
-	struct buffer *buffer = (struct buffer *)data;
-
-	if (off >= buffer->size) {
-		*eof = 1;
-		return 0;
-	}
-
-	count = min((int) (buffer->size - off), count);
-
-	memcpy(page, &buffer->data[off], count);
-
-	return count;
+	struct buffer *b = PDE_DATA(file_inode(file));
+	return simple_read_from_buffer(buf, count, ppos, b->data, b->size);
 }
 
+static const struct file_operations atags_fops = {
+	.read = atags_read,
+	.llseek = default_llseek,
+};
+
 #define BOOT_PARAMS_SIZE 1536
 static char __initdata atags_copy[BOOT_PARAMS_SIZE];
 
@@ -66,9 +60,7 @@ static int __init init_atags_procfs(void)
 	b->size = size;
 	memcpy(b->data, atags_copy, size);
 
-	tags_entry = create_proc_read_entry("atags", 0400,
-			NULL, read_buffer, b);
-
+	tags_entry = proc_create_data("atags", 0400, NULL, &atags_fops, b);
 	if (!tags_entry)
 		goto nomem;
 
diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
index a1f73b5..b2ed73c 100644
--- a/arch/arm/kernel/bios32.c
+++ b/arch/arm/kernel/bios32.c
@@ -462,6 +462,7 @@ static void pcibios_init_hw(struct hw_pci *hw, struct list_head *head)
 		sys->busnr   = busnr;
 		sys->swizzle = hw->swizzle;
 		sys->map_irq = hw->map_irq;
+		sys->align_resource = hw->align_resource;
 		INIT_LIST_HEAD(&sys->resources);
 
 		if (hw->private_data)
@@ -574,6 +575,8 @@ char * __init pcibios_setup(char *str)
 resource_size_t pcibios_align_resource(void *data, const struct resource *res,
 				resource_size_t size, resource_size_t align)
 {
+	struct pci_dev *dev = data;
+	struct pci_sys_data *sys = dev->sysdata;
 	resource_size_t start = res->start;
 
 	if (res->flags & IORESOURCE_IO && start & 0x300)
@@ -581,6 +584,9 @@ resource_size_t pcibios_align_resource(void *data, const struct resource *res,
 
 	start = (start + align - 1) & ~(align - 1);
 
+	if (sys->align_resource)
+		return sys->align_resource(dev, res, start, size, align);
+
 	return start;
 }
 
diff --git a/arch/arm/kernel/early_printk.c b/arch/arm/kernel/early_printk.c
index 85aa2b2..4307653 100644
--- a/arch/arm/kernel/early_printk.c
+++ b/arch/arm/kernel/early_printk.c
@@ -29,28 +29,17 @@ static void early_console_write(struct console *con, const char *s, unsigned n)
 	early_write(s, n);
 }
 
-static struct console early_console = {
+static struct console early_console_dev = {
 	.name =		"earlycon",
 	.write =	early_console_write,
 	.flags =	CON_PRINTBUFFER | CON_BOOT,
 	.index =	-1,
 };
 
-asmlinkage void early_printk(const char *fmt, ...)
-{
-	char buf[512];
-	int n;
-	va_list ap;
-
-	va_start(ap, fmt);
-	n = vscnprintf(buf, sizeof(buf), fmt, ap);
-	early_write(buf, n);
-	va_end(ap);
-}
-
 static int __init setup_early_printk(char *buf)
 {
-	register_console(&early_console);
+	early_console = &early_console_dev;
+	register_console(&early_console_dev);
 	return 0;
 }
 
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 0f82098..582b405 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -192,18 +192,6 @@ __dabt_svc:
 	svc_entry
 	mov	r2, sp
 	dabt_helper
-
-	@
-	@ IRQs off again before pulling preserved data off the stack
-	@
-	disable_irq_notrace
-
-#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)
@@ -223,12 +211,7 @@ __irq_svc:
 	blne	svc_preempt
 #endif
 
-#ifdef CONFIG_TRACE_IRQFLAGS
-	@ 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 r5				@ return from exception
+	svc_exit r5, irq = 1			@ return from exception
  UNWIND(.fnend		)
 ENDPROC(__irq_svc)
 
@@ -295,22 +278,8 @@ __und_svc_fault:
 	mov	r0, sp				@ struct pt_regs *regs
 	bl	__und_fault
 
-	@
-	@ IRQs off again before pulling preserved data off the stack
-	@
 __und_svc_finish:
-	disable_irq_notrace
-
-	@
-	@ restore SPSR and restart the instruction
-	@
 	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)
@@ -320,18 +289,6 @@ __pabt_svc:
 	svc_entry
 	mov	r2, sp				@ regs
 	pabt_helper
-
-	@
-	@ IRQs off again before pulling preserved data off the stack
-	@
-	disable_irq_notrace
-
-#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)
@@ -396,6 +353,7 @@ ENDPROC(__pabt_svc)
 #ifdef CONFIG_IRQSOFF_TRACER
 	bl	trace_hardirqs_off
 #endif
+	ct_user_exit save = 0
 	.endm
 
 	.macro	kuser_cmpxchg_check
@@ -562,21 +520,21 @@ ENDPROC(__und_usr)
 	@ Fall-through from Thumb-2 __und_usr
 	@
 #ifdef CONFIG_NEON
+	get_thread_info r10			@ get current thread
 	adr	r6, .LCneon_thumb_opcodes
 	b	2f
 #endif
 call_fpe:
+	get_thread_info r10			@ get current thread
 #ifdef CONFIG_NEON
 	adr	r6, .LCneon_arm_opcodes
-2:
-	ldr	r7, [r6], #4			@ mask value
-	cmp	r7, #0				@ end mask?
-	beq	1f
-	and	r8, r0, r7
+2:	ldr	r5, [r6], #4			@ mask value
 	ldr	r7, [r6], #4			@ opcode bits matching in mask
+	cmp	r5, #0				@ end mask?
+	beq	1f
+	and	r8, r0, r5
 	cmp	r8, r7				@ NEON instruction?
 	bne	2b
-	get_thread_info r10
 	mov	r7, #1
 	strb	r7, [r10, #TI_USED_CP + 10]	@ mark CP#10 as used
 	strb	r7, [r10, #TI_USED_CP + 11]	@ mark CP#11 as used
@@ -586,7 +544,6 @@ call_fpe:
 	tst	r0, #0x08000000			@ only CDP/CPRT/LDC/STC have bit 27
 	tstne	r0, #0x04000000			@ bit 26 set on both ARM and Thumb-2
 	moveq	pc, lr
-	get_thread_info r10			@ get current thread
 	and	r8, r0, #0x00000f00		@ mask out CP number
  THUMB(	lsr	r8, r8, #8		)
 	mov	r7, #1
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index 3248cde..bc5bc0a 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -35,12 +35,11 @@ ret_fast_syscall:
 	ldr	r1, [tsk, #TI_FLAGS]
 	tst	r1, #_TIF_WORK_MASK
 	bne	fast_work_pending
-#if defined(CONFIG_IRQSOFF_TRACER)
 	asm_trace_hardirqs_on
-#endif
 
 	/* perform architecture specific actions before user return */
 	arch_ret_to_user r1, lr
+	ct_user_enter
 
 	restore_user_regs fast = 1, offset = S_OFF
  UNWIND(.fnend		)
@@ -71,11 +70,11 @@ ENTRY(ret_to_user_from_irq)
 	tst	r1, #_TIF_WORK_MASK
 	bne	work_pending
 no_work_pending:
-#if defined(CONFIG_IRQSOFF_TRACER)
 	asm_trace_hardirqs_on
-#endif
+
 	/* perform architecture specific actions before user return */
 	arch_ret_to_user r1, lr
+	ct_user_enter save = 0
 
 	restore_user_regs fast = 0, offset = 0
 ENDPROC(ret_to_user_from_irq)
@@ -276,7 +275,13 @@ ENDPROC(ftrace_graph_caller_old)
  */
 
 .macro mcount_enter
+/*
+ * This pad compensates for the push {lr} at the call site.  Note that we are
+ * unable to unwind through a function which does not otherwise save its lr.
+ */
+ UNWIND(.pad	#4)
 	stmdb	sp!, {r0-r3, lr}
+ UNWIND(.save	{r0-r3, lr})
 .endm
 
 .macro mcount_get_lr reg
@@ -289,6 +294,7 @@ ENDPROC(ftrace_graph_caller_old)
 .endm
 
 ENTRY(__gnu_mcount_nc)
+UNWIND(.fnstart)
 #ifdef CONFIG_DYNAMIC_FTRACE
 	mov	ip, lr
 	ldmia	sp!, {lr}
@@ -296,17 +302,22 @@ ENTRY(__gnu_mcount_nc)
 #else
 	__mcount
 #endif
+UNWIND(.fnend)
 ENDPROC(__gnu_mcount_nc)
 
 #ifdef CONFIG_DYNAMIC_FTRACE
 ENTRY(ftrace_caller)
+UNWIND(.fnstart)
 	__ftrace_caller
+UNWIND(.fnend)
 ENDPROC(ftrace_caller)
 #endif
 
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 ENTRY(ftrace_graph_caller)
+UNWIND(.fnstart)
 	__ftrace_graph_caller
+UNWIND(.fnend)
 ENDPROC(ftrace_graph_caller)
 #endif
 
@@ -394,6 +405,7 @@ ENTRY(vector_swi)
 	mcr	p15, 0, ip, c1, c0		@ update control register
 #endif
 	enable_irq
+	ct_user_exit
 
 	get_thread_info tsk
 	adr	tbl, sys_call_table		@ load syscall table pointer
diff --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S
index 9a8531e..160f337 100644
--- a/arch/arm/kernel/entry-header.S
+++ b/arch/arm/kernel/entry-header.S
@@ -74,7 +74,24 @@
 	.endm
 
 #ifndef CONFIG_THUMB2_KERNEL
-	.macro	svc_exit, rpsr
+	.macro	svc_exit, rpsr, irq = 0
+	.if	\irq != 0
+	@ IRQs already off
+#ifdef CONFIG_TRACE_IRQFLAGS
+	@ 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
+	.else
+	@ IRQs off again before pulling preserved data off the stack
+	disable_irq_notrace
+#ifdef CONFIG_TRACE_IRQFLAGS
+	tst	\rpsr, #PSR_I_BIT
+	bleq	trace_hardirqs_on
+	tst	\rpsr, #PSR_I_BIT
+	blne	trace_hardirqs_off
+#endif
+	.endif
 	msr	spsr_cxsf, \rpsr
 #if defined(CONFIG_CPU_V6)
 	ldr	r0, [sp]
@@ -120,7 +137,24 @@
 	mov	pc, \reg
 	.endm
 #else	/* CONFIG_THUMB2_KERNEL */
-	.macro	svc_exit, rpsr
+	.macro	svc_exit, rpsr, irq = 0
+	.if	\irq != 0
+	@ IRQs already off
+#ifdef CONFIG_TRACE_IRQFLAGS
+	@ 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
+	.else
+	@ IRQs off again before pulling preserved data off the stack
+	disable_irq_notrace
+#ifdef CONFIG_TRACE_IRQFLAGS
+	tst	\rpsr, #PSR_I_BIT
+	bleq	trace_hardirqs_on
+	tst	\rpsr, #PSR_I_BIT
+	blne	trace_hardirqs_off
+#endif
+	.endif
 	ldr	lr, [sp, #S_SP]			@ top of the stack
 	ldrd	r0, r1, [sp, #S_LR]		@ calling lr and pc
 	clrex					@ clear the exclusive monitor
@@ -164,6 +198,34 @@
 #endif	/* !CONFIG_THUMB2_KERNEL */
 
 /*
+ * Context tracking subsystem.  Used to instrument transitions
+ * between user and kernel mode.
+ */
+	.macro ct_user_exit, save = 1
+#ifdef CONFIG_CONTEXT_TRACKING
+	.if	\save
+	stmdb   sp!, {r0-r3, ip, lr}
+	bl	user_exit
+	ldmia	sp!, {r0-r3, ip, lr}
+	.else
+	bl	user_exit
+	.endif
+#endif
+	.endm
+
+	.macro ct_user_enter, save = 1
+#ifdef CONFIG_CONTEXT_TRACKING
+	.if	\save
+	stmdb   sp!, {r0-r3, ip, lr}
+	bl	user_enter
+	ldmia	sp!, {r0-r3, ip, lr}
+	.else
+	bl	user_enter
+	.endif
+#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-common.S b/arch/arm/kernel/head-common.S
index 854bd22..5b391a6 100644
--- a/arch/arm/kernel/head-common.S
+++ b/arch/arm/kernel/head-common.S
@@ -98,8 +98,9 @@ __mmap_switched:
 	str	r9, [r4]			@ Save processor ID
 	str	r1, [r5]			@ Save machine type
 	str	r2, [r6]			@ Save atags pointer
-	bic	r4, r0, #CR_A			@ Clear 'A' bit
-	stmia	r7, {r0, r4}			@ Save control register values
+	cmp	r7, #0
+	bicne	r4, r0, #CR_A			@ Clear 'A' bit
+	stmneia	r7, {r0, r4}			@ Save control register values
 	b	start_kernel
 ENDPROC(__mmap_switched)
 
@@ -113,7 +114,11 @@ __mmap_switched_data:
 	.long	processor_id			@ r4
 	.long	__machine_arch_type		@ r5
 	.long	__atags_pointer			@ r6
+#ifdef CONFIG_CPU_CP15
 	.long	cr_alignment			@ r7
+#else
+	.long	0				@ r7
+#endif
 	.long	init_thread_union + THREAD_START_SP @ sp
 	.size	__mmap_switched_data, . - __mmap_switched_data
 
diff --git a/arch/arm/kernel/head-nommu.S b/arch/arm/kernel/head-nommu.S
index 2c228a0..6a2e09c 100644
--- a/arch/arm/kernel/head-nommu.S
+++ b/arch/arm/kernel/head-nommu.S
@@ -32,15 +32,21 @@
  * numbers for r1.
  *
  */
-	.arm
 
 	__HEAD
+
+#ifdef CONFIG_CPU_THUMBONLY
+	.thumb
+ENTRY(stext)
+#else
+	.arm
 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:			)
+#endif
 
 	setmode	PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9 @ ensure svc mode
 						@ and irqs disabled
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index e0eb9a1..8bac553 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -267,7 +267,7 @@ __create_page_tables:
 	addne	r6, r6, #1 << SECTION_SHIFT
 	strne	r6, [r3]
 
-#if defined(CONFIG_LPAE) && defined(CONFIG_CPU_ENDIAN_BE8)
+#if defined(CONFIG_ARM_LPAE) && defined(CONFIG_CPU_ENDIAN_BE8)
 	sub	r4, r4, #4			@ Fixup page table pointer
 						@ for 64-bit descriptors
 #endif
diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c
index 96093b7..5dc1aa6 100644
--- a/arch/arm/kernel/hw_breakpoint.c
+++ b/arch/arm/kernel/hw_breakpoint.c
@@ -966,7 +966,7 @@ static void reset_ctrl_regs(void *unused)
 	}
 
 	if (err) {
-		pr_warning("CPU %d debug is powered down!\n", cpu);
+		pr_warn_once("CPU %d debug is powered down!\n", cpu);
 		cpumask_or(&debug_err_mask, &debug_err_mask, cpumask_of(cpu));
 		return;
 	}
@@ -987,7 +987,7 @@ clear_vcr:
 	isb();
 
 	if (cpumask_intersects(&debug_err_mask, cpumask_of(cpu))) {
-		pr_warning("CPU %d failed to disable vector catch\n", cpu);
+		pr_warn_once("CPU %d failed to disable vector catch\n", cpu);
 		return;
 	}
 
@@ -1007,7 +1007,7 @@ clear_vcr:
 	}
 
 	if (cpumask_intersects(&debug_err_mask, cpumask_of(cpu))) {
-		pr_warning("CPU %d failed to clear debug register pairs\n", cpu);
+		pr_warn_once("CPU %d failed to clear debug register pairs\n", cpu);
 		return;
 	}
 
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
index 8e4ef4c..9723d17 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -26,6 +26,7 @@
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
+#include <linux/irqchip.h>
 #include <linux/random.h>
 #include <linux/smp.h>
 #include <linux/init.h>
@@ -114,7 +115,10 @@ EXPORT_SYMBOL_GPL(set_irq_flags);
 
 void __init init_IRQ(void)
 {
-	machine_desc->init_irq();
+	if (IS_ENABLED(CONFIG_OF) && !machine_desc->init_irq)
+		irqchip_init();
+	else
+		machine_desc->init_irq();
 }
 
 #ifdef CONFIG_MULTI_IRQ_HANDLER
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 047d3e4..cbd0f51 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -459,15 +459,16 @@ unsigned long arch_randomize_brk(struct mm_struct *mm)
  * atomic helpers and the signal restart code. Insert it into the
  * gate_vma so that it is visible through ptrace and /proc/<pid>/mem.
  */
-static struct vm_area_struct gate_vma;
+static struct vm_area_struct gate_vma = {
+	.vm_start	= 0xffff0000,
+	.vm_end		= 0xffff0000 + PAGE_SIZE,
+	.vm_flags	= VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYEXEC,
+	.vm_mm		= &init_mm,
+};
 
 static int __init gate_vma_init(void)
 {
-	gate_vma.vm_start	= 0xffff0000;
-	gate_vma.vm_end		= 0xffff0000 + PAGE_SIZE;
-	gate_vma.vm_page_prot	= PAGE_READONLY_EXEC;
-	gate_vma.vm_flags	= VM_READ | VM_EXEC |
-				  VM_MAYREAD | VM_MAYEXEC;
+	gate_vma.vm_page_prot = PAGE_READONLY_EXEC;
 	return 0;
 }
 arch_initcall(gate_vma_init);
diff --git a/arch/arm/kernel/return_address.c b/arch/arm/kernel/return_address.c
index 8085417..fafedd8 100644
--- a/arch/arm/kernel/return_address.c
+++ b/arch/arm/kernel/return_address.c
@@ -26,7 +26,7 @@ static int save_return_addr(struct stackframe *frame, void *d)
 	struct return_address_data *data = d;
 
 	if (!data->level) {
-		data->addr = (void *)frame->lr;
+		data->addr = (void *)frame->pc;
 
 		return 1;
 	} else {
@@ -41,7 +41,8 @@ void *return_address(unsigned int level)
 	struct stackframe frame;
 	register unsigned long current_sp asm ("sp");
 
-	data.level = level + 1;
+	data.level = level + 2;
+	data.addr = NULL;
 
 	frame.fp = (unsigned long)__builtin_frame_address(0);
 	frame.sp = current_sp;
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 3f6cbb2..aec3c82 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -291,10 +291,10 @@ static int cpu_has_aliasing_icache(unsigned int arch)
 
 static void __init cacheid_init(void)
 {
-	unsigned int cachetype = read_cpuid_cachetype();
 	unsigned int arch = cpu_architecture();
 
 	if (arch >= CPU_ARCH_ARMv6) {
+		unsigned int cachetype = read_cpuid_cachetype();
 		if ((cachetype & (7 << 29)) == 4 << 29) {
 			/* ARMv7 register format */
 			arch = CPU_ARCH_ARMv7;
@@ -353,6 +353,23 @@ void __init early_print(const char *str, ...)
 	printk("%s", buf);
 }
 
+static void __init cpuid_init_hwcaps(void)
+{
+	unsigned int divide_instrs;
+
+	if (cpu_architecture() < CPU_ARCH_ARMv7)
+		return;
+
+	divide_instrs = (read_cpuid_ext(CPUID_EXT_ISAR0) & 0x0f000000) >> 24;
+
+	switch (divide_instrs) {
+	case 2:
+		elf_hwcap |= HWCAP_IDIVA;
+	case 1:
+		elf_hwcap |= HWCAP_IDIVT;
+	}
+}
+
 static void __init feat_v6_fixup(void)
 {
 	int id = read_cpuid_id();
@@ -483,8 +500,11 @@ static void __init setup_processor(void)
 	snprintf(elf_platform, ELF_PLATFORM_SIZE, "%s%c",
 		 list->elf_name, ENDIANNESS);
 	elf_hwcap = list->elf_hwcap;
+
+	cpuid_init_hwcaps();
+
 #ifndef CONFIG_ARM_THUMB
-	elf_hwcap &= ~HWCAP_THUMB;
+	elf_hwcap &= ~(HWCAP_THUMB | HWCAP_IDIVT);
 #endif
 
 	feat_v6_fixup();
@@ -524,7 +544,7 @@ int __init arm_add_memory(phys_addr_t start, phys_addr_t size)
 	size -= start & ~PAGE_MASK;
 	bank->start = PAGE_ALIGN(start);
 
-#ifndef CONFIG_LPAE
+#ifndef CONFIG_ARM_LPAE
 	if (bank->start + size < bank->start) {
 		printk(KERN_CRIT "Truncating memory at 0x%08llx to fit in "
 			"32-bit physical address space\n", (long long)start);
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 79078ed..1f2cccc 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -673,9 +673,6 @@ static int cpufreq_callback(struct notifier_block *nb,
 	if (freq->flags & CPUFREQ_CONST_LOOPS)
 		return NOTIFY_OK;
 
-	if (arm_delay_ops.const_clock)
-		return NOTIFY_OK;
-
 	if (!per_cpu(l_p_j_ref, cpu)) {
 		per_cpu(l_p_j_ref, cpu) =
 			per_cpu(cpu_data, cpu).loops_per_jiffy;
diff --git a/arch/arm/kernel/smp_scu.c b/arch/arm/kernel/smp_scu.c
index 45eac87..5bc1a63 100644
--- a/arch/arm/kernel/smp_scu.c
+++ b/arch/arm/kernel/smp_scu.c
@@ -41,7 +41,7 @@ void scu_enable(void __iomem *scu_base)
 
 #ifdef CONFIG_ARM_ERRATA_764369
 	/* Cortex-A9 only */
-	if ((read_cpuid(CPUID_ID) & 0xff0ffff0) == 0x410fc090) {
+	if ((read_cpuid_id() & 0xff0ffff0) == 0x410fc090) {
 		scu_ctrl = __raw_readl(scu_base + 0x30);
 		if (!(scu_ctrl & 1))
 			__raw_writel(scu_ctrl | 0x1, scu_base + 0x30);
diff --git a/arch/arm/kernel/smp_tlb.c b/arch/arm/kernel/smp_tlb.c
index bd03005..e82e1d2 100644
--- a/arch/arm/kernel/smp_tlb.c
+++ b/arch/arm/kernel/smp_tlb.c
@@ -12,6 +12,7 @@
 
 #include <asm/smp_plat.h>
 #include <asm/tlbflush.h>
+#include <asm/mmu_context.h>
 
 /**********************************************************************/
 
@@ -69,12 +70,72 @@ static inline void ipi_flush_bp_all(void *ignored)
 	local_flush_bp_all();
 }
 
+#ifdef CONFIG_ARM_ERRATA_798181
+static int erratum_a15_798181(void)
+{
+	unsigned int midr = read_cpuid_id();
+
+	/* Cortex-A15 r0p0..r3p2 affected */
+	if ((midr & 0xff0ffff0) != 0x410fc0f0 || midr > 0x413fc0f2)
+		return 0;
+	return 1;
+}
+#else
+static int erratum_a15_798181(void)
+{
+	return 0;
+}
+#endif
+
+static void ipi_flush_tlb_a15_erratum(void *arg)
+{
+	dmb();
+}
+
+static void broadcast_tlb_a15_erratum(void)
+{
+	if (!erratum_a15_798181())
+		return;
+
+	dummy_flush_tlb_a15_erratum();
+	smp_call_function_many(cpu_online_mask, ipi_flush_tlb_a15_erratum,
+			       NULL, 1);
+}
+
+static void broadcast_tlb_mm_a15_erratum(struct mm_struct *mm)
+{
+	int cpu;
+	cpumask_t mask = { CPU_BITS_NONE };
+
+	if (!erratum_a15_798181())
+		return;
+
+	dummy_flush_tlb_a15_erratum();
+	for_each_online_cpu(cpu) {
+		if (cpu == smp_processor_id())
+			continue;
+		/*
+		 * We only need to send an IPI if the other CPUs are running
+		 * the same ASID as the one being invalidated. There is no
+		 * need for locking around the active_asids check since the
+		 * switch_mm() function has at least one dmb() (as required by
+		 * this workaround) in case a context switch happens on
+		 * another CPU after the condition below.
+		 */
+		if (atomic64_read(&mm->context.id) ==
+		    atomic64_read(&per_cpu(active_asids, cpu)))
+			cpumask_set_cpu(cpu, &mask);
+	}
+	smp_call_function_many(&mask, ipi_flush_tlb_a15_erratum, NULL, 1);
+}
+
 void flush_tlb_all(void)
 {
 	if (tlb_ops_need_broadcast())
 		on_each_cpu(ipi_flush_tlb_all, NULL, 1);
 	else
 		local_flush_tlb_all();
+	broadcast_tlb_a15_erratum();
 }
 
 void flush_tlb_mm(struct mm_struct *mm)
@@ -83,6 +144,7 @@ void flush_tlb_mm(struct mm_struct *mm)
 		on_each_cpu_mask(mm_cpumask(mm), ipi_flush_tlb_mm, mm, 1);
 	else
 		local_flush_tlb_mm(mm);
+	broadcast_tlb_mm_a15_erratum(mm);
 }
 
 void flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
@@ -95,6 +157,7 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
 					&ta, 1);
 	} else
 		local_flush_tlb_page(vma, uaddr);
+	broadcast_tlb_mm_a15_erratum(vma->vm_mm);
 }
 
 void flush_tlb_kernel_page(unsigned long kaddr)
@@ -105,6 +168,7 @@ void flush_tlb_kernel_page(unsigned long kaddr)
 		on_each_cpu(ipi_flush_tlb_kernel_page, &ta, 1);
 	} else
 		local_flush_tlb_kernel_page(kaddr);
+	broadcast_tlb_a15_erratum();
 }
 
 void flush_tlb_range(struct vm_area_struct *vma,
@@ -119,6 +183,7 @@ void flush_tlb_range(struct vm_area_struct *vma,
 					&ta, 1);
 	} else
 		local_flush_tlb_range(vma, start, end);
+	broadcast_tlb_mm_a15_erratum(vma->vm_mm);
 }
 
 void flush_tlb_kernel_range(unsigned long start, unsigned long end)
@@ -130,6 +195,7 @@ void flush_tlb_kernel_range(unsigned long start, unsigned long end)
 		on_each_cpu(ipi_flush_tlb_kernel_range, &ta, 1);
 	} else
 		local_flush_tlb_kernel_range(start, end);
+	broadcast_tlb_a15_erratum();
 }
 
 void flush_bp_all(void)
diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c
index 3f25650..90525d9 100644
--- a/arch/arm/kernel/smp_twd.c
+++ b/arch/arm/kernel/smp_twd.c
@@ -362,25 +362,13 @@ int __init twd_local_timer_register(struct twd_local_timer *tlt)
 }
 
 #ifdef CONFIG_OF
-const static struct of_device_id twd_of_match[] __initconst = {
-	{ .compatible = "arm,cortex-a9-twd-timer",	},
-	{ .compatible = "arm,cortex-a5-twd-timer",	},
-	{ .compatible = "arm,arm11mp-twd-timer",	},
-	{ },
-};
-
-void __init twd_local_timer_of_register(void)
+static void __init twd_local_timer_of_register(struct device_node *np)
 {
-	struct device_node *np;
 	int err;
 
 	if (!is_smp() || !setup_max_cpus)
 		return;
 
-	np = of_find_matching_node(NULL, twd_of_match);
-	if (!np)
-		return;
-
 	twd_ppi = irq_of_parse_and_map(np, 0);
 	if (!twd_ppi) {
 		err = -EINVAL;
@@ -398,4 +386,7 @@ void __init twd_local_timer_of_register(void)
 out:
 	WARN(err, "twd_local_timer_of_register failed (%d)\n", err);
 }
+CLOCKSOURCE_OF_DECLARE(arm_twd_a9, "arm,cortex-a9-twd-timer", twd_local_timer_of_register);
+CLOCKSOURCE_OF_DECLARE(arm_twd_a5, "arm,cortex-a5-twd-timer", twd_local_timer_of_register);
+CLOCKSOURCE_OF_DECLARE(arm_twd_11mp, "arm,arm11mp-twd-timer", twd_local_timer_of_register);
 #endif
diff --git a/arch/arm/kernel/swp_emulate.c b/arch/arm/kernel/swp_emulate.c
index ab1017b..0bba47a 100644
--- a/arch/arm/kernel/swp_emulate.c
+++ b/arch/arm/kernel/swp_emulate.c
@@ -268,12 +268,11 @@ static int __init swp_emulation_init(void)
 #ifdef CONFIG_PROC_FS
 	struct proc_dir_entry *res;
 
-	res = create_proc_entry("cpu/swp_emulation", S_IRUGO, NULL);
+	res = create_proc_read_entry("cpu/swp_emulation", S_IRUGO, NULL,
+					proc_read_status, NULL);
 
 	if (!res)
 		return -ENOMEM;
-
-	res->read_proc = proc_read_status;
 #endif /* CONFIG_PROC_FS */
 
 	printk(KERN_NOTICE "Registering SWP/SWPB emulation handler\n");
diff --git a/arch/arm/kernel/topology.c b/arch/arm/kernel/topology.c
index 79282eb..f10316b 100644
--- a/arch/arm/kernel/topology.c
+++ b/arch/arm/kernel/topology.c
@@ -100,7 +100,7 @@ static void __init parse_dt_topology(void)
 	int alloc_size, cpu = 0;
 
 	alloc_size = nr_cpu_ids * sizeof(struct cpu_capacity);
-	cpu_capacity = (struct cpu_capacity *)kzalloc(alloc_size, GFP_NOWAIT);
+	cpu_capacity = kzalloc(alloc_size, GFP_NOWAIT);
 
 	while ((cn = of_find_node_by_type(cn, "cpu"))) {
 		const u32 *rate, *reg;
diff --git a/arch/arm/kvm/Makefile b/arch/arm/kvm/Makefile
index fc96ce6..8dc5e76 100644
--- a/arch/arm/kvm/Makefile
+++ b/arch/arm/kvm/Makefile
@@ -17,7 +17,7 @@ AFLAGS_interrupts.o := -Wa,-march=armv7-a$(plus_virt)
 kvm-arm-y = $(addprefix ../../../virt/kvm/, kvm_main.o coalesced_mmio.o)
 
 obj-y += kvm-arm.o init.o interrupts.o
-obj-y += arm.o guest.o mmu.o emulate.o reset.o
+obj-y += arm.o handle_exit.o guest.o mmu.o emulate.o reset.o
 obj-y += coproc.o coproc_a15.o mmio.o psci.o
 obj-$(CONFIG_KVM_ARM_VGIC) += vgic.o
 obj-$(CONFIG_KVM_ARM_TIMER) += arch_timer.o
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index 5a93698..5777e0c 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -30,11 +30,9 @@
 #define CREATE_TRACE_POINTS
 #include "trace.h"
 
-#include <asm/unified.h>
 #include <asm/uaccess.h>
 #include <asm/ptrace.h>
 #include <asm/mman.h>
-#include <asm/cputype.h>
 #include <asm/tlbflush.h>
 #include <asm/cacheflush.h>
 #include <asm/virt.h>
@@ -44,14 +42,13 @@
 #include <asm/kvm_emulate.h>
 #include <asm/kvm_coproc.h>
 #include <asm/kvm_psci.h>
-#include <asm/opcodes.h>
 
 #ifdef REQUIRES_VIRT
 __asm__(".arch_extension	virt");
 #endif
 
 static DEFINE_PER_CPU(unsigned long, kvm_arm_hyp_stack_page);
-static struct vfp_hard_struct __percpu *kvm_host_vfp_state;
+static kvm_kernel_vfp_t __percpu *kvm_host_vfp_state;
 static unsigned long hyp_default_vectors;
 
 /* Per-CPU variable containing the currently running vcpu. */
@@ -220,27 +217,18 @@ long kvm_arch_dev_ioctl(struct file *filp,
 	return -EINVAL;
 }
 
-int kvm_arch_set_memory_region(struct kvm *kvm,
-			       struct kvm_userspace_memory_region *mem,
-			       struct kvm_memory_slot old,
-			       int user_alloc)
-{
-	return 0;
-}
-
 int kvm_arch_prepare_memory_region(struct kvm *kvm,
 				   struct kvm_memory_slot *memslot,
-				   struct kvm_memory_slot old,
 				   struct kvm_userspace_memory_region *mem,
-				   bool user_alloc)
+				   enum kvm_mr_change change)
 {
 	return 0;
 }
 
 void kvm_arch_commit_memory_region(struct kvm *kvm,
 				   struct kvm_userspace_memory_region *mem,
-				   struct kvm_memory_slot old,
-				   bool user_alloc)
+				   const struct kvm_memory_slot *old,
+				   enum kvm_mr_change change)
 {
 }
 
@@ -303,22 +291,6 @@ int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)
 	return 0;
 }
 
-int __attribute_const__ kvm_target_cpu(void)
-{
-	unsigned long implementor = read_cpuid_implementor();
-	unsigned long part_number = read_cpuid_part_number();
-
-	if (implementor != ARM_CPU_IMP_ARM)
-		return -EINVAL;
-
-	switch (part_number) {
-	case ARM_CPU_PART_CORTEX_A15:
-		return KVM_ARM_TARGET_CORTEX_A15;
-	default:
-		return -EINVAL;
-	}
-}
-
 int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
 {
 	int ret;
@@ -481,163 +453,6 @@ static void update_vttbr(struct kvm *kvm)
 	spin_unlock(&kvm_vmid_lock);
 }
 
-static int handle_svc_hyp(struct kvm_vcpu *vcpu, struct kvm_run *run)
-{
-	/* SVC called from Hyp mode should never get here */
-	kvm_debug("SVC called from Hyp mode shouldn't go here\n");
-	BUG();
-	return -EINVAL; /* Squash warning */
-}
-
-static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run)
-{
-	trace_kvm_hvc(*vcpu_pc(vcpu), *vcpu_reg(vcpu, 0),
-		      vcpu->arch.hsr & HSR_HVC_IMM_MASK);
-
-	if (kvm_psci_call(vcpu))
-		return 1;
-
-	kvm_inject_undefined(vcpu);
-	return 1;
-}
-
-static int handle_smc(struct kvm_vcpu *vcpu, struct kvm_run *run)
-{
-	if (kvm_psci_call(vcpu))
-		return 1;
-
-	kvm_inject_undefined(vcpu);
-	return 1;
-}
-
-static int handle_pabt_hyp(struct kvm_vcpu *vcpu, struct kvm_run *run)
-{
-	/* The hypervisor should never cause aborts */
-	kvm_err("Prefetch Abort taken from Hyp mode at %#08x (HSR: %#08x)\n",
-		vcpu->arch.hxfar, vcpu->arch.hsr);
-	return -EFAULT;
-}
-
-static int handle_dabt_hyp(struct kvm_vcpu *vcpu, struct kvm_run *run)
-{
-	/* This is either an error in the ws. code or an external abort */
-	kvm_err("Data Abort taken from Hyp mode at %#08x (HSR: %#08x)\n",
-		vcpu->arch.hxfar, vcpu->arch.hsr);
-	return -EFAULT;
-}
-
-typedef int (*exit_handle_fn)(struct kvm_vcpu *, struct kvm_run *);
-static exit_handle_fn arm_exit_handlers[] = {
-	[HSR_EC_WFI]		= kvm_handle_wfi,
-	[HSR_EC_CP15_32]	= kvm_handle_cp15_32,
-	[HSR_EC_CP15_64]	= kvm_handle_cp15_64,
-	[HSR_EC_CP14_MR]	= kvm_handle_cp14_access,
-	[HSR_EC_CP14_LS]	= kvm_handle_cp14_load_store,
-	[HSR_EC_CP14_64]	= kvm_handle_cp14_access,
-	[HSR_EC_CP_0_13]	= kvm_handle_cp_0_13_access,
-	[HSR_EC_CP10_ID]	= kvm_handle_cp10_id,
-	[HSR_EC_SVC_HYP]	= handle_svc_hyp,
-	[HSR_EC_HVC]		= handle_hvc,
-	[HSR_EC_SMC]		= handle_smc,
-	[HSR_EC_IABT]		= kvm_handle_guest_abort,
-	[HSR_EC_IABT_HYP]	= handle_pabt_hyp,
-	[HSR_EC_DABT]		= kvm_handle_guest_abort,
-	[HSR_EC_DABT_HYP]	= handle_dabt_hyp,
-};
-
-/*
- * A conditional instruction is allowed to trap, even though it
- * wouldn't be executed.  So let's re-implement the hardware, in
- * software!
- */
-static bool kvm_condition_valid(struct kvm_vcpu *vcpu)
-{
-	unsigned long cpsr, cond, insn;
-
-	/*
-	 * Exception Code 0 can only happen if we set HCR.TGE to 1, to
-	 * catch undefined instructions, and then we won't get past
-	 * the arm_exit_handlers test anyway.
-	 */
-	BUG_ON(((vcpu->arch.hsr & HSR_EC) >> HSR_EC_SHIFT) == 0);
-
-	/* Top two bits non-zero?  Unconditional. */
-	if (vcpu->arch.hsr >> 30)
-		return true;
-
-	cpsr = *vcpu_cpsr(vcpu);
-
-	/* Is condition field valid? */
-	if ((vcpu->arch.hsr & HSR_CV) >> HSR_CV_SHIFT)
-		cond = (vcpu->arch.hsr & HSR_COND) >> HSR_COND_SHIFT;
-	else {
-		/* This can happen in Thumb mode: examine IT state. */
-		unsigned long it;
-
-		it = ((cpsr >> 8) & 0xFC) | ((cpsr >> 25) & 0x3);
-
-		/* it == 0 => unconditional. */
-		if (it == 0)
-			return true;
-
-		/* The cond for this insn works out as the top 4 bits. */
-		cond = (it >> 4);
-	}
-
-	/* Shift makes it look like an ARM-mode instruction */
-	insn = cond << 28;
-	return arm_check_condition(insn, cpsr) != ARM_OPCODE_CONDTEST_FAIL;
-}
-
-/*
- * Return > 0 to return to guest, < 0 on error, 0 (and set exit_reason) on
- * proper exit to QEMU.
- */
-static int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *run,
-		       int exception_index)
-{
-	unsigned long hsr_ec;
-
-	switch (exception_index) {
-	case ARM_EXCEPTION_IRQ:
-		return 1;
-	case ARM_EXCEPTION_UNDEFINED:
-		kvm_err("Undefined exception in Hyp mode at: %#08x\n",
-			vcpu->arch.hyp_pc);
-		BUG();
-		panic("KVM: Hypervisor undefined exception!\n");
-	case ARM_EXCEPTION_DATA_ABORT:
-	case ARM_EXCEPTION_PREF_ABORT:
-	case ARM_EXCEPTION_HVC:
-		hsr_ec = (vcpu->arch.hsr & HSR_EC) >> HSR_EC_SHIFT;
-
-		if (hsr_ec >= ARRAY_SIZE(arm_exit_handlers)
-		    || !arm_exit_handlers[hsr_ec]) {
-			kvm_err("Unkown exception class: %#08lx, "
-				"hsr: %#08x\n", hsr_ec,
-				(unsigned int)vcpu->arch.hsr);
-			BUG();
-		}
-
-		/*
-		 * See ARM ARM B1.14.1: "Hyp traps on instructions
-		 * that fail their condition code check"
-		 */
-		if (!kvm_condition_valid(vcpu)) {
-			bool is_wide = vcpu->arch.hsr & HSR_IL;
-			kvm_skip_instr(vcpu, is_wide);
-			return 1;
-		}
-
-		return arm_exit_handlers[hsr_ec](vcpu, run);
-	default:
-		kvm_pr_unimpl("Unsupported exception type: %d",
-			      exception_index);
-		run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
-		return 0;
-	}
-}
-
 static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu)
 {
 	if (likely(vcpu->arch.has_run_once))
@@ -972,7 +787,6 @@ long kvm_arch_vm_ioctl(struct file *filp,
 static void cpu_init_hyp_mode(void *vector)
 {
 	unsigned long long pgd_ptr;
-	unsigned long pgd_low, pgd_high;
 	unsigned long hyp_stack_ptr;
 	unsigned long stack_page;
 	unsigned long vector_ptr;
@@ -981,20 +795,11 @@ static void cpu_init_hyp_mode(void *vector)
 	__hyp_set_vectors((unsigned long)vector);
 
 	pgd_ptr = (unsigned long long)kvm_mmu_get_httbr();
-	pgd_low = (pgd_ptr & ((1ULL << 32) - 1));
-	pgd_high = (pgd_ptr >> 32ULL);
 	stack_page = __get_cpu_var(kvm_arm_hyp_stack_page);
 	hyp_stack_ptr = stack_page + PAGE_SIZE;
 	vector_ptr = (unsigned long)__kvm_hyp_vector;
 
-	/*
-	 * Call initialization code, and switch to the full blown
-	 * HYP code. The init code doesn't need to preserve these registers as
-	 * r1-r3 and r12 are already callee save according to the AAPCS.
-	 * Note that we slightly misuse the prototype by casing the pgd_low to
-	 * a void *.
-	 */
-	kvm_call_hyp((void *)pgd_low, pgd_high, hyp_stack_ptr, vector_ptr);
+	__cpu_init_hyp_mode(pgd_ptr, hyp_stack_ptr, vector_ptr);
 }
 
 /**
@@ -1077,7 +882,7 @@ static int init_hyp_mode(void)
 	/*
 	 * Map the host VFP structures
 	 */
-	kvm_host_vfp_state = alloc_percpu(struct vfp_hard_struct);
+	kvm_host_vfp_state = alloc_percpu(kvm_kernel_vfp_t);
 	if (!kvm_host_vfp_state) {
 		err = -ENOMEM;
 		kvm_err("Cannot allocate host VFP state\n");
@@ -1085,7 +890,7 @@ static int init_hyp_mode(void)
 	}
 
 	for_each_possible_cpu(cpu) {
-		struct vfp_hard_struct *vfp;
+		kvm_kernel_vfp_t *vfp;
 
 		vfp = per_cpu_ptr(kvm_host_vfp_state, cpu);
 		err = create_hyp_mappings(vfp, vfp + 1);
diff --git a/arch/arm/kvm/coproc.c b/arch/arm/kvm/coproc.c
index 4ea9a98..94eee8b 100644
--- a/arch/arm/kvm/coproc.c
+++ b/arch/arm/kvm/coproc.c
@@ -76,7 +76,7 @@ static bool access_dcsw(struct kvm_vcpu *vcpu,
 			const struct coproc_params *p,
 			const struct coproc_reg *r)
 {
-	u32 val;
+	unsigned long val;
 	int cpu;
 
 	cpu = get_cpu();
@@ -293,12 +293,12 @@ static int emulate_cp15(struct kvm_vcpu *vcpu,
 
 		if (likely(r->access(vcpu, params, r))) {
 			/* Skip instruction, since it was emulated */
-			kvm_skip_instr(vcpu, (vcpu->arch.hsr >> 25) & 1);
+			kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu));
 			return 1;
 		}
 		/* If access function fails, it should complain. */
 	} else {
-		kvm_err("Unsupported guest CP15 access at: %08x\n",
+		kvm_err("Unsupported guest CP15 access at: %08lx\n",
 			*vcpu_pc(vcpu));
 		print_cp_instr(params);
 	}
@@ -315,14 +315,14 @@ int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run)
 {
 	struct coproc_params params;
 
-	params.CRm = (vcpu->arch.hsr >> 1) & 0xf;
-	params.Rt1 = (vcpu->arch.hsr >> 5) & 0xf;
-	params.is_write = ((vcpu->arch.hsr & 1) == 0);
+	params.CRm = (kvm_vcpu_get_hsr(vcpu) >> 1) & 0xf;
+	params.Rt1 = (kvm_vcpu_get_hsr(vcpu) >> 5) & 0xf;
+	params.is_write = ((kvm_vcpu_get_hsr(vcpu) & 1) == 0);
 	params.is_64bit = true;
 
-	params.Op1 = (vcpu->arch.hsr >> 16) & 0xf;
+	params.Op1 = (kvm_vcpu_get_hsr(vcpu) >> 16) & 0xf;
 	params.Op2 = 0;
-	params.Rt2 = (vcpu->arch.hsr >> 10) & 0xf;
+	params.Rt2 = (kvm_vcpu_get_hsr(vcpu) >> 10) & 0xf;
 	params.CRn = 0;
 
 	return emulate_cp15(vcpu, &params);
@@ -347,14 +347,14 @@ int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run)
 {
 	struct coproc_params params;
 
-	params.CRm = (vcpu->arch.hsr >> 1) & 0xf;
-	params.Rt1 = (vcpu->arch.hsr >> 5) & 0xf;
-	params.is_write = ((vcpu->arch.hsr & 1) == 0);
+	params.CRm = (kvm_vcpu_get_hsr(vcpu) >> 1) & 0xf;
+	params.Rt1 = (kvm_vcpu_get_hsr(vcpu) >> 5) & 0xf;
+	params.is_write = ((kvm_vcpu_get_hsr(vcpu) & 1) == 0);
 	params.is_64bit = false;
 
-	params.CRn = (vcpu->arch.hsr >> 10) & 0xf;
-	params.Op1 = (vcpu->arch.hsr >> 14) & 0x7;
-	params.Op2 = (vcpu->arch.hsr >> 17) & 0x7;
+	params.CRn = (kvm_vcpu_get_hsr(vcpu) >> 10) & 0xf;
+	params.Op1 = (kvm_vcpu_get_hsr(vcpu) >> 14) & 0x7;
+	params.Op2 = (kvm_vcpu_get_hsr(vcpu) >> 17) & 0x7;
 	params.Rt2 = 0;
 
 	return emulate_cp15(vcpu, &params);
diff --git a/arch/arm/kvm/coproc.h b/arch/arm/kvm/coproc.h
index 992adfa..b7301d3 100644
--- a/arch/arm/kvm/coproc.h
+++ b/arch/arm/kvm/coproc.h
@@ -84,7 +84,7 @@ static inline bool read_zero(struct kvm_vcpu *vcpu,
 static inline bool write_to_read_only(struct kvm_vcpu *vcpu,
 				      const struct coproc_params *params)
 {
-	kvm_debug("CP15 write to read-only register at: %08x\n",
+	kvm_debug("CP15 write to read-only register at: %08lx\n",
 		  *vcpu_pc(vcpu));
 	print_cp_instr(params);
 	return false;
@@ -93,7 +93,7 @@ static inline bool write_to_read_only(struct kvm_vcpu *vcpu,
 static inline bool read_from_write_only(struct kvm_vcpu *vcpu,
 					const struct coproc_params *params)
 {
-	kvm_debug("CP15 read to write-only register at: %08x\n",
+	kvm_debug("CP15 read to write-only register at: %08lx\n",
 		  *vcpu_pc(vcpu));
 	print_cp_instr(params);
 	return false;
diff --git a/arch/arm/kvm/emulate.c b/arch/arm/kvm/emulate.c
index d61450a..bdede9e 100644
--- a/arch/arm/kvm/emulate.c
+++ b/arch/arm/kvm/emulate.c
@@ -20,6 +20,7 @@
 #include <linux/kvm_host.h>
 #include <asm/kvm_arm.h>
 #include <asm/kvm_emulate.h>
+#include <asm/opcodes.h>
 #include <trace/events/kvm.h>
 
 #include "trace.h"
@@ -109,10 +110,10 @@ static const unsigned long vcpu_reg_offsets[VCPU_NR_MODES][15] = {
  * Return a pointer to the register number valid in the current mode of
  * the virtual CPU.
  */
-u32 *vcpu_reg(struct kvm_vcpu *vcpu, u8 reg_num)
+unsigned long *vcpu_reg(struct kvm_vcpu *vcpu, u8 reg_num)
 {
-	u32 *reg_array = (u32 *)&vcpu->arch.regs;
-	u32 mode = *vcpu_cpsr(vcpu) & MODE_MASK;
+	unsigned long *reg_array = (unsigned long *)&vcpu->arch.regs;
+	unsigned long mode = *vcpu_cpsr(vcpu) & MODE_MASK;
 
 	switch (mode) {
 	case USR_MODE...SVC_MODE:
@@ -141,9 +142,9 @@ u32 *vcpu_reg(struct kvm_vcpu *vcpu, u8 reg_num)
 /*
  * Return the SPSR for the current mode of the virtual CPU.
  */
-u32 *vcpu_spsr(struct kvm_vcpu *vcpu)
+unsigned long *vcpu_spsr(struct kvm_vcpu *vcpu)
 {
-	u32 mode = *vcpu_cpsr(vcpu) & MODE_MASK;
+	unsigned long mode = *vcpu_cpsr(vcpu) & MODE_MASK;
 	switch (mode) {
 	case SVC_MODE:
 		return &vcpu->arch.regs.KVM_ARM_SVC_spsr;
@@ -160,20 +161,48 @@ u32 *vcpu_spsr(struct kvm_vcpu *vcpu)
 	}
 }
 
-/**
- * kvm_handle_wfi - handle a wait-for-interrupts instruction executed by a guest
- * @vcpu:	the vcpu pointer
- * @run:	the kvm_run structure pointer
- *
- * Simply sets the wait_for_interrupts flag on the vcpu structure, which will
- * halt execution of world-switches and schedule other host processes until
- * there is an incoming IRQ or FIQ to the VM.
+/*
+ * A conditional instruction is allowed to trap, even though it
+ * wouldn't be executed.  So let's re-implement the hardware, in
+ * software!
  */
-int kvm_handle_wfi(struct kvm_vcpu *vcpu, struct kvm_run *run)
+bool kvm_condition_valid(struct kvm_vcpu *vcpu)
 {
-	trace_kvm_wfi(*vcpu_pc(vcpu));
-	kvm_vcpu_block(vcpu);
-	return 1;
+	unsigned long cpsr, cond, insn;
+
+	/*
+	 * Exception Code 0 can only happen if we set HCR.TGE to 1, to
+	 * catch undefined instructions, and then we won't get past
+	 * the arm_exit_handlers test anyway.
+	 */
+	BUG_ON(!kvm_vcpu_trap_get_class(vcpu));
+
+	/* Top two bits non-zero?  Unconditional. */
+	if (kvm_vcpu_get_hsr(vcpu) >> 30)
+		return true;
+
+	cpsr = *vcpu_cpsr(vcpu);
+
+	/* Is condition field valid? */
+	if ((kvm_vcpu_get_hsr(vcpu) & HSR_CV) >> HSR_CV_SHIFT)
+		cond = (kvm_vcpu_get_hsr(vcpu) & HSR_COND) >> HSR_COND_SHIFT;
+	else {
+		/* This can happen in Thumb mode: examine IT state. */
+		unsigned long it;
+
+		it = ((cpsr >> 8) & 0xFC) | ((cpsr >> 25) & 0x3);
+
+		/* it == 0 => unconditional. */
+		if (it == 0)
+			return true;
+
+		/* The cond for this insn works out as the top 4 bits. */
+		cond = (it >> 4);
+	}
+
+	/* Shift makes it look like an ARM-mode instruction */
+	insn = cond << 28;
+	return arm_check_condition(insn, cpsr) != ARM_OPCODE_CONDTEST_FAIL;
 }
 
 /**
@@ -257,9 +286,9 @@ static u32 exc_vector_base(struct kvm_vcpu *vcpu)
  */
 void kvm_inject_undefined(struct kvm_vcpu *vcpu)
 {
-	u32 new_lr_value;
-	u32 new_spsr_value;
-	u32 cpsr = *vcpu_cpsr(vcpu);
+	unsigned long new_lr_value;
+	unsigned long new_spsr_value;
+	unsigned long cpsr = *vcpu_cpsr(vcpu);
 	u32 sctlr = vcpu->arch.cp15[c1_SCTLR];
 	bool is_thumb = (cpsr & PSR_T_BIT);
 	u32 vect_offset = 4;
@@ -291,9 +320,9 @@ void kvm_inject_undefined(struct kvm_vcpu *vcpu)
  */
 static void inject_abt(struct kvm_vcpu *vcpu, bool is_pabt, unsigned long addr)
 {
-	u32 new_lr_value;
-	u32 new_spsr_value;
-	u32 cpsr = *vcpu_cpsr(vcpu);
+	unsigned long new_lr_value;
+	unsigned long new_spsr_value;
+	unsigned long cpsr = *vcpu_cpsr(vcpu);
 	u32 sctlr = vcpu->arch.cp15[c1_SCTLR];
 	bool is_thumb = (cpsr & PSR_T_BIT);
 	u32 vect_offset;
diff --git a/arch/arm/kvm/guest.c b/arch/arm/kvm/guest.c
index 2339d96..152d036 100644
--- a/arch/arm/kvm/guest.c
+++ b/arch/arm/kvm/guest.c
@@ -22,6 +22,7 @@
 #include <linux/module.h>
 #include <linux/vmalloc.h>
 #include <linux/fs.h>
+#include <asm/cputype.h>
 #include <asm/uaccess.h>
 #include <asm/kvm.h>
 #include <asm/kvm_asm.h>
@@ -180,6 +181,22 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
 	return -EINVAL;
 }
 
+int __attribute_const__ kvm_target_cpu(void)
+{
+	unsigned long implementor = read_cpuid_implementor();
+	unsigned long part_number = read_cpuid_part_number();
+
+	if (implementor != ARM_CPU_IMP_ARM)
+		return -EINVAL;
+
+	switch (part_number) {
+	case ARM_CPU_PART_CORTEX_A15:
+		return KVM_ARM_TARGET_CORTEX_A15;
+	default:
+		return -EINVAL;
+	}
+}
+
 int kvm_vcpu_set_target(struct kvm_vcpu *vcpu,
 			const struct kvm_vcpu_init *init)
 {
diff --git a/arch/arm/kvm/handle_exit.c b/arch/arm/kvm/handle_exit.c
new file mode 100644
index 0000000..26ad173
--- /dev/null
+++ b/arch/arm/kvm/handle_exit.c
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2012 - Virtual Open Systems and Columbia University
+ * Author: Christoffer Dall <c.dall@virtualopensystems.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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include <linux/kvm.h>
+#include <linux/kvm_host.h>
+#include <asm/kvm_emulate.h>
+#include <asm/kvm_coproc.h>
+#include <asm/kvm_mmu.h>
+#include <asm/kvm_psci.h>
+#include <trace/events/kvm.h>
+
+#include "trace.h"
+
+#include "trace.h"
+
+typedef int (*exit_handle_fn)(struct kvm_vcpu *, struct kvm_run *);
+
+static int handle_svc_hyp(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+	/* SVC called from Hyp mode should never get here */
+	kvm_debug("SVC called from Hyp mode shouldn't go here\n");
+	BUG();
+	return -EINVAL; /* Squash warning */
+}
+
+static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+	trace_kvm_hvc(*vcpu_pc(vcpu), *vcpu_reg(vcpu, 0),
+		      kvm_vcpu_hvc_get_imm(vcpu));
+
+	if (kvm_psci_call(vcpu))
+		return 1;
+
+	kvm_inject_undefined(vcpu);
+	return 1;
+}
+
+static int handle_smc(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+	if (kvm_psci_call(vcpu))
+		return 1;
+
+	kvm_inject_undefined(vcpu);
+	return 1;
+}
+
+static int handle_pabt_hyp(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+	/* The hypervisor should never cause aborts */
+	kvm_err("Prefetch Abort taken from Hyp mode at %#08lx (HSR: %#08x)\n",
+		kvm_vcpu_get_hfar(vcpu), kvm_vcpu_get_hsr(vcpu));
+	return -EFAULT;
+}
+
+static int handle_dabt_hyp(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+	/* This is either an error in the ws. code or an external abort */
+	kvm_err("Data Abort taken from Hyp mode at %#08lx (HSR: %#08x)\n",
+		kvm_vcpu_get_hfar(vcpu), kvm_vcpu_get_hsr(vcpu));
+	return -EFAULT;
+}
+
+/**
+ * kvm_handle_wfi - handle a wait-for-interrupts instruction executed by a guest
+ * @vcpu:	the vcpu pointer
+ * @run:	the kvm_run structure pointer
+ *
+ * Simply sets the wait_for_interrupts flag on the vcpu structure, which will
+ * halt execution of world-switches and schedule other host processes until
+ * there is an incoming IRQ or FIQ to the VM.
+ */
+static int kvm_handle_wfi(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+	trace_kvm_wfi(*vcpu_pc(vcpu));
+	kvm_vcpu_block(vcpu);
+	return 1;
+}
+
+static exit_handle_fn arm_exit_handlers[] = {
+	[HSR_EC_WFI]		= kvm_handle_wfi,
+	[HSR_EC_CP15_32]	= kvm_handle_cp15_32,
+	[HSR_EC_CP15_64]	= kvm_handle_cp15_64,
+	[HSR_EC_CP14_MR]	= kvm_handle_cp14_access,
+	[HSR_EC_CP14_LS]	= kvm_handle_cp14_load_store,
+	[HSR_EC_CP14_64]	= kvm_handle_cp14_access,
+	[HSR_EC_CP_0_13]	= kvm_handle_cp_0_13_access,
+	[HSR_EC_CP10_ID]	= kvm_handle_cp10_id,
+	[HSR_EC_SVC_HYP]	= handle_svc_hyp,
+	[HSR_EC_HVC]		= handle_hvc,
+	[HSR_EC_SMC]		= handle_smc,
+	[HSR_EC_IABT]		= kvm_handle_guest_abort,
+	[HSR_EC_IABT_HYP]	= handle_pabt_hyp,
+	[HSR_EC_DABT]		= kvm_handle_guest_abort,
+	[HSR_EC_DABT_HYP]	= handle_dabt_hyp,
+};
+
+static exit_handle_fn kvm_get_exit_handler(struct kvm_vcpu *vcpu)
+{
+	u8 hsr_ec = kvm_vcpu_trap_get_class(vcpu);
+
+	if (hsr_ec >= ARRAY_SIZE(arm_exit_handlers) ||
+	    !arm_exit_handlers[hsr_ec]) {
+		kvm_err("Unkown exception class: hsr: %#08x\n",
+			(unsigned int)kvm_vcpu_get_hsr(vcpu));
+		BUG();
+	}
+
+	return arm_exit_handlers[hsr_ec];
+}
+
+/*
+ * Return > 0 to return to guest, < 0 on error, 0 (and set exit_reason) on
+ * proper exit to userspace.
+ */
+int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *run,
+		       int exception_index)
+{
+	exit_handle_fn exit_handler;
+
+	switch (exception_index) {
+	case ARM_EXCEPTION_IRQ:
+		return 1;
+	case ARM_EXCEPTION_UNDEFINED:
+		kvm_err("Undefined exception in Hyp mode at: %#08lx\n",
+			kvm_vcpu_get_hyp_pc(vcpu));
+		BUG();
+		panic("KVM: Hypervisor undefined exception!\n");
+	case ARM_EXCEPTION_DATA_ABORT:
+	case ARM_EXCEPTION_PREF_ABORT:
+	case ARM_EXCEPTION_HVC:
+		/*
+		 * See ARM ARM B1.14.1: "Hyp traps on instructions
+		 * that fail their condition code check"
+		 */
+		if (!kvm_condition_valid(vcpu)) {
+			kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu));
+			return 1;
+		}
+
+		exit_handler = kvm_get_exit_handler(vcpu);
+
+		return exit_handler(vcpu, run);
+	default:
+		kvm_pr_unimpl("Unsupported exception type: %d",
+			      exception_index);
+		run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+		return 0;
+	}
+}
diff --git a/arch/arm/kvm/interrupts.S b/arch/arm/kvm/interrupts.S
index 8ca87ab..f7793df 100644
--- a/arch/arm/kvm/interrupts.S
+++ b/arch/arm/kvm/interrupts.S
@@ -35,15 +35,18 @@ __kvm_hyp_code_start:
 /********************************************************************
  * Flush per-VMID TLBs
  *
- * void __kvm_tlb_flush_vmid(struct kvm *kvm);
+ * void __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa);
  *
  * We rely on the hardware to broadcast the TLB invalidation to all CPUs
  * inside the inner-shareable domain (which is the case for all v7
  * implementations).  If we come across a non-IS SMP implementation, we'll
  * have to use an IPI based mechanism. Until then, we stick to the simple
  * hardware assisted version.
+ *
+ * As v7 does not support flushing per IPA, just nuke the whole TLB
+ * instead, ignoring the ipa value.
  */
-ENTRY(__kvm_tlb_flush_vmid)
+ENTRY(__kvm_tlb_flush_vmid_ipa)
 	push	{r2, r3}
 
 	add	r0, r0, #KVM_VTTBR
@@ -60,7 +63,7 @@ ENTRY(__kvm_tlb_flush_vmid)
 
 	pop	{r2, r3}
 	bx	lr
-ENDPROC(__kvm_tlb_flush_vmid)
+ENDPROC(__kvm_tlb_flush_vmid_ipa)
 
 /********************************************************************
  * Flush TLBs and instruction caches of all CPUs inside the inner-shareable
@@ -235,9 +238,9 @@ ENTRY(kvm_call_hyp)
  * instruction is issued since all traps are disabled when running the host
  * kernel as per the Hyp-mode initialization at boot time.
  *
- * HVC instructions cause a trap to the vector page + offset 0x18 (see hyp_hvc
+ * HVC instructions cause a trap to the vector page + offset 0x14 (see hyp_hvc
  * below) when the HVC instruction is called from SVC mode (i.e. a guest or the
- * host kernel) and they cause a trap to the vector page + offset 0xc when HVC
+ * host kernel) and they cause a trap to the vector page + offset 0x8 when HVC
  * instructions are called from within Hyp-mode.
  *
  * Hyp-ABI: Calling HYP-mode functions from host (in SVC mode):
diff --git a/arch/arm/kvm/mmio.c b/arch/arm/kvm/mmio.c
index 98a870f..72a12f2 100644
--- a/arch/arm/kvm/mmio.c
+++ b/arch/arm/kvm/mmio.c
@@ -33,16 +33,16 @@
  */
 int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run)
 {
-	__u32 *dest;
+	unsigned long *dest;
 	unsigned int len;
 	int mask;
 
 	if (!run->mmio.is_write) {
 		dest = vcpu_reg(vcpu, vcpu->arch.mmio_decode.rt);
-		memset(dest, 0, sizeof(int));
+		*dest = 0;
 
 		len = run->mmio.len;
-		if (len > 4)
+		if (len > sizeof(unsigned long))
 			return -EINVAL;
 
 		memcpy(dest, run->mmio.data, len);
@@ -50,7 +50,8 @@ int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run)
 		trace_kvm_mmio(KVM_TRACE_MMIO_READ, len, run->mmio.phys_addr,
 				*((u64 *)run->mmio.data));
 
-		if (vcpu->arch.mmio_decode.sign_extend && len < 4) {
+		if (vcpu->arch.mmio_decode.sign_extend &&
+		    len < sizeof(unsigned long)) {
 			mask = 1U << ((len * 8) - 1);
 			*dest = (*dest ^ mask) - mask;
 		}
@@ -65,40 +66,29 @@ static int decode_hsr(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
 	unsigned long rt, len;
 	bool is_write, sign_extend;
 
-	if ((vcpu->arch.hsr >> 8) & 1) {
+	if (kvm_vcpu_dabt_isextabt(vcpu)) {
 		/* cache operation on I/O addr, tell guest unsupported */
-		kvm_inject_dabt(vcpu, vcpu->arch.hxfar);
+		kvm_inject_dabt(vcpu, kvm_vcpu_get_hfar(vcpu));
 		return 1;
 	}
 
-	if ((vcpu->arch.hsr >> 7) & 1) {
+	if (kvm_vcpu_dabt_iss1tw(vcpu)) {
 		/* page table accesses IO mem: tell guest to fix its TTBR */
-		kvm_inject_dabt(vcpu, vcpu->arch.hxfar);
+		kvm_inject_dabt(vcpu, kvm_vcpu_get_hfar(vcpu));
 		return 1;
 	}
 
-	switch ((vcpu->arch.hsr >> 22) & 0x3) {
-	case 0:
-		len = 1;
-		break;
-	case 1:
-		len = 2;
-		break;
-	case 2:
-		len = 4;
-		break;
-	default:
-		kvm_err("Hardware is weird: SAS 0b11 is reserved\n");
-		return -EFAULT;
-	}
+	len = kvm_vcpu_dabt_get_as(vcpu);
+	if (unlikely(len < 0))
+		return len;
 
-	is_write = vcpu->arch.hsr & HSR_WNR;
-	sign_extend = vcpu->arch.hsr & HSR_SSE;
-	rt = (vcpu->arch.hsr & HSR_SRT_MASK) >> HSR_SRT_SHIFT;
+	is_write = kvm_vcpu_dabt_iswrite(vcpu);
+	sign_extend = kvm_vcpu_dabt_issext(vcpu);
+	rt = kvm_vcpu_dabt_get_rd(vcpu);
 
 	if (kvm_vcpu_reg_is_pc(vcpu, rt)) {
 		/* IO memory trying to read/write pc */
-		kvm_inject_pabt(vcpu, vcpu->arch.hxfar);
+		kvm_inject_pabt(vcpu, kvm_vcpu_get_hfar(vcpu));
 		return 1;
 	}
 
@@ -112,7 +102,7 @@ static int decode_hsr(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
 	 * The MMIO instruction is emulated and should not be re-executed
 	 * in the guest.
 	 */
-	kvm_skip_instr(vcpu, (vcpu->arch.hsr >> 25) & 1);
+	kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu));
 	return 0;
 }
 
@@ -130,7 +120,7 @@ int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
 	 * space do its magic.
 	 */
 
-	if (vcpu->arch.hsr & HSR_ISV) {
+	if (kvm_vcpu_dabt_isvalid(vcpu)) {
 		ret = decode_hsr(vcpu, fault_ipa, &mmio);
 		if (ret)
 			return ret;
diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
index 99e07c7..2f12e40 100644
--- a/arch/arm/kvm/mmu.c
+++ b/arch/arm/kvm/mmu.c
@@ -20,7 +20,6 @@
 #include <linux/kvm_host.h>
 #include <linux/io.h>
 #include <trace/events/kvm.h>
-#include <asm/idmap.h>
 #include <asm/pgalloc.h>
 #include <asm/cacheflush.h>
 #include <asm/kvm_arm.h>
@@ -28,8 +27,6 @@
 #include <asm/kvm_mmio.h>
 #include <asm/kvm_asm.h>
 #include <asm/kvm_emulate.h>
-#include <asm/mach/map.h>
-#include <trace/events/kvm.h>
 
 #include "trace.h"
 
@@ -37,19 +34,9 @@ extern char  __hyp_idmap_text_start[], __hyp_idmap_text_end[];
 
 static DEFINE_MUTEX(kvm_hyp_pgd_mutex);
 
-static void kvm_tlb_flush_vmid(struct kvm *kvm)
+static void kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa)
 {
-	kvm_call_hyp(__kvm_tlb_flush_vmid, kvm);
-}
-
-static void kvm_set_pte(pte_t *pte, pte_t new_pte)
-{
-	pte_val(*pte) = new_pte;
-	/*
-	 * flush_pmd_entry just takes a void pointer and cleans the necessary
-	 * cache entries, so we can reuse the function for ptes.
-	 */
-	flush_pmd_entry(pte);
+	kvm_call_hyp(__kvm_tlb_flush_vmid_ipa, kvm, ipa);
 }
 
 static int mmu_topup_memory_cache(struct kvm_mmu_memory_cache *cache,
@@ -98,33 +85,42 @@ static void free_ptes(pmd_t *pmd, unsigned long addr)
 	}
 }
 
+static void free_hyp_pgd_entry(unsigned long addr)
+{
+	pgd_t *pgd;
+	pud_t *pud;
+	pmd_t *pmd;
+	unsigned long hyp_addr = KERN_TO_HYP(addr);
+
+	pgd = hyp_pgd + pgd_index(hyp_addr);
+	pud = pud_offset(pgd, hyp_addr);
+
+	if (pud_none(*pud))
+		return;
+	BUG_ON(pud_bad(*pud));
+
+	pmd = pmd_offset(pud, hyp_addr);
+	free_ptes(pmd, addr);
+	pmd_free(NULL, pmd);
+	pud_clear(pud);
+}
+
 /**
  * free_hyp_pmds - free a Hyp-mode level-2 tables and child level-3 tables
  *
  * Assumes this is a page table used strictly in Hyp-mode and therefore contains
- * only mappings in the kernel memory area, which is above PAGE_OFFSET.
+ * either mappings in the kernel memory area (above PAGE_OFFSET), or
+ * device mappings in the vmalloc range (from VMALLOC_START to VMALLOC_END).
  */
 void free_hyp_pmds(void)
 {
-	pgd_t *pgd;
-	pud_t *pud;
-	pmd_t *pmd;
 	unsigned long addr;
 
 	mutex_lock(&kvm_hyp_pgd_mutex);
-	for (addr = PAGE_OFFSET; addr != 0; addr += PGDIR_SIZE) {
-		pgd = hyp_pgd + pgd_index(addr);
-		pud = pud_offset(pgd, addr);
-
-		if (pud_none(*pud))
-			continue;
-		BUG_ON(pud_bad(*pud));
-
-		pmd = pmd_offset(pud, addr);
-		free_ptes(pmd, addr);
-		pmd_free(NULL, pmd);
-		pud_clear(pud);
-	}
+	for (addr = PAGE_OFFSET; virt_addr_valid(addr); addr += PGDIR_SIZE)
+		free_hyp_pgd_entry(addr);
+	for (addr = VMALLOC_START; is_vmalloc_addr((void*)addr); addr += PGDIR_SIZE)
+		free_hyp_pgd_entry(addr);
 	mutex_unlock(&kvm_hyp_pgd_mutex);
 }
 
@@ -136,7 +132,9 @@ static void create_hyp_pte_mappings(pmd_t *pmd, unsigned long start,
 	struct page *page;
 
 	for (addr = start & PAGE_MASK; addr < end; addr += PAGE_SIZE) {
-		pte = pte_offset_kernel(pmd, addr);
+		unsigned long hyp_addr = KERN_TO_HYP(addr);
+
+		pte = pte_offset_kernel(pmd, hyp_addr);
 		BUG_ON(!virt_addr_valid(addr));
 		page = virt_to_page(addr);
 		kvm_set_pte(pte, mk_pte(page, PAGE_HYP));
@@ -151,7 +149,9 @@ static void create_hyp_io_pte_mappings(pmd_t *pmd, unsigned long start,
 	unsigned long addr;
 
 	for (addr = start & PAGE_MASK; addr < end; addr += PAGE_SIZE) {
-		pte = pte_offset_kernel(pmd, addr);
+		unsigned long hyp_addr = KERN_TO_HYP(addr);
+
+		pte = pte_offset_kernel(pmd, hyp_addr);
 		BUG_ON(pfn_valid(*pfn_base));
 		kvm_set_pte(pte, pfn_pte(*pfn_base, PAGE_HYP_DEVICE));
 		(*pfn_base)++;
@@ -166,12 +166,13 @@ static int create_hyp_pmd_mappings(pud_t *pud, unsigned long start,
 	unsigned long addr, next;
 
 	for (addr = start; addr < end; addr = next) {
-		pmd = pmd_offset(pud, addr);
+		unsigned long hyp_addr = KERN_TO_HYP(addr);
+		pmd = pmd_offset(pud, hyp_addr);
 
 		BUG_ON(pmd_sect(*pmd));
 
 		if (pmd_none(*pmd)) {
-			pte = pte_alloc_one_kernel(NULL, addr);
+			pte = pte_alloc_one_kernel(NULL, hyp_addr);
 			if (!pte) {
 				kvm_err("Cannot allocate Hyp pte\n");
 				return -ENOMEM;
@@ -206,17 +207,23 @@ static int __create_hyp_mappings(void *from, void *to, unsigned long *pfn_base)
 	unsigned long addr, next;
 	int err = 0;
 
-	BUG_ON(start > end);
-	if (start < PAGE_OFFSET)
+	if (start >= end)
+		return -EINVAL;
+	/* Check for a valid kernel memory mapping */
+	if (!pfn_base && (!virt_addr_valid(from) || !virt_addr_valid(to - 1)))
+		return -EINVAL;
+	/* Check for a valid kernel IO mapping */
+	if (pfn_base && (!is_vmalloc_addr(from) || !is_vmalloc_addr(to - 1)))
 		return -EINVAL;
 
 	mutex_lock(&kvm_hyp_pgd_mutex);
 	for (addr = start; addr < end; addr = next) {
-		pgd = hyp_pgd + pgd_index(addr);
-		pud = pud_offset(pgd, addr);
+		unsigned long hyp_addr = KERN_TO_HYP(addr);
+		pgd = hyp_pgd + pgd_index(hyp_addr);
+		pud = pud_offset(pgd, hyp_addr);
 
 		if (pud_none_or_clear_bad(pud)) {
-			pmd = pmd_alloc_one(NULL, addr);
+			pmd = pmd_alloc_one(NULL, hyp_addr);
 			if (!pmd) {
 				kvm_err("Cannot allocate Hyp pmd\n");
 				err = -ENOMEM;
@@ -236,12 +243,13 @@ out:
 }
 
 /**
- * create_hyp_mappings - map a kernel virtual address range in Hyp mode
+ * create_hyp_mappings - duplicate a kernel virtual address range in Hyp mode
  * @from:	The virtual kernel start address of the range
  * @to:		The virtual kernel end address of the range (exclusive)
  *
- * The same virtual address as the kernel virtual address is also used in
- * Hyp-mode mapping to the same underlying physical pages.
+ * The same virtual address as the kernel virtual address is also used
+ * in Hyp-mode mapping (modulo HYP_PAGE_OFFSET) to the same underlying
+ * physical pages.
  *
  * Note: Wrapping around zero in the "to" address is not supported.
  */
@@ -251,10 +259,13 @@ int create_hyp_mappings(void *from, void *to)
 }
 
 /**
- * create_hyp_io_mappings - map a physical IO range in Hyp mode
- * @from:	The virtual HYP start address of the range
- * @to:		The virtual HYP end address of the range (exclusive)
+ * create_hyp_io_mappings - duplicate a kernel IO mapping into Hyp mode
+ * @from:	The kernel start VA of the range
+ * @to:		The kernel end VA of the range (exclusive)
  * @addr:	The physical start address which gets mapped
+ *
+ * The resulting HYP VA is the same as the kernel VA, modulo
+ * HYP_PAGE_OFFSET.
  */
 int create_hyp_io_mappings(void *from, void *to, phys_addr_t addr)
 {
@@ -290,7 +301,7 @@ int kvm_alloc_stage2_pgd(struct kvm *kvm)
 	VM_BUG_ON((unsigned long)pgd & (S2_PGD_SIZE - 1));
 
 	memset(pgd, 0, PTRS_PER_S2_PGD * sizeof(pgd_t));
-	clean_dcache_area(pgd, PTRS_PER_S2_PGD * sizeof(pgd_t));
+	kvm_clean_pgd(pgd);
 	kvm->arch.pgd = pgd;
 
 	return 0;
@@ -422,22 +433,22 @@ static int stage2_set_pte(struct kvm *kvm, struct kvm_mmu_memory_cache *cache,
 			return 0; /* ignore calls from kvm_set_spte_hva */
 		pmd = mmu_memory_cache_alloc(cache);
 		pud_populate(NULL, pud, pmd);
-		pmd += pmd_index(addr);
 		get_page(virt_to_page(pud));
-	} else
-		pmd = pmd_offset(pud, addr);
+	}
+
+	pmd = pmd_offset(pud, addr);
 
 	/* Create 2nd stage page table mapping - Level 2 */
 	if (pmd_none(*pmd)) {
 		if (!cache)
 			return 0; /* ignore calls from kvm_set_spte_hva */
 		pte = mmu_memory_cache_alloc(cache);
-		clean_pte_table(pte);
+		kvm_clean_pte(pte);
 		pmd_populate_kernel(NULL, pmd, pte);
-		pte += pte_index(addr);
 		get_page(virt_to_page(pmd));
-	} else
-		pte = pte_offset_kernel(pmd, addr);
+	}
+
+	pte = pte_offset_kernel(pmd, addr);
 
 	if (iomap && pte_present(*pte))
 		return -EFAULT;
@@ -446,7 +457,7 @@ static int stage2_set_pte(struct kvm *kvm, struct kvm_mmu_memory_cache *cache,
 	old_pte = *pte;
 	kvm_set_pte(pte, *new_pte);
 	if (pte_present(old_pte))
-		kvm_tlb_flush_vmid(kvm);
+		kvm_tlb_flush_vmid_ipa(kvm, addr);
 	else
 		get_page(virt_to_page(pte));
 
@@ -473,7 +484,8 @@ int kvm_phys_addr_ioremap(struct kvm *kvm, phys_addr_t guest_ipa,
 	pfn = __phys_to_pfn(pa);
 
 	for (addr = guest_ipa; addr < end; addr += PAGE_SIZE) {
-		pte_t pte = pfn_pte(pfn, PAGE_S2_DEVICE | L_PTE_S2_RDWR);
+		pte_t pte = pfn_pte(pfn, PAGE_S2_DEVICE);
+		kvm_set_s2pte_writable(&pte);
 
 		ret = mmu_topup_memory_cache(&cache, 2, 2);
 		if (ret)
@@ -492,29 +504,6 @@ out:
 	return ret;
 }
 
-static void coherent_icache_guest_page(struct kvm *kvm, gfn_t gfn)
-{
-	/*
-	 * If we are going to insert an instruction page and the icache is
-	 * either VIPT or PIPT, there is a potential problem where the host
-	 * (or another VM) may have used the same page as this guest, and we
-	 * read incorrect data from the icache.  If we're using a PIPT cache,
-	 * we can invalidate just that page, but if we are using a VIPT cache
-	 * we need to invalidate the entire icache - damn shame - as written
-	 * in the ARM ARM (DDI 0406C.b - Page B3-1393).
-	 *
-	 * VIVT caches are tagged using both the ASID and the VMID and doesn't
-	 * need any kind of flushing (DDI 0406C.b - Page B3-1392).
-	 */
-	if (icache_is_pipt()) {
-		unsigned long hva = gfn_to_hva(kvm, gfn);
-		__cpuc_coherent_user_range(hva, hva + PAGE_SIZE);
-	} else if (!icache_is_vivt_asid_tagged()) {
-		/* any kind of VIPT cache */
-		__flush_icache_all();
-	}
-}
-
 static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
 			  gfn_t gfn, struct kvm_memory_slot *memslot,
 			  unsigned long fault_status)
@@ -526,7 +515,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
 	unsigned long mmu_seq;
 	struct kvm_mmu_memory_cache *memcache = &vcpu->arch.mmu_page_cache;
 
-	write_fault = kvm_is_write_fault(vcpu->arch.hsr);
+	write_fault = kvm_is_write_fault(kvm_vcpu_get_hsr(vcpu));
 	if (fault_status == FSC_PERM && !write_fault) {
 		kvm_err("Unexpected L2 read permission error\n");
 		return -EFAULT;
@@ -560,7 +549,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
 	if (mmu_notifier_retry(vcpu->kvm, mmu_seq))
 		goto out_unlock;
 	if (writable) {
-		pte_val(new_pte) |= L_PTE_S2_RDWR;
+		kvm_set_s2pte_writable(&new_pte);
 		kvm_set_pfn_dirty(pfn);
 	}
 	stage2_set_pte(vcpu->kvm, memcache, fault_ipa, &new_pte, false);
@@ -585,7 +574,6 @@ out_unlock:
  */
 int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run)
 {
-	unsigned long hsr_ec;
 	unsigned long fault_status;
 	phys_addr_t fault_ipa;
 	struct kvm_memory_slot *memslot;
@@ -593,18 +581,17 @@ int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run)
 	gfn_t gfn;
 	int ret, idx;
 
-	hsr_ec = vcpu->arch.hsr >> HSR_EC_SHIFT;
-	is_iabt = (hsr_ec == HSR_EC_IABT);
-	fault_ipa = ((phys_addr_t)vcpu->arch.hpfar & HPFAR_MASK) << 8;
+	is_iabt = kvm_vcpu_trap_is_iabt(vcpu);
+	fault_ipa = kvm_vcpu_get_fault_ipa(vcpu);
 
-	trace_kvm_guest_fault(*vcpu_pc(vcpu), vcpu->arch.hsr,
-			      vcpu->arch.hxfar, fault_ipa);
+	trace_kvm_guest_fault(*vcpu_pc(vcpu), kvm_vcpu_get_hsr(vcpu),
+			      kvm_vcpu_get_hfar(vcpu), fault_ipa);
 
 	/* Check the stage-2 fault is trans. fault or write fault */
-	fault_status = (vcpu->arch.hsr & HSR_FSC_TYPE);
+	fault_status = kvm_vcpu_trap_get_fault(vcpu);
 	if (fault_status != FSC_FAULT && fault_status != FSC_PERM) {
-		kvm_err("Unsupported fault status: EC=%#lx DFCS=%#lx\n",
-			hsr_ec, fault_status);
+		kvm_err("Unsupported fault status: EC=%#x DFCS=%#lx\n",
+			kvm_vcpu_trap_get_class(vcpu), fault_status);
 		return -EFAULT;
 	}
 
@@ -614,7 +601,7 @@ int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run)
 	if (!kvm_is_visible_gfn(vcpu->kvm, gfn)) {
 		if (is_iabt) {
 			/* Prefetch Abort on I/O address */
-			kvm_inject_pabt(vcpu, vcpu->arch.hxfar);
+			kvm_inject_pabt(vcpu, kvm_vcpu_get_hfar(vcpu));
 			ret = 1;
 			goto out_unlock;
 		}
@@ -626,8 +613,13 @@ int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run)
 			goto out_unlock;
 		}
 
-		/* Adjust page offset */
-		fault_ipa |= vcpu->arch.hxfar & ~PAGE_MASK;
+		/*
+		 * The IPA is reported as [MAX:12], so we need to
+		 * complement it with the bottom 12 bits from the
+		 * faulting VA. This is always 12 bits, irrespective
+		 * of the page size.
+		 */
+		fault_ipa |= kvm_vcpu_get_hfar(vcpu) & ((1 << 12) - 1);
 		ret = io_mem_abort(vcpu, run, fault_ipa);
 		goto out_unlock;
 	}
@@ -682,7 +674,7 @@ static void handle_hva_to_gpa(struct kvm *kvm,
 static void kvm_unmap_hva_handler(struct kvm *kvm, gpa_t gpa, void *data)
 {
 	unmap_stage2_range(kvm, gpa, PAGE_SIZE);
-	kvm_tlb_flush_vmid(kvm);
+	kvm_tlb_flush_vmid_ipa(kvm, gpa);
 }
 
 int kvm_unmap_hva(struct kvm *kvm, unsigned long hva)
@@ -776,7 +768,7 @@ void kvm_clear_hyp_idmap(void)
 		pmd = pmd_offset(pud, addr);
 
 		pud_clear(pud);
-		clean_pmd_entry(pmd);
+		kvm_clean_pmd_entry(pmd);
 		pmd_free(NULL, (pmd_t *)((unsigned long)pmd & PAGE_MASK));
 	} while (pgd++, addr = next, addr < end);
 }
diff --git a/arch/arm/kvm/vgic.c b/arch/arm/kvm/vgic.c
index c9a1731..17c5ac7 100644
--- a/arch/arm/kvm/vgic.c
+++ b/arch/arm/kvm/vgic.c
@@ -883,8 +883,7 @@ static bool vgic_queue_irq(struct kvm_vcpu *vcpu, u8 sgi_source_id, int irq)
 			  lr, irq, vgic_cpu->vgic_lr[lr]);
 		BUG_ON(!test_bit(lr, vgic_cpu->lr_used));
 		vgic_cpu->vgic_lr[lr] |= GICH_LR_PENDING_BIT;
-
-		goto out;
+		return true;
 	}
 
 	/* Try to use another LR for this interrupt */
@@ -898,7 +897,6 @@ static bool vgic_queue_irq(struct kvm_vcpu *vcpu, u8 sgi_source_id, int irq)
 	vgic_cpu->vgic_irq_lr_map[irq] = lr;
 	set_bit(lr, vgic_cpu->lr_used);
 
-out:
 	if (!vgic_irq_is_edge(vcpu, irq))
 		vgic_cpu->vgic_lr[lr] |= GICH_LR_EOI;
 
@@ -1018,21 +1016,6 @@ static bool vgic_process_maintenance(struct kvm_vcpu *vcpu)
 
 	kvm_debug("MISR = %08x\n", vgic_cpu->vgic_misr);
 
-	/*
-	 * We do not need to take the distributor lock here, since the only
-	 * action we perform is clearing the irq_active_bit for an EOIed
-	 * level interrupt.  There is a potential race with
-	 * the queuing of an interrupt in __kvm_vgic_flush_hwstate(), where we
-	 * check if the interrupt is already active. Two possibilities:
-	 *
-	 * - The queuing is occurring on the same vcpu: cannot happen,
-	 *   as we're already in the context of this vcpu, and
-	 *   executing the handler
-	 * - The interrupt has been migrated to another vcpu, and we
-	 *   ignore this interrupt for this run. Big deal. It is still
-	 *   pending though, and will get considered when this vcpu
-	 *   exits.
-	 */
 	if (vgic_cpu->vgic_misr & GICH_MISR_EOI) {
 		/*
 		 * Some level interrupts have been EOIed. Clear their
@@ -1054,6 +1037,13 @@ static bool vgic_process_maintenance(struct kvm_vcpu *vcpu)
 			} else {
 				vgic_cpu_irq_clear(vcpu, irq);
 			}
+
+			/*
+			 * Despite being EOIed, the LR may not have
+			 * been marked as empty.
+			 */
+			set_bit(lr, (unsigned long *)vgic_cpu->vgic_elrsr);
+			vgic_cpu->vgic_lr[lr] &= ~GICH_LR_ACTIVE_BIT;
 		}
 	}
 
@@ -1064,9 +1054,8 @@ static bool vgic_process_maintenance(struct kvm_vcpu *vcpu)
 }
 
 /*
- * Sync back the VGIC state after a guest run. We do not really touch
- * the distributor here (the irq_pending_on_cpu bit is safe to set),
- * so there is no need for taking its lock.
+ * Sync back the VGIC state after a guest run. The distributor lock is
+ * needed so we don't get preempted in the middle of the state processing.
  */
 static void __kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu)
 {
@@ -1112,10 +1101,14 @@ void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu)
 
 void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu)
 {
+	struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
+
 	if (!irqchip_in_kernel(vcpu->kvm))
 		return;
 
+	spin_lock(&dist->lock);
 	__kvm_vgic_sync_hwstate(vcpu);
+	spin_unlock(&dist->lock);
 }
 
 int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu)
@@ -1484,7 +1477,7 @@ int kvm_vgic_set_addr(struct kvm *kvm, unsigned long type, u64 addr)
 	if (addr & ~KVM_PHYS_MASK)
 		return -E2BIG;
 
-	if (addr & ~PAGE_MASK)
+	if (addr & (SZ_4K - 1))
 		return -EINVAL;
 
 	mutex_lock(&kvm->lock);
diff --git a/arch/arm/lib/delay.c b/arch/arm/lib/delay.c
index 6b93f6a..64dbfa5 100644
--- a/arch/arm/lib/delay.c
+++ b/arch/arm/lib/delay.c
@@ -58,7 +58,7 @@ static void __timer_delay(unsigned long cycles)
 static void __timer_const_udelay(unsigned long xloops)
 {
 	unsigned long long loops = xloops;
-	loops *= loops_per_jiffy;
+	loops *= arm_delay_ops.ticks_per_jiffy;
 	__timer_delay(loops >> UDELAY_SHIFT);
 }
 
@@ -73,11 +73,13 @@ void __init register_current_timer_delay(const struct delay_timer *timer)
 		pr_info("Switching to timer-based delay loop\n");
 		delay_timer			= timer;
 		lpj_fine			= timer->freq / HZ;
-		loops_per_jiffy			= lpj_fine;
+
+		/* cpufreq may scale loops_per_jiffy, so keep a private copy */
+		arm_delay_ops.ticks_per_jiffy	= lpj_fine;
 		arm_delay_ops.delay		= __timer_delay;
 		arm_delay_ops.const_udelay	= __timer_const_udelay;
 		arm_delay_ops.udelay		= __timer_udelay;
-		arm_delay_ops.const_clock	= true;
+
 		delay_calibrated		= true;
 	} else {
 		pr_info("Ignoring duplicate/late registration of read_current_timer delay\n");
diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
index 6071f4c..0280238 100644
--- a/arch/arm/mach-at91/Kconfig
+++ b/arch/arm/mach-at91/Kconfig
@@ -1,14 +1,15 @@
 if ARCH_AT91
 
-config HAVE_AT91_DATAFLASH_CARD
-	bool
-
 config HAVE_AT91_DBGU0
 	bool
 
 config HAVE_AT91_DBGU1
 	bool
 
+config AT91_PMC_UNIT
+	bool
+	default !ARCH_AT91X40
+
 config AT91_SAM9_ALT_RESET
 	bool
 	default !ARCH_AT91X40
@@ -17,17 +18,59 @@ config AT91_SAM9G45_RESET
 	bool
 	default !ARCH_AT91X40
 
+config AT91_SAM9_TIME
+	bool
+
 config SOC_AT91SAM9
 	bool
+	select AT91_SAM9_TIME
 	select CPU_ARM926T
 	select GENERIC_CLOCKEVENTS
 	select MULTI_IRQ_HANDLER
 	select SPARSE_IRQ
 
+config SOC_SAMA5
+	bool
+	select AT91_SAM9_TIME
+	select CPU_V7
+	select GENERIC_CLOCKEVENTS
+	select MULTI_IRQ_HANDLER
+	select SPARSE_IRQ
+
 menu "Atmel AT91 System-on-Chip"
 
+choice
+
+	prompt "Core type"
+
+config SOC_SAM_V4_V5
+	bool "ARM7/ARM9"
+	help
+	  Select this if you are using one of Atmel's AT91SAM9, AT91RM9200
+	  or AT91X40 SoC.
+
+config SOC_SAM_V7
+	bool "Cortex A5"
+	help
+	  Select this if you are using one of Atmel's SAMA5D3 SoC.
+
+endchoice
+
 comment "Atmel AT91 Processor"
 
+if SOC_SAM_V7
+config SOC_SAMA5D3
+	bool "SAMA5D3 family"
+	depends on SOC_SAM_V7
+	select SOC_SAMA5
+	select HAVE_FB_ATMEL
+	select HAVE_AT91_DBGU1
+	help
+	  Select this if you are using one of Atmel's SAMA5D3 family SoC.
+	  This support covers SAMA5D31, SAMA5D33, SAMA5D34, SAMA5D35.
+endif
+
+if SOC_SAM_V4_V5
 config SOC_AT91RM9200
 	bool "AT91RM9200"
 	select CPU_ARM920T
@@ -93,394 +136,10 @@ config SOC_AT91SAM9N12
 	help
 	  Select this if you are using Atmel's AT91SAM9N12 SoC.
 
-choice
-	prompt "Atmel AT91 Processor Devices for non DT boards"
-
-config ARCH_AT91_NONE
-	bool "None"
-
-config ARCH_AT91RM9200
-	bool "AT91RM9200"
-	select SOC_AT91RM9200
-
-config ARCH_AT91SAM9260
-	bool "AT91SAM9260 or AT91SAM9XE"
-	select SOC_AT91SAM9260
-
-config ARCH_AT91SAM9261
-	bool "AT91SAM9261"
-	select SOC_AT91SAM9261
-
-config ARCH_AT91SAM9G10
-	bool "AT91SAM9G10"
-	select SOC_AT91SAM9261
-
-config ARCH_AT91SAM9263
-	bool "AT91SAM9263"
-	select SOC_AT91SAM9263
-
-config ARCH_AT91SAM9RL
-	bool "AT91SAM9RL"
-	select SOC_AT91SAM9RL
-
-config ARCH_AT91SAM9G20
-	bool "AT91SAM9G20"
-	select SOC_AT91SAM9260
-
-config ARCH_AT91SAM9G45
-	bool "AT91SAM9G45"
-	select SOC_AT91SAM9G45
-
-config ARCH_AT91X40
-	bool "AT91x40"
-	depends on !MMU
-	select ARCH_USES_GETTIMEOFFSET
-	select MULTI_IRQ_HANDLER
-	select SPARSE_IRQ
-
-endchoice
-
-config AT91_PMC_UNIT
-	bool
-	default !ARCH_AT91X40
-
-# ----------------------------------------------------------
-
-if ARCH_AT91RM9200
-
-comment "AT91RM9200 Board Type"
-
-config MACH_ONEARM
-	bool "Ajeco 1ARM Single Board Computer"
-	help
-	  Select this if you are using Ajeco's 1ARM Single Board Computer.
-	  <http://www.ajeco.fi/>
-
-config ARCH_AT91RM9200DK
-	bool "Atmel AT91RM9200-DK Development board"
-	select HAVE_AT91_DATAFLASH_CARD
-	help
-	  Select this if you are using Atmel's AT91RM9200-DK Development board.
-	  (Discontinued)
-
-config MACH_AT91RM9200EK
-	bool "Atmel AT91RM9200-EK Evaluation Kit"
-	select HAVE_AT91_DATAFLASH_CARD
-	help
-	  Select this if you are using Atmel's AT91RM9200-EK Evaluation Kit.
-	  <http://www.atmel.com/dyn/products/tools_card.asp?tool_id=3507>
-
-config MACH_CSB337
-	bool "Cogent CSB337"
-	help
-	  Select this if you are using Cogent's CSB337 board.
-	  <http://www.cogcomp.com/csb_csb337.htm>
-
-config MACH_CSB637
-	bool "Cogent CSB637"
-	help
-	  Select this if you are using Cogent's CSB637 board.
-	  <http://www.cogcomp.com/csb_csb637.htm>
-
-config MACH_CARMEVA
-	bool "Conitec ARM&EVA"
-	help
-	  Select this if you are using Conitec's AT91RM9200-MCU-Module.
-	  <http://www.conitec.net/english/linuxboard.php>
-
-config MACH_ATEB9200
-	bool "Embest ATEB9200"
-	help
-	  Select this if you are using Embest's ATEB9200 board.
-	  <http://www.embedinfo.com/english/product/ATEB9200.asp>
-
-config MACH_KB9200
-	bool "KwikByte KB920x"
-	help
-	  Select this if you are using KwikByte's KB920x board.
-	  <http://www.kwikbyte.com/KB9202.html>
-
-config MACH_PICOTUX2XX
-	bool "picotux 200"
-	help
-	  Select this if you are using a picotux 200.
-	  <http://www.picotux.com/>
-
-config MACH_KAFA
-	bool "Sperry-Sun KAFA board"
-	help
-	  Select this if you are using Sperry-Sun's KAFA board.
-
-config MACH_ECBAT91
-	bool "emQbit ECB_AT91 SBC"
-	select HAVE_AT91_DATAFLASH_CARD
-	help
-	  Select this if you are using emQbit's ECB_AT91 board.
-	  <http://wiki.emqbit.com/free-ecb-at91>
-
-config MACH_YL9200
-	bool "ucDragon YL-9200"
-	help
-	  Select this if you are using the ucDragon YL-9200 board.
-
-config MACH_CPUAT91
-	bool "Eukrea CPUAT91"
-	help
-	  Select this if you are using the Eukrea Electromatique's
-	  CPUAT91 board <http://www.eukrea.com/>.
-
-config MACH_ECO920
-	bool "eco920"
-	help
-	  Select this if you are using the eco920 board
-
-config MACH_RSI_EWS
-	bool "RSI Embedded Webserver"
-	depends on ARCH_AT91RM9200
-	help
-	  Select this if you are using RSIs EWS board.
-endif
-
-# ----------------------------------------------------------
-
-if ARCH_AT91SAM9260
-
-comment "AT91SAM9260 Variants"
-
-comment "AT91SAM9260 / AT91SAM9XE Board Type"
-
-config MACH_AT91SAM9260EK
-	bool "Atmel AT91SAM9260-EK / AT91SAM9XE Evaluation Kit"
-	select HAVE_AT91_DATAFLASH_CARD
-	help
-	  Select this if you are using Atmel's AT91SAM9260-EK or AT91SAM9XE Evaluation Kit
-	  <http://www.atmel.com/dyn/products/tools_card.asp?tool_id=3933>
-
-config MACH_CAM60
-	bool "KwikByte KB9260 (CAM60) board"
-	help
-	  Select this if you are using KwikByte's KB9260 (CAM60) board based on the Atmel AT91SAM9260.
-	  <http://www.kwikbyte.com/KB9260.html>
-
-config MACH_SAM9_L9260
-	bool "Olimex SAM9-L9260 board"
-	select HAVE_AT91_DATAFLASH_CARD
-	help
-	  Select this if you are using Olimex's SAM9-L9260 board based on the Atmel AT91SAM9260.
-	  <http://www.olimex.com/dev/sam9-L9260.html>
-
-config MACH_AFEB9260
-	bool "Custom afeb9260 board v1"
-	help
-	  Select this if you are using custom afeb9260 board based on
-	  open hardware design. Select this for revision 1 of the board.
-	  <svn://194.85.238.22/home/users/george/svn/arm9eb>
-	  <http://groups.google.com/group/arm9fpga-evolution-board>
-
-config MACH_USB_A9260
-	bool "CALAO USB-A9260"
-	help
-	  Select this if you are using a Calao Systems USB-A9260.
-	  <http://www.calao-systems.com>
-
-config MACH_QIL_A9260
-	bool "CALAO QIL-A9260 board"
-	help
-	  Select this if you are using a Calao Systems QIL-A9260 Board.
-	  <http://www.calao-systems.com>
-
-config MACH_CPU9260
-	bool "Eukrea CPU9260 board"
-	help
-	  Select this if you are using a Eukrea Electromatique's
-	  CPU9260 Board <http://www.eukrea.com/>
-
-config MACH_FLEXIBITY
-	bool "Flexibity Connect board"
-	help
-	  Select this if you are using Flexibity Connect board
-	  <http://www.flexibity.com>
-
-endif
-
-# ----------------------------------------------------------
-
-if ARCH_AT91SAM9261
-
-comment "AT91SAM9261 Board Type"
-
-config MACH_AT91SAM9261EK
-	bool "Atmel AT91SAM9261-EK Evaluation Kit"
-	select HAVE_AT91_DATAFLASH_CARD
-	help
-	  Select this if you are using Atmel's AT91SAM9261-EK Evaluation Kit.
-	  <http://www.atmel.com/dyn/products/tools_card.asp?tool_id=3820>
-
-endif
-
-# ----------------------------------------------------------
-
-if ARCH_AT91SAM9G10
-
-comment "AT91SAM9G10 Board Type"
-
-config MACH_AT91SAM9G10EK
-	bool "Atmel AT91SAM9G10-EK Evaluation Kit"
-	select HAVE_AT91_DATAFLASH_CARD
-	help
-	  Select this if you are using Atmel's AT91SAM9G10-EK Evaluation Kit.
-	  <http://www.atmel.com/dyn/products/tools_card.asp?tool_id=4588>
-
-endif
-
-# ----------------------------------------------------------
-
-if ARCH_AT91SAM9263
-
-comment "AT91SAM9263 Board Type"
-
-config MACH_AT91SAM9263EK
-	bool "Atmel AT91SAM9263-EK Evaluation Kit"
-	select HAVE_AT91_DATAFLASH_CARD
-	help
-	  Select this if you are using Atmel's AT91SAM9263-EK Evaluation Kit.
-	  <http://www.atmel.com/dyn/products/tools_card.asp?tool_id=4057>
-
-config MACH_USB_A9263
-	bool "CALAO USB-A9263"
-	help
-	  Select this if you are using a Calao Systems USB-A9263.
-	  <http://www.calao-systems.com>
-
-endif
-
-# ----------------------------------------------------------
-
-if ARCH_AT91SAM9RL
-
-comment "AT91SAM9RL Board Type"
-
-config MACH_AT91SAM9RLEK
-	bool "Atmel AT91SAM9RL-EK Evaluation Kit"
-	help
-	  Select this if you are using Atmel's AT91SAM9RL-EK Evaluation Kit.
-
-endif
-
 # ----------------------------------------------------------
 
-if ARCH_AT91SAM9G20
-
-comment "AT91SAM9G20 Board Type"
-
-config MACH_AT91SAM9G20EK
-	bool "Atmel AT91SAM9G20-EK Evaluation Kit"
-	select HAVE_AT91_DATAFLASH_CARD
-	help
-	  Select this if you are using Atmel's AT91SAM9G20-EK Evaluation Kit
-	  that embeds only one SD/MMC slot.
-
-config MACH_AT91SAM9G20EK_2MMC
-	depends on MACH_AT91SAM9G20EK
-	bool "Atmel AT91SAM9G20-EK Evaluation Kit with 2 SD/MMC Slots"
-	help
-	  Select this if you are using an Atmel AT91SAM9G20-EK Evaluation Kit
-	  with 2 SD/MMC Slots. This is the case for AT91SAM9G20-EK rev. C and
-	  onwards.
-	  <http://www.atmel.com/tools/SAM9G20-EK.aspx>
-
-config MACH_CPU9G20
-	bool "Eukrea CPU9G20 board"
-	help
-	  Select this if you are using a Eukrea Electromatique's
-	  CPU9G20 Board <http://www.eukrea.com/>
-
-config MACH_ACMENETUSFOXG20
-	bool "Acme Systems srl FOX Board G20"
-	help
-	  Select this if you are using Acme Systems
-	  FOX Board G20 <http://www.acmesystems.it>
-
-config MACH_PORTUXG20
-	bool "taskit PortuxG20"
-	help
-	  Select this if you are using taskit's PortuxG20.
-	  <http://www.taskit.de/en/>
-
-config MACH_STAMP9G20
-	bool "taskit Stamp9G20 CPU module"
-	help
-	  Select this if you are using taskit's Stamp9G20 CPU module on its
-	  evaluation board.
-	  <http://www.taskit.de/en/>
-
-config MACH_PCONTROL_G20
-	bool "PControl G20 CPU module"
-	help
-	  Select this if you are using taskit's Stamp9G20 CPU module on this
-	  carrier board, beeing the decentralized unit of a building automation
-	  system; featuring nvram, eth-switch, iso-rs485, display, io
-
-config MACH_GSIA18S
-	bool "GS_IA18_S board"
-	help
-	  This enables support for the GS_IA18_S board
-	  produced by GeoSIG Ltd company. This is an internet accelerograph.
-	  <http://www.geosig.com>
-
-config MACH_USB_A9G20
-	bool "CALAO USB-A9G20"
-	depends on ARCH_AT91SAM9G20
-	help
-	  Select this if you are using a Calao Systems USB-A9G20.
-	  <http://www.calao-systems.com>
-
-endif
-
-if (ARCH_AT91SAM9260 || ARCH_AT91SAM9G20)
-comment "AT91SAM9260/AT91SAM9G20 boards"
-
-config MACH_SNAPPER_9260
-        bool "Bluewater Systems Snapper 9260/9G20 module"
-        help
-          Select this if you are using the Bluewater Systems Snapper 9260 or
-          Snapper 9G20 modules.
-          <http://www.bluewatersys.com/>
-endif
-
-# ----------------------------------------------------------
-
-if ARCH_AT91SAM9G45
-
-comment "AT91SAM9G45 Board Type"
-
-config MACH_AT91SAM9M10G45EK
-	bool "Atmel AT91SAM9M10G45-EK Evaluation Kits"
-	help
-	  Select this if you are using Atmel's AT91SAM9M10G45-EK Evaluation Kit.
-	  Those boards can be populated with any SoC of AT91SAM9G45 or AT91SAM9M10
-	  families: AT91SAM9G45, AT91SAM9G46, AT91SAM9M10 and AT91SAM9M11.
-	  <http://www.atmel.com/tools/SAM9M10-G45-EK.aspx>
-
-endif
-
-# ----------------------------------------------------------
-
-if ARCH_AT91X40
-
-comment "AT91X40 Board Type"
-
-config MACH_AT91EB01
-	bool "Atmel AT91EB01 Evaluation Kit"
-	help
-	  Select this if you are using Atmel's AT91EB01 Evaluation Kit.
-	  It is also a popular target for simulators such as GDB's
-	  ARM simulator (commonly known as the ARMulator) and the
-	  Skyeye simulator.
-
-endif
-
-# ----------------------------------------------------------
+source arch/arm/mach-at91/Kconfig.non_dt
+endif # SOC_SAM_V4_V5
 
 comment "Generic Board Type"
 
@@ -492,7 +151,7 @@ config MACH_AT91RM9200_DT
 	  Select this if you want to experiment device-tree with
 	  an Atmel RM9200 Evaluation Kit.
 
-config MACH_AT91SAM_DT
+config MACH_AT91SAM9_DT
 	bool "Atmel AT91SAM Evaluation Kits with device-tree support"
 	depends on SOC_AT91SAM9
 	select USE_OF
@@ -500,15 +159,13 @@ config MACH_AT91SAM_DT
 	  Select this if you want to experiment device-tree with
 	  an Atmel Evaluation Kit.
 
-# ----------------------------------------------------------
-
-comment "AT91 Board Options"
-
-config MTD_AT91_DATAFLASH_CARD
-	bool "Enable DataFlash Card support"
-	depends on HAVE_AT91_DATAFLASH_CARD
+config MACH_SAMA5_DT
+	bool "Atmel SAMA5 Evaluation Kits with device-tree support"
+	depends on SOC_SAMA5
+	select USE_OF
 	help
-	  Enable support for the DataFlash card.
+	  Select this if you want to experiment device-tree with
+	  an Atmel Evaluation Kit.
 
 # ----------------------------------------------------------
 
diff --git a/arch/arm/mach-at91/Kconfig.non_dt b/arch/arm/mach-at91/Kconfig.non_dt
new file mode 100644
index 0000000..6c24985
--- /dev/null
+++ b/arch/arm/mach-at91/Kconfig.non_dt
@@ -0,0 +1,399 @@
+menu "Atmel Non-DT world"
+
+config HAVE_AT91_DATAFLASH_CARD
+	bool
+
+choice
+	prompt "Atmel AT91 Processor Devices for non DT boards"
+
+config ARCH_AT91_NONE
+	bool "None"
+
+config ARCH_AT91RM9200
+	bool "AT91RM9200"
+	select SOC_AT91RM9200
+
+config ARCH_AT91SAM9260
+	bool "AT91SAM9260 or AT91SAM9XE"
+	select SOC_AT91SAM9260
+
+config ARCH_AT91SAM9261
+	bool "AT91SAM9261"
+	select SOC_AT91SAM9261
+
+config ARCH_AT91SAM9G10
+	bool "AT91SAM9G10"
+	select SOC_AT91SAM9261
+
+config ARCH_AT91SAM9263
+	bool "AT91SAM9263"
+	select SOC_AT91SAM9263
+
+config ARCH_AT91SAM9RL
+	bool "AT91SAM9RL"
+	select SOC_AT91SAM9RL
+
+config ARCH_AT91SAM9G20
+	bool "AT91SAM9G20"
+	select SOC_AT91SAM9260
+
+config ARCH_AT91SAM9G45
+	bool "AT91SAM9G45"
+	select SOC_AT91SAM9G45
+
+config ARCH_AT91X40
+	bool "AT91x40"
+	depends on !MMU
+	select ARCH_USES_GETTIMEOFFSET
+	select MULTI_IRQ_HANDLER
+	select SPARSE_IRQ
+
+endchoice
+
+# ----------------------------------------------------------
+
+if ARCH_AT91RM9200
+
+comment "AT91RM9200 Board Type"
+
+config MACH_ONEARM
+	bool "Ajeco 1ARM Single Board Computer"
+	help
+	  Select this if you are using Ajeco's 1ARM Single Board Computer.
+	  <http://www.ajeco.fi/>
+
+config ARCH_AT91RM9200DK
+	bool "Atmel AT91RM9200-DK Development board"
+	select HAVE_AT91_DATAFLASH_CARD
+	help
+	  Select this if you are using Atmel's AT91RM9200-DK Development board.
+	  (Discontinued)
+
+config MACH_AT91RM9200EK
+	bool "Atmel AT91RM9200-EK Evaluation Kit"
+	select HAVE_AT91_DATAFLASH_CARD
+	help
+	  Select this if you are using Atmel's AT91RM9200-EK Evaluation Kit.
+	  <http://www.atmel.com/dyn/products/tools_card.asp?tool_id=3507>
+
+config MACH_CSB337
+	bool "Cogent CSB337"
+	help
+	  Select this if you are using Cogent's CSB337 board.
+	  <http://www.cogcomp.com/csb_csb337.htm>
+
+config MACH_CSB637
+	bool "Cogent CSB637"
+	help
+	  Select this if you are using Cogent's CSB637 board.
+	  <http://www.cogcomp.com/csb_csb637.htm>
+
+config MACH_CARMEVA
+	bool "Conitec ARM&EVA"
+	help
+	  Select this if you are using Conitec's AT91RM9200-MCU-Module.
+	  <http://www.conitec.net/english/linuxboard.php>
+
+config MACH_ATEB9200
+	bool "Embest ATEB9200"
+	help
+	  Select this if you are using Embest's ATEB9200 board.
+	  <http://www.embedinfo.com/english/product/ATEB9200.asp>
+
+config MACH_KB9200
+	bool "KwikByte KB920x"
+	help
+	  Select this if you are using KwikByte's KB920x board.
+	  <http://www.kwikbyte.com/KB9202.html>
+
+config MACH_PICOTUX2XX
+	bool "picotux 200"
+	help
+	  Select this if you are using a picotux 200.
+	  <http://www.picotux.com/>
+
+config MACH_KAFA
+	bool "Sperry-Sun KAFA board"
+	help
+	  Select this if you are using Sperry-Sun's KAFA board.
+
+config MACH_ECBAT91
+	bool "emQbit ECB_AT91 SBC"
+	select HAVE_AT91_DATAFLASH_CARD
+	help
+	  Select this if you are using emQbit's ECB_AT91 board.
+	  <http://wiki.emqbit.com/free-ecb-at91>
+
+config MACH_YL9200
+	bool "ucDragon YL-9200"
+	help
+	  Select this if you are using the ucDragon YL-9200 board.
+
+config MACH_CPUAT91
+	bool "Eukrea CPUAT91"
+	help
+	  Select this if you are using the Eukrea Electromatique's
+	  CPUAT91 board <http://www.eukrea.com/>.
+
+config MACH_ECO920
+	bool "eco920"
+	help
+	  Select this if you are using the eco920 board
+
+config MACH_RSI_EWS
+	bool "RSI Embedded Webserver"
+	depends on ARCH_AT91RM9200
+	help
+	  Select this if you are using RSIs EWS board.
+endif
+
+# ----------------------------------------------------------
+
+if ARCH_AT91SAM9260
+
+comment "AT91SAM9260 Variants"
+
+comment "AT91SAM9260 / AT91SAM9XE Board Type"
+
+config MACH_AT91SAM9260EK
+	bool "Atmel AT91SAM9260-EK / AT91SAM9XE Evaluation Kit"
+	select HAVE_AT91_DATAFLASH_CARD
+	help
+	  Select this if you are using Atmel's AT91SAM9260-EK or AT91SAM9XE Evaluation Kit
+	  <http://www.atmel.com/dyn/products/tools_card.asp?tool_id=3933>
+
+config MACH_CAM60
+	bool "KwikByte KB9260 (CAM60) board"
+	help
+	  Select this if you are using KwikByte's KB9260 (CAM60) board based on the Atmel AT91SAM9260.
+	  <http://www.kwikbyte.com/KB9260.html>
+
+config MACH_SAM9_L9260
+	bool "Olimex SAM9-L9260 board"
+	select HAVE_AT91_DATAFLASH_CARD
+	help
+	  Select this if you are using Olimex's SAM9-L9260 board based on the Atmel AT91SAM9260.
+	  <http://www.olimex.com/dev/sam9-L9260.html>
+
+config MACH_AFEB9260
+	bool "Custom afeb9260 board v1"
+	help
+	  Select this if you are using custom afeb9260 board based on
+	  open hardware design. Select this for revision 1 of the board.
+	  <svn://194.85.238.22/home/users/george/svn/arm9eb>
+	  <http://groups.google.com/group/arm9fpga-evolution-board>
+
+config MACH_USB_A9260
+	bool "CALAO USB-A9260"
+	help
+	  Select this if you are using a Calao Systems USB-A9260.
+	  <http://www.calao-systems.com>
+
+config MACH_QIL_A9260
+	bool "CALAO QIL-A9260 board"
+	help
+	  Select this if you are using a Calao Systems QIL-A9260 Board.
+	  <http://www.calao-systems.com>
+
+config MACH_CPU9260
+	bool "Eukrea CPU9260 board"
+	help
+	  Select this if you are using a Eukrea Electromatique's
+	  CPU9260 Board <http://www.eukrea.com/>
+
+config MACH_FLEXIBITY
+	bool "Flexibity Connect board"
+	help
+	  Select this if you are using Flexibity Connect board
+	  <http://www.flexibity.com>
+
+endif
+
+# ----------------------------------------------------------
+
+if ARCH_AT91SAM9261
+
+comment "AT91SAM9261 Board Type"
+
+config MACH_AT91SAM9261EK
+	bool "Atmel AT91SAM9261-EK Evaluation Kit"
+	select HAVE_AT91_DATAFLASH_CARD
+	help
+	  Select this if you are using Atmel's AT91SAM9261-EK Evaluation Kit.
+	  <http://www.atmel.com/dyn/products/tools_card.asp?tool_id=3820>
+
+endif
+
+# ----------------------------------------------------------
+
+if ARCH_AT91SAM9G10
+
+comment "AT91SAM9G10 Board Type"
+
+config MACH_AT91SAM9G10EK
+	bool "Atmel AT91SAM9G10-EK Evaluation Kit"
+	select HAVE_AT91_DATAFLASH_CARD
+	help
+	  Select this if you are using Atmel's AT91SAM9G10-EK Evaluation Kit.
+	  <http://www.atmel.com/dyn/products/tools_card.asp?tool_id=4588>
+
+endif
+
+# ----------------------------------------------------------
+
+if ARCH_AT91SAM9263
+
+comment "AT91SAM9263 Board Type"
+
+config MACH_AT91SAM9263EK
+	bool "Atmel AT91SAM9263-EK Evaluation Kit"
+	select HAVE_AT91_DATAFLASH_CARD
+	help
+	  Select this if you are using Atmel's AT91SAM9263-EK Evaluation Kit.
+	  <http://www.atmel.com/dyn/products/tools_card.asp?tool_id=4057>
+
+config MACH_USB_A9263
+	bool "CALAO USB-A9263"
+	help
+	  Select this if you are using a Calao Systems USB-A9263.
+	  <http://www.calao-systems.com>
+
+endif
+
+# ----------------------------------------------------------
+
+if ARCH_AT91SAM9RL
+
+comment "AT91SAM9RL Board Type"
+
+config MACH_AT91SAM9RLEK
+	bool "Atmel AT91SAM9RL-EK Evaluation Kit"
+	help
+	  Select this if you are using Atmel's AT91SAM9RL-EK Evaluation Kit.
+
+endif
+
+# ----------------------------------------------------------
+
+if ARCH_AT91SAM9G20
+
+comment "AT91SAM9G20 Board Type"
+
+config MACH_AT91SAM9G20EK
+	bool "Atmel AT91SAM9G20-EK Evaluation Kit"
+	select HAVE_AT91_DATAFLASH_CARD
+	help
+	  Select this if you are using Atmel's AT91SAM9G20-EK Evaluation Kit
+	  that embeds only one SD/MMC slot.
+
+config MACH_AT91SAM9G20EK_2MMC
+	depends on MACH_AT91SAM9G20EK
+	bool "Atmel AT91SAM9G20-EK Evaluation Kit with 2 SD/MMC Slots"
+	help
+	  Select this if you are using an Atmel AT91SAM9G20-EK Evaluation Kit
+	  with 2 SD/MMC Slots. This is the case for AT91SAM9G20-EK rev. C and
+	  onwards.
+	  <http://www.atmel.com/tools/SAM9G20-EK.aspx>
+
+config MACH_CPU9G20
+	bool "Eukrea CPU9G20 board"
+	help
+	  Select this if you are using a Eukrea Electromatique's
+	  CPU9G20 Board <http://www.eukrea.com/>
+
+config MACH_ACMENETUSFOXG20
+	bool "Acme Systems srl FOX Board G20"
+	help
+	  Select this if you are using Acme Systems
+	  FOX Board G20 <http://www.acmesystems.it>
+
+config MACH_PORTUXG20
+	bool "taskit PortuxG20"
+	help
+	  Select this if you are using taskit's PortuxG20.
+	  <http://www.taskit.de/en/>
+
+config MACH_STAMP9G20
+	bool "taskit Stamp9G20 CPU module"
+	help
+	  Select this if you are using taskit's Stamp9G20 CPU module on its
+	  evaluation board.
+	  <http://www.taskit.de/en/>
+
+config MACH_PCONTROL_G20
+	bool "PControl G20 CPU module"
+	help
+	  Select this if you are using taskit's Stamp9G20 CPU module on this
+	  carrier board, beeing the decentralized unit of a building automation
+	  system; featuring nvram, eth-switch, iso-rs485, display, io
+
+config MACH_GSIA18S
+	bool "GS_IA18_S board"
+	help
+	  This enables support for the GS_IA18_S board
+	  produced by GeoSIG Ltd company. This is an internet accelerograph.
+	  <http://www.geosig.com>
+
+config MACH_USB_A9G20
+	bool "CALAO USB-A9G20"
+	depends on ARCH_AT91SAM9G20
+	help
+	  Select this if you are using a Calao Systems USB-A9G20.
+	  <http://www.calao-systems.com>
+
+endif
+
+if (ARCH_AT91SAM9260 || ARCH_AT91SAM9G20)
+comment "AT91SAM9260/AT91SAM9G20 boards"
+
+config MACH_SNAPPER_9260
+        bool "Bluewater Systems Snapper 9260/9G20 module"
+        help
+          Select this if you are using the Bluewater Systems Snapper 9260 or
+          Snapper 9G20 modules.
+          <http://www.bluewatersys.com/>
+endif
+
+# ----------------------------------------------------------
+
+if ARCH_AT91SAM9G45
+
+comment "AT91SAM9G45 Board Type"
+
+config MACH_AT91SAM9M10G45EK
+	bool "Atmel AT91SAM9M10G45-EK Evaluation Kits"
+	help
+	  Select this if you are using Atmel's AT91SAM9M10G45-EK Evaluation Kit.
+	  Those boards can be populated with any SoC of AT91SAM9G45 or AT91SAM9M10
+	  families: AT91SAM9G45, AT91SAM9G46, AT91SAM9M10 and AT91SAM9M11.
+	  <http://www.atmel.com/tools/SAM9M10-G45-EK.aspx>
+
+endif
+
+# ----------------------------------------------------------
+
+if ARCH_AT91X40
+
+comment "AT91X40 Board Type"
+
+config MACH_AT91EB01
+	bool "Atmel AT91EB01 Evaluation Kit"
+	help
+	  Select this if you are using Atmel's AT91EB01 Evaluation Kit.
+	  It is also a popular target for simulators such as GDB's
+	  ARM simulator (commonly known as the ARMulator) and the
+	  Skyeye simulator.
+
+endif
+
+# ----------------------------------------------------------
+
+comment "AT91 Board Options"
+
+config MTD_AT91_DATAFLASH_CARD
+	bool "Enable DataFlash Card support"
+	depends on HAVE_AT91_DATAFLASH_CARD
+	help
+	  Enable support for the DataFlash card.
+
+endmenu
diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile
index 39218ca..788562d 100644
--- a/arch/arm/mach-at91/Makefile
+++ b/arch/arm/mach-at91/Makefile
@@ -10,7 +10,8 @@ obj-		:=
 obj-$(CONFIG_AT91_PMC_UNIT)	+= clock.o
 obj-$(CONFIG_AT91_SAM9_ALT_RESET) += at91sam9_alt_reset.o
 obj-$(CONFIG_AT91_SAM9G45_RESET) += at91sam9g45_reset.o
-obj-$(CONFIG_SOC_AT91SAM9)	+= at91sam926x_time.o sam9_smc.o
+obj-$(CONFIG_AT91_SAM9_TIME)	+= at91sam926x_time.o
+obj-$(CONFIG_SOC_AT91SAM9)	+= sam9_smc.o
 
 # CPU-specific support
 obj-$(CONFIG_SOC_AT91RM9200)	+= at91rm9200.o at91rm9200_time.o
@@ -21,6 +22,7 @@ obj-$(CONFIG_SOC_AT91SAM9G45)	+= at91sam9g45.o
 obj-$(CONFIG_SOC_AT91SAM9N12)	+= at91sam9n12.o
 obj-$(CONFIG_SOC_AT91SAM9X5)	+= at91sam9x5.o
 obj-$(CONFIG_SOC_AT91SAM9RL)	+= at91sam9rl.o
+obj-$(CONFIG_SOC_SAMA5D3)	+= sama5d3.o
 
 obj-$(CONFIG_ARCH_AT91RM9200)	+= at91rm9200_devices.o
 obj-$(CONFIG_ARCH_AT91SAM9260)	+= at91sam9260_devices.o
@@ -87,8 +89,11 @@ obj-$(CONFIG_MACH_SNAPPER_9260)	+= board-snapper9260.o
 obj-$(CONFIG_MACH_AT91SAM9M10G45EK) += board-sam9m10g45ek.o
 
 # AT91SAM board with device-tree
-obj-$(CONFIG_MACH_AT91RM9200_DT) += board-rm9200-dt.o
-obj-$(CONFIG_MACH_AT91SAM_DT) += board-dt.o
+obj-$(CONFIG_MACH_AT91RM9200_DT) += board-dt-rm9200.o
+obj-$(CONFIG_MACH_AT91SAM9_DT) += board-dt-sam9.o
+
+# SAMA5 board with device-tree
+obj-$(CONFIG_MACH_SAMA5_DT) += board-dt-sama5.o
 
 # AT91X40 board-specific support
 obj-$(CONFIG_MACH_AT91EB01)	+= board-eb01.o
diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c
index 9706c00..d193a40 100644
--- a/arch/arm/mach-at91/at91rm9200.c
+++ b/arch/arm/mach-at91/at91rm9200.c
@@ -212,6 +212,7 @@ static struct clk_lookup periph_clocks_lookups[] = {
 	CLKDEV_CON_DEV_ID("t2_clk", "fffa4000.timer", &tc5_clk),
 	CLKDEV_CON_DEV_ID("mci_clk", "fffb4000.mmc", &mmc_clk),
 	CLKDEV_CON_DEV_ID("emac_clk", "fffbc000.ethernet", &ether_clk),
+	CLKDEV_CON_DEV_ID(NULL, "fffb8000.i2c", &twi_clk),
 	CLKDEV_CON_DEV_ID("hclk", "300000.ohci", &ohci_clk),
 	CLKDEV_CON_DEV_ID(NULL, "fffff400.gpio", &pioA_clk),
 	CLKDEV_CON_DEV_ID(NULL, "fffff600.gpio", &pioB_clk),
@@ -384,7 +385,7 @@ static unsigned int at91rm9200_default_irq_priority[NR_AIC_IRQS] __initdata = {
 	0	/* Advanced Interrupt Controller (IRQ6) */
 };
 
-AT91_SOC_START(rm9200)
+AT91_SOC_START(at91rm9200)
 	.map_io = at91rm9200_map_io,
 	.default_irq_priority = at91rm9200_default_irq_priority,
 	.ioremap_registers = at91rm9200_ioremap_registers,
diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c
index b67cd53..1833b4c 100644
--- a/arch/arm/mach-at91/at91sam9260.c
+++ b/arch/arm/mach-at91/at91sam9260.c
@@ -395,7 +395,7 @@ static unsigned int at91sam9260_default_irq_priority[NR_AIC_IRQS] __initdata = {
 	0,	/* Advanced Interrupt Controller */
 };
 
-AT91_SOC_START(sam9260)
+AT91_SOC_START(at91sam9260)
 	.map_io = at91sam9260_map_io,
 	.default_irq_priority = at91sam9260_default_irq_priority,
 	.ioremap_registers = at91sam9260_ioremap_registers,
diff --git a/arch/arm/mach-at91/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c
index 2998a08..25efb5a 100644
--- a/arch/arm/mach-at91/at91sam9261.c
+++ b/arch/arm/mach-at91/at91sam9261.c
@@ -169,6 +169,8 @@ static struct clk *periph_clocks[] __initdata = {
 };
 
 static struct clk_lookup periph_clocks_lookups[] = {
+	CLKDEV_CON_DEV_ID("hclk", "at91sam9261-lcdfb.0", &hck1),
+	CLKDEV_CON_DEV_ID("hclk", "at91sam9g10-lcdfb.0", &hck1),
 	CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.0", &spi0_clk),
 	CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.1", &spi1_clk),
 	CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tc0_clk),
@@ -337,7 +339,7 @@ static unsigned int at91sam9261_default_irq_priority[NR_AIC_IRQS] __initdata = {
 	0,	/* Advanced Interrupt Controller */
 };
 
-AT91_SOC_START(sam9261)
+AT91_SOC_START(at91sam9261)
 	.map_io = at91sam9261_map_io,
 	.default_irq_priority = at91sam9261_default_irq_priority,
 	.ioremap_registers = at91sam9261_ioremap_registers,
diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c
index 92e0f86..629ea5f 100644
--- a/arch/arm/mach-at91/at91sam9261_devices.c
+++ b/arch/arm/mach-at91/at91sam9261_devices.c
@@ -488,7 +488,6 @@ static struct resource lcdc_resources[] = {
 };
 
 static struct platform_device at91_lcdc_device = {
-	.name		= "atmel_lcdfb",
 	.id		= 0,
 	.dev		= {
 				.dma_mask		= &lcdc_dmamask,
@@ -505,6 +504,11 @@ void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data)
 		return;
 	}
 
+	if (cpu_is_at91sam9g10())
+		at91_lcdc_device.name = "at91sam9g10-lcdfb";
+	else
+		at91_lcdc_device.name = "at91sam9261-lcdfb";
+
 #if defined(CONFIG_FB_ATMEL_STN)
 	at91_set_A_periph(AT91_PIN_PB0, 0);     /* LCDVSYNC */
 	at91_set_A_periph(AT91_PIN_PB1, 0);     /* LCDHSYNC */
diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c
index b9fc60d..f44ffd2 100644
--- a/arch/arm/mach-at91/at91sam9263.c
+++ b/arch/arm/mach-at91/at91sam9263.c
@@ -190,6 +190,7 @@ static struct clk_lookup periph_clocks_lookups[] = {
 	CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.1", &ssc1_clk),
 	CLKDEV_CON_DEV_ID("pclk", "fff98000.ssc", &ssc0_clk),
 	CLKDEV_CON_DEV_ID("pclk", "fff9c000.ssc", &ssc1_clk),
+	CLKDEV_CON_DEV_ID("hclk", "at91sam9263-lcdfb.0", &lcdc_clk),
 	CLKDEV_CON_DEV_ID("mci_clk", "atmel_mci.0", &mmc0_clk),
 	CLKDEV_CON_DEV_ID("mci_clk", "atmel_mci.1", &mmc1_clk),
 	CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.0", &spi0_clk),
@@ -374,7 +375,7 @@ static unsigned int at91sam9263_default_irq_priority[NR_AIC_IRQS] __initdata = {
 	0,	/* Advanced Interrupt Controller (IRQ1) */
 };
 
-AT91_SOC_START(sam9263)
+AT91_SOC_START(at91sam9263)
 	.map_io = at91sam9263_map_io,
 	.default_irq_priority = at91sam9263_default_irq_priority,
 	.ioremap_registers = at91sam9263_ioremap_registers,
diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
index ed666f5..858c8aa 100644
--- a/arch/arm/mach-at91/at91sam9263_devices.c
+++ b/arch/arm/mach-at91/at91sam9263_devices.c
@@ -848,7 +848,7 @@ static struct resource lcdc_resources[] = {
 };
 
 static struct platform_device at91_lcdc_device = {
-	.name		= "atmel_lcdfb",
+	.name		= "at91sam9263-lcdfb",
 	.id		= 0,
 	.dev		= {
 				.dma_mask		= &lcdc_dmamask,
diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c
index d3addee..dc49c2c 100644
--- a/arch/arm/mach-at91/at91sam9g45.c
+++ b/arch/arm/mach-at91/at91sam9g45.c
@@ -228,6 +228,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
 	CLKDEV_CON_ID("hclk", &macb_clk),
 	/* One additional fake clock for ohci */
 	CLKDEV_CON_ID("ohci_clk", &uhphs_clk),
+	CLKDEV_CON_DEV_ID("hclk", "at91sam9g45-lcdfb.0", &lcdc_clk),
+	CLKDEV_CON_DEV_ID("hclk", "at91sam9g45es-lcdfb.0", &lcdc_clk),
 	CLKDEV_CON_DEV_ID("ehci_clk", "atmel-ehci", &uhphs_clk),
 	CLKDEV_CON_DEV_ID("hclk", "atmel_usba_udc", &utmi_clk),
 	CLKDEV_CON_DEV_ID("pclk", "atmel_usba_udc", &udphs_clk),
@@ -418,7 +420,7 @@ static unsigned int at91sam9g45_default_irq_priority[NR_AIC_IRQS] __initdata = {
 	0,	/* Advanced Interrupt Controller (IRQ0) */
 };
 
-AT91_SOC_START(sam9g45)
+AT91_SOC_START(at91sam9g45)
 	.map_io = at91sam9g45_map_io,
 	.default_irq_priority = at91sam9g45_default_irq_priority,
 	.ioremap_registers = at91sam9g45_ioremap_registers,
diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c
index 827c9f2..acb703e 100644
--- a/arch/arm/mach-at91/at91sam9g45_devices.c
+++ b/arch/arm/mach-at91/at91sam9g45_devices.c
@@ -18,7 +18,7 @@
 #include <linux/platform_device.h>
 #include <linux/i2c-gpio.h>
 #include <linux/atmel-mci.h>
-#include <linux/platform_data/atmel-aes.h>
+#include <linux/platform_data/crypto-atmel.h>
 
 #include <linux/platform_data/at91_adc.h>
 
@@ -981,7 +981,6 @@ static struct resource lcdc_resources[] = {
 };
 
 static struct platform_device at91_lcdc_device = {
-	.name		= "atmel_lcdfb",
 	.id		= 0,
 	.dev		= {
 				.dma_mask		= &lcdc_dmamask,
@@ -997,6 +996,11 @@ void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data)
 	if (!data)
 		return;
 
+	if (cpu_is_at91sam9g45es())
+		at91_lcdc_device.name = "at91sam9g45es-lcdfb";
+	else
+		at91_lcdc_device.name = "at91sam9g45-lcdfb";
+
 	at91_set_A_periph(AT91_PIN_PE0, 0);	/* LCDDPWR */
 
 	at91_set_A_periph(AT91_PIN_PE2, 0);	/* LCDCC */
@@ -1900,7 +1904,8 @@ static void __init at91_add_device_tdes(void) {}
  * -------------------------------------------------------------------- */
 
 #if defined(CONFIG_CRYPTO_DEV_ATMEL_AES) || defined(CONFIG_CRYPTO_DEV_ATMEL_AES_MODULE)
-static struct aes_platform_data aes_data;
+static struct crypto_platform_data aes_data;
+static struct crypto_dma_data alt_atslave;
 static u64 aes_dmamask = DMA_BIT_MASK(32);
 
 static struct resource aes_resources[] = {
@@ -1931,23 +1936,20 @@ static struct platform_device at91sam9g45_aes_device = {
 static void __init at91_add_device_aes(void)
 {
 	struct at_dma_slave	*atslave;
-	struct aes_dma_data	*alt_atslave;
-
-	alt_atslave = kzalloc(sizeof(struct aes_dma_data), GFP_KERNEL);
 
 	/* DMA TX slave channel configuration */
-	atslave = &alt_atslave->txdata;
+	atslave = &alt_atslave.txdata;
 	atslave->dma_dev = &at_hdmac_device.dev;
 	atslave->cfg = ATC_FIFOCFG_ENOUGHSPACE	| ATC_SRC_H2SEL_HW |
 						ATC_SRC_PER(AT_DMA_ID_AES_RX);
 
 	/* DMA RX slave channel configuration */
-	atslave = &alt_atslave->rxdata;
+	atslave = &alt_atslave.rxdata;
 	atslave->dma_dev = &at_hdmac_device.dev;
 	atslave->cfg = ATC_FIFOCFG_ENOUGHSPACE	| ATC_DST_H2SEL_HW |
 						ATC_DST_PER(AT_DMA_ID_AES_TX);
 
-	aes_data.dma_slave = alt_atslave;
+	aes_data.dma_slave = &alt_atslave;
 	platform_device_register(&at91sam9g45_aes_device);
 }
 #else
diff --git a/arch/arm/mach-at91/at91sam9n12.c b/arch/arm/mach-at91/at91sam9n12.c
index 5dfc8fd..2c7a2f4 100644
--- a/arch/arm/mach-at91/at91sam9n12.c
+++ b/arch/arm/mach-at91/at91sam9n12.c
@@ -226,7 +226,7 @@ void __init at91sam9n12_initialize(void)
 	at91_extern_irq = (1 << AT91SAM9N12_ID_IRQ0);
 }
 
-AT91_SOC_START(sam9n12)
+AT91_SOC_START(at91sam9n12)
 	.map_io = at91sam9n12_map_io,
 	.register_clocks = at91sam9n12_register_clocks,
 	.init = at91sam9n12_initialize,
diff --git a/arch/arm/mach-at91/at91sam9rl.c b/arch/arm/mach-at91/at91sam9rl.c
index eb98704..f77fae5 100644
--- a/arch/arm/mach-at91/at91sam9rl.c
+++ b/arch/arm/mach-at91/at91sam9rl.c
@@ -179,6 +179,7 @@ static struct clk *periph_clocks[] __initdata = {
 };
 
 static struct clk_lookup periph_clocks_lookups[] = {
+	CLKDEV_CON_DEV_ID("hclk", "at91sam9rl-lcdfb.0", &lcdc_clk),
 	CLKDEV_CON_DEV_ID("hclk", "atmel_usba_udc", &utmi_clk),
 	CLKDEV_CON_DEV_ID("pclk", "atmel_usba_udc", &udphs_clk),
 	CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tc0_clk),
@@ -340,7 +341,7 @@ static unsigned int at91sam9rl_default_irq_priority[NR_AIC_IRQS] __initdata = {
 	0,	/* Advanced Interrupt Controller */
 };
 
-AT91_SOC_START(sam9rl)
+AT91_SOC_START(at91sam9rl)
 	.map_io = at91sam9rl_map_io,
 	.default_irq_priority = at91sam9rl_default_irq_priority,
 	.ioremap_registers = at91sam9rl_ioremap_registers,
diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c
index ddf223f..352468f 100644
--- a/arch/arm/mach-at91/at91sam9rl_devices.c
+++ b/arch/arm/mach-at91/at91sam9rl_devices.c
@@ -514,7 +514,7 @@ static struct resource lcdc_resources[] = {
 };
 
 static struct platform_device at91_lcdc_device = {
-	.name		= "atmel_lcdfb",
+	.name		= "at91sam9rl-lcdfb",
 	.id		= 0,
 	.dev		= {
 				.dma_mask		= &lcdc_dmamask,
diff --git a/arch/arm/mach-at91/at91sam9x5.c b/arch/arm/mach-at91/at91sam9x5.c
index 44a9a62..3a1a799 100644
--- a/arch/arm/mach-at91/at91sam9x5.c
+++ b/arch/arm/mach-at91/at91sam9x5.c
@@ -320,7 +320,7 @@ static void __init at91sam9x5_map_io(void)
  *  Interrupt initialization
  * -------------------------------------------------------------------- */
 
-AT91_SOC_START(sam9x5)
+AT91_SOC_START(at91sam9x5)
 	.map_io = at91sam9x5_map_io,
 	.register_clocks = at91sam9x5_register_clocks,
 AT91_SOC_END
diff --git a/arch/arm/mach-at91/board-dt-rm9200.c b/arch/arm/mach-at91/board-dt-rm9200.c
new file mode 100644
index 0000000..3fcb662
--- /dev/null
+++ b/arch/arm/mach-at91/board-dt-rm9200.c
@@ -0,0 +1,57 @@
+/*
+ *  Setup code for AT91RM9200 Evaluation Kits with Device Tree support
+ *
+ *  Copyright (C) 2011 Atmel,
+ *                2011 Nicolas Ferre <nicolas.ferre@atmel.com>
+ *                2012 Joachim Eastwood <manabian@gmail.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+
+#include <asm/setup.h>
+#include <asm/irq.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include "at91_aic.h"
+#include "generic.h"
+
+
+static const struct of_device_id irq_of_match[] __initconst = {
+	{ .compatible = "atmel,at91rm9200-aic", .data = at91_aic_of_init },
+	{ /*sentinel*/ }
+};
+
+static void __init at91rm9200_dt_init_irq(void)
+{
+	of_irq_init(irq_of_match);
+}
+
+static void __init at91rm9200_dt_device_init(void)
+{
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+}
+
+static const char *at91rm9200_dt_board_compat[] __initdata = {
+	"atmel,at91rm9200",
+	NULL
+};
+
+DT_MACHINE_START(at91rm9200_dt, "Atmel AT91RM9200 (Device Tree)")
+	.init_time      = at91rm9200_timer_init,
+	.map_io		= at91_map_io,
+	.handle_irq	= at91_aic_handle_irq,
+	.init_early	= at91rm9200_dt_initialize,
+	.init_irq	= at91rm9200_dt_init_irq,
+	.init_machine	= at91rm9200_dt_device_init,
+	.dt_compat	= at91rm9200_dt_board_compat,
+MACHINE_END
diff --git a/arch/arm/mach-at91/board-dt-sam9.c b/arch/arm/mach-at91/board-dt-sam9.c
new file mode 100644
index 0000000..8db3013
--- /dev/null
+++ b/arch/arm/mach-at91/board-dt-sam9.c
@@ -0,0 +1,59 @@
+/*
+ *  Setup code for AT91SAM Evaluation Kits with Device Tree support
+ *
+ *  Copyright (C) 2011 Atmel,
+ *                2011 Nicolas Ferre <nicolas.ferre@atmel.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+
+#include <asm/setup.h>
+#include <asm/irq.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include "at91_aic.h"
+#include "board.h"
+#include "generic.h"
+
+
+static const struct of_device_id irq_of_match[] __initconst = {
+
+	{ .compatible = "atmel,at91rm9200-aic", .data = at91_aic_of_init },
+	{ /*sentinel*/ }
+};
+
+static void __init at91_dt_init_irq(void)
+{
+	of_irq_init(irq_of_match);
+}
+
+static void __init at91_dt_device_init(void)
+{
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+}
+
+static const char *at91_dt_board_compat[] __initdata = {
+	"atmel,at91sam9",
+	NULL
+};
+
+DT_MACHINE_START(at91sam_dt, "Atmel AT91SAM (Device Tree)")
+	/* Maintainer: Atmel */
+	.init_time	= at91sam926x_pit_init,
+	.map_io		= at91_map_io,
+	.handle_irq	= at91_aic_handle_irq,
+	.init_early	= at91_dt_initialize,
+	.init_irq	= at91_dt_init_irq,
+	.init_machine	= at91_dt_device_init,
+	.dt_compat	= at91_dt_board_compat,
+MACHINE_END
diff --git a/arch/arm/mach-at91/board-dt-sama5.c b/arch/arm/mach-at91/board-dt-sama5.c
new file mode 100644
index 0000000..705305e
--- /dev/null
+++ b/arch/arm/mach-at91/board-dt-sama5.c
@@ -0,0 +1,86 @@
+/*
+ *  Setup code for SAMA5 Evaluation Kits with Device Tree support
+ *
+ *  Copyright (C) 2013 Atmel,
+ *                2013 Ludovic Desroches <ludovic.desroches@atmel.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/micrel_phy.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/phy.h>
+
+#include <asm/setup.h>
+#include <asm/irq.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include "at91_aic.h"
+#include "generic.h"
+
+
+static const struct of_device_id irq_of_match[] __initconst = {
+
+	{ .compatible = "atmel,sama5d3-aic", .data = at91_aic5_of_init },
+	{ /*sentinel*/ }
+};
+
+static void __init at91_dt_init_irq(void)
+{
+	of_irq_init(irq_of_match);
+}
+
+static int ksz9021rn_phy_fixup(struct phy_device *phy)
+{
+	int value;
+
+#define GMII_RCCPSR	260
+#define GMII_RRDPSR	261
+#define GMII_ERCR	11
+#define GMII_ERDWR	12
+
+	/* Set delay values */
+	value = GMII_RCCPSR | 0x8000;
+	phy_write(phy, GMII_ERCR, value);
+	value = 0xF2F4;
+	phy_write(phy, GMII_ERDWR, value);
+	value = GMII_RRDPSR | 0x8000;
+	phy_write(phy, GMII_ERCR, value);
+	value = 0x2222;
+	phy_write(phy, GMII_ERDWR, value);
+
+	return 0;
+}
+
+static void __init sama5_dt_device_init(void)
+{
+	if (of_machine_is_compatible("atmel,sama5d3xcm"))
+		phy_register_fixup_for_uid(PHY_ID_KSZ9021, MICREL_PHY_ID_MASK,
+			ksz9021rn_phy_fixup);
+
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+}
+
+static const char *sama5_dt_board_compat[] __initdata = {
+	"atmel,sama5",
+	NULL
+};
+
+DT_MACHINE_START(sama5_dt, "Atmel SAMA5 (Device Tree)")
+	/* Maintainer: Atmel */
+	.init_time	= at91sam926x_pit_init,
+	.map_io		= at91_map_io,
+	.handle_irq	= at91_aic5_handle_irq,
+	.init_early	= at91_dt_initialize,
+	.init_irq	= at91_dt_init_irq,
+	.init_machine	= sama5_dt_device_init,
+	.dt_compat	= sama5_dt_board_compat,
+MACHINE_END
diff --git a/arch/arm/mach-at91/board-dt.c b/arch/arm/mach-at91/board-dt.c
deleted file mode 100644
index 8db3013..0000000
--- a/arch/arm/mach-at91/board-dt.c
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- *  Setup code for AT91SAM Evaluation Kits with Device Tree support
- *
- *  Copyright (C) 2011 Atmel,
- *                2011 Nicolas Ferre <nicolas.ferre@atmel.com>
- *
- * Licensed under GPLv2 or later.
- */
-
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/gpio.h>
-#include <linux/of.h>
-#include <linux/of_irq.h>
-#include <linux/of_platform.h>
-
-#include <asm/setup.h>
-#include <asm/irq.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include "at91_aic.h"
-#include "board.h"
-#include "generic.h"
-
-
-static const struct of_device_id irq_of_match[] __initconst = {
-
-	{ .compatible = "atmel,at91rm9200-aic", .data = at91_aic_of_init },
-	{ /*sentinel*/ }
-};
-
-static void __init at91_dt_init_irq(void)
-{
-	of_irq_init(irq_of_match);
-}
-
-static void __init at91_dt_device_init(void)
-{
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-}
-
-static const char *at91_dt_board_compat[] __initdata = {
-	"atmel,at91sam9",
-	NULL
-};
-
-DT_MACHINE_START(at91sam_dt, "Atmel AT91SAM (Device Tree)")
-	/* Maintainer: Atmel */
-	.init_time	= at91sam926x_pit_init,
-	.map_io		= at91_map_io,
-	.handle_irq	= at91_aic_handle_irq,
-	.init_early	= at91_dt_initialize,
-	.init_irq	= at91_dt_init_irq,
-	.init_machine	= at91_dt_device_init,
-	.dt_compat	= at91_dt_board_compat,
-MACHINE_END
diff --git a/arch/arm/mach-at91/board-rm9200-dt.c b/arch/arm/mach-at91/board-rm9200-dt.c
deleted file mode 100644
index 3fcb662..0000000
--- a/arch/arm/mach-at91/board-rm9200-dt.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- *  Setup code for AT91RM9200 Evaluation Kits with Device Tree support
- *
- *  Copyright (C) 2011 Atmel,
- *                2011 Nicolas Ferre <nicolas.ferre@atmel.com>
- *                2012 Joachim Eastwood <manabian@gmail.com>
- *
- * Licensed under GPLv2 or later.
- */
-
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/gpio.h>
-#include <linux/of.h>
-#include <linux/of_irq.h>
-#include <linux/of_platform.h>
-
-#include <asm/setup.h>
-#include <asm/irq.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include "at91_aic.h"
-#include "generic.h"
-
-
-static const struct of_device_id irq_of_match[] __initconst = {
-	{ .compatible = "atmel,at91rm9200-aic", .data = at91_aic_of_init },
-	{ /*sentinel*/ }
-};
-
-static void __init at91rm9200_dt_init_irq(void)
-{
-	of_irq_init(irq_of_match);
-}
-
-static void __init at91rm9200_dt_device_init(void)
-{
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-}
-
-static const char *at91rm9200_dt_board_compat[] __initdata = {
-	"atmel,at91rm9200",
-	NULL
-};
-
-DT_MACHINE_START(at91rm9200_dt, "Atmel AT91RM9200 (Device Tree)")
-	.init_time      = at91rm9200_timer_init,
-	.map_io		= at91_map_io,
-	.handle_irq	= at91_aic_handle_irq,
-	.init_early	= at91rm9200_dt_initialize,
-	.init_irq	= at91rm9200_dt_init_irq,
-	.init_machine	= at91rm9200_dt_device_init,
-	.dt_compat	= at91rm9200_dt_board_compat,
-MACHINE_END
diff --git a/arch/arm/mach-at91/clock.c b/arch/arm/mach-at91/clock.c
index 3336150..da84188 100644
--- a/arch/arm/mach-at91/clock.c
+++ b/arch/arm/mach-at91/clock.c
@@ -54,7 +54,10 @@ EXPORT_SYMBOL_GPL(at91_pmc_base);
  */
 #define cpu_has_utmi()		(  cpu_is_at91sam9rl() \
 				|| cpu_is_at91sam9g45() \
-				|| cpu_is_at91sam9x5())
+				|| cpu_is_at91sam9x5() \
+				|| cpu_is_sama5d3())
+
+#define cpu_has_1056M_plla()	(cpu_is_sama5d3())
 
 #define cpu_has_800M_plla()	(  cpu_is_at91sam9g20() \
 				|| cpu_is_at91sam9g45() \
@@ -75,7 +78,8 @@ EXPORT_SYMBOL_GPL(at91_pmc_base);
 				|| cpu_is_at91sam9n12()))
 
 #define cpu_has_upll()		(cpu_is_at91sam9g45() \
-				|| cpu_is_at91sam9x5())
+				|| cpu_is_at91sam9x5() \
+				|| cpu_is_sama5d3())
 
 /* USB host HS & FS */
 #define cpu_has_uhp()		(!cpu_is_at91sam9rl())
@@ -83,18 +87,22 @@ EXPORT_SYMBOL_GPL(at91_pmc_base);
 /* USB device FS only */
 #define cpu_has_udpfs()		(!(cpu_is_at91sam9rl() \
 				|| cpu_is_at91sam9g45() \
-				|| cpu_is_at91sam9x5()))
+				|| cpu_is_at91sam9x5() \
+				|| cpu_is_sama5d3()))
 
 #define cpu_has_plladiv2()	(cpu_is_at91sam9g45() \
 				|| cpu_is_at91sam9x5() \
-				|| cpu_is_at91sam9n12())
+				|| cpu_is_at91sam9n12() \
+				|| cpu_is_sama5d3())
 
 #define cpu_has_mdiv3()		(cpu_is_at91sam9g45() \
 				|| cpu_is_at91sam9x5() \
-				|| cpu_is_at91sam9n12())
+				|| cpu_is_at91sam9n12() \
+				|| cpu_is_sama5d3())
 
 #define cpu_has_alt_prescaler()	(cpu_is_at91sam9x5() \
-				|| cpu_is_at91sam9n12())
+				|| cpu_is_at91sam9n12() \
+				|| cpu_is_sama5d3())
 
 static LIST_HEAD(clocks);
 static DEFINE_SPINLOCK(clk_lock);
@@ -210,10 +218,26 @@ struct clk mck = {
 
 static void pmc_periph_mode(struct clk *clk, int is_on)
 {
-	if (is_on)
-		at91_pmc_write(AT91_PMC_PCER, clk->pmc_mask);
-	else
-		at91_pmc_write(AT91_PMC_PCDR, clk->pmc_mask);
+	u32 regval = 0;
+
+	/*
+	 * With sama5d3 devices, we are managing clock division so we have to
+	 * use the Peripheral Control Register introduced from at91sam9x5
+	 * devices.
+	 */
+	if (cpu_is_sama5d3()) {
+		regval |= AT91_PMC_PCR_CMD; /* write command */
+		regval |= clk->pid & AT91_PMC_PCR_PID; /* peripheral selection */
+		regval |= AT91_PMC_PCR_DIV(clk->div);
+		if (is_on)
+			regval |= AT91_PMC_PCR_EN; /* enable clock */
+		at91_pmc_write(AT91_PMC_PCR, regval);
+	} else {
+		if (is_on)
+			at91_pmc_write(AT91_PMC_PCER, clk->pmc_mask);
+		else
+			at91_pmc_write(AT91_PMC_PCDR, clk->pmc_mask);
+	}
 }
 
 static struct clk __init *at91_css_to_clk(unsigned long css)
@@ -443,14 +467,18 @@ static void __init init_programmable_clock(struct clk *clk)
 
 static int at91_clk_show(struct seq_file *s, void *unused)
 {
-	u32		scsr, pcsr, uckr = 0, sr;
+	u32		scsr, pcsr, pcsr1 = 0, uckr = 0, sr;
 	struct clk	*clk;
 
 	scsr = at91_pmc_read(AT91_PMC_SCSR);
 	pcsr = at91_pmc_read(AT91_PMC_PCSR);
+	if (cpu_is_sama5d3())
+		pcsr1 = at91_pmc_read(AT91_PMC_PCSR1);
 	sr = at91_pmc_read(AT91_PMC_SR);
 	seq_printf(s, "SCSR = %8x\n", scsr);
 	seq_printf(s, "PCSR = %8x\n", pcsr);
+	if (cpu_is_sama5d3())
+		seq_printf(s, "PCSR1 = %8x\n", pcsr1);
 	seq_printf(s, "MOR  = %8x\n", at91_pmc_read(AT91_CKGR_MOR));
 	seq_printf(s, "MCFR = %8x\n", at91_pmc_read(AT91_CKGR_MCFR));
 	seq_printf(s, "PLLA = %8x\n", at91_pmc_read(AT91_CKGR_PLLAR));
@@ -470,20 +498,30 @@ static int at91_clk_show(struct seq_file *s, void *unused)
 	list_for_each_entry(clk, &clocks, node) {
 		char	*state;
 
-		if (clk->mode == pmc_sys_mode)
+		if (clk->mode == pmc_sys_mode) {
 			state = (scsr & clk->pmc_mask) ? "on" : "off";
-		else if (clk->mode == pmc_periph_mode)
-			state = (pcsr & clk->pmc_mask) ? "on" : "off";
-		else if (clk->mode == pmc_uckr_mode)
+		} else if (clk->mode == pmc_periph_mode) {
+			if (cpu_is_sama5d3()) {
+				u32 pmc_mask = 1 << (clk->pid % 32);
+
+				if (clk->pid > 31)
+					state = (pcsr1 & pmc_mask) ? "on" : "off";
+				else
+					state = (pcsr & pmc_mask) ? "on" : "off";
+			} else {
+				state = (pcsr & clk->pmc_mask) ? "on" : "off";
+			}
+		} else if (clk->mode == pmc_uckr_mode) {
 			state = (uckr & clk->pmc_mask) ? "on" : "off";
-		else if (clk->pmc_mask)
+		} else if (clk->pmc_mask) {
 			state = (sr & clk->pmc_mask) ? "on" : "off";
-		else if (clk == &clk32k || clk == &main_clk)
+		} else if (clk == &clk32k || clk == &main_clk) {
 			state = "on";
-		else
+		} else {
 			state = "";
+		}
 
-		seq_printf(s, "%-10s users=%2d %-3s %9ld Hz %s\n",
+		seq_printf(s, "%-10s users=%2d %-3s %9lu Hz %s\n",
 			clk->name, clk->users, state, clk_get_rate(clk),
 			clk->parent ? clk->parent->name : "");
 	}
@@ -530,6 +568,9 @@ int __init clk_register(struct clk *clk)
 	if (clk_is_peripheral(clk)) {
 		if (!clk->parent)
 			clk->parent = &mck;
+		if (cpu_is_sama5d3())
+			clk->rate_hz = DIV_ROUND_UP(clk->parent->rate_hz,
+						    1 << clk->div);
 		clk->mode = pmc_periph_mode;
 	}
 	else if (clk_is_sys(clk)) {
@@ -555,7 +596,11 @@ static u32 __init at91_pll_rate(struct clk *pll, u32 freq, u32 reg)
 	unsigned mul, div;
 
 	div = reg & 0xff;
-	mul = (reg >> 16) & 0x7ff;
+	if (cpu_is_sama5d3())
+		mul = AT91_PMC3_MUL_GET(reg);
+	else
+		mul = AT91_PMC_MUL_GET(reg);
+
 	if (div && mul) {
 		freq /= div;
 		freq *= mul + 1;
@@ -706,12 +751,15 @@ static int __init at91_pmc_init(unsigned long main_clock)
 
 	/* report if PLLA is more than mildly overclocked */
 	plla.rate_hz = at91_pll_rate(&plla, main_clock, at91_pmc_read(AT91_CKGR_PLLAR));
-	if (cpu_has_300M_plla()) {
-		if (plla.rate_hz > 300000000)
+	if (cpu_has_1056M_plla()) {
+		if (plla.rate_hz > 1056000000)
 			pll_overclock = true;
 	} else if (cpu_has_800M_plla()) {
 		if (plla.rate_hz > 800000000)
 			pll_overclock = true;
+	} else if (cpu_has_300M_plla()) {
+		if (plla.rate_hz > 300000000)
+			pll_overclock = true;
 	} else if (cpu_has_240M_plla()) {
 		if (plla.rate_hz > 240000000)
 			pll_overclock = true;
@@ -872,6 +920,7 @@ int __init at91_clock_init(unsigned long main_clock)
 static int __init at91_clock_reset(void)
 {
 	unsigned long pcdr = 0;
+	unsigned long pcdr1 = 0;
 	unsigned long scdr = 0;
 	struct clk *clk;
 
@@ -879,8 +928,17 @@ static int __init at91_clock_reset(void)
 		if (clk->users > 0)
 			continue;
 
-		if (clk->mode == pmc_periph_mode)
-			pcdr |= clk->pmc_mask;
+		if (clk->mode == pmc_periph_mode) {
+			if (cpu_is_sama5d3()) {
+				u32 pmc_mask = 1 << (clk->pid % 32);
+
+				if (clk->pid > 31)
+					pcdr1 |= pmc_mask;
+				else
+					pcdr |= pmc_mask;
+			} else
+				pcdr |= clk->pmc_mask;
+		}
 
 		if (clk->mode == pmc_sys_mode)
 			scdr |= clk->pmc_mask;
@@ -888,8 +946,9 @@ static int __init at91_clock_reset(void)
 		pr_debug("Clocks: disable unused %s\n", clk->name);
 	}
 
-	at91_pmc_write(AT91_PMC_PCDR, pcdr);
 	at91_pmc_write(AT91_PMC_SCDR, scdr);
+	if (cpu_is_sama5d3())
+		at91_pmc_write(AT91_PMC_PCDR1, pcdr1);
 
 	return 0;
 }
diff --git a/arch/arm/mach-at91/clock.h b/arch/arm/mach-at91/clock.h
index c2e63e4..a98a39b 100644
--- a/arch/arm/mach-at91/clock.h
+++ b/arch/arm/mach-at91/clock.h
@@ -20,7 +20,9 @@ struct clk {
 	const char	*name;		/* unique clock name */
 	struct clk_lookup cl;
 	unsigned long	rate_hz;
+	unsigned	div;		/* parent clock divider */
 	struct clk	*parent;
+	unsigned	pid;		/* peripheral ID */
 	u32		pmc_mask;
 	void		(*mode)(struct clk *, int);
 	unsigned	id:3;		/* PCK0..4, or 32k/main/a/b */
diff --git a/arch/arm/mach-at91/gpio.c b/arch/arm/mach-at91/gpio.c
index c5d7e1e..a5afcf7 100644
--- a/arch/arm/mach-at91/gpio.c
+++ b/arch/arm/mach-at91/gpio.c
@@ -22,10 +22,9 @@
 #include <linux/module.h>
 #include <linux/io.h>
 #include <linux/irqdomain.h>
+#include <linux/irqchip/chained_irq.h>
 #include <linux/of_address.h>
 
-#include <asm/mach/irq.h>
-
 #include <mach/hardware.h>
 #include <mach/at91_pio.h>
 
diff --git a/arch/arm/mach-at91/include/mach/at91_pmc.h b/arch/arm/mach-at91/include/mach/at91_pmc.h
index ea2c57a..31df120 100644
--- a/arch/arm/mach-at91/include/mach/at91_pmc.h
+++ b/arch/arm/mach-at91/include/mach/at91_pmc.h
@@ -75,6 +75,9 @@ extern void __iomem *at91_pmc_base;
 #define		AT91_PMC_PLLCOUNT	(0x3f  <<  8)		/* PLL Counter */
 #define		AT91_PMC_OUT		(3     << 14)		/* PLL Clock Frequency Range */
 #define		AT91_PMC_MUL		(0x7ff << 16)		/* PLL Multiplier */
+#define		AT91_PMC_MUL_GET(n)	((n) >> 16 & 0x7ff)
+#define		AT91_PMC3_MUL		(0x7f  << 18)		/* PLL Multiplier [SAMA5 only] */
+#define		AT91_PMC3_MUL_GET(n)	((n) >> 18 & 0x7f)
 #define		AT91_PMC_USBDIV		(3     << 28)		/* USB Divisor (PLLB only) */
 #define			AT91_PMC_USBDIV_1		(0 << 28)
 #define			AT91_PMC_USBDIV_2		(1 << 28)
@@ -167,11 +170,18 @@ extern void __iomem *at91_pmc_base;
 #define		AT91_PMC_WPVS		(0x1  <<  0)		/* Write Protect Violation Status */
 #define		AT91_PMC_WPVSRC		(0xffff  <<  8)		/* Write Protect Violation Source */
 
-#define AT91_PMC_PCR		0x10c			/* Peripheral Control Register [some SAM9] */
+#define AT91_PMC_PCER1		0x100			/* Peripheral Clock Enable Register 1 [SAMA5 only]*/
+#define AT91_PMC_PCDR1		0x104			/* Peripheral Clock Enable Register 1 */
+#define AT91_PMC_PCSR1		0x108			/* Peripheral Clock Enable Register 1 */
+
+#define AT91_PMC_PCR		0x10c			/* Peripheral Control Register [some SAM9 and SAMA5] */
 #define		AT91_PMC_PCR_PID	(0x3f  <<  0)		/* Peripheral ID */
-#define		AT91_PMC_PCR_CMD	(0x1  <<  12)		/* Command */
-#define		AT91_PMC_PCR_DIV	(0x3  <<  16)		/* Divisor Value */
-#define		AT91_PMC_PCRDIV(n)	(((n) <<  16) & AT91_PMC_PCR_DIV)
+#define		AT91_PMC_PCR_CMD	(0x1  <<  12)		/* Command (read=0, write=1) */
+#define		AT91_PMC_PCR_DIV(n)	((n)  <<  16)		/* Divisor Value */
+#define			AT91_PMC_PCR_DIV0	0x0			/* Peripheral clock is MCK */
+#define			AT91_PMC_PCR_DIV2	0x2			/* Peripheral clock is MCK/2 */
+#define			AT91_PMC_PCR_DIV4	0x4			/* Peripheral clock is MCK/4 */
+#define			AT91_PMC_PCR_DIV8	0x8			/* Peripheral clock is MCK/8 */
 #define		AT91_PMC_PCR_EN		(0x1  <<  28)		/* Enable */
 
 #endif
diff --git a/arch/arm/mach-at91/include/mach/cpu.h b/arch/arm/mach-at91/include/mach/cpu.h
index b6504c1..0f3379f 100644
--- a/arch/arm/mach-at91/include/mach/cpu.h
+++ b/arch/arm/mach-at91/include/mach/cpu.h
@@ -36,6 +36,8 @@
 #define ARCH_ID_AT91M40807	0x14080745
 #define ARCH_ID_AT91R40008	0x44000840
 
+#define ARCH_ID_SAMA5D3		0x8A5C07C0
+
 #define ARCH_EXID_AT91SAM9M11	0x00000001
 #define ARCH_EXID_AT91SAM9M10	0x00000002
 #define ARCH_EXID_AT91SAM9G46	0x00000003
@@ -47,6 +49,11 @@
 #define ARCH_EXID_AT91SAM9G25	0x00000003
 #define ARCH_EXID_AT91SAM9X25	0x00000004
 
+#define ARCH_EXID_SAMA5D31	0x00444300
+#define ARCH_EXID_SAMA5D33	0x00414300
+#define ARCH_EXID_SAMA5D34	0x00414301
+#define ARCH_EXID_SAMA5D35	0x00584300
+
 #define ARCH_FAMILY_AT91X92	0x09200000
 #define ARCH_FAMILY_AT91SAM9	0x01900000
 #define ARCH_FAMILY_AT91SAM9XE	0x02900000
@@ -75,6 +82,9 @@ enum at91_soc_type {
 	/* SAM9N12 */
 	AT91_SOC_SAM9N12,
 
+	/* SAMA5D3 */
+	AT91_SOC_SAMA5D3,
+
 	/* Unknown type */
 	AT91_SOC_NONE
 };
@@ -93,6 +103,10 @@ enum at91_soc_subtype {
 	AT91_SOC_SAM9G15, AT91_SOC_SAM9G35, AT91_SOC_SAM9X35,
 	AT91_SOC_SAM9G25, AT91_SOC_SAM9X25,
 
+	/* SAMA5D3 */
+	AT91_SOC_SAMA5D31, AT91_SOC_SAMA5D33, AT91_SOC_SAMA5D34,
+	AT91_SOC_SAMA5D35,
+
 	/* Unknown subtype */
 	AT91_SOC_SUBTYPE_NONE
 };
@@ -187,6 +201,12 @@ static inline int at91_soc_is_detected(void)
 #define cpu_is_at91sam9n12()	(0)
 #endif
 
+#ifdef CONFIG_SOC_SAMA5D3
+#define cpu_is_sama5d3()	(at91_soc_initdata.type == AT91_SOC_SAMA5D3)
+#else
+#define cpu_is_sama5d3()	(0)
+#endif
+
 /*
  * Since this is ARM, we will never run on any AVR32 CPU. But these
  * definitions may reduce clutter in common drivers.
diff --git a/arch/arm/mach-at91/include/mach/sama5d3.h b/arch/arm/mach-at91/include/mach/sama5d3.h
new file mode 100644
index 0000000..6dc81ee
--- /dev/null
+++ b/arch/arm/mach-at91/include/mach/sama5d3.h
@@ -0,0 +1,73 @@
+/*
+ * Chip-specific header file for the SAMA5D3 family
+ *
+ *  Copyright (C) 2013 Atmel,
+ *                2013 Ludovic Desroches <ludovic.desroches@atmel.com>
+ *
+ * Common definitions.
+ * Based on SAMA5D3 datasheet.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#ifndef SAMA5D3_H
+#define SAMA5D3_H
+
+/*
+ * Peripheral identifiers/interrupts.
+ */
+#define AT91_ID_FIQ		 0	/* Advanced Interrupt Controller (FIQ) */
+#define AT91_ID_SYS		 1	/* System Peripherals */
+#define SAMA5D3_ID_DBGU		 2	/* debug Unit (usually no special interrupt line) */
+#define AT91_ID_PIT		 3	/* PIT */
+#define SAMA5D3_ID_WDT		 4	/* Watchdog Timer Interrupt */
+#define SAMA5D3_ID_HSMC		 5	/* Static Memory Controller */
+#define SAMA5D3_ID_PIOA		 6	/* PIOA */
+#define SAMA5D3_ID_PIOB		 7	/* PIOB */
+#define SAMA5D3_ID_PIOC		 8	/* PIOC */
+#define SAMA5D3_ID_PIOD		 9	/* PIOD */
+#define SAMA5D3_ID_PIOE		10	/* PIOE */
+#define SAMA5D3_ID_SMD		11	/* SMD Soft Modem */
+#define SAMA5D3_ID_USART0	12	/* USART0 */
+#define SAMA5D3_ID_USART1	13	/* USART1 */
+#define SAMA5D3_ID_USART2	14	/* USART2 */
+#define SAMA5D3_ID_USART3	15	/* USART3 */
+#define SAMA5D3_ID_UART0	16	/* UART 0 */
+#define SAMA5D3_ID_UART1	17	/* UART 1 */
+#define SAMA5D3_ID_TWI0		18	/* Two-Wire Interface 0 */
+#define SAMA5D3_ID_TWI1		19	/* Two-Wire Interface 1 */
+#define SAMA5D3_ID_TWI2		20	/* Two-Wire Interface 2 */
+#define SAMA5D3_ID_HSMCI0	21	/* MCI */
+#define SAMA5D3_ID_HSMCI1	22	/* MCI */
+#define SAMA5D3_ID_HSMCI2	23	/* MCI */
+#define SAMA5D3_ID_SPI0		24	/* Serial Peripheral Interface 0 */
+#define SAMA5D3_ID_SPI1		25	/* Serial Peripheral Interface 1 */
+#define SAMA5D3_ID_TC0		26	/* Timer Counter 0 */
+#define SAMA5D3_ID_TC1		27	/* Timer Counter 2 */
+#define SAMA5D3_ID_PWM		28	/* Pulse Width Modulation Controller */
+#define SAMA5D3_ID_ADC		29	/* Touch Screen ADC Controller */
+#define SAMA5D3_ID_DMA0		30	/* DMA Controller 0 */
+#define SAMA5D3_ID_DMA1		31	/* DMA Controller 1 */
+#define SAMA5D3_ID_UHPHS	32	/* USB Host High Speed */
+#define SAMA5D3_ID_UDPHS	33	/* USB Device High Speed */
+#define SAMA5D3_ID_GMAC		34	/* Gigabit Ethernet MAC */
+#define SAMA5D3_ID_EMAC		35	/* Ethernet MAC */
+#define SAMA5D3_ID_LCDC		36	/* LCD Controller */
+#define SAMA5D3_ID_ISI		37	/* Image Sensor Interface */
+#define SAMA5D3_ID_SSC0		38	/* Synchronous Serial Controller 0 */
+#define SAMA5D3_ID_SSC1		39	/* Synchronous Serial Controller 1 */
+#define SAMA5D3_ID_CAN0		40	/* CAN Controller 0 */
+#define SAMA5D3_ID_CAN1		41	/* CAN Controller 1 */
+#define SAMA5D3_ID_SHA		42	/* Secure Hash Algorithm */
+#define SAMA5D3_ID_AES		43	/* Advanced Encryption Standard */
+#define SAMA5D3_ID_TDES		44	/* Triple Data Encryption Standard */
+#define SAMA5D3_ID_TRNG		45	/* True Random Generator Number */
+#define SAMA5D3_ID_IRQ0		47	/* Advanced Interrupt Controller (IRQ0) */
+
+/*
+ * Internal Memory
+ */
+#define SAMA5D3_SRAM_BASE	0x00300000	/* Internal SRAM base address */
+#define SAMA5D3_SRAM_SIZE	(128 * SZ_1K)	/* Internal SRAM size (128Kb) */
+
+#endif
diff --git a/arch/arm/mach-at91/sama5d3.c b/arch/arm/mach-at91/sama5d3.c
new file mode 100644
index 0000000..4012797
--- /dev/null
+++ b/arch/arm/mach-at91/sama5d3.c
@@ -0,0 +1,377 @@
+/*
+ *  Chip-specific setup code for the SAMA5D3 family
+ *
+ *  Copyright (C) 2013 Atmel,
+ *                2013 Ludovic Desroches <ludovic.desroches@atmel.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/module.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/irq.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <mach/sama5d3.h>
+#include <mach/at91_pmc.h>
+#include <mach/cpu.h>
+
+#include "soc.h"
+#include "generic.h"
+#include "clock.h"
+#include "sam9_smc.h"
+
+/* --------------------------------------------------------------------
+ *  Clocks
+ * -------------------------------------------------------------------- */
+
+/*
+ * The peripheral clocks.
+ */
+
+static struct clk pioA_clk = {
+	.name		= "pioA_clk",
+	.pid		= SAMA5D3_ID_PIOA,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk pioB_clk = {
+	.name		= "pioB_clk",
+	.pid		= SAMA5D3_ID_PIOB,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk pioC_clk = {
+	.name		= "pioC_clk",
+	.pid		= SAMA5D3_ID_PIOC,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk pioD_clk = {
+	.name		= "pioD_clk",
+	.pid		= SAMA5D3_ID_PIOD,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk pioE_clk = {
+	.name		= "pioE_clk",
+	.pid		= SAMA5D3_ID_PIOE,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart0_clk = {
+	.name		= "usart0_clk",
+	.pid		= SAMA5D3_ID_USART0,
+	.type		= CLK_TYPE_PERIPHERAL,
+	.div		= AT91_PMC_PCR_DIV2,
+};
+static struct clk usart1_clk = {
+	.name		= "usart1_clk",
+	.pid		= SAMA5D3_ID_USART1,
+	.type		= CLK_TYPE_PERIPHERAL,
+	.div		= AT91_PMC_PCR_DIV2,
+};
+static struct clk usart2_clk = {
+	.name		= "usart2_clk",
+	.pid		= SAMA5D3_ID_USART2,
+	.type		= CLK_TYPE_PERIPHERAL,
+	.div		= AT91_PMC_PCR_DIV2,
+};
+static struct clk usart3_clk = {
+	.name		= "usart3_clk",
+	.pid		= SAMA5D3_ID_USART3,
+	.type		= CLK_TYPE_PERIPHERAL,
+	.div		= AT91_PMC_PCR_DIV2,
+};
+static struct clk uart0_clk = {
+	.name		= "uart0_clk",
+	.pid		= SAMA5D3_ID_UART0,
+	.type		= CLK_TYPE_PERIPHERAL,
+	.div		= AT91_PMC_PCR_DIV2,
+};
+static struct clk uart1_clk = {
+	.name		= "uart1_clk",
+	.pid		= SAMA5D3_ID_UART1,
+	.type		= CLK_TYPE_PERIPHERAL,
+	.div		= AT91_PMC_PCR_DIV2,
+};
+static struct clk twi0_clk = {
+	.name		= "twi0_clk",
+	.pid		= SAMA5D3_ID_TWI0,
+	.type		= CLK_TYPE_PERIPHERAL,
+	.div		= AT91_PMC_PCR_DIV2,
+};
+static struct clk twi1_clk = {
+	.name		= "twi1_clk",
+	.pid		= SAMA5D3_ID_TWI1,
+	.type		= CLK_TYPE_PERIPHERAL,
+	.div		= AT91_PMC_PCR_DIV2,
+};
+static struct clk twi2_clk = {
+	.name		= "twi2_clk",
+	.pid		= SAMA5D3_ID_TWI2,
+	.type		= CLK_TYPE_PERIPHERAL,
+	.div		= AT91_PMC_PCR_DIV2,
+};
+static struct clk mmc0_clk = {
+	.name		= "mci0_clk",
+	.pid		= SAMA5D3_ID_HSMCI0,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk mmc1_clk = {
+	.name		= "mci1_clk",
+	.pid		= SAMA5D3_ID_HSMCI1,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk mmc2_clk = {
+	.name		= "mci2_clk",
+	.pid		= SAMA5D3_ID_HSMCI2,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk spi0_clk = {
+	.name		= "spi0_clk",
+	.pid		= SAMA5D3_ID_SPI0,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk spi1_clk = {
+	.name		= "spi1_clk",
+	.pid		= SAMA5D3_ID_SPI1,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk tcb0_clk = {
+	.name		= "tcb0_clk",
+	.pid		= SAMA5D3_ID_TC0,
+	.type		= CLK_TYPE_PERIPHERAL,
+	.div		= AT91_PMC_PCR_DIV2,
+};
+static struct clk tcb1_clk = {
+	.name		= "tcb1_clk",
+	.pid		= SAMA5D3_ID_TC1,
+	.type		= CLK_TYPE_PERIPHERAL,
+	.div		= AT91_PMC_PCR_DIV2,
+};
+static struct clk adc_clk = {
+	.name		= "adc_clk",
+	.pid		= SAMA5D3_ID_ADC,
+	.type		= CLK_TYPE_PERIPHERAL,
+	.div		= AT91_PMC_PCR_DIV2,
+};
+static struct clk adc_op_clk = {
+	.name		= "adc_op_clk",
+	.type		= CLK_TYPE_PERIPHERAL,
+	.rate_hz	= 5000000,
+};
+static struct clk dma0_clk = {
+	.name		= "dma0_clk",
+	.pid		= SAMA5D3_ID_DMA0,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk dma1_clk = {
+	.name		= "dma1_clk",
+	.pid		= SAMA5D3_ID_DMA1,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk uhphs_clk = {
+	.name		= "uhphs",
+	.pid		= SAMA5D3_ID_UHPHS,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk udphs_clk = {
+	.name		= "udphs_clk",
+	.pid		= SAMA5D3_ID_UDPHS,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+/* gmac only for sama5d33, sama5d34, sama5d35 */
+static struct clk macb0_clk = {
+	.name		= "macb0_clk",
+	.pid		= SAMA5D3_ID_GMAC,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+/* emac only for sama5d31, sama5d35 */
+static struct clk macb1_clk = {
+	.name		= "macb1_clk",
+	.pid		= SAMA5D3_ID_EMAC,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+/* lcd only for sama5d31, sama5d33, sama5d34 */
+static struct clk lcdc_clk = {
+	.name		= "lcdc_clk",
+	.pid		= SAMA5D3_ID_LCDC,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+/* isi only for sama5d33, sama5d35 */
+static struct clk isi_clk = {
+	.name		= "isi_clk",
+	.pid		= SAMA5D3_ID_ISI,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk can0_clk = {
+	.name		= "can0_clk",
+	.pid		= SAMA5D3_ID_CAN0,
+	.type		= CLK_TYPE_PERIPHERAL,
+	.div		= AT91_PMC_PCR_DIV2,
+};
+static struct clk can1_clk = {
+	.name		= "can1_clk",
+	.pid		= SAMA5D3_ID_CAN1,
+	.type		= CLK_TYPE_PERIPHERAL,
+	.div		= AT91_PMC_PCR_DIV2,
+};
+static struct clk ssc0_clk = {
+	.name		= "ssc0_clk",
+	.pid		= SAMA5D3_ID_SSC0,
+	.type		= CLK_TYPE_PERIPHERAL,
+	.div		= AT91_PMC_PCR_DIV2,
+};
+static struct clk ssc1_clk = {
+	.name		= "ssc1_clk",
+	.pid		= SAMA5D3_ID_SSC1,
+	.type		= CLK_TYPE_PERIPHERAL,
+	.div		= AT91_PMC_PCR_DIV2,
+};
+static struct clk sha_clk = {
+	.name		= "sha_clk",
+	.pid		= SAMA5D3_ID_SHA,
+	.type		= CLK_TYPE_PERIPHERAL,
+	.div		= AT91_PMC_PCR_DIV8,
+};
+static struct clk aes_clk = {
+	.name		= "aes_clk",
+	.pid		= SAMA5D3_ID_AES,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk tdes_clk = {
+	.name		= "tdes_clk",
+	.pid		= SAMA5D3_ID_TDES,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+
+static struct clk *periph_clocks[] __initdata = {
+	&pioA_clk,
+	&pioB_clk,
+	&pioC_clk,
+	&pioD_clk,
+	&pioE_clk,
+	&usart0_clk,
+	&usart1_clk,
+	&usart2_clk,
+	&usart3_clk,
+	&uart0_clk,
+	&uart1_clk,
+	&twi0_clk,
+	&twi1_clk,
+	&twi2_clk,
+	&mmc0_clk,
+	&mmc1_clk,
+	&mmc2_clk,
+	&spi0_clk,
+	&spi1_clk,
+	&tcb0_clk,
+	&tcb1_clk,
+	&adc_clk,
+	&adc_op_clk,
+	&dma0_clk,
+	&dma1_clk,
+	&uhphs_clk,
+	&udphs_clk,
+	&macb0_clk,
+	&macb1_clk,
+	&lcdc_clk,
+	&isi_clk,
+	&can0_clk,
+	&can1_clk,
+	&ssc0_clk,
+	&ssc1_clk,
+	&sha_clk,
+	&aes_clk,
+	&tdes_clk,
+};
+
+static struct clk pck0 = {
+	.name		= "pck0",
+	.pmc_mask	= AT91_PMC_PCK0,
+	.type		= CLK_TYPE_PROGRAMMABLE,
+	.id		= 0,
+};
+
+static struct clk pck1 = {
+	.name		= "pck1",
+	.pmc_mask	= AT91_PMC_PCK1,
+	.type		= CLK_TYPE_PROGRAMMABLE,
+	.id		= 1,
+};
+
+static struct clk pck2 = {
+	.name		= "pck2",
+	.pmc_mask	= AT91_PMC_PCK2,
+	.type		= CLK_TYPE_PROGRAMMABLE,
+	.id		= 2,
+};
+
+static struct clk_lookup periph_clocks_lookups[] = {
+	/* lookup table for DT entries */
+	CLKDEV_CON_DEV_ID("usart", "ffffee00.serial", &mck),
+	CLKDEV_CON_DEV_ID(NULL, "fffff200.gpio", &pioA_clk),
+	CLKDEV_CON_DEV_ID(NULL, "fffff400.gpio", &pioB_clk),
+	CLKDEV_CON_DEV_ID(NULL, "fffff600.gpio", &pioC_clk),
+	CLKDEV_CON_DEV_ID(NULL, "fffff800.gpio", &pioD_clk),
+	CLKDEV_CON_DEV_ID(NULL, "fffffa00.gpio", &pioE_clk),
+	CLKDEV_CON_DEV_ID("usart", "f001c000.serial", &usart0_clk),
+	CLKDEV_CON_DEV_ID("usart", "f0020000.serial", &usart1_clk),
+	CLKDEV_CON_DEV_ID("usart", "f8020000.serial", &usart2_clk),
+	CLKDEV_CON_DEV_ID("usart", "f8024000.serial", &usart3_clk),
+	CLKDEV_CON_DEV_ID(NULL, "f0014000.i2c", &twi0_clk),
+	CLKDEV_CON_DEV_ID(NULL, "f0018000.i2c", &twi1_clk),
+	CLKDEV_CON_DEV_ID(NULL, "f801c000.i2c", &twi2_clk),
+	CLKDEV_CON_DEV_ID("mci_clk", "f0000000.mmc", &mmc0_clk),
+	CLKDEV_CON_DEV_ID("mci_clk", "f8000000.mmc", &mmc1_clk),
+	CLKDEV_CON_DEV_ID("mci_clk", "f8004000.mmc", &mmc2_clk),
+	CLKDEV_CON_DEV_ID("spi_clk", "f0004000.spi", &spi0_clk),
+	CLKDEV_CON_DEV_ID("spi_clk", "f8008000.spi", &spi1_clk),
+	CLKDEV_CON_DEV_ID("t0_clk", "f0010000.timer", &tcb0_clk),
+	CLKDEV_CON_DEV_ID("t0_clk", "f8014000.timer", &tcb1_clk),
+	CLKDEV_CON_DEV_ID("tsc_clk", "f8018000.tsadcc", &adc_clk),
+	CLKDEV_CON_DEV_ID("dma_clk", "ffffe600.dma-controller", &dma0_clk),
+	CLKDEV_CON_DEV_ID("dma_clk", "ffffe800.dma-controller", &dma1_clk),
+	CLKDEV_CON_DEV_ID("hclk", "600000.ohci", &uhphs_clk),
+	CLKDEV_CON_DEV_ID("ohci_clk", "600000.ohci", &uhphs_clk),
+	CLKDEV_CON_DEV_ID("ehci_clk", "700000.ehci", &uhphs_clk),
+	CLKDEV_CON_DEV_ID("pclk", "500000.gadget", &udphs_clk),
+	CLKDEV_CON_DEV_ID("hclk", "500000.gadget", &utmi_clk),
+	CLKDEV_CON_DEV_ID("hclk", "f0028000.ethernet", &macb0_clk),
+	CLKDEV_CON_DEV_ID("pclk", "f0028000.ethernet", &macb0_clk),
+	CLKDEV_CON_DEV_ID("hclk", "f802c000.ethernet", &macb1_clk),
+	CLKDEV_CON_DEV_ID("pclk", "f802c000.ethernet", &macb1_clk),
+	CLKDEV_CON_DEV_ID("pclk", "f0008000.ssc", &ssc0_clk),
+	CLKDEV_CON_DEV_ID("pclk", "f000c000.ssc", &ssc1_clk),
+	CLKDEV_CON_DEV_ID("can_clk", "f000c000.can", &can0_clk),
+	CLKDEV_CON_DEV_ID("can_clk", "f8010000.can", &can1_clk),
+	CLKDEV_CON_DEV_ID("sha_clk", "f8034000.sha", &sha_clk),
+	CLKDEV_CON_DEV_ID("aes_clk", "f8038000.aes", &aes_clk),
+	CLKDEV_CON_DEV_ID("tdes_clk", "f803c000.tdes", &tdes_clk),
+};
+
+static void __init sama5d3_register_clocks(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(periph_clocks); i++)
+		clk_register(periph_clocks[i]);
+
+	clkdev_add_table(periph_clocks_lookups,
+			 ARRAY_SIZE(periph_clocks_lookups));
+
+	clk_register(&pck0);
+	clk_register(&pck1);
+	clk_register(&pck2);
+}
+
+/* --------------------------------------------------------------------
+ *  AT91SAM9x5 processor initialization
+ * -------------------------------------------------------------------- */
+
+static void __init sama5d3_map_io(void)
+{
+	at91_init_sram(0, SAMA5D3_SRAM_BASE, SAMA5D3_SRAM_SIZE);
+}
+
+AT91_SOC_START(sama5d3)
+	.map_io = sama5d3_map_io,
+	.register_clocks = sama5d3_register_clocks,
+AT91_SOC_END
diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c
index 4b67847..c62c57e 100644
--- a/arch/arm/mach-at91/setup.c
+++ b/arch/arm/mach-at91/setup.c
@@ -151,6 +151,11 @@ static void __init soc_detect(u32 dbgu_base)
 		at91_soc_initdata.type = AT91_SOC_SAM9N12;
 		at91_boot_soc = at91sam9n12_soc;
 		break;
+
+	case ARCH_ID_SAMA5D3:
+		at91_soc_initdata.type = AT91_SOC_SAMA5D3;
+		at91_boot_soc = sama5d3_soc;
+		break;
 	}
 
 	/* at91sam9g10 */
@@ -206,6 +211,23 @@ static void __init soc_detect(u32 dbgu_base)
 			break;
 		}
 	}
+
+	if (at91_soc_initdata.type == AT91_SOC_SAMA5D3) {
+		switch (at91_soc_initdata.exid) {
+		case ARCH_EXID_SAMA5D31:
+			at91_soc_initdata.subtype = AT91_SOC_SAMA5D31;
+			break;
+		case ARCH_EXID_SAMA5D33:
+			at91_soc_initdata.subtype = AT91_SOC_SAMA5D33;
+			break;
+		case ARCH_EXID_SAMA5D34:
+			at91_soc_initdata.subtype = AT91_SOC_SAMA5D34;
+			break;
+		case ARCH_EXID_SAMA5D35:
+			at91_soc_initdata.subtype = AT91_SOC_SAMA5D35;
+			break;
+		}
+	}
 }
 
 static const char *soc_name[] = {
@@ -219,6 +241,7 @@ static const char *soc_name[] = {
 	[AT91_SOC_SAM9RL]	= "at91sam9rl",
 	[AT91_SOC_SAM9X5]	= "at91sam9x5",
 	[AT91_SOC_SAM9N12]	= "at91sam9n12",
+	[AT91_SOC_SAMA5D3]	= "sama5d3",
 	[AT91_SOC_NONE]		= "Unknown"
 };
 
@@ -241,6 +264,10 @@ static const char *soc_subtype_name[] = {
 	[AT91_SOC_SAM9X35]	= "at91sam9x35",
 	[AT91_SOC_SAM9G25]	= "at91sam9g25",
 	[AT91_SOC_SAM9X25]	= "at91sam9x25",
+	[AT91_SOC_SAMA5D31]	= "sama5d31",
+	[AT91_SOC_SAMA5D33]	= "sama5d33",
+	[AT91_SOC_SAMA5D34]	= "sama5d34",
+	[AT91_SOC_SAMA5D35]	= "sama5d35",
 	[AT91_SOC_SUBTYPE_NONE]	= "Unknown"
 };
 
@@ -333,7 +360,7 @@ static void at91_dt_rstc(void)
 
 	of_id = of_match_node(rstc_ids, np);
 	if (!of_id)
-		panic("AT91: rtsc no restart function availlable\n");
+		panic("AT91: rtsc no restart function available\n");
 
 	arm_pm_restart = of_id->data;
 
diff --git a/arch/arm/mach-at91/soc.h b/arch/arm/mach-at91/soc.h
index 9c6d3d4..43a225f 100644
--- a/arch/arm/mach-at91/soc.h
+++ b/arch/arm/mach-at91/soc.h
@@ -22,9 +22,10 @@ extern struct at91_init_soc at91sam9g45_soc;
 extern struct at91_init_soc at91sam9rl_soc;
 extern struct at91_init_soc at91sam9x5_soc;
 extern struct at91_init_soc at91sam9n12_soc;
+extern struct at91_init_soc sama5d3_soc;
 
 #define AT91_SOC_START(_name)				\
-struct at91_init_soc __initdata at91##_name##_soc	\
+struct at91_init_soc __initdata _name##_soc		\
  __used							\
 						= {	\
 	.builtin	= 1,				\
@@ -68,3 +69,7 @@ static inline int at91_soc_is_enabled(void)
 #if !defined(CONFIG_SOC_AT91SAM9N12)
 #define at91sam9n12_soc	at91_boot_soc
 #endif
+
+#if !defined(CONFIG_SOC_SAMA5D3)
+#define sama5d3_soc	at91_boot_soc
+#endif
diff --git a/arch/arm/mach-bcm2835/Kconfig b/arch/arm/mach-bcm2835/Kconfig
new file mode 100644
index 0000000..560045c
--- /dev/null
+++ b/arch/arm/mach-bcm2835/Kconfig
@@ -0,0 +1,15 @@
+config ARCH_BCM2835
+	bool "Broadcom BCM2835 family" if ARCH_MULTI_V6
+	select ARCH_REQUIRE_GPIOLIB
+	select ARM_AMBA
+	select ARM_ERRATA_411920
+	select ARM_TIMER_SP804
+	select CLKDEV_LOOKUP
+	select CLKSRC_OF
+	select CPU_V6
+	select GENERIC_CLOCKEVENTS
+	select PINCTRL
+	select PINCTRL_BCM2835
+	help
+	  This enables support for the Broadcom BCM2835 SoC. This SoC is
+	  use in the Raspberry Pi, and Roku 2 devices.
diff --git a/arch/arm/mach-bcm2835/Makefile.boot b/arch/arm/mach-bcm2835/Makefile.boot
deleted file mode 100644
index b327175..0000000
--- a/arch/arm/mach-bcm2835/Makefile.boot
+++ /dev/null
@@ -1 +0,0 @@
-zreladdr-y := 0x00008000
diff --git a/arch/arm/mach-bcm2835/bcm2835.c b/arch/arm/mach-bcm2835/bcm2835.c
index 6f57859..740fa9e 100644
--- a/arch/arm/mach-bcm2835/bcm2835.c
+++ b/arch/arm/mach-bcm2835/bcm2835.c
@@ -23,8 +23,6 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <mach/bcm2835_soc.h>
-
 #define PM_RSTC				0x1c
 #define PM_RSTS				0x20
 #define PM_WDOG				0x24
@@ -34,6 +32,10 @@
 #define PM_RSTC_WRCFG_FULL_RESET	0x00000020
 #define PM_RSTS_HADWRH_SET		0x00000040
 
+#define BCM2835_PERIPH_PHYS	0x20000000
+#define BCM2835_PERIPH_VIRT	0xf0000000
+#define BCM2835_PERIPH_SIZE	SZ_16M
+
 static void __iomem *wdt_regs;
 
 /*
diff --git a/arch/arm/mach-bcm2835/include/mach/bcm2835_soc.h b/arch/arm/mach-bcm2835/include/mach/bcm2835_soc.h
deleted file mode 100644
index d4dfcf7..0000000
--- a/arch/arm/mach-bcm2835/include/mach/bcm2835_soc.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2012 Stephen Warren
- *
- * Derived from code:
- * Copyright (C) 2010 Broadcom
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT 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_BCM2835_BCM2835_SOC_H__
-#define __MACH_BCM2835_BCM2835_SOC_H__
-
-#include <asm/sizes.h>
-
-#define BCM2835_PERIPH_PHYS	0x20000000
-#define BCM2835_PERIPH_VIRT	0xf0000000
-#define BCM2835_PERIPH_SIZE	SZ_16M
-#define BCM2835_DEBUG_PHYS	0x20201000
-#define BCM2835_DEBUG_VIRT	0xf0201000
-
-#endif
diff --git a/arch/arm/mach-bcm2835/include/mach/debug-macro.S b/arch/arm/mach-bcm2835/include/mach/debug-macro.S
deleted file mode 100644
index 8a161e4..0000000
--- a/arch/arm/mach-bcm2835/include/mach/debug-macro.S
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Debugging macro include header
- *
- * Copyright (C) 2010 Broadcom
- * Copyright (C) 1994-1999 Russell King
- * Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-
-#include <mach/bcm2835_soc.h>
-
-	.macro	addruart, rp, rv, tmp
-	ldr	\rp, =BCM2835_DEBUG_PHYS
-	ldr	\rv, =BCM2835_DEBUG_VIRT
-	.endm
-
-#include <asm/hardware/debug-pl01x.S>
diff --git a/arch/arm/mach-bcm2835/include/mach/gpio.h b/arch/arm/mach-bcm2835/include/mach/gpio.h
deleted file mode 100644
index 40a8c17..0000000
--- a/arch/arm/mach-bcm2835/include/mach/gpio.h
+++ /dev/null
@@ -1 +0,0 @@
-/* empty */
diff --git a/arch/arm/mach-bcm2835/include/mach/timex.h b/arch/arm/mach-bcm2835/include/mach/timex.h
deleted file mode 100644
index 6d021e1..0000000
--- a/arch/arm/mach-bcm2835/include/mach/timex.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- *  BCM2835 system clock frequency
- *
- *  Copyright (C) 2010 Broadcom
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You 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_ARCH_TIMEX_H
-#define __ASM_ARCH_TIMEX_H
-
-#define CLOCK_TICK_RATE		(1000000)
-
-#endif
diff --git a/arch/arm/mach-bcm2835/include/mach/uncompress.h b/arch/arm/mach-bcm2835/include/mach/uncompress.h
deleted file mode 100644
index bf86dca..0000000
--- a/arch/arm/mach-bcm2835/include/mach/uncompress.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2010 Broadcom
- * Copyright (C) 2003 ARM Limited
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT 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/io.h>
-#include <linux/amba/serial.h>
-#include <mach/bcm2835_soc.h>
-
-#define UART0_BASE BCM2835_DEBUG_PHYS
-
-#define BCM2835_UART_DR IOMEM(UART0_BASE + UART01x_DR)
-#define BCM2835_UART_FR IOMEM(UART0_BASE + UART01x_FR)
-#define BCM2835_UART_CR IOMEM(UART0_BASE + UART011_CR)
-
-static inline void putc(int c)
-{
-	while (__raw_readl(BCM2835_UART_FR) & UART01x_FR_TXFF)
-		barrier();
-
-	__raw_writel(c, BCM2835_UART_DR);
-}
-
-static inline void flush(void)
-{
-	int fr;
-
-	do {
-		fr = __raw_readl(BCM2835_UART_FR);
-		barrier();
-	} while ((fr & (UART011_FR_TXFE | UART01x_FR_BUSY)) != UART011_FR_TXFE);
-}
-
-#define arch_decomp_setup()
diff --git a/arch/arm/mach-cns3xxx/Kconfig b/arch/arm/mach-cns3xxx/Kconfig
index 9ebfcc4..dbf0df8 100644
--- a/arch/arm/mach-cns3xxx/Kconfig
+++ b/arch/arm/mach-cns3xxx/Kconfig
@@ -1,8 +1,20 @@
+config ARCH_CNS3XXX
+	bool "Cavium Networks CNS3XXX family" if ARCH_MULTI_V6
+	select ARM_GIC
+	select CPU_V6K
+	select GENERIC_CLOCKEVENTS
+	select MIGHT_HAVE_CACHE_L2X0
+	select MIGHT_HAVE_PCI
+	select PCI_DOMAINS if PCI
+	help
+	  Support for Cavium Networks CNS3XXX platform.
+
 menu "CNS3XXX platform type"
 	depends on ARCH_CNS3XXX
 
 config MACH_CNS3420VB
 	bool "Support for CNS3420 Validation Board"
+	depends on ATAGS
 	help
 	  Include support for the Cavium Networks CNS3420 MPCore Platform
 	  Baseboard.
diff --git a/arch/arm/mach-cns3xxx/Makefile b/arch/arm/mach-cns3xxx/Makefile
index 11033f1..a1ff108 100644
--- a/arch/arm/mach-cns3xxx/Makefile
+++ b/arch/arm/mach-cns3xxx/Makefile
@@ -1,3 +1,5 @@
-obj-$(CONFIG_ARCH_CNS3XXX)		+= core.o pm.o devices.o
-obj-$(CONFIG_PCI)			+= pcie.o
-obj-$(CONFIG_MACH_CNS3420VB)		+= cns3420vb.o
+obj-$(CONFIG_ARCH_CNS3XXX)		+= cns3xxx.o
+cns3xxx-y				+= core.o pm.o
+cns3xxx-$(CONFIG_ATAGS)			+= devices.o
+cns3xxx-$(CONFIG_PCI)			+= pcie.o
+cns3xxx-$(CONFIG_MACH_CNS3420VB)	+= cns3420vb.o
diff --git a/arch/arm/mach-cns3xxx/cns3420vb.c b/arch/arm/mach-cns3xxx/cns3420vb.c
index a71867e..ce096d6 100644
--- a/arch/arm/mach-cns3xxx/cns3420vb.c
+++ b/arch/arm/mach-cns3xxx/cns3420vb.c
@@ -31,9 +31,8 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
-#include <mach/cns3xxx.h>
-#include <mach/irqs.h>
-#include <mach/pm.h>
+#include "cns3xxx.h"
+#include "pm.h"
 #include "core.h"
 #include "devices.h"
 
@@ -247,6 +246,7 @@ static void __init cns3420_map_io(void)
 
 MACHINE_START(CNS3420VB, "Cavium Networks CNS3420 Validation Board")
 	.atag_offset	= 0x100,
+	.nr_irqs	= NR_IRQS_CNS3XXX,
 	.map_io		= cns3420_map_io,
 	.init_irq	= cns3xxx_init_irq,
 	.init_time	= cns3xxx_timer_init,
diff --git a/arch/arm/mach-cns3xxx/cns3xxx.h b/arch/arm/mach-cns3xxx/cns3xxx.h
new file mode 100644
index 0000000..ae5eb42
--- /dev/null
+++ b/arch/arm/mach-cns3xxx/cns3xxx.h
@@ -0,0 +1,629 @@
+/*
+ * 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_BOARD_CNS3XXXH
+#define __MACH_BOARD_CNS3XXXH
+
+/*
+ * Memory map
+ */
+#define CNS3XXX_FLASH_BASE			0x10000000	/* Flash/SRAM Memory Bank 0 */
+#define CNS3XXX_FLASH_SIZE			SZ_256M
+
+#define CNS3XXX_DDR2SDRAM_BASE			0x20000000	/* DDR2 SDRAM Memory */
+
+#define CNS3XXX_SPI_FLASH_BASE			0x60000000	/* SPI Serial Flash Memory */
+
+#define CNS3XXX_SWITCH_BASE			0x70000000	/* Switch and HNAT Control */
+#define CNS3XXX_SWITCH_BASE_VIRT		0xFFF00000
+
+#define CNS3XXX_PPE_BASE			0x70001000	/* HANT	*/
+#define CNS3XXX_PPE_BASE_VIRT			0xFFF50000
+
+#define CNS3XXX_EMBEDDED_SRAM_BASE		0x70002000	/* HANT Embedded SRAM */
+#define CNS3XXX_EMBEDDED_SRAM_BASE_VIRT		0xFFF60000
+
+#define CNS3XXX_SSP_BASE			0x71000000	/* Synchronous Serial Port - SPI/PCM/I2C */
+#define CNS3XXX_SSP_BASE_VIRT			0xFFF01000
+
+#define CNS3XXX_DMC_BASE			0x72000000	/* DMC Control (DDR2 SDRAM) */
+#define CNS3XXX_DMC_BASE_VIRT			0xFFF02000
+
+#define CNS3XXX_SMC_BASE			0x73000000	/* SMC Control */
+#define CNS3XXX_SMC_BASE_VIRT			0xFFF03000
+
+#define SMC_MEMC_STATUS_OFFSET			0x000
+#define SMC_MEMIF_CFG_OFFSET			0x004
+#define SMC_MEMC_CFG_SET_OFFSET			0x008
+#define SMC_MEMC_CFG_CLR_OFFSET			0x00C
+#define SMC_DIRECT_CMD_OFFSET			0x010
+#define SMC_SET_CYCLES_OFFSET			0x014
+#define SMC_SET_OPMODE_OFFSET			0x018
+#define SMC_REFRESH_PERIOD_0_OFFSET		0x020
+#define SMC_REFRESH_PERIOD_1_OFFSET		0x024
+#define SMC_SRAM_CYCLES0_0_OFFSET		0x100
+#define SMC_NAND_CYCLES0_0_OFFSET		0x100
+#define SMC_OPMODE0_0_OFFSET			0x104
+#define SMC_SRAM_CYCLES0_1_OFFSET		0x120
+#define SMC_NAND_CYCLES0_1_OFFSET		0x120
+#define SMC_OPMODE0_1_OFFSET			0x124
+#define SMC_USER_STATUS_OFFSET			0x200
+#define SMC_USER_CONFIG_OFFSET			0x204
+#define SMC_ECC_STATUS_OFFSET			0x300
+#define SMC_ECC_MEMCFG_OFFSET			0x304
+#define SMC_ECC_MEMCOMMAND1_OFFSET		0x308
+#define SMC_ECC_MEMCOMMAND2_OFFSET		0x30C
+#define SMC_ECC_ADDR0_OFFSET			0x310
+#define SMC_ECC_ADDR1_OFFSET			0x314
+#define SMC_ECC_VALUE0_OFFSET			0x318
+#define SMC_ECC_VALUE1_OFFSET			0x31C
+#define SMC_ECC_VALUE2_OFFSET			0x320
+#define SMC_ECC_VALUE3_OFFSET			0x324
+#define SMC_PERIPH_ID_0_OFFSET			0xFE0
+#define SMC_PERIPH_ID_1_OFFSET			0xFE4
+#define SMC_PERIPH_ID_2_OFFSET			0xFE8
+#define SMC_PERIPH_ID_3_OFFSET			0xFEC
+#define SMC_PCELL_ID_0_OFFSET			0xFF0
+#define SMC_PCELL_ID_1_OFFSET			0xFF4
+#define SMC_PCELL_ID_2_OFFSET			0xFF8
+#define SMC_PCELL_ID_3_OFFSET			0xFFC
+
+#define CNS3XXX_GPIOA_BASE			0x74000000	/* GPIO port A */
+#define CNS3XXX_GPIOA_BASE_VIRT			0xFFF04000
+
+#define CNS3XXX_GPIOB_BASE			0x74800000	/* GPIO port B */
+#define CNS3XXX_GPIOB_BASE_VIRT			0xFFF05000
+
+#define CNS3XXX_RTC_BASE			0x75000000	/* Real Time Clock */
+#define CNS3XXX_RTC_BASE_VIRT			0xFFF06000
+
+#define RTC_SEC_OFFSET				0x00
+#define RTC_MIN_OFFSET				0x04
+#define RTC_HOUR_OFFSET				0x08
+#define RTC_DAY_OFFSET				0x0C
+#define RTC_SEC_ALM_OFFSET			0x10
+#define RTC_MIN_ALM_OFFSET			0x14
+#define RTC_HOUR_ALM_OFFSET			0x18
+#define RTC_REC_OFFSET				0x1C
+#define RTC_CTRL_OFFSET				0x20
+#define RTC_INTR_STS_OFFSET			0x34
+
+#define CNS3XXX_MISC_BASE			0x76000000	/* Misc Control */
+#define CNS3XXX_MISC_BASE_VIRT			0xFB000000	/* Misc Control */
+
+#define CNS3XXX_PM_BASE				0x77000000	/* Power Management Control */
+#define CNS3XXX_PM_BASE_VIRT			0xFB001000
+
+#define PM_CLK_GATE_OFFSET			0x00
+#define PM_SOFT_RST_OFFSET			0x04
+#define PM_HS_CFG_OFFSET			0x08
+#define PM_CACTIVE_STA_OFFSET			0x0C
+#define PM_PWR_STA_OFFSET			0x10
+#define PM_SYS_CLK_CTRL_OFFSET			0x14
+#define PM_PLL_LCD_I2S_CTRL_OFFSET		0x18
+#define PM_PLL_HM_PD_OFFSET			0x1C
+
+#define CNS3XXX_UART0_BASE			0x78000000	/* UART 0 */
+#define CNS3XXX_UART0_BASE_VIRT			0xFB002000
+
+#define CNS3XXX_UART1_BASE			0x78400000	/* UART 1 */
+#define CNS3XXX_UART1_BASE_VIRT			0xFFF0A000
+
+#define CNS3XXX_UART2_BASE			0x78800000	/* UART 2 */
+#define CNS3XXX_UART2_BASE_VIRT			0xFFF0B000
+
+#define CNS3XXX_DMAC_BASE			0x79000000	/* Generic DMA Control */
+#define CNS3XXX_DMAC_BASE_VIRT			0xFFF0D000
+
+#define CNS3XXX_CORESIGHT_BASE			0x7A000000	/* CoreSight */
+#define CNS3XXX_CORESIGHT_BASE_VIRT		0xFFF0E000
+
+#define CNS3XXX_CRYPTO_BASE			0x7B000000	/* Crypto */
+#define CNS3XXX_CRYPTO_BASE_VIRT		0xFFF0F000
+
+#define CNS3XXX_I2S_BASE			0x7C000000	/* I2S */
+#define CNS3XXX_I2S_BASE_VIRT			0xFFF10000
+
+#define CNS3XXX_TIMER1_2_3_BASE			0x7C800000	/* Timer */
+#define CNS3XXX_TIMER1_2_3_BASE_VIRT		0xFB003000
+
+#define TIMER1_COUNTER_OFFSET			0x00
+#define TIMER1_AUTO_RELOAD_OFFSET		0x04
+#define TIMER1_MATCH_V1_OFFSET			0x08
+#define TIMER1_MATCH_V2_OFFSET			0x0C
+
+#define TIMER2_COUNTER_OFFSET			0x10
+#define TIMER2_AUTO_RELOAD_OFFSET		0x14
+#define TIMER2_MATCH_V1_OFFSET			0x18
+#define TIMER2_MATCH_V2_OFFSET			0x1C
+
+#define TIMER1_2_CONTROL_OFFSET			0x30
+#define TIMER1_2_INTERRUPT_STATUS_OFFSET	0x34
+#define TIMER1_2_INTERRUPT_MASK_OFFSET		0x38
+
+#define TIMER_FREERUN_OFFSET			0x40
+#define TIMER_FREERUN_CONTROL_OFFSET		0x44
+
+#define CNS3XXX_HCIE_BASE			0x7D000000	/* HCIE Control */
+#define CNS3XXX_HCIE_BASE_VIRT			0xFFF30000
+
+#define CNS3XXX_RAID_BASE			0x7E000000	/* RAID Control */
+#define CNS3XXX_RAID_BASE_VIRT			0xFFF12000
+
+#define CNS3XXX_AXI_IXC_BASE			0x7F000000	/* AXI IXC */
+#define CNS3XXX_AXI_IXC_BASE_VIRT		0xFFF13000
+
+#define CNS3XXX_CLCD_BASE			0x80000000	/* LCD Control */
+#define CNS3XXX_CLCD_BASE_VIRT			0xFFF14000
+
+#define CNS3XXX_USBOTG_BASE			0x81000000	/* USB OTG Control */
+#define CNS3XXX_USBOTG_BASE_VIRT		0xFFF15000
+
+#define CNS3XXX_USB_BASE			0x82000000	/* USB Host Control */
+
+#define CNS3XXX_SATA2_BASE			0x83000000	/* SATA */
+#define CNS3XXX_SATA2_SIZE			SZ_16M
+#define CNS3XXX_SATA2_BASE_VIRT			0xFFF17000
+
+#define CNS3XXX_CAMERA_BASE			0x84000000	/* Camera Interface */
+#define CNS3XXX_CAMERA_BASE_VIRT		0xFFF18000
+
+#define CNS3XXX_SDIO_BASE			0x85000000	/* SDIO */
+#define CNS3XXX_SDIO_BASE_VIRT			0xFFF19000
+
+#define CNS3XXX_I2S_TDM_BASE			0x86000000	/* I2S TDM */
+#define CNS3XXX_I2S_TDM_BASE_VIRT		0xFFF1A000
+
+#define CNS3XXX_2DG_BASE			0x87000000	/* 2D Graphic Control */
+#define CNS3XXX_2DG_BASE_VIRT			0xFFF1B000
+
+#define CNS3XXX_USB_OHCI_BASE			0x88000000	/* USB OHCI */
+
+#define CNS3XXX_L2C_BASE			0x92000000	/* L2 Cache Control */
+#define CNS3XXX_L2C_BASE_VIRT			0xFFF27000
+
+#define CNS3XXX_PCIE0_MEM_BASE			0xA0000000	/* PCIe Port 0 IO/Memory Space */
+#define CNS3XXX_PCIE0_MEM_BASE_VIRT		0xE0000000
+
+#define CNS3XXX_PCIE0_HOST_BASE			0xAB000000	/* PCIe Port 0 RC Base */
+#define CNS3XXX_PCIE0_HOST_BASE_VIRT		0xE1000000
+
+#define CNS3XXX_PCIE0_IO_BASE			0xAC000000	/* PCIe Port 0 */
+#define CNS3XXX_PCIE0_IO_BASE_VIRT		0xE2000000
+
+#define CNS3XXX_PCIE0_CFG0_BASE			0xAD000000	/* PCIe Port 0 CFG Type 0 */
+#define CNS3XXX_PCIE0_CFG0_BASE_VIRT		0xE3000000
+
+#define CNS3XXX_PCIE0_CFG1_BASE			0xAE000000	/* PCIe Port 0 CFG Type 1 */
+#define CNS3XXX_PCIE0_CFG1_BASE_VIRT		0xE4000000
+
+#define CNS3XXX_PCIE0_MSG_BASE			0xAF000000	/* PCIe Port 0 Message Space */
+#define CNS3XXX_PCIE0_MSG_BASE_VIRT		0xE5000000
+
+#define CNS3XXX_PCIE1_MEM_BASE			0xB0000000	/* PCIe Port 1 IO/Memory Space */
+#define CNS3XXX_PCIE1_MEM_BASE_VIRT		0xE8000000
+
+#define CNS3XXX_PCIE1_HOST_BASE			0xBB000000	/* PCIe Port 1 RC Base */
+#define CNS3XXX_PCIE1_HOST_BASE_VIRT		0xE9000000
+
+#define CNS3XXX_PCIE1_IO_BASE			0xBC000000	/* PCIe Port 1 */
+#define CNS3XXX_PCIE1_IO_BASE_VIRT		0xEA000000
+
+#define CNS3XXX_PCIE1_CFG0_BASE			0xBD000000	/* PCIe Port 1 CFG Type 0 */
+#define CNS3XXX_PCIE1_CFG0_BASE_VIRT		0xEB000000
+
+#define CNS3XXX_PCIE1_CFG1_BASE			0xBE000000	/* PCIe Port 1 CFG Type 1 */
+#define CNS3XXX_PCIE1_CFG1_BASE_VIRT		0xEC000000
+
+#define CNS3XXX_PCIE1_MSG_BASE			0xBF000000	/* PCIe Port 1 Message Space */
+#define CNS3XXX_PCIE1_MSG_BASE_VIRT		0xED000000
+
+/*
+ * Testchip peripheral and fpga gic regions
+ */
+#define CNS3XXX_TC11MP_SCU_BASE			0x90000000	/* IRQ, Test chip */
+#define CNS3XXX_TC11MP_SCU_BASE_VIRT		0xFB004000
+
+#define CNS3XXX_TC11MP_GIC_CPU_BASE		0x90000100	/* Test chip interrupt controller CPU interface */
+#define CNS3XXX_TC11MP_GIC_CPU_BASE_VIRT	(CNS3XXX_TC11MP_SCU_BASE_VIRT + 0x100)
+
+#define CNS3XXX_TC11MP_TWD_BASE			0x90000600
+#define CNS3XXX_TC11MP_TWD_BASE_VIRT		(CNS3XXX_TC11MP_SCU_BASE_VIRT + 0x600)
+
+#define CNS3XXX_TC11MP_GIC_DIST_BASE		0x90001000	/* Test chip interrupt controller distributor */
+#define CNS3XXX_TC11MP_GIC_DIST_BASE_VIRT	(CNS3XXX_TC11MP_SCU_BASE_VIRT + 0x1000)
+
+#define CNS3XXX_TC11MP_L220_BASE		0x92002000	/* L220 registers */
+#define CNS3XXX_TC11MP_L220_BASE_VIRT		0xFF002000
+
+/*
+ * Misc block
+ */
+#define MISC_MEM_MAP(offs) (void __iomem *)(CNS3XXX_MISC_BASE_VIRT + (offs))
+
+#define MISC_MEMORY_REMAP_REG			MISC_MEM_MAP(0x00)
+#define MISC_CHIP_CONFIG_REG			MISC_MEM_MAP(0x04)
+#define MISC_DEBUG_PROBE_DATA_REG		MISC_MEM_MAP(0x08)
+#define MISC_DEBUG_PROBE_SELECTION_REG		MISC_MEM_MAP(0x0C)
+#define MISC_IO_PIN_FUNC_SELECTION_REG		MISC_MEM_MAP(0x10)
+#define MISC_GPIOA_PIN_ENABLE_REG		MISC_MEM_MAP(0x14)
+#define MISC_GPIOB_PIN_ENABLE_REG		MISC_MEM_MAP(0x18)
+#define MISC_IO_PAD_DRIVE_STRENGTH_CTRL_A	MISC_MEM_MAP(0x1C)
+#define MISC_IO_PAD_DRIVE_STRENGTH_CTRL_B	MISC_MEM_MAP(0x20)
+#define MISC_GPIOA_15_0_PULL_CTRL_REG		MISC_MEM_MAP(0x24)
+#define MISC_GPIOA_16_31_PULL_CTRL_REG		MISC_MEM_MAP(0x28)
+#define MISC_GPIOB_15_0_PULL_CTRL_REG		MISC_MEM_MAP(0x2C)
+#define MISC_GPIOB_16_31_PULL_CTRL_REG		MISC_MEM_MAP(0x30)
+#define MISC_IO_PULL_CTRL_REG			MISC_MEM_MAP(0x34)
+#define MISC_E_FUSE_31_0_REG			MISC_MEM_MAP(0x40)
+#define MISC_E_FUSE_63_32_REG			MISC_MEM_MAP(0x44)
+#define MISC_E_FUSE_95_64_REG			MISC_MEM_MAP(0x48)
+#define MISC_E_FUSE_127_96_REG			MISC_MEM_MAP(0x4C)
+#define MISC_SOFTWARE_TEST_1_REG		MISC_MEM_MAP(0x50)
+#define MISC_SOFTWARE_TEST_2_REG		MISC_MEM_MAP(0x54)
+
+#define MISC_SATA_POWER_MODE			MISC_MEM_MAP(0x310)
+
+#define MISC_USB_CFG_REG			MISC_MEM_MAP(0x800)
+#define MISC_USB_STS_REG			MISC_MEM_MAP(0x804)
+#define MISC_USBPHY00_CFG_REG			MISC_MEM_MAP(0x808)
+#define MISC_USBPHY01_CFG_REG			MISC_MEM_MAP(0x80c)
+#define MISC_USBPHY10_CFG_REG			MISC_MEM_MAP(0x810)
+#define MISC_USBPHY11_CFG_REG			MISC_MEM_MAP(0x814)
+
+#define MISC_PCIEPHY_CMCTL(x)			MISC_MEM_MAP(0x900 + (x) * 0x004)
+#define MISC_PCIEPHY_CTL(x)			MISC_MEM_MAP(0x940 + (x) * 0x100)
+#define MISC_PCIE_AXIS_AWMISC(x)		MISC_MEM_MAP(0x944 + (x) * 0x100)
+#define MISC_PCIE_AXIS_ARMISC(x)		MISC_MEM_MAP(0x948 + (x) * 0x100)
+#define MISC_PCIE_AXIS_RMISC(x)			MISC_MEM_MAP(0x94C + (x) * 0x100)
+#define MISC_PCIE_AXIS_BMISC(x)			MISC_MEM_MAP(0x950 + (x) * 0x100)
+#define MISC_PCIE_AXIM_RMISC(x)			MISC_MEM_MAP(0x954 + (x) * 0x100)
+#define MISC_PCIE_AXIM_BMISC(x)			MISC_MEM_MAP(0x958 + (x) * 0x100)
+#define MISC_PCIE_CTRL(x)			MISC_MEM_MAP(0x95C + (x) * 0x100)
+#define MISC_PCIE_PM_DEBUG(x)			MISC_MEM_MAP(0x960 + (x) * 0x100)
+#define MISC_PCIE_RFC_DEBUG(x)			MISC_MEM_MAP(0x964 + (x) * 0x100)
+#define MISC_PCIE_CXPL_DEBUGL(x)		MISC_MEM_MAP(0x968 + (x) * 0x100)
+#define MISC_PCIE_CXPL_DEBUGH(x)		MISC_MEM_MAP(0x96C + (x) * 0x100)
+#define MISC_PCIE_DIAG_DEBUGH(x)		MISC_MEM_MAP(0x970 + (x) * 0x100)
+#define MISC_PCIE_W1CLR(x)			MISC_MEM_MAP(0x974 + (x) * 0x100)
+#define MISC_PCIE_INT_MASK(x)			MISC_MEM_MAP(0x978 + (x) * 0x100)
+#define MISC_PCIE_INT_STATUS(x)			MISC_MEM_MAP(0x97C + (x) * 0x100)
+
+/*
+ * Power management and clock control
+ */
+#define PMU_MEM_MAP(offs) (void __iomem *)(CNS3XXX_PM_BASE_VIRT + (offs))
+
+#define PM_CLK_GATE_REG					PMU_MEM_MAP(0x000)
+#define PM_SOFT_RST_REG					PMU_MEM_MAP(0x004)
+#define PM_HS_CFG_REG					PMU_MEM_MAP(0x008)
+#define PM_CACTIVE_STA_REG				PMU_MEM_MAP(0x00C)
+#define PM_PWR_STA_REG					PMU_MEM_MAP(0x010)
+#define PM_CLK_CTRL_REG					PMU_MEM_MAP(0x014)
+#define PM_PLL_LCD_I2S_CTRL_REG				PMU_MEM_MAP(0x018)
+#define PM_PLL_HM_PD_CTRL_REG				PMU_MEM_MAP(0x01C)
+#define PM_REGULAT_CTRL_REG				PMU_MEM_MAP(0x020)
+#define PM_WDT_CTRL_REG					PMU_MEM_MAP(0x024)
+#define PM_WU_CTRL0_REG					PMU_MEM_MAP(0x028)
+#define PM_WU_CTRL1_REG					PMU_MEM_MAP(0x02C)
+#define PM_CSR_REG					PMU_MEM_MAP(0x030)
+
+/* PM_CLK_GATE_REG */
+#define PM_CLK_GATE_REG_OFFSET_SDIO			(25)
+#define PM_CLK_GATE_REG_OFFSET_GPU			(24)
+#define PM_CLK_GATE_REG_OFFSET_CIM			(23)
+#define PM_CLK_GATE_REG_OFFSET_LCDC			(22)
+#define PM_CLK_GATE_REG_OFFSET_I2S			(21)
+#define PM_CLK_GATE_REG_OFFSET_RAID			(20)
+#define PM_CLK_GATE_REG_OFFSET_SATA			(19)
+#define PM_CLK_GATE_REG_OFFSET_PCIE(x)			(17 + (x))
+#define PM_CLK_GATE_REG_OFFSET_USB_HOST			(16)
+#define PM_CLK_GATE_REG_OFFSET_USB_OTG			(15)
+#define PM_CLK_GATE_REG_OFFSET_TIMER			(14)
+#define PM_CLK_GATE_REG_OFFSET_CRYPTO			(13)
+#define PM_CLK_GATE_REG_OFFSET_HCIE			(12)
+#define PM_CLK_GATE_REG_OFFSET_SWITCH			(11)
+#define PM_CLK_GATE_REG_OFFSET_GPIO			(10)
+#define PM_CLK_GATE_REG_OFFSET_UART3			(9)
+#define PM_CLK_GATE_REG_OFFSET_UART2			(8)
+#define PM_CLK_GATE_REG_OFFSET_UART1			(7)
+#define PM_CLK_GATE_REG_OFFSET_RTC			(5)
+#define PM_CLK_GATE_REG_OFFSET_GDMA			(4)
+#define PM_CLK_GATE_REG_OFFSET_SPI_PCM_I2C		(3)
+#define PM_CLK_GATE_REG_OFFSET_SMC_NFI			(1)
+#define PM_CLK_GATE_REG_MASK				(0x03FFFFBA)
+
+/* PM_SOFT_RST_REG */
+#define PM_SOFT_RST_REG_OFFST_WARM_RST_FLAG		(31)
+#define PM_SOFT_RST_REG_OFFST_CPU1			(29)
+#define PM_SOFT_RST_REG_OFFST_CPU0			(28)
+#define PM_SOFT_RST_REG_OFFST_SDIO			(25)
+#define PM_SOFT_RST_REG_OFFST_GPU			(24)
+#define PM_SOFT_RST_REG_OFFST_CIM			(23)
+#define PM_SOFT_RST_REG_OFFST_LCDC			(22)
+#define PM_SOFT_RST_REG_OFFST_I2S			(21)
+#define PM_SOFT_RST_REG_OFFST_RAID			(20)
+#define PM_SOFT_RST_REG_OFFST_SATA			(19)
+#define PM_SOFT_RST_REG_OFFST_PCIE(x)			(17 + (x))
+#define PM_SOFT_RST_REG_OFFST_USB_HOST			(16)
+#define PM_SOFT_RST_REG_OFFST_USB_OTG			(15)
+#define PM_SOFT_RST_REG_OFFST_TIMER			(14)
+#define PM_SOFT_RST_REG_OFFST_CRYPTO			(13)
+#define PM_SOFT_RST_REG_OFFST_HCIE			(12)
+#define PM_SOFT_RST_REG_OFFST_SWITCH			(11)
+#define PM_SOFT_RST_REG_OFFST_GPIO			(10)
+#define PM_SOFT_RST_REG_OFFST_UART3			(9)
+#define PM_SOFT_RST_REG_OFFST_UART2			(8)
+#define PM_SOFT_RST_REG_OFFST_UART1			(7)
+#define PM_SOFT_RST_REG_OFFST_RTC			(5)
+#define PM_SOFT_RST_REG_OFFST_GDMA			(4)
+#define PM_SOFT_RST_REG_OFFST_SPI_PCM_I2C		(3)
+#define PM_SOFT_RST_REG_OFFST_DMC			(2)
+#define PM_SOFT_RST_REG_OFFST_SMC_NFI			(1)
+#define PM_SOFT_RST_REG_OFFST_GLOBAL			(0)
+#define PM_SOFT_RST_REG_MASK				(0xF3FFFFBF)
+
+/* PMHS_CFG_REG */
+#define PM_HS_CFG_REG_OFFSET_SDIO			(25)
+#define PM_HS_CFG_REG_OFFSET_GPU			(24)
+#define PM_HS_CFG_REG_OFFSET_CIM			(23)
+#define PM_HS_CFG_REG_OFFSET_LCDC			(22)
+#define PM_HS_CFG_REG_OFFSET_I2S			(21)
+#define PM_HS_CFG_REG_OFFSET_RAID			(20)
+#define PM_HS_CFG_REG_OFFSET_SATA			(19)
+#define PM_HS_CFG_REG_OFFSET_PCIE1			(18)
+#define PM_HS_CFG_REG_OFFSET_PCIE0			(17)
+#define PM_HS_CFG_REG_OFFSET_USB_HOST			(16)
+#define PM_HS_CFG_REG_OFFSET_USB_OTG			(15)
+#define PM_HS_CFG_REG_OFFSET_TIMER			(14)
+#define PM_HS_CFG_REG_OFFSET_CRYPTO			(13)
+#define PM_HS_CFG_REG_OFFSET_HCIE			(12)
+#define PM_HS_CFG_REG_OFFSET_SWITCH			(11)
+#define PM_HS_CFG_REG_OFFSET_GPIO			(10)
+#define PM_HS_CFG_REG_OFFSET_UART3			(9)
+#define PM_HS_CFG_REG_OFFSET_UART2			(8)
+#define PM_HS_CFG_REG_OFFSET_UART1			(7)
+#define PM_HS_CFG_REG_OFFSET_RTC			(5)
+#define PM_HS_CFG_REG_OFFSET_GDMA			(4)
+#define PM_HS_CFG_REG_OFFSET_SPI_PCM_I2S		(3)
+#define PM_HS_CFG_REG_OFFSET_DMC			(2)
+#define PM_HS_CFG_REG_OFFSET_SMC_NFI			(1)
+#define PM_HS_CFG_REG_MASK				(0x03FFFFBE)
+#define PM_HS_CFG_REG_MASK_SUPPORT			(0x01100806)
+
+/* PM_CACTIVE_STA_REG */
+#define PM_CACTIVE_STA_REG_OFFSET_SDIO			(25)
+#define PM_CACTIVE_STA_REG_OFFSET_GPU			(24)
+#define PM_CACTIVE_STA_REG_OFFSET_CIM			(23)
+#define PM_CACTIVE_STA_REG_OFFSET_LCDC			(22)
+#define PM_CACTIVE_STA_REG_OFFSET_I2S			(21)
+#define PM_CACTIVE_STA_REG_OFFSET_RAID			(20)
+#define PM_CACTIVE_STA_REG_OFFSET_SATA			(19)
+#define PM_CACTIVE_STA_REG_OFFSET_PCIE1			(18)
+#define PM_CACTIVE_STA_REG_OFFSET_PCIE0			(17)
+#define PM_CACTIVE_STA_REG_OFFSET_USB_HOST		(16)
+#define PM_CACTIVE_STA_REG_OFFSET_USB_OTG		(15)
+#define PM_CACTIVE_STA_REG_OFFSET_TIMER			(14)
+#define PM_CACTIVE_STA_REG_OFFSET_CRYPTO		(13)
+#define PM_CACTIVE_STA_REG_OFFSET_HCIE			(12)
+#define PM_CACTIVE_STA_REG_OFFSET_SWITCH		(11)
+#define PM_CACTIVE_STA_REG_OFFSET_GPIO			(10)
+#define PM_CACTIVE_STA_REG_OFFSET_UART3			(9)
+#define PM_CACTIVE_STA_REG_OFFSET_UART2			(8)
+#define PM_CACTIVE_STA_REG_OFFSET_UART1			(7)
+#define PM_CACTIVE_STA_REG_OFFSET_RTC			(5)
+#define PM_CACTIVE_STA_REG_OFFSET_GDMA			(4)
+#define PM_CACTIVE_STA_REG_OFFSET_SPI_PCM_I2S		(3)
+#define PM_CACTIVE_STA_REG_OFFSET_DMC			(2)
+#define PM_CACTIVE_STA_REG_OFFSET_SMC_NFI		(1)
+#define PM_CACTIVE_STA_REG_MASK				(0x03FFFFBE)
+
+/* PM_PWR_STA_REG */
+#define PM_PWR_STA_REG_REG_OFFSET_SDIO			(25)
+#define PM_PWR_STA_REG_REG_OFFSET_GPU			(24)
+#define PM_PWR_STA_REG_REG_OFFSET_CIM			(23)
+#define PM_PWR_STA_REG_REG_OFFSET_LCDC			(22)
+#define PM_PWR_STA_REG_REG_OFFSET_I2S			(21)
+#define PM_PWR_STA_REG_REG_OFFSET_RAID			(20)
+#define PM_PWR_STA_REG_REG_OFFSET_SATA			(19)
+#define PM_PWR_STA_REG_REG_OFFSET_PCIE1			(18)
+#define PM_PWR_STA_REG_REG_OFFSET_PCIE0			(17)
+#define PM_PWR_STA_REG_REG_OFFSET_USB_HOST		(16)
+#define PM_PWR_STA_REG_REG_OFFSET_USB_OTG		(15)
+#define PM_PWR_STA_REG_REG_OFFSET_TIMER			(14)
+#define PM_PWR_STA_REG_REG_OFFSET_CRYPTO		(13)
+#define PM_PWR_STA_REG_REG_OFFSET_HCIE			(12)
+#define PM_PWR_STA_REG_REG_OFFSET_SWITCH		(11)
+#define PM_PWR_STA_REG_REG_OFFSET_GPIO			(10)
+#define PM_PWR_STA_REG_REG_OFFSET_UART3			(9)
+#define PM_PWR_STA_REG_REG_OFFSET_UART2			(8)
+#define PM_PWR_STA_REG_REG_OFFSET_UART1			(7)
+#define PM_PWR_STA_REG_REG_OFFSET_RTC			(5)
+#define PM_PWR_STA_REG_REG_OFFSET_GDMA			(4)
+#define PM_PWR_STA_REG_REG_OFFSET_SPI_PCM_I2S		(3)
+#define PM_PWR_STA_REG_REG_OFFSET_DMC			(2)
+#define PM_PWR_STA_REG_REG_OFFSET_SMC_NFI		(1)
+#define PM_PWR_STA_REG_REG_MASK				(0x03FFFFBE)
+
+/* PM_CLK_CTRL_REG */
+#define PM_CLK_CTRL_REG_OFFSET_I2S_MCLK			(31)
+#define PM_CLK_CTRL_REG_OFFSET_DDR2_CHG_EN		(30)
+#define PM_CLK_CTRL_REG_OFFSET_PCIE_REF1_EN		(29)
+#define PM_CLK_CTRL_REG_OFFSET_PCIE_REF0_EN		(28)
+#define PM_CLK_CTRL_REG_OFFSET_TIMER_SIM_MODE		(27)
+#define PM_CLK_CTRL_REG_OFFSET_I2SCLK_DIV		(24)
+#define PM_CLK_CTRL_REG_OFFSET_I2SCLK_SEL		(22)
+#define PM_CLK_CTRL_REG_OFFSET_CLKOUT_DIV		(20)
+#define PM_CLK_CTRL_REG_OFFSET_CLKOUT_SEL		(16)
+#define PM_CLK_CTRL_REG_OFFSET_MDC_DIV			(14)
+#define PM_CLK_CTRL_REG_OFFSET_CRYPTO_CLK_SEL		(12)
+#define PM_CLK_CTRL_REG_OFFSET_CPU_PWR_MODE		(9)
+#define PM_CLK_CTRL_REG_OFFSET_PLL_DDR2_SEL		(7)
+#define PM_CLK_CTRL_REG_OFFSET_DIV_IMMEDIATE		(6)
+#define PM_CLK_CTRL_REG_OFFSET_CPU_CLK_DIV		(4)
+#define PM_CLK_CTRL_REG_OFFSET_PLL_CPU_SEL		(0)
+
+#define PM_CPU_CLK_DIV(DIV) { \
+	PM_CLK_CTRL_REG &= ~((0x3) << PM_CLK_CTRL_REG_OFFSET_CPU_CLK_DIV); \
+	PM_CLK_CTRL_REG |= (((DIV)&0x3) << PM_CLK_CTRL_REG_OFFSET_CPU_CLK_DIV); \
+}
+
+#define PM_PLL_CPU_SEL(CPU) { \
+	PM_CLK_CTRL_REG &= ~((0xF) << PM_CLK_CTRL_REG_OFFSET_PLL_CPU_SEL); \
+	PM_CLK_CTRL_REG |= (((CPU)&0xF) << PM_CLK_CTRL_REG_OFFSET_PLL_CPU_SEL); \
+}
+
+/* PM_PLL_LCD_I2S_CTRL_REG */
+#define PM_PLL_LCD_I2S_CTRL_REG_OFFSET_MCLK_SMC_DIV	(22)
+#define PM_PLL_LCD_I2S_CTRL_REG_OFFSET_R_SEL		(17)
+#define PM_PLL_LCD_I2S_CTRL_REG_OFFSET_PLL_LCD_P	(11)
+#define PM_PLL_LCD_I2S_CTRL_REG_OFFSET_PLL_LCD_M	(3)
+#define PM_PLL_LCD_I2S_CTRL_REG_OFFSET_PLL_LCD_S	(0)
+
+/* PM_PLL_HM_PD_CTRL_REG */
+#define PM_PLL_HM_PD_CTRL_REG_OFFSET_SATA_PHY1		(11)
+#define PM_PLL_HM_PD_CTRL_REG_OFFSET_SATA_PHY0		(10)
+#define PM_PLL_HM_PD_CTRL_REG_OFFSET_PLL_I2SCD		(6)
+#define PM_PLL_HM_PD_CTRL_REG_OFFSET_PLL_I2S		(5)
+#define PM_PLL_HM_PD_CTRL_REG_OFFSET_PLL_LCD		(4)
+#define PM_PLL_HM_PD_CTRL_REG_OFFSET_PLL_USB		(3)
+#define PM_PLL_HM_PD_CTRL_REG_OFFSET_PLL_RGMII		(2)
+#define PM_PLL_HM_PD_CTRL_REG_MASK			(0x00000C7C)
+
+/* PM_WDT_CTRL_REG */
+#define PM_WDT_CTRL_REG_OFFSET_RESET_CPU_ONLY		(0)
+
+/* PM_CSR_REG - Clock Scaling Register*/
+#define PM_CSR_REG_OFFSET_CSR_EN			(30)
+#define PM_CSR_REG_OFFSET_CSR_NUM			(0)
+
+#define CNS3XXX_PWR_CLK_EN(BLOCK) (0x1<<PM_CLK_GATE_REG_OFFSET_##BLOCK)
+
+/* Software reset*/
+#define CNS3XXX_PWR_SOFTWARE_RST(BLOCK) (0x1<<PM_SOFT_RST_REG_OFFST_##BLOCK)
+
+/*
+ * CNS3XXX support several power saving mode as following,
+ * DFS, IDLE, HALT, DOZE, SLEEP, Hibernate
+ */
+#define CNS3XXX_PWR_CPU_MODE_DFS			(0)
+#define CNS3XXX_PWR_CPU_MODE_IDLE			(1)
+#define CNS3XXX_PWR_CPU_MODE_HALT			(2)
+#define CNS3XXX_PWR_CPU_MODE_DOZE			(3)
+#define CNS3XXX_PWR_CPU_MODE_SLEEP			(4)
+#define CNS3XXX_PWR_CPU_MODE_HIBERNATE			(5)
+
+#define CNS3XXX_PWR_PLL(BLOCK)	(0x1<<PM_PLL_HM_PD_CTRL_REG_OFFSET_##BLOCK)
+#define CNS3XXX_PWR_PLL_ALL	PM_PLL_HM_PD_CTRL_REG_MASK
+
+/* Change CPU frequency and divider */
+#define CNS3XXX_PWR_PLL_CPU_300MHZ			(0)
+#define CNS3XXX_PWR_PLL_CPU_333MHZ			(1)
+#define CNS3XXX_PWR_PLL_CPU_366MHZ			(2)
+#define CNS3XXX_PWR_PLL_CPU_400MHZ			(3)
+#define CNS3XXX_PWR_PLL_CPU_433MHZ			(4)
+#define CNS3XXX_PWR_PLL_CPU_466MHZ			(5)
+#define CNS3XXX_PWR_PLL_CPU_500MHZ			(6)
+#define CNS3XXX_PWR_PLL_CPU_533MHZ			(7)
+#define CNS3XXX_PWR_PLL_CPU_566MHZ			(8)
+#define CNS3XXX_PWR_PLL_CPU_600MHZ			(9)
+#define CNS3XXX_PWR_PLL_CPU_633MHZ			(10)
+#define CNS3XXX_PWR_PLL_CPU_666MHZ			(11)
+#define CNS3XXX_PWR_PLL_CPU_700MHZ			(12)
+
+#define CNS3XXX_PWR_CPU_CLK_DIV_BY1			(0)
+#define CNS3XXX_PWR_CPU_CLK_DIV_BY2			(1)
+#define CNS3XXX_PWR_CPU_CLK_DIV_BY4			(2)
+
+/* Change DDR2 frequency */
+#define CNS3XXX_PWR_PLL_DDR2_200MHZ			(0)
+#define CNS3XXX_PWR_PLL_DDR2_266MHZ			(1)
+#define CNS3XXX_PWR_PLL_DDR2_333MHZ			(2)
+#define CNS3XXX_PWR_PLL_DDR2_400MHZ			(3)
+
+void cns3xxx_pwr_soft_rst(unsigned int block);
+void cns3xxx_pwr_clk_en(unsigned int block);
+int cns3xxx_cpu_clock(void);
+
+/*
+ * ARM11 MPCore interrupt sources (primary GIC)
+ */
+#define IRQ_TC11MP_GIC_START	32
+
+#define IRQ_CNS3XXX_PMU			(IRQ_TC11MP_GIC_START + 0)
+#define IRQ_CNS3XXX_SDIO		(IRQ_TC11MP_GIC_START + 1)
+#define IRQ_CNS3XXX_L2CC		(IRQ_TC11MP_GIC_START + 2)
+#define IRQ_CNS3XXX_RTC			(IRQ_TC11MP_GIC_START + 3)
+#define IRQ_CNS3XXX_I2S			(IRQ_TC11MP_GIC_START + 4)
+#define IRQ_CNS3XXX_PCM			(IRQ_TC11MP_GIC_START + 5)
+#define IRQ_CNS3XXX_SPI			(IRQ_TC11MP_GIC_START + 6)
+#define IRQ_CNS3XXX_I2C			(IRQ_TC11MP_GIC_START + 7)
+#define IRQ_CNS3XXX_CIM			(IRQ_TC11MP_GIC_START + 8)
+#define IRQ_CNS3XXX_GPU			(IRQ_TC11MP_GIC_START + 9)
+#define IRQ_CNS3XXX_LCD			(IRQ_TC11MP_GIC_START + 10)
+#define IRQ_CNS3XXX_GPIOA		(IRQ_TC11MP_GIC_START + 11)
+#define IRQ_CNS3XXX_GPIOB		(IRQ_TC11MP_GIC_START + 12)
+#define IRQ_CNS3XXX_UART0		(IRQ_TC11MP_GIC_START + 13)
+#define IRQ_CNS3XXX_UART1		(IRQ_TC11MP_GIC_START + 14)
+#define IRQ_CNS3XXX_UART2		(IRQ_TC11MP_GIC_START + 15)
+#define IRQ_CNS3XXX_ARM11		(IRQ_TC11MP_GIC_START + 16)
+
+#define IRQ_CNS3XXX_SW_STATUS		(IRQ_TC11MP_GIC_START + 17)
+#define IRQ_CNS3XXX_SW_R0TXC		(IRQ_TC11MP_GIC_START + 18)
+#define IRQ_CNS3XXX_SW_R0RXC		(IRQ_TC11MP_GIC_START + 19)
+#define IRQ_CNS3XXX_SW_R0QE		(IRQ_TC11MP_GIC_START + 20)
+#define IRQ_CNS3XXX_SW_R0QF		(IRQ_TC11MP_GIC_START + 21)
+#define IRQ_CNS3XXX_SW_R1TXC		(IRQ_TC11MP_GIC_START + 22)
+#define IRQ_CNS3XXX_SW_R1RXC		(IRQ_TC11MP_GIC_START + 23)
+#define IRQ_CNS3XXX_SW_R1QE		(IRQ_TC11MP_GIC_START + 24)
+#define IRQ_CNS3XXX_SW_R1QF		(IRQ_TC11MP_GIC_START + 25)
+#define IRQ_CNS3XXX_SW_PPE		(IRQ_TC11MP_GIC_START + 26)
+
+#define IRQ_CNS3XXX_CRYPTO		(IRQ_TC11MP_GIC_START + 27)
+#define IRQ_CNS3XXX_HCIE		(IRQ_TC11MP_GIC_START + 28)
+#define IRQ_CNS3XXX_PCIE0_DEVICE	(IRQ_TC11MP_GIC_START + 29)
+#define IRQ_CNS3XXX_PCIE1_DEVICE	(IRQ_TC11MP_GIC_START + 30)
+#define IRQ_CNS3XXX_USB_OTG		(IRQ_TC11MP_GIC_START + 31)
+#define IRQ_CNS3XXX_USB_EHCI		(IRQ_TC11MP_GIC_START + 32)
+#define IRQ_CNS3XXX_SATA		(IRQ_TC11MP_GIC_START + 33)
+#define IRQ_CNS3XXX_RAID		(IRQ_TC11MP_GIC_START + 34)
+#define IRQ_CNS3XXX_SMC			(IRQ_TC11MP_GIC_START + 35)
+
+#define IRQ_CNS3XXX_DMAC_ABORT		(IRQ_TC11MP_GIC_START + 36)
+#define IRQ_CNS3XXX_DMAC0		(IRQ_TC11MP_GIC_START + 37)
+#define IRQ_CNS3XXX_DMAC1		(IRQ_TC11MP_GIC_START + 38)
+#define IRQ_CNS3XXX_DMAC2		(IRQ_TC11MP_GIC_START + 39)
+#define IRQ_CNS3XXX_DMAC3		(IRQ_TC11MP_GIC_START + 40)
+#define IRQ_CNS3XXX_DMAC4		(IRQ_TC11MP_GIC_START + 41)
+#define IRQ_CNS3XXX_DMAC5		(IRQ_TC11MP_GIC_START + 42)
+#define IRQ_CNS3XXX_DMAC6		(IRQ_TC11MP_GIC_START + 43)
+#define IRQ_CNS3XXX_DMAC7		(IRQ_TC11MP_GIC_START + 44)
+#define IRQ_CNS3XXX_DMAC8		(IRQ_TC11MP_GIC_START + 45)
+#define IRQ_CNS3XXX_DMAC9		(IRQ_TC11MP_GIC_START + 46)
+#define IRQ_CNS3XXX_DMAC10		(IRQ_TC11MP_GIC_START + 47)
+#define IRQ_CNS3XXX_DMAC11		(IRQ_TC11MP_GIC_START + 48)
+#define IRQ_CNS3XXX_DMAC12		(IRQ_TC11MP_GIC_START + 49)
+#define IRQ_CNS3XXX_DMAC13		(IRQ_TC11MP_GIC_START + 50)
+#define IRQ_CNS3XXX_DMAC14		(IRQ_TC11MP_GIC_START + 51)
+#define IRQ_CNS3XXX_DMAC15		(IRQ_TC11MP_GIC_START + 52)
+#define IRQ_CNS3XXX_DMAC16		(IRQ_TC11MP_GIC_START + 53)
+#define IRQ_CNS3XXX_DMAC17		(IRQ_TC11MP_GIC_START + 54)
+
+#define IRQ_CNS3XXX_PCIE0_RC		(IRQ_TC11MP_GIC_START + 55)
+#define IRQ_CNS3XXX_PCIE1_RC		(IRQ_TC11MP_GIC_START + 56)
+#define IRQ_CNS3XXX_TIMER0		(IRQ_TC11MP_GIC_START + 57)
+#define IRQ_CNS3XXX_TIMER1		(IRQ_TC11MP_GIC_START + 58)
+#define IRQ_CNS3XXX_USB_OHCI		(IRQ_TC11MP_GIC_START + 59)
+#define IRQ_CNS3XXX_TIMER2		(IRQ_TC11MP_GIC_START + 60)
+#define IRQ_CNS3XXX_EXTERNAL_PIN0	(IRQ_TC11MP_GIC_START + 61)
+#define IRQ_CNS3XXX_EXTERNAL_PIN1	(IRQ_TC11MP_GIC_START + 62)
+#define IRQ_CNS3XXX_EXTERNAL_PIN2	(IRQ_TC11MP_GIC_START + 63)
+
+#define NR_IRQS_CNS3XXX			(IRQ_TC11MP_GIC_START + 64)
+
+#endif	/* __MACH_BOARD_CNS3XXX_H */
diff --git a/arch/arm/mach-cns3xxx/core.c b/arch/arm/mach-cns3xxx/core.c
index e698f26..71609ee 100644
--- a/arch/arm/mach-cns3xxx/core.c
+++ b/arch/arm/mach-cns3xxx/core.c
@@ -13,28 +13,24 @@
 #include <linux/clockchips.h>
 #include <linux/io.h>
 #include <linux/irqchip/arm-gic.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/usb/ehci_pdriver.h>
+#include <linux/usb/ohci_pdriver.h>
+#include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
 #include <asm/mach/irq.h>
 #include <asm/hardware/cache-l2x0.h>
-#include <mach/cns3xxx.h>
+#include "cns3xxx.h"
 #include "core.h"
+#include "pm.h"
 
 static struct map_desc cns3xxx_io_desc[] __initdata = {
 	{
-		.virtual	= CNS3XXX_TC11MP_TWD_BASE_VIRT,
-		.pfn		= __phys_to_pfn(CNS3XXX_TC11MP_TWD_BASE),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= CNS3XXX_TC11MP_GIC_CPU_BASE_VIRT,
-		.pfn		= __phys_to_pfn(CNS3XXX_TC11MP_GIC_CPU_BASE),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= CNS3XXX_TC11MP_GIC_DIST_BASE_VIRT,
-		.pfn		= __phys_to_pfn(CNS3XXX_TC11MP_GIC_DIST_BASE),
-		.length		= SZ_4K,
+		.virtual	= CNS3XXX_TC11MP_SCU_BASE_VIRT,
+		.pfn		= __phys_to_pfn(CNS3XXX_TC11MP_SCU_BASE),
+		.length		= SZ_8K,
 		.type		= MT_DEVICE,
 	}, {
 		.virtual	= CNS3XXX_TIMER1_2_3_BASE_VIRT,
@@ -276,3 +272,116 @@ void __init cns3xxx_l2x0_init(void)
 }
 
 #endif /* CONFIG_CACHE_L2X0 */
+
+static int csn3xxx_usb_power_on(struct platform_device *pdev)
+{
+	/*
+	 * EHCI and OHCI share the same clock and power,
+	 * resetting twice would cause the 1st controller been reset.
+	 * Therefore only do power up  at the first up device, and
+	 * power down at the last down device.
+	 *
+	 * Set USB AHB INCR length to 16
+	 */
+	if (atomic_inc_return(&usb_pwr_ref) == 1) {
+		cns3xxx_pwr_power_up(1 << PM_PLL_HM_PD_CTRL_REG_OFFSET_PLL_USB);
+		cns3xxx_pwr_clk_en(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST);
+		cns3xxx_pwr_soft_rst(1 << PM_SOFT_RST_REG_OFFST_USB_HOST);
+		__raw_writel((__raw_readl(MISC_CHIP_CONFIG_REG) | (0X2 << 24)),
+			MISC_CHIP_CONFIG_REG);
+	}
+
+	return 0;
+}
+
+static void csn3xxx_usb_power_off(struct platform_device *pdev)
+{
+	/*
+	 * EHCI and OHCI share the same clock and power,
+	 * resetting twice would cause the 1st controller been reset.
+	 * Therefore only do power up  at the first up device, and
+	 * power down at the last down device.
+	 */
+	if (atomic_dec_return(&usb_pwr_ref) == 0)
+		cns3xxx_pwr_clk_dis(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST);
+}
+
+static struct usb_ehci_pdata cns3xxx_usb_ehci_pdata = {
+	.power_on	= csn3xxx_usb_power_on,
+	.power_off	= csn3xxx_usb_power_off,
+};
+
+static struct usb_ohci_pdata cns3xxx_usb_ohci_pdata = {
+	.num_ports	= 1,
+	.power_on	= csn3xxx_usb_power_on,
+	.power_off	= csn3xxx_usb_power_off,
+};
+
+static struct of_dev_auxdata cns3xxx_auxdata[] __initconst = {
+	{ "intel,usb-ehci", CNS3XXX_USB_BASE, "ehci-platform", &cns3xxx_usb_ehci_pdata },
+	{ "intel,usb-ohci", CNS3XXX_USB_OHCI_BASE, "ohci-platform", &cns3xxx_usb_ohci_pdata },
+	{ "cavium,cns3420-ahci", CNS3XXX_SATA2_BASE, "ahci", NULL },
+	{ "cavium,cns3420-sdhci", CNS3XXX_SDIO_BASE, "ahci", NULL },
+	{},
+};
+
+static void __init cns3xxx_init(void)
+{
+	struct device_node *dn;
+
+	cns3xxx_l2x0_init();
+
+	dn = of_find_compatible_node(NULL, NULL, "cavium,cns3420-ahci");
+	if (of_device_is_available(dn)) {
+		u32 tmp;
+	
+		tmp = __raw_readl(MISC_SATA_POWER_MODE);
+		tmp |= 0x1 << 16; /* Disable SATA PHY 0 from SLUMBER Mode */
+		tmp |= 0x1 << 17; /* Disable SATA PHY 1 from SLUMBER Mode */
+		__raw_writel(tmp, MISC_SATA_POWER_MODE);
+	
+		/* Enable SATA PHY */
+		cns3xxx_pwr_power_up(0x1 << PM_PLL_HM_PD_CTRL_REG_OFFSET_SATA_PHY0);
+		cns3xxx_pwr_power_up(0x1 << PM_PLL_HM_PD_CTRL_REG_OFFSET_SATA_PHY1);
+	
+		/* Enable SATA Clock */
+		cns3xxx_pwr_clk_en(0x1 << PM_CLK_GATE_REG_OFFSET_SATA);
+	
+		/* De-Asscer SATA Reset */
+		cns3xxx_pwr_soft_rst(CNS3XXX_PWR_SOFTWARE_RST(SATA));
+	}
+
+	dn = of_find_compatible_node(NULL, NULL, "cavium,cns3420-sdhci");
+	if (of_device_is_available(dn)) {
+		u32 __iomem *gpioa = IOMEM(CNS3XXX_MISC_BASE_VIRT + 0x0014);
+		u32 gpioa_pins = __raw_readl(gpioa);
+	
+		/* MMC/SD pins share with GPIOA */
+		gpioa_pins |= 0x1fff0004;
+		__raw_writel(gpioa_pins, gpioa);
+	
+		cns3xxx_pwr_clk_en(CNS3XXX_PWR_CLK_EN(SDIO));
+		cns3xxx_pwr_soft_rst(CNS3XXX_PWR_SOFTWARE_RST(SDIO));
+	}
+
+	pm_power_off = cns3xxx_power_off;
+
+	of_platform_populate(NULL, of_default_bus_match_table,
+                        cns3xxx_auxdata, NULL);
+}
+
+static const char *cns3xxx_dt_compat[] __initdata = {
+	"cavium,cns3410",
+	"cavium,cns3420",
+	NULL,
+};
+
+DT_MACHINE_START(CNS3XXX_DT, "Cavium Networks CNS3xxx")
+	.dt_compat	= cns3xxx_dt_compat,
+	.nr_irqs	= NR_IRQS_CNS3XXX,
+	.map_io		= cns3xxx_map_io,
+	.init_irq	= cns3xxx_init_irq,
+	.init_time	= cns3xxx_timer_init,
+	.init_machine	= cns3xxx_init,
+	.restart	= cns3xxx_restart,
+MACHINE_END
diff --git a/arch/arm/mach-cns3xxx/devices.c b/arch/arm/mach-cns3xxx/devices.c
index 1e40c99..7da78a2 100644
--- a/arch/arm/mach-cns3xxx/devices.c
+++ b/arch/arm/mach-cns3xxx/devices.c
@@ -16,9 +16,8 @@
 #include <linux/compiler.h>
 #include <linux/dma-mapping.h>
 #include <linux/platform_device.h>
-#include <mach/cns3xxx.h>
-#include <mach/irqs.h>
-#include <mach/pm.h>
+#include "cns3xxx.h"
+#include "pm.h"
 #include "core.h"
 #include "devices.h"
 
diff --git a/arch/arm/mach-cns3xxx/include/mach/cns3xxx.h b/arch/arm/mach-cns3xxx/include/mach/cns3xxx.h
deleted file mode 100644
index 191c8e5..0000000
--- a/arch/arm/mach-cns3xxx/include/mach/cns3xxx.h
+++ /dev/null
@@ -1,632 +0,0 @@
-/*
- * 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_BOARD_CNS3XXXH
-#define __MACH_BOARD_CNS3XXXH
-
-/*
- * Memory map
- */
-#define CNS3XXX_FLASH_BASE			0x10000000	/* Flash/SRAM Memory Bank 0 */
-#define CNS3XXX_FLASH_SIZE			SZ_256M
-
-#define CNS3XXX_DDR2SDRAM_BASE			0x20000000	/* DDR2 SDRAM Memory */
-
-#define CNS3XXX_SPI_FLASH_BASE			0x60000000	/* SPI Serial Flash Memory */
-
-#define CNS3XXX_SWITCH_BASE			0x70000000	/* Switch and HNAT Control */
-#define CNS3XXX_SWITCH_BASE_VIRT		0xFFF00000
-
-#define CNS3XXX_PPE_BASE			0x70001000	/* HANT	*/
-#define CNS3XXX_PPE_BASE_VIRT			0xFFF50000
-
-#define CNS3XXX_EMBEDDED_SRAM_BASE		0x70002000	/* HANT Embedded SRAM */
-#define CNS3XXX_EMBEDDED_SRAM_BASE_VIRT		0xFFF60000
-
-#define CNS3XXX_SSP_BASE			0x71000000	/* Synchronous Serial Port - SPI/PCM/I2C */
-#define CNS3XXX_SSP_BASE_VIRT			0xFFF01000
-
-#define CNS3XXX_DMC_BASE			0x72000000	/* DMC Control (DDR2 SDRAM) */
-#define CNS3XXX_DMC_BASE_VIRT			0xFFF02000
-
-#define CNS3XXX_SMC_BASE			0x73000000	/* SMC Control */
-#define CNS3XXX_SMC_BASE_VIRT			0xFFF03000
-
-#define SMC_MEMC_STATUS_OFFSET			0x000
-#define SMC_MEMIF_CFG_OFFSET			0x004
-#define SMC_MEMC_CFG_SET_OFFSET			0x008
-#define SMC_MEMC_CFG_CLR_OFFSET			0x00C
-#define SMC_DIRECT_CMD_OFFSET			0x010
-#define SMC_SET_CYCLES_OFFSET			0x014
-#define SMC_SET_OPMODE_OFFSET			0x018
-#define SMC_REFRESH_PERIOD_0_OFFSET		0x020
-#define SMC_REFRESH_PERIOD_1_OFFSET		0x024
-#define SMC_SRAM_CYCLES0_0_OFFSET		0x100
-#define SMC_NAND_CYCLES0_0_OFFSET		0x100
-#define SMC_OPMODE0_0_OFFSET			0x104
-#define SMC_SRAM_CYCLES0_1_OFFSET		0x120
-#define SMC_NAND_CYCLES0_1_OFFSET		0x120
-#define SMC_OPMODE0_1_OFFSET			0x124
-#define SMC_USER_STATUS_OFFSET			0x200
-#define SMC_USER_CONFIG_OFFSET			0x204
-#define SMC_ECC_STATUS_OFFSET			0x300
-#define SMC_ECC_MEMCFG_OFFSET			0x304
-#define SMC_ECC_MEMCOMMAND1_OFFSET		0x308
-#define SMC_ECC_MEMCOMMAND2_OFFSET		0x30C
-#define SMC_ECC_ADDR0_OFFSET			0x310
-#define SMC_ECC_ADDR1_OFFSET			0x314
-#define SMC_ECC_VALUE0_OFFSET			0x318
-#define SMC_ECC_VALUE1_OFFSET			0x31C
-#define SMC_ECC_VALUE2_OFFSET			0x320
-#define SMC_ECC_VALUE3_OFFSET			0x324
-#define SMC_PERIPH_ID_0_OFFSET			0xFE0
-#define SMC_PERIPH_ID_1_OFFSET			0xFE4
-#define SMC_PERIPH_ID_2_OFFSET			0xFE8
-#define SMC_PERIPH_ID_3_OFFSET			0xFEC
-#define SMC_PCELL_ID_0_OFFSET			0xFF0
-#define SMC_PCELL_ID_1_OFFSET			0xFF4
-#define SMC_PCELL_ID_2_OFFSET			0xFF8
-#define SMC_PCELL_ID_3_OFFSET			0xFFC
-
-#define CNS3XXX_GPIOA_BASE			0x74000000	/* GPIO port A */
-#define CNS3XXX_GPIOA_BASE_VIRT			0xFFF04000
-
-#define CNS3XXX_GPIOB_BASE			0x74800000	/* GPIO port B */
-#define CNS3XXX_GPIOB_BASE_VIRT			0xFFF05000
-
-#define CNS3XXX_RTC_BASE			0x75000000	/* Real Time Clock */
-#define CNS3XXX_RTC_BASE_VIRT			0xFFF06000
-
-#define RTC_SEC_OFFSET				0x00
-#define RTC_MIN_OFFSET				0x04
-#define RTC_HOUR_OFFSET				0x08
-#define RTC_DAY_OFFSET				0x0C
-#define RTC_SEC_ALM_OFFSET			0x10
-#define RTC_MIN_ALM_OFFSET			0x14
-#define RTC_HOUR_ALM_OFFSET			0x18
-#define RTC_REC_OFFSET				0x1C
-#define RTC_CTRL_OFFSET				0x20
-#define RTC_INTR_STS_OFFSET			0x34
-
-#define CNS3XXX_MISC_BASE			0x76000000	/* Misc Control */
-#define CNS3XXX_MISC_BASE_VIRT			0xFFF07000	/* Misc Control */
-
-#define CNS3XXX_PM_BASE				0x77000000	/* Power Management Control */
-#define CNS3XXX_PM_BASE_VIRT			0xFFF08000
-
-#define PM_CLK_GATE_OFFSET			0x00
-#define PM_SOFT_RST_OFFSET			0x04
-#define PM_HS_CFG_OFFSET			0x08
-#define PM_CACTIVE_STA_OFFSET			0x0C
-#define PM_PWR_STA_OFFSET			0x10
-#define PM_SYS_CLK_CTRL_OFFSET			0x14
-#define PM_PLL_LCD_I2S_CTRL_OFFSET		0x18
-#define PM_PLL_HM_PD_OFFSET			0x1C
-
-#define CNS3XXX_UART0_BASE			0x78000000	/* UART 0 */
-#define CNS3XXX_UART0_BASE_VIRT			0xFFF09000
-
-#define CNS3XXX_UART1_BASE			0x78400000	/* UART 1 */
-#define CNS3XXX_UART1_BASE_VIRT			0xFFF0A000
-
-#define CNS3XXX_UART2_BASE			0x78800000	/* UART 2 */
-#define CNS3XXX_UART2_BASE_VIRT			0xFFF0B000
-
-#define CNS3XXX_DMAC_BASE			0x79000000	/* Generic DMA Control */
-#define CNS3XXX_DMAC_BASE_VIRT			0xFFF0D000
-
-#define CNS3XXX_CORESIGHT_BASE			0x7A000000	/* CoreSight */
-#define CNS3XXX_CORESIGHT_BASE_VIRT		0xFFF0E000
-
-#define CNS3XXX_CRYPTO_BASE			0x7B000000	/* Crypto */
-#define CNS3XXX_CRYPTO_BASE_VIRT		0xFFF0F000
-
-#define CNS3XXX_I2S_BASE			0x7C000000	/* I2S */
-#define CNS3XXX_I2S_BASE_VIRT			0xFFF10000
-
-#define CNS3XXX_TIMER1_2_3_BASE			0x7C800000	/* Timer */
-#define CNS3XXX_TIMER1_2_3_BASE_VIRT		0xFFF10800
-
-#define TIMER1_COUNTER_OFFSET			0x00
-#define TIMER1_AUTO_RELOAD_OFFSET		0x04
-#define TIMER1_MATCH_V1_OFFSET			0x08
-#define TIMER1_MATCH_V2_OFFSET			0x0C
-
-#define TIMER2_COUNTER_OFFSET			0x10
-#define TIMER2_AUTO_RELOAD_OFFSET		0x14
-#define TIMER2_MATCH_V1_OFFSET			0x18
-#define TIMER2_MATCH_V2_OFFSET			0x1C
-
-#define TIMER1_2_CONTROL_OFFSET			0x30
-#define TIMER1_2_INTERRUPT_STATUS_OFFSET	0x34
-#define TIMER1_2_INTERRUPT_MASK_OFFSET		0x38
-
-#define TIMER_FREERUN_OFFSET			0x40
-#define TIMER_FREERUN_CONTROL_OFFSET		0x44
-
-#define CNS3XXX_HCIE_BASE			0x7D000000	/* HCIE Control */
-#define CNS3XXX_HCIE_BASE_VIRT			0xFFF30000
-
-#define CNS3XXX_RAID_BASE			0x7E000000	/* RAID Control */
-#define CNS3XXX_RAID_BASE_VIRT			0xFFF12000
-
-#define CNS3XXX_AXI_IXC_BASE			0x7F000000	/* AXI IXC */
-#define CNS3XXX_AXI_IXC_BASE_VIRT		0xFFF13000
-
-#define CNS3XXX_CLCD_BASE			0x80000000	/* LCD Control */
-#define CNS3XXX_CLCD_BASE_VIRT			0xFFF14000
-
-#define CNS3XXX_USBOTG_BASE			0x81000000	/* USB OTG Control */
-#define CNS3XXX_USBOTG_BASE_VIRT		0xFFF15000
-
-#define CNS3XXX_USB_BASE			0x82000000	/* USB Host Control */
-
-#define CNS3XXX_SATA2_BASE			0x83000000	/* SATA */
-#define CNS3XXX_SATA2_SIZE			SZ_16M
-#define CNS3XXX_SATA2_BASE_VIRT			0xFFF17000
-
-#define CNS3XXX_CAMERA_BASE			0x84000000	/* Camera Interface */
-#define CNS3XXX_CAMERA_BASE_VIRT		0xFFF18000
-
-#define CNS3XXX_SDIO_BASE			0x85000000	/* SDIO */
-#define CNS3XXX_SDIO_BASE_VIRT			0xFFF19000
-
-#define CNS3XXX_I2S_TDM_BASE			0x86000000	/* I2S TDM */
-#define CNS3XXX_I2S_TDM_BASE_VIRT		0xFFF1A000
-
-#define CNS3XXX_2DG_BASE			0x87000000	/* 2D Graphic Control */
-#define CNS3XXX_2DG_BASE_VIRT			0xFFF1B000
-
-#define CNS3XXX_USB_OHCI_BASE			0x88000000	/* USB OHCI */
-
-#define CNS3XXX_L2C_BASE			0x92000000	/* L2 Cache Control */
-#define CNS3XXX_L2C_BASE_VIRT			0xFFF27000
-
-#define CNS3XXX_PCIE0_MEM_BASE			0xA0000000	/* PCIe Port 0 IO/Memory Space */
-#define CNS3XXX_PCIE0_MEM_BASE_VIRT		0xE0000000
-
-#define CNS3XXX_PCIE0_HOST_BASE			0xAB000000	/* PCIe Port 0 RC Base */
-#define CNS3XXX_PCIE0_HOST_BASE_VIRT		0xE1000000
-
-#define CNS3XXX_PCIE0_IO_BASE			0xAC000000	/* PCIe Port 0 */
-#define CNS3XXX_PCIE0_IO_BASE_VIRT		0xE2000000
-
-#define CNS3XXX_PCIE0_CFG0_BASE			0xAD000000	/* PCIe Port 0 CFG Type 0 */
-#define CNS3XXX_PCIE0_CFG0_BASE_VIRT		0xE3000000
-
-#define CNS3XXX_PCIE0_CFG1_BASE			0xAE000000	/* PCIe Port 0 CFG Type 1 */
-#define CNS3XXX_PCIE0_CFG1_BASE_VIRT		0xE4000000
-
-#define CNS3XXX_PCIE0_MSG_BASE			0xAF000000	/* PCIe Port 0 Message Space */
-#define CNS3XXX_PCIE0_MSG_BASE_VIRT		0xE5000000
-
-#define CNS3XXX_PCIE1_MEM_BASE			0xB0000000	/* PCIe Port 1 IO/Memory Space */
-#define CNS3XXX_PCIE1_MEM_BASE_VIRT		0xE8000000
-
-#define CNS3XXX_PCIE1_HOST_BASE			0xBB000000	/* PCIe Port 1 RC Base */
-#define CNS3XXX_PCIE1_HOST_BASE_VIRT		0xE9000000
-
-#define CNS3XXX_PCIE1_IO_BASE			0xBC000000	/* PCIe Port 1 */
-#define CNS3XXX_PCIE1_IO_BASE_VIRT		0xEA000000
-
-#define CNS3XXX_PCIE1_CFG0_BASE			0xBD000000	/* PCIe Port 1 CFG Type 0 */
-#define CNS3XXX_PCIE1_CFG0_BASE_VIRT		0xEB000000
-
-#define CNS3XXX_PCIE1_CFG1_BASE			0xBE000000	/* PCIe Port 1 CFG Type 1 */
-#define CNS3XXX_PCIE1_CFG1_BASE_VIRT		0xEC000000
-
-#define CNS3XXX_PCIE1_MSG_BASE			0xBF000000	/* PCIe Port 1 Message Space */
-#define CNS3XXX_PCIE1_MSG_BASE_VIRT		0xED000000
-
-/*
- * Testchip peripheral and fpga gic regions
- */
-#define CNS3XXX_TC11MP_SCU_BASE			0x90000000	/* IRQ, Test chip */
-#define CNS3XXX_TC11MP_SCU_BASE_VIRT		0xFF000000
-
-#define CNS3XXX_TC11MP_GIC_CPU_BASE		0x90000100	/* Test chip interrupt controller CPU interface */
-#define CNS3XXX_TC11MP_GIC_CPU_BASE_VIRT	0xFF000100
-
-#define CNS3XXX_TC11MP_TWD_BASE			0x90000600
-#define CNS3XXX_TC11MP_TWD_BASE_VIRT		0xFF000600
-
-#define CNS3XXX_TC11MP_GIC_DIST_BASE		0x90001000	/* Test chip interrupt controller distributor */
-#define CNS3XXX_TC11MP_GIC_DIST_BASE_VIRT	0xFF001000
-
-#define CNS3XXX_TC11MP_L220_BASE		0x92002000	/* L220 registers */
-#define CNS3XXX_TC11MP_L220_BASE_VIRT		0xFF002000
-
-/*
- * Misc block
- */
-#define MISC_MEM_MAP(offs) (void __iomem *)(CNS3XXX_MISC_BASE_VIRT + (offs))
-
-#define MISC_MEMORY_REMAP_REG			MISC_MEM_MAP(0x00)
-#define MISC_CHIP_CONFIG_REG			MISC_MEM_MAP(0x04)
-#define MISC_DEBUG_PROBE_DATA_REG		MISC_MEM_MAP(0x08)
-#define MISC_DEBUG_PROBE_SELECTION_REG		MISC_MEM_MAP(0x0C)
-#define MISC_IO_PIN_FUNC_SELECTION_REG		MISC_MEM_MAP(0x10)
-#define MISC_GPIOA_PIN_ENABLE_REG		MISC_MEM_MAP(0x14)
-#define MISC_GPIOB_PIN_ENABLE_REG		MISC_MEM_MAP(0x18)
-#define MISC_IO_PAD_DRIVE_STRENGTH_CTRL_A	MISC_MEM_MAP(0x1C)
-#define MISC_IO_PAD_DRIVE_STRENGTH_CTRL_B	MISC_MEM_MAP(0x20)
-#define MISC_GPIOA_15_0_PULL_CTRL_REG		MISC_MEM_MAP(0x24)
-#define MISC_GPIOA_16_31_PULL_CTRL_REG		MISC_MEM_MAP(0x28)
-#define MISC_GPIOB_15_0_PULL_CTRL_REG		MISC_MEM_MAP(0x2C)
-#define MISC_GPIOB_16_31_PULL_CTRL_REG		MISC_MEM_MAP(0x30)
-#define MISC_IO_PULL_CTRL_REG			MISC_MEM_MAP(0x34)
-#define MISC_E_FUSE_31_0_REG			MISC_MEM_MAP(0x40)
-#define MISC_E_FUSE_63_32_REG			MISC_MEM_MAP(0x44)
-#define MISC_E_FUSE_95_64_REG			MISC_MEM_MAP(0x48)
-#define MISC_E_FUSE_127_96_REG			MISC_MEM_MAP(0x4C)
-#define MISC_SOFTWARE_TEST_1_REG		MISC_MEM_MAP(0x50)
-#define MISC_SOFTWARE_TEST_2_REG		MISC_MEM_MAP(0x54)
-
-#define MISC_SATA_POWER_MODE			MISC_MEM_MAP(0x310)
-
-#define MISC_USB_CFG_REG			MISC_MEM_MAP(0x800)
-#define MISC_USB_STS_REG			MISC_MEM_MAP(0x804)
-#define MISC_USBPHY00_CFG_REG			MISC_MEM_MAP(0x808)
-#define MISC_USBPHY01_CFG_REG			MISC_MEM_MAP(0x80c)
-#define MISC_USBPHY10_CFG_REG			MISC_MEM_MAP(0x810)
-#define MISC_USBPHY11_CFG_REG			MISC_MEM_MAP(0x814)
-
-#define MISC_PCIEPHY_CMCTL(x)			MISC_MEM_MAP(0x900 + (x) * 0x004)
-#define MISC_PCIEPHY_CTL(x)			MISC_MEM_MAP(0x940 + (x) * 0x100)
-#define MISC_PCIE_AXIS_AWMISC(x)		MISC_MEM_MAP(0x944 + (x) * 0x100)
-#define MISC_PCIE_AXIS_ARMISC(x)		MISC_MEM_MAP(0x948 + (x) * 0x100)
-#define MISC_PCIE_AXIS_RMISC(x)			MISC_MEM_MAP(0x94C + (x) * 0x100)
-#define MISC_PCIE_AXIS_BMISC(x)			MISC_MEM_MAP(0x950 + (x) * 0x100)
-#define MISC_PCIE_AXIM_RMISC(x)			MISC_MEM_MAP(0x954 + (x) * 0x100)
-#define MISC_PCIE_AXIM_BMISC(x)			MISC_MEM_MAP(0x958 + (x) * 0x100)
-#define MISC_PCIE_CTRL(x)			MISC_MEM_MAP(0x95C + (x) * 0x100)
-#define MISC_PCIE_PM_DEBUG(x)			MISC_MEM_MAP(0x960 + (x) * 0x100)
-#define MISC_PCIE_RFC_DEBUG(x)			MISC_MEM_MAP(0x964 + (x) * 0x100)
-#define MISC_PCIE_CXPL_DEBUGL(x)		MISC_MEM_MAP(0x968 + (x) * 0x100)
-#define MISC_PCIE_CXPL_DEBUGH(x)		MISC_MEM_MAP(0x96C + (x) * 0x100)
-#define MISC_PCIE_DIAG_DEBUGH(x)		MISC_MEM_MAP(0x970 + (x) * 0x100)
-#define MISC_PCIE_W1CLR(x)			MISC_MEM_MAP(0x974 + (x) * 0x100)
-#define MISC_PCIE_INT_MASK(x)			MISC_MEM_MAP(0x978 + (x) * 0x100)
-#define MISC_PCIE_INT_STATUS(x)			MISC_MEM_MAP(0x97C + (x) * 0x100)
-
-/*
- * Power management and clock control
- */
-#define PMU_MEM_MAP(offs) (void __iomem *)(CNS3XXX_PM_BASE_VIRT + (offs))
-
-#define PM_CLK_GATE_REG					PMU_MEM_MAP(0x000)
-#define PM_SOFT_RST_REG					PMU_MEM_MAP(0x004)
-#define PM_HS_CFG_REG					PMU_MEM_MAP(0x008)
-#define PM_CACTIVE_STA_REG				PMU_MEM_MAP(0x00C)
-#define PM_PWR_STA_REG					PMU_MEM_MAP(0x010)
-#define PM_CLK_CTRL_REG					PMU_MEM_MAP(0x014)
-#define PM_PLL_LCD_I2S_CTRL_REG				PMU_MEM_MAP(0x018)
-#define PM_PLL_HM_PD_CTRL_REG				PMU_MEM_MAP(0x01C)
-#define PM_REGULAT_CTRL_REG				PMU_MEM_MAP(0x020)
-#define PM_WDT_CTRL_REG					PMU_MEM_MAP(0x024)
-#define PM_WU_CTRL0_REG					PMU_MEM_MAP(0x028)
-#define PM_WU_CTRL1_REG					PMU_MEM_MAP(0x02C)
-#define PM_CSR_REG					PMU_MEM_MAP(0x030)
-
-/* PM_CLK_GATE_REG */
-#define PM_CLK_GATE_REG_OFFSET_SDIO			(25)
-#define PM_CLK_GATE_REG_OFFSET_GPU			(24)
-#define PM_CLK_GATE_REG_OFFSET_CIM			(23)
-#define PM_CLK_GATE_REG_OFFSET_LCDC			(22)
-#define PM_CLK_GATE_REG_OFFSET_I2S			(21)
-#define PM_CLK_GATE_REG_OFFSET_RAID			(20)
-#define PM_CLK_GATE_REG_OFFSET_SATA			(19)
-#define PM_CLK_GATE_REG_OFFSET_PCIE(x)			(17 + (x))
-#define PM_CLK_GATE_REG_OFFSET_USB_HOST			(16)
-#define PM_CLK_GATE_REG_OFFSET_USB_OTG			(15)
-#define PM_CLK_GATE_REG_OFFSET_TIMER			(14)
-#define PM_CLK_GATE_REG_OFFSET_CRYPTO			(13)
-#define PM_CLK_GATE_REG_OFFSET_HCIE			(12)
-#define PM_CLK_GATE_REG_OFFSET_SWITCH			(11)
-#define PM_CLK_GATE_REG_OFFSET_GPIO			(10)
-#define PM_CLK_GATE_REG_OFFSET_UART3			(9)
-#define PM_CLK_GATE_REG_OFFSET_UART2			(8)
-#define PM_CLK_GATE_REG_OFFSET_UART1			(7)
-#define PM_CLK_GATE_REG_OFFSET_RTC			(5)
-#define PM_CLK_GATE_REG_OFFSET_GDMA			(4)
-#define PM_CLK_GATE_REG_OFFSET_SPI_PCM_I2C		(3)
-#define PM_CLK_GATE_REG_OFFSET_SMC_NFI			(1)
-#define PM_CLK_GATE_REG_MASK				(0x03FFFFBA)
-
-/* PM_SOFT_RST_REG */
-#define PM_SOFT_RST_REG_OFFST_WARM_RST_FLAG		(31)
-#define PM_SOFT_RST_REG_OFFST_CPU1			(29)
-#define PM_SOFT_RST_REG_OFFST_CPU0			(28)
-#define PM_SOFT_RST_REG_OFFST_SDIO			(25)
-#define PM_SOFT_RST_REG_OFFST_GPU			(24)
-#define PM_SOFT_RST_REG_OFFST_CIM			(23)
-#define PM_SOFT_RST_REG_OFFST_LCDC			(22)
-#define PM_SOFT_RST_REG_OFFST_I2S			(21)
-#define PM_SOFT_RST_REG_OFFST_RAID			(20)
-#define PM_SOFT_RST_REG_OFFST_SATA			(19)
-#define PM_SOFT_RST_REG_OFFST_PCIE(x)			(17 + (x))
-#define PM_SOFT_RST_REG_OFFST_USB_HOST			(16)
-#define PM_SOFT_RST_REG_OFFST_USB_OTG			(15)
-#define PM_SOFT_RST_REG_OFFST_TIMER			(14)
-#define PM_SOFT_RST_REG_OFFST_CRYPTO			(13)
-#define PM_SOFT_RST_REG_OFFST_HCIE			(12)
-#define PM_SOFT_RST_REG_OFFST_SWITCH			(11)
-#define PM_SOFT_RST_REG_OFFST_GPIO			(10)
-#define PM_SOFT_RST_REG_OFFST_UART3			(9)
-#define PM_SOFT_RST_REG_OFFST_UART2			(8)
-#define PM_SOFT_RST_REG_OFFST_UART1			(7)
-#define PM_SOFT_RST_REG_OFFST_RTC			(5)
-#define PM_SOFT_RST_REG_OFFST_GDMA			(4)
-#define PM_SOFT_RST_REG_OFFST_SPI_PCM_I2C		(3)
-#define PM_SOFT_RST_REG_OFFST_DMC			(2)
-#define PM_SOFT_RST_REG_OFFST_SMC_NFI			(1)
-#define PM_SOFT_RST_REG_OFFST_GLOBAL			(0)
-#define PM_SOFT_RST_REG_MASK				(0xF3FFFFBF)
-
-/* PMHS_CFG_REG */
-#define PM_HS_CFG_REG_OFFSET_SDIO			(25)
-#define PM_HS_CFG_REG_OFFSET_GPU			(24)
-#define PM_HS_CFG_REG_OFFSET_CIM			(23)
-#define PM_HS_CFG_REG_OFFSET_LCDC			(22)
-#define PM_HS_CFG_REG_OFFSET_I2S			(21)
-#define PM_HS_CFG_REG_OFFSET_RAID			(20)
-#define PM_HS_CFG_REG_OFFSET_SATA			(19)
-#define PM_HS_CFG_REG_OFFSET_PCIE1			(18)
-#define PM_HS_CFG_REG_OFFSET_PCIE0			(17)
-#define PM_HS_CFG_REG_OFFSET_USB_HOST			(16)
-#define PM_HS_CFG_REG_OFFSET_USB_OTG			(15)
-#define PM_HS_CFG_REG_OFFSET_TIMER			(14)
-#define PM_HS_CFG_REG_OFFSET_CRYPTO			(13)
-#define PM_HS_CFG_REG_OFFSET_HCIE			(12)
-#define PM_HS_CFG_REG_OFFSET_SWITCH			(11)
-#define PM_HS_CFG_REG_OFFSET_GPIO			(10)
-#define PM_HS_CFG_REG_OFFSET_UART3			(9)
-#define PM_HS_CFG_REG_OFFSET_UART2			(8)
-#define PM_HS_CFG_REG_OFFSET_UART1			(7)
-#define PM_HS_CFG_REG_OFFSET_RTC			(5)
-#define PM_HS_CFG_REG_OFFSET_GDMA			(4)
-#define PM_HS_CFG_REG_OFFSET_SPI_PCM_I2S		(3)
-#define PM_HS_CFG_REG_OFFSET_DMC			(2)
-#define PM_HS_CFG_REG_OFFSET_SMC_NFI			(1)
-#define PM_HS_CFG_REG_MASK				(0x03FFFFBE)
-#define PM_HS_CFG_REG_MASK_SUPPORT			(0x01100806)
-
-/* PM_CACTIVE_STA_REG */
-#define PM_CACTIVE_STA_REG_OFFSET_SDIO			(25)
-#define PM_CACTIVE_STA_REG_OFFSET_GPU			(24)
-#define PM_CACTIVE_STA_REG_OFFSET_CIM			(23)
-#define PM_CACTIVE_STA_REG_OFFSET_LCDC			(22)
-#define PM_CACTIVE_STA_REG_OFFSET_I2S			(21)
-#define PM_CACTIVE_STA_REG_OFFSET_RAID			(20)
-#define PM_CACTIVE_STA_REG_OFFSET_SATA			(19)
-#define PM_CACTIVE_STA_REG_OFFSET_PCIE1			(18)
-#define PM_CACTIVE_STA_REG_OFFSET_PCIE0			(17)
-#define PM_CACTIVE_STA_REG_OFFSET_USB_HOST		(16)
-#define PM_CACTIVE_STA_REG_OFFSET_USB_OTG		(15)
-#define PM_CACTIVE_STA_REG_OFFSET_TIMER			(14)
-#define PM_CACTIVE_STA_REG_OFFSET_CRYPTO		(13)
-#define PM_CACTIVE_STA_REG_OFFSET_HCIE			(12)
-#define PM_CACTIVE_STA_REG_OFFSET_SWITCH		(11)
-#define PM_CACTIVE_STA_REG_OFFSET_GPIO			(10)
-#define PM_CACTIVE_STA_REG_OFFSET_UART3			(9)
-#define PM_CACTIVE_STA_REG_OFFSET_UART2			(8)
-#define PM_CACTIVE_STA_REG_OFFSET_UART1			(7)
-#define PM_CACTIVE_STA_REG_OFFSET_RTC			(5)
-#define PM_CACTIVE_STA_REG_OFFSET_GDMA			(4)
-#define PM_CACTIVE_STA_REG_OFFSET_SPI_PCM_I2S		(3)
-#define PM_CACTIVE_STA_REG_OFFSET_DMC			(2)
-#define PM_CACTIVE_STA_REG_OFFSET_SMC_NFI		(1)
-#define PM_CACTIVE_STA_REG_MASK				(0x03FFFFBE)
-
-/* PM_PWR_STA_REG */
-#define PM_PWR_STA_REG_REG_OFFSET_SDIO			(25)
-#define PM_PWR_STA_REG_REG_OFFSET_GPU			(24)
-#define PM_PWR_STA_REG_REG_OFFSET_CIM			(23)
-#define PM_PWR_STA_REG_REG_OFFSET_LCDC			(22)
-#define PM_PWR_STA_REG_REG_OFFSET_I2S			(21)
-#define PM_PWR_STA_REG_REG_OFFSET_RAID			(20)
-#define PM_PWR_STA_REG_REG_OFFSET_SATA			(19)
-#define PM_PWR_STA_REG_REG_OFFSET_PCIE1			(18)
-#define PM_PWR_STA_REG_REG_OFFSET_PCIE0			(17)
-#define PM_PWR_STA_REG_REG_OFFSET_USB_HOST		(16)
-#define PM_PWR_STA_REG_REG_OFFSET_USB_OTG		(15)
-#define PM_PWR_STA_REG_REG_OFFSET_TIMER			(14)
-#define PM_PWR_STA_REG_REG_OFFSET_CRYPTO		(13)
-#define PM_PWR_STA_REG_REG_OFFSET_HCIE			(12)
-#define PM_PWR_STA_REG_REG_OFFSET_SWITCH		(11)
-#define PM_PWR_STA_REG_REG_OFFSET_GPIO			(10)
-#define PM_PWR_STA_REG_REG_OFFSET_UART3			(9)
-#define PM_PWR_STA_REG_REG_OFFSET_UART2			(8)
-#define PM_PWR_STA_REG_REG_OFFSET_UART1			(7)
-#define PM_PWR_STA_REG_REG_OFFSET_RTC			(5)
-#define PM_PWR_STA_REG_REG_OFFSET_GDMA			(4)
-#define PM_PWR_STA_REG_REG_OFFSET_SPI_PCM_I2S		(3)
-#define PM_PWR_STA_REG_REG_OFFSET_DMC			(2)
-#define PM_PWR_STA_REG_REG_OFFSET_SMC_NFI		(1)
-#define PM_PWR_STA_REG_REG_MASK				(0x03FFFFBE)
-
-/* PM_CLK_CTRL_REG */
-#define PM_CLK_CTRL_REG_OFFSET_I2S_MCLK			(31)
-#define PM_CLK_CTRL_REG_OFFSET_DDR2_CHG_EN		(30)
-#define PM_CLK_CTRL_REG_OFFSET_PCIE_REF1_EN		(29)
-#define PM_CLK_CTRL_REG_OFFSET_PCIE_REF0_EN		(28)
-#define PM_CLK_CTRL_REG_OFFSET_TIMER_SIM_MODE		(27)
-#define PM_CLK_CTRL_REG_OFFSET_I2SCLK_DIV		(24)
-#define PM_CLK_CTRL_REG_OFFSET_I2SCLK_SEL		(22)
-#define PM_CLK_CTRL_REG_OFFSET_CLKOUT_DIV		(20)
-#define PM_CLK_CTRL_REG_OFFSET_CLKOUT_SEL		(16)
-#define PM_CLK_CTRL_REG_OFFSET_MDC_DIV			(14)
-#define PM_CLK_CTRL_REG_OFFSET_CRYPTO_CLK_SEL		(12)
-#define PM_CLK_CTRL_REG_OFFSET_CPU_PWR_MODE		(9)
-#define PM_CLK_CTRL_REG_OFFSET_PLL_DDR2_SEL		(7)
-#define PM_CLK_CTRL_REG_OFFSET_DIV_IMMEDIATE		(6)
-#define PM_CLK_CTRL_REG_OFFSET_CPU_CLK_DIV		(4)
-#define PM_CLK_CTRL_REG_OFFSET_PLL_CPU_SEL		(0)
-
-#define PM_CPU_CLK_DIV(DIV) { \
-	PM_CLK_CTRL_REG &= ~((0x3) << PM_CLK_CTRL_REG_OFFSET_CPU_CLK_DIV); \
-	PM_CLK_CTRL_REG |= (((DIV)&0x3) << PM_CLK_CTRL_REG_OFFSET_CPU_CLK_DIV); \
-}
-
-#define PM_PLL_CPU_SEL(CPU) { \
-	PM_CLK_CTRL_REG &= ~((0xF) << PM_CLK_CTRL_REG_OFFSET_PLL_CPU_SEL); \
-	PM_CLK_CTRL_REG |= (((CPU)&0xF) << PM_CLK_CTRL_REG_OFFSET_PLL_CPU_SEL); \
-}
-
-/* PM_PLL_LCD_I2S_CTRL_REG */
-#define PM_PLL_LCD_I2S_CTRL_REG_OFFSET_MCLK_SMC_DIV	(22)
-#define PM_PLL_LCD_I2S_CTRL_REG_OFFSET_R_SEL		(17)
-#define PM_PLL_LCD_I2S_CTRL_REG_OFFSET_PLL_LCD_P	(11)
-#define PM_PLL_LCD_I2S_CTRL_REG_OFFSET_PLL_LCD_M	(3)
-#define PM_PLL_LCD_I2S_CTRL_REG_OFFSET_PLL_LCD_S	(0)
-
-/* PM_PLL_HM_PD_CTRL_REG */
-#define PM_PLL_HM_PD_CTRL_REG_OFFSET_SATA_PHY1		(11)
-#define PM_PLL_HM_PD_CTRL_REG_OFFSET_SATA_PHY0		(10)
-#define PM_PLL_HM_PD_CTRL_REG_OFFSET_PLL_I2SCD		(6)
-#define PM_PLL_HM_PD_CTRL_REG_OFFSET_PLL_I2S		(5)
-#define PM_PLL_HM_PD_CTRL_REG_OFFSET_PLL_LCD		(4)
-#define PM_PLL_HM_PD_CTRL_REG_OFFSET_PLL_USB		(3)
-#define PM_PLL_HM_PD_CTRL_REG_OFFSET_PLL_RGMII		(2)
-#define PM_PLL_HM_PD_CTRL_REG_MASK			(0x00000C7C)
-
-/* PM_WDT_CTRL_REG */
-#define PM_WDT_CTRL_REG_OFFSET_RESET_CPU_ONLY		(0)
-
-/* PM_CSR_REG - Clock Scaling Register*/
-#define PM_CSR_REG_OFFSET_CSR_EN			(30)
-#define PM_CSR_REG_OFFSET_CSR_NUM			(0)
-
-#define CNS3XXX_PWR_CLK_EN(BLOCK) (0x1<<PM_CLK_GATE_REG_OFFSET_##BLOCK)
-
-/* Software reset*/
-#define CNS3XXX_PWR_SOFTWARE_RST(BLOCK) (0x1<<PM_SOFT_RST_REG_OFFST_##BLOCK)
-
-/*
- * CNS3XXX support several power saving mode as following,
- * DFS, IDLE, HALT, DOZE, SLEEP, Hibernate
- */
-#define CNS3XXX_PWR_CPU_MODE_DFS			(0)
-#define CNS3XXX_PWR_CPU_MODE_IDLE			(1)
-#define CNS3XXX_PWR_CPU_MODE_HALT			(2)
-#define CNS3XXX_PWR_CPU_MODE_DOZE			(3)
-#define CNS3XXX_PWR_CPU_MODE_SLEEP			(4)
-#define CNS3XXX_PWR_CPU_MODE_HIBERNATE			(5)
-
-#define CNS3XXX_PWR_PLL(BLOCK)	(0x1<<PM_PLL_HM_PD_CTRL_REG_OFFSET_##BLOCK)
-#define CNS3XXX_PWR_PLL_ALL	PM_PLL_HM_PD_CTRL_REG_MASK
-
-/* Change CPU frequency and divider */
-#define CNS3XXX_PWR_PLL_CPU_300MHZ			(0)
-#define CNS3XXX_PWR_PLL_CPU_333MHZ			(1)
-#define CNS3XXX_PWR_PLL_CPU_366MHZ			(2)
-#define CNS3XXX_PWR_PLL_CPU_400MHZ			(3)
-#define CNS3XXX_PWR_PLL_CPU_433MHZ			(4)
-#define CNS3XXX_PWR_PLL_CPU_466MHZ			(5)
-#define CNS3XXX_PWR_PLL_CPU_500MHZ			(6)
-#define CNS3XXX_PWR_PLL_CPU_533MHZ			(7)
-#define CNS3XXX_PWR_PLL_CPU_566MHZ			(8)
-#define CNS3XXX_PWR_PLL_CPU_600MHZ			(9)
-#define CNS3XXX_PWR_PLL_CPU_633MHZ			(10)
-#define CNS3XXX_PWR_PLL_CPU_666MHZ			(11)
-#define CNS3XXX_PWR_PLL_CPU_700MHZ			(12)
-
-#define CNS3XXX_PWR_CPU_CLK_DIV_BY1			(0)
-#define CNS3XXX_PWR_CPU_CLK_DIV_BY2			(1)
-#define CNS3XXX_PWR_CPU_CLK_DIV_BY4			(2)
-
-/* Change DDR2 frequency */
-#define CNS3XXX_PWR_PLL_DDR2_200MHZ			(0)
-#define CNS3XXX_PWR_PLL_DDR2_266MHZ			(1)
-#define CNS3XXX_PWR_PLL_DDR2_333MHZ			(2)
-#define CNS3XXX_PWR_PLL_DDR2_400MHZ			(3)
-
-void cns3xxx_pwr_soft_rst(unsigned int block);
-void cns3xxx_pwr_clk_en(unsigned int block);
-int cns3xxx_cpu_clock(void);
-
-/*
- * ARM11 MPCore interrupt sources (primary GIC)
- */
-#define IRQ_CNS3XXX_PMU			(IRQ_TC11MP_GIC_START + 0)
-#define IRQ_CNS3XXX_SDIO		(IRQ_TC11MP_GIC_START + 1)
-#define IRQ_CNS3XXX_L2CC		(IRQ_TC11MP_GIC_START + 2)
-#define IRQ_CNS3XXX_RTC			(IRQ_TC11MP_GIC_START + 3)
-#define IRQ_CNS3XXX_I2S			(IRQ_TC11MP_GIC_START + 4)
-#define IRQ_CNS3XXX_PCM			(IRQ_TC11MP_GIC_START + 5)
-#define IRQ_CNS3XXX_SPI			(IRQ_TC11MP_GIC_START + 6)
-#define IRQ_CNS3XXX_I2C			(IRQ_TC11MP_GIC_START + 7)
-#define IRQ_CNS3XXX_CIM			(IRQ_TC11MP_GIC_START + 8)
-#define IRQ_CNS3XXX_GPU			(IRQ_TC11MP_GIC_START + 9)
-#define IRQ_CNS3XXX_LCD			(IRQ_TC11MP_GIC_START + 10)
-#define IRQ_CNS3XXX_GPIOA		(IRQ_TC11MP_GIC_START + 11)
-#define IRQ_CNS3XXX_GPIOB		(IRQ_TC11MP_GIC_START + 12)
-#define IRQ_CNS3XXX_UART0		(IRQ_TC11MP_GIC_START + 13)
-#define IRQ_CNS3XXX_UART1		(IRQ_TC11MP_GIC_START + 14)
-#define IRQ_CNS3XXX_UART2		(IRQ_TC11MP_GIC_START + 15)
-#define IRQ_CNS3XXX_ARM11		(IRQ_TC11MP_GIC_START + 16)
-
-#define IRQ_CNS3XXX_SW_STATUS		(IRQ_TC11MP_GIC_START + 17)
-#define IRQ_CNS3XXX_SW_R0TXC		(IRQ_TC11MP_GIC_START + 18)
-#define IRQ_CNS3XXX_SW_R0RXC		(IRQ_TC11MP_GIC_START + 19)
-#define IRQ_CNS3XXX_SW_R0QE		(IRQ_TC11MP_GIC_START + 20)
-#define IRQ_CNS3XXX_SW_R0QF		(IRQ_TC11MP_GIC_START + 21)
-#define IRQ_CNS3XXX_SW_R1TXC		(IRQ_TC11MP_GIC_START + 22)
-#define IRQ_CNS3XXX_SW_R1RXC		(IRQ_TC11MP_GIC_START + 23)
-#define IRQ_CNS3XXX_SW_R1QE		(IRQ_TC11MP_GIC_START + 24)
-#define IRQ_CNS3XXX_SW_R1QF		(IRQ_TC11MP_GIC_START + 25)
-#define IRQ_CNS3XXX_SW_PPE		(IRQ_TC11MP_GIC_START + 26)
-
-#define IRQ_CNS3XXX_CRYPTO		(IRQ_TC11MP_GIC_START + 27)
-#define IRQ_CNS3XXX_HCIE		(IRQ_TC11MP_GIC_START + 28)
-#define IRQ_CNS3XXX_PCIE0_DEVICE	(IRQ_TC11MP_GIC_START + 29)
-#define IRQ_CNS3XXX_PCIE1_DEVICE	(IRQ_TC11MP_GIC_START + 30)
-#define IRQ_CNS3XXX_USB_OTG		(IRQ_TC11MP_GIC_START + 31)
-#define IRQ_CNS3XXX_USB_EHCI		(IRQ_TC11MP_GIC_START + 32)
-#define IRQ_CNS3XXX_SATA		(IRQ_TC11MP_GIC_START + 33)
-#define IRQ_CNS3XXX_RAID		(IRQ_TC11MP_GIC_START + 34)
-#define IRQ_CNS3XXX_SMC			(IRQ_TC11MP_GIC_START + 35)
-
-#define IRQ_CNS3XXX_DMAC_ABORT		(IRQ_TC11MP_GIC_START + 36)
-#define IRQ_CNS3XXX_DMAC0		(IRQ_TC11MP_GIC_START + 37)
-#define IRQ_CNS3XXX_DMAC1		(IRQ_TC11MP_GIC_START + 38)
-#define IRQ_CNS3XXX_DMAC2		(IRQ_TC11MP_GIC_START + 39)
-#define IRQ_CNS3XXX_DMAC3		(IRQ_TC11MP_GIC_START + 40)
-#define IRQ_CNS3XXX_DMAC4		(IRQ_TC11MP_GIC_START + 41)
-#define IRQ_CNS3XXX_DMAC5		(IRQ_TC11MP_GIC_START + 42)
-#define IRQ_CNS3XXX_DMAC6		(IRQ_TC11MP_GIC_START + 43)
-#define IRQ_CNS3XXX_DMAC7		(IRQ_TC11MP_GIC_START + 44)
-#define IRQ_CNS3XXX_DMAC8		(IRQ_TC11MP_GIC_START + 45)
-#define IRQ_CNS3XXX_DMAC9		(IRQ_TC11MP_GIC_START + 46)
-#define IRQ_CNS3XXX_DMAC10		(IRQ_TC11MP_GIC_START + 47)
-#define IRQ_CNS3XXX_DMAC11		(IRQ_TC11MP_GIC_START + 48)
-#define IRQ_CNS3XXX_DMAC12		(IRQ_TC11MP_GIC_START + 49)
-#define IRQ_CNS3XXX_DMAC13		(IRQ_TC11MP_GIC_START + 50)
-#define IRQ_CNS3XXX_DMAC14		(IRQ_TC11MP_GIC_START + 51)
-#define IRQ_CNS3XXX_DMAC15		(IRQ_TC11MP_GIC_START + 52)
-#define IRQ_CNS3XXX_DMAC16		(IRQ_TC11MP_GIC_START + 53)
-#define IRQ_CNS3XXX_DMAC17		(IRQ_TC11MP_GIC_START + 54)
-
-#define IRQ_CNS3XXX_PCIE0_RC		(IRQ_TC11MP_GIC_START + 55)
-#define IRQ_CNS3XXX_PCIE1_RC		(IRQ_TC11MP_GIC_START + 56)
-#define IRQ_CNS3XXX_TIMER0		(IRQ_TC11MP_GIC_START + 57)
-#define IRQ_CNS3XXX_TIMER1		(IRQ_TC11MP_GIC_START + 58)
-#define IRQ_CNS3XXX_USB_OHCI		(IRQ_TC11MP_GIC_START + 59)
-#define IRQ_CNS3XXX_TIMER2		(IRQ_TC11MP_GIC_START + 60)
-#define IRQ_CNS3XXX_EXTERNAL_PIN0	(IRQ_TC11MP_GIC_START + 61)
-#define IRQ_CNS3XXX_EXTERNAL_PIN1	(IRQ_TC11MP_GIC_START + 62)
-#define IRQ_CNS3XXX_EXTERNAL_PIN2	(IRQ_TC11MP_GIC_START + 63)
-
-#define NR_IRQS_CNS3XXX			(IRQ_TC11MP_GIC_START + 64)
-
-#if !defined(NR_IRQS) || (NR_IRQS < NR_IRQS_CNS3XXX)
-#undef NR_IRQS
-#define NR_IRQS				NR_IRQS_CNS3XXX
-#endif
-
-#endif	/* __MACH_BOARD_CNS3XXX_H */
diff --git a/arch/arm/mach-cns3xxx/include/mach/debug-macro.S b/arch/arm/mach-cns3xxx/include/mach/debug-macro.S
deleted file mode 100644
index d04c150..0000000
--- a/arch/arm/mach-cns3xxx/include/mach/debug-macro.S
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Debugging macro include header
- *
- * Copyright 1994-1999 Russell King
- * Copyright 2008 Cavium Networks
- * Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
- *
- * 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.
- */
-
-		.macro	addruart,rp,rv,tmp
-		mov	\rp, #0x00009000
-		orr	\rv, \rp, #0xf0000000	@ virtual base
-		orr	\rp, \rp, #0x10000000
-		.endm
-
-#include <asm/hardware/debug-pl01x.S>
diff --git a/arch/arm/mach-cns3xxx/include/mach/irqs.h b/arch/arm/mach-cns3xxx/include/mach/irqs.h
deleted file mode 100644
index 2ab96f8..0000000
--- a/arch/arm/mach-cns3xxx/include/mach/irqs.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright 2000 Deep Blue Solutions Ltd.
- * 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_IRQS_H
-#define __MACH_IRQS_H
-
-#define IRQ_LOCALTIMER		29
-#define IRQ_LOCALWDOG		30
-#define IRQ_TC11MP_GIC_START	32
-
-#include <mach/cns3xxx.h>
-
-#ifndef NR_IRQS
-#error "NR_IRQS not defined by the board-specific files"
-#endif
-
-#endif
diff --git a/arch/arm/mach-cns3xxx/include/mach/pm.h b/arch/arm/mach-cns3xxx/include/mach/pm.h
deleted file mode 100644
index c2588cc..0000000
--- a/arch/arm/mach-cns3xxx/include/mach/pm.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright 2000 Deep Blue Solutions Ltd
- * Copyright 2004 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 __CNS3XXX_PM_H
-#define __CNS3XXX_PM_H
-
-#include <linux/atomic.h>
-
-void cns3xxx_pwr_clk_en(unsigned int block);
-void cns3xxx_pwr_clk_dis(unsigned int block);
-void cns3xxx_pwr_power_up(unsigned int block);
-void cns3xxx_pwr_power_down(unsigned int block);
-
-extern atomic_t usb_pwr_ref;
-
-#endif /* __CNS3XXX_PM_H */
diff --git a/arch/arm/mach-cns3xxx/include/mach/timex.h b/arch/arm/mach-cns3xxx/include/mach/timex.h
deleted file mode 100644
index 1fd0421..0000000
--- a/arch/arm/mach-cns3xxx/include/mach/timex.h
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- * Cavium Networks architecture timex specifications
- *
- * 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.
- */
-
-#define CLOCK_TICK_RATE		(50000000 / 16)
diff --git a/arch/arm/mach-cns3xxx/include/mach/uncompress.h b/arch/arm/mach-cns3xxx/include/mach/uncompress.h
deleted file mode 100644
index 7a030b9..0000000
--- a/arch/arm/mach-cns3xxx/include/mach/uncompress.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * 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.
- */
-
-#include <asm/mach-types.h>
-#include <mach/cns3xxx.h>
-
-#define AMBA_UART_DR(base)	(*(volatile unsigned char *)((base) + 0x00))
-#define AMBA_UART_LCRH(base)	(*(volatile unsigned char *)((base) + 0x2c))
-#define AMBA_UART_CR(base)	(*(volatile unsigned char *)((base) + 0x30))
-#define AMBA_UART_FR(base)	(*(volatile unsigned char *)((base) + 0x18))
-
-/*
- * Return the UART base address
- */
-static inline unsigned long get_uart_base(void)
-{
-	if (machine_is_cns3420vb())
-		return CNS3XXX_UART0_BASE;
-	else
-		return 0;
-}
-
-/*
- * This does not append a newline
- */
-static inline void putc(int c)
-{
-	unsigned long base = get_uart_base();
-
-	while (AMBA_UART_FR(base) & (1 << 5))
-		barrier();
-
-	AMBA_UART_DR(base) = c;
-}
-
-static inline void flush(void)
-{
-	unsigned long base = get_uart_base();
-
-	while (AMBA_UART_FR(base) & (1 << 3))
-		barrier();
-}
-
-/*
- * nothing to do
- */
-#define arch_decomp_setup()
diff --git a/arch/arm/mach-cns3xxx/pcie.c b/arch/arm/mach-cns3xxx/pcie.c
index 3113283..c7b204b 100644
--- a/arch/arm/mach-cns3xxx/pcie.c
+++ b/arch/arm/mach-cns3xxx/pcie.c
@@ -20,7 +20,7 @@
 #include <linux/interrupt.h>
 #include <linux/ptrace.h>
 #include <asm/mach/map.h>
-#include <mach/cns3xxx.h>
+#include "cns3xxx.h"
 #include "core.h"
 
 enum cns3xxx_access_type {
diff --git a/arch/arm/mach-cns3xxx/pm.c b/arch/arm/mach-cns3xxx/pm.c
index 3645808..79e3d47 100644
--- a/arch/arm/mach-cns3xxx/pm.c
+++ b/arch/arm/mach-cns3xxx/pm.c
@@ -11,8 +11,8 @@
 #include <linux/io.h>
 #include <linux/delay.h>
 #include <linux/atomic.h>
-#include <mach/cns3xxx.h>
-#include <mach/pm.h>
+#include "cns3xxx.h"
+#include "pm.h"
 #include "core.h"
 
 void cns3xxx_pwr_clk_en(unsigned int block)
diff --git a/arch/arm/mach-cns3xxx/pm.h b/arch/arm/mach-cns3xxx/pm.h
new file mode 100644
index 0000000..c2588cc
--- /dev/null
+++ b/arch/arm/mach-cns3xxx/pm.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2000 Deep Blue Solutions Ltd
+ * Copyright 2004 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 __CNS3XXX_PM_H
+#define __CNS3XXX_PM_H
+
+#include <linux/atomic.h>
+
+void cns3xxx_pwr_clk_en(unsigned int block);
+void cns3xxx_pwr_clk_dis(unsigned int block);
+void cns3xxx_pwr_power_up(unsigned int block);
+void cns3xxx_pwr_power_down(unsigned int block);
+
+extern atomic_t usb_pwr_ref;
+
+#endif /* __CNS3XXX_PM_H */
diff --git a/arch/arm/mach-davinci/board-dm644x-evm.c b/arch/arm/mach-davinci/board-dm644x-evm.c
index 71735e7..a021800 100644
--- a/arch/arm/mach-davinci/board-dm644x-evm.c
+++ b/arch/arm/mach-davinci/board-dm644x-evm.c
@@ -649,7 +649,7 @@ static struct vpbe_enc_mode_info dm644xevm_enc_std_timing[] = {
 static struct vpbe_enc_mode_info dm644xevm_enc_preset_timing[] = {
 	{
 		.name		= "480p59_94",
-		.timings_type	= VPBE_ENC_CUSTOM_TIMINGS,
+		.timings_type	= VPBE_ENC_DV_TIMINGS,
 		.dv_timings	= V4L2_DV_BT_CEA_720X480P59_94,
 		.interlaced	= 0,
 		.xres		= 720,
@@ -661,7 +661,7 @@ static struct vpbe_enc_mode_info dm644xevm_enc_preset_timing[] = {
 	},
 	{
 		.name		= "576p50",
-		.timings_type	= VPBE_ENC_CUSTOM_TIMINGS,
+		.timings_type	= VPBE_ENC_DV_TIMINGS,
 		.dv_timings	= V4L2_DV_BT_CEA_720X576P50,
 		.interlaced	= 0,
 		.xres		= 720,
diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c b/arch/arm/mach-davinci/board-dm646x-evm.c
index de7adff..fc4871a 100644
--- a/arch/arm/mach-davinci/board-dm646x-evm.c
+++ b/arch/arm/mach-davinci/board-dm646x-evm.c
@@ -514,7 +514,7 @@ static const struct vpif_output dm6467_ch0_outputs[] = {
 			.index = 1,
 			.name = "Component",
 			.type = V4L2_OUTPUT_TYPE_ANALOG,
-			.capabilities = V4L2_OUT_CAP_CUSTOM_TIMINGS,
+			.capabilities = V4L2_OUT_CAP_DV_TIMINGS,
 		},
 		.subdev_name = "adv7343",
 		.output_route = ADV7343_COMPONENT_ID,
diff --git a/arch/arm/mach-davinci/cpufreq.c b/arch/arm/mach-davinci/cpufreq.c
index 4729eaa..7c2e943 100644
--- a/arch/arm/mach-davinci/cpufreq.c
+++ b/arch/arm/mach-davinci/cpufreq.c
@@ -79,18 +79,8 @@ static int davinci_target(struct cpufreq_policy *policy,
 	struct davinci_cpufreq_config *pdata = cpufreq.dev->platform_data;
 	struct clk *armclk = cpufreq.armclk;
 
-	/*
-	 * Ensure desired rate is within allowed range.  Some govenors
-	 * (ondemand) will just pass target_freq=0 to get the minimum.
-	 */
-	if (target_freq < policy->cpuinfo.min_freq)
-		target_freq = policy->cpuinfo.min_freq;
-	if (target_freq > policy->cpuinfo.max_freq)
-		target_freq = policy->cpuinfo.max_freq;
-
 	freqs.old = davinci_getspeed(0);
 	freqs.new = clk_round_rate(armclk, target_freq * 1000) / 1000;
-	freqs.cpu = 0;
 
 	if (freqs.old == freqs.new)
 		return ret;
@@ -102,7 +92,7 @@ static int davinci_target(struct cpufreq_policy *policy,
 	if (ret)
 		return -EINVAL;
 
-	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
 
 	/* if moving to higher frequency, up the voltage beforehand */
 	if (pdata->set_voltage && freqs.new > freqs.old) {
@@ -126,7 +116,7 @@ static int davinci_target(struct cpufreq_policy *policy,
 		pdata->set_voltage(idx);
 
 out:
-	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
 
 	return ret;
 }
@@ -147,21 +137,16 @@ static int davinci_cpu_init(struct cpufreq_policy *policy)
 			return result;
 	}
 
-	policy->cur = policy->min = policy->max = davinci_getspeed(0);
+	policy->cur = davinci_getspeed(0);
 
-	if (freq_table) {
-		result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
-		if (!result)
-			cpufreq_frequency_table_get_attr(freq_table,
-							policy->cpu);
-	} else {
-		policy->cpuinfo.min_freq = policy->min;
-		policy->cpuinfo.max_freq = policy->max;
+	result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
+	if (result) {
+		pr_err("%s: cpufreq_frequency_table_cpuinfo() failed",
+				__func__);
+		return result;
 	}
 
-	policy->min = policy->cpuinfo.min_freq;
-	policy->max = policy->cpuinfo.max_freq;
-	policy->cur = davinci_getspeed(0);
+	cpufreq_frequency_table_get_attr(freq_table, policy->cpu);
 
 	/*
 	 * Time measurement across the target() function yields ~1500-1800us
diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c
index db1dd92..ee0e994 100644
--- a/arch/arm/mach-davinci/dm644x.c
+++ b/arch/arm/mach-davinci/dm644x.c
@@ -706,7 +706,7 @@ static int dm644x_venc_setup_clock(enum vpbe_enc_timings_type type,
 		v |= DM644X_VPSS_DACCLKEN;
 		writel(v, DAVINCI_SYSMOD_VIRT(SYSMOD_VPSS_CLKCTL));
 		break;
-	case VPBE_ENC_CUSTOM_TIMINGS:
+	case VPBE_ENC_DV_TIMINGS:
 		if (pclock <= 27000000) {
 			v |= DM644X_VPSS_DACCLKEN;
 			writel(v, DAVINCI_SYSMOD_VIRT(SYSMOD_VPSS_CLKCTL));
diff --git a/arch/arm/mach-ep93xx/include/mach/uncompress.h b/arch/arm/mach-ep93xx/include/mach/uncompress.h
index d2afb4d..b5cc77d 100644
--- a/arch/arm/mach-ep93xx/include/mach/uncompress.h
+++ b/arch/arm/mach-ep93xx/include/mach/uncompress.h
@@ -47,9 +47,13 @@ static void __raw_writel(unsigned int value, unsigned int ptr)
 
 static inline void putc(int c)
 {
-	/* Transmit fifo not full?  */
-	while (__raw_readb(PHYS_UART_FLAG) & UART_FLAG_TXFF)
-		;
+	int i;
+
+	for (i = 0; i < 10000; i++) {
+		/* Transmit fifo not full? */
+		if (!(__raw_readb(PHYS_UART_FLAG) & UART_FLAG_TXFF))
+			break;
+	}
 
 	__raw_writeb(c, PHYS_UART_DATA);
 }
diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig
index 70f94c8..e538705 100644
--- a/arch/arm/mach-exynos/Kconfig
+++ b/arch/arm/mach-exynos/Kconfig
@@ -61,6 +61,7 @@ config SOC_EXYNOS5250
 	bool "SAMSUNG EXYNOS5250"
 	default y
 	depends on ARCH_EXYNOS5
+	select PM_GENERIC_DOMAINS if PM
 	select S5P_PM if PM
 	select S5P_SLEEP if PM
 	select S5P_DEV_MFC
@@ -79,12 +80,6 @@ config SOC_EXYNOS5440
 	help
 	  Enable EXYNOS5440 SoC support
 
-config EXYNOS4_MCT
-	bool
-	default y
-	help
-	  Use MCT (Multi Core Timer) as kernel timers
-
 config EXYNOS_DEV_DMA
 	bool
 	help
@@ -255,7 +250,6 @@ config MACH_UNIVERSAL_C210
 	select EXYNOS_DEV_DMA
 	select EXYNOS_DEV_DRM
 	select EXYNOS_DEV_SYSMMU
-	select HAVE_SCHED_CLOCK
 	select S3C_DEV_HSMMC
 	select S3C_DEV_HSMMC2
 	select S3C_DEV_HSMMC3
@@ -276,8 +270,8 @@ config MACH_UNIVERSAL_C210
 	select S5P_DEV_ONENAND
 	select S5P_DEV_TV
 	select S5P_GPIO_INT
-	select S5P_HRT
 	select S5P_SETUP_MIPIPHY
+	select SAMSUNG_HRT
 	help
 	  Machine support for Samsung Mobile Universal S5PC210 Reference
 	  Board.
@@ -406,10 +400,12 @@ config MACH_EXYNOS4_DT
 	bool "Samsung Exynos4 Machine using device tree"
 	depends on ARCH_EXYNOS4
 	select ARM_AMBA
+	select CLKSRC_OF
 	select CPU_EXYNOS4210
-	select HAVE_SAMSUNG_KEYPAD if INPUT_KEYBOARD
+	select KEYBOARD_SAMSUNG if INPUT_KEYBOARD
 	select PINCTRL
 	select PINCTRL_EXYNOS
+	select S5P_DEV_MFC
 	select USE_OF
 	help
 	  Machine support for Samsung Exynos4 machine with device tree enabled.
@@ -422,6 +418,7 @@ config MACH_EXYNOS5_DT
 	default y
 	depends on ARCH_EXYNOS5
 	select ARM_AMBA
+	select CLKSRC_OF
 	select USE_OF
 	help
 	  Machine support for Samsung EXYNOS5 machine with device tree enabled.
diff --git a/arch/arm/mach-exynos/Makefile b/arch/arm/mach-exynos/Makefile
index 435757e..b09b027 100644
--- a/arch/arm/mach-exynos/Makefile
+++ b/arch/arm/mach-exynos/Makefile
@@ -13,10 +13,6 @@ obj-				:=
 # Core
 
 obj-$(CONFIG_ARCH_EXYNOS)	+= common.o
-obj-$(CONFIG_ARCH_EXYNOS4)	+= clock-exynos4.o
-obj-$(CONFIG_CPU_EXYNOS4210)	+= clock-exynos4210.o
-obj-$(CONFIG_SOC_EXYNOS4212)	+= clock-exynos4212.o
-obj-$(CONFIG_SOC_EXYNOS5250)	+= clock-exynos5.o
 
 obj-$(CONFIG_PM)		+= pm.o
 obj-$(CONFIG_PM_GENERIC_DOMAINS) += pm_domains.o
@@ -26,10 +22,14 @@ obj-$(CONFIG_ARCH_EXYNOS)	+= pmu.o
 
 obj-$(CONFIG_SMP)		+= platsmp.o headsmp.o
 
-obj-$(CONFIG_EXYNOS4_MCT)	+= mct.o
-
 obj-$(CONFIG_HOTPLUG_CPU)	+= hotplug.o
 
+obj-$(CONFIG_ARCH_EXYNOS)	+= exynos-smc.o
+obj-$(CONFIG_ARCH_EXYNOS)	+= firmware.o
+
+plus_sec := $(call as-instr,.arch_extension sec,+sec)
+AFLAGS_exynos-smc.o		:=-Wa,-march=armv7-a$(plus_sec)
+
 # machine support
 
 obj-$(CONFIG_MACH_SMDKC210)		+= mach-smdkv310.o
diff --git a/arch/arm/mach-exynos/clock-exynos4.c b/arch/arm/mach-exynos/clock-exynos4.c
deleted file mode 100644
index 8a8468d..0000000
--- a/arch/arm/mach-exynos/clock-exynos4.c
+++ /dev/null
@@ -1,1601 +0,0 @@
-/*
- * Copyright (c) 2010-2012 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * EXYNOS4 - Clock 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/err.h>
-#include <linux/io.h>
-#include <linux/syscore_ops.h>
-
-#include <plat/cpu-freq.h>
-#include <plat/clock.h>
-#include <plat/cpu.h>
-#include <plat/pll.h>
-#include <plat/s5p-clock.h>
-#include <plat/clock-clksrc.h>
-#include <plat/pm.h>
-
-#include <mach/map.h>
-#include <mach/regs-clock.h>
-
-#include "common.h"
-#include "clock-exynos4.h"
-
-#ifdef CONFIG_PM_SLEEP
-static struct sleep_save exynos4_clock_save[] = {
-	SAVE_ITEM(EXYNOS4_CLKDIV_LEFTBUS),
-	SAVE_ITEM(EXYNOS4_CLKGATE_IP_LEFTBUS),
-	SAVE_ITEM(EXYNOS4_CLKDIV_RIGHTBUS),
-	SAVE_ITEM(EXYNOS4_CLKGATE_IP_RIGHTBUS),
-	SAVE_ITEM(EXYNOS4_CLKSRC_TOP0),
-	SAVE_ITEM(EXYNOS4_CLKSRC_TOP1),
-	SAVE_ITEM(EXYNOS4_CLKSRC_CAM),
-	SAVE_ITEM(EXYNOS4_CLKSRC_TV),
-	SAVE_ITEM(EXYNOS4_CLKSRC_MFC),
-	SAVE_ITEM(EXYNOS4_CLKSRC_G3D),
-	SAVE_ITEM(EXYNOS4_CLKSRC_LCD0),
-	SAVE_ITEM(EXYNOS4_CLKSRC_MAUDIO),
-	SAVE_ITEM(EXYNOS4_CLKSRC_FSYS),
-	SAVE_ITEM(EXYNOS4_CLKSRC_PERIL0),
-	SAVE_ITEM(EXYNOS4_CLKSRC_PERIL1),
-	SAVE_ITEM(EXYNOS4_CLKDIV_CAM),
-	SAVE_ITEM(EXYNOS4_CLKDIV_TV),
-	SAVE_ITEM(EXYNOS4_CLKDIV_MFC),
-	SAVE_ITEM(EXYNOS4_CLKDIV_G3D),
-	SAVE_ITEM(EXYNOS4_CLKDIV_LCD0),
-	SAVE_ITEM(EXYNOS4_CLKDIV_MAUDIO),
-	SAVE_ITEM(EXYNOS4_CLKDIV_FSYS0),
-	SAVE_ITEM(EXYNOS4_CLKDIV_FSYS1),
-	SAVE_ITEM(EXYNOS4_CLKDIV_FSYS2),
-	SAVE_ITEM(EXYNOS4_CLKDIV_FSYS3),
-	SAVE_ITEM(EXYNOS4_CLKDIV_PERIL0),
-	SAVE_ITEM(EXYNOS4_CLKDIV_PERIL1),
-	SAVE_ITEM(EXYNOS4_CLKDIV_PERIL2),
-	SAVE_ITEM(EXYNOS4_CLKDIV_PERIL3),
-	SAVE_ITEM(EXYNOS4_CLKDIV_PERIL4),
-	SAVE_ITEM(EXYNOS4_CLKDIV_PERIL5),
-	SAVE_ITEM(EXYNOS4_CLKDIV_TOP),
-	SAVE_ITEM(EXYNOS4_CLKSRC_MASK_TOP),
-	SAVE_ITEM(EXYNOS4_CLKSRC_MASK_CAM),
-	SAVE_ITEM(EXYNOS4_CLKSRC_MASK_TV),
-	SAVE_ITEM(EXYNOS4_CLKSRC_MASK_LCD0),
-	SAVE_ITEM(EXYNOS4_CLKSRC_MASK_MAUDIO),
-	SAVE_ITEM(EXYNOS4_CLKSRC_MASK_FSYS),
-	SAVE_ITEM(EXYNOS4_CLKSRC_MASK_PERIL0),
-	SAVE_ITEM(EXYNOS4_CLKSRC_MASK_PERIL1),
-	SAVE_ITEM(EXYNOS4_CLKDIV2_RATIO),
-	SAVE_ITEM(EXYNOS4_CLKGATE_SCLKCAM),
-	SAVE_ITEM(EXYNOS4_CLKGATE_IP_CAM),
-	SAVE_ITEM(EXYNOS4_CLKGATE_IP_TV),
-	SAVE_ITEM(EXYNOS4_CLKGATE_IP_MFC),
-	SAVE_ITEM(EXYNOS4_CLKGATE_IP_G3D),
-	SAVE_ITEM(EXYNOS4_CLKGATE_IP_LCD0),
-	SAVE_ITEM(EXYNOS4_CLKGATE_IP_FSYS),
-	SAVE_ITEM(EXYNOS4_CLKGATE_IP_GPS),
-	SAVE_ITEM(EXYNOS4_CLKGATE_IP_PERIL),
-	SAVE_ITEM(EXYNOS4_CLKGATE_BLOCK),
-	SAVE_ITEM(EXYNOS4_CLKSRC_MASK_DMC),
-	SAVE_ITEM(EXYNOS4_CLKSRC_DMC),
-	SAVE_ITEM(EXYNOS4_CLKDIV_DMC0),
-	SAVE_ITEM(EXYNOS4_CLKDIV_DMC1),
-	SAVE_ITEM(EXYNOS4_CLKGATE_IP_DMC),
-	SAVE_ITEM(EXYNOS4_CLKSRC_CPU),
-	SAVE_ITEM(EXYNOS4_CLKDIV_CPU),
-	SAVE_ITEM(EXYNOS4_CLKDIV_CPU + 0x4),
-	SAVE_ITEM(EXYNOS4_CLKGATE_SCLKCPU),
-	SAVE_ITEM(EXYNOS4_CLKGATE_IP_CPU),
-};
-#endif
-
-static struct clk exynos4_clk_sclk_hdmi27m = {
-	.name		= "sclk_hdmi27m",
-	.rate		= 27000000,
-};
-
-static struct clk exynos4_clk_sclk_hdmiphy = {
-	.name		= "sclk_hdmiphy",
-};
-
-static struct clk exynos4_clk_sclk_usbphy0 = {
-	.name		= "sclk_usbphy0",
-	.rate		= 27000000,
-};
-
-static struct clk exynos4_clk_sclk_usbphy1 = {
-	.name		= "sclk_usbphy1",
-};
-
-static struct clk dummy_apb_pclk = {
-	.name		= "apb_pclk",
-	.id		= -1,
-};
-
-static int exynos4_clksrc_mask_top_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKSRC_MASK_TOP, clk, enable);
-}
-
-static int exynos4_clksrc_mask_cam_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKSRC_MASK_CAM, clk, enable);
-}
-
-static int exynos4_clksrc_mask_lcd0_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKSRC_MASK_LCD0, clk, enable);
-}
-
-int exynos4_clksrc_mask_fsys_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKSRC_MASK_FSYS, clk, enable);
-}
-
-static int exynos4_clksrc_mask_peril0_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKSRC_MASK_PERIL0, clk, enable);
-}
-
-static int exynos4_clksrc_mask_peril1_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKSRC_MASK_PERIL1, clk, enable);
-}
-
-static int exynos4_clk_ip_mfc_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKGATE_IP_MFC, clk, enable);
-}
-
-static int exynos4_clksrc_mask_tv_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKSRC_MASK_TV, clk, enable);
-}
-
-static int exynos4_clk_ip_cam_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKGATE_IP_CAM, clk, enable);
-}
-
-static int exynos4_clk_ip_tv_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKGATE_IP_TV, clk, enable);
-}
-
-int exynos4_clk_ip_image_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKGATE_IP_IMAGE, clk, enable);
-}
-
-static int exynos4_clk_ip_lcd0_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKGATE_IP_LCD0, clk, enable);
-}
-
-int exynos4_clk_ip_lcd1_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4210_CLKGATE_IP_LCD1, clk, enable);
-}
-
-int exynos4_clk_ip_fsys_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKGATE_IP_FSYS, clk, enable);
-}
-
-static int exynos4_clk_ip_peril_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKGATE_IP_PERIL, clk, enable);
-}
-
-static int exynos4_clk_ip_perir_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKGATE_IP_PERIR, clk, enable);
-}
-
-int exynos4_clk_ip_dmc_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKGATE_IP_DMC, clk, enable);
-}
-
-static int exynos4_clk_hdmiphy_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_HDMI_PHY_CONTROL, clk, enable);
-}
-
-static int exynos4_clk_dac_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_DAC_PHY_CONTROL, clk, enable);
-}
-
-/* Core list of CMU_CPU side */
-
-static struct clksrc_clk exynos4_clk_mout_apll = {
-	.clk	= {
-		.name		= "mout_apll",
-	},
-	.sources = &clk_src_apll,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_CPU, .shift = 0, .size = 1 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_apll = {
-	.clk	= {
-		.name		= "sclk_apll",
-		.parent		= &exynos4_clk_mout_apll.clk,
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_CPU, .shift = 24, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_mout_epll = {
-	.clk	= {
-		.name		= "mout_epll",
-	},
-	.sources = &clk_src_epll,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_TOP0, .shift = 4, .size = 1 },
-};
-
-struct clksrc_clk exynos4_clk_mout_mpll = {
-	.clk	= {
-		.name		= "mout_mpll",
-	},
-	.sources = &clk_src_mpll,
-
-	/* reg_src will be added in each SoCs' clock */
-};
-
-static struct clk *exynos4_clkset_moutcore_list[] = {
-	[0] = &exynos4_clk_mout_apll.clk,
-	[1] = &exynos4_clk_mout_mpll.clk,
-};
-
-static struct clksrc_sources exynos4_clkset_moutcore = {
-	.sources	= exynos4_clkset_moutcore_list,
-	.nr_sources	= ARRAY_SIZE(exynos4_clkset_moutcore_list),
-};
-
-static struct clksrc_clk exynos4_clk_moutcore = {
-	.clk	= {
-		.name		= "moutcore",
-	},
-	.sources = &exynos4_clkset_moutcore,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_CPU, .shift = 16, .size = 1 },
-};
-
-static struct clksrc_clk exynos4_clk_coreclk = {
-	.clk	= {
-		.name		= "core_clk",
-		.parent		= &exynos4_clk_moutcore.clk,
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_CPU, .shift = 0, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_armclk = {
-	.clk	= {
-		.name		= "armclk",
-		.parent		= &exynos4_clk_coreclk.clk,
-	},
-};
-
-static struct clksrc_clk exynos4_clk_aclk_corem0 = {
-	.clk	= {
-		.name		= "aclk_corem0",
-		.parent		= &exynos4_clk_coreclk.clk,
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_CPU, .shift = 4, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_aclk_cores = {
-	.clk	= {
-		.name		= "aclk_cores",
-		.parent		= &exynos4_clk_coreclk.clk,
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_CPU, .shift = 4, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_aclk_corem1 = {
-	.clk	= {
-		.name		= "aclk_corem1",
-		.parent		= &exynos4_clk_coreclk.clk,
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_CPU, .shift = 8, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_periphclk = {
-	.clk	= {
-		.name		= "periphclk",
-		.parent		= &exynos4_clk_coreclk.clk,
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_CPU, .shift = 12, .size = 3 },
-};
-
-/* Core list of CMU_CORE side */
-
-static struct clk *exynos4_clkset_corebus_list[] = {
-	[0] = &exynos4_clk_mout_mpll.clk,
-	[1] = &exynos4_clk_sclk_apll.clk,
-};
-
-struct clksrc_sources exynos4_clkset_mout_corebus = {
-	.sources	= exynos4_clkset_corebus_list,
-	.nr_sources	= ARRAY_SIZE(exynos4_clkset_corebus_list),
-};
-
-static struct clksrc_clk exynos4_clk_mout_corebus = {
-	.clk	= {
-		.name		= "mout_corebus",
-	},
-	.sources = &exynos4_clkset_mout_corebus,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_DMC, .shift = 4, .size = 1 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_dmc = {
-	.clk	= {
-		.name		= "sclk_dmc",
-		.parent		= &exynos4_clk_mout_corebus.clk,
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_DMC0, .shift = 12, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_aclk_cored = {
-	.clk	= {
-		.name		= "aclk_cored",
-		.parent		= &exynos4_clk_sclk_dmc.clk,
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_DMC0, .shift = 16, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_aclk_corep = {
-	.clk	= {
-		.name		= "aclk_corep",
-		.parent		= &exynos4_clk_aclk_cored.clk,
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_DMC0, .shift = 20, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_aclk_acp = {
-	.clk	= {
-		.name		= "aclk_acp",
-		.parent		= &exynos4_clk_mout_corebus.clk,
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_DMC0, .shift = 0, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_pclk_acp = {
-	.clk	= {
-		.name		= "pclk_acp",
-		.parent		= &exynos4_clk_aclk_acp.clk,
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_DMC0, .shift = 4, .size = 3 },
-};
-
-/* Core list of CMU_TOP side */
-
-struct clk *exynos4_clkset_aclk_top_list[] = {
-	[0] = &exynos4_clk_mout_mpll.clk,
-	[1] = &exynos4_clk_sclk_apll.clk,
-};
-
-static struct clksrc_sources exynos4_clkset_aclk = {
-	.sources	= exynos4_clkset_aclk_top_list,
-	.nr_sources	= ARRAY_SIZE(exynos4_clkset_aclk_top_list),
-};
-
-static struct clksrc_clk exynos4_clk_aclk_200 = {
-	.clk	= {
-		.name		= "aclk_200",
-	},
-	.sources = &exynos4_clkset_aclk,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_TOP0, .shift = 12, .size = 1 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_TOP, .shift = 0, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_aclk_100 = {
-	.clk	= {
-		.name		= "aclk_100",
-	},
-	.sources = &exynos4_clkset_aclk,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_TOP0, .shift = 16, .size = 1 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_TOP, .shift = 4, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_aclk_160 = {
-	.clk	= {
-		.name		= "aclk_160",
-	},
-	.sources = &exynos4_clkset_aclk,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_TOP0, .shift = 20, .size = 1 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_TOP, .shift = 8, .size = 3 },
-};
-
-struct clksrc_clk exynos4_clk_aclk_133 = {
-	.clk	= {
-		.name		= "aclk_133",
-	},
-	.sources = &exynos4_clkset_aclk,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_TOP0, .shift = 24, .size = 1 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_TOP, .shift = 12, .size = 3 },
-};
-
-static struct clk *exynos4_clkset_vpllsrc_list[] = {
-	[0] = &clk_fin_vpll,
-	[1] = &exynos4_clk_sclk_hdmi27m,
-};
-
-static struct clksrc_sources exynos4_clkset_vpllsrc = {
-	.sources	= exynos4_clkset_vpllsrc_list,
-	.nr_sources	= ARRAY_SIZE(exynos4_clkset_vpllsrc_list),
-};
-
-static struct clksrc_clk exynos4_clk_vpllsrc = {
-	.clk	= {
-		.name		= "vpll_src",
-		.enable		= exynos4_clksrc_mask_top_ctrl,
-		.ctrlbit	= (1 << 0),
-	},
-	.sources = &exynos4_clkset_vpllsrc,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_TOP1, .shift = 0, .size = 1 },
-};
-
-static struct clk *exynos4_clkset_sclk_vpll_list[] = {
-	[0] = &exynos4_clk_vpllsrc.clk,
-	[1] = &clk_fout_vpll,
-};
-
-static struct clksrc_sources exynos4_clkset_sclk_vpll = {
-	.sources	= exynos4_clkset_sclk_vpll_list,
-	.nr_sources	= ARRAY_SIZE(exynos4_clkset_sclk_vpll_list),
-};
-
-static struct clksrc_clk exynos4_clk_sclk_vpll = {
-	.clk	= {
-		.name		= "sclk_vpll",
-	},
-	.sources = &exynos4_clkset_sclk_vpll,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_TOP0, .shift = 8, .size = 1 },
-};
-
-static struct clk exynos4_init_clocks_off[] = {
-	{
-		.name		= "timers",
-		.parent		= &exynos4_clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1<<24),
-	}, {
-		.name		= "csis",
-		.devname	= "s5p-mipi-csis.0",
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
-		.name		= "csis",
-		.devname	= "s5p-mipi-csis.1",
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 5),
-	}, {
-		.name		= "jpeg",
-		.id		= 0,
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 6),
-	}, {
-		.name		= "fimc",
-		.devname	= "exynos4-fimc.0",
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "fimc",
-		.devname	= "exynos4-fimc.1",
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 1),
-	}, {
-		.name		= "fimc",
-		.devname	= "exynos4-fimc.2",
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 2),
-	}, {
-		.name		= "fimc",
-		.devname	= "exynos4-fimc.3",
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 3),
-	}, {
-		.name		= "tsi",
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
-		.name		= "hsmmc",
-		.devname	= "exynos4-sdhci.0",
-		.parent		= &exynos4_clk_aclk_133.clk,
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 5),
-	}, {
-		.name		= "hsmmc",
-		.devname	= "exynos4-sdhci.1",
-		.parent		= &exynos4_clk_aclk_133.clk,
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 6),
-	}, {
-		.name		= "hsmmc",
-		.devname	= "exynos4-sdhci.2",
-		.parent		= &exynos4_clk_aclk_133.clk,
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 7),
-	}, {
-		.name		= "hsmmc",
-		.devname	= "exynos4-sdhci.3",
-		.parent		= &exynos4_clk_aclk_133.clk,
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 8),
-	}, {
-		.name		= "biu",
-		.parent		= &exynos4_clk_aclk_133.clk,
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 9),
-	}, {
-		.name		= "onenand",
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 15),
-	}, {
-		.name		= "nfcon",
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 16),
-	}, {
-		.name		= "dac",
-		.devname	= "s5p-sdo",
-		.enable		= exynos4_clk_ip_tv_ctrl,
-		.ctrlbit	= (1 << 2),
-	}, {
-		.name		= "mixer",
-		.devname	= "s5p-mixer",
-		.enable		= exynos4_clk_ip_tv_ctrl,
-		.ctrlbit	= (1 << 1),
-	}, {
-		.name		= "vp",
-		.devname	= "s5p-mixer",
-		.enable		= exynos4_clk_ip_tv_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "hdmi",
-		.devname	= "exynos4-hdmi",
-		.enable		= exynos4_clk_ip_tv_ctrl,
-		.ctrlbit	= (1 << 3),
-	}, {
-		.name		= "hdmiphy",
-		.devname	= "exynos4-hdmi",
-		.enable		= exynos4_clk_hdmiphy_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "dacphy",
-		.devname	= "s5p-sdo",
-		.enable		= exynos4_clk_dac_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "adc",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 15),
-	}, {
-		.name		= "tmu_apbif",
-		.enable		= exynos4_clk_ip_perir_ctrl,
-		.ctrlbit	= (1 << 17),
-	}, {
-		.name		= "keypad",
-		.enable		= exynos4_clk_ip_perir_ctrl,
-		.ctrlbit	= (1 << 16),
-	}, {
-		.name		= "rtc",
-		.enable		= exynos4_clk_ip_perir_ctrl,
-		.ctrlbit	= (1 << 15),
-	}, {
-		.name		= "watchdog",
-		.parent		= &exynos4_clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_perir_ctrl,
-		.ctrlbit	= (1 << 14),
-	}, {
-		.name		= "usbhost",
-		.enable		= exynos4_clk_ip_fsys_ctrl ,
-		.ctrlbit	= (1 << 12),
-	}, {
-		.name		= "otg",
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 13),
-	}, {
-		.name		= "spi",
-		.devname	= "exynos4210-spi.0",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 16),
-	}, {
-		.name		= "spi",
-		.devname	= "exynos4210-spi.1",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 17),
-	}, {
-		.name		= "spi",
-		.devname	= "exynos4210-spi.2",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 18),
-	}, {
-		.name		= "iis",
-		.devname	= "samsung-i2s.1",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 20),
-	}, {
-		.name		= "iis",
-		.devname	= "samsung-i2s.2",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 21),
-	}, {
-		.name		= "pcm",
-		.devname	= "samsung-pcm.1",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 22),
-	}, {
-		.name		= "pcm",
-		.devname	= "samsung-pcm.2",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 23),
-	}, {
-		.name		= "slimbus",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 25),
-	}, {
-		.name		= "spdif",
-		.devname	= "samsung-spdif",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 26),
-	}, {
-		.name		= "ac97",
-		.devname	= "samsung-ac97",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 27),
-	}, {
-		.name		= "mfc",
-		.devname	= "s5p-mfc",
-		.enable		= exynos4_clk_ip_mfc_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.0",
-		.parent		= &exynos4_clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 6),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.1",
-		.parent		= &exynos4_clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 7),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.2",
-		.parent		= &exynos4_clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 8),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.3",
-		.parent		= &exynos4_clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 9),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.4",
-		.parent		= &exynos4_clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 10),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.5",
-		.parent		= &exynos4_clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 11),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.6",
-		.parent		= &exynos4_clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 12),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.7",
-		.parent		= &exynos4_clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 13),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-hdmiphy-i2c",
-		.parent		= &exynos4_clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 14),
-	}, {
-		.name		= "sysmmu",
-		.devname	= "exynos-sysmmu.0",
-		.enable		= exynos4_clk_ip_mfc_ctrl,
-		.ctrlbit	= (1 << 1),
-	}, {
-		.name		= "sysmmu",
-		.devname	= "exynos-sysmmu.1",
-		.enable		= exynos4_clk_ip_mfc_ctrl,
-		.ctrlbit	= (1 << 2),
-	}, {
-		.name		= "sysmmu",
-		.devname	= "exynos-sysmmu.2",
-		.enable		= exynos4_clk_ip_tv_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
-		.name		= "sysmmu",
-		.devname	= "exynos-sysmmu.3",
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 11),
-	}, {
-		.name		= "sysmmu",
-		.devname	= "exynos-sysmmu.4",
-		.enable		= exynos4_clk_ip_image_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
-		.name		= "sysmmu",
-		.devname	= "exynos-sysmmu.5",
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 7),
-	}, {
-		.name		= "sysmmu",
-		.devname	= "exynos-sysmmu.6",
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 8),
-	}, {
-		.name		= "sysmmu",
-		.devname	= "exynos-sysmmu.7",
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 9),
-	}, {
-		.name		= "sysmmu",
-		.devname	= "exynos-sysmmu.8",
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 10),
-	}, {
-		.name		= "sysmmu",
-		.devname	= "exynos-sysmmu.10",
-		.enable		= exynos4_clk_ip_lcd0_ctrl,
-		.ctrlbit	= (1 << 4),
-	}
-};
-
-static struct clk exynos4_init_clocks_on[] = {
-	{
-		.name		= "uart",
-		.devname	= "s5pv210-uart.0",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "uart",
-		.devname	= "s5pv210-uart.1",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 1),
-	}, {
-		.name		= "uart",
-		.devname	= "s5pv210-uart.2",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 2),
-	}, {
-		.name		= "uart",
-		.devname	= "s5pv210-uart.3",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 3),
-	}, {
-		.name		= "uart",
-		.devname	= "s5pv210-uart.4",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
-		.name		= "uart",
-		.devname	= "s5pv210-uart.5",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 5),
-	}
-};
-
-static struct clk exynos4_clk_pdma0 = {
-	.name		= "dma",
-	.devname	= "dma-pl330.0",
-	.enable		= exynos4_clk_ip_fsys_ctrl,
-	.ctrlbit	= (1 << 0),
-};
-
-static struct clk exynos4_clk_pdma1 = {
-	.name		= "dma",
-	.devname	= "dma-pl330.1",
-	.enable		= exynos4_clk_ip_fsys_ctrl,
-	.ctrlbit	= (1 << 1),
-};
-
-static struct clk exynos4_clk_mdma1 = {
-	.name		= "dma",
-	.devname	= "dma-pl330.2",
-	.enable		= exynos4_clk_ip_image_ctrl,
-	.ctrlbit	= ((1 << 8) | (1 << 5) | (1 << 2)),
-};
-
-static struct clk exynos4_clk_fimd0 = {
-	.name		= "fimd",
-	.devname	= "exynos4-fb.0",
-	.enable		= exynos4_clk_ip_lcd0_ctrl,
-	.ctrlbit	= (1 << 0),
-};
-
-struct clk *exynos4_clkset_group_list[] = {
-	[0] = &clk_ext_xtal_mux,
-	[1] = &clk_xusbxti,
-	[2] = &exynos4_clk_sclk_hdmi27m,
-	[3] = &exynos4_clk_sclk_usbphy0,
-	[4] = &exynos4_clk_sclk_usbphy1,
-	[5] = &exynos4_clk_sclk_hdmiphy,
-	[6] = &exynos4_clk_mout_mpll.clk,
-	[7] = &exynos4_clk_mout_epll.clk,
-	[8] = &exynos4_clk_sclk_vpll.clk,
-};
-
-struct clksrc_sources exynos4_clkset_group = {
-	.sources	= exynos4_clkset_group_list,
-	.nr_sources	= ARRAY_SIZE(exynos4_clkset_group_list),
-};
-
-static struct clk *exynos4_clkset_mout_g2d0_list[] = {
-	[0] = &exynos4_clk_mout_mpll.clk,
-	[1] = &exynos4_clk_sclk_apll.clk,
-};
-
-struct clksrc_sources exynos4_clkset_mout_g2d0 = {
-	.sources	= exynos4_clkset_mout_g2d0_list,
-	.nr_sources	= ARRAY_SIZE(exynos4_clkset_mout_g2d0_list),
-};
-
-static struct clk *exynos4_clkset_mout_g2d1_list[] = {
-	[0] = &exynos4_clk_mout_epll.clk,
-	[1] = &exynos4_clk_sclk_vpll.clk,
-};
-
-struct clksrc_sources exynos4_clkset_mout_g2d1 = {
-	.sources	= exynos4_clkset_mout_g2d1_list,
-	.nr_sources	= ARRAY_SIZE(exynos4_clkset_mout_g2d1_list),
-};
-
-static struct clk *exynos4_clkset_mout_mfc0_list[] = {
-	[0] = &exynos4_clk_mout_mpll.clk,
-	[1] = &exynos4_clk_sclk_apll.clk,
-};
-
-static struct clksrc_sources exynos4_clkset_mout_mfc0 = {
-	.sources	= exynos4_clkset_mout_mfc0_list,
-	.nr_sources	= ARRAY_SIZE(exynos4_clkset_mout_mfc0_list),
-};
-
-static struct clksrc_clk exynos4_clk_mout_mfc0 = {
-	.clk	= {
-		.name		= "mout_mfc0",
-	},
-	.sources = &exynos4_clkset_mout_mfc0,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_MFC, .shift = 0, .size = 1 },
-};
-
-static struct clk *exynos4_clkset_mout_mfc1_list[] = {
-	[0] = &exynos4_clk_mout_epll.clk,
-	[1] = &exynos4_clk_sclk_vpll.clk,
-};
-
-static struct clksrc_sources exynos4_clkset_mout_mfc1 = {
-	.sources	= exynos4_clkset_mout_mfc1_list,
-	.nr_sources	= ARRAY_SIZE(exynos4_clkset_mout_mfc1_list),
-};
-
-static struct clksrc_clk exynos4_clk_mout_mfc1 = {
-	.clk	= {
-		.name		= "mout_mfc1",
-	},
-	.sources = &exynos4_clkset_mout_mfc1,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_MFC, .shift = 4, .size = 1 },
-};
-
-static struct clk *exynos4_clkset_mout_mfc_list[] = {
-	[0] = &exynos4_clk_mout_mfc0.clk,
-	[1] = &exynos4_clk_mout_mfc1.clk,
-};
-
-static struct clksrc_sources exynos4_clkset_mout_mfc = {
-	.sources	= exynos4_clkset_mout_mfc_list,
-	.nr_sources	= ARRAY_SIZE(exynos4_clkset_mout_mfc_list),
-};
-
-static struct clk *exynos4_clkset_sclk_dac_list[] = {
-	[0] = &exynos4_clk_sclk_vpll.clk,
-	[1] = &exynos4_clk_sclk_hdmiphy,
-};
-
-static struct clksrc_sources exynos4_clkset_sclk_dac = {
-	.sources	= exynos4_clkset_sclk_dac_list,
-	.nr_sources	= ARRAY_SIZE(exynos4_clkset_sclk_dac_list),
-};
-
-static struct clksrc_clk exynos4_clk_sclk_dac = {
-	.clk		= {
-		.name		= "sclk_dac",
-		.enable		= exynos4_clksrc_mask_tv_ctrl,
-		.ctrlbit	= (1 << 8),
-	},
-	.sources = &exynos4_clkset_sclk_dac,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_TV, .shift = 8, .size = 1 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_pixel = {
-	.clk		= {
-		.name		= "sclk_pixel",
-		.parent		= &exynos4_clk_sclk_vpll.clk,
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_TV, .shift = 0, .size = 4 },
-};
-
-static struct clk *exynos4_clkset_sclk_hdmi_list[] = {
-	[0] = &exynos4_clk_sclk_pixel.clk,
-	[1] = &exynos4_clk_sclk_hdmiphy,
-};
-
-static struct clksrc_sources exynos4_clkset_sclk_hdmi = {
-	.sources	= exynos4_clkset_sclk_hdmi_list,
-	.nr_sources	= ARRAY_SIZE(exynos4_clkset_sclk_hdmi_list),
-};
-
-static struct clksrc_clk exynos4_clk_sclk_hdmi = {
-	.clk		= {
-		.name		= "sclk_hdmi",
-		.enable		= exynos4_clksrc_mask_tv_ctrl,
-		.ctrlbit	= (1 << 0),
-	},
-	.sources = &exynos4_clkset_sclk_hdmi,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_TV, .shift = 0, .size = 1 },
-};
-
-static struct clk *exynos4_clkset_sclk_mixer_list[] = {
-	[0] = &exynos4_clk_sclk_dac.clk,
-	[1] = &exynos4_clk_sclk_hdmi.clk,
-};
-
-static struct clksrc_sources exynos4_clkset_sclk_mixer = {
-	.sources	= exynos4_clkset_sclk_mixer_list,
-	.nr_sources	= ARRAY_SIZE(exynos4_clkset_sclk_mixer_list),
-};
-
-static struct clksrc_clk exynos4_clk_sclk_mixer = {
-	.clk	= {
-		.name		= "sclk_mixer",
-		.enable		= exynos4_clksrc_mask_tv_ctrl,
-		.ctrlbit	= (1 << 4),
-	},
-	.sources = &exynos4_clkset_sclk_mixer,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_TV, .shift = 4, .size = 1 },
-};
-
-static struct clksrc_clk *exynos4_sclk_tv[] = {
-	&exynos4_clk_sclk_dac,
-	&exynos4_clk_sclk_pixel,
-	&exynos4_clk_sclk_hdmi,
-	&exynos4_clk_sclk_mixer,
-};
-
-static struct clksrc_clk exynos4_clk_dout_mmc0 = {
-	.clk	= {
-		.name		= "dout_mmc0",
-	},
-	.sources = &exynos4_clkset_group,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_FSYS, .shift = 0, .size = 4 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_FSYS1, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_dout_mmc1 = {
-	.clk	= {
-		.name		= "dout_mmc1",
-	},
-	.sources = &exynos4_clkset_group,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_FSYS, .shift = 4, .size = 4 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_FSYS1, .shift = 16, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_dout_mmc2 = {
-	.clk	= {
-		.name		= "dout_mmc2",
-	},
-	.sources = &exynos4_clkset_group,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_FSYS, .shift = 8, .size = 4 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_FSYS2, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_dout_mmc3 = {
-	.clk	= {
-		.name		= "dout_mmc3",
-	},
-	.sources = &exynos4_clkset_group,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_FSYS, .shift = 12, .size = 4 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_FSYS2, .shift = 16, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_dout_mmc4 = {
-	.clk		= {
-		.name		= "dout_mmc4",
-	},
-	.sources = &exynos4_clkset_group,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_FSYS, .shift = 16, .size = 4 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_FSYS3, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clksrcs[] = {
-	{
-		.clk	= {
-			.name		= "sclk_pwm",
-			.enable		= exynos4_clksrc_mask_peril0_ctrl,
-			.ctrlbit	= (1 << 24),
-		},
-		.sources = &exynos4_clkset_group,
-		.reg_src = { .reg = EXYNOS4_CLKSRC_PERIL0, .shift = 24, .size = 4 },
-		.reg_div = { .reg = EXYNOS4_CLKDIV_PERIL3, .shift = 0, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_csis",
-			.devname	= "s5p-mipi-csis.0",
-			.enable		= exynos4_clksrc_mask_cam_ctrl,
-			.ctrlbit	= (1 << 24),
-		},
-		.sources = &exynos4_clkset_group,
-		.reg_src = { .reg = EXYNOS4_CLKSRC_CAM, .shift = 24, .size = 4 },
-		.reg_div = { .reg = EXYNOS4_CLKDIV_CAM, .shift = 24, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_csis",
-			.devname	= "s5p-mipi-csis.1",
-			.enable		= exynos4_clksrc_mask_cam_ctrl,
-			.ctrlbit	= (1 << 28),
-		},
-		.sources = &exynos4_clkset_group,
-		.reg_src = { .reg = EXYNOS4_CLKSRC_CAM, .shift = 28, .size = 4 },
-		.reg_div = { .reg = EXYNOS4_CLKDIV_CAM, .shift = 28, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_cam0",
-			.enable		= exynos4_clksrc_mask_cam_ctrl,
-			.ctrlbit	= (1 << 16),
-		},
-		.sources = &exynos4_clkset_group,
-		.reg_src = { .reg = EXYNOS4_CLKSRC_CAM, .shift = 16, .size = 4 },
-		.reg_div = { .reg = EXYNOS4_CLKDIV_CAM, .shift = 16, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_cam1",
-			.enable		= exynos4_clksrc_mask_cam_ctrl,
-			.ctrlbit	= (1 << 20),
-		},
-		.sources = &exynos4_clkset_group,
-		.reg_src = { .reg = EXYNOS4_CLKSRC_CAM, .shift = 20, .size = 4 },
-		.reg_div = { .reg = EXYNOS4_CLKDIV_CAM, .shift = 20, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_fimc",
-			.devname	= "exynos4-fimc.0",
-			.enable		= exynos4_clksrc_mask_cam_ctrl,
-			.ctrlbit	= (1 << 0),
-		},
-		.sources = &exynos4_clkset_group,
-		.reg_src = { .reg = EXYNOS4_CLKSRC_CAM, .shift = 0, .size = 4 },
-		.reg_div = { .reg = EXYNOS4_CLKDIV_CAM, .shift = 0, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_fimc",
-			.devname	= "exynos4-fimc.1",
-			.enable		= exynos4_clksrc_mask_cam_ctrl,
-			.ctrlbit	= (1 << 4),
-		},
-		.sources = &exynos4_clkset_group,
-		.reg_src = { .reg = EXYNOS4_CLKSRC_CAM, .shift = 4, .size = 4 },
-		.reg_div = { .reg = EXYNOS4_CLKDIV_CAM, .shift = 4, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_fimc",
-			.devname	= "exynos4-fimc.2",
-			.enable		= exynos4_clksrc_mask_cam_ctrl,
-			.ctrlbit	= (1 << 8),
-		},
-		.sources = &exynos4_clkset_group,
-		.reg_src = { .reg = EXYNOS4_CLKSRC_CAM, .shift = 8, .size = 4 },
-		.reg_div = { .reg = EXYNOS4_CLKDIV_CAM, .shift = 8, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_fimc",
-			.devname	= "exynos4-fimc.3",
-			.enable		= exynos4_clksrc_mask_cam_ctrl,
-			.ctrlbit	= (1 << 12),
-		},
-		.sources = &exynos4_clkset_group,
-		.reg_src = { .reg = EXYNOS4_CLKSRC_CAM, .shift = 12, .size = 4 },
-		.reg_div = { .reg = EXYNOS4_CLKDIV_CAM, .shift = 12, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_fimd",
-			.devname	= "exynos4-fb.0",
-			.enable		= exynos4_clksrc_mask_lcd0_ctrl,
-			.ctrlbit	= (1 << 0),
-		},
-		.sources = &exynos4_clkset_group,
-		.reg_src = { .reg = EXYNOS4_CLKSRC_LCD0, .shift = 0, .size = 4 },
-		.reg_div = { .reg = EXYNOS4_CLKDIV_LCD0, .shift = 0, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_mfc",
-			.devname	= "s5p-mfc",
-		},
-		.sources = &exynos4_clkset_mout_mfc,
-		.reg_src = { .reg = EXYNOS4_CLKSRC_MFC, .shift = 8, .size = 1 },
-		.reg_div = { .reg = EXYNOS4_CLKDIV_MFC, .shift = 0, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "ciu",
-			.parent		= &exynos4_clk_dout_mmc4.clk,
-			.enable		= exynos4_clksrc_mask_fsys_ctrl,
-			.ctrlbit	= (1 << 16),
-		},
-		.reg_div = { .reg = EXYNOS4_CLKDIV_FSYS3, .shift = 8, .size = 8 },
-	}
-};
-
-static struct clksrc_clk exynos4_clk_sclk_uart0 = {
-	.clk	= {
-		.name		= "uclk1",
-		.devname	= "exynos4210-uart.0",
-		.enable		= exynos4_clksrc_mask_peril0_ctrl,
-		.ctrlbit	= (1 << 0),
-	},
-	.sources = &exynos4_clkset_group,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_PERIL0, .shift = 0, .size = 4 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_PERIL0, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_uart1 = {
-	.clk	= {
-		.name		= "uclk1",
-		.devname	= "exynos4210-uart.1",
-		.enable		= exynos4_clksrc_mask_peril0_ctrl,
-		.ctrlbit	= (1 << 4),
-	},
-	.sources = &exynos4_clkset_group,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_PERIL0, .shift = 4, .size = 4 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_PERIL0, .shift = 4, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_uart2 = {
-	.clk	= {
-		.name		= "uclk1",
-		.devname	= "exynos4210-uart.2",
-		.enable		= exynos4_clksrc_mask_peril0_ctrl,
-		.ctrlbit	= (1 << 8),
-	},
-	.sources = &exynos4_clkset_group,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_PERIL0, .shift = 8, .size = 4 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_PERIL0, .shift = 8, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_uart3 = {
-	.clk	= {
-		.name		= "uclk1",
-		.devname	= "exynos4210-uart.3",
-		.enable		= exynos4_clksrc_mask_peril0_ctrl,
-		.ctrlbit	= (1 << 12),
-	},
-	.sources = &exynos4_clkset_group,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_PERIL0, .shift = 12, .size = 4 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_PERIL0, .shift = 12, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_mmc0 = {
-	.clk	= {
-		.name		= "sclk_mmc",
-		.devname	= "exynos4-sdhci.0",
-		.parent		= &exynos4_clk_dout_mmc0.clk,
-		.enable		= exynos4_clksrc_mask_fsys_ctrl,
-		.ctrlbit	= (1 << 0),
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_FSYS1, .shift = 8, .size = 8 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_mmc1 = {
-	.clk	= {
-		.name		= "sclk_mmc",
-		.devname	= "exynos4-sdhci.1",
-		.parent		= &exynos4_clk_dout_mmc1.clk,
-		.enable		= exynos4_clksrc_mask_fsys_ctrl,
-		.ctrlbit	= (1 << 4),
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_FSYS1, .shift = 24, .size = 8 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_mmc2 = {
-	.clk	= {
-		.name		= "sclk_mmc",
-		.devname	= "exynos4-sdhci.2",
-		.parent		= &exynos4_clk_dout_mmc2.clk,
-		.enable		= exynos4_clksrc_mask_fsys_ctrl,
-		.ctrlbit	= (1 << 8),
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_FSYS2, .shift = 8, .size = 8 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_mmc3 = {
-	.clk	= {
-		.name		= "sclk_mmc",
-		.devname	= "exynos4-sdhci.3",
-		.parent		= &exynos4_clk_dout_mmc3.clk,
-		.enable		= exynos4_clksrc_mask_fsys_ctrl,
-		.ctrlbit	= (1 << 12),
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_FSYS2, .shift = 24, .size = 8 },
-};
-
-static struct clksrc_clk exynos4_clk_mdout_spi0 = {
-	.clk	= {
-		.name		= "mdout_spi",
-		.devname	= "exynos4210-spi.0",
-	},
-	.sources = &exynos4_clkset_group,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_PERIL1, .shift = 16, .size = 4 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_PERIL1, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_mdout_spi1 = {
-	.clk	= {
-		.name		= "mdout_spi",
-		.devname	= "exynos4210-spi.1",
-	},
-	.sources = &exynos4_clkset_group,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_PERIL1, .shift = 20, .size = 4 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_PERIL1, .shift = 16, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_mdout_spi2 = {
-	.clk	= {
-		.name		= "mdout_spi",
-		.devname	= "exynos4210-spi.2",
-	},
-	.sources = &exynos4_clkset_group,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_PERIL1, .shift = 24, .size = 4 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_PERIL2, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_spi0 = {
-	.clk	= {
-		.name		= "sclk_spi",
-		.devname	= "exynos4210-spi.0",
-		.parent		= &exynos4_clk_mdout_spi0.clk,
-		.enable		= exynos4_clksrc_mask_peril1_ctrl,
-		.ctrlbit	= (1 << 16),
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_PERIL1, .shift = 8, .size = 8 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_spi1 = {
-	.clk	= {
-		.name		= "sclk_spi",
-		.devname	= "exynos4210-spi.1",
-		.parent		= &exynos4_clk_mdout_spi1.clk,
-		.enable		= exynos4_clksrc_mask_peril1_ctrl,
-		.ctrlbit	= (1 << 20),
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_PERIL1, .shift = 24, .size = 8 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_spi2 = {
-	.clk	= {
-		.name		= "sclk_spi",
-		.devname	= "exynos4210-spi.2",
-		.parent		= &exynos4_clk_mdout_spi2.clk,
-		.enable		= exynos4_clksrc_mask_peril1_ctrl,
-		.ctrlbit	= (1 << 24),
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_PERIL2, .shift = 8, .size = 8 },
-};
-
-/* Clock initialization code */
-static struct clksrc_clk *exynos4_sysclks[] = {
-	&exynos4_clk_mout_apll,
-	&exynos4_clk_sclk_apll,
-	&exynos4_clk_mout_epll,
-	&exynos4_clk_mout_mpll,
-	&exynos4_clk_moutcore,
-	&exynos4_clk_coreclk,
-	&exynos4_clk_armclk,
-	&exynos4_clk_aclk_corem0,
-	&exynos4_clk_aclk_cores,
-	&exynos4_clk_aclk_corem1,
-	&exynos4_clk_periphclk,
-	&exynos4_clk_mout_corebus,
-	&exynos4_clk_sclk_dmc,
-	&exynos4_clk_aclk_cored,
-	&exynos4_clk_aclk_corep,
-	&exynos4_clk_aclk_acp,
-	&exynos4_clk_pclk_acp,
-	&exynos4_clk_vpllsrc,
-	&exynos4_clk_sclk_vpll,
-	&exynos4_clk_aclk_200,
-	&exynos4_clk_aclk_100,
-	&exynos4_clk_aclk_160,
-	&exynos4_clk_aclk_133,
-	&exynos4_clk_dout_mmc0,
-	&exynos4_clk_dout_mmc1,
-	&exynos4_clk_dout_mmc2,
-	&exynos4_clk_dout_mmc3,
-	&exynos4_clk_dout_mmc4,
-	&exynos4_clk_mout_mfc0,
-	&exynos4_clk_mout_mfc1,
-};
-
-static struct clk *exynos4_clk_cdev[] = {
-	&exynos4_clk_pdma0,
-	&exynos4_clk_pdma1,
-	&exynos4_clk_mdma1,
-	&exynos4_clk_fimd0,
-};
-
-static struct clksrc_clk *exynos4_clksrc_cdev[] = {
-	&exynos4_clk_sclk_uart0,
-	&exynos4_clk_sclk_uart1,
-	&exynos4_clk_sclk_uart2,
-	&exynos4_clk_sclk_uart3,
-	&exynos4_clk_sclk_mmc0,
-	&exynos4_clk_sclk_mmc1,
-	&exynos4_clk_sclk_mmc2,
-	&exynos4_clk_sclk_mmc3,
-	&exynos4_clk_sclk_spi0,
-	&exynos4_clk_sclk_spi1,
-	&exynos4_clk_sclk_spi2,
-	&exynos4_clk_mdout_spi0,
-	&exynos4_clk_mdout_spi1,
-	&exynos4_clk_mdout_spi2,
-};
-
-static struct clk_lookup exynos4_clk_lookup[] = {
-	CLKDEV_INIT("exynos4210-uart.0", "clk_uart_baud0", &exynos4_clk_sclk_uart0.clk),
-	CLKDEV_INIT("exynos4210-uart.1", "clk_uart_baud0", &exynos4_clk_sclk_uart1.clk),
-	CLKDEV_INIT("exynos4210-uart.2", "clk_uart_baud0", &exynos4_clk_sclk_uart2.clk),
-	CLKDEV_INIT("exynos4210-uart.3", "clk_uart_baud0", &exynos4_clk_sclk_uart3.clk),
-	CLKDEV_INIT("exynos4-sdhci.0", "mmc_busclk.2", &exynos4_clk_sclk_mmc0.clk),
-	CLKDEV_INIT("exynos4-sdhci.1", "mmc_busclk.2", &exynos4_clk_sclk_mmc1.clk),
-	CLKDEV_INIT("exynos4-sdhci.2", "mmc_busclk.2", &exynos4_clk_sclk_mmc2.clk),
-	CLKDEV_INIT("exynos4-sdhci.3", "mmc_busclk.2", &exynos4_clk_sclk_mmc3.clk),
-	CLKDEV_INIT("exynos4-fb.0", "lcd", &exynos4_clk_fimd0),
-	CLKDEV_INIT("dma-pl330.0", "apb_pclk", &exynos4_clk_pdma0),
-	CLKDEV_INIT("dma-pl330.1", "apb_pclk", &exynos4_clk_pdma1),
-	CLKDEV_INIT("dma-pl330.2", "apb_pclk", &exynos4_clk_mdma1),
-	CLKDEV_INIT("exynos4210-spi.0", "spi_busclk0", &exynos4_clk_sclk_spi0.clk),
-	CLKDEV_INIT("exynos4210-spi.1", "spi_busclk0", &exynos4_clk_sclk_spi1.clk),
-	CLKDEV_INIT("exynos4210-spi.2", "spi_busclk0", &exynos4_clk_sclk_spi2.clk),
-};
-
-static int xtal_rate;
-
-static unsigned long exynos4_fout_apll_get_rate(struct clk *clk)
-{
-	if (soc_is_exynos4210())
-		return s5p_get_pll45xx(xtal_rate, __raw_readl(EXYNOS4_APLL_CON0),
-					pll_4508);
-	else if (soc_is_exynos4212() || soc_is_exynos4412())
-		return s5p_get_pll35xx(xtal_rate, __raw_readl(EXYNOS4_APLL_CON0));
-	else
-		return 0;
-}
-
-static struct clk_ops exynos4_fout_apll_ops = {
-	.get_rate = exynos4_fout_apll_get_rate,
-};
-
-static u32 exynos4_vpll_div[][8] = {
-	{  54000000, 3, 53, 3, 1024, 0, 17, 0 },
-	{ 108000000, 3, 53, 2, 1024, 0, 17, 0 },
-};
-
-static unsigned long exynos4_vpll_get_rate(struct clk *clk)
-{
-	return clk->rate;
-}
-
-static int exynos4_vpll_set_rate(struct clk *clk, unsigned long rate)
-{
-	unsigned int vpll_con0, vpll_con1 = 0;
-	unsigned int i;
-
-	/* Return if nothing changed */
-	if (clk->rate == rate)
-		return 0;
-
-	vpll_con0 = __raw_readl(EXYNOS4_VPLL_CON0);
-	vpll_con0 &= ~(0x1 << 27 |					\
-			PLL90XX_MDIV_MASK << PLL46XX_MDIV_SHIFT |	\
-			PLL90XX_PDIV_MASK << PLL46XX_PDIV_SHIFT |	\
-			PLL90XX_SDIV_MASK << PLL46XX_SDIV_SHIFT);
-
-	vpll_con1 = __raw_readl(EXYNOS4_VPLL_CON1);
-	vpll_con1 &= ~(PLL46XX_MRR_MASK << PLL46XX_MRR_SHIFT |	\
-			PLL46XX_MFR_MASK << PLL46XX_MFR_SHIFT |	\
-			PLL4650C_KDIV_MASK << PLL46XX_KDIV_SHIFT);
-
-	for (i = 0; i < ARRAY_SIZE(exynos4_vpll_div); i++) {
-		if (exynos4_vpll_div[i][0] == rate) {
-			vpll_con0 |= exynos4_vpll_div[i][1] << PLL46XX_PDIV_SHIFT;
-			vpll_con0 |= exynos4_vpll_div[i][2] << PLL46XX_MDIV_SHIFT;
-			vpll_con0 |= exynos4_vpll_div[i][3] << PLL46XX_SDIV_SHIFT;
-			vpll_con1 |= exynos4_vpll_div[i][4] << PLL46XX_KDIV_SHIFT;
-			vpll_con1 |= exynos4_vpll_div[i][5] << PLL46XX_MFR_SHIFT;
-			vpll_con1 |= exynos4_vpll_div[i][6] << PLL46XX_MRR_SHIFT;
-			vpll_con0 |= exynos4_vpll_div[i][7] << 27;
-			break;
-		}
-	}
-
-	if (i == ARRAY_SIZE(exynos4_vpll_div)) {
-		printk(KERN_ERR "%s: Invalid Clock VPLL Frequency\n",
-				__func__);
-		return -EINVAL;
-	}
-
-	__raw_writel(vpll_con0, EXYNOS4_VPLL_CON0);
-	__raw_writel(vpll_con1, EXYNOS4_VPLL_CON1);
-
-	/* Wait for VPLL lock */
-	while (!(__raw_readl(EXYNOS4_VPLL_CON0) & (1 << PLL46XX_LOCKED_SHIFT)))
-		continue;
-
-	clk->rate = rate;
-	return 0;
-}
-
-static struct clk_ops exynos4_vpll_ops = {
-	.get_rate = exynos4_vpll_get_rate,
-	.set_rate = exynos4_vpll_set_rate,
-};
-
-void __init_or_cpufreq exynos4_setup_clocks(void)
-{
-	struct clk *xtal_clk;
-	unsigned long apll = 0;
-	unsigned long mpll = 0;
-	unsigned long epll = 0;
-	unsigned long vpll = 0;
-	unsigned long vpllsrc;
-	unsigned long xtal;
-	unsigned long armclk;
-	unsigned long sclk_dmc;
-	unsigned long aclk_200;
-	unsigned long aclk_100;
-	unsigned long aclk_160;
-	unsigned long aclk_133;
-	unsigned int ptr;
-
-	printk(KERN_DEBUG "%s: registering clocks\n", __func__);
-
-	xtal_clk = clk_get(NULL, "xtal");
-	BUG_ON(IS_ERR(xtal_clk));
-
-	xtal = clk_get_rate(xtal_clk);
-
-	xtal_rate = xtal;
-
-	clk_put(xtal_clk);
-
-	printk(KERN_DEBUG "%s: xtal is %ld\n", __func__, xtal);
-
-	if (soc_is_exynos4210()) {
-		apll = s5p_get_pll45xx(xtal, __raw_readl(EXYNOS4_APLL_CON0),
-					pll_4508);
-		mpll = s5p_get_pll45xx(xtal, __raw_readl(EXYNOS4_MPLL_CON0),
-					pll_4508);
-		epll = s5p_get_pll46xx(xtal, __raw_readl(EXYNOS4_EPLL_CON0),
-					__raw_readl(EXYNOS4_EPLL_CON1), pll_4600);
-
-		vpllsrc = clk_get_rate(&exynos4_clk_vpllsrc.clk);
-		vpll = s5p_get_pll46xx(vpllsrc, __raw_readl(EXYNOS4_VPLL_CON0),
-					__raw_readl(EXYNOS4_VPLL_CON1), pll_4650c);
-	} else if (soc_is_exynos4212() || soc_is_exynos4412()) {
-		apll = s5p_get_pll35xx(xtal, __raw_readl(EXYNOS4_APLL_CON0));
-		mpll = s5p_get_pll35xx(xtal, __raw_readl(EXYNOS4_MPLL_CON0));
-		epll = s5p_get_pll36xx(xtal, __raw_readl(EXYNOS4_EPLL_CON0),
-					__raw_readl(EXYNOS4_EPLL_CON1));
-
-		vpllsrc = clk_get_rate(&exynos4_clk_vpllsrc.clk);
-		vpll = s5p_get_pll36xx(vpllsrc, __raw_readl(EXYNOS4_VPLL_CON0),
-					__raw_readl(EXYNOS4_VPLL_CON1));
-	} else {
-		/* nothing */
-	}
-
-	clk_fout_apll.ops = &exynos4_fout_apll_ops;
-	clk_fout_mpll.rate = mpll;
-	clk_fout_epll.rate = epll;
-	clk_fout_vpll.ops = &exynos4_vpll_ops;
-	clk_fout_vpll.rate = vpll;
-
-	printk(KERN_INFO "EXYNOS4: PLL settings, A=%ld, M=%ld, E=%ld V=%ld",
-			apll, mpll, epll, vpll);
-
-	armclk = clk_get_rate(&exynos4_clk_armclk.clk);
-	sclk_dmc = clk_get_rate(&exynos4_clk_sclk_dmc.clk);
-
-	aclk_200 = clk_get_rate(&exynos4_clk_aclk_200.clk);
-	aclk_100 = clk_get_rate(&exynos4_clk_aclk_100.clk);
-	aclk_160 = clk_get_rate(&exynos4_clk_aclk_160.clk);
-	aclk_133 = clk_get_rate(&exynos4_clk_aclk_133.clk);
-
-	printk(KERN_INFO "EXYNOS4: ARMCLK=%ld, DMC=%ld, ACLK200=%ld\n"
-			 "ACLK100=%ld, ACLK160=%ld, ACLK133=%ld\n",
-			armclk, sclk_dmc, aclk_200,
-			aclk_100, aclk_160, aclk_133);
-
-	clk_f.rate = armclk;
-	clk_h.rate = sclk_dmc;
-	clk_p.rate = aclk_100;
-
-	for (ptr = 0; ptr < ARRAY_SIZE(exynos4_clksrcs); ptr++)
-		s3c_set_clksrc(&exynos4_clksrcs[ptr], true);
-}
-
-static struct clk *exynos4_clks[] __initdata = {
-	&exynos4_clk_sclk_hdmi27m,
-	&exynos4_clk_sclk_hdmiphy,
-	&exynos4_clk_sclk_usbphy0,
-	&exynos4_clk_sclk_usbphy1,
-};
-
-#ifdef CONFIG_PM_SLEEP
-static int exynos4_clock_suspend(void)
-{
-	s3c_pm_do_save(exynos4_clock_save, ARRAY_SIZE(exynos4_clock_save));
-	return 0;
-}
-
-static void exynos4_clock_resume(void)
-{
-	s3c_pm_do_restore_core(exynos4_clock_save, ARRAY_SIZE(exynos4_clock_save));
-}
-
-#else
-#define exynos4_clock_suspend NULL
-#define exynos4_clock_resume NULL
-#endif
-
-static struct syscore_ops exynos4_clock_syscore_ops = {
-	.suspend	= exynos4_clock_suspend,
-	.resume		= exynos4_clock_resume,
-};
-
-void __init exynos4_register_clocks(void)
-{
-	int ptr;
-
-	s3c24xx_register_clocks(exynos4_clks, ARRAY_SIZE(exynos4_clks));
-
-	for (ptr = 0; ptr < ARRAY_SIZE(exynos4_sysclks); ptr++)
-		s3c_register_clksrc(exynos4_sysclks[ptr], 1);
-
-	for (ptr = 0; ptr < ARRAY_SIZE(exynos4_sclk_tv); ptr++)
-		s3c_register_clksrc(exynos4_sclk_tv[ptr], 1);
-
-	for (ptr = 0; ptr < ARRAY_SIZE(exynos4_clksrc_cdev); ptr++)
-		s3c_register_clksrc(exynos4_clksrc_cdev[ptr], 1);
-
-	s3c_register_clksrc(exynos4_clksrcs, ARRAY_SIZE(exynos4_clksrcs));
-	s3c_register_clocks(exynos4_init_clocks_on, ARRAY_SIZE(exynos4_init_clocks_on));
-
-	s3c24xx_register_clocks(exynos4_clk_cdev, ARRAY_SIZE(exynos4_clk_cdev));
-	for (ptr = 0; ptr < ARRAY_SIZE(exynos4_clk_cdev); ptr++)
-		s3c_disable_clocks(exynos4_clk_cdev[ptr], 1);
-
-	s3c_register_clocks(exynos4_init_clocks_off, ARRAY_SIZE(exynos4_init_clocks_off));
-	s3c_disable_clocks(exynos4_init_clocks_off, ARRAY_SIZE(exynos4_init_clocks_off));
-	clkdev_add_table(exynos4_clk_lookup, ARRAY_SIZE(exynos4_clk_lookup));
-
-	register_syscore_ops(&exynos4_clock_syscore_ops);
-	s3c24xx_register_clock(&dummy_apb_pclk);
-
-	s3c_pwmclk_init();
-}
diff --git a/arch/arm/mach-exynos/clock-exynos4.h b/arch/arm/mach-exynos/clock-exynos4.h
deleted file mode 100644
index bd12d5f..0000000
--- a/arch/arm/mach-exynos/clock-exynos4.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2011-2012 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * Header file for exynos4 clock 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_CLOCK_H
-#define __ASM_ARCH_CLOCK_H __FILE__
-
-#include <linux/clk.h>
-
-extern struct clksrc_clk exynos4_clk_aclk_133;
-extern struct clksrc_clk exynos4_clk_mout_mpll;
-
-extern struct clksrc_sources exynos4_clkset_mout_corebus;
-extern struct clksrc_sources exynos4_clkset_group;
-
-extern struct clk *exynos4_clkset_aclk_top_list[];
-extern struct clk *exynos4_clkset_group_list[];
-
-extern struct clksrc_sources exynos4_clkset_mout_g2d0;
-extern struct clksrc_sources exynos4_clkset_mout_g2d1;
-
-extern int exynos4_clksrc_mask_fsys_ctrl(struct clk *clk, int enable);
-extern int exynos4_clk_ip_fsys_ctrl(struct clk *clk, int enable);
-extern int exynos4_clk_ip_lcd1_ctrl(struct clk *clk, int enable);
-extern int exynos4_clk_ip_image_ctrl(struct clk *clk, int enable);
-extern int exynos4_clk_ip_dmc_ctrl(struct clk *clk, int enable);
-
-#endif /* __ASM_ARCH_CLOCK_H */
diff --git a/arch/arm/mach-exynos/clock-exynos4210.c b/arch/arm/mach-exynos/clock-exynos4210.c
deleted file mode 100644
index 19af9f7..0000000
--- a/arch/arm/mach-exynos/clock-exynos4210.c
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * Copyright (c) 2011-2012 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * EXYNOS4210 - Clock 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/err.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/syscore_ops.h>
-
-#include <plat/cpu-freq.h>
-#include <plat/clock.h>
-#include <plat/cpu.h>
-#include <plat/pll.h>
-#include <plat/s5p-clock.h>
-#include <plat/clock-clksrc.h>
-#include <plat/pm.h>
-
-#include <mach/hardware.h>
-#include <mach/map.h>
-#include <mach/regs-clock.h>
-
-#include "common.h"
-#include "clock-exynos4.h"
-
-#ifdef CONFIG_PM_SLEEP
-static struct sleep_save exynos4210_clock_save[] = {
-	SAVE_ITEM(EXYNOS4_CLKSRC_IMAGE),
-	SAVE_ITEM(EXYNOS4_CLKDIV_IMAGE),
-	SAVE_ITEM(EXYNOS4210_CLKSRC_LCD1),
-	SAVE_ITEM(EXYNOS4210_CLKDIV_LCD1),
-	SAVE_ITEM(EXYNOS4210_CLKSRC_MASK_LCD1),
-	SAVE_ITEM(EXYNOS4210_CLKGATE_IP_IMAGE),
-	SAVE_ITEM(EXYNOS4210_CLKGATE_IP_LCD1),
-	SAVE_ITEM(EXYNOS4210_CLKGATE_IP_PERIR),
-};
-#endif
-
-static struct clksrc_clk *sysclks[] = {
-	/* nothing here yet */
-};
-
-static struct clksrc_clk exynos4210_clk_mout_g2d0 = {
-	.clk	= {
-		.name		= "mout_g2d0",
-	},
-	.sources = &exynos4_clkset_mout_g2d0,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_IMAGE, .shift = 0, .size = 1 },
-};
-
-static struct clksrc_clk exynos4210_clk_mout_g2d1 = {
-	.clk	= {
-		.name		= "mout_g2d1",
-	},
-	.sources = &exynos4_clkset_mout_g2d1,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_IMAGE, .shift = 4, .size = 1 },
-};
-
-static struct clk *exynos4210_clkset_mout_g2d_list[] = {
-	[0] = &exynos4210_clk_mout_g2d0.clk,
-	[1] = &exynos4210_clk_mout_g2d1.clk,
-};
-
-static struct clksrc_sources exynos4210_clkset_mout_g2d = {
-	.sources	= exynos4210_clkset_mout_g2d_list,
-	.nr_sources	= ARRAY_SIZE(exynos4210_clkset_mout_g2d_list),
-};
-
-static int exynos4_clksrc_mask_lcd1_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4210_CLKSRC_MASK_LCD1, clk, enable);
-}
-
-static struct clksrc_clk clksrcs[] = {
-	{
-		.clk		= {
-			.name		= "sclk_sata",
-			.id		= -1,
-			.enable		= exynos4_clksrc_mask_fsys_ctrl,
-			.ctrlbit	= (1 << 24),
-		},
-		.sources = &exynos4_clkset_mout_corebus,
-		.reg_src = { .reg = EXYNOS4_CLKSRC_FSYS, .shift = 24, .size = 1 },
-		.reg_div = { .reg = EXYNOS4_CLKDIV_FSYS0, .shift = 20, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_fimd",
-			.devname	= "exynos4-fb.1",
-			.enable		= exynos4_clksrc_mask_lcd1_ctrl,
-			.ctrlbit	= (1 << 0),
-		},
-		.sources = &exynos4_clkset_group,
-		.reg_src = { .reg = EXYNOS4210_CLKSRC_LCD1, .shift = 0, .size = 4 },
-		.reg_div = { .reg = EXYNOS4210_CLKDIV_LCD1, .shift = 0, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_fimg2d",
-		},
-		.sources = &exynos4210_clkset_mout_g2d,
-		.reg_src = { .reg = EXYNOS4_CLKSRC_IMAGE, .shift = 8, .size = 1 },
-		.reg_div = { .reg = EXYNOS4_CLKDIV_IMAGE, .shift = 0, .size = 4 },
-	},
-};
-
-static struct clk init_clocks_off[] = {
-	{
-		.name		= "sataphy",
-		.id		= -1,
-		.parent		= &exynos4_clk_aclk_133.clk,
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 3),
-	}, {
-		.name		= "sata",
-		.id		= -1,
-		.parent		= &exynos4_clk_aclk_133.clk,
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 10),
-	}, {
-		.name		= "fimd",
-		.devname	= "exynos4-fb.1",
-		.enable		= exynos4_clk_ip_lcd1_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "sysmmu",
-		.devname	= "exynos-sysmmu.9",
-		.enable		= exynos4_clk_ip_image_ctrl,
-		.ctrlbit	= (1 << 3),
-	}, {
-		.name		= "sysmmu",
-		.devname	= "exynos-sysmmu.11",
-		.enable		= exynos4_clk_ip_lcd1_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
-		.name		= "fimg2d",
-		.enable		= exynos4_clk_ip_image_ctrl,
-		.ctrlbit	= (1 << 0),
-	},
-};
-
-#ifdef CONFIG_PM_SLEEP
-static int exynos4210_clock_suspend(void)
-{
-	s3c_pm_do_save(exynos4210_clock_save, ARRAY_SIZE(exynos4210_clock_save));
-
-	return 0;
-}
-
-static void exynos4210_clock_resume(void)
-{
-	s3c_pm_do_restore_core(exynos4210_clock_save, ARRAY_SIZE(exynos4210_clock_save));
-}
-
-#else
-#define exynos4210_clock_suspend NULL
-#define exynos4210_clock_resume NULL
-#endif
-
-static struct syscore_ops exynos4210_clock_syscore_ops = {
-	.suspend	= exynos4210_clock_suspend,
-	.resume		= exynos4210_clock_resume,
-};
-
-void __init exynos4210_register_clocks(void)
-{
-	int ptr;
-
-	exynos4_clk_mout_mpll.reg_src.reg = EXYNOS4_CLKSRC_CPU;
-	exynos4_clk_mout_mpll.reg_src.shift = 8;
-	exynos4_clk_mout_mpll.reg_src.size = 1;
-
-	for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
-		s3c_register_clksrc(sysclks[ptr], 1);
-
-	s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
-
-	s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
-	s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
-
-	register_syscore_ops(&exynos4210_clock_syscore_ops);
-}
diff --git a/arch/arm/mach-exynos/clock-exynos4212.c b/arch/arm/mach-exynos/clock-exynos4212.c
deleted file mode 100644
index 529476f..0000000
--- a/arch/arm/mach-exynos/clock-exynos4212.c
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * Copyright (c) 2011-2012 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * EXYNOS4212 - Clock 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/err.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/syscore_ops.h>
-
-#include <plat/cpu-freq.h>
-#include <plat/clock.h>
-#include <plat/cpu.h>
-#include <plat/pll.h>
-#include <plat/s5p-clock.h>
-#include <plat/clock-clksrc.h>
-#include <plat/pm.h>
-
-#include <mach/hardware.h>
-#include <mach/map.h>
-#include <mach/regs-clock.h>
-
-#include "common.h"
-#include "clock-exynos4.h"
-
-#ifdef CONFIG_PM_SLEEP
-static struct sleep_save exynos4212_clock_save[] = {
-	SAVE_ITEM(EXYNOS4_CLKSRC_IMAGE),
-	SAVE_ITEM(EXYNOS4_CLKDIV_IMAGE),
-	SAVE_ITEM(EXYNOS4212_CLKGATE_IP_IMAGE),
-	SAVE_ITEM(EXYNOS4212_CLKGATE_IP_PERIR),
-};
-#endif
-
-static int exynos4212_clk_ip_isp0_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKGATE_IP_ISP0, clk, enable);
-}
-
-static int exynos4212_clk_ip_isp1_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKGATE_IP_ISP1, clk, enable);
-}
-
-static struct clk *clk_src_mpll_user_list[] = {
-	[0] = &clk_fin_mpll,
-	[1] = &exynos4_clk_mout_mpll.clk,
-};
-
-static struct clksrc_sources clk_src_mpll_user = {
-	.sources	= clk_src_mpll_user_list,
-	.nr_sources	= ARRAY_SIZE(clk_src_mpll_user_list),
-};
-
-static struct clksrc_clk clk_mout_mpll_user = {
-	.clk = {
-		.name		= "mout_mpll_user",
-	},
-	.sources	= &clk_src_mpll_user,
-	.reg_src	= { .reg = EXYNOS4_CLKSRC_CPU, .shift = 24, .size = 1 },
-};
-
-static struct clksrc_clk exynos4x12_clk_mout_g2d0 = {
-	.clk	= {
-		.name		= "mout_g2d0",
-	},
-	.sources = &exynos4_clkset_mout_g2d0,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_DMC, .shift = 20, .size = 1 },
-};
-
-static struct clksrc_clk exynos4x12_clk_mout_g2d1 = {
-	.clk	= {
-		.name		= "mout_g2d1",
-	},
-	.sources = &exynos4_clkset_mout_g2d1,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_DMC, .shift = 24, .size = 1 },
-};
-
-static struct clk *exynos4x12_clkset_mout_g2d_list[] = {
-	[0] = &exynos4x12_clk_mout_g2d0.clk,
-	[1] = &exynos4x12_clk_mout_g2d1.clk,
-};
-
-static struct clksrc_sources exynos4x12_clkset_mout_g2d = {
-	.sources	= exynos4x12_clkset_mout_g2d_list,
-	.nr_sources	= ARRAY_SIZE(exynos4x12_clkset_mout_g2d_list),
-};
-
-static struct clksrc_clk *sysclks[] = {
-	&clk_mout_mpll_user,
-};
-
-static struct clksrc_clk clksrcs[] = {
-	{
-		.clk	= {
-			.name		= "sclk_fimg2d",
-		},
-		.sources = &exynos4x12_clkset_mout_g2d,
-		.reg_src = { .reg = EXYNOS4_CLKSRC_DMC, .shift = 28, .size = 1 },
-		.reg_div = { .reg = EXYNOS4_CLKDIV_DMC1, .shift = 0, .size = 4 },
-	},
-};
-
-static struct clk init_clocks_off[] = {
-	{
-		.name		= "sysmmu",
-		.devname	= "exynos-sysmmu.9",
-		.enable		= exynos4_clk_ip_dmc_ctrl,
-		.ctrlbit	= (1 << 24),
-	}, {
-		.name		= "sysmmu",
-		.devname	= "exynos-sysmmu.12",
-		.enable		= exynos4212_clk_ip_isp0_ctrl,
-		.ctrlbit	= (7 << 8),
-	}, {
-		.name		= "sysmmu",
-		.devname	= "exynos-sysmmu.13",
-		.enable		= exynos4212_clk_ip_isp1_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
-		.name		= "sysmmu",
-		.devname	= "exynos-sysmmu.14",
-		.enable		= exynos4212_clk_ip_isp0_ctrl,
-		.ctrlbit	= (1 << 11),
-	}, {
-		.name		= "sysmmu",
-		.devname	= "exynos-sysmmu.15",
-		.enable		= exynos4212_clk_ip_isp0_ctrl,
-		.ctrlbit	= (1 << 12),
-	}, {
-		.name		= "flite",
-		.devname	= "exynos-fimc-lite.0",
-		.enable		= exynos4212_clk_ip_isp0_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
-		.name		= "flite",
-		.devname	= "exynos-fimc-lite.1",
-		.enable		= exynos4212_clk_ip_isp0_ctrl,
-		.ctrlbit	= (1 << 3),
-	}, {
-		.name		= "fimg2d",
-		.enable		= exynos4_clk_ip_dmc_ctrl,
-		.ctrlbit	= (1 << 23),
-	},
-};
-
-#ifdef CONFIG_PM_SLEEP
-static int exynos4212_clock_suspend(void)
-{
-	s3c_pm_do_save(exynos4212_clock_save, ARRAY_SIZE(exynos4212_clock_save));
-
-	return 0;
-}
-
-static void exynos4212_clock_resume(void)
-{
-	s3c_pm_do_restore_core(exynos4212_clock_save, ARRAY_SIZE(exynos4212_clock_save));
-}
-
-#else
-#define exynos4212_clock_suspend NULL
-#define exynos4212_clock_resume NULL
-#endif
-
-static struct syscore_ops exynos4212_clock_syscore_ops = {
-	.suspend	= exynos4212_clock_suspend,
-	.resume		= exynos4212_clock_resume,
-};
-
-void __init exynos4212_register_clocks(void)
-{
-	int ptr;
-
-	/* usbphy1 is removed */
-	exynos4_clkset_group_list[4] = NULL;
-
-	/* mout_mpll_user is used */
-	exynos4_clkset_group_list[6] = &clk_mout_mpll_user.clk;
-	exynos4_clkset_aclk_top_list[0] = &clk_mout_mpll_user.clk;
-
-	exynos4_clk_mout_mpll.reg_src.reg = EXYNOS4_CLKSRC_DMC;
-	exynos4_clk_mout_mpll.reg_src.shift = 12;
-	exynos4_clk_mout_mpll.reg_src.size = 1;
-
-	for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
-		s3c_register_clksrc(sysclks[ptr], 1);
-
-	s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
-
-	s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
-	s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
-
-	register_syscore_ops(&exynos4212_clock_syscore_ops);
-}
diff --git a/arch/arm/mach-exynos/clock-exynos5.c b/arch/arm/mach-exynos/clock-exynos5.c
deleted file mode 100644
index b0ea31f..0000000
--- a/arch/arm/mach-exynos/clock-exynos5.c
+++ /dev/null
@@ -1,1645 +0,0 @@
-/*
- * Copyright (c) 2012 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * Clock support for EXYNOS5 SoCs
- *
- * This program is free software; you can 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/err.h>
-#include <linux/io.h>
-#include <linux/syscore_ops.h>
-
-#include <plat/cpu-freq.h>
-#include <plat/clock.h>
-#include <plat/cpu.h>
-#include <plat/pll.h>
-#include <plat/s5p-clock.h>
-#include <plat/clock-clksrc.h>
-#include <plat/pm.h>
-
-#include <mach/map.h>
-#include <mach/regs-clock.h>
-
-#include "common.h"
-
-#ifdef CONFIG_PM_SLEEP
-static struct sleep_save exynos5_clock_save[] = {
-	SAVE_ITEM(EXYNOS5_CLKSRC_MASK_TOP),
-	SAVE_ITEM(EXYNOS5_CLKSRC_MASK_GSCL),
-	SAVE_ITEM(EXYNOS5_CLKSRC_MASK_DISP1_0),
-	SAVE_ITEM(EXYNOS5_CLKSRC_MASK_FSYS),
-	SAVE_ITEM(EXYNOS5_CLKSRC_MASK_MAUDIO),
-	SAVE_ITEM(EXYNOS5_CLKSRC_MASK_PERIC0),
-	SAVE_ITEM(EXYNOS5_CLKSRC_MASK_PERIC1),
-	SAVE_ITEM(EXYNOS5_CLKGATE_IP_GSCL),
-	SAVE_ITEM(EXYNOS5_CLKGATE_IP_DISP1),
-	SAVE_ITEM(EXYNOS5_CLKGATE_IP_MFC),
-	SAVE_ITEM(EXYNOS5_CLKGATE_IP_G3D),
-	SAVE_ITEM(EXYNOS5_CLKGATE_IP_GEN),
-	SAVE_ITEM(EXYNOS5_CLKGATE_IP_FSYS),
-	SAVE_ITEM(EXYNOS5_CLKGATE_IP_PERIC),
-	SAVE_ITEM(EXYNOS5_CLKGATE_IP_PERIS),
-	SAVE_ITEM(EXYNOS5_CLKGATE_BLOCK),
-	SAVE_ITEM(EXYNOS5_CLKDIV_TOP0),
-	SAVE_ITEM(EXYNOS5_CLKDIV_TOP1),
-	SAVE_ITEM(EXYNOS5_CLKDIV_GSCL),
-	SAVE_ITEM(EXYNOS5_CLKDIV_DISP1_0),
-	SAVE_ITEM(EXYNOS5_CLKDIV_GEN),
-	SAVE_ITEM(EXYNOS5_CLKDIV_MAUDIO),
-	SAVE_ITEM(EXYNOS5_CLKDIV_FSYS0),
-	SAVE_ITEM(EXYNOS5_CLKDIV_FSYS1),
-	SAVE_ITEM(EXYNOS5_CLKDIV_FSYS2),
-	SAVE_ITEM(EXYNOS5_CLKDIV_FSYS3),
-	SAVE_ITEM(EXYNOS5_CLKDIV_PERIC0),
-	SAVE_ITEM(EXYNOS5_CLKDIV_PERIC1),
-	SAVE_ITEM(EXYNOS5_CLKDIV_PERIC2),
-	SAVE_ITEM(EXYNOS5_CLKDIV_PERIC3),
-	SAVE_ITEM(EXYNOS5_CLKDIV_PERIC4),
-	SAVE_ITEM(EXYNOS5_CLKDIV_PERIC5),
-	SAVE_ITEM(EXYNOS5_SCLK_DIV_ISP),
-	SAVE_ITEM(EXYNOS5_CLKSRC_TOP0),
-	SAVE_ITEM(EXYNOS5_CLKSRC_TOP1),
-	SAVE_ITEM(EXYNOS5_CLKSRC_TOP2),
-	SAVE_ITEM(EXYNOS5_CLKSRC_TOP3),
-	SAVE_ITEM(EXYNOS5_CLKSRC_GSCL),
-	SAVE_ITEM(EXYNOS5_CLKSRC_DISP1_0),
-	SAVE_ITEM(EXYNOS5_CLKSRC_MAUDIO),
-	SAVE_ITEM(EXYNOS5_CLKSRC_FSYS),
-	SAVE_ITEM(EXYNOS5_CLKSRC_PERIC0),
-	SAVE_ITEM(EXYNOS5_CLKSRC_PERIC1),
-	SAVE_ITEM(EXYNOS5_SCLK_SRC_ISP),
-	SAVE_ITEM(EXYNOS5_EPLL_CON0),
-	SAVE_ITEM(EXYNOS5_EPLL_CON1),
-	SAVE_ITEM(EXYNOS5_EPLL_CON2),
-	SAVE_ITEM(EXYNOS5_VPLL_CON0),
-	SAVE_ITEM(EXYNOS5_VPLL_CON1),
-	SAVE_ITEM(EXYNOS5_VPLL_CON2),
-	SAVE_ITEM(EXYNOS5_PWR_CTRL1),
-	SAVE_ITEM(EXYNOS5_PWR_CTRL2),
-};
-#endif
-
-static struct clk exynos5_clk_sclk_dptxphy = {
-	.name		= "sclk_dptx",
-};
-
-static struct clk exynos5_clk_sclk_hdmi24m = {
-	.name		= "sclk_hdmi24m",
-	.rate		= 24000000,
-};
-
-static struct clk exynos5_clk_sclk_hdmi27m = {
-	.name		= "sclk_hdmi27m",
-	.rate		= 27000000,
-};
-
-static struct clk exynos5_clk_sclk_hdmiphy = {
-	.name		= "sclk_hdmiphy",
-};
-
-static struct clk exynos5_clk_sclk_usbphy = {
-	.name		= "sclk_usbphy",
-	.rate		= 48000000,
-};
-
-static int exynos5_clksrc_mask_top_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS5_CLKSRC_MASK_TOP, clk, enable);
-}
-
-static int exynos5_clksrc_mask_disp1_0_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS5_CLKSRC_MASK_DISP1_0, clk, enable);
-}
-
-static int exynos5_clksrc_mask_fsys_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS5_CLKSRC_MASK_FSYS, clk, enable);
-}
-
-static int exynos5_clksrc_mask_gscl_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS5_CLKSRC_MASK_GSCL, clk, enable);
-}
-
-static int exynos5_clksrc_mask_peric0_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS5_CLKSRC_MASK_PERIC0, clk, enable);
-}
-
-static int exynos5_clksrc_mask_peric1_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS5_CLKSRC_MASK_PERIC1, clk, enable);
-}
-
-static int exynos5_clk_ip_acp_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS5_CLKGATE_IP_ACP, clk, enable);
-}
-
-static int exynos5_clk_ip_core_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS5_CLKGATE_IP_CORE, clk, enable);
-}
-
-static int exynos5_clk_ip_disp1_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS5_CLKGATE_IP_DISP1, clk, enable);
-}
-
-static int exynos5_clk_ip_fsys_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS5_CLKGATE_IP_FSYS, clk, enable);
-}
-
-static int exynos5_clk_block_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS5_CLKGATE_BLOCK, clk, enable);
-}
-
-static int exynos5_clk_ip_gen_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS5_CLKGATE_IP_GEN, clk, enable);
-}
-
-static int exynos5_clk_ip_mfc_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS5_CLKGATE_IP_MFC, clk, enable);
-}
-
-static int exynos5_clk_ip_peric_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS5_CLKGATE_IP_PERIC, clk, enable);
-}
-
-static int exynos5_clk_ip_peris_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS5_CLKGATE_IP_PERIS, clk, enable);
-}
-
-static int exynos5_clk_ip_gscl_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS5_CLKGATE_IP_GSCL, clk, enable);
-}
-
-static int exynos5_clk_ip_isp0_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS5_CLKGATE_IP_ISP0, clk, enable);
-}
-
-static int exynos5_clk_ip_isp1_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS5_CLKGATE_IP_ISP1, clk, enable);
-}
-
-static int exynos5_clk_hdmiphy_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_HDMI_PHY_CONTROL, clk, enable);
-}
-
-/* Core list of CMU_CPU side */
-
-static struct clksrc_clk exynos5_clk_mout_apll = {
-	.clk	= {
-		.name		= "mout_apll",
-	},
-	.sources = &clk_src_apll,
-	.reg_src = { .reg = EXYNOS5_CLKSRC_CPU, .shift = 0, .size = 1 },
-};
-
-static struct clksrc_clk exynos5_clk_sclk_apll = {
-	.clk	= {
-		.name		= "sclk_apll",
-		.parent		= &exynos5_clk_mout_apll.clk,
-	},
-	.reg_div = { .reg = EXYNOS5_CLKDIV_CPU0, .shift = 24, .size = 3 },
-};
-
-static struct clksrc_clk exynos5_clk_mout_bpll_fout = {
-	.clk	= {
-		.name		= "mout_bpll_fout",
-	},
-	.sources = &clk_src_bpll_fout,
-	.reg_src = { .reg = EXYNOS5_PLL_DIV2_SEL, .shift = 0, .size = 1 },
-};
-
-static struct clk *exynos5_clk_src_bpll_list[] = {
-	[0] = &clk_fin_bpll,
-	[1] = &exynos5_clk_mout_bpll_fout.clk,
-};
-
-static struct clksrc_sources exynos5_clk_src_bpll = {
-	.sources	= exynos5_clk_src_bpll_list,
-	.nr_sources	= ARRAY_SIZE(exynos5_clk_src_bpll_list),
-};
-
-static struct clksrc_clk exynos5_clk_mout_bpll = {
-	.clk	= {
-		.name		= "mout_bpll",
-	},
-	.sources = &exynos5_clk_src_bpll,
-	.reg_src = { .reg = EXYNOS5_CLKSRC_CDREX, .shift = 0, .size = 1 },
-};
-
-static struct clk *exynos5_clk_src_bpll_user_list[] = {
-	[0] = &clk_fin_mpll,
-	[1] = &exynos5_clk_mout_bpll.clk,
-};
-
-static struct clksrc_sources exynos5_clk_src_bpll_user = {
-	.sources	= exynos5_clk_src_bpll_user_list,
-	.nr_sources	= ARRAY_SIZE(exynos5_clk_src_bpll_user_list),
-};
-
-static struct clksrc_clk exynos5_clk_mout_bpll_user = {
-	.clk	= {
-		.name		= "mout_bpll_user",
-	},
-	.sources = &exynos5_clk_src_bpll_user,
-	.reg_src = { .reg = EXYNOS5_CLKSRC_TOP2, .shift = 24, .size = 1 },
-};
-
-static struct clksrc_clk exynos5_clk_mout_cpll = {
-	.clk	= {
-		.name		= "mout_cpll",
-	},
-	.sources = &clk_src_cpll,
-	.reg_src = { .reg = EXYNOS5_CLKSRC_TOP2, .shift = 8, .size = 1 },
-};
-
-static struct clksrc_clk exynos5_clk_mout_epll = {
-	.clk	= {
-		.name		= "mout_epll",
-	},
-	.sources = &clk_src_epll,
-	.reg_src = { .reg = EXYNOS5_CLKSRC_TOP2, .shift = 12, .size = 1 },
-};
-
-static struct clksrc_clk exynos5_clk_mout_mpll_fout = {
-	.clk	= {
-		.name		= "mout_mpll_fout",
-	},
-	.sources = &clk_src_mpll_fout,
-	.reg_src = { .reg = EXYNOS5_PLL_DIV2_SEL, .shift = 4, .size = 1 },
-};
-
-static struct clk *exynos5_clk_src_mpll_list[] = {
-	[0] = &clk_fin_mpll,
-	[1] = &exynos5_clk_mout_mpll_fout.clk,
-};
-
-static struct clksrc_sources exynos5_clk_src_mpll = {
-	.sources	= exynos5_clk_src_mpll_list,
-	.nr_sources	= ARRAY_SIZE(exynos5_clk_src_mpll_list),
-};
-
-static struct clksrc_clk exynos5_clk_mout_mpll = {
-	.clk = {
-		.name		= "mout_mpll",
-	},
-	.sources = &exynos5_clk_src_mpll,
-	.reg_src = { .reg = EXYNOS5_CLKSRC_CORE1, .shift = 8, .size = 1 },
-};
-
-static struct clk *exynos_clkset_vpllsrc_list[] = {
-	[0] = &clk_fin_vpll,
-	[1] = &exynos5_clk_sclk_hdmi27m,
-};
-
-static struct clksrc_sources exynos5_clkset_vpllsrc = {
-	.sources	= exynos_clkset_vpllsrc_list,
-	.nr_sources	= ARRAY_SIZE(exynos_clkset_vpllsrc_list),
-};
-
-static struct clksrc_clk exynos5_clk_vpllsrc = {
-	.clk	= {
-		.name		= "vpll_src",
-		.enable		= exynos5_clksrc_mask_top_ctrl,
-		.ctrlbit	= (1 << 0),
-	},
-	.sources = &exynos5_clkset_vpllsrc,
-	.reg_src = { .reg = EXYNOS5_CLKSRC_TOP2, .shift = 0, .size = 1 },
-};
-
-static struct clk *exynos5_clkset_sclk_vpll_list[] = {
-	[0] = &exynos5_clk_vpllsrc.clk,
-	[1] = &clk_fout_vpll,
-};
-
-static struct clksrc_sources exynos5_clkset_sclk_vpll = {
-	.sources	= exynos5_clkset_sclk_vpll_list,
-	.nr_sources	= ARRAY_SIZE(exynos5_clkset_sclk_vpll_list),
-};
-
-static struct clksrc_clk exynos5_clk_sclk_vpll = {
-	.clk	= {
-		.name		= "sclk_vpll",
-	},
-	.sources = &exynos5_clkset_sclk_vpll,
-	.reg_src = { .reg = EXYNOS5_CLKSRC_TOP2, .shift = 16, .size = 1 },
-};
-
-static struct clksrc_clk exynos5_clk_sclk_pixel = {
-	.clk	= {
-		.name		= "sclk_pixel",
-		.parent		= &exynos5_clk_sclk_vpll.clk,
-	},
-	.reg_div = { .reg = EXYNOS5_CLKDIV_DISP1_0, .shift = 28, .size = 4 },
-};
-
-static struct clk *exynos5_clkset_sclk_hdmi_list[] = {
-	[0] = &exynos5_clk_sclk_pixel.clk,
-	[1] = &exynos5_clk_sclk_hdmiphy,
-};
-
-static struct clksrc_sources exynos5_clkset_sclk_hdmi = {
-	.sources	= exynos5_clkset_sclk_hdmi_list,
-	.nr_sources	= ARRAY_SIZE(exynos5_clkset_sclk_hdmi_list),
-};
-
-static struct clksrc_clk exynos5_clk_sclk_hdmi = {
-	.clk	= {
-		.name		= "sclk_hdmi",
-		.enable		= exynos5_clksrc_mask_disp1_0_ctrl,
-		.ctrlbit	= (1 << 20),
-	},
-	.sources = &exynos5_clkset_sclk_hdmi,
-	.reg_src = { .reg = EXYNOS5_CLKSRC_DISP1_0, .shift = 20, .size = 1 },
-};
-
-static struct clksrc_clk *exynos5_sclk_tv[] = {
-	&exynos5_clk_sclk_pixel,
-	&exynos5_clk_sclk_hdmi,
-};
-
-static struct clk *exynos5_clk_src_mpll_user_list[] = {
-	[0] = &clk_fin_mpll,
-	[1] = &exynos5_clk_mout_mpll.clk,
-};
-
-static struct clksrc_sources exynos5_clk_src_mpll_user = {
-	.sources	= exynos5_clk_src_mpll_user_list,
-	.nr_sources	= ARRAY_SIZE(exynos5_clk_src_mpll_user_list),
-};
-
-static struct clksrc_clk exynos5_clk_mout_mpll_user = {
-	.clk	= {
-		.name		= "mout_mpll_user",
-	},
-	.sources = &exynos5_clk_src_mpll_user,
-	.reg_src = { .reg = EXYNOS5_CLKSRC_TOP2, .shift = 20, .size = 1 },
-};
-
-static struct clk *exynos5_clkset_mout_cpu_list[] = {
-	[0] = &exynos5_clk_mout_apll.clk,
-	[1] = &exynos5_clk_mout_mpll.clk,
-};
-
-static struct clksrc_sources exynos5_clkset_mout_cpu = {
-	.sources	= exynos5_clkset_mout_cpu_list,
-	.nr_sources	= ARRAY_SIZE(exynos5_clkset_mout_cpu_list),
-};
-
-static struct clksrc_clk exynos5_clk_mout_cpu = {
-	.clk	= {
-		.name		= "mout_cpu",
-	},
-	.sources = &exynos5_clkset_mout_cpu,
-	.reg_src = { .reg = EXYNOS5_CLKSRC_CPU, .shift = 16, .size = 1 },
-};
-
-static struct clksrc_clk exynos5_clk_dout_armclk = {
-	.clk	= {
-		.name		= "dout_armclk",
-		.parent		= &exynos5_clk_mout_cpu.clk,
-	},
-	.reg_div = { .reg = EXYNOS5_CLKDIV_CPU0, .shift = 0, .size = 3 },
-};
-
-static struct clksrc_clk exynos5_clk_dout_arm2clk = {
-	.clk	= {
-		.name		= "dout_arm2clk",
-		.parent		= &exynos5_clk_dout_armclk.clk,
-	},
-	.reg_div = { .reg = EXYNOS5_CLKDIV_CPU0, .shift = 28, .size = 3 },
-};
-
-static struct clk exynos5_clk_armclk = {
-	.name		= "armclk",
-	.parent		= &exynos5_clk_dout_arm2clk.clk,
-};
-
-/* Core list of CMU_CDREX side */
-
-static struct clk *exynos5_clkset_cdrex_list[] = {
-	[0] = &exynos5_clk_mout_mpll.clk,
-	[1] = &exynos5_clk_mout_bpll.clk,
-};
-
-static struct clksrc_sources exynos5_clkset_cdrex = {
-	.sources	= exynos5_clkset_cdrex_list,
-	.nr_sources	= ARRAY_SIZE(exynos5_clkset_cdrex_list),
-};
-
-static struct clksrc_clk exynos5_clk_cdrex = {
-	.clk	= {
-		.name		= "clk_cdrex",
-	},
-	.sources = &exynos5_clkset_cdrex,
-	.reg_src = { .reg = EXYNOS5_CLKSRC_CDREX, .shift = 4, .size = 1 },
-	.reg_div = { .reg = EXYNOS5_CLKDIV_CDREX, .shift = 16, .size = 3 },
-};
-
-static struct clksrc_clk exynos5_clk_aclk_acp = {
-	.clk	= {
-		.name		= "aclk_acp",
-		.parent		= &exynos5_clk_mout_mpll.clk,
-	},
-	.reg_div = { .reg = EXYNOS5_CLKDIV_ACP, .shift = 0, .size = 3 },
-};
-
-static struct clksrc_clk exynos5_clk_pclk_acp = {
-	.clk	= {
-		.name		= "pclk_acp",
-		.parent		= &exynos5_clk_aclk_acp.clk,
-	},
-	.reg_div = { .reg = EXYNOS5_CLKDIV_ACP, .shift = 4, .size = 3 },
-};
-
-/* Core list of CMU_TOP side */
-
-static struct clk *exynos5_clkset_aclk_top_list[] = {
-	[0] = &exynos5_clk_mout_mpll_user.clk,
-	[1] = &exynos5_clk_mout_bpll_user.clk,
-};
-
-static struct clksrc_sources exynos5_clkset_aclk = {
-	.sources	= exynos5_clkset_aclk_top_list,
-	.nr_sources	= ARRAY_SIZE(exynos5_clkset_aclk_top_list),
-};
-
-static struct clksrc_clk exynos5_clk_aclk_400 = {
-	.clk	= {
-		.name		= "aclk_400",
-	},
-	.sources = &exynos5_clkset_aclk,
-	.reg_src = { .reg = EXYNOS5_CLKSRC_TOP0, .shift = 20, .size = 1 },
-	.reg_div = { .reg = EXYNOS5_CLKDIV_TOP0, .shift = 24, .size = 3 },
-};
-
-static struct clk *exynos5_clkset_aclk_333_166_list[] = {
-	[0] = &exynos5_clk_mout_cpll.clk,
-	[1] = &exynos5_clk_mout_mpll_user.clk,
-};
-
-static struct clksrc_sources exynos5_clkset_aclk_333_166 = {
-	.sources	= exynos5_clkset_aclk_333_166_list,
-	.nr_sources	= ARRAY_SIZE(exynos5_clkset_aclk_333_166_list),
-};
-
-static struct clksrc_clk exynos5_clk_aclk_333 = {
-	.clk	= {
-		.name		= "aclk_333",
-	},
-	.sources = &exynos5_clkset_aclk_333_166,
-	.reg_src = { .reg = EXYNOS5_CLKSRC_TOP0, .shift = 16, .size = 1 },
-	.reg_div = { .reg = EXYNOS5_CLKDIV_TOP0, .shift = 20, .size = 3 },
-};
-
-static struct clksrc_clk exynos5_clk_aclk_166 = {
-	.clk	= {
-		.name		= "aclk_166",
-	},
-	.sources = &exynos5_clkset_aclk_333_166,
-	.reg_src = { .reg = EXYNOS5_CLKSRC_TOP0, .shift = 8, .size = 1 },
-	.reg_div = { .reg = EXYNOS5_CLKDIV_TOP0, .shift = 8, .size = 3 },
-};
-
-static struct clksrc_clk exynos5_clk_aclk_266 = {
-	.clk	= {
-		.name		= "aclk_266",
-		.parent		= &exynos5_clk_mout_mpll_user.clk,
-	},
-	.reg_div = { .reg = EXYNOS5_CLKDIV_TOP0, .shift = 16, .size = 3 },
-};
-
-static struct clksrc_clk exynos5_clk_aclk_200 = {
-	.clk	= {
-		.name		= "aclk_200",
-	},
-	.sources = &exynos5_clkset_aclk,
-	.reg_src = { .reg = EXYNOS5_CLKSRC_TOP0, .shift = 12, .size = 1 },
-	.reg_div = { .reg = EXYNOS5_CLKDIV_TOP0, .shift = 12, .size = 3 },
-};
-
-static struct clksrc_clk exynos5_clk_aclk_66_pre = {
-	.clk	= {
-		.name		= "aclk_66_pre",
-		.parent		= &exynos5_clk_mout_mpll_user.clk,
-	},
-	.reg_div = { .reg = EXYNOS5_CLKDIV_TOP1, .shift = 24, .size = 3 },
-};
-
-static struct clksrc_clk exynos5_clk_aclk_66 = {
-	.clk	= {
-		.name		= "aclk_66",
-		.parent		= &exynos5_clk_aclk_66_pre.clk,
-	},
-	.reg_div = { .reg = EXYNOS5_CLKDIV_TOP0, .shift = 0, .size = 3 },
-};
-
-static struct clksrc_clk exynos5_clk_mout_aclk_300_gscl_mid = {
-	.clk	= {
-		.name		= "mout_aclk_300_gscl_mid",
-	},
-	.sources = &exynos5_clkset_aclk,
-	.reg_src = { .reg = EXYNOS5_CLKSRC_TOP0, .shift = 24, .size = 1 },
-};
-
-static struct clk *exynos5_clkset_aclk_300_mid1_list[] = {
-	[0] = &exynos5_clk_sclk_vpll.clk,
-	[1] = &exynos5_clk_mout_cpll.clk,
-};
-
-static struct clksrc_sources exynos5_clkset_aclk_300_gscl_mid1 = {
-	.sources	= exynos5_clkset_aclk_300_mid1_list,
-	.nr_sources	= ARRAY_SIZE(exynos5_clkset_aclk_300_mid1_list),
-};
-
-static struct clksrc_clk exynos5_clk_mout_aclk_300_gscl_mid1 = {
-	.clk	= {
-		.name		= "mout_aclk_300_gscl_mid1",
-	},
-	.sources = &exynos5_clkset_aclk_300_gscl_mid1,
-	.reg_src = { .reg = EXYNOS5_CLKSRC_TOP1, .shift = 12, .size = 1 },
-};
-
-static struct clk *exynos5_clkset_aclk_300_gscl_list[] = {
-	[0] = &exynos5_clk_mout_aclk_300_gscl_mid.clk,
-	[1] = &exynos5_clk_mout_aclk_300_gscl_mid1.clk,
-};
-
-static struct clksrc_sources exynos5_clkset_aclk_300_gscl = {
-	.sources	= exynos5_clkset_aclk_300_gscl_list,
-	.nr_sources	= ARRAY_SIZE(exynos5_clkset_aclk_300_gscl_list),
-};
-
-static struct clksrc_clk exynos5_clk_mout_aclk_300_gscl = {
-	.clk	= {
-		.name		= "mout_aclk_300_gscl",
-	},
-	.sources = &exynos5_clkset_aclk_300_gscl,
-	.reg_src = { .reg = EXYNOS5_CLKSRC_TOP0, .shift = 25, .size = 1 },
-};
-
-static struct clk *exynos5_clk_src_gscl_300_list[] = {
-	[0] = &clk_ext_xtal_mux,
-	[1] = &exynos5_clk_mout_aclk_300_gscl.clk,
-};
-
-static struct clksrc_sources exynos5_clk_src_gscl_300 = {
-	.sources	= exynos5_clk_src_gscl_300_list,
-	.nr_sources	= ARRAY_SIZE(exynos5_clk_src_gscl_300_list),
-};
-
-static struct clksrc_clk exynos5_clk_aclk_300_gscl = {
-	.clk	= {
-		.name		= "aclk_300_gscl",
-	},
-	.sources = &exynos5_clk_src_gscl_300,
-	.reg_src = { .reg = EXYNOS5_CLKSRC_TOP3, .shift = 10, .size = 1 },
-};
-
-static struct clk exynos5_init_clocks_off[] = {
-	{
-		.name		= "timers",
-		.parent		= &exynos5_clk_aclk_66.clk,
-		.enable		= exynos5_clk_ip_peric_ctrl,
-		.ctrlbit	= (1 << 24),
-	}, {
-		.name		= "tmu_apbif",
-		.parent		= &exynos5_clk_aclk_66.clk,
-		.enable		= exynos5_clk_ip_peris_ctrl,
-		.ctrlbit	= (1 << 21),
-	}, {
-		.name		= "rtc",
-		.parent		= &exynos5_clk_aclk_66.clk,
-		.enable		= exynos5_clk_ip_peris_ctrl,
-		.ctrlbit	= (1 << 20),
-	}, {
-		.name		= "watchdog",
-		.parent		= &exynos5_clk_aclk_66.clk,
-		.enable		= exynos5_clk_ip_peris_ctrl,
-		.ctrlbit	= (1 << 19),
-	}, {
-		.name		= "biu",	/* bus interface unit clock */
-		.devname	= "dw_mmc.0",
-		.parent		= &exynos5_clk_aclk_200.clk,
-		.enable		= exynos5_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 12),
-	}, {
-		.name		= "biu",
-		.devname	= "dw_mmc.1",
-		.parent		= &exynos5_clk_aclk_200.clk,
-		.enable		= exynos5_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 13),
-	}, {
-		.name		= "biu",
-		.devname	= "dw_mmc.2",
-		.parent		= &exynos5_clk_aclk_200.clk,
-		.enable		= exynos5_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 14),
-	}, {
-		.name		= "biu",
-		.devname	= "dw_mmc.3",
-		.parent		= &exynos5_clk_aclk_200.clk,
-		.enable		= exynos5_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 15),
-	}, {
-		.name		= "sata",
-		.devname	= "exynos5-sata",
-		.parent         = &exynos5_clk_aclk_200.clk,
-		.enable		= exynos5_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 6),
-	}, {
-		.name		= "sata-phy",
-		.devname	= "exynos5-sata-phy",
-		.parent         = &exynos5_clk_aclk_200.clk,
-		.enable		= exynos5_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 24),
-	}, {
-		.name		= "i2c",
-		.devname	= "exynos5-sata-phy-i2c",
-		.parent         = &exynos5_clk_aclk_200.clk,
-		.enable		= exynos5_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 25),
-	}, {
-		.name		= "mfc",
-		.devname	= "s5p-mfc-v6",
-		.enable		= exynos5_clk_ip_mfc_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "hdmi",
-		.devname	= "exynos5-hdmi",
-		.enable		= exynos5_clk_ip_disp1_ctrl,
-		.ctrlbit	= (1 << 6),
-	}, {
-		.name		= "hdmiphy",
-		.devname	= "exynos5-hdmi",
-		.enable		= exynos5_clk_hdmiphy_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "mixer",
-		.devname	= "exynos5-mixer",
-		.enable		= exynos5_clk_ip_disp1_ctrl,
-		.ctrlbit	= (1 << 5),
-	}, {
-		.name		= "dp",
-		.devname	= "exynos-dp",
-		.enable		= exynos5_clk_ip_disp1_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
-		.name		= "jpeg",
-		.enable		= exynos5_clk_ip_gen_ctrl,
-		.ctrlbit	= (1 << 2),
-	}, {
-		.name		= "dsim0",
-		.enable		= exynos5_clk_ip_disp1_ctrl,
-		.ctrlbit	= (1 << 3),
-	}, {
-		.name		= "iis",
-		.devname	= "samsung-i2s.1",
-		.enable		= exynos5_clk_ip_peric_ctrl,
-		.ctrlbit	= (1 << 20),
-	}, {
-		.name		= "iis",
-		.devname	= "samsung-i2s.2",
-		.enable		= exynos5_clk_ip_peric_ctrl,
-		.ctrlbit	= (1 << 21),
-	}, {
-		.name		= "pcm",
-		.devname	= "samsung-pcm.1",
-		.enable		= exynos5_clk_ip_peric_ctrl,
-		.ctrlbit	= (1 << 22),
-	}, {
-		.name		= "pcm",
-		.devname	= "samsung-pcm.2",
-		.enable		= exynos5_clk_ip_peric_ctrl,
-		.ctrlbit	= (1 << 23),
-	}, {
-		.name		= "spdif",
-		.devname	= "samsung-spdif",
-		.enable		= exynos5_clk_ip_peric_ctrl,
-		.ctrlbit	= (1 << 26),
-	}, {
-		.name		= "ac97",
-		.devname	= "samsung-ac97",
-		.enable		= exynos5_clk_ip_peric_ctrl,
-		.ctrlbit	= (1 << 27),
-	}, {
-		.name		= "usbhost",
-		.enable		= exynos5_clk_ip_fsys_ctrl ,
-		.ctrlbit	= (1 << 18),
-	}, {
-		.name		= "usbotg",
-		.enable		= exynos5_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 7),
-	}, {
-		.name		= "nfcon",
-		.enable		= exynos5_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 22),
-	}, {
-		.name		= "iop",
-		.enable		= exynos5_clk_ip_fsys_ctrl,
-		.ctrlbit	= ((1 << 30) | (1 << 26) | (1 << 23)),
-	}, {
-		.name		= "core_iop",
-		.enable		= exynos5_clk_ip_core_ctrl,
-		.ctrlbit	= ((1 << 21) | (1 << 3)),
-	}, {
-		.name		= "mcu_iop",
-		.enable		= exynos5_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.0",
-		.parent		= &exynos5_clk_aclk_66.clk,
-		.enable		= exynos5_clk_ip_peric_ctrl,
-		.ctrlbit	= (1 << 6),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.1",
-		.parent		= &exynos5_clk_aclk_66.clk,
-		.enable		= exynos5_clk_ip_peric_ctrl,
-		.ctrlbit	= (1 << 7),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.2",
-		.parent		= &exynos5_clk_aclk_66.clk,
-		.enable		= exynos5_clk_ip_peric_ctrl,
-		.ctrlbit	= (1 << 8),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.3",
-		.parent		= &exynos5_clk_aclk_66.clk,
-		.enable		= exynos5_clk_ip_peric_ctrl,
-		.ctrlbit	= (1 << 9),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.4",
-		.parent		= &exynos5_clk_aclk_66.clk,
-		.enable		= exynos5_clk_ip_peric_ctrl,
-		.ctrlbit	= (1 << 10),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.5",
-		.parent		= &exynos5_clk_aclk_66.clk,
-		.enable		= exynos5_clk_ip_peric_ctrl,
-		.ctrlbit	= (1 << 11),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.6",
-		.parent		= &exynos5_clk_aclk_66.clk,
-		.enable		= exynos5_clk_ip_peric_ctrl,
-		.ctrlbit	= (1 << 12),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.7",
-		.parent		= &exynos5_clk_aclk_66.clk,
-		.enable		= exynos5_clk_ip_peric_ctrl,
-		.ctrlbit	= (1 << 13),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-hdmiphy-i2c",
-		.parent		= &exynos5_clk_aclk_66.clk,
-		.enable		= exynos5_clk_ip_peric_ctrl,
-		.ctrlbit	= (1 << 14),
-	}, {
-		.name		= "spi",
-		.devname	= "exynos4210-spi.0",
-		.parent		= &exynos5_clk_aclk_66.clk,
-		.enable		= exynos5_clk_ip_peric_ctrl,
-		.ctrlbit	= (1 << 16),
-	}, {
-		.name		= "spi",
-		.devname	= "exynos4210-spi.1",
-		.parent		= &exynos5_clk_aclk_66.clk,
-		.enable		= exynos5_clk_ip_peric_ctrl,
-		.ctrlbit	= (1 << 17),
-	}, {
-		.name		= "spi",
-		.devname	= "exynos4210-spi.2",
-		.parent		= &exynos5_clk_aclk_66.clk,
-		.enable		= exynos5_clk_ip_peric_ctrl,
-		.ctrlbit	= (1 << 18),
-	}, {
-		.name		= "gscl",
-		.devname	= "exynos-gsc.0",
-		.enable		= exynos5_clk_ip_gscl_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "gscl",
-		.devname	= "exynos-gsc.1",
-		.enable		= exynos5_clk_ip_gscl_ctrl,
-		.ctrlbit	= (1 << 1),
-	}, {
-		.name		= "gscl",
-		.devname	= "exynos-gsc.2",
-		.enable		= exynos5_clk_ip_gscl_ctrl,
-		.ctrlbit	= (1 << 2),
-	}, {
-		.name		= "gscl",
-		.devname	= "exynos-gsc.3",
-		.enable		= exynos5_clk_ip_gscl_ctrl,
-		.ctrlbit	= (1 << 3),
-	}, {
-		.name		= "sysmmu",
-		.devname	= "exynos-sysmmu.1",
-		.enable		= &exynos5_clk_ip_mfc_ctrl,
-		.ctrlbit	= (1 << 1),
-	}, {
-		.name		= "sysmmu",
-		.devname	= "exynos-sysmmu.0",
-		.enable		= &exynos5_clk_ip_mfc_ctrl,
-		.ctrlbit	= (1 << 2),
-	}, {
-		.name		= "sysmmu",
-		.devname	= "exynos-sysmmu.2",
-		.enable		= &exynos5_clk_ip_disp1_ctrl,
-		.ctrlbit	= (1 << 9)
-	}, {
-		.name		= "sysmmu",
-		.devname	= "exynos-sysmmu.3",
-		.enable		= &exynos5_clk_ip_gen_ctrl,
-		.ctrlbit	= (1 << 7),
-	}, {
-		.name		= "sysmmu",
-		.devname	= "exynos-sysmmu.4",
-		.enable		= &exynos5_clk_ip_gen_ctrl,
-		.ctrlbit	= (1 << 6)
-	}, {
-		.name		= "sysmmu",
-		.devname	= "exynos-sysmmu.5",
-		.enable		= &exynos5_clk_ip_gscl_ctrl,
-		.ctrlbit	= (1 << 7),
-	}, {
-		.name		= "sysmmu",
-		.devname	= "exynos-sysmmu.6",
-		.enable		= &exynos5_clk_ip_gscl_ctrl,
-		.ctrlbit	= (1 << 8),
-	}, {
-		.name		= "sysmmu",
-		.devname	= "exynos-sysmmu.7",
-		.enable		= &exynos5_clk_ip_gscl_ctrl,
-		.ctrlbit	= (1 << 9),
-	}, {
-		.name		= "sysmmu",
-		.devname	= "exynos-sysmmu.8",
-		.enable		= &exynos5_clk_ip_gscl_ctrl,
-		.ctrlbit	= (1 << 10),
-	}, {
-		.name		= "sysmmu",
-		.devname	= "exynos-sysmmu.9",
-		.enable		= &exynos5_clk_ip_isp0_ctrl,
-		.ctrlbit	= (0x3F << 8),
-	}, {
-		.name		= "sysmmu",
-		.devname	= "exynos-sysmmu.10",
-		.enable		= &exynos5_clk_ip_isp1_ctrl,
-		.ctrlbit	= (0xF << 4),
-	}, {
-		.name		= "sysmmu",
-		.devname	= "exynos-sysmmu.11",
-		.enable		= &exynos5_clk_ip_disp1_ctrl,
-		.ctrlbit	= (1 << 8)
-	}, {
-		.name		= "sysmmu",
-		.devname	= "exynos-sysmmu.12",
-		.enable		= &exynos5_clk_ip_gscl_ctrl,
-		.ctrlbit	= (1 << 11),
-	}, {
-		.name		= "sysmmu",
-		.devname	= "exynos-sysmmu.13",
-		.enable		= &exynos5_clk_ip_gscl_ctrl,
-		.ctrlbit	= (1 << 12),
-	}, {
-		.name		= "sysmmu",
-		.devname	= "exynos-sysmmu.14",
-		.enable		= &exynos5_clk_ip_acp_ctrl,
-		.ctrlbit	= (1 << 7)
-	}
-};
-
-static struct clk exynos5_init_clocks_on[] = {
-	{
-		.name		= "uart",
-		.devname	= "s5pv210-uart.0",
-		.enable		= exynos5_clk_ip_peric_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "uart",
-		.devname	= "s5pv210-uart.1",
-		.enable		= exynos5_clk_ip_peric_ctrl,
-		.ctrlbit	= (1 << 1),
-	}, {
-		.name		= "uart",
-		.devname	= "s5pv210-uart.2",
-		.enable		= exynos5_clk_ip_peric_ctrl,
-		.ctrlbit	= (1 << 2),
-	}, {
-		.name		= "uart",
-		.devname	= "s5pv210-uart.3",
-		.enable		= exynos5_clk_ip_peric_ctrl,
-		.ctrlbit	= (1 << 3),
-	}, {
-		.name		= "uart",
-		.devname	= "s5pv210-uart.4",
-		.enable		= exynos5_clk_ip_peric_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
-		.name		= "uart",
-		.devname	= "s5pv210-uart.5",
-		.enable		= exynos5_clk_ip_peric_ctrl,
-		.ctrlbit	= (1 << 5),
-	}
-};
-
-static struct clk exynos5_clk_pdma0 = {
-	.name		= "dma",
-	.devname	= "dma-pl330.0",
-	.enable		= exynos5_clk_ip_fsys_ctrl,
-	.ctrlbit	= (1 << 1),
-};
-
-static struct clk exynos5_clk_pdma1 = {
-	.name		= "dma",
-	.devname	= "dma-pl330.1",
-	.enable		= exynos5_clk_ip_fsys_ctrl,
-	.ctrlbit	= (1 << 2),
-};
-
-static struct clk exynos5_clk_mdma1 = {
-	.name		= "dma",
-	.devname	= "dma-pl330.2",
-	.enable		= exynos5_clk_ip_gen_ctrl,
-	.ctrlbit	= (1 << 4),
-};
-
-static struct clk exynos5_clk_fimd1 = {
-	.name		= "fimd",
-	.devname	= "exynos5-fb.1",
-	.enable		= exynos5_clk_ip_disp1_ctrl,
-	.ctrlbit	= (1 << 0),
-};
-
-static struct clk *exynos5_clkset_group_list[] = {
-	[0] = &clk_ext_xtal_mux,
-	[1] = NULL,
-	[2] = &exynos5_clk_sclk_hdmi24m,
-	[3] = &exynos5_clk_sclk_dptxphy,
-	[4] = &exynos5_clk_sclk_usbphy,
-	[5] = &exynos5_clk_sclk_hdmiphy,
-	[6] = &exynos5_clk_mout_mpll_user.clk,
-	[7] = &exynos5_clk_mout_epll.clk,
-	[8] = &exynos5_clk_sclk_vpll.clk,
-	[9] = &exynos5_clk_mout_cpll.clk,
-};
-
-static struct clksrc_sources exynos5_clkset_group = {
-	.sources	= exynos5_clkset_group_list,
-	.nr_sources	= ARRAY_SIZE(exynos5_clkset_group_list),
-};
-
-/* Possible clock sources for aclk_266_gscl_sub Mux */
-static struct clk *clk_src_gscl_266_list[] = {
-	[0] = &clk_ext_xtal_mux,
-	[1] = &exynos5_clk_aclk_266.clk,
-};
-
-static struct clksrc_sources clk_src_gscl_266 = {
-	.sources	= clk_src_gscl_266_list,
-	.nr_sources	= ARRAY_SIZE(clk_src_gscl_266_list),
-};
-
-static struct clksrc_clk exynos5_clk_dout_mmc0 = {
-	.clk		= {
-		.name		= "dout_mmc0",
-	},
-	.sources = &exynos5_clkset_group,
-	.reg_src = { .reg = EXYNOS5_CLKSRC_FSYS, .shift = 0, .size = 4 },
-	.reg_div = { .reg = EXYNOS5_CLKDIV_FSYS1, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk exynos5_clk_dout_mmc1 = {
-	.clk		= {
-		.name		= "dout_mmc1",
-	},
-	.sources = &exynos5_clkset_group,
-	.reg_src = { .reg = EXYNOS5_CLKSRC_FSYS, .shift = 4, .size = 4 },
-	.reg_div = { .reg = EXYNOS5_CLKDIV_FSYS1, .shift = 16, .size = 4 },
-};
-
-static struct clksrc_clk exynos5_clk_dout_mmc2 = {
-	.clk		= {
-		.name		= "dout_mmc2",
-	},
-	.sources = &exynos5_clkset_group,
-	.reg_src = { .reg = EXYNOS5_CLKSRC_FSYS, .shift = 8, .size = 4 },
-	.reg_div = { .reg = EXYNOS5_CLKDIV_FSYS2, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk exynos5_clk_dout_mmc3 = {
-	.clk		= {
-		.name		= "dout_mmc3",
-	},
-	.sources = &exynos5_clkset_group,
-	.reg_src = { .reg = EXYNOS5_CLKSRC_FSYS, .shift = 12, .size = 4 },
-	.reg_div = { .reg = EXYNOS5_CLKDIV_FSYS2, .shift = 16, .size = 4 },
-};
-
-static struct clksrc_clk exynos5_clk_dout_mmc4 = {
-	.clk		= {
-		.name		= "dout_mmc4",
-	},
-	.sources = &exynos5_clkset_group,
-	.reg_src = { .reg = EXYNOS5_CLKSRC_FSYS, .shift = 16, .size = 4 },
-	.reg_div = { .reg = EXYNOS5_CLKDIV_FSYS3, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk exynos5_clk_sclk_uart0 = {
-	.clk	= {
-		.name		= "uclk1",
-		.devname	= "exynos4210-uart.0",
-		.enable		= exynos5_clksrc_mask_peric0_ctrl,
-		.ctrlbit	= (1 << 0),
-	},
-	.sources = &exynos5_clkset_group,
-	.reg_src = { .reg = EXYNOS5_CLKSRC_PERIC0, .shift = 0, .size = 4 },
-	.reg_div = { .reg = EXYNOS5_CLKDIV_PERIC0, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk exynos5_clk_sclk_uart1 = {
-	.clk	= {
-		.name		= "uclk1",
-		.devname	= "exynos4210-uart.1",
-		.enable		= exynos5_clksrc_mask_peric0_ctrl,
-		.ctrlbit	= (1 << 4),
-	},
-	.sources = &exynos5_clkset_group,
-	.reg_src = { .reg = EXYNOS5_CLKSRC_PERIC0, .shift = 4, .size = 4 },
-	.reg_div = { .reg = EXYNOS5_CLKDIV_PERIC0, .shift = 4, .size = 4 },
-};
-
-static struct clksrc_clk exynos5_clk_sclk_uart2 = {
-	.clk	= {
-		.name		= "uclk1",
-		.devname	= "exynos4210-uart.2",
-		.enable		= exynos5_clksrc_mask_peric0_ctrl,
-		.ctrlbit	= (1 << 8),
-	},
-	.sources = &exynos5_clkset_group,
-	.reg_src = { .reg = EXYNOS5_CLKSRC_PERIC0, .shift = 8, .size = 4 },
-	.reg_div = { .reg = EXYNOS5_CLKDIV_PERIC0, .shift = 8, .size = 4 },
-};
-
-static struct clksrc_clk exynos5_clk_sclk_uart3 = {
-	.clk	= {
-		.name		= "uclk1",
-		.devname	= "exynos4210-uart.3",
-		.enable		= exynos5_clksrc_mask_peric0_ctrl,
-		.ctrlbit	= (1 << 12),
-	},
-	.sources = &exynos5_clkset_group,
-	.reg_src = { .reg = EXYNOS5_CLKSRC_PERIC0, .shift = 12, .size = 4 },
-	.reg_div = { .reg = EXYNOS5_CLKDIV_PERIC0, .shift = 12, .size = 4 },
-};
-
-static struct clksrc_clk exynos5_clk_sclk_mmc0 = {
-	.clk	= {
-		.name		= "ciu",	/* card interface unit clock */
-		.devname	= "dw_mmc.0",
-		.parent		= &exynos5_clk_dout_mmc0.clk,
-		.enable		= exynos5_clksrc_mask_fsys_ctrl,
-		.ctrlbit	= (1 << 0),
-	},
-	.reg_div = { .reg = EXYNOS5_CLKDIV_FSYS1, .shift = 8, .size = 8 },
-};
-
-static struct clksrc_clk exynos5_clk_sclk_mmc1 = {
-	.clk	= {
-		.name		= "ciu",
-		.devname	= "dw_mmc.1",
-		.parent		= &exynos5_clk_dout_mmc1.clk,
-		.enable		= exynos5_clksrc_mask_fsys_ctrl,
-		.ctrlbit	= (1 << 4),
-	},
-	.reg_div = { .reg = EXYNOS5_CLKDIV_FSYS1, .shift = 24, .size = 8 },
-};
-
-static struct clksrc_clk exynos5_clk_sclk_mmc2 = {
-	.clk	= {
-		.name		= "ciu",
-		.devname	= "dw_mmc.2",
-		.parent		= &exynos5_clk_dout_mmc2.clk,
-		.enable		= exynos5_clksrc_mask_fsys_ctrl,
-		.ctrlbit	= (1 << 8),
-	},
-	.reg_div = { .reg = EXYNOS5_CLKDIV_FSYS2, .shift = 8, .size = 8 },
-};
-
-static struct clksrc_clk exynos5_clk_sclk_mmc3 = {
-	.clk	= {
-		.name		= "ciu",
-		.devname	= "dw_mmc.3",
-		.parent		= &exynos5_clk_dout_mmc3.clk,
-		.enable		= exynos5_clksrc_mask_fsys_ctrl,
-		.ctrlbit	= (1 << 12),
-	},
-	.reg_div = { .reg = EXYNOS5_CLKDIV_FSYS2, .shift = 24, .size = 8 },
-};
-
-static struct clksrc_clk exynos5_clk_mdout_spi0 = {
-	.clk	= {
-		.name		= "mdout_spi",
-		.devname	= "exynos4210-spi.0",
-	},
-	.sources = &exynos5_clkset_group,
-	.reg_src = { .reg = EXYNOS5_CLKSRC_PERIC1, .shift = 16, .size = 4 },
-	.reg_div = { .reg = EXYNOS5_CLKDIV_PERIC1, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk exynos5_clk_mdout_spi1 = {
-	.clk	= {
-		.name		= "mdout_spi",
-		.devname	= "exynos4210-spi.1",
-	},
-	.sources = &exynos5_clkset_group,
-	.reg_src = { .reg = EXYNOS5_CLKSRC_PERIC1, .shift = 20, .size = 4 },
-	.reg_div = { .reg = EXYNOS5_CLKDIV_PERIC1, .shift = 16, .size = 4 },
-};
-
-static struct clksrc_clk exynos5_clk_mdout_spi2 = {
-	.clk	= {
-		.name		= "mdout_spi",
-		.devname	= "exynos4210-spi.2",
-	},
-	.sources = &exynos5_clkset_group,
-	.reg_src = { .reg = EXYNOS5_CLKSRC_PERIC1, .shift = 24, .size = 4 },
-	.reg_div = { .reg = EXYNOS5_CLKDIV_PERIC2, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk exynos5_clk_sclk_spi0 = {
-	.clk	= {
-		.name		= "sclk_spi",
-		.devname	= "exynos4210-spi.0",
-		.parent		= &exynos5_clk_mdout_spi0.clk,
-		.enable		= exynos5_clksrc_mask_peric1_ctrl,
-		.ctrlbit	= (1 << 16),
-	},
-	.reg_div = { .reg = EXYNOS5_CLKDIV_PERIC1, .shift = 8, .size = 8 },
-};
-
-static struct clksrc_clk exynos5_clk_sclk_spi1 = {
-	.clk	= {
-		.name		= "sclk_spi",
-		.devname	= "exynos4210-spi.1",
-		.parent		= &exynos5_clk_mdout_spi1.clk,
-		.enable		= exynos5_clksrc_mask_peric1_ctrl,
-		.ctrlbit	= (1 << 20),
-	},
-	.reg_div = { .reg = EXYNOS5_CLKDIV_PERIC1, .shift = 24, .size = 8 },
-};
-
-static struct clksrc_clk exynos5_clk_sclk_spi2 = {
-	.clk	= {
-		.name		= "sclk_spi",
-		.devname	= "exynos4210-spi.2",
-		.parent		= &exynos5_clk_mdout_spi2.clk,
-		.enable		= exynos5_clksrc_mask_peric1_ctrl,
-		.ctrlbit	= (1 << 24),
-	},
-	.reg_div = { .reg = EXYNOS5_CLKDIV_PERIC2, .shift = 8, .size = 8 },
-};
-
-static struct clksrc_clk exynos5_clk_sclk_fimd1 = {
-	.clk	= {
-		.name		= "sclk_fimd",
-		.devname	= "exynos5-fb.1",
-		.enable		= exynos5_clksrc_mask_disp1_0_ctrl,
-		.ctrlbit	= (1 << 0),
-	},
-	.sources = &exynos5_clkset_group,
-	.reg_src = { .reg = EXYNOS5_CLKSRC_DISP1_0, .shift = 0, .size = 4 },
-	.reg_div = { .reg = EXYNOS5_CLKDIV_DISP1_0, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk exynos5_clksrcs[] = {
-	{
-		.clk	= {
-			.name		= "aclk_266_gscl",
-		},
-		.sources = &clk_src_gscl_266,
-		.reg_src = { .reg = EXYNOS5_CLKSRC_TOP3, .shift = 8, .size = 1 },
-	}, {
-		.clk	= {
-			.name		= "sclk_g3d",
-			.devname	= "mali-t604.0",
-			.enable		= exynos5_clk_block_ctrl,
-			.ctrlbit	= (1 << 1),
-		},
-		.sources = &exynos5_clkset_aclk,
-		.reg_src = { .reg = EXYNOS5_CLKSRC_TOP0, .shift = 20, .size = 1 },
-		.reg_div = { .reg = EXYNOS5_CLKDIV_TOP0, .shift = 24, .size = 3 },
-	}, {
-		.clk	= {
-			.name		= "sclk_sata",
-			.devname	= "exynos5-sata",
-			.enable		= exynos5_clksrc_mask_fsys_ctrl,
-			.ctrlbit	= (1 << 24),
-		},
-		.sources = &exynos5_clkset_aclk,
-		.reg_src = { .reg = EXYNOS5_CLKSRC_FSYS, .shift = 24, .size = 1 },
-		.reg_div = { .reg = EXYNOS5_CLKDIV_FSYS0, .shift = 20, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_gscl_wrap",
-			.devname	= "s5p-mipi-csis.0",
-			.enable		= exynos5_clksrc_mask_gscl_ctrl,
-			.ctrlbit	= (1 << 24),
-		},
-		.sources = &exynos5_clkset_group,
-		.reg_src = { .reg = EXYNOS5_CLKSRC_GSCL, .shift = 24, .size = 4 },
-		.reg_div = { .reg = EXYNOS5_CLKDIV_GSCL, .shift = 24, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_gscl_wrap",
-			.devname	= "s5p-mipi-csis.1",
-			.enable		= exynos5_clksrc_mask_gscl_ctrl,
-			.ctrlbit	= (1 << 28),
-		},
-		.sources = &exynos5_clkset_group,
-		.reg_src = { .reg = EXYNOS5_CLKSRC_GSCL, .shift = 28, .size = 4 },
-		.reg_div = { .reg = EXYNOS5_CLKDIV_GSCL, .shift = 28, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_cam0",
-			.enable		= exynos5_clksrc_mask_gscl_ctrl,
-			.ctrlbit	= (1 << 16),
-		},
-		.sources = &exynos5_clkset_group,
-		.reg_src = { .reg = EXYNOS5_CLKSRC_GSCL, .shift = 16, .size = 4 },
-		.reg_div = { .reg = EXYNOS5_CLKDIV_GSCL, .shift = 16, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_cam1",
-			.enable		= exynos5_clksrc_mask_gscl_ctrl,
-			.ctrlbit	= (1 << 20),
-		},
-		.sources = &exynos5_clkset_group,
-		.reg_src = { .reg = EXYNOS5_CLKSRC_GSCL, .shift = 20, .size = 4 },
-		.reg_div = { .reg = EXYNOS5_CLKDIV_GSCL, .shift = 20, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_jpeg",
-			.parent		= &exynos5_clk_mout_cpll.clk,
-		},
-		.reg_div = { .reg = EXYNOS5_CLKDIV_GEN, .shift = 4, .size = 3 },
-	},
-};
-
-/* Clock initialization code */
-static struct clksrc_clk *exynos5_sysclks[] = {
-	&exynos5_clk_mout_apll,
-	&exynos5_clk_sclk_apll,
-	&exynos5_clk_mout_bpll,
-	&exynos5_clk_mout_bpll_fout,
-	&exynos5_clk_mout_bpll_user,
-	&exynos5_clk_mout_cpll,
-	&exynos5_clk_mout_epll,
-	&exynos5_clk_mout_mpll,
-	&exynos5_clk_mout_mpll_fout,
-	&exynos5_clk_mout_mpll_user,
-	&exynos5_clk_vpllsrc,
-	&exynos5_clk_sclk_vpll,
-	&exynos5_clk_mout_cpu,
-	&exynos5_clk_dout_armclk,
-	&exynos5_clk_dout_arm2clk,
-	&exynos5_clk_cdrex,
-	&exynos5_clk_aclk_400,
-	&exynos5_clk_aclk_333,
-	&exynos5_clk_aclk_266,
-	&exynos5_clk_aclk_200,
-	&exynos5_clk_aclk_166,
-	&exynos5_clk_aclk_300_gscl,
-	&exynos5_clk_mout_aclk_300_gscl,
-	&exynos5_clk_mout_aclk_300_gscl_mid,
-	&exynos5_clk_mout_aclk_300_gscl_mid1,
-	&exynos5_clk_aclk_66_pre,
-	&exynos5_clk_aclk_66,
-	&exynos5_clk_dout_mmc0,
-	&exynos5_clk_dout_mmc1,
-	&exynos5_clk_dout_mmc2,
-	&exynos5_clk_dout_mmc3,
-	&exynos5_clk_dout_mmc4,
-	&exynos5_clk_aclk_acp,
-	&exynos5_clk_pclk_acp,
-	&exynos5_clk_sclk_spi0,
-	&exynos5_clk_sclk_spi1,
-	&exynos5_clk_sclk_spi2,
-	&exynos5_clk_mdout_spi0,
-	&exynos5_clk_mdout_spi1,
-	&exynos5_clk_mdout_spi2,
-	&exynos5_clk_sclk_fimd1,
-};
-
-static struct clk *exynos5_clk_cdev[] = {
-	&exynos5_clk_pdma0,
-	&exynos5_clk_pdma1,
-	&exynos5_clk_mdma1,
-	&exynos5_clk_fimd1,
-};
-
-static struct clksrc_clk *exynos5_clksrc_cdev[] = {
-	&exynos5_clk_sclk_uart0,
-	&exynos5_clk_sclk_uart1,
-	&exynos5_clk_sclk_uart2,
-	&exynos5_clk_sclk_uart3,
-	&exynos5_clk_sclk_mmc0,
-	&exynos5_clk_sclk_mmc1,
-	&exynos5_clk_sclk_mmc2,
-	&exynos5_clk_sclk_mmc3,
-};
-
-static struct clk_lookup exynos5_clk_lookup[] = {
-	CLKDEV_INIT("exynos4210-uart.0", "clk_uart_baud0", &exynos5_clk_sclk_uart0.clk),
-	CLKDEV_INIT("exynos4210-uart.1", "clk_uart_baud0", &exynos5_clk_sclk_uart1.clk),
-	CLKDEV_INIT("exynos4210-uart.2", "clk_uart_baud0", &exynos5_clk_sclk_uart2.clk),
-	CLKDEV_INIT("exynos4210-uart.3", "clk_uart_baud0", &exynos5_clk_sclk_uart3.clk),
-	CLKDEV_INIT("exynos4-sdhci.0", "mmc_busclk.2", &exynos5_clk_sclk_mmc0.clk),
-	CLKDEV_INIT("exynos4-sdhci.1", "mmc_busclk.2", &exynos5_clk_sclk_mmc1.clk),
-	CLKDEV_INIT("exynos4-sdhci.2", "mmc_busclk.2", &exynos5_clk_sclk_mmc2.clk),
-	CLKDEV_INIT("exynos4-sdhci.3", "mmc_busclk.2", &exynos5_clk_sclk_mmc3.clk),
-	CLKDEV_INIT("exynos4210-spi.0", "spi_busclk0", &exynos5_clk_sclk_spi0.clk),
-	CLKDEV_INIT("exynos4210-spi.1", "spi_busclk0", &exynos5_clk_sclk_spi1.clk),
-	CLKDEV_INIT("exynos4210-spi.2", "spi_busclk0", &exynos5_clk_sclk_spi2.clk),
-	CLKDEV_INIT("dma-pl330.0", "apb_pclk", &exynos5_clk_pdma0),
-	CLKDEV_INIT("dma-pl330.1", "apb_pclk", &exynos5_clk_pdma1),
-	CLKDEV_INIT("dma-pl330.2", "apb_pclk", &exynos5_clk_mdma1),
-	CLKDEV_INIT("exynos5-fb.1", "lcd", &exynos5_clk_fimd1),
-};
-
-static unsigned long exynos5_epll_get_rate(struct clk *clk)
-{
-	return clk->rate;
-}
-
-static struct clk *exynos5_clks[] __initdata = {
-	&exynos5_clk_sclk_hdmi27m,
-	&exynos5_clk_sclk_hdmiphy,
-	&clk_fout_bpll,
-	&clk_fout_bpll_div2,
-	&clk_fout_cpll,
-	&clk_fout_mpll_div2,
-	&exynos5_clk_armclk,
-};
-
-static u32 epll_div[][6] = {
-	{ 192000000, 0, 48, 3, 1, 0 },
-	{ 180000000, 0, 45, 3, 1, 0 },
-	{  73728000, 1, 73, 3, 3, 47710 },
-	{  67737600, 1, 90, 4, 3, 20762 },
-	{  49152000, 0, 49, 3, 3, 9961 },
-	{  45158400, 0, 45, 3, 3, 10381 },
-	{ 180633600, 0, 45, 3, 1, 10381 },
-};
-
-static int exynos5_epll_set_rate(struct clk *clk, unsigned long rate)
-{
-	unsigned int epll_con, epll_con_k;
-	unsigned int i;
-	unsigned int tmp;
-	unsigned int epll_rate;
-	unsigned int locktime;
-	unsigned int lockcnt;
-
-	/* Return if nothing changed */
-	if (clk->rate == rate)
-		return 0;
-
-	if (clk->parent)
-		epll_rate = clk_get_rate(clk->parent);
-	else
-		epll_rate = clk_ext_xtal_mux.rate;
-
-	if (epll_rate != 24000000) {
-		pr_err("Invalid Clock : recommended clock is 24MHz.\n");
-		return -EINVAL;
-	}
-
-	epll_con = __raw_readl(EXYNOS5_EPLL_CON0);
-	epll_con &= ~(0x1 << 27 | \
-			PLL46XX_MDIV_MASK << PLL46XX_MDIV_SHIFT |   \
-			PLL46XX_PDIV_MASK << PLL46XX_PDIV_SHIFT | \
-			PLL46XX_SDIV_MASK << PLL46XX_SDIV_SHIFT);
-
-	for (i = 0; i < ARRAY_SIZE(epll_div); i++) {
-		if (epll_div[i][0] == rate) {
-			epll_con_k = epll_div[i][5] << 0;
-			epll_con |= epll_div[i][1] << 27;
-			epll_con |= epll_div[i][2] << PLL46XX_MDIV_SHIFT;
-			epll_con |= epll_div[i][3] << PLL46XX_PDIV_SHIFT;
-			epll_con |= epll_div[i][4] << PLL46XX_SDIV_SHIFT;
-			break;
-		}
-	}
-
-	if (i == ARRAY_SIZE(epll_div)) {
-		printk(KERN_ERR "%s: Invalid Clock EPLL Frequency\n",
-				__func__);
-		return -EINVAL;
-	}
-
-	epll_rate /= 1000000;
-
-	/* 3000 max_cycls : specification data */
-	locktime = 3000 / epll_rate * epll_div[i][3];
-	lockcnt = locktime * 10000 / (10000 / epll_rate);
-
-	__raw_writel(lockcnt, EXYNOS5_EPLL_LOCK);
-
-	__raw_writel(epll_con, EXYNOS5_EPLL_CON0);
-	__raw_writel(epll_con_k, EXYNOS5_EPLL_CON1);
-
-	do {
-		tmp = __raw_readl(EXYNOS5_EPLL_CON0);
-	} while (!(tmp & 0x1 << EXYNOS5_EPLLCON0_LOCKED_SHIFT));
-
-	clk->rate = rate;
-
-	return 0;
-}
-
-static struct clk_ops exynos5_epll_ops = {
-	.get_rate = exynos5_epll_get_rate,
-	.set_rate = exynos5_epll_set_rate,
-};
-
-static int xtal_rate;
-
-static unsigned long exynos5_fout_apll_get_rate(struct clk *clk)
-{
-	return s5p_get_pll35xx(xtal_rate, __raw_readl(EXYNOS5_APLL_CON0));
-}
-
-static struct clk_ops exynos5_fout_apll_ops = {
-	.get_rate = exynos5_fout_apll_get_rate,
-};
-
-#ifdef CONFIG_PM
-static int exynos5_clock_suspend(void)
-{
-	s3c_pm_do_save(exynos5_clock_save, ARRAY_SIZE(exynos5_clock_save));
-
-	return 0;
-}
-
-static void exynos5_clock_resume(void)
-{
-	s3c_pm_do_restore_core(exynos5_clock_save, ARRAY_SIZE(exynos5_clock_save));
-}
-#else
-#define exynos5_clock_suspend NULL
-#define exynos5_clock_resume NULL
-#endif
-
-static struct syscore_ops exynos5_clock_syscore_ops = {
-	.suspend	= exynos5_clock_suspend,
-	.resume		= exynos5_clock_resume,
-};
-
-void __init_or_cpufreq exynos5_setup_clocks(void)
-{
-	struct clk *xtal_clk;
-	unsigned long apll;
-	unsigned long bpll;
-	unsigned long cpll;
-	unsigned long mpll;
-	unsigned long epll;
-	unsigned long vpll;
-	unsigned long vpllsrc;
-	unsigned long xtal;
-	unsigned long armclk;
-	unsigned long mout_cdrex;
-	unsigned long aclk_400;
-	unsigned long aclk_333;
-	unsigned long aclk_266;
-	unsigned long aclk_200;
-	unsigned long aclk_166;
-	unsigned long aclk_66;
-	unsigned int ptr;
-
-	printk(KERN_DEBUG "%s: registering clocks\n", __func__);
-
-	xtal_clk = clk_get(NULL, "xtal");
-	BUG_ON(IS_ERR(xtal_clk));
-
-	xtal = clk_get_rate(xtal_clk);
-
-	xtal_rate = xtal;
-
-	clk_put(xtal_clk);
-
-	printk(KERN_DEBUG "%s: xtal is %ld\n", __func__, xtal);
-
-	apll = s5p_get_pll35xx(xtal, __raw_readl(EXYNOS5_APLL_CON0));
-	bpll = s5p_get_pll35xx(xtal, __raw_readl(EXYNOS5_BPLL_CON0));
-	cpll = s5p_get_pll35xx(xtal, __raw_readl(EXYNOS5_CPLL_CON0));
-	mpll = s5p_get_pll35xx(xtal, __raw_readl(EXYNOS5_MPLL_CON0));
-	epll = s5p_get_pll36xx(xtal, __raw_readl(EXYNOS5_EPLL_CON0),
-			__raw_readl(EXYNOS5_EPLL_CON1));
-
-	vpllsrc = clk_get_rate(&exynos5_clk_vpllsrc.clk);
-	vpll = s5p_get_pll36xx(vpllsrc, __raw_readl(EXYNOS5_VPLL_CON0),
-			__raw_readl(EXYNOS5_VPLL_CON1));
-
-	clk_fout_apll.ops = &exynos5_fout_apll_ops;
-	clk_fout_bpll.rate = bpll;
-	clk_fout_bpll_div2.rate = bpll >> 1;
-	clk_fout_cpll.rate = cpll;
-	clk_fout_mpll.rate = mpll;
-	clk_fout_mpll_div2.rate = mpll >> 1;
-	clk_fout_epll.rate = epll;
-	clk_fout_vpll.rate = vpll;
-
-	printk(KERN_INFO "EXYNOS5: PLL settings, A=%ld, B=%ld, C=%ld\n"
-			"M=%ld, E=%ld V=%ld",
-			apll, bpll, cpll, mpll, epll, vpll);
-
-	armclk = clk_get_rate(&exynos5_clk_armclk);
-	mout_cdrex = clk_get_rate(&exynos5_clk_cdrex.clk);
-
-	aclk_400 = clk_get_rate(&exynos5_clk_aclk_400.clk);
-	aclk_333 = clk_get_rate(&exynos5_clk_aclk_333.clk);
-	aclk_266 = clk_get_rate(&exynos5_clk_aclk_266.clk);
-	aclk_200 = clk_get_rate(&exynos5_clk_aclk_200.clk);
-	aclk_166 = clk_get_rate(&exynos5_clk_aclk_166.clk);
-	aclk_66 = clk_get_rate(&exynos5_clk_aclk_66.clk);
-
-	printk(KERN_INFO "EXYNOS5: ARMCLK=%ld, CDREX=%ld, ACLK400=%ld\n"
-			"ACLK333=%ld, ACLK266=%ld, ACLK200=%ld\n"
-			"ACLK166=%ld, ACLK66=%ld\n",
-			armclk, mout_cdrex, aclk_400,
-			aclk_333, aclk_266, aclk_200,
-			aclk_166, aclk_66);
-
-
-	clk_fout_epll.ops = &exynos5_epll_ops;
-
-	if (clk_set_parent(&exynos5_clk_mout_epll.clk, &clk_fout_epll))
-		printk(KERN_ERR "Unable to set parent %s of clock %s.\n",
-				clk_fout_epll.name, exynos5_clk_mout_epll.clk.name);
-
-	clk_set_rate(&exynos5_clk_sclk_apll.clk, 100000000);
-	clk_set_rate(&exynos5_clk_aclk_266.clk, 300000000);
-
-	clk_set_rate(&exynos5_clk_aclk_acp.clk, 267000000);
-	clk_set_rate(&exynos5_clk_pclk_acp.clk, 134000000);
-
-	for (ptr = 0; ptr < ARRAY_SIZE(exynos5_clksrcs); ptr++)
-		s3c_set_clksrc(&exynos5_clksrcs[ptr], true);
-}
-
-void __init exynos5_register_clocks(void)
-{
-	int ptr;
-
-	s3c24xx_register_clocks(exynos5_clks, ARRAY_SIZE(exynos5_clks));
-
-	for (ptr = 0; ptr < ARRAY_SIZE(exynos5_sysclks); ptr++)
-		s3c_register_clksrc(exynos5_sysclks[ptr], 1);
-
-	for (ptr = 0; ptr < ARRAY_SIZE(exynos5_sclk_tv); ptr++)
-		s3c_register_clksrc(exynos5_sclk_tv[ptr], 1);
-
-	for (ptr = 0; ptr < ARRAY_SIZE(exynos5_clksrc_cdev); ptr++)
-		s3c_register_clksrc(exynos5_clksrc_cdev[ptr], 1);
-
-	s3c_register_clksrc(exynos5_clksrcs, ARRAY_SIZE(exynos5_clksrcs));
-	s3c_register_clocks(exynos5_init_clocks_on, ARRAY_SIZE(exynos5_init_clocks_on));
-
-	s3c24xx_register_clocks(exynos5_clk_cdev, ARRAY_SIZE(exynos5_clk_cdev));
-	for (ptr = 0; ptr < ARRAY_SIZE(exynos5_clk_cdev); ptr++)
-		s3c_disable_clocks(exynos5_clk_cdev[ptr], 1);
-
-	s3c_register_clocks(exynos5_init_clocks_off, ARRAY_SIZE(exynos5_init_clocks_off));
-	s3c_disable_clocks(exynos5_init_clocks_off, ARRAY_SIZE(exynos5_init_clocks_off));
-	clkdev_add_table(exynos5_clk_lookup, ARRAY_SIZE(exynos5_clk_lookup));
-
-	register_syscore_ops(&exynos5_clock_syscore_ops);
-	s3c_pwmclk_init();
-}
diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c
index d63d399..baa8264 100644
--- a/arch/arm/mach-exynos/common.c
+++ b/arch/arm/mach-exynos/common.c
@@ -23,9 +23,11 @@
 #include <linux/of_irq.h>
 #include <linux/export.h>
 #include <linux/irqdomain.h>
-#include <linux/irqchip.h>
 #include <linux/of_address.h>
+#include <linux/clocksource.h>
+#include <linux/clk-provider.h>
 #include <linux/irqchip/arm-gic.h>
+#include <linux/irqchip/chained_irq.h>
 
 #include <asm/proc-fns.h>
 #include <asm/exception.h>
@@ -37,9 +39,9 @@
 #include <mach/regs-irq.h>
 #include <mach/regs-pmu.h>
 #include <mach/regs-gpio.h>
+#include <mach/irqs.h>
 
 #include <plat/cpu.h>
-#include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/pm.h>
 #include <plat/sdhci.h>
@@ -65,17 +67,16 @@ static const char name_exynos5440[] = "EXYNOS5440";
 static void exynos4_map_io(void);
 static void exynos5_map_io(void);
 static void exynos5440_map_io(void);
-static void exynos4_init_clocks(int xtal);
-static void exynos5_init_clocks(int xtal);
 static void exynos4_init_uarts(struct s3c2410_uartcfg *cfg, int no);
 static int exynos_init(void);
 
+unsigned long xxti_f = 0, xusbxti_f = 0;
+
 static struct cpu_table cpu_ids[] __initdata = {
 	{
 		.idcode		= EXYNOS4210_CPU_ID,
 		.idmask		= EXYNOS4_CPU_MASK,
 		.map_io		= exynos4_map_io,
-		.init_clocks	= exynos4_init_clocks,
 		.init_uarts	= exynos4_init_uarts,
 		.init		= exynos_init,
 		.name		= name_exynos4210,
@@ -83,7 +84,6 @@ static struct cpu_table cpu_ids[] __initdata = {
 		.idcode		= EXYNOS4212_CPU_ID,
 		.idmask		= EXYNOS4_CPU_MASK,
 		.map_io		= exynos4_map_io,
-		.init_clocks	= exynos4_init_clocks,
 		.init_uarts	= exynos4_init_uarts,
 		.init		= exynos_init,
 		.name		= name_exynos4212,
@@ -91,7 +91,6 @@ static struct cpu_table cpu_ids[] __initdata = {
 		.idcode		= EXYNOS4412_CPU_ID,
 		.idmask		= EXYNOS4_CPU_MASK,
 		.map_io		= exynos4_map_io,
-		.init_clocks	= exynos4_init_clocks,
 		.init_uarts	= exynos4_init_uarts,
 		.init		= exynos_init,
 		.name		= name_exynos4412,
@@ -99,7 +98,6 @@ static struct cpu_table cpu_ids[] __initdata = {
 		.idcode		= EXYNOS5250_SOC_ID,
 		.idmask		= EXYNOS5_SOC_MASK,
 		.map_io		= exynos5_map_io,
-		.init_clocks	= exynos5_init_clocks,
 		.init		= exynos_init,
 		.name		= name_exynos5250,
 	}, {
@@ -235,6 +233,33 @@ static struct map_desc exynos4_iodesc1[] __initdata = {
 	},
 };
 
+static struct map_desc exynos4210_iodesc[] __initdata = {
+	{
+		.virtual	= (unsigned long)S5P_VA_SYSRAM_NS,
+		.pfn		= __phys_to_pfn(EXYNOS4210_PA_SYSRAM_NS),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	},
+};
+
+static struct map_desc exynos4x12_iodesc[] __initdata = {
+	{
+		.virtual	= (unsigned long)S5P_VA_SYSRAM_NS,
+		.pfn		= __phys_to_pfn(EXYNOS4x12_PA_SYSRAM_NS),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	},
+};
+
+static struct map_desc exynos5250_iodesc[] __initdata = {
+	{
+		.virtual	= (unsigned long)S5P_VA_SYSRAM_NS,
+		.pfn		= __phys_to_pfn(EXYNOS5250_PA_SYSRAM_NS),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	},
+};
+
 static struct map_desc exynos5_iodesc[] __initdata = {
 	{
 		.virtual	= (unsigned long)S3C_VA_SYS,
@@ -257,11 +282,6 @@ static struct map_desc exynos5_iodesc[] __initdata = {
 		.length		= SZ_4K,
 		.type		= MT_DEVICE,
 	}, {
-		.virtual	= (unsigned long)S5P_VA_SYSTIMER,
-		.pfn		= __phys_to_pfn(EXYNOS5_PA_SYSTIMER),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	}, {
 		.virtual	= (unsigned long)S5P_VA_SYSRAM,
 		.pfn		= __phys_to_pfn(EXYNOS5_PA_SYSRAM),
 		.length		= SZ_4K,
@@ -368,6 +388,11 @@ static void __init exynos4_map_io(void)
 	else
 		iotable_init(exynos4_iodesc1, ARRAY_SIZE(exynos4_iodesc1));
 
+	if (soc_is_exynos4210())
+		iotable_init(exynos4210_iodesc, ARRAY_SIZE(exynos4210_iodesc));
+	if (soc_is_exynos4212() || soc_is_exynos4412())
+		iotable_init(exynos4x12_iodesc, ARRAY_SIZE(exynos4x12_iodesc));
+
 	/* initialize device information early */
 	exynos4_default_sdhci0();
 	exynos4_default_sdhci1();
@@ -400,22 +425,9 @@ static void __init exynos4_map_io(void)
 static void __init exynos5_map_io(void)
 {
 	iotable_init(exynos5_iodesc, ARRAY_SIZE(exynos5_iodesc));
-}
 
-static void __init exynos4_init_clocks(int xtal)
-{
-	printk(KERN_DEBUG "%s: initializing clocks\n", __func__);
-
-	s3c24xx_register_baseclocks(xtal);
-	s5p_register_clocks(xtal);
-
-	if (soc_is_exynos4210())
-		exynos4210_register_clocks();
-	else if (soc_is_exynos4212() || soc_is_exynos4412())
-		exynos4212_register_clocks();
-
-	exynos4_register_clocks();
-	exynos4_setup_clocks();
+	if (soc_is_exynos5250())
+		iotable_init(exynos5250_iodesc, ARRAY_SIZE(exynos5250_iodesc));
 }
 
 static void __init exynos5440_map_io(void)
@@ -423,22 +435,19 @@ static void __init exynos5440_map_io(void)
 	iotable_init(exynos5440_iodesc0, ARRAY_SIZE(exynos5440_iodesc0));
 }
 
-static void __init exynos5_init_clocks(int xtal)
+void __init exynos_init_time(void)
 {
-	printk(KERN_DEBUG "%s: initializing clocks\n", __func__);
-
-	/* EXYNOS5440 can support only common clock framework */
-
-	if (soc_is_exynos5440())
-		return;
-
-#ifdef CONFIG_SOC_EXYNOS5250
-	s3c24xx_register_baseclocks(xtal);
-	s5p_register_clocks(xtal);
-
-	exynos5_register_clocks();
-	exynos5_setup_clocks();
+	if (of_have_populated_dt()) {
+#ifdef CONFIG_OF
+		of_clk_init(NULL);
+		clocksource_of_init();
 #endif
+	} else {
+		/* todo: remove after migrating legacy E4 platforms to dt */
+		exynos4_clk_init(NULL);
+		exynos4_clk_register_fixed_ext(xxti_f, xusbxti_f);
+		mct_init();
+	}
 }
 
 void __init exynos4_init_irq(void)
@@ -463,6 +472,8 @@ void __init exynos4_init_irq(void)
 	 * uses GIC instead of VIC.
 	 */
 	s5p_init_irq(NULL, 0);
+
+	gic_arch_extn.irq_set_wake = s3c_irq_wake;
 }
 
 void __init exynos5_init_irq(void)
@@ -822,6 +833,7 @@ static int __init exynos_init_irq_eint(void)
 	static const struct of_device_id exynos_pinctrl_ids[] = {
 		{ .compatible = "samsung,exynos4210-pinctrl", },
 		{ .compatible = "samsung,exynos4x12-pinctrl", },
+		{ .compatible = "samsung,exynos5250-pinctrl", },
 	};
 	struct device_node *pctrl_np, *wkup_np;
 	const char *wkup_compat = "samsung,exynos4210-wakeup-eint";
@@ -875,3 +887,30 @@ static int __init exynos_init_irq_eint(void)
 	return 0;
 }
 arch_initcall(exynos_init_irq_eint);
+
+static struct resource exynos4_pmu_resource[] = {
+	DEFINE_RES_IRQ(EXYNOS4_IRQ_PMU),
+	DEFINE_RES_IRQ(EXYNOS4_IRQ_PMU_CPU1),
+#if defined(CONFIG_SOC_EXYNOS4412)
+	DEFINE_RES_IRQ(EXYNOS4_IRQ_PMU_CPU2),
+	DEFINE_RES_IRQ(EXYNOS4_IRQ_PMU_CPU3),
+#endif
+};
+
+static struct platform_device exynos4_device_pmu = {
+	.name		= "arm-pmu",
+	.num_resources	= ARRAY_SIZE(exynos4_pmu_resource),
+	.resource	= exynos4_pmu_resource,
+};
+
+static int __init exynos_armpmu_init(void)
+{
+	if (!of_have_populated_dt()) {
+		if (soc_is_exynos4210() || soc_is_exynos4212())
+			exynos4_device_pmu.num_resources = 2;
+		platform_device_register(&exynos4_device_pmu);
+	}
+
+	return 0;
+}
+arch_initcall(exynos_armpmu_init);
diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h
index 9339bb8..fcfc64c 100644
--- a/arch/arm/mach-exynos/common.h
+++ b/arch/arm/mach-exynos/common.h
@@ -12,7 +12,11 @@
 #ifndef __ARCH_ARM_MACH_EXYNOS_COMMON_H
 #define __ARCH_ARM_MACH_EXYNOS_COMMON_H
 
-extern void exynos4_timer_init(void);
+#include <linux/of.h>
+
+extern void mct_init(void);
+void exynos_init_time(void);
+extern unsigned long xxti_f, xusbxti_f;
 
 struct map_desc;
 void exynos_init_io(struct map_desc *mach_desc, int size);
@@ -22,6 +26,12 @@ void exynos4_restart(char mode, const char *cmd);
 void exynos5_restart(char mode, const char *cmd);
 void exynos_init_late(void);
 
+void exynos_firmware_init(void);
+
+/* ToDo: remove these after migrating legacy exynos4 platforms to dt */
+void exynos4_clk_init(struct device_node *np);
+void exynos4_clk_register_fixed_ext(unsigned long, unsigned long);
+
 #ifdef CONFIG_PM_GENERIC_DOMAINS
 int exynos_pm_late_initcall(void);
 #else
diff --git a/arch/arm/mach-exynos/cpuidle.c b/arch/arm/mach-exynos/cpuidle.c
index fcfe025..e2689d1 100644
--- a/arch/arm/mach-exynos/cpuidle.c
+++ b/arch/arm/mach-exynos/cpuidle.c
@@ -41,24 +41,25 @@ static int exynos4_enter_lowpower(struct cpuidle_device *dev,
 				struct cpuidle_driver *drv,
 				int index);
 
-static struct cpuidle_state exynos4_cpuidle_set[] __initdata = {
-	[0] = ARM_CPUIDLE_WFI_STATE,
-	[1] = {
-		.enter			= exynos4_enter_lowpower,
-		.exit_latency		= 300,
-		.target_residency	= 100000,
-		.flags			= CPUIDLE_FLAG_TIME_VALID,
-		.name			= "C1",
-		.desc			= "ARM power down",
-	},
-};
-
 static DEFINE_PER_CPU(struct cpuidle_device, exynos4_cpuidle_device);
 
 static struct cpuidle_driver exynos4_idle_driver = {
 	.name			= "exynos4_idle",
 	.owner			= THIS_MODULE,
 	.en_core_tk_irqen	= 1,
+	.states = {
+		[0] = ARM_CPUIDLE_WFI_STATE,
+		[1] = {
+			.enter			= exynos4_enter_lowpower,
+			.exit_latency		= 300,
+			.target_residency	= 100000,
+			.flags			= CPUIDLE_FLAG_TIME_VALID,
+			.name			= "C1",
+			.desc			= "ARM power down",
+		},
+	},
+	.state_count = 2,
+	.safe_state_index = 0,
 };
 
 /* Ext-GIC nIRQ/nFIQ is the only wakeup source in AFTR */
@@ -193,37 +194,30 @@ static void __init exynos5_core_down_clk(void)
 
 static int __init exynos4_init_cpuidle(void)
 {
-	int i, max_cpuidle_state, cpu_id;
+	int cpu_id, ret;
 	struct cpuidle_device *device;
-	struct cpuidle_driver *drv = &exynos4_idle_driver;
 
 	if (soc_is_exynos5250())
 		exynos5_core_down_clk();
 
-	/* Setup cpuidle driver */
-	drv->state_count = (sizeof(exynos4_cpuidle_set) /
-				       sizeof(struct cpuidle_state));
-	max_cpuidle_state = drv->state_count;
-	for (i = 0; i < max_cpuidle_state; i++) {
-		memcpy(&drv->states[i], &exynos4_cpuidle_set[i],
-				sizeof(struct cpuidle_state));
+	ret = cpuidle_register_driver(&exynos4_idle_driver);
+	if (ret) {
+		printk(KERN_ERR "CPUidle failed to register driver\n");
+		return ret;
 	}
-	drv->safe_state_index = 0;
-	cpuidle_register_driver(&exynos4_idle_driver);
 
-	for_each_cpu(cpu_id, cpu_online_mask) {
+	for_each_online_cpu(cpu_id) {
 		device = &per_cpu(exynos4_cpuidle_device, cpu_id);
 		device->cpu = cpu_id;
 
-		if (cpu_id == 0)
-			device->state_count = (sizeof(exynos4_cpuidle_set) /
-					       sizeof(struct cpuidle_state));
-		else
-			device->state_count = 1;	/* Support IDLE only */
+		/* Support IDLE only */
+		if (cpu_id != 0)
+			device->state_count = 1;
 
-		if (cpuidle_register_device(device)) {
-			printk(KERN_ERR "CPUidle register device failed\n,");
-			return -EIO;
+		ret = cpuidle_register_device(device);
+		if (ret) {
+			printk(KERN_ERR "CPUidle register device failed\n");
+			return ret;
 		}
 	}
 
diff --git a/arch/arm/mach-exynos/exynos-smc.S b/arch/arm/mach-exynos/exynos-smc.S
new file mode 100644
index 0000000..2e27aa3
--- /dev/null
+++ b/arch/arm/mach-exynos/exynos-smc.S
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2012 Samsung Electronics.
+ *
+ * Copied from omap-smc.S 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 version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/linkage.h>
+
+/*
+ * Function signature: void exynos_smc(u32 cmd, u32 arg1, u32 arg2, u32 arg3)
+ */
+
+ENTRY(exynos_smc)
+	stmfd	sp!, {r4-r11, lr}
+	dsb
+	smc	#0
+	ldmfd	sp!, {r4-r11, pc}
+ENDPROC(exynos_smc)
diff --git a/arch/arm/mach-exynos/firmware.c b/arch/arm/mach-exynos/firmware.c
new file mode 100644
index 0000000..ed11f10
--- /dev/null
+++ b/arch/arm/mach-exynos/firmware.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2012 Samsung Electronics.
+ * Kyungmin Park <kyungmin.park@samsung.com>
+ * Tomasz Figa <t.figa@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/io.h>
+#include <linux/init.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include <asm/firmware.h>
+
+#include <mach/map.h>
+
+#include "smc.h"
+
+static int exynos_do_idle(void)
+{
+	exynos_smc(SMC_CMD_SLEEP, 0, 0, 0);
+	return 0;
+}
+
+static int exynos_cpu_boot(int cpu)
+{
+	exynos_smc(SMC_CMD_CPU1BOOT, cpu, 0, 0);
+	return 0;
+}
+
+static int exynos_set_cpu_boot_addr(int cpu, unsigned long boot_addr)
+{
+	void __iomem *boot_reg = S5P_VA_SYSRAM_NS + 0x1c + 4*cpu;
+
+	__raw_writel(boot_addr, boot_reg);
+	return 0;
+}
+
+static const struct firmware_ops exynos_firmware_ops = {
+	.do_idle		= exynos_do_idle,
+	.set_cpu_boot_addr	= exynos_set_cpu_boot_addr,
+	.cpu_boot		= exynos_cpu_boot,
+};
+
+void __init exynos_firmware_init(void)
+{
+	if (of_have_populated_dt()) {
+		struct device_node *nd;
+		const __be32 *addr;
+
+		nd = of_find_compatible_node(NULL, NULL,
+						"samsung,secure-firmware");
+		if (!nd)
+			return;
+
+		addr = of_get_address(nd, 0, NULL, NULL);
+		if (!addr) {
+			pr_err("%s: No address specified.\n", __func__);
+			return;
+		}
+	}
+
+	pr_info("Running under secure firmware.\n");
+
+	register_firmware_ops(&exynos_firmware_ops);
+}
diff --git a/arch/arm/mach-exynos/include/mach/irqs.h b/arch/arm/mach-exynos/include/mach/irqs.h
index 1f4dc35..35fe6d5 100644
--- a/arch/arm/mach-exynos/include/mach/irqs.h
+++ b/arch/arm/mach-exynos/include/mach/irqs.h
@@ -30,8 +30,6 @@
 
 /* For EXYNOS4 and EXYNOS5 */
 
-#define EXYNOS_IRQ_MCT_LOCALTIMER	IRQ_PPI(12)
-
 #define EXYNOS_IRQ_EINT16_31		IRQ_SPI(32)
 
 /* For EXYNOS4 SoCs */
@@ -128,7 +126,7 @@
 #define EXYNOS4_IRQ_ADC1		IRQ_SPI(107)
 #define EXYNOS4_IRQ_PEN1		IRQ_SPI(108)
 #define EXYNOS4_IRQ_KEYPAD		IRQ_SPI(109)
-#define EXYNOS4_IRQ_PMU			IRQ_SPI(110)
+#define EXYNOS4_IRQ_POWER_PMU		IRQ_SPI(110)
 #define EXYNOS4_IRQ_GPS			IRQ_SPI(111)
 #define EXYNOS4_IRQ_INTFEEDCTRL_SSS	IRQ_SPI(112)
 #define EXYNOS4_IRQ_SLIMBUS		IRQ_SPI(113)
@@ -136,6 +134,11 @@
 #define EXYNOS4_IRQ_TSI			IRQ_SPI(115)
 #define EXYNOS4_IRQ_SATA		IRQ_SPI(116)
 
+#define EXYNOS4_IRQ_PMU			COMBINER_IRQ(2, 2)
+#define EXYNOS4_IRQ_PMU_CPU1		COMBINER_IRQ(3, 2)
+#define EXYNOS4_IRQ_PMU_CPU2		COMBINER_IRQ(18, 2)
+#define EXYNOS4_IRQ_PMU_CPU3		COMBINER_IRQ(19, 2)
+
 #define EXYNOS4_IRQ_TMU_TRIG0		COMBINER_IRQ(2, 4)
 #define EXYNOS4_IRQ_TMU_TRIG1		COMBINER_IRQ(3, 4)
 
@@ -168,7 +171,10 @@
 #define EXYNOS4_IRQ_FIMD0_VSYNC		COMBINER_IRQ(11, 1)
 #define EXYNOS4_IRQ_FIMD0_SYSTEM	COMBINER_IRQ(11, 2)
 
-#define EXYNOS4_MAX_COMBINER_NR		16
+#define EXYNOS4210_MAX_COMBINER_NR	16
+#define EXYNOS4212_MAX_COMBINER_NR	18
+#define EXYNOS4412_MAX_COMBINER_NR	20
+#define EXYNOS4_MAX_COMBINER_NR		EXYNOS4412_MAX_COMBINER_NR
 
 #define EXYNOS4_IRQ_GPIO1_NR_GROUPS	16
 #define EXYNOS4_IRQ_GPIO2_NR_GROUPS	9
@@ -233,7 +239,6 @@
 #define IRQ_TC				EXYNOS4_IRQ_PEN0
 
 #define IRQ_KEYPAD			EXYNOS4_IRQ_KEYPAD
-#define IRQ_PMU				EXYNOS4_IRQ_PMU
 
 #define IRQ_FIMD0_FIFO			EXYNOS4_IRQ_FIMD0_FIFO
 #define IRQ_FIMD0_VSYNC			EXYNOS4_IRQ_FIMD0_VSYNC
@@ -323,8 +328,6 @@
 #define EXYNOS5_IRQ_CEC			IRQ_SPI(114)
 #define EXYNOS5_IRQ_SATA		IRQ_SPI(115)
 
-#define EXYNOS5_IRQ_MCT_L0		IRQ_SPI(120)
-#define EXYNOS5_IRQ_MCT_L1		IRQ_SPI(121)
 #define EXYNOS5_IRQ_MMC44		IRQ_SPI(123)
 #define EXYNOS5_IRQ_MDMA1		IRQ_SPI(124)
 #define EXYNOS5_IRQ_FIMC_LITE0		IRQ_SPI(125)
@@ -419,8 +422,6 @@
 #define EXYNOS5_IRQ_PMU_CPU1		COMBINER_IRQ(22, 4)
 
 #define EXYNOS5_IRQ_EINT0		COMBINER_IRQ(23, 0)
-#define EXYNOS5_IRQ_MCT_G0		COMBINER_IRQ(23, 3)
-#define EXYNOS5_IRQ_MCT_G1		COMBINER_IRQ(23, 4)
 
 #define EXYNOS5_IRQ_EINT1		COMBINER_IRQ(24, 0)
 #define EXYNOS5_IRQ_SYSMMU_LITE1_0	COMBINER_IRQ(24, 1)
diff --git a/arch/arm/mach-exynos/include/mach/map.h b/arch/arm/mach-exynos/include/mach/map.h
index 1df6abb..99e0a79 100644
--- a/arch/arm/mach-exynos/include/mach/map.h
+++ b/arch/arm/mach-exynos/include/mach/map.h
@@ -26,6 +26,9 @@
 #define EXYNOS4_PA_SYSRAM0		0x02025000
 #define EXYNOS4_PA_SYSRAM1		0x02020000
 #define EXYNOS5_PA_SYSRAM		0x02020000
+#define EXYNOS4210_PA_SYSRAM_NS		0x0203F000
+#define EXYNOS4x12_PA_SYSRAM_NS		0x0204F000
+#define EXYNOS5250_PA_SYSRAM_NS		0x0204F000
 
 #define EXYNOS4_PA_FIMC0		0x11800000
 #define EXYNOS4_PA_FIMC1		0x11810000
@@ -65,7 +68,6 @@
 #define EXYNOS5_PA_CMU			0x10010000
 
 #define EXYNOS4_PA_SYSTIMER		0x10050000
-#define EXYNOS5_PA_SYSTIMER		0x101C0000
 
 #define EXYNOS4_PA_WATCHDOG		0x10060000
 #define EXYNOS5_PA_WATCHDOG		0x101D0000
diff --git a/arch/arm/mach-exynos/include/mach/pm-core.h b/arch/arm/mach-exynos/include/mach/pm-core.h
index a67ecfa..7dbbfec 100644
--- a/arch/arm/mach-exynos/include/mach/pm-core.h
+++ b/arch/arm/mach-exynos/include/mach/pm-core.h
@@ -27,13 +27,8 @@ static inline void s3c_pm_debug_init_uart(void)
 
 static inline void s3c_pm_arch_prepare_irqs(void)
 {
-	unsigned int tmp;
-	tmp = __raw_readl(S5P_WAKEUP_MASK);
-	tmp &= ~(1 << 31);
-	__raw_writel(tmp, S5P_WAKEUP_MASK);
-
-	__raw_writel(s3c_irqwake_intmask, S5P_WAKEUP_MASK);
-	__raw_writel(s3c_irqwake_eintmask & 0xFFFFFFFE, S5P_EINT_WAKEUP_MASK);
+	__raw_writel(s3c_irqwake_eintmask, S5P_EINT_WAKEUP_MASK);
+	__raw_writel(s3c_irqwake_intmask & ~(1 << 31), S5P_WAKEUP_MASK);
 }
 
 static inline void s3c_pm_arch_stop_clocks(void)
diff --git a/arch/arm/mach-exynos/include/mach/regs-clock.h b/arch/arm/mach-exynos/include/mach/regs-clock.h
index d36ad76..20fbbdd 100644
--- a/arch/arm/mach-exynos/include/mach/regs-clock.h
+++ b/arch/arm/mach-exynos/include/mach/regs-clock.h
@@ -256,113 +256,6 @@
 #define EXYNOS4_CLKDIV_CAM1_JPEG_SHIFT		(0)
 #define EXYNOS4_CLKDIV_CAM1_JPEG_MASK		(0xf << EXYNOS4_CLKDIV_CAM1_JPEG_SHIFT)
 
-/* For EXYNOS5250 */
-
-#define EXYNOS5_APLL_LOCK			EXYNOS_CLKREG(0x00000)
-#define EXYNOS5_APLL_CON0			EXYNOS_CLKREG(0x00100)
-#define EXYNOS5_CLKSRC_CPU			EXYNOS_CLKREG(0x00200)
-#define EXYNOS5_CLKMUX_STATCPU			EXYNOS_CLKREG(0x00400)
-#define EXYNOS5_CLKDIV_CPU0			EXYNOS_CLKREG(0x00500)
-#define EXYNOS5_CLKDIV_CPU1			EXYNOS_CLKREG(0x00504)
-#define EXYNOS5_CLKDIV_STATCPU0			EXYNOS_CLKREG(0x00600)
-#define EXYNOS5_CLKDIV_STATCPU1			EXYNOS_CLKREG(0x00604)
-
-#define EXYNOS5_PWR_CTRL1			EXYNOS_CLKREG(0x01020)
-#define EXYNOS5_PWR_CTRL2			EXYNOS_CLKREG(0x01024)
-
-#define EXYNOS5_MPLL_CON0			EXYNOS_CLKREG(0x04100)
-#define EXYNOS5_CLKSRC_CORE1			EXYNOS_CLKREG(0x04204)
-
-#define EXYNOS5_CLKGATE_IP_CORE			EXYNOS_CLKREG(0x04900)
-
-#define EXYNOS5_CLKDIV_ACP			EXYNOS_CLKREG(0x08500)
-
-#define EXYNOS5_EPLL_CON0			EXYNOS_CLKREG(0x10130)
-#define EXYNOS5_EPLL_CON1			EXYNOS_CLKREG(0x10134)
-#define EXYNOS5_EPLL_CON2			EXYNOS_CLKREG(0x10138)
-#define EXYNOS5_VPLL_CON0			EXYNOS_CLKREG(0x10140)
-#define EXYNOS5_VPLL_CON1			EXYNOS_CLKREG(0x10144)
-#define EXYNOS5_VPLL_CON2			EXYNOS_CLKREG(0x10148)
-#define EXYNOS5_CPLL_CON0			EXYNOS_CLKREG(0x10120)
-
-#define EXYNOS5_CLKSRC_TOP0			EXYNOS_CLKREG(0x10210)
-#define EXYNOS5_CLKSRC_TOP1			EXYNOS_CLKREG(0x10214)
-#define EXYNOS5_CLKSRC_TOP2			EXYNOS_CLKREG(0x10218)
-#define EXYNOS5_CLKSRC_TOP3			EXYNOS_CLKREG(0x1021C)
-#define EXYNOS5_CLKSRC_GSCL			EXYNOS_CLKREG(0x10220)
-#define EXYNOS5_CLKSRC_DISP1_0			EXYNOS_CLKREG(0x1022C)
-#define EXYNOS5_CLKSRC_MAUDIO			EXYNOS_CLKREG(0x10240)
-#define EXYNOS5_CLKSRC_FSYS			EXYNOS_CLKREG(0x10244)
-#define EXYNOS5_CLKSRC_PERIC0			EXYNOS_CLKREG(0x10250)
-#define EXYNOS5_CLKSRC_PERIC1			EXYNOS_CLKREG(0x10254)
-#define EXYNOS5_SCLK_SRC_ISP			EXYNOS_CLKREG(0x10270)
-
-#define EXYNOS5_CLKSRC_MASK_TOP			EXYNOS_CLKREG(0x10310)
-#define EXYNOS5_CLKSRC_MASK_GSCL		EXYNOS_CLKREG(0x10320)
-#define EXYNOS5_CLKSRC_MASK_DISP1_0		EXYNOS_CLKREG(0x1032C)
-#define EXYNOS5_CLKSRC_MASK_MAUDIO		EXYNOS_CLKREG(0x10334)
-#define EXYNOS5_CLKSRC_MASK_FSYS		EXYNOS_CLKREG(0x10340)
-#define EXYNOS5_CLKSRC_MASK_PERIC0		EXYNOS_CLKREG(0x10350)
-#define EXYNOS5_CLKSRC_MASK_PERIC1		EXYNOS_CLKREG(0x10354)
-
-#define EXYNOS5_CLKDIV_TOP0			EXYNOS_CLKREG(0x10510)
-#define EXYNOS5_CLKDIV_TOP1			EXYNOS_CLKREG(0x10514)
-#define EXYNOS5_CLKDIV_GSCL			EXYNOS_CLKREG(0x10520)
-#define EXYNOS5_CLKDIV_DISP1_0			EXYNOS_CLKREG(0x1052C)
-#define EXYNOS5_CLKDIV_GEN			EXYNOS_CLKREG(0x1053C)
-#define EXYNOS5_CLKDIV_MAUDIO			EXYNOS_CLKREG(0x10544)
-#define EXYNOS5_CLKDIV_FSYS0			EXYNOS_CLKREG(0x10548)
-#define EXYNOS5_CLKDIV_FSYS1			EXYNOS_CLKREG(0x1054C)
-#define EXYNOS5_CLKDIV_FSYS2			EXYNOS_CLKREG(0x10550)
-#define EXYNOS5_CLKDIV_FSYS3			EXYNOS_CLKREG(0x10554)
-#define EXYNOS5_CLKDIV_PERIC0			EXYNOS_CLKREG(0x10558)
-#define EXYNOS5_CLKDIV_PERIC1			EXYNOS_CLKREG(0x1055C)
-#define EXYNOS5_CLKDIV_PERIC2			EXYNOS_CLKREG(0x10560)
-#define EXYNOS5_CLKDIV_PERIC3			EXYNOS_CLKREG(0x10564)
-#define EXYNOS5_CLKDIV_PERIC4			EXYNOS_CLKREG(0x10568)
-#define EXYNOS5_CLKDIV_PERIC5			EXYNOS_CLKREG(0x1056C)
-#define EXYNOS5_SCLK_DIV_ISP			EXYNOS_CLKREG(0x10580)
-
-#define EXYNOS5_CLKGATE_IP_ACP			EXYNOS_CLKREG(0x08800)
-#define EXYNOS5_CLKGATE_IP_ISP0			EXYNOS_CLKREG(0x0C800)
-#define EXYNOS5_CLKGATE_IP_ISP1			EXYNOS_CLKREG(0x0C804)
-#define EXYNOS5_CLKGATE_IP_GSCL			EXYNOS_CLKREG(0x10920)
-#define EXYNOS5_CLKGATE_IP_DISP1		EXYNOS_CLKREG(0x10928)
-#define EXYNOS5_CLKGATE_IP_MFC			EXYNOS_CLKREG(0x1092C)
-#define EXYNOS5_CLKGATE_IP_G3D			EXYNOS_CLKREG(0x10930)
-#define EXYNOS5_CLKGATE_IP_GEN			EXYNOS_CLKREG(0x10934)
-#define EXYNOS5_CLKGATE_IP_FSYS			EXYNOS_CLKREG(0x10944)
-#define EXYNOS5_CLKGATE_IP_GPS			EXYNOS_CLKREG(0x1094C)
-#define EXYNOS5_CLKGATE_IP_PERIC		EXYNOS_CLKREG(0x10950)
-#define EXYNOS5_CLKGATE_IP_PERIS		EXYNOS_CLKREG(0x10960)
-#define EXYNOS5_CLKGATE_BLOCK			EXYNOS_CLKREG(0x10980)
-
-#define EXYNOS5_BPLL_CON0			EXYNOS_CLKREG(0x20110)
-#define EXYNOS5_CLKSRC_CDREX			EXYNOS_CLKREG(0x20200)
-#define EXYNOS5_CLKDIV_CDREX			EXYNOS_CLKREG(0x20500)
-
-#define EXYNOS5_PLL_DIV2_SEL			EXYNOS_CLKREG(0x20A24)
-
-#define EXYNOS5_EPLL_LOCK			EXYNOS_CLKREG(0x10030)
-
-#define EXYNOS5_EPLLCON0_LOCKED_SHIFT		(29)
-
-#define PWR_CTRL1_CORE2_DOWN_RATIO		(7 << 28)
-#define PWR_CTRL1_CORE1_DOWN_RATIO		(7 << 16)
-#define PWR_CTRL1_DIV2_DOWN_EN			(1 << 9)
-#define PWR_CTRL1_DIV1_DOWN_EN			(1 << 8)
-#define PWR_CTRL1_USE_CORE1_WFE			(1 << 5)
-#define PWR_CTRL1_USE_CORE0_WFE			(1 << 4)
-#define PWR_CTRL1_USE_CORE1_WFI			(1 << 1)
-#define PWR_CTRL1_USE_CORE0_WFI			(1 << 0)
-
-#define PWR_CTRL2_DIV2_UP_EN			(1 << 25)
-#define PWR_CTRL2_DIV1_UP_EN			(1 << 24)
-#define PWR_CTRL2_DUR_STANDBY2_VAL		(1 << 16)
-#define PWR_CTRL2_DUR_STANDBY1_VAL		(1 << 8)
-#define PWR_CTRL2_CORE2_UP_RATIO		(1 << 4)
-#define PWR_CTRL2_CORE1_UP_RATIO		(1 << 0)
-
 /* Compatibility defines and inclusion */
 
 #include <mach/regs-pmu.h>
diff --git a/arch/arm/mach-exynos/include/mach/regs-mct.h b/arch/arm/mach-exynos/include/mach/regs-mct.h
deleted file mode 100644
index 80dd02a..0000000
--- a/arch/arm/mach-exynos/include/mach/regs-mct.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/* arch/arm/mach-exynos4/include/mach/regs-mct.h
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * EXYNOS4 MCT configutation
- *
- * This program is free software; you can 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_MCT_H
-#define __ASM_ARCH_REGS_MCT_H __FILE__
-
-#include <mach/map.h>
-
-#define EXYNOS4_MCTREG(x)		(S5P_VA_SYSTIMER + (x))
-
-#define EXYNOS4_MCT_G_CNT_L		EXYNOS4_MCTREG(0x100)
-#define EXYNOS4_MCT_G_CNT_U		EXYNOS4_MCTREG(0x104)
-#define EXYNOS4_MCT_G_CNT_WSTAT		EXYNOS4_MCTREG(0x110)
-
-#define EXYNOS4_MCT_G_COMP0_L		EXYNOS4_MCTREG(0x200)
-#define EXYNOS4_MCT_G_COMP0_U		EXYNOS4_MCTREG(0x204)
-#define EXYNOS4_MCT_G_COMP0_ADD_INCR	EXYNOS4_MCTREG(0x208)
-
-#define EXYNOS4_MCT_G_TCON		EXYNOS4_MCTREG(0x240)
-
-#define EXYNOS4_MCT_G_INT_CSTAT		EXYNOS4_MCTREG(0x244)
-#define EXYNOS4_MCT_G_INT_ENB		EXYNOS4_MCTREG(0x248)
-#define EXYNOS4_MCT_G_WSTAT		EXYNOS4_MCTREG(0x24C)
-
-#define _EXYNOS4_MCT_L_BASE		EXYNOS4_MCTREG(0x300)
-#define EXYNOS4_MCT_L_BASE(x)		(_EXYNOS4_MCT_L_BASE + (0x100 * x))
-#define EXYNOS4_MCT_L_MASK		(0xffffff00)
-
-#define MCT_L_TCNTB_OFFSET		(0x00)
-#define MCT_L_ICNTB_OFFSET		(0x08)
-#define MCT_L_TCON_OFFSET		(0x20)
-#define MCT_L_INT_CSTAT_OFFSET		(0x30)
-#define MCT_L_INT_ENB_OFFSET		(0x34)
-#define MCT_L_WSTAT_OFFSET		(0x40)
-
-#define MCT_G_TCON_START		(1 << 8)
-#define MCT_G_TCON_COMP0_AUTO_INC	(1 << 1)
-#define MCT_G_TCON_COMP0_ENABLE		(1 << 0)
-
-#define MCT_L_TCON_INTERVAL_MODE	(1 << 2)
-#define MCT_L_TCON_INT_START		(1 << 1)
-#define MCT_L_TCON_TIMER_START		(1 << 0)
-
-#endif /* __ASM_ARCH_REGS_MCT_H */
diff --git a/arch/arm/mach-exynos/mach-armlex4210.c b/arch/arm/mach-exynos/mach-armlex4210.c
index 685f291..2c23b65 100644
--- a/arch/arm/mach-exynos/mach-armlex4210.c
+++ b/arch/arm/mach-exynos/mach-armlex4210.c
@@ -177,7 +177,6 @@ static void __init armlex4210_smsc911x_init(void)
 static void __init armlex4210_map_io(void)
 {
 	exynos_init_io(NULL, 0);
-	s3c24xx_init_clocks(24000000);
 	s3c24xx_init_uarts(armlex4210_uartcfgs,
 			   ARRAY_SIZE(armlex4210_uartcfgs));
 }
@@ -202,6 +201,6 @@ MACHINE_START(ARMLEX4210, "ARMLEX4210")
 	.map_io		= armlex4210_map_io,
 	.init_machine	= armlex4210_machine_init,
 	.init_late	= exynos_init_late,
-	.init_time	= exynos4_timer_init,
+	.init_time	= exynos_init_time,
 	.restart	= exynos4_restart,
 MACHINE_END
diff --git a/arch/arm/mach-exynos/mach-exynos4-dt.c b/arch/arm/mach-exynos/mach-exynos4-dt.c
index 3358088..b9ed834 100644
--- a/arch/arm/mach-exynos/mach-exynos4-dt.c
+++ b/arch/arm/mach-exynos/mach-exynos4-dt.c
@@ -11,121 +11,26 @@
  * published by the Free Software Foundation.
 */
 
+#include <linux/kernel.h>
 #include <linux/of_platform.h>
+#include <linux/of_fdt.h>
 #include <linux/serial_core.h>
+#include <linux/memblock.h>
+#include <linux/clocksource.h>
 
 #include <asm/mach/arch.h>
-#include <mach/map.h>
-
-#include <plat/cpu.h>
-#include <plat/regs-serial.h>
+#include <plat/mfc.h>
 
 #include "common.h"
 
-/*
- * The following lookup table is used to override device names when devices
- * are registered from device tree. This is temporarily added to enable
- * device tree support addition for the Exynos4 architecture.
- *
- * For drivers that require platform data to be provided from the machine
- * file, a platform data pointer can also be supplied along with the
- * devices names. Usually, the platform data elements that cannot be parsed
- * from the device tree by the drivers (example: function pointers) are
- * supplied. But it should be noted that this is a temporary mechanism and
- * at some point, the drivers should be capable of parsing all the platform
- * data from the device tree.
- */
-static const struct of_dev_auxdata exynos4_auxdata_lookup[] __initconst = {
-	OF_DEV_AUXDATA("samsung,exynos4210-uart", EXYNOS4_PA_UART0,
-				"exynos4210-uart.0", NULL),
-	OF_DEV_AUXDATA("samsung,exynos4210-uart", EXYNOS4_PA_UART1,
-				"exynos4210-uart.1", NULL),
-	OF_DEV_AUXDATA("samsung,exynos4210-uart", EXYNOS4_PA_UART2,
-				"exynos4210-uart.2", NULL),
-	OF_DEV_AUXDATA("samsung,exynos4210-uart", EXYNOS4_PA_UART3,
-				"exynos4210-uart.3", NULL),
-	OF_DEV_AUXDATA("samsung,exynos4210-sdhci", EXYNOS4_PA_HSMMC(0),
-				"exynos4-sdhci.0", NULL),
-	OF_DEV_AUXDATA("samsung,exynos4210-sdhci", EXYNOS4_PA_HSMMC(1),
-				"exynos4-sdhci.1", NULL),
-	OF_DEV_AUXDATA("samsung,exynos4210-sdhci", EXYNOS4_PA_HSMMC(2),
-				"exynos4-sdhci.2", NULL),
-	OF_DEV_AUXDATA("samsung,exynos4210-sdhci", EXYNOS4_PA_HSMMC(3),
-				"exynos4-sdhci.3", NULL),
-	OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS4_PA_IIC(0),
-				"s3c2440-i2c.0", NULL),
-	OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS4_PA_IIC(1),
-				"s3c2440-i2c.1", NULL),
-	OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS4_PA_IIC(2),
-				"s3c2440-i2c.2", NULL),
-	OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS4_PA_IIC(3),
-				"s3c2440-i2c.3", NULL),
-	OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS4_PA_IIC(4),
-				"s3c2440-i2c.4", NULL),
-	OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS4_PA_IIC(5),
-				"s3c2440-i2c.5", NULL),
-	OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS4_PA_IIC(6),
-				"s3c2440-i2c.6", NULL),
-	OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS4_PA_IIC(7),
-				"s3c2440-i2c.7", NULL),
-	OF_DEV_AUXDATA("samsung,exynos4210-spi", EXYNOS4_PA_SPI0,
-				"exynos4210-spi.0", NULL),
-	OF_DEV_AUXDATA("samsung,exynos4210-spi", EXYNOS4_PA_SPI1,
-				"exynos4210-spi.1", NULL),
-	OF_DEV_AUXDATA("samsung,exynos4210-spi", EXYNOS4_PA_SPI2,
-				"exynos4210-spi.2", NULL),
-	OF_DEV_AUXDATA("arm,pl330", EXYNOS4_PA_PDMA0, "dma-pl330.0", NULL),
-	OF_DEV_AUXDATA("arm,pl330", EXYNOS4_PA_PDMA1, "dma-pl330.1", NULL),
-	OF_DEV_AUXDATA("arm,pl330", EXYNOS4_PA_MDMA1, "dma-pl330.2", NULL),
-	OF_DEV_AUXDATA("samsung,exynos4210-tmu", EXYNOS4_PA_TMU,
-				"exynos-tmu", NULL),
-	OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x13620000,
-			"exynos-sysmmu.0", NULL), /* MFC_L */
-	OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x13630000,
-			"exynos-sysmmu.1", NULL), /* MFC_R */
-	OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x13E20000,
-			"exynos-sysmmu.2", NULL), /* TV */
-	OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x11A60000,
-			"exynos-sysmmu.3", NULL), /* JPEG */
-	OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x12A30000,
-			"exynos-sysmmu.4", NULL), /* ROTATOR */
-	OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x11A20000,
-			"exynos-sysmmu.5", NULL), /* FIMC0 */
-	OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x11A30000,
-			"exynos-sysmmu.6", NULL), /* FIMC1 */
-	OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x11A40000,
-			"exynos-sysmmu.7", NULL), /* FIMC2 */
-	OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x11A50000,
-			"exynos-sysmmu.8", NULL), /* FIMC3 */
-	OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x12A20000,
-			"exynos-sysmmu.9", NULL), /* G2D(4210) */
-	OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x10A40000,
-			"exynos-sysmmu.9", NULL), /* G2D(4x12) */
-	OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x11E20000,
-			"exynos-sysmmu.10", NULL), /* FIMD0 */
-	OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x12220000,
-			"exynos-sysmmu.11", NULL), /* FIMD1(4210) */
-	OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x12260000,
-			"exynos-sysmmu.12", NULL), /* IS0(4x12) */
-	OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x122B0000,
-			"exynos-sysmmu.13", NULL), /* IS1(4x12) */
-	OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x123B0000,
-			"exynos-sysmmu.14", NULL), /* FIMC-LITE0(4x12) */
-	OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x123C0000,
-			"exynos-sysmmu.15", NULL), /* FIMC-LITE1(4x12) */
-	{},
-};
-
 static void __init exynos4_dt_map_io(void)
 {
 	exynos_init_io(NULL, 0);
-	s3c24xx_init_clocks(24000000);
 }
 
 static void __init exynos4_dt_machine_init(void)
 {
-	of_platform_populate(NULL, of_default_bus_match_table,
-				exynos4_auxdata_lookup, NULL);
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
 static char const *exynos4_dt_compat[] __initdata = {
@@ -135,14 +40,28 @@ static char const *exynos4_dt_compat[] __initdata = {
 	NULL
 };
 
+static void __init exynos4_reserve(void)
+{
+#ifdef CONFIG_S5P_DEV_MFC
+	struct s5p_mfc_dt_meminfo mfc_mem;
+
+	/* Reserve memory for MFC only if it's available */
+	mfc_mem.compatible = "samsung,mfc-v5";
+	if (of_scan_flat_dt(s5p_fdt_find_mfc_mem, &mfc_mem))
+		s5p_mfc_reserve_mem(mfc_mem.roff, mfc_mem.rsize, mfc_mem.loff,
+				mfc_mem.lsize);
+#endif
+}
 DT_MACHINE_START(EXYNOS4210_DT, "Samsung Exynos4 (Flattened Device Tree)")
 	/* Maintainer: Thomas Abraham <thomas.abraham@linaro.org> */
 	.smp		= smp_ops(exynos_smp_ops),
 	.init_irq	= exynos4_init_irq,
 	.map_io		= exynos4_dt_map_io,
+	.init_early	= exynos_firmware_init,
 	.init_machine	= exynos4_dt_machine_init,
 	.init_late	= exynos_init_late,
-	.init_time	= exynos4_timer_init,
+	.init_time	= exynos_init_time,
 	.dt_compat	= exynos4_dt_compat,
 	.restart        = exynos4_restart,
+	.reserve	= exynos4_reserve,
 MACHINE_END
diff --git a/arch/arm/mach-exynos/mach-exynos5-dt.c b/arch/arm/mach-exynos/mach-exynos5-dt.c
index acaeb14..753b94f 100644
--- a/arch/arm/mach-exynos/mach-exynos5-dt.c
+++ b/arch/arm/mach-exynos/mach-exynos5-dt.c
@@ -11,151 +11,21 @@
 
 #include <linux/of_platform.h>
 #include <linux/of_fdt.h>
-#include <linux/serial_core.h>
 #include <linux/memblock.h>
 #include <linux/io.h>
+#include <linux/clocksource.h>
 
 #include <asm/mach/arch.h>
-#include <mach/map.h>
 #include <mach/regs-pmu.h>
 
 #include <plat/cpu.h>
-#include <plat/regs-serial.h>
 #include <plat/mfc.h>
 
 #include "common.h"
 
-/*
- * The following lookup table is used to override device names when devices
- * are registered from device tree. This is temporarily added to enable
- * device tree support addition for the EXYNOS5 architecture.
- *
- * For drivers that require platform data to be provided from the machine
- * file, a platform data pointer can also be supplied along with the
- * devices names. Usually, the platform data elements that cannot be parsed
- * from the device tree by the drivers (example: function pointers) are
- * supplied. But it should be noted that this is a temporary mechanism and
- * at some point, the drivers should be capable of parsing all the platform
- * data from the device tree.
- */
-static const struct of_dev_auxdata exynos5250_auxdata_lookup[] __initconst = {
-	OF_DEV_AUXDATA("samsung,exynos4210-uart", EXYNOS5_PA_UART0,
-				"exynos4210-uart.0", NULL),
-	OF_DEV_AUXDATA("samsung,exynos4210-uart", EXYNOS5_PA_UART1,
-				"exynos4210-uart.1", NULL),
-	OF_DEV_AUXDATA("samsung,exynos4210-uart", EXYNOS5_PA_UART2,
-				"exynos4210-uart.2", NULL),
-	OF_DEV_AUXDATA("samsung,exynos4210-uart", EXYNOS5_PA_UART3,
-				"exynos4210-uart.3", NULL),
-	OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS5_PA_IIC(0),
-				"s3c2440-i2c.0", NULL),
-	OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS5_PA_IIC(1),
-				"s3c2440-i2c.1", NULL),
-	OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS5_PA_IIC(2),
-				"s3c2440-i2c.2", NULL),
-	OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS5_PA_IIC(3),
-				"s3c2440-i2c.3", NULL),
-	OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS5_PA_IIC(4),
-				"s3c2440-i2c.4", NULL),
-	OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS5_PA_IIC(5),
-				"s3c2440-i2c.5", NULL),
-	OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS5_PA_IIC(6),
-				"s3c2440-i2c.6", NULL),
-	OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS5_PA_IIC(7),
-				"s3c2440-i2c.7", NULL),
-	OF_DEV_AUXDATA("samsung,s3c2440-hdmiphy-i2c", EXYNOS5_PA_IIC(8),
-				"s3c2440-hdmiphy-i2c", NULL),
-	OF_DEV_AUXDATA("samsung,exynos5250-dw-mshc", EXYNOS5_PA_DWMCI0,
-				"dw_mmc.0", NULL),
-	OF_DEV_AUXDATA("samsung,exynos5250-dw-mshc", EXYNOS5_PA_DWMCI1,
-				"dw_mmc.1", NULL),
-	OF_DEV_AUXDATA("samsung,exynos5250-dw-mshc", EXYNOS5_PA_DWMCI2,
-				"dw_mmc.2", NULL),
-	OF_DEV_AUXDATA("samsung,exynos5250-dw-mshc", EXYNOS5_PA_DWMCI3,
-				"dw_mmc.3", NULL),
-	OF_DEV_AUXDATA("samsung,exynos4210-spi", EXYNOS5_PA_SPI0,
-				"exynos4210-spi.0", NULL),
-	OF_DEV_AUXDATA("samsung,exynos4210-spi", EXYNOS5_PA_SPI1,
-				"exynos4210-spi.1", NULL),
-	OF_DEV_AUXDATA("samsung,exynos4210-spi", EXYNOS5_PA_SPI2,
-				"exynos4210-spi.2", NULL),
-	OF_DEV_AUXDATA("samsung,exynos5-sata-ahci", 0x122F0000,
-				"exynos5-sata", NULL),
-	OF_DEV_AUXDATA("samsung,exynos5-sata-phy", 0x12170000,
-				"exynos5-sata-phy", NULL),
-	OF_DEV_AUXDATA("samsung,exynos5-sata-phy-i2c", 0x121D0000,
-				"exynos5-sata-phy-i2c", NULL),
-	OF_DEV_AUXDATA("arm,pl330", EXYNOS5_PA_PDMA0, "dma-pl330.0", NULL),
-	OF_DEV_AUXDATA("arm,pl330", EXYNOS5_PA_PDMA1, "dma-pl330.1", NULL),
-	OF_DEV_AUXDATA("arm,pl330", EXYNOS5_PA_MDMA1, "dma-pl330.2", NULL),
-	OF_DEV_AUXDATA("samsung,exynos5-gsc", EXYNOS5_PA_GSC0,
-				"exynos-gsc.0", NULL),
-	OF_DEV_AUXDATA("samsung,exynos5-gsc", EXYNOS5_PA_GSC1,
-				"exynos-gsc.1", NULL),
-	OF_DEV_AUXDATA("samsung,exynos5-gsc", EXYNOS5_PA_GSC2,
-				"exynos-gsc.2", NULL),
-	OF_DEV_AUXDATA("samsung,exynos5-gsc", EXYNOS5_PA_GSC3,
-				"exynos-gsc.3", NULL),
-	OF_DEV_AUXDATA("samsung,exynos5-hdmi", 0x14530000,
-				"exynos5-hdmi", NULL),
-	OF_DEV_AUXDATA("samsung,exynos5-mixer", 0x14450000,
-				"exynos5-mixer", NULL),
-	OF_DEV_AUXDATA("samsung,mfc-v6", 0x11000000, "s5p-mfc-v6", NULL),
-	OF_DEV_AUXDATA("samsung,exynos5250-tmu", 0x10060000,
-				"exynos-tmu", NULL),
-	OF_DEV_AUXDATA("samsung,i2s-v5", 0x03830000,
-				"samsung-i2s.0", NULL),
-	OF_DEV_AUXDATA("samsung,i2s-v5", 0x12D60000,
-				"samsung-i2s.1", NULL),
-	OF_DEV_AUXDATA("samsung,i2s-v5", 0x12D70000,
-				"samsung-i2s.2", NULL),
-	OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x11210000,
-			"exynos-sysmmu.0", "mfc"), /* MFC_L */
-	OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x11200000,
-			"exynos-sysmmu.1", "mfc"), /* MFC_R */
-	OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x14650000,
-			"exynos-sysmmu.2", NULL), /* TV */
-	OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x11F20000,
-			"exynos-sysmmu.3", "jpeg"), /* JPEG */
-	OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x11D40000,
-			"exynos-sysmmu.4", NULL), /* ROTATOR */
-	OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x13E80000,
-			"exynos-sysmmu.5", "gscl"), /* GSCL0 */
-	OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x13E90000,
-			"exynos-sysmmu.6", "gscl"), /* GSCL1 */
-	OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x13EA0000,
-			"exynos-sysmmu.7", "gscl"), /* GSCL2 */
-	OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x13EB0000,
-			"exynos-sysmmu.8", "gscl"), /* GSCL3 */
-	OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x13260000,
-			"exynos-sysmmu.9", NULL), /* FIMC-IS0 */
-	OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x132C0000,
-			"exynos-sysmmu.10", NULL), /* FIMC-IS1 */
-	OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x14640000,
-			"exynos-sysmmu.11", NULL), /* FIMD1 */
-	OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x13C40000,
-			"exynos-sysmmu.12", NULL), /* FIMC-LITE0 */
-	OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x13C50000,
-			"exynos-sysmmu.13", NULL), /* FIMC-LITE1 */
-	OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x10A60000,
-			"exynos-sysmmu.14", NULL), /* G2D */
-	{},
-};
-
-static const struct of_dev_auxdata exynos5440_auxdata_lookup[] __initconst = {
-	OF_DEV_AUXDATA("samsung,exynos4210-uart", EXYNOS5440_PA_UART0,
-				"exynos4210-uart.0", NULL),
-	{},
-};
-
 static void __init exynos5_dt_map_io(void)
 {
-	unsigned long root = of_get_flat_dt_root();
-
 	exynos_init_io(NULL, 0);
-
-	if (of_flat_dt_is_compatible(root, "samsung,exynos5250"))
-		s3c24xx_init_clocks(24000000);
 }
 
 static void __init exynos5_dt_machine_init(void)
@@ -182,12 +52,7 @@ static void __init exynos5_dt_machine_init(void)
 		}
 	}
 
-	if (of_machine_is_compatible("samsung,exynos5250"))
-		of_platform_populate(NULL, of_default_bus_match_table,
-				     exynos5250_auxdata_lookup, NULL);
-	else if (of_machine_is_compatible("samsung,exynos5440"))
-		of_platform_populate(NULL, of_default_bus_match_table,
-				     exynos5440_auxdata_lookup, NULL);
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
 static char const *exynos5_dt_compat[] __initdata = {
@@ -216,7 +81,7 @@ DT_MACHINE_START(EXYNOS5_DT, "SAMSUNG EXYNOS5 (Flattened Device Tree)")
 	.map_io		= exynos5_dt_map_io,
 	.init_machine	= exynos5_dt_machine_init,
 	.init_late	= exynos_init_late,
-	.init_time	= exynos4_timer_init,
+	.init_time	= exynos_init_time,
 	.dt_compat	= exynos5_dt_compat,
 	.restart        = exynos5_restart,
 	.reserve	= exynos5_reserve,
diff --git a/arch/arm/mach-exynos/mach-nuri.c b/arch/arm/mach-exynos/mach-nuri.c
index 1ea7973..b84a132 100644
--- a/arch/arm/mach-exynos/mach-nuri.c
+++ b/arch/arm/mach-exynos/mach-nuri.c
@@ -1251,7 +1251,7 @@ static void __init nuri_camera_init(void)
 	}
 
 	m5mols_board_info.irq = s5p_register_gpio_interrupt(GPIO_CAM_8M_ISP_INT);
-	if (!IS_ERR_VALUE(m5mols_board_info.irq))
+	if (m5mols_board_info.irq >= 0)
 		s3c_gpio_cfgpin(GPIO_CAM_8M_ISP_INT, S3C_GPIO_SFN(0xF));
 	else
 		pr_err("%s: Failed to configure 8M_ISP_INT GPIO\n", __func__);
@@ -1330,8 +1330,9 @@ static struct platform_device *nuri_devices[] __initdata = {
 static void __init nuri_map_io(void)
 {
 	exynos_init_io(NULL, 0);
-	s3c24xx_init_clocks(clk_xusbxti.rate);
 	s3c24xx_init_uarts(nuri_uartcfgs, ARRAY_SIZE(nuri_uartcfgs));
+	xxti_f = 0;
+	xusbxti_f = 24000000;
 }
 
 static void __init nuri_reserve(void)
@@ -1380,7 +1381,7 @@ MACHINE_START(NURI, "NURI")
 	.map_io		= nuri_map_io,
 	.init_machine	= nuri_machine_init,
 	.init_late	= exynos_init_late,
-	.init_time	= exynos4_timer_init,
+	.init_time	= exynos_init_time,
 	.reserve        = &nuri_reserve,
 	.restart	= exynos4_restart,
 MACHINE_END
diff --git a/arch/arm/mach-exynos/mach-origen.c b/arch/arm/mach-exynos/mach-origen.c
index 579d2d1..a9aa5c0 100644
--- a/arch/arm/mach-exynos/mach-origen.c
+++ b/arch/arm/mach-exynos/mach-origen.c
@@ -754,8 +754,9 @@ static void s5p_tv_setup(void)
 static void __init origen_map_io(void)
 {
 	exynos_init_io(NULL, 0);
-	s3c24xx_init_clocks(clk_xusbxti.rate);
 	s3c24xx_init_uarts(origen_uartcfgs, ARRAY_SIZE(origen_uartcfgs));
+	xxti_f = 0;
+	xusbxti_f = 24000000;
 }
 
 static void __init origen_power_init(void)
@@ -815,7 +816,7 @@ MACHINE_START(ORIGEN, "ORIGEN")
 	.map_io		= origen_map_io,
 	.init_machine	= origen_machine_init,
 	.init_late	= exynos_init_late,
-	.init_time	= exynos4_timer_init,
+	.init_time	= exynos_init_time,
 	.reserve	= &origen_reserve,
 	.restart	= exynos4_restart,
 MACHINE_END
diff --git a/arch/arm/mach-exynos/mach-smdk4x12.c b/arch/arm/mach-exynos/mach-smdk4x12.c
index fe61496..184faa3 100644
--- a/arch/arm/mach-exynos/mach-smdk4x12.c
+++ b/arch/arm/mach-exynos/mach-smdk4x12.c
@@ -322,7 +322,6 @@ static struct platform_device *smdk4x12_devices[] __initdata = {
 static void __init smdk4x12_map_io(void)
 {
 	exynos_init_io(NULL, 0);
-	s3c24xx_init_clocks(clk_xusbxti.rate);
 	s3c24xx_init_uarts(smdk4x12_uartcfgs, ARRAY_SIZE(smdk4x12_uartcfgs));
 }
 
@@ -376,7 +375,7 @@ MACHINE_START(SMDK4212, "SMDK4212")
 	.init_irq	= exynos4_init_irq,
 	.map_io		= smdk4x12_map_io,
 	.init_machine	= smdk4x12_machine_init,
-	.init_time	= exynos4_timer_init,
+	.init_time	= exynos_init_time,
 	.restart	= exynos4_restart,
 	.reserve	= &smdk4x12_reserve,
 MACHINE_END
@@ -390,7 +389,7 @@ MACHINE_START(SMDK4412, "SMDK4412")
 	.map_io		= smdk4x12_map_io,
 	.init_machine	= smdk4x12_machine_init,
 	.init_late	= exynos_init_late,
-	.init_time	= exynos4_timer_init,
+	.init_time	= exynos_init_time,
 	.restart	= exynos4_restart,
 	.reserve	= &smdk4x12_reserve,
 MACHINE_END
diff --git a/arch/arm/mach-exynos/mach-smdkv310.c b/arch/arm/mach-exynos/mach-smdkv310.c
index d716729..75eca7d 100644
--- a/arch/arm/mach-exynos/mach-smdkv310.c
+++ b/arch/arm/mach-exynos/mach-smdkv310.c
@@ -371,8 +371,9 @@ static void s5p_tv_setup(void)
 static void __init smdkv310_map_io(void)
 {
 	exynos_init_io(NULL, 0);
-	s3c24xx_init_clocks(clk_xusbxti.rate);
 	s3c24xx_init_uarts(smdkv310_uartcfgs, ARRAY_SIZE(smdkv310_uartcfgs));
+	xxti_f = 12000000;
+	xusbxti_f = 24000000;
 }
 
 static void __init smdkv310_reserve(void)
@@ -423,7 +424,7 @@ MACHINE_START(SMDKV310, "SMDKV310")
 	.init_irq	= exynos4_init_irq,
 	.map_io		= smdkv310_map_io,
 	.init_machine	= smdkv310_machine_init,
-	.init_time	= exynos4_timer_init,
+	.init_time	= exynos_init_time,
 	.reserve	= &smdkv310_reserve,
 	.restart	= exynos4_restart,
 MACHINE_END
@@ -436,7 +437,7 @@ MACHINE_START(SMDKC210, "SMDKC210")
 	.map_io		= smdkv310_map_io,
 	.init_machine	= smdkv310_machine_init,
 	.init_late	= exynos_init_late,
-	.init_time	= exynos4_timer_init,
+	.init_time	= exynos_init_time,
 	.reserve	= &smdkv310_reserve,
 	.restart	= exynos4_restart,
 MACHINE_END
diff --git a/arch/arm/mach-exynos/mach-universal_c210.c b/arch/arm/mach-exynos/mach-universal_c210.c
index 497fcb7..72f08fd 100644
--- a/arch/arm/mach-exynos/mach-universal_c210.c
+++ b/arch/arm/mach-exynos/mach-universal_c210.c
@@ -41,7 +41,7 @@
 #include <plat/mfc.h>
 #include <plat/sdhci.h>
 #include <plat/fimc-core.h>
-#include <plat/s5p-time.h>
+#include <plat/samsung-time.h>
 #include <plat/camport.h>
 
 #include <mach/map.h>
@@ -1092,9 +1092,10 @@ static struct platform_device *universal_devices[] __initdata = {
 static void __init universal_map_io(void)
 {
 	exynos_init_io(NULL, 0);
-	s3c24xx_init_clocks(clk_xusbxti.rate);
 	s3c24xx_init_uarts(universal_uartcfgs, ARRAY_SIZE(universal_uartcfgs));
-	s5p_set_timer_source(S5P_PWM2, S5P_PWM4);
+	samsung_set_timer_source(SAMSUNG_PWM2, SAMSUNG_PWM4);
+	xxti_f = 0;
+	xusbxti_f = 24000000;
 }
 
 static void s5p_tv_setup(void)
@@ -1152,7 +1153,7 @@ MACHINE_START(UNIVERSAL_C210, "UNIVERSAL_C210")
 	.map_io		= universal_map_io,
 	.init_machine	= universal_machine_init,
 	.init_late	= exynos_init_late,
-	.init_time	= s5p_timer_init,
+	.init_time	= samsung_timer_init,
 	.reserve        = &universal_reserve,
 	.restart	= exynos4_restart,
 MACHINE_END
diff --git a/arch/arm/mach-exynos/mct.c b/arch/arm/mach-exynos/mct.c
deleted file mode 100644
index c9d6650..0000000
--- a/arch/arm/mach-exynos/mct.c
+++ /dev/null
@@ -1,485 +0,0 @@
-/* linux/arch/arm/mach-exynos4/mct.c
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * EXYNOS4 MCT(Multi-Core Timer) 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/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 <linux/delay.h>
-#include <linux/percpu.h>
-#include <linux/of.h>
-
-#include <asm/arch_timer.h>
-#include <asm/localtimer.h>
-
-#include <plat/cpu.h>
-
-#include <mach/map.h>
-#include <mach/irqs.h>
-#include <mach/regs-mct.h>
-#include <asm/mach/time.h>
-
-#define TICK_BASE_CNT	1
-
-enum {
-	MCT_INT_SPI,
-	MCT_INT_PPI
-};
-
-static unsigned long clk_rate;
-static unsigned int mct_int_type;
-
-struct mct_clock_event_device {
-	struct clock_event_device *evt;
-	void __iomem *base;
-	char name[10];
-};
-
-static void exynos4_mct_write(unsigned int value, void *addr)
-{
-	void __iomem *stat_addr;
-	u32 mask;
-	u32 i;
-
-	__raw_writel(value, addr);
-
-	if (likely(addr >= EXYNOS4_MCT_L_BASE(0))) {
-		u32 base = (u32) addr & EXYNOS4_MCT_L_MASK;
-		switch ((u32) addr & ~EXYNOS4_MCT_L_MASK) {
-		case (u32) MCT_L_TCON_OFFSET:
-			stat_addr = (void __iomem *) base + MCT_L_WSTAT_OFFSET;
-			mask = 1 << 3;		/* L_TCON write status */
-			break;
-		case (u32) MCT_L_ICNTB_OFFSET:
-			stat_addr = (void __iomem *) base + MCT_L_WSTAT_OFFSET;
-			mask = 1 << 1;		/* L_ICNTB write status */
-			break;
-		case (u32) MCT_L_TCNTB_OFFSET:
-			stat_addr = (void __iomem *) base + MCT_L_WSTAT_OFFSET;
-			mask = 1 << 0;		/* L_TCNTB write status */
-			break;
-		default:
-			return;
-		}
-	} else {
-		switch ((u32) addr) {
-		case (u32) EXYNOS4_MCT_G_TCON:
-			stat_addr = EXYNOS4_MCT_G_WSTAT;
-			mask = 1 << 16;		/* G_TCON write status */
-			break;
-		case (u32) EXYNOS4_MCT_G_COMP0_L:
-			stat_addr = EXYNOS4_MCT_G_WSTAT;
-			mask = 1 << 0;		/* G_COMP0_L write status */
-			break;
-		case (u32) EXYNOS4_MCT_G_COMP0_U:
-			stat_addr = EXYNOS4_MCT_G_WSTAT;
-			mask = 1 << 1;		/* G_COMP0_U write status */
-			break;
-		case (u32) EXYNOS4_MCT_G_COMP0_ADD_INCR:
-			stat_addr = EXYNOS4_MCT_G_WSTAT;
-			mask = 1 << 2;		/* G_COMP0_ADD_INCR w status */
-			break;
-		case (u32) EXYNOS4_MCT_G_CNT_L:
-			stat_addr = EXYNOS4_MCT_G_CNT_WSTAT;
-			mask = 1 << 0;		/* G_CNT_L write status */
-			break;
-		case (u32) EXYNOS4_MCT_G_CNT_U:
-			stat_addr = EXYNOS4_MCT_G_CNT_WSTAT;
-			mask = 1 << 1;		/* G_CNT_U write status */
-			break;
-		default:
-			return;
-		}
-	}
-
-	/* Wait maximum 1 ms until written values are applied */
-	for (i = 0; i < loops_per_jiffy / 1000 * HZ; i++)
-		if (__raw_readl(stat_addr) & mask) {
-			__raw_writel(mask, stat_addr);
-			return;
-		}
-
-	panic("MCT hangs after writing %d (addr:0x%08x)\n", value, (u32)addr);
-}
-
-/* Clocksource handling */
-static void exynos4_mct_frc_start(u32 hi, u32 lo)
-{
-	u32 reg;
-
-	exynos4_mct_write(lo, EXYNOS4_MCT_G_CNT_L);
-	exynos4_mct_write(hi, EXYNOS4_MCT_G_CNT_U);
-
-	reg = __raw_readl(EXYNOS4_MCT_G_TCON);
-	reg |= MCT_G_TCON_START;
-	exynos4_mct_write(reg, EXYNOS4_MCT_G_TCON);
-}
-
-static cycle_t exynos4_frc_read(struct clocksource *cs)
-{
-	unsigned int lo, hi;
-	u32 hi2 = __raw_readl(EXYNOS4_MCT_G_CNT_U);
-
-	do {
-		hi = hi2;
-		lo = __raw_readl(EXYNOS4_MCT_G_CNT_L);
-		hi2 = __raw_readl(EXYNOS4_MCT_G_CNT_U);
-	} while (hi != hi2);
-
-	return ((cycle_t)hi << 32) | lo;
-}
-
-static void exynos4_frc_resume(struct clocksource *cs)
-{
-	exynos4_mct_frc_start(0, 0);
-}
-
-struct clocksource mct_frc = {
-	.name		= "mct-frc",
-	.rating		= 400,
-	.read		= exynos4_frc_read,
-	.mask		= CLOCKSOURCE_MASK(64),
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
-	.resume		= exynos4_frc_resume,
-};
-
-static void __init exynos4_clocksource_init(void)
-{
-	exynos4_mct_frc_start(0, 0);
-
-	if (clocksource_register_hz(&mct_frc, clk_rate))
-		panic("%s: can't register clocksource\n", mct_frc.name);
-}
-
-static void exynos4_mct_comp0_stop(void)
-{
-	unsigned int tcon;
-
-	tcon = __raw_readl(EXYNOS4_MCT_G_TCON);
-	tcon &= ~(MCT_G_TCON_COMP0_ENABLE | MCT_G_TCON_COMP0_AUTO_INC);
-
-	exynos4_mct_write(tcon, EXYNOS4_MCT_G_TCON);
-	exynos4_mct_write(0, EXYNOS4_MCT_G_INT_ENB);
-}
-
-static void exynos4_mct_comp0_start(enum clock_event_mode mode,
-				    unsigned long cycles)
-{
-	unsigned int tcon;
-	cycle_t comp_cycle;
-
-	tcon = __raw_readl(EXYNOS4_MCT_G_TCON);
-
-	if (mode == CLOCK_EVT_MODE_PERIODIC) {
-		tcon |= MCT_G_TCON_COMP0_AUTO_INC;
-		exynos4_mct_write(cycles, EXYNOS4_MCT_G_COMP0_ADD_INCR);
-	}
-
-	comp_cycle = exynos4_frc_read(&mct_frc) + cycles;
-	exynos4_mct_write((u32)comp_cycle, EXYNOS4_MCT_G_COMP0_L);
-	exynos4_mct_write((u32)(comp_cycle >> 32), EXYNOS4_MCT_G_COMP0_U);
-
-	exynos4_mct_write(0x1, EXYNOS4_MCT_G_INT_ENB);
-
-	tcon |= MCT_G_TCON_COMP0_ENABLE;
-	exynos4_mct_write(tcon , EXYNOS4_MCT_G_TCON);
-}
-
-static int exynos4_comp_set_next_event(unsigned long cycles,
-				       struct clock_event_device *evt)
-{
-	exynos4_mct_comp0_start(evt->mode, cycles);
-
-	return 0;
-}
-
-static void exynos4_comp_set_mode(enum clock_event_mode mode,
-				  struct clock_event_device *evt)
-{
-	unsigned long cycles_per_jiffy;
-	exynos4_mct_comp0_stop();
-
-	switch (mode) {
-	case CLOCK_EVT_MODE_PERIODIC:
-		cycles_per_jiffy =
-			(((unsigned long long) NSEC_PER_SEC / HZ * evt->mult) >> evt->shift);
-		exynos4_mct_comp0_start(mode, cycles_per_jiffy);
-		break;
-
-	case CLOCK_EVT_MODE_ONESHOT:
-	case CLOCK_EVT_MODE_UNUSED:
-	case CLOCK_EVT_MODE_SHUTDOWN:
-	case CLOCK_EVT_MODE_RESUME:
-		break;
-	}
-}
-
-static struct clock_event_device mct_comp_device = {
-	.name		= "mct-comp",
-	.features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
-	.rating		= 250,
-	.set_next_event	= exynos4_comp_set_next_event,
-	.set_mode	= exynos4_comp_set_mode,
-};
-
-static irqreturn_t exynos4_mct_comp_isr(int irq, void *dev_id)
-{
-	struct clock_event_device *evt = dev_id;
-
-	exynos4_mct_write(0x1, EXYNOS4_MCT_G_INT_CSTAT);
-
-	evt->event_handler(evt);
-
-	return IRQ_HANDLED;
-}
-
-static struct irqaction mct_comp_event_irq = {
-	.name		= "mct_comp_irq",
-	.flags		= IRQF_TIMER | IRQF_IRQPOLL,
-	.handler	= exynos4_mct_comp_isr,
-	.dev_id		= &mct_comp_device,
-};
-
-static void exynos4_clockevent_init(void)
-{
-	mct_comp_device.cpumask = cpumask_of(0);
-	clockevents_config_and_register(&mct_comp_device, clk_rate,
-					0xf, 0xffffffff);
-
-	if (soc_is_exynos5250())
-		setup_irq(EXYNOS5_IRQ_MCT_G0, &mct_comp_event_irq);
-	else
-		setup_irq(EXYNOS4_IRQ_MCT_G0, &mct_comp_event_irq);
-}
-
-#ifdef CONFIG_LOCAL_TIMERS
-
-static DEFINE_PER_CPU(struct mct_clock_event_device, percpu_mct_tick);
-
-/* Clock event handling */
-static void exynos4_mct_tick_stop(struct mct_clock_event_device *mevt)
-{
-	unsigned long tmp;
-	unsigned long mask = MCT_L_TCON_INT_START | MCT_L_TCON_TIMER_START;
-	void __iomem *addr = mevt->base + MCT_L_TCON_OFFSET;
-
-	tmp = __raw_readl(addr);
-	if (tmp & mask) {
-		tmp &= ~mask;
-		exynos4_mct_write(tmp, addr);
-	}
-}
-
-static void exynos4_mct_tick_start(unsigned long cycles,
-				   struct mct_clock_event_device *mevt)
-{
-	unsigned long tmp;
-
-	exynos4_mct_tick_stop(mevt);
-
-	tmp = (1 << 31) | cycles;	/* MCT_L_UPDATE_ICNTB */
-
-	/* update interrupt count buffer */
-	exynos4_mct_write(tmp, mevt->base + MCT_L_ICNTB_OFFSET);
-
-	/* enable MCT tick interrupt */
-	exynos4_mct_write(0x1, mevt->base + MCT_L_INT_ENB_OFFSET);
-
-	tmp = __raw_readl(mevt->base + MCT_L_TCON_OFFSET);
-	tmp |= MCT_L_TCON_INT_START | MCT_L_TCON_TIMER_START |
-	       MCT_L_TCON_INTERVAL_MODE;
-	exynos4_mct_write(tmp, mevt->base + MCT_L_TCON_OFFSET);
-}
-
-static int exynos4_tick_set_next_event(unsigned long cycles,
-				       struct clock_event_device *evt)
-{
-	struct mct_clock_event_device *mevt = this_cpu_ptr(&percpu_mct_tick);
-
-	exynos4_mct_tick_start(cycles, mevt);
-
-	return 0;
-}
-
-static inline void exynos4_tick_set_mode(enum clock_event_mode mode,
-					 struct clock_event_device *evt)
-{
-	struct mct_clock_event_device *mevt = this_cpu_ptr(&percpu_mct_tick);
-	unsigned long cycles_per_jiffy;
-
-	exynos4_mct_tick_stop(mevt);
-
-	switch (mode) {
-	case CLOCK_EVT_MODE_PERIODIC:
-		cycles_per_jiffy =
-			(((unsigned long long) NSEC_PER_SEC / HZ * evt->mult) >> evt->shift);
-		exynos4_mct_tick_start(cycles_per_jiffy, mevt);
-		break;
-
-	case CLOCK_EVT_MODE_ONESHOT:
-	case CLOCK_EVT_MODE_UNUSED:
-	case CLOCK_EVT_MODE_SHUTDOWN:
-	case CLOCK_EVT_MODE_RESUME:
-		break;
-	}
-}
-
-static int exynos4_mct_tick_clear(struct mct_clock_event_device *mevt)
-{
-	struct clock_event_device *evt = mevt->evt;
-
-	/*
-	 * This is for supporting oneshot mode.
-	 * Mct would generate interrupt periodically
-	 * without explicit stopping.
-	 */
-	if (evt->mode != CLOCK_EVT_MODE_PERIODIC)
-		exynos4_mct_tick_stop(mevt);
-
-	/* Clear the MCT tick interrupt */
-	if (__raw_readl(mevt->base + MCT_L_INT_CSTAT_OFFSET) & 1) {
-		exynos4_mct_write(0x1, mevt->base + MCT_L_INT_CSTAT_OFFSET);
-		return 1;
-	} else {
-		return 0;
-	}
-}
-
-static irqreturn_t exynos4_mct_tick_isr(int irq, void *dev_id)
-{
-	struct mct_clock_event_device *mevt = dev_id;
-	struct clock_event_device *evt = mevt->evt;
-
-	exynos4_mct_tick_clear(mevt);
-
-	evt->event_handler(evt);
-
-	return IRQ_HANDLED;
-}
-
-static struct irqaction mct_tick0_event_irq = {
-	.name		= "mct_tick0_irq",
-	.flags		= IRQF_TIMER | IRQF_NOBALANCING,
-	.handler	= exynos4_mct_tick_isr,
-};
-
-static struct irqaction mct_tick1_event_irq = {
-	.name		= "mct_tick1_irq",
-	.flags		= IRQF_TIMER | IRQF_NOBALANCING,
-	.handler	= exynos4_mct_tick_isr,
-};
-
-static int __cpuinit exynos4_local_timer_setup(struct clock_event_device *evt)
-{
-	struct mct_clock_event_device *mevt;
-	unsigned int cpu = smp_processor_id();
-	int mct_lx_irq;
-
-	mevt = this_cpu_ptr(&percpu_mct_tick);
-	mevt->evt = evt;
-
-	mevt->base = EXYNOS4_MCT_L_BASE(cpu);
-	sprintf(mevt->name, "mct_tick%d", cpu);
-
-	evt->name = mevt->name;
-	evt->cpumask = cpumask_of(cpu);
-	evt->set_next_event = exynos4_tick_set_next_event;
-	evt->set_mode = exynos4_tick_set_mode;
-	evt->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
-	evt->rating = 450;
-	clockevents_config_and_register(evt, clk_rate / (TICK_BASE_CNT + 1),
-					0xf, 0x7fffffff);
-
-	exynos4_mct_write(TICK_BASE_CNT, mevt->base + MCT_L_TCNTB_OFFSET);
-
-	if (mct_int_type == MCT_INT_SPI) {
-		if (cpu == 0) {
-			mct_lx_irq = soc_is_exynos4210() ? EXYNOS4_IRQ_MCT_L0 :
-						EXYNOS5_IRQ_MCT_L0;
-			mct_tick0_event_irq.dev_id = mevt;
-			evt->irq = mct_lx_irq;
-			setup_irq(mct_lx_irq, &mct_tick0_event_irq);
-		} else {
-			mct_lx_irq = soc_is_exynos4210() ? EXYNOS4_IRQ_MCT_L1 :
-						EXYNOS5_IRQ_MCT_L1;
-			mct_tick1_event_irq.dev_id = mevt;
-			evt->irq = mct_lx_irq;
-			setup_irq(mct_lx_irq, &mct_tick1_event_irq);
-			irq_set_affinity(mct_lx_irq, cpumask_of(1));
-		}
-	} else {
-		enable_percpu_irq(EXYNOS_IRQ_MCT_LOCALTIMER, 0);
-	}
-
-	return 0;
-}
-
-static void exynos4_local_timer_stop(struct clock_event_device *evt)
-{
-	unsigned int cpu = smp_processor_id();
-	evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt);
-	if (mct_int_type == MCT_INT_SPI)
-		if (cpu == 0)
-			remove_irq(evt->irq, &mct_tick0_event_irq);
-		else
-			remove_irq(evt->irq, &mct_tick1_event_irq);
-	else
-		disable_percpu_irq(EXYNOS_IRQ_MCT_LOCALTIMER);
-}
-
-static struct local_timer_ops exynos4_mct_tick_ops __cpuinitdata = {
-	.setup	= exynos4_local_timer_setup,
-	.stop	= exynos4_local_timer_stop,
-};
-#endif /* CONFIG_LOCAL_TIMERS */
-
-static void __init exynos4_timer_resources(void)
-{
-	struct clk *mct_clk;
-	mct_clk = clk_get(NULL, "xtal");
-
-	clk_rate = clk_get_rate(mct_clk);
-
-#ifdef CONFIG_LOCAL_TIMERS
-	if (mct_int_type == MCT_INT_PPI) {
-		int err;
-
-		err = request_percpu_irq(EXYNOS_IRQ_MCT_LOCALTIMER,
-					 exynos4_mct_tick_isr, "MCT",
-					 &percpu_mct_tick);
-		WARN(err, "MCT: can't request IRQ %d (%d)\n",
-		     EXYNOS_IRQ_MCT_LOCALTIMER, err);
-	}
-
-	local_timer_register(&exynos4_mct_tick_ops);
-#endif /* CONFIG_LOCAL_TIMERS */
-}
-
-void __init exynos4_timer_init(void)
-{
-	if (soc_is_exynos5440()) {
-		arch_timer_of_register();
-		return;
-	}
-
-	if ((soc_is_exynos4210()) || (soc_is_exynos5250()))
-		mct_int_type = MCT_INT_SPI;
-	else
-		mct_int_type = MCT_INT_PPI;
-
-	exynos4_timer_resources();
-	exynos4_clocksource_init();
-	exynos4_clockevent_init();
-}
diff --git a/arch/arm/mach-exynos/platsmp.c b/arch/arm/mach-exynos/platsmp.c
index 60f7c5b..a0e8ff7 100644
--- a/arch/arm/mach-exynos/platsmp.c
+++ b/arch/arm/mach-exynos/platsmp.c
@@ -20,11 +20,11 @@
 #include <linux/jiffies.h>
 #include <linux/smp.h>
 #include <linux/io.h>
-#include <linux/irqchip/arm-gic.h>
 
 #include <asm/cacheflush.h>
 #include <asm/smp_plat.h>
 #include <asm/smp_scu.h>
+#include <asm/firmware.h>
 
 #include <mach/hardware.h>
 #include <mach/regs-clock.h>
@@ -76,13 +76,6 @@ static DEFINE_SPINLOCK(boot_lock);
 static void __cpuinit exynos_secondary_init(unsigned int cpu)
 {
 	/*
-	 * if any interrupts are already enabled for the primary
-	 * core (e.g. timer irq), then they will not have been enabled
-	 * for us: do so
-	 */
-	gic_secondary_init(0);
-
-	/*
 	 * let the primary processor know we're out of the
 	 * pen, then head off into the C entry point
 	 */
@@ -145,10 +138,21 @@ static int __cpuinit exynos_boot_secondary(unsigned int cpu, struct task_struct
 
 	timeout = jiffies + (1 * HZ);
 	while (time_before(jiffies, timeout)) {
+		unsigned long boot_addr;
+
 		smp_rmb();
 
-		__raw_writel(virt_to_phys(exynos4_secondary_startup),
-							cpu_boot_reg(phys_cpu));
+		boot_addr = virt_to_phys(exynos4_secondary_startup);
+
+		/*
+		 * Try to set boot address using firmware first
+		 * and fall back to boot register if it fails.
+		 */
+		if (call_firmware_op(set_cpu_boot_addr, phys_cpu, boot_addr))
+			__raw_writel(boot_addr, cpu_boot_reg(phys_cpu));
+
+		call_firmware_op(cpu_boot, phys_cpu);
+
 		arch_send_wakeup_ipi_mask(cpumask_of(cpu));
 
 		if (pen_release == -1)
@@ -204,10 +208,20 @@ static void __init exynos_smp_prepare_cpus(unsigned int max_cpus)
 	 * system-wide flags register. The boot monitor waits
 	 * until it receives a soft interrupt, and then the
 	 * secondary CPU branches to this address.
+	 *
+	 * Try using firmware operation first and fall back to
+	 * boot register if it fails.
 	 */
-	for (i = 1; i < max_cpus; ++i)
-		__raw_writel(virt_to_phys(exynos4_secondary_startup),
-					cpu_boot_reg(cpu_logical_map(i)));
+	for (i = 1; i < max_cpus; ++i) {
+		unsigned long phys_cpu;
+		unsigned long boot_addr;
+
+		phys_cpu = cpu_logical_map(i);
+		boot_addr = virt_to_phys(exynos4_secondary_startup);
+
+		if (call_firmware_op(set_cpu_boot_addr, phys_cpu, boot_addr))
+			__raw_writel(boot_addr, cpu_boot_reg(phys_cpu));
+	}
 }
 
 struct smp_operations exynos_smp_ops __initdata = {
diff --git a/arch/arm/mach-exynos/smc.h b/arch/arm/mach-exynos/smc.h
new file mode 100644
index 0000000..13a1dc8
--- /dev/null
+++ b/arch/arm/mach-exynos/smc.h
@@ -0,0 +1,31 @@
+/*
+ *  Copyright (c) 2012 Samsung Electronics.
+ *
+ * EXYNOS - SMC Call
+ *
+ * This program is free software; you can 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_EXYNOS_SMC_H
+#define __ASM_ARCH_EXYNOS_SMC_H
+
+#define SMC_CMD_INIT		(-1)
+#define SMC_CMD_INFO		(-2)
+/* For Power Management */
+#define SMC_CMD_SLEEP		(-3)
+#define SMC_CMD_CPU1BOOT	(-4)
+#define SMC_CMD_CPU0AFTR	(-5)
+/* For CP15 Access */
+#define SMC_CMD_C15RESUME	(-11)
+/* For L2 Cache Access */
+#define SMC_CMD_L2X0CTRL	(-21)
+#define SMC_CMD_L2X0SETUP1	(-22)
+#define SMC_CMD_L2X0SETUP2	(-23)
+#define SMC_CMD_L2X0INVALL	(-24)
+#define SMC_CMD_L2X0DEBUG	(-25)
+
+extern void exynos_smc(u32 cmd, u32 arg1, u32 arg2, u32 arg3);
+
+#endif
diff --git a/arch/arm/mach-gemini/Makefile b/arch/arm/mach-gemini/Makefile
index 7355c0b..7963a77 100644
--- a/arch/arm/mach-gemini/Makefile
+++ b/arch/arm/mach-gemini/Makefile
@@ -4,7 +4,7 @@
 
 # Object file lists.
 
-obj-y			:= irq.o mm.o time.o devices.o gpio.o idle.o
+obj-y			:= irq.o mm.o time.o devices.o gpio.o idle.o reset.o
 
 # Board-specific support
 obj-$(CONFIG_MACH_NAS4220B)	+= board-nas4220b.o
diff --git a/arch/arm/mach-gemini/board-nas4220b.c b/arch/arm/mach-gemini/board-nas4220b.c
index 08bd650..ca8a25b 100644
--- a/arch/arm/mach-gemini/board-nas4220b.c
+++ b/arch/arm/mach-gemini/board-nas4220b.c
@@ -103,4 +103,5 @@ MACHINE_START(NAS4220B, "Raidsonic NAS IB-4220-B")
 	.init_irq	= gemini_init_irq,
 	.init_time	= gemini_timer_init,
 	.init_machine	= ib4220b_init,
+	.restart	= gemini_restart,
 MACHINE_END
diff --git a/arch/arm/mach-gemini/board-rut1xx.c b/arch/arm/mach-gemini/board-rut1xx.c
index fa0a363..7a675f8 100644
--- a/arch/arm/mach-gemini/board-rut1xx.c
+++ b/arch/arm/mach-gemini/board-rut1xx.c
@@ -14,6 +14,7 @@
 #include <linux/leds.h>
 #include <linux/input.h>
 #include <linux/gpio_keys.h>
+#include <linux/sizes.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -87,4 +88,5 @@ MACHINE_START(RUT100, "Teltonika RUT100")
 	.init_irq	= gemini_init_irq,
 	.init_time	= gemini_timer_init,
 	.init_machine	= rut1xx_init,
+	.restart	= gemini_restart,
 MACHINE_END
diff --git a/arch/arm/mach-gemini/board-wbd111.c b/arch/arm/mach-gemini/board-wbd111.c
index 3321cd6..418188c 100644
--- a/arch/arm/mach-gemini/board-wbd111.c
+++ b/arch/arm/mach-gemini/board-wbd111.c
@@ -130,4 +130,5 @@ MACHINE_START(WBD111, "Wiliboard WBD-111")
 	.init_irq	= gemini_init_irq,
 	.init_time	= gemini_timer_init,
 	.init_machine	= wbd111_init,
+	.restart	= gemini_restart,
 MACHINE_END
diff --git a/arch/arm/mach-gemini/board-wbd222.c b/arch/arm/mach-gemini/board-wbd222.c
index fe33c82..266b265 100644
--- a/arch/arm/mach-gemini/board-wbd222.c
+++ b/arch/arm/mach-gemini/board-wbd222.c
@@ -130,4 +130,5 @@ MACHINE_START(WBD222, "Wiliboard WBD-222")
 	.init_irq	= gemini_init_irq,
 	.init_time	= gemini_timer_init,
 	.init_machine	= wbd222_init,
+	.restart	= gemini_restart,
 MACHINE_END
diff --git a/arch/arm/mach-gemini/common.h b/arch/arm/mach-gemini/common.h
index 7670c39..38a4526 100644
--- a/arch/arm/mach-gemini/common.h
+++ b/arch/arm/mach-gemini/common.h
@@ -26,4 +26,6 @@ extern int platform_register_pflash(unsigned int size,
 				    struct mtd_partition *parts,
 				    unsigned int nr_parts);
 
+extern void gemini_restart(char mode, const char *cmd);
+
 #endif /* __GEMINI_COMMON_H__ */
diff --git a/arch/arm/mach-gemini/gpio.c b/arch/arm/mach-gemini/gpio.c
index fdc7ef1..70bfa57 100644
--- a/arch/arm/mach-gemini/gpio.c
+++ b/arch/arm/mach-gemini/gpio.c
@@ -21,6 +21,7 @@
 
 #include <mach/hardware.h>
 #include <mach/irqs.h>
+#include <mach/gpio.h>
 
 #define GPIO_BASE(x)		IO_ADDRESS(GEMINI_GPIO_BASE(x))
 
@@ -44,7 +45,7 @@
 
 #define GPIO_PORT_NUM		3
 
-static void _set_gpio_irqenable(unsigned int base, unsigned int index,
+static void _set_gpio_irqenable(void __iomem *base, unsigned int index,
 				int enable)
 {
 	unsigned int reg;
@@ -57,7 +58,7 @@ static void _set_gpio_irqenable(unsigned int base, unsigned int index,
 static void gpio_ack_irq(struct irq_data *d)
 {
 	unsigned int gpio = irq_to_gpio(d->irq);
-	unsigned int base = GPIO_BASE(gpio / 32);
+	void __iomem *base = GPIO_BASE(gpio / 32);
 
 	__raw_writel(1 << (gpio % 32), base + GPIO_INT_CLR);
 }
@@ -65,7 +66,7 @@ static void gpio_ack_irq(struct irq_data *d)
 static void gpio_mask_irq(struct irq_data *d)
 {
 	unsigned int gpio = irq_to_gpio(d->irq);
-	unsigned int base = GPIO_BASE(gpio / 32);
+	void __iomem *base = GPIO_BASE(gpio / 32);
 
 	_set_gpio_irqenable(base, gpio % 32, 0);
 }
@@ -73,7 +74,7 @@ static void gpio_mask_irq(struct irq_data *d)
 static void gpio_unmask_irq(struct irq_data *d)
 {
 	unsigned int gpio = irq_to_gpio(d->irq);
-	unsigned int base = GPIO_BASE(gpio / 32);
+	void __iomem *base = GPIO_BASE(gpio / 32);
 
 	_set_gpio_irqenable(base, gpio % 32, 1);
 }
@@ -82,7 +83,7 @@ static int gpio_set_irq_type(struct irq_data *d, unsigned int type)
 {
 	unsigned int gpio = irq_to_gpio(d->irq);
 	unsigned int gpio_mask = 1 << (gpio % 32);
-	unsigned int base = GPIO_BASE(gpio / 32);
+	void __iomem *base = GPIO_BASE(gpio / 32);
 	unsigned int reg_both, reg_level, reg_type;
 
 	reg_type = __raw_readl(base + GPIO_INT_TYPE);
@@ -120,7 +121,7 @@ static int gpio_set_irq_type(struct irq_data *d, unsigned int type)
 	__raw_writel(reg_level, base + GPIO_INT_LEVEL);
 	__raw_writel(reg_both, base + GPIO_INT_BOTH_EDGE);
 
-	gpio_ack_irq(d->irq);
+	gpio_ack_irq(d);
 
 	return 0;
 }
@@ -153,7 +154,7 @@ static struct irq_chip gpio_irq_chip = {
 static void _set_gpio_direction(struct gpio_chip *chip, unsigned offset,
 				int dir)
 {
-	unsigned int base = GPIO_BASE(offset / 32);
+	void __iomem *base = GPIO_BASE(offset / 32);
 	unsigned int reg;
 
 	reg = __raw_readl(base + GPIO_DIR);
@@ -166,7 +167,7 @@ static void _set_gpio_direction(struct gpio_chip *chip, unsigned offset,
 
 static void gemini_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 {
-	unsigned int base = GPIO_BASE(offset / 32);
+	void __iomem *base = GPIO_BASE(offset / 32);
 
 	if (value)
 		__raw_writel(1 << (offset % 32), base + GPIO_DATA_SET);
@@ -176,7 +177,7 @@ static void gemini_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 
 static int gemini_gpio_get(struct gpio_chip *chip, unsigned offset)
 {
-	unsigned int base = GPIO_BASE(offset / 32);
+	void __iomem *base = GPIO_BASE(offset / 32);
 
 	return (__raw_readl(base + GPIO_DATA_IN) >> (offset % 32)) & 1;
 }
diff --git a/arch/arm/mach-gemini/include/mach/hardware.h b/arch/arm/mach-gemini/include/mach/hardware.h
index 8c950e1..98e7b0f 100644
--- a/arch/arm/mach-gemini/include/mach/hardware.h
+++ b/arch/arm/mach-gemini/include/mach/hardware.h
@@ -69,6 +69,6 @@
 /*
  * macro to get at IO space when running virtually
  */
-#define IO_ADDRESS(x)	((((x) & 0xFFF00000) >> 4) | ((x) & 0x000FFFFF) | 0xF0000000)
+#define IO_ADDRESS(x)	IOMEM((((x) & 0xFFF00000) >> 4) | ((x) & 0x000FFFFF) | 0xF0000000)
 
 #endif
diff --git a/arch/arm/mach-gemini/include/mach/system.h b/arch/arm/mach-gemini/include/mach/system.h
deleted file mode 100644
index a33b5a1..0000000
--- a/arch/arm/mach-gemini/include/mach/system.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- *  Copyright (C) 2001-2006 Storlink, Corp.
- *  Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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 __MACH_SYSTEM_H
-#define __MACH_SYSTEM_H
-
-#include <linux/io.h>
-#include <mach/hardware.h>
-#include <mach/global_reg.h>
-
-static inline void arch_reset(char mode, const char *cmd)
-{
-	__raw_writel(RESET_GLOBAL | RESET_CPU1,
-		     IO_ADDRESS(GEMINI_GLOBAL_BASE) + GLOBAL_RESET);
-}
-
-#endif /* __MACH_SYSTEM_H */
diff --git a/arch/arm/mach-gemini/irq.c b/arch/arm/mach-gemini/irq.c
index 020852d..30bef11 100644
--- a/arch/arm/mach-gemini/irq.c
+++ b/arch/arm/mach-gemini/irq.c
@@ -65,8 +65,8 @@ static struct irq_chip gemini_irq_chip = {
 
 static struct resource irq_resource = {
 	.name	= "irq_handler",
-	.start	= IO_ADDRESS(GEMINI_INTERRUPT_BASE),
-	.end	= IO_ADDRESS(FIQ_STATUS(GEMINI_INTERRUPT_BASE)) + 4,
+	.start	= GEMINI_INTERRUPT_BASE,
+	.end	= FIQ_STATUS(GEMINI_INTERRUPT_BASE) + 4,
 };
 
 void __init gemini_init_irq(void)
diff --git a/arch/arm/mach-gemini/mm.c b/arch/arm/mach-gemini/mm.c
index 5194824..2c2cd28 100644
--- a/arch/arm/mach-gemini/mm.c
+++ b/arch/arm/mach-gemini/mm.c
@@ -19,57 +19,57 @@
 /* Page table mapping for I/O region */
 static struct map_desc gemini_io_desc[] __initdata = {
 	{
-		.virtual	= IO_ADDRESS(GEMINI_GLOBAL_BASE),
+		.virtual	= (unsigned long)IO_ADDRESS(GEMINI_GLOBAL_BASE),
 		.pfn		=__phys_to_pfn(GEMINI_GLOBAL_BASE),
 		.length		= SZ_512K,
 		.type 		= MT_DEVICE,
 	}, {
-		.virtual	= IO_ADDRESS(GEMINI_UART_BASE),
+		.virtual	= (unsigned long)IO_ADDRESS(GEMINI_UART_BASE),
 		.pfn		= __phys_to_pfn(GEMINI_UART_BASE),
 		.length		= SZ_512K,
 		.type 		= MT_DEVICE,
 	}, {
-		.virtual	= IO_ADDRESS(GEMINI_TIMER_BASE),
+		.virtual	= (unsigned long)IO_ADDRESS(GEMINI_TIMER_BASE),
 		.pfn		= __phys_to_pfn(GEMINI_TIMER_BASE),
 		.length		= SZ_512K,
 		.type 		= MT_DEVICE,
 	}, {
-		.virtual	= IO_ADDRESS(GEMINI_INTERRUPT_BASE),
+		.virtual	= (unsigned long)IO_ADDRESS(GEMINI_INTERRUPT_BASE),
 		.pfn		= __phys_to_pfn(GEMINI_INTERRUPT_BASE),
 		.length		= SZ_512K,
 		.type 		= MT_DEVICE,
 	}, {
-		.virtual	= IO_ADDRESS(GEMINI_POWER_CTRL_BASE),
+		.virtual	= (unsigned long)IO_ADDRESS(GEMINI_POWER_CTRL_BASE),
 		.pfn		= __phys_to_pfn(GEMINI_POWER_CTRL_BASE),
 		.length		= SZ_512K,
 		.type 		= MT_DEVICE,
 	}, {
-		.virtual	= IO_ADDRESS(GEMINI_GPIO_BASE(0)),
+		.virtual	= (unsigned long)IO_ADDRESS(GEMINI_GPIO_BASE(0)),
 		.pfn		= __phys_to_pfn(GEMINI_GPIO_BASE(0)),
 		.length		= SZ_512K,
 		.type 		= MT_DEVICE,
 	}, {
-		.virtual	= IO_ADDRESS(GEMINI_GPIO_BASE(1)),
+		.virtual	= (unsigned long)IO_ADDRESS(GEMINI_GPIO_BASE(1)),
 		.pfn		= __phys_to_pfn(GEMINI_GPIO_BASE(1)),
 		.length		= SZ_512K,
 		.type 		= MT_DEVICE,
 	}, {
-		.virtual	= IO_ADDRESS(GEMINI_GPIO_BASE(2)),
+		.virtual	= (unsigned long)IO_ADDRESS(GEMINI_GPIO_BASE(2)),
 		.pfn		= __phys_to_pfn(GEMINI_GPIO_BASE(2)),
 		.length		= SZ_512K,
 		.type 		= MT_DEVICE,
 	}, {
-		.virtual	= IO_ADDRESS(GEMINI_FLASH_CTRL_BASE),
+		.virtual	= (unsigned long)IO_ADDRESS(GEMINI_FLASH_CTRL_BASE),
 		.pfn		= __phys_to_pfn(GEMINI_FLASH_CTRL_BASE),
 		.length		= SZ_512K,
 		.type 		= MT_DEVICE,
 	}, {
-		.virtual	= IO_ADDRESS(GEMINI_DRAM_CTRL_BASE),
+		.virtual	= (unsigned long)IO_ADDRESS(GEMINI_DRAM_CTRL_BASE),
 		.pfn		= __phys_to_pfn(GEMINI_DRAM_CTRL_BASE),
 		.length		= SZ_512K,
 		.type 		= MT_DEVICE,
 	}, {
-		.virtual	= IO_ADDRESS(GEMINI_GENERAL_DMA_BASE),
+		.virtual	= (unsigned long)IO_ADDRESS(GEMINI_GENERAL_DMA_BASE),
 		.pfn		= __phys_to_pfn(GEMINI_GENERAL_DMA_BASE),
 		.length		= SZ_512K,
 		.type 		= MT_DEVICE,
diff --git a/arch/arm/mach-gemini/reset.c b/arch/arm/mach-gemini/reset.c
new file mode 100644
index 0000000..b266597
--- /dev/null
+++ b/arch/arm/mach-gemini/reset.c
@@ -0,0 +1,23 @@
+/*
+ *  Copyright (C) 2001-2006 Storlink, Corp.
+ *  Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 __MACH_SYSTEM_H
+#define __MACH_SYSTEM_H
+
+#include <linux/io.h>
+#include <mach/hardware.h>
+#include <mach/global_reg.h>
+
+void gemini_restart(char mode, const char *cmd)
+{
+	__raw_writel(RESET_GLOBAL | RESET_CPU1,
+		     IO_ADDRESS(GEMINI_GLOBAL_BASE) + GLOBAL_RESET);
+}
+
+#endif /* __MACH_SYSTEM_H */
diff --git a/arch/arm/mach-h720x/Kconfig b/arch/arm/mach-h720x/Kconfig
deleted file mode 100644
index 6bb755b..0000000
--- a/arch/arm/mach-h720x/Kconfig
+++ /dev/null
@@ -1,40 +0,0 @@
-if ARCH_H720X
-
-menu "h720x Implementations"
-
-config ARCH_H7201
-	bool "gms30c7201"
-	depends on ARCH_H720X
-	select CPU_H7201
-	select ZONE_DMA
-	help
-	  Say Y here if you are using the Hynix GMS30C7201 Reference Board
-
-config ARCH_H7202
-	bool "hms30c7202"
-	depends on ARCH_H720X
-	select CPU_H7202
-	select ZONE_DMA
-	help
-	  Say Y here if you are using the Hynix HMS30C7202 Reference Board
-
-endmenu
-
-config CPU_H7201
-	bool
-	help
-	  Select code specific to h7201 variants
-
-config CPU_H7202
-	bool
-	help
-	  Select code specific to h7202 variants
-config H7202_SERIAL23
-	depends on CPU_H7202
-	bool "Use serial ports 2+3"
-	help
-	  Say Y here if you wish to use serial ports 2+3. They share their
-	  pins with the keyboard matrix controller, so you have to decide.
-
-
-endif
diff --git a/arch/arm/mach-h720x/Makefile b/arch/arm/mach-h720x/Makefile
deleted file mode 100644
index e4cf728..0000000
--- a/arch/arm/mach-h720x/Makefile
+++ /dev/null
@@ -1,16 +0,0 @@
-#
-# Makefile for the linux kernel.
-#
-
-# Common support
-obj-y := common.o
-obj-m :=
-obj-n :=
-obj-  :=
-
-# Specific board support
-
-obj-$(CONFIG_ARCH_H7201)		+= h7201-eval.o
-obj-$(CONFIG_ARCH_H7202)		+= h7202-eval.o
-obj-$(CONFIG_CPU_H7201) 		+= cpu-h7201.o
-obj-$(CONFIG_CPU_H7202) 		+= cpu-h7202.o
diff --git a/arch/arm/mach-h720x/Makefile.boot b/arch/arm/mach-h720x/Makefile.boot
deleted file mode 100644
index d875a70..0000000
--- a/arch/arm/mach-h720x/Makefile.boot
+++ /dev/null
@@ -1,2 +0,0 @@
-   zreladdr-$(CONFIG_ARCH_H720X)	+= 0x40008000
-
diff --git a/arch/arm/mach-h720x/common.c b/arch/arm/mach-h720x/common.c
deleted file mode 100644
index 17ef91f..0000000
--- a/arch/arm/mach-h720x/common.c
+++ /dev/null
@@ -1,268 +0,0 @@
-/*
- * linux/arch/arm/mach-h720x/common.c
- *
- * Copyright (C) 2003 Thomas Gleixner <tglx@linutronix.de>
- *               2003 Robert Schwebel <r.schwebel@pengutronix.de>
- *               2004 Sascha Hauer    <s.hauer@pengutronix.de>
- *
- * common stuff for Hynix h720x processors
- *
- * This program is free software; you can 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/mman.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/dma.h>
-#include <mach/hardware.h>
-#include <asm/irq.h>
-#include <asm/system_misc.h>
-#include <asm/mach/irq.h>
-#include <asm/mach/map.h>
-#include <mach/irqs.h>
-
-#include <asm/mach/dma.h>
-
-#if 0
-#define IRQDBG(args...) printk(args)
-#else
-#define IRQDBG(args...) do {} while(0)
-#endif
-
-void __init arch_dma_init(dma_t *dma)
-{
-}
-
-/*
- * Return nsecs since last timer reload
- * (timercount * (usecs perjiffie)) / (ticks per jiffie)
- */
-u32 h720x_gettimeoffset(void)
-{
-	return ((CPU_REG(TIMER_VIRT, TM0_COUNT) * tick_usec) / LATCH) * 1000;
-}
-
-/*
- * mask Global irq's
- */
-static void mask_global_irq(struct irq_data *d)
-{
-	CPU_REG (IRQC_VIRT, IRQC_IER) &= ~(1 << d->irq);
-}
-
-/*
- * unmask Global irq's
- */
-static void unmask_global_irq(struct irq_data *d)
-{
-	CPU_REG (IRQC_VIRT, IRQC_IER) |= (1 << d->irq);
-}
-
-
-/*
- * ack GPIO irq's
- * Ack only for edge triggered int's valid
- */
-static void inline ack_gpio_irq(struct irq_data *d)
-{
-	u32 reg_base = GPIO_VIRT(IRQ_TO_REGNO(d->irq));
-	u32 bit = IRQ_TO_BIT(d->irq);
-	if ( (CPU_REG (reg_base, GPIO_EDGE) & bit))
-		CPU_REG (reg_base, GPIO_CLR) = bit;
-}
-
-/*
- * mask GPIO irq's
- */
-static void inline mask_gpio_irq(struct irq_data *d)
-{
-	u32 reg_base = GPIO_VIRT(IRQ_TO_REGNO(d->irq));
-	u32 bit = IRQ_TO_BIT(d->irq);
-	CPU_REG (reg_base, GPIO_MASK) &= ~bit;
-}
-
-/*
- * unmask GPIO irq's
- */
-static void inline unmask_gpio_irq(struct irq_data *d)
-{
-	u32 reg_base = GPIO_VIRT(IRQ_TO_REGNO(d->irq));
-	u32 bit = IRQ_TO_BIT(d->irq);
-	CPU_REG (reg_base, GPIO_MASK) |= bit;
-}
-
-static void
-h720x_gpio_handler(unsigned int mask, unsigned int irq,
-                 struct irq_desc *desc)
-{
-	IRQDBG("%s irq: %d\n", __func__, irq);
-	while (mask) {
-		if (mask & 1) {
-			IRQDBG("handling irq %d\n", irq);
-			generic_handle_irq(irq);
-		}
-		irq++;
-		mask >>= 1;
-	}
-}
-
-static void
-h720x_gpioa_demux_handler(unsigned int irq_unused, struct irq_desc *desc)
-{
-	unsigned int mask, irq;
-
-	mask = CPU_REG(GPIO_A_VIRT,GPIO_STAT);
-	irq = IRQ_CHAINED_GPIOA(0);
-	IRQDBG("%s mask: 0x%08x irq: %d\n", __func__, mask,irq);
-	h720x_gpio_handler(mask, irq, desc);
-}
-
-static void
-h720x_gpiob_demux_handler(unsigned int irq_unused, struct irq_desc *desc)
-{
-	unsigned int mask, irq;
-	mask = CPU_REG(GPIO_B_VIRT,GPIO_STAT);
-	irq = IRQ_CHAINED_GPIOB(0);
-	IRQDBG("%s mask: 0x%08x irq: %d\n", __func__, mask,irq);
-	h720x_gpio_handler(mask, irq, desc);
-}
-
-static void
-h720x_gpioc_demux_handler(unsigned int irq_unused, struct irq_desc *desc)
-{
-	unsigned int mask, irq;
-
-	mask = CPU_REG(GPIO_C_VIRT,GPIO_STAT);
-	irq = IRQ_CHAINED_GPIOC(0);
-	IRQDBG("%s mask: 0x%08x irq: %d\n", __func__, mask,irq);
-	h720x_gpio_handler(mask, irq, desc);
-}
-
-static void
-h720x_gpiod_demux_handler(unsigned int irq_unused, struct irq_desc *desc)
-{
-	unsigned int mask, irq;
-
-	mask = CPU_REG(GPIO_D_VIRT,GPIO_STAT);
-	irq = IRQ_CHAINED_GPIOD(0);
-	IRQDBG("%s mask: 0x%08x irq: %d\n", __func__, mask,irq);
-	h720x_gpio_handler(mask, irq, desc);
-}
-
-#ifdef CONFIG_CPU_H7202
-static void
-h720x_gpioe_demux_handler(unsigned int irq_unused, struct irq_desc *desc)
-{
-	unsigned int mask, irq;
-
-	mask = CPU_REG(GPIO_E_VIRT,GPIO_STAT);
-	irq = IRQ_CHAINED_GPIOE(0);
-	IRQDBG("%s mask: 0x%08x irq: %d\n", __func__, mask,irq);
-	h720x_gpio_handler(mask, irq, desc);
-}
-#endif
-
-static struct irq_chip h720x_global_chip = {
-	.irq_ack = mask_global_irq,
-	.irq_mask = mask_global_irq,
-	.irq_unmask = unmask_global_irq,
-};
-
-static struct irq_chip h720x_gpio_chip = {
-	.irq_ack = ack_gpio_irq,
-	.irq_mask = mask_gpio_irq,
-	.irq_unmask = unmask_gpio_irq,
-};
-
-/*
- * Initialize IRQ's, mask all, enable multiplexed irq's
- */
-void __init h720x_init_irq (void)
-{
-	int 	irq;
-
-	/* Mask global irq's */
-	CPU_REG (IRQC_VIRT, IRQC_IER) = 0x0;
-
-	/* Mask all multiplexed irq's */
-	CPU_REG (GPIO_A_VIRT, GPIO_MASK) = 0x0;
-	CPU_REG (GPIO_B_VIRT, GPIO_MASK) = 0x0;
-	CPU_REG (GPIO_C_VIRT, GPIO_MASK) = 0x0;
-	CPU_REG (GPIO_D_VIRT, GPIO_MASK) = 0x0;
-
-	/* Initialize global IRQ's, fast path */
-	for (irq = 0; irq < NR_GLBL_IRQS; irq++) {
-		irq_set_chip_and_handler(irq, &h720x_global_chip,
-					 handle_level_irq);
-		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
-	}
-
-	/* Initialize multiplexed IRQ's, slow path */
-	for (irq = IRQ_CHAINED_GPIOA(0) ; irq <= IRQ_CHAINED_GPIOD(31); irq++) {
-		irq_set_chip_and_handler(irq, &h720x_gpio_chip,
-					 handle_edge_irq);
-		set_irq_flags(irq, IRQF_VALID );
-	}
-	irq_set_chained_handler(IRQ_GPIOA, h720x_gpioa_demux_handler);
-	irq_set_chained_handler(IRQ_GPIOB, h720x_gpiob_demux_handler);
-	irq_set_chained_handler(IRQ_GPIOC, h720x_gpioc_demux_handler);
-	irq_set_chained_handler(IRQ_GPIOD, h720x_gpiod_demux_handler);
-
-#ifdef CONFIG_CPU_H7202
-	for (irq = IRQ_CHAINED_GPIOE(0) ; irq <= IRQ_CHAINED_GPIOE(31); irq++) {
-		irq_set_chip_and_handler(irq, &h720x_gpio_chip,
-					 handle_edge_irq);
-		set_irq_flags(irq, IRQF_VALID );
-	}
-	irq_set_chained_handler(IRQ_GPIOE, h720x_gpioe_demux_handler);
-#endif
-
-	/* Enable multiplexed irq's */
-	CPU_REG (IRQC_VIRT, IRQC_IER) = IRQ_ENA_MUX;
-}
-
-static struct map_desc h720x_io_desc[] __initdata = {
-	{
-		.virtual	= IO_VIRT,
-		.pfn		= __phys_to_pfn(IO_PHYS),
-		.length		= IO_SIZE,
-		.type		= MT_DEVICE
-	},
-};
-
-/* Initialize io tables */
-void __init h720x_map_io(void)
-{
-	iotable_init(h720x_io_desc,ARRAY_SIZE(h720x_io_desc));
-}
-
-void h720x_restart(char mode, const char *cmd)
-{
-	CPU_REG (PMU_BASE, PMU_STAT) |= PMU_WARMRESET;
-}
-
-static void h720x__idle(void)
-{
-	CPU_REG (PMU_BASE, PMU_MODE) = PMU_MODE_IDLE;
-	nop();
-	nop();
-	CPU_REG (PMU_BASE, PMU_MODE) = PMU_MODE_RUN;
-	nop();
-	nop();
-}
-
-static int __init h720x_idle_init(void)
-{
-	arm_pm_idle = h720x__idle;
-	return 0;
-}
-
-arch_initcall(h720x_idle_init);
diff --git a/arch/arm/mach-h720x/common.h b/arch/arm/mach-h720x/common.h
deleted file mode 100644
index 7e73841..0000000
--- a/arch/arm/mach-h720x/common.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * linux/arch/arm/mach-h720x/common.h
- *
- * Copyright (C) 2003 Thomas Gleixner <tglx@linutronix.de>
- *               2003 Robert Schwebel <r.schwebel@pengutronix.de>
- *               2004 Sascha Hauer    <s.hauer@pengutronix.de>
- *
- * Architecture specific stuff for Hynix GMS30C7201 development board
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-
-extern u32 h720x_gettimeoffset(void);
-extern void __init h720x_init_irq(void);
-extern void __init h720x_map_io(void);
-extern void h720x_restart(char, const char *);
-
-#ifdef CONFIG_ARCH_H7202
-extern void h7202_timer_init(void);
-extern void __init init_hw_h7202(void);
-extern void __init h7202_init_irq(void);
-extern void __init h7202_init_time(void);
-#endif
-
-#ifdef CONFIG_ARCH_H7201
-extern void h7201_timer_init(void);
-#endif
diff --git a/arch/arm/mach-h720x/cpu-h7201.c b/arch/arm/mach-h720x/cpu-h7201.c
deleted file mode 100644
index 13c7412..0000000
--- a/arch/arm/mach-h720x/cpu-h7201.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * linux/arch/arm/mach-h720x/cpu-h7201.c
- *
- * Copyright (C) 2003 Thomas Gleixner <tglx@linutronix.de>
- *               2003 Robert Schwebel <r.schwebel@pengutronix.de>
- *               2004 Sascha Hauer    <s.hauer@pengutronix.de>
- *
- * processor specific stuff for the Hynix h7201
- *
- * This program is free software; you can 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/module.h>
-#include <asm/types.h>
-#include <mach/hardware.h>
-#include <asm/irq.h>
-#include <mach/irqs.h>
-#include <asm/mach/irq.h>
-#include <asm/mach/time.h>
-#include "common.h"
-/*
- * Timer interrupt handler
- */
-static irqreturn_t
-h7201_timer_interrupt(int irq, void *dev_id)
-{
-	CPU_REG (TIMER_VIRT, TIMER_TOPSTAT);
-	timer_tick();
-
-	return IRQ_HANDLED;
-}
-
-static struct irqaction h7201_timer_irq = {
-	.name		= "h7201 Timer Tick",
-	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
-	.handler	= h7201_timer_interrupt,
-};
-
-/*
- * Setup TIMER0 as system timer
- */
-void __init h7201_timer_init(void)
-{
-	arch_gettimeoffset = h720x_gettimeoffset;
-
-	CPU_REG (TIMER_VIRT, TM0_PERIOD) = LATCH;
-	CPU_REG (TIMER_VIRT, TM0_CTRL) = TM_RESET;
-	CPU_REG (TIMER_VIRT, TM0_CTRL) = TM_REPEAT | TM_START;
-	CPU_REG (TIMER_VIRT, TIMER_TOPCTRL) = ENABLE_TM0_INTR | TIMER_ENABLE_BIT;
-
-	setup_irq(IRQ_TIMER0, &h7201_timer_irq);
-}
diff --git a/arch/arm/mach-h720x/cpu-h7202.c b/arch/arm/mach-h720x/cpu-h7202.c
deleted file mode 100644
index e2ae7e8..0000000
--- a/arch/arm/mach-h720x/cpu-h7202.c
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * linux/arch/arm/mach-h720x/cpu-h7202.c
- *
- * Copyright (C) 2003 Thomas Gleixner <tglx@linutronix.de>
- *               2003 Robert Schwebel <r.schwebel@pengutronix.de>
- *               2004 Sascha Hauer    <s.hauer@pengutronix.de>
- *
- * processor specific stuff for the Hynix h7202
- *
- * This program is free software; you can 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/module.h>
-#include <asm/types.h>
-#include <mach/hardware.h>
-#include <asm/irq.h>
-#include <mach/irqs.h>
-#include <asm/mach/irq.h>
-#include <asm/mach/time.h>
-#include <linux/device.h>
-#include <linux/serial_8250.h>
-#include "common.h"
-
-static struct resource h7202ps2_resources[] = {
-	[0] = {
-		.start	= 0x8002c000,
-		.end	= 0x8002c040,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_PS2,
-		.end	= IRQ_PS2,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device h7202ps2_device = {
-	.name		= "h7202ps2",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(h7202ps2_resources),
-	.resource	= h7202ps2_resources,
-};
-
-static struct plat_serial8250_port serial_platform_data[] = {
-	{
-		.membase	= (void*)SERIAL0_VIRT,
-		.mapbase	= SERIAL0_BASE,
-		.irq		= IRQ_UART0,
-		.uartclk	= 2*1843200,
-		.regshift	= 2,
-		.iotype		= UPIO_MEM,
-		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
-	},
-	{
-		.membase	= (void*)SERIAL1_VIRT,
-		.mapbase	= SERIAL1_BASE,
-		.irq		= IRQ_UART1,
-		.uartclk	= 2*1843200,
-		.regshift	= 2,
-		.iotype		= UPIO_MEM,
-		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
-	},
-#ifdef CONFIG_H7202_SERIAL23
-	{
-		.membase	= (void*)SERIAL2_VIRT,
-		.mapbase	= SERIAL2_BASE,
-		.irq		= IRQ_UART2,
-		.uartclk	= 2*1843200,
-		.regshift	= 2,
-		.iotype		= UPIO_MEM,
-		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
-	},
-	{
-		.membase	= (void*)SERIAL3_VIRT,
-		.mapbase	= SERIAL3_BASE,
-		.irq		= IRQ_UART3,
-		.uartclk	= 2*1843200,
-		.regshift	= 2,
-		.iotype		= UPIO_MEM,
-		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
-	},
-#endif
-	{ },
-};
-
-static struct platform_device serial_device = {
-	.name			= "serial8250",
-	.id			= PLAT8250_DEV_PLATFORM,
-	.dev			= {
-		.platform_data	= serial_platform_data,
-	},
-};
-
-static struct platform_device *devices[] __initdata = {
-	&h7202ps2_device,
-	&serial_device,
-};
-
-/* Although we have two interrupt lines for the timers, we only have one
- * status register which clears all pending timer interrupts on reading. So
- * we have to handle all timer interrupts in one place.
- */
-static void
-h7202_timerx_demux_handler(unsigned int irq_unused, struct irq_desc *desc)
-{
-	unsigned int mask, irq;
-
-	mask = CPU_REG (TIMER_VIRT, TIMER_TOPSTAT);
-
-	if ( mask & TSTAT_T0INT ) {
-		timer_tick();
-		if( mask == TSTAT_T0INT )
-			return;
-	}
-
-	mask >>= 1;
-	irq = IRQ_TIMER1;
-	while (mask) {
-		if (mask & 1)
-			generic_handle_irq(irq);
-		irq++;
-		mask >>= 1;
-	}
-}
-
-/*
- * Timer interrupt handler
- */
-static irqreturn_t
-h7202_timer_interrupt(int irq, void *dev_id)
-{
-	h7202_timerx_demux_handler(0, NULL);
-	return IRQ_HANDLED;
-}
-
-/*
- * mask multiplexed timer IRQs
- */
-static void inline __mask_timerx_irq(unsigned int irq)
-{
-	unsigned int bit;
-	bit = 2 << ((irq == IRQ_TIMER64B) ? 4 : (irq - IRQ_TIMER1));
-	CPU_REG (TIMER_VIRT, TIMER_TOPCTRL) &= ~bit;
-}
-
-static void inline mask_timerx_irq(struct irq_data *d)
-{
-	__mask_timerx_irq(d->irq);
-}
-
-/*
- * unmask multiplexed timer IRQs
- */
-static void inline unmask_timerx_irq(struct irq_data *d)
-{
-	unsigned int bit;
-	bit = 2 << ((d->irq == IRQ_TIMER64B) ? 4 : (d->irq - IRQ_TIMER1));
-	CPU_REG (TIMER_VIRT, TIMER_TOPCTRL) |= bit;
-}
-
-static struct irq_chip h7202_timerx_chip = {
-	.irq_ack = mask_timerx_irq,
-	.irq_mask = mask_timerx_irq,
-	.irq_unmask = unmask_timerx_irq,
-};
-
-static struct irqaction h7202_timer_irq = {
-	.name		= "h7202 Timer Tick",
-	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
-	.handler	= h7202_timer_interrupt,
-};
-
-/*
- * Setup TIMER0 as system timer
- */
-void __init h7202_timer_init(void)
-{
-	arch_gettimeoffset = h720x_gettimeoffset;
-
-	CPU_REG (TIMER_VIRT, TM0_PERIOD) = LATCH;
-	CPU_REG (TIMER_VIRT, TM0_CTRL) = TM_RESET;
-	CPU_REG (TIMER_VIRT, TM0_CTRL) = TM_REPEAT | TM_START;
-	CPU_REG (TIMER_VIRT, TIMER_TOPCTRL) = ENABLE_TM0_INTR | TIMER_ENABLE_BIT;
-
-	setup_irq(IRQ_TIMER0, &h7202_timer_irq);
-}
-
-void __init h7202_init_irq (void)
-{
-	int 	irq;
-
-	CPU_REG (GPIO_E_VIRT, GPIO_MASK) = 0x0;
-
-	for (irq = IRQ_TIMER1;
-	                  irq < IRQ_CHAINED_TIMERX(NR_TIMERX_IRQS); irq++) {
-		__mask_timerx_irq(irq);
-		irq_set_chip_and_handler(irq, &h7202_timerx_chip,
-					 handle_edge_irq);
-		set_irq_flags(irq, IRQF_VALID );
-	}
-	irq_set_chained_handler(IRQ_TIMERX, h7202_timerx_demux_handler);
-
-	h720x_init_irq();
-}
-
-void __init init_hw_h7202(void)
-{
-	/* Enable clocks */
-	CPU_REG (PMU_BASE, PMU_PLL_CTRL) |= PLL_2_EN | PLL_1_EN | PLL_3_MUTE;
-
-	CPU_REG (SERIAL0_VIRT, SERIAL_ENABLE) = SERIAL_ENABLE_EN;
-	CPU_REG (SERIAL1_VIRT, SERIAL_ENABLE) = SERIAL_ENABLE_EN;
-#ifdef CONFIG_H7202_SERIAL23
-	CPU_REG (SERIAL2_VIRT, SERIAL_ENABLE) = SERIAL_ENABLE_EN;
-	CPU_REG (SERIAL3_VIRT, SERIAL_ENABLE) = SERIAL_ENABLE_EN;
-	CPU_IO (GPIO_AMULSEL) = AMULSEL_USIN2 | AMULSEL_USOUT2 |
-	                        AMULSEL_USIN3 | AMULSEL_USOUT3;
-#endif
-	(void) platform_add_devices(devices, ARRAY_SIZE(devices));
-}
diff --git a/arch/arm/mach-h720x/h7201-eval.c b/arch/arm/mach-h720x/h7201-eval.c
deleted file mode 100644
index 4fdeb68..0000000
--- a/arch/arm/mach-h720x/h7201-eval.c
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * linux/arch/arm/mach-h720x/h7201-eval.c
- *
- * Copyright (C) 2003 Thomas Gleixner <tglx@linutronix.de>
- *               2003 Robert Schwebel <r.schwebel@pengutronix.de>
- *               2004 Sascha Hauer    <s.hauer@pengutronix.de>
- *
- * Architecture specific stuff for Hynix GMS30C7201 development board
- *
- * This program is free software; you can 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/kernel.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/device.h>
-
-#include <asm/setup.h>
-#include <asm/types.h>
-#include <asm/mach-types.h>
-#include <asm/page.h>
-#include <asm/mach/arch.h>
-#include <mach/hardware.h>
-#include "common.h"
-
-MACHINE_START(H7201, "Hynix GMS30C7201")
-	/* Maintainer: Robert Schwebel, Pengutronix */
-	.atag_offset	= 0x1000,
-	.map_io		= h720x_map_io,
-	.init_irq	= h720x_init_irq,
-	.init_time	= h7201_timer_init,
-	.dma_zone_size	= SZ_256M,
-	.restart	= h720x_restart,
-MACHINE_END
diff --git a/arch/arm/mach-h720x/h7202-eval.c b/arch/arm/mach-h720x/h7202-eval.c
deleted file mode 100644
index f68e967..0000000
--- a/arch/arm/mach-h720x/h7202-eval.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * linux/arch/arm/mach-h720x/h7202-eval.c
- *
- * Copyright (C) 2003 Thomas Gleixner <tglx@linutronix.de>
- *               2003 Robert Schwebel <r.schwebel@pengutronix.de>
- *		 2004 Sascha Hauer <s.hauer@pengutronix.de>
- *
- * Architecture specific stuff for Hynix HMS30C7202 development board
- *
- * This program is free software; you can 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/kernel.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/platform_device.h>
-
-#include <asm/setup.h>
-#include <asm/types.h>
-#include <asm/mach-types.h>
-#include <asm/page.h>
-#include <asm/mach/arch.h>
-#include <mach/irqs.h>
-#include <mach/hardware.h>
-#include "common.h"
-
-static struct resource cirrus_resources[] = {
-	[0] = {
-		.start	= ETH0_PHYS + 0x300,
-		.end	= ETH0_PHYS + 0x300 + 0x10,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_CHAINED_GPIOB(8),
-		.end	= IRQ_CHAINED_GPIOB(8),
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device cirrus_device = {
-	.name		= "cirrus-cs89x0",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(cirrus_resources),
-	.resource	= cirrus_resources,
-};
-
-static struct platform_device *devices[] __initdata = {
-	&cirrus_device,
-};
-
-/*
- * Hardware init. This is called early in initcalls
- * Place pin inits here. So you avoid adding ugly
- * #ifdef stuff to common drivers.
- * Use this only, if your bootloader is not able
- * to initialize the pins proper.
- */
-static void __init init_eval_h7202(void)
-{
-	init_hw_h7202();
-	(void) platform_add_devices(devices, ARRAY_SIZE(devices));
-
-	/* Enable interrupt on portb bit 8 (ethernet) */
-	CPU_REG (GPIO_B_VIRT, GPIO_POL) &= ~(1 << 8);
-	CPU_REG (GPIO_B_VIRT, GPIO_EN) |= (1 << 8);
-}
-
-MACHINE_START(H7202, "Hynix HMS30C7202")
-	/* Maintainer: Robert Schwebel, Pengutronix */
-	.atag_offset	= 0x100,
-	.map_io		= h720x_map_io,
-	.init_irq	= h7202_init_irq,
-	.init_time	= h7202_timer_init,
-	.init_machine	= init_eval_h7202,
-	.dma_zone_size	= SZ_256M,
-	.restart	= h720x_restart,
-MACHINE_END
diff --git a/arch/arm/mach-h720x/include/mach/boards.h b/arch/arm/mach-h720x/include/mach/boards.h
deleted file mode 100644
index 38b8e0d..0000000
--- a/arch/arm/mach-h720x/include/mach/boards.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * arch/arm/mach-h720x/include/mach/boards.h
- *
- * Copyright (C) 2003 Thomas Gleixner <tglx@linutronix.de>
- *           (C) 2003 Robert Schwebel <r.schwebel@pengutronix.de>
- *
- * This file contains the board specific defines for various devices
- *
- * This program is free software; you can 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_INCMACH_H
-#error Do not include this file directly. Include asm/hardware.h instead !
-#endif
-
-/* Hynix H7202 developer board specific device defines */
-#ifdef CONFIG_ARCH_H7202
-
-/* FLASH */
-#define H720X_FLASH_VIRT	0xd0000000
-#define H720X_FLASH_PHYS	0x00000000
-#define H720X_FLASH_SIZE	0x02000000
-
-/* onboard LAN controller */
-# define ETH0_PHYS		0x08000000
-
-/* Touch screen defines */
-/* GPIO Port */
-#define PEN_GPIO		GPIO_B_VIRT
-/* Bitmask for pen down interrupt */
-#define PEN_INT_BIT		(1<<7)
-/* Bitmask for pen up interrupt */
-#define PEN_ENA_BIT		(1<<6)
-/* pen up interrupt */
-#define IRQ_PEN			IRQ_MUX_GPIOB(7)
-
-#endif
-
-/* Hynix H7201 developer board specific device defines */
-#if defined (CONFIG_ARCH_H7201)
-/* ROM DISK SPACE */
-#define ROM_DISK_BASE           0xc1800000
-#define ROM_DISK_START          0x41800000
-#define ROM_DISK_SIZE           0x00700000
-
-/* SRAM DISK SPACE */
-#define SRAM_DISK_BASE          0xf1000000
-#define SRAM_DISK_START         0x04000000
-#define SRAM_DISK_SIZE          0x00400000
-#endif
-
diff --git a/arch/arm/mach-h720x/include/mach/debug-macro.S b/arch/arm/mach-h720x/include/mach/debug-macro.S
deleted file mode 100644
index 8a46157..0000000
--- a/arch/arm/mach-h720x/include/mach/debug-macro.S
+++ /dev/null
@@ -1,40 +0,0 @@
-/* arch/arm/mach-h720x/include/mach/debug-macro.S
- *
- * Debugging macro include header
- *
- *  Copyright (C) 1994-1999 Russell King
- *  Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
-*/
-
-#include <mach/hardware.h>
-
-		.equ    io_virt, IO_VIRT
-		.equ    io_phys, IO_PHYS
-
-		.macro  addruart, rp, rv, tmp
-		mov     \rp, #0x00020000	@ UART1
-		add     \rv, \rp, #io_virt	@ virtual address
-		add     \rp, \rp, #io_phys	@ physical base address
-		.endm
-
-		.macro  senduart,rd,rx
-		str     \rd, [\rx, #0x0]        @ UARTDR
-
-		.endm
-
-		.macro  waituart,rd,rx
-1001:		ldr     \rd, [\rx, #0x18]       @ UARTFLG
-		tst     \rd, #1 << 5	       @ UARTFLGUTXFF - 1 when full
-		bne     1001b
-		.endm
-
-		.macro  busyuart,rd,rx
-1001:		ldr     \rd, [\rx, #0x18]       @ UARTFLG
-		tst     \rd, #1 << 3	       @ UARTFLGUBUSY - 1 when busy
-		bne     1001b
-		.endm
diff --git a/arch/arm/mach-h720x/include/mach/entry-macro.S b/arch/arm/mach-h720x/include/mach/entry-macro.S
deleted file mode 100644
index 75267fa..0000000
--- a/arch/arm/mach-h720x/include/mach/entry-macro.S
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * arch/arm/mach-h720x/include/mach/entry-macro.S
- *
- * Low-level IRQ helper macros for Hynix HMS720x based platforms
- *
- * This file is licensed under  the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-		.macro  get_irqnr_preamble, base, tmp
-		.endm
-
-		.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-#if defined (CONFIG_CPU_H7201) || defined (CONFIG_CPU_H7202)
-		@ we could use the id register on H7202, but this is not
-		@ properly updated when we come back from asm_do_irq
-		@ without a previous return from interrupt
-		@ (see loops below in irq_svc, irq_usr)
-		@ We see unmasked pending ints only, as the masked pending ints
-		@ are not visible here
-
-		mov     \base, #0xf0000000	       @ base register
-		orr     \base, \base, #0x24000	       @ irqbase
-		ldr     \irqstat, [\base, #0x04]        @ get interrupt status
-#if defined (CONFIG_CPU_H7201)
-		ldr	\tmp, =0x001fffff
-#else
-		mvn     \tmp, #0xc0000000
-#endif
-		and     \irqstat, \irqstat, \tmp        @ mask out unused ints
-		mov     \irqnr, #0
-
-		mov     \tmp, #0xff00
-		orr     \tmp, \tmp, #0xff
-		tst     \irqstat, \tmp
-		addeq   \irqnr, \irqnr, #16
-		moveq   \irqstat, \irqstat, lsr #16
-		tst     \irqstat, #255
-		addeq   \irqnr, \irqnr, #8
-		moveq   \irqstat, \irqstat, lsr #8
-		tst     \irqstat, #15
-		addeq   \irqnr, \irqnr, #4
-		moveq   \irqstat, \irqstat, lsr #4
-		tst     \irqstat, #3
-		addeq   \irqnr, \irqnr, #2
-		moveq   \irqstat, \irqstat, lsr #2
-		tst     \irqstat, #1
-		addeq   \irqnr, \irqnr, #1
-		moveq   \irqstat, \irqstat, lsr #1
-		tst     \irqstat, #1		       @ bit 0 should be set
-		.endm
-
-#else
-#error hynix processor selection missmatch
-#endif
-
diff --git a/arch/arm/mach-h720x/include/mach/h7201-regs.h b/arch/arm/mach-h720x/include/mach/h7201-regs.h
deleted file mode 100644
index 611b494..0000000
--- a/arch/arm/mach-h720x/include/mach/h7201-regs.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * arch/arm/mach-h720x/include/mach/h7201-regs.h
- *
- * Copyright (C) 2000 Jungjun Kim, Hynix Semiconductor Inc.
- *           (C) 2003 Thomas Gleixner <tglx@linutronix.de>
- *           (C) 2003 Robert Schwebel <r.schwebel@pengutronix.de>
- *           (C) 2004 Sascha Hauer    <s.hauer@pengutronix.de>
- *
- * This file contains the hardware definitions of the h720x processors
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Do not add implementations specific defines here. This files contains
- * only defines of the onchip peripherals. Add those defines to boards.h,
- * which is included by this file.
- */
-
-#define SERIAL2_VIRT 		(IO_VIRT + 0x50100)
-#define SERIAL3_VIRT 		(IO_VIRT + 0x50200)
-
-/*
- * PCMCIA
- */
-#define PCMCIA0_ATT_BASE        0xe5000000
-#define PCMCIA0_ATT_SIZE        0x00200000
-#define PCMCIA0_ATT_START       0x20000000
-#define PCMCIA0_MEM_BASE        0xe5200000
-#define PCMCIA0_MEM_SIZE        0x00200000
-#define PCMCIA0_MEM_START       0x24000000
-#define PCMCIA0_IO_BASE         0xe5400000
-#define PCMCIA0_IO_SIZE         0x00200000
-#define PCMCIA0_IO_START        0x28000000
-
-#define PCMCIA1_ATT_BASE        0xe5600000
-#define PCMCIA1_ATT_SIZE        0x00200000
-#define PCMCIA1_ATT_START       0x30000000
-#define PCMCIA1_MEM_BASE        0xe5800000
-#define PCMCIA1_MEM_SIZE        0x00200000
-#define PCMCIA1_MEM_START       0x34000000
-#define PCMCIA1_IO_BASE         0xe5a00000
-#define PCMCIA1_IO_SIZE         0x00200000
-#define PCMCIA1_IO_START        0x38000000
-
-#define PRIME3C_BASE            0xf0050000
-#define PRIME3C_SIZE            0x00001000
-#define PRIME3C_START           0x10000000
-
-/* VGA Controller */
-#define VGA_RAMBASE 		0x50
-#define VGA_TIMING0 		0x60
-#define VGA_TIMING1 		0x64
-#define VGA_TIMING2 		0x68
-#define VGA_TIMING3 		0x6c
-
-#define LCD_CTRL_VGA_ENABLE   	0x00000100
-#define LCD_CTRL_VGA_BPP_MASK 	0x00000600
-#define LCD_CTRL_VGA_4BPP    	0x00000000
-#define LCD_CTRL_VGA_8BPP    	0x00000200
-#define LCD_CTRL_VGA_16BPP   	0x00000300
-#define LCD_CTRL_SHARE_DMA    	0x00000800
-#define LCD_CTRL_VDE          	0x00100000
-#define LCD_CTRL_LPE          	0x00400000	/* LCD Power enable */
-#define LCD_CTRL_BLE          	0x00800000	/* LCD backlight enable */
-
-#define VGA_PALETTE_BASE	(IO_VIRT + 0x10800)
diff --git a/arch/arm/mach-h720x/include/mach/h7202-regs.h b/arch/arm/mach-h720x/include/mach/h7202-regs.h
deleted file mode 100644
index 17c12eb..0000000
--- a/arch/arm/mach-h720x/include/mach/h7202-regs.h
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * arch/arm/mach-h720x/include/mach/h7202-regs.h
- *
- * Copyright (C) 2000 Jungjun Kim, Hynix Semiconductor Inc.
- *           (C) 2003 Thomas Gleixner <tglx@linutronix.de>
- *           (C) 2003 Robert Schwebel <r.schwebel@pengutronix.de>
- *           (C) 2004 Sascha Hauer    <s.hauer@pengutronix.de>
- *
- * This file contains the hardware definitions of the h720x processors
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Do not add implementations specific defines here. This files contains
- * only defines of the onchip peripherals. Add those defines to boards.h,
- * which is included by this file.
- */
-
-#define SERIAL2_OFS		0x2d000
-#define SERIAL2_BASE		(IO_PHYS + SERIAL2_OFS)
-#define SERIAL2_VIRT 		(IO_VIRT + SERIAL2_OFS)
-#define SERIAL3_OFS		0x2e000
-#define SERIAL3_BASE		(IO_PHYS + SERIAL3_OFS)
-#define SERIAL3_VIRT 		(IO_VIRT + SERIAL3_OFS)
-
-/* Matrix Keyboard Controller */
-#define KBD_VIRT		(IO_VIRT + 0x22000)
-#define KBD_KBCR		0x00
-#define KBD_KBSC		0x04
-#define KBD_KBTR		0x08
-#define KBD_KBVR0		0x0C
-#define KBD_KBVR1		0x10
-#define KBD_KBSR		0x18
-
-#define KBD_KBCR_SCANENABLE	(1 << 7)
-#define KBD_KBCR_NPOWERDOWN	(1 << 2)
-#define KBD_KBCR_CLKSEL_MASK	(3)
-#define KBD_KBCR_CLKSEL_PCLK2	0x0
-#define KBD_KBCR_CLKSEL_PCLK128	0x1
-#define KBD_KBCR_CLKSEL_PCLK256	0x2
-#define KBD_KBCR_CLKSEL_PCLK512	0x3
-
-#define KBD_KBSR_INTR		(1 << 0)
-#define KBD_KBSR_WAKEUP		(1 << 1)
-
-/* USB device controller */
-
-#define USBD_BASE		(IO_VIRT + 0x12000)
-#define USBD_LENGTH		0x3C
-
-#define USBD_GCTRL		0x00
-#define USBD_EPCTRL		0x04
-#define USBD_INTMASK		0x08
-#define USBD_INTSTAT		0x0C
-#define USBD_PWR		0x10
-#define USBD_DMARXTX		0x14
-#define USBD_DEVID		0x18
-#define USBD_DEVCLASS		0x1C
-#define USBD_INTCLASS		0x20
-#define USBD_SETUP0		0x24
-#define USBD_SETUP1		0x28
-#define USBD_ENDP0RD		0x2C
-#define USBD_ENDP0WT		0x30
-#define USBD_ENDP1RD		0x34
-#define USBD_ENDP2WT		0x38
-
-/* PS/2 port */
-#define PSDATA 0x00
-#define PSSTAT 0x04
-#define PSSTAT_TXEMPTY (1<<0)
-#define PSSTAT_TXBUSY (1<<1)
-#define PSSTAT_RXFULL (1<<2)
-#define PSSTAT_RXBUSY (1<<3)
-#define PSSTAT_CLKIN (1<<4)
-#define PSSTAT_DATAIN (1<<5)
-#define PSSTAT_PARITY (1<<6)
-
-#define PSCONF 0x08
-#define PSCONF_ENABLE (1<<0)
-#define PSCONF_TXINTEN (1<<2)
-#define PSCONF_RXINTEN (1<<3)
-#define PSCONF_FORCECLKLOW (1<<4)
-#define PSCONF_FORCEDATLOW (1<<5)
-#define PSCONF_LCE (1<<6)
-
-#define PSINTR 0x0C
-#define PSINTR_TXINT (1<<0)
-#define PSINTR_RXINT (1<<1)
-#define PSINTR_PAR (1<<2)
-#define PSINTR_RXTO (1<<3)
-#define PSINTR_TXTO (1<<4)
-
-#define PSTDLO 0x10 /* clk low before start transmission */
-#define PSTPRI 0x14 /* PRI clock */
-#define PSTXMT 0x18 /* maximum transmission time */
-#define PSTREC 0x20 /* maximum receive time */
-#define PSPWDN 0x3c
-
-/* ADC converter */
-#define ADC_BASE 		(IO_VIRT + 0x29000)
-#define ADC_CR 			0x00
-#define ADC_TSCTRL 		0x04
-#define ADC_BT_CTRL 		0x08
-#define ADC_MC_CTRL		0x0C
-#define ADC_STATUS		0x10
-
-/* ADC control register bits */
-#define ADC_CR_PW_CTRL 		0x80
-#define ADC_CR_DIRECTC		0x04
-#define ADC_CR_CONTIME_NO	0x00
-#define ADC_CR_CONTIME_2	0x04
-#define ADC_CR_CONTIME_4	0x08
-#define ADC_CR_CONTIME_ADE	0x0c
-#define ADC_CR_LONGCALTIME	0x01
-
-/* ADC touch panel register bits */
-#define ADC_TSCTRL_ENABLE 	0x80
-#define ADC_TSCTRL_INTR   	0x40
-#define	ADC_TSCTRL_SWBYPSS	0x20
-#define ADC_TSCTRL_SWINVT	0x10
-#define ADC_TSCTRL_S400   	0x03
-#define ADC_TSCTRL_S200   	0x02
-#define ADC_TSCTRL_S100   	0x01
-#define ADC_TSCTRL_S50    	0x00
-
-/* ADC Interrupt Status Register bits */
-#define ADC_STATUS_TS_BIT	0x80
-#define ADC_STATUS_MBT_BIT	0x40
-#define ADC_STATUS_BBT_BIT	0x20
-#define ADC_STATUS_MIC_BIT	0x10
-
-/* Touch data registers */
-#define ADC_TS_X0X1  		0x30
-#define ADC_TS_X2X3		0x34
-#define ADC_TS_Y0Y1		0x38
-#define ADC_TS_Y2Y3  		0x3c
-#define ADC_TS_X4X5  		0x40
-#define ADC_TS_X6X7  		0x44
-#define ADC_TS_Y4Y5		0x48
-#define ADC_TS_Y6Y7		0x50
-
-/* battery data */
-#define ADC_MB_DATA		0x54
-#define ADC_BB_DATA		0x58
-
-/* Sound data register */
-#define ADC_SD_DAT0 		0x60
-#define ADC_SD_DAT1		0x64
-#define ADC_SD_DAT2		0x68
-#define ADC_SD_DAT3		0x6c
-#define ADC_SD_DAT4		0x70
-#define ADC_SD_DAT5		0x74
-#define ADC_SD_DAT6		0x78
-#define ADC_SD_DAT7		0x7c
diff --git a/arch/arm/mach-h720x/include/mach/hardware.h b/arch/arm/mach-h720x/include/mach/hardware.h
deleted file mode 100644
index c55a52c..0000000
--- a/arch/arm/mach-h720x/include/mach/hardware.h
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * arch/arm/mach-h720x/include/mach/hardware.h
- *
- * Copyright (C) 2000 Jungjun Kim, Hynix Semiconductor Inc.
- *           (C) 2003 Thomas Gleixner <tglx@linutronix.de>
- *           (C) 2003 Robert Schwebel <r.schwebel@pengutronix.de>
- *
- * This file contains the hardware definitions of the h720x processors
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Do not add implementations specific defines here. This files contains
- * only defines of the onchip peripherals. Add those defines to boards.h,
- * which is included by this file.
- */
-
-#ifndef __ASM_ARCH_HARDWARE_H
-#define __ASM_ARCH_HARDWARE_H
-
-#define IOCLK (3686400L)
-
-/* Onchip peripherals */
-
-#define IO_VIRT			0xf0000000	/* IO peripherals */
-#define IO_PHYS			0x80000000
-#define IO_SIZE			0x00050000
-
-#ifdef CONFIG_CPU_H7202
-#include "h7202-regs.h"
-#elif defined CONFIG_CPU_H7201
-#include "h7201-regs.h"
-#else
-#error machine definition mismatch
-#endif
-
-/* Macro to access the CPU IO */
-#define CPU_IO(x) (*(volatile u32*)(x))
-
-/* Macro to access general purpose regs (base, offset) */
-#define CPU_REG(x,y) CPU_IO(x+y)
-
-/* Macro to access irq related regs */
-#define IRQ_REG(x) CPU_REG(IRQC_VIRT,x)
-
-/* CPU registers */
-/* general purpose I/O */
-#define GPIO_VIRT(x)		(IO_VIRT + 0x23000 + ((x)<<5))
-#define GPIO_A_VIRT		(GPIO_VIRT(0))
-#define GPIO_B_VIRT		(GPIO_VIRT(1))
-#define GPIO_C_VIRT		(GPIO_VIRT(2))
-#define GPIO_D_VIRT		(GPIO_VIRT(3))
-#define GPIO_E_VIRT		(GPIO_VIRT(4))
-#define GPIO_AMULSEL		(GPIO_VIRT(0) + 0xA4)
-
-#define AMULSEL_USIN2	(1<<5)
-#define AMULSEL_USOUT2	(1<<6)
-#define AMULSEL_USIN3	(1<<13)
-#define AMULSEL_USOUT3	(1<<14)
-#define AMULSEL_IRDIN	(1<<15)
-#define AMULSEL_IRDOUT	(1<<7)
-
-/* Register offsets general purpose I/O */
-#define GPIO_DATA		0x00
-#define GPIO_DIR		0x04
-#define GPIO_MASK		0x08
-#define GPIO_STAT		0x0C
-#define GPIO_EDGE		0x10
-#define GPIO_CLR		0x14
-#define GPIO_POL		0x18
-#define GPIO_EN			0x1C
-
-/*interrupt controller */
-#define IRQC_VIRT		(IO_VIRT + 0x24000)
-/* register offset interrupt controller */
-#define IRQC_IER		0x00
-#define IRQC_ISR		0x04
-
-/* timer unit */
-#define TIMER_VIRT		(IO_VIRT + 0x25000)
-/* Register offsets timer unit */
-#define TM0_PERIOD   		0x00
-#define TM0_COUNT    		0x08
-#define TM0_CTRL     		0x10
-#define TM1_PERIOD   		0x20
-#define TM1_COUNT    		0x28
-#define TM1_CTRL     		0x30
-#define TM2_PERIOD   		0x40
-#define TM2_COUNT    		0x48
-#define TM2_CTRL     		0x50
-#define TIMER_TOPCTRL		0x60
-#define TIMER_TOPSTAT		0x64
-#define T64_COUNTL		0x80
-#define T64_COUNTH		0x84
-#define T64_CTRL		0x88
-#define T64_BASEL		0x94
-#define T64_BASEH		0x98
-/* Bitmaks timer unit TOPSTAT reg */
-#define TSTAT_T0INT		0x1
-#define TSTAT_T1INT		0x2
-#define TSTAT_T2INT		0x4
-#define TSTAT_T3INT		0x8
-/* Bit description of TMx_CTRL register */
-#define TM_START  		0x1
-#define TM_REPEAT 		0x2
-#define TM_RESET  		0x4
-/* Bit description of TIMER_CTRL register */
-#define ENABLE_TM0_INTR  	0x1
-#define ENABLE_TM1_INTR  	0x2
-#define ENABLE_TM2_INTR  	0x4
-#define TIMER_ENABLE_BIT 	0x8
-#define ENABLE_TIMER64   	0x10
-#define ENABLE_TIMER64_INT	0x20
-
-/* PMU & PLL */
-#define PMU_BASE 		(IO_VIRT + 0x1000)
-#define PMU_MODE		0x00
-#define PMU_STAT   		0x20
-#define PMU_PLL_CTRL 		0x28
-
-/* PMU Mode bits */
-#define PMU_MODE_SLOW		0x00
-#define PMU_MODE_RUN		0x01
-#define PMU_MODE_IDLE		0x02
-#define PMU_MODE_SLEEP		0x03
-#define PMU_MODE_INIT		0x04
-#define PMU_MODE_DEEPSLEEP	0x07
-#define PMU_MODE_WAKEUP		0x08
-
-/* PMU ... */
-#define PLL_2_EN		0x8000
-#define PLL_1_EN		0x4000
-#define PLL_3_MUTE		0x0080
-
-/* Control bits for PMU/ PLL */
-#define PMU_WARMRESET		0x00010000
-#define PLL_CTRL_MASK23		0x000080ff
-
-/* LCD Controller */
-#define LCD_BASE 		(IO_VIRT + 0x10000)
-#define LCD_CTRL 		0x00
-#define LCD_STATUS		0x04
-#define LCD_STATUS_M		0x08
-#define LCD_INTERRUPT		0x0C
-#define LCD_DBAR		0x10
-#define LCD_DCAR		0x14
-#define LCD_TIMING0 		0x20
-#define LCD_TIMING1 		0x24
-#define LCD_TIMING2 		0x28
-#define LCD_TEST		0x40
-
-/* LCD Control Bits */
-#define LCD_CTRL_LCD_ENABLE   	0x00000001
-/* Bits per pixel */
-#define LCD_CTRL_LCD_BPP_MASK 	0x00000006
-#define LCD_CTRL_LCD_4BPP    	0x00000000
-#define LCD_CTRL_LCD_8BPP    	0x00000002
-#define LCD_CTRL_LCD_16BPP   	0x00000004
-#define LCD_CTRL_LCD_BW		0x00000008
-#define LCD_CTRL_LCD_TFT	0x00000010
-#define LCD_CTRL_BGR		0x00001000
-#define LCD_CTRL_LCD_VCOMP	0x00080000
-#define LCD_CTRL_LCD_MONO8	0x00200000
-#define LCD_CTRL_LCD_PWR	0x00400000
-#define LCD_CTRL_LCD_BLE	0x00800000
-#define LCD_CTRL_LDBUSEN	0x01000000
-
-/* Palette */
-#define LCD_PALETTE_BASE 	(IO_VIRT + 0x10400)
-
-/* Serial ports */
-#define SERIAL0_OFS		0x20000
-#define SERIAL0_VIRT 		(IO_VIRT + SERIAL0_OFS)
-#define SERIAL0_BASE		(IO_PHYS + SERIAL0_OFS)
-
-#define SERIAL1_OFS		0x21000
-#define SERIAL1_VIRT 		(IO_VIRT + SERIAL1_OFS)
-#define SERIAL1_BASE		(IO_PHYS + SERIAL1_OFS)
-
-#define SERIAL_ENABLE		0x30
-#define SERIAL_ENABLE_EN	(1<<0)
-
-/* General defines to pacify gcc */
-
-#define __ASM_ARCH_HARDWARE_INCMACH_H
-#include "boards.h"
-#undef __ASM_ARCH_HARDWARE_INCMACH_H
-
-#endif				/* __ASM_ARCH_HARDWARE_H */
diff --git a/arch/arm/mach-h720x/include/mach/irqs.h b/arch/arm/mach-h720x/include/mach/irqs.h
deleted file mode 100644
index 430a92b..0000000
--- a/arch/arm/mach-h720x/include/mach/irqs.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * arch/arm/mach-h720x/include/mach/irqs.h
- *
- * Copyright (C) 2000 Jungjun Kim
- *           (C) 2003 Robert Schwebel <r.schwebel@pengutronix.de>
- *           (C) 2003 Thomas Gleixner <tglx@linutronix.de>
- *
- */
-
-#ifndef __ASM_ARCH_IRQS_H
-#define __ASM_ARCH_IRQS_H
-
-#if defined (CONFIG_CPU_H7201)
-
-#define IRQ_PMU		0		/* 0x000001 */
-#define IRQ_DMA		1 		/* 0x000002 */
-#define IRQ_LCD		2		/* 0x000004 */
-#define IRQ_VGA		3 		/* 0x000008 */
-#define IRQ_PCMCIA1 	4 		/* 0x000010 */
-#define IRQ_PCMCIA2 	5 		/* 0x000020 */
-#define IRQ_AFE		6 		/* 0x000040 */
-#define IRQ_AIC		7 		/* 0x000080 */
-#define IRQ_KEYBOARD 	8 		/* 0x000100 */
-#define IRQ_TIMER0	9 		/* 0x000200 */
-#define IRQ_RTC		10		/* 0x000400 */
-#define IRQ_SOUND	11		/* 0x000800 */
-#define IRQ_USB		12		/* 0x001000 */
-#define IRQ_IrDA 	13		/* 0x002000 */
-#define IRQ_UART0	14		/* 0x004000 */
-#define IRQ_UART1	15		/* 0x008000 */
-#define IRQ_SPI		16		/* 0x010000 */
-#define IRQ_GPIOA 	17		/* 0x020000 */
-#define IRQ_GPIOB	18		/* 0x040000 */
-#define IRQ_GPIOC	19		/* 0x080000 */
-#define IRQ_GPIOD	20		/* 0x100000 */
-#define IRQ_CommRX	21		/* 0x200000 */
-#define IRQ_CommTX	22		/* 0x400000 */
-#define IRQ_Soft	23		/* 0x800000 */
-
-#define NR_GLBL_IRQS	24
-
-#define IRQ_CHAINED_GPIOA(x)  (NR_GLBL_IRQS + x)
-#define IRQ_CHAINED_GPIOB(x)  (IRQ_CHAINED_GPIOA(32) + x)
-#define IRQ_CHAINED_GPIOC(x)  (IRQ_CHAINED_GPIOB(32) + x)
-#define IRQ_CHAINED_GPIOD(x)  (IRQ_CHAINED_GPIOC(32) + x)
-#define NR_IRQS               IRQ_CHAINED_GPIOD(32)
-
-/* Enable mask for multiplexed interrupts */
-#define IRQ_ENA_MUX	(1<<IRQ_GPIOA) | (1<<IRQ_GPIOB) \
-			| (1<<IRQ_GPIOC) | (1<<IRQ_GPIOD)
-
-
-#elif defined (CONFIG_CPU_H7202)
-
-#define IRQ_PMU		0		/* 0x00000001 */
-#define IRQ_DMA		1		/* 0x00000002 */
-#define IRQ_LCD		2		/* 0x00000004 */
-#define IRQ_SOUND	3		/* 0x00000008 */
-#define IRQ_I2S		4		/* 0x00000010 */
-#define IRQ_USB 	5		/* 0x00000020 */
-#define IRQ_MMC 	6		/* 0x00000040 */
-#define IRQ_RTC 	7		/* 0x00000080 */
-#define IRQ_UART0 	8		/* 0x00000100 */
-#define IRQ_UART1 	9		/* 0x00000200 */
-#define IRQ_UART2 	10		/* 0x00000400 */
-#define IRQ_UART3 	11		/* 0x00000800 */
-#define IRQ_KBD 	12		/* 0x00001000 */
-#define IRQ_PS2 	13		/* 0x00002000 */
-#define IRQ_AIC 	14		/* 0x00004000 */
-#define IRQ_TIMER0 	15		/* 0x00008000 */
-#define IRQ_TIMERX 	16		/* 0x00010000 */
-#define IRQ_WDT 	17		/* 0x00020000 */
-#define IRQ_CAN0 	18		/* 0x00040000 */
-#define IRQ_CAN1 	19		/* 0x00080000 */
-#define IRQ_EXT0 	20		/* 0x00100000 */
-#define IRQ_EXT1 	21		/* 0x00200000 */
-#define IRQ_GPIOA 	22		/* 0x00400000 */
-#define IRQ_GPIOB 	23		/* 0x00800000 */
-#define IRQ_GPIOC 	24		/* 0x01000000 */
-#define IRQ_GPIOD 	25		/* 0x02000000 */
-#define IRQ_GPIOE 	26		/* 0x04000000 */
-#define IRQ_COMMRX 	27		/* 0x08000000 */
-#define IRQ_COMMTX 	28		/* 0x10000000 */
-#define IRQ_SMC 	29		/* 0x20000000 */
-#define IRQ_Soft 	30		/* 0x40000000 */
-#define IRQ_RESERVED1 	31		/* 0x80000000 */
-#define NR_GLBL_IRQS	32
-
-#define NR_TIMERX_IRQS	3
-
-#define IRQ_CHAINED_GPIOA(x)  (NR_GLBL_IRQS + x)
-#define IRQ_CHAINED_GPIOB(x)  (IRQ_CHAINED_GPIOA(32) + x)
-#define IRQ_CHAINED_GPIOC(x)  (IRQ_CHAINED_GPIOB(32) + x)
-#define IRQ_CHAINED_GPIOD(x)  (IRQ_CHAINED_GPIOC(32) + x)
-#define IRQ_CHAINED_GPIOE(x)  (IRQ_CHAINED_GPIOD(32) + x)
-#define IRQ_CHAINED_TIMERX(x) (IRQ_CHAINED_GPIOE(32) + x)
-#define IRQ_TIMER1            (IRQ_CHAINED_TIMERX(0))
-#define IRQ_TIMER2            (IRQ_CHAINED_TIMERX(1))
-#define IRQ_TIMER64B          (IRQ_CHAINED_TIMERX(2))
-
-#define NR_IRQS		(IRQ_CHAINED_TIMERX(NR_TIMERX_IRQS))
-
-/* Enable mask for multiplexed interrupts */
-#define IRQ_ENA_MUX	(1<<IRQ_TIMERX) | (1<<IRQ_GPIOA) | (1<<IRQ_GPIOB) | \
-			(1<<IRQ_GPIOC) 	| (1<<IRQ_GPIOD) | (1<<IRQ_GPIOE) | \
-			(1<<IRQ_TIMERX)
-
-#else
-#error cpu definition mismatch
-#endif
-
-/* decode irq number to register number */
-#define IRQ_TO_REGNO(irq) ((irq - NR_GLBL_IRQS) >> 5)
-#define IRQ_TO_BIT(irq) (1 << ((irq - NR_GLBL_IRQS) % 32))
-
-#endif
diff --git a/arch/arm/mach-h720x/include/mach/isa-dma.h b/arch/arm/mach-h720x/include/mach/isa-dma.h
deleted file mode 100644
index 3eafb3f..0000000
--- a/arch/arm/mach-h720x/include/mach/isa-dma.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * arch/arm/mach-h720x/include/mach/isa-dma.h
- *
- * Architecture DMA routes
- *
- * Copyright (C) 1997.1998 Russell King
- */
-#ifndef __ASM_ARCH_DMA_H
-#define __ASM_ARCH_DMA_H
-
-#if defined (CONFIG_CPU_H7201)
-#define MAX_DMA_CHANNELS	3
-#elif defined (CONFIG_CPU_H7202)
-#define MAX_DMA_CHANNELS	4
-#else
-#error processor definition missmatch
-#endif
-
-#endif /* __ASM_ARCH_DMA_H */
diff --git a/arch/arm/mach-h720x/include/mach/timex.h b/arch/arm/mach-h720x/include/mach/timex.h
deleted file mode 100644
index 3f2f447..0000000
--- a/arch/arm/mach-h720x/include/mach/timex.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * arch/arm/mach-h720x/include/mach/timex.h
- * Copyright (C) 2000 Jungjun Kim, Hynix Semiconductor Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __ASM_ARCH_TIMEX
-#define __ASM_ARCH_TIMEX
-
-#define CLOCK_TICK_RATE		3686400
-
-#endif
diff --git a/arch/arm/mach-h720x/include/mach/uncompress.h b/arch/arm/mach-h720x/include/mach/uncompress.h
deleted file mode 100644
index 43e343c..0000000
--- a/arch/arm/mach-h720x/include/mach/uncompress.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * arch/arm/mach-h720x/include/mach/uncompress.h
- *
- * Copyright (C) 2001-2002 Jungjun Kim
- */
-
-#ifndef __ASM_ARCH_UNCOMPRESS_H
-#define __ASM_ARCH_UNCOMPRESS_H
-
-#include <mach/hardware.h>
-
-#define LSR 	0x14
-#define TEMPTY 	0x40
-
-static inline void putc(int c)
-{
-	volatile unsigned char *p = (volatile unsigned char *)(IO_PHYS+0x20000);
-
-	/* wait until transmit buffer is empty */
-	while((p[LSR] & TEMPTY) == 0x0)
-		barrier();
-
-	/* write next character */
-	*p = c;
-}
-
-static inline void flush(void)
-{
-}
-
-/*
- * nothing to do
- */
-#define arch_decomp_setup()
-
-#endif
diff --git a/arch/arm/mach-highbank/highbank.c b/arch/arm/mach-highbank/highbank.c
index a4f9f50..76c1170 100644
--- a/arch/arm/mach-highbank/highbank.c
+++ b/arch/arm/mach-highbank/highbank.c
@@ -32,7 +32,6 @@
 #include <asm/cacheflush.h>
 #include <asm/cputype.h>
 #include <asm/smp_plat.h>
-#include <asm/smp_twd.h>
 #include <asm/hardware/arm_timer.h>
 #include <asm/hardware/timer-sp.h>
 #include <asm/hardware/cache-l2x0.h>
@@ -119,10 +118,10 @@ static void __init highbank_timer_init(void)
 	sp804_clocksource_and_sched_clock_init(timer_base + 0x20, "timer1");
 	sp804_clockevents_init(timer_base, irq, "timer0");
 
-	twd_local_timer_of_register();
-
 	arch_timer_of_register();
 	arch_timer_sched_clock_init();
+
+	clocksource_of_init();
 }
 
 static void highbank_power_off(void)
diff --git a/arch/arm/mach-highbank/platsmp.c b/arch/arm/mach-highbank/platsmp.c
index 8797a70..a984573 100644
--- a/arch/arm/mach-highbank/platsmp.c
+++ b/arch/arm/mach-highbank/platsmp.c
@@ -17,7 +17,6 @@
 #include <linux/init.h>
 #include <linux/smp.h>
 #include <linux/io.h>
-#include <linux/irqchip/arm-gic.h>
 
 #include <asm/smp_scu.h>
 
@@ -25,11 +24,6 @@
 
 extern void secondary_startup(void);
 
-static void __cpuinit highbank_secondary_init(unsigned int cpu)
-{
-	gic_secondary_init(0);
-}
-
 static int __cpuinit highbank_boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
 	highbank_set_cpu_jump(cpu, secondary_startup);
@@ -67,7 +61,6 @@ static void __init highbank_smp_prepare_cpus(unsigned int max_cpus)
 struct smp_operations highbank_smp_ops __initdata = {
 	.smp_init_cpus		= highbank_smp_init_cpus,
 	.smp_prepare_cpus	= highbank_smp_prepare_cpus,
-	.smp_secondary_init	= highbank_secondary_init,
 	.smp_boot_secondary	= highbank_boot_secondary,
 #ifdef CONFIG_HOTPLUG_CPU
 	.cpu_die		= highbank_cpu_die,
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 4c9c6f9..355d55c 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -65,6 +65,9 @@ config IRAM_ALLOC
 	bool
 	select GENERIC_ALLOCATOR
 
+config HAVE_IMX_ANATOP
+	bool
+
 config HAVE_IMX_GPC
 	bool
 
@@ -73,6 +76,7 @@ config HAVE_IMX_MMDC
 
 config HAVE_IMX_SRC
 	def_bool y if SMP
+	select ARCH_HAS_RESET_CONTROLLER
 
 config IMX_HAVE_IOMUX_V1
 	bool
@@ -128,6 +132,8 @@ config SOC_IMX25
 
 config SOC_IMX27
 	bool
+	select ARCH_HAS_CPUFREQ
+	select ARCH_HAS_OPP
 	select COMMON_CLK
 	select CPU_ARM926T
 	select IMX_HAVE_IOMUX_V1
@@ -155,6 +161,7 @@ config SOC_IMX35
 config SOC_IMX5
 	bool
 	select ARCH_HAS_CPUFREQ
+	select ARCH_HAS_OPP
 	select ARCH_MX5
 	select ARCH_MXC_IOMUX_V3
 	select COMMON_CLK
@@ -165,6 +172,7 @@ config	SOC_IMX51
 	bool
 	select ARCH_MX5
 	select ARCH_MX51
+	select HAVE_IMX_SRC
 	select PINCTRL
 	select PINCTRL_IMX51
 	select SOC_IMX5
@@ -792,6 +800,7 @@ config	SOC_IMX53
 	select ARCH_MX5
 	select ARCH_MX53
 	select HAVE_CAN_FLEXCAN if CAN
+	select HAVE_IMX_SRC
 	select IMX_HAVE_PLATFORM_IMX2_WDT
 	select PINCTRL
 	select PINCTRL_IMX53
@@ -801,7 +810,7 @@ config	SOC_IMX53
 	  This enables support for Freescale i.MX53 processor.
 
 config SOC_IMX6Q
-	bool "i.MX6 Quad support"
+	bool "i.MX6 Quad/DualLite support"
 	select ARCH_HAS_CPUFREQ
 	select ARCH_HAS_OPP
 	select ARM_CPU_SUSPEND if PM
@@ -813,6 +822,7 @@ config SOC_IMX6Q
 	select CPU_V7
 	select HAVE_ARM_SCU
 	select HAVE_CAN_FLEXCAN if CAN
+	select HAVE_IMX_ANATOP
 	select HAVE_IMX_GPC
 	select HAVE_IMX_MMDC
 	select HAVE_IMX_SRC
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index c4ce090..b16eb39 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -12,7 +12,7 @@ obj-$(CONFIG_SOC_IMX31) += mm-imx3.o cpu-imx31.o clk-imx31.o iomux-imx31.o ehci-
 obj-$(CONFIG_SOC_IMX35) += mm-imx3.o cpu-imx35.o clk-imx35.o ehci-imx35.o pm-imx3.o
 
 imx5-pm-$(CONFIG_PM) += pm-imx5.o
-obj-$(CONFIG_SOC_IMX5) += cpu-imx5.o mm-imx5.o clk-imx51-imx53.o ehci-imx5.o $(imx5-pm-y) cpu_op-mx51.o
+obj-$(CONFIG_SOC_IMX5) += cpu-imx5.o mm-imx5.o clk-imx51-imx53.o ehci-imx5.o $(imx5-pm-y)
 
 obj-$(CONFIG_COMMON_CLK) += clk-pllv1.o clk-pllv2.o clk-pllv3.o clk-gate2.o \
 			    clk-pfd.o clk-busy.o clk.o
@@ -27,7 +27,6 @@ obj-$(CONFIG_IRAM_ALLOC) += iram_alloc.o
 obj-$(CONFIG_MXC_ULPI) += ulpi.o
 obj-$(CONFIG_MXC_USE_EPIT) += epit.o
 obj-$(CONFIG_MXC_DEBUG_BOARD) += 3ds_debugboard.o
-obj-$(CONFIG_CPU_FREQ_IMX)    += cpufreq.o
 
 ifeq ($(CONFIG_CPU_IDLE),y)
 obj-y += cpuidle.o
@@ -92,6 +91,7 @@ obj-$(CONFIG_MACH_EUKREA_CPUIMX35SD) += mach-cpuimx35.o
 obj-$(CONFIG_MACH_EUKREA_MBIMXSD35_BASEBOARD) += eukrea_mbimxsd35-baseboard.o
 obj-$(CONFIG_MACH_VPR200) += mach-vpr200.o
 
+obj-$(CONFIG_HAVE_IMX_ANATOP) += anatop.o
 obj-$(CONFIG_HAVE_IMX_GPC) += gpc.o
 obj-$(CONFIG_HAVE_IMX_MMDC) += mmdc.o
 obj-$(CONFIG_HAVE_IMX_SRC) += src.o
diff --git a/arch/arm/mach-imx/Makefile.boot b/arch/arm/mach-imx/Makefile.boot
deleted file mode 100644
index 41ba1bb..0000000
--- a/arch/arm/mach-imx/Makefile.boot
+++ /dev/null
@@ -1,35 +0,0 @@
-zreladdr-$(CONFIG_SOC_IMX1)	+= 0x08008000
-params_phys-$(CONFIG_SOC_IMX1)	:= 0x08000100
-initrd_phys-$(CONFIG_SOC_IMX1)	:= 0x08800000
-
-zreladdr-$(CONFIG_SOC_IMX21)	+= 0xC0008000
-params_phys-$(CONFIG_SOC_IMX21)	:= 0xC0000100
-initrd_phys-$(CONFIG_SOC_IMX21)	:= 0xC0800000
-
-zreladdr-$(CONFIG_SOC_IMX25)	+= 0x80008000
-params_phys-$(CONFIG_SOC_IMX25)	:= 0x80000100
-initrd_phys-$(CONFIG_SOC_IMX25)	:= 0x80800000
-
-zreladdr-$(CONFIG_SOC_IMX27)	+= 0xA0008000
-params_phys-$(CONFIG_SOC_IMX27)	:= 0xA0000100
-initrd_phys-$(CONFIG_SOC_IMX27)	:= 0xA0800000
-
-zreladdr-$(CONFIG_SOC_IMX31)	+= 0x80008000
-params_phys-$(CONFIG_SOC_IMX31)	:= 0x80000100
-initrd_phys-$(CONFIG_SOC_IMX31)	:= 0x80800000
-
-zreladdr-$(CONFIG_SOC_IMX35)	+= 0x80008000
-params_phys-$(CONFIG_SOC_IMX35)	:= 0x80000100
-initrd_phys-$(CONFIG_SOC_IMX35)	:= 0x80800000
-
-zreladdr-$(CONFIG_SOC_IMX51)	+= 0x90008000
-params_phys-$(CONFIG_SOC_IMX51)	:= 0x90000100
-initrd_phys-$(CONFIG_SOC_IMX51)	:= 0x90800000
-
-zreladdr-$(CONFIG_SOC_IMX53)	+= 0x70008000
-params_phys-$(CONFIG_SOC_IMX53)	:= 0x70000100
-initrd_phys-$(CONFIG_SOC_IMX53)	:= 0x70800000
-
-zreladdr-$(CONFIG_SOC_IMX6Q)	+= 0x10008000
-params_phys-$(CONFIG_SOC_IMX6Q)	:= 0x10000100
-initrd_phys-$(CONFIG_SOC_IMX6Q)	:= 0x10800000
diff --git a/arch/arm/mach-imx/anatop.c b/arch/arm/mach-imx/anatop.c
new file mode 100644
index 0000000..0cfa07d
--- /dev/null
+++ b/arch/arm/mach-imx/anatop.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2013 Freescale Semiconductor, Inc.
+ *
+ * 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/err.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
+#include "common.h"
+
+#define REG_SET		0x4
+#define REG_CLR		0x8
+
+#define ANADIG_REG_2P5		0x130
+#define ANADIG_REG_CORE		0x140
+#define ANADIG_ANA_MISC0	0x150
+#define ANADIG_USB1_CHRG_DETECT	0x1b0
+#define ANADIG_USB2_CHRG_DETECT	0x210
+#define ANADIG_DIGPROG		0x260
+
+#define BM_ANADIG_REG_2P5_ENABLE_WEAK_LINREG	0x40000
+#define BM_ANADIG_REG_CORE_FET_ODRIVE		0x20000000
+#define BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG	0x1000
+#define BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B	0x80000
+#define BM_ANADIG_USB_CHRG_DETECT_EN_B		0x100000
+
+static struct regmap *anatop;
+
+static void imx_anatop_enable_weak2p5(bool enable)
+{
+	u32 reg, val;
+
+	regmap_read(anatop, ANADIG_ANA_MISC0, &val);
+
+	/* can only be enabled when stop_mode_config is clear. */
+	reg = ANADIG_REG_2P5;
+	reg += (enable && (val & BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG) == 0) ?
+		REG_SET : REG_CLR;
+	regmap_write(anatop, reg, BM_ANADIG_REG_2P5_ENABLE_WEAK_LINREG);
+}
+
+static void imx_anatop_enable_fet_odrive(bool enable)
+{
+	regmap_write(anatop, ANADIG_REG_CORE + (enable ? REG_SET : REG_CLR),
+		BM_ANADIG_REG_CORE_FET_ODRIVE);
+}
+
+void imx_anatop_pre_suspend(void)
+{
+	imx_anatop_enable_weak2p5(true);
+	imx_anatop_enable_fet_odrive(true);
+}
+
+void imx_anatop_post_resume(void)
+{
+	imx_anatop_enable_fet_odrive(false);
+	imx_anatop_enable_weak2p5(false);
+}
+
+void imx_anatop_usb_chrg_detect_disable(void)
+{
+	regmap_write(anatop, ANADIG_USB1_CHRG_DETECT,
+		BM_ANADIG_USB_CHRG_DETECT_EN_B
+		| BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B);
+	regmap_write(anatop, ANADIG_USB2_CHRG_DETECT,
+		BM_ANADIG_USB_CHRG_DETECT_EN_B |
+		BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B);
+}
+
+u32 imx_anatop_get_digprog(void)
+{
+	struct device_node *np;
+	void __iomem *anatop_base;
+	static u32 digprog;
+
+	if (digprog)
+		return digprog;
+
+	np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-anatop");
+	anatop_base = of_iomap(np, 0);
+	WARN_ON(!anatop_base);
+	digprog = readl_relaxed(anatop_base + ANADIG_DIGPROG);
+
+	return digprog;
+}
+
+void __init imx_anatop_init(void)
+{
+	anatop = syscon_regmap_lookup_by_compatible("fsl,imx6q-anatop");
+	if (IS_ERR(anatop)) {
+		pr_err("%s: failed to find imx6q-anatop regmap!\n", __func__);
+		return;
+	}
+}
diff --git a/arch/arm/mach-imx/avic.c b/arch/arm/mach-imx/avic.c
index 0eff23e..e163ec7 100644
--- a/arch/arm/mach-imx/avic.c
+++ b/arch/arm/mach-imx/avic.c
@@ -51,11 +51,9 @@
 
 #define AVIC_NUM_IRQS 64
 
-void __iomem *avic_base;
+static void __iomem *avic_base;
 static struct irq_domain *domain;
 
-static u32 avic_saved_mask_reg[2];
-
 #ifdef CONFIG_MXC_IRQ_PRIOR
 static int avic_irq_set_priority(unsigned char irq, unsigned char prio)
 {
@@ -113,6 +111,8 @@ static struct mxc_extra_irq avic_extra_irq = {
 };
 
 #ifdef CONFIG_PM
+static u32 avic_saved_mask_reg[2];
+
 static void avic_irq_suspend(struct irq_data *d)
 {
 	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
diff --git a/arch/arm/mach-imx/clk-busy.c b/arch/arm/mach-imx/clk-busy.c
index 1ab91b5..4bb1bc4 100644
--- a/arch/arm/mach-imx/clk-busy.c
+++ b/arch/arm/mach-imx/clk-busy.c
@@ -147,7 +147,7 @@ static int clk_busy_mux_set_parent(struct clk_hw *hw, u8 index)
 	return ret;
 }
 
-struct clk_ops clk_busy_mux_ops = {
+static struct clk_ops clk_busy_mux_ops = {
 	.get_parent = clk_busy_mux_get_parent,
 	.set_parent = clk_busy_mux_set_parent,
 };
@@ -169,7 +169,7 @@ struct clk *imx_clk_busy_mux(const char *name, void __iomem *reg, u8 shift,
 
 	busy->mux.reg = reg;
 	busy->mux.shift = shift;
-	busy->mux.width = width;
+	busy->mux.mask = BIT(width) - 1;
 	busy->mux.lock = &imx_ccm_lock;
 	busy->mux_ops = &clk_mux_ops;
 
diff --git a/arch/arm/mach-imx/clk-gate2.c b/arch/arm/mach-imx/clk-gate2.c
index cc49c7a..a63e415 100644
--- a/arch/arm/mach-imx/clk-gate2.c
+++ b/arch/arm/mach-imx/clk-gate2.c
@@ -15,6 +15,7 @@
 #include <linux/io.h>
 #include <linux/err.h>
 #include <linux/string.h>
+#include "clk.h"
 
 /**
  * DOC: basic gatable clock which can gate and ungate it's ouput
diff --git a/arch/arm/mach-imx/clk-imx27.c b/arch/arm/mach-imx/clk-imx27.c
index 30b3242..c3cfa41 100644
--- a/arch/arm/mach-imx/clk-imx27.c
+++ b/arch/arm/mach-imx/clk-imx27.c
@@ -86,10 +86,12 @@ enum mx27_clks {
 };
 
 static struct clk *clk[clk_max];
+static struct clk_onecell_data clk_data;
 
 int __init mx27_clocks_init(unsigned long fref)
 {
 	int i;
+	struct device_node *np;
 
 	clk[dummy] = imx_clk_fixed("dummy", 0);
 	clk[ckih] = imx_clk_fixed("ckih", fref);
@@ -198,6 +200,13 @@ int __init mx27_clocks_init(unsigned long fref)
 			pr_err("i.MX27 clk %d: register failed with %ld\n",
 				i, PTR_ERR(clk[i]));
 
+	np = of_find_compatible_node(NULL, NULL, "fsl,imx27-ccm");
+	if (np) {
+		clk_data.clks = clk;
+		clk_data.clk_num = ARRAY_SIZE(clk);
+		of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+	}
+
 	clk_register_clkdev(clk[uart1_ipg_gate], "ipg", "imx21-uart.0");
 	clk_register_clkdev(clk[per1_gate], "per", "imx21-uart.0");
 	clk_register_clkdev(clk[uart2_ipg_gate], "ipg", "imx21-uart.1");
@@ -276,10 +285,8 @@ int __init mx27_clocks_init(unsigned long fref)
 	clk_register_clkdev(clk[ata_ahb_gate], "ata", NULL);
 	clk_register_clkdev(clk[rtc_ipg_gate], NULL, "imx21-rtc");
 	clk_register_clkdev(clk[scc_ipg_gate], "scc", NULL);
-	clk_register_clkdev(clk[cpu_div], "cpu", NULL);
+	clk_register_clkdev(clk[cpu_div], NULL, "cpufreq-cpu0.0");
 	clk_register_clkdev(clk[emi_ahb_gate], "emi_ahb" , NULL);
-	clk_register_clkdev(clk[ssi1_baud_gate], "bitrate" , "imx-ssi.0");
-	clk_register_clkdev(clk[ssi2_baud_gate], "bitrate" , "imx-ssi.1");
 
 	mxc_timer_init(MX27_IO_ADDRESS(MX27_GPT1_BASE_ADDR), MX27_INT_GPT1);
 
diff --git a/arch/arm/mach-imx/clk-imx51-imx53.c b/arch/arm/mach-imx/clk-imx51-imx53.c
index 0f39f8c..1be5078 100644
--- a/arch/arm/mach-imx/clk-imx51-imx53.c
+++ b/arch/arm/mach-imx/clk-imx51-imx53.c
@@ -47,8 +47,32 @@ static const char *mx51_tve_ext_sel[] = { "osc", "ckih1", };
 static const char *mx53_tve_ext_sel[] = { "pll4_sw", "ckih1", };
 static const char *tve_sel[] = { "tve_pred", "tve_ext_sel", };
 static const char *ipu_sel[] = { "axi_a", "axi_b", "emi_slow_gate", "ahb", };
+static const char *gpu3d_sel[] = { "axi_a", "axi_b", "emi_slow_gate", "ahb" };
+static const char *gpu2d_sel[] = { "axi_a", "axi_b", "emi_slow_gate", "ahb" };
 static const char *vpu_sel[] = { "axi_a", "axi_b", "emi_slow_gate", "ahb", };
 static const char *mx53_can_sel[] = { "ipg", "ckih1", "ckih2", "lp_apm", };
+static const char *mx53_cko1_sel[] = {
+	"cpu_podf", "pll1_sw", "pll2_sw", "pll3_sw",
+	"emi_slow_podf", "pll4_sw", "nfc_podf", "dummy",
+	"di_pred", "dummy", "dummy", "ahb",
+	"ipg", "per_root", "ckil", "dummy",};
+static const char *mx53_cko2_sel[] = {
+	"dummy"/* dptc_core */, "dummy"/* dptc_perich */,
+	"dummy", "esdhc_a_podf",
+	"usboh3_podf", "dummy"/* wrck_clk_root */,
+	"ecspi_podf", "dummy"/* pll1_ref_clk */,
+	"esdhc_b_podf", "dummy"/* ddr_clk_root */,
+	"dummy"/* arm_axi_clk_root */, "dummy"/* usb_phy_out */,
+	"vpu_sel", "ipu_sel",
+	"osc", "ckih1",
+	"dummy", "esdhc_c_sel",
+	"ssi1_root_podf", "ssi2_root_podf",
+	"dummy", "dummy",
+	"dummy"/* lpsr_clk_root */, "dummy"/* pgc_clk_root */,
+	"dummy"/* tve_out */, "usb_phy_sel",
+	"tve_sel", "lp_apm",
+	"uart_root", "dummy"/* spdif0_clk_root */,
+	"dummy", "dummy", };
 
 enum imx5_clks {
 	dummy, ckil, osc, ckih1, ckih2, ahb, ipg, axi_a, axi_b, uart_pred,
@@ -83,7 +107,10 @@ enum imx5_clks {
 	ssi2_root_gate, ssi3_root_gate, ssi_ext1_gate, ssi_ext2_gate,
 	epit1_ipg_gate, epit1_hf_gate, epit2_ipg_gate, epit2_hf_gate,
 	can_sel, can1_serial_gate, can1_ipg_gate,
-	owire_gate,
+	owire_gate, gpu3d_s, gpu2d_s, gpu3d_gate, gpu2d_gate, garb_gate,
+	cko1_sel, cko1_podf, cko1,
+	cko2_sel, cko2_podf, cko2,
+	srtc_gate, pata_gate,
 	clk_max
 };
 
@@ -200,6 +227,11 @@ static void __init mx5_clocks_common_init(unsigned long rate_ckil,
 	clk[nfc_gate] = imx_clk_gate2("nfc_gate", "nfc_podf", MXC_CCM_CCGR5, 20);
 	clk[ipu_di0_gate] = imx_clk_gate2("ipu_di0_gate", "ipu_di0_sel", MXC_CCM_CCGR6, 10);
 	clk[ipu_di1_gate] = imx_clk_gate2("ipu_di1_gate", "ipu_di1_sel", MXC_CCM_CCGR6, 12);
+	clk[gpu3d_s] = imx_clk_mux("gpu3d_sel", MXC_CCM_CBCMR, 4, 2, gpu3d_sel, ARRAY_SIZE(gpu3d_sel));
+	clk[gpu2d_s] = imx_clk_mux("gpu2d_sel", MXC_CCM_CBCMR, 16, 2, gpu2d_sel, ARRAY_SIZE(gpu2d_sel));
+	clk[gpu3d_gate] = imx_clk_gate2("gpu3d_gate", "gpu3d_sel", MXC_CCM_CCGR5, 2);
+	clk[garb_gate] = imx_clk_gate2("garb_gate", "axi_a", MXC_CCM_CCGR5, 4);
+	clk[gpu2d_gate] = imx_clk_gate2("gpu2d_gate", "gpu2d_sel", MXC_CCM_CCGR6, 14);
 	clk[vpu_s] = imx_clk_mux("vpu_sel", MXC_CCM_CBCMR, 14, 2, vpu_sel, ARRAY_SIZE(vpu_sel));
 	clk[vpu_gate] = imx_clk_gate2("vpu_gate", "vpu_sel", MXC_CCM_CCGR5, 6);
 	clk[vpu_reference_gate] = imx_clk_gate2("vpu_reference_gate", "osc", MXC_CCM_CCGR5, 8);
@@ -235,6 +267,8 @@ static void __init mx5_clocks_common_init(unsigned long rate_ckil,
 	clk[epit2_ipg_gate] = imx_clk_gate2("epit2_ipg_gate", "ipg", MXC_CCM_CCGR2, 6);
 	clk[epit2_hf_gate] = imx_clk_gate2("epit2_hf_gate", "per_root", MXC_CCM_CCGR2, 8);
 	clk[owire_gate] = imx_clk_gate2("owire_gate", "per_root", MXC_CCM_CCGR2, 22);
+	clk[srtc_gate] = imx_clk_gate2("srtc_gate", "per_root", MXC_CCM_CCGR4, 28);
+	clk[pata_gate] = imx_clk_gate2("pata_gate", "ipg", MXC_CCM_CCGR4, 0);
 
 	for (i = 0; i < ARRAY_SIZE(clk); i++)
 		if (IS_ERR(clk[i]))
@@ -281,7 +315,7 @@ static void __init mx5_clocks_common_init(unsigned long rate_ckil,
 	clk_register_clkdev(clk[ssi_ext1_gate], "ssi_ext1", NULL);
 	clk_register_clkdev(clk[ssi_ext2_gate], "ssi_ext2", NULL);
 	clk_register_clkdev(clk[sdma_gate], NULL, "imx35-sdma");
-	clk_register_clkdev(clk[cpu_podf], "cpu", NULL);
+	clk_register_clkdev(clk[cpu_podf], NULL, "cpufreq-cpu0.0");
 	clk_register_clkdev(clk[iim_gate], "iim", NULL);
 	clk_register_clkdev(clk[dummy], NULL, "imx2-wdt.0");
 	clk_register_clkdev(clk[dummy], NULL, "imx2-wdt.1");
@@ -362,9 +396,6 @@ int __init mx51_clocks_init(unsigned long rate_ckil, unsigned long rate_osc,
 	clk_register_clkdev(clk[mx51_mipi], "mipi_hsp", NULL);
 	clk_register_clkdev(clk[vpu_gate], NULL, "imx51-vpu.0");
 	clk_register_clkdev(clk[fec_gate], NULL, "imx27-fec.0");
-	clk_register_clkdev(clk[ipu_gate], "bus", "40000000.ipu");
-	clk_register_clkdev(clk[ipu_di0_gate], "di0", "40000000.ipu");
-	clk_register_clkdev(clk[ipu_di1_gate], "di1", "40000000.ipu");
 	clk_register_clkdev(clk[usb_phy_gate], "phy", "mxc-ehci.0");
 	clk_register_clkdev(clk[esdhc1_ipg_gate], "ipg", "sdhci-esdhc-imx51.0");
 	clk_register_clkdev(clk[dummy], "ahb", "sdhci-esdhc-imx51.0");
@@ -423,15 +454,15 @@ int __init mx53_clocks_init(unsigned long rate_ckil, unsigned long rate_osc,
 	clk[pll3_sw] = imx_clk_pllv2("pll3_sw", "osc", MX53_DPLL3_BASE);
 	clk[pll4_sw] = imx_clk_pllv2("pll4_sw", "osc", MX53_DPLL4_BASE);
 
-	clk[ldb_di1_sel] = imx_clk_mux("ldb_di1_sel", MXC_CCM_CSCMR2, 9, 1,
-				mx53_ldb_di1_sel, ARRAY_SIZE(mx53_ldb_di1_sel));
 	clk[ldb_di1_div_3_5] = imx_clk_fixed_factor("ldb_di1_div_3_5", "ldb_di1_sel", 2, 7);
-	clk[ldb_di1_div] = imx_clk_divider("ldb_di1_div", "ldb_di1_div_3_5", MXC_CCM_CSCMR2, 11, 1);
+	clk[ldb_di1_div] = imx_clk_divider_flags("ldb_di1_div", "ldb_di1_div_3_5", MXC_CCM_CSCMR2, 11, 1, 0);
+	clk[ldb_di1_sel] = imx_clk_mux_flags("ldb_di1_sel", MXC_CCM_CSCMR2, 9, 1,
+				mx53_ldb_di1_sel, ARRAY_SIZE(mx53_ldb_di1_sel), CLK_SET_RATE_PARENT);
 	clk[di_pll4_podf] = imx_clk_divider("di_pll4_podf", "pll4_sw", MXC_CCM_CDCDR, 16, 3);
-	clk[ldb_di0_sel] = imx_clk_mux("ldb_di0_sel", MXC_CCM_CSCMR2, 8, 1,
-				mx53_ldb_di0_sel, ARRAY_SIZE(mx53_ldb_di0_sel));
 	clk[ldb_di0_div_3_5] = imx_clk_fixed_factor("ldb_di0_div_3_5", "ldb_di0_sel", 2, 7);
-	clk[ldb_di0_div] = imx_clk_divider("ldb_di0_div", "ldb_di0_div_3_5", MXC_CCM_CSCMR2, 10, 1);
+	clk[ldb_di0_div] = imx_clk_divider_flags("ldb_di0_div", "ldb_di0_div_3_5", MXC_CCM_CSCMR2, 10, 1, 0);
+	clk[ldb_di0_sel] = imx_clk_mux_flags("ldb_di0_sel", MXC_CCM_CSCMR2, 8, 1,
+				mx53_ldb_di0_sel, ARRAY_SIZE(mx53_ldb_di0_sel), CLK_SET_RATE_PARENT);
 	clk[ldb_di0_gate] = imx_clk_gate2("ldb_di0_gate", "ldb_di0_div", MXC_CCM_CCGR6, 28);
 	clk[ldb_di1_gate] = imx_clk_gate2("ldb_di1_gate", "ldb_di1_div", MXC_CCM_CCGR6, 30);
 	clk[ipu_di0_sel] = imx_clk_mux("ipu_di0_sel", MXC_CCM_CSCMR2, 26, 3,
@@ -456,6 +487,16 @@ int __init mx53_clocks_init(unsigned long rate_ckil, unsigned long rate_osc,
 	clk[can2_ipg_gate] = imx_clk_gate2("can2_ipg_gate", "ipg", MXC_CCM_CCGR4, 6);
 	clk[i2c3_gate] = imx_clk_gate2("i2c3_gate", "per_root", MXC_CCM_CCGR1, 22);
 
+	clk[cko1_sel] = imx_clk_mux("cko1_sel", MXC_CCM_CCOSR, 0, 4,
+				mx53_cko1_sel, ARRAY_SIZE(mx53_cko1_sel));
+	clk[cko1_podf] = imx_clk_divider("cko1_podf", "cko1_sel", MXC_CCM_CCOSR, 4, 3);
+	clk[cko1] = imx_clk_gate2("cko1", "cko1_podf", MXC_CCM_CCOSR, 7);
+
+	clk[cko2_sel] = imx_clk_mux("cko2_sel", MXC_CCM_CCOSR, 16, 5,
+				mx53_cko2_sel, ARRAY_SIZE(mx53_cko2_sel));
+	clk[cko2_podf] = imx_clk_divider("cko2_podf", "cko2_sel", MXC_CCM_CCOSR, 21, 3);
+	clk[cko2] = imx_clk_gate2("cko2", "cko2_podf", MXC_CCM_CCOSR, 24);
+
 	for (i = 0; i < ARRAY_SIZE(clk); i++)
 		if (IS_ERR(clk[i]))
 			pr_err("i.MX53 clk %d: register failed with %ld\n",
@@ -471,10 +512,6 @@ int __init mx53_clocks_init(unsigned long rate_ckil, unsigned long rate_osc,
 	clk_register_clkdev(clk[vpu_gate], NULL, "imx53-vpu.0");
 	clk_register_clkdev(clk[i2c3_gate], NULL, "imx21-i2c.2");
 	clk_register_clkdev(clk[fec_gate], NULL, "imx25-fec.0");
-	clk_register_clkdev(clk[ipu_gate], "bus", "18000000.ipu");
-	clk_register_clkdev(clk[ipu_di0_gate], "di0", "18000000.ipu");
-	clk_register_clkdev(clk[ipu_di1_gate], "di1", "18000000.ipu");
-	clk_register_clkdev(clk[ipu_gate], "hsp", "18000000.ipu");
 	clk_register_clkdev(clk[usb_phy1_gate], "usb_phy1", "mxc-ehci.0");
 	clk_register_clkdev(clk[esdhc1_ipg_gate], "ipg", "sdhci-esdhc-imx53.0");
 	clk_register_clkdev(clk[dummy], "ahb", "sdhci-esdhc-imx53.0");
diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c
index 2f9ff93..65319d5 100644
--- a/arch/arm/mach-imx/clk-imx6q.c
+++ b/arch/arm/mach-imx/clk-imx6q.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011-2013 Freescale Semiconductor, Inc.
  * Copyright 2011 Linaro Ltd.
  *
  * The code contained herein is licensed under the GNU General Public
@@ -14,6 +14,7 @@
 #include <linux/types.h>
 #include <linux/clk.h>
 #include <linux/clkdev.h>
+#include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/io.h>
 #include <linux/of.h>
@@ -22,6 +23,12 @@
 
 #include "clk.h"
 #include "common.h"
+#include "hardware.h"
+
+#define CCR				0x0
+#define BM_CCR_WB_COUNT			(0x7 << 16)
+#define BM_CCR_RBC_BYPASS_COUNT		(0x3f << 21)
+#define BM_CCR_RBC_EN			(0x1 << 27)
 
 #define CCGR0				0x68
 #define CCGR1				0x6c
@@ -67,6 +74,67 @@ void imx6q_set_chicken_bit(void)
 	writel_relaxed(val, ccm_base + CGPR);
 }
 
+static void imx6q_enable_rbc(bool enable)
+{
+	u32 val;
+	static bool last_rbc_mode;
+
+	if (last_rbc_mode == enable)
+		return;
+	/*
+	 * need to mask all interrupts in GPC before
+	 * operating RBC configurations
+	 */
+	imx_gpc_mask_all();
+
+	/* configure RBC enable bit */
+	val = readl_relaxed(ccm_base + CCR);
+	val &= ~BM_CCR_RBC_EN;
+	val |= enable ? BM_CCR_RBC_EN : 0;
+	writel_relaxed(val, ccm_base + CCR);
+
+	/* configure RBC count */
+	val = readl_relaxed(ccm_base + CCR);
+	val &= ~BM_CCR_RBC_BYPASS_COUNT;
+	val |= enable ? BM_CCR_RBC_BYPASS_COUNT : 0;
+	writel(val, ccm_base + CCR);
+
+	/*
+	 * need to delay at least 2 cycles of CKIL(32K)
+	 * due to hardware design requirement, which is
+	 * ~61us, here we use 65us for safe
+	 */
+	udelay(65);
+
+	/* restore GPC interrupt mask settings */
+	imx_gpc_restore_all();
+
+	last_rbc_mode = enable;
+}
+
+static void imx6q_enable_wb(bool enable)
+{
+	u32 val;
+	static bool last_wb_mode;
+
+	if (last_wb_mode == enable)
+		return;
+
+	/* configure well bias enable bit */
+	val = readl_relaxed(ccm_base + CLPCR);
+	val &= ~BM_CLPCR_WB_PER_AT_LPM;
+	val |= enable ? BM_CLPCR_WB_PER_AT_LPM : 0;
+	writel_relaxed(val, ccm_base + CLPCR);
+
+	/* configure well bias count */
+	val = readl_relaxed(ccm_base + CCR);
+	val &= ~BM_CCR_WB_COUNT;
+	val |= enable ? BM_CCR_WB_COUNT : 0;
+	writel_relaxed(val, ccm_base + CCR);
+
+	last_wb_mode = enable;
+}
+
 int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode)
 {
 	u32 val = readl_relaxed(ccm_base + CLPCR);
@@ -74,6 +142,8 @@ int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode)
 	val &= ~BM_CLPCR_LPM;
 	switch (mode) {
 	case WAIT_CLOCKED:
+		imx6q_enable_wb(false);
+		imx6q_enable_rbc(false);
 		break;
 	case WAIT_UNCLOCKED:
 		val |= 0x1 << BP_CLPCR_LPM;
@@ -92,6 +162,8 @@ int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode)
 		val |= 0x3 << BP_CLPCR_STBY_COUNT;
 		val |= BM_CLPCR_VSTBY;
 		val |= BM_CLPCR_SBYOS;
+		imx6q_enable_wb(true);
+		imx6q_enable_rbc(true);
 		break;
 	default:
 		return -EINVAL;
@@ -109,29 +181,29 @@ static const char *periph_clk2_sels[]	= { "pll3_usb_otg", "osc", };
 static const char *periph_sels[]	= { "periph_pre", "periph_clk2", };
 static const char *periph2_sels[]	= { "periph2_pre", "periph2_clk2", };
 static const char *axi_sels[]		= { "periph", "pll2_pfd2_396m", "pll3_pfd1_540m", };
-static const char *audio_sels[]	= { "pll4_audio", "pll3_pfd2_508m", "pll3_pfd3_454m", "pll3_usb_otg", };
+static const char *audio_sels[]	= { "pll4_post_div", "pll3_pfd2_508m", "pll3_pfd3_454m", "pll3_usb_otg", };
 static const char *gpu_axi_sels[]	= { "axi", "ahb", };
 static const char *gpu2d_core_sels[]	= { "axi", "pll3_usb_otg", "pll2_pfd0_352m", "pll2_pfd2_396m", };
 static const char *gpu3d_core_sels[]	= { "mmdc_ch0_axi", "pll3_usb_otg", "pll2_pfd1_594m", "pll2_pfd2_396m", };
 static const char *gpu3d_shader_sels[] = { "mmdc_ch0_axi", "pll3_usb_otg", "pll2_pfd1_594m", "pll2_pfd9_720m", };
 static const char *ipu_sels[]		= { "mmdc_ch0_axi", "pll2_pfd2_396m", "pll3_120m", "pll3_pfd1_540m", };
-static const char *ldb_di_sels[]	= { "pll5_video", "pll2_pfd0_352m", "pll2_pfd2_396m", "mmdc_ch1_axi", "pll3_pfd1_540m", };
-static const char *ipu_di_pre_sels[]	= { "mmdc_ch0_axi", "pll3_usb_otg", "pll5_video", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll3_pfd1_540m", };
+static const char *ldb_di_sels[]	= { "pll5_video_div", "pll2_pfd0_352m", "pll2_pfd2_396m", "mmdc_ch1_axi", "pll3_pfd1_540m", };
+static const char *ipu_di_pre_sels[]	= { "mmdc_ch0_axi", "pll3_usb_otg", "pll5_video_div", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll3_pfd1_540m", };
 static const char *ipu1_di0_sels[]	= { "ipu1_di0_pre", "dummy", "dummy", "ldb_di0", "ldb_di1", };
 static const char *ipu1_di1_sels[]	= { "ipu1_di1_pre", "dummy", "dummy", "ldb_di0", "ldb_di1", };
 static const char *ipu2_di0_sels[]	= { "ipu2_di0_pre", "dummy", "dummy", "ldb_di0", "ldb_di1", };
 static const char *ipu2_di1_sels[]	= { "ipu2_di1_pre", "dummy", "dummy", "ldb_di0", "ldb_di1", };
 static const char *hsi_tx_sels[]	= { "pll3_120m", "pll2_pfd2_396m", };
 static const char *pcie_axi_sels[]	= { "axi", "ahb", };
-static const char *ssi_sels[]		= { "pll3_pfd2_508m", "pll3_pfd3_454m", "pll4_audio", };
+static const char *ssi_sels[]		= { "pll3_pfd2_508m", "pll3_pfd3_454m", "pll4_post_div", };
 static const char *usdhc_sels[]	= { "pll2_pfd2_396m", "pll2_pfd0_352m", };
 static const char *enfc_sels[]	= { "pll2_pfd0_352m", "pll2_bus", "pll3_usb_otg", "pll2_pfd2_396m", };
 static const char *emi_sels[]		= { "axi", "pll3_usb_otg", "pll2_pfd2_396m", "pll2_pfd0_352m", };
 static const char *vdo_axi_sels[]	= { "axi", "ahb", };
 static const char *vpu_axi_sels[]	= { "axi", "pll2_pfd2_396m", "pll2_pfd0_352m", };
-static const char *cko1_sels[]	= { "pll3_usb_otg", "pll2_bus", "pll1_sys", "pll5_video",
+static const char *cko1_sels[]	= { "pll3_usb_otg", "pll2_bus", "pll1_sys", "pll5_video_div",
 				    "dummy", "axi", "enfc", "ipu1_di0", "ipu1_di1", "ipu2_di0",
-				    "ipu2_di1", "ahb", "ipg", "ipg_per", "ckil", "pll4_audio", };
+				    "ipu2_di1", "ahb", "ipg", "ipg_per", "ckil", "pll4_post_div", };
 
 enum mx6q_clks {
 	dummy, ckil, ckih, osc, pll2_pfd0_352m, pll2_pfd1_594m, pll2_pfd2_396m,
@@ -165,7 +237,7 @@ enum mx6q_clks {
 	pll4_audio, pll5_video, pll8_mlb, pll7_usb_host, pll6_enet, ssi1_ipg,
 	ssi2_ipg, ssi3_ipg, rom, usbphy1, usbphy2, ldb_di0_div_3_5, ldb_di1_div_3_5,
 	sata_ref, sata_ref_100m, pcie_ref, pcie_ref_125m, enet_ref, usbphy1_gate,
-	usbphy2_gate, clk_max
+	usbphy2_gate, pll4_post_div, pll5_post_div, pll5_video_div, clk_max
 };
 
 static struct clk *clk[clk_max];
@@ -182,6 +254,21 @@ static struct clk_div_table clk_enet_ref_table[] = {
 	{ .val = 3, .div = 4, },
 };
 
+static struct clk_div_table post_div_table[] = {
+	{ .val = 2, .div = 1, },
+	{ .val = 1, .div = 2, },
+	{ .val = 0, .div = 4, },
+	{ }
+};
+
+static struct clk_div_table video_div_table[] = {
+	{ .val = 0, .div = 1, },
+	{ .val = 1, .div = 2, },
+	{ .val = 2, .div = 1, },
+	{ .val = 3, .div = 4, },
+	{ }
+};
+
 int __init mx6q_clocks_init(void)
 {
 	struct device_node *np;
@@ -208,6 +295,14 @@ int __init mx6q_clocks_init(void)
 	base = of_iomap(np, 0);
 	WARN_ON(!base);
 
+	/* Audio/video PLL post dividers do not work on i.MX6q revision 1.0 */
+	if (cpu_is_imx6q() && imx6q_revision() == IMX_CHIP_REVISION_1_0) {
+		post_div_table[1].div = 1;
+		post_div_table[2].div = 1;
+		video_div_table[1].div = 1;
+		video_div_table[2].div = 1;
+	};
+
 	/*                   type                               name         parent_name  base     div_mask */
 	clk[pll1_sys]      = imx_clk_pllv3(IMX_PLLV3_SYS,	"pll1_sys",	"osc", base,        0x7f);
 	clk[pll2_bus]      = imx_clk_pllv3(IMX_PLLV3_GENERIC,	"pll2_bus",	"osc", base + 0x30, 0x1);
@@ -260,6 +355,10 @@ int __init mx6q_clocks_init(void)
 	clk[pll3_60m]  = imx_clk_fixed_factor("pll3_60m",  "pll3_usb_otg",   1, 8);
 	clk[twd]       = imx_clk_fixed_factor("twd",       "arm",            1, 2);
 
+	clk[pll4_post_div] = clk_register_divider_table(NULL, "pll4_post_div", "pll4_audio", CLK_SET_RATE_PARENT, base + 0x70, 19, 2, 0, post_div_table, &imx_ccm_lock);
+	clk[pll5_post_div] = clk_register_divider_table(NULL, "pll5_post_div", "pll5_video", CLK_SET_RATE_PARENT, base + 0xa0, 19, 2, 0, post_div_table, &imx_ccm_lock);
+	clk[pll5_video_div] = clk_register_divider_table(NULL, "pll5_video_div", "pll5_post_div", CLK_SET_RATE_PARENT, base + 0x170, 30, 2, 0, video_div_table, &imx_ccm_lock);
+
 	np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-ccm");
 	base = of_iomap(np, 0);
 	WARN_ON(!base);
@@ -283,8 +382,8 @@ int __init mx6q_clocks_init(void)
 	clk[gpu3d_shader_sel] = imx_clk_mux("gpu3d_shader_sel", base + 0x18, 8,  2, gpu3d_shader_sels, ARRAY_SIZE(gpu3d_shader_sels));
 	clk[ipu1_sel]         = imx_clk_mux("ipu1_sel",         base + 0x3c, 9,  2, ipu_sels,          ARRAY_SIZE(ipu_sels));
 	clk[ipu2_sel]         = imx_clk_mux("ipu2_sel",         base + 0x3c, 14, 2, ipu_sels,          ARRAY_SIZE(ipu_sels));
-	clk[ldb_di0_sel]      = imx_clk_mux("ldb_di0_sel",      base + 0x2c, 9,  3, ldb_di_sels,       ARRAY_SIZE(ldb_di_sels));
-	clk[ldb_di1_sel]      = imx_clk_mux("ldb_di1_sel",      base + 0x2c, 12, 3, ldb_di_sels,       ARRAY_SIZE(ldb_di_sels));
+	clk[ldb_di0_sel]      = imx_clk_mux_flags("ldb_di0_sel", base + 0x2c, 9,  3, ldb_di_sels,      ARRAY_SIZE(ldb_di_sels), CLK_SET_RATE_PARENT);
+	clk[ldb_di1_sel]      = imx_clk_mux_flags("ldb_di1_sel", base + 0x2c, 12, 3, ldb_di_sels,      ARRAY_SIZE(ldb_di_sels), CLK_SET_RATE_PARENT);
 	clk[ipu1_di0_pre_sel] = imx_clk_mux("ipu1_di0_pre_sel", base + 0x34, 6,  3, ipu_di_pre_sels,   ARRAY_SIZE(ipu_di_pre_sels));
 	clk[ipu1_di1_pre_sel] = imx_clk_mux("ipu1_di1_pre_sel", base + 0x34, 15, 3, ipu_di_pre_sels,   ARRAY_SIZE(ipu_di_pre_sels));
 	clk[ipu2_di0_pre_sel] = imx_clk_mux("ipu2_di0_pre_sel", base + 0x38, 6,  3, ipu_di_pre_sels,   ARRAY_SIZE(ipu_di_pre_sels));
@@ -332,9 +431,9 @@ int __init mx6q_clocks_init(void)
 	clk[ipu1_podf]        = imx_clk_divider("ipu1_podf",        "ipu1_sel",          base + 0x3c, 11, 3);
 	clk[ipu2_podf]        = imx_clk_divider("ipu2_podf",        "ipu2_sel",          base + 0x3c, 16, 3);
 	clk[ldb_di0_div_3_5]  = imx_clk_fixed_factor("ldb_di0_div_3_5", "ldb_di0_sel", 2, 7);
-	clk[ldb_di0_podf]     = imx_clk_divider("ldb_di0_podf",     "ldb_di0_div_3_5",       base + 0x20, 10, 1);
+	clk[ldb_di0_podf]     = imx_clk_divider_flags("ldb_di0_podf", "ldb_di0_div_3_5", base + 0x20, 10, 1, 0);
 	clk[ldb_di1_div_3_5]  = imx_clk_fixed_factor("ldb_di1_div_3_5", "ldb_di1_sel", 2, 7);
-	clk[ldb_di1_podf]     = imx_clk_divider("ldb_di1_podf",     "ldb_di1_div_3_5",   base + 0x20, 11, 1);
+	clk[ldb_di1_podf]     = imx_clk_divider_flags("ldb_di1_podf", "ldb_di1_div_3_5", base + 0x20, 11, 1, 0);
 	clk[ipu1_di0_pre]     = imx_clk_divider("ipu1_di0_pre",     "ipu1_di0_pre_sel",  base + 0x34, 3,  3);
 	clk[ipu1_di1_pre]     = imx_clk_divider("ipu1_di1_pre",     "ipu1_di1_pre_sel",  base + 0x34, 12, 3);
 	clk[ipu2_di0_pre]     = imx_clk_divider("ipu2_di0_pre",     "ipu2_di0_pre_sel",  base + 0x38, 3,  3);
@@ -449,6 +548,11 @@ int __init mx6q_clocks_init(void)
 	clk_register_clkdev(clk[cko1], "cko1", NULL);
 	clk_register_clkdev(clk[arm], NULL, "cpu0");
 
+	if (imx6q_revision() != IMX_CHIP_REVISION_1_0) {
+		clk_set_parent(clk[ldb_di0_sel], clk[pll5_video_div]);
+		clk_set_parent(clk[ldb_di1_sel], clk[pll5_video_div]);
+	}
+
 	/*
 	 * The gpmi needs 100MHz frequency in the EDO/Sync mode,
 	 * We can not get the 100MHz from the pll2_pfd0_352m.
diff --git a/arch/arm/mach-imx/clk-pllv1.c b/arch/arm/mach-imx/clk-pllv1.c
index abff350..c1eaee3 100644
--- a/arch/arm/mach-imx/clk-pllv1.c
+++ b/arch/arm/mach-imx/clk-pllv1.c
@@ -78,7 +78,7 @@ static unsigned long clk_pllv1_recalc_rate(struct clk_hw *hw,
 	return ll;
 }
 
-struct clk_ops clk_pllv1_ops = {
+static struct clk_ops clk_pllv1_ops = {
 	.recalc_rate = clk_pllv1_recalc_rate,
 };
 
diff --git a/arch/arm/mach-imx/clk-pllv2.c b/arch/arm/mach-imx/clk-pllv2.c
index 0440379..20889d5 100644
--- a/arch/arm/mach-imx/clk-pllv2.c
+++ b/arch/arm/mach-imx/clk-pllv2.c
@@ -229,7 +229,7 @@ static void clk_pllv2_unprepare(struct clk_hw *hw)
 	__raw_writel(reg, pllbase + MXC_PLL_DP_CTL);
 }
 
-struct clk_ops clk_pllv2_ops = {
+static struct clk_ops clk_pllv2_ops = {
 	.prepare = clk_pllv2_prepare,
 	.unprepare = clk_pllv2_unprepare,
 	.recalc_rate = clk_pllv2_recalc_rate,
diff --git a/arch/arm/mach-imx/clk.c b/arch/arm/mach-imx/clk.c
index f5e8be8..37e884e 100644
--- a/arch/arm/mach-imx/clk.c
+++ b/arch/arm/mach-imx/clk.c
@@ -1,3 +1,4 @@
 #include <linux/spinlock.h>
+#include "clk.h"
 
 DEFINE_SPINLOCK(imx_ccm_lock);
diff --git a/arch/arm/mach-imx/clk.h b/arch/arm/mach-imx/clk.h
index 9d1f3b9..d9d9d9c 100644
--- a/arch/arm/mach-imx/clk.h
+++ b/arch/arm/mach-imx/clk.h
@@ -59,6 +59,14 @@ static inline struct clk *imx_clk_divider(const char *name, const char *parent,
 			reg, shift, width, 0, &imx_ccm_lock);
 }
 
+static inline struct clk *imx_clk_divider_flags(const char *name,
+		const char *parent, void __iomem *reg, u8 shift, u8 width,
+		unsigned long flags)
+{
+	return clk_register_divider(NULL, name, parent, flags,
+			reg, shift, width, 0, &imx_ccm_lock);
+}
+
 static inline struct clk *imx_clk_gate(const char *name, const char *parent,
 		void __iomem *reg, u8 shift)
 {
@@ -73,6 +81,15 @@ static inline struct clk *imx_clk_mux(const char *name, void __iomem *reg,
 			width, 0, &imx_ccm_lock);
 }
 
+static inline struct clk *imx_clk_mux_flags(const char *name,
+		void __iomem *reg, u8 shift, u8 width, const char **parents,
+		int num_parents, unsigned long flags)
+{
+	return clk_register_mux(NULL, name, parents, num_parents,
+			flags, reg, shift, width, 0,
+			&imx_ccm_lock);
+}
+
 static inline struct clk *imx_clk_fixed_factor(const char *name,
 		const char *parent, unsigned int mult, unsigned int div)
 {
diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h
index 5a800bf..4cba7db 100644
--- a/arch/arm/mach-imx/common.h
+++ b/arch/arm/mach-imx/common.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2004-2013 Freescale Semiconductor, Inc. All Rights Reserved.
  */
 
 /*
@@ -74,6 +74,7 @@ extern void mxc_set_cpu_type(unsigned int type);
 extern void mxc_restart(char, const char *);
 extern void mxc_arch_reset_init(void __iomem *);
 extern int mx53_revision(void);
+extern int imx6q_revision(void);
 extern int mx53_display_revision(void);
 extern void imx_set_aips(void __iomem *);
 extern int mxc_device_init(void);
@@ -110,8 +111,9 @@ void tzic_handle_irq(struct pt_regs *);
 
 extern void imx_enable_cpu(int cpu, bool enable);
 extern void imx_set_cpu_jump(int cpu, void *jump_addr);
+extern u32 imx_get_cpu_arg(int cpu);
+extern void imx_set_cpu_arg(int cpu, u32 arg);
 extern void v7_cpu_resume(void);
-extern u32 *pl310_get_save_ptr(void);
 #ifdef CONFIG_SMP
 extern void v7_secondary_startup(void);
 extern void imx_scu_map_io(void);
@@ -122,13 +124,18 @@ static inline void imx_scu_map_io(void) {}
 static inline void imx_smp_prepare(void) {}
 static inline void imx_scu_standby_enable(void) {}
 #endif
-extern void imx_enable_cpu(int cpu, bool enable);
-extern void imx_set_cpu_jump(int cpu, void *jump_addr);
 extern void imx_src_init(void);
 extern void imx_src_prepare_restart(void);
 extern void imx_gpc_init(void);
 extern void imx_gpc_pre_suspend(void);
 extern void imx_gpc_post_resume(void);
+extern void imx_gpc_mask_all(void);
+extern void imx_gpc_restore_all(void);
+extern void imx_anatop_init(void);
+extern void imx_anatop_pre_suspend(void);
+extern void imx_anatop_post_resume(void);
+extern void imx_anatop_usb_chrg_detect_disable(void);
+extern u32 imx_anatop_get_digprog(void);
 extern int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode);
 extern void imx6q_set_chicken_bit(void);
 
diff --git a/arch/arm/mach-imx/cpu-imx5.c b/arch/arm/mach-imx/cpu-imx5.c
index d7ce722..c1c99a7 100644
--- a/arch/arm/mach-imx/cpu-imx5.c
+++ b/arch/arm/mach-imx/cpu-imx5.c
@@ -18,6 +18,7 @@
 #include <linux/io.h>
 
 #include "hardware.h"
+#include "common.h"
 
 static int mx5_cpu_rev = -1;
 
diff --git a/arch/arm/mach-imx/cpu.c b/arch/arm/mach-imx/cpu.c
index 03fcbd0..e70e3ac 100644
--- a/arch/arm/mach-imx/cpu.c
+++ b/arch/arm/mach-imx/cpu.c
@@ -3,6 +3,7 @@
 #include <linux/io.h>
 
 #include "hardware.h"
+#include "common.h"
 
 unsigned int __mxc_cpu_type;
 EXPORT_SYMBOL(__mxc_cpu_type);
diff --git a/arch/arm/mach-imx/cpu_op-mx51.c b/arch/arm/mach-imx/cpu_op-mx51.c
deleted file mode 100644
index b9ef692..0000000
--- a/arch/arm/mach-imx/cpu_op-mx51.c
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2010 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/bug.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-
-#include "hardware.h"
-
-static struct cpu_op mx51_cpu_op[] = {
-	{
-	.cpu_rate = 160000000,},
-	{
-	.cpu_rate = 800000000,},
-};
-
-struct cpu_op *mx51_get_cpu_op(int *op)
-{
-	*op = ARRAY_SIZE(mx51_cpu_op);
-	return mx51_cpu_op;
-}
diff --git a/arch/arm/mach-imx/cpu_op-mx51.h b/arch/arm/mach-imx/cpu_op-mx51.h
deleted file mode 100644
index 97477fe..0000000
--- a/arch/arm/mach-imx/cpu_op-mx51.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Copyright (C) 2010 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
- */
-
-extern struct cpu_op *mx51_get_cpu_op(int *op);
diff --git a/arch/arm/mach-imx/cpufreq.c b/arch/arm/mach-imx/cpufreq.c
deleted file mode 100644
index d8c75c3..0000000
--- a/arch/arm/mach-imx/cpufreq.c
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * Copyright (C) 2010 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
- */
-
-/*
- * A driver for the Freescale Semiconductor i.MXC CPUfreq module.
- * The CPUFREQ driver is for controlling CPU frequency. It allows you to change
- * the CPU clock speed on the fly.
- */
-
-#include <linux/module.h>
-#include <linux/cpufreq.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/slab.h>
-
-#include "hardware.h"
-
-#define CLK32_FREQ	32768
-#define NANOSECOND	(1000 * 1000 * 1000)
-
-struct cpu_op *(*get_cpu_op)(int *op);
-
-static int cpu_freq_khz_min;
-static int cpu_freq_khz_max;
-
-static struct clk *cpu_clk;
-static struct cpufreq_frequency_table *imx_freq_table;
-
-static int cpu_op_nr;
-static struct cpu_op *cpu_op_tbl;
-
-static int set_cpu_freq(int freq)
-{
-	int ret = 0;
-	int org_cpu_rate;
-
-	org_cpu_rate = clk_get_rate(cpu_clk);
-	if (org_cpu_rate == freq)
-		return ret;
-
-	ret = clk_set_rate(cpu_clk, freq);
-	if (ret != 0) {
-		printk(KERN_DEBUG "cannot set CPU clock rate\n");
-		return ret;
-	}
-
-	return ret;
-}
-
-static int mxc_verify_speed(struct cpufreq_policy *policy)
-{
-	if (policy->cpu != 0)
-		return -EINVAL;
-
-	return cpufreq_frequency_table_verify(policy, imx_freq_table);
-}
-
-static unsigned int mxc_get_speed(unsigned int cpu)
-{
-	if (cpu)
-		return 0;
-
-	return clk_get_rate(cpu_clk) / 1000;
-}
-
-static int mxc_set_target(struct cpufreq_policy *policy,
-			  unsigned int target_freq, unsigned int relation)
-{
-	struct cpufreq_freqs freqs;
-	int freq_Hz;
-	int ret = 0;
-	unsigned int index;
-
-	cpufreq_frequency_table_target(policy, imx_freq_table,
-			target_freq, relation, &index);
-	freq_Hz = imx_freq_table[index].frequency * 1000;
-
-	freqs.old = clk_get_rate(cpu_clk) / 1000;
-	freqs.new = freq_Hz / 1000;
-	freqs.cpu = 0;
-	freqs.flags = 0;
-	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
-
-	ret = set_cpu_freq(freq_Hz);
-
-	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
-
-	return ret;
-}
-
-static int mxc_cpufreq_init(struct cpufreq_policy *policy)
-{
-	int ret;
-	int i;
-
-	printk(KERN_INFO "i.MXC CPU frequency driver\n");
-
-	if (policy->cpu != 0)
-		return -EINVAL;
-
-	if (!get_cpu_op)
-		return -EINVAL;
-
-	cpu_clk = clk_get(NULL, "cpu_clk");
-	if (IS_ERR(cpu_clk)) {
-		printk(KERN_ERR "%s: failed to get cpu clock\n", __func__);
-		return PTR_ERR(cpu_clk);
-	}
-
-	cpu_op_tbl = get_cpu_op(&cpu_op_nr);
-
-	cpu_freq_khz_min = cpu_op_tbl[0].cpu_rate / 1000;
-	cpu_freq_khz_max = cpu_op_tbl[0].cpu_rate / 1000;
-
-	imx_freq_table = kmalloc(
-		sizeof(struct cpufreq_frequency_table) * (cpu_op_nr + 1),
-			GFP_KERNEL);
-	if (!imx_freq_table) {
-		ret = -ENOMEM;
-		goto err1;
-	}
-
-	for (i = 0; i < cpu_op_nr; i++) {
-		imx_freq_table[i].index = i;
-		imx_freq_table[i].frequency = cpu_op_tbl[i].cpu_rate / 1000;
-
-		if ((cpu_op_tbl[i].cpu_rate / 1000) < cpu_freq_khz_min)
-			cpu_freq_khz_min = cpu_op_tbl[i].cpu_rate / 1000;
-
-		if ((cpu_op_tbl[i].cpu_rate / 1000) > cpu_freq_khz_max)
-			cpu_freq_khz_max = cpu_op_tbl[i].cpu_rate / 1000;
-	}
-
-	imx_freq_table[i].index = i;
-	imx_freq_table[i].frequency = CPUFREQ_TABLE_END;
-
-	policy->cur = clk_get_rate(cpu_clk) / 1000;
-	policy->min = policy->cpuinfo.min_freq = cpu_freq_khz_min;
-	policy->max = policy->cpuinfo.max_freq = cpu_freq_khz_max;
-
-	/* Manual states, that PLL stabilizes in two CLK32 periods */
-	policy->cpuinfo.transition_latency = 2 * NANOSECOND / CLK32_FREQ;
-
-	ret = cpufreq_frequency_table_cpuinfo(policy, imx_freq_table);
-
-	if (ret < 0) {
-		printk(KERN_ERR "%s: failed to register i.MXC CPUfreq with error code %d\n",
-		       __func__, ret);
-		goto err;
-	}
-
-	cpufreq_frequency_table_get_attr(imx_freq_table, policy->cpu);
-	return 0;
-err:
-	kfree(imx_freq_table);
-err1:
-	clk_put(cpu_clk);
-	return ret;
-}
-
-static int mxc_cpufreq_exit(struct cpufreq_policy *policy)
-{
-	cpufreq_frequency_table_put_attr(policy->cpu);
-
-	set_cpu_freq(cpu_freq_khz_max * 1000);
-	clk_put(cpu_clk);
-	kfree(imx_freq_table);
-	return 0;
-}
-
-static struct cpufreq_driver mxc_driver = {
-	.flags = CPUFREQ_STICKY,
-	.verify = mxc_verify_speed,
-	.target = mxc_set_target,
-	.get = mxc_get_speed,
-	.init = mxc_cpufreq_init,
-	.exit = mxc_cpufreq_exit,
-	.name = "imx",
-};
-
-static int mxc_cpufreq_driver_init(void)
-{
-	return cpufreq_register_driver(&mxc_driver);
-}
-
-static void mxc_cpufreq_driver_exit(void)
-{
-	cpufreq_unregister_driver(&mxc_driver);
-}
-
-module_init(mxc_cpufreq_driver_init);
-module_exit(mxc_cpufreq_driver_exit);
-
-MODULE_AUTHOR("Freescale Semiconductor Inc. Yong Shen <yong.shen@linaro.org>");
-MODULE_DESCRIPTION("CPUfreq driver for i.MX");
-MODULE_LICENSE("GPL");
diff --git a/arch/arm/mach-imx/cpuidle-imx6q.c b/arch/arm/mach-imx/cpuidle-imx6q.c
index d533e26..a783a63 100644
--- a/arch/arm/mach-imx/cpuidle-imx6q.c
+++ b/arch/arm/mach-imx/cpuidle-imx6q.c
@@ -6,7 +6,6 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/clockchips.h>
 #include <linux/cpuidle.h>
 #include <linux/module.h>
 #include <asm/cpuidle.h>
@@ -21,10 +20,6 @@ static DEFINE_SPINLOCK(master_lock);
 static int imx6q_enter_wait(struct cpuidle_device *dev,
 			    struct cpuidle_driver *drv, int index)
 {
-	int cpu = dev->cpu;
-
-	clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
-
 	if (atomic_inc_return(&master) == num_online_cpus()) {
 		/*
 		 * With this lock, we prevent other cpu to exit and enter
@@ -43,22 +38,10 @@ idle:
 	cpu_do_idle();
 done:
 	atomic_dec(&master);
-	clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu);
 
 	return index;
 }
 
-/*
- * For each cpu, setup the broadcast timer because local timer
- * stops for the states other than WFI.
- */
-static void imx6q_setup_broadcast_timer(void *arg)
-{
-	int cpu = smp_processor_id();
-
-	clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ON, &cpu);
-}
-
 static struct cpuidle_driver imx6q_cpuidle_driver = {
 	.name = "imx6q_cpuidle",
 	.owner = THIS_MODULE,
@@ -70,7 +53,8 @@ static struct cpuidle_driver imx6q_cpuidle_driver = {
 		{
 			.exit_latency = 50,
 			.target_residency = 75,
-			.flags = CPUIDLE_FLAG_TIME_VALID,
+			.flags = CPUIDLE_FLAG_TIME_VALID |
+			         CPUIDLE_FLAG_TIMER_STOP,
 			.enter = imx6q_enter_wait,
 			.name = "WAIT",
 			.desc = "Clock off",
@@ -88,8 +72,5 @@ int __init imx6q_cpuidle_init(void)
 	/* Set chicken bit to get a reliable WAIT mode support */
 	imx6q_set_chicken_bit();
 
-	/* Configure the broadcast timer on each cpu */
-	on_each_cpu(imx6q_setup_broadcast_timer, NULL, 1);
-
 	return imx_cpuidle_init(&imx6q_cpuidle_driver);
 }
diff --git a/arch/arm/mach-imx/devices/devices.c b/arch/arm/mach-imx/devices/devices.c
index 1b37482..1b4366a 100644
--- a/arch/arm/mach-imx/devices/devices.c
+++ b/arch/arm/mach-imx/devices/devices.c
@@ -37,7 +37,7 @@ int __init mxc_device_init(void)
 	int ret;
 
 	ret = device_register(&mxc_aips_bus);
-	if (IS_ERR_VALUE(ret))
+	if (ret < 0)
 		goto done;
 
 	ret = device_register(&mxc_ahb_bus);
diff --git a/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c b/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c
index b4c7002..b2f08bf 100644
--- a/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c
+++ b/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c
@@ -46,7 +46,7 @@ static const int eukrea_mbimx27_pins[] __initconst = {
 	PE10_PF_UART3_CTS,
 	PE11_PF_UART3_RTS,
 	/* UART4 */
-#if !defined(MACH_EUKREA_CPUIMX27_USEUART4)
+#if !defined(CONFIG_MACH_EUKREA_CPUIMX27_USEUART4)
 	PB26_AF_UART4_RTS,
 	PB28_AF_UART4_TXD,
 	PB29_AF_UART4_CTS,
@@ -306,7 +306,7 @@ void __init eukrea_mbimx27_baseboard_init(void)
 
 	imx27_add_imx_uart1(&uart_pdata);
 	imx27_add_imx_uart2(&uart_pdata);
-#if !defined(MACH_EUKREA_CPUIMX27_USEUART4)
+#if !defined(CONFIG_MACH_EUKREA_CPUIMX27_USEUART4)
 	imx27_add_imx_uart3(&uart_pdata);
 #endif
 
diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c
index a96ccc7..44a65e9 100644
--- a/arch/arm/mach-imx/gpc.c
+++ b/arch/arm/mach-imx/gpc.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011-2013 Freescale Semiconductor, Inc.
  * Copyright 2011 Linaro Ltd.
  *
  * The code contained herein is licensed under the GNU General Public
@@ -16,6 +16,7 @@
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <linux/irqchip/arm-gic.h>
+#include "common.h"
 
 #define GPC_IMR1		0x008
 #define GPC_PGC_CPU_PDN		0x2a0
@@ -68,6 +69,27 @@ static int imx_gpc_irq_set_wake(struct irq_data *d, unsigned int on)
 	return 0;
 }
 
+void imx_gpc_mask_all(void)
+{
+	void __iomem *reg_imr1 = gpc_base + GPC_IMR1;
+	int i;
+
+	for (i = 0; i < IMR_NUM; i++) {
+		gpc_saved_imrs[i] = readl_relaxed(reg_imr1 + i * 4);
+		writel_relaxed(~0, reg_imr1 + i * 4);
+	}
+
+}
+
+void imx_gpc_restore_all(void)
+{
+	void __iomem *reg_imr1 = gpc_base + GPC_IMR1;
+	int i;
+
+	for (i = 0; i < IMR_NUM; i++)
+		writel_relaxed(gpc_saved_imrs[i], reg_imr1 + i * 4);
+}
+
 static void imx_gpc_irq_unmask(struct irq_data *d)
 {
 	void __iomem *reg;
diff --git a/arch/arm/mach-imx/hardware.h b/arch/arm/mach-imx/hardware.h
index 911e9b3..356131f 100644
--- a/arch/arm/mach-imx/hardware.h
+++ b/arch/arm/mach-imx/hardware.h
@@ -102,7 +102,6 @@
 
 #include "mxc.h"
 
-#include "mx6q.h"
 #include "mx51.h"
 #include "mx53.h"
 #include "mx3x.h"
diff --git a/arch/arm/mach-imx/hotplug.c b/arch/arm/mach-imx/hotplug.c
index 7bc5fe1..361a253 100644
--- a/arch/arm/mach-imx/hotplug.c
+++ b/arch/arm/mach-imx/hotplug.c
@@ -46,11 +46,23 @@ static inline void cpu_enter_lowpower(void)
 void imx_cpu_die(unsigned int cpu)
 {
 	cpu_enter_lowpower();
+	/*
+	 * We use the cpu jumping argument register to sync with
+	 * imx_cpu_kill() which is running on cpu0 and waiting for
+	 * the register being cleared to kill the cpu.
+	 */
+	imx_set_cpu_arg(cpu, ~0);
 	cpu_do_idle();
 }
 
 int imx_cpu_kill(unsigned int cpu)
 {
+	unsigned long timeout = jiffies + msecs_to_jiffies(50);
+
+	while (imx_get_cpu_arg(cpu) == 0)
+		if (time_after(jiffies, timeout))
+			return 0;
 	imx_enable_cpu(cpu, false);
+	imx_set_cpu_arg(cpu, 0);
 	return 1;
 }
diff --git a/arch/arm/mach-imx/imx27-dt.c b/arch/arm/mach-imx/imx27-dt.c
index c915a49..4aaead0 100644
--- a/arch/arm/mach-imx/imx27-dt.c
+++ b/arch/arm/mach-imx/imx27-dt.c
@@ -18,25 +18,13 @@
 #include "common.h"
 #include "mx27.h"
 
-static const struct of_dev_auxdata imx27_auxdata_lookup[] __initconst = {
-	OF_DEV_AUXDATA("fsl,imx27-uart", MX27_UART1_BASE_ADDR, "imx21-uart.0", NULL),
-	OF_DEV_AUXDATA("fsl,imx27-uart", MX27_UART2_BASE_ADDR, "imx21-uart.1", NULL),
-	OF_DEV_AUXDATA("fsl,imx27-uart", MX27_UART3_BASE_ADDR, "imx21-uart.2", NULL),
-	OF_DEV_AUXDATA("fsl,imx27-fec", MX27_FEC_BASE_ADDR, "imx27-fec.0", NULL),
-	OF_DEV_AUXDATA("fsl,imx27-i2c", MX27_I2C1_BASE_ADDR, "imx21-i2c.0", NULL),
-	OF_DEV_AUXDATA("fsl,imx27-i2c", MX27_I2C2_BASE_ADDR, "imx21-i2c.1", NULL),
-	OF_DEV_AUXDATA("fsl,imx27-cspi", MX27_CSPI1_BASE_ADDR, "imx27-cspi.0", NULL),
-	OF_DEV_AUXDATA("fsl,imx27-cspi", MX27_CSPI2_BASE_ADDR, "imx27-cspi.1", NULL),
-	OF_DEV_AUXDATA("fsl,imx27-cspi", MX27_CSPI3_BASE_ADDR, "imx27-cspi.2", NULL),
-	OF_DEV_AUXDATA("fsl,imx27-wdt", MX27_WDOG_BASE_ADDR, "imx2-wdt.0", NULL),
-	OF_DEV_AUXDATA("fsl,imx27-nand", MX27_NFC_BASE_ADDR, "imx27-nand.0", NULL),
-	{ /* sentinel */ }
-};
-
 static void __init imx27_dt_init(void)
 {
-	of_platform_populate(NULL, of_default_bus_match_table,
-			     imx27_auxdata_lookup, NULL);
+	struct platform_device_info devinfo = { .name = "cpufreq-cpu0", };
+
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+
+	platform_device_register_full(&devinfo);
 }
 
 static const char * const imx27_dt_board_compat[] __initconst = {
diff --git a/arch/arm/mach-imx/imx51-dt.c b/arch/arm/mach-imx/imx51-dt.c
index e2926a8..ab24cc3 100644
--- a/arch/arm/mach-imx/imx51-dt.c
+++ b/arch/arm/mach-imx/imx51-dt.c
@@ -21,7 +21,10 @@
 
 static void __init imx51_dt_init(void)
 {
+	struct platform_device_info devinfo = { .name = "cpufreq-cpu0", };
+
 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+	platform_device_register_full(&devinfo);
 }
 
 static const char *imx51_dt_board_compat[] __initdata = {
diff --git a/arch/arm/mach-imx/iomux-imx31.c b/arch/arm/mach-imx/iomux-imx31.c
index cabefbc..7c66805 100644
--- a/arch/arm/mach-imx/iomux-imx31.c
+++ b/arch/arm/mach-imx/iomux-imx31.c
@@ -40,7 +40,7 @@ static DEFINE_SPINLOCK(gpio_mux_lock);
 
 #define IOMUX_REG_MASK (IOMUX_PADNUM_MASK & ~0x3)
 
-unsigned long mxc_pin_alloc_map[NB_PORTS * 32 / BITS_PER_LONG];
+static unsigned long mxc_pin_alloc_map[NB_PORTS * 32 / BITS_PER_LONG];
 /*
  * set the mode for a IOMUX pin.
  */
diff --git a/arch/arm/mach-imx/irq-common.c b/arch/arm/mach-imx/irq-common.c
index b6e1145..4b34f52 100644
--- a/arch/arm/mach-imx/irq-common.c
+++ b/arch/arm/mach-imx/irq-common.c
@@ -21,25 +21,6 @@
 
 #include "irq-common.h"
 
-int imx_irq_set_priority(unsigned char irq, unsigned char prio)
-{
-	struct irq_chip_generic *gc;
-	struct mxc_extra_irq *exirq;
-	int ret;
-
-	ret = -ENOSYS;
-
-	gc = irq_get_chip_data(irq);
-	if (gc && gc->private) {
-		exirq = gc->private;
-		if (exirq->set_priority)
-			ret = exirq->set_priority(irq, prio);
-	}
-
-	return ret;
-}
-EXPORT_SYMBOL(imx_irq_set_priority);
-
 int mxc_set_irq_fiq(unsigned int irq, unsigned int type)
 {
 	struct irq_chip_generic *gc;
diff --git a/arch/arm/mach-imx/mach-cpuimx27.c b/arch/arm/mach-imx/mach-cpuimx27.c
index 1465593..ea50870 100644
--- a/arch/arm/mach-imx/mach-cpuimx27.c
+++ b/arch/arm/mach-imx/mach-cpuimx27.c
@@ -48,7 +48,7 @@ static const int eukrea_cpuimx27_pins[] __initconst = {
 	PE14_PF_UART1_CTS,
 	PE15_PF_UART1_RTS,
 	/* UART4 */
-#if defined(MACH_EUKREA_CPUIMX27_USEUART4)
+#if defined(CONFIG_MACH_EUKREA_CPUIMX27_USEUART4)
 	PB26_AF_UART4_RTS,
 	PB28_AF_UART4_TXD,
 	PB29_AF_UART4_CTS,
@@ -272,7 +272,7 @@ static void __init eukrea_cpuimx27_init(void)
 	/* SDHC2 can be used for Wifi */
 	imx27_add_mxc_mmc(1, NULL);
 #endif
-#if defined(MACH_EUKREA_CPUIMX27_USEUART4)
+#if defined(CONFIG_MACH_EUKREA_CPUIMX27_USEUART4)
 	/* in which case UART4 is also used for Bluetooth */
 	imx27_add_imx_uart3(&uart_pdata);
 #endif
diff --git a/arch/arm/mach-imx/mach-cpuimx51sd.c b/arch/arm/mach-imx/mach-cpuimx51sd.c
index 9b73932..9b5ddf5 100644
--- a/arch/arm/mach-imx/mach-cpuimx51sd.c
+++ b/arch/arm/mach-imx/mach-cpuimx51sd.c
@@ -33,7 +33,6 @@
 
 #include "common.h"
 #include "devices-imx51.h"
-#include "cpu_op-mx51.h"
 #include "eukrea-baseboards.h"
 #include "hardware.h"
 #include "iomux-mx51.h"
@@ -285,10 +284,6 @@ static void __init eukrea_cpuimx51sd_init(void)
 	mxc_iomux_v3_setup_multiple_pads(eukrea_cpuimx51sd_pads,
 					ARRAY_SIZE(eukrea_cpuimx51sd_pads));
 
-#if defined(CONFIG_CPU_FREQ_IMX)
-	get_cpu_op = mx51_get_cpu_op;
-#endif
-
 	imx51_add_imx_uart(0, &uart_pdata);
 	imx51_add_mxc_nand(&eukrea_cpuimx51sd_nand_board_info);
 	imx51_add_imx2_wdt(0);
diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c
index 9ffd103..5536fd8 100644
--- a/arch/arm/mach-imx/mach-imx6q.c
+++ b/arch/arm/mach-imx/mach-imx6q.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011-2013 Freescale Semiconductor, Inc.
  * Copyright 2011 Linaro Ltd.
  *
  * The code contained herein is licensed under the GNU General Public
@@ -12,6 +12,7 @@
 
 #include <linux/clk.h>
 #include <linux/clkdev.h>
+#include <linux/clocksource.h>
 #include <linux/cpu.h>
 #include <linux/delay.h>
 #include <linux/export.h>
@@ -28,52 +29,44 @@
 #include <linux/regmap.h>
 #include <linux/micrel_phy.h>
 #include <linux/mfd/syscon.h>
-#include <asm/smp_twd.h>
 #include <asm/hardware/cache-l2x0.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
-#include <asm/mach/time.h>
 #include <asm/system_misc.h>
 
 #include "common.h"
 #include "cpuidle.h"
 #include "hardware.h"
 
-#define IMX6Q_ANALOG_DIGPROG	0x260
+static u32 chip_revision;
 
-static int imx6q_revision(void)
+int imx6q_revision(void)
 {
-	struct device_node *np;
-	void __iomem *base;
-	static u32 rev;
-
-	if (!rev) {
-		np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-anatop");
-		if (!np)
-			return IMX_CHIP_REVISION_UNKNOWN;
-		base = of_iomap(np, 0);
-		if (!base) {
-			of_node_put(np);
-			return IMX_CHIP_REVISION_UNKNOWN;
-		}
-		rev =  readl_relaxed(base + IMX6Q_ANALOG_DIGPROG);
-		iounmap(base);
-		of_node_put(np);
-	}
+	return chip_revision;
+}
+
+static void __init imx6q_init_revision(void)
+{
+	u32 rev = imx_anatop_get_digprog();
 
 	switch (rev & 0xff) {
 	case 0:
-		return IMX_CHIP_REVISION_1_0;
+		chip_revision = IMX_CHIP_REVISION_1_0;
+		break;
 	case 1:
-		return IMX_CHIP_REVISION_1_1;
+		chip_revision = IMX_CHIP_REVISION_1_1;
+		break;
 	case 2:
-		return IMX_CHIP_REVISION_1_2;
+		chip_revision = IMX_CHIP_REVISION_1_2;
+		break;
 	default:
-		return IMX_CHIP_REVISION_UNKNOWN;
+		chip_revision = IMX_CHIP_REVISION_UNKNOWN;
 	}
+
+	mxc_set_cpu_type(rev >> 16 & 0xff);
 }
 
-void imx6q_restart(char mode, const char *cmd)
+static void imx6q_restart(char mode, const char *cmd)
 {
 	struct device_node *np;
 	void __iomem *wdog_base;
@@ -165,29 +158,7 @@ static void __init imx6q_1588_init(void)
 }
 static void __init imx6q_usb_init(void)
 {
-	struct regmap *anatop;
-
-#define HW_ANADIG_USB1_CHRG_DETECT		0x000001b0
-#define HW_ANADIG_USB2_CHRG_DETECT		0x00000210
-
-#define BM_ANADIG_USB_CHRG_DETECT_EN_B		0x00100000
-#define BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B	0x00080000
-
-	anatop = syscon_regmap_lookup_by_compatible("fsl,imx6q-anatop");
-	if (!IS_ERR(anatop)) {
-		/*
-		 * The external charger detector needs to be disabled,
-		 * or the signal at DP will be poor
-		 */
-		regmap_write(anatop, HW_ANADIG_USB1_CHRG_DETECT,
-				BM_ANADIG_USB_CHRG_DETECT_EN_B
-				| BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B);
-		regmap_write(anatop, HW_ANADIG_USB2_CHRG_DETECT,
-				BM_ANADIG_USB_CHRG_DETECT_EN_B |
-				BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B);
-	} else {
-		pr_warn("failed to find fsl,imx6q-anatop regmap\n");
-	}
+	imx_anatop_usb_chrg_detect_disable();
 }
 
 static void __init imx6q_init_machine(void)
@@ -197,6 +168,7 @@ static void __init imx6q_init_machine(void)
 
 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 
+	imx_anatop_init();
 	imx6q_pm_init();
 	imx6q_usb_init();
 	imx6q_1588_init();
@@ -256,7 +228,7 @@ put_node:
 	of_node_put(np);
 }
 
-struct platform_device imx6q_cpufreq_pdev = {
+static struct platform_device imx6q_cpufreq_pdev = {
 	.name = "imx6q-cpufreq",
 };
 
@@ -283,6 +255,7 @@ static void __init imx6q_map_io(void)
 
 static void __init imx6q_init_irq(void)
 {
+	imx6q_init_revision();
 	l2x0_of_init(0, ~0UL);
 	imx_src_init();
 	imx_gpc_init();
@@ -292,16 +265,18 @@ static void __init imx6q_init_irq(void)
 static void __init imx6q_timer_init(void)
 {
 	mx6q_clocks_init();
-	twd_local_timer_of_register();
-	imx_print_silicon_rev("i.MX6Q", imx6q_revision());
+	clocksource_of_init();
+	imx_print_silicon_rev(cpu_is_imx6dl() ? "i.MX6DL" : "i.MX6Q",
+			      imx6q_revision());
 }
 
 static const char *imx6q_dt_compat[] __initdata = {
+	"fsl,imx6dl",
 	"fsl,imx6q",
 	NULL,
 };
 
-DT_MACHINE_START(IMX6Q, "Freescale i.MX6 Quad (Device Tree)")
+DT_MACHINE_START(IMX6Q, "Freescale i.MX6 Quad/DualLite (Device Tree)")
 	.smp		= smp_ops(imx_smp_ops),
 	.map_io		= imx6q_map_io,
 	.init_irq	= imx6q_init_irq,
diff --git a/arch/arm/mach-imx/mach-mx51_babbage.c b/arch/arm/mach-imx/mach-mx51_babbage.c
index 6c4d7fe..f3d264a 100644
--- a/arch/arm/mach-imx/mach-mx51_babbage.c
+++ b/arch/arm/mach-imx/mach-mx51_babbage.c
@@ -27,7 +27,6 @@
 
 #include "common.h"
 #include "devices-imx51.h"
-#include "cpu_op-mx51.h"
 #include "hardware.h"
 #include "iomux-mx51.h"
 
@@ -371,9 +370,6 @@ static void __init mx51_babbage_init(void)
 
 	imx51_soc_init();
 
-#if defined(CONFIG_CPU_FREQ_IMX)
-	get_cpu_op = mx51_get_cpu_op;
-#endif
 	imx51_babbage_common_init();
 
 	imx51_add_imx_uart(0, &uart_pdata);
diff --git a/arch/arm/mach-imx/mm-imx1.c b/arch/arm/mach-imx/mm-imx1.c
index 7a14667..3c609c5 100644
--- a/arch/arm/mach-imx/mm-imx1.c
+++ b/arch/arm/mach-imx/mm-imx1.c
@@ -51,6 +51,8 @@ void __init mx1_init_irq(void)
 
 void __init imx1_soc_init(void)
 {
+	mxc_device_init();
+
 	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,
diff --git a/arch/arm/mach-imx/mm-imx3.c b/arch/arm/mach-imx/mm-imx3.c
index cefa047..e0e69a6 100644
--- a/arch/arm/mach-imx/mm-imx3.c
+++ b/arch/arm/mach-imx/mm-imx3.c
@@ -82,7 +82,7 @@ static void __iomem *imx3_ioremap_caller(unsigned long phys_addr, size_t size,
 	return __arm_ioremap_caller(phys_addr, size, mtype, caller);
 }
 
-void __init imx3_init_l2x0(void)
+static void __init imx3_init_l2x0(void)
 {
 #ifdef CONFIG_CACHE_L2X0
 	void __iomem *l2x0_base;
diff --git a/arch/arm/mach-imx/mm-imx5.c b/arch/arm/mach-imx/mm-imx5.c
index cf34994..b7c4e70 100644
--- a/arch/arm/mach-imx/mm-imx5.c
+++ b/arch/arm/mach-imx/mm-imx5.c
@@ -84,6 +84,7 @@ void __init imx51_init_early(void)
 	mxc_set_cpu_type(MXC_CPU_MX51);
 	mxc_iomux_v3_init(MX51_IO_ADDRESS(MX51_IOMUXC_BASE_ADDR));
 	mxc_arch_reset_init(MX51_IO_ADDRESS(MX51_WDOG1_BASE_ADDR));
+	imx_src_init();
 }
 
 void __init imx53_init_early(void)
@@ -91,6 +92,7 @@ void __init imx53_init_early(void)
 	mxc_set_cpu_type(MXC_CPU_MX53);
 	mxc_iomux_v3_init(MX53_IO_ADDRESS(MX53_IOMUXC_BASE_ADDR));
 	mxc_arch_reset_init(MX53_IO_ADDRESS(MX53_WDOG1_BASE_ADDR));
+	imx_src_init();
 }
 
 void __init mx51_init_irq(void)
diff --git a/arch/arm/mach-imx/mx6q.h b/arch/arm/mach-imx/mx6q.h
deleted file mode 100644
index 19d3f54..0000000
--- a/arch/arm/mach-imx/mx6q.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright 2011 Linaro Ltd.
- *
- * 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
- */
-
-#ifndef __MACH_MX6Q_H__
-#define __MACH_MX6Q_H__
-
-#define MX6Q_IO_P2V(x)			IMX_IO_P2V(x)
-#define MX6Q_IO_ADDRESS(x)		IOMEM(MX6Q_IO_P2V(x))
-
-/*
- * The following are the blocks that need to be statically mapped.
- * For other blocks, the base address really should be retrieved from
- * device tree.
- */
-#define MX6Q_SCU_BASE_ADDR		0x00a00000
-#define MX6Q_SCU_SIZE			0x1000
-#define MX6Q_CCM_BASE_ADDR		0x020c4000
-#define MX6Q_CCM_SIZE			0x4000
-#define MX6Q_ANATOP_BASE_ADDR		0x020c8000
-#define MX6Q_ANATOP_SIZE		0x1000
-
-#endif	/* __MACH_MX6Q_H__ */
diff --git a/arch/arm/mach-imx/mxc.h b/arch/arm/mach-imx/mxc.h
index 7dce17a..8629e5b 100644
--- a/arch/arm/mach-imx/mxc.h
+++ b/arch/arm/mach-imx/mxc.h
@@ -34,6 +34,8 @@
 #define MXC_CPU_MX35		35
 #define MXC_CPU_MX51		51
 #define MXC_CPU_MX53		53
+#define MXC_CPU_IMX6DL		0x61
+#define MXC_CPU_IMX6Q		0x63
 
 #define IMX_CHIP_REVISION_1_0		0x10
 #define IMX_CHIP_REVISION_1_1		0x11
@@ -150,6 +152,15 @@ extern unsigned int __mxc_cpu_type;
 #endif
 
 #ifndef __ASSEMBLY__
+static inline bool cpu_is_imx6dl(void)
+{
+	return __mxc_cpu_type == MXC_CPU_IMX6DL;
+}
+
+static inline bool cpu_is_imx6q(void)
+{
+	return __mxc_cpu_type == MXC_CPU_IMX6Q;
+}
 
 struct cpu_op {
 	u32 cpu_rate;
diff --git a/arch/arm/mach-imx/platsmp.c b/arch/arm/mach-imx/platsmp.c
index 7c0b03f..4a69305 100644
--- a/arch/arm/mach-imx/platsmp.c
+++ b/arch/arm/mach-imx/platsmp.c
@@ -12,7 +12,6 @@
 
 #include <linux/init.h>
 #include <linux/smp.h>
-#include <linux/irqchip/arm-gic.h>
 #include <asm/page.h>
 #include <asm/smp_scu.h>
 #include <asm/mach/map.h>
@@ -52,16 +51,6 @@ void imx_scu_standby_enable(void)
 	writel_relaxed(val, scu_base);
 }
 
-static void __cpuinit imx_secondary_init(unsigned int cpu)
-{
-	/*
-	 * if any interrupts are already enabled for the primary
-	 * core (e.g. timer irq), then they will not have been enabled
-	 * for us: do so
-	 */
-	gic_secondary_init(0);
-}
-
 static int __cpuinit imx_boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
 	imx_set_cpu_jump(cpu, v7_secondary_startup);
@@ -79,8 +68,8 @@ static void __init imx_smp_init_cpus(void)
 
 	ncores = scu_get_core_count(scu_base);
 
-	for (i = 0; i < ncores; i++)
-		set_cpu_possible(i, true);
+	for (i = ncores; i < NR_CPUS; i++)
+		set_cpu_possible(i, false);
 }
 
 void imx_smp_prepare(void)
@@ -96,7 +85,6 @@ static void __init imx_smp_prepare_cpus(unsigned int max_cpus)
 struct smp_operations  imx_smp_ops __initdata = {
 	.smp_init_cpus		= imx_smp_init_cpus,
 	.smp_prepare_cpus	= imx_smp_prepare_cpus,
-	.smp_secondary_init	= imx_secondary_init,
 	.smp_boot_secondary	= imx_boot_secondary,
 #ifdef CONFIG_HOTPLUG_CPU
 	.cpu_die		= imx_cpu_die,
diff --git a/arch/arm/mach-imx/pm-imx6q.c b/arch/arm/mach-imx/pm-imx6q.c
index 5faba7a..2049427 100644
--- a/arch/arm/mach-imx/pm-imx6q.c
+++ b/arch/arm/mach-imx/pm-imx6q.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011-2013 Freescale Semiconductor, Inc.
  * Copyright 2011 Linaro Ltd.
  *
  * The code contained herein is licensed under the GNU General Public
@@ -34,10 +34,12 @@ static int imx6q_pm_enter(suspend_state_t state)
 	case PM_SUSPEND_MEM:
 		imx6q_set_lpm(STOP_POWER_OFF);
 		imx_gpc_pre_suspend();
+		imx_anatop_pre_suspend();
 		imx_set_cpu_jump(0, v7_cpu_resume);
 		/* Zzz ... */
 		cpu_suspend(0, imx6q_suspend_finish);
 		imx_smp_prepare();
+		imx_anatop_post_resume();
 		imx_gpc_post_resume();
 		imx6q_set_lpm(WAIT_CLOCKED);
 		break;
diff --git a/arch/arm/mach-imx/src.c b/arch/arm/mach-imx/src.c
index e15f155..dc101898 100644
--- a/arch/arm/mach-imx/src.c
+++ b/arch/arm/mach-imx/src.c
@@ -14,16 +14,73 @@
 #include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/reset-controller.h>
 #include <linux/smp.h>
 #include <asm/smp_plat.h>
+#include "common.h"
 
 #define SRC_SCR				0x000
 #define SRC_GPR1			0x020
 #define BP_SRC_SCR_WARM_RESET_ENABLE	0
+#define BP_SRC_SCR_SW_GPU_RST		1
+#define BP_SRC_SCR_SW_VPU_RST		2
+#define BP_SRC_SCR_SW_IPU1_RST		3
+#define BP_SRC_SCR_SW_OPEN_VG_RST	4
+#define BP_SRC_SCR_SW_IPU2_RST		12
 #define BP_SRC_SCR_CORE1_RST		14
 #define BP_SRC_SCR_CORE1_ENABLE		22
 
 static void __iomem *src_base;
+static DEFINE_SPINLOCK(scr_lock);
+
+static const int sw_reset_bits[5] = {
+	BP_SRC_SCR_SW_GPU_RST,
+	BP_SRC_SCR_SW_VPU_RST,
+	BP_SRC_SCR_SW_IPU1_RST,
+	BP_SRC_SCR_SW_OPEN_VG_RST,
+	BP_SRC_SCR_SW_IPU2_RST
+};
+
+static int imx_src_reset_module(struct reset_controller_dev *rcdev,
+		unsigned long sw_reset_idx)
+{
+	unsigned long timeout;
+	unsigned long flags;
+	int bit;
+	u32 val;
+
+	if (!src_base)
+		return -ENODEV;
+
+	if (sw_reset_idx >= ARRAY_SIZE(sw_reset_bits))
+		return -EINVAL;
+
+	bit = 1 << sw_reset_bits[sw_reset_idx];
+
+	spin_lock_irqsave(&scr_lock, flags);
+	val = readl_relaxed(src_base + SRC_SCR);
+	val |= bit;
+	writel_relaxed(val, src_base + SRC_SCR);
+	spin_unlock_irqrestore(&scr_lock, flags);
+
+	timeout = jiffies + msecs_to_jiffies(1000);
+	while (readl(src_base + SRC_SCR) & bit) {
+		if (time_after(jiffies, timeout))
+			return -ETIME;
+		cpu_relax();
+	}
+
+	return 0;
+}
+
+static struct reset_control_ops imx_src_ops = {
+	.reset = imx_src_reset_module,
+};
+
+static struct reset_controller_dev imx_reset_controller = {
+	.ops = &imx_src_ops,
+	.nr_resets = ARRAY_SIZE(sw_reset_bits),
+};
 
 void imx_enable_cpu(int cpu, bool enable)
 {
@@ -31,9 +88,11 @@ void imx_enable_cpu(int cpu, bool enable)
 
 	cpu = cpu_logical_map(cpu);
 	mask = 1 << (BP_SRC_SCR_CORE1_ENABLE + cpu - 1);
+	spin_lock(&scr_lock);
 	val = readl_relaxed(src_base + SRC_SCR);
 	val = enable ? val | mask : val & ~mask;
 	writel_relaxed(val, src_base + SRC_SCR);
+	spin_unlock(&scr_lock);
 }
 
 void imx_set_cpu_jump(int cpu, void *jump_addr)
@@ -43,14 +102,28 @@ void imx_set_cpu_jump(int cpu, void *jump_addr)
 		       src_base + SRC_GPR1 + cpu * 8);
 }
 
+u32 imx_get_cpu_arg(int cpu)
+{
+	cpu = cpu_logical_map(cpu);
+	return readl_relaxed(src_base + SRC_GPR1 + cpu * 8 + 4);
+}
+
+void imx_set_cpu_arg(int cpu, u32 arg)
+{
+	cpu = cpu_logical_map(cpu);
+	writel_relaxed(arg, src_base + SRC_GPR1 + cpu * 8 + 4);
+}
+
 void imx_src_prepare_restart(void)
 {
 	u32 val;
 
 	/* clear enable bits of secondary cores */
+	spin_lock(&scr_lock);
 	val = readl_relaxed(src_base + SRC_SCR);
 	val &= ~(0x7 << BP_SRC_SCR_CORE1_ENABLE);
 	writel_relaxed(val, src_base + SRC_SCR);
+	spin_unlock(&scr_lock);
 
 	/* clear persistent entry register of primary core */
 	writel_relaxed(0, src_base + SRC_GPR1);
@@ -61,15 +134,22 @@ void __init imx_src_init(void)
 	struct device_node *np;
 	u32 val;
 
-	np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-src");
+	np = of_find_compatible_node(NULL, NULL, "fsl,imx51-src");
+	if (!np)
+		return;
 	src_base = of_iomap(np, 0);
 	WARN_ON(!src_base);
 
+	imx_reset_controller.of_node = np;
+	reset_controller_register(&imx_reset_controller);
+
 	/*
 	 * force warm reset sources to generate cold reset
 	 * for a more reliable restart
 	 */
+	spin_lock(&scr_lock);
 	val = readl_relaxed(src_base + SRC_SCR);
 	val &= ~(1 << BP_SRC_SCR_WARM_RESET_ENABLE);
 	writel_relaxed(val, src_base + SRC_SCR);
+	spin_unlock(&scr_lock);
 }
diff --git a/arch/arm/mach-imx/tzic.c b/arch/arm/mach-imx/tzic.c
index 9721161..8183178 100644
--- a/arch/arm/mach-imx/tzic.c
+++ b/arch/arm/mach-imx/tzic.c
@@ -49,7 +49,7 @@
 #define TZIC_SWINT	0x0F00	/* Software Interrupt Rigger Register */
 #define TZIC_ID0	0x0FD0	/* Indentification Register 0 */
 
-void __iomem *tzic_base; /* Used as irq controller base in entry-macro.S */
+static void __iomem *tzic_base;
 static struct irq_domain *domain;
 
 #define TZIC_NUM_IRQS 128
diff --git a/arch/arm/mach-integrator/cpu.c b/arch/arm/mach-integrator/cpu.c
index 590c192..df863c3 100644
--- a/arch/arm/mach-integrator/cpu.c
+++ b/arch/arm/mach-integrator/cpu.c
@@ -123,14 +123,12 @@ static int integrator_set_target(struct cpufreq_policy *policy,
 	vco = icst_hz_to_vco(&cclk_params, target_freq * 1000);
 	freqs.new = icst_hz(&cclk_params, vco) / 1000;
 
-	freqs.cpu = policy->cpu;
-
 	if (freqs.old == freqs.new) {
 		set_cpus_allowed(current, cpus_allowed);
 		return 0;
 	}
 
-	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
 
 	cm_osc = __raw_readl(CM_OSC);
 
@@ -151,7 +149,7 @@ static int integrator_set_target(struct cpufreq_policy *policy,
 	 */
 	set_cpus_allowed(current, cpus_allowed);
 
-	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
 
 	return 0;
 }
diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c
index ea96144..b23c8e4 100644
--- a/arch/arm/mach-integrator/integrator_ap.c
+++ b/arch/arm/mach-integrator/integrator_ap.c
@@ -536,16 +536,14 @@ static void __init ap_init_of(void)
 					   'A' + (ap_sc_id & 0x0f));
 
 	soc_dev = soc_device_register(soc_dev_attr);
-	if (IS_ERR_OR_NULL(soc_dev)) {
+	if (IS_ERR(soc_dev)) {
 		kfree(soc_dev_attr->revision);
 		kfree(soc_dev_attr);
 		return;
 	}
 
 	parent = soc_device_to_device(soc_dev);
-
-	if (!IS_ERR_OR_NULL(parent))
-		integrator_init_sysfs(parent, ap_sc_id);
+	integrator_init_sysfs(parent, ap_sc_id);
 
 	of_platform_populate(root, of_default_bus_match_table,
 			ap_auxdata_lookup, parent);
diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c
index 2b0db82..da1091b 100644
--- a/arch/arm/mach-integrator/integrator_cp.c
+++ b/arch/arm/mach-integrator/integrator_cp.c
@@ -360,17 +360,14 @@ static void __init intcp_init_of(void)
 					   'A' + (intcp_sc_id & 0x0f));
 
 	soc_dev = soc_device_register(soc_dev_attr);
-	if (IS_ERR_OR_NULL(soc_dev)) {
+	if (IS_ERR(soc_dev)) {
 		kfree(soc_dev_attr->revision);
 		kfree(soc_dev_attr);
 		return;
 	}
 
 	parent = soc_device_to_device(soc_dev);
-
-	if (!IS_ERR_OR_NULL(parent))
-		integrator_init_sysfs(parent, intcp_sc_id);
-
+	integrator_init_sysfs(parent, intcp_sc_id);
 	of_platform_populate(root, of_default_bus_match_table,
 			intcp_auxdata_lookup, parent);
 }
diff --git a/arch/arm/mach-kirkwood/guruplug-setup.c b/arch/arm/mach-kirkwood/guruplug-setup.c
index 1c6e736..08dd739 100644
--- a/arch/arm/mach-kirkwood/guruplug-setup.c
+++ b/arch/arm/mach-kirkwood/guruplug-setup.c
@@ -53,6 +53,8 @@ static struct mv_sata_platform_data guruplug_sata_data = {
 
 static struct mvsdio_platform_data guruplug_mvsdio_data = {
 	/* unfortunately the CD signal has not been connected */
+	.gpio_card_detect = -1,
+	.gpio_write_protect = -1,
 };
 
 static struct gpio_led guruplug_led_pins[] = {
diff --git a/arch/arm/mach-kirkwood/openrd-setup.c b/arch/arm/mach-kirkwood/openrd-setup.c
index 8ddd69f..6a6eb54 100644
--- a/arch/arm/mach-kirkwood/openrd-setup.c
+++ b/arch/arm/mach-kirkwood/openrd-setup.c
@@ -55,6 +55,7 @@ static struct mv_sata_platform_data openrd_sata_data = {
 
 static struct mvsdio_platform_data openrd_mvsdio_data = {
 	.gpio_card_detect = 29,	/* MPP29 used as SD card detect */
+	.gpio_write_protect = -1,
 };
 
 static unsigned int openrd_mpp_config[] __initdata = {
diff --git a/arch/arm/mach-kirkwood/rd88f6281-setup.c b/arch/arm/mach-kirkwood/rd88f6281-setup.c
index c7d93b4..d242231 100644
--- a/arch/arm/mach-kirkwood/rd88f6281-setup.c
+++ b/arch/arm/mach-kirkwood/rd88f6281-setup.c
@@ -69,6 +69,7 @@ static struct mv_sata_platform_data rd88f6281_sata_data = {
 
 static struct mvsdio_platform_data rd88f6281_mvsdio_data = {
 	.gpio_card_detect = 28,
+	.gpio_write_protect = -1,
 };
 
 static unsigned int rd88f6281_mpp_config[] __initdata = {
diff --git a/arch/arm/mach-l7200/include/mach/debug-macro.S b/arch/arm/mach-l7200/include/mach/debug-macro.S
deleted file mode 100644
index 0b4e760..0000000
--- a/arch/arm/mach-l7200/include/mach/debug-macro.S
+++ /dev/null
@@ -1,38 +0,0 @@
-/* arch/arm/mach-l7200/include/mach/debug-macro.S
- *
- * Debugging macro include header
- *
- *  Copyright (C) 1994-1999 Russell King
- *  Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
-*/
-
-		.equ	io_virt, IO_BASE
-		.equ	io_phys, IO_START
-
-		.macro	addruart, rp, rv, tmp
-		mov	\rp, #0x00044000	@ UART1
-@		mov	\rp, #0x00045000	@ UART2
-		add	\rv, \rp, #io_virt	@ virtual address
-		add	\rp, \rp, #io_phys	@ physical base address
-		.endm
-
-		.macro	senduart,rd,rx
-		str	\rd, [\rx, #0x0]	@ UARTDR
-		.endm
-
-		.macro	waituart,rd,rx
-1001:		ldr	\rd, [\rx, #0x18]	@ UARTFLG
-		tst	\rd, #1 << 5		@ UARTFLGUTXFF - 1 when full
-		bne	1001b
-		.endm
-
-		.macro	busyuart,rd,rx
-1001:		ldr	\rd, [\rx, #0x18]	@ UARTFLG
-		tst	\rd, #1 << 3		@ UARTFLGUBUSY - 1 when busy
-		bne	1001b
-		.endm
diff --git a/arch/arm/mach-mmp/aspenite.c b/arch/arm/mach-mmp/aspenite.c
index 9f64d56..76901f4 100644
--- a/arch/arm/mach-mmp/aspenite.c
+++ b/arch/arm/mach-mmp/aspenite.c
@@ -223,13 +223,7 @@ static struct pxa27x_keypad_platform_data aspenite_keypad_info __initdata = {
 };
 
 #if defined(CONFIG_USB_EHCI_MV)
-static char *pxa168_sph_clock_name[] = {
-	[0] = "PXA168-USBCLK",
-};
-
 static struct mv_usb_platform_data pxa168_sph_pdata = {
-	.clknum         = 1,
-	.clkname        = pxa168_sph_clock_name,
 	.mode           = MV_USB_MODE_HOST,
 	.phy_init	= pxa_usb_phy_init,
 	.phy_deinit	= pxa_usb_phy_deinit,
diff --git a/arch/arm/mach-mmp/ttc_dkb.c b/arch/arm/mach-mmp/ttc_dkb.c
index 22a9058..6528a5f 100644
--- a/arch/arm/mach-mmp/ttc_dkb.c
+++ b/arch/arm/mach-mmp/ttc_dkb.c
@@ -162,13 +162,7 @@ static struct i2c_board_info ttc_dkb_i2c_info[] = {
 #ifdef CONFIG_USB_SUPPORT
 #if defined(CONFIG_USB_MV_UDC) || defined(CONFIG_USB_EHCI_MV_U2O)
 
-static char *pxa910_usb_clock_name[] = {
-	[0] = "U2OCLK",
-};
-
 static struct mv_usb_platform_data ttc_usb_pdata = {
-	.clknum		= 1,
-	.clkname	= pxa910_usb_clock_name,
 	.vbus		= NULL,
 	.mode		= MV_USB_MODE_OTG,
 	.otg_force_a_bus_req = 1,
diff --git a/arch/arm/mach-msm/board-halibut.c b/arch/arm/mach-msm/board-halibut.c
index 84d720a..82eaf88 100644
--- a/arch/arm/mach-msm/board-halibut.c
+++ b/arch/arm/mach-msm/board-halibut.c
@@ -59,6 +59,7 @@ static struct platform_device smc91x_device = {
 };
 
 static struct platform_device *devices[] __initdata = {
+	&msm_device_gpio_7201,
 	&msm_device_uart3,
 	&msm_device_smd,
 	&msm_device_nand,
diff --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c
index 7bc3f82..520c141 100644
--- a/arch/arm/mach-msm/board-msm7x30.c
+++ b/arch/arm/mach-msm/board-msm7x30.c
@@ -89,6 +89,7 @@ struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS] = {
 };
 
 static struct platform_device *devices[] __initdata = {
+	&msm_device_gpio_7x30,
 #if defined(CONFIG_SERIAL_MSM) || defined(CONFIG_MSM_SERIAL_DEBUGGER)
         &msm_device_uart2,
 #endif
diff --git a/arch/arm/mach-msm/board-qsd8x50.c b/arch/arm/mach-msm/board-qsd8x50.c
index 686e794..38a532d 100644
--- a/arch/arm/mach-msm/board-qsd8x50.c
+++ b/arch/arm/mach-msm/board-qsd8x50.c
@@ -89,6 +89,7 @@ static struct msm_otg_platform_data msm_otg_pdata = {
 };
 
 static struct platform_device *devices[] __initdata = {
+	&msm_device_gpio_8x50,
 	&msm_device_uart3,
 	&msm_device_smd,
 	&msm_device_otg,
diff --git a/arch/arm/mach-msm/board-trout.c b/arch/arm/mach-msm/board-trout.c
index 919bfa3..80fe1c5 100644
--- a/arch/arm/mach-msm/board-trout.c
+++ b/arch/arm/mach-msm/board-trout.c
@@ -36,6 +36,7 @@
 extern int trout_init_mmc(unsigned int);
 
 static struct platform_device *devices[] __initdata = {
+	&msm_device_gpio_7201,
 	&msm_device_uart3,
 	&msm_device_smd,
 	&msm_device_nand,
diff --git a/arch/arm/mach-msm/devices-msm7x00.c b/arch/arm/mach-msm/devices-msm7x00.c
index f66ee6e..1a0a230 100644
--- a/arch/arm/mach-msm/devices-msm7x00.c
+++ b/arch/arm/mach-msm/devices-msm7x00.c
@@ -29,6 +29,37 @@
 #include "clock-pcom.h"
 #include <linux/platform_data/mmc-msm_sdcc.h>
 
+static struct resource msm_gpio_resources[] = {
+	{
+		.start	= 32 + 0,
+		.end	= 32 + 0,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.start	= 32 + 1,
+		.end	= 32 + 1,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.start	= 0xa9200800,
+		.end	= 0xa9200800 + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+		.name  = "gpio1"
+	},
+	{
+		.start	= 0xa9300C00,
+		.end	= 0xa9300C00 + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+		.name  = "gpio2"
+	},
+};
+
+struct platform_device msm_device_gpio_7201 = {
+	.name	= "gpio-msm-7201",
+	.num_resources	= ARRAY_SIZE(msm_gpio_resources),
+	.resource	= msm_gpio_resources,
+};
+
 static struct resource resources_uart1[] = {
 	{
 		.start	= INT_UART1,
diff --git a/arch/arm/mach-msm/devices-msm7x30.c b/arch/arm/mach-msm/devices-msm7x30.c
index e90ab59..12f482c 100644
--- a/arch/arm/mach-msm/devices-msm7x30.c
+++ b/arch/arm/mach-msm/devices-msm7x30.c
@@ -33,6 +33,37 @@
 
 #include <linux/platform_data/mmc-msm_sdcc.h>
 
+static struct resource msm_gpio_resources[] = {
+	{
+		.start	= 32 + 18,
+		.end	= 32 + 18,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.start	= 32 + 19,
+		.end	= 32 + 19,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.start	= 0xac001000,
+		.end	= 0xac001000 + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+		.name  = "gpio1"
+	},
+	{
+		.start	= 0xac101400,
+		.end	= 0xac101400 + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+		.name  = "gpio2"
+	},
+};
+
+struct platform_device msm_device_gpio_7x30 = {
+	.name	= "gpio-msm-7x30",
+	.num_resources	= ARRAY_SIZE(msm_gpio_resources),
+	.resource	= msm_gpio_resources,
+};
+
 static struct resource resources_uart2[] = {
 	{
 		.start	= INT_UART2,
diff --git a/arch/arm/mach-msm/devices-qsd8x50.c b/arch/arm/mach-msm/devices-qsd8x50.c
index 4db61d5..2e1b3ec 100644
--- a/arch/arm/mach-msm/devices-qsd8x50.c
+++ b/arch/arm/mach-msm/devices-qsd8x50.c
@@ -30,6 +30,37 @@
 #include <linux/platform_data/mmc-msm_sdcc.h>
 #include "clock-pcom.h"
 
+static struct resource msm_gpio_resources[] = {
+	{
+		.start	= 64 + 165 + 9,
+		.end	= 64 + 165 + 9,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.start	= 64 + 165 + 10,
+		.end	= 64 + 165 + 10,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.start	= 0xa9000800,
+		.end	= 0xa9000800 + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+		.name  = "gpio1"
+	},
+	{
+		.start	= 0xa9100C00,
+		.end	= 0xa9100C00 + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+		.name  = "gpio2"
+	},
+};
+
+struct platform_device msm_device_gpio_8x50 = {
+	.name	= "gpio-msm-8x50",
+	.num_resources	= ARRAY_SIZE(msm_gpio_resources),
+	.resource	= msm_gpio_resources,
+};
+
 static struct resource resources_uart3[] = {
 	{
 		.start	= INT_UART3,
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index 9545c19..da902cf 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -20,6 +20,10 @@
 
 #include "clock.h"
 
+extern struct platform_device msm_device_gpio_7201;
+extern struct platform_device msm_device_gpio_7x30;
+extern struct platform_device msm_device_gpio_8x50;
+
 extern struct platform_device msm_device_uart1;
 extern struct platform_device msm_device_uart2;
 extern struct platform_device msm_device_uart3;
diff --git a/arch/arm/mach-msm/dma.c b/arch/arm/mach-msm/dma.c
index 354b91d..b279fd8 100644
--- a/arch/arm/mach-msm/dma.c
+++ b/arch/arm/mach-msm/dma.c
@@ -19,9 +19,35 @@
 #include <linux/interrupt.h>
 #include <linux/completion.h>
 #include <mach/dma.h>
+#include <mach/msm_iomap.h>
 
 #define MSM_DMOV_CHANNEL_COUNT 16
 
+#define DMOV_SD0(off, ch) (MSM_DMOV_BASE + 0x0000 + (off) + ((ch) << 2))
+#define DMOV_SD1(off, ch) (MSM_DMOV_BASE + 0x0400 + (off) + ((ch) << 2))
+#define DMOV_SD2(off, ch) (MSM_DMOV_BASE + 0x0800 + (off) + ((ch) << 2))
+#define DMOV_SD3(off, ch) (MSM_DMOV_BASE + 0x0C00 + (off) + ((ch) << 2))
+
+#if defined(CONFIG_ARCH_MSM7X30)
+#define DMOV_SD_AARM DMOV_SD2
+#else
+#define DMOV_SD_AARM DMOV_SD3
+#endif
+
+#define DMOV_CMD_PTR(ch)      DMOV_SD_AARM(0x000, ch)
+#define DMOV_RSLT(ch)         DMOV_SD_AARM(0x040, ch)
+#define DMOV_FLUSH0(ch)       DMOV_SD_AARM(0x080, ch)
+#define DMOV_FLUSH1(ch)       DMOV_SD_AARM(0x0C0, ch)
+#define DMOV_FLUSH2(ch)       DMOV_SD_AARM(0x100, ch)
+#define DMOV_FLUSH3(ch)       DMOV_SD_AARM(0x140, ch)
+#define DMOV_FLUSH4(ch)       DMOV_SD_AARM(0x180, ch)
+#define DMOV_FLUSH5(ch)       DMOV_SD_AARM(0x1C0, ch)
+
+#define DMOV_STATUS(ch)       DMOV_SD_AARM(0x200, ch)
+#define DMOV_ISR              DMOV_SD_AARM(0x380, 0)
+
+#define DMOV_CONFIG(ch)       DMOV_SD_AARM(0x300, ch)
+
 enum {
 	MSM_DMOV_PRINT_ERRORS = 1,
 	MSM_DMOV_PRINT_IO = 2,
diff --git a/arch/arm/mach-msm/include/mach/cpu.h b/arch/arm/mach-msm/include/mach/cpu.h
deleted file mode 100644
index a9481b0..0000000
--- a/arch/arm/mach-msm/include/mach/cpu.h
+++ /dev/null
@@ -1,54 +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.
- *
- * You 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 __ARCH_ARM_MACH_MSM_CPU_H__
-#define __ARCH_ARM_MACH_MSM_CPU_H__
-
-/* TODO: For now, only one CPU can be compiled at a time. */
-
-#define cpu_is_msm7x01()	0
-#define cpu_is_msm7x30()	0
-#define cpu_is_qsd8x50()	0
-#define cpu_is_msm8x60()	0
-#define cpu_is_msm8960()	0
-
-#ifdef CONFIG_ARCH_MSM7X00A
-# undef cpu_is_msm7x01
-# define cpu_is_msm7x01()	1
-#endif
-
-#ifdef CONFIG_ARCH_MSM7X30
-# undef cpu_is_msm7x30
-# define cpu_is_msm7x30()	1
-#endif
-
-#ifdef CONFIG_ARCH_QSD8X50
-# undef cpu_is_qsd8x50
-# define cpu_is_qsd8x50()	1
-#endif
-
-#ifdef CONFIG_ARCH_MSM8X60
-# undef cpu_is_msm8x60
-# define cpu_is_msm8x60()	1
-#endif
-
-#ifdef CONFIG_ARCH_MSM8960
-# undef cpu_is_msm8960
-# define cpu_is_msm8960()	1
-#endif
-
-#endif
diff --git a/arch/arm/mach-msm/include/mach/dma.h b/arch/arm/mach-msm/include/mach/dma.h
index 05583f5..a72d48d 100644
--- a/arch/arm/mach-msm/include/mach/dma.h
+++ b/arch/arm/mach-msm/include/mach/dma.h
@@ -16,7 +16,6 @@
 #ifndef __ASM_ARCH_MSM_DMA_H
 
 #include <linux/list.h>
-#include <mach/msm_iomap.h>
 
 struct msm_dmov_errdata {
 	uint32_t flush[6];
@@ -45,48 +44,23 @@ static inline
 int msm_dmov_exec_cmd(unsigned id, unsigned int cmdptr) { return -EIO; }
 #endif
 
-
-#define DMOV_SD0(off, ch) (MSM_DMOV_BASE + 0x0000 + (off) + ((ch) << 2))
-#define DMOV_SD1(off, ch) (MSM_DMOV_BASE + 0x0400 + (off) + ((ch) << 2))
-#define DMOV_SD2(off, ch) (MSM_DMOV_BASE + 0x0800 + (off) + ((ch) << 2))
-#define DMOV_SD3(off, ch) (MSM_DMOV_BASE + 0x0C00 + (off) + ((ch) << 2))
-
-#if defined(CONFIG_ARCH_MSM7X30)
-#define DMOV_SD_AARM DMOV_SD2
-#else
-#define DMOV_SD_AARM DMOV_SD3
-#endif
-
-#define DMOV_CMD_PTR(ch)      DMOV_SD_AARM(0x000, ch)
 #define DMOV_CMD_LIST         (0 << 29) /* does not work */
 #define DMOV_CMD_PTR_LIST     (1 << 29) /* works */
 #define DMOV_CMD_INPUT_CFG    (2 << 29) /* untested */
 #define DMOV_CMD_OUTPUT_CFG   (3 << 29) /* untested */
 #define DMOV_CMD_ADDR(addr)   ((addr) >> 3)
 
-#define DMOV_RSLT(ch)         DMOV_SD_AARM(0x040, ch)
 #define DMOV_RSLT_VALID       (1 << 31) /* 0 == host has empties result fifo */
 #define DMOV_RSLT_ERROR       (1 << 3)
 #define DMOV_RSLT_FLUSH       (1 << 2)
 #define DMOV_RSLT_DONE        (1 << 1)  /* top pointer done */
 #define DMOV_RSLT_USER        (1 << 0)  /* command with FR force result */
 
-#define DMOV_FLUSH0(ch)       DMOV_SD_AARM(0x080, ch)
-#define DMOV_FLUSH1(ch)       DMOV_SD_AARM(0x0C0, ch)
-#define DMOV_FLUSH2(ch)       DMOV_SD_AARM(0x100, ch)
-#define DMOV_FLUSH3(ch)       DMOV_SD_AARM(0x140, ch)
-#define DMOV_FLUSH4(ch)       DMOV_SD_AARM(0x180, ch)
-#define DMOV_FLUSH5(ch)       DMOV_SD_AARM(0x1C0, ch)
-
-#define DMOV_STATUS(ch)       DMOV_SD_AARM(0x200, ch)
 #define DMOV_STATUS_RSLT_COUNT(n)    (((n) >> 29))
 #define DMOV_STATUS_CMD_COUNT(n)     (((n) >> 27) & 3)
 #define DMOV_STATUS_RSLT_VALID       (1 << 1)
 #define DMOV_STATUS_CMD_PTR_RDY      (1 << 0)
 
-#define DMOV_ISR              DMOV_SD_AARM(0x380, 0)
-  
-#define DMOV_CONFIG(ch)       DMOV_SD_AARM(0x300, ch)
 #define DMOV_CONFIG_FORCE_TOP_PTR_RSLT (1 << 2)
 #define DMOV_CONFIG_FORCE_FLUSH_RSLT   (1 << 1)
 #define DMOV_CONFIG_IRQ_EN             (1 << 0)
diff --git a/arch/arm/mach-msm/last_radio_log.c b/arch/arm/mach-msm/last_radio_log.c
index 1e243f4..7777767 100644
--- a/arch/arm/mach-msm/last_radio_log.c
+++ b/arch/arm/mach-msm/last_radio_log.c
@@ -31,20 +31,8 @@ extern void *smem_item(unsigned id, unsigned *size);
 static ssize_t last_radio_log_read(struct file *file, char __user *buf,
 			size_t len, loff_t *offset)
 {
-	loff_t pos = *offset;
-	ssize_t count;
-
-	if (pos >= radio_log_size)
-		return 0;
-
-	count = min(len, (size_t)(radio_log_size - pos));
-	if (copy_to_user(buf, radio_log_base + pos, count)) {
-		pr_err("%s: copy to user failed\n", __func__);
-		return -EFAULT;
-	}
-
-	*offset += count;
-	return count;
+	return simple_read_from_buffer(buf, len, offset,
+				radio_log_base, radio_log_size);
 }
 
 static struct file_operations last_radio_log_fops = {
@@ -67,7 +55,8 @@ void msm_init_last_radio_log(struct module *owner)
 		return;
 	}
 
-	entry = create_proc_entry("last_radio_log", S_IFREG | S_IRUGO, NULL);
+	entry = proc_create("last_radio_log", S_IRUGO, NULL,
+				&last_radio_log_fops);
 	if (!entry) {
 		pr_err("%s: could not create proc entry for radio log\n",
 				__func__);
@@ -77,7 +66,6 @@ void msm_init_last_radio_log(struct module *owner)
 	pr_err("%s: last radio log is %d bytes long\n", __func__,
 		radio_log_size);
 	last_radio_log_fops.owner = owner;
-	entry->proc_fops = &last_radio_log_fops;
 	entry->size = radio_log_size;
 }
 EXPORT_SYMBOL(msm_init_last_radio_log);
diff --git a/arch/arm/mach-msm/platsmp.c b/arch/arm/mach-msm/platsmp.c
index 42932865..00cdb0a 100644
--- a/arch/arm/mach-msm/platsmp.c
+++ b/arch/arm/mach-msm/platsmp.c
@@ -15,7 +15,6 @@
 #include <linux/jiffies.h>
 #include <linux/smp.h>
 #include <linux/io.h>
-#include <linux/irqchip/arm-gic.h>
 
 #include <asm/cacheflush.h>
 #include <asm/cputype.h>
@@ -42,13 +41,6 @@ static inline int get_core_count(void)
 static void __cpuinit msm_secondary_init(unsigned int cpu)
 {
 	/*
-	 * if any interrupts are already enabled for the primary
-	 * core (e.g. timer irq), then they will not have been enabled
-	 * for us: do so
-	 */
-	gic_secondary_init(0);
-
-	/*
 	 * let the primary processor know we're out of the
 	 * pen, then head off into the C entry point
 	 */
diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c
index 2969027..284313f 100644
--- a/arch/arm/mach-msm/timer.c
+++ b/arch/arm/mach-msm/timer.c
@@ -30,19 +30,22 @@
 
 #include "common.h"
 
-#define TIMER_MATCH_VAL         0x0000
-#define TIMER_COUNT_VAL         0x0004
-#define TIMER_ENABLE            0x0008
-#define TIMER_ENABLE_CLR_ON_MATCH_EN    BIT(1)
-#define TIMER_ENABLE_EN                 BIT(0)
-#define TIMER_CLEAR             0x000C
-#define DGT_CLK_CTL_DIV_4	0x3
+#define TIMER_MATCH_VAL			0x0000
+#define TIMER_COUNT_VAL			0x0004
+#define TIMER_ENABLE			0x0008
+#define TIMER_ENABLE_CLR_ON_MATCH_EN	BIT(1)
+#define TIMER_ENABLE_EN			BIT(0)
+#define TIMER_CLEAR			0x000C
+#define DGT_CLK_CTL			0x10
+#define DGT_CLK_CTL_DIV_4		0x3
+#define TIMER_STS_GPT0_CLR_PEND		BIT(10)
 
 #define GPT_HZ 32768
 
 #define MSM_DGT_SHIFT 5
 
 static void __iomem *event_base;
+static void __iomem *sts_base;
 
 static irqreturn_t msm_timer_interrupt(int irq, void *dev_id)
 {
@@ -62,8 +65,16 @@ static int msm_timer_set_next_event(unsigned long cycles,
 {
 	u32 ctrl = readl_relaxed(event_base + TIMER_ENABLE);
 
-	writel_relaxed(0, event_base + TIMER_CLEAR);
+	ctrl &= ~TIMER_ENABLE_EN;
+	writel_relaxed(ctrl, event_base + TIMER_ENABLE);
+
+	writel_relaxed(ctrl, event_base + TIMER_CLEAR);
 	writel_relaxed(cycles, event_base + TIMER_MATCH_VAL);
+
+	if (sts_base)
+		while (readl_relaxed(sts_base) & TIMER_STS_GPT0_CLR_PEND)
+			cpu_relax();
+
 	writel_relaxed(ctrl | TIMER_ENABLE_EN, event_base + TIMER_ENABLE);
 	return 0;
 }
@@ -134,9 +145,6 @@ static int __cpuinit msm_local_timer_setup(struct clock_event_device *evt)
 	if (!smp_processor_id())
 		return 0;
 
-	writel_relaxed(0, event_base + TIMER_ENABLE);
-	writel_relaxed(0, event_base + TIMER_CLEAR);
-	writel_relaxed(~0, event_base + TIMER_MATCH_VAL);
 	evt->irq = msm_clockevent.irq;
 	evt->name = "local_timer";
 	evt->features = msm_clockevent.features;
@@ -174,9 +182,6 @@ static void __init msm_timer_init(u32 dgt_hz, int sched_bits, int irq,
 	struct clocksource *cs = &msm_clocksource;
 	int res;
 
-	writel_relaxed(0, event_base + TIMER_ENABLE);
-	writel_relaxed(0, event_base + TIMER_CLEAR);
-	writel_relaxed(~0, event_base + TIMER_MATCH_VAL);
 	ce->cpumask = cpumask_of(0);
 	ce->irq = irq;
 
@@ -214,13 +219,9 @@ err:
 }
 
 #ifdef CONFIG_OF
-static const struct of_device_id msm_dgt_match[] __initconst = {
-	{ .compatible = "qcom,msm-dgt" },
-	{ },
-};
-
-static const struct of_device_id msm_gpt_match[] __initconst = {
-	{ .compatible = "qcom,msm-gpt" },
+static const struct of_device_id msm_timer_match[] __initconst = {
+	{ .compatible = "qcom,kpss-timer" },
+	{ .compatible = "qcom,scss-timer" },
 	{ },
 };
 
@@ -231,33 +232,29 @@ void __init msm_dt_timer_init(void)
 	int irq;
 	struct resource res;
 	u32 percpu_offset;
-	void __iomem *dgt_clk_ctl;
+	void __iomem *base;
+	void __iomem *cpu0_base;
 
-	np = of_find_matching_node(NULL, msm_gpt_match);
+	np = of_find_matching_node(NULL, msm_timer_match);
 	if (!np) {
-		pr_err("Can't find GPT DT node\n");
+		pr_err("Can't find msm timer DT node\n");
 		return;
 	}
 
-	event_base = of_iomap(np, 0);
-	if (!event_base) {
+	base = of_iomap(np, 0);
+	if (!base) {
 		pr_err("Failed to map event base\n");
 		return;
 	}
 
-	irq = irq_of_parse_and_map(np, 0);
+	/* We use GPT0 for the clockevent */
+	irq = irq_of_parse_and_map(np, 1);
 	if (irq <= 0) {
 		pr_err("Can't get irq\n");
 		return;
 	}
-	of_node_put(np);
-
-	np = of_find_matching_node(NULL, msm_dgt_match);
-	if (!np) {
-		pr_err("Can't find DGT DT node\n");
-		return;
-	}
 
+	/* We use CPU0's DGT for the clocksource */
 	if (of_property_read_u32(np, "cpu-offset", &percpu_offset))
 		percpu_offset = 0;
 
@@ -266,45 +263,43 @@ void __init msm_dt_timer_init(void)
 		return;
 	}
 
-	source_base = ioremap(res.start + percpu_offset, resource_size(&res));
-	if (!source_base) {
+	cpu0_base = ioremap(res.start + percpu_offset, resource_size(&res));
+	if (!cpu0_base) {
 		pr_err("Failed to map source base\n");
 		return;
 	}
 
-	if (!of_address_to_resource(np, 1, &res)) {
-		dgt_clk_ctl = ioremap(res.start + percpu_offset,
-				      resource_size(&res));
-		if (!dgt_clk_ctl) {
-			pr_err("Failed to map DGT control base\n");
-			return;
-		}
-		writel_relaxed(DGT_CLK_CTL_DIV_4, dgt_clk_ctl);
-		iounmap(dgt_clk_ctl);
-	}
-
 	if (of_property_read_u32(np, "clock-frequency", &freq)) {
 		pr_err("Unknown frequency\n");
 		return;
 	}
 	of_node_put(np);
 
+	event_base = base + 0x4;
+	sts_base = base + 0x88;
+	source_base = cpu0_base + 0x24;
+	freq /= 4;
+	writel_relaxed(DGT_CLK_CTL_DIV_4, source_base + DGT_CLK_CTL);
+
 	msm_timer_init(freq, 32, irq, !!percpu_offset);
 }
 #endif
 
-static int __init msm_timer_map(phys_addr_t event, phys_addr_t source)
+static int __init msm_timer_map(phys_addr_t addr, u32 event, u32 source,
+				u32 sts)
 {
-	event_base = ioremap(event, SZ_64);
-	if (!event_base) {
-		pr_err("Failed to map event base\n");
-		return 1;
-	}
-	source_base = ioremap(source, SZ_64);
-	if (!source_base) {
-		pr_err("Failed to map source base\n");
-		return 1;
+	void __iomem *base;
+
+	base = ioremap(addr, SZ_256);
+	if (!base) {
+		pr_err("Failed to map timer base\n");
+		return -ENOMEM;
 	}
+	event_base = base + event;
+	source_base = base + source;
+	if (sts)
+		sts_base = base + sts;
+
 	return 0;
 }
 
@@ -312,7 +307,7 @@ void __init msm7x01_timer_init(void)
 {
 	struct clocksource *cs = &msm_clocksource;
 
-	if (msm_timer_map(0xc0100000, 0xc0100010))
+	if (msm_timer_map(0xc0100000, 0x0, 0x10, 0x0))
 		return;
 	cs->read = msm_read_timer_count_shift;
 	cs->mask = CLOCKSOURCE_MASK((32 - MSM_DGT_SHIFT));
@@ -323,14 +318,14 @@ void __init msm7x01_timer_init(void)
 
 void __init msm7x30_timer_init(void)
 {
-	if (msm_timer_map(0xc0100004, 0xc0100024))
+	if (msm_timer_map(0xc0100000, 0x4, 0x24, 0x80))
 		return;
 	msm_timer_init(24576000 / 4, 32, 1, false);
 }
 
 void __init qsd8x50_timer_init(void)
 {
-	if (msm_timer_map(0xAC100000, 0xAC100010))
+	if (msm_timer_map(0xAC100000, 0x0, 0x10, 0x34))
 		return;
 	msm_timer_init(19200000 / 4, 32, 7, false);
 }
diff --git a/arch/arm/mach-mvebu/irq-armada-370-xp.c b/arch/arm/mach-mvebu/irq-armada-370-xp.c
index 274ff58..2cae252 100644
--- a/arch/arm/mach-mvebu/irq-armada-370-xp.c
+++ b/arch/arm/mach-mvebu/irq-armada-370-xp.c
@@ -44,6 +44,8 @@
 
 #define ARMADA_370_XP_MAX_PER_CPU_IRQS		(28)
 
+#define ARMADA_370_XP_TIMER0_PER_CPU_IRQ	(5)
+
 #define ACTIVE_DOORBELLS			(8)
 
 static DEFINE_RAW_SPINLOCK(irq_controller_lock);
@@ -55,14 +57,14 @@ static struct irq_domain *armada_370_xp_mpic_domain;
 /*
  * In SMP mode:
  * For shared global interrupts, mask/unmask global enable bit
- * For CPU interrtups, mask/unmask the calling CPU's bit
+ * For CPU interrupts, mask/unmask the calling CPU's bit
  */
 static void armada_370_xp_irq_mask(struct irq_data *d)
 {
 #ifdef CONFIG_SMP
 	irq_hw_number_t hwirq = irqd_to_hwirq(d);
 
-	if (hwirq > ARMADA_370_XP_MAX_PER_CPU_IRQS)
+	if (hwirq != ARMADA_370_XP_TIMER0_PER_CPU_IRQ)
 		writel(hwirq, main_int_base +
 				ARMADA_370_XP_INT_CLEAR_ENABLE_OFFS);
 	else
@@ -79,7 +81,7 @@ static void armada_370_xp_irq_unmask(struct irq_data *d)
 #ifdef CONFIG_SMP
 	irq_hw_number_t hwirq = irqd_to_hwirq(d);
 
-	if (hwirq > ARMADA_370_XP_MAX_PER_CPU_IRQS)
+	if (hwirq != ARMADA_370_XP_TIMER0_PER_CPU_IRQ)
 		writel(hwirq, main_int_base +
 				ARMADA_370_XP_INT_SET_ENABLE_OFFS);
 	else
@@ -147,7 +149,7 @@ static int armada_370_xp_mpic_irq_map(struct irq_domain *h,
 	writel(hw, main_int_base + ARMADA_370_XP_INT_SET_ENABLE_OFFS);
 	irq_set_status_flags(virq, IRQ_LEVEL);
 
-	if (hw < ARMADA_370_XP_MAX_PER_CPU_IRQS) {
+	if (hw == ARMADA_370_XP_TIMER0_PER_CPU_IRQ) {
 		irq_set_percpu_devid(virq);
 		irq_set_chip_and_handler(virq, &armada_370_xp_irq_chip,
 					handle_percpu_devid_irq);
diff --git a/arch/arm/mach-mxs/Kconfig b/arch/arm/mach-mxs/Kconfig
index ecc4319..4dc2fbb 100644
--- a/arch/arm/mach-mxs/Kconfig
+++ b/arch/arm/mach-mxs/Kconfig
@@ -1,8 +1,7 @@
-if ARCH_MXS
-
 config SOC_IMX23
 	bool
 	select ARM_AMBA
+	select ARM_CPU_SUSPEND if PM
 	select CPU_ARM926T
 	select HAVE_PWM
 	select PINCTRL_IMX23
@@ -10,19 +9,24 @@ config SOC_IMX23
 config SOC_IMX28
 	bool
 	select ARM_AMBA
+	select ARM_CPU_SUSPEND if PM
 	select CPU_ARM926T
 	select HAVE_CAN_FLEXCAN if CAN
 	select HAVE_PWM
 	select PINCTRL_IMX28
 
-comment "MXS platforms:"
-
-config MACH_MXS_DT
-	bool "Support MXS platforms from device tree"
+config ARCH_MXS
+	bool "Freescale MXS (i.MX23, i.MX28) support"
+	depends on ARCH_MULTI_V5
+	select ARCH_REQUIRE_GPIOLIB
+	select CLKDEV_LOOKUP
+	select CLKSRC_MMIO
+	select CLKSRC_OF
+	select GENERIC_CLOCKEVENTS
+	select HAVE_CLK_PREPARE
+	select PINCTRL
 	select SOC_IMX23
 	select SOC_IMX28
+	select STMP_DEVICE
 	help
-	  Include support for Freescale MXS platforms(i.MX23 and i.MX28)
-	  using the device tree for discovery
-
-endif
+	  Support for Freescale MXS-based family of processors
diff --git a/arch/arm/mach-mxs/Makefile b/arch/arm/mach-mxs/Makefile
index 3d3c8a9..cc2bf67 100644
--- a/arch/arm/mach-mxs/Makefile
+++ b/arch/arm/mach-mxs/Makefile
@@ -1,6 +1,2 @@
-# Common support
-obj-y := icoll.o ocotp.o system.o timer.o mm.o
-
 obj-$(CONFIG_PM) += pm.o
-
-obj-$(CONFIG_MACH_MXS_DT) += mach-mxs.o
+obj-$(CONFIG_ARCH_MXS) += mach-mxs.o
diff --git a/arch/arm/mach-mxs/Makefile.boot b/arch/arm/mach-mxs/Makefile.boot
deleted file mode 100644
index 07b11fe..0000000
--- a/arch/arm/mach-mxs/Makefile.boot
+++ /dev/null
@@ -1 +0,0 @@
-zreladdr-y += 0x40008000
diff --git a/arch/arm/mach-mxs/icoll.c b/arch/arm/mach-mxs/icoll.c
deleted file mode 100644
index e26eeba..0000000
--- a/arch/arm/mach-mxs/icoll.c
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (C) 2009-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/kernel.h>
-#include <linux/init.h>
-#include <linux/irq.h>
-#include <linux/irqdomain.h>
-#include <linux/io.h>
-#include <linux/of.h>
-#include <linux/of_irq.h>
-#include <asm/exception.h>
-#include <mach/mxs.h>
-#include <mach/common.h>
-
-#define HW_ICOLL_VECTOR				0x0000
-#define HW_ICOLL_LEVELACK			0x0010
-#define HW_ICOLL_CTRL				0x0020
-#define HW_ICOLL_STAT_OFFSET			0x0070
-#define HW_ICOLL_INTERRUPTn_SET(n)		(0x0124 + (n) * 0x10)
-#define HW_ICOLL_INTERRUPTn_CLR(n)		(0x0128 + (n) * 0x10)
-#define BM_ICOLL_INTERRUPTn_ENABLE		0x00000004
-#define BV_ICOLL_LEVELACK_IRQLEVELACK__LEVEL0	0x1
-
-#define ICOLL_NUM_IRQS		128
-
-static void __iomem *icoll_base = MXS_IO_ADDRESS(MXS_ICOLL_BASE_ADDR);
-static struct irq_domain *icoll_domain;
-
-static void icoll_ack_irq(struct irq_data *d)
-{
-	/*
-	 * The Interrupt Collector is able to prioritize irqs.
-	 * Currently only level 0 is used. So acking can use
-	 * BV_ICOLL_LEVELACK_IRQLEVELACK__LEVEL0 unconditionally.
-	 */
-	__raw_writel(BV_ICOLL_LEVELACK_IRQLEVELACK__LEVEL0,
-			icoll_base + HW_ICOLL_LEVELACK);
-}
-
-static void icoll_mask_irq(struct irq_data *d)
-{
-	__raw_writel(BM_ICOLL_INTERRUPTn_ENABLE,
-			icoll_base + HW_ICOLL_INTERRUPTn_CLR(d->hwirq));
-}
-
-static void icoll_unmask_irq(struct irq_data *d)
-{
-	__raw_writel(BM_ICOLL_INTERRUPTn_ENABLE,
-			icoll_base + HW_ICOLL_INTERRUPTn_SET(d->hwirq));
-}
-
-static struct irq_chip mxs_icoll_chip = {
-	.irq_ack = icoll_ack_irq,
-	.irq_mask = icoll_mask_irq,
-	.irq_unmask = icoll_unmask_irq,
-};
-
-asmlinkage void __exception_irq_entry icoll_handle_irq(struct pt_regs *regs)
-{
-	u32 irqnr;
-
-	do {
-		irqnr = __raw_readl(icoll_base + HW_ICOLL_STAT_OFFSET);
-		if (irqnr != 0x7f) {
-			__raw_writel(irqnr, icoll_base + HW_ICOLL_VECTOR);
-			irqnr = irq_find_mapping(icoll_domain, irqnr);
-			handle_IRQ(irqnr, regs);
-			continue;
-		}
-		break;
-	} while (1);
-}
-
-static int icoll_irq_domain_map(struct irq_domain *d, unsigned int virq,
-				irq_hw_number_t hw)
-{
-	irq_set_chip_and_handler(virq, &mxs_icoll_chip, handle_level_irq);
-	set_irq_flags(virq, IRQF_VALID);
-
-	return 0;
-}
-
-static struct irq_domain_ops icoll_irq_domain_ops = {
-	.map = icoll_irq_domain_map,
-	.xlate = irq_domain_xlate_onecell,
-};
-
-static void __init icoll_of_init(struct device_node *np,
-			  struct device_node *interrupt_parent)
-{
-	/*
-	 * Interrupt Collector reset, which initializes the priority
-	 * for each irq to level 0.
-	 */
-	mxs_reset_block(icoll_base + HW_ICOLL_CTRL);
-
-	icoll_domain = irq_domain_add_linear(np, ICOLL_NUM_IRQS,
-					     &icoll_irq_domain_ops, NULL);
-	WARN_ON(!icoll_domain);
-}
-
-static const struct of_device_id icoll_of_match[] __initconst = {
-	{.compatible = "fsl,icoll", .data = icoll_of_init},
-	{ /* sentinel */ }
-};
-
-void __init icoll_init_irq(void)
-{
-	of_irq_init(icoll_of_match);
-}
diff --git a/arch/arm/mach-mxs/include/mach/common.h b/arch/arm/mach-mxs/include/mach/common.h
deleted file mode 100644
index be5a9c9..0000000
--- a/arch/arm/mach-mxs/include/mach/common.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2004-2007 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.
- */
-
-#ifndef __MACH_MXS_COMMON_H__
-#define __MACH_MXS_COMMON_H__
-
-extern const u32 *mxs_get_ocotp(void);
-extern int mxs_reset_block(void __iomem *);
-extern void mxs_timer_init(void);
-extern void mxs_restart(char, const char *);
-extern int mxs_saif_clkmux_select(unsigned int clkmux);
-
-extern int mx23_clocks_init(void);
-extern void mx23_map_io(void);
-
-extern int mx28_clocks_init(void);
-extern void mx28_map_io(void);
-
-extern void icoll_init_irq(void);
-extern void icoll_handle_irq(struct pt_regs *);
-
-#endif /* __MACH_MXS_COMMON_H__ */
diff --git a/arch/arm/mach-mxs/include/mach/debug-macro.S b/arch/arm/mach-mxs/include/mach/debug-macro.S
deleted file mode 100644
index 90c6b78..0000000
--- a/arch/arm/mach-mxs/include/mach/debug-macro.S
+++ /dev/null
@@ -1,30 +0,0 @@
-/* arch/arm/mach-mxs/include/mach/debug-macro.S
- *
- * Debugging macro include header
- *
- *  Copyright (C) 1994-1999 Russell King
- *  Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-
-#include <mach/mx23.h>
-#include <mach/mx28.h>
-
-#ifdef CONFIG_DEBUG_IMX23_UART
-#define UART_PADDR	MX23_DUART_BASE_ADDR
-#elif defined (CONFIG_DEBUG_IMX28_UART)
-#define UART_PADDR	MX28_DUART_BASE_ADDR
-#endif
-
-#define UART_VADDR	MXS_IO_ADDRESS(UART_PADDR)
-
-		.macro	addruart, rp, rv, tmp
-		ldr	\rp, =UART_PADDR	@ physical
-		ldr	\rv, =UART_VADDR	@ virtual
-		.endm
-
-#include <asm/hardware/debug-pl01x.S>
diff --git a/arch/arm/mach-mxs/include/mach/digctl.h b/arch/arm/mach-mxs/include/mach/digctl.h
deleted file mode 100644
index 1796406..0000000
--- a/arch/arm/mach-mxs/include/mach/digctl.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef __MACH_DIGCTL_H__
-#define __MACH_DIGCTL_H__
-
-/* MXS DIGCTL SAIF CLKMUX */
-#define MXS_DIGCTL_SAIF_CLKMUX_DIRECT		0x0
-#define MXS_DIGCTL_SAIF_CLKMUX_CROSSINPUT	0x1
-#define MXS_DIGCTL_SAIF_CLKMUX_EXTMSTR0		0x2
-#define MXS_DIGCTL_SAIF_CLKMUX_EXTMSTR1		0x3
-
-#define HW_DIGCTL_CTRL			0x0
-#define  BP_DIGCTL_CTRL_SAIF_CLKMUX	10
-#define  BM_DIGCTL_CTRL_SAIF_CLKMUX	(0x3 << 10)
-#define HW_DIGCTL_CHIPID		0x310
-#endif
diff --git a/arch/arm/mach-mxs/include/mach/hardware.h b/arch/arm/mach-mxs/include/mach/hardware.h
deleted file mode 100644
index 4c0e8a6..0000000
--- a/arch/arm/mach-mxs/include/mach/hardware.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright 2004-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 __MACH_MXS_HARDWARE_H__
-#define __MACH_MXS_HARDWARE_H__
-
-#endif /* __MACH_MXS_HARDWARE_H__ */
diff --git a/arch/arm/mach-mxs/include/mach/mx23.h b/arch/arm/mach-mxs/include/mach/mx23.h
deleted file mode 100644
index 599094b..0000000
--- a/arch/arm/mach-mxs/include/mach/mx23.h
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Copyright (C) 2009-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.
- */
-
-#ifndef __MACH_MX23_H__
-#define __MACH_MX23_H__
-
-#include <mach/mxs.h>
-
-/*
- * OCRAM
- */
-#define MX23_OCRAM_BASE_ADDR		0x00000000
-#define MX23_OCRAM_SIZE			SZ_32K
-
-/*
- * IO
- */
-#define MX23_IO_BASE_ADDR		0x80000000
-#define MX23_IO_SIZE			SZ_1M
-
-#define MX23_ICOLL_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x000000)
-#define MX23_APBH_DMA_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x004000)
-#define MX23_BCH_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x00a000)
-#define MX23_GPMI_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x00c000)
-#define MX23_SSP1_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x010000)
-#define MX23_PINCTRL_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x018000)
-#define MX23_DIGCTL_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x01c000)
-#define MX23_ETM_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x020000)
-#define MX23_APBX_DMA_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x024000)
-#define MX23_DCP_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x028000)
-#define MX23_PXP_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x02a000)
-#define MX23_OCOTP_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x02c000)
-#define MX23_AXI_AHB0_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x02e000)
-#define MX23_LCDIF_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x030000)
-#define MX23_SSP2_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x034000)
-#define MX23_TVENC_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x038000)
-#define MX23_CLKCTRL_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x040000)
-#define MX23_SAIF0_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x042000)
-#define MX23_POWER_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x044000)
-#define MX23_SAIF1_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x046000)
-#define MX23_AUDIOOUT_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x048000)
-#define MX23_AUDIOIN_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x04c000)
-#define MX23_LRADC_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x050000)
-#define MX23_SPDIF_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x054000)
-#define MX23_I2C_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x058000)
-#define MX23_RTC_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x05c000)
-#define MX23_PWM_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x064000)
-#define MX23_TIMROT_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x068000)
-#define MX23_AUART1_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x06c000)
-#define MX23_AUART2_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x06e000)
-#define MX23_DUART_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x070000)
-#define MX23_USBPHY_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x07c000)
-#define MX23_USBCTRL_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x080000)
-#define MX23_DRAM_BASE_ADDR		(MX23_IO_BASE_ADDR + 0x0e0000)
-
-#define MX23_IO_P2V(x)			MXS_IO_P2V(x)
-#define MX23_IO_ADDRESS(x)		IOMEM(MX23_IO_P2V(x))
-
-/*
- * IRQ
- */
-#define MX23_INT_DUART			0
-#define MX23_INT_COMMS_RX		1
-#define MX23_INT_COMMS_TX		1
-#define MX23_INT_SSP2_ERROR		2
-#define MX23_INT_VDD5V			3
-#define MX23_INT_HEADPHONE_SHORT	4
-#define MX23_INT_DAC_DMA		5
-#define MX23_INT_DAC_ERROR		6
-#define MX23_INT_ADC_DMA		7
-#define MX23_INT_ADC_ERROR		8
-#define MX23_INT_SPDIF_DMA		9
-#define MX23_INT_SAIF2_DMA		9
-#define MX23_INT_SPDIF_ERROR		10
-#define MX23_INT_SAIF1_IRQ		10
-#define MX23_INT_SAIF2_IRQ		10
-#define MX23_INT_USB_CTRL		11
-#define MX23_INT_USB_WAKEUP		12
-#define MX23_INT_GPMI_DMA		13
-#define MX23_INT_SSP1_DMA		14
-#define MX23_INT_SSP1_ERROR		15
-#define MX23_INT_GPIO0			16
-#define MX23_INT_GPIO1			17
-#define MX23_INT_GPIO2			18
-#define MX23_INT_SAIF1_DMA		19
-#define MX23_INT_SSP2_DMA		20
-#define MX23_INT_ECC8_IRQ		21
-#define MX23_INT_RTC_ALARM		22
-#define MX23_INT_AUART1_TX_DMA		23
-#define MX23_INT_AUART1			24
-#define MX23_INT_AUART1_RX_DMA		25
-#define MX23_INT_I2C_DMA		26
-#define MX23_INT_I2C_ERROR		27
-#define MX23_INT_TIMER0			28
-#define MX23_INT_TIMER1			29
-#define MX23_INT_TIMER2			30
-#define MX23_INT_TIMER3			31
-#define MX23_INT_BATT_BRNOUT		32
-#define MX23_INT_VDDD_BRNOUT		33
-#define MX23_INT_VDDIO_BRNOUT		34
-#define MX23_INT_VDD18_BRNOUT		35
-#define MX23_INT_TOUCH_DETECT		36
-#define MX23_INT_LRADC_CH0		37
-#define MX23_INT_LRADC_CH1		38
-#define MX23_INT_LRADC_CH2		39
-#define MX23_INT_LRADC_CH3		40
-#define MX23_INT_LRADC_CH4		41
-#define MX23_INT_LRADC_CH5		42
-#define MX23_INT_LRADC_CH6		43
-#define MX23_INT_LRADC_CH7		44
-#define MX23_INT_LCDIF_DMA		45
-#define MX23_INT_LCDIF_ERROR		46
-#define MX23_INT_DIGCTL_DEBUG_TRAP	47
-#define MX23_INT_RTC_1MSEC		48
-#define MX23_INT_DRI_DMA		49
-#define MX23_INT_DRI_ATTENTION		50
-#define MX23_INT_GPMI_ATTENTION		51
-#define MX23_INT_IR			52
-#define MX23_INT_DCP_VMI		53
-#define MX23_INT_DCP			54
-#define MX23_INT_BCH			56
-#define MX23_INT_PXP			57
-#define MX23_INT_AUART2_TX_DMA		58
-#define MX23_INT_AUART2			59
-#define MX23_INT_AUART2_RX_DMA		60
-#define MX23_INT_VDAC_DETECT		61
-#define MX23_INT_VDD5V_DROOP		64
-#define MX23_INT_DCDC4P2_BO		65
-
-/*
- * APBH DMA
- */
-#define MX23_DMA_SSP1			1
-#define MX23_DMA_SSP2			2
-#define MX23_DMA_GPMI0			4
-#define MX23_DMA_GPMI1			5
-#define MX23_DMA_GPMI2			6
-#define MX23_DMA_GPMI3			7
-
-/*
- * APBX DMA
- */
-#define MX23_DMA_ADC			0
-#define MX23_DMA_DAC			1
-#define MX23_DMA_SPDIF			2
-#define MX23_DMA_I2C			3
-#define MX23_DMA_SAIF0			4
-#define MX23_DMA_UART0_RX		6
-#define MX23_DMA_UART0_TX		7
-#define MX23_DMA_UART1_RX		8
-#define MX23_DMA_UART1_TX		9
-#define MX23_DMA_SAIF1			10
-
-#endif /* __MACH_MX23_H__ */
diff --git a/arch/arm/mach-mxs/include/mach/mx28.h b/arch/arm/mach-mxs/include/mach/mx28.h
deleted file mode 100644
index 30c7990..0000000
--- a/arch/arm/mach-mxs/include/mach/mx28.h
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * Copyright (C) 2009-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.
- */
-
-#ifndef __MACH_MX28_H__
-#define __MACH_MX28_H__
-
-#include <mach/mxs.h>
-
-/*
- * OCRAM
- */
-#define MX28_OCRAM_BASE_ADDR		0x00000000
-#define MX28_OCRAM_SIZE			SZ_128K
-
-/*
- * IO
- */
-#define MX28_IO_BASE_ADDR		0x80000000
-#define MX28_IO_SIZE			SZ_1M
-
-#define MX28_ICOLL_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x000000)
-#define MX28_HSADC_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x002000)
-#define MX28_APBH_DMA_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x004000)
-#define MX28_PERFMON_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x006000)
-#define MX28_BCH_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x00a000)
-#define MX28_GPMI_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x00c000)
-#define MX28_SSP0_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x010000)
-#define MX28_SSP1_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x012000)
-#define MX28_SSP2_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x014000)
-#define MX28_SSP3_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x016000)
-#define MX28_PINCTRL_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x018000)
-#define MX28_DIGCTL_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x01c000)
-#define MX28_ETM_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x022000)
-#define MX28_APBX_DMA_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x024000)
-#define MX28_DCP_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x028000)
-#define MX28_PXP_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x02a000)
-#define MX28_OCOTP_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x02c000)
-#define MX28_AXI_AHB0_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x02e000)
-#define MX28_LCDIF_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x030000)
-#define MX28_CAN0_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x032000)
-#define MX28_CAN1_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x034000)
-#define MX28_SIMDBG_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x03c000)
-#define MX28_SIMGPMISEL_BASE_ADDR	(MX28_IO_BASE_ADDR + 0x03c200)
-#define MX28_SIMSSPSEL_BASE_ADDR	(MX28_IO_BASE_ADDR + 0x03c300)
-#define MX28_SIMMEMSEL_BASE_ADDR	(MX28_IO_BASE_ADDR + 0x03c400)
-#define MX28_GPIOMON_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x03c500)
-#define MX28_SIMENET_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x03c700)
-#define MX28_ARMJTAG_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x03c800)
-#define MX28_CLKCTRL_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x040000)
-#define MX28_SAIF0_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x042000)
-#define MX28_POWER_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x044000)
-#define MX28_SAIF1_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x046000)
-#define MX28_LRADC_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x050000)
-#define MX28_SPDIF_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x054000)
-#define MX28_RTC_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x056000)
-#define MX28_I2C0_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x058000)
-#define MX28_I2C1_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x05a000)
-#define MX28_PWM_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x064000)
-#define MX28_TIMROT_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x068000)
-#define MX28_AUART0_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x06a000)
-#define MX28_AUART1_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x06c000)
-#define MX28_AUART2_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x06e000)
-#define MX28_AUART3_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x070000)
-#define MX28_AUART4_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x072000)
-#define MX28_DUART_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x074000)
-#define MX28_USBPHY0_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x07C000)
-#define MX28_USBPHY1_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x07e000)
-#define MX28_USBCTRL0_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x080000)
-#define MX28_USBCTRL1_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x090000)
-#define MX28_DFLPT_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x0c0000)
-#define MX28_DRAM_BASE_ADDR		(MX28_IO_BASE_ADDR + 0x0e0000)
-#define MX28_ENET_MAC0_BASE_ADDR	(MX28_IO_BASE_ADDR + 0x0f0000)
-#define MX28_ENET_MAC1_BASE_ADDR	(MX28_IO_BASE_ADDR + 0x0f4000)
-
-#define MX28_IO_P2V(x)			MXS_IO_P2V(x)
-#define MX28_IO_ADDRESS(x)		IOMEM(MX28_IO_P2V(x))
-
-/*
- * IRQ
- */
-#define MX28_INT_BATT_BRNOUT		0
-#define MX28_INT_VDDD_BRNOUT		1
-#define MX28_INT_VDDIO_BRNOUT		2
-#define MX28_INT_VDDA_BRNOUT		3
-#define MX28_INT_VDD5V_DROOP		4
-#define MX28_INT_DCDC4P2_BRNOUT		5
-#define MX28_INT_VDD5V			6
-#define MX28_INT_CAN0			8
-#define MX28_INT_CAN1			9
-#define MX28_INT_LRADC_TOUCH		10
-#define MX28_INT_HSADC			13
-#define MX28_INT_LRADC_THRESH0		14
-#define MX28_INT_LRADC_THRESH1		15
-#define MX28_INT_LRADC_CH0		16
-#define MX28_INT_LRADC_CH1		17
-#define MX28_INT_LRADC_CH2		18
-#define MX28_INT_LRADC_CH3		19
-#define MX28_INT_LRADC_CH4		20
-#define MX28_INT_LRADC_CH5		21
-#define MX28_INT_LRADC_CH6		22
-#define MX28_INT_LRADC_CH7		23
-#define MX28_INT_LRADC_BUTTON0		24
-#define MX28_INT_LRADC_BUTTON1		25
-#define MX28_INT_PERFMON		27
-#define MX28_INT_RTC_1MSEC		28
-#define MX28_INT_RTC_ALARM		29
-#define MX28_INT_COMMS			31
-#define MX28_INT_EMI_ERR		32
-#define MX28_INT_LCDIF			38
-#define MX28_INT_PXP			39
-#define MX28_INT_BCH			41
-#define MX28_INT_GPMI			42
-#define MX28_INT_SPDIF_ERROR		45
-#define MX28_INT_DUART			47
-#define MX28_INT_TIMER0			48
-#define MX28_INT_TIMER1			49
-#define MX28_INT_TIMER2			50
-#define MX28_INT_TIMER3			51
-#define MX28_INT_DCP_VMI		52
-#define MX28_INT_DCP			53
-#define MX28_INT_DCP_SECURE		54
-#define MX28_INT_SAIF1			58
-#define MX28_INT_SAIF0			59
-#define MX28_INT_SPDIF_DMA		66
-#define MX28_INT_I2C0_DMA		68
-#define MX28_INT_I2C1_DMA		69
-#define MX28_INT_AUART0_RX_DMA		70
-#define MX28_INT_AUART0_TX_DMA		71
-#define MX28_INT_AUART1_RX_DMA		72
-#define MX28_INT_AUART1_TX_DMA		73
-#define MX28_INT_AUART2_RX_DMA		74
-#define MX28_INT_AUART2_TX_DMA		75
-#define MX28_INT_AUART3_RX_DMA		76
-#define MX28_INT_AUART3_TX_DMA		77
-#define MX28_INT_AUART4_RX_DMA		78
-#define MX28_INT_AUART4_TX_DMA		79
-#define MX28_INT_SAIF0_DMA		80
-#define MX28_INT_SAIF1_DMA		81
-#define MX28_INT_SSP0_DMA		82
-#define MX28_INT_SSP1_DMA		83
-#define MX28_INT_SSP2_DMA		84
-#define MX28_INT_SSP3_DMA		85
-#define MX28_INT_LCDIF_DMA		86
-#define MX28_INT_HSADC_DMA		87
-#define MX28_INT_GPMI_DMA		88
-#define MX28_INT_DIGCTL_DEBUG_TRAP	89
-#define MX28_INT_USB1			92
-#define MX28_INT_USB0			93
-#define MX28_INT_USB1_WAKEUP		94
-#define MX28_INT_USB0_WAKEUP		95
-#define MX28_INT_SSP0_ERROR		96
-#define MX28_INT_SSP1_ERROR		97
-#define MX28_INT_SSP2_ERROR		98
-#define MX28_INT_SSP3_ERROR		99
-#define MX28_INT_ENET_SWI		100
-#define MX28_INT_ENET_MAC0		101
-#define MX28_INT_ENET_MAC1		102
-#define MX28_INT_ENET_MAC0_1588		103
-#define MX28_INT_ENET_MAC1_1588		104
-#define MX28_INT_I2C1_ERROR		110
-#define MX28_INT_I2C0_ERROR		111
-#define MX28_INT_AUART0			112
-#define MX28_INT_AUART1			113
-#define MX28_INT_AUART2			114
-#define MX28_INT_AUART3			115
-#define MX28_INT_AUART4			116
-#define MX28_INT_GPIO4			123
-#define MX28_INT_GPIO3			124
-#define MX28_INT_GPIO2			125
-#define MX28_INT_GPIO1			126
-#define MX28_INT_GPIO0			127
-
-/*
- * APBH DMA
- */
-#define MX28_DMA_SSP0			0
-#define MX28_DMA_SSP1			1
-#define MX28_DMA_SSP2			2
-#define MX28_DMA_SSP3			3
-#define MX28_DMA_GPMI0			4
-#define MX28_DMA_GPMI1			5
-#define MX28_DMA_GPMI2			6
-#define MX28_DMA_GPMI3			7
-#define MX28_DMA_GPMI4			8
-#define MX28_DMA_GPMI5			9
-#define MX28_DMA_GPMI6			10
-#define MX28_DMA_GPMI7			11
-#define MX28_DMA_HSADC			12
-#define MX28_DMA_LCDIF			13
-
-/*
- * APBX DMA
- */
-#define MX28_DMA_AUART4_RX		0
-#define MX28_DMA_AUART4_TX		1
-#define MX28_DMA_SPDIF_TX		2
-#define MX28_DMA_SAIF0			4
-#define MX28_DMA_SAIF1			5
-#define MX28_DMA_I2C0			6
-#define MX28_DMA_I2C1			7
-#define MX28_DMA_AUART0_RX		8
-#define MX28_DMA_AUART0_TX		9
-#define MX28_DMA_AUART1_RX		10
-#define MX28_DMA_AUART1_TX		11
-#define MX28_DMA_AUART2_RX		12
-#define MX28_DMA_AUART2_TX		13
-#define MX28_DMA_AUART3_RX		14
-#define MX28_DMA_AUART3_TX		15
-
-#endif /* __MACH_MX28_H__ */
diff --git a/arch/arm/mach-mxs/include/mach/mxs.h b/arch/arm/mach-mxs/include/mach/mxs.h
deleted file mode 100644
index 7d4fb6d..0000000
--- a/arch/arm/mach-mxs/include/mach/mxs.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (C) 2009-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.
- */
-
-#ifndef __MACH_MXS_H__
-#define __MACH_MXS_H__
-
-#ifndef __ASSEMBLER__
-#include <linux/io.h>
-#endif
-#include <asm/mach-types.h>
-#include <mach/digctl.h>
-#include <mach/hardware.h>
-
-/*
- * IO addresses common to MXS-based
- */
-#define MXS_IO_BASE_ADDR		0x80000000
-#define MXS_IO_SIZE			SZ_1M
-
-#define MXS_ICOLL_BASE_ADDR		(MXS_IO_BASE_ADDR + 0x000000)
-#define MXS_APBH_DMA_BASE_ADDR		(MXS_IO_BASE_ADDR + 0x004000)
-#define MXS_BCH_BASE_ADDR		(MXS_IO_BASE_ADDR + 0x00a000)
-#define MXS_GPMI_BASE_ADDR		(MXS_IO_BASE_ADDR + 0x00c000)
-#define MXS_PINCTRL_BASE_ADDR		(MXS_IO_BASE_ADDR + 0x018000)
-#define MXS_DIGCTL_BASE_ADDR		(MXS_IO_BASE_ADDR + 0x01c000)
-#define MXS_APBX_DMA_BASE_ADDR		(MXS_IO_BASE_ADDR + 0x024000)
-#define MXS_DCP_BASE_ADDR		(MXS_IO_BASE_ADDR + 0x028000)
-#define MXS_PXP_BASE_ADDR		(MXS_IO_BASE_ADDR + 0x02a000)
-#define MXS_OCOTP_BASE_ADDR		(MXS_IO_BASE_ADDR + 0x02c000)
-#define MXS_AXI_AHB0_BASE_ADDR		(MXS_IO_BASE_ADDR + 0x02e000)
-#define MXS_LCDIF_BASE_ADDR		(MXS_IO_BASE_ADDR + 0x030000)
-#define MXS_CLKCTRL_BASE_ADDR		(MXS_IO_BASE_ADDR + 0x040000)
-#define MXS_SAIF0_BASE_ADDR		(MXS_IO_BASE_ADDR + 0x042000)
-#define MXS_POWER_BASE_ADDR		(MXS_IO_BASE_ADDR + 0x044000)
-#define MXS_SAIF1_BASE_ADDR		(MXS_IO_BASE_ADDR + 0x046000)
-#define MXS_LRADC_BASE_ADDR		(MXS_IO_BASE_ADDR + 0x050000)
-#define MXS_SPDIF_BASE_ADDR		(MXS_IO_BASE_ADDR + 0x054000)
-#define MXS_I2C0_BASE_ADDR		(MXS_IO_BASE_ADDR + 0x058000)
-#define MXS_PWM_BASE_ADDR		(MXS_IO_BASE_ADDR + 0x064000)
-#define MXS_TIMROT_BASE_ADDR		(MXS_IO_BASE_ADDR + 0x068000)
-#define MXS_AUART1_BASE_ADDR		(MXS_IO_BASE_ADDR + 0x06c000)
-#define MXS_AUART2_BASE_ADDR		(MXS_IO_BASE_ADDR + 0x06e000)
-#define MXS_DRAM_BASE_ADDR		(MXS_IO_BASE_ADDR + 0x0e0000)
-
-/*
- * It maps the whole address space to [0xf4000000, 0xf50fffff].
- *
- *	OCRAM	0x00000000+0x020000	->	0xf4000000+0x020000
- *	IO	0x80000000+0x100000	->	0xf5000000+0x100000
- */
-#define MXS_IO_P2V(x)	(0xf4000000 +					\
-			(((x) & 0x80000000) >> 7) +			\
-			(((x) & 0x000fffff)))
-
-#define MXS_IO_ADDRESS(x)	IOMEM(MXS_IO_P2V(x))
-
-#define mxs_map_entry(soc, name, _type)	{				\
-	.virtual = soc ## _IO_P2V(soc ## _ ## name ## _BASE_ADDR),	\
-	.pfn = __phys_to_pfn(soc ## _ ## name ## _BASE_ADDR),		\
-	.length = soc ## _ ## name ## _SIZE,				\
-	.type = _type,							\
-}
-
-#define MXS_GPIO_NR(bank, nr)	((bank) * 32 + (nr))
-
-#define MXS_SET_ADDR		0x4
-#define MXS_CLR_ADDR		0x8
-#define MXS_TOG_ADDR		0xc
-
-#ifndef __ASSEMBLER__
-static inline void __mxs_setl(u32 mask, void __iomem *reg)
-{
-	__raw_writel(mask, reg + MXS_SET_ADDR);
-}
-
-static inline void __mxs_clrl(u32 mask, void __iomem *reg)
-{
-	__raw_writel(mask, reg + MXS_CLR_ADDR);
-}
-
-static inline void __mxs_togl(u32 mask, void __iomem *reg)
-{
-	__raw_writel(mask, reg + MXS_TOG_ADDR);
-}
-
-/*
- * MXS CPU types
- */
-#define MXS_CHIPID (MXS_IO_ADDRESS(MXS_DIGCTL_BASE_ADDR) + HW_DIGCTL_CHIPID)
-
-static inline int cpu_is_mx23(void)
-{
-	return ((__raw_readl(MXS_CHIPID) >> 16) == 0x3780);
-}
-
-static inline int cpu_is_mx28(void)
-{
-	return ((__raw_readl(MXS_CHIPID) >> 16) == 0x2800);
-}
-#endif
-
-#endif /* __MACH_MXS_H__ */
diff --git a/arch/arm/mach-mxs/include/mach/timex.h b/arch/arm/mach-mxs/include/mach/timex.h
deleted file mode 100644
index 734ce89..0000000
--- a/arch/arm/mach-mxs/include/mach/timex.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- *  Copyright (C) 1999 ARM Limited
- * Copyright 2004-2007 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.
- */
-
-#ifndef __MACH_MXS_TIMEX_H__
-#define __MACH_MXS_TIMEX_H__
-
-#define CLOCK_TICK_RATE		32000	/* 32K */
-
-#endif /* __MACH_MXS_TIMEX_H__ */
diff --git a/arch/arm/mach-mxs/include/mach/uncompress.h b/arch/arm/mach-mxs/include/mach/uncompress.h
deleted file mode 100644
index 533f518..0000000
--- a/arch/arm/mach-mxs/include/mach/uncompress.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- *  arch/arm/mach-mxs/include/mach/uncompress.h
- *
- *  Copyright (C) 1999 ARM Limited
- *  Copyright (C) Shane Nay (shane@minirl.com)
- *  Copyright 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.
- */
-#ifndef __MACH_MXS_UNCOMPRESS_H__
-#define __MACH_MXS_UNCOMPRESS_H__
-
-unsigned long mxs_duart_base;
-
-#define MXS_DUART(x)	(*(volatile unsigned long *)(mxs_duart_base + (x)))
-
-#define MXS_DUART_DR		0x00
-#define MXS_DUART_FR		0x18
-#define MXS_DUART_FR_TXFE	(1 << 7)
-#define MXS_DUART_CR		0x30
-#define MXS_DUART_CR_UARTEN	(1 << 0)
-
-/*
- * The following code assumes the serial port has already been
- * initialized by the bootloader. If it's not, the output is
- * simply discarded.
- */
-
-static void putc(int ch)
-{
-	if (!mxs_duart_base)
-		return;
-	if (!(MXS_DUART(MXS_DUART_CR) & MXS_DUART_CR_UARTEN))
-		return;
-
-	while (!(MXS_DUART(MXS_DUART_FR) & MXS_DUART_FR_TXFE))
-		barrier();
-
-	MXS_DUART(MXS_DUART_DR) = ch;
-}
-
-static inline void flush(void)
-{
-}
-
-#define MX23_DUART_BASE_ADDR	0x80070000
-#define MX28_DUART_BASE_ADDR	0x80074000
-#define MXS_DIGCTL_CHIPID	0x8001c310
-
-static inline void __arch_decomp_setup(unsigned long arch_id)
-{
-	u16 chipid = (*(volatile unsigned long *) MXS_DIGCTL_CHIPID) >> 16;
-
-	switch (chipid) {
-	case 0x3780:
-		mxs_duart_base = MX23_DUART_BASE_ADDR;
-		break;
-	case 0x2800:
-		mxs_duart_base = MX28_DUART_BASE_ADDR;
-		break;
-	default:
-		break;
-	}
-}
-
-#define arch_decomp_setup()	__arch_decomp_setup(arch_id)
-
-#endif /* __MACH_MXS_UNCOMPRESS_H__ */
diff --git a/arch/arm/mach-mxs/mach-mxs.c b/arch/arm/mach-mxs/mach-mxs.c
index e7b781d..5b62b64 100644
--- a/arch/arm/mach-mxs/mach-mxs.c
+++ b/arch/arm/mach-mxs/mach-mxs.c
@@ -11,122 +11,54 @@
  */
 
 #include <linux/clk.h>
+#include <linux/clk/mxs.h>
 #include <linux/clkdev.h>
+#include <linux/clocksource.h>
 #include <linux/can/platform/flexcan.h>
 #include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/gpio.h>
 #include <linux/init.h>
+#include <linux/irqchip.h>
+#include <linux/irqchip/mxs.h>
 #include <linux/micrel_phy.h>
-#include <linux/mxsfb.h>
+#include <linux/of_address.h>
 #include <linux/of_platform.h>
 #include <linux/phy.h>
 #include <linux/pinctrl/consumer.h>
 #include <asm/mach/arch.h>
+#include <asm/mach/map.h>
 #include <asm/mach/time.h>
-#include <mach/common.h>
-#include <mach/digctl.h>
-#include <mach/mxs.h>
-
-static struct fb_videomode mx23evk_video_modes[] = {
-	{
-		.name		= "Samsung-LMS430HF02",
-		.refresh	= 60,
-		.xres		= 480,
-		.yres		= 272,
-		.pixclock	= 108096, /* picosecond (9.2 MHz) */
-		.left_margin	= 15,
-		.right_margin	= 8,
-		.upper_margin	= 12,
-		.lower_margin	= 4,
-		.hsync_len	= 1,
-		.vsync_len	= 1,
-	},
-};
+#include <asm/system_misc.h>
 
-static struct fb_videomode mx28evk_video_modes[] = {
-	{
-		.name		= "Seiko-43WVF1G",
-		.refresh	= 60,
-		.xres		= 800,
-		.yres		= 480,
-		.pixclock	= 29851, /* picosecond (33.5 MHz) */
-		.left_margin	= 89,
-		.right_margin	= 164,
-		.upper_margin	= 23,
-		.lower_margin	= 10,
-		.hsync_len	= 10,
-		.vsync_len	= 10,
-	},
-};
+#include "pm.h"
 
-static struct fb_videomode m28evk_video_modes[] = {
-	{
-		.name		= "Ampire AM-800480R2TMQW-T01H",
-		.refresh	= 60,
-		.xres		= 800,
-		.yres		= 480,
-		.pixclock	= 30066, /* picosecond (33.26 MHz) */
-		.left_margin	= 0,
-		.right_margin	= 256,
-		.upper_margin	= 0,
-		.lower_margin	= 45,
-		.hsync_len	= 1,
-		.vsync_len	= 1,
-	},
-};
+/* MXS DIGCTL SAIF CLKMUX */
+#define MXS_DIGCTL_SAIF_CLKMUX_DIRECT		0x0
+#define MXS_DIGCTL_SAIF_CLKMUX_CROSSINPUT	0x1
+#define MXS_DIGCTL_SAIF_CLKMUX_EXTMSTR0		0x2
+#define MXS_DIGCTL_SAIF_CLKMUX_EXTMSTR1		0x3
 
-static struct fb_videomode apx4devkit_video_modes[] = {
-	{
-		.name		= "HannStar PJ70112A",
-		.refresh	= 60,
-		.xres		= 800,
-		.yres		= 480,
-		.pixclock	= 33333, /* picosecond (30.00 MHz) */
-		.left_margin	= 88,
-		.right_margin	= 40,
-		.upper_margin	= 32,
-		.lower_margin	= 13,
-		.hsync_len	= 48,
-		.vsync_len	= 3,
-		.sync		= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	},
-};
+#define MXS_GPIO_NR(bank, nr)	((bank) * 32 + (nr))
 
-static struct fb_videomode apf28dev_video_modes[] = {
-	{
-		.name = "LW700",
-		.refresh = 60,
-		.xres = 800,
-		.yres = 480,
-		.pixclock = 30303, /* picosecond */
-		.left_margin = 96,
-		.right_margin = 96, /* at least 3 & 1 */
-		.upper_margin = 0x14,
-		.lower_margin = 0x15,
-		.hsync_len = 64,
-		.vsync_len = 4,
-		.sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	},
-};
+#define MXS_SET_ADDR		0x4
+#define MXS_CLR_ADDR		0x8
+#define MXS_TOG_ADDR		0xc
 
-static struct fb_videomode cfa10049_video_modes[] = {
-	{
-		.name		= "Himax HX8357-B",
-		.refresh	= 60,
-		.xres		= 320,
-		.yres		= 480,
-		.pixclock	= 108506, /* picosecond (9.216 MHz) */
-		.left_margin	= 2,
-		.right_margin	= 2,
-		.upper_margin	= 2,
-		.lower_margin	= 2,
-		.hsync_len	= 15,
-		.vsync_len	= 15,
-	},
-};
+static inline void __mxs_setl(u32 mask, void __iomem *reg)
+{
+	__raw_writel(mask, reg + MXS_SET_ADDR);
+}
 
-static struct mxsfb_platform_data mxsfb_pdata __initdata;
+static inline void __mxs_clrl(u32 mask, void __iomem *reg)
+{
+	__raw_writel(mask, reg + MXS_CLR_ADDR);
+}
+
+static inline void __mxs_togl(u32 mask, void __iomem *reg)
+{
+	__raw_writel(mask, reg + MXS_TOG_ADDR);
+}
 
 /*
  * MX28EVK_FLEXCAN_SWITCH is shared between both flexcan controllers
@@ -158,21 +90,85 @@ static void mx28evk_flexcan1_switch(int enable)
 static struct flexcan_platform_data flexcan_pdata[2];
 
 static struct of_dev_auxdata mxs_auxdata_lookup[] __initdata = {
-	OF_DEV_AUXDATA("fsl,imx23-lcdif", 0x80030000, NULL, &mxsfb_pdata),
-	OF_DEV_AUXDATA("fsl,imx28-lcdif", 0x80030000, NULL, &mxsfb_pdata),
 	OF_DEV_AUXDATA("fsl,imx28-flexcan", 0x80032000, NULL, &flexcan_pdata[0]),
 	OF_DEV_AUXDATA("fsl,imx28-flexcan", 0x80034000, NULL, &flexcan_pdata[1]),
 	{ /* sentinel */ }
 };
 
-static void __init imx23_timer_init(void)
-{
-	mx23_clocks_init();
-}
+#define OCOTP_WORD_OFFSET		0x20
+#define OCOTP_WORD_COUNT		0x20
+
+#define BM_OCOTP_CTRL_BUSY		(1 << 8)
+#define BM_OCOTP_CTRL_ERROR		(1 << 9)
+#define BM_OCOTP_CTRL_RD_BANK_OPEN	(1 << 12)
 
-static void __init imx28_timer_init(void)
+static DEFINE_MUTEX(ocotp_mutex);
+static u32 ocotp_words[OCOTP_WORD_COUNT];
+
+static const u32 *mxs_get_ocotp(void)
 {
-	mx28_clocks_init();
+	struct device_node *np;
+	void __iomem *ocotp_base;
+	int timeout = 0x400;
+	size_t i;
+	static int once;
+
+	if (once)
+		return ocotp_words;
+
+	np = of_find_compatible_node(NULL, NULL, "fsl,ocotp");
+	ocotp_base = of_iomap(np, 0);
+	WARN_ON(!ocotp_base);
+
+	mutex_lock(&ocotp_mutex);
+
+	/*
+	 * clk_enable(hbus_clk) for ocotp can be skipped
+	 * as it must be on when system is running.
+	 */
+
+	/* try to clear ERROR bit */
+	__mxs_clrl(BM_OCOTP_CTRL_ERROR, ocotp_base);
+
+	/* check both BUSY and ERROR cleared */
+	while ((__raw_readl(ocotp_base) &
+		(BM_OCOTP_CTRL_BUSY | BM_OCOTP_CTRL_ERROR)) && --timeout)
+		cpu_relax();
+
+	if (unlikely(!timeout))
+		goto error_unlock;
+
+	/* open OCOTP banks for read */
+	__mxs_setl(BM_OCOTP_CTRL_RD_BANK_OPEN, ocotp_base);
+
+	/* approximately wait 32 hclk cycles */
+	udelay(1);
+
+	/* poll BUSY bit becoming cleared */
+	timeout = 0x400;
+	while ((__raw_readl(ocotp_base) & BM_OCOTP_CTRL_BUSY) && --timeout)
+		cpu_relax();
+
+	if (unlikely(!timeout))
+		goto error_unlock;
+
+	for (i = 0; i < OCOTP_WORD_COUNT; i++)
+		ocotp_words[i] = __raw_readl(ocotp_base + OCOTP_WORD_OFFSET +
+						i * 0x10);
+
+	/* close banks for power saving */
+	__mxs_clrl(BM_OCOTP_CTRL_RD_BANK_OPEN, ocotp_base);
+
+	once = 1;
+
+	mutex_unlock(&ocotp_mutex);
+
+	return ocotp_words;
+
+error_unlock:
+	mutex_unlock(&ocotp_mutex);
+	pr_err("%s: timeout in reading OCOTP\n", __func__);
+	return NULL;
 }
 
 enum mac_oui {
@@ -243,16 +239,6 @@ static void __init update_fec_mac_prop(enum mac_oui oui)
 	}
 }
 
-static void __init imx23_evk_init(void)
-{
-	mxsfb_pdata.mode_list = mx23evk_video_modes;
-	mxsfb_pdata.mode_count = ARRAY_SIZE(mx23evk_video_modes);
-	mxsfb_pdata.default_bpp = 32;
-	mxsfb_pdata.ld_intf_width = STMLCDIF_24BIT;
-	mxsfb_pdata.sync = MXSFB_SYNC_DATA_ENABLE_HIGH_ACT |
-				MXSFB_SYNC_DOTCLK_FAILING_ACT;
-}
-
 static inline void enable_clk_enet_out(void)
 {
 	struct clk *clk = clk_get_sys("enet_out", NULL);
@@ -263,16 +249,8 @@ static inline void enable_clk_enet_out(void)
 
 static void __init imx28_evk_init(void)
 {
-	enable_clk_enet_out();
 	update_fec_mac_prop(OUI_FSL);
 
-	mxsfb_pdata.mode_list = mx28evk_video_modes;
-	mxsfb_pdata.mode_count = ARRAY_SIZE(mx28evk_video_modes);
-	mxsfb_pdata.default_bpp = 32;
-	mxsfb_pdata.ld_intf_width = STMLCDIF_24BIT;
-	mxsfb_pdata.sync = MXSFB_SYNC_DATA_ENABLE_HIGH_ACT |
-				MXSFB_SYNC_DOTCLK_FAILING_ACT;
-
 	mxs_saif_clkmux_select(MXS_DIGCTL_SAIF_CLKMUX_EXTMSTR0);
 }
 
@@ -285,20 +263,6 @@ static void __init imx28_evk_post_init(void)
 	}
 }
 
-static void __init m28evk_init(void)
-{
-	mxsfb_pdata.mode_list = m28evk_video_modes;
-	mxsfb_pdata.mode_count = ARRAY_SIZE(m28evk_video_modes);
-	mxsfb_pdata.default_bpp = 16;
-	mxsfb_pdata.ld_intf_width = STMLCDIF_18BIT;
-	mxsfb_pdata.sync = MXSFB_SYNC_DATA_ENABLE_HIGH_ACT;
-}
-
-static void __init sc_sps1_init(void)
-{
-	enable_clk_enet_out();
-}
-
 static int apx4devkit_phy_fixup(struct phy_device *phy)
 {
 	phy->dev_flags |= MICREL_PHY_50MHZ_CLK;
@@ -312,13 +276,6 @@ static void __init apx4devkit_init(void)
 	if (IS_BUILTIN(CONFIG_PHYLIB))
 		phy_register_fixup_for_uid(PHY_ID_KSZ8051, MICREL_PHY_ID_MASK,
 					   apx4devkit_phy_fixup);
-
-	mxsfb_pdata.mode_list = apx4devkit_video_modes;
-	mxsfb_pdata.mode_count = ARRAY_SIZE(apx4devkit_video_modes);
-	mxsfb_pdata.default_bpp = 32;
-	mxsfb_pdata.ld_intf_width = STMLCDIF_24BIT;
-	mxsfb_pdata.sync = MXSFB_SYNC_DATA_ENABLE_HIGH_ACT |
-				MXSFB_SYNC_DOTCLK_FAILING_ACT;
 }
 
 #define ENET0_MDC__GPIO_4_0	MXS_GPIO_NR(4, 0)
@@ -397,52 +354,24 @@ static void __init tx28_post_init(void)
 
 static void __init cfa10049_init(void)
 {
-	enable_clk_enet_out();
 	update_fec_mac_prop(OUI_CRYSTALFONTZ);
-
-	mxsfb_pdata.mode_list = cfa10049_video_modes;
-	mxsfb_pdata.mode_count = ARRAY_SIZE(cfa10049_video_modes);
-	mxsfb_pdata.default_bpp = 32;
-	mxsfb_pdata.ld_intf_width = STMLCDIF_18BIT;
-	mxsfb_pdata.sync = MXSFB_SYNC_DATA_ENABLE_HIGH_ACT;
 }
 
 static void __init cfa10037_init(void)
 {
-	enable_clk_enet_out();
 	update_fec_mac_prop(OUI_CRYSTALFONTZ);
 }
 
-static void __init apf28_init(void)
-{
-	enable_clk_enet_out();
-
-	mxsfb_pdata.mode_list = apf28dev_video_modes;
-	mxsfb_pdata.mode_count = ARRAY_SIZE(apf28dev_video_modes);
-	mxsfb_pdata.default_bpp = 16;
-	mxsfb_pdata.ld_intf_width = STMLCDIF_16BIT;
-	mxsfb_pdata.sync = MXSFB_SYNC_DATA_ENABLE_HIGH_ACT |
-				MXSFB_SYNC_DOTCLK_FAILING_ACT;
-}
-
 static void __init mxs_machine_init(void)
 {
 	if (of_machine_is_compatible("fsl,imx28-evk"))
 		imx28_evk_init();
-	else if (of_machine_is_compatible("fsl,imx23-evk"))
-		imx23_evk_init();
-	else if (of_machine_is_compatible("denx,m28evk"))
-		m28evk_init();
 	else if (of_machine_is_compatible("bluegiga,apx4devkit"))
 		apx4devkit_init();
 	else if (of_machine_is_compatible("crystalfontz,cfa10037"))
 		cfa10037_init();
 	else if (of_machine_is_compatible("crystalfontz,cfa10049"))
 		cfa10049_init();
-	else if (of_machine_is_compatible("armadeus,imx28-apf28"))
-		apf28_init();
-	else if (of_machine_is_compatible("schulercontrol,imx28-sps1"))
-		sc_sps1_init();
 
 	of_platform_populate(NULL, of_default_bus_match_table,
 			     mxs_auxdata_lookup, NULL);
@@ -454,32 +383,63 @@ static void __init mxs_machine_init(void)
 		imx28_evk_post_init();
 }
 
-static const char *imx23_dt_compat[] __initdata = {
-	"fsl,imx23",
-	NULL,
-};
+#define MX23_CLKCTRL_RESET_OFFSET	0x120
+#define MX28_CLKCTRL_RESET_OFFSET	0x1e0
+#define MXS_CLKCTRL_RESET_CHIP		(1 << 1)
 
-static const char *imx28_dt_compat[] __initdata = {
+/*
+ * Reset the system. It is called by machine_restart().
+ */
+static void mxs_restart(char mode, const char *cmd)
+{
+	struct device_node *np;
+	void __iomem *reset_addr;
+
+	np = of_find_compatible_node(NULL, NULL, "fsl,clkctrl");
+	reset_addr = of_iomap(np, 0);
+	if (!reset_addr)
+		goto soft;
+
+	if (of_device_is_compatible(np, "fsl,imx23-clkctrl"))
+		reset_addr += MX23_CLKCTRL_RESET_OFFSET;
+	else
+		reset_addr += MX28_CLKCTRL_RESET_OFFSET;
+
+	/* reset the chip */
+	__mxs_setl(MXS_CLKCTRL_RESET_CHIP, reset_addr);
+
+	pr_err("Failed to assert the chip reset\n");
+
+	/* Delay to allow the serial port to show the message */
+	mdelay(50);
+
+soft:
+	/* We'll take a jump through zero as a poor second */
+	soft_restart(0);
+}
+
+static void __init mxs_timer_init(void)
+{
+	if (of_machine_is_compatible("fsl,imx23"))
+		mx23_clocks_init();
+	else
+		mx28_clocks_init();
+	clocksource_of_init();
+}
+
+static const char *mxs_dt_compat[] __initdata = {
 	"fsl,imx28",
+	"fsl,imx23",
 	NULL,
 };
 
-DT_MACHINE_START(IMX23, "Freescale i.MX23 (Device Tree)")
-	.map_io		= mx23_map_io,
-	.init_irq	= icoll_init_irq,
-	.handle_irq	= icoll_handle_irq,
-	.init_time	= imx23_timer_init,
-	.init_machine	= mxs_machine_init,
-	.dt_compat	= imx23_dt_compat,
-	.restart	= mxs_restart,
-MACHINE_END
-
-DT_MACHINE_START(IMX28, "Freescale i.MX28 (Device Tree)")
-	.map_io		= mx28_map_io,
-	.init_irq	= icoll_init_irq,
+DT_MACHINE_START(MXS, "Freescale MXS (Device Tree)")
+	.map_io		= debug_ll_io_init,
+	.init_irq	= irqchip_init,
 	.handle_irq	= icoll_handle_irq,
-	.init_time	= imx28_timer_init,
+	.init_time	= mxs_timer_init,
 	.init_machine	= mxs_machine_init,
-	.dt_compat	= imx28_dt_compat,
+	.init_late      = mxs_pm_init,
+	.dt_compat	= mxs_dt_compat,
 	.restart	= mxs_restart,
 MACHINE_END
diff --git a/arch/arm/mach-mxs/mm.c b/arch/arm/mach-mxs/mm.c
deleted file mode 100644
index e63b7d8..0000000
--- a/arch/arm/mach-mxs/mm.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright 2008-2010 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
- *
- * Create static mapping between physical to virtual memory.
- */
-
-#include <linux/mm.h>
-#include <linux/init.h>
-
-#include <asm/mach/map.h>
-
-#include <mach/mx23.h>
-#include <mach/mx28.h>
-#include <mach/common.h>
-
-/*
- * Define the MX23 memory map.
- */
-static struct map_desc mx23_io_desc[] __initdata = {
-	mxs_map_entry(MX23, OCRAM, MT_DEVICE),
-	mxs_map_entry(MX23, IO, MT_DEVICE),
-};
-
-/*
- * Define the MX28 memory map.
- */
-static struct map_desc mx28_io_desc[] __initdata = {
-	mxs_map_entry(MX28, OCRAM, MT_DEVICE),
-	mxs_map_entry(MX28, IO, MT_DEVICE),
-};
-
-/*
- * This function initializes the memory map. It is called during the
- * system startup to create static physical to virtual memory mappings
- * for the IO modules.
- */
-void __init mx23_map_io(void)
-{
-	iotable_init(mx23_io_desc, ARRAY_SIZE(mx23_io_desc));
-}
-
-void __init mx28_map_io(void)
-{
-	iotable_init(mx28_io_desc, ARRAY_SIZE(mx28_io_desc));
-}
diff --git a/arch/arm/mach-mxs/ocotp.c b/arch/arm/mach-mxs/ocotp.c
deleted file mode 100644
index 1dff467..0000000
--- a/arch/arm/mach-mxs/ocotp.c
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright 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.
- */
-
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/mutex.h>
-
-#include <asm/processor.h>	/* for cpu_relax() */
-
-#include <mach/mxs.h>
-#include <mach/common.h>
-
-#define OCOTP_WORD_OFFSET		0x20
-#define OCOTP_WORD_COUNT		0x20
-
-#define BM_OCOTP_CTRL_BUSY		(1 << 8)
-#define BM_OCOTP_CTRL_ERROR		(1 << 9)
-#define BM_OCOTP_CTRL_RD_BANK_OPEN	(1 << 12)
-
-static DEFINE_MUTEX(ocotp_mutex);
-static u32 ocotp_words[OCOTP_WORD_COUNT];
-
-const u32 *mxs_get_ocotp(void)
-{
-	void __iomem *ocotp_base = MXS_IO_ADDRESS(MXS_OCOTP_BASE_ADDR);
-	int timeout = 0x400;
-	size_t i;
-	static int once = 0;
-
-	if (once)
-		return ocotp_words;
-
-	mutex_lock(&ocotp_mutex);
-
-	/*
-	 * clk_enable(hbus_clk) for ocotp can be skipped
-	 * as it must be on when system is running.
-	 */
-
-	/* try to clear ERROR bit */
-	__mxs_clrl(BM_OCOTP_CTRL_ERROR, ocotp_base);
-
-	/* check both BUSY and ERROR cleared */
-	while ((__raw_readl(ocotp_base) &
-		(BM_OCOTP_CTRL_BUSY | BM_OCOTP_CTRL_ERROR)) && --timeout)
-		cpu_relax();
-
-	if (unlikely(!timeout))
-		goto error_unlock;
-
-	/* open OCOTP banks for read */
-	__mxs_setl(BM_OCOTP_CTRL_RD_BANK_OPEN, ocotp_base);
-
-	/* approximately wait 32 hclk cycles */
-	udelay(1);
-
-	/* poll BUSY bit becoming cleared */
-	timeout = 0x400;
-	while ((__raw_readl(ocotp_base) & BM_OCOTP_CTRL_BUSY) && --timeout)
-		cpu_relax();
-
-	if (unlikely(!timeout))
-		goto error_unlock;
-
-	for (i = 0; i < OCOTP_WORD_COUNT; i++)
-		ocotp_words[i] = __raw_readl(ocotp_base + OCOTP_WORD_OFFSET +
-						i * 0x10);
-
-	/* close banks for power saving */
-	__mxs_clrl(BM_OCOTP_CTRL_RD_BANK_OPEN, ocotp_base);
-
-	once = 1;
-
-	mutex_unlock(&ocotp_mutex);
-
-	return ocotp_words;
-
-error_unlock:
-	mutex_unlock(&ocotp_mutex);
-	pr_err("%s: timeout in reading OCOTP\n", __func__);
-	return NULL;
-}
diff --git a/arch/arm/mach-mxs/pm.c b/arch/arm/mach-mxs/pm.c
index a9b4bbc..b2494d2 100644
--- a/arch/arm/mach-mxs/pm.c
+++ b/arch/arm/mach-mxs/pm.c
@@ -34,9 +34,7 @@ static struct platform_suspend_ops mxs_suspend_ops = {
 	.valid = suspend_valid_only_mem,
 };
 
-static int __init mxs_pm_init(void)
+void __init mxs_pm_init(void)
 {
 	suspend_set_ops(&mxs_suspend_ops);
-	return 0;
 }
-device_initcall(mxs_pm_init);
diff --git a/arch/arm/mach-mxs/pm.h b/arch/arm/mach-mxs/pm.h
new file mode 100644
index 0000000..f57e7cd
--- /dev/null
+++ b/arch/arm/mach-mxs/pm.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) 2013 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ARCH_MXS_PM_H
+#define __ARCH_MXS_PM_H
+
+void mxs_pm_init(void);
+
+#endif
diff --git a/arch/arm/mach-mxs/system.c b/arch/arm/mach-mxs/system.c
deleted file mode 100644
index 30042e2..0000000
--- a/arch/arm/mach-mxs/system.c
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright (C) 1999 ARM Limited
- * Copyright (C) 2000 Deep Blue Solutions Ltd
- * Copyright 2006-2007,2010 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
- * Copyright 2009 Ilya Yanok, Emcraft Systems Ltd, yanok@emcraft.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/kernel.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/err.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/module.h>
-
-#include <asm/proc-fns.h>
-#include <asm/system_misc.h>
-
-#include <mach/mxs.h>
-#include <mach/common.h>
-
-#define MX23_CLKCTRL_RESET_OFFSET	0x120
-#define MX28_CLKCTRL_RESET_OFFSET	0x1e0
-#define MXS_CLKCTRL_RESET_CHIP		(1 << 1)
-
-#define MXS_MODULE_CLKGATE		(1 << 30)
-#define MXS_MODULE_SFTRST		(1 << 31)
-
-static void __iomem *mxs_clkctrl_reset_addr;
-
-/*
- * Reset the system. It is called by machine_restart().
- */
-void mxs_restart(char mode, const char *cmd)
-{
-	/* reset the chip */
-	__mxs_setl(MXS_CLKCTRL_RESET_CHIP, mxs_clkctrl_reset_addr);
-
-	pr_err("Failed to assert the chip reset\n");
-
-	/* Delay to allow the serial port to show the message */
-	mdelay(50);
-
-	/* We'll take a jump through zero as a poor second */
-	soft_restart(0);
-}
-
-static int __init mxs_arch_reset_init(void)
-{
-	struct clk *clk;
-
-	mxs_clkctrl_reset_addr = MXS_IO_ADDRESS(MXS_CLKCTRL_BASE_ADDR) +
-				(cpu_is_mx23() ? MX23_CLKCTRL_RESET_OFFSET :
-						 MX28_CLKCTRL_RESET_OFFSET);
-
-	clk = clk_get_sys("rtc", NULL);
-	if (!IS_ERR(clk))
-		clk_prepare_enable(clk);
-
-	return 0;
-}
-core_initcall(mxs_arch_reset_init);
-
-/*
- * Clear the bit and poll it cleared.  This is usually called with
- * a reset address and mask being either SFTRST(bit 31) or CLKGATE
- * (bit 30).
- */
-static int clear_poll_bit(void __iomem *addr, u32 mask)
-{
-	int timeout = 0x400;
-
-	/* clear the bit */
-	__mxs_clrl(mask, addr);
-
-	/*
-	 * SFTRST needs 3 GPMI clocks to settle, the reference manual
-	 * recommends to wait 1us.
-	 */
-	udelay(1);
-
-	/* poll the bit becoming clear */
-	while ((__raw_readl(addr) & mask) && --timeout)
-		/* nothing */;
-
-	return !timeout;
-}
-
-int mxs_reset_block(void __iomem *reset_addr)
-{
-	int ret;
-	int timeout = 0x400;
-
-	/* clear and poll SFTRST */
-	ret = clear_poll_bit(reset_addr, MXS_MODULE_SFTRST);
-	if (unlikely(ret))
-		goto error;
-
-	/* clear CLKGATE */
-	__mxs_clrl(MXS_MODULE_CLKGATE, reset_addr);
-
-	/* set SFTRST to reset the block */
-	__mxs_setl(MXS_MODULE_SFTRST, reset_addr);
-	udelay(1);
-
-	/* poll CLKGATE becoming set */
-	while ((!(__raw_readl(reset_addr) & MXS_MODULE_CLKGATE)) && --timeout)
-		/* nothing */;
-	if (unlikely(!timeout))
-		goto error;
-
-	/* clear and poll SFTRST */
-	ret = clear_poll_bit(reset_addr, MXS_MODULE_SFTRST);
-	if (unlikely(ret))
-		goto error;
-
-	/* clear and poll CLKGATE */
-	ret = clear_poll_bit(reset_addr, MXS_MODULE_CLKGATE);
-	if (unlikely(ret))
-		goto error;
-
-	return 0;
-
-error:
-	pr_err("%s(%p): module reset timeout\n", __func__, reset_addr);
-	return -ETIMEDOUT;
-}
-EXPORT_SYMBOL(mxs_reset_block);
diff --git a/arch/arm/mach-mxs/timer.c b/arch/arm/mach-mxs/timer.c
deleted file mode 100644
index 4210204..0000000
--- a/arch/arm/mach-mxs/timer.c
+++ /dev/null
@@ -1,306 +0,0 @@
-/*
- *  Copyright (C) 2000-2001 Deep Blue Solutions
- *  Copyright (C) 2002 Shane Nay (shane@minirl.com)
- *  Copyright (C) 2006-2007 Pavel Pisa (ppisa@pikron.com)
- *  Copyright (C) 2008 Juergen Beisert (kernel@pengutronix.de)
- *  Copyright (C) 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/err.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/clockchips.h>
-#include <linux/clk.h>
-#include <linux/of.h>
-#include <linux/of_irq.h>
-
-#include <asm/mach/time.h>
-#include <asm/sched_clock.h>
-#include <mach/mxs.h>
-#include <mach/common.h>
-
-/*
- * There are 2 versions of the timrot on Freescale MXS-based SoCs.
- * The v1 on MX23 only gets 16 bits counter, while v2 on MX28
- * extends the counter to 32 bits.
- *
- * The implementation uses two timers, one for clock_event and
- * another for clocksource. MX28 uses timrot 0 and 1, while MX23
- * uses 0 and 2.
- */
-
-#define MX23_TIMROT_VERSION_OFFSET	0x0a0
-#define MX28_TIMROT_VERSION_OFFSET	0x120
-#define BP_TIMROT_MAJOR_VERSION		24
-#define BV_TIMROT_VERSION_1		0x01
-#define BV_TIMROT_VERSION_2		0x02
-#define timrot_is_v1()	(timrot_major_version == BV_TIMROT_VERSION_1)
-
-/*
- * There are 4 registers for each timrotv2 instance, and 2 registers
- * for each timrotv1. So address step 0x40 in macros below strides
- * one instance of timrotv2 while two instances of timrotv1.
- *
- * As the result, HW_TIMROT_XXXn(1) defines the address of timrot1
- * on MX28 while timrot2 on MX23.
- */
-/* common between v1 and v2 */
-#define HW_TIMROT_ROTCTRL		0x00
-#define HW_TIMROT_TIMCTRLn(n)		(0x20 + (n) * 0x40)
-/* v1 only */
-#define HW_TIMROT_TIMCOUNTn(n)		(0x30 + (n) * 0x40)
-/* v2 only */
-#define HW_TIMROT_RUNNING_COUNTn(n)	(0x30 + (n) * 0x40)
-#define HW_TIMROT_FIXED_COUNTn(n)	(0x40 + (n) * 0x40)
-
-#define BM_TIMROT_TIMCTRLn_RELOAD	(1 << 6)
-#define BM_TIMROT_TIMCTRLn_UPDATE	(1 << 7)
-#define BM_TIMROT_TIMCTRLn_IRQ_EN	(1 << 14)
-#define BM_TIMROT_TIMCTRLn_IRQ		(1 << 15)
-#define BP_TIMROT_TIMCTRLn_SELECT	0
-#define BV_TIMROTv1_TIMCTRLn_SELECT__32KHZ_XTAL		0x8
-#define BV_TIMROTv2_TIMCTRLn_SELECT__32KHZ_XTAL		0xb
-#define BV_TIMROTv2_TIMCTRLn_SELECT__TICK_ALWAYS	0xf
-
-static struct clock_event_device mxs_clockevent_device;
-static enum clock_event_mode mxs_clockevent_mode = CLOCK_EVT_MODE_UNUSED;
-
-static void __iomem *mxs_timrot_base = MXS_IO_ADDRESS(MXS_TIMROT_BASE_ADDR);
-static u32 timrot_major_version;
-
-static inline void timrot_irq_disable(void)
-{
-	__mxs_clrl(BM_TIMROT_TIMCTRLn_IRQ_EN,
-			mxs_timrot_base + HW_TIMROT_TIMCTRLn(0));
-}
-
-static inline void timrot_irq_enable(void)
-{
-	__mxs_setl(BM_TIMROT_TIMCTRLn_IRQ_EN,
-			mxs_timrot_base + HW_TIMROT_TIMCTRLn(0));
-}
-
-static void timrot_irq_acknowledge(void)
-{
-	__mxs_clrl(BM_TIMROT_TIMCTRLn_IRQ,
-			mxs_timrot_base + HW_TIMROT_TIMCTRLn(0));
-}
-
-static cycle_t timrotv1_get_cycles(struct clocksource *cs)
-{
-	return ~((__raw_readl(mxs_timrot_base + HW_TIMROT_TIMCOUNTn(1))
-			& 0xffff0000) >> 16);
-}
-
-static int timrotv1_set_next_event(unsigned long evt,
-					struct clock_event_device *dev)
-{
-	/* timrot decrements the count */
-	__raw_writel(evt, mxs_timrot_base + HW_TIMROT_TIMCOUNTn(0));
-
-	return 0;
-}
-
-static int timrotv2_set_next_event(unsigned long evt,
-					struct clock_event_device *dev)
-{
-	/* timrot decrements the count */
-	__raw_writel(evt, mxs_timrot_base + HW_TIMROT_FIXED_COUNTn(0));
-
-	return 0;
-}
-
-static irqreturn_t mxs_timer_interrupt(int irq, void *dev_id)
-{
-	struct clock_event_device *evt = dev_id;
-
-	timrot_irq_acknowledge();
-	evt->event_handler(evt);
-
-	return IRQ_HANDLED;
-}
-
-static struct irqaction mxs_timer_irq = {
-	.name		= "MXS Timer Tick",
-	.dev_id		= &mxs_clockevent_device,
-	.flags		= IRQF_TIMER | IRQF_IRQPOLL,
-	.handler	= mxs_timer_interrupt,
-};
-
-#ifdef DEBUG
-static const char *clock_event_mode_label[] const = {
-	[CLOCK_EVT_MODE_PERIODIC] = "CLOCK_EVT_MODE_PERIODIC",
-	[CLOCK_EVT_MODE_ONESHOT]  = "CLOCK_EVT_MODE_ONESHOT",
-	[CLOCK_EVT_MODE_SHUTDOWN] = "CLOCK_EVT_MODE_SHUTDOWN",
-	[CLOCK_EVT_MODE_UNUSED]   = "CLOCK_EVT_MODE_UNUSED"
-};
-#endif /* DEBUG */
-
-static void mxs_set_mode(enum clock_event_mode mode,
-				struct clock_event_device *evt)
-{
-	/* Disable interrupt in timer module */
-	timrot_irq_disable();
-
-	if (mode != mxs_clockevent_mode) {
-		/* Set event time into the furthest future */
-		if (timrot_is_v1())
-			__raw_writel(0xffff,
-				mxs_timrot_base + HW_TIMROT_TIMCOUNTn(1));
-		else
-			__raw_writel(0xffffffff,
-				mxs_timrot_base + HW_TIMROT_FIXED_COUNTn(1));
-
-		/* Clear pending interrupt */
-		timrot_irq_acknowledge();
-	}
-
-#ifdef DEBUG
-	pr_info("%s: changing mode from %s to %s\n", __func__,
-		clock_event_mode_label[mxs_clockevent_mode],
-		clock_event_mode_label[mode]);
-#endif /* DEBUG */
-
-	/* Remember timer mode */
-	mxs_clockevent_mode = mode;
-
-	switch (mode) {
-	case CLOCK_EVT_MODE_PERIODIC:
-		pr_err("%s: Periodic mode is not implemented\n", __func__);
-		break;
-	case CLOCK_EVT_MODE_ONESHOT:
-		timrot_irq_enable();
-		break;
-	case CLOCK_EVT_MODE_SHUTDOWN:
-	case CLOCK_EVT_MODE_UNUSED:
-	case CLOCK_EVT_MODE_RESUME:
-		/* Left event sources disabled, no more interrupts appear */
-		break;
-	}
-}
-
-static struct clock_event_device mxs_clockevent_device = {
-	.name		= "mxs_timrot",
-	.features	= CLOCK_EVT_FEAT_ONESHOT,
-	.set_mode	= mxs_set_mode,
-	.set_next_event	= timrotv2_set_next_event,
-	.rating		= 200,
-};
-
-static int __init mxs_clockevent_init(struct clk *timer_clk)
-{
-	if (timrot_is_v1())
-		mxs_clockevent_device.set_next_event = timrotv1_set_next_event;
-	mxs_clockevent_device.cpumask = cpumask_of(0);
-	clockevents_config_and_register(&mxs_clockevent_device,
-					clk_get_rate(timer_clk),
-					timrot_is_v1() ? 0xf : 0x2,
-					timrot_is_v1() ? 0xfffe : 0xfffffffe);
-
-	return 0;
-}
-
-static struct clocksource clocksource_mxs = {
-	.name		= "mxs_timer",
-	.rating		= 200,
-	.read		= timrotv1_get_cycles,
-	.mask		= CLOCKSOURCE_MASK(16),
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
-static u32 notrace mxs_read_sched_clock_v2(void)
-{
-	return ~readl_relaxed(mxs_timrot_base + HW_TIMROT_RUNNING_COUNTn(1));
-}
-
-static int __init mxs_clocksource_init(struct clk *timer_clk)
-{
-	unsigned int c = clk_get_rate(timer_clk);
-
-	if (timrot_is_v1())
-		clocksource_register_hz(&clocksource_mxs, c);
-	else {
-		clocksource_mmio_init(mxs_timrot_base + HW_TIMROT_RUNNING_COUNTn(1),
-			"mxs_timer", c, 200, 32, clocksource_mmio_readl_down);
-		setup_sched_clock(mxs_read_sched_clock_v2, 32, c);
-	}
-
-	return 0;
-}
-
-void __init mxs_timer_init(void)
-{
-	struct device_node *np;
-	struct clk *timer_clk;
-	int irq;
-
-	np = of_find_compatible_node(NULL, NULL, "fsl,timrot");
-	if (!np) {
-		pr_err("%s: failed find timrot node\n", __func__);
-		return;
-	}
-
-	timer_clk = clk_get_sys("timrot", NULL);
-	if (IS_ERR(timer_clk)) {
-		pr_err("%s: failed to get clk\n", __func__);
-		return;
-	}
-
-	clk_prepare_enable(timer_clk);
-
-	/*
-	 * Initialize timers to a known state
-	 */
-	mxs_reset_block(mxs_timrot_base + HW_TIMROT_ROTCTRL);
-
-	/* get timrot version */
-	timrot_major_version = __raw_readl(mxs_timrot_base +
-				(cpu_is_mx23() ? MX23_TIMROT_VERSION_OFFSET :
-						MX28_TIMROT_VERSION_OFFSET));
-	timrot_major_version >>= BP_TIMROT_MAJOR_VERSION;
-
-	/* one for clock_event */
-	__raw_writel((timrot_is_v1() ?
-			BV_TIMROTv1_TIMCTRLn_SELECT__32KHZ_XTAL :
-			BV_TIMROTv2_TIMCTRLn_SELECT__TICK_ALWAYS) |
-			BM_TIMROT_TIMCTRLn_UPDATE |
-			BM_TIMROT_TIMCTRLn_IRQ_EN,
-			mxs_timrot_base + HW_TIMROT_TIMCTRLn(0));
-
-	/* another for clocksource */
-	__raw_writel((timrot_is_v1() ?
-			BV_TIMROTv1_TIMCTRLn_SELECT__32KHZ_XTAL :
-			BV_TIMROTv2_TIMCTRLn_SELECT__TICK_ALWAYS) |
-			BM_TIMROT_TIMCTRLn_RELOAD,
-			mxs_timrot_base + HW_TIMROT_TIMCTRLn(1));
-
-	/* set clocksource timer fixed count to the maximum */
-	if (timrot_is_v1())
-		__raw_writel(0xffff,
-			mxs_timrot_base + HW_TIMROT_TIMCOUNTn(1));
-	else
-		__raw_writel(0xffffffff,
-			mxs_timrot_base + HW_TIMROT_FIXED_COUNTn(1));
-
-	/* init and register the timer to the framework */
-	mxs_clocksource_init(timer_clk);
-	mxs_clockevent_init(timer_clk);
-
-	/* Make irqs happen */
-	irq = irq_of_parse_and_map(np, 0);
-	setup_irq(irq, &mxs_timer_irq);
-}
diff --git a/arch/arm/mach-nomadik/Kconfig b/arch/arm/mach-nomadik/Kconfig
index 82226a5..3213bad 100644
--- a/arch/arm/mach-nomadik/Kconfig
+++ b/arch/arm/mach-nomadik/Kconfig
@@ -1,5 +1,23 @@
-if ARCH_NOMADIK
+config ARCH_NOMADIK
+	bool "ST-Ericsson Nomadik"
+	depends on ARCH_MULTI_V5
+	select ARCH_REQUIRE_GPIOLIB
+	select ARM_AMBA
+	select ARM_VIC
+	select CLKSRC_NOMADIK_MTU
+	select COMMON_CLK
+	select CPU_ARM926T
+	select GENERIC_CLOCKEVENTS
+	select MIGHT_HAVE_CACHE_L2X0
+	select PINCTRL
+	select PINCTRL_NOMADIK
+	select PINCTRL_STN8815
+	select SPARSE_IRQ
+	select USE_OF
+	help
+	  Support for the Nomadik platform by ST-Ericsson
 
+if ARCH_NOMADIK
 menu "Nomadik boards"
 
 config MACH_NOMADIK_8815NHK
@@ -9,8 +27,8 @@ config MACH_NOMADIK_8815NHK
 	select I2C_ALGOBIT
 
 endmenu
+endif
 
 config NOMADIK_8815
+	depends on ARCH_NOMADIK
 	bool
-
-endif
diff --git a/arch/arm/mach-nomadik/Makefile.boot b/arch/arm/mach-nomadik/Makefile.boot
deleted file mode 100644
index ff0a4b5..0000000
--- a/arch/arm/mach-nomadik/Makefile.boot
+++ /dev/null
@@ -1,4 +0,0 @@
-   zreladdr-y	+= 0x00008000
-params_phys-y	:= 0x00000100
-initrd_phys-y	:= 0x00800000
-
diff --git a/arch/arm/mach-nomadik/cpu-8815.c b/arch/arm/mach-nomadik/cpu-8815.c
index 21c1aa5..59f6ff5 100644
--- a/arch/arm/mach-nomadik/cpu-8815.c
+++ b/arch/arm/mach-nomadik/cpu-8815.c
@@ -38,7 +38,6 @@
 #include <linux/gpio.h>
 #include <linux/amba/mmci.h>
 
-#include <mach/irqs.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
diff --git a/arch/arm/mach-nomadik/include/mach/debug-macro.S b/arch/arm/mach-nomadik/include/mach/debug-macro.S
deleted file mode 100644
index 7354179..0000000
--- a/arch/arm/mach-nomadik/include/mach/debug-macro.S
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Debugging macro include header
- *
- *  Copyright (C) 1994-1999 Russell King
- *  Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
-*/
-
-		.macro	addruart, rp, rv, tmp
-		mov	\rp, #0x00100000
-		add	\rp, \rp, #0x000fb000
-		add	\rv, \rp, #0xf0000000	@ virtual base
-		add	\rp, \rp, #0x10000000	@ physical base address
-		.endm
-
-#include <asm/hardware/debug-pl01x.S>
diff --git a/arch/arm/mach-nomadik/include/mach/irqs.h b/arch/arm/mach-nomadik/include/mach/irqs.h
deleted file mode 100644
index 90ac965..0000000
--- a/arch/arm/mach-nomadik/include/mach/irqs.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- *  mach-nomadik/include/mach/irqs.h
- *
- *  Copyright (C) ST 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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You 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_ARCH_IRQS_H
-#define __ASM_ARCH_IRQS_H
-
-#define IRQ_VIC_START		32	/* first VIC interrupt is 1 */
-
-/*
- * Interrupt numbers generic for all Nomadik Chip cuts
- */
-#define IRQ_WATCHDOG			(IRQ_VIC_START+0)
-#define IRQ_SOFTINT			(IRQ_VIC_START+1)
-#define IRQ_CRYPTO			(IRQ_VIC_START+2)
-#define IRQ_OWM				(IRQ_VIC_START+3)
-#define IRQ_MTU0			(IRQ_VIC_START+4)
-#define IRQ_MTU1			(IRQ_VIC_START+5)
-#define IRQ_GPIO0			(IRQ_VIC_START+6)
-#define IRQ_GPIO1			(IRQ_VIC_START+7)
-#define IRQ_GPIO2			(IRQ_VIC_START+8)
-#define IRQ_GPIO3			(IRQ_VIC_START+9)
-#define IRQ_RTC_RTT			(IRQ_VIC_START+10)
-#define IRQ_SSP				(IRQ_VIC_START+11)
-#define IRQ_UART0			(IRQ_VIC_START+12)
-#define IRQ_DMA1			(IRQ_VIC_START+13)
-#define IRQ_CLCD_MDIF			(IRQ_VIC_START+14)
-#define IRQ_DMA0			(IRQ_VIC_START+15)
-#define IRQ_PWRFAIL			(IRQ_VIC_START+16)
-#define IRQ_UART1			(IRQ_VIC_START+17)
-#define IRQ_FIRDA			(IRQ_VIC_START+18)
-#define IRQ_MSP0			(IRQ_VIC_START+19)
-#define IRQ_I2C0			(IRQ_VIC_START+20)
-#define IRQ_I2C1			(IRQ_VIC_START+21)
-#define IRQ_SDMMC			(IRQ_VIC_START+22)
-#define IRQ_USBOTG			(IRQ_VIC_START+23)
-#define IRQ_SVA_IT0			(IRQ_VIC_START+24)
-#define IRQ_SVA_IT1			(IRQ_VIC_START+25)
-#define IRQ_SAA_IT0			(IRQ_VIC_START+26)
-#define IRQ_SAA_IT1			(IRQ_VIC_START+27)
-#define IRQ_UART2			(IRQ_VIC_START+28)
-#define IRQ_MSP2			(IRQ_VIC_START+29)
-#define IRQ_L2CC			(IRQ_VIC_START+30)
-#define IRQ_HPI				(IRQ_VIC_START+31)
-#define IRQ_SKE				(IRQ_VIC_START+32)
-#define IRQ_KP				(IRQ_VIC_START+33)
-#define IRQ_MEMST			(IRQ_VIC_START+34)
-#define IRQ_SGA_IT			(IRQ_VIC_START+35)
-#define IRQ_USBM			(IRQ_VIC_START+36)
-#define IRQ_MSP1			(IRQ_VIC_START+37)
-
-#define NOMADIK_GPIO_OFFSET		(IRQ_VIC_START+64)
-
-/* After chip-specific IRQ numbers we have the GPIO ones */
-#define NOMADIK_NR_GPIO			128 /* last 4 not wired to pins */
-#define NOMADIK_GPIO_TO_IRQ(gpio)	((gpio) + NOMADIK_GPIO_OFFSET)
-#define NOMADIK_IRQ_TO_GPIO(irq)	((irq) - NOMADIK_GPIO_OFFSET)
-#define NOMADIK_NR_IRQS			NOMADIK_GPIO_TO_IRQ(NOMADIK_NR_GPIO)
-
-/* Following two are used by entry_macro.S, to access our dual-vic */
-#define VIC_REG_IRQSR0		0
-#define VIC_REG_IRQSR1		0x20
-
-#endif /* __ASM_ARCH_IRQS_H */
diff --git a/arch/arm/mach-nomadik/include/mach/timex.h b/arch/arm/mach-nomadik/include/mach/timex.h
deleted file mode 100644
index 318b889..0000000
--- a/arch/arm/mach-nomadik/include/mach/timex.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __ASM_ARCH_TIMEX_H
-#define __ASM_ARCH_TIMEX_H
-
-#define CLOCK_TICK_RATE         2400000
-
-#endif
diff --git a/arch/arm/mach-nomadik/include/mach/uncompress.h b/arch/arm/mach-nomadik/include/mach/uncompress.h
deleted file mode 100644
index 106fccc..0000000
--- a/arch/arm/mach-nomadik/include/mach/uncompress.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- *  Copyright (C) 2008 STMicroelectronics
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You 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_ARCH_UNCOMPRESS_H
-#define __ASM_ARCH_UNCOMPRESS_H
-
-#include <asm/setup.h>
-#include <asm/io.h>
-
-/* we need the constants in amba/serial.h, but it refers to amba_device */
-struct amba_device;
-#include <linux/amba/serial.h>
-
-#define NOMADIK_UART_DR		(void __iomem *)0x101FB000
-#define NOMADIK_UART_LCRH	(void __iomem *)0x101FB02c
-#define NOMADIK_UART_CR		(void __iomem *)0x101FB030
-#define NOMADIK_UART_FR		(void __iomem *)0x101FB018
-
-static void putc(const char c)
-{
-	/* Do nothing if the UART is not enabled. */
-	if (!(readb(NOMADIK_UART_CR) & UART01x_CR_UARTEN))
-		return;
-
-	if (c == '\n')
-		putc('\r');
-
-	while (readb(NOMADIK_UART_FR) & UART01x_FR_TXFF)
-		barrier();
-	writeb(c, NOMADIK_UART_DR);
-}
-
-static void flush(void)
-{
-	if (!(readb(NOMADIK_UART_CR) & UART01x_CR_UARTEN))
-		return;
-	while (readb(NOMADIK_UART_FR) & UART01x_FR_BUSY)
-		barrier();
-}
-
-static inline void arch_decomp_setup(void)
-{
-}
-
-#endif /* __ASM_ARCH_UNCOMPRESS_H */
diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile
index 222d58c..3889b6c 100644
--- a/arch/arm/mach-omap1/Makefile
+++ b/arch/arm/mach-omap1/Makefile
@@ -19,10 +19,6 @@ obj-$(CONFIG_ARCH_OMAP16XX) += ocpi.o
 # Power Management
 obj-$(CONFIG_PM) += pm.o sleep.o
 
-# DSP
-obj-$(CONFIG_OMAP_MBOX_FWK)	+= mailbox_mach.o
-mailbox_mach-objs		:= mailbox.o
-
 i2c-omap-$(CONFIG_I2C_OMAP)		:= i2c.o
 obj-y					+= $(i2c-omap-m) $(i2c-omap-y)
 
diff --git a/arch/arm/mach-omap1/clock_data.c b/arch/arm/mach-omap1/clock_data.c
index cb7c6ae..6c4f766 100644
--- a/arch/arm/mach-omap1/clock_data.c
+++ b/arch/arm/mach-omap1/clock_data.c
@@ -543,15 +543,6 @@ static struct clk usb_dc_ck = {
 	/* Direct from ULPD, no parent */
 	.rate		= 48000000,
 	.enable_reg	= OMAP1_IO_ADDRESS(SOFT_REQ_REG),
-	.enable_bit	= USB_REQ_EN_SHIFT,
-};
-
-static struct clk usb_dc_ck7xx = {
-	.name		= "usb_dc_ck",
-	.ops		= &clkops_generic,
-	/* Direct from ULPD, no parent */
-	.rate		= 48000000,
-	.enable_reg	= OMAP1_IO_ADDRESS(SOFT_REQ_REG),
 	.enable_bit	= SOFT_USB_OTG_DPLL_REQ_SHIFT,
 };
 
@@ -727,8 +718,7 @@ static struct omap_clk omap_clks[] = {
 	CLK(NULL,	"usb_clko",	&usb_clko,	CK_16XX | CK_1510 | CK_310),
 	CLK(NULL,	"usb_hhc_ck",	&usb_hhc_ck1510, CK_1510 | CK_310),
 	CLK(NULL,	"usb_hhc_ck",	&usb_hhc_ck16xx, CK_16XX),
-	CLK(NULL,	"usb_dc_ck",	&usb_dc_ck,	CK_16XX),
-	CLK(NULL,	"usb_dc_ck",	&usb_dc_ck7xx,	CK_7XX),
+	CLK(NULL,	"usb_dc_ck",	&usb_dc_ck,	CK_16XX | CK_7XX),
 	CLK(NULL,	"mclk",		&mclk_1510,	CK_1510 | CK_310),
 	CLK(NULL,	"mclk",		&mclk_16xx,	CK_16XX),
 	CLK(NULL,	"bclk",		&bclk_1510,	CK_1510 | CK_310),
diff --git a/arch/arm/mach-omap1/mailbox.c b/arch/arm/mach-omap1/mailbox.c
deleted file mode 100644
index efc8f20..0000000
--- a/arch/arm/mach-omap1/mailbox.c
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * Mailbox reservation modules for OMAP1
- *
- * Copyright (C) 2006-2009 Nokia Corporation
- * Written by: Hiroshi DOYU <Hiroshi.DOYU@nokia.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/module.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <plat/mailbox.h>
-
-#define MAILBOX_ARM2DSP1		0x00
-#define MAILBOX_ARM2DSP1b		0x04
-#define MAILBOX_DSP2ARM1		0x08
-#define MAILBOX_DSP2ARM1b		0x0c
-#define MAILBOX_DSP2ARM2		0x10
-#define MAILBOX_DSP2ARM2b		0x14
-#define MAILBOX_ARM2DSP1_Flag		0x18
-#define MAILBOX_DSP2ARM1_Flag		0x1c
-#define MAILBOX_DSP2ARM2_Flag		0x20
-
-static void __iomem *mbox_base;
-
-struct omap_mbox1_fifo {
-	unsigned long cmd;
-	unsigned long data;
-	unsigned long flag;
-};
-
-struct omap_mbox1_priv {
-	struct omap_mbox1_fifo tx_fifo;
-	struct omap_mbox1_fifo rx_fifo;
-};
-
-static inline int mbox_read_reg(size_t ofs)
-{
-	return __raw_readw(mbox_base + ofs);
-}
-
-static inline void mbox_write_reg(u32 val, size_t ofs)
-{
-	__raw_writew(val, mbox_base + ofs);
-}
-
-/* msg */
-static mbox_msg_t omap1_mbox_fifo_read(struct omap_mbox *mbox)
-{
-	struct omap_mbox1_fifo *fifo =
-		&((struct omap_mbox1_priv *)mbox->priv)->rx_fifo;
-	mbox_msg_t msg;
-
-	msg = mbox_read_reg(fifo->data);
-	msg |= ((mbox_msg_t) mbox_read_reg(fifo->cmd)) << 16;
-
-	return msg;
-}
-
-static void
-omap1_mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg)
-{
-	struct omap_mbox1_fifo *fifo =
-		&((struct omap_mbox1_priv *)mbox->priv)->tx_fifo;
-
-	mbox_write_reg(msg & 0xffff, fifo->data);
-	mbox_write_reg(msg >> 16, fifo->cmd);
-}
-
-static int omap1_mbox_fifo_empty(struct omap_mbox *mbox)
-{
-	return 0;
-}
-
-static int omap1_mbox_fifo_full(struct omap_mbox *mbox)
-{
-	struct omap_mbox1_fifo *fifo =
-		&((struct omap_mbox1_priv *)mbox->priv)->rx_fifo;
-
-	return mbox_read_reg(fifo->flag);
-}
-
-/* irq */
-static void
-omap1_mbox_enable_irq(struct omap_mbox *mbox, omap_mbox_type_t irq)
-{
-	if (irq == IRQ_RX)
-		enable_irq(mbox->irq);
-}
-
-static void
-omap1_mbox_disable_irq(struct omap_mbox *mbox, omap_mbox_type_t irq)
-{
-	if (irq == IRQ_RX)
-		disable_irq(mbox->irq);
-}
-
-static int
-omap1_mbox_is_irq(struct omap_mbox *mbox, omap_mbox_type_t irq)
-{
-	if (irq == IRQ_TX)
-		return 0;
-	return 1;
-}
-
-static struct omap_mbox_ops omap1_mbox_ops = {
-	.type		= OMAP_MBOX_TYPE1,
-	.fifo_read	= omap1_mbox_fifo_read,
-	.fifo_write	= omap1_mbox_fifo_write,
-	.fifo_empty	= omap1_mbox_fifo_empty,
-	.fifo_full	= omap1_mbox_fifo_full,
-	.enable_irq	= omap1_mbox_enable_irq,
-	.disable_irq	= omap1_mbox_disable_irq,
-	.is_irq		= omap1_mbox_is_irq,
-};
-
-/* FIXME: the following struct should be created automatically by the user id */
-
-/* DSP */
-static struct omap_mbox1_priv omap1_mbox_dsp_priv = {
-	.tx_fifo = {
-		.cmd	= MAILBOX_ARM2DSP1b,
-		.data	= MAILBOX_ARM2DSP1,
-		.flag	= MAILBOX_ARM2DSP1_Flag,
-	},
-	.rx_fifo = {
-		.cmd	= MAILBOX_DSP2ARM1b,
-		.data	= MAILBOX_DSP2ARM1,
-		.flag	= MAILBOX_DSP2ARM1_Flag,
-	},
-};
-
-static struct omap_mbox mbox_dsp_info = {
-	.name	= "dsp",
-	.ops	= &omap1_mbox_ops,
-	.priv	= &omap1_mbox_dsp_priv,
-};
-
-static struct omap_mbox *omap1_mboxes[] = { &mbox_dsp_info, NULL };
-
-static int omap1_mbox_probe(struct platform_device *pdev)
-{
-	struct resource *mem;
-	int ret;
-	struct omap_mbox **list;
-
-	list = omap1_mboxes;
-	list[0]->irq = platform_get_irq_byname(pdev, "dsp");
-
-	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	mbox_base = ioremap(mem->start, resource_size(mem));
-	if (!mbox_base)
-		return -ENOMEM;
-
-	ret = omap_mbox_register(&pdev->dev, list);
-	if (ret) {
-		iounmap(mbox_base);
-		return ret;
-	}
-
-	return 0;
-}
-
-static int omap1_mbox_remove(struct platform_device *pdev)
-{
-	omap_mbox_unregister();
-	iounmap(mbox_base);
-	return 0;
-}
-
-static struct platform_driver omap1_mbox_driver = {
-	.probe	= omap1_mbox_probe,
-	.remove	= omap1_mbox_remove,
-	.driver	= {
-		.name	= "omap-mailbox",
-	},
-};
-
-static int __init omap1_mbox_init(void)
-{
-	return platform_driver_register(&omap1_mbox_driver);
-}
-
-static void __exit omap1_mbox_exit(void)
-{
-	platform_driver_unregister(&omap1_mbox_driver);
-}
-
-module_init(omap1_mbox_init);
-module_exit(omap1_mbox_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("omap mailbox: omap1 architecture specific functions");
-MODULE_AUTHOR("Hiroshi DOYU <Hiroshi.DOYU@nokia.com>");
-MODULE_ALIAS("platform:omap1-mailbox");
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index b068b7f..4098635 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -203,9 +203,6 @@ obj-$(CONFIG_ARCH_OMAP4)		+= omap_hwmod_44xx_data.o
 obj-$(CONFIG_OMAP3_EMU)			+= emu.o
 obj-$(CONFIG_HW_PERF_EVENTS)		+= pmu.o
 
-obj-$(CONFIG_OMAP_MBOX_FWK)		+= mailbox_mach.o
-mailbox_mach-objs			:= mailbox.o
-
 iommu-$(CONFIG_OMAP_IOMMU)		:= omap-iommu.o
 obj-y					+= $(iommu-m) $(iommu-y)
 
diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c
index a3e0aaa..e551aae 100644
--- a/arch/arm/mach-omap2/board-2430sdp.c
+++ b/arch/arm/mach-omap2/board-2430sdp.c
@@ -38,7 +38,7 @@
 #include "gpmc-smc91x.h"
 
 #include <video/omapdss.h>
-#include <video/omap-panel-generic-dpi.h>
+#include <video/omap-panel-data.h>
 
 #include "mux.h"
 #include "hsmmc.h"
@@ -108,24 +108,13 @@ static struct platform_device *sdp2430_devices[] __initdata = {
 #define SDP2430_LCD_PANEL_BACKLIGHT_GPIO	91
 #define SDP2430_LCD_PANEL_ENABLE_GPIO		154
 
-static int sdp2430_panel_enable_lcd(struct omap_dss_device *dssdev)
-{
-	gpio_direction_output(SDP2430_LCD_PANEL_ENABLE_GPIO, 1);
-	gpio_direction_output(SDP2430_LCD_PANEL_BACKLIGHT_GPIO, 1);
-
-	return 0;
-}
-
-static void sdp2430_panel_disable_lcd(struct omap_dss_device *dssdev)
-{
-	gpio_direction_output(SDP2430_LCD_PANEL_ENABLE_GPIO, 0);
-	gpio_direction_output(SDP2430_LCD_PANEL_BACKLIGHT_GPIO, 0);
-}
-
 static struct panel_generic_dpi_data sdp2430_panel_data = {
 	.name			= "nec_nl2432dr22-11b",
-	.platform_enable	= sdp2430_panel_enable_lcd,
-	.platform_disable	= sdp2430_panel_disable_lcd,
+	.num_gpios		= 2,
+	.gpios			= {
+		SDP2430_LCD_PANEL_ENABLE_GPIO,
+		SDP2430_LCD_PANEL_BACKLIGHT_GPIO,
+	},
 };
 
 static struct omap_dss_device sdp2430_lcd_device = {
@@ -146,26 +135,6 @@ static struct omap_dss_board_info sdp2430_dss_data = {
 	.default_device	= &sdp2430_lcd_device,
 };
 
-static void __init sdp2430_display_init(void)
-{
-	int r;
-
-	static struct gpio gpios[] __initdata = {
-		{ SDP2430_LCD_PANEL_ENABLE_GPIO, GPIOF_OUT_INIT_LOW,
-			"LCD reset" },
-		{ SDP2430_LCD_PANEL_BACKLIGHT_GPIO, GPIOF_OUT_INIT_LOW,
-			"LCD Backlight" },
-	};
-
-	r = gpio_request_array(gpios, ARRAY_SIZE(gpios));
-	if (r) {
-		pr_err("Cannot request LCD GPIOs, error %d\n", r);
-		return;
-	}
-
-	omap_display_init(&sdp2430_dss_data);
-}
-
 #if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91x_MODULE)
 
 static struct omap_smc91x_platform_data board_smc91x_data = {
@@ -273,7 +242,7 @@ static void __init omap_2430sdp_init(void)
 	gpio_request_one(SECONDARY_LCD_GPIO, GPIOF_OUT_INIT_LOW,
 			 "Secondary LCD backlight");
 
-	sdp2430_display_init();
+	omap_display_init(&sdp2430_dss_data);
 }
 
 MACHINE_START(OMAP_2430SDP, "OMAP2430 sdp2430 board")
diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
index ce812de..594c633 100644
--- a/arch/arm/mach-omap2/board-3430sdp.c
+++ b/arch/arm/mach-omap2/board-3430sdp.c
@@ -35,7 +35,7 @@
 #include "common.h"
 #include <linux/omap-dma.h>
 #include <video/omapdss.h>
-#include <video/omap-panel-tfp410.h>
+#include <video/omap-panel-data.h>
 
 #include "gpmc.h"
 #include "gpmc-smc91x.h"
@@ -108,53 +108,38 @@ static struct twl4030_keypad_data sdp3430_kp_data = {
 #define SDP3430_LCD_PANEL_BACKLIGHT_GPIO	8
 #define SDP3430_LCD_PANEL_ENABLE_GPIO		5
 
-static struct gpio sdp3430_dss_gpios[] __initdata = {
-	{SDP3430_LCD_PANEL_ENABLE_GPIO,    GPIOF_OUT_INIT_LOW, "LCD reset"    },
-	{SDP3430_LCD_PANEL_BACKLIGHT_GPIO, GPIOF_OUT_INIT_LOW, "LCD Backlight"},
-};
-
 static void __init sdp3430_display_init(void)
 {
 	int r;
 
-	r = gpio_request_array(sdp3430_dss_gpios,
-			       ARRAY_SIZE(sdp3430_dss_gpios));
+	/*
+	 * the backlight GPIO doesn't directly go to the panel, it enables
+	 * an internal circuit on 3430sdp to create the signal V_BKL_28V,
+	 * this is connected to LED+ pin of the sharp panel. This GPIO
+	 * is left enabled in the board file, and not passed to the panel
+	 * as platform_data.
+	 */
+	r = gpio_request_one(SDP3430_LCD_PANEL_BACKLIGHT_GPIO,
+				GPIOF_OUT_INIT_HIGH, "LCD Backlight");
 	if (r)
-		printk(KERN_ERR "failed to get LCD control GPIOs\n");
-
-}
+		pr_err("failed to get LCD Backlight GPIO\n");
 
-static int sdp3430_panel_enable_lcd(struct omap_dss_device *dssdev)
-{
-	gpio_direction_output(SDP3430_LCD_PANEL_ENABLE_GPIO, 1);
-	gpio_direction_output(SDP3430_LCD_PANEL_BACKLIGHT_GPIO, 1);
-
-	return 0;
-}
-
-static void sdp3430_panel_disable_lcd(struct omap_dss_device *dssdev)
-{
-	gpio_direction_output(SDP3430_LCD_PANEL_ENABLE_GPIO, 0);
-	gpio_direction_output(SDP3430_LCD_PANEL_BACKLIGHT_GPIO, 0);
-}
-
-static int sdp3430_panel_enable_tv(struct omap_dss_device *dssdev)
-{
-	return 0;
-}
-
-static void sdp3430_panel_disable_tv(struct omap_dss_device *dssdev)
-{
 }
 
+static struct panel_sharp_ls037v7dw01_data sdp3430_lcd_data = {
+	.resb_gpio = SDP3430_LCD_PANEL_ENABLE_GPIO,
+	.ini_gpio = -1,
+	.mo_gpio = -1,
+	.lr_gpio = -1,
+	.ud_gpio = -1,
+};
 
 static struct omap_dss_device sdp3430_lcd_device = {
 	.name			= "lcd",
 	.driver_name		= "sharp_ls_panel",
 	.type			= OMAP_DISPLAY_TYPE_DPI,
 	.phy.dpi.data_lines	= 16,
-	.platform_enable	= sdp3430_panel_enable_lcd,
-	.platform_disable	= sdp3430_panel_disable_lcd,
+	.data			= &sdp3430_lcd_data,
 };
 
 static struct tfp410_platform_data dvi_panel = {
@@ -175,8 +160,6 @@ static struct omap_dss_device sdp3430_tv_device = {
 	.driver_name		= "venc",
 	.type			= OMAP_DISPLAY_TYPE_VENC,
 	.phy.venc.type		= OMAP_DSS_VENC_TYPE_SVIDEO,
-	.platform_enable	= sdp3430_panel_enable_tv,
-	.platform_disable	= sdp3430_panel_disable_tv,
 };
 
 
diff --git a/arch/arm/mach-omap2/board-am3517evm.c b/arch/arm/mach-omap2/board-am3517evm.c
index 9fb8590..2b9eb3d 100644
--- a/arch/arm/mach-omap2/board-am3517evm.c
+++ b/arch/arm/mach-omap2/board-am3517evm.c
@@ -35,8 +35,7 @@
 
 #include "common.h"
 #include <video/omapdss.h>
-#include <video/omap-panel-generic-dpi.h>
-#include <video/omap-panel-tfp410.h>
+#include <video/omap-panel-data.h>
 
 #include "am35xx-emac.h"
 #include "mux.h"
@@ -121,63 +120,14 @@ static int __init am3517_evm_i2c_init(void)
 	return 0;
 }
 
-static int lcd_enabled;
-static int dvi_enabled;
-
-#if defined(CONFIG_PANEL_SHARP_LQ043T1DG01) || \
-		defined(CONFIG_PANEL_SHARP_LQ043T1DG01_MODULE)
-static struct gpio am3517_evm_dss_gpios[] __initdata = {
-	/* GPIO 182 = LCD Backlight Power */
-	{ LCD_PANEL_BKLIGHT_PWR, GPIOF_OUT_INIT_HIGH, "lcd_backlight_pwr" },
-	/* GPIO 181 = LCD Panel PWM */
-	{ LCD_PANEL_PWM,	 GPIOF_OUT_INIT_HIGH, "lcd bl enable"	  },
-	/* GPIO 176 = LCD Panel Power enable pin */
-	{ LCD_PANEL_PWR,	 GPIOF_OUT_INIT_HIGH, "dvi enable"	  },
-};
-
-static void __init am3517_evm_display_init(void)
-{
-	int r;
-
-	omap_mux_init_gpio(LCD_PANEL_PWR, OMAP_PIN_INPUT_PULLUP);
-	omap_mux_init_gpio(LCD_PANEL_BKLIGHT_PWR, OMAP_PIN_INPUT_PULLDOWN);
-	omap_mux_init_gpio(LCD_PANEL_PWM, OMAP_PIN_INPUT_PULLDOWN);
-
-	r = gpio_request_array(am3517_evm_dss_gpios,
-			       ARRAY_SIZE(am3517_evm_dss_gpios));
-	if (r) {
-		printk(KERN_ERR "failed to get DSS panel control GPIOs\n");
-		return;
-	}
-
-	printk(KERN_INFO "Display initialized successfully\n");
-}
-#else
-static void __init am3517_evm_display_init(void) {}
-#endif
-
-static int am3517_evm_panel_enable_lcd(struct omap_dss_device *dssdev)
-{
-	if (dvi_enabled) {
-		printk(KERN_ERR "cannot enable LCD, DVI is enabled\n");
-		return -EINVAL;
-	}
-	gpio_set_value(LCD_PANEL_PWR, 1);
-	lcd_enabled = 1;
-
-	return 0;
-}
-
-static void am3517_evm_panel_disable_lcd(struct omap_dss_device *dssdev)
-{
-	gpio_set_value(LCD_PANEL_PWR, 0);
-	lcd_enabled = 0;
-}
-
 static struct panel_generic_dpi_data lcd_panel = {
 	.name			= "sharp_lq",
-	.platform_enable	= am3517_evm_panel_enable_lcd,
-	.platform_disable	= am3517_evm_panel_disable_lcd,
+	.num_gpios		= 3,
+	.gpios			= {
+		LCD_PANEL_PWR,
+		LCD_PANEL_BKLIGHT_PWR,
+		LCD_PANEL_PWM,
+	},
 };
 
 static struct omap_dss_device am3517_evm_lcd_device = {
@@ -188,22 +138,11 @@ static struct omap_dss_device am3517_evm_lcd_device = {
 	.phy.dpi.data_lines 	= 16,
 };
 
-static int am3517_evm_panel_enable_tv(struct omap_dss_device *dssdev)
-{
-	return 0;
-}
-
-static void am3517_evm_panel_disable_tv(struct omap_dss_device *dssdev)
-{
-}
-
 static struct omap_dss_device am3517_evm_tv_device = {
 	.type 			= OMAP_DISPLAY_TYPE_VENC,
 	.name 			= "tv",
 	.driver_name		= "venc",
 	.phy.venc.type		= OMAP_DSS_VENC_TYPE_SVIDEO,
-	.platform_enable	= am3517_evm_panel_enable_tv,
-	.platform_disable	= am3517_evm_panel_disable_tv,
 };
 
 static struct tfp410_platform_data dvi_panel = {
@@ -363,8 +302,6 @@ static void __init am3517_evm_init(void)
 	omap_mux_init_gpio(57, OMAP_PIN_OUTPUT);
 	usbhs_init(&usbhs_bdata);
 	am3517_evm_hecc_init(&am3517_evm_hecc_pdata);
-	/* DSS */
-	am3517_evm_display_init();
 
 	/* RTC - S35390A */
 	am3517_evm_rtc_init();
diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c
index af2bb21..710e99d 100644
--- a/arch/arm/mach-omap2/board-cm-t35.c
+++ b/arch/arm/mach-omap2/board-cm-t35.c
@@ -41,8 +41,7 @@
 
 #include <linux/platform_data/mtd-nand-omap2.h>
 #include <video/omapdss.h>
-#include <video/omap-panel-generic-dpi.h>
-#include <video/omap-panel-tfp410.h>
+#include <video/omap-panel-data.h>
 #include <linux/platform_data/spi-omap2-mcspi.h>
 
 #include "common.h"
@@ -191,45 +190,12 @@ static inline void cm_t35_init_nand(void) {}
 #define CM_T35_LCD_BL_GPIO 58
 #define CM_T35_DVI_EN_GPIO 54
 
-static int lcd_enabled;
-static int dvi_enabled;
-
-static int cm_t35_panel_enable_lcd(struct omap_dss_device *dssdev)
-{
-	if (dvi_enabled) {
-		printk(KERN_ERR "cannot enable LCD, DVI is enabled\n");
-		return -EINVAL;
-	}
-
-	gpio_set_value(CM_T35_LCD_EN_GPIO, 1);
-	gpio_set_value(CM_T35_LCD_BL_GPIO, 1);
-
-	lcd_enabled = 1;
-
-	return 0;
-}
-
-static void cm_t35_panel_disable_lcd(struct omap_dss_device *dssdev)
-{
-	lcd_enabled = 0;
-
-	gpio_set_value(CM_T35_LCD_BL_GPIO, 0);
-	gpio_set_value(CM_T35_LCD_EN_GPIO, 0);
-}
-
-static int cm_t35_panel_enable_tv(struct omap_dss_device *dssdev)
-{
-	return 0;
-}
-
-static void cm_t35_panel_disable_tv(struct omap_dss_device *dssdev)
-{
-}
-
 static struct panel_generic_dpi_data lcd_panel = {
 	.name			= "toppoly_tdo35s",
-	.platform_enable	= cm_t35_panel_enable_lcd,
-	.platform_disable	= cm_t35_panel_disable_lcd,
+	.num_gpios		= 1,
+	.gpios			= {
+		CM_T35_LCD_BL_GPIO,
+	},
 };
 
 static struct omap_dss_device cm_t35_lcd_device = {
@@ -258,8 +224,6 @@ static struct omap_dss_device cm_t35_tv_device = {
 	.driver_name		= "venc",
 	.type			= OMAP_DISPLAY_TYPE_VENC,
 	.phy.venc.type		= OMAP_DSS_VENC_TYPE_SVIDEO,
-	.platform_enable	= cm_t35_panel_enable_tv,
-	.platform_disable	= cm_t35_panel_disable_tv,
 };
 
 static struct omap_dss_device *cm_t35_dss_devices[] = {
@@ -293,11 +257,6 @@ static struct spi_board_info cm_t35_lcd_spi_board_info[] __initdata = {
 	},
 };
 
-static struct gpio cm_t35_dss_gpios[] __initdata = {
-	{ CM_T35_LCD_EN_GPIO, GPIOF_OUT_INIT_LOW,  "lcd enable"    },
-	{ CM_T35_LCD_BL_GPIO, GPIOF_OUT_INIT_LOW,  "lcd bl enable" },
-};
-
 static void __init cm_t35_init_display(void)
 {
 	int err;
@@ -305,23 +264,21 @@ static void __init cm_t35_init_display(void)
 	spi_register_board_info(cm_t35_lcd_spi_board_info,
 				ARRAY_SIZE(cm_t35_lcd_spi_board_info));
 
-	err = gpio_request_array(cm_t35_dss_gpios,
-				 ARRAY_SIZE(cm_t35_dss_gpios));
+
+	err = gpio_request_one(CM_T35_LCD_EN_GPIO, GPIOF_OUT_INIT_LOW,
+			"lcd bl enable");
 	if (err) {
-		pr_err("CM-T35: failed to request DSS control GPIOs\n");
+		pr_err("CM-T35: failed to request LCD EN GPIO\n");
 		return;
 	}
 
-	gpio_export(CM_T35_LCD_EN_GPIO, 0);
-	gpio_export(CM_T35_LCD_BL_GPIO, 0);
-
 	msleep(50);
 	gpio_set_value(CM_T35_LCD_EN_GPIO, 1);
 
 	err = omap_display_init(&cm_t35_dss_data);
 	if (err) {
 		pr_err("CM-T35: failed to register DSS device\n");
-		gpio_free_array(cm_t35_dss_gpios, ARRAY_SIZE(cm_t35_dss_gpios));
+		gpio_free(CM_T35_LCD_EN_GPIO);
 	}
 }
 
diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c
index 53056c3..34944cf 100644
--- a/arch/arm/mach-omap2/board-devkit8000.c
+++ b/arch/arm/mach-omap2/board-devkit8000.c
@@ -43,8 +43,7 @@
 #include "gpmc.h"
 #include <linux/platform_data/mtd-nand-omap2.h>
 #include <video/omapdss.h>
-#include <video/omap-panel-generic-dpi.h>
-#include <video/omap-panel-tfp410.h>
+#include <video/omap-panel-data.h>
 
 #include <linux/platform_data/spi-omap2-mcspi.h>
 #include <linux/input/matrix_keypad.h>
@@ -104,19 +103,6 @@ static struct omap2_hsmmc_info mmc[] = {
 	{}	/* Terminator */
 };
 
-static int devkit8000_panel_enable_lcd(struct omap_dss_device *dssdev)
-{
-	if (gpio_is_valid(dssdev->reset_gpio))
-		gpio_set_value_cansleep(dssdev->reset_gpio, 1);
-	return 0;
-}
-
-static void devkit8000_panel_disable_lcd(struct omap_dss_device *dssdev)
-{
-	if (gpio_is_valid(dssdev->reset_gpio))
-		gpio_set_value_cansleep(dssdev->reset_gpio, 0);
-}
-
 static struct regulator_consumer_supply devkit8000_vmmc1_supply[] = {
 	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
 };
@@ -128,8 +114,7 @@ static struct regulator_consumer_supply devkit8000_vio_supply[] = {
 
 static struct panel_generic_dpi_data lcd_panel = {
 	.name			= "innolux_at070tn83",
-	.platform_enable        = devkit8000_panel_enable_lcd,
-	.platform_disable       = devkit8000_panel_disable_lcd,
+	/* gpios filled in code */
 };
 
 static struct omap_dss_device devkit8000_lcd_device = {
@@ -211,8 +196,6 @@ static struct gpio_led gpio_leds[];
 static int devkit8000_twl_gpio_setup(struct device *dev,
 		unsigned gpio, unsigned ngpio)
 {
-	int ret;
-
 	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
 	mmc[0].gpio_cd = gpio + 0;
 	omap_hsmmc_late_init(mmc);
@@ -221,13 +204,8 @@ static int devkit8000_twl_gpio_setup(struct device *dev,
 	gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1;
 
 	/* TWL4030_GPIO_MAX + 0 is "LCD_PWREN" (out, active high) */
-	devkit8000_lcd_device.reset_gpio = gpio + TWL4030_GPIO_MAX + 0;
-	ret = gpio_request_one(devkit8000_lcd_device.reset_gpio,
-			       GPIOF_OUT_INIT_LOW, "LCD_PWREN");
-	if (ret < 0) {
-		devkit8000_lcd_device.reset_gpio = -EINVAL;
-		printk(KERN_ERR "Failed to request GPIO for LCD_PWRN\n");
-	}
+	lcd_panel.num_gpios = 1;
+	lcd_panel.gpios[0] = gpio + TWL4030_GPIO_MAX + 0;
 
 	/* gpio + 7 is "DVI_PD" (out, active low) */
 	dvi_panel.power_down_gpio = gpio + 7;
diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c
index 812c829..0c1bdd7 100644
--- a/arch/arm/mach-omap2/board-h4.c
+++ b/arch/arm/mach-omap2/board-h4.c
@@ -34,7 +34,7 @@
 #include <asm/mach/map.h>
 
 #include <video/omapdss.h>
-#include <video/omap-panel-generic-dpi.h>
+#include <video/omap-panel-data.h>
 
 #include "common.h"
 #include "mux.h"
diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c
index bf92678..e979d48 100644
--- a/arch/arm/mach-omap2/board-igep0020.c
+++ b/arch/arm/mach-omap2/board-igep0020.c
@@ -31,7 +31,7 @@
 #include <asm/mach/arch.h>
 
 #include <video/omapdss.h>
-#include <video/omap-panel-tfp410.h>
+#include <video/omap-panel-data.h>
 #include <linux/platform_data/mtd-onenand-omap2.h>
 
 #include "common.h"
diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c
index b12fe96..d0d17bc 100644
--- a/arch/arm/mach-omap2/board-ldp.c
+++ b/arch/arm/mach-omap2/board-ldp.c
@@ -41,7 +41,7 @@
 #include "gpmc-smsc911x.h"
 
 #include <video/omapdss.h>
-#include <video/omap-panel-generic-dpi.h>
+#include <video/omap-panel-data.h>
 
 #include "board-flash.h"
 #include "mux.h"
@@ -181,34 +181,13 @@ static inline void __init ldp_init_smsc911x(void)
 
 /* LCD */
 
-static int ldp_backlight_gpio;
-static int ldp_lcd_enable_gpio;
-
 #define LCD_PANEL_RESET_GPIO		55
 #define LCD_PANEL_QVGA_GPIO		56
 
-static int ldp_panel_enable_lcd(struct omap_dss_device *dssdev)
-{
-	if (gpio_is_valid(ldp_lcd_enable_gpio))
-		gpio_direction_output(ldp_lcd_enable_gpio, 1);
-	if (gpio_is_valid(ldp_backlight_gpio))
-		gpio_direction_output(ldp_backlight_gpio, 1);
-
-	return 0;
-}
-
-static void ldp_panel_disable_lcd(struct omap_dss_device *dssdev)
-{
-	if (gpio_is_valid(ldp_lcd_enable_gpio))
-		gpio_direction_output(ldp_lcd_enable_gpio, 0);
-	if (gpio_is_valid(ldp_backlight_gpio))
-		gpio_direction_output(ldp_backlight_gpio, 0);
-}
-
 static struct panel_generic_dpi_data ldp_panel_data = {
 	.name			= "nec_nl2432dr22-11b",
-	.platform_enable	= ldp_panel_enable_lcd,
-	.platform_disable	= ldp_panel_disable_lcd,
+	.num_gpios		= 4,
+	/* gpios filled in code */
 };
 
 static struct omap_dss_device ldp_lcd_device = {
@@ -231,41 +210,19 @@ static struct omap_dss_board_info ldp_dss_data = {
 
 static void __init ldp_display_init(void)
 {
-	int r;
-
-	static struct gpio gpios[] __initdata = {
-		{LCD_PANEL_RESET_GPIO, GPIOF_OUT_INIT_HIGH, "LCD RESET"},
-		{LCD_PANEL_QVGA_GPIO, GPIOF_OUT_INIT_HIGH, "LCD QVGA"},
-	};
-
-	r = gpio_request_array(gpios, ARRAY_SIZE(gpios));
-	if (r) {
-		pr_err("Cannot request LCD GPIOs, error %d\n", r);
-		return;
-	}
+	ldp_panel_data.gpios[2] = LCD_PANEL_RESET_GPIO;
+	ldp_panel_data.gpios[3] = LCD_PANEL_QVGA_GPIO;
 
 	omap_display_init(&ldp_dss_data);
 }
 
 static int ldp_twl_gpio_setup(struct device *dev, unsigned gpio, unsigned ngpio)
 {
-	int r;
-
-	struct gpio gpios[] = {
-		{gpio + 7 , GPIOF_OUT_INIT_LOW, "LCD ENABLE"},
-		{gpio + 15, GPIOF_OUT_INIT_LOW, "LCD BACKLIGHT"},
-	};
-
-	r = gpio_request_array(gpios, ARRAY_SIZE(gpios));
-	if (r) {
-		pr_err("Cannot request LCD GPIOs, error %d\n", r);
-		ldp_backlight_gpio = -EINVAL;
-		ldp_lcd_enable_gpio = -EINVAL;
-		return r;
-	}
-
-	ldp_backlight_gpio = gpio + 15;
-	ldp_lcd_enable_gpio = gpio + 7;
+	ldp_panel_data.gpios[0] = gpio + 7;
+	ldp_panel_data.gpio_invert[0] = true;
+
+	ldp_panel_data.gpios[1] = gpio + 15;
+	ldp_panel_data.gpio_invert[1] = true;
 
 	return 0;
 }
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index c3558f9..fff1413 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -43,7 +43,7 @@
 #include <asm/mach/flash.h>
 
 #include <video/omapdss.h>
-#include <video/omap-panel-tfp410.h>
+#include <video/omap-panel-data.h>
 #include <linux/platform_data/mtd-nand-omap2.h>
 
 #include "common.h"
@@ -479,7 +479,7 @@ static int __init beagle_opp_init(void)
 
 	/* Initialize the omap3 opp table if not already created. */
 	r = omap3_opp_init();
-	if (IS_ERR_VALUE(r) && (r != -EEXIST)) {
+	if (r < 0 && (r != -EEXIST)) {
 		pr_err("%s: opp default init failed\n", __func__);
 		return r;
 	}
diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
index 48789e0..5eecc17 100644
--- a/arch/arm/mach-omap2/board-omap3evm.c
+++ b/arch/arm/mach-omap2/board-omap3evm.c
@@ -51,7 +51,7 @@
 #include "common.h"
 #include <linux/platform_data/spi-omap2-mcspi.h>
 #include <video/omapdss.h>
-#include <video/omap-panel-tfp410.h>
+#include <video/omap-panel-data.h>
 
 #include "soc.h"
 #include "mux.h"
@@ -155,61 +155,43 @@ static inline void __init omap3evm_init_smsc911x(void) { return; }
 #define OMAP3EVM_LCD_PANEL_LR		2
 #define OMAP3EVM_LCD_PANEL_UD		3
 #define OMAP3EVM_LCD_PANEL_INI		152
-#define OMAP3EVM_LCD_PANEL_ENVDD	153
 #define OMAP3EVM_LCD_PANEL_QVGA		154
 #define OMAP3EVM_LCD_PANEL_RESB		155
+
+#define OMAP3EVM_LCD_PANEL_ENVDD	153
 #define OMAP3EVM_LCD_PANEL_BKLIGHT_GPIO	210
+
+/*
+ * OMAP3EVM DVI control signals
+ */
 #define OMAP3EVM_DVI_PANEL_EN_GPIO	199
 
-static struct gpio omap3_evm_dss_gpios[] __initdata = {
-	{ OMAP3EVM_LCD_PANEL_RESB,  GPIOF_OUT_INIT_HIGH, "lcd_panel_resb"  },
-	{ OMAP3EVM_LCD_PANEL_INI,   GPIOF_OUT_INIT_HIGH, "lcd_panel_ini"   },
-	{ OMAP3EVM_LCD_PANEL_QVGA,  GPIOF_OUT_INIT_LOW,  "lcd_panel_qvga"  },
-	{ OMAP3EVM_LCD_PANEL_LR,    GPIOF_OUT_INIT_HIGH, "lcd_panel_lr"    },
-	{ OMAP3EVM_LCD_PANEL_UD,    GPIOF_OUT_INIT_HIGH, "lcd_panel_ud"    },
-	{ OMAP3EVM_LCD_PANEL_ENVDD, GPIOF_OUT_INIT_LOW,  "lcd_panel_envdd" },
+static struct panel_sharp_ls037v7dw01_data omap3_evm_lcd_data = {
+	.resb_gpio = OMAP3EVM_LCD_PANEL_RESB,
+	.ini_gpio = OMAP3EVM_LCD_PANEL_INI,
+	.mo_gpio = OMAP3EVM_LCD_PANEL_QVGA,
+	.lr_gpio = OMAP3EVM_LCD_PANEL_LR,
+	.ud_gpio = OMAP3EVM_LCD_PANEL_UD,
 };
 
-static int lcd_enabled;
-static int dvi_enabled;
-
 static void __init omap3_evm_display_init(void)
 {
 	int r;
 
-	r = gpio_request_array(omap3_evm_dss_gpios,
-			       ARRAY_SIZE(omap3_evm_dss_gpios));
+	r = gpio_request_one(OMAP3EVM_LCD_PANEL_ENVDD, GPIOF_OUT_INIT_LOW,
+				"lcd_panel_envdd");
 	if (r)
-		printk(KERN_ERR "failed to get lcd_panel_* gpios\n");
-}
+		pr_err("failed to get lcd_panel_envdd GPIO\n");
 
-static int omap3_evm_enable_lcd(struct omap_dss_device *dssdev)
-{
-	if (dvi_enabled) {
-		printk(KERN_ERR "cannot enable LCD, DVI is enabled\n");
-		return -EINVAL;
-	}
-	gpio_set_value(OMAP3EVM_LCD_PANEL_ENVDD, 0);
+	r = gpio_request_one(OMAP3EVM_LCD_PANEL_BKLIGHT_GPIO,
+				GPIOF_OUT_INIT_LOW, "lcd_panel_bklight");
+	if (r)
+		pr_err("failed to get lcd_panel_bklight GPIO\n");
 
 	if (get_omap3_evm_rev() >= OMAP3EVM_BOARD_GEN_2)
 		gpio_set_value_cansleep(OMAP3EVM_LCD_PANEL_BKLIGHT_GPIO, 0);
 	else
 		gpio_set_value_cansleep(OMAP3EVM_LCD_PANEL_BKLIGHT_GPIO, 1);
-
-	lcd_enabled = 1;
-	return 0;
-}
-
-static void omap3_evm_disable_lcd(struct omap_dss_device *dssdev)
-{
-	gpio_set_value(OMAP3EVM_LCD_PANEL_ENVDD, 1);
-
-	if (get_omap3_evm_rev() >= OMAP3EVM_BOARD_GEN_2)
-		gpio_set_value_cansleep(OMAP3EVM_LCD_PANEL_BKLIGHT_GPIO, 1);
-	else
-		gpio_set_value_cansleep(OMAP3EVM_LCD_PANEL_BKLIGHT_GPIO, 0);
-
-	lcd_enabled = 0;
 }
 
 static struct omap_dss_device omap3_evm_lcd_device = {
@@ -217,26 +199,14 @@ static struct omap_dss_device omap3_evm_lcd_device = {
 	.driver_name		= "sharp_ls_panel",
 	.type			= OMAP_DISPLAY_TYPE_DPI,
 	.phy.dpi.data_lines	= 18,
-	.platform_enable	= omap3_evm_enable_lcd,
-	.platform_disable	= omap3_evm_disable_lcd,
+	.data			= &omap3_evm_lcd_data,
 };
 
-static int omap3_evm_enable_tv(struct omap_dss_device *dssdev)
-{
-	return 0;
-}
-
-static void omap3_evm_disable_tv(struct omap_dss_device *dssdev)
-{
-}
-
 static struct omap_dss_device omap3_evm_tv_device = {
 	.name			= "tv",
 	.driver_name		= "venc",
 	.type			= OMAP_DISPLAY_TYPE_VENC,
 	.phy.venc.type		= OMAP_DSS_VENC_TYPE_SVIDEO,
-	.platform_enable	= omap3_evm_enable_tv,
-	.platform_disable	= omap3_evm_disable_tv,
 };
 
 static struct tfp410_platform_data dvi_panel = {
diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c
index 2bba362..533180f 100644
--- a/arch/arm/mach-omap2/board-omap3pandora.c
+++ b/arch/arm/mach-omap2/board-omap3pandora.c
@@ -44,6 +44,7 @@
 
 #include "common.h"
 #include <video/omapdss.h>
+#include <video/omap-panel-data.h>
 #include <linux/platform_data/mtd-nand-omap2.h>
 
 #include "mux.h"
@@ -230,12 +231,16 @@ static struct twl4030_keypad_data pandora_kp_data = {
 	.rep		= 1,
 };
 
+static struct panel_tpo_td043_data lcd_data = {
+	.nreset_gpio		= 157,
+};
+
 static struct omap_dss_device pandora_lcd_device = {
 	.name			= "lcd",
 	.driver_name		= "tpo_td043mtea1_panel",
 	.type			= OMAP_DISPLAY_TYPE_DPI,
 	.phy.dpi.data_lines	= 24,
-	.reset_gpio		= 157,
+	.data			= &lcd_data,
 };
 
 static struct omap_dss_device pandora_tv_device = {
diff --git a/arch/arm/mach-omap2/board-omap3stalker.c b/arch/arm/mach-omap2/board-omap3stalker.c
index 95c10b3..5e63f07 100644
--- a/arch/arm/mach-omap2/board-omap3stalker.c
+++ b/arch/arm/mach-omap2/board-omap3stalker.c
@@ -44,8 +44,7 @@
 #include "gpmc.h"
 #include <linux/platform_data/mtd-nand-omap2.h>
 #include <video/omapdss.h>
-#include <video/omap-panel-generic-dpi.h>
-#include <video/omap-panel-tfp410.h>
+#include <video/omap-panel-data.h>
 
 #include <linux/platform_data/spi-omap2-mcspi.h>
 
@@ -95,15 +94,6 @@ static void __init omap3_stalker_display_init(void)
 	return;
 }
 
-static int omap3_stalker_enable_tv(struct omap_dss_device *dssdev)
-{
-	return 0;
-}
-
-static void omap3_stalker_disable_tv(struct omap_dss_device *dssdev)
-{
-}
-
 static struct omap_dss_device omap3_stalker_tv_device = {
 	.name			= "tv",
 	.driver_name		= "venc",
@@ -113,8 +103,6 @@ static struct omap_dss_device omap3_stalker_tv_device = {
 #elif defined(CONFIG_OMAP2_VENC_OUT_TYPE_COMPOSITE)
 	.u.venc.type		= OMAP_DSS_VENC_TYPE_COMPOSITE,
 #endif
-	.platform_enable	= omap3_stalker_enable_tv,
-	.platform_disable	= omap3_stalker_disable_tv,
 };
 
 static struct tfp410_platform_data dvi_panel = {
diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
index 86bab51..f790ce5 100644
--- a/arch/arm/mach-omap2/board-overo.c
+++ b/arch/arm/mach-omap2/board-overo.c
@@ -47,8 +47,7 @@
 #include <asm/mach/map.h>
 
 #include <video/omapdss.h>
-#include <video/omap-panel-generic-dpi.h>
-#include <video/omap-panel-tfp410.h>
+#include <video/omap-panel-data.h>
 
 #include "common.h"
 #include "mux.h"
@@ -146,28 +145,9 @@ static inline void __init overo_init_smsc911x(void) { return; }
 #endif
 
 /* DSS */
-static int lcd_enabled;
-static int dvi_enabled;
-
 #define OVERO_GPIO_LCD_EN 144
 #define OVERO_GPIO_LCD_BL 145
 
-static struct gpio overo_dss_gpios[] __initdata = {
-	{ OVERO_GPIO_LCD_EN, GPIOF_OUT_INIT_HIGH, "OVERO_GPIO_LCD_EN" },
-	{ OVERO_GPIO_LCD_BL, GPIOF_OUT_INIT_HIGH, "OVERO_GPIO_LCD_BL" },
-};
-
-static void __init overo_display_init(void)
-{
-	if (gpio_request_array(overo_dss_gpios, ARRAY_SIZE(overo_dss_gpios))) {
-		printk(KERN_ERR "could not obtain DSS control GPIOs\n");
-		return;
-	}
-
-	gpio_export(OVERO_GPIO_LCD_EN, 0);
-	gpio_export(OVERO_GPIO_LCD_BL, 0);
-}
-
 static struct tfp410_platform_data dvi_panel = {
 	.i2c_bus_num		= 3,
 	.power_down_gpio	= -1,
@@ -188,30 +168,13 @@ static struct omap_dss_device overo_tv_device = {
 	.phy.venc.type = OMAP_DSS_VENC_TYPE_SVIDEO,
 };
 
-static int overo_panel_enable_lcd(struct omap_dss_device *dssdev)
-{
-	if (dvi_enabled) {
-		printk(KERN_ERR "cannot enable LCD, DVI is enabled\n");
-		return -EINVAL;
-	}
-
-	gpio_set_value(OVERO_GPIO_LCD_EN, 1);
-	gpio_set_value(OVERO_GPIO_LCD_BL, 1);
-	lcd_enabled = 1;
-	return 0;
-}
-
-static void overo_panel_disable_lcd(struct omap_dss_device *dssdev)
-{
-	gpio_set_value(OVERO_GPIO_LCD_EN, 0);
-	gpio_set_value(OVERO_GPIO_LCD_BL, 0);
-	lcd_enabled = 0;
-}
-
 static struct panel_generic_dpi_data lcd43_panel = {
 	.name			= "samsung_lte430wq_f0c",
-	.platform_enable	= overo_panel_enable_lcd,
-	.platform_disable	= overo_panel_disable_lcd,
+	.num_gpios		= 2,
+	.gpios			= {
+		OVERO_GPIO_LCD_EN,
+		OVERO_GPIO_LCD_BL
+	},
 };
 
 static struct omap_dss_device overo_lcd43_device = {
@@ -224,13 +187,20 @@ static struct omap_dss_device overo_lcd43_device = {
 
 #if defined(CONFIG_PANEL_LGPHILIPS_LB035Q02) || \
 	defined(CONFIG_PANEL_LGPHILIPS_LB035Q02_MODULE)
+static struct panel_generic_dpi_data lcd35_panel = {
+	.num_gpios		= 2,
+	.gpios			= {
+		OVERO_GPIO_LCD_EN,
+		OVERO_GPIO_LCD_BL
+	},
+};
+
 static struct omap_dss_device overo_lcd35_device = {
 	.type			= OMAP_DISPLAY_TYPE_DPI,
 	.name			= "lcd35",
 	.driver_name		= "lgphilips_lb035q02_panel",
 	.phy.dpi.data_lines	= 24,
-	.platform_enable	= overo_panel_enable_lcd,
-	.platform_disable	= overo_panel_disable_lcd,
+	.data			= &lcd35_panel,
 };
 #endif
 
@@ -505,7 +475,6 @@ static void __init overo_init(void)
 	usbhs_init(&usbhs_bdata);
 	overo_spi_init();
 	overo_init_smsc911x();
-	overo_display_init();
 	overo_init_led();
 	overo_init_keys();
 	omap_twl4030_audio_init("overo", NULL);
diff --git a/arch/arm/mach-omap2/board-rx51-video.c b/arch/arm/mach-omap2/board-rx51-video.c
index eb66726..bd74f9f 100644
--- a/arch/arm/mach-omap2/board-rx51-video.c
+++ b/arch/arm/mach-omap2/board-rx51-video.c
@@ -16,6 +16,8 @@
 #include <linux/mm.h>
 #include <asm/mach-types.h>
 #include <video/omapdss.h>
+#include <video/omap-panel-data.h>
+
 #include <linux/platform_data/spi-omap2-mcspi.h>
 
 #include "soc.h"
@@ -27,25 +29,16 @@
 
 #if defined(CONFIG_FB_OMAP2) || defined(CONFIG_FB_OMAP2_MODULE)
 
-static int rx51_lcd_enable(struct omap_dss_device *dssdev)
-{
-	gpio_set_value(dssdev->reset_gpio, 1);
-	return 0;
-}
-
-static void rx51_lcd_disable(struct omap_dss_device *dssdev)
-{
-	gpio_set_value(dssdev->reset_gpio, 0);
-}
+static struct panel_acx565akm_data lcd_data = {
+	.reset_gpio	= RX51_LCD_RESET_GPIO,
+};
 
 static struct omap_dss_device rx51_lcd_device = {
 	.name			= "lcd",
 	.driver_name		= "panel-acx565akm",
 	.type			= OMAP_DISPLAY_TYPE_SDI,
 	.phy.sdi.datapairs	= 2,
-	.reset_gpio		= RX51_LCD_RESET_GPIO,
-	.platform_enable	= rx51_lcd_enable,
-	.platform_disable	= rx51_lcd_disable,
+	.data			= &lcd_data,
 };
 
 static struct omap_dss_device  rx51_tv_device = {
@@ -76,13 +69,8 @@ static int __init rx51_video_init(void)
 		return 0;
 	}
 
-	if (gpio_request_one(RX51_LCD_RESET_GPIO, GPIOF_OUT_INIT_HIGH,
-			     "LCD ACX565AKM reset")) {
-		pr_err("%s failed to get LCD Reset GPIO\n", __func__);
-		return 0;
-	}
-
 	omap_display_init(&rx51_dss_board_info);
+
 	return 0;
 }
 
diff --git a/arch/arm/mach-omap2/board-zoom-display.c b/arch/arm/mach-omap2/board-zoom-display.c
index 8cef477..c2a079c 100644
--- a/arch/arm/mach-omap2/board-zoom-display.c
+++ b/arch/arm/mach-omap2/board-zoom-display.c
@@ -12,12 +12,12 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
-#include <linux/i2c/twl.h>
 #include <linux/spi/spi.h>
 #include <linux/platform_data/spi-omap2-mcspi.h>
 #include <video/omapdss.h>
-#include "board-zoom.h"
+#include <video/omap-panel-data.h>
 
+#include "board-zoom.h"
 #include "soc.h"
 #include "common.h"
 
@@ -25,92 +25,17 @@
 #define LCD_PANEL_RESET_GPIO_PILOT	55
 #define LCD_PANEL_QVGA_GPIO		56
 
-static struct gpio zoom_lcd_gpios[] __initdata = {
-	{ -EINVAL,		GPIOF_OUT_INIT_HIGH, "lcd reset" },
-	{ LCD_PANEL_QVGA_GPIO,	GPIOF_OUT_INIT_HIGH, "lcd qvga"	 },
+static struct panel_nec_nl8048_data zoom_lcd_data = {
+	/* res_gpio filled in code */
+	.qvga_gpio = LCD_PANEL_QVGA_GPIO,
 };
 
-static void __init zoom_lcd_panel_init(void)
-{
-	zoom_lcd_gpios[0].gpio = (omap_rev() > OMAP3430_REV_ES3_0) ?
-			LCD_PANEL_RESET_GPIO_PROD :
-			LCD_PANEL_RESET_GPIO_PILOT;
-
-	if (gpio_request_array(zoom_lcd_gpios, ARRAY_SIZE(zoom_lcd_gpios)))
-		pr_err("%s: Failed to get LCD GPIOs.\n", __func__);
-}
-
-static int zoom_panel_enable_lcd(struct omap_dss_device *dssdev)
-{
-	return 0;
-}
-
-static void zoom_panel_disable_lcd(struct omap_dss_device *dssdev)
-{
-}
-
-/* Register offsets in TWL4030_MODULE_INTBR */
-#define TWL_INTBR_PMBR1	0xD
-#define TWL_INTBR_GPBR1	0xC
-
-/* Register offsets in TWL_MODULE_PWM */
-#define TWL_LED_PWMON	0x3
-#define TWL_LED_PWMOFF	0x4
-
-static int zoom_set_bl_intensity(struct omap_dss_device *dssdev, int level)
-{
-#ifdef CONFIG_TWL4030_CORE
-	unsigned char c;
-	u8 mux_pwm, enb_pwm;
-
-	if (level > 100)
-		return -1;
-
-	twl_i2c_read_u8(TWL4030_MODULE_INTBR, &mux_pwm, TWL_INTBR_PMBR1);
-	twl_i2c_read_u8(TWL4030_MODULE_INTBR, &enb_pwm, TWL_INTBR_GPBR1);
-
-	if (level == 0) {
-		/* disable pwm1 output and clock */
-		enb_pwm = enb_pwm & 0xF5;
-		/* change pwm1 pin to gpio pin */
-		mux_pwm = mux_pwm & 0xCF;
-		twl_i2c_write_u8(TWL4030_MODULE_INTBR,
-					enb_pwm, TWL_INTBR_GPBR1);
-		twl_i2c_write_u8(TWL4030_MODULE_INTBR,
-					mux_pwm, TWL_INTBR_PMBR1);
-		return 0;
-	}
-
-	if (!((enb_pwm & 0xA) && (mux_pwm & 0x30))) {
-		/* change gpio pin to pwm1 pin */
-		mux_pwm = mux_pwm | 0x30;
-		/* enable pwm1 output and clock*/
-		enb_pwm = enb_pwm | 0x0A;
-		twl_i2c_write_u8(TWL4030_MODULE_INTBR,
-					mux_pwm, TWL_INTBR_PMBR1);
-		twl_i2c_write_u8(TWL4030_MODULE_INTBR,
-					enb_pwm, TWL_INTBR_GPBR1);
-	}
-
-	c = ((50 * (100 - level)) / 100) + 1;
-	twl_i2c_write_u8(TWL_MODULE_PWM, 0x7F, TWL_LED_PWMOFF);
-	twl_i2c_write_u8(TWL_MODULE_PWM, c, TWL_LED_PWMON);
-#else
-	pr_warn("Backlight not enabled\n");
-#endif
-
-	return 0;
-}
-
 static struct omap_dss_device zoom_lcd_device = {
 	.name			= "lcd",
 	.driver_name		= "NEC_8048_panel",
 	.type			= OMAP_DISPLAY_TYPE_DPI,
 	.phy.dpi.data_lines	= 24,
-	.platform_enable	= zoom_panel_enable_lcd,
-	.platform_disable	= zoom_panel_disable_lcd,
-	.max_backlight_level	= 100,
-	.set_backlight		= zoom_set_bl_intensity,
+	.data			= &zoom_lcd_data,
 };
 
 static struct omap_dss_device *zoom_dss_devices[] = {
@@ -123,6 +48,13 @@ static struct omap_dss_board_info zoom_dss_data = {
 	.default_device		= &zoom_lcd_device,
 };
 
+static void __init zoom_lcd_panel_init(void)
+{
+	zoom_lcd_data.res_gpio = (omap_rev() > OMAP3430_REV_ES3_0) ?
+			LCD_PANEL_RESET_GPIO_PROD :
+			LCD_PANEL_RESET_GPIO_PILOT;
+}
+
 static struct omap2_mcspi_device_config dss_lcd_mcspi_config = {
 	.turbo_mode		= 1,
 };
diff --git a/arch/arm/mach-omap2/board-zoom-peripherals.c b/arch/arm/mach-omap2/board-zoom-peripherals.c
index cdc0c10..a90375d 100644
--- a/arch/arm/mach-omap2/board-zoom-peripherals.c
+++ b/arch/arm/mach-omap2/board-zoom-peripherals.c
@@ -22,6 +22,9 @@
 #include <linux/platform_data/gpio-omap.h>
 #include <linux/platform_data/omap-twl4030.h>
 #include <linux/usb/phy.h>
+#include <linux/pwm.h>
+#include <linux/leds_pwm.h>
+#include <linux/pwm_backlight.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -193,6 +196,53 @@ static struct platform_device omap_vwlan_device = {
 	},
 };
 
+static struct pwm_lookup zoom_pwm_lookup[] = {
+	PWM_LOOKUP("twl-pwm", 0, "leds_pwm", "zoom::keypad"),
+	PWM_LOOKUP("twl-pwm", 1, "pwm-backlight", "backlight"),
+};
+
+static struct led_pwm zoom_pwm_leds[] = {
+	{
+		.name		= "zoom::keypad",
+		.max_brightness	= 127,
+		.pwm_period_ns	= 7812500,
+	},
+};
+
+static struct led_pwm_platform_data zoom_pwm_data = {
+	.num_leds	= ARRAY_SIZE(zoom_pwm_leds),
+	.leds		= zoom_pwm_leds,
+};
+
+static struct platform_device zoom_leds_pwm = {
+	.name	= "leds_pwm",
+	.id	= -1,
+	.dev	= {
+		.platform_data = &zoom_pwm_data,
+	},
+};
+
+static struct platform_pwm_backlight_data zoom_backlight_data = {
+	.pwm_id = 1,
+	.max_brightness = 127,
+	.dft_brightness = 127,
+	.pwm_period_ns = 7812500,
+};
+
+static struct platform_device zoom_backlight_pwm = {
+	.name   = "pwm-backlight",
+	.id     = -1,
+	.dev    = {
+		.platform_data = &zoom_backlight_data,
+	},
+};
+
+static struct platform_device *zoom_devices[] __initdata = {
+	&omap_vwlan_device,
+	&zoom_leds_pwm,
+	&zoom_backlight_pwm,
+};
+
 static struct wl12xx_platform_data omap_zoom_wlan_data __initdata = {
 	.board_ref_clock = WL12XX_REFCLOCK_26, /* 26 MHz */
 };
@@ -301,7 +351,8 @@ void __init zoom_peripherals_init(void)
 
 	omap_hsmmc_init(mmc);
 	omap_i2c_init();
-	platform_device_register(&omap_vwlan_device);
+	pwm_add_table(zoom_pwm_lookup, ARRAY_SIZE(zoom_pwm_lookup));
+	platform_add_devices(zoom_devices, ARRAY_SIZE(zoom_devices));
 	usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
 	usb_musb_init(NULL);
 	enable_board_wakeup_source();
diff --git a/arch/arm/mach-omap2/cclock44xx_data.c b/arch/arm/mach-omap2/cclock44xx_data.c
index 3d58f33..0c6834a 100644
--- a/arch/arm/mach-omap2/cclock44xx_data.c
+++ b/arch/arm/mach-omap2/cclock44xx_data.c
@@ -52,6 +52,13 @@
  */
 #define OMAP4_DPLL_ABE_DEFFREQ				98304000
 
+/*
+ * OMAP4 USB DPLL default frequency. In OMAP4430 TRM version V, section
+ * "3.6.3.9.5 DPLL_USB Preferred Settings" shows that the preferred
+ * locked frequency for the USB DPLL is 960MHz.
+ */
+#define OMAP4_DPLL_USB_DEFFREQ				960000000
+
 /* Root clocks */
 
 DEFINE_CLK_FIXED_RATE(extalt_clkin_ck, CLK_IS_ROOT, 59000000, 0x0);
@@ -1011,6 +1018,10 @@ DEFINE_CLK_OMAP_MUX(hsmmc2_fclk, "l3_init_clkdm", hsmmc1_fclk_sel,
 		    OMAP4430_CM_L3INIT_MMC2_CLKCTRL, OMAP4430_CLKSEL_MASK,
 		    hsmmc1_fclk_parents, func_dmic_abe_gfclk_ops);
 
+DEFINE_CLK_GATE(ocp2scp_usb_phy_phy_48m, "func_48m_fclk", &func_48m_fclk, 0x0,
+		OMAP4430_CM_L3INIT_USBPHYOCP2SCP_CLKCTRL,
+		OMAP4430_OPTFCLKEN_PHY_48M_SHIFT, 0x0, NULL);
+
 DEFINE_CLK_GATE(sha2md5_fck, "l3_div_ck", &l3_div_ck, 0x0,
 		OMAP4430_CM_L4SEC_SHA2MD51_CLKCTRL,
 		OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
@@ -1538,6 +1549,7 @@ static struct omap_clk omap44xx_clks[] = {
 	CLK(NULL,	"per_mcbsp4_gfclk",			&per_mcbsp4_gfclk,	CK_443X),
 	CLK(NULL,	"hsmmc1_fclk",			&hsmmc1_fclk,	CK_443X),
 	CLK(NULL,	"hsmmc2_fclk",			&hsmmc2_fclk,	CK_443X),
+	CLK(NULL,	"ocp2scp_usb_phy_phy_48m",	&ocp2scp_usb_phy_phy_48m,	CK_443X),
 	CLK(NULL,	"sha2md5_fck",			&sha2md5_fck,	CK_443X),
 	CLK(NULL,	"slimbus1_fclk_1",		&slimbus1_fclk_1,	CK_443X),
 	CLK(NULL,	"slimbus1_fclk_0",		&slimbus1_fclk_0,	CK_443X),
@@ -1705,5 +1717,13 @@ int __init omap4xxx_clk_init(void)
 	if (rc)
 		pr_err("%s: failed to configure ABE DPLL!\n", __func__);
 
+	/*
+	 * Lock USB DPLL on OMAP4 devices so that the L3INIT power
+	 * domain can transition to retention state when not in use.
+	 */
+	rc = clk_set_rate(&dpll_usb_ck, OMAP4_DPLL_USB_DEFFREQ);
+	if (rc)
+		pr_err("%s: failed to configure USB DPLL!\n", __func__);
+
 	return 0;
 }
diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
index e4ec3a6..2191f25 100644
--- a/arch/arm/mach-omap2/clock.c
+++ b/arch/arm/mach-omap2/clock.c
@@ -596,7 +596,7 @@ int __init omap2_clk_switch_mpurate_at_boot(const char *mpurate_ck_name)
 		return -ENOENT;
 
 	r = clk_set_rate(mpurate_ck, mpurate);
-	if (IS_ERR_VALUE(r)) {
+	if (r < 0) {
 		WARN(1, "clock: %s: unable to set MPU rate to %d: %d\n",
 		     mpurate_ck_name, mpurate, r);
 		clk_put(mpurate_ck);
diff --git a/arch/arm/mach-omap2/common.h b/arch/arm/mach-omap2/common.h
index 40f4a03..d6ba13e 100644
--- a/arch/arm/mach-omap2/common.h
+++ b/arch/arm/mach-omap2/common.h
@@ -293,5 +293,8 @@ extern void omap_reserve(void);
 struct omap_hwmod;
 extern int omap_dss_reset(struct omap_hwmod *);
 
+/* SoC specific clock initializer */
+extern int (*omap_clk_init)(void);
+
 #endif /* __ASSEMBLER__ */
 #endif /* __ARCH_ARM_MACH_OMAP2PLUS_COMMON_H */
diff --git a/arch/arm/mach-omap2/cpuidle44xx.c b/arch/arm/mach-omap2/cpuidle44xx.c
index d639aef..f4b1b23 100644
--- a/arch/arm/mach-omap2/cpuidle44xx.c
+++ b/arch/arm/mach-omap2/cpuidle44xx.c
@@ -14,7 +14,6 @@
 #include <linux/cpuidle.h>
 #include <linux/cpu_pm.h>
 #include <linux/export.h>
-#include <linux/clockchips.h>
 
 #include <asm/proc-fns.h>
 
@@ -82,7 +81,6 @@ static int omap4_enter_idle_coupled(struct cpuidle_device *dev,
 			int index)
 {
 	struct omap4_idle_statedata *cx = &omap4_idle_data[index];
-	int cpu_id = smp_processor_id();
 
 	local_fiq_disable();
 
@@ -109,8 +107,6 @@ static int omap4_enter_idle_coupled(struct cpuidle_device *dev,
 		}
 	}
 
-	clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu_id);
-
 	/*
 	 * Call idle CPU PM enter notifier chain so that
 	 * VFP and per CPU interrupt context is saved.
@@ -152,8 +148,6 @@ static int omap4_enter_idle_coupled(struct cpuidle_device *dev,
 	if (omap4_mpuss_read_prev_context_state())
 		cpu_cluster_pm_exit();
 
-	clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu_id);
-
 fail:
 	cpuidle_coupled_parallel_barrier(dev, &abort_barrier);
 	cpu_done[dev->cpu] = false;
@@ -163,16 +157,6 @@ fail:
 	return index;
 }
 
-/*
- * For each cpu, setup the broadcast timer because local timers
- * stops for the states above C1.
- */
-static void omap_setup_broadcast_timer(void *arg)
-{
-	int cpu = smp_processor_id();
-	clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ON, &cpu);
-}
-
 static DEFINE_PER_CPU(struct cpuidle_device, omap4_idle_dev);
 
 static struct cpuidle_driver omap4_idle_driver = {
@@ -193,7 +177,8 @@ static struct cpuidle_driver omap4_idle_driver = {
 			/* C2 - CPU0 OFF + CPU1 OFF + MPU CSWR */
 			.exit_latency = 328 + 440,
 			.target_residency = 960,
-			.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_COUPLED,
+			.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_COUPLED |
+			         CPUIDLE_FLAG_TIMER_STOP,
 			.enter = omap4_enter_idle_coupled,
 			.name = "C2",
 			.desc = "MPUSS CSWR",
@@ -202,7 +187,8 @@ static struct cpuidle_driver omap4_idle_driver = {
 			/* C3 - CPU0 OFF + CPU1 OFF + MPU OSWR */
 			.exit_latency = 460 + 518,
 			.target_residency = 1100,
-			.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_COUPLED,
+			.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_COUPLED |
+			         CPUIDLE_FLAG_TIMER_STOP,
 			.enter = omap4_enter_idle_coupled,
 			.name = "C3",
 			.desc = "MPUSS OSWR",
@@ -236,9 +222,6 @@ int __init omap4_idle_init(void)
 	if (!cpu_clkdm[0] || !cpu_clkdm[1])
 		return -ENODEV;
 
-	/* Configure the broadcast timer on each cpu */
-	on_each_cpu(omap_setup_broadcast_timer, NULL, 1);
-
 	for_each_cpu(cpu_id, cpu_online_mask) {
 		dev = &per_cpu(omap4_idle_dev, cpu_id);
 		dev->cpu = cpu_id;
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
index 1ec7f05..72ba57c 100644
--- a/arch/arm/mach-omap2/devices.c
+++ b/arch/arm/mach-omap2/devices.c
@@ -20,6 +20,7 @@
 #include <linux/pinctrl/machine.h>
 #include <linux/platform_data/omap4-keypad.h>
 #include <linux/platform_data/omap_ocp2scp.h>
+#include <linux/platform_data/mailbox-omap.h>
 #include <linux/usb/omap_control_usb.h>
 
 #include <asm/mach-types.h>
@@ -327,25 +328,31 @@ int __init omap4_keyboard_init(struct omap4_keypad_platform_data
 	return 0;
 }
 
-#if defined(CONFIG_OMAP_MBOX_FWK) || defined(CONFIG_OMAP_MBOX_FWK_MODULE)
+#if defined(CONFIG_OMAP2PLUS_MBOX) || defined(CONFIG_OMAP2PLUS_MBOX_MODULE)
 static inline void __init omap_init_mbox(void)
 {
 	struct omap_hwmod *oh;
 	struct platform_device *pdev;
+	struct omap_mbox_pdata *pdata;
 
 	oh = omap_hwmod_lookup("mailbox");
 	if (!oh) {
 		pr_err("%s: unable to find hwmod\n", __func__);
 		return;
 	}
+	if (!oh->dev_attr) {
+		pr_err("%s: hwmod doesn't have valid attrs\n", __func__);
+		return;
+	}
 
-	pdev = omap_device_build("omap-mailbox", -1, oh, NULL, 0);
+	pdata = (struct omap_mbox_pdata *)oh->dev_attr;
+	pdev = omap_device_build("omap-mailbox", -1, oh, pdata, sizeof(*pdata));
 	WARN(IS_ERR(pdev), "%s: could not build device, err %ld\n",
 						__func__, PTR_ERR(pdev));
 }
 #else
 static inline void omap_init_mbox(void) { }
-#endif /* CONFIG_OMAP_MBOX_FWK */
+#endif /* CONFIG_OMAP2PLUS_MBOX */
 
 static inline void omap_init_sti(void) {}
 
diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c
index dab9fc0..49fd0d5 100644
--- a/arch/arm/mach-omap2/dma.c
+++ b/arch/arm/mach-omap2/dma.c
@@ -28,6 +28,7 @@
 #include <linux/init.h>
 #include <linux/device.h>
 #include <linux/dma-mapping.h>
+#include <linux/of.h>
 #include <linux/omap-dma.h>
 
 #include "soc.h"
@@ -304,6 +305,9 @@ static int __init omap2_system_dma_init(void)
 	if (res)
 		return res;
 
+	if (of_have_populated_dt())
+		return res;
+
 	pdev = platform_device_register_full(&omap_dma_dev_info);
 	if (IS_ERR(pdev))
 		return PTR_ERR(pdev);
diff --git a/arch/arm/mach-omap2/dss-common.c b/arch/arm/mach-omap2/dss-common.c
index 4be5cfc..393aeef 100644
--- a/arch/arm/mach-omap2/dss-common.c
+++ b/arch/arm/mach-omap2/dss-common.c
@@ -27,9 +27,7 @@
 #include <linux/gpio.h>
 
 #include <video/omapdss.h>
-#include <video/omap-panel-tfp410.h>
-#include <video/omap-panel-nokia-dsi.h>
-#include <video/omap-panel-picodlp.h>
+#include <video/omap-panel-data.h>
 
 #include "soc.h"
 #include "dss-common.h"
@@ -54,7 +52,6 @@ static struct omap_dss_device omap4_panda_dvi_device = {
 	.driver_name		= "tfp410",
 	.data			= &omap4_dvi_panel,
 	.phy.dpi.data_lines	= 24,
-	.reset_gpio		= PANDA_DVI_TFP410_POWER_DOWN_GPIO,
 	.channel		= OMAP_DSS_CHANNEL_LCD2,
 };
 
@@ -179,45 +176,12 @@ static struct picodlp_panel_data sdp4430_picodlp_pdata = {
 	.pwrgood_gpio		= 45,
 };
 
-static void sdp4430_picodlp_init(void)
-{
-	int r;
-	const struct gpio picodlp_gpios[] = {
-		{DLP_POWER_ON_GPIO, GPIOF_OUT_INIT_LOW,
-			"DLP POWER ON"},
-		{sdp4430_picodlp_pdata.emu_done_gpio, GPIOF_IN,
-			"DLP EMU DONE"},
-		{sdp4430_picodlp_pdata.pwrgood_gpio, GPIOF_OUT_INIT_LOW,
-			"DLP PWRGOOD"},
-	};
-
-	r = gpio_request_array(picodlp_gpios, ARRAY_SIZE(picodlp_gpios));
-	if (r)
-		pr_err("Cannot request PicoDLP GPIOs, error %d\n", r);
-}
-
-static int sdp4430_panel_enable_picodlp(struct omap_dss_device *dssdev)
-{
-	gpio_set_value(DISPLAY_SEL_GPIO, 0);
-	gpio_set_value(DLP_POWER_ON_GPIO, 1);
-
-	return 0;
-}
-
-static void sdp4430_panel_disable_picodlp(struct omap_dss_device *dssdev)
-{
-	gpio_set_value(DLP_POWER_ON_GPIO, 0);
-	gpio_set_value(DISPLAY_SEL_GPIO, 1);
-}
-
 static struct omap_dss_device sdp4430_picodlp_device = {
 	.name			= "picodlp",
 	.driver_name		= "picodlp_panel",
 	.type			= OMAP_DISPLAY_TYPE_DPI,
 	.phy.dpi.data_lines	= 24,
 	.channel		= OMAP_DSS_CHANNEL_LCD2,
-	.platform_enable	= sdp4430_panel_enable_picodlp,
-	.platform_disable	= sdp4430_panel_disable_picodlp,
 	.data			= &sdp4430_picodlp_pdata,
 };
 
@@ -234,17 +198,26 @@ static struct omap_dss_board_info sdp4430_dss_data = {
 	.default_device	= &sdp4430_lcd_device,
 };
 
+/*
+ * we select LCD2 by default (instead of Pico DLP) by setting DISPLAY_SEL_GPIO.
+ * Setting DLP_POWER_ON gpio enables the VDLP_2V5 VDLP_1V8 and VDLP_1V0 rails
+ * used by picodlp on the 4430sdp platform. Keep this gpio disabled as LCD2 is
+ * selected by default
+ */
 void __init omap_4430sdp_display_init(void)
 {
 	int r;
 
-	/* Enable LCD2 by default (instead of Pico DLP) */
 	r = gpio_request_one(DISPLAY_SEL_GPIO, GPIOF_OUT_INIT_HIGH,
 			"display_sel");
 	if (r)
 		pr_err("%s: Could not get display_sel GPIO\n", __func__);
 
-	sdp4430_picodlp_init();
+	r = gpio_request_one(DLP_POWER_ON_GPIO, GPIOF_OUT_INIT_LOW,
+		"DLP POWER ON");
+	if (r)
+		pr_err("%s: Could not get DLP POWER ON GPIO\n", __func__);
+
 	omap_display_init(&sdp4430_dss_data);
 	/*
 	 * OMAP4460SDP/Blaze and OMAP4430 ES2.3 SDP/Blaze boards and
@@ -264,12 +237,15 @@ void __init omap_4430sdp_display_init_of(void)
 {
 	int r;
 
-	/* Enable LCD2 by default (instead of Pico DLP) */
 	r = gpio_request_one(DISPLAY_SEL_GPIO, GPIOF_OUT_INIT_HIGH,
 			"display_sel");
 	if (r)
 		pr_err("%s: Could not get display_sel GPIO\n", __func__);
 
-	sdp4430_picodlp_init();
+	r = gpio_request_one(DLP_POWER_ON_GPIO, GPIOF_OUT_INIT_LOW,
+		"DLP POWER ON");
+	if (r)
+		pr_err("%s: Could not get DLP POWER ON GPIO\n", __func__);
+
 	omap_display_init(&sdp4430_dss_data);
 }
diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c
index fadd8743..0d75889 100644
--- a/arch/arm/mach-omap2/gpmc-onenand.c
+++ b/arch/arm/mach-omap2/gpmc-onenand.c
@@ -303,7 +303,7 @@ static int omap2_onenand_setup_async(void __iomem *onenand_base)
 	t = omap2_onenand_calc_async_timings();
 
 	ret = gpmc_set_async_mode(gpmc_onenand_data->cs, &t);
-	if (IS_ERR_VALUE(ret))
+	if (ret < 0)
 		return ret;
 
 	omap2_onenand_set_async_mode(onenand_base);
@@ -325,7 +325,7 @@ static int omap2_onenand_setup_sync(void __iomem *onenand_base, int *freq_ptr)
 	t = omap2_onenand_calc_sync_timings(gpmc_onenand_data, freq);
 
 	ret = gpmc_set_sync_mode(gpmc_onenand_data->cs, &t);
-	if (IS_ERR_VALUE(ret))
+	if (ret < 0)
 		return ret;
 
 	set_onenand_cfg(onenand_base);
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index 410e1ba..6de3173 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -716,7 +716,7 @@ static int gpmc_setup_irq(void)
 		return -EINVAL;
 
 	gpmc_irq_start = irq_alloc_descs(-1, 0, GPMC_NR_IRQ, 0);
-	if (IS_ERR_VALUE(gpmc_irq_start)) {
+	if (gpmc_irq_start < 0) {
 		pr_err("irq_alloc_descs failed\n");
 		return gpmc_irq_start;
 	}
@@ -801,7 +801,7 @@ static int gpmc_mem_init(void)
 			continue;
 		gpmc_cs_get_memconf(cs, &base, &size);
 		rc = gpmc_cs_insert_mem(cs, base, size);
-		if (IS_ERR_VALUE(rc)) {
+		if (rc < 0) {
 			while (--cs >= 0)
 				if (gpmc_cs_mem_enabled(cs))
 					gpmc_cs_delete_mem(cs);
@@ -1370,14 +1370,14 @@ static int gpmc_probe(struct platform_device *pdev)
 		 GPMC_REVISION_MINOR(l));
 
 	rc = gpmc_mem_init();
-	if (IS_ERR_VALUE(rc)) {
+	if (rc < 0) {
 		clk_disable_unprepare(gpmc_l3_clk);
 		clk_put(gpmc_l3_clk);
 		dev_err(gpmc_dev, "failed to reserve memory\n");
 		return rc;
 	}
 
-	if (IS_ERR_VALUE(gpmc_setup_irq()))
+	if (gpmc_setup_irq() < 0)
 		dev_warn(gpmc_dev, "gpmc_setup_irq failed\n");
 
 	/* Now the GPMC is initialised, unreserve the chip-selects */
diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c
index 8a68f1e..577298e 100644
--- a/arch/arm/mach-omap2/id.c
+++ b/arch/arm/mach-omap2/id.c
@@ -300,7 +300,7 @@ void __init omap3xxx_check_revision(void)
 	 * If the processor type is Cortex-A8 and the revision is 0x0
 	 * it means its Cortex r0p0 which is 3430 ES1.0.
 	 */
-	cpuid = read_cpuid(CPUID_ID);
+	cpuid = read_cpuid_id();
 	if ((((cpuid >> 4) & 0xfff) == 0xc08) && ((cpuid & 0xf) == 0x0)) {
 		omap_revision = OMAP3430_REV_ES1_0;
 		cpu_rev = "1.0";
@@ -460,7 +460,7 @@ void __init omap4xxx_check_revision(void)
 	 * Use ARM register to detect the correct ES version
 	 */
 	if (!rev && (hawkeye != 0xb94e) && (hawkeye != 0xb975)) {
-		idcode = read_cpuid(CPUID_ID);
+		idcode = read_cpuid_id();
 		rev = (idcode & 0xf) - 1;
 	}
 
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
index 2c3fdd6..5c445ca 100644
--- a/arch/arm/mach-omap2/io.c
+++ b/arch/arm/mach-omap2/io.c
@@ -55,6 +55,12 @@
 #include "prm44xx.h"
 
 /*
+ * omap_clk_init: points to a function that does the SoC-specific
+ * clock initializations
+ */
+int (*omap_clk_init)(void);
+
+/*
  * The machine specific code may provide the extra mapping besides the
  * default mapping provided here.
  */
@@ -397,7 +403,7 @@ void __init omap2420_init_early(void)
 	omap242x_clockdomains_init();
 	omap2420_hwmod_init();
 	omap_hwmod_init_postsetup();
-	omap2420_clk_init();
+	omap_clk_init = omap2420_clk_init;
 }
 
 void __init omap2420_init_late(void)
@@ -427,7 +433,7 @@ void __init omap2430_init_early(void)
 	omap243x_clockdomains_init();
 	omap2430_hwmod_init();
 	omap_hwmod_init_postsetup();
-	omap2430_clk_init();
+	omap_clk_init = omap2430_clk_init;
 }
 
 void __init omap2430_init_late(void)
@@ -462,7 +468,7 @@ void __init omap3_init_early(void)
 	omap3xxx_clockdomains_init();
 	omap3xxx_hwmod_init();
 	omap_hwmod_init_postsetup();
-	omap3xxx_clk_init();
+	omap_clk_init = omap3xxx_clk_init;
 }
 
 void __init omap3430_init_early(void)
@@ -500,7 +506,7 @@ void __init ti81xx_init_early(void)
 	omap3xxx_clockdomains_init();
 	omap3xxx_hwmod_init();
 	omap_hwmod_init_postsetup();
-	omap3xxx_clk_init();
+	omap_clk_init = omap3xxx_clk_init;
 }
 
 void __init omap3_init_late(void)
@@ -568,7 +574,7 @@ void __init am33xx_init_early(void)
 	am33xx_clockdomains_init();
 	am33xx_hwmod_init();
 	omap_hwmod_init_postsetup();
-	am33xx_clk_init();
+	omap_clk_init = am33xx_clk_init;
 }
 #endif
 
@@ -593,7 +599,7 @@ void __init omap4430_init_early(void)
 	omap44xx_clockdomains_init();
 	omap44xx_hwmod_init();
 	omap_hwmod_init_postsetup();
-	omap4xxx_clk_init();
+	omap_clk_init = omap4xxx_clk_init;
 }
 
 void __init omap4430_init_late(void)
diff --git a/arch/arm/mach-omap2/mailbox.c b/arch/arm/mach-omap2/mailbox.c
deleted file mode 100644
index 0b08026..0000000
--- a/arch/arm/mach-omap2/mailbox.c
+++ /dev/null
@@ -1,430 +0,0 @@
-/*
- * Mailbox reservation modules for OMAP2/3
- *
- * Copyright (C) 2006-2009 Nokia Corporation
- * Written by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
- *        and  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-
-#include <linux/module.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/pm_runtime.h>
-
-#include <plat/mailbox.h>
-
-#include "soc.h"
-
-#define MAILBOX_REVISION		0x000
-#define MAILBOX_MESSAGE(m)		(0x040 + 4 * (m))
-#define MAILBOX_FIFOSTATUS(m)		(0x080 + 4 * (m))
-#define MAILBOX_MSGSTATUS(m)		(0x0c0 + 4 * (m))
-#define MAILBOX_IRQSTATUS(u)		(0x100 + 8 * (u))
-#define MAILBOX_IRQENABLE(u)		(0x104 + 8 * (u))
-
-#define OMAP4_MAILBOX_IRQSTATUS(u)	(0x104 + 0x10 * (u))
-#define OMAP4_MAILBOX_IRQENABLE(u)	(0x108 + 0x10 * (u))
-#define OMAP4_MAILBOX_IRQENABLE_CLR(u)	(0x10c + 0x10 * (u))
-
-#define MAILBOX_IRQ_NEWMSG(m)		(1 << (2 * (m)))
-#define MAILBOX_IRQ_NOTFULL(m)		(1 << (2 * (m) + 1))
-
-#define MBOX_REG_SIZE			0x120
-
-#define OMAP4_MBOX_REG_SIZE		0x130
-
-#define MBOX_NR_REGS			(MBOX_REG_SIZE / sizeof(u32))
-#define OMAP4_MBOX_NR_REGS		(OMAP4_MBOX_REG_SIZE / sizeof(u32))
-
-static void __iomem *mbox_base;
-
-struct omap_mbox2_fifo {
-	unsigned long msg;
-	unsigned long fifo_stat;
-	unsigned long msg_stat;
-};
-
-struct omap_mbox2_priv {
-	struct omap_mbox2_fifo tx_fifo;
-	struct omap_mbox2_fifo rx_fifo;
-	unsigned long irqenable;
-	unsigned long irqstatus;
-	u32 newmsg_bit;
-	u32 notfull_bit;
-	u32 ctx[OMAP4_MBOX_NR_REGS];
-	unsigned long irqdisable;
-};
-
-static void omap2_mbox_enable_irq(struct omap_mbox *mbox,
-				  omap_mbox_type_t irq);
-
-static inline unsigned int mbox_read_reg(size_t ofs)
-{
-	return __raw_readl(mbox_base + ofs);
-}
-
-static inline void mbox_write_reg(u32 val, size_t ofs)
-{
-	__raw_writel(val, mbox_base + ofs);
-}
-
-/* Mailbox H/W preparations */
-static int omap2_mbox_startup(struct omap_mbox *mbox)
-{
-	u32 l;
-
-	pm_runtime_enable(mbox->dev->parent);
-	pm_runtime_get_sync(mbox->dev->parent);
-
-	l = mbox_read_reg(MAILBOX_REVISION);
-	pr_debug("omap mailbox rev %d.%d\n", (l & 0xf0) >> 4, (l & 0x0f));
-
-	return 0;
-}
-
-static void omap2_mbox_shutdown(struct omap_mbox *mbox)
-{
-	pm_runtime_put_sync(mbox->dev->parent);
-	pm_runtime_disable(mbox->dev->parent);
-}
-
-/* Mailbox FIFO handle functions */
-static mbox_msg_t omap2_mbox_fifo_read(struct omap_mbox *mbox)
-{
-	struct omap_mbox2_fifo *fifo =
-		&((struct omap_mbox2_priv *)mbox->priv)->rx_fifo;
-	return (mbox_msg_t) mbox_read_reg(fifo->msg);
-}
-
-static void omap2_mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg)
-{
-	struct omap_mbox2_fifo *fifo =
-		&((struct omap_mbox2_priv *)mbox->priv)->tx_fifo;
-	mbox_write_reg(msg, fifo->msg);
-}
-
-static int omap2_mbox_fifo_empty(struct omap_mbox *mbox)
-{
-	struct omap_mbox2_fifo *fifo =
-		&((struct omap_mbox2_priv *)mbox->priv)->rx_fifo;
-	return (mbox_read_reg(fifo->msg_stat) == 0);
-}
-
-static int omap2_mbox_fifo_full(struct omap_mbox *mbox)
-{
-	struct omap_mbox2_fifo *fifo =
-		&((struct omap_mbox2_priv *)mbox->priv)->tx_fifo;
-	return mbox_read_reg(fifo->fifo_stat);
-}
-
-/* Mailbox IRQ handle functions */
-static void omap2_mbox_enable_irq(struct omap_mbox *mbox,
-		omap_mbox_type_t irq)
-{
-	struct omap_mbox2_priv *p = mbox->priv;
-	u32 l, bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
-
-	l = mbox_read_reg(p->irqenable);
-	l |= bit;
-	mbox_write_reg(l, p->irqenable);
-}
-
-static void omap2_mbox_disable_irq(struct omap_mbox *mbox,
-		omap_mbox_type_t irq)
-{
-	struct omap_mbox2_priv *p = mbox->priv;
-	u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
-
-	if (!cpu_is_omap44xx())
-		bit = mbox_read_reg(p->irqdisable) & ~bit;
-
-	mbox_write_reg(bit, p->irqdisable);
-}
-
-static void omap2_mbox_ack_irq(struct omap_mbox *mbox,
-		omap_mbox_type_t irq)
-{
-	struct omap_mbox2_priv *p = mbox->priv;
-	u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
-
-	mbox_write_reg(bit, p->irqstatus);
-
-	/* Flush posted write for irq status to avoid spurious interrupts */
-	mbox_read_reg(p->irqstatus);
-}
-
-static int omap2_mbox_is_irq(struct omap_mbox *mbox,
-		omap_mbox_type_t irq)
-{
-	struct omap_mbox2_priv *p = mbox->priv;
-	u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
-	u32 enable = mbox_read_reg(p->irqenable);
-	u32 status = mbox_read_reg(p->irqstatus);
-
-	return (int)(enable & status & bit);
-}
-
-static void omap2_mbox_save_ctx(struct omap_mbox *mbox)
-{
-	int i;
-	struct omap_mbox2_priv *p = mbox->priv;
-	int nr_regs;
-	if (cpu_is_omap44xx())
-		nr_regs = OMAP4_MBOX_NR_REGS;
-	else
-		nr_regs = MBOX_NR_REGS;
-	for (i = 0; i < nr_regs; i++) {
-		p->ctx[i] = mbox_read_reg(i * sizeof(u32));
-
-		dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__,
-			i, p->ctx[i]);
-	}
-}
-
-static void omap2_mbox_restore_ctx(struct omap_mbox *mbox)
-{
-	int i;
-	struct omap_mbox2_priv *p = mbox->priv;
-	int nr_regs;
-	if (cpu_is_omap44xx())
-		nr_regs = OMAP4_MBOX_NR_REGS;
-	else
-		nr_regs = MBOX_NR_REGS;
-	for (i = 0; i < nr_regs; i++) {
-		mbox_write_reg(p->ctx[i], i * sizeof(u32));
-
-		dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__,
-			i, p->ctx[i]);
-	}
-}
-
-static struct omap_mbox_ops omap2_mbox_ops = {
-	.type		= OMAP_MBOX_TYPE2,
-	.startup	= omap2_mbox_startup,
-	.shutdown	= omap2_mbox_shutdown,
-	.fifo_read	= omap2_mbox_fifo_read,
-	.fifo_write	= omap2_mbox_fifo_write,
-	.fifo_empty	= omap2_mbox_fifo_empty,
-	.fifo_full	= omap2_mbox_fifo_full,
-	.enable_irq	= omap2_mbox_enable_irq,
-	.disable_irq	= omap2_mbox_disable_irq,
-	.ack_irq	= omap2_mbox_ack_irq,
-	.is_irq		= omap2_mbox_is_irq,
-	.save_ctx	= omap2_mbox_save_ctx,
-	.restore_ctx	= omap2_mbox_restore_ctx,
-};
-
-/*
- * MAILBOX 0: ARM -> DSP,
- * MAILBOX 1: ARM <- DSP.
- * MAILBOX 2: ARM -> IVA,
- * MAILBOX 3: ARM <- IVA.
- */
-
-/* FIXME: the following structs should be filled automatically by the user id */
-
-#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP2)
-/* DSP */
-static struct omap_mbox2_priv omap2_mbox_dsp_priv = {
-	.tx_fifo = {
-		.msg		= MAILBOX_MESSAGE(0),
-		.fifo_stat	= MAILBOX_FIFOSTATUS(0),
-	},
-	.rx_fifo = {
-		.msg		= MAILBOX_MESSAGE(1),
-		.msg_stat	= MAILBOX_MSGSTATUS(1),
-	},
-	.irqenable	= MAILBOX_IRQENABLE(0),
-	.irqstatus	= MAILBOX_IRQSTATUS(0),
-	.notfull_bit	= MAILBOX_IRQ_NOTFULL(0),
-	.newmsg_bit	= MAILBOX_IRQ_NEWMSG(1),
-	.irqdisable	= MAILBOX_IRQENABLE(0),
-};
-
-struct omap_mbox mbox_dsp_info = {
-	.name	= "dsp",
-	.ops	= &omap2_mbox_ops,
-	.priv	= &omap2_mbox_dsp_priv,
-};
-#endif
-
-#if defined(CONFIG_ARCH_OMAP3)
-struct omap_mbox *omap3_mboxes[] = { &mbox_dsp_info, NULL };
-#endif
-
-#if defined(CONFIG_SOC_OMAP2420)
-/* IVA */
-static struct omap_mbox2_priv omap2_mbox_iva_priv = {
-	.tx_fifo = {
-		.msg		= MAILBOX_MESSAGE(2),
-		.fifo_stat	= MAILBOX_FIFOSTATUS(2),
-	},
-	.rx_fifo = {
-		.msg		= MAILBOX_MESSAGE(3),
-		.msg_stat	= MAILBOX_MSGSTATUS(3),
-	},
-	.irqenable	= MAILBOX_IRQENABLE(3),
-	.irqstatus	= MAILBOX_IRQSTATUS(3),
-	.notfull_bit	= MAILBOX_IRQ_NOTFULL(2),
-	.newmsg_bit	= MAILBOX_IRQ_NEWMSG(3),
-	.irqdisable	= MAILBOX_IRQENABLE(3),
-};
-
-static struct omap_mbox mbox_iva_info = {
-	.name	= "iva",
-	.ops	= &omap2_mbox_ops,
-	.priv	= &omap2_mbox_iva_priv,
-};
-#endif
-
-#ifdef CONFIG_ARCH_OMAP2
-struct omap_mbox *omap2_mboxes[] = {
-	&mbox_dsp_info,
-#ifdef CONFIG_SOC_OMAP2420
-	&mbox_iva_info,
-#endif
-	NULL
-};
-#endif
-
-#if defined(CONFIG_ARCH_OMAP4)
-/* OMAP4 */
-static struct omap_mbox2_priv omap2_mbox_1_priv = {
-	.tx_fifo = {
-		.msg		= MAILBOX_MESSAGE(0),
-		.fifo_stat	= MAILBOX_FIFOSTATUS(0),
-	},
-	.rx_fifo = {
-		.msg		= MAILBOX_MESSAGE(1),
-		.msg_stat	= MAILBOX_MSGSTATUS(1),
-	},
-	.irqenable	= OMAP4_MAILBOX_IRQENABLE(0),
-	.irqstatus	= OMAP4_MAILBOX_IRQSTATUS(0),
-	.notfull_bit	= MAILBOX_IRQ_NOTFULL(0),
-	.newmsg_bit	= MAILBOX_IRQ_NEWMSG(1),
-	.irqdisable	= OMAP4_MAILBOX_IRQENABLE_CLR(0),
-};
-
-struct omap_mbox mbox_1_info = {
-	.name	= "mailbox-1",
-	.ops	= &omap2_mbox_ops,
-	.priv	= &omap2_mbox_1_priv,
-};
-
-static struct omap_mbox2_priv omap2_mbox_2_priv = {
-	.tx_fifo = {
-		.msg		= MAILBOX_MESSAGE(3),
-		.fifo_stat	= MAILBOX_FIFOSTATUS(3),
-	},
-	.rx_fifo = {
-		.msg		= MAILBOX_MESSAGE(2),
-		.msg_stat	= MAILBOX_MSGSTATUS(2),
-	},
-	.irqenable	= OMAP4_MAILBOX_IRQENABLE(0),
-	.irqstatus	= OMAP4_MAILBOX_IRQSTATUS(0),
-	.notfull_bit	= MAILBOX_IRQ_NOTFULL(3),
-	.newmsg_bit	= MAILBOX_IRQ_NEWMSG(2),
-	.irqdisable     = OMAP4_MAILBOX_IRQENABLE_CLR(0),
-};
-
-struct omap_mbox mbox_2_info = {
-	.name	= "mailbox-2",
-	.ops	= &omap2_mbox_ops,
-	.priv	= &omap2_mbox_2_priv,
-};
-
-struct omap_mbox *omap4_mboxes[] = { &mbox_1_info, &mbox_2_info, NULL };
-#endif
-
-static int omap2_mbox_probe(struct platform_device *pdev)
-{
-	struct resource *mem;
-	int ret;
-	struct omap_mbox **list;
-
-	if (false)
-		;
-#if defined(CONFIG_ARCH_OMAP3)
-	else if (cpu_is_omap34xx()) {
-		list = omap3_mboxes;
-
-		list[0]->irq = platform_get_irq(pdev, 0);
-	}
-#endif
-#if defined(CONFIG_ARCH_OMAP2)
-	else if (cpu_is_omap2430()) {
-		list = omap2_mboxes;
-
-		list[0]->irq = platform_get_irq(pdev, 0);
-	} else if (cpu_is_omap2420()) {
-		list = omap2_mboxes;
-
-		list[0]->irq = platform_get_irq_byname(pdev, "dsp");
-		list[1]->irq = platform_get_irq_byname(pdev, "iva");
-	}
-#endif
-#if defined(CONFIG_ARCH_OMAP4)
-	else if (cpu_is_omap44xx()) {
-		list = omap4_mboxes;
-
-		list[0]->irq = list[1]->irq = platform_get_irq(pdev, 0);
-	}
-#endif
-	else {
-		pr_err("%s: platform not supported\n", __func__);
-		return -ENODEV;
-	}
-
-	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	mbox_base = ioremap(mem->start, resource_size(mem));
-	if (!mbox_base)
-		return -ENOMEM;
-
-	ret = omap_mbox_register(&pdev->dev, list);
-	if (ret) {
-		iounmap(mbox_base);
-		return ret;
-	}
-
-	return 0;
-}
-
-static int omap2_mbox_remove(struct platform_device *pdev)
-{
-	omap_mbox_unregister();
-	iounmap(mbox_base);
-	return 0;
-}
-
-static struct platform_driver omap2_mbox_driver = {
-	.probe = omap2_mbox_probe,
-	.remove = omap2_mbox_remove,
-	.driver = {
-		.name = "omap-mailbox",
-	},
-};
-
-static int __init omap2_mbox_init(void)
-{
-	return platform_driver_register(&omap2_mbox_driver);
-}
-
-static void __exit omap2_mbox_exit(void)
-{
-	platform_driver_unregister(&omap2_mbox_driver);
-}
-
-module_init(omap2_mbox_init);
-module_exit(omap2_mbox_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("omap mailbox: omap2/3/4 architecture specific functions");
-MODULE_AUTHOR("Hiroshi DOYU <Hiroshi.DOYU@nokia.com>");
-MODULE_AUTHOR("Paul Mundt");
-MODULE_ALIAS("platform:omap2-mailbox");
diff --git a/arch/arm/mach-omap2/omap-smp.c b/arch/arm/mach-omap2/omap-smp.c
index d972721..f089773 100644
--- a/arch/arm/mach-omap2/omap-smp.c
+++ b/arch/arm/mach-omap2/omap-smp.c
@@ -67,13 +67,6 @@ static void __cpuinit omap4_secondary_init(unsigned int cpu)
 							4, 0, 0, 0, 0, 0);
 
 	/*
-	 * If any interrupts are already enabled for the primary
-	 * core (e.g. timer irq), then they will not have been enabled
-	 * for us: do so
-	 */
-	gic_secondary_init(0);
-
-	/*
 	 * Synchronise with the boot thread.
 	 */
 	spin_lock(&boot_lock);
@@ -209,7 +202,7 @@ static void __init omap4_smp_init_cpus(void)
 	unsigned int i = 0, ncores = 1, cpu_id;
 
 	/* Use ARM cpuid check here, as SoC detection will not work so early */
-	cpu_id = read_cpuid(CPUID_ID) & CPU_MASK;
+	cpu_id = read_cpuid_id() & CPU_MASK;
 	if (cpu_id == CPU_CORTEX_A9) {
 		/*
 		 * Currently we can't call ioremap here because
diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c
index 381be7a..2448c7a 100644
--- a/arch/arm/mach-omap2/omap_device.c
+++ b/arch/arm/mach-omap2/omap_device.c
@@ -131,7 +131,7 @@ static int omap_device_build_from_dt(struct platform_device *pdev)
 	int oh_cnt, i, ret = 0;
 
 	oh_cnt = of_property_count_strings(node, "ti,hwmods");
-	if (!oh_cnt || IS_ERR_VALUE(oh_cnt)) {
+	if (oh_cnt <= 0) {
 		dev_dbg(&pdev->dev, "No 'hwmods' to build omap_device\n");
 		return -ENODEV;
 	}
@@ -815,20 +815,17 @@ struct device *omap_device_get_by_hwmod_name(const char *oh_name)
 	}
 
 	oh = omap_hwmod_lookup(oh_name);
-	if (IS_ERR_OR_NULL(oh)) {
+	if (!oh) {
 		WARN(1, "%s: no hwmod for %s\n", __func__,
 			oh_name);
-		return ERR_PTR(oh ? PTR_ERR(oh) : -ENODEV);
+		return -ENODEV;
 	}
-	if (IS_ERR_OR_NULL(oh->od)) {
+	if (!oh->od) {
 		WARN(1, "%s: no omap_device for %s\n", __func__,
 			oh_name);
-		return ERR_PTR(oh->od ? PTR_ERR(oh->od) : -ENODEV);
+		return -ENODEV;
 	}
 
-	if (IS_ERR_OR_NULL(oh->od->pdev))
-		return ERR_PTR(oh->od->pdev ? PTR_ERR(oh->od->pdev) : -ENODEV);
-
 	return &oh->od->pdev->dev;
 }
 
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index c2c798c..ede9d49 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -1368,7 +1368,9 @@ static void _enable_sysc(struct omap_hwmod *oh)
 	}
 
 	if (sf & SYSC_HAS_MIDLEMODE) {
-		if (oh->flags & HWMOD_SWSUP_MSTANDBY) {
+		if (oh->flags & HWMOD_FORCE_MSTANDBY) {
+			idlemode = HWMOD_IDLEMODE_FORCE;
+		} else if (oh->flags & HWMOD_SWSUP_MSTANDBY) {
 			idlemode = HWMOD_IDLEMODE_NO;
 		} else {
 			if (sf & SYSC_HAS_ENAWAKEUP)
@@ -1440,7 +1442,8 @@ static void _idle_sysc(struct omap_hwmod *oh)
 	}
 
 	if (sf & SYSC_HAS_MIDLEMODE) {
-		if (oh->flags & HWMOD_SWSUP_MSTANDBY) {
+		if ((oh->flags & HWMOD_SWSUP_MSTANDBY) ||
+		    (oh->flags & HWMOD_FORCE_MSTANDBY)) {
 			idlemode = HWMOD_IDLEMODE_FORCE;
 		} else {
 			if (sf & SYSC_HAS_ENAWAKEUP)
@@ -1663,7 +1666,7 @@ static int _deassert_hardreset(struct omap_hwmod *oh, const char *name)
 		return -ENOSYS;
 
 	ret = _lookup_hardreset(oh, name, &ohri);
-	if (IS_ERR_VALUE(ret))
+	if (ret < 0)
 		return ret;
 
 	if (oh->clkdm) {
@@ -2413,7 +2416,7 @@ static int __init _init(struct omap_hwmod *oh, void *data)
 	_init_mpu_rt_base(oh, NULL);
 
 	r = _init_clocks(oh, NULL);
-	if (IS_ERR_VALUE(r)) {
+	if (r < 0) {
 		WARN(1, "omap_hwmod: %s: couldn't init clocks\n", oh->name);
 		return -EINVAL;
 	}
diff --git a/arch/arm/mach-omap2/omap_hwmod.h b/arch/arm/mach-omap2/omap_hwmod.h
index d43d9b6..d5dc935 100644
--- a/arch/arm/mach-omap2/omap_hwmod.h
+++ b/arch/arm/mach-omap2/omap_hwmod.h
@@ -427,8 +427,8 @@ struct omap_hwmod_omap4_prcm {
  *
  * HWMOD_SWSUP_SIDLE: omap_hwmod code should manually bring module in and out
  *     of idle, rather than relying on module smart-idle
- * HWMOD_SWSUP_MSTDBY: omap_hwmod code should manually bring module in and out
- *     of standby, rather than relying on module smart-standby
+ * HWMOD_SWSUP_MSTANDBY: omap_hwmod code should manually bring module in and
+ *     out of standby, rather than relying on module smart-standby
  * HWMOD_INIT_NO_RESET: don't reset this module at boot - important for
  *     SDRAM controller, etc. XXX probably belongs outside the main hwmod file
  *     XXX Should be HWMOD_SETUP_NO_RESET
@@ -459,6 +459,10 @@ struct omap_hwmod_omap4_prcm {
  *     correctly, or this is being abused to deal with some PM latency
  *     issues -- but we're currently suffering from a shortage of
  *     folks who are able to track these issues down properly.
+ * HWMOD_FORCE_MSTANDBY: Always keep MIDLEMODE bits cleared so that device
+ *     is kept in force-standby mode. Failing to do so causes PM problems
+ *     with musb on OMAP3630 at least. Note that musb has a dedicated register
+ *     to control MSTANDBY signal when MIDLEMODE is set to force-standby.
  */
 #define HWMOD_SWSUP_SIDLE			(1 << 0)
 #define HWMOD_SWSUP_MSTANDBY			(1 << 1)
@@ -471,6 +475,7 @@ struct omap_hwmod_omap4_prcm {
 #define HWMOD_16BIT_REG				(1 << 8)
 #define HWMOD_EXT_OPT_MAIN_CLK			(1 << 9)
 #define HWMOD_BLOCK_WFI				(1 << 10)
+#define HWMOD_FORCE_MSTANDBY			(1 << 11)
 
 /*
  * omap_hwmod._int_flags definitions
diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
index 6a764af..8dcd65a 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
@@ -16,6 +16,7 @@
 #include <linux/i2c-omap.h>
 #include <linux/platform_data/spi-omap2-mcspi.h>
 #include <linux/omap-dma.h>
+#include <linux/platform_data/mailbox-omap.h>
 #include <plat/dmtimer.h>
 
 #include "omap_hwmod.h"
@@ -166,6 +167,16 @@ static struct omap_hwmod omap2420_dma_system_hwmod = {
 };
 
 /* mailbox */
+static struct omap_mbox_dev_info omap2420_mailbox_info[] = {
+	{ .name = "dsp", .tx_id = 0, .rx_id = 1, .irq_id = 0, .usr_id = 0 },
+	{ .name = "iva", .tx_id = 2, .rx_id = 3, .irq_id = 1, .usr_id = 3 },
+};
+
+static struct omap_mbox_pdata omap2420_mailbox_attrs = {
+	.info_cnt	= ARRAY_SIZE(omap2420_mailbox_info),
+	.info		= omap2420_mailbox_info,
+};
+
 static struct omap_hwmod_irq_info omap2420_mailbox_irqs[] = {
 	{ .name = "dsp", .irq = 26 + OMAP_INTC_START, },
 	{ .name = "iva", .irq = 34 + OMAP_INTC_START, },
@@ -186,6 +197,7 @@ static struct omap_hwmod omap2420_mailbox_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_MAILBOXES_SHIFT,
 		},
 	},
+	.dev_attr	= &omap2420_mailbox_attrs,
 };
 
 /*
diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
index d2d3840..468c682 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
@@ -17,6 +17,7 @@
 #include <linux/platform_data/asoc-ti-mcbsp.h>
 #include <linux/platform_data/spi-omap2-mcspi.h>
 #include <linux/omap-dma.h>
+#include <linux/platform_data/mailbox-omap.h>
 #include <plat/dmtimer.h>
 
 #include "omap_hwmod.h"
@@ -170,6 +171,15 @@ static struct omap_hwmod omap2430_dma_system_hwmod = {
 };
 
 /* mailbox */
+static struct omap_mbox_dev_info omap2430_mailbox_info[] = {
+	{ .name = "dsp", .tx_id = 0, .rx_id = 1 },
+};
+
+static struct omap_mbox_pdata omap2430_mailbox_attrs = {
+	.info_cnt	= ARRAY_SIZE(omap2430_mailbox_info),
+	.info		= omap2430_mailbox_info,
+};
+
 static struct omap_hwmod_irq_info omap2430_mailbox_irqs[] = {
 	{ .irq = 26 + OMAP_INTC_START, },
 	{ .irq = -1 },
@@ -189,6 +199,7 @@ static struct omap_hwmod omap2430_mailbox_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_MAILBOXES_SHIFT,
 		},
 	},
+	.dev_attr	= &omap2430_mailbox_attrs,
 };
 
 /* mcspi3 */
diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index ac7e03e..c354312 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -25,6 +25,7 @@
 #include <linux/platform_data/asoc-ti-mcbsp.h>
 #include <linux/platform_data/spi-omap2-mcspi.h>
 #include <linux/platform_data/iommu-omap.h>
+#include <linux/platform_data/mailbox-omap.h>
 #include <plat/dmtimer.h>
 
 #include "am35xx.h"
@@ -1501,6 +1502,15 @@ static struct omap_hwmod_class omap3xxx_mailbox_hwmod_class = {
 	.sysc = &omap3xxx_mailbox_sysc,
 };
 
+static struct omap_mbox_dev_info omap3xxx_mailbox_info[] = {
+	{ .name = "dsp", .tx_id = 0, .rx_id = 1 },
+};
+
+static struct omap_mbox_pdata omap3xxx_mailbox_attrs = {
+	.info_cnt	= ARRAY_SIZE(omap3xxx_mailbox_info),
+	.info		= omap3xxx_mailbox_info,
+};
+
 static struct omap_hwmod_irq_info omap3xxx_mailbox_irqs[] = {
 	{ .irq = 26 + OMAP_INTC_START, },
 	{ .irq = -1 },
@@ -1520,6 +1530,7 @@ static struct omap_hwmod omap3xxx_mailbox_hwmod = {
 			.idlest_idle_bit = OMAP3430_ST_MAILBOXES_SHIFT,
 		},
 	},
+	.dev_attr	= &omap3xxx_mailbox_attrs,
 };
 
 /*
@@ -1707,9 +1718,14 @@ static struct omap_hwmod omap3xxx_usbhsotg_hwmod = {
 	 * Erratum ID: i479  idle_req / idle_ack mechanism potentially
 	 * broken when autoidle is enabled
 	 * workaround is to disable the autoidle bit at module level.
+	 *
+	 * Enabling the device in any other MIDLEMODE setting but force-idle
+	 * causes core_pwrdm not enter idle states at least on OMAP3630.
+	 * Note that musb has OTG_FORCESTDBY register that controls MSTANDBY
+	 * signal when MIDLEMODE is set to force-idle.
 	 */
 	.flags		= HWMOD_NO_OCP_AUTOIDLE | HWMOD_SWSUP_SIDLE
-				| HWMOD_SWSUP_MSTANDBY,
+				| HWMOD_FORCE_MSTANDBY,
 };
 
 /* usb_otg_hs */
diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index 0e47d2e..206f6f8 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -29,6 +29,7 @@
 #include <linux/platform_data/spi-omap2-mcspi.h>
 #include <linux/platform_data/asoc-ti-mcbsp.h>
 #include <linux/platform_data/iommu-omap.h>
+#include <linux/platform_data/mailbox-omap.h>
 #include <plat/dmtimer.h>
 
 #include "omap_hwmod.h"
@@ -1861,6 +1862,17 @@ static struct omap_hwmod_class omap44xx_mailbox_hwmod_class = {
 };
 
 /* mailbox */
+static struct omap_mbox_dev_info omap44xx_mailbox_info[] = {
+	{ .name = "mbox-ipu", .tx_id = 0, .rx_id = 1 },
+	{ .name = "mbox-dsp", .tx_id = 3, .rx_id = 2 },
+};
+
+static struct omap_mbox_pdata omap44xx_mailbox_attrs = {
+	.intr_type	= MBOX_INTR_CFG_TYPE2,
+	.info_cnt	= ARRAY_SIZE(omap44xx_mailbox_info),
+	.info		= omap44xx_mailbox_info,
+};
+
 static struct omap_hwmod_irq_info omap44xx_mailbox_irqs[] = {
 	{ .irq = 26 + OMAP44XX_IRQ_GIC_START },
 	{ .irq = -1 }
@@ -1877,6 +1889,7 @@ static struct omap_hwmod omap44xx_mailbox_hwmod = {
 			.context_offs = OMAP4_RM_L4CFG_MAILBOX_CONTEXT_OFFSET,
 		},
 	},
+	.dev_attr	= &omap44xx_mailbox_attrs,
 };
 
 /*
@@ -2714,6 +2727,10 @@ static struct omap_ocp2scp_dev ocp2scp_dev_attr[] = {
 	{ }
 };
 
+static struct omap_hwmod_opt_clk ocp2scp_usb_phy_opt_clks[] = {
+	{ .role = "48mhz", .clk = "ocp2scp_usb_phy_phy_48m" },
+};
+
 /* ocp2scp_usb_phy */
 static struct omap_hwmod omap44xx_ocp2scp_usb_phy_hwmod = {
 	.name		= "ocp2scp_usb_phy",
@@ -2728,6 +2745,8 @@ static struct omap_hwmod omap44xx_ocp2scp_usb_phy_hwmod = {
 		},
 	},
 	.dev_attr	= ocp2scp_dev_attr,
+	.opt_clks	= ocp2scp_usb_phy_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(ocp2scp_usb_phy_opt_clks),
 };
 
 /*
diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c
index 1edd000..0b33986 100644
--- a/arch/arm/mach-omap2/pm-debug.c
+++ b/arch/arm/mach-omap2/pm-debug.c
@@ -217,7 +217,7 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *dir)
 		return 0;
 
 	d = debugfs_create_dir(pwrdm->name, (struct dentry *)dir);
-	if (!(IS_ERR_OR_NULL(d)))
+	if (d)
 		(void) debugfs_create_file("suspend", S_IRUGO|S_IWUSR, d,
 			(void *)pwrdm, &pwrdm_suspend_fops);
 
@@ -261,8 +261,8 @@ static int __init pm_dbg_init(void)
 		return 0;
 
 	d = debugfs_create_dir("pm_debug", NULL);
-	if (IS_ERR_OR_NULL(d))
-		return PTR_ERR(d);
+	if (!d)
+		return -EINVAL;
 
 	(void) debugfs_create_file("count", S_IRUGO,
 		d, (void *)DEBUG_FILE_COUNTERS, &debug_fops);
diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c
index ea62e75..152a10c 100644
--- a/arch/arm/mach-omap2/pm44xx.c
+++ b/arch/arm/mach-omap2/pm44xx.c
@@ -126,8 +126,8 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
  * omap_default_idle - OMAP4 default ilde routine.'
  *
  * Implements OMAP4 memory, IO ordering requirements which can't be addressed
- * with default cpu_do_idle() hook. Used by all CPUs with !CONFIG_CPUIDLE and
- * by secondary CPU with CONFIG_CPUIDLE.
+ * with default cpu_do_idle() hook. Used by all CPUs with !CONFIG_CPU_IDLE and
+ * by secondary CPU with CONFIG_CPU_IDLE.
  */
 static void omap_default_idle(void)
 {
diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index 8e61d80..43ac20c 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -1182,7 +1182,7 @@ bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm)
 {
 	int i;
 
-	if (IS_ERR_OR_NULL(pwrdm)) {
+	if (!pwrdm) {
 		pr_debug("powerdomain: %s: invalid powerdomain pointer\n",
 			 __func__);
 		return 1;
diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
index 2bdd4cf..2814203 100644
--- a/arch/arm/mach-omap2/timer.c
+++ b/arch/arm/mach-omap2/timer.c
@@ -287,7 +287,7 @@ static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,
 			r = -EINVAL;
 		} else {
 			r = clk_set_parent(timer->fclk, src);
-			if (IS_ERR_VALUE(r))
+			if (r < 0)
 				pr_warn("%s: %s cannot set source\n",
 					__func__, oh->name);
 			clk_put(src);
@@ -547,6 +547,8 @@ static inline void __init realtime_counter_init(void)
 			       clksrc_nr, clksrc_src)			\
 void __init omap##name##_gptimer_timer_init(void)			\
 {									\
+	if (omap_clk_init)						\
+		omap_clk_init();					\
 	omap_dmtimer_init();						\
 	omap2_gp_clockevent_init((clkev_nr), clkev_src, clkev_prop);	\
 	omap2_gptimer_clocksource_init((clksrc_nr), clksrc_src);	\
@@ -556,6 +558,8 @@ void __init omap##name##_gptimer_timer_init(void)			\
 				clksrc_nr, clksrc_src)			\
 void __init omap##name##_sync32k_timer_init(void)		\
 {									\
+	if (omap_clk_init)						\
+		omap_clk_init();					\
 	omap_dmtimer_init();						\
 	omap2_gp_clockevent_init((clkev_nr), clkev_src, clkev_prop);	\
 	/* Enable the use of clocksource="gp_timer" kernel parameter */	\
@@ -597,7 +601,7 @@ void __init omap4_local_timer_init(void)
 		int err;
 
 		if (of_have_populated_dt()) {
-			twd_local_timer_of_register();
+			clocksource_of_init();
 			return;
 		}
 
diff --git a/arch/arm/mach-orion5x/pci.c b/arch/arm/mach-orion5x/pci.c
index d9c7c3b..973db98 100644
--- a/arch/arm/mach-orion5x/pci.c
+++ b/arch/arm/mach-orion5x/pci.c
@@ -402,8 +402,9 @@ static void __init orion5x_pci_master_slave_enable(void)
 	orion5x_pci_hw_wr_conf(bus_nr, 0, func, reg, 4, val | 0x7);
 }
 
-static void __init orion5x_setup_pci_wins(struct mbus_dram_target_info *dram)
+static void __init orion5x_setup_pci_wins(void)
 {
+	const struct mbus_dram_target_info *dram = mv_mbus_dram_info();
 	u32 win_enable;
 	int bus;
 	int i;
@@ -420,7 +421,7 @@ static void __init orion5x_setup_pci_wins(struct mbus_dram_target_info *dram)
 	bus = orion5x_pci_local_bus_nr();
 
 	for (i = 0; i < dram->num_cs; i++) {
-		struct mbus_dram_window *cs = dram->cs + i;
+		const struct mbus_dram_window *cs = dram->cs + i;
 		u32 func = PCI_CONF_FUNC_BAR_CS(cs->cs_index);
 		u32 reg;
 		u32 val;
@@ -467,7 +468,7 @@ static int __init pci_setup(struct pci_sys_data *sys)
 	/*
 	 * Point PCI unit MBUS decode windows to DRAM space.
 	 */
-	orion5x_setup_pci_wins(&orion_mbus_dram_info);
+	orion5x_setup_pci_wins();
 
 	/*
 	 * Master + Slave enable
diff --git a/arch/arm/mach-prima2/Kconfig b/arch/arm/mach-prima2/Kconfig
index 4f7379f..587c0bd 100644
--- a/arch/arm/mach-prima2/Kconfig
+++ b/arch/arm/mach-prima2/Kconfig
@@ -1,6 +1,26 @@
+config ARCH_SIRF
+	bool "CSR SiRF" if ARCH_MULTI_V7
+	select ARCH_REQUIRE_GPIOLIB
+	select GENERIC_CLOCKEVENTS
+	select GENERIC_IRQ_CHIP
+	select MIGHT_HAVE_CACHE_L2X0
+	select NO_IOPORT
+	select PINCTRL
+	select PINCTRL_SIRF
+	help
+	  Support for CSR SiRFprimaII/Marco/Polo platforms
+
 if ARCH_SIRF
 
-menu "CSR SiRF primaII/Marco/Polo Specific Features"
+menu "CSR SiRF atlas6/primaII/Marco/Polo Specific Features"
+
+config ARCH_ATLAS6
+	bool "CSR SiRFSoC ATLAS6 ARM Cortex A9 Platform"
+	default y
+	select CPU_V7
+	select SIRF_IRQ
+	help
+          Support for CSR SiRFSoC ARM Cortex A9 Platform
 
 config ARCH_PRIMA2
 	bool "CSR SiRFSoC PRIMA2 ARM Cortex A9 Platform"
diff --git a/arch/arm/mach-prima2/Makefile b/arch/arm/mach-prima2/Makefile
index bfe360c..7a6b4a3 100644
--- a/arch/arm/mach-prima2/Makefile
+++ b/arch/arm/mach-prima2/Makefile
@@ -4,8 +4,7 @@ obj-y += rtciobrg.o
 obj-$(CONFIG_DEBUG_LL) += lluart.o
 obj-$(CONFIG_CACHE_L2X0) += l2x0.o
 obj-$(CONFIG_SUSPEND) += pm.o sleep.o
-obj-$(CONFIG_SIRF_IRQ) += irq.o
 obj-$(CONFIG_SMP) += platsmp.o headsmp.o
 obj-$(CONFIG_HOTPLUG_CPU)  += hotplug.o
-obj-$(CONFIG_ARCH_PRIMA2) += timer-prima2.o
-obj-$(CONFIG_ARCH_MARCO) += timer-marco.o
+
+CFLAGS_hotplug.o += -march=armv7-a
diff --git a/arch/arm/mach-prima2/common.c b/arch/arm/mach-prima2/common.c
index 2d57aa4..4f94cd8 100644
--- a/arch/arm/mach-prima2/common.c
+++ b/arch/arm/mach-prima2/common.c
@@ -6,6 +6,7 @@
  * Licensed under GPLv2 or later.
  */
 
+#include <linux/clocksource.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/irqchip.h>
@@ -31,12 +32,38 @@ void __init sirfsoc_init_late(void)
 	sirfsoc_pm_init();
 }
 
+static __init void sirfsoc_init_time(void)
+{
+	/* initialize clocking early, we want to set the OS timer */
+	sirfsoc_of_clk_init();
+	clocksource_of_init();
+}
+
 static __init void sirfsoc_map_io(void)
 {
 	sirfsoc_map_lluart();
 	sirfsoc_map_scu();
 }
 
+#ifdef CONFIG_ARCH_ATLAS6
+static const char *atlas6_dt_match[] __initdata = {
+	"sirf,atlas6",
+	NULL
+};
+
+DT_MACHINE_START(ATLAS6_DT, "Generic ATLAS6 (Flattened Device Tree)")
+	/* Maintainer: Barry Song <baohua.song@csr.com> */
+	.nr_irqs	= 128,
+	.map_io         = sirfsoc_map_io,
+	.init_irq	= irqchip_init,
+	.init_time	= sirfsoc_init_time,
+	.init_machine	= sirfsoc_mach_init,
+	.init_late	= sirfsoc_init_late,
+	.dt_compat      = atlas6_dt_match,
+	.restart	= sirfsoc_restart,
+MACHINE_END
+#endif
+
 #ifdef CONFIG_ARCH_PRIMA2
 static const char *prima2_dt_match[] __initdata = {
        "sirf,prima2",
@@ -45,12 +72,10 @@ static const char *prima2_dt_match[] __initdata = {
 
 DT_MACHINE_START(PRIMA2_DT, "Generic PRIMA2 (Flattened Device Tree)")
 	/* Maintainer: Barry Song <baohua.song@csr.com> */
+	.nr_irqs	= 128,
 	.map_io         = sirfsoc_map_io,
-	.init_irq	= sirfsoc_of_irq_init,
-	.init_time	= sirfsoc_prima2_timer_init,
-#ifdef CONFIG_MULTI_IRQ_HANDLER
-	.handle_irq     = sirfsoc_handle_irq,
-#endif
+	.init_irq	= irqchip_init,
+	.init_time	= sirfsoc_init_time,
 	.dma_zone_size	= SZ_256M,
 	.init_machine	= sirfsoc_mach_init,
 	.init_late	= sirfsoc_init_late,
@@ -70,7 +95,7 @@ DT_MACHINE_START(MARCO_DT, "Generic MARCO (Flattened Device Tree)")
 	.smp            = smp_ops(sirfsoc_smp_ops),
 	.map_io         = sirfsoc_map_io,
 	.init_irq	= irqchip_init,
-	.init_time	= sirfsoc_marco_timer_init,
+	.init_time	= sirfsoc_init_time,
 	.init_machine	= sirfsoc_mach_init,
 	.init_late	= sirfsoc_init_late,
 	.dt_compat      = marco_dt_match,
diff --git a/arch/arm/mach-prima2/common.h b/arch/arm/mach-prima2/common.h
index b7c26b6..81135cd 100644
--- a/arch/arm/mach-prima2/common.h
+++ b/arch/arm/mach-prima2/common.h
@@ -13,8 +13,8 @@
 #include <asm/mach/time.h>
 #include <asm/exception.h>
 
-extern void sirfsoc_prima2_timer_init(void);
-extern void sirfsoc_marco_timer_init(void);
+#define SIRFSOC_VA_BASE		_AC(0xFEC00000, UL)
+#define SIRFSOC_VA(x)		(SIRFSOC_VA_BASE + ((x) & 0x00FFF000))
 
 extern struct smp_operations   sirfsoc_smp_ops;
 extern void sirfsoc_secondary_startup(void);
diff --git a/arch/arm/mach-prima2/include/mach/clkdev.h b/arch/arm/mach-prima2/include/mach/clkdev.h
deleted file mode 100644
index 6693251..0000000
--- a/arch/arm/mach-prima2/include/mach/clkdev.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * 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
deleted file mode 100644
index cd97492..0000000
--- a/arch/arm/mach-prima2/include/mach/debug-macro.S
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * 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, tmp
-	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
deleted file mode 100644
index 86434e7..0000000
--- a/arch/arm/mach-prima2/include/mach/entry-macro.S
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * 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
diff --git a/arch/arm/mach-prima2/include/mach/hardware.h b/arch/arm/mach-prima2/include/mach/hardware.h
deleted file mode 100644
index 105b969..0000000
--- a/arch/arm/mach-prima2/include/mach/hardware.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * 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/irqs.h b/arch/arm/mach-prima2/include/mach/irqs.h
deleted file mode 100644
index b778a0f..0000000
--- a/arch/arm/mach-prima2/include/mach/irqs.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * 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    127
-#define SIRFSOC_GPIO_IRQ_START     (SIRFSOC_INTENAL_IRQ_END + 1)
-#define NR_IRQS	288
-
-#endif
diff --git a/arch/arm/mach-prima2/include/mach/map.h b/arch/arm/mach-prima2/include/mach/map.h
deleted file mode 100644
index 6f24353..0000000
--- a/arch/arm/mach-prima2/include/mach/map.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * 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 <linux/const.h>
-
-#define SIRFSOC_VA_BASE		_AC(0xFEC00000, UL)
-
-#define SIRFSOC_VA(x)		(SIRFSOC_VA_BASE + ((x) & 0x00FFF000))
-
-#endif
diff --git a/arch/arm/mach-prima2/include/mach/timex.h b/arch/arm/mach-prima2/include/mach/timex.h
deleted file mode 100644
index d6f98a7..0000000
--- a/arch/arm/mach-prima2/include/mach/timex.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * 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
deleted file mode 100644
index c10510d..0000000
--- a/arch/arm/mach-prima2/include/mach/uart.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * 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 */
-#if defined(CONFIG_DEBUG_SIRFPRIMA2_UART1)
-#define SIRFSOC_UART1_PA_BASE          0xb0060000
-#elif defined(CONFIG_DEBUG_SIRFMARCO_UART1)
-#define SIRFSOC_UART1_PA_BASE          0xcc060000
-#else
-#define SIRFSOC_UART1_PA_BASE          0
-#endif
-#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
deleted file mode 100644
index d1513a3..0000000
--- a/arch/arm/mach-prima2/include/mach/uncompress.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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)
-{
-}
-
-static __inline__ void putc(char c)
-{
-	/*
-	 * during kernel decompression, all mappings are flat:
-	 *  virt_addr == phys_addr
-	 */
-	if (!SIRFSOC_UART1_PA_BASE)
-		return;
-
-	while (__raw_readl((void __iomem *)SIRFSOC_UART1_PA_BASE + SIRFSOC_UART_TXFIFO_STATUS)
-		& SIRFSOC_UART1_TXFIFO_FULL)
-		barrier();
-
-	__raw_writel(c, (void __iomem *)SIRFSOC_UART1_PA_BASE + SIRFSOC_UART_TXFIFO_DATA);
-}
-
-static inline void flush(void)
-{
-}
-
-#endif
-
diff --git a/arch/arm/mach-prima2/irq.c b/arch/arm/mach-prima2/irq.c
deleted file mode 100644
index 6c0f3e9..0000000
--- a/arch/arm/mach-prima2/irq.c
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * 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 <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/irqdomain.h>
-#include <linux/syscore_ops.h>
-#include <asm/mach/irq.h>
-#include <asm/exception.h>
-#include <mach/hardware.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
-#define SIRFSOC_INIT_IRQ_ID		0x0038
-
-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 + 1 - 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);
-}
-
-asmlinkage void __exception_irq_entry sirfsoc_handle_irq(struct pt_regs *regs)
-{
-	u32 irqstat, irqnr;
-
-	irqstat = readl_relaxed(sirfsoc_intc_base + SIRFSOC_INIT_IRQ_ID);
-	irqnr = irqstat & 0xff;
-
-	handle_IRQ(irqnr, regs);
-}
-
-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)
-		return;
-
-	sirfsoc_intc_base = of_iomap(np, 0);
-	if (!sirfsoc_intc_base)
-		panic("unable to map intc cpu registers\n");
-
-	irq_domain_add_legacy(np, SIRFSOC_INTENAL_IRQ_END + 1, 0, 0,
-		&irq_domain_simple_ops, NULL);
-
-	of_node_put(np);
-
-	sirfsoc_irq_init();
-}
-
-struct sirfsoc_irq_status {
-	u32 mask0;
-	u32 mask1;
-	u32 level0;
-	u32 level1;
-};
-
-static struct sirfsoc_irq_status sirfsoc_irq_st;
-
-static int sirfsoc_irq_suspend(void)
-{
-	sirfsoc_irq_st.mask0 = readl_relaxed(sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK0);
-	sirfsoc_irq_st.mask1 = readl_relaxed(sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK1);
-	sirfsoc_irq_st.level0 = readl_relaxed(sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL0);
-	sirfsoc_irq_st.level1 = readl_relaxed(sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL1);
-
-	return 0;
-}
-
-static void sirfsoc_irq_resume(void)
-{
-	writel_relaxed(sirfsoc_irq_st.mask0, sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK0);
-	writel_relaxed(sirfsoc_irq_st.mask1, sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK1);
-	writel_relaxed(sirfsoc_irq_st.level0, sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL0);
-	writel_relaxed(sirfsoc_irq_st.level1, sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL1);
-}
-
-static struct syscore_ops sirfsoc_irq_syscore_ops = {
-	.suspend	= sirfsoc_irq_suspend,
-	.resume		= sirfsoc_irq_resume,
-};
-
-static int __init sirfsoc_irq_pm_init(void)
-{
-	register_syscore_ops(&sirfsoc_irq_syscore_ops);
-	return 0;
-}
-device_initcall(sirfsoc_irq_pm_init);
diff --git a/arch/arm/mach-prima2/lluart.c b/arch/arm/mach-prima2/lluart.c
index a89f9b3..99c0c92 100644
--- a/arch/arm/mach-prima2/lluart.c
+++ b/arch/arm/mach-prima2/lluart.c
@@ -9,8 +9,18 @@
 #include <linux/kernel.h>
 #include <asm/page.h>
 #include <asm/mach/map.h>
-#include <mach/map.h>
-#include <mach/uart.h>
+#include "common.h"
+
+#if defined(CONFIG_DEBUG_SIRFPRIMA2_UART1)
+#define SIRFSOC_UART1_PA_BASE          0xb0060000
+#elif defined(CONFIG_DEBUG_SIRFMARCO_UART1)
+#define SIRFSOC_UART1_PA_BASE          0xcc060000
+#else
+#define SIRFSOC_UART1_PA_BASE          0
+#endif
+
+#define SIRFSOC_UART1_VA_BASE          SIRFSOC_VA(0x060000)
+#define SIRFSOC_UART1_SIZE		SZ_4K
 
 void __init sirfsoc_map_lluart(void)
 {
diff --git a/arch/arm/mach-prima2/platsmp.c b/arch/arm/mach-prima2/platsmp.c
index 4b78831..1c3de7b 100644
--- a/arch/arm/mach-prima2/platsmp.c
+++ b/arch/arm/mach-prima2/platsmp.c
@@ -11,14 +11,12 @@
 #include <linux/delay.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
-#include <linux/irqchip/arm-gic.h>
 #include <asm/page.h>
 #include <asm/mach/map.h>
 #include <asm/smp_plat.h>
 #include <asm/smp_scu.h>
 #include <asm/cacheflush.h>
 #include <asm/cputype.h>
-#include <mach/map.h>
 
 #include "common.h"
 
@@ -49,13 +47,6 @@ void __init sirfsoc_map_scu(void)
 static void __cpuinit sirfsoc_secondary_init(unsigned int cpu)
 {
 	/*
-	 * if any interrupts are already enabled for the primary
-	 * core (e.g. timer irq), then they will not have been enabled
-	 * for us: do so
-	 */
-	gic_secondary_init(0);
-
-	/*
 	 * let the primary processor know we're out of the
 	 * pen, then head off into the C entry point
 	 */
diff --git a/arch/arm/mach-prima2/timer-marco.c b/arch/arm/mach-prima2/timer-marco.c
deleted file mode 100644
index f4eea2e..0000000
--- a/arch/arm/mach-prima2/timer-marco.c
+++ /dev/null
@@ -1,316 +0,0 @@
-/*
- * 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/slab.h>
-#include <linux/of.h>
-#include <linux/of_irq.h>
-#include <linux/of_address.h>
-#include <asm/sched_clock.h>
-#include <asm/localtimer.h>
-#include <asm/mach/time.h>
-
-#include "common.h"
-
-#define SIRFSOC_TIMER_32COUNTER_0_CTRL			0x0000
-#define SIRFSOC_TIMER_32COUNTER_1_CTRL			0x0004
-#define SIRFSOC_TIMER_MATCH_0				0x0018
-#define SIRFSOC_TIMER_MATCH_1				0x001c
-#define SIRFSOC_TIMER_COUNTER_0				0x0048
-#define SIRFSOC_TIMER_COUNTER_1				0x004c
-#define SIRFSOC_TIMER_INTR_STATUS			0x0060
-#define SIRFSOC_TIMER_WATCHDOG_EN			0x0064
-#define SIRFSOC_TIMER_64COUNTER_CTRL			0x0068
-#define SIRFSOC_TIMER_64COUNTER_LO			0x006c
-#define SIRFSOC_TIMER_64COUNTER_HI			0x0070
-#define SIRFSOC_TIMER_64COUNTER_LOAD_LO			0x0074
-#define SIRFSOC_TIMER_64COUNTER_LOAD_HI			0x0078
-#define SIRFSOC_TIMER_64COUNTER_RLATCHED_LO		0x007c
-#define SIRFSOC_TIMER_64COUNTER_RLATCHED_HI		0x0080
-
-#define SIRFSOC_TIMER_REG_CNT 6
-
-static const u32 sirfsoc_timer_reg_list[SIRFSOC_TIMER_REG_CNT] = {
-	SIRFSOC_TIMER_WATCHDOG_EN,
-	SIRFSOC_TIMER_32COUNTER_0_CTRL,
-	SIRFSOC_TIMER_32COUNTER_1_CTRL,
-	SIRFSOC_TIMER_64COUNTER_CTRL,
-	SIRFSOC_TIMER_64COUNTER_RLATCHED_LO,
-	SIRFSOC_TIMER_64COUNTER_RLATCHED_HI,
-};
-
-static u32 sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT];
-
-static void __iomem *sirfsoc_timer_base;
-static void __init sirfsoc_of_timer_map(void);
-
-/* disable count and interrupt */
-static inline void sirfsoc_timer_count_disable(int idx)
-{
-	writel_relaxed(readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL + 4 * idx) & ~0x7,
-		sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL + 4 * idx);
-}
-
-/* enable count and interrupt */
-static inline void sirfsoc_timer_count_enable(int idx)
-{
-	writel_relaxed(readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL + 4 * idx) | 0x7,
-		sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL + 4 * idx);
-}
-
-/* timer interrupt handler */
-static irqreturn_t sirfsoc_timer_interrupt(int irq, void *dev_id)
-{
-	struct clock_event_device *ce = dev_id;
-	int cpu = smp_processor_id();
-
-	/* clear timer interrupt */
-	writel_relaxed(BIT(cpu), sirfsoc_timer_base + SIRFSOC_TIMER_INTR_STATUS);
-
-	if (ce->mode == CLOCK_EVT_MODE_ONESHOT)
-		sirfsoc_timer_count_disable(cpu);
-
-	ce->event_handler(ce);
-
-	return IRQ_HANDLED;
-}
-
-/* read 64-bit timer counter */
-static cycle_t sirfsoc_timer_read(struct clocksource *cs)
-{
-	u64 cycles;
-
-	writel_relaxed((readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL) |
-			BIT(0)) & ~BIT(1), sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL);
-
-	cycles = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_RLATCHED_HI);
-	cycles = (cycles << 32) | readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_RLATCHED_LO);
-
-	return cycles;
-}
-
-static int sirfsoc_timer_set_next_event(unsigned long delta,
-	struct clock_event_device *ce)
-{
-	int cpu = smp_processor_id();
-
-	writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_0 +
-		4 * cpu);
-	writel_relaxed(delta, sirfsoc_timer_base + SIRFSOC_TIMER_MATCH_0 +
-		4 * cpu);
-
-	/* enable the tick */
-	sirfsoc_timer_count_enable(cpu);
-
-	return 0;
-}
-
-static void sirfsoc_timer_set_mode(enum clock_event_mode mode,
-	struct clock_event_device *ce)
-{
-	switch (mode) {
-	case CLOCK_EVT_MODE_ONESHOT:
-		/* enable in set_next_event */
-		break;
-	default:
-		break;
-	}
-
-	sirfsoc_timer_count_disable(smp_processor_id());
-}
-
-static void sirfsoc_clocksource_suspend(struct clocksource *cs)
-{
-	int i;
-
-	for (i = 0; i < SIRFSOC_TIMER_REG_CNT; i++)
-		sirfsoc_timer_reg_val[i] = readl_relaxed(sirfsoc_timer_base + sirfsoc_timer_reg_list[i]);
-}
-
-static void sirfsoc_clocksource_resume(struct clocksource *cs)
-{
-	int i;
-
-	for (i = 0; i < SIRFSOC_TIMER_REG_CNT - 2; i++)
-		writel_relaxed(sirfsoc_timer_reg_val[i], sirfsoc_timer_base + sirfsoc_timer_reg_list[i]);
-
-	writel_relaxed(sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT - 2],
-		sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_LOAD_LO);
-	writel_relaxed(sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT - 1],
-		sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_LOAD_HI);
-
-	writel_relaxed(readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL) |
-		BIT(1) | BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL);
-}
-
-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,
-	.suspend = sirfsoc_clocksource_suspend,
-	.resume = sirfsoc_clocksource_resume,
-};
-
-static struct irqaction sirfsoc_timer_irq = {
-	.name = "sirfsoc_timer0",
-	.flags = IRQF_TIMER | IRQF_NOBALANCING,
-	.handler = sirfsoc_timer_interrupt,
-	.dev_id = &sirfsoc_clockevent,
-};
-
-#ifdef CONFIG_LOCAL_TIMERS
-
-static struct irqaction sirfsoc_timer1_irq = {
-	.name = "sirfsoc_timer1",
-	.flags = IRQF_TIMER | IRQF_NOBALANCING,
-	.handler = sirfsoc_timer_interrupt,
-};
-
-static int __cpuinit sirfsoc_local_timer_setup(struct clock_event_device *ce)
-{
-	/* Use existing clock_event for cpu 0 */
-	if (!smp_processor_id())
-		return 0;
-
-	ce->irq = sirfsoc_timer1_irq.irq;
-	ce->name = "local_timer";
-	ce->features = sirfsoc_clockevent.features;
-	ce->rating = sirfsoc_clockevent.rating;
-	ce->set_mode = sirfsoc_timer_set_mode;
-	ce->set_next_event = sirfsoc_timer_set_next_event;
-	ce->shift = sirfsoc_clockevent.shift;
-	ce->mult = sirfsoc_clockevent.mult;
-	ce->max_delta_ns = sirfsoc_clockevent.max_delta_ns;
-	ce->min_delta_ns = sirfsoc_clockevent.min_delta_ns;
-
-	sirfsoc_timer1_irq.dev_id = ce;
-	BUG_ON(setup_irq(ce->irq, &sirfsoc_timer1_irq));
-	irq_set_affinity(sirfsoc_timer1_irq.irq, cpumask_of(1));
-
-	clockevents_register_device(ce);
-	return 0;
-}
-
-static void sirfsoc_local_timer_stop(struct clock_event_device *ce)
-{
-	sirfsoc_timer_count_disable(1);
-
-	remove_irq(sirfsoc_timer1_irq.irq, &sirfsoc_timer1_irq);
-}
-
-static struct local_timer_ops sirfsoc_local_timer_ops __cpuinitdata = {
-	.setup	= sirfsoc_local_timer_setup,
-	.stop	= sirfsoc_local_timer_stop,
-};
-#endif /* CONFIG_LOCAL_TIMERS */
-
-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);
-#ifdef CONFIG_LOCAL_TIMERS
-	local_timer_register(&sirfsoc_local_timer_ops);
-#endif
-}
-
-/* initialize the kernel jiffy timer source */
-void __init sirfsoc_marco_timer_init(void)
-{
-	unsigned long rate;
-	u32 timer_div;
-	struct clk *clk;
-
-	/* initialize clocking early, we want to set the OS timer */
-	sirfsoc_of_clk_init();
-
-	/* timer's input clock is io clock */
-	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);
-
-	sirfsoc_of_timer_map();
-
-	/* Initialize the timer dividers */
-	timer_div = rate / CLOCK_TICK_RATE - 1;
-	writel_relaxed(timer_div << 16, sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL);
-	writel_relaxed(timer_div << 16, sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL);
-	writel_relaxed(timer_div << 16, sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_1_CTRL);
-
-	/* Initialize timer counters to 0 */
-	writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_LOAD_LO);
-	writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_LOAD_HI);
-	writel_relaxed(readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL) |
-		BIT(1) | BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL);
-	writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_0);
-	writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_1);
-
-	/* Clear all interrupts */
-	writel_relaxed(0xFFFF, sirfsoc_timer_base + SIRFSOC_TIMER_INTR_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,marco-tick" },
-	{},
-};
-
-static void __init sirfsoc_of_timer_map(void)
-{
-	struct device_node *np;
-
-	np = of_find_matching_node(NULL, timer_ids);
-	if (!np)
-		return;
-	sirfsoc_timer_base = of_iomap(np, 0);
-	if (!sirfsoc_timer_base)
-		panic("unable to map timer cpu registers\n");
-
-	sirfsoc_timer_irq.irq = irq_of_parse_and_map(np, 0);
-	if (!sirfsoc_timer_irq.irq)
-		panic("No irq passed for timer0 via DT\n");
-
-#ifdef CONFIG_LOCAL_TIMERS
-	sirfsoc_timer1_irq.irq = irq_of_parse_and_map(np, 1);
-	if (!sirfsoc_timer1_irq.irq)
-		panic("No irq passed for timer1 via DT\n");
-#endif
-
-	of_node_put(np);
-}
diff --git a/arch/arm/mach-prima2/timer-prima2.c b/arch/arm/mach-prima2/timer-prima2.c
deleted file mode 100644
index 6da584f..0000000
--- a/arch/arm/mach-prima2/timer-prima2.c
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * 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/sched_clock.h>
-#include <asm/mach/time.h>
-
-#include "common.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)
-
-#define SIRFSOC_TIMER_REG_CNT 11
-
-static const u32 sirfsoc_timer_reg_list[SIRFSOC_TIMER_REG_CNT] = {
-	SIRFSOC_TIMER_MATCH_0, SIRFSOC_TIMER_MATCH_1, SIRFSOC_TIMER_MATCH_2,
-	SIRFSOC_TIMER_MATCH_3, SIRFSOC_TIMER_MATCH_4, SIRFSOC_TIMER_MATCH_5,
-	SIRFSOC_TIMER_INT_EN, SIRFSOC_TIMER_WATCHDOG_EN, SIRFSOC_TIMER_DIV,
-	SIRFSOC_TIMER_LATCHED_LO, SIRFSOC_TIMER_LATCHED_HI,
-};
-
-static u32 sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT];
-
-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 void sirfsoc_clocksource_suspend(struct clocksource *cs)
-{
-	int i;
-
-	writel_relaxed(SIRFSOC_TIMER_LATCH_BIT, sirfsoc_timer_base + SIRFSOC_TIMER_LATCH);
-
-	for (i = 0; i < SIRFSOC_TIMER_REG_CNT; i++)
-		sirfsoc_timer_reg_val[i] = readl_relaxed(sirfsoc_timer_base + sirfsoc_timer_reg_list[i]);
-}
-
-static void sirfsoc_clocksource_resume(struct clocksource *cs)
-{
-	int i;
-
-	for (i = 0; i < SIRFSOC_TIMER_REG_CNT - 2; i++)
-		writel_relaxed(sirfsoc_timer_reg_val[i], sirfsoc_timer_base + sirfsoc_timer_reg_list[i]);
-
-	writel_relaxed(sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT - 2], sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_LO);
-	writel_relaxed(sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT - 1], sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_HI);
-}
-
-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,
-	.suspend = sirfsoc_clocksource_suspend,
-	.resume = sirfsoc_clocksource_resume,
-};
-
-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 */
-static u32 notrace sirfsoc_read_sched_clock(void)
-{
-	return (u32)(sirfsoc_timer_read(NULL) & 0xffffffff);
-}
-
-static void __init sirfsoc_clockevent_init(void)
-{
-	sirfsoc_clockevent.cpumask = cpumask_of(0);
-	clockevents_config_and_register(&sirfsoc_clockevent, CLOCK_TICK_RATE,
-					2, -2);
-}
-
-/* initialize the kernel jiffy timer source */
-void __init sirfsoc_prima2_timer_init(void)
-{
-	unsigned long rate;
-	struct clk *clk;
-
-	/* initialize clocking early, we want to set the OS timer */
-	sirfsoc_of_clk_init();
-
-	/* timer's input clock is io clock */
-	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);
-
-	sirfsoc_of_timer_map();
-
-	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));
-
-	setup_sched_clock(sirfsoc_read_sched_clock, 32, 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)
-		return;
-	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);
-}
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index 86eec41..0e74ba0 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -160,7 +160,6 @@ config MACH_XCEP
 	select MTD
 	select MTD_CFI
 	select MTD_CFI_INTELEXT
-	select MTD_CHAR
 	select MTD_PHYSMAP
 	select PXA25x
 	select SMC91X
diff --git a/arch/arm/mach-pxa/cpufreq-pxa2xx.c b/arch/arm/mach-pxa/cpufreq-pxa2xx.c
index 6a7aeab..f1ca4da 100644
--- a/arch/arm/mach-pxa/cpufreq-pxa2xx.c
+++ b/arch/arm/mach-pxa/cpufreq-pxa2xx.c
@@ -311,7 +311,6 @@ static int pxa_set_target(struct cpufreq_policy *policy,
 	new_freq_mem = pxa_freq_settings[idx].membus;
 	freqs.old = policy->cur;
 	freqs.new = new_freq_cpu;
-	freqs.cpu = policy->cpu;
 
 	if (freq_debug)
 		pr_debug("Changing CPU frequency to %d Mhz, (SDRAM %d Mhz)\n",
@@ -327,7 +326,7 @@ static int pxa_set_target(struct cpufreq_policy *policy,
 	 * you should add a notify client with any platform specific
 	 * Vcc changing capability
 	 */
-	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
 
 	/* Calculate the next MDREFR.  If we're slowing down the SDRAM clock
 	 * we need to preset the smaller DRI before the change.	 If we're
@@ -382,7 +381,7 @@ static int pxa_set_target(struct cpufreq_policy *policy,
 	 * you should add a notify client with any platform specific
 	 * SDRAM refresh timer adjustments
 	 */
-	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
 
 	/*
 	 * Even if voltage setting fails, we don't report it, as the frequency
diff --git a/arch/arm/mach-pxa/cpufreq-pxa3xx.c b/arch/arm/mach-pxa/cpufreq-pxa3xx.c
index b85b4ab..8c45b2b 100644
--- a/arch/arm/mach-pxa/cpufreq-pxa3xx.c
+++ b/arch/arm/mach-pxa/cpufreq-pxa3xx.c
@@ -184,7 +184,6 @@ static int pxa3xx_cpufreq_set(struct cpufreq_policy *policy,
 
 	freqs.old = policy->cur;
 	freqs.new = next->cpufreq_mhz * 1000;
-	freqs.cpu = policy->cpu;
 
 	pr_debug("CPU frequency from %d MHz to %d MHz%s\n",
 			freqs.old / 1000, freqs.new / 1000,
@@ -193,14 +192,14 @@ static int pxa3xx_cpufreq_set(struct cpufreq_policy *policy,
 	if (freqs.old == target_freq)
 		return 0;
 
-	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
 
 	local_irq_save(flags);
 	__update_core_freq(next);
 	__update_bus_freq(next);
 	local_irq_restore(flags);
 
-	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
 
 	return 0;
 }
diff --git a/arch/arm/mach-s3c24xx/Kconfig b/arch/arm/mach-s3c24xx/Kconfig
index 37f513d..f2f7088 100644
--- a/arch/arm/mach-s3c24xx/Kconfig
+++ b/arch/arm/mach-s3c24xx/Kconfig
@@ -30,29 +30,30 @@ config CPU_S3C2410
 	select S3C2410_CLOCK
 	select S3C2410_CPUFREQ if CPU_FREQ_S3C24XX
 	select S3C2410_PM if PM
+	select SAMSUNG_HRT
 	help
 	  Support for S3C2410 and S3C2410A family from the S3C24XX line
 	  of Samsung Mobile CPUs.
 
 config CPU_S3C2412
 	bool "SAMSUNG S3C2412"
-	depends on ARCH_S3C24XX
 	select CPU_ARM926T
 	select CPU_LLSERIAL_S3C2440
 	select S3C2412_DMA if S3C24XX_DMA
 	select S3C2412_PM if PM
+	select SAMSUNG_HRT
 	help
 	  Support for the S3C2412 and S3C2413 SoCs from the S3C24XX line
 
 config CPU_S3C2416
 	bool "SAMSUNG S3C2416/S3C2450"
-	depends on ARCH_S3C24XX
 	select CPU_ARM926T
 	select CPU_LLSERIAL_S3C2440
 	select S3C2416_PM if PM
 	select S3C2443_COMMON
 	select S3C2443_DMA if S3C24XX_DMA
 	select SAMSUNG_CLKSRC
+	select SAMSUNG_HRT
 	help
 	  Support for the S3C2416 SoC from the S3C24XX line
 
@@ -63,6 +64,7 @@ config CPU_S3C2440
 	select S3C2410_CLOCK
 	select S3C2410_PM if PM
 	select S3C2440_DMA if S3C24XX_DMA
+	select SAMSUNG_HRT
 	help
 	  Support for S3C2440 Samsung Mobile CPU based systems.
 
@@ -72,6 +74,7 @@ config CPU_S3C2442
 	select CPU_LLSERIAL_S3C2440
 	select S3C2410_CLOCK
 	select S3C2410_PM if PM
+	select SAMSUNG_HRT
 	help
 	  Support for S3C2442 Samsung Mobile CPU based systems.
 
@@ -81,12 +84,12 @@ config CPU_S3C244X
 
 config CPU_S3C2443
 	bool "SAMSUNG S3C2443"
-	depends on ARCH_S3C24XX
 	select CPU_ARM920T
 	select CPU_LLSERIAL_S3C2440
 	select S3C2443_COMMON
 	select S3C2443_DMA if S3C24XX_DMA
 	select SAMSUNG_CLKSRC
+	select SAMSUNG_HRT
 	help
 	  Support for the S3C2443 SoC from the S3C24XX line
 
@@ -133,7 +136,6 @@ config S3C24XX_SETUP_TS
 
 config S3C24XX_DMA
 	bool "S3C2410 DMA support"
-	depends on ARCH_S3C24XX
 	select S3C_DMA
 	help
 	  S3C2410 DMA support. This is needed for drivers like sound which
@@ -142,7 +144,7 @@ config S3C24XX_DMA
 
 config S3C2410_DMA_DEBUG
 	bool "S3C2410 DMA support debug"
-	depends on ARCH_S3C24XX && S3C2410_DMA
+	depends on S3C2410_DMA
 	help
 	  Enable debugging output for the DMA code. This option sends info
 	  to the kernel log, at priority KERN_DEBUG.
@@ -233,7 +235,7 @@ if CPU_S3C2410
 
 config S3C2410_CPUFREQ
 	bool
-	depends on CPU_FREQ_S3C24XX && CPU_S3C2410
+	depends on CPU_FREQ_S3C24XX
 	select S3C2410_CPUFREQ_UTILS
 	help
 	  CPU Frequency scaling support for S3C2410
@@ -320,7 +322,6 @@ config PM_H1940
 
 config MACH_N30
 	bool "Acer N30 family"
-	select MACH_N35
 	select S3C_DEV_NAND
 	select S3C_DEV_USB_HOST
 	help
@@ -380,14 +381,13 @@ if CPU_S3C2412
 
 config CPU_S3C2412_ONLY
 	bool
-	depends on ARCH_S3C24XX && !CPU_S3C2410 && \
-		   !CPU_S3C2416 && !CPU_S3C2440 && !CPU_S3C2442 && \
-		   !CPU_S3C2443 && CPU_S3C2412
+	depends on !CPU_S3C2410 && !CPU_S3C2416 && !CPU_S3C2440 && \
+		   !CPU_S3C2442 && !CPU_S3C2443
 	default y
 
 config S3C2412_CPUFREQ
 	bool
-	depends on CPU_FREQ_S3C24XX && CPU_S3C2412
+	depends on CPU_FREQ_S3C24XX
 	default y
 	select S3C2412_IOTIMING
 	help
@@ -401,6 +401,7 @@ config S3C2412_DMA
 config S3C2412_PM
 	bool
 	select S3C2412_PM_SLEEP
+	select SAMSUNG_WAKEMASK
 	help
 	  Internal config node to apply S3C2412 power management
 
@@ -642,7 +643,6 @@ comment "S3C2442 Boards"
 config MACH_NEO1973_GTA02
 	bool "Openmoko GTA02 / Freerunner phone"
 	select I2C
-	select MACH_NEO1973
 	select MFD_PCF50633
 	select PCF50633_GPIO
 	select POWER_SUPPLY
@@ -663,10 +663,7 @@ config MACH_RX1950
 	help
 	   Say Y here if you're using HP iPAQ rx1950
 
-config SMDK2440_CPU2442
-	bool "SMDM2440 with S3C2442 CPU module"
-
-endif	# CPU_S3C2440
+endif	# CPU_S3C2442
 
 if CPU_S3C2443 || CPU_S3C2416
 
diff --git a/arch/arm/mach-s3c24xx/Makefile b/arch/arm/mach-s3c24xx/Makefile
index af53d27..6f46ecf 100644
--- a/arch/arm/mach-s3c24xx/Makefile
+++ b/arch/arm/mach-s3c24xx/Makefile
@@ -14,7 +14,7 @@ obj-				:=
 
 # core
 
-obj-y				+= common.o irq.o
+obj-y				+= common.o
 
 obj-$(CONFIG_CPU_S3C2410)	+= s3c2410.o
 obj-$(CONFIG_S3C2410_CPUFREQ)	+= cpufreq-s3c2410.o
@@ -22,7 +22,7 @@ obj-$(CONFIG_S3C2410_DMA)	+= dma-s3c2410.o
 obj-$(CONFIG_S3C2410_PLL)	+= pll-s3c2410.o
 obj-$(CONFIG_S3C2410_PM)	+= pm-s3c2410.o sleep-s3c2410.o
 
-obj-$(CONFIG_CPU_S3C2412)	+= s3c2412.o irq-s3c2412.o clock-s3c2412.o
+obj-$(CONFIG_CPU_S3C2412)	+= s3c2412.o clock-s3c2412.o
 obj-$(CONFIG_S3C2412_CPUFREQ)	+= cpufreq-s3c2412.o
 obj-$(CONFIG_S3C2412_DMA)	+= dma-s3c2412.o
 obj-$(CONFIG_S3C2412_PM)	+= pm-s3c2412.o
@@ -31,9 +31,9 @@ obj-$(CONFIG_S3C2412_PM_SLEEP)	+= sleep-s3c2412.o
 obj-$(CONFIG_CPU_S3C2416)	+= s3c2416.o clock-s3c2416.o
 obj-$(CONFIG_S3C2416_PM)	+= pm-s3c2416.o
 
-obj-$(CONFIG_CPU_S3C2440)	+= s3c2440.o irq-s3c2440.o clock-s3c2440.o
+obj-$(CONFIG_CPU_S3C2440)	+= s3c2440.o clock-s3c2440.o
 obj-$(CONFIG_CPU_S3C2442)	+= s3c2442.o
-obj-$(CONFIG_CPU_S3C244X)	+= s3c244x.o irq-s3c244x.o clock-s3c244x.o
+obj-$(CONFIG_CPU_S3C244X)	+= s3c244x.o clock-s3c244x.o
 obj-$(CONFIG_S3C2440_CPUFREQ)	+= cpufreq-s3c2440.o
 obj-$(CONFIG_S3C2440_DMA)	+= dma-s3c2440.o
 obj-$(CONFIG_S3C2440_PLL_12000000) += pll-s3c2440-12000000.o
diff --git a/arch/arm/mach-s3c24xx/bast-irq.c b/arch/arm/mach-s3c24xx/bast-irq.c
index c0daa95..cb1b791 100644
--- a/arch/arm/mach-s3c24xx/bast-irq.c
+++ b/arch/arm/mach-s3c24xx/bast-irq.c
@@ -34,8 +34,6 @@
 #include <mach/hardware.h>
 #include <mach/regs-irq.h>
 
-#include <plat/irq.h>
-
 #include "bast.h"
 
 #define irqdbf(x...)
diff --git a/arch/arm/mach-s3c24xx/clock-s3c2410.c b/arch/arm/mach-s3c24xx/clock-s3c2410.c
index 641266f3..34fffdf 100644
--- a/arch/arm/mach-s3c24xx/clock-s3c2410.c
+++ b/arch/arm/mach-s3c24xx/clock-s3c2410.c
@@ -40,7 +40,6 @@
 #include <mach/regs-clock.h>
 #include <mach/regs-gpio.h>
 
-#include <plat/s3c2410.h>
 #include <plat/clock.h>
 #include <plat/cpu.h>
 
diff --git a/arch/arm/mach-s3c24xx/clock-s3c2412.c b/arch/arm/mach-s3c24xx/clock-s3c2412.c
index d10b695..2cc017d 100644
--- a/arch/arm/mach-s3c24xx/clock-s3c2412.c
+++ b/arch/arm/mach-s3c24xx/clock-s3c2412.c
@@ -41,7 +41,6 @@
 #include <mach/regs-clock.h>
 #include <mach/regs-gpio.h>
 
-#include <plat/s3c2412.h>
 #include <plat/clock.h>
 #include <plat/cpu.h>
 
diff --git a/arch/arm/mach-s3c24xx/clock-s3c2416.c b/arch/arm/mach-s3c24xx/clock-s3c2416.c
index 14a81c2..036056ce 100644
--- a/arch/arm/mach-s3c24xx/clock-s3c2416.c
+++ b/arch/arm/mach-s3c24xx/clock-s3c2416.c
@@ -14,7 +14,6 @@
 #include <linux/init.h>
 #include <linux/clk.h>
 
-#include <plat/s3c2416.h>
 #include <plat/clock.h>
 #include <plat/clock-clksrc.h>
 #include <plat/cpu.h>
diff --git a/arch/arm/mach-s3c24xx/clock-s3c2443.c b/arch/arm/mach-s3c24xx/clock-s3c2443.c
index bdaba59..0a53051 100644
--- a/arch/arm/mach-s3c24xx/clock-s3c2443.c
+++ b/arch/arm/mach-s3c24xx/clock-s3c2443.c
@@ -41,7 +41,6 @@
 
 #include <plat/cpu-freq.h>
 
-#include <plat/s3c2443.h>
 #include <plat/clock.h>
 #include <plat/clock-clksrc.h>
 #include <plat/cpu.h>
diff --git a/arch/arm/mach-s3c24xx/common-smdk.c b/arch/arm/mach-s3c24xx/common-smdk.c
index 3b2cf6d..404444d 100644
--- a/arch/arm/mach-s3c24xx/common-smdk.c
+++ b/arch/arm/mach-s3c24xx/common-smdk.c
@@ -41,11 +41,12 @@
 
 #include <linux/platform_data/mtd-nand-s3c2410.h>
 
-#include <plat/common-smdk.h>
 #include <plat/gpio-cfg.h>
 #include <plat/devs.h>
 #include <plat/pm.h>
 
+#include "common-smdk.h"
+
 /* LED devices */
 
 static struct s3c24xx_led_platdata smdk_pdata_led4 = {
diff --git a/arch/arm/mach-s3c24xx/common-smdk.h b/arch/arm/mach-s3c24xx/common-smdk.h
new file mode 100644
index 0000000..98f733e
--- /dev/null
+++ b/arch/arm/mach-s3c24xx/common-smdk.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Common code for SMDK2410 and SMDK2440 boards
+ *
+ * http://www.fluff.org/ben/smdk2440/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+extern void smdk_machine_init(void);
diff --git a/arch/arm/mach-s3c24xx/common.c b/arch/arm/mach-s3c24xx/common.c
index 6bcf87f..d97533d 100644
--- a/arch/arm/mach-s3c24xx/common.c
+++ b/arch/arm/mach-s3c24xx/common.c
@@ -47,14 +47,11 @@
 #include <plat/cpu.h>
 #include <plat/devs.h>
 #include <plat/clock.h>
-#include <plat/s3c2410.h>
-#include <plat/s3c2412.h>
-#include <plat/s3c2416.h>
-#include <plat/s3c244x.h>
-#include <plat/s3c2443.h>
 #include <plat/cpu-freq.h>
 #include <plat/pll.h>
 
+#include "common.h"
+
 /* table of supported CPUs */
 
 static const char name_s3c2410[]  = "S3C2410";
diff --git a/arch/arm/mach-s3c24xx/common.h b/arch/arm/mach-s3c24xx/common.h
index ed6276f..307c371 100644
--- a/arch/arm/mach-s3c24xx/common.h
+++ b/arch/arm/mach-s3c24xx/common.h
@@ -12,8 +12,98 @@
 #ifndef __ARCH_ARM_MACH_S3C24XX_COMMON_H
 #define __ARCH_ARM_MACH_S3C24XX_COMMON_H __FILE__
 
-void s3c2410_restart(char mode, const char *cmd);
-void s3c244x_restart(char mode, const char *cmd);
+struct s3c2410_uartcfg;
+
+#ifdef CONFIG_CPU_S3C2410
+extern  int s3c2410_init(void);
+extern  int s3c2410a_init(void);
+extern void s3c2410_map_io(void);
+extern void s3c2410_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+extern void s3c2410_init_clocks(int xtal);
+extern void s3c2410_restart(char mode, const char *cmd);
+extern void s3c2410_init_irq(void);
+#else
+#define s3c2410_init_clocks NULL
+#define s3c2410_init_uarts NULL
+#define s3c2410_map_io NULL
+#define s3c2410_init NULL
+#define s3c2410a_init NULL
+#endif
+
+#ifdef CONFIG_CPU_S3C2412
+extern  int s3c2412_init(void);
+extern void s3c2412_map_io(void);
+extern void s3c2412_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+extern void s3c2412_init_clocks(int xtal);
+extern  int s3c2412_baseclk_add(void);
+extern void s3c2412_restart(char mode, const char *cmd);
+extern void s3c2412_init_irq(void);
+#else
+#define s3c2412_init_clocks NULL
+#define s3c2412_init_uarts NULL
+#define s3c2412_map_io NULL
+#define s3c2412_init NULL
+#endif
+
+#ifdef CONFIG_CPU_S3C2416
+extern  int s3c2416_init(void);
+extern void s3c2416_map_io(void);
+extern void s3c2416_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+extern void s3c2416_init_clocks(int xtal);
+extern  int s3c2416_baseclk_add(void);
+extern void s3c2416_restart(char mode, const char *cmd);
+extern void s3c2416_init_irq(void);
+
+extern struct syscore_ops s3c2416_irq_syscore_ops;
+#else
+#define s3c2416_init_clocks NULL
+#define s3c2416_init_uarts NULL
+#define s3c2416_map_io NULL
+#define s3c2416_init NULL
+#endif
+
+#if defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2442)
+extern void s3c244x_map_io(void);
+extern void s3c244x_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+extern void s3c244x_init_clocks(int xtal);
+extern void s3c244x_restart(char mode, const char *cmd);
+#else
+#define s3c244x_init_clocks NULL
+#define s3c244x_init_uarts NULL
+#endif
+
+#ifdef CONFIG_CPU_S3C2440
+extern  int s3c2440_init(void);
+extern void s3c2440_map_io(void);
+extern void s3c2440_init_irq(void);
+#else
+#define s3c2440_init NULL
+#define s3c2440_map_io NULL
+#endif
+
+#ifdef CONFIG_CPU_S3C2442
+extern  int s3c2442_init(void);
+extern void s3c2442_map_io(void);
+extern void s3c2442_init_irq(void);
+#else
+#define s3c2442_init NULL
+#define s3c2442_map_io NULL
+#endif
+
+#ifdef CONFIG_CPU_S3C2443
+extern  int s3c2443_init(void);
+extern void s3c2443_map_io(void);
+extern void s3c2443_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+extern void s3c2443_init_clocks(int xtal);
+extern  int s3c2443_baseclk_add(void);
+extern void s3c2443_restart(char mode, const char *cmd);
+extern void s3c2443_init_irq(void);
+#else
+#define s3c2443_init_clocks NULL
+#define s3c2443_init_uarts NULL
+#define s3c2443_map_io NULL
+#define s3c2443_init NULL
+#endif
 
 extern struct syscore_ops s3c24xx_irq_syscore_ops;
 
diff --git a/arch/arm/mach-s3c24xx/cpufreq.c b/arch/arm/mach-s3c24xx/cpufreq.c
index 5f181e7..3c0e78e 100644
--- a/arch/arm/mach-s3c24xx/cpufreq.c
+++ b/arch/arm/mach-s3c24xx/cpufreq.c
@@ -204,7 +204,6 @@ static int s3c_cpufreq_settarget(struct cpufreq_policy *policy,
 	freqs.old = cpu_cur.freq;
 	freqs.new = cpu_new.freq;
 
-	freqs.freqs.cpu = 0;
 	freqs.freqs.old = cpu_cur.freq.armclk / 1000;
 	freqs.freqs.new = cpu_new.freq.armclk / 1000;
 
@@ -218,9 +217,7 @@ static int s3c_cpufreq_settarget(struct cpufreq_policy *policy,
 	s3c_cpufreq_updateclk(clk_pclk, cpu_new.freq.pclk);
 
 	/* start the frequency change */
-
-	if (policy)
-		cpufreq_notify_transition(&freqs.freqs, CPUFREQ_PRECHANGE);
+	cpufreq_notify_transition(policy, &freqs.freqs, CPUFREQ_PRECHANGE);
 
 	/* If hclk is staying the same, then we do not need to
 	 * re-write the IO or the refresh timings whilst we are changing
@@ -264,8 +261,7 @@ static int s3c_cpufreq_settarget(struct cpufreq_policy *policy,
 	local_irq_restore(flags);
 
 	/* notify everyone we've done this */
-	if (policy)
-		cpufreq_notify_transition(&freqs.freqs, CPUFREQ_POSTCHANGE);
+	cpufreq_notify_transition(policy, &freqs.freqs, CPUFREQ_POSTCHANGE);
 
 	s3c_freq_dbg("%s: finished\n", __func__);
 	return 0;
diff --git a/arch/arm/mach-s3c24xx/dma-s3c2410.c b/arch/arm/mach-s3c24xx/dma-s3c2410.c
index 25d085a..a6c94b8 100644
--- a/arch/arm/mach-s3c24xx/dma-s3c2410.c
+++ b/arch/arm/mach-s3c24xx/dma-s3c2410.c
@@ -28,7 +28,6 @@
 #include <plat/regs-ac97.h>
 #include <plat/regs-dma.h>
 #include <mach/regs-lcd.h>
-#include <mach/regs-sdi.h>
 #include <plat/regs-iis.h>
 #include <plat/regs-spi.h>
 
diff --git a/arch/arm/mach-s3c24xx/dma-s3c2412.c b/arch/arm/mach-s3c24xx/dma-s3c2412.c
index d2408ba..c0e8c3f 100644
--- a/arch/arm/mach-s3c24xx/dma-s3c2412.c
+++ b/arch/arm/mach-s3c24xx/dma-s3c2412.c
@@ -28,7 +28,6 @@
 #include <plat/regs-ac97.h>
 #include <plat/regs-dma.h>
 #include <mach/regs-lcd.h>
-#include <mach/regs-sdi.h>
 #include <plat/regs-iis.h>
 #include <plat/regs-spi.h>
 
diff --git a/arch/arm/mach-s3c24xx/dma-s3c2440.c b/arch/arm/mach-s3c24xx/dma-s3c2440.c
index 0b86e74..1c08eccd 100644
--- a/arch/arm/mach-s3c24xx/dma-s3c2440.c
+++ b/arch/arm/mach-s3c24xx/dma-s3c2440.c
@@ -28,7 +28,6 @@
 #include <plat/regs-ac97.h>
 #include <plat/regs-dma.h>
 #include <mach/regs-lcd.h>
-#include <mach/regs-sdi.h>
 #include <plat/regs-iis.h>
 #include <plat/regs-spi.h>
 
diff --git a/arch/arm/mach-s3c24xx/dma-s3c2443.c b/arch/arm/mach-s3c24xx/dma-s3c2443.c
index 0553625..000e4c6 100644
--- a/arch/arm/mach-s3c24xx/dma-s3c2443.c
+++ b/arch/arm/mach-s3c24xx/dma-s3c2443.c
@@ -28,7 +28,6 @@
 #include <plat/regs-ac97.h>
 #include <plat/regs-dma.h>
 #include <mach/regs-lcd.h>
-#include <mach/regs-sdi.h>
 #include <plat/regs-iis.h>
 #include <plat/regs-spi.h>
 
diff --git a/arch/arm/mach-s3c24xx/include/mach/entry-macro.S b/arch/arm/mach-s3c24xx/include/mach/entry-macro.S
deleted file mode 100644
index 6a21bee..0000000
--- a/arch/arm/mach-s3c24xx/include/mach/entry-macro.S
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * arch/arm/mach-s3c2410/include/mach/entry-macro.S
- *
- * Low-level IRQ helper macros for S3C2410-based platforms
- *
- * This file is licensed under  the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
-*/
-
-/* We have a problem that the INTOFFSET register does not always
- * show one interrupt. Occasionally we get two interrupts through
- * the prioritiser, and this causes the INTOFFSET register to show
- * what looks like the logical-or of the two interrupt numbers.
- *
- * Thanks to Klaus, Shannon, et al for helping to debug this problem
-*/
-
-#define INTPND		(0x10)
-#define INTOFFSET	(0x14)
-
-#include <mach/hardware.h>
-#include <asm/irq.h>
-
-	.macro  get_irqnr_preamble, base, tmp
-	.endm
-
-	.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
-
-		mov	\base, #S3C24XX_VA_IRQ
-
-		@@ try the interrupt offset register, since it is there
-
-		ldr	\irqstat, [\base, #INTPND ]
-		teq	\irqstat, #0
-		beq	1002f
-		ldr	\irqnr, [\base, #INTOFFSET ]
-		mov	\tmp, #1
-		tst	\irqstat, \tmp, lsl \irqnr
-		bne	1001f
-
-		@@ the number specified is not a valid irq, so try
-		@@ and work it out for ourselves
-
-		mov	\irqnr, #0		@@ start here
-
-		@@ work out which irq (if any) we got
-
-		movs	\tmp, \irqstat, lsl#16
-		addeq	\irqnr, \irqnr, #16
-		moveq	\irqstat, \irqstat, lsr#16
-		tst	\irqstat, #0xff
-		addeq	\irqnr, \irqnr, #8
-		moveq	\irqstat, \irqstat, lsr#8
-		tst	\irqstat, #0xf
-		addeq	\irqnr, \irqnr, #4
-		moveq	\irqstat, \irqstat, lsr#4
-		tst	\irqstat, #0x3
-		addeq	\irqnr, \irqnr, #2
-		moveq	\irqstat, \irqstat, lsr#2
-		tst	\irqstat, #0x1
-		addeq	\irqnr, \irqnr, #1
-
-		@@ we have the value
-1001:
-		adds	\irqnr, \irqnr, #IRQ_EINT0
-1002:
-		@@ exit here, Z flag unset if IRQ
-
-	.endm
diff --git a/arch/arm/mach-s3c24xx/include/mach/irqs.h b/arch/arm/mach-s3c24xx/include/mach/irqs.h
index b7a9f4d..43cada8 100644
--- a/arch/arm/mach-s3c24xx/include/mach/irqs.h
+++ b/arch/arm/mach-s3c24xx/include/mach/irqs.h
@@ -59,49 +59,53 @@
 #define IRQ_ADCPARENT  S3C2410_IRQ(31)
 
 /* interrupts generated from the external interrupts sources */
-#define IRQ_EINT4      S3C2410_IRQ(32)	   /* 48 */
-#define IRQ_EINT5      S3C2410_IRQ(33)
-#define IRQ_EINT6      S3C2410_IRQ(34)
-#define IRQ_EINT7      S3C2410_IRQ(35)
-#define IRQ_EINT8      S3C2410_IRQ(36)
-#define IRQ_EINT9      S3C2410_IRQ(37)
-#define IRQ_EINT10     S3C2410_IRQ(38)
-#define IRQ_EINT11     S3C2410_IRQ(39)
-#define IRQ_EINT12     S3C2410_IRQ(40)
-#define IRQ_EINT13     S3C2410_IRQ(41)
-#define IRQ_EINT14     S3C2410_IRQ(42)
-#define IRQ_EINT15     S3C2410_IRQ(43)
-#define IRQ_EINT16     S3C2410_IRQ(44)
-#define IRQ_EINT17     S3C2410_IRQ(45)
-#define IRQ_EINT18     S3C2410_IRQ(46)
-#define IRQ_EINT19     S3C2410_IRQ(47)
-#define IRQ_EINT20     S3C2410_IRQ(48)	   /* 64 */
-#define IRQ_EINT21     S3C2410_IRQ(49)
-#define IRQ_EINT22     S3C2410_IRQ(50)
-#define IRQ_EINT23     S3C2410_IRQ(51)
+#define IRQ_EINT0_2412 S3C2410_IRQ(32)
+#define IRQ_EINT1_2412 S3C2410_IRQ(33)
+#define IRQ_EINT2_2412 S3C2410_IRQ(34)
+#define IRQ_EINT3_2412 S3C2410_IRQ(35)
+#define IRQ_EINT4      S3C2410_IRQ(36)	   /* 52 */
+#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_EINT19     S3C2410_IRQ(51)
+#define IRQ_EINT20     S3C2410_IRQ(52)	   /* 68 */
+#define IRQ_EINT21     S3C2410_IRQ(53)
+#define IRQ_EINT22     S3C2410_IRQ(54)
+#define IRQ_EINT23     S3C2410_IRQ(55)
 
 #define IRQ_EINT_BIT(x)	((x) - IRQ_EINT4 + 4)
 #define IRQ_EINT(x)    (((x) >= 4) ? (IRQ_EINT4 + (x) - 4) : (IRQ_EINT0 + (x)))
 
-#define IRQ_LCD_FIFO   S3C2410_IRQ(52)
-#define IRQ_LCD_FRAME  S3C2410_IRQ(53)
+#define IRQ_LCD_FIFO   S3C2410_IRQ(56)
+#define IRQ_LCD_FRAME  S3C2410_IRQ(57)
 
 /* IRQs for the interal UARTs, and ADC
  * these need to be ordered in number of appearance in the
  * SUBSRC mask register
 */
 
-#define S3C2410_IRQSUB(x)	S3C2410_IRQ((x)+54)
+#define S3C2410_IRQSUB(x)	S3C2410_IRQ((x)+58)
 
-#define IRQ_S3CUART_RX0		S3C2410_IRQSUB(0)	/* 70 */
+#define IRQ_S3CUART_RX0		S3C2410_IRQSUB(0)	/* 74 */
 #define IRQ_S3CUART_TX0		S3C2410_IRQSUB(1)
 #define IRQ_S3CUART_ERR0	S3C2410_IRQSUB(2)
 
-#define IRQ_S3CUART_RX1		S3C2410_IRQSUB(3)	/* 73 */
+#define IRQ_S3CUART_RX1		S3C2410_IRQSUB(3)	/* 77 */
 #define IRQ_S3CUART_TX1		S3C2410_IRQSUB(4)
 #define IRQ_S3CUART_ERR1	S3C2410_IRQSUB(5)
 
-#define IRQ_S3CUART_RX2		S3C2410_IRQSUB(6)	/* 76 */
+#define IRQ_S3CUART_RX2		S3C2410_IRQSUB(6)	/* 80 */
 #define IRQ_S3CUART_TX2		S3C2410_IRQSUB(7)
 #define IRQ_S3CUART_ERR2	S3C2410_IRQSUB(8)
 
@@ -136,7 +140,7 @@
 
 /* second interrupt-register of s3c2416/s3c2450 */
 
-#define S3C2416_IRQ(x)		S3C2410_IRQ((x) + 54 + 29)
+#define S3C2416_IRQ(x)		S3C2410_IRQ((x) + 58 + 29)
 #define IRQ_S3C2416_2D		S3C2416_IRQ(0)
 #define IRQ_S3C2416_IIC1	S3C2416_IRQ(1)
 #define IRQ_S3C2416_RESERVED2	S3C2416_IRQ(2)
diff --git a/arch/arm/mach-s3c24xx/include/mach/regs-sdi.h b/arch/arm/mach-s3c24xx/include/mach/regs-sdi.h
deleted file mode 100644
index cbf2d88..0000000
--- a/arch/arm/mach-s3c24xx/include/mach/regs-sdi.h
+++ /dev/null
@@ -1,127 +0,0 @@
-/* arch/arm/mach-s3c2410/include/mach/regs-sdi.h
- *
- * Copyright (c) 2004 Simtec Electronics <linux@simtec.co.uk>
- *		      http://www.simtec.co.uk/products/SWLINUX/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * S3C2410 MMC/SDIO register definitions
-*/
-
-#ifndef __ASM_ARM_REGS_SDI
-#define __ASM_ARM_REGS_SDI "regs-sdi.h"
-
-#define S3C2410_SDICON                (0x00)
-#define S3C2410_SDIPRE                (0x04)
-#define S3C2410_SDICMDARG             (0x08)
-#define S3C2410_SDICMDCON             (0x0C)
-#define S3C2410_SDICMDSTAT            (0x10)
-#define S3C2410_SDIRSP0               (0x14)
-#define S3C2410_SDIRSP1               (0x18)
-#define S3C2410_SDIRSP2               (0x1C)
-#define S3C2410_SDIRSP3               (0x20)
-#define S3C2410_SDITIMER              (0x24)
-#define S3C2410_SDIBSIZE              (0x28)
-#define S3C2410_SDIDCON               (0x2C)
-#define S3C2410_SDIDCNT               (0x30)
-#define S3C2410_SDIDSTA               (0x34)
-#define S3C2410_SDIFSTA               (0x38)
-
-#define S3C2410_SDIDATA               (0x3C)
-#define S3C2410_SDIIMSK               (0x40)
-
-#define S3C2440_SDIDATA               (0x40)
-#define S3C2440_SDIIMSK               (0x3C)
-
-#define S3C2440_SDICON_SDRESET        (1<<8)
-#define S3C2440_SDICON_MMCCLOCK       (1<<5)
-#define S3C2410_SDICON_BYTEORDER      (1<<4)
-#define S3C2410_SDICON_SDIOIRQ        (1<<3)
-#define S3C2410_SDICON_RWAITEN        (1<<2)
-#define S3C2410_SDICON_FIFORESET      (1<<1)
-#define S3C2410_SDICON_CLOCKTYPE      (1<<0)
-
-#define S3C2410_SDICMDCON_ABORT       (1<<12)
-#define S3C2410_SDICMDCON_WITHDATA    (1<<11)
-#define S3C2410_SDICMDCON_LONGRSP     (1<<10)
-#define S3C2410_SDICMDCON_WAITRSP     (1<<9)
-#define S3C2410_SDICMDCON_CMDSTART    (1<<8)
-#define S3C2410_SDICMDCON_SENDERHOST  (1<<6)
-#define S3C2410_SDICMDCON_INDEX       (0x3f)
-
-#define S3C2410_SDICMDSTAT_CRCFAIL    (1<<12)
-#define S3C2410_SDICMDSTAT_CMDSENT    (1<<11)
-#define S3C2410_SDICMDSTAT_CMDTIMEOUT (1<<10)
-#define S3C2410_SDICMDSTAT_RSPFIN     (1<<9)
-#define S3C2410_SDICMDSTAT_XFERING    (1<<8)
-#define S3C2410_SDICMDSTAT_INDEX      (0xff)
-
-#define S3C2440_SDIDCON_DS_BYTE       (0<<22)
-#define S3C2440_SDIDCON_DS_HALFWORD   (1<<22)
-#define S3C2440_SDIDCON_DS_WORD       (2<<22)
-#define S3C2410_SDIDCON_IRQPERIOD     (1<<21)
-#define S3C2410_SDIDCON_TXAFTERRESP   (1<<20)
-#define S3C2410_SDIDCON_RXAFTERCMD    (1<<19)
-#define S3C2410_SDIDCON_BUSYAFTERCMD  (1<<18)
-#define S3C2410_SDIDCON_BLOCKMODE     (1<<17)
-#define S3C2410_SDIDCON_WIDEBUS       (1<<16)
-#define S3C2410_SDIDCON_DMAEN         (1<<15)
-#define S3C2410_SDIDCON_STOP          (1<<14)
-#define S3C2440_SDIDCON_DATSTART      (1<<14)
-#define S3C2410_SDIDCON_DATMODE	      (3<<12)
-#define S3C2410_SDIDCON_BLKNUM        (0x7ff)
-
-/* constants for S3C2410_SDIDCON_DATMODE */
-#define S3C2410_SDIDCON_XFER_READY    (0<<12)
-#define S3C2410_SDIDCON_XFER_CHKSTART (1<<12)
-#define S3C2410_SDIDCON_XFER_RXSTART  (2<<12)
-#define S3C2410_SDIDCON_XFER_TXSTART  (3<<12)
-
-#define S3C2410_SDIDCON_BLKNUM_MASK   (0xFFF)
-#define S3C2410_SDIDCNT_BLKNUM_SHIFT  (12)
-
-#define S3C2410_SDIDSTA_RDYWAITREQ    (1<<10)
-#define S3C2410_SDIDSTA_SDIOIRQDETECT (1<<9)
-#define S3C2410_SDIDSTA_FIFOFAIL      (1<<8)	/* reserved on 2440 */
-#define S3C2410_SDIDSTA_CRCFAIL       (1<<7)
-#define S3C2410_SDIDSTA_RXCRCFAIL     (1<<6)
-#define S3C2410_SDIDSTA_DATATIMEOUT   (1<<5)
-#define S3C2410_SDIDSTA_XFERFINISH    (1<<4)
-#define S3C2410_SDIDSTA_BUSYFINISH    (1<<3)
-#define S3C2410_SDIDSTA_SBITERR       (1<<2)	/* reserved on 2410a/2440 */
-#define S3C2410_SDIDSTA_TXDATAON      (1<<1)
-#define S3C2410_SDIDSTA_RXDATAON      (1<<0)
-
-#define S3C2440_SDIFSTA_FIFORESET      (1<<16)
-#define S3C2440_SDIFSTA_FIFOFAIL       (3<<14)  /* 3 is correct (2 bits) */
-#define S3C2410_SDIFSTA_TFDET          (1<<13)
-#define S3C2410_SDIFSTA_RFDET          (1<<12)
-#define S3C2410_SDIFSTA_TFHALF         (1<<11)
-#define S3C2410_SDIFSTA_TFEMPTY        (1<<10)
-#define S3C2410_SDIFSTA_RFLAST         (1<<9)
-#define S3C2410_SDIFSTA_RFFULL         (1<<8)
-#define S3C2410_SDIFSTA_RFHALF         (1<<7)
-#define S3C2410_SDIFSTA_COUNTMASK      (0x7f)
-
-#define S3C2410_SDIIMSK_RESPONSECRC    (1<<17)
-#define S3C2410_SDIIMSK_CMDSENT        (1<<16)
-#define S3C2410_SDIIMSK_CMDTIMEOUT     (1<<15)
-#define S3C2410_SDIIMSK_RESPONSEND     (1<<14)
-#define S3C2410_SDIIMSK_READWAIT       (1<<13)
-#define S3C2410_SDIIMSK_SDIOIRQ        (1<<12)
-#define S3C2410_SDIIMSK_FIFOFAIL       (1<<11)
-#define S3C2410_SDIIMSK_CRCSTATUS      (1<<10)
-#define S3C2410_SDIIMSK_DATACRC        (1<<9)
-#define S3C2410_SDIIMSK_DATATIMEOUT    (1<<8)
-#define S3C2410_SDIIMSK_DATAFINISH     (1<<7)
-#define S3C2410_SDIIMSK_BUSYFINISH     (1<<6)
-#define S3C2410_SDIIMSK_SBITERR        (1<<5)	/* reserved 2440/2410a */
-#define S3C2410_SDIIMSK_TXFIFOHALF     (1<<4)
-#define S3C2410_SDIIMSK_TXFIFOEMPTY    (1<<3)
-#define S3C2410_SDIIMSK_RXFIFOLAST     (1<<2)
-#define S3C2410_SDIIMSK_RXFIFOFULL     (1<<1)
-#define S3C2410_SDIIMSK_RXFIFOHALF     (1<<0)
-
-#endif /* __ASM_ARM_REGS_SDI */
diff --git a/arch/arm/mach-s3c24xx/irq-pm.c b/arch/arm/mach-s3c24xx/irq-pm.c
index e119959..b91341e 100644
--- a/arch/arm/mach-s3c24xx/irq-pm.c
+++ b/arch/arm/mach-s3c24xx/irq-pm.c
@@ -16,10 +16,15 @@
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/syscore_ops.h>
+#include <linux/io.h>
 
 #include <plat/cpu.h>
 #include <plat/pm.h>
-#include <plat/irq.h>
+#include <plat/map-base.h>
+#include <plat/map-s3c.h>
+
+#include <mach/regs-irq.h>
+#include <mach/regs-gpio.h>
 
 #include <asm/irq.h>
 
diff --git a/arch/arm/mach-s3c24xx/irq-s3c2412.c b/arch/arm/mach-s3c24xx/irq-s3c2412.c
deleted file mode 100644
index 67d7631..0000000
--- a/arch/arm/mach-s3c24xx/irq-s3c2412.c
+++ /dev/null
@@ -1,215 +0,0 @@
-/* linux/arch/arm/mach-s3c2412/irq.c
- *
- * Copyright (c) 2006 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
-*/
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/device.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <asm/irq.h>
-
-#include <asm/mach/irq.h>
-
-#include <mach/regs-irq.h>
-#include <mach/regs-gpio.h>
-
-#include <plat/cpu.h>
-#include <plat/irq.h>
-#include <plat/pm.h>
-
-#include "s3c2412-power.h"
-
-#define INTMSK(start, end) ((1 << ((end) + 1 - (start))) - 1)
-#define INTMSK_SUB(start, end) (INTMSK(start, end) << ((start - S3C2410_IRQSUB(0))))
-
-/* the s3c2412 changes the behaviour of IRQ_EINT0 through IRQ_EINT3 by
- * having them turn up in both the INT* and the EINT* registers. Whilst
- * both show the status, they both now need to be acked when the IRQs
- * go off.
-*/
-
-static void
-s3c2412_irq_mask(struct irq_data *data)
-{
-	unsigned long bitval = 1UL << (data->irq - IRQ_EINT0);
-	unsigned long mask;
-
-	mask = __raw_readl(S3C2410_INTMSK);
-	__raw_writel(mask | bitval, S3C2410_INTMSK);
-
-	mask = __raw_readl(S3C2412_EINTMASK);
-	__raw_writel(mask | bitval, S3C2412_EINTMASK);
-}
-
-static inline void
-s3c2412_irq_ack(struct irq_data *data)
-{
-	unsigned long bitval = 1UL << (data->irq - IRQ_EINT0);
-
-	__raw_writel(bitval, S3C2412_EINTPEND);
-	__raw_writel(bitval, S3C2410_SRCPND);
-	__raw_writel(bitval, S3C2410_INTPND);
-}
-
-static inline void
-s3c2412_irq_maskack(struct irq_data *data)
-{
-	unsigned long bitval = 1UL << (data->irq - IRQ_EINT0);
-	unsigned long mask;
-
-	mask = __raw_readl(S3C2410_INTMSK);
-	__raw_writel(mask|bitval, S3C2410_INTMSK);
-
-	mask = __raw_readl(S3C2412_EINTMASK);
-	__raw_writel(mask | bitval, S3C2412_EINTMASK);
-
-	__raw_writel(bitval, S3C2412_EINTPEND);
-	__raw_writel(bitval, S3C2410_SRCPND);
-	__raw_writel(bitval, S3C2410_INTPND);
-}
-
-static void
-s3c2412_irq_unmask(struct irq_data *data)
-{
-	unsigned long bitval = 1UL << (data->irq - IRQ_EINT0);
-	unsigned long mask;
-
-	mask = __raw_readl(S3C2412_EINTMASK);
-	__raw_writel(mask & ~bitval, S3C2412_EINTMASK);
-
-	mask = __raw_readl(S3C2410_INTMSK);
-	__raw_writel(mask & ~bitval, S3C2410_INTMSK);
-}
-
-static struct irq_chip s3c2412_irq_eint0t4 = {
-	.irq_ack	= s3c2412_irq_ack,
-	.irq_mask	= s3c2412_irq_mask,
-	.irq_unmask	= s3c2412_irq_unmask,
-	.irq_set_wake	= s3c_irq_wake,
-	.irq_set_type	= s3c_irqext_type,
-};
-
-#define INTBIT(x)	(1 << ((x) - S3C2410_IRQSUB(0)))
-
-/* CF and SDI sub interrupts */
-
-static void s3c2412_irq_demux_cfsdi(unsigned int irq, struct irq_desc *desc)
-{
-	unsigned int subsrc, submsk;
-
-	subsrc = __raw_readl(S3C2410_SUBSRCPND);
-	submsk = __raw_readl(S3C2410_INTSUBMSK);
-
-	subsrc  &= ~submsk;
-
-	if (subsrc & INTBIT(IRQ_S3C2412_SDI))
-		generic_handle_irq(IRQ_S3C2412_SDI);
-
-	if (subsrc & INTBIT(IRQ_S3C2412_CF))
-		generic_handle_irq(IRQ_S3C2412_CF);
-}
-
-#define INTMSK_CFSDI	(1UL << (IRQ_S3C2412_CFSDI - IRQ_EINT0))
-#define SUBMSK_CFSDI	INTMSK_SUB(IRQ_S3C2412_SDI, IRQ_S3C2412_CF)
-
-static void s3c2412_irq_cfsdi_mask(struct irq_data *data)
-{
-	s3c_irqsub_mask(data->irq, INTMSK_CFSDI, SUBMSK_CFSDI);
-}
-
-static void s3c2412_irq_cfsdi_unmask(struct irq_data *data)
-{
-	s3c_irqsub_unmask(data->irq, INTMSK_CFSDI);
-}
-
-static void s3c2412_irq_cfsdi_ack(struct irq_data *data)
-{
-	s3c_irqsub_maskack(data->irq, INTMSK_CFSDI, SUBMSK_CFSDI);
-}
-
-static struct irq_chip s3c2412_irq_cfsdi = {
-	.name		= "s3c2412-cfsdi",
-	.irq_ack	= s3c2412_irq_cfsdi_ack,
-	.irq_mask	= s3c2412_irq_cfsdi_mask,
-	.irq_unmask	= s3c2412_irq_cfsdi_unmask,
-};
-
-static int s3c2412_irq_rtc_wake(struct irq_data *data, unsigned int state)
-{
-	unsigned long pwrcfg;
-
-	pwrcfg = __raw_readl(S3C2412_PWRCFG);
-	if (state)
-		pwrcfg &= ~S3C2412_PWRCFG_RTC_MASKIRQ;
-	else
-		pwrcfg |= S3C2412_PWRCFG_RTC_MASKIRQ;
-	__raw_writel(pwrcfg, S3C2412_PWRCFG);
-
-	return s3c_irq_chip.irq_set_wake(data, state);
-}
-
-static struct irq_chip s3c2412_irq_rtc_chip;
-
-static int s3c2412_irq_add(struct device *dev, struct subsys_interface *sif)
-{
-	unsigned int irqno;
-
-	for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) {
-		irq_set_chip_and_handler(irqno, &s3c2412_irq_eint0t4,
-					 handle_edge_irq);
-		set_irq_flags(irqno, IRQF_VALID);
-	}
-
-	/* add demux support for CF/SDI */
-
-	irq_set_chained_handler(IRQ_S3C2412_CFSDI, s3c2412_irq_demux_cfsdi);
-
-	for (irqno = IRQ_S3C2412_SDI; irqno <= IRQ_S3C2412_CF; irqno++) {
-		irq_set_chip_and_handler(irqno, &s3c2412_irq_cfsdi,
-					 handle_level_irq);
-		set_irq_flags(irqno, IRQF_VALID);
-	}
-
-	/* change RTC IRQ's set wake method */
-
-	s3c2412_irq_rtc_chip = s3c_irq_chip;
-	s3c2412_irq_rtc_chip.irq_set_wake = s3c2412_irq_rtc_wake;
-
-	irq_set_chip(IRQ_RTC, &s3c2412_irq_rtc_chip);
-
-	return 0;
-}
-
-static struct subsys_interface s3c2412_irq_interface = {
-	.name		= "s3c2412_irq",
-	.subsys		= &s3c2412_subsys,
-	.add_dev	= s3c2412_irq_add,
-};
-
-static int s3c2412_irq_init(void)
-{
-	return subsys_interface_register(&s3c2412_irq_interface);
-}
-
-arch_initcall(s3c2412_irq_init);
diff --git a/arch/arm/mach-s3c24xx/irq-s3c2440.c b/arch/arm/mach-s3c24xx/irq-s3c2440.c
deleted file mode 100644
index 4a18cde..0000000
--- a/arch/arm/mach-s3c24xx/irq-s3c2440.c
+++ /dev/null
@@ -1,128 +0,0 @@
-/* linux/arch/arm/mach-s3c2440/irq.c
- *
- * Copyright (c) 2003-2004 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
-*/
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/device.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <asm/irq.h>
-
-#include <asm/mach/irq.h>
-
-#include <mach/regs-irq.h>
-#include <mach/regs-gpio.h>
-
-#include <plat/cpu.h>
-#include <plat/pm.h>
-#include <plat/irq.h>
-
-/* WDT/AC97 */
-
-static void s3c_irq_demux_wdtac97(unsigned int irq,
-				  struct irq_desc *desc)
-{
-	unsigned int subsrc, submsk;
-
-	/* read the current pending interrupts, and the mask
-	 * for what it is available */
-
-	subsrc = __raw_readl(S3C2410_SUBSRCPND);
-	submsk = __raw_readl(S3C2410_INTSUBMSK);
-
-	subsrc &= ~submsk;
-	subsrc >>= 13;
-	subsrc &= 3;
-
-	if (subsrc != 0) {
-		if (subsrc & 1) {
-			generic_handle_irq(IRQ_S3C2440_WDT);
-		}
-		if (subsrc & 2) {
-			generic_handle_irq(IRQ_S3C2440_AC97);
-		}
-	}
-}
-
-
-#define INTMSK_WDT	 (1UL << (IRQ_WDT - IRQ_EINT0))
-
-static void
-s3c_irq_wdtac97_mask(struct irq_data *data)
-{
-	s3c_irqsub_mask(data->irq, INTMSK_WDT, 3 << 13);
-}
-
-static void
-s3c_irq_wdtac97_unmask(struct irq_data *data)
-{
-	s3c_irqsub_unmask(data->irq, INTMSK_WDT);
-}
-
-static void
-s3c_irq_wdtac97_ack(struct irq_data *data)
-{
-	s3c_irqsub_maskack(data->irq, INTMSK_WDT, 3 << 13);
-}
-
-static struct irq_chip s3c_irq_wdtac97 = {
-	.irq_mask	= s3c_irq_wdtac97_mask,
-	.irq_unmask	= s3c_irq_wdtac97_unmask,
-	.irq_ack	= s3c_irq_wdtac97_ack,
-};
-
-static int s3c2440_irq_add(struct device *dev, struct subsys_interface *sif)
-{
-	unsigned int irqno;
-
-	printk("S3C2440: IRQ Support\n");
-
-	/* add new chained handler for wdt, ac7 */
-
-	irq_set_chip_and_handler(IRQ_WDT, &s3c_irq_level_chip,
-				 handle_level_irq);
-	irq_set_chained_handler(IRQ_WDT, s3c_irq_demux_wdtac97);
-
-	for (irqno = IRQ_S3C2440_WDT; irqno <= IRQ_S3C2440_AC97; irqno++) {
-		irq_set_chip_and_handler(irqno, &s3c_irq_wdtac97,
-					 handle_level_irq);
-		set_irq_flags(irqno, IRQF_VALID);
-	}
-
-	return 0;
-}
-
-static struct subsys_interface s3c2440_irq_interface = {
-	.name		= "s3c2440_irq",
-	.subsys		= &s3c2440_subsys,
-	.add_dev	= s3c2440_irq_add,
-};
-
-static int s3c2440_irq_init(void)
-{
-	return subsys_interface_register(&s3c2440_irq_interface);
-}
-
-arch_initcall(s3c2440_irq_init);
-
diff --git a/arch/arm/mach-s3c24xx/irq-s3c244x.c b/arch/arm/mach-s3c24xx/irq-s3c244x.c
deleted file mode 100644
index 5fe8e58..0000000
--- a/arch/arm/mach-s3c24xx/irq-s3c244x.c
+++ /dev/null
@@ -1,142 +0,0 @@
-/* linux/arch/arm/plat-s3c24xx/s3c244x-irq.c
- *
- * Copyright (c) 2003-2004 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
-*/
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/device.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <asm/irq.h>
-
-#include <asm/mach/irq.h>
-
-#include <mach/regs-irq.h>
-#include <mach/regs-gpio.h>
-
-#include <plat/cpu.h>
-#include <plat/pm.h>
-#include <plat/irq.h>
-
-/* camera irq */
-
-static void s3c_irq_demux_cam(unsigned int irq,
-			      struct irq_desc *desc)
-{
-	unsigned int subsrc, submsk;
-
-	/* read the current pending interrupts, and the mask
-	 * for what it is available */
-
-	subsrc = __raw_readl(S3C2410_SUBSRCPND);
-	submsk = __raw_readl(S3C2410_INTSUBMSK);
-
-	subsrc &= ~submsk;
-	subsrc >>= 11;
-	subsrc &= 3;
-
-	if (subsrc != 0) {
-		if (subsrc & 1) {
-			generic_handle_irq(IRQ_S3C2440_CAM_C);
-		}
-		if (subsrc & 2) {
-			generic_handle_irq(IRQ_S3C2440_CAM_P);
-		}
-	}
-}
-
-#define INTMSK_CAM (1UL << (IRQ_CAM - IRQ_EINT0))
-
-static void
-s3c_irq_cam_mask(struct irq_data *data)
-{
-	s3c_irqsub_mask(data->irq, INTMSK_CAM, 3 << 11);
-}
-
-static void
-s3c_irq_cam_unmask(struct irq_data *data)
-{
-	s3c_irqsub_unmask(data->irq, INTMSK_CAM);
-}
-
-static void
-s3c_irq_cam_ack(struct irq_data *data)
-{
-	s3c_irqsub_maskack(data->irq, INTMSK_CAM, 3 << 11);
-}
-
-static struct irq_chip s3c_irq_cam = {
-	.irq_mask	= s3c_irq_cam_mask,
-	.irq_unmask	= s3c_irq_cam_unmask,
-	.irq_ack	= s3c_irq_cam_ack,
-};
-
-static int s3c244x_irq_add(struct device *dev, struct subsys_interface *sif)
-{
-	unsigned int irqno;
-
-	irq_set_chip_and_handler(IRQ_NFCON, &s3c_irq_level_chip,
-				 handle_level_irq);
-	set_irq_flags(IRQ_NFCON, IRQF_VALID);
-
-	/* add chained handler for camera */
-
-	irq_set_chip_and_handler(IRQ_CAM, &s3c_irq_level_chip,
-				 handle_level_irq);
-	irq_set_chained_handler(IRQ_CAM, s3c_irq_demux_cam);
-
-	for (irqno = IRQ_S3C2440_CAM_C; irqno <= IRQ_S3C2440_CAM_P; irqno++) {
-		irq_set_chip_and_handler(irqno, &s3c_irq_cam,
-					 handle_level_irq);
-		set_irq_flags(irqno, IRQF_VALID);
-	}
-
-	return 0;
-}
-
-static struct subsys_interface s3c2440_irq_interface = {
-	.name		= "s3c2440_irq",
-	.subsys		= &s3c2440_subsys,
-	.add_dev	= s3c244x_irq_add,
-};
-
-static int s3c2440_irq_init(void)
-{
-	return subsys_interface_register(&s3c2440_irq_interface);
-}
-
-arch_initcall(s3c2440_irq_init);
-
-static struct subsys_interface s3c2442_irq_interface = {
-	.name		= "s3c2442_irq",
-	.subsys		= &s3c2442_subsys,
-	.add_dev	= s3c244x_irq_add,
-};
-
-
-static int s3c2442_irq_init(void)
-{
-	return subsys_interface_register(&s3c2442_irq_interface);
-}
-
-arch_initcall(s3c2442_irq_init);
diff --git a/arch/arm/mach-s3c24xx/irq.c b/arch/arm/mach-s3c24xx/irq.c
deleted file mode 100644
index cb9f5e0..0000000
--- a/arch/arm/mach-s3c24xx/irq.c
+++ /dev/null
@@ -1,822 +0,0 @@
-/*
- * S3C24XX IRQ handling
- *
- * Copyright (c) 2003-2004 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- * Copyright (c) 2012 Heiko Stuebner <heiko@sntech.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.
-*/
-
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/io.h>
-#include <linux/err.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/device.h>
-#include <linux/irqdomain.h>
-
-#include <asm/mach/irq.h>
-
-#include <mach/regs-irq.h>
-#include <mach/regs-gpio.h>
-
-#include <plat/cpu.h>
-#include <plat/regs-irqtype.h>
-#include <plat/pm.h>
-#include <plat/irq.h>
-
-#define S3C_IRQTYPE_NONE	0
-#define S3C_IRQTYPE_EINT	1
-#define S3C_IRQTYPE_EDGE	2
-#define S3C_IRQTYPE_LEVEL	3
-
-struct s3c_irq_data {
-	unsigned int type;
-	unsigned long parent_irq;
-
-	/* data gets filled during init */
-	struct s3c_irq_intc *intc;
-	unsigned long sub_bits;
-	struct s3c_irq_intc *sub_intc;
-};
-
-/*
- * Sructure holding the controller data
- * @reg_pending		register holding pending irqs
- * @reg_intpnd		special register intpnd in main intc
- * @reg_mask		mask register
- * @domain		irq_domain of the controller
- * @parent		parent controller for ext and sub irqs
- * @irqs		irq-data, always s3c_irq_data[32]
- */
-struct s3c_irq_intc {
-	void __iomem		*reg_pending;
-	void __iomem		*reg_intpnd;
-	void __iomem		*reg_mask;
-	struct irq_domain	*domain;
-	struct s3c_irq_intc	*parent;
-	struct s3c_irq_data	*irqs;
-};
-
-static void s3c_irq_mask(struct irq_data *data)
-{
-	struct s3c_irq_intc *intc = data->domain->host_data;
-	struct s3c_irq_intc *parent_intc = intc->parent;
-	struct s3c_irq_data *irq_data = &intc->irqs[data->hwirq];
-	struct s3c_irq_data *parent_data;
-	unsigned long mask;
-	unsigned int irqno;
-
-	mask = __raw_readl(intc->reg_mask);
-	mask |= (1UL << data->hwirq);
-	__raw_writel(mask, intc->reg_mask);
-
-	if (parent_intc && irq_data->parent_irq) {
-		parent_data = &parent_intc->irqs[irq_data->parent_irq];
-
-		/* check to see if we need to mask the parent IRQ */
-		if ((mask & parent_data->sub_bits) == parent_data->sub_bits) {
-			irqno = irq_find_mapping(parent_intc->domain,
-					 irq_data->parent_irq);
-			s3c_irq_mask(irq_get_irq_data(irqno));
-		}
-	}
-}
-
-static void s3c_irq_unmask(struct irq_data *data)
-{
-	struct s3c_irq_intc *intc = data->domain->host_data;
-	struct s3c_irq_intc *parent_intc = intc->parent;
-	struct s3c_irq_data *irq_data = &intc->irqs[data->hwirq];
-	unsigned long mask;
-	unsigned int irqno;
-
-	mask = __raw_readl(intc->reg_mask);
-	mask &= ~(1UL << data->hwirq);
-	__raw_writel(mask, intc->reg_mask);
-
-	if (parent_intc && irq_data->parent_irq) {
-		irqno = irq_find_mapping(parent_intc->domain,
-					 irq_data->parent_irq);
-		s3c_irq_unmask(irq_get_irq_data(irqno));
-	}
-}
-
-static inline void s3c_irq_ack(struct irq_data *data)
-{
-	struct s3c_irq_intc *intc = data->domain->host_data;
-	unsigned long bitval = 1UL << data->hwirq;
-
-	__raw_writel(bitval, intc->reg_pending);
-	if (intc->reg_intpnd)
-		__raw_writel(bitval, intc->reg_intpnd);
-}
-
-static int s3c_irqext_type_set(void __iomem *gpcon_reg,
-			       void __iomem *extint_reg,
-			       unsigned long gpcon_offset,
-			       unsigned long extint_offset,
-			       unsigned int type)
-{
-	unsigned long newvalue = 0, value;
-
-	/* Set the GPIO to external interrupt mode */
-	value = __raw_readl(gpcon_reg);
-	value = (value & ~(3 << gpcon_offset)) | (0x02 << gpcon_offset);
-	__raw_writel(value, gpcon_reg);
-
-	/* Set the external interrupt to pointed trigger type */
-	switch (type)
-	{
-		case IRQ_TYPE_NONE:
-			pr_warn("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:
-			pr_err("No such irq type %d", type);
-			return -EINVAL;
-	}
-
-	value = __raw_readl(extint_reg);
-	value = (value & ~(7 << extint_offset)) | (newvalue << extint_offset);
-	__raw_writel(value, extint_reg);
-
-	return 0;
-}
-
-/* FIXME: make static when it's out of plat-samsung/irq.h */
-int s3c_irqext_type(struct irq_data *data, unsigned int type)
-{
-	void __iomem *extint_reg;
-	void __iomem *gpcon_reg;
-	unsigned long gpcon_offset, extint_offset;
-
-	if ((data->hwirq >= 4) && (data->hwirq <= 7)) {
-		gpcon_reg = S3C2410_GPFCON;
-		extint_reg = S3C24XX_EXTINT0;
-		gpcon_offset = (data->hwirq) * 2;
-		extint_offset = (data->hwirq) * 4;
-	} else if ((data->hwirq >= 8) && (data->hwirq <= 15)) {
-		gpcon_reg = S3C2410_GPGCON;
-		extint_reg = S3C24XX_EXTINT1;
-		gpcon_offset = (data->hwirq - 8) * 2;
-		extint_offset = (data->hwirq - 8) * 4;
-	} else if ((data->hwirq >= 16) && (data->hwirq <= 23)) {
-		gpcon_reg = S3C2410_GPGCON;
-		extint_reg = S3C24XX_EXTINT2;
-		gpcon_offset = (data->hwirq - 8) * 2;
-		extint_offset = (data->hwirq - 16) * 4;
-	} else {
-		return -EINVAL;
-	}
-
-	return s3c_irqext_type_set(gpcon_reg, extint_reg, gpcon_offset,
-				   extint_offset, type);
-}
-
-static int s3c_irqext0_type(struct irq_data *data, unsigned int type)
-{
-	void __iomem *extint_reg;
-	void __iomem *gpcon_reg;
-	unsigned long gpcon_offset, extint_offset;
-
-	if ((data->hwirq >= 0) && (data->hwirq <= 3)) {
-		gpcon_reg = S3C2410_GPFCON;
-		extint_reg = S3C24XX_EXTINT0;
-		gpcon_offset = (data->hwirq) * 2;
-		extint_offset = (data->hwirq) * 4;
-	} else {
-		return -EINVAL;
-	}
-
-	return s3c_irqext_type_set(gpcon_reg, extint_reg, gpcon_offset,
-				   extint_offset, type);
-}
-
-struct irq_chip s3c_irq_chip = {
-	.name		= "s3c",
-	.irq_ack	= s3c_irq_ack,
-	.irq_mask	= s3c_irq_mask,
-	.irq_unmask	= s3c_irq_unmask,
-	.irq_set_wake	= s3c_irq_wake
-};
-
-struct irq_chip s3c_irq_level_chip = {
-	.name		= "s3c-level",
-	.irq_mask	= s3c_irq_mask,
-	.irq_unmask	= s3c_irq_unmask,
-	.irq_ack	= s3c_irq_ack,
-};
-
-static struct irq_chip s3c_irqext_chip = {
-	.name		= "s3c-ext",
-	.irq_mask	= s3c_irq_mask,
-	.irq_unmask	= s3c_irq_unmask,
-	.irq_ack	= s3c_irq_ack,
-	.irq_set_type	= s3c_irqext_type,
-	.irq_set_wake	= s3c_irqext_wake
-};
-
-static struct irq_chip s3c_irq_eint0t4 = {
-	.name		= "s3c-ext0",
-	.irq_ack	= s3c_irq_ack,
-	.irq_mask	= s3c_irq_mask,
-	.irq_unmask	= s3c_irq_unmask,
-	.irq_set_wake	= s3c_irq_wake,
-	.irq_set_type	= s3c_irqext0_type,
-};
-
-static void s3c_irq_demux(unsigned int irq, struct irq_desc *desc)
-{
-	struct irq_chip *chip = irq_desc_get_chip(desc);
-	struct s3c_irq_intc *intc = desc->irq_data.domain->host_data;
-	struct s3c_irq_data *irq_data = &intc->irqs[desc->irq_data.hwirq];
-	struct s3c_irq_intc *sub_intc = irq_data->sub_intc;
-	unsigned long src;
-	unsigned long msk;
-	unsigned int n;
-
-	chained_irq_enter(chip, desc);
-
-	src = __raw_readl(sub_intc->reg_pending);
-	msk = __raw_readl(sub_intc->reg_mask);
-
-	src &= ~msk;
-	src &= irq_data->sub_bits;
-
-	while (src) {
-		n = __ffs(src);
-		src &= ~(1 << n);
-		generic_handle_irq(irq_find_mapping(sub_intc->domain, n));
-	}
-
-	chained_irq_exit(chip, desc);
-}
-
-#ifdef CONFIG_FIQ
-/**
- * s3c24xx_set_fiq - set the FIQ routing
- * @irq: IRQ number to route to FIQ on processor.
- * @on: Whether to route @irq to the FIQ, or to remove the FIQ routing.
- *
- * Change the state of the IRQ to FIQ routing depending on @irq and @on. If
- * @on is true, the @irq is checked to see if it can be routed and the
- * interrupt controller updated to route the IRQ. If @on is false, the FIQ
- * routing is cleared, regardless of which @irq is specified.
- */
-int s3c24xx_set_fiq(unsigned int irq, bool on)
-{
-	u32 intmod;
-	unsigned offs;
-
-	if (on) {
-		offs = irq - FIQ_START;
-		if (offs > 31)
-			return -EINVAL;
-
-		intmod = 1 << offs;
-	} else {
-		intmod = 0;
-	}
-
-	__raw_writel(intmod, S3C2410_INTMOD);
-	return 0;
-}
-
-EXPORT_SYMBOL_GPL(s3c24xx_set_fiq);
-#endif
-
-static int s3c24xx_irq_map(struct irq_domain *h, unsigned int virq,
-							irq_hw_number_t hw)
-{
-	struct s3c_irq_intc *intc = h->host_data;
-	struct s3c_irq_data *irq_data = &intc->irqs[hw];
-	struct s3c_irq_intc *parent_intc;
-	struct s3c_irq_data *parent_irq_data;
-	unsigned int irqno;
-
-	if (!intc) {
-		pr_err("irq-s3c24xx: no controller found for hwirq %lu\n", hw);
-		return -EINVAL;
-	}
-
-	if (!irq_data) {
-		pr_err("irq-s3c24xx: no irq data found for hwirq %lu\n", hw);
-		return -EINVAL;
-	}
-
-	/* attach controller pointer to irq_data */
-	irq_data->intc = intc;
-
-	/* set handler and flags */
-	switch (irq_data->type) {
-	case S3C_IRQTYPE_NONE:
-		return 0;
-	case S3C_IRQTYPE_EINT:
-		if (irq_data->parent_irq)
-			irq_set_chip_and_handler(virq, &s3c_irqext_chip,
-						 handle_edge_irq);
-		else
-			irq_set_chip_and_handler(virq, &s3c_irq_eint0t4,
-						 handle_edge_irq);
-		break;
-	case S3C_IRQTYPE_EDGE:
-		if (irq_data->parent_irq ||
-		    intc->reg_pending == S3C2416_SRCPND2)
-			irq_set_chip_and_handler(virq, &s3c_irq_level_chip,
-						 handle_edge_irq);
-		else
-			irq_set_chip_and_handler(virq, &s3c_irq_chip,
-						 handle_edge_irq);
-		break;
-	case S3C_IRQTYPE_LEVEL:
-		if (irq_data->parent_irq)
-			irq_set_chip_and_handler(virq, &s3c_irq_level_chip,
-						 handle_level_irq);
-		else
-			irq_set_chip_and_handler(virq, &s3c_irq_chip,
-						 handle_level_irq);
-		break;
-	default:
-		pr_err("irq-s3c24xx: unsupported irqtype %d\n", irq_data->type);
-		return -EINVAL;
-	}
-	set_irq_flags(virq, IRQF_VALID);
-
-	if (irq_data->parent_irq) {
-		parent_intc = intc->parent;
-		if (!parent_intc) {
-			pr_err("irq-s3c24xx: no parent controller found for hwirq %lu\n",
-			       hw);
-			goto err;
-		}
-
-		parent_irq_data = &parent_intc->irqs[irq_data->parent_irq];
-		if (!irq_data) {
-			pr_err("irq-s3c24xx: no irq data found for hwirq %lu\n",
-			       hw);
-			goto err;
-		}
-
-		parent_irq_data->sub_intc = intc;
-		parent_irq_data->sub_bits |= (1UL << hw);
-
-		/* attach the demuxer to the parent irq */
-		irqno = irq_find_mapping(parent_intc->domain,
-					 irq_data->parent_irq);
-		if (!irqno) {
-			pr_err("irq-s3c24xx: could not find mapping for parent irq %lu\n",
-			       irq_data->parent_irq);
-			goto err;
-		}
-		irq_set_chained_handler(irqno, s3c_irq_demux);
-	}
-
-	return 0;
-
-err:
-	set_irq_flags(virq, 0);
-
-	/* the only error can result from bad mapping data*/
-	return -EINVAL;
-}
-
-static struct irq_domain_ops s3c24xx_irq_ops = {
-	.map = s3c24xx_irq_map,
-	.xlate = irq_domain_xlate_twocell,
-};
-
-static void s3c24xx_clear_intc(struct s3c_irq_intc *intc)
-{
-	void __iomem *reg_source;
-	unsigned long pend;
-	unsigned long last;
-	int i;
-
-	/* if intpnd is set, read the next pending irq from there */
-	reg_source = intc->reg_intpnd ? intc->reg_intpnd : intc->reg_pending;
-
-	last = 0;
-	for (i = 0; i < 4; i++) {
-		pend = __raw_readl(reg_source);
-
-		if (pend == 0 || pend == last)
-			break;
-
-		__raw_writel(pend, intc->reg_pending);
-		if (intc->reg_intpnd)
-			__raw_writel(pend, intc->reg_intpnd);
-
-		pr_info("irq: clearing pending status %08x\n", (int)pend);
-		last = pend;
-	}
-}
-
-struct s3c_irq_intc *s3c24xx_init_intc(struct device_node *np,
-				       struct s3c_irq_data *irq_data,
-				       struct s3c_irq_intc *parent,
-				       unsigned long address)
-{
-	struct s3c_irq_intc *intc;
-	void __iomem *base = (void *)0xf6000000; /* static mapping */
-	int irq_num;
-	int irq_start;
-	int irq_offset;
-	int ret;
-
-	intc = kzalloc(sizeof(struct s3c_irq_intc), GFP_KERNEL);
-	if (!intc)
-		return ERR_PTR(-ENOMEM);
-
-	intc->irqs = irq_data;
-
-	if (parent)
-		intc->parent = parent;
-
-	/* select the correct data for the controller.
-	 * Need to hard code the irq num start and offset
-	 * to preserve the static mapping for now
-	 */
-	switch (address) {
-	case 0x4a000000:
-		pr_debug("irq: found main intc\n");
-		intc->reg_pending = base;
-		intc->reg_mask = base + 0x08;
-		intc->reg_intpnd = base + 0x10;
-		irq_num = 32;
-		irq_start = S3C2410_IRQ(0);
-		irq_offset = 0;
-		break;
-	case 0x4a000018:
-		pr_debug("irq: found subintc\n");
-		intc->reg_pending = base + 0x18;
-		intc->reg_mask = base + 0x1c;
-		irq_num = 29;
-		irq_start = S3C2410_IRQSUB(0);
-		irq_offset = 0;
-		break;
-	case 0x4a000040:
-		pr_debug("irq: found intc2\n");
-		intc->reg_pending = base + 0x40;
-		intc->reg_mask = base + 0x48;
-		intc->reg_intpnd = base + 0x50;
-		irq_num = 8;
-		irq_start = S3C2416_IRQ(0);
-		irq_offset = 0;
-		break;
-	case 0x560000a4:
-		pr_debug("irq: found eintc\n");
-		base = (void *)0xfd000000;
-
-		intc->reg_mask = base + 0xa4;
-		intc->reg_pending = base + 0x08;
-		irq_num = 20;
-		irq_start = S3C2410_IRQ(32);
-		irq_offset = 4;
-		break;
-	default:
-		pr_err("irq: unsupported controller address\n");
-		ret = -EINVAL;
-		goto err;
-	}
-
-	/* now that all the data is complete, init the irq-domain */
-	s3c24xx_clear_intc(intc);
-	intc->domain = irq_domain_add_legacy(np, irq_num, irq_start,
-					     irq_offset, &s3c24xx_irq_ops,
-					     intc);
-	if (!intc->domain) {
-		pr_err("irq: could not create irq-domain\n");
-		ret = -EINVAL;
-		goto err;
-	}
-
-	return intc;
-
-err:
-	kfree(intc);
-	return ERR_PTR(ret);
-}
-
-/* s3c24xx_init_irq
- *
- * Initialise S3C2410 IRQ system
-*/
-
-static struct s3c_irq_data init_base[32] = {
-	{ .type = S3C_IRQTYPE_EINT, }, /* EINT0 */
-	{ .type = S3C_IRQTYPE_EINT, }, /* EINT1 */
-	{ .type = S3C_IRQTYPE_EINT, }, /* EINT2 */
-	{ .type = S3C_IRQTYPE_EINT, }, /* EINT3 */
-	{ .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */
-	{ .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */
-	{ .type = S3C_IRQTYPE_NONE, }, /* reserved */
-	{ .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */
-	{ .type = S3C_IRQTYPE_EDGE, }, /* TICK */
-	{ .type = S3C_IRQTYPE_EDGE, }, /* WDT */
-	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */
-	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */
-	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */
-	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */
-	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */
-	{ .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */
-	{ .type = S3C_IRQTYPE_EDGE, }, /* LCD */
-	{ .type = S3C_IRQTYPE_EDGE, }, /* DMA0 */
-	{ .type = S3C_IRQTYPE_EDGE, }, /* DMA1 */
-	{ .type = S3C_IRQTYPE_EDGE, }, /* DMA2 */
-	{ .type = S3C_IRQTYPE_EDGE, }, /* DMA3 */
-	{ .type = S3C_IRQTYPE_EDGE, }, /* SDI */
-	{ .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */
-	{ .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */
-	{ .type = S3C_IRQTYPE_NONE, }, /* reserved */
-	{ .type = S3C_IRQTYPE_EDGE, }, /* USBD */
-	{ .type = S3C_IRQTYPE_EDGE, }, /* USBH */
-	{ .type = S3C_IRQTYPE_EDGE, }, /* IIC */
-	{ .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */
-	{ .type = S3C_IRQTYPE_EDGE, }, /* SPI1 */
-	{ .type = S3C_IRQTYPE_EDGE, }, /* RTC */
-	{ .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */
-};
-
-static struct s3c_irq_data init_eint[32] = {
-	{ .type = S3C_IRQTYPE_NONE, }, /* reserved */
-	{ .type = S3C_IRQTYPE_NONE, }, /* reserved */
-	{ .type = S3C_IRQTYPE_NONE, }, /* reserved */
-	{ .type = S3C_IRQTYPE_NONE, }, /* reserved */
-	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT4 */
-	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT5 */
-	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT6 */
-	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT7 */
-	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT8 */
-	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT9 */
-	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT10 */
-	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT11 */
-	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT12 */
-	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT13 */
-	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT14 */
-	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT15 */
-	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT16 */
-	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT17 */
-	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT18 */
-	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT19 */
-	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT20 */
-	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT21 */
-	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT22 */
-	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT23 */
-};
-
-static struct s3c_irq_data init_subint[32] = {
-	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */
-	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */
-	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */
-	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */
-	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */
-	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */
-	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */
-	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */
-	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */
-	{ .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */
-	{ .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */
-};
-
-void __init s3c24xx_init_irq(void)
-{
-	struct s3c_irq_intc *main_intc;
-
-#ifdef CONFIG_FIQ
-	init_FIQ(FIQ_START);
-#endif
-
-	main_intc = s3c24xx_init_intc(NULL, &init_base[0], NULL, 0x4a000000);
-	if (IS_ERR(main_intc)) {
-		pr_err("irq: could not create main interrupt controller\n");
-		return;
-	}
-
-	s3c24xx_init_intc(NULL, &init_subint[0], main_intc, 0x4a000018);
-	s3c24xx_init_intc(NULL, &init_eint[0], main_intc, 0x560000a4);
-}
-
-#ifdef CONFIG_CPU_S3C2416
-static struct s3c_irq_data init_s3c2416base[32] = {
-	{ .type = S3C_IRQTYPE_EINT, }, /* EINT0 */
-	{ .type = S3C_IRQTYPE_EINT, }, /* EINT1 */
-	{ .type = S3C_IRQTYPE_EINT, }, /* EINT2 */
-	{ .type = S3C_IRQTYPE_EINT, }, /* EINT3 */
-	{ .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */
-	{ .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */
-	{ .type = S3C_IRQTYPE_NONE, }, /* reserved */
-	{ .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */
-	{ .type = S3C_IRQTYPE_EDGE, }, /* TICK */
-	{ .type = S3C_IRQTYPE_LEVEL, }, /* WDT/AC97 */
-	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */
-	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */
-	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */
-	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */
-	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */
-	{ .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */
-	{ .type = S3C_IRQTYPE_LEVEL, }, /* LCD */
-	{ .type = S3C_IRQTYPE_LEVEL, }, /* DMA */
-	{ .type = S3C_IRQTYPE_LEVEL, }, /* UART3 */
-	{ .type = S3C_IRQTYPE_NONE, }, /* reserved */
-	{ .type = S3C_IRQTYPE_EDGE, }, /* SDI1 */
-	{ .type = S3C_IRQTYPE_EDGE, }, /* SDI0 */
-	{ .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */
-	{ .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */
-	{ .type = S3C_IRQTYPE_EDGE, }, /* NAND */
-	{ .type = S3C_IRQTYPE_EDGE, }, /* USBD */
-	{ .type = S3C_IRQTYPE_EDGE, }, /* USBH */
-	{ .type = S3C_IRQTYPE_EDGE, }, /* IIC */
-	{ .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */
-	{ .type = S3C_IRQTYPE_NONE, },
-	{ .type = S3C_IRQTYPE_EDGE, }, /* RTC */
-	{ .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */
-};
-
-static struct s3c_irq_data init_s3c2416subint[32] = {
-	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */
-	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */
-	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */
-	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */
-	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */
-	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */
-	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */
-	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */
-	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */
-	{ .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */
-	{ .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */
-	{ .type = S3C_IRQTYPE_NONE }, /* reserved */
-	{ .type = S3C_IRQTYPE_NONE }, /* reserved */
-	{ .type = S3C_IRQTYPE_NONE }, /* reserved */
-	{ .type = S3C_IRQTYPE_NONE }, /* reserved */
-	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD2 */
-	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD3 */
-	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD4 */
-	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA0 */
-	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA1 */
-	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA2 */
-	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA3 */
-	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA4 */
-	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA5 */
-	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-RX */
-	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-TX */
-	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-ERR */
-	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* WDT */
-	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* AC97 */
-};
-
-static struct s3c_irq_data init_s3c2416_second[32] = {
-	{ .type = S3C_IRQTYPE_EDGE }, /* 2D */
-	{ .type = S3C_IRQTYPE_EDGE }, /* IIC1 */
-	{ .type = S3C_IRQTYPE_NONE }, /* reserved */
-	{ .type = S3C_IRQTYPE_NONE }, /* reserved */
-	{ .type = S3C_IRQTYPE_EDGE }, /* PCM0 */
-	{ .type = S3C_IRQTYPE_EDGE }, /* PCM1 */
-	{ .type = S3C_IRQTYPE_EDGE }, /* I2S0 */
-	{ .type = S3C_IRQTYPE_EDGE }, /* I2S1 */
-};
-
-void __init s3c2416_init_irq(void)
-{
-	struct s3c_irq_intc *main_intc;
-
-	pr_info("S3C2416: IRQ Support\n");
-
-#ifdef CONFIG_FIQ
-	init_FIQ(FIQ_START);
-#endif
-
-	main_intc = s3c24xx_init_intc(NULL, &init_s3c2416base[0], NULL, 0x4a000000);
-	if (IS_ERR(main_intc)) {
-		pr_err("irq: could not create main interrupt controller\n");
-		return;
-	}
-
-	s3c24xx_init_intc(NULL, &init_eint[0], main_intc, 0x560000a4);
-	s3c24xx_init_intc(NULL, &init_s3c2416subint[0], main_intc, 0x4a000018);
-
-	s3c24xx_init_intc(NULL, &init_s3c2416_second[0], NULL, 0x4a000040);
-}
-
-#endif
-
-#ifdef CONFIG_CPU_S3C2443
-static struct s3c_irq_data init_s3c2443base[32] = {
-	{ .type = S3C_IRQTYPE_EINT, }, /* EINT0 */
-	{ .type = S3C_IRQTYPE_EINT, }, /* EINT1 */
-	{ .type = S3C_IRQTYPE_EINT, }, /* EINT2 */
-	{ .type = S3C_IRQTYPE_EINT, }, /* EINT3 */
-	{ .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */
-	{ .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */
-	{ .type = S3C_IRQTYPE_LEVEL, }, /* CAM */
-	{ .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */
-	{ .type = S3C_IRQTYPE_EDGE, }, /* TICK */
-	{ .type = S3C_IRQTYPE_LEVEL, }, /* WDT/AC97 */
-	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */
-	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */
-	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */
-	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */
-	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */
-	{ .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */
-	{ .type = S3C_IRQTYPE_LEVEL, }, /* LCD */
-	{ .type = S3C_IRQTYPE_LEVEL, }, /* DMA */
-	{ .type = S3C_IRQTYPE_LEVEL, }, /* UART3 */
-	{ .type = S3C_IRQTYPE_EDGE, }, /* CFON */
-	{ .type = S3C_IRQTYPE_EDGE, }, /* SDI1 */
-	{ .type = S3C_IRQTYPE_EDGE, }, /* SDI0 */
-	{ .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */
-	{ .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */
-	{ .type = S3C_IRQTYPE_EDGE, }, /* NAND */
-	{ .type = S3C_IRQTYPE_EDGE, }, /* USBD */
-	{ .type = S3C_IRQTYPE_EDGE, }, /* USBH */
-	{ .type = S3C_IRQTYPE_EDGE, }, /* IIC */
-	{ .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */
-	{ .type = S3C_IRQTYPE_EDGE, }, /* SPI1 */
-	{ .type = S3C_IRQTYPE_EDGE, }, /* RTC */
-	{ .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */
-};
-
-
-static struct s3c_irq_data init_s3c2443subint[32] = {
-	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */
-	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */
-	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */
-	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */
-	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */
-	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */
-	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */
-	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */
-	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */
-	{ .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */
-	{ .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */
-	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 }, /* CAM_C */
-	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 }, /* CAM_P */
-	{ .type = S3C_IRQTYPE_NONE }, /* reserved */
-	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD1 */
-	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD2 */
-	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD3 */
-	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD4 */
-	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA0 */
-	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA1 */
-	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA2 */
-	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA3 */
-	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA4 */
-	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA5 */
-	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-RX */
-	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-TX */
-	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-ERR */
-	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* WDT */
-	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* AC97 */
-};
-
-void __init s3c2443_init_irq(void)
-{
-	struct s3c_irq_intc *main_intc;
-
-	pr_info("S3C2443: IRQ Support\n");
-
-#ifdef CONFIG_FIQ
-	init_FIQ(FIQ_START);
-#endif
-
-	main_intc = s3c24xx_init_intc(NULL, &init_s3c2443base[0], NULL, 0x4a000000);
-	if (IS_ERR(main_intc)) {
-		pr_err("irq: could not create main interrupt controller\n");
-		return;
-	}
-
-	s3c24xx_init_intc(NULL, &init_eint[0], main_intc, 0x560000a4);
-	s3c24xx_init_intc(NULL, &init_s3c2443subint[0], main_intc, 0x4a000018);
-}
-#endif
diff --git a/arch/arm/mach-s3c24xx/mach-amlm5900.c b/arch/arm/mach-s3c24xx/mach-amlm5900.c
index 0e0279e..e27b5c9 100644
--- a/arch/arm/mach-s3c24xx/mach-amlm5900.c
+++ b/arch/arm/mach-s3c24xx/mach-amlm5900.c
@@ -63,6 +63,8 @@
 #include <linux/mtd/map.h>
 #include <linux/mtd/physmap.h>
 
+#include <plat/samsung-time.h>
+
 #include "common.h"
 
 static struct resource amlm5900_nor_resource =
@@ -160,6 +162,7 @@ static void __init amlm5900_map_io(void)
 	s3c24xx_init_io(amlm5900_iodesc, ARRAY_SIZE(amlm5900_iodesc));
 	s3c24xx_init_clocks(0);
 	s3c24xx_init_uarts(amlm5900_uartcfgs, ARRAY_SIZE(amlm5900_uartcfgs));
+	samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
 #ifdef CONFIG_FB_S3C2410
@@ -235,8 +238,8 @@ static void __init amlm5900_init(void)
 MACHINE_START(AML_M5900, "AML_M5900")
 	.atag_offset	= 0x100,
 	.map_io		= amlm5900_map_io,
-	.init_irq	= s3c24xx_init_irq,
+	.init_irq	= s3c2410_init_irq,
 	.init_machine	= amlm5900_init,
-	.init_time	= s3c24xx_timer_init,
+	.init_time	= samsung_timer_init,
 	.restart	= s3c2410_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/mach-anubis.c b/arch/arm/mach-s3c24xx/mach-anubis.c
index bb595f1..c1fb6c3 100644
--- a/arch/arm/mach-s3c24xx/mach-anubis.c
+++ b/arch/arm/mach-s3c24xx/mach-anubis.c
@@ -49,6 +49,7 @@
 #include <plat/devs.h>
 #include <plat/cpu.h>
 #include <linux/platform_data/asoc-s3c24xx_simtec.h>
+#include <plat/samsung-time.h>
 
 #include "anubis.h"
 #include "common.h"
@@ -410,6 +411,7 @@ static void __init anubis_map_io(void)
 	s3c24xx_init_io(anubis_iodesc, ARRAY_SIZE(anubis_iodesc));
 	s3c24xx_init_clocks(0);
 	s3c24xx_init_uarts(anubis_uartcfgs, ARRAY_SIZE(anubis_uartcfgs));
+	samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 
 	/* check for the newer revision boards with large page nand */
 
@@ -443,7 +445,7 @@ MACHINE_START(ANUBIS, "Simtec-Anubis")
 	.atag_offset	= 0x100,
 	.map_io		= anubis_map_io,
 	.init_machine	= anubis_init,
-	.init_irq	= s3c24xx_init_irq,
-	.init_time	= s3c24xx_timer_init,
+	.init_irq	= s3c2440_init_irq,
+	.init_time	= samsung_timer_init,
 	.restart	= s3c244x_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/mach-at2440evb.c b/arch/arm/mach-s3c24xx/mach-at2440evb.c
index b4bc60c..6dfeeb7 100644
--- a/arch/arm/mach-s3c24xx/mach-at2440evb.c
+++ b/arch/arm/mach-s3c24xx/mach-at2440evb.c
@@ -48,6 +48,7 @@
 #include <plat/devs.h>
 #include <plat/cpu.h>
 #include <linux/platform_data/mmc-s3cmci.h>
+#include <plat/samsung-time.h>
 
 #include "common.h"
 
@@ -192,6 +193,7 @@ static void __init at2440evb_map_io(void)
 	s3c24xx_init_io(at2440evb_iodesc, ARRAY_SIZE(at2440evb_iodesc));
 	s3c24xx_init_clocks(16934400);
 	s3c24xx_init_uarts(at2440evb_uartcfgs, ARRAY_SIZE(at2440evb_uartcfgs));
+	samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
 static void __init at2440evb_init(void)
@@ -209,7 +211,7 @@ MACHINE_START(AT2440EVB, "AT2440EVB")
 	.atag_offset	= 0x100,
 	.map_io		= at2440evb_map_io,
 	.init_machine	= at2440evb_init,
-	.init_irq	= s3c24xx_init_irq,
-	.init_time	= s3c24xx_timer_init,
+	.init_irq	= s3c2440_init_irq,
+	.init_time	= samsung_timer_init,
 	.restart	= s3c244x_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/mach-bast.c b/arch/arm/mach-s3c24xx/mach-bast.c
index ca66180..22d6ae9 100644
--- a/arch/arm/mach-s3c24xx/mach-bast.c
+++ b/arch/arm/mach-s3c24xx/mach-bast.c
@@ -55,6 +55,7 @@
 #include <plat/devs.h>
 #include <plat/gpio-cfg.h>
 #include <plat/regs-serial.h>
+#include <plat/samsung-time.h>
 
 #include "bast.h"
 #include "common.h"
@@ -576,6 +577,7 @@ static void __init bast_map_io(void)
 	s3c24xx_init_io(bast_iodesc, ARRAY_SIZE(bast_iodesc));
 	s3c24xx_init_clocks(0);
 	s3c24xx_init_uarts(bast_uartcfgs, ARRAY_SIZE(bast_uartcfgs));
+	samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
 static void __init bast_init(void)
@@ -603,8 +605,8 @@ MACHINE_START(BAST, "Simtec-BAST")
 	/* Maintainer: Ben Dooks <ben@simtec.co.uk> */
 	.atag_offset	= 0x100,
 	.map_io		= bast_map_io,
-	.init_irq	= s3c24xx_init_irq,
+	.init_irq	= s3c2410_init_irq,
 	.init_machine	= bast_init,
-	.init_time	= s3c24xx_timer_init,
+	.init_time	= samsung_timer_init,
 	.restart	= s3c2410_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/mach-gta02.c b/arch/arm/mach-s3c24xx/mach-gta02.c
index a25e8c5..13d8d07 100644
--- a/arch/arm/mach-s3c24xx/mach-gta02.c
+++ b/arch/arm/mach-s3c24xx/mach-gta02.c
@@ -81,6 +81,7 @@
 #include <plat/gpio-cfg.h>
 #include <plat/pm.h>
 #include <plat/regs-serial.h>
+#include <plat/samsung-time.h>
 
 #include "common.h"
 #include "gta02.h"
@@ -501,6 +502,7 @@ static void __init gta02_map_io(void)
 	s3c24xx_init_io(gta02_iodesc, ARRAY_SIZE(gta02_iodesc));
 	s3c24xx_init_clocks(12000000);
 	s3c24xx_init_uarts(gta02_uartcfgs, ARRAY_SIZE(gta02_uartcfgs));
+	samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
 
@@ -587,8 +589,8 @@ MACHINE_START(NEO1973_GTA02, "GTA02")
 	/* Maintainer: Nelson Castillo <arhuaco@freaks-unidos.net> */
 	.atag_offset	= 0x100,
 	.map_io		= gta02_map_io,
-	.init_irq	= s3c24xx_init_irq,
+	.init_irq	= s3c2442_init_irq,
 	.init_machine	= gta02_machine_init,
-	.init_time	= s3c24xx_timer_init,
+	.init_time	= samsung_timer_init,
 	.restart	= s3c244x_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/mach-h1940.c b/arch/arm/mach-s3c24xx/mach-h1940.c
index 79bc083..af4334d 100644
--- a/arch/arm/mach-s3c24xx/mach-h1940.c
+++ b/arch/arm/mach-s3c24xx/mach-h1940.c
@@ -62,7 +62,7 @@
 #include <plat/pll.h>
 #include <plat/pm.h>
 #include <plat/regs-serial.h>
-
+#include <plat/samsung-time.h>
 
 #include "common.h"
 #include "h1940.h"
@@ -646,6 +646,7 @@ static void __init h1940_map_io(void)
 	s3c24xx_init_io(h1940_iodesc, ARRAY_SIZE(h1940_iodesc));
 	s3c24xx_init_clocks(0);
 	s3c24xx_init_uarts(h1940_uartcfgs, ARRAY_SIZE(h1940_uartcfgs));
+	samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 
 	/* setup PM */
 
@@ -666,11 +667,6 @@ static void __init h1940_reserve(void)
 	memblock_reserve(0x30081000, 0x1000);
 }
 
-static void __init h1940_init_irq(void)
-{
-	s3c24xx_init_irq();
-}
-
 static void __init h1940_init(void)
 {
 	u32 tmp;
@@ -739,8 +735,8 @@ MACHINE_START(H1940, "IPAQ-H1940")
 	.atag_offset	= 0x100,
 	.map_io		= h1940_map_io,
 	.reserve	= h1940_reserve,
-	.init_irq	= h1940_init_irq,
+	.init_irq	= s3c2410_init_irq,
 	.init_machine	= h1940_init,
-	.init_time	= s3c24xx_timer_init,
+	.init_time	= samsung_timer_init,
 	.restart	= s3c2410_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/mach-jive.c b/arch/arm/mach-s3c24xx/mach-jive.c
index 54e83c1..a45fcd8 100644
--- a/arch/arm/mach-s3c24xx/mach-jive.c
+++ b/arch/arm/mach-s3c24xx/mach-jive.c
@@ -46,14 +46,15 @@
 #include <linux/mtd/nand_ecc.h>
 #include <linux/mtd/partitions.h>
 
-#include <plat/s3c2412.h>
 #include <plat/gpio-cfg.h>
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
 #include <plat/pm.h>
 #include <linux/platform_data/usb-s3c2410_udc.h>
+#include <plat/samsung-time.h>
 
+#include "common.h"
 #include "s3c2412-power.h"
 
 static struct map_desc jive_iodesc[] __initdata = {
@@ -506,6 +507,7 @@ static void __init jive_map_io(void)
 	s3c24xx_init_io(jive_iodesc, ARRAY_SIZE(jive_iodesc));
 	s3c24xx_init_clocks(12000000);
 	s3c24xx_init_uarts(jive_uartcfgs, ARRAY_SIZE(jive_uartcfgs));
+	samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
 static void jive_power_off(void)
@@ -658,9 +660,9 @@ MACHINE_START(JIVE, "JIVE")
 	/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
 	.atag_offset	= 0x100,
 
-	.init_irq	= s3c24xx_init_irq,
+	.init_irq	= s3c2412_init_irq,
 	.map_io		= jive_map_io,
 	.init_machine	= jive_machine_init,
-	.init_time	= s3c24xx_timer_init,
+	.init_time	= samsung_timer_init,
 	.restart	= s3c2412_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/mach-mini2440.c b/arch/arm/mach-s3c24xx/mach-mini2440.c
index 2865e59..a83db46 100644
--- a/arch/arm/mach-s3c24xx/mach-mini2440.c
+++ b/arch/arm/mach-s3c24xx/mach-mini2440.c
@@ -56,6 +56,7 @@
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
+#include <plat/samsung-time.h>
 
 #include <sound/s3c24xx_uda134x.h>
 
@@ -525,6 +526,7 @@ static void __init mini2440_map_io(void)
 	s3c24xx_init_io(mini2440_iodesc, ARRAY_SIZE(mini2440_iodesc));
 	s3c24xx_init_clocks(12000000);
 	s3c24xx_init_uarts(mini2440_uartcfgs, ARRAY_SIZE(mini2440_uartcfgs));
+	samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
 /*
@@ -686,7 +688,7 @@ MACHINE_START(MINI2440, "MINI2440")
 	.atag_offset	= 0x100,
 	.map_io		= mini2440_map_io,
 	.init_machine	= mini2440_init,
-	.init_irq	= s3c24xx_init_irq,
-	.init_time	= s3c24xx_timer_init,
+	.init_irq	= s3c2440_init_irq,
+	.init_time	= samsung_timer_init,
 	.restart	= s3c244x_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/mach-n30.c b/arch/arm/mach-s3c24xx/mach-n30.c
index d9d04b2..2cb46c3 100644
--- a/arch/arm/mach-s3c24xx/mach-n30.c
+++ b/arch/arm/mach-s3c24xx/mach-n30.c
@@ -48,8 +48,8 @@
 #include <plat/cpu.h>
 #include <plat/devs.h>
 #include <linux/platform_data/mmc-s3cmci.h>
-#include <plat/s3c2410.h>
 #include <linux/platform_data/usb-s3c2410_udc.h>
+#include <plat/samsung-time.h>
 
 #include "common.h"
 
@@ -536,6 +536,7 @@ static void __init n30_map_io(void)
 	n30_hwinit();
 	s3c24xx_init_clocks(0);
 	s3c24xx_init_uarts(n30_uartcfgs, ARRAY_SIZE(n30_uartcfgs));
+	samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
 /* GPB3 is the line that controls the pull-up for the USB D+ line */
@@ -589,9 +590,9 @@ MACHINE_START(N30, "Acer-N30")
 				Ben Dooks <ben-linux@fluff.org>
 	*/
 	.atag_offset	= 0x100,
-	.init_time	= s3c24xx_timer_init,
+	.init_time	= samsung_timer_init,
 	.init_machine	= n30_init,
-	.init_irq	= s3c24xx_init_irq,
+	.init_irq	= s3c2410_init_irq,
 	.map_io		= n30_map_io,
 	.restart	= s3c2410_restart,
 MACHINE_END
@@ -600,9 +601,9 @@ MACHINE_START(N35, "Acer-N35")
 	/* Maintainer: Christer Weinigel <christer@weinigel.se>
 	*/
 	.atag_offset	= 0x100,
-	.init_time	= s3c24xx_timer_init,
+	.init_time	= samsung_timer_init,
 	.init_machine	= n30_init,
-	.init_irq	= s3c24xx_init_irq,
+	.init_irq	= s3c2410_init_irq,
 	.map_io		= n30_map_io,
 	.restart	= s3c2410_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/mach-nexcoder.c b/arch/arm/mach-s3c24xx/mach-nexcoder.c
index a454e24..01f4354 100644
--- a/arch/arm/mach-s3c24xx/mach-nexcoder.c
+++ b/arch/arm/mach-s3c24xx/mach-nexcoder.c
@@ -41,11 +41,10 @@
 #include <linux/platform_data/i2c-s3c2410.h>
 
 #include <plat/gpio-cfg.h>
-#include <plat/s3c2410.h>
-#include <plat/s3c244x.h>
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
+#include <plat/samsung-time.h>
 
 #include "common.h"
 
@@ -137,6 +136,7 @@ static void __init nexcoder_map_io(void)
 	s3c24xx_init_io(nexcoder_iodesc, ARRAY_SIZE(nexcoder_iodesc));
 	s3c24xx_init_clocks(0);
 	s3c24xx_init_uarts(nexcoder_uartcfgs, ARRAY_SIZE(nexcoder_uartcfgs));
+	samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 
 	nexcoder_sensorboard_init();
 }
@@ -152,7 +152,7 @@ MACHINE_START(NEXCODER_2440, "NexVision - Nexcoder 2440")
 	.atag_offset	= 0x100,
 	.map_io		= nexcoder_map_io,
 	.init_machine	= nexcoder_init,
-	.init_irq	= s3c24xx_init_irq,
-	.init_time	= s3c24xx_timer_init,
+	.init_irq	= s3c2440_init_irq,
+	.init_time	= samsung_timer_init,
 	.restart	= s3c244x_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/mach-osiris.c b/arch/arm/mach-s3c24xx/mach-osiris.c
index ae2cbdf..58d6fbe 100644
--- a/arch/arm/mach-s3c24xx/mach-osiris.c
+++ b/arch/arm/mach-s3c24xx/mach-osiris.c
@@ -45,6 +45,7 @@
 #include <plat/devs.h>
 #include <plat/gpio-cfg.h>
 #include <plat/regs-serial.h>
+#include <plat/samsung-time.h>
 
 #include <mach/hardware.h>
 #include <mach/regs-gpio.h>
@@ -384,6 +385,7 @@ static void __init osiris_map_io(void)
 	s3c24xx_init_io(osiris_iodesc, ARRAY_SIZE(osiris_iodesc));
 	s3c24xx_init_clocks(0);
 	s3c24xx_init_uarts(osiris_uartcfgs, ARRAY_SIZE(osiris_uartcfgs));
+	samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 
 	/* check for the newer revision boards with large page nand */
 
@@ -424,8 +426,8 @@ MACHINE_START(OSIRIS, "Simtec-OSIRIS")
 	/* Maintainer: Ben Dooks <ben@simtec.co.uk> */
 	.atag_offset	= 0x100,
 	.map_io		= osiris_map_io,
-	.init_irq	= s3c24xx_init_irq,
+	.init_irq	= s3c2440_init_irq,
 	.init_machine	= osiris_init,
-	.init_time	= s3c24xx_timer_init,
+	.init_time	= samsung_timer_init,
 	.restart	= s3c244x_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/mach-otom.c b/arch/arm/mach-s3c24xx/mach-otom.c
index 40a47d6..7e16b07 100644
--- a/arch/arm/mach-s3c24xx/mach-otom.c
+++ b/arch/arm/mach-s3c24xx/mach-otom.c
@@ -33,7 +33,7 @@
 #include <plat/cpu.h>
 #include <plat/devs.h>
 #include <plat/regs-serial.h>
-#include <plat/s3c2410.h>
+#include <plat/samsung-time.h>
 
 #include "common.h"
 #include "otom.h"
@@ -102,6 +102,7 @@ static void __init otom11_map_io(void)
 	s3c24xx_init_io(otom11_iodesc, ARRAY_SIZE(otom11_iodesc));
 	s3c24xx_init_clocks(0);
 	s3c24xx_init_uarts(otom11_uartcfgs, ARRAY_SIZE(otom11_uartcfgs));
+	samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
 static void __init otom11_init(void)
@@ -115,7 +116,7 @@ MACHINE_START(OTOM, "Nex Vision - Otom 1.1")
 	.atag_offset	= 0x100,
 	.map_io		= otom11_map_io,
 	.init_machine	= otom11_init,
-	.init_irq	= s3c24xx_init_irq,
-	.init_time	= s3c24xx_timer_init,
+	.init_irq	= s3c2410_init_irq,
+	.init_time	= samsung_timer_init,
 	.restart	= s3c2410_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/mach-qt2410.c b/arch/arm/mach-s3c24xx/mach-qt2410.c
index 56175f0..f8feaea 100644
--- a/arch/arm/mach-s3c24xx/mach-qt2410.c
+++ b/arch/arm/mach-s3c24xx/mach-qt2410.c
@@ -55,13 +55,14 @@
 #include <linux/platform_data/usb-s3c2410_udc.h>
 #include <linux/platform_data/i2c-s3c2410.h>
 
-#include <plat/common-smdk.h>
 #include <plat/gpio-cfg.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
 #include <plat/pm.h>
+#include <plat/samsung-time.h>
 
 #include "common.h"
+#include "common-smdk.h"
 
 static struct map_desc qt2410_iodesc[] __initdata = {
 	{ 0xe0000000, __phys_to_pfn(S3C2410_CS3+0x01000000), SZ_1M, MT_DEVICE }
@@ -304,6 +305,7 @@ static void __init qt2410_map_io(void)
 	s3c24xx_init_io(qt2410_iodesc, ARRAY_SIZE(qt2410_iodesc));
 	s3c24xx_init_clocks(12*1000*1000);
 	s3c24xx_init_uarts(smdk2410_uartcfgs, ARRAY_SIZE(smdk2410_uartcfgs));
+	samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
 static void __init qt2410_machine_init(void)
@@ -341,8 +343,8 @@ static void __init qt2410_machine_init(void)
 MACHINE_START(QT2410, "QT2410")
 	.atag_offset	= 0x100,
 	.map_io		= qt2410_map_io,
-	.init_irq	= s3c24xx_init_irq,
+	.init_irq	= s3c2410_init_irq,
 	.init_machine	= qt2410_machine_init,
-	.init_time	= s3c24xx_timer_init,
+	.init_time	= samsung_timer_init,
 	.restart	= s3c2410_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/mach-rx1950.c b/arch/arm/mach-s3c24xx/mach-rx1950.c
index 1f9ba2a..44ca018 100644
--- a/arch/arm/mach-s3c24xx/mach-rx1950.c
+++ b/arch/arm/mach-s3c24xx/mach-rx1950.c
@@ -56,8 +56,8 @@
 #include <plat/cpu.h>
 #include <plat/devs.h>
 #include <plat/pm.h>
-#include <plat/regs-iic.h>
 #include <plat/regs-serial.h>
+#include <plat/samsung-time.h>
 
 #include "common.h"
 #include "h1940.h"
@@ -741,6 +741,7 @@ static void __init rx1950_map_io(void)
 	s3c24xx_init_io(rx1950_iodesc, ARRAY_SIZE(rx1950_iodesc));
 	s3c24xx_init_clocks(16934000);
 	s3c24xx_init_uarts(rx1950_uartcfgs, ARRAY_SIZE(rx1950_uartcfgs));
+	samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 
 	/* setup PM */
 
@@ -811,8 +812,8 @@ MACHINE_START(RX1950, "HP iPAQ RX1950")
 	.atag_offset = 0x100,
 	.map_io = rx1950_map_io,
 	.reserve	= rx1950_reserve,
-	.init_irq = s3c24xx_init_irq,
+	.init_irq	= s3c2442_init_irq,
 	.init_machine = rx1950_init_machine,
-	.init_time	= s3c24xx_timer_init,
+	.init_time	= samsung_timer_init,
 	.restart	= s3c244x_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/mach-rx3715.c b/arch/arm/mach-s3c24xx/mach-rx3715.c
index f20418a..3bc6231 100644
--- a/arch/arm/mach-s3c24xx/mach-rx3715.c
+++ b/arch/arm/mach-s3c24xx/mach-rx3715.c
@@ -49,6 +49,7 @@
 #include <plat/devs.h>
 #include <plat/pm.h>
 #include <plat/regs-serial.h>
+#include <plat/samsung-time.h>
 
 #include "common.h"
 #include "h1940.h"
@@ -179,6 +180,7 @@ static void __init rx3715_map_io(void)
 	s3c24xx_init_io(rx3715_iodesc, ARRAY_SIZE(rx3715_iodesc));
 	s3c24xx_init_clocks(16934000);
 	s3c24xx_init_uarts(rx3715_uartcfgs, ARRAY_SIZE(rx3715_uartcfgs));
+	samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
 /* H1940 and RX3715 need to reserve this for suspend */
@@ -188,11 +190,6 @@ static void __init rx3715_reserve(void)
 	memblock_reserve(0x30081000, 0x1000);
 }
 
-static void __init rx3715_init_irq(void)
-{
-	s3c24xx_init_irq();
-}
-
 static void __init rx3715_init_machine(void)
 {
 #ifdef CONFIG_PM_H1940
@@ -210,8 +207,8 @@ MACHINE_START(RX3715, "IPAQ-RX3715")
 	.atag_offset	= 0x100,
 	.map_io		= rx3715_map_io,
 	.reserve	= rx3715_reserve,
-	.init_irq	= rx3715_init_irq,
+	.init_irq	= s3c2440_init_irq,
 	.init_machine	= rx3715_init_machine,
-	.init_time	= s3c24xx_timer_init,
+	.init_time	= samsung_timer_init,
 	.restart	= s3c244x_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/mach-smdk2410.c b/arch/arm/mach-s3c24xx/mach-smdk2410.c
index e184bfa..a773789 100644
--- a/arch/arm/mach-s3c24xx/mach-smdk2410.c
+++ b/arch/arm/mach-s3c24xx/mach-smdk2410.c
@@ -51,10 +51,10 @@
 
 #include <plat/devs.h>
 #include <plat/cpu.h>
-
-#include <plat/common-smdk.h>
+#include <plat/samsung-time.h>
 
 #include "common.h"
+#include "common-smdk.h"
 
 static struct map_desc smdk2410_iodesc[] __initdata = {
   /* nothing here yet */
@@ -101,6 +101,7 @@ static void __init smdk2410_map_io(void)
 	s3c24xx_init_io(smdk2410_iodesc, ARRAY_SIZE(smdk2410_iodesc));
 	s3c24xx_init_clocks(0);
 	s3c24xx_init_uarts(smdk2410_uartcfgs, ARRAY_SIZE(smdk2410_uartcfgs));
+	samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
 static void __init smdk2410_init(void)
@@ -115,8 +116,8 @@ MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switc
 	/* Maintainer: Jonas Dietsche */
 	.atag_offset	= 0x100,
 	.map_io		= smdk2410_map_io,
-	.init_irq	= s3c24xx_init_irq,
+	.init_irq	= s3c2410_init_irq,
 	.init_machine	= smdk2410_init,
-	.init_time	= s3c24xx_timer_init,
+	.init_time	= samsung_timer_init,
 	.restart	= s3c2410_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/mach-smdk2413.c b/arch/arm/mach-s3c24xx/mach-smdk2413.c
index 86d7847..8146e92 100644
--- a/arch/arm/mach-s3c24xx/mach-smdk2413.c
+++ b/arch/arm/mach-s3c24xx/mach-smdk2413.c
@@ -41,13 +41,13 @@
 #include <linux/platform_data/i2c-s3c2410.h>
 #include <mach/fb.h>
 
-#include <plat/s3c2410.h>
-#include <plat/s3c2412.h>
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
+#include <plat/samsung-time.h>
 
-#include <plat/common-smdk.h>
+#include "common.h"
+#include "common-smdk.h"
 
 static struct map_desc smdk2413_iodesc[] __initdata = {
 };
@@ -106,6 +106,7 @@ static void __init smdk2413_map_io(void)
 	s3c24xx_init_io(smdk2413_iodesc, ARRAY_SIZE(smdk2413_iodesc));
 	s3c24xx_init_clocks(12000000);
 	s3c24xx_init_uarts(smdk2413_uartcfgs, ARRAY_SIZE(smdk2413_uartcfgs));
+	samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
 static void __init smdk2413_machine_init(void)
@@ -129,10 +130,10 @@ MACHINE_START(S3C2413, "S3C2413")
 	.atag_offset	= 0x100,
 
 	.fixup		= smdk2413_fixup,
-	.init_irq	= s3c24xx_init_irq,
+	.init_irq	= s3c2412_init_irq,
 	.map_io		= smdk2413_map_io,
 	.init_machine	= smdk2413_machine_init,
-	.init_time	= s3c24xx_timer_init,
+	.init_time	= samsung_timer_init,
 	.restart	= s3c2412_restart,
 MACHINE_END
 
@@ -141,10 +142,10 @@ MACHINE_START(SMDK2412, "SMDK2412")
 	.atag_offset	= 0x100,
 
 	.fixup		= smdk2413_fixup,
-	.init_irq	= s3c24xx_init_irq,
+	.init_irq	= s3c2412_init_irq,
 	.map_io		= smdk2413_map_io,
 	.init_machine	= smdk2413_machine_init,
-	.init_time	= s3c24xx_timer_init,
+	.init_time	= samsung_timer_init,
 	.restart	= s3c2412_restart,
 MACHINE_END
 
@@ -153,9 +154,9 @@ MACHINE_START(SMDK2413, "SMDK2413")
 	.atag_offset	= 0x100,
 
 	.fixup		= smdk2413_fixup,
-	.init_irq	= s3c24xx_init_irq,
+	.init_irq	= s3c2412_init_irq,
 	.map_io		= smdk2413_map_io,
 	.init_machine	= smdk2413_machine_init,
-	.init_time	= s3c24xx_timer_init,
+	.init_time	= samsung_timer_init,
 	.restart	= s3c2412_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/mach-smdk2416.c b/arch/arm/mach-s3c24xx/mach-smdk2416.c
index ebb2e61..cb46847 100644
--- a/arch/arm/mach-s3c24xx/mach-smdk2416.c
+++ b/arch/arm/mach-s3c24xx/mach-smdk2416.c
@@ -42,7 +42,6 @@
 #include <linux/platform_data/leds-s3c24xx.h>
 #include <linux/platform_data/i2c-s3c2410.h>
 
-#include <plat/s3c2416.h>
 #include <plat/gpio-cfg.h>
 #include <plat/clock.h>
 #include <plat/devs.h>
@@ -51,10 +50,12 @@
 #include <plat/sdhci.h>
 #include <linux/platform_data/usb-s3c2410_udc.h>
 #include <linux/platform_data/s3c-hsudc.h>
+#include <plat/samsung-time.h>
 
 #include <plat/fb.h>
 
-#include <plat/common-smdk.h>
+#include "common.h"
+#include "common-smdk.h"
 
 static struct map_desc smdk2416_iodesc[] __initdata = {
 	/* ISA IO Space map (memory space selected by A24) */
@@ -221,6 +222,7 @@ static void __init smdk2416_map_io(void)
 	s3c24xx_init_io(smdk2416_iodesc, ARRAY_SIZE(smdk2416_iodesc));
 	s3c24xx_init_clocks(12000000);
 	s3c24xx_init_uarts(smdk2416_uartcfgs, ARRAY_SIZE(smdk2416_uartcfgs));
+	samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
 static void __init smdk2416_machine_init(void)
@@ -253,6 +255,6 @@ MACHINE_START(SMDK2416, "SMDK2416")
 	.init_irq	= s3c2416_init_irq,
 	.map_io		= smdk2416_map_io,
 	.init_machine	= smdk2416_machine_init,
-	.init_time	= s3c24xx_timer_init,
+	.init_time	= samsung_timer_init,
 	.restart	= s3c2416_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/mach-smdk2440.c b/arch/arm/mach-s3c24xx/mach-smdk2440.c
index 08cc38c..de2e5d3 100644
--- a/arch/arm/mach-s3c24xx/mach-smdk2440.c
+++ b/arch/arm/mach-s3c24xx/mach-smdk2440.c
@@ -38,15 +38,13 @@
 #include <mach/fb.h>
 #include <linux/platform_data/i2c-s3c2410.h>
 
-#include <plat/s3c2410.h>
-#include <plat/s3c244x.h>
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
-
-#include <plat/common-smdk.h>
+#include <plat/samsung-time.h>
 
 #include "common.h"
+#include "common-smdk.h"
 
 static struct map_desc smdk2440_iodesc[] __initdata = {
 	/* ISA IO Space map (memory space selected by A24) */
@@ -163,6 +161,7 @@ static void __init smdk2440_map_io(void)
 	s3c24xx_init_io(smdk2440_iodesc, ARRAY_SIZE(smdk2440_iodesc));
 	s3c24xx_init_clocks(16934400);
 	s3c24xx_init_uarts(smdk2440_uartcfgs, ARRAY_SIZE(smdk2440_uartcfgs));
+	samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
 static void __init smdk2440_machine_init(void)
@@ -178,9 +177,9 @@ MACHINE_START(S3C2440, "SMDK2440")
 	/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
 	.atag_offset	= 0x100,
 
-	.init_irq	= s3c24xx_init_irq,
+	.init_irq	= s3c2440_init_irq,
 	.map_io		= smdk2440_map_io,
 	.init_machine	= smdk2440_machine_init,
-	.init_time	= s3c24xx_timer_init,
+	.init_time	= samsung_timer_init,
 	.restart	= s3c244x_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/mach-smdk2443.c b/arch/arm/mach-s3c24xx/mach-smdk2443.c
index fc65d74..9435c3b 100644
--- a/arch/arm/mach-s3c24xx/mach-smdk2443.c
+++ b/arch/arm/mach-s3c24xx/mach-smdk2443.c
@@ -38,13 +38,13 @@
 #include <mach/fb.h>
 #include <linux/platform_data/i2c-s3c2410.h>
 
-#include <plat/s3c2410.h>
-#include <plat/s3c2443.h>
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
+#include <plat/samsung-time.h>
 
-#include <plat/common-smdk.h>
+#include "common.h"
+#include "common-smdk.h"
 
 static struct map_desc smdk2443_iodesc[] __initdata = {
 	/* ISA IO Space map (memory space selected by A24) */
@@ -122,6 +122,7 @@ static void __init smdk2443_map_io(void)
 	s3c24xx_init_io(smdk2443_iodesc, ARRAY_SIZE(smdk2443_iodesc));
 	s3c24xx_init_clocks(12000000);
 	s3c24xx_init_uarts(smdk2443_uartcfgs, ARRAY_SIZE(smdk2443_uartcfgs));
+	samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
 static void __init smdk2443_machine_init(void)
@@ -143,6 +144,6 @@ MACHINE_START(SMDK2443, "SMDK2443")
 	.init_irq	= s3c2443_init_irq,
 	.map_io		= smdk2443_map_io,
 	.init_machine	= smdk2443_machine_init,
-	.init_time	= s3c24xx_timer_init,
+	.init_time	= samsung_timer_init,
 	.restart	= s3c2443_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/mach-tct_hammer.c b/arch/arm/mach-s3c24xx/mach-tct_hammer.c
index 24b3d79..7fad8f0 100644
--- a/arch/arm/mach-s3c24xx/mach-tct_hammer.c
+++ b/arch/arm/mach-s3c24xx/mach-tct_hammer.c
@@ -53,6 +53,7 @@
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/map.h>
 #include <linux/mtd/physmap.h>
+#include <plat/samsung-time.h>
 
 #include "common.h"
 
@@ -136,6 +137,7 @@ static void __init tct_hammer_map_io(void)
 	s3c24xx_init_io(tct_hammer_iodesc, ARRAY_SIZE(tct_hammer_iodesc));
 	s3c24xx_init_clocks(0);
 	s3c24xx_init_uarts(tct_hammer_uartcfgs, ARRAY_SIZE(tct_hammer_uartcfgs));
+	samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
 static void __init tct_hammer_init(void)
@@ -147,8 +149,8 @@ static void __init tct_hammer_init(void)
 MACHINE_START(TCT_HAMMER, "TCT_HAMMER")
 	.atag_offset	= 0x100,
 	.map_io		= tct_hammer_map_io,
-	.init_irq	= s3c24xx_init_irq,
+	.init_irq	= s3c2410_init_irq,
 	.init_machine	= tct_hammer_init,
-	.init_time	= s3c24xx_timer_init,
+	.init_time	= samsung_timer_init,
 	.restart	= s3c2410_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/mach-vr1000.c b/arch/arm/mach-s3c24xx/mach-vr1000.c
index ec42d1e..42e7187 100644
--- a/arch/arm/mach-s3c24xx/mach-vr1000.c
+++ b/arch/arm/mach-s3c24xx/mach-vr1000.c
@@ -45,6 +45,7 @@
 #include <plat/cpu.h>
 #include <plat/devs.h>
 #include <plat/regs-serial.h>
+#include <plat/samsung-time.h>
 
 #include "bast.h"
 #include "common.h"
@@ -332,6 +333,7 @@ static void __init vr1000_map_io(void)
 	s3c24xx_init_io(vr1000_iodesc, ARRAY_SIZE(vr1000_iodesc));
 	s3c24xx_init_clocks(0);
 	s3c24xx_init_uarts(vr1000_uartcfgs, ARRAY_SIZE(vr1000_uartcfgs));
+	samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
 static void __init vr1000_init(void)
@@ -353,7 +355,7 @@ MACHINE_START(VR1000, "Thorcom-VR1000")
 	.atag_offset	= 0x100,
 	.map_io		= vr1000_map_io,
 	.init_machine	= vr1000_init,
-	.init_irq	= s3c24xx_init_irq,
-	.init_time	= s3c24xx_timer_init,
+	.init_irq	= s3c2410_init_irq,
+	.init_time	= samsung_timer_init,
 	.restart	= s3c2410_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/mach-vstms.c b/arch/arm/mach-s3c24xx/mach-vstms.c
index 3e2bfdd..b665884 100644
--- a/arch/arm/mach-s3c24xx/mach-vstms.c
+++ b/arch/arm/mach-s3c24xx/mach-vstms.c
@@ -41,12 +41,12 @@
 #include <linux/platform_data/i2c-s3c2410.h>
 #include <linux/platform_data/mtd-nand-s3c2410.h>
 
-#include <plat/s3c2410.h>
-#include <plat/s3c2412.h>
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
+#include <plat/samsung-time.h>
 
+#include "common.h"
 
 static struct map_desc vstms_iodesc[] __initdata = {
 };
@@ -143,6 +143,7 @@ static void __init vstms_map_io(void)
 	s3c24xx_init_io(vstms_iodesc, ARRAY_SIZE(vstms_iodesc));
 	s3c24xx_init_clocks(12000000);
 	s3c24xx_init_uarts(vstms_uartcfgs, ARRAY_SIZE(vstms_uartcfgs));
+	samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
 static void __init vstms_init(void)
@@ -157,9 +158,9 @@ MACHINE_START(VSTMS, "VSTMS")
 	.atag_offset	= 0x100,
 
 	.fixup		= vstms_fixup,
-	.init_irq	= s3c24xx_init_irq,
+	.init_irq	= s3c2412_init_irq,
 	.init_machine	= vstms_init,
 	.map_io		= vstms_map_io,
-	.init_time	= s3c24xx_timer_init,
+	.init_time	= samsung_timer_init,
 	.restart	= s3c2412_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/pm-s3c2412.c b/arch/arm/mach-s3c24xx/pm-s3c2412.c
index 668a78a..d75f95e 100644
--- a/arch/arm/mach-s3c24xx/pm-s3c2412.c
+++ b/arch/arm/mach-s3c24xx/pm-s3c2412.c
@@ -29,7 +29,7 @@
 
 #include <plat/cpu.h>
 #include <plat/pm.h>
-#include <plat/s3c2412.h>
+#include <plat/wakeup-mask.h>
 
 #include "regs-dsc.h"
 #include "s3c2412-power.h"
@@ -52,8 +52,15 @@ static int s3c2412_cpu_suspend(unsigned long arg)
 	return 1; /* Aborting suspend */
 }
 
+/* mapping of interrupts to parts of the wakeup mask */
+static struct samsung_wakeup_mask wake_irqs[] = {
+	{ .irq = IRQ_RTC,	.bit = S3C2412_PWRCFG_RTC_MASKIRQ, },
+};
+
 static void s3c2412_pm_prepare(void)
 {
+	samsung_sync_wakemask(S3C2412_PWRCFG,
+			      wake_irqs, ARRAY_SIZE(wake_irqs));
 }
 
 static int s3c2412_pm_add(struct device *dev, struct subsys_interface *sif)
diff --git a/arch/arm/mach-s3c24xx/s3c2410.c b/arch/arm/mach-s3c24xx/s3c2410.c
index 9ebef95..d850ea5 100644
--- a/arch/arm/mach-s3c24xx/s3c2410.c
+++ b/arch/arm/mach-s3c24xx/s3c2410.c
@@ -37,7 +37,6 @@
 #include <mach/regs-clock.h>
 #include <plat/regs-serial.h>
 
-#include <plat/s3c2410.h>
 #include <plat/cpu.h>
 #include <plat/devs.h>
 #include <plat/clock.h>
diff --git a/arch/arm/mach-s3c24xx/s3c2412.c b/arch/arm/mach-s3c24xx/s3c2412.c
index 0d59215..0f864d4 100644
--- a/arch/arm/mach-s3c24xx/s3c2412.c
+++ b/arch/arm/mach-s3c24xx/s3c2412.c
@@ -44,7 +44,6 @@
 #include <plat/pm.h>
 #include <plat/regs-serial.h>
 #include <plat/regs-spi.h>
-#include <plat/s3c2412.h>
 
 #include "common.h"
 #include "regs-dsc.h"
diff --git a/arch/arm/mach-s3c24xx/s3c2416.c b/arch/arm/mach-s3c24xx/s3c2416.c
index e30476d..b9c5d38 100644
--- a/arch/arm/mach-s3c24xx/s3c2416.c
+++ b/arch/arm/mach-s3c24xx/s3c2416.c
@@ -50,7 +50,6 @@
 #include <plat/gpio-core.h>
 #include <plat/gpio-cfg.h>
 #include <plat/gpio-cfg-helpers.h>
-#include <plat/s3c2416.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
 #include <plat/sdhci.h>
diff --git a/arch/arm/mach-s3c24xx/s3c2440.c b/arch/arm/mach-s3c24xx/s3c2440.c
index 559e394..5f9d656 100644
--- a/arch/arm/mach-s3c24xx/s3c2440.c
+++ b/arch/arm/mach-s3c24xx/s3c2440.c
@@ -33,7 +33,6 @@
 
 #include <plat/devs.h>
 #include <plat/cpu.h>
-#include <plat/s3c244x.h>
 #include <plat/pm.h>
 
 #include <plat/gpio-core.h>
diff --git a/arch/arm/mach-s3c24xx/s3c2442.c b/arch/arm/mach-s3c24xx/s3c2442.c
index f732826..6819961 100644
--- a/arch/arm/mach-s3c24xx/s3c2442.c
+++ b/arch/arm/mach-s3c24xx/s3c2442.c
@@ -44,7 +44,6 @@
 
 #include <plat/clock.h>
 #include <plat/cpu.h>
-#include <plat/s3c244x.h>
 #include <plat/pm.h>
 
 #include <plat/gpio-core.h>
diff --git a/arch/arm/mach-s3c24xx/s3c2443.c b/arch/arm/mach-s3c24xx/s3c2443.c
index 165b6a6..8328cd6 100644
--- a/arch/arm/mach-s3c24xx/s3c2443.c
+++ b/arch/arm/mach-s3c24xx/s3c2443.c
@@ -36,7 +36,6 @@
 #include <plat/gpio-core.h>
 #include <plat/gpio-cfg.h>
 #include <plat/gpio-cfg-helpers.h>
-#include <plat/s3c2443.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
 #include <plat/fb-core.h>
diff --git a/arch/arm/mach-s3c24xx/s3c244x.c b/arch/arm/mach-s3c24xx/s3c244x.c
index ad2671b..2a35edb 100644
--- a/arch/arm/mach-s3c24xx/s3c244x.c
+++ b/arch/arm/mach-s3c24xx/s3c244x.c
@@ -37,8 +37,6 @@
 #include <plat/regs-serial.h>
 #include <mach/regs-gpio.h>
 
-#include <plat/s3c2410.h>
-#include <plat/s3c244x.h>
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
diff --git a/arch/arm/mach-s3c64xx/Kconfig b/arch/arm/mach-s3c64xx/Kconfig
index 131c862..283cb77 100644
--- a/arch/arm/mach-s3c64xx/Kconfig
+++ b/arch/arm/mach-s3c64xx/Kconfig
@@ -17,11 +17,13 @@ config PLAT_S3C64XX
 # Configuration options for the S3C6410 CPU
 
 config CPU_S3C6400
+	select SAMSUNG_HRT
 	bool
 	help
 	  Enable S3C6400 CPU support
 
 config CPU_S3C6410
+	select SAMSUNG_HRT
 	bool
 	help
 	  Enable S3C6410 CPU support
diff --git a/arch/arm/mach-s3c64xx/Makefile b/arch/arm/mach-s3c64xx/Makefile
index f9ce1dc..31d0c91 100644
--- a/arch/arm/mach-s3c64xx/Makefile
+++ b/arch/arm/mach-s3c64xx/Makefile
@@ -32,7 +32,6 @@ obj-$(CONFIG_S3C64XX_DMA)	+= dma.o
 
 obj-y				+= dev-uart.o
 obj-y				+= dev-audio.o
-obj-$(CONFIG_S3C64XX_DEV_SPI)	+= dev-spi.o
 
 # Device setup
 
diff --git a/arch/arm/mach-s3c64xx/dma.c b/arch/arm/mach-s3c64xx/dma.c
index 6af1aa1..759846c 100644
--- a/arch/arm/mach-s3c64xx/dma.c
+++ b/arch/arm/mach-s3c64xx/dma.c
@@ -509,6 +509,7 @@ int s3c2410_dma_request(enum dma_ch channel,
 	chan->client = client;
 	chan->in_use = 1;
 	chan->peripheral = channel;
+	chan->flags = 0;
 
 	local_irq_restore(flags);
 
diff --git a/arch/arm/mach-s3c64xx/mach-anw6410.c b/arch/arm/mach-s3c64xx/mach-anw6410.c
index 728eef3..35e3f54 100644
--- a/arch/arm/mach-s3c64xx/mach-anw6410.c
+++ b/arch/arm/mach-s3c64xx/mach-anw6410.c
@@ -49,6 +49,7 @@
 #include <plat/devs.h>
 #include <plat/cpu.h>
 #include <mach/regs-gpio.h>
+#include <plat/samsung-time.h>
 
 #include "common.h"
 #include "regs-modem.h"
@@ -208,6 +209,7 @@ static void __init anw6410_map_io(void)
 	s3c64xx_init_io(anw6410_iodesc, ARRAY_SIZE(anw6410_iodesc));
 	s3c24xx_init_clocks(12000000);
 	s3c24xx_init_uarts(anw6410_uartcfgs, ARRAY_SIZE(anw6410_uartcfgs));
+	samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 
 	anw6410_lcd_mode_set();
 }
@@ -232,6 +234,6 @@ MACHINE_START(ANW6410, "A&W6410")
 	.map_io		= anw6410_map_io,
 	.init_machine	= anw6410_machine_init,
 	.init_late	= s3c64xx_init_late,
-	.init_time	= s3c24xx_timer_init,
+	.init_time	= samsung_timer_init,
 	.restart	= s3c64xx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c64xx/mach-crag6410-module.c b/arch/arm/mach-s3c64xx/mach-crag6410-module.c
index bf3d1c0..a946b75 100644
--- a/arch/arm/mach-s3c64xx/mach-crag6410-module.c
+++ b/arch/arm/mach-s3c64xx/mach-crag6410-module.c
@@ -210,6 +210,7 @@ static struct arizona_pdata wm5102_reva_pdata = {
 	.gpio_base = CODEC_GPIO_BASE,
 	.irq_active_high = true,
 	.micd_pol_gpio = CODEC_GPIO_BASE + 4,
+	.micd_rate = 6,
 	.gpio_defaults = {
 		[2] = 0x10000, /* AIF3TXLRCLK */
 		[3] = 0x4,     /* OPCLK */
diff --git a/arch/arm/mach-s3c64xx/mach-crag6410.c b/arch/arm/mach-s3c64xx/mach-crag6410.c
index 1acf02b..8ad88ac 100644
--- a/arch/arm/mach-s3c64xx/mach-crag6410.c
+++ b/arch/arm/mach-s3c64xx/mach-crag6410.c
@@ -64,6 +64,7 @@
 #include <plat/adc.h>
 #include <linux/platform_data/i2c-s3c2410.h>
 #include <plat/pm.h>
+#include <plat/samsung-time.h>
 
 #include "common.h"
 #include "crag6410.h"
@@ -744,6 +745,7 @@ 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));
+	samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 
 	/* LCD type and Bypass set by bootloader */
 }
@@ -868,6 +870,6 @@ MACHINE_START(WLF_CRAGG_6410, "Wolfson Cragganmore 6410")
 	.map_io		= crag6410_map_io,
 	.init_machine	= crag6410_machine_init,
 	.init_late	= s3c64xx_init_late,
-	.init_time	= s3c24xx_timer_init,
+	.init_time	= samsung_timer_init,
 	.restart	= s3c64xx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c64xx/mach-hmt.c b/arch/arm/mach-s3c64xx/mach-hmt.c
index 7212eb9..5b7f357 100644
--- a/arch/arm/mach-s3c64xx/mach-hmt.c
+++ b/arch/arm/mach-s3c64xx/mach-hmt.c
@@ -41,6 +41,7 @@
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
+#include <plat/samsung-time.h>
 
 #include "common.h"
 
@@ -248,6 +249,7 @@ static void __init hmt_map_io(void)
 	s3c64xx_init_io(hmt_iodesc, ARRAY_SIZE(hmt_iodesc));
 	s3c24xx_init_clocks(12000000);
 	s3c24xx_init_uarts(hmt_uartcfgs, ARRAY_SIZE(hmt_uartcfgs));
+	samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
 static void __init hmt_machine_init(void)
@@ -275,6 +277,6 @@ MACHINE_START(HMT, "Airgoo-HMT")
 	.map_io		= hmt_map_io,
 	.init_machine	= hmt_machine_init,
 	.init_late	= s3c64xx_init_late,
-	.init_time	= s3c24xx_timer_init,
+	.init_time	= samsung_timer_init,
 	.restart	= s3c64xx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c64xx/mach-mini6410.c b/arch/arm/mach-s3c64xx/mach-mini6410.c
index 4b41fcd..fc043e3 100644
--- a/arch/arm/mach-s3c64xx/mach-mini6410.c
+++ b/arch/arm/mach-s3c64xx/mach-mini6410.c
@@ -41,6 +41,7 @@
 
 #include <video/platform_lcd.h>
 #include <video/samsung_fimd.h>
+#include <plat/samsung-time.h>
 
 #include "common.h"
 #include "regs-modem.h"
@@ -232,6 +233,7 @@ static void __init mini6410_map_io(void)
 	s3c64xx_init_io(NULL, 0);
 	s3c24xx_init_clocks(12000000);
 	s3c24xx_init_uarts(mini6410_uartcfgs, ARRAY_SIZE(mini6410_uartcfgs));
+	samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 
 	/* set the LCD type */
 	tmp = __raw_readl(S3C64XX_SPCON);
@@ -354,6 +356,6 @@ MACHINE_START(MINI6410, "MINI6410")
 	.map_io		= mini6410_map_io,
 	.init_machine	= mini6410_machine_init,
 	.init_late	= s3c64xx_init_late,
-	.init_time	= s3c24xx_timer_init,
+	.init_time	= samsung_timer_init,
 	.restart	= s3c64xx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c64xx/mach-ncp.c b/arch/arm/mach-s3c64xx/mach-ncp.c
index 8d3cedd..7e2c390 100644
--- a/arch/arm/mach-s3c64xx/mach-ncp.c
+++ b/arch/arm/mach-s3c64xx/mach-ncp.c
@@ -43,6 +43,7 @@
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
+#include <plat/samsung-time.h>
 
 #include "common.h"
 
@@ -87,6 +88,7 @@ static void __init ncp_map_io(void)
 	s3c64xx_init_io(ncp_iodesc, ARRAY_SIZE(ncp_iodesc));
 	s3c24xx_init_clocks(12000000);
 	s3c24xx_init_uarts(ncp_uartcfgs, ARRAY_SIZE(ncp_uartcfgs));
+	samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
 static void __init ncp_machine_init(void)
@@ -103,6 +105,6 @@ MACHINE_START(NCP, "NCP")
 	.map_io		= ncp_map_io,
 	.init_machine	= ncp_machine_init,
 	.init_late	= s3c64xx_init_late,
-	.init_time	= s3c24xx_timer_init,
+	.init_time	= samsung_timer_init,
 	.restart	= s3c64xx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c64xx/mach-real6410.c b/arch/arm/mach-s3c64xx/mach-real6410.c
index fa12bd2..8bed37b 100644
--- a/arch/arm/mach-s3c64xx/mach-real6410.c
+++ b/arch/arm/mach-s3c64xx/mach-real6410.c
@@ -42,6 +42,7 @@
 
 #include <video/platform_lcd.h>
 #include <video/samsung_fimd.h>
+#include <plat/samsung-time.h>
 
 #include "common.h"
 #include "regs-modem.h"
@@ -211,6 +212,7 @@ static void __init real6410_map_io(void)
 	s3c64xx_init_io(NULL, 0);
 	s3c24xx_init_clocks(12000000);
 	s3c24xx_init_uarts(real6410_uartcfgs, ARRAY_SIZE(real6410_uartcfgs));
+	samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 
 	/* set the LCD type */
 	tmp = __raw_readl(S3C64XX_SPCON);
@@ -333,6 +335,6 @@ MACHINE_START(REAL6410, "REAL6410")
 	.map_io		= real6410_map_io,
 	.init_machine	= real6410_machine_init,
 	.init_late	= s3c64xx_init_late,
-	.init_time	= s3c24xx_timer_init,
+	.init_time	= samsung_timer_init,
 	.restart	= s3c64xx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c64xx/mach-smartq.c b/arch/arm/mach-s3c64xx/mach-smartq.c
index fc3e9b3..58ac990 100644
--- a/arch/arm/mach-s3c64xx/mach-smartq.c
+++ b/arch/arm/mach-s3c64xx/mach-smartq.c
@@ -38,6 +38,7 @@
 #include <linux/platform_data/touchscreen-s3c2410.h>
 
 #include <video/platform_lcd.h>
+#include <plat/samsung-time.h>
 
 #include "common.h"
 #include "regs-modem.h"
@@ -378,6 +379,7 @@ void __init smartq_map_io(void)
 	s3c64xx_init_io(smartq_iodesc, ARRAY_SIZE(smartq_iodesc));
 	s3c24xx_init_clocks(12000000);
 	s3c24xx_init_uarts(smartq_uartcfgs, ARRAY_SIZE(smartq_uartcfgs));
+	samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 
 	smartq_lcd_mode_set();
 }
diff --git a/arch/arm/mach-s3c64xx/mach-smartq5.c b/arch/arm/mach-s3c64xx/mach-smartq5.c
index ca2afcf..8aca5da 100644
--- a/arch/arm/mach-s3c64xx/mach-smartq5.c
+++ b/arch/arm/mach-s3c64xx/mach-smartq5.c
@@ -28,6 +28,7 @@
 #include <plat/devs.h>
 #include <plat/fb.h>
 #include <plat/gpio-cfg.h>
+#include <plat/samsung-time.h>
 
 #include "common.h"
 #include "mach-smartq.h"
@@ -155,6 +156,6 @@ MACHINE_START(SMARTQ5, "SmartQ 5")
 	.map_io		= smartq_map_io,
 	.init_machine	= smartq5_machine_init,
 	.init_late	= s3c64xx_init_late,
-	.init_time	= s3c24xx_timer_init,
+	.init_time	= samsung_timer_init,
 	.restart	= s3c64xx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c64xx/mach-smartq7.c b/arch/arm/mach-s3c64xx/mach-smartq7.c
index 37bb0c6..a052e10 100644
--- a/arch/arm/mach-s3c64xx/mach-smartq7.c
+++ b/arch/arm/mach-s3c64xx/mach-smartq7.c
@@ -28,6 +28,7 @@
 #include <plat/devs.h>
 #include <plat/fb.h>
 #include <plat/gpio-cfg.h>
+#include <plat/samsung-time.h>
 
 #include "common.h"
 #include "mach-smartq.h"
@@ -171,6 +172,6 @@ MACHINE_START(SMARTQ7, "SmartQ 7")
 	.map_io		= smartq_map_io,
 	.init_machine	= smartq7_machine_init,
 	.init_late	= s3c64xx_init_late,
-	.init_time	= s3c24xx_timer_init,
+	.init_time	= samsung_timer_init,
 	.restart	= s3c64xx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c64xx/mach-smdk6400.c b/arch/arm/mach-s3c64xx/mach-smdk6400.c
index a392869..d70c084 100644
--- a/arch/arm/mach-s3c64xx/mach-smdk6400.c
+++ b/arch/arm/mach-s3c64xx/mach-smdk6400.c
@@ -35,6 +35,7 @@
 #include <plat/devs.h>
 #include <plat/cpu.h>
 #include <linux/platform_data/i2c-s3c2410.h>
+#include <plat/samsung-time.h>
 
 #include "common.h"
 
@@ -66,6 +67,7 @@ static void __init smdk6400_map_io(void)
 	s3c64xx_init_io(smdk6400_iodesc, ARRAY_SIZE(smdk6400_iodesc));
 	s3c24xx_init_clocks(12000000);
 	s3c24xx_init_uarts(smdk6400_uartcfgs, ARRAY_SIZE(smdk6400_uartcfgs));
+	samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
 static struct platform_device *smdk6400_devices[] __initdata = {
@@ -92,6 +94,6 @@ MACHINE_START(SMDK6400, "SMDK6400")
 	.map_io		= smdk6400_map_io,
 	.init_machine	= smdk6400_machine_init,
 	.init_late	= s3c64xx_init_late,
-	.init_time	= s3c24xx_timer_init,
+	.init_time	= samsung_timer_init,
 	.restart	= s3c64xx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c64xx/mach-smdk6410.c b/arch/arm/mach-s3c64xx/mach-smdk6410.c
index ba7544e..bd3295a 100644
--- a/arch/arm/mach-s3c64xx/mach-smdk6410.c
+++ b/arch/arm/mach-s3c64xx/mach-smdk6410.c
@@ -69,6 +69,7 @@
 #include <linux/platform_data/touchscreen-s3c2410.h>
 #include <plat/keypad.h>
 #include <plat/backlight.h>
+#include <plat/samsung-time.h>
 
 #include "common.h"
 #include "regs-modem.h"
@@ -634,6 +635,7 @@ static void __init smdk6410_map_io(void)
 	s3c64xx_init_io(smdk6410_iodesc, ARRAY_SIZE(smdk6410_iodesc));
 	s3c24xx_init_clocks(12000000);
 	s3c24xx_init_uarts(smdk6410_uartcfgs, ARRAY_SIZE(smdk6410_uartcfgs));
+	samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 
 	/* set the LCD type */
 
@@ -702,6 +704,6 @@ MACHINE_START(SMDK6410, "SMDK6410")
 	.map_io		= smdk6410_map_io,
 	.init_machine	= smdk6410_machine_init,
 	.init_late	= s3c64xx_init_late,
-	.init_time	= s3c24xx_timer_init,
+	.init_time	= samsung_timer_init,
 	.restart	= s3c64xx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s5p64x0/Kconfig b/arch/arm/mach-s5p64x0/Kconfig
index e8742cb..5a707bd 100644
--- a/arch/arm/mach-s5p64x0/Kconfig
+++ b/arch/arm/mach-s5p64x0/Kconfig
@@ -9,16 +9,16 @@ if ARCH_S5P64X0
 
 config CPU_S5P6440
 	bool
-	select S5P_HRT
 	select S5P_SLEEP if PM
 	select SAMSUNG_DMADEV
+	select SAMSUNG_HRT
 	select SAMSUNG_WAKEMASK if PM
 	help
 	  Enable S5P6440 CPU support
 
 config CPU_S5P6450
 	bool
-	select S5P_HRT
+	select SAMSUNG_HRT
 	select S5P_SLEEP if PM
 	select SAMSUNG_DMADEV
 	select SAMSUNG_WAKEMASK if PM
diff --git a/arch/arm/mach-s5p64x0/mach-smdk6440.c b/arch/arm/mach-s5p64x0/mach-smdk6440.c
index e23723a..73f71a6 100644
--- a/arch/arm/mach-s5p64x0/mach-smdk6440.c
+++ b/arch/arm/mach-s5p64x0/mach-smdk6440.c
@@ -48,7 +48,7 @@
 #include <plat/pll.h>
 #include <plat/adc.h>
 #include <linux/platform_data/touchscreen-s3c2410.h>
-#include <plat/s5p-time.h>
+#include <plat/samsung-time.h>
 #include <plat/backlight.h>
 #include <plat/fb.h>
 #include <plat/sdhci.h>
@@ -229,7 +229,7 @@ static void __init smdk6440_map_io(void)
 	s5p64x0_init_io(NULL, 0);
 	s3c24xx_init_clocks(12000000);
 	s3c24xx_init_uarts(smdk6440_uartcfgs, ARRAY_SIZE(smdk6440_uartcfgs));
-	s5p_set_timer_source(S5P_PWM3, S5P_PWM4);
+	samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
 static void s5p6440_set_lcd_interface(void)
@@ -273,6 +273,6 @@ MACHINE_START(SMDK6440, "SMDK6440")
 	.init_irq	= s5p6440_init_irq,
 	.map_io		= smdk6440_map_io,
 	.init_machine	= smdk6440_machine_init,
-	.init_time	= s5p_timer_init,
+	.init_time	= samsung_timer_init,
 	.restart	= s5p64x0_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s5p64x0/mach-smdk6450.c b/arch/arm/mach-s5p64x0/mach-smdk6450.c
index ca10963..18303e1 100644
--- a/arch/arm/mach-s5p64x0/mach-smdk6450.c
+++ b/arch/arm/mach-s5p64x0/mach-smdk6450.c
@@ -48,7 +48,7 @@
 #include <plat/pll.h>
 #include <plat/adc.h>
 #include <linux/platform_data/touchscreen-s3c2410.h>
-#include <plat/s5p-time.h>
+#include <plat/samsung-time.h>
 #include <plat/backlight.h>
 #include <plat/fb.h>
 #include <plat/sdhci.h>
@@ -248,7 +248,7 @@ static void __init smdk6450_map_io(void)
 	s5p64x0_init_io(NULL, 0);
 	s3c24xx_init_clocks(19200000);
 	s3c24xx_init_uarts(smdk6450_uartcfgs, ARRAY_SIZE(smdk6450_uartcfgs));
-	s5p_set_timer_source(S5P_PWM3, S5P_PWM4);
+	samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
 static void s5p6450_set_lcd_interface(void)
@@ -292,6 +292,6 @@ MACHINE_START(SMDK6450, "SMDK6450")
 	.init_irq	= s5p6450_init_irq,
 	.map_io		= smdk6450_map_io,
 	.init_machine	= smdk6450_machine_init,
-	.init_time	= s5p_timer_init,
+	.init_time	= samsung_timer_init,
 	.restart	= s5p64x0_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s5pc100/Kconfig b/arch/arm/mach-s5pc100/Kconfig
index 15170be..2f456a4 100644
--- a/arch/arm/mach-s5pc100/Kconfig
+++ b/arch/arm/mach-s5pc100/Kconfig
@@ -11,6 +11,7 @@ config CPU_S5PC100
 	bool
 	select S5P_EXT_INT
 	select SAMSUNG_DMADEV
+	select SAMSUNG_HRT
 	help
 	  Enable S5PC100 CPU support
 
diff --git a/arch/arm/mach-s5pc100/common.h b/arch/arm/mach-s5pc100/common.h
index 9fbd3ae..c41f912 100644
--- a/arch/arm/mach-s5pc100/common.h
+++ b/arch/arm/mach-s5pc100/common.h
@@ -20,18 +20,9 @@ void s5pc100_setup_clocks(void);
 
 void s5pc100_restart(char mode, const char *cmd);
 
-#ifdef CONFIG_CPU_S5PC100
-
 extern  int s5pc100_init(void);
 extern void s5pc100_map_io(void);
 extern void s5pc100_init_clocks(int xtal);
 extern void s5pc100_init_uarts(struct s3c2410_uartcfg *cfg, int no);
 
-#else
-#define s5pc100_init_clocks NULL
-#define s5pc100_init_uarts NULL
-#define s5pc100_map_io NULL
-#define s5pc100_init NULL
-#endif
-
 #endif /* __ARCH_ARM_MACH_S5PC100_COMMON_H */
diff --git a/arch/arm/mach-s5pc100/mach-smdkc100.c b/arch/arm/mach-s5pc100/mach-smdkc100.c
index 185a195..8c880f7 100644
--- a/arch/arm/mach-s5pc100/mach-smdkc100.c
+++ b/arch/arm/mach-s5pc100/mach-smdkc100.c
@@ -51,6 +51,7 @@
 #include <linux/platform_data/touchscreen-s3c2410.h>
 #include <linux/platform_data/asoc-s3c.h>
 #include <plat/backlight.h>
+#include <plat/samsung-time.h>
 
 #include "common.h"
 
@@ -221,6 +222,7 @@ static void __init smdkc100_map_io(void)
 	s5pc100_init_io(NULL, 0);
 	s3c24xx_init_clocks(12000000);
 	s3c24xx_init_uarts(smdkc100_uartcfgs, ARRAY_SIZE(smdkc100_uartcfgs));
+	samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
 static void __init smdkc100_machine_init(void)
@@ -255,6 +257,6 @@ MACHINE_START(SMDKC100, "SMDKC100")
 	.init_irq	= s5pc100_init_irq,
 	.map_io		= smdkc100_map_io,
 	.init_machine	= smdkc100_machine_init,
-	.init_time	= s3c24xx_timer_init,
+	.init_time	= samsung_timer_init,
 	.restart	= s5pc100_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s5pv210/Kconfig b/arch/arm/mach-s5pv210/Kconfig
index 92ad72f..0963283 100644
--- a/arch/arm/mach-s5pv210/Kconfig
+++ b/arch/arm/mach-s5pv210/Kconfig
@@ -12,10 +12,10 @@ if ARCH_S5PV210
 config CPU_S5PV210
 	bool
 	select S5P_EXT_INT
-	select S5P_HRT
 	select S5P_PM if PM
 	select S5P_SLEEP if PM
 	select SAMSUNG_DMADEV
+	select SAMSUNG_HRT
 	help
 	  Enable S5PV210 CPU support
 
diff --git a/arch/arm/mach-s5pv210/common.h b/arch/arm/mach-s5pv210/common.h
index 6ed2af5..0a1cc0ae 100644
--- a/arch/arm/mach-s5pv210/common.h
+++ b/arch/arm/mach-s5pv210/common.h
@@ -20,18 +20,9 @@ void s5pv210_setup_clocks(void);
 
 void s5pv210_restart(char mode, const char *cmd);
 
-#ifdef CONFIG_CPU_S5PV210
-
 extern  int s5pv210_init(void);
 extern void s5pv210_map_io(void);
 extern void s5pv210_init_clocks(int xtal);
 extern void s5pv210_init_uarts(struct s3c2410_uartcfg *cfg, int no);
 
-#else
-#define s5pv210_init_clocks NULL
-#define s5pv210_init_uarts NULL
-#define s5pv210_map_io NULL
-#define s5pv210_init NULL
-#endif
-
 #endif /* __ARCH_ARM_MACH_S5PV210_COMMON_H */
diff --git a/arch/arm/mach-s5pv210/mach-aquila.c b/arch/arm/mach-s5pv210/mach-aquila.c
index 11900a8..ed2b854 100644
--- a/arch/arm/mach-s5pv210/mach-aquila.c
+++ b/arch/arm/mach-s5pv210/mach-aquila.c
@@ -38,7 +38,7 @@
 #include <plat/fb.h>
 #include <plat/fimc-core.h>
 #include <plat/sdhci.h>
-#include <plat/s5p-time.h>
+#include <plat/samsung-time.h>
 
 #include "common.h"
 
@@ -651,7 +651,7 @@ static void __init aquila_map_io(void)
 	s5pv210_init_io(NULL, 0);
 	s3c24xx_init_clocks(24000000);
 	s3c24xx_init_uarts(aquila_uartcfgs, ARRAY_SIZE(aquila_uartcfgs));
-	s5p_set_timer_source(S5P_PWM3, S5P_PWM4);
+	samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
 static void __init aquila_machine_init(void)
@@ -686,6 +686,6 @@ MACHINE_START(AQUILA, "Aquila")
 	.init_irq	= s5pv210_init_irq,
 	.map_io		= aquila_map_io,
 	.init_machine	= aquila_machine_init,
-	.init_time	= s5p_timer_init,
+	.init_time	= samsung_timer_init,
 	.restart	= s5pv210_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s5pv210/mach-goni.c b/arch/arm/mach-s5pv210/mach-goni.c
index e373de4..30b24ad 100644
--- a/arch/arm/mach-s5pv210/mach-goni.c
+++ b/arch/arm/mach-s5pv210/mach-goni.c
@@ -47,7 +47,7 @@
 #include <plat/keypad.h>
 #include <plat/sdhci.h>
 #include <plat/clock.h>
-#include <plat/s5p-time.h>
+#include <plat/samsung-time.h>
 #include <plat/mfc.h>
 #include <plat/camport.h>
 
@@ -908,7 +908,7 @@ static void __init goni_map_io(void)
 	s5pv210_init_io(NULL, 0);
 	s3c24xx_init_clocks(clk_xusbxti.rate);
 	s3c24xx_init_uarts(goni_uartcfgs, ARRAY_SIZE(goni_uartcfgs));
-	s5p_set_timer_source(S5P_PWM3, S5P_PWM4);
+	samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
 static void __init goni_reserve(void)
@@ -973,7 +973,7 @@ MACHINE_START(GONI, "GONI")
 	.init_irq	= s5pv210_init_irq,
 	.map_io		= goni_map_io,
 	.init_machine	= goni_machine_init,
-	.init_time	= s5p_timer_init,
+	.init_time	= samsung_timer_init,
 	.reserve	= &goni_reserve,
 	.restart	= s5pv210_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s5pv210/mach-smdkc110.c b/arch/arm/mach-s5pv210/mach-smdkc110.c
index 28bd024..7c0ed07 100644
--- a/arch/arm/mach-s5pv210/mach-smdkc110.c
+++ b/arch/arm/mach-s5pv210/mach-smdkc110.c
@@ -29,7 +29,7 @@
 #include <linux/platform_data/ata-samsung_cf.h>
 #include <linux/platform_data/i2c-s3c2410.h>
 #include <plat/pm.h>
-#include <plat/s5p-time.h>
+#include <plat/samsung-time.h>
 #include <plat/mfc.h>
 
 #include "common.h"
@@ -120,7 +120,7 @@ static void __init smdkc110_map_io(void)
 	s5pv210_init_io(NULL, 0);
 	s3c24xx_init_clocks(24000000);
 	s3c24xx_init_uarts(smdkv210_uartcfgs, ARRAY_SIZE(smdkv210_uartcfgs));
-	s5p_set_timer_source(S5P_PWM3, S5P_PWM4);
+	samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
 static void __init smdkc110_reserve(void)
@@ -153,7 +153,7 @@ MACHINE_START(SMDKC110, "SMDKC110")
 	.init_irq	= s5pv210_init_irq,
 	.map_io		= smdkc110_map_io,
 	.init_machine	= smdkc110_machine_init,
-	.init_time	= s5p_timer_init,
+	.init_time	= samsung_timer_init,
 	.restart	= s5pv210_restart,
 	.reserve	= &smdkc110_reserve,
 MACHINE_END
diff --git a/arch/arm/mach-s5pv210/mach-smdkv210.c b/arch/arm/mach-s5pv210/mach-smdkv210.c
index 3c73f36..d50b6f1 100644
--- a/arch/arm/mach-s5pv210/mach-smdkv210.c
+++ b/arch/arm/mach-s5pv210/mach-smdkv210.c
@@ -44,7 +44,7 @@
 #include <plat/keypad.h>
 #include <plat/pm.h>
 #include <plat/fb.h>
-#include <plat/s5p-time.h>
+#include <plat/samsung-time.h>
 #include <plat/backlight.h>
 #include <plat/mfc.h>
 #include <plat/clock.h>
@@ -285,7 +285,7 @@ static void __init smdkv210_map_io(void)
 	s5pv210_init_io(NULL, 0);
 	s3c24xx_init_clocks(clk_xusbxti.rate);
 	s3c24xx_init_uarts(smdkv210_uartcfgs, ARRAY_SIZE(smdkv210_uartcfgs));
-	s5p_set_timer_source(S5P_PWM2, S5P_PWM4);
+	samsung_set_timer_source(SAMSUNG_PWM2, SAMSUNG_PWM4);
 }
 
 static void __init smdkv210_reserve(void)
@@ -329,7 +329,7 @@ MACHINE_START(SMDKV210, "SMDKV210")
 	.init_irq	= s5pv210_init_irq,
 	.map_io		= smdkv210_map_io,
 	.init_machine	= smdkv210_machine_init,
-	.init_time	= s5p_timer_init,
+	.init_time	= samsung_timer_init,
 	.restart	= s5pv210_restart,
 	.reserve	= &smdkv210_reserve,
 MACHINE_END
diff --git a/arch/arm/mach-s5pv210/mach-torbreck.c b/arch/arm/mach-s5pv210/mach-torbreck.c
index 2d4c553..579afe8 100644
--- a/arch/arm/mach-s5pv210/mach-torbreck.c
+++ b/arch/arm/mach-s5pv210/mach-torbreck.c
@@ -26,7 +26,7 @@
 #include <plat/devs.h>
 #include <plat/cpu.h>
 #include <linux/platform_data/i2c-s3c2410.h>
-#include <plat/s5p-time.h>
+#include <plat/samsung-time.h>
 
 #include "common.h"
 
@@ -106,7 +106,7 @@ static void __init torbreck_map_io(void)
 	s5pv210_init_io(NULL, 0);
 	s3c24xx_init_clocks(24000000);
 	s3c24xx_init_uarts(torbreck_uartcfgs, ARRAY_SIZE(torbreck_uartcfgs));
-	s5p_set_timer_source(S5P_PWM3, S5P_PWM4);
+	samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
 static void __init torbreck_machine_init(void)
@@ -130,6 +130,6 @@ MACHINE_START(TORBRECK, "TORBRECK")
 	.init_irq	= s5pv210_init_irq,
 	.map_io		= torbreck_map_io,
 	.init_machine	= torbreck_machine_init,
-	.init_time	= s5p_timer_init,
+	.init_time	= samsung_timer_init,
 	.restart	= s5pv210_restart,
 MACHINE_END
diff --git a/arch/arm/mach-sa1100/cpu-sa1100.c b/arch/arm/mach-sa1100/cpu-sa1100.c
index e8f4d1e..3268761 100644
--- a/arch/arm/mach-sa1100/cpu-sa1100.c
+++ b/arch/arm/mach-sa1100/cpu-sa1100.c
@@ -201,9 +201,8 @@ static int sa1100_target(struct cpufreq_policy *policy,
 
 	freqs.old = cur;
 	freqs.new = sa11x0_ppcr_to_freq(new_ppcr);
-	freqs.cpu = 0;
 
-	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
 
 	if (freqs.new > cur)
 		sa1100_update_dram_timings(cur, freqs.new);
@@ -213,7 +212,7 @@ static int sa1100_target(struct cpufreq_policy *policy,
 	if (freqs.new < cur)
 		sa1100_update_dram_timings(cur, freqs.new);
 
-	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
 
 	return 0;
 }
diff --git a/arch/arm/mach-sa1100/cpu-sa1110.c b/arch/arm/mach-sa1100/cpu-sa1110.c
index 48c45b0..38a7733 100644
--- a/arch/arm/mach-sa1100/cpu-sa1110.c
+++ b/arch/arm/mach-sa1100/cpu-sa1110.c
@@ -258,7 +258,6 @@ static int sa1110_target(struct cpufreq_policy *policy,
 
 	freqs.old = sa11x0_getspeed(0);
 	freqs.new = sa11x0_ppcr_to_freq(ppcr);
-	freqs.cpu = 0;
 
 	sdram_calculate_timing(&sd, freqs.new, sdram);
 
@@ -279,7 +278,7 @@ static int sa1110_target(struct cpufreq_policy *policy,
 	sd.mdcas[2] = 0xaaaaaaaa;
 #endif
 
-	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
 
 	/*
 	 * The clock could be going away for some time.  Set the SDRAMs
@@ -327,7 +326,7 @@ static int sa1110_target(struct cpufreq_policy *policy,
 	 */
 	sdram_update_refresh(freqs.new, sdram);
 
-	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
 
 	return 0;
 }
diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig
index 9255546..1a517e2 100644
--- a/arch/arm/mach-shmobile/Kconfig
+++ b/arch/arm/mach-shmobile/Kconfig
@@ -16,12 +16,30 @@ config ARCH_SH73A0
 	select CPU_V7
 	select I2C
 	select SH_CLK_CPG
+	select RENESAS_INTC_IRQPIN
+
+config ARCH_R8A73A4
+	bool "R-Mobile APE6 (R8A73A40)"
+	select ARCH_WANT_OPTIONAL_GPIOLIB
+	select ARM_GIC
+	select CPU_V7
+	select ARM_ARCH_TIMER
+	select SH_CLK_CPG
+	select RENESAS_IRQC
 
 config ARCH_R8A7740
 	bool "R-Mobile A1 (R8A77400)"
 	select ARCH_WANT_OPTIONAL_GPIOLIB
+	select ARM_GIC
 	select CPU_V7
 	select SH_CLK_CPG
+	select RENESAS_INTC_IRQPIN
+
+config ARCH_R8A7778
+	bool "R-Car M1 (R8A77780)"
+	select CPU_V7
+	select SH_CLK_CPG
+	select ARM_GIC
 
 config ARCH_R8A7779
 	bool "R-Car H1 (R8A77790)"
@@ -31,6 +49,16 @@ config ARCH_R8A7779
 	select SH_CLK_CPG
 	select USB_ARCH_HAS_EHCI
 	select USB_ARCH_HAS_OHCI
+	select RENESAS_INTC_IRQPIN
+
+config ARCH_R8A7790
+	bool "R-Car H2 (R8A77900)"
+	select ARCH_WANT_OPTIONAL_GPIOLIB
+	select ARM_GIC
+	select CPU_V7
+	select ARM_ARCH_TIMER
+	select SH_CLK_CPG
+	select RENESAS_IRQC
 
 config ARCH_EMEV2
 	bool "Emma Mobile EV2"
@@ -68,6 +96,11 @@ config MACH_AG5EVM
 	select REGULATOR_FIXED_VOLTAGE if REGULATOR
 	select SH_LCD_MIPI_DSI
 
+config MACH_APE6EVM
+	bool "APE6EVM board"
+	depends on ARCH_R8A73A4
+	select USE_OF
+
 config MACH_MACKEREL
 	bool "mackerel board"
 	depends on ARCH_SH7372
@@ -96,12 +129,37 @@ config MACH_ARMADILLO800EVA
 	select SND_SOC_WM8978 if SND_SIMPLE_CARD
 	select USE_OF
 
+config MACH_BOCKW
+	bool "BOCK-W platform"
+	depends on ARCH_R8A7778
+	select ARCH_REQUIRE_GPIOLIB
+	select RENESAS_INTC_IRQPIN
+	select USE_OF
+
 config MACH_MARZEN
 	bool "MARZEN board"
 	depends on ARCH_R8A7779
 	select ARCH_REQUIRE_GPIOLIB
 	select REGULATOR_FIXED_VOLTAGE if REGULATOR
 
+config MACH_MARZEN_REFERENCE
+	bool "MARZEN board - Reference Device Tree Implementation"
+	depends on ARCH_R8A7779
+	select ARCH_REQUIRE_GPIOLIB
+	select REGULATOR_FIXED_VOLTAGE if REGULATOR
+	select USE_OF
+	---help---
+	   Use reference implementation of Marzen board support
+	   which makes use of device tree at the expense
+	   of not supporting a number of devices.
+
+	   This is intended to aid developers
+
+config MACH_LAGER
+	bool "Lager board"
+	depends on ARCH_R8A7790
+	select USE_OF
+
 config MACH_KZM9D
 	bool "KZM9D board"
 	depends on ARCH_EMEV2
@@ -116,6 +174,20 @@ config MACH_KZM9G
 	select SND_SOC_AK4642 if SND_SIMPLE_CARD
 	select USE_OF
 
+config MACH_KZM9G_REFERENCE
+	bool "KZM-A9-GT board - Reference Device Tree Implementation"
+	depends on ARCH_SH73A0
+	select ARCH_REQUIRE_GPIOLIB
+	select REGULATOR_FIXED_VOLTAGE if REGULATOR
+	select SND_SOC_AK4642 if SND_SIMPLE_CARD
+	select USE_OF
+	---help---
+	   Use reference implementation of KZM-A9-GT board support
+	   which makes as greater use of device tree at the expense
+	   of not supporting a number of devices.
+
+	   This is intended to aid developers
+
 comment "SH-Mobile System Configuration"
 
 config CPU_HAS_INTEVT
@@ -128,7 +200,8 @@ config MEMORY_START
 	hex "Physical memory start address"
 	default "0x40000000" if MACH_AP4EVB || MACH_AG5EVM || \
 				MACH_MACKEREL || MACH_BONITO || \
-				MACH_ARMADILLO800EVA
+				MACH_ARMADILLO800EVA || MACH_APE6EVM || \
+				MACH_LAGER
 	default "0x41000000" if MACH_KOTA2
 	default "0x00000000"
 	---help---
@@ -138,6 +211,8 @@ config MEMORY_START
 
 config MEMORY_SIZE
 	hex "Physical memory size"
+	default "0x80000000" if MACH_LAGER
+	default "0x40000000" if MACH_APE6EVM
 	default "0x20000000" if MACH_AG5EVM || MACH_BONITO || \
 				MACH_ARMADILLO800EVA
 	default "0x1e000000" if MACH_KOTA2
diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile
index e1fac57..068f1da 100644
--- a/arch/arm/mach-shmobile/Makefile
+++ b/arch/arm/mach-shmobile/Makefile
@@ -8,16 +8,18 @@ obj-y				:= timer.o console.o clock.o
 # CPU objects
 obj-$(CONFIG_ARCH_SH7372)	+= setup-sh7372.o clock-sh7372.o intc-sh7372.o
 obj-$(CONFIG_ARCH_SH73A0)	+= setup-sh73a0.o clock-sh73a0.o intc-sh73a0.o
+obj-$(CONFIG_ARCH_R8A73A4)	+= setup-r8a73a4.o clock-r8a73a4.o
 obj-$(CONFIG_ARCH_R8A7740)	+= setup-r8a7740.o clock-r8a7740.o intc-r8a7740.o
+obj-$(CONFIG_ARCH_R8A7778)	+= setup-r8a7778.o clock-r8a7778.o
 obj-$(CONFIG_ARCH_R8A7779)	+= setup-r8a7779.o clock-r8a7779.o intc-r8a7779.o
+obj-$(CONFIG_ARCH_R8A7790)	+= setup-r8a7790.o clock-r8a7790.o
 obj-$(CONFIG_ARCH_EMEV2)	+= setup-emev2.o clock-emev2.o
 
 # SMP objects
 smp-y				:= platsmp.o headsmp.o
-smp-$(CONFIG_HOTPLUG_CPU)	+= hotplug.o
-smp-$(CONFIG_ARCH_SH73A0)	+= smp-sh73a0.o headsmp-sh73a0.o
-smp-$(CONFIG_ARCH_R8A7779)	+= smp-r8a7779.o
-smp-$(CONFIG_ARCH_EMEV2)	+= smp-emev2.o
+smp-$(CONFIG_ARCH_SH73A0)	+= smp-sh73a0.o headsmp-scu.o
+smp-$(CONFIG_ARCH_R8A7779)	+= smp-r8a7779.o headsmp-scu.o
+smp-$(CONFIG_ARCH_EMEV2)	+= smp-emev2.o headsmp-scu.o
 
 # IRQ objects
 obj-$(CONFIG_ARCH_SH7372)	+= entry-intc.o
@@ -35,13 +37,18 @@ obj-$(CONFIG_ARCH_SH73A0)	+= pm-sh73a0.o
 # Board objects
 obj-$(CONFIG_MACH_AP4EVB)	+= board-ap4evb.o
 obj-$(CONFIG_MACH_AG5EVM)	+= board-ag5evm.o
+obj-$(CONFIG_MACH_APE6EVM)	+= board-ape6evm.o
 obj-$(CONFIG_MACH_MACKEREL)	+= board-mackerel.o
 obj-$(CONFIG_MACH_KOTA2)	+= board-kota2.o
 obj-$(CONFIG_MACH_BONITO)	+= board-bonito.o
+obj-$(CONFIG_MACH_BOCKW)	+= board-bockw.o
 obj-$(CONFIG_MACH_MARZEN)	+= board-marzen.o
+obj-$(CONFIG_MACH_MARZEN_REFERENCE)	+= board-marzen-reference.o
+obj-$(CONFIG_MACH_LAGER)	+= board-lager.o
 obj-$(CONFIG_MACH_ARMADILLO800EVA)	+= board-armadillo800eva.o
 obj-$(CONFIG_MACH_KZM9D)	+= board-kzm9d.o
 obj-$(CONFIG_MACH_KZM9G)	+= board-kzm9g.o
+obj-$(CONFIG_MACH_KZM9G_REFERENCE)	+= board-kzm9g-reference.o
 
 # Framework support
 obj-$(CONFIG_SMP)		+= $(smp-y)
diff --git a/arch/arm/mach-shmobile/board-ag5evm.c b/arch/arm/mach-shmobile/board-ag5evm.c
index 8ff53a1..c754071 100644
--- a/arch/arm/mach-shmobile/board-ag5evm.c
+++ b/arch/arm/mach-shmobile/board-ag5evm.c
@@ -23,6 +23,8 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
+#include <linux/pinctrl/machine.h>
+#include <linux/pinctrl/pinconf-generic.h>
 #include <linux/platform_device.h>
 #include <linux/delay.h>
 #include <linux/io.h>
@@ -304,9 +306,9 @@ static int lcd_backlight_set_brightness(int brightness)
 
 	if (brightness == 0) {
 		/* Reset the chip */
-		gpio_set_value(GPIO_PORT235, 0);
+		gpio_set_value(235, 0);
 		mdelay(24);
-		gpio_set_value(GPIO_PORT235, 1);
+		gpio_set_value(235, 1);
 		return 0;
 	}
 
@@ -406,7 +408,7 @@ static struct sh_mobile_sdhi_info sdhi0_info = {
 	.tmio_flags	= TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_USE_GPIO_CD,
 	.tmio_caps	= MMC_CAP_SD_HIGHSPEED,
 	.tmio_ocr_mask	= MMC_VDD_27_28 | MMC_VDD_28_29,
-	.cd_gpio	= GPIO_PORT251,
+	.cd_gpio	= 251,
 };
 
 static struct resource sdhi0_resources[] = {
@@ -461,7 +463,7 @@ static struct regulator_init_data cn4_power_init_data = {
 static struct fixed_voltage_config cn4_power_info = {
 	.supply_name = "CN4 SD/MMC Vdd",
 	.microvolts = 3300000,
-	.gpio = GPIO_PORT114,
+	.gpio = 114,
 	.enable_high = 1,
 	.init_data = &cn4_power_init_data,
 };
@@ -479,10 +481,10 @@ static void ag5evm_sdhi1_set_pwr(struct platform_device *pdev, int state)
 	static int power_gpio = -EINVAL;
 
 	if (power_gpio < 0) {
-		int ret = gpio_request_one(GPIO_PORT114, GPIOF_OUT_INIT_LOW,
+		int ret = gpio_request_one(114, GPIOF_OUT_INIT_LOW,
 					   "sdhi1_power");
 		if (!ret)
-			power_gpio = GPIO_PORT114;
+			power_gpio = 114;
 	}
 
 	/*
@@ -493,7 +495,7 @@ static void ag5evm_sdhi1_set_pwr(struct platform_device *pdev, int state)
 	 * regulator driver. We have to live with the race in case the driver
 	 * gets unloaded and the GPIO freed between these two steps.
 	 */
-	gpio_set_value(GPIO_PORT114, state);
+	gpio_set_value(114, state);
 }
 
 static struct sh_mobile_sdhi_info sh_sdhi1_info = {
@@ -550,6 +552,77 @@ static struct platform_device *ag5evm_devices[] __initdata = {
 	&sdhi1_device,
 };
 
+static unsigned long pin_pullup_conf[] = {
+	PIN_CONF_PACKED(PIN_CONFIG_BIAS_PULL_UP, 0),
+};
+
+static const struct pinctrl_map ag5evm_pinctrl_map[] = {
+	/* FSIA */
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_fsi2.0", "pfc-sh73a0",
+				  "fsia_mclk_in", "fsia"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_fsi2.0", "pfc-sh73a0",
+				  "fsia_sclk_in", "fsia"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_fsi2.0", "pfc-sh73a0",
+				  "fsia_data_in", "fsia"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_fsi2.0", "pfc-sh73a0",
+				  "fsia_data_out", "fsia"),
+	/* I2C2 & I2C3 */
+	PIN_MAP_MUX_GROUP_DEFAULT("i2c-sh_mobile.2", "pfc-sh73a0",
+				  "i2c2_0", "i2c2"),
+	PIN_MAP_MUX_GROUP_DEFAULT("i2c-sh_mobile.3", "pfc-sh73a0",
+				  "i2c3_0", "i2c3"),
+	/* IrDA */
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_irda.0", "pfc-sh73a0",
+				  "irda_0", "irda"),
+	/* KEYSC */
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_keysc.0", "pfc-sh73a0",
+				  "keysc_in8", "keysc"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_keysc.0", "pfc-sh73a0",
+				  "keysc_out04", "keysc"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_keysc.0", "pfc-sh73a0",
+				  "keysc_out5", "keysc"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_keysc.0", "pfc-sh73a0",
+				  "keysc_out6_0", "keysc"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_keysc.0", "pfc-sh73a0",
+				  "keysc_out7_0", "keysc"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_keysc.0", "pfc-sh73a0",
+				  "keysc_out8_0", "keysc"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_keysc.0", "pfc-sh73a0",
+				  "keysc_out9_2", "keysc"),
+	PIN_MAP_CONFIGS_GROUP_DEFAULT("sh_keysc.0", "pfc-sh73a0",
+				      "keysc_in8", pin_pullup_conf),
+	/* MMCIF */
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mmcif.0", "pfc-sh73a0",
+				  "mmc0_data8_0", "mmc0"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mmcif.0", "pfc-sh73a0",
+				  "mmc0_ctrl_0", "mmc0"),
+	PIN_MAP_CONFIGS_PIN_DEFAULT("sh_mmcif.0", "pfc-sh73a0",
+				    "PORT279", pin_pullup_conf),
+	PIN_MAP_CONFIGS_GROUP_DEFAULT("sh_mmcif.0", "pfc-sh73a0",
+				      "mmc0_data8_0", pin_pullup_conf),
+	/* SCIFA2 */
+	PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.2", "pfc-sh73a0",
+				  "scifa2_data_0", "scifa2"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.2", "pfc-sh73a0",
+				  "scifa2_ctrl_0", "scifa2"),
+	/* SDHI0 (CN15 [SD I/F]) */
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-sh73a0",
+				  "sdhi0_data4", "sdhi0"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-sh73a0",
+				  "sdhi0_ctrl", "sdhi0"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-sh73a0",
+				  "sdhi0_wp", "sdhi0"),
+	/* SDHI1 (CN4 [WLAN I/F]) */
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.1", "pfc-sh73a0",
+				  "sdhi1_data4", "sdhi1"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.1", "pfc-sh73a0",
+				  "sdhi1_ctrl", "sdhi1"),
+	PIN_MAP_CONFIGS_GROUP_DEFAULT("sh_mobile_sdhi.1", "pfc-sh73a0",
+				      "sdhi1_data4", pin_pullup_conf),
+	PIN_MAP_CONFIGS_PIN_DEFAULT("sh_mobile_sdhi.1", "pfc-sh73a0",
+				    "PORT263", pin_pullup_conf),
+};
+
 static void __init ag5evm_init(void)
 {
 	regulator_register_always_on(0, "fixed-1.8V", fixed1v8_power_consumers,
@@ -558,96 +631,27 @@ static void __init ag5evm_init(void)
 				     ARRAY_SIZE(fixed2v8_power_consumers), 3300000);
 	regulator_register_fixed(3, dummy_supplies, ARRAY_SIZE(dummy_supplies));
 
+	pinctrl_register_mappings(ag5evm_pinctrl_map,
+				  ARRAY_SIZE(ag5evm_pinctrl_map));
 	sh73a0_pinmux_init();
 
-	/* enable SCIFA2 */
-	gpio_request(GPIO_FN_SCIFA2_TXD1, NULL);
-	gpio_request(GPIO_FN_SCIFA2_RXD1, NULL);
-	gpio_request(GPIO_FN_SCIFA2_RTS1_, NULL);
-	gpio_request(GPIO_FN_SCIFA2_CTS1_, NULL);
-
-	/* enable KEYSC */
-	gpio_request(GPIO_FN_KEYIN0_PU, NULL);
-	gpio_request(GPIO_FN_KEYIN1_PU, NULL);
-	gpio_request(GPIO_FN_KEYIN2_PU, NULL);
-	gpio_request(GPIO_FN_KEYIN3_PU, NULL);
-	gpio_request(GPIO_FN_KEYIN4_PU, NULL);
-	gpio_request(GPIO_FN_KEYIN5_PU, NULL);
-	gpio_request(GPIO_FN_KEYIN6_PU, NULL);
-	gpio_request(GPIO_FN_KEYIN7_PU, NULL);
-	gpio_request(GPIO_FN_KEYOUT0, NULL);
-	gpio_request(GPIO_FN_KEYOUT1, NULL);
-	gpio_request(GPIO_FN_KEYOUT2, NULL);
-	gpio_request(GPIO_FN_KEYOUT3, NULL);
-	gpio_request(GPIO_FN_KEYOUT4, NULL);
-	gpio_request(GPIO_FN_KEYOUT5, NULL);
-	gpio_request(GPIO_FN_PORT59_KEYOUT6, NULL);
-	gpio_request(GPIO_FN_PORT58_KEYOUT7, NULL);
-	gpio_request(GPIO_FN_KEYOUT8, NULL);
-	gpio_request(GPIO_FN_PORT149_KEYOUT9, NULL);
-
-	/* enable I2C channel 2 and 3 */
-	gpio_request(GPIO_FN_PORT236_I2C_SDA2, NULL);
-	gpio_request(GPIO_FN_PORT237_I2C_SCL2, NULL);
-	gpio_request(GPIO_FN_PORT248_I2C_SCL3, NULL);
-	gpio_request(GPIO_FN_PORT249_I2C_SDA3, NULL);
-
 	/* enable MMCIF */
-	gpio_request(GPIO_FN_MMCCLK0, NULL);
-	gpio_request(GPIO_FN_MMCCMD0_PU, NULL);
-	gpio_request(GPIO_FN_MMCD0_0_PU, NULL);
-	gpio_request(GPIO_FN_MMCD0_1_PU, NULL);
-	gpio_request(GPIO_FN_MMCD0_2_PU, NULL);
-	gpio_request(GPIO_FN_MMCD0_3_PU, NULL);
-	gpio_request(GPIO_FN_MMCD0_4_PU, NULL);
-	gpio_request(GPIO_FN_MMCD0_5_PU, NULL);
-	gpio_request(GPIO_FN_MMCD0_6_PU, NULL);
-	gpio_request(GPIO_FN_MMCD0_7_PU, NULL);
-	gpio_request_one(GPIO_PORT208, GPIOF_OUT_INIT_HIGH, NULL); /* Reset */
+	gpio_request_one(208, GPIOF_OUT_INIT_HIGH, NULL); /* Reset */
 
 	/* enable SMSC911X */
-	gpio_request_one(GPIO_PORT144, GPIOF_IN, NULL); /* PINTA2 */
-	gpio_request_one(GPIO_PORT145, GPIOF_OUT_INIT_HIGH, NULL); /* RESET */
-
-	/* FSI A */
-	gpio_request(GPIO_FN_FSIACK, NULL);
-	gpio_request(GPIO_FN_FSIAILR, NULL);
-	gpio_request(GPIO_FN_FSIAIBT, NULL);
-	gpio_request(GPIO_FN_FSIAISLD, NULL);
-	gpio_request(GPIO_FN_FSIAOSLD, NULL);
-
-	/* IrDA */
-	gpio_request(GPIO_FN_PORT241_IRDA_OUT, NULL);
-	gpio_request(GPIO_FN_PORT242_IRDA_IN,  NULL);
-	gpio_request(GPIO_FN_PORT243_IRDA_FIRSEL, NULL);
+	gpio_request_one(144, GPIOF_IN, NULL); /* PINTA2 */
+	gpio_request_one(145, GPIOF_OUT_INIT_HIGH, NULL); /* RESET */
 
 	/* LCD panel */
-	gpio_request_one(GPIO_PORT217, GPIOF_OUT_INIT_LOW, NULL); /* RESET */
+	gpio_request_one(217, GPIOF_OUT_INIT_LOW, NULL); /* RESET */
 	mdelay(1);
-	gpio_set_value(GPIO_PORT217, 1);
+	gpio_set_value(217, 1);
 	mdelay(100);
 
 	/* LCD backlight controller */
-	gpio_request_one(GPIO_PORT235, GPIOF_OUT_INIT_LOW, NULL); /* RESET */
+	gpio_request_one(235, GPIOF_OUT_INIT_LOW, NULL); /* RESET */
 	lcd_backlight_set_brightness(0);
 
-	/* enable SDHI0 on CN15 [SD I/F] */
-	gpio_request(GPIO_FN_SDHIWP0, NULL);
-	gpio_request(GPIO_FN_SDHICMD0, NULL);
-	gpio_request(GPIO_FN_SDHICLK0, NULL);
-	gpio_request(GPIO_FN_SDHID0_3, NULL);
-	gpio_request(GPIO_FN_SDHID0_2, NULL);
-	gpio_request(GPIO_FN_SDHID0_1, NULL);
-	gpio_request(GPIO_FN_SDHID0_0, NULL);
-
-	/* enable SDHI1 on CN4 [WLAN I/F] */
-	gpio_request(GPIO_FN_SDHICLK1, NULL);
-	gpio_request(GPIO_FN_SDHICMD1_PU, NULL);
-	gpio_request(GPIO_FN_SDHID1_3_PU, NULL);
-	gpio_request(GPIO_FN_SDHID1_2_PU, NULL);
-	gpio_request(GPIO_FN_SDHID1_1_PU, NULL);
-	gpio_request(GPIO_FN_SDHID1_0_PU, NULL);
-
 #ifdef CONFIG_CACHE_L2X0
 	/* Shared attribute override enable, 64K*8way */
 	l2x0_init(IOMEM(0xf0100000), 0x00460000, 0xc2000fff);
diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c
index 38f1259..45f78ca 100644
--- a/arch/arm/mach-shmobile/board-ap4evb.c
+++ b/arch/arm/mach-shmobile/board-ap4evb.c
@@ -34,6 +34,7 @@
 #include <linux/i2c.h>
 #include <linux/i2c/tsc2007.h>
 #include <linux/io.h>
+#include <linux/pinctrl/machine.h>
 #include <linux/regulator/fixed.h>
 #include <linux/regulator/machine.h>
 #include <linux/smsc911x.h>
@@ -273,11 +274,11 @@ static struct platform_device smc911x_device = {
 
 /*
  * The card detect pin of the top SD/MMC slot (CN7) is active low and is
- * connected to GPIO A22 of SH7372 (GPIO_PORT41).
+ * connected to GPIO A22 of SH7372 (GPIO 41).
  */
 static int slot_cn7_get_cd(struct platform_device *pdev)
 {
-	return !gpio_get_value(GPIO_PORT41);
+	return !gpio_get_value(41);
 }
 /* MERAM */
 static struct sh_mobile_meram_info meram_info = {
@@ -838,22 +839,22 @@ static struct platform_device fsi_hdmi_device = {
 static struct gpio_led ap4evb_leds[] = {
 	{
 		.name			= "led4",
-		.gpio			= GPIO_PORT185,
+		.gpio			= 185,
 		.default_state	= LEDS_GPIO_DEFSTATE_ON,
 	},
 	{
 		.name			= "led2",
-		.gpio			= GPIO_PORT186,
+		.gpio			= 186,
 		.default_state	= LEDS_GPIO_DEFSTATE_ON,
 	},
 	{
 		.name			= "led3",
-		.gpio			= GPIO_PORT187,
+		.gpio			= 187,
 		.default_state	= LEDS_GPIO_DEFSTATE_ON,
 	},
 	{
 		.name			= "led1",
-		.gpio			= GPIO_PORT188,
+		.gpio			= 188,
 		.default_state	= LEDS_GPIO_DEFSTATE_ON,
 	}
 };
@@ -1026,10 +1027,10 @@ out:
 /* TouchScreen */
 #ifdef CONFIG_AP4EVB_QHD
 # define GPIO_TSC_IRQ	GPIO_FN_IRQ28_123
-# define GPIO_TSC_PORT	GPIO_PORT123
+# define GPIO_TSC_PORT	123
 #else /* WVGA */
 # define GPIO_TSC_IRQ	GPIO_FN_IRQ7_40
-# define GPIO_TSC_PORT	GPIO_PORT40
+# define GPIO_TSC_PORT	40
 #endif
 
 #define IRQ28	evt2irq(0x3380) /* IRQ28A */
@@ -1084,6 +1085,28 @@ static struct i2c_board_info i2c1_devices[] = {
 };
 
 
+static const struct pinctrl_map ap4evb_pinctrl_map[] = {
+	/* MMCIF */
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mmcif.0", "pfc-sh7372",
+				  "mmc0_data8_0", "mmc0"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mmcif.0", "pfc-sh7372",
+				  "mmc0_ctrl_0", "mmc0"),
+	/* SDHI0 */
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-sh7372",
+				  "sdhi0_data4", "sdhi0"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-sh7372",
+				  "sdhi0_ctrl", "sdhi0"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-sh7372",
+				  "sdhi0_cd", "sdhi0"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-sh7372",
+				  "sdhi0_wp", "sdhi0"),
+	/* SDHI1 */
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.1", "pfc-sh7372",
+				  "sdhi1_data4", "sdhi1"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.1", "pfc-sh7372",
+				  "sdhi1_ctrl", "sdhi1"),
+};
+
 #define GPIO_PORT9CR	IOMEM(0xE6051009)
 #define GPIO_PORT10CR	IOMEM(0xE605100A)
 #define USCCR1		IOMEM(0xE6058144)
@@ -1110,6 +1133,8 @@ static void __init ap4evb_init(void)
 	/* External clock source */
 	clk_set_rate(&sh7372_dv_clki_clk, 27000000);
 
+	pinctrl_register_mappings(ap4evb_pinctrl_map,
+				  ARRAY_SIZE(ap4evb_pinctrl_map));
 	sh7372_pinmux_init();
 
 	/* enable SCIFA0 */
@@ -1121,40 +1146,10 @@ static void __init ap4evb_init(void)
 	gpio_request(GPIO_FN_IRQ6_39,	NULL);
 
 	/* enable Debug switch (S6) */
-	gpio_request_one(GPIO_PORT32, GPIOF_IN | GPIOF_EXPORT, NULL);
-	gpio_request_one(GPIO_PORT33, GPIOF_IN | GPIOF_EXPORT, NULL);
-	gpio_request_one(GPIO_PORT34, GPIOF_IN | GPIOF_EXPORT, NULL);
-	gpio_request_one(GPIO_PORT35, GPIOF_IN | GPIOF_EXPORT, NULL);
-
-	/* SDHI0 */
-	gpio_request(GPIO_FN_SDHICD0, NULL);
-	gpio_request(GPIO_FN_SDHIWP0, NULL);
-	gpio_request(GPIO_FN_SDHICMD0, NULL);
-	gpio_request(GPIO_FN_SDHICLK0, NULL);
-	gpio_request(GPIO_FN_SDHID0_3, NULL);
-	gpio_request(GPIO_FN_SDHID0_2, NULL);
-	gpio_request(GPIO_FN_SDHID0_1, NULL);
-	gpio_request(GPIO_FN_SDHID0_0, NULL);
-
-	/* SDHI1 */
-	gpio_request(GPIO_FN_SDHICMD1, NULL);
-	gpio_request(GPIO_FN_SDHICLK1, NULL);
-	gpio_request(GPIO_FN_SDHID1_3, NULL);
-	gpio_request(GPIO_FN_SDHID1_2, NULL);
-	gpio_request(GPIO_FN_SDHID1_1, NULL);
-	gpio_request(GPIO_FN_SDHID1_0, NULL);
-
-	/* MMCIF */
-	gpio_request(GPIO_FN_MMCD0_0, NULL);
-	gpio_request(GPIO_FN_MMCD0_1, NULL);
-	gpio_request(GPIO_FN_MMCD0_2, NULL);
-	gpio_request(GPIO_FN_MMCD0_3, NULL);
-	gpio_request(GPIO_FN_MMCD0_4, NULL);
-	gpio_request(GPIO_FN_MMCD0_5, NULL);
-	gpio_request(GPIO_FN_MMCD0_6, NULL);
-	gpio_request(GPIO_FN_MMCD0_7, NULL);
-	gpio_request(GPIO_FN_MMCCMD0, NULL);
-	gpio_request(GPIO_FN_MMCCLK0, NULL);
+	gpio_request_one(32, GPIOF_IN | GPIOF_EXPORT, NULL);
+	gpio_request_one(33, GPIOF_IN | GPIOF_EXPORT, NULL);
+	gpio_request_one(34, GPIOF_IN | GPIOF_EXPORT, NULL);
+	gpio_request_one(35, GPIOF_IN | GPIOF_EXPORT, NULL);
 
 	/* USB enable */
 	gpio_request(GPIO_FN_VBUS0_1,    NULL);
@@ -1172,15 +1167,15 @@ static void __init ap4evb_init(void)
 	gpio_request(GPIO_FN_FSIAILR,	NULL);
 	gpio_request(GPIO_FN_FSIAISLD,	NULL);
 	gpio_request(GPIO_FN_FSIAOSLD,	NULL);
-	gpio_request_one(GPIO_PORT161, GPIOF_OUT_INIT_LOW, NULL); /* slave */
+	gpio_request_one(161, GPIOF_OUT_INIT_LOW, NULL); /* slave */
 
-	gpio_request(GPIO_PORT9, NULL);
-	gpio_request(GPIO_PORT10, NULL);
+	gpio_request(9, NULL);
+	gpio_request(10, NULL);
 	gpio_direction_none(GPIO_PORT9CR);  /* FSIAOBT needs no direction */
 	gpio_direction_none(GPIO_PORT10CR); /* FSIAOLR needs no direction */
 
 	/* card detect pin for MMC slot (CN7) */
-	gpio_request_one(GPIO_PORT41, GPIOF_IN, NULL);
+	gpio_request_one(41, GPIOF_IN, NULL);
 
 	/* setup FSI2 port B (HDMI) */
 	gpio_request(GPIO_FN_FSIBCK, NULL);
@@ -1268,8 +1263,8 @@ static void __init ap4evb_init(void)
 	gpio_request(GPIO_FN_LCDDISP,  NULL);
 	gpio_request(GPIO_FN_LCDDCK,   NULL);
 
-	gpio_request_one(GPIO_PORT189, GPIOF_OUT_INIT_HIGH, NULL); /* backlight */
-	gpio_request_one(GPIO_PORT151, GPIOF_OUT_INIT_HIGH, NULL); /* LCDDON */
+	gpio_request_one(189, GPIOF_OUT_INIT_HIGH, NULL); /* backlight */
+	gpio_request_one(151, GPIOF_OUT_INIT_HIGH, NULL); /* LCDDON */
 
 	lcdc_info.clock_source			= LCDC_CLK_BUS;
 	lcdc_info.ch[0].interface_type		= RGB18;
diff --git a/arch/arm/mach-shmobile/board-ape6evm.c b/arch/arm/mach-shmobile/board-ape6evm.c
new file mode 100644
index 0000000..55b8c9f
--- /dev/null
+++ b/arch/arm/mach-shmobile/board-ape6evm.c
@@ -0,0 +1,94 @@
+/*
+ * APE6EVM board support
+ *
+ * Copyright (C) 2013  Renesas Solutions Corp.
+ * Copyright (C) 2013  Magnus Damm
+ *
+ * This program is free software; 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/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/irqchip.h>
+#include <linux/kernel.h>
+#include <linux/pinctrl/machine.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/fixed.h>
+#include <linux/regulator/machine.h>
+#include <linux/smsc911x.h>
+#include <mach/common.h>
+#include <mach/irqs.h>
+#include <mach/r8a73a4.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+/* Dummy supplies, where voltage doesn't matter */
+static struct regulator_consumer_supply dummy_supplies[] = {
+	REGULATOR_SUPPLY("vddvario", "smsc911x"),
+	REGULATOR_SUPPLY("vdd33a", "smsc911x"),
+};
+
+/* SMSC LAN9220 */
+static const struct resource lan9220_res[] = {
+	DEFINE_RES_MEM(0x08000000, 0x1000),
+	{
+		.start	= irq_pin(40), /* IRQ40 */
+		.flags	= IORESOURCE_IRQ | IRQF_TRIGGER_HIGH,
+	},
+};
+
+static const struct smsc911x_platform_config lan9220_data = {
+	.flags		= SMSC911X_USE_32BIT,
+	.irq_type	= SMSC911X_IRQ_TYPE_PUSH_PULL,
+	.irq_polarity	= SMSC911X_IRQ_POLARITY_ACTIVE_HIGH,
+};
+
+static const struct pinctrl_map ape6evm_pinctrl_map[] = {
+	/* SCIFA0 console */
+	PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.0", "pfc-r8a73a4",
+				  "scifa0_data", "scifa0"),
+	/* SMSC */
+	PIN_MAP_MUX_GROUP_DEFAULT("smsc911x", "pfc-r8a73a4",
+				  "irqc_irq40", "irqc"),
+};
+
+static void __init ape6evm_add_standard_devices(void)
+{
+	r8a73a4_clock_init();
+	pinctrl_register_mappings(ape6evm_pinctrl_map,
+				  ARRAY_SIZE(ape6evm_pinctrl_map));
+	r8a73a4_pinmux_init();
+	r8a73a4_add_standard_devices();
+
+	/* LAN9220 ethernet */
+	gpio_request_one(270, GPIOF_OUT_INIT_HIGH, NULL); /* smsc9220 RESET */
+
+	regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
+
+	platform_device_register_resndata(&platform_bus, "smsc911x", -1,
+					  lan9220_res, ARRAY_SIZE(lan9220_res),
+					  &lan9220_data, sizeof(lan9220_data));
+}
+
+static const char *ape6evm_boards_compat_dt[] __initdata = {
+	"renesas,ape6evm",
+	NULL,
+};
+
+DT_MACHINE_START(APE6EVM_DT, "ape6evm")
+	.init_irq	= irqchip_init,
+	.init_time	= shmobile_timer_init,
+	.init_machine	= ape6evm_add_standard_devices,
+	.dt_compat	= ape6evm_boards_compat_dt,
+MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
index f2ec077..2dfb1f8 100644
--- a/arch/arm/mach-shmobile/board-armadillo800eva.c
+++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
@@ -28,7 +28,10 @@
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
 #include <linux/gpio_keys.h>
+#include <linux/regulator/driver.h>
+#include <linux/pinctrl/machine.h>
 #include <linux/regulator/fixed.h>
+#include <linux/regulator/gpio-regulator.h>
 #include <linux/regulator/machine.h>
 #include <linux/sh_eth.h>
 #include <linux/videodev2.h>
@@ -145,7 +148,7 @@
  * see
  *	usbhsf_power_ctrl()
  */
-#define IRQ7		evt2irq(0x02e0)
+#define IRQ7		irq_pin(7)
 #define USBCR1		IOMEM(0xe605810a)
 #define USBH		0xC6700000
 #define USBH_USBCTR	0x10834
@@ -169,7 +172,7 @@ static int usbhsf_get_id(struct platform_device *pdev)
 	return USBHS_GADGET;
 }
 
-static void usbhsf_power_ctrl(struct platform_device *pdev,
+static int usbhsf_power_ctrl(struct platform_device *pdev,
 			      void __iomem *base, int enable)
 {
 	struct usbhsf_private *priv = usbhsf_get_priv(pdev);
@@ -223,11 +226,13 @@ static void usbhsf_power_ctrl(struct platform_device *pdev,
 		clk_disable(priv->pci);		/* usb work around */
 		clk_disable(priv->usb24);	/* usb work around */
 	}
+
+	return 0;
 }
 
 static int usbhsf_get_vbus(struct platform_device *pdev)
 {
-	return gpio_get_value(GPIO_PORT209);
+	return gpio_get_value(209);
 }
 
 static irqreturn_t usbhsf_interrupt(int irq, void *data)
@@ -239,7 +244,7 @@ static irqreturn_t usbhsf_interrupt(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
-static void usbhsf_hardware_exit(struct platform_device *pdev)
+static int usbhsf_hardware_exit(struct platform_device *pdev)
 {
 	struct usbhsf_private *priv = usbhsf_get_priv(pdev);
 
@@ -264,6 +269,8 @@ static void usbhsf_hardware_exit(struct platform_device *pdev)
 	priv->usbh_base	= NULL;
 
 	free_irq(IRQ7, pdev);
+
+	return 0;
 }
 
 static int usbhsf_hardware_init(struct platform_device *pdev)
@@ -330,7 +337,7 @@ static struct resource usbhsf_resources[] = {
 		.flags	= IORESOURCE_MEM,
 	},
 	{
-		.start	= evt2irq(0x0A20),
+		.start	= gic_spi(51),
 		.flags	= IORESOURCE_IRQ,
 	},
 };
@@ -363,7 +370,7 @@ static struct resource sh_eth_resources[] = {
 		.end	= 0xe9a02000 - 1,
 		.flags	= IORESOURCE_MEM,
 	}, {
-		.start	= evt2irq(0x0500),
+		.start	= gic_spi(110),
 		.flags	= IORESOURCE_IRQ,
 	},
 };
@@ -417,7 +424,7 @@ static struct resource lcdc0_resources[] = {
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= intcs_evt2irq(0x580),
+		.start	= gic_spi(177),
 		.flags	= IORESOURCE_IRQ,
 	},
 };
@@ -452,7 +459,7 @@ static struct resource hdmi_resources[] = {
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= evt2irq(0x1700),
+		.start	= gic_spi(131),
 		.flags	= IORESOURCE_IRQ,
 	},
 	[2] = {
@@ -514,7 +521,7 @@ static struct resource hdmi_lcdc_resources[] = {
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= intcs_evt2irq(0x1780),
+		.start	= gic_spi(178),
 		.flags	= IORESOURCE_IRQ,
 	},
 };
@@ -535,10 +542,10 @@ static struct platform_device hdmi_lcdc_device = {
 	{ .code = c, .gpio = g, .desc = d, .active_low = 1, __VA_ARGS__ }
 
 static struct gpio_keys_button gpio_buttons[] = {
-	GPIO_KEY(KEY_POWER,	GPIO_PORT99,	"SW3", .wakeup = 1),
-	GPIO_KEY(KEY_BACK,	GPIO_PORT100,	"SW4"),
-	GPIO_KEY(KEY_MENU,	GPIO_PORT97,	"SW5"),
-	GPIO_KEY(KEY_HOME,	GPIO_PORT98,	"SW6"),
+	GPIO_KEY(KEY_POWER,	99,	"SW3", .wakeup = 1),
+	GPIO_KEY(KEY_BACK,	100,	"SW4"),
+	GPIO_KEY(KEY_MENU,	97,	"SW5"),
+	GPIO_KEY(KEY_HOME,	98,	"SW6"),
 };
 
 static struct gpio_keys_platform_data gpio_key_info = {
@@ -554,15 +561,119 @@ static struct platform_device gpio_keys_device = {
 	},
 };
 
-/* Fixed 3.3V regulator to be used by SDHI0, SDHI1, MMCIF */
-static struct regulator_consumer_supply fixed3v3_power_consumers[] =
-{
+/* Fixed 3.3V regulator to be used by SDHI1, MMCIF */
+static struct regulator_consumer_supply fixed3v3_power_consumers[] = {
+	REGULATOR_SUPPLY("vmmc", "sh_mmcif"),
+	REGULATOR_SUPPLY("vqmmc", "sh_mmcif"),
+};
+
+/* Fixed 3.3V regulator to be used by SDHI0 */
+static struct regulator_consumer_supply vcc_sdhi0_consumers[] = {
 	REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.0"),
+};
+
+static struct regulator_init_data vcc_sdhi0_init_data = {
+	.constraints = {
+		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies  = ARRAY_SIZE(vcc_sdhi0_consumers),
+	.consumer_supplies      = vcc_sdhi0_consumers,
+};
+
+static struct fixed_voltage_config vcc_sdhi0_info = {
+	.supply_name = "SDHI0 Vcc",
+	.microvolts = 3300000,
+	.gpio = GPIO_PORT75,
+	.enable_high = 1,
+	.init_data = &vcc_sdhi0_init_data,
+};
+
+static struct platform_device vcc_sdhi0 = {
+	.name = "reg-fixed-voltage",
+	.id   = 1,
+	.dev  = {
+		.platform_data = &vcc_sdhi0_info,
+	},
+};
+
+/* 1.8 / 3.3V SDHI0 VccQ regulator */
+static struct regulator_consumer_supply vccq_sdhi0_consumers[] = {
 	REGULATOR_SUPPLY("vqmmc", "sh_mobile_sdhi.0"),
+};
+
+static struct regulator_init_data vccq_sdhi0_init_data = {
+	.constraints = {
+		.input_uV	= 3300000,
+		.min_uV		= 1800000,
+		.max_uV         = 3300000,
+		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+				  REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies  = ARRAY_SIZE(vccq_sdhi0_consumers),
+	.consumer_supplies      = vccq_sdhi0_consumers,
+};
+
+static struct gpio vccq_sdhi0_gpios[] = {
+	{GPIO_PORT17, GPIOF_OUT_INIT_LOW, "vccq-sdhi0" },
+};
+
+static struct gpio_regulator_state vccq_sdhi0_states[] = {
+	{ .value = 3300000, .gpios = (0 << 0) },
+	{ .value = 1800000, .gpios = (1 << 0) },
+};
+
+static struct gpio_regulator_config vccq_sdhi0_info = {
+	.supply_name = "vqmmc",
+
+	.enable_gpio = GPIO_PORT74,
+	.enable_high = 1,
+	.enabled_at_boot = 0,
+
+	.gpios = vccq_sdhi0_gpios,
+	.nr_gpios = ARRAY_SIZE(vccq_sdhi0_gpios),
+
+	.states = vccq_sdhi0_states,
+	.nr_states = ARRAY_SIZE(vccq_sdhi0_states),
+
+	.type = REGULATOR_VOLTAGE,
+	.init_data = &vccq_sdhi0_init_data,
+};
+
+static struct platform_device vccq_sdhi0 = {
+	.name = "gpio-regulator",
+	.id   = -1,
+	.dev  = {
+		.platform_data = &vccq_sdhi0_info,
+	},
+};
+
+/* Fixed 3.3V regulator to be used by SDHI1 */
+static struct regulator_consumer_supply vcc_sdhi1_consumers[] = {
 	REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.1"),
-	REGULATOR_SUPPLY("vqmmc", "sh_mobile_sdhi.1"),
-	REGULATOR_SUPPLY("vmmc", "sh_mmcif"),
-	REGULATOR_SUPPLY("vqmmc", "sh_mmcif"),
+};
+
+static struct regulator_init_data vcc_sdhi1_init_data = {
+	.constraints = {
+		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies  = ARRAY_SIZE(vcc_sdhi1_consumers),
+	.consumer_supplies      = vcc_sdhi1_consumers,
+};
+
+static struct fixed_voltage_config vcc_sdhi1_info = {
+	.supply_name = "SDHI1 Vcc",
+	.microvolts = 3300000,
+	.gpio = GPIO_PORT16,
+	.enable_high = 1,
+	.init_data = &vcc_sdhi1_init_data,
+};
+
+static struct platform_device vcc_sdhi1 = {
+	.name = "reg-fixed-voltage",
+	.id   = 2,
+	.dev  = {
+		.platform_data = &vcc_sdhi1_info,
+	},
 };
 
 /* SDHI0 */
@@ -574,14 +685,14 @@ static struct regulator_consumer_supply fixed3v3_power_consumers[] =
  * We can use IRQ31 as card detect irq,
  * but it needs chattering removal operation
  */
-#define IRQ31	evt2irq(0x33E0)
+#define IRQ31	irq_pin(31)
 static struct sh_mobile_sdhi_info sdhi0_info = {
 	.dma_slave_tx	= SHDMA_SLAVE_SDHI0_TX,
 	.dma_slave_rx	= SHDMA_SLAVE_SDHI0_RX,
-	.tmio_caps	= MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ |\
-			  MMC_CAP_NEEDS_POLL,
-	.tmio_ocr_mask	= MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34,
-	.tmio_flags	= TMIO_MMC_HAS_IDLE_WAIT,
+	.tmio_caps	= MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ |
+			  MMC_CAP_POWER_OFF_CARD,
+	.tmio_flags	= TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_USE_GPIO_CD,
+	.cd_gpio	= GPIO_PORT167,
 };
 
 static struct resource sdhi0_resources[] = {
@@ -596,12 +707,12 @@ static struct resource sdhi0_resources[] = {
 	 */
 	{
 		.name	= SH_MOBILE_SDHI_IRQ_SDCARD,
-		.start	= evt2irq(0x0E20),
+		.start	= gic_spi(118),
 		.flags	= IORESOURCE_IRQ,
 	},
 	{
 		.name	= SH_MOBILE_SDHI_IRQ_SDIO,
-		.start	= evt2irq(0x0E40),
+		.start	= gic_spi(119),
 		.flags	= IORESOURCE_IRQ,
 	},
 };
@@ -620,9 +731,11 @@ static struct platform_device sdhi0_device = {
 static struct sh_mobile_sdhi_info sdhi1_info = {
 	.dma_slave_tx	= SHDMA_SLAVE_SDHI1_TX,
 	.dma_slave_rx	= SHDMA_SLAVE_SDHI1_RX,
-	.tmio_caps	= MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ,
-	.tmio_ocr_mask	= MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34,
-	.tmio_flags	= TMIO_MMC_HAS_IDLE_WAIT,
+	.tmio_caps	= MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ |
+			  MMC_CAP_POWER_OFF_CARD,
+	.tmio_flags	= TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_USE_GPIO_CD,
+	/* Port72 cannot generate IRQs, will be used in polling mode. */
+	.cd_gpio	= GPIO_PORT72,
 };
 
 static struct resource sdhi1_resources[] = {
@@ -633,15 +746,15 @@ static struct resource sdhi1_resources[] = {
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= evt2irq(0x0E80),
+		.start	= gic_spi(121),
 		.flags	= IORESOURCE_IRQ,
 	},
 	[2] = {
-		.start	= evt2irq(0x0EA0),
+		.start	= gic_spi(122),
 		.flags	= IORESOURCE_IRQ,
 	},
 	[3] = {
-		.start	= evt2irq(0x0EC0),
+		.start	= gic_spi(123),
 		.flags	= IORESOURCE_IRQ,
 	},
 };
@@ -656,10 +769,20 @@ static struct platform_device sdhi1_device = {
 	.resource	= sdhi1_resources,
 };
 
+static const struct pinctrl_map eva_sdhi1_pinctrl_map[] = {
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.1", "pfc-r8a7740",
+				  "sdhi1_data4", "sdhi1"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.1", "pfc-r8a7740",
+				  "sdhi1_ctrl", "sdhi1"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.1", "pfc-r8a7740",
+				  "sdhi1_cd", "sdhi1"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.1", "pfc-r8a7740",
+				  "sdhi1_wp", "sdhi1"),
+};
+
 /* MMCIF */
 static struct sh_mmcif_plat_data sh_mmcif_plat = {
 	.sup_pclk	= 0,
-	.ocr		= MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34,
 	.caps		= MMC_CAP_4_BIT_DATA |
 			  MMC_CAP_8_BIT_DATA |
 			  MMC_CAP_NONREMOVABLE,
@@ -674,12 +797,12 @@ static struct resource sh_mmcif_resources[] = {
 	},
 	[1] = {
 		/* MMC ERR */
-		.start	= evt2irq(0x1AC0),
+		.start	= gic_spi(56),
 		.flags	= IORESOURCE_IRQ,
 	},
 	[2] = {
 		/* MMC NOR */
-		.start	= evt2irq(0x1AE0),
+		.start	= gic_spi(57),
 		.flags	= IORESOURCE_IRQ,
 	},
 };
@@ -708,9 +831,9 @@ static int mt9t111_power(struct device *dev, int mode)
 		/* video1 (= CON1 camera) expect 24MHz */
 		clk_set_rate(mclk, clk_round_rate(mclk, 24000000));
 		clk_enable(mclk);
-		gpio_set_value(GPIO_PORT158, 1);
+		gpio_set_value(158, 1);
 	} else {
-		gpio_set_value(GPIO_PORT158, 0);
+		gpio_set_value(158, 0);
 		clk_disable(mclk);
 	}
 
@@ -756,7 +879,7 @@ static struct resource ceu0_resources[] = {
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start  = intcs_evt2irq(0x0500),
+		.start  = gic_spi(160),
 		.flags  = IORESOURCE_IRQ,
 	},
 	[2] = {
@@ -798,7 +921,7 @@ static struct resource fsi_resources[] = {
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start  = evt2irq(0x1840),
+		.start  = gic_spi(9),
 		.flags  = IORESOURCE_IRQ,
 	},
 };
@@ -864,8 +987,8 @@ static struct platform_device fsi_hdmi_device = {
 
 /* RTC: RTC connects i2c-gpio. */
 static struct i2c_gpio_platform_data i2c_gpio_data = {
-	.sda_pin	= GPIO_PORT208,
-	.scl_pin	= GPIO_PORT91,
+	.sda_pin	= 208,
+	.scl_pin	= 91,
 	.udelay		= 5, /* 100 kHz */
 };
 
@@ -881,7 +1004,7 @@ static struct platform_device i2c_gpio_device = {
 static struct i2c_board_info i2c0_devices[] = {
 	{
 		I2C_BOARD_INFO("st1232-ts", 0x55),
-		.irq = evt2irq(0x0340),
+		.irq = irq_pin(10),
 	},
 	{
 		I2C_BOARD_INFO("wm8978", 0x1a),
@@ -902,6 +1025,8 @@ static struct platform_device *eva_devices[] __initdata = {
 	&lcdc0_device,
 	&gpio_keys_device,
 	&sh_eth_device,
+	&vcc_sdhi0,
+	&vccq_sdhi0,
 	&sdhi0_device,
 	&sh_mmcif_device,
 	&hdmi_device,
@@ -914,6 +1039,28 @@ static struct platform_device *eva_devices[] __initdata = {
 	&i2c_gpio_device,
 };
 
+static const struct pinctrl_map eva_pinctrl_map[] = {
+	/* LCD0 */
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_lcdc_fb.0", "pfc-r8a7740",
+				  "lcd0_data24_0", "lcd0"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_lcdc_fb.0", "pfc-r8a7740",
+				  "lcd0_lclk_1", "lcd0"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_lcdc_fb.0", "pfc-r8a7740",
+				  "lcd0_sync", "lcd0"),
+	/* MMCIF */
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mmcif.0", "pfc-r8a7740",
+				  "mmc0_data8_1", "mmc0"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mmcif.0", "pfc-r8a7740",
+				  "mmc0_ctrl_1", "mmc0"),
+	/* SDHI0 */
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7740",
+				  "sdhi0_data4", "sdhi0"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7740",
+				  "sdhi0_ctrl", "sdhi0"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7740",
+				  "sdhi0_wp", "sdhi0"),
+};
+
 static void __init eva_clock_init(void)
 {
 	struct clk *system	= clk_get(NULL, "system_clk");
@@ -961,6 +1108,8 @@ static void __init eva_init(void)
 	regulator_register_always_on(0, "fixed-3.3V", fixed3v3_power_consumers,
 				     ARRAY_SIZE(fixed3v3_power_consumers), 3300000);
 
+	pinctrl_register_mappings(eva_pinctrl_map, ARRAY_SIZE(eva_pinctrl_map));
+
 	r8a7740_pinmux_init();
 	r8a7740_meram_workaround();
 
@@ -970,42 +1119,13 @@ static void __init eva_init(void)
 
 	/* LCDC0 */
 	gpio_request(GPIO_FN_LCDC0_SELECT,	NULL);
-	gpio_request(GPIO_FN_LCD0_D0,		NULL);
-	gpio_request(GPIO_FN_LCD0_D1,		NULL);
-	gpio_request(GPIO_FN_LCD0_D2,		NULL);
-	gpio_request(GPIO_FN_LCD0_D3,		NULL);
-	gpio_request(GPIO_FN_LCD0_D4,		NULL);
-	gpio_request(GPIO_FN_LCD0_D5,		NULL);
-	gpio_request(GPIO_FN_LCD0_D6,		NULL);
-	gpio_request(GPIO_FN_LCD0_D7,		NULL);
-	gpio_request(GPIO_FN_LCD0_D8,		NULL);
-	gpio_request(GPIO_FN_LCD0_D9,		NULL);
-	gpio_request(GPIO_FN_LCD0_D10,		NULL);
-	gpio_request(GPIO_FN_LCD0_D11,		NULL);
-	gpio_request(GPIO_FN_LCD0_D12,		NULL);
-	gpio_request(GPIO_FN_LCD0_D13,		NULL);
-	gpio_request(GPIO_FN_LCD0_D14,		NULL);
-	gpio_request(GPIO_FN_LCD0_D15,		NULL);
-	gpio_request(GPIO_FN_LCD0_D16,		NULL);
-	gpio_request(GPIO_FN_LCD0_D17,		NULL);
-	gpio_request(GPIO_FN_LCD0_D18_PORT40,	NULL);
-	gpio_request(GPIO_FN_LCD0_D19_PORT4,	NULL);
-	gpio_request(GPIO_FN_LCD0_D20_PORT3,	NULL);
-	gpio_request(GPIO_FN_LCD0_D21_PORT2,	NULL);
-	gpio_request(GPIO_FN_LCD0_D22_PORT0,	NULL);
-	gpio_request(GPIO_FN_LCD0_D23_PORT1,	NULL);
-	gpio_request(GPIO_FN_LCD0_DCK,		NULL);
-	gpio_request(GPIO_FN_LCD0_VSYN,		NULL);
-	gpio_request(GPIO_FN_LCD0_HSYN,		NULL);
-	gpio_request(GPIO_FN_LCD0_DISP,		NULL);
-	gpio_request(GPIO_FN_LCD0_LCLK_PORT165,	NULL);
-
-	gpio_request_one(GPIO_PORT61, GPIOF_OUT_INIT_HIGH, NULL); /* LCDDON */
-	gpio_request_one(GPIO_PORT202, GPIOF_OUT_INIT_LOW, NULL); /* LCD0_LED_CONT */
+
+	gpio_request_one(61, GPIOF_OUT_INIT_HIGH, NULL); /* LCDDON */
+	gpio_request_one(202, GPIOF_OUT_INIT_LOW, NULL); /* LCD0_LED_CONT */
 
 	/* Touchscreen */
 	gpio_request(GPIO_FN_IRQ10,	NULL); /* TP_INT */
-	gpio_request_one(GPIO_PORT166, GPIOF_OUT_INIT_HIGH, NULL); /* TP_RST_B */
+	gpio_request_one(166, GPIOF_OUT_INIT_HIGH, NULL); /* TP_RST_B */
 
 	/* GETHER */
 	gpio_request(GPIO_FN_ET_CRS,		NULL);
@@ -1028,12 +1148,12 @@ static void __init eva_init(void)
 	gpio_request(GPIO_FN_ET_RX_DV,		NULL);
 	gpio_request(GPIO_FN_ET_RX_CLK,		NULL);
 
-	gpio_request_one(GPIO_PORT18, GPIOF_OUT_INIT_HIGH, NULL); /* PHY_RST */
+	gpio_request_one(18, GPIOF_OUT_INIT_HIGH, NULL); /* PHY_RST */
 
 	/* USB */
-	gpio_request_one(GPIO_PORT159, GPIOF_IN, NULL); /* USB_DEVICE_MODE */
+	gpio_request_one(159, GPIOF_IN, NULL); /* USB_DEVICE_MODE */
 
-	if (gpio_get_value(GPIO_PORT159)) {
+	if (gpio_get_value(159)) {
 		/* USB Host */
 	} else {
 		/* USB Func */
@@ -1042,47 +1162,15 @@ static void __init eva_init(void)
 		 * OTOH, usbhs interrupt needs its value (HI/LOW) to decide
 		 * USB connection/disconnection (usbhsf_get_vbus()).
 		 * This means we needs to select GPIO_FN_IRQ7_PORT209 first,
-		 * and select GPIO_PORT209 here
+		 * and select GPIO 209 here
 		 */
 		gpio_request(GPIO_FN_IRQ7_PORT209, NULL);
-		gpio_request_one(GPIO_PORT209, GPIOF_IN, NULL);
+		gpio_request_one(209, GPIOF_IN, NULL);
 
 		platform_device_register(&usbhsf_device);
 		usb = &usbhsf_device;
 	}
 
-	/* SDHI0 */
-	gpio_request(GPIO_FN_SDHI0_CMD, NULL);
-	gpio_request(GPIO_FN_SDHI0_CLK, NULL);
-	gpio_request(GPIO_FN_SDHI0_D0, NULL);
-	gpio_request(GPIO_FN_SDHI0_D1, NULL);
-	gpio_request(GPIO_FN_SDHI0_D2, NULL);
-	gpio_request(GPIO_FN_SDHI0_D3, NULL);
-	gpio_request(GPIO_FN_SDHI0_WP, NULL);
-
-	gpio_request_one(GPIO_PORT17, GPIOF_OUT_INIT_LOW, NULL);  /* SDHI0_18/33_B */
-	gpio_request_one(GPIO_PORT74, GPIOF_OUT_INIT_HIGH, NULL); /* SDHI0_PON */
-	gpio_request_one(GPIO_PORT75, GPIOF_OUT_INIT_HIGH, NULL); /* SDSLOT1_PON */
-
-	/* we can use GPIO_FN_IRQ31_PORT167 here for SDHI0 CD irq */
-
-	/*
-	 * MMCIF
-	 *
-	 * Here doesn't care SW1.4 status,
-	 * since CON2 is not mounted.
-	 */
-	gpio_request(GPIO_FN_MMC1_CLK_PORT103,	NULL);
-	gpio_request(GPIO_FN_MMC1_CMD_PORT104,	NULL);
-	gpio_request(GPIO_FN_MMC1_D0_PORT149,	NULL);
-	gpio_request(GPIO_FN_MMC1_D1_PORT148,	NULL);
-	gpio_request(GPIO_FN_MMC1_D2_PORT147,	NULL);
-	gpio_request(GPIO_FN_MMC1_D3_PORT146,	NULL);
-	gpio_request(GPIO_FN_MMC1_D4_PORT145,	NULL);
-	gpio_request(GPIO_FN_MMC1_D5_PORT144,	NULL);
-	gpio_request(GPIO_FN_MMC1_D6_PORT143,	NULL);
-	gpio_request(GPIO_FN_MMC1_D7_PORT142,	NULL);
-
 	/* CEU0 */
 	gpio_request(GPIO_FN_VIO0_D7,		NULL);
 	gpio_request(GPIO_FN_VIO0_D6,		NULL);
@@ -1099,10 +1187,10 @@ static void __init eva_init(void)
 	gpio_request(GPIO_FN_VIO_CKO,		NULL);
 
 	/* CON1/CON15 Camera */
-	gpio_request_one(GPIO_PORT173, GPIOF_OUT_INIT_LOW, NULL);  /* STANDBY */
-	gpio_request_one(GPIO_PORT172, GPIOF_OUT_INIT_HIGH, NULL); /* RST */
+	gpio_request_one(173, GPIOF_OUT_INIT_LOW, NULL);  /* STANDBY */
+	gpio_request_one(172, GPIOF_OUT_INIT_HIGH, NULL); /* RST */
 	/* see mt9t111_power() */
-	gpio_request_one(GPIO_PORT158, GPIOF_OUT_INIT_LOW, NULL);  /* CAM_PON */
+	gpio_request_one(158, GPIOF_OUT_INIT_LOW, NULL);  /* CAM_PON */
 
 	/* FSI-WM8978 */
 	gpio_request(GPIO_FN_FSIAIBT,		NULL);
@@ -1111,8 +1199,8 @@ static void __init eva_init(void)
 	gpio_request(GPIO_FN_FSIAOSLD,		NULL);
 	gpio_request(GPIO_FN_FSIAISLD_PORT5,	NULL);
 
-	gpio_request(GPIO_PORT7, NULL);
-	gpio_request(GPIO_PORT8, NULL);
+	gpio_request(7, NULL);
+	gpio_request(8, NULL);
 	gpio_direction_none(GPIO_PORT7CR); /* FSIAOBT needs no direction */
 	gpio_direction_none(GPIO_PORT8CR); /* FSIAOLR needs no direction */
 
@@ -1129,29 +1217,21 @@ static void __init eva_init(void)
 	 * DBGMD/LCDC0/FSIA MUX
 	 * DBGMD_SELECT_B should be set after setting PFC Function.
 	 */
-	gpio_request_one(GPIO_PORT176, GPIOF_OUT_INIT_HIGH, NULL);
+	gpio_request_one(176, GPIOF_OUT_INIT_HIGH, NULL);
 
 	/*
 	 * We can switch CON8/CON14 by SW1.5,
 	 * but it needs after DBGMD_SELECT_B
 	 */
-	gpio_request_one(GPIO_PORT6, GPIOF_IN, NULL);
-	if (gpio_get_value(GPIO_PORT6)) {
+	gpio_request_one(6, GPIOF_IN, NULL);
+	if (gpio_get_value(6)) {
 		/* CON14 enable */
 	} else {
 		/* CON8 (SDHI1) enable */
-		gpio_request(GPIO_FN_SDHI1_CLK,	NULL);
-		gpio_request(GPIO_FN_SDHI1_CMD,	NULL);
-		gpio_request(GPIO_FN_SDHI1_D0,	NULL);
-		gpio_request(GPIO_FN_SDHI1_D1,	NULL);
-		gpio_request(GPIO_FN_SDHI1_D2,	NULL);
-		gpio_request(GPIO_FN_SDHI1_D3,	NULL);
-		gpio_request(GPIO_FN_SDHI1_CD,	NULL);
-		gpio_request(GPIO_FN_SDHI1_WP,	NULL);
-
-		/* SDSLOT2_PON */
-		gpio_request_one(GPIO_PORT16, GPIOF_OUT_INIT_HIGH, NULL);
+		pinctrl_register_mappings(eva_sdhi1_pinctrl_map,
+					  ARRAY_SIZE(eva_sdhi1_pinctrl_map));
 
+		platform_device_register(&vcc_sdhi1);
 		platform_device_register(&sdhi1_device);
 	}
 
@@ -1207,7 +1287,6 @@ DT_MACHINE_START(ARMADILLO800EVA_DT, "armadillo800eva")
 	.map_io		= r8a7740_map_io,
 	.init_early	= eva_add_early_devices,
 	.init_irq	= r8a7740_init_irq,
-	.handle_irq	= shmobile_handle_irq_intc,
 	.init_machine	= eva_init,
 	.init_late	= shmobile_init_late,
 	.init_time	= eva_earlytimer_init,
diff --git a/arch/arm/mach-shmobile/board-bockw.c b/arch/arm/mach-shmobile/board-bockw.c
new file mode 100644
index 0000000..38e5e50
--- /dev/null
+++ b/arch/arm/mach-shmobile/board-bockw.c
@@ -0,0 +1,81 @@
+/*
+ * Bock-W board support
+ *
+ * Copyright (C) 2013  Renesas Solutions Corp.
+ * Copyright (C) 2013  Kuninori Morimoto <kuninori.morimoto.gx@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
+ * 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/platform_device.h>
+#include <linux/smsc911x.h>
+#include <mach/common.h>
+#include <mach/irqs.h>
+#include <mach/r8a7778.h>
+#include <asm/mach/arch.h>
+
+static struct smsc911x_platform_config smsc911x_data = {
+	.irq_polarity	= SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
+	.irq_type	= SMSC911X_IRQ_TYPE_PUSH_PULL,
+	.flags		= SMSC911X_USE_32BIT,
+	.phy_interface	= PHY_INTERFACE_MODE_MII,
+};
+
+static struct resource smsc911x_resources[] = {
+	DEFINE_RES_MEM(0x18300000, 0x1000),
+	DEFINE_RES_IRQ(irq_pin(0)), /* IRQ 0 */
+};
+
+#define IRQ0MR	0x30
+static void __init bockw_init(void)
+{
+	void __iomem *fpga;
+
+	r8a7778_clock_init();
+	r8a7778_init_irq_extpin(1);
+	r8a7778_add_standard_devices();
+
+	fpga = ioremap_nocache(0x18200000, SZ_1M);
+	if (fpga) {
+		/*
+		 * CAUTION
+		 *
+		 * IRQ0/1 is cascaded interrupt from FPGA.
+		 * it should be cared in the future
+		 * Now, it is assuming IRQ0 was used only from SMSC.
+		 */
+		u16 val = ioread16(fpga + IRQ0MR);
+		val &= ~(1 << 4); /* enable SMSC911x */
+		iowrite16(val, fpga + IRQ0MR);
+		iounmap(fpga);
+
+		platform_device_register_resndata(
+			&platform_bus, "smsc911x", -1,
+			smsc911x_resources, ARRAY_SIZE(smsc911x_resources),
+			&smsc911x_data, sizeof(smsc911x_data));
+	}
+}
+
+static const char *bockw_boards_compat_dt[] __initdata = {
+	"renesas,bockw",
+	NULL,
+};
+
+DT_MACHINE_START(BOCKW_DT, "bockw")
+	.init_early	= r8a7778_init_delay,
+	.init_irq	= r8a7778_init_irq_dt,
+	.init_machine	= bockw_init,
+	.init_time	= shmobile_timer_init,
+	.dt_compat	= bockw_boards_compat_dt,
+MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-bonito.c b/arch/arm/mach-shmobile/board-bonito.c
index e50f866..70d992c 100644
--- a/arch/arm/mach-shmobile/board-bonito.c
+++ b/arch/arm/mach-shmobile/board-bonito.c
@@ -24,6 +24,7 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
+#include <linux/pinctrl/machine.h>
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
 #include <linux/regulator/fixed.h>
@@ -288,6 +289,16 @@ static struct platform_device lcdc0_device = {
 	},
 };
 
+static const struct pinctrl_map lcdc0_pinctrl_map[] = {
+	/* LCD0 */
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_lcdc_fb.0", "pfc-r8a7740",
+				  "lcd0_data24_1", "lcd0"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_lcdc_fb.0", "pfc-r8a7740",
+				  "lcd0_lclk_1", "lcd0"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_lcdc_fb.0", "pfc-r8a7740",
+				  "lcd0_sync", "lcd0"),
+};
+
 /*
  * SMSC 9221
  */
@@ -392,8 +403,8 @@ static void __init bonito_init(void)
 	/*
 	 * base board settings
 	 */
-	gpio_request_one(GPIO_PORT176, GPIOF_IN, NULL);
-	if (!gpio_get_value(GPIO_PORT176)) {
+	gpio_request_one(176, GPIOF_IN, NULL);
+	if (!gpio_get_value(176)) {
 		u16 bsw2;
 		u16 bsw3;
 		u16 bsw4;
@@ -430,38 +441,11 @@ static void __init bonito_init(void)
 		 */
 		if (BIT_ON(bsw2, 3) &&	/* S38.1 = OFF */
 		    BIT_ON(bsw2, 2)) {	/* S38.2 = OFF */
-			gpio_request(GPIO_FN_LCDC0_SELECT,	NULL);
-			gpio_request(GPIO_FN_LCD0_D0,		NULL);
-			gpio_request(GPIO_FN_LCD0_D1,		NULL);
-			gpio_request(GPIO_FN_LCD0_D2,		NULL);
-			gpio_request(GPIO_FN_LCD0_D3,		NULL);
-			gpio_request(GPIO_FN_LCD0_D4,		NULL);
-			gpio_request(GPIO_FN_LCD0_D5,		NULL);
-			gpio_request(GPIO_FN_LCD0_D6,		NULL);
-			gpio_request(GPIO_FN_LCD0_D7,		NULL);
-			gpio_request(GPIO_FN_LCD0_D8,		NULL);
-			gpio_request(GPIO_FN_LCD0_D9,		NULL);
-			gpio_request(GPIO_FN_LCD0_D10,		NULL);
-			gpio_request(GPIO_FN_LCD0_D11,		NULL);
-			gpio_request(GPIO_FN_LCD0_D12,		NULL);
-			gpio_request(GPIO_FN_LCD0_D13,		NULL);
-			gpio_request(GPIO_FN_LCD0_D14,		NULL);
-			gpio_request(GPIO_FN_LCD0_D15,		NULL);
-			gpio_request(GPIO_FN_LCD0_D16,		NULL);
-			gpio_request(GPIO_FN_LCD0_D17,		NULL);
-			gpio_request(GPIO_FN_LCD0_D18_PORT163,	NULL);
-			gpio_request(GPIO_FN_LCD0_D19_PORT162,	NULL);
-			gpio_request(GPIO_FN_LCD0_D20_PORT161,	NULL);
-			gpio_request(GPIO_FN_LCD0_D21_PORT158,	NULL);
-			gpio_request(GPIO_FN_LCD0_D22_PORT160,	NULL);
-			gpio_request(GPIO_FN_LCD0_D23_PORT159,	NULL);
-			gpio_request(GPIO_FN_LCD0_DCK,		NULL);
-			gpio_request(GPIO_FN_LCD0_VSYN,		NULL);
-			gpio_request(GPIO_FN_LCD0_HSYN,		NULL);
-			gpio_request(GPIO_FN_LCD0_DISP,		NULL);
-			gpio_request(GPIO_FN_LCD0_LCLK_PORT165,	NULL);
-
-			gpio_request_one(GPIO_PORT61, GPIOF_OUT_INIT_HIGH,
+			pinctrl_register_mappings(lcdc0_pinctrl_map,
+						  ARRAY_SIZE(lcdc0_pinctrl_map));
+			gpio_request(GPIO_FN_LCDC0_SELECT, NULL);
+
+			gpio_request_one(61, GPIOF_OUT_INIT_HIGH,
 					 NULL); /* LCDDON */
 
 			/* backlight on */
diff --git a/arch/arm/mach-shmobile/board-kota2.c b/arch/arm/mach-shmobile/board-kota2.c
index 2ccc860..ef5ca0e 100644
--- a/arch/arm/mach-shmobile/board-kota2.c
+++ b/arch/arm/mach-shmobile/board-kota2.c
@@ -24,6 +24,8 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
+#include <linux/pinctrl/machine.h>
+#include <linux/pinctrl/pinconf-generic.h>
 #include <linux/platform_device.h>
 #include <linux/delay.h>
 #include <linux/io.h>
@@ -135,17 +137,17 @@ static struct platform_device keysc_device = {
 #define GPIO_KEY(c, g, d) { .code = c, .gpio = g, .desc = d, .active_low = 1 }
 
 static struct gpio_keys_button gpio_buttons[] = {
-	GPIO_KEY(KEY_VOLUMEUP, GPIO_PORT56, "+"), /* S2: VOL+ [IRQ9] */
-	GPIO_KEY(KEY_VOLUMEDOWN, GPIO_PORT54, "-"), /* S3: VOL- [IRQ10] */
-	GPIO_KEY(KEY_MENU, GPIO_PORT27, "Menu"), /* S4: MENU [IRQ30] */
-	GPIO_KEY(KEY_HOMEPAGE, GPIO_PORT26, "Home"), /* S5: HOME [IRQ31] */
-	GPIO_KEY(KEY_BACK, GPIO_PORT11, "Back"), /* S6: BACK [IRQ0] */
-	GPIO_KEY(KEY_PHONE, GPIO_PORT238, "Tel"), /* S7: TEL [IRQ11] */
-	GPIO_KEY(KEY_POWER, GPIO_PORT239, "C1"), /* S8: CAM [IRQ13] */
-	GPIO_KEY(KEY_MAIL, GPIO_PORT224, "Mail"), /* S9: MAIL [IRQ3] */
-	/* Omitted button "C3?": GPIO_PORT223 - S10: CUST [IRQ8] */
-	GPIO_KEY(KEY_CAMERA, GPIO_PORT164, "C2"), /* S11: CAM_HALF [IRQ25] */
-	/* Omitted button "?": GPIO_PORT152 - S12: CAM_FULL [No IRQ] */
+	GPIO_KEY(KEY_VOLUMEUP, 56, "+"), /* S2: VOL+ [IRQ9] */
+	GPIO_KEY(KEY_VOLUMEDOWN, 54, "-"), /* S3: VOL- [IRQ10] */
+	GPIO_KEY(KEY_MENU, 27, "Menu"), /* S4: MENU [IRQ30] */
+	GPIO_KEY(KEY_HOMEPAGE, 26, "Home"), /* S5: HOME [IRQ31] */
+	GPIO_KEY(KEY_BACK, 11, "Back"), /* S6: BACK [IRQ0] */
+	GPIO_KEY(KEY_PHONE, 238, "Tel"), /* S7: TEL [IRQ11] */
+	GPIO_KEY(KEY_POWER, 239, "C1"), /* S8: CAM [IRQ13] */
+	GPIO_KEY(KEY_MAIL, 224, "Mail"), /* S9: MAIL [IRQ3] */
+	/* Omitted button "C3?": 223 - S10: CUST [IRQ8] */
+	GPIO_KEY(KEY_CAMERA, 164, "C2"), /* S11: CAM_HALF [IRQ25] */
+	/* Omitted button "?": 152 - S12: CAM_FULL [No IRQ] */
 };
 
 static struct gpio_keys_platform_data gpio_key_info = {
@@ -165,9 +167,9 @@ static struct platform_device gpio_keys_device = {
 #define GPIO_LED(n, g) { .name = n, .gpio = g }
 
 static struct gpio_led gpio_leds[] = {
-	GPIO_LED("G", GPIO_PORT20), /* PORT20 [GPO0] -> LED7 -> "G" */
-	GPIO_LED("H", GPIO_PORT21), /* PORT21 [GPO1] -> LED8 -> "H" */
-	GPIO_LED("J", GPIO_PORT22), /* PORT22 [GPO2] -> LED9 -> "J" */
+	GPIO_LED("G", 20), /* PORT20 [GPO0] -> LED7 -> "G" */
+	GPIO_LED("H", 21), /* PORT21 [GPO1] -> LED8 -> "H" */
+	GPIO_LED("J", 22), /* PORT22 [GPO2] -> LED9 -> "J" */
 };
 
 static struct gpio_led_platform_data gpio_leds_info = {
@@ -187,7 +189,7 @@ static struct platform_device gpio_leds_device = {
 static struct led_renesas_tpu_config led_renesas_tpu12_pdata = {
 	.name		= "V2513",
 	.pin_gpio_fn	= GPIO_FN_TPU1TO2,
-	.pin_gpio	= GPIO_PORT153,
+	.pin_gpio	= 153,
 	.channel_offset = 0x90,
 	.timer_bit = 2,
 	.max_brightness = 1000,
@@ -215,7 +217,7 @@ static struct platform_device leds_tpu12_device = {
 static struct led_renesas_tpu_config led_renesas_tpu41_pdata = {
 	.name		= "V2514",
 	.pin_gpio_fn	= GPIO_FN_TPU4TO1,
-	.pin_gpio	= GPIO_PORT199,
+	.pin_gpio	= 199,
 	.channel_offset = 0x50,
 	.timer_bit = 1,
 	.max_brightness = 1000,
@@ -243,7 +245,7 @@ static struct platform_device leds_tpu41_device = {
 static struct led_renesas_tpu_config led_renesas_tpu21_pdata = {
 	.name		= "V2515",
 	.pin_gpio_fn	= GPIO_FN_TPU2TO1,
-	.pin_gpio	= GPIO_PORT197,
+	.pin_gpio	= 197,
 	.channel_offset = 0x50,
 	.timer_bit = 1,
 	.max_brightness = 1000,
@@ -271,7 +273,7 @@ static struct platform_device leds_tpu21_device = {
 static struct led_renesas_tpu_config led_renesas_tpu30_pdata = {
 	.name		= "KEYLED",
 	.pin_gpio_fn	= GPIO_FN_TPU3TO0,
-	.pin_gpio	= GPIO_PORT163,
+	.pin_gpio	= 163,
 	.channel_offset = 0x10,
 	.timer_bit = 0,
 	.max_brightness = 1000,
@@ -433,6 +435,85 @@ static struct platform_device *kota2_devices[] __initdata = {
 	&sdhi1_device,
 };
 
+static unsigned long pin_pullup_conf[] = {
+	PIN_CONF_PACKED(PIN_CONFIG_BIAS_PULL_UP, 0),
+};
+
+static const struct pinctrl_map kota2_pinctrl_map[] = {
+	/* KEYSC */
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_keysc.0", "pfc-sh73a0",
+				  "keysc_in8", "keysc"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_keysc.0", "pfc-sh73a0",
+				  "keysc_out04", "keysc"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_keysc.0", "pfc-sh73a0",
+				  "keysc_out5", "keysc"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_keysc.0", "pfc-sh73a0",
+				  "keysc_out6_0", "keysc"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_keysc.0", "pfc-sh73a0",
+				  "keysc_out7_0", "keysc"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_keysc.0", "pfc-sh73a0",
+				  "keysc_out8_0", "keysc"),
+	PIN_MAP_CONFIGS_GROUP_DEFAULT("sh_keysc.0", "pfc-sh73a0",
+				      "keysc_in8", pin_pullup_conf),
+	/* MMCIF */
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mmcif.0", "pfc-sh73a0",
+				  "mmc0_data8_0", "mmc0"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mmcif.0", "pfc-sh73a0",
+				  "mmc0_ctrl_0", "mmc0"),
+	PIN_MAP_CONFIGS_PIN_DEFAULT("sh_mmcif.0", "pfc-sh73a0",
+				    "PORT279", pin_pullup_conf),
+	PIN_MAP_CONFIGS_GROUP_DEFAULT("sh_mmcif.0", "pfc-sh73a0",
+				      "mmc0_data8_0", pin_pullup_conf),
+	/* SCIFA2 (UART2) */
+	PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.2", "pfc-sh73a0",
+				  "scifa2_data_0", "scifa2"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.2", "pfc-sh73a0",
+				  "scifa2_ctrl_0", "scifa2"),
+	/* SCIFA4 (UART1) */
+	PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.4", "pfc-sh73a0",
+				  "scifa4_data", "scifa4"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.4", "pfc-sh73a0",
+				  "scifa4_ctrl", "scifa4"),
+	/* SCIFB (BT) */
+	PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.8", "pfc-sh73a0",
+				  "scifb_data_0", "scifb"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.8", "pfc-sh73a0",
+				  "scifb_clk_0", "scifb"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.8", "pfc-sh73a0",
+				  "scifb_ctrl_0", "scifb"),
+	/* SDHI0 (microSD) */
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-sh73a0",
+				  "sdhi0_data4", "sdhi0"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-sh73a0",
+				  "sdhi0_ctrl", "sdhi0"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-sh73a0",
+				  "sdhi0_cd", "sdhi0"),
+	PIN_MAP_CONFIGS_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-sh73a0",
+				      "sdhi0_data4", pin_pullup_conf),
+	PIN_MAP_CONFIGS_PIN_DEFAULT("sh_mobile_sdhi.0", "pfc-sh73a0",
+				    "PORT256", pin_pullup_conf),
+	PIN_MAP_CONFIGS_PIN_DEFAULT("sh_mobile_sdhi.0", "pfc-sh73a0",
+				    "PORT251", pin_pullup_conf),
+	/* SDHI1 (BCM4330) */
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.1", "pfc-sh73a0",
+				  "sdhi1_data4", "sdhi1"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.1", "pfc-sh73a0",
+				  "sdhi1_ctrl", "sdhi1"),
+	PIN_MAP_CONFIGS_GROUP_DEFAULT("sh_mobile_sdhi.1", "pfc-sh73a0",
+				      "sdhi1_data4", pin_pullup_conf),
+	PIN_MAP_CONFIGS_PIN_DEFAULT("sh_mobile_sdhi.1", "pfc-sh73a0",
+				    "PORT263", pin_pullup_conf),
+	/* SMSC911X */
+	PIN_MAP_MUX_GROUP_DEFAULT("smsc911x.0", "pfc-sh73a0",
+				  "bsc_data_0_7", "bsc"),
+	PIN_MAP_MUX_GROUP_DEFAULT("smsc911x.0", "pfc-sh73a0",
+				  "bsc_data_8_15", "bsc"),
+	PIN_MAP_MUX_GROUP_DEFAULT("smsc911x.0", "pfc-sh73a0",
+				  "bsc_cs5_a", "bsc"),
+	PIN_MAP_MUX_GROUP_DEFAULT("smsc911x.0", "pfc-sh73a0",
+				  "bsc_we0", "bsc"),
+};
+
 static void __init kota2_init(void)
 {
 	regulator_register_always_on(0, "fixed-1.8V", fixed1v8_power_consumers,
@@ -441,97 +522,16 @@ static void __init kota2_init(void)
 				     ARRAY_SIZE(fixed3v3_power_consumers), 3300000);
 	regulator_register_fixed(2, dummy_supplies, ARRAY_SIZE(dummy_supplies));
 
+	pinctrl_register_mappings(kota2_pinctrl_map,
+				  ARRAY_SIZE(kota2_pinctrl_map));
 	sh73a0_pinmux_init();
 
-	/* SCIFA2 (UART2) */
-	gpio_request(GPIO_FN_SCIFA2_TXD1, NULL);
-	gpio_request(GPIO_FN_SCIFA2_RXD1, NULL);
-	gpio_request(GPIO_FN_SCIFA2_RTS1_, NULL);
-	gpio_request(GPIO_FN_SCIFA2_CTS1_, NULL);
-
-	/* SCIFA4 (UART1) */
-	gpio_request(GPIO_FN_SCIFA4_TXD, NULL);
-	gpio_request(GPIO_FN_SCIFA4_RXD, NULL);
-	gpio_request(GPIO_FN_SCIFA4_RTS_, NULL);
-	gpio_request(GPIO_FN_SCIFA4_CTS_, NULL);
-
 	/* SMSC911X */
-	gpio_request(GPIO_FN_D0_NAF0, NULL);
-	gpio_request(GPIO_FN_D1_NAF1, NULL);
-	gpio_request(GPIO_FN_D2_NAF2, NULL);
-	gpio_request(GPIO_FN_D3_NAF3, NULL);
-	gpio_request(GPIO_FN_D4_NAF4, NULL);
-	gpio_request(GPIO_FN_D5_NAF5, NULL);
-	gpio_request(GPIO_FN_D6_NAF6, NULL);
-	gpio_request(GPIO_FN_D7_NAF7, NULL);
-	gpio_request(GPIO_FN_D8_NAF8, NULL);
-	gpio_request(GPIO_FN_D9_NAF9, NULL);
-	gpio_request(GPIO_FN_D10_NAF10, NULL);
-	gpio_request(GPIO_FN_D11_NAF11, NULL);
-	gpio_request(GPIO_FN_D12_NAF12, NULL);
-	gpio_request(GPIO_FN_D13_NAF13, NULL);
-	gpio_request(GPIO_FN_D14_NAF14, NULL);
-	gpio_request(GPIO_FN_D15_NAF15, NULL);
-	gpio_request(GPIO_FN_CS5A_, NULL);
-	gpio_request(GPIO_FN_WE0__FWE, NULL);
-	gpio_request_one(GPIO_PORT144, GPIOF_IN, NULL); /* PINTA2 */
-	gpio_request_one(GPIO_PORT145, GPIOF_OUT_INIT_HIGH, NULL); /* RESET */
-
-	/* KEYSC */
-	gpio_request(GPIO_FN_KEYIN0_PU, NULL);
-	gpio_request(GPIO_FN_KEYIN1_PU, NULL);
-	gpio_request(GPIO_FN_KEYIN2_PU, NULL);
-	gpio_request(GPIO_FN_KEYIN3_PU, NULL);
-	gpio_request(GPIO_FN_KEYIN4_PU, NULL);
-	gpio_request(GPIO_FN_KEYIN5_PU, NULL);
-	gpio_request(GPIO_FN_KEYIN6_PU, NULL);
-	gpio_request(GPIO_FN_KEYIN7_PU, NULL);
-	gpio_request(GPIO_FN_KEYOUT0, NULL);
-	gpio_request(GPIO_FN_KEYOUT1, NULL);
-	gpio_request(GPIO_FN_KEYOUT2, NULL);
-	gpio_request(GPIO_FN_KEYOUT3, NULL);
-	gpio_request(GPIO_FN_KEYOUT4, NULL);
-	gpio_request(GPIO_FN_KEYOUT5, NULL);
-	gpio_request(GPIO_FN_PORT59_KEYOUT6, NULL);
-	gpio_request(GPIO_FN_PORT58_KEYOUT7, NULL);
-	gpio_request(GPIO_FN_KEYOUT8, NULL);
+	gpio_request_one(144, GPIOF_IN, NULL); /* PINTA2 */
+	gpio_request_one(145, GPIOF_OUT_INIT_HIGH, NULL); /* RESET */
 
 	/* MMCIF */
-	gpio_request(GPIO_FN_MMCCLK0, NULL);
-	gpio_request(GPIO_FN_MMCD0_0, NULL);
-	gpio_request(GPIO_FN_MMCD0_1, NULL);
-	gpio_request(GPIO_FN_MMCD0_2, NULL);
-	gpio_request(GPIO_FN_MMCD0_3, NULL);
-	gpio_request(GPIO_FN_MMCD0_4, NULL);
-	gpio_request(GPIO_FN_MMCD0_5, NULL);
-	gpio_request(GPIO_FN_MMCD0_6, NULL);
-	gpio_request(GPIO_FN_MMCD0_7, NULL);
-	gpio_request(GPIO_FN_MMCCMD0, NULL);
-	gpio_request_one(GPIO_PORT208, GPIOF_OUT_INIT_HIGH, NULL); /* Reset */
-
-	/* SDHI0 (microSD) */
-	gpio_request(GPIO_FN_SDHICD0_PU, NULL);
-	gpio_request(GPIO_FN_SDHICMD0_PU, NULL);
-	gpio_request(GPIO_FN_SDHICLK0, NULL);
-	gpio_request(GPIO_FN_SDHID0_3_PU, NULL);
-	gpio_request(GPIO_FN_SDHID0_2_PU, NULL);
-	gpio_request(GPIO_FN_SDHID0_1_PU, NULL);
-	gpio_request(GPIO_FN_SDHID0_0_PU, NULL);
-
-	/* SCIFB (BT) */
-	gpio_request(GPIO_FN_PORT159_SCIFB_SCK, NULL);
-	gpio_request(GPIO_FN_PORT160_SCIFB_TXD, NULL);
-	gpio_request(GPIO_FN_PORT161_SCIFB_CTS_, NULL);
-	gpio_request(GPIO_FN_PORT162_SCIFB_RXD, NULL);
-	gpio_request(GPIO_FN_PORT163_SCIFB_RTS_, NULL);
-
-	/* SDHI1 (BCM4330) */
-	gpio_request(GPIO_FN_SDHICLK1, NULL);
-	gpio_request(GPIO_FN_SDHICMD1_PU, NULL);
-	gpio_request(GPIO_FN_SDHID1_3_PU, NULL);
-	gpio_request(GPIO_FN_SDHID1_2_PU, NULL);
-	gpio_request(GPIO_FN_SDHID1_1_PU, NULL);
-	gpio_request(GPIO_FN_SDHID1_0_PU, NULL);
+	gpio_request_one(208, GPIOF_OUT_INIT_HIGH, NULL); /* Reset */
 
 #ifdef CONFIG_CACHE_L2X0
 	/* Early BRESP enable, Shared attribute override enable, 64K*8way */
diff --git a/arch/arm/mach-shmobile/board-kzm9g-reference.c b/arch/arm/mach-shmobile/board-kzm9g-reference.c
new file mode 100644
index 0000000..aefa50d
--- /dev/null
+++ b/arch/arm/mach-shmobile/board-kzm9g-reference.c
@@ -0,0 +1,107 @@
+/*
+ * KZM-A9-GT board support - Reference Device Tree Implementation
+ *
+ * Copyright (C) 2012	Horms Solutions Ltd.
+ *
+ * Based on board-kzm9g.c
+ * Copyright (C) 2012	Kuninori Morimoto <kuninori.morimoto.gx@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
+ * 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/delay.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqchip.h>
+#include <linux/input.h>
+#include <linux/of_platform.h>
+#include <linux/pinctrl/machine.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <mach/sh73a0.h>
+#include <mach/common.h>
+#include <asm/hardware/cache-l2x0.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+static unsigned long pin_pullup_conf[] = {
+	PIN_CONF_PACKED(PIN_CONFIG_BIAS_PULL_UP, 0),
+};
+
+static const struct pinctrl_map kzm_pinctrl_map[] = {
+	PIN_MAP_MUX_GROUP_DEFAULT("e6826000.i2c", "pfc-sh73a0",
+				  "i2c3_1", "i2c3"),
+	/* MMCIF */
+	PIN_MAP_MUX_GROUP_DEFAULT("e6bd0000.mmcif", "pfc-sh73a0",
+				  "mmc0_data8_0", "mmc0"),
+	PIN_MAP_MUX_GROUP_DEFAULT("e6bd0000.mmcif", "pfc-sh73a0",
+				  "mmc0_ctrl_0", "mmc0"),
+	PIN_MAP_CONFIGS_PIN_DEFAULT("e6bd0000.mmcif", "pfc-sh73a0",
+				    "PORT279", pin_pullup_conf),
+	PIN_MAP_CONFIGS_GROUP_DEFAULT("e6bd0000.mmcif", "pfc-sh73a0",
+				      "mmc0_data8_0", pin_pullup_conf),
+	/* SCIFA4 */
+	PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.4", "pfc-sh73a0",
+				  "scifa4_data", "scifa4"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.4", "pfc-sh73a0",
+				  "scifa4_ctrl", "scifa4"),
+	/* SDHI0 */
+	PIN_MAP_MUX_GROUP_DEFAULT("ee100000.sdhi", "pfc-sh73a0",
+				  "sdhi0_data4", "sdhi0"),
+	PIN_MAP_MUX_GROUP_DEFAULT("ee100000.sdhi", "pfc-sh73a0",
+				  "sdhi0_ctrl", "sdhi0"),
+	PIN_MAP_MUX_GROUP_DEFAULT("ee100000.sdhi", "pfc-sh73a0",
+				  "sdhi0_cd", "sdhi0"),
+	PIN_MAP_MUX_GROUP_DEFAULT("ee100000.sdhi", "pfc-sh73a0",
+				  "sdhi0_wp", "sdhi0"),
+	/* SDHI2 */
+	PIN_MAP_MUX_GROUP_DEFAULT("ee140000.sdhi", "pfc-sh73a0",
+				  "sdhi2_data4", "sdhi2"),
+	PIN_MAP_MUX_GROUP_DEFAULT("ee140000.sdhi", "pfc-sh73a0",
+				  "sdhi2_ctrl", "sdhi2"),
+};
+
+static void __init kzm_init(void)
+{
+	sh73a0_add_standard_devices_dt();
+	pinctrl_register_mappings(kzm_pinctrl_map, ARRAY_SIZE(kzm_pinctrl_map));
+	sh73a0_pinmux_init();
+
+	/* enable SD */
+	gpio_request(GPIO_FN_SDHI0_VCCQ_MC0_ON,	NULL);
+	gpio_request_one(15, GPIOF_OUT_INIT_HIGH, NULL); /* power */
+
+	gpio_request_one(14, GPIOF_OUT_INIT_HIGH, NULL); /* power */
+
+#ifdef CONFIG_CACHE_L2X0
+	/* Early BRESP enable, Shared attribute override enable, 64K*8way */
+	l2x0_init(IOMEM(0xf0100000), 0x40460000, 0x82000fff);
+#endif
+}
+
+static const char *kzm9g_boards_compat_dt[] __initdata = {
+	"renesas,kzm9g-reference",
+	NULL,
+};
+
+DT_MACHINE_START(KZM9G_DT, "kzm9g-reference")
+	.smp		= smp_ops(sh73a0_smp_ops),
+	.map_io		= sh73a0_map_io,
+	.init_early	= sh73a0_init_delay,
+	.nr_irqs	= NR_IRQS_LEGACY,
+	.init_irq	= irqchip_init,
+	.init_machine	= kzm_init,
+	.init_time	= shmobile_timer_init,
+	.dt_compat	= kzm9g_boards_compat_dt,
+MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-kzm9g.c b/arch/arm/mach-shmobile/board-kzm9g.c
index 7f3a6b7..e6b775a 100644
--- a/arch/arm/mach-shmobile/board-kzm9g.c
+++ b/arch/arm/mach-shmobile/board-kzm9g.c
@@ -30,6 +30,8 @@
 #include <linux/mmc/sh_mmcif.h>
 #include <linux/mmc/sh_mobile_sdhi.h>
 #include <linux/mfd/tmio.h>
+#include <linux/pinctrl/machine.h>
+#include <linux/pinctrl/pinconf-generic.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/fixed.h>
 #include <linux/regulator/machine.h>
@@ -61,8 +63,8 @@
 
 /* Dummy supplies, where voltage doesn't matter */
 static struct regulator_consumer_supply dummy_supplies[] = {
-	REGULATOR_SUPPLY("vddvario", "smsc911x"),
-	REGULATOR_SUPPLY("vdd33a", "smsc911x"),
+	REGULATOR_SUPPLY("vddvario", "smsc911x.0"),
+	REGULATOR_SUPPLY("vdd33a", "smsc911x.0"),
 };
 
 /*
@@ -81,7 +83,7 @@ static struct resource smsc9221_resources[] = {
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= intcs_evt2irq(0x260), /* IRQ3 */
+		.start	= irq_pin(3), /* IRQ3 */
 		.flags	= IORESOURCE_IRQ,
 	},
 };
@@ -115,7 +117,7 @@ static struct resource usb_resources[] = {
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= intcs_evt2irq(0x220), /* IRQ1 */
+		.start	= irq_pin(1), /* IRQ1 */
 		.flags	= IORESOURCE_IRQ,
 	},
 };
@@ -138,7 +140,7 @@ struct usbhs_private {
 	struct renesas_usbhs_platform_info info;
 };
 
-#define IRQ15			intcs_evt2irq(0x03e0)
+#define IRQ15			irq_pin(15)
 #define USB_PHY_MODE		(1 << 4)
 #define USB_PHY_INT_EN		((1 << 3) | (1 << 2))
 #define USB_PHY_ON		(1 << 1)
@@ -155,12 +157,14 @@ static int usbhs_get_vbus(struct platform_device *pdev)
 	return !((1 << 7) & __raw_readw(priv->cr2));
 }
 
-static void usbhs_phy_reset(struct platform_device *pdev)
+static int usbhs_phy_reset(struct platform_device *pdev)
 {
 	struct usbhs_private *priv = usbhs_get_priv(pdev);
 
 	/* init phy */
 	__raw_writew(0x8a0a, priv->cr2);
+
+	return 0;
 }
 
 static int usbhs_get_id(struct platform_device *pdev)
@@ -202,7 +206,7 @@ static int usbhs_hardware_init(struct platform_device *pdev)
 	return 0;
 }
 
-static void usbhs_hardware_exit(struct platform_device *pdev)
+static int usbhs_hardware_exit(struct platform_device *pdev)
 {
 	struct usbhs_private *priv = usbhs_get_priv(pdev);
 
@@ -210,6 +214,8 @@ static void usbhs_hardware_exit(struct platform_device *pdev)
 	__raw_writew(USB_PHY_MODE | USB_PHY_INT_CLR, priv->phy);
 
 	free_irq(IRQ15, pdev);
+
+	return 0;
 }
 
 static u32 usbhs_pipe_cfg[] = {
@@ -373,13 +379,64 @@ static struct platform_device mmc_device = {
 	.resource	= sh_mmcif_resources,
 };
 
-/* Fixed 2.8V regulators to be used by SDHI0 and SDHI2 */
-static struct regulator_consumer_supply fixed2v8_power_consumers[] =
+/* Fixed 3.3V regulators to be used by SDHI0 */
+static struct regulator_consumer_supply vcc_sdhi0_consumers[] =
 {
 	REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.0"),
-	REGULATOR_SUPPLY("vqmmc", "sh_mobile_sdhi.0"),
+};
+
+static struct regulator_init_data vcc_sdhi0_init_data = {
+	.constraints = {
+		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies  = ARRAY_SIZE(vcc_sdhi0_consumers),
+	.consumer_supplies      = vcc_sdhi0_consumers,
+};
+
+static struct fixed_voltage_config vcc_sdhi0_info = {
+	.supply_name = "SDHI0 Vcc",
+	.microvolts = 3300000,
+	.gpio = 15,
+	.enable_high = 1,
+	.init_data = &vcc_sdhi0_init_data,
+};
+
+static struct platform_device vcc_sdhi0 = {
+	.name = "reg-fixed-voltage",
+	.id   = 0,
+	.dev  = {
+		.platform_data = &vcc_sdhi0_info,
+	},
+};
+
+/* Fixed 3.3V regulators to be used by SDHI2 */
+static struct regulator_consumer_supply vcc_sdhi2_consumers[] =
+{
 	REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.2"),
-	REGULATOR_SUPPLY("vqmmc", "sh_mobile_sdhi.2"),
+};
+
+static struct regulator_init_data vcc_sdhi2_init_data = {
+	.constraints = {
+		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies  = ARRAY_SIZE(vcc_sdhi2_consumers),
+	.consumer_supplies      = vcc_sdhi2_consumers,
+};
+
+static struct fixed_voltage_config vcc_sdhi2_info = {
+	.supply_name = "SDHI2 Vcc",
+	.microvolts = 3300000,
+	.gpio = 14,
+	.enable_high = 1,
+	.init_data = &vcc_sdhi2_init_data,
+};
+
+static struct platform_device vcc_sdhi2 = {
+	.name = "reg-fixed-voltage",
+	.id   = 1,
+	.dev  = {
+		.platform_data = &vcc_sdhi2_info,
+	},
 };
 
 /* SDHI */
@@ -387,8 +444,8 @@ static struct sh_mobile_sdhi_info sdhi0_info = {
 	.dma_slave_tx	= SHDMA_SLAVE_SDHI0_TX,
 	.dma_slave_rx	= SHDMA_SLAVE_SDHI0_RX,
 	.tmio_flags	= TMIO_MMC_HAS_IDLE_WAIT,
-	.tmio_caps	= MMC_CAP_SD_HIGHSPEED,
-	.tmio_ocr_mask	= MMC_VDD_27_28 | MMC_VDD_28_29,
+	.tmio_caps	= MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ |
+			  MMC_CAP_POWER_OFF_CARD,
 };
 
 static struct resource sdhi0_resources[] = {
@@ -431,9 +488,8 @@ static struct sh_mobile_sdhi_info sdhi2_info = {
 	.tmio_flags	= TMIO_MMC_HAS_IDLE_WAIT |
 			  TMIO_MMC_USE_GPIO_CD |
 			  TMIO_MMC_WRPROTECT_DISABLE,
-	.tmio_caps	= MMC_CAP_SD_HIGHSPEED,
-	.tmio_ocr_mask	= MMC_VDD_27_28 | MMC_VDD_28_29,
-	.cd_gpio	= GPIO_PORT13,
+	.tmio_caps	= MMC_CAP_SD_HIGHSPEED | MMC_CAP_POWER_OFF_CARD,
+	.cd_gpio	= 13,
 };
 
 static struct resource sdhi2_resources[] = {
@@ -563,25 +619,25 @@ static struct i2c_board_info i2c0_devices[] = {
 	},
 	{
 		I2C_BOARD_INFO("ak8975", 0x0c),
-		.irq = intcs_evt2irq(0x3380), /* IRQ28 */
+		.irq = irq_pin(28), /* IRQ28 */
 	},
 	{
 		I2C_BOARD_INFO("adxl34x", 0x1d),
-		.irq = intcs_evt2irq(0x3340), /* IRQ26 */
+		.irq = irq_pin(26), /* IRQ26 */
 	},
 };
 
 static struct i2c_board_info i2c1_devices[] = {
 	{
 		I2C_BOARD_INFO("st1232-ts", 0x55),
-		.irq = intcs_evt2irq(0x300), /* IRQ8 */
+		.irq = irq_pin(8), /* IRQ8 */
 	},
 };
 
 static struct i2c_board_info i2c3_devices[] = {
 	{
 		I2C_BOARD_INFO("pcf8575", 0x20),
-		.irq		= intcs_evt2irq(0x3260), /* IRQ19 */
+		.irq = irq_pin(19), /* IRQ19 */
 		.platform_data = &pcf8575_pdata,
 	},
 };
@@ -592,6 +648,8 @@ static struct platform_device *kzm_devices[] __initdata = {
 	&usbhs_device,
 	&lcdc_device,
 	&mmc_device,
+	&vcc_sdhi0,
+	&vcc_sdhi2,
 	&sdhi0_device,
 	&sdhi2_device,
 	&gpio_keys_device,
@@ -599,6 +657,64 @@ static struct platform_device *kzm_devices[] __initdata = {
 	&fsi_ak4648_device,
 };
 
+static unsigned long pin_pullup_conf[] = {
+	PIN_CONF_PACKED(PIN_CONFIG_BIAS_PULL_UP, 0),
+};
+
+static const struct pinctrl_map kzm_pinctrl_map[] = {
+	/* FSIA (AK4648) */
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_fsi2.0", "pfc-sh73a0",
+				  "fsia_mclk_in", "fsia"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_fsi2.0", "pfc-sh73a0",
+				  "fsia_sclk_in", "fsia"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_fsi2.0", "pfc-sh73a0",
+				  "fsia_data_in", "fsia"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_fsi2.0", "pfc-sh73a0",
+				  "fsia_data_out", "fsia"),
+	/* I2C3 */
+	PIN_MAP_MUX_GROUP_DEFAULT("i2c-sh_mobile.3", "pfc-sh73a0",
+				  "i2c3_1", "i2c3"),
+	/* LCD */
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_lcdc_fb.0", "pfc-sh73a0",
+				  "lcd_data24", "lcd"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_lcdc_fb.0", "pfc-sh73a0",
+				  "lcd_sync", "lcd"),
+	/* MMCIF */
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mmcif.0", "pfc-sh73a0",
+				  "mmc0_data8_0", "mmc0"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mmcif.0", "pfc-sh73a0",
+				  "mmc0_ctrl_0", "mmc0"),
+	PIN_MAP_CONFIGS_PIN_DEFAULT("sh_mmcif.0", "pfc-sh73a0",
+				    "PORT279", pin_pullup_conf),
+	PIN_MAP_CONFIGS_GROUP_DEFAULT("sh_mmcif.0", "pfc-sh73a0",
+				      "mmc0_data8_0", pin_pullup_conf),
+	/* SCIFA4 */
+	PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.4", "pfc-sh73a0",
+				  "scifa4_data", "scifa4"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.4", "pfc-sh73a0",
+				  "scifa4_ctrl", "scifa4"),
+	/* SDHI0 */
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-sh73a0",
+				  "sdhi0_data4", "sdhi0"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-sh73a0",
+				  "sdhi0_ctrl", "sdhi0"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-sh73a0",
+				  "sdhi0_cd", "sdhi0"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-sh73a0",
+				  "sdhi0_wp", "sdhi0"),
+	/* SDHI2 */
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.2", "pfc-sh73a0",
+				  "sdhi2_data4", "sdhi2"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.2", "pfc-sh73a0",
+				  "sdhi2_ctrl", "sdhi2"),
+	/* SMSC */
+	PIN_MAP_MUX_GROUP_DEFAULT("smsc911x.0", "pfc-sh73a0",
+				  "bsc_cs4", "bsc"),
+	/* USB */
+	PIN_MAP_MUX_GROUP_DEFAULT("renesas_usbhs", "pfc-sh73a0",
+				  "usb_vbus", "usb"),
+};
+
 /*
  * FIXME
  *
@@ -654,106 +770,26 @@ device_initcall(as3711_enable_lcdc_backlight);
 
 static void __init kzm_init(void)
 {
-	regulator_register_always_on(0, "fixed-1.8V", fixed1v8_power_consumers,
+	regulator_register_always_on(2, "fixed-1.8V", fixed1v8_power_consumers,
 				     ARRAY_SIZE(fixed1v8_power_consumers), 1800000);
-	regulator_register_always_on(1, "fixed-2.8V", fixed2v8_power_consumers,
-				     ARRAY_SIZE(fixed2v8_power_consumers), 2800000);
-	regulator_register_fixed(2, dummy_supplies, ARRAY_SIZE(dummy_supplies));
+	regulator_register_fixed(3, dummy_supplies, ARRAY_SIZE(dummy_supplies));
 
-	sh73a0_pinmux_init();
-
-	/* enable SCIFA4 */
-	gpio_request(GPIO_FN_SCIFA4_TXD, NULL);
-	gpio_request(GPIO_FN_SCIFA4_RXD, NULL);
-	gpio_request(GPIO_FN_SCIFA4_RTS_, NULL);
-	gpio_request(GPIO_FN_SCIFA4_CTS_, NULL);
+	pinctrl_register_mappings(kzm_pinctrl_map, ARRAY_SIZE(kzm_pinctrl_map));
 
-	/* CS4 for SMSC/USB */
-	gpio_request(GPIO_FN_CS4_, NULL); /* CS4 */
+	sh73a0_pinmux_init();
 
 	/* SMSC */
-	gpio_request_one(GPIO_PORT224, GPIOF_IN, NULL); /* IRQ3 */
+	gpio_request_one(224, GPIOF_IN, NULL); /* IRQ3 */
 
 	/* LCDC */
-	gpio_request(GPIO_FN_LCDD23,	NULL);
-	gpio_request(GPIO_FN_LCDD22,	NULL);
-	gpio_request(GPIO_FN_LCDD21,	NULL);
-	gpio_request(GPIO_FN_LCDD20,	NULL);
-	gpio_request(GPIO_FN_LCDD19,	NULL);
-	gpio_request(GPIO_FN_LCDD18,	NULL);
-	gpio_request(GPIO_FN_LCDD17,	NULL);
-	gpio_request(GPIO_FN_LCDD16,	NULL);
-	gpio_request(GPIO_FN_LCDD15,	NULL);
-	gpio_request(GPIO_FN_LCDD14,	NULL);
-	gpio_request(GPIO_FN_LCDD13,	NULL);
-	gpio_request(GPIO_FN_LCDD12,	NULL);
-	gpio_request(GPIO_FN_LCDD11,	NULL);
-	gpio_request(GPIO_FN_LCDD10,	NULL);
-	gpio_request(GPIO_FN_LCDD9,	NULL);
-	gpio_request(GPIO_FN_LCDD8,	NULL);
-	gpio_request(GPIO_FN_LCDD7,	NULL);
-	gpio_request(GPIO_FN_LCDD6,	NULL);
-	gpio_request(GPIO_FN_LCDD5,	NULL);
-	gpio_request(GPIO_FN_LCDD4,	NULL);
-	gpio_request(GPIO_FN_LCDD3,	NULL);
-	gpio_request(GPIO_FN_LCDD2,	NULL);
-	gpio_request(GPIO_FN_LCDD1,	NULL);
-	gpio_request(GPIO_FN_LCDD0,	NULL);
-	gpio_request(GPIO_FN_LCDDISP,	NULL);
-	gpio_request(GPIO_FN_LCDDCK,	NULL);
-
-	gpio_request_one(GPIO_PORT222, GPIOF_OUT_INIT_HIGH, NULL); /* LCDCDON */
-	gpio_request_one(GPIO_PORT226, GPIOF_OUT_INIT_HIGH, NULL); /* SC */
+	gpio_request_one(222, GPIOF_OUT_INIT_HIGH, NULL); /* LCDCDON */
+	gpio_request_one(226, GPIOF_OUT_INIT_HIGH, NULL); /* SC */
 
 	/* Touchscreen */
-	gpio_request_one(GPIO_PORT223, GPIOF_IN, NULL); /* IRQ8 */
-
-	/* enable MMCIF */
-	gpio_request(GPIO_FN_MMCCLK0,		NULL);
-	gpio_request(GPIO_FN_MMCCMD0_PU,	NULL);
-	gpio_request(GPIO_FN_MMCD0_0_PU,	NULL);
-	gpio_request(GPIO_FN_MMCD0_1_PU,	NULL);
-	gpio_request(GPIO_FN_MMCD0_2_PU,	NULL);
-	gpio_request(GPIO_FN_MMCD0_3_PU,	NULL);
-	gpio_request(GPIO_FN_MMCD0_4_PU,	NULL);
-	gpio_request(GPIO_FN_MMCD0_5_PU,	NULL);
-	gpio_request(GPIO_FN_MMCD0_6_PU,	NULL);
-	gpio_request(GPIO_FN_MMCD0_7_PU,	NULL);
+	gpio_request_one(223, GPIOF_IN, NULL); /* IRQ8 */
 
 	/* enable SD */
-	gpio_request(GPIO_FN_SDHIWP0,		NULL);
-	gpio_request(GPIO_FN_SDHICD0,		NULL);
-	gpio_request(GPIO_FN_SDHICMD0,		NULL);
-	gpio_request(GPIO_FN_SDHICLK0,		NULL);
-	gpio_request(GPIO_FN_SDHID0_3,		NULL);
-	gpio_request(GPIO_FN_SDHID0_2,		NULL);
-	gpio_request(GPIO_FN_SDHID0_1,		NULL);
-	gpio_request(GPIO_FN_SDHID0_0,		NULL);
 	gpio_request(GPIO_FN_SDHI0_VCCQ_MC0_ON,	NULL);
-	gpio_request_one(GPIO_PORT15, GPIOF_OUT_INIT_HIGH, NULL); /* power */
-
-	/* enable Micro SD */
-	gpio_request(GPIO_FN_SDHID2_0,		NULL);
-	gpio_request(GPIO_FN_SDHID2_1,		NULL);
-	gpio_request(GPIO_FN_SDHID2_2,		NULL);
-	gpio_request(GPIO_FN_SDHID2_3,		NULL);
-	gpio_request(GPIO_FN_SDHICMD2,		NULL);
-	gpio_request(GPIO_FN_SDHICLK2,		NULL);
-	gpio_request_one(GPIO_PORT14, GPIOF_OUT_INIT_HIGH, NULL); /* power */
-
-	/* I2C 3 */
-	gpio_request(GPIO_FN_PORT27_I2C_SCL3, NULL);
-	gpio_request(GPIO_FN_PORT28_I2C_SDA3, NULL);
-
-	/* enable FSI2 port A (ak4648) */
-	gpio_request(GPIO_FN_FSIACK,	NULL);
-	gpio_request(GPIO_FN_FSIAILR,	NULL);
-	gpio_request(GPIO_FN_FSIAIBT,	NULL);
-	gpio_request(GPIO_FN_FSIAISLD,	NULL);
-	gpio_request(GPIO_FN_FSIAOSLD,	NULL);
-
-	/* enable USB */
-	gpio_request(GPIO_FN_VBUS_0,	NULL);
 
 #ifdef CONFIG_CACHE_L2X0
 	/* Early BRESP enable, Shared attribute override enable, 64K*8way */
diff --git a/arch/arm/mach-shmobile/board-lager.c b/arch/arm/mach-shmobile/board-lager.c
new file mode 100644
index 0000000..ea6f9e5
--- /dev/null
+++ b/arch/arm/mach-shmobile/board-lager.c
@@ -0,0 +1,46 @@
+/*
+ * Lager board support
+ *
+ * Copyright (C) 2013  Renesas Solutions Corp.
+ * Copyright (C) 2013  Magnus Damm
+ *
+ * This program is free software; 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/interrupt.h>
+#include <linux/irqchip.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <mach/common.h>
+#include <mach/r8a7790.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+static void __init lager_add_standard_devices(void)
+{
+	r8a7790_clock_init();
+	r8a7790_add_standard_devices();
+}
+
+static const char *lager_boards_compat_dt[] __initdata = {
+	"renesas,lager",
+	NULL,
+};
+
+DT_MACHINE_START(LAGER_DT, "lager")
+	.init_irq	= irqchip_init,
+	.init_time	= shmobile_timer_init,
+	.init_machine	= lager_add_standard_devices,
+	.dt_compat	= lager_boards_compat_dt,
+MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c
index db968a5..fa3407d 100644
--- a/arch/arm/mach-shmobile/board-mackerel.c
+++ b/arch/arm/mach-shmobile/board-mackerel.c
@@ -40,6 +40,7 @@
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/physmap.h>
 #include <linux/mtd/sh_flctl.h>
+#include <linux/pinctrl/machine.h>
 #include <linux/pm_clock.h>
 #include <linux/regulator/fixed.h>
 #include <linux/regulator/machine.h>
@@ -363,7 +364,7 @@ static struct fb_videomode mackerel_lcdc_modes[] = {
 
 static int mackerel_set_brightness(int brightness)
 {
-	gpio_set_value(GPIO_PORT31, brightness);
+	gpio_set_value(31, brightness);
 
 	return 0;
 }
@@ -596,12 +597,14 @@ static int usbhs_get_vbus(struct platform_device *pdev)
 	return usbhs_is_connected(usbhs_get_priv(pdev));
 }
 
-static void usbhs_phy_reset(struct platform_device *pdev)
+static int usbhs_phy_reset(struct platform_device *pdev)
 {
 	struct usbhs_private *priv = usbhs_get_priv(pdev);
 
 	/* init phy */
 	__raw_writew(0x8a0a, priv->usbcrcaddr);
+
+	return 0;
 }
 
 static int usbhs0_get_id(struct platform_device *pdev)
@@ -628,11 +631,13 @@ static int usbhs0_hardware_init(struct platform_device *pdev)
 	return 0;
 }
 
-static void usbhs0_hardware_exit(struct platform_device *pdev)
+static int usbhs0_hardware_exit(struct platform_device *pdev)
 {
 	struct usbhs_private *priv = usbhs_get_priv(pdev);
 
 	cancel_delayed_work_sync(&priv->work);
+
+	return 0;
 }
 
 static struct usbhs_private usbhs0_private = {
@@ -735,7 +740,7 @@ static int usbhs1_hardware_init(struct platform_device *pdev)
 	return 0;
 }
 
-static void usbhs1_hardware_exit(struct platform_device *pdev)
+static int usbhs1_hardware_exit(struct platform_device *pdev)
 {
 	struct usbhs_private *priv = usbhs_get_priv(pdev);
 
@@ -743,6 +748,8 @@ static void usbhs1_hardware_exit(struct platform_device *pdev)
 	__raw_writew(USB_PHY_MODE | USB_PHY_INT_CLR, priv->usbphyaddr);
 
 	free_irq(IRQ8, pdev);
+
+	return 0;
 }
 
 static int usbhs1_get_id(struct platform_device *pdev)
@@ -819,22 +826,22 @@ static struct platform_device usbhs1_device = {
 static struct gpio_led mackerel_leds[] = {
 	{
 		.name		= "led0",
-		.gpio		= GPIO_PORT0,
+		.gpio		= 0,
 		.default_state	= LEDS_GPIO_DEFSTATE_ON,
 	},
 	{
 		.name		= "led1",
-		.gpio		= GPIO_PORT1,
+		.gpio		= 1,
 		.default_state	= LEDS_GPIO_DEFSTATE_ON,
 	},
 	{
 		.name		= "led2",
-		.gpio		= GPIO_PORT2,
+		.gpio		= 2,
 		.default_state	= LEDS_GPIO_DEFSTATE_ON,
 	},
 	{
 		.name		= "led3",
-		.gpio		= GPIO_PORT159,
+		.gpio		= 159,
 		.default_state	= LEDS_GPIO_DEFSTATE_ON,
 	}
 };
@@ -962,40 +969,27 @@ static struct platform_device nand_flash_device = {
 	},
 };
 
-/*
- * The card detect pin of the top SD/MMC slot (CN7) is active low and is
- * connected to GPIO A22 of SH7372 (GPIO_PORT41).
- */
-static int slot_cn7_get_cd(struct platform_device *pdev)
-{
-	return !gpio_get_value(GPIO_PORT41);
-}
-
 /* SDHI0 */
 static struct sh_mobile_sdhi_info sdhi0_info = {
 	.dma_slave_tx	= SHDMA_SLAVE_SDHI0_TX,
 	.dma_slave_rx	= SHDMA_SLAVE_SDHI0_RX,
 	.tmio_flags	= TMIO_MMC_USE_GPIO_CD,
 	.tmio_caps	= MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ,
-	.cd_gpio	= GPIO_PORT172,
+	.cd_gpio	= 172,
 };
 
 static struct resource sdhi0_resources[] = {
-	[0] = {
+	{
 		.name	= "SDHI0",
 		.start	= 0xe6850000,
 		.end	= 0xe68500ff,
 		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= evt2irq(0x0e00) /* SDHI0_SDHI0I0 */,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[2] = {
+	}, {
+		.name	= SH_MOBILE_SDHI_IRQ_SDCARD,
 		.start	= evt2irq(0x0e20) /* SDHI0_SDHI0I1 */,
 		.flags	= IORESOURCE_IRQ,
-	},
-	[3] = {
+	}, {
+		.name	= SH_MOBILE_SDHI_IRQ_SDIO,
 		.start	= evt2irq(0x0e40) /* SDHI0_SDHI0I2 */,
 		.flags	= IORESOURCE_IRQ,
 	},
@@ -1011,36 +1005,30 @@ static struct platform_device sdhi0_device = {
 	},
 };
 
-#if !defined(CONFIG_MMC_SH_MMCIF) && !defined(CONFIG_MMC_SH_MMCIF_MODULE)
+#if !IS_ENABLED(CONFIG_MMC_SH_MMCIF)
 /* SDHI1 */
+
+/* GPIO 41 can trigger IRQ8, but it is used by USBHS1, we have to poll */
 static struct sh_mobile_sdhi_info sdhi1_info = {
 	.dma_slave_tx	= SHDMA_SLAVE_SDHI1_TX,
 	.dma_slave_rx	= SHDMA_SLAVE_SDHI1_RX,
-	.tmio_ocr_mask	= MMC_VDD_165_195,
-	.tmio_flags	= TMIO_MMC_WRPROTECT_DISABLE,
+	.tmio_flags	= TMIO_MMC_WRPROTECT_DISABLE | TMIO_MMC_USE_GPIO_CD,
 	.tmio_caps	= MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ |
 			  MMC_CAP_NEEDS_POLL,
-	.get_cd		= slot_cn7_get_cd,
+	.cd_gpio	= 41,
 };
 
 static struct resource sdhi1_resources[] = {
-	[0] = {
+	{
 		.name	= "SDHI1",
 		.start	= 0xe6860000,
 		.end	= 0xe68600ff,
 		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.name	= SH_MOBILE_SDHI_IRQ_CARD_DETECT,
-		.start	= evt2irq(0x0e80), /* SDHI1_SDHI1I0 */
-		.flags	= IORESOURCE_IRQ,
-	},
-	[2] = {
+	}, {
 		.name	= SH_MOBILE_SDHI_IRQ_SDCARD,
 		.start	= evt2irq(0x0ea0), /* SDHI1_SDHI1I1 */
 		.flags	= IORESOURCE_IRQ,
-	},
-	[3] = {
+	}, {
 		.name	= SH_MOBILE_SDHI_IRQ_SDIO,
 		.start	= evt2irq(0x0ec0), /* SDHI1_SDHI1I2 */
 		.flags	= IORESOURCE_IRQ,
@@ -1058,43 +1046,32 @@ static struct platform_device sdhi1_device = {
 };
 #endif
 
+/* SDHI2 */
+
 /*
  * The card detect pin of the top SD/MMC slot (CN23) is active low and is
- * connected to GPIO SCIFB_SCK of SH7372 (GPIO_PORT162).
+ * connected to GPIO SCIFB_SCK of SH7372 (GPIO 162).
  */
-static int slot_cn23_get_cd(struct platform_device *pdev)
-{
-	return !gpio_get_value(GPIO_PORT162);
-}
-
-/* SDHI2 */
 static struct sh_mobile_sdhi_info sdhi2_info = {
 	.dma_slave_tx	= SHDMA_SLAVE_SDHI2_TX,
 	.dma_slave_rx	= SHDMA_SLAVE_SDHI2_RX,
-	.tmio_flags	= TMIO_MMC_WRPROTECT_DISABLE,
+	.tmio_flags	= TMIO_MMC_WRPROTECT_DISABLE | TMIO_MMC_USE_GPIO_CD,
 	.tmio_caps	= MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ |
 			  MMC_CAP_NEEDS_POLL,
-	.get_cd		= slot_cn23_get_cd,
+	.cd_gpio	= 162,
 };
 
 static struct resource sdhi2_resources[] = {
-	[0] = {
+	{
 		.name	= "SDHI2",
 		.start	= 0xe6870000,
 		.end	= 0xe68700ff,
 		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.name	= SH_MOBILE_SDHI_IRQ_CARD_DETECT,
-		.start	= evt2irq(0x1200), /* SDHI2_SDHI2I0 */
-		.flags	= IORESOURCE_IRQ,
-	},
-	[2] = {
+	}, {
 		.name	= SH_MOBILE_SDHI_IRQ_SDCARD,
 		.start	= evt2irq(0x1220), /* SDHI2_SDHI2I1 */
 		.flags	= IORESOURCE_IRQ,
-	},
-	[3] = {
+	}, {
 		.name	= SH_MOBILE_SDHI_IRQ_SDIO,
 		.start	= evt2irq(0x1240), /* SDHI2_SDHI2I2 */
 		.flags	= IORESOURCE_IRQ,
@@ -1112,6 +1089,7 @@ static struct platform_device sdhi2_device = {
 };
 
 /* SH_MMCIF */
+#if IS_ENABLED(CONFIG_MMC_SH_MMCIF)
 static struct resource sh_mmcif_resources[] = {
 	[0] = {
 		.name	= "MMCIF",
@@ -1133,11 +1111,12 @@ static struct resource sh_mmcif_resources[] = {
 
 static struct sh_mmcif_plat_data sh_mmcif_plat = {
 	.sup_pclk	= 0,
-	.ocr		= MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34,
 	.caps		= MMC_CAP_4_BIT_DATA |
 			  MMC_CAP_8_BIT_DATA |
 			  MMC_CAP_NEEDS_POLL,
-	.get_cd		= slot_cn7_get_cd,
+	.use_cd_gpio	= true,
+	/* card detect pin for SD/MMC slot (CN7) */
+	.cd_gpio	= 41,
 	.slave_id_tx	= SHDMA_SLAVE_MMCIF_TX,
 	.slave_id_rx	= SHDMA_SLAVE_MMCIF_RX,
 };
@@ -1153,7 +1132,7 @@ static struct platform_device sh_mmcif_device = {
 	.num_resources	= ARRAY_SIZE(sh_mmcif_resources),
 	.resource	= sh_mmcif_resources,
 };
-
+#endif
 
 static int mackerel_camera_add(struct soc_camera_device *icd);
 static void mackerel_camera_del(struct soc_camera_device *icd);
@@ -1260,11 +1239,12 @@ static struct platform_device *mackerel_devices[] __initdata = {
 	&fsi_hdmi_device,
 	&nand_flash_device,
 	&sdhi0_device,
-#if !defined(CONFIG_MMC_SH_MMCIF) && !defined(CONFIG_MMC_SH_MMCIF_MODULE)
+#if !IS_ENABLED(CONFIG_MMC_SH_MMCIF)
 	&sdhi1_device,
+#else
+	&sh_mmcif_device,
 #endif
 	&sdhi2_device,
-	&sh_mmcif_device,
 	&ceu_device,
 	&mackerel_camera,
 	&hdmi_device,
@@ -1328,6 +1308,34 @@ static struct i2c_board_info i2c1_devices[] = {
 	},
 };
 
+static const struct pinctrl_map mackerel_pinctrl_map[] = {
+	/* SDHI0 */
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-sh7372",
+				  "sdhi0_data4", "sdhi0"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-sh7372",
+				  "sdhi0_ctrl", "sdhi0"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-sh7372",
+				  "sdhi0_wp", "sdhi0"),
+	/* SDHI1 */
+#if !IS_ENABLED(CONFIG_MMC_SH_MMCIF)
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.1", "pfc-sh7372",
+				  "sdhi1_data4", "sdhi1"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.1", "pfc-sh7372",
+				  "sdhi1_ctrl", "sdhi1"),
+#else
+	/* MMCIF */
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mmcif.0", "pfc-sh7372",
+				  "mmc0_data8_0", "mmc0"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mmcif.0", "pfc-sh7372",
+				  "mmc0_ctrl_0", "mmc0"),
+#endif
+	/* SDHI2 */
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.2", "pfc-sh7372",
+				  "sdhi2_data4", "sdhi2"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.2", "pfc-sh7372",
+				  "sdhi2_ctrl", "sdhi2"),
+};
+
 #define GPIO_PORT9CR	IOMEM(0xE6051009)
 #define GPIO_PORT10CR	IOMEM(0xE605100A)
 #define GPIO_PORT167CR	IOMEM(0xE60520A7)
@@ -1344,10 +1352,11 @@ static void __init mackerel_init(void)
 		{ "A3SP", &usbhs0_device, },
 		{ "A3SP", &usbhs1_device, },
 		{ "A3SP", &nand_flash_device, },
-		{ "A3SP", &sh_mmcif_device, },
 		{ "A3SP", &sdhi0_device, },
-#if !defined(CONFIG_MMC_SH_MMCIF) && !defined(CONFIG_MMC_SH_MMCIF_MODULE)
+#if !IS_ENABLED(CONFIG_MMC_SH_MMCIF)
 		{ "A3SP", &sdhi1_device, },
+#else
+		{ "A3SP", &sh_mmcif_device, },
 #endif
 		{ "A3SP", &sdhi2_device, },
 		{ "A4R", &ceu_device, },
@@ -1364,6 +1373,8 @@ static void __init mackerel_init(void)
 	/* External clock source */
 	clk_set_rate(&sh7372_dv_clki_clk, 27000000);
 
+	pinctrl_register_mappings(mackerel_pinctrl_map,
+				  ARRAY_SIZE(mackerel_pinctrl_map));
 	sh7372_pinmux_init();
 
 	/* enable SCIFA0 */
@@ -1403,9 +1414,9 @@ static void __init mackerel_init(void)
 	gpio_request(GPIO_FN_LCDDCK,   NULL);
 
 	/* backlight, off by default */
-	gpio_request_one(GPIO_PORT31, GPIOF_OUT_INIT_LOW, NULL);
+	gpio_request_one(31, GPIOF_OUT_INIT_LOW, NULL);
 
-	gpio_request_one(GPIO_PORT151, GPIOF_OUT_INIT_HIGH, NULL); /* LCDDON */
+	gpio_request_one(151, GPIOF_OUT_INIT_HIGH, NULL); /* LCDDON */
 
 	/* USBHS0 */
 	gpio_request(GPIO_FN_VBUS0_0, NULL);
@@ -1421,10 +1432,10 @@ static void __init mackerel_init(void)
 	gpio_request(GPIO_FN_FSIAILR,	NULL);
 	gpio_request(GPIO_FN_FSIAISLD,	NULL);
 	gpio_request(GPIO_FN_FSIAOSLD,	NULL);
-	gpio_request_one(GPIO_PORT161, GPIOF_OUT_INIT_LOW, NULL); /* slave */
+	gpio_request_one(161, GPIOF_OUT_INIT_LOW, NULL); /* slave */
 
-	gpio_request(GPIO_PORT9,  NULL);
-	gpio_request(GPIO_PORT10, NULL);
+	gpio_request(9,  NULL);
+	gpio_request(10, NULL);
 	gpio_direction_none(GPIO_PORT9CR);  /* FSIAOBT needs no direction */
 	gpio_direction_none(GPIO_PORT10CR); /* FSIAOLR needs no direction */
 
@@ -1453,53 +1464,9 @@ static void __init mackerel_init(void)
 	gpio_request(GPIO_FN_IRQ21,	NULL);
 	irq_set_irq_type(IRQ21, IRQ_TYPE_LEVEL_HIGH);
 
-	/* enable SDHI0 */
-	gpio_request(GPIO_FN_SDHIWP0, NULL);
-	gpio_request(GPIO_FN_SDHICMD0, NULL);
-	gpio_request(GPIO_FN_SDHICLK0, NULL);
-	gpio_request(GPIO_FN_SDHID0_3, NULL);
-	gpio_request(GPIO_FN_SDHID0_2, NULL);
-	gpio_request(GPIO_FN_SDHID0_1, NULL);
-	gpio_request(GPIO_FN_SDHID0_0, NULL);
-
 	/* SDHI0 PORT172 card-detect IRQ26 */
 	gpio_request(GPIO_FN_IRQ26_172, NULL);
 
-#if !defined(CONFIG_MMC_SH_MMCIF) && !defined(CONFIG_MMC_SH_MMCIF_MODULE)
-	/* enable SDHI1 */
-	gpio_request(GPIO_FN_SDHICMD1, NULL);
-	gpio_request(GPIO_FN_SDHICLK1, NULL);
-	gpio_request(GPIO_FN_SDHID1_3, NULL);
-	gpio_request(GPIO_FN_SDHID1_2, NULL);
-	gpio_request(GPIO_FN_SDHID1_1, NULL);
-	gpio_request(GPIO_FN_SDHID1_0, NULL);
-#endif
-	/* card detect pin for MMC slot (CN7) */
-	gpio_request_one(GPIO_PORT41, GPIOF_IN, NULL);
-
-	/* enable SDHI2 */
-	gpio_request(GPIO_FN_SDHICMD2, NULL);
-	gpio_request(GPIO_FN_SDHICLK2, NULL);
-	gpio_request(GPIO_FN_SDHID2_3, NULL);
-	gpio_request(GPIO_FN_SDHID2_2, NULL);
-	gpio_request(GPIO_FN_SDHID2_1, NULL);
-	gpio_request(GPIO_FN_SDHID2_0, NULL);
-
-	/* card detect pin for microSD slot (CN23) */
-	gpio_request_one(GPIO_PORT162, GPIOF_IN, NULL);
-
-	/* MMCIF */
-	gpio_request(GPIO_FN_MMCD0_0, NULL);
-	gpio_request(GPIO_FN_MMCD0_1, NULL);
-	gpio_request(GPIO_FN_MMCD0_2, NULL);
-	gpio_request(GPIO_FN_MMCD0_3, NULL);
-	gpio_request(GPIO_FN_MMCD0_4, NULL);
-	gpio_request(GPIO_FN_MMCD0_5, NULL);
-	gpio_request(GPIO_FN_MMCD0_6, NULL);
-	gpio_request(GPIO_FN_MMCD0_7, NULL);
-	gpio_request(GPIO_FN_MMCCMD0, NULL);
-	gpio_request(GPIO_FN_MMCCLK0, NULL);
-
 	/* FLCTL */
 	gpio_request(GPIO_FN_D0_NAF0, NULL);
 	gpio_request(GPIO_FN_D1_NAF1, NULL);
diff --git a/arch/arm/mach-shmobile/board-marzen-reference.c b/arch/arm/mach-shmobile/board-marzen-reference.c
new file mode 100644
index 0000000..480d882
--- /dev/null
+++ b/arch/arm/mach-shmobile/board-marzen-reference.c
@@ -0,0 +1,75 @@
+/*
+ * marzen board support - Reference DT implementation
+ *
+ * Copyright (C) 2011  Renesas Solutions Corp.
+ * Copyright (C) 2011  Magnus Damm
+ * Copyright (C) 2013  Simon Horman
+ *
+ * This program is free software; 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/pinctrl/machine.h>
+#include <mach/r8a7779.h>
+#include <mach/common.h>
+#include <mach/irqs.h>
+#include <asm/irq.h>
+#include <asm/mach/arch.h>
+
+static const struct pinctrl_map marzen_pinctrl_map[] = {
+	/* SCIF2 (CN18: DEBUG0) */
+	PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.2", "pfc-r8a7779",
+				  "scif2_data_c", "scif2"),
+	/* SCIF4 (CN19: DEBUG1) */
+	PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.4", "pfc-r8a7779",
+				  "scif4_data", "scif4"),
+	/* SDHI0 */
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7779",
+				  "sdhi0_data4", "sdhi0"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7779",
+				  "sdhi0_ctrl", "sdhi0"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7779",
+				  "sdhi0_cd", "sdhi0"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7779",
+				  "sdhi0_wp", "sdhi0"),
+	/* SMSC */
+	PIN_MAP_MUX_GROUP_DEFAULT("smsc911x", "pfc-r8a7779",
+				  "intc_irq1_b", "intc"),
+	PIN_MAP_MUX_GROUP_DEFAULT("smsc911x", "pfc-r8a7779",
+				  "lbsc_ex_cs0", "lbsc"),
+};
+
+static void __init marzen_init(void)
+{
+	pinctrl_register_mappings(marzen_pinctrl_map,
+				  ARRAY_SIZE(marzen_pinctrl_map));
+	r8a7779_pinmux_init();
+
+	r8a7779_add_standard_devices_dt();
+}
+
+static const char *marzen_boards_compat_dt[] __initdata = {
+	"renesas,marzen-reference",
+	NULL,
+};
+
+DT_MACHINE_START(MARZEN, "marzen")
+	.smp		= smp_ops(r8a7779_smp_ops),
+	.map_io		= r8a7779_map_io,
+	.init_early	= r8a7779_init_delay,
+	.nr_irqs	= NR_IRQS_LEGACY,
+	.init_irq	= r8a7779_init_irq_dt,
+	.init_machine	= marzen_init,
+	.init_time	= shmobile_timer_init,
+	.dt_compat	= marzen_boards_compat_dt,
+MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-marzen.c b/arch/arm/mach-shmobile/board-marzen.c
index fec49eb..9105285 100644
--- a/arch/arm/mach-shmobile/board-marzen.c
+++ b/arch/arm/mach-shmobile/board-marzen.c
@@ -25,8 +25,9 @@
 #include <linux/platform_device.h>
 #include <linux/delay.h>
 #include <linux/io.h>
-#include <linux/gpio.h>
+#include <linux/leds.h>
 #include <linux/dma-mapping.h>
+#include <linux/pinctrl/machine.h>
 #include <linux/regulator/fixed.h>
 #include <linux/regulator/machine.h>
 #include <linux/smsc911x.h>
@@ -67,7 +68,7 @@ static struct resource smsc911x_resources[] = {
 		.flags		= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start		= gic_spi(28), /* IRQ 1 */
+		.start		= gic_iid(0x3c), /* IRQ 1 */
 		.flags		= IORESOURCE_IRQ,
 	},
 };
@@ -97,7 +98,7 @@ static struct resource sdhi0_resources[] = {
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= gic_spi(104),
+		.start	= gic_iid(0x88),
 		.flags	= IORESOURCE_IRQ,
 	},
 };
@@ -168,12 +169,43 @@ static struct platform_device usb_phy_device = {
 	.num_resources	= ARRAY_SIZE(usb_phy_resources),
 };
 
+/* LEDS */
+static struct gpio_led marzen_leds[] = {
+	{
+		.name		= "led2",
+		.gpio		= 157,
+		.default_state	= LEDS_GPIO_DEFSTATE_ON,
+	}, {
+		.name		= "led3",
+		.gpio		= 158,
+		.default_state	= LEDS_GPIO_DEFSTATE_ON,
+	}, {
+		.name		= "led4",
+		.gpio		= 159,
+		.default_state	= LEDS_GPIO_DEFSTATE_ON,
+	},
+};
+
+static struct gpio_led_platform_data marzen_leds_pdata = {
+	.leds		= marzen_leds,
+	.num_leds	= ARRAY_SIZE(marzen_leds),
+};
+
+static struct platform_device leds_device = {
+	.name	= "leds-gpio",
+	.id	= 0,
+	.dev	= {
+		.platform_data  = &marzen_leds_pdata,
+	},
+};
+
 static struct platform_device *marzen_devices[] __initdata = {
 	&eth_device,
 	&sdhi0_device,
 	&thermal_device,
 	&hspi_device,
 	&usb_phy_device,
+	&leds_device,
 };
 
 /* USB */
@@ -215,7 +247,7 @@ static struct resource ehci0_resources[] = {
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= gic_spi(44),
+		.start	= gic_iid(0x4c),
 		.flags	= IORESOURCE_IRQ,
 	},
 };
@@ -239,7 +271,7 @@ static struct resource ehci1_resources[] = {
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= gic_spi(45),
+		.start	= gic_iid(0x4d),
 		.flags	= IORESOURCE_IRQ,
 	},
 };
@@ -269,7 +301,7 @@ static struct resource ohci0_resources[] = {
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= gic_spi(44),
+		.start	= gic_iid(0x4c),
 		.flags	= IORESOURCE_IRQ,
 	},
 };
@@ -293,7 +325,7 @@ static struct resource ohci1_resources[] = {
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= gic_spi(45),
+		.start	= gic_iid(0x4d),
 		.flags	= IORESOURCE_IRQ,
 	},
 };
@@ -327,6 +359,41 @@ void __init marzen_init_late(void)
 			     ARRAY_SIZE(marzen_late_devices));
 }
 
+static const struct pinctrl_map marzen_pinctrl_map[] = {
+	/* HSPI0 */
+	PIN_MAP_MUX_GROUP_DEFAULT("sh-hspi.0", "pfc-r8a7779",
+				  "hspi0", "hspi0"),
+	/* SCIF2 (CN18: DEBUG0) */
+	PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.2", "pfc-r8a7779",
+				  "scif2_data_c", "scif2"),
+	/* SCIF4 (CN19: DEBUG1) */
+	PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.4", "pfc-r8a7779",
+				  "scif4_data", "scif4"),
+	/* SDHI0 */
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7779",
+				  "sdhi0_data4", "sdhi0"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7779",
+				  "sdhi0_ctrl", "sdhi0"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7779",
+				  "sdhi0_cd", "sdhi0"),
+	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7779",
+				  "sdhi0_wp", "sdhi0"),
+	/* SMSC */
+	PIN_MAP_MUX_GROUP_DEFAULT("smsc911x", "pfc-r8a7779",
+				  "intc_irq1_b", "intc"),
+	PIN_MAP_MUX_GROUP_DEFAULT("smsc911x", "pfc-r8a7779",
+				  "lbsc_ex_cs0", "lbsc"),
+	/* USB0 */
+	PIN_MAP_MUX_GROUP_DEFAULT("ehci-platform.0", "pfc-r8a7779",
+				  "usb0", "usb0"),
+	/* USB1 */
+	PIN_MAP_MUX_GROUP_DEFAULT("ehci-platform.0", "pfc-r8a7779",
+				  "usb1", "usb1"),
+	/* USB2 */
+	PIN_MAP_MUX_GROUP_DEFAULT("ehci-platform.1", "pfc-r8a7779",
+				  "usb2", "usb2"),
+};
+
 static void __init marzen_init(void)
 {
 	regulator_register_always_on(0, "fixed-3.3V", fixed3v3_power_consumers,
@@ -334,44 +401,10 @@ static void __init marzen_init(void)
 	regulator_register_fixed(1, dummy_supplies,
 				ARRAY_SIZE(dummy_supplies));
 
+	pinctrl_register_mappings(marzen_pinctrl_map,
+				  ARRAY_SIZE(marzen_pinctrl_map));
 	r8a7779_pinmux_init();
 
-	/* SCIF2 (CN18: DEBUG0) */
-	gpio_request(GPIO_FN_TX2_C, NULL);
-	gpio_request(GPIO_FN_RX2_C, NULL);
-
-	/* SCIF4 (CN19: DEBUG1) */
-	gpio_request(GPIO_FN_TX4, NULL);
-	gpio_request(GPIO_FN_RX4, NULL);
-
-	/* LAN89218 */
-	gpio_request(GPIO_FN_EX_CS0, NULL); /* nCS */
-	gpio_request(GPIO_FN_IRQ1_B, NULL); /* IRQ + PME */
-
-	/* SD0 (CN20) */
-	gpio_request(GPIO_FN_SD0_CLK, NULL);
-	gpio_request(GPIO_FN_SD0_CMD, NULL);
-	gpio_request(GPIO_FN_SD0_DAT0, NULL);
-	gpio_request(GPIO_FN_SD0_DAT1, NULL);
-	gpio_request(GPIO_FN_SD0_DAT2, NULL);
-	gpio_request(GPIO_FN_SD0_DAT3, NULL);
-	gpio_request(GPIO_FN_SD0_CD, NULL);
-	gpio_request(GPIO_FN_SD0_WP, NULL);
-
-	/* HSPI 0 */
-	gpio_request(GPIO_FN_HSPI_CLK0,	NULL);
-	gpio_request(GPIO_FN_HSPI_CS0,	NULL);
-	gpio_request(GPIO_FN_HSPI_TX0,	NULL);
-	gpio_request(GPIO_FN_HSPI_RX0,	NULL);
-
-	/* USB (CN21) */
-	gpio_request(GPIO_FN_USB_OVC0, NULL);
-	gpio_request(GPIO_FN_USB_OVC1, NULL);
-	gpio_request(GPIO_FN_USB_OVC2, NULL);
-
-	/* USB (CN22) */
-	gpio_request(GPIO_FN_USB_PENC2, NULL);
-
 	r8a7779_add_standard_devices();
 	platform_add_devices(marzen_devices, ARRAY_SIZE(marzen_devices));
 }
diff --git a/arch/arm/mach-shmobile/clock-r8a73a4.c b/arch/arm/mach-shmobile/clock-r8a73a4.c
new file mode 100644
index 0000000..e710c00
--- /dev/null
+++ b/arch/arm/mach-shmobile/clock-r8a73a4.c
@@ -0,0 +1,115 @@
+/*
+ * r8a73a4 clock framework support
+ *
+ * Copyright (C) 2013  Renesas Solutions Corp.
+ * Copyright (C) 2013  Magnus Damm
+ *
+ * This program is free software; 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/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/sh_clk.h>
+#include <linux/clkdev.h>
+#include <mach/common.h>
+
+#define CPG_BASE 0xe6150000
+#define CPG_LEN 0x270
+
+#define MPCKCR 0xe6150080
+#define SMSTPCR2 0xe6150138
+#define SMSTPCR5 0xe6150144
+
+static struct clk_mapping cpg_mapping = {
+	.phys   = CPG_BASE,
+	.len    = CPG_LEN,
+};
+
+static struct clk extalr_clk = {
+	.rate	= 32768,
+	.mapping	= &cpg_mapping,
+};
+
+static struct clk extal1_clk = {
+	.rate	= 26000000,
+	.mapping	= &cpg_mapping,
+};
+
+static struct clk extal2_clk = {
+	.rate	= 48000000,
+	.mapping	= &cpg_mapping,
+};
+
+static struct clk *main_clks[] = {
+	&extalr_clk,
+	&extal1_clk,
+	&extal2_clk,
+};
+
+enum {
+	MSTP217, MSTP216, MSTP207, MSTP206, MSTP204, MSTP203,
+	MSTP522,
+	MSTP_NR
+};
+
+static struct clk mstp_clks[MSTP_NR] = {
+	[MSTP204] = SH_CLK_MSTP32(&extal2_clk, SMSTPCR2, 4, 0), /* SCIFA0 */
+	[MSTP203] = SH_CLK_MSTP32(&extal2_clk, SMSTPCR2, 3, 0), /* SCIFA1 */
+	[MSTP206] = SH_CLK_MSTP32(&extal2_clk, SMSTPCR2, 6, 0), /* SCIFB0 */
+	[MSTP207] = SH_CLK_MSTP32(&extal2_clk, SMSTPCR2, 7, 0), /* SCIFB1 */
+	[MSTP216] = SH_CLK_MSTP32(&extal2_clk, SMSTPCR2, 16, 0), /* SCIFB2 */
+	[MSTP217] = SH_CLK_MSTP32(&extal2_clk, SMSTPCR2, 17, 0), /* SCIFB3 */
+	[MSTP522] = SH_CLK_MSTP32(&extal2_clk, SMSTPCR5, 22, 0), /* Thermal */
+};
+
+static struct clk_lookup lookups[] = {
+	CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP204]),
+	CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP203]),
+	CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP206]),
+	CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP207]),
+	CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP216]),
+	CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP217]),
+	CLKDEV_DEV_ID("rcar_thermal", &mstp_clks[MSTP522]),
+
+	/* for DT */
+	CLKDEV_DEV_ID("e61f0000.thermal", &mstp_clks[MSTP522]),
+};
+
+void __init r8a73a4_clock_init(void)
+{
+	void __iomem *cpg_base, *reg;
+	int k, ret = 0;
+
+	/* fix MPCLK to EXTAL2 for now.
+	 * this is needed until more detailed clock topology is supported
+	 */
+	cpg_base = ioremap_nocache(CPG_BASE, CPG_LEN);
+	BUG_ON(!cpg_base);
+	reg = cpg_base + (MPCKCR - CPG_BASE);
+	iowrite32(ioread32(reg) | 1 << 7 | 0x0c, reg); /* set CKSEL */
+	iounmap(cpg_base);
+
+	for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
+		ret = clk_register(main_clks[k]);
+
+	if (!ret)
+		ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);
+
+	clkdev_add_table(lookups, ARRAY_SIZE(lookups));
+
+	if (!ret)
+		shmobile_clk_init();
+	else
+		panic("failed to setup r8a73a4 clocks\n");
+}
diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c
index 19ce885..c0d39aa 100644
--- a/arch/arm/mach-shmobile/clock-r8a7740.c
+++ b/arch/arm/mach-shmobile/clock-r8a7740.c
@@ -22,6 +22,7 @@
 #include <linux/io.h>
 #include <linux/sh_clk.h>
 #include <linux/clkdev.h>
+#include <mach/clock.h>
 #include <mach/common.h>
 #include <mach/r8a7740.h>
 
@@ -97,42 +98,13 @@ static struct clk dv_clk = {
 	.rate	= 27000000,
 };
 
-static unsigned long div_recalc(struct clk *clk)
-{
-	return clk->parent->rate / (int)(clk->priv);
-}
-
-static struct sh_clk_ops div_clk_ops = {
-	.recalc	= div_recalc,
-};
-
-/* extal1 / 2 */
-static struct clk extal1_div2_clk = {
-	.ops	= &div_clk_ops,
-	.priv	= (void *)2,
-	.parent	= &extal1_clk,
-};
-
-/* extal1 / 1024 */
-static struct clk extal1_div1024_clk = {
-	.ops	= &div_clk_ops,
-	.priv	= (void *)1024,
-	.parent	= &extal1_clk,
-};
-
-/* extal1 / 2 / 1024 */
-static struct clk extal1_div2048_clk = {
-	.ops	= &div_clk_ops,
-	.priv	= (void *)1024,
-	.parent	= &extal1_div2_clk,
-};
+SH_CLK_RATIO(div2,	1, 2);
+SH_CLK_RATIO(div1k,	1, 1024);
 
-/* extal2 / 2 */
-static struct clk extal2_div2_clk = {
-	.ops	= &div_clk_ops,
-	.priv	= (void *)2,
-	.parent	= &extal2_clk,
-};
+SH_FIXED_RATIO_CLK(extal1_div2_clk,	extal1_clk,		div2);
+SH_FIXED_RATIO_CLK(extal1_div1024_clk,	extal1_clk,		div1k);
+SH_FIXED_RATIO_CLK(extal1_div2048_clk,	extal1_div2_clk,	div1k);
+SH_FIXED_RATIO_CLK(extal2_div2_clk,	extal2_clk,		div2);
 
 static struct sh_clk_ops followparent_clk_ops = {
 	.recalc	= followparent_recalc,
@@ -143,11 +115,7 @@ static struct clk system_clk = {
 	.ops	= &followparent_clk_ops,
 };
 
-static struct clk system_div2_clk = {
-	.ops	= &div_clk_ops,
-	.priv	= (void *)2,
-	.parent	= &system_clk,
-};
+SH_FIXED_RATIO_CLK(system_div2_clk, system_clk,	div2);
 
 /* r_clk */
 static struct clk r_clk = {
@@ -184,11 +152,7 @@ static struct clk pllc1_clk = {
 };
 
 /* PLLC1 / 2 */
-static struct clk pllc1_div2_clk = {
-	.ops		= &div_clk_ops,
-	.priv		= (void *)2,
-	.parent		= &pllc1_clk,
-};
+SH_FIXED_RATIO_CLK(pllc1_div2_clk, pllc1_clk, div2);
 
 /* USB clock */
 /*
@@ -323,6 +287,7 @@ struct clk *main_clks[] = {
 	&fsibck_clk,
 };
 
+/* DIV4 clocks */
 static void div4_kick(struct clk *clk)
 {
 	unsigned long value;
@@ -346,6 +311,26 @@ static struct clk_div4_table div4_table = {
 	.kick = div4_kick,
 };
 
+enum {
+	DIV4_I, DIV4_ZG, DIV4_B, DIV4_M1, DIV4_HP,
+	DIV4_HPP, DIV4_USBP, DIV4_S, DIV4_ZB, DIV4_M3, DIV4_CP,
+	DIV4_NR
+};
+
+struct clk div4_clks[DIV4_NR] = {
+	[DIV4_I]	= SH_CLK_DIV4(&pllc1_clk, FRQCRA, 20, 0x6fff, CLK_ENABLE_ON_INIT),
+	[DIV4_ZG]	= SH_CLK_DIV4(&pllc1_clk, FRQCRA, 16, 0x6fff, CLK_ENABLE_ON_INIT),
+	[DIV4_B]	= SH_CLK_DIV4(&pllc1_clk, FRQCRA,  8, 0x6fff, CLK_ENABLE_ON_INIT),
+	[DIV4_M1]	= SH_CLK_DIV4(&pllc1_clk, FRQCRA,  4, 0x6fff, CLK_ENABLE_ON_INIT),
+	[DIV4_HP]	= SH_CLK_DIV4(&pllc1_clk, FRQCRB,  4, 0x6fff, 0),
+	[DIV4_HPP]	= SH_CLK_DIV4(&pllc1_clk, FRQCRC, 20, 0x6fff, 0),
+	[DIV4_USBP]	= SH_CLK_DIV4(&pllc1_clk, FRQCRC, 16, 0x6fff, 0),
+	[DIV4_S]	= SH_CLK_DIV4(&pllc1_clk, FRQCRC, 12, 0x6fff, 0),
+	[DIV4_ZB]	= SH_CLK_DIV4(&pllc1_clk, FRQCRC,  8, 0x6fff, 0),
+	[DIV4_M3]	= SH_CLK_DIV4(&pllc1_clk, FRQCRC,  4, 0x6fff, 0),
+	[DIV4_CP]	= SH_CLK_DIV4(&pllc1_clk, FRQCRC,  0, 0x6fff, 0),
+};
+
 /* DIV6 reparent */
 enum {
 	DIV6_HDMI,
@@ -391,6 +376,16 @@ static struct clk div6_reparent_clks[DIV6_REPARENT_NR] = {
 				      fsib_parents, ARRAY_SIZE(fsib_parents), 6, 2),
 };
 
+/* DIV6 clocks */
+enum {
+	DIV6_SUB,
+	DIV6_NR
+};
+
+static struct clk div6_clks[DIV6_NR] = {
+	[DIV6_SUB]	= SH_CLK_DIV6(&pllc1_div2_clk, SUBCKCR, 0),
+};
+
 /* HDMI1/2 clock */
 static unsigned long hdmi12_recalc(struct clk *clk)
 {
@@ -456,35 +451,6 @@ static struct clk fsidivs[] = {
 
 /* MSTP */
 enum {
-	DIV4_I, DIV4_ZG, DIV4_B, DIV4_M1, DIV4_HP,
-	DIV4_HPP, DIV4_USBP, DIV4_S, DIV4_ZB, DIV4_M3, DIV4_CP,
-	DIV4_NR
-};
-
-struct clk div4_clks[DIV4_NR] = {
-	[DIV4_I]	= SH_CLK_DIV4(&pllc1_clk, FRQCRA, 20, 0x6fff, CLK_ENABLE_ON_INIT),
-	[DIV4_ZG]	= SH_CLK_DIV4(&pllc1_clk, FRQCRA, 16, 0x6fff, CLK_ENABLE_ON_INIT),
-	[DIV4_B]	= SH_CLK_DIV4(&pllc1_clk, FRQCRA,  8, 0x6fff, CLK_ENABLE_ON_INIT),
-	[DIV4_M1]	= SH_CLK_DIV4(&pllc1_clk, FRQCRA,  4, 0x6fff, CLK_ENABLE_ON_INIT),
-	[DIV4_HP]	= SH_CLK_DIV4(&pllc1_clk, FRQCRB,  4, 0x6fff, 0),
-	[DIV4_HPP]	= SH_CLK_DIV4(&pllc1_clk, FRQCRC, 20, 0x6fff, 0),
-	[DIV4_USBP]	= SH_CLK_DIV4(&pllc1_clk, FRQCRC, 16, 0x6fff, 0),
-	[DIV4_S]	= SH_CLK_DIV4(&pllc1_clk, FRQCRC, 12, 0x6fff, 0),
-	[DIV4_ZB]	= SH_CLK_DIV4(&pllc1_clk, FRQCRC,  8, 0x6fff, 0),
-	[DIV4_M3]	= SH_CLK_DIV4(&pllc1_clk, FRQCRC,  4, 0x6fff, 0),
-	[DIV4_CP]	= SH_CLK_DIV4(&pllc1_clk, FRQCRC,  0, 0x6fff, 0),
-};
-
-enum {
-	DIV6_SUB,
-	DIV6_NR
-};
-
-static struct clk div6_clks[DIV6_NR] = {
-	[DIV6_SUB]	= SH_CLK_DIV6(&pllc1_div2_clk, SUBCKCR, 0),
-};
-
-enum {
 	MSTP128, MSTP127, MSTP125,
 	MSTP116, MSTP111, MSTP100, MSTP117,
 
@@ -593,29 +559,42 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_DEV_ID("sh_mobile_ceu.1",	&mstp_clks[MSTP128]),
 
 	CLKDEV_DEV_ID("sh-sci.4",		&mstp_clks[MSTP200]),
+	CLKDEV_DEV_ID("e6c80000.sci",		&mstp_clks[MSTP200]),
 	CLKDEV_DEV_ID("sh-sci.3",		&mstp_clks[MSTP201]),
+	CLKDEV_DEV_ID("e6c70000.sci",		&mstp_clks[MSTP201]),
 	CLKDEV_DEV_ID("sh-sci.2",		&mstp_clks[MSTP202]),
+	CLKDEV_DEV_ID("e6c60000.sci",		&mstp_clks[MSTP202]),
 	CLKDEV_DEV_ID("sh-sci.1",		&mstp_clks[MSTP203]),
+	CLKDEV_DEV_ID("e6c50000.sci",		&mstp_clks[MSTP203]),
 	CLKDEV_DEV_ID("sh-sci.0",		&mstp_clks[MSTP204]),
+	CLKDEV_DEV_ID("e6c40000.sci",		&mstp_clks[MSTP204]),
 	CLKDEV_DEV_ID("sh-sci.8",		&mstp_clks[MSTP206]),
+	CLKDEV_DEV_ID("e6c30000.sci",		&mstp_clks[MSTP206]),
 	CLKDEV_DEV_ID("sh-sci.5",		&mstp_clks[MSTP207]),
+	CLKDEV_DEV_ID("e6cb0000.sci",		&mstp_clks[MSTP207]),
 	CLKDEV_DEV_ID("sh-dma-engine.3",	&mstp_clks[MSTP214]),
 	CLKDEV_DEV_ID("sh-dma-engine.2",	&mstp_clks[MSTP216]),
 	CLKDEV_DEV_ID("sh-dma-engine.1",	&mstp_clks[MSTP217]),
 	CLKDEV_DEV_ID("sh-dma-engine.0",	&mstp_clks[MSTP218]),
 	CLKDEV_DEV_ID("sh-sci.7",		&mstp_clks[MSTP222]),
+	CLKDEV_DEV_ID("e6cd0000.sci",		&mstp_clks[MSTP222]),
 	CLKDEV_DEV_ID("sh-sci.6",		&mstp_clks[MSTP230]),
+	CLKDEV_DEV_ID("e6cc0000.sci",		&mstp_clks[MSTP230]),
 
 	CLKDEV_DEV_ID("sh_cmt.10",		&mstp_clks[MSTP329]),
 	CLKDEV_DEV_ID("sh_fsi2",		&mstp_clks[MSTP328]),
 	CLKDEV_DEV_ID("i2c-sh_mobile.1",	&mstp_clks[MSTP323]),
 	CLKDEV_DEV_ID("renesas_usbhs",		&mstp_clks[MSTP320]),
 	CLKDEV_DEV_ID("sh_mobile_sdhi.0",	&mstp_clks[MSTP314]),
+	CLKDEV_DEV_ID("e6850000.sdhi",          &mstp_clks[MSTP314]),
 	CLKDEV_DEV_ID("sh_mobile_sdhi.1",	&mstp_clks[MSTP313]),
+	CLKDEV_DEV_ID("e6860000.sdhi",          &mstp_clks[MSTP313]),
 	CLKDEV_DEV_ID("sh_mmcif",		&mstp_clks[MSTP312]),
+	CLKDEV_DEV_ID("e6bd0000.mmcif",         &mstp_clks[MSTP312]),
 	CLKDEV_DEV_ID("sh-eth",			&mstp_clks[MSTP309]),
 
 	CLKDEV_DEV_ID("sh_mobile_sdhi.2",	&mstp_clks[MSTP415]),
+	CLKDEV_DEV_ID("e6870000.sdhi",          &mstp_clks[MSTP415]),
 
 	/* ICK */
 	CLKDEV_ICK_ID("host",	"renesas_usbhs",	&mstp_clks[MSTP416]),
diff --git a/arch/arm/mach-shmobile/clock-r8a7778.c b/arch/arm/mach-shmobile/clock-r8a7778.c
new file mode 100644
index 0000000..f1277f4
--- /dev/null
+++ b/arch/arm/mach-shmobile/clock-r8a7778.c
@@ -0,0 +1,104 @@
+/*
+ * r8a7778 clock framework support
+ *
+ * Copyright (C) 2013  Renesas Solutions Corp.
+ * Copyright (C) 2013  Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+ *
+ * based on r8a7779
+ *
+ * Copyright (C) 2011  Renesas Solutions Corp.
+ * Copyright (C) 2011  Magnus Damm
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either 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/io.h>
+#include <linux/sh_clk.h>
+#include <linux/clkdev.h>
+#include <mach/common.h>
+
+#define MSTPCR0		IOMEM(0xffc80030)
+#define MSTPCR1		IOMEM(0xffc80034)
+#define MSTPCR3		IOMEM(0xffc8003c)
+#define MSTPSR1		IOMEM(0xffc80044)
+#define MSTPSR4		IOMEM(0xffc80048)
+#define MSTPSR6		IOMEM(0xffc8004c)
+#define MSTPCR4		IOMEM(0xffc80050)
+#define MSTPCR5		IOMEM(0xffc80054)
+#define MSTPCR6		IOMEM(0xffc80058)
+
+/* ioremap() through clock mapping mandatory to avoid
+ * collision with ARM coherent DMA virtual memory range.
+ */
+
+static struct clk_mapping cpg_mapping = {
+	.phys	= 0xffc80000,
+	.len	= 0x80,
+};
+
+static struct clk clkp = {
+	.rate   = 62500000, /* FIXME: shortcut */
+	.flags  = CLK_ENABLE_ON_INIT,
+	.mapping = &cpg_mapping,
+};
+
+static struct clk *main_clks[] = {
+	&clkp,
+};
+
+enum {
+	MSTP026, MSTP025, MSTP024, MSTP023, MSTP022, MSTP021,
+	MSTP016, MSTP015,
+	MSTP_NR };
+
+static struct clk mstp_clks[MSTP_NR] = {
+	[MSTP026] = SH_CLK_MSTP32(&clkp, MSTPCR0, 26, 0), /* SCIF0 */
+	[MSTP025] = SH_CLK_MSTP32(&clkp, MSTPCR0, 25, 0), /* SCIF1 */
+	[MSTP024] = SH_CLK_MSTP32(&clkp, MSTPCR0, 24, 0), /* SCIF2 */
+	[MSTP023] = SH_CLK_MSTP32(&clkp, MSTPCR0, 23, 0), /* SCIF3 */
+	[MSTP022] = SH_CLK_MSTP32(&clkp, MSTPCR0, 22, 0), /* SCIF4 */
+	[MSTP021] = SH_CLK_MSTP32(&clkp, MSTPCR0, 21, 0), /* SCIF5 */
+	[MSTP016] = SH_CLK_MSTP32(&clkp, MSTPCR0, 16, 0), /* TMU0 */
+	[MSTP015] = SH_CLK_MSTP32(&clkp, MSTPCR0, 15, 0), /* TMU1 */
+};
+
+static struct clk_lookup lookups[] = {
+	/* MSTP32 clocks */
+	CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP026]), /* SCIF0 */
+	CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP025]), /* SCIF1 */
+	CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP024]), /* SCIF2 */
+	CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP023]), /* SCIF3 */
+	CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP022]), /* SCIF4 */
+	CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP021]), /* SCIF6 */
+	CLKDEV_DEV_ID("sh_tmu.0", &mstp_clks[MSTP016]), /* TMU00 */
+	CLKDEV_DEV_ID("sh_tmu.1", &mstp_clks[MSTP015]), /* TMU01 */
+};
+
+void __init r8a7778_clock_init(void)
+{
+	int k, ret = 0;
+
+	for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
+		ret = clk_register(main_clks[k]);
+
+	if (!ret)
+		ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);
+
+	clkdev_add_table(lookups, ARRAY_SIZE(lookups));
+
+	if (!ret)
+		shmobile_clk_init();
+	else
+		panic("failed to setup r8a7778 clocks\n");
+}
diff --git a/arch/arm/mach-shmobile/clock-r8a7779.c b/arch/arm/mach-shmobile/clock-r8a7779.c
index 1db3653..5436b51 100644
--- a/arch/arm/mach-shmobile/clock-r8a7779.c
+++ b/arch/arm/mach-shmobile/clock-r8a7779.c
@@ -17,13 +17,36 @@
  * 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/bitops.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/io.h>
 #include <linux/sh_clk.h>
 #include <linux/clkdev.h>
+#include <mach/clock.h>
 #include <mach/common.h>
 
+/*
+ *		MD1 = 1			MD1 = 0
+ *		(PLLA = 1500)		(PLLA = 1600)
+ *		(MHz)			(MHz)
+ *------------------------------------------------+--------------------
+ * clkz		1000   (2/3)		800   (1/2)
+ * clkzs	 250   (1/6)		200   (1/8)
+ * clki		 750   (1/2)		800   (1/2)
+ * clks		 250   (1/6)		200   (1/8)
+ * clks1	 125   (1/12)		100   (1/16)
+ * clks3	 187.5 (1/8)		200   (1/8)
+ * clks4	  93.7 (1/16)		100   (1/16)
+ * clkp		  62.5 (1/24)		 50   (1/32)
+ * clkg		  62.5 (1/24)		 66.6 (1/24)
+ * clkb, CLKOUT
+ * (MD2 = 0)	  62.5 (1/24)		 66.6 (1/24)
+ * (MD2 = 1)	  41.6 (1/36)		 50   (1/32)
+*/
+
+#define MD(nr)	BIT(nr)
+
 #define FRQMR		IOMEM(0xffc80014)
 #define MSTPCR0		IOMEM(0xffc80030)
 #define MSTPCR1		IOMEM(0xffc80034)
@@ -36,6 +59,9 @@
 #define MSTPCR6		IOMEM(0xffc80058)
 #define MSTPCR7		IOMEM(0xffc80040)
 
+#define MODEMR		0xffcc0020
+
+
 /* ioremap() through clock mapping mandatory to avoid
  * collision with ARM coherent DMA virtual memory range.
  */
@@ -50,44 +76,44 @@ static struct clk_mapping cpg_mapping = {
  * from the platform code.
  */
 static struct clk plla_clk = {
-	.rate		= 1500000000,
+	/* .rate will be updated on r8a7779_clock_init() */
 	.mapping	= &cpg_mapping,
 };
 
+/*
+ * clock ratio of these clock will be updated
+ * on r8a7779_clock_init()
+ */
+SH_FIXED_RATIO_CLK_SET(clkz_clk,	plla_clk, 1, 1);
+SH_FIXED_RATIO_CLK_SET(clkzs_clk,	plla_clk, 1, 1);
+SH_FIXED_RATIO_CLK_SET(clki_clk,	plla_clk, 1, 1);
+SH_FIXED_RATIO_CLK_SET(clks_clk,	plla_clk, 1, 1);
+SH_FIXED_RATIO_CLK_SET(clks1_clk,	plla_clk, 1, 1);
+SH_FIXED_RATIO_CLK_SET(clks3_clk,	plla_clk, 1, 1);
+SH_FIXED_RATIO_CLK_SET(clks4_clk,	plla_clk, 1, 1);
+SH_FIXED_RATIO_CLK_SET(clkb_clk,	plla_clk, 1, 1);
+SH_FIXED_RATIO_CLK_SET(clkout_clk,	plla_clk, 1, 1);
+SH_FIXED_RATIO_CLK_SET(clkp_clk,	plla_clk, 1, 1);
+SH_FIXED_RATIO_CLK_SET(clkg_clk,	plla_clk, 1, 1);
+
 static struct clk *main_clks[] = {
 	&plla_clk,
-};
-
-static int divisors[] = { 0, 0, 0, 6, 8, 12, 16, 0, 24, 32, 36, 0, 0, 0, 0, 0 };
-
-static struct clk_div_mult_table div4_div_mult_table = {
-	.divisors = divisors,
-	.nr_divisors = ARRAY_SIZE(divisors),
-};
-
-static struct clk_div4_table div4_table = {
-	.div_mult_table = &div4_div_mult_table,
-};
-
-enum { DIV4_S, DIV4_OUT, DIV4_S4, DIV4_S3, DIV4_S1, DIV4_P, DIV4_NR };
-
-static struct clk div4_clks[DIV4_NR] = {
-	[DIV4_S]	= SH_CLK_DIV4(&plla_clk, FRQMR, 20,
-				      0x0018, CLK_ENABLE_ON_INIT),
-	[DIV4_OUT]	= SH_CLK_DIV4(&plla_clk, FRQMR, 16,
-				      0x0700, CLK_ENABLE_ON_INIT),
-	[DIV4_S4]	= SH_CLK_DIV4(&plla_clk, FRQMR, 12,
-				      0x0040, CLK_ENABLE_ON_INIT),
-	[DIV4_S3]	= SH_CLK_DIV4(&plla_clk, FRQMR, 8,
-				      0x0010, CLK_ENABLE_ON_INIT),
-	[DIV4_S1]	= SH_CLK_DIV4(&plla_clk, FRQMR, 4,
-				      0x0060, CLK_ENABLE_ON_INIT),
-	[DIV4_P]	= SH_CLK_DIV4(&plla_clk, FRQMR, 0,
-				      0x0300, CLK_ENABLE_ON_INIT),
+	&clkz_clk,
+	&clkzs_clk,
+	&clki_clk,
+	&clks_clk,
+	&clks1_clk,
+	&clks3_clk,
+	&clks4_clk,
+	&clkb_clk,
+	&clkout_clk,
+	&clkp_clk,
+	&clkg_clk,
 };
 
 enum { MSTP323, MSTP322, MSTP321, MSTP320,
-	MSTP101, MSTP100,
+	MSTP115,
+	MSTP103, MSTP101, MSTP100,
 	MSTP030,
 	MSTP029, MSTP028, MSTP027, MSTP026, MSTP025, MSTP024, MSTP023, MSTP022, MSTP021,
 	MSTP016, MSTP015, MSTP014,
@@ -95,50 +121,28 @@ enum { MSTP323, MSTP322, MSTP321, MSTP320,
 	MSTP_NR };
 
 static struct clk mstp_clks[MSTP_NR] = {
-	[MSTP323] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 23, 0), /* SDHI0 */
-	[MSTP322] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 22, 0), /* SDHI1 */
-	[MSTP321] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 21, 0), /* SDHI2 */
-	[MSTP320] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 20, 0), /* SDHI3 */
-	[MSTP101] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1,  1, 0), /* USB2 */
-	[MSTP100] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1,  0, 0), /* USB0/1 */
-	[MSTP030] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 30, 0), /* I2C0 */
-	[MSTP029] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 29, 0), /* I2C1 */
-	[MSTP028] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 28, 0), /* I2C2 */
-	[MSTP027] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 27, 0), /* I2C3 */
-	[MSTP026] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 26, 0), /* SCIF0 */
-	[MSTP025] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 25, 0), /* SCIF1 */
-	[MSTP024] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 24, 0), /* SCIF2 */
-	[MSTP023] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 23, 0), /* SCIF3 */
-	[MSTP022] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 22, 0), /* SCIF4 */
-	[MSTP021] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 21, 0), /* SCIF5 */
-	[MSTP016] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 16, 0), /* TMU0 */
-	[MSTP015] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 15, 0), /* TMU1 */
-	[MSTP014] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 14, 0), /* TMU2 */
-	[MSTP007] = SH_CLK_MSTP32(&div4_clks[DIV4_S], MSTPCR0,  7, 0), /* HSPI */
-};
-
-static unsigned long mul4_recalc(struct clk *clk)
-{
-	return clk->parent->rate * 4;
-}
-
-static struct sh_clk_ops mul4_clk_ops = {
-	.recalc		= mul4_recalc,
-};
-
-struct clk clkz_clk = {
-	.ops		= &mul4_clk_ops,
-	.parent		= &div4_clks[DIV4_S],
-};
-
-struct clk clkzs_clk = {
-	/* clks x 4 / 4 = clks */
-	.parent		= &div4_clks[DIV4_S],
-};
-
-static struct clk *late_main_clks[] = {
-	&clkz_clk,
-	&clkzs_clk,
+	[MSTP323] = SH_CLK_MSTP32(&clkp_clk, MSTPCR3, 23, 0), /* SDHI0 */
+	[MSTP322] = SH_CLK_MSTP32(&clkp_clk, MSTPCR3, 22, 0), /* SDHI1 */
+	[MSTP321] = SH_CLK_MSTP32(&clkp_clk, MSTPCR3, 21, 0), /* SDHI2 */
+	[MSTP320] = SH_CLK_MSTP32(&clkp_clk, MSTPCR3, 20, 0), /* SDHI3 */
+	[MSTP115] = SH_CLK_MSTP32(&clkp_clk, MSTPCR1, 15, 0), /* SATA */
+	[MSTP103] = SH_CLK_MSTP32(&clks_clk, MSTPCR1,  3, 0), /* DU */
+	[MSTP101] = SH_CLK_MSTP32(&clkp_clk, MSTPCR1,  1, 0), /* USB2 */
+	[MSTP100] = SH_CLK_MSTP32(&clkp_clk, MSTPCR1,  0, 0), /* USB0/1 */
+	[MSTP030] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 30, 0), /* I2C0 */
+	[MSTP029] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 29, 0), /* I2C1 */
+	[MSTP028] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 28, 0), /* I2C2 */
+	[MSTP027] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 27, 0), /* I2C3 */
+	[MSTP026] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 26, 0), /* SCIF0 */
+	[MSTP025] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 25, 0), /* SCIF1 */
+	[MSTP024] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 24, 0), /* SCIF2 */
+	[MSTP023] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 23, 0), /* SCIF3 */
+	[MSTP022] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 22, 0), /* SCIF4 */
+	[MSTP021] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 21, 0), /* SCIF5 */
+	[MSTP016] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 16, 0), /* TMU0 */
+	[MSTP015] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 15, 0), /* TMU1 */
+	[MSTP014] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 14, 0), /* TMU2 */
+	[MSTP007] = SH_CLK_MSTP32(&clks_clk, MSTPCR0,  7, 0), /* HSPI */
 };
 
 static struct clk_lookup lookups[] = {
@@ -148,14 +152,16 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_CON_ID("clkzs_clk", &clkzs_clk),
 
 	/* DIV4 clocks */
-	CLKDEV_CON_ID("shyway_clk",	&div4_clks[DIV4_S]),
-	CLKDEV_CON_ID("bus_clk",	&div4_clks[DIV4_OUT]),
-	CLKDEV_CON_ID("shyway4_clk",	&div4_clks[DIV4_S4]),
-	CLKDEV_CON_ID("shyway3_clk",	&div4_clks[DIV4_S3]),
-	CLKDEV_CON_ID("shyway1_clk",	&div4_clks[DIV4_S1]),
-	CLKDEV_CON_ID("peripheral_clk",	&div4_clks[DIV4_P]),
+	CLKDEV_CON_ID("shyway_clk",	&clks_clk),
+	CLKDEV_CON_ID("bus_clk",	&clkout_clk),
+	CLKDEV_CON_ID("shyway4_clk",	&clks4_clk),
+	CLKDEV_CON_ID("shyway3_clk",	&clks3_clk),
+	CLKDEV_CON_ID("shyway1_clk",	&clks1_clk),
+	CLKDEV_CON_ID("peripheral_clk",	&clkp_clk),
 
 	/* MSTP32 clocks */
+	CLKDEV_DEV_ID("sata_rcar", &mstp_clks[MSTP115]), /* SATA */
+	CLKDEV_DEV_ID("fc600000.sata", &mstp_clks[MSTP115]), /* SATA w/DT */
 	CLKDEV_DEV_ID("ehci-platform.1", &mstp_clks[MSTP101]), /* USB EHCI port2 */
 	CLKDEV_DEV_ID("ohci-platform.1", &mstp_clks[MSTP101]), /* USB OHCI port2 */
 	CLKDEV_DEV_ID("ehci-platform.0", &mstp_clks[MSTP100]), /* USB EHCI port0/1 */
@@ -180,24 +186,65 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP322]), /* SDHI1 */
 	CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP321]), /* SDHI2 */
 	CLKDEV_DEV_ID("sh_mobile_sdhi.3", &mstp_clks[MSTP320]), /* SDHI3 */
+	CLKDEV_DEV_ID("rcar-du.0", &mstp_clks[MSTP103]), /* DU */
 };
 
 void __init r8a7779_clock_init(void)
 {
+	void __iomem *modemr = ioremap_nocache(MODEMR, PAGE_SIZE);
+	u32 mode;
 	int k, ret = 0;
 
+	BUG_ON(!modemr);
+	mode = ioread32(modemr);
+	iounmap(modemr);
+
+	if (mode & MD(1)) {
+		plla_clk.rate = 1500000000;
+
+		SH_CLK_SET_RATIO(&clkz_clk_ratio,	2, 3);
+		SH_CLK_SET_RATIO(&clkzs_clk_ratio,	1, 6);
+		SH_CLK_SET_RATIO(&clki_clk_ratio,	1, 2);
+		SH_CLK_SET_RATIO(&clks_clk_ratio,	1, 6);
+		SH_CLK_SET_RATIO(&clks1_clk_ratio,	1, 12);
+		SH_CLK_SET_RATIO(&clks3_clk_ratio,	1, 8);
+		SH_CLK_SET_RATIO(&clks4_clk_ratio,	1, 16);
+		SH_CLK_SET_RATIO(&clkp_clk_ratio,	1, 24);
+		SH_CLK_SET_RATIO(&clkg_clk_ratio,	1, 24);
+		if (mode & MD(2)) {
+			SH_CLK_SET_RATIO(&clkb_clk_ratio,	1, 36);
+			SH_CLK_SET_RATIO(&clkout_clk_ratio,	1, 36);
+		} else {
+			SH_CLK_SET_RATIO(&clkb_clk_ratio,	1, 24);
+			SH_CLK_SET_RATIO(&clkout_clk_ratio,	1, 24);
+		}
+	} else {
+		plla_clk.rate = 1600000000;
+
+		SH_CLK_SET_RATIO(&clkz_clk_ratio,	1, 2);
+		SH_CLK_SET_RATIO(&clkzs_clk_ratio,	1, 8);
+		SH_CLK_SET_RATIO(&clki_clk_ratio,	1, 2);
+		SH_CLK_SET_RATIO(&clks_clk_ratio,	1, 8);
+		SH_CLK_SET_RATIO(&clks1_clk_ratio,	1, 16);
+		SH_CLK_SET_RATIO(&clks3_clk_ratio,	1, 8);
+		SH_CLK_SET_RATIO(&clks4_clk_ratio,	1, 16);
+		SH_CLK_SET_RATIO(&clkp_clk_ratio,	1, 32);
+		SH_CLK_SET_RATIO(&clkg_clk_ratio,	1, 24);
+		if (mode & MD(2)) {
+			SH_CLK_SET_RATIO(&clkb_clk_ratio,	1, 32);
+			SH_CLK_SET_RATIO(&clkout_clk_ratio,	1, 32);
+		} else {
+			SH_CLK_SET_RATIO(&clkb_clk_ratio,	1, 24);
+			SH_CLK_SET_RATIO(&clkout_clk_ratio,	1, 24);
+		}
+	}
+
 	for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
 		ret = clk_register(main_clks[k]);
 
 	if (!ret)
-		ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table);
-
-	if (!ret)
 		ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);
 
-	for (k = 0; !ret && (k < ARRAY_SIZE(late_main_clks)); k++)
-		ret = clk_register(late_main_clks[k]);
-
 	clkdev_add_table(lookups, ARRAY_SIZE(lookups));
 
 	if (!ret)
diff --git a/arch/arm/mach-shmobile/clock-r8a7790.c b/arch/arm/mach-shmobile/clock-r8a7790.c
new file mode 100644
index 0000000..bad9bf2
--- /dev/null
+++ b/arch/arm/mach-shmobile/clock-r8a7790.c
@@ -0,0 +1,93 @@
+/*
+ * r8a7790 clock framework support
+ *
+ * Copyright (C) 2013  Renesas Solutions Corp.
+ * Copyright (C) 2013  Magnus Damm
+ *
+ * This program is free software; 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/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/sh_clk.h>
+#include <linux/clkdev.h>
+#include <mach/common.h>
+
+#define CPG_BASE 0xe6150000
+#define CPG_LEN 0x1000
+
+#define SMSTPCR2 0xe6150138
+#define SMSTPCR7 0xe615014c
+
+static struct clk_mapping cpg_mapping = {
+	.phys   = CPG_BASE,
+	.len    = CPG_LEN,
+};
+
+static struct clk p_clk = {
+	.rate	= 65000000, /* shortcut for now */
+	.mapping	= &cpg_mapping,
+};
+
+static struct clk mp_clk = {
+	.rate	= 52000000,  /* shortcut for now */
+	.mapping	= &cpg_mapping,
+};
+
+static struct clk *main_clks[] = {
+	&p_clk,
+	&mp_clk,
+};
+
+enum { MSTP721, MSTP720,
+	MSTP216, MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP_NR };
+static struct clk mstp_clks[MSTP_NR] = {
+	[MSTP721] = SH_CLK_MSTP32(&p_clk, SMSTPCR7, 21, 0), /* SCIF0 */
+	[MSTP720] = SH_CLK_MSTP32(&p_clk, SMSTPCR7, 20, 0), /* SCIF1 */
+	[MSTP216] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 16, 0), /* SCIFB2 */
+	[MSTP207] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 7, 0), /* SCIFB1 */
+	[MSTP206] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 6, 0), /* SCIFB0 */
+	[MSTP204] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 4, 0), /* SCIFA0 */
+	[MSTP203] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 3, 0), /* SCIFA1 */
+	[MSTP202] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 2, 0), /* SCIFA2 */
+};
+
+static struct clk_lookup lookups[] = {
+	CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP204]),
+	CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP203]),
+	CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP206]),
+	CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP207]),
+	CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP216]),
+	CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP202]),
+	CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[MSTP721]),
+	CLKDEV_DEV_ID("sh-sci.7", &mstp_clks[MSTP720]),
+};
+
+void __init r8a7790_clock_init(void)
+{
+	int k, ret = 0;
+
+	for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
+		ret = clk_register(main_clks[k]);
+
+	if (!ret)
+		ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);
+
+	clkdev_add_table(lookups, ARRAY_SIZE(lookups));
+
+	if (!ret)
+		shmobile_clk_init();
+	else
+		panic("failed to setup r8a7790 clocks\n");
+}
diff --git a/arch/arm/mach-shmobile/clock-sh7372.c b/arch/arm/mach-shmobile/clock-sh7372.c
index 45d21fe..7e10593 100644
--- a/arch/arm/mach-shmobile/clock-sh7372.c
+++ b/arch/arm/mach-shmobile/clock-sh7372.c
@@ -21,6 +21,7 @@
 #include <linux/io.h>
 #include <linux/sh_clk.h>
 #include <linux/clkdev.h>
+#include <mach/clock.h>
 #include <mach/common.h>
 
 /* SH7372 registers */
@@ -83,39 +84,12 @@ struct clk sh7372_extal2_clk = {
 	.rate		= 48000000,
 };
 
-/* A fixed divide-by-2 block */
-static unsigned long div2_recalc(struct clk *clk)
-{
-	return clk->parent->rate / 2;
-}
-
-static struct sh_clk_ops div2_clk_ops = {
-	.recalc		= div2_recalc,
-};
+SH_CLK_RATIO(div2, 1, 2);
 
-/* Divide dv_clki by two */
-struct clk sh7372_dv_clki_div2_clk = {
-	.ops		= &div2_clk_ops,
-	.parent		= &sh7372_dv_clki_clk,
-};
-
-/* Divide extal1 by two */
-static struct clk extal1_div2_clk = {
-	.ops		= &div2_clk_ops,
-	.parent		= &sh7372_extal1_clk,
-};
-
-/* Divide extal2 by two */
-static struct clk extal2_div2_clk = {
-	.ops		= &div2_clk_ops,
-	.parent		= &sh7372_extal2_clk,
-};
-
-/* Divide extal2 by four */
-static struct clk extal2_div4_clk = {
-	.ops		= &div2_clk_ops,
-	.parent		= &extal2_div2_clk,
-};
+SH_FIXED_RATIO_CLKg(sh7372_dv_clki_div2_clk,	sh7372_dv_clki_clk,	div2);
+SH_FIXED_RATIO_CLK(extal1_div2_clk,		sh7372_extal1_clk,	div2);
+SH_FIXED_RATIO_CLK(extal2_div2_clk,		sh7372_extal2_clk,	div2);
+SH_FIXED_RATIO_CLK(extal2_div4_clk,		extal2_div2_clk,	div2);
 
 /* PLLC0 and PLLC1 */
 static unsigned long pllc01_recalc(struct clk *clk)
@@ -147,10 +121,7 @@ static struct clk pllc1_clk = {
 };
 
 /* Divide PLLC1 by two */
-static struct clk pllc1_div2_clk = {
-	.ops		= &div2_clk_ops,
-	.parent		= &pllc1_clk,
-};
+SH_FIXED_RATIO_CLK(pllc1_div2_clk,	pllc1_clk,	div2);
 
 /* PLLC2 */
 
@@ -342,7 +313,7 @@ static struct clk_div4_table div4_table = {
 };
 
 enum { DIV4_I, DIV4_ZG, DIV4_B, DIV4_M1, DIV4_CSIR,
-       DIV4_ZTR, DIV4_ZT, DIV4_ZX, DIV4_HP,
+       DIV4_ZX, DIV4_HP,
        DIV4_ISPB, DIV4_S, DIV4_ZB, DIV4_ZB3, DIV4_CP,
        DIV4_DDRP, DIV4_NR };
 
@@ -355,8 +326,6 @@ static struct clk div4_clks[DIV4_NR] = {
 	[DIV4_B] = DIV4(FRQCRA, 8, 0x6fff, CLK_ENABLE_ON_INIT),
 	[DIV4_M1] = DIV4(FRQCRA, 4, 0x6fff, CLK_ENABLE_ON_INIT),
 	[DIV4_CSIR] = DIV4(FRQCRA, 0, 0x6fff, 0),
-	[DIV4_ZTR] = DIV4(FRQCRB, 20, 0x6fff, 0),
-	[DIV4_ZT] = DIV4(FRQCRB, 16, 0x6fff, 0),
 	[DIV4_ZX] = DIV4(FRQCRB, 12, 0x6fff, 0),
 	[DIV4_HP] = DIV4(FRQCRB, 4, 0x6fff, 0),
 	[DIV4_ISPB] = DIV4(FRQCRC, 20, 0x6fff, 0),
@@ -516,8 +485,6 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_CON_ID("b_clk", &div4_clks[DIV4_B]),
 	CLKDEV_CON_ID("m1_clk", &div4_clks[DIV4_M1]),
 	CLKDEV_CON_ID("csir_clk", &div4_clks[DIV4_CSIR]),
-	CLKDEV_CON_ID("ztr_clk", &div4_clks[DIV4_ZTR]),
-	CLKDEV_CON_ID("zt_clk", &div4_clks[DIV4_ZT]),
 	CLKDEV_CON_ID("zx_clk", &div4_clks[DIV4_ZX]),
 	CLKDEV_CON_ID("hp_clk", &div4_clks[DIV4_HP]),
 	CLKDEV_CON_ID("ispb_clk", &div4_clks[DIV4_ISPB]),
@@ -654,5 +621,4 @@ void __init sh7372_clock_init(void)
 		shmobile_clk_init();
 	else
 		panic("failed to setup sh7372 clocks\n");
-
 }
diff --git a/arch/arm/mach-shmobile/clock-sh73a0.c b/arch/arm/mach-shmobile/clock-sh73a0.c
index afa5423..784fbaa 100644
--- a/arch/arm/mach-shmobile/clock-sh73a0.c
+++ b/arch/arm/mach-shmobile/clock-sh73a0.c
@@ -21,6 +21,8 @@
 #include <linux/io.h>
 #include <linux/sh_clk.h>
 #include <linux/clkdev.h>
+#include <asm/processor.h>
+#include <mach/clock.h>
 #include <mach/common.h>
 
 #define FRQCRA		IOMEM(0xe6150000)
@@ -82,61 +84,16 @@ struct clk sh73a0_extal2_clk = {
 	.rate		= 48000000,
 };
 
-/* A fixed divide-by-2 block */
-static unsigned long div2_recalc(struct clk *clk)
-{
-	return clk->parent->rate / 2;
-}
-
-static struct sh_clk_ops div2_clk_ops = {
-	.recalc		= div2_recalc,
-};
-
-static unsigned long div7_recalc(struct clk *clk)
-{
-	return clk->parent->rate / 7;
-}
-
-static struct sh_clk_ops div7_clk_ops = {
-	.recalc		= div7_recalc,
-};
-
-static unsigned long div13_recalc(struct clk *clk)
-{
-	return clk->parent->rate / 13;
-}
-
-static struct sh_clk_ops div13_clk_ops = {
-	.recalc		= div13_recalc,
-};
-
-/* Divide extal1 by two */
-static struct clk extal1_div2_clk = {
-	.ops		= &div2_clk_ops,
-	.parent		= &sh73a0_extal1_clk,
-};
-
-/* Divide extal2 by two */
-static struct clk extal2_div2_clk = {
-	.ops		= &div2_clk_ops,
-	.parent		= &sh73a0_extal2_clk,
-};
-
 static struct sh_clk_ops main_clk_ops = {
 	.recalc		= followparent_recalc,
 };
 
 /* Main clock */
 static struct clk main_clk = {
+	/* .parent wll be set on sh73a0_clock_init() */
 	.ops		= &main_clk_ops,
 };
 
-/* Divide Main clock by two */
-static struct clk main_div2_clk = {
-	.ops		= &div2_clk_ops,
-	.parent		= &main_clk,
-};
-
 /* PLL0, PLL1, PLL2, PLL3 */
 static unsigned long pll_recalc(struct clk *clk)
 {
@@ -192,21 +149,17 @@ static struct clk pll3_clk = {
 	.enable_bit	= 3,
 };
 
-/* Divide PLL */
-static struct clk pll1_div2_clk = {
-	.ops		= &div2_clk_ops,
-	.parent		= &pll1_clk,
-};
-
-static struct clk pll1_div7_clk = {
-	.ops		= &div7_clk_ops,
-	.parent		= &pll1_clk,
-};
+/* A fixed divide block */
+SH_CLK_RATIO(div2,  1, 2);
+SH_CLK_RATIO(div7,  1, 7);
+SH_CLK_RATIO(div13, 1, 13);
 
-static struct clk pll1_div13_clk = {
-	.ops		= &div13_clk_ops,
-	.parent		= &pll1_clk,
-};
+SH_FIXED_RATIO_CLK(extal1_div2_clk,	sh73a0_extal1_clk,	div2);
+SH_FIXED_RATIO_CLK(extal2_div2_clk,	sh73a0_extal2_clk,	div2);
+SH_FIXED_RATIO_CLK(main_div2_clk,	main_clk,		div2);
+SH_FIXED_RATIO_CLK(pll1_div2_clk,	pll1_clk,		div2);
+SH_FIXED_RATIO_CLK(pll1_div7_clk,	pll1_clk,		div7);
+SH_FIXED_RATIO_CLK(pll1_div13_clk,	pll1_clk,		div13);
 
 /* External input clock */
 struct clk sh73a0_extcki_clk = {
@@ -234,14 +187,24 @@ static struct clk *main_clks[] = {
 	&sh73a0_extalr_clk,
 };
 
-static void div4_kick(struct clk *clk)
+static int frqcr_kick(void)
 {
-	unsigned long value;
+	int i;
+
+	/* set KICK bit in FRQCRB to update hardware setting, check success */
+	__raw_writel(__raw_readl(FRQCRB) | (1 << 31), FRQCRB);
+	for (i = 1000; i; i--)
+		if (__raw_readl(FRQCRB) & (1 << 31))
+			cpu_relax();
+		else
+			return i;
 
-	/* set KICK bit in FRQCRB to update hardware setting */
-	value = __raw_readl(FRQCRB);
-	value |= (1 << 31);
-	__raw_writel(value, FRQCRB);
+	return -ETIMEDOUT;
+}
+
+static void div4_kick(struct clk *clk)
+{
+	frqcr_kick();
 }
 
 static int divisors[] = { 2, 3, 4, 6, 8, 12, 16, 18,
@@ -258,25 +221,37 @@ static struct clk_div4_table div4_table = {
 };
 
 enum { DIV4_I, DIV4_ZG, DIV4_M3, DIV4_B, DIV4_M1, DIV4_M2,
-	DIV4_Z, DIV4_ZTR, DIV4_ZT, DIV4_ZX, DIV4_HP, DIV4_NR };
+	DIV4_Z, DIV4_ZX, DIV4_HP, DIV4_NR };
 
 #define DIV4(_reg, _bit, _mask, _flags) \
 	SH_CLK_DIV4(&pll1_clk, _reg, _bit, _mask, _flags)
 
 static struct clk div4_clks[DIV4_NR] = {
 	[DIV4_I] = DIV4(FRQCRA, 20, 0xdff, CLK_ENABLE_ON_INIT),
-	[DIV4_ZG] = DIV4(FRQCRA, 16, 0xd7f, CLK_ENABLE_ON_INIT),
+	[DIV4_ZG] = SH_CLK_DIV4(&pll0_clk, FRQCRA, 16, 0xd7f, CLK_ENABLE_ON_INIT),
 	[DIV4_M3] = DIV4(FRQCRA, 12, 0x1dff, CLK_ENABLE_ON_INIT),
 	[DIV4_B] = DIV4(FRQCRA, 8, 0xdff, CLK_ENABLE_ON_INIT),
 	[DIV4_M1] = DIV4(FRQCRA, 4, 0x1dff, 0),
 	[DIV4_M2] = DIV4(FRQCRA, 0, 0x1dff, 0),
-	[DIV4_Z] = DIV4(FRQCRB, 24, 0x97f, 0),
-	[DIV4_ZTR] = DIV4(FRQCRB, 20, 0xdff, 0),
-	[DIV4_ZT] = DIV4(FRQCRB, 16, 0xdff, 0),
+	[DIV4_Z] = SH_CLK_DIV4(&pll0_clk, FRQCRB, 24, 0x97f, 0),
 	[DIV4_ZX] = DIV4(FRQCRB, 12, 0xdff, 0),
 	[DIV4_HP] = DIV4(FRQCRB, 4, 0xdff, 0),
 };
 
+static unsigned long twd_recalc(struct clk *clk)
+{
+	return clk_get_rate(clk->parent) / 4;
+}
+
+static struct sh_clk_ops twd_clk_ops = {
+	.recalc = twd_recalc,
+};
+
+static struct clk twd_clk = {
+	.parent = &div4_clks[DIV4_Z],
+	.ops = &twd_clk_ops,
+};
+
 enum { DIV6_VCK1, DIV6_VCK2, DIV6_VCK3, DIV6_ZB1,
 	DIV6_FLCTL, DIV6_SDHI0, DIV6_SDHI1, DIV6_SDHI2,
 	DIV6_FSIA, DIV6_FSIB, DIV6_SUB,
@@ -471,6 +446,7 @@ static struct clk dsi1phy_clk = {
 static struct clk *late_main_clks[] = {
 	&dsi0phy_clk,
 	&dsi1phy_clk,
+	&twd_clk,
 };
 
 enum { MSTP001,
@@ -535,6 +511,7 @@ static struct clk mstp_clks[MSTP_NR] = {
 static struct clk_lookup lookups[] = {
 	/* main clocks */
 	CLKDEV_CON_ID("r_clk", &r_clk),
+	CLKDEV_DEV_ID("smp_twd", &twd_clk), /* smp_twd */
 
 	/* DIV6 clocks */
 	CLKDEV_CON_ID("vck1_clk", &div6_clks[DIV6_VCK1]),
@@ -581,10 +558,13 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_DEV_ID("e6822000.i2c", &mstp_clks[MSTP323]), /* I2C1 */
 	CLKDEV_DEV_ID("renesas_usbhs", &mstp_clks[MSTP322]), /* USB */
 	CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]), /* SDHI0 */
+	CLKDEV_DEV_ID("ee100000.sdhi", &mstp_clks[MSTP314]), /* SDHI0 */
 	CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]), /* SDHI1 */
+	CLKDEV_DEV_ID("ee120000.sdhi", &mstp_clks[MSTP313]), /* SDHI1 */
 	CLKDEV_DEV_ID("sh_mmcif.0", &mstp_clks[MSTP312]), /* MMCIF0 */
 	CLKDEV_DEV_ID("e6bd0000.mmcif", &mstp_clks[MSTP312]), /* MMCIF0 */
 	CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP311]), /* SDHI2 */
+	CLKDEV_DEV_ID("ee140000.sdhi", &mstp_clks[MSTP311]), /* SDHI2 */
 	CLKDEV_DEV_ID("leds-renesas-tpu.12", &mstp_clks[MSTP303]), /* TPU1 */
 	CLKDEV_DEV_ID("leds-renesas-tpu.21", &mstp_clks[MSTP302]), /* TPU2 */
 	CLKDEV_DEV_ID("leds-renesas-tpu.30", &mstp_clks[MSTP301]), /* TPU3 */
diff --git a/arch/arm/mach-shmobile/clock.c b/arch/arm/mach-shmobile/clock.c
index e816ca9..ad7df62 100644
--- a/arch/arm/mach-shmobile/clock.c
+++ b/arch/arm/mach-shmobile/clock.c
@@ -23,6 +23,19 @@
 #include <linux/init.h>
 #include <linux/sh_clk.h>
 #include <linux/export.h>
+#include <mach/clock.h>
+#include <mach/common.h>
+
+unsigned long shmobile_fixed_ratio_clk_recalc(struct clk *clk)
+{
+	struct clk_ratio *p = clk->priv;
+
+	return clk->parent->rate / p->div * p->mul;
+};
+
+struct sh_clk_ops shmobile_fixed_ratio_clk_ops = {
+	.recalc	= shmobile_fixed_ratio_clk_recalc,
+};
 
 int __init shmobile_clk_init(void)
 {
diff --git a/arch/arm/mach-shmobile/headsmp-scu.S b/arch/arm/mach-shmobile/headsmp-scu.S
new file mode 100644
index 0000000..7d113f8
--- /dev/null
+++ b/arch/arm/mach-shmobile/headsmp-scu.S
@@ -0,0 +1,57 @@
+/*
+ * Shared SCU setup for mach-shmobile
+ *
+ * Copyright (C) 2012 Bastian Hecht
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR /PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/memory.h>
+
+	__CPUINIT
+/*
+ * Reset vector for secondary CPUs.
+ *
+ * First we turn on L1 cache coherency for our CPU. Then we jump to
+ * shmobile_invalidate_start that invalidates the cache and hands over control
+ * to the common ARM startup code.
+ * This function will be mapped to address 0 by the SBAR register.
+ * A normal branch is out of range here so we need a long jump. We jump to
+ * the physical address as the MMU is still turned off.
+ */
+	.align	12
+ENTRY(shmobile_secondary_vector_scu)
+	mrc     p15, 0, r0, c0, c0, 5	@ read MIPDR
+	and	r0, r0, #3		@ mask out cpu ID
+	lsl	r0, r0, #3		@ we will shift by cpu_id * 8 bits
+	ldr	r1, 2f
+	ldr	r1, [r1]		@ SCU base address
+	ldr	r2, [r1, #8]		@ SCU Power Status Register
+	mov	r3, #3
+	bic	r2, r2, r3, lsl r0	@ Clear bits of our CPU (Run Mode)
+	str	r2, [r1, #8]		@ write back
+
+	ldr	pc, 1f
+1:	.long shmobile_invalidate_start - PAGE_OFFSET + PLAT_PHYS_OFFSET
+2:	.long shmobile_scu_base - PAGE_OFFSET + PLAT_PHYS_OFFSET
+ENDPROC(shmobile_secondary_vector_scu)
+
+	.text
+	.globl	shmobile_scu_base
+shmobile_scu_base:
+	.space	4
diff --git a/arch/arm/mach-shmobile/headsmp-sh73a0.S b/arch/arm/mach-shmobile/headsmp-sh73a0.S
deleted file mode 100644
index bec4c0d..0000000
--- a/arch/arm/mach-shmobile/headsmp-sh73a0.S
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * SMP support for SoC sh73a0
- *
- * Copyright (C) 2012 Bastian Hecht
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR /PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
- */
-
-#include <linux/linkage.h>
-#include <linux/init.h>
-#include <asm/memory.h>
-
-	__CPUINIT
-/*
- * Reset vector for secondary CPUs.
- *
- * First we turn on L1 cache coherency for our CPU. Then we jump to
- * shmobile_invalidate_start that invalidates the cache and hands over control
- * to the common ARM startup code.
- * This function will be mapped to address 0 by the SBAR register.
- * A normal branch is out of range here so we need a long jump. We jump to
- * the physical address as the MMU is still turned off.
- */
-	.align	12
-ENTRY(sh73a0_secondary_vector)
-	mrc     p15, 0, r0, c0, c0, 5	@ read MIPDR
-	and	r0, r0, #3		@ mask out cpu ID
-	lsl	r0, r0, #3		@ we will shift by cpu_id * 8 bits
-	mov	r1, #0xf0000000		@ SCU base address
-	ldr	r2, [r1, #8]		@ SCU Power Status Register
-	mov	r3, #3
-	bic	r2, r2, r3, lsl r0	@ Clear bits of our CPU (Run Mode)
-	str	r2, [r1, #8]		@ write back
-
-	ldr	pc, 1f
-1:	.long shmobile_invalidate_start - PAGE_OFFSET + PLAT_PHYS_OFFSET
-ENDPROC(sh73a0_secondary_vector)
diff --git a/arch/arm/mach-shmobile/hotplug.c b/arch/arm/mach-shmobile/hotplug.c
deleted file mode 100644
index a1524e3..0000000
--- a/arch/arm/mach-shmobile/hotplug.c
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * SMP support for R-Mobile / SH-Mobile
- *
- * Copyright (C) 2010  Magnus Damm
- *
- * Based on realview, 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/kernel.h>
-#include <linux/errno.h>
-#include <linux/smp.h>
-#include <linux/cpumask.h>
-#include <linux/delay.h>
-#include <linux/of.h>
-#include <mach/common.h>
-#include <mach/r8a7779.h>
-#include <mach/emev2.h>
-#include <asm/cacheflush.h>
-#include <asm/mach-types.h>
-
-static cpumask_t dead_cpus;
-
-void shmobile_cpu_die(unsigned int cpu)
-{
-	/* hardware shutdown code running on the CPU that is being offlined */
-	flush_cache_all();
-	dsb();
-
-	/* notify platform_cpu_kill() that hardware shutdown is finished */
-	cpumask_set_cpu(cpu, &dead_cpus);
-
-	/* wait for SoC code in platform_cpu_kill() to shut off CPU core
-	 * power. CPU bring up starts from the reset vector.
-	 */
-	while (1) {
-		/*
-		 * here's the WFI
-		 */
-		asm(".word	0xe320f003\n"
-		    :
-		    :
-		    : "memory", "cc");
-	}
-}
-
-int shmobile_cpu_disable(unsigned int cpu)
-{
-	cpumask_clear_cpu(cpu, &dead_cpus);
-	/*
-	 * we don't allow CPU 0 to be shutdown (it is still too special
-	 * e.g. clock tick interrupts)
-	 */
-	return cpu == 0 ? -EPERM : 0;
-}
-
-int shmobile_cpu_disable_any(unsigned int cpu)
-{
-	cpumask_clear_cpu(cpu, &dead_cpus);
-	return 0;
-}
-
-int shmobile_cpu_is_dead(unsigned int cpu)
-{
-	return cpumask_test_cpu(cpu, &dead_cpus);
-}
diff --git a/arch/arm/mach-shmobile/include/mach/clock.h b/arch/arm/mach-shmobile/include/mach/clock.h
new file mode 100644
index 0000000..8902044
--- /dev/null
+++ b/arch/arm/mach-shmobile/include/mach/clock.h
@@ -0,0 +1,39 @@
+#ifndef CLOCK_H
+#define CLOCK_H
+
+unsigned long shmobile_fixed_ratio_clk_recalc(struct clk *clk);
+extern struct sh_clk_ops shmobile_fixed_ratio_clk_ops;
+
+/* clock ratio */
+struct clk_ratio {
+	int mul;
+	int div;
+};
+
+#define SH_CLK_RATIO(name, m, d)		\
+static struct clk_ratio name ##_ratio = {	\
+	.mul = m,				\
+	.div = d,				\
+}
+
+#define SH_FIXED_RATIO_CLKg(name, p, r)	\
+struct clk name = {			\
+	.parent	= &p,				\
+	.ops	= &shmobile_fixed_ratio_clk_ops,\
+	.priv	= &r ## _ratio,			\
+}
+
+#define SH_FIXED_RATIO_CLK(name, p, r)		\
+static SH_FIXED_RATIO_CLKg(name, p, r)
+
+#define SH_FIXED_RATIO_CLK_SET(name, p, m, d)	\
+	SH_CLK_RATIO(name, m, d);		\
+	SH_FIXED_RATIO_CLK(name, p, name)
+
+#define SH_CLK_SET_RATIO(p, m, d)	\
+{			\
+	(p)->mul = m;	\
+	(p)->div = d;	\
+}
+
+#endif
diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h
index e48606d..e002cfd 100644
--- a/arch/arm/mach-shmobile/include/mach/common.h
+++ b/arch/arm/mach-shmobile/include/mach/common.h
@@ -8,6 +8,7 @@ extern void shmobile_setup_delay(unsigned int max_cpu_core_mhz,
 struct twd_local_timer;
 extern void shmobile_setup_console(void);
 extern void shmobile_secondary_vector(void);
+extern void shmobile_secondary_vector_scu(void);
 struct clk;
 extern int shmobile_clk_init(void);
 extern void shmobile_handle_irq_intc(struct pt_regs *);
@@ -18,58 +19,6 @@ extern int shmobile_enter_wfi(struct cpuidle_device *dev,
 			      struct cpuidle_driver *drv, int index);
 extern void shmobile_cpuidle_set_driver(struct cpuidle_driver *drv);
 
-extern void sh7372_init_irq(void);
-extern void sh7372_map_io(void);
-extern void sh7372_earlytimer_init(void);
-extern void sh7372_add_early_devices(void);
-extern void sh7372_add_standard_devices(void);
-extern void sh7372_add_early_devices_dt(void);
-extern void sh7372_add_standard_devices_dt(void);
-extern void sh7372_clock_init(void);
-extern void sh7372_pinmux_init(void);
-extern void sh7372_pm_init(void);
-extern void sh7372_resume_core_standby_sysc(void);
-extern int sh7372_do_idle_sysc(unsigned long sleep_mode);
-extern struct clk sh7372_extal1_clk;
-extern struct clk sh7372_extal2_clk;
-
-extern void sh73a0_init_irq(void);
-extern void sh73a0_init_irq_dt(void);
-extern void sh73a0_map_io(void);
-extern void sh73a0_earlytimer_init(void);
-extern void sh73a0_add_early_devices(void);
-extern void sh73a0_add_early_devices_dt(void);
-extern void sh73a0_add_standard_devices(void);
-extern void sh73a0_add_standard_devices_dt(void);
-extern void sh73a0_clock_init(void);
-extern void sh73a0_pinmux_init(void);
-extern void sh73a0_pm_init(void);
-extern void sh73a0_secondary_vector(void);
-extern struct clk sh73a0_extal1_clk;
-extern struct clk sh73a0_extal2_clk;
-extern struct clk sh73a0_extcki_clk;
-extern struct clk sh73a0_extalr_clk;
-
-extern void r8a7740_init_irq(void);
-extern void r8a7740_map_io(void);
-extern void r8a7740_add_early_devices(void);
-extern void r8a7740_add_standard_devices(void);
-extern void r8a7740_clock_init(u8 md_ck);
-extern void r8a7740_pinmux_init(void);
-extern void r8a7740_pm_init(void);
-
-extern void r8a7779_init_irq(void);
-extern void r8a7779_map_io(void);
-extern void r8a7779_earlytimer_init(void);
-extern void r8a7779_add_early_devices(void);
-extern void r8a7779_add_standard_devices(void);
-extern void r8a7779_clock_init(void);
-extern void r8a7779_pinmux_init(void);
-extern void r8a7779_pm_init(void);
-extern void r8a7740_meram_workaround(void);
-
-extern void r8a7779_register_twd(void);
-
 #ifdef CONFIG_SUSPEND
 int shmobile_suspend_init(void);
 #else
@@ -82,16 +31,7 @@ int shmobile_cpuidle_init(void);
 static inline int shmobile_cpuidle_init(void) { return 0; }
 #endif
 
-extern void shmobile_cpu_die(unsigned int cpu);
-extern int shmobile_cpu_disable(unsigned int cpu);
-extern int shmobile_cpu_disable_any(unsigned int cpu);
-
-#ifdef CONFIG_HOTPLUG_CPU
-extern int shmobile_cpu_is_dead(unsigned int cpu);
-#else
-static inline int shmobile_cpu_is_dead(unsigned int cpu) { return 1; }
-#endif
-
+extern void __iomem *shmobile_scu_base;
 extern void shmobile_smp_init_cpus(unsigned int ncores);
 
 static inline void __init shmobile_init_late(void)
diff --git a/arch/arm/mach-shmobile/include/mach/irqs.h b/arch/arm/mach-shmobile/include/mach/irqs.h
index 06a5da3..b2074e2 100644
--- a/arch/arm/mach-shmobile/include/mach/irqs.h
+++ b/arch/arm/mach-shmobile/include/mach/irqs.h
@@ -5,10 +5,15 @@
 
 /* GIC */
 #define gic_spi(nr)		((nr) + 32)
+#define gic_iid(nr)		(nr) /* ICCIAR / interrupt ID */
 
 /* INTCS */
 #define INTCS_VECT_BASE		0x3400
 #define INTCS_VECT(n, vect)	INTC_VECT((n), INTCS_VECT_BASE + (vect))
 #define intcs_evt2irq(evt)	evt2irq(INTCS_VECT_BASE + (evt))
 
+/* External IRQ pins */
+#define IRQPIN_BASE		2000
+#define irq_pin(nr)		((nr) + IRQPIN_BASE)
+
 #endif /* __ASM_MACH_IRQS_H */
diff --git a/arch/arm/mach-shmobile/include/mach/r8a73a4.h b/arch/arm/mach-shmobile/include/mach/r8a73a4.h
new file mode 100644
index 0000000..f043103
--- /dev/null
+++ b/arch/arm/mach-shmobile/include/mach/r8a73a4.h
@@ -0,0 +1,8 @@
+#ifndef __ASM_R8A73A4_H__
+#define __ASM_R8A73A4_H__
+
+void r8a73a4_add_standard_devices(void);
+void r8a73a4_clock_init(void);
+void r8a73a4_pinmux_init(void);
+
+#endif /* __ASM_R8A73A4_H__ */
diff --git a/arch/arm/mach-shmobile/include/mach/r8a7740.h b/arch/arm/mach-shmobile/include/mach/r8a7740.h
index 59d252f..abdc4d4 100644
--- a/arch/arm/mach-shmobile/include/mach/r8a7740.h
+++ b/arch/arm/mach-shmobile/include/mach/r8a7740.h
@@ -241,48 +241,9 @@ enum {
 
 	/* LCD0 */
 	GPIO_FN_LCDC0_SELECT,
-	GPIO_FN_LCD0_D0,	GPIO_FN_LCD0_D1,	GPIO_FN_LCD0_D2,
-	GPIO_FN_LCD0_D3,	GPIO_FN_LCD0_D4,	GPIO_FN_LCD0_D5,
-	GPIO_FN_LCD0_D6,	GPIO_FN_LCD0_D7,	GPIO_FN_LCD0_D8,
-	GPIO_FN_LCD0_D9,	GPIO_FN_LCD0_D10,	GPIO_FN_LCD0_D11,
-	GPIO_FN_LCD0_D12,	GPIO_FN_LCD0_D13,	GPIO_FN_LCD0_D14,
-	GPIO_FN_LCD0_D15,	GPIO_FN_LCD0_D16,	GPIO_FN_LCD0_D17,
-	GPIO_FN_LCD0_DON,	GPIO_FN_LCD0_VCPWC,	GPIO_FN_LCD0_VEPWC,
-
-	GPIO_FN_LCD0_DCK,	GPIO_FN_LCD0_VSYN, /* for RGB */
-	GPIO_FN_LCD0_HSYN,	GPIO_FN_LCD0_DISP, /* for RGB */
-
-	GPIO_FN_LCD0_WR,	GPIO_FN_LCD0_RD, /* for SYS */
-	GPIO_FN_LCD0_CS,	GPIO_FN_LCD0_RS, /* for SYS */
-
-	GPIO_FN_LCD0_D18_PORT163,	GPIO_FN_LCD0_D19_PORT162,
-	GPIO_FN_LCD0_D20_PORT161,	GPIO_FN_LCD0_D21_PORT158,
-	GPIO_FN_LCD0_D22_PORT160,	GPIO_FN_LCD0_D23_PORT159,
-	GPIO_FN_LCD0_LCLK_PORT165,	 /* MSEL5CR_6_1 */
-
-	GPIO_FN_LCD0_D18_PORT40,	GPIO_FN_LCD0_D19_PORT4,
-	GPIO_FN_LCD0_D20_PORT3,		GPIO_FN_LCD0_D21_PORT2,
-	GPIO_FN_LCD0_D22_PORT0,		GPIO_FN_LCD0_D23_PORT1,
-	GPIO_FN_LCD0_LCLK_PORT102,	/* MSEL5CR_6_0 */
 
 	/* LCD1 */
 	GPIO_FN_LCDC1_SELECT,
-	GPIO_FN_LCD1_D0,	GPIO_FN_LCD1_D1,	GPIO_FN_LCD1_D2,
-	GPIO_FN_LCD1_D3,	GPIO_FN_LCD1_D4,	GPIO_FN_LCD1_D5,
-	GPIO_FN_LCD1_D6,	GPIO_FN_LCD1_D7,	GPIO_FN_LCD1_D8,
-	GPIO_FN_LCD1_D9,	GPIO_FN_LCD1_D10,	GPIO_FN_LCD1_D11,
-	GPIO_FN_LCD1_D12,	GPIO_FN_LCD1_D13,	GPIO_FN_LCD1_D14,
-	GPIO_FN_LCD1_D15,	GPIO_FN_LCD1_D16,	GPIO_FN_LCD1_D17,
-	GPIO_FN_LCD1_D18,	GPIO_FN_LCD1_D19,	GPIO_FN_LCD1_D20,
-	GPIO_FN_LCD1_D21,	GPIO_FN_LCD1_D22,	GPIO_FN_LCD1_D23,
-	GPIO_FN_LCD1_DON,	GPIO_FN_LCD1_VCPWC,
-	GPIO_FN_LCD1_LCLK,	GPIO_FN_LCD1_VEPWC,
-
-	GPIO_FN_LCD1_DCK,	GPIO_FN_LCD1_VSYN, /* for RGB */
-	GPIO_FN_LCD1_HSYN,	GPIO_FN_LCD1_DISP, /* for RGB */
-
-	GPIO_FN_LCD1_WR,	GPIO_FN_LCD1_RD, /* for SYS */
-	GPIO_FN_LCD1_CS,	GPIO_FN_LCD1_RS, /* for SYS */
 
 	/* RSPI */
 	GPIO_FN_RSPI_SSL0_A,	GPIO_FN_RSPI_SSL1_A,
@@ -346,26 +307,6 @@ enum {
 	GPIO_FN_SIM_D_PORT22, /* SIM_D  Port 22/199 */
 	GPIO_FN_SIM_D_PORT199,
 
-	/* SDHI0 */
-	GPIO_FN_SDHI0_D0,	GPIO_FN_SDHI0_D1,	GPIO_FN_SDHI0_D2,
-	GPIO_FN_SDHI0_D3,	GPIO_FN_SDHI0_CD,	GPIO_FN_SDHI0_WP,
-	GPIO_FN_SDHI0_CMD,	GPIO_FN_SDHI0_CLK,
-
-	/* SDHI1 */
-	GPIO_FN_SDHI1_D0,	GPIO_FN_SDHI1_D1,	GPIO_FN_SDHI1_D2,
-	GPIO_FN_SDHI1_D3,	GPIO_FN_SDHI1_CD,	GPIO_FN_SDHI1_WP,
-	GPIO_FN_SDHI1_CMD,	GPIO_FN_SDHI1_CLK,
-
-	/* SDHI2 */
-	GPIO_FN_SDHI2_D0,	GPIO_FN_SDHI2_D1,	GPIO_FN_SDHI2_D2,
-	GPIO_FN_SDHI2_D3,	GPIO_FN_SDHI2_CLK,	GPIO_FN_SDHI2_CMD,
-
-	GPIO_FN_SDHI2_CD_PORT24, /* MSEL5CR_19_0 */
-	GPIO_FN_SDHI2_WP_PORT25,
-
-	GPIO_FN_SDHI2_WP_PORT177, /* MSEL5CR_19_1 */
-	GPIO_FN_SDHI2_CD_PORT202,
-
 	/* MSIOF2 */
 	GPIO_FN_MSIOF2_TXD,	GPIO_FN_MSIOF2_RXD,	GPIO_FN_MSIOF2_TSCK,
 	GPIO_FN_MSIOF2_SS2,	GPIO_FN_MSIOF2_TSYNC,	GPIO_FN_MSIOF2_SS1,
@@ -417,21 +358,6 @@ enum {
 	GPIO_FN_MEMC_DREQ1,
 	GPIO_FN_MEMC_A0,
 
-	/* MMC */
-	GPIO_FN_MMC0_D0_PORT68,		GPIO_FN_MMC0_D1_PORT69,
-	GPIO_FN_MMC0_D2_PORT70,		GPIO_FN_MMC0_D3_PORT71,
-	GPIO_FN_MMC0_D4_PORT72,		GPIO_FN_MMC0_D5_PORT73,
-	GPIO_FN_MMC0_D6_PORT74,		GPIO_FN_MMC0_D7_PORT75,
-	GPIO_FN_MMC0_CLK_PORT66,
-	GPIO_FN_MMC0_CMD_PORT67,	/* MSEL4CR_15_0 */
-
-	GPIO_FN_MMC1_D0_PORT149,	GPIO_FN_MMC1_D1_PORT148,
-	GPIO_FN_MMC1_D2_PORT147,	GPIO_FN_MMC1_D3_PORT146,
-	GPIO_FN_MMC1_D4_PORT145,	GPIO_FN_MMC1_D5_PORT144,
-	GPIO_FN_MMC1_D6_PORT143,	GPIO_FN_MMC1_D7_PORT142,
-	GPIO_FN_MMC1_CLK_PORT103,
-	GPIO_FN_MMC1_CMD_PORT104,	/* MSEL4CR_15_1 */
-
 	/* MSIOF0 */
 	GPIO_FN_MSIOF0_SS1,	GPIO_FN_MSIOF0_SS2,
 	GPIO_FN_MSIOF0_RXD,	GPIO_FN_MSIOF0_TXD,
@@ -606,6 +532,15 @@ enum {
 	SHDMA_SLAVE_USBHS_RX,
 };
 
+extern void r8a7740_meram_workaround(void);
+extern void r8a7740_init_irq(void);
+extern void r8a7740_map_io(void);
+extern void r8a7740_add_early_devices(void);
+extern void r8a7740_add_standard_devices(void);
+extern void r8a7740_clock_init(u8 md_ck);
+extern void r8a7740_pinmux_init(void);
+extern void r8a7740_pm_init(void);
+
 #ifdef CONFIG_PM
 extern void __init r8a7740_init_pm_domains(void);
 #else
diff --git a/arch/arm/mach-shmobile/include/mach/r8a7778.h b/arch/arm/mach-shmobile/include/mach/r8a7778.h
new file mode 100644
index 0000000..e0c6205
--- /dev/null
+++ b/arch/arm/mach-shmobile/include/mach/r8a7778.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2013  Renesas Solutions Corp.
+ * Copyright (C) 2013  Kuninori Morimoto <kuninori.morimoto.gx@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
+ * 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
+ */
+#ifndef __ASM_R8A7778_H__
+#define __ASM_R8A7778_H__
+
+extern void r8a7778_add_standard_devices(void);
+extern void r8a7778_add_standard_devices_dt(void);
+extern void r8a7778_init_delay(void);
+extern void r8a7778_init_irq(void);
+extern void r8a7778_init_irq_dt(void);
+extern void r8a7778_clock_init(void);
+extern void r8a7778_init_irq_extpin(int irlm);
+
+#endif /* __ASM_R8A7778_H__ */
diff --git a/arch/arm/mach-shmobile/include/mach/r8a7779.h b/arch/arm/mach-shmobile/include/mach/r8a7779.h
index 8ab0cd6..945299e 100644
--- a/arch/arm/mach-shmobile/include/mach/r8a7779.h
+++ b/arch/arm/mach-shmobile/include/mach/r8a7779.h
@@ -4,327 +4,6 @@
 #include <linux/sh_clk.h>
 #include <linux/pm_domain.h>
 
-/* Pin Function Controller:
- * GPIO_FN_xx - GPIO used to select pin function
- * GPIO_GP_x_x - GPIO mapped to real I/O pin on CPU
- */
-enum {
-	GPIO_GP_0_0, GPIO_GP_0_1, GPIO_GP_0_2, GPIO_GP_0_3,
-	GPIO_GP_0_4, GPIO_GP_0_5, GPIO_GP_0_6, GPIO_GP_0_7,
-	GPIO_GP_0_8, GPIO_GP_0_9, GPIO_GP_0_10, GPIO_GP_0_11,
-	GPIO_GP_0_12, GPIO_GP_0_13, GPIO_GP_0_14, GPIO_GP_0_15,
-	GPIO_GP_0_16, GPIO_GP_0_17, GPIO_GP_0_18, GPIO_GP_0_19,
-	GPIO_GP_0_20, GPIO_GP_0_21, GPIO_GP_0_22, GPIO_GP_0_23,
-	GPIO_GP_0_24, GPIO_GP_0_25, GPIO_GP_0_26, GPIO_GP_0_27,
-	GPIO_GP_0_28, GPIO_GP_0_29, GPIO_GP_0_30, GPIO_GP_0_31,
-
-	GPIO_GP_1_0, GPIO_GP_1_1, GPIO_GP_1_2, GPIO_GP_1_3,
-	GPIO_GP_1_4, GPIO_GP_1_5, GPIO_GP_1_6, GPIO_GP_1_7,
-	GPIO_GP_1_8, GPIO_GP_1_9, GPIO_GP_1_10, GPIO_GP_1_11,
-	GPIO_GP_1_12, GPIO_GP_1_13, GPIO_GP_1_14, GPIO_GP_1_15,
-	GPIO_GP_1_16, GPIO_GP_1_17, GPIO_GP_1_18, GPIO_GP_1_19,
-	GPIO_GP_1_20, GPIO_GP_1_21, GPIO_GP_1_22, GPIO_GP_1_23,
-	GPIO_GP_1_24, GPIO_GP_1_25, GPIO_GP_1_26, GPIO_GP_1_27,
-	GPIO_GP_1_28, GPIO_GP_1_29, GPIO_GP_1_30, GPIO_GP_1_31,
-
-	GPIO_GP_2_0, GPIO_GP_2_1, GPIO_GP_2_2, GPIO_GP_2_3,
-	GPIO_GP_2_4, GPIO_GP_2_5, GPIO_GP_2_6, GPIO_GP_2_7,
-	GPIO_GP_2_8, GPIO_GP_2_9, GPIO_GP_2_10, GPIO_GP_2_11,
-	GPIO_GP_2_12, GPIO_GP_2_13, GPIO_GP_2_14, GPIO_GP_2_15,
-	GPIO_GP_2_16, GPIO_GP_2_17, GPIO_GP_2_18, GPIO_GP_2_19,
-	GPIO_GP_2_20, GPIO_GP_2_21, GPIO_GP_2_22, GPIO_GP_2_23,
-	GPIO_GP_2_24, GPIO_GP_2_25, GPIO_GP_2_26, GPIO_GP_2_27,
-	GPIO_GP_2_28, GPIO_GP_2_29, GPIO_GP_2_30, GPIO_GP_2_31,
-
-	GPIO_GP_3_0, GPIO_GP_3_1, GPIO_GP_3_2, GPIO_GP_3_3,
-	GPIO_GP_3_4, GPIO_GP_3_5, GPIO_GP_3_6, GPIO_GP_3_7,
-	GPIO_GP_3_8, GPIO_GP_3_9, GPIO_GP_3_10, GPIO_GP_3_11,
-	GPIO_GP_3_12, GPIO_GP_3_13, GPIO_GP_3_14, GPIO_GP_3_15,
-	GPIO_GP_3_16, GPIO_GP_3_17, GPIO_GP_3_18, GPIO_GP_3_19,
-	GPIO_GP_3_20, GPIO_GP_3_21, GPIO_GP_3_22, GPIO_GP_3_23,
-	GPIO_GP_3_24, GPIO_GP_3_25, GPIO_GP_3_26, GPIO_GP_3_27,
-	GPIO_GP_3_28, GPIO_GP_3_29, GPIO_GP_3_30, GPIO_GP_3_31,
-
-	GPIO_GP_4_0, GPIO_GP_4_1, GPIO_GP_4_2, GPIO_GP_4_3,
-	GPIO_GP_4_4, GPIO_GP_4_5, GPIO_GP_4_6, GPIO_GP_4_7,
-	GPIO_GP_4_8, GPIO_GP_4_9, GPIO_GP_4_10, GPIO_GP_4_11,
-	GPIO_GP_4_12, GPIO_GP_4_13, GPIO_GP_4_14, GPIO_GP_4_15,
-	GPIO_GP_4_16, GPIO_GP_4_17, GPIO_GP_4_18, GPIO_GP_4_19,
-	GPIO_GP_4_20, GPIO_GP_4_21, GPIO_GP_4_22, GPIO_GP_4_23,
-	GPIO_GP_4_24, GPIO_GP_4_25, GPIO_GP_4_26, GPIO_GP_4_27,
-	GPIO_GP_4_28, GPIO_GP_4_29, GPIO_GP_4_30, GPIO_GP_4_31,
-
-	GPIO_GP_5_0, GPIO_GP_5_1, GPIO_GP_5_2, GPIO_GP_5_3,
-	GPIO_GP_5_4, GPIO_GP_5_5, GPIO_GP_5_6, GPIO_GP_5_7,
-	GPIO_GP_5_8, GPIO_GP_5_9, GPIO_GP_5_10, GPIO_GP_5_11,
-	GPIO_GP_5_12, GPIO_GP_5_13, GPIO_GP_5_14, GPIO_GP_5_15,
-	GPIO_GP_5_16, GPIO_GP_5_17, GPIO_GP_5_18, GPIO_GP_5_19,
-	GPIO_GP_5_20, GPIO_GP_5_21, GPIO_GP_5_22, GPIO_GP_5_23,
-	GPIO_GP_5_24, GPIO_GP_5_25, GPIO_GP_5_26, GPIO_GP_5_27,
-	GPIO_GP_5_28, GPIO_GP_5_29, GPIO_GP_5_30, GPIO_GP_5_31,
-
-	GPIO_GP_6_0, GPIO_GP_6_1, GPIO_GP_6_2, GPIO_GP_6_3,
-	GPIO_GP_6_4, GPIO_GP_6_5, GPIO_GP_6_6, GPIO_GP_6_7,
-	GPIO_GP_6_8,
-
-	GPIO_FN_AVS1, GPIO_FN_AVS2, GPIO_FN_A17, GPIO_FN_A18,
-	GPIO_FN_A19,
-
-	/* IPSR0 */
-	GPIO_FN_USB_PENC2, GPIO_FN_SCK0, GPIO_FN_PWM1, GPIO_FN_PWMFSW0,
-	GPIO_FN_SCIF_CLK, GPIO_FN_TCLK0_C, GPIO_FN_BS, GPIO_FN_SD1_DAT2,
-	GPIO_FN_MMC0_D2, GPIO_FN_FD2, GPIO_FN_ATADIR0, GPIO_FN_SDSELF,
-	GPIO_FN_HCTS1, GPIO_FN_TX4_C, GPIO_FN_A0, GPIO_FN_SD1_DAT3,
-	GPIO_FN_MMC0_D3, GPIO_FN_FD3, GPIO_FN_A20, GPIO_FN_TX5_D,
-	GPIO_FN_HSPI_TX2_B, GPIO_FN_A21, GPIO_FN_SCK5_D, GPIO_FN_HSPI_CLK2_B,
-	GPIO_FN_A22, GPIO_FN_RX5_D, GPIO_FN_HSPI_RX2_B, GPIO_FN_VI1_R0,
-	GPIO_FN_A23, GPIO_FN_FCLE, GPIO_FN_HSPI_CLK2, GPIO_FN_VI1_R1,
-	GPIO_FN_A24, GPIO_FN_SD1_CD, GPIO_FN_MMC0_D4, GPIO_FN_FD4,
-	GPIO_FN_HSPI_CS2, GPIO_FN_VI1_R2, GPIO_FN_SSI_WS78_B, GPIO_FN_A25,
-	GPIO_FN_SD1_WP, GPIO_FN_MMC0_D5, GPIO_FN_FD5, GPIO_FN_HSPI_RX2,
-	GPIO_FN_VI1_R3, GPIO_FN_TX5_B, GPIO_FN_SSI_SDATA7_B, GPIO_FN_CTS0_B,
-	GPIO_FN_CLKOUT, GPIO_FN_TX3C_IRDA_TX_C, GPIO_FN_PWM0_B, GPIO_FN_CS0,
-	GPIO_FN_HSPI_CS2_B, GPIO_FN_CS1_A26, GPIO_FN_HSPI_TX2,
-	GPIO_FN_SDSELF_B, GPIO_FN_RD_WR, GPIO_FN_FWE, GPIO_FN_ATAG0,
-	GPIO_FN_VI1_R7, GPIO_FN_HRTS1, GPIO_FN_RX4_C,
-
-	/* IPSR1 */
-	GPIO_FN_EX_CS0, GPIO_FN_RX3_C_IRDA_RX_C, GPIO_FN_MMC0_D6,
-	GPIO_FN_FD6, GPIO_FN_EX_CS1, GPIO_FN_MMC0_D7, GPIO_FN_FD7,
-	GPIO_FN_EX_CS2, GPIO_FN_SD1_CLK, GPIO_FN_MMC0_CLK, GPIO_FN_FALE,
-	GPIO_FN_ATACS00, GPIO_FN_EX_CS3, GPIO_FN_SD1_CMD, GPIO_FN_MMC0_CMD,
-	GPIO_FN_FRE, GPIO_FN_ATACS10, GPIO_FN_VI1_R4, GPIO_FN_RX5_B,
-	GPIO_FN_HSCK1, GPIO_FN_SSI_SDATA8_B, GPIO_FN_RTS0_B_TANS_B,
-	GPIO_FN_SSI_SDATA9, GPIO_FN_EX_CS4, GPIO_FN_SD1_DAT0, GPIO_FN_MMC0_D0,
-	GPIO_FN_FD0, GPIO_FN_ATARD0, GPIO_FN_VI1_R5, GPIO_FN_SCK5_B,
-	GPIO_FN_HTX1, GPIO_FN_TX2_E, GPIO_FN_TX0_B, GPIO_FN_SSI_SCK9,
-	GPIO_FN_EX_CS5, GPIO_FN_SD1_DAT1, GPIO_FN_MMC0_D1, GPIO_FN_FD1,
-	GPIO_FN_ATAWR0, GPIO_FN_VI1_R6, GPIO_FN_HRX1, GPIO_FN_RX2_E,
-	GPIO_FN_RX0_B, GPIO_FN_SSI_WS9, GPIO_FN_MLB_CLK, GPIO_FN_PWM2,
-	GPIO_FN_SCK4, GPIO_FN_MLB_SIG, GPIO_FN_PWM3, GPIO_FN_TX4,
-	GPIO_FN_MLB_DAT, GPIO_FN_PWM4, GPIO_FN_RX4, GPIO_FN_HTX0,
-	GPIO_FN_TX1, GPIO_FN_SDATA, GPIO_FN_CTS0_C, GPIO_FN_SUB_TCK,
-	GPIO_FN_CC5_STATE2, GPIO_FN_CC5_STATE10, GPIO_FN_CC5_STATE18,
-	GPIO_FN_CC5_STATE26, GPIO_FN_CC5_STATE34,
-
-	/* IPSR2 */
-	GPIO_FN_HRX0, GPIO_FN_RX1, GPIO_FN_SCKZ, GPIO_FN_RTS0_C_TANS_C,
-	GPIO_FN_SUB_TDI, GPIO_FN_CC5_STATE3, GPIO_FN_CC5_STATE11,
-	GPIO_FN_CC5_STATE19, GPIO_FN_CC5_STATE27, GPIO_FN_CC5_STATE35,
-	GPIO_FN_HSCK0, GPIO_FN_SCK1, GPIO_FN_MTS, GPIO_FN_PWM5,
-	GPIO_FN_SCK0_C, GPIO_FN_SSI_SDATA9_B, GPIO_FN_SUB_TDO,
-	GPIO_FN_CC5_STATE0, GPIO_FN_CC5_STATE8, GPIO_FN_CC5_STATE16,
-	GPIO_FN_CC5_STATE24, GPIO_FN_CC5_STATE32, GPIO_FN_HCTS0, GPIO_FN_CTS1,
-	GPIO_FN_STM, GPIO_FN_PWM0_D, GPIO_FN_RX0_C, GPIO_FN_SCIF_CLK_C,
-	GPIO_FN_SUB_TRST, GPIO_FN_TCLK1_B, GPIO_FN_CC5_OSCOUT, GPIO_FN_HRTS0,
-	GPIO_FN_RTS1_TANS, GPIO_FN_MDATA, GPIO_FN_TX0_C, GPIO_FN_SUB_TMS,
-	GPIO_FN_CC5_STATE1, GPIO_FN_CC5_STATE9, GPIO_FN_CC5_STATE17,
-	GPIO_FN_CC5_STATE25, GPIO_FN_CC5_STATE33, GPIO_FN_DU0_DR0,
-	GPIO_FN_LCDOUT0, GPIO_FN_DREQ0, GPIO_FN_GPS_CLK_B, GPIO_FN_AUDATA0,
-	GPIO_FN_TX5_C, GPIO_FN_DU0_DR1,	GPIO_FN_LCDOUT1, GPIO_FN_DACK0,
-	GPIO_FN_DRACK0, GPIO_FN_GPS_SIGN_B, GPIO_FN_AUDATA1, GPIO_FN_RX5_C,
-	GPIO_FN_DU0_DR2, GPIO_FN_LCDOUT2, GPIO_FN_DU0_DR3, GPIO_FN_LCDOUT3,
-	GPIO_FN_DU0_DR4, GPIO_FN_LCDOUT4, GPIO_FN_DU0_DR5, GPIO_FN_LCDOUT5,
-	GPIO_FN_DU0_DR6, GPIO_FN_LCDOUT6, GPIO_FN_DU0_DR7, GPIO_FN_LCDOUT7,
-	GPIO_FN_DU0_DG0, GPIO_FN_LCDOUT8, GPIO_FN_DREQ1, GPIO_FN_SCL2,
-	GPIO_FN_AUDATA2,
-
-	/* IPSR3 */
-	GPIO_FN_DU0_DG1, GPIO_FN_LCDOUT9, GPIO_FN_DACK1, GPIO_FN_SDA2,
-	GPIO_FN_AUDATA3, GPIO_FN_DU0_DG2, GPIO_FN_LCDOUT10, GPIO_FN_DU0_DG3,
-	GPIO_FN_LCDOUT11, GPIO_FN_DU0_DG4, GPIO_FN_LCDOUT12, GPIO_FN_DU0_DG5,
-	GPIO_FN_LCDOUT13, GPIO_FN_DU0_DG6, GPIO_FN_LCDOUT14, GPIO_FN_DU0_DG7,
-	GPIO_FN_LCDOUT15, GPIO_FN_DU0_DB0, GPIO_FN_LCDOUT16, GPIO_FN_EX_WAIT1,
-	GPIO_FN_SCL1, GPIO_FN_TCLK1, GPIO_FN_AUDATA4, GPIO_FN_DU0_DB1,
-	GPIO_FN_LCDOUT17, GPIO_FN_EX_WAIT2, GPIO_FN_SDA1, GPIO_FN_GPS_MAG_B,
-	GPIO_FN_AUDATA5, GPIO_FN_SCK5_C, GPIO_FN_DU0_DB2, GPIO_FN_LCDOUT18,
-	GPIO_FN_DU0_DB3, GPIO_FN_LCDOUT19, GPIO_FN_DU0_DB4, GPIO_FN_LCDOUT20,
-	GPIO_FN_DU0_DB5, GPIO_FN_LCDOUT21, GPIO_FN_DU0_DB6, GPIO_FN_LCDOUT22,
-	GPIO_FN_DU0_DB7, GPIO_FN_LCDOUT23, GPIO_FN_DU0_DOTCLKIN,
-	GPIO_FN_QSTVA_QVS, GPIO_FN_TX3_D_IRDA_TX_D, GPIO_FN_SCL3_B,
-	GPIO_FN_DU0_DOTCLKOUT0, GPIO_FN_QCLK, GPIO_FN_DU0_DOTCLKOUT1,
-	GPIO_FN_QSTVB_QVE, GPIO_FN_RX3_D_IRDA_RX_D, GPIO_FN_SDA3_B,
-	GPIO_FN_SDA2_C, GPIO_FN_DACK0_B, GPIO_FN_DRACK0_B,
-	GPIO_FN_DU0_EXHSYNC_DU0_HSYNC, GPIO_FN_QSTH_QHS,
-	GPIO_FN_DU0_EXVSYNC_DU0_VSYNC, GPIO_FN_QSTB_QHE,
-	GPIO_FN_DU0_EXODDF_DU0_ODDF_DISP_CDE, GPIO_FN_QCPV_QDE,
-	GPIO_FN_CAN1_TX, GPIO_FN_TX2_C, GPIO_FN_SCL2_C, GPIO_FN_REMOCON,
-
-	/* IPSR4 */
-	GPIO_FN_DU0_DISP, GPIO_FN_QPOLA, GPIO_FN_CAN_CLK_C, GPIO_FN_SCK2_C,
-	GPIO_FN_DU0_CDE, GPIO_FN_QPOLB, GPIO_FN_CAN1_RX, GPIO_FN_RX2_C,
-	GPIO_FN_DREQ0_B, GPIO_FN_SSI_SCK78_B, GPIO_FN_SCK0_B, GPIO_FN_DU1_DR0,
-	GPIO_FN_VI2_DATA0_VI2_B0, GPIO_FN_PWM6, GPIO_FN_SD3_CLK,
-	GPIO_FN_TX3_E_IRDA_TX_E, GPIO_FN_AUDCK, GPIO_FN_PWMFSW0_B,
-	GPIO_FN_DU1_DR1, GPIO_FN_VI2_DATA1_VI2_B1, GPIO_FN_PWM0,
-	GPIO_FN_SD3_CMD, GPIO_FN_RX3_E_IRDA_RX_E, GPIO_FN_AUDSYNC,
-	GPIO_FN_CTS0_D, GPIO_FN_DU1_DR2, GPIO_FN_VI2_G0, GPIO_FN_DU1_DR3,
-	GPIO_FN_VI2_G1, GPIO_FN_DU1_DR4, GPIO_FN_VI2_G2, GPIO_FN_DU1_DR5,
-	GPIO_FN_VI2_G3, GPIO_FN_DU1_DR6, GPIO_FN_VI2_G4, GPIO_FN_DU1_DR7,
-	GPIO_FN_VI2_G5, GPIO_FN_DU1_DG0, GPIO_FN_VI2_DATA2_VI2_B2,
-	GPIO_FN_SCL1_B, GPIO_FN_SD3_DAT2, GPIO_FN_SCK3_E, GPIO_FN_AUDATA6,
-	GPIO_FN_TX0_D, GPIO_FN_DU1_DG1, GPIO_FN_VI2_DATA3_VI2_B3,
-	GPIO_FN_SDA1_B, GPIO_FN_SD3_DAT3, GPIO_FN_SCK5, GPIO_FN_AUDATA7,
-	GPIO_FN_RX0_D, GPIO_FN_DU1_DG2,	GPIO_FN_VI2_G6, GPIO_FN_DU1_DG3,
-	GPIO_FN_VI2_G7, GPIO_FN_DU1_DG4, GPIO_FN_VI2_R0, GPIO_FN_DU1_DG5,
-	GPIO_FN_VI2_R1, GPIO_FN_DU1_DG6, GPIO_FN_VI2_R2, GPIO_FN_DU1_DG7,
-	GPIO_FN_VI2_R3, GPIO_FN_DU1_DB0, GPIO_FN_VI2_DATA4_VI2_B4,
-	GPIO_FN_SCL2_B, GPIO_FN_SD3_DAT0, GPIO_FN_TX5, GPIO_FN_SCK0_D,
-
-	/* IPSR5 */
-	GPIO_FN_DU1_DB1, GPIO_FN_VI2_DATA5_VI2_B5, GPIO_FN_SDA2_B,
-	GPIO_FN_SD3_DAT1, GPIO_FN_RX5, GPIO_FN_RTS0_D_TANS_D,
-	GPIO_FN_DU1_DB2, GPIO_FN_VI2_R4, GPIO_FN_DU1_DB3, GPIO_FN_VI2_R5,
-	GPIO_FN_DU1_DB4, GPIO_FN_VI2_R6, GPIO_FN_DU1_DB5, GPIO_FN_VI2_R7,
-	GPIO_FN_DU1_DB6, GPIO_FN_SCL2_D, GPIO_FN_DU1_DB7, GPIO_FN_SDA2_D,
-	GPIO_FN_DU1_DOTCLKIN, GPIO_FN_VI2_CLKENB, GPIO_FN_HSPI_CS1,
-	GPIO_FN_SCL1_D, GPIO_FN_DU1_DOTCLKOUT, GPIO_FN_VI2_FIELD,
-	GPIO_FN_SDA1_D, GPIO_FN_DU1_EXHSYNC_DU1_HSYNC, GPIO_FN_VI2_HSYNC,
-	GPIO_FN_VI3_HSYNC, GPIO_FN_DU1_EXVSYNC_DU1_VSYNC, GPIO_FN_VI2_VSYNC,
-	GPIO_FN_VI3_VSYNC, GPIO_FN_DU1_EXODDF_DU1_ODDF_DISP_CDE,
-	GPIO_FN_VI2_CLK, GPIO_FN_TX3_B_IRDA_TX_B, GPIO_FN_SD3_CD,
-	GPIO_FN_HSPI_TX1, GPIO_FN_VI1_CLKENB, GPIO_FN_VI3_CLKENB,
-	GPIO_FN_AUDIO_CLKC, GPIO_FN_TX2_D, GPIO_FN_SPEEDIN,
-	GPIO_FN_GPS_SIGN_D, GPIO_FN_DU1_DISP, GPIO_FN_VI2_DATA6_VI2_B6,
-	GPIO_FN_TCLK0, GPIO_FN_QSTVA_B_QVS_B, GPIO_FN_HSPI_CLK1,
-	GPIO_FN_SCK2_D, GPIO_FN_AUDIO_CLKOUT_B, GPIO_FN_GPS_MAG_D,
-	GPIO_FN_DU1_CDE, GPIO_FN_VI2_DATA7_VI2_B7, GPIO_FN_RX3_B_IRDA_RX_B,
-	GPIO_FN_SD3_WP, GPIO_FN_HSPI_RX1, GPIO_FN_VI1_FIELD, GPIO_FN_VI3_FIELD,
-	GPIO_FN_AUDIO_CLKOUT, GPIO_FN_RX2_D, GPIO_FN_GPS_CLK_C,
-	GPIO_FN_GPS_CLK_D, GPIO_FN_AUDIO_CLKA, GPIO_FN_CAN_TXCLK,
-	GPIO_FN_AUDIO_CLKB, GPIO_FN_USB_OVC2, GPIO_FN_CAN_DEBUGOUT0,
-	GPIO_FN_MOUT0,
-
-	/* IPSR6 */
-	GPIO_FN_SSI_SCK0129, GPIO_FN_CAN_DEBUGOUT1, GPIO_FN_MOUT1,
-	GPIO_FN_SSI_WS0129, GPIO_FN_CAN_DEBUGOUT2, GPIO_FN_MOUT2,
-	GPIO_FN_SSI_SDATA0, GPIO_FN_CAN_DEBUGOUT3, GPIO_FN_MOUT5,
-	GPIO_FN_SSI_SDATA1, GPIO_FN_CAN_DEBUGOUT4, GPIO_FN_MOUT6,
-	GPIO_FN_SSI_SDATA2, GPIO_FN_CAN_DEBUGOUT5, GPIO_FN_SSI_SCK34,
-	GPIO_FN_CAN_DEBUGOUT6, GPIO_FN_CAN0_TX_B, GPIO_FN_IERX,
-	GPIO_FN_SSI_SCK9_C, GPIO_FN_SSI_WS34, GPIO_FN_CAN_DEBUGOUT7,
-	GPIO_FN_CAN0_RX_B, GPIO_FN_IETX, GPIO_FN_SSI_WS9_C,
-	GPIO_FN_SSI_SDATA3, GPIO_FN_PWM0_C, GPIO_FN_CAN_DEBUGOUT8,
-	GPIO_FN_CAN_CLK_B, GPIO_FN_IECLK, GPIO_FN_SCIF_CLK_B, GPIO_FN_TCLK0_B,
-	GPIO_FN_SSI_SDATA4, GPIO_FN_CAN_DEBUGOUT9, GPIO_FN_SSI_SDATA9_C,
-	GPIO_FN_SSI_SCK5, GPIO_FN_ADICLK, GPIO_FN_CAN_DEBUGOUT10,
-	GPIO_FN_SCK3, GPIO_FN_TCLK0_D, GPIO_FN_SSI_WS5, GPIO_FN_ADICS_SAMP,
-	GPIO_FN_CAN_DEBUGOUT11, GPIO_FN_TX3_IRDA_TX, GPIO_FN_SSI_SDATA5,
-	GPIO_FN_ADIDATA, GPIO_FN_CAN_DEBUGOUT12, GPIO_FN_RX3_IRDA_RX,
-	GPIO_FN_SSI_SCK6, GPIO_FN_ADICHS0, GPIO_FN_CAN0_TX, GPIO_FN_IERX_B,
-
-	/* IPSR7 */
-	GPIO_FN_SSI_WS6, GPIO_FN_ADICHS1, GPIO_FN_CAN0_RX, GPIO_FN_IETX_B,
-	GPIO_FN_SSI_SDATA6, GPIO_FN_ADICHS2, GPIO_FN_CAN_CLK, GPIO_FN_IECLK_B,
-	GPIO_FN_SSI_SCK78, GPIO_FN_CAN_DEBUGOUT13, GPIO_FN_IRQ0_B,
-	GPIO_FN_SSI_SCK9_B, GPIO_FN_HSPI_CLK1_C, GPIO_FN_SSI_WS78,
-	GPIO_FN_CAN_DEBUGOUT14, GPIO_FN_IRQ1_B, GPIO_FN_SSI_WS9_B,
-	GPIO_FN_HSPI_CS1_C, GPIO_FN_SSI_SDATA7, GPIO_FN_CAN_DEBUGOUT15,
-	GPIO_FN_IRQ2_B, GPIO_FN_TCLK1_C, GPIO_FN_HSPI_TX1_C,
-	GPIO_FN_SSI_SDATA8, GPIO_FN_VSP, GPIO_FN_IRQ3_B, GPIO_FN_HSPI_RX1_C,
-	GPIO_FN_SD0_CLK, GPIO_FN_ATACS01, GPIO_FN_SCK1_B, GPIO_FN_SD0_CMD,
-	GPIO_FN_ATACS11, GPIO_FN_TX1_B, GPIO_FN_CC5_TDO, GPIO_FN_SD0_DAT0,
-	GPIO_FN_ATADIR1, GPIO_FN_RX1_B, GPIO_FN_CC5_TRST, GPIO_FN_SD0_DAT1,
-	GPIO_FN_ATAG1, GPIO_FN_SCK2_B, GPIO_FN_CC5_TMS, GPIO_FN_SD0_DAT2,
-	GPIO_FN_ATARD1,	GPIO_FN_TX2_B, GPIO_FN_CC5_TCK, GPIO_FN_SD0_DAT3,
-	GPIO_FN_ATAWR1,	GPIO_FN_RX2_B, GPIO_FN_CC5_TDI, GPIO_FN_SD0_CD,
-	GPIO_FN_DREQ2,	GPIO_FN_RTS1_B_TANS_B, GPIO_FN_SD0_WP, GPIO_FN_DACK2,
-	GPIO_FN_CTS1_B,
-
-	/* IPSR8 */
-	GPIO_FN_HSPI_CLK0, GPIO_FN_CTS0, GPIO_FN_USB_OVC0, GPIO_FN_AD_CLK,
-	GPIO_FN_CC5_STATE4, GPIO_FN_CC5_STATE12, GPIO_FN_CC5_STATE20,
-	GPIO_FN_CC5_STATE28, GPIO_FN_CC5_STATE36, GPIO_FN_HSPI_CS0,
-	GPIO_FN_RTS0_TANS, GPIO_FN_USB_OVC1, GPIO_FN_AD_DI,
-	GPIO_FN_CC5_STATE5, GPIO_FN_CC5_STATE13, GPIO_FN_CC5_STATE21,
-	GPIO_FN_CC5_STATE29, GPIO_FN_CC5_STATE37, GPIO_FN_HSPI_TX0,
-	GPIO_FN_TX0, GPIO_FN_CAN_DEBUG_HW_TRIGGER, GPIO_FN_AD_DO,
-	GPIO_FN_CC5_STATE6, GPIO_FN_CC5_STATE14, GPIO_FN_CC5_STATE22,
-	GPIO_FN_CC5_STATE30, GPIO_FN_CC5_STATE38, GPIO_FN_HSPI_RX0,
-	GPIO_FN_RX0, GPIO_FN_CAN_STEP0, GPIO_FN_AD_NCS, GPIO_FN_CC5_STATE7,
-	GPIO_FN_CC5_STATE15, GPIO_FN_CC5_STATE23, GPIO_FN_CC5_STATE31,
-	GPIO_FN_CC5_STATE39, GPIO_FN_FMCLK, GPIO_FN_RDS_CLK, GPIO_FN_PCMOE,
-	GPIO_FN_BPFCLK, GPIO_FN_PCMWE, GPIO_FN_FMIN, GPIO_FN_RDS_DATA,
-	GPIO_FN_VI0_CLK, GPIO_FN_MMC1_CLK, GPIO_FN_VI0_CLKENB, GPIO_FN_TX1_C,
-	GPIO_FN_HTX1_B, GPIO_FN_MT1_SYNC, GPIO_FN_VI0_FIELD, GPIO_FN_RX1_C,
-	GPIO_FN_HRX1_B, GPIO_FN_VI0_HSYNC, GPIO_FN_VI0_DATA0_B_VI0_B0_B,
-	GPIO_FN_CTS1_C, GPIO_FN_TX4_D, GPIO_FN_MMC1_CMD, GPIO_FN_HSCK1_B,
-	GPIO_FN_VI0_VSYNC, GPIO_FN_VI0_DATA1_B_VI0_B1_B,
-	GPIO_FN_RTS1_C_TANS_C, GPIO_FN_RX4_D, GPIO_FN_PWMFSW0_C,
-
-	/* IPSR9 */
-	GPIO_FN_VI0_DATA0_VI0_B0, GPIO_FN_HRTS1_B, GPIO_FN_MT1_VCXO,
-	GPIO_FN_VI0_DATA1_VI0_B1, GPIO_FN_HCTS1_B, GPIO_FN_MT1_PWM,
-	GPIO_FN_VI0_DATA2_VI0_B2, GPIO_FN_MMC1_D0, GPIO_FN_VI0_DATA3_VI0_B3,
-	GPIO_FN_MMC1_D1, GPIO_FN_VI0_DATA4_VI0_B4, GPIO_FN_MMC1_D2,
-	GPIO_FN_VI0_DATA5_VI0_B5, GPIO_FN_MMC1_D3, GPIO_FN_VI0_DATA6_VI0_B6,
-	GPIO_FN_MMC1_D4, GPIO_FN_ARM_TRACEDATA_0, GPIO_FN_VI0_DATA7_VI0_B7,
-	GPIO_FN_MMC1_D5, GPIO_FN_ARM_TRACEDATA_1, GPIO_FN_VI0_G0,
-	GPIO_FN_SSI_SCK78_C, GPIO_FN_IRQ0, GPIO_FN_ARM_TRACEDATA_2,
-	GPIO_FN_VI0_G1, GPIO_FN_SSI_WS78_C, GPIO_FN_IRQ1,
-	GPIO_FN_ARM_TRACEDATA_3, GPIO_FN_VI0_G2, GPIO_FN_ETH_TXD1,
-	GPIO_FN_MMC1_D6, GPIO_FN_ARM_TRACEDATA_4, GPIO_FN_TS_SPSYNC0,
-	GPIO_FN_VI0_G3, GPIO_FN_ETH_CRS_DV, GPIO_FN_MMC1_D7,
-	GPIO_FN_ARM_TRACEDATA_5, GPIO_FN_TS_SDAT0, GPIO_FN_VI0_G4,
-	GPIO_FN_ETH_TX_EN, GPIO_FN_SD2_DAT0_B, GPIO_FN_ARM_TRACEDATA_6,
-	GPIO_FN_VI0_G5,	GPIO_FN_ETH_RX_ER, GPIO_FN_SD2_DAT1_B,
-	GPIO_FN_ARM_TRACEDATA_7, GPIO_FN_VI0_G6, GPIO_FN_ETH_RXD0,
-	GPIO_FN_SD2_DAT2_B, GPIO_FN_ARM_TRACEDATA_8, GPIO_FN_VI0_G7,
-	GPIO_FN_ETH_RXD1, GPIO_FN_SD2_DAT3_B, GPIO_FN_ARM_TRACEDATA_9,
-
-	/* IPSR10 */
-	GPIO_FN_VI0_R0, GPIO_FN_SSI_SDATA7_C, GPIO_FN_SCK1_C, GPIO_FN_DREQ1_B,
-	GPIO_FN_ARM_TRACEDATA_10, GPIO_FN_DREQ0_C, GPIO_FN_VI0_R1,
-	GPIO_FN_SSI_SDATA8_C, GPIO_FN_DACK1_B, GPIO_FN_ARM_TRACEDATA_11,
-	GPIO_FN_DACK0_C, GPIO_FN_DRACK0_C, GPIO_FN_VI0_R2, GPIO_FN_ETH_LINK,
-	GPIO_FN_SD2_CLK_B, GPIO_FN_IRQ2, GPIO_FN_ARM_TRACEDATA_12,
-	GPIO_FN_VI0_R3, GPIO_FN_ETH_MAGIC, GPIO_FN_SD2_CMD_B, GPIO_FN_IRQ3,
-	GPIO_FN_ARM_TRACEDATA_13, GPIO_FN_VI0_R4, GPIO_FN_ETH_REFCLK,
-	GPIO_FN_SD2_CD_B, GPIO_FN_HSPI_CLK1_B, GPIO_FN_ARM_TRACEDATA_14,
-	GPIO_FN_MT1_CLK, GPIO_FN_TS_SCK0, GPIO_FN_VI0_R5, GPIO_FN_ETH_TXD0,
-	GPIO_FN_SD2_WP_B, GPIO_FN_HSPI_CS1_B, GPIO_FN_ARM_TRACEDATA_15,
-	GPIO_FN_MT1_D, GPIO_FN_TS_SDEN0, GPIO_FN_VI0_R6, GPIO_FN_ETH_MDC,
-	GPIO_FN_DREQ2_C, GPIO_FN_HSPI_TX1_B, GPIO_FN_TRACECLK,
-	GPIO_FN_MT1_BEN, GPIO_FN_PWMFSW0_D, GPIO_FN_VI0_R7, GPIO_FN_ETH_MDIO,
-	GPIO_FN_DACK2_C, GPIO_FN_HSPI_RX1_B, GPIO_FN_SCIF_CLK_D,
-	GPIO_FN_TRACECTL, GPIO_FN_MT1_PEN, GPIO_FN_VI1_CLK, GPIO_FN_SIM_D,
-	GPIO_FN_SDA3, GPIO_FN_VI1_HSYNC, GPIO_FN_VI3_CLK, GPIO_FN_SSI_SCK4,
-	GPIO_FN_GPS_SIGN_C, GPIO_FN_PWMFSW0_E, GPIO_FN_VI1_VSYNC,
-	GPIO_FN_AUDIO_CLKOUT_C, GPIO_FN_SSI_WS4, GPIO_FN_SIM_CLK,
-	GPIO_FN_GPS_MAG_C, GPIO_FN_SPV_TRST, GPIO_FN_SCL3,
-
-	/* IPSR11 */
-	GPIO_FN_VI1_DATA0_VI1_B0, GPIO_FN_SD2_DAT0, GPIO_FN_SIM_RST,
-	GPIO_FN_SPV_TCK, GPIO_FN_ADICLK_B, GPIO_FN_VI1_DATA1_VI1_B1,
-	GPIO_FN_SD2_DAT1, GPIO_FN_MT0_CLK, GPIO_FN_SPV_TMS,
-	GPIO_FN_ADICS_B_SAMP_B, GPIO_FN_VI1_DATA2_VI1_B2, GPIO_FN_SD2_DAT2,
-	GPIO_FN_MT0_D, GPIO_FN_SPVTDI, GPIO_FN_ADIDATA_B,
-	GPIO_FN_VI1_DATA3_VI1_B3, GPIO_FN_SD2_DAT3, GPIO_FN_MT0_BEN,
-	GPIO_FN_SPV_TDO, GPIO_FN_ADICHS0_B, GPIO_FN_VI1_DATA4_VI1_B4,
-	GPIO_FN_SD2_CLK, GPIO_FN_MT0_PEN, GPIO_FN_SPA_TRST,
-	GPIO_FN_HSPI_CLK1_D, GPIO_FN_ADICHS1_B, GPIO_FN_VI1_DATA5_VI1_B5,
-	GPIO_FN_SD2_CMD, GPIO_FN_MT0_SYNC, GPIO_FN_SPA_TCK,
-	GPIO_FN_HSPI_CS1_D, GPIO_FN_ADICHS2_B, GPIO_FN_VI1_DATA6_VI1_B6,
-	GPIO_FN_SD2_CD, GPIO_FN_MT0_VCXO, GPIO_FN_SPA_TMS, GPIO_FN_HSPI_TX1_D,
-	GPIO_FN_VI1_DATA7_VI1_B7, GPIO_FN_SD2_WP, GPIO_FN_MT0_PWM,
-	GPIO_FN_SPA_TDI, GPIO_FN_HSPI_RX1_D, GPIO_FN_VI1_G0, GPIO_FN_VI3_DATA0,
-	GPIO_FN_DU1_DOTCLKOUT1, GPIO_FN_TS_SCK1, GPIO_FN_DREQ2_B, GPIO_FN_TX2,
-	GPIO_FN_SPA_TDO, GPIO_FN_HCTS0_B, GPIO_FN_VI1_G1, GPIO_FN_VI3_DATA1,
-	GPIO_FN_SSI_SCK1, GPIO_FN_TS_SDEN1, GPIO_FN_DACK2_B, GPIO_FN_RX2,
-	GPIO_FN_HRTS0_B,
-
-	/* IPSR12 */
-	GPIO_FN_VI1_G2, GPIO_FN_VI3_DATA2, GPIO_FN_SSI_WS1, GPIO_FN_TS_SPSYNC1,
-	GPIO_FN_SCK2, GPIO_FN_HSCK0_B, GPIO_FN_VI1_G3, GPIO_FN_VI3_DATA3,
-	GPIO_FN_SSI_SCK2, GPIO_FN_TS_SDAT1, GPIO_FN_SCL1_C, GPIO_FN_HTX0_B,
-	GPIO_FN_VI1_G4, GPIO_FN_VI3_DATA4, GPIO_FN_SSI_WS2, GPIO_FN_SDA1_C,
-	GPIO_FN_SIM_RST_B, GPIO_FN_HRX0_B, GPIO_FN_VI1_G5, GPIO_FN_VI3_DATA5,
-	GPIO_FN_GPS_CLK, GPIO_FN_FSE, GPIO_FN_TX4_B, GPIO_FN_SIM_D_B,
-	GPIO_FN_VI1_G6, GPIO_FN_VI3_DATA6, GPIO_FN_GPS_SIGN, GPIO_FN_FRB,
-	GPIO_FN_RX4_B, GPIO_FN_SIM_CLK_B, GPIO_FN_VI1_G7, GPIO_FN_VI3_DATA7,
-	GPIO_FN_GPS_MAG, GPIO_FN_FCE, GPIO_FN_SCK4_B,
-};
-
 struct platform_device;
 
 struct r8a7779_pm_ch {
@@ -343,6 +22,19 @@ static inline struct r8a7779_pm_ch *to_r8a7779_ch(struct generic_pm_domain *d)
 	return &container_of(d, struct r8a7779_pm_domain, genpd)->ch;
 }
 
+extern void r8a7779_init_delay(void);
+extern void r8a7779_init_irq(void);
+extern void r8a7779_init_irq_extpin(int irlm);
+extern void r8a7779_init_irq_dt(void);
+extern void r8a7779_map_io(void);
+extern void r8a7779_earlytimer_init(void);
+extern void r8a7779_add_early_devices(void);
+extern void r8a7779_add_standard_devices(void);
+extern void r8a7779_add_standard_devices_dt(void);
+extern void r8a7779_clock_init(void);
+extern void r8a7779_pinmux_init(void);
+extern void r8a7779_pm_init(void);
+extern void r8a7779_register_twd(void);
 extern int r8a7779_sysc_power_down(struct r8a7779_pm_ch *r8a7779_ch);
 extern int r8a7779_sysc_power_up(struct r8a7779_pm_ch *r8a7779_ch);
 
diff --git a/arch/arm/mach-shmobile/include/mach/r8a7790.h b/arch/arm/mach-shmobile/include/mach/r8a7790.h
new file mode 100644
index 0000000..9bd6f5c
--- /dev/null
+++ b/arch/arm/mach-shmobile/include/mach/r8a7790.h
@@ -0,0 +1,8 @@
+#ifndef __ASM_R8A7790_H__
+#define __ASM_R8A7790_H__
+
+void r8a7790_add_standard_devices(void);
+void r8a7790_clock_init(void);
+void r8a7790_pinmux_init(void);
+
+#endif /* __ASM_R8A7790_H__ */
diff --git a/arch/arm/mach-shmobile/include/mach/sh7372.h b/arch/arm/mach-shmobile/include/mach/sh7372.h
index b582fac..fd7cba0 100644
--- a/arch/arm/mach-shmobile/include/mach/sh7372.h
+++ b/arch/arm/mach-shmobile/include/mach/sh7372.h
@@ -294,21 +294,6 @@ enum {
 	GPIO_FN_D12_NAF12,	GPIO_FN_D13_NAF13,	GPIO_FN_D14_NAF14,
 	GPIO_FN_D15_NAF15,
 
-	/*
-	 * MMCIF(1)		(PORT 84, 85, 86, 87, 88, 89,
-	 *			      90, 91, 92, 99)
-	 */
-	GPIO_FN_MMCD0_0,	GPIO_FN_MMCD0_1,	GPIO_FN_MMCD0_2,
-	GPIO_FN_MMCD0_3,	GPIO_FN_MMCD0_4,	GPIO_FN_MMCD0_5,
-	GPIO_FN_MMCD0_6,	GPIO_FN_MMCD0_7,
-	GPIO_FN_MMCCMD0,	GPIO_FN_MMCCLK0,
-
-	/* MMCIF(2)		(PORT 54, 55, 56, 57, 58, 59, 60, 61, 66, 67) */
-	GPIO_FN_MMCD1_0,	GPIO_FN_MMCD1_1,	GPIO_FN_MMCD1_2,
-	GPIO_FN_MMCD1_3,	GPIO_FN_MMCD1_4,	GPIO_FN_MMCD1_5,
-	GPIO_FN_MMCD1_6,	GPIO_FN_MMCD1_7,
-	GPIO_FN_MMCCLK1,	GPIO_FN_MMCCMD1,
-
 	/* SPU2		(PORT 65) */
 	GPIO_FN_VINT_I,
 
@@ -416,20 +401,6 @@ enum {
 	/* HDMI		(PORT 169, 170) */
 	GPIO_FN_HDMI_HPD,	GPIO_FN_HDMI_CEC,
 
-	/* SDHI0	(PORT 171, 172, 173, 174, 175, 176, 177, 178) */
-	GPIO_FN_SDHICLK0,	GPIO_FN_SDHICD0,
-	GPIO_FN_SDHICMD0,	GPIO_FN_SDHIWP0,
-	GPIO_FN_SDHID0_0,	GPIO_FN_SDHID0_1,
-	GPIO_FN_SDHID0_2,	GPIO_FN_SDHID0_3,
-
-	/* SDHI1	(PORT 179, 180, 181, 182, 183, 184) */
-	GPIO_FN_SDHICLK1,	GPIO_FN_SDHICMD1,	GPIO_FN_SDHID1_0,
-	GPIO_FN_SDHID1_1,	GPIO_FN_SDHID1_2,	GPIO_FN_SDHID1_3,
-
-	/* SDHI2	(PORT 185, 186, 187, 188, 189, 190) */
-	GPIO_FN_SDHICLK2,	GPIO_FN_SDHICMD2,	GPIO_FN_SDHID2_0,
-	GPIO_FN_SDHID2_1,	GPIO_FN_SDHID2_2,	GPIO_FN_SDHID2_3,
-
 	/* SDENC	see MSEL4CR 19 */
 	GPIO_FN_SDENC_CPG,
 	GPIO_FN_SDENC_DV_CLKI,
@@ -478,6 +449,18 @@ extern struct clk sh7372_dv_clki_clk;
 extern struct clk sh7372_dv_clki_div2_clk;
 extern struct clk sh7372_pllc2_clk;
 
+extern void sh7372_init_irq(void);
+extern void sh7372_map_io(void);
+extern void sh7372_earlytimer_init(void);
+extern void sh7372_add_early_devices(void);
+extern void sh7372_add_standard_devices(void);
+extern void sh7372_add_early_devices_dt(void);
+extern void sh7372_add_standard_devices_dt(void);
+extern void sh7372_clock_init(void);
+extern void sh7372_pinmux_init(void);
+extern void sh7372_pm_init(void);
+extern void sh7372_resume_core_standby_sysc(void);
+extern int  sh7372_do_idle_sysc(unsigned long sleep_mode);
 extern void sh7372_intcs_suspend(void);
 extern void sh7372_intcs_resume(void);
 extern void sh7372_intca_suspend(void);
diff --git a/arch/arm/mach-shmobile/include/mach/sh73a0.h b/arch/arm/mach-shmobile/include/mach/sh73a0.h
index 606d31d..eb7a432 100644
--- a/arch/arm/mach-shmobile/include/mach/sh73a0.h
+++ b/arch/arm/mach-shmobile/include/mach/sh73a0.h
@@ -94,8 +94,7 @@ enum {
 	GPIO_PORT305, GPIO_PORT306, GPIO_PORT307, GPIO_PORT308, GPIO_PORT309,
 
 	/* Table 25-1 (Function 0-7) */
-	GPIO_FN_VBUS_0,
-	GPIO_FN_GPI0,
+	GPIO_FN_GPI0 = 310,
 	GPIO_FN_GPI1,
 	GPIO_FN_GPI2,
 	GPIO_FN_GPI3,
@@ -103,15 +102,11 @@ enum {
 	GPIO_FN_GPI5,
 	GPIO_FN_GPI6,
 	GPIO_FN_GPI7,
-	GPIO_FN_SCIFA7_RXD,
-	GPIO_FN_SCIFA7_CTS_,
 	GPIO_FN_GPO7, GPIO_FN_MFG0_OUT2,
 	GPIO_FN_GPO6, GPIO_FN_MFG1_OUT2,
-	GPIO_FN_GPO5, GPIO_FN_SCIFA0_SCK, GPIO_FN_FSICOSLDT3, \
+	GPIO_FN_GPO5,
 	GPIO_FN_PORT16_VIO_CKOR,
-	GPIO_FN_SCIFA0_TXD,
-	GPIO_FN_SCIFA7_TXD,
-	GPIO_FN_SCIFA7_RTS_, GPIO_FN_PORT19_VIO_CKO2,
+	GPIO_FN_PORT19_VIO_CKO2,
 	GPIO_FN_GPO0,
 	GPIO_FN_GPO1,
 	GPIO_FN_GPO2, GPIO_FN_STATUS0,
@@ -119,83 +114,44 @@ enum {
 	GPIO_FN_GPO4, GPIO_FN_STATUS2,
 	GPIO_FN_VINT,
 	GPIO_FN_TCKON,
-	GPIO_FN_XDVFS1, GPIO_FN_PORT27_I2C_SCL2, GPIO_FN_PORT27_I2C_SCL3, \
+	GPIO_FN_XDVFS1,
 	GPIO_FN_MFG0_OUT1, GPIO_FN_PORT27_IROUT,
-	GPIO_FN_XDVFS2, GPIO_FN_PORT28_I2C_SDA2, GPIO_FN_PORT28_I2C_SDA3, \
+	GPIO_FN_XDVFS2,
 	GPIO_FN_PORT28_TPU1TO1,
 	GPIO_FN_SIM_RST, GPIO_FN_PORT29_TPU1TO1,
 	GPIO_FN_SIM_CLK, GPIO_FN_PORT30_VIO_CKOR,
 	GPIO_FN_SIM_D, GPIO_FN_PORT31_IROUT,
-	GPIO_FN_SCIFA4_TXD,
-	GPIO_FN_SCIFA4_RXD, GPIO_FN_XWUP,
-	GPIO_FN_SCIFA4_RTS_,
-	GPIO_FN_SCIFA4_CTS_,
-	GPIO_FN_FSIBOBT, GPIO_FN_FSIBIBT,
-	GPIO_FN_FSIBOLR, GPIO_FN_FSIBILR,
-	GPIO_FN_FSIBOSLD,
-	GPIO_FN_FSIBISLD,
+	GPIO_FN_XWUP,
 	GPIO_FN_VACK,
 	GPIO_FN_XTAL1L,
-	GPIO_FN_SCIFA0_RTS_, GPIO_FN_FSICOSLDT2,
-	GPIO_FN_SCIFA0_RXD,
-	GPIO_FN_SCIFA0_CTS_, GPIO_FN_FSICOSLDT1,
-	GPIO_FN_FSICOBT, GPIO_FN_FSICIBT, GPIO_FN_FSIDOBT, GPIO_FN_FSIDIBT,
-	GPIO_FN_FSICOLR, GPIO_FN_FSICILR, GPIO_FN_FSIDOLR, GPIO_FN_FSIDILR,
-	GPIO_FN_FSICOSLD, GPIO_FN_PORT47_FSICSPDIF,
-	GPIO_FN_FSICISLD, GPIO_FN_FSIDISLD,
-	GPIO_FN_FSIACK, GPIO_FN_PORT49_IRDA_OUT, GPIO_FN_PORT49_IROUT, \
-	GPIO_FN_FSIAOMC,
-	GPIO_FN_FSIAOLR, GPIO_FN_BBIF2_TSYNC2, GPIO_FN_TPU2TO2, GPIO_FN_FSIAILR,
-
-	GPIO_FN_FSIAOBT, GPIO_FN_BBIF2_TSCK2, GPIO_FN_TPU2TO3, GPIO_FN_FSIAIBT,
-	GPIO_FN_FSIAOSLD, GPIO_FN_BBIF2_TXD2,
-	GPIO_FN_FSIASPDIF, GPIO_FN_PORT53_IRDA_IN, GPIO_FN_TPU3TO3, \
-	GPIO_FN_FSIBSPDIF, GPIO_FN_PORT53_FSICSPDIF,
-	GPIO_FN_FSIBCK, GPIO_FN_PORT54_IRDA_FIRSEL, GPIO_FN_TPU3TO2, \
-	GPIO_FN_FSIBOMC, GPIO_FN_FSICCK, GPIO_FN_FSICOMC,
-	GPIO_FN_FSIAISLD, GPIO_FN_TPU0TO0,
+	GPIO_FN_PORT49_IROUT,
+	GPIO_FN_BBIF2_TSYNC2, GPIO_FN_TPU2TO2,
+
+	GPIO_FN_BBIF2_TSCK2, GPIO_FN_TPU2TO3,
+	GPIO_FN_BBIF2_TXD2,
+	GPIO_FN_TPU3TO3,
+	GPIO_FN_TPU3TO2,
+	GPIO_FN_TPU0TO0,
 	GPIO_FN_A0, GPIO_FN_BS_,
-	GPIO_FN_A12, GPIO_FN_PORT58_KEYOUT7, GPIO_FN_TPU4TO2,
-	GPIO_FN_A13, GPIO_FN_PORT59_KEYOUT6, GPIO_FN_TPU0TO1,
-	GPIO_FN_A14, GPIO_FN_KEYOUT5,
-	GPIO_FN_A15, GPIO_FN_KEYOUT4,
-	GPIO_FN_A16, GPIO_FN_KEYOUT3, GPIO_FN_MSIOF0_SS1,
-	GPIO_FN_A17, GPIO_FN_KEYOUT2, GPIO_FN_MSIOF0_TSYNC,
-	GPIO_FN_A18, GPIO_FN_KEYOUT1, GPIO_FN_MSIOF0_TSCK,
-	GPIO_FN_A19, GPIO_FN_KEYOUT0, GPIO_FN_MSIOF0_TXD,
-	GPIO_FN_A20, GPIO_FN_KEYIN0, GPIO_FN_MSIOF0_RSCK,
-	GPIO_FN_A21, GPIO_FN_KEYIN1, GPIO_FN_MSIOF0_RSYNC,
-	GPIO_FN_A22, GPIO_FN_KEYIN2, GPIO_FN_MSIOF0_MCK0,
-	GPIO_FN_A23, GPIO_FN_KEYIN3, GPIO_FN_MSIOF0_MCK1,
-	GPIO_FN_A24, GPIO_FN_KEYIN4, GPIO_FN_MSIOF0_RXD,
-	GPIO_FN_A25, GPIO_FN_KEYIN5, GPIO_FN_MSIOF0_SS2,
-	GPIO_FN_A26, GPIO_FN_KEYIN6,
-	GPIO_FN_KEYIN7,
-	GPIO_FN_D0_NAF0,
-	GPIO_FN_D1_NAF1,
-	GPIO_FN_D2_NAF2,
-	GPIO_FN_D3_NAF3,
-	GPIO_FN_D4_NAF4,
-	GPIO_FN_D5_NAF5,
-	GPIO_FN_D6_NAF6,
-	GPIO_FN_D7_NAF7,
-	GPIO_FN_D8_NAF8,
-	GPIO_FN_D9_NAF9,
-	GPIO_FN_D10_NAF10,
-	GPIO_FN_D11_NAF11,
-	GPIO_FN_D12_NAF12,
-	GPIO_FN_D13_NAF13,
-	GPIO_FN_D14_NAF14,
-	GPIO_FN_D15_NAF15,
-	GPIO_FN_CS4_,
-	GPIO_FN_CS5A_, GPIO_FN_PORT91_RDWR,
-	GPIO_FN_CS5B_, GPIO_FN_FCE1_,
-	GPIO_FN_CS6B_, GPIO_FN_DACK0,
-	GPIO_FN_FCE0_, GPIO_FN_CS6A_,
+	GPIO_FN_A12, GPIO_FN_TPU4TO2,
+	GPIO_FN_A13, GPIO_FN_TPU0TO1,
+	GPIO_FN_A14,
+	GPIO_FN_A15,
+	GPIO_FN_A16, GPIO_FN_MSIOF0_SS1,
+	GPIO_FN_A17, GPIO_FN_MSIOF0_TSYNC,
+	GPIO_FN_A18, GPIO_FN_MSIOF0_TSCK,
+	GPIO_FN_A19, GPIO_FN_MSIOF0_TXD,
+	GPIO_FN_A20, GPIO_FN_MSIOF0_RSCK,
+	GPIO_FN_A21, GPIO_FN_MSIOF0_RSYNC,
+	GPIO_FN_A22, GPIO_FN_MSIOF0_MCK0,
+	GPIO_FN_A23, GPIO_FN_MSIOF0_MCK1,
+	GPIO_FN_A24, GPIO_FN_MSIOF0_RXD,
+	GPIO_FN_A25, GPIO_FN_MSIOF0_SS2,
+	GPIO_FN_A26,
+	GPIO_FN_FCE1_,
+	GPIO_FN_DACK0,
+	GPIO_FN_FCE0_,
 	GPIO_FN_WAIT_, GPIO_FN_DREQ0,
-	GPIO_FN_RD__FSC,
-	GPIO_FN_WE0__FWE, GPIO_FN_RDWR_FWE,
-	GPIO_FN_WE1_,
 	GPIO_FN_FRB,
 	GPIO_FN_CKO,
 	GPIO_FN_NBRSTOUT_,
@@ -204,145 +160,118 @@ enum {
 	GPIO_FN_BBIF2_RXD,
 	GPIO_FN_BBIF2_SYNC,
 	GPIO_FN_BBIF2_SCK,
-	GPIO_FN_SCIFA3_CTS_, GPIO_FN_MFG3_IN2,
-	GPIO_FN_SCIFA3_RXD, GPIO_FN_MFG3_IN1,
-	GPIO_FN_BBIF1_SS2, GPIO_FN_SCIFA3_RTS_, GPIO_FN_MFG3_OUT1,
-	GPIO_FN_SCIFA3_TXD,
+	GPIO_FN_MFG3_IN2,
+	GPIO_FN_MFG3_IN1,
+	GPIO_FN_BBIF1_SS2, GPIO_FN_MFG3_OUT1,
 	GPIO_FN_HSI_RX_DATA, GPIO_FN_BBIF1_RXD,
 	GPIO_FN_HSI_TX_WAKE, GPIO_FN_BBIF1_TSCK,
 	GPIO_FN_HSI_TX_DATA, GPIO_FN_BBIF1_TSYNC,
 	GPIO_FN_HSI_TX_READY, GPIO_FN_BBIF1_TXD,
-	GPIO_FN_HSI_RX_READY, GPIO_FN_BBIF1_RSCK, GPIO_FN_PORT115_I2C_SCL2, \
-	GPIO_FN_PORT115_I2C_SCL3,
-	GPIO_FN_HSI_RX_WAKE, GPIO_FN_BBIF1_RSYNC, GPIO_FN_PORT116_I2C_SDA2, \
-	GPIO_FN_PORT116_I2C_SDA3,
+	GPIO_FN_HSI_RX_READY, GPIO_FN_BBIF1_RSCK,
+	GPIO_FN_HSI_RX_WAKE, GPIO_FN_BBIF1_RSYNC,
 	GPIO_FN_HSI_RX_FLAG, GPIO_FN_BBIF1_SS1, GPIO_FN_BBIF1_FLOW,
 	GPIO_FN_HSI_TX_FLAG,
-	GPIO_FN_VIO_VD, GPIO_FN_PORT128_LCD2VSYN, GPIO_FN_VIO2_VD, \
-	GPIO_FN_LCD2D0,
-
-	GPIO_FN_VIO_HD, GPIO_FN_PORT129_LCD2HSYN, GPIO_FN_PORT129_LCD2CS_, \
-	GPIO_FN_VIO2_HD, GPIO_FN_LCD2D1,
-	GPIO_FN_VIO_D0, GPIO_FN_PORT130_MSIOF2_RXD, GPIO_FN_LCD2D10,
-	GPIO_FN_VIO_D1, GPIO_FN_PORT131_KEYOUT6, GPIO_FN_PORT131_MSIOF2_SS1, \
-	GPIO_FN_PORT131_KEYOUT11, GPIO_FN_LCD2D11,
-	GPIO_FN_VIO_D2, GPIO_FN_PORT132_KEYOUT7, GPIO_FN_PORT132_MSIOF2_SS2, \
-	GPIO_FN_PORT132_KEYOUT10, GPIO_FN_LCD2D12,
-	GPIO_FN_VIO_D3, GPIO_FN_MSIOF2_TSYNC, GPIO_FN_LCD2D13,
-	GPIO_FN_VIO_D4, GPIO_FN_MSIOF2_TXD, GPIO_FN_LCD2D14,
-	GPIO_FN_VIO_D5, GPIO_FN_MSIOF2_TSCK, GPIO_FN_LCD2D15,
-	GPIO_FN_VIO_D6, GPIO_FN_PORT136_KEYOUT8, GPIO_FN_LCD2D16,
-	GPIO_FN_VIO_D7, GPIO_FN_PORT137_KEYOUT9, GPIO_FN_LCD2D17,
-	GPIO_FN_VIO_D8, GPIO_FN_PORT138_KEYOUT8, GPIO_FN_VIO2_D0, \
-	GPIO_FN_LCD2D6,
-	GPIO_FN_VIO_D9, GPIO_FN_PORT139_KEYOUT9, GPIO_FN_VIO2_D1, \
-	GPIO_FN_LCD2D7,
-	GPIO_FN_VIO_D10, GPIO_FN_TPU0TO2, GPIO_FN_VIO2_D2, GPIO_FN_LCD2D8,
-	GPIO_FN_VIO_D11, GPIO_FN_TPU0TO3, GPIO_FN_VIO2_D3, GPIO_FN_LCD2D9,
-	GPIO_FN_VIO_D12, GPIO_FN_PORT142_KEYOUT10, GPIO_FN_VIO2_D4, \
-	GPIO_FN_LCD2D2,
-	GPIO_FN_VIO_D13, GPIO_FN_PORT143_KEYOUT11, GPIO_FN_PORT143_KEYOUT6, \
-	GPIO_FN_VIO2_D5, GPIO_FN_LCD2D3,
-	GPIO_FN_VIO_D14, GPIO_FN_PORT144_KEYOUT7, GPIO_FN_VIO2_D6, \
-	GPIO_FN_LCD2D4,
-	GPIO_FN_VIO_D15, GPIO_FN_TPU1TO3, GPIO_FN_PORT145_LCD2DISP, \
-	GPIO_FN_PORT145_LCD2RS, GPIO_FN_VIO2_D7, GPIO_FN_LCD2D5,
-	GPIO_FN_VIO_CLK, GPIO_FN_LCD2DCK, GPIO_FN_PORT146_LCD2WR_, \
-	GPIO_FN_VIO2_CLK, GPIO_FN_LCD2D18,
-	GPIO_FN_VIO_FIELD, GPIO_FN_LCD2RD_, GPIO_FN_VIO2_FIELD, GPIO_FN_LCD2D19,
+	GPIO_FN_VIO_VD, GPIO_FN_VIO2_VD,
+
+	GPIO_FN_VIO_HD,
+	GPIO_FN_VIO2_HD,
+	GPIO_FN_VIO_D0, GPIO_FN_PORT130_MSIOF2_RXD,
+	GPIO_FN_VIO_D1, GPIO_FN_PORT131_MSIOF2_SS1,
+	GPIO_FN_VIO_D2, GPIO_FN_PORT132_MSIOF2_SS2,
+	GPIO_FN_VIO_D3, GPIO_FN_MSIOF2_TSYNC,
+	GPIO_FN_VIO_D4, GPIO_FN_MSIOF2_TXD,
+	GPIO_FN_VIO_D5, GPIO_FN_MSIOF2_TSCK,
+	GPIO_FN_VIO_D6,
+	GPIO_FN_VIO_D7,
+	GPIO_FN_VIO_D8, GPIO_FN_VIO2_D0,
+	GPIO_FN_VIO_D9, GPIO_FN_VIO2_D1,
+	GPIO_FN_VIO_D10, GPIO_FN_TPU0TO2, GPIO_FN_VIO2_D2,
+	GPIO_FN_VIO_D11, GPIO_FN_TPU0TO3, GPIO_FN_VIO2_D3,
+	GPIO_FN_VIO_D12, GPIO_FN_VIO2_D4,
+	GPIO_FN_VIO_D13,
+	GPIO_FN_VIO2_D5,
+	GPIO_FN_VIO_D14, GPIO_FN_VIO2_D6,
+	GPIO_FN_VIO_D15, GPIO_FN_TPU1TO3,
+	GPIO_FN_VIO2_D7,
+	GPIO_FN_VIO_CLK,
+	GPIO_FN_VIO2_CLK,
+	GPIO_FN_VIO_FIELD, GPIO_FN_VIO2_FIELD,
 	GPIO_FN_VIO_CKO,
-	GPIO_FN_A27, GPIO_FN_PORT149_RDWR, GPIO_FN_MFG0_IN1, \
-	GPIO_FN_PORT149_KEYOUT9,
+	GPIO_FN_A27, GPIO_FN_MFG0_IN1,
 	GPIO_FN_MFG0_IN2,
 	GPIO_FN_TS_SPSYNC3, GPIO_FN_MSIOF2_RSCK,
 	GPIO_FN_TS_SDAT3, GPIO_FN_MSIOF2_RSYNC,
 	GPIO_FN_TPU1TO2, GPIO_FN_TS_SDEN3, GPIO_FN_PORT153_MSIOF2_SS1,
-	GPIO_FN_SCIFA2_TXD1, GPIO_FN_MSIOF2_MCK0,
-	GPIO_FN_SCIFA2_RXD1, GPIO_FN_MSIOF2_MCK1,
-	GPIO_FN_SCIFA2_RTS1_, GPIO_FN_PORT156_MSIOF2_SS2,
-	GPIO_FN_SCIFA2_CTS1_, GPIO_FN_PORT157_MSIOF2_RXD,
-	GPIO_FN_DINT_, GPIO_FN_SCIFA2_SCK1, GPIO_FN_TS_SCK3,
-	GPIO_FN_PORT159_SCIFB_SCK, GPIO_FN_PORT159_SCIFA5_SCK, GPIO_FN_NMI,
-	GPIO_FN_PORT160_SCIFB_TXD, GPIO_FN_PORT160_SCIFA5_TXD,
-	GPIO_FN_PORT161_SCIFB_CTS_, GPIO_FN_PORT161_SCIFA5_CTS_,
-	GPIO_FN_PORT162_SCIFB_RXD, GPIO_FN_PORT162_SCIFA5_RXD,
-	GPIO_FN_PORT163_SCIFB_RTS_, GPIO_FN_PORT163_SCIFA5_RTS_, \
+	GPIO_FN_MSIOF2_MCK0,
+	GPIO_FN_MSIOF2_MCK1,
+	GPIO_FN_PORT156_MSIOF2_SS2,
+	GPIO_FN_PORT157_MSIOF2_RXD,
+	GPIO_FN_DINT_, GPIO_FN_TS_SCK3,
+	GPIO_FN_NMI,
 	GPIO_FN_TPU3TO0,
-	GPIO_FN_LCDD0,
-	GPIO_FN_LCDD1, GPIO_FN_PORT193_SCIFA5_CTS_, GPIO_FN_BBIF2_TSYNC1,
-	GPIO_FN_LCDD2, GPIO_FN_PORT194_SCIFA5_RTS_, GPIO_FN_BBIF2_TSCK1,
-	GPIO_FN_LCDD3, GPIO_FN_PORT195_SCIFA5_RXD, GPIO_FN_BBIF2_TXD1,
-	GPIO_FN_LCDD4, GPIO_FN_PORT196_SCIFA5_TXD,
-	GPIO_FN_LCDD5, GPIO_FN_PORT197_SCIFA5_SCK, GPIO_FN_MFG2_OUT2, \
+	GPIO_FN_BBIF2_TSYNC1,
+	GPIO_FN_BBIF2_TSCK1,
+	GPIO_FN_BBIF2_TXD1,
+	GPIO_FN_MFG2_OUT2,
 	GPIO_FN_TPU2TO1,
-	GPIO_FN_LCDD6,
-	GPIO_FN_LCDD7, GPIO_FN_TPU4TO1, GPIO_FN_MFG4_OUT2,
-	GPIO_FN_LCDD8, GPIO_FN_D16,
-	GPIO_FN_LCDD9, GPIO_FN_D17,
-	GPIO_FN_LCDD10, GPIO_FN_D18,
-	GPIO_FN_LCDD11, GPIO_FN_D19,
-	GPIO_FN_LCDD12, GPIO_FN_D20,
-	GPIO_FN_LCDD13, GPIO_FN_D21,
-	GPIO_FN_LCDD14, GPIO_FN_D22,
-	GPIO_FN_LCDD15, GPIO_FN_PORT207_MSIOF0L_SS1, GPIO_FN_D23,
-	GPIO_FN_LCDD16, GPIO_FN_PORT208_MSIOF0L_SS2, GPIO_FN_D24,
-	GPIO_FN_LCDD17, GPIO_FN_D25,
-	GPIO_FN_LCDD18, GPIO_FN_DREQ2, GPIO_FN_PORT210_MSIOF0L_SS1, GPIO_FN_D26,
-	GPIO_FN_LCDD19, GPIO_FN_PORT211_MSIOF0L_SS2, GPIO_FN_D27,
-	GPIO_FN_LCDD20, GPIO_FN_TS_SPSYNC1, GPIO_FN_MSIOF0L_MCK0, GPIO_FN_D28,
-	GPIO_FN_LCDD21, GPIO_FN_TS_SDAT1, GPIO_FN_MSIOF0L_MCK1, GPIO_FN_D29,
-	GPIO_FN_LCDD22, GPIO_FN_TS_SDEN1, GPIO_FN_MSIOF0L_RSCK, GPIO_FN_D30,
-	GPIO_FN_LCDD23, GPIO_FN_TS_SCK1, GPIO_FN_MSIOF0L_RSYNC, GPIO_FN_D31,
-	GPIO_FN_LCDDCK, GPIO_FN_LCDWR_,
-	GPIO_FN_LCDRD_, GPIO_FN_DACK2, GPIO_FN_PORT217_LCD2RS, \
-	GPIO_FN_MSIOF0L_TSYNC, GPIO_FN_VIO2_FIELD3, GPIO_FN_PORT217_LCD2DISP,
-	GPIO_FN_LCDHSYN, GPIO_FN_LCDCS_, GPIO_FN_LCDCS2_, GPIO_FN_DACK3, \
+	GPIO_FN_TPU4TO1, GPIO_FN_MFG4_OUT2,
+	GPIO_FN_D16,
+	GPIO_FN_D17,
+	GPIO_FN_D18,
+	GPIO_FN_D19,
+	GPIO_FN_D20,
+	GPIO_FN_D21,
+	GPIO_FN_D22,
+	GPIO_FN_PORT207_MSIOF0L_SS1, GPIO_FN_D23,
+	GPIO_FN_PORT208_MSIOF0L_SS2, GPIO_FN_D24,
+	GPIO_FN_D25,
+	GPIO_FN_DREQ2, GPIO_FN_PORT210_MSIOF0L_SS1, GPIO_FN_D26,
+	GPIO_FN_PORT211_MSIOF0L_SS2, GPIO_FN_D27,
+	GPIO_FN_TS_SPSYNC1, GPIO_FN_MSIOF0L_MCK0, GPIO_FN_D28,
+	GPIO_FN_TS_SDAT1, GPIO_FN_MSIOF0L_MCK1, GPIO_FN_D29,
+	GPIO_FN_TS_SDEN1, GPIO_FN_MSIOF0L_RSCK, GPIO_FN_D30,
+	GPIO_FN_TS_SCK1, GPIO_FN_MSIOF0L_RSYNC, GPIO_FN_D31,
+	GPIO_FN_DACK2,
+	GPIO_FN_MSIOF0L_TSYNC, GPIO_FN_VIO2_FIELD3,
+	GPIO_FN_DACK3,
 	GPIO_FN_PORT218_VIO_CKOR,
-	GPIO_FN_LCDDISP, GPIO_FN_LCDRS, GPIO_FN_PORT219_LCD2WR_, \
 	GPIO_FN_DREQ3, GPIO_FN_MSIOF0L_TSCK, GPIO_FN_VIO2_CLK3, \
-	GPIO_FN_LCD2DCK_2,
-	GPIO_FN_LCDVSYN, GPIO_FN_LCDVSYN2,
-	GPIO_FN_LCDLCLK, GPIO_FN_DREQ1, GPIO_FN_PORT221_LCD2CS_, \
+	GPIO_FN_DREQ1,
 	GPIO_FN_PWEN, GPIO_FN_MSIOF0L_RXD, GPIO_FN_VIO2_HD3, \
-	GPIO_FN_PORT221_LCD2HSYN,
-	GPIO_FN_LCDDON, GPIO_FN_LCDDON2, GPIO_FN_DACK1, GPIO_FN_OVCN, \
-	GPIO_FN_MSIOF0L_TXD, GPIO_FN_VIO2_VD3, GPIO_FN_PORT222_LCD2VSYN,
-
-	GPIO_FN_SCIFA1_TXD, GPIO_FN_OVCN2,
-	GPIO_FN_EXTLP, GPIO_FN_SCIFA1_SCK, GPIO_FN_PORT226_VIO_CKO2,
-	GPIO_FN_SCIFA1_RTS_, GPIO_FN_IDIN,
-	GPIO_FN_SCIFA1_RXD,
-	GPIO_FN_SCIFA1_CTS_, GPIO_FN_MFG1_IN1,
-	GPIO_FN_MSIOF1_TXD, GPIO_FN_SCIFA2_TXD2,
-	GPIO_FN_MSIOF1_TSYNC, GPIO_FN_SCIFA2_CTS2_,
-	GPIO_FN_MSIOF1_TSCK, GPIO_FN_SCIFA2_SCK2,
-	GPIO_FN_MSIOF1_RXD, GPIO_FN_SCIFA2_RXD2,
-	GPIO_FN_MSIOF1_RSCK, GPIO_FN_SCIFA2_RTS2_, GPIO_FN_VIO2_CLK2, \
-	GPIO_FN_LCD2D20,
+	GPIO_FN_DACK1, GPIO_FN_OVCN,
+	GPIO_FN_MSIOF0L_TXD, GPIO_FN_VIO2_VD3,
+
+	GPIO_FN_OVCN2,
+	GPIO_FN_EXTLP, GPIO_FN_PORT226_VIO_CKO2,
+	GPIO_FN_IDIN,
+	GPIO_FN_MFG1_IN1,
+	GPIO_FN_MSIOF1_TXD,
+	GPIO_FN_MSIOF1_TSYNC,
+	GPIO_FN_MSIOF1_TSCK,
+	GPIO_FN_MSIOF1_RXD,
+	GPIO_FN_MSIOF1_RSCK, GPIO_FN_VIO2_CLK2,
 	GPIO_FN_MSIOF1_RSYNC, GPIO_FN_MFG1_IN2, GPIO_FN_VIO2_VD2, \
-	GPIO_FN_LCD2D21,
-	GPIO_FN_MSIOF1_MCK0, GPIO_FN_PORT236_I2C_SDA2,
-	GPIO_FN_MSIOF1_MCK1, GPIO_FN_PORT237_I2C_SCL2,
-	GPIO_FN_MSIOF1_SS1, GPIO_FN_VIO2_FIELD2, GPIO_FN_LCD2D22,
-	GPIO_FN_MSIOF1_SS2, GPIO_FN_VIO2_HD2, GPIO_FN_LCD2D23,
-	GPIO_FN_SCIFA6_TXD,
-	GPIO_FN_PORT241_IRDA_OUT, GPIO_FN_PORT241_IROUT, GPIO_FN_MFG4_OUT1, \
+	GPIO_FN_MSIOF1_MCK0,
+	GPIO_FN_MSIOF1_MCK1,
+	GPIO_FN_MSIOF1_SS1, GPIO_FN_VIO2_FIELD2,
+	GPIO_FN_MSIOF1_SS2, GPIO_FN_VIO2_HD2,
+	GPIO_FN_PORT241_IROUT, GPIO_FN_MFG4_OUT1, \
 	GPIO_FN_TPU4TO0,
-	GPIO_FN_PORT242_IRDA_IN, GPIO_FN_MFG4_IN2,
-	GPIO_FN_PORT243_IRDA_FIRSEL, GPIO_FN_PORT243_VIO_CKO2,
-	GPIO_FN_PORT244_SCIFA5_CTS_, GPIO_FN_MFG2_IN1, \
-	GPIO_FN_PORT244_SCIFB_CTS_, GPIO_FN_MSIOF2R_RXD,
-	GPIO_FN_PORT245_SCIFA5_RTS_, GPIO_FN_MFG2_IN2, \
-	GPIO_FN_PORT245_SCIFB_RTS_, GPIO_FN_MSIOF2R_TXD,
-	GPIO_FN_PORT246_SCIFA5_RXD, GPIO_FN_MFG1_OUT1, \
-	GPIO_FN_PORT246_SCIFB_RXD, GPIO_FN_TPU1TO0,
-	GPIO_FN_PORT247_SCIFA5_TXD, GPIO_FN_MFG3_OUT2, \
-	GPIO_FN_PORT247_SCIFB_TXD, GPIO_FN_TPU3TO1,
-	GPIO_FN_PORT248_SCIFA5_SCK, GPIO_FN_MFG2_OUT1, \
-	GPIO_FN_PORT248_SCIFB_SCK, GPIO_FN_TPU2TO0, \
-	GPIO_FN_PORT248_I2C_SCL3, GPIO_FN_MSIOF2R_TSCK,
+	GPIO_FN_MFG4_IN2,
+	GPIO_FN_PORT243_VIO_CKO2,
+	GPIO_FN_MFG2_IN1,
+	GPIO_FN_MSIOF2R_RXD,
+	GPIO_FN_MFG2_IN2,
+	GPIO_FN_MSIOF2R_TXD,
+	GPIO_FN_MFG1_OUT1,
+	GPIO_FN_TPU1TO0,
+	GPIO_FN_MFG3_OUT2,
+	GPIO_FN_TPU3TO1,
+	GPIO_FN_MFG2_OUT1,
+	GPIO_FN_TPU2TO0,
+	GPIO_FN_MSIOF2R_TSCK,
 	GPIO_FN_PORT249_IROUT, GPIO_FN_MFG4_IN1, \
-	GPIO_FN_PORT249_I2C_SDA3, GPIO_FN_MSIOF2R_TSYNC,
+	GPIO_FN_MSIOF2R_TSYNC,
 	GPIO_FN_SDHICLK0,
 	GPIO_FN_SDHICD0,
 	GPIO_FN_SDHID0_0,
@@ -435,54 +364,12 @@ enum {
 	GPIO_FN_IRQ9_MEM_INT,
 	GPIO_FN_IRQ9_MCP_INT,
 	GPIO_FN_A11,
-	GPIO_FN_KEYOUT8,
 	GPIO_FN_TPU4TO3,
 	GPIO_FN_RESETA_N_PU_ON,
 	GPIO_FN_RESETA_N_PU_OFF,
 	GPIO_FN_EDBGREQ_PD,
 	GPIO_FN_EDBGREQ_PU,
 
-	/* Functions with pull-ups */
-	GPIO_FN_KEYIN0_PU,
-	GPIO_FN_KEYIN1_PU,
-	GPIO_FN_KEYIN2_PU,
-	GPIO_FN_KEYIN3_PU,
-	GPIO_FN_KEYIN4_PU,
-	GPIO_FN_KEYIN5_PU,
-	GPIO_FN_KEYIN6_PU,
-	GPIO_FN_KEYIN7_PU,
-	GPIO_FN_SDHICD0_PU,
-	GPIO_FN_SDHID0_0_PU,
-	GPIO_FN_SDHID0_1_PU,
-	GPIO_FN_SDHID0_2_PU,
-	GPIO_FN_SDHID0_3_PU,
-	GPIO_FN_SDHICMD0_PU,
-	GPIO_FN_SDHIWP0_PU,
-	GPIO_FN_SDHID1_0_PU,
-	GPIO_FN_SDHID1_1_PU,
-	GPIO_FN_SDHID1_2_PU,
-	GPIO_FN_SDHID1_3_PU,
-	GPIO_FN_SDHICMD1_PU,
-	GPIO_FN_SDHID2_0_PU,
-	GPIO_FN_SDHID2_1_PU,
-	GPIO_FN_SDHID2_2_PU,
-	GPIO_FN_SDHID2_3_PU,
-	GPIO_FN_SDHICMD2_PU,
-	GPIO_FN_MMCCMD0_PU,
-	GPIO_FN_MMCCMD1_PU,
-	GPIO_FN_MMCD0_0_PU,
-	GPIO_FN_MMCD0_1_PU,
-	GPIO_FN_MMCD0_2_PU,
-	GPIO_FN_MMCD0_3_PU,
-	GPIO_FN_MMCD0_4_PU,
-	GPIO_FN_MMCD0_5_PU,
-	GPIO_FN_MMCD0_6_PU,
-	GPIO_FN_MMCD0_7_PU,
-	GPIO_FN_FSIACK_PU,
-	GPIO_FN_FSIAILR_PU,
-	GPIO_FN_FSIAIBT_PU,
-	GPIO_FN_FSIAISLD_PU,
-
 	/* end of GPIO */
 	GPIO_NR,
 };
@@ -557,6 +444,21 @@ enum {
 #define SH73A0_PINT0_IRQ(irq) ((irq) + 700)
 #define SH73A0_PINT1_IRQ(irq) ((irq) + 732)
 
+extern void sh73a0_init_delay(void);
+extern void sh73a0_init_irq(void);
+extern void sh73a0_init_irq_dt(void);
+extern void sh73a0_map_io(void);
+extern void sh73a0_earlytimer_init(void);
+extern void sh73a0_add_early_devices(void);
+extern void sh73a0_add_standard_devices(void);
+extern void sh73a0_add_standard_devices_dt(void);
+extern void sh73a0_clock_init(void);
+extern void sh73a0_pinmux_init(void);
+extern void sh73a0_pm_init(void);
+extern struct clk sh73a0_extal1_clk;
+extern struct clk sh73a0_extal2_clk;
+extern struct clk sh73a0_extcki_clk;
+extern struct clk sh73a0_extalr_clk;
 extern struct smp_operations sh73a0_smp_ops;
 
 #endif /* __ASM_SH73A0_H__ */
diff --git a/arch/arm/mach-shmobile/intc-r8a7740.c b/arch/arm/mach-shmobile/intc-r8a7740.c
index 9a69a31..b741c84 100644
--- a/arch/arm/mach-shmobile/intc-r8a7740.c
+++ b/arch/arm/mach-shmobile/intc-r8a7740.c
@@ -18,620 +18,39 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-#include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
 #include <linux/io.h>
-#include <linux/sh_intc.h>
-#include <mach/intc.h>
-#include <mach/irqs.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-
-/*
- *		INTCA
- */
-enum {
-	UNUSED_INTCA = 0,
-
-	/* interrupt sources INTCA */
-	DIRC,
-	ATAPI,
-	IIC1_ALI, IIC1_TACKI, IIC1_WAITI, IIC1_DTEI,
-	AP_ARM_COMMTX, AP_ARM_COMMRX,
-	MFI, MFIS,
-	BBIF1, BBIF2,
-	USBHSDMAC,
-	USBF_OUL_SOF, USBF_IXL_INT,
-	SGX540,
-	CMT1_0, CMT1_1, CMT1_2, CMT1_3,
-	CMT2,
-	CMT3,
-	KEYSC,
-	SCIFA0, SCIFA1, SCIFA2, SCIFA3,
-	MSIOF2, MSIOF1,
-	SCIFA4, SCIFA5, SCIFB,
-	FLCTL_FLSTEI, FLCTL_FLTENDI, FLCTL_FLTREQ0I, FLCTL_FLTREQ1I,
-	SDHI0_0, SDHI0_1, SDHI0_2, SDHI0_3,
-	SDHI1_0, SDHI1_1, SDHI1_2, SDHI1_3,
-	AP_ARM_L2CINT,
-	IRDA,
-	TPU0,
-	SCIFA6, SCIFA7,
-	GbEther,
-	ICBS0,
-	DDM,
-	SDHI2_0, SDHI2_1, SDHI2_2, SDHI2_3,
-	RWDT0,
-	DMAC1_1_DEI0, DMAC1_1_DEI1, DMAC1_1_DEI2, DMAC1_1_DEI3,
-	DMAC1_2_DEI4, DMAC1_2_DEI5, DMAC1_2_DADERR,
-	DMAC2_1_DEI0, DMAC2_1_DEI1, DMAC2_1_DEI2, DMAC2_1_DEI3,
-	DMAC2_2_DEI4, DMAC2_2_DEI5, DMAC2_2_DADERR,
-	DMAC3_1_DEI0, DMAC3_1_DEI1, DMAC3_1_DEI2, DMAC3_1_DEI3,
-	DMAC3_2_DEI4, DMAC3_2_DEI5, DMAC3_2_DADERR,
-	SHWYSTAT_RT, SHWYSTAT_HS, SHWYSTAT_COM,
-	HDMI,
-	USBH_INT, USBH_OHCI, USBH_EHCI, USBH_PME, USBH_BIND,
-	RSPI_OVRF, RSPI_SPTEF, RSPI_SPRF,
-	SPU2_0, SPU2_1,
-	FSI, FMSI,
-	HDMI_SSS, HDMI_KEY,
-	IPMMU,
-	AP_ARM_CTIIRQ, AP_ARM_PMURQ,
-	MFIS2,
-	CPORTR2S,
-	CMT14, CMT15,
-	MMCIF_0, MMCIF_1, MMCIF_2,
-	SIM_ERI, SIM_RXI, SIM_TXI, SIM_TEI,
-	STPRO_0, STPRO_1, STPRO_2, STPRO_3, STPRO_4,
-
-	/* interrupt groups INTCA */
-	DMAC1_1, DMAC1_2,
-	DMAC2_1, DMAC2_2,
-	DMAC3_1, DMAC3_2,
-	AP_ARM1, AP_ARM2,
-	SDHI0, SDHI1, SDHI2,
-	SHWYSTAT,
-	USBF, USBH1, USBH2,
-	RSPI, SPU2, FLCTL, IIC1,
-};
-
-static struct intc_vect intca_vectors[] __initdata = {
-	INTC_VECT(DIRC,			0x0560),
-	INTC_VECT(ATAPI,		0x05E0),
-	INTC_VECT(IIC1_ALI,		0x0780),
-	INTC_VECT(IIC1_TACKI,		0x07A0),
-	INTC_VECT(IIC1_WAITI,		0x07C0),
-	INTC_VECT(IIC1_DTEI,		0x07E0),
-	INTC_VECT(AP_ARM_COMMTX,	0x0840),
-	INTC_VECT(AP_ARM_COMMRX,	0x0860),
-	INTC_VECT(MFI,			0x0900),
-	INTC_VECT(MFIS,			0x0920),
-	INTC_VECT(BBIF1,		0x0940),
-	INTC_VECT(BBIF2,		0x0960),
-	INTC_VECT(USBHSDMAC,		0x0A00),
-	INTC_VECT(USBF_OUL_SOF,		0x0A20),
-	INTC_VECT(USBF_IXL_INT,		0x0A40),
-	INTC_VECT(SGX540,		0x0A60),
-	INTC_VECT(CMT1_0,		0x0B00),
-	INTC_VECT(CMT1_1,		0x0B20),
-	INTC_VECT(CMT1_2,		0x0B40),
-	INTC_VECT(CMT1_3,		0x0B60),
-	INTC_VECT(CMT2,			0x0B80),
-	INTC_VECT(CMT3,			0x0BA0),
-	INTC_VECT(KEYSC,		0x0BE0),
-	INTC_VECT(SCIFA0,		0x0C00),
-	INTC_VECT(SCIFA1,		0x0C20),
-	INTC_VECT(SCIFA2,		0x0C40),
-	INTC_VECT(SCIFA3,		0x0C60),
-	INTC_VECT(MSIOF2,		0x0C80),
-	INTC_VECT(MSIOF1,		0x0D00),
-	INTC_VECT(SCIFA4,		0x0D20),
-	INTC_VECT(SCIFA5,		0x0D40),
-	INTC_VECT(SCIFB,		0x0D60),
-	INTC_VECT(FLCTL_FLSTEI,		0x0D80),
-	INTC_VECT(FLCTL_FLTENDI,	0x0DA0),
-	INTC_VECT(FLCTL_FLTREQ0I,	0x0DC0),
-	INTC_VECT(FLCTL_FLTREQ1I,	0x0DE0),
-	INTC_VECT(SDHI0_0,		0x0E00),
-	INTC_VECT(SDHI0_1,		0x0E20),
-	INTC_VECT(SDHI0_2,		0x0E40),
-	INTC_VECT(SDHI0_3,		0x0E60),
-	INTC_VECT(SDHI1_0,		0x0E80),
-	INTC_VECT(SDHI1_1,		0x0EA0),
-	INTC_VECT(SDHI1_2,		0x0EC0),
-	INTC_VECT(SDHI1_3,		0x0EE0),
-	INTC_VECT(AP_ARM_L2CINT,	0x0FA0),
-	INTC_VECT(IRDA,			0x0480),
-	INTC_VECT(TPU0,			0x04A0),
-	INTC_VECT(SCIFA6,		0x04C0),
-	INTC_VECT(SCIFA7,		0x04E0),
-	INTC_VECT(GbEther,		0x0500),
-	INTC_VECT(ICBS0,		0x0540),
-	INTC_VECT(DDM,			0x1140),
-	INTC_VECT(SDHI2_0,		0x1200),
-	INTC_VECT(SDHI2_1,		0x1220),
-	INTC_VECT(SDHI2_2,		0x1240),
-	INTC_VECT(SDHI2_3,		0x1260),
-	INTC_VECT(RWDT0,		0x1280),
-	INTC_VECT(DMAC1_1_DEI0,		0x2000),
-	INTC_VECT(DMAC1_1_DEI1,		0x2020),
-	INTC_VECT(DMAC1_1_DEI2,		0x2040),
-	INTC_VECT(DMAC1_1_DEI3,		0x2060),
-	INTC_VECT(DMAC1_2_DEI4,		0x2080),
-	INTC_VECT(DMAC1_2_DEI5,		0x20A0),
-	INTC_VECT(DMAC1_2_DADERR,	0x20C0),
-	INTC_VECT(DMAC2_1_DEI0,		0x2100),
-	INTC_VECT(DMAC2_1_DEI1,		0x2120),
-	INTC_VECT(DMAC2_1_DEI2,		0x2140),
-	INTC_VECT(DMAC2_1_DEI3,		0x2160),
-	INTC_VECT(DMAC2_2_DEI4,		0x2180),
-	INTC_VECT(DMAC2_2_DEI5,		0x21A0),
-	INTC_VECT(DMAC2_2_DADERR,	0x21C0),
-	INTC_VECT(DMAC3_1_DEI0,		0x2200),
-	INTC_VECT(DMAC3_1_DEI1,		0x2220),
-	INTC_VECT(DMAC3_1_DEI2,		0x2240),
-	INTC_VECT(DMAC3_1_DEI3,		0x2260),
-	INTC_VECT(DMAC3_2_DEI4,		0x2280),
-	INTC_VECT(DMAC3_2_DEI5,		0x22A0),
-	INTC_VECT(DMAC3_2_DADERR,	0x22C0),
-	INTC_VECT(SHWYSTAT_RT,		0x1300),
-	INTC_VECT(SHWYSTAT_HS,		0x1320),
-	INTC_VECT(SHWYSTAT_COM,		0x1340),
-	INTC_VECT(USBH_INT,		0x1540),
-	INTC_VECT(USBH_OHCI,		0x1560),
-	INTC_VECT(USBH_EHCI,		0x1580),
-	INTC_VECT(USBH_PME,		0x15A0),
-	INTC_VECT(USBH_BIND,		0x15C0),
-	INTC_VECT(HDMI,			0x1700),
-	INTC_VECT(RSPI_OVRF,		0x1780),
-	INTC_VECT(RSPI_SPTEF,		0x17A0),
-	INTC_VECT(RSPI_SPRF,		0x17C0),
-	INTC_VECT(SPU2_0,		0x1800),
-	INTC_VECT(SPU2_1,		0x1820),
-	INTC_VECT(FSI,			0x1840),
-	INTC_VECT(FMSI,			0x1860),
-	INTC_VECT(HDMI_SSS,		0x18A0),
-	INTC_VECT(HDMI_KEY,		0x18C0),
-	INTC_VECT(IPMMU,		0x1920),
-	INTC_VECT(AP_ARM_CTIIRQ,	0x1980),
-	INTC_VECT(AP_ARM_PMURQ,		0x19A0),
-	INTC_VECT(MFIS2,		0x1A00),
-	INTC_VECT(CPORTR2S,		0x1A20),
-	INTC_VECT(CMT14,		0x1A40),
-	INTC_VECT(CMT15,		0x1A60),
-	INTC_VECT(MMCIF_0,		0x1AA0),
-	INTC_VECT(MMCIF_1,		0x1AC0),
-	INTC_VECT(MMCIF_2,		0x1AE0),
-	INTC_VECT(SIM_ERI,		0x1C00),
-	INTC_VECT(SIM_RXI,		0x1C20),
-	INTC_VECT(SIM_TXI,		0x1C40),
-	INTC_VECT(SIM_TEI,		0x1C60),
-	INTC_VECT(STPRO_0,		0x1C80),
-	INTC_VECT(STPRO_1,		0x1CA0),
-	INTC_VECT(STPRO_2,		0x1CC0),
-	INTC_VECT(STPRO_3,		0x1CE0),
-	INTC_VECT(STPRO_4,		0x1D00),
-};
-
-static struct intc_group intca_groups[] __initdata = {
-	INTC_GROUP(DMAC1_1,
-		   DMAC1_1_DEI0, DMAC1_1_DEI1, DMAC1_1_DEI2, DMAC1_1_DEI3),
-	INTC_GROUP(DMAC1_2,
-		   DMAC1_2_DEI4, DMAC1_2_DEI5, DMAC1_2_DADERR),
-	INTC_GROUP(DMAC2_1,
-		   DMAC2_1_DEI0, DMAC2_1_DEI1, DMAC2_1_DEI2, DMAC2_1_DEI3),
-	INTC_GROUP(DMAC2_2,
-		   DMAC2_2_DEI4, DMAC2_2_DEI5, DMAC2_2_DADERR),
-	INTC_GROUP(DMAC3_1,
-		   DMAC3_1_DEI0, DMAC3_1_DEI1, DMAC3_1_DEI2, DMAC3_1_DEI3),
-	INTC_GROUP(DMAC3_2,
-		   DMAC3_2_DEI4, DMAC3_2_DEI5, DMAC3_2_DADERR),
-	INTC_GROUP(AP_ARM1,
-		   AP_ARM_COMMTX, AP_ARM_COMMRX),
-	INTC_GROUP(AP_ARM2,
-		   AP_ARM_CTIIRQ, AP_ARM_PMURQ),
-	INTC_GROUP(USBF,
-		   USBF_OUL_SOF, USBF_IXL_INT),
-	INTC_GROUP(SDHI0,
-		   SDHI0_0, SDHI0_1, SDHI0_2, SDHI0_3),
-	INTC_GROUP(SDHI1,
-		   SDHI1_0, SDHI1_1, SDHI1_2, SDHI1_3),
-	INTC_GROUP(SDHI2,
-		   SDHI2_0, SDHI2_1, SDHI2_2, SDHI2_3),
-	INTC_GROUP(SHWYSTAT,
-		   SHWYSTAT_RT, SHWYSTAT_HS, SHWYSTAT_COM),
-	INTC_GROUP(USBH1, /* FIXME */
-		   USBH_INT, USBH_OHCI),
-	INTC_GROUP(USBH2, /* FIXME */
-		   USBH_EHCI,
-		   USBH_PME, USBH_BIND),
-	INTC_GROUP(RSPI,
-		   RSPI_OVRF, RSPI_SPTEF, RSPI_SPRF),
-	INTC_GROUP(SPU2,
-		   SPU2_0, SPU2_1),
-	INTC_GROUP(FLCTL,
-		   FLCTL_FLSTEI, FLCTL_FLTENDI, FLCTL_FLTREQ0I, FLCTL_FLTREQ1I),
-	INTC_GROUP(IIC1,
-		   IIC1_ALI, IIC1_TACKI, IIC1_WAITI, IIC1_DTEI),
-};
-
-static struct intc_mask_reg intca_mask_registers[] __initdata = {
-	{ /* IMR0A / IMCR0A */ 0xe6940080, 0xe69400c0, 8,
-	  { DMAC2_1_DEI3, DMAC2_1_DEI2, DMAC2_1_DEI1, DMAC2_1_DEI0,
-	    0, 0, AP_ARM_COMMTX, AP_ARM_COMMRX } },
-	{ /* IMR1A / IMCR1A */ 0xe6940084, 0xe69400c4, 8,
-	  { ATAPI, 0, DIRC, 0,
-	    DMAC1_1_DEI3, DMAC1_1_DEI2, DMAC1_1_DEI1, DMAC1_1_DEI0 } },
-	{ /* IMR2A / IMCR2A */ 0xe6940088, 0xe69400c8, 8,
-	  { 0, 0, 0, 0,
-	    BBIF1, BBIF2, MFIS, MFI } },
-	{ /* IMR3A / IMCR3A */ 0xe694008c, 0xe69400cc, 8,
-	  { DMAC3_1_DEI3, DMAC3_1_DEI2, DMAC3_1_DEI1, DMAC3_1_DEI0,
-	    DMAC3_2_DADERR, DMAC3_2_DEI5, DMAC3_2_DEI4, IRDA } },
-	{ /* IMR4A / IMCR4A */ 0xe6940090, 0xe69400d0, 8,
-	  { DDM, 0, 0, 0,
-	    0, 0, 0, 0 } },
-	{ /* IMR5A / IMCR5A */ 0xe6940094, 0xe69400d4, 8,
-	  { KEYSC, DMAC1_2_DADERR, DMAC1_2_DEI5, DMAC1_2_DEI4,
-	    SCIFA3, SCIFA2, SCIFA1, SCIFA0 } },
-	{ /* IMR6A / IMCR6A */ 0xe6940098, 0xe69400d8, 8,
-	  { SCIFB, SCIFA5, SCIFA4, MSIOF1,
-	    0, 0, MSIOF2, 0 } },
-	{ /* IMR7A / IMCR7A */ 0xe694009c, 0xe69400dc, 8,
-	  { SDHI0_3, SDHI0_2, SDHI0_1, SDHI0_0,
-	    FLCTL_FLTREQ1I, FLCTL_FLTREQ0I, FLCTL_FLTENDI, FLCTL_FLSTEI } },
-	{ /* IMR8A / IMCR8A */ 0xe69400a0, 0xe69400e0, 8,
-	  { SDHI1_3, SDHI1_2, SDHI1_1, SDHI1_0,
-	    0, USBHSDMAC, 0, AP_ARM_L2CINT } },
-	{ /* IMR9A / IMCR9A */ 0xe69400a4, 0xe69400e4, 8,
-	  { CMT1_3, CMT1_2, CMT1_1, CMT1_0,
-	    CMT2, USBF_IXL_INT, USBF_OUL_SOF, SGX540 } },
-	{ /* IMR10A / IMCR10A */ 0xe69400a8, 0xe69400e8, 8,
-	  { 0, DMAC2_2_DADERR, DMAC2_2_DEI5, DMAC2_2_DEI4,
-	    0, 0, 0, 0 } },
-	{ /* IMR11A / IMCR11A */ 0xe69400ac, 0xe69400ec, 8,
-	  { IIC1_DTEI, IIC1_WAITI, IIC1_TACKI, IIC1_ALI,
-	    ICBS0, 0, 0, 0 } },
-	{ /* IMR12A / IMCR12A */ 0xe69400b0, 0xe69400f0, 8,
-	  { 0, 0, TPU0, SCIFA6,
-	    SCIFA7, GbEther, 0, 0 } },
-	{ /* IMR13A / IMCR13A */ 0xe69400b4, 0xe69400f4, 8,
-	  { SDHI2_3, SDHI2_2, SDHI2_1, SDHI2_0,
-	    0, CMT3, 0, RWDT0 } },
-	{ /* IMR0A3 / IMCR0A3 */ 0xe6950080, 0xe69500c0, 8,
-	  { SHWYSTAT_RT, SHWYSTAT_HS, SHWYSTAT_COM, 0,
-	    0, 0, 0, 0 } },
-	  /* IMR1A3 / IMCR1A3 */
-	{ /* IMR2A3 / IMCR2A3 */ 0xe6950088, 0xe69500c8, 8,
-	  { 0, 0, USBH_INT, USBH_OHCI,
-	    USBH_EHCI, USBH_PME, USBH_BIND, 0 } },
-	  /* IMR3A3 / IMCR3A3 */
-	{ /* IMR4A3 / IMCR4A3 */ 0xe6950090, 0xe69500d0, 8,
-	  { HDMI, 0, 0, 0,
-	    RSPI_OVRF, RSPI_SPTEF, RSPI_SPRF, 0 } },
-	{ /* IMR5A3 / IMCR5A3 */ 0xe6950094, 0xe69500d4, 8,
-	  { SPU2_0, SPU2_1, FSI, FMSI,
-	    0, HDMI_SSS, HDMI_KEY, 0 } },
-	{ /* IMR6A3 / IMCR6A3 */ 0xe6950098, 0xe69500d8, 8,
-	  { 0, IPMMU, 0, 0,
-	    AP_ARM_CTIIRQ, AP_ARM_PMURQ, 0, 0 } },
-	{ /* IMR7A3 / IMCR7A3 */ 0xe695009c, 0xe69500dc, 8,
-	  { MFIS2, CPORTR2S, CMT14, CMT15,
-	    0, MMCIF_0, MMCIF_1, MMCIF_2 } },
-	  /* IMR8A3 / IMCR8A3 */
-	{ /* IMR9A3 / IMCR9A3 */ 0xe69500a4, 0xe69500e4, 8,
-	  { SIM_ERI, SIM_RXI, SIM_TXI, SIM_TEI,
-	    STPRO_0, STPRO_1, STPRO_2, STPRO_3 } },
-	{ /* IMR10A3 / IMCR10A3 */ 0xe69500a8, 0xe69500e8, 8,
-	  { STPRO_4, 0, 0, 0,
-	    0, 0, 0, 0 } },
-};
-
-static struct intc_prio_reg intca_prio_registers[] __initdata = {
-	{ 0xe6940000, 0, 16, 4, /* IPRAA */ { DMAC3_1, DMAC3_2, CMT2, ICBS0 } },
-	{ 0xe6940004, 0, 16, 4, /* IPRBA */ { IRDA, 0, BBIF1, BBIF2 } },
-	{ 0xe6940008, 0, 16, 4, /* IPRCA */ { ATAPI, 0, CMT1_1, AP_ARM1 } },
-	{ 0xe694000c, 0, 16, 4, /* IPRDA */ { 0, 0, CMT1_2, 0 } },
-	{ 0xe6940010, 0, 16, 4, /* IPREA */ { DMAC1_1, MFIS, MFI, USBF } },
-	{ 0xe6940014, 0, 16, 4, /* IPRFA */ { KEYSC, DMAC1_2,
-					      SGX540, CMT1_0 } },
-	{ 0xe6940018, 0, 16, 4, /* IPRGA */ { SCIFA0, SCIFA1,
-					      SCIFA2, SCIFA3 } },
-	{ 0xe694001c, 0, 16, 4, /* IPRGH */ { MSIOF2, USBHSDMAC,
-					      FLCTL, SDHI0 } },
-	{ 0xe6940020, 0, 16, 4, /* IPRIA */ { MSIOF1, SCIFA4, 0, IIC1 } },
-	{ 0xe6940024, 0, 16, 4, /* IPRJA */ { DMAC2_1, DMAC2_2,
-					      AP_ARM_L2CINT, 0 } },
-	{ 0xe6940028, 0, 16, 4, /* IPRKA */ { 0, CMT1_3, 0, SDHI1 } },
-	{ 0xe694002c, 0, 16, 4, /* IPRLA */ { TPU0, SCIFA6,
-					      SCIFA7, GbEther } },
-	{ 0xe6940030, 0, 16, 4, /* IPRMA */ { 0, CMT3, 0, RWDT0 } },
-	{ 0xe6940034, 0, 16, 4, /* IPRNA */ { SCIFB, SCIFA5, 0, DDM } },
-	{ 0xe6940038, 0, 16, 4, /* IPROA */ { 0, 0, DIRC, SDHI2 } },
-	{ 0xe6950000, 0, 16, 4, /* IPRAA3 */ { SHWYSTAT, 0, 0, 0 } },
-				/* IPRBA3 */
-				/* IPRCA3 */
-				/* IPRDA3 */
-	{ 0xe6950010, 0, 16, 4, /* IPREA3 */ { USBH1, 0, 0, 0 } },
-	{ 0xe6950014, 0, 16, 4, /* IPRFA3 */ { USBH2, 0, 0, 0 } },
-				/* IPRGA3 */
-				/* IPRHA3 */
-	{ 0xe6950020, 0, 16, 4, /* IPRIA3 */ { HDMI, 0, 0, 0 } },
-	{ 0xe6950024, 0, 16, 4, /* IPRJA3 */ { RSPI, 0, 0, 0 } },
-	{ 0xe6950028, 0, 16, 4, /* IPRKA3 */ { SPU2, 0, FSI, FMSI } },
-	{ 0xe695002c, 0, 16, 4, /* IPRLA3 */ { 0, HDMI_SSS, HDMI_KEY, 0 } },
-	{ 0xe6950030, 0, 16, 4, /* IPRMA3 */ { IPMMU, 0, 0, 0 } },
-	{ 0xe6950034, 0, 16, 4, /* IPRNA3 */ { AP_ARM2, 0, 0, 0 } },
-	{ 0xe6950038, 0, 16, 4, /* IPROA3 */ { MFIS2, CPORTR2S,
-					       CMT14, CMT15 } },
-	{ 0xe695003c, 0, 16, 4, /* IPRPA3 */ { 0, MMCIF_0, MMCIF_1, MMCIF_2 } },
-				/* IPRQA3 */
-				/* IPRRA3 */
-	{ 0xe6950048, 0, 16, 4, /* IPRSA3 */ { SIM_ERI, SIM_RXI,
-					       SIM_TXI, SIM_TEI } },
-	{ 0xe695004c, 0, 16, 4, /* IPRTA3 */ { STPRO_0, STPRO_1,
-					       STPRO_2, STPRO_3 } },
-	{ 0xe6950050, 0, 16, 4, /* IPRUA3 */ { STPRO_4, 0, 0, 0 } },
-};
-
-static DECLARE_INTC_DESC(intca_desc, "r8a7740-intca",
-			 intca_vectors, intca_groups,
-			 intca_mask_registers, intca_prio_registers,
-			 NULL);
-
-INTC_IRQ_PINS_32(intca_irq_pins, 0xe6900000,
-		 INTC_VECT, "r8a7740-intca-irq-pins");
-
-
-/*
- *		INTCS
- */
-enum {
-	UNUSED_INTCS = 0,
-
-	INTCS,
-
-	/* interrupt sources INTCS */
-
-	/* HUDI */
-	/* STPRO */
-	/* RTDMAC(1) */
-	VPU5HA2,
-	_2DG_TRAP, _2DG_GPM_INT, _2DG_CER_INT,
-	/* MFI */
-	/* BBIF2 */
-	VPU5F,
-	_2DG_BRK_INT,
-	/* SGX540 */
-	/* 2DDMAC */
-	/* IPMMU */
-	/* RTDMAC 2 */
-	/* KEYSC */
-	/* MSIOF */
-	IIC0_ALI, IIC0_TACKI, IIC0_WAITI, IIC0_DTEI,
-	TMU0_0, TMU0_1, TMU0_2,
-	CMT0,
-	/* CMT2 */
-	LMB,
-	CTI,
-	VOU,
-	/* RWDT0 */
-	ICB,
-	VIO6C,
-	CEU20, CEU21,
-	JPU,
-	LCDC0,
-	LCRC,
-	/* RTDMAC2(1) */
-	/* RTDMAC2(2) */
-	LCDC1,
-	/* SPU2 */
-	/* FSI */
-	/* FMSI */
-	TMU1_0, TMU1_1, TMU1_2,
-	CMT4,
-	DISP,
-	DSRV,
-	/* MFIS2 */
-	CPORTS2R,
-
-	/* interrupt groups INTCS */
-	_2DG1,
-	IIC0, TMU1,
-};
-
-static struct intc_vect intcs_vectors[] = {
-	/* HUDI */
-	/* STPRO */
-	/* RTDMAC(1) */
-	INTCS_VECT(VPU5HA2,		0x0880),
-	INTCS_VECT(_2DG_TRAP,		0x08A0),
-	INTCS_VECT(_2DG_GPM_INT,	0x08C0),
-	INTCS_VECT(_2DG_CER_INT,	0x08E0),
-	/* MFI */
-	/* BBIF2 */
-	INTCS_VECT(VPU5F,		0x0980),
-	INTCS_VECT(_2DG_BRK_INT,	0x09A0),
-	/* SGX540 */
-	/* 2DDMAC */
-	/* IPMMU */
-	/* RTDMAC(2) */
-	/* KEYSC */
-	/* MSIOF */
-	INTCS_VECT(IIC0_ALI,		0x0E00),
-	INTCS_VECT(IIC0_TACKI,		0x0E20),
-	INTCS_VECT(IIC0_WAITI,		0x0E40),
-	INTCS_VECT(IIC0_DTEI,		0x0E60),
-	INTCS_VECT(TMU0_0,		0x0E80),
-	INTCS_VECT(TMU0_1,		0x0EA0),
-	INTCS_VECT(TMU0_2,		0x0EC0),
-	INTCS_VECT(CMT0,		0x0F00),
-	/* CMT2 */
-	INTCS_VECT(LMB,			0x0F60),
-	INTCS_VECT(CTI,			0x0400),
-	INTCS_VECT(VOU,			0x0420),
-	/* RWDT0 */
-	INTCS_VECT(ICB,			0x0480),
-	INTCS_VECT(VIO6C,		0x04E0),
-	INTCS_VECT(CEU20,		0x0500),
-	INTCS_VECT(CEU21,		0x0520),
-	INTCS_VECT(JPU,			0x0560),
-	INTCS_VECT(LCDC0,		0x0580),
-	INTCS_VECT(LCRC,		0x05A0),
-	/* RTDMAC2(1) */
-	/* RTDMAC2(2) */
-	INTCS_VECT(LCDC1,		0x1780),
-	/* SPU2 */
-	/* FSI */
-	/* FMSI */
-	INTCS_VECT(TMU1_0,		0x1900),
-	INTCS_VECT(TMU1_1,		0x1920),
-	INTCS_VECT(TMU1_2,		0x1940),
-	INTCS_VECT(CMT4,		0x1980),
-	INTCS_VECT(DISP,		0x19A0),
-	INTCS_VECT(DSRV,		0x19C0),
-	/* MFIS2 */
-	INTCS_VECT(CPORTS2R,		0x1A20),
-
-	INTC_VECT(INTCS,		0xf80),
-};
-
-static struct intc_group intcs_groups[] __initdata = {
-	INTC_GROUP(_2DG1, /*FIXME*/
-		   _2DG_CER_INT, _2DG_GPM_INT, _2DG_TRAP),
-	INTC_GROUP(IIC0,
-		   IIC0_DTEI, IIC0_WAITI, IIC0_TACKI, IIC0_ALI),
-	INTC_GROUP(TMU1,
-		   TMU1_0, TMU1_1, TMU1_2),
-};
-
-static struct intc_mask_reg intcs_mask_registers[] = {
-	  /* IMR0SA / IMCR0SA */ /* all 0 */
-	{ /* IMR1SA / IMCR1SA */ 0xffd20184, 0xffd201c4, 8,
-	  { _2DG_CER_INT, _2DG_GPM_INT, _2DG_TRAP, VPU5HA2,
-	    0, 0, 0, 0 /*STPRO*/ } },
-	{ /* IMR2SA / IMCR2SA */ 0xffd20188, 0xffd201c8, 8,
-	  { 0/*STPRO*/, 0, CEU21, VPU5F,
-	    0/*BBIF2*/, 0, 0, 0/*MFI*/ } },
-	{ /* IMR3SA / IMCR3SA */ 0xffd2018c, 0xffd201cc, 8,
-	  { 0, 0, 0, 0, /*2DDMAC*/
-	    VIO6C, 0, 0, ICB } },
-	{ /* IMR4SA / IMCR4SA */ 0xffd20190, 0xffd201d0, 8,
-	  { 0, 0, VOU, CTI,
-	    JPU, 0, LCRC, LCDC0 } },
-	  /* IMR5SA / IMCR5SA */ /*KEYSC/RTDMAC2/RTDMAC1*/
-	  /* IMR6SA / IMCR6SA */ /*MSIOF/SGX540*/
-	{ /* IMR7SA / IMCR7SA */ 0xffd2019c, 0xffd201dc, 8,
-	  { 0, TMU0_2, TMU0_1, TMU0_0,
-	    0, 0, 0, 0 } },
-	{ /* IMR8SA / IMCR8SA */ 0xffd201a0, 0xffd201e0, 8,
-	  { 0, 0, 0, 0,
-	    CEU20, 0, 0, 0 } },
-	{ /* IMR9SA / IMCR9SA */ 0xffd201a4, 0xffd201e4, 8,
-	  { 0, 0/*RWDT0*/, 0/*CMT2*/, CMT0,
-	    0, 0, 0, 0 } },
-	  /* IMR10SA / IMCR10SA */ /*IPMMU*/
-	{ /* IMR11SA / IMCR11SA */ 0xffd201ac, 0xffd201ec, 8,
-	  { IIC0_DTEI, IIC0_WAITI, IIC0_TACKI, IIC0_ALI,
-	    0, _2DG_BRK_INT, LMB, 0 } },
-	  /* IMR12SA / IMCR12SA */
-	  /* IMR13SA / IMCR13SA */
-	  /* IMR0SA3 / IMCR0SA3 */ /*RTDMAC2(1)/RTDMAC2(2)*/
-	  /* IMR1SA3 / IMCR1SA3 */
-	  /* IMR2SA3 / IMCR2SA3 */
-	  /* IMR3SA3 / IMCR3SA3 */
-	{ /* IMR4SA3 / IMCR4SA3 */ 0xffd50190, 0xffd501d0, 8,
-	  { 0, 0, 0, 0,
-	    LCDC1, 0, 0, 0 } },
-	  /* IMR5SA3 / IMCR5SA3 */ /* SPU2/FSI/FMSI */
-	{ /* IMR6SA3 / IMCR6SA3 */ 0xffd50198, 0xffd501d8, 8,
-	  { TMU1_0, TMU1_1, TMU1_2, 0,
-	    CMT4, DISP, DSRV, 0 } },
-	{ /* IMR7SA3 / IMCR7SA3 */ 0xffd5019c, 0xffd501dc, 8,
-	  { 0/*MFIS2*/, CPORTS2R, 0, 0,
-	    0, 0, 0, 0 } },
-	{ /* INTAMASK */ 0xffd20104, 0, 16,
-	  { 0, 0, 0, 0, 0, 0, 0, 0,
-	    0, 0, 0, 0, 0, 0, 0, INTCS } },
-};
-
-/* Priority is needed for INTCA to receive the INTCS interrupt */
-static struct intc_prio_reg intcs_prio_registers[] = {
-	{ 0xffd20000, 0, 16, 4, /* IPRAS */ { CTI, VOU, 0/*2DDMAC*/, ICB } },
-	{ 0xffd20004, 0, 16, 4, /* IPRBS */ { JPU, LCDC0, 0, LCRC } },
-				/* IPRCS */ /*BBIF2*/
-				/* IPRDS */
-	{ 0xffd20010, 0, 16, 4, /* IPRES */ { 0/*RTDMAC(1)*/, VPU5HA2,
-					      0/*MFI*/, VPU5F } },
-	{ 0xffd20014, 0, 16, 4, /* IPRFS */ { 0/*KEYSC*/, 0/*RTDMAC(2)*/,
-					      0/*CMT2*/, CMT0 } },
-	{ 0xffd20018, 0, 16, 4, /* IPRGS */ { TMU0_0, TMU0_1,
-					      TMU0_2, _2DG1 } },
-	{ 0xffd2001c, 0, 16, 4, /* IPRHS */ { 0, 0/*STPRO*/, 0/*STPRO*/,
-					      _2DG_BRK_INT/*FIXME*/ } },
-	{ 0xffd20020, 0, 16, 4, /* IPRIS */ { 0, 0/*MSIOF*/, 0, IIC0 } },
-	{ 0xffd20024, 0, 16, 4, /* IPRJS */ { CEU20, 0/*SGX540*/, 0, 0 } },
-	{ 0xffd20028, 0, 16, 4, /* IPRKS */ { VIO6C, 0, LMB, 0 } },
-	{ 0xffd2002c, 0, 16, 4, /* IPRLS */ { 0/*IPMMU*/, 0, CEU21, 0 } },
-				/* IPRMS */ /*RWDT0*/
-				/* IPRAS3 */ /*RTDMAC2(1)*/
-				/* IPRBS3 */ /*RTDMAC2(2)*/
-				/* IPRCS3 */
-				/* IPRDS3 */
-				/* IPRES3 */
-				/* IPRFS3 */
-				/* IPRGS3 */
-				/* IPRHS3 */
-				/* IPRIS3 */
-	{ 0xffd50024, 0, 16, 4, /* IPRJS3 */ { LCDC1, 0, 0, 0 } },
-				/* IPRKS3 */ /*SPU2/FSI/FMSi*/
-				/* IPRLS3 */
-	{ 0xffd50030, 0, 16, 4, /* IPRMS3 */ { TMU1, 0, 0, 0 } },
-	{ 0xffd50034, 0, 16, 4, /* IPRNS3 */ { CMT4, DISP, DSRV, 0 } },
-	{ 0xffd50038, 0, 16, 4, /* IPROS3 */ { 0/*MFIS2*/, CPORTS2R, 0, 0 } },
-				/* IPRPS3 */
-};
-
-static struct resource intcs_resources[] __initdata = {
-	[0] = {
-		.start	= 0xffd20000,
-		.end	= 0xffd201ff,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= 0xffd50000,
-		.end	= 0xffd501ff,
-		.flags	= IORESOURCE_MEM,
-	}
-};
-
-static struct intc_desc intcs_desc __initdata = {
-	.name = "r8a7740-intcs",
-	.resource = intcs_resources,
-	.num_resources = ARRAY_SIZE(intcs_resources),
-	.hw = INTC_HW_DESC(intcs_vectors, intcs_groups, intcs_mask_registers,
-			   intcs_prio_registers, NULL, NULL),
-};
-
-static void intcs_demux(unsigned int irq, struct irq_desc *desc)
-{
-	void __iomem *reg = (void *)irq_get_handler_data(irq);
-	unsigned int evtcodeas = ioread32(reg);
-
-	generic_handle_irq(intcs_evt2irq(evtcodeas));
-}
+#include <linux/irqchip/arm-gic.h>
 
 void __init r8a7740_init_irq(void)
 {
-	void __iomem *intevtsa = ioremap_nocache(0xffd20100, PAGE_SIZE);
-
-	register_intc_controller(&intca_desc);
-	register_intc_controller(&intca_irq_pins_desc);
-	register_intc_controller(&intcs_desc);
-
-	/* demux using INTEVTSA */
-	irq_set_handler_data(evt2irq(0xf80), (void *)intevtsa);
-	irq_set_chained_handler(evt2irq(0xf80), intcs_demux);
+	void __iomem *gic_dist_base = ioremap_nocache(0xc2800000, 0x1000);
+	void __iomem *gic_cpu_base = ioremap_nocache(0xc2000000, 0x1000);
+	void __iomem *intc_prio_base = ioremap_nocache(0xe6900010, 0x10);
+	void __iomem *intc_msk_base = ioremap_nocache(0xe6900040, 0x10);
+	void __iomem *pfc_inta_ctrl = ioremap_nocache(0xe605807c, 0x4);
+
+	/* initialize the Generic Interrupt Controller PL390 r0p0 */
+	gic_init(0, 29, gic_dist_base, gic_cpu_base);
+
+	/* route signals to GIC */
+	iowrite32(0x0, pfc_inta_ctrl);
+
+	/*
+	 * To mask the shared interrupt to SPI 149 we must ensure to set
+	 * PRIO *and* MASK. Else we run into IRQ floods when registering
+	 * the intc_irqpin devices
+	 */
+	iowrite32(0x0, intc_prio_base + 0x0);
+	iowrite32(0x0, intc_prio_base + 0x4);
+	iowrite32(0x0, intc_prio_base + 0x8);
+	iowrite32(0x0, intc_prio_base + 0xc);
+	iowrite8(0xff, intc_msk_base + 0x0);
+	iowrite8(0xff, intc_msk_base + 0x4);
+	iowrite8(0xff, intc_msk_base + 0x8);
+	iowrite8(0xff, intc_msk_base + 0xc);
+
+	iounmap(intc_prio_base);
+	iounmap(intc_msk_base);
+	iounmap(pfc_inta_ctrl);
 }
diff --git a/arch/arm/mach-shmobile/intc-r8a7779.c b/arch/arm/mach-shmobile/intc-r8a7779.c
index 8807c27..b86dc89 100644
--- a/arch/arm/mach-shmobile/intc-r8a7779.c
+++ b/arch/arm/mach-shmobile/intc-r8a7779.c
@@ -19,12 +19,16 @@
  */
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/platform_device.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/io.h>
 #include <linux/irqchip/arm-gic.h>
+#include <linux/platform_data/irq-renesas-intc-irqpin.h>
+#include <linux/irqchip.h>
 #include <mach/common.h>
 #include <mach/intc.h>
+#include <mach/irqs.h>
 #include <mach/r8a7779.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -38,18 +42,61 @@
 #define INT2NTSR0 IOMEM(0xfe700060)
 #define INT2NTSR1 IOMEM(0xfe700064)
 
+static struct renesas_intc_irqpin_config irqpin0_platform_data = {
+	.irq_base = irq_pin(0), /* IRQ0 -> IRQ3 */
+	.sense_bitfield_width = 2,
+};
+
+static struct resource irqpin0_resources[] = {
+	DEFINE_RES_MEM(0xfe78001c, 4), /* ICR1 */
+	DEFINE_RES_MEM(0xfe780010, 4), /* INTPRI */
+	DEFINE_RES_MEM(0xfe780024, 4), /* INTREQ */
+	DEFINE_RES_MEM(0xfe780044, 4), /* INTMSK0 */
+	DEFINE_RES_MEM(0xfe780064, 4), /* INTMSKCLR0 */
+	DEFINE_RES_IRQ(gic_spi(27)), /* IRQ0 */
+	DEFINE_RES_IRQ(gic_spi(28)), /* IRQ1 */
+	DEFINE_RES_IRQ(gic_spi(29)), /* IRQ2 */
+	DEFINE_RES_IRQ(gic_spi(30)), /* IRQ3 */
+};
+
+static struct platform_device irqpin0_device = {
+	.name		= "renesas_intc_irqpin",
+	.id		= 0,
+	.resource	= irqpin0_resources,
+	.num_resources	= ARRAY_SIZE(irqpin0_resources),
+	.dev		= {
+		.platform_data	= &irqpin0_platform_data,
+	},
+};
+
+void __init r8a7779_init_irq_extpin(int irlm)
+{
+	void __iomem *icr0 = ioremap_nocache(0xfe780000, PAGE_SIZE);
+	unsigned long tmp;
+
+	if (icr0) {
+		tmp = ioread32(icr0);
+		if (irlm)
+			tmp |= 1 << 23; /* IRQ0 -> IRQ3 as individual pins */
+		else
+			tmp &= ~(1 << 23); /* IRL mode - not supported */
+		tmp |= (1 << 21); /* LVLMODE = 1 */
+		iowrite32(tmp, icr0);
+		iounmap(icr0);
+
+		if (irlm)
+			platform_device_register(&irqpin0_device);
+	} else
+		pr_warn("r8a7779: unable to setup external irq pin mode\n");
+}
+
 static int r8a7779_set_wake(struct irq_data *data, unsigned int on)
 {
 	return 0; /* always allow wakeup */
 }
 
-void __init r8a7779_init_irq(void)
+static void __init r8a7779_init_irq_common(void)
 {
-	void __iomem *gic_dist_base = IOMEM(0xf0001000);
-	void __iomem *gic_cpu_base = IOMEM(0xf0000100);
-
-	/* use GIC to handle interrupts */
-	gic_init(0, 29, gic_dist_base, gic_cpu_base);
 	gic_arch_extn.irq_set_wake = r8a7779_set_wake;
 
 	/* route all interrupts to ARM */
@@ -63,3 +110,22 @@ void __init r8a7779_init_irq(void)
 	__raw_writel(0xbffffffc, INT2SMSKCR3);
 	__raw_writel(0x003fee3f, INT2SMSKCR4);
 }
+
+void __init r8a7779_init_irq(void)
+{
+	void __iomem *gic_dist_base = IOMEM(0xf0001000);
+	void __iomem *gic_cpu_base = IOMEM(0xf0000100);
+
+	/* use GIC to handle interrupts */
+	gic_init(0, 29, gic_dist_base, gic_cpu_base);
+
+	r8a7779_init_irq_common();
+}
+
+#ifdef CONFIG_OF
+void __init r8a7779_init_irq_dt(void)
+{
+	irqchip_init();
+	r8a7779_init_irq_common();
+}
+#endif
diff --git a/arch/arm/mach-shmobile/intc-sh73a0.c b/arch/arm/mach-shmobile/intc-sh73a0.c
index 91faba6..19a26f4 100644
--- a/arch/arm/mach-shmobile/intc-sh73a0.c
+++ b/arch/arm/mach-shmobile/intc-sh73a0.c
@@ -260,108 +260,6 @@ static int sh73a0_set_wake(struct irq_data *data, unsigned int on)
 	return 0; /* always allow wakeup */
 }
 
-#define RELOC_BASE 0x1200
-
-/* INTCA IRQ pins at INTCS + RELOC_BASE to make space for GIC+INTC handling */
-#define INTCS_VECT_RELOC(n, vect) INTCS_VECT((n), (vect) + RELOC_BASE)
-
-INTC_IRQ_PINS_32(intca_irq_pins, 0xe6900000,
-		 INTCS_VECT_RELOC, "sh73a0-intca-irq-pins");
-
-static int to_gic_irq(struct irq_data *data)
-{
-	unsigned int vect = irq2evt(data->irq) - INTCS_VECT_BASE;
-
-	if (vect >= 0x3200)
-		vect -= 0x3000;
-	else
-		vect -= 0x0200;
-
-	return gic_spi((vect >> 5) + 1);
-}
-
-static int to_intca_reloc_irq(struct irq_data *data)
-{
-	return data->irq + (RELOC_BASE >> 5);
-}
-
-#define irq_cb(cb, irq) irq_get_chip(irq)->cb(irq_get_irq_data(irq))
-#define irq_cbp(cb, irq, p...) irq_get_chip(irq)->cb(irq_get_irq_data(irq), p)
-
-static void intca_gic_enable(struct irq_data *data)
-{
-	irq_cb(irq_unmask, to_intca_reloc_irq(data));
-	irq_cb(irq_unmask, to_gic_irq(data));
-}
-
-static void intca_gic_disable(struct irq_data *data)
-{
-	irq_cb(irq_mask, to_gic_irq(data));
-	irq_cb(irq_mask, to_intca_reloc_irq(data));
-}
-
-static void intca_gic_mask_ack(struct irq_data *data)
-{
-	irq_cb(irq_mask, to_gic_irq(data));
-	irq_cb(irq_mask_ack, to_intca_reloc_irq(data));
-}
-
-static void intca_gic_eoi(struct irq_data *data)
-{
-	irq_cb(irq_eoi, to_gic_irq(data));
-}
-
-static int intca_gic_set_type(struct irq_data *data, unsigned int type)
-{
-	return irq_cbp(irq_set_type, to_intca_reloc_irq(data), type);
-}
-
-#ifdef CONFIG_SMP
-static int intca_gic_set_affinity(struct irq_data *data,
-				  const struct cpumask *cpumask,
-				  bool force)
-{
-	return irq_cbp(irq_set_affinity, to_gic_irq(data), cpumask, force);
-}
-#endif
-
-struct irq_chip intca_gic_irq_chip = {
-	.name			= "INTCA-GIC",
-	.irq_mask		= intca_gic_disable,
-	.irq_unmask		= intca_gic_enable,
-	.irq_mask_ack		= intca_gic_mask_ack,
-	.irq_eoi		= intca_gic_eoi,
-	.irq_enable		= intca_gic_enable,
-	.irq_disable		= intca_gic_disable,
-	.irq_shutdown		= intca_gic_disable,
-	.irq_set_type		= intca_gic_set_type,
-	.irq_set_wake		= sh73a0_set_wake,
-#ifdef CONFIG_SMP
-	.irq_set_affinity	= intca_gic_set_affinity,
-#endif
-};
-
-static int to_intc_vect(int irq)
-{
-	unsigned int irq_pin = irq - gic_spi(1);
-	unsigned int offs;
-
-	if (irq_pin < 16)
-		offs = 0x0200;
-	else
-		offs = 0x3000;
-
-	return offs + (irq_pin << 5);
-}
-
-static irqreturn_t sh73a0_irq_pin_demux(int irq, void *dev_id)
-{
-	generic_handle_irq(intcs_evt2irq(to_intc_vect(irq)));
-	return IRQ_HANDLED;
-}
-
-static struct irqaction sh73a0_irq_pin_cascade[32];
-
 #define PINTER0_PHYS 0xe69000a0
 #define PINTER1_PHYS 0xe69000a4
 #define PINTER0_VIRT IOMEM(0xe69000a0)
@@ -422,13 +320,11 @@ void __init sh73a0_init_irq(void)
 	void __iomem *gic_dist_base = IOMEM(0xf0001000);
 	void __iomem *gic_cpu_base = IOMEM(0xf0000100);
 	void __iomem *intevtsa = ioremap_nocache(0xffd20100, PAGE_SIZE);
-	int k, n;
 
 	gic_init(0, 29, gic_dist_base, gic_cpu_base);
 	gic_arch_extn.irq_set_wake = sh73a0_set_wake;
 
 	register_intc_controller(&intcs_desc);
-	register_intc_controller(&intca_irq_pins_desc);
 	register_intc_controller(&intc_pint0_desc);
 	register_intc_controller(&intc_pint1_desc);
 
@@ -438,19 +334,6 @@ void __init sh73a0_init_irq(void)
 	sh73a0_intcs_cascade.dev_id = intevtsa;
 	setup_irq(gic_spi(50), &sh73a0_intcs_cascade);
 
-	/* IRQ pins require special handling through INTCA and GIC */
-	for (k = 0; k < 32; k++) {
-		sh73a0_irq_pin_cascade[k].name = "INTCA-GIC cascade";
-		sh73a0_irq_pin_cascade[k].handler = sh73a0_irq_pin_demux;
-		setup_irq(gic_spi(1 + k), &sh73a0_irq_pin_cascade[k]);
-
-		n = intcs_evt2irq(to_intc_vect(gic_spi(1 + k)));
-		WARN_ON(irq_alloc_desc_at(n, numa_node_id()) != n);
-		irq_set_chip_and_handler_name(n, &intca_gic_irq_chip,
-					      handle_level_irq, "level");
-		set_irq_flags(n, IRQF_VALID); /* yuck */
-	}
-
 	/* PINT pins are sanely tied to the GIC as SPI */
 	sh73a0_pint0_cascade.name = "PINT0 cascade";
 	sh73a0_pint0_cascade.handler = sh73a0_pint0_demux;
@@ -460,11 +343,3 @@ void __init sh73a0_init_irq(void)
 	sh73a0_pint1_cascade.handler = sh73a0_pint1_demux;
 	setup_irq(gic_spi(34), &sh73a0_pint1_cascade);
 }
-
-#ifdef CONFIG_OF
-void __init sh73a0_init_irq_dt(void)
-{
-	irqchip_init();
-	gic_arch_extn.irq_set_wake = sh73a0_set_wake;
-}
-#endif
diff --git a/arch/arm/mach-shmobile/setup-emev2.c b/arch/arm/mach-shmobile/setup-emev2.c
index 47662a5..e4545c1 100644
--- a/arch/arm/mach-shmobile/setup-emev2.c
+++ b/arch/arm/mach-shmobile/setup-emev2.c
@@ -404,7 +404,7 @@ void __init emev2_add_standard_devices(void)
 			     ARRAY_SIZE(emev2_late_devices));
 }
 
-void __init emev2_init_delay(void)
+static void __init emev2_init_delay(void)
 {
 	shmobile_setup_delay(533, 1, 3); /* Cortex-A9 @ 533MHz */
 }
@@ -439,7 +439,7 @@ static const struct of_dev_auxdata emev2_auxdata_lookup[] __initconst = {
 	{ }
 };
 
-void __init emev2_add_standard_devices_dt(void)
+static void __init emev2_add_standard_devices_dt(void)
 {
 	of_platform_populate(NULL, of_default_bus_match_table,
 			     emev2_auxdata_lookup, NULL);
diff --git a/arch/arm/mach-shmobile/setup-r8a73a4.c b/arch/arm/mach-shmobile/setup-r8a73a4.c
new file mode 100644
index 0000000..c5a75a7
--- /dev/null
+++ b/arch/arm/mach-shmobile/setup-r8a73a4.c
@@ -0,0 +1,202 @@
+/*
+ * r8a73a4 processor support
+ *
+ * Copyright (C) 2013  Renesas Solutions Corp.
+ * Copyright (C) 2013  Magnus Damm
+ *
+ * This program is free software; 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/irq.h>
+#include <linux/irqchip.h>
+#include <linux/kernel.h>
+#include <linux/of_platform.h>
+#include <linux/platform_data/irq-renesas-irqc.h>
+#include <linux/serial_sci.h>
+#include <mach/common.h>
+#include <mach/irqs.h>
+#include <mach/r8a73a4.h>
+#include <asm/mach/arch.h>
+
+static const struct resource pfc_resources[] = {
+	DEFINE_RES_MEM(0xe6050000, 0x9000),
+};
+
+void __init r8a73a4_pinmux_init(void)
+{
+	platform_device_register_simple("pfc-r8a73a4", -1, pfc_resources,
+					ARRAY_SIZE(pfc_resources));
+}
+
+#define SCIF_COMMON(scif_type, baseaddr, irq)			\
+	.type		= scif_type,				\
+	.mapbase	= baseaddr,				\
+	.flags		= UPF_BOOT_AUTOCONF | UPF_IOREMAP,	\
+	.scbrr_algo_id	= SCBRR_ALGO_4,				\
+	.irqs		= SCIx_IRQ_MUXED(irq)
+
+#define SCIFA_DATA(index, baseaddr, irq)		\
+[index] = {						\
+	SCIF_COMMON(PORT_SCIFA, baseaddr, irq),		\
+	.scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE0,	\
+}
+
+#define SCIFB_DATA(index, baseaddr, irq)	\
+[index] = {					\
+	SCIF_COMMON(PORT_SCIFB, baseaddr, irq),	\
+	.scscr = SCSCR_RE | SCSCR_TE,		\
+}
+
+enum { SCIFA0, SCIFA1, SCIFB0, SCIFB1, SCIFB2, SCIFB3 };
+
+static const struct plat_sci_port scif[] = {
+	SCIFA_DATA(SCIFA0, 0xe6c40000, gic_spi(144)), /* SCIFA0 */
+	SCIFA_DATA(SCIFA1, 0xe6c50000, gic_spi(145)), /* SCIFA1 */
+	SCIFB_DATA(SCIFB0, 0xe6c50000, gic_spi(145)), /* SCIFB0 */
+	SCIFB_DATA(SCIFB1, 0xe6c30000, gic_spi(149)), /* SCIFB1 */
+	SCIFB_DATA(SCIFB2, 0xe6ce0000, gic_spi(150)), /* SCIFB2 */
+	SCIFB_DATA(SCIFB3, 0xe6cf0000, gic_spi(151)), /* SCIFB3 */
+};
+
+static inline void r8a73a4_register_scif(int idx)
+{
+	platform_device_register_data(&platform_bus, "sh-sci", idx, &scif[idx],
+				      sizeof(struct plat_sci_port));
+}
+
+static const struct renesas_irqc_config irqc0_data = {
+	.irq_base = irq_pin(0), /* IRQ0 -> IRQ31 */
+};
+
+static const struct resource irqc0_resources[] = {
+	DEFINE_RES_MEM(0xe61c0000, 0x200), /* IRQC Event Detector Block_0 */
+	DEFINE_RES_IRQ(gic_spi(0)), /* IRQ0 */
+	DEFINE_RES_IRQ(gic_spi(1)), /* IRQ1 */
+	DEFINE_RES_IRQ(gic_spi(2)), /* IRQ2 */
+	DEFINE_RES_IRQ(gic_spi(3)), /* IRQ3 */
+	DEFINE_RES_IRQ(gic_spi(4)), /* IRQ4 */
+	DEFINE_RES_IRQ(gic_spi(5)), /* IRQ5 */
+	DEFINE_RES_IRQ(gic_spi(6)), /* IRQ6 */
+	DEFINE_RES_IRQ(gic_spi(7)), /* IRQ7 */
+	DEFINE_RES_IRQ(gic_spi(8)), /* IRQ8 */
+	DEFINE_RES_IRQ(gic_spi(9)), /* IRQ9 */
+	DEFINE_RES_IRQ(gic_spi(10)), /* IRQ10 */
+	DEFINE_RES_IRQ(gic_spi(11)), /* IRQ11 */
+	DEFINE_RES_IRQ(gic_spi(12)), /* IRQ12 */
+	DEFINE_RES_IRQ(gic_spi(13)), /* IRQ13 */
+	DEFINE_RES_IRQ(gic_spi(14)), /* IRQ14 */
+	DEFINE_RES_IRQ(gic_spi(15)), /* IRQ15 */
+	DEFINE_RES_IRQ(gic_spi(16)), /* IRQ16 */
+	DEFINE_RES_IRQ(gic_spi(17)), /* IRQ17 */
+	DEFINE_RES_IRQ(gic_spi(18)), /* IRQ18 */
+	DEFINE_RES_IRQ(gic_spi(19)), /* IRQ19 */
+	DEFINE_RES_IRQ(gic_spi(20)), /* IRQ20 */
+	DEFINE_RES_IRQ(gic_spi(21)), /* IRQ21 */
+	DEFINE_RES_IRQ(gic_spi(22)), /* IRQ22 */
+	DEFINE_RES_IRQ(gic_spi(23)), /* IRQ23 */
+	DEFINE_RES_IRQ(gic_spi(24)), /* IRQ24 */
+	DEFINE_RES_IRQ(gic_spi(25)), /* IRQ25 */
+	DEFINE_RES_IRQ(gic_spi(26)), /* IRQ26 */
+	DEFINE_RES_IRQ(gic_spi(27)), /* IRQ27 */
+	DEFINE_RES_IRQ(gic_spi(28)), /* IRQ28 */
+	DEFINE_RES_IRQ(gic_spi(29)), /* IRQ29 */
+	DEFINE_RES_IRQ(gic_spi(30)), /* IRQ30 */
+	DEFINE_RES_IRQ(gic_spi(31)), /* IRQ31 */
+};
+
+static const struct renesas_irqc_config irqc1_data = {
+	.irq_base = irq_pin(32), /* IRQ32 -> IRQ57 */
+};
+
+static const struct resource irqc1_resources[] = {
+	DEFINE_RES_MEM(0xe61c0200, 0x200), /* IRQC Event Detector Block_1 */
+	DEFINE_RES_IRQ(gic_spi(32)), /* IRQ32 */
+	DEFINE_RES_IRQ(gic_spi(33)), /* IRQ33 */
+	DEFINE_RES_IRQ(gic_spi(34)), /* IRQ34 */
+	DEFINE_RES_IRQ(gic_spi(35)), /* IRQ35 */
+	DEFINE_RES_IRQ(gic_spi(36)), /* IRQ36 */
+	DEFINE_RES_IRQ(gic_spi(37)), /* IRQ37 */
+	DEFINE_RES_IRQ(gic_spi(38)), /* IRQ38 */
+	DEFINE_RES_IRQ(gic_spi(39)), /* IRQ39 */
+	DEFINE_RES_IRQ(gic_spi(40)), /* IRQ40 */
+	DEFINE_RES_IRQ(gic_spi(41)), /* IRQ41 */
+	DEFINE_RES_IRQ(gic_spi(42)), /* IRQ42 */
+	DEFINE_RES_IRQ(gic_spi(43)), /* IRQ43 */
+	DEFINE_RES_IRQ(gic_spi(44)), /* IRQ44 */
+	DEFINE_RES_IRQ(gic_spi(45)), /* IRQ45 */
+	DEFINE_RES_IRQ(gic_spi(46)), /* IRQ46 */
+	DEFINE_RES_IRQ(gic_spi(47)), /* IRQ47 */
+	DEFINE_RES_IRQ(gic_spi(48)), /* IRQ48 */
+	DEFINE_RES_IRQ(gic_spi(49)), /* IRQ49 */
+	DEFINE_RES_IRQ(gic_spi(50)), /* IRQ50 */
+	DEFINE_RES_IRQ(gic_spi(51)), /* IRQ51 */
+	DEFINE_RES_IRQ(gic_spi(52)), /* IRQ52 */
+	DEFINE_RES_IRQ(gic_spi(53)), /* IRQ53 */
+	DEFINE_RES_IRQ(gic_spi(54)), /* IRQ54 */
+	DEFINE_RES_IRQ(gic_spi(55)), /* IRQ55 */
+	DEFINE_RES_IRQ(gic_spi(56)), /* IRQ56 */
+	DEFINE_RES_IRQ(gic_spi(57)), /* IRQ57 */
+};
+
+#define r8a73a4_register_irqc(idx)					\
+	platform_device_register_resndata(&platform_bus, "renesas_irqc", \
+					  idx, irqc##idx##_resources,	\
+					  ARRAY_SIZE(irqc##idx##_resources), \
+					  &irqc##idx##_data,		\
+					  sizeof(struct renesas_irqc_config))
+
+/* Thermal0 -> Thermal2 */
+static const struct resource thermal0_resources[] = {
+	DEFINE_RES_MEM(0xe61f0000, 0x14),
+	DEFINE_RES_MEM(0xe61f0100, 0x38),
+	DEFINE_RES_MEM(0xe61f0200, 0x38),
+	DEFINE_RES_MEM(0xe61f0300, 0x38),
+	DEFINE_RES_IRQ(gic_spi(69)),
+};
+
+#define r8a73a4_register_thermal()					\
+	platform_device_register_simple("rcar_thermal", -1,		\
+					thermal0_resources,		\
+					ARRAY_SIZE(thermal0_resources))
+
+void __init r8a73a4_add_standard_devices(void)
+{
+	r8a73a4_register_scif(SCIFA0);
+	r8a73a4_register_scif(SCIFA1);
+	r8a73a4_register_scif(SCIFB0);
+	r8a73a4_register_scif(SCIFB1);
+	r8a73a4_register_scif(SCIFB2);
+	r8a73a4_register_scif(SCIFB3);
+	r8a73a4_register_irqc(0);
+	r8a73a4_register_irqc(1);
+	r8a73a4_register_thermal();
+}
+
+#ifdef CONFIG_USE_OF
+void __init r8a73a4_add_standard_devices_dt(void)
+{
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+}
+
+static const char *r8a73a4_boards_compat_dt[] __initdata = {
+	"renesas,r8a73a4",
+	NULL,
+};
+
+DT_MACHINE_START(R8A73A4_DT, "Generic R8A73A4 (Flattened Device Tree)")
+	.init_irq	= irqchip_init,
+	.init_machine	= r8a73a4_add_standard_devices_dt,
+	.init_time	= shmobile_timer_init,
+	.dt_compat	= r8a73a4_boards_compat_dt,
+MACHINE_END
+#endif /* CONFIG_USE_OF */
diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c
index 8b85d4d..228d7ab 100644
--- a/arch/arm/mach-shmobile/setup-r8a7740.c
+++ b/arch/arm/mach-shmobile/setup-r8a7740.c
@@ -22,6 +22,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/io.h>
+#include <linux/platform_data/irq-renesas-intc-irqpin.h>
 #include <linux/platform_device.h>
 #include <linux/of_platform.h>
 #include <linux/serial_sci.h>
@@ -94,6 +95,126 @@ void __init r8a7740_pinmux_init(void)
 	platform_device_register(&r8a7740_pfc_device);
 }
 
+static struct renesas_intc_irqpin_config irqpin0_platform_data = {
+	.irq_base = irq_pin(0), /* IRQ0 -> IRQ7 */
+};
+
+static struct resource irqpin0_resources[] = {
+	DEFINE_RES_MEM(0xe6900000, 4), /* ICR1A */
+	DEFINE_RES_MEM(0xe6900010, 4), /* INTPRI00A */
+	DEFINE_RES_MEM(0xe6900020, 1), /* INTREQ00A */
+	DEFINE_RES_MEM(0xe6900040, 1), /* INTMSK00A */
+	DEFINE_RES_MEM(0xe6900060, 1), /* INTMSKCLR00A */
+	DEFINE_RES_IRQ(gic_spi(149)), /* IRQ0 */
+	DEFINE_RES_IRQ(gic_spi(149)), /* IRQ1 */
+	DEFINE_RES_IRQ(gic_spi(149)), /* IRQ2 */
+	DEFINE_RES_IRQ(gic_spi(149)), /* IRQ3 */
+	DEFINE_RES_IRQ(gic_spi(149)), /* IRQ4 */
+	DEFINE_RES_IRQ(gic_spi(149)), /* IRQ5 */
+	DEFINE_RES_IRQ(gic_spi(149)), /* IRQ6 */
+	DEFINE_RES_IRQ(gic_spi(149)), /* IRQ7 */
+};
+
+static struct platform_device irqpin0_device = {
+	.name		= "renesas_intc_irqpin",
+	.id		= 0,
+	.resource	= irqpin0_resources,
+	.num_resources	= ARRAY_SIZE(irqpin0_resources),
+	.dev		= {
+		.platform_data  = &irqpin0_platform_data,
+	},
+};
+
+static struct renesas_intc_irqpin_config irqpin1_platform_data = {
+	.irq_base = irq_pin(8), /* IRQ8 -> IRQ15 */
+};
+
+static struct resource irqpin1_resources[] = {
+	DEFINE_RES_MEM(0xe6900004, 4), /* ICR2A */
+	DEFINE_RES_MEM(0xe6900014, 4), /* INTPRI10A */
+	DEFINE_RES_MEM(0xe6900024, 1), /* INTREQ10A */
+	DEFINE_RES_MEM(0xe6900044, 1), /* INTMSK10A */
+	DEFINE_RES_MEM(0xe6900064, 1), /* INTMSKCLR10A */
+	DEFINE_RES_IRQ(gic_spi(149)), /* IRQ8 */
+	DEFINE_RES_IRQ(gic_spi(149)), /* IRQ9 */
+	DEFINE_RES_IRQ(gic_spi(149)), /* IRQ10 */
+	DEFINE_RES_IRQ(gic_spi(149)), /* IRQ11 */
+	DEFINE_RES_IRQ(gic_spi(149)), /* IRQ12 */
+	DEFINE_RES_IRQ(gic_spi(149)), /* IRQ13 */
+	DEFINE_RES_IRQ(gic_spi(149)), /* IRQ14 */
+	DEFINE_RES_IRQ(gic_spi(149)), /* IRQ15 */
+};
+
+static struct platform_device irqpin1_device = {
+	.name		= "renesas_intc_irqpin",
+	.id		= 1,
+	.resource	= irqpin1_resources,
+	.num_resources	= ARRAY_SIZE(irqpin1_resources),
+	.dev		= {
+		.platform_data  = &irqpin1_platform_data,
+	},
+};
+
+static struct renesas_intc_irqpin_config irqpin2_platform_data = {
+	.irq_base = irq_pin(16), /* IRQ16 -> IRQ23 */
+};
+
+static struct resource irqpin2_resources[] = {
+	DEFINE_RES_MEM(0xe6900008, 4), /* ICR3A */
+	DEFINE_RES_MEM(0xe6900018, 4), /* INTPRI30A */
+	DEFINE_RES_MEM(0xe6900028, 1), /* INTREQ30A */
+	DEFINE_RES_MEM(0xe6900048, 1), /* INTMSK30A */
+	DEFINE_RES_MEM(0xe6900068, 1), /* INTMSKCLR30A */
+	DEFINE_RES_IRQ(gic_spi(149)), /* IRQ16 */
+	DEFINE_RES_IRQ(gic_spi(149)), /* IRQ17 */
+	DEFINE_RES_IRQ(gic_spi(149)), /* IRQ18 */
+	DEFINE_RES_IRQ(gic_spi(149)), /* IRQ19 */
+	DEFINE_RES_IRQ(gic_spi(149)), /* IRQ20 */
+	DEFINE_RES_IRQ(gic_spi(149)), /* IRQ21 */
+	DEFINE_RES_IRQ(gic_spi(149)), /* IRQ22 */
+	DEFINE_RES_IRQ(gic_spi(149)), /* IRQ23 */
+};
+
+static struct platform_device irqpin2_device = {
+	.name		= "renesas_intc_irqpin",
+	.id		= 2,
+	.resource	= irqpin2_resources,
+	.num_resources	= ARRAY_SIZE(irqpin2_resources),
+	.dev		= {
+		.platform_data  = &irqpin2_platform_data,
+	},
+};
+
+static struct renesas_intc_irqpin_config irqpin3_platform_data = {
+	.irq_base = irq_pin(24), /* IRQ24 -> IRQ31 */
+};
+
+static struct resource irqpin3_resources[] = {
+	DEFINE_RES_MEM(0xe690000c, 4), /* ICR3A */
+	DEFINE_RES_MEM(0xe690001c, 4), /* INTPRI30A */
+	DEFINE_RES_MEM(0xe690002c, 1), /* INTREQ30A */
+	DEFINE_RES_MEM(0xe690004c, 1), /* INTMSK30A */
+	DEFINE_RES_MEM(0xe690006c, 1), /* INTMSKCLR30A */
+	DEFINE_RES_IRQ(gic_spi(149)), /* IRQ24 */
+	DEFINE_RES_IRQ(gic_spi(149)), /* IRQ25 */
+	DEFINE_RES_IRQ(gic_spi(149)), /* IRQ26 */
+	DEFINE_RES_IRQ(gic_spi(149)), /* IRQ27 */
+	DEFINE_RES_IRQ(gic_spi(149)), /* IRQ28 */
+	DEFINE_RES_IRQ(gic_spi(149)), /* IRQ29 */
+	DEFINE_RES_IRQ(gic_spi(149)), /* IRQ30 */
+	DEFINE_RES_IRQ(gic_spi(149)), /* IRQ31 */
+};
+
+static struct platform_device irqpin3_device = {
+	.name		= "renesas_intc_irqpin",
+	.id		= 3,
+	.resource	= irqpin3_resources,
+	.num_resources	= ARRAY_SIZE(irqpin3_resources),
+	.dev		= {
+		.platform_data  = &irqpin3_platform_data,
+	},
+};
+
 /* SCIFA0 */
 static struct plat_sci_port scif0_platform_data = {
 	.mapbase	= 0xe6c40000,
@@ -101,7 +222,7 @@ static struct plat_sci_port scif0_platform_data = {
 	.scscr		= SCSCR_RE | SCSCR_TE,
 	.scbrr_algo_id	= SCBRR_ALGO_4,
 	.type		= PORT_SCIFA,
-	.irqs		= SCIx_IRQ_MUXED(evt2irq(0x0c00)),
+	.irqs		= SCIx_IRQ_MUXED(gic_spi(100)),
 };
 
 static struct platform_device scif0_device = {
@@ -119,7 +240,7 @@ static struct plat_sci_port scif1_platform_data = {
 	.scscr		= SCSCR_RE | SCSCR_TE,
 	.scbrr_algo_id	= SCBRR_ALGO_4,
 	.type		= PORT_SCIFA,
-	.irqs		= SCIx_IRQ_MUXED(evt2irq(0x0c20)),
+	.irqs		= SCIx_IRQ_MUXED(gic_spi(101)),
 };
 
 static struct platform_device scif1_device = {
@@ -137,7 +258,7 @@ static struct plat_sci_port scif2_platform_data = {
 	.scscr		= SCSCR_RE | SCSCR_TE,
 	.scbrr_algo_id	= SCBRR_ALGO_4,
 	.type		= PORT_SCIFA,
-	.irqs		= SCIx_IRQ_MUXED(evt2irq(0x0c40)),
+	.irqs		= SCIx_IRQ_MUXED(gic_spi(102)),
 };
 
 static struct platform_device scif2_device = {
@@ -155,7 +276,7 @@ static struct plat_sci_port scif3_platform_data = {
 	.scscr		= SCSCR_RE | SCSCR_TE,
 	.scbrr_algo_id	= SCBRR_ALGO_4,
 	.type		= PORT_SCIFA,
-	.irqs		= SCIx_IRQ_MUXED(evt2irq(0x0c60)),
+	.irqs		= SCIx_IRQ_MUXED(gic_spi(103)),
 };
 
 static struct platform_device scif3_device = {
@@ -173,7 +294,7 @@ static struct plat_sci_port scif4_platform_data = {
 	.scscr		= SCSCR_RE | SCSCR_TE,
 	.scbrr_algo_id	= SCBRR_ALGO_4,
 	.type		= PORT_SCIFA,
-	.irqs		= SCIx_IRQ_MUXED(evt2irq(0x0d20)),
+	.irqs		= SCIx_IRQ_MUXED(gic_spi(104)),
 };
 
 static struct platform_device scif4_device = {
@@ -191,7 +312,7 @@ static struct plat_sci_port scif5_platform_data = {
 	.scscr		= SCSCR_RE | SCSCR_TE,
 	.scbrr_algo_id	= SCBRR_ALGO_4,
 	.type		= PORT_SCIFA,
-	.irqs		= SCIx_IRQ_MUXED(evt2irq(0x0d40)),
+	.irqs		= SCIx_IRQ_MUXED(gic_spi(105)),
 };
 
 static struct platform_device scif5_device = {
@@ -209,7 +330,7 @@ static struct plat_sci_port scif6_platform_data = {
 	.scscr		= SCSCR_RE | SCSCR_TE,
 	.scbrr_algo_id	= SCBRR_ALGO_4,
 	.type		= PORT_SCIFA,
-	.irqs		= SCIx_IRQ_MUXED(evt2irq(0x04c0)),
+	.irqs		= SCIx_IRQ_MUXED(gic_spi(106)),
 };
 
 static struct platform_device scif6_device = {
@@ -227,7 +348,7 @@ static struct plat_sci_port scif7_platform_data = {
 	.scscr		= SCSCR_RE | SCSCR_TE,
 	.scbrr_algo_id	= SCBRR_ALGO_4,
 	.type		= PORT_SCIFA,
-	.irqs		= SCIx_IRQ_MUXED(evt2irq(0x04e0)),
+	.irqs		= SCIx_IRQ_MUXED(gic_spi(107)),
 };
 
 static struct platform_device scif7_device = {
@@ -245,7 +366,7 @@ static struct plat_sci_port scifb_platform_data = {
 	.scscr		= SCSCR_RE | SCSCR_TE,
 	.scbrr_algo_id	= SCBRR_ALGO_4,
 	.type		= PORT_SCIFB,
-	.irqs		= SCIx_IRQ_MUXED(evt2irq(0x0d60)),
+	.irqs		= SCIx_IRQ_MUXED(gic_spi(108)),
 };
 
 static struct platform_device scifb_device = {
@@ -273,7 +394,7 @@ static struct resource cmt10_resources[] = {
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= evt2irq(0x0b00),
+		.start	= gic_spi(58),
 		.flags	= IORESOURCE_IRQ,
 	},
 };
@@ -304,7 +425,7 @@ static struct resource tmu00_resources[] = {
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= intcs_evt2irq(0xe80),
+		.start	= gic_spi(198),
 		.flags	= IORESOURCE_IRQ,
 	},
 };
@@ -334,7 +455,7 @@ static struct resource tmu01_resources[] = {
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= intcs_evt2irq(0xea0),
+		.start	= gic_spi(199),
 		.flags	= IORESOURCE_IRQ,
 	},
 };
@@ -364,7 +485,7 @@ static struct resource tmu02_resources[] = {
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= intcs_evt2irq(0xec0),
+		.start	= gic_spi(200),
 		.flags	= IORESOURCE_IRQ,
 	},
 };
@@ -411,6 +532,10 @@ static struct platform_device ipmmu_device = {
 };
 
 static struct platform_device *r8a7740_early_devices[] __initdata = {
+	&irqpin0_device,
+	&irqpin1_device,
+	&irqpin2_device,
+	&irqpin3_device,
 	&scif0_device,
 	&scif1_device,
 	&scif2_device,
@@ -525,14 +650,14 @@ static struct resource r8a7740_dmae0_resources[] = {
 	},
 	{
 		.name	= "error_irq",
-		.start	= evt2irq(0x20c0),
-		.end	= evt2irq(0x20c0),
+		.start	= gic_spi(34),
+		.end	= gic_spi(34),
 		.flags	= IORESOURCE_IRQ,
 	},
 	{
 		/* IRQ for channels 0-5 */
-		.start	= evt2irq(0x2000),
-		.end	= evt2irq(0x20a0),
+		.start	= gic_spi(28),
+		.end	= gic_spi(33),
 		.flags	= IORESOURCE_IRQ,
 	},
 };
@@ -553,14 +678,14 @@ static struct resource r8a7740_dmae1_resources[] = {
 	},
 	{
 		.name	= "error_irq",
-		.start	= evt2irq(0x21c0),
-		.end	= evt2irq(0x21c0),
+		.start	= gic_spi(41),
+		.end	= gic_spi(41),
 		.flags	= IORESOURCE_IRQ,
 	},
 	{
 		/* IRQ for channels 0-5 */
-		.start	= evt2irq(0x2100),
-		.end	= evt2irq(0x21a0),
+		.start	= gic_spi(35),
+		.end	= gic_spi(40),
 		.flags	= IORESOURCE_IRQ,
 	},
 };
@@ -581,14 +706,14 @@ static struct resource r8a7740_dmae2_resources[] = {
 	},
 	{
 		.name	= "error_irq",
-		.start	= evt2irq(0x22c0),
-		.end	= evt2irq(0x22c0),
+		.start	= gic_spi(48),
+		.end	= gic_spi(48),
 		.flags	= IORESOURCE_IRQ,
 	},
 	{
 		/* IRQ for channels 0-5 */
-		.start	= evt2irq(0x2200),
-		.end	= evt2irq(0x22a0),
+		.start	= gic_spi(42),
+		.end	= gic_spi(47),
 		.flags	= IORESOURCE_IRQ,
 	},
 };
@@ -677,8 +802,8 @@ static struct resource r8a7740_usb_dma_resources[] = {
 	},
 	{
 		/* IRQ for channels */
-		.start	= evt2irq(0x0a00),
-		.end	= evt2irq(0x0a00),
+		.start	= gic_spi(49),
+		.end	= gic_spi(49),
 		.flags	= IORESOURCE_IRQ,
 	},
 };
@@ -702,8 +827,8 @@ static struct resource i2c0_resources[] = {
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= intcs_evt2irq(0xe00),
-		.end	= intcs_evt2irq(0xe60),
+		.start	= gic_spi(201),
+		.end	= gic_spi(204),
 		.flags	= IORESOURCE_IRQ,
 	},
 };
@@ -716,8 +841,8 @@ static struct resource i2c1_resources[] = {
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start  = evt2irq(0x780), /* IIC1_ALI1 */
-		.end    = evt2irq(0x7e0), /* IIC1_DTEI1 */
+		.start  = gic_spi(70), /* IIC1_ALI1 */
+		.end    = gic_spi(73), /* IIC1_DTEI1 */
 		.flags	= IORESOURCE_IRQ,
 	},
 };
@@ -738,8 +863,8 @@ static struct platform_device i2c1_device = {
 
 static struct resource pmu_resources[] = {
 	[0] = {
-		.start	= evt2irq(0x19a0),
-		.end	= evt2irq(0x19a0),
+		.start	= gic_spi(83),
+		.end	= gic_spi(83),
 		.flags  = IORESOURCE_IRQ,
 	},
 };
@@ -904,7 +1029,6 @@ DT_MACHINE_START(R8A7740_DT, "Generic R8A7740 (Flattened Device Tree)")
 	.map_io		= r8a7740_map_io,
 	.init_early	= r8a7740_add_early_devices_dt,
 	.init_irq	= r8a7740_init_irq,
-	.handle_irq	= shmobile_handle_irq_intc,
 	.init_machine	= r8a7740_add_standard_devices_dt,
 	.init_time	= shmobile_timer_init,
 	.dt_compat	= r8a7740_boards_compat_dt,
diff --git a/arch/arm/mach-shmobile/setup-r8a7778.c b/arch/arm/mach-shmobile/setup-r8a7778.c
new file mode 100644
index 0000000..2882305
--- /dev/null
+++ b/arch/arm/mach-shmobile/setup-r8a7778.c
@@ -0,0 +1,229 @@
+/*
+ * r8a7778 processor support
+ *
+ * Copyright (C) 2013  Renesas Solutions Corp.
+ * Copyright (C) 2013  Kuninori Morimoto <kuninori.morimoto.gx@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
+ * 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/kernel.h>
+#include <linux/io.h>
+#include <linux/irqchip/arm-gic.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_data/irq-renesas-intc-irqpin.h>
+#include <linux/platform_device.h>
+#include <linux/irqchip.h>
+#include <linux/serial_sci.h>
+#include <linux/sh_timer.h>
+#include <mach/irqs.h>
+#include <mach/r8a7778.h>
+#include <mach/common.h>
+#include <asm/mach/arch.h>
+#include <asm/hardware/cache-l2x0.h>
+
+/* SCIF */
+#define SCIF_INFO(baseaddr, irq)				\
+{								\
+	.mapbase	= baseaddr,				\
+	.flags		= UPF_BOOT_AUTOCONF | UPF_IOREMAP,	\
+	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_CKE1,	\
+	.scbrr_algo_id	= SCBRR_ALGO_2,				\
+	.type		= PORT_SCIF,				\
+	.irqs		= SCIx_IRQ_MUXED(irq),			\
+}
+
+static struct plat_sci_port scif_platform_data[] = {
+	SCIF_INFO(0xffe40000, gic_iid(0x66)),
+	SCIF_INFO(0xffe41000, gic_iid(0x67)),
+	SCIF_INFO(0xffe42000, gic_iid(0x68)),
+	SCIF_INFO(0xffe43000, gic_iid(0x69)),
+	SCIF_INFO(0xffe44000, gic_iid(0x6a)),
+	SCIF_INFO(0xffe45000, gic_iid(0x6b)),
+};
+
+/* TMU */
+static struct resource sh_tmu0_resources[] = {
+	DEFINE_RES_MEM(0xffd80008, 12),
+	DEFINE_RES_IRQ(gic_iid(0x40)),
+};
+
+static struct sh_timer_config sh_tmu0_platform_data = {
+	.name			= "TMU00",
+	.channel_offset		= 0x4,
+	.timer_bit		= 0,
+	.clockevent_rating	= 200,
+};
+
+static struct resource sh_tmu1_resources[] = {
+	DEFINE_RES_MEM(0xffd80014, 12),
+	DEFINE_RES_IRQ(gic_iid(0x41)),
+};
+
+static struct sh_timer_config sh_tmu1_platform_data = {
+	.name			= "TMU01",
+	.channel_offset		= 0x10,
+	.timer_bit		= 1,
+	.clocksource_rating	= 200,
+};
+
+#define r8a7778_register_tmu(idx)			\
+	platform_device_register_resndata(		\
+		&platform_bus, "sh_tmu", idx,		\
+		sh_tmu##idx##_resources,		\
+		ARRAY_SIZE(sh_tmu##idx##_resources),	\
+		&sh_tmu##idx##_platform_data,		\
+		sizeof(sh_tmu##idx##_platform_data))
+
+void __init r8a7778_add_standard_devices(void)
+{
+	int i;
+
+#ifdef CONFIG_CACHE_L2X0
+	void __iomem *base = ioremap_nocache(0xf0100000, 0x1000);
+	if (base) {
+		/*
+		 * Early BRESP enable, Shared attribute override enable, 64K*16way
+		 * don't call iounmap(base)
+		 */
+		l2x0_init(base, 0x40470000, 0x82000fff);
+	}
+#endif
+
+	for (i = 0; i < ARRAY_SIZE(scif_platform_data); i++)
+		platform_device_register_data(&platform_bus, "sh-sci", i,
+					      &scif_platform_data[i],
+					      sizeof(struct plat_sci_port));
+
+	r8a7778_register_tmu(0);
+	r8a7778_register_tmu(1);
+}
+
+static struct renesas_intc_irqpin_config irqpin_platform_data = {
+	.irq_base = irq_pin(0), /* IRQ0 -> IRQ3 */
+	.sense_bitfield_width = 2,
+};
+
+static struct resource irqpin_resources[] = {
+	DEFINE_RES_MEM(0xfe78001c, 4), /* ICR1 */
+	DEFINE_RES_MEM(0xfe780010, 4), /* INTPRI */
+	DEFINE_RES_MEM(0xfe780024, 4), /* INTREQ */
+	DEFINE_RES_MEM(0xfe780044, 4), /* INTMSK0 */
+	DEFINE_RES_MEM(0xfe780064, 4), /* INTMSKCLR0 */
+	DEFINE_RES_IRQ(gic_iid(0x3b)), /* IRQ0 */
+	DEFINE_RES_IRQ(gic_iid(0x3c)), /* IRQ1 */
+	DEFINE_RES_IRQ(gic_iid(0x3d)), /* IRQ2 */
+	DEFINE_RES_IRQ(gic_iid(0x3e)), /* IRQ3 */
+};
+
+void __init r8a7778_init_irq_extpin(int irlm)
+{
+	void __iomem *icr0 = ioremap_nocache(0xfe780000, PAGE_SIZE);
+	unsigned long tmp;
+
+	if (!icr0) {
+		pr_warn("r8a7778: unable to setup external irq pin mode\n");
+		return;
+	}
+
+	tmp = ioread32(icr0);
+	if (irlm)
+		tmp |= 1 << 23; /* IRQ0 -> IRQ3 as individual pins */
+	else
+		tmp &= ~(1 << 23); /* IRL mode - not supported */
+	tmp |= (1 << 21); /* LVLMODE = 1 */
+	iowrite32(tmp, icr0);
+	iounmap(icr0);
+
+	if (irlm)
+		platform_device_register_resndata(
+			&platform_bus, "renesas_intc_irqpin", -1,
+			irqpin_resources, ARRAY_SIZE(irqpin_resources),
+			&irqpin_platform_data, sizeof(irqpin_platform_data));
+}
+
+#define INT2SMSKCR0	0x82288 /* 0xfe782288 */
+#define INT2SMSKCR1	0x8228c /* 0xfe78228c */
+
+#define INT2NTSR0	0x00018 /* 0xfe700018 */
+#define INT2NTSR1	0x0002c /* 0xfe70002c */
+static void __init r8a7778_init_irq_common(void)
+{
+	void __iomem *base = ioremap_nocache(0xfe700000, 0x00100000);
+
+	BUG_ON(!base);
+
+	/* route all interrupts to ARM */
+	__raw_writel(0x73ffffff, base + INT2NTSR0);
+	__raw_writel(0xffffffff, base + INT2NTSR1);
+
+	/* unmask all known interrupts in INTCS2 */
+	__raw_writel(0x08330773, base + INT2SMSKCR0);
+	__raw_writel(0x00311110, base + INT2SMSKCR1);
+
+	iounmap(base);
+}
+
+void __init r8a7778_init_irq(void)
+{
+	void __iomem *gic_dist_base;
+	void __iomem *gic_cpu_base;
+
+	gic_dist_base = ioremap_nocache(0xfe438000, PAGE_SIZE);
+	gic_cpu_base  = ioremap_nocache(0xfe430000, PAGE_SIZE);
+	BUG_ON(!gic_dist_base || !gic_cpu_base);
+
+	/* use GIC to handle interrupts */
+	gic_init(0, 29, gic_dist_base, gic_cpu_base);
+
+	r8a7778_init_irq_common();
+}
+
+void __init r8a7778_init_delay(void)
+{
+	shmobile_setup_delay(800, 1, 3); /* Cortex-A9 @ 800MHz */
+}
+
+#ifdef CONFIG_USE_OF
+void __init r8a7778_init_irq_dt(void)
+{
+	irqchip_init();
+	r8a7778_init_irq_common();
+}
+
+static const struct of_dev_auxdata r8a7778_auxdata_lookup[] __initconst = {
+	{},
+};
+
+void __init r8a7778_add_standard_devices_dt(void)
+{
+	of_platform_populate(NULL, of_default_bus_match_table,
+			     r8a7778_auxdata_lookup, NULL);
+}
+
+static const char *r8a7778_compat_dt[] __initdata = {
+	"renesas,r8a7778",
+	NULL,
+};
+
+DT_MACHINE_START(R8A7778_DT, "Generic R8A7778 (Flattened Device Tree)")
+	.init_early	= r8a7778_init_delay,
+	.init_irq	= r8a7778_init_irq_dt,
+	.init_machine	= r8a7778_add_standard_devices_dt,
+	.init_time	= shmobile_timer_init,
+	.dt_compat	= r8a7778_compat_dt,
+MACHINE_END
+
+#endif /* CONFIG_USE_OF */
diff --git a/arch/arm/mach-shmobile/setup-r8a7779.c b/arch/arm/mach-shmobile/setup-r8a7779.c
index c54ff9b..a460ba3 100644
--- a/arch/arm/mach-shmobile/setup-r8a7779.c
+++ b/arch/arm/mach-shmobile/setup-r8a7779.c
@@ -21,6 +21,8 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
+#include <linux/of_platform.h>
+#include <linux/platform_data/gpio-rcar.h>
 #include <linux/platform_device.h>
 #include <linux/delay.h>
 #include <linux/input.h>
@@ -28,6 +30,7 @@
 #include <linux/serial_sci.h>
 #include <linux/sh_intc.h>
 #include <linux/sh_timer.h>
+#include <linux/dma-mapping.h>
 #include <mach/hardware.h>
 #include <mach/irqs.h>
 #include <mach/r8a7779.h>
@@ -66,11 +69,6 @@ static struct resource r8a7779_pfc_resources[] = {
 		.end	= 0xfffc023b,
 		.flags	= IORESOURCE_MEM,
 	},
-	[1] = {
-		.start	= 0xffc40000,
-		.end	= 0xffc46fff,
-		.flags	= IORESOURCE_MEM,
-	}
 };
 
 static struct platform_device r8a7779_pfc_device = {
@@ -80,9 +78,59 @@ static struct platform_device r8a7779_pfc_device = {
 	.num_resources	= ARRAY_SIZE(r8a7779_pfc_resources),
 };
 
+#define R8A7779_GPIO(idx, npins) \
+static struct resource r8a7779_gpio##idx##_resources[] = {		\
+	[0] = {								\
+		.start	= 0xffc40000 + 0x1000 * (idx),			\
+		.end	= 0xffc4002b + 0x1000 * (idx),			\
+		.flags	= IORESOURCE_MEM,				\
+	},								\
+	[1] = {								\
+		.start	= gic_iid(0xad + (idx)),			\
+		.flags	= IORESOURCE_IRQ,				\
+	}								\
+};									\
+									\
+static struct gpio_rcar_config r8a7779_gpio##idx##_platform_data = {	\
+	.gpio_base	= 32 * (idx),					\
+	.irq_base	= 0,						\
+	.number_of_pins	= npins,					\
+	.pctl_name	= "pfc-r8a7779",				\
+};									\
+									\
+static struct platform_device r8a7779_gpio##idx##_device = {		\
+	.name		= "gpio_rcar",					\
+	.id		= idx,						\
+	.resource	= r8a7779_gpio##idx##_resources,		\
+	.num_resources	= ARRAY_SIZE(r8a7779_gpio##idx##_resources),	\
+	.dev		= {						\
+		.platform_data	= &r8a7779_gpio##idx##_platform_data,	\
+	},								\
+}
+
+R8A7779_GPIO(0, 32);
+R8A7779_GPIO(1, 32);
+R8A7779_GPIO(2, 32);
+R8A7779_GPIO(3, 32);
+R8A7779_GPIO(4, 32);
+R8A7779_GPIO(5, 32);
+R8A7779_GPIO(6, 9);
+
+static struct platform_device *r8a7779_pinctrl_devices[] __initdata = {
+	&r8a7779_pfc_device,
+	&r8a7779_gpio0_device,
+	&r8a7779_gpio1_device,
+	&r8a7779_gpio2_device,
+	&r8a7779_gpio3_device,
+	&r8a7779_gpio4_device,
+	&r8a7779_gpio5_device,
+	&r8a7779_gpio6_device,
+};
+
 void __init r8a7779_pinmux_init(void)
 {
-	platform_device_register(&r8a7779_pfc_device);
+	platform_add_devices(r8a7779_pinctrl_devices,
+			    ARRAY_SIZE(r8a7779_pinctrl_devices));
 }
 
 static struct plat_sci_port scif0_platform_data = {
@@ -91,7 +139,7 @@ static struct plat_sci_port scif0_platform_data = {
 	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_CKE1,
 	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
-	.irqs		= SCIx_IRQ_MUXED(gic_spi(88)),
+	.irqs		= SCIx_IRQ_MUXED(gic_iid(0x78)),
 };
 
 static struct platform_device scif0_device = {
@@ -108,7 +156,7 @@ static struct plat_sci_port scif1_platform_data = {
 	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_CKE1,
 	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
-	.irqs		= SCIx_IRQ_MUXED(gic_spi(89)),
+	.irqs		= SCIx_IRQ_MUXED(gic_iid(0x79)),
 };
 
 static struct platform_device scif1_device = {
@@ -125,7 +173,7 @@ static struct plat_sci_port scif2_platform_data = {
 	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_CKE1,
 	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
-	.irqs		= SCIx_IRQ_MUXED(gic_spi(90)),
+	.irqs		= SCIx_IRQ_MUXED(gic_iid(0x7a)),
 };
 
 static struct platform_device scif2_device = {
@@ -142,7 +190,7 @@ static struct plat_sci_port scif3_platform_data = {
 	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_CKE1,
 	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
-	.irqs		= SCIx_IRQ_MUXED(gic_spi(91)),
+	.irqs		= SCIx_IRQ_MUXED(gic_iid(0x7b)),
 };
 
 static struct platform_device scif3_device = {
@@ -159,7 +207,7 @@ static struct plat_sci_port scif4_platform_data = {
 	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_CKE1,
 	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
-	.irqs		= SCIx_IRQ_MUXED(gic_spi(92)),
+	.irqs		= SCIx_IRQ_MUXED(gic_iid(0x7c)),
 };
 
 static struct platform_device scif4_device = {
@@ -176,7 +224,7 @@ static struct plat_sci_port scif5_platform_data = {
 	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_CKE1,
 	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
-	.irqs		= SCIx_IRQ_MUXED(gic_spi(93)),
+	.irqs		= SCIx_IRQ_MUXED(gic_iid(0x7d)),
 };
 
 static struct platform_device scif5_device = {
@@ -203,7 +251,7 @@ static struct resource tmu00_resources[] = {
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= gic_spi(32),
+		.start	= gic_iid(0x40),
 		.flags	= IORESOURCE_IRQ,
 	},
 };
@@ -233,7 +281,7 @@ static struct resource tmu01_resources[] = {
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= gic_spi(33),
+		.start	= gic_iid(0x41),
 		.flags	= IORESOURCE_IRQ,
 	},
 };
@@ -255,7 +303,7 @@ static struct resource rcar_i2c0_res[] = {
 		.end    = 0xffc70fff,
 		.flags  = IORESOURCE_MEM,
 	}, {
-		.start  = gic_spi(79),
+		.start  = gic_iid(0x6f),
 		.flags  = IORESOURCE_IRQ,
 	},
 };
@@ -273,7 +321,7 @@ static struct resource rcar_i2c1_res[] = {
 		.end    = 0xffc71fff,
 		.flags  = IORESOURCE_MEM,
 	}, {
-		.start  = gic_spi(82),
+		.start  = gic_iid(0x72),
 		.flags  = IORESOURCE_IRQ,
 	},
 };
@@ -291,7 +339,7 @@ static struct resource rcar_i2c2_res[] = {
 		.end    = 0xffc72fff,
 		.flags  = IORESOURCE_MEM,
 	}, {
-		.start  = gic_spi(80),
+		.start  = gic_iid(0x70),
 		.flags  = IORESOURCE_IRQ,
 	},
 };
@@ -309,7 +357,7 @@ static struct resource rcar_i2c3_res[] = {
 		.end    = 0xffc73fff,
 		.flags  = IORESOURCE_MEM,
 	}, {
-		.start  = gic_spi(81),
+		.start  = gic_iid(0x71),
 		.flags  = IORESOURCE_IRQ,
 	},
 };
@@ -321,7 +369,31 @@ static struct platform_device i2c3_device = {
 	.num_resources	= ARRAY_SIZE(rcar_i2c3_res),
 };
 
-static struct platform_device *r8a7779_early_devices[] __initdata = {
+static struct resource sata_resources[] = {
+	[0] = {
+		.name	= "rcar-sata",
+		.start	= 0xfc600000,
+		.end	= 0xfc601fff,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= gic_iid(0x84),
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device sata_device = {
+	.name		= "sata_rcar",
+	.id		= -1,
+	.resource	= sata_resources,
+	.num_resources	= ARRAY_SIZE(sata_resources),
+	.dev		= {
+		.dma_mask		= &sata_device.dev.coherent_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
+
+static struct platform_device *r8a7779_devices_dt[] __initdata = {
 	&scif0_device,
 	&scif1_device,
 	&scif2_device,
@@ -330,13 +402,14 @@ static struct platform_device *r8a7779_early_devices[] __initdata = {
 	&scif5_device,
 	&tmu00_device,
 	&tmu01_device,
+};
+
+static struct platform_device *r8a7779_late_devices[] __initdata = {
 	&i2c0_device,
 	&i2c1_device,
 	&i2c2_device,
 	&i2c3_device,
-};
-
-static struct platform_device *r8a7779_late_devices[] __initdata = {
+	&sata_device,
 };
 
 void __init r8a7779_add_standard_devices(void)
@@ -349,8 +422,8 @@ void __init r8a7779_add_standard_devices(void)
 
 	r8a7779_init_pm_domains();
 
-	platform_add_devices(r8a7779_early_devices,
-			    ARRAY_SIZE(r8a7779_early_devices));
+	platform_add_devices(r8a7779_devices_dt,
+			    ARRAY_SIZE(r8a7779_devices_dt));
 	platform_add_devices(r8a7779_late_devices,
 			    ARRAY_SIZE(r8a7779_late_devices));
 }
@@ -367,8 +440,8 @@ void __init r8a7779_earlytimer_init(void)
 
 void __init r8a7779_add_early_devices(void)
 {
-	early_platform_add_devices(r8a7779_early_devices,
-				   ARRAY_SIZE(r8a7779_early_devices));
+	early_platform_add_devices(r8a7779_devices_dt,
+				   ARRAY_SIZE(r8a7779_devices_dt));
 
 	/* Early serial console setup is not included here due to
 	 * memory map collisions. The SCIF serial ports in r8a7779
@@ -386,3 +459,40 @@ void __init r8a7779_add_early_devices(void)
 	 * command line in case of the marzen board.
 	 */
 }
+
+#ifdef CONFIG_USE_OF
+void __init r8a7779_init_delay(void)
+{
+	shmobile_setup_delay(1000, 2, 4); /* Cortex-A9 @ 1000MHz */
+}
+
+static const struct of_dev_auxdata r8a7779_auxdata_lookup[] __initconst = {
+	{},
+};
+
+void __init r8a7779_add_standard_devices_dt(void)
+{
+	/* clocks are setup late during boot in the case of DT */
+	r8a7779_clock_init();
+
+	platform_add_devices(r8a7779_devices_dt,
+			     ARRAY_SIZE(r8a7779_devices_dt));
+	of_platform_populate(NULL, of_default_bus_match_table,
+			     r8a7779_auxdata_lookup, NULL);
+}
+
+static const char *r8a7779_compat_dt[] __initdata = {
+	"renesas,r8a7779",
+	NULL,
+};
+
+DT_MACHINE_START(R8A7779_DT, "Generic R8A7779 (Flattened Device Tree)")
+	.map_io		= r8a7779_map_io,
+	.init_early	= r8a7779_init_delay,
+	.nr_irqs	= NR_IRQS_LEGACY,
+	.init_irq	= r8a7779_init_irq_dt,
+	.init_machine	= r8a7779_add_standard_devices_dt,
+	.init_time	= shmobile_timer_init,
+	.dt_compat	= r8a7779_compat_dt,
+MACHINE_END
+#endif /* CONFIG_USE_OF */
diff --git a/arch/arm/mach-shmobile/setup-r8a7790.c b/arch/arm/mach-shmobile/setup-r8a7790.c
new file mode 100644
index 0000000..481201a
--- /dev/null
+++ b/arch/arm/mach-shmobile/setup-r8a7790.c
@@ -0,0 +1,137 @@
+/*
+ * r8a7790 processor support
+ *
+ * Copyright (C) 2013  Renesas Solutions Corp.
+ * Copyright (C) 2013  Magnus Damm
+ *
+ * This program is free software; 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/irq.h>
+#include <linux/irqchip.h>
+#include <linux/kernel.h>
+#include <linux/of_platform.h>
+#include <linux/serial_sci.h>
+#include <linux/platform_data/irq-renesas-irqc.h>
+#include <mach/common.h>
+#include <mach/irqs.h>
+#include <mach/r8a7790.h>
+#include <asm/mach/arch.h>
+
+static const struct resource pfc_resources[] = {
+	DEFINE_RES_MEM(0xe6060000, 0x250),
+};
+
+void __init r8a7790_pinmux_init(void)
+{
+	platform_device_register_simple("pfc-r8a7790", -1, pfc_resources,
+					ARRAY_SIZE(pfc_resources));
+}
+
+#define SCIF_COMMON(scif_type, baseaddr, irq)			\
+	.type		= scif_type,				\
+	.mapbase	= baseaddr,				\
+	.flags		= UPF_BOOT_AUTOCONF | UPF_IOREMAP,	\
+	.irqs		= SCIx_IRQ_MUXED(irq)
+
+#define SCIFA_DATA(index, baseaddr, irq)		\
+[index] = {						\
+	SCIF_COMMON(PORT_SCIFA, baseaddr, irq),		\
+	.scbrr_algo_id	= SCBRR_ALGO_4,			\
+	.scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE0,	\
+}
+
+#define SCIFB_DATA(index, baseaddr, irq)	\
+[index] = {					\
+	SCIF_COMMON(PORT_SCIFB, baseaddr, irq),	\
+	.scbrr_algo_id	= SCBRR_ALGO_4,		\
+	.scscr = SCSCR_RE | SCSCR_TE,		\
+}
+
+#define SCIF_DATA(index, baseaddr, irq)		\
+[index] = {						\
+	SCIF_COMMON(PORT_SCIF, baseaddr, irq),		\
+	.scbrr_algo_id	= SCBRR_ALGO_2,			\
+	.scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE1,	\
+}
+
+enum { SCIFA0, SCIFA1, SCIFB0, SCIFB1, SCIFB2, SCIFA2, SCIF0, SCIF1 };
+
+static const struct plat_sci_port scif[] = {
+	SCIFA_DATA(SCIFA0, 0xe6c40000, gic_spi(144)), /* SCIFA0 */
+	SCIFA_DATA(SCIFA1, 0xe6c50000, gic_spi(145)), /* SCIFA1 */
+	SCIFB_DATA(SCIFB0, 0xe6c20000, gic_spi(148)), /* SCIFB0 */
+	SCIFB_DATA(SCIFB1, 0xe6c30000, gic_spi(149)), /* SCIFB1 */
+	SCIFB_DATA(SCIFB2, 0xe6ce0000, gic_spi(150)), /* SCIFB2 */
+	SCIFA_DATA(SCIFA2, 0xe6c60000, gic_spi(151)), /* SCIFA2 */
+	SCIF_DATA(SCIF0, 0xe6e60000, gic_spi(152)), /* SCIF0 */
+	SCIF_DATA(SCIF1, 0xe6e68000, gic_spi(153)), /* SCIF1 */
+};
+
+static inline void r8a7790_register_scif(int idx)
+{
+	platform_device_register_data(&platform_bus, "sh-sci", idx, &scif[idx],
+				      sizeof(struct plat_sci_port));
+}
+
+static struct renesas_irqc_config irqc0_data = {
+	.irq_base = irq_pin(0), /* IRQ0 -> IRQ3 */
+};
+
+static struct resource irqc0_resources[] = {
+	DEFINE_RES_MEM(0xe61c0000, 0x200), /* IRQC Event Detector Block_0 */
+	DEFINE_RES_IRQ(gic_spi(0)), /* IRQ0 */
+	DEFINE_RES_IRQ(gic_spi(1)), /* IRQ1 */
+	DEFINE_RES_IRQ(gic_spi(2)), /* IRQ2 */
+	DEFINE_RES_IRQ(gic_spi(3)), /* IRQ3 */
+};
+
+#define r8a7790_register_irqc(idx)					\
+	platform_device_register_resndata(&platform_bus, "renesas_irqc", \
+					  idx, irqc##idx##_resources,	\
+					  ARRAY_SIZE(irqc##idx##_resources), \
+					  &irqc##idx##_data,		\
+					  sizeof(struct renesas_irqc_config))
+
+void __init r8a7790_add_standard_devices(void)
+{
+	r8a7790_register_scif(SCIFA0);
+	r8a7790_register_scif(SCIFA1);
+	r8a7790_register_scif(SCIFB0);
+	r8a7790_register_scif(SCIFB1);
+	r8a7790_register_scif(SCIFB2);
+	r8a7790_register_scif(SCIFA2);
+	r8a7790_register_scif(SCIF0);
+	r8a7790_register_scif(SCIF1);
+	r8a7790_register_irqc(0);
+}
+
+#ifdef CONFIG_USE_OF
+void __init r8a7790_add_standard_devices_dt(void)
+{
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+}
+
+static const char *r8a7790_boards_compat_dt[] __initdata = {
+	"renesas,r8a7790",
+	NULL,
+};
+
+DT_MACHINE_START(R8A7790_DT, "Generic R8A7790 (Flattened Device Tree)")
+	.init_irq	= irqchip_init,
+	.init_machine	= r8a7790_add_standard_devices_dt,
+	.init_time	= shmobile_timer_init,
+	.dt_compat	= r8a7790_boards_compat_dt,
+MACHINE_END
+#endif /* CONFIG_USE_OF */
diff --git a/arch/arm/mach-shmobile/setup-sh73a0.c b/arch/arm/mach-shmobile/setup-sh73a0.c
index bdab575..e8cd93a 100644
--- a/arch/arm/mach-shmobile/setup-sh73a0.c
+++ b/arch/arm/mach-shmobile/setup-sh73a0.c
@@ -22,6 +22,7 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
+#include <linux/irqchip.h>
 #include <linux/platform_device.h>
 #include <linux/of_platform.h>
 #include <linux/delay.h>
@@ -32,6 +33,7 @@
 #include <linux/sh_intc.h>
 #include <linux/sh_timer.h>
 #include <linux/platform_data/sh_ipmmu.h>
+#include <linux/platform_data/irq-renesas-intc-irqpin.h>
 #include <mach/dma-register.h>
 #include <mach/hardware.h>
 #include <mach/irqs.h>
@@ -810,7 +812,128 @@ static struct platform_device ipmmu_device = {
 	.num_resources  = ARRAY_SIZE(ipmmu_resources),
 };
 
-static struct platform_device *sh73a0_early_devices_dt[] __initdata = {
+static struct renesas_intc_irqpin_config irqpin0_platform_data = {
+	.irq_base = irq_pin(0), /* IRQ0 -> IRQ7 */
+};
+
+static struct resource irqpin0_resources[] = {
+	DEFINE_RES_MEM(0xe6900000, 4), /* ICR1A */
+	DEFINE_RES_MEM(0xe6900010, 4), /* INTPRI00A */
+	DEFINE_RES_MEM(0xe6900020, 1), /* INTREQ00A */
+	DEFINE_RES_MEM(0xe6900040, 1), /* INTMSK00A */
+	DEFINE_RES_MEM(0xe6900060, 1), /* INTMSKCLR00A */
+	DEFINE_RES_IRQ(gic_spi(1)), /* IRQ0 */
+	DEFINE_RES_IRQ(gic_spi(2)), /* IRQ1 */
+	DEFINE_RES_IRQ(gic_spi(3)), /* IRQ2 */
+	DEFINE_RES_IRQ(gic_spi(4)), /* IRQ3 */
+	DEFINE_RES_IRQ(gic_spi(5)), /* IRQ4 */
+	DEFINE_RES_IRQ(gic_spi(6)), /* IRQ5 */
+	DEFINE_RES_IRQ(gic_spi(7)), /* IRQ6 */
+	DEFINE_RES_IRQ(gic_spi(8)), /* IRQ7 */
+};
+
+static struct platform_device irqpin0_device = {
+	.name		= "renesas_intc_irqpin",
+	.id		= 0,
+	.resource	= irqpin0_resources,
+	.num_resources	= ARRAY_SIZE(irqpin0_resources),
+	.dev		= {
+		.platform_data	= &irqpin0_platform_data,
+	},
+};
+
+static struct renesas_intc_irqpin_config irqpin1_platform_data = {
+	.irq_base = irq_pin(8), /* IRQ8 -> IRQ15 */
+	.control_parent = true, /* Disable spurious IRQ10 */
+};
+
+static struct resource irqpin1_resources[] = {
+	DEFINE_RES_MEM(0xe6900004, 4), /* ICR2A */
+	DEFINE_RES_MEM(0xe6900014, 4), /* INTPRI10A */
+	DEFINE_RES_MEM(0xe6900024, 1), /* INTREQ10A */
+	DEFINE_RES_MEM(0xe6900044, 1), /* INTMSK10A */
+	DEFINE_RES_MEM(0xe6900064, 1), /* INTMSKCLR10A */
+	DEFINE_RES_IRQ(gic_spi(9)), /* IRQ8 */
+	DEFINE_RES_IRQ(gic_spi(10)), /* IRQ9 */
+	DEFINE_RES_IRQ(gic_spi(11)), /* IRQ10 */
+	DEFINE_RES_IRQ(gic_spi(12)), /* IRQ11 */
+	DEFINE_RES_IRQ(gic_spi(13)), /* IRQ12 */
+	DEFINE_RES_IRQ(gic_spi(14)), /* IRQ13 */
+	DEFINE_RES_IRQ(gic_spi(15)), /* IRQ14 */
+	DEFINE_RES_IRQ(gic_spi(16)), /* IRQ15 */
+};
+
+static struct platform_device irqpin1_device = {
+	.name		= "renesas_intc_irqpin",
+	.id		= 1,
+	.resource	= irqpin1_resources,
+	.num_resources	= ARRAY_SIZE(irqpin1_resources),
+	.dev		= {
+		.platform_data	= &irqpin1_platform_data,
+	},
+};
+
+static struct renesas_intc_irqpin_config irqpin2_platform_data = {
+	.irq_base = irq_pin(16), /* IRQ16 -> IRQ23 */
+};
+
+static struct resource irqpin2_resources[] = {
+	DEFINE_RES_MEM(0xe6900008, 4), /* ICR3A */
+	DEFINE_RES_MEM(0xe6900018, 4), /* INTPRI20A */
+	DEFINE_RES_MEM(0xe6900028, 1), /* INTREQ20A */
+	DEFINE_RES_MEM(0xe6900048, 1), /* INTMSK20A */
+	DEFINE_RES_MEM(0xe6900068, 1), /* INTMSKCLR20A */
+	DEFINE_RES_IRQ(gic_spi(17)), /* IRQ16 */
+	DEFINE_RES_IRQ(gic_spi(18)), /* IRQ17 */
+	DEFINE_RES_IRQ(gic_spi(19)), /* IRQ18 */
+	DEFINE_RES_IRQ(gic_spi(20)), /* IRQ19 */
+	DEFINE_RES_IRQ(gic_spi(21)), /* IRQ20 */
+	DEFINE_RES_IRQ(gic_spi(22)), /* IRQ21 */
+	DEFINE_RES_IRQ(gic_spi(23)), /* IRQ22 */
+	DEFINE_RES_IRQ(gic_spi(24)), /* IRQ23 */
+};
+
+static struct platform_device irqpin2_device = {
+	.name		= "renesas_intc_irqpin",
+	.id		= 2,
+	.resource	= irqpin2_resources,
+	.num_resources	= ARRAY_SIZE(irqpin2_resources),
+	.dev		= {
+		.platform_data	= &irqpin2_platform_data,
+	},
+};
+
+static struct renesas_intc_irqpin_config irqpin3_platform_data = {
+	.irq_base = irq_pin(24), /* IRQ24 -> IRQ31 */
+};
+
+static struct resource irqpin3_resources[] = {
+	DEFINE_RES_MEM(0xe690000c, 4), /* ICR4A */
+	DEFINE_RES_MEM(0xe690001c, 4), /* INTPRI30A */
+	DEFINE_RES_MEM(0xe690002c, 1), /* INTREQ30A */
+	DEFINE_RES_MEM(0xe690004c, 1), /* INTMSK30A */
+	DEFINE_RES_MEM(0xe690006c, 1), /* INTMSKCLR30A */
+	DEFINE_RES_IRQ(gic_spi(25)), /* IRQ24 */
+	DEFINE_RES_IRQ(gic_spi(26)), /* IRQ25 */
+	DEFINE_RES_IRQ(gic_spi(27)), /* IRQ26 */
+	DEFINE_RES_IRQ(gic_spi(28)), /* IRQ27 */
+	DEFINE_RES_IRQ(gic_spi(29)), /* IRQ28 */
+	DEFINE_RES_IRQ(gic_spi(30)), /* IRQ29 */
+	DEFINE_RES_IRQ(gic_spi(31)), /* IRQ30 */
+	DEFINE_RES_IRQ(gic_spi(32)), /* IRQ31 */
+};
+
+static struct platform_device irqpin3_device = {
+	.name		= "renesas_intc_irqpin",
+	.id		= 3,
+	.resource	= irqpin3_resources,
+	.num_resources	= ARRAY_SIZE(irqpin3_resources),
+	.dev		= {
+		.platform_data	= &irqpin3_platform_data,
+	},
+};
+
+static struct platform_device *sh73a0_devices_dt[] __initdata = {
 	&scif0_device,
 	&scif1_device,
 	&scif2_device,
@@ -838,6 +961,10 @@ static struct platform_device *sh73a0_late_devices[] __initdata = {
 	&dma0_device,
 	&mpdma0_device,
 	&pmu_device,
+	&irqpin0_device,
+	&irqpin1_device,
+	&irqpin2_device,
+	&irqpin3_device,
 };
 
 #define SRCR2          IOMEM(0xe61580b0)
@@ -847,8 +974,8 @@ void __init sh73a0_add_standard_devices(void)
 	/* Clear software reset bit on SY-DMAC module */
 	__raw_writel(__raw_readl(SRCR2) & ~(1 << 18), SRCR2);
 
-	platform_add_devices(sh73a0_early_devices_dt,
-			    ARRAY_SIZE(sh73a0_early_devices_dt));
+	platform_add_devices(sh73a0_devices_dt,
+			    ARRAY_SIZE(sh73a0_devices_dt));
 	platform_add_devices(sh73a0_early_devices,
 			    ARRAY_SIZE(sh73a0_early_devices));
 	platform_add_devices(sh73a0_late_devices,
@@ -867,8 +994,8 @@ void __init sh73a0_earlytimer_init(void)
 
 void __init sh73a0_add_early_devices(void)
 {
-	early_platform_add_devices(sh73a0_early_devices_dt,
-				   ARRAY_SIZE(sh73a0_early_devices_dt));
+	early_platform_add_devices(sh73a0_devices_dt,
+				   ARRAY_SIZE(sh73a0_devices_dt));
 	early_platform_add_devices(sh73a0_early_devices,
 				   ARRAY_SIZE(sh73a0_early_devices));
 
@@ -878,23 +1005,9 @@ void __init sh73a0_add_early_devices(void)
 
 #ifdef CONFIG_USE_OF
 
-/* Please note that the clock initialisation shcheme used in
- * sh73a0_add_early_devices_dt() and sh73a0_add_standard_devices_dt()
- * does not work with SMP as there is a yet to be resolved lock-up in
- * workqueue initialisation.
- *
- * CONFIG_SMP should be disabled when using this code.
- */
-
-void __init sh73a0_add_early_devices_dt(void)
+void __init sh73a0_init_delay(void)
 {
 	shmobile_setup_delay(1196, 44, 46); /* Cortex-A9 @ 1196MHz */
-
-	early_platform_add_devices(sh73a0_early_devices_dt,
-				   ARRAY_SIZE(sh73a0_early_devices_dt));
-
-	/* setup early console here as well */
-	shmobile_setup_console();
 }
 
 static const struct of_dev_auxdata sh73a0_auxdata_lookup[] __initconst = {
@@ -906,8 +1019,8 @@ void __init sh73a0_add_standard_devices_dt(void)
 	/* clocks are setup late during boot in the case of DT */
 	sh73a0_clock_init();
 
-	platform_add_devices(sh73a0_early_devices_dt,
-			     ARRAY_SIZE(sh73a0_early_devices_dt));
+	platform_add_devices(sh73a0_devices_dt,
+			     ARRAY_SIZE(sh73a0_devices_dt));
 	of_platform_populate(NULL, of_default_bus_match_table,
 			     sh73a0_auxdata_lookup, NULL);
 }
@@ -918,10 +1031,11 @@ static const char *sh73a0_boards_compat_dt[] __initdata = {
 };
 
 DT_MACHINE_START(SH73A0_DT, "Generic SH73A0 (Flattened Device Tree)")
+	.smp		= smp_ops(sh73a0_smp_ops),
 	.map_io		= sh73a0_map_io,
-	.init_early	= sh73a0_add_early_devices_dt,
+	.init_early	= sh73a0_init_delay,
 	.nr_irqs	= NR_IRQS_LEGACY,
-	.init_irq	= sh73a0_init_irq_dt,
+	.init_irq	= irqchip_init,
 	.init_machine	= sh73a0_add_standard_devices_dt,
 	.init_time	= shmobile_timer_init,
 	.dt_compat	= sh73a0_boards_compat_dt,
diff --git a/arch/arm/mach-shmobile/smp-emev2.c b/arch/arm/mach-shmobile/smp-emev2.c
index 953eb1f..0c7e43f 100644
--- a/arch/arm/mach-shmobile/smp-emev2.c
+++ b/arch/arm/mach-shmobile/smp-emev2.c
@@ -23,12 +23,10 @@
 #include <linux/spinlock.h>
 #include <linux/io.h>
 #include <linux/delay.h>
-#include <linux/irqchip/arm-gic.h>
 #include <mach/common.h>
 #include <mach/emev2.h>
 #include <asm/smp_plat.h>
 #include <asm/smp_scu.h>
-#include <asm/cacheflush.h>
 
 #define EMEV2_SCU_BASE 0x1e000000
 
@@ -50,73 +48,32 @@ static void modify_scu_cpu_psr(unsigned long set, unsigned long clr)
 
 }
 
-static unsigned int __init emev2_get_core_count(void)
-{
-	if (!scu_base) {
-		scu_base = ioremap(EMEV2_SCU_BASE, PAGE_SIZE);
-		emev2_clock_init(); /* need ioremapped SMU */
-	}
-
-	WARN_ON_ONCE(!scu_base);
-
-	return scu_base ? scu_get_core_count(scu_base) : 1;
-}
-
-static int emev2_platform_cpu_kill(unsigned int cpu)
-{
-	return 0; /* not supported yet */
-}
-
-static int __maybe_unused emev2_cpu_kill(unsigned int cpu)
-{
-	int k;
-
-	/* this function is running on another CPU than the offline target,
-	 * here we need wait for shutdown code in platform_cpu_die() to
-	 * finish before asking SoC-specific code to power off the CPU core.
-	 */
-	for (k = 0; k < 1000; k++) {
-		if (shmobile_cpu_is_dead(cpu))
-			return emev2_platform_cpu_kill(cpu);
-		mdelay(1);
-	}
-
-	return 0;
-}
-
-
-static void __cpuinit emev2_secondary_init(unsigned int cpu)
-{
-	gic_secondary_init(0);
-}
-
 static int __cpuinit emev2_boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
-	cpu = cpu_logical_map(cpu);
-
-	/* enable cache coherency */
-	modify_scu_cpu_psr(0, 3 << (cpu * 8));
-
-	/* Tell ROM loader about our vector (in headsmp.S) */
-	emev2_set_boot_vector(__pa(shmobile_secondary_vector));
-
-	arch_send_wakeup_ipi_mask(cpumask_of(cpu));
+	arch_send_wakeup_ipi_mask(cpumask_of(cpu_logical_map(cpu)));
 	return 0;
 }
 
 static void __init emev2_smp_prepare_cpus(unsigned int max_cpus)
 {
-	int cpu = cpu_logical_map(0);
+	scu_enable(shmobile_scu_base);
 
-	scu_enable(scu_base);
+	/* Tell ROM loader about our vector (in headsmp-scu.S) */
+	emev2_set_boot_vector(__pa(shmobile_secondary_vector_scu));
 
-	/* enable cache coherency on CPU0 */
-	modify_scu_cpu_psr(0, 3 << (cpu * 8));
+	/* enable cache coherency on booting CPU */
+	scu_power_mode(shmobile_scu_base, SCU_PM_NORMAL);
 }
 
 static void __init emev2_smp_init_cpus(void)
 {
-	unsigned int ncores = emev2_get_core_count();
+	unsigned int ncores;
+
+	/* setup EMEV2 specific SCU base */
+	shmobile_scu_base = ioremap(EMEV2_SCU_BASE, PAGE_SIZE);
+	emev2_clock_init(); /* need ioremapped SMU */
+
+	ncores = shmobile_scu_base ? scu_get_core_count(shmobile_scu_base) : 1;
 
 	shmobile_smp_init_cpus(ncores);
 }
@@ -124,11 +81,5 @@ static void __init emev2_smp_init_cpus(void)
 struct smp_operations emev2_smp_ops __initdata = {
 	.smp_init_cpus		= emev2_smp_init_cpus,
 	.smp_prepare_cpus	= emev2_smp_prepare_cpus,
-	.smp_secondary_init	= emev2_secondary_init,
 	.smp_boot_secondary	= emev2_boot_secondary,
-#ifdef CONFIG_HOTPLUG_CPU
-	.cpu_kill		= emev2_cpu_kill,
-	.cpu_die		= shmobile_cpu_die,
-	.cpu_disable		= shmobile_cpu_disable,
-#endif
 };
diff --git a/arch/arm/mach-shmobile/smp-r8a7779.c b/arch/arm/mach-shmobile/smp-r8a7779.c
index 3a4acf2..a853bf1 100644
--- a/arch/arm/mach-shmobile/smp-r8a7779.c
+++ b/arch/arm/mach-shmobile/smp-r8a7779.c
@@ -23,14 +23,15 @@
 #include <linux/spinlock.h>
 #include <linux/io.h>
 #include <linux/delay.h>
-#include <linux/irqchip/arm-gic.h>
 #include <mach/common.h>
 #include <mach/r8a7779.h>
+#include <asm/cacheflush.h>
 #include <asm/smp_plat.h>
 #include <asm/smp_scu.h>
 #include <asm/smp_twd.h>
 
 #define AVECR IOMEM(0xfe700040)
+#define R8A7779_SCU_BASE 0xf0000000
 
 static struct r8a7779_pm_ch r8a7779_ch_cpu1 = {
 	.chan_offs = 0x40, /* PWRSR0 .. PWRER0 */
@@ -56,44 +57,14 @@ static struct r8a7779_pm_ch *r8a7779_ch_cpu[4] = {
 	[3] = &r8a7779_ch_cpu3,
 };
 
-static void __iomem *scu_base_addr(void)
-{
-	return (void __iomem *)0xf0000000;
-}
-
-static DEFINE_SPINLOCK(scu_lock);
-static unsigned long tmp;
-
 #ifdef CONFIG_HAVE_ARM_TWD
-static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, 0xf0000600, 29);
-
+static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, R8A7779_SCU_BASE + 0x600, 29);
 void __init r8a7779_register_twd(void)
 {
 	twd_local_timer_register(&twd_local_timer);
 }
 #endif
 
-static void modify_scu_cpu_psr(unsigned long set, unsigned long clr)
-{
-	void __iomem *scu_base = scu_base_addr();
-
-	spin_lock(&scu_lock);
-	tmp = __raw_readl(scu_base + 8);
-	tmp &= ~clr;
-	tmp |= set;
-	spin_unlock(&scu_lock);
-
-	/* disable cache coherency after releasing the lock */
-	__raw_writel(tmp, scu_base + 8);
-}
-
-static unsigned int __init r8a7779_get_core_count(void)
-{
-	void __iomem *scu_base = scu_base_addr();
-
-	return scu_get_core_count(scu_base);
-}
-
 static int r8a7779_platform_cpu_kill(unsigned int cpu)
 {
 	struct r8a7779_pm_ch *ch = NULL;
@@ -101,9 +72,6 @@ static int r8a7779_platform_cpu_kill(unsigned int cpu)
 
 	cpu = cpu_logical_map(cpu);
 
-	/* disable cache coherency */
-	modify_scu_cpu_psr(3 << (cpu * 8), 0);
-
 	if (cpu < ARRAY_SIZE(r8a7779_ch_cpu))
 		ch = r8a7779_ch_cpu[cpu];
 
@@ -113,30 +81,6 @@ static int r8a7779_platform_cpu_kill(unsigned int cpu)
 	return ret ? ret : 1;
 }
 
-static int __maybe_unused r8a7779_cpu_kill(unsigned int cpu)
-{
-	int k;
-
-	/* this function is running on another CPU than the offline target,
-	 * here we need wait for shutdown code in platform_cpu_die() to
-	 * finish before asking SoC-specific code to power off the CPU core.
-	 */
-	for (k = 0; k < 1000; k++) {
-		if (shmobile_cpu_is_dead(cpu))
-			return r8a7779_platform_cpu_kill(cpu);
-
-		mdelay(1);
-	}
-
-	return 0;
-}
-
-
-static void __cpuinit r8a7779_secondary_init(unsigned int cpu)
-{
-	gic_secondary_init(0);
-}
-
 static int __cpuinit r8a7779_boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
 	struct r8a7779_pm_ch *ch = NULL;
@@ -144,9 +88,6 @@ static int __cpuinit r8a7779_boot_secondary(unsigned int cpu, struct task_struct
 
 	cpu = cpu_logical_map(cpu);
 
-	/* enable cache coherency */
-	modify_scu_cpu_psr(0, 3 << (cpu * 8));
-
 	if (cpu < ARRAY_SIZE(r8a7779_ch_cpu))
 		ch = r8a7779_ch_cpu[cpu];
 
@@ -158,15 +99,13 @@ static int __cpuinit r8a7779_boot_secondary(unsigned int cpu, struct task_struct
 
 static void __init r8a7779_smp_prepare_cpus(unsigned int max_cpus)
 {
-	int cpu = cpu_logical_map(0);
-
-	scu_enable(scu_base_addr());
+	scu_enable(shmobile_scu_base);
 
-	/* Map the reset vector (in headsmp.S) */
-	__raw_writel(__pa(shmobile_secondary_vector), AVECR);
+	/* Map the reset vector (in headsmp-scu.S) */
+	__raw_writel(__pa(shmobile_secondary_vector_scu), AVECR);
 
-	/* enable cache coherency on CPU0 */
-	modify_scu_cpu_psr(0, 3 << (cpu * 8));
+	/* enable cache coherency on booting CPU */
+	scu_power_mode(shmobile_scu_base, SCU_PM_NORMAL);
 
 	r8a7779_pm_init();
 
@@ -178,19 +117,68 @@ static void __init r8a7779_smp_prepare_cpus(unsigned int max_cpus)
 
 static void __init r8a7779_smp_init_cpus(void)
 {
-	unsigned int ncores = r8a7779_get_core_count();
+	/* setup r8a7779 specific SCU base */
+	shmobile_scu_base = IOMEM(R8A7779_SCU_BASE);
+
+	shmobile_smp_init_cpus(scu_get_core_count(shmobile_scu_base));
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+static int r8a7779_scu_psr_core_disabled(int cpu)
+{
+	unsigned long mask = 3 << (cpu * 8);
+
+	if ((__raw_readl(shmobile_scu_base + 8) & mask) == mask)
+		return 1;
+
+	return 0;
+}
+
+static int r8a7779_cpu_kill(unsigned int cpu)
+{
+	int k;
 
-	shmobile_smp_init_cpus(ncores);
+	/* this function is running on another CPU than the offline target,
+	 * here we need wait for shutdown code in platform_cpu_die() to
+	 * finish before asking SoC-specific code to power off the CPU core.
+	 */
+	for (k = 0; k < 1000; k++) {
+		if (r8a7779_scu_psr_core_disabled(cpu))
+			return r8a7779_platform_cpu_kill(cpu);
+
+		mdelay(1);
+	}
+
+	return 0;
+}
+
+static void r8a7779_cpu_die(unsigned int cpu)
+{
+	dsb();
+	flush_cache_all();
+
+	/* disable cache coherency */
+	scu_power_mode(shmobile_scu_base, SCU_PM_POWEROFF);
+
+	/* Endless loop until power off from r8a7779_cpu_kill() */
+	while (1)
+		cpu_do_idle();
+}
+
+static int r8a7779_cpu_disable(unsigned int cpu)
+{
+	/* only CPU1->3 have power domains, do not allow hotplug of CPU0 */
+	return cpu == 0 ? -EPERM : 0;
 }
+#endif /* CONFIG_HOTPLUG_CPU */
 
 struct smp_operations r8a7779_smp_ops  __initdata = {
 	.smp_init_cpus		= r8a7779_smp_init_cpus,
 	.smp_prepare_cpus	= r8a7779_smp_prepare_cpus,
-	.smp_secondary_init	= r8a7779_secondary_init,
 	.smp_boot_secondary	= r8a7779_boot_secondary,
 #ifdef CONFIG_HOTPLUG_CPU
 	.cpu_kill		= r8a7779_cpu_kill,
-	.cpu_die		= shmobile_cpu_die,
-	.cpu_disable		= shmobile_cpu_disable,
+	.cpu_die		= r8a7779_cpu_die,
+	.cpu_disable		= r8a7779_cpu_disable,
 #endif
 };
diff --git a/arch/arm/mach-shmobile/smp-sh73a0.c b/arch/arm/mach-shmobile/smp-sh73a0.c
index acb46a9..bf79626 100644
--- a/arch/arm/mach-shmobile/smp-sh73a0.c
+++ b/arch/arm/mach-shmobile/smp-sh73a0.c
@@ -23,7 +23,6 @@
 #include <linux/spinlock.h>
 #include <linux/io.h>
 #include <linux/delay.h>
-#include <linux/irqchip/arm-gic.h>
 #include <mach/common.h>
 #include <asm/cacheflush.h>
 #include <asm/smp_plat.h>
@@ -39,31 +38,16 @@
 
 #define PSTR_SHUTDOWN_MODE	3
 
-static void __iomem *scu_base_addr(void)
-{
-	return (void __iomem *)0xf0000000;
-}
+#define SH73A0_SCU_BASE 0xf0000000
 
 #ifdef CONFIG_HAVE_ARM_TWD
-static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, 0xf0000600, 29);
+static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, SH73A0_SCU_BASE + 0x600, 29);
 void __init sh73a0_register_twd(void)
 {
 	twd_local_timer_register(&twd_local_timer);
 }
 #endif
 
-static unsigned int __init sh73a0_get_core_count(void)
-{
-	void __iomem *scu_base = scu_base_addr();
-
-	return scu_get_core_count(scu_base);
-}
-
-static void __cpuinit sh73a0_secondary_init(unsigned int cpu)
-{
-	gic_secondary_init(0);
-}
-
 static int __cpuinit sh73a0_boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
 	cpu = cpu_logical_map(cpu);
@@ -78,21 +62,22 @@ static int __cpuinit sh73a0_boot_secondary(unsigned int cpu, struct task_struct
 
 static void __init sh73a0_smp_prepare_cpus(unsigned int max_cpus)
 {
-	scu_enable(scu_base_addr());
+	scu_enable(shmobile_scu_base);
 
-	/* Map the reset vector (in headsmp-sh73a0.S) */
+	/* Map the reset vector (in headsmp-scu.S) */
 	__raw_writel(0, APARMBAREA);      /* 4k */
-	__raw_writel(__pa(sh73a0_secondary_vector), SBAR);
+	__raw_writel(__pa(shmobile_secondary_vector_scu), SBAR);
 
 	/* enable cache coherency on booting CPU */
-	scu_power_mode(scu_base_addr(), SCU_PM_NORMAL);
+	scu_power_mode(shmobile_scu_base, SCU_PM_NORMAL);
 }
 
 static void __init sh73a0_smp_init_cpus(void)
 {
-	unsigned int ncores = sh73a0_get_core_count();
+	/* setup sh73a0 specific SCU base */
+	shmobile_scu_base = IOMEM(SH73A0_SCU_BASE);
 
-	shmobile_smp_init_cpus(ncores);
+	shmobile_smp_init_cpus(scu_get_core_count(shmobile_scu_base));
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
@@ -128,21 +113,25 @@ static void sh73a0_cpu_die(unsigned int cpu)
 	flush_cache_all();
 
 	/* Set power off mode. This takes the CPU out of the MP cluster */
-	scu_power_mode(scu_base_addr(), SCU_PM_POWEROFF);
+	scu_power_mode(shmobile_scu_base, SCU_PM_POWEROFF);
 
 	/* Enter shutdown mode */
 	cpu_do_idle();
 }
+
+static int sh73a0_cpu_disable(unsigned int cpu)
+{
+	return 0; /* CPU0 and CPU1 supported */
+}
 #endif /* CONFIG_HOTPLUG_CPU */
 
 struct smp_operations sh73a0_smp_ops __initdata = {
 	.smp_init_cpus		= sh73a0_smp_init_cpus,
 	.smp_prepare_cpus	= sh73a0_smp_prepare_cpus,
-	.smp_secondary_init	= sh73a0_secondary_init,
 	.smp_boot_secondary	= sh73a0_boot_secondary,
 #ifdef CONFIG_HOTPLUG_CPU
 	.cpu_kill		= sh73a0_cpu_kill,
 	.cpu_die		= sh73a0_cpu_die,
-	.cpu_disable		= shmobile_cpu_disable_any,
+	.cpu_disable		= sh73a0_cpu_disable,
 #endif
 };
diff --git a/arch/arm/mach-socfpga/platsmp.c b/arch/arm/mach-socfpga/platsmp.c
index 84c60fa..ca14d1d 100644
--- a/arch/arm/mach-socfpga/platsmp.c
+++ b/arch/arm/mach-socfpga/platsmp.c
@@ -22,7 +22,6 @@
 #include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
-#include <linux/irqchip/arm-gic.h>
 
 #include <asm/cacheflush.h>
 #include <asm/smp_scu.h>
@@ -33,16 +32,6 @@
 extern void __iomem *sys_manager_base_addr;
 extern void __iomem *rst_manager_base_addr;
 
-static void __cpuinit socfpga_secondary_init(unsigned int cpu)
-{
-	/*
-	 * if any interrupts are already enabled for the primary
-	 * core (e.g. timer irq), then they will not have been enabled
-	 * for us: do so
-	 */
-	gic_secondary_init(0);
-}
-
 static int __cpuinit socfpga_boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
 	int trampoline_size = &secondary_trampoline_end - &secondary_trampoline;
@@ -109,7 +98,6 @@ static void socfpga_cpu_die(unsigned int cpu)
 struct smp_operations socfpga_smp_ops __initdata = {
 	.smp_init_cpus		= socfpga_smp_init_cpus,
 	.smp_prepare_cpus	= socfpga_smp_prepare_cpus,
-	.smp_secondary_init	= socfpga_secondary_init,
 	.smp_boot_secondary	= socfpga_boot_secondary,
 #ifdef CONFIG_HOTPLUG_CPU
 	.cpu_die		= socfpga_cpu_die,
diff --git a/arch/arm/mach-spear/Kconfig b/arch/arm/mach-spear/Kconfig
new file mode 100644
index 0000000..5412aeb
--- /dev/null
+++ b/arch/arm/mach-spear/Kconfig
@@ -0,0 +1,103 @@
+#
+# SPEAr Platform configuration file
+#
+
+menuconfig PLAT_SPEAR
+	bool "ST SPEAr Family" if ARCH_MULTI_V7 || ARCH_MULTI_V5
+	default PLAT_SPEAR_SINGLE
+	select ARCH_REQUIRE_GPIOLIB
+	select ARM_AMBA
+	select CLKDEV_LOOKUP
+	select CLKSRC_MMIO
+	select COMMON_CLK
+	select GENERIC_CLOCKEVENTS
+	select HAVE_CLK
+
+if PLAT_SPEAR
+
+config ARCH_SPEAR13XX
+	bool "ST SPEAr13xx"
+	depends on ARCH_MULTI_V7 || PLAT_SPEAR_SINGLE
+	select ARCH_HAS_CPUFREQ
+	select ARM_GIC
+	select CPU_V7
+	select GPIO_SPEAR_SPICS
+	select HAVE_SMP
+	select MIGHT_HAVE_CACHE_L2X0
+	select PINCTRL
+	select USE_OF
+	help
+	  Supports for ARM's SPEAR13XX family
+
+if ARCH_SPEAR13XX
+
+config MACH_SPEAR1310
+	bool "SPEAr1310 Machine support with Device Tree"
+	select PINCTRL_SPEAR1310
+	help
+	  Supports ST SPEAr1310 machine configured via the device-tree
+
+config MACH_SPEAR1340
+	bool "SPEAr1340 Machine support with Device Tree"
+	select PINCTRL_SPEAR1340
+	help
+	  Supports ST SPEAr1340 machine configured via the device-tree
+
+endif #ARCH_SPEAR13XX
+
+config ARCH_SPEAR3XX
+	bool "ST SPEAr3xx"
+	depends on ARCH_MULTI_V5 || PLAT_SPEAR_SINGLE
+	depends on !ARCH_SPEAR13XX
+	select ARM_VIC
+	select CPU_ARM926T
+	select PINCTRL
+	select USE_OF
+	help
+	  Supports for ARM's SPEAR3XX family
+
+if ARCH_SPEAR3XX
+
+config MACH_SPEAR300
+	bool "SPEAr300 Machine support with Device Tree"
+	select PINCTRL_SPEAR300
+	help
+	  Supports ST SPEAr300 machine configured via the device-tree
+
+config MACH_SPEAR310
+	bool "SPEAr310 Machine support with Device Tree"
+	select PINCTRL_SPEAR310
+	help
+	  Supports ST SPEAr310 machine configured via the device-tree
+
+config MACH_SPEAR320
+	bool "SPEAr320 Machine support with Device Tree"
+	select PINCTRL_SPEAR320
+	help
+	  Supports ST SPEAr320 machine configured via the device-tree
+
+endif
+
+config ARCH_SPEAR6XX
+	bool "ST SPEAr6XX"
+	depends on ARCH_MULTI_V5 || PLAT_SPEAR_SINGLE
+	depends on !ARCH_SPEAR13XX
+	select ARM_VIC
+	select CPU_ARM926T
+	help
+	  Supports for ARM's SPEAR6XX family
+
+config MACH_SPEAR600
+	def_bool y
+	depends on ARCH_SPEAR6XX
+	select USE_OF
+	help
+	  Supports ST SPEAr600 boards configured via the device-treesource "arch/arm/mach-spear6xx/Kconfig"
+
+config ARCH_SPEAR_AUTO
+	def_bool PLAT_SPEAR_SINGLE
+	depends on !ARCH_SPEAR13XX && !ARCH_SPEAR6XX
+	select ARCH_SPEAR3XX
+
+endif
+
diff --git a/arch/arm/mach-spear/Makefile b/arch/arm/mach-spear/Makefile
new file mode 100644
index 0000000..af9bffb
--- /dev/null
+++ b/arch/arm/mach-spear/Makefile
@@ -0,0 +1,26 @@
+#
+# SPEAr Platform specific Makefile
+#
+
+ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include
+
+# Common support
+obj-y	:= restart.o time.o
+
+obj-$(CONFIG_SMP)		+= headsmp.o platsmp.o
+obj-$(CONFIG_HOTPLUG_CPU)	+= hotplug.o
+
+obj-$(CONFIG_ARCH_SPEAR13XX)	+= spear13xx.o
+obj-$(CONFIG_MACH_SPEAR1310)	+= spear1310.o
+obj-$(CONFIG_MACH_SPEAR1340)	+= spear1340.o
+
+obj-$(CONFIG_ARCH_SPEAR3XX)	+= spear3xx.o
+obj-$(CONFIG_ARCH_SPEAR3XX)	+= pl080.o
+obj-$(CONFIG_MACH_SPEAR300)	+= spear300.o
+obj-$(CONFIG_MACH_SPEAR310)	+= spear310.o
+obj-$(CONFIG_MACH_SPEAR320)	+= spear320.o
+
+obj-$(CONFIG_ARCH_SPEAR6XX)	+= spear6xx.o
+obj-$(CONFIG_ARCH_SPEAR6XX)	+= pl080.o
+
+CFLAGS_hotplug.o		+= -march=armv7-a
diff --git a/arch/arm/mach-spear/Makefile.boot b/arch/arm/mach-spear/Makefile.boot
new file mode 100644
index 0000000..4674a4c
--- /dev/null
+++ b/arch/arm/mach-spear/Makefile.boot
@@ -0,0 +1,3 @@
+zreladdr-y	+= 0x00008000
+params_phys-y	:= 0x00000100
+initrd_phys-y	:= 0x00800000
diff --git a/arch/arm/mach-spear/generic.h b/arch/arm/mach-spear/generic.h
new file mode 100644
index 0000000..8ba7e75
--- /dev/null
+++ b/arch/arm/mach-spear/generic.h
@@ -0,0 +1,59 @@
+/*
+ * spear machine family generic header file
+ *
+ * Copyright (C) 2009-2012 ST Microelectronics
+ * Rajeev Kumar <rajeev-dlh.kumar@st.com>
+ * Viresh Kumar <viresh.linux@gmail.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_GENERIC_H
+#define __MACH_GENERIC_H
+
+#include <linux/dmaengine.h>
+#include <linux/amba/pl08x.h>
+#include <linux/init.h>
+#include <asm/mach/time.h>
+
+extern void spear13xx_timer_init(void);
+extern void spear3xx_timer_init(void);
+extern struct pl022_ssp_controller pl022_plat_data;
+extern struct pl08x_platform_data pl080_plat_data;
+extern struct dw_dma_platform_data dmac_plat_data;
+extern struct dw_dma_slave cf_dma_priv;
+extern struct dw_dma_slave nand_read_dma_priv;
+extern struct dw_dma_slave nand_write_dma_priv;
+bool dw_dma_filter(struct dma_chan *chan, void *slave);
+
+void __init spear_setup_of_timer(void);
+void __init spear3xx_clk_init(void __iomem *misc_base,
+			      void __iomem *soc_config_base);
+void __init spear3xx_map_io(void);
+void __init spear3xx_dt_init_irq(void);
+void __init spear6xx_clk_init(void __iomem *misc_base);
+void __init spear13xx_map_io(void);
+void __init spear13xx_l2x0_init(void);
+
+void spear_restart(char, const char *);
+
+void spear13xx_secondary_startup(void);
+void __cpuinit spear13xx_cpu_die(unsigned int cpu);
+
+extern struct smp_operations spear13xx_smp_ops;
+
+#ifdef CONFIG_MACH_SPEAR1310
+void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base);
+#else
+static inline void spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base) {}
+#endif
+
+#ifdef CONFIG_MACH_SPEAR1340
+void __init spear1340_clk_init(void __iomem *misc_base);
+#else
+static inline void spear1340_clk_init(void __iomem *misc_base) {}
+#endif
+
+#endif /* __MACH_GENERIC_H */
diff --git a/arch/arm/mach-spear/headsmp.S b/arch/arm/mach-spear/headsmp.S
new file mode 100644
index 0000000..ed85473
--- /dev/null
+++ b/arch/arm/mach-spear/headsmp.S
@@ -0,0 +1,47 @@
+/*
+ * arch/arm/mach-spear13XX/headsmp.S
+ *
+ * Picked from realview
+ * Copyright (c) 2012 ST Microelectronics Limited
+ * Shiraz Hashim <shiraz.hashim@st.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/linkage.h>
+#include <linux/init.h>
+
+	__INIT
+
+/*
+ * spear13xx specific entry point for secondary CPUs. This provides
+ * a "holding pen" into which all secondary cores are held until we're
+ * ready for them to initialise.
+ */
+ENTRY(spear13xx_secondary_startup)
+	mrc	p15, 0, r0, c0, c0, 5
+	and	r0, r0, #15
+	adr	r4, 1f
+	ldmia	r4, {r5, r6}
+	sub	r4, r4, r5
+	add	r6, r6, r4
+pen:	ldr	r7, [r6]
+	cmp	r7, r0
+	bne	pen
+
+	/* re-enable coherency */
+	mrc	p15, 0, r0, c1, c0, 1
+	orr	r0, r0, #(1 << 6) | (1 << 0)
+	mcr	p15, 0, r0, c1, c0, 1
+	/*
+	 * we've been released from the holding pen: secondary_stack
+	 * should now contain the SVC stack for this core
+	 */
+	b	secondary_startup
+
+	.align
+1:	.long	.
+	.long	pen_release
+ENDPROC(spear13xx_secondary_startup)
diff --git a/arch/arm/mach-spear/hotplug.c b/arch/arm/mach-spear/hotplug.c
new file mode 100644
index 0000000..a7d2dd1
--- /dev/null
+++ b/arch/arm/mach-spear/hotplug.c
@@ -0,0 +1,103 @@
+/*
+ * linux/arch/arm/mach-spear13xx/hotplug.c
+ *
+ * Copyright (C) 2012 ST Microelectronics Ltd.
+ * Deepak Sikri <deepak.sikri@st.com>
+ *
+ * based upon linux/arch/arm/mach-realview/hotplug.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/smp.h>
+#include <asm/cacheflush.h>
+#include <asm/cp15.h>
+#include <asm/smp_plat.h>
+
+static inline void cpu_enter_lowpower(void)
+{
+	unsigned int v;
+
+	flush_cache_all();
+	asm volatile(
+	"	mcr	p15, 0, %1, c7, c5, 0\n"
+	"	dsb\n"
+	/*
+	 * Turn off coherency
+	 */
+	"	mrc	p15, 0, %0, c1, c0, 1\n"
+	"	bic	%0, %0, #0x20\n"
+	"	mcr	p15, 0, %0, c1, c0, 1\n"
+	"	mrc	p15, 0, %0, c1, c0, 0\n"
+	"	bic	%0, %0, %2\n"
+	"	mcr	p15, 0, %0, c1, c0, 0\n"
+	: "=&r" (v)
+	: "r" (0), "Ir" (CR_C)
+	: "cc", "memory");
+}
+
+static inline void cpu_leave_lowpower(void)
+{
+	unsigned int v;
+
+	asm volatile("mrc	p15, 0, %0, c1, c0, 0\n"
+	"	orr	%0, %0, %1\n"
+	"	mcr	p15, 0, %0, c1, c0, 0\n"
+	"	mrc	p15, 0, %0, c1, c0, 1\n"
+	"	orr	%0, %0, #0x20\n"
+	"	mcr	p15, 0, %0, c1, c0, 1\n"
+	: "=&r" (v)
+	: "Ir" (CR_C)
+	: "cc");
+}
+
+static inline void spear13xx_do_lowpower(unsigned int cpu, int *spurious)
+{
+	for (;;) {
+		wfi();
+
+		if (pen_release == cpu) {
+			/*
+			 * OK, proper wakeup, we're done
+			 */
+			break;
+		}
+
+		/*
+		 * Getting here, means that we have come out of WFI without
+		 * having been woken up - this shouldn't happen
+		 *
+		 * Just note it happening - when we're woken, we can report
+		 * its occurrence.
+		 */
+		(*spurious)++;
+	}
+}
+
+/*
+ * platform-specific code to shutdown a CPU
+ *
+ * Called with IRQs disabled
+ */
+void __ref spear13xx_cpu_die(unsigned int cpu)
+{
+	int spurious = 0;
+
+	/*
+	 * we're ready for shutdown now, so do it
+	 */
+	cpu_enter_lowpower();
+	spear13xx_do_lowpower(cpu, &spurious);
+
+	/*
+	 * bring this CPU back into the world of cache
+	 * coherency, and then restore interrupts
+	 */
+	cpu_leave_lowpower();
+
+	if (spurious)
+		pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
+}
diff --git a/arch/arm/mach-spear/include/mach/debug-macro.S b/arch/arm/mach-spear/include/mach/debug-macro.S
new file mode 100644
index 0000000..75b05ad
--- /dev/null
+++ b/arch/arm/mach-spear/include/mach/debug-macro.S
@@ -0,0 +1,36 @@
+/*
+ * arch/arm/plat-spear/include/plat/debug-macro.S
+ *
+ * Debugging macro include header for spear platform
+ *
+ * Copyright (C) 2009 ST Microelectronics
+ * Viresh Kumar <viresh.linux@gmail.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/amba/serial.h>
+#include <mach/spear.h>
+
+		.macro	addruart, rp, rv, tmp
+		mov	\rp, #SPEAR_DBG_UART_BASE		@ Physical base
+		mov	\rv, #VA_SPEAR_DBG_UART_BASE		@ Virtual base
+		.endm
+
+		.macro	senduart, rd, rx
+		strb	\rd, [\rx, #UART01x_DR]			@ ASC_TX_BUFFER
+		.endm
+
+		.macro	waituart, rd, rx
+1001:		ldr	\rd, [\rx, #UART01x_FR]			@ FLAG REGISTER
+		tst	\rd, #UART01x_FR_TXFF			@ TX_FULL
+		bne	1001b
+		.endm
+
+		.macro	busyuart, rd, rx
+1002:		ldr	\rd, [\rx, #UART01x_FR]			@ FLAG REGISTER
+		tst	\rd, #UART011_FR_TXFE			@ TX_EMPTY
+		beq	1002b
+		.endm
diff --git a/arch/arm/mach-spear/include/mach/irqs.h b/arch/arm/mach-spear/include/mach/irqs.h
new file mode 100644
index 0000000..92da0a8
--- /dev/null
+++ b/arch/arm/mach-spear/include/mach/irqs.h
@@ -0,0 +1,35 @@
+/*
+ * IRQ helper macros for spear machine family
+ *
+ * Copyright (C) 2009-2012 ST Microelectronics
+ * Rajeev Kumar <rajeev-dlh.kumar@st.com>
+ * Viresh Kumar <viresh.linux@gmail.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_IRQS_H
+#define __MACH_IRQS_H
+
+#ifdef CONFIG_ARCH_SPEAR3XX
+#define NR_IRQS			256
+#endif
+
+#ifdef CONFIG_ARCH_SPEAR6XX
+/* IRQ definitions */
+/* VIC 1 */
+#define IRQ_VIC_END				64
+
+/* GPIO pins virtual irqs */
+#define VIRTUAL_IRQS				24
+#define NR_IRQS					(IRQ_VIC_END + VIRTUAL_IRQS)
+#endif
+
+#ifdef CONFIG_ARCH_SPEAR13XX
+#define IRQ_GIC_END			160
+#define NR_IRQS				IRQ_GIC_END
+#endif
+
+#endif /* __MACH_IRQS_H */
diff --git a/arch/arm/mach-spear/include/mach/misc_regs.h b/arch/arm/mach-spear/include/mach/misc_regs.h
new file mode 100644
index 0000000..935639c
--- /dev/null
+++ b/arch/arm/mach-spear/include/mach/misc_regs.h
@@ -0,0 +1,22 @@
+/*
+ * arch/arm/mach-spear3xx/include/mach/misc_regs.h
+ *
+ * Miscellaneous registers definitions for SPEAr3xx machine family
+ *
+ * Copyright (C) 2009 ST Microelectronics
+ * Viresh Kumar <viresh.linux@gmail.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_MISC_REGS_H
+#define __MACH_MISC_REGS_H
+
+#include <mach/spear.h>
+
+#define MISC_BASE		(VA_SPEAR_ICM3_MISC_REG_BASE)
+#define DMA_CHN_CFG		(MISC_BASE + 0x0A0)
+
+#endif /* __MACH_MISC_REGS_H */
diff --git a/arch/arm/mach-spear/include/mach/spear.h b/arch/arm/mach-spear/include/mach/spear.h
new file mode 100644
index 0000000..374ddc3
--- /dev/null
+++ b/arch/arm/mach-spear/include/mach/spear.h
@@ -0,0 +1,95 @@
+/*
+ * SPEAr3xx/6xx Machine family specific definition
+ *
+ * Copyright (C) 2009,2012 ST Microelectronics
+ * Rajeev Kumar<rajeev-dlh.kumar@st.com>
+ * Viresh Kumar <viresh.linux@gmail.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_SPEAR_H
+#define __MACH_SPEAR_H
+
+#include <asm/memory.h>
+
+#if defined(CONFIG_ARCH_SPEAR3XX) || defined (CONFIG_ARCH_SPEAR6XX)
+
+/* ICM1 - Low speed connection */
+#define SPEAR_ICM1_2_BASE		UL(0xD0000000)
+#define VA_SPEAR_ICM1_2_BASE		IOMEM(0xFD000000)
+#define SPEAR_ICM1_UART_BASE		UL(0xD0000000)
+#define VA_SPEAR_ICM1_UART_BASE		(VA_SPEAR_ICM1_2_BASE - SPEAR_ICM1_2_BASE + SPEAR_ICM1_UART_BASE)
+#define SPEAR3XX_ICM1_SSP_BASE		UL(0xD0100000)
+
+/* ML-1, 2 - Multi Layer CPU Subsystem */
+#define SPEAR_ICM3_ML1_2_BASE		UL(0xF0000000)
+#define VA_SPEAR6XX_ML_CPU_BASE		IOMEM(0xF0000000)
+
+/* ICM3 - Basic Subsystem */
+#define SPEAR_ICM3_SMI_CTRL_BASE	UL(0xFC000000)
+#define VA_SPEAR_ICM3_SMI_CTRL_BASE	IOMEM(0xFC000000)
+#define SPEAR_ICM3_DMA_BASE		UL(0xFC400000)
+#define SPEAR_ICM3_SYS_CTRL_BASE	UL(0xFCA00000)
+#define VA_SPEAR_ICM3_SYS_CTRL_BASE	(VA_SPEAR_ICM3_SMI_CTRL_BASE - SPEAR_ICM3_SMI_CTRL_BASE + SPEAR_ICM3_SYS_CTRL_BASE)
+#define SPEAR_ICM3_MISC_REG_BASE	UL(0xFCA80000)
+#define VA_SPEAR_ICM3_MISC_REG_BASE	(VA_SPEAR_ICM3_SMI_CTRL_BASE - SPEAR_ICM3_SMI_CTRL_BASE + SPEAR_ICM3_MISC_REG_BASE)
+
+/* Debug uart for linux, will be used for debug and uncompress messages */
+#define SPEAR_DBG_UART_BASE		SPEAR_ICM1_UART_BASE
+#define VA_SPEAR_DBG_UART_BASE		VA_SPEAR_ICM1_UART_BASE
+
+/* Sysctl base for spear platform */
+#define SPEAR_SYS_CTRL_BASE		SPEAR_ICM3_SYS_CTRL_BASE
+#define VA_SPEAR_SYS_CTRL_BASE		VA_SPEAR_ICM3_SYS_CTRL_BASE
+#endif /* SPEAR3xx || SPEAR6XX */
+
+/* SPEAr320 Macros */
+#define SPEAR320_SOC_CONFIG_BASE	UL(0xB3000000)
+#define VA_SPEAR320_SOC_CONFIG_BASE	IOMEM(0xFE000000)
+
+#ifdef CONFIG_ARCH_SPEAR13XX
+
+#define PERIP_GRP2_BASE				UL(0xB3000000)
+#define VA_PERIP_GRP2_BASE			IOMEM(0xFE000000)
+#define MCIF_SDHCI_BASE				UL(0xB3000000)
+#define SYSRAM0_BASE				UL(0xB3800000)
+#define VA_SYSRAM0_BASE				IOMEM(0xFE800000)
+#define SYS_LOCATION				(VA_SYSRAM0_BASE + 0x600)
+
+#define PERIP_GRP1_BASE				UL(0xE0000000)
+#define VA_PERIP_GRP1_BASE			IOMEM(0xFD000000)
+#define UART_BASE				UL(0xE0000000)
+#define VA_UART_BASE				IOMEM(0xFD000000)
+#define SSP_BASE				UL(0xE0100000)
+#define MISC_BASE				UL(0xE0700000)
+#define VA_MISC_BASE				IOMEM(0xFD700000)
+
+#define A9SM_AND_MPMC_BASE			UL(0xEC000000)
+#define VA_A9SM_AND_MPMC_BASE			IOMEM(0xFC000000)
+
+#define SPEAR1310_RAS_BASE			UL(0xD8400000)
+#define VA_SPEAR1310_RAS_BASE			IOMEM(UL(0xFA400000))
+
+/* A9SM peripheral offsets */
+#define A9SM_PERIP_BASE				UL(0xEC800000)
+#define VA_A9SM_PERIP_BASE			IOMEM(0xFC800000)
+#define VA_SCU_BASE				(VA_A9SM_PERIP_BASE + 0x00)
+
+#define L2CC_BASE				UL(0xED000000)
+#define VA_L2CC_BASE				IOMEM(UL(0xFB000000))
+
+/* others */
+#define DMAC0_BASE				UL(0xEA800000)
+#define DMAC1_BASE				UL(0xEB000000)
+#define MCIF_CF_BASE				UL(0xB2800000)
+
+/* Debug uart for linux, will be used for debug and uncompress messages */
+#define SPEAR_DBG_UART_BASE			UART_BASE
+#define VA_SPEAR_DBG_UART_BASE			VA_UART_BASE
+
+#endif /* SPEAR13XX */
+
+#endif /* __MACH_SPEAR_H */
diff --git a/arch/arm/mach-spear/include/mach/timex.h b/arch/arm/mach-spear/include/mach/timex.h
new file mode 100644
index 0000000..ef95e5b
--- /dev/null
+++ b/arch/arm/mach-spear/include/mach/timex.h
@@ -0,0 +1,19 @@
+/*
+ * arch/arm/plat-spear/include/plat/timex.h
+ *
+ * SPEAr platform specific timex definitions
+ *
+ * Copyright (C) 2009 ST Microelectronics
+ * Viresh Kumar <viresh.linux@gmail.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_TIMEX_H
+#define __PLAT_TIMEX_H
+
+#define CLOCK_TICK_RATE			48000000
+
+#endif /* __PLAT_TIMEX_H */
diff --git a/arch/arm/mach-spear/include/mach/uncompress.h b/arch/arm/mach-spear/include/mach/uncompress.h
new file mode 100644
index 0000000..51b2dc9
--- /dev/null
+++ b/arch/arm/mach-spear/include/mach/uncompress.h
@@ -0,0 +1,42 @@
+/*
+ * arch/arm/plat-spear/include/plat/uncompress.h
+ *
+ * Serial port stubs for kernel decompress status messages
+ *
+ * Copyright (C) 2009 ST Microelectronics
+ * Viresh Kumar <viresh.linux@gmail.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/io.h>
+#include <linux/amba/serial.h>
+#include <mach/spear.h>
+
+#ifndef __PLAT_UNCOMPRESS_H
+#define __PLAT_UNCOMPRESS_H
+/*
+ * This does not append a newline
+ */
+static inline void putc(int c)
+{
+	void __iomem *base = (void __iomem *)SPEAR_DBG_UART_BASE;
+
+	while (readl_relaxed(base + UART01x_FR) & UART01x_FR_TXFF)
+		barrier();
+
+	writel_relaxed(c, base + UART01x_DR);
+}
+
+static inline void flush(void)
+{
+}
+
+/*
+ * nothing to do
+ */
+#define arch_decomp_setup()
+
+#endif /* __PLAT_UNCOMPRESS_H */
diff --git a/arch/arm/mach-spear/pl080.c b/arch/arm/mach-spear/pl080.c
new file mode 100644
index 0000000..cfa1199
--- /dev/null
+++ b/arch/arm/mach-spear/pl080.c
@@ -0,0 +1,78 @@
+/*
+ * arch/arm/plat-spear/pl080.c
+ *
+ * DMAC pl080 definitions for SPEAr platform
+ *
+ * Copyright (C) 2012 ST Microelectronics
+ * Viresh Kumar <viresh.linux@gmail.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/amba/pl08x.h>
+#include <linux/amba/bus.h>
+#include <linux/bug.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/spinlock_types.h>
+#include <mach/spear.h>
+#include <mach/misc_regs.h>
+
+static spinlock_t lock = __SPIN_LOCK_UNLOCKED(x);
+
+struct {
+	unsigned char busy;
+	unsigned char val;
+} signals[16] = {{0, 0}, };
+
+int pl080_get_signal(const struct pl08x_channel_data *cd)
+{
+	unsigned int signal = cd->min_signal, val;
+	unsigned long flags;
+
+	spin_lock_irqsave(&lock, flags);
+
+	/* Return if signal is already acquired by somebody else */
+	if (signals[signal].busy &&
+			(signals[signal].val != cd->muxval)) {
+		spin_unlock_irqrestore(&lock, flags);
+		return -EBUSY;
+	}
+
+	/* If acquiring for the first time, configure it */
+	if (!signals[signal].busy) {
+		val = readl(DMA_CHN_CFG);
+
+		/*
+		 * Each request line has two bits in DMA_CHN_CFG register. To
+		 * goto the bits of current request line, do left shift of
+		 * value by 2 * signal number.
+		 */
+		val &= ~(0x3 << (signal * 2));
+		val |= cd->muxval << (signal * 2);
+		writel(val, DMA_CHN_CFG);
+	}
+
+	signals[signal].busy++;
+	signals[signal].val = cd->muxval;
+	spin_unlock_irqrestore(&lock, flags);
+
+	return signal;
+}
+
+void pl080_put_signal(const struct pl08x_channel_data *cd, int signal)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&lock, flags);
+
+	/* if signal is not used */
+	if (!signals[signal].busy)
+		BUG();
+
+	signals[signal].busy--;
+
+	spin_unlock_irqrestore(&lock, flags);
+}
diff --git a/arch/arm/mach-spear/pl080.h b/arch/arm/mach-spear/pl080.h
new file mode 100644
index 0000000..eb6590d
--- /dev/null
+++ b/arch/arm/mach-spear/pl080.h
@@ -0,0 +1,21 @@
+/*
+ * arch/arm/plat-spear/include/plat/pl080.h
+ *
+ * DMAC pl080 definitions for SPEAr platform
+ *
+ * Copyright (C) 2012 ST Microelectronics
+ * Viresh Kumar <viresh.linux@gmail.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_PL080_H
+#define __PLAT_PL080_H
+
+struct pl08x_channel_data;
+int pl080_get_signal(const struct pl08x_channel_data *cd);
+void pl080_put_signal(const struct pl08x_channel_data *cd, int signal);
+
+#endif /* __PLAT_PL080_H */
diff --git a/arch/arm/mach-spear/platsmp.c b/arch/arm/mach-spear/platsmp.c
new file mode 100644
index 0000000..9c4c722
--- /dev/null
+++ b/arch/arm/mach-spear/platsmp.c
@@ -0,0 +1,122 @@
+/*
+ * arch/arm/mach-spear13xx/platsmp.c
+ *
+ * based upon linux/arch/arm/mach-realview/platsmp.c
+ *
+ * Copyright (C) 2012 ST Microelectronics Ltd.
+ * Shiraz Hashim <shiraz.hashim@st.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/delay.h>
+#include <linux/jiffies.h>
+#include <linux/io.h>
+#include <linux/smp.h>
+#include <asm/cacheflush.h>
+#include <asm/smp_scu.h>
+#include <mach/spear.h>
+#include "generic.h"
+
+static DEFINE_SPINLOCK(boot_lock);
+
+static void __iomem *scu_base = IOMEM(VA_SCU_BASE);
+
+static void __cpuinit spear13xx_secondary_init(unsigned int cpu)
+{
+	/*
+	 * let the primary processor know we're out of the
+	 * pen, then head off into the C entry point
+	 */
+	pen_release = -1;
+	smp_wmb();
+
+	/*
+	 * Synchronise with the boot thread.
+	 */
+	spin_lock(&boot_lock);
+	spin_unlock(&boot_lock);
+}
+
+static int __cpuinit spear13xx_boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+	unsigned long timeout;
+
+	/*
+	 * set synchronisation state between this boot processor
+	 * and the secondary one
+	 */
+	spin_lock(&boot_lock);
+
+	/*
+	 * The secondary processor is waiting to be released from
+	 * the holding pen - release it, then wait for it to flag
+	 * that it has been released by resetting pen_release.
+	 *
+	 * Note that "pen_release" is the hardware CPU ID, whereas
+	 * "cpu" is Linux's internal ID.
+	 */
+	pen_release = cpu;
+	flush_cache_all();
+	outer_flush_all();
+
+	timeout = jiffies + (1 * HZ);
+	while (time_before(jiffies, timeout)) {
+		smp_rmb();
+		if (pen_release == -1)
+			break;
+
+		udelay(10);
+	}
+
+	/*
+	 * now the secondary core is starting up let it run its
+	 * calibrations, then wait for it to finish
+	 */
+	spin_unlock(&boot_lock);
+
+	return pen_release != -1 ? -ENOSYS : 0;
+}
+
+/*
+ * Initialise the CPU possible map early - this describes the CPUs
+ * which may be present or become present in the system.
+ */
+static void __init spear13xx_smp_init_cpus(void)
+{
+	unsigned int i, ncores = scu_get_core_count(scu_base);
+
+	if (ncores > nr_cpu_ids) {
+		pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
+			ncores, nr_cpu_ids);
+		ncores = nr_cpu_ids;
+	}
+
+	for (i = 0; i < ncores; i++)
+		set_cpu_possible(i, true);
+}
+
+static void __init spear13xx_smp_prepare_cpus(unsigned int max_cpus)
+{
+
+	scu_enable(scu_base);
+
+	/*
+	 * Write the address of secondary startup into the system-wide location
+	 * (presently it is in SRAM). The BootMonitor waits until it receives a
+	 * soft interrupt, and then the secondary CPU branches to this address.
+	 */
+	__raw_writel(virt_to_phys(spear13xx_secondary_startup), SYS_LOCATION);
+}
+
+struct smp_operations spear13xx_smp_ops __initdata = {
+       .smp_init_cpus		= spear13xx_smp_init_cpus,
+       .smp_prepare_cpus	= spear13xx_smp_prepare_cpus,
+       .smp_secondary_init	= spear13xx_secondary_init,
+       .smp_boot_secondary	= spear13xx_boot_secondary,
+#ifdef CONFIG_HOTPLUG_CPU
+       .cpu_die			= spear13xx_cpu_die,
+#endif
+};
diff --git a/arch/arm/mach-spear/restart.c b/arch/arm/mach-spear/restart.c
new file mode 100644
index 0000000..2b44500
--- /dev/null
+++ b/arch/arm/mach-spear/restart.c
@@ -0,0 +1,34 @@
+/*
+ * arch/arm/plat-spear/restart.c
+ *
+ * SPEAr platform specific restart functions
+ *
+ * Copyright (C) 2009 ST Microelectronics
+ * Viresh Kumar <viresh.linux@gmail.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/io.h>
+#include <linux/amba/sp810.h>
+#include <asm/system_misc.h>
+#include <mach/spear.h>
+#include "generic.h"
+
+#define SPEAR13XX_SYS_SW_RES			(VA_MISC_BASE + 0x204)
+void spear_restart(char mode, const char *cmd)
+{
+	if (mode == 's') {
+		/* software reset, Jump into ROM at address 0 */
+		soft_restart(0);
+	} else {
+		/* hardware reset, Use on-chip reset capability */
+#ifdef CONFIG_ARCH_SPEAR13XX
+		writel_relaxed(0x01, SPEAR13XX_SYS_SW_RES);
+#endif
+#if defined(CONFIG_ARCH_SPEAR3XX) || defined(CONFIG_ARCH_SPEAR6XX)
+		sysctl_soft_reset((void __iomem *)VA_SPEAR_SYS_CTRL_BASE);
+#endif
+	}
+}
diff --git a/arch/arm/mach-spear/spear1310.c b/arch/arm/mach-spear/spear1310.c
new file mode 100644
index 0000000..ed3b5c2
--- /dev/null
+++ b/arch/arm/mach-spear/spear1310.c
@@ -0,0 +1,96 @@
+/*
+ * arch/arm/mach-spear13xx/spear1310.c
+ *
+ * SPEAr1310 machine source file
+ *
+ * Copyright (C) 2012 ST Microelectronics
+ * Viresh Kumar <viresh.linux@gmail.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.
+ */
+
+#define pr_fmt(fmt) "SPEAr1310: " fmt
+
+#include <linux/amba/pl022.h>
+#include <linux/irqchip.h>
+#include <linux/of_platform.h>
+#include <linux/pata_arasan_cf_data.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include "generic.h"
+#include <mach/spear.h>
+
+/* Base addresses */
+#define SPEAR1310_SSP1_BASE			UL(0x5D400000)
+#define SPEAR1310_SATA0_BASE			UL(0xB1000000)
+#define SPEAR1310_SATA1_BASE			UL(0xB1800000)
+#define SPEAR1310_SATA2_BASE			UL(0xB4000000)
+
+#define SPEAR1310_RAS_GRP1_BASE			UL(0xD8000000)
+#define VA_SPEAR1310_RAS_GRP1_BASE		UL(0xFA000000)
+
+static struct arasan_cf_pdata cf_pdata = {
+	.cf_if_clk = CF_IF_CLK_166M,
+	.quirk = CF_BROKEN_UDMA,
+	.dma_priv = &cf_dma_priv,
+};
+
+/* ssp device registration */
+static struct pl022_ssp_controller ssp1_plat_data = {
+	.enable_dma = 0,
+};
+
+/* Add SPEAr1310 auxdata to pass platform data */
+static struct of_dev_auxdata spear1310_auxdata_lookup[] __initdata = {
+	OF_DEV_AUXDATA("arasan,cf-spear1340", MCIF_CF_BASE, NULL, &cf_pdata),
+	OF_DEV_AUXDATA("snps,dma-spear1340", DMAC0_BASE, NULL, &dmac_plat_data),
+	OF_DEV_AUXDATA("snps,dma-spear1340", DMAC1_BASE, NULL, &dmac_plat_data),
+	OF_DEV_AUXDATA("arm,pl022", SSP_BASE, NULL, &pl022_plat_data),
+
+	OF_DEV_AUXDATA("arm,pl022", SPEAR1310_SSP1_BASE, NULL, &ssp1_plat_data),
+	{}
+};
+
+static void __init spear1310_dt_init(void)
+{
+	of_platform_populate(NULL, of_default_bus_match_table,
+			spear1310_auxdata_lookup, NULL);
+}
+
+static const char * const spear1310_dt_board_compat[] = {
+	"st,spear1310",
+	"st,spear1310-evb",
+	NULL,
+};
+
+/*
+ * Following will create 16MB static virtual/physical mappings
+ * PHYSICAL		VIRTUAL
+ * 0xD8000000		0xFA000000
+ */
+struct map_desc spear1310_io_desc[] __initdata = {
+	{
+		.virtual	= VA_SPEAR1310_RAS_GRP1_BASE,
+		.pfn		= __phys_to_pfn(SPEAR1310_RAS_GRP1_BASE),
+		.length		= SZ_16M,
+		.type		= MT_DEVICE
+	},
+};
+
+static void __init spear1310_map_io(void)
+{
+	iotable_init(spear1310_io_desc, ARRAY_SIZE(spear1310_io_desc));
+	spear13xx_map_io();
+}
+
+DT_MACHINE_START(SPEAR1310_DT, "ST SPEAr1310 SoC with Flattened Device Tree")
+	.smp		=	smp_ops(spear13xx_smp_ops),
+	.map_io		=	spear1310_map_io,
+	.init_irq	=	irqchip_init,
+	.init_time	=	spear13xx_timer_init,
+	.init_machine	=	spear1310_dt_init,
+	.restart	=	spear_restart,
+	.dt_compat	=	spear1310_dt_board_compat,
+MACHINE_END
diff --git a/arch/arm/mach-spear/spear1340.c b/arch/arm/mach-spear/spear1340.c
new file mode 100644
index 0000000..75e3864
--- /dev/null
+++ b/arch/arm/mach-spear/spear1340.c
@@ -0,0 +1,193 @@
+/*
+ * arch/arm/mach-spear13xx/spear1340.c
+ *
+ * SPEAr1340 machine source file
+ *
+ * Copyright (C) 2012 ST Microelectronics
+ * Viresh Kumar <viresh.linux@gmail.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.
+ */
+
+#define pr_fmt(fmt) "SPEAr1340: " fmt
+
+#include <linux/ahci_platform.h>
+#include <linux/amba/serial.h>
+#include <linux/delay.h>
+#include <linux/dw_dmac.h>
+#include <linux/of_platform.h>
+#include <linux/irqchip.h>
+#include <asm/mach/arch.h>
+#include "generic.h"
+#include <mach/spear.h>
+
+#include "spear13xx-dma.h"
+
+/* Base addresses */
+#define SPEAR1340_SATA_BASE			UL(0xB1000000)
+#define SPEAR1340_UART1_BASE			UL(0xB4100000)
+
+/* Power Management Registers */
+#define SPEAR1340_PCM_CFG			(VA_MISC_BASE + 0x100)
+#define SPEAR1340_PCM_WKUP_CFG			(VA_MISC_BASE + 0x104)
+#define SPEAR1340_SWITCH_CTR			(VA_MISC_BASE + 0x108)
+
+#define SPEAR1340_PERIP1_SW_RST			(VA_MISC_BASE + 0x318)
+#define SPEAR1340_PERIP2_SW_RST			(VA_MISC_BASE + 0x31C)
+#define SPEAR1340_PERIP3_SW_RST			(VA_MISC_BASE + 0x320)
+
+/* PCIE - SATA configuration registers */
+#define SPEAR1340_PCIE_SATA_CFG			(VA_MISC_BASE + 0x424)
+	/* PCIE CFG MASks */
+	#define SPEAR1340_PCIE_CFG_DEVICE_PRESENT	(1 << 11)
+	#define SPEAR1340_PCIE_CFG_POWERUP_RESET	(1 << 10)
+	#define SPEAR1340_PCIE_CFG_CORE_CLK_EN		(1 << 9)
+	#define SPEAR1340_PCIE_CFG_AUX_CLK_EN		(1 << 8)
+	#define SPEAR1340_SATA_CFG_TX_CLK_EN		(1 << 4)
+	#define SPEAR1340_SATA_CFG_RX_CLK_EN		(1 << 3)
+	#define SPEAR1340_SATA_CFG_POWERUP_RESET	(1 << 2)
+	#define SPEAR1340_SATA_CFG_PM_CLK_EN		(1 << 1)
+	#define SPEAR1340_PCIE_SATA_SEL_PCIE		(0)
+	#define SPEAR1340_PCIE_SATA_SEL_SATA		(1)
+	#define SPEAR1340_SATA_PCIE_CFG_MASK		0xF1F
+	#define SPEAR1340_PCIE_CFG_VAL	(SPEAR1340_PCIE_SATA_SEL_PCIE | \
+			SPEAR1340_PCIE_CFG_AUX_CLK_EN | \
+			SPEAR1340_PCIE_CFG_CORE_CLK_EN | \
+			SPEAR1340_PCIE_CFG_POWERUP_RESET | \
+			SPEAR1340_PCIE_CFG_DEVICE_PRESENT)
+	#define SPEAR1340_SATA_CFG_VAL	(SPEAR1340_PCIE_SATA_SEL_SATA | \
+			SPEAR1340_SATA_CFG_PM_CLK_EN | \
+			SPEAR1340_SATA_CFG_POWERUP_RESET | \
+			SPEAR1340_SATA_CFG_RX_CLK_EN | \
+			SPEAR1340_SATA_CFG_TX_CLK_EN)
+
+#define SPEAR1340_PCIE_MIPHY_CFG		(VA_MISC_BASE + 0x428)
+	#define SPEAR1340_MIPHY_OSC_BYPASS_EXT		(1 << 31)
+	#define SPEAR1340_MIPHY_CLK_REF_DIV2		(1 << 27)
+	#define SPEAR1340_MIPHY_CLK_REF_DIV4		(2 << 27)
+	#define SPEAR1340_MIPHY_CLK_REF_DIV8		(3 << 27)
+	#define SPEAR1340_MIPHY_PLL_RATIO_TOP(x)	(x << 0)
+	#define SPEAR1340_PCIE_SATA_MIPHY_CFG_SATA \
+			(SPEAR1340_MIPHY_OSC_BYPASS_EXT | \
+			SPEAR1340_MIPHY_CLK_REF_DIV2 | \
+			SPEAR1340_MIPHY_PLL_RATIO_TOP(60))
+	#define SPEAR1340_PCIE_SATA_MIPHY_CFG_SATA_25M_CRYSTAL_CLK \
+			(SPEAR1340_MIPHY_PLL_RATIO_TOP(120))
+	#define SPEAR1340_PCIE_SATA_MIPHY_CFG_PCIE \
+			(SPEAR1340_MIPHY_OSC_BYPASS_EXT | \
+			SPEAR1340_MIPHY_PLL_RATIO_TOP(25))
+
+static struct dw_dma_slave uart1_dma_param[] = {
+	{
+		/* Tx */
+		.cfg_hi = DWC_CFGH_DST_PER(SPEAR1340_DMA_REQ_UART1_TX),
+		.cfg_lo = 0,
+		.src_master = DMA_MASTER_MEMORY,
+		.dst_master = SPEAR1340_DMA_MASTER_UART1,
+	}, {
+		/* Rx */
+		.cfg_hi = DWC_CFGH_SRC_PER(SPEAR1340_DMA_REQ_UART1_RX),
+		.cfg_lo = 0,
+		.src_master = SPEAR1340_DMA_MASTER_UART1,
+		.dst_master = DMA_MASTER_MEMORY,
+	}
+};
+
+static struct amba_pl011_data uart1_data = {
+	.dma_filter = dw_dma_filter,
+	.dma_tx_param = &uart1_dma_param[0],
+	.dma_rx_param = &uart1_dma_param[1],
+};
+
+/* SATA device registration */
+static int sata_miphy_init(struct device *dev, void __iomem *addr)
+{
+	writel(SPEAR1340_SATA_CFG_VAL, SPEAR1340_PCIE_SATA_CFG);
+	writel(SPEAR1340_PCIE_SATA_MIPHY_CFG_SATA_25M_CRYSTAL_CLK,
+			SPEAR1340_PCIE_MIPHY_CFG);
+	/* Switch on sata power domain */
+	writel((readl(SPEAR1340_PCM_CFG) | (0x800)), SPEAR1340_PCM_CFG);
+	msleep(20);
+	/* Disable PCIE SATA Controller reset */
+	writel((readl(SPEAR1340_PERIP1_SW_RST) & (~0x1000)),
+			SPEAR1340_PERIP1_SW_RST);
+	msleep(20);
+
+	return 0;
+}
+
+void sata_miphy_exit(struct device *dev)
+{
+	writel(0, SPEAR1340_PCIE_SATA_CFG);
+	writel(0, SPEAR1340_PCIE_MIPHY_CFG);
+
+	/* Enable PCIE SATA Controller reset */
+	writel((readl(SPEAR1340_PERIP1_SW_RST) | (0x1000)),
+			SPEAR1340_PERIP1_SW_RST);
+	msleep(20);
+	/* Switch off sata power domain */
+	writel((readl(SPEAR1340_PCM_CFG) & (~0x800)), SPEAR1340_PCM_CFG);
+	msleep(20);
+}
+
+int sata_suspend(struct device *dev)
+{
+	if (dev->power.power_state.event == PM_EVENT_FREEZE)
+		return 0;
+
+	sata_miphy_exit(dev);
+
+	return 0;
+}
+
+int sata_resume(struct device *dev)
+{
+	if (dev->power.power_state.event == PM_EVENT_THAW)
+		return 0;
+
+	return sata_miphy_init(dev, NULL);
+}
+
+static struct ahci_platform_data sata_pdata = {
+	.init = sata_miphy_init,
+	.exit = sata_miphy_exit,
+	.suspend = sata_suspend,
+	.resume = sata_resume,
+};
+
+/* Add SPEAr1340 auxdata to pass platform data */
+static struct of_dev_auxdata spear1340_auxdata_lookup[] __initdata = {
+	OF_DEV_AUXDATA("arasan,cf-spear1340", MCIF_CF_BASE, NULL, &cf_dma_priv),
+	OF_DEV_AUXDATA("snps,dma-spear1340", DMAC0_BASE, NULL, &dmac_plat_data),
+	OF_DEV_AUXDATA("snps,dma-spear1340", DMAC1_BASE, NULL, &dmac_plat_data),
+	OF_DEV_AUXDATA("arm,pl022", SSP_BASE, NULL, &pl022_plat_data),
+
+	OF_DEV_AUXDATA("snps,spear-ahci", SPEAR1340_SATA_BASE, NULL,
+			&sata_pdata),
+	OF_DEV_AUXDATA("arm,pl011", SPEAR1340_UART1_BASE, NULL, &uart1_data),
+	{}
+};
+
+static void __init spear1340_dt_init(void)
+{
+	of_platform_populate(NULL, of_default_bus_match_table,
+			spear1340_auxdata_lookup, NULL);
+}
+
+static const char * const spear1340_dt_board_compat[] = {
+	"st,spear1340",
+	"st,spear1340-evb",
+	NULL,
+};
+
+DT_MACHINE_START(SPEAR1340_DT, "ST SPEAr1340 SoC with Flattened Device Tree")
+	.smp		=	smp_ops(spear13xx_smp_ops),
+	.map_io		=	spear13xx_map_io,
+	.init_irq	=	irqchip_init,
+	.init_time	=	spear13xx_timer_init,
+	.init_machine	=	spear1340_dt_init,
+	.restart	=	spear_restart,
+	.dt_compat	=	spear1340_dt_board_compat,
+MACHINE_END
diff --git a/arch/arm/mach-spear/spear13xx-dma.h b/arch/arm/mach-spear/spear13xx-dma.h
new file mode 100644
index 0000000..d50bdb6
--- /dev/null
+++ b/arch/arm/mach-spear/spear13xx-dma.h
@@ -0,0 +1,128 @@
+/*
+ * arch/arm/mach-spear13xx/include/mach/dma.h
+ *
+ * DMA information for SPEAr13xx machine family
+ *
+ * Copyright (C) 2012 ST Microelectronics
+ * Viresh Kumar <viresh.linux@gmail.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_DMA_H
+#define __MACH_DMA_H
+
+/* request id of all the peripherals */
+enum dma_master_info {
+	/* Accessible from only one master */
+	DMA_MASTER_MCIF = 0,
+	DMA_MASTER_FSMC = 1,
+	/* Accessible from both 0 & 1 */
+	DMA_MASTER_MEMORY = 0,
+	DMA_MASTER_ADC = 0,
+	DMA_MASTER_UART0 = 0,
+	DMA_MASTER_SSP0 = 0,
+	DMA_MASTER_I2C0 = 0,
+
+#ifdef CONFIG_MACH_SPEAR1310
+	/* Accessible from only one master */
+	SPEAR1310_DMA_MASTER_JPEG = 1,
+
+	/* Accessible from both 0 & 1 */
+	SPEAR1310_DMA_MASTER_I2S = 0,
+	SPEAR1310_DMA_MASTER_UART1 = 0,
+	SPEAR1310_DMA_MASTER_UART2 = 0,
+	SPEAR1310_DMA_MASTER_UART3 = 0,
+	SPEAR1310_DMA_MASTER_UART4 = 0,
+	SPEAR1310_DMA_MASTER_UART5 = 0,
+	SPEAR1310_DMA_MASTER_I2C1 = 0,
+	SPEAR1310_DMA_MASTER_I2C2 = 0,
+	SPEAR1310_DMA_MASTER_I2C3 = 0,
+	SPEAR1310_DMA_MASTER_I2C4 = 0,
+	SPEAR1310_DMA_MASTER_I2C5 = 0,
+	SPEAR1310_DMA_MASTER_I2C6 = 0,
+	SPEAR1310_DMA_MASTER_I2C7 = 0,
+	SPEAR1310_DMA_MASTER_SSP1 = 0,
+#endif
+
+#ifdef CONFIG_MACH_SPEAR1340
+	/* Accessible from only one master */
+	SPEAR1340_DMA_MASTER_I2S_PLAY = 1,
+	SPEAR1340_DMA_MASTER_I2S_REC = 1,
+	SPEAR1340_DMA_MASTER_I2C1 = 1,
+	SPEAR1340_DMA_MASTER_UART1 = 1,
+
+	/* following are accessible from both master 0 & 1 */
+	SPEAR1340_DMA_MASTER_SPDIF = 0,
+	SPEAR1340_DMA_MASTER_CAM = 1,
+	SPEAR1340_DMA_MASTER_VIDEO_IN = 0,
+	SPEAR1340_DMA_MASTER_MALI = 0,
+#endif
+};
+
+enum request_id {
+	DMA_REQ_ADC = 0,
+	DMA_REQ_SSP0_TX = 4,
+	DMA_REQ_SSP0_RX = 5,
+	DMA_REQ_UART0_TX = 6,
+	DMA_REQ_UART0_RX = 7,
+	DMA_REQ_I2C0_TX = 8,
+	DMA_REQ_I2C0_RX = 9,
+
+#ifdef CONFIG_MACH_SPEAR1310
+	SPEAR1310_DMA_REQ_FROM_JPEG = 2,
+	SPEAR1310_DMA_REQ_TO_JPEG = 3,
+	SPEAR1310_DMA_REQ_I2S_TX = 10,
+	SPEAR1310_DMA_REQ_I2S_RX = 11,
+
+	SPEAR1310_DMA_REQ_I2C1_RX = 0,
+	SPEAR1310_DMA_REQ_I2C1_TX = 1,
+	SPEAR1310_DMA_REQ_I2C2_RX = 2,
+	SPEAR1310_DMA_REQ_I2C2_TX = 3,
+	SPEAR1310_DMA_REQ_I2C3_RX = 4,
+	SPEAR1310_DMA_REQ_I2C3_TX = 5,
+	SPEAR1310_DMA_REQ_I2C4_RX = 6,
+	SPEAR1310_DMA_REQ_I2C4_TX = 7,
+	SPEAR1310_DMA_REQ_I2C5_RX = 8,
+	SPEAR1310_DMA_REQ_I2C5_TX = 9,
+	SPEAR1310_DMA_REQ_I2C6_RX = 10,
+	SPEAR1310_DMA_REQ_I2C6_TX = 11,
+	SPEAR1310_DMA_REQ_UART1_RX = 12,
+	SPEAR1310_DMA_REQ_UART1_TX = 13,
+	SPEAR1310_DMA_REQ_UART2_RX = 14,
+	SPEAR1310_DMA_REQ_UART2_TX = 15,
+	SPEAR1310_DMA_REQ_UART5_RX = 16,
+	SPEAR1310_DMA_REQ_UART5_TX = 17,
+	SPEAR1310_DMA_REQ_SSP1_RX = 18,
+	SPEAR1310_DMA_REQ_SSP1_TX = 19,
+	SPEAR1310_DMA_REQ_I2C7_RX = 20,
+	SPEAR1310_DMA_REQ_I2C7_TX = 21,
+	SPEAR1310_DMA_REQ_UART3_RX = 28,
+	SPEAR1310_DMA_REQ_UART3_TX = 29,
+	SPEAR1310_DMA_REQ_UART4_RX = 30,
+	SPEAR1310_DMA_REQ_UART4_TX = 31,
+#endif
+
+#ifdef CONFIG_MACH_SPEAR1340
+	SPEAR1340_DMA_REQ_SPDIF_TX = 2,
+	SPEAR1340_DMA_REQ_SPDIF_RX = 3,
+	SPEAR1340_DMA_REQ_I2S_TX = 10,
+	SPEAR1340_DMA_REQ_I2S_RX = 11,
+	SPEAR1340_DMA_REQ_UART1_TX = 12,
+	SPEAR1340_DMA_REQ_UART1_RX = 13,
+	SPEAR1340_DMA_REQ_I2C1_TX = 14,
+	SPEAR1340_DMA_REQ_I2C1_RX = 15,
+	SPEAR1340_DMA_REQ_CAM0_EVEN = 0,
+	SPEAR1340_DMA_REQ_CAM0_ODD = 1,
+	SPEAR1340_DMA_REQ_CAM1_EVEN = 2,
+	SPEAR1340_DMA_REQ_CAM1_ODD = 3,
+	SPEAR1340_DMA_REQ_CAM2_EVEN = 4,
+	SPEAR1340_DMA_REQ_CAM2_ODD = 5,
+	SPEAR1340_DMA_REQ_CAM3_EVEN = 6,
+	SPEAR1340_DMA_REQ_CAM3_ODD = 7,
+#endif
+};
+
+#endif /* __MACH_DMA_H */
diff --git a/arch/arm/mach-spear/spear13xx.c b/arch/arm/mach-spear/spear13xx.c
new file mode 100644
index 0000000..6dd2089
--- /dev/null
+++ b/arch/arm/mach-spear/spear13xx.c
@@ -0,0 +1,184 @@
+/*
+ * arch/arm/mach-spear13xx/spear13xx.c
+ *
+ * SPEAr13XX machines common source file
+ *
+ * Copyright (C) 2012 ST Microelectronics
+ * Viresh Kumar <viresh.linux@gmail.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.
+ */
+
+#define pr_fmt(fmt) "SPEAr13xx: " fmt
+
+#include <linux/amba/pl022.h>
+#include <linux/clk.h>
+#include <linux/clocksource.h>
+#include <linux/dw_dmac.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <asm/hardware/cache-l2x0.h>
+#include <asm/mach/map.h>
+#include "generic.h"
+#include <mach/spear.h>
+
+#include "spear13xx-dma.h"
+
+/* common dw_dma filter routine to be used by peripherals */
+bool dw_dma_filter(struct dma_chan *chan, void *slave)
+{
+	struct dw_dma_slave *dws = (struct dw_dma_slave *)slave;
+
+	if (chan->device->dev == dws->dma_dev) {
+		chan->private = slave;
+		return true;
+	} else {
+		return false;
+	}
+}
+
+/* ssp device registration */
+static struct dw_dma_slave ssp_dma_param[] = {
+	{
+		/* Tx */
+		.cfg_hi = DWC_CFGH_DST_PER(DMA_REQ_SSP0_TX),
+		.cfg_lo = 0,
+		.src_master = DMA_MASTER_MEMORY,
+		.dst_master = DMA_MASTER_SSP0,
+	}, {
+		/* Rx */
+		.cfg_hi = DWC_CFGH_SRC_PER(DMA_REQ_SSP0_RX),
+		.cfg_lo = 0,
+		.src_master = DMA_MASTER_SSP0,
+		.dst_master = DMA_MASTER_MEMORY,
+	}
+};
+
+struct pl022_ssp_controller pl022_plat_data = {
+	.enable_dma = 1,
+	.dma_filter = dw_dma_filter,
+	.dma_rx_param = &ssp_dma_param[1],
+	.dma_tx_param = &ssp_dma_param[0],
+};
+
+/* CF device registration */
+struct dw_dma_slave cf_dma_priv = {
+	.cfg_hi = 0,
+	.cfg_lo = 0,
+	.src_master = 0,
+	.dst_master = 0,
+};
+
+/* dmac device registeration */
+struct dw_dma_platform_data dmac_plat_data = {
+	.nr_channels = 8,
+	.chan_allocation_order = CHAN_ALLOCATION_DESCENDING,
+	.chan_priority = CHAN_PRIORITY_DESCENDING,
+	.block_size = 4095U,
+	.nr_masters = 2,
+	.data_width = { 3, 3, 0, 0 },
+};
+
+void __init spear13xx_l2x0_init(void)
+{
+	/*
+	 * 512KB (64KB/way), 8-way associativity, parity supported
+	 *
+	 * FIXME: 9th bit, of Auxillary Controller register must be set
+	 * for some spear13xx devices for stable L2 operation.
+	 *
+	 * Enable Early BRESP, L2 prefetch for Instruction and Data,
+	 * write alloc and 'Full line of zero' options
+	 *
+	 */
+
+	writel_relaxed(0x06, VA_L2CC_BASE + L2X0_PREFETCH_CTRL);
+
+	/*
+	 * Program following latencies in order to make
+	 * SPEAr1340 work at 600 MHz
+	 */
+	writel_relaxed(0x221, VA_L2CC_BASE + L2X0_TAG_LATENCY_CTRL);
+	writel_relaxed(0x441, VA_L2CC_BASE + L2X0_DATA_LATENCY_CTRL);
+	l2x0_init(VA_L2CC_BASE, 0x70A60001, 0xfe00ffff);
+}
+
+/*
+ * Following will create 16MB static virtual/physical mappings
+ * PHYSICAL		VIRTUAL
+ * 0xB3000000		0xFE000000
+ * 0xE0000000		0xFD000000
+ * 0xEC000000		0xFC000000
+ * 0xED000000		0xFB000000
+ */
+struct map_desc spear13xx_io_desc[] __initdata = {
+	{
+		.virtual	= (unsigned long)VA_PERIP_GRP2_BASE,
+		.pfn		= __phys_to_pfn(PERIP_GRP2_BASE),
+		.length		= SZ_16M,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= (unsigned long)VA_PERIP_GRP1_BASE,
+		.pfn		= __phys_to_pfn(PERIP_GRP1_BASE),
+		.length		= SZ_16M,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= (unsigned long)VA_A9SM_AND_MPMC_BASE,
+		.pfn		= __phys_to_pfn(A9SM_AND_MPMC_BASE),
+		.length		= SZ_16M,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= (unsigned long)VA_L2CC_BASE,
+		.pfn		= __phys_to_pfn(L2CC_BASE),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE
+	},
+};
+
+/* This will create static memory mapping for selected devices */
+void __init spear13xx_map_io(void)
+{
+	iotable_init(spear13xx_io_desc, ARRAY_SIZE(spear13xx_io_desc));
+}
+
+static void __init spear13xx_clk_init(void)
+{
+	if (of_machine_is_compatible("st,spear1310"))
+		spear1310_clk_init(VA_MISC_BASE, VA_SPEAR1310_RAS_BASE);
+	else if (of_machine_is_compatible("st,spear1340"))
+		spear1340_clk_init(VA_MISC_BASE);
+	else
+		pr_err("%s: Unknown machine\n", __func__);
+}
+
+void __init spear13xx_timer_init(void)
+{
+	char pclk_name[] = "osc_24m_clk";
+	struct clk *gpt_clk, *pclk;
+
+	spear13xx_clk_init();
+
+	/* get the system timer clock */
+	gpt_clk = clk_get_sys("gpt0", NULL);
+	if (IS_ERR(gpt_clk)) {
+		pr_err("%s:couldn't get clk for gpt\n", __func__);
+		BUG();
+	}
+
+	/* get the suitable parent clock for timer*/
+	pclk = clk_get(NULL, pclk_name);
+	if (IS_ERR(pclk)) {
+		pr_err("%s:couldn't get %s as parent for gpt\n", __func__,
+				pclk_name);
+		BUG();
+	}
+
+	clk_set_parent(gpt_clk, pclk);
+	clk_put(gpt_clk);
+	clk_put(pclk);
+
+	spear_setup_of_timer();
+	clocksource_of_init();
+}
diff --git a/arch/arm/mach-spear/spear300.c b/arch/arm/mach-spear/spear300.c
new file mode 100644
index 0000000..bac56e8
--- /dev/null
+++ b/arch/arm/mach-spear/spear300.c
@@ -0,0 +1,220 @@
+/*
+ * arch/arm/mach-spear3xx/spear300.c
+ *
+ * SPEAr300 machine source file
+ *
+ * Copyright (C) 2009-2012 ST Microelectronics
+ * Viresh Kumar <viresh.linux@gmail.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.
+ */
+
+#define pr_fmt(fmt) "SPEAr300: " fmt
+
+#include <linux/amba/pl08x.h>
+#include <linux/irqchip.h>
+#include <linux/of_platform.h>
+#include <asm/mach/arch.h>
+#include "generic.h"
+#include <mach/spear.h>
+
+/* DMAC platform data's slave info */
+struct pl08x_channel_data spear300_dma_info[] = {
+	{
+		.bus_id = "uart0_rx",
+		.min_signal = 2,
+		.max_signal = 2,
+		.muxval = 0,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "uart0_tx",
+		.min_signal = 3,
+		.max_signal = 3,
+		.muxval = 0,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "ssp0_rx",
+		.min_signal = 8,
+		.max_signal = 8,
+		.muxval = 0,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "ssp0_tx",
+		.min_signal = 9,
+		.max_signal = 9,
+		.muxval = 0,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "i2c_rx",
+		.min_signal = 10,
+		.max_signal = 10,
+		.muxval = 0,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "i2c_tx",
+		.min_signal = 11,
+		.max_signal = 11,
+		.muxval = 0,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "irda",
+		.min_signal = 12,
+		.max_signal = 12,
+		.muxval = 0,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "adc",
+		.min_signal = 13,
+		.max_signal = 13,
+		.muxval = 0,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "to_jpeg",
+		.min_signal = 14,
+		.max_signal = 14,
+		.muxval = 0,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "from_jpeg",
+		.min_signal = 15,
+		.max_signal = 15,
+		.muxval = 0,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "ras0_rx",
+		.min_signal = 0,
+		.max_signal = 0,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "ras0_tx",
+		.min_signal = 1,
+		.max_signal = 1,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "ras1_rx",
+		.min_signal = 2,
+		.max_signal = 2,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "ras1_tx",
+		.min_signal = 3,
+		.max_signal = 3,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "ras2_rx",
+		.min_signal = 4,
+		.max_signal = 4,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "ras2_tx",
+		.min_signal = 5,
+		.max_signal = 5,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "ras3_rx",
+		.min_signal = 6,
+		.max_signal = 6,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "ras3_tx",
+		.min_signal = 7,
+		.max_signal = 7,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "ras4_rx",
+		.min_signal = 8,
+		.max_signal = 8,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "ras4_tx",
+		.min_signal = 9,
+		.max_signal = 9,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "ras5_rx",
+		.min_signal = 10,
+		.max_signal = 10,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "ras5_tx",
+		.min_signal = 11,
+		.max_signal = 11,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "ras6_rx",
+		.min_signal = 12,
+		.max_signal = 12,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "ras6_tx",
+		.min_signal = 13,
+		.max_signal = 13,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "ras7_rx",
+		.min_signal = 14,
+		.max_signal = 14,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "ras7_tx",
+		.min_signal = 15,
+		.max_signal = 15,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB1,
+	},
+};
+
+/* Add SPEAr300 auxdata to pass platform data */
+static struct of_dev_auxdata spear300_auxdata_lookup[] __initdata = {
+	OF_DEV_AUXDATA("arm,pl022", SPEAR3XX_ICM1_SSP_BASE, NULL,
+			&pl022_plat_data),
+	OF_DEV_AUXDATA("arm,pl080", SPEAR_ICM3_DMA_BASE, NULL,
+			&pl080_plat_data),
+	{}
+};
+
+static void __init spear300_dt_init(void)
+{
+	pl080_plat_data.slave_channels = spear300_dma_info;
+	pl080_plat_data.num_slave_channels = ARRAY_SIZE(spear300_dma_info);
+
+	of_platform_populate(NULL, of_default_bus_match_table,
+			spear300_auxdata_lookup, NULL);
+}
+
+static const char * const spear300_dt_board_compat[] = {
+	"st,spear300",
+	"st,spear300-evb",
+	NULL,
+};
+
+static void __init spear300_map_io(void)
+{
+	spear3xx_map_io();
+}
+
+DT_MACHINE_START(SPEAR300_DT, "ST SPEAr300 SoC with Flattened Device Tree")
+	.map_io		=	spear300_map_io,
+	.init_irq	=	irqchip_init,
+	.init_time	=	spear3xx_timer_init,
+	.init_machine	=	spear300_dt_init,
+	.restart	=	spear_restart,
+	.dt_compat	=	spear300_dt_board_compat,
+MACHINE_END
diff --git a/arch/arm/mach-spear/spear310.c b/arch/arm/mach-spear/spear310.c
new file mode 100644
index 0000000..6ffbc63
--- /dev/null
+++ b/arch/arm/mach-spear/spear310.c
@@ -0,0 +1,262 @@
+/*
+ * arch/arm/mach-spear3xx/spear310.c
+ *
+ * SPEAr310 machine source file
+ *
+ * Copyright (C) 2009-2012 ST Microelectronics
+ * Viresh Kumar <viresh.linux@gmail.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.
+ */
+
+#define pr_fmt(fmt) "SPEAr310: " fmt
+
+#include <linux/amba/pl08x.h>
+#include <linux/amba/serial.h>
+#include <linux/irqchip.h>
+#include <linux/of_platform.h>
+#include <asm/mach/arch.h>
+#include "generic.h"
+#include <mach/spear.h>
+
+#define SPEAR310_UART1_BASE		UL(0xB2000000)
+#define SPEAR310_UART2_BASE		UL(0xB2080000)
+#define SPEAR310_UART3_BASE		UL(0xB2100000)
+#define SPEAR310_UART4_BASE		UL(0xB2180000)
+#define SPEAR310_UART5_BASE		UL(0xB2200000)
+
+/* DMAC platform data's slave info */
+struct pl08x_channel_data spear310_dma_info[] = {
+	{
+		.bus_id = "uart0_rx",
+		.min_signal = 2,
+		.max_signal = 2,
+		.muxval = 0,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "uart0_tx",
+		.min_signal = 3,
+		.max_signal = 3,
+		.muxval = 0,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "ssp0_rx",
+		.min_signal = 8,
+		.max_signal = 8,
+		.muxval = 0,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "ssp0_tx",
+		.min_signal = 9,
+		.max_signal = 9,
+		.muxval = 0,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "i2c_rx",
+		.min_signal = 10,
+		.max_signal = 10,
+		.muxval = 0,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "i2c_tx",
+		.min_signal = 11,
+		.max_signal = 11,
+		.muxval = 0,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "irda",
+		.min_signal = 12,
+		.max_signal = 12,
+		.muxval = 0,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "adc",
+		.min_signal = 13,
+		.max_signal = 13,
+		.muxval = 0,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "to_jpeg",
+		.min_signal = 14,
+		.max_signal = 14,
+		.muxval = 0,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "from_jpeg",
+		.min_signal = 15,
+		.max_signal = 15,
+		.muxval = 0,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "uart1_rx",
+		.min_signal = 0,
+		.max_signal = 0,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "uart1_tx",
+		.min_signal = 1,
+		.max_signal = 1,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "uart2_rx",
+		.min_signal = 2,
+		.max_signal = 2,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "uart2_tx",
+		.min_signal = 3,
+		.max_signal = 3,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "uart3_rx",
+		.min_signal = 4,
+		.max_signal = 4,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "uart3_tx",
+		.min_signal = 5,
+		.max_signal = 5,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "uart4_rx",
+		.min_signal = 6,
+		.max_signal = 6,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "uart4_tx",
+		.min_signal = 7,
+		.max_signal = 7,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "uart5_rx",
+		.min_signal = 8,
+		.max_signal = 8,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "uart5_tx",
+		.min_signal = 9,
+		.max_signal = 9,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "ras5_rx",
+		.min_signal = 10,
+		.max_signal = 10,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "ras5_tx",
+		.min_signal = 11,
+		.max_signal = 11,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "ras6_rx",
+		.min_signal = 12,
+		.max_signal = 12,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "ras6_tx",
+		.min_signal = 13,
+		.max_signal = 13,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "ras7_rx",
+		.min_signal = 14,
+		.max_signal = 14,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "ras7_tx",
+		.min_signal = 15,
+		.max_signal = 15,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB1,
+	},
+};
+
+/* uart devices plat data */
+static struct amba_pl011_data spear310_uart_data[] = {
+	{
+		.dma_filter = pl08x_filter_id,
+		.dma_tx_param = "uart1_tx",
+		.dma_rx_param = "uart1_rx",
+	}, {
+		.dma_filter = pl08x_filter_id,
+		.dma_tx_param = "uart2_tx",
+		.dma_rx_param = "uart2_rx",
+	}, {
+		.dma_filter = pl08x_filter_id,
+		.dma_tx_param = "uart3_tx",
+		.dma_rx_param = "uart3_rx",
+	}, {
+		.dma_filter = pl08x_filter_id,
+		.dma_tx_param = "uart4_tx",
+		.dma_rx_param = "uart4_rx",
+	}, {
+		.dma_filter = pl08x_filter_id,
+		.dma_tx_param = "uart5_tx",
+		.dma_rx_param = "uart5_rx",
+	},
+};
+
+/* Add SPEAr310 auxdata to pass platform data */
+static struct of_dev_auxdata spear310_auxdata_lookup[] __initdata = {
+	OF_DEV_AUXDATA("arm,pl022", SPEAR3XX_ICM1_SSP_BASE, NULL,
+			&pl022_plat_data),
+	OF_DEV_AUXDATA("arm,pl080", SPEAR_ICM3_DMA_BASE, NULL,
+			&pl080_plat_data),
+	OF_DEV_AUXDATA("arm,pl011", SPEAR310_UART1_BASE, NULL,
+			&spear310_uart_data[0]),
+	OF_DEV_AUXDATA("arm,pl011", SPEAR310_UART2_BASE, NULL,
+			&spear310_uart_data[1]),
+	OF_DEV_AUXDATA("arm,pl011", SPEAR310_UART3_BASE, NULL,
+			&spear310_uart_data[2]),
+	OF_DEV_AUXDATA("arm,pl011", SPEAR310_UART4_BASE, NULL,
+			&spear310_uart_data[3]),
+	OF_DEV_AUXDATA("arm,pl011", SPEAR310_UART5_BASE, NULL,
+			&spear310_uart_data[4]),
+	{}
+};
+
+static void __init spear310_dt_init(void)
+{
+	pl080_plat_data.slave_channels = spear310_dma_info;
+	pl080_plat_data.num_slave_channels = ARRAY_SIZE(spear310_dma_info);
+
+	of_platform_populate(NULL, of_default_bus_match_table,
+			spear310_auxdata_lookup, NULL);
+}
+
+static const char * const spear310_dt_board_compat[] = {
+	"st,spear310",
+	"st,spear310-evb",
+	NULL,
+};
+
+static void __init spear310_map_io(void)
+{
+	spear3xx_map_io();
+}
+
+DT_MACHINE_START(SPEAR310_DT, "ST SPEAr310 SoC with Flattened Device Tree")
+	.map_io		=	spear310_map_io,
+	.init_irq	=	irqchip_init,
+	.init_time	=	spear3xx_timer_init,
+	.init_machine	=	spear310_dt_init,
+	.restart	=	spear_restart,
+	.dt_compat	=	spear310_dt_board_compat,
+MACHINE_END
diff --git a/arch/arm/mach-spear/spear320.c b/arch/arm/mach-spear/spear320.c
new file mode 100644
index 0000000..6eb3eec
--- /dev/null
+++ b/arch/arm/mach-spear/spear320.c
@@ -0,0 +1,277 @@
+/*
+ * arch/arm/mach-spear3xx/spear320.c
+ *
+ * SPEAr320 machine source file
+ *
+ * Copyright (C) 2009-2012 ST Microelectronics
+ * Viresh Kumar <viresh.linux@gmail.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.
+ */
+
+#define pr_fmt(fmt) "SPEAr320: " fmt
+
+#include <linux/amba/pl022.h>
+#include <linux/amba/pl08x.h>
+#include <linux/amba/serial.h>
+#include <linux/irqchip.h>
+#include <linux/of_platform.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include "generic.h"
+#include <mach/spear.h>
+
+#define SPEAR320_UART1_BASE		UL(0xA3000000)
+#define SPEAR320_UART2_BASE		UL(0xA4000000)
+#define SPEAR320_SSP0_BASE		UL(0xA5000000)
+#define SPEAR320_SSP1_BASE		UL(0xA6000000)
+
+/* DMAC platform data's slave info */
+struct pl08x_channel_data spear320_dma_info[] = {
+	{
+		.bus_id = "uart0_rx",
+		.min_signal = 2,
+		.max_signal = 2,
+		.muxval = 0,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "uart0_tx",
+		.min_signal = 3,
+		.max_signal = 3,
+		.muxval = 0,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "ssp0_rx",
+		.min_signal = 8,
+		.max_signal = 8,
+		.muxval = 0,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "ssp0_tx",
+		.min_signal = 9,
+		.max_signal = 9,
+		.muxval = 0,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "i2c0_rx",
+		.min_signal = 10,
+		.max_signal = 10,
+		.muxval = 0,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "i2c0_tx",
+		.min_signal = 11,
+		.max_signal = 11,
+		.muxval = 0,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "irda",
+		.min_signal = 12,
+		.max_signal = 12,
+		.muxval = 0,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "adc",
+		.min_signal = 13,
+		.max_signal = 13,
+		.muxval = 0,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "to_jpeg",
+		.min_signal = 14,
+		.max_signal = 14,
+		.muxval = 0,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "from_jpeg",
+		.min_signal = 15,
+		.max_signal = 15,
+		.muxval = 0,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "ssp1_rx",
+		.min_signal = 0,
+		.max_signal = 0,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB2,
+	}, {
+		.bus_id = "ssp1_tx",
+		.min_signal = 1,
+		.max_signal = 1,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB2,
+	}, {
+		.bus_id = "ssp2_rx",
+		.min_signal = 2,
+		.max_signal = 2,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB2,
+	}, {
+		.bus_id = "ssp2_tx",
+		.min_signal = 3,
+		.max_signal = 3,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB2,
+	}, {
+		.bus_id = "uart1_rx",
+		.min_signal = 4,
+		.max_signal = 4,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB2,
+	}, {
+		.bus_id = "uart1_tx",
+		.min_signal = 5,
+		.max_signal = 5,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB2,
+	}, {
+		.bus_id = "uart2_rx",
+		.min_signal = 6,
+		.max_signal = 6,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB2,
+	}, {
+		.bus_id = "uart2_tx",
+		.min_signal = 7,
+		.max_signal = 7,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB2,
+	}, {
+		.bus_id = "i2c1_rx",
+		.min_signal = 8,
+		.max_signal = 8,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB2,
+	}, {
+		.bus_id = "i2c1_tx",
+		.min_signal = 9,
+		.max_signal = 9,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB2,
+	}, {
+		.bus_id = "i2c2_rx",
+		.min_signal = 10,
+		.max_signal = 10,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB2,
+	}, {
+		.bus_id = "i2c2_tx",
+		.min_signal = 11,
+		.max_signal = 11,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB2,
+	}, {
+		.bus_id = "i2s_rx",
+		.min_signal = 12,
+		.max_signal = 12,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB2,
+	}, {
+		.bus_id = "i2s_tx",
+		.min_signal = 13,
+		.max_signal = 13,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB2,
+	}, {
+		.bus_id = "rs485_rx",
+		.min_signal = 14,
+		.max_signal = 14,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB2,
+	}, {
+		.bus_id = "rs485_tx",
+		.min_signal = 15,
+		.max_signal = 15,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB2,
+	},
+};
+
+static struct pl022_ssp_controller spear320_ssp_data[] = {
+	{
+		.bus_id = 1,
+		.enable_dma = 1,
+		.dma_filter = pl08x_filter_id,
+		.dma_tx_param = "ssp1_tx",
+		.dma_rx_param = "ssp1_rx",
+		.num_chipselect = 2,
+	}, {
+		.bus_id = 2,
+		.enable_dma = 1,
+		.dma_filter = pl08x_filter_id,
+		.dma_tx_param = "ssp2_tx",
+		.dma_rx_param = "ssp2_rx",
+		.num_chipselect = 2,
+	}
+};
+
+static struct amba_pl011_data spear320_uart_data[] = {
+	{
+		.dma_filter = pl08x_filter_id,
+		.dma_tx_param = "uart1_tx",
+		.dma_rx_param = "uart1_rx",
+	}, {
+		.dma_filter = pl08x_filter_id,
+		.dma_tx_param = "uart2_tx",
+		.dma_rx_param = "uart2_rx",
+	},
+};
+
+/* Add SPEAr310 auxdata to pass platform data */
+static struct of_dev_auxdata spear320_auxdata_lookup[] __initdata = {
+	OF_DEV_AUXDATA("arm,pl022", SPEAR3XX_ICM1_SSP_BASE, NULL,
+			&pl022_plat_data),
+	OF_DEV_AUXDATA("arm,pl080", SPEAR_ICM3_DMA_BASE, NULL,
+			&pl080_plat_data),
+	OF_DEV_AUXDATA("arm,pl022", SPEAR320_SSP0_BASE, NULL,
+			&spear320_ssp_data[0]),
+	OF_DEV_AUXDATA("arm,pl022", SPEAR320_SSP1_BASE, NULL,
+			&spear320_ssp_data[1]),
+	OF_DEV_AUXDATA("arm,pl011", SPEAR320_UART1_BASE, NULL,
+			&spear320_uart_data[0]),
+	OF_DEV_AUXDATA("arm,pl011", SPEAR320_UART2_BASE, NULL,
+			&spear320_uart_data[1]),
+	{}
+};
+
+static void __init spear320_dt_init(void)
+{
+	pl080_plat_data.slave_channels = spear320_dma_info;
+	pl080_plat_data.num_slave_channels = ARRAY_SIZE(spear320_dma_info);
+
+	of_platform_populate(NULL, of_default_bus_match_table,
+			spear320_auxdata_lookup, NULL);
+}
+
+static const char * const spear320_dt_board_compat[] = {
+	"st,spear320",
+	"st,spear320-evb",
+	"st,spear320-hmi",
+	NULL,
+};
+
+struct map_desc spear320_io_desc[] __initdata = {
+	{
+		.virtual	= (unsigned long)VA_SPEAR320_SOC_CONFIG_BASE,
+		.pfn		= __phys_to_pfn(SPEAR320_SOC_CONFIG_BASE),
+		.length		= SZ_16M,
+		.type		= MT_DEVICE
+	},
+};
+
+static void __init spear320_map_io(void)
+{
+	iotable_init(spear320_io_desc, ARRAY_SIZE(spear320_io_desc));
+	spear3xx_map_io();
+}
+
+DT_MACHINE_START(SPEAR320_DT, "ST SPEAr320 SoC with Flattened Device Tree")
+	.map_io		=	spear320_map_io,
+	.init_irq	=	irqchip_init,
+	.init_time	=	spear3xx_timer_init,
+	.init_machine	=	spear320_dt_init,
+	.restart	=	spear_restart,
+	.dt_compat	=	spear320_dt_board_compat,
+MACHINE_END
diff --git a/arch/arm/mach-spear/spear3xx.c b/arch/arm/mach-spear/spear3xx.c
new file mode 100644
index 0000000..0227c97
--- /dev/null
+++ b/arch/arm/mach-spear/spear3xx.c
@@ -0,0 +1,116 @@
+/*
+ * arch/arm/mach-spear3xx/spear3xx.c
+ *
+ * SPEAr3XX machines common source file
+ *
+ * Copyright (C) 2009-2012 ST Microelectronics
+ * Viresh Kumar <viresh.linux@gmail.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.
+ */
+
+#define pr_fmt(fmt) "SPEAr3xx: " fmt
+
+#include <linux/amba/pl022.h>
+#include <linux/amba/pl080.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <asm/mach/map.h>
+#include "pl080.h"
+#include "generic.h"
+#include <mach/spear.h>
+#include <mach/misc_regs.h>
+
+/* ssp device registration */
+struct pl022_ssp_controller pl022_plat_data = {
+	.bus_id = 0,
+	.enable_dma = 1,
+	.dma_filter = pl08x_filter_id,
+	.dma_tx_param = "ssp0_tx",
+	.dma_rx_param = "ssp0_rx",
+	/*
+	 * This is number of spi devices that can be connected to spi. There are
+	 * two type of chipselects on which slave devices can work. One is chip
+	 * select provided by spi masters other is controlled through external
+	 * gpio's. We can't use chipselect provided from spi master (because as
+	 * soon as FIFO becomes empty, CS is disabled and transfer ends). So
+	 * this number now depends on number of gpios available for spi. each
+	 * slave on each master requires a separate gpio pin.
+	 */
+	.num_chipselect = 2,
+};
+
+/* dmac device registration */
+struct pl08x_platform_data pl080_plat_data = {
+	.memcpy_channel = {
+		.bus_id = "memcpy",
+		.cctl_memcpy =
+			(PL080_BSIZE_16 << PL080_CONTROL_SB_SIZE_SHIFT | \
+			PL080_BSIZE_16 << PL080_CONTROL_DB_SIZE_SHIFT | \
+			PL080_WIDTH_32BIT << PL080_CONTROL_SWIDTH_SHIFT | \
+			PL080_WIDTH_32BIT << PL080_CONTROL_DWIDTH_SHIFT | \
+			PL080_CONTROL_PROT_BUFF | PL080_CONTROL_PROT_CACHE | \
+			PL080_CONTROL_PROT_SYS),
+	},
+	.lli_buses = PL08X_AHB1,
+	.mem_buses = PL08X_AHB1,
+	.get_signal = pl080_get_signal,
+	.put_signal = pl080_put_signal,
+};
+
+/*
+ * Following will create 16MB static virtual/physical mappings
+ * PHYSICAL		VIRTUAL
+ * 0xD0000000		0xFD000000
+ * 0xFC000000		0xFC000000
+ */
+struct map_desc spear3xx_io_desc[] __initdata = {
+	{
+		.virtual	= (unsigned long)VA_SPEAR_ICM1_2_BASE,
+		.pfn		= __phys_to_pfn(SPEAR_ICM1_2_BASE),
+		.length		= SZ_16M,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= (unsigned long)VA_SPEAR_ICM3_SMI_CTRL_BASE,
+		.pfn		= __phys_to_pfn(SPEAR_ICM3_SMI_CTRL_BASE),
+		.length		= SZ_16M,
+		.type		= MT_DEVICE
+	},
+};
+
+/* This will create static memory mapping for selected devices */
+void __init spear3xx_map_io(void)
+{
+	iotable_init(spear3xx_io_desc, ARRAY_SIZE(spear3xx_io_desc));
+}
+
+void __init spear3xx_timer_init(void)
+{
+	char pclk_name[] = "pll3_clk";
+	struct clk *gpt_clk, *pclk;
+
+	spear3xx_clk_init(MISC_BASE, VA_SPEAR320_SOC_CONFIG_BASE);
+
+	/* get the system timer clock */
+	gpt_clk = clk_get_sys("gpt0", NULL);
+	if (IS_ERR(gpt_clk)) {
+		pr_err("%s:couldn't get clk for gpt\n", __func__);
+		BUG();
+	}
+
+	/* get the suitable parent clock for timer*/
+	pclk = clk_get(NULL, pclk_name);
+	if (IS_ERR(pclk)) {
+		pr_err("%s:couldn't get %s as parent for gpt\n",
+				__func__, pclk_name);
+		BUG();
+	}
+
+	clk_set_parent(gpt_clk, pclk);
+	clk_put(gpt_clk);
+	clk_put(pclk);
+
+	spear_setup_of_timer();
+}
diff --git a/arch/arm/mach-spear/spear6xx.c b/arch/arm/mach-spear/spear6xx.c
new file mode 100644
index 0000000..ec8eefb
--- /dev/null
+++ b/arch/arm/mach-spear/spear6xx.c
@@ -0,0 +1,431 @@
+/*
+ * arch/arm/mach-spear6xx/spear6xx.c
+ *
+ * SPEAr6XX machines common source file
+ *
+ * Copyright (C) 2009 ST Microelectronics
+ * Rajeev Kumar<rajeev-dlh.kumar@st.com>
+ *
+ * Copyright 2012 Stefan Roese <sr@denx.de>
+ *
+ * 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/amba/pl08x.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/irqchip.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/amba/pl080.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <asm/mach/map.h>
+#include "pl080.h"
+#include "generic.h"
+#include <mach/spear.h>
+#include <mach/misc_regs.h>
+
+/* dmac device registration */
+static struct pl08x_channel_data spear600_dma_info[] = {
+	{
+		.bus_id = "ssp1_rx",
+		.min_signal = 0,
+		.max_signal = 0,
+		.muxval = 0,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "ssp1_tx",
+		.min_signal = 1,
+		.max_signal = 1,
+		.muxval = 0,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "uart0_rx",
+		.min_signal = 2,
+		.max_signal = 2,
+		.muxval = 0,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "uart0_tx",
+		.min_signal = 3,
+		.max_signal = 3,
+		.muxval = 0,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "uart1_rx",
+		.min_signal = 4,
+		.max_signal = 4,
+		.muxval = 0,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "uart1_tx",
+		.min_signal = 5,
+		.max_signal = 5,
+		.muxval = 0,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "ssp2_rx",
+		.min_signal = 6,
+		.max_signal = 6,
+		.muxval = 0,
+		.periph_buses = PL08X_AHB2,
+	}, {
+		.bus_id = "ssp2_tx",
+		.min_signal = 7,
+		.max_signal = 7,
+		.muxval = 0,
+		.periph_buses = PL08X_AHB2,
+	}, {
+		.bus_id = "ssp0_rx",
+		.min_signal = 8,
+		.max_signal = 8,
+		.muxval = 0,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "ssp0_tx",
+		.min_signal = 9,
+		.max_signal = 9,
+		.muxval = 0,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "i2c_rx",
+		.min_signal = 10,
+		.max_signal = 10,
+		.muxval = 0,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "i2c_tx",
+		.min_signal = 11,
+		.max_signal = 11,
+		.muxval = 0,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "irda",
+		.min_signal = 12,
+		.max_signal = 12,
+		.muxval = 0,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "adc",
+		.min_signal = 13,
+		.max_signal = 13,
+		.muxval = 0,
+		.periph_buses = PL08X_AHB2,
+	}, {
+		.bus_id = "to_jpeg",
+		.min_signal = 14,
+		.max_signal = 14,
+		.muxval = 0,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "from_jpeg",
+		.min_signal = 15,
+		.max_signal = 15,
+		.muxval = 0,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "ras0_rx",
+		.min_signal = 0,
+		.max_signal = 0,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "ras0_tx",
+		.min_signal = 1,
+		.max_signal = 1,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "ras1_rx",
+		.min_signal = 2,
+		.max_signal = 2,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "ras1_tx",
+		.min_signal = 3,
+		.max_signal = 3,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "ras2_rx",
+		.min_signal = 4,
+		.max_signal = 4,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "ras2_tx",
+		.min_signal = 5,
+		.max_signal = 5,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "ras3_rx",
+		.min_signal = 6,
+		.max_signal = 6,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "ras3_tx",
+		.min_signal = 7,
+		.max_signal = 7,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "ras4_rx",
+		.min_signal = 8,
+		.max_signal = 8,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "ras4_tx",
+		.min_signal = 9,
+		.max_signal = 9,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "ras5_rx",
+		.min_signal = 10,
+		.max_signal = 10,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "ras5_tx",
+		.min_signal = 11,
+		.max_signal = 11,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "ras6_rx",
+		.min_signal = 12,
+		.max_signal = 12,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "ras6_tx",
+		.min_signal = 13,
+		.max_signal = 13,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "ras7_rx",
+		.min_signal = 14,
+		.max_signal = 14,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "ras7_tx",
+		.min_signal = 15,
+		.max_signal = 15,
+		.muxval = 1,
+		.periph_buses = PL08X_AHB1,
+	}, {
+		.bus_id = "ext0_rx",
+		.min_signal = 0,
+		.max_signal = 0,
+		.muxval = 2,
+		.periph_buses = PL08X_AHB2,
+	}, {
+		.bus_id = "ext0_tx",
+		.min_signal = 1,
+		.max_signal = 1,
+		.muxval = 2,
+		.periph_buses = PL08X_AHB2,
+	}, {
+		.bus_id = "ext1_rx",
+		.min_signal = 2,
+		.max_signal = 2,
+		.muxval = 2,
+		.periph_buses = PL08X_AHB2,
+	}, {
+		.bus_id = "ext1_tx",
+		.min_signal = 3,
+		.max_signal = 3,
+		.muxval = 2,
+		.periph_buses = PL08X_AHB2,
+	}, {
+		.bus_id = "ext2_rx",
+		.min_signal = 4,
+		.max_signal = 4,
+		.muxval = 2,
+		.periph_buses = PL08X_AHB2,
+	}, {
+		.bus_id = "ext2_tx",
+		.min_signal = 5,
+		.max_signal = 5,
+		.muxval = 2,
+		.periph_buses = PL08X_AHB2,
+	}, {
+		.bus_id = "ext3_rx",
+		.min_signal = 6,
+		.max_signal = 6,
+		.muxval = 2,
+		.periph_buses = PL08X_AHB2,
+	}, {
+		.bus_id = "ext3_tx",
+		.min_signal = 7,
+		.max_signal = 7,
+		.muxval = 2,
+		.periph_buses = PL08X_AHB2,
+	}, {
+		.bus_id = "ext4_rx",
+		.min_signal = 8,
+		.max_signal = 8,
+		.muxval = 2,
+		.periph_buses = PL08X_AHB2,
+	}, {
+		.bus_id = "ext4_tx",
+		.min_signal = 9,
+		.max_signal = 9,
+		.muxval = 2,
+		.periph_buses = PL08X_AHB2,
+	}, {
+		.bus_id = "ext5_rx",
+		.min_signal = 10,
+		.max_signal = 10,
+		.muxval = 2,
+		.periph_buses = PL08X_AHB2,
+	}, {
+		.bus_id = "ext5_tx",
+		.min_signal = 11,
+		.max_signal = 11,
+		.muxval = 2,
+		.periph_buses = PL08X_AHB2,
+	}, {
+		.bus_id = "ext6_rx",
+		.min_signal = 12,
+		.max_signal = 12,
+		.muxval = 2,
+		.periph_buses = PL08X_AHB2,
+	}, {
+		.bus_id = "ext6_tx",
+		.min_signal = 13,
+		.max_signal = 13,
+		.muxval = 2,
+		.periph_buses = PL08X_AHB2,
+	}, {
+		.bus_id = "ext7_rx",
+		.min_signal = 14,
+		.max_signal = 14,
+		.muxval = 2,
+		.periph_buses = PL08X_AHB2,
+	}, {
+		.bus_id = "ext7_tx",
+		.min_signal = 15,
+		.max_signal = 15,
+		.muxval = 2,
+		.periph_buses = PL08X_AHB2,
+	},
+};
+
+static struct pl08x_platform_data spear6xx_pl080_plat_data = {
+	.memcpy_channel = {
+		.bus_id = "memcpy",
+		.cctl_memcpy =
+			(PL080_BSIZE_16 << PL080_CONTROL_SB_SIZE_SHIFT | \
+			PL080_BSIZE_16 << PL080_CONTROL_DB_SIZE_SHIFT | \
+			PL080_WIDTH_32BIT << PL080_CONTROL_SWIDTH_SHIFT | \
+			PL080_WIDTH_32BIT << PL080_CONTROL_DWIDTH_SHIFT | \
+			PL080_CONTROL_PROT_BUFF | PL080_CONTROL_PROT_CACHE | \
+			PL080_CONTROL_PROT_SYS),
+	},
+	.lli_buses = PL08X_AHB1,
+	.mem_buses = PL08X_AHB1,
+	.get_signal = pl080_get_signal,
+	.put_signal = pl080_put_signal,
+	.slave_channels = spear600_dma_info,
+	.num_slave_channels = ARRAY_SIZE(spear600_dma_info),
+};
+
+/*
+ * Following will create 16MB static virtual/physical mappings
+ * PHYSICAL		VIRTUAL
+ * 0xF0000000		0xF0000000
+ * 0xF1000000		0xF1000000
+ * 0xD0000000		0xFD000000
+ * 0xFC000000		0xFC000000
+ */
+struct map_desc spear6xx_io_desc[] __initdata = {
+	{
+		.virtual	= (unsigned long)VA_SPEAR6XX_ML_CPU_BASE,
+		.pfn		= __phys_to_pfn(SPEAR_ICM3_ML1_2_BASE),
+		.length		= 2 * SZ_16M,
+		.type		= MT_DEVICE
+	},	{
+		.virtual	= (unsigned long)VA_SPEAR_ICM1_2_BASE,
+		.pfn		= __phys_to_pfn(SPEAR_ICM1_2_BASE),
+		.length		= SZ_16M,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= (unsigned long)VA_SPEAR_ICM3_SMI_CTRL_BASE,
+		.pfn		= __phys_to_pfn(SPEAR_ICM3_SMI_CTRL_BASE),
+		.length		= SZ_16M,
+		.type		= MT_DEVICE
+	},
+};
+
+/* This will create static memory mapping for selected devices */
+void __init spear6xx_map_io(void)
+{
+	iotable_init(spear6xx_io_desc, ARRAY_SIZE(spear6xx_io_desc));
+}
+
+void __init spear6xx_timer_init(void)
+{
+	char pclk_name[] = "pll3_clk";
+	struct clk *gpt_clk, *pclk;
+
+	spear6xx_clk_init(MISC_BASE);
+
+	/* get the system timer clock */
+	gpt_clk = clk_get_sys("gpt0", NULL);
+	if (IS_ERR(gpt_clk)) {
+		pr_err("%s:couldn't get clk for gpt\n", __func__);
+		BUG();
+	}
+
+	/* get the suitable parent clock for timer*/
+	pclk = clk_get(NULL, pclk_name);
+	if (IS_ERR(pclk)) {
+		pr_err("%s:couldn't get %s as parent for gpt\n",
+				__func__, pclk_name);
+		BUG();
+	}
+
+	clk_set_parent(gpt_clk, pclk);
+	clk_put(gpt_clk);
+	clk_put(pclk);
+
+	spear_setup_of_timer();
+}
+
+/* Add auxdata to pass platform data */
+struct of_dev_auxdata spear6xx_auxdata_lookup[] __initdata = {
+	OF_DEV_AUXDATA("arm,pl080", SPEAR_ICM3_DMA_BASE, NULL,
+			&spear6xx_pl080_plat_data),
+	{}
+};
+
+static void __init spear600_dt_init(void)
+{
+	of_platform_populate(NULL, of_default_bus_match_table,
+			spear6xx_auxdata_lookup, NULL);
+}
+
+static const char *spear600_dt_board_compat[] = {
+	"st,spear600",
+	NULL
+};
+
+DT_MACHINE_START(SPEAR600_DT, "ST SPEAr600 (Flattened Device Tree)")
+	.map_io		=	spear6xx_map_io,
+	.init_irq	=	irqchip_init,
+	.init_time	=	spear6xx_timer_init,
+	.init_machine	=	spear600_dt_init,
+	.restart	=	spear_restart,
+	.dt_compat	=	spear600_dt_board_compat,
+MACHINE_END
diff --git a/arch/arm/mach-spear/time.c b/arch/arm/mach-spear/time.c
new file mode 100644
index 0000000..d449673
--- /dev/null
+++ b/arch/arm/mach-spear/time.c
@@ -0,0 +1,245 @@
+/*
+ * arch/arm/plat-spear/time.c
+ *
+ * Copyright (C) 2010 ST Microelectronics
+ * Shiraz Hashim<shiraz.hashim@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.
+ */
+
+#include <linux/clk.h>
+#include <linux/clockchips.h>
+#include <linux/clocksource.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+#include <linux/time.h>
+#include <linux/irq.h>
+#include <asm/mach/time.h>
+#include "generic.h"
+
+/*
+ * We would use TIMER0 and TIMER1 as clockevent and clocksource.
+ * Timer0 and Timer1 both belong to same gpt block in cpu subbsystem. Further
+ * they share same functional clock. Any change in one's functional clock will
+ * also affect other timer.
+ */
+
+#define CLKEVT	0	/* gpt0, channel0 as clockevent */
+#define CLKSRC	1	/* gpt0, channel1 as clocksource */
+
+/* Register offsets, x is channel number */
+#define CR(x)		((x) * 0x80 + 0x80)
+#define IR(x)		((x) * 0x80 + 0x84)
+#define LOAD(x)		((x) * 0x80 + 0x88)
+#define COUNT(x)	((x) * 0x80 + 0x8C)
+
+/* Reg bit definitions */
+#define CTRL_INT_ENABLE		0x0100
+#define CTRL_ENABLE		0x0020
+#define CTRL_ONE_SHOT		0x0010
+
+#define CTRL_PRESCALER1		0x0
+#define CTRL_PRESCALER2		0x1
+#define CTRL_PRESCALER4		0x2
+#define CTRL_PRESCALER8		0x3
+#define CTRL_PRESCALER16	0x4
+#define CTRL_PRESCALER32	0x5
+#define CTRL_PRESCALER64	0x6
+#define CTRL_PRESCALER128	0x7
+#define CTRL_PRESCALER256	0x8
+
+#define INT_STATUS		0x1
+
+/*
+ * Minimum clocksource/clockevent timer range in seconds
+ */
+#define SPEAR_MIN_RANGE 4
+
+static __iomem void *gpt_base;
+static struct clk *gpt_clk;
+
+static void clockevent_set_mode(enum clock_event_mode mode,
+				struct clock_event_device *clk_event_dev);
+static int clockevent_next_event(unsigned long evt,
+				 struct clock_event_device *clk_event_dev);
+
+static void spear_clocksource_init(void)
+{
+	u32 tick_rate;
+	u16 val;
+
+	/* program the prescaler (/256)*/
+	writew(CTRL_PRESCALER256, gpt_base + CR(CLKSRC));
+
+	/* find out actual clock driving Timer */
+	tick_rate = clk_get_rate(gpt_clk);
+	tick_rate >>= CTRL_PRESCALER256;
+
+	writew(0xFFFF, gpt_base + LOAD(CLKSRC));
+
+	val = readw(gpt_base + CR(CLKSRC));
+	val &= ~CTRL_ONE_SHOT;	/* autoreload mode */
+	val |= CTRL_ENABLE ;
+	writew(val, gpt_base + CR(CLKSRC));
+
+	/* register the clocksource */
+	clocksource_mmio_init(gpt_base + COUNT(CLKSRC), "tmr1", tick_rate,
+		200, 16, clocksource_mmio_readw_up);
+}
+
+static struct clock_event_device clkevt = {
+	.name = "tmr0",
+	.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+	.set_mode = clockevent_set_mode,
+	.set_next_event = clockevent_next_event,
+	.shift = 0,	/* to be computed */
+};
+
+static void clockevent_set_mode(enum clock_event_mode mode,
+				struct clock_event_device *clk_event_dev)
+{
+	u32 period;
+	u16 val;
+
+	/* stop the timer */
+	val = readw(gpt_base + CR(CLKEVT));
+	val &= ~CTRL_ENABLE;
+	writew(val, gpt_base + CR(CLKEVT));
+
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		period = clk_get_rate(gpt_clk) / HZ;
+		period >>= CTRL_PRESCALER16;
+		writew(period, gpt_base + LOAD(CLKEVT));
+
+		val = readw(gpt_base + CR(CLKEVT));
+		val &= ~CTRL_ONE_SHOT;
+		val |= CTRL_ENABLE | CTRL_INT_ENABLE;
+		writew(val, gpt_base + CR(CLKEVT));
+
+		break;
+	case CLOCK_EVT_MODE_ONESHOT:
+		val = readw(gpt_base + CR(CLKEVT));
+		val |= CTRL_ONE_SHOT;
+		writew(val, gpt_base + CR(CLKEVT));
+
+		break;
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_SHUTDOWN:
+	case CLOCK_EVT_MODE_RESUME:
+
+		break;
+	default:
+		pr_err("Invalid mode requested\n");
+		break;
+	}
+}
+
+static int clockevent_next_event(unsigned long cycles,
+				 struct clock_event_device *clk_event_dev)
+{
+	u16 val = readw(gpt_base + CR(CLKEVT));
+
+	if (val & CTRL_ENABLE)
+		writew(val & ~CTRL_ENABLE, gpt_base + CR(CLKEVT));
+
+	writew(cycles, gpt_base + LOAD(CLKEVT));
+
+	val |= CTRL_ENABLE | CTRL_INT_ENABLE;
+	writew(val, gpt_base + CR(CLKEVT));
+
+	return 0;
+}
+
+static irqreturn_t spear_timer_interrupt(int irq, void *dev_id)
+{
+	struct clock_event_device *evt = &clkevt;
+
+	writew(INT_STATUS, gpt_base + IR(CLKEVT));
+
+	evt->event_handler(evt);
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction spear_timer_irq = {
+	.name = "timer",
+	.flags = IRQF_DISABLED | IRQF_TIMER,
+	.handler = spear_timer_interrupt
+};
+
+static void __init spear_clockevent_init(int irq)
+{
+	u32 tick_rate;
+
+	/* program the prescaler */
+	writew(CTRL_PRESCALER16, gpt_base + CR(CLKEVT));
+
+	tick_rate = clk_get_rate(gpt_clk);
+	tick_rate >>= CTRL_PRESCALER16;
+
+	clkevt.cpumask = cpumask_of(0);
+
+	clockevents_config_and_register(&clkevt, tick_rate, 3, 0xfff0);
+
+	setup_irq(irq, &spear_timer_irq);
+}
+
+const static struct of_device_id timer_of_match[] __initconst = {
+	{ .compatible = "st,spear-timer", },
+	{ },
+};
+
+void __init spear_setup_of_timer(void)
+{
+	struct device_node *np;
+	int irq, ret;
+
+	np = of_find_matching_node(NULL, timer_of_match);
+	if (!np) {
+		pr_err("%s: No timer passed via DT\n", __func__);
+		return;
+	}
+
+	irq = irq_of_parse_and_map(np, 0);
+	if (!irq) {
+		pr_err("%s: No irq passed for timer via DT\n", __func__);
+		return;
+	}
+
+	gpt_base = of_iomap(np, 0);
+	if (!gpt_base) {
+		pr_err("%s: of iomap failed\n", __func__);
+		return;
+	}
+
+	gpt_clk = clk_get_sys("gpt0", NULL);
+	if (!gpt_clk) {
+		pr_err("%s:couldn't get clk for gpt\n", __func__);
+		goto err_iomap;
+	}
+
+	ret = clk_prepare_enable(gpt_clk);
+	if (ret < 0) {
+		pr_err("%s:couldn't prepare-enable gpt clock\n", __func__);
+		goto err_prepare_enable_clk;
+	}
+
+	spear_clockevent_init(irq);
+	spear_clocksource_init();
+
+	return;
+
+err_prepare_enable_clk:
+	clk_put(gpt_clk);
+err_iomap:
+	iounmap(gpt_base);
+}
diff --git a/arch/arm/mach-spear13xx/Kconfig b/arch/arm/mach-spear13xx/Kconfig
deleted file mode 100644
index eaadc66..0000000
--- a/arch/arm/mach-spear13xx/Kconfig
+++ /dev/null
@@ -1,20 +0,0 @@
-#
-# SPEAr13XX Machine configuration file
-#
-
-if ARCH_SPEAR13XX
-
-menu "SPEAr13xx Implementations"
-config MACH_SPEAR1310
-	bool "SPEAr1310 Machine support with Device Tree"
-	select PINCTRL_SPEAR1310
-	help
-	  Supports ST SPEAr1310 machine configured via the device-tree
-
-config MACH_SPEAR1340
-	bool "SPEAr1340 Machine support with Device Tree"
-	select PINCTRL_SPEAR1340
-	help
-	  Supports ST SPEAr1340 machine configured via the device-tree
-endmenu
-endif #ARCH_SPEAR13XX
diff --git a/arch/arm/mach-spear13xx/Makefile b/arch/arm/mach-spear13xx/Makefile
deleted file mode 100644
index 3435ea7..0000000
--- a/arch/arm/mach-spear13xx/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-#
-# Makefile for SPEAr13XX machine series
-#
-
-obj-$(CONFIG_SMP)		+= headsmp.o platsmp.o
-obj-$(CONFIG_HOTPLUG_CPU)	+= hotplug.o
-
-obj-$(CONFIG_ARCH_SPEAR13XX)	+= spear13xx.o
-obj-$(CONFIG_MACH_SPEAR1310)	+= spear1310.o
-obj-$(CONFIG_MACH_SPEAR1340)	+= spear1340.o
diff --git a/arch/arm/mach-spear13xx/Makefile.boot b/arch/arm/mach-spear13xx/Makefile.boot
deleted file mode 100644
index 4674a4c..0000000
--- a/arch/arm/mach-spear13xx/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-spear13xx/headsmp.S b/arch/arm/mach-spear13xx/headsmp.S
deleted file mode 100644
index ed85473..0000000
--- a/arch/arm/mach-spear13xx/headsmp.S
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * arch/arm/mach-spear13XX/headsmp.S
- *
- * Picked from realview
- * Copyright (c) 2012 ST Microelectronics Limited
- * Shiraz Hashim <shiraz.hashim@st.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/linkage.h>
-#include <linux/init.h>
-
-	__INIT
-
-/*
- * spear13xx specific entry point for secondary CPUs. This provides
- * a "holding pen" into which all secondary cores are held until we're
- * ready for them to initialise.
- */
-ENTRY(spear13xx_secondary_startup)
-	mrc	p15, 0, r0, c0, c0, 5
-	and	r0, r0, #15
-	adr	r4, 1f
-	ldmia	r4, {r5, r6}
-	sub	r4, r4, r5
-	add	r6, r6, r4
-pen:	ldr	r7, [r6]
-	cmp	r7, r0
-	bne	pen
-
-	/* re-enable coherency */
-	mrc	p15, 0, r0, c1, c0, 1
-	orr	r0, r0, #(1 << 6) | (1 << 0)
-	mcr	p15, 0, r0, c1, c0, 1
-	/*
-	 * we've been released from the holding pen: secondary_stack
-	 * should now contain the SVC stack for this core
-	 */
-	b	secondary_startup
-
-	.align
-1:	.long	.
-	.long	pen_release
-ENDPROC(spear13xx_secondary_startup)
diff --git a/arch/arm/mach-spear13xx/hotplug.c b/arch/arm/mach-spear13xx/hotplug.c
deleted file mode 100644
index a7d2dd1..0000000
--- a/arch/arm/mach-spear13xx/hotplug.c
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * linux/arch/arm/mach-spear13xx/hotplug.c
- *
- * Copyright (C) 2012 ST Microelectronics Ltd.
- * Deepak Sikri <deepak.sikri@st.com>
- *
- * based upon linux/arch/arm/mach-realview/hotplug.c
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/smp.h>
-#include <asm/cacheflush.h>
-#include <asm/cp15.h>
-#include <asm/smp_plat.h>
-
-static inline void cpu_enter_lowpower(void)
-{
-	unsigned int v;
-
-	flush_cache_all();
-	asm volatile(
-	"	mcr	p15, 0, %1, c7, c5, 0\n"
-	"	dsb\n"
-	/*
-	 * Turn off coherency
-	 */
-	"	mrc	p15, 0, %0, c1, c0, 1\n"
-	"	bic	%0, %0, #0x20\n"
-	"	mcr	p15, 0, %0, c1, c0, 1\n"
-	"	mrc	p15, 0, %0, c1, c0, 0\n"
-	"	bic	%0, %0, %2\n"
-	"	mcr	p15, 0, %0, c1, c0, 0\n"
-	: "=&r" (v)
-	: "r" (0), "Ir" (CR_C)
-	: "cc", "memory");
-}
-
-static inline void cpu_leave_lowpower(void)
-{
-	unsigned int v;
-
-	asm volatile("mrc	p15, 0, %0, c1, c0, 0\n"
-	"	orr	%0, %0, %1\n"
-	"	mcr	p15, 0, %0, c1, c0, 0\n"
-	"	mrc	p15, 0, %0, c1, c0, 1\n"
-	"	orr	%0, %0, #0x20\n"
-	"	mcr	p15, 0, %0, c1, c0, 1\n"
-	: "=&r" (v)
-	: "Ir" (CR_C)
-	: "cc");
-}
-
-static inline void spear13xx_do_lowpower(unsigned int cpu, int *spurious)
-{
-	for (;;) {
-		wfi();
-
-		if (pen_release == cpu) {
-			/*
-			 * OK, proper wakeup, we're done
-			 */
-			break;
-		}
-
-		/*
-		 * Getting here, means that we have come out of WFI without
-		 * having been woken up - this shouldn't happen
-		 *
-		 * Just note it happening - when we're woken, we can report
-		 * its occurrence.
-		 */
-		(*spurious)++;
-	}
-}
-
-/*
- * platform-specific code to shutdown a CPU
- *
- * Called with IRQs disabled
- */
-void __ref spear13xx_cpu_die(unsigned int cpu)
-{
-	int spurious = 0;
-
-	/*
-	 * we're ready for shutdown now, so do it
-	 */
-	cpu_enter_lowpower();
-	spear13xx_do_lowpower(cpu, &spurious);
-
-	/*
-	 * bring this CPU back into the world of cache
-	 * coherency, and then restore interrupts
-	 */
-	cpu_leave_lowpower();
-
-	if (spurious)
-		pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
-}
diff --git a/arch/arm/mach-spear13xx/include/mach/debug-macro.S b/arch/arm/mach-spear13xx/include/mach/debug-macro.S
deleted file mode 100644
index 9e3ae6b..0000000
--- a/arch/arm/mach-spear13xx/include/mach/debug-macro.S
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * arch/arm/mach-spear13xx/include/mach/debug-macro.S
- *
- * Debugging macro include header spear13xx machine family
- *
- * Copyright (C) 2012 ST Microelectronics
- * Viresh Kumar <viresh.linux@gmail.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 <plat/debug-macro.S>
diff --git a/arch/arm/mach-spear13xx/include/mach/dma.h b/arch/arm/mach-spear13xx/include/mach/dma.h
deleted file mode 100644
index d50bdb6..0000000
--- a/arch/arm/mach-spear13xx/include/mach/dma.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * arch/arm/mach-spear13xx/include/mach/dma.h
- *
- * DMA information for SPEAr13xx machine family
- *
- * Copyright (C) 2012 ST Microelectronics
- * Viresh Kumar <viresh.linux@gmail.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_DMA_H
-#define __MACH_DMA_H
-
-/* request id of all the peripherals */
-enum dma_master_info {
-	/* Accessible from only one master */
-	DMA_MASTER_MCIF = 0,
-	DMA_MASTER_FSMC = 1,
-	/* Accessible from both 0 & 1 */
-	DMA_MASTER_MEMORY = 0,
-	DMA_MASTER_ADC = 0,
-	DMA_MASTER_UART0 = 0,
-	DMA_MASTER_SSP0 = 0,
-	DMA_MASTER_I2C0 = 0,
-
-#ifdef CONFIG_MACH_SPEAR1310
-	/* Accessible from only one master */
-	SPEAR1310_DMA_MASTER_JPEG = 1,
-
-	/* Accessible from both 0 & 1 */
-	SPEAR1310_DMA_MASTER_I2S = 0,
-	SPEAR1310_DMA_MASTER_UART1 = 0,
-	SPEAR1310_DMA_MASTER_UART2 = 0,
-	SPEAR1310_DMA_MASTER_UART3 = 0,
-	SPEAR1310_DMA_MASTER_UART4 = 0,
-	SPEAR1310_DMA_MASTER_UART5 = 0,
-	SPEAR1310_DMA_MASTER_I2C1 = 0,
-	SPEAR1310_DMA_MASTER_I2C2 = 0,
-	SPEAR1310_DMA_MASTER_I2C3 = 0,
-	SPEAR1310_DMA_MASTER_I2C4 = 0,
-	SPEAR1310_DMA_MASTER_I2C5 = 0,
-	SPEAR1310_DMA_MASTER_I2C6 = 0,
-	SPEAR1310_DMA_MASTER_I2C7 = 0,
-	SPEAR1310_DMA_MASTER_SSP1 = 0,
-#endif
-
-#ifdef CONFIG_MACH_SPEAR1340
-	/* Accessible from only one master */
-	SPEAR1340_DMA_MASTER_I2S_PLAY = 1,
-	SPEAR1340_DMA_MASTER_I2S_REC = 1,
-	SPEAR1340_DMA_MASTER_I2C1 = 1,
-	SPEAR1340_DMA_MASTER_UART1 = 1,
-
-	/* following are accessible from both master 0 & 1 */
-	SPEAR1340_DMA_MASTER_SPDIF = 0,
-	SPEAR1340_DMA_MASTER_CAM = 1,
-	SPEAR1340_DMA_MASTER_VIDEO_IN = 0,
-	SPEAR1340_DMA_MASTER_MALI = 0,
-#endif
-};
-
-enum request_id {
-	DMA_REQ_ADC = 0,
-	DMA_REQ_SSP0_TX = 4,
-	DMA_REQ_SSP0_RX = 5,
-	DMA_REQ_UART0_TX = 6,
-	DMA_REQ_UART0_RX = 7,
-	DMA_REQ_I2C0_TX = 8,
-	DMA_REQ_I2C0_RX = 9,
-
-#ifdef CONFIG_MACH_SPEAR1310
-	SPEAR1310_DMA_REQ_FROM_JPEG = 2,
-	SPEAR1310_DMA_REQ_TO_JPEG = 3,
-	SPEAR1310_DMA_REQ_I2S_TX = 10,
-	SPEAR1310_DMA_REQ_I2S_RX = 11,
-
-	SPEAR1310_DMA_REQ_I2C1_RX = 0,
-	SPEAR1310_DMA_REQ_I2C1_TX = 1,
-	SPEAR1310_DMA_REQ_I2C2_RX = 2,
-	SPEAR1310_DMA_REQ_I2C2_TX = 3,
-	SPEAR1310_DMA_REQ_I2C3_RX = 4,
-	SPEAR1310_DMA_REQ_I2C3_TX = 5,
-	SPEAR1310_DMA_REQ_I2C4_RX = 6,
-	SPEAR1310_DMA_REQ_I2C4_TX = 7,
-	SPEAR1310_DMA_REQ_I2C5_RX = 8,
-	SPEAR1310_DMA_REQ_I2C5_TX = 9,
-	SPEAR1310_DMA_REQ_I2C6_RX = 10,
-	SPEAR1310_DMA_REQ_I2C6_TX = 11,
-	SPEAR1310_DMA_REQ_UART1_RX = 12,
-	SPEAR1310_DMA_REQ_UART1_TX = 13,
-	SPEAR1310_DMA_REQ_UART2_RX = 14,
-	SPEAR1310_DMA_REQ_UART2_TX = 15,
-	SPEAR1310_DMA_REQ_UART5_RX = 16,
-	SPEAR1310_DMA_REQ_UART5_TX = 17,
-	SPEAR1310_DMA_REQ_SSP1_RX = 18,
-	SPEAR1310_DMA_REQ_SSP1_TX = 19,
-	SPEAR1310_DMA_REQ_I2C7_RX = 20,
-	SPEAR1310_DMA_REQ_I2C7_TX = 21,
-	SPEAR1310_DMA_REQ_UART3_RX = 28,
-	SPEAR1310_DMA_REQ_UART3_TX = 29,
-	SPEAR1310_DMA_REQ_UART4_RX = 30,
-	SPEAR1310_DMA_REQ_UART4_TX = 31,
-#endif
-
-#ifdef CONFIG_MACH_SPEAR1340
-	SPEAR1340_DMA_REQ_SPDIF_TX = 2,
-	SPEAR1340_DMA_REQ_SPDIF_RX = 3,
-	SPEAR1340_DMA_REQ_I2S_TX = 10,
-	SPEAR1340_DMA_REQ_I2S_RX = 11,
-	SPEAR1340_DMA_REQ_UART1_TX = 12,
-	SPEAR1340_DMA_REQ_UART1_RX = 13,
-	SPEAR1340_DMA_REQ_I2C1_TX = 14,
-	SPEAR1340_DMA_REQ_I2C1_RX = 15,
-	SPEAR1340_DMA_REQ_CAM0_EVEN = 0,
-	SPEAR1340_DMA_REQ_CAM0_ODD = 1,
-	SPEAR1340_DMA_REQ_CAM1_EVEN = 2,
-	SPEAR1340_DMA_REQ_CAM1_ODD = 3,
-	SPEAR1340_DMA_REQ_CAM2_EVEN = 4,
-	SPEAR1340_DMA_REQ_CAM2_ODD = 5,
-	SPEAR1340_DMA_REQ_CAM3_EVEN = 6,
-	SPEAR1340_DMA_REQ_CAM3_ODD = 7,
-#endif
-};
-
-#endif /* __MACH_DMA_H */
diff --git a/arch/arm/mach-spear13xx/include/mach/generic.h b/arch/arm/mach-spear13xx/include/mach/generic.h
deleted file mode 100644
index 633e678..0000000
--- a/arch/arm/mach-spear13xx/include/mach/generic.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * arch/arm/mach-spear13xx/include/mach/generic.h
- *
- * spear13xx machine family generic header file
- *
- * Copyright (C) 2012 ST Microelectronics
- * Viresh Kumar <viresh.linux@gmail.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_GENERIC_H
-#define __MACH_GENERIC_H
-
-#include <linux/dmaengine.h>
-#include <asm/mach/time.h>
-
-/* Add spear13xx structure declarations here */
-extern void spear13xx_timer_init(void);
-extern struct pl022_ssp_controller pl022_plat_data;
-extern struct dw_dma_platform_data dmac_plat_data;
-extern struct dw_dma_slave cf_dma_priv;
-extern struct dw_dma_slave nand_read_dma_priv;
-extern struct dw_dma_slave nand_write_dma_priv;
-
-/* Add spear13xx family function declarations here */
-void __init spear_setup_of_timer(void);
-void __init spear13xx_map_io(void);
-void __init spear13xx_l2x0_init(void);
-bool dw_dma_filter(struct dma_chan *chan, void *slave);
-void spear_restart(char, const char *);
-void spear13xx_secondary_startup(void);
-void __cpuinit spear13xx_cpu_die(unsigned int cpu);
-
-extern struct smp_operations spear13xx_smp_ops;
-
-#ifdef CONFIG_MACH_SPEAR1310
-void __init spear1310_clk_init(void);
-#else
-static inline void spear1310_clk_init(void) {}
-#endif
-
-#ifdef CONFIG_MACH_SPEAR1340
-void __init spear1340_clk_init(void);
-#else
-static inline void spear1340_clk_init(void) {}
-#endif
-
-#endif /* __MACH_GENERIC_H */
diff --git a/arch/arm/mach-spear13xx/include/mach/hardware.h b/arch/arm/mach-spear13xx/include/mach/hardware.h
deleted file mode 100644
index 40a8c17..0000000
--- a/arch/arm/mach-spear13xx/include/mach/hardware.h
+++ /dev/null
@@ -1 +0,0 @@
-/* empty */
diff --git a/arch/arm/mach-spear13xx/include/mach/irqs.h b/arch/arm/mach-spear13xx/include/mach/irqs.h
deleted file mode 100644
index 271a62b..0000000
--- a/arch/arm/mach-spear13xx/include/mach/irqs.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * arch/arm/mach-spear13xx/include/mach/irqs.h
- *
- * IRQ helper macros for spear13xx machine family
- *
- * Copyright (C) 2012 ST Microelectronics
- * Viresh Kumar <viresh.linux@gmail.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_IRQS_H
-#define __MACH_IRQS_H
-
-#define IRQ_GIC_END			160
-#define NR_IRQS				IRQ_GIC_END
-
-#endif /* __MACH_IRQS_H */
diff --git a/arch/arm/mach-spear13xx/include/mach/spear.h b/arch/arm/mach-spear13xx/include/mach/spear.h
deleted file mode 100644
index 7cfa681..0000000
--- a/arch/arm/mach-spear13xx/include/mach/spear.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * arch/arm/mach-spear13xx/include/mach/spear.h
- *
- * spear13xx Machine family specific definition
- *
- * Copyright (C) 2012 ST Microelectronics
- * Viresh Kumar <viresh.linux@gmail.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_SPEAR13XX_H
-#define __MACH_SPEAR13XX_H
-
-#include <asm/memory.h>
-
-#define PERIP_GRP2_BASE				UL(0xB3000000)
-#define VA_PERIP_GRP2_BASE			IOMEM(0xFE000000)
-#define MCIF_SDHCI_BASE				UL(0xB3000000)
-#define SYSRAM0_BASE				UL(0xB3800000)
-#define VA_SYSRAM0_BASE				IOMEM(0xFE800000)
-#define SYS_LOCATION				(VA_SYSRAM0_BASE + 0x600)
-
-#define PERIP_GRP1_BASE				UL(0xE0000000)
-#define VA_PERIP_GRP1_BASE			IOMEM(0xFD000000)
-#define UART_BASE				UL(0xE0000000)
-#define VA_UART_BASE				IOMEM(0xFD000000)
-#define SSP_BASE				UL(0xE0100000)
-#define MISC_BASE				UL(0xE0700000)
-#define VA_MISC_BASE				IOMEM(0xFD700000)
-
-#define A9SM_AND_MPMC_BASE			UL(0xEC000000)
-#define VA_A9SM_AND_MPMC_BASE			IOMEM(0xFC000000)
-
-/* A9SM peripheral offsets */
-#define A9SM_PERIP_BASE				UL(0xEC800000)
-#define VA_A9SM_PERIP_BASE			IOMEM(0xFC800000)
-#define VA_SCU_BASE				(VA_A9SM_PERIP_BASE + 0x00)
-
-#define L2CC_BASE				UL(0xED000000)
-#define VA_L2CC_BASE				IOMEM(UL(0xFB000000))
-
-/* others */
-#define DMAC0_BASE				UL(0xEA800000)
-#define DMAC1_BASE				UL(0xEB000000)
-#define MCIF_CF_BASE				UL(0xB2800000)
-
-/* Debug uart for linux, will be used for debug and uncompress messages */
-#define SPEAR_DBG_UART_BASE			UART_BASE
-#define VA_SPEAR_DBG_UART_BASE			VA_UART_BASE
-
-#endif /* __MACH_SPEAR13XX_H */
diff --git a/arch/arm/mach-spear13xx/include/mach/timex.h b/arch/arm/mach-spear13xx/include/mach/timex.h
deleted file mode 100644
index 3a58b82..0000000
--- a/arch/arm/mach-spear13xx/include/mach/timex.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * arch/arm/mach-spear3xx/include/mach/timex.h
- *
- * SPEAr3XX machine family specific timex definitions
- *
- * Copyright (C) 2012 ST Microelectronics
- * Viresh Kumar <viresh.linux@gmail.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_TIMEX_H
-#define __MACH_TIMEX_H
-
-#include <plat/timex.h>
-
-#endif /* __MACH_TIMEX_H */
diff --git a/arch/arm/mach-spear13xx/include/mach/uncompress.h b/arch/arm/mach-spear13xx/include/mach/uncompress.h
deleted file mode 100644
index 70fe72f..0000000
--- a/arch/arm/mach-spear13xx/include/mach/uncompress.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * arch/arm/mach-spear13xx/include/mach/uncompress.h
- *
- * Serial port stubs for kernel decompress status messages
- *
- * Copyright (C) 2012 ST Microelectronics
- * Viresh Kumar <viresh.linux@gmail.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_UNCOMPRESS_H
-#define __MACH_UNCOMPRESS_H
-
-#include <plat/uncompress.h>
-
-#endif /* __MACH_UNCOMPRESS_H */
diff --git a/arch/arm/mach-spear13xx/platsmp.c b/arch/arm/mach-spear13xx/platsmp.c
deleted file mode 100644
index af4ade6..0000000
--- a/arch/arm/mach-spear13xx/platsmp.c
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * arch/arm/mach-spear13xx/platsmp.c
- *
- * based upon linux/arch/arm/mach-realview/platsmp.c
- *
- * Copyright (C) 2012 ST Microelectronics Ltd.
- * Shiraz Hashim <shiraz.hashim@st.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/delay.h>
-#include <linux/jiffies.h>
-#include <linux/io.h>
-#include <linux/smp.h>
-#include <linux/irqchip/arm-gic.h>
-#include <asm/cacheflush.h>
-#include <asm/smp_scu.h>
-#include <mach/spear.h>
-#include <mach/generic.h>
-
-static DEFINE_SPINLOCK(boot_lock);
-
-static void __iomem *scu_base = IOMEM(VA_SCU_BASE);
-
-static void __cpuinit spear13xx_secondary_init(unsigned int cpu)
-{
-	/*
-	 * if any interrupts are already enabled for the primary
-	 * core (e.g. timer irq), then they will not have been enabled
-	 * for us: do so
-	 */
-	gic_secondary_init(0);
-
-	/*
-	 * let the primary processor know we're out of the
-	 * pen, then head off into the C entry point
-	 */
-	pen_release = -1;
-	smp_wmb();
-
-	/*
-	 * Synchronise with the boot thread.
-	 */
-	spin_lock(&boot_lock);
-	spin_unlock(&boot_lock);
-}
-
-static int __cpuinit spear13xx_boot_secondary(unsigned int cpu, struct task_struct *idle)
-{
-	unsigned long timeout;
-
-	/*
-	 * set synchronisation state between this boot processor
-	 * and the secondary one
-	 */
-	spin_lock(&boot_lock);
-
-	/*
-	 * The secondary processor is waiting to be released from
-	 * the holding pen - release it, then wait for it to flag
-	 * that it has been released by resetting pen_release.
-	 *
-	 * Note that "pen_release" is the hardware CPU ID, whereas
-	 * "cpu" is Linux's internal ID.
-	 */
-	pen_release = cpu;
-	flush_cache_all();
-	outer_flush_all();
-
-	timeout = jiffies + (1 * HZ);
-	while (time_before(jiffies, timeout)) {
-		smp_rmb();
-		if (pen_release == -1)
-			break;
-
-		udelay(10);
-	}
-
-	/*
-	 * now the secondary core is starting up let it run its
-	 * calibrations, then wait for it to finish
-	 */
-	spin_unlock(&boot_lock);
-
-	return pen_release != -1 ? -ENOSYS : 0;
-}
-
-/*
- * Initialise the CPU possible map early - this describes the CPUs
- * which may be present or become present in the system.
- */
-static void __init spear13xx_smp_init_cpus(void)
-{
-	unsigned int i, ncores = scu_get_core_count(scu_base);
-
-	if (ncores > nr_cpu_ids) {
-		pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
-			ncores, nr_cpu_ids);
-		ncores = nr_cpu_ids;
-	}
-
-	for (i = 0; i < ncores; i++)
-		set_cpu_possible(i, true);
-}
-
-static void __init spear13xx_smp_prepare_cpus(unsigned int max_cpus)
-{
-
-	scu_enable(scu_base);
-
-	/*
-	 * Write the address of secondary startup into the system-wide location
-	 * (presently it is in SRAM). The BootMonitor waits until it receives a
-	 * soft interrupt, and then the secondary CPU branches to this address.
-	 */
-	__raw_writel(virt_to_phys(spear13xx_secondary_startup), SYS_LOCATION);
-}
-
-struct smp_operations spear13xx_smp_ops __initdata = {
-       .smp_init_cpus		= spear13xx_smp_init_cpus,
-       .smp_prepare_cpus	= spear13xx_smp_prepare_cpus,
-       .smp_secondary_init	= spear13xx_secondary_init,
-       .smp_boot_secondary	= spear13xx_boot_secondary,
-#ifdef CONFIG_HOTPLUG_CPU
-       .cpu_die			= spear13xx_cpu_die,
-#endif
-};
diff --git a/arch/arm/mach-spear13xx/spear1310.c b/arch/arm/mach-spear13xx/spear1310.c
deleted file mode 100644
index 56214d1..0000000
--- a/arch/arm/mach-spear13xx/spear1310.c
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * arch/arm/mach-spear13xx/spear1310.c
- *
- * SPEAr1310 machine source file
- *
- * Copyright (C) 2012 ST Microelectronics
- * Viresh Kumar <viresh.linux@gmail.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.
- */
-
-#define pr_fmt(fmt) "SPEAr1310: " fmt
-
-#include <linux/amba/pl022.h>
-#include <linux/irqchip.h>
-#include <linux/of_platform.h>
-#include <linux/pata_arasan_cf_data.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <mach/generic.h>
-#include <mach/spear.h>
-
-/* Base addresses */
-#define SPEAR1310_SSP1_BASE			UL(0x5D400000)
-#define SPEAR1310_SATA0_BASE			UL(0xB1000000)
-#define SPEAR1310_SATA1_BASE			UL(0xB1800000)
-#define SPEAR1310_SATA2_BASE			UL(0xB4000000)
-
-#define SPEAR1310_RAS_GRP1_BASE			UL(0xD8000000)
-#define VA_SPEAR1310_RAS_GRP1_BASE		UL(0xFA000000)
-#define SPEAR1310_RAS_BASE			UL(0xD8400000)
-#define VA_SPEAR1310_RAS_BASE			IOMEM(UL(0xFA400000))
-
-static struct arasan_cf_pdata cf_pdata = {
-	.cf_if_clk = CF_IF_CLK_166M,
-	.quirk = CF_BROKEN_UDMA,
-	.dma_priv = &cf_dma_priv,
-};
-
-/* ssp device registration */
-static struct pl022_ssp_controller ssp1_plat_data = {
-	.enable_dma = 0,
-};
-
-/* Add SPEAr1310 auxdata to pass platform data */
-static struct of_dev_auxdata spear1310_auxdata_lookup[] __initdata = {
-	OF_DEV_AUXDATA("arasan,cf-spear1340", MCIF_CF_BASE, NULL, &cf_pdata),
-	OF_DEV_AUXDATA("snps,dma-spear1340", DMAC0_BASE, NULL, &dmac_plat_data),
-	OF_DEV_AUXDATA("snps,dma-spear1340", DMAC1_BASE, NULL, &dmac_plat_data),
-	OF_DEV_AUXDATA("arm,pl022", SSP_BASE, NULL, &pl022_plat_data),
-
-	OF_DEV_AUXDATA("arm,pl022", SPEAR1310_SSP1_BASE, NULL, &ssp1_plat_data),
-	{}
-};
-
-static void __init spear1310_dt_init(void)
-{
-	of_platform_populate(NULL, of_default_bus_match_table,
-			spear1310_auxdata_lookup, NULL);
-}
-
-static const char * const spear1310_dt_board_compat[] = {
-	"st,spear1310",
-	"st,spear1310-evb",
-	NULL,
-};
-
-/*
- * Following will create 16MB static virtual/physical mappings
- * PHYSICAL		VIRTUAL
- * 0xD8000000		0xFA000000
- */
-struct map_desc spear1310_io_desc[] __initdata = {
-	{
-		.virtual	= VA_SPEAR1310_RAS_GRP1_BASE,
-		.pfn		= __phys_to_pfn(SPEAR1310_RAS_GRP1_BASE),
-		.length		= SZ_16M,
-		.type		= MT_DEVICE
-	},
-};
-
-static void __init spear1310_map_io(void)
-{
-	iotable_init(spear1310_io_desc, ARRAY_SIZE(spear1310_io_desc));
-	spear13xx_map_io();
-}
-
-DT_MACHINE_START(SPEAR1310_DT, "ST SPEAr1310 SoC with Flattened Device Tree")
-	.smp		=	smp_ops(spear13xx_smp_ops),
-	.map_io		=	spear1310_map_io,
-	.init_irq	=	irqchip_init,
-	.init_time	=	spear13xx_timer_init,
-	.init_machine	=	spear1310_dt_init,
-	.restart	=	spear_restart,
-	.dt_compat	=	spear1310_dt_board_compat,
-MACHINE_END
diff --git a/arch/arm/mach-spear13xx/spear1340.c b/arch/arm/mach-spear13xx/spear1340.c
deleted file mode 100644
index 9a28beb..0000000
--- a/arch/arm/mach-spear13xx/spear1340.c
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * arch/arm/mach-spear13xx/spear1340.c
- *
- * SPEAr1340 machine source file
- *
- * Copyright (C) 2012 ST Microelectronics
- * Viresh Kumar <viresh.linux@gmail.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.
- */
-
-#define pr_fmt(fmt) "SPEAr1340: " fmt
-
-#include <linux/ahci_platform.h>
-#include <linux/amba/serial.h>
-#include <linux/delay.h>
-#include <linux/dw_dmac.h>
-#include <linux/of_platform.h>
-#include <linux/irqchip.h>
-#include <asm/mach/arch.h>
-#include <mach/dma.h>
-#include <mach/generic.h>
-#include <mach/spear.h>
-
-/* Base addresses */
-#define SPEAR1340_SATA_BASE			UL(0xB1000000)
-#define SPEAR1340_UART1_BASE			UL(0xB4100000)
-
-/* Power Management Registers */
-#define SPEAR1340_PCM_CFG			(VA_MISC_BASE + 0x100)
-#define SPEAR1340_PCM_WKUP_CFG			(VA_MISC_BASE + 0x104)
-#define SPEAR1340_SWITCH_CTR			(VA_MISC_BASE + 0x108)
-
-#define SPEAR1340_PERIP1_SW_RST			(VA_MISC_BASE + 0x318)
-#define SPEAR1340_PERIP2_SW_RST			(VA_MISC_BASE + 0x31C)
-#define SPEAR1340_PERIP3_SW_RST			(VA_MISC_BASE + 0x320)
-
-/* PCIE - SATA configuration registers */
-#define SPEAR1340_PCIE_SATA_CFG			(VA_MISC_BASE + 0x424)
-	/* PCIE CFG MASks */
-	#define SPEAR1340_PCIE_CFG_DEVICE_PRESENT	(1 << 11)
-	#define SPEAR1340_PCIE_CFG_POWERUP_RESET	(1 << 10)
-	#define SPEAR1340_PCIE_CFG_CORE_CLK_EN		(1 << 9)
-	#define SPEAR1340_PCIE_CFG_AUX_CLK_EN		(1 << 8)
-	#define SPEAR1340_SATA_CFG_TX_CLK_EN		(1 << 4)
-	#define SPEAR1340_SATA_CFG_RX_CLK_EN		(1 << 3)
-	#define SPEAR1340_SATA_CFG_POWERUP_RESET	(1 << 2)
-	#define SPEAR1340_SATA_CFG_PM_CLK_EN		(1 << 1)
-	#define SPEAR1340_PCIE_SATA_SEL_PCIE		(0)
-	#define SPEAR1340_PCIE_SATA_SEL_SATA		(1)
-	#define SPEAR1340_SATA_PCIE_CFG_MASK		0xF1F
-	#define SPEAR1340_PCIE_CFG_VAL	(SPEAR1340_PCIE_SATA_SEL_PCIE | \
-			SPEAR1340_PCIE_CFG_AUX_CLK_EN | \
-			SPEAR1340_PCIE_CFG_CORE_CLK_EN | \
-			SPEAR1340_PCIE_CFG_POWERUP_RESET | \
-			SPEAR1340_PCIE_CFG_DEVICE_PRESENT)
-	#define SPEAR1340_SATA_CFG_VAL	(SPEAR1340_PCIE_SATA_SEL_SATA | \
-			SPEAR1340_SATA_CFG_PM_CLK_EN | \
-			SPEAR1340_SATA_CFG_POWERUP_RESET | \
-			SPEAR1340_SATA_CFG_RX_CLK_EN | \
-			SPEAR1340_SATA_CFG_TX_CLK_EN)
-
-#define SPEAR1340_PCIE_MIPHY_CFG		(VA_MISC_BASE + 0x428)
-	#define SPEAR1340_MIPHY_OSC_BYPASS_EXT		(1 << 31)
-	#define SPEAR1340_MIPHY_CLK_REF_DIV2		(1 << 27)
-	#define SPEAR1340_MIPHY_CLK_REF_DIV4		(2 << 27)
-	#define SPEAR1340_MIPHY_CLK_REF_DIV8		(3 << 27)
-	#define SPEAR1340_MIPHY_PLL_RATIO_TOP(x)	(x << 0)
-	#define SPEAR1340_PCIE_SATA_MIPHY_CFG_SATA \
-			(SPEAR1340_MIPHY_OSC_BYPASS_EXT | \
-			SPEAR1340_MIPHY_CLK_REF_DIV2 | \
-			SPEAR1340_MIPHY_PLL_RATIO_TOP(60))
-	#define SPEAR1340_PCIE_SATA_MIPHY_CFG_SATA_25M_CRYSTAL_CLK \
-			(SPEAR1340_MIPHY_PLL_RATIO_TOP(120))
-	#define SPEAR1340_PCIE_SATA_MIPHY_CFG_PCIE \
-			(SPEAR1340_MIPHY_OSC_BYPASS_EXT | \
-			SPEAR1340_MIPHY_PLL_RATIO_TOP(25))
-
-static struct dw_dma_slave uart1_dma_param[] = {
-	{
-		/* Tx */
-		.cfg_hi = DWC_CFGH_DST_PER(SPEAR1340_DMA_REQ_UART1_TX),
-		.cfg_lo = 0,
-		.src_master = DMA_MASTER_MEMORY,
-		.dst_master = SPEAR1340_DMA_MASTER_UART1,
-	}, {
-		/* Rx */
-		.cfg_hi = DWC_CFGH_SRC_PER(SPEAR1340_DMA_REQ_UART1_RX),
-		.cfg_lo = 0,
-		.src_master = SPEAR1340_DMA_MASTER_UART1,
-		.dst_master = DMA_MASTER_MEMORY,
-	}
-};
-
-static struct amba_pl011_data uart1_data = {
-	.dma_filter = dw_dma_filter,
-	.dma_tx_param = &uart1_dma_param[0],
-	.dma_rx_param = &uart1_dma_param[1],
-};
-
-/* SATA device registration */
-static int sata_miphy_init(struct device *dev, void __iomem *addr)
-{
-	writel(SPEAR1340_SATA_CFG_VAL, SPEAR1340_PCIE_SATA_CFG);
-	writel(SPEAR1340_PCIE_SATA_MIPHY_CFG_SATA_25M_CRYSTAL_CLK,
-			SPEAR1340_PCIE_MIPHY_CFG);
-	/* Switch on sata power domain */
-	writel((readl(SPEAR1340_PCM_CFG) | (0x800)), SPEAR1340_PCM_CFG);
-	msleep(20);
-	/* Disable PCIE SATA Controller reset */
-	writel((readl(SPEAR1340_PERIP1_SW_RST) & (~0x1000)),
-			SPEAR1340_PERIP1_SW_RST);
-	msleep(20);
-
-	return 0;
-}
-
-void sata_miphy_exit(struct device *dev)
-{
-	writel(0, SPEAR1340_PCIE_SATA_CFG);
-	writel(0, SPEAR1340_PCIE_MIPHY_CFG);
-
-	/* Enable PCIE SATA Controller reset */
-	writel((readl(SPEAR1340_PERIP1_SW_RST) | (0x1000)),
-			SPEAR1340_PERIP1_SW_RST);
-	msleep(20);
-	/* Switch off sata power domain */
-	writel((readl(SPEAR1340_PCM_CFG) & (~0x800)), SPEAR1340_PCM_CFG);
-	msleep(20);
-}
-
-int sata_suspend(struct device *dev)
-{
-	if (dev->power.power_state.event == PM_EVENT_FREEZE)
-		return 0;
-
-	sata_miphy_exit(dev);
-
-	return 0;
-}
-
-int sata_resume(struct device *dev)
-{
-	if (dev->power.power_state.event == PM_EVENT_THAW)
-		return 0;
-
-	return sata_miphy_init(dev, NULL);
-}
-
-static struct ahci_platform_data sata_pdata = {
-	.init = sata_miphy_init,
-	.exit = sata_miphy_exit,
-	.suspend = sata_suspend,
-	.resume = sata_resume,
-};
-
-/* Add SPEAr1340 auxdata to pass platform data */
-static struct of_dev_auxdata spear1340_auxdata_lookup[] __initdata = {
-	OF_DEV_AUXDATA("arasan,cf-spear1340", MCIF_CF_BASE, NULL, &cf_dma_priv),
-	OF_DEV_AUXDATA("snps,dma-spear1340", DMAC0_BASE, NULL, &dmac_plat_data),
-	OF_DEV_AUXDATA("snps,dma-spear1340", DMAC1_BASE, NULL, &dmac_plat_data),
-	OF_DEV_AUXDATA("arm,pl022", SSP_BASE, NULL, &pl022_plat_data),
-
-	OF_DEV_AUXDATA("snps,spear-ahci", SPEAR1340_SATA_BASE, NULL,
-			&sata_pdata),
-	OF_DEV_AUXDATA("arm,pl011", SPEAR1340_UART1_BASE, NULL, &uart1_data),
-	{}
-};
-
-static void __init spear1340_dt_init(void)
-{
-	of_platform_populate(NULL, of_default_bus_match_table,
-			spear1340_auxdata_lookup, NULL);
-}
-
-static const char * const spear1340_dt_board_compat[] = {
-	"st,spear1340",
-	"st,spear1340-evb",
-	NULL,
-};
-
-DT_MACHINE_START(SPEAR1340_DT, "ST SPEAr1340 SoC with Flattened Device Tree")
-	.smp		=	smp_ops(spear13xx_smp_ops),
-	.map_io		=	spear13xx_map_io,
-	.init_irq	=	irqchip_init,
-	.init_time	=	spear13xx_timer_init,
-	.init_machine	=	spear1340_dt_init,
-	.restart	=	spear_restart,
-	.dt_compat	=	spear1340_dt_board_compat,
-MACHINE_END
diff --git a/arch/arm/mach-spear13xx/spear13xx.c b/arch/arm/mach-spear13xx/spear13xx.c
deleted file mode 100644
index c7d2b4a..0000000
--- a/arch/arm/mach-spear13xx/spear13xx.c
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * arch/arm/mach-spear13xx/spear13xx.c
- *
- * SPEAr13XX machines common source file
- *
- * Copyright (C) 2012 ST Microelectronics
- * Viresh Kumar <viresh.linux@gmail.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.
- */
-
-#define pr_fmt(fmt) "SPEAr13xx: " fmt
-
-#include <linux/amba/pl022.h>
-#include <linux/clk.h>
-#include <linux/dw_dmac.h>
-#include <linux/err.h>
-#include <linux/of.h>
-#include <asm/hardware/cache-l2x0.h>
-#include <asm/mach/map.h>
-#include <asm/smp_twd.h>
-#include <mach/dma.h>
-#include <mach/generic.h>
-#include <mach/spear.h>
-
-/* common dw_dma filter routine to be used by peripherals */
-bool dw_dma_filter(struct dma_chan *chan, void *slave)
-{
-	struct dw_dma_slave *dws = (struct dw_dma_slave *)slave;
-
-	if (chan->device->dev == dws->dma_dev) {
-		chan->private = slave;
-		return true;
-	} else {
-		return false;
-	}
-}
-
-/* ssp device registration */
-static struct dw_dma_slave ssp_dma_param[] = {
-	{
-		/* Tx */
-		.cfg_hi = DWC_CFGH_DST_PER(DMA_REQ_SSP0_TX),
-		.cfg_lo = 0,
-		.src_master = DMA_MASTER_MEMORY,
-		.dst_master = DMA_MASTER_SSP0,
-	}, {
-		/* Rx */
-		.cfg_hi = DWC_CFGH_SRC_PER(DMA_REQ_SSP0_RX),
-		.cfg_lo = 0,
-		.src_master = DMA_MASTER_SSP0,
-		.dst_master = DMA_MASTER_MEMORY,
-	}
-};
-
-struct pl022_ssp_controller pl022_plat_data = {
-	.enable_dma = 1,
-	.dma_filter = dw_dma_filter,
-	.dma_rx_param = &ssp_dma_param[1],
-	.dma_tx_param = &ssp_dma_param[0],
-};
-
-/* CF device registration */
-struct dw_dma_slave cf_dma_priv = {
-	.cfg_hi = 0,
-	.cfg_lo = 0,
-	.src_master = 0,
-	.dst_master = 0,
-};
-
-/* dmac device registeration */
-struct dw_dma_platform_data dmac_plat_data = {
-	.nr_channels = 8,
-	.chan_allocation_order = CHAN_ALLOCATION_DESCENDING,
-	.chan_priority = CHAN_PRIORITY_DESCENDING,
-	.block_size = 4095U,
-	.nr_masters = 2,
-	.data_width = { 3, 3, 0, 0 },
-};
-
-void __init spear13xx_l2x0_init(void)
-{
-	/*
-	 * 512KB (64KB/way), 8-way associativity, parity supported
-	 *
-	 * FIXME: 9th bit, of Auxillary Controller register must be set
-	 * for some spear13xx devices for stable L2 operation.
-	 *
-	 * Enable Early BRESP, L2 prefetch for Instruction and Data,
-	 * write alloc and 'Full line of zero' options
-	 *
-	 */
-
-	writel_relaxed(0x06, VA_L2CC_BASE + L2X0_PREFETCH_CTRL);
-
-	/*
-	 * Program following latencies in order to make
-	 * SPEAr1340 work at 600 MHz
-	 */
-	writel_relaxed(0x221, VA_L2CC_BASE + L2X0_TAG_LATENCY_CTRL);
-	writel_relaxed(0x441, VA_L2CC_BASE + L2X0_DATA_LATENCY_CTRL);
-	l2x0_init(VA_L2CC_BASE, 0x70A60001, 0xfe00ffff);
-}
-
-/*
- * Following will create 16MB static virtual/physical mappings
- * PHYSICAL		VIRTUAL
- * 0xB3000000		0xFE000000
- * 0xE0000000		0xFD000000
- * 0xEC000000		0xFC000000
- * 0xED000000		0xFB000000
- */
-struct map_desc spear13xx_io_desc[] __initdata = {
-	{
-		.virtual	= (unsigned long)VA_PERIP_GRP2_BASE,
-		.pfn		= __phys_to_pfn(PERIP_GRP2_BASE),
-		.length		= SZ_16M,
-		.type		= MT_DEVICE
-	}, {
-		.virtual	= (unsigned long)VA_PERIP_GRP1_BASE,
-		.pfn		= __phys_to_pfn(PERIP_GRP1_BASE),
-		.length		= SZ_16M,
-		.type		= MT_DEVICE
-	}, {
-		.virtual	= (unsigned long)VA_A9SM_AND_MPMC_BASE,
-		.pfn		= __phys_to_pfn(A9SM_AND_MPMC_BASE),
-		.length		= SZ_16M,
-		.type		= MT_DEVICE
-	}, {
-		.virtual	= (unsigned long)VA_L2CC_BASE,
-		.pfn		= __phys_to_pfn(L2CC_BASE),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE
-	},
-};
-
-/* This will create static memory mapping for selected devices */
-void __init spear13xx_map_io(void)
-{
-	iotable_init(spear13xx_io_desc, ARRAY_SIZE(spear13xx_io_desc));
-}
-
-static void __init spear13xx_clk_init(void)
-{
-	if (of_machine_is_compatible("st,spear1310"))
-		spear1310_clk_init();
-	else if (of_machine_is_compatible("st,spear1340"))
-		spear1340_clk_init();
-	else
-		pr_err("%s: Unknown machine\n", __func__);
-}
-
-void __init spear13xx_timer_init(void)
-{
-	char pclk_name[] = "osc_24m_clk";
-	struct clk *gpt_clk, *pclk;
-
-	spear13xx_clk_init();
-
-	/* get the system timer clock */
-	gpt_clk = clk_get_sys("gpt0", NULL);
-	if (IS_ERR(gpt_clk)) {
-		pr_err("%s:couldn't get clk for gpt\n", __func__);
-		BUG();
-	}
-
-	/* get the suitable parent clock for timer*/
-	pclk = clk_get(NULL, pclk_name);
-	if (IS_ERR(pclk)) {
-		pr_err("%s:couldn't get %s as parent for gpt\n", __func__,
-				pclk_name);
-		BUG();
-	}
-
-	clk_set_parent(gpt_clk, pclk);
-	clk_put(gpt_clk);
-	clk_put(pclk);
-
-	spear_setup_of_timer();
-	twd_local_timer_of_register();
-}
diff --git a/arch/arm/mach-spear3xx/Kconfig b/arch/arm/mach-spear3xx/Kconfig
deleted file mode 100644
index 8bd3729..0000000
--- a/arch/arm/mach-spear3xx/Kconfig
+++ /dev/null
@@ -1,26 +0,0 @@
-#
-# SPEAr3XX Machine configuration file
-#
-
-if ARCH_SPEAR3XX
-
-menu "SPEAr3xx Implementations"
-config MACH_SPEAR300
-	bool "SPEAr300 Machine support with Device Tree"
-	select PINCTRL_SPEAR300
-	help
-	  Supports ST SPEAr300 machine configured via the device-tree
-
-config MACH_SPEAR310
-	bool "SPEAr310 Machine support with Device Tree"
-	select PINCTRL_SPEAR310
-	help
-	  Supports ST SPEAr310 machine configured via the device-tree
-
-config MACH_SPEAR320
-	bool "SPEAr320 Machine support with Device Tree"
-	select PINCTRL_SPEAR320
-	help
-	  Supports ST SPEAr320 machine configured via the device-tree
-endmenu
-endif #ARCH_SPEAR3XX
diff --git a/arch/arm/mach-spear3xx/Makefile b/arch/arm/mach-spear3xx/Makefile
deleted file mode 100644
index 8d12faa..0000000
--- a/arch/arm/mach-spear3xx/Makefile
+++ /dev/null
@@ -1,15 +0,0 @@
-#
-# Makefile for SPEAr3XX machine series
-#
-
-# common files
-obj-$(CONFIG_ARCH_SPEAR3XX)	+= spear3xx.o
-
-# spear300 specific files
-obj-$(CONFIG_MACH_SPEAR300) += spear300.o
-
-# spear310 specific files
-obj-$(CONFIG_MACH_SPEAR310) += spear310.o
-
-# spear320 specific files
-obj-$(CONFIG_MACH_SPEAR320) += spear320.o
diff --git a/arch/arm/mach-spear3xx/Makefile.boot b/arch/arm/mach-spear3xx/Makefile.boot
deleted file mode 100644
index 4674a4c..0000000
--- a/arch/arm/mach-spear3xx/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-spear3xx/include/mach/debug-macro.S b/arch/arm/mach-spear3xx/include/mach/debug-macro.S
deleted file mode 100644
index 0a6381f..0000000
--- a/arch/arm/mach-spear3xx/include/mach/debug-macro.S
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * arch/arm/mach-spear3xx/include/mach/debug-macro.S
- *
- * Debugging macro include header spear3xx machine family
- *
- * Copyright (C) 2009 ST Microelectronics
- * Viresh Kumar<viresh.linux@gmail.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 <plat/debug-macro.S>
diff --git a/arch/arm/mach-spear3xx/include/mach/generic.h b/arch/arm/mach-spear3xx/include/mach/generic.h
deleted file mode 100644
index df31079..0000000
--- a/arch/arm/mach-spear3xx/include/mach/generic.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * arch/arm/mach-spear3xx/generic.h
- *
- * SPEAr3XX machine family generic header file
- *
- * Copyright (C) 2009 ST Microelectronics
- * Viresh Kumar<viresh.linux@gmail.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_GENERIC_H
-#define __MACH_GENERIC_H
-
-#include <linux/amba/pl08x.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/amba/bus.h>
-#include <asm/mach/time.h>
-#include <asm/mach/map.h>
-
-/* Add spear3xx family device structure declarations here */
-extern void spear3xx_timer_init(void);
-extern struct pl022_ssp_controller pl022_plat_data;
-extern struct pl08x_platform_data pl080_plat_data;
-
-/* Add spear3xx family function declarations here */
-void __init spear_setup_of_timer(void);
-void __init spear3xx_clk_init(void);
-void __init spear3xx_map_io(void);
-
-void spear_restart(char, const char *);
-
-#endif /* __MACH_GENERIC_H */
diff --git a/arch/arm/mach-spear3xx/include/mach/hardware.h b/arch/arm/mach-spear3xx/include/mach/hardware.h
deleted file mode 100644
index 40a8c17..0000000
--- a/arch/arm/mach-spear3xx/include/mach/hardware.h
+++ /dev/null
@@ -1 +0,0 @@
-/* empty */
diff --git a/arch/arm/mach-spear3xx/include/mach/irqs.h b/arch/arm/mach-spear3xx/include/mach/irqs.h
deleted file mode 100644
index f95e5b2..0000000
--- a/arch/arm/mach-spear3xx/include/mach/irqs.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * arch/arm/mach-spear3xx/include/mach/irqs.h
- *
- * IRQ helper macros for SPEAr3xx machine family
- *
- * Copyright (C) 2009 ST Microelectronics
- * Viresh Kumar <viresh.linux@gmail.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_IRQS_H
-#define __MACH_IRQS_H
-
-#define NR_IRQS			256
-
-#endif /* __MACH_IRQS_H */
diff --git a/arch/arm/mach-spear3xx/include/mach/misc_regs.h b/arch/arm/mach-spear3xx/include/mach/misc_regs.h
deleted file mode 100644
index 6309bf6..0000000
--- a/arch/arm/mach-spear3xx/include/mach/misc_regs.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * arch/arm/mach-spear3xx/include/mach/misc_regs.h
- *
- * Miscellaneous registers definitions for SPEAr3xx machine family
- *
- * Copyright (C) 2009 ST Microelectronics
- * Viresh Kumar <viresh.linux@gmail.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_MISC_REGS_H
-#define __MACH_MISC_REGS_H
-
-#include <mach/spear.h>
-
-#define MISC_BASE		IOMEM(VA_SPEAR3XX_ICM3_MISC_REG_BASE)
-#define DMA_CHN_CFG		(MISC_BASE + 0x0A0)
-
-#endif /* __MACH_MISC_REGS_H */
diff --git a/arch/arm/mach-spear3xx/include/mach/spear.h b/arch/arm/mach-spear3xx/include/mach/spear.h
deleted file mode 100644
index 8cca951..0000000
--- a/arch/arm/mach-spear3xx/include/mach/spear.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * arch/arm/mach-spear3xx/include/mach/spear.h
- *
- * SPEAr3xx Machine family specific definition
- *
- * Copyright (C) 2009 ST Microelectronics
- * Viresh Kumar <viresh.linux@gmail.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_SPEAR3XX_H
-#define __MACH_SPEAR3XX_H
-
-#include <asm/memory.h>
-
-/* ICM1 - Low speed connection */
-#define SPEAR3XX_ICM1_2_BASE		UL(0xD0000000)
-#define VA_SPEAR3XX_ICM1_2_BASE		UL(0xFD000000)
-#define SPEAR3XX_ICM1_UART_BASE		UL(0xD0000000)
-#define VA_SPEAR3XX_ICM1_UART_BASE	(VA_SPEAR3XX_ICM1_2_BASE | SPEAR3XX_ICM1_UART_BASE)
-#define SPEAR3XX_ICM1_SSP_BASE		UL(0xD0100000)
-
-/* ML1 - Multi Layer CPU Subsystem */
-#define SPEAR3XX_ICM3_ML1_2_BASE	UL(0xF0000000)
-#define VA_SPEAR6XX_ML_CPU_BASE		UL(0xF0000000)
-
-/* ICM3 - Basic Subsystem */
-#define SPEAR3XX_ICM3_SMI_CTRL_BASE	UL(0xFC000000)
-#define VA_SPEAR3XX_ICM3_SMI_CTRL_BASE	UL(0xFC000000)
-#define SPEAR3XX_ICM3_DMA_BASE		UL(0xFC400000)
-#define SPEAR3XX_ICM3_SYS_CTRL_BASE	UL(0xFCA00000)
-#define VA_SPEAR3XX_ICM3_SYS_CTRL_BASE	(VA_SPEAR3XX_ICM3_SMI_CTRL_BASE | SPEAR3XX_ICM3_SYS_CTRL_BASE)
-#define SPEAR3XX_ICM3_MISC_REG_BASE	UL(0xFCA80000)
-#define VA_SPEAR3XX_ICM3_MISC_REG_BASE	(VA_SPEAR3XX_ICM3_SMI_CTRL_BASE | SPEAR3XX_ICM3_MISC_REG_BASE)
-
-/* Debug uart for linux, will be used for debug and uncompress messages */
-#define SPEAR_DBG_UART_BASE		SPEAR3XX_ICM1_UART_BASE
-#define VA_SPEAR_DBG_UART_BASE		VA_SPEAR3XX_ICM1_UART_BASE
-
-/* Sysctl base for spear platform */
-#define SPEAR_SYS_CTRL_BASE		SPEAR3XX_ICM3_SYS_CTRL_BASE
-#define VA_SPEAR_SYS_CTRL_BASE		VA_SPEAR3XX_ICM3_SYS_CTRL_BASE
-
-/* SPEAr320 Macros */
-#define SPEAR320_SOC_CONFIG_BASE	UL(0xB3000000)
-#define VA_SPEAR320_SOC_CONFIG_BASE	UL(0xFE000000)
-#define SPEAR320_CONTROL_REG		IOMEM(VA_SPEAR320_SOC_CONFIG_BASE)
-#define SPEAR320_EXT_CTRL_REG		IOMEM(VA_SPEAR320_SOC_CONFIG_BASE + 0x0018)
-	#define SPEAR320_UARTX_PCLK_MASK		0x1
-	#define SPEAR320_UART2_PCLK_SHIFT		8
-	#define SPEAR320_UART3_PCLK_SHIFT		9
-	#define SPEAR320_UART4_PCLK_SHIFT		10
-	#define SPEAR320_UART5_PCLK_SHIFT		11
-	#define SPEAR320_UART6_PCLK_SHIFT		12
-	#define SPEAR320_RS485_PCLK_SHIFT		13
-
-#endif /* __MACH_SPEAR3XX_H */
diff --git a/arch/arm/mach-spear3xx/include/mach/timex.h b/arch/arm/mach-spear3xx/include/mach/timex.h
deleted file mode 100644
index 9f5d08b..0000000
--- a/arch/arm/mach-spear3xx/include/mach/timex.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * arch/arm/mach-spear3xx/include/mach/timex.h
- *
- * SPEAr3XX machine family specific timex definitions
- *
- * Copyright (C) 2009 ST Microelectronics
- * Viresh Kumar <viresh.linux@gmail.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_TIMEX_H
-#define __MACH_TIMEX_H
-
-#include <plat/timex.h>
-
-#endif /* __MACH_TIMEX_H */
diff --git a/arch/arm/mach-spear3xx/include/mach/uncompress.h b/arch/arm/mach-spear3xx/include/mach/uncompress.h
deleted file mode 100644
index b909b01..0000000
--- a/arch/arm/mach-spear3xx/include/mach/uncompress.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * arch/arm/mach-spear3xx/include/mach/uncompress.h
- *
- * Serial port stubs for kernel decompress status messages
- *
- * Copyright (C) 2009 ST Microelectronics
- * Viresh Kumar <viresh.linux@gmail.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_UNCOMPRESS_H
-#define __MACH_UNCOMPRESS_H
-
-#include <plat/uncompress.h>
-
-#endif /* __MACH_UNCOMPRESS_H */
diff --git a/arch/arm/mach-spear3xx/spear300.c b/arch/arm/mach-spear3xx/spear300.c
deleted file mode 100644
index bbc9b7e..0000000
--- a/arch/arm/mach-spear3xx/spear300.c
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * arch/arm/mach-spear3xx/spear300.c
- *
- * SPEAr300 machine source file
- *
- * Copyright (C) 2009-2012 ST Microelectronics
- * Viresh Kumar <viresh.linux@gmail.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.
- */
-
-#define pr_fmt(fmt) "SPEAr300: " fmt
-
-#include <linux/amba/pl08x.h>
-#include <linux/irqchip.h>
-#include <linux/of_platform.h>
-#include <asm/mach/arch.h>
-#include <mach/generic.h>
-#include <mach/spear.h>
-
-/* DMAC platform data's slave info */
-struct pl08x_channel_data spear300_dma_info[] = {
-	{
-		.bus_id = "uart0_rx",
-		.min_signal = 2,
-		.max_signal = 2,
-		.muxval = 0,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "uart0_tx",
-		.min_signal = 3,
-		.max_signal = 3,
-		.muxval = 0,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "ssp0_rx",
-		.min_signal = 8,
-		.max_signal = 8,
-		.muxval = 0,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "ssp0_tx",
-		.min_signal = 9,
-		.max_signal = 9,
-		.muxval = 0,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "i2c_rx",
-		.min_signal = 10,
-		.max_signal = 10,
-		.muxval = 0,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "i2c_tx",
-		.min_signal = 11,
-		.max_signal = 11,
-		.muxval = 0,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "irda",
-		.min_signal = 12,
-		.max_signal = 12,
-		.muxval = 0,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "adc",
-		.min_signal = 13,
-		.max_signal = 13,
-		.muxval = 0,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "to_jpeg",
-		.min_signal = 14,
-		.max_signal = 14,
-		.muxval = 0,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "from_jpeg",
-		.min_signal = 15,
-		.max_signal = 15,
-		.muxval = 0,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "ras0_rx",
-		.min_signal = 0,
-		.max_signal = 0,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "ras0_tx",
-		.min_signal = 1,
-		.max_signal = 1,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "ras1_rx",
-		.min_signal = 2,
-		.max_signal = 2,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "ras1_tx",
-		.min_signal = 3,
-		.max_signal = 3,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "ras2_rx",
-		.min_signal = 4,
-		.max_signal = 4,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "ras2_tx",
-		.min_signal = 5,
-		.max_signal = 5,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "ras3_rx",
-		.min_signal = 6,
-		.max_signal = 6,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "ras3_tx",
-		.min_signal = 7,
-		.max_signal = 7,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "ras4_rx",
-		.min_signal = 8,
-		.max_signal = 8,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "ras4_tx",
-		.min_signal = 9,
-		.max_signal = 9,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "ras5_rx",
-		.min_signal = 10,
-		.max_signal = 10,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "ras5_tx",
-		.min_signal = 11,
-		.max_signal = 11,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "ras6_rx",
-		.min_signal = 12,
-		.max_signal = 12,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "ras6_tx",
-		.min_signal = 13,
-		.max_signal = 13,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "ras7_rx",
-		.min_signal = 14,
-		.max_signal = 14,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "ras7_tx",
-		.min_signal = 15,
-		.max_signal = 15,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB1,
-	},
-};
-
-/* Add SPEAr300 auxdata to pass platform data */
-static struct of_dev_auxdata spear300_auxdata_lookup[] __initdata = {
-	OF_DEV_AUXDATA("arm,pl022", SPEAR3XX_ICM1_SSP_BASE, NULL,
-			&pl022_plat_data),
-	OF_DEV_AUXDATA("arm,pl080", SPEAR3XX_ICM3_DMA_BASE, NULL,
-			&pl080_plat_data),
-	{}
-};
-
-static void __init spear300_dt_init(void)
-{
-	pl080_plat_data.slave_channels = spear300_dma_info;
-	pl080_plat_data.num_slave_channels = ARRAY_SIZE(spear300_dma_info);
-
-	of_platform_populate(NULL, of_default_bus_match_table,
-			spear300_auxdata_lookup, NULL);
-}
-
-static const char * const spear300_dt_board_compat[] = {
-	"st,spear300",
-	"st,spear300-evb",
-	NULL,
-};
-
-static void __init spear300_map_io(void)
-{
-	spear3xx_map_io();
-}
-
-DT_MACHINE_START(SPEAR300_DT, "ST SPEAr300 SoC with Flattened Device Tree")
-	.map_io		=	spear300_map_io,
-	.init_irq	=	irqchip_init,
-	.init_time	=	spear3xx_timer_init,
-	.init_machine	=	spear300_dt_init,
-	.restart	=	spear_restart,
-	.dt_compat	=	spear300_dt_board_compat,
-MACHINE_END
diff --git a/arch/arm/mach-spear3xx/spear310.c b/arch/arm/mach-spear3xx/spear310.c
deleted file mode 100644
index c13a434..0000000
--- a/arch/arm/mach-spear3xx/spear310.c
+++ /dev/null
@@ -1,262 +0,0 @@
-/*
- * arch/arm/mach-spear3xx/spear310.c
- *
- * SPEAr310 machine source file
- *
- * Copyright (C) 2009-2012 ST Microelectronics
- * Viresh Kumar <viresh.linux@gmail.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.
- */
-
-#define pr_fmt(fmt) "SPEAr310: " fmt
-
-#include <linux/amba/pl08x.h>
-#include <linux/amba/serial.h>
-#include <linux/irqchip.h>
-#include <linux/of_platform.h>
-#include <asm/mach/arch.h>
-#include <mach/generic.h>
-#include <mach/spear.h>
-
-#define SPEAR310_UART1_BASE		UL(0xB2000000)
-#define SPEAR310_UART2_BASE		UL(0xB2080000)
-#define SPEAR310_UART3_BASE		UL(0xB2100000)
-#define SPEAR310_UART4_BASE		UL(0xB2180000)
-#define SPEAR310_UART5_BASE		UL(0xB2200000)
-
-/* DMAC platform data's slave info */
-struct pl08x_channel_data spear310_dma_info[] = {
-	{
-		.bus_id = "uart0_rx",
-		.min_signal = 2,
-		.max_signal = 2,
-		.muxval = 0,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "uart0_tx",
-		.min_signal = 3,
-		.max_signal = 3,
-		.muxval = 0,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "ssp0_rx",
-		.min_signal = 8,
-		.max_signal = 8,
-		.muxval = 0,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "ssp0_tx",
-		.min_signal = 9,
-		.max_signal = 9,
-		.muxval = 0,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "i2c_rx",
-		.min_signal = 10,
-		.max_signal = 10,
-		.muxval = 0,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "i2c_tx",
-		.min_signal = 11,
-		.max_signal = 11,
-		.muxval = 0,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "irda",
-		.min_signal = 12,
-		.max_signal = 12,
-		.muxval = 0,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "adc",
-		.min_signal = 13,
-		.max_signal = 13,
-		.muxval = 0,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "to_jpeg",
-		.min_signal = 14,
-		.max_signal = 14,
-		.muxval = 0,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "from_jpeg",
-		.min_signal = 15,
-		.max_signal = 15,
-		.muxval = 0,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "uart1_rx",
-		.min_signal = 0,
-		.max_signal = 0,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "uart1_tx",
-		.min_signal = 1,
-		.max_signal = 1,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "uart2_rx",
-		.min_signal = 2,
-		.max_signal = 2,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "uart2_tx",
-		.min_signal = 3,
-		.max_signal = 3,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "uart3_rx",
-		.min_signal = 4,
-		.max_signal = 4,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "uart3_tx",
-		.min_signal = 5,
-		.max_signal = 5,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "uart4_rx",
-		.min_signal = 6,
-		.max_signal = 6,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "uart4_tx",
-		.min_signal = 7,
-		.max_signal = 7,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "uart5_rx",
-		.min_signal = 8,
-		.max_signal = 8,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "uart5_tx",
-		.min_signal = 9,
-		.max_signal = 9,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "ras5_rx",
-		.min_signal = 10,
-		.max_signal = 10,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "ras5_tx",
-		.min_signal = 11,
-		.max_signal = 11,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "ras6_rx",
-		.min_signal = 12,
-		.max_signal = 12,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "ras6_tx",
-		.min_signal = 13,
-		.max_signal = 13,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "ras7_rx",
-		.min_signal = 14,
-		.max_signal = 14,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "ras7_tx",
-		.min_signal = 15,
-		.max_signal = 15,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB1,
-	},
-};
-
-/* uart devices plat data */
-static struct amba_pl011_data spear310_uart_data[] = {
-	{
-		.dma_filter = pl08x_filter_id,
-		.dma_tx_param = "uart1_tx",
-		.dma_rx_param = "uart1_rx",
-	}, {
-		.dma_filter = pl08x_filter_id,
-		.dma_tx_param = "uart2_tx",
-		.dma_rx_param = "uart2_rx",
-	}, {
-		.dma_filter = pl08x_filter_id,
-		.dma_tx_param = "uart3_tx",
-		.dma_rx_param = "uart3_rx",
-	}, {
-		.dma_filter = pl08x_filter_id,
-		.dma_tx_param = "uart4_tx",
-		.dma_rx_param = "uart4_rx",
-	}, {
-		.dma_filter = pl08x_filter_id,
-		.dma_tx_param = "uart5_tx",
-		.dma_rx_param = "uart5_rx",
-	},
-};
-
-/* Add SPEAr310 auxdata to pass platform data */
-static struct of_dev_auxdata spear310_auxdata_lookup[] __initdata = {
-	OF_DEV_AUXDATA("arm,pl022", SPEAR3XX_ICM1_SSP_BASE, NULL,
-			&pl022_plat_data),
-	OF_DEV_AUXDATA("arm,pl080", SPEAR3XX_ICM3_DMA_BASE, NULL,
-			&pl080_plat_data),
-	OF_DEV_AUXDATA("arm,pl011", SPEAR310_UART1_BASE, NULL,
-			&spear310_uart_data[0]),
-	OF_DEV_AUXDATA("arm,pl011", SPEAR310_UART2_BASE, NULL,
-			&spear310_uart_data[1]),
-	OF_DEV_AUXDATA("arm,pl011", SPEAR310_UART3_BASE, NULL,
-			&spear310_uart_data[2]),
-	OF_DEV_AUXDATA("arm,pl011", SPEAR310_UART4_BASE, NULL,
-			&spear310_uart_data[3]),
-	OF_DEV_AUXDATA("arm,pl011", SPEAR310_UART5_BASE, NULL,
-			&spear310_uart_data[4]),
-	{}
-};
-
-static void __init spear310_dt_init(void)
-{
-	pl080_plat_data.slave_channels = spear310_dma_info;
-	pl080_plat_data.num_slave_channels = ARRAY_SIZE(spear310_dma_info);
-
-	of_platform_populate(NULL, of_default_bus_match_table,
-			spear310_auxdata_lookup, NULL);
-}
-
-static const char * const spear310_dt_board_compat[] = {
-	"st,spear310",
-	"st,spear310-evb",
-	NULL,
-};
-
-static void __init spear310_map_io(void)
-{
-	spear3xx_map_io();
-}
-
-DT_MACHINE_START(SPEAR310_DT, "ST SPEAr310 SoC with Flattened Device Tree")
-	.map_io		=	spear310_map_io,
-	.init_irq	=	irqchip_init,
-	.init_time	=	spear3xx_timer_init,
-	.init_machine	=	spear310_dt_init,
-	.restart	=	spear_restart,
-	.dt_compat	=	spear310_dt_board_compat,
-MACHINE_END
diff --git a/arch/arm/mach-spear3xx/spear320.c b/arch/arm/mach-spear3xx/spear320.c
deleted file mode 100644
index e1c7707..0000000
--- a/arch/arm/mach-spear3xx/spear320.c
+++ /dev/null
@@ -1,276 +0,0 @@
-/*
- * arch/arm/mach-spear3xx/spear320.c
- *
- * SPEAr320 machine source file
- *
- * Copyright (C) 2009-2012 ST Microelectronics
- * Viresh Kumar <viresh.linux@gmail.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.
- */
-
-#define pr_fmt(fmt) "SPEAr320: " fmt
-
-#include <linux/amba/pl022.h>
-#include <linux/amba/pl08x.h>
-#include <linux/amba/serial.h>
-#include <linux/irqchip.h>
-#include <linux/of_platform.h>
-#include <asm/mach/arch.h>
-#include <mach/generic.h>
-#include <mach/spear.h>
-
-#define SPEAR320_UART1_BASE		UL(0xA3000000)
-#define SPEAR320_UART2_BASE		UL(0xA4000000)
-#define SPEAR320_SSP0_BASE		UL(0xA5000000)
-#define SPEAR320_SSP1_BASE		UL(0xA6000000)
-
-/* DMAC platform data's slave info */
-struct pl08x_channel_data spear320_dma_info[] = {
-	{
-		.bus_id = "uart0_rx",
-		.min_signal = 2,
-		.max_signal = 2,
-		.muxval = 0,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "uart0_tx",
-		.min_signal = 3,
-		.max_signal = 3,
-		.muxval = 0,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "ssp0_rx",
-		.min_signal = 8,
-		.max_signal = 8,
-		.muxval = 0,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "ssp0_tx",
-		.min_signal = 9,
-		.max_signal = 9,
-		.muxval = 0,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "i2c0_rx",
-		.min_signal = 10,
-		.max_signal = 10,
-		.muxval = 0,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "i2c0_tx",
-		.min_signal = 11,
-		.max_signal = 11,
-		.muxval = 0,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "irda",
-		.min_signal = 12,
-		.max_signal = 12,
-		.muxval = 0,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "adc",
-		.min_signal = 13,
-		.max_signal = 13,
-		.muxval = 0,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "to_jpeg",
-		.min_signal = 14,
-		.max_signal = 14,
-		.muxval = 0,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "from_jpeg",
-		.min_signal = 15,
-		.max_signal = 15,
-		.muxval = 0,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "ssp1_rx",
-		.min_signal = 0,
-		.max_signal = 0,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB2,
-	}, {
-		.bus_id = "ssp1_tx",
-		.min_signal = 1,
-		.max_signal = 1,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB2,
-	}, {
-		.bus_id = "ssp2_rx",
-		.min_signal = 2,
-		.max_signal = 2,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB2,
-	}, {
-		.bus_id = "ssp2_tx",
-		.min_signal = 3,
-		.max_signal = 3,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB2,
-	}, {
-		.bus_id = "uart1_rx",
-		.min_signal = 4,
-		.max_signal = 4,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB2,
-	}, {
-		.bus_id = "uart1_tx",
-		.min_signal = 5,
-		.max_signal = 5,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB2,
-	}, {
-		.bus_id = "uart2_rx",
-		.min_signal = 6,
-		.max_signal = 6,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB2,
-	}, {
-		.bus_id = "uart2_tx",
-		.min_signal = 7,
-		.max_signal = 7,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB2,
-	}, {
-		.bus_id = "i2c1_rx",
-		.min_signal = 8,
-		.max_signal = 8,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB2,
-	}, {
-		.bus_id = "i2c1_tx",
-		.min_signal = 9,
-		.max_signal = 9,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB2,
-	}, {
-		.bus_id = "i2c2_rx",
-		.min_signal = 10,
-		.max_signal = 10,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB2,
-	}, {
-		.bus_id = "i2c2_tx",
-		.min_signal = 11,
-		.max_signal = 11,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB2,
-	}, {
-		.bus_id = "i2s_rx",
-		.min_signal = 12,
-		.max_signal = 12,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB2,
-	}, {
-		.bus_id = "i2s_tx",
-		.min_signal = 13,
-		.max_signal = 13,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB2,
-	}, {
-		.bus_id = "rs485_rx",
-		.min_signal = 14,
-		.max_signal = 14,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB2,
-	}, {
-		.bus_id = "rs485_tx",
-		.min_signal = 15,
-		.max_signal = 15,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB2,
-	},
-};
-
-static struct pl022_ssp_controller spear320_ssp_data[] = {
-	{
-		.bus_id = 1,
-		.enable_dma = 1,
-		.dma_filter = pl08x_filter_id,
-		.dma_tx_param = "ssp1_tx",
-		.dma_rx_param = "ssp1_rx",
-		.num_chipselect = 2,
-	}, {
-		.bus_id = 2,
-		.enable_dma = 1,
-		.dma_filter = pl08x_filter_id,
-		.dma_tx_param = "ssp2_tx",
-		.dma_rx_param = "ssp2_rx",
-		.num_chipselect = 2,
-	}
-};
-
-static struct amba_pl011_data spear320_uart_data[] = {
-	{
-		.dma_filter = pl08x_filter_id,
-		.dma_tx_param = "uart1_tx",
-		.dma_rx_param = "uart1_rx",
-	}, {
-		.dma_filter = pl08x_filter_id,
-		.dma_tx_param = "uart2_tx",
-		.dma_rx_param = "uart2_rx",
-	},
-};
-
-/* Add SPEAr310 auxdata to pass platform data */
-static struct of_dev_auxdata spear320_auxdata_lookup[] __initdata = {
-	OF_DEV_AUXDATA("arm,pl022", SPEAR3XX_ICM1_SSP_BASE, NULL,
-			&pl022_plat_data),
-	OF_DEV_AUXDATA("arm,pl080", SPEAR3XX_ICM3_DMA_BASE, NULL,
-			&pl080_plat_data),
-	OF_DEV_AUXDATA("arm,pl022", SPEAR320_SSP0_BASE, NULL,
-			&spear320_ssp_data[0]),
-	OF_DEV_AUXDATA("arm,pl022", SPEAR320_SSP1_BASE, NULL,
-			&spear320_ssp_data[1]),
-	OF_DEV_AUXDATA("arm,pl011", SPEAR320_UART1_BASE, NULL,
-			&spear320_uart_data[0]),
-	OF_DEV_AUXDATA("arm,pl011", SPEAR320_UART2_BASE, NULL,
-			&spear320_uart_data[1]),
-	{}
-};
-
-static void __init spear320_dt_init(void)
-{
-	pl080_plat_data.slave_channels = spear320_dma_info;
-	pl080_plat_data.num_slave_channels = ARRAY_SIZE(spear320_dma_info);
-
-	of_platform_populate(NULL, of_default_bus_match_table,
-			spear320_auxdata_lookup, NULL);
-}
-
-static const char * const spear320_dt_board_compat[] = {
-	"st,spear320",
-	"st,spear320-evb",
-	"st,spear320-hmi",
-	NULL,
-};
-
-struct map_desc spear320_io_desc[] __initdata = {
-	{
-		.virtual	= VA_SPEAR320_SOC_CONFIG_BASE,
-		.pfn		= __phys_to_pfn(SPEAR320_SOC_CONFIG_BASE),
-		.length		= SZ_16M,
-		.type		= MT_DEVICE
-	},
-};
-
-static void __init spear320_map_io(void)
-{
-	iotable_init(spear320_io_desc, ARRAY_SIZE(spear320_io_desc));
-	spear3xx_map_io();
-}
-
-DT_MACHINE_START(SPEAR320_DT, "ST SPEAr320 SoC with Flattened Device Tree")
-	.map_io		=	spear320_map_io,
-	.init_irq	=	irqchip_init,
-	.init_time	=	spear3xx_timer_init,
-	.init_machine	=	spear320_dt_init,
-	.restart	=	spear_restart,
-	.dt_compat	=	spear320_dt_board_compat,
-MACHINE_END
diff --git a/arch/arm/mach-spear3xx/spear3xx.c b/arch/arm/mach-spear3xx/spear3xx.c
deleted file mode 100644
index d2b3937..0000000
--- a/arch/arm/mach-spear3xx/spear3xx.c
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * arch/arm/mach-spear3xx/spear3xx.c
- *
- * SPEAr3XX machines common source file
- *
- * Copyright (C) 2009-2012 ST Microelectronics
- * Viresh Kumar <viresh.linux@gmail.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.
- */
-
-#define pr_fmt(fmt) "SPEAr3xx: " fmt
-
-#include <linux/amba/pl022.h>
-#include <linux/amba/pl080.h>
-#include <linux/io.h>
-#include <plat/pl080.h>
-#include <mach/generic.h>
-#include <mach/spear.h>
-
-/* ssp device registration */
-struct pl022_ssp_controller pl022_plat_data = {
-	.bus_id = 0,
-	.enable_dma = 1,
-	.dma_filter = pl08x_filter_id,
-	.dma_tx_param = "ssp0_tx",
-	.dma_rx_param = "ssp0_rx",
-	/*
-	 * This is number of spi devices that can be connected to spi. There are
-	 * two type of chipselects on which slave devices can work. One is chip
-	 * select provided by spi masters other is controlled through external
-	 * gpio's. We can't use chipselect provided from spi master (because as
-	 * soon as FIFO becomes empty, CS is disabled and transfer ends). So
-	 * this number now depends on number of gpios available for spi. each
-	 * slave on each master requires a separate gpio pin.
-	 */
-	.num_chipselect = 2,
-};
-
-/* dmac device registration */
-struct pl08x_platform_data pl080_plat_data = {
-	.memcpy_channel = {
-		.bus_id = "memcpy",
-		.cctl_memcpy =
-			(PL080_BSIZE_16 << PL080_CONTROL_SB_SIZE_SHIFT | \
-			PL080_BSIZE_16 << PL080_CONTROL_DB_SIZE_SHIFT | \
-			PL080_WIDTH_32BIT << PL080_CONTROL_SWIDTH_SHIFT | \
-			PL080_WIDTH_32BIT << PL080_CONTROL_DWIDTH_SHIFT | \
-			PL080_CONTROL_PROT_BUFF | PL080_CONTROL_PROT_CACHE | \
-			PL080_CONTROL_PROT_SYS),
-	},
-	.lli_buses = PL08X_AHB1,
-	.mem_buses = PL08X_AHB1,
-	.get_signal = pl080_get_signal,
-	.put_signal = pl080_put_signal,
-};
-
-/*
- * Following will create 16MB static virtual/physical mappings
- * PHYSICAL		VIRTUAL
- * 0xD0000000		0xFD000000
- * 0xFC000000		0xFC000000
- */
-struct map_desc spear3xx_io_desc[] __initdata = {
-	{
-		.virtual	= VA_SPEAR3XX_ICM1_2_BASE,
-		.pfn		= __phys_to_pfn(SPEAR3XX_ICM1_2_BASE),
-		.length		= SZ_16M,
-		.type		= MT_DEVICE
-	}, {
-		.virtual	= VA_SPEAR3XX_ICM3_SMI_CTRL_BASE,
-		.pfn		= __phys_to_pfn(SPEAR3XX_ICM3_SMI_CTRL_BASE),
-		.length		= SZ_16M,
-		.type		= MT_DEVICE
-	},
-};
-
-/* This will create static memory mapping for selected devices */
-void __init spear3xx_map_io(void)
-{
-	iotable_init(spear3xx_io_desc, ARRAY_SIZE(spear3xx_io_desc));
-}
-
-void __init spear3xx_timer_init(void)
-{
-	char pclk_name[] = "pll3_clk";
-	struct clk *gpt_clk, *pclk;
-
-	spear3xx_clk_init();
-
-	/* get the system timer clock */
-	gpt_clk = clk_get_sys("gpt0", NULL);
-	if (IS_ERR(gpt_clk)) {
-		pr_err("%s:couldn't get clk for gpt\n", __func__);
-		BUG();
-	}
-
-	/* get the suitable parent clock for timer*/
-	pclk = clk_get(NULL, pclk_name);
-	if (IS_ERR(pclk)) {
-		pr_err("%s:couldn't get %s as parent for gpt\n",
-				__func__, pclk_name);
-		BUG();
-	}
-
-	clk_set_parent(gpt_clk, pclk);
-	clk_put(gpt_clk);
-	clk_put(pclk);
-
-	spear_setup_of_timer();
-}
diff --git a/arch/arm/mach-spear6xx/Kconfig b/arch/arm/mach-spear6xx/Kconfig
deleted file mode 100644
index 339f397..0000000
--- a/arch/arm/mach-spear6xx/Kconfig
+++ /dev/null
@@ -1,10 +0,0 @@
-#
-# SPEAr6XX Machine configuration file
-#
-
-config MACH_SPEAR600
-	def_bool y
-	depends on ARCH_SPEAR6XX
-	select USE_OF
-	help
-	  Supports ST SPEAr600 boards configured via the device-tree
diff --git a/arch/arm/mach-spear6xx/Makefile b/arch/arm/mach-spear6xx/Makefile
deleted file mode 100644
index 898831d..0000000
--- a/arch/arm/mach-spear6xx/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-#
-# Makefile for SPEAr6XX machine series
-#
-
-# common files
-obj-y	+= spear6xx.o
diff --git a/arch/arm/mach-spear6xx/Makefile.boot b/arch/arm/mach-spear6xx/Makefile.boot
deleted file mode 100644
index 4674a4c..0000000
--- a/arch/arm/mach-spear6xx/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-spear6xx/include/mach/debug-macro.S b/arch/arm/mach-spear6xx/include/mach/debug-macro.S
deleted file mode 100644
index 0f3ea39..0000000
--- a/arch/arm/mach-spear6xx/include/mach/debug-macro.S
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * arch/arm/mach-spear6xx/include/mach/debug-macro.S
- *
- * Debugging macro include header for SPEAr6xx machine family
- *
- * Copyright (C) 2009 ST Microelectronics
- * Rajeev Kumar<rajeev-dlh.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.
- */
-
-#include <plat/debug-macro.S>
diff --git a/arch/arm/mach-spear6xx/include/mach/generic.h b/arch/arm/mach-spear6xx/include/mach/generic.h
deleted file mode 100644
index 65514b1..0000000
--- a/arch/arm/mach-spear6xx/include/mach/generic.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * arch/arm/mach-spear6xx/include/mach/generic.h
- *
- * SPEAr6XX machine family specific generic header file
- *
- * Copyright (C) 2009 ST Microelectronics
- * Rajeev Kumar<rajeev-dlh.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_GENERIC_H
-#define __MACH_GENERIC_H
-
-#include <linux/init.h>
-
-void __init spear_setup_of_timer(void);
-void spear_restart(char, const char *);
-void __init spear6xx_clk_init(void);
-
-#endif /* __MACH_GENERIC_H */
diff --git a/arch/arm/mach-spear6xx/include/mach/hardware.h b/arch/arm/mach-spear6xx/include/mach/hardware.h
deleted file mode 100644
index 40a8c17..0000000
--- a/arch/arm/mach-spear6xx/include/mach/hardware.h
+++ /dev/null
@@ -1 +0,0 @@
-/* empty */
diff --git a/arch/arm/mach-spear6xx/include/mach/irqs.h b/arch/arm/mach-spear6xx/include/mach/irqs.h
deleted file mode 100644
index 37a5c41..0000000
--- a/arch/arm/mach-spear6xx/include/mach/irqs.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * arch/arm/mach-spear6xx/include/mach/irqs.h
- *
- * IRQ helper macros for SPEAr6xx machine family
- *
- * Copyright (C) 2009 ST Microelectronics
- * Rajeev Kumar<rajeev-dlh.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_IRQS_H
-#define __MACH_IRQS_H
-
-/* IRQ definitions */
-/* VIC 1 */
-#define IRQ_VIC_END				64
-
-/* GPIO pins virtual irqs */
-#define VIRTUAL_IRQS				24
-#define NR_IRQS					(IRQ_VIC_END + VIRTUAL_IRQS)
-
-#endif	/* __MACH_IRQS_H */
diff --git a/arch/arm/mach-spear6xx/include/mach/misc_regs.h b/arch/arm/mach-spear6xx/include/mach/misc_regs.h
deleted file mode 100644
index c34acc2..0000000
--- a/arch/arm/mach-spear6xx/include/mach/misc_regs.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * arch/arm/mach-spear6xx/include/mach/misc_regs.h
- *
- * Miscellaneous registers definitions for SPEAr6xx machine family
- *
- * Copyright (C) 2009 ST Microelectronics
- * Viresh Kumar <viresh.linux@gmail.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_MISC_REGS_H
-#define __MACH_MISC_REGS_H
-
-#include <mach/spear.h>
-
-#define MISC_BASE		IOMEM(VA_SPEAR6XX_ICM3_MISC_REG_BASE)
-#define DMA_CHN_CFG		(MISC_BASE + 0x0A0)
-
-#endif /* __MACH_MISC_REGS_H */
diff --git a/arch/arm/mach-spear6xx/include/mach/spear.h b/arch/arm/mach-spear6xx/include/mach/spear.h
deleted file mode 100644
index cb8ed2f..0000000
--- a/arch/arm/mach-spear6xx/include/mach/spear.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * arch/arm/mach-spear6xx/include/mach/spear.h
- *
- * SPEAr6xx Machine family specific definition
- *
- * Copyright (C) 2009 ST Microelectronics
- * Rajeev Kumar<rajeev-dlh.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_SPEAR6XX_H
-#define __MACH_SPEAR6XX_H
-
-#include <asm/memory.h>
-
-/* ICM1 - Low speed connection */
-#define SPEAR6XX_ICM1_BASE		UL(0xD0000000)
-#define VA_SPEAR6XX_ICM1_BASE		UL(0xFD000000)
-#define SPEAR6XX_ICM1_UART0_BASE	UL(0xD0000000)
-#define VA_SPEAR6XX_ICM1_UART0_BASE	(VA_SPEAR6XX_ICM1_2_BASE | SPEAR6XX_ICM1_UART0_BASE)
-
-/* ML-1, 2 - Multi Layer CPU Subsystem */
-#define SPEAR6XX_ML_CPU_BASE		UL(0xF0000000)
-#define VA_SPEAR6XX_ML_CPU_BASE		UL(0xF0000000)
-
-/* ICM3 - Basic Subsystem */
-#define SPEAR6XX_ICM3_SMI_CTRL_BASE	UL(0xFC000000)
-#define VA_SPEAR6XX_ICM3_SMI_CTRL_BASE	UL(0xFC000000)
-#define SPEAR6XX_ICM3_DMA_BASE		UL(0xFC400000)
-#define SPEAR6XX_ICM3_SYS_CTRL_BASE	UL(0xFCA00000)
-#define VA_SPEAR6XX_ICM3_SYS_CTRL_BASE	(VA_SPEAR6XX_ICM3_SMI_CTRL_BASE | SPEAR6XX_ICM3_SYS_CTRL_BASE)
-#define SPEAR6XX_ICM3_MISC_REG_BASE	UL(0xFCA80000)
-#define VA_SPEAR6XX_ICM3_MISC_REG_BASE	(VA_SPEAR6XX_ICM3_SMI_CTRL_BASE | SPEAR6XX_ICM3_MISC_REG_BASE)
-
-/* Debug uart for linux, will be used for debug and uncompress messages */
-#define SPEAR_DBG_UART_BASE		SPEAR6XX_ICM1_UART0_BASE
-#define VA_SPEAR_DBG_UART_BASE		VA_SPEAR6XX_ICM1_UART0_BASE
-
-/* Sysctl base for spear platform */
-#define SPEAR_SYS_CTRL_BASE		SPEAR6XX_ICM3_SYS_CTRL_BASE
-#define VA_SPEAR_SYS_CTRL_BASE		VA_SPEAR6XX_ICM3_SYS_CTRL_BASE
-
-#endif /* __MACH_SPEAR6XX_H */
diff --git a/arch/arm/mach-spear6xx/include/mach/timex.h b/arch/arm/mach-spear6xx/include/mach/timex.h
deleted file mode 100644
index ac1c5b0..0000000
--- a/arch/arm/mach-spear6xx/include/mach/timex.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * arch/arm/mach-spear6xx/include/mach/timex.h
- *
- * SPEAr6XX machine family specific timex definitions
- *
- * Copyright (C) 2009 ST Microelectronics
- * Rajeev Kumar<rajeev-dlh.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_TIMEX_H
-#define __MACH_TIMEX_H
-
-#include <plat/timex.h>
-
-#endif	/* __MACH_TIMEX_H */
diff --git a/arch/arm/mach-spear6xx/include/mach/uncompress.h b/arch/arm/mach-spear6xx/include/mach/uncompress.h
deleted file mode 100644
index 77f0765..0000000
--- a/arch/arm/mach-spear6xx/include/mach/uncompress.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * arch/arm/mach-spear6xx/include/mach/uncompress.h
- *
- * Serial port stubs for kernel decompress status messages
- *
- * Copyright (C) 2009 ST Microelectronics
- * Rajeev Kumar<rajeev-dlh.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_UNCOMPRESS_H
-#define __MACH_UNCOMPRESS_H
-
-#include <plat/uncompress.h>
-
-#endif	/* __MACH_UNCOMPRESS_H */
diff --git a/arch/arm/mach-spear6xx/spear6xx.c b/arch/arm/mach-spear6xx/spear6xx.c
deleted file mode 100644
index 8904d8a..0000000
--- a/arch/arm/mach-spear6xx/spear6xx.c
+++ /dev/null
@@ -1,430 +0,0 @@
-/*
- * arch/arm/mach-spear6xx/spear6xx.c
- *
- * SPEAr6XX machines common source file
- *
- * Copyright (C) 2009 ST Microelectronics
- * Rajeev Kumar<rajeev-dlh.kumar@st.com>
- *
- * Copyright 2012 Stefan Roese <sr@denx.de>
- *
- * 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/amba/pl08x.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/irqchip.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_platform.h>
-#include <linux/amba/pl080.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-#include <asm/mach/map.h>
-#include <plat/pl080.h>
-#include <mach/generic.h>
-#include <mach/spear.h>
-
-/* dmac device registration */
-static struct pl08x_channel_data spear600_dma_info[] = {
-	{
-		.bus_id = "ssp1_rx",
-		.min_signal = 0,
-		.max_signal = 0,
-		.muxval = 0,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "ssp1_tx",
-		.min_signal = 1,
-		.max_signal = 1,
-		.muxval = 0,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "uart0_rx",
-		.min_signal = 2,
-		.max_signal = 2,
-		.muxval = 0,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "uart0_tx",
-		.min_signal = 3,
-		.max_signal = 3,
-		.muxval = 0,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "uart1_rx",
-		.min_signal = 4,
-		.max_signal = 4,
-		.muxval = 0,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "uart1_tx",
-		.min_signal = 5,
-		.max_signal = 5,
-		.muxval = 0,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "ssp2_rx",
-		.min_signal = 6,
-		.max_signal = 6,
-		.muxval = 0,
-		.periph_buses = PL08X_AHB2,
-	}, {
-		.bus_id = "ssp2_tx",
-		.min_signal = 7,
-		.max_signal = 7,
-		.muxval = 0,
-		.periph_buses = PL08X_AHB2,
-	}, {
-		.bus_id = "ssp0_rx",
-		.min_signal = 8,
-		.max_signal = 8,
-		.muxval = 0,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "ssp0_tx",
-		.min_signal = 9,
-		.max_signal = 9,
-		.muxval = 0,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "i2c_rx",
-		.min_signal = 10,
-		.max_signal = 10,
-		.muxval = 0,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "i2c_tx",
-		.min_signal = 11,
-		.max_signal = 11,
-		.muxval = 0,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "irda",
-		.min_signal = 12,
-		.max_signal = 12,
-		.muxval = 0,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "adc",
-		.min_signal = 13,
-		.max_signal = 13,
-		.muxval = 0,
-		.periph_buses = PL08X_AHB2,
-	}, {
-		.bus_id = "to_jpeg",
-		.min_signal = 14,
-		.max_signal = 14,
-		.muxval = 0,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "from_jpeg",
-		.min_signal = 15,
-		.max_signal = 15,
-		.muxval = 0,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "ras0_rx",
-		.min_signal = 0,
-		.max_signal = 0,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "ras0_tx",
-		.min_signal = 1,
-		.max_signal = 1,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "ras1_rx",
-		.min_signal = 2,
-		.max_signal = 2,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "ras1_tx",
-		.min_signal = 3,
-		.max_signal = 3,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "ras2_rx",
-		.min_signal = 4,
-		.max_signal = 4,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "ras2_tx",
-		.min_signal = 5,
-		.max_signal = 5,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "ras3_rx",
-		.min_signal = 6,
-		.max_signal = 6,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "ras3_tx",
-		.min_signal = 7,
-		.max_signal = 7,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "ras4_rx",
-		.min_signal = 8,
-		.max_signal = 8,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "ras4_tx",
-		.min_signal = 9,
-		.max_signal = 9,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "ras5_rx",
-		.min_signal = 10,
-		.max_signal = 10,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "ras5_tx",
-		.min_signal = 11,
-		.max_signal = 11,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "ras6_rx",
-		.min_signal = 12,
-		.max_signal = 12,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "ras6_tx",
-		.min_signal = 13,
-		.max_signal = 13,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "ras7_rx",
-		.min_signal = 14,
-		.max_signal = 14,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "ras7_tx",
-		.min_signal = 15,
-		.max_signal = 15,
-		.muxval = 1,
-		.periph_buses = PL08X_AHB1,
-	}, {
-		.bus_id = "ext0_rx",
-		.min_signal = 0,
-		.max_signal = 0,
-		.muxval = 2,
-		.periph_buses = PL08X_AHB2,
-	}, {
-		.bus_id = "ext0_tx",
-		.min_signal = 1,
-		.max_signal = 1,
-		.muxval = 2,
-		.periph_buses = PL08X_AHB2,
-	}, {
-		.bus_id = "ext1_rx",
-		.min_signal = 2,
-		.max_signal = 2,
-		.muxval = 2,
-		.periph_buses = PL08X_AHB2,
-	}, {
-		.bus_id = "ext1_tx",
-		.min_signal = 3,
-		.max_signal = 3,
-		.muxval = 2,
-		.periph_buses = PL08X_AHB2,
-	}, {
-		.bus_id = "ext2_rx",
-		.min_signal = 4,
-		.max_signal = 4,
-		.muxval = 2,
-		.periph_buses = PL08X_AHB2,
-	}, {
-		.bus_id = "ext2_tx",
-		.min_signal = 5,
-		.max_signal = 5,
-		.muxval = 2,
-		.periph_buses = PL08X_AHB2,
-	}, {
-		.bus_id = "ext3_rx",
-		.min_signal = 6,
-		.max_signal = 6,
-		.muxval = 2,
-		.periph_buses = PL08X_AHB2,
-	}, {
-		.bus_id = "ext3_tx",
-		.min_signal = 7,
-		.max_signal = 7,
-		.muxval = 2,
-		.periph_buses = PL08X_AHB2,
-	}, {
-		.bus_id = "ext4_rx",
-		.min_signal = 8,
-		.max_signal = 8,
-		.muxval = 2,
-		.periph_buses = PL08X_AHB2,
-	}, {
-		.bus_id = "ext4_tx",
-		.min_signal = 9,
-		.max_signal = 9,
-		.muxval = 2,
-		.periph_buses = PL08X_AHB2,
-	}, {
-		.bus_id = "ext5_rx",
-		.min_signal = 10,
-		.max_signal = 10,
-		.muxval = 2,
-		.periph_buses = PL08X_AHB2,
-	}, {
-		.bus_id = "ext5_tx",
-		.min_signal = 11,
-		.max_signal = 11,
-		.muxval = 2,
-		.periph_buses = PL08X_AHB2,
-	}, {
-		.bus_id = "ext6_rx",
-		.min_signal = 12,
-		.max_signal = 12,
-		.muxval = 2,
-		.periph_buses = PL08X_AHB2,
-	}, {
-		.bus_id = "ext6_tx",
-		.min_signal = 13,
-		.max_signal = 13,
-		.muxval = 2,
-		.periph_buses = PL08X_AHB2,
-	}, {
-		.bus_id = "ext7_rx",
-		.min_signal = 14,
-		.max_signal = 14,
-		.muxval = 2,
-		.periph_buses = PL08X_AHB2,
-	}, {
-		.bus_id = "ext7_tx",
-		.min_signal = 15,
-		.max_signal = 15,
-		.muxval = 2,
-		.periph_buses = PL08X_AHB2,
-	},
-};
-
-struct pl08x_platform_data pl080_plat_data = {
-	.memcpy_channel = {
-		.bus_id = "memcpy",
-		.cctl_memcpy =
-			(PL080_BSIZE_16 << PL080_CONTROL_SB_SIZE_SHIFT | \
-			PL080_BSIZE_16 << PL080_CONTROL_DB_SIZE_SHIFT | \
-			PL080_WIDTH_32BIT << PL080_CONTROL_SWIDTH_SHIFT | \
-			PL080_WIDTH_32BIT << PL080_CONTROL_DWIDTH_SHIFT | \
-			PL080_CONTROL_PROT_BUFF | PL080_CONTROL_PROT_CACHE | \
-			PL080_CONTROL_PROT_SYS),
-	},
-	.lli_buses = PL08X_AHB1,
-	.mem_buses = PL08X_AHB1,
-	.get_signal = pl080_get_signal,
-	.put_signal = pl080_put_signal,
-	.slave_channels = spear600_dma_info,
-	.num_slave_channels = ARRAY_SIZE(spear600_dma_info),
-};
-
-/*
- * Following will create 16MB static virtual/physical mappings
- * PHYSICAL		VIRTUAL
- * 0xF0000000		0xF0000000
- * 0xF1000000		0xF1000000
- * 0xD0000000		0xFD000000
- * 0xFC000000		0xFC000000
- */
-struct map_desc spear6xx_io_desc[] __initdata = {
-	{
-		.virtual	= VA_SPEAR6XX_ML_CPU_BASE,
-		.pfn		= __phys_to_pfn(SPEAR6XX_ML_CPU_BASE),
-		.length		= 2 * SZ_16M,
-		.type		= MT_DEVICE
-	},	{
-		.virtual	= VA_SPEAR6XX_ICM1_BASE,
-		.pfn		= __phys_to_pfn(SPEAR6XX_ICM1_BASE),
-		.length		= SZ_16M,
-		.type		= MT_DEVICE
-	}, {
-		.virtual	= VA_SPEAR6XX_ICM3_SMI_CTRL_BASE,
-		.pfn		= __phys_to_pfn(SPEAR6XX_ICM3_SMI_CTRL_BASE),
-		.length		= SZ_16M,
-		.type		= MT_DEVICE
-	},
-};
-
-/* This will create static memory mapping for selected devices */
-void __init spear6xx_map_io(void)
-{
-	iotable_init(spear6xx_io_desc, ARRAY_SIZE(spear6xx_io_desc));
-}
-
-void __init spear6xx_timer_init(void)
-{
-	char pclk_name[] = "pll3_clk";
-	struct clk *gpt_clk, *pclk;
-
-	spear6xx_clk_init();
-
-	/* get the system timer clock */
-	gpt_clk = clk_get_sys("gpt0", NULL);
-	if (IS_ERR(gpt_clk)) {
-		pr_err("%s:couldn't get clk for gpt\n", __func__);
-		BUG();
-	}
-
-	/* get the suitable parent clock for timer*/
-	pclk = clk_get(NULL, pclk_name);
-	if (IS_ERR(pclk)) {
-		pr_err("%s:couldn't get %s as parent for gpt\n",
-				__func__, pclk_name);
-		BUG();
-	}
-
-	clk_set_parent(gpt_clk, pclk);
-	clk_put(gpt_clk);
-	clk_put(pclk);
-
-	spear_setup_of_timer();
-}
-
-/* Add auxdata to pass platform data */
-struct of_dev_auxdata spear6xx_auxdata_lookup[] __initdata = {
-	OF_DEV_AUXDATA("arm,pl080", SPEAR6XX_ICM3_DMA_BASE, NULL,
-			&pl080_plat_data),
-	{}
-};
-
-static void __init spear600_dt_init(void)
-{
-	of_platform_populate(NULL, of_default_bus_match_table,
-			spear6xx_auxdata_lookup, NULL);
-}
-
-static const char *spear600_dt_board_compat[] = {
-	"st,spear600",
-	NULL
-};
-
-DT_MACHINE_START(SPEAR600_DT, "ST SPEAr600 (Flattened Device Tree)")
-	.map_io		=	spear6xx_map_io,
-	.init_irq	=	irqchip_init,
-	.init_time	=	spear6xx_timer_init,
-	.init_machine	=	spear600_dt_init,
-	.restart	=	spear_restart,
-	.dt_compat	=	spear600_dt_board_compat,
-MACHINE_END
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
index d1c4893..661ba32 100644
--- a/arch/arm/mach-tegra/Kconfig
+++ b/arch/arm/mach-tegra/Kconfig
@@ -1,13 +1,28 @@
-if ARCH_TEGRA
+config ARCH_TEGRA
+	bool "NVIDIA Tegra" if ARCH_MULTI_V7
+	select ARCH_HAS_CPUFREQ
+	select ARCH_REQUIRE_GPIOLIB
+	select CLKDEV_LOOKUP
+	select CLKSRC_MMIO
+	select CLKSRC_OF
+	select COMMON_CLK
+	select GENERIC_CLOCKEVENTS
+	select HAVE_CLK
+	select HAVE_SMP
+	select MIGHT_HAVE_CACHE_L2X0
+	select SOC_BUS
+	select SPARSE_IRQ
+	select USE_OF
+	help
+	  This enables support for NVIDIA Tegra based systems.
 
-comment "NVIDIA Tegra options"
+menu "NVIDIA Tegra options"
+	depends on ARCH_TEGRA
 
 config ARCH_TEGRA_2x_SOC
 	bool "Enable support for Tegra20 family"
 	select ARCH_NEEDS_CPU_IDLE_COUPLED if SMP
 	select ARM_ERRATA_720789
-	select ARM_ERRATA_742230 if SMP
-	select ARM_ERRATA_751472
 	select ARM_ERRATA_754327 if SMP
 	select ARM_ERRATA_764369 if SMP
 	select ARM_GIC
@@ -18,16 +33,14 @@ config ARCH_TEGRA_2x_SOC
 	select PL310_ERRATA_727915 if CACHE_L2X0
 	select PL310_ERRATA_769419 if CACHE_L2X0
 	select USB_ARCH_HAS_EHCI if USB_SUPPORT
-	select USB_ULPI if USB
-	select USB_ULPI_VIEWPORT if USB_SUPPORT
+	select USB_ULPI if USB_PHY
+	select USB_ULPI_VIEWPORT if USB_PHY
 	help
 	  Support for NVIDIA Tegra AP20 and T20 processors, based on the
 	  ARM CortexA9MP CPU and the ARM PL310 L2 cache controller
 
 config ARCH_TEGRA_3x_SOC
 	bool "Enable support for Tegra30 family"
-	select ARM_ERRATA_743622
-	select ARM_ERRATA_751472
 	select ARM_ERRATA_754322
 	select ARM_ERRATA_764369 if SMP
 	select ARM_GIC
@@ -37,8 +50,8 @@ config ARCH_TEGRA_3x_SOC
 	select PINCTRL_TEGRA30
 	select PL310_ERRATA_769419 if CACHE_L2X0
 	select USB_ARCH_HAS_EHCI if USB_SUPPORT
-	select USB_ULPI if USB
-	select USB_ULPI_VIEWPORT if USB_SUPPORT
+	select USB_ULPI if USB_PHY
+	select USB_ULPI_VIEWPORT if USB_PHY
 	help
 	  Support for NVIDIA Tegra T30 processor family, based on the
 	  ARM CortexA9MP CPU and the ARM PL310 L2 cache controller
@@ -71,4 +84,4 @@ config TEGRA_AHB
 config TEGRA_EMC_SCALING_ENABLE
 	bool "Enable scaling the memory frequency"
 
-endif
+endmenu
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index f6b46ae..e40326d 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -10,6 +10,7 @@ obj-y					+= pm.o
 obj-y					+= reset.o
 obj-y					+= reset-handler.o
 obj-y					+= sleep.o
+obj-y					+= tegra.o
 obj-$(CONFIG_CPU_IDLE)			+= cpuidle.o
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= tegra20_speedo.o
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= tegra2_emc.o
@@ -27,9 +28,7 @@ obj-$(CONFIG_HOTPLUG_CPU)               += hotplug.o
 obj-$(CONFIG_CPU_FREQ)                  += cpu-tegra.o
 obj-$(CONFIG_TEGRA_PCI)			+= pcie.o
 
-obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= board-dt-tegra20.o
-obj-$(CONFIG_ARCH_TEGRA_3x_SOC)		+= board-dt-tegra30.o
-obj-$(CONFIG_ARCH_TEGRA_114_SOC)	+= board-dt-tegra114.o
+obj-$(CONFIG_ARCH_TEGRA_114_SOC)	+= tegra114_speedo.o
 ifeq ($(CONFIG_CPU_IDLE),y)
 obj-$(CONFIG_ARCH_TEGRA_114_SOC)	+= cpuidle-tegra114.o
 endif
diff --git a/arch/arm/mach-tegra/Makefile.boot b/arch/arm/mach-tegra/Makefile.boot
deleted file mode 100644
index 2943381..0000000
--- a/arch/arm/mach-tegra/Makefile.boot
+++ /dev/null
@@ -1,3 +0,0 @@
-zreladdr-$(CONFIG_ARCH_TEGRA_2x_SOC)	+= 0x00008000
-params_phys-$(CONFIG_ARCH_TEGRA_2x_SOC)	:= 0x00000100
-initrd_phys-$(CONFIG_ARCH_TEGRA_2x_SOC)	:= 0x00800000
diff --git a/arch/arm/mach-tegra/board-dt-tegra114.c b/arch/arm/mach-tegra/board-dt-tegra114.c
deleted file mode 100644
index 085d636..0000000
--- a/arch/arm/mach-tegra/board-dt-tegra114.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * NVIDIA Tegra114 device tree board support
- *
- * Copyright (C) 2013 NVIDIA Corporation
- *
- * 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/of.h>
-#include <linux/of_platform.h>
-#include <linux/clocksource.h>
-
-#include <asm/mach/arch.h>
-
-#include "board.h"
-#include "common.h"
-
-static void __init tegra114_dt_init(void)
-{
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-}
-
-static const char * const tegra114_dt_board_compat[] = {
-	"nvidia,tegra114",
-	NULL,
-};
-
-DT_MACHINE_START(TEGRA114_DT, "NVIDIA Tegra114 (Flattened Device Tree)")
-	.smp		= smp_ops(tegra_smp_ops),
-	.map_io		= tegra_map_common_io,
-	.init_early	= tegra114_init_early,
-	.init_irq	= tegra_dt_init_irq,
-	.init_time	= clocksource_of_init,
-	.init_machine	= tegra114_dt_init,
-	.init_late	= tegra_init_late,
-	.restart	= tegra_assert_system_reset,
-	.dt_compat	= tegra114_dt_board_compat,
-MACHINE_END
diff --git a/arch/arm/mach-tegra/board-dt-tegra20.c b/arch/arm/mach-tegra/board-dt-tegra20.c
deleted file mode 100644
index a0edf25..0000000
--- a/arch/arm/mach-tegra/board-dt-tegra20.c
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * nVidia Tegra device tree board support
- *
- * Copyright (C) 2010 Secret Lab Technologies, Ltd.
- * Copyright (C) 2010 Google, 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.
- *
- */
-
-#include <linux/clocksource.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/serial_8250.h>
-#include <linux/clk.h>
-#include <linux/dma-mapping.h>
-#include <linux/irqdomain.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_fdt.h>
-#include <linux/of_platform.h>
-#include <linux/pda_power.h>
-#include <linux/platform_data/tegra_usb.h>
-#include <linux/io.h>
-#include <linux/i2c.h>
-#include <linux/i2c-tegra.h>
-#include <linux/usb/tegra_usb_phy.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-#include <asm/setup.h>
-
-#include "board.h"
-#include "common.h"
-#include "iomap.h"
-
-static struct tegra_ehci_platform_data tegra_ehci1_pdata = {
-	.operating_mode = TEGRA_USB_OTG,
-	.power_down_on_bus_suspend = 1,
-	.vbus_gpio = -1,
-};
-
-static struct tegra_ulpi_config tegra_ehci2_ulpi_phy_config = {
-	.reset_gpio = -1,
-	.clk = "cdev2",
-};
-
-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,
-	.vbus_gpio = -1,
-};
-
-static struct tegra_ehci_platform_data tegra_ehci3_pdata = {
-	.operating_mode = TEGRA_USB_HOST,
-	.power_down_on_bus_suspend = 1,
-	.vbus_gpio = -1,
-};
-
-static struct of_dev_auxdata tegra20_auxdata_lookup[] __initdata = {
-	OF_DEV_AUXDATA("nvidia,tegra20-ehci", 0xC5000000, "tegra-ehci.0",
-		       &tegra_ehci1_pdata),
-	OF_DEV_AUXDATA("nvidia,tegra20-ehci", 0xC5004000, "tegra-ehci.1",
-		       &tegra_ehci2_pdata),
-	OF_DEV_AUXDATA("nvidia,tegra20-ehci", 0xC5008000, "tegra-ehci.2",
-		       &tegra_ehci3_pdata),
-	{}
-};
-
-static void __init tegra_dt_init(void)
-{
-	/*
-	 * Finished with the static registrations now; fill in the missing
-	 * devices
-	 */
-	of_platform_populate(NULL, of_default_bus_match_table,
-				tegra20_auxdata_lookup, NULL);
-}
-
-static void __init trimslice_init(void)
-{
-#ifdef CONFIG_TEGRA_PCI
-	int ret;
-
-	ret = tegra_pcie_init(true, true);
-	if (ret)
-		pr_err("tegra_pci_init() failed: %d\n", ret);
-#endif
-}
-
-static void __init harmony_init(void)
-{
-#ifdef CONFIG_TEGRA_PCI
-	int ret;
-
-	ret = harmony_pcie_init();
-	if (ret)
-		pr_err("harmony_pcie_init() failed: %d\n", ret);
-#endif
-}
-
-static void __init paz00_init(void)
-{
-	tegra_paz00_wifikill_init();
-}
-
-static struct {
-	char *machine;
-	void (*init)(void);
-} board_init_funcs[] = {
-	{ "compulab,trimslice", trimslice_init },
-	{ "nvidia,harmony", harmony_init },
-	{ "compal,paz00", paz00_init },
-};
-
-static void __init tegra_dt_init_late(void)
-{
-	int i;
-
-	tegra_init_late();
-
-	for (i = 0; i < ARRAY_SIZE(board_init_funcs); i++) {
-		if (of_machine_is_compatible(board_init_funcs[i].machine)) {
-			board_init_funcs[i].init();
-			break;
-		}
-	}
-}
-
-static const char *tegra20_dt_board_compat[] = {
-	"nvidia,tegra20",
-	NULL
-};
-
-DT_MACHINE_START(TEGRA_DT, "nVidia Tegra20 (Flattened Device Tree)")
-	.map_io		= tegra_map_common_io,
-	.smp		= smp_ops(tegra_smp_ops),
-	.init_early	= tegra20_init_early,
-	.init_irq	= tegra_dt_init_irq,
-	.init_time	= clocksource_of_init,
-	.init_machine	= tegra_dt_init,
-	.init_late	= tegra_dt_init_late,
-	.restart	= tegra_assert_system_reset,
-	.dt_compat	= tegra20_dt_board_compat,
-MACHINE_END
diff --git a/arch/arm/mach-tegra/board-dt-tegra30.c b/arch/arm/mach-tegra/board-dt-tegra30.c
deleted file mode 100644
index bf68567..0000000
--- a/arch/arm/mach-tegra/board-dt-tegra30.c
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * arch/arm/mach-tegra/board-dt-tegra30.c
- *
- * NVIDIA Tegra30 device tree board support
- *
- * Copyright (C) 2011 NVIDIA Corporation
- *
- * Derived from:
- *
- * arch/arm/mach-tegra/board-dt-tegra20.c
- *
- * Copyright (C) 2010 Secret Lab Technologies, Ltd.
- * Copyright (C) 2010 Google, 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.
- *
- */
-
-#include <linux/clocksource.h>
-#include <linux/kernel.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_fdt.h>
-#include <linux/of_irq.h>
-#include <linux/of_platform.h>
-
-#include <asm/mach/arch.h>
-
-#include "board.h"
-#include "common.h"
-#include "iomap.h"
-
-static void __init tegra30_dt_init(void)
-{
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-}
-
-static const char *tegra30_dt_board_compat[] = {
-	"nvidia,tegra30",
-	NULL
-};
-
-DT_MACHINE_START(TEGRA30_DT, "NVIDIA Tegra30 (Flattened Device Tree)")
-	.smp		= smp_ops(tegra_smp_ops),
-	.map_io		= tegra_map_common_io,
-	.init_early	= tegra30_init_early,
-	.init_irq	= tegra_dt_init_irq,
-	.init_time	= clocksource_of_init,
-	.init_machine	= tegra30_dt_init,
-	.init_late	= tegra_init_late,
-	.restart	= tegra_assert_system_reset,
-	.dt_compat	= tegra30_dt_board_compat,
-MACHINE_END
diff --git a/arch/arm/mach-tegra/board-harmony-pcie.c b/arch/arm/mach-tegra/board-harmony-pcie.c
index 3cdc1bb..035b240 100644
--- a/arch/arm/mach-tegra/board-harmony-pcie.c
+++ b/arch/arm/mach-tegra/board-harmony-pcie.c
@@ -56,13 +56,17 @@ int __init harmony_pcie_init(void)
 	gpio_direction_output(en_vdd_1v05, 1);
 
 	regulator = regulator_get(NULL, "vdd_ldo0,vddio_pex_clk");
-	if (IS_ERR_OR_NULL(regulator)) {
-		pr_err("%s: regulator_get failed: %d\n", __func__,
-		       (int)PTR_ERR(regulator));
+	if (IS_ERR(regulator)) {
+		err = PTR_ERR(regulator);
+		pr_err("%s: regulator_get failed: %d\n", __func__, err);
 		goto err_reg;
 	}
 
-	regulator_enable(regulator);
+	err = regulator_enable(regulator);
+	if (err) {
+		pr_err("%s: regulator_enable failed: %d\n", __func__, err);
+		goto err_en;
+	}
 
 	err = tegra_pcie_init(true, true);
 	if (err) {
@@ -74,6 +78,7 @@ int __init harmony_pcie_init(void)
 
 err_pcie:
 	regulator_disable(regulator);
+err_en:
 	regulator_put(regulator);
 err_reg:
 	gpio_free(en_vdd_1v05);
diff --git a/arch/arm/mach-tegra/board.h b/arch/arm/mach-tegra/board.h
index 86851c8..1787327 100644
--- a/arch/arm/mach-tegra/board.h
+++ b/arch/arm/mach-tegra/board.h
@@ -26,9 +26,7 @@
 
 void tegra_assert_system_reset(char mode, const char *cmd);
 
-void __init tegra20_init_early(void);
-void __init tegra30_init_early(void);
-void __init tegra114_init_early(void);
+void __init tegra_init_early(void);
 void __init tegra_map_common_io(void);
 void __init tegra_init_irq(void);
 void __init tegra_dt_init_irq(void);
@@ -42,6 +40,7 @@ int tegra_clk_debugfs_init(void);
 static inline int tegra_clk_debugfs_init(void) { return 0; }
 #endif
 
+int __init tegra_powergate_init(void);
 #if defined(CONFIG_ARCH_TEGRA_2x_SOC) && defined(CONFIG_DEBUG_FS)
 int __init tegra_powergate_debugfs_init(void);
 #else
diff --git a/arch/arm/mach-tegra/common.c b/arch/arm/mach-tegra/common.c
index 5449a3f..9f852c6 100644
--- a/arch/arm/mach-tegra/common.c
+++ b/arch/arm/mach-tegra/common.c
@@ -27,12 +27,11 @@
 
 #include <asm/hardware/cache-l2x0.h>
 
-#include <mach/powergate.h>
-
 #include "board.h"
 #include "common.h"
 #include "fuse.h"
 #include "iomap.h"
+#include "irq.h"
 #include "pmc.h"
 #include "apbio.h"
 #include "sleep.h"
@@ -61,8 +60,10 @@ u32 tegra_uart_config[4] = {
 void __init tegra_dt_init_irq(void)
 {
 	tegra_clocks_init();
+	tegra_pmc_init();
 	tegra_init_irq();
 	irqchip_init();
+	tegra_legacy_irq_syscore_init();
 }
 #endif
 
@@ -94,40 +95,18 @@ static void __init tegra_init_cache(void)
 
 }
 
-static void __init tegra_init_early(void)
+void __init tegra_init_early(void)
 {
 	tegra_cpu_reset_handler_init();
 	tegra_apb_io_init();
 	tegra_init_fuse();
 	tegra_init_cache();
-	tegra_pmc_init();
 	tegra_powergate_init();
+	tegra_hotplug_init();
 }
 
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
-void __init tegra20_init_early(void)
-{
-	tegra_init_early();
-	tegra20_hotplug_init();
-}
-#endif
-
-#ifdef CONFIG_ARCH_TEGRA_3x_SOC
-void __init tegra30_init_early(void)
-{
-	tegra_init_early();
-	tegra30_hotplug_init();
-}
-#endif
-
-#ifdef CONFIG_ARCH_TEGRA_114_SOC
-void __init tegra114_init_early(void)
-{
-	tegra_init_early();
-}
-#endif
-
 void __init tegra_init_late(void)
 {
+	tegra_init_suspend();
 	tegra_powergate_debugfs_init();
 }
diff --git a/arch/arm/mach-tegra/cpu-tegra.c b/arch/arm/mach-tegra/cpu-tegra.c
index e3d6e15..11ca730 100644
--- a/arch/arm/mach-tegra/cpu-tegra.c
+++ b/arch/arm/mach-tegra/cpu-tegra.c
@@ -106,7 +106,8 @@ out:
 	return ret;
 }
 
-static int tegra_update_cpu_speed(unsigned long rate)
+static int tegra_update_cpu_speed(struct cpufreq_policy *policy,
+		unsigned long rate)
 {
 	int ret = 0;
 	struct cpufreq_freqs freqs;
@@ -128,8 +129,7 @@ static int tegra_update_cpu_speed(unsigned long rate)
 	else
 		clk_set_rate(emc_clk, 100000000);  /* emc 50Mhz */
 
-	for_each_online_cpu(freqs.cpu)
-		cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
 
 #ifdef CONFIG_CPU_FREQ_DEBUG
 	printk(KERN_DEBUG "cpufreq-tegra: transition: %u --> %u\n",
@@ -143,8 +143,7 @@ static int tegra_update_cpu_speed(unsigned long rate)
 		return ret;
 	}
 
-	for_each_online_cpu(freqs.cpu)
-		cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
 
 	return 0;
 }
@@ -181,7 +180,7 @@ static int tegra_target(struct cpufreq_policy *policy,
 
 	target_cpu_speed[policy->cpu] = freq;
 
-	ret = tegra_update_cpu_speed(tegra_cpu_highest_speed());
+	ret = tegra_update_cpu_speed(policy, tegra_cpu_highest_speed());
 
 out:
 	mutex_unlock(&tegra_cpu_lock);
@@ -193,10 +192,12 @@ static int tegra_pm_notify(struct notifier_block *nb, unsigned long event,
 {
 	mutex_lock(&tegra_cpu_lock);
 	if (event == PM_SUSPEND_PREPARE) {
+		struct cpufreq_policy *policy = cpufreq_cpu_get(0);
 		is_suspended = true;
 		pr_info("Tegra cpufreq suspend: setting frequency to %d kHz\n",
 			freq_table[0].frequency);
-		tegra_update_cpu_speed(freq_table[0].frequency);
+		tegra_update_cpu_speed(policy, freq_table[0].frequency);
+		cpufreq_cpu_put(policy);
 	} else if (event == PM_POST_SUSPEND) {
 		is_suspended = false;
 	}
diff --git a/arch/arm/mach-tegra/cpuidle-tegra20.c b/arch/arm/mach-tegra/cpuidle-tegra20.c
index 825ced4..8bbbdeb 100644
--- a/arch/arm/mach-tegra/cpuidle-tegra20.c
+++ b/arch/arm/mach-tegra/cpuidle-tegra20.c
@@ -130,10 +130,6 @@ static bool tegra20_cpu_cluster_power_down(struct cpuidle_device *dev,
 					   struct cpuidle_driver *drv,
 					   int index)
 {
-	struct cpuidle_state *state = &drv->states[index];
-	u32 cpu_on_time = state->exit_latency;
-	u32 cpu_off_time = state->target_residency - state->exit_latency;
-
 	while (tegra20_cpu_is_resettable_soon())
 		cpu_relax();
 
@@ -142,7 +138,7 @@ static bool tegra20_cpu_cluster_power_down(struct cpuidle_device *dev,
 
 	clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu);
 
-	tegra_idle_lp2_last(cpu_on_time, cpu_off_time);
+	tegra_idle_lp2_last();
 
 	clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu);
 
diff --git a/arch/arm/mach-tegra/cpuidle-tegra30.c b/arch/arm/mach-tegra/cpuidle-tegra30.c
index 8b50cf4..c0931c8 100644
--- a/arch/arm/mach-tegra/cpuidle-tegra30.c
+++ b/arch/arm/mach-tegra/cpuidle-tegra30.c
@@ -72,10 +72,6 @@ static bool tegra30_cpu_cluster_power_down(struct cpuidle_device *dev,
 					   struct cpuidle_driver *drv,
 					   int index)
 {
-	struct cpuidle_state *state = &drv->states[index];
-	u32 cpu_on_time = state->exit_latency;
-	u32 cpu_off_time = state->target_residency - state->exit_latency;
-
 	/* All CPUs entering LP2 is not working.
 	 * Don't let CPU0 enter LP2 when any secondary CPU is online.
 	 */
@@ -86,7 +82,7 @@ static bool tegra30_cpu_cluster_power_down(struct cpuidle_device *dev,
 
 	clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu);
 
-	tegra_idle_lp2_last(cpu_on_time, cpu_off_time);
+	tegra_idle_lp2_last();
 
 	clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu);
 
@@ -102,12 +98,8 @@ static bool tegra30_cpu_core_power_down(struct cpuidle_device *dev,
 
 	smp_wmb();
 
-	save_cpu_arch_register();
-
 	cpu_suspend(0, tegra30_sleep_cpu_secondary_finish);
 
-	restore_cpu_arch_register();
-
 	clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu);
 
 	return true;
diff --git a/arch/arm/mach-tegra/fuse.c b/arch/arm/mach-tegra/fuse.c
index f7db078..e035cd2 100644
--- a/arch/arm/mach-tegra/fuse.c
+++ b/arch/arm/mach-tegra/fuse.c
@@ -2,6 +2,7 @@
  * arch/arm/mach-tegra/fuse.c
  *
  * Copyright (C) 2010 Google, Inc.
+ * Copyright (c) 2013, NVIDIA CORPORATION.  All rights reserved.
  *
  * Author:
  *	Colin Cross <ccross@android.com>
@@ -137,6 +138,9 @@ void tegra_init_fuse(void)
 		tegra_fuse_spare_bit = TEGRA30_FUSE_SPARE_BIT;
 		tegra_init_speedo_data = &tegra30_init_speedo_data;
 		break;
+	case TEGRA114:
+		tegra_init_speedo_data = &tegra114_init_speedo_data;
+		break;
 	default:
 		pr_warn("Tegra: unknown chip id %d\n", tegra_chip_id);
 		tegra_fuse_spare_bit = TEGRA20_FUSE_SPARE_BIT;
diff --git a/arch/arm/mach-tegra/fuse.h b/arch/arm/mach-tegra/fuse.h
index da78434..aacc00d 100644
--- a/arch/arm/mach-tegra/fuse.h
+++ b/arch/arm/mach-tegra/fuse.h
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2010 Google, Inc.
+ * Copyright (c) 2013, NVIDIA CORPORATION.  All rights reserved.
  *
  * Author:
  *	Colin Cross <ccross@android.com>
@@ -66,4 +67,10 @@ void tegra30_init_speedo_data(void);
 static inline void tegra30_init_speedo_data(void) {}
 #endif
 
+#ifdef CONFIG_ARCH_TEGRA_114_SOC
+void tegra114_init_speedo_data(void);
+#else
+static inline void tegra114_init_speedo_data(void) {}
+#endif
+
 #endif
diff --git a/arch/arm/mach-tegra/headsmp.S b/arch/arm/mach-tegra/headsmp.S
index fd473f2..045c16f 100644
--- a/arch/arm/mach-tegra/headsmp.S
+++ b/arch/arm/mach-tegra/headsmp.S
@@ -7,8 +7,5 @@
 
 ENTRY(tegra_secondary_startup)
         bl      v7_invalidate_l1
-	/* Enable coresight */
-	mov32	r0, 0xC5ACCE55
-	mcr	p14, 0, r0, c7, c12, 6
         b       secondary_startup
 ENDPROC(tegra_secondary_startup)
diff --git a/arch/arm/mach-tegra/hotplug.c b/arch/arm/mach-tegra/hotplug.c
index a599f6e..8da9f78 100644
--- a/arch/arm/mach-tegra/hotplug.c
+++ b/arch/arm/mach-tegra/hotplug.c
@@ -1,8 +1,7 @@
 /*
- *
  *  Copyright (C) 2002 ARM Ltd.
  *  All Rights Reserved
- *  Copyright (c) 2010, 2012 NVIDIA Corporation. All rights reserved.
+ *  Copyright (c) 2010, 2012-2013, NVIDIA Corporation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -15,6 +14,7 @@
 #include <asm/cacheflush.h>
 #include <asm/smp_plat.h>
 
+#include "fuse.h"
 #include "sleep.h"
 
 static void (*tegra_hotplug_shutdown)(void);
@@ -56,18 +56,13 @@ int tegra_cpu_disable(unsigned int cpu)
 	return cpu == 0 ? -EPERM : 0;
 }
 
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
-extern void tegra20_hotplug_shutdown(void);
-void __init tegra20_hotplug_init(void)
+void __init tegra_hotplug_init(void)
 {
-	tegra_hotplug_shutdown = tegra20_hotplug_shutdown;
-}
-#endif
+	if (!IS_ENABLED(CONFIG_HOTPLUG_CPU))
+		return;
 
-#ifdef CONFIG_ARCH_TEGRA_3x_SOC
-extern void tegra30_hotplug_shutdown(void);
-void __init tegra30_hotplug_init(void)
-{
-	tegra_hotplug_shutdown = tegra30_hotplug_shutdown;
+	if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) && tegra_chip_id == TEGRA20)
+		tegra_hotplug_shutdown = tegra20_hotplug_shutdown;
+	if (IS_ENABLED(CONFIG_ARCH_TEGRA_3x_SOC) && tegra_chip_id == TEGRA30)
+		tegra_hotplug_shutdown = tegra30_hotplug_shutdown;
 }
-#endif
diff --git a/arch/arm/mach-tegra/include/mach/powergate.h b/arch/arm/mach-tegra/include/mach/powergate.h
deleted file mode 100644
index 06763fe..0000000
--- a/arch/arm/mach-tegra/include/mach/powergate.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * drivers/regulator/tegra-regulator.c
- *
- * 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_TEGRA_POWERGATE_H_
-#define _MACH_TEGRA_POWERGATE_H_
-
-struct clk;
-
-#define TEGRA_POWERGATE_CPU	0
-#define TEGRA_POWERGATE_3D	1
-#define TEGRA_POWERGATE_VENC	2
-#define TEGRA_POWERGATE_PCIE	3
-#define TEGRA_POWERGATE_VDEC	4
-#define TEGRA_POWERGATE_L2	5
-#define TEGRA_POWERGATE_MPE	6
-#define TEGRA_POWERGATE_HEG	7
-#define TEGRA_POWERGATE_SATA	8
-#define TEGRA_POWERGATE_CPU1	9
-#define TEGRA_POWERGATE_CPU2	10
-#define TEGRA_POWERGATE_CPU3	11
-#define TEGRA_POWERGATE_CELP	12
-#define TEGRA_POWERGATE_3D1	13
-
-#define TEGRA_POWERGATE_CPU0	TEGRA_POWERGATE_CPU
-#define TEGRA_POWERGATE_3D0	TEGRA_POWERGATE_3D
-
-int  __init tegra_powergate_init(void);
-
-int tegra_cpu_powergate_id(int cpuid);
-int tegra_powergate_is_powered(int id);
-int tegra_powergate_power_on(int id);
-int tegra_powergate_power_off(int id);
-int tegra_powergate_remove_clamping(int id);
-
-/* Must be called with clk disabled, and returns with clk enabled */
-int tegra_powergate_sequence_power_up(int id, struct clk *clk);
-
-#endif /* _MACH_TEGRA_POWERGATE_H_ */
diff --git a/arch/arm/mach-tegra/include/mach/timex.h b/arch/arm/mach-tegra/include/mach/timex.h
deleted file mode 100644
index a44ccbd..0000000
--- a/arch/arm/mach-tegra/include/mach/timex.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * arch/arm/mach-tegra/include/mach/timex.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_TIMEX_H
-#define __MACH_TEGRA_TIMEX_H
-
-#define CLOCK_TICK_RATE		1000000
-
-#endif
diff --git a/arch/arm/mach-tegra/include/mach/uncompress.h b/arch/arm/mach-tegra/include/mach/uncompress.h
deleted file mode 100644
index 0838641..0000000
--- a/arch/arm/mach-tegra/include/mach/uncompress.h
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * arch/arm/mach-tegra/include/mach/uncompress.h
- *
- * Copyright (C) 2010 Google, Inc.
- * Copyright (C) 2011 Google, Inc.
- * Copyright (C) 2011-2012 NVIDIA CORPORATION. All Rights Reserved.
- *
- * Author:
- *	Colin Cross <ccross@google.com>
- *	Erik Gilling <konkers@google.com>
- *	Doug Anderson <dianders@chromium.org>
- *	Stephen Warren <swarren@nvidia.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_UNCOMPRESS_H
-#define __MACH_TEGRA_UNCOMPRESS_H
-
-#include <linux/types.h>
-#include <linux/serial_reg.h>
-
-#include "../../iomap.h"
-
-#define BIT(x) (1 << (x))
-#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
-
-#define DEBUG_UART_SHIFT 2
-
-volatile u8 *uart;
-
-static void putc(int c)
-{
-	if (uart == NULL)
-		return;
-
-	while (!(uart[UART_LSR << DEBUG_UART_SHIFT] & UART_LSR_THRE))
-		barrier();
-	uart[UART_TX << DEBUG_UART_SHIFT] = c;
-}
-
-static inline void flush(void)
-{
-}
-
-static const struct {
-	u32 base;
-	u32 reset_reg;
-	u32 clock_reg;
-	u32 bit;
-} uarts[] = {
-	{
-		TEGRA_UARTA_BASE,
-		TEGRA_CLK_RESET_BASE + 0x04,
-		TEGRA_CLK_RESET_BASE + 0x10,
-		6,
-	},
-	{
-		TEGRA_UARTB_BASE,
-		TEGRA_CLK_RESET_BASE + 0x04,
-		TEGRA_CLK_RESET_BASE + 0x10,
-		7,
-	},
-	{
-		TEGRA_UARTC_BASE,
-		TEGRA_CLK_RESET_BASE + 0x08,
-		TEGRA_CLK_RESET_BASE + 0x14,
-		23,
-	},
-	{
-		TEGRA_UARTD_BASE,
-		TEGRA_CLK_RESET_BASE + 0x0c,
-		TEGRA_CLK_RESET_BASE + 0x18,
-		1,
-	},
-	{
-		TEGRA_UARTE_BASE,
-		TEGRA_CLK_RESET_BASE + 0x0c,
-		TEGRA_CLK_RESET_BASE + 0x18,
-		2,
-	},
-};
-
-static inline bool uart_clocked(int i)
-{
-	if (*(u8 *)uarts[i].reset_reg & BIT(uarts[i].bit))
-		return false;
-
-	if (!(*(u8 *)uarts[i].clock_reg & BIT(uarts[i].bit)))
-		return false;
-
-	return true;
-}
-
-#ifdef CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA
-int auto_odmdata(void)
-{
-	volatile u32 *pmc = (volatile u32 *)TEGRA_PMC_BASE;
-	u32 odmdata = pmc[0xa0 / 4];
-
-	/*
-	 * Bits 19:18 are the console type: 0=default, 1=none, 2==DCC, 3==UART
-	 * Some boards apparently swap the last two values, but we don't have
-	 * any way of catering for that here, so we just accept either. If this
-	 * doesn't make sense for your board, just don't enable this feature.
-	 *
-	 * Bits 17:15 indicate the UART to use, 0/1/2/3/4 are UART A/B/C/D/E.
-	 */
-
-	switch  ((odmdata >> 18) & 3) {
-	case 2:
-	case 3:
-		break;
-	default:
-		return -1;
-	}
-
-	return (odmdata >> 15) & 7;
-}
-#endif
-
-/*
- * Setup before decompression.  This is where we do UART selection for
- * earlyprintk and init the uart_base register.
- */
-static inline void arch_decomp_setup(void)
-{
-	int uart_id;
-	volatile u32 *apb_misc = (volatile u32 *)TEGRA_APB_MISC_BASE;
-	u32 chip, div;
-
-#if defined(CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA)
-	uart_id = auto_odmdata();
-#elif defined(CONFIG_TEGRA_DEBUG_UARTA)
-	uart_id = 0;
-#elif defined(CONFIG_TEGRA_DEBUG_UARTB)
-	uart_id = 1;
-#elif defined(CONFIG_TEGRA_DEBUG_UARTC)
-	uart_id = 2;
-#elif defined(CONFIG_TEGRA_DEBUG_UARTD)
-	uart_id = 3;
-#elif defined(CONFIG_TEGRA_DEBUG_UARTE)
-	uart_id = 4;
-#endif
-
-	if (uart_id < 0 || uart_id >= ARRAY_SIZE(uarts) ||
-	    !uart_clocked(uart_id))
-		uart = NULL;
-	else
-		uart = (volatile u8 *)uarts[uart_id].base;
-
-	if (uart == NULL)
-		return;
-
-	chip = (apb_misc[0x804 / 4] >> 8) & 0xff;
-	if (chip == 0x20)
-		div = 0x0075;
-	else
-		div = 0x00dd;
-
-	uart[UART_LCR << DEBUG_UART_SHIFT] |= UART_LCR_DLAB;
-	uart[UART_DLL << DEBUG_UART_SHIFT] = div & 0xff;
-	uart[UART_DLM << DEBUG_UART_SHIFT] = div >> 8;
-	uart[UART_LCR << DEBUG_UART_SHIFT] = 3;
-}
-
-#endif
diff --git a/arch/arm/mach-tegra/irq.c b/arch/arm/mach-tegra/irq.c
index 1952e82..0de4eed 100644
--- a/arch/arm/mach-tegra/irq.c
+++ b/arch/arm/mach-tegra/irq.c
@@ -4,7 +4,7 @@
  * Author:
  *	Colin Cross <ccross@android.com>
  *
- * Copyright (C) 2010, NVIDIA Corporation
+ * Copyright (C) 2010,2013, NVIDIA Corporation
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -23,6 +23,7 @@
 #include <linux/io.h>
 #include <linux/of.h>
 #include <linux/irqchip/arm-gic.h>
+#include <linux/syscore_ops.h>
 
 #include "board.h"
 #include "iomap.h"
@@ -43,6 +44,7 @@
 #define ICTLR_COP_IEP_CLASS	0x3c
 
 #define FIRST_LEGACY_IRQ 32
+#define TEGRA_MAX_NUM_ICTLRS	5
 
 #define SGI_MASK 0xFFFF
 
@@ -56,6 +58,15 @@ static void __iomem *ictlr_reg_base[] = {
 	IO_ADDRESS(TEGRA_QUINARY_ICTLR_BASE),
 };
 
+#ifdef CONFIG_PM_SLEEP
+static u32 cop_ier[TEGRA_MAX_NUM_ICTLRS];
+static u32 cop_iep[TEGRA_MAX_NUM_ICTLRS];
+static u32 cpu_ier[TEGRA_MAX_NUM_ICTLRS];
+static u32 cpu_iep[TEGRA_MAX_NUM_ICTLRS];
+
+static u32 ictlr_wake_mask[TEGRA_MAX_NUM_ICTLRS];
+#endif
+
 bool tegra_pending_sgi(void)
 {
 	u32 pending_set;
@@ -125,6 +136,87 @@ static int tegra_retrigger(struct irq_data *d)
 	return 1;
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int tegra_set_wake(struct irq_data *d, unsigned int enable)
+{
+	u32 irq = d->irq;
+	u32 index, mask;
+
+	if (irq < FIRST_LEGACY_IRQ ||
+		irq >= FIRST_LEGACY_IRQ + num_ictlrs * 32)
+		return -EINVAL;
+
+	index = ((irq - FIRST_LEGACY_IRQ) / 32);
+	mask = BIT((irq - FIRST_LEGACY_IRQ) % 32);
+	if (enable)
+		ictlr_wake_mask[index] |= mask;
+	else
+		ictlr_wake_mask[index] &= ~mask;
+
+	return 0;
+}
+
+static int tegra_legacy_irq_suspend(void)
+{
+	unsigned long flags;
+	int i;
+
+	local_irq_save(flags);
+	for (i = 0; i < num_ictlrs; i++) {
+		void __iomem *ictlr = ictlr_reg_base[i];
+		/* Save interrupt state */
+		cpu_ier[i] = readl_relaxed(ictlr + ICTLR_CPU_IER);
+		cpu_iep[i] = readl_relaxed(ictlr + ICTLR_CPU_IEP_CLASS);
+		cop_ier[i] = readl_relaxed(ictlr + ICTLR_COP_IER);
+		cop_iep[i] = readl_relaxed(ictlr + ICTLR_COP_IEP_CLASS);
+
+		/* Disable COP interrupts */
+		writel_relaxed(~0ul, ictlr + ICTLR_COP_IER_CLR);
+
+		/* Disable CPU interrupts */
+		writel_relaxed(~0ul, ictlr + ICTLR_CPU_IER_CLR);
+
+		/* Enable the wakeup sources of ictlr */
+		writel_relaxed(ictlr_wake_mask[i], ictlr + ICTLR_CPU_IER_SET);
+	}
+	local_irq_restore(flags);
+
+	return 0;
+}
+
+static void tegra_legacy_irq_resume(void)
+{
+	unsigned long flags;
+	int i;
+
+	local_irq_save(flags);
+	for (i = 0; i < num_ictlrs; i++) {
+		void __iomem *ictlr = ictlr_reg_base[i];
+		writel_relaxed(cpu_iep[i], ictlr + ICTLR_CPU_IEP_CLASS);
+		writel_relaxed(~0ul, ictlr + ICTLR_CPU_IER_CLR);
+		writel_relaxed(cpu_ier[i], ictlr + ICTLR_CPU_IER_SET);
+		writel_relaxed(cop_iep[i], ictlr + ICTLR_COP_IEP_CLASS);
+		writel_relaxed(~0ul, ictlr + ICTLR_COP_IER_CLR);
+		writel_relaxed(cop_ier[i], ictlr + ICTLR_COP_IER_SET);
+	}
+	local_irq_restore(flags);
+}
+
+static struct syscore_ops tegra_legacy_irq_syscore_ops = {
+	.suspend = tegra_legacy_irq_suspend,
+	.resume = tegra_legacy_irq_resume,
+};
+
+int tegra_legacy_irq_syscore_init(void)
+{
+	register_syscore_ops(&tegra_legacy_irq_syscore_ops);
+
+	return 0;
+}
+#else
+#define tegra_set_wake NULL
+#endif
+
 void __init tegra_init_irq(void)
 {
 	int i;
@@ -150,6 +242,8 @@ void __init tegra_init_irq(void)
 	gic_arch_extn.irq_mask = tegra_mask;
 	gic_arch_extn.irq_unmask = tegra_unmask;
 	gic_arch_extn.irq_retrigger = tegra_retrigger;
+	gic_arch_extn.irq_set_wake = tegra_set_wake;
+	gic_arch_extn.flags = IRQCHIP_MASK_ON_SUSPEND;
 
 	/*
 	 * Check if there is a devicetree present, since the GIC will be
diff --git a/arch/arm/mach-tegra/irq.h b/arch/arm/mach-tegra/irq.h
index 5142649..bc05ce5 100644
--- a/arch/arm/mach-tegra/irq.h
+++ b/arch/arm/mach-tegra/irq.h
@@ -19,4 +19,10 @@
 
 bool tegra_pending_sgi(void);
 
+#ifdef CONFIG_PM_SLEEP
+int tegra_legacy_irq_syscore_init(void);
+#else
+static inline int tegra_legacy_irq_syscore_init(void) { return 0; }
+#endif
+
 #endif
diff --git a/arch/arm/mach-tegra/pcie.c b/arch/arm/mach-tegra/pcie.c
index b60165f..46144a1 100644
--- a/arch/arm/mach-tegra/pcie.c
+++ b/arch/arm/mach-tegra/pcie.c
@@ -34,12 +34,11 @@
 #include <linux/delay.h>
 #include <linux/export.h>
 #include <linux/clk/tegra.h>
+#include <linux/tegra-powergate.h>
 
 #include <asm/sizes.h>
 #include <asm/mach/pci.h>
 
-#include <mach/powergate.h>
-
 #include "board.h"
 #include "iomap.h"
 
diff --git a/arch/arm/mach-tegra/platsmp.c b/arch/arm/mach-tegra/platsmp.c
index 2c6b3d5..0c4963b 100644
--- a/arch/arm/mach-tegra/platsmp.c
+++ b/arch/arm/mach-tegra/platsmp.c
@@ -18,7 +18,6 @@
 #include <linux/jiffies.h>
 #include <linux/smp.h>
 #include <linux/io.h>
-#include <linux/irqchip/arm-gic.h>
 #include <linux/clk/tegra.h>
 
 #include <asm/cacheflush.h>
@@ -26,53 +25,58 @@
 #include <asm/smp_scu.h>
 #include <asm/smp_plat.h>
 
-#include <mach/powergate.h>
-
 #include "fuse.h"
 #include "flowctrl.h"
 #include "reset.h"
+#include "pmc.h"
 
 #include "common.h"
 #include "iomap.h"
 
-extern void tegra_secondary_startup(void);
-
 static cpumask_t tegra_cpu_init_mask;
 
-#define EVP_CPU_RESET_VECTOR \
-	(IO_ADDRESS(TEGRA_EXCEPTION_VECTORS_BASE) + 0x100)
-
 static void __cpuinit tegra_secondary_init(unsigned int cpu)
 {
-	/*
-	 * if any interrupts are already enabled for the primary
-	 * core (e.g. timer irq), then they will not have been enabled
-	 * for us: do so
-	 */
-	gic_secondary_init(0);
-
 	cpumask_set_cpu(cpu, &tegra_cpu_init_mask);
 }
 
-static int tegra20_power_up_cpu(unsigned int cpu)
+
+static int tegra20_boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
-	/* Enable the CPU clock. */
-	tegra_enable_cpu_clock(cpu);
+	cpu = cpu_logical_map(cpu);
+
+	/*
+	 * Force the CPU into reset. The CPU must remain in reset when
+	 * the flow controller state is cleared (which will cause the
+	 * flow controller to stop driving reset if the CPU has been
+	 * power-gated via the flow controller). This will have no
+	 * effect on first boot of the CPU since it should already be
+	 * in reset.
+	 */
+	tegra_put_cpu_in_reset(cpu);
 
-	/* Clear flow controller CSR. */
-	flowctrl_write_cpu_csr(cpu, 0);
+	/*
+	 * Unhalt the CPU. If the flow controller was used to
+	 * power-gate the CPU this will cause the flow controller to
+	 * stop driving reset. The CPU will remain in reset because the
+	 * clock and reset block is now driving reset.
+	 */
+	flowctrl_write_cpu_halt(cpu, 0);
 
+	tegra_enable_cpu_clock(cpu);
+	flowctrl_write_cpu_csr(cpu, 0); /* Clear flow controller CSR. */
+	tegra_cpu_out_of_reset(cpu);
 	return 0;
 }
 
-static int tegra30_power_up_cpu(unsigned int cpu)
+static int tegra30_boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
-	int ret, pwrgateid;
+	int ret;
 	unsigned long timeout;
 
-	pwrgateid = tegra_cpu_powergate_id(cpu);
-	if (pwrgateid < 0)
-		return pwrgateid;
+	cpu = cpu_logical_map(cpu);
+	tegra_put_cpu_in_reset(cpu);
+	flowctrl_write_cpu_halt(cpu, 0);
 
 	/*
 	 * The power up sequence of cold boot CPU and warm boot CPU
@@ -85,13 +89,13 @@ static int tegra30_power_up_cpu(unsigned int cpu)
 	 * the IO clamps.
 	 * For cold boot CPU, do not wait. After the cold boot CPU be
 	 * booted, it will run to tegra_secondary_init() and set
-	 * tegra_cpu_init_mask which influences what tegra30_power_up_cpu()
+	 * tegra_cpu_init_mask which influences what tegra30_boot_secondary()
 	 * next time around.
 	 */
 	if (cpumask_test_cpu(cpu, &tegra_cpu_init_mask)) {
 		timeout = jiffies + msecs_to_jiffies(50);
 		do {
-			if (!tegra_powergate_is_powered(pwrgateid))
+			if (tegra_pmc_cpu_is_powered(cpu))
 				goto remove_clamps;
 			udelay(10);
 		} while (time_before(jiffies, timeout));
@@ -103,14 +107,14 @@ static int tegra30_power_up_cpu(unsigned int cpu)
 	 * be un-gated by un-toggling the power gate register
 	 * manually.
 	 */
-	if (!tegra_powergate_is_powered(pwrgateid)) {
-		ret = tegra_powergate_power_on(pwrgateid);
+	if (!tegra_pmc_cpu_is_powered(cpu)) {
+		ret = tegra_pmc_cpu_power_on(cpu);
 		if (ret)
 			return ret;
 
 		/* Wait for the power to come up. */
 		timeout = jiffies + msecs_to_jiffies(100);
-		while (tegra_powergate_is_powered(pwrgateid)) {
+		while (tegra_pmc_cpu_is_powered(cpu)) {
 			if (time_after(jiffies, timeout))
 				return -ETIMEDOUT;
 			udelay(10);
@@ -123,57 +127,34 @@ remove_clamps:
 	udelay(10);
 
 	/* Remove I/O clamps. */
-	ret = tegra_powergate_remove_clamping(pwrgateid);
-	udelay(10);
+	ret = tegra_pmc_cpu_remove_clamping(cpu);
+	if (ret)
+		return ret;
 
-	/* Clear flow controller CSR. */
-	flowctrl_write_cpu_csr(cpu, 0);
+	udelay(10);
 
+	flowctrl_write_cpu_csr(cpu, 0); /* Clear flow controller CSR. */
+	tegra_cpu_out_of_reset(cpu);
 	return 0;
 }
 
-static int __cpuinit tegra_boot_secondary(unsigned int cpu, struct task_struct *idle)
+static int tegra114_boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
-	int status;
-
 	cpu = cpu_logical_map(cpu);
+	return tegra_pmc_cpu_power_on(cpu);
+}
 
-	/*
-	 * Force the CPU into reset. The CPU must remain in reset when the
-	 * flow controller state is cleared (which will cause the flow
-	 * controller to stop driving reset if the CPU has been power-gated
-	 * via the flow controller). This will have no effect on first boot
-	 * of the CPU since it should already be in reset.
-	 */
-	tegra_put_cpu_in_reset(cpu);
-
-	/*
-	 * Unhalt the CPU. If the flow controller was used to power-gate the
-	 * CPU this will cause the flow controller to stop driving reset.
-	 * The CPU will remain in reset because the clock and reset block
-	 * is now driving reset.
-	 */
-	flowctrl_write_cpu_halt(cpu, 0);
-
-	switch (tegra_chip_id) {
-	case TEGRA20:
-		status = tegra20_power_up_cpu(cpu);
-		break;
-	case TEGRA30:
-		status = tegra30_power_up_cpu(cpu);
-		break;
-	default:
-		status = -EINVAL;
-		break;
-	}
-
-	if (status)
-		goto done;
-
-	/* Take the CPU out of reset. */
-	tegra_cpu_out_of_reset(cpu);
-done:
-	return status;
+static int __cpuinit tegra_boot_secondary(unsigned int cpu,
+					  struct task_struct *idle)
+{
+	if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) && tegra_chip_id == TEGRA20)
+		return tegra20_boot_secondary(cpu, idle);
+	if (IS_ENABLED(CONFIG_ARCH_TEGRA_3x_SOC) && tegra_chip_id == TEGRA30)
+		return tegra30_boot_secondary(cpu, idle);
+	if (IS_ENABLED(CONFIG_ARCH_TEGRA_114_SOC) && tegra_chip_id == TEGRA114)
+		return tegra114_boot_secondary(cpu, idle);
+
+	return -EINVAL;
 }
 
 static void __init tegra_smp_prepare_cpus(unsigned int max_cpus)
diff --git a/arch/arm/mach-tegra/pm.c b/arch/arm/mach-tegra/pm.c
index 523604d..6ce6beb 100644
--- a/arch/arm/mach-tegra/pm.c
+++ b/arch/arm/mach-tegra/pm.c
@@ -22,7 +22,7 @@
 #include <linux/cpumask.h>
 #include <linux/delay.h>
 #include <linux/cpu_pm.h>
-#include <linux/clk.h>
+#include <linux/suspend.h>
 #include <linux/err.h>
 #include <linux/clk/tegra.h>
 
@@ -37,67 +37,14 @@
 #include "reset.h"
 #include "flowctrl.h"
 #include "fuse.h"
+#include "pmc.h"
 #include "sleep.h"
-
-#define TEGRA_POWER_CPU_PWRREQ_OE	(1 << 16)  /* CPU pwr req enable */
-
-#define PMC_CTRL		0x0
-#define PMC_CPUPWRGOOD_TIMER	0xc8
-#define PMC_CPUPWROFF_TIMER	0xcc
+#include "pmc.h"
 
 #ifdef CONFIG_PM_SLEEP
-static unsigned int g_diag_reg;
 static DEFINE_SPINLOCK(tegra_lp2_lock);
-static void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE);
-static struct clk *tegra_pclk;
 void (*tegra_tear_down_cpu)(void);
 
-void save_cpu_arch_register(void)
-{
-	/* read diagnostic register */
-	asm("mrc p15, 0, %0, c15, c0, 1" : "=r"(g_diag_reg) : : "cc");
-	return;
-}
-
-void restore_cpu_arch_register(void)
-{
-	/* write diagnostic register */
-	asm("mcr p15, 0, %0, c15, c0, 1" : : "r"(g_diag_reg) : "cc");
-	return;
-}
-
-static void set_power_timers(unsigned long us_on, unsigned long us_off)
-{
-	unsigned long long ticks;
-	unsigned long long pclk;
-	unsigned long rate;
-	static unsigned long tegra_last_pclk;
-
-	if (tegra_pclk == NULL) {
-		tegra_pclk = clk_get_sys(NULL, "pclk");
-		WARN_ON(IS_ERR(tegra_pclk));
-	}
-
-	rate = clk_get_rate(tegra_pclk);
-
-	if (WARN_ON_ONCE(rate <= 0))
-		pclk = 100000000;
-	else
-		pclk = rate;
-
-	if ((rate != tegra_last_pclk)) {
-		ticks = (us_on * pclk) + 999999ull;
-		do_div(ticks, 1000000);
-		writel((unsigned long)ticks, pmc + PMC_CPUPWRGOOD_TIMER);
-
-		ticks = (us_off * pclk) + 999999ull;
-		do_div(ticks, 1000000);
-		writel((unsigned long)ticks, pmc + PMC_CPUPWROFF_TIMER);
-		wmb();
-	}
-	tegra_last_pclk = pclk;
-}
-
 /*
  * restore_cpu_complex
  *
@@ -119,8 +66,6 @@ static void restore_cpu_complex(void)
 	tegra_cpu_clock_resume();
 
 	flowctrl_cpu_suspend_exit(cpu);
-
-	restore_cpu_arch_register();
 }
 
 /*
@@ -145,8 +90,6 @@ static void suspend_cpu_complex(void)
 	tegra_cpu_clock_suspend();
 
 	flowctrl_cpu_suspend_enter(cpu);
-
-	save_cpu_arch_register();
 }
 
 void tegra_clear_cpu_in_lp2(int phy_cpu_id)
@@ -183,12 +126,7 @@ bool tegra_set_cpu_in_lp2(int phy_cpu_id)
 
 static int tegra_sleep_cpu(unsigned long v2p)
 {
-	/* Switch to the identity mapping. */
-	cpu_switch_mm(idmap_pgd, &init_mm);
-
-	/* Flush the TLB. */
-	local_flush_tlb_all();
-
+	setup_mm_for_reboot();
 	tegra_sleep_cpu_finish(v2p);
 
 	/* should never here */
@@ -197,16 +135,9 @@ static int tegra_sleep_cpu(unsigned long v2p)
 	return 0;
 }
 
-void tegra_idle_lp2_last(u32 cpu_on_time, u32 cpu_off_time)
+void tegra_idle_lp2_last(void)
 {
-	u32 mode;
-
-	/* Only the last cpu down does the final suspend steps */
-	mode = readl(pmc + PMC_CTRL);
-	mode |= TEGRA_POWER_CPU_PWRREQ_OE;
-	writel(mode, pmc + PMC_CTRL);
-
-	set_power_timers(cpu_on_time, cpu_off_time);
+	tegra_pmc_pm_set(TEGRA_SUSPEND_LP2);
 
 	cpu_cluster_pm_enter();
 	suspend_cpu_complex();
@@ -216,4 +147,81 @@ void tegra_idle_lp2_last(u32 cpu_on_time, u32 cpu_off_time)
 	restore_cpu_complex();
 	cpu_cluster_pm_exit();
 }
+
+enum tegra_suspend_mode tegra_pm_validate_suspend_mode(
+				enum tegra_suspend_mode mode)
+{
+	/* Tegra114 didn't support any suspending mode yet. */
+	if (tegra_chip_id == TEGRA114)
+		return TEGRA_SUSPEND_NONE;
+
+	/*
+	 * The Tegra devices only support suspending to LP2 currently.
+	 */
+	if (mode > TEGRA_SUSPEND_LP2)
+		return TEGRA_SUSPEND_LP2;
+
+	return mode;
+}
+
+static const char *lp_state[TEGRA_MAX_SUSPEND_MODE] = {
+	[TEGRA_SUSPEND_NONE] = "none",
+	[TEGRA_SUSPEND_LP2] = "LP2",
+	[TEGRA_SUSPEND_LP1] = "LP1",
+	[TEGRA_SUSPEND_LP0] = "LP0",
+};
+
+static int __cpuinit tegra_suspend_enter(suspend_state_t state)
+{
+	enum tegra_suspend_mode mode = tegra_pmc_get_suspend_mode();
+
+	if (WARN_ON(mode < TEGRA_SUSPEND_NONE ||
+		    mode >= TEGRA_MAX_SUSPEND_MODE))
+		return -EINVAL;
+
+	pr_info("Entering suspend state %s\n", lp_state[mode]);
+
+	tegra_pmc_pm_set(mode);
+
+	local_fiq_disable();
+
+	suspend_cpu_complex();
+	switch (mode) {
+	case TEGRA_SUSPEND_LP2:
+		tegra_set_cpu_in_lp2(0);
+		break;
+	default:
+		break;
+	}
+
+	cpu_suspend(PHYS_OFFSET - PAGE_OFFSET, &tegra_sleep_cpu);
+
+	switch (mode) {
+	case TEGRA_SUSPEND_LP2:
+		tegra_clear_cpu_in_lp2(0);
+		break;
+	default:
+		break;
+	}
+	restore_cpu_complex();
+
+	local_fiq_enable();
+
+	return 0;
+}
+
+static const struct platform_suspend_ops tegra_suspend_ops = {
+	.valid		= suspend_valid_only_mem,
+	.enter		= tegra_suspend_enter,
+};
+
+void __init tegra_init_suspend(void)
+{
+	if (tegra_pmc_get_suspend_mode() == TEGRA_SUSPEND_NONE)
+		return;
+
+	tegra_pmc_suspend_init();
+
+	suspend_set_ops(&tegra_suspend_ops);
+}
 #endif
diff --git a/arch/arm/mach-tegra/pm.h b/arch/arm/mach-tegra/pm.h
index 787335c..9d2d038 100644
--- a/arch/arm/mach-tegra/pm.h
+++ b/arch/arm/mach-tegra/pm.h
@@ -21,6 +21,8 @@
 #ifndef _MACH_TEGRA_PM_H_
 #define _MACH_TEGRA_PM_H_
 
+#include "pmc.h"
+
 extern unsigned long l2x0_saved_regs_addr;
 
 void save_cpu_arch_register(void);
@@ -29,7 +31,20 @@ void restore_cpu_arch_register(void);
 void tegra_clear_cpu_in_lp2(int phy_cpu_id);
 bool tegra_set_cpu_in_lp2(int phy_cpu_id);
 
-void tegra_idle_lp2_last(u32 cpu_on_time, u32 cpu_off_time);
+void tegra_idle_lp2_last(void);
 extern void (*tegra_tear_down_cpu)(void);
 
+#ifdef CONFIG_PM_SLEEP
+enum tegra_suspend_mode tegra_pm_validate_suspend_mode(
+				enum tegra_suspend_mode mode);
+void tegra_init_suspend(void);
+#else
+enum tegra_suspend_mode tegra_pm_validate_suspend_mode(
+				enum tegra_suspend_mode mode)
+{
+	return TEGRA_SUSPEND_NONE;
+}
+static inline void tegra_init_suspend(void) {}
+#endif
+
 #endif /* _MACH_TEGRA_PM_H_ */
diff --git a/arch/arm/mach-tegra/pmc.c b/arch/arm/mach-tegra/pmc.c
index d4fdb5f..32360e5 100644
--- a/arch/arm/mach-tegra/pmc.c
+++ b/arch/arm/mach-tegra/pmc.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved.
+ * Copyright (C) 2012,2013 NVIDIA 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,
@@ -16,59 +16,313 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
 
-#include "iomap.h"
+#include "fuse.h"
+#include "pm.h"
+#include "pmc.h"
+#include "sleep.h"
 
-#define PMC_CTRL		0x0
-#define PMC_CTRL_INTR_LOW	(1 << 17)
+#define TEGRA_POWER_EFFECT_LP0		(1 << 14)  /* LP0 when CPU pwr gated */
+#define TEGRA_POWER_CPU_PWRREQ_POLARITY	(1 << 15)  /* CPU pwr req polarity */
+#define TEGRA_POWER_CPU_PWRREQ_OE	(1 << 16)  /* CPU pwr req enable */
+
+#define PMC_CTRL			0x0
+#define PMC_CTRL_INTR_LOW		(1 << 17)
+#define PMC_PWRGATE_TOGGLE		0x30
+#define PMC_PWRGATE_TOGGLE_START	(1 << 8)
+#define PMC_REMOVE_CLAMPING		0x34
+#define PMC_PWRGATE_STATUS		0x38
+
+#define PMC_CPUPWRGOOD_TIMER	0xc8
+#define PMC_CPUPWROFF_TIMER	0xcc
+
+#define TEGRA_POWERGATE_PCIE	3
+#define TEGRA_POWERGATE_VDEC	4
+#define TEGRA_POWERGATE_CPU1	9
+#define TEGRA_POWERGATE_CPU2	10
+#define TEGRA_POWERGATE_CPU3	11
+
+static u8 tegra_cpu_domains[] = {
+	0xFF,			/* not available for CPU0 */
+	TEGRA_POWERGATE_CPU1,
+	TEGRA_POWERGATE_CPU2,
+	TEGRA_POWERGATE_CPU3,
+};
+static DEFINE_SPINLOCK(tegra_powergate_lock);
+
+static void __iomem *tegra_pmc_base;
+static bool tegra_pmc_invert_interrupt;
+static struct clk *tegra_pclk;
+
+struct pmc_pm_data {
+	u32 cpu_good_time;	/* CPU power good time in uS */
+	u32 cpu_off_time;	/* CPU power off time in uS */
+	u32 core_osc_time;	/* Core power good osc time in uS */
+	u32 core_pmu_time;	/* Core power good pmu time in uS */
+	u32 core_off_time;	/* Core power off time in uS */
+	bool corereq_high;	/* Core power request active-high */
+	bool sysclkreq_high;	/* System clock request active-high */
+	bool combined_req;	/* Combined pwr req for CPU & Core */
+	bool cpu_pwr_good_en;	/* CPU power good signal is enabled */
+	u32 lp0_vec_phy_addr;	/* The phy addr of LP0 warm boot code */
+	u32 lp0_vec_size;	/* The size of LP0 warm boot code */
+	enum tegra_suspend_mode suspend_mode;
+};
+static struct pmc_pm_data pmc_pm_data;
 
 static inline u32 tegra_pmc_readl(u32 reg)
 {
-	return readl(IO_ADDRESS(TEGRA_PMC_BASE + reg));
+	return readl(tegra_pmc_base + reg);
 }
 
 static inline void tegra_pmc_writel(u32 val, u32 reg)
 {
-	writel(val, IO_ADDRESS(TEGRA_PMC_BASE + reg));
+	writel(val, tegra_pmc_base + reg);
+}
+
+static int tegra_pmc_get_cpu_powerdomain_id(int cpuid)
+{
+	if (cpuid <= 0 || cpuid >= num_possible_cpus())
+		return -EINVAL;
+	return tegra_cpu_domains[cpuid];
+}
+
+static bool tegra_pmc_powergate_is_powered(int id)
+{
+	return (tegra_pmc_readl(PMC_PWRGATE_STATUS) >> id) & 1;
+}
+
+static int tegra_pmc_powergate_set(int id, bool new_state)
+{
+	bool old_state;
+	unsigned long flags;
+
+	spin_lock_irqsave(&tegra_powergate_lock, flags);
+
+	old_state = tegra_pmc_powergate_is_powered(id);
+	WARN_ON(old_state == new_state);
+
+	tegra_pmc_writel(PMC_PWRGATE_TOGGLE_START | id, PMC_PWRGATE_TOGGLE);
+
+	spin_unlock_irqrestore(&tegra_powergate_lock, flags);
+
+	return 0;
+}
+
+static int tegra_pmc_powergate_remove_clamping(int id)
+{
+	u32 mask;
+
+	/*
+	 * Tegra has a bug where PCIE and VDE clamping masks are
+	 * swapped relatively to the partition ids.
+	 */
+	if (id ==  TEGRA_POWERGATE_VDEC)
+		mask = (1 << TEGRA_POWERGATE_PCIE);
+	else if	(id == TEGRA_POWERGATE_PCIE)
+		mask = (1 << TEGRA_POWERGATE_VDEC);
+	else
+		mask = (1 << id);
+
+	tegra_pmc_writel(mask, PMC_REMOVE_CLAMPING);
+
+	return 0;
+}
+
+bool tegra_pmc_cpu_is_powered(int cpuid)
+{
+	int id;
+
+	id = tegra_pmc_get_cpu_powerdomain_id(cpuid);
+	if (id < 0)
+		return false;
+	return tegra_pmc_powergate_is_powered(id);
 }
 
-#ifdef CONFIG_OF
+int tegra_pmc_cpu_power_on(int cpuid)
+{
+	int id;
+
+	id = tegra_pmc_get_cpu_powerdomain_id(cpuid);
+	if (id < 0)
+		return id;
+	return tegra_pmc_powergate_set(id, true);
+}
+
+int tegra_pmc_cpu_remove_clamping(int cpuid)
+{
+	int id;
+
+	id = tegra_pmc_get_cpu_powerdomain_id(cpuid);
+	if (id < 0)
+		return id;
+	return tegra_pmc_powergate_remove_clamping(id);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static void set_power_timers(u32 us_on, u32 us_off, unsigned long rate)
+{
+	unsigned long long ticks;
+	unsigned long long pclk;
+	static unsigned long tegra_last_pclk;
+
+	if (WARN_ON_ONCE(rate <= 0))
+		pclk = 100000000;
+	else
+		pclk = rate;
+
+	if ((rate != tegra_last_pclk)) {
+		ticks = (us_on * pclk) + 999999ull;
+		do_div(ticks, 1000000);
+		tegra_pmc_writel((unsigned long)ticks, PMC_CPUPWRGOOD_TIMER);
+
+		ticks = (us_off * pclk) + 999999ull;
+		do_div(ticks, 1000000);
+		tegra_pmc_writel((unsigned long)ticks, PMC_CPUPWROFF_TIMER);
+		wmb();
+	}
+	tegra_last_pclk = pclk;
+}
+
+enum tegra_suspend_mode tegra_pmc_get_suspend_mode(void)
+{
+	return pmc_pm_data.suspend_mode;
+}
+
+void tegra_pmc_pm_set(enum tegra_suspend_mode mode)
+{
+	u32 reg;
+	unsigned long rate = 0;
+
+	reg = tegra_pmc_readl(PMC_CTRL);
+	reg |= TEGRA_POWER_CPU_PWRREQ_OE;
+	reg &= ~TEGRA_POWER_EFFECT_LP0;
+
+	switch (mode) {
+	case TEGRA_SUSPEND_LP2:
+		rate = clk_get_rate(tegra_pclk);
+		break;
+	default:
+		break;
+	}
+
+	set_power_timers(pmc_pm_data.cpu_good_time, pmc_pm_data.cpu_off_time,
+			 rate);
+
+	tegra_pmc_writel(reg, PMC_CTRL);
+}
+
+void tegra_pmc_suspend_init(void)
+{
+	u32 reg;
+
+	/* Always enable CPU power request */
+	reg = tegra_pmc_readl(PMC_CTRL);
+	reg |= TEGRA_POWER_CPU_PWRREQ_OE;
+	tegra_pmc_writel(reg, PMC_CTRL);
+}
+#endif
+
 static const struct of_device_id matches[] __initconst = {
+	{ .compatible = "nvidia,tegra114-pmc" },
+	{ .compatible = "nvidia,tegra30-pmc" },
 	{ .compatible = "nvidia,tegra20-pmc" },
 	{ }
 };
-#endif
 
-void __init tegra_pmc_init(void)
+static void tegra_pmc_parse_dt(void)
 {
-	/*
-	 * For now, Harmony is the only board that uses the PMC, and it wants
-	 * the signal inverted. Seaboard would too if it used the PMC.
-	 * Hopefully by the time other boards want to use the PMC, everything
-	 * will be device-tree, or they also want it inverted.
-	 */
-	bool invert_interrupt = true;
-	u32 val;
+	struct device_node *np;
+	u32 prop;
+	enum tegra_suspend_mode suspend_mode;
+	u32 core_good_time[2] = {0, 0};
+	u32 lp0_vec[2] = {0, 0};
 
-#ifdef CONFIG_OF
-	if (of_have_populated_dt()) {
-		struct device_node *np;
+	np = of_find_matching_node(NULL, matches);
+	BUG_ON(!np);
 
-		invert_interrupt = false;
+	tegra_pmc_base = of_iomap(np, 0);
 
-		np = of_find_matching_node(NULL, matches);
-		if (np) {
-			if (of_find_property(np, "nvidia,invert-interrupt",
-						NULL))
-				invert_interrupt = true;
+	tegra_pmc_invert_interrupt = of_property_read_bool(np,
+				     "nvidia,invert-interrupt");
+	tegra_pclk = of_clk_get_by_name(np, "pclk");
+	WARN_ON(IS_ERR(tegra_pclk));
+
+	/* Grabbing the power management configurations */
+	if (of_property_read_u32(np, "nvidia,suspend-mode", &prop)) {
+		suspend_mode = TEGRA_SUSPEND_NONE;
+	} else {
+		switch (prop) {
+		case 0:
+			suspend_mode = TEGRA_SUSPEND_LP0;
+			break;
+		case 1:
+			suspend_mode = TEGRA_SUSPEND_LP1;
+			break;
+		case 2:
+			suspend_mode = TEGRA_SUSPEND_LP2;
+			break;
+		default:
+			suspend_mode = TEGRA_SUSPEND_NONE;
+			break;
 		}
 	}
-#endif
+	suspend_mode = tegra_pm_validate_suspend_mode(suspend_mode);
+
+	if (of_property_read_u32(np, "nvidia,cpu-pwr-good-time", &prop))
+		suspend_mode = TEGRA_SUSPEND_NONE;
+	pmc_pm_data.cpu_good_time = prop;
+
+	if (of_property_read_u32(np, "nvidia,cpu-pwr-off-time", &prop))
+		suspend_mode = TEGRA_SUSPEND_NONE;
+	pmc_pm_data.cpu_off_time = prop;
+
+	if (of_property_read_u32_array(np, "nvidia,core-pwr-good-time",
+			core_good_time, ARRAY_SIZE(core_good_time)))
+		suspend_mode = TEGRA_SUSPEND_NONE;
+	pmc_pm_data.core_osc_time = core_good_time[0];
+	pmc_pm_data.core_pmu_time = core_good_time[1];
+
+	if (of_property_read_u32(np, "nvidia,core-pwr-off-time",
+				 &prop))
+		suspend_mode = TEGRA_SUSPEND_NONE;
+	pmc_pm_data.core_off_time = prop;
+
+	pmc_pm_data.corereq_high = of_property_read_bool(np,
+				"nvidia,core-power-req-active-high");
+
+	pmc_pm_data.sysclkreq_high = of_property_read_bool(np,
+				"nvidia,sys-clock-req-active-high");
+
+	pmc_pm_data.combined_req = of_property_read_bool(np,
+				"nvidia,combined-power-req");
+
+	pmc_pm_data.cpu_pwr_good_en = of_property_read_bool(np,
+				"nvidia,cpu-pwr-good-en");
+
+	if (of_property_read_u32_array(np, "nvidia,lp0-vec", lp0_vec,
+				       ARRAY_SIZE(lp0_vec)))
+		if (suspend_mode == TEGRA_SUSPEND_LP0)
+			suspend_mode = TEGRA_SUSPEND_LP1;
+
+	pmc_pm_data.lp0_vec_phy_addr = lp0_vec[0];
+	pmc_pm_data.lp0_vec_size = lp0_vec[1];
+
+	pmc_pm_data.suspend_mode = suspend_mode;
+}
+
+void __init tegra_pmc_init(void)
+{
+	u32 val;
+
+	tegra_pmc_parse_dt();
 
 	val = tegra_pmc_readl(PMC_CTRL);
-	if (invert_interrupt)
+	if (tegra_pmc_invert_interrupt)
 		val |= PMC_CTRL_INTR_LOW;
 	else
 		val &= ~PMC_CTRL_INTR_LOW;
diff --git a/arch/arm/mach-tegra/pmc.h b/arch/arm/mach-tegra/pmc.h
index 8995ee4..e1c2df2 100644
--- a/arch/arm/mach-tegra/pmc.h
+++ b/arch/arm/mach-tegra/pmc.h
@@ -18,6 +18,24 @@
 #ifndef __MACH_TEGRA_PMC_H
 #define __MACH_TEGRA_PMC_H
 
+enum tegra_suspend_mode {
+	TEGRA_SUSPEND_NONE = 0,
+	TEGRA_SUSPEND_LP2,	/* CPU voltage off */
+	TEGRA_SUSPEND_LP1,	/* CPU voltage off, DRAM self-refresh */
+	TEGRA_SUSPEND_LP0,      /* CPU + core voltage off, DRAM self-refresh */
+	TEGRA_MAX_SUSPEND_MODE,
+};
+
+#ifdef CONFIG_PM_SLEEP
+enum tegra_suspend_mode tegra_pmc_get_suspend_mode(void);
+void tegra_pmc_pm_set(enum tegra_suspend_mode mode);
+void tegra_pmc_suspend_init(void);
+#endif
+
+bool tegra_pmc_cpu_is_powered(int cpuid);
+int tegra_pmc_cpu_power_on(int cpuid);
+int tegra_pmc_cpu_remove_clamping(int cpuid);
+
 void tegra_pmc_init(void);
 
 #endif
diff --git a/arch/arm/mach-tegra/powergate.c b/arch/arm/mach-tegra/powergate.c
index c6bc8f8..f076f0f 100644
--- a/arch/arm/mach-tegra/powergate.c
+++ b/arch/arm/mach-tegra/powergate.c
@@ -22,13 +22,13 @@
 #include <linux/debugfs.h>
 #include <linux/delay.h>
 #include <linux/err.h>
+#include <linux/export.h>
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/seq_file.h>
 #include <linux/spinlock.h>
 #include <linux/clk/tegra.h>
-
-#include <mach/powergate.h>
+#include <linux/tegra-powergate.h>
 
 #include "fuse.h"
 #include "iomap.h"
@@ -75,7 +75,7 @@ static int tegra_powergate_set(int id, bool new_state)
 
 	if (status == new_state) {
 		spin_unlock_irqrestore(&tegra_powergate_lock, flags);
-		return -EINVAL;
+		return 0;
 	}
 
 	pmc_write(PWRGATE_TOGGLE_START | id, PWRGATE_TOGGLE);
@@ -168,6 +168,7 @@ err_clk:
 err_power:
 	return ret;
 }
+EXPORT_SYMBOL(tegra_powergate_sequence_power_up);
 
 int tegra_cpu_powergate_id(int cpuid)
 {
diff --git a/arch/arm/mach-tegra/reset-handler.S b/arch/arm/mach-tegra/reset-handler.S
index 54382ce..1676aba 100644
--- a/arch/arm/mach-tegra/reset-handler.S
+++ b/arch/arm/mach-tegra/reset-handler.S
@@ -41,9 +41,6 @@
  */
 ENTRY(tegra_resume)
 	bl	v7_invalidate_l1
-	/* Enable coresight */
-	mov32	r0, 0xC5ACCE55
-	mcr	p14, 0, r0, c7, c12, 6
 
 	cpu_id	r0
 	cmp	r0, #0				@ CPU0?
@@ -99,6 +96,8 @@ ENTRY(__tegra_cpu_reset_handler_start)
  *
  * Register usage within the reset handler:
  *
+ *      Others: scratch
+ *      R6  = SoC ID << 8
  *      R7  = CPU present (to the OS) mask
  *      R8  = CPU in LP1 state mask
  *      R9  = CPU in LP2 state mask
@@ -114,6 +113,40 @@ ENTRY(__tegra_cpu_reset_handler_start)
 ENTRY(__tegra_cpu_reset_handler)
 
 	cpsid	aif, 0x13			@ SVC mode, interrupts disabled
+
+	mov32	r6, TEGRA_APB_MISC_BASE
+	ldr	r6, [r6, #APB_MISC_GP_HIDREV]
+	and	r6, r6, #0xff00
+#ifdef CONFIG_ARCH_TEGRA_2x_SOC
+t20_check:
+	cmp	r6, #(0x20 << 8)
+	bne	after_t20_check
+t20_errata:
+	# Tegra20 is a Cortex-A9 r1p1
+	mrc	p15, 0, r0, c1, c0, 0   @ read system control register
+	orr	r0, r0, #1 << 14        @ erratum 716044
+	mcr	p15, 0, r0, c1, c0, 0   @ write system control register
+	mrc	p15, 0, r0, c15, c0, 1  @ read diagnostic register
+	orr	r0, r0, #1 << 4         @ erratum 742230
+	orr	r0, r0, #1 << 11        @ erratum 751472
+	mcr	p15, 0, r0, c15, c0, 1  @ write diagnostic register
+	b	after_errata
+after_t20_check:
+#endif
+#ifdef CONFIG_ARCH_TEGRA_3x_SOC
+t30_check:
+	cmp	r6, #(0x30 << 8)
+	bne	after_t30_check
+t30_errata:
+	# Tegra30 is a Cortex-A9 r2p9
+	mrc	p15, 0, r0, c15, c0, 1  @ read diagnostic register
+	orr	r0, r0, #1 << 6         @ erratum 743622
+	orr	r0, r0, #1 << 11        @ erratum 751472
+	mcr	p15, 0, r0, c15, c0, 1  @ write diagnostic register
+	b	after_errata
+after_t30_check:
+#endif
+after_errata:
 	mrc	p15, 0, r10, c0, c0, 5		@ MPIDR
 	and	r10, r10, #0x3			@ R10 = CPU number
 	mov	r11, #1
@@ -129,16 +162,13 @@ ENTRY(__tegra_cpu_reset_handler)
 
 #ifdef CONFIG_ARCH_TEGRA_2x_SOC
 	/* Are we on Tegra20? */
-	mov32	r6, TEGRA_APB_MISC_BASE
-	ldr	r0, [r6, #APB_MISC_GP_HIDREV]
-	and	r0, r0, #0xff00
-	cmp	r0, #(0x20 << 8)
+	cmp	r6, #(0x20 << 8)
 	bne	1f
 	/* If not CPU0, don't let CPU0 reset CPU1 now that CPU1 is coming up. */
-	mov32	r6, TEGRA_PMC_BASE
+	mov32	r5, TEGRA_PMC_BASE
 	mov	r0, #0
 	cmp	r10, #0
-	strne	r0, [r6, #PMC_SCRATCH41]
+	strne	r0, [r5, #PMC_SCRATCH41]
 1:
 #endif
 
diff --git a/arch/arm/mach-tegra/sleep.h b/arch/arm/mach-tegra/sleep.h
index 4ffae54..970ebd5 100644
--- a/arch/arm/mach-tegra/sleep.h
+++ b/arch/arm/mach-tegra/sleep.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved.
+ * Copyright (c) 2010-2013, NVIDIA 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,
@@ -124,11 +124,11 @@ int tegra_sleep_cpu_finish(unsigned long);
 void tegra_disable_clean_inv_dcache(void);
 
 #ifdef CONFIG_HOTPLUG_CPU
-void tegra20_hotplug_init(void);
-void tegra30_hotplug_init(void);
+void tegra20_hotplug_shutdown(void);
+void tegra30_hotplug_shutdown(void);
+void tegra_hotplug_init(void);
 #else
-static inline void tegra20_hotplug_init(void) {}
-static inline void tegra30_hotplug_init(void) {}
+static inline void tegra_hotplug_init(void) {}
 #endif
 
 void tegra20_cpu_shutdown(int cpu);
diff --git a/arch/arm/mach-tegra/tegra.c b/arch/arm/mach-tegra/tegra.c
new file mode 100644
index 0000000..9cf1ab1
--- /dev/null
+++ b/arch/arm/mach-tegra/tegra.c
@@ -0,0 +1,184 @@
+/*
+ * NVIDIA Tegra SoC device tree board support
+ *
+ * Copyright (C) 2011, 2013, NVIDIA Corporation
+ * Copyright (C) 2010 Secret Lab Technologies, Ltd.
+ * Copyright (C) 2010 Google, 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.
+ *
+ */
+
+#include <linux/clocksource.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/serial_8250.h>
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/irqdomain.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_fdt.h>
+#include <linux/of_platform.h>
+#include <linux/pda_power.h>
+#include <linux/platform_data/tegra_usb.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/sys_soc.h>
+#include <linux/usb/tegra_usb_phy.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <asm/setup.h>
+
+#include "board.h"
+#include "common.h"
+#include "fuse.h"
+#include "iomap.h"
+
+static struct tegra_ehci_platform_data tegra_ehci1_pdata = {
+	.operating_mode = TEGRA_USB_OTG,
+	.power_down_on_bus_suspend = 1,
+	.vbus_gpio = -1,
+};
+
+static struct tegra_ulpi_config tegra_ehci2_ulpi_phy_config = {
+	.reset_gpio = -1,
+	.clk = "cdev2",
+};
+
+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,
+	.vbus_gpio = -1,
+};
+
+static struct tegra_ehci_platform_data tegra_ehci3_pdata = {
+	.operating_mode = TEGRA_USB_HOST,
+	.power_down_on_bus_suspend = 1,
+	.vbus_gpio = -1,
+};
+
+static struct of_dev_auxdata tegra20_auxdata_lookup[] __initdata = {
+	OF_DEV_AUXDATA("nvidia,tegra20-ehci", 0xC5000000, "tegra-ehci.0",
+		       &tegra_ehci1_pdata),
+	OF_DEV_AUXDATA("nvidia,tegra20-ehci", 0xC5004000, "tegra-ehci.1",
+		       &tegra_ehci2_pdata),
+	OF_DEV_AUXDATA("nvidia,tegra20-ehci", 0xC5008000, "tegra-ehci.2",
+		       &tegra_ehci3_pdata),
+	{}
+};
+
+static void __init tegra_dt_init(void)
+{
+	struct soc_device_attribute *soc_dev_attr;
+	struct soc_device *soc_dev;
+	struct device *parent = NULL;
+
+	soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
+	if (!soc_dev_attr)
+		goto out;
+
+	soc_dev_attr->family = kasprintf(GFP_KERNEL, "Tegra");
+	soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%d", tegra_revision);
+	soc_dev_attr->soc_id = kasprintf(GFP_KERNEL, "%d", tegra_chip_id);
+
+	soc_dev = soc_device_register(soc_dev_attr);
+	if (IS_ERR(soc_dev)) {
+		kfree(soc_dev_attr->family);
+		kfree(soc_dev_attr->revision);
+		kfree(soc_dev_attr->soc_id);
+		kfree(soc_dev_attr);
+		goto out;
+	}
+
+	parent = soc_device_to_device(soc_dev);
+
+	/*
+	 * Finished with the static registrations now; fill in the missing
+	 * devices
+	 */
+out:
+	of_platform_populate(NULL, of_default_bus_match_table,
+				tegra20_auxdata_lookup, parent);
+}
+
+static void __init trimslice_init(void)
+{
+#ifdef CONFIG_TEGRA_PCI
+	int ret;
+
+	ret = tegra_pcie_init(true, true);
+	if (ret)
+		pr_err("tegra_pci_init() failed: %d\n", ret);
+#endif
+}
+
+static void __init harmony_init(void)
+{
+#ifdef CONFIG_TEGRA_PCI
+	int ret;
+
+	ret = harmony_pcie_init();
+	if (ret)
+		pr_err("harmony_pcie_init() failed: %d\n", ret);
+#endif
+}
+
+static void __init paz00_init(void)
+{
+	if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC))
+		tegra_paz00_wifikill_init();
+}
+
+static struct {
+	char *machine;
+	void (*init)(void);
+} board_init_funcs[] = {
+	{ "compulab,trimslice", trimslice_init },
+	{ "nvidia,harmony", harmony_init },
+	{ "compal,paz00", paz00_init },
+};
+
+static void __init tegra_dt_init_late(void)
+{
+	int i;
+
+	tegra_init_late();
+
+	for (i = 0; i < ARRAY_SIZE(board_init_funcs); i++) {
+		if (of_machine_is_compatible(board_init_funcs[i].machine)) {
+			board_init_funcs[i].init();
+			break;
+		}
+	}
+}
+
+static const char * const tegra_dt_board_compat[] = {
+	"nvidia,tegra114",
+	"nvidia,tegra30",
+	"nvidia,tegra20",
+	NULL
+};
+
+DT_MACHINE_START(TEGRA_DT, "NVIDIA Tegra SoC (Flattened Device Tree)")
+	.map_io		= tegra_map_common_io,
+	.smp		= smp_ops(tegra_smp_ops),
+	.init_early	= tegra_init_early,
+	.init_irq	= tegra_dt_init_irq,
+	.init_time	= clocksource_of_init,
+	.init_machine	= tegra_dt_init,
+	.init_late	= tegra_dt_init_late,
+	.restart	= tegra_assert_system_reset,
+	.dt_compat	= tegra_dt_board_compat,
+MACHINE_END
diff --git a/arch/arm/mach-tegra/tegra114_speedo.c b/arch/arm/mach-tegra/tegra114_speedo.c
new file mode 100644
index 0000000..5218d48
--- /dev/null
+++ b/arch/arm/mach-tegra/tegra114_speedo.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2013, NVIDIA 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/bug.h>
+
+#include "fuse.h"
+
+#define CORE_PROCESS_CORNERS_NUM	2
+#define CPU_PROCESS_CORNERS_NUM		2
+
+enum {
+	THRESHOLD_INDEX_0,
+	THRESHOLD_INDEX_1,
+	THRESHOLD_INDEX_COUNT,
+};
+
+static const u32 core_process_speedos[][CORE_PROCESS_CORNERS_NUM] = {
+	{1123,     UINT_MAX},
+	{0,        UINT_MAX},
+};
+
+static const u32 cpu_process_speedos[][CPU_PROCESS_CORNERS_NUM] = {
+	{1695,     UINT_MAX},
+	{0,        UINT_MAX},
+};
+
+static void rev_sku_to_speedo_ids(int rev, int sku, int *threshold)
+{
+	u32 tmp;
+
+	switch (sku) {
+	case 0x00:
+	case 0x10:
+	case 0x05:
+	case 0x06:
+		tegra_cpu_speedo_id = 1;
+		tegra_soc_speedo_id = 0;
+		*threshold = THRESHOLD_INDEX_0;
+		break;
+
+	case 0x03:
+	case 0x04:
+		tegra_cpu_speedo_id = 2;
+		tegra_soc_speedo_id = 1;
+		*threshold = THRESHOLD_INDEX_1;
+		break;
+
+	default:
+		pr_err("Tegra114 Unknown SKU %d\n", sku);
+		tegra_cpu_speedo_id = 0;
+		tegra_soc_speedo_id = 0;
+		*threshold = THRESHOLD_INDEX_0;
+		break;
+	}
+
+	if (rev == TEGRA_REVISION_A01) {
+		tmp = tegra_fuse_readl(0x270) << 1;
+		tmp |= tegra_fuse_readl(0x26c);
+		if (!tmp)
+			tegra_cpu_speedo_id = 0;
+	}
+}
+
+void tegra114_init_speedo_data(void)
+{
+	u32 cpu_speedo_val;
+	u32 core_speedo_val;
+	int threshold;
+	int i;
+
+	BUILD_BUG_ON(ARRAY_SIZE(cpu_process_speedos) !=
+			THRESHOLD_INDEX_COUNT);
+	BUILD_BUG_ON(ARRAY_SIZE(core_process_speedos) !=
+			THRESHOLD_INDEX_COUNT);
+
+	rev_sku_to_speedo_ids(tegra_revision, tegra_sku_id, &threshold);
+
+	cpu_speedo_val = tegra_fuse_readl(0x12c) + 1024;
+	core_speedo_val = tegra_fuse_readl(0x134);
+
+	for (i = 0; i < CPU_PROCESS_CORNERS_NUM; i++)
+		if (cpu_speedo_val < cpu_process_speedos[threshold][i])
+			break;
+	tegra_cpu_process_id = i;
+
+	for (i = 0; i < CORE_PROCESS_CORNERS_NUM; i++)
+		if (core_speedo_val < core_process_speedos[threshold][i])
+			break;
+	tegra_core_process_id = i;
+}
diff --git a/arch/arm/mach-tegra/tegra2_emc.c b/arch/arm/mach-tegra/tegra2_emc.c
index ce7ce42..9e8bdfa 100644
--- a/arch/arm/mach-tegra/tegra2_emc.c
+++ b/arch/arm/mach-tegra/tegra2_emc.c
@@ -276,7 +276,7 @@ static struct tegra_emc_pdata *tegra_emc_fill_pdata(struct platform_device *pdev
 	int i;
 
 	WARN_ON(pdev->dev.platform_data);
-	BUG_ON(IS_ERR_OR_NULL(c));
+	BUG_ON(IS_ERR(c));
 
 	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
 	pdata->tables = devm_kzalloc(&pdev->dev, sizeof(*pdata->tables),
diff --git a/arch/arm/mach-ux500/board-mop500-regulators.c b/arch/arm/mach-ux500/board-mop500-regulators.c
index 2a17bc5..33c353b 100644
--- a/arch/arm/mach-ux500/board-mop500-regulators.c
+++ b/arch/arm/mach-ux500/board-mop500-regulators.c
@@ -5,6 +5,7 @@
  *
  * Authors: Sundar Iyer <sundar.iyer@stericsson.com>
  *          Bengt Jonsson <bengt.g.jonsson@stericsson.com>
+ *          Daniel Willerud <daniel.willerud@stericsson.com>
  *
  * MOP500 board specific initialization for regulators
  */
@@ -12,6 +13,7 @@
 #include <linux/regulator/machine.h>
 #include <linux/regulator/ab8500.h>
 #include "board-mop500-regulators.h"
+#include "id.h"
 
 static struct regulator_consumer_supply gpio_en_3v3_consumers[] = {
        REGULATOR_SUPPLY("vdd33a", "smsc911x.0"),
@@ -28,6 +30,20 @@ struct regulator_init_data gpio_en_3v3_regulator = {
        .consumer_supplies = gpio_en_3v3_consumers,
 };
 
+static struct regulator_consumer_supply sdi0_reg_consumers[] = {
+        REGULATOR_SUPPLY("vqmmc", "sdi0"),
+};
+
+struct regulator_init_data sdi0_reg_init_data = {
+        .constraints = {
+                .min_uV         = 1800000,
+                .max_uV         = 2900000,
+                .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE|REGULATOR_CHANGE_STATUS,
+        },
+        .num_consumer_supplies  = ARRAY_SIZE(sdi0_reg_consumers),
+        .consumer_supplies      = sdi0_reg_consumers,
+};
+
 /*
  * TPS61052 regulator
  */
@@ -53,21 +69,37 @@ struct regulator_init_data tps61052_regulator = {
 };
 
 static struct regulator_consumer_supply ab8500_vaux1_consumers[] = {
-	/* External displays, connector on board 2v5 power supply */
-	REGULATOR_SUPPLY("vaux12v5", "mcde.0"),
+	/* Main display, u8500 R3 uib */
+	REGULATOR_SUPPLY("vddi", "mcde_disp_sony_acx424akp.0"),
+	/* Main display, u8500 uib and ST uib */
+	REGULATOR_SUPPLY("vdd1", "samsung_s6d16d0.0"),
+	/* Secondary display, ST uib */
+	REGULATOR_SUPPLY("vdd1", "samsung_s6d16d0.1"),
 	/* SFH7741 proximity sensor */
 	REGULATOR_SUPPLY("vcc", "gpio-keys.0"),
 	/* BH1780GLS ambient light sensor */
 	REGULATOR_SUPPLY("vcc", "2-0029"),
 	/* lsm303dlh accelerometer */
-	REGULATOR_SUPPLY("vdd", "3-0018"),
+	REGULATOR_SUPPLY("vdd", "2-0018"),
+	/* lsm303dlhc accelerometer */
+	REGULATOR_SUPPLY("vdd", "2-0019"),
 	/* lsm303dlh magnetometer */
-	REGULATOR_SUPPLY("vdd", "3-001e"),
+	REGULATOR_SUPPLY("vdd", "2-001e"),
 	/* Rohm BU21013 Touchscreen devices */
 	REGULATOR_SUPPLY("avdd", "3-005c"),
 	REGULATOR_SUPPLY("avdd", "3-005d"),
 	/* Synaptics RMI4 Touchscreen device */
 	REGULATOR_SUPPLY("vdd", "3-004b"),
+	/* L3G4200D Gyroscope device */
+	REGULATOR_SUPPLY("vdd", "2-0068"),
+	/* Ambient light sensor device */
+	REGULATOR_SUPPLY("vdd", "3-0029"),
+	/* Pressure sensor device */
+	REGULATOR_SUPPLY("vdd", "2-005c"),
+	/* Cypress TrueTouch Touchscreen device */
+	REGULATOR_SUPPLY("vcpin", "spi8.0"),
+	/* Camera device */
+	REGULATOR_SUPPLY("vaux12v5", "mmio_camera"),
 };
 
 static struct regulator_consumer_supply ab8500_vaux2_consumers[] = {
@@ -75,18 +107,50 @@ static struct regulator_consumer_supply ab8500_vaux2_consumers[] = {
 	REGULATOR_SUPPLY("vmmc", "sdi4"),
 	/* AB8500 audio codec */
 	REGULATOR_SUPPLY("vcc-N2158", "ab8500-codec.0"),
+	/* AB8500 accessory detect 1 */
+	REGULATOR_SUPPLY("vcc-N2158", "ab8500-acc-det.0"),
+	/* AB8500 Tv-out device */
+	REGULATOR_SUPPLY("vcc-N2158", "mcde_tv_ab8500.4"),
+	/* AV8100 HDMI device */
+	REGULATOR_SUPPLY("vcc-N2158", "av8100_hdmi.3"),
 };
 
 static struct regulator_consumer_supply ab8500_vaux3_consumers[] = {
+	REGULATOR_SUPPLY("v-SD-STM", "stm"),
 	/* External MMC slot power */
 	REGULATOR_SUPPLY("vmmc", "sdi0"),
 };
 
+static struct regulator_consumer_supply ab8505_vaux4_consumers[] = {
+};
+
+static struct regulator_consumer_supply ab8505_vaux5_consumers[] = {
+};
+
+static struct regulator_consumer_supply ab8505_vaux6_consumers[] = {
+};
+
+static struct regulator_consumer_supply ab8505_vaux8_consumers[] = {
+	/* AB8500 audio codec device */
+	REGULATOR_SUPPLY("v-aux8", NULL),
+};
+
+static struct regulator_consumer_supply ab8505_vadc_consumers[] = {
+	/* Internal general-purpose ADC */
+	REGULATOR_SUPPLY("vddadc", "ab8500-gpadc.0"),
+	/* ADC for charger */
+	REGULATOR_SUPPLY("vddadc", "ab8500-charger.0"),
+};
+
 static struct regulator_consumer_supply ab8500_vtvout_consumers[] = {
 	/* TV-out DENC supply */
 	REGULATOR_SUPPLY("vtvout", "ab8500-denc.0"),
 	/* Internal general-purpose ADC */
 	REGULATOR_SUPPLY("vddadc", "ab8500-gpadc.0"),
+	/* ADC for charger */
+	REGULATOR_SUPPLY("vddadc", "ab8500-charger.0"),
+	/* AB8500 Tv-out device */
+	REGULATOR_SUPPLY("vtvout", "mcde_tv_ab8500.4"),
 };
 
 static struct regulator_consumer_supply ab8500_vaud_consumers[] = {
@@ -114,77 +178,90 @@ static struct regulator_consumer_supply ab8500_vintcore_consumers[] = {
 	REGULATOR_SUPPLY("v-intcore", NULL),
 	/* USB Transceiver */
 	REGULATOR_SUPPLY("vddulpivio18", "ab8500-usb.0"),
+	/* Handled by abx500 clk driver */
+	REGULATOR_SUPPLY("v-intcore", "abx500-clk.0"),
+};
+
+static struct regulator_consumer_supply ab8505_usb_consumers[] = {
+	/* HS USB OTG physical interface */
+	REGULATOR_SUPPLY("v-ape", NULL),
 };
 
 static struct regulator_consumer_supply ab8500_vana_consumers[] = {
-	/* External displays, connector on board, 1v8 power supply */
-	REGULATOR_SUPPLY("vsmps2", "mcde.0"),
+	/* DB8500 DSI */
+	REGULATOR_SUPPLY("vdddsi1v2", "mcde"),
+	REGULATOR_SUPPLY("vdddsi1v2", "b2r2_core"),
+	REGULATOR_SUPPLY("vdddsi1v2", "b2r2_1_core"),
+	REGULATOR_SUPPLY("vdddsi1v2", "dsilink.0"),
+	REGULATOR_SUPPLY("vdddsi1v2", "dsilink.1"),
+	REGULATOR_SUPPLY("vdddsi1v2", "dsilink.2"),
+	/* DB8500 CSI */
+	REGULATOR_SUPPLY("vddcsi1v2", "mmio_camera"),
 };
 
 /* ab8500 regulator register initialization */
-struct ab8500_regulator_reg_init
-ab8500_regulator_reg_init[AB8500_NUM_REGULATOR_REGISTERS] = {
+static struct ab8500_regulator_reg_init ab8500_reg_init[] = {
 	/*
 	 * VanaRequestCtrl          = HP/LP depending on VxRequest
 	 * VextSupply1RequestCtrl   = HP/LP depending on VxRequest
 	 */
-	INIT_REGULATOR_REGISTER(AB8500_REGUREQUESTCTRL2, 0x00),
+	INIT_REGULATOR_REGISTER(AB8500_REGUREQUESTCTRL2,       0xf0, 0x00),
 	/*
 	 * VextSupply2RequestCtrl   = HP/LP depending on VxRequest
 	 * VextSupply3RequestCtrl   = HP/LP depending on VxRequest
 	 * Vaux1RequestCtrl         = HP/LP depending on VxRequest
 	 * Vaux2RequestCtrl         = HP/LP depending on VxRequest
 	 */
-	INIT_REGULATOR_REGISTER(AB8500_REGUREQUESTCTRL3, 0x00),
+	INIT_REGULATOR_REGISTER(AB8500_REGUREQUESTCTRL3,       0xff, 0x00),
 	/*
 	 * Vaux3RequestCtrl         = HP/LP depending on VxRequest
 	 * SwHPReq                  = Control through SWValid disabled
 	 */
-	INIT_REGULATOR_REGISTER(AB8500_REGUREQUESTCTRL4, 0x00),
+	INIT_REGULATOR_REGISTER(AB8500_REGUREQUESTCTRL4,       0x07, 0x00),
 	/*
 	 * VanaSysClkReq1HPValid    = disabled
 	 * Vaux1SysClkReq1HPValid   = disabled
 	 * Vaux2SysClkReq1HPValid   = disabled
 	 * Vaux3SysClkReq1HPValid   = disabled
 	 */
-	INIT_REGULATOR_REGISTER(AB8500_REGUSYSCLKREQ1HPVALID1, 0x00),
+	INIT_REGULATOR_REGISTER(AB8500_REGUSYSCLKREQ1HPVALID1, 0xe8, 0x00),
 	/*
 	 * VextSupply1SysClkReq1HPValid = disabled
 	 * VextSupply2SysClkReq1HPValid = disabled
 	 * VextSupply3SysClkReq1HPValid = SysClkReq1 controlled
 	 */
-	INIT_REGULATOR_REGISTER(AB8500_REGUSYSCLKREQ1HPVALID2, 0x40),
+	INIT_REGULATOR_REGISTER(AB8500_REGUSYSCLKREQ1HPVALID2, 0x70, 0x40),
 	/*
 	 * VanaHwHPReq1Valid        = disabled
 	 * Vaux1HwHPreq1Valid       = disabled
 	 * Vaux2HwHPReq1Valid       = disabled
 	 * Vaux3HwHPReqValid        = disabled
 	 */
-	INIT_REGULATOR_REGISTER(AB8500_REGUHWHPREQ1VALID1, 0x00),
+	INIT_REGULATOR_REGISTER(AB8500_REGUHWHPREQ1VALID1,     0xe8, 0x00),
 	/*
 	 * VextSupply1HwHPReq1Valid = disabled
 	 * VextSupply2HwHPReq1Valid = disabled
 	 * VextSupply3HwHPReq1Valid = disabled
 	 */
-	INIT_REGULATOR_REGISTER(AB8500_REGUHWHPREQ1VALID2, 0x00),
+	INIT_REGULATOR_REGISTER(AB8500_REGUHWHPREQ1VALID2,     0x07, 0x00),
 	/*
 	 * VanaHwHPReq2Valid        = disabled
 	 * Vaux1HwHPReq2Valid       = disabled
 	 * Vaux2HwHPReq2Valid       = disabled
 	 * Vaux3HwHPReq2Valid       = disabled
 	 */
-	INIT_REGULATOR_REGISTER(AB8500_REGUHWHPREQ2VALID1, 0x00),
+	INIT_REGULATOR_REGISTER(AB8500_REGUHWHPREQ2VALID1,     0xe8, 0x00),
 	/*
 	 * VextSupply1HwHPReq2Valid = disabled
 	 * VextSupply2HwHPReq2Valid = disabled
 	 * VextSupply3HwHPReq2Valid = HWReq2 controlled
 	 */
-	INIT_REGULATOR_REGISTER(AB8500_REGUHWHPREQ2VALID2, 0x04),
+	INIT_REGULATOR_REGISTER(AB8500_REGUHWHPREQ2VALID2,     0x07, 0x04),
 	/*
 	 * VanaSwHPReqValid         = disabled
 	 * Vaux1SwHPReqValid        = disabled
 	 */
-	INIT_REGULATOR_REGISTER(AB8500_REGUSWHPREQVALID1, 0x00),
+	INIT_REGULATOR_REGISTER(AB8500_REGUSWHPREQVALID1,      0xa0, 0x00),
 	/*
 	 * Vaux2SwHPReqValid        = disabled
 	 * Vaux3SwHPReqValid        = disabled
@@ -192,7 +269,7 @@ ab8500_regulator_reg_init[AB8500_NUM_REGULATOR_REGISTERS] = {
 	 * VextSupply2SwHPReqValid  = disabled
 	 * VextSupply3SwHPReqValid  = disabled
 	 */
-	INIT_REGULATOR_REGISTER(AB8500_REGUSWHPREQVALID2, 0x00),
+	INIT_REGULATOR_REGISTER(AB8500_REGUSWHPREQVALID2,      0x1f, 0x00),
 	/*
 	 * SysClkReq2Valid1         = SysClkReq2 controlled
 	 * SysClkReq3Valid1         = disabled
@@ -202,7 +279,7 @@ ab8500_regulator_reg_init[AB8500_NUM_REGULATOR_REGISTERS] = {
 	 * SysClkReq7Valid1         = disabled
 	 * SysClkReq8Valid1         = disabled
 	 */
-	INIT_REGULATOR_REGISTER(AB8500_REGUSYSCLKREQVALID1, 0x2a),
+	INIT_REGULATOR_REGISTER(AB8500_REGUSYSCLKREQVALID1,    0xfe, 0x2a),
 	/*
 	 * SysClkReq2Valid2         = disabled
 	 * SysClkReq3Valid2         = disabled
@@ -212,7 +289,7 @@ ab8500_regulator_reg_init[AB8500_NUM_REGULATOR_REGISTERS] = {
 	 * SysClkReq7Valid2         = disabled
 	 * SysClkReq8Valid2         = disabled
 	 */
-	INIT_REGULATOR_REGISTER(AB8500_REGUSYSCLKREQVALID2, 0x20),
+	INIT_REGULATOR_REGISTER(AB8500_REGUSYSCLKREQVALID2,    0xfe, 0x20),
 	/*
 	 * VTVoutEna                = disabled
 	 * Vintcore12Ena            = disabled
@@ -220,66 +297,62 @@ ab8500_regulator_reg_init[AB8500_NUM_REGULATOR_REGISTERS] = {
 	 * Vintcore12LP             = inactive (HP)
 	 * VTVoutLP                 = inactive (HP)
 	 */
-	INIT_REGULATOR_REGISTER(AB8500_REGUMISC1, 0x10),
+	INIT_REGULATOR_REGISTER(AB8500_REGUMISC1,              0xfe, 0x10),
 	/*
 	 * VaudioEna                = disabled
 	 * VdmicEna                 = disabled
 	 * Vamic1Ena                = disabled
 	 * Vamic2Ena                = disabled
 	 */
-	INIT_REGULATOR_REGISTER(AB8500_VAUDIOSUPPLY, 0x00),
+	INIT_REGULATOR_REGISTER(AB8500_VAUDIOSUPPLY,           0x1e, 0x00),
 	/*
 	 * Vamic1_dzout             = high-Z when Vamic1 is disabled
 	 * Vamic2_dzout             = high-Z when Vamic2 is disabled
 	 */
-	INIT_REGULATOR_REGISTER(AB8500_REGUCTRL1VAMIC, 0x00),
+	INIT_REGULATOR_REGISTER(AB8500_REGUCTRL1VAMIC,         0x03, 0x00),
 	/*
-	 * VPll                     = Hw controlled
+	 * VPll                     = Hw controlled (NOTE! PRCMU bits)
 	 * VanaRegu                 = force off
 	 */
-	INIT_REGULATOR_REGISTER(AB8500_VPLLVANAREGU, 0x02),
+	INIT_REGULATOR_REGISTER(AB8500_VPLLVANAREGU,           0x0f, 0x02),
 	/*
 	 * VrefDDREna               = disabled
 	 * VrefDDRSleepMode         = inactive (no pulldown)
 	 */
-	INIT_REGULATOR_REGISTER(AB8500_VREFDDR, 0x00),
+	INIT_REGULATOR_REGISTER(AB8500_VREFDDR,                0x03, 0x00),
 	/*
-	 * VextSupply1Regu          = HW control
-	 * VextSupply2Regu          = HW control
-	 * VextSupply3Regu          = HW control
+	 * VextSupply1Regu          = force LP
+	 * VextSupply2Regu          = force OFF
+	 * VextSupply3Regu          = force HP (-> STBB2=LP and TPS=LP)
 	 * ExtSupply2Bypass         = ExtSupply12LPn ball is 0 when Ena is 0
 	 * ExtSupply3Bypass         = ExtSupply3LPn ball is 0 when Ena is 0
 	 */
-	INIT_REGULATOR_REGISTER(AB8500_EXTSUPPLYREGU, 0x2a),
+	INIT_REGULATOR_REGISTER(AB8500_EXTSUPPLYREGU,          0xff, 0x13),
 	/*
 	 * Vaux1Regu                = force HP
 	 * Vaux2Regu                = force off
 	 */
-	INIT_REGULATOR_REGISTER(AB8500_VAUX12REGU, 0x01),
-	/*
-	 * Vaux3regu                = force off
-	 */
-	INIT_REGULATOR_REGISTER(AB8500_VRF1VAUX3REGU, 0x00),
+	INIT_REGULATOR_REGISTER(AB8500_VAUX12REGU,             0x0f, 0x01),
 	/*
-	 * Vsmps1                   = 1.15V
+	 * Vaux3Regu                = force off
 	 */
-	INIT_REGULATOR_REGISTER(AB8500_VSMPS1SEL1, 0x24),
+	INIT_REGULATOR_REGISTER(AB8500_VRF1VAUX3REGU,          0x03, 0x00),
 	/*
-	 * Vaux1Sel                 = 2.5 V
+	 * Vaux1Sel                 = 2.8 V
 	 */
-	INIT_REGULATOR_REGISTER(AB8500_VAUX1SEL, 0x08),
+	INIT_REGULATOR_REGISTER(AB8500_VAUX1SEL,               0x0f, 0x0C),
 	/*
 	 * Vaux2Sel                 = 2.9 V
 	 */
-	INIT_REGULATOR_REGISTER(AB8500_VAUX2SEL, 0x0d),
+	INIT_REGULATOR_REGISTER(AB8500_VAUX2SEL,               0x0f, 0x0d),
 	/*
 	 * Vaux3Sel                 = 2.91 V
 	 */
-	INIT_REGULATOR_REGISTER(AB8500_VRF1VAUX3SEL, 0x07),
+	INIT_REGULATOR_REGISTER(AB8500_VRF1VAUX3SEL,           0x07, 0x07),
 	/*
 	 * VextSupply12LP           = disabled (no LP)
 	 */
-	INIT_REGULATOR_REGISTER(AB8500_REGUCTRL2SPARE, 0x00),
+	INIT_REGULATOR_REGISTER(AB8500_REGUCTRL2SPARE,         0x01, 0x00),
 	/*
 	 * Vaux1Disch               = short discharge time
 	 * Vaux2Disch               = short discharge time
@@ -288,33 +361,26 @@ ab8500_regulator_reg_init[AB8500_NUM_REGULATOR_REGISTERS] = {
 	 * VTVoutDisch              = short discharge time
 	 * VaudioDisch              = short discharge time
 	 */
-	INIT_REGULATOR_REGISTER(AB8500_REGUCTRLDISCH, 0x00),
+	INIT_REGULATOR_REGISTER(AB8500_REGUCTRLDISCH,          0xfc, 0x00),
 	/*
 	 * VanaDisch                = short discharge time
 	 * VdmicPullDownEna         = pulldown disabled when Vdmic is disabled
 	 * VdmicDisch               = short discharge time
 	 */
-	INIT_REGULATOR_REGISTER(AB8500_REGUCTRLDISCH2, 0x00),
+	INIT_REGULATOR_REGISTER(AB8500_REGUCTRLDISCH2,         0x16, 0x00),
 };
 
 /* AB8500 regulators */
-struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS] = {
+static struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS] = {
 	/* supplies to the display/camera */
 	[AB8500_LDO_AUX1] = {
 		.constraints = {
 			.name = "V-DISPLAY",
-			.min_uV = 2500000,
-			.max_uV = 2900000,
+			.min_uV = 2800000,
+			.max_uV = 3300000,
 			.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
 					  REGULATOR_CHANGE_STATUS,
 			.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,
@@ -326,7 +392,10 @@ struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS] = {
 			.min_uV = 1100000,
 			.max_uV = 3300000,
 			.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
-					  REGULATOR_CHANGE_STATUS,
+					  REGULATOR_CHANGE_STATUS |
+					  REGULATOR_CHANGE_MODE,
+			.valid_modes_mask = REGULATOR_MODE_NORMAL |
+					    REGULATOR_MODE_IDLE,
 		},
 		.num_consumer_supplies = ARRAY_SIZE(ab8500_vaux2_consumers),
 		.consumer_supplies = ab8500_vaux2_consumers,
@@ -338,7 +407,10 @@ struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS] = {
 			.min_uV = 1100000,
 			.max_uV = 3300000,
 			.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
-					  REGULATOR_CHANGE_STATUS,
+					  REGULATOR_CHANGE_STATUS |
+					  REGULATOR_CHANGE_MODE,
+			.valid_modes_mask = REGULATOR_MODE_NORMAL |
+					    REGULATOR_MODE_IDLE,
 		},
 		.num_consumer_supplies = ARRAY_SIZE(ab8500_vaux3_consumers),
 		.consumer_supplies = ab8500_vaux3_consumers,
@@ -392,18 +464,614 @@ struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS] = {
 	[AB8500_LDO_INTCORE] = {
 		.constraints = {
 			.name = "V-INTCORE",
-			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+			.min_uV = 1250000,
+			.max_uV = 1350000,
+			.input_uV = 1800000,
+			.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+					  REGULATOR_CHANGE_STATUS |
+					  REGULATOR_CHANGE_MODE |
+					  REGULATOR_CHANGE_DRMS,
+			.valid_modes_mask = REGULATOR_MODE_NORMAL |
+					    REGULATOR_MODE_IDLE,
 		},
 		.num_consumer_supplies = ARRAY_SIZE(ab8500_vintcore_consumers),
 		.consumer_supplies = ab8500_vintcore_consumers,
 	},
-	/* supply for U8500 CSI/DSI, VANA LDO */
+	/* supply for U8500 CSI-DSI, VANA LDO */
 	[AB8500_LDO_ANA] = {
 		.constraints = {
-			.name = "V-CSI/DSI",
+			.name = "V-CSI-DSI",
 			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
 		},
 		.num_consumer_supplies = ARRAY_SIZE(ab8500_vana_consumers),
 		.consumer_supplies = ab8500_vana_consumers,
 	},
 };
+
+/* supply for VextSupply3 */
+static struct regulator_consumer_supply ab8500_ext_supply3_consumers[] = {
+	/* SIM supply for 3 V SIM cards */
+	REGULATOR_SUPPLY("vinvsim", "sim-detect.0"),
+};
+
+/* extended configuration for VextSupply2, only used for HREFP_V20 boards */
+static struct ab8500_ext_regulator_cfg ab8500_ext_supply2 = {
+	.hwreq = true,
+};
+
+/*
+ * AB8500 external regulators
+ */
+static struct regulator_init_data ab8500_ext_regulators[] = {
+	/* fixed Vbat supplies VSMPS1_EXT_1V8 */
+	[AB8500_EXT_SUPPLY1] = {
+		.constraints = {
+			.name = "ab8500-ext-supply1",
+			.min_uV = 1800000,
+			.max_uV = 1800000,
+			.initial_mode = REGULATOR_MODE_IDLE,
+			.boot_on = 1,
+			.always_on = 1,
+		},
+	},
+	/* fixed Vbat supplies VSMPS2_EXT_1V36 and VSMPS5_EXT_1V15 */
+	[AB8500_EXT_SUPPLY2] = {
+		.constraints = {
+			.name = "ab8500-ext-supply2",
+			.min_uV = 1360000,
+			.max_uV = 1360000,
+		},
+	},
+	/* fixed Vbat supplies VSMPS3_EXT_3V4 and VSMPS4_EXT_3V4 */
+	[AB8500_EXT_SUPPLY3] = {
+		.constraints = {
+			.name = "ab8500-ext-supply3",
+			.min_uV = 3400000,
+			.max_uV = 3400000,
+			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+			.boot_on = 1,
+		},
+		.num_consumer_supplies =
+			ARRAY_SIZE(ab8500_ext_supply3_consumers),
+		.consumer_supplies = ab8500_ext_supply3_consumers,
+	},
+};
+
+/* ab8505 regulator register initialization */
+static struct ab8500_regulator_reg_init ab8505_reg_init[] = {
+	/*
+	 * VarmRequestCtrl
+	 * VsmpsCRequestCtrl
+	 * VsmpsARequestCtrl
+	 * VsmpsBRequestCtrl
+	 */
+	INIT_REGULATOR_REGISTER(AB8505_REGUREQUESTCTRL1,       0x00, 0x00),
+	/*
+	 * VsafeRequestCtrl
+	 * VpllRequestCtrl
+	 * VanaRequestCtrl          = HP/LP depending on VxRequest
+	 */
+	INIT_REGULATOR_REGISTER(AB8505_REGUREQUESTCTRL2,       0x30, 0x00),
+	/*
+	 * Vaux1RequestCtrl         = HP/LP depending on VxRequest
+	 * Vaux2RequestCtrl         = HP/LP depending on VxRequest
+	 */
+	INIT_REGULATOR_REGISTER(AB8505_REGUREQUESTCTRL3,       0xf0, 0x00),
+	/*
+	 * Vaux3RequestCtrl         = HP/LP depending on VxRequest
+	 * SwHPReq                  = Control through SWValid disabled
+	 */
+	INIT_REGULATOR_REGISTER(AB8505_REGUREQUESTCTRL4,       0x07, 0x00),
+	/*
+	 * VsmpsASysClkReq1HPValid
+	 * VsmpsBSysClkReq1HPValid
+	 * VsafeSysClkReq1HPValid
+	 * VanaSysClkReq1HPValid    = disabled
+	 * VpllSysClkReq1HPValid
+	 * Vaux1SysClkReq1HPValid   = disabled
+	 * Vaux2SysClkReq1HPValid   = disabled
+	 * Vaux3SysClkReq1HPValid   = disabled
+	 */
+	INIT_REGULATOR_REGISTER(AB8505_REGUSYSCLKREQ1HPVALID1, 0xe8, 0x00),
+	/*
+	 * VsmpsCSysClkReq1HPValid
+	 * VarmSysClkReq1HPValid
+	 * VbbSysClkReq1HPValid
+	 * VsmpsMSysClkReq1HPValid
+	 */
+	INIT_REGULATOR_REGISTER(AB8505_REGUSYSCLKREQ1HPVALID2, 0x00, 0x00),
+	/*
+	 * VsmpsAHwHPReq1Valid
+	 * VsmpsBHwHPReq1Valid
+	 * VsafeHwHPReq1Valid
+	 * VanaHwHPReq1Valid        = disabled
+	 * VpllHwHPReq1Valid
+	 * Vaux1HwHPreq1Valid       = disabled
+	 * Vaux2HwHPReq1Valid       = disabled
+	 * Vaux3HwHPReqValid        = disabled
+	 */
+	INIT_REGULATOR_REGISTER(AB8505_REGUHWHPREQ1VALID1,     0xe8, 0x00),
+	/*
+	 * VsmpsMHwHPReq1Valid
+	 */
+	INIT_REGULATOR_REGISTER(AB8505_REGUHWHPREQ1VALID2,     0x00, 0x00),
+	/*
+	 * VsmpsAHwHPReq2Valid
+	 * VsmpsBHwHPReq2Valid
+	 * VsafeHwHPReq2Valid
+	 * VanaHwHPReq2Valid        = disabled
+	 * VpllHwHPReq2Valid
+	 * Vaux1HwHPReq2Valid       = disabled
+	 * Vaux2HwHPReq2Valid       = disabled
+	 * Vaux3HwHPReq2Valid       = disabled
+	 */
+	INIT_REGULATOR_REGISTER(AB8505_REGUHWHPREQ2VALID1,     0xe8, 0x00),
+	/*
+	 * VsmpsMHwHPReq2Valid
+	 */
+	INIT_REGULATOR_REGISTER(AB8505_REGUHWHPREQ2VALID2,     0x00, 0x00),
+	/**
+	 * VsmpsCSwHPReqValid
+	 * VarmSwHPReqValid
+	 * VsmpsASwHPReqValid
+	 * VsmpsBSwHPReqValid
+	 * VsafeSwHPReqValid
+	 * VanaSwHPReqValid
+	 * VanaSwHPReqValid         = disabled
+	 * VpllSwHPReqValid
+	 * Vaux1SwHPReqValid        = disabled
+	 */
+	INIT_REGULATOR_REGISTER(AB8505_REGUSWHPREQVALID1,      0xa0, 0x00),
+	/*
+	 * Vaux2SwHPReqValid        = disabled
+	 * Vaux3SwHPReqValid        = disabled
+	 * VsmpsMSwHPReqValid
+	 */
+	INIT_REGULATOR_REGISTER(AB8505_REGUSWHPREQVALID2,      0x03, 0x00),
+	/*
+	 * SysClkReq2Valid1         = SysClkReq2 controlled
+	 * SysClkReq3Valid1         = disabled
+	 * SysClkReq4Valid1         = SysClkReq4 controlled
+	 */
+	INIT_REGULATOR_REGISTER(AB8505_REGUSYSCLKREQVALID1,    0x0e, 0x0a),
+	/*
+	 * SysClkReq2Valid2         = disabled
+	 * SysClkReq3Valid2         = disabled
+	 * SysClkReq4Valid2         = disabled
+	 */
+	INIT_REGULATOR_REGISTER(AB8505_REGUSYSCLKREQVALID2,    0x0e, 0x00),
+	/*
+	 * Vaux4SwHPReqValid
+	 * Vaux4HwHPReq2Valid
+	 * Vaux4HwHPReq1Valid
+	 * Vaux4SysClkReq1HPValid
+	 */
+	INIT_REGULATOR_REGISTER(AB8505_REGUVAUX4REQVALID,    0x00, 0x00),
+	/*
+	 * VadcEna                  = disabled
+	 * VintCore12Ena            = disabled
+	 * VintCore12Sel            = 1.25 V
+	 * VintCore12LP             = inactive (HP)
+	 * VadcLP                   = inactive (HP)
+	 */
+	INIT_REGULATOR_REGISTER(AB8505_REGUMISC1,              0xfe, 0x10),
+	/*
+	 * VaudioEna                = disabled
+	 * Vaux8Ena                 = disabled
+	 * Vamic1Ena                = disabled
+	 * Vamic2Ena                = disabled
+	 */
+	INIT_REGULATOR_REGISTER(AB8505_VAUDIOSUPPLY,           0x1e, 0x00),
+	/*
+	 * Vamic1_dzout             = high-Z when Vamic1 is disabled
+	 * Vamic2_dzout             = high-Z when Vamic2 is disabled
+	 */
+	INIT_REGULATOR_REGISTER(AB8505_REGUCTRL1VAMIC,         0x03, 0x00),
+	/*
+	 * VsmpsARegu
+	 * VsmpsASelCtrl
+	 * VsmpsAAutoMode
+	 * VsmpsAPWMMode
+	 */
+	INIT_REGULATOR_REGISTER(AB8505_VSMPSAREGU,    0x00, 0x00),
+	/*
+	 * VsmpsBRegu
+	 * VsmpsBSelCtrl
+	 * VsmpsBAutoMode
+	 * VsmpsBPWMMode
+	 */
+	INIT_REGULATOR_REGISTER(AB8505_VSMPSBREGU,    0x00, 0x00),
+	/*
+	 * VsafeRegu
+	 * VsafeSelCtrl
+	 * VsafeAutoMode
+	 * VsafePWMMode
+	 */
+	INIT_REGULATOR_REGISTER(AB8505_VSAFEREGU,    0x00, 0x00),
+	/*
+	 * VPll                     = Hw controlled (NOTE! PRCMU bits)
+	 * VanaRegu                 = force off
+	 */
+	INIT_REGULATOR_REGISTER(AB8505_VPLLVANAREGU,           0x0f, 0x02),
+	/*
+	 * VextSupply1Regu          = force OFF (OTP_ExtSupply12LPnPolarity 1)
+	 * VextSupply2Regu          = force OFF (OTP_ExtSupply12LPnPolarity 1)
+	 * VextSupply3Regu          = force OFF (OTP_ExtSupply3LPnPolarity 0)
+	 * ExtSupply2Bypass         = ExtSupply12LPn ball is 0 when Ena is 0
+	 * ExtSupply3Bypass         = ExtSupply3LPn ball is 0 when Ena is 0
+	 */
+	INIT_REGULATOR_REGISTER(AB8505_EXTSUPPLYREGU,          0xff, 0x30),
+	/*
+	 * Vaux1Regu                = force HP
+	 * Vaux2Regu                = force off
+	 */
+	INIT_REGULATOR_REGISTER(AB8505_VAUX12REGU,             0x0f, 0x01),
+	/*
+	 * Vaux3Regu                = force off
+	 */
+	INIT_REGULATOR_REGISTER(AB8505_VRF1VAUX3REGU,          0x03, 0x00),
+	/*
+	 * VsmpsASel1
+	 */
+	INIT_REGULATOR_REGISTER(AB8505_VSMPSASEL1,    0x00, 0x00),
+	/*
+	 * VsmpsASel2
+	 */
+	INIT_REGULATOR_REGISTER(AB8505_VSMPSASEL2,    0x00, 0x00),
+	/*
+	 * VsmpsASel3
+	 */
+	INIT_REGULATOR_REGISTER(AB8505_VSMPSASEL3,    0x00, 0x00),
+	/*
+	 * VsmpsBSel1
+	 */
+	INIT_REGULATOR_REGISTER(AB8505_VSMPSBSEL1,    0x00, 0x00),
+	/*
+	 * VsmpsBSel2
+	 */
+	INIT_REGULATOR_REGISTER(AB8505_VSMPSBSEL2,    0x00, 0x00),
+	/*
+	 * VsmpsBSel3
+	 */
+	INIT_REGULATOR_REGISTER(AB8505_VSMPSBSEL3,    0x00, 0x00),
+	/*
+	 * VsafeSel1
+	 */
+	INIT_REGULATOR_REGISTER(AB8505_VSAFESEL1,    0x00, 0x00),
+	/*
+	 * VsafeSel2
+	 */
+	INIT_REGULATOR_REGISTER(AB8505_VSAFESEL2,    0x00, 0x00),
+	/*
+	 * VsafeSel3
+	 */
+	INIT_REGULATOR_REGISTER(AB8505_VSAFESEL3,    0x00, 0x00),
+	/*
+	 * Vaux1Sel                 = 2.8 V
+	 */
+	INIT_REGULATOR_REGISTER(AB8505_VAUX1SEL,               0x0f, 0x0C),
+	/*
+	 * Vaux2Sel                 = 2.9 V
+	 */
+	INIT_REGULATOR_REGISTER(AB8505_VAUX2SEL,               0x0f, 0x0d),
+	/*
+	 * Vaux3Sel                 = 2.91 V
+	 */
+	INIT_REGULATOR_REGISTER(AB8505_VRF1VAUX3SEL,           0x07, 0x07),
+	/*
+	 * Vaux4RequestCtrl
+	 */
+	INIT_REGULATOR_REGISTER(AB8505_VAUX4REQCTRL,    0x00, 0x00),
+	/*
+	 * Vaux4Regu
+	 */
+	INIT_REGULATOR_REGISTER(AB8505_VAUX4REGU,    0x00, 0x00),
+	/*
+	 * Vaux4Sel
+	 */
+	INIT_REGULATOR_REGISTER(AB8505_VAUX4SEL,    0x00, 0x00),
+	/*
+	 * Vaux1Disch               = short discharge time
+	 * Vaux2Disch               = short discharge time
+	 * Vaux3Disch               = short discharge time
+	 * Vintcore12Disch          = short discharge time
+	 * VTVoutDisch              = short discharge time
+	 * VaudioDisch              = short discharge time
+	 */
+	INIT_REGULATOR_REGISTER(AB8505_REGUCTRLDISCH,          0xfc, 0x00),
+	/*
+	 * VanaDisch                = short discharge time
+	 * Vaux8PullDownEna         = pulldown disabled when Vaux8 is disabled
+	 * Vaux8Disch               = short discharge time
+	 */
+	INIT_REGULATOR_REGISTER(AB8505_REGUCTRLDISCH2,         0x16, 0x00),
+	/*
+	 * Vaux4Disch               = short discharge time
+	 */
+	INIT_REGULATOR_REGISTER(AB8505_REGUCTRLDISCH3,         0x01, 0x00),
+	/*
+	 * Vaux5Sel
+	 * Vaux5LP
+	 * Vaux5Ena
+	 * Vaux5Disch
+	 * Vaux5DisSfst
+	 * Vaux5DisPulld
+	 */
+	INIT_REGULATOR_REGISTER(AB8505_CTRLVAUX5,              0x00, 0x00),
+	/*
+	 * Vaux6Sel
+	 * Vaux6LP
+	 * Vaux6Ena
+	 * Vaux6DisPulld
+	 */
+	INIT_REGULATOR_REGISTER(AB8505_CTRLVAUX6,              0x00, 0x00),
+};
+
+struct regulator_init_data ab8505_regulators[AB8505_NUM_REGULATORS] = {
+	/* supplies to the display/camera */
+	[AB8505_LDO_AUX1] = {
+		.constraints = {
+			.name = "V-DISPLAY",
+			.min_uV = 2800000,
+			.max_uV = 3300000,
+			.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+					  REGULATOR_CHANGE_STATUS,
+			.boot_on = 1, /* display is on at boot */
+		},
+		.num_consumer_supplies = ARRAY_SIZE(ab8500_vaux1_consumers),
+		.consumer_supplies = ab8500_vaux1_consumers,
+	},
+	/* supplies to the on-board eMMC */
+	[AB8505_LDO_AUX2] = {
+		.constraints = {
+			.name = "V-eMMC1",
+			.min_uV = 1100000,
+			.max_uV = 3300000,
+			.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+					  REGULATOR_CHANGE_STATUS |
+					  REGULATOR_CHANGE_MODE,
+			.valid_modes_mask = REGULATOR_MODE_NORMAL |
+					    REGULATOR_MODE_IDLE,
+		},
+		.num_consumer_supplies = ARRAY_SIZE(ab8500_vaux2_consumers),
+		.consumer_supplies = ab8500_vaux2_consumers,
+	},
+	/* supply for VAUX3, supplies to SDcard slots */
+	[AB8505_LDO_AUX3] = {
+		.constraints = {
+			.name = "V-MMC-SD",
+			.min_uV = 1100000,
+			.max_uV = 3300000,
+			.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+					  REGULATOR_CHANGE_STATUS |
+					  REGULATOR_CHANGE_MODE,
+			.valid_modes_mask = REGULATOR_MODE_NORMAL |
+					    REGULATOR_MODE_IDLE,
+		},
+		.num_consumer_supplies = ARRAY_SIZE(ab8500_vaux3_consumers),
+		.consumer_supplies = ab8500_vaux3_consumers,
+	},
+	/* supply for VAUX4, supplies to NFC and standalone secure element */
+	[AB8505_LDO_AUX4] = {
+		.constraints = {
+			.name = "V-NFC-SE",
+			.min_uV = 1100000,
+			.max_uV = 3300000,
+			.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+					  REGULATOR_CHANGE_STATUS |
+					  REGULATOR_CHANGE_MODE,
+			.valid_modes_mask = REGULATOR_MODE_NORMAL |
+					    REGULATOR_MODE_IDLE,
+		},
+		.num_consumer_supplies = ARRAY_SIZE(ab8505_vaux4_consumers),
+		.consumer_supplies = ab8505_vaux4_consumers,
+	},
+	/* supply for VAUX5, supplies to TBD */
+	[AB8505_LDO_AUX5] = {
+		.constraints = {
+			.name = "V-AUX5",
+			.min_uV = 1050000,
+			.max_uV = 2790000,
+			.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+					  REGULATOR_CHANGE_STATUS |
+					  REGULATOR_CHANGE_MODE,
+			.valid_modes_mask = REGULATOR_MODE_NORMAL |
+					    REGULATOR_MODE_IDLE,
+		},
+		.num_consumer_supplies = ARRAY_SIZE(ab8505_vaux5_consumers),
+		.consumer_supplies = ab8505_vaux5_consumers,
+	},
+	/* supply for VAUX6, supplies to TBD */
+	[AB8505_LDO_AUX6] = {
+		.constraints = {
+			.name = "V-AUX6",
+			.min_uV = 1050000,
+			.max_uV = 2790000,
+			.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+					  REGULATOR_CHANGE_STATUS |
+					  REGULATOR_CHANGE_MODE,
+			.valid_modes_mask = REGULATOR_MODE_NORMAL |
+					    REGULATOR_MODE_IDLE,
+		},
+		.num_consumer_supplies = ARRAY_SIZE(ab8505_vaux6_consumers),
+		.consumer_supplies = ab8505_vaux6_consumers,
+	},
+	/* supply for gpadc, ADC LDO */
+	[AB8505_LDO_ADC] = {
+		.constraints = {
+			.name = "V-ADC",
+			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+		},
+		.num_consumer_supplies = ARRAY_SIZE(ab8505_vadc_consumers),
+		.consumer_supplies = ab8505_vadc_consumers,
+	},
+	/* supply for ab8500-vaudio, VAUDIO LDO */
+	[AB8505_LDO_AUDIO] = {
+		.constraints = {
+			.name = "V-AUD",
+			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+		},
+		.num_consumer_supplies = ARRAY_SIZE(ab8500_vaud_consumers),
+		.consumer_supplies = ab8500_vaud_consumers,
+	},
+	/* supply for v-anamic1 VAMic1-LDO */
+	[AB8505_LDO_ANAMIC1] = {
+		.constraints = {
+			.name = "V-AMIC1",
+			.valid_ops_mask = REGULATOR_CHANGE_STATUS |
+					  REGULATOR_CHANGE_MODE,
+			.valid_modes_mask = REGULATOR_MODE_NORMAL |
+					    REGULATOR_MODE_IDLE,
+		},
+		.num_consumer_supplies = ARRAY_SIZE(ab8500_vamic1_consumers),
+		.consumer_supplies = ab8500_vamic1_consumers,
+	},
+	/* supply for v-amic2, VAMIC2 LDO, reuse constants for AMIC1 */
+	[AB8505_LDO_ANAMIC2] = {
+		.constraints = {
+			.name = "V-AMIC2",
+			.valid_ops_mask = REGULATOR_CHANGE_STATUS |
+					  REGULATOR_CHANGE_MODE,
+			.valid_modes_mask = REGULATOR_MODE_NORMAL |
+					    REGULATOR_MODE_IDLE,
+		},
+		.num_consumer_supplies = ARRAY_SIZE(ab8500_vamic2_consumers),
+		.consumer_supplies = ab8500_vamic2_consumers,
+	},
+	/* supply for v-aux8, VAUX8 LDO */
+	[AB8505_LDO_AUX8] = {
+		.constraints = {
+			.name = "V-AUX8",
+			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+		},
+		.num_consumer_supplies = ARRAY_SIZE(ab8505_vaux8_consumers),
+		.consumer_supplies = ab8505_vaux8_consumers,
+	},
+	/* supply for v-intcore12, VINTCORE12 LDO */
+	[AB8505_LDO_INTCORE] = {
+		.constraints = {
+			.name = "V-INTCORE",
+			.min_uV = 1250000,
+			.max_uV = 1350000,
+			.input_uV = 1800000,
+			.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+					  REGULATOR_CHANGE_STATUS |
+					  REGULATOR_CHANGE_MODE |
+					  REGULATOR_CHANGE_DRMS,
+			.valid_modes_mask = REGULATOR_MODE_NORMAL |
+					    REGULATOR_MODE_IDLE,
+		},
+		.num_consumer_supplies = ARRAY_SIZE(ab8500_vintcore_consumers),
+		.consumer_supplies = ab8500_vintcore_consumers,
+	},
+	/* supply for LDO USB */
+	[AB8505_LDO_USB] = {
+		.constraints = {
+			.name = "V-USB",
+			.valid_ops_mask = REGULATOR_CHANGE_STATUS |
+					  REGULATOR_CHANGE_MODE,
+			.valid_modes_mask = REGULATOR_MODE_NORMAL |
+					    REGULATOR_MODE_IDLE,
+		},
+		.num_consumer_supplies = ARRAY_SIZE(ab8505_usb_consumers),
+		.consumer_supplies = ab8505_usb_consumers,
+	},
+	/* supply for U8500 CSI-DSI, VANA LDO */
+	[AB8505_LDO_ANA] = {
+		.constraints = {
+			.name = "V-CSI-DSI",
+			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+		},
+		.num_consumer_supplies = ARRAY_SIZE(ab8500_vana_consumers),
+		.consumer_supplies = ab8500_vana_consumers,
+	},
+};
+
+struct ab8500_regulator_platform_data ab8500_regulator_plat_data = {
+	.reg_init               = ab8500_reg_init,
+	.num_reg_init           = ARRAY_SIZE(ab8500_reg_init),
+	.regulator              = ab8500_regulators,
+	.num_regulator          = ARRAY_SIZE(ab8500_regulators),
+	.ext_regulator          = ab8500_ext_regulators,
+	.num_ext_regulator      = ARRAY_SIZE(ab8500_ext_regulators),
+};
+
+/* Use the AB8500 init settings for AB8505 as they are the same right now */
+struct ab8500_regulator_platform_data ab8505_regulator_plat_data = {
+	.reg_init               = ab8505_reg_init,
+	.num_reg_init           = ARRAY_SIZE(ab8505_reg_init),
+	.regulator              = ab8505_regulators,
+	.num_regulator          = ARRAY_SIZE(ab8505_regulators),
+};
+
+static void ab8500_modify_reg_init(int id, u8 mask, u8 value)
+{
+	int i;
+
+	if (cpu_is_u8520()) {
+		for (i = ARRAY_SIZE(ab8505_reg_init) - 1; i >= 0; i--) {
+			if (ab8505_reg_init[i].id == id) {
+				u8 initval = ab8505_reg_init[i].value;
+				initval = (initval & ~mask) | (value & mask);
+				ab8505_reg_init[i].value = initval;
+
+				BUG_ON(mask & ~ab8505_reg_init[i].mask);
+				return;
+			}
+		}
+	} else {
+		for (i = ARRAY_SIZE(ab8500_reg_init) - 1; i >= 0; i--) {
+			if (ab8500_reg_init[i].id == id) {
+				u8 initval = ab8500_reg_init[i].value;
+				initval = (initval & ~mask) | (value & mask);
+				ab8500_reg_init[i].value = initval;
+
+				BUG_ON(mask & ~ab8500_reg_init[i].mask);
+				return;
+			}
+		}
+	}
+
+	BUG_ON(1);
+}
+
+void mop500_regulator_init(void)
+{
+	struct regulator_init_data *regulator;
+
+	/*
+	 * Temporarily turn on Vaux2 on 8520 machine
+	 */
+	if (cpu_is_u8520()) {
+		/* Vaux2 initialized to be on */
+		ab8500_modify_reg_init(AB8505_VAUX12REGU, 0x0f, 0x05);
+	}
+
+	/*
+	 * Handle AB8500_EXT_SUPPLY2 on HREFP_V20_V50 boards (do it for
+	 * all HREFP_V20 boards)
+	 */
+	if (cpu_is_u8500v20()) {
+		/* VextSupply2RequestCtrl =  HP/OFF depending on VxRequest */
+		ab8500_modify_reg_init(AB8500_REGUREQUESTCTRL3, 0x01, 0x01);
+
+		/* VextSupply2SysClkReq1HPValid = SysClkReq1 controlled */
+		ab8500_modify_reg_init(AB8500_REGUSYSCLKREQ1HPVALID2,
+			0x20, 0x20);
+
+		/* VextSupply2 = force HP at initialization */
+		ab8500_modify_reg_init(AB8500_EXTSUPPLYREGU, 0x0c, 0x04);
+
+		/* enable VextSupply2 during platform active */
+		regulator = &ab8500_ext_regulators[AB8500_EXT_SUPPLY2];
+		regulator->constraints.always_on = 1;
+
+		/* disable VextSupply2 in suspend */
+		regulator = &ab8500_ext_regulators[AB8500_EXT_SUPPLY2];
+		regulator->constraints.state_mem.disabled = 1;
+		regulator->constraints.state_standby.disabled = 1;
+
+		/* enable VextSupply2 HW control (used in suspend) */
+		regulator->driver_data = (void *)&ab8500_ext_supply2;
+	}
+}
diff --git a/arch/arm/mach-ux500/board-mop500-regulators.h b/arch/arm/mach-ux500/board-mop500-regulators.h
index 78a0642..039f513 100644
--- a/arch/arm/mach-ux500/board-mop500-regulators.h
+++ b/arch/arm/mach-ux500/board-mop500-regulators.h
@@ -14,10 +14,12 @@
 #include <linux/regulator/machine.h>
 #include <linux/regulator/ab8500.h>
 
-extern struct ab8500_regulator_reg_init
-ab8500_regulator_reg_init[AB8500_NUM_REGULATOR_REGISTERS];
-extern struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS];
+extern struct ab8500_regulator_platform_data ab8500_regulator_plat_data;
+extern struct ab8500_regulator_platform_data ab8505_regulator_plat_data;
 extern struct regulator_init_data tps61052_regulator;
 extern struct regulator_init_data gpio_en_3v3_regulator;
+extern struct regulator_init_data sdi0_reg_init_data;
+
+void mop500_regulator_init(void);
 
 #endif
diff --git a/arch/arm/mach-ux500/board-mop500-sdi.c b/arch/arm/mach-ux500/board-mop500-sdi.c
index 051b62c..6db0740 100644
--- a/arch/arm/mach-ux500/board-mop500-sdi.c
+++ b/arch/arm/mach-ux500/board-mop500-sdi.c
@@ -31,35 +31,6 @@
  * SDI 0 (MicroSD slot)
  */
 
-/* GPIO pins used by the sdi0 level shifter */
-static int sdi0_en = -1;
-static int sdi0_vsel = -1;
-
-static int mop500_sdi0_ios_handler(struct device *dev, struct mmc_ios *ios)
-{
-	switch (ios->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 0;
-}
-
 #ifdef CONFIG_STE_DMA40
 struct stedma40_chan_cfg mop500_sdi0_dma_cfg_rx = {
 	.mode = STEDMA40_MODE_LOGICAL,
@@ -81,7 +52,6 @@ static struct stedma40_chan_cfg mop500_sdi0_dma_cfg_tx = {
 #endif
 
 struct mmci_platform_data mop500_sdi0_data = {
-	.ios_handler	= mop500_sdi0_ios_handler,
 	.ocr_mask	= MMC_VDD_29_30,
 	.f_max		= 50000000,
 	.capabilities	= MMC_CAP_4_BIT_DATA |
@@ -101,22 +71,6 @@ struct mmci_platform_data mop500_sdi0_data = {
 
 static void sdi0_configure(struct device *parent)
 {
-	int ret;
-
-	ret = gpio_request(sdi0_en, "level shifter enable");
-	if (!ret)
-		ret = gpio_request(sdi0_vsel,
-				   "level shifter 1v8-3v select");
-
-	if (ret) {
-		pr_warning("unable to config sdi0 gpios for level shifter.\n");
-		return;
-	}
-
-	/* Select the default 2.9V and enable level shifter */
-	gpio_direction_output(sdi0_vsel, 0);
-	gpio_direction_output(sdi0_en, 1);
-
 	/* Add the device, force v2 to subrevision 1 */
 	db8500_add_sdi0(parent, &mop500_sdi0_data, U8500_SDI_V2_PERIPHID);
 }
@@ -124,8 +78,6 @@ static void sdi0_configure(struct device *parent)
 void mop500_sdi_tc35892_init(struct device *parent)
 {
 	mop500_sdi0_data.gpio_cd = GPIO_SDMMC_CD;
-	sdi0_en = GPIO_SDMMC_EN;
-	sdi0_vsel = GPIO_SDMMC_1V8_3V_SEL;
 	sdi0_configure(parent);
 }
 
@@ -264,8 +216,6 @@ void __init snowball_sdi_init(struct device *parent)
 	/* External Micro SD slot */
 	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(parent);
 }
 
@@ -277,8 +227,6 @@ void __init hrefv60_sdi_init(struct device *parent)
 	db8500_add_sdi4(parent, &mop500_sdi4_data, U8500_SDI_V2_PERIPHID);
 	/* External Micro SD slot */
 	mop500_sdi0_data.gpio_cd = HREFV60_SDMMC_CD_GPIO;
-	sdi0_en = HREFV60_SDMMC_EN_GPIO;
-	sdi0_vsel = HREFV60_SDMMC_1V8_3V_GPIO;
 	sdi0_configure(parent);
 	/* WLAN SDIO channel */
 	db8500_add_sdi1(parent, &mop500_sdi1_data, U8500_SDI_V2_PERIPHID);
diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c
index b034578..574916b 100644
--- a/arch/arm/mach-ux500/board-mop500.c
+++ b/arch/arm/mach-ux500/board-mop500.c
@@ -12,6 +12,7 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
+#include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/i2c.h>
 #include <linux/platform_data/i2c-nomadik.h>
@@ -24,6 +25,8 @@
 #include <linux/mfd/abx500/ab8500.h>
 #include <linux/regulator/ab8500.h>
 #include <linux/regulator/fixed.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/gpio-regulator.h>
 #include <linux/mfd/tc3589x.h>
 #include <linux/mfd/tps6105x.h>
 #include <linux/mfd/abx500/ab8500-gpio.h>
@@ -89,6 +92,37 @@ static struct platform_device snowball_gpio_en_3v3_regulator_dev = {
        },
 };
 
+/* Dynamically populated. */
+static struct gpio sdi0_reg_gpios[] = {
+	{ 0, GPIOF_OUT_INIT_LOW, "mmci_vsel" },
+};
+
+static struct gpio_regulator_state sdi0_reg_states[] = {
+	{ .value = 2900000, .gpios = (0 << 0) },
+	{ .value = 1800000, .gpios = (1 << 0) },
+};
+
+static struct gpio_regulator_config sdi0_reg_info = {
+	.supply_name		= "ext-mmc-level-shifter",
+	.gpios			= sdi0_reg_gpios,
+	.nr_gpios		= ARRAY_SIZE(sdi0_reg_gpios),
+	.states			= sdi0_reg_states,
+	.nr_states		= ARRAY_SIZE(sdi0_reg_states),
+	.type			= REGULATOR_VOLTAGE,
+	.enable_high		= 1,
+	.enabled_at_boot	= 0,
+	.init_data		= &sdi0_reg_init_data,
+	.startup_delay		= 100,
+};
+
+static struct platform_device sdi0_regulator = {
+	.name = "gpio-regulator",
+	.id   = -1,
+	.dev  = {
+		.platform_data = &sdi0_reg_info,
+	},
+};
+
 static struct abx500_gpio_platform_data ab8500_gpio_pdata = {
 	.gpio_base		= MOP500_AB8500_PIN_GPIO(1),
 };
@@ -198,10 +232,7 @@ static struct platform_device snowball_sbnet_dev = {
 
 struct ab8500_platform_data ab8500_platdata = {
 	.irq_base	= MOP500_AB8500_IRQ_BASE,
-	.regulator_reg_init = ab8500_regulator_reg_init,
-	.num_regulator_reg_init	= ARRAY_SIZE(ab8500_regulator_reg_init),
-	.regulator	= ab8500_regulators,
-	.num_regulator	= ARRAY_SIZE(ab8500_regulators),
+	.regulator	= &ab8500_regulator_plat_data,
 	.gpio		= &ab8500_gpio_pdata,
 	.codec		= &ab8500_codec_pdata,
 };
@@ -439,6 +470,15 @@ static void mop500_prox_deactivate(struct device *dev)
 	regulator_put(prox_regulator);
 }
 
+void mop500_snowball_ethernet_clock_enable(void)
+{
+	struct clk *clk;
+
+	clk = clk_get_sys("fsmc", NULL);
+	if (!IS_ERR(clk))
+		clk_prepare_enable(clk);
+}
+
 static struct cryp_platform_data u8500_cryp1_platform_data = {
 		.mem_to_engine = {
 				.dir = STEDMA40_MEM_TO_PERIPH,
@@ -481,6 +521,7 @@ static struct hash_platform_data u8500_hash1_platform_data = {
 /* add any platform devices here - TODO */
 static struct platform_device *mop500_platform_devs[] __initdata = {
 	&mop500_gpio_keys_device,
+	&sdi0_regulator,
 };
 
 #ifdef CONFIG_STE_DMA40
@@ -624,6 +665,7 @@ static struct platform_device *snowball_platform_devs[] __initdata = {
 	&snowball_gpio_en_3v3_regulator_dev,
 	&u8500_thsens_device,
 	&u8500_cpufreq_cooling_device,
+	&sdi0_regulator,
 };
 
 static void __init mop500_init_machine(void)
@@ -635,6 +677,9 @@ static void __init mop500_init_machine(void)
 	platform_device_register(&db8500_prcmu_device);
 	mop500_gpio_keys[0].gpio = GPIO_PROX_SENSOR;
 
+	sdi0_reg_info.enable_gpio = GPIO_SDMMC_EN;
+	sdi0_reg_info.gpios[0].gpio = GPIO_SDMMC_1V8_3V_SEL;
+
 	mop500_pinmaps_init();
 	parent = u8500_init_devices(&ab8500_platdata);
 
@@ -668,6 +713,10 @@ static void __init snowball_init_machine(void)
 	int i;
 
 	platform_device_register(&db8500_prcmu_device);
+
+	sdi0_reg_info.enable_gpio = SNOWBALL_SDMMC_EN_GPIO;
+	sdi0_reg_info.gpios[0].gpio = SNOWBALL_SDMMC_1V8_3V_GPIO;
+
 	snowball_pinmaps_init();
 	parent = u8500_init_devices(&ab8500_platdata);
 
@@ -683,6 +732,8 @@ static void __init snowball_init_machine(void)
 	mop500_audio_init(parent);
 	mop500_uart_init(parent);
 
+	mop500_snowball_ethernet_clock_enable();
+
 	/* This board has full regulator constraints */
 	regulator_has_full_constraints();
 }
@@ -701,6 +752,9 @@ static void __init hrefv60_init_machine(void)
 	 */
 	mop500_gpio_keys[0].gpio = HREFV60_PROX_SENSE_GPIO;
 
+	sdi0_reg_info.enable_gpio = HREFV60_SDMMC_EN_GPIO;
+	sdi0_reg_info.gpios[0].gpio = HREFV60_SDMMC_1V8_3V_GPIO;
+
 	hrefv60_pinmaps_init();
 	parent = u8500_init_devices(&ab8500_platdata);
 
diff --git a/arch/arm/mach-ux500/board-mop500.h b/arch/arm/mach-ux500/board-mop500.h
index eaa605f..d38951b 100644
--- a/arch/arm/mach-ux500/board-mop500.h
+++ b/arch/arm/mach-ux500/board-mop500.h
@@ -104,6 +104,7 @@ void __init mop500_pinmaps_init(void);
 void __init snowball_pinmaps_init(void);
 void __init hrefv60_pinmaps_init(void);
 void mop500_audio_init(struct device *parent);
+void mop500_snowball_ethernet_clock_enable(void);
 
 int __init mop500_uib_init(void);
 void mop500_uib_i2c_add(int busnum, struct i2c_board_info *info,
diff --git a/arch/arm/mach-ux500/cache-l2x0.c b/arch/arm/mach-ux500/cache-l2x0.c
index 1c1609d..f815efe 100644
--- a/arch/arm/mach-ux500/cache-l2x0.c
+++ b/arch/arm/mach-ux500/cache-l2x0.c
@@ -47,8 +47,8 @@ static int __init ux500_l2x0_init(void)
 	/* Unlock before init */
 	ux500_l2x0_unlock();
 
-	/* DB9540's L2 has 128KB way size */
-	if (cpu_is_u9540())
+	/* DBx540's L2 has 128KB way size */
+	if (cpu_is_ux540_family())
 		/* 128KB way size */
 		aux_val |= (0x4 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT);
 	else
diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c
index 19235cf..5c6c2e6 100644
--- a/arch/arm/mach-ux500/cpu-db8500.c
+++ b/arch/arm/mach-ux500/cpu-db8500.c
@@ -282,6 +282,7 @@ static struct of_dev_auxdata u8500_auxdata_lookup[] __initdata = {
 	OF_DEV_AUXDATA("st,nomadik-i2c", 0x8012a000, "nmk-i2c.4", NULL),
 	OF_DEV_AUXDATA("stericsson,db8500-prcmu", 0x80157000, "db8500-prcmu",
 			&db8500_prcmu_pdata),
+	OF_DEV_AUXDATA("smsc,lan9115", 0x50000000, "smsc911x", NULL),
 	/* Requires device name bindings. */
 	OF_DEV_AUXDATA("stericsson,nmk-pinctrl", U8500_PRCMU_BASE,
 		"pinctrl-db8500", NULL),
@@ -312,9 +313,10 @@ static void __init u8500_init_machine(void)
 	/* Pinmaps must be in place before devices register */
 	if (of_machine_is_compatible("st-ericsson,mop500"))
 		mop500_pinmaps_init();
-	else if (of_machine_is_compatible("calaosystems,snowball-a9500"))
+	else if (of_machine_is_compatible("calaosystems,snowball-a9500")) {
 		snowball_pinmaps_init();
-	else if (of_machine_is_compatible("st-ericsson,hrefv60+"))
+		mop500_snowball_ethernet_clock_enable();
+	} else if (of_machine_is_compatible("st-ericsson,hrefv60+"))
 		hrefv60_pinmaps_init();
 	else if (of_machine_is_compatible("st-ericsson,ccu9540")) {}
 		/* TODO: Add pinmaps for ccu9540 board. */
diff --git a/arch/arm/mach-ux500/cpu.c b/arch/arm/mach-ux500/cpu.c
index 537870d..002da9a 100644
--- a/arch/arm/mach-ux500/cpu.c
+++ b/arch/arm/mach-ux500/cpu.c
@@ -140,14 +140,13 @@ struct device * __init ux500_soc_device_init(const char *soc_id)
 	soc_info_populate(soc_dev_attr, soc_id);
 
 	soc_dev = soc_device_register(soc_dev_attr);
-	if (IS_ERR_OR_NULL(soc_dev)) {
+	if (IS_ERR(soc_dev)) {
 	        kfree(soc_dev_attr);
 		return NULL;
 	}
 
 	parent = soc_device_to_device(soc_dev);
-	if (!IS_ERR_OR_NULL(parent))
-		device_create_file(parent, &ux500_soc_attr);
+	device_create_file(parent, &ux500_soc_attr);
 
 	return parent;
 }
diff --git a/arch/arm/mach-ux500/cpuidle.c b/arch/arm/mach-ux500/cpuidle.c
index ce91493..1b16d9e 100644
--- a/arch/arm/mach-ux500/cpuidle.c
+++ b/arch/arm/mach-ux500/cpuidle.c
@@ -11,7 +11,6 @@
 
 #include <linux/module.h>
 #include <linux/cpuidle.h>
-#include <linux/clockchips.h>
 #include <linux/spinlock.h>
 #include <linux/atomic.h>
 #include <linux/smp.h>
@@ -30,8 +29,6 @@ static inline int ux500_enter_idle(struct cpuidle_device *dev,
 	int this_cpu = smp_processor_id();
 	bool recouple = false;
 
-	clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &this_cpu);
-
 	if (atomic_inc_return(&master) == num_online_cpus()) {
 
 		/* With this lock, we prevent the other cpu to exit and enter
@@ -91,8 +88,6 @@ out:
 		spin_unlock(&master_lock);
 	}
 
-	clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &this_cpu);
-
 	return index;
 }
 
@@ -106,7 +101,8 @@ static struct cpuidle_driver ux500_idle_driver = {
 			.enter		  = ux500_enter_idle,
 			.exit_latency	  = 70,
 			.target_residency = 260,
-			.flags		  = CPUIDLE_FLAG_TIME_VALID,
+			.flags		  = CPUIDLE_FLAG_TIME_VALID |
+			                    CPUIDLE_FLAG_TIMER_STOP,
 			.name		  = "ApIdle",
 			.desc		  = "ARM Retention",
 		},
@@ -115,16 +111,6 @@ static struct cpuidle_driver ux500_idle_driver = {
 	.state_count = 2,
 };
 
-/*
- * For each cpu, setup the broadcast timer because we will
- * need to migrate the timers for the states >= ApIdle.
- */
-static void ux500_setup_broadcast_timer(void *arg)
-{
-	int cpu = smp_processor_id();
-	clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ON, &cpu);
-}
-
 int __init ux500_idle_init(void)
 {
 	int ret, cpu;
@@ -134,13 +120,6 @@ int __init ux500_idle_init(void)
 	prcmu_enable_wakeups(PRCMU_WAKEUP(ARM) | PRCMU_WAKEUP(RTC) |
 			     PRCMU_WAKEUP(ABB));
 
-	/*
-	 * Configure the timer broadcast for each cpu, that must
-	 * be done from the cpu context, so we use a smp cross
-	 * call with 'on_each_cpu'.
-	 */
-	on_each_cpu(ux500_setup_broadcast_timer, NULL, 1);
-
 	ret = cpuidle_register_driver(&ux500_idle_driver);
 	if (ret) {
 		printk(KERN_ERR "failed to register ux500 idle driver\n");
diff --git a/arch/arm/mach-ux500/platsmp.c b/arch/arm/mach-ux500/platsmp.c
index 18f7af3..152b130 100644
--- a/arch/arm/mach-ux500/platsmp.c
+++ b/arch/arm/mach-ux500/platsmp.c
@@ -16,7 +16,6 @@
 #include <linux/device.h>
 #include <linux/smp.h>
 #include <linux/io.h>
-#include <linux/irqchip/arm-gic.h>
 
 #include <asm/cacheflush.h>
 #include <asm/smp_plat.h>
@@ -58,13 +57,6 @@ static DEFINE_SPINLOCK(boot_lock);
 static void __cpuinit ux500_secondary_init(unsigned int cpu)
 {
 	/*
-	 * if any interrupts are already enabled for the primary
-	 * core (e.g. timer irq), then they will not have been enabled
-	 * for us: do so
-	 */
-	gic_secondary_init(0);
-
-	/*
 	 * let the primary processor know we're out of the
 	 * pen, then head off into the C entry point
 	 */
diff --git a/arch/arm/mach-ux500/timer.c b/arch/arm/mach-ux500/timer.c
index a6af0b8..d07bbe7 100644
--- a/arch/arm/mach-ux500/timer.c
+++ b/arch/arm/mach-ux500/timer.c
@@ -7,6 +7,7 @@
 #include <linux/io.h>
 #include <linux/errno.h>
 #include <linux/clksrc-dbx500-prcmu.h>
+#include <linux/clocksource.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/platform_data/clocksource-nomadik-mtu.h>
@@ -32,7 +33,7 @@ static void __init ux500_twd_init(void)
 	twd_local_timer = &u8500_twd_local_timer;
 
 	if (of_have_populated_dt())
-		twd_local_timer_of_register();
+		clocksource_of_init();
 	else {
 		err = twd_local_timer_register(twd_local_timer);
 		if (err)
diff --git a/arch/arm/mach-vexpress/Kconfig b/arch/arm/mach-vexpress/Kconfig
index 52d315b..0f1c5e5 100644
--- a/arch/arm/mach-vexpress/Kconfig
+++ b/arch/arm/mach-vexpress/Kconfig
@@ -17,6 +17,9 @@ config ARCH_VEXPRESS
 	select NO_IOPORT
 	select PLAT_VERSATILE
 	select PLAT_VERSATILE_CLCD
+	select POWER_RESET
+	select POWER_RESET_VEXPRESS
+	select POWER_SUPPLY
 	select REGULATOR_FIXED_VOLTAGE if REGULATOR
 	select VEXPRESS_CONFIG
 	help
diff --git a/arch/arm/mach-vexpress/Makefile b/arch/arm/mach-vexpress/Makefile
index 80b6497..42703e8 100644
--- a/arch/arm/mach-vexpress/Makefile
+++ b/arch/arm/mach-vexpress/Makefile
@@ -4,7 +4,7 @@
 ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include \
 	-I$(srctree)/arch/arm/plat-versatile/include
 
-obj-y					:= v2m.o reset.o
+obj-y					:= v2m.o
 obj-$(CONFIG_ARCH_VEXPRESS_CA9X4)	+= ct-ca9x4.o
 obj-$(CONFIG_SMP)			+= platsmp.o
 obj-$(CONFIG_HOTPLUG_CPU)		+= hotplug.o
diff --git a/arch/arm/mach-vexpress/reset.c b/arch/arm/mach-vexpress/reset.c
deleted file mode 100644
index 465923a..0000000
--- a/arch/arm/mach-vexpress/reset.c
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * This program is free software; you can 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 (C) 2012 ARM Limited
- */
-
-#include <linux/jiffies.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/platform_device.h>
-#include <linux/stat.h>
-#include <linux/vexpress.h>
-
-static void vexpress_reset_do(struct device *dev, const char *what)
-{
-	int err = -ENOENT;
-	struct vexpress_config_func *func =
-			vexpress_config_func_get_by_dev(dev);
-
-	if (func) {
-		unsigned long timeout;
-
-		err = vexpress_config_write(func, 0, 0);
-
-		timeout = jiffies + HZ;
-		while (time_before(jiffies, timeout))
-			cpu_relax();
-	}
-
-	dev_emerg(dev, "Unable to %s (%d)\n", what, err);
-}
-
-static struct device *vexpress_power_off_device;
-
-void vexpress_power_off(void)
-{
-	vexpress_reset_do(vexpress_power_off_device, "power off");
-}
-
-static struct device *vexpress_restart_device;
-
-void vexpress_restart(char str, const char *cmd)
-{
-	vexpress_reset_do(vexpress_restart_device, "restart");
-}
-
-static ssize_t vexpress_reset_active_show(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	return sprintf(buf, "%d\n", vexpress_restart_device == dev);
-}
-
-static ssize_t vexpress_reset_active_store(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t count)
-{
-	long value;
-	int err = kstrtol(buf, 0, &value);
-
-	if (!err && value)
-		vexpress_restart_device = dev;
-
-	return err ? err : count;
-}
-
-DEVICE_ATTR(active, S_IRUGO | S_IWUSR, vexpress_reset_active_show,
-		vexpress_reset_active_store);
-
-
-enum vexpress_reset_func { FUNC_RESET, FUNC_SHUTDOWN, FUNC_REBOOT };
-
-static struct of_device_id vexpress_reset_of_match[] = {
-	{
-		.compatible = "arm,vexpress-reset",
-		.data = (void *)FUNC_RESET,
-	}, {
-		.compatible = "arm,vexpress-shutdown",
-		.data = (void *)FUNC_SHUTDOWN
-	}, {
-		.compatible = "arm,vexpress-reboot",
-		.data = (void *)FUNC_REBOOT
-	},
-	{}
-};
-
-static int vexpress_reset_probe(struct platform_device *pdev)
-{
-	enum vexpress_reset_func func;
-	const struct of_device_id *match =
-			of_match_device(vexpress_reset_of_match, &pdev->dev);
-
-	if (match)
-		func = (enum vexpress_reset_func)match->data;
-	else
-		func = pdev->id_entry->driver_data;
-
-	switch (func) {
-	case FUNC_SHUTDOWN:
-		vexpress_power_off_device = &pdev->dev;
-		break;
-	case FUNC_RESET:
-		if (!vexpress_restart_device)
-			vexpress_restart_device = &pdev->dev;
-		device_create_file(&pdev->dev, &dev_attr_active);
-		break;
-	case FUNC_REBOOT:
-		vexpress_restart_device = &pdev->dev;
-		device_create_file(&pdev->dev, &dev_attr_active);
-		break;
-	};
-
-	return 0;
-}
-
-static const struct platform_device_id vexpress_reset_id_table[] = {
-	{ .name = "vexpress-reset", .driver_data = FUNC_RESET, },
-	{ .name = "vexpress-shutdown", .driver_data = FUNC_SHUTDOWN, },
-	{ .name = "vexpress-reboot", .driver_data = FUNC_REBOOT, },
-	{}
-};
-
-static struct platform_driver vexpress_reset_driver = {
-	.probe = vexpress_reset_probe,
-	.driver = {
-		.name = "vexpress-reset",
-		.of_match_table = vexpress_reset_of_match,
-	},
-	.id_table = vexpress_reset_id_table,
-};
-
-static int __init vexpress_reset_init(void)
-{
-	return platform_driver_register(&vexpress_reset_driver);
-}
-device_initcall(vexpress_reset_init);
diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c
index 915683c..992dc96 100644
--- a/arch/arm/mach-vexpress/v2m.c
+++ b/arch/arm/mach-vexpress/v2m.c
@@ -5,6 +5,7 @@
 #include <linux/amba/bus.h>
 #include <linux/amba/mmci.h>
 #include <linux/io.h>
+#include <linux/clocksource.h>
 #include <linux/smp.h>
 #include <linux/init.h>
 #include <linux/irqchip.h>
@@ -25,7 +26,6 @@
 #include <asm/arch_timer.h>
 #include <asm/mach-types.h>
 #include <asm/sizes.h>
-#include <asm/smp_twd.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
@@ -361,8 +361,6 @@ static void __init v2m_init(void)
 	for (i = 0; i < ARRAY_SIZE(v2m_amba_devs); i++)
 		amba_device_register(v2m_amba_devs[i], &iomem_resource);
 
-	pm_power_off = vexpress_power_off;
-
 	ct_desc->init_tile();
 }
 
@@ -374,7 +372,6 @@ MACHINE_START(VEXPRESS, "ARM-Versatile Express")
 	.init_irq	= v2m_init_irq,
 	.init_time	= v2m_timer_init,
 	.init_machine	= v2m_init,
-	.restart	= vexpress_restart,
 MACHINE_END
 
 static struct map_desc v2m_rs1_io_desc __initdata = {
@@ -435,6 +432,7 @@ static void __init v2m_dt_timer_init(void)
 
 	vexpress_clk_of_init();
 
+	clocksource_of_init();
 	do {
 		node = of_find_compatible_node(node, NULL, "arm,sp804");
 	} while (node && vexpress_get_site_by_node(node) != VEXPRESS_SITE_MB);
@@ -445,8 +443,7 @@ static void __init v2m_dt_timer_init(void)
 				irq_of_parse_and_map(node, 0));
 	}
 
-	if (arch_timer_of_register() != 0)
-		twd_local_timer_of_register();
+	arch_timer_of_register();
 
 	if (arch_timer_sched_clock_init() != 0)
 		versatile_sched_clock_init(vexpress_get_24mhz_clock_base(),
@@ -464,7 +461,6 @@ static void __init v2m_dt_init(void)
 {
 	l2x0_of_init(0x00400000, 0xfe0fffff);
 	of_platform_populate(NULL, v2m_dt_bus_match, NULL, NULL);
-	pm_power_off = vexpress_power_off;
 }
 
 static const char * const v2m_dt_match[] __initconst = {
@@ -481,5 +477,4 @@ DT_MACHINE_START(VEXPRESS_DT, "ARM-Versatile Express")
 	.init_irq	= irqchip_init,
 	.init_time	= v2m_dt_timer_init,
 	.init_machine	= v2m_dt_init,
-	.restart	= vexpress_restart,
 MACHINE_END
diff --git a/arch/arm/mach-virt/platsmp.c b/arch/arm/mach-virt/platsmp.c
index 8badaab..f4143f5 100644
--- a/arch/arm/mach-virt/platsmp.c
+++ b/arch/arm/mach-virt/platsmp.c
@@ -21,8 +21,6 @@
 #include <linux/smp.h>
 #include <linux/of.h>
 
-#include <linux/irqchip/arm-gic.h>
-
 #include <asm/psci.h>
 #include <asm/smp_plat.h>
 
@@ -45,14 +43,8 @@ static int __cpuinit virt_boot_secondary(unsigned int cpu,
 	return -ENODEV;
 }
 
-static void __cpuinit virt_secondary_init(unsigned int cpu)
-{
-	gic_secondary_init(0);
-}
-
 struct smp_operations __initdata virt_smp_ops = {
 	.smp_init_cpus		= virt_smp_init_cpus,
 	.smp_prepare_cpus	= virt_smp_prepare_cpus,
-	.smp_secondary_init	= virt_secondary_init,
 	.smp_boot_secondary	= virt_boot_secondary,
 };
diff --git a/arch/arm/mach-zynq/Kconfig b/arch/arm/mach-zynq/Kconfig
index adb6c0e..f4a7e63 100644
--- a/arch/arm/mach-zynq/Kconfig
+++ b/arch/arm/mach-zynq/Kconfig
@@ -8,6 +8,8 @@ config ARCH_ZYNQ
 	select ICST
 	select MIGHT_HAVE_CACHE_L2X0
 	select USE_OF
+	select HAVE_SMP
 	select SPARSE_IRQ
+	select CADENCE_TTC_TIMER
 	help
 	  Support for Xilinx Zynq ARM Cortex A9 Platform
diff --git a/arch/arm/mach-zynq/Makefile b/arch/arm/mach-zynq/Makefile
index 397268c..1b25d92 100644
--- a/arch/arm/mach-zynq/Makefile
+++ b/arch/arm/mach-zynq/Makefile
@@ -3,4 +3,8 @@
 #
 
 # Common support
-obj-y				:= common.o timer.o
+obj-y				:= common.o slcr.o
+CFLAGS_REMOVE_hotplug.o		=-march=armv6k
+CFLAGS_hotplug.o 		=-Wa,-march=armv7-a -mcpu=cortex-a9
+obj-$(CONFIG_HOTPLUG_CPU)	+= hotplug.o
+obj-$(CONFIG_SMP)		+= headsmp.o platsmp.o
diff --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c
index 5c89832..5bfe703 100644
--- a/arch/arm/mach-zynq/common.c
+++ b/arch/arm/mach-zynq/common.c
@@ -20,6 +20,7 @@
 #include <linux/platform_device.h>
 #include <linux/clk.h>
 #include <linux/clk/zynq.h>
+#include <linux/clocksource.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
@@ -32,20 +33,23 @@
 #include <asm/mach-types.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
+#include <asm/smp_scu.h>
 #include <asm/hardware/cache-l2x0.h>
 
 #include "common.h"
 
+void __iomem *zynq_scu_base;
+
 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.
+ * zynq_init_machine - System specific initialization, intended to be
+ *		       called from board specific initialization.
  */
-static void __init xilinx_init_machine(void)
+static void __init zynq_init_machine(void)
 {
 	/*
 	 * 64KB way size, 8-way associativity, parity disabled
@@ -55,50 +59,56 @@ static void __init xilinx_init_machine(void)
 	of_platform_bus_probe(NULL, zynq_of_bus_ids, NULL);
 }
 
-#define SCU_PERIPH_PHYS		0xF8F00000
-#define SCU_PERIPH_SIZE		SZ_8K
-#define SCU_PERIPH_VIRT		(VMALLOC_END - SCU_PERIPH_SIZE)
+static void __init zynq_timer_init(void)
+{
+	zynq_slcr_init();
+	clocksource_of_init();
+}
 
-static struct map_desc scu_desc __initdata = {
-	.virtual	= SCU_PERIPH_VIRT,
-	.pfn		= __phys_to_pfn(SCU_PERIPH_PHYS),
-	.length		= SCU_PERIPH_SIZE,
-	.type		= MT_DEVICE,
+static struct map_desc zynq_cortex_a9_scu_map __initdata = {
+	.length	= SZ_256,
+	.type	= MT_DEVICE,
 };
 
-static void __init xilinx_zynq_timer_init(void)
+static void __init zynq_scu_map_io(void)
 {
-	struct device_node *np;
-	void __iomem *slcr;
-
-	np = of_find_compatible_node(NULL, NULL, "xlnx,zynq-slcr");
-	slcr = of_iomap(np, 0);
-	WARN_ON(!slcr);
+	unsigned long base;
 
-	xilinx_zynq_clocks_init(slcr);
-
-	xttcps_timer_init();
+	base = scu_a9_get_base();
+	zynq_cortex_a9_scu_map.pfn = __phys_to_pfn(base);
+	/* Expected address is in vmalloc area that's why simple assign here */
+	zynq_cortex_a9_scu_map.virtual = base;
+	iotable_init(&zynq_cortex_a9_scu_map, 1);
+	zynq_scu_base = (void __iomem *)base;
+	BUG_ON(!zynq_scu_base);
 }
 
 /**
- * xilinx_map_io() - Create memory mappings needed for early I/O.
+ * zynq_map_io - Create memory mappings needed for early I/O.
  */
-static void __init xilinx_map_io(void)
+static void __init zynq_map_io(void)
 {
 	debug_ll_io_init();
-	iotable_init(&scu_desc, 1);
+	zynq_scu_map_io();
+}
+
+static void zynq_system_reset(char mode, const char *cmd)
+{
+	zynq_slcr_system_reset();
 }
 
-static const char *xilinx_dt_match[] = {
+static const char * const zynq_dt_match[] = {
 	"xlnx,zynq-zc702",
 	"xlnx,zynq-7000",
 	NULL
 };
 
 MACHINE_START(XILINX_EP107, "Xilinx Zynq Platform")
-	.map_io		= xilinx_map_io,
+	.smp		= smp_ops(zynq_smp_ops),
+	.map_io		= zynq_map_io,
 	.init_irq	= irqchip_init,
-	.init_machine	= xilinx_init_machine,
-	.init_time	= xilinx_zynq_timer_init,
-	.dt_compat	= xilinx_dt_match,
+	.init_machine	= zynq_init_machine,
+	.init_time	= zynq_timer_init,
+	.dt_compat	= zynq_dt_match,
+	.restart	= zynq_system_reset,
 MACHINE_END
diff --git a/arch/arm/mach-zynq/common.h b/arch/arm/mach-zynq/common.h
index 8b4dbba..fbbd0e2 100644
--- a/arch/arm/mach-zynq/common.h
+++ b/arch/arm/mach-zynq/common.h
@@ -17,6 +17,24 @@
 #ifndef __MACH_ZYNQ_COMMON_H__
 #define __MACH_ZYNQ_COMMON_H__
 
-void __init xttcps_timer_init(void);
+extern int zynq_slcr_init(void);
+extern void zynq_slcr_system_reset(void);
+extern void zynq_slcr_cpu_stop(int cpu);
+extern void zynq_slcr_cpu_start(int cpu);
+
+#ifdef CONFIG_SMP
+extern void secondary_startup(void);
+extern char zynq_secondary_trampoline;
+extern char zynq_secondary_trampoline_jump;
+extern char zynq_secondary_trampoline_end;
+extern int __cpuinit zynq_cpun_start(u32 address, int cpu);
+extern struct smp_operations zynq_smp_ops __initdata;
+#endif
+
+extern void __iomem *zynq_slcr_base;
+extern void __iomem *zynq_scu_base;
+
+/* Hotplug */
+extern void zynq_platform_cpu_die(unsigned int cpu);
 
 #endif
diff --git a/arch/arm/mach-zynq/headsmp.S b/arch/arm/mach-zynq/headsmp.S
new file mode 100644
index 0000000..d183cd2
--- /dev/null
+++ b/arch/arm/mach-zynq/headsmp.S
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2013 Steffen Trumtrar <s.trumtrar@pengutronix.de>
+ * Copyright (c) 2012-2013 Xilinx
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/linkage.h>
+#include <linux/init.h>
+
+	__CPUINIT
+
+ENTRY(zynq_secondary_trampoline)
+	ldr	r0, [pc]
+	bx	r0
+.globl zynq_secondary_trampoline_jump
+zynq_secondary_trampoline_jump:
+	/* Space for jumping address */
+	.word	/* cpu 1 */
+.globl zynq_secondary_trampoline_end
+zynq_secondary_trampoline_end:
+
+ENDPROC(zynq_secondary_trampoline)
diff --git a/arch/arm/mach-zynq/hotplug.c b/arch/arm/mach-zynq/hotplug.c
new file mode 100644
index 0000000..c89672b
--- /dev/null
+++ b/arch/arm/mach-zynq/hotplug.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2012-2013 Xilinx
+ *
+ * based on linux/arch/arm/mach-realview/hotplug.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/kernel.h>
+#include <linux/errno.h>
+#include <linux/smp.h>
+
+#include <asm/cacheflush.h>
+#include <asm/cp15.h>
+#include "common.h"
+
+static inline void zynq_cpu_enter_lowpower(void)
+{
+	unsigned int v;
+
+	flush_cache_all();
+	asm volatile(
+	"	mcr	p15, 0, %1, c7, c5, 0\n"
+	"	dsb\n"
+	/*
+	 * Turn off coherency
+	 */
+	"	mrc	p15, 0, %0, c1, c0, 1\n"
+	"	bic	%0, %0, #0x40\n"
+	"	mcr	p15, 0, %0, c1, c0, 1\n"
+	"	mrc	p15, 0, %0, c1, c0, 0\n"
+	"	bic	%0, %0, %2\n"
+	"	mcr	p15, 0, %0, c1, c0, 0\n"
+	  : "=&r" (v)
+	  : "r" (0), "Ir" (CR_C)
+	  : "cc");
+}
+
+static inline void zynq_cpu_leave_lowpower(void)
+{
+	unsigned int v;
+
+	asm volatile(
+	"	mrc	p15, 0, %0, c1, c0, 0\n"
+	"	orr	%0, %0, %1\n"
+	"	mcr	p15, 0, %0, c1, c0, 0\n"
+	"	mrc	p15, 0, %0, c1, c0, 1\n"
+	"	orr	%0, %0, #0x40\n"
+	"	mcr	p15, 0, %0, c1, c0, 1\n"
+	  : "=&r" (v)
+	  : "Ir" (CR_C)
+	  : "cc");
+}
+
+static inline void zynq_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 (;;) {
+		dsb();
+		wfi();
+
+		/*
+		 * Getting here, means that we have come out of WFI without
+		 * having been woken up - this shouldn't happen
+		 *
+		 * Just note it happening - when we're woken, we can report
+		 * its occurrence.
+		 */
+		(*spurious)++;
+	}
+}
+
+/*
+ * platform-specific code to shutdown a CPU
+ *
+ * Called with IRQs disabled
+ */
+void zynq_platform_cpu_die(unsigned int cpu)
+{
+	int spurious = 0;
+
+	/*
+	 * we're ready for shutdown now, so do it
+	 */
+	zynq_cpu_enter_lowpower();
+	zynq_platform_do_lowpower(cpu, &spurious);
+
+	/*
+	 * bring this CPU back into the world of cache
+	 * coherency, and then restore interrupts
+	 */
+	zynq_cpu_leave_lowpower();
+
+	if (spurious)
+		pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
+}
diff --git a/arch/arm/mach-zynq/platsmp.c b/arch/arm/mach-zynq/platsmp.c
new file mode 100644
index 0000000..3072cbd
--- /dev/null
+++ b/arch/arm/mach-zynq/platsmp.c
@@ -0,0 +1,152 @@
+/*
+ * This file contains Xilinx specific SMP code, used to start up
+ * the second processor.
+ *
+ * Copyright (C) 2011-2013 Xilinx
+ *
+ * based on linux/arch/arm/mach-realview/platsmp.c
+ *
+ * Copyright (C) 2002 ARM Ltd.
+ *
+ * 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/export.h>
+#include <linux/jiffies.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <asm/cacheflush.h>
+#include <asm/smp_scu.h>
+#include <linux/irqchip/arm-gic.h>
+#include "common.h"
+
+/*
+ * Store number of cores in the system
+ * Because of scu_get_core_count() must be in __init section and can't
+ * be called from zynq_cpun_start() because it is in __cpuinit section.
+ */
+static int ncores;
+
+/* Secondary CPU kernel startup is a 2 step process. The primary CPU
+ * starts the secondary CPU by giving it the address of the kernel and
+ * then sending it an event to wake it up. The secondary CPU then
+ * starts the kernel and tells the primary CPU it's up and running.
+ */
+static void __cpuinit zynq_secondary_init(unsigned int cpu)
+{
+	/*
+	 * if any interrupts are already enabled for the primary
+	 * core (e.g. timer irq), then they will not have been enabled
+	 * for us: do so
+	 */
+	gic_secondary_init(0);
+}
+
+int __cpuinit zynq_cpun_start(u32 address, int cpu)
+{
+	u32 trampoline_code_size = &zynq_secondary_trampoline_end -
+						&zynq_secondary_trampoline;
+
+	if (cpu > ncores) {
+		pr_warn("CPU No. is not available in the system\n");
+		return -1;
+	}
+
+	/* MS: Expectation that SLCR are directly map and accessible */
+	/* Not possible to jump to non aligned address */
+	if (!(address & 3) && (!address || (address >= trampoline_code_size))) {
+		/* Store pointer to ioremap area which points to address 0x0 */
+		static u8 __iomem *zero;
+		u32 trampoline_size = &zynq_secondary_trampoline_jump -
+						&zynq_secondary_trampoline;
+
+		zynq_slcr_cpu_stop(cpu);
+
+		if (__pa(PAGE_OFFSET)) {
+			zero = ioremap(0, trampoline_code_size);
+			if (!zero) {
+				pr_warn("BOOTUP jump vectors not accessible\n");
+				return -1;
+			}
+		} else {
+			zero = (__force u8 __iomem *)PAGE_OFFSET;
+		}
+
+		/*
+		 * This is elegant way how to jump to any address
+		 * 0x0: Load address at 0x8 to r0
+		 * 0x4: Jump by mov instruction
+		 * 0x8: Jumping address
+		 */
+		memcpy((__force void *)zero, &zynq_secondary_trampoline,
+						trampoline_size);
+		writel(address, zero + trampoline_size);
+
+		flush_cache_all();
+		outer_flush_range(0, trampoline_code_size);
+		smp_wmb();
+
+		if (__pa(PAGE_OFFSET))
+			iounmap(zero);
+
+		zynq_slcr_cpu_start(cpu);
+
+		return 0;
+	}
+
+	pr_warn("Can't start CPU%d: Wrong starting address %x\n", cpu, address);
+
+	return -1;
+}
+EXPORT_SYMBOL(zynq_cpun_start);
+
+static int __cpuinit zynq_boot_secondary(unsigned int cpu,
+						struct task_struct *idle)
+{
+	return zynq_cpun_start(virt_to_phys(secondary_startup), cpu);
+}
+
+/*
+ * Initialise the CPU possible map early - this describes the CPUs
+ * which may be present or become present in the system.
+ */
+static void __init zynq_smp_init_cpus(void)
+{
+	int i;
+
+	ncores = scu_get_core_count(zynq_scu_base);
+
+	for (i = 0; i < ncores && i < CONFIG_NR_CPUS; i++)
+		set_cpu_possible(i, true);
+}
+
+static void __init zynq_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(zynq_scu_base);
+}
+
+struct smp_operations zynq_smp_ops __initdata = {
+	.smp_init_cpus		= zynq_smp_init_cpus,
+	.smp_prepare_cpus	= zynq_smp_prepare_cpus,
+	.smp_secondary_init	= zynq_secondary_init,
+	.smp_boot_secondary	= zynq_boot_secondary,
+#ifdef CONFIG_HOTPLUG_CPU
+	.cpu_die		= zynq_platform_cpu_die,
+#endif
+};
diff --git a/arch/arm/mach-zynq/slcr.c b/arch/arm/mach-zynq/slcr.c
new file mode 100644
index 0000000..c70969b
--- /dev/null
+++ b/arch/arm/mach-zynq/slcr.c
@@ -0,0 +1,125 @@
+/*
+ * Xilinx SLCR driver
+ *
+ * Copyright (c) 2011-2013 Xilinx Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA
+ * 02139, USA.
+ */
+
+#include <linux/export.h>
+#include <linux/io.h>
+#include <linux/fs.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/uaccess.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/clk/zynq.h>
+#include "common.h"
+
+#define SLCR_UNLOCK_MAGIC		0xDF0D
+#define SLCR_UNLOCK			0x8   /* SCLR unlock register */
+
+#define SLCR_PS_RST_CTRL_OFFSET		0x200 /* PS Software Reset Control */
+
+#define SLCR_A9_CPU_CLKSTOP		0x10
+#define SLCR_A9_CPU_RST			0x1
+
+#define SLCR_A9_CPU_RST_CTRL		0x244 /* CPU Software Reset Control */
+#define SLCR_REBOOT_STATUS		0x258 /* PS Reboot Status */
+
+void __iomem *zynq_slcr_base;
+
+/**
+ * zynq_slcr_system_reset - Reset the entire system.
+ */
+void zynq_slcr_system_reset(void)
+{
+	u32 reboot;
+
+	/*
+	 * Unlock the SLCR then reset the system.
+	 * Note that this seems to require raw i/o
+	 * functions or there's a lockup?
+	 */
+	writel(SLCR_UNLOCK_MAGIC, zynq_slcr_base + SLCR_UNLOCK);
+
+	/*
+	 * Clear 0x0F000000 bits of reboot status register to workaround
+	 * the FSBL not loading the bitstream after soft-reboot
+	 * This is a temporary solution until we know more.
+	 */
+	reboot = readl(zynq_slcr_base + SLCR_REBOOT_STATUS);
+	writel(reboot & 0xF0FFFFFF, zynq_slcr_base + SLCR_REBOOT_STATUS);
+	writel(1, zynq_slcr_base + SLCR_PS_RST_CTRL_OFFSET);
+}
+
+/**
+ * zynq_slcr_cpu_start - Start cpu
+ * @cpu:	cpu number
+ */
+void zynq_slcr_cpu_start(int cpu)
+{
+	/* enable CPUn */
+	writel(SLCR_A9_CPU_CLKSTOP << cpu,
+	       zynq_slcr_base + SLCR_A9_CPU_RST_CTRL);
+	/* enable CLK for CPUn */
+	writel(0x0 << cpu, zynq_slcr_base + SLCR_A9_CPU_RST_CTRL);
+}
+
+/**
+ * zynq_slcr_cpu_stop - Stop cpu
+ * @cpu:	cpu number
+ */
+void zynq_slcr_cpu_stop(int cpu)
+{
+	/* stop CLK and reset CPUn */
+	writel((SLCR_A9_CPU_CLKSTOP | SLCR_A9_CPU_RST) << cpu,
+	       zynq_slcr_base + SLCR_A9_CPU_RST_CTRL);
+}
+
+/**
+ * zynq_slcr_init
+ * Returns 0 on success, negative errno otherwise.
+ *
+ * Called early during boot from platform code to remap SLCR area.
+ */
+int __init zynq_slcr_init(void)
+{
+	struct device_node *np;
+
+	np = of_find_compatible_node(NULL, NULL, "xlnx,zynq-slcr");
+	if (!np) {
+		pr_err("%s: no slcr node found\n", __func__);
+		BUG();
+	}
+
+	zynq_slcr_base = of_iomap(np, 0);
+	if (!zynq_slcr_base) {
+		pr_err("%s: Unable to map I/O memory\n", __func__);
+		BUG();
+	}
+
+	/* unlock the SLCR so that registers can be changed */
+	writel(SLCR_UNLOCK_MAGIC, zynq_slcr_base + SLCR_UNLOCK);
+
+	pr_info("%s mapped to %p\n", np->name, zynq_slcr_base);
+
+	xilinx_zynq_clocks_init(zynq_slcr_base);
+
+	of_node_put(np);
+
+	return 0;
+}
diff --git a/arch/arm/mach-zynq/timer.c b/arch/arm/mach-zynq/timer.c
deleted file mode 100644
index f9fbc9c..0000000
--- a/arch/arm/mach-zynq/timer.c
+++ /dev/null
@@ -1,324 +0,0 @@
-/*
- * 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/interrupt.h>
-#include <linux/clockchips.h>
-#include <linux/of_address.h>
-#include <linux/of_irq.h>
-#include <linux/slab.h>
-#include <linux/clk-provider.h>
-#include "common.h"
-
-/*
- * Timer Register Offset Definitions of Timer 1, Increment base address by 4
- * and use same offsets for Timer 2
- */
-#define XTTCPS_CLK_CNTRL_OFFSET		0x00 /* Clock Control Reg, RW */
-#define XTTCPS_CNT_CNTRL_OFFSET		0x0C /* Counter Control Reg, RW */
-#define XTTCPS_COUNT_VAL_OFFSET		0x18 /* Counter Value Reg, RO */
-#define XTTCPS_INTR_VAL_OFFSET		0x24 /* Interval Count Reg, RW */
-#define XTTCPS_ISR_OFFSET		0x54 /* Interrupt Status Reg, RO */
-#define XTTCPS_IER_OFFSET		0x60 /* Interrupt Enable Reg, RW */
-
-#define XTTCPS_CNT_CNTRL_DISABLE_MASK	0x1
-
-/*
- * Setup the timers to use pre-scaling, using a fixed value for now that will
- * work across most input frequency, but it may need to be more dynamic
- */
-#define PRESCALE_EXPONENT	11	/* 2 ^ PRESCALE_EXPONENT = PRESCALE */
-#define PRESCALE		2048	/* The exponent must match this */
-#define CLK_CNTRL_PRESCALE	((PRESCALE_EXPONENT - 1) << 1)
-#define CLK_CNTRL_PRESCALE_EN	1
-#define CNT_CNTRL_RESET		(1<<4)
-
-/**
- * struct xttcps_timer - This definition defines local timer structure
- *
- * @base_addr:	Base address of timer
- **/
-struct xttcps_timer {
-	void __iomem	*base_addr;
-};
-
-struct xttcps_timer_clocksource {
-	struct xttcps_timer	xttc;
-	struct clocksource	cs;
-};
-
-#define to_xttcps_timer_clksrc(x) \
-		container_of(x, struct xttcps_timer_clocksource, cs)
-
-struct xttcps_timer_clockevent {
-	struct xttcps_timer		xttc;
-	struct clock_event_device	ce;
-	struct clk			*clk;
-};
-
-#define to_xttcps_timer_clkevent(x) \
-		container_of(x, struct xttcps_timer_clockevent, ce)
-
-/**
- * xttcps_set_interval - Set the timer interval value
- *
- * @timer:	Pointer to the timer instance
- * @cycles:	Timer interval ticks
- **/
-static void xttcps_set_interval(struct xttcps_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 + XTTCPS_CNT_CNTRL_OFFSET);
-	ctrl_reg |= XTTCPS_CNT_CNTRL_DISABLE_MASK;
-	__raw_writel(ctrl_reg, timer->base_addr + XTTCPS_CNT_CNTRL_OFFSET);
-
-	__raw_writel(cycles, timer->base_addr + XTTCPS_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 |= CNT_CNTRL_RESET;
-	ctrl_reg &= ~XTTCPS_CNT_CNTRL_DISABLE_MASK;
-	__raw_writel(ctrl_reg, timer->base_addr + XTTCPS_CNT_CNTRL_OFFSET);
-}
-
-/**
- * xttcps_clock_event_interrupt - Clock event timer interrupt handler
- *
- * @irq:	IRQ number of the Timer
- * @dev_id:	void pointer to the xttcps_timer instance
- *
- * returns: Always IRQ_HANDLED - success
- **/
-static irqreturn_t xttcps_clock_event_interrupt(int irq, void *dev_id)
-{
-	struct xttcps_timer_clockevent *xttce = dev_id;
-	struct xttcps_timer *timer = &xttce->xttc;
-
-	/* Acknowledge the interrupt and call event handler */
-	__raw_readl(timer->base_addr + XTTCPS_ISR_OFFSET);
-
-	xttce->ce.event_handler(&xttce->ce);
-
-	return IRQ_HANDLED;
-}
-
-/**
- * __xttc_clocksource_read - Reads the timer counter register
- *
- * returns: Current timer counter register value
- **/
-static cycle_t __xttc_clocksource_read(struct clocksource *cs)
-{
-	struct xttcps_timer *timer = &to_xttcps_timer_clksrc(cs)->xttc;
-
-	return (cycle_t)__raw_readl(timer->base_addr +
-				XTTCPS_COUNT_VAL_OFFSET);
-}
-
-/**
- * xttcps_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 xttcps_set_next_event(unsigned long cycles,
-					struct clock_event_device *evt)
-{
-	struct xttcps_timer_clockevent *xttce = to_xttcps_timer_clkevent(evt);
-	struct xttcps_timer *timer = &xttce->xttc;
-
-	xttcps_set_interval(timer, cycles);
-	return 0;
-}
-
-/**
- * xttcps_set_mode - Sets the mode of timer
- *
- * @mode:	Mode to be set
- * @evt:	Address of clock event instance
- **/
-static void xttcps_set_mode(enum clock_event_mode mode,
-					struct clock_event_device *evt)
-{
-	struct xttcps_timer_clockevent *xttce = to_xttcps_timer_clkevent(evt);
-	struct xttcps_timer *timer = &xttce->xttc;
-	u32 ctrl_reg;
-
-	switch (mode) {
-	case CLOCK_EVT_MODE_PERIODIC:
-		xttcps_set_interval(timer,
-				     DIV_ROUND_CLOSEST(clk_get_rate(xttce->clk),
-						       PRESCALE * HZ));
-		break;
-	case CLOCK_EVT_MODE_ONESHOT:
-	case CLOCK_EVT_MODE_UNUSED:
-	case CLOCK_EVT_MODE_SHUTDOWN:
-		ctrl_reg = __raw_readl(timer->base_addr +
-					XTTCPS_CNT_CNTRL_OFFSET);
-		ctrl_reg |= XTTCPS_CNT_CNTRL_DISABLE_MASK;
-		__raw_writel(ctrl_reg,
-				timer->base_addr + XTTCPS_CNT_CNTRL_OFFSET);
-		break;
-	case CLOCK_EVT_MODE_RESUME:
-		ctrl_reg = __raw_readl(timer->base_addr +
-					XTTCPS_CNT_CNTRL_OFFSET);
-		ctrl_reg &= ~XTTCPS_CNT_CNTRL_DISABLE_MASK;
-		__raw_writel(ctrl_reg,
-				timer->base_addr + XTTCPS_CNT_CNTRL_OFFSET);
-		break;
-	}
-}
-
-static void __init zynq_ttc_setup_clocksource(struct device_node *np,
-					     void __iomem *base)
-{
-	struct xttcps_timer_clocksource *ttccs;
-	struct clk *clk;
-	int err;
-	u32 reg;
-
-	ttccs = kzalloc(sizeof(*ttccs), GFP_KERNEL);
-	if (WARN_ON(!ttccs))
-		return;
-
-	err = of_property_read_u32(np, "reg", &reg);
-	if (WARN_ON(err))
-		return;
-
-	clk = of_clk_get_by_name(np, "cpu_1x");
-	if (WARN_ON(IS_ERR(clk)))
-		return;
-
-	err = clk_prepare_enable(clk);
-	if (WARN_ON(err))
-		return;
-
-	ttccs->xttc.base_addr = base + reg * 4;
-
-	ttccs->cs.name = np->name;
-	ttccs->cs.rating = 200;
-	ttccs->cs.read = __xttc_clocksource_read;
-	ttccs->cs.mask = CLOCKSOURCE_MASK(16);
-	ttccs->cs.flags = CLOCK_SOURCE_IS_CONTINUOUS;
-
-	__raw_writel(0x0,  ttccs->xttc.base_addr + XTTCPS_IER_OFFSET);
-	__raw_writel(CLK_CNTRL_PRESCALE | CLK_CNTRL_PRESCALE_EN,
-		     ttccs->xttc.base_addr + XTTCPS_CLK_CNTRL_OFFSET);
-	__raw_writel(CNT_CNTRL_RESET,
-		     ttccs->xttc.base_addr + XTTCPS_CNT_CNTRL_OFFSET);
-
-	err = clocksource_register_hz(&ttccs->cs, clk_get_rate(clk) / PRESCALE);
-	if (WARN_ON(err))
-		return;
-}
-
-static void __init zynq_ttc_setup_clockevent(struct device_node *np,
-					    void __iomem *base)
-{
-	struct xttcps_timer_clockevent *ttcce;
-	int err, irq;
-	u32 reg;
-
-	ttcce = kzalloc(sizeof(*ttcce), GFP_KERNEL);
-	if (WARN_ON(!ttcce))
-		return;
-
-	err = of_property_read_u32(np, "reg", &reg);
-	if (WARN_ON(err))
-		return;
-
-	ttcce->xttc.base_addr = base + reg * 4;
-
-	ttcce->clk = of_clk_get_by_name(np, "cpu_1x");
-	if (WARN_ON(IS_ERR(ttcce->clk)))
-		return;
-
-	err = clk_prepare_enable(ttcce->clk);
-	if (WARN_ON(err))
-		return;
-
-	irq = irq_of_parse_and_map(np, 0);
-	if (WARN_ON(!irq))
-		return;
-
-	ttcce->ce.name = np->name;
-	ttcce->ce.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
-	ttcce->ce.set_next_event = xttcps_set_next_event;
-	ttcce->ce.set_mode = xttcps_set_mode;
-	ttcce->ce.rating = 200;
-	ttcce->ce.irq = irq;
-	ttcce->ce.cpumask = cpu_possible_mask;
-
-	__raw_writel(0x23, ttcce->xttc.base_addr + XTTCPS_CNT_CNTRL_OFFSET);
-	__raw_writel(CLK_CNTRL_PRESCALE | CLK_CNTRL_PRESCALE_EN,
-		     ttcce->xttc.base_addr + XTTCPS_CLK_CNTRL_OFFSET);
-	__raw_writel(0x1,  ttcce->xttc.base_addr + XTTCPS_IER_OFFSET);
-
-	err = request_irq(irq, xttcps_clock_event_interrupt, IRQF_TIMER,
-			  np->name, ttcce);
-	if (WARN_ON(err))
-		return;
-
-	clockevents_config_and_register(&ttcce->ce,
-					clk_get_rate(ttcce->clk) / PRESCALE,
-					1, 0xfffe);
-}
-
-static const __initconst struct of_device_id zynq_ttc_match[] = {
-	{ .compatible = "xlnx,ttc-counter-clocksource",
-		.data = zynq_ttc_setup_clocksource, },
-	{ .compatible = "xlnx,ttc-counter-clockevent",
-		.data = zynq_ttc_setup_clockevent, },
-	{}
-};
-
-/**
- * xttcps_timer_init - Initialize the timer
- *
- * Initializes the timer hardware and register the clock source and clock event
- * timers with Linux kernal timer framework
- **/
-void __init xttcps_timer_init(void)
-{
-	struct device_node *np;
-
-	for_each_compatible_node(np, NULL, "xlnx,ttc") {
-		struct device_node *np_chld;
-		void __iomem *base;
-
-		base = of_iomap(np, 0);
-		if (WARN_ON(!base))
-			return;
-
-		for_each_available_child_of_node(np, np_chld) {
-			int (*cb)(struct device_node *np, void __iomem *base);
-			const struct of_device_id *match;
-
-			match = of_match_node(zynq_ttc_match, np_chld);
-			if (match) {
-				cb = match->data;
-				cb(np_chld, base);
-			}
-		}
-	}
-}
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index 025d173..cb812a1 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -397,6 +397,13 @@ config CPU_V7
 	select CPU_PABRT_V7
 	select CPU_TLB_V7 if MMU
 
+config CPU_THUMBONLY
+	bool
+	# There are no CPUs available with MMU that don't implement an ARM ISA:
+	depends on !MMU
+	help
+	  Select this if your CPU doesn't support the 32 bit ARM instructions.
+
 # Figure out what processor architecture version we should be using.
 # This defines the compiler instruction set which depends on the machine type.
 config CPU_32v3
@@ -608,7 +615,7 @@ config ARCH_DMA_ADDR_T_64BIT
 	bool
 
 config ARM_THUMB
-	bool "Support Thumb user binaries"
+	bool "Support Thumb user binaries" if !CPU_THUMBONLY
 	depends on CPU_ARM720T || CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || CPU_ARM1020 || CPU_ARM1020E || CPU_ARM1022 || CPU_ARM1026 || CPU_XSCALE || CPU_XSC3 || CPU_MOHAWK || CPU_V6 || CPU_V6K || CPU_V7 || CPU_FEROCEON
 	default y
 	help
diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c
index db26e2e..6f4585b 100644
--- a/arch/arm/mm/alignment.c
+++ b/arch/arm/mm/alignment.c
@@ -961,12 +961,14 @@ static int __init alignment_init(void)
 		return -ENOMEM;
 #endif
 
+#ifdef CONFIG_CPU_CP15
 	if (cpu_is_v6_unaligned()) {
 		cr_alignment &= ~CR_A;
 		cr_no_alignment &= ~CR_A;
 		set_cr(cr_alignment);
 		ai_usermode = safe_usermode(ai_usermode, false);
 	}
+#endif
 
 	hook_fault_code(FAULT_CODE_ALIGNMENT, do_alignment, SIGBUS, BUS_ADRALN,
 			"alignment exception");
diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c
index c2f3739..c465fac 100644
--- a/arch/arm/mm/cache-l2x0.c
+++ b/arch/arm/mm/cache-l2x0.c
@@ -299,7 +299,7 @@ static void l2x0_unlock(u32 cache_id)
 	int lockregs;
 	int i;
 
-	switch (cache_id) {
+	switch (cache_id & L2X0_CACHE_ID_PART_MASK) {
 	case L2X0_CACHE_ID_PART_L310:
 		lockregs = 8;
 		break;
@@ -333,15 +333,14 @@ void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask)
 	if (cache_id_part_number_from_dt)
 		cache_id = cache_id_part_number_from_dt;
 	else
-		cache_id = readl_relaxed(l2x0_base + L2X0_CACHE_ID)
-			& L2X0_CACHE_ID_PART_MASK;
+		cache_id = readl_relaxed(l2x0_base + L2X0_CACHE_ID);
 	aux = readl_relaxed(l2x0_base + L2X0_AUX_CTRL);
 
 	aux &= aux_mask;
 	aux |= aux_val;
 
 	/* Determine the number of ways */
-	switch (cache_id) {
+	switch (cache_id & L2X0_CACHE_ID_PART_MASK) {
 	case L2X0_CACHE_ID_PART_L310:
 		if (aux & (1 << 16))
 			ways = 16;
@@ -725,7 +724,6 @@ static const struct l2x0_of_data pl310_data = {
 		.flush_all   = l2x0_flush_all,
 		.inv_all     = l2x0_inv_all,
 		.disable     = l2x0_disable,
-		.set_debug   = pl310_set_debug,
 	},
 };
 
@@ -814,9 +812,8 @@ int __init l2x0_of_init(u32 aux_val, u32 aux_mask)
 		data->save();
 
 	of_init = true;
-	l2x0_init(l2x0_base, aux_val, aux_mask);
-
 	memcpy(&outer_cache, &data->outer_cache, sizeof(outer_cache));
+	l2x0_init(l2x0_base, aux_val, aux_mask);
 
 	return 0;
 }
diff --git a/arch/arm/mm/context.c b/arch/arm/mm/context.c
index a5a4b2bc..2ac3737 100644
--- a/arch/arm/mm/context.c
+++ b/arch/arm/mm/context.c
@@ -48,7 +48,7 @@ static DEFINE_RAW_SPINLOCK(cpu_asid_lock);
 static atomic64_t asid_generation = ATOMIC64_INIT(ASID_FIRST_VERSION);
 static DECLARE_BITMAP(asid_map, NUM_USER_ASIDS);
 
-static DEFINE_PER_CPU(atomic64_t, active_asids);
+DEFINE_PER_CPU(atomic64_t, active_asids);
 static DEFINE_PER_CPU(u64, reserved_asids);
 static cpumask_t tlb_flush_pending;
 
@@ -215,6 +215,7 @@ void check_and_switch_context(struct mm_struct *mm, struct task_struct *tsk)
 	if (cpumask_test_and_clear_cpu(cpu, &tlb_flush_pending)) {
 		local_flush_bp_all();
 		local_flush_tlb_all();
+		dummy_flush_tlb_a15_erratum();
 	}
 
 	atomic64_set(&per_cpu(active_asids, cpu), asid);
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index ad722f1..9a5cdc0 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -99,6 +99,9 @@ void show_mem(unsigned int filter)
 	printk("Mem-info:\n");
 	show_free_areas(filter);
 
+	if (filter & SHOW_MEM_FILTER_PAGE_COUNT)
+		return;
+
 	for_each_bank (i, mi) {
 		struct membank *bank = &mi->bank[i];
 		unsigned int pfn1, pfn2;
@@ -424,24 +427,6 @@ void __init bootmem_init(void)
 	max_pfn = max_high - PHYS_PFN_OFFSET;
 }
 
-static inline int free_area(unsigned long pfn, unsigned long end, char *s)
-{
-	unsigned int pages = 0, size = (end - pfn) << (PAGE_SHIFT - 10);
-
-	for (; pfn < end; pfn++) {
-		struct page *page = pfn_to_page(pfn);
-		ClearPageReserved(page);
-		init_page_count(page);
-		__free_page(page);
-		pages++;
-	}
-
-	if (size && s)
-		printk(KERN_INFO "Freeing %s memory: %dK\n", s, size);
-
-	return pages;
-}
-
 /*
  * Poison init memory with an undefined instruction (ARM) or a branch to an
  * undefined instruction (Thumb).
@@ -534,6 +519,14 @@ static void __init free_unused_memmap(struct meminfo *mi)
 #endif
 }
 
+#ifdef CONFIG_HIGHMEM
+static inline void free_area_high(unsigned long pfn, unsigned long end)
+{
+	for (; pfn < end; pfn++)
+		free_highmem_page(pfn_to_page(pfn));
+}
+#endif
+
 static void __init free_highpages(void)
 {
 #ifdef CONFIG_HIGHMEM
@@ -569,8 +562,7 @@ static void __init free_highpages(void)
 			if (res_end > end)
 				res_end = end;
 			if (res_start != start)
-				totalhigh_pages += free_area(start, res_start,
-							     NULL);
+				free_area_high(start, res_start);
 			start = res_end;
 			if (start == end)
 				break;
@@ -578,9 +570,8 @@ static void __init free_highpages(void)
 
 		/* And now free anything which remains */
 		if (start < end)
-			totalhigh_pages += free_area(start, end, NULL);
+			free_area_high(start, end);
 	}
-	totalram_pages += totalhigh_pages;
 #endif
 }
 
@@ -609,8 +600,7 @@ void __init mem_init(void)
 
 #ifdef CONFIG_SA1111
 	/* now that our DMA memory is actually so designated, we can free it */
-	totalram_pages += free_area(PHYS_PFN_OFFSET,
-				    __phys_to_pfn(__pa(swapper_pg_dir)), NULL);
+	free_reserved_area(__va(PHYS_PFN_OFFSET), swapper_pg_dir, 0, NULL);
 #endif
 
 	free_highpages();
@@ -738,16 +728,12 @@ void free_initmem(void)
 	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");
+	free_reserved_area(&__tcm_start, &__tcm_end, 0, "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)),
-					    "init");
+		free_initmem_default(0);
 }
 
 #ifdef CONFIG_BLK_DEV_INITRD
@@ -758,9 +744,7 @@ void free_initrd_mem(unsigned long start, unsigned long end)
 {
 	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");
+		free_reserved_area(start, end, 0, "initrd");
 	}
 }
 
diff --git a/arch/arm/mm/mmap.c b/arch/arm/mm/mmap.c
index 10062ce..0c63562 100644
--- a/arch/arm/mm/mmap.c
+++ b/arch/arm/mm/mmap.c
@@ -181,11 +181,9 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
 	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;
 	}
 }
 
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index e95a996..a3549e9 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -112,6 +112,7 @@ static struct cachepolicy cache_policies[] __initdata = {
 	}
 };
 
+#ifdef CONFIG_CPU_CP15
 /*
  * These are useful for identifying cache coherency
  * problems by allowing the cache or the cache and
@@ -210,6 +211,22 @@ void adjust_cr(unsigned long mask, unsigned long set)
 }
 #endif
 
+#else /* ifdef CONFIG_CPU_CP15 */
+
+static int __init early_cachepolicy(char *p)
+{
+	pr_warning("cachepolicy kernel parameter not supported without cp15\n");
+}
+early_param("cachepolicy", early_cachepolicy);
+
+static int __init noalign_setup(char *__unused)
+{
+	pr_warning("noalign kernel parameter not supported without cp15\n");
+}
+__setup("noalign", noalign_setup);
+
+#endif /* ifdef CONFIG_CPU_CP15 / else */
+
 #define PROT_PTE_DEVICE		L_PTE_PRESENT|L_PTE_YOUNG|L_PTE_DIRTY|L_PTE_XN
 #define PROT_SECT_DEVICE	PMD_TYPE_SECT|PMD_SECT_AP_WRITE
 
@@ -598,39 +615,60 @@ static void __init alloc_init_pte(pmd_t *pmd, unsigned long addr,
 	} while (pte++, addr += PAGE_SIZE, addr != end);
 }
 
-static void __init alloc_init_section(pud_t *pud, unsigned long addr,
-				      unsigned long end, phys_addr_t phys,
-				      const struct mem_type *type)
+static void __init map_init_section(pmd_t *pmd, unsigned long addr,
+			unsigned long end, phys_addr_t phys,
+			const struct mem_type *type)
 {
-	pmd_t *pmd = pmd_offset(pud, addr);
-
+#ifndef CONFIG_ARM_LPAE
 	/*
-	 * Try a section mapping - end, addr and phys must all be aligned
-	 * to a section boundary.  Note that PMDs refer to the individual
-	 * L1 entries, whereas PGDs refer to a group of L1 entries making
-	 * up one logical pointer to an L2 table.
+	 * In classic MMU format, puds and pmds are folded in to
+	 * the pgds. pmd_offset gives the PGD entry. PGDs refer to a
+	 * group of L1 entries making up one logical pointer to
+	 * an L2 table (2MB), where as PMDs refer to the individual
+	 * L1 entries (1MB). Hence increment to get the correct
+	 * offset for odd 1MB sections.
+	 * (See arch/arm/include/asm/pgtable-2level.h)
 	 */
-	if (type->prot_sect && ((addr | end | phys) & ~SECTION_MASK) == 0) {
-		pmd_t *p = pmd;
-
-#ifndef CONFIG_ARM_LPAE
-		if (addr & SECTION_SIZE)
-			pmd++;
+	if (addr & SECTION_SIZE)
+		pmd++;
 #endif
+	do {
+		*pmd = __pmd(phys | type->prot_sect);
+		phys += SECTION_SIZE;
+	} while (pmd++, addr += SECTION_SIZE, addr != end);
 
-		do {
-			*pmd = __pmd(phys | type->prot_sect);
-			phys += SECTION_SIZE;
-		} while (pmd++, addr += SECTION_SIZE, addr != end);
+	flush_pmd_entry(pmd);
+}
 
-		flush_pmd_entry(p);
-	} else {
+static void __init alloc_init_pmd(pud_t *pud, unsigned long addr,
+				      unsigned long end, phys_addr_t phys,
+				      const struct mem_type *type)
+{
+	pmd_t *pmd = pmd_offset(pud, addr);
+	unsigned long next;
+
+	do {
 		/*
-		 * No need to loop; pte's aren't interested in the
-		 * individual L1 entries.
+		 * With LPAE, we must loop over to map
+		 * all the pmds for the given range.
 		 */
-		alloc_init_pte(pmd, addr, end, __phys_to_pfn(phys), type);
-	}
+		next = pmd_addr_end(addr, end);
+
+		/*
+		 * Try a section mapping - addr, next and phys must all be
+		 * aligned to a section boundary.
+		 */
+		if (type->prot_sect &&
+				((addr | next | phys) & ~SECTION_MASK) == 0) {
+			map_init_section(pmd, addr, next, phys, type);
+		} else {
+			alloc_init_pte(pmd, addr, next,
+						__phys_to_pfn(phys), type);
+		}
+
+		phys += next - addr;
+
+	} while (pmd++, addr = next, addr != end);
 }
 
 static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr,
@@ -641,7 +679,7 @@ static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr,
 
 	do {
 		next = pud_addr_end(addr, end);
-		alloc_init_section(pud, addr, next, phys, type);
+		alloc_init_pmd(pud, addr, next, phys, type);
 		phys += next - addr;
 	} while (pud++, addr = next, addr != end);
 }
diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S
index bcaaa8d..a286d47 100644
--- a/arch/arm/mm/proc-v6.S
+++ b/arch/arm/mm/proc-v6.S
@@ -80,12 +80,10 @@ ENTRY(cpu_v6_do_idle)
 	mov	pc, lr
 
 ENTRY(cpu_v6_dcache_clean_area)
-#ifndef TLB_CAN_READ_FROM_L1_CACHE
 1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
 	add	r0, r0, #D_CACHE_LINE_SIZE
 	subs	r1, r1, #D_CACHE_LINE_SIZE
 	bhi	1b
-#endif
 	mov	pc, lr
 
 /*
diff --git a/arch/arm/mm/proc-v7-2level.S b/arch/arm/mm/proc-v7-2level.S
index 78f520b..9704097 100644
--- a/arch/arm/mm/proc-v7-2level.S
+++ b/arch/arm/mm/proc-v7-2level.S
@@ -110,7 +110,8 @@ ENTRY(cpu_v7_set_pte_ext)
  ARM(	str	r3, [r0, #2048]! )
  THUMB(	add	r0, r0, #2048 )
  THUMB(	str	r3, [r0] )
-	mcr	p15, 0, r0, c7, c10, 1		@ flush_pte
+	ALT_SMP(mov	pc,lr)
+	ALT_UP (mcr	p15, 0, r0, c7, c10, 1)		@ flush_pte
 #endif
 	mov	pc, lr
 ENDPROC(cpu_v7_set_pte_ext)
diff --git a/arch/arm/mm/proc-v7-3level.S b/arch/arm/mm/proc-v7-3level.S
index 6ffd78c..363027e 100644
--- a/arch/arm/mm/proc-v7-3level.S
+++ b/arch/arm/mm/proc-v7-3level.S
@@ -73,7 +73,8 @@ ENTRY(cpu_v7_set_pte_ext)
 	tst	r3, #1 << (55 - 32)		@ L_PTE_DIRTY
 	orreq	r2, #L_PTE_RDONLY
 1:	strd	r2, r3, [r0]
-	mcr	p15, 0, r0, c7, c10, 1		@ flush_pte
+	ALT_SMP(mov	pc, lr)
+	ALT_UP (mcr	p15, 0, r0, c7, c10, 1)		@ flush_pte
 #endif
 	mov	pc, lr
 ENDPROC(cpu_v7_set_pte_ext)
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
index 3a3c015..5886ea1 100644
--- a/arch/arm/mm/proc-v7.S
+++ b/arch/arm/mm/proc-v7.S
@@ -75,14 +75,14 @@ ENTRY(cpu_v7_do_idle)
 ENDPROC(cpu_v7_do_idle)
 
 ENTRY(cpu_v7_dcache_clean_area)
-#ifndef TLB_CAN_READ_FROM_L1_CACHE
+	ALT_SMP(mov	pc, lr)			@ MP extensions imply L1 PTW
+	ALT_UP(W(nop))
 	dcache_line_size r2, r3
 1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
 	add	r0, r0, r2
 	subs	r1, r1, r2
 	bhi	1b
 	dsb
-#endif
 	mov	pc, lr
 ENDPROC(cpu_v7_dcache_clean_area)
 
@@ -420,7 +420,7 @@ __v7_pj4b_proc_info:
 __v7_ca7mp_proc_info:
 	.long	0x410fc070
 	.long	0xff0ffff0
-	__v7_proc __v7_ca7mp_setup, hwcaps = HWCAP_IDIV
+	__v7_proc __v7_ca7mp_setup
 	.size	__v7_ca7mp_proc_info, . - __v7_ca7mp_proc_info
 
 	/*
@@ -430,10 +430,25 @@ __v7_ca7mp_proc_info:
 __v7_ca15mp_proc_info:
 	.long	0x410fc0f0
 	.long	0xff0ffff0
-	__v7_proc __v7_ca15mp_setup, hwcaps = HWCAP_IDIV
+	__v7_proc __v7_ca15mp_setup
 	.size	__v7_ca15mp_proc_info, . - __v7_ca15mp_proc_info
 
 	/*
+	 * Qualcomm Inc. Krait processors.
+	 */
+	.type	__krait_proc_info, #object
+__krait_proc_info:
+	.long	0x510f0400		@ Required ID value
+	.long	0xff0ffc00		@ Mask for ID
+	/*
+	 * Some Krait processors don't indicate support for SDIV and UDIV
+	 * instructions in the ARM instruction set, even though they actually
+	 * do support them.
+	 */
+	__v7_proc __v7_setup, hwcaps = HWCAP_IDIV
+	.size	__krait_proc_info, . - __krait_proc_info
+
+	/*
 	 * Match any ARMv7 processor core.
 	 */
 	.type	__v7_proc_info, #object
diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c
index a0bd8a7..1a643ee 100644
--- a/arch/arm/net/bpf_jit_32.c
+++ b/arch/arm/net/bpf_jit_32.c
@@ -918,9 +918,8 @@ void bpf_jit_compile(struct sk_filter *fp)
 #endif
 
 	if (bpf_jit_enable > 1)
-		print_hex_dump(KERN_INFO, "BPF JIT code: ",
-			       DUMP_PREFIX_ADDRESS, 16, 4, ctx.target,
-			       alloc_size, false);
+		/* there are 2 passes here */
+		bpf_jit_dump(fp->len, alloc_size, 2, ctx.target);
 
 	fp->bpf_func = (void *)ctx.target;
 out:
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
index ce66eb9..f82bae2 100644
--- a/arch/arm/plat-omap/Kconfig
+++ b/arch/arm/plat-omap/Kconfig
@@ -86,22 +86,6 @@ config OMAP_MUX_WARNINGS
 	  to change the pin multiplexing setup.	 When there are no warnings
 	  printed, it's safe to deselect OMAP_MUX for your product.
 
-config OMAP_MBOX_FWK
-	tristate "Mailbox framework support"
-	depends on ARCH_OMAP && !ARCH_MULTIPLATFORM
-	help
-	  Say Y here if you want to use OMAP Mailbox framework support for
-	  DSP, IVA1.0 and IVA2 in OMAP1/2/3.
-
-config OMAP_MBOX_KFIFO_SIZE
-	int "Mailbox kfifo default buffer size (bytes)"
-	depends on OMAP_MBOX_FWK
-	default 256
-	help
-	  Specify the default size of mailbox's kfifo buffers (bytes).
-	  This can also be changed at runtime (via the mbox_kfifo_size
-	  module parameter).
-
 config OMAP_IOMMU_IVA2
 	bool
 
diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile
index 3119941..0b01b68 100644
--- a/arch/arm/plat-omap/Makefile
+++ b/arch/arm/plat-omap/Makefile
@@ -17,6 +17,3 @@ obj-$(CONFIG_OMAP_DEBUG_LEDS) += debug-leds.o
 i2c-omap-$(CONFIG_I2C_OMAP) := i2c.o
 obj-y += $(i2c-omap-m) $(i2c-omap-y)
 
-# OMAP mailbox framework
-obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox.o
-
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index a0daa2f..e6dbc8d 100644
--- a/arch/arm/plat-omap/dmtimer.c
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -140,8 +140,7 @@ static int omap_dm_timer_prepare(struct omap_dm_timer *timer)
 	 */
 	if (!(timer->capability & OMAP_TIMER_NEEDS_RESET)) {
 		timer->fclk = clk_get(&timer->pdev->dev, "fck");
-		if (WARN_ON_ONCE(IS_ERR_OR_NULL(timer->fclk))) {
-			timer->fclk = NULL;
+		if (WARN_ON_ONCE(IS_ERR(timer->fclk))) {
 			dev_err(&timer->pdev->dev, ": No fclk handle.\n");
 			return -EINVAL;
 		}
@@ -373,7 +372,7 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask);
 
 struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer)
 {
-	if (timer)
+	if (timer && !IS_ERR(timer->fclk))
 		return timer->fclk;
 	return NULL;
 }
@@ -482,7 +481,7 @@ int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
 	if (pdata && pdata->set_timer_src)
 		return pdata->set_timer_src(timer->pdev, source);
 
-	if (!timer->fclk)
+	if (IS_ERR(timer->fclk))
 		return -EINVAL;
 
 	switch (source) {
@@ -500,13 +499,13 @@ int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
 	}
 
 	parent = clk_get(&timer->pdev->dev, parent_name);
-	if (IS_ERR_OR_NULL(parent)) {
+	if (IS_ERR(parent)) {
 		pr_err("%s: %s not found\n", __func__, parent_name);
 		return -EINVAL;
 	}
 
 	ret = clk_set_parent(timer->fclk, parent);
-	if (IS_ERR_VALUE(ret))
+	if (ret < 0)
 		pr_err("%s: failed to set %s as parent\n", __func__,
 			parent_name);
 
@@ -808,6 +807,7 @@ static int omap_dm_timer_probe(struct platform_device *pdev)
 		return  -ENOMEM;
 	}
 
+	timer->fclk = ERR_PTR(-ENODEV);
 	timer->io_base = devm_ioremap_resource(dev, mem);
 	if (IS_ERR(timer->io_base))
 		return PTR_ERR(timer->io_base);
diff --git a/arch/arm/plat-omap/include/plat/mailbox.h b/arch/arm/plat-omap/include/plat/mailbox.h
deleted file mode 100644
index cc3921e..0000000
--- a/arch/arm/plat-omap/include/plat/mailbox.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/* mailbox.h */
-
-#ifndef MAILBOX_H
-#define MAILBOX_H
-
-#include <linux/spinlock.h>
-#include <linux/workqueue.h>
-#include <linux/interrupt.h>
-#include <linux/device.h>
-#include <linux/kfifo.h>
-
-typedef u32 mbox_msg_t;
-struct omap_mbox;
-
-typedef int __bitwise omap_mbox_irq_t;
-#define IRQ_TX ((__force omap_mbox_irq_t) 1)
-#define IRQ_RX ((__force omap_mbox_irq_t) 2)
-
-typedef int __bitwise omap_mbox_type_t;
-#define OMAP_MBOX_TYPE1 ((__force omap_mbox_type_t) 1)
-#define OMAP_MBOX_TYPE2 ((__force omap_mbox_type_t) 2)
-
-struct omap_mbox_ops {
-	omap_mbox_type_t	type;
-	int		(*startup)(struct omap_mbox *mbox);
-	void		(*shutdown)(struct omap_mbox *mbox);
-	/* fifo */
-	mbox_msg_t	(*fifo_read)(struct omap_mbox *mbox);
-	void		(*fifo_write)(struct omap_mbox *mbox, mbox_msg_t msg);
-	int		(*fifo_empty)(struct omap_mbox *mbox);
-	int		(*fifo_full)(struct omap_mbox *mbox);
-	/* irq */
-	void		(*enable_irq)(struct omap_mbox *mbox,
-						omap_mbox_irq_t irq);
-	void		(*disable_irq)(struct omap_mbox *mbox,
-						omap_mbox_irq_t irq);
-	void		(*ack_irq)(struct omap_mbox *mbox, omap_mbox_irq_t irq);
-	int		(*is_irq)(struct omap_mbox *mbox, omap_mbox_irq_t irq);
-	/* ctx */
-	void		(*save_ctx)(struct omap_mbox *mbox);
-	void		(*restore_ctx)(struct omap_mbox *mbox);
-};
-
-struct omap_mbox_queue {
-	spinlock_t		lock;
-	struct kfifo		fifo;
-	struct work_struct	work;
-	struct tasklet_struct	tasklet;
-	struct omap_mbox	*mbox;
-	bool full;
-};
-
-struct omap_mbox {
-	char			*name;
-	unsigned int		irq;
-	struct omap_mbox_queue	*txq, *rxq;
-	struct omap_mbox_ops	*ops;
-	struct device		*dev;
-	void			*priv;
-	int			use_count;
-	struct blocking_notifier_head   notifier;
-};
-
-int omap_mbox_msg_send(struct omap_mbox *, mbox_msg_t msg);
-void omap_mbox_init_seq(struct omap_mbox *);
-
-struct omap_mbox *omap_mbox_get(const char *, struct notifier_block *nb);
-void omap_mbox_put(struct omap_mbox *mbox, struct notifier_block *nb);
-
-int omap_mbox_register(struct device *parent, struct omap_mbox **);
-int omap_mbox_unregister(void);
-
-static inline void omap_mbox_save_ctx(struct omap_mbox *mbox)
-{
-	if (!mbox->ops->save_ctx) {
-		dev_err(mbox->dev, "%s:\tno save\n", __func__);
-		return;
-	}
-
-	mbox->ops->save_ctx(mbox);
-}
-
-static inline void omap_mbox_restore_ctx(struct omap_mbox *mbox)
-{
-	if (!mbox->ops->restore_ctx) {
-		dev_err(mbox->dev, "%s:\tno restore\n", __func__);
-		return;
-	}
-
-	mbox->ops->restore_ctx(mbox);
-}
-
-static inline void omap_mbox_enable_irq(struct omap_mbox *mbox,
-					omap_mbox_irq_t irq)
-{
-	mbox->ops->enable_irq(mbox, irq);
-}
-
-static inline void omap_mbox_disable_irq(struct omap_mbox *mbox,
-					 omap_mbox_irq_t irq)
-{
-	mbox->ops->disable_irq(mbox, irq);
-}
-
-#endif /* MAILBOX_H */
diff --git a/arch/arm/plat-omap/mailbox.c b/arch/arm/plat-omap/mailbox.c
deleted file mode 100644
index 42377ef..0000000
--- a/arch/arm/plat-omap/mailbox.c
+++ /dev/null
@@ -1,435 +0,0 @@
-/*
- * OMAP mailbox driver
- *
- * Copyright (C) 2006-2009 Nokia Corporation. All rights reserved.
- *
- * Contact: Hiroshi DOYU <Hiroshi.DOYU@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/interrupt.h>
-#include <linux/spinlock.h>
-#include <linux/mutex.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/kfifo.h>
-#include <linux/err.h>
-#include <linux/notifier.h>
-#include <linux/module.h>
-
-#include <plat/mailbox.h>
-
-static struct omap_mbox **mboxes;
-
-static int mbox_configured;
-static DEFINE_MUTEX(mbox_configured_lock);
-
-static unsigned int mbox_kfifo_size = CONFIG_OMAP_MBOX_KFIFO_SIZE;
-module_param(mbox_kfifo_size, uint, S_IRUGO);
-MODULE_PARM_DESC(mbox_kfifo_size, "Size of omap's mailbox kfifo (bytes)");
-
-/* Mailbox FIFO handle functions */
-static inline mbox_msg_t mbox_fifo_read(struct omap_mbox *mbox)
-{
-	return mbox->ops->fifo_read(mbox);
-}
-static inline void mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg)
-{
-	mbox->ops->fifo_write(mbox, msg);
-}
-static inline int mbox_fifo_empty(struct omap_mbox *mbox)
-{
-	return mbox->ops->fifo_empty(mbox);
-}
-static inline int mbox_fifo_full(struct omap_mbox *mbox)
-{
-	return mbox->ops->fifo_full(mbox);
-}
-
-/* Mailbox IRQ handle functions */
-static inline void ack_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
-{
-	if (mbox->ops->ack_irq)
-		mbox->ops->ack_irq(mbox, irq);
-}
-static inline int is_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
-{
-	return mbox->ops->is_irq(mbox, irq);
-}
-
-/*
- * message sender
- */
-static int __mbox_poll_for_space(struct omap_mbox *mbox)
-{
-	int ret = 0, i = 1000;
-
-	while (mbox_fifo_full(mbox)) {
-		if (mbox->ops->type == OMAP_MBOX_TYPE2)
-			return -1;
-		if (--i == 0)
-			return -1;
-		udelay(1);
-	}
-	return ret;
-}
-
-int omap_mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg)
-{
-	struct omap_mbox_queue *mq = mbox->txq;
-	int ret = 0, len;
-
-	spin_lock_bh(&mq->lock);
-
-	if (kfifo_avail(&mq->fifo) < sizeof(msg)) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	if (kfifo_is_empty(&mq->fifo) && !__mbox_poll_for_space(mbox)) {
-		mbox_fifo_write(mbox, msg);
-		goto out;
-	}
-
-	len = kfifo_in(&mq->fifo, (unsigned char *)&msg, sizeof(msg));
-	WARN_ON(len != sizeof(msg));
-
-	tasklet_schedule(&mbox->txq->tasklet);
-
-out:
-	spin_unlock_bh(&mq->lock);
-	return ret;
-}
-EXPORT_SYMBOL(omap_mbox_msg_send);
-
-static void mbox_tx_tasklet(unsigned long tx_data)
-{
-	struct omap_mbox *mbox = (struct omap_mbox *)tx_data;
-	struct omap_mbox_queue *mq = mbox->txq;
-	mbox_msg_t msg;
-	int ret;
-
-	while (kfifo_len(&mq->fifo)) {
-		if (__mbox_poll_for_space(mbox)) {
-			omap_mbox_enable_irq(mbox, IRQ_TX);
-			break;
-		}
-
-		ret = kfifo_out(&mq->fifo, (unsigned char *)&msg,
-								sizeof(msg));
-		WARN_ON(ret != sizeof(msg));
-
-		mbox_fifo_write(mbox, msg);
-	}
-}
-
-/*
- * Message receiver(workqueue)
- */
-static void mbox_rx_work(struct work_struct *work)
-{
-	struct omap_mbox_queue *mq =
-			container_of(work, struct omap_mbox_queue, work);
-	mbox_msg_t msg;
-	int len;
-
-	while (kfifo_len(&mq->fifo) >= sizeof(msg)) {
-		len = kfifo_out(&mq->fifo, (unsigned char *)&msg, sizeof(msg));
-		WARN_ON(len != sizeof(msg));
-
-		blocking_notifier_call_chain(&mq->mbox->notifier, len,
-								(void *)msg);
-		spin_lock_irq(&mq->lock);
-		if (mq->full) {
-			mq->full = false;
-			omap_mbox_enable_irq(mq->mbox, IRQ_RX);
-		}
-		spin_unlock_irq(&mq->lock);
-	}
-}
-
-/*
- * Mailbox interrupt handler
- */
-static void __mbox_tx_interrupt(struct omap_mbox *mbox)
-{
-	omap_mbox_disable_irq(mbox, IRQ_TX);
-	ack_mbox_irq(mbox, IRQ_TX);
-	tasklet_schedule(&mbox->txq->tasklet);
-}
-
-static void __mbox_rx_interrupt(struct omap_mbox *mbox)
-{
-	struct omap_mbox_queue *mq = mbox->rxq;
-	mbox_msg_t msg;
-	int len;
-
-	while (!mbox_fifo_empty(mbox)) {
-		if (unlikely(kfifo_avail(&mq->fifo) < sizeof(msg))) {
-			omap_mbox_disable_irq(mbox, IRQ_RX);
-			mq->full = true;
-			goto nomem;
-		}
-
-		msg = mbox_fifo_read(mbox);
-
-		len = kfifo_in(&mq->fifo, (unsigned char *)&msg, sizeof(msg));
-		WARN_ON(len != sizeof(msg));
-
-		if (mbox->ops->type == OMAP_MBOX_TYPE1)
-			break;
-	}
-
-	/* no more messages in the fifo. clear IRQ source. */
-	ack_mbox_irq(mbox, IRQ_RX);
-nomem:
-	schedule_work(&mbox->rxq->work);
-}
-
-static irqreturn_t mbox_interrupt(int irq, void *p)
-{
-	struct omap_mbox *mbox = p;
-
-	if (is_mbox_irq(mbox, IRQ_TX))
-		__mbox_tx_interrupt(mbox);
-
-	if (is_mbox_irq(mbox, IRQ_RX))
-		__mbox_rx_interrupt(mbox);
-
-	return IRQ_HANDLED;
-}
-
-static struct omap_mbox_queue *mbox_queue_alloc(struct omap_mbox *mbox,
-					void (*work) (struct work_struct *),
-					void (*tasklet)(unsigned long))
-{
-	struct omap_mbox_queue *mq;
-
-	mq = kzalloc(sizeof(struct omap_mbox_queue), GFP_KERNEL);
-	if (!mq)
-		return NULL;
-
-	spin_lock_init(&mq->lock);
-
-	if (kfifo_alloc(&mq->fifo, mbox_kfifo_size, GFP_KERNEL))
-		goto error;
-
-	if (work)
-		INIT_WORK(&mq->work, work);
-
-	if (tasklet)
-		tasklet_init(&mq->tasklet, tasklet, (unsigned long)mbox);
-	return mq;
-error:
-	kfree(mq);
-	return NULL;
-}
-
-static void mbox_queue_free(struct omap_mbox_queue *q)
-{
-	kfifo_free(&q->fifo);
-	kfree(q);
-}
-
-static int omap_mbox_startup(struct omap_mbox *mbox)
-{
-	int ret = 0;
-	struct omap_mbox_queue *mq;
-
-	mutex_lock(&mbox_configured_lock);
-	if (!mbox_configured++) {
-		if (likely(mbox->ops->startup)) {
-			ret = mbox->ops->startup(mbox);
-			if (unlikely(ret))
-				goto fail_startup;
-		} else
-			goto fail_startup;
-	}
-
-	if (!mbox->use_count++) {
-		ret = request_irq(mbox->irq, mbox_interrupt, IRQF_SHARED,
-							mbox->name, mbox);
-		if (unlikely(ret)) {
-			pr_err("failed to register mailbox interrupt:%d\n",
-									ret);
-			goto fail_request_irq;
-		}
-		mq = mbox_queue_alloc(mbox, NULL, mbox_tx_tasklet);
-		if (!mq) {
-			ret = -ENOMEM;
-			goto fail_alloc_txq;
-		}
-		mbox->txq = mq;
-
-		mq = mbox_queue_alloc(mbox, mbox_rx_work, NULL);
-		if (!mq) {
-			ret = -ENOMEM;
-			goto fail_alloc_rxq;
-		}
-		mbox->rxq = mq;
-		mq->mbox = mbox;
-
-		omap_mbox_enable_irq(mbox, IRQ_RX);
-	}
-	mutex_unlock(&mbox_configured_lock);
-	return 0;
-
-fail_alloc_rxq:
-	mbox_queue_free(mbox->txq);
-fail_alloc_txq:
-	free_irq(mbox->irq, mbox);
-fail_request_irq:
-	if (mbox->ops->shutdown)
-		mbox->ops->shutdown(mbox);
-	mbox->use_count--;
-fail_startup:
-	mbox_configured--;
-	mutex_unlock(&mbox_configured_lock);
-	return ret;
-}
-
-static void omap_mbox_fini(struct omap_mbox *mbox)
-{
-	mutex_lock(&mbox_configured_lock);
-
-	if (!--mbox->use_count) {
-		omap_mbox_disable_irq(mbox, IRQ_RX);
-		free_irq(mbox->irq, mbox);
-		tasklet_kill(&mbox->txq->tasklet);
-		flush_work(&mbox->rxq->work);
-		mbox_queue_free(mbox->txq);
-		mbox_queue_free(mbox->rxq);
-	}
-
-	if (likely(mbox->ops->shutdown)) {
-		if (!--mbox_configured)
-			mbox->ops->shutdown(mbox);
-	}
-
-	mutex_unlock(&mbox_configured_lock);
-}
-
-struct omap_mbox *omap_mbox_get(const char *name, struct notifier_block *nb)
-{
-	struct omap_mbox *_mbox, *mbox = NULL;
-	int i, ret;
-
-	if (!mboxes)
-		return ERR_PTR(-EINVAL);
-
-	for (i = 0; (_mbox = mboxes[i]); i++) {
-		if (!strcmp(_mbox->name, name)) {
-			mbox = _mbox;
-			break;
-		}
-	}
-
-	if (!mbox)
-		return ERR_PTR(-ENOENT);
-
-	if (nb)
-		blocking_notifier_chain_register(&mbox->notifier, nb);
-
-	ret = omap_mbox_startup(mbox);
-	if (ret) {
-		blocking_notifier_chain_unregister(&mbox->notifier, nb);
-		return ERR_PTR(-ENODEV);
-	}
-
-	return mbox;
-}
-EXPORT_SYMBOL(omap_mbox_get);
-
-void omap_mbox_put(struct omap_mbox *mbox, struct notifier_block *nb)
-{
-	blocking_notifier_chain_unregister(&mbox->notifier, nb);
-	omap_mbox_fini(mbox);
-}
-EXPORT_SYMBOL(omap_mbox_put);
-
-static struct class omap_mbox_class = { .name = "mbox", };
-
-int omap_mbox_register(struct device *parent, struct omap_mbox **list)
-{
-	int ret;
-	int i;
-
-	mboxes = list;
-	if (!mboxes)
-		return -EINVAL;
-
-	for (i = 0; mboxes[i]; i++) {
-		struct omap_mbox *mbox = mboxes[i];
-		mbox->dev = device_create(&omap_mbox_class,
-				parent, 0, mbox, "%s", mbox->name);
-		if (IS_ERR(mbox->dev)) {
-			ret = PTR_ERR(mbox->dev);
-			goto err_out;
-		}
-
-		BLOCKING_INIT_NOTIFIER_HEAD(&mbox->notifier);
-	}
-	return 0;
-
-err_out:
-	while (i--)
-		device_unregister(mboxes[i]->dev);
-	return ret;
-}
-EXPORT_SYMBOL(omap_mbox_register);
-
-int omap_mbox_unregister(void)
-{
-	int i;
-
-	if (!mboxes)
-		return -EINVAL;
-
-	for (i = 0; mboxes[i]; i++)
-		device_unregister(mboxes[i]->dev);
-	mboxes = NULL;
-	return 0;
-}
-EXPORT_SYMBOL(omap_mbox_unregister);
-
-static int __init omap_mbox_init(void)
-{
-	int err;
-
-	err = class_register(&omap_mbox_class);
-	if (err)
-		return err;
-
-	/* kfifo size sanity check: alignment and minimal size */
-	mbox_kfifo_size = ALIGN(mbox_kfifo_size, sizeof(mbox_msg_t));
-	mbox_kfifo_size = max_t(unsigned int, mbox_kfifo_size,
-							sizeof(mbox_msg_t));
-
-	return 0;
-}
-subsys_initcall(omap_mbox_init);
-
-static void __exit omap_mbox_exit(void)
-{
-	class_unregister(&omap_mbox_class);
-}
-module_exit(omap_mbox_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("omap mailbox: interrupt driven messaging");
-MODULE_AUTHOR("Toshihiro Kobayashi");
-MODULE_AUTHOR("Hiroshi DOYU");
diff --git a/arch/arm/plat-orion/Makefile b/arch/arm/plat-orion/Makefile
index a82cecb..b1c2a12 100644
--- a/arch/arm/plat-orion/Makefile
+++ b/arch/arm/plat-orion/Makefile
@@ -3,8 +3,12 @@
 #
 ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include
 
-obj-y                             += addr-map.o
+obj-$(CONFIG_ARCH_MVEBU)          += addr-map.o
+obj-$(CONFIG_ARCH_KIRKWOOD)       += addr-map.o
+obj-$(CONFIG_ARCH_DOVE)           += addr-map.o
+obj-$(CONFIG_ARCH_ORION5X)        += addr-map.o
+obj-$(CONFIG_ARCH_MV78XX0)        += addr-map.o
 
-orion-gpio-$(CONFIG_GENERIC_GPIO) += gpio.o
+orion-gpio-$(CONFIG_GPIOLIB)      += gpio.o
 obj-$(CONFIG_PLAT_ORION_LEGACY)   += irq.o pcie.o time.o common.o mpp.o
 obj-$(CONFIG_PLAT_ORION_LEGACY)   += $(orion-gpio-y)
diff --git a/arch/arm/plat-orion/common.c b/arch/arm/plat-orion/common.c
index 2d4b641..251f827 100644
--- a/arch/arm/plat-orion/common.c
+++ b/arch/arm/plat-orion/common.c
@@ -238,6 +238,7 @@ static __init void ge_complete(
 	struct mv643xx_eth_shared_platform_data *orion_ge_shared_data,
 	struct resource *orion_ge_resource, unsigned long irq,
 	struct platform_device *orion_ge_shared,
+	struct platform_device *orion_ge_mvmdio,
 	struct mv643xx_eth_platform_data *eth_data,
 	struct platform_device *orion_ge)
 {
@@ -247,6 +248,8 @@ static __init void ge_complete(
 	orion_ge->dev.platform_data = eth_data;
 
 	platform_device_register(orion_ge_shared);
+	if (orion_ge_mvmdio)
+		platform_device_register(orion_ge_mvmdio);
 	platform_device_register(orion_ge);
 }
 
@@ -258,8 +261,6 @@ struct mv643xx_eth_shared_platform_data orion_ge00_shared_data;
 static struct resource orion_ge00_shared_resources[] = {
 	{
 		.name	= "ge00 base",
-	}, {
-		.name	= "ge00 err irq",
 	},
 };
 
@@ -271,6 +272,19 @@ static struct platform_device orion_ge00_shared = {
 	},
 };
 
+static struct resource orion_ge_mvmdio_resources[] = {
+	{
+		.name	= "ge00 mvmdio base",
+	}, {
+		.name	= "ge00 mvmdio err irq",
+	},
+};
+
+static struct platform_device orion_ge_mvmdio = {
+	.name		= "orion-mdio",
+	.id		= -1,
+};
+
 static struct resource orion_ge00_resources[] = {
 	{
 		.name	= "ge00 irq",
@@ -295,26 +309,25 @@ void __init orion_ge00_init(struct mv643xx_eth_platform_data *eth_data,
 			    unsigned int tx_csum_limit)
 {
 	fill_resources(&orion_ge00_shared, orion_ge00_shared_resources,
-		       mapbase + 0x2000, SZ_16K - 1, irq_err);
+		       mapbase + 0x2000, SZ_16K - 1, NO_IRQ);
+	fill_resources(&orion_ge_mvmdio, orion_ge_mvmdio_resources,
+			mapbase + 0x2004, 0x84 - 1, irq_err);
 	orion_ge00_shared_data.tx_csum_limit = tx_csum_limit;
 	ge_complete(&orion_ge00_shared_data,
 		    orion_ge00_resources, irq, &orion_ge00_shared,
+		    &orion_ge_mvmdio,
 		    eth_data, &orion_ge00);
 }
 
 /*****************************************************************************
  * GE01
  ****************************************************************************/
-struct mv643xx_eth_shared_platform_data orion_ge01_shared_data = {
-	.shared_smi	= &orion_ge00_shared,
-};
+struct mv643xx_eth_shared_platform_data orion_ge01_shared_data;
 
 static struct resource orion_ge01_shared_resources[] = {
 	{
 		.name	= "ge01 base",
-	}, {
-		.name	= "ge01 err irq",
-	},
+	}
 };
 
 static struct platform_device orion_ge01_shared = {
@@ -349,26 +362,23 @@ void __init orion_ge01_init(struct mv643xx_eth_platform_data *eth_data,
 			    unsigned int tx_csum_limit)
 {
 	fill_resources(&orion_ge01_shared, orion_ge01_shared_resources,
-		       mapbase + 0x2000, SZ_16K - 1, irq_err);
+		       mapbase + 0x2000, SZ_16K - 1, NO_IRQ);
 	orion_ge01_shared_data.tx_csum_limit = tx_csum_limit;
 	ge_complete(&orion_ge01_shared_data,
 		    orion_ge01_resources, irq, &orion_ge01_shared,
+		    NULL,
 		    eth_data, &orion_ge01);
 }
 
 /*****************************************************************************
  * GE10
  ****************************************************************************/
-struct mv643xx_eth_shared_platform_data orion_ge10_shared_data = {
-	.shared_smi	= &orion_ge00_shared,
-};
+struct mv643xx_eth_shared_platform_data orion_ge10_shared_data;
 
 static struct resource orion_ge10_shared_resources[] = {
 	{
 		.name	= "ge10 base",
-	}, {
-		.name	= "ge10 err irq",
-	},
+	}
 };
 
 static struct platform_device orion_ge10_shared = {
@@ -402,24 +412,21 @@ void __init orion_ge10_init(struct mv643xx_eth_platform_data *eth_data,
 			    unsigned long irq_err)
 {
 	fill_resources(&orion_ge10_shared, orion_ge10_shared_resources,
-		       mapbase + 0x2000, SZ_16K - 1, irq_err);
+		       mapbase + 0x2000, SZ_16K - 1, NO_IRQ);
 	ge_complete(&orion_ge10_shared_data,
 		    orion_ge10_resources, irq, &orion_ge10_shared,
+		    NULL,
 		    eth_data, &orion_ge10);
 }
 
 /*****************************************************************************
  * GE11
  ****************************************************************************/
-struct mv643xx_eth_shared_platform_data orion_ge11_shared_data = {
-	.shared_smi	= &orion_ge00_shared,
-};
+struct mv643xx_eth_shared_platform_data orion_ge11_shared_data;
 
 static struct resource orion_ge11_shared_resources[] = {
 	{
 		.name	= "ge11 base",
-	}, {
-		.name	= "ge11 err irq",
 	},
 };
 
@@ -454,9 +461,10 @@ void __init orion_ge11_init(struct mv643xx_eth_platform_data *eth_data,
 			    unsigned long irq_err)
 {
 	fill_resources(&orion_ge11_shared, orion_ge11_shared_resources,
-		       mapbase + 0x2000, SZ_16K - 1, irq_err);
+		       mapbase + 0x2000, SZ_16K - 1, NO_IRQ);
 	ge_complete(&orion_ge11_shared_data,
 		    orion_ge11_resources, irq, &orion_ge11_shared,
+		    NULL,
 		    eth_data, &orion_ge11);
 }
 
diff --git a/arch/arm/plat-orion/pcie.c b/arch/arm/plat-orion/pcie.c
index f20a321..8b8c06d 100644
--- a/arch/arm/plat-orion/pcie.c
+++ b/arch/arm/plat-orion/pcie.c
@@ -120,12 +120,14 @@ void __init orion_pcie_reset(void __iomem *base)
  * BAR[0,2] -> disabled, BAR[1] -> covers all DRAM banks
  * WIN[0-3] -> DRAM bank[0-3]
  */
-static void __init orion_pcie_setup_wins(void __iomem *base,
-					 struct mbus_dram_target_info *dram)
+static void __init orion_pcie_setup_wins(void __iomem *base)
 {
+	const struct mbus_dram_target_info *dram;
 	u32 size;
 	int i;
 
+	dram = mv_mbus_dram_info();
+
 	/*
 	 * First, disable and clear BARs and windows.
 	 */
@@ -150,7 +152,7 @@ static void __init orion_pcie_setup_wins(void __iomem *base,
 	 */
 	size = 0;
 	for (i = 0; i < dram->num_cs; i++) {
-		struct mbus_dram_window *cs = dram->cs + i;
+		const struct mbus_dram_window *cs = dram->cs + i;
 
 		writel(cs->base & 0xffff0000, base + PCIE_WIN04_BASE_OFF(i));
 		writel(0, base + PCIE_WIN04_REMAP_OFF(i));
@@ -184,7 +186,7 @@ void __init orion_pcie_setup(void __iomem *base)
 	/*
 	 * Point PCIe unit MBUS decode windows to DRAM space.
 	 */
-	orion_pcie_setup_wins(base, &orion_mbus_dram_info);
+	orion_pcie_setup_wins(base);
 
 	/*
 	 * Master + slave enable.
diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig
index a9d5216..54d1861 100644
--- a/arch/arm/plat-samsung/Kconfig
+++ b/arch/arm/plat-samsung/Kconfig
@@ -25,7 +25,7 @@ config PLAT_S5P
 	select PLAT_SAMSUNG
 	select S3C_GPIO_TRACK
 	select S5P_GPIO_DRVSTR
-	select SAMSUNG_CLKSRC
+	select SAMSUNG_CLKSRC if !COMMON_CLK
 	select SAMSUNG_GPIOLIB_4BIT
 	select SAMSUNG_IRQ_VIC_TIMER
 	help
@@ -37,14 +37,6 @@ if PLAT_SAMSUNG
 
 comment "Boot options"
 
-config S3C_BOOT_WATCHDOG
-	bool "S3C Initialisation watchdog"
-	depends on S3C2410_WATCHDOG
-	help
-	  Say y to enable the watchdog during the kernel decompression
-	  stage. If the kernel fails to uncompress, then the watchdog
-	  will trigger a reset and the system should restart.
-
 config S3C_BOOT_ERROR_RESET
 	bool "S3C Reboot on decompression error"
 	help
@@ -70,7 +62,7 @@ config S3C_LOWLEVEL_UART_PORT
 
 # timer options
 
-config S5P_HRT
+config SAMSUNG_HRT
 	bool
 	select SAMSUNG_DEV_PWM
 	help
@@ -89,7 +81,7 @@ config SAMSUNG_CLKSRC
 	  used by newer systems such as the S3C64XX.
 
 config S5P_CLOCK
-	def_bool (ARCH_S5P64X0 || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_EXYNOS)
+	def_bool (ARCH_S5P64X0 || ARCH_S5PC100 || ARCH_S5PV210)
 	help
 	  Support common clock part for ARCH_S5P and ARCH_EXYNOS SoCs
 
@@ -125,12 +117,6 @@ config SAMSUNG_GPIOLIB_4BIT
 	  configuration. GPIOlib shall be compiled only for S3C64XX and S5P
 	  series of processors.
 
-config S3C_GPIO_CFG_S3C64XX
-	bool
-	help
-	  Internal configuration to enable S3C64XX style GPIO configuration
-	  functions.
-
 config S5P_GPIO_DRVSTR
 	bool
 	help
diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile
index 3a7c64d..a23c460 100644
--- a/arch/arm/plat-samsung/Makefile
+++ b/arch/arm/plat-samsung/Makefile
@@ -12,8 +12,7 @@ obj-				:=
 # Objects we always build independent of SoC choice
 
 obj-y				+= init.o cpu.o
-obj-$(CONFIG_ARCH_USES_GETTIMEOFFSET)   += time.o
-obj-$(CONFIG_S5P_HRT) 		+= s5p-time.o
+obj-$(CONFIG_SAMSUNG_HRT) 	+= samsung-time.o
 
 obj-$(CONFIG_SAMSUNG_CLOCK)	+= clock.o
 obj-$(CONFIG_SAMSUNG_CLOCK)	+= pwm-clock.o
diff --git a/arch/arm/plat-samsung/devs.c b/arch/arm/plat-samsung/devs.c
index 51afedd..6317a9e 100644
--- a/arch/arm/plat-samsung/devs.c
+++ b/arch/arm/plat-samsung/devs.c
@@ -62,7 +62,6 @@
 #include <linux/platform_data/usb-s3c2410_udc.h>
 #include <linux/platform_data/usb-ohci-s3c2410.h>
 #include <plat/usb-phy.h>
-#include <plat/regs-iic.h>
 #include <plat/regs-serial.h>
 #include <plat/regs-spi.h>
 #include <linux/platform_data/spi-s3c64xx.h>
@@ -1113,7 +1112,7 @@ struct platform_device s5p_device_onenand = {
 
 /* PMU */
 
-#ifdef CONFIG_PLAT_S5P
+#if defined(CONFIG_PLAT_S5P) && !defined(CONFIG_ARCH_EXYNOS)
 static struct resource s5p_pmu_resource[] = {
 	DEFINE_RES_IRQ(IRQ_PMU)
 };
diff --git a/arch/arm/plat-samsung/include/plat/common-smdk.h b/arch/arm/plat-samsung/include/plat/common-smdk.h
deleted file mode 100644
index ba028f1..0000000
--- a/arch/arm/plat-samsung/include/plat/common-smdk.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/* linux/arch/arm/plat-samsung/include/plat/common-smdk.h
- *
- * Copyright (c) 2006 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * Common code for SMDK2410 and SMDK2440 boards
- *
- * http://www.fluff.org/ben/smdk2440/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-extern void smdk_machine_init(void);
diff --git a/arch/arm/plat-samsung/include/plat/cpu.h b/arch/arm/plat-samsung/include/plat/cpu.h
index 37703ef..989fefe 100644
--- a/arch/arm/plat-samsung/include/plat/cpu.h
+++ b/arch/arm/plat-samsung/include/plat/cpu.h
@@ -23,6 +23,9 @@ extern unsigned long samsung_cpu_id;
 #define S3C24XX_CPU_ID		0x32400000
 #define S3C24XX_CPU_MASK	0xFFF00000
 
+#define S3C2412_CPU_ID		0x32412000
+#define S3C2412_CPU_MASK	0xFFFFF000
+
 #define S3C6400_CPU_ID		0x36400000
 #define S3C6410_CPU_ID		0x36410000
 #define S3C64XX_CPU_MASK	0xFFFFF000
@@ -53,6 +56,7 @@ static inline int is_samsung_##name(void)	\
 }
 
 IS_SAMSUNG_CPU(s3c24xx, S3C24XX_CPU_ID, S3C24XX_CPU_MASK)
+IS_SAMSUNG_CPU(s3c2412, S3C2412_CPU_ID, S3C2412_CPU_MASK)
 IS_SAMSUNG_CPU(s3c6400, S3C6400_CPU_ID, S3C64XX_CPU_MASK)
 IS_SAMSUNG_CPU(s3c6410, S3C6410_CPU_ID, S3C64XX_CPU_MASK)
 IS_SAMSUNG_CPU(s5p6440, S5P6440_CPU_ID, S5P64XX_CPU_MASK)
@@ -74,6 +78,12 @@ IS_SAMSUNG_CPU(exynos5440, EXYNOS5440_SOC_ID, EXYNOS5_SOC_MASK)
 # define soc_is_s3c24xx()	0
 #endif
 
+#if defined(CONFIG_CPU_S3C2412)
+# define soc_is_s3c2412()	is_samsung_s3c2412()
+#else
+# define soc_is_s3c2412()	0
+#endif
+
 #if defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410)
 # define soc_is_s3c64xx()	(is_samsung_s3c6400() || is_samsung_s3c6410())
 #else
@@ -173,7 +183,6 @@ extern void s3c_init_cpu(unsigned long idcode,
 
 /* core initialisation functions */
 
-extern void s3c24xx_init_irq(void);
 extern void s5p_init_irq(u32 *vic, u32 num_vic);
 
 extern void s3c24xx_init_io(struct map_desc *mach_desc, int size);
@@ -192,10 +201,6 @@ extern void s3c24xx_init_uartdevs(char *name,
 				  struct s3c24xx_uart_resources *res,
 				  struct s3c2410_uartcfg *cfg, int no);
 
-/* timer for 2410/2440 */
-
-extern void s3c24xx_timer_init(void);
-
 extern struct syscore_ops s3c2410_pm_syscore_ops;
 extern struct syscore_ops s3c2412_pm_syscore_ops;
 extern struct syscore_ops s3c2416_pm_syscore_ops;
diff --git a/arch/arm/plat-samsung/include/plat/irq.h b/arch/arm/plat-samsung/include/plat/irq.h
deleted file mode 100644
index e21a89b..0000000
--- a/arch/arm/plat-samsung/include/plat/irq.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/* linux/arch/arm/plat-samsung/include/plat/irq.h
- *
- * Copyright (c) 2004-2005 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * Header file for S3C24XX CPU IRQ 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 <mach/hardware.h>
-#include <mach/regs-irq.h>
-#include <mach/regs-gpio.h>
-
-#define irqdbf(x...)
-#define irqdbf2(x...)
-
-#define EXTINT_OFF (IRQ_EINT4 - 4)
-
-/* these are exported for arch/arm/mach-* usage */
-extern struct irq_chip s3c_irq_level_chip;
-extern struct irq_chip s3c_irq_chip;
-
-static inline void s3c_irqsub_mask(unsigned int irqno,
-				   unsigned int parentbit,
-				   int subcheck)
-{
-	unsigned long mask;
-	unsigned long submask;
-
-	submask = __raw_readl(S3C2410_INTSUBMSK);
-	mask = __raw_readl(S3C2410_INTMSK);
-
-	submask |= (1UL << (irqno - IRQ_S3CUART_RX0));
-
-	/* check to see if we need to mask the parent IRQ */
-
-	if ((submask  & subcheck) == subcheck)
-		__raw_writel(mask | parentbit, S3C2410_INTMSK);
-
-	/* write back masks */
-	__raw_writel(submask, S3C2410_INTSUBMSK);
-
-}
-
-static inline void s3c_irqsub_unmask(unsigned int irqno,
-				     unsigned int parentbit)
-{
-	unsigned long mask;
-	unsigned long submask;
-
-	submask = __raw_readl(S3C2410_INTSUBMSK);
-	mask = __raw_readl(S3C2410_INTMSK);
-
-	submask &= ~(1UL << (irqno - IRQ_S3CUART_RX0));
-	mask &= ~parentbit;
-
-	/* write back masks */
-	__raw_writel(submask, S3C2410_INTSUBMSK);
-	__raw_writel(mask, S3C2410_INTMSK);
-}
-
-
-static inline void s3c_irqsub_maskack(unsigned int irqno,
-				      unsigned int parentmask,
-				      unsigned int group)
-{
-	unsigned int bit = 1UL << (irqno - IRQ_S3CUART_RX0);
-
-	s3c_irqsub_mask(irqno, parentmask, group);
-
-	__raw_writel(bit, S3C2410_SUBSRCPND);
-
-	/* only ack parent if we've got all the irqs (seems we must
-	 * ack, all and hope that the irq system retriggers ok when
-	 * the interrupt goes off again)
-	 */
-
-	if (1) {
-		__raw_writel(parentmask, S3C2410_SRCPND);
-		__raw_writel(parentmask, S3C2410_INTPND);
-	}
-}
-
-static inline void s3c_irqsub_ack(unsigned int irqno,
-				  unsigned int parentmask,
-				  unsigned int group)
-{
-	unsigned int bit = 1UL << (irqno - IRQ_S3CUART_RX0);
-
-	__raw_writel(bit, S3C2410_SUBSRCPND);
-
-	/* only ack parent if we've got all the irqs (seems we must
-	 * ack, all and hope that the irq system retriggers ok when
-	 * the interrupt goes off again)
-	 */
-
-	if (1) {
-		__raw_writel(parentmask, S3C2410_SRCPND);
-		__raw_writel(parentmask, S3C2410_INTPND);
-	}
-}
-
-/* exported for use in arch/arm/mach-s3c2410 */
-
-#ifdef CONFIG_PM
-extern int s3c_irq_wake(struct irq_data *data, unsigned int state);
-#else
-#define s3c_irq_wake NULL
-#endif
-
-extern int s3c_irqext_type(struct irq_data *d, unsigned int type);
diff --git a/arch/arm/plat-samsung/include/plat/map-s5p.h b/arch/arm/plat-samsung/include/plat/map-s5p.h
index c2d7bda..c186786 100644
--- a/arch/arm/plat-samsung/include/plat/map-s5p.h
+++ b/arch/arm/plat-samsung/include/plat/map-s5p.h
@@ -22,6 +22,7 @@
 #define S5P_VA_GPIO3		S3C_ADDR(0x02280000)
 
 #define S5P_VA_SYSRAM		S3C_ADDR(0x02400000)
+#define S5P_VA_SYSRAM_NS	S3C_ADDR(0x02410000)
 #define S5P_VA_DMC0		S3C_ADDR(0x02440000)
 #define S5P_VA_DMC1		S3C_ADDR(0x02480000)
 #define S5P_VA_SROMC		S3C_ADDR(0x024C0000)
diff --git a/arch/arm/plat-samsung/include/plat/regs-iic.h b/arch/arm/plat-samsung/include/plat/regs-iic.h
deleted file mode 100644
index 2f7c17d..0000000
--- a/arch/arm/plat-samsung/include/plat/regs-iic.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/* arch/arm/mach-s3c2410/include/mach/regs-iic.h
- *
- * Copyright (c) 2004 Simtec Electronics <linux@simtec.co.uk>
- *		http://www.simtec.co.uk/products/SWLINUX/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * S3C2410 I2C Controller
-*/
-
-#ifndef __ASM_ARCH_REGS_IIC_H
-#define __ASM_ARCH_REGS_IIC_H __FILE__
-
-/* see s3c2410x user guide, v1.1, section 9 (p447) for more info */
-
-#define S3C2410_IICREG(x) (x)
-
-#define S3C2410_IICCON    S3C2410_IICREG(0x00)
-#define S3C2410_IICSTAT   S3C2410_IICREG(0x04)
-#define S3C2410_IICADD    S3C2410_IICREG(0x08)
-#define S3C2410_IICDS     S3C2410_IICREG(0x0C)
-#define S3C2440_IICLC	  S3C2410_IICREG(0x10)
-
-#define S3C2410_IICCON_ACKEN		(1<<7)
-#define S3C2410_IICCON_TXDIV_16		(0<<6)
-#define S3C2410_IICCON_TXDIV_512	(1<<6)
-#define S3C2410_IICCON_IRQEN		(1<<5)
-#define S3C2410_IICCON_IRQPEND		(1<<4)
-#define S3C2410_IICCON_SCALE(x)		((x)&15)
-#define S3C2410_IICCON_SCALEMASK	(0xf)
-
-#define S3C2410_IICSTAT_MASTER_RX	(2<<6)
-#define S3C2410_IICSTAT_MASTER_TX	(3<<6)
-#define S3C2410_IICSTAT_SLAVE_RX	(0<<6)
-#define S3C2410_IICSTAT_SLAVE_TX	(1<<6)
-#define S3C2410_IICSTAT_MODEMASK	(3<<6)
-
-#define S3C2410_IICSTAT_START		(1<<5)
-#define S3C2410_IICSTAT_BUSBUSY		(1<<5)
-#define S3C2410_IICSTAT_TXRXEN		(1<<4)
-#define S3C2410_IICSTAT_ARBITR		(1<<3)
-#define S3C2410_IICSTAT_ASSLAVE		(1<<2)
-#define S3C2410_IICSTAT_ADDR0		(1<<1)
-#define S3C2410_IICSTAT_LASTBIT		(1<<0)
-
-#define S3C2410_IICLC_SDA_DELAY0	(0 << 0)
-#define S3C2410_IICLC_SDA_DELAY5	(1 << 0)
-#define S3C2410_IICLC_SDA_DELAY10	(2 << 0)
-#define S3C2410_IICLC_SDA_DELAY15	(3 << 0)
-#define S3C2410_IICLC_SDA_DELAY_MASK	(3 << 0)
-
-#define S3C2410_IICLC_FILTER_ON		(1<<2)
-
-#endif /* __ASM_ARCH_REGS_IIC_H */
diff --git a/arch/arm/plat-samsung/include/plat/rtc-core.h b/arch/arm/plat-samsung/include/plat/rtc-core.h
index 21d8594..7b542f7 100644
--- a/arch/arm/plat-samsung/include/plat/rtc-core.h
+++ b/arch/arm/plat-samsung/include/plat/rtc-core.h
@@ -19,7 +19,7 @@
 /* re-define device name depending on support. */
 static inline void s3c_rtc_setname(char *name)
 {
-#if defined(CONFIG_SAMSUNG_DEV_RTC) || defined(CONFIG_PLAT_S3C24XX)
+#if defined(CONFIG_S3C_DEV_RTC) || defined(CONFIG_PLAT_S3C24XX)
 	s3c_device_rtc.name = name;
 #endif
 }
diff --git a/arch/arm/plat-samsung/include/plat/s3c2410.h b/arch/arm/plat-samsung/include/plat/s3c2410.h
deleted file mode 100644
index 55b0e5f..0000000
--- a/arch/arm/plat-samsung/include/plat/s3c2410.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/* linux/arch/arm/plat-samsung/include/plat/s3c2410.h
- *
- * Copyright (c) 2004 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * Header file for s3c2410 machine directory
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
-*/
-
-#ifdef CONFIG_CPU_S3C2410
-
-extern  int s3c2410_init(void);
-extern  int s3c2410a_init(void);
-
-extern void s3c2410_map_io(void);
-
-extern void s3c2410_init_uarts(struct s3c2410_uartcfg *cfg, int no);
-
-extern void s3c2410_init_clocks(int xtal);
-
-#else
-#define s3c2410_init_clocks NULL
-#define s3c2410_init_uarts NULL
-#define s3c2410_map_io NULL
-#define s3c2410_init NULL
-#define s3c2410a_init NULL
-#endif
diff --git a/arch/arm/plat-samsung/include/plat/s3c2412.h b/arch/arm/plat-samsung/include/plat/s3c2412.h
deleted file mode 100644
index cbae50d..0000000
--- a/arch/arm/plat-samsung/include/plat/s3c2412.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/* linux/arch/arm/plat-samsung/include/plat/s3c2412.h
- *
- * Copyright (c) 2006 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * Header file for s3c2412 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.
-*/
-
-#ifdef CONFIG_CPU_S3C2412
-
-extern  int s3c2412_init(void);
-
-extern void s3c2412_map_io(void);
-
-extern void s3c2412_init_uarts(struct s3c2410_uartcfg *cfg, int no);
-
-extern void s3c2412_init_clocks(int xtal);
-
-extern  int s3c2412_baseclk_add(void);
-
-extern void s3c2412_restart(char mode, const char *cmd);
-#else
-#define s3c2412_init_clocks NULL
-#define s3c2412_init_uarts NULL
-#define s3c2412_map_io NULL
-#define s3c2412_init NULL
-#define s3c2412_restart NULL
-#endif
diff --git a/arch/arm/plat-samsung/include/plat/s3c2416.h b/arch/arm/plat-samsung/include/plat/s3c2416.h
deleted file mode 100644
index f27399a..0000000
--- a/arch/arm/plat-samsung/include/plat/s3c2416.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* linux/arch/arm/plat-samsung/include/plat/s3c2416.h
- *
- * Copyright (c) 2009 Yauhen Kharuzhy <jekhor@gmail.com>
- *
- * Header file for s3c2416 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.
-*/
-
-#ifdef CONFIG_CPU_S3C2416
-
-struct s3c2410_uartcfg;
-
-extern  int s3c2416_init(void);
-
-extern void s3c2416_map_io(void);
-
-extern void s3c2416_init_uarts(struct s3c2410_uartcfg *cfg, int no);
-
-extern void s3c2416_init_clocks(int xtal);
-
-extern  int s3c2416_baseclk_add(void);
-
-extern void s3c2416_restart(char mode, const char *cmd);
-
-extern void s3c2416_init_irq(void);
-extern struct syscore_ops s3c2416_irq_syscore_ops;
-
-#else
-#define s3c2416_init_clocks NULL
-#define s3c2416_init_uarts NULL
-#define s3c2416_map_io NULL
-#define s3c2416_init NULL
-#define s3c2416_restart NULL
-#endif
diff --git a/arch/arm/plat-samsung/include/plat/s3c2443.h b/arch/arm/plat-samsung/include/plat/s3c2443.h
deleted file mode 100644
index 71b88ec..0000000
--- a/arch/arm/plat-samsung/include/plat/s3c2443.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/* linux/arch/arm/plat-samsung/include/plat/s3c2443.h
- *
- * Copyright (c) 2004-2005 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * Header file for s3c2443 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.
-*/
-
-#ifdef CONFIG_CPU_S3C2443
-
-struct s3c2410_uartcfg;
-
-extern  int s3c2443_init(void);
-
-extern void s3c2443_map_io(void);
-
-extern void s3c2443_init_uarts(struct s3c2410_uartcfg *cfg, int no);
-
-extern void s3c2443_init_clocks(int xtal);
-
-extern  int s3c2443_baseclk_add(void);
-
-extern void s3c2443_restart(char mode, const char *cmd);
-
-extern void s3c2443_init_irq(void);
-#else
-#define s3c2443_init_clocks NULL
-#define s3c2443_init_uarts NULL
-#define s3c2443_map_io NULL
-#define s3c2443_init NULL
-#define s3c2443_restart NULL
-#endif
diff --git a/arch/arm/plat-samsung/include/plat/s3c244x.h b/arch/arm/plat-samsung/include/plat/s3c244x.h
deleted file mode 100644
index ea0c961..0000000
--- a/arch/arm/plat-samsung/include/plat/s3c244x.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/* linux/arch/arm/plat-samsung/include/plat/s3c244x.h
- *
- * Copyright (c) 2004-2005 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * Header file for S3C2440 and S3C2442 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.
-*/
-
-#if defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2442)
-
-extern void s3c244x_map_io(void);
-
-extern void s3c244x_init_uarts(struct s3c2410_uartcfg *cfg, int no);
-
-extern void s3c244x_init_clocks(int xtal);
-
-#else
-#define s3c244x_init_clocks NULL
-#define s3c244x_init_uarts NULL
-#endif
-
-#ifdef CONFIG_CPU_S3C2440
-extern  int s3c2440_init(void);
-
-extern void s3c2440_map_io(void);
-#else
-#define s3c2440_init NULL
-#define s3c2440_map_io NULL
-#endif
-
-#ifdef CONFIG_CPU_S3C2442
-extern  int s3c2442_init(void);
-
-extern void s3c2442_map_io(void);
-#else
-#define s3c2442_init NULL
-#define s3c2442_map_io NULL
-#endif
diff --git a/arch/arm/plat-samsung/include/plat/s5p-time.h b/arch/arm/plat-samsung/include/plat/s5p-time.h
deleted file mode 100644
index 9c96f35..0000000
--- a/arch/arm/plat-samsung/include/plat/s5p-time.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/* linux/arch/arm/plat-samsung/include/plat/s5p-time.h
- *
- * Copyright 2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * Header file for s5p time 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_PLAT_S5P_TIME_H
-#define __ASM_PLAT_S5P_TIME_H __FILE__
-
-/* S5P HR-Timer Clock mode */
-enum s5p_timer_mode {
-	S5P_PWM0,
-	S5P_PWM1,
-	S5P_PWM2,
-	S5P_PWM3,
-	S5P_PWM4,
-};
-
-struct s5p_timer_source {
-	unsigned int event_id;
-	unsigned int source_id;
-};
-
-/* Be able to sleep for atleast 4 seconds (usually more) */
-#define S5PTIMER_MIN_RANGE	4
-
-#define TCNT_MAX		0xffffffff
-#define NON_PERIODIC		0
-#define PERIODIC		1
-
-extern void __init s5p_set_timer_source(enum s5p_timer_mode event,
-					enum s5p_timer_mode source);
-extern	void s5p_timer_init(void);
-#endif /* __ASM_PLAT_S5P_TIME_H */
diff --git a/arch/arm/plat-samsung/include/plat/samsung-time.h b/arch/arm/plat-samsung/include/plat/samsung-time.h
new file mode 100644
index 0000000..4cc99bb
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/samsung-time.h
@@ -0,0 +1,53 @@
+/* linux/arch/arm/plat-samsung/include/plat/samsung-time.h
+ *
+ * Copyright 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * Header file for samsung s3c and s5p time 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_PLAT_SAMSUNG_TIME_H
+#define __ASM_PLAT_SAMSUNG_TIME_H __FILE__
+
+/* SAMSUNG HR-Timer Clock mode */
+enum samsung_timer_mode {
+	SAMSUNG_PWM0,
+	SAMSUNG_PWM1,
+	SAMSUNG_PWM2,
+	SAMSUNG_PWM3,
+	SAMSUNG_PWM4,
+};
+
+struct samsung_timer_source {
+	unsigned int event_id;
+	unsigned int source_id;
+};
+
+/* Be able to sleep for atleast 4 seconds (usually more) */
+#define SAMSUNG_TIMER_MIN_RANGE	4
+
+#if defined(CONFIG_ARCH_S3C24XX) || defined(CONFIG_ARCH_S5PC100)
+#define TCNT_MAX		0xffff
+#define TSCALER_DIV		25
+#define TDIV			50
+#define TSIZE			16
+#else
+#define TCNT_MAX		0xffffffff
+#define TSCALER_DIV		2
+#define TDIV			2
+#define TSIZE			32
+#endif
+
+#define NON_PERIODIC		0
+#define PERIODIC		1
+
+extern void __init samsung_set_timer_source(enum samsung_timer_mode event,
+					enum samsung_timer_mode source);
+
+extern void __init samsung_timer_init(void);
+
+#endif /* __ASM_PLAT_SAMSUNG_TIME_H */
diff --git a/arch/arm/plat-samsung/include/plat/sdhci.h b/arch/arm/plat-samsung/include/plat/sdhci.h
index 9b87f38..5560586 100644
--- a/arch/arm/plat-samsung/include/plat/sdhci.h
+++ b/arch/arm/plat-samsung/include/plat/sdhci.h
@@ -206,7 +206,7 @@ static inline void s3c6400_default_sdhci2(void) { }
 
 /* S5P64X0 SDHCI setup */
 
-#ifdef CONFIG_S5P64X0_SETUP_SDHCI
+#ifdef CONFIG_S5P64X0_SETUP_SDHCI_GPIO
 static inline void s5p64x0_default_sdhci0(void)
 {
 #ifdef CONFIG_S3C_DEV_HSMMC
@@ -241,7 +241,7 @@ static inline void s5p64x0_default_sdhci1(void) { }
 static inline void s5p6440_default_sdhci2(void) { }
 static inline void s5p6450_default_sdhci2(void) { }
 
-#endif /* CONFIG_S5P64X0_SETUP_SDHCI */
+#endif /* CONFIG_S5P64X0_SETUP_SDHCI_GPIO */
 
 /* S5PC100 SDHCI setup */
 
diff --git a/arch/arm/plat-samsung/irq-vic-timer.c b/arch/arm/plat-samsung/irq-vic-timer.c
index f980cf3..5d205e7 100644
--- a/arch/arm/plat-samsung/irq-vic-timer.c
+++ b/arch/arm/plat-samsung/irq-vic-timer.c
@@ -16,6 +16,7 @@
 #include <linux/kernel.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
+#include <linux/irqchip/chained_irq.h>
 #include <linux/io.h>
 
 #include <mach/map.h>
@@ -23,8 +24,6 @@
 #include <plat/irq-vic-timer.h>
 #include <plat/regs-timer.h>
 
-#include <asm/mach/irq.h>
-
 static void s3c_irq_demux_vic_timer(unsigned int irq, struct irq_desc *desc)
 {
 	struct irq_chip *chip = irq_get_chip(irq);
diff --git a/arch/arm/plat-samsung/s5p-irq-gpioint.c b/arch/arm/plat-samsung/s5p-irq-gpioint.c
index bae5613..fafdb05 100644
--- a/arch/arm/plat-samsung/s5p-irq-gpioint.c
+++ b/arch/arm/plat-samsung/s5p-irq-gpioint.c
@@ -14,6 +14,7 @@
 #include <linux/kernel.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
+#include <linux/irqchip/chained_irq.h>
 #include <linux/io.h>
 #include <linux/gpio.h>
 #include <linux/slab.h>
@@ -22,8 +23,6 @@
 #include <plat/gpio-core.h>
 #include <plat/gpio-cfg.h>
 
-#include <asm/mach/irq.h>
-
 #define GPIO_BASE(chip)		((void __iomem *)((unsigned long)((chip)->base) & 0xFFFFF000u))
 
 #define CON_OFFSET		0x700
diff --git a/arch/arm/plat-samsung/s5p-sleep.S b/arch/arm/plat-samsung/s5p-sleep.S
index bdf6dad..a030e73 100644
--- a/arch/arm/plat-samsung/s5p-sleep.S
+++ b/arch/arm/plat-samsung/s5p-sleep.S
@@ -25,6 +25,9 @@
 #include <asm/asm-offsets.h>
 #include <asm/hardware/cache-l2x0.h>
 
+#define CPU_MASK	0xff0ffff0
+#define CPU_CORTEX_A9	0x410fc090
+
 /*
  *	 The following code is located into the .data section. This is to
  *	 allow l2x0_regs_phys to be accessed with a relative load while we
@@ -51,6 +54,12 @@
 
 ENTRY(s3c_cpu_resume)
 #ifdef CONFIG_CACHE_L2X0
+	mrc	p15, 0, r0, c0, c0, 0
+	ldr	r1, =CPU_MASK
+	and	r0, r0, r1
+	ldr	r1, =CPU_CORTEX_A9
+	cmp	r0, r1
+	bne	resume_l2on
 	adr	r0, l2x0_regs_phys
 	ldr	r0, [r0]
 	ldr	r1, [r0, #L2X0_R_PHY_BASE]
diff --git a/arch/arm/plat-samsung/s5p-time.c b/arch/arm/plat-samsung/s5p-time.c
deleted file mode 100644
index e92510c..0000000
--- a/arch/arm/plat-samsung/s5p-time.c
+++ /dev/null
@@ -1,394 +0,0 @@
-/*
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5P - Common hr-timer 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/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 <asm/mach/time.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/sched_clock.h>
-
-#include <mach/map.h>
-#include <plat/devs.h>
-#include <plat/regs-timer.h>
-#include <plat/s5p-time.h>
-
-static struct clk *tin_event;
-static struct clk *tin_source;
-static struct clk *tdiv_event;
-static struct clk *tdiv_source;
-static struct clk *timerclk;
-static struct s5p_timer_source timer_source;
-static unsigned long clock_count_per_tick;
-static void s5p_timer_resume(void);
-
-static void s5p_time_stop(enum s5p_timer_mode mode)
-{
-	unsigned long tcon;
-
-	tcon = __raw_readl(S3C2410_TCON);
-
-	switch (mode) {
-	case S5P_PWM0:
-		tcon &= ~S3C2410_TCON_T0START;
-		break;
-
-	case S5P_PWM1:
-		tcon &= ~S3C2410_TCON_T1START;
-		break;
-
-	case S5P_PWM2:
-		tcon &= ~S3C2410_TCON_T2START;
-		break;
-
-	case S5P_PWM3:
-		tcon &= ~S3C2410_TCON_T3START;
-		break;
-
-	case S5P_PWM4:
-		tcon &= ~S3C2410_TCON_T4START;
-		break;
-
-	default:
-		printk(KERN_ERR "Invalid Timer %d\n", mode);
-		break;
-	}
-	__raw_writel(tcon, S3C2410_TCON);
-}
-
-static void s5p_time_setup(enum s5p_timer_mode mode, unsigned long tcnt)
-{
-	unsigned long tcon;
-
-	tcon = __raw_readl(S3C2410_TCON);
-
-	tcnt--;
-
-	switch (mode) {
-	case S5P_PWM0:
-		tcon &= ~(0x0f << 0);
-		tcon |= S3C2410_TCON_T0MANUALUPD;
-		break;
-
-	case S5P_PWM1:
-		tcon &= ~(0x0f << 8);
-		tcon |= S3C2410_TCON_T1MANUALUPD;
-		break;
-
-	case S5P_PWM2:
-		tcon &= ~(0x0f << 12);
-		tcon |= S3C2410_TCON_T2MANUALUPD;
-		break;
-
-	case S5P_PWM3:
-		tcon &= ~(0x0f << 16);
-		tcon |= S3C2410_TCON_T3MANUALUPD;
-		break;
-
-	case S5P_PWM4:
-		tcon &= ~(0x07 << 20);
-		tcon |= S3C2410_TCON_T4MANUALUPD;
-		break;
-
-	default:
-		printk(KERN_ERR "Invalid Timer %d\n", mode);
-		break;
-	}
-
-	__raw_writel(tcnt, S3C2410_TCNTB(mode));
-	__raw_writel(tcnt, S3C2410_TCMPB(mode));
-	__raw_writel(tcon, S3C2410_TCON);
-}
-
-static void s5p_time_start(enum s5p_timer_mode mode, bool periodic)
-{
-	unsigned long tcon;
-
-	tcon  = __raw_readl(S3C2410_TCON);
-
-	switch (mode) {
-	case S5P_PWM0:
-		tcon |= S3C2410_TCON_T0START;
-		tcon &= ~S3C2410_TCON_T0MANUALUPD;
-
-		if (periodic)
-			tcon |= S3C2410_TCON_T0RELOAD;
-		else
-			tcon &= ~S3C2410_TCON_T0RELOAD;
-		break;
-
-	case S5P_PWM1:
-		tcon |= S3C2410_TCON_T1START;
-		tcon &= ~S3C2410_TCON_T1MANUALUPD;
-
-		if (periodic)
-			tcon |= S3C2410_TCON_T1RELOAD;
-		else
-			tcon &= ~S3C2410_TCON_T1RELOAD;
-		break;
-
-	case S5P_PWM2:
-		tcon |= S3C2410_TCON_T2START;
-		tcon &= ~S3C2410_TCON_T2MANUALUPD;
-
-		if (periodic)
-			tcon |= S3C2410_TCON_T2RELOAD;
-		else
-			tcon &= ~S3C2410_TCON_T2RELOAD;
-		break;
-
-	case S5P_PWM3:
-		tcon |= S3C2410_TCON_T3START;
-		tcon &= ~S3C2410_TCON_T3MANUALUPD;
-
-		if (periodic)
-			tcon |= S3C2410_TCON_T3RELOAD;
-		else
-			tcon &= ~S3C2410_TCON_T3RELOAD;
-		break;
-
-	case S5P_PWM4:
-		tcon |= S3C2410_TCON_T4START;
-		tcon &= ~S3C2410_TCON_T4MANUALUPD;
-
-		if (periodic)
-			tcon |= S3C2410_TCON_T4RELOAD;
-		else
-			tcon &= ~S3C2410_TCON_T4RELOAD;
-		break;
-
-	default:
-		printk(KERN_ERR "Invalid Timer %d\n", mode);
-		break;
-	}
-	__raw_writel(tcon, S3C2410_TCON);
-}
-
-static int s5p_set_next_event(unsigned long cycles,
-				struct clock_event_device *evt)
-{
-	s5p_time_setup(timer_source.event_id, cycles);
-	s5p_time_start(timer_source.event_id, NON_PERIODIC);
-
-	return 0;
-}
-
-static void s5p_set_mode(enum clock_event_mode mode,
-				struct clock_event_device *evt)
-{
-	s5p_time_stop(timer_source.event_id);
-
-	switch (mode) {
-	case CLOCK_EVT_MODE_PERIODIC:
-		s5p_time_setup(timer_source.event_id, clock_count_per_tick);
-		s5p_time_start(timer_source.event_id, PERIODIC);
-		break;
-
-	case CLOCK_EVT_MODE_ONESHOT:
-		break;
-
-	case CLOCK_EVT_MODE_UNUSED:
-	case CLOCK_EVT_MODE_SHUTDOWN:
-		break;
-
-	case CLOCK_EVT_MODE_RESUME:
-		s5p_timer_resume();
-		break;
-	}
-}
-
-static void s5p_timer_resume(void)
-{
-	/* event timer restart */
-	s5p_time_setup(timer_source.event_id, clock_count_per_tick);
-	s5p_time_start(timer_source.event_id, PERIODIC);
-
-	/* source timer restart */
-	s5p_time_setup(timer_source.source_id, TCNT_MAX);
-	s5p_time_start(timer_source.source_id, PERIODIC);
-}
-
-void __init s5p_set_timer_source(enum s5p_timer_mode event,
-				 enum s5p_timer_mode source)
-{
-	s3c_device_timer[event].dev.bus = &platform_bus_type;
-	s3c_device_timer[source].dev.bus = &platform_bus_type;
-
-	timer_source.event_id = event;
-	timer_source.source_id = source;
-}
-
-static struct clock_event_device time_event_device = {
-	.name		= "s5p_event_timer",
-	.features	= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
-	.rating		= 200,
-	.set_next_event	= s5p_set_next_event,
-	.set_mode	= s5p_set_mode,
-};
-
-static irqreturn_t s5p_clock_event_isr(int irq, void *dev_id)
-{
-	struct clock_event_device *evt = dev_id;
-
-	evt->event_handler(evt);
-
-	return IRQ_HANDLED;
-}
-
-static struct irqaction s5p_clock_event_irq = {
-	.name		= "s5p_time_irq",
-	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
-	.handler	= s5p_clock_event_isr,
-	.dev_id		= &time_event_device,
-};
-
-static void __init s5p_clockevent_init(void)
-{
-	unsigned long pclk;
-	unsigned long clock_rate;
-	unsigned int irq_number;
-	struct clk *tscaler;
-
-	pclk = clk_get_rate(timerclk);
-
-	tscaler = clk_get_parent(tdiv_event);
-
-	clk_set_rate(tscaler, pclk / 2);
-	clk_set_rate(tdiv_event, pclk / 2);
-	clk_set_parent(tin_event, tdiv_event);
-
-	clock_rate = clk_get_rate(tin_event);
-	clock_count_per_tick = clock_rate / HZ;
-
-	time_event_device.cpumask = cpumask_of(0);
-	clockevents_config_and_register(&time_event_device, clock_rate, 1, -1);
-
-	irq_number = timer_source.event_id + IRQ_TIMER0;
-	setup_irq(irq_number, &s5p_clock_event_irq);
-}
-
-static void __iomem *s5p_timer_reg(void)
-{
-	unsigned long offset = 0;
-
-	switch (timer_source.source_id) {
-	case S5P_PWM0:
-	case S5P_PWM1:
-	case S5P_PWM2:
-	case S5P_PWM3:
-		offset = (timer_source.source_id * 0x0c) + 0x14;
-		break;
-
-	case S5P_PWM4:
-		offset = 0x40;
-		break;
-
-	default:
-		printk(KERN_ERR "Invalid Timer %d\n", timer_source.source_id);
-		return NULL;
-	}
-
-	return S3C_TIMERREG(offset);
-}
-
-/*
- * Override the global weak sched_clock symbol with this
- * local implementation which uses the clocksource to get some
- * better resolution when scheduling the kernel. We accept that
- * this wraps around for now, since it is just a relative time
- * stamp. (Inspired by U300 implementation.)
- */
-static u32 notrace s5p_read_sched_clock(void)
-{
-	void __iomem *reg = s5p_timer_reg();
-
-	if (!reg)
-		return 0;
-
-	return ~__raw_readl(reg);
-}
-
-static void __init s5p_clocksource_init(void)
-{
-	unsigned long pclk;
-	unsigned long clock_rate;
-
-	pclk = clk_get_rate(timerclk);
-
-	clk_set_rate(tdiv_source, pclk / 2);
-	clk_set_parent(tin_source, tdiv_source);
-
-	clock_rate = clk_get_rate(tin_source);
-
-	s5p_time_setup(timer_source.source_id, TCNT_MAX);
-	s5p_time_start(timer_source.source_id, PERIODIC);
-
-	setup_sched_clock(s5p_read_sched_clock, 32, clock_rate);
-
-	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)
-{
-
-	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))
-		panic("failed to get timers clock for timer");
-
-	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");
-
-	tdiv_event = clk_get(&s3c_device_timer[event_id].dev, "pwm-tdiv");
-	if (IS_ERR(tdiv_event))
-		panic("failed to get pwm-tdiv clock for event timer");
-
-	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");
-
-	tdiv_source = clk_get(&s3c_device_timer[source_id].dev, "pwm-tdiv");
-	if (IS_ERR(tdiv_source))
-		panic("failed to get pwm-tdiv clock for source timer");
-
-	clk_enable(tin_source);
-}
-
-void __init s5p_timer_init(void)
-{
-	s5p_timer_resources();
-	s5p_clockevent_init();
-	s5p_clocksource_init();
-}
diff --git a/arch/arm/plat-samsung/samsung-time.c b/arch/arm/plat-samsung/samsung-time.c
new file mode 100644
index 0000000..f899cbc
--- /dev/null
+++ b/arch/arm/plat-samsung/samsung-time.c
@@ -0,0 +1,394 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * samsung - Common hr-timer support (s3c and s5p)
+ *
+ * This program is free software; you can 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/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 <asm/mach/time.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/sched_clock.h>
+
+#include <mach/map.h>
+#include <plat/devs.h>
+#include <plat/regs-timer.h>
+#include <plat/samsung-time.h>
+
+static struct clk *tin_event;
+static struct clk *tin_source;
+static struct clk *tdiv_event;
+static struct clk *tdiv_source;
+static struct clk *timerclk;
+static struct samsung_timer_source timer_source;
+static unsigned long clock_count_per_tick;
+static void samsung_timer_resume(void);
+
+static void samsung_time_stop(enum samsung_timer_mode mode)
+{
+	unsigned long tcon;
+
+	tcon = __raw_readl(S3C2410_TCON);
+
+	switch (mode) {
+	case SAMSUNG_PWM0:
+		tcon &= ~S3C2410_TCON_T0START;
+		break;
+
+	case SAMSUNG_PWM1:
+		tcon &= ~S3C2410_TCON_T1START;
+		break;
+
+	case SAMSUNG_PWM2:
+		tcon &= ~S3C2410_TCON_T2START;
+		break;
+
+	case SAMSUNG_PWM3:
+		tcon &= ~S3C2410_TCON_T3START;
+		break;
+
+	case SAMSUNG_PWM4:
+		tcon &= ~S3C2410_TCON_T4START;
+		break;
+
+	default:
+		printk(KERN_ERR "Invalid Timer %d\n", mode);
+		break;
+	}
+	__raw_writel(tcon, S3C2410_TCON);
+}
+
+static void samsung_time_setup(enum samsung_timer_mode mode, unsigned long tcnt)
+{
+	unsigned long tcon;
+
+	tcon = __raw_readl(S3C2410_TCON);
+
+	tcnt--;
+
+	switch (mode) {
+	case SAMSUNG_PWM0:
+		tcon &= ~(0x0f << 0);
+		tcon |= S3C2410_TCON_T0MANUALUPD;
+		break;
+
+	case SAMSUNG_PWM1:
+		tcon &= ~(0x0f << 8);
+		tcon |= S3C2410_TCON_T1MANUALUPD;
+		break;
+
+	case SAMSUNG_PWM2:
+		tcon &= ~(0x0f << 12);
+		tcon |= S3C2410_TCON_T2MANUALUPD;
+		break;
+
+	case SAMSUNG_PWM3:
+		tcon &= ~(0x0f << 16);
+		tcon |= S3C2410_TCON_T3MANUALUPD;
+		break;
+
+	case SAMSUNG_PWM4:
+		tcon &= ~(0x07 << 20);
+		tcon |= S3C2410_TCON_T4MANUALUPD;
+		break;
+
+	default:
+		printk(KERN_ERR "Invalid Timer %d\n", mode);
+		break;
+	}
+
+	__raw_writel(tcnt, S3C2410_TCNTB(mode));
+	__raw_writel(tcnt, S3C2410_TCMPB(mode));
+	__raw_writel(tcon, S3C2410_TCON);
+}
+
+static void samsung_time_start(enum samsung_timer_mode mode, bool periodic)
+{
+	unsigned long tcon;
+
+	tcon  = __raw_readl(S3C2410_TCON);
+
+	switch (mode) {
+	case SAMSUNG_PWM0:
+		tcon |= S3C2410_TCON_T0START;
+		tcon &= ~S3C2410_TCON_T0MANUALUPD;
+
+		if (periodic)
+			tcon |= S3C2410_TCON_T0RELOAD;
+		else
+			tcon &= ~S3C2410_TCON_T0RELOAD;
+		break;
+
+	case SAMSUNG_PWM1:
+		tcon |= S3C2410_TCON_T1START;
+		tcon &= ~S3C2410_TCON_T1MANUALUPD;
+
+		if (periodic)
+			tcon |= S3C2410_TCON_T1RELOAD;
+		else
+			tcon &= ~S3C2410_TCON_T1RELOAD;
+		break;
+
+	case SAMSUNG_PWM2:
+		tcon |= S3C2410_TCON_T2START;
+		tcon &= ~S3C2410_TCON_T2MANUALUPD;
+
+		if (periodic)
+			tcon |= S3C2410_TCON_T2RELOAD;
+		else
+			tcon &= ~S3C2410_TCON_T2RELOAD;
+		break;
+
+	case SAMSUNG_PWM3:
+		tcon |= S3C2410_TCON_T3START;
+		tcon &= ~S3C2410_TCON_T3MANUALUPD;
+
+		if (periodic)
+			tcon |= S3C2410_TCON_T3RELOAD;
+		else
+			tcon &= ~S3C2410_TCON_T3RELOAD;
+		break;
+
+	case SAMSUNG_PWM4:
+		tcon |= S3C2410_TCON_T4START;
+		tcon &= ~S3C2410_TCON_T4MANUALUPD;
+
+		if (periodic)
+			tcon |= S3C2410_TCON_T4RELOAD;
+		else
+			tcon &= ~S3C2410_TCON_T4RELOAD;
+		break;
+
+	default:
+		printk(KERN_ERR "Invalid Timer %d\n", mode);
+		break;
+	}
+	__raw_writel(tcon, S3C2410_TCON);
+}
+
+static int samsung_set_next_event(unsigned long cycles,
+				struct clock_event_device *evt)
+{
+	samsung_time_setup(timer_source.event_id, cycles);
+	samsung_time_start(timer_source.event_id, NON_PERIODIC);
+
+	return 0;
+}
+
+static void samsung_set_mode(enum clock_event_mode mode,
+				struct clock_event_device *evt)
+{
+	samsung_time_stop(timer_source.event_id);
+
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		samsung_time_setup(timer_source.event_id, clock_count_per_tick);
+		samsung_time_start(timer_source.event_id, PERIODIC);
+		break;
+
+	case CLOCK_EVT_MODE_ONESHOT:
+		break;
+
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_SHUTDOWN:
+		break;
+
+	case CLOCK_EVT_MODE_RESUME:
+		samsung_timer_resume();
+		break;
+	}
+}
+
+static void samsung_timer_resume(void)
+{
+	/* event timer restart */
+	samsung_time_setup(timer_source.event_id, clock_count_per_tick);
+	samsung_time_start(timer_source.event_id, PERIODIC);
+
+	/* source timer restart */
+	samsung_time_setup(timer_source.source_id, TCNT_MAX);
+	samsung_time_start(timer_source.source_id, PERIODIC);
+}
+
+void __init samsung_set_timer_source(enum samsung_timer_mode event,
+				 enum samsung_timer_mode source)
+{
+	s3c_device_timer[event].dev.bus = &platform_bus_type;
+	s3c_device_timer[source].dev.bus = &platform_bus_type;
+
+	timer_source.event_id = event;
+	timer_source.source_id = source;
+}
+
+static struct clock_event_device time_event_device = {
+	.name		= "samsung_event_timer",
+	.features	= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+	.rating		= 200,
+	.set_next_event	= samsung_set_next_event,
+	.set_mode	= samsung_set_mode,
+};
+
+static irqreturn_t samsung_clock_event_isr(int irq, void *dev_id)
+{
+	struct clock_event_device *evt = dev_id;
+
+	evt->event_handler(evt);
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction samsung_clock_event_irq = {
+	.name		= "samsung_time_irq",
+	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+	.handler	= samsung_clock_event_isr,
+	.dev_id		= &time_event_device,
+};
+
+static void __init samsung_clockevent_init(void)
+{
+	unsigned long pclk;
+	unsigned long clock_rate;
+	unsigned int irq_number;
+	struct clk *tscaler;
+
+	pclk = clk_get_rate(timerclk);
+
+	tscaler = clk_get_parent(tdiv_event);
+
+	clk_set_rate(tscaler, pclk / TSCALER_DIV);
+	clk_set_rate(tdiv_event, pclk / TDIV);
+	clk_set_parent(tin_event, tdiv_event);
+
+	clock_rate = clk_get_rate(tin_event);
+	clock_count_per_tick = clock_rate / HZ;
+
+	time_event_device.cpumask = cpumask_of(0);
+	clockevents_config_and_register(&time_event_device, clock_rate, 1, -1);
+
+	irq_number = timer_source.event_id + IRQ_TIMER0;
+	setup_irq(irq_number, &samsung_clock_event_irq);
+}
+
+static void __iomem *samsung_timer_reg(void)
+{
+	unsigned long offset = 0;
+
+	switch (timer_source.source_id) {
+	case SAMSUNG_PWM0:
+	case SAMSUNG_PWM1:
+	case SAMSUNG_PWM2:
+	case SAMSUNG_PWM3:
+		offset = (timer_source.source_id * 0x0c) + 0x14;
+		break;
+
+	case SAMSUNG_PWM4:
+		offset = 0x40;
+		break;
+
+	default:
+		printk(KERN_ERR "Invalid Timer %d\n", timer_source.source_id);
+		return NULL;
+	}
+
+	return S3C_TIMERREG(offset);
+}
+
+/*
+ * Override the global weak sched_clock symbol with this
+ * local implementation which uses the clocksource to get some
+ * better resolution when scheduling the kernel. We accept that
+ * this wraps around for now, since it is just a relative time
+ * stamp. (Inspired by U300 implementation.)
+ */
+static u32 notrace samsung_read_sched_clock(void)
+{
+	void __iomem *reg = samsung_timer_reg();
+
+	if (!reg)
+		return 0;
+
+	return ~__raw_readl(reg);
+}
+
+static void __init samsung_clocksource_init(void)
+{
+	unsigned long pclk;
+	unsigned long clock_rate;
+
+	pclk = clk_get_rate(timerclk);
+
+	clk_set_rate(tdiv_source, pclk / TDIV);
+	clk_set_parent(tin_source, tdiv_source);
+
+	clock_rate = clk_get_rate(tin_source);
+
+	samsung_time_setup(timer_source.source_id, TCNT_MAX);
+	samsung_time_start(timer_source.source_id, PERIODIC);
+
+	setup_sched_clock(samsung_read_sched_clock, TSIZE, clock_rate);
+
+	if (clocksource_mmio_init(samsung_timer_reg(), "samsung_clocksource_timer",
+			clock_rate, 250, TSIZE, clocksource_mmio_readl_down))
+		panic("samsung_clocksource_timer: can't register clocksource\n");
+}
+
+static void __init samsung_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))
+		panic("failed to get timers clock for timer");
+
+	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");
+
+	tdiv_event = clk_get(&s3c_device_timer[event_id].dev, "pwm-tdiv");
+	if (IS_ERR(tdiv_event))
+		panic("failed to get pwm-tdiv clock for event timer");
+
+	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");
+
+	tdiv_source = clk_get(&s3c_device_timer[source_id].dev, "pwm-tdiv");
+	if (IS_ERR(tdiv_source))
+		panic("failed to get pwm-tdiv clock for source timer");
+
+	clk_enable(tin_source);
+}
+
+void __init samsung_timer_init(void)
+{
+	samsung_timer_resources();
+	samsung_clockevent_init();
+	samsung_clocksource_init();
+}
diff --git a/arch/arm/plat-samsung/setup-mipiphy.c b/arch/arm/plat-samsung/setup-mipiphy.c
index 1474593..66df315 100644
--- a/arch/arm/plat-samsung/setup-mipiphy.c
+++ b/arch/arm/plat-samsung/setup-mipiphy.c
@@ -8,6 +8,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/export.h>
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
@@ -50,8 +51,10 @@ int s5p_csis_phy_enable(int id, bool on)
 {
 	return __s5p_mipi_phy_control(id, on, S5P_MIPI_DPHY_SRESETN);
 }
+EXPORT_SYMBOL(s5p_csis_phy_enable);
 
 int s5p_dsim_phy_enable(struct platform_device *pdev, bool on)
 {
 	return __s5p_mipi_phy_control(pdev->id, on, S5P_MIPI_DPHY_MRESETN);
 }
+EXPORT_SYMBOL(s5p_dsim_phy_enable);
diff --git a/arch/arm/plat-samsung/time.c b/arch/arm/plat-samsung/time.c
deleted file mode 100644
index 73defd0..0000000
--- a/arch/arm/plat-samsung/time.c
+++ /dev/null
@@ -1,287 +0,0 @@
-/* linux/arch/arm/plat-samsung/time.c
- *
- * 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 as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You 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/sched.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <linux/syscore_ops.h>
-
-#include <asm/mach-types.h>
-
-#include <asm/irq.h>
-#include <mach/map.h>
-#include <plat/regs-timer.h>
-#include <mach/regs-irq.h>
-#include <asm/mach/time.h>
-#include <mach/tick.h>
-
-#include <plat/clock.h>
-#include <plat/cpu.h>
-
-static unsigned long timer_startval;
-static unsigned long timer_usec_ticks;
-
-#ifndef TICK_MAX
-#define TICK_MAX (0xffff)
-#endif
-
-#define TIMER_USEC_SHIFT 16
-
-/* we use the shifted arithmetic to work out the ratio of timer ticks
- * to usecs, as often the peripheral clock is not a nice even multiple
- * of 1MHz.
- *
- * shift of 14 and 15 are too low for the 12MHz, 16 seems to be ok
- * for the current HZ value of 200 without producing overflows.
- *
- * Original patch by Dimitry Andric, updated by Ben Dooks
-*/
-
-
-/* timer_mask_usec_ticks
- *
- * given a clock and divisor, make the value to pass into timer_ticks_to_usec
- * to scale the ticks into usecs
-*/
-
-static inline unsigned long
-timer_mask_usec_ticks(unsigned long scaler, unsigned long pclk)
-{
-	unsigned long den = pclk / 1000;
-
-	return ((1000 << TIMER_USEC_SHIFT) * scaler + (den >> 1)) / den;
-}
-
-/* timer_ticks_to_usec
- *
- * convert timer ticks to usec.
-*/
-
-static inline unsigned long timer_ticks_to_usec(unsigned long ticks)
-{
-	unsigned long res;
-
-	res = ticks * timer_usec_ticks;
-	res += 1 << (TIMER_USEC_SHIFT - 4);	/* round up slightly */
-
-	return res >> TIMER_USEC_SHIFT;
-}
-
-/***
- * Returns microsecond  since last clock interrupt.  Note that interrupts
- * will have been disabled by do_gettimeoffset()
- * IRQs are disabled before entering here from do_gettimeofday()
- */
-
-static u32 s3c2410_gettimeoffset(void)
-{
-	unsigned long tdone;
-	unsigned long tval;
-
-	/* work out how many ticks have gone since last timer interrupt */
-
-	tval =  __raw_readl(S3C2410_TCNTO(4));
-	tdone = timer_startval - tval;
-
-	/* check to see if there is an interrupt pending */
-
-	if (s3c24xx_ostimer_pending()) {
-		/* re-read the timer, and try and fix up for the missed
-		 * interrupt. Note, the interrupt may go off before the
-		 * timer has re-loaded from wrapping.
-		 */
-
-		tval =  __raw_readl(S3C2410_TCNTO(4));
-		tdone = timer_startval - tval;
-
-		if (tval != 0)
-			tdone += timer_startval;
-	}
-
-	return timer_ticks_to_usec(tdone) * 1000;
-}
-
-
-/*
- * IRQ handler for the timer
- */
-static irqreturn_t
-s3c2410_timer_interrupt(int irq, void *dev_id)
-{
-	timer_tick();
-	return IRQ_HANDLED;
-}
-
-static struct irqaction s3c2410_timer_irq = {
-	.name		= "S3C2410 Timer Tick",
-	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
-	.handler	= s3c2410_timer_interrupt,
-};
-
-#define use_tclk1_12() ( \
-	machine_is_bast()	|| \
-	machine_is_vr1000()	|| \
-	machine_is_anubis()	|| \
-	machine_is_osiris())
-
-static struct clk *tin;
-static struct clk *tdiv;
-static struct clk *timerclk;
-
-/*
- * Set up timer interrupt, and return the current time in seconds.
- *
- * Currently we only use timer4, as it is the only timer which has no
- * other function that can be exploited externally
- */
-static void s3c2410_timer_setup (void)
-{
-	unsigned long tcon;
-	unsigned long tcnt;
-	unsigned long tcfg1;
-	unsigned long tcfg0;
-
-	tcnt = TICK_MAX;  /* default value for tcnt */
-
-	/* configure the system for whichever machine is in use */
-
-	if (use_tclk1_12()) {
-		/* timer is at 12MHz, scaler is 1 */
-		timer_usec_ticks = timer_mask_usec_ticks(1, 12000000);
-		tcnt = 12000000 / HZ;
-
-		tcfg1 = __raw_readl(S3C2410_TCFG1);
-		tcfg1 &= ~S3C2410_TCFG1_MUX4_MASK;
-		tcfg1 |= S3C2410_TCFG1_MUX4_TCLK1;
-		__raw_writel(tcfg1, S3C2410_TCFG1);
-	} else {
-		unsigned long pclk;
-		struct clk *tscaler;
-
-		/* for the h1940 (and others), we use the pclk from the core
-		 * to generate the timer values. since values around 50 to
-		 * 70MHz are not values we can directly generate the timer
-		 * value from, we need to pre-scale and divide before using it.
-		 *
-		 * for instance, using 50.7MHz and dividing by 6 gives 8.45MHz
-		 * (8.45 ticks per usec)
-		 */
-
-		pclk = clk_get_rate(timerclk);
-
-		/* configure clock tick */
-
-		timer_usec_ticks = timer_mask_usec_ticks(6, pclk);
-
-		tscaler = clk_get_parent(tdiv);
-
-		clk_set_rate(tscaler, pclk / 3);
-		clk_set_rate(tdiv, pclk / 6);
-		clk_set_parent(tin, tdiv);
-
-		tcnt = clk_get_rate(tin) / HZ;
-	}
-
-	tcon = __raw_readl(S3C2410_TCON);
-	tcfg0 = __raw_readl(S3C2410_TCFG0);
-	tcfg1 = __raw_readl(S3C2410_TCFG1);
-
-	/* timers reload after counting zero, so reduce the count by 1 */
-
-	tcnt--;
-
-	printk(KERN_DEBUG "timer tcon=%08lx, tcnt %04lx, tcfg %08lx,%08lx, usec %08lx\n",
-	       tcon, tcnt, tcfg0, tcfg1, timer_usec_ticks);
-
-	/* check to see if timer is within 16bit range... */
-	if (tcnt > TICK_MAX) {
-		panic("setup_timer: HZ is too small, cannot configure timer!");
-		return;
-	}
-
-	__raw_writel(tcfg1, S3C2410_TCFG1);
-	__raw_writel(tcfg0, S3C2410_TCFG0);
-
-	timer_startval = tcnt;
-	__raw_writel(tcnt, S3C2410_TCNTB(4));
-
-	/* ensure timer is stopped... */
-
-	tcon &= ~(7<<20);
-	tcon |= S3C2410_TCON_T4RELOAD;
-	tcon |= S3C2410_TCON_T4MANUALUPD;
-
-	__raw_writel(tcon, S3C2410_TCON);
-	__raw_writel(tcnt, S3C2410_TCNTB(4));
-	__raw_writel(tcnt, S3C2410_TCMPB(4));
-
-	/* start the timer running */
-	tcon |= S3C2410_TCON_T4START;
-	tcon &= ~S3C2410_TCON_T4MANUALUPD;
-	__raw_writel(tcon, S3C2410_TCON);
-}
-
-static void __init s3c2410_timer_resources(void)
-{
-	struct platform_device tmpdev;
-
-	tmpdev.dev.bus = &platform_bus_type;
-	tmpdev.id = 4;
-
-	timerclk = clk_get(NULL, "timers");
-	if (IS_ERR(timerclk))
-		panic("failed to get clock for system timer");
-
-	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");
-
-		tdiv = clk_get(&tmpdev.dev, "pwm-tdiv");
-		if (IS_ERR(tdiv))
-			panic("failed to get pwm-tdiv clock for system timer");
-	}
-
-	clk_enable(tin);
-}
-
-static struct syscore_ops s3c24xx_syscore_ops = {
-	.resume		= s3c2410_timer_setup,
-};
-
-void __init s3c24xx_timer_init(void)
-{
-	arch_gettimeoffset = s3c2410_gettimeoffset;
-
-	s3c2410_timer_resources();
-	s3c2410_timer_setup();
-	setup_irq(IRQ_TIMER4, &s3c2410_timer_irq);
-	register_syscore_ops(&s3c24xx_syscore_ops);
-}
diff --git a/arch/arm/plat-spear/Kconfig b/arch/arm/plat-spear/Kconfig
deleted file mode 100644
index 8a08c31..0000000
--- a/arch/arm/plat-spear/Kconfig
+++ /dev/null
@@ -1,47 +0,0 @@
-#
-# SPEAr Platform configuration file
-#
-
-if PLAT_SPEAR
-
-choice
-	prompt "ST SPEAr Family"
-	default ARCH_SPEAR3XX
-
-config ARCH_SPEAR13XX
-	bool "ST SPEAr13xx with Device Tree"
-	select ARCH_HAS_CPUFREQ
-	select ARM_GIC
-	select CPU_V7
-	select GPIO_SPEAR_SPICS
-	select HAVE_SMP
-	select MIGHT_HAVE_CACHE_L2X0
-	select PINCTRL
-	select USE_OF
-	help
-	  Supports for ARM's SPEAR13XX family
-
-config ARCH_SPEAR3XX
-	bool "ST SPEAr3xx with Device Tree"
-	select ARM_VIC
-	select CPU_ARM926T
-	select PINCTRL
-	select USE_OF
-	help
-	  Supports for ARM's SPEAR3XX family
-
-config ARCH_SPEAR6XX
-	bool "SPEAr6XX"
-	select ARM_VIC
-	select CPU_ARM926T
-	help
-	  Supports for ARM's SPEAR6XX family
-
-endchoice
-
-# Adding SPEAr machine specific configuration files
-source "arch/arm/mach-spear13xx/Kconfig"
-source "arch/arm/mach-spear3xx/Kconfig"
-source "arch/arm/mach-spear6xx/Kconfig"
-
-endif
diff --git a/arch/arm/plat-spear/Makefile b/arch/arm/plat-spear/Makefile
deleted file mode 100644
index 01e8853..0000000
--- a/arch/arm/plat-spear/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-#
-# SPEAr Platform specific Makefile
-#
-
-# Common support
-obj-y	:= restart.o time.o
-
-obj-$(CONFIG_ARCH_SPEAR3XX)	+= pl080.o
-obj-$(CONFIG_ARCH_SPEAR6XX)	+= pl080.o
diff --git a/arch/arm/plat-spear/include/plat/debug-macro.S b/arch/arm/plat-spear/include/plat/debug-macro.S
deleted file mode 100644
index 75b05ad..0000000
--- a/arch/arm/plat-spear/include/plat/debug-macro.S
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * arch/arm/plat-spear/include/plat/debug-macro.S
- *
- * Debugging macro include header for spear platform
- *
- * Copyright (C) 2009 ST Microelectronics
- * Viresh Kumar <viresh.linux@gmail.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/amba/serial.h>
-#include <mach/spear.h>
-
-		.macro	addruart, rp, rv, tmp
-		mov	\rp, #SPEAR_DBG_UART_BASE		@ Physical base
-		mov	\rv, #VA_SPEAR_DBG_UART_BASE		@ Virtual base
-		.endm
-
-		.macro	senduart, rd, rx
-		strb	\rd, [\rx, #UART01x_DR]			@ ASC_TX_BUFFER
-		.endm
-
-		.macro	waituart, rd, rx
-1001:		ldr	\rd, [\rx, #UART01x_FR]			@ FLAG REGISTER
-		tst	\rd, #UART01x_FR_TXFF			@ TX_FULL
-		bne	1001b
-		.endm
-
-		.macro	busyuart, rd, rx
-1002:		ldr	\rd, [\rx, #UART01x_FR]			@ FLAG REGISTER
-		tst	\rd, #UART011_FR_TXFE			@ TX_EMPTY
-		beq	1002b
-		.endm
diff --git a/arch/arm/plat-spear/include/plat/pl080.h b/arch/arm/plat-spear/include/plat/pl080.h
deleted file mode 100644
index eb6590d..0000000
--- a/arch/arm/plat-spear/include/plat/pl080.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * arch/arm/plat-spear/include/plat/pl080.h
- *
- * DMAC pl080 definitions for SPEAr platform
- *
- * Copyright (C) 2012 ST Microelectronics
- * Viresh Kumar <viresh.linux@gmail.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_PL080_H
-#define __PLAT_PL080_H
-
-struct pl08x_channel_data;
-int pl080_get_signal(const struct pl08x_channel_data *cd);
-void pl080_put_signal(const struct pl08x_channel_data *cd, int signal);
-
-#endif /* __PLAT_PL080_H */
diff --git a/arch/arm/plat-spear/include/plat/timex.h b/arch/arm/plat-spear/include/plat/timex.h
deleted file mode 100644
index ef95e5b..0000000
--- a/arch/arm/plat-spear/include/plat/timex.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * arch/arm/plat-spear/include/plat/timex.h
- *
- * SPEAr platform specific timex definitions
- *
- * Copyright (C) 2009 ST Microelectronics
- * Viresh Kumar <viresh.linux@gmail.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_TIMEX_H
-#define __PLAT_TIMEX_H
-
-#define CLOCK_TICK_RATE			48000000
-
-#endif /* __PLAT_TIMEX_H */
diff --git a/arch/arm/plat-spear/include/plat/uncompress.h b/arch/arm/plat-spear/include/plat/uncompress.h
deleted file mode 100644
index 51b2dc9..0000000
--- a/arch/arm/plat-spear/include/plat/uncompress.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * arch/arm/plat-spear/include/plat/uncompress.h
- *
- * Serial port stubs for kernel decompress status messages
- *
- * Copyright (C) 2009 ST Microelectronics
- * Viresh Kumar <viresh.linux@gmail.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/io.h>
-#include <linux/amba/serial.h>
-#include <mach/spear.h>
-
-#ifndef __PLAT_UNCOMPRESS_H
-#define __PLAT_UNCOMPRESS_H
-/*
- * This does not append a newline
- */
-static inline void putc(int c)
-{
-	void __iomem *base = (void __iomem *)SPEAR_DBG_UART_BASE;
-
-	while (readl_relaxed(base + UART01x_FR) & UART01x_FR_TXFF)
-		barrier();
-
-	writel_relaxed(c, base + UART01x_DR);
-}
-
-static inline void flush(void)
-{
-}
-
-/*
- * nothing to do
- */
-#define arch_decomp_setup()
-
-#endif /* __PLAT_UNCOMPRESS_H */
diff --git a/arch/arm/plat-spear/pl080.c b/arch/arm/plat-spear/pl080.c
deleted file mode 100644
index cfa1199..0000000
--- a/arch/arm/plat-spear/pl080.c
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * arch/arm/plat-spear/pl080.c
- *
- * DMAC pl080 definitions for SPEAr platform
- *
- * Copyright (C) 2012 ST Microelectronics
- * Viresh Kumar <viresh.linux@gmail.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/amba/pl08x.h>
-#include <linux/amba/bus.h>
-#include <linux/bug.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/spinlock_types.h>
-#include <mach/spear.h>
-#include <mach/misc_regs.h>
-
-static spinlock_t lock = __SPIN_LOCK_UNLOCKED(x);
-
-struct {
-	unsigned char busy;
-	unsigned char val;
-} signals[16] = {{0, 0}, };
-
-int pl080_get_signal(const struct pl08x_channel_data *cd)
-{
-	unsigned int signal = cd->min_signal, val;
-	unsigned long flags;
-
-	spin_lock_irqsave(&lock, flags);
-
-	/* Return if signal is already acquired by somebody else */
-	if (signals[signal].busy &&
-			(signals[signal].val != cd->muxval)) {
-		spin_unlock_irqrestore(&lock, flags);
-		return -EBUSY;
-	}
-
-	/* If acquiring for the first time, configure it */
-	if (!signals[signal].busy) {
-		val = readl(DMA_CHN_CFG);
-
-		/*
-		 * Each request line has two bits in DMA_CHN_CFG register. To
-		 * goto the bits of current request line, do left shift of
-		 * value by 2 * signal number.
-		 */
-		val &= ~(0x3 << (signal * 2));
-		val |= cd->muxval << (signal * 2);
-		writel(val, DMA_CHN_CFG);
-	}
-
-	signals[signal].busy++;
-	signals[signal].val = cd->muxval;
-	spin_unlock_irqrestore(&lock, flags);
-
-	return signal;
-}
-
-void pl080_put_signal(const struct pl08x_channel_data *cd, int signal)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&lock, flags);
-
-	/* if signal is not used */
-	if (!signals[signal].busy)
-		BUG();
-
-	signals[signal].busy--;
-
-	spin_unlock_irqrestore(&lock, flags);
-}
diff --git a/arch/arm/plat-spear/restart.c b/arch/arm/plat-spear/restart.c
deleted file mode 100644
index 7d4616d..0000000
--- a/arch/arm/plat-spear/restart.c
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * arch/arm/plat-spear/restart.c
- *
- * SPEAr platform specific restart functions
- *
- * Copyright (C) 2009 ST Microelectronics
- * Viresh Kumar <viresh.linux@gmail.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/io.h>
-#include <linux/amba/sp810.h>
-#include <asm/system_misc.h>
-#include <mach/spear.h>
-#include <mach/generic.h>
-
-#define SPEAR13XX_SYS_SW_RES			(VA_MISC_BASE + 0x204)
-void spear_restart(char mode, const char *cmd)
-{
-	if (mode == 's') {
-		/* software reset, Jump into ROM at address 0 */
-		soft_restart(0);
-	} else {
-		/* hardware reset, Use on-chip reset capability */
-#ifdef CONFIG_ARCH_SPEAR13XX
-		writel_relaxed(0x01, SPEAR13XX_SYS_SW_RES);
-#else
-		sysctl_soft_reset((void __iomem *)VA_SPEAR_SYS_CTRL_BASE);
-#endif
-	}
-}
diff --git a/arch/arm/plat-spear/time.c b/arch/arm/plat-spear/time.c
deleted file mode 100644
index bd5c53c..0000000
--- a/arch/arm/plat-spear/time.c
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * arch/arm/plat-spear/time.c
- *
- * Copyright (C) 2010 ST Microelectronics
- * Shiraz Hashim<shiraz.hashim@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.
- */
-
-#include <linux/clk.h>
-#include <linux/clockchips.h>
-#include <linux/clocksource.h>
-#include <linux/err.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/of_irq.h>
-#include <linux/of_address.h>
-#include <linux/time.h>
-#include <linux/irq.h>
-#include <asm/mach/time.h>
-#include <mach/generic.h>
-
-/*
- * We would use TIMER0 and TIMER1 as clockevent and clocksource.
- * Timer0 and Timer1 both belong to same gpt block in cpu subbsystem. Further
- * they share same functional clock. Any change in one's functional clock will
- * also affect other timer.
- */
-
-#define CLKEVT	0	/* gpt0, channel0 as clockevent */
-#define CLKSRC	1	/* gpt0, channel1 as clocksource */
-
-/* Register offsets, x is channel number */
-#define CR(x)		((x) * 0x80 + 0x80)
-#define IR(x)		((x) * 0x80 + 0x84)
-#define LOAD(x)		((x) * 0x80 + 0x88)
-#define COUNT(x)	((x) * 0x80 + 0x8C)
-
-/* Reg bit definitions */
-#define CTRL_INT_ENABLE		0x0100
-#define CTRL_ENABLE		0x0020
-#define CTRL_ONE_SHOT		0x0010
-
-#define CTRL_PRESCALER1		0x0
-#define CTRL_PRESCALER2		0x1
-#define CTRL_PRESCALER4		0x2
-#define CTRL_PRESCALER8		0x3
-#define CTRL_PRESCALER16	0x4
-#define CTRL_PRESCALER32	0x5
-#define CTRL_PRESCALER64	0x6
-#define CTRL_PRESCALER128	0x7
-#define CTRL_PRESCALER256	0x8
-
-#define INT_STATUS		0x1
-
-/*
- * Minimum clocksource/clockevent timer range in seconds
- */
-#define SPEAR_MIN_RANGE 4
-
-static __iomem void *gpt_base;
-static struct clk *gpt_clk;
-
-static void clockevent_set_mode(enum clock_event_mode mode,
-				struct clock_event_device *clk_event_dev);
-static int clockevent_next_event(unsigned long evt,
-				 struct clock_event_device *clk_event_dev);
-
-static void spear_clocksource_init(void)
-{
-	u32 tick_rate;
-	u16 val;
-
-	/* program the prescaler (/256)*/
-	writew(CTRL_PRESCALER256, gpt_base + CR(CLKSRC));
-
-	/* find out actual clock driving Timer */
-	tick_rate = clk_get_rate(gpt_clk);
-	tick_rate >>= CTRL_PRESCALER256;
-
-	writew(0xFFFF, gpt_base + LOAD(CLKSRC));
-
-	val = readw(gpt_base + CR(CLKSRC));
-	val &= ~CTRL_ONE_SHOT;	/* autoreload mode */
-	val |= CTRL_ENABLE ;
-	writew(val, gpt_base + CR(CLKSRC));
-
-	/* register the clocksource */
-	clocksource_mmio_init(gpt_base + COUNT(CLKSRC), "tmr1", tick_rate,
-		200, 16, clocksource_mmio_readw_up);
-}
-
-static struct clock_event_device clkevt = {
-	.name = "tmr0",
-	.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
-	.set_mode = clockevent_set_mode,
-	.set_next_event = clockevent_next_event,
-	.shift = 0,	/* to be computed */
-};
-
-static void clockevent_set_mode(enum clock_event_mode mode,
-				struct clock_event_device *clk_event_dev)
-{
-	u32 period;
-	u16 val;
-
-	/* stop the timer */
-	val = readw(gpt_base + CR(CLKEVT));
-	val &= ~CTRL_ENABLE;
-	writew(val, gpt_base + CR(CLKEVT));
-
-	switch (mode) {
-	case CLOCK_EVT_MODE_PERIODIC:
-		period = clk_get_rate(gpt_clk) / HZ;
-		period >>= CTRL_PRESCALER16;
-		writew(period, gpt_base + LOAD(CLKEVT));
-
-		val = readw(gpt_base + CR(CLKEVT));
-		val &= ~CTRL_ONE_SHOT;
-		val |= CTRL_ENABLE | CTRL_INT_ENABLE;
-		writew(val, gpt_base + CR(CLKEVT));
-
-		break;
-	case CLOCK_EVT_MODE_ONESHOT:
-		val = readw(gpt_base + CR(CLKEVT));
-		val |= CTRL_ONE_SHOT;
-		writew(val, gpt_base + CR(CLKEVT));
-
-		break;
-	case CLOCK_EVT_MODE_UNUSED:
-	case CLOCK_EVT_MODE_SHUTDOWN:
-	case CLOCK_EVT_MODE_RESUME:
-
-		break;
-	default:
-		pr_err("Invalid mode requested\n");
-		break;
-	}
-}
-
-static int clockevent_next_event(unsigned long cycles,
-				 struct clock_event_device *clk_event_dev)
-{
-	u16 val = readw(gpt_base + CR(CLKEVT));
-
-	if (val & CTRL_ENABLE)
-		writew(val & ~CTRL_ENABLE, gpt_base + CR(CLKEVT));
-
-	writew(cycles, gpt_base + LOAD(CLKEVT));
-
-	val |= CTRL_ENABLE | CTRL_INT_ENABLE;
-	writew(val, gpt_base + CR(CLKEVT));
-
-	return 0;
-}
-
-static irqreturn_t spear_timer_interrupt(int irq, void *dev_id)
-{
-	struct clock_event_device *evt = &clkevt;
-
-	writew(INT_STATUS, gpt_base + IR(CLKEVT));
-
-	evt->event_handler(evt);
-
-	return IRQ_HANDLED;
-}
-
-static struct irqaction spear_timer_irq = {
-	.name = "timer",
-	.flags = IRQF_DISABLED | IRQF_TIMER,
-	.handler = spear_timer_interrupt
-};
-
-static void __init spear_clockevent_init(int irq)
-{
-	u32 tick_rate;
-
-	/* program the prescaler */
-	writew(CTRL_PRESCALER16, gpt_base + CR(CLKEVT));
-
-	tick_rate = clk_get_rate(gpt_clk);
-	tick_rate >>= CTRL_PRESCALER16;
-
-	clkevt.cpumask = cpumask_of(0);
-
-	clockevents_config_and_register(&clkevt, tick_rate, 3, 0xfff0);
-
-	setup_irq(irq, &spear_timer_irq);
-}
-
-const static struct of_device_id timer_of_match[] __initconst = {
-	{ .compatible = "st,spear-timer", },
-	{ },
-};
-
-void __init spear_setup_of_timer(void)
-{
-	struct device_node *np;
-	int irq, ret;
-
-	np = of_find_matching_node(NULL, timer_of_match);
-	if (!np) {
-		pr_err("%s: No timer passed via DT\n", __func__);
-		return;
-	}
-
-	irq = irq_of_parse_and_map(np, 0);
-	if (!irq) {
-		pr_err("%s: No irq passed for timer via DT\n", __func__);
-		return;
-	}
-
-	gpt_base = of_iomap(np, 0);
-	if (!gpt_base) {
-		pr_err("%s: of iomap failed\n", __func__);
-		return;
-	}
-
-	gpt_clk = clk_get_sys("gpt0", NULL);
-	if (!gpt_clk) {
-		pr_err("%s:couldn't get clk for gpt\n", __func__);
-		goto err_iomap;
-	}
-
-	ret = clk_prepare_enable(gpt_clk);
-	if (ret < 0) {
-		pr_err("%s:couldn't prepare-enable gpt clock\n", __func__);
-		goto err_prepare_enable_clk;
-	}
-
-	spear_clockevent_init(irq);
-	spear_clocksource_init();
-
-	return;
-
-err_prepare_enable_clk:
-	clk_put(gpt_clk);
-err_iomap:
-	iounmap(gpt_base);
-}
diff --git a/arch/arm/plat-versatile/platsmp.c b/arch/arm/plat-versatile/platsmp.c
index f2ac155..1e1b2d7 100644
--- a/arch/arm/plat-versatile/platsmp.c
+++ b/arch/arm/plat-versatile/platsmp.c
@@ -14,7 +14,6 @@
 #include <linux/device.h>
 #include <linux/jiffies.h>
 #include <linux/smp.h>
-#include <linux/irqchip/arm-gic.h>
 
 #include <asm/cacheflush.h>
 #include <asm/smp_plat.h>
@@ -37,13 +36,6 @@ static DEFINE_SPINLOCK(boot_lock);
 void __cpuinit versatile_secondary_init(unsigned int cpu)
 {
 	/*
-	 * if any interrupts are already enabled for the primary
-	 * core (e.g. timer irq), then they will not have been enabled
-	 * for us: do so
-	 */
-	gic_secondary_init(0);
-
-	/*
 	 * let the primary processor know we're out of the
 	 * pen, then head off into the C entry point
 	 */
diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
index 831e1fd..a10297d 100644
--- a/arch/arm/tools/mach-types
+++ b/arch/arm/tools/mach-types
@@ -16,7 +16,7 @@
 # are merged into mainline or have been edited in the machine database
 # within the last 12 months.  References to machine_is_NAME() do not count!
 #
-# Last update: Thu Apr 26 08:44:23 2012
+# Last update: Fri Mar 22 17:24:50 2013
 #
 # machine_is_xxx	CONFIG_xxxx		MACH_TYPE_xxx		number
 #
@@ -64,8 +64,8 @@ h7201			ARCH_H7201		H7201			161
 h7202			ARCH_H7202		H7202			162
 iq80321			ARCH_IQ80321		IQ80321			169
 ks8695			ARCH_KS8695		KS8695			180
-karo			ARCH_KARO		KARO			190
 smdk2410		ARCH_SMDK2410		SMDK2410		193
+ceiva			ARCH_CEIVA		CEIVA			200
 voiceblue		MACH_VOICEBLUE		VOICEBLUE		218
 h5400			ARCH_H5400		H5400			220
 omap_innovator		MACH_OMAP_INNOVATOR	OMAP_INNOVATOR		234
@@ -95,6 +95,7 @@ lpd7a400		MACH_LPD7A400		LPD7A400		389
 lpd7a404		MACH_LPD7A404		LPD7A404		390
 csb337			MACH_CSB337		CSB337			399
 mainstone		MACH_MAINSTONE		MAINSTONE		406
+lite300			MACH_LITE300		LITE300			408
 xcep			MACH_XCEP		XCEP			413
 arcom_vulcan		MACH_ARCOM_VULCAN	ARCOM_VULCAN		414
 nomadik			MACH_NOMADIK		NOMADIK			420
@@ -131,12 +132,14 @@ kb9200			MACH_KB9200		KB9200			612
 sx1			MACH_SX1		SX1			613
 ixdp465			MACH_IXDP465		IXDP465			618
 ixdp2351		MACH_IXDP2351		IXDP2351		619
+cm4008			MACH_CM4008		CM4008			624
 iq80332			MACH_IQ80332		IQ80332			629
 gtwx5715		MACH_GTWX5715		GTWX5715		641
 csb637			MACH_CSB637		CSB637			648
 n30			MACH_N30		N30			656
 nec_mp900		MACH_NEC_MP900		NEC_MP900		659
 kafa			MACH_KAFA		KAFA			662
+cm41xx			MACH_CM41XX		CM41XX			672
 ts72xx			MACH_TS72XX		TS72XX			673
 otom			MACH_OTOM		OTOM			680
 nexcoder_2440		MACH_NEXCODER_2440	NEXCODER_2440		681
@@ -149,6 +152,7 @@ colibri			MACH_COLIBRI		COLIBRI			729
 gateway7001		MACH_GATEWAY7001	GATEWAY7001		731
 pcm027			MACH_PCM027		PCM027			732
 anubis			MACH_ANUBIS		ANUBIS			734
+xboardgp8		MACH_XBOARDGP8		XBOARDGP8		742
 akita			MACH_AKITA		AKITA			744
 e330			MACH_E330		E330			753
 nokia770		MACH_NOKIA770		NOKIA770		755
@@ -157,9 +161,11 @@ edb9315a		MACH_EDB9315A		EDB9315A		772
 stargate2		MACH_STARGATE2		STARGATE2		774
 intelmote2		MACH_INTELMOTE2		INTELMOTE2		775
 trizeps4		MACH_TRIZEPS4		TRIZEPS4		776
+pnx4008			MACH_PNX4008		PNX4008			782
 cpuat91			MACH_CPUAT91		CPUAT91			787
 iq81340sc		MACH_IQ81340SC		IQ81340SC		799
 iq81340mc		MACH_IQ81340MC		IQ81340MC		801
+se4200			MACH_SE4200		SE4200			809
 micro9			MACH_MICRO9		MICRO9			811
 micro9l			MACH_MICRO9L		MICRO9L			812
 omap_palmte		MACH_OMAP_PALMTE	OMAP_PALMTE		817
@@ -178,6 +184,7 @@ mx21ads			MACH_MX21ADS		MX21ADS			851
 ams_delta		MACH_AMS_DELTA		AMS_DELTA		862
 nas100d			MACH_NAS100D		NAS100D			865
 magician		MACH_MAGICIAN		MAGICIAN		875
+cm4002			MACH_CM4002		CM4002			876
 nxdkn			MACH_NXDKN		NXDKN			880
 palmtx			MACH_PALMTX		PALMTX			885
 s3c2413			MACH_S3C2413		S3C2413			887
@@ -203,7 +210,6 @@ omap_fsample		MACH_OMAP_FSAMPLE	OMAP_FSAMPLE		970
 snapper_cl15		MACH_SNAPPER_CL15	SNAPPER_CL15		986
 omap_palmz71		MACH_OMAP_PALMZ71	OMAP_PALMZ71		993
 smdk2412		MACH_SMDK2412		SMDK2412		1009
-bkde303			MACH_BKDE303		BKDE303			1021
 smdk2413		MACH_SMDK2413		SMDK2413		1022
 aml_m5900		MACH_AML_M5900		AML_M5900		1024
 balloon3		MACH_BALLOON3		BALLOON3		1029
@@ -214,6 +220,7 @@ fsg			MACH_FSG		FSG			1091
 at91sam9260ek		MACH_AT91SAM9260EK	AT91SAM9260EK		1099
 glantank		MACH_GLANTANK		GLANTANK		1100
 n2100			MACH_N2100		N2100			1101
+im42xx			MACH_IM42XX		IM42XX			1105
 qt2410			MACH_QT2410		QT2410			1108
 kixrp435		MACH_KIXRP435		KIXRP435		1109
 cc9p9360dev		MACH_CC9P9360DEV	CC9P9360DEV		1114
@@ -247,6 +254,7 @@ csb726			MACH_CSB726		CSB726			1359
 davinci_dm6467_evm	MACH_DAVINCI_DM6467_EVM	DAVINCI_DM6467_EVM	1380
 davinci_dm355_evm	MACH_DAVINCI_DM355_EVM	DAVINCI_DM355_EVM	1381
 littleton		MACH_LITTLETON		LITTLETON		1388
+im4004			MACH_IM4004		IM4004			1400
 realview_pb11mp		MACH_REALVIEW_PB11MP	REALVIEW_PB11MP		1407
 mx27_3ds		MACH_MX27_3DS		MX27_3DS		1430
 halibut			MACH_HALIBUT		HALIBUT			1439
@@ -268,6 +276,7 @@ dns323			MACH_DNS323		DNS323			1542
 omap3_beagle		MACH_OMAP3_BEAGLE	OMAP3_BEAGLE		1546
 nokia_n810		MACH_NOKIA_N810		NOKIA_N810		1548
 pcm038			MACH_PCM038		PCM038			1551
+sg310			MACH_SG310		SG310			1564
 ts209			MACH_TS209		TS209			1565
 at91cap9adk		MACH_AT91CAP9ADK	AT91CAP9ADK		1566
 mx31moboard		MACH_MX31MOBOARD	MX31MOBOARD		1574
@@ -371,7 +380,6 @@ pcm043			MACH_PCM043		PCM043			2072
 sheevaplug		MACH_SHEEVAPLUG		SHEEVAPLUG		2097
 avengers_lite		MACH_AVENGERS_LITE	AVENGERS_LITE		2104
 mx51_babbage		MACH_MX51_BABBAGE	MX51_BABBAGE		2125
-tx37			MACH_TX37		TX37			2127
 rd78x00_masa		MACH_RD78X00_MASA	RD78X00_MASA		2135
 dm355_leopard		MACH_DM355_LEOPARD	DM355_LEOPARD		2138
 ts219			MACH_TS219		TS219			2139
@@ -380,12 +388,12 @@ davinci_da850_evm	MACH_DAVINCI_DA850_EVM	DAVINCI_DA850_EVM	2157
 at91sam9g10ek		MACH_AT91SAM9G10EK	AT91SAM9G10EK		2159
 omap_4430sdp		MACH_OMAP_4430SDP	OMAP_4430SDP		2160
 magx_zn5		MACH_MAGX_ZN5		MAGX_ZN5		2162
-tx25			MACH_TX25		TX25			2177
 omap3_torpedo		MACH_OMAP3_TORPEDO	OMAP3_TORPEDO		2178
 anw6410			MACH_ANW6410		ANW6410			2183
 imx27_visstrim_m10	MACH_IMX27_VISSTRIM_M10	IMX27_VISSTRIM_M10	2187
 portuxg20		MACH_PORTUXG20		PORTUXG20		2191
 smdkc110		MACH_SMDKC110		SMDKC110		2193
+cabespresso		MACH_CABESPRESSO	CABESPRESSO		2194
 omap3517evm		MACH_OMAP3517EVM	OMAP3517EVM		2200
 netspace_v2		MACH_NETSPACE_V2	NETSPACE_V2		2201
 netspace_max_v2		MACH_NETSPACE_MAX_V2	NETSPACE_MAX_V2		2202
@@ -404,6 +412,7 @@ bigdisk			MACH_BIGDISK		BIGDISK			2283
 at91sam9g20ek_2mmc	MACH_AT91SAM9G20EK_2MMC	AT91SAM9G20EK_2MMC	2288
 bcmring			MACH_BCMRING		BCMRING			2289
 mahimahi		MACH_MAHIMAHI		MAHIMAHI		2304
+cerebric		MACH_CEREBRIC		CEREBRIC		2311
 smdk6442		MACH_SMDK6442		SMDK6442		2324
 openrd_base		MACH_OPENRD_BASE	OPENRD_BASE		2325
 devkit8000		MACH_DEVKIT8000		DEVKIT8000		2330
@@ -423,10 +432,10 @@ raumfeld_rc		MACH_RAUMFELD_RC	RAUMFELD_RC		2413
 raumfeld_connector	MACH_RAUMFELD_CONNECTOR	RAUMFELD_CONNECTOR	2414
 raumfeld_speaker	MACH_RAUMFELD_SPEAKER	RAUMFELD_SPEAKER	2415
 tnetv107x		MACH_TNETV107X		TNETV107X		2418
-mx51_m2id		MACH_MX51_M2ID		MX51_M2ID		2428
 smdkv210		MACH_SMDKV210		SMDKV210		2456
 omap_zoom3		MACH_OMAP_ZOOM3		OMAP_ZOOM3		2464
 omap_3630sdp		MACH_OMAP_3630SDP	OMAP_3630SDP		2465
+cybook2440		MACH_CYBOOK2440		CYBOOK2440		2466
 smartq7			MACH_SMARTQ7		SMARTQ7			2479
 watson_efm_plugin	MACH_WATSON_EFM_PLUGIN	WATSON_EFM_PLUGIN	2491
 g4evm			MACH_G4EVM		G4EVM			2493
@@ -434,12 +443,10 @@ omapl138_hawkboard	MACH_OMAPL138_HAWKBOARD	OMAPL138_HAWKBOARD	2495
 ts41x			MACH_TS41X		TS41X			2502
 phy3250			MACH_PHY3250		PHY3250			2511
 mini6410		MACH_MINI6410		MINI6410		2520
-tx51			MACH_TX51		TX51			2529
 mx28evk			MACH_MX28EVK		MX28EVK			2531
 smartq5			MACH_SMARTQ5		SMARTQ5			2534
 davinci_dm6467tevm	MACH_DAVINCI_DM6467TEVM	DAVINCI_DM6467TEVM	2548
 mxt_td60		MACH_MXT_TD60		MXT_TD60		2550
-pca101			MACH_PCA101		PCA101			2595
 capc7117		MACH_CAPC7117		CAPC7117		2612
 icontrol		MACH_ICONTROL		ICONTROL		2624
 gplugd			MACH_GPLUGD		GPLUGD			2625
@@ -465,6 +472,7 @@ igep0030		MACH_IGEP0030		IGEP0030		2717
 sbc3530			MACH_SBC3530		SBC3530			2722
 saarb			MACH_SAARB		SAARB			2727
 harmony			MACH_HARMONY		HARMONY			2731
+cybook_orizon		MACH_CYBOOK_ORIZON	CYBOOK_ORIZON		2733
 msm7x30_fluid		MACH_MSM7X30_FLUID	MSM7X30_FLUID		2741
 cm_t3517		MACH_CM_T3517		CM_T3517		2750
 wbd222			MACH_WBD222		WBD222			2753
@@ -480,10 +488,8 @@ eukrea_cpuimx35sd	MACH_EUKREA_CPUIMX35SD	EUKREA_CPUIMX35SD	2821
 eukrea_cpuimx51sd	MACH_EUKREA_CPUIMX51SD	EUKREA_CPUIMX51SD	2822
 eukrea_cpuimx51		MACH_EUKREA_CPUIMX51	EUKREA_CPUIMX51		2823
 smdkc210		MACH_SMDKC210		SMDKC210		2838
-pcaal1			MACH_PCAAL1		PCAAL1			2843
 t5325			MACH_T5325		T5325			2846
 income			MACH_INCOME		INCOME			2849
-mx257sx			MACH_MX257SX		MX257SX			2861
 goni			MACH_GONI		GONI			2862
 bv07			MACH_BV07		BV07			2882
 openrd_ultimate		MACH_OPENRD_ULTIMATE	OPENRD_ULTIMATE		2884
@@ -491,7 +497,6 @@ devixp			MACH_DEVIXP		DEVIXP			2885
 miccpt			MACH_MICCPT		MICCPT			2886
 mic256			MACH_MIC256		MIC256			2887
 u5500			MACH_U5500		U5500			2890
-pov15hd			MACH_POV15HD		POV15HD			2910
 linkstation_lschl	MACH_LINKSTATION_LSCHL	LINKSTATION_LSCHL	2913
 smdkv310		MACH_SMDKV310		SMDKV310		2925
 wm8505_7in_netbook	MACH_WM8505_7IN_NETBOOK	WM8505_7IN_NETBOOK	2928
@@ -518,7 +523,6 @@ prima2_evb		MACH_PRIMA2_EVB		PRIMA2_EVB		3103
 paz00			MACH_PAZ00		PAZ00			3128
 acmenetusfoxg20		MACH_ACMENETUSFOXG20	ACMENETUSFOXG20		3129
 ag5evm			MACH_AG5EVM		AG5EVM			3189
-tsunagi			MACH_TSUNAGI		TSUNAGI			3197
 ics_if_voip		MACH_ICS_IF_VOIP	ICS_IF_VOIP		3206
 wlf_cragg_6410		MACH_WLF_CRAGG_6410	WLF_CRAGG_6410		3207
 trimslice		MACH_TRIMSLICE		TRIMSLICE		3209
@@ -529,8 +533,6 @@ msm8960_sim		MACH_MSM8960_SIM	MSM8960_SIM		3230
 msm8960_rumi3		MACH_MSM8960_RUMI3	MSM8960_RUMI3		3231
 gsia18s			MACH_GSIA18S		GSIA18S			3234
 mx53_loco		MACH_MX53_LOCO		MX53_LOCO		3273
-tx53			MACH_TX53		TX53			3279
-encore			MACH_ENCORE		ENCORE			3284
 wario			MACH_WARIO		WARIO			3288
 cm_t3730		MACH_CM_T3730		CM_T3730		3290
 hrefv60			MACH_HREFV60		HREFV60			3293
@@ -538,603 +540,24 @@ armlex4210		MACH_ARMLEX4210		ARMLEX4210		3361
 snowball		MACH_SNOWBALL		SNOWBALL		3363
 xilinx_ep107		MACH_XILINX_EP107	XILINX_EP107		3378
 nuri			MACH_NURI		NURI			3379
-wtplug			MACH_WTPLUG		WTPLUG			3412
-veridis_a300		MACH_VERIDIS_A300	VERIDIS_A300		3448
 origen			MACH_ORIGEN		ORIGEN			3455
-wm8650refboard		MACH_WM8650REFBOARD	WM8650REFBOARD		3472
-xarina			MACH_XARINA		XARINA			3476
-sdvr			MACH_SDVR		SDVR			3478
-acer_maya		MACH_ACER_MAYA		ACER_MAYA		3479
-pico			MACH_PICO		PICO			3480
-cwmx233			MACH_CWMX233		CWMX233			3481
-cwam1808		MACH_CWAM1808		CWAM1808		3482
-cwdm365			MACH_CWDM365		CWDM365			3483
-mx51_moray		MACH_MX51_MORAY		MX51_MORAY		3484
-thales_cbc		MACH_THALES_CBC		THALES_CBC		3485
-bluepoint		MACH_BLUEPOINT		BLUEPOINT		3486
-dir665			MACH_DIR665		DIR665			3487
-acmerover1		MACH_ACMEROVER1		ACMEROVER1		3488
-shooter_ct		MACH_SHOOTER_CT		SHOOTER_CT		3489
-bliss			MACH_BLISS		BLISS			3490
-blissc			MACH_BLISSC		BLISSC			3491
-thales_adc		MACH_THALES_ADC		THALES_ADC		3492
-ubisys_p9d_evp		MACH_UBISYS_P9D_EVP	UBISYS_P9D_EVP		3493
-atdgp318		MACH_ATDGP318		ATDGP318		3494
-dma210u			MACH_DMA210U		DMA210U			3495
-em_t3			MACH_EM_T3		EM_T3			3496
-htx3250			MACH_HTX3250		HTX3250			3497
-g50			MACH_G50		G50			3498
-eco5			MACH_ECO5		ECO5			3499
-wintergrasp		MACH_WINTERGRASP	WINTERGRASP		3500
-puro			MACH_PURO		PURO			3501
-shooter_k		MACH_SHOOTER_K		SHOOTER_K		3502
 nspire			MACH_NSPIRE		NSPIRE			3503
-mickxx			MACH_MICKXX		MICKXX			3504
-lxmb			MACH_LXMB		LXMB			3505
-adam			MACH_ADAM		ADAM			3507
-b1004			MACH_B1004		B1004			3508
-oboea			MACH_OBOEA		OBOEA			3509
-a1015			MACH_A1015		A1015			3510
-robin_vbdt30		MACH_ROBIN_VBDT30	ROBIN_VBDT30		3511
-tegra_enterprise	MACH_TEGRA_ENTERPRISE	TEGRA_ENTERPRISE	3512
-rfl108200_mk10		MACH_RFL108200_MK10	RFL108200_MK10		3513
-rfl108300_mk16		MACH_RFL108300_MK16	RFL108300_MK16		3514
-rover_v7		MACH_ROVER_V7		ROVER_V7		3515
-miphone			MACH_MIPHONE		MIPHONE			3516
-femtobts		MACH_FEMTOBTS		FEMTOBTS		3517
-monopoli		MACH_MONOPOLI		MONOPOLI		3518
-boss			MACH_BOSS		BOSS			3519
-davinci_dm368_vtam	MACH_DAVINCI_DM368_VTAM	DAVINCI_DM368_VTAM	3520
-clcon			MACH_CLCON		CLCON			3521
 nokia_rm696		MACH_NOKIA_RM696	NOKIA_RM696		3522
-tahiti			MACH_TAHITI		TAHITI			3523
-fighter			MACH_FIGHTER		FIGHTER			3524
-sgh_i710		MACH_SGH_I710		SGH_I710		3525
-integreproscb		MACH_INTEGREPROSCB	INTEGREPROSCB		3526
-monza			MACH_MONZA		MONZA			3527
-calimain		MACH_CALIMAIN		CALIMAIN		3528
-mx6q_sabreauto		MACH_MX6Q_SABREAUTO	MX6Q_SABREAUTO		3529
-gma01x			MACH_GMA01X		GMA01X			3530
-sbc51			MACH_SBC51		SBC51			3531
-fit			MACH_FIT		FIT			3532
-steelhead		MACH_STEELHEAD		STEELHEAD		3533
-panther			MACH_PANTHER		PANTHER			3534
-msm8960_liquid		MACH_MSM8960_LIQUID	MSM8960_LIQUID		3535
-lexikonct		MACH_LEXIKONCT		LEXIKONCT		3536
-ns2816_stb		MACH_NS2816_STB		NS2816_STB		3537
-sei_mm2_lpc3250		MACH_SEI_MM2_LPC3250	SEI_MM2_LPC3250		3538
-cmimx53			MACH_CMIMX53		CMIMX53			3539
-sandwich		MACH_SANDWICH		SANDWICH		3540
-chief			MACH_CHIEF		CHIEF			3541
-pogo_e02		MACH_POGO_E02		POGO_E02		3542
 mikrap_x168		MACH_MIKRAP_X168	MIKRAP_X168		3543
-htcmozart		MACH_HTCMOZART		HTCMOZART		3544
-htcgold			MACH_HTCGOLD		HTCGOLD			3545
-mt72xx			MACH_MT72XX		MT72XX			3546
-mx51_ivy		MACH_MX51_IVY		MX51_IVY		3547
-mx51_lvd		MACH_MX51_LVD		MX51_LVD		3548
-omap3_wiser2		MACH_OMAP3_WISER2	OMAP3_WISER2		3549
-dreamplug		MACH_DREAMPLUG		DREAMPLUG		3550
-cobas_c_111		MACH_COBAS_C_111	COBAS_C_111		3551
-cobas_u_411		MACH_COBAS_U_411	COBAS_U_411		3552
-hssd			MACH_HSSD		HSSD			3553
-iom35x			MACH_IOM35X		IOM35X			3554
-psom_omap		MACH_PSOM_OMAP		PSOM_OMAP		3555
-iphone_2g		MACH_IPHONE_2G		IPHONE_2G		3556
-iphone_3g		MACH_IPHONE_3G		IPHONE_3G		3557
-ipod_touch_1g		MACH_IPOD_TOUCH_1G	IPOD_TOUCH_1G		3558
-pharos_tpc		MACH_PHAROS_TPC		PHAROS_TPC		3559
-mx53_hydra		MACH_MX53_HYDRA		MX53_HYDRA		3560
-ns2816_dev_board	MACH_NS2816_DEV_BOARD	NS2816_DEV_BOARD	3561
-iphone_3gs		MACH_IPHONE_3GS		IPHONE_3GS		3562
-iphone_4		MACH_IPHONE_4		IPHONE_4		3563
-ipod_touch_4g		MACH_IPOD_TOUCH_4G	IPOD_TOUCH_4G		3564
-dragon_e1100		MACH_DRAGON_E1100	DRAGON_E1100		3565
-topside			MACH_TOPSIDE		TOPSIDE			3566
-irisiii			MACH_IRISIII		IRISIII			3567
 deto_macarm9		MACH_DETO_MACARM9	DETO_MACARM9		3568
-eti_d1			MACH_ETI_D1		ETI_D1			3569
-som3530sdk		MACH_SOM3530SDK		SOM3530SDK		3570
-oc_engine		MACH_OC_ENGINE		OC_ENGINE		3571
-apq8064_sim		MACH_APQ8064_SIM	APQ8064_SIM		3572
-alps			MACH_ALPS		ALPS			3575
-tny_t3730		MACH_TNY_T3730		TNY_T3730		3576
-geryon_nfe		MACH_GERYON_NFE		GERYON_NFE		3577
-ns2816_ref_board	MACH_NS2816_REF_BOARD	NS2816_REF_BOARD	3578
-silverstone		MACH_SILVERSTONE	SILVERSTONE		3579
-mtt2440			MACH_MTT2440		MTT2440			3580
-ynicdb			MACH_YNICDB		YNICDB			3581
-bct			MACH_BCT		BCT			3582
-tuscan			MACH_TUSCAN		TUSCAN			3583
-xbt_sam9g45		MACH_XBT_SAM9G45	XBT_SAM9G45		3584
-enbw_cmc		MACH_ENBW_CMC		ENBW_CMC		3585
-ch104mx257		MACH_CH104MX257		CH104MX257		3587
-openpri			MACH_OPENPRI		OPENPRI			3588
-am335xevm		MACH_AM335XEVM		AM335XEVM		3589
-picodmb			MACH_PICODMB		PICODMB			3590
-waluigi			MACH_WALUIGI		WALUIGI			3591
-punicag7		MACH_PUNICAG7		PUNICAG7		3592
-ipad_1g			MACH_IPAD_1G		IPAD_1G			3593
-appletv_2g		MACH_APPLETV_2G		APPLETV_2G		3594
-mach_ecog45		MACH_MACH_ECOG45	MACH_ECOG45		3595
-ait_cam_enc_4xx		MACH_AIT_CAM_ENC_4XX	AIT_CAM_ENC_4XX		3596
-runnymede		MACH_RUNNYMEDE		RUNNYMEDE		3597
-play			MACH_PLAY		PLAY			3598
-hw90260			MACH_HW90260		HW90260			3599
-tagh			MACH_TAGH		TAGH			3600
-filbert			MACH_FILBERT		FILBERT			3601
-getinge_netcomv3	MACH_GETINGE_NETCOMV3	GETINGE_NETCOMV3	3602
-cw20			MACH_CW20		CW20			3603
-cinema			MACH_CINEMA		CINEMA			3604
-cinema_tea		MACH_CINEMA_TEA		CINEMA_TEA		3605
-cinema_coffee		MACH_CINEMA_COFFEE	CINEMA_COFFEE		3606
-cinema_juice		MACH_CINEMA_JUICE	CINEMA_JUICE		3607
-mx53_mirage2		MACH_MX53_MIRAGE2	MX53_MIRAGE2		3609
-mx53_efikasb		MACH_MX53_EFIKASB	MX53_EFIKASB		3610
-stm_b2000		MACH_STM_B2000		STM_B2000		3612
 m28evk			MACH_M28EVK		M28EVK			3613
-pda			MACH_PDA		PDA			3614
-meraki_mr58		MACH_MERAKI_MR58	MERAKI_MR58		3615
 kota2			MACH_KOTA2		KOTA2			3616
-letcool			MACH_LETCOOL		LETCOOL			3617
-mx27iat			MACH_MX27IAT		MX27IAT			3618
-apollo_td		MACH_APOLLO_TD		APOLLO_TD		3619
-arena			MACH_ARENA		ARENA			3620
-gsngateway		MACH_GSNGATEWAY		GSNGATEWAY		3621
-lf2000			MACH_LF2000		LF2000			3622
 bonito			MACH_BONITO		BONITO			3623
-asymptote		MACH_ASYMPTOTE		ASYMPTOTE		3624
-bst2brd			MACH_BST2BRD		BST2BRD			3625
-tx335s			MACH_TX335S		TX335S			3626
-pelco_tesla		MACH_PELCO_TESLA	PELCO_TESLA		3627
-rrhtestplat		MACH_RRHTESTPLAT	RRHTESTPLAT		3628
-vidtonic_pro		MACH_VIDTONIC_PRO	VIDTONIC_PRO		3629
-pl_apollo		MACH_PL_APOLLO		PL_APOLLO		3630
-pl_phoenix		MACH_PL_PHOENIX		PL_PHOENIX		3631
-m28cu3			MACH_M28CU3		M28CU3			3632
-vvbox_hd		MACH_VVBOX_HD		VVBOX_HD		3633
-coreware_sam9260_	MACH_COREWARE_SAM9260_	COREWARE_SAM9260_	3634
-marmaduke		MACH_MARMADUKE		MARMADUKE		3635
-amg_xlcore_camera	MACH_AMG_XLCORE_CAMERA	AMG_XLCORE_CAMERA	3636
 omap3_egf		MACH_OMAP3_EGF		OMAP3_EGF		3637
 smdk4212		MACH_SMDK4212		SMDK4212		3638
-dnp9200			MACH_DNP9200		DNP9200			3639
-tf101			MACH_TF101		TF101			3640
-omap3silvio		MACH_OMAP3SILVIO	OMAP3SILVIO		3641
-picasso2		MACH_PICASSO2		PICASSO2		3642
-vangogh2		MACH_VANGOGH2		VANGOGH2		3643
-olpc_xo_1_75		MACH_OLPC_XO_1_75	OLPC_XO_1_75		3644
-gx400			MACH_GX400		GX400			3645
-gs300			MACH_GS300		GS300			3646
-acer_a9			MACH_ACER_A9		ACER_A9			3647
-vivow_evm		MACH_VIVOW_EVM		VIVOW_EVM		3648
-veloce_cxq		MACH_VELOCE_CXQ		VELOCE_CXQ		3649
-veloce_cxm		MACH_VELOCE_CXM		VELOCE_CXM		3650
-p1852			MACH_P1852		P1852			3651
-naxy100			MACH_NAXY100		NAXY100			3652
-taishan			MACH_TAISHAN		TAISHAN			3653
-touchlink		MACH_TOUCHLINK		TOUCHLINK		3654
-stm32f103ze		MACH_STM32F103ZE	STM32F103ZE		3655
-mcx			MACH_MCX		MCX			3656
-stm_nmhdk_fli7610	MACH_STM_NMHDK_FLI7610	STM_NMHDK_FLI7610	3657
-top28x			MACH_TOP28X		TOP28X			3658
-okl4vp_microvisor	MACH_OKL4VP_MICROVISOR	OKL4VP_MICROVISOR	3659
-pop			MACH_POP		POP			3660
-layer			MACH_LAYER		LAYER			3661
-trondheim		MACH_TRONDHEIM		TRONDHEIM		3662
-eva			MACH_EVA		EVA			3663
-trust_taurus		MACH_TRUST_TAURUS	TRUST_TAURUS		3664
-ns2816_huashan		MACH_NS2816_HUASHAN	NS2816_HUASHAN		3665
-ns2816_yangcheng	MACH_NS2816_YANGCHENG	NS2816_YANGCHENG	3666
-p852			MACH_P852		P852			3667
-flea3			MACH_FLEA3		FLEA3			3668
-bowfin			MACH_BOWFIN		BOWFIN			3669
-mv88de3100		MACH_MV88DE3100		MV88DE3100		3670
-pia_am35x		MACH_PIA_AM35X		PIA_AM35X		3671
-cedar			MACH_CEDAR		CEDAR			3672
-picasso_e		MACH_PICASSO_E		PICASSO_E		3673
-samsung_e60		MACH_SAMSUNG_E60	SAMSUNG_E60		3674
-sdvr_mini		MACH_SDVR_MINI		SDVR_MINI		3676
-omap3_ij3k		MACH_OMAP3_IJ3K		OMAP3_IJ3K		3677
-modasmc1		MACH_MODASMC1		MODASMC1		3678
-apq8064_rumi3		MACH_APQ8064_RUMI3	APQ8064_RUMI3		3679
-matrix506		MACH_MATRIX506		MATRIX506		3680
-msm9615_mtp		MACH_MSM9615_MTP	MSM9615_MTP		3681
-dm36x_spawndc		MACH_DM36X_SPAWNDC	DM36X_SPAWNDC		3682
-sff792			MACH_SFF792		SFF792			3683
-am335xiaevm		MACH_AM335XIAEVM	AM335XIAEVM		3684
-g3c2440			MACH_G3C2440		G3C2440			3685
-tion270			MACH_TION270		TION270			3686
-w22q7arm02		MACH_W22Q7ARM02		W22Q7ARM02		3687
-omap_cat		MACH_OMAP_CAT		OMAP_CAT		3688
-at91sam9n12ek		MACH_AT91SAM9N12EK	AT91SAM9N12EK		3689
-morrison		MACH_MORRISON		MORRISON		3690
-svdu			MACH_SVDU		SVDU			3691
-lpp01			MACH_LPP01		LPP01			3692
-ubc283			MACH_UBC283		UBC283			3693
-zeppelin		MACH_ZEPPELIN		ZEPPELIN		3694
-motus			MACH_MOTUS		MOTUS			3695
-neomainboard		MACH_NEOMAINBOARD	NEOMAINBOARD		3696
-devkit3250		MACH_DEVKIT3250		DEVKIT3250		3697
-devkit7000		MACH_DEVKIT7000		DEVKIT7000		3698
-fmc_uic			MACH_FMC_UIC		FMC_UIC			3699
-fmc_dcm			MACH_FMC_DCM		FMC_DCM			3700
-batwm			MACH_BATWM		BATWM			3701
-atlas6cb		MACH_ATLAS6CB		ATLAS6CB		3702
-blue			MACH_BLUE		BLUE			3705
-colorado		MACH_COLORADO		COLORADO		3706
-popc			MACH_POPC		POPC			3707
-promwad_jade		MACH_PROMWAD_JADE	PROMWAD_JADE		3708
-amp			MACH_AMP		AMP			3709
-gnet_amp		MACH_GNET_AMP		GNET_AMP		3710
-toques			MACH_TOQUES		TOQUES			3711
 apx4devkit		MACH_APX4DEVKIT		APX4DEVKIT		3712
-dct_storm		MACH_DCT_STORM		DCT_STORM		3713
-owl			MACH_OWL		OWL			3715
-cogent_csb1741		MACH_COGENT_CSB1741	COGENT_CSB1741		3716
-adillustra610		MACH_ADILLUSTRA610	ADILLUSTRA610		3718
-ecafe_na04		MACH_ECAFE_NA04		ECAFE_NA04		3719
-popct			MACH_POPCT		POPCT			3720
-omap3_helena		MACH_OMAP3_HELENA	OMAP3_HELENA		3721
-ach			MACH_ACH		ACH			3722
-module_dtb		MACH_MODULE_DTB		MODULE_DTB		3723
-oslo_elisabeth		MACH_OSLO_ELISABETH	OSLO_ELISABETH		3725
-tt01			MACH_TT01		TT01			3726
-msm8930_cdp		MACH_MSM8930_CDP	MSM8930_CDP		3727
-msm8930_mtp		MACH_MSM8930_MTP	MSM8930_MTP		3728
-msm8930_fluid		MACH_MSM8930_FLUID	MSM8930_FLUID		3729
-ltu11			MACH_LTU11		LTU11			3730
-am1808_spawnco		MACH_AM1808_SPAWNCO	AM1808_SPAWNCO		3731
-flx6410			MACH_FLX6410		FLX6410			3732
-mx6q_qsb		MACH_MX6Q_QSB		MX6Q_QSB		3733
-mx53_plt424		MACH_MX53_PLT424	MX53_PLT424		3734
-jasmine			MACH_JASMINE		JASMINE			3735
-l138_owlboard_plus	MACH_L138_OWLBOARD_PLUS	L138_OWLBOARD_PLUS	3736
-wr21			MACH_WR21		WR21			3737
-peaboy			MACH_PEABOY		PEABOY			3739
-mx28_plato		MACH_MX28_PLATO		MX28_PLATO		3740
-kacom2			MACH_KACOM2		KACOM2			3741
-slco			MACH_SLCO		SLCO			3742
-imx51pico		MACH_IMX51PICO		IMX51PICO		3743
-glink1			MACH_GLINK1		GLINK1			3744
-diamond			MACH_DIAMOND		DIAMOND			3745
-d9000			MACH_D9000		D9000			3746
-w5300e01		MACH_W5300E01		W5300E01		3747
-im6000			MACH_IM6000		IM6000			3748
-mx51_fred51		MACH_MX51_FRED51	MX51_FRED51		3749
-stm32f2			MACH_STM32F2		STM32F2			3750
-ville			MACH_VILLE		VILLE			3751
-ptip_murnau		MACH_PTIP_MURNAU	PTIP_MURNAU		3752
-ptip_classic		MACH_PTIP_CLASSIC	PTIP_CLASSIC		3753
-mx53grb			MACH_MX53GRB		MX53GRB			3754
-gagarin			MACH_GAGARIN		GAGARIN			3755
-nas2big			MACH_NAS2BIG		NAS2BIG			3757
-superfemto		MACH_SUPERFEMTO		SUPERFEMTO		3758
-teufel			MACH_TEUFEL		TEUFEL			3759
-dinara			MACH_DINARA		DINARA			3760
-vanquish		MACH_VANQUISH		VANQUISH		3761
-zipabox1		MACH_ZIPABOX1		ZIPABOX1		3762
-u9540			MACH_U9540		U9540			3763
-jet			MACH_JET		JET			3764
 smdk4412		MACH_SMDK4412		SMDK4412		3765
-elite			MACH_ELITE		ELITE			3766
-spear320_hmi		MACH_SPEAR320_HMI	SPEAR320_HMI		3767
-ontario			MACH_ONTARIO		ONTARIO			3768
-mx6q_sabrelite		MACH_MX6Q_SABRELITE	MX6Q_SABRELITE		3769
-vc200			MACH_VC200		VC200			3770
-msm7625a_ffa		MACH_MSM7625A_FFA	MSM7625A_FFA		3771
-msm7625a_surf		MACH_MSM7625A_SURF	MSM7625A_SURF		3772
-benthossbp		MACH_BENTHOSSBP		BENTHOSSBP		3773
-smdk5210		MACH_SMDK5210		SMDK5210		3774
-empq2300		MACH_EMPQ2300		EMPQ2300		3775
-minipos			MACH_MINIPOS		MINIPOS			3776
-omap5_sevm		MACH_OMAP5_SEVM		OMAP5_SEVM		3777
-shelter			MACH_SHELTER		SHELTER			3778
-omap3_devkit8500	MACH_OMAP3_DEVKIT8500	OMAP3_DEVKIT8500	3779
-edgetd			MACH_EDGETD		EDGETD			3780
-copperyard		MACH_COPPERYARD		COPPERYARD		3781
-edge_u			MACH_EDGE_U		EDGE_U			3783
-edge_td			MACH_EDGE_TD		EDGE_TD			3784
-wdss			MACH_WDSS		WDSS			3785
-dl_pb25			MACH_DL_PB25		DL_PB25			3786
-dss11			MACH_DSS11		DSS11			3787
-cpa			MACH_CPA		CPA			3788
-aptp2000		MACH_APTP2000		APTP2000		3789
 marzen			MACH_MARZEN		MARZEN			3790
-st_turbine		MACH_ST_TURBINE		ST_TURBINE		3791
-gtl_it3300		MACH_GTL_IT3300		GTL_IT3300		3792
-mx6_mule		MACH_MX6_MULE		MX6_MULE		3793
-v7pxa_dt		MACH_V7PXA_DT		V7PXA_DT		3794
-v7mmp_dt		MACH_V7MMP_DT		V7MMP_DT		3795
-dragon7			MACH_DRAGON7		DRAGON7			3796
 krome			MACH_KROME		KROME			3797
-oratisdante		MACH_ORATISDANTE	ORATISDANTE		3798
-fathom			MACH_FATHOM		FATHOM			3799
-dns325			MACH_DNS325		DNS325			3800
-sarnen			MACH_SARNEN		SARNEN			3801
-ubisys_g1		MACH_UBISYS_G1		UBISYS_G1		3802
-mx53_pf1		MACH_MX53_PF1		MX53_PF1		3803
-asanti			MACH_ASANTI		ASANTI			3804
-volta			MACH_VOLTA		VOLTA			3805
-knight			MACH_KNIGHT		KNIGHT			3807
-beaglebone		MACH_BEAGLEBONE		BEAGLEBONE		3808
-becker			MACH_BECKER		BECKER			3809
-fc360			MACH_FC360		FC360			3810
-pmi2_xls		MACH_PMI2_XLS		PMI2_XLS		3811
-taranto			MACH_TARANTO		TARANTO			3812
-plutux			MACH_PLUTUX		PLUTUX			3813
-ipmp_medcom		MACH_IPMP_MEDCOM	IPMP_MEDCOM		3814
-absolut			MACH_ABSOLUT		ABSOLUT			3815
-awpb3			MACH_AWPB3		AWPB3			3816
-nfp32xx_dt		MACH_NFP32XX_DT		NFP32XX_DT		3817
-dl_pb53			MACH_DL_PB53		DL_PB53			3818
-acu_ii			MACH_ACU_II		ACU_II			3819
-avalon			MACH_AVALON		AVALON			3820
-sphinx			MACH_SPHINX		SPHINX			3821
-titan_t			MACH_TITAN_T		TITAN_T			3822
-harvest_boris		MACH_HARVEST_BORIS	HARVEST_BORIS		3823
-mach_msm7x30_m3s	MACH_MACH_MSM7X30_M3S	MACH_MSM7X30_M3S	3824
-smdk5250		MACH_SMDK5250		SMDK5250		3825
-imxt_lite		MACH_IMXT_LITE		IMXT_LITE		3826
-imxt_std		MACH_IMXT_STD		IMXT_STD		3827
-imxt_log		MACH_IMXT_LOG		IMXT_LOG		3828
-imxt_nav		MACH_IMXT_NAV		IMXT_NAV		3829
-imxt_full		MACH_IMXT_FULL		IMXT_FULL		3830
-ag09015			MACH_AG09015		AG09015			3831
-am3517_mt_ventoux	MACH_AM3517_MT_VENTOUX	AM3517_MT_VENTOUX	3832
-dp1arm9			MACH_DP1ARM9		DP1ARM9			3833
-picasso_m		MACH_PICASSO_M		PICASSO_M		3834
-video_gadget		MACH_VIDEO_GADGET	VIDEO_GADGET		3835
-mtt_om3x		MACH_MTT_OM3X		MTT_OM3X		3836
-mx6q_arm2		MACH_MX6Q_ARM2		MX6Q_ARM2		3837
-picosam9g45		MACH_PICOSAM9G45	PICOSAM9G45		3838
-vpm_dm365		MACH_VPM_DM365		VPM_DM365		3839
-bonfire			MACH_BONFIRE		BONFIRE			3840
-mt2p2d			MACH_MT2P2D		MT2P2D			3841
-sigpda01		MACH_SIGPDA01		SIGPDA01		3842
-cn27			MACH_CN27		CN27			3843
-mx25_cwtap		MACH_MX25_CWTAP		MX25_CWTAP		3844
-apf28			MACH_APF28		APF28			3845
-pelco_maxwell		MACH_PELCO_MAXWELL	PELCO_MAXWELL		3846
-ge_phoenix		MACH_GE_PHOENIX		GE_PHOENIX		3847
-empc_a500		MACH_EMPC_A500		EMPC_A500		3848
-ims_arm9		MACH_IMS_ARM9		IMS_ARM9		3849
-mini2416		MACH_MINI2416		MINI2416		3850
-mini2450		MACH_MINI2450		MINI2450		3851
-mini310			MACH_MINI310		MINI310			3852
-spear_hurricane		MACH_SPEAR_HURRICANE	SPEAR_HURRICANE		3853
-mt7208			MACH_MT7208		MT7208			3854
-lpc178x			MACH_LPC178X		LPC178X			3855
-farleys			MACH_FARLEYS		FARLEYS			3856
-efm32gg_dk3750		MACH_EFM32GG_DK3750	EFM32GG_DK3750		3857
-zeus_board		MACH_ZEUS_BOARD		ZEUS_BOARD		3858
-cc51			MACH_CC51		CC51			3859
-fxi_c210		MACH_FXI_C210		FXI_C210		3860
-msm8627_cdp		MACH_MSM8627_CDP	MSM8627_CDP		3861
-msm8627_mtp		MACH_MSM8627_MTP	MSM8627_MTP		3862
 armadillo800eva		MACH_ARMADILLO800EVA	ARMADILLO800EVA		3863
-primou			MACH_PRIMOU		PRIMOU			3864
-primoc			MACH_PRIMOC		PRIMOC			3865
-primoct			MACH_PRIMOCT		PRIMOCT			3866
-a9500			MACH_A9500		A9500			3867
-pluto			MACH_PLUTO		PLUTO			3869
-acfx100			MACH_ACFX100		ACFX100			3870
-msm8625_rumi3		MACH_MSM8625_RUMI3	MSM8625_RUMI3		3871
-valente			MACH_VALENTE		VALENTE			3872
-crfs_rfeye		MACH_CRFS_RFEYE		CRFS_RFEYE		3873
-rfeye			MACH_RFEYE		RFEYE			3874
-phidget_sbc3		MACH_PHIDGET_SBC3	PHIDGET_SBC3		3875
-tcw_mika		MACH_TCW_MIKA		TCW_MIKA		3876
-imx28_egf		MACH_IMX28_EGF		IMX28_EGF		3877
-valente_wx		MACH_VALENTE_WX		VALENTE_WX		3878
-huangshans		MACH_HUANGSHANS		HUANGSHANS		3879
-bosphorus1		MACH_BOSPHORUS1		BOSPHORUS1		3880
-prima			MACH_PRIMA		PRIMA			3881
-evita_ulk		MACH_EVITA_ULK		EVITA_ULK		3884
-merisc600		MACH_MERISC600		MERISC600		3885
-dolak			MACH_DOLAK		DOLAK			3886
-sbc53			MACH_SBC53		SBC53			3887
-elite_ulk		MACH_ELITE_ULK		ELITE_ULK		3888
-pov2			MACH_POV2		POV2			3889
-ipod_touch_2g		MACH_IPOD_TOUCH_2G	IPOD_TOUCH_2G		3890
-da850_pqab		MACH_DA850_PQAB		DA850_PQAB		3891
-fermi			MACH_FERMI		FERMI			3892
-ccardwmx28		MACH_CCARDWMX28		CCARDWMX28		3893
-ccardmx28		MACH_CCARDMX28		CCARDMX28		3894
-fs20_fcm2050		MACH_FS20_FCM2050	FS20_FCM2050		3895
-kinetis			MACH_KINETIS		KINETIS			3896
-kai			MACH_KAI		KAI			3897
-bcthb2			MACH_BCTHB2		BCTHB2			3898
-inels3_cu		MACH_INELS3_CU		INELS3_CU		3899
-da850_apollo		MACH_DA850_APOLLO	DA850_APOLLO		3901
-tracnas			MACH_TRACNAS		TRACNAS			3902
-mityarm335x		MACH_MITYARM335X	MITYARM335X		3903
-xcgz7x			MACH_XCGZ7X		XCGZ7X			3904
-cubox			MACH_CUBOX		CUBOX			3905
-terminator		MACH_TERMINATOR		TERMINATOR		3906
-eye03			MACH_EYE03		EYE03			3907
-kota3			MACH_KOTA3		KOTA3			3908
-pscpe			MACH_PSCPE		PSCPE			3910
-akt1100			MACH_AKT1100		AKT1100			3911
-pcaaxl2			MACH_PCAAXL2		PCAAXL2			3912
-primodd_ct		MACH_PRIMODD_CT		PRIMODD_CT		3913
-nsbc			MACH_NSBC		NSBC			3914
-meson2_skt		MACH_MESON2_SKT		MESON2_SKT		3915
-meson2_ref		MACH_MESON2_REF		MESON2_REF		3916
-ccardwmx28js		MACH_CCARDWMX28JS	CCARDWMX28JS		3917
-ccardmx28js		MACH_CCARDMX28JS	CCARDMX28JS		3918
-indico			MACH_INDICO		INDICO			3919
-msm8960dt		MACH_MSM8960DT		MSM8960DT		3920
-primods			MACH_PRIMODS		PRIMODS			3921
-beluga_m1388		MACH_BELUGA_M1388	BELUGA_M1388		3922
-primotd			MACH_PRIMOTD		PRIMOTD			3923
-varan_master		MACH_VARAN_MASTER	VARAN_MASTER		3924
-primodd			MACH_PRIMODD		PRIMODD			3925
-jetduo			MACH_JETDUO		JETDUO			3926
 mx53_umobo		MACH_MX53_UMOBO		MX53_UMOBO		3927
-trats			MACH_TRATS		TRATS			3928
-starcraft		MACH_STARCRAFT		STARCRAFT		3929
-qseven_tegra2		MACH_QSEVEN_TEGRA2	QSEVEN_TEGRA2		3930
-lichee_sun4i_devbd	MACH_LICHEE_SUN4I_DEVBD	LICHEE_SUN4I_DEVBD	3931
-movenow			MACH_MOVENOW		MOVENOW			3932
-golf_u			MACH_GOLF_U		GOLF_U			3933
-msm7627a_evb		MACH_MSM7627A_EVB	MSM7627A_EVB		3934
-rambo			MACH_RAMBO		RAMBO			3935
-golfu			MACH_GOLFU		GOLFU			3936
-mango310		MACH_MANGO310		MANGO310		3937
-dns343			MACH_DNS343		DNS343			3938
-var_som_om44		MACH_VAR_SOM_OM44	VAR_SOM_OM44		3939
-naon			MACH_NAON		NAON			3940
-vp4000			MACH_VP4000		VP4000			3941
-impcard			MACH_IMPCARD		IMPCARD			3942
-smoovcam		MACH_SMOOVCAM		SMOOVCAM		3943
-cobham3725		MACH_COBHAM3725		COBHAM3725		3944
-cobham3730		MACH_COBHAM3730		COBHAM3730		3945
-cobham3703		MACH_COBHAM3703		COBHAM3703		3946
-quetzal			MACH_QUETZAL		QUETZAL			3947
-apq8064_cdp		MACH_APQ8064_CDP	APQ8064_CDP		3948
-apq8064_mtp		MACH_APQ8064_MTP	APQ8064_MTP		3949
-apq8064_fluid		MACH_APQ8064_FLUID	APQ8064_FLUID		3950
-apq8064_liquid		MACH_APQ8064_LIQUID	APQ8064_LIQUID		3951
-mango210		MACH_MANGO210		MANGO210		3952
-mango100		MACH_MANGO100		MANGO100		3953
-mango24			MACH_MANGO24		MANGO24			3954
-mango64			MACH_MANGO64		MANGO64			3955
-nsa320			MACH_NSA320		NSA320			3956
-elv_ccu2		MACH_ELV_CCU2		ELV_CCU2		3957
-triton_x00		MACH_TRITON_X00		TRITON_X00		3958
-triton_1500_2000	MACH_TRITON_1500_2000	TRITON_1500_2000	3959
-pogoplugv4		MACH_POGOPLUGV4		POGOPLUGV4		3960
-venus_cl		MACH_VENUS_CL		VENUS_CL		3961
-vulcano_g20		MACH_VULCANO_G20	VULCANO_G20		3962
-sgs_i9100		MACH_SGS_I9100		SGS_I9100		3963
-stsv2			MACH_STSV2		STSV2			3964
-csb1724			MACH_CSB1724		CSB1724			3965
-omapl138_lcdk		MACH_OMAPL138_LCDK	OMAPL138_LCDK		3966
-pvd_mx25		MACH_PVD_MX25		PVD_MX25		3968
-meson6_skt		MACH_MESON6_SKT		MESON6_SKT		3969
-meson6_ref		MACH_MESON6_REF		MESON6_REF		3970
-pxm			MACH_PXM		PXM			3971
-pogoplugv3		MACH_POGOPLUGV3		POGOPLUGV3		3973
-mlp89626		MACH_MLP89626		MLP89626		3974
-iomegahmndce		MACH_IOMEGAHMNDCE	IOMEGAHMNDCE		3975
-pogoplugv3pci		MACH_POGOPLUGV3PCI	POGOPLUGV3PCI		3976
-bntv250			MACH_BNTV250		BNTV250			3977
-mx53_qseven		MACH_MX53_QSEVEN	MX53_QSEVEN		3978
-gtl_it1100		MACH_GTL_IT1100		GTL_IT1100		3979
-mx6q_sabresd		MACH_MX6Q_SABRESD	MX6Q_SABRESD		3980
 mt4			MACH_MT4		MT4			3981
-jumbo_d			MACH_JUMBO_D		JUMBO_D			3982
-jumbo_i			MACH_JUMBO_I		JUMBO_I			3983
-fs20_dmp		MACH_FS20_DMP		FS20_DMP		3984
-dns320			MACH_DNS320		DNS320			3985
-mx28bacos		MACH_MX28BACOS		MX28BACOS		3986
-tl80			MACH_TL80		TL80			3987
-polatis_nic_1001	MACH_POLATIS_NIC_1001	POLATIS_NIC_1001	3988
-tely			MACH_TELY		TELY			3989
 u8520			MACH_U8520		U8520			3990
-manta			MACH_MANTA		MANTA			3991
-mpq8064_cdp		MACH_MPQ8064_CDP	MPQ8064_CDP		3993
-mpq8064_dtv		MACH_MPQ8064_DTV	MPQ8064_DTV		3995
-dm368som		MACH_DM368SOM		DM368SOM		3996
-gprisb2			MACH_GPRISB2		GPRISB2			3997
-chammid			MACH_CHAMMID		CHAMMID			3998
-seoul2			MACH_SEOUL2		SEOUL2			3999
-omap4_nooktablet	MACH_OMAP4_NOOKTABLET	OMAP4_NOOKTABLET	4000
-aalto			MACH_AALTO		AALTO			4001
-metro			MACH_METRO		METRO			4002
-cydm3730		MACH_CYDM3730		CYDM3730		4003
-tqma53			MACH_TQMA53		TQMA53			4004
-msm7627a_qrd3		MACH_MSM7627A_QRD3	MSM7627A_QRD3		4005
-mx28_canby		MACH_MX28_CANBY		MX28_CANBY		4006
-tiger			MACH_TIGER		TIGER			4007
-pcats_9307_type_a	MACH_PCATS_9307_TYPE_A	PCATS_9307_TYPE_A	4008
-pcats_9307_type_o	MACH_PCATS_9307_TYPE_O	PCATS_9307_TYPE_O	4009
-pcats_9307_type_r	MACH_PCATS_9307_TYPE_R	PCATS_9307_TYPE_R	4010
-streamplug		MACH_STREAMPLUG		STREAMPLUG		4011
-icechicken_dev		MACH_ICECHICKEN_DEV	ICECHICKEN_DEV		4012
-hedgehog		MACH_HEDGEHOG		HEDGEHOG		4013
-yusend_obc		MACH_YUSEND_OBC		YUSEND_OBC		4014
-imxninja		MACH_IMXNINJA		IMXNINJA		4015
-omap4_jarod		MACH_OMAP4_JAROD	OMAP4_JAROD		4016
-eco5_pk			MACH_ECO5_PK		ECO5_PK			4017
-qj2440			MACH_QJ2440		QJ2440			4018
-mx6q_mercury		MACH_MX6Q_MERCURY	MX6Q_MERCURY		4019
-cm6810			MACH_CM6810		CM6810			4020
-omap4_torpedo		MACH_OMAP4_TORPEDO	OMAP4_TORPEDO		4021
-nsa310			MACH_NSA310		NSA310			4022
-tmx536			MACH_TMX536		TMX536			4023
-ktt20			MACH_KTT20		KTT20			4024
-dragonix		MACH_DRAGONIX		DRAGONIX		4025
-lungching		MACH_LUNGCHING		LUNGCHING		4026
-bulogics		MACH_BULOGICS		BULOGICS		4027
-mx535_sx		MACH_MX535_SX		MX535_SX		4028
-ngui3250		MACH_NGUI3250		NGUI3250		4029
-salutec_dac		MACH_SALUTEC_DAC	SALUTEC_DAC		4030
-loco			MACH_LOCO		LOCO			4031
-ctera_plug_usi		MACH_CTERA_PLUG_USI	CTERA_PLUG_USI		4032
-scepter			MACH_SCEPTER		SCEPTER			4033
-sga			MACH_SGA		SGA			4034
-p_81_j5			MACH_P_81_J5		P_81_J5			4035
-p_81_o4			MACH_P_81_O4		P_81_O4			4036
-msm8625_surf		MACH_MSM8625_SURF	MSM8625_SURF		4037
-carallon_shark		MACH_CARALLON_SHARK	CARALLON_SHARK		4038
-ordog			MACH_ORDOG		ORDOG			4040
-puente_io		MACH_PUENTE_IO		PUENTE_IO		4041
-msm8625_evb		MACH_MSM8625_EVB	MSM8625_EVB		4042
-ev_am1707		MACH_EV_AM1707		EV_AM1707		4043
-ev_am1707e2		MACH_EV_AM1707E2	EV_AM1707E2		4044
-ev_am3517e2		MACH_EV_AM3517E2	EV_AM3517E2		4045
-calabria		MACH_CALABRIA		CALABRIA		4046
-ev_imx287		MACH_EV_IMX287		EV_IMX287		4047
-erau			MACH_ERAU		ERAU			4048
-sichuan			MACH_SICHUAN		SICHUAN			4049
-davinci_da850		MACH_DAVINCI_DA850	DAVINCI_DA850		4051
-omap138_trunarc		MACH_OMAP138_TRUNARC	OMAP138_TRUNARC		4052
-bcm4761			MACH_BCM4761		BCM4761			4053
-picasso_e2		MACH_PICASSO_E2		PICASSO_E2		4054
-picasso_mf		MACH_PICASSO_MF		PICASSO_MF		4055
-miro			MACH_MIRO		MIRO			4056
-at91sam9g20ewon3	MACH_AT91SAM9G20EWON3	AT91SAM9G20EWON3	4057
-yoyo			MACH_YOYO		YOYO			4058
-windjkl			MACH_WINDJKL		WINDJKL			4059
-monarudo		MACH_MONARUDO		MONARUDO		4060
-batan			MACH_BATAN		BATAN			4061
-tadao			MACH_TADAO		TADAO			4062
-baso			MACH_BASO		BASO			4063
-mahon			MACH_MAHON		MAHON			4064
-villec2			MACH_VILLEC2		VILLEC2			4065
-asi1230			MACH_ASI1230		ASI1230			4066
-alaska			MACH_ALASKA		ALASKA			4067
-swarco_shdsl2		MACH_SWARCO_SHDSL2	SWARCO_SHDSL2		4068
-oxrtu			MACH_OXRTU		OXRTU			4069
-omap5_panda		MACH_OMAP5_PANDA	OMAP5_PANDA		4070
-c8000			MACH_C8000		C8000			4072
-bje_display3_5		MACH_BJE_DISPLAY3_5	BJE_DISPLAY3_5		4073
-picomod7		MACH_PICOMOD7		PICOMOD7		4074
-picocom5		MACH_PICOCOM5		PICOCOM5		4075
-qblissa8		MACH_QBLISSA8		QBLISSA8		4076
-armstonea8		MACH_ARMSTONEA8		ARMSTONEA8		4077
-netdcu14		MACH_NETDCU14		NETDCU14		4078
-at91sam9x5_epiphan	MACH_AT91SAM9X5_EPIPHAN	AT91SAM9X5_EPIPHAN	4079
-p2u			MACH_P2U		P2U			4080
-doris			MACH_DORIS		DORIS			4081
-j49			MACH_J49		J49			4082
-vdss2e			MACH_VDSS2E		VDSS2E			4083
-vc300			MACH_VC300		VC300			4084
-ns115_pad_test		MACH_NS115_PAD_TEST	NS115_PAD_TEST		4085
-ns115_pad_ref		MACH_NS115_PAD_REF	NS115_PAD_REF		4086
-ns115_phone_test	MACH_NS115_PHONE_TEST	NS115_PHONE_TEST	4087
-ns115_phone_ref		MACH_NS115_PHONE_REF	NS115_PHONE_REF		4088
-golfc			MACH_GOLFC		GOLFC			4089
-xerox_olympus		MACH_XEROX_OLYMPUS	XEROX_OLYMPUS		4090
-mx6sl_arm2		MACH_MX6SL_ARM2		MX6SL_ARM2		4091
-csb1701_csb1726		MACH_CSB1701_CSB1726	CSB1701_CSB1726		4092
-at91sam9xeek		MACH_AT91SAM9XEEK	AT91SAM9XEEK		4093
-ebv210			MACH_EBV210		EBV210			4094
-msm7627a_qrd7		MACH_MSM7627A_QRD7	MSM7627A_QRD7		4095
-svthin			MACH_SVTHIN		SVTHIN			4096
-duovero			MACH_DUOVERO		DUOVERO			4097
 chupacabra		MACH_CHUPACABRA		CHUPACABRA		4098
 scorpion		MACH_SCORPION		SCORPION		4099
 davinci_he_hmi10	MACH_DAVINCI_HE_HMI10	DAVINCI_HE_HMI10	4100
@@ -1157,7 +580,6 @@ tam335x			MACH_TAM335X		TAM335X			4116
 grouper			MACH_GROUPER		GROUPER			4117
 mpcsa21_9g20		MACH_MPCSA21_9G20	MPCSA21_9G20		4118
 m6u_cpu			MACH_M6U_CPU		M6U_CPU			4119
-davinci_dp10		MACH_DAVINCI_DP10	DAVINCI_DP10		4120
 ginkgo			MACH_GINKGO		GINKGO			4121
 cgt_qmx6		MACH_CGT_QMX6		CGT_QMX6		4122
 profpga			MACH_PROFPGA		PROFPGA			4123
@@ -1204,3 +626,384 @@ baileys			MACH_BAILEYS		BAILEYS			4169
 familybox		MACH_FAMILYBOX		FAMILYBOX		4170
 ensemble_mx35		MACH_ENSEMBLE_MX35	ENSEMBLE_MX35		4171
 sc_sps_1		MACH_SC_SPS_1		SC_SPS_1		4172
+ucsimply_sam9260	MACH_UCSIMPLY_SAM9260	UCSIMPLY_SAM9260	4173
+unicorn			MACH_UNICORN		UNICORN			4174
+m9g45a			MACH_M9G45A		M9G45A			4175
+mtwebif			MACH_MTWEBIF		MTWEBIF			4176
+playstone		MACH_PLAYSTONE		PLAYSTONE		4177
+chelsea			MACH_CHELSEA		CHELSEA			4178
+bayern			MACH_BAYERN		BAYERN			4179
+mitwo			MACH_MITWO		MITWO			4180
+mx25_noah		MACH_MX25_NOAH		MX25_NOAH		4181
+stm_b2020		MACH_STM_B2020		STM_B2020		4182
+annax_src		MACH_ANNAX_SRC		ANNAX_SRC		4183
+ionics_stratus		MACH_IONICS_STRATUS	IONICS_STRATUS		4184
+hugo			MACH_HUGO		HUGO			4185
+em300			MACH_EM300		EM300			4186
+mmp3_qseven		MACH_MMP3_QSEVEN	MMP3_QSEVEN		4187
+bosphorus2		MACH_BOSPHORUS2		BOSPHORUS2		4188
+tt2200			MACH_TT2200		TT2200			4189
+ocelot3			MACH_OCELOT3		OCELOT3			4190
+tek_cobra		MACH_TEK_COBRA		TEK_COBRA		4191
+protou			MACH_PROTOU		PROTOU			4192
+msm8625_evt		MACH_MSM8625_EVT	MSM8625_EVT		4193
+mx53_sellwood		MACH_MX53_SELLWOOD	MX53_SELLWOOD		4194
+somiq_am35		MACH_SOMIQ_AM35		SOMIQ_AM35		4195
+somiq_am37		MACH_SOMIQ_AM37		SOMIQ_AM37		4196
+k2_plc_cl		MACH_K2_PLC_CL		K2_PLC_CL		4197
+tc2			MACH_TC2		TC2			4198
+dulex_j			MACH_DULEX_J		DULEX_J			4199
+stm_b2044		MACH_STM_B2044		STM_B2044		4200
+deluxe_j		MACH_DELUXE_J		DELUXE_J		4201
+mango2443		MACH_MANGO2443		MANGO2443		4202
+cp2dcg			MACH_CP2DCG		CP2DCG			4203
+cp2dtg			MACH_CP2DTG		CP2DTG			4204
+cp2dug			MACH_CP2DUG		CP2DUG			4205
+var_som_am33		MACH_VAR_SOM_AM33	VAR_SOM_AM33		4206
+pepper			MACH_PEPPER		PEPPER			4207
+mango2450		MACH_MANGO2450		MANGO2450		4208
+valente_wx_c9		MACH_VALENTE_WX_C9	VALENTE_WX_C9		4209
+minitv			MACH_MINITV		MINITV			4210
+u8540			MACH_U8540		U8540			4211
+iv_atlas_i_z7e		MACH_IV_ATLAS_I_Z7E	IV_ATLAS_I_Z7E		4212
+mach_type_sky		MACH_MACH_TYPE_SKY	MACH_TYPE_SKY		4214
+bluesky			MACH_BLUESKY		BLUESKY			4215
+ngrouter		MACH_NGROUTER		NGROUTER		4216
+mx53_denetim		MACH_MX53_DENETIM	MX53_DENETIM		4217
+opal			MACH_OPAL		OPAL			4218
+gnet_us3gref		MACH_GNET_US3GREF	GNET_US3GREF		4219
+gnet_nc3g		MACH_GNET_NC3G		GNET_NC3G		4220
+gnet_ge3g		MACH_GNET_GE3G		GNET_GE3G		4221
+adp2			MACH_ADP2		ADP2			4222
+tqma28			MACH_TQMA28		TQMA28			4223
+kacom3			MACH_KACOM3		KACOM3			4224
+rrhdemo			MACH_RRHDEMO		RRHDEMO			4225
+protodug		MACH_PROTODUG		PROTODUG		4226
+lago			MACH_LAGO		LAGO			4227
+ktt30			MACH_KTT30		KTT30			4228
+ts43xx			MACH_TS43XX		TS43XX			4229
+mx6q_denso		MACH_MX6Q_DENSO		MX6Q_DENSO		4230
+comsat_gsmumts8		MACH_COMSAT_GSMUMTS8	COMSAT_GSMUMTS8		4231
+dreamx			MACH_DREAMX		DREAMX			4232
+thunderstonem		MACH_THUNDERSTONEM	THUNDERSTONEM		4233
+yoyopad			MACH_YOYOPAD		YOYOPAD			4234
+yoyopatient		MACH_YOYOPATIENT	YOYOPATIENT		4235
+a10l			MACH_A10L		A10L			4236
+mq60			MACH_MQ60		MQ60			4237
+linkstation_lsql	MACH_LINKSTATION_LSQL	LINKSTATION_LSQL	4238
+am3703gateway		MACH_AM3703GATEWAY	AM3703GATEWAY		4239
+accipiter		MACH_ACCIPITER		ACCIPITER		4240
+magnidug		MACH_MAGNIDUG		MAGNIDUG		4242
+hydra			MACH_HYDRA		HYDRA			4243
+sun3i			MACH_SUN3I		SUN3I			4244
+stm_b2078		MACH_STM_B2078		STM_B2078		4245
+at91sam9263deskv2	MACH_AT91SAM9263DESKV2	AT91SAM9263DESKV2	4246
+deluxe_r		MACH_DELUXE_R		DELUXE_R		4247
+p_98_v			MACH_P_98_V		P_98_V			4248
+p_98_c			MACH_P_98_C		P_98_C			4249
+davinci_am18xx_omn	MACH_DAVINCI_AM18XX_OMN	DAVINCI_AM18XX_OMN	4250
+socfpga_cyclone5	MACH_SOCFPGA_CYCLONE5	SOCFPGA_CYCLONE5	4251
+cabatuin		MACH_CABATUIN		CABATUIN		4252
+yoyopad_ft		MACH_YOYOPAD_FT		YOYOPAD_FT		4253
+dan2400evb		MACH_DAN2400EVB		DAN2400EVB		4254
+dan3400evb		MACH_DAN3400EVB		DAN3400EVB		4255
+edm_sf_imx6		MACH_EDM_SF_IMX6	EDM_SF_IMX6		4256
+edm_cf_imx6		MACH_EDM_CF_IMX6	EDM_CF_IMX6		4257
+vpos3xx			MACH_VPOS3XX		VPOS3XX			4258
+vulcano_9x5		MACH_VULCANO_9X5	VULCANO_9X5		4259
+spmp8000		MACH_SPMP8000		SPMP8000		4260
+catalina		MACH_CATALINA		CATALINA		4261
+rd88f5181l_fe		MACH_RD88F5181L_FE	RD88F5181L_FE		4262
+mx535_mx		MACH_MX535_MX		MX535_MX		4263
+armadillo840		MACH_ARMADILLO840	ARMADILLO840		4264
+spc9000baseboard	MACH_SPC9000BASEBOARD	SPC9000BASEBOARD	4265
+iris			MACH_IRIS		IRIS			4266
+protodcg		MACH_PROTODCG		PROTODCG		4267
+palmtree		MACH_PALMTREE		PALMTREE		4268
+novena			MACH_NOVENA		NOVENA			4269
+ma_um			MACH_MA_UM		MA_UM			4270
+ma_am			MACH_MA_AM		MA_AM			4271
+ems348			MACH_EMS348		EMS348			4272
+cm_fx6			MACH_CM_FX6		CM_FX6			4273
+arndale			MACH_ARNDALE		ARNDALE			4274
+q5xr5			MACH_Q5XR5		Q5XR5			4275
+willow			MACH_WILLOW		WILLOW			4276
+omap3621_odyv3		MACH_OMAP3621_ODYV3	OMAP3621_ODYV3		4277
+omapl138_presonus	MACH_OMAPL138_PRESONUS	OMAPL138_PRESONUS	4278
+dvf99			MACH_DVF99		DVF99			4279
+impression_j		MACH_IMPRESSION_J	IMPRESSION_J		4280
+qblissa9		MACH_QBLISSA9		QBLISSA9		4281
+robin_heliview10	MACH_ROBIN_HELIVIEW10	ROBIN_HELIVIEW10	4282
+sun7i			MACH_SUN7I		SUN7I			4283
+mx6q_hdmidongle		MACH_MX6Q_HDMIDONGLE	MX6Q_HDMIDONGLE		4284
+mx6_sid2		MACH_MX6_SID2		MX6_SID2		4285
+helios_v3		MACH_HELIOS_V3		HELIOS_V3		4286
+helios_v4		MACH_HELIOS_V4		HELIOS_V4		4287
+q7_imx6			MACH_Q7_IMX6		Q7_IMX6			4288
+odroidx			MACH_ODROIDX		ODROIDX			4289
+robpro			MACH_ROBPRO		ROBPRO			4290
+research59if_mk1	MACH_RESEARCH59IF_MK1	RESEARCH59IF_MK1	4291
+bobsleigh		MACH_BOBSLEIGH		BOBSLEIGH		4292
+dcshgwt3		MACH_DCSHGWT3		DCSHGWT3		4293
+gld1018			MACH_GLD1018		GLD1018			4294
+ev10			MACH_EV10		EV10			4295
+nitrogen6x		MACH_NITROGEN6X		NITROGEN6X		4296
+p_107_bb		MACH_P_107_BB		P_107_BB		4297
+evita_utl		MACH_EVITA_UTL		EVITA_UTL		4298
+falconwing		MACH_FALCONWING		FALCONWING		4299
+dct3			MACH_DCT3		DCT3			4300
+cpx2e_cell		MACH_CPX2E_CELL		CPX2E_CELL		4301
+amiro			MACH_AMIRO		AMIRO			4302
+mx6q_brassboard		MACH_MX6Q_BRASSBOARD	MX6Q_BRASSBOARD		4303
+dalmore			MACH_DALMORE		DALMORE			4304
+omap3_portal7cp		MACH_OMAP3_PORTAL7CP	OMAP3_PORTAL7CP		4305
+tegra_pluto		MACH_TEGRA_PLUTO	TEGRA_PLUTO		4306
+mx6sl_evk		MACH_MX6SL_EVK		MX6SL_EVK		4307
+m7			MACH_M7			M7			4308
+pxm2			MACH_PXM2		PXM2			4309
+haba_knx_lite		MACH_HABA_KNX_LITE	HABA_KNX_LITE		4310
+tai			MACH_TAI		TAI			4311
+prototd			MACH_PROTOTD		PROTOTD			4312
+dst_tonto		MACH_DST_TONTO		DST_TONTO		4313
+draco			MACH_DRACO		DRACO			4314
+dxr2			MACH_DXR2		DXR2			4315
+rut			MACH_RUT		RUT			4316
+am180x_wsc		MACH_AM180X_WSC		AM180X_WSC		4317
+deluxe_u		MACH_DELUXE_U		DELUXE_U		4318
+deluxe_ul		MACH_DELUXE_UL		DELUXE_UL		4319
+at91sam9260medths	MACH_AT91SAM9260MEDTHS	AT91SAM9260MEDTHS	4320
+matrix516		MACH_MATRIX516		MATRIX516		4321
+vid401x			MACH_VID401X		VID401X			4322
+helios_v5		MACH_HELIOS_V5		HELIOS_V5		4323
+playpaq2		MACH_PLAYPAQ2		PLAYPAQ2		4324
+igam			MACH_IGAM		IGAM			4325
+amico_i			MACH_AMICO_I		AMICO_I			4326
+amico_e			MACH_AMICO_E		AMICO_E			4327
+sentient_mm3_ck		MACH_SENTIENT_MM3_CK	SENTIENT_MM3_CK		4328
+smx6			MACH_SMX6		SMX6			4329
+pango			MACH_PANGO		PANGO			4330
+ns115_stick		MACH_NS115_STICK	NS115_STICK		4331
+bctrm3			MACH_BCTRM3		BCTRM3			4332
+doctorws		MACH_DOCTORWS		DOCTORWS		4333
+m2601			MACH_M2601		M2601			4334
+vgg1111			MACH_VGG1111		VGG1111			4337
+countach		MACH_COUNTACH		COUNTACH		4338
+visstrim_sm20		MACH_VISSTRIM_SM20	VISSTRIM_SM20		4339
+a639			MACH_A639		A639			4340
+spacemonkey		MACH_SPACEMONKEY	SPACEMONKEY		4341
+zpdu_stamp		MACH_ZPDU_STAMP		ZPDU_STAMP		4342
+htc_g7_clone		MACH_HTC_G7_CLONE	HTC_G7_CLONE		4343
+ft2080_corvus		MACH_FT2080_CORVUS	FT2080_CORVUS		4344
+fisland			MACH_FISLAND		FISLAND			4345
+zpdu			MACH_ZPDU		ZPDU			4346
+urt			MACH_URT		URT			4347
+conti_ovip		MACH_CONTI_OVIP		CONTI_OVIP		4348
+omapl138_nagra		MACH_OMAPL138_NAGRA	OMAPL138_NAGRA		4349
+da850_at3kp1		MACH_DA850_AT3KP1	DA850_AT3KP1		4350
+da850_at3kp2		MACH_DA850_AT3KP2	DA850_AT3KP2		4351
+surma			MACH_SURMA		SURMA			4352
+stm_b2092		MACH_STM_B2092		STM_B2092		4353
+mx535_ycr		MACH_MX535_YCR		MX535_YCR		4354
+m7_wl			MACH_M7_WL		M7_WL			4355
+m7_u			MACH_M7_U		M7_U			4356
+omap3_stndt_evm		MACH_OMAP3_STNDT_EVM	OMAP3_STNDT_EVM		4357
+m7_wlv			MACH_M7_WLV		M7_WLV			4358
+xam3517			MACH_XAM3517		XAM3517			4359
+a220			MACH_A220		A220			4360
+aclima_odie		MACH_ACLIMA_ODIE	ACLIMA_ODIE		4361
+vibble			MACH_VIBBLE		VIBBLE			4362
+k2_u			MACH_K2_U		K2_U			4363
+mx53_egf		MACH_MX53_EGF		MX53_EGF		4364
+novpek_imx53		MACH_NOVPEK_IMX53	NOVPEK_IMX53		4365
+novpek_imx6x		MACH_NOVPEK_IMX6X	NOVPEK_IMX6X		4366
+mx25_smartbox		MACH_MX25_SMARTBOX	MX25_SMARTBOX		4367
+eicg6410		MACH_EICG6410		EICG6410		4368
+picasso_e3		MACH_PICASSO_E3		PICASSO_E3		4369
+motonavigator		MACH_MOTONAVIGATOR	MOTONAVIGATOR		4370
+varioconnect2		MACH_VARIOCONNECT2	VARIOCONNECT2		4371
+deluxe_tw		MACH_DELUXE_TW		DELUXE_TW		4372
+kore3			MACH_KORE3		KORE3			4374
+mx6s_drs		MACH_MX6S_DRS		MX6S_DRS		4375
+cmimx6			MACH_CMIMX6		CMIMX6			4376
+roth			MACH_ROTH		ROTH			4377
+eq4ux			MACH_EQ4UX		EQ4UX			4378
+x1plus			MACH_X1PLUS		X1PLUS			4379
+modimx27		MACH_MODIMX27		MODIMX27		4380
+videon_hduac		MACH_VIDEON_HDUAC	VIDEON_HDUAC		4381
+blackbird		MACH_BLACKBIRD		BLACKBIRD		4382
+runmaster		MACH_RUNMASTER		RUNMASTER		4383
+ceres			MACH_CERES		CERES			4384
+nad435			MACH_NAD435		NAD435			4385
+ns115_proto_type	MACH_NS115_PROTO_TYPE	NS115_PROTO_TYPE	4386
+fs20_vcc		MACH_FS20_VCC		FS20_VCC		4387
+meson6tv_skt		MACH_MESON6TV_SKT	MESON6TV_SKT		4389
+keystone		MACH_KEYSTONE		KEYSTONE		4390
+pcm052			MACH_PCM052		PCM052			4391
+qrd_skud_prime		MACH_QRD_SKUD_PRIME	QRD_SKUD_PRIME		4393
+guf_santaro		MACH_GUF_SANTARO	GUF_SANTARO		4395
+sheepshead		MACH_SHEEPSHEAD		SHEEPSHEAD		4396
+mx6_iwg15m_mxm		MACH_MX6_IWG15M_MXM	MX6_IWG15M_MXM		4397
+mx6_iwg15m_q7		MACH_MX6_IWG15M_Q7	MX6_IWG15M_Q7		4398
+at91sam9263if8mic	MACH_AT91SAM9263IF8MIC	AT91SAM9263IF8MIC	4399
+marcopolo		MACH_MARCOPOLO		MARCOPOLO		4401
+mx535_sdcr		MACH_MX535_SDCR		MX535_SDCR		4402
+mx53_csb2733		MACH_MX53_CSB2733	MX53_CSB2733		4403
+diva			MACH_DIVA		DIVA			4404
+ncr_7744		MACH_NCR_7744		NCR_7744		4405
+macallan		MACH_MACALLAN		MACALLAN		4406
+wnr3500			MACH_WNR3500		WNR3500			4407
+pgavrf			MACH_PGAVRF		PGAVRF			4408
+helios_v6		MACH_HELIOS_V6		HELIOS_V6		4409
+lcct			MACH_LCCT		LCCT			4410
+csndug			MACH_CSNDUG		CSNDUG			4411
+wandboard_imx6		MACH_WANDBOARD_IMX6	WANDBOARD_IMX6		4412
+omap4_jet		MACH_OMAP4_JET		OMAP4_JET		4413
+tegra_roth		MACH_TEGRA_ROTH		TEGRA_ROTH		4414
+m7dcg			MACH_M7DCG		M7DCG			4415
+m7dug			MACH_M7DUG		M7DUG			4416
+m7dtg			MACH_M7DTG		M7DTG			4417
+ap42x			MACH_AP42X		AP42X			4418
+var_som_mx6		MACH_VAR_SOM_MX6	VAR_SOM_MX6		4419
+pdlu			MACH_PDLU		PDLU			4420
+hydrogen		MACH_HYDROGEN		HYDROGEN		4421
+npa211e			MACH_NPA211E		NPA211E			4422
+arcadia			MACH_ARCADIA		ARCADIA			4423
+arcadia_l		MACH_ARCADIA_L		ARCADIA_L		4424
+msm8930dt		MACH_MSM8930DT		MSM8930DT		4425
+ktam3874		MACH_KTAM3874		KTAM3874		4426
+cec4			MACH_CEC4		CEC4			4427
+ape6evm			MACH_APE6EVM		APE6EVM			4428
+tx6			MACH_TX6		TX6			4429
+cfa10037		MACH_CFA10037		CFA10037		4431
+ezp1000			MACH_EZP1000		EZP1000			4433
+wgr826v			MACH_WGR826V		WGR826V			4434
+exuma			MACH_EXUMA		EXUMA			4435
+fregate			MACH_FREGATE		FREGATE			4436
+osirisimx508		MACH_OSIRISIMX508	OSIRISIMX508		4437
+st_exigo		MACH_ST_EXIGO		ST_EXIGO		4438
+pismo			MACH_PISMO		PISMO			4439
+atc7			MACH_ATC7		ATC7			4440
+nspireclp		MACH_NSPIRECLP		NSPIRECLP		4441
+nspiretp		MACH_NSPIRETP		NSPIRETP		4442
+nspirecx		MACH_NSPIRECX		NSPIRECX		4443
+maya			MACH_MAYA		MAYA			4444
+wecct			MACH_WECCT		WECCT			4445
+m2s			MACH_M2S		M2S			4446
+msm8625q_evbd		MACH_MSM8625Q_EVBD	MSM8625Q_EVBD		4447
+tiny210			MACH_TINY210		TINY210			4448
+g3			MACH_G3			G3			4449
+hurricane		MACH_HURRICANE		HURRICANE		4450
+mx6_pod			MACH_MX6_POD		MX6_POD			4451
+elondcn			MACH_ELONDCN		ELONDCN			4452
+cwmx535			MACH_CWMX535		CWMX535			4453
+m7_wlj			MACH_M7_WLJ		M7_WLJ			4454
+qsp_arm			MACH_QSP_ARM		QSP_ARM			4455
+msm8625q_skud		MACH_MSM8625Q_SKUD	MSM8625Q_SKUD		4456
+htcmondrian		MACH_HTCMONDRIAN	HTCMONDRIAN		4457
+watson_ead		MACH_WATSON_EAD		WATSON_EAD		4458
+mitwoa			MACH_MITWOA		MITWOA			4459
+omap3_wolverine		MACH_OMAP3_WOLVERINE	OMAP3_WOLVERINE		4460
+mapletree		MACH_MAPLETREE		MAPLETREE		4461
+msm8625_fih_sae		MACH_MSM8625_FIH_SAE	MSM8625_FIH_SAE		4462
+epc35			MACH_EPC35		EPC35			4463
+smartrtu		MACH_SMARTRTU		SMARTRTU		4464
+rcm101			MACH_RCM101		RCM101			4465
+amx_imx53_mxx		MACH_AMX_IMX53_MXX	AMX_IMX53_MXX		4466
+acer_a12		MACH_ACER_A12		ACER_A12		4470
+sbc6x			MACH_SBC6X		SBC6X			4471
+u2			MACH_U2			U2			4472
+smdk4270		MACH_SMDK4270		SMDK4270		4473
+priscillag		MACH_PRISCILLAG		PRISCILLAG		4474
+priscillac		MACH_PRISCILLAC		PRISCILLAC		4475
+priscilla		MACH_PRISCILLA		PRISCILLA		4476
+innova_shpu_v2		MACH_INNOVA_SHPU_V2	INNOVA_SHPU_V2		4477
+mach_type_dep2410	MACH_MACH_TYPE_DEP2410	MACH_TYPE_DEP2410	4479
+bctre3			MACH_BCTRE3		BCTRE3			4480
+omap_m100		MACH_OMAP_M100		OMAP_M100		4481
+flo			MACH_FLO		FLO			4482
+nanobone		MACH_NANOBONE		NANOBONE		4483
+stm_b2105		MACH_STM_B2105		STM_B2105		4484
+omap4_bsc_bap_v3	MACH_OMAP4_BSC_BAP_V3	OMAP4_BSC_BAP_V3	4485
+ss1pam			MACH_SS1PAM		SS1PAM			4486
+primominiu		MACH_PRIMOMINIU		PRIMOMINIU		4488
+mrt_35hd_dualnas_e	MACH_MRT_35HD_DUALNAS_E	MRT_35HD_DUALNAS_E	4489
+kiwi			MACH_KIWI		KIWI			4490
+hw90496			MACH_HW90496		HW90496			4491
+mep2440			MACH_MEP2440		MEP2440			4492
+colibri_t30		MACH_COLIBRI_T30	COLIBRI_T30		4493
+cwv1			MACH_CWV1		CWV1			4494
+nsa325			MACH_NSA325		NSA325			4495
+dpxmtc			MACH_DPXMTC		DPXMTC			4497
+tt_stuttgart		MACH_TT_STUTTGART	TT_STUTTGART		4498
+miranda_apcii		MACH_MIRANDA_APCII	MIRANDA_APCII		4499
+mx6q_moderox		MACH_MX6Q_MODEROX	MX6Q_MODEROX		4500
+mudskipper		MACH_MUDSKIPPER		MUDSKIPPER		4501
+urania			MACH_URANIA		URANIA			4502
+stm_b2112		MACH_STM_B2112		STM_B2112		4503
+mx6q_ats_phoenix	MACH_MX6Q_ATS_PHOENIX	MX6Q_ATS_PHOENIX	4505
+stm_b2116		MACH_STM_B2116		STM_B2116		4506
+mythology		MACH_MYTHOLOGY		MYTHOLOGY		4507
+fc360v1			MACH_FC360V1		FC360V1			4508
+gps_sensor		MACH_GPS_SENSOR		GPS_SENSOR		4509
+gazelle			MACH_GAZELLE		GAZELLE			4510
+mpq8064_dma		MACH_MPQ8064_DMA	MPQ8064_DMA		4511
+wems_asd01		MACH_WEMS_ASD01		WEMS_ASD01		4512
+apalis_t30		MACH_APALIS_T30		APALIS_T30		4513
+armstonea9		MACH_ARMSTONEA9		ARMSTONEA9		4515
+omap_blazetablet	MACH_OMAP_BLAZETABLET	OMAP_BLAZETABLET	4516
+ar6mxq			MACH_AR6MXQ		AR6MXQ			4517
+ar6mxs			MACH_AR6MXS		AR6MXS			4518
+gwventana		MACH_GWVENTANA		GWVENTANA		4520
+igep0033		MACH_IGEP0033		IGEP0033		4521
+h52c1_concerto		MACH_H52C1_CONCERTO	H52C1_CONCERTO		4524
+fcmbrd			MACH_FCMBRD		FCMBRD			4525
+pcaaxs1			MACH_PCAAXS1		PCAAXS1			4526
+ls_orca			MACH_LS_ORCA		LS_ORCA			4527
+pcm051lb		MACH_PCM051LB		PCM051LB		4528
+mx6s_lp507_gvci		MACH_MX6S_LP507_GVCI	MX6S_LP507_GVCI		4529
+dido			MACH_DIDO		DIDO			4530
+swarco_itc3_9g20	MACH_SWARCO_ITC3_9G20	SWARCO_ITC3_9G20	4531
+robo_roady		MACH_ROBO_ROADY		ROBO_ROADY		4532
+rskrza1			MACH_RSKRZA1		RSKRZA1			4533
+swarco_sid		MACH_SWARCO_SID		SWARCO_SID		4534
+mx6_iwg15s_sbc		MACH_MX6_IWG15S_SBC	MX6_IWG15S_SBC		4535
+mx6q_camaro		MACH_MX6Q_CAMARO	MX6Q_CAMARO		4536
+hb6mxs			MACH_HB6MXS		HB6MXS			4537
+lager			MACH_LAGER		LAGER			4538
+lp8x4x			MACH_LP8X4X		LP8X4X			4539
+tegratab7		MACH_TEGRATAB7		TEGRATAB7		4540
+andromeda		MACH_ANDROMEDA		ANDROMEDA		4541
+bootes			MACH_BOOTES		BOOTES			4542
+nethmi			MACH_NETHMI		NETHMI			4543
+tegratab		MACH_TEGRATAB		TEGRATAB		4544
+som5_evb		MACH_SOM5_EVB		SOM5_EVB		4545
+venaticorum		MACH_VENATICORUM	VENATICORUM		4546
+stm_b2110		MACH_STM_B2110		STM_B2110		4547
+elux_hathor		MACH_ELUX_HATHOR	ELUX_HATHOR		4548
+helios_v7		MACH_HELIOS_V7		HELIOS_V7		4549
+xc10v1			MACH_XC10V1		XC10V1			4550
+cp2u			MACH_CP2U		CP2U			4551
+iap_f			MACH_IAP_F		IAP_F			4552
+iap_g			MACH_IAP_G		IAP_G			4553
+aae			MACH_AAE		AAE			4554
+pegasus			MACH_PEGASUS		PEGASUS			4555
+cygnus			MACH_CYGNUS		CYGNUS			4556
+centaurus		MACH_CENTAURUS		CENTAURUS		4557
+msm8930_qrd8930		MACH_MSM8930_QRD8930	MSM8930_QRD8930		4558
+quby_tim		MACH_QUBY_TIM		QUBY_TIM		4559
+zedi3250a		MACH_ZEDI3250A		ZEDI3250A		4560
+grus			MACH_GRUS		GRUS			4561
+apollo3			MACH_APOLLO3		APOLLO3			4562
+cowon_r7		MACH_COWON_R7		COWON_R7		4563
+tonga3			MACH_TONGA3		TONGA3			4564
+p535			MACH_P535		P535			4565
+sa3874i			MACH_SA3874I		SA3874I			4566
+mx6_navico_com		MACH_MX6_NAVICO_COM	MX6_NAVICO_COM		4567
+proxmobil2		MACH_PROXMOBIL2		PROXMOBIL2		4568
+ubinux1			MACH_UBINUX1		UBINUX1			4569
+istos			MACH_ISTOS		ISTOS			4570
+benvolio4		MACH_BENVOLIO4		BENVOLIO4		4571
+eco5_bx2		MACH_ECO5_BX2		ECO5_BX2		4572
+eukrea_cpuimx28sd	MACH_EUKREA_CPUIMX28SD	EUKREA_CPUIMX28SD	4573
+domotab			MACH_DOMOTAB		DOMOTAB			4574
+pfla03			MACH_PFLA03		PFLA03			4575
diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
index e5fe4f9..a13a4a4 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -39,7 +39,6 @@ generic-y += shmbuf.h
 generic-y += sizes.h
 generic-y += socket.h
 generic-y += sockios.h
-generic-y += string.h
 generic-y += switch_to.h
 generic-y += swab.h
 generic-y += termbits.h
diff --git a/arch/arm64/include/asm/bitops.h b/arch/arm64/include/asm/bitops.h
index 5e69307..aa5b59d 100644
--- a/arch/arm64/include/asm/bitops.h
+++ b/arch/arm64/include/asm/bitops.h
@@ -32,6 +32,16 @@
 #error only <linux/bitops.h> can be included directly
 #endif
 
+/*
+ * Little endian assembly atomic bitops.
+ */
+extern void set_bit(int nr, volatile unsigned long *p);
+extern void clear_bit(int nr, volatile unsigned long *p);
+extern void change_bit(int nr, volatile unsigned long *p);
+extern int test_and_set_bit(int nr, volatile unsigned long *p);
+extern int test_and_clear_bit(int nr, volatile unsigned long *p);
+extern int test_and_change_bit(int nr, volatile unsigned long *p);
+
 #include <asm-generic/bitops/builtin-__ffs.h>
 #include <asm-generic/bitops/builtin-ffs.h>
 #include <asm-generic/bitops/builtin-__fls.h>
@@ -45,9 +55,13 @@
 #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/le.h>
-#include <asm-generic/bitops/ext2-atomic.h>
+
+/*
+ * 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)
 
 #endif /* __ASM_BITOPS_H */
diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h
index ef54125..cf27494 100644
--- a/arch/arm64/include/asm/cputype.h
+++ b/arch/arm64/include/asm/cputype.h
@@ -17,6 +17,7 @@
 #define __ASM_CPUTYPE_H
 
 #define ID_MIDR_EL1		"midr_el1"
+#define ID_MPIDR_EL1		"mpidr_el1"
 #define ID_CTR_EL0		"ctr_el0"
 
 #define ID_AA64PFR0_EL1		"id_aa64pfr0_el1"
@@ -25,12 +26,24 @@
 #define ID_AA64ISAR0_EL1	"id_aa64isar0_el1"
 #define ID_AA64MMFR0_EL1	"id_aa64mmfr0_el1"
 
+#define INVALID_HWID		ULONG_MAX
+
+#define MPIDR_HWID_BITMASK	0xff00ffffff
+
 #define read_cpuid(reg) ({						\
 	u64 __val;							\
 	asm("mrs	%0, " reg : "=r" (__val));			\
 	__val;								\
 })
 
+#define ARM_CPU_IMP_ARM		0x41
+
+#define ARM_CPU_PART_AEM_V8	0xD0F0
+#define ARM_CPU_PART_FOUNDATION	0xD000
+#define ARM_CPU_PART_CORTEX_A57	0xD070
+
+#ifndef __ASSEMBLY__
+
 /*
  * The CPU ID never changes at run time, so we might as well tell the
  * compiler that it's constant.  Use this function to read the CPU ID
@@ -41,9 +54,26 @@ static inline u32 __attribute_const__ read_cpuid_id(void)
 	return read_cpuid(ID_MIDR_EL1);
 }
 
+static inline u64 __attribute_const__ read_cpuid_mpidr(void)
+{
+	return read_cpuid(ID_MPIDR_EL1);
+}
+
+static inline unsigned int __attribute_const__ read_cpuid_implementor(void)
+{
+	return (read_cpuid_id() & 0xFF000000) >> 24;
+}
+
+static inline unsigned int __attribute_const__ read_cpuid_part_number(void)
+{
+	return (read_cpuid_id() & 0xFFF0);
+}
+
 static inline u32 __attribute_const__ read_cpuid_cachetype(void)
 {
 	return read_cpuid(ID_CTR_EL0);
 }
 
+#endif /* __ASSEMBLY__ */
+
 #endif
diff --git a/arch/arm64/include/asm/exception.h b/arch/arm64/include/asm/exception.h
index ac63519..0303705 100644
--- a/arch/arm64/include/asm/exception.h
+++ b/arch/arm64/include/asm/exception.h
@@ -19,5 +19,6 @@
 #define __ASM_EXCEPTION_H
 
 #define __exception	__attribute__((section(".exception.text")))
+#define __exception_irq_entry	__exception
 
 #endif	/* __ASM_EXCEPTION_H */
diff --git a/arch/arm64/include/asm/hardirq.h b/arch/arm64/include/asm/hardirq.h
index 5075463..990c051 100644
--- a/arch/arm64/include/asm/hardirq.h
+++ b/arch/arm64/include/asm/hardirq.h
@@ -49,4 +49,9 @@ static inline void ack_bad_irq(unsigned int irq)
 
 extern void handle_IRQ(unsigned int, struct pt_regs *);
 
+/*
+ * No arch-specific IRQ flags.
+ */
+#define set_irq_flags(irq, flags)
+
 #endif /* __ASM_HARDIRQ_H */
diff --git a/arch/arm64/include/asm/irq.h b/arch/arm64/include/asm/irq.h
index a4e1cad..0332fc0 100644
--- a/arch/arm64/include/asm/irq.h
+++ b/arch/arm64/include/asm/irq.h
@@ -4,5 +4,6 @@
 #include <asm-generic/irq.h>
 
 extern void (*handle_arch_irq)(struct pt_regs *);
+extern void set_handle_irq(void (*handle_irq)(struct pt_regs *));
 
 #endif
diff --git a/arch/arm64/include/asm/smp_plat.h b/arch/arm64/include/asm/smp_plat.h
new file mode 100644
index 0000000..ed43a0d
--- /dev/null
+++ b/arch/arm64/include/asm/smp_plat.h
@@ -0,0 +1,30 @@
+/*
+ * Definitions specific to SMP platforms.
+ *
+ * Copyright (C) 2013 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU 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 __ASM_SMP_PLAT_H
+#define __ASM_SMP_PLAT_H
+
+#include <asm/types.h>
+
+/*
+ * Logical CPU mapping.
+ */
+extern u64 __cpu_logical_map[NR_CPUS];
+#define cpu_logical_map(cpu)    __cpu_logical_map[cpu]
+
+#endif /* __ASM_SMP_PLAT_H */
diff --git a/arch/arm64/include/asm/string.h b/arch/arm64/include/asm/string.h
new file mode 100644
index 0000000..3ee8b30
--- /dev/null
+++ b/arch/arm64/include/asm/string.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2013 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU 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 __ASM_STRING_H
+#define __ASM_STRING_H
+
+#define __HAVE_ARCH_STRRCHR
+extern char *strrchr(const char *, int c);
+
+#define __HAVE_ARCH_STRCHR
+extern char *strchr(const char *, int c);
+
+#define __HAVE_ARCH_MEMCPY
+extern void *memcpy(void *, const void *, __kernel_size_t);
+
+#define __HAVE_ARCH_MEMMOVE
+extern void *memmove(void *, const void *, __kernel_size_t);
+
+#define __HAVE_ARCH_MEMCHR
+extern void *memchr(const void *, int, __kernel_size_t);
+
+#define __HAVE_ARCH_MEMSET
+extern void *memset(void *, int, __kernel_size_t);
+
+#endif
diff --git a/arch/arm64/kernel/arm64ksyms.c b/arch/arm64/kernel/arm64ksyms.c
index aa3e948..7df1aad 100644
--- a/arch/arm64/kernel/arm64ksyms.c
+++ b/arch/arm64/kernel/arm64ksyms.c
@@ -39,10 +39,21 @@ EXPORT_SYMBOL(__copy_from_user);
 EXPORT_SYMBOL(__copy_to_user);
 EXPORT_SYMBOL(__clear_user);
 
-	/* bitops */
-#ifdef CONFIG_SMP
-EXPORT_SYMBOL(__atomic_hash);
-#endif
-
 	/* physical memory */
 EXPORT_SYMBOL(memstart_addr);
+
+	/* string / mem functions */
+EXPORT_SYMBOL(strchr);
+EXPORT_SYMBOL(strrchr);
+EXPORT_SYMBOL(memset);
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(memmove);
+EXPORT_SYMBOL(memchr);
+
+	/* atomic bitops */
+EXPORT_SYMBOL(set_bit);
+EXPORT_SYMBOL(test_and_set_bit);
+EXPORT_SYMBOL(clear_bit);
+EXPORT_SYMBOL(test_and_clear_bit);
+EXPORT_SYMBOL(change_bit);
+EXPORT_SYMBOL(test_and_change_bit);
diff --git a/arch/arm64/kernel/early_printk.c b/arch/arm64/kernel/early_printk.c
index 7e320a2..ac974f4 100644
--- a/arch/arm64/kernel/early_printk.c
+++ b/arch/arm64/kernel/early_printk.c
@@ -24,6 +24,7 @@
 #include <linux/io.h>
 
 #include <linux/amba/serial.h>
+#include <linux/serial_reg.h>
 
 static void __iomem *early_base;
 static void (*printch)(char ch);
@@ -40,6 +41,37 @@ static void pl011_printch(char ch)
 		;
 }
 
+/*
+ * Semihosting-based debug console
+ */
+static void smh_printch(char ch)
+{
+	asm volatile("mov  x1, %0\n"
+		     "mov  x0, #3\n"
+		     "hlt  0xf000\n"
+		     : : "r" (&ch) : "x0", "x1", "memory");
+}
+
+/*
+ * 8250/16550 (8-bit aligned registers) single character TX.
+ */
+static void uart8250_8bit_printch(char ch)
+{
+	while (!(readb_relaxed(early_base + UART_LSR) & UART_LSR_THRE))
+		;
+	writeb_relaxed(ch, early_base + UART_TX);
+}
+
+/*
+ * 8250/16550 (32-bit aligned registers) single character TX.
+ */
+static void uart8250_32bit_printch(char ch)
+{
+	while (!(readl_relaxed(early_base + (UART_LSR << 2)) & UART_LSR_THRE))
+		;
+	writel_relaxed(ch, early_base + (UART_TX << 2));
+}
+
 struct earlycon_match {
 	const char *name;
 	void (*printch)(char ch);
@@ -47,6 +79,9 @@ struct earlycon_match {
 
 static const struct earlycon_match earlycon_match[] __initconst = {
 	{ .name = "pl011", .printch = pl011_printch, },
+	{ .name = "smh", .printch = smh_printch, },
+	{ .name = "uart8250-8bit", .printch = uart8250_8bit_printch, },
+	{ .name = "uart8250-32bit", .printch = uart8250_32bit_printch, },
 	{}
 };
 
diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
index 0a0a497..53dcae4 100644
--- a/arch/arm64/kernel/head.S
+++ b/arch/arm64/kernel/head.S
@@ -26,6 +26,7 @@
 #include <asm/assembler.h>
 #include <asm/ptrace.h>
 #include <asm/asm-offsets.h>
+#include <asm/cputype.h>
 #include <asm/memory.h>
 #include <asm/thread_info.h>
 #include <asm/pgtable-hwdef.h>
@@ -229,7 +230,8 @@ ENTRY(secondary_holding_pen)
 	bl	__calc_phys_offset		// x24=phys offset
 	bl	el2_setup			// Drop to EL1
 	mrs	x0, mpidr_el1
-	and	x0, x0, #15			// CPU number
+	ldr     x1, =MPIDR_HWID_BITMASK
+	and	x0, x0, x1
 	adr	x1, 1b
 	ldp	x2, x3, [x1]
 	sub	x1, x1, x2
diff --git a/arch/arm64/kernel/irq.c b/arch/arm64/kernel/irq.c
index 0373c66..ecb3354 100644
--- a/arch/arm64/kernel/irq.c
+++ b/arch/arm64/kernel/irq.c
@@ -25,7 +25,7 @@
 #include <linux/irq.h>
 #include <linux/smp.h>
 #include <linux/init.h>
-#include <linux/of_irq.h>
+#include <linux/irqchip.h>
 #include <linux/seq_file.h>
 #include <linux/ratelimit.h>
 
@@ -67,18 +67,17 @@ void handle_IRQ(unsigned int irq, struct pt_regs *regs)
 	set_irq_regs(old_regs);
 }
 
-/*
- * Interrupt controllers supported by the kernel.
- */
-static const struct of_device_id intctrl_of_match[] __initconst = {
-	/* IRQ controllers { .compatible, .data } info to go here */
-	{}
-};
+void __init set_handle_irq(void (*handle_irq)(struct pt_regs *))
+{
+	if (handle_arch_irq)
+		return;
+
+	handle_arch_irq = handle_irq;
+}
 
 void __init init_IRQ(void)
 {
-	of_irq_init(intctrl_of_match);
-
+	irqchip_init();
 	if (!handle_arch_irq)
 		panic("No interrupt controller found.");
 }
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index 113db86..6a9a532 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -32,6 +32,7 @@
 #include <linux/kexec.h>
 #include <linux/crash_dump.h>
 #include <linux/root_dev.h>
+#include <linux/clk-provider.h>
 #include <linux/cpu.h>
 #include <linux/interrupt.h>
 #include <linux/smp.h>
@@ -46,6 +47,7 @@
 #include <asm/cputable.h>
 #include <asm/sections.h>
 #include <asm/setup.h>
+#include <asm/smp_plat.h>
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
 #include <asm/traps.h>
@@ -240,6 +242,8 @@ static void __init request_standard_resources(void)
 	}
 }
 
+u64 __cpu_logical_map[NR_CPUS] = { [0 ... NR_CPUS-1] = INVALID_HWID };
+
 void __init setup_arch(char **cmdline_p)
 {
 	setup_processor();
@@ -264,6 +268,7 @@ void __init setup_arch(char **cmdline_p)
 
 	psci_init();
 
+	cpu_logical_map(0) = read_cpuid_mpidr() & MPIDR_HWID_BITMASK;
 #ifdef CONFIG_SMP
 	smp_init_cpus();
 #endif
@@ -277,6 +282,13 @@ void __init setup_arch(char **cmdline_p)
 #endif
 }
 
+static int __init arm64_of_clk_init(void)
+{
+	of_clk_init(NULL);
+	return 0;
+}
+arch_initcall(arm64_of_clk_init);
+
 static DEFINE_PER_CPU(struct cpu, cpu_data);
 
 static int __init topology_init(void)
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index bdd3459..d4dcc65 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -43,6 +43,7 @@
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
 #include <asm/processor.h>
+#include <asm/smp_plat.h>
 #include <asm/sections.h>
 #include <asm/tlbflush.h>
 #include <asm/ptrace.h>
@@ -53,7 +54,7 @@
  * where to place its SVC stack
  */
 struct secondary_data secondary_data;
-volatile unsigned long secondary_holding_pen_release = -1;
+volatile unsigned long secondary_holding_pen_release = INVALID_HWID;
 
 enum ipi_msg_type {
 	IPI_RESCHEDULE,
@@ -70,7 +71,7 @@ static DEFINE_RAW_SPINLOCK(boot_lock);
  * in coherency or not.  This is necessary for the hotplug code to work
  * reliably.
  */
-static void __cpuinit write_pen_release(int val)
+static void __cpuinit write_pen_release(u64 val)
 {
 	void *start = (void *)&secondary_holding_pen_release;
 	unsigned long size = sizeof(secondary_holding_pen_release);
@@ -96,7 +97,7 @@ static int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
 	/*
 	 * Update the pen release flag.
 	 */
-	write_pen_release(cpu);
+	write_pen_release(cpu_logical_map(cpu));
 
 	/*
 	 * Send an event, causing the secondaries to read pen_release.
@@ -105,7 +106,7 @@ static int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
 
 	timeout = jiffies + (1 * HZ);
 	while (time_before(jiffies, timeout)) {
-		if (secondary_holding_pen_release == -1UL)
+		if (secondary_holding_pen_release == INVALID_HWID)
 			break;
 		udelay(10);
 	}
@@ -116,7 +117,7 @@ static int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
 	 */
 	raw_spin_unlock(&boot_lock);
 
-	return secondary_holding_pen_release != -1 ? -ENOSYS : 0;
+	return secondary_holding_pen_release != INVALID_HWID ? -ENOSYS : 0;
 }
 
 static DECLARE_COMPLETION(cpu_running);
@@ -190,7 +191,7 @@ asmlinkage void __cpuinit secondary_start_kernel(void)
 	 * Let the primary processor know we're out of the
 	 * pen, then head off into the C entry point
 	 */
-	write_pen_release(-1);
+	write_pen_release(INVALID_HWID);
 
 	/*
 	 * Synchronise with the boot thread.
@@ -257,15 +258,77 @@ static const struct smp_enable_ops * __init smp_get_enable_ops(const char *name)
 }
 
 /*
- * Enumerate the possible CPU set from the device tree.
+ * Enumerate the possible CPU set from the device tree and build the
+ * cpu logical map array containing MPIDR values related to logical
+ * cpus. Assumes that cpu_logical_map(0) has already been initialized.
  */
 void __init smp_init_cpus(void)
 {
 	const char *enable_method;
 	struct device_node *dn = NULL;
-	int cpu = 0;
+	int i, cpu = 1;
+	bool bootcpu_valid = false;
 
 	while ((dn = of_find_node_by_type(dn, "cpu"))) {
+		u64 hwid;
+
+		/*
+		 * A cpu node with missing "reg" property is
+		 * considered invalid to build a cpu_logical_map
+		 * entry.
+		 */
+		if (of_property_read_u64(dn, "reg", &hwid)) {
+			pr_err("%s: missing reg property\n", dn->full_name);
+			goto next;
+		}
+
+		/*
+		 * Non affinity bits must be set to 0 in the DT
+		 */
+		if (hwid & ~MPIDR_HWID_BITMASK) {
+			pr_err("%s: invalid reg property\n", dn->full_name);
+			goto next;
+		}
+
+		/*
+		 * Duplicate MPIDRs are a recipe for disaster. Scan
+		 * all initialized entries and check for
+		 * duplicates. If any is found just ignore the cpu.
+		 * cpu_logical_map was initialized to INVALID_HWID to
+		 * avoid matching valid MPIDR values.
+		 */
+		for (i = 1; (i < cpu) && (i < NR_CPUS); i++) {
+			if (cpu_logical_map(i) == hwid) {
+				pr_err("%s: duplicate cpu reg properties in the DT\n",
+					dn->full_name);
+				goto next;
+			}
+		}
+
+		/*
+		 * The numbering scheme requires that the boot CPU
+		 * must be assigned logical id 0. Record it so that
+		 * the logical map built from DT is validated and can
+		 * be used.
+		 */
+		if (hwid == cpu_logical_map(0)) {
+			if (bootcpu_valid) {
+				pr_err("%s: duplicate boot cpu reg property in DT\n",
+					dn->full_name);
+				goto next;
+			}
+
+			bootcpu_valid = true;
+
+			/*
+			 * cpu_logical_map has already been
+			 * initialized and the boot cpu doesn't need
+			 * the enable-method so continue without
+			 * incrementing cpu.
+			 */
+			continue;
+		}
+
 		if (cpu >= NR_CPUS)
 			goto next;
 
@@ -274,22 +337,24 @@ void __init smp_init_cpus(void)
 		 */
 		enable_method = of_get_property(dn, "enable-method", NULL);
 		if (!enable_method) {
-			pr_err("CPU %d: missing enable-method property\n", cpu);
+			pr_err("%s: missing enable-method property\n",
+				dn->full_name);
 			goto next;
 		}
 
 		smp_enable_ops[cpu] = smp_get_enable_ops(enable_method);
 
 		if (!smp_enable_ops[cpu]) {
-			pr_err("CPU %d: invalid enable-method property: %s\n",
-			       cpu, enable_method);
+			pr_err("%s: invalid enable-method property: %s\n",
+			       dn->full_name, enable_method);
 			goto next;
 		}
 
 		if (smp_enable_ops[cpu]->init_cpu(dn, cpu))
 			goto next;
 
-		set_cpu_possible(cpu, true);
+		pr_debug("cpu logical map 0x%llx\n", hwid);
+		cpu_logical_map(cpu) = hwid;
 next:
 		cpu++;
 	}
@@ -298,6 +363,19 @@ next:
 	if (cpu > NR_CPUS)
 		pr_warning("no. of cores (%d) greater than configured maximum of %d - clipping\n",
 			   cpu, NR_CPUS);
+
+	if (!bootcpu_valid) {
+		pr_err("DT missing boot CPU MPIDR, not enabling secondaries\n");
+		return;
+	}
+
+	/*
+	 * All the cpus that made it to the cpu_logical_map have been
+	 * validated so set them as possible cpus.
+	 */
+	for (i = 0; i < NR_CPUS; i++)
+		if (cpu_logical_map(i) != INVALID_HWID)
+			set_cpu_possible(i, true);
 }
 
 void __init smp_prepare_cpus(unsigned int max_cpus)
diff --git a/arch/arm64/kernel/smp_psci.c b/arch/arm64/kernel/smp_psci.c
index 1120916..0c53330 100644
--- a/arch/arm64/kernel/smp_psci.c
+++ b/arch/arm64/kernel/smp_psci.c
@@ -21,6 +21,7 @@
 #include <linux/smp.h>
 
 #include <asm/psci.h>
+#include <asm/smp_plat.h>
 
 static int __init smp_psci_init_cpu(struct device_node *dn, int cpu)
 {
@@ -36,7 +37,7 @@ static int __init smp_psci_prepare_cpu(int cpu)
 		return -ENODEV;
 	}
 
-	err = psci_ops.cpu_on(cpu, __pa(secondary_holding_pen));
+	err = psci_ops.cpu_on(cpu_logical_map(cpu), __pa(secondary_holding_pen));
 	if (err) {
 		pr_err("psci: failed to boot CPU%d (%d)\n", cpu, err);
 		return err;
@@ -47,6 +48,6 @@ static int __init smp_psci_prepare_cpu(int cpu)
 
 const struct smp_enable_ops smp_psci_ops __initconst = {
 	.name		= "psci",
-	.init_cpu 	= smp_psci_init_cpu,
+	.init_cpu	= smp_psci_init_cpu,
 	.prepare_cpu	= smp_psci_prepare_cpu,
 };
diff --git a/arch/arm64/kernel/sys32.S b/arch/arm64/kernel/sys32.S
index 9416d04..db01aa9 100644
--- a/arch/arm64/kernel/sys32.S
+++ b/arch/arm64/kernel/sys32.S
@@ -84,13 +84,6 @@ compat_sys_readahead_wrapper:
 	b	sys_readahead
 ENDPROC(compat_sys_readahead_wrapper)
 
-compat_sys_lookup_dcookie:
-	orr	x0, x0, x1, lsl #32
-	mov	w1, w2
-	mov	w2, w3
-	b	sys_lookup_dcookie
-ENDPROC(compat_sys_lookup_dcookie)
-
 compat_sys_fadvise64_64_wrapper:
 	mov	w6, w1
 	orr	x1, x2, x3, lsl #32
diff --git a/arch/arm64/lib/Makefile b/arch/arm64/lib/Makefile
index 2fb7f60..59acc0e 100644
--- a/arch/arm64/lib/Makefile
+++ b/arch/arm64/lib/Makefile
@@ -1,4 +1,6 @@
 lib-y		:= bitops.o delay.o					\
 		   strncpy_from_user.o strnlen_user.o clear_user.o	\
 		   copy_from_user.o copy_to_user.o copy_in_user.o	\
-		   copy_page.o clear_page.o
+		   copy_page.o clear_page.o				\
+		   memchr.o memcpy.o memmove.o memset.o			\
+		   strchr.o strrchr.o
diff --git a/arch/arm64/lib/bitops.S b/arch/arm64/lib/bitops.S
new file mode 100644
index 0000000..fd1e801
--- /dev/null
+++ b/arch/arm64/lib/bitops.S
@@ -0,0 +1,70 @@
+/*
+ * Based on arch/arm/lib/bitops.h
+ *
+ * Copyright (C) 2013 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU 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/linkage.h>
+#include <asm/assembler.h>
+
+/*
+ * x0: bits 5:0  bit offset
+ *     bits 63:6 word offset
+ * x1: address
+ */
+	.macro	bitop, name, instr
+ENTRY(	\name	)
+	and	x3, x0, #63		// Get bit offset
+	eor	x0, x0, x3		// Clear low bits
+	mov	x2, #1
+	add	x1, x1, x0, lsr #3	// Get word offset
+	lsl	x3, x2, x3		// Create mask
+1:	ldxr	x2, [x1]
+	\instr	x2, x2, x3
+	stxr	w0, x2, [x1]
+	cbnz	w0, 1b
+	ret
+ENDPROC(\name	)
+	.endm
+
+	.macro	testop, name, instr
+ENTRY(	\name	)
+	and	x3, x0, #63		// Get bit offset
+	eor	x0, x0, x3		// Clear low bits
+	mov	x2, #1
+	add	x1, x1, x0, lsr #3	// Get word offset
+	lsl	x4, x2, x3		// Create mask
+	smp_dmb	ish
+1:	ldxr	x2, [x1]
+	lsr	x0, x2, x3		// Save old value of bit
+	\instr	x2, x2, x4		// toggle bit
+	stxr	w2, x2, [x1]
+	cbnz	w2, 1b
+	smp_dmb	ish
+	and	x0, x0, #1
+3:	ret
+ENDPROC(\name	)
+	.endm
+
+/*
+ * Atomic bit operations.
+ */
+	bitop	change_bit, eor
+	bitop	clear_bit, bic
+	bitop	set_bit, orr
+
+	testop	test_and_change_bit, eor
+	testop	test_and_clear_bit, bic
+	testop	test_and_set_bit, orr
diff --git a/arch/arm64/lib/bitops.c b/arch/arm64/lib/bitops.c
deleted file mode 100644
index aa4965e..0000000
--- a/arch/arm64/lib/bitops.c
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2012 ARM 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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU 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/spinlock.h>
-#include <linux/atomic.h>
-
-#ifdef CONFIG_SMP
-arch_spinlock_t __atomic_hash[ATOMIC_HASH_SIZE] __lock_aligned = {
-       [0 ... (ATOMIC_HASH_SIZE-1)]  = __ARCH_SPIN_LOCK_UNLOCKED
-};
-#endif
diff --git a/arch/arm64/lib/memchr.S b/arch/arm64/lib/memchr.S
new file mode 100644
index 0000000..8636b75
--- /dev/null
+++ b/arch/arm64/lib/memchr.S
@@ -0,0 +1,44 @@
+/*
+ * Based on arch/arm/lib/memchr.S
+ *
+ * Copyright (C) 1995-2000 Russell King
+ * Copyright (C) 2013 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU 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/linkage.h>
+#include <asm/assembler.h>
+
+/*
+ * Find a character in an area of memory.
+ *
+ * Parameters:
+ *	x0 - buf
+ *	x1 - c
+ *	x2 - n
+ * Returns:
+ *	x0 - address of first occurrence of 'c' or 0
+ */
+ENTRY(memchr)
+	and	w1, w1, #0xff
+1:	subs	x2, x2, #1
+	b.mi	2f
+	ldrb	w3, [x0], #1
+	cmp	w3, w1
+	b.ne	1b
+	sub	x0, x0, #1
+	ret
+2:	mov	x0, #0
+	ret
+ENDPROC(memchr)
diff --git a/arch/arm64/lib/memcpy.S b/arch/arm64/lib/memcpy.S
new file mode 100644
index 0000000..27b5003
--- /dev/null
+++ b/arch/arm64/lib/memcpy.S
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2013 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU 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/linkage.h>
+#include <asm/assembler.h>
+
+/*
+ * Copy a buffer from src to dest (alignment handled by the hardware)
+ *
+ * Parameters:
+ *	x0 - dest
+ *	x1 - src
+ *	x2 - n
+ * Returns:
+ *	x0 - dest
+ */
+ENTRY(memcpy)
+	mov	x4, x0
+	subs	x2, x2, #8
+	b.mi	2f
+1:	ldr	x3, [x1], #8
+	subs	x2, x2, #8
+	str	x3, [x4], #8
+	b.pl	1b
+2:	adds	x2, x2, #4
+	b.mi	3f
+	ldr	w3, [x1], #4
+	sub	x2, x2, #4
+	str	w3, [x4], #4
+3:	adds	x2, x2, #2
+	b.mi	4f
+	ldrh	w3, [x1], #2
+	sub	x2, x2, #2
+	strh	w3, [x4], #2
+4:	adds	x2, x2, #1
+	b.mi	5f
+	ldrb	w3, [x1]
+	strb	w3, [x4]
+5:	ret
+ENDPROC(memcpy)
diff --git a/arch/arm64/lib/memmove.S b/arch/arm64/lib/memmove.S
new file mode 100644
index 0000000..b79fdfa
--- /dev/null
+++ b/arch/arm64/lib/memmove.S
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2013 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU 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/linkage.h>
+#include <asm/assembler.h>
+
+/*
+ * Move a buffer from src to test (alignment handled by the hardware).
+ * If dest <= src, call memcpy, otherwise copy in reverse order.
+ *
+ * Parameters:
+ *	x0 - dest
+ *	x1 - src
+ *	x2 - n
+ * Returns:
+ *	x0 - dest
+ */
+ENTRY(memmove)
+	cmp	x0, x1
+	b.ls	memcpy
+	add	x4, x0, x2
+	add	x1, x1, x2
+	subs	x2, x2, #8
+	b.mi	2f
+1:	ldr	x3, [x1, #-8]!
+	subs	x2, x2, #8
+	str	x3, [x4, #-8]!
+	b.pl	1b
+2:	adds	x2, x2, #4
+	b.mi	3f
+	ldr	w3, [x1, #-4]!
+	sub	x2, x2, #4
+	str	w3, [x4, #-4]!
+3:	adds	x2, x2, #2
+	b.mi	4f
+	ldrh	w3, [x1, #-2]!
+	sub	x2, x2, #2
+	strh	w3, [x4, #-2]!
+4:	adds	x2, x2, #1
+	b.mi	5f
+	ldrb	w3, [x1, #-1]
+	strb	w3, [x4, #-1]
+5:	ret
+ENDPROC(memmove)
diff --git a/arch/arm64/lib/memset.S b/arch/arm64/lib/memset.S
new file mode 100644
index 0000000..87e4a68
--- /dev/null
+++ b/arch/arm64/lib/memset.S
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2013 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU 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/linkage.h>
+#include <asm/assembler.h>
+
+/*
+ * Fill in the buffer with character c (alignment handled by the hardware)
+ *
+ * Parameters:
+ *	x0 - buf
+ *	x1 - c
+ *	x2 - n
+ * Returns:
+ *	x0 - buf
+ */
+ENTRY(memset)
+	mov	x4, x0
+	and	w1, w1, #0xff
+	orr	w1, w1, w1, lsl #8
+	orr	w1, w1, w1, lsl #16
+	orr	x1, x1, x1, lsl #32
+	subs	x2, x2, #8
+	b.mi	2f
+1:	str	x1, [x4], #8
+	subs	x2, x2, #8
+	b.pl	1b
+2:	adds	x2, x2, #4
+	b.mi	3f
+	sub	x2, x2, #4
+	str	w1, [x4], #4
+3:	adds	x2, x2, #2
+	b.mi	4f
+	sub	x2, x2, #2
+	strh	w1, [x4], #2
+4:	adds	x2, x2, #1
+	b.mi	5f
+	strb	w1, [x4]
+5:	ret
+ENDPROC(memset)
diff --git a/arch/arm64/lib/strchr.S b/arch/arm64/lib/strchr.S
new file mode 100644
index 0000000..dae0cf5
--- /dev/null
+++ b/arch/arm64/lib/strchr.S
@@ -0,0 +1,42 @@
+/*
+ * Based on arch/arm/lib/strchr.S
+ *
+ * Copyright (C) 1995-2000 Russell King
+ * Copyright (C) 2013 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU 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/linkage.h>
+#include <asm/assembler.h>
+
+/*
+ * Find the first occurrence of a character in a string.
+ *
+ * Parameters:
+ *	x0 - str
+ *	x1 - c
+ * Returns:
+ *	x0 - address of first occurrence of 'c' or 0
+ */
+ENTRY(strchr)
+	and	w1, w1, #0xff
+1:	ldrb	w2, [x0], #1
+	cmp	w2, w1
+	ccmp	w2, wzr, #4, ne
+	b.ne	1b
+	sub	x0, x0, #1
+	cmp	w2, w1
+	csel	x0, x0, xzr, eq
+	ret
+ENDPROC(strchr)
diff --git a/arch/arm64/lib/strrchr.S b/arch/arm64/lib/strrchr.S
new file mode 100644
index 0000000..61eabd9
--- /dev/null
+++ b/arch/arm64/lib/strrchr.S
@@ -0,0 +1,43 @@
+/*
+ * Based on arch/arm/lib/strrchr.S
+ *
+ * Copyright (C) 1995-2000 Russell King
+ * Copyright (C) 2013 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU 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/linkage.h>
+#include <asm/assembler.h>
+
+/*
+ * Find the last occurrence of a character in a string.
+ *
+ * Parameters:
+ *	x0 - str
+ *	x1 - c
+ * Returns:
+ *	x0 - address of last occurrence of 'c' or 0
+ */
+ENTRY(strrchr)
+	mov	x3, #0
+	and	w1, w1, #0xff
+1:	ldrb	w2, [x0], #1
+	cbz	w2, 2f
+	cmp	w2, w1
+	b.ne	1b
+	sub	x3, x0, #1
+	b	1b
+2:	mov	x0, x3
+	ret
+ENDPROC(strrchr)
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index 800aac3..f497ca7 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -197,24 +197,6 @@ void __init bootmem_init(void)
 	max_pfn = max_low_pfn = max;
 }
 
-static inline int free_area(unsigned long pfn, unsigned long end, char *s)
-{
-	unsigned int pages = 0, size = (end - pfn) << (PAGE_SHIFT - 10);
-
-	for (; pfn < end; pfn++) {
-		struct page *page = pfn_to_page(pfn);
-		ClearPageReserved(page);
-		init_page_count(page);
-		__free_page(page);
-		pages++;
-	}
-
-	if (size && s)
-		pr_info("Freeing %s memory: %dK\n", s, size);
-
-	return pages;
-}
-
 /*
  * Poison init memory with an undefined instruction (0x0).
  */
@@ -405,9 +387,7 @@ void __init mem_init(void)
 void free_initmem(void)
 {
 	poison_init_mem(__init_begin, __init_end - __init_begin);
-	totalram_pages += free_area(__phys_to_pfn(__pa(__init_begin)),
-				    __phys_to_pfn(__pa(__init_end)),
-				    "init");
+	free_initmem_default(0);
 }
 
 #ifdef CONFIG_BLK_DEV_INITRD
@@ -418,9 +398,7 @@ void free_initrd_mem(unsigned long start, unsigned long end)
 {
 	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");
+		free_reserved_area(start, end, 0, "initrd");
 	}
 }
 
diff --git a/arch/arm64/mm/mmap.c b/arch/arm64/mm/mmap.c
index 7c7be78..8ed6cb1 100644
--- a/arch/arm64/mm/mmap.c
+++ b/arch/arm64/mm/mmap.c
@@ -90,11 +90,9 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
 	if (mmap_is_legacy()) {
 		mm->mmap_base = TASK_UNMAPPED_BASE;
 		mm->get_unmapped_area = arch_get_unmapped_area;
-		mm->unmap_area = arch_unmap_area;
 	} else {
 		mm->mmap_base = mmap_base();
 		mm->get_unmapped_area = arch_get_unmapped_area_topdown;
-		mm->unmap_area = arch_unmap_area_topdown;
 	}
 }
 EXPORT_SYMBOL_GPL(arch_pick_mmap_layout);
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index 70b8cd4..eeecc9c 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -391,17 +391,14 @@ int kern_addr_valid(unsigned long addr)
 }
 #ifdef CONFIG_SPARSEMEM_VMEMMAP
 #ifdef CONFIG_ARM64_64K_PAGES
-int __meminit vmemmap_populate(struct page *start_page,
-			       unsigned long size, int node)
+int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node)
 {
-	return vmemmap_populate_basepages(start_page, size, node);
+	return vmemmap_populate_basepages(start, end, node);
 }
 #else	/* !CONFIG_ARM64_64K_PAGES */
-int __meminit vmemmap_populate(struct page *start_page,
-			       unsigned long size, int node)
+int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node)
 {
-	unsigned long addr = (unsigned long)start_page;
-	unsigned long end = (unsigned long)(start_page + size);
+	unsigned long addr = start;
 	unsigned long next;
 	pgd_t *pgd;
 	pud_t *pud;
@@ -434,7 +431,7 @@ int __meminit vmemmap_populate(struct page *start_page,
 	return 0;
 }
 #endif	/* CONFIG_ARM64_64K_PAGES */
-void vmemmap_free(struct page *memmap, unsigned long nr_pages)
+void vmemmap_free(unsigned long start, unsigned long end)
 {
 }
 #endif	/* CONFIG_SPARSEMEM_VMEMMAP */
diff --git a/arch/avr32/Kconfig b/arch/avr32/Kconfig
index c1a868d..d22c6b4 100644
--- a/arch/avr32/Kconfig
+++ b/arch/avr32/Kconfig
@@ -27,7 +27,7 @@ config AVR32
 	  http://avr32linux.org/.
 
 config GENERIC_GPIO
-	def_bool y
+	def_bool n
 
 config STACKTRACE_SUPPORT
 	def_bool y
diff --git a/arch/avr32/configs/favr-32_defconfig b/arch/avr32/configs/favr-32_defconfig
index 0421498..9791820 100644
--- a/arch/avr32/configs/favr-32_defconfig
+++ b/arch/avr32/configs/favr-32_defconfig
@@ -122,7 +122,6 @@ CONFIG_USB_G_SERIAL=m
 CONFIG_USB_CDC_COMPOSITE=m
 CONFIG_MMC=y
 CONFIG_MMC_ATMELMCI=y
-CONFIG_MMC_ATMELMCI_DMA=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
 CONFIG_LEDS_ATMEL_PWM=m
diff --git a/arch/avr32/configs/merisc_defconfig b/arch/avr32/configs/merisc_defconfig
index 3befab9..65de443 100644
--- a/arch/avr32/configs/merisc_defconfig
+++ b/arch/avr32/configs/merisc_defconfig
@@ -102,7 +102,6 @@ CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_LOGO=y
 CONFIG_MMC=y
 CONFIG_MMC_ATMELMCI=y
-CONFIG_MMC_ATMELMCI_DMA=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
 CONFIG_LEDS_ATMEL_PWM=y
diff --git a/arch/avr32/include/asm/unistd.h b/arch/avr32/include/asm/unistd.h
index dc4d5a9..c1eb080 100644
--- a/arch/avr32/include/asm/unistd.h
+++ b/arch/avr32/include/asm/unistd.h
@@ -41,12 +41,4 @@
 #define __ARCH_WANT_SYS_VFORK
 #define __ARCH_WANT_SYS_CLONE
 
-/*
- * "Conditional" syscalls
- *
- * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
- * but it doesn't work on all toolchains, so we just do it by hand
- */
-#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
-
 #endif /* __ASM_AVR32_UNISTD_H */
diff --git a/arch/avr32/include/uapi/asm/socket.h b/arch/avr32/include/uapi/asm/socket.h
index 51c6401..37401f5 100644
--- a/arch/avr32/include/uapi/asm/socket.h
+++ b/arch/avr32/include/uapi/asm/socket.h
@@ -72,4 +72,6 @@
 
 #define SO_LOCK_FILTER		44
 
+#define SO_SELECT_ERR_QUEUE	45
+
 #endif /* __ASM_AVR32_SOCKET_H */
diff --git a/arch/avr32/mach-at32ap/at32ap700x.c b/arch/avr32/mach-at32ap/at32ap700x.c
index b323d8d..7c2f668 100644
--- a/arch/avr32/mach-at32ap/at32ap700x.c
+++ b/arch/avr32/mach-at32ap/at32ap700x.c
@@ -1453,7 +1453,7 @@ static struct resource atmel_lcdfb0_resource[] = {
 	},
 };
 DEFINE_DEV_DATA(atmel_lcdfb, 0);
-DEV_CLK(hck1, atmel_lcdfb0, hsb, 7);
+DEV_CLK(hclk, atmel_lcdfb0, hsb, 7);
 static struct clk atmel_lcdfb0_pixclk = {
 	.name		= "lcdc_clk",
 	.dev		= &atmel_lcdfb0_device.dev,
@@ -1530,6 +1530,8 @@ at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_info *data,
 	memcpy(info, data, sizeof(struct atmel_lcdfb_info));
 	info->default_monspecs = monspecs;
 
+	pdev->name = "at32ap-lcdfb";
+
 	platform_device_register(pdev);
 	return pdev;
 
@@ -2246,7 +2248,7 @@ static __initdata struct clk *init_clocks[] = {
 	&atmel_twi0_pclk,
 	&atmel_mci0_pclk,
 #if defined(CONFIG_CPU_AT32AP7000) || defined(CONFIG_CPU_AT32AP7002)
-	&atmel_lcdfb0_hck1,
+	&atmel_lcdfb0_hclk,
 	&atmel_lcdfb0_pixclk,
 #endif
 	&ssc0_pclk,
diff --git a/arch/avr32/mach-at32ap/cpufreq.c b/arch/avr32/mach-at32ap/cpufreq.c
index 18b7656..6544887 100644
--- a/arch/avr32/mach-at32ap/cpufreq.c
+++ b/arch/avr32/mach-at32ap/cpufreq.c
@@ -61,7 +61,6 @@ static int at32_set_target(struct cpufreq_policy *policy,
 
 	freqs.old = at32_get_speed(0);
 	freqs.new = (freq + 500) / 1000;
-	freqs.cpu = 0;
 	freqs.flags = 0;
 
 	if (!ref_freq) {
@@ -69,7 +68,7 @@ static int at32_set_target(struct cpufreq_policy *policy,
 		loops_per_jiffy_ref = boot_cpu_data.loops_per_jiffy;
 	}
 
-	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
 	if (freqs.old < freqs.new)
 		boot_cpu_data.loops_per_jiffy = cpufreq_scale(
 				loops_per_jiffy_ref, ref_freq, freqs.new);
@@ -77,7 +76,7 @@ static int at32_set_target(struct cpufreq_policy *policy,
 	if (freqs.new < freqs.old)
 		boot_cpu_data.loops_per_jiffy = cpufreq_scale(
 				loops_per_jiffy_ref, ref_freq, freqs.new);
-	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
 
 	pr_debug("cpufreq: set frequency %lu Hz\n", freq);
 
diff --git a/arch/avr32/mm/init.c b/arch/avr32/mm/init.c
index 2798c2d..e66e840 100644
--- a/arch/avr32/mm/init.c
+++ b/arch/avr32/mm/init.c
@@ -146,34 +146,14 @@ void __init mem_init(void)
 		initsize >> 10);
 }
 
-static inline void free_area(unsigned long addr, unsigned long end, char *s)
-{
-	unsigned int size = (end - addr) >> 10;
-
-	for (; addr < end; addr += PAGE_SIZE) {
-		struct page *page = virt_to_page(addr);
-		ClearPageReserved(page);
-		init_page_count(page);
-		free_page(addr);
-		totalram_pages++;
-	}
-
-	if (size && s)
-		printk(KERN_INFO "Freeing %s memory: %dK (%lx - %lx)\n",
-		       s, size, end - (size << 10), end);
-}
-
 void free_initmem(void)
 {
-	free_area((unsigned long)__init_begin, (unsigned long)__init_end,
-		  "init");
+	free_initmem_default(0);
 }
 
 #ifdef CONFIG_BLK_DEV_INITRD
-
 void free_initrd_mem(unsigned long start, unsigned long end)
 {
-	free_area(start, end, "initrd");
+	free_reserved_area(start, end, 0, "initrd");
 }
-
 #endif
diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig
index c3f2e0b..ed62933 100644
--- a/arch/blackfin/Kconfig
+++ b/arch/blackfin/Kconfig
@@ -1,7 +1,3 @@
-config SYMBOL_PREFIX
-	string
-	default "_"
-
 config MMU
 	def_bool n
 
@@ -31,8 +27,9 @@ config BLACKFIN
 	select HAVE_OPROFILE
 	select HAVE_PERF_EVENTS
 	select ARCH_HAVE_CUSTOM_GPIO_H
-	select ARCH_WANT_OPTIONAL_GPIOLIB
+	select ARCH_REQUIRE_GPIOLIB
 	select HAVE_UID16
+	select HAVE_UNDERSCORE_SYMBOL_PREFIX
 	select VIRT_TO_BUS
 	select ARCH_WANT_IPC_PARSE_VERSION
 	select HAVE_GENERIC_HARDIRQS
@@ -56,7 +53,7 @@ config ZONE_DMA
 	def_bool y
 
 config GENERIC_GPIO
-	def_bool y
+	def_bool n
 
 config FORCE_MAX_ZONEORDER
 	int
diff --git a/arch/blackfin/include/asm/bfin_sport3.h b/arch/blackfin/include/asm/bfin_sport3.h
index 03c0022..d82f5fa 100644
--- a/arch/blackfin/include/asm/bfin_sport3.h
+++ b/arch/blackfin/include/asm/bfin_sport3.h
@@ -41,7 +41,7 @@
 #define SPORT_CTL_LAFS                0x00020000    /* Late Transmit frame select */
 #define SPORT_CTL_RJUST               0x00040000    /* Right Justified mode select */
 #define SPORT_CTL_FSED                0x00080000    /* External frame sync edge select */
-#define SPORT_CTL_TFIEN               0x00100000    /* Transmit finish interrrupt enable select */
+#define SPORT_CTL_TFIEN               0x00100000    /* Transmit finish interrupt enable select */
 #define SPORT_CTL_GCLKEN              0x00200000    /* Gated clock mode select */
 #define SPORT_CTL_SPENSEC             0x01000000    /* Enable secondary channel */
 #define SPORT_CTL_SPTRAN              0x02000000    /* Data direction control */
diff --git a/arch/blackfin/include/asm/unistd.h b/arch/blackfin/include/asm/unistd.h
index 04e83ea..c35414b 100644
--- a/arch/blackfin/include/asm/unistd.h
+++ b/arch/blackfin/include/asm/unistd.h
@@ -20,12 +20,4 @@
 #define __ARCH_WANT_SYS_NICE
 #define __ARCH_WANT_SYS_VFORK
 
-/*
- * "Conditional" syscalls
- *
- * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
- * but it doesn't work on all toolchains, so we just do it by hand
- */
-#define cond_syscall(x) asm(".weak\t_" #x "\n\t.set\t_" #x ",_sys_ni_syscall");
-
 #endif				/* __ASM_BFIN_UNISTD_H */
diff --git a/arch/blackfin/kernel/cplbinfo.c b/arch/blackfin/kernel/cplbinfo.c
index e1d0b24..404045d 100644
--- a/arch/blackfin/kernel/cplbinfo.c
+++ b/arch/blackfin/kernel/cplbinfo.c
@@ -116,14 +116,12 @@ static const struct seq_operations cplbinfo_sops = {
 
 static int cplbinfo_open(struct inode *inode, struct file *file)
 {
-	struct proc_dir_entry *pde = PDE(file_inode(file));
 	char cplb_type;
-	unsigned int cpu;
+	unsigned int cpu = (unsigned long)PDE_DATA(file_inode(file));
 	int ret;
 	struct seq_file *m;
 	struct cplbinfo_data *cdata;
 
-	cpu = (unsigned int)pde->data;
 	cplb_type = cpu & CPLBINFO_DCPLB_FLAG ? 'D' : 'I';
 	cpu &= ~CPLBINFO_DCPLB_FLAG;
 
diff --git a/arch/blackfin/kernel/early_printk.c b/arch/blackfin/kernel/early_printk.c
index 84ed837..61fbd2d 100644
--- a/arch/blackfin/kernel/early_printk.c
+++ b/arch/blackfin/kernel/early_printk.c
@@ -25,8 +25,6 @@ extern struct console *bfin_earlyserial_init(unsigned int port,
 extern struct console *bfin_jc_early_init(void);
 #endif
 
-static struct console *early_console;
-
 /* Default console */
 #define DEFAULT_PORT 0
 #define DEFAULT_CFLAG CS8|B57600
diff --git a/arch/blackfin/mach-bf609/boards/ezkit.c b/arch/blackfin/mach-bf609/boards/ezkit.c
index 61c1f47..97d7016 100644
--- a/arch/blackfin/mach-bf609/boards/ezkit.c
+++ b/arch/blackfin/mach-bf609/boards/ezkit.c
@@ -936,19 +936,19 @@ static struct v4l2_input adv7842_inputs[] = {
 		.index = 2,
 		.name = "Component",
 		.type = V4L2_INPUT_TYPE_CAMERA,
-		.capabilities = V4L2_IN_CAP_CUSTOM_TIMINGS,
+		.capabilities = V4L2_IN_CAP_DV_TIMINGS,
 	},
 	{
 		.index = 3,
 		.name = "VGA",
 		.type = V4L2_INPUT_TYPE_CAMERA,
-		.capabilities = V4L2_IN_CAP_CUSTOM_TIMINGS,
+		.capabilities = V4L2_IN_CAP_DV_TIMINGS,
 	},
 	{
 		.index = 4,
 		.name = "HDMI",
 		.type = V4L2_INPUT_TYPE_CAMERA,
-		.capabilities = V4L2_IN_CAP_CUSTOM_TIMINGS,
+		.capabilities = V4L2_IN_CAP_DV_TIMINGS,
 	},
 };
 
@@ -1074,7 +1074,7 @@ static struct v4l2_output adv7511_outputs[] = {
 		.index = 0,
 		.name = "HDMI",
 		.type = V4L2_INPUT_TYPE_CAMERA,
-		.capabilities = V4L2_OUT_CAP_CUSTOM_TIMINGS,
+		.capabilities = V4L2_OUT_CAP_DV_TIMINGS,
 	},
 };
 
diff --git a/arch/blackfin/mach-common/cpufreq.c b/arch/blackfin/mach-common/cpufreq.c
index d88bd31..995511e80 100644
--- a/arch/blackfin/mach-common/cpufreq.c
+++ b/arch/blackfin/mach-common/cpufreq.c
@@ -127,13 +127,13 @@ unsigned long cpu_set_cclk(int cpu, unsigned long new)
 }
 #endif
 
-static int bfin_target(struct cpufreq_policy *poli,
+static int bfin_target(struct cpufreq_policy *policy,
 			unsigned int target_freq, unsigned int relation)
 {
 #ifndef CONFIG_BF60x
 	unsigned int plldiv;
 #endif
-	unsigned int index, cpu;
+	unsigned int index;
 	unsigned long cclk_hz;
 	struct cpufreq_freqs freqs;
 	static unsigned long lpj_ref;
@@ -144,59 +144,48 @@ static int bfin_target(struct cpufreq_policy *poli,
 	cycles_t cycles;
 #endif
 
-	for_each_online_cpu(cpu) {
-		struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
+	if (cpufreq_frequency_table_target(policy, bfin_freq_table, target_freq,
+				relation, &index))
+		return -EINVAL;
 
-		if (!policy)
-			continue;
+	cclk_hz = bfin_freq_table[index].frequency;
 
-		if (cpufreq_frequency_table_target(policy, bfin_freq_table,
-				 target_freq, relation, &index))
-			return -EINVAL;
+	freqs.old = bfin_getfreq_khz(0);
+	freqs.new = cclk_hz;
 
-		cclk_hz = bfin_freq_table[index].frequency;
+	pr_debug("cpufreq: changing cclk to %lu; target = %u, oldfreq = %u\n",
+			cclk_hz, target_freq, freqs.old);
 
-		freqs.old = bfin_getfreq_khz(0);
-		freqs.new = cclk_hz;
-		freqs.cpu = cpu;
-
-		pr_debug("cpufreq: changing cclk to %lu; target = %u, oldfreq = %u\n",
-			 cclk_hz, target_freq, freqs.old);
-
-		cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
-		if (cpu == CPUFREQ_CPU) {
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
 #ifndef CONFIG_BF60x
-			plldiv = (bfin_read_PLL_DIV() & SSEL) |
-						dpm_state_table[index].csel;
-			bfin_write_PLL_DIV(plldiv);
+	plldiv = (bfin_read_PLL_DIV() & SSEL) | dpm_state_table[index].csel;
+	bfin_write_PLL_DIV(plldiv);
 #else
-			ret = cpu_set_cclk(cpu, freqs.new * 1000);
-			if (ret != 0) {
-				WARN_ONCE(ret, "cpufreq set freq failed %d\n", ret);
-				break;
-			}
+	ret = cpu_set_cclk(policy->cpu, freqs.new * 1000);
+	if (ret != 0) {
+		WARN_ONCE(ret, "cpufreq set freq failed %d\n", ret);
+		return ret;
+	}
 #endif
-			on_each_cpu(bfin_adjust_core_timer, &index, 1);
+	on_each_cpu(bfin_adjust_core_timer, &index, 1);
 #if defined(CONFIG_CYCLES_CLOCKSOURCE)
-			cycles = get_cycles();
-			SSYNC();
-			cycles += 10; /* ~10 cycles we lose after get_cycles() */
-			__bfin_cycles_off +=
-			    (cycles << __bfin_cycles_mod) - (cycles << index);
-			__bfin_cycles_mod = index;
+	cycles = get_cycles();
+	SSYNC();
+	cycles += 10; /* ~10 cycles we lose after get_cycles() */
+	__bfin_cycles_off += (cycles << __bfin_cycles_mod) - (cycles << index);
+	__bfin_cycles_mod = index;
 #endif
-			if (!lpj_ref_freq) {
-				lpj_ref = loops_per_jiffy;
-				lpj_ref_freq = freqs.old;
-			}
-			if (freqs.new != freqs.old) {
-				loops_per_jiffy = cpufreq_scale(lpj_ref,
-						lpj_ref_freq, freqs.new);
-			}
-		}
-		/* TODO: just test case for cycles clock source, remove later */
-		cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	if (!lpj_ref_freq) {
+		lpj_ref = loops_per_jiffy;
+		lpj_ref_freq = freqs.old;
 	}
+	if (freqs.new != freqs.old) {
+		loops_per_jiffy = cpufreq_scale(lpj_ref,
+				lpj_ref_freq, freqs.new);
+	}
+
+	/* TODO: just test case for cycles clock source, remove later */
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
 
 	pr_debug("cpufreq: done\n");
 	return ret;
diff --git a/arch/blackfin/mm/init.c b/arch/blackfin/mm/init.c
index 9cb8553..82d01a7 100644
--- a/arch/blackfin/mm/init.c
+++ b/arch/blackfin/mm/init.c
@@ -103,7 +103,7 @@ void __init mem_init(void)
 	max_mapnr = num_physpages = MAP_NR(high_memory);
 	printk(KERN_DEBUG "Kernel managed physical pages: %lu\n", num_physpages);
 
-	/* This will put all memory onto the freelists. */
+	/* This will put all low memory onto the freelists. */
 	totalram_pages = free_all_bootmem();
 
 	reservedpages = 0;
@@ -129,24 +129,11 @@ void __init mem_init(void)
 		initk, codek, datak, DMA_UNCACHED_REGION >> 10, (reservedpages << (PAGE_SHIFT-10)));
 }
 
-static void __init free_init_pages(const char *what, unsigned long begin, unsigned long end)
-{
-	unsigned long addr;
-	/* next to check that the page we free is not a partial page */
-	for (addr = begin; addr + PAGE_SIZE <= 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 %s: %ldk freed\n", what, (end - begin) >> 10);
-}
-
 #ifdef CONFIG_BLK_DEV_INITRD
 void __init free_initrd_mem(unsigned long start, unsigned long end)
 {
 #ifndef CONFIG_MPU
-	free_init_pages("initrd memory", start, end);
+	free_reserved_area(start, end, 0, "initrd");
 #endif
 }
 #endif
@@ -154,10 +141,7 @@ void __init free_initrd_mem(unsigned long start, unsigned long end)
 void __init_refok free_initmem(void)
 {
 #if defined CONFIG_RAMKERNEL && !defined CONFIG_MPU
-	free_init_pages("unused kernel memory",
-			(unsigned long)(&__init_begin),
-			(unsigned long)(&__init_end));
-
+	free_initmem_default(0);
 	if (memory_start == (unsigned long)(&__init_end))
 		memory_start = (unsigned long)(&__init_begin);
 #endif
diff --git a/arch/c6x/mm/init.c b/arch/c6x/mm/init.c
index 89395f0..a9fcd89 100644
--- a/arch/c6x/mm/init.c
+++ b/arch/c6x/mm/init.c
@@ -77,37 +77,11 @@ void __init mem_init(void)
 #ifdef CONFIG_BLK_DEV_INITRD
 void __init free_initrd_mem(unsigned long start, unsigned long end)
 {
-	int pages = 0;
-	for (; start < end; start += PAGE_SIZE) {
-		ClearPageReserved(virt_to_page(start));
-		init_page_count(virt_to_page(start));
-		free_page(start);
-		totalram_pages++;
-		pages++;
-	}
-	printk(KERN_INFO "Freeing initrd memory: %luk freed\n",
-	       (pages * PAGE_SIZE) >> 10);
+	free_reserved_area(start, end, 0, "initrd");
 }
 #endif
 
 void __init free_initmem(void)
 {
-	unsigned long addr;
-
-	/*
-	 * The following code should be cool even if these sections
-	 * are not page aligned.
-	 */
-	addr = PAGE_ALIGN((unsigned long)(__init_begin));
-
-	/* next to check that the page we free is not a partial page */
-	for (; addr + PAGE_SIZE < (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: %dK freed\n",
-	       (int) ((addr - PAGE_ALIGN((long) &__init_begin)) >> 10));
+	free_initmem_default(0);
 }
diff --git a/arch/cris/Kconfig b/arch/cris/Kconfig
index 06dd026..d32a6b4 100644
--- a/arch/cris/Kconfig
+++ b/arch/cris/Kconfig
@@ -99,9 +99,6 @@ config ETRAX_KMALLOCED_MODULES
 	help
 	  Enable module allocation with kmalloc instead of vmalloc.
 
-config OOM_REBOOT
-       bool "Enable reboot at out of memory"
-
 source "kernel/Kconfig.preempt"
 
 source mm/Kconfig
@@ -264,45 +261,12 @@ config ETRAX_AXISFLASHMAP
 	select MTD_CFI
 	select MTD_CFI_AMDSTD
 	select MTD_JEDECPROBE if ETRAX_ARCH_V32
-	select MTD_CHAR
 	select MTD_BLOCK
 	select MTD_COMPLEX_MAPPINGS
 	help
 	  This option enables MTD mapping of flash devices.  Needed to use
 	  flash memories.  If unsure, say Y.
 
-config ETRAX_RTC
-	bool "Real Time Clock support"
-	depends on ETRAX_I2C
-	help
-	  Enables drivers for the Real-Time Clock battery-backed chips on
-	  some products. The kernel reads the time when booting, and
-	  the date can be set using ioctl(fd, RTC_SET_TIME, &rt) with rt a
-	  rtc_time struct (see <file:arch/cris/include/asm/rtc.h>) on the
-	  /dev/rtc device.  You can check the time with cat /proc/rtc, but
-	  normal time reading should be done using libc function time and
-	  friends.
-
-choice
-	prompt "RTC chip"
-	depends on ETRAX_RTC
-	default ETRAX_DS1302
-
-config ETRAX_DS1302
-	depends on ETRAX_ARCH_V10
-	bool "DS1302"
-	help
-	  Enables the driver for the DS1302 Real-Time Clock battery-backed
-	  chip on some products.
-
-config ETRAX_PCF8563
-	bool "PCF8563"
-	help
-	  Enables the driver for the PCF8563 Real-Time Clock battery-backed
-	  chip on some products.
-
-endchoice
-
 config ETRAX_SYNCHRONOUS_SERIAL
 	bool "Synchronous serial-port support"
 	help
diff --git a/arch/cris/arch-v10/drivers/Kconfig b/arch/cris/arch-v10/drivers/Kconfig
index 5f2cdb3..e5be544 100644
--- a/arch/cris/arch-v10/drivers/Kconfig
+++ b/arch/cris/arch-v10/drivers/Kconfig
@@ -582,51 +582,4 @@ config ETRAX_PB_CHANGEABLE_BITS
 	  Bit set = changeable.
 	  You probably want 00 here.
 
-config ETRAX_DS1302_RST_ON_GENERIC_PORT
-	bool "DS1302 RST on Generic Port"
-	depends on ETRAX_DS1302
-	help
-	  If your product has the RST signal line for the DS1302 RTC on the
-	  Generic Port then say Y here, otherwise leave it as N in which
-	  case the RST signal line is assumed to be connected to Port PB
-	  (just like the SCL and SDA lines).
-
-config ETRAX_DS1302_RSTBIT
-	int "DS1302 RST bit number"
-	depends on ETRAX_DS1302
-	default "2"
-	help
-	  This is the bit number for the RST signal line of the DS1302 RTC on
-	  the selected port. If you have selected the generic port then it
-	  should be bit 27, otherwise your best bet is bit 5.
-
-config ETRAX_DS1302_SCLBIT
-	int "DS1302 SCL bit number"
-	depends on ETRAX_DS1302
-	default "1"
-	help
-	  This is the bit number for the SCL signal line of the DS1302 RTC on
-	  Port PB. This is probably best left at 3.
-
-config ETRAX_DS1302_SDABIT
-	int "DS1302 SDA bit number"
-	depends on ETRAX_DS1302
-	default "0"
-	help
-	  This is the bit number for the SDA signal line of the DS1302 RTC on
-	  Port PB. This is probably best left at 2.
-
-config ETRAX_DS1302_TRICKLE_CHARGE
-	int "DS1302 Trickle charger value"
-	depends on ETRAX_DS1302
-	default "0"
-	help
-	  This controls the initial value of the trickle charge register.
-	  0 = disabled (use this if you are unsure or have a non rechargeable battery)
-	  Otherwise the following values can be OR:ed together to control the
-	  charge current:
-	  1 = 2kohm, 2 = 4kohm, 3 = 4kohm
-	  4 = 1 diode, 8 = 2 diodes
-	  Allowed values are (increasing current): 0, 11, 10, 9, 7, 6, 5
-
 endif
diff --git a/arch/cris/arch-v10/drivers/Makefile b/arch/cris/arch-v10/drivers/Makefile
index 44bf2e8..e5c1318 100644
--- a/arch/cris/arch-v10/drivers/Makefile
+++ b/arch/cris/arch-v10/drivers/Makefile
@@ -6,7 +6,5 @@ obj-$(CONFIG_ETRAX_AXISFLASHMAP)	+= axisflashmap.o
 obj-$(CONFIG_ETRAX_I2C)			+= i2c.o
 obj-$(CONFIG_ETRAX_I2C_EEPROM)		+= eeprom.o
 obj-$(CONFIG_ETRAX_GPIO)		+= gpio.o
-obj-$(CONFIG_ETRAX_DS1302)		+= ds1302.o
-obj-$(CONFIG_ETRAX_PCF8563)		+= pcf8563.o
 obj-$(CONFIG_ETRAX_SYNCHRONOUS_SERIAL)	+= sync_serial.o
 
diff --git a/arch/cris/arch-v10/kernel/fasttimer.c b/arch/cris/arch-v10/kernel/fasttimer.c
index 082f189..52bb9b5 100644
--- a/arch/cris/arch-v10/kernel/fasttimer.c
+++ b/arch/cris/arch-v10/kernel/fasttimer.c
@@ -491,7 +491,6 @@ void schedule_usleep(unsigned long us)
 #ifdef CONFIG_PROC_FS
 static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len
                        ,int *eof, void *data_unused);
-static struct proc_dir_entry *fasttimer_proc_entry;
 #endif /* CONFIG_PROC_FS */
 
 #ifdef CONFIG_PROC_FS
@@ -857,8 +856,7 @@ int fast_timer_init(void)
     }
 #endif
 #ifdef CONFIG_PROC_FS
-   if ((fasttimer_proc_entry = create_proc_entry( "fasttimer", 0, 0 )))
-     fasttimer_proc_entry->read_proc = proc_fasttimer_read;
+   create_proc_read_entry("fasttimer", 0, NULL, proc_fasttimer_read, NULL);
 #endif /* PROC_FS */
     if(request_irq(TIMER1_IRQ_NBR, timer1_handler, 0,
                    "fast timer int", NULL))
diff --git a/arch/cris/arch-v32/drivers/Kconfig b/arch/cris/arch-v32/drivers/Kconfig
index af4a486..c55971a 100644
--- a/arch/cris/arch-v32/drivers/Kconfig
+++ b/arch/cris/arch-v32/drivers/Kconfig
@@ -404,7 +404,6 @@ config ETRAX_AXISFLASHMAP
 	select MTD_CFI
 	select MTD_CFI_AMDSTD
 	select MTD_JEDECPROBE
-	select MTD_CHAR
 	select MTD_BLOCK
 	select MTD_COMPLEX_MAPPINGS
 	help
diff --git a/arch/cris/arch-v32/kernel/fasttimer.c b/arch/cris/arch-v32/kernel/fasttimer.c
index ab1551e..dd1c998 100644
--- a/arch/cris/arch-v32/kernel/fasttimer.c
+++ b/arch/cris/arch-v32/kernel/fasttimer.c
@@ -465,7 +465,6 @@ void schedule_usleep(unsigned long us)
 #ifdef CONFIG_PROC_FS
 static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len
                        ,int *eof, void *data_unused);
-static struct proc_dir_entry *fasttimer_proc_entry;
 #endif /* CONFIG_PROC_FS */
 
 #ifdef CONFIG_PROC_FS
@@ -816,9 +815,7 @@ int fast_timer_init(void)
     printk("fast_timer_init()\n");
 
 #ifdef CONFIG_PROC_FS
-    fasttimer_proc_entry = create_proc_entry("fasttimer", 0, 0);
-    if (fasttimer_proc_entry)
-      fasttimer_proc_entry->read_proc = proc_fasttimer_read;
+    create_proc_read_entry("fasttimer", 0, NULL, proc_fasttimer_read, NULL);
 #endif /* PROC_FS */
 		if (request_irq(TIMER0_INTR_VECT, timer_trig_interrupt,
 				IRQF_SHARED | IRQF_DISABLED,
diff --git a/arch/cris/arch-v32/mach-a3/cpufreq.c b/arch/cris/arch-v32/mach-a3/cpufreq.c
index ee391ec..ee142c4 100644
--- a/arch/cris/arch-v32/mach-a3/cpufreq.c
+++ b/arch/cris/arch-v32/mach-a3/cpufreq.c
@@ -27,23 +27,17 @@ static unsigned int cris_freq_get_cpu_frequency(unsigned int cpu)
 	return clk_ctrl.pll ? 200000 : 6000;
 }
 
-static void cris_freq_set_cpu_state(unsigned int state)
+static void cris_freq_set_cpu_state(struct cpufreq_policy *policy,
+		unsigned int state)
 {
-	int i = 0;
 	struct cpufreq_freqs freqs;
 	reg_clkgen_rw_clk_ctrl clk_ctrl;
 	clk_ctrl = REG_RD(clkgen, regi_clkgen, rw_clk_ctrl);
 
-#ifdef CONFIG_SMP
-	for_each_present_cpu(i)
-#endif
-	{
-		freqs.old = cris_freq_get_cpu_frequency(i);
-		freqs.new = cris_freq_table[state].frequency;
-		freqs.cpu = i;
-	}
+	freqs.old = cris_freq_get_cpu_frequency(policy->cpu);
+	freqs.new = cris_freq_table[state].frequency;
 
-	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
 
 	local_irq_disable();
 
@@ -57,7 +51,7 @@ static void cris_freq_set_cpu_state(unsigned int state)
 
 	local_irq_enable();
 
-	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
 };
 
 static int cris_freq_verify(struct cpufreq_policy *policy)
@@ -75,7 +69,7 @@ static int cris_freq_target(struct cpufreq_policy *policy,
 			target_freq, relation, &newstate))
 		return -EINVAL;
 
-	cris_freq_set_cpu_state(newstate);
+	cris_freq_set_cpu_state(policy, newstate);
 
 	return 0;
 }
diff --git a/arch/cris/arch-v32/mach-fs/cpufreq.c b/arch/cris/arch-v32/mach-fs/cpufreq.c
index d92cf70..1295223 100644
--- a/arch/cris/arch-v32/mach-fs/cpufreq.c
+++ b/arch/cris/arch-v32/mach-fs/cpufreq.c
@@ -27,20 +27,17 @@ static unsigned int cris_freq_get_cpu_frequency(unsigned int cpu)
 	return clk_ctrl.pll ? 200000 : 6000;
 }
 
-static void cris_freq_set_cpu_state(unsigned int state)
+static void cris_freq_set_cpu_state(struct cpufreq_policy *policy,
+		unsigned int state)
 {
-	int i;
 	struct cpufreq_freqs freqs;
 	reg_config_rw_clk_ctrl clk_ctrl;
 	clk_ctrl = REG_RD(config, regi_config, rw_clk_ctrl);
 
-	for_each_possible_cpu(i) {
-		freqs.old = cris_freq_get_cpu_frequency(i);
-		freqs.new = cris_freq_table[state].frequency;
-		freqs.cpu = i;
-	}
+	freqs.old = cris_freq_get_cpu_frequency(policy->cpu);
+	freqs.new = cris_freq_table[state].frequency;
 
-	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
 
 	local_irq_disable();
 
@@ -54,7 +51,7 @@ static void cris_freq_set_cpu_state(unsigned int state)
 
 	local_irq_enable();
 
-	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
 };
 
 static int cris_freq_verify(struct cpufreq_policy *policy)
@@ -71,7 +68,7 @@ static int cris_freq_target(struct cpufreq_policy *policy,
 	    (policy, cris_freq_table, target_freq, relation, &newstate))
 		return -EINVAL;
 
-	cris_freq_set_cpu_state(newstate);
+	cris_freq_set_cpu_state(policy, newstate);
 
 	return 0;
 }
diff --git a/arch/cris/include/asm/unistd.h b/arch/cris/include/asm/unistd.h
index be57a98..0ff3f68 100644
--- a/arch/cris/include/asm/unistd.h
+++ b/arch/cris/include/asm/unistd.h
@@ -34,12 +34,4 @@
 #define __ARCH_WANT_SYS_VFORK
 #define __ARCH_WANT_SYS_CLONE
 
-/*
- * "Conditional" syscalls
- *
- * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
- * but it doesn't work on all toolchains, so we just do it by hand
- */
-#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
-
 #endif /* _ASM_CRIS_UNISTD_H_ */
diff --git a/arch/cris/include/uapi/asm/socket.h b/arch/cris/include/uapi/asm/socket.h
index 50692b7..ba409c9 100644
--- a/arch/cris/include/uapi/asm/socket.h
+++ b/arch/cris/include/uapi/asm/socket.h
@@ -74,6 +74,8 @@
 
 #define SO_LOCK_FILTER		44
 
+#define SO_SELECT_ERR_QUEUE	45
+
 #endif /* _ASM_SOCKET_H */
 
 
diff --git a/arch/cris/mm/init.c b/arch/cris/mm/init.c
index d72ab58..9ac8094 100644
--- a/arch/cris/mm/init.c
+++ b/arch/cris/mm/init.c
@@ -12,12 +12,10 @@
 #include <linux/init.h>
 #include <linux/bootmem.h>
 #include <asm/tlb.h>
+#include <asm/sections.h>
 
 unsigned long empty_zero_page;
 
-extern char _stext, _edata, _etext; /* From linkerscript */
-extern char __init_begin, __init_end;
-
 void __init
 mem_init(void)
 {
@@ -67,15 +65,5 @@ mem_init(void)
 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 - &__init_begin) >> 10));
+	free_initmem_default(0);
 }
diff --git a/arch/frv/include/asm/unistd.h b/arch/frv/include/asm/unistd.h
index 4cfcc7b..70ec729 100644
--- a/arch/frv/include/asm/unistd.h
+++ b/arch/frv/include/asm/unistd.h
@@ -31,14 +31,4 @@
 #define __ARCH_WANT_SYS_VFORK
 #define __ARCH_WANT_SYS_CLONE
 
-/*
- * "Conditional" syscalls
- *
- * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
- * but it doesn't work on all toolchains, so we just do it by hand
- */
-#ifndef cond_syscall
-#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
-#endif
-
 #endif /* _ASM_UNISTD_H_ */
diff --git a/arch/frv/include/uapi/asm/socket.h b/arch/frv/include/uapi/asm/socket.h
index 595391f..31dbb5d 100644
--- a/arch/frv/include/uapi/asm/socket.h
+++ b/arch/frv/include/uapi/asm/socket.h
@@ -72,5 +72,7 @@
 
 #define SO_LOCK_FILTER		44
 
+#define SO_SELECT_ERR_QUEUE	45
+
 #endif /* _ASM_SOCKET_H */
 
diff --git a/arch/frv/mm/init.c b/arch/frv/mm/init.c
index 92e97b0..dee354f 100644
--- a/arch/frv/mm/init.c
+++ b/arch/frv/mm/init.c
@@ -122,7 +122,7 @@ void __init mem_init(void)
 #endif
 	int codek = 0, datak = 0;
 
-	/* this will put all memory onto the freelists */
+	/* this will put all low memory onto the freelists */
 	totalram_pages = free_all_bootmem();
 
 #ifdef CONFIG_MMU
@@ -131,14 +131,8 @@ void __init mem_init(void)
 			datapages++;
 
 #ifdef CONFIG_HIGHMEM
-	for (pfn = num_physpages - 1; pfn >= num_mappedpages; pfn--) {
-		struct page *page = &mem_map[pfn];
-
-		ClearPageReserved(page);
-		init_page_count(page);
-		__free_page(page);
-		totalram_pages++;
-	}
+	for (pfn = num_physpages - 1; pfn >= num_mappedpages; pfn--)
+		free_highmem_page(&mem_map[pfn]);
 #endif
 
 	codek = ((unsigned long) &_etext - (unsigned long) &_stext) >> 10;
@@ -168,21 +162,7 @@ void __init mem_init(void)
 void free_initmem(void)
 {
 #if defined(CONFIG_RAMKERNEL) && !defined(CONFIG_PROTECT_KERNEL)
-	unsigned long start, end, addr;
-
-	start = PAGE_ALIGN((unsigned long) &__init_begin);	/* round up */
-	end   = ((unsigned long) &__init_end) & PAGE_MASK;	/* round down */
-
-	/* next to check that the page we free is not a partial page */
-	for (addr = start; addr < end; addr += PAGE_SIZE) {
-		ClearPageReserved(virt_to_page(addr));
-		init_page_count(virt_to_page(addr));
-		free_page(addr);
-		totalram_pages++;
-	}
-
-	printk("Freeing unused kernel memory: %ldKiB freed (0x%lx - 0x%lx)\n",
-	       (end - start) >> 10, start, end);
+	free_initmem_default(0);
 #endif
 } /* end free_initmem() */
 
@@ -193,14 +173,6 @@ void free_initmem(void)
 #ifdef CONFIG_BLK_DEV_INITRD
 void __init free_initrd_mem(unsigned long start, unsigned long end)
 {
-	int pages = 0;
-	for (; start < end; start += PAGE_SIZE) {
-		ClearPageReserved(virt_to_page(start));
-		init_page_count(virt_to_page(start));
-		free_page(start);
-		totalram_pages++;
-		pages++;
-	}
-	printk("Freeing initrd memory: %dKiB freed\n", (pages * PAGE_SIZE) >> 10);
+	free_reserved_area(start, end, 0, "initrd");
 } /* end free_initrd_mem() */
 #endif
diff --git a/arch/h8300/Kconfig b/arch/h8300/Kconfig
index 79250de..303e4f9 100644
--- a/arch/h8300/Kconfig
+++ b/arch/h8300/Kconfig
@@ -12,10 +12,7 @@ config H8300
 	select MODULES_USE_ELF_RELA
 	select OLD_SIGSUSPEND3
 	select OLD_SIGACTION
-
-config SYMBOL_PREFIX
-	string
-	default "_"
+	select HAVE_UNDERSCORE_SYMBOL_PREFIX
 
 config MMU
 	bool
diff --git a/arch/h8300/include/asm/linkage.h b/arch/h8300/include/asm/linkage.h
index 6f4df7d..1d81604 100644
--- a/arch/h8300/include/asm/linkage.h
+++ b/arch/h8300/include/asm/linkage.h
@@ -2,7 +2,5 @@
 #define _H8300_LINKAGE_H
 
 #undef SYMBOL_NAME_LABEL
-#undef SYMBOL_NAME
 #define SYMBOL_NAME_LABEL(_name_) _##_name_##:
-#define SYMBOL_NAME(_name_) _##_name_
 #endif
diff --git a/arch/h8300/include/asm/unistd.h b/arch/h8300/include/asm/unistd.h
index 6721856..ab671ec 100644
--- a/arch/h8300/include/asm/unistd.h
+++ b/arch/h8300/include/asm/unistd.h
@@ -33,11 +33,4 @@
 #define __ARCH_WANT_SYS_VFORK
 #define __ARCH_WANT_SYS_CLONE
 
-/*
- * "Conditional" syscalls
- */
-#define cond_syscall(name)						\
-  asm (".weak\t_" #name "\n"				\
-       ".set\t_" #name ",_sys_ni_syscall");
-
 #endif /* _ASM_H8300_UNISTD_H_ */
diff --git a/arch/h8300/include/uapi/asm/socket.h b/arch/h8300/include/uapi/asm/socket.h
index 43e3262..5d1c6d0 100644
--- a/arch/h8300/include/uapi/asm/socket.h
+++ b/arch/h8300/include/uapi/asm/socket.h
@@ -72,4 +72,6 @@
 
 #define SO_LOCK_FILTER		44
 
+#define SO_SELECT_ERR_QUEUE	45
+
 #endif /* _ASM_SOCKET_H */
diff --git a/arch/h8300/kernel/gpio.c b/arch/h8300/kernel/gpio.c
index 6a25dd5..f8a4f5b 100644
--- a/arch/h8300/kernel/gpio.c
+++ b/arch/h8300/kernel/gpio.c
@@ -158,9 +158,8 @@ static __init int register_proc(void)
 {
 	struct proc_dir_entry *proc_gpio;
 
-	proc_gpio = create_proc_entry("gpio", S_IRUGO, NULL);
-	if (proc_gpio) 
-		proc_gpio->read_proc = gpio_proc_read;
+	proc_gpio = create_proc_read_entry("gpio", S_IRUGO, NULL,
+					gpio_proc_read, NULL);
 	return proc_gpio != NULL;
 }
 
diff --git a/arch/h8300/mm/init.c b/arch/h8300/mm/init.c
index 981e250..ff349d7 100644
--- a/arch/h8300/mm/init.c
+++ b/arch/h8300/mm/init.c
@@ -139,7 +139,7 @@ void __init mem_init(void)
 	start_mem = PAGE_ALIGN(start_mem);
 	max_mapnr = num_physpages = MAP_NR(high_memory);
 
-	/* this will put all memory onto the freelists */
+	/* this will put all low memory onto the freelists */
 	totalram_pages = free_all_bootmem();
 
 	codek = (_etext - _stext) >> 10;
@@ -161,15 +161,7 @@ void __init mem_init(void)
 #ifdef CONFIG_BLK_DEV_INITRD
 void free_initrd_mem(unsigned long start, unsigned long end)
 {
-	int pages = 0;
-	for (; start < end; start += PAGE_SIZE) {
-		ClearPageReserved(virt_to_page(start));
-		init_page_count(virt_to_page(start));
-		free_page(start);
-		totalram_pages++;
-		pages++;
-	}
-	printk ("Freeing initrd memory: %dk freed\n", pages);
+	free_reserved_area(start, end, 0, "initrd");
 }
 #endif
 
@@ -177,23 +169,7 @@ void
 free_initmem(void)
 {
 #ifdef CONFIG_RAMKERNEL
-	unsigned long addr;
-/*
- *	the following code should be cool even if these sections
- *	are not page aligned.
- */
-	addr = PAGE_ALIGN((unsigned long)(__init_begin));
-	/* next to check that the page we free is not a partial page */
-	for (; addr + PAGE_SIZE < (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: %ldk freed (0x%x - 0x%x)\n",
-			(addr - PAGE_ALIGN((long) __init_begin)) >> 10,
-			(int)(PAGE_ALIGN((unsigned long)__init_begin)),
-			(int)(addr - PAGE_SIZE));
+	free_initmem_default(0);
 #endif
 }
 
diff --git a/arch/hexagon/Kconfig b/arch/hexagon/Kconfig
index e4decc6..04dff5b 100644
--- a/arch/hexagon/Kconfig
+++ b/arch/hexagon/Kconfig
@@ -29,21 +29,17 @@ config HEXAGON
 	select GENERIC_CLOCKEVENTS
 	select GENERIC_CLOCKEVENTS_BROADCAST
 	select MODULES_USE_ELF_RELA
+	select GENERIC_CPU_DEVICES
+	select GENERIC_KERNEL_THREAD
+	select GENERIC_KERNEL_EXECVE
 	---help---
 	  Qualcomm Hexagon is a processor architecture designed for high
 	  performance and low power across a wide variety of applications.
 
-config HEXAGON_ARCH_V1
-	bool
-
-config HEXAGON_ARCH_V2
-	bool
-
-config HEXAGON_ARCH_V3
-	bool
-
-config HEXAGON_ARCH_V4
-	bool
+config HEXAGON_PHYS_OFFSET
+	def_bool y
+	---help---
+	  Platforms that don't load the kernel at zero set this.
 
 config FRAME_POINTER
 	def_bool y
@@ -81,9 +77,6 @@ config RWSEM_GENERIC_SPINLOCK
 config RWSEM_XCHGADD_ALGORITHM
 	def_bool y
 
-config GENERIC_FIND_NEXT_BIT
-	def_bool y
-
 config GENERIC_HWEIGHT
 	def_bool y
 
@@ -103,14 +96,14 @@ choice
 
 config HEXAGON_COMET
 	bool "Comet Board"
-	select HEXAGON_ARCH_V2
 	---help---
 	  Support for the Comet platform.
 
 endchoice
 
-config HEXAGON_VM
-	def_bool y
+config HEXAGON_ARCH_VERSION
+	int "Architecture version"
+	default 2
 
 config CMDLINE
 	string "Default kernel command string"
@@ -122,12 +115,6 @@ config CMDLINE
 	  minimum, you should specify the memory size and the root device
 	  (e.g., mem=64M root=/dev/nfs).
 
-config HEXAGON_ANGEL_TRAPS
-	bool "Use Angel Traps"
-	default n
-	---help---
-	  Enable angel debug traps (for printk's).
-
 config SMP
 	bool "Multi-Processing support"
 	---help---
diff --git a/arch/hexagon/Makefile b/arch/hexagon/Makefile
index d00d900..207711a0 100644
--- a/arch/hexagon/Makefile
+++ b/arch/hexagon/Makefile
@@ -15,20 +15,9 @@ KBUILD_CFLAGS += -fno-short-enums
 # LDFLAGS_MODULE += -shared
 CFLAGS_MODULE += -mlong-calls
 
-cflags-$(CONFIG_HEXAGON_ARCH_V1) += $(call cc-option,-mv1)
-cflags-$(CONFIG_HEXAGON_ARCH_V2) += $(call cc-option,-mv2)
-cflags-$(CONFIG_HEXAGON_ARCH_V3) += $(call cc-option,-mv3)
-cflags-$(CONFIG_HEXAGON_ARCH_V4) += $(call cc-option,-mv4)
-
-aflags-$(CONFIG_HEXAGON_ARCH_V1) += $(call cc-option,-mv1)
-aflags-$(CONFIG_HEXAGON_ARCH_V2) += $(call cc-option,-mv2)
-aflags-$(CONFIG_HEXAGON_ARCH_V3) += $(call cc-option,-mv3)
-aflags-$(CONFIG_HEXAGON_ARCH_V4) += $(call cc-option,-mv4)
-
-ldflags-$(CONFIG_HEXAGON_ARCH_V1) += $(call cc-option,-mv1)
-ldflags-$(CONFIG_HEXAGON_ARCH_V2) += $(call cc-option,-mv2)
-ldflags-$(CONFIG_HEXAGON_ARCH_V3) += $(call cc-option,-mv3)
-ldflags-$(CONFIG_HEXAGON_ARCH_V4) += $(call cc-option,-mv4)
+cflags-y += $(call cc-option,-mv${CONFIG_HEXAGON_ARCH_VERSION})
+aflags-y += $(call cc-option,-mv${CONFIG_HEXAGON_ARCH_VERSION})
+ldflags-y += $(call cc-option,-mv${CONFIG_HEXAGON_ARCH_VERSION})
 
 KBUILD_CFLAGS += $(cflags-y)
 KBUILD_AFLAGS += $(aflags-y)
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
index bdb54ce..1da17ca 100644
--- a/arch/hexagon/include/asm/Kbuild
+++ b/arch/hexagon/include/asm/Kbuild
@@ -25,7 +25,6 @@ generic-y += kdebug.h
 generic-y += kmap_types.h
 generic-y += local64.h
 generic-y += local.h
-generic-y += local.h
 generic-y += mman.h
 generic-y += msgbuf.h
 generic-y += pci.h
@@ -41,6 +40,7 @@ generic-y += sembuf.h
 generic-y += shmbuf.h
 generic-y += shmparam.h
 generic-y += siginfo.h
+generic-y += sizes.h
 generic-y += socket.h
 generic-y += sockios.h
 generic-y += statfs.h
diff --git a/arch/hexagon/include/asm/atomic.h b/arch/hexagon/include/asm/atomic.h
index 468fbb0..8a64ff2 100644
--- a/arch/hexagon/include/asm/atomic.h
+++ b/arch/hexagon/include/asm/atomic.h
@@ -1,7 +1,7 @@
 /*
  * Atomic operations for the Hexagon architecture
  *
- * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
  *
  *
  * This program is free software; you can redistribute it and/or modify
@@ -117,35 +117,37 @@ static inline int atomic_sub_return(int i, atomic_t *v)
 #define atomic_sub(i, v) atomic_sub_return(i, (v))
 
 /**
- * atomic_add_unless - add unless the number is a given value
+ * __atomic_add_unless - add unless the number is a given value
  * @v: pointer to value
  * @a: amount to add
  * @u: unless value is equal to u
  *
- * Returns 1 if the add happened, 0 if it didn't.
+ * Returns old value.
+ *
  */
+
 static inline int __atomic_add_unless(atomic_t *v, int a, int u)
 {
-	int output, __oldval;
+	int __oldval;
+	register int tmp;
+
 	asm volatile(
 		"1:	%0 = memw_locked(%2);"
 		"	{"
 		"		p3 = cmp.eq(%0, %4);"
 		"		if (p3.new) jump:nt 2f;"
-		"		%0 = add(%0, %3);"
-		"		%1 = #0;"
+		"		%1 = add(%0, %3);"
 		"	}"
-		"	memw_locked(%2, p3) = %0;"
+		"	memw_locked(%2, p3) = %1;"
 		"	{"
 		"		if !p3 jump 1b;"
-		"		%1 = #1;"
 		"	}"
 		"2:"
-		: "=&r" (__oldval), "=&r" (output)
+		: "=&r" (__oldval), "=&r" (tmp)
 		: "r" (v), "r" (a), "r" (u)
 		: "memory", "p3"
 	);
-	return output;
+	return __oldval;
 }
 
 #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
diff --git a/arch/hexagon/include/asm/elf.h b/arch/hexagon/include/asm/elf.h
index 1f14e08..f52d8ec 100644
--- a/arch/hexagon/include/asm/elf.h
+++ b/arch/hexagon/include/asm/elf.h
@@ -1,7 +1,7 @@
 /*
  * ELF definitions for the Hexagon architecture
  *
- * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2010-2012, The Linux Foundation. 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
@@ -168,15 +168,15 @@ do {					\
 #define ELF_DATA	ELFDATA2LSB
 #define ELF_ARCH	EM_HEXAGON
 
-#ifdef CONFIG_HEXAGON_ARCH_V2
+#if CONFIG_HEXAGON_ARCH_VERSION == 2
 #define ELF_CORE_EFLAGS 0x1
 #endif
 
-#ifdef CONFIG_HEXAGON_ARCH_V3
+#if CONFIG_HEXAGON_ARCH_VERSION == 3
 #define ELF_CORE_EFLAGS 0x2
 #endif
 
-#ifdef CONFIG_HEXAGON_ARCH_V4
+#if CONFIG_HEXAGON_ARCH_VERSION == 4
 #define ELF_CORE_EFLAGS 0x3
 #endif
 
diff --git a/arch/hexagon/include/asm/hexagon_vm.h b/arch/hexagon/include/asm/hexagon_vm.h
index c144bee..67bb6d6 100644
--- a/arch/hexagon/include/asm/hexagon_vm.h
+++ b/arch/hexagon/include/asm/hexagon_vm.h
@@ -1,7 +1,7 @@
 /*
  * Declarations for to Hexagon Virtal Machine.
  *
- * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2010-2013, The Linux Foundation. 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
@@ -31,10 +31,26 @@
  * for tracing/debugging.
  */
 
-/*
- * Lets make this stuff visible only if configured,
- * so we can unconditionally include the file.
- */
+#define HVM_TRAP1_VMVERSION		0
+#define HVM_TRAP1_VMRTE			1
+#define HVM_TRAP1_VMSETVEC		2
+#define HVM_TRAP1_VMSETIE		3
+#define HVM_TRAP1_VMGETIE		4
+#define HVM_TRAP1_VMINTOP		5
+#define HVM_TRAP1_VMCLRMAP		10
+#define HVM_TRAP1_VMNEWMAP		11
+#define HVM_TRAP1_FORMERLY_VMWIRE	12
+#define HVM_TRAP1_VMCACHE		13
+#define HVM_TRAP1_VMGETTIME		14
+#define HVM_TRAP1_VMSETTIME		15
+#define HVM_TRAP1_VMWAIT		16
+#define HVM_TRAP1_VMYIELD		17
+#define HVM_TRAP1_VMSTART		18
+#define HVM_TRAP1_VMSTOP		19
+#define HVM_TRAP1_VMVPID		20
+#define HVM_TRAP1_VMSETREGS		21
+#define HVM_TRAP1_VMGETREGS		22
+#define HVM_TRAP1_VMTIMEROP		24
 
 #ifndef __ASSEMBLY__
 
@@ -175,31 +191,19 @@ static inline long __vmintop_clear(long i)
 
 #else /* Only assembly code should reference these */
 
-#define HVM_TRAP1_VMRTE			1
-#define HVM_TRAP1_VMSETVEC		2
-#define HVM_TRAP1_VMSETIE		3
-#define HVM_TRAP1_VMGETIE		4
-#define HVM_TRAP1_VMINTOP		5
-#define HVM_TRAP1_VMCLRMAP		10
-#define HVM_TRAP1_VMNEWMAP		11
-#define HVM_TRAP1_FORMERLY_VMWIRE	12
-#define HVM_TRAP1_VMCACHE		13
-#define HVM_TRAP1_VMGETTIME		14
-#define HVM_TRAP1_VMSETTIME		15
-#define HVM_TRAP1_VMWAIT		16
-#define HVM_TRAP1_VMYIELD		17
-#define HVM_TRAP1_VMSTART		18
-#define HVM_TRAP1_VMSTOP		19
-#define HVM_TRAP1_VMVPID		20
-#define HVM_TRAP1_VMSETREGS		21
-#define HVM_TRAP1_VMGETREGS		22
-
 #endif /* __ASSEMBLY__ */
 
 /*
  * Constants for virtual instruction parameters and return values
  */
 
+/* vmnewmap arguments */
+
+#define VM_TRANS_TYPE_LINEAR 0
+#define VM_TRANS_TYPE_TABLE 1
+#define VM_TLB_INVALIDATE_FALSE 0
+#define VM_TLB_INVALIDATE_TRUE 1
+
 /* vmsetie arguments */
 
 #define VM_INT_DISABLE	0
@@ -224,6 +228,8 @@ static inline long __vmintop_clear(long i)
 #define HVM_VMEST_UM_MSK	1
 #define HVM_VMEST_IE_SFT	30
 #define HVM_VMEST_IE_MSK	1
+#define HVM_VMEST_SS_SFT	29
+#define HVM_VMEST_SS_MSK	1
 #define HVM_VMEST_EVENTNUM_SFT	16
 #define HVM_VMEST_EVENTNUM_MSK	0xff
 #define HVM_VMEST_CAUSE_SFT	0
@@ -260,6 +266,8 @@ static inline long __vmintop_clear(long i)
 #define HVM_GE_C_INVI	0x15
 #define HVM_GE_C_PRIVI	0x1B
 #define HVM_GE_C_XMAL	0x1C
+#define HVM_GE_C_WREG	0x1D
+#define HVM_GE_C_PCAL	0x1E
 #define HVM_GE_C_RMAL	0x20
 #define HVM_GE_C_WMAL	0x21
 #define HVM_GE_C_RPROT	0x22
diff --git a/arch/hexagon/include/asm/io.h b/arch/hexagon/include/asm/io.h
index e527cfe..1b7698e 100644
--- a/arch/hexagon/include/asm/io.h
+++ b/arch/hexagon/include/asm/io.h
@@ -1,7 +1,7 @@
 /*
  * IO definitions for the Hexagon architecture
  *
- * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2010-2013, The Linux Foundation. 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
@@ -40,6 +40,8 @@
 #define IO_SPACE_LIMIT 0xffff
 #define _IO_BASE ((void __iomem *)0xfe000000)
 
+#define IOMEM(x)        ((void __force __iomem *)(x))
+
 extern int remap_area_pages(unsigned long start, unsigned long phys_addr,
 				unsigned long end, unsigned long flags);
 
@@ -176,6 +178,18 @@ static inline void writel(u32 data, volatile void __iomem *addr)
 #define __raw_readl readl
 
 /*
+ * http://comments.gmane.org/gmane.linux.ports.arm.kernel/117626
+ */
+
+#define readb_relaxed __raw_readb
+#define readw_relaxed __raw_readw
+#define readl_relaxed __raw_readl
+
+#define writeb_relaxed __raw_writeb
+#define writew_relaxed __raw_writew
+#define writel_relaxed __raw_writel
+
+/*
  * Need an mtype somewhere in here, for cache type deals?
  * This is probably too long for an inline.
  */
diff --git a/arch/hexagon/include/asm/mem-layout.h b/arch/hexagon/include/asm/mem-layout.h
index af16e97..2cb7a70 100644
--- a/arch/hexagon/include/asm/mem-layout.h
+++ b/arch/hexagon/include/asm/mem-layout.h
@@ -1,7 +1,7 @@
 /*
  * Memory layout definitions for the Hexagon architecture
  *
- * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2010-2013, The Linux Foundation. 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
@@ -32,16 +32,25 @@
 #define PAGE_OFFSET			_AC(0xc0000000, UL)
 
 /*
- * LOAD_ADDRESS is the physical/linear address of where in memory
- * the kernel gets loaded. The 12 least significant bits must be zero (0)
- * due to limitations on setting the EVB
- *
+ * Compiling for a platform that needs a crazy physical offset
+ * (like if the memory starts at 1GB and up) means we need
+ * an actual PHYS_OFFSET.  Should be set up in head.S.
  */
 
-#ifndef LOAD_ADDRESS
-#define LOAD_ADDRESS			0x00000000
+#ifdef CONFIG_HEXAGON_PHYS_OFFSET
+#ifndef __ASSEMBLY__
+extern unsigned long	__phys_offset;
+#endif
+#define PHYS_OFFSET	__phys_offset
+#endif
+
+#ifndef PHYS_OFFSET
+#define PHYS_OFFSET	0
 #endif
 
+#define PHYS_PFN_OFFSET	(PHYS_OFFSET >> PAGE_SHIFT)
+#define ARCH_PFN_OFFSET	PHYS_PFN_OFFSET
+
 #define TASK_SIZE			(PAGE_OFFSET)
 
 /*  not sure how these are used yet  */
@@ -55,7 +64,7 @@ enum fixed_addresses {
 	__end_of_fixed_addresses
 };
 
-#define MIN_KERNEL_SEG 0x300   /* From 0xc0000000 */
+#define MIN_KERNEL_SEG (PAGE_OFFSET >> PGDIR_SHIFT)   /* L1 shift is 22 bits */
 extern int max_kernel_seg;
 
 /*
diff --git a/arch/hexagon/include/asm/page.h b/arch/hexagon/include/asm/page.h
index 692adc213..f3b26f1 100644
--- a/arch/hexagon/include/asm/page.h
+++ b/arch/hexagon/include/asm/page.h
@@ -1,7 +1,7 @@
 /*
  * Page management definitions for the Hexagon architecture
  *
- * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2010-2013, The Linux Foundation. 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
@@ -96,8 +96,8 @@ typedef struct page *pgtable_t;
  * MIPS says they're only used during mem_init.
  * also, check if we need a PHYS_OFFSET.
  */
-#define __pa(x) ((unsigned long)(x) - PAGE_OFFSET)
-#define __va(x) ((void *)((unsigned long)(x) + PAGE_OFFSET))
+#define __pa(x) ((unsigned long)(x) - PAGE_OFFSET + PHYS_OFFSET)
+#define __va(x) ((void *)((unsigned long)(x) - PHYS_OFFSET + PAGE_OFFSET))
 
 /* The "page frame" descriptor is defined in linux/mm.h */
 struct page;
@@ -147,6 +147,7 @@ static inline void clear_page(void *page)
  */
 #define kern_addr_valid(addr)   (1)
 
+#include <asm/mem-layout.h>
 #include <asm-generic/memory_model.h>
 /* XXX Todo: implement assembly-optimized version of getorder. */
 #include <asm-generic/getorder.h>
diff --git a/arch/hexagon/include/asm/processor.h b/arch/hexagon/include/asm/processor.h
index 6dd5d37..45a8254 100644
--- a/arch/hexagon/include/asm/processor.h
+++ b/arch/hexagon/include/asm/processor.h
@@ -1,7 +1,7 @@
 /*
  * Process/processor support for the Hexagon architecture
  *
- * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2010-2012, The Linux Foundation. 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
@@ -100,12 +100,49 @@ extern unsigned long get_wchan(struct task_struct *p);
  */
 
 struct hexagon_switch_stack {
-	unsigned long long	r1716;
-	unsigned long long	r1918;
-	unsigned long long	r2120;
-	unsigned long long	r2322;
-	unsigned long long	r2524;
-	unsigned long long	r2726;
+	union {
+		struct {
+			unsigned long r16;
+			unsigned long r17;
+		};
+		unsigned long long	r1716;
+	};
+	union {
+		struct {
+			unsigned long r18;
+			unsigned long r19;
+		};
+		unsigned long long	r1918;
+	};
+	union {
+		struct {
+			unsigned long r20;
+			unsigned long r21;
+		};
+		unsigned long long	r2120;
+	};
+	union {
+		struct {
+			unsigned long r22;
+			unsigned long r23;
+		};
+		unsigned long long	r2322;
+	};
+	union {
+		struct {
+			unsigned long r24;
+			unsigned long r25;
+		};
+		unsigned long long	r2524;
+	};
+	union {
+		struct {
+			unsigned long r26;
+			unsigned long r27;
+		};
+		unsigned long long	r2726;
+	};
+
 	unsigned long		fp;
 	unsigned long		lr;
 };
diff --git a/arch/hexagon/include/asm/vm_mmu.h b/arch/hexagon/include/asm/vm_mmu.h
index 9a94de7..096537d 100644
--- a/arch/hexagon/include/asm/vm_mmu.h
+++ b/arch/hexagon/include/asm/vm_mmu.h
@@ -1,7 +1,7 @@
 /*
  * Hexagon VM page table entry definitions
  *
- * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2010-2011,2013 The Linux Foundation. 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
@@ -68,14 +68,13 @@
 
 #define __HEXAGON_C_WB		0x0	/* Write-back, no L2 */
 #define	__HEXAGON_C_WT		0x1	/* Write-through, no L2 */
+#define	__HEXAGON_C_UNC		0x6	/* Uncached memory */
+#if CONFIG_HEXAGON_ARCH_VERSION >= 2
 #define	__HEXAGON_C_DEV		0x4	/* Device register space */
-#define	__HEXAGON_C_WT_L2	0x5	/* Write-through, with L2 */
-/* this really should be #if CONFIG_HEXAGON_ARCH = 2 but that's not defined */
-#if defined(CONFIG_HEXAGON_COMET) || defined(CONFIG_QDSP6_ST1)
-#define __HEXAGON_C_UNC		__HEXAGON_C_DEV
 #else
-#define	__HEXAGON_C_UNC		0x6	/* Uncached memory */
+#define __HEXAGON_C_DEV		__HEXAGON_C_UNC
 #endif
+#define	__HEXAGON_C_WT_L2	0x5	/* Write-through, with L2 */
 #define	__HEXAGON_C_WB_L2	0x7	/* Write-back, with L2 */
 
 /*
diff --git a/arch/hexagon/include/uapi/asm/ptrace.h b/arch/hexagon/include/uapi/asm/ptrace.h
index 1ffce0c..065e5b3 100644
--- a/arch/hexagon/include/uapi/asm/ptrace.h
+++ b/arch/hexagon/include/uapi/asm/ptrace.h
@@ -36,4 +36,9 @@ extern const char *regs_query_register_name(unsigned int offset);
 	((struct pt_regs *) \
 	 ((unsigned long)current_thread_info() + THREAD_SIZE) - 1)
 
+#if CONFIG_HEXAGON_ARCH_VERSION >= 4
+#define arch_has_single_step()	(1)
+#endif
+
+
 #endif
diff --git a/arch/hexagon/include/uapi/asm/registers.h b/arch/hexagon/include/uapi/asm/registers.h
index c20406f..487d6ce 100644
--- a/arch/hexagon/include/uapi/asm/registers.h
+++ b/arch/hexagon/include/uapi/asm/registers.h
@@ -57,10 +57,17 @@ struct pt_regs {
 	};
 	union {
 		struct {
-			unsigned long gp;
 			unsigned long ugp;
+			unsigned long gp;
 		};
-		long long int ugpgp;
+		long long int gpugp;
+	};
+	union {
+		struct {
+			unsigned long cs0;
+			unsigned long cs1;
+		};
+		long long int cs1cs0;
 	};
 	/*
 	* Be extremely careful with rearranging these, if at all.  Some code
@@ -204,9 +211,11 @@ struct pt_regs {
 #define pt_psp(regs) ((regs)->hvmer.vmpsp)
 #define pt_badva(regs) ((regs)->hvmer.vmbadva)
 
+#define pt_set_singlestep(regs) ((regs)->hvmer.vmest |= (1<<HVM_VMEST_SS_SFT))
+#define pt_clr_singlestep(regs) ((regs)->hvmer.vmest &= ~(1<<HVM_VMEST_SS_SFT))
+
 #define pt_set_rte_sp(regs, sp) do {\
-	pt_psp(regs) = (sp);\
-	(regs)->SP = (unsigned long) &((regs)->hvmer);\
+	pt_psp(regs) = (regs)->SP = (sp);\
 	} while (0)
 
 #define pt_set_kmode(regs) \
diff --git a/arch/hexagon/include/uapi/asm/signal.h b/arch/hexagon/include/uapi/asm/signal.h
index 9395568..98106e5 100644
--- a/arch/hexagon/include/uapi/asm/signal.h
+++ b/arch/hexagon/include/uapi/asm/signal.h
@@ -19,8 +19,12 @@
 #ifndef _ASM_SIGNAL_H
 #define _ASM_SIGNAL_H
 
+#include <uapi/asm/registers.h>
+
 extern unsigned long __rt_sigtramp_template[2];
 
+void do_signal(struct pt_regs *regs);
+
 #include <asm-generic/signal.h>
 
 #endif
diff --git a/arch/hexagon/include/uapi/asm/unistd.h b/arch/hexagon/include/uapi/asm/unistd.h
index 4a87cc4..ffee405 100644
--- a/arch/hexagon/include/uapi/asm/unistd.h
+++ b/arch/hexagon/include/uapi/asm/unistd.h
@@ -27,6 +27,9 @@
  */
 
 #define sys_mmap2 sys_mmap_pgoff
+#define __ARCH_WANT_SYS_EXECVE
 #define __ARCH_WANT_SYS_CLONE
+#define __ARCH_WANT_SYS_VFORK
+#define __ARCH_WANT_SYS_FORK
 
 #include <asm-generic/unistd.h>
diff --git a/arch/hexagon/include/uapi/asm/user.h b/arch/hexagon/include/uapi/asm/user.h
index cef13ee..3dae94d 100644
--- a/arch/hexagon/include/uapi/asm/user.h
+++ b/arch/hexagon/include/uapi/asm/user.h
@@ -55,9 +55,15 @@ struct user_regs_struct {
 	unsigned long pc;
 	unsigned long cause;
 	unsigned long badva;
+#if CONFIG_HEXAGON_ARCH_VERSION < 4
 	unsigned long pad1;  /* pad out to 48 words total */
 	unsigned long pad2;  /* pad out to 48 words total */
 	unsigned long pad3;  /* pad out to 48 words total */
+#else
+	unsigned long cs0;
+	unsigned long cs1;
+	unsigned long pad1;  /* pad out to 48 words total */
+#endif
 };
 
 #endif
diff --git a/arch/hexagon/kernel/Makefile b/arch/hexagon/kernel/Makefile
index 6c19501..29fc933 100644
--- a/arch/hexagon/kernel/Makefile
+++ b/arch/hexagon/kernel/Makefile
@@ -1,6 +1,6 @@
 extra-y := head.o vmlinux.lds
 
-obj-$(CONFIG_SMP) += smp.o topology.o
+obj-$(CONFIG_SMP) += smp.o
 
 obj-y += setup.o irq_cpu.o traps.o syscalltab.o signal.o time.o
 obj-y += process.o trampoline.o reset.o ptrace.o vdso.o
diff --git a/arch/hexagon/kernel/asm-offsets.c b/arch/hexagon/kernel/asm-offsets.c
index 2d5e84d..308be68 100644
--- a/arch/hexagon/kernel/asm-offsets.c
+++ b/arch/hexagon/kernel/asm-offsets.c
@@ -5,7 +5,7 @@
  * Kevin Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
  * Copyright (C) 2000 MIPS Technologies, Inc.
  *
- * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2010-2012, The Linux Foundation. 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
@@ -44,7 +44,8 @@ int main(void)
 
 	COMMENT("Hexagon pt_regs definitions");
 	OFFSET(_PT_SYSCALL_NR, pt_regs, syscall_nr);
-	OFFSET(_PT_UGPGP, pt_regs, ugpgp);
+	OFFSET(_PT_GPUGP, pt_regs, gpugp);
+	OFFSET(_PT_CS1CS0, pt_regs, cs1cs0);
 	OFFSET(_PT_R3130, pt_regs, r3130);
 	OFFSET(_PT_R2928, pt_regs, r2928);
 	OFFSET(_PT_R2726, pt_regs, r2726);
diff --git a/arch/hexagon/kernel/head.S b/arch/hexagon/kernel/head.S
index d859402..b9b63d0 100644
--- a/arch/hexagon/kernel/head.S
+++ b/arch/hexagon/kernel/head.S
@@ -1,7 +1,7 @@
 /*
  * Early kernel startup code for Hexagon
  *
- * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
  *
  *
  * This program is free software; you can redistribute it and/or modify
@@ -25,6 +25,9 @@
 #include <asm/mem-layout.h>
 #include <asm/vm_mmu.h>
 #include <asm/page.h>
+#include <asm/hexagon_vm.h>
+
+#define SEGTABLE_ENTRIES #0x0e0
 
 	__INIT
 ENTRY(stext)
@@ -43,40 +46,93 @@ ENTRY(stext)
 	 * Symbol is kernel segment address, but we need
 	 * the logical/physical address.
 	 */
-	r24 = asl(r24, #2)
-	r24 = lsr(r24, #2)
+	r25 = pc;
+	r2.h = #0xffc0;
+	r2.l = #0x0000;
+	r25 = and(r2,r25);	/*  R25 holds PHYS_OFFSET now  */
+	r1.h = #HI(PAGE_OFFSET);
+	r1.l = #LO(PAGE_OFFSET);
+	r24 = sub(r24,r1);	/* swapper_pg_dir - PAGE_OFFSET */
+	r24 = add(r24,r25);	/* + PHYS_OFFSET */
 
-	r0 = r24
+	r0 = r24;  /* aka __pa(swapper_pg_dir)  */
 
 	/*
-	 * Initialize a 16MB PTE to make the virtual and physical
+	 * Initialize page dir to make the virtual and physical
 	 * addresses where the kernel was loaded be identical.
+	 * Done in 4MB chunks.
 	 */
 #define PTE_BITS ( __HVM_PTE_R | __HVM_PTE_W | __HVM_PTE_X	\
 		  | __HEXAGON_C_WB_L2 << 6			\
 		  | __HVM_PDE_S_4MB)
 
-	r1 = pc
-	r2.H = #0xffc0
-	r2.L = #0x0000
-	r1 = and(r1,r2)		/* round PC to 4MB boundary	*/
+	/*
+	 * Get number of VA=PA entries; only really needed for jump
+	 * to hyperspace; gets blown away immediately after
+	 */
+
+	{
+		r1.l = #LO(_end);
+		r2.l = #LO(stext);
+		r3 = #1;
+	}
+	{
+		r1.h = #HI(_end);
+		r2.h = #HI(stext);
+		r3 = asl(r3, #22);
+	}
+	{
+		r1 = sub(r1, r2);
+		r3 = add(r3, #-1);
+	}  /* r1 =  _end - stext  */
+	r1 = add(r1, r3);  /*  + (4M-1) */
+	r26 = lsr(r1, #22); /*  / 4M = # of entries */
+
+	r1 = r25;
+	r2.h = #0xffc0;
+	r2.l = #0x0000;		/* round back down to 4MB boundary  */
+	r1 = and(r1,r2);
 	r2 = lsr(r1, #22)	/* 4MB page number		*/
 	r2 = asl(r2, #2)	/* times sizeof(PTE) (4bytes)	*/
 	r0 = add(r0,r2)		/* r0 = address of correct PTE	*/
 	r2 = #PTE_BITS
 	r1 = add(r1,r2)		/* r1 = 4MB PTE for the first entry	*/
 	r2.h = #0x0040
-	r2.l = #0x0000		/* 4MB	*/
-	memw(r0 ++ #4) = r1
-	r1 = add(r1, r2)
+	r2.l = #0x0000		/* 4MB increments */
+	loop0(1f,r26);
+1:
 	memw(r0 ++ #4) = r1
+	{ r1 = add(r1, r2); } :endloop0
+
+	/*  Also need to overwrite the initial 0xc0000000 entries  */
+	/*  PAGE_OFFSET >> (4MB shift - 4 bytes per entry shift)  */
+	R1.H = #HI(PAGE_OFFSET >> (22 - 2))
+	R1.L = #LO(PAGE_OFFSET >> (22 - 2))
+
+	r0 = add(r1, r24);	/* advance to 0xc0000000 entry */
+	r1 = r25;
+	r2.h = #0xffc0;
+	r2.l = #0x0000;		/* round back down to 4MB boundary  */
+	r1 = and(r1,r2);	/* for huge page */
+	r2 = #PTE_BITS
+	r1 = add(r1,r2);
+	r2.h = #0x0040
+	r2.l = #0x0000		/* 4MB increments */
 
-	r0 = r24
+	loop0(1f,SEGTABLE_ENTRIES);
+1:
+	memw(r0 ++ #4) = r1;
+	{ r1 = add(r1,r2); } :endloop0
+
+	r0 = r24;
 
 	/*
 	 * The subroutine wrapper around the virtual instruction touches
 	 * no memory, so we should be able to use it even here.
+	 * Note that in this version, R1 and R2 get "clobbered"; see
+	 * vm_ops.S
 	 */
+	r1 = #VM_TRANS_TYPE_TABLE
 	call	__vmnewmap;
 
 	/*  Jump into virtual address range.  */
@@ -90,17 +146,29 @@ ENTRY(stext)
 __head_s_vaddr_target:
 	/*
 	 * Tear down VA=PA translation now that we are running
-	 * in the desgnated kernel segments.
+	 * in kernel virtual space.
 	 */
 	r0 = #__HVM_PDE_S_INVALID
-	r1 = r24
-	loop0(1f,#0x100)
+
+	r1.h = #0xffc0;
+	r1.l = #0x0000;
+	r2 = r25;		/* phys_offset */
+	r2 = and(r1,r2);
+
+	r1.l = #lo(swapper_pg_dir)
+	r1.h = #hi(swapper_pg_dir)
+	r2 = lsr(r2, #22)	/* 4MB page number		*/
+	r2 = asl(r2, #2)	/* times sizeof(PTE) (4bytes)	*/
+	r1 = add(r1,r2);
+	loop0(1f,r26)
+
 1:
 	{
 		memw(R1 ++ #4) = R0
 	}:endloop0
 
 	r0 = r24
+	r1 = #VM_TRANS_TYPE_TABLE
 	call __vmnewmap
 
 	/*  Go ahead and install the trap0 return so angel calls work  */
@@ -143,6 +211,13 @@ __head_s_vaddr_target:
 	r2 = sub(r2,r0);
 	call memset;
 
+	/*  Set PHYS_OFFSET; should be in R25 */
+#ifdef CONFIG_HEXAGON_PHYS_OFFSET
+	r0.l = #LO(__phys_offset);
+	r0.h = #HI(__phys_offset);
+	memw(r0) = r25;
+#endif
+
 	/* Time to make the doughnuts.   */
 	call start_kernel
 
diff --git a/arch/hexagon/kernel/kgdb.c b/arch/hexagon/kernel/kgdb.c
index 3446453..82d5c25 100644
--- a/arch/hexagon/kernel/kgdb.c
+++ b/arch/hexagon/kernel/kgdb.c
@@ -1,7 +1,7 @@
 /*
  * arch/hexagon/kernel/kgdb.c - Hexagon KGDB Support
  *
- * Copyright (c) 2011, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2012, The Linux Foundation. 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
@@ -70,6 +70,8 @@ struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] = {
 	{ "lc1", GDB_SIZEOF_REG, offsetof(struct pt_regs, lc1)},
 	{ " gp", GDB_SIZEOF_REG, offsetof(struct pt_regs, gp)},
 	{ "ugp", GDB_SIZEOF_REG, offsetof(struct pt_regs, ugp)},
+	{ "cs0", GDB_SIZEOF_REG, offsetof(struct pt_regs, cs0)},
+	{ "cs1", GDB_SIZEOF_REG, offsetof(struct pt_regs, cs1)},
 	{ "psp", GDB_SIZEOF_REG, offsetof(struct pt_regs, hvmer.vmpsp)},
 	{ "elr", GDB_SIZEOF_REG, offsetof(struct pt_regs, hvmer.vmel)},
 	{ "est", GDB_SIZEOF_REG, offsetof(struct pt_regs, hvmer.vmest)},
diff --git a/arch/hexagon/kernel/process.c b/arch/hexagon/kernel/process.c
index 06ae9ff..a91b290 100644
--- a/arch/hexagon/kernel/process.c
+++ b/arch/hexagon/kernel/process.c
@@ -24,6 +24,7 @@
 #include <linux/tick.h>
 #include <linux/uaccess.h>
 #include <linux/slab.h>
+#include <linux/tracehook.h>
 
 /*
  * Program thread launch.  Often defined as a macro in processor.h,
@@ -112,7 +113,8 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
 	if (unlikely(p->flags & PF_KTHREAD)) {
 		memset(childregs, 0, sizeof(struct pt_regs));
 		/* r24 <- fn, r25 <- arg */
-		ss->r2524 = usp | ((u64)arg << 32);
+		ss->r24 = usp;
+		ss->r25 = arg;
 		pt_set_kmode(childregs);
 		return 0;
 	}
@@ -202,3 +204,40 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
 {
 	return 0;
 }
+
+
+/*
+ * Called on the exit path of event entry; see vm_entry.S
+ *
+ * Interrupts will already be disabled.
+ *
+ * Returns 0 if there's no need to re-check for more work.
+ */
+
+int do_work_pending(struct pt_regs *regs, u32 thread_info_flags)
+{
+	if (!(thread_info_flags & _TIF_WORK_MASK)) {
+		return 0;
+	}  /* shortcut -- no work to be done */
+
+	local_irq_enable();
+
+	if (thread_info_flags & _TIF_NEED_RESCHED) {
+		schedule();
+		return 1;
+	}
+
+	if (thread_info_flags & _TIF_SIGPENDING) {
+		do_signal(regs);
+		return 1;
+	}
+
+	if (thread_info_flags & _TIF_NOTIFY_RESUME) {
+		clear_thread_flag(TIF_NOTIFY_RESUME);
+		tracehook_notify_resume(regs);
+	}
+
+	/* Should not even reach here */
+	panic("%s: bad thread_info flags 0x%08x\n", __func__,
+		thread_info_flags);
+}
diff --git a/arch/hexagon/kernel/ptrace.c b/arch/hexagon/kernel/ptrace.c
index 670b1b0..de829eb 100644
--- a/arch/hexagon/kernel/ptrace.c
+++ b/arch/hexagon/kernel/ptrace.c
@@ -1,7 +1,7 @@
 /*
  * Ptrace support for Hexagon
  *
- * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2010-2013, The Linux Foundation. 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
@@ -32,6 +32,21 @@
 
 #include <asm/user.h>
 
+#if arch_has_single_step()
+/*  Both called from ptrace_resume  */
+void user_enable_single_step(struct task_struct *child)
+{
+	pt_set_singlestep(task_pt_regs(child));
+	set_tsk_thread_flag(child, TIF_SINGLESTEP);
+}
+
+void user_disable_single_step(struct task_struct *child)
+{
+	pt_clr_singlestep(task_pt_regs(child));
+	clear_tsk_thread_flag(child, TIF_SINGLESTEP);
+}
+#endif
+
 static int genregs_get(struct task_struct *target,
 		   const struct user_regset *regset,
 		   unsigned int pos, unsigned int count,
@@ -76,6 +91,10 @@ static int genregs_get(struct task_struct *target,
 	dummy = pt_cause(regs);
 	ONEXT(&dummy, cause);
 	ONEXT(&pt_badva(regs), badva);
+#if CONFIG_HEXAGON_ARCH_VERSION >=4
+	ONEXT(&regs->cs0, cs0);
+	ONEXT(&regs->cs1, cs1);
+#endif
 
 	/* Pad the rest with zeros, if needed */
 	if (!ret)
@@ -123,6 +142,11 @@ static int genregs_set(struct task_struct *target,
 	INEXT(&bucket, cause);
 	INEXT(&bucket, badva);
 
+#if CONFIG_HEXAGON_ARCH_VERSION >=4
+	INEXT(&regs->cs0, cs0);
+	INEXT(&regs->cs1, cs1);
+#endif
+
 	/* Ignore the rest, if needed */
 	if (!ret)
 		ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
diff --git a/arch/hexagon/kernel/setup.c b/arch/hexagon/kernel/setup.c
index 94a3878..bfe1331 100644
--- a/arch/hexagon/kernel/setup.c
+++ b/arch/hexagon/kernel/setup.c
@@ -1,7 +1,7 @@
 /*
  * Arch related setup for Hexagon
  *
- * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2010-2013, The Linux Foundation. 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
@@ -68,6 +68,8 @@ void __init setup_arch(char **cmdline_p)
 	 */
 	__vmsetvec(_K_VM_event_vector);
 
+	printk(KERN_INFO "PHYS_OFFSET=0x%08x\n", PHYS_OFFSET);
+
 	/*
 	 * Simulator has a few differences from the hardware.
 	 * For now, check uninitialized-but-mapped memory
@@ -128,6 +130,11 @@ static int show_cpuinfo(struct seq_file *m, void *v)
 {
 	int cpu = (unsigned long) v - 1;
 
+#ifdef CONFIG_SMP
+	if (!cpu_online(cpu))
+		return 0;
+#endif
+
 	seq_printf(m, "processor\t: %d\n", cpu);
 	seq_printf(m, "model name\t: Hexagon Virtual Machine\n");
 	seq_printf(m, "BogoMips\t: %lu.%02lu\n",
diff --git a/arch/hexagon/kernel/signal.c b/arch/hexagon/kernel/signal.c
index 60fa2ca..d7c7387 100644
--- a/arch/hexagon/kernel/signal.c
+++ b/arch/hexagon/kernel/signal.c
@@ -1,7 +1,7 @@
 /*
  * Signal support for Hexagon processor
  *
- * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2010-2012, The Linux Foundation. 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
@@ -41,6 +41,10 @@ static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
 {
 	unsigned long sp = regs->r29;
 
+	/* check if we would overflow the alt stack */
+	if (on_sig_stack(sp) && !likely(on_sig_stack(sp - frame_size)))
+		return (void __user __force *)-1UL;
+
 	/* Switch to signal stack if appropriate */
 	if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0))
 		sp = current->sas_ss_sp + current->sas_ss_size;
@@ -66,7 +70,10 @@ static int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
 	err |= __put_user(regs->preds, &sc->sc_regs.p3_0);
 	err |= __put_user(regs->gp, &sc->sc_regs.gp);
 	err |= __put_user(regs->ugp, &sc->sc_regs.ugp);
-
+#if CONFIG_HEXAGON_ARCH_VERSION >= 4
+	err |= __put_user(regs->cs0, &sc->sc_regs.cs0);
+	err |= __put_user(regs->cs1, &sc->sc_regs.cs1);
+#endif
 	tmp = pt_elr(regs); err |= __put_user(tmp, &sc->sc_regs.pc);
 	tmp = pt_cause(regs); err |= __put_user(tmp, &sc->sc_regs.cause);
 	tmp = pt_badva(regs); err |= __put_user(tmp, &sc->sc_regs.badva);
@@ -93,7 +100,10 @@ static int restore_sigcontext(struct pt_regs *regs,
 	err |= __get_user(regs->preds, &sc->sc_regs.p3_0);
 	err |= __get_user(regs->gp, &sc->sc_regs.gp);
 	err |= __get_user(regs->ugp, &sc->sc_regs.ugp);
-
+#if CONFIG_HEXAGON_ARCH_VERSION >= 4
+	err |= __get_user(regs->cs0, &sc->sc_regs.cs0);
+	err |= __get_user(regs->cs1, &sc->sc_regs.cs1);
+#endif
 	err |= __get_user(tmp, &sc->sc_regs.pc); pt_set_elr(regs, tmp);
 
 	return err;
@@ -193,7 +203,7 @@ static void handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka,
 /*
  * Called from return-from-event code.
  */
-static void do_signal(struct pt_regs *regs)
+void do_signal(struct pt_regs *regs)
 {
 	struct k_sigaction sigact;
 	siginfo_t info;
@@ -210,8 +220,9 @@ static void do_signal(struct pt_regs *regs)
 	}
 
 	/*
-	 * If we came from a system call, handle the restart.
+	 * No (more) signals; if we came from a system call, handle the restart.
 	 */
+
 	if (regs->syscall_nr >= 0) {
 		switch (regs->r00) {
 		case -ERESTARTNOHAND:
@@ -234,17 +245,6 @@ no_restart:
 	restore_saved_sigmask();
 }
 
-void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)
-{
-	if (thread_info_flags & _TIF_SIGPENDING)
-		do_signal(regs);
-
-	if (thread_info_flags & _TIF_NOTIFY_RESUME) {
-		clear_thread_flag(TIF_NOTIFY_RESUME);
-		tracehook_notify_resume(regs);
-	}
-}
-
 /*
  * Architecture-specific wrappers for signal-related system calls
  */
@@ -272,21 +272,12 @@ asmlinkage int sys_rt_sigreturn(void)
 	/* Restore the user's stack as well */
 	pt_psp(regs) = regs->r29;
 
-	/*
-	 * Leave a trace in the stack frame that this was a sigreturn.
-	 * If the system call is to replay, we've already restored the
-	 * number in the GPR slot and it will be regenerated on the
-	 * new system call trap entry. Note that if restore_sigcontext()
-	 * did something other than a bulk copy of the pt_regs struct,
-	 * we could avoid this assignment by simply not overwriting
-	 * regs->syscall_nr.
-	 */
-	regs->syscall_nr = __NR_rt_sigreturn;
+	regs->syscall_nr = -1;
 
 	if (restore_altstack(&frame->uc.uc_stack))
 		goto badframe;
 
-	return 0;
+	return regs->r00;
 
 badframe:
 	force_sig(SIGSEGV, current);
diff --git a/arch/hexagon/kernel/topology.c b/arch/hexagon/kernel/topology.c
deleted file mode 100644
index 352f27e..0000000
--- a/arch/hexagon/kernel/topology.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * CPU topology for Hexagon
- *
- * Copyright (c) 2010-2011, The Linux Foundation. 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/cpu.h>
-#include <linux/cpumask.h>
-#include <linux/init.h>
-#include <linux/node.h>
-#include <linux/nodemask.h>
-#include <linux/percpu.h>
-
-/*  Swiped from MIPS.  */
-
-static DEFINE_PER_CPU(struct cpu, cpu_devices);
-
-static int __init topology_init(void)
-{
-	int i, ret;
-
-	for_each_present_cpu(i) {
-
-		/*
-		 * register_cpu takes a per_cpu pointer and
-		 * just points it at another per_cpu struct...
-		 */
-
-		ret = register_cpu(&per_cpu(cpu_devices, i), i);
-		if (ret)
-			printk(KERN_WARNING "topology_init: register_cpu %d "
-			       "failed (%d)\n", i, ret);
-	}
-
-	return 0;
-}
-
-subsys_initcall(topology_init);
diff --git a/arch/hexagon/kernel/traps.c b/arch/hexagon/kernel/traps.c
index be5e2dd..aaf53f8 100644
--- a/arch/hexagon/kernel/traps.c
+++ b/arch/hexagon/kernel/traps.c
@@ -1,7 +1,7 @@
 /*
  * Kernel traps/events for Hexagon processor
  *
- * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2010-2013, The Linux Foundation. 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
@@ -65,6 +65,10 @@ static const char *ex_name(int ex)
 		return "Write protection fault";
 	case HVM_GE_C_XMAL:
 		return "Misaligned instruction";
+	case HVM_GE_C_WREG:
+		return "Multiple writes to same register in packet";
+	case HVM_GE_C_PCAL:
+		return "Program counter values that are not properly aligned";
 	case HVM_GE_C_RMAL:
 		return "Misaligned data load";
 	case HVM_GE_C_WMAL:
@@ -324,6 +328,12 @@ void do_genex(struct pt_regs *regs)
 	case HVM_GE_C_XMAL:
 		misaligned_instruction(regs);
 		break;
+	case HVM_GE_C_WREG:
+		illegal_instruction(regs);
+		break;
+	case HVM_GE_C_PCAL:
+		misaligned_instruction(regs);
+		break;
 	case HVM_GE_C_RMAL:
 		misaligned_data_load(regs);
 		break;
@@ -356,7 +366,6 @@ long sys_syscall(void)
 
 void do_trap0(struct pt_regs *regs)
 {
-	unsigned long syscallret = 0;
 	syscall_fn syscall;
 
 	switch (pt_cause(regs)) {
@@ -396,21 +405,11 @@ void do_trap0(struct pt_regs *regs)
 		} else {
 			syscall = (syscall_fn)
 				  (sys_call_table[regs->syscall_nr]);
-			syscallret = syscall(regs->r00, regs->r01,
+			regs->r00 = syscall(regs->r00, regs->r01,
 				   regs->r02, regs->r03,
 				   regs->r04, regs->r05);
 		}
 
-		/*
-		 * If it was a sigreturn system call, don't overwrite
-		 * r0 value in stack frame with return value.
-		 *
-		 * __NR_sigreturn doesn't seem to exist in new unistd.h
-		 */
-
-		if (regs->syscall_nr != __NR_rt_sigreturn)
-			regs->r00 = syscallret;
-
 		/* allow strace to get the syscall return state  */
 		if (unlikely(test_thread_flag(TIF_SYSCALL_TRACE)))
 			tracehook_report_syscall_exit(regs, 0);
@@ -452,3 +451,14 @@ void do_machcheck(struct pt_regs *regs)
 	/* Halt and catch fire */
 	__vmstop();
 }
+
+/*
+ * Treat this like the old 0xdb trap.
+ */
+
+void do_debug_exception(struct pt_regs *regs)
+{
+	regs->hvmer.vmest &= ~HVM_VMEST_CAUSE_MSK;
+	regs->hvmer.vmest |= (TRAP_DEBUG << HVM_VMEST_CAUSE_SFT);
+	do_trap0(regs);
+}
diff --git a/arch/hexagon/kernel/vm_entry.S b/arch/hexagon/kernel/vm_entry.S
index 425e50c..e308618 100644
--- a/arch/hexagon/kernel/vm_entry.S
+++ b/arch/hexagon/kernel/vm_entry.S
@@ -1,7 +1,7 @@
 /*
  * Event entry/exit for Hexagon
  *
- * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2010-2013, The Linux Foundation. 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
@@ -45,48 +45,88 @@
  * number in the case where we decode a system call (trap0(#1)).
  */
 
+#if CONFIG_HEXAGON_ARCH_VERSION < 4
 #define save_pt_regs()\
-	memd(R0 + #_PT_R3130) = R31:30; \
+ memd(R0 + #_PT_R3130) = R31:30; \
+ { memw(R0 + #_PT_R2928) = R28; \
+   R31 = memw(R0 + #_PT_ER_VMPSP); }\
+ { memw(R0 + #(_PT_R2928 + 4)) = R31; \
+   R31 = ugp; } \
+ { memd(R0 + #_PT_R2726) = R27:26; \
+   R30 = gp ; } \
+ memd(R0 + #_PT_R2524) = R25:24; \
+ memd(R0 + #_PT_R2322) = R23:22; \
+ memd(R0 + #_PT_R2120) = R21:20; \
+ memd(R0 + #_PT_R1918) = R19:18; \
+ memd(R0 + #_PT_R1716) = R17:16; \
+ memd(R0 + #_PT_R1514) = R15:14; \
+ memd(R0 + #_PT_R1312) = R13:12; \
+ { memd(R0 + #_PT_R1110) = R11:10; \
+   R15 = lc0; } \
+ { memd(R0 + #_PT_R0908) = R9:8; \
+   R14 = sa0; } \
+ { memd(R0 + #_PT_R0706) = R7:6; \
+   R13 = lc1; } \
+ { memd(R0 + #_PT_R0504) = R5:4; \
+   R12 = sa1; } \
+ { memd(R0 + #_PT_GPUGP) = R31:30; \
+   R11 = m1; \
+   R2.H = #HI(_THREAD_SIZE); } \
+ { memd(R0 + #_PT_LC0SA0) = R15:14; \
+   R10 = m0; \
+   R2.L = #LO(_THREAD_SIZE); } \
+ { memd(R0 + #_PT_LC1SA1) = R13:12; \
+   R15 = p3:0; \
+   R2 = neg(R2); } \
+ { memd(R0 + #_PT_M1M0) = R11:10; \
+   R14  = usr; \
+   R2 = and(R0,R2); } \
+ { memd(R0 + #_PT_PREDSUSR) =  R15:14; \
+   THREADINFO_REG = R2; } \
+ { r24 = memw(THREADINFO_REG + #_THREAD_INFO_PT_REGS); \
+   memw(THREADINFO_REG + #_THREAD_INFO_PT_REGS) = R0; \
+   R2 = #-1; } \
+ { memw(R0 + #_PT_SYSCALL_NR) = R2; \
+   R30 = #0; }
+#else
+/* V4+ */
+/* the # ## # syntax inserts a literal ## */
+#define save_pt_regs()\
+	{ memd(R0 + #_PT_R3130) = R31:30; \
+		R30 = memw(R0 + #_PT_ER_VMPSP); }\
 	{ memw(R0 + #_PT_R2928) = R28; \
-	  R31 = memw(R0 + #_PT_ER_VMPSP); }\
-	{ memw(R0 + #(_PT_R2928 + 4)) = R31; \
-	  R31 = ugp; } \
-	{ memd(R0 + #_PT_R2726) = R27:26; \
-	  R30 = gp ; } \
-	memd(R0 + #_PT_R2524) = R25:24; \
-	memd(R0 + #_PT_R2322) = R23:22; \
-	memd(R0 + #_PT_R2120) = R21:20; \
-	memd(R0 + #_PT_R1918) = R19:18; \
-	memd(R0 + #_PT_R1716) = R17:16; \
-	memd(R0 + #_PT_R1514) = R15:14; \
-	memd(R0 + #_PT_R1312) = R13:12; \
+		memw(R0 + #(_PT_R2928 + 4)) = R30; }\
+	{ R31:30 = C11:10; \
+		memd(R0 + #_PT_R2726) = R27:26; \
+		memd(R0 + #_PT_R2524) = R25:24; }\
+	{ memd(R0 + #_PT_R2322) = R23:22; \
+		memd(R0 + #_PT_R2120) = R21:20; }\
+	{ memd(R0 + #_PT_R1918) = R19:18; \
+		memd(R0 + #_PT_R1716) = R17:16; }\
+	{ memd(R0 + #_PT_R1514) = R15:14; \
+		memd(R0 + #_PT_R1312) = R13:12; \
+		R17:16 = C13:12; }\
 	{ memd(R0 + #_PT_R1110) = R11:10; \
-	  R15 = lc0; } \
-	{ memd(R0 + #_PT_R0908) = R9:8; \
-	  R14 = sa0; } \
+		memd(R0 + #_PT_R0908) = R9:8; \
+	  R15:14 = C1:0; } \
 	{ memd(R0 + #_PT_R0706) = R7:6; \
-	  R13 = lc1; } \
-	{ memd(R0 + #_PT_R0504) = R5:4; \
-	  R12 = sa1; } \
-	{ memd(R0 + #_PT_UGPGP) = R31:30; \
-	  R11 = m1; \
-	  R2.H = #HI(_THREAD_SIZE); } \
-	{ memd(R0 + #_PT_LC0SA0) = R15:14; \
-	  R10 = m0; \
-	  R2.L = #LO(_THREAD_SIZE); } \
-	{ memd(R0 + #_PT_LC1SA1) = R13:12; \
-	  R15 = p3:0; \
-	  R2 = neg(R2); } \
+		memd(R0 + #_PT_R0504) = R5:4; \
+    R13:12 = C3:2; } \
+	{ memd(R0 + #_PT_GPUGP) = R31:30; \
+		memd(R0 + #_PT_LC0SA0) = R15:14; \
+	  R11:10 = C7:6; }\
+	{	THREADINFO_REG = and(R0, # ## #-_THREAD_SIZE); \
+		memd(R0 + #_PT_LC1SA1) = R13:12; \
+	  R15 = p3:0; }\
 	{ memd(R0 + #_PT_M1M0) = R11:10; \
-	  R14  = usr; \
-	  R2 = and(R0,R2); } \
-	{ memd(R0 + #_PT_PREDSUSR) =  R15:14; \
-	  THREADINFO_REG = R2; } \
+		memw(R0 + #_PT_PREDSUSR + 4) =  R15; }\
 	{ r24 = memw(THREADINFO_REG + #_THREAD_INFO_PT_REGS); \
 	  memw(THREADINFO_REG + #_THREAD_INFO_PT_REGS) = R0; \
 	  R2 = #-1; } \
 	{ memw(R0 + #_PT_SYSCALL_NR) = R2; \
+		memd(R0 + #_PT_CS1CS0) = R17:16; \
 	  R30 = #0; }
+#endif
 
 /*
  * Restore registers and thread_info.regs state. THREADINFO_REG
@@ -94,6 +134,7 @@
  * preserved. Don't restore R29 (SP) until later.
  */
 
+#if CONFIG_HEXAGON_ARCH_VERSION < 4
 #define restore_pt_regs() \
 	{ memw(THREADINFO_REG + #_THREAD_INFO_PT_REGS) = R24; \
 	  R15:14 = memd(R0 + #_PT_PREDSUSR); } \
@@ -121,11 +162,44 @@
 	  R23:22 = memd(R0 + #_PT_R2322); } \
 	{ R25:24 = memd(R0 + #_PT_R2524); \
 	  R27:26 = memd(R0 + #_PT_R2726); } \
-	R31:30 = memd(R0 + #_PT_UGPGP); \
+	R31:30 = memd(R0 + #_PT_GPUGP); \
 	{ R28 = memw(R0 + #_PT_R2928); \
 	  ugp = R31; } \
 	{ R31:30 = memd(R0 + #_PT_R3130); \
 	  gp = R30; }
+#else
+/* V4+ */
+#define restore_pt_regs() \
+	{ memw(THREADINFO_REG + #_THREAD_INFO_PT_REGS) = R24; \
+	  R15:14 = memd(R0 + #_PT_PREDSUSR); } \
+	{ R11:10 = memd(R0 + #_PT_M1M0); \
+		R13:12 = memd(R0 + #_PT_LC1SA1); \
+		p3:0 = R15; } \
+	{ R15:14 = memd(R0 + #_PT_LC0SA0); \
+		R3:2 = memd(R0 + #_PT_R0302); \
+		usr = R14; } \
+	{ R5:4 = memd(R0 + #_PT_R0504); \
+		R7:6 = memd(R0 + #_PT_R0706); \
+		C7:6 = R11:10; }\
+	{ R9:8 = memd(R0 + #_PT_R0908); \
+		R11:10 = memd(R0 + #_PT_R1110); \
+    C3:2 = R13:12; }\
+	{ R13:12 = memd(R0 + #_PT_R1312); \
+	  R15:14 = memd(R0 + #_PT_R1514); \
+		C1:0 = R15:14; }\
+	{ R17:16 = memd(R0 + #_PT_R1716); \
+	  R19:18 = memd(R0 + #_PT_R1918); } \
+	{ R21:20 = memd(R0 + #_PT_R2120); \
+	  R23:22 = memd(R0 + #_PT_R2322); } \
+	{ R25:24 = memd(R0 + #_PT_R2524); \
+	  R27:26 = memd(R0 + #_PT_R2726); } \
+	R31:30 = memd(R0 + #_PT_CS1CS0); \
+	{ C13:12 = R31:30; \
+		R31:30 = memd(R0 + #_PT_GPUGP) ; \
+		R28 = memw(R0 + #_PT_R2928); }\
+	{ C11:10 = R31:30; \
+		R31:30 = memd(R0 + #_PT_R3130); }
+#endif
 
 	/*
 	 * Clears off enough space for the rest of pt_regs; evrec is a part
@@ -139,6 +213,7 @@
  * Need to save off R0, R1, R2, R3 immediately.
  */
 
+#if CONFIG_HEXAGON_ARCH_VERSION < 4
 #define	vm_event_entry(CHandler) \
 	{ \
 		R29 = add(R29, #-(_PT_REGS_SIZE)); \
@@ -158,6 +233,34 @@
 		R1.H = #HI(CHandler); \
 		jump event_dispatch; \
 	}
+#else
+/* V4+ */
+/* turn on I$ prefetch early */
+/* the # ## # syntax inserts a literal ## */
+#define	vm_event_entry(CHandler) \
+	{ \
+		R29 = add(R29, #-(_PT_REGS_SIZE)); \
+		memd(R29 + #(_PT_R0100 + -_PT_REGS_SIZE)) = R1:0; \
+		memd(R29 + #(_PT_R0302 + -_PT_REGS_SIZE)) = R3:2; \
+		R0 = usr; \
+	} \
+	{ \
+		memw(R29 + #_PT_PREDSUSR) = R0; \
+		R0 = setbit(R0, #16); \
+	} \
+	usr = R0; \
+	R1:0 = G1:0; \
+	{ \
+		memd(R29 + #_PT_ER_VMEL) = R1:0; \
+		R1 = # ## #(CHandler); \
+		R3:2 = G3:2; \
+	} \
+	{ \
+		R0 = R29; \
+		memd(R29 + #_PT_ER_VMPSP) = R3:2; \
+		jump event_dispatch; \
+	}
+#endif
 
 .text
 	/*
@@ -171,6 +274,9 @@ event_dispatch:
 	callr	r1
 
 	/*
+	 * Coming back from the C-world, our thread info pointer
+	 * should be in the designated register (usually R19)
+	 *
 	 * If we were in kernel mode, we don't need to check scheduler
 	 * or signals if CONFIG_PREEMPT is not set.  If set, then it has
 	 * to jump to a need_resched kind of block.
@@ -183,69 +289,68 @@ event_dispatch:
 #endif
 
 	/*  "Nested control path" -- if the previous mode was kernel  */
-	R0 = memw(R29 + #_PT_ER_VMEST);
-	P0 = tstbit(R0, #HVM_VMEST_UM_SFT);
-	if !P0 jump restore_all;
-	/*
-	 * Returning from system call, normally coming back from user mode
-	 */
-return_from_syscall:
-	/*  Disable interrupts while checking TIF  */
-	R0 = #VM_INT_DISABLE
-	trap1(#HVM_TRAP1_VMSETIE)
-
-	/*
-	 * Coming back from the C-world, our thread info pointer
-	 * should be in the designated register (usually R19)
-	 */
-	R1.L = #LO(_TIF_ALLWORK_MASK)
 	{
-		R1.H = #HI(_TIF_ALLWORK_MASK);
-		R0 = memw(THREADINFO_REG + #_THREAD_INFO_FLAGS);
+		R0 = memw(R29 + #_PT_ER_VMEST);
+		R16.L = #LO(do_work_pending);
+	}
+	{
+		P0 = tstbit(R0, #HVM_VMEST_UM_SFT);
+		if (!P0.new) jump:nt restore_all;
+		R16.H = #HI(do_work_pending);
+		R0 = #VM_INT_DISABLE;
 	}
 
 	/*
-	 * Compare against the "return to userspace" _TIF_WORK_MASK
+	 * Check also the return from fork/system call, normally coming back from
+	 * user mode
+	 *
+	 * R16 needs to have do_work_pending, and R0 should have VM_INT_DISABLE
 	 */
-	R1 = and(R1,R0);
-	{ P0 = cmp.eq(R1,#0); if (!P0.new) jump:t work_pending;}
-	jump restore_all;  /*  we're outta here!  */
 
-work_pending:
+check_work_pending:
+	/*  Disable interrupts while checking TIF  */
+	trap1(#HVM_TRAP1_VMSETIE)
 	{
-		P0 = tstbit(R1, #TIF_NEED_RESCHED);
-		if (!P0.new) jump:nt work_notifysig;
+		R0 = R29;  /*  regs should still be at top of stack  */
+		R1 = memw(THREADINFO_REG + #_THREAD_INFO_FLAGS);
+		callr R16;
 	}
-	call schedule
-	jump return_from_syscall;  /*  check for more work  */
 
-work_notifysig:
-	/*  this is the part that's kind of fuzzy.  */
-	R1 = and(R0, #(_TIF_SIGPENDING | _TIF_NOTIFY_RESUME));
-	P0 = cmp.eq(R1, #0);
-	if P0 jump restore_all
-	R1 = R0; 	/* unsigned long thread_info_flags */
-	R0 = R29;	/* regs should still be at top of stack  */
-	call do_notify_resume
+	{
+		P0 = cmp.eq(R0, #0); if (!P0.new) jump:nt check_work_pending;
+		R0 = #VM_INT_DISABLE;
+	}
 
 restore_all:
-	/* Disable interrupts, if they weren't already, before reg restore.  */
-	R0 = #VM_INT_DISABLE
+	/*
+	 * Disable interrupts, if they weren't already, before reg restore.
+	 * R0 gets preloaded with #VM_INT_DISABLE before we get here.
+	 */
 	trap1(#HVM_TRAP1_VMSETIE)
 
 	/*  do the setregs here for VM 0.5  */
 	/*  R29 here should already be pointing at pt_regs  */
-	R1:0 = memd(R29 + #_PT_ER_VMEL);
-	R3:2 = memd(R29 + #_PT_ER_VMPSP);
+	{
+		R1:0 = memd(R29 + #_PT_ER_VMEL);
+		R3:2 = memd(R29 + #_PT_ER_VMPSP);
+	}
+#if CONFIG_HEXAGON_ARCH_VERSION < 4
 	trap1(#HVM_TRAP1_VMSETREGS);
+#else
+	G1:0 = R1:0;
+	G3:2 = R3:2;
+#endif
 
 	R0 = R29
 	restore_pt_regs()
-	R1:0 = memd(R29 + #_PT_R0100);
-	R29 = add(R29, #_PT_REGS_SIZE);
+	{
+		R1:0 = memd(R29 + #_PT_R0100);
+		R29 = add(R29, #_PT_REGS_SIZE);
+	}
 	trap1(#HVM_TRAP1_VMRTE)
 	/* Notreached */
 
+
 	.globl _K_enter_genex
 _K_enter_genex:
 	vm_event_entry(do_genex)
@@ -262,12 +367,27 @@ _K_enter_trap0:
 _K_enter_machcheck:
 	vm_event_entry(do_machcheck)
 
+	.globl _K_enter_debug
+_K_enter_debug:
+	vm_event_entry(do_debug_exception)
 
 	.globl ret_from_fork
 ret_from_fork:
-	call schedule_tail
-	P0 = cmp.eq(R24, #0);
-	if P0 jump return_from_syscall
-	R0 = R25;
-	callr R24
-	jump return_from_syscall
+	{
+		call schedule_tail
+		R16.H = #HI(do_work_pending);
+	}
+	{
+		P0 = cmp.eq(R24, #0);
+		R16.L = #LO(do_work_pending);
+		R0 = #VM_INT_DISABLE;
+	}
+	if P0 jump check_work_pending
+	{
+		R0 = R25;
+		callr R24
+	}
+	{
+		jump check_work_pending
+		R0 = #VM_INT_DISABLE;
+	}
diff --git a/arch/hexagon/kernel/vm_events.c b/arch/hexagon/kernel/vm_events.c
index 9b5a4a2..3e44530 100644
--- a/arch/hexagon/kernel/vm_events.c
+++ b/arch/hexagon/kernel/vm_events.c
@@ -1,7 +1,7 @@
 /*
  * Mostly IRQ support for Hexagon
  *
- * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2010-2012, The Linux Foundation. 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
@@ -42,6 +42,8 @@ void show_regs(struct pt_regs *regs)
 	       regs->lc1, regs->sa1, regs->m1);
 	printk(KERN_EMERG "gp: \t0x%08lx   ugp: 0x%08lx   usr: 0x%08lx\n",
 	       regs->gp, regs->ugp, regs->usr);
+	printk(KERN_EMERG "cs0: \t0x%08lx   cs1: 0x%08lx\n",
+	       regs->cs0, regs->cs1);
 	printk(KERN_EMERG "r0: \t0x%08lx %08lx %08lx %08lx\n", regs->r00,
 		regs->r01,
 		regs->r02,
diff --git a/arch/hexagon/kernel/vm_vectors.S b/arch/hexagon/kernel/vm_vectors.S
index 620f42c..791a742 100644
--- a/arch/hexagon/kernel/vm_vectors.S
+++ b/arch/hexagon/kernel/vm_vectors.S
@@ -1,7 +1,7 @@
 /*
  * Event jump tables
  *
- * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2010-2012,2013, The Linux Foundation. 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
@@ -41,7 +41,7 @@ _K_VM_event_vector:
 	jump 1b;  /*  Reset  */
 	jump _K_enter_machcheck;
 	jump _K_enter_genex;
-	jump 1b;  /*  3 Rsvd  */
+	jump _K_enter_debug;
 	jump 1b;  /*  4 Rsvd  */
 	jump _K_enter_trap0;
 	jump 1b;  /*  6 Rsvd  */
diff --git a/arch/hexagon/kernel/vmlinux.lds.S b/arch/hexagon/kernel/vmlinux.lds.S
index 14e793f..44d8c47 100644
--- a/arch/hexagon/kernel/vmlinux.lds.S
+++ b/arch/hexagon/kernel/vmlinux.lds.S
@@ -1,7 +1,7 @@
 /*
  * Linker script for Hexagon kernel
  *
- * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2010-2013, The Linux Foundation. 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
@@ -18,8 +18,6 @@
  * 02110-1301, USA.
  */
 
-#define LOAD_OFFSET PAGE_OFFSET
-
 #include <asm-generic/vmlinux.lds.h>
 #include <asm/asm-offsets.h>	/*  Most of the kernel defines are here  */
 #include <asm/mem-layout.h>	/*  except for page_offset  */
@@ -36,13 +34,9 @@ See asm-generic/sections.h for seemingly required labels.
 
 #define PAGE_SIZE _PAGE_SIZE
 
-/*  This LOAD_OFFSET is temporary for debugging on the simulator; it may change
-    for hypervisor pseudo-physical memory.  */
-
-
 SECTIONS
 {
-	. = PAGE_OFFSET + LOAD_ADDRESS;
+	. = PAGE_OFFSET;
 
 	__init_begin = .;
 	HEAD_TEXT_SECTION
@@ -52,7 +46,7 @@ SECTIONS
 
         . = ALIGN(_PAGE_SIZE);
 	_stext = .;
-	.text : AT(ADDR(.text) - LOAD_OFFSET) {
+	.text : AT(ADDR(.text)) {
 		_text = .;
 		TEXT_TEXT
 		SCHED_TEXT
diff --git a/arch/hexagon/mm/init.c b/arch/hexagon/mm/init.c
index 69ffcfd..2561d25 100644
--- a/arch/hexagon/mm/init.c
+++ b/arch/hexagon/mm/init.c
@@ -1,7 +1,7 @@
 /*
  * Memory subsystem initialization for Hexagon
  *
- * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2010-2013, The Linux Foundation. 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
@@ -31,9 +31,10 @@
  * Define a startpg just past the end of the kernel image and a lastpg
  * that corresponds to the end of real or simulated platform memory.
  */
-#define bootmem_startpg (PFN_UP(((unsigned long) _end) - PAGE_OFFSET))
+#define bootmem_startpg (PFN_UP(((unsigned long) _end) - PAGE_OFFSET + PHYS_OFFSET))
 
-unsigned long bootmem_lastpg;  /*  Should be set by platform code  */
+unsigned long bootmem_lastpg;	/*  Should be set by platform code  */
+unsigned long __phys_offset;	/*  physical kernel offset >> 12  */
 
 /*  Set as variable to limit PMD copies  */
 int max_kernel_seg = 0x303;
@@ -44,7 +45,6 @@ unsigned long zero_page_mask;
 /*  indicate pfn's of high memory  */
 unsigned long highstart_pfn, highend_pfn;
 
-/* struct mmu_gather defined in asm-generic.h;  */
 DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
 
 /* Default cache attribute for newly created page tables */
@@ -71,7 +71,7 @@ void __init mem_init(void)
 {
 	/*  No idea where this is actually declared.  Seems to evade LXR.  */
 	totalram_pages += free_all_bootmem();
-	num_physpages = bootmem_lastpg;	/*  seriously, what?  */
+	num_physpages = bootmem_lastpg-ARCH_PFN_OFFSET;
 
 	printk(KERN_INFO "totalram_pages = %ld\n", totalram_pages);
 
@@ -193,6 +193,9 @@ void __init setup_arch_memory(void)
 	 * This needs to change for highmem setups.
 	 */
 
+	/*  Prior to this, bootmem_lastpg is actually mem size  */
+	bootmem_lastpg += ARCH_PFN_OFFSET;
+
 	/* Memory size needs to be a multiple of 16M */
 	bootmem_lastpg = PFN_DOWN((bootmem_lastpg << PAGE_SHIFT) &
 		~((BIG_KERNEL_PAGE_SIZE) - 1));
@@ -201,12 +204,15 @@ void __init setup_arch_memory(void)
 	 * Reserve the top DMA_RESERVE bytes of RAM for DMA (uncached)
 	 * memory allocation
 	 */
-	bootmap_size = init_bootmem(bootmem_startpg, bootmem_lastpg -
-				    PFN_DOWN(DMA_RESERVED_BYTES));
+
+	max_low_pfn = bootmem_lastpg - PFN_DOWN(DMA_RESERVED_BYTES);
+	min_low_pfn = ARCH_PFN_OFFSET;
+	bootmap_size =  init_bootmem_node(NODE_DATA(0), bootmem_startpg, min_low_pfn, max_low_pfn);
 
 	printk(KERN_INFO "bootmem_startpg:  0x%08lx\n", bootmem_startpg);
 	printk(KERN_INFO "bootmem_lastpg:  0x%08lx\n", bootmem_lastpg);
 	printk(KERN_INFO "bootmap_size:  %d\n", bootmap_size);
+	printk(KERN_INFO "min_low_pfn:  0x%08lx\n", min_low_pfn);
 	printk(KERN_INFO "max_low_pfn:  0x%08lx\n", max_low_pfn);
 
 	/*
@@ -221,14 +227,17 @@ void __init setup_arch_memory(void)
 	/*  this actually only goes to the end of the first gig  */
 	segtable_end = segtable + (1<<(30-22));
 
-	/*  Move forward to the start of empty pages  */
-	segtable += bootmem_lastpg >> (22-PAGE_SHIFT);
+	/*
+	 * Move forward to the start of empty pages; take into account
+	 * phys_offset shift.
+	 */
 
+	segtable += (bootmem_lastpg-ARCH_PFN_OFFSET)>>(22-PAGE_SHIFT);
 	{
-	    int i;
+		int i;
 
-	    for (i = 1 ; i <= DMA_RESERVE ; i++)
-		segtable[-i] = ((segtable[-i] & __HVM_PTE_PGMASK_4MB)
+		for (i = 1 ; i <= DMA_RESERVE ; i++)
+			segtable[-i] = ((segtable[-i] & __HVM_PTE_PGMASK_4MB)
 				| __HVM_PTE_R | __HVM_PTE_W | __HVM_PTE_X
 				| __HEXAGON_C_UNC << 6
 				| __HVM_PDE_S_4MB);
@@ -256,7 +265,7 @@ void __init setup_arch_memory(void)
 	 * Free all the memory that wasn't taken up by the bootmap, the DMA
 	 * reserve, or kernel itself.
 	 */
-	free_bootmem(PFN_PHYS(bootmem_startpg)+bootmap_size,
+	free_bootmem(PFN_PHYS(bootmem_startpg) + bootmap_size,
 		     PFN_PHYS(bootmem_lastpg - bootmem_startpg) - bootmap_size -
 		     DMA_RESERVED_BYTES);
 
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index 9a02f71..e7e55a0 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -187,7 +187,7 @@ config IA64_DIG
 
 config IA64_DIG_VTD
 	bool "DIG+Intel+IOMMU"
-	select DMAR
+	select INTEL_IOMMU
 	select PCI_MSI
 
 config IA64_HP_ZX1
diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c
index da2f319..e70cade 100644
--- a/arch/ia64/hp/sim/simserial.c
+++ b/arch/ia64/hp/sim/simserial.c
@@ -142,8 +142,7 @@ static void transmit_chars(struct tty_struct *tty, struct serial_state *info,
 		goto out;
 	}
 
-	if (info->xmit.head == info->xmit.tail || tty->stopped ||
-			tty->hw_stopped) {
+	if (info->xmit.head == info->xmit.tail || tty->stopped) {
 #ifdef SIMSERIAL_DEBUG
 		printk("transmit_chars: head=%d, tail=%d, stopped=%d\n",
 		       info->xmit.head, info->xmit.tail, tty->stopped);
@@ -181,7 +180,7 @@ static void rs_flush_chars(struct tty_struct *tty)
 	struct serial_state *info = tty->driver_data;
 
 	if (info->xmit.head == info->xmit.tail || tty->stopped ||
-			tty->hw_stopped || !info->xmit.buf)
+			!info->xmit.buf)
 		return;
 
 	transmit_chars(tty, info, NULL);
@@ -217,7 +216,7 @@ static int rs_write(struct tty_struct * tty,
 	 * Hey, we transmit directly from here in our case
 	 */
 	if (CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE) &&
-			!tty->stopped && !tty->hw_stopped)
+			!tty->stopped)
 		transmit_chars(tty, info, NULL);
 
 	return ret;
@@ -325,14 +324,6 @@ static int rs_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg)
 
 #define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
 
-static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
-{
-	/* Handle turning off CRTSCTS */
-	if ((old_termios->c_cflag & CRTSCTS) &&
-	    !(tty->termios.c_cflag & CRTSCTS)) {
-		tty->hw_stopped = 0;
-	}
-}
 /*
  * This routine will shutdown a serial port; interrupts are disabled, and
  * DTR is dropped if the hangup on close termio flag is on.
@@ -481,7 +472,6 @@ static const struct tty_operations hp_ops = {
 	.throttle = rs_throttle,
 	.unthrottle = rs_unthrottle,
 	.send_xchar = rs_send_xchar,
-	.set_termios = rs_set_termios,
 	.hangup = rs_hangup,
 	.proc_fops = &rs_proc_fops,
 };
diff --git a/arch/ia64/include/asm/futex.h b/arch/ia64/include/asm/futex.h
index d2bf1fd..76acbcd 100644
--- a/arch/ia64/include/asm/futex.h
+++ b/arch/ia64/include/asm/futex.h
@@ -106,16 +106,15 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
 		return -EFAULT;
 
 	{
-		register unsigned long r8 __asm ("r8");
+		register unsigned long r8 __asm ("r8") = 0;
 		unsigned long prev;
 		__asm__ __volatile__(
 			"	mf;;					\n"
-			"	mov %0=r0				\n"
 			"	mov ar.ccv=%4;;				\n"
 			"[1:]	cmpxchg4.acq %1=[%2],%3,ar.ccv		\n"
 			"	.xdata4 \"__ex_table\", 1b-., 2f-.	\n"
 			"[2:]"
-			: "=r" (r8), "=r" (prev)
+			: "+r" (r8), "=&r" (prev)
 			: "r" (uaddr), "r" (newval),
 			  "rO" ((long) (unsigned) oldval)
 			: "memory");
diff --git a/arch/ia64/include/asm/hugetlb.h b/arch/ia64/include/asm/hugetlb.h
index 94eaa5b..aa91005 100644
--- a/arch/ia64/include/asm/hugetlb.h
+++ b/arch/ia64/include/asm/hugetlb.h
@@ -2,6 +2,7 @@
 #define _ASM_IA64_HUGETLB_H
 
 #include <asm/page.h>
+#include <asm-generic/hugetlb.h>
 
 
 void hugetlb_free_pgd_range(struct mmu_gather *tlb, unsigned long addr,
diff --git a/arch/ia64/include/asm/linkage.h b/arch/ia64/include/asm/linkage.h
index ef22a45..7875757 100644
--- a/arch/ia64/include/asm/linkage.h
+++ b/arch/ia64/include/asm/linkage.h
@@ -11,4 +11,8 @@
 
 #endif
 
+#define cond_syscall(x) asm(".weak\t" #x "#\n" #x "#\t=\tsys_ni_syscall#")
+#define SYSCALL_ALIAS(alias, name)					\
+	asm ( #alias "# = " #name "#\n\t.globl " #alias "#")
+
 #endif
diff --git a/arch/ia64/include/asm/mca.h b/arch/ia64/include/asm/mca.h
index 43f96ab..8c70961 100644
--- a/arch/ia64/include/asm/mca.h
+++ b/arch/ia64/include/asm/mca.h
@@ -143,6 +143,7 @@ extern unsigned long __per_cpu_mca[NR_CPUS];
 extern int cpe_vector;
 extern int ia64_cpe_irq;
 extern void ia64_mca_init(void);
+extern void ia64_mca_irq_init(void);
 extern void ia64_mca_cpu_init(void *);
 extern void ia64_os_mca_dispatch(void);
 extern void ia64_os_mca_dispatch_end(void);
diff --git a/arch/ia64/include/asm/numa.h b/arch/ia64/include/asm/numa.h
index 2e27ef1..2db0a6c 100644
--- a/arch/ia64/include/asm/numa.h
+++ b/arch/ia64/include/asm/numa.h
@@ -67,14 +67,13 @@ extern int paddr_to_nid(unsigned long paddr);
 
 extern void map_cpu_to_node(int cpu, int nid);
 extern void unmap_cpu_from_node(int cpu, int nid);
-
+extern void numa_clear_node(int cpu);
 
 #else /* !CONFIG_NUMA */
 #define map_cpu_to_node(cpu, nid)	do{}while(0)
 #define unmap_cpu_from_node(cpu, nid)	do{}while(0)
-
 #define paddr_to_nid(addr)	0
-
+#define numa_clear_node(cpu)	do { } while (0)
 #endif /* CONFIG_NUMA */
 
 #endif /* _ASM_IA64_NUMA_H */
diff --git a/arch/ia64/include/asm/unistd.h b/arch/ia64/include/asm/unistd.h
index 0963738..afd45e0 100644
--- a/arch/ia64/include/asm/unistd.h
+++ b/arch/ia64/include/asm/unistd.h
@@ -46,15 +46,5 @@ asmlinkage unsigned long sys_mmap2(
 struct pt_regs;
 asmlinkage long sys_ia64_pipe(void);
 
-/*
- * "Conditional" syscalls
- *
- * Note, this macro can only be used in the file which defines sys_ni_syscall, i.e., in
- * kernel/sys_ni.c.  This version causes warnings because the declaration isn't a
- * proper prototype, but we can't use __typeof__ either, because not all cond_syscall()
- * declarations have prototypes at the moment.
- */
-#define cond_syscall(x) asmlinkage long x (void) __attribute__((weak,alias("sys_ni_syscall")))
-
 #endif /* !__ASSEMBLY__ */
 #endif /* _ASM_IA64_UNISTD_H */
diff --git a/arch/ia64/include/uapi/asm/socket.h b/arch/ia64/include/uapi/asm/socket.h
index c567adc..6b4329f 100644
--- a/arch/ia64/include/uapi/asm/socket.h
+++ b/arch/ia64/include/uapi/asm/socket.h
@@ -81,4 +81,6 @@
 
 #define SO_LOCK_FILTER		44
 
+#define SO_SELECT_ERR_QUEUE	45
+
 #endif /* _ASM_IA64_SOCKET_H */
diff --git a/arch/ia64/kernel/cpufreq/acpi-cpufreq.c b/arch/ia64/kernel/cpufreq/acpi-cpufreq.c
index f09b174..4700fef 100644
--- a/arch/ia64/kernel/cpufreq/acpi-cpufreq.c
+++ b/arch/ia64/kernel/cpufreq/acpi-cpufreq.c
@@ -137,7 +137,7 @@ migrate_end:
 static int
 processor_set_freq (
 	struct cpufreq_acpi_io	*data,
-	unsigned int		cpu,
+	struct cpufreq_policy   *policy,
 	int			state)
 {
 	int			ret = 0;
@@ -149,8 +149,8 @@ processor_set_freq (
 	pr_debug("processor_set_freq\n");
 
 	saved_mask = current->cpus_allowed;
-	set_cpus_allowed_ptr(current, cpumask_of(cpu));
-	if (smp_processor_id() != cpu) {
+	set_cpus_allowed_ptr(current, cpumask_of(policy->cpu));
+	if (smp_processor_id() != policy->cpu) {
 		retval = -EAGAIN;
 		goto migrate_end;
 	}
@@ -170,12 +170,11 @@ processor_set_freq (
 		data->acpi_data.state, state);
 
 	/* cpufreq frequency struct */
-	cpufreq_freqs.cpu = cpu;
 	cpufreq_freqs.old = data->freq_table[data->acpi_data.state].frequency;
 	cpufreq_freqs.new = data->freq_table[state].frequency;
 
 	/* notify cpufreq */
-	cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_PRECHANGE);
+	cpufreq_notify_transition(policy, &cpufreq_freqs, CPUFREQ_PRECHANGE);
 
 	/*
 	 * First we write the target state's 'control' value to the
@@ -189,17 +188,20 @@ processor_set_freq (
 	ret = processor_set_pstate(value);
 	if (ret) {
 		unsigned int tmp = cpufreq_freqs.new;
-		cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_POSTCHANGE);
+		cpufreq_notify_transition(policy, &cpufreq_freqs,
+				CPUFREQ_POSTCHANGE);
 		cpufreq_freqs.new = cpufreq_freqs.old;
 		cpufreq_freqs.old = tmp;
-		cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_PRECHANGE);
-		cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_POSTCHANGE);
+		cpufreq_notify_transition(policy, &cpufreq_freqs,
+				CPUFREQ_PRECHANGE);
+		cpufreq_notify_transition(policy, &cpufreq_freqs,
+				CPUFREQ_POSTCHANGE);
 		printk(KERN_WARNING "Transition failed with error %d\n", ret);
 		retval = -ENODEV;
 		goto migrate_end;
 	}
 
-	cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_POSTCHANGE);
+	cpufreq_notify_transition(policy, &cpufreq_freqs, CPUFREQ_POSTCHANGE);
 
 	data->acpi_data.state = state;
 
@@ -240,7 +242,7 @@ acpi_cpufreq_target (
 	if (result)
 		return (result);
 
-	result = processor_set_freq(data, policy->cpu, next_state);
+	result = processor_set_freq(data, policy, next_state);
 
 	return (result);
 }
diff --git a/arch/ia64/kernel/fsys.S b/arch/ia64/kernel/fsys.S
index c4cd45d..abc6dee 100644
--- a/arch/ia64/kernel/fsys.S
+++ b/arch/ia64/kernel/fsys.S
@@ -90,53 +90,6 @@ ENTRY(fsys_getpid)
 	FSYS_RETURN
 END(fsys_getpid)
 
-ENTRY(fsys_getppid)
-	.prologue
-	.altrp b6
-	.body
-	add r17=IA64_TASK_GROUP_LEADER_OFFSET,r16
-	;;
-	ld8 r17=[r17]				// r17 = current->group_leader
-	add r9=TI_FLAGS+IA64_TASK_SIZE,r16
-	;;
-
-	ld4 r9=[r9]
-	add r17=IA64_TASK_REAL_PARENT_OFFSET,r17 // r17 = &current->group_leader->real_parent
-	;;
-	and r9=TIF_ALLWORK_MASK,r9
-
-1:	ld8 r18=[r17]				// r18 = current->group_leader->real_parent
-	;;
-	cmp.ne p8,p0=0,r9
-	add r8=IA64_TASK_TGID_OFFSET,r18	// r8 = &current->group_leader->real_parent->tgid
-	;;
-
-	/*
-	 * The .acq is needed to ensure that the read of tgid has returned its data before
-	 * we re-check "real_parent".
-	 */
-	ld4.acq r8=[r8]				// r8 = current->group_leader->real_parent->tgid
-#ifdef CONFIG_SMP
-	/*
-	 * Re-read current->group_leader->real_parent.
-	 */
-	ld8 r19=[r17]				// r19 = current->group_leader->real_parent
-(p8)	br.spnt.many fsys_fallback_syscall
-	;;
-	cmp.ne p6,p0=r18,r19			// did real_parent change?
-	mov r19=0			// i must not leak kernel bits...
-(p6)	br.cond.spnt.few 1b			// yes -> redo the read of tgid and the check
-	;;
-	mov r17=0			// i must not leak kernel bits...
-	mov r18=0			// i must not leak kernel bits...
-#else
-	mov r17=0			// i must not leak kernel bits...
-	mov r18=0			// i must not leak kernel bits...
-	mov r19=0			// i must not leak kernel bits...
-#endif
-	FSYS_RETURN
-END(fsys_getppid)
-
 ENTRY(fsys_set_tid_address)
 	.prologue
 	.altrp b6
@@ -614,7 +567,7 @@ paravirt_fsyscall_table:
 	data8 0				// chown
 	data8 0				// lseek		// 1040
 	data8 fsys_getpid		// getpid
-	data8 fsys_getppid		// getppid
+	data8 0				// getppid
 	data8 0				// mount
 	data8 0				// umount
 	data8 0				// setuid		// 1045
diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c
index ee33c3a..19f107b 100644
--- a/arch/ia64/kernel/iosapic.c
+++ b/arch/ia64/kernel/iosapic.c
@@ -76,7 +76,7 @@
  *	PCI pin -> global system interrupt (GSI) -> IA-64 vector <-> IRQ
  *
  * Note: The term "IRQ" is loosely used everywhere in Linux kernel to
- * describeinterrupts.  Now we use "IRQ" only for Linux IRQ's.  ISA IRQ
+ * describe interrupts.  Now we use "IRQ" only for Linux IRQ's.  ISA IRQ
  * (isa_irq) is the only exception in this source code.
  */
 
@@ -1010,6 +1010,26 @@ iosapic_check_gsi_range (unsigned int gsi_base, unsigned int ver)
 	return 0;
 }
 
+static int
+iosapic_delete_rte(unsigned int irq, unsigned int gsi)
+{
+	struct iosapic_rte_info *rte, *temp;
+
+	list_for_each_entry_safe(rte, temp, &iosapic_intr_info[irq].rtes,
+								rte_list) {
+		if (rte->iosapic->gsi_base + rte->rte_index == gsi) {
+			if (rte->refcnt)
+				return -EBUSY;
+
+			list_del(&rte->rte_list);
+			kfree(rte);
+			return 0;
+		}
+	}
+
+	return -EINVAL;
+}
+
 int iosapic_init(unsigned long phys_addr, unsigned int gsi_base)
 {
 	int num_rte, err, index;
@@ -1069,7 +1089,7 @@ int iosapic_init(unsigned long phys_addr, unsigned int gsi_base)
 
 int iosapic_remove(unsigned int gsi_base)
 {
-	int index, err = 0;
+	int i, irq, index, err = 0;
 	unsigned long flags;
 
 	spin_lock_irqsave(&iosapic_lock, flags);
@@ -1087,6 +1107,16 @@ int iosapic_remove(unsigned int gsi_base)
 		goto out;
 	}
 
+	for (i = gsi_base; i < gsi_base + iosapic_lists[index].num_rte; i++) {
+		irq = __gsi_to_irq(i);
+		if (irq < 0)
+			continue;
+
+		err = iosapic_delete_rte(irq, i);
+		if (err)
+			goto out;
+	}
+
 	iounmap(iosapic_lists[index].addr);
 	iosapic_free(index);
  out:
diff --git a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c
index ad69606..f2c41828 100644
--- a/arch/ia64/kernel/irq.c
+++ b/arch/ia64/kernel/irq.c
@@ -23,6 +23,8 @@
 #include <linux/interrupt.h>
 #include <linux/kernel_stat.h>
 
+#include <asm/mca.h>
+
 /*
  * 'what should we do if we get a hw irq event on an illegal vector'.
  * each architecture has to answer this themselves.
@@ -83,6 +85,12 @@ bool is_affinity_mask_valid(const struct cpumask *cpumask)
 
 #endif /* CONFIG_SMP */
 
+int __init arch_early_irq_init(void)
+{
+	ia64_mca_irq_init();
+	return 0;
+}
+
 #ifdef CONFIG_HOTPLUG_CPU
 unsigned int vectors_in_migration[NR_IRQS];
 
diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c
index 65bf9cd..d7396db 100644
--- a/arch/ia64/kernel/mca.c
+++ b/arch/ia64/kernel/mca.c
@@ -2074,22 +2074,16 @@ ia64_mca_init(void)
 	printk(KERN_INFO "MCA related initialization done\n");
 }
 
+
 /*
- * ia64_mca_late_init
- *
- *	Opportunity to setup things that require initialization later
- *	than ia64_mca_init.  Setup a timer to poll for CPEs if the
- *	platform doesn't support an interrupt driven mechanism.
- *
- *  Inputs  :   None
- *  Outputs :   Status
+ * These pieces cannot be done in ia64_mca_init() because it is called before
+ * early_irq_init() which would wipe out our percpu irq registrations. But we
+ * cannot leave them until ia64_mca_late_init() because by then all the other
+ * processors have been brought online and have set their own CMC vectors to
+ * point at a non-existant action. Called from arch_early_irq_init().
  */
-static int __init
-ia64_mca_late_init(void)
+void __init ia64_mca_irq_init(void)
 {
-	if (!mca_init)
-		return 0;
-
 	/*
 	 *  Configure the CMCI/P vector and handler. Interrupts for CMC are
 	 *  per-processor, so AP CMC interrupts are setup in smp_callin() (smpboot.c).
@@ -2108,6 +2102,23 @@ ia64_mca_late_init(void)
 	/* Setup the CPEI/P handler */
 	register_percpu_irq(IA64_CPEP_VECTOR, &mca_cpep_irqaction);
 #endif
+}
+
+/*
+ * ia64_mca_late_init
+ *
+ *	Opportunity to setup things that require initialization later
+ *	than ia64_mca_init.  Setup a timer to poll for CPEs if the
+ *	platform doesn't support an interrupt driven mechanism.
+ *
+ *  Inputs  :   None
+ *  Outputs :   Status
+ */
+static int __init
+ia64_mca_late_init(void)
+{
+	if (!mca_init)
+		return 0;
 
 	register_hotcpu_notifier(&mca_cpu_notifier);
 
diff --git a/arch/ia64/kernel/mca_drv.c b/arch/ia64/kernel/mca_drv.c
index 9392e02..94f8bf7 100644
--- a/arch/ia64/kernel/mca_drv.c
+++ b/arch/ia64/kernel/mca_drv.c
@@ -349,7 +349,7 @@ init_record_index_pools(void)
 
 	/* - 3 - */
 	slidx_pool.max_idx = (rec_max_size/sect_min_size) * 2 + 1;
-	slidx_pool.buffer = (slidx_list_t *)
+	slidx_pool.buffer =
 		kmalloc(slidx_pool.max_idx * sizeof(slidx_list_t), GFP_KERNEL);
 
 	return slidx_pool.buffer ? 0 : -ENOMEM;
diff --git a/arch/ia64/kernel/palinfo.c b/arch/ia64/kernel/palinfo.c
index 77597e5..79521d5 100644
--- a/arch/ia64/kernel/palinfo.c
+++ b/arch/ia64/kernel/palinfo.c
@@ -849,17 +849,6 @@ static palinfo_entry_t palinfo_entries[]={
 
 #define NR_PALINFO_ENTRIES	(int) ARRAY_SIZE(palinfo_entries)
 
-/*
- * this array is used to keep track of the proc entries we create. This is
- * required in the module mode when we need to remove all entries. The procfs code
- * does not do recursion of deletion
- *
- * Notes:
- *	- +1 accounts for the cpuN directory entry in /proc/pal
- */
-#define NR_PALINFO_PROC_ENTRIES	(NR_CPUS*(NR_PALINFO_ENTRIES+1))
-
-static struct proc_dir_entry *palinfo_proc_entries[NR_PALINFO_PROC_ENTRIES];
 static struct proc_dir_entry *palinfo_dir;
 
 /*
@@ -971,60 +960,32 @@ palinfo_read_entry(char *page, char **start, off_t off, int count, int *eof, voi
 static void __cpuinit
 create_palinfo_proc_entries(unsigned int cpu)
 {
-#	define CPUSTR	"cpu%d"
-
 	pal_func_cpu_u_t f;
-	struct proc_dir_entry **pdir;
 	struct proc_dir_entry *cpu_dir;
 	int j;
-	char cpustr[sizeof(CPUSTR)];
-
-
-	/*
-	 * we keep track of created entries in a depth-first order for
-	 * cleanup purposes. Each entry is stored into palinfo_proc_entries
-	 */
-	sprintf(cpustr,CPUSTR, cpu);
+	char cpustr[3+4+1];	/* cpu numbers are up to 4095 on itanic */
+	sprintf(cpustr, "cpu%d", cpu);
 
 	cpu_dir = proc_mkdir(cpustr, palinfo_dir);
+	if (!cpu_dir)
+		return;
 
 	f.req_cpu = cpu;
 
-	/*
-	 * Compute the location to store per cpu entries
-	 * We dont store the top level entry in this list, but
-	 * remove it finally after removing all cpu entries.
-	 */
-	pdir = &palinfo_proc_entries[cpu*(NR_PALINFO_ENTRIES+1)];
-	*pdir++ = cpu_dir;
 	for (j=0; j < NR_PALINFO_ENTRIES; j++) {
 		f.func_id = j;
-		*pdir = create_proc_read_entry(
-				palinfo_entries[j].name, 0, cpu_dir,
-				palinfo_read_entry, (void *)f.value);
-		pdir++;
+		create_proc_read_entry(
+			palinfo_entries[j].name, 0, cpu_dir,
+			palinfo_read_entry, (void *)f.value);
 	}
 }
 
 static void
 remove_palinfo_proc_entries(unsigned int hcpu)
 {
-	int j;
-	struct proc_dir_entry *cpu_dir, **pdir;
-
-	pdir = &palinfo_proc_entries[hcpu*(NR_PALINFO_ENTRIES+1)];
-	cpu_dir = *pdir;
-	*pdir++=NULL;
-	for (j=0; j < (NR_PALINFO_ENTRIES); j++) {
-		if ((*pdir)) {
-			remove_proc_entry ((*pdir)->name, cpu_dir);
-			*pdir ++= NULL;
-		}
-	}
-
-	if (cpu_dir) {
-		remove_proc_entry(cpu_dir->name, palinfo_dir);
-	}
+	char cpustr[3+4+1];	/* cpu numbers are up to 4095 on itanic */
+	sprintf(cpustr, "cpu%d", hcpu);
+	remove_proc_subtree(cpustr, palinfo_dir);
 }
 
 static int __cpuinit palinfo_cpu_callback(struct notifier_block *nfb,
@@ -1058,6 +1019,8 @@ palinfo_init(void)
 
 	printk(KERN_INFO "PAL Information Facility v%s\n", PALINFO_VERSION);
 	palinfo_dir = proc_mkdir("pal", NULL);
+	if (!palinfo_dir)
+		return -ENOMEM;
 
 	/* Create palinfo dirs in /proc for all online cpus */
 	for_each_online_cpu(i) {
@@ -1073,22 +1036,8 @@ palinfo_init(void)
 static void __exit
 palinfo_exit(void)
 {
-	int i = 0;
-
-	/* remove all nodes: depth first pass. Could optimize this  */
-	for_each_online_cpu(i) {
-		remove_palinfo_proc_entries(i);
-	}
-
-	/*
-	 * Remove the top level entry finally
-	 */
-	remove_proc_entry(palinfo_dir->name, NULL);
-
-	/*
-	 * Unregister from cpu notifier callbacks
-	 */
 	unregister_hotcpu_notifier(&palinfo_cpu_notifier);
+	remove_proc_subtree("pal", NULL);
 }
 
 module_init(palinfo_init);
diff --git a/arch/ia64/kernel/salinfo.c b/arch/ia64/kernel/salinfo.c
index aa527d7..a97d75b 100644
--- a/arch/ia64/kernel/salinfo.c
+++ b/arch/ia64/kernel/salinfo.c
@@ -301,9 +301,7 @@ salinfo_event_open(struct inode *inode, struct file *file)
 static ssize_t
 salinfo_event_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
 {
-	struct inode *inode = file_inode(file);
-	struct proc_dir_entry *entry = PDE(inode);
-	struct salinfo_data *data = entry->data;
+	struct salinfo_data *data = PDE_DATA(file_inode(file));
 	char cmd[32];
 	size_t size;
 	int i, n, cpu = -1;
@@ -360,8 +358,7 @@ static const struct file_operations salinfo_event_fops = {
 static int
 salinfo_log_open(struct inode *inode, struct file *file)
 {
-	struct proc_dir_entry *entry = PDE(inode);
-	struct salinfo_data *data = entry->data;
+	struct salinfo_data *data = PDE_DATA(inode);
 
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
@@ -386,8 +383,7 @@ salinfo_log_open(struct inode *inode, struct file *file)
 static int
 salinfo_log_release(struct inode *inode, struct file *file)
 {
-	struct proc_dir_entry *entry = PDE(inode);
-	struct salinfo_data *data = entry->data;
+	struct salinfo_data *data = PDE_DATA(inode);
 
 	if (data->state == STATE_NO_DATA) {
 		vfree(data->log_buffer);
@@ -463,9 +459,7 @@ retry:
 static ssize_t
 salinfo_log_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
 {
-	struct inode *inode = file_inode(file);
-	struct proc_dir_entry *entry = PDE(inode);
-	struct salinfo_data *data = entry->data;
+	struct salinfo_data *data = PDE_DATA(file_inode(file));
 	u8 *buf;
 	u64 bufsize;
 
@@ -524,9 +518,7 @@ salinfo_log_clear(struct salinfo_data *data, int cpu)
 static ssize_t
 salinfo_log_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
 {
-	struct inode *inode = file_inode(file);
-	struct proc_dir_entry *entry = PDE(inode);
-	struct salinfo_data *data = entry->data;
+	struct salinfo_data *data = PDE_DATA(file_inode(file));
 	char cmd[32];
 	size_t size;
 	u32 offset;
diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c
index ad3126a..7a54455 100644
--- a/arch/ia64/kvm/kvm-ia64.c
+++ b/arch/ia64/kvm/kvm-ia64.c
@@ -942,24 +942,6 @@ long kvm_arch_vm_ioctl(struct file *filp,
 	int r = -ENOTTY;
 
 	switch (ioctl) {
-	case KVM_SET_MEMORY_REGION: {
-		struct kvm_memory_region kvm_mem;
-		struct kvm_userspace_memory_region kvm_userspace_mem;
-
-		r = -EFAULT;
-		if (copy_from_user(&kvm_mem, argp, sizeof kvm_mem))
-			goto out;
-		kvm_userspace_mem.slot = kvm_mem.slot;
-		kvm_userspace_mem.flags = kvm_mem.flags;
-		kvm_userspace_mem.guest_phys_addr =
-					kvm_mem.guest_phys_addr;
-		kvm_userspace_mem.memory_size = kvm_mem.memory_size;
-		r = kvm_vm_ioctl_set_memory_region(kvm,
-					&kvm_userspace_mem, false);
-		if (r)
-			goto out;
-		break;
-		}
 	case KVM_CREATE_IRQCHIP:
 		r = -EFAULT;
 		r = kvm_ioapic_init(kvm);
@@ -1578,9 +1560,8 @@ int kvm_arch_create_memslot(struct kvm_memory_slot *slot, unsigned long npages)
 
 int kvm_arch_prepare_memory_region(struct kvm *kvm,
 		struct kvm_memory_slot *memslot,
-		struct kvm_memory_slot old,
 		struct kvm_userspace_memory_region *mem,
-		bool user_alloc)
+		enum kvm_mr_change change)
 {
 	unsigned long i;
 	unsigned long pfn;
@@ -1610,8 +1591,8 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
 
 void kvm_arch_commit_memory_region(struct kvm *kvm,
 		struct kvm_userspace_memory_region *mem,
-		struct kvm_memory_slot old,
-		bool user_alloc)
+		const struct kvm_memory_slot *old,
+		enum kvm_mr_change change)
 {
 	return;
 }
diff --git a/arch/ia64/kvm/vtlb.c b/arch/ia64/kvm/vtlb.c
index 4332f7e..a7869f8 100644
--- a/arch/ia64/kvm/vtlb.c
+++ b/arch/ia64/kvm/vtlb.c
@@ -256,7 +256,7 @@ u64 guest_vhpt_lookup(u64 iha, u64 *pte)
 			"srlz.d;;"
 			"ssm psr.i;;"
 			"srlz.d;;"
-			: "=r"(ret) : "r"(iha), "r"(pte):"memory");
+			: "=&r"(ret) : "r"(iha), "r"(pte) : "memory");
 
 	return ret;
 }
diff --git a/arch/ia64/mm/contig.c b/arch/ia64/mm/contig.c
index 80dab50..67c59eb 100644
--- a/arch/ia64/mm/contig.c
+++ b/arch/ia64/mm/contig.c
@@ -47,6 +47,8 @@ void show_mem(unsigned int filter)
 	printk(KERN_INFO "Mem-info:\n");
 	show_free_areas(filter);
 	printk(KERN_INFO "Node memory in pages:\n");
+	if (filter & SHOW_MEM_FILTER_PAGE_COUNT)
+		return;
 	for_each_online_pgdat(pgdat) {
 		unsigned long present;
 		unsigned long flags;
diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c
index c2e955e..ae4db4b 100644
--- a/arch/ia64/mm/discontig.c
+++ b/arch/ia64/mm/discontig.c
@@ -623,6 +623,8 @@ void show_mem(unsigned int filter)
 
 	printk(KERN_INFO "Mem-info:\n");
 	show_free_areas(filter);
+	if (filter & SHOW_MEM_FILTER_PAGE_COUNT)
+		return;
 	printk(KERN_INFO "Node memory in pages:\n");
 	for_each_online_pgdat(pgdat) {
 		unsigned long present;
@@ -817,13 +819,12 @@ void arch_refresh_nodedata(int update_node, pg_data_t *update_pgdat)
 #endif
 
 #ifdef CONFIG_SPARSEMEM_VMEMMAP
-int __meminit vmemmap_populate(struct page *start_page,
-						unsigned long size, int node)
+int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node)
 {
-	return vmemmap_populate_basepages(start_page, size, node);
+	return vmemmap_populate_basepages(start, end, node);
 }
 
-void vmemmap_free(struct page *memmap, unsigned long nr_pages)
+void vmemmap_free(unsigned long start, unsigned long end)
 {
 }
 #endif
diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c
index 20bc967..d1fe4b4 100644
--- a/arch/ia64/mm/init.c
+++ b/arch/ia64/mm/init.c
@@ -154,25 +154,14 @@ ia64_init_addr_space (void)
 void
 free_initmem (void)
 {
-	unsigned long addr, eaddr;
-
-	addr = (unsigned long) ia64_imva(__init_begin);
-	eaddr = (unsigned long) ia64_imva(__init_end);
-	while (addr < eaddr) {
-		ClearPageReserved(virt_to_page(addr));
-		init_page_count(virt_to_page(addr));
-		free_page(addr);
-		++totalram_pages;
-		addr += PAGE_SIZE;
-	}
-	printk(KERN_INFO "Freeing unused kernel memory: %ldkB freed\n",
-	       (__init_end - __init_begin) >> 10);
+	free_reserved_area((unsigned long)ia64_imva(__init_begin),
+			   (unsigned long)ia64_imva(__init_end),
+			   0, "unused kernel");
 }
 
 void __init
 free_initrd_mem (unsigned long start, unsigned long end)
 {
-	struct page *page;
 	/*
 	 * EFI uses 4KB pages while the kernel can use 4KB or bigger.
 	 * Thus EFI and the kernel may have different page sizes. It is
@@ -213,11 +202,7 @@ free_initrd_mem (unsigned long start, unsigned long end)
 	for (; start < end; start += PAGE_SIZE) {
 		if (!virt_addr_valid(start))
 			continue;
-		page = virt_to_page(start);
-		ClearPageReserved(page);
-		init_page_count(page);
-		free_page(start);
-		++totalram_pages;
+		free_reserved_page(virt_to_page(start));
 	}
 }
 
diff --git a/arch/ia64/mm/ioremap.c b/arch/ia64/mm/ioremap.c
index 3dccdd8..43964cd 100644
--- a/arch/ia64/mm/ioremap.c
+++ b/arch/ia64/mm/ioremap.c
@@ -16,7 +16,7 @@
 #include <asm/meminit.h>
 
 static inline void __iomem *
-__ioremap (unsigned long phys_addr)
+__ioremap_uc(unsigned long phys_addr)
 {
 	return (void __iomem *) (__IA64_UNCACHED_OFFSET | phys_addr);
 }
@@ -24,7 +24,11 @@ __ioremap (unsigned long phys_addr)
 void __iomem *
 early_ioremap (unsigned long phys_addr, unsigned long size)
 {
-	return __ioremap(phys_addr);
+	u64 attr;
+	attr = kern_mem_attribute(phys_addr, size);
+	if (attr & EFI_MEMORY_WB)
+		return (void __iomem *) phys_to_virt(phys_addr);
+	return __ioremap_uc(phys_addr);
 }
 
 void __iomem *
@@ -47,7 +51,7 @@ ioremap (unsigned long phys_addr, unsigned long size)
 	if (attr & EFI_MEMORY_WB)
 		return (void __iomem *) phys_to_virt(phys_addr);
 	else if (attr & EFI_MEMORY_UC)
-		return __ioremap(phys_addr);
+		return __ioremap_uc(phys_addr);
 
 	/*
 	 * Some chipsets don't support UC access to memory.  If
@@ -93,7 +97,7 @@ ioremap (unsigned long phys_addr, unsigned long size)
 		return (void __iomem *) (offset + (char __iomem *)addr);
 	}
 
-	return __ioremap(phys_addr);
+	return __ioremap_uc(phys_addr);
 }
 EXPORT_SYMBOL(ioremap);
 
@@ -103,7 +107,7 @@ ioremap_nocache (unsigned long phys_addr, unsigned long size)
 	if (kern_mem_attribute(phys_addr, size) & EFI_MEMORY_WB)
 		return NULL;
 
-	return __ioremap(phys_addr);
+	return __ioremap_uc(phys_addr);
 }
 EXPORT_SYMBOL(ioremap_nocache);
 
diff --git a/arch/ia64/mm/numa.c b/arch/ia64/mm/numa.c
index 3efea7d..4248492 100644
--- a/arch/ia64/mm/numa.c
+++ b/arch/ia64/mm/numa.c
@@ -61,18 +61,36 @@ paddr_to_nid(unsigned long paddr)
 int __meminit __early_pfn_to_nid(unsigned long pfn)
 {
 	int i, section = pfn >> PFN_SECTION_SHIFT, ssec, esec;
+	/*
+	 * NOTE: The following SMP-unsafe globals are only used early in boot
+	 * when the kernel is running single-threaded.
+	 */
+	static int __meminitdata last_ssec, last_esec;
+	static int __meminitdata last_nid;
+
+	if (section >= last_ssec && section < last_esec)
+		return last_nid;
 
 	for (i = 0; i < num_node_memblks; i++) {
 		ssec = node_memblk[i].start_paddr >> PA_SECTION_SHIFT;
 		esec = (node_memblk[i].start_paddr + node_memblk[i].size +
 			((1L << PA_SECTION_SHIFT) - 1)) >> PA_SECTION_SHIFT;
-		if (section >= ssec && section < esec)
+		if (section >= ssec && section < esec) {
+			last_ssec = ssec;
+			last_esec = esec;
+			last_nid = node_memblk[i].nid;
 			return node_memblk[i].nid;
+		}
 	}
 
 	return -1;
 }
 
+void __cpuinit numa_clear_node(int cpu)
+{
+	unmap_cpu_from_node(cpu, NUMA_NO_NODE);
+}
+
 #ifdef CONFIG_MEMORY_HOTPLUG
 /*
  *  SRAT information is stored in node_memblk[], then we can use SRAT
diff --git a/arch/ia64/sn/kernel/sn2/prominfo_proc.c b/arch/ia64/sn/kernel/sn2/prominfo_proc.c
index 20b88cb..90298bd 100644
--- a/arch/ia64/sn/kernel/sn2/prominfo_proc.c
+++ b/arch/ia64/sn/kernel/sn2/prominfo_proc.c
@@ -216,58 +216,40 @@ void __exit prominfo_exit(void);
 module_init(prominfo_init);
 module_exit(prominfo_exit);
 
-static struct proc_dir_entry **proc_entries;
 static struct proc_dir_entry *sgi_prominfo_entry;
 
 #define NODE_NAME_LEN 11
 
 int __init prominfo_init(void)
 {
-	struct proc_dir_entry **entp;
 	cnodeid_t cnodeid;
-	unsigned long nasid;
-	int size;
-	char name[NODE_NAME_LEN];
 
 	if (!ia64_platform_is("sn2"))
 		return 0;
 
-	size = num_online_nodes() * sizeof(struct proc_dir_entry *);
-	proc_entries = kzalloc(size, GFP_KERNEL);
-	if (!proc_entries)
-		return -ENOMEM;
-
 	sgi_prominfo_entry = proc_mkdir("sgi_prominfo", NULL);
+	if (!sgi_prominfo_entry)
+		return -ENOMEM;
 
-	entp = proc_entries;
 	for_each_online_node(cnodeid) {
+		struct proc_dir_entry *dir;
+		unsigned long nasid;
+		char name[NODE_NAME_LEN];
+
 		sprintf(name, "node%d", cnodeid);
-		*entp = proc_mkdir(name, sgi_prominfo_entry);
+		dir = proc_mkdir(name, sgi_prominfo_entry);
+		if (!dir)
+			continue;
 		nasid = cnodeid_to_nasid(cnodeid);
-		create_proc_read_entry("fit", 0, *entp, read_fit_entry,
+		create_proc_read_entry("fit", 0, dir, read_fit_entry,
 					   (void *)nasid);
-		create_proc_read_entry("version", 0, *entp,
+		create_proc_read_entry("version", 0, dir,
 					   read_version_entry, (void *)nasid);
-		entp++;
 	}
-
 	return 0;
 }
 
 void __exit prominfo_exit(void)
 {
-	struct proc_dir_entry **entp;
-	unsigned int cnodeid;
-	char name[NODE_NAME_LEN];
-
-	entp = proc_entries;
-	for_each_online_node(cnodeid) {
-		remove_proc_entry("fit", *entp);
-		remove_proc_entry("version", *entp);
-		sprintf(name, "node%d", cnodeid);
-		remove_proc_entry(name, sgi_prominfo_entry);
-		entp++;
-	}
-	remove_proc_entry("sgi_prominfo", NULL);
-	kfree(proc_entries);
+	remove_proc_subtree("sgi_prominfo", NULL);
 }
diff --git a/arch/ia64/sn/kernel/tiocx.c b/arch/ia64/sn/kernel/tiocx.c
index 14c1711..e35f648 100644
--- a/arch/ia64/sn/kernel/tiocx.c
+++ b/arch/ia64/sn/kernel/tiocx.c
@@ -490,11 +490,14 @@ static int __init tiocx_init(void)
 {
 	cnodeid_t cnodeid;
 	int found_tiocx_device = 0;
+	int err;
 
 	if (!ia64_platform_is("sn2"))
 		return 0;
 
-	bus_register(&tiocx_bus_type);
+	err = bus_register(&tiocx_bus_type);
+	if (err)
+		return err;
 
 	for (cnodeid = 0; cnodeid < num_cnodes; cnodeid++) {
 		nasid_t nasid;
diff --git a/arch/m32r/include/asm/unistd.h b/arch/m32r/include/asm/unistd.h
index 555629b..59db801 100644
--- a/arch/m32r/include/asm/unistd.h
+++ b/arch/m32r/include/asm/unistd.h
@@ -48,14 +48,4 @@
 #define __IGNORE_getresgid
 #define __IGNORE_chown
 
-/*
- * "Conditional" syscalls
- *
- * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
- * but it doesn't work on all toolchains, so we just do it by hand
- */
-#ifndef cond_syscall
-#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
-#endif
-
 #endif /* _ASM_M32R_UNISTD_H */
diff --git a/arch/m32r/include/uapi/asm/socket.h b/arch/m32r/include/uapi/asm/socket.h
index 519afa2..2a3b59e 100644
--- a/arch/m32r/include/uapi/asm/socket.h
+++ b/arch/m32r/include/uapi/asm/socket.h
@@ -72,4 +72,6 @@
 
 #define SO_LOCK_FILTER		44
 
+#define SO_SELECT_ERR_QUEUE	45
+
 #endif /* _ASM_M32R_SOCKET_H */
diff --git a/arch/m32r/mm/init.c b/arch/m32r/mm/init.c
index 78b660e..ab4cbce 100644
--- a/arch/m32r/mm/init.c
+++ b/arch/m32r/mm/init.c
@@ -28,10 +28,7 @@
 #include <asm/mmu_context.h>
 #include <asm/setup.h>
 #include <asm/tlb.h>
-
-/* References to section boundaries */
-extern char _text, _etext, _edata;
-extern char __init_begin, __init_end;
+#include <asm/sections.h>
 
 pgd_t swapper_pg_dir[1024];
 
@@ -184,17 +181,7 @@ void __init mem_init(void)
  *======================================================================*/
 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: %dk freed\n", \
-	  (int)(&__init_end - &__init_begin) >> 10);
+	free_initmem_default(0);
 }
 
 #ifdef CONFIG_BLK_DEV_INITRD
@@ -204,13 +191,6 @@ void free_initmem(void)
  *======================================================================*/
 void free_initrd_mem(unsigned long start, unsigned long end)
 {
-	unsigned long p;
-	for (p = start; p < end; p += PAGE_SIZE) {
-		ClearPageReserved(virt_to_page(p));
-		init_page_count(virt_to_page(p));
-		free_page(p);
-		totalram_pages++;
-	}
-	printk (KERN_INFO "Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
+	free_reserved_area(start, end, 0, "initrd");
 }
 #endif
diff --git a/arch/m68k/Kconfig.cpu b/arch/m68k/Kconfig.cpu
index b1cfff8..d266787 100644
--- a/arch/m68k/Kconfig.cpu
+++ b/arch/m68k/Kconfig.cpu
@@ -22,8 +22,7 @@ config M68KCLASSIC
 
 config COLDFIRE
 	bool "Coldfire CPU family support"
-	select GENERIC_GPIO
-	select ARCH_WANT_OPTIONAL_GPIOLIB
+	select ARCH_REQUIRE_GPIOLIB
 	select ARCH_HAVE_CUSTOM_GPIO_H
 	select CPU_HAS_NO_BITFIELDS
 	select CPU_HAS_NO_MULDIV64
diff --git a/arch/m68k/Kconfig.machine b/arch/m68k/Kconfig.machine
index 7240584..28ec0c0 100644
--- a/arch/m68k/Kconfig.machine
+++ b/arch/m68k/Kconfig.machine
@@ -539,15 +539,6 @@ config ROMVEC
 	  68000 type variants the vectors are at the base of the boot device
 	  on system startup.
 
-config ROMVECSIZE
-	hex "Size of ROM vector region (in bytes)"
-	default "0x400"
-	depends on ROM
-	help
-	  Define the size of the vector region in ROM. For most 68000
-	  variants this would be 0x400 bytes in size. Set to 0 if you do
-	  not want a vector region at the start of the ROM.
-
 config ROMSTART
 	hex "Address of the base of system image in ROM"
 	default "0x400"
diff --git a/arch/m68k/include/asm/commproc.h b/arch/m68k/include/asm/commproc.h
index a739985..66a36bd 100644
--- a/arch/m68k/include/asm/commproc.h
+++ b/arch/m68k/include/asm/commproc.h
@@ -480,23 +480,6 @@ typedef struct scc_enet {
 #define SICR_ENET_CLKRT	((uint)0x0000003d)
 #endif
 
-#ifdef CONFIG_RPXLITE
-/* This ENET stuff is for the MPC850 with ethernet on SCC2.  Some of
- * this may be unique to the RPX-Lite configuration.
- * Note TENA is on Port B.
- */
-#define PA_ENET_RXD	((ushort)0x0004)
-#define PA_ENET_TXD	((ushort)0x0008)
-#define PA_ENET_TCLK	((ushort)0x0200)
-#define PA_ENET_RCLK	((ushort)0x0800)
-#define PB_ENET_TENA	((uint)0x00002000)
-#define PC_ENET_CLSN	((ushort)0x0040)
-#define PC_ENET_RENA	((ushort)0x0080)
-
-#define SICR_ENET_MASK	((uint)0x0000ff00)
-#define SICR_ENET_CLKRT	((uint)0x00003d00)
-#endif
-
 #ifdef CONFIG_BSEIP
 /* This ENET stuff is for the MPC823 with ethernet on SCC2.
  * This is unique to the BSE ip-Engine board.
diff --git a/arch/m68k/include/asm/unistd.h b/arch/m68k/include/asm/unistd.h
index 6cd9267..014f288 100644
--- a/arch/m68k/include/asm/unistd.h
+++ b/arch/m68k/include/asm/unistd.h
@@ -32,12 +32,4 @@
 #define __ARCH_WANT_SYS_FORK
 #define __ARCH_WANT_SYS_VFORK
 
-/*
- * "Conditional" syscalls
- *
- * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
- * but it doesn't work on all toolchains, so we just do it by hand
- */
-#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
-
 #endif /* _ASM_M68K_UNISTD_H_ */
diff --git a/arch/m68k/mm/init.c b/arch/m68k/mm/init.c
index 519aad8..1af2ca3 100644
--- a/arch/m68k/mm/init.c
+++ b/arch/m68k/mm/init.c
@@ -110,18 +110,7 @@ void __init paging_init(void)
 void free_initmem(void)
 {
 #ifndef CONFIG_MMU_SUN3
-	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++;
-	}
-	pr_notice("Freeing unused kernel memory: %luk freed (0x%x - 0x%x)\n",
-		(addr - (unsigned long) __init_begin) >> 10,
-		(unsigned int) __init_begin, (unsigned int) __init_end);
+	free_initmem_default(0);
 #endif /* CONFIG_MMU_SUN3 */
 }
 
@@ -213,15 +202,6 @@ void __init mem_init(void)
 #ifdef CONFIG_BLK_DEV_INITRD
 void free_initrd_mem(unsigned long start, unsigned long end)
 {
-	int pages = 0;
-	for (; start < end; start += PAGE_SIZE) {
-		ClearPageReserved(virt_to_page(start));
-		init_page_count(virt_to_page(start));
-		free_page(start);
-		totalram_pages++;
-		pages++;
-	}
-	pr_notice("Freeing initrd memory: %dk freed\n",
-		pages << (PAGE_SHIFT - 10));
+	free_reserved_area(start, end, 0, "initrd");
 }
 #endif
diff --git a/arch/metag/Kconfig b/arch/metag/Kconfig
index afc8973..6f16c14 100644
--- a/arch/metag/Kconfig
+++ b/arch/metag/Kconfig
@@ -1,7 +1,3 @@
-config SYMBOL_PREFIX
-	string
-	default "_"
-
 config METAG
 	def_bool y
 	select EMBEDDED
@@ -25,8 +21,10 @@ config METAG
 	select HAVE_MEMBLOCK
 	select HAVE_MEMBLOCK_NODE_MAP
 	select HAVE_MOD_ARCH_SPECIFIC
+	select HAVE_OPROFILE
 	select HAVE_PERF_EVENTS
 	select HAVE_SYSCALL_TRACEPOINTS
+	select HAVE_UNDERSCORE_SYMBOL_PREFIX
 	select IRQ_DOMAIN
 	select MODULES_USE_ELF_RELA
 	select OF
@@ -209,6 +207,9 @@ config METAG_PERFCOUNTER_IRQS
 	  When disabled, Performance Counters information will be collected
 	  based on Timer Interrupt.
 
+config HW_PERF_EVENTS
+	def_bool METAG_PERFCOUNTER_IRQS && PERF_EVENTS
+
 config METAG_DA
 	bool "DA support"
 	help
diff --git a/arch/metag/Makefile b/arch/metag/Makefile
index 81bd6a1..b566116 100644
--- a/arch/metag/Makefile
+++ b/arch/metag/Makefile
@@ -49,6 +49,8 @@ core-y					+= arch/metag/mm/
 libs-y					+= arch/metag/lib/
 libs-y					+= arch/metag/tbx/
 
+drivers-$(CONFIG_OPROFILE)		+= arch/metag/oprofile/
+
 boot					:= arch/metag/boot
 
 boot_targets				+= uImage
diff --git a/arch/metag/include/asm/metag_mem.h b/arch/metag/include/asm/metag_mem.h
index 3f7b54d..aa5a076 100644
--- a/arch/metag/include/asm/metag_mem.h
+++ b/arch/metag/include/asm/metag_mem.h
@@ -700,6 +700,9 @@
 #define     SYSC_xCPARTG_AND_S    8
 #define     SYSC_xCPARTL_OR_BITS  0x000F0000 /* Ors into top 4 bits */
 #define     SYSC_xCPARTL_OR_S     16
+#ifdef METAC_2_1
+#define     SYSC_DCPART_GCON_BIT  0x00100000 /* Coherent shared local */
+#endif /* METAC_2_1 */
 #define     SYSC_xCPARTG_OR_BITS  0x0F000000 /* Ors into top 4 bits */
 #define     SYSC_xCPARTG_OR_S     24
 #define     SYSC_CWRMODE_BIT      0x80000000 /* Write cache mode bit */
diff --git a/arch/metag/include/uapi/asm/Kbuild b/arch/metag/include/uapi/asm/Kbuild
index 876c71f..84e09fe 100644
--- a/arch/metag/include/uapi/asm/Kbuild
+++ b/arch/metag/include/uapi/asm/Kbuild
@@ -2,6 +2,7 @@
 include include/uapi/asm-generic/Kbuild.asm
 
 header-y += byteorder.h
+header-y += ech.h
 header-y += ptrace.h
 header-y += resource.h
 header-y += sigcontext.h
diff --git a/arch/metag/include/uapi/asm/ech.h b/arch/metag/include/uapi/asm/ech.h
new file mode 100644
index 0000000..ac94d1c
--- /dev/null
+++ b/arch/metag/include/uapi/asm/ech.h
@@ -0,0 +1,15 @@
+#ifndef _UAPI_METAG_ECH_H
+#define _UAPI_METAG_ECH_H
+
+/*
+ * These bits can be set in the top half of the D0.8 register when DSP context
+ * switching is enabled, in order to support partial DSP context save/restore.
+ */
+
+#define TBICTX_XEXT_BIT	0x1000	/* Enable extended context save */
+#define TBICTX_XTDP_BIT	0x0800	/* DSP accumulators/RAM/templates */
+#define TBICTX_XHL2_BIT	0x0400	/* Hardware loops */
+#define TBICTX_XAXX_BIT	0x0200	/* Extended AX registers (A*.4-7) */
+#define TBICTX_XDX8_BIT	0x0100	/* Extended DX registers (D*.8-15) */
+
+#endif /* _UAPI_METAG_ECH_H */
diff --git a/arch/metag/kernel/cachepart.c b/arch/metag/kernel/cachepart.c
index 3a589dfb..954548b 100644
--- a/arch/metag/kernel/cachepart.c
+++ b/arch/metag/kernel/cachepart.c
@@ -24,15 +24,21 @@
 unsigned int get_dcache_size(void)
 {
 	unsigned int config2 = metag_in32(METAC_CORE_CONFIG2);
-	return 0x1000 << ((config2 & METAC_CORECFG2_DCSZ_BITS)
-				>> METAC_CORECFG2_DCSZ_S);
+	unsigned int sz = 0x1000 << ((config2 & METAC_CORECFG2_DCSZ_BITS)
+				     >> METAC_CORECFG2_DCSZ_S);
+	if (config2 & METAC_CORECFG2_DCSMALL_BIT)
+		sz >>= 6;
+	return sz;
 }
 
 unsigned int get_icache_size(void)
 {
 	unsigned int config2 = metag_in32(METAC_CORE_CONFIG2);
-	return 0x1000 << ((config2 & METAC_CORE_C2ICSZ_BITS)
-				>> METAC_CORE_C2ICSZ_S);
+	unsigned int sz = 0x1000 << ((config2 & METAC_CORE_C2ICSZ_BITS)
+				     >> METAC_CORE_C2ICSZ_S);
+	if (config2 & METAC_CORECFG2_ICSMALL_BIT)
+		sz >>= 6;
+	return sz;
 }
 
 unsigned int get_global_dcache_size(void)
@@ -61,7 +67,7 @@ static unsigned int get_thread_cache_size(unsigned int cache, int thread_id)
 		return 0;
 #if PAGE_OFFSET >= LINGLOBAL_BASE
 	/* Checking for global cache */
-	cache_size = (cache == DCACHE ? get_global_dache_size() :
+	cache_size = (cache == DCACHE ? get_global_dcache_size() :
 		get_global_icache_size());
 	offset = 8;
 #else
diff --git a/arch/metag/kernel/da.c b/arch/metag/kernel/da.c
index 52aabb6..a35dbed 100644
--- a/arch/metag/kernel/da.c
+++ b/arch/metag/kernel/da.c
@@ -5,12 +5,14 @@
  */
 
 
+#include <linux/export.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <asm/da.h>
 #include <asm/metag_mem.h>
 
 bool _metag_da_present;
+EXPORT_SYMBOL_GPL(_metag_da_present);
 
 int __init metag_da_probe(void)
 {
diff --git a/arch/metag/kernel/head.S b/arch/metag/kernel/head.S
index 969dffa..713f71d 100644
--- a/arch/metag/kernel/head.S
+++ b/arch/metag/kernel/head.S
@@ -1,6 +1,7 @@
 	! Copyright 2005,2006,2007,2009 Imagination Technologies
 
 #include <linux/init.h>
+#include <asm/metag_mem.h>
 #include <generated/asm-offsets.h>
 #undef __exit
 
@@ -48,6 +49,13 @@ __exit:
 	.global _secondary_startup
 	.type _secondary_startup,function
 _secondary_startup:
+#if CONFIG_PAGE_OFFSET < LINGLOBAL_BASE
+	! In case GCOn has just been turned on we need to fence any writes that
+	! the boot thread might have performed prior to coherency taking effect.
+	MOVT	D0Re0,#HI(LINSYSEVENT_WR_ATOMIC_UNLOCK)
+	MOV	D1Re0,#0
+	SETD	[D0Re0], D1Re0
+#endif
 	MOVT	A0StP,#HI(_secondary_data_stack)
 	ADD	A0StP,A0StP,#LO(_secondary_data_stack)
 	GETD	A0StP,[A0StP]
diff --git a/arch/metag/kernel/perf/perf_event.c b/arch/metag/kernel/perf/perf_event.c
index a876d5f..3665694 100644
--- a/arch/metag/kernel/perf/perf_event.c
+++ b/arch/metag/kernel/perf/perf_event.c
@@ -22,9 +22,9 @@
 #include <linux/slab.h>
 
 #include <asm/core_reg.h>
-#include <asm/hwthread.h>
 #include <asm/io.h>
 #include <asm/irq.h>
+#include <asm/processor.h>
 
 #include "perf_event.h"
 
@@ -40,10 +40,10 @@ static DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events);
 /* PMU admin */
 const char *perf_pmu_name(void)
 {
-	if (metag_pmu)
-		return metag_pmu->pmu.name;
+	if (!metag_pmu)
+		return NULL;
 
-	return NULL;
+	return metag_pmu->name;
 }
 EXPORT_SYMBOL_GPL(perf_pmu_name);
 
@@ -171,6 +171,7 @@ static int metag_pmu_event_init(struct perf_event *event)
 	switch (event->attr.type) {
 	case PERF_TYPE_HARDWARE:
 	case PERF_TYPE_HW_CACHE:
+	case PERF_TYPE_RAW:
 		err = _hw_perf_event_init(event);
 		break;
 
@@ -211,9 +212,10 @@ again:
 	/*
 	 * Calculate the delta and add it to the counter.
 	 */
-	delta = new_raw_count - prev_raw_count;
+	delta = (new_raw_count - prev_raw_count) & MAX_PERIOD;
 
 	local64_add(delta, &event->count);
+	local64_sub(delta, &hwc->period_left);
 }
 
 int metag_pmu_event_set_period(struct perf_event *event,
@@ -223,6 +225,10 @@ int metag_pmu_event_set_period(struct perf_event *event,
 	s64 period = hwc->sample_period;
 	int ret = 0;
 
+	/* The period may have been changed */
+	if (unlikely(period != hwc->last_period))
+		left += period - hwc->last_period;
+
 	if (unlikely(left <= -period)) {
 		left = period;
 		local64_set(&hwc->period_left, left);
@@ -240,8 +246,10 @@ int metag_pmu_event_set_period(struct perf_event *event,
 	if (left > (s64)metag_pmu->max_period)
 		left = metag_pmu->max_period;
 
-	if (metag_pmu->write)
-		metag_pmu->write(idx, (u64)(-left) & MAX_PERIOD);
+	if (metag_pmu->write) {
+		local64_set(&hwc->prev_count, -(s32)left);
+		metag_pmu->write(idx, -left & MAX_PERIOD);
+	}
 
 	perf_event_update_userpage(event);
 
@@ -549,6 +557,10 @@ static int _hw_perf_event_init(struct perf_event *event)
 		if (err)
 			return err;
 		break;
+
+	case PERF_TYPE_RAW:
+		mapping = attr->config;
+		break;
 	}
 
 	/* Return early if the event is unsupported */
@@ -610,15 +622,13 @@ static void metag_pmu_enable_counter(struct hw_perf_event *event, int idx)
 		WARN_ONCE((config != 0x100),
 			"invalid configuration (%d) for counter (%d)\n",
 			config, idx);
-
-		/* Reset the cycle count */
-		__core_reg_set(TXTACTCYC, 0);
+		local64_set(&event->prev_count, __core_reg_get(TXTACTCYC));
 		goto unlock;
 	}
 
 	/* Check for a core internal or performance channel event. */
 	if (tmp) {
-		void *perf_addr = (void *)PERF_COUNT(idx);
+		void *perf_addr;
 
 		/*
 		 * Anything other than a cycle count will write the low-
@@ -632,9 +642,14 @@ static void metag_pmu_enable_counter(struct hw_perf_event *event, int idx)
 		case 0xf0:
 			perf_addr = (void *)PERF_CHAN(idx);
 			break;
+
+		default:
+			perf_addr = NULL;
+			break;
 		}
 
-		metag_out32((tmp & 0x0f), perf_addr);
+		if (perf_addr)
+			metag_out32((config & 0x0f), perf_addr);
 
 		/*
 		 * Now we use the high nibble as the performance event to
@@ -643,13 +658,21 @@ static void metag_pmu_enable_counter(struct hw_perf_event *event, int idx)
 		config = tmp >> 4;
 	}
 
-	/*
-	 * Enabled counters start from 0. Early cores clear the count on
-	 * write but newer cores don't, so we make sure that the count is
-	 * set to 0.
-	 */
 	tmp = ((config & 0xf) << 28) |
-			((1 << 24) << cpu_2_hwthread_id[get_cpu()]);
+			((1 << 24) << hard_processor_id());
+	if (metag_pmu->max_period)
+		/*
+		 * Cores supporting overflow interrupts may have had the counter
+		 * set to a specific value that needs preserving.
+		 */
+		tmp |= metag_in32(PERF_COUNT(idx)) & 0x00ffffff;
+	else
+		/*
+		 * Older cores reset the counter on write, so prev_count needs
+		 * resetting too so we can calculate a correct delta.
+		 */
+		local64_set(&event->prev_count, 0);
+
 	metag_out32(tmp, PERF_COUNT(idx));
 unlock:
 	raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
@@ -693,9 +716,8 @@ static u64 metag_pmu_read_counter(int idx)
 {
 	u32 tmp = 0;
 
-	/* The act of reading the cycle counter also clears it */
 	if (METAG_INST_COUNTER == idx) {
-		__core_reg_swap(TXTACTCYC, tmp);
+		tmp = __core_reg_get(TXTACTCYC);
 		goto out;
 	}
 
@@ -764,10 +786,16 @@ static irqreturn_t metag_pmu_counter_overflow(int irq, void *dev)
 
 	/*
 	 * Enable the counter again once core overflow processing has
-	 * completed.
+	 * completed. Note the counter value may have been modified while it was
+	 * inactive to set it up ready for the next interrupt.
 	 */
-	if (!perf_event_overflow(event, &sampledata, regs))
+	if (!perf_event_overflow(event, &sampledata, regs)) {
+		__global_lock2(flags);
+		counter = (counter & 0xff000000) |
+			  (metag_in32(PERF_COUNT(idx)) & 0x00ffffff);
 		metag_out32(counter, PERF_COUNT(idx));
+		__global_unlock2(flags);
+	}
 
 	return IRQ_HANDLED;
 }
@@ -830,7 +858,7 @@ static int __init init_hw_perf_events(void)
 			metag_pmu->max_period = 0;
 		}
 
-		metag_pmu->name = "Meta 2";
+		metag_pmu->name = "meta2";
 		metag_pmu->version = version;
 		metag_pmu->pmu = pmu;
 	}
diff --git a/arch/metag/kernel/ptrace.c b/arch/metag/kernel/ptrace.c
index 47a8828..7563628 100644
--- a/arch/metag/kernel/ptrace.c
+++ b/arch/metag/kernel/ptrace.c
@@ -288,10 +288,36 @@ static int metag_rp_state_set(struct task_struct *target,
 	return metag_rp_state_copyin(regs, pos, count, kbuf, ubuf);
 }
 
+static int metag_tls_get(struct task_struct *target,
+			const struct user_regset *regset,
+			unsigned int pos, unsigned int count,
+			void *kbuf, void __user *ubuf)
+{
+	void __user *tls = target->thread.tls_ptr;
+	return user_regset_copyout(&pos, &count, &kbuf, &ubuf, &tls, 0, -1);
+}
+
+static int metag_tls_set(struct task_struct *target,
+			const struct user_regset *regset,
+			unsigned int pos, unsigned int count,
+			const void *kbuf, const void __user *ubuf)
+{
+	int ret;
+	void __user *tls;
+
+	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &tls, 0, -1);
+	if (ret)
+		return ret;
+
+	target->thread.tls_ptr = tls;
+	return ret;
+}
+
 enum metag_regset {
 	REGSET_GENERAL,
 	REGSET_CBUF,
 	REGSET_READPIPE,
+	REGSET_TLS,
 };
 
 static const struct user_regset metag_regsets[] = {
@@ -319,6 +345,14 @@ static const struct user_regset metag_regsets[] = {
 		.get = metag_rp_state_get,
 		.set = metag_rp_state_set,
 	},
+	[REGSET_TLS] = {
+		.core_note_type = NT_METAG_TLS,
+		.n = 1,
+		.size = sizeof(void *),
+		.align = sizeof(void *),
+		.get = metag_tls_get,
+		.set = metag_tls_set,
+	},
 };
 
 static const struct user_regset_view user_metag_view = {
diff --git a/arch/metag/kernel/setup.c b/arch/metag/kernel/setup.c
index 8792461..4f5726f 100644
--- a/arch/metag/kernel/setup.c
+++ b/arch/metag/kernel/setup.c
@@ -124,6 +124,7 @@ struct machine_desc *machine_desc __initdata;
 u8 cpu_2_hwthread_id[NR_CPUS] __read_mostly = {
 	[0 ... NR_CPUS-1] = BAD_HWTHREAD_ID
 };
+EXPORT_SYMBOL_GPL(cpu_2_hwthread_id);
 
 /*
  * Map a hardware thread ID to a Linux CPU number
diff --git a/arch/metag/kernel/smp.c b/arch/metag/kernel/smp.c
index 4b6d1f14..4e7751a 100644
--- a/arch/metag/kernel/smp.c
+++ b/arch/metag/kernel/smp.c
@@ -28,6 +28,8 @@
 #include <asm/cachepart.h>
 #include <asm/core_reg.h>
 #include <asm/cpu.h>
+#include <asm/global_lock.h>
+#include <asm/metag_mem.h>
 #include <asm/mmu_context.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
@@ -37,6 +39,9 @@
 #include <asm/hwthread.h>
 #include <asm/traps.h>
 
+#define SYSC_DCPART(n)	(SYSC_DCPART0 + SYSC_xCPARTn_STRIDE * (n))
+#define SYSC_ICPART(n)	(SYSC_ICPART0 + SYSC_xCPARTn_STRIDE * (n))
+
 DECLARE_PER_CPU(PTBI, pTBI);
 
 void *secondary_data_stack;
@@ -99,6 +104,114 @@ int __cpuinit boot_secondary(unsigned int thread, struct task_struct *idle)
 	return 0;
 }
 
+/**
+ * describe_cachepart_change: describe a change to cache partitions.
+ * @thread:	Hardware thread number.
+ * @label:	Label of cache type, e.g. "dcache" or "icache".
+ * @sz:		Total size of the cache.
+ * @old:	Old cache partition configuration (*CPART* register).
+ * @new:	New cache partition configuration (*CPART* register).
+ *
+ * If the cache partition has changed, prints a message to the log describing
+ * those changes.
+ */
+static __cpuinit void describe_cachepart_change(unsigned int thread,
+						const char *label,
+						unsigned int sz,
+						unsigned int old,
+						unsigned int new)
+{
+	unsigned int lor1, land1, gor1, gand1;
+	unsigned int lor2, land2, gor2, gand2;
+	unsigned int diff = old ^ new;
+
+	if (!diff)
+		return;
+
+	pr_info("Thread %d: %s partition changed:", thread, label);
+	if (diff & (SYSC_xCPARTL_OR_BITS | SYSC_xCPARTL_AND_BITS)) {
+		lor1   = (old & SYSC_xCPARTL_OR_BITS)  >> SYSC_xCPARTL_OR_S;
+		lor2   = (new & SYSC_xCPARTL_OR_BITS)  >> SYSC_xCPARTL_OR_S;
+		land1  = (old & SYSC_xCPARTL_AND_BITS) >> SYSC_xCPARTL_AND_S;
+		land2  = (new & SYSC_xCPARTL_AND_BITS) >> SYSC_xCPARTL_AND_S;
+		pr_cont(" L:%#x+%#x->%#x+%#x",
+			(lor1 * sz) >> 4,
+			((land1 + 1) * sz) >> 4,
+			(lor2 * sz) >> 4,
+			((land2 + 1) * sz) >> 4);
+	}
+	if (diff & (SYSC_xCPARTG_OR_BITS | SYSC_xCPARTG_AND_BITS)) {
+		gor1   = (old & SYSC_xCPARTG_OR_BITS)  >> SYSC_xCPARTG_OR_S;
+		gor2   = (new & SYSC_xCPARTG_OR_BITS)  >> SYSC_xCPARTG_OR_S;
+		gand1  = (old & SYSC_xCPARTG_AND_BITS) >> SYSC_xCPARTG_AND_S;
+		gand2  = (new & SYSC_xCPARTG_AND_BITS) >> SYSC_xCPARTG_AND_S;
+		pr_cont(" G:%#x+%#x->%#x+%#x",
+			(gor1 * sz) >> 4,
+			((gand1 + 1) * sz) >> 4,
+			(gor2 * sz) >> 4,
+			((gand2 + 1) * sz) >> 4);
+	}
+	if (diff & SYSC_CWRMODE_BIT)
+		pr_cont(" %sWR",
+			(new & SYSC_CWRMODE_BIT) ? "+" : "-");
+	if (diff & SYSC_DCPART_GCON_BIT)
+		pr_cont(" %sGCOn",
+			(new & SYSC_DCPART_GCON_BIT) ? "+" : "-");
+	pr_cont("\n");
+}
+
+/**
+ * setup_smp_cache: ensure cache coherency for new SMP thread.
+ * @thread:	New hardware thread number.
+ *
+ * Ensures that coherency is enabled and that the threads share the same cache
+ * partitions.
+ */
+static __cpuinit void setup_smp_cache(unsigned int thread)
+{
+	unsigned int this_thread, lflags;
+	unsigned int dcsz, dcpart_this, dcpart_old, dcpart_new;
+	unsigned int icsz, icpart_old, icpart_new;
+
+	/*
+	 * Copy over the current thread's cache partition configuration to the
+	 * new thread so that they share cache partitions.
+	 */
+	__global_lock2(lflags);
+	this_thread = hard_processor_id();
+	/* Share dcache partition */
+	dcpart_this = metag_in32(SYSC_DCPART(this_thread));
+	dcpart_old = metag_in32(SYSC_DCPART(thread));
+	dcpart_new = dcpart_this;
+#if PAGE_OFFSET < LINGLOBAL_BASE
+	/*
+	 * For the local data cache to be coherent the threads must also have
+	 * GCOn enabled.
+	 */
+	dcpart_new |= SYSC_DCPART_GCON_BIT;
+	metag_out32(dcpart_new, SYSC_DCPART(this_thread));
+#endif
+	metag_out32(dcpart_new, SYSC_DCPART(thread));
+	/* Share icache partition too */
+	icpart_new = metag_in32(SYSC_ICPART(this_thread));
+	icpart_old = metag_in32(SYSC_ICPART(thread));
+	metag_out32(icpart_new, SYSC_ICPART(thread));
+	__global_unlock2(lflags);
+
+	/*
+	 * Log if the cache partitions were altered so the user is aware of any
+	 * potential unintentional cache wastage.
+	 */
+	dcsz = get_dcache_size();
+	icsz = get_dcache_size();
+	describe_cachepart_change(this_thread, "dcache", dcsz,
+				  dcpart_this, dcpart_new);
+	describe_cachepart_change(thread, "dcache", dcsz,
+				  dcpart_old, dcpart_new);
+	describe_cachepart_change(thread, "icache", icsz,
+				  icpart_old, icpart_new);
+}
+
 int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *idle)
 {
 	unsigned int thread = cpu_2_hwthread_id[cpu];
@@ -108,6 +221,8 @@ int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *idle)
 
 	flush_tlb_all();
 
+	setup_smp_cache(thread);
+
 	/*
 	 * Tell the secondary CPU where to find its idle thread's stack.
 	 */
diff --git a/arch/metag/mm/Kconfig b/arch/metag/mm/Kconfig
index 975f2f4..794f26a 100644
--- a/arch/metag/mm/Kconfig
+++ b/arch/metag/mm/Kconfig
@@ -98,9 +98,6 @@ config MAX_ACTIVE_REGIONS
 	default "2" if SPARSEMEM
 	default "1"
 
-config ARCH_POPULATES_NODE_MAP
-	def_bool y
-
 config ARCH_SELECT_MEMORY_MODEL
 	def_bool y
 
diff --git a/arch/metag/mm/init.c b/arch/metag/mm/init.c
index 504a398..d05b845 100644
--- a/arch/metag/mm/init.c
+++ b/arch/metag/mm/init.c
@@ -380,14 +380,8 @@ void __init mem_init(void)
 
 #ifdef CONFIG_HIGHMEM
 	unsigned long tmp;
-	for (tmp = highstart_pfn; tmp < highend_pfn; tmp++) {
-		struct page *page = pfn_to_page(tmp);
-		ClearPageReserved(page);
-		init_page_count(page);
-		__free_page(page);
-		totalhigh_pages++;
-	}
-	totalram_pages += totalhigh_pages;
+	for (tmp = highstart_pfn; tmp < highend_pfn; tmp++)
+		free_highmem_page(pfn_to_page(tmp));
 	num_physpages += totalhigh_pages;
 #endif /* CONFIG_HIGHMEM */
 
@@ -412,32 +406,15 @@ void __init mem_init(void)
 	return;
 }
 
-static void free_init_pages(char *what, unsigned long begin, unsigned long end)
-{
-	unsigned long addr;
-
-	for (addr = begin; addr < end; addr += PAGE_SIZE) {
-		ClearPageReserved(virt_to_page(addr));
-		init_page_count(virt_to_page(addr));
-		memset((void *)addr, POISON_FREE_INITMEM, PAGE_SIZE);
-		free_page(addr);
-		totalram_pages++;
-	}
-	pr_info("Freeing %s: %luk freed\n", what, (end - begin) >> 10);
-}
-
 void free_initmem(void)
 {
-	free_init_pages("unused kernel memory",
-			(unsigned long)(&__init_begin),
-			(unsigned long)(&__init_end));
+	free_initmem_default(POISON_FREE_INITMEM);
 }
 
 #ifdef CONFIG_BLK_DEV_INITRD
 void free_initrd_mem(unsigned long start, unsigned long end)
 {
-	end = end & PAGE_MASK;
-	free_init_pages("initrd memory", start, end);
+	free_reserved_area(start, end, POISON_FREE_INITMEM, "initrd");
 }
 #endif
 
diff --git a/arch/metag/oprofile/Makefile b/arch/metag/oprofile/Makefile
new file mode 100644
index 0000000..c9639d4
--- /dev/null
+++ b/arch/metag/oprofile/Makefile
@@ -0,0 +1,17 @@
+obj-$(CONFIG_OPROFILE)	+= oprofile.o
+
+oprofile-core-y	+= buffer_sync.o
+oprofile-core-y	+= cpu_buffer.o
+oprofile-core-y	+= event_buffer.o
+oprofile-core-y	+= oprof.o
+oprofile-core-y	+= oprofile_files.o
+oprofile-core-y	+= oprofile_stats.o
+oprofile-core-y	+= oprofilefs.o
+oprofile-core-y	+= timer_int.o
+oprofile-core-$(CONFIG_HW_PERF_EVENTS)	+= oprofile_perf.o
+
+oprofile-y	+= backtrace.o
+oprofile-y	+= common.o
+oprofile-y	+= $(addprefix ../../../drivers/oprofile/,$(oprofile-core-y))
+
+ccflags-y	+= -Werror
diff --git a/arch/metag/oprofile/backtrace.c b/arch/metag/oprofile/backtrace.c
new file mode 100644
index 0000000..7cc3f37
--- /dev/null
+++ b/arch/metag/oprofile/backtrace.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2010-2013 Imagination Technologies Ltd.
+ *
+ * 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/oprofile.h>
+#include <linux/uaccess.h>
+#include <asm/processor.h>
+#include <asm/stacktrace.h>
+
+#include "backtrace.h"
+
+static void user_backtrace_fp(unsigned long __user *fp, unsigned int depth)
+{
+	while (depth-- && access_ok(VERIFY_READ, fp, 8)) {
+		unsigned long addr;
+		unsigned long __user *fpnew;
+		if (__copy_from_user_inatomic(&addr, fp + 1, sizeof(addr)))
+			break;
+		addr -= 4;
+
+		oprofile_add_trace(addr);
+
+		/* stack grows up, so frame pointers must decrease */
+		if (__copy_from_user_inatomic(&fpnew, fp + 0, sizeof(fpnew)))
+			break;
+		if (fpnew >= fp)
+			break;
+		fp = fpnew;
+	}
+}
+
+static int kernel_backtrace_frame(struct stackframe *frame, void *data)
+{
+	unsigned int *depth = data;
+
+	oprofile_add_trace(frame->pc);
+
+	/* decrement depth and stop if we reach 0 */
+	if ((*depth)-- == 0)
+		return 1;
+
+	/* otherwise onto the next frame */
+	return 0;
+}
+
+void metag_backtrace(struct pt_regs * const regs, unsigned int depth)
+{
+	if (user_mode(regs)) {
+		unsigned long *fp = (unsigned long *)regs->ctx.AX[1].U0;
+		user_backtrace_fp((unsigned long __user __force *)fp, depth);
+	} else {
+		struct stackframe frame;
+		frame.fp = regs->ctx.AX[1].U0;		/* A0FrP */
+		frame.sp = user_stack_pointer(regs);	/* A0StP */
+		frame.lr = 0;				/* from stack */
+		frame.pc = regs->ctx.CurrPC;		/* PC */
+		walk_stackframe(&frame, &kernel_backtrace_frame, &depth);
+	}
+}
diff --git a/arch/metag/oprofile/backtrace.h b/arch/metag/oprofile/backtrace.h
new file mode 100644
index 0000000..c0fcc42
--- /dev/null
+++ b/arch/metag/oprofile/backtrace.h
@@ -0,0 +1,6 @@
+#ifndef _METAG_OPROFILE_BACKTRACE_H
+#define _METAG_OPROFILE_BACKTRACE_H
+
+void metag_backtrace(struct pt_regs * const regs, unsigned int depth);
+
+#endif
diff --git a/arch/metag/oprofile/common.c b/arch/metag/oprofile/common.c
new file mode 100644
index 0000000..ba26152
--- /dev/null
+++ b/arch/metag/oprofile/common.c
@@ -0,0 +1,66 @@
+/*
+ * arch/metag/oprofile/common.c
+ *
+ * Copyright (C) 2013 Imagination Technologies Ltd.
+ *
+ * Based on arch/sh/oprofile/common.c:
+ *
+ * Copyright (C) 2003 - 2010  Paul Mundt
+ *
+ * Based on arch/mips/oprofile/common.c:
+ *
+ *	Copyright (C) 2004, 2005 Ralf Baechle
+ *	Copyright (C) 2005 MIPS Technologies, Inc.
+ *
+ * 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/errno.h>
+#include <linux/init.h>
+#include <linux/oprofile.h>
+#include <linux/perf_event.h>
+#include <linux/slab.h>
+
+#include "backtrace.h"
+
+#ifdef CONFIG_HW_PERF_EVENTS
+/*
+ * This will need to be reworked when multiple PMUs are supported.
+ */
+static char *metag_pmu_op_name;
+
+char *op_name_from_perf_id(void)
+{
+	return metag_pmu_op_name;
+}
+
+int __init oprofile_arch_init(struct oprofile_operations *ops)
+{
+	ops->backtrace = metag_backtrace;
+
+	if (perf_num_counters() == 0)
+		return -ENODEV;
+
+	metag_pmu_op_name = kasprintf(GFP_KERNEL, "metag/%s",
+				      perf_pmu_name());
+	if (unlikely(!metag_pmu_op_name))
+		return -ENOMEM;
+
+	return oprofile_perf_init(ops);
+}
+
+void oprofile_arch_exit(void)
+{
+	oprofile_perf_exit();
+	kfree(metag_pmu_op_name);
+}
+#else
+int __init oprofile_arch_init(struct oprofile_operations *ops)
+{
+	ops->backtrace = metag_backtrace;
+	/* fall back to timer interrupt PC sampling */
+	return -ENODEV;
+}
+void oprofile_arch_exit(void) {}
+#endif /* CONFIG_HW_PERF_EVENTS */
diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig
index 1323fa2..173ab2c 100644
--- a/arch/microblaze/Kconfig
+++ b/arch/microblaze/Kconfig
@@ -38,9 +38,6 @@ config RWSEM_GENERIC_SPINLOCK
 config ZONE_DMA
 	def_bool y
 
-config ARCH_POPULATES_NODE_MAP
-	def_bool y
-
 config RWSEM_XCHGADD_ALGORITHM
 	bool
 
diff --git a/arch/microblaze/include/asm/setup.h b/arch/microblaze/include/asm/setup.h
index 0e0b0a5..f05df56 100644
--- a/arch/microblaze/include/asm/setup.h
+++ b/arch/microblaze/include/asm/setup.h
@@ -46,7 +46,6 @@ void machine_shutdown(void);
 void machine_halt(void);
 void machine_power_off(void);
 
-void free_init_pages(char *what, unsigned long begin, unsigned long end);
 extern void *alloc_maybe_bootmem(size_t size, gfp_t mask);
 extern void *zalloc_maybe_bootmem(size_t size, gfp_t mask);
 
diff --git a/arch/microblaze/include/asm/unistd.h b/arch/microblaze/include/asm/unistd.h
index b377839..6dece2d 100644
--- a/arch/microblaze/include/asm/unistd.h
+++ b/arch/microblaze/include/asm/unistd.h
@@ -37,13 +37,5 @@
 #define __ARCH_WANT_SYS_VFORK
 #define __ARCH_WANT_SYS_FORK
 
-/*
- * "Conditional" syscalls
- *
- * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
- * but it doesn't work on all toolchains, so we just do it by hand
- */
-#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
-
 #endif /* __ASSEMBLY__ */
 #endif /* _ASM_MICROBLAZE_UNISTD_H */
diff --git a/arch/microblaze/kernel/early_printk.c b/arch/microblaze/kernel/early_printk.c
index 60dcacc..365f2d5 100644
--- a/arch/microblaze/kernel/early_printk.c
+++ b/arch/microblaze/kernel/early_printk.c
@@ -21,7 +21,6 @@
 #include <asm/setup.h>
 #include <asm/prom.h>
 
-static u32 early_console_initialized;
 static u32 base_addr;
 
 #ifdef CONFIG_SERIAL_UARTLITE_CONSOLE
@@ -109,27 +108,11 @@ static struct console early_serial_uart16550_console = {
 };
 #endif /* CONFIG_SERIAL_8250_CONSOLE */
 
-static struct console *early_console;
-
-void early_printk(const char *fmt, ...)
-{
-	char buf[512];
-	int n;
-	va_list ap;
-
-	if (early_console_initialized) {
-		va_start(ap, fmt);
-		n = vscnprintf(buf, 512, fmt, ap);
-		early_console->write(early_console, buf, n);
-		va_end(ap);
-	}
-}
-
 int __init setup_early_printk(char *opt)
 {
 	int version = 0;
 
-	if (early_console_initialized)
+	if (early_console)
 		return 1;
 
 	base_addr = of_early_console(&version);
@@ -159,7 +142,6 @@ int __init setup_early_printk(char *opt)
 		}
 
 		register_console(early_console);
-		early_console_initialized = 1;
 		return 0;
 	}
 	return 1;
@@ -169,7 +151,7 @@ int __init setup_early_printk(char *opt)
  * only for early console because of performance degression */
 void __init remap_early_printk(void)
 {
-	if (!early_console_initialized || !early_console)
+	if (!early_console)
 		return;
 	pr_info("early_printk_console remapping from 0x%x to ", base_addr);
 	base_addr = (u32) ioremap(base_addr, PAGE_SIZE);
@@ -194,9 +176,9 @@ void __init remap_early_printk(void)
 
 void __init disable_early_printk(void)
 {
-	if (!early_console_initialized || !early_console)
+	if (!early_console)
 		return;
 	pr_warn("disabling early console\n");
 	unregister_console(early_console);
-	early_console_initialized = 0;
+	early_console = NULL;
 }
diff --git a/arch/microblaze/kernel/intc.c b/arch/microblaze/kernel/intc.c
index 8778adf..d85fa3a 100644
--- a/arch/microblaze/kernel/intc.c
+++ b/arch/microblaze/kernel/intc.c
@@ -172,4 +172,6 @@ void __init init_IRQ(void)
 	 * and commits this patch.  ~~gcl */
 	root_domain = irq_domain_add_linear(intc, nr_irq, &xintc_irq_domain_ops,
 							(void *)intr_mask);
+
+	irq_set_default_host(root_domain);
 }
diff --git a/arch/microblaze/mm/init.c b/arch/microblaze/mm/init.c
index 8f8b367..4ec137d 100644
--- a/arch/microblaze/mm/init.c
+++ b/arch/microblaze/mm/init.c
@@ -82,13 +82,9 @@ static unsigned long highmem_setup(void)
 		/* FIXME not sure about */
 		if (memblock_is_reserved(pfn << PAGE_SHIFT))
 			continue;
-		ClearPageReserved(page);
-		init_page_count(page);
-		__free_page(page);
-		totalhigh_pages++;
+		free_highmem_page(page);
 		reservedpages++;
 	}
-	totalram_pages += totalhigh_pages;
 	pr_info("High memory: %luk\n",
 					totalhigh_pages << (PAGE_SHIFT-10));
 
@@ -236,40 +232,16 @@ void __init setup_memory(void)
 	paging_init();
 }
 
-void free_init_pages(char *what, unsigned long begin, unsigned long end)
-{
-	unsigned long addr;
-
-	for (addr = begin; addr < end; addr += PAGE_SIZE) {
-		ClearPageReserved(virt_to_page(addr));
-		init_page_count(virt_to_page(addr));
-		free_page(addr);
-		totalram_pages++;
-	}
-	pr_info("Freeing %s: %ldk freed\n", what, (end - begin) >> 10);
-}
-
 #ifdef CONFIG_BLK_DEV_INITRD
 void free_initrd_mem(unsigned long start, unsigned long end)
 {
-	int pages = 0;
-	for (; start < end; start += PAGE_SIZE) {
-		ClearPageReserved(virt_to_page(start));
-		init_page_count(virt_to_page(start));
-		free_page(start);
-		totalram_pages++;
-		pages++;
-	}
-	pr_notice("Freeing initrd memory: %dk freed\n",
-					(int)(pages * (PAGE_SIZE / 1024)));
+	free_reserved_area(start, end, 0, "initrd");
 }
 #endif
 
 void free_initmem(void)
 {
-	free_init_pages("unused kernel memory",
-			(unsigned long)(&__init_begin),
-			(unsigned long)(&__init_end));
+	free_initmem_default(0);
 }
 
 void __init mem_init(void)
diff --git a/arch/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-common.c
index 9ea521e..bdb8ea1 100644
--- a/arch/microblaze/pci/pci-common.c
+++ b/arch/microblaze/pci/pci-common.c
@@ -30,7 +30,6 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_pci.h>
-#include <linux/pci.h>
 #include <linux/export.h>
 
 #include <asm/processor.h>
diff --git a/arch/mips/Kbuild b/arch/mips/Kbuild
index 7dd65cf..d2cfe45 100644
--- a/arch/mips/Kbuild
+++ b/arch/mips/Kbuild
@@ -17,3 +17,7 @@ obj- := $(platform-)
 obj-y += kernel/
 obj-y += mm/
 obj-y += math-emu/
+
+ifdef CONFIG_KVM
+obj-y += kvm/
+endif
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index cd2e21f..652bd31 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -18,7 +18,7 @@ config MIPS
 	select HAVE_KRETPROBES
 	select HAVE_DEBUG_KMEMLEAK
 	select ARCH_BINFMT_ELF_RANDOMIZE_PIE
-	select HAVE_ARCH_TRANSPARENT_HUGEPAGE
+	select HAVE_ARCH_TRANSPARENT_HUGEPAGE if CPU_SUPPORTS_HUGEPAGES && 64BIT
 	select RTC_LIB if !MACH_LOONGSON
 	select GENERIC_ATOMIC64 if !64BIT
 	select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
@@ -61,8 +61,7 @@ config MIPS_ALCHEMY
 	select SYS_HAS_CPU_MIPS32_R1
 	select SYS_SUPPORTS_32BIT_KERNEL
 	select SYS_SUPPORTS_APM_EMULATION
-	select GENERIC_GPIO
-	select ARCH_WANT_OPTIONAL_GPIOLIB
+	select ARCH_REQUIRE_GPIOLIB
 	select SYS_SUPPORTS_ZBOOT
 	select USB_ARCH_HAS_OHCI
 	select USB_ARCH_HAS_EHCI
@@ -225,7 +224,6 @@ config MACH_JZ4740
 	select SYS_SUPPORTS_ZBOOT_UART16550
 	select DMA_NONCOHERENT
 	select IRQ_CPU
-	select GENERIC_GPIO
 	select ARCH_REQUIRE_GPIOLIB
 	select SYS_HAS_EARLY_PRINTK
 	select HAVE_PWM
@@ -354,6 +352,7 @@ config MIPS_SEAD3
 	select SYS_SUPPORTS_BIG_ENDIAN
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 	select SYS_SUPPORTS_SMARTMIPS
+	select SYS_SUPPORTS_MICROMIPS
 	select USB_ARCH_HAS_EHCI
 	select USB_EHCI_BIG_ENDIAN_DESC
 	select USB_EHCI_BIG_ENDIAN_MMIO
@@ -935,7 +934,6 @@ config CSRC_SB1250
 	bool
 
 config GPIO_TXX9
-	select GENERIC_GPIO
 	select ARCH_REQUIRE_GPIOLIB
 	bool
 
@@ -1110,7 +1108,6 @@ config SOC_PNX833X
 	select SYS_SUPPORTS_32BIT_KERNEL
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 	select SYS_SUPPORTS_BIG_ENDIAN
-	select GENERIC_GPIO
 	select CPU_MIPSR2_IRQ_VI
 
 config SOC_PNX8335
@@ -1201,7 +1198,6 @@ config CPU_LOONGSON2F
 	bool "Loongson 2F"
 	depends on SYS_HAS_CPU_LOONGSON2F
 	select CPU_LOONGSON2
-	select GENERIC_GPIO
 	select ARCH_REQUIRE_GPIOLIB
 	help
 	  The Loongson 2F processor implements the MIPS III instruction set
@@ -1242,6 +1238,7 @@ config CPU_MIPS32_R2
 	select CPU_HAS_PREFETCH
 	select CPU_SUPPORTS_32BIT_KERNEL
 	select CPU_SUPPORTS_HIGHMEM
+	select HAVE_KVM
 	help
 	  Choose this option to build a kernel for release 2 or later of the
 	  MIPS32 architecture.  Most modern embedded systems with a 32-bit
@@ -1493,7 +1490,6 @@ config CPU_XLP
 	select CPU_SUPPORTS_32BIT_KERNEL
 	select CPU_SUPPORTS_64BIT_KERNEL
 	select CPU_SUPPORTS_HIGHMEM
-	select CPU_HAS_LLSC
 	select WEAK_ORDERING
 	select WEAK_REORDERING_BEYOND_LLSC
 	select CPU_HAS_PREFETCH
@@ -1737,12 +1733,25 @@ config 32BIT
 config 64BIT
 	bool "64-bit kernel"
 	depends on CPU_SUPPORTS_64BIT_KERNEL && SYS_SUPPORTS_64BIT_KERNEL
-	select HAVE_SYSCALL_WRAPPERS
 	help
 	  Select this option if you want to build a 64-bit kernel.
 
 endchoice
 
+config KVM_GUEST
+	bool "KVM Guest Kernel"
+	help
+	  Select this option if building a guest kernel for KVM (Trap & Emulate) mode
+
+config KVM_HOST_FREQ
+	int "KVM Host Processor Frequency (MHz)"
+	depends on KVM_GUEST
+	default 500
+	help
+	  Select this option if building a guest kernel for KVM to skip
+	  RTC emulation when determining guest CPU Frequency.  Instead, the guest
+	  processor frequency is automatically derived from the host frequency.
+
 choice
 	prompt "Kernel page size"
 	default PAGE_SIZE_4KB
@@ -2023,6 +2032,7 @@ config SB1_PASS_2_1_WORKAROUNDS
 	depends on CPU_SB1 && CPU_SB1_PASS_2
 	default y
 
+
 config 64BIT_PHYS_ADDR
 	bool
 
@@ -2103,6 +2113,9 @@ config SYS_SUPPORTS_HIGHMEM
 config SYS_SUPPORTS_SMARTMIPS
 	bool
 
+config SYS_SUPPORTS_MICROMIPS
+	bool
+
 config ARCH_FLATMEM_ENABLE
 	def_bool y
 	depends on !NUMA && !CPU_LOONGSON2
@@ -2556,3 +2569,5 @@ source "security/Kconfig"
 source "crypto/Kconfig"
 
 source "lib/Kconfig"
+
+source "arch/mips/kvm/Kconfig"
diff --git a/arch/mips/bcm63xx/boards/board_bcm963xx.c b/arch/mips/bcm63xx/boards/board_bcm963xx.c
index ed1949c..9aa7d44 100644
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -745,10 +745,7 @@ void __init board_prom_init(void)
 		strcpy(cfe_version, "unknown");
 	printk(KERN_INFO PFX "CFE version: %s\n", cfe_version);
 
-	if (bcm63xx_nvram_init(boot_addr + BCM963XX_NVRAM_OFFSET)) {
-		printk(KERN_ERR PFX "invalid nvram checksum\n");
-		return;
-	}
+	bcm63xx_nvram_init(boot_addr + BCM963XX_NVRAM_OFFSET);
 
 	board_name = bcm63xx_nvram_get_name();
 	/* find board by name */
diff --git a/arch/mips/bcm63xx/nvram.c b/arch/mips/bcm63xx/nvram.c
index 6206116..a4b8864 100644
--- a/arch/mips/bcm63xx/nvram.c
+++ b/arch/mips/bcm63xx/nvram.c
@@ -38,7 +38,7 @@ struct bcm963xx_nvram {
 static struct bcm963xx_nvram nvram;
 static int mac_addr_used;
 
-int __init bcm63xx_nvram_init(void *addr)
+void __init bcm63xx_nvram_init(void *addr)
 {
 	unsigned int check_len;
 	u32 crc, expected_crc;
@@ -60,9 +60,8 @@ int __init bcm63xx_nvram_init(void *addr)
 	crc = crc32_le(~0, (u8 *)&nvram, check_len);
 
 	if (crc != expected_crc)
-		return -EINVAL;
-
-	return 0;
+		pr_warn("nvram checksum failed, contents may be invalid (expected %08x, got %08x)\n",
+			expected_crc, crc);
 }
 
 u8 *bcm63xx_nvram_get_name(void)
diff --git a/arch/mips/bcm63xx/setup.c b/arch/mips/bcm63xx/setup.c
index 314231b..35e18e9 100644
--- a/arch/mips/bcm63xx/setup.c
+++ b/arch/mips/bcm63xx/setup.c
@@ -157,4 +157,4 @@ int __init bcm63xx_register_devices(void)
 	return board_register_devices();
 }
 
-device_initcall(bcm63xx_register_devices);
+arch_initcall(bcm63xx_register_devices);
diff --git a/arch/mips/configs/malta_kvm_defconfig b/arch/mips/configs/malta_kvm_defconfig
new file mode 100644
index 0000000..88bf758
--- /dev/null
+++ b/arch/mips/configs/malta_kvm_defconfig
@@ -0,0 +1,2267 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Linux/mips 3.7.0-rc5 Kernel Configuration
+#
+CONFIG_MIPS=y
+
+#
+# Machine selection
+#
+CONFIG_ZONE_DMA=y
+# CONFIG_MIPS_ALCHEMY is not set
+# CONFIG_AR7 is not set
+# CONFIG_ATH79 is not set
+# CONFIG_BCM47XX is not set
+# CONFIG_BCM63XX is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_MACH_JZ4740 is not set
+# CONFIG_LANTIQ is not set
+# CONFIG_LASAT is not set
+# CONFIG_MACH_LOONGSON is not set
+# CONFIG_MACH_LOONGSON1 is not set
+CONFIG_MIPS_MALTA=y
+# CONFIG_MIPS_SEAD3 is not set
+# CONFIG_NEC_MARKEINS is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_NXP_STB220 is not set
+# CONFIG_NXP_STB225 is not set
+# CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
+# CONFIG_PMC_MSP is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_POWERTV is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP28 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_CRHONE is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SNI_RM is not set
+# CONFIG_MACH_TX39XX is not set
+# CONFIG_MACH_TX49XX is not set
+# CONFIG_MIKROTIK_RB532 is not set
+# CONFIG_WR_PPMC is not set
+# CONFIG_CAVIUM_OCTEON_SIMULATOR is not set
+# CONFIG_CAVIUM_OCTEON_REFERENCE_BOARD is not set
+# CONFIG_NLM_XLR_BOARD is not set
+# CONFIG_NLM_XLP_BOARD is not set
+# CONFIG_ALCHEMY_GPIO_INDIRECT is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_BOOT_RAW=y
+CONFIG_CEVT_R4K_LIB=y
+CONFIG_CEVT_R4K=y
+CONFIG_CSRC_R4K_LIB=y
+CONFIG_CSRC_R4K=y
+# CONFIG_ARCH_DMA_ADDR_T_64BIT is not set
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_SYS_HAS_EARLY_PRINTK=y
+CONFIG_I8259=y
+CONFIG_MIPS_BONITO64=y
+CONFIG_MIPS_MSC=y
+# CONFIG_MIPS_MACHINE is not set
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_ISA_DMA_API=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_IRQ_GIC=y
+CONFIG_MIPS_BOARDS_GEN=y
+CONFIG_PCI_GT64XXX_PCI0=y
+CONFIG_SWAP_IO_SPACE=y
+CONFIG_BOOT_ELF32=y
+CONFIG_MIPS_L1_CACHE_SHIFT=6
+
+#
+# CPU selection
+#
+# CONFIG_CPU_MIPS32_R1 is not set
+CONFIG_CPU_MIPS32_R2=y
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_RM7000 is not set
+CONFIG_SYS_SUPPORTS_ZBOOT=y
+CONFIG_SYS_HAS_CPU_MIPS32_R1=y
+CONFIG_SYS_HAS_CPU_MIPS32_R2=y
+CONFIG_SYS_HAS_CPU_MIPS64_R1=y
+CONFIG_SYS_HAS_CPU_MIPS64_R2=y
+CONFIG_SYS_HAS_CPU_NEVADA=y
+CONFIG_SYS_HAS_CPU_RM7000=y
+CONFIG_CPU_MIPS32=y
+CONFIG_CPU_MIPSR2=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_HARDWARE_WATCHPOINTS=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_KVM_GUEST is not set
+CONFIG_KVM_HOST_FREQ=500
+# CONFIG_PAGE_SIZE_4KB is not set
+CONFIG_PAGE_SIZE_16KB=y
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_BOARD_SCACHE=y
+CONFIG_MIPS_CPU_SCACHE=y
+CONFIG_CPU_HAS_PREFETCH=y
+CONFIG_CPU_GENERIC_DUMP_TLB=y
+CONFIG_CPU_R4K_FPU=y
+CONFIG_CPU_R4K_CACHE_TLB=y
+# CONFIG_MIPS_MT_DISABLED is not set
+CONFIG_MIPS_MT_SMP=y
+# CONFIG_MIPS_MT_SMTC is not set
+CONFIG_MIPS_MT=y
+# CONFIG_SCHED_SMT is not set
+CONFIG_SYS_SUPPORTS_SCHED_SMT=y
+CONFIG_SYS_SUPPORTS_MULTITHREADING=y
+CONFIG_MIPS_MT_FPAFF=y
+# CONFIG_MIPS_VPE_LOADER is not set
+# CONFIG_MIPS_CMP is not set
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
+# CONFIG_CPU_HAS_SMARTMIPS is not set
+CONFIG_CPU_MIPSR2_IRQ_VI=y
+CONFIG_CPU_MIPSR2_IRQ_EI=y
+CONFIG_CPU_HAS_SYNC=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
+CONFIG_SYS_SUPPORTS_SMARTMIPS=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_HW_PERF_EVENTS=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_HAVE_MEMBLOCK_NODE_MAP=y
+CONFIG_ARCH_DISCARD_MEMBLOCK=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_COMPACTION=y
+CONFIG_MIGRATION=y
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_CROSS_MEMORY_ATTACH=y
+# CONFIG_CLEANCACHE is not set
+# CONFIG_FRONTSWAP is not set
+CONFIG_SMP=y
+CONFIG_SMP_UP=y
+CONFIG_SYS_SUPPORTS_MIPS_CMP=y
+CONFIG_SYS_SUPPORTS_SMP=y
+CONFIG_NR_CPUS_DEFAULT_2=y
+CONFIG_NR_CPUS=2
+CONFIG_MIPS_PERF_SHARED_TC_COUNTERS=y
+# CONFIG_HZ_48 is not set
+CONFIG_HZ_100=y
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+# CONFIG_HZ_1000 is not set
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=100
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_KEXEC is not set
+CONFIG_SECCOMP=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_HAVE_IRQ_WORK=y
+CONFIG_IRQ_WORK=y
+CONFIG_BUILDTIME_EXTABLE_SORT=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE=""
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_BZIP2=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_BZIP2 is not set
+# CONFIG_KERNEL_LZMA is not set
+# CONFIG_KERNEL_LZO is not set
+CONFIG_DEFAULT_HOSTNAME="(none)"
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_FHANDLE is not set
+# CONFIG_AUDIT is not set
+CONFIG_HAVE_GENERIC_HARDIRQS=y
+
+#
+# IRQ subsystem
+#
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_IRQ_FORCED_THREADING=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+
+#
+# Timers subsystem
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+
+#
+# CPU/Task time and stats accounting
+#
+CONFIG_TICK_CPU_ACCOUNTING=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TREE_RCU=y
+# CONFIG_PREEMPT_RCU is not set
+CONFIG_RCU_FANOUT=32
+CONFIG_RCU_FANOUT_LEAF=16
+# CONFIG_RCU_FANOUT_EXACT is not set
+# CONFIG_RCU_FAST_NO_HZ is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=15
+# CONFIG_CGROUPS is not set
+# CONFIG_CHECKPOINT_RESTORE is not set
+CONFIG_NAMESPACES=y
+CONFIG_UTS_NS=y
+CONFIG_IPC_NS=y
+CONFIG_PID_NS=y
+CONFIG_NET_NS=y
+# CONFIG_SCHED_AUTOGROUP is not set
+# CONFIG_SYSFS_DEPRECATED is not set
+CONFIG_RELAY=y
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EXPERT=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_PCSPKR_PLATFORM=y
+CONFIG_HAVE_PCSPKR_PLATFORM=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+# CONFIG_EMBEDDED is not set
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_PERF_USE_VMALLOC=y
+
+#
+# Kernel Performance Events And Counters
+#
+CONFIG_PERF_EVENTS=y
+# CONFIG_DEBUG_PERF_USE_VMALLOC is not set
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_PCI_QUIRKS=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+CONFIG_TRACEPOINTS=y
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+# CONFIG_JUMP_LABEL is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_DMA_ATTRS=y
+CONFIG_USE_GENERIC_SMP_HELPERS=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
+CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
+CONFIG_MODULES_USE_ELF_REL=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+# CONFIG_MODULE_SIG is not set
+CONFIG_STOP_MACHINE=y
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+CONFIG_BLK_DEV_BSG=y
+CONFIG_BLK_DEV_BSGLIB=y
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_PREEMPT_NOTIFIERS=y
+CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
+CONFIG_INLINE_READ_UNLOCK=y
+CONFIG_INLINE_READ_UNLOCK_IRQ=y
+CONFIG_INLINE_WRITE_UNLOCK=y
+CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
+CONFIG_MUTEX_SPIN_ON_OWNER=y
+# CONFIG_FREEZER is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_REALLOC_ENABLE_AUTO is not set
+# CONFIG_PCI_STUB is not set
+# CONFIG_PCI_IOV is not set
+# CONFIG_PCI_PRI is not set
+# CONFIG_PCI_PASID is not set
+# CONFIG_PCIEPORTBUS is not set
+CONFIG_MMU=y
+CONFIG_I8253=y
+# CONFIG_PCCARD is not set
+# CONFIG_HOTPLUG_PCI is not set
+# CONFIG_RAPIDIO is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y
+CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+CONFIG_COREDUMP=y
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Power management options
+#
+# CONFIG_PM_RUNTIME is not set
+CONFIG_MIPS_EXTERNAL_TIMER=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_DIAG is not set
+CONFIG_UNIX=y
+# CONFIG_UNIX_DIAG is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_ALGO=y
+CONFIG_XFRM_USER=m
+# CONFIG_XFRM_SUB_POLICY is not set
+CONFIG_XFRM_MIGRATE=y
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_XFRM_IPCOMP=m
+CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+# CONFIG_IP_FIB_TRIE_STATS is not set
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_ROUTE_CLASSID=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+CONFIG_NET_IPIP=m
+# CONFIG_NET_IPGRE_DEMUX is not set
+CONFIG_IP_MROUTE=y
+# CONFIG_IP_MROUTE_MULTIPLE_TABLES is not set
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_NET_IPVTI is not set
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_LRO=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_INET_UDP_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+# CONFIG_IPV6_MIP6 is not set
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=m
+# CONFIG_IPV6_SIT_6RD is not set
+CONFIG_IPV6_NDISC_NODETYPE=y
+CONFIG_IPV6_TUNNEL=m
+# CONFIG_IPV6_GRE is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+CONFIG_IPV6_MROUTE=y
+# CONFIG_IPV6_MROUTE_MULTIPLE_TABLES is not set
+CONFIG_IPV6_PIMSM_V2=y
+CONFIG_NETWORK_SECMARK=y
+# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+# CONFIG_NETFILTER_NETLINK_ACCT is not set
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_PROCFS=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+# CONFIG_NF_CONNTRACK_TIMEOUT is not set
+# CONFIG_NF_CONNTRACK_TIMESTAMP is not set
+CONFIG_NF_CT_PROTO_DCCP=m
+CONFIG_NF_CT_PROTO_GRE=m
+CONFIG_NF_CT_PROTO_SCTP=m
+CONFIG_NF_CT_PROTO_UDPLITE=m
+CONFIG_NF_CONNTRACK_AMANDA=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_H323=m
+CONFIG_NF_CONNTRACK_IRC=m
+# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
+# CONFIG_NF_CONNTRACK_SNMP is not set
+CONFIG_NF_CONNTRACK_PPTP=m
+CONFIG_NF_CONNTRACK_SANE=m
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NF_CT_NETLINK=m
+# CONFIG_NF_CT_NETLINK_TIMEOUT is not set
+# CONFIG_NETFILTER_NETLINK_QUEUE_CT is not set
+CONFIG_NETFILTER_TPROXY=m
+CONFIG_NETFILTER_XTABLES=m
+
+#
+# Xtables combined modules
+#
+CONFIG_NETFILTER_XT_MARK=m
+CONFIG_NETFILTER_XT_CONNMARK=m
+
+#
+# Xtables targets
+#
+# CONFIG_NETFILTER_XT_TARGET_CHECKSUM is not set
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+# CONFIG_NETFILTER_XT_TARGET_CONNSECMARK is not set
+# CONFIG_NETFILTER_XT_TARGET_CT is not set
+# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
+CONFIG_NETFILTER_XT_TARGET_HL=m
+# CONFIG_NETFILTER_XT_TARGET_HMARK is not set
+# CONFIG_NETFILTER_XT_TARGET_IDLETIMER is not set
+# CONFIG_NETFILTER_XT_TARGET_LOG is not set
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_RATEEST=m
+# CONFIG_NETFILTER_XT_TARGET_TEE is not set
+CONFIG_NETFILTER_XT_TARGET_TPROXY=m
+CONFIG_NETFILTER_XT_TARGET_TRACE=m
+CONFIG_NETFILTER_XT_TARGET_SECMARK=m
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
+CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
+
+#
+# Xtables matches
+#
+# CONFIG_NETFILTER_XT_MATCH_ADDRTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_CLUSTER is not set
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+# CONFIG_NETFILTER_XT_MATCH_CPU is not set
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+# CONFIG_NETFILTER_XT_MATCH_DEVGROUP is not set
+# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
+CONFIG_NETFILTER_XT_MATCH_ECN=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_HL=m
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
+# CONFIG_NETFILTER_XT_MATCH_IPVS is not set
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+# CONFIG_NETFILTER_XT_MATCH_NFACCT is not set
+# CONFIG_NETFILTER_XT_MATCH_OSF is not set
+CONFIG_NETFILTER_XT_MATCH_OWNER=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_RATEEST=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_RECENT=m
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_SOCKET=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_TIME=m
+CONFIG_NETFILTER_XT_MATCH_U32=m
+# CONFIG_IP_SET is not set
+CONFIG_IP_VS=m
+CONFIG_IP_VS_IPV6=y
+# CONFIG_IP_VS_DEBUG is not set
+CONFIG_IP_VS_TAB_BITS=12
+
+#
+# IPVS transport protocol load balancing support
+#
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_AH_ESP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+# CONFIG_IP_VS_PROTO_SCTP is not set
+
+#
+# IPVS scheduler
+#
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+
+#
+# IPVS SH scheduler
+#
+CONFIG_IP_VS_SH_TAB_BITS=8
+
+#
+# IPVS application helper
+#
+# CONFIG_IP_VS_NFCT is not set
+# CONFIG_IP_VS_PE_SIP is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV4=m
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_ECN=m
+# CONFIG_IP_NF_MATCH_RPFILTER is not set
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_ULOG=m
+# CONFIG_NF_NAT_IPV4 is not set
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV6=m
+CONFIG_NF_CONNTRACK_IPV6=m
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_MH=m
+# CONFIG_IP6_NF_MATCH_RPFILTER is not set
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_RAW=m
+# CONFIG_NF_NAT_IPV6 is not set
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_IP6=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_BRIDGE_EBT_ULOG=m
+CONFIG_BRIDGE_EBT_NFLOG=m
+# CONFIG_IP_DCCP is not set
+CONFIG_IP_SCTP=m
+# CONFIG_SCTP_DBG_MSG is not set
+# CONFIG_SCTP_DBG_OBJCNT is not set
+# CONFIG_SCTP_HMAC_NONE is not set
+# CONFIG_SCTP_HMAC_SHA1 is not set
+CONFIG_SCTP_HMAC_MD5=y
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_L2TP is not set
+CONFIG_STP=m
+CONFIG_GARP=m
+CONFIG_BRIDGE=m
+CONFIG_BRIDGE_IGMP_SNOOPING=y
+# CONFIG_NET_DSA is not set
+CONFIG_VLAN_8021Q=m
+CONFIG_VLAN_8021Q_GVRP=y
+# CONFIG_DECNET is not set
+CONFIG_LLC=m
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+CONFIG_ATALK=m
+CONFIG_DEV_APPLETALK=m
+CONFIG_IPDDP=m
+CONFIG_IPDDP_ENCAP=y
+CONFIG_IPDDP_DECAP=y
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_WAN_ROUTER is not set
+CONFIG_PHONET=m
+# CONFIG_IEEE802154 is not set
+CONFIG_NET_SCHED=y
+
+#
+# Queueing/Scheduling
+#
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_PRIO=m
+# CONFIG_NET_SCH_MULTIQ is not set
+CONFIG_NET_SCH_RED=m
+# CONFIG_NET_SCH_SFB is not set
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_NETEM=m
+# CONFIG_NET_SCH_DRR is not set
+# CONFIG_NET_SCH_MQPRIO is not set
+# CONFIG_NET_SCH_CHOKE is not set
+# CONFIG_NET_SCH_QFQ is not set
+# CONFIG_NET_SCH_CODEL is not set
+# CONFIG_NET_SCH_FQ_CODEL is not set
+CONFIG_NET_SCH_INGRESS=m
+# CONFIG_NET_SCH_PLUG is not set
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+# CONFIG_CLS_U32_PERF is not set
+# CONFIG_CLS_U32_MARK is not set
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_CLS_FLOW=m
+# CONFIG_NET_EMATCH is not set
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=y
+CONFIG_NET_ACT_GACT=m
+CONFIG_GACT_PROB=y
+CONFIG_NET_ACT_MIRRED=m
+CONFIG_NET_ACT_IPT=m
+CONFIG_NET_ACT_NAT=m
+CONFIG_NET_ACT_PEDIT=m
+CONFIG_NET_ACT_SIMP=m
+CONFIG_NET_ACT_SKBEDIT=m
+# CONFIG_NET_ACT_CSUM is not set
+CONFIG_NET_CLS_IND=y
+CONFIG_NET_SCH_FIFO=y
+# CONFIG_DCB is not set
+# CONFIG_BATMAN_ADV is not set
+# CONFIG_OPENVSWITCH is not set
+CONFIG_RPS=y
+CONFIG_RFS_ACCEL=y
+CONFIG_XPS=y
+CONFIG_BQL=y
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NET_DROP_MONITOR is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+CONFIG_FIB_RULES=y
+CONFIG_WIRELESS=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WEXT_CORE=y
+CONFIG_WEXT_PROC=y
+CONFIG_WEXT_SPY=y
+CONFIG_WEXT_PRIV=y
+CONFIG_CFG80211=m
+# CONFIG_NL80211_TESTMODE is not set
+# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
+# CONFIG_CFG80211_REG_DEBUG is not set
+# CONFIG_CFG80211_CERTIFICATION_ONUS is not set
+CONFIG_CFG80211_DEFAULT_PS=y
+# CONFIG_CFG80211_DEBUGFS is not set
+# CONFIG_CFG80211_INTERNAL_REGDB is not set
+# CONFIG_CFG80211_WEXT is not set
+CONFIG_LIB80211=m
+CONFIG_LIB80211_CRYPT_WEP=m
+CONFIG_LIB80211_CRYPT_CCMP=m
+CONFIG_LIB80211_CRYPT_TKIP=m
+# CONFIG_LIB80211_DEBUG is not set
+CONFIG_MAC80211=m
+CONFIG_MAC80211_HAS_RC=y
+CONFIG_MAC80211_RC_PID=y
+CONFIG_MAC80211_RC_MINSTREL=y
+CONFIG_MAC80211_RC_MINSTREL_HT=y
+CONFIG_MAC80211_RC_DEFAULT_PID=y
+# CONFIG_MAC80211_RC_DEFAULT_MINSTREL is not set
+CONFIG_MAC80211_RC_DEFAULT="pid"
+CONFIG_MAC80211_MESH=y
+# CONFIG_MAC80211_DEBUGFS is not set
+# CONFIG_MAC80211_MESSAGE_TRACING is not set
+# CONFIG_MAC80211_DEBUG_MENU is not set
+# CONFIG_WIMAX is not set
+CONFIG_RFKILL=m
+# CONFIG_RFKILL_INPUT is not set
+# CONFIG_NET_9P is not set
+# CONFIG_CAIF is not set
+# CONFIG_CEPH_LIB is not set
+# CONFIG_NFC is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_DEVTMPFS is not set
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_GENERIC_CPU_DEVICES is not set
+# CONFIG_DMA_SHARED_BUFFER is not set
+
+#
+# Bus devices
+#
+# CONFIG_OMAP_OCP2SCP is not set
+CONFIG_CONNECTOR=m
+CONFIG_MTD=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_SM_FTL is not set
+CONFIG_MTD_OOPS=m
+# CONFIG_MTD_SWAP is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_STAA=y
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
+# CONFIG_MTD_INTEL_VR_NOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOCG3 is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+CONFIG_MTD_UBI=m
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_LIMIT=20
+# CONFIG_MTD_UBI_FASTMAP is not set
+CONFIG_MTD_UBI_GLUEBI=m
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+CONFIG_BLK_DEV_FD=m
+# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+CONFIG_BLK_DEV_UMEM=m
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_LOOP_MIN_COUNT=8
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+# CONFIG_BLK_DEV_DRBD is not set
+CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_NVME is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_XIP is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+CONFIG_ATA_OVER_ETH=m
+# CONFIG_BLK_DEV_HD is not set
+# CONFIG_BLK_DEV_RBD is not set
+
+#
+# Misc devices
+#
+# CONFIG_SENSORS_LIS3LV02D is not set
+# CONFIG_PHANTOM is not set
+# CONFIG_INTEL_MID_PTI is not set
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_HP_ILO is not set
+# CONFIG_PCH_PHUB is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+
+#
+# Altera FPGA firmware download module
+#
+CONFIG_HAVE_IDE=y
+CONFIG_IDE=y
+
+#
+# Please see Documentation/ide/ide.txt for help/info on IDE drives
+#
+CONFIG_IDE_XFER_MODE=y
+CONFIG_IDE_ATAPI=y
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_IDE_GD=y
+CONFIG_IDE_GD_ATA=y
+# CONFIG_IDE_GD_ATAPI is not set
+CONFIG_BLK_DEV_IDECD=y
+CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_PROC_FS=y
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_BLK_DEV_PLATFORM is not set
+CONFIG_BLK_DEV_IDEDMA_SFF=y
+
+#
+# PCI IDE chipsets support
+#
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_PCIBUS_ORDER=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_JMICRON is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+CONFIG_BLK_DEV_PIIX=y
+# CONFIG_BLK_DEV_IT8172 is not set
+CONFIG_BLK_DEV_IT8213=m
+# CONFIG_BLK_DEV_IT821X is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+CONFIG_BLK_DEV_TC86C001=m
+CONFIG_BLK_DEV_IDEDMA=y
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=m
+CONFIG_RAID_ATTRS=m
+CONFIG_SCSI=m
+CONFIG_SCSI_DMA=y
+CONFIG_SCSI_TGT=m
+CONFIG_SCSI_NETLINK=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=m
+# CONFIG_CHR_DEV_SCH is not set
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+
+#
+# SCSI Transports
+#
+CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_FC_ATTRS=m
+# CONFIG_SCSI_FC_TGT_ATTRS is not set
+CONFIG_SCSI_ISCSI_ATTRS=m
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+CONFIG_ISCSI_TCP=m
+# CONFIG_ISCSI_BOOT_SYSFS is not set
+# CONFIG_SCSI_CXGB3_ISCSI is not set
+# CONFIG_SCSI_CXGB4_ISCSI is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
+# CONFIG_SCSI_BNX2X_FCOE is not set
+# CONFIG_BE2ISCSI is not set
+CONFIG_BLK_DEV_3W_XXXX_RAID=m
+# CONFIG_SCSI_HPSA is not set
+CONFIG_SCSI_3W_9XXX=m
+# CONFIG_SCSI_3W_SAS is not set
+CONFIG_SCSI_ACARD=m
+CONFIG_SCSI_AACRAID=m
+CONFIG_SCSI_AIC7XXX=m
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=32
+CONFIG_AIC7XXX_RESET_DELAY_MS=15000
+# CONFIG_AIC7XXX_DEBUG_ENABLE is not set
+CONFIG_AIC7XXX_DEBUG_MASK=0
+CONFIG_AIC7XXX_REG_PRETTY_PRINT=y
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
+# CONFIG_SCSI_MVUMI is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_ARCMSR is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_MPT2SAS is not set
+# CONFIG_SCSI_UFSHCD is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
+# CONFIG_FCOE is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_STEX is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_PMCRAID is not set
+# CONFIG_SCSI_PM8001 is not set
+# CONFIG_SCSI_SRP is not set
+# CONFIG_SCSI_BFA_FC is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=m
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+CONFIG_MD_RAID10=m
+CONFIG_MD_RAID456=m
+# CONFIG_MULTICORE_RAID456 is not set
+CONFIG_MD_MULTIPATH=m
+CONFIG_MD_FAULTY=m
+CONFIG_BLK_DEV_DM=m
+# CONFIG_DM_DEBUG is not set
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+# CONFIG_DM_THIN_PROVISIONING is not set
+CONFIG_DM_MIRROR=m
+# CONFIG_DM_RAID is not set
+# CONFIG_DM_LOG_USERSPACE is not set
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+# CONFIG_DM_MULTIPATH_QL is not set
+# CONFIG_DM_MULTIPATH_ST is not set
+# CONFIG_DM_DELAY is not set
+# CONFIG_DM_UEVENT is not set
+# CONFIG_DM_FLAKEY is not set
+# CONFIG_DM_VERITY is not set
+# CONFIG_TARGET_CORE is not set
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_FIREWIRE is not set
+# CONFIG_FIREWIRE_NOSY is not set
+# CONFIG_I2O is not set
+CONFIG_NETDEVICES=y
+CONFIG_NET_CORE=y
+CONFIG_BONDING=m
+CONFIG_DUMMY=m
+CONFIG_EQUALIZER=m
+# CONFIG_NET_FC is not set
+CONFIG_MII=y
+CONFIG_IFB=m
+# CONFIG_NET_TEAM is not set
+CONFIG_MACVLAN=m
+# CONFIG_MACVTAP is not set
+# CONFIG_VXLAN is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+CONFIG_TUN=m
+CONFIG_VETH=m
+# CONFIG_ARCNET is not set
+
+#
+# CAIF transport drivers
+#
+CONFIG_ETHERNET=y
+CONFIG_MDIO=m
+CONFIG_NET_VENDOR_3COM=y
+# CONFIG_VORTEX is not set
+# CONFIG_TYPHOON is not set
+CONFIG_NET_VENDOR_ADAPTEC=y
+# CONFIG_ADAPTEC_STARFIRE is not set
+CONFIG_NET_VENDOR_ALTEON=y
+# CONFIG_ACENIC is not set
+CONFIG_NET_VENDOR_AMD=y
+# CONFIG_AMD8111_ETH is not set
+CONFIG_PCNET32=y
+CONFIG_NET_VENDOR_ATHEROS=y
+# CONFIG_ATL2 is not set
+# CONFIG_ATL1 is not set
+# CONFIG_ATL1E is not set
+# CONFIG_ATL1C is not set
+CONFIG_NET_VENDOR_BROADCOM=y
+# CONFIG_B44 is not set
+# CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2X is not set
+CONFIG_NET_VENDOR_BROCADE=y
+# CONFIG_BNA is not set
+# CONFIG_NET_CALXEDA_XGMAC is not set
+CONFIG_NET_VENDOR_CHELSIO=y
+# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3=m
+# CONFIG_CHELSIO_T4 is not set
+# CONFIG_CHELSIO_T4VF is not set
+CONFIG_NET_VENDOR_CISCO=y
+# CONFIG_ENIC is not set
+# CONFIG_DM9000 is not set
+# CONFIG_DNET is not set
+CONFIG_NET_VENDOR_DEC=y
+# CONFIG_NET_TULIP is not set
+CONFIG_NET_VENDOR_DLINK=y
+# CONFIG_DL2K is not set
+# CONFIG_SUNDANCE is not set
+CONFIG_NET_VENDOR_EMULEX=y
+# CONFIG_BE2NET is not set
+CONFIG_NET_VENDOR_EXAR=y
+# CONFIG_S2IO is not set
+# CONFIG_VXGE is not set
+CONFIG_NET_VENDOR_HP=y
+# CONFIG_HP100 is not set
+CONFIG_NET_VENDOR_INTEL=y
+# CONFIG_E100 is not set
+# CONFIG_E1000 is not set
+# CONFIG_E1000E is not set
+# CONFIG_IGB is not set
+# CONFIG_IGBVF is not set
+# CONFIG_IXGB is not set
+# CONFIG_IXGBE is not set
+CONFIG_NET_VENDOR_I825XX=y
+# CONFIG_IP1000 is not set
+# CONFIG_JME is not set
+CONFIG_NET_VENDOR_MARVELL=y
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+CONFIG_NET_VENDOR_MELLANOX=y
+# CONFIG_MLX4_EN is not set
+# CONFIG_MLX4_CORE is not set
+CONFIG_NET_VENDOR_MICREL=y
+# CONFIG_KS8851_MLL is not set
+# CONFIG_KSZ884X_PCI is not set
+CONFIG_NET_VENDOR_MYRI=y
+# CONFIG_MYRI10GE is not set
+# CONFIG_FEALNX is not set
+CONFIG_NET_VENDOR_NATSEMI=y
+# CONFIG_NATSEMI is not set
+# CONFIG_NS83820 is not set
+CONFIG_NET_VENDOR_8390=y
+CONFIG_AX88796=m
+# CONFIG_AX88796_93CX6 is not set
+# CONFIG_NE2K_PCI is not set
+CONFIG_NET_VENDOR_NVIDIA=y
+# CONFIG_FORCEDETH is not set
+CONFIG_NET_VENDOR_OKI=y
+# CONFIG_PCH_GBE is not set
+# CONFIG_ETHOC is not set
+CONFIG_NET_PACKET_ENGINE=y
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+CONFIG_NET_VENDOR_QLOGIC=y
+# CONFIG_QLA3XXX is not set
+# CONFIG_QLCNIC is not set
+# CONFIG_QLGE is not set
+CONFIG_NETXEN_NIC=m
+CONFIG_NET_VENDOR_REALTEK=y
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_R8169 is not set
+CONFIG_NET_VENDOR_RDC=y
+# CONFIG_R6040 is not set
+CONFIG_NET_VENDOR_SEEQ=y
+# CONFIG_SEEQ8005 is not set
+CONFIG_NET_VENDOR_SILAN=y
+# CONFIG_SC92031 is not set
+CONFIG_NET_VENDOR_SIS=y
+# CONFIG_SIS900 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SFC is not set
+CONFIG_NET_VENDOR_SMSC=y
+# CONFIG_SMC91X is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SMSC911X is not set
+# CONFIG_SMSC9420 is not set
+CONFIG_NET_VENDOR_STMICRO=y
+# CONFIG_STMMAC_ETH is not set
+CONFIG_NET_VENDOR_SUN=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NIU is not set
+CONFIG_NET_VENDOR_TEHUTI=y
+# CONFIG_TEHUTI is not set
+CONFIG_NET_VENDOR_TI=y
+# CONFIG_TLAN is not set
+CONFIG_NET_VENDOR_TOSHIBA=y
+CONFIG_TC35815=m
+CONFIG_NET_VENDOR_VIA=y
+# CONFIG_VIA_RHINE is not set
+# CONFIG_VIA_VELOCITY is not set
+CONFIG_NET_VENDOR_WIZNET=y
+# CONFIG_WIZNET_W5100 is not set
+# CONFIG_WIZNET_W5300 is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PHYLIB=m
+
+#
+# MII PHY device drivers
+#
+# CONFIG_AT803X_PHY is not set
+# CONFIG_AMD_PHY is not set
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+CONFIG_VITESSE_PHY=m
+CONFIG_SMSC_PHY=m
+CONFIG_BROADCOM_PHY=m
+# CONFIG_BCM87XX_PHY is not set
+CONFIG_ICPLUS_PHY=m
+CONFIG_REALTEK_PHY=m
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_MICREL_PHY is not set
+CONFIG_MDIO_BITBANG=m
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+CONFIG_WLAN=y
+# CONFIG_LIBERTAS_THINFIRM is not set
+# CONFIG_AIRO is not set
+CONFIG_ATMEL=m
+CONFIG_PCI_ATMEL=m
+CONFIG_PRISM54=m
+# CONFIG_RTL8180 is not set
+# CONFIG_ADM8211 is not set
+# CONFIG_MAC80211_HWSIM is not set
+# CONFIG_MWL8K is not set
+# CONFIG_ATH_COMMON is not set
+# CONFIG_B43 is not set
+# CONFIG_B43LEGACY is not set
+# CONFIG_BRCMFMAC is not set
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+CONFIG_HOSTAP_PLX=m
+CONFIG_HOSTAP_PCI=m
+CONFIG_IPW2100=m
+CONFIG_IPW2100_MONITOR=y
+# CONFIG_IPW2100_DEBUG is not set
+CONFIG_LIBIPW=m
+# CONFIG_LIBIPW_DEBUG is not set
+# CONFIG_IWLWIFI is not set
+# CONFIG_IWL4965 is not set
+# CONFIG_IWL3945 is not set
+CONFIG_LIBERTAS=m
+# CONFIG_LIBERTAS_DEBUG is not set
+# CONFIG_LIBERTAS_MESH is not set
+# CONFIG_P54_COMMON is not set
+# CONFIG_RT2X00 is not set
+# CONFIG_RTL8192CE is not set
+# CONFIG_RTL8192SE is not set
+# CONFIG_RTL8192DE is not set
+# CONFIG_WL_TI is not set
+# CONFIG_MWIFIEX is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# CONFIG_WAN is not set
+# CONFIG_VMXNET3 is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+# CONFIG_INPUT_MATRIXKMAP is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO_ALTERA_PS2 is not set
+# CONFIG_SERIO_PS2MULT is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_NOZOMI is not set
+# CONFIG_N_GSM is not set
+# CONFIG_TRACE_SINK is not set
+CONFIG_DEVKMEM=y
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_MFD_HSU is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+# CONFIG_SERIAL_SCCNXP is not set
+# CONFIG_SERIAL_TIMBERDALE is not set
+# CONFIG_SERIAL_ALTERA_JTAGUART is not set
+# CONFIG_SERIAL_ALTERA_UART is not set
+# CONFIG_SERIAL_PCH_UART is not set
+# CONFIG_SERIAL_XILINX_PS_UART is not set
+# CONFIG_TTY_PRINTK is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=m
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_DEVPORT=y
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+# CONFIG_HSI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+
+#
+# PPS generators support
+#
+
+#
+# PTP clock support
+#
+
+#
+# Enable Device Drivers -> PPS to see the PTP clock options.
+#
+CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_POWER_AVS is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+CONFIG_BCMA_POSSIBLE=y
+
+#
+# Broadcom specific AMBA
+#
+# CONFIG_BCMA is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_ABX500_CORE is not set
+# CONFIG_LPC_SCH is not set
+# CONFIG_LPC_ICH is not set
+# CONFIG_MFD_RDC321X is not set
+# CONFIG_MFD_JANZ_CMODIO is not set
+# CONFIG_MFD_VX855 is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+CONFIG_VGA_ARB=y
+CONFIG_VGA_ARB_MAX_GPUS=16
+# CONFIG_DRM is not set
+# CONFIG_STUB_POULSBO is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_WMT_GE_ROPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+CONFIG_FB_CIRRUS=y
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_UVESA is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_I740 is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_S3 is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_VT8623 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_ARK is not set
+# CONFIG_FB_PM3 is not set
+# CONFIG_FB_CARMINE is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_BROADSHEET is not set
+# CONFIG_FB_AUO_K190X is not set
+# CONFIG_EXYNOS_VIDEO is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+# CONFIG_LOGO is not set
+# CONFIG_SOUND is not set
+
+#
+# HID support
+#
+CONFIG_HID=m
+# CONFIG_HIDRAW is not set
+# CONFIG_UHID is not set
+CONFIG_HID_GENERIC=m
+
+#
+# Special HID drivers
+#
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB_ARCH_HAS_XHCI=y
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+# CONFIG_USB_EZUSB_FX2 is not set
+# CONFIG_OMAP_USB2 is not set
+# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_UWB is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_INFINIBAND is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+CONFIG_RTC_DRV_CMOS=y
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_MSM6242 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_RP5C01 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+# CONFIG_RTC_DRV_DS2404 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+CONFIG_UIO=m
+CONFIG_UIO_CIF=m
+# CONFIG_UIO_PDRV is not set
+# CONFIG_UIO_PDRV_GENIRQ is not set
+# CONFIG_UIO_AEC is not set
+# CONFIG_UIO_SERCOS3 is not set
+# CONFIG_UIO_PCI_GENERIC is not set
+# CONFIG_UIO_NETX is not set
+
+#
+# Virtio drivers
+#
+# CONFIG_VIRTIO_PCI is not set
+# CONFIG_VIRTIO_MMIO is not set
+
+#
+# Microsoft Hyper-V guest support
+#
+# CONFIG_STAGING is not set
+
+#
+# Hardware Spinlock drivers
+#
+CONFIG_CLKSRC_I8253=y
+CONFIG_CLKEVT_I8253=y
+CONFIG_I8253_LOCK=y
+CONFIG_CLKBLD_I8253=y
+CONFIG_IOMMU_SUPPORT=y
+
+#
+# Remoteproc drivers (EXPERIMENTAL)
+#
+# CONFIG_STE_MODEM_RPROC is not set
+
+#
+# Rpmsg drivers (EXPERIMENTAL)
+#
+# CONFIG_VIRT_DRIVERS is not set
+# CONFIG_PM_DEVFREQ is not set
+# CONFIG_EXTCON is not set
+# CONFIG_MEMORY is not set
+# CONFIG_IIO is not set
+# CONFIG_VME_BUS is not set
+# CONFIG_PWM is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_DEFAULTS_TO_ORDERED=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4_FS is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+CONFIG_REISERFS_PROC_INFO=y
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+CONFIG_JFS_FS=m
+CONFIG_JFS_POSIX_ACL=y
+CONFIG_JFS_SECURITY=y
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+CONFIG_XFS_FS=m
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_POSIX_ACL=y
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_DEBUG is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_EXPORTFS=y
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_FANOTIFY is not set
+CONFIG_QUOTA=y
+# CONFIG_QUOTA_NETLINK_INTERFACE is not set
+CONFIG_PRINT_QUOTA_WARNING=y
+# CONFIG_QUOTA_DEBUG is not set
+CONFIG_QUOTA_TREE=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+# CONFIG_AUTOFS4_FS is not set
+CONFIG_FUSE_FS=m
+# CONFIG_CUSE is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_CONFIGFS_FS=y
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+CONFIG_AFFS_FS=m
+CONFIG_HFS_FS=m
+CONFIG_HFSPLUS_FS=m
+CONFIG_BEFS_FS=m
+# CONFIG_BEFS_DEBUG is not set
+CONFIG_BFS_FS=m
+CONFIG_EFS_FS=m
+CONFIG_JFFS2_FS=m
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+CONFIG_JFFS2_FS_XATTR=y
+CONFIG_JFFS2_FS_POSIX_ACL=y
+CONFIG_JFFS2_FS_SECURITY=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+CONFIG_JFFS2_RUBIN=y
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
+# CONFIG_UBIFS_FS is not set
+# CONFIG_LOGFS is not set
+CONFIG_CRAMFS=m
+# CONFIG_SQUASHFS is not set
+CONFIG_VXFS_FS=m
+CONFIG_MINIX_FS=m
+CONFIG_MINIX_FS_NATIVE_ENDIAN=y
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX6FS_FS is not set
+CONFIG_ROMFS_FS=m
+CONFIG_ROMFS_BACKED_BY_BLOCK=y
+# CONFIG_ROMFS_BACKED_BY_MTD is not set
+# CONFIG_ROMFS_BACKED_BY_BOTH is not set
+CONFIG_ROMFS_ON_BLOCK=y
+# CONFIG_PSTORE is not set
+CONFIG_SYSV_FS=m
+CONFIG_UFS_FS=m
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_UFS_DEBUG is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V2=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_SWAP is not set
+CONFIG_ROOT_NFS=y
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+# CONFIG_NFSD_V4 is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_DEBUG is not set
+# CONFIG_CEPH_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+# CONFIG_NLS_MAC_ROMAN is not set
+# CONFIG_NLS_MAC_CELTIC is not set
+# CONFIG_NLS_MAC_CENTEURO is not set
+# CONFIG_NLS_MAC_CROATIAN is not set
+# CONFIG_NLS_MAC_CYRILLIC is not set
+# CONFIG_NLS_MAC_GAELIC is not set
+# CONFIG_NLS_MAC_GREEK is not set
+# CONFIG_NLS_MAC_ICELAND is not set
+# CONFIG_NLS_MAC_INUIT is not set
+# CONFIG_NLS_MAC_ROMANIAN is not set
+# CONFIG_NLS_MAC_TURKISH is not set
+CONFIG_NLS_UTF8=m
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_PRINTK_TIME is not set
+CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_READABLE_ASM is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_SECTION_MISMATCH is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+# CONFIG_LOCKUP_DETECTOR is not set
+# CONFIG_PANIC_ON_OOPS is not set
+CONFIG_PANIC_ON_OOPS_VALUE=0
+# CONFIG_DETECT_HUNG_TASK is not set
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_HAVE_DEBUG_KMEMLEAK=y
+# CONFIG_DEBUG_KMEMLEAK is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_SPARSE_RCU_POINTER is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_ATOMIC_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+CONFIG_STACKTRACE=y
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_TEST_LIST_SORT is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_RCU_CPU_STALL_TIMEOUT=60
+# CONFIG_RCU_CPU_STALL_INFO is not set
+# CONFIG_RCU_TRACE is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+# CONFIG_DEBUG_PER_CPU_MAPS is not set
+# CONFIG_LKDTM is not set
+# CONFIG_NOTIFIER_ERROR_INJECTION is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+CONFIG_NOP_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_TRACE_CLOCK=y
+CONFIG_RING_BUFFER=y
+CONFIG_EVENT_TRACING=y
+# CONFIG_EVENT_POWER_TRACING_DEPRECATED is not set
+CONFIG_CONTEXT_SWITCH_TRACER=y
+CONFIG_TRACING=y
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+CONFIG_ENABLE_DEFAULT_TRACERS=y
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_PROBE_EVENTS is not set
+# CONFIG_RING_BUFFER_BENCHMARK is not set
+# CONFIG_RBTREE_TEST is not set
+# CONFIG_INTERVAL_TREE_TEST is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
+# CONFIG_ASYNC_RAID6_TEST is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_TEST_KSTRTOX is not set
+CONFIG_EARLY_PRINTK=y
+# CONFIG_CMDLINE_BOOL is not set
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_RUNTIME_DEBUG is not set
+# CONFIG_DEBUG_ZBOOT is not set
+# CONFIG_SPINLOCK_TEST is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY_DMESG_RESTRICT is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_XOR_BLOCKS=m
+CONFIG_ASYNC_CORE=m
+CONFIG_ASYNC_MEMCPY=m
+CONFIG_ASYNC_XOR=m
+CONFIG_ASYNC_PQ=m
+CONFIG_ASYNC_RAID6_RECOV=m
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP2=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_USER is not set
+CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_NULL=m
+# CONFIG_CRYPTO_PCRYPT is not set
+CONFIG_CRYPTO_WORKQUEUE=y
+CONFIG_CRYPTO_CRYPTD=m
+CONFIG_CRYPTO_AUTHENC=m
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=m
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_XCBC=m
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_GHASH is not set
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=m
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_BLOWFISH_COMMON=m
+CONFIG_CRYPTO_CAMELLIA=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_KHAZAD=m
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=m
+# CONFIG_CRYPTO_ZLIB is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_USER_API_HASH is not set
+# CONFIG_CRYPTO_USER_API_SKCIPHER is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+CONFIG_BINARY_PRINTF=y
+
+#
+# Library routines
+#
+CONFIG_RAID6_PQ=m
+CONFIG_BITREVERSE=y
+CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_IO=y
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC16=m
+# CONFIG_CRC_T10DIF is not set
+CONFIG_CRC_ITU_T=m
+CONFIG_CRC32=y
+# CONFIG_CRC32_SELFTEST is not set
+CONFIG_CRC32_SLICEBY8=y
+# CONFIG_CRC32_SLICEBY4 is not set
+# CONFIG_CRC32_SARWATE is not set
+# CONFIG_CRC32_BIT is not set
+# CONFIG_CRC7 is not set
+CONFIG_LIBCRC32C=m
+# CONFIG_CRC8 is not set
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
+# CONFIG_XZ_DEC is not set
+# CONFIG_XZ_DEC_BCJ is not set
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_CPU_RMAP=y
+CONFIG_DQL=y
+CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
+CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y
+CONFIG_AVERAGE=y
+# CONFIG_CORDIC is not set
+# CONFIG_DDR is not set
+CONFIG_HAVE_KVM=y
+CONFIG_KVM_MMIO=y
+CONFIG_VIRTUALIZATION=y
+CONFIG_KVM=m
+CONFIG_KVM_MIPS_DYN_TRANS=y
+CONFIG_KVM_MIPS_DEBUG_COP0_COUNTERS=y
+CONFIG_VHOST_NET=m
diff --git a/arch/mips/configs/malta_kvm_guest_defconfig b/arch/mips/configs/malta_kvm_guest_defconfig
new file mode 100644
index 0000000..17b6afa
--- /dev/null
+++ b/arch/mips/configs/malta_kvm_guest_defconfig
@@ -0,0 +1,2237 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Linux/mips 3.7.0-rc1 Kernel Configuration
+#
+CONFIG_MIPS=y
+
+#
+# Machine selection
+#
+CONFIG_ZONE_DMA=y
+# CONFIG_MIPS_ALCHEMY is not set
+# CONFIG_AR7 is not set
+# CONFIG_ATH79 is not set
+# CONFIG_BCM47XX is not set
+# CONFIG_BCM63XX is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_MACH_JZ4740 is not set
+# CONFIG_LANTIQ is not set
+# CONFIG_LASAT is not set
+# CONFIG_MACH_LOONGSON is not set
+# CONFIG_MACH_LOONGSON1 is not set
+CONFIG_MIPS_MALTA=y
+# CONFIG_MIPS_SEAD3 is not set
+# CONFIG_NEC_MARKEINS is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_NXP_STB220 is not set
+# CONFIG_NXP_STB225 is not set
+# CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
+# CONFIG_PMC_MSP is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_POWERTV is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP28 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_CRHONE is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SNI_RM is not set
+# CONFIG_MACH_TX39XX is not set
+# CONFIG_MACH_TX49XX is not set
+# CONFIG_MIKROTIK_RB532 is not set
+# CONFIG_WR_PPMC is not set
+# CONFIG_CAVIUM_OCTEON_SIMULATOR is not set
+# CONFIG_CAVIUM_OCTEON_REFERENCE_BOARD is not set
+# CONFIG_NLM_XLR_BOARD is not set
+# CONFIG_NLM_XLP_BOARD is not set
+# CONFIG_ALCHEMY_GPIO_INDIRECT is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_BOOT_RAW=y
+CONFIG_CEVT_R4K_LIB=y
+CONFIG_CEVT_R4K=y
+CONFIG_CSRC_R4K_LIB=y
+CONFIG_CSRC_R4K=y
+# CONFIG_ARCH_DMA_ADDR_T_64BIT is not set
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_SYS_HAS_EARLY_PRINTK=y
+CONFIG_I8259=y
+CONFIG_MIPS_BONITO64=y
+CONFIG_MIPS_MSC=y
+# CONFIG_MIPS_MACHINE is not set
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_ISA_DMA_API=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_IRQ_GIC=y
+CONFIG_MIPS_BOARDS_GEN=y
+CONFIG_PCI_GT64XXX_PCI0=y
+CONFIG_SWAP_IO_SPACE=y
+CONFIG_BOOT_ELF32=y
+CONFIG_MIPS_L1_CACHE_SHIFT=6
+
+#
+# CPU selection
+#
+# CONFIG_CPU_MIPS32_R1 is not set
+CONFIG_CPU_MIPS32_R2=y
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_RM7000 is not set
+CONFIG_SYS_SUPPORTS_ZBOOT=y
+CONFIG_SYS_HAS_CPU_MIPS32_R1=y
+CONFIG_SYS_HAS_CPU_MIPS32_R2=y
+CONFIG_SYS_HAS_CPU_MIPS64_R1=y
+CONFIG_SYS_HAS_CPU_MIPS64_R2=y
+CONFIG_SYS_HAS_CPU_NEVADA=y
+CONFIG_SYS_HAS_CPU_RM7000=y
+CONFIG_CPU_MIPS32=y
+CONFIG_CPU_MIPSR2=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_HARDWARE_WATCHPOINTS=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_PAGE_SIZE_4KB is not set
+CONFIG_PAGE_SIZE_16KB=y
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_BOARD_SCACHE=y
+CONFIG_MIPS_CPU_SCACHE=y
+CONFIG_CPU_HAS_PREFETCH=y
+CONFIG_CPU_GENERIC_DUMP_TLB=y
+CONFIG_CPU_R4K_FPU=y
+CONFIG_CPU_R4K_CACHE_TLB=y
+CONFIG_MIPS_MT_DISABLED=y
+# CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
+CONFIG_SYS_SUPPORTS_MULTITHREADING=y
+# CONFIG_MIPS_VPE_LOADER is not set
+# CONFIG_MIPS_CMP is not set
+CONFIG_KVM_GUEST=y
+CONFIG_KVM_HOST_FREQ=500
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
+# CONFIG_CPU_HAS_SMARTMIPS is not set
+CONFIG_CPU_HAS_SYNC=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
+CONFIG_SYS_SUPPORTS_SMARTMIPS=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_HAVE_MEMBLOCK_NODE_MAP=y
+CONFIG_ARCH_DISCARD_MEMBLOCK=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_COMPACTION=y
+CONFIG_MIGRATION=y
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_CROSS_MEMORY_ATTACH=y
+CONFIG_NEED_PER_CPU_KM=y
+# CONFIG_CLEANCACHE is not set
+# CONFIG_FRONTSWAP is not set
+CONFIG_SYS_SUPPORTS_MIPS_CMP=y
+# CONFIG_HZ_48 is not set
+CONFIG_HZ_100=y
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+# CONFIG_HZ_1000 is not set
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=100
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_KEXEC is not set
+CONFIG_SECCOMP=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_HAVE_IRQ_WORK=y
+CONFIG_BUILDTIME_EXTABLE_SORT=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE=""
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_BZIP2=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_BZIP2 is not set
+# CONFIG_KERNEL_LZMA is not set
+# CONFIG_KERNEL_LZO is not set
+CONFIG_DEFAULT_HOSTNAME="(none)"
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_FHANDLE is not set
+# CONFIG_AUDIT is not set
+CONFIG_HAVE_GENERIC_HARDIRQS=y
+
+#
+# IRQ subsystem
+#
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_IRQ_FORCED_THREADING=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+
+#
+# Timers subsystem
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+
+#
+# CPU/Task time and stats accounting
+#
+CONFIG_TICK_CPU_ACCOUNTING=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TINY_RCU=y
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=15
+# CONFIG_CGROUPS is not set
+# CONFIG_CHECKPOINT_RESTORE is not set
+CONFIG_NAMESPACES=y
+CONFIG_UTS_NS=y
+CONFIG_IPC_NS=y
+CONFIG_PID_NS=y
+CONFIG_NET_NS=y
+# CONFIG_SCHED_AUTOGROUP is not set
+# CONFIG_SYSFS_DEPRECATED is not set
+CONFIG_RELAY=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+# CONFIG_RD_XZ is not set
+# CONFIG_RD_LZO is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EXPERT=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_PCSPKR_PLATFORM=y
+CONFIG_HAVE_PCSPKR_PLATFORM=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+# CONFIG_EMBEDDED is not set
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_PERF_USE_VMALLOC=y
+
+#
+# Kernel Performance Events And Counters
+#
+# CONFIG_PERF_EVENTS is not set
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_PCI_QUIRKS=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+# CONFIG_JUMP_LABEL is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_DMA_ATTRS=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
+CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
+CONFIG_MODULES_USE_ELF_REL=y
+
+#
+# GCOV-based kernel profiling
+#
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+# CONFIG_MODULE_SIG is not set
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+CONFIG_BLK_DEV_BSG=y
+CONFIG_BLK_DEV_BSGLIB=y
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
+CONFIG_INLINE_READ_UNLOCK=y
+CONFIG_INLINE_READ_UNLOCK_IRQ=y
+CONFIG_INLINE_WRITE_UNLOCK=y
+CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
+CONFIG_FREEZER=y
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_REALLOC_ENABLE_AUTO is not set
+# CONFIG_PCI_STUB is not set
+# CONFIG_PCI_IOV is not set
+# CONFIG_PCI_PRI is not set
+# CONFIG_PCI_PASID is not set
+# CONFIG_PCIEPORTBUS is not set
+CONFIG_MMU=y
+CONFIG_I8253=y
+# CONFIG_PCCARD is not set
+# CONFIG_HOTPLUG_PCI is not set
+# CONFIG_RAPIDIO is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y
+CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+CONFIG_COREDUMP=y
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Power management options
+#
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+# CONFIG_HIBERNATION is not set
+CONFIG_PM_SLEEP=y
+# CONFIG_PM_AUTOSLEEP is not set
+# CONFIG_PM_WAKELOCKS is not set
+# CONFIG_PM_RUNTIME is not set
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+CONFIG_MIPS_EXTERNAL_TIMER=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_DIAG is not set
+CONFIG_UNIX=y
+# CONFIG_UNIX_DIAG is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_ALGO=y
+CONFIG_XFRM_USER=m
+# CONFIG_XFRM_SUB_POLICY is not set
+CONFIG_XFRM_MIGRATE=y
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_XFRM_IPCOMP=m
+CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+# CONFIG_IP_FIB_TRIE_STATS is not set
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_ROUTE_CLASSID=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+CONFIG_NET_IPIP=m
+# CONFIG_NET_IPGRE_DEMUX is not set
+CONFIG_IP_MROUTE=y
+# CONFIG_IP_MROUTE_MULTIPLE_TABLES is not set
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_NET_IPVTI is not set
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_LRO=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_INET_UDP_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+# CONFIG_IPV6_MIP6 is not set
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=m
+# CONFIG_IPV6_SIT_6RD is not set
+CONFIG_IPV6_NDISC_NODETYPE=y
+CONFIG_IPV6_TUNNEL=m
+# CONFIG_IPV6_GRE is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+CONFIG_IPV6_MROUTE=y
+# CONFIG_IPV6_MROUTE_MULTIPLE_TABLES is not set
+CONFIG_IPV6_PIMSM_V2=y
+CONFIG_NETWORK_SECMARK=y
+# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+# CONFIG_NETFILTER_NETLINK_ACCT is not set
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_PROCFS=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+# CONFIG_NF_CONNTRACK_TIMEOUT is not set
+# CONFIG_NF_CONNTRACK_TIMESTAMP is not set
+CONFIG_NF_CT_PROTO_DCCP=m
+CONFIG_NF_CT_PROTO_GRE=m
+CONFIG_NF_CT_PROTO_SCTP=m
+CONFIG_NF_CT_PROTO_UDPLITE=m
+CONFIG_NF_CONNTRACK_AMANDA=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_H323=m
+CONFIG_NF_CONNTRACK_IRC=m
+# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
+# CONFIG_NF_CONNTRACK_SNMP is not set
+CONFIG_NF_CONNTRACK_PPTP=m
+CONFIG_NF_CONNTRACK_SANE=m
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NF_CT_NETLINK=m
+# CONFIG_NF_CT_NETLINK_TIMEOUT is not set
+# CONFIG_NETFILTER_NETLINK_QUEUE_CT is not set
+CONFIG_NETFILTER_TPROXY=m
+CONFIG_NETFILTER_XTABLES=m
+
+#
+# Xtables combined modules
+#
+CONFIG_NETFILTER_XT_MARK=m
+CONFIG_NETFILTER_XT_CONNMARK=m
+
+#
+# Xtables targets
+#
+# CONFIG_NETFILTER_XT_TARGET_CHECKSUM is not set
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+# CONFIG_NETFILTER_XT_TARGET_CONNSECMARK is not set
+# CONFIG_NETFILTER_XT_TARGET_CT is not set
+# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
+CONFIG_NETFILTER_XT_TARGET_HL=m
+# CONFIG_NETFILTER_XT_TARGET_HMARK is not set
+# CONFIG_NETFILTER_XT_TARGET_IDLETIMER is not set
+# CONFIG_NETFILTER_XT_TARGET_LOG is not set
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_RATEEST=m
+# CONFIG_NETFILTER_XT_TARGET_TEE is not set
+CONFIG_NETFILTER_XT_TARGET_TPROXY=m
+CONFIG_NETFILTER_XT_TARGET_TRACE=m
+CONFIG_NETFILTER_XT_TARGET_SECMARK=m
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
+CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
+
+#
+# Xtables matches
+#
+# CONFIG_NETFILTER_XT_MATCH_ADDRTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_CLUSTER is not set
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+# CONFIG_NETFILTER_XT_MATCH_CPU is not set
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+# CONFIG_NETFILTER_XT_MATCH_DEVGROUP is not set
+# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
+CONFIG_NETFILTER_XT_MATCH_ECN=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_HL=m
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
+# CONFIG_NETFILTER_XT_MATCH_IPVS is not set
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+# CONFIG_NETFILTER_XT_MATCH_NFACCT is not set
+# CONFIG_NETFILTER_XT_MATCH_OSF is not set
+CONFIG_NETFILTER_XT_MATCH_OWNER=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_RATEEST=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_RECENT=m
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_SOCKET=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_TIME=m
+CONFIG_NETFILTER_XT_MATCH_U32=m
+# CONFIG_IP_SET is not set
+CONFIG_IP_VS=m
+CONFIG_IP_VS_IPV6=y
+# CONFIG_IP_VS_DEBUG is not set
+CONFIG_IP_VS_TAB_BITS=12
+
+#
+# IPVS transport protocol load balancing support
+#
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_AH_ESP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+# CONFIG_IP_VS_PROTO_SCTP is not set
+
+#
+# IPVS scheduler
+#
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+
+#
+# IPVS SH scheduler
+#
+CONFIG_IP_VS_SH_TAB_BITS=8
+
+#
+# IPVS application helper
+#
+# CONFIG_IP_VS_NFCT is not set
+# CONFIG_IP_VS_PE_SIP is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV4=m
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_ECN=m
+# CONFIG_IP_NF_MATCH_RPFILTER is not set
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_ULOG=m
+# CONFIG_NF_NAT_IPV4 is not set
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV6=m
+CONFIG_NF_CONNTRACK_IPV6=m
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_MH=m
+# CONFIG_IP6_NF_MATCH_RPFILTER is not set
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_RAW=m
+# CONFIG_NF_NAT_IPV6 is not set
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_IP6=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_BRIDGE_EBT_ULOG=m
+CONFIG_BRIDGE_EBT_NFLOG=m
+# CONFIG_IP_DCCP is not set
+CONFIG_IP_SCTP=m
+# CONFIG_SCTP_DBG_MSG is not set
+# CONFIG_SCTP_DBG_OBJCNT is not set
+# CONFIG_SCTP_HMAC_NONE is not set
+# CONFIG_SCTP_HMAC_SHA1 is not set
+CONFIG_SCTP_HMAC_MD5=y
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_L2TP is not set
+CONFIG_STP=m
+CONFIG_GARP=m
+CONFIG_BRIDGE=m
+CONFIG_BRIDGE_IGMP_SNOOPING=y
+# CONFIG_NET_DSA is not set
+CONFIG_VLAN_8021Q=m
+CONFIG_VLAN_8021Q_GVRP=y
+# CONFIG_DECNET is not set
+CONFIG_LLC=m
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+CONFIG_ATALK=m
+CONFIG_DEV_APPLETALK=m
+CONFIG_IPDDP=m
+CONFIG_IPDDP_ENCAP=y
+CONFIG_IPDDP_DECAP=y
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_WAN_ROUTER is not set
+CONFIG_PHONET=m
+# CONFIG_IEEE802154 is not set
+CONFIG_NET_SCHED=y
+
+#
+# Queueing/Scheduling
+#
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_PRIO=m
+# CONFIG_NET_SCH_MULTIQ is not set
+CONFIG_NET_SCH_RED=m
+# CONFIG_NET_SCH_SFB is not set
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_NETEM=m
+# CONFIG_NET_SCH_DRR is not set
+# CONFIG_NET_SCH_MQPRIO is not set
+# CONFIG_NET_SCH_CHOKE is not set
+# CONFIG_NET_SCH_QFQ is not set
+# CONFIG_NET_SCH_CODEL is not set
+# CONFIG_NET_SCH_FQ_CODEL is not set
+CONFIG_NET_SCH_INGRESS=m
+# CONFIG_NET_SCH_PLUG is not set
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+# CONFIG_CLS_U32_PERF is not set
+# CONFIG_CLS_U32_MARK is not set
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_CLS_FLOW=m
+# CONFIG_NET_EMATCH is not set
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=y
+CONFIG_NET_ACT_GACT=m
+CONFIG_GACT_PROB=y
+CONFIG_NET_ACT_MIRRED=m
+CONFIG_NET_ACT_IPT=m
+CONFIG_NET_ACT_NAT=m
+CONFIG_NET_ACT_PEDIT=m
+CONFIG_NET_ACT_SIMP=m
+CONFIG_NET_ACT_SKBEDIT=m
+# CONFIG_NET_ACT_CSUM is not set
+CONFIG_NET_CLS_IND=y
+CONFIG_NET_SCH_FIFO=y
+# CONFIG_DCB is not set
+# CONFIG_BATMAN_ADV is not set
+# CONFIG_OPENVSWITCH is not set
+CONFIG_BQL=y
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+CONFIG_FIB_RULES=y
+CONFIG_WIRELESS=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WEXT_CORE=y
+CONFIG_WEXT_PROC=y
+CONFIG_WEXT_SPY=y
+CONFIG_WEXT_PRIV=y
+CONFIG_CFG80211=m
+# CONFIG_NL80211_TESTMODE is not set
+# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
+# CONFIG_CFG80211_REG_DEBUG is not set
+# CONFIG_CFG80211_CERTIFICATION_ONUS is not set
+CONFIG_CFG80211_DEFAULT_PS=y
+# CONFIG_CFG80211_INTERNAL_REGDB is not set
+# CONFIG_CFG80211_WEXT is not set
+CONFIG_LIB80211=m
+CONFIG_LIB80211_CRYPT_WEP=m
+CONFIG_LIB80211_CRYPT_CCMP=m
+CONFIG_LIB80211_CRYPT_TKIP=m
+# CONFIG_LIB80211_DEBUG is not set
+CONFIG_MAC80211=m
+CONFIG_MAC80211_HAS_RC=y
+CONFIG_MAC80211_RC_PID=y
+CONFIG_MAC80211_RC_MINSTREL=y
+CONFIG_MAC80211_RC_MINSTREL_HT=y
+CONFIG_MAC80211_RC_DEFAULT_PID=y
+# CONFIG_MAC80211_RC_DEFAULT_MINSTREL is not set
+CONFIG_MAC80211_RC_DEFAULT="pid"
+CONFIG_MAC80211_MESH=y
+# CONFIG_MAC80211_MESSAGE_TRACING is not set
+# CONFIG_MAC80211_DEBUG_MENU is not set
+# CONFIG_WIMAX is not set
+CONFIG_RFKILL=m
+# CONFIG_RFKILL_INPUT is not set
+# CONFIG_NET_9P is not set
+# CONFIG_CAIF is not set
+# CONFIG_CEPH_LIB is not set
+# CONFIG_NFC is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_DEVTMPFS is not set
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_GENERIC_CPU_DEVICES is not set
+# CONFIG_DMA_SHARED_BUFFER is not set
+
+#
+# Bus devices
+#
+# CONFIG_OMAP_OCP2SCP is not set
+CONFIG_CONNECTOR=m
+CONFIG_MTD=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_SM_FTL is not set
+CONFIG_MTD_OOPS=m
+# CONFIG_MTD_SWAP is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_STAA=y
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
+# CONFIG_MTD_INTEL_VR_NOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOCG3 is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+CONFIG_MTD_UBI=m
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_LIMIT=20
+# CONFIG_MTD_UBI_FASTMAP is not set
+CONFIG_MTD_UBI_GLUEBI=m
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+CONFIG_BLK_DEV_FD=m
+# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+CONFIG_BLK_DEV_UMEM=m
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_LOOP_MIN_COUNT=8
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+# CONFIG_BLK_DEV_DRBD is not set
+CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_NVME is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_XIP is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+CONFIG_ATA_OVER_ETH=m
+CONFIG_VIRTIO_BLK=y
+# CONFIG_BLK_DEV_HD is not set
+# CONFIG_BLK_DEV_RBD is not set
+
+#
+# Misc devices
+#
+# CONFIG_SENSORS_LIS3LV02D is not set
+# CONFIG_PHANTOM is not set
+# CONFIG_INTEL_MID_PTI is not set
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_HP_ILO is not set
+# CONFIG_PCH_PHUB is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+
+#
+# Altera FPGA firmware download module
+#
+CONFIG_HAVE_IDE=y
+CONFIG_IDE=y
+
+#
+# Please see Documentation/ide/ide.txt for help/info on IDE drives
+#
+CONFIG_IDE_XFER_MODE=y
+CONFIG_IDE_ATAPI=y
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_IDE_GD=y
+CONFIG_IDE_GD_ATA=y
+# CONFIG_IDE_GD_ATAPI is not set
+CONFIG_BLK_DEV_IDECD=y
+CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_PROC_FS=y
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_BLK_DEV_PLATFORM is not set
+CONFIG_BLK_DEV_IDEDMA_SFF=y
+
+#
+# PCI IDE chipsets support
+#
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_PCIBUS_ORDER=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_JMICRON is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+CONFIG_BLK_DEV_PIIX=y
+# CONFIG_BLK_DEV_IT8172 is not set
+CONFIG_BLK_DEV_IT8213=m
+# CONFIG_BLK_DEV_IT821X is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+CONFIG_BLK_DEV_TC86C001=m
+CONFIG_BLK_DEV_IDEDMA=y
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=m
+CONFIG_RAID_ATTRS=m
+CONFIG_SCSI=m
+CONFIG_SCSI_DMA=y
+CONFIG_SCSI_TGT=m
+CONFIG_SCSI_NETLINK=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=m
+# CONFIG_CHR_DEV_SCH is not set
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+
+#
+# SCSI Transports
+#
+CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_FC_ATTRS=m
+# CONFIG_SCSI_FC_TGT_ATTRS is not set
+CONFIG_SCSI_ISCSI_ATTRS=m
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+CONFIG_ISCSI_TCP=m
+# CONFIG_ISCSI_BOOT_SYSFS is not set
+# CONFIG_SCSI_CXGB3_ISCSI is not set
+# CONFIG_SCSI_CXGB4_ISCSI is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
+# CONFIG_SCSI_BNX2X_FCOE is not set
+# CONFIG_BE2ISCSI is not set
+CONFIG_BLK_DEV_3W_XXXX_RAID=m
+# CONFIG_SCSI_HPSA is not set
+CONFIG_SCSI_3W_9XXX=m
+# CONFIG_SCSI_3W_SAS is not set
+CONFIG_SCSI_ACARD=m
+CONFIG_SCSI_AACRAID=m
+CONFIG_SCSI_AIC7XXX=m
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=32
+CONFIG_AIC7XXX_RESET_DELAY_MS=15000
+# CONFIG_AIC7XXX_DEBUG_ENABLE is not set
+CONFIG_AIC7XXX_DEBUG_MASK=0
+CONFIG_AIC7XXX_REG_PRETTY_PRINT=y
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
+# CONFIG_SCSI_MVUMI is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_ARCMSR is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_MPT2SAS is not set
+# CONFIG_SCSI_UFSHCD is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
+# CONFIG_FCOE is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_STEX is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_PMCRAID is not set
+# CONFIG_SCSI_PM8001 is not set
+# CONFIG_SCSI_SRP is not set
+# CONFIG_SCSI_BFA_FC is not set
+# CONFIG_SCSI_VIRTIO is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=m
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+CONFIG_MD_RAID10=m
+CONFIG_MD_RAID456=m
+CONFIG_MD_MULTIPATH=m
+CONFIG_MD_FAULTY=m
+CONFIG_BLK_DEV_DM=m
+# CONFIG_DM_DEBUG is not set
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+# CONFIG_DM_THIN_PROVISIONING is not set
+CONFIG_DM_MIRROR=m
+# CONFIG_DM_RAID is not set
+# CONFIG_DM_LOG_USERSPACE is not set
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+# CONFIG_DM_MULTIPATH_QL is not set
+# CONFIG_DM_MULTIPATH_ST is not set
+# CONFIG_DM_DELAY is not set
+# CONFIG_DM_UEVENT is not set
+# CONFIG_DM_FLAKEY is not set
+# CONFIG_DM_VERITY is not set
+# CONFIG_TARGET_CORE is not set
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_FIREWIRE is not set
+# CONFIG_FIREWIRE_NOSY is not set
+# CONFIG_I2O is not set
+CONFIG_NETDEVICES=y
+CONFIG_NET_CORE=y
+CONFIG_BONDING=m
+CONFIG_DUMMY=m
+CONFIG_EQUALIZER=m
+# CONFIG_NET_FC is not set
+CONFIG_MII=y
+CONFIG_IFB=m
+# CONFIG_NET_TEAM is not set
+CONFIG_MACVLAN=m
+# CONFIG_MACVTAP is not set
+# CONFIG_VXLAN is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+CONFIG_TUN=m
+CONFIG_VETH=m
+CONFIG_VIRTIO_NET=y
+# CONFIG_ARCNET is not set
+
+#
+# CAIF transport drivers
+#
+CONFIG_ETHERNET=y
+CONFIG_MDIO=m
+CONFIG_NET_VENDOR_3COM=y
+# CONFIG_VORTEX is not set
+# CONFIG_TYPHOON is not set
+CONFIG_NET_VENDOR_ADAPTEC=y
+# CONFIG_ADAPTEC_STARFIRE is not set
+CONFIG_NET_VENDOR_ALTEON=y
+# CONFIG_ACENIC is not set
+CONFIG_NET_VENDOR_AMD=y
+# CONFIG_AMD8111_ETH is not set
+CONFIG_PCNET32=y
+CONFIG_NET_VENDOR_ATHEROS=y
+# CONFIG_ATL2 is not set
+# CONFIG_ATL1 is not set
+# CONFIG_ATL1E is not set
+# CONFIG_ATL1C is not set
+CONFIG_NET_VENDOR_BROADCOM=y
+# CONFIG_B44 is not set
+# CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2X is not set
+CONFIG_NET_VENDOR_BROCADE=y
+# CONFIG_BNA is not set
+# CONFIG_NET_CALXEDA_XGMAC is not set
+CONFIG_NET_VENDOR_CHELSIO=y
+# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3=m
+# CONFIG_CHELSIO_T4 is not set
+# CONFIG_CHELSIO_T4VF is not set
+CONFIG_NET_VENDOR_CISCO=y
+# CONFIG_ENIC is not set
+# CONFIG_DM9000 is not set
+# CONFIG_DNET is not set
+CONFIG_NET_VENDOR_DEC=y
+# CONFIG_NET_TULIP is not set
+CONFIG_NET_VENDOR_DLINK=y
+# CONFIG_DL2K is not set
+# CONFIG_SUNDANCE is not set
+CONFIG_NET_VENDOR_EMULEX=y
+# CONFIG_BE2NET is not set
+CONFIG_NET_VENDOR_EXAR=y
+# CONFIG_S2IO is not set
+# CONFIG_VXGE is not set
+CONFIG_NET_VENDOR_HP=y
+# CONFIG_HP100 is not set
+CONFIG_NET_VENDOR_INTEL=y
+# CONFIG_E100 is not set
+# CONFIG_E1000 is not set
+# CONFIG_E1000E is not set
+# CONFIG_IGB is not set
+# CONFIG_IGBVF is not set
+# CONFIG_IXGB is not set
+# CONFIG_IXGBE is not set
+CONFIG_NET_VENDOR_I825XX=y
+# CONFIG_IP1000 is not set
+# CONFIG_JME is not set
+CONFIG_NET_VENDOR_MARVELL=y
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+CONFIG_NET_VENDOR_MELLANOX=y
+# CONFIG_MLX4_EN is not set
+# CONFIG_MLX4_CORE is not set
+CONFIG_NET_VENDOR_MICREL=y
+# CONFIG_KS8851_MLL is not set
+# CONFIG_KSZ884X_PCI is not set
+CONFIG_NET_VENDOR_MYRI=y
+# CONFIG_MYRI10GE is not set
+# CONFIG_FEALNX is not set
+CONFIG_NET_VENDOR_NATSEMI=y
+# CONFIG_NATSEMI is not set
+# CONFIG_NS83820 is not set
+CONFIG_NET_VENDOR_8390=y
+CONFIG_AX88796=m
+# CONFIG_AX88796_93CX6 is not set
+# CONFIG_NE2K_PCI is not set
+CONFIG_NET_VENDOR_NVIDIA=y
+# CONFIG_FORCEDETH is not set
+CONFIG_NET_VENDOR_OKI=y
+# CONFIG_PCH_GBE is not set
+# CONFIG_ETHOC is not set
+CONFIG_NET_PACKET_ENGINE=y
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+CONFIG_NET_VENDOR_QLOGIC=y
+# CONFIG_QLA3XXX is not set
+# CONFIG_QLCNIC is not set
+# CONFIG_QLGE is not set
+CONFIG_NETXEN_NIC=m
+CONFIG_NET_VENDOR_REALTEK=y
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_R8169 is not set
+CONFIG_NET_VENDOR_RDC=y
+# CONFIG_R6040 is not set
+CONFIG_NET_VENDOR_SEEQ=y
+# CONFIG_SEEQ8005 is not set
+CONFIG_NET_VENDOR_SILAN=y
+# CONFIG_SC92031 is not set
+CONFIG_NET_VENDOR_SIS=y
+# CONFIG_SIS900 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SFC is not set
+CONFIG_NET_VENDOR_SMSC=y
+# CONFIG_SMC91X is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SMSC911X is not set
+# CONFIG_SMSC9420 is not set
+CONFIG_NET_VENDOR_STMICRO=y
+# CONFIG_STMMAC_ETH is not set
+CONFIG_NET_VENDOR_SUN=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NIU is not set
+CONFIG_NET_VENDOR_TEHUTI=y
+# CONFIG_TEHUTI is not set
+CONFIG_NET_VENDOR_TI=y
+# CONFIG_TLAN is not set
+CONFIG_NET_VENDOR_TOSHIBA=y
+CONFIG_TC35815=m
+CONFIG_NET_VENDOR_VIA=y
+# CONFIG_VIA_RHINE is not set
+# CONFIG_VIA_VELOCITY is not set
+CONFIG_NET_VENDOR_WIZNET=y
+# CONFIG_WIZNET_W5100 is not set
+# CONFIG_WIZNET_W5300 is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PHYLIB=m
+
+#
+# MII PHY device drivers
+#
+# CONFIG_AMD_PHY is not set
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+CONFIG_VITESSE_PHY=m
+CONFIG_SMSC_PHY=m
+CONFIG_BROADCOM_PHY=m
+# CONFIG_BCM87XX_PHY is not set
+CONFIG_ICPLUS_PHY=m
+CONFIG_REALTEK_PHY=m
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_MICREL_PHY is not set
+CONFIG_MDIO_BITBANG=m
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+CONFIG_WLAN=y
+# CONFIG_LIBERTAS_THINFIRM is not set
+# CONFIG_AIRO is not set
+CONFIG_ATMEL=m
+CONFIG_PCI_ATMEL=m
+CONFIG_PRISM54=m
+# CONFIG_RTL8180 is not set
+# CONFIG_ADM8211 is not set
+# CONFIG_MAC80211_HWSIM is not set
+# CONFIG_MWL8K is not set
+# CONFIG_ATH_COMMON is not set
+# CONFIG_B43 is not set
+# CONFIG_B43LEGACY is not set
+# CONFIG_BRCMFMAC is not set
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+CONFIG_HOSTAP_PLX=m
+CONFIG_HOSTAP_PCI=m
+CONFIG_IPW2100=m
+CONFIG_IPW2100_MONITOR=y
+# CONFIG_IPW2100_DEBUG is not set
+CONFIG_LIBIPW=m
+# CONFIG_LIBIPW_DEBUG is not set
+# CONFIG_IWLWIFI is not set
+# CONFIG_IWL4965 is not set
+# CONFIG_IWL3945 is not set
+CONFIG_LIBERTAS=m
+# CONFIG_LIBERTAS_DEBUG is not set
+# CONFIG_LIBERTAS_MESH is not set
+# CONFIG_P54_COMMON is not set
+# CONFIG_RT2X00 is not set
+# CONFIG_RTL8192CE is not set
+# CONFIG_RTL8192SE is not set
+# CONFIG_RTL8192DE is not set
+# CONFIG_WL_TI is not set
+# CONFIG_MWIFIEX is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# CONFIG_WAN is not set
+# CONFIG_VMXNET3 is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+# CONFIG_INPUT_MATRIXKMAP is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO_ALTERA_PS2 is not set
+# CONFIG_SERIO_PS2MULT is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_VT_CONSOLE_SLEEP=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_NOZOMI is not set
+# CONFIG_N_GSM is not set
+# CONFIG_TRACE_SINK is not set
+CONFIG_DEVKMEM=y
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_MFD_HSU is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+# CONFIG_SERIAL_SCCNXP is not set
+# CONFIG_SERIAL_TIMBERDALE is not set
+# CONFIG_SERIAL_ALTERA_JTAGUART is not set
+# CONFIG_SERIAL_ALTERA_UART is not set
+# CONFIG_SERIAL_PCH_UART is not set
+# CONFIG_SERIAL_XILINX_PS_UART is not set
+# CONFIG_TTY_PRINTK is not set
+# CONFIG_VIRTIO_CONSOLE is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=m
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+# CONFIG_HW_RANDOM_VIRTIO is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_DEVPORT=y
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+# CONFIG_HSI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+
+#
+# PPS generators support
+#
+
+#
+# PTP clock support
+#
+
+#
+# Enable Device Drivers -> PPS to see the PTP clock options.
+#
+CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_POWER_AVS is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+CONFIG_BCMA_POSSIBLE=y
+
+#
+# Broadcom specific AMBA
+#
+# CONFIG_BCMA is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_ABX500_CORE is not set
+# CONFIG_LPC_SCH is not set
+# CONFIG_LPC_ICH is not set
+# CONFIG_MFD_RDC321X is not set
+# CONFIG_MFD_JANZ_CMODIO is not set
+# CONFIG_MFD_VX855 is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+CONFIG_VGA_ARB=y
+CONFIG_VGA_ARB_MAX_GPUS=16
+# CONFIG_DRM is not set
+# CONFIG_STUB_POULSBO is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_WMT_GE_ROPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+CONFIG_FB_CIRRUS=y
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_UVESA is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_I740 is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_S3 is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_VT8623 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_ARK is not set
+# CONFIG_FB_PM3 is not set
+# CONFIG_FB_CARMINE is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_BROADSHEET is not set
+# CONFIG_FB_AUO_K190X is not set
+# CONFIG_EXYNOS_VIDEO is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+# CONFIG_LOGO is not set
+# CONFIG_SOUND is not set
+
+#
+# HID support
+#
+CONFIG_HID=m
+# CONFIG_HIDRAW is not set
+# CONFIG_UHID is not set
+CONFIG_HID_GENERIC=m
+
+#
+# Special HID drivers
+#
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB_ARCH_HAS_XHCI=y
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+# CONFIG_USB_EZUSB_FX2 is not set
+# CONFIG_OMAP_USB2 is not set
+# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_UWB is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_INFINIBAND is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+CONFIG_RTC_DRV_CMOS=y
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_MSM6242 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_RP5C01 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+# CONFIG_RTC_DRV_DS2404 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+CONFIG_UIO=m
+CONFIG_UIO_CIF=m
+# CONFIG_UIO_PDRV is not set
+# CONFIG_UIO_PDRV_GENIRQ is not set
+# CONFIG_UIO_AEC is not set
+# CONFIG_UIO_SERCOS3 is not set
+# CONFIG_UIO_PCI_GENERIC is not set
+# CONFIG_UIO_NETX is not set
+CONFIG_VIRTIO=y
+
+#
+# Virtio drivers
+#
+CONFIG_VIRTIO_PCI=y
+CONFIG_VIRTIO_BALLOON=y
+CONFIG_VIRTIO_MMIO=y
+# CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES is not set
+
+#
+# Microsoft Hyper-V guest support
+#
+# CONFIG_STAGING is not set
+
+#
+# Hardware Spinlock drivers
+#
+CONFIG_CLKSRC_I8253=y
+CONFIG_CLKEVT_I8253=y
+CONFIG_I8253_LOCK=y
+CONFIG_CLKBLD_I8253=y
+CONFIG_IOMMU_SUPPORT=y
+
+#
+# Remoteproc drivers (EXPERIMENTAL)
+#
+# CONFIG_STE_MODEM_RPROC is not set
+
+#
+# Rpmsg drivers (EXPERIMENTAL)
+#
+# CONFIG_VIRT_DRIVERS is not set
+# CONFIG_PM_DEVFREQ is not set
+# CONFIG_EXTCON is not set
+# CONFIG_MEMORY is not set
+# CONFIG_IIO is not set
+# CONFIG_VME_BUS is not set
+# CONFIG_PWM is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_DEFAULTS_TO_ORDERED=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4_FS is not set
+CONFIG_JBD=y
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+CONFIG_REISERFS_PROC_INFO=y
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+CONFIG_JFS_FS=m
+CONFIG_JFS_POSIX_ACL=y
+CONFIG_JFS_SECURITY=y
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+CONFIG_XFS_FS=m
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_POSIX_ACL=y
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_DEBUG is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_EXPORTFS=y
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_FANOTIFY is not set
+CONFIG_QUOTA=y
+# CONFIG_QUOTA_NETLINK_INTERFACE is not set
+CONFIG_PRINT_QUOTA_WARNING=y
+# CONFIG_QUOTA_DEBUG is not set
+CONFIG_QUOTA_TREE=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+# CONFIG_AUTOFS4_FS is not set
+CONFIG_FUSE_FS=m
+# CONFIG_CUSE is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+CONFIG_AFFS_FS=m
+CONFIG_HFS_FS=m
+CONFIG_HFSPLUS_FS=m
+CONFIG_BEFS_FS=m
+# CONFIG_BEFS_DEBUG is not set
+CONFIG_BFS_FS=m
+CONFIG_EFS_FS=m
+CONFIG_JFFS2_FS=m
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+CONFIG_JFFS2_FS_XATTR=y
+CONFIG_JFFS2_FS_POSIX_ACL=y
+CONFIG_JFFS2_FS_SECURITY=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+CONFIG_JFFS2_RUBIN=y
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
+# CONFIG_UBIFS_FS is not set
+# CONFIG_LOGFS is not set
+CONFIG_CRAMFS=m
+# CONFIG_SQUASHFS is not set
+CONFIG_VXFS_FS=m
+CONFIG_MINIX_FS=m
+CONFIG_MINIX_FS_NATIVE_ENDIAN=y
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX6FS_FS is not set
+CONFIG_ROMFS_FS=m
+CONFIG_ROMFS_BACKED_BY_BLOCK=y
+# CONFIG_ROMFS_BACKED_BY_MTD is not set
+# CONFIG_ROMFS_BACKED_BY_BOTH is not set
+CONFIG_ROMFS_ON_BLOCK=y
+# CONFIG_PSTORE is not set
+CONFIG_SYSV_FS=m
+CONFIG_UFS_FS=m
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_UFS_DEBUG is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V2=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_SWAP is not set
+CONFIG_ROOT_NFS=y
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+# CONFIG_NFSD_V4 is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_DEBUG is not set
+# CONFIG_CEPH_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+# CONFIG_NLS_MAC_ROMAN is not set
+# CONFIG_NLS_MAC_CELTIC is not set
+# CONFIG_NLS_MAC_CENTEURO is not set
+# CONFIG_NLS_MAC_CROATIAN is not set
+# CONFIG_NLS_MAC_CYRILLIC is not set
+# CONFIG_NLS_MAC_GAELIC is not set
+# CONFIG_NLS_MAC_GREEK is not set
+# CONFIG_NLS_MAC_ICELAND is not set
+# CONFIG_NLS_MAC_INUIT is not set
+# CONFIG_NLS_MAC_ROMANIAN is not set
+# CONFIG_NLS_MAC_TURKISH is not set
+CONFIG_NLS_UTF8=m
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_PRINTK_TIME is not set
+CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_READABLE_ASM is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_SECTION_MISMATCH is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+# CONFIG_LOCKUP_DETECTOR is not set
+# CONFIG_PANIC_ON_OOPS is not set
+CONFIG_PANIC_ON_OOPS_VALUE=0
+# CONFIG_DETECT_HUNG_TASK is not set
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_HAVE_DEBUG_KMEMLEAK=y
+# CONFIG_DEBUG_KMEMLEAK is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_SPARSE_RCU_POINTER is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_ATOMIC_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_TEST_LIST_SORT is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_TRACE is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+# CONFIG_NOTIFIER_ERROR_INJECTION is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_PROBE_EVENTS is not set
+# CONFIG_RBTREE_TEST is not set
+# CONFIG_INTERVAL_TREE_TEST is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
+# CONFIG_ASYNC_RAID6_TEST is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_TEST_KSTRTOX is not set
+CONFIG_EARLY_PRINTK=y
+# CONFIG_CMDLINE_BOOL is not set
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_RUNTIME_DEBUG is not set
+# CONFIG_DEBUG_ZBOOT is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY_DMESG_RESTRICT is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_XOR_BLOCKS=m
+CONFIG_ASYNC_CORE=m
+CONFIG_ASYNC_MEMCPY=m
+CONFIG_ASYNC_XOR=m
+CONFIG_ASYNC_PQ=m
+CONFIG_ASYNC_RAID6_RECOV=m
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP2=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_USER is not set
+CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_WORKQUEUE=y
+CONFIG_CRYPTO_CRYPTD=m
+CONFIG_CRYPTO_AUTHENC=m
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=m
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_XCBC=m
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_GHASH is not set
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=m
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_BLOWFISH_COMMON=m
+CONFIG_CRYPTO_CAMELLIA=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_KHAZAD=m
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=m
+# CONFIG_CRYPTO_ZLIB is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_USER_API_HASH is not set
+# CONFIG_CRYPTO_USER_API_SKCIPHER is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_RAID6_PQ=m
+CONFIG_BITREVERSE=y
+CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_IO=y
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC16=m
+# CONFIG_CRC_T10DIF is not set
+CONFIG_CRC_ITU_T=m
+CONFIG_CRC32=y
+# CONFIG_CRC32_SELFTEST is not set
+CONFIG_CRC32_SLICEBY8=y
+# CONFIG_CRC32_SLICEBY4 is not set
+# CONFIG_CRC32_SARWATE is not set
+# CONFIG_CRC32_BIT is not set
+# CONFIG_CRC7 is not set
+CONFIG_LIBCRC32C=m
+# CONFIG_CRC8 is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+# CONFIG_XZ_DEC is not set
+# CONFIG_XZ_DEC_BCJ is not set
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_DQL=y
+CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
+CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y
+CONFIG_AVERAGE=y
+# CONFIG_CORDIC is not set
+# CONFIG_DDR is not set
+CONFIG_HAVE_KVM=y
+# CONFIG_VIRTUALIZATION is not set
diff --git a/arch/mips/include/asm/hugetlb.h b/arch/mips/include/asm/hugetlb.h
index ef99db9..fe0d15d 100644
--- a/arch/mips/include/asm/hugetlb.h
+++ b/arch/mips/include/asm/hugetlb.h
@@ -10,6 +10,7 @@
 #define __ASM_HUGETLB_H
 
 #include <asm/page.h>
+#include <asm-generic/hugetlb.h>
 
 
 static inline int is_hugepage_only_range(struct mm_struct *mm,
diff --git a/arch/mips/include/asm/kvm.h b/arch/mips/include/asm/kvm.h
new file mode 100644
index 0000000..85789ea
--- /dev/null
+++ b/arch/mips/include/asm/kvm.h
@@ -0,0 +1,55 @@
+/*
+* 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) 2012  MIPS Technologies, Inc.  All rights reserved.
+* Authors: Sanjay Lal <sanjayl@kymasys.com>
+*/
+
+#ifndef __LINUX_KVM_MIPS_H
+#define __LINUX_KVM_MIPS_H
+
+#include <linux/types.h>
+
+#define __KVM_MIPS
+
+#define N_MIPS_COPROC_REGS      32
+#define N_MIPS_COPROC_SEL   	8
+
+/* for KVM_GET_REGS and KVM_SET_REGS */
+struct kvm_regs {
+	__u32 gprs[32];
+	__u32 hi;
+	__u32 lo;
+	__u32 pc;
+
+	__u32 cp0reg[N_MIPS_COPROC_REGS][N_MIPS_COPROC_SEL];
+};
+
+/* for KVM_GET_SREGS and KVM_SET_SREGS */
+struct kvm_sregs {
+};
+
+/* for KVM_GET_FPU and KVM_SET_FPU */
+struct kvm_fpu {
+};
+
+struct kvm_debug_exit_arch {
+};
+
+/* for KVM_SET_GUEST_DEBUG */
+struct kvm_guest_debug_arch {
+};
+
+struct kvm_mips_interrupt {
+	/* in */
+	__u32 cpu;
+	__u32 irq;
+};
+
+/* definition of registers in kvm_run */
+struct kvm_sync_regs {
+};
+
+#endif /* __LINUX_KVM_MIPS_H */
diff --git a/arch/mips/include/asm/kvm_host.h b/arch/mips/include/asm/kvm_host.h
new file mode 100644
index 0000000..143875c
--- /dev/null
+++ b/arch/mips/include/asm/kvm_host.h
@@ -0,0 +1,667 @@
+/*
+* 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) 2012  MIPS Technologies, Inc.  All rights reserved.
+* Authors: Sanjay Lal <sanjayl@kymasys.com>
+*/
+
+#ifndef __MIPS_KVM_HOST_H__
+#define __MIPS_KVM_HOST_H__
+
+#include <linux/mutex.h>
+#include <linux/hrtimer.h>
+#include <linux/interrupt.h>
+#include <linux/types.h>
+#include <linux/kvm.h>
+#include <linux/kvm_types.h>
+#include <linux/threads.h>
+#include <linux/spinlock.h>
+
+
+#define KVM_MAX_VCPUS		1
+#define KVM_USER_MEM_SLOTS	8
+/* memory slots that does not exposed to userspace */
+#define KVM_PRIVATE_MEM_SLOTS 	0
+
+#define KVM_COALESCED_MMIO_PAGE_OFFSET 1
+
+/* Don't support huge pages */
+#define KVM_HPAGE_GFN_SHIFT(x)	0
+
+/* We don't currently support large pages. */
+#define KVM_NR_PAGE_SIZES	1
+#define KVM_PAGES_PER_HPAGE(x)	1
+
+
+
+/* Special address that contains the comm page, used for reducing # of traps */
+#define KVM_GUEST_COMMPAGE_ADDR     0x0
+
+#define KVM_GUEST_KERNEL_MODE(vcpu)	((kvm_read_c0_guest_status(vcpu->arch.cop0) & (ST0_EXL | ST0_ERL)) || \
+					((kvm_read_c0_guest_status(vcpu->arch.cop0) & KSU_USER) == 0))
+
+#define KVM_GUEST_KUSEG             0x00000000UL
+#define KVM_GUEST_KSEG0             0x40000000UL
+#define KVM_GUEST_KSEG23            0x60000000UL
+#define KVM_GUEST_KSEGX(a)          ((_ACAST32_(a)) & 0x60000000)
+#define KVM_GUEST_CPHYSADDR(a)      ((_ACAST32_(a)) & 0x1fffffff)
+
+#define KVM_GUEST_CKSEG0ADDR(a)		(KVM_GUEST_CPHYSADDR(a) | KVM_GUEST_KSEG0)
+#define KVM_GUEST_CKSEG1ADDR(a)		(KVM_GUEST_CPHYSADDR(a) | KVM_GUEST_KSEG1)
+#define KVM_GUEST_CKSEG23ADDR(a)	(KVM_GUEST_CPHYSADDR(a) | KVM_GUEST_KSEG23)
+
+/*
+ * Map an address to a certain kernel segment
+ */
+#define KVM_GUEST_KSEG0ADDR(a)		(KVM_GUEST_CPHYSADDR(a) | KVM_GUEST_KSEG0)
+#define KVM_GUEST_KSEG1ADDR(a)		(KVM_GUEST_CPHYSADDR(a) | KVM_GUEST_KSEG1)
+#define KVM_GUEST_KSEG23ADDR(a)		(KVM_GUEST_CPHYSADDR(a) | KVM_GUEST_KSEG23)
+
+#define KVM_INVALID_PAGE            0xdeadbeef
+#define KVM_INVALID_INST            0xdeadbeef
+#define KVM_INVALID_ADDR            0xdeadbeef
+
+#define KVM_MALTA_GUEST_RTC_ADDR    0xb8000070UL
+
+#define GUEST_TICKS_PER_JIFFY (40000000/HZ)
+#define MS_TO_NS(x) (x * 1E6L)
+
+#define CAUSEB_DC       27
+#define CAUSEF_DC       (_ULCAST_(1)   << 27)
+
+struct kvm;
+struct kvm_run;
+struct kvm_vcpu;
+struct kvm_interrupt;
+
+extern atomic_t kvm_mips_instance;
+extern pfn_t(*kvm_mips_gfn_to_pfn) (struct kvm *kvm, gfn_t gfn);
+extern void (*kvm_mips_release_pfn_clean) (pfn_t pfn);
+extern bool(*kvm_mips_is_error_pfn) (pfn_t pfn);
+
+struct kvm_vm_stat {
+	u32 remote_tlb_flush;
+};
+
+struct kvm_vcpu_stat {
+	u32 wait_exits;
+	u32 cache_exits;
+	u32 signal_exits;
+	u32 int_exits;
+	u32 cop_unusable_exits;
+	u32 tlbmod_exits;
+	u32 tlbmiss_ld_exits;
+	u32 tlbmiss_st_exits;
+	u32 addrerr_st_exits;
+	u32 addrerr_ld_exits;
+	u32 syscall_exits;
+	u32 resvd_inst_exits;
+	u32 break_inst_exits;
+	u32 flush_dcache_exits;
+	u32 halt_wakeup;
+};
+
+enum kvm_mips_exit_types {
+	WAIT_EXITS,
+	CACHE_EXITS,
+	SIGNAL_EXITS,
+	INT_EXITS,
+	COP_UNUSABLE_EXITS,
+	TLBMOD_EXITS,
+	TLBMISS_LD_EXITS,
+	TLBMISS_ST_EXITS,
+	ADDRERR_ST_EXITS,
+	ADDRERR_LD_EXITS,
+	SYSCALL_EXITS,
+	RESVD_INST_EXITS,
+	BREAK_INST_EXITS,
+	FLUSH_DCACHE_EXITS,
+	MAX_KVM_MIPS_EXIT_TYPES
+};
+
+struct kvm_arch_memory_slot {
+};
+
+struct kvm_arch {
+	/* Guest GVA->HPA page table */
+	unsigned long *guest_pmap;
+	unsigned long guest_pmap_npages;
+
+	/* Wired host TLB used for the commpage */
+	int commpage_tlb;
+};
+
+#define N_MIPS_COPROC_REGS      32
+#define N_MIPS_COPROC_SEL   	8
+
+struct mips_coproc {
+	unsigned long reg[N_MIPS_COPROC_REGS][N_MIPS_COPROC_SEL];
+#ifdef CONFIG_KVM_MIPS_DEBUG_COP0_COUNTERS
+	unsigned long stat[N_MIPS_COPROC_REGS][N_MIPS_COPROC_SEL];
+#endif
+};
+
+/*
+ * Coprocessor 0 register names
+ */
+#define	MIPS_CP0_TLB_INDEX	    0
+#define	MIPS_CP0_TLB_RANDOM	    1
+#define	MIPS_CP0_TLB_LOW	    2
+#define	MIPS_CP0_TLB_LO0	    2
+#define	MIPS_CP0_TLB_LO1	    3
+#define	MIPS_CP0_TLB_CONTEXT	4
+#define	MIPS_CP0_TLB_PG_MASK	5
+#define	MIPS_CP0_TLB_WIRED	    6
+#define	MIPS_CP0_HWRENA 	    7
+#define	MIPS_CP0_BAD_VADDR	    8
+#define	MIPS_CP0_COUNT	        9
+#define	MIPS_CP0_TLB_HI	        10
+#define	MIPS_CP0_COMPARE	    11
+#define	MIPS_CP0_STATUS	        12
+#define	MIPS_CP0_CAUSE	        13
+#define	MIPS_CP0_EXC_PC	        14
+#define	MIPS_CP0_PRID		    15
+#define	MIPS_CP0_CONFIG	        16
+#define	MIPS_CP0_LLADDR	        17
+#define	MIPS_CP0_WATCH_LO	    18
+#define	MIPS_CP0_WATCH_HI	    19
+#define	MIPS_CP0_TLB_XCONTEXT   20
+#define	MIPS_CP0_ECC		    26
+#define	MIPS_CP0_CACHE_ERR	    27
+#define	MIPS_CP0_TAG_LO	        28
+#define	MIPS_CP0_TAG_HI	        29
+#define	MIPS_CP0_ERROR_PC	    30
+#define	MIPS_CP0_DEBUG	        23
+#define	MIPS_CP0_DEPC		    24
+#define	MIPS_CP0_PERFCNT	    25
+#define	MIPS_CP0_ERRCTL         26
+#define	MIPS_CP0_DATA_LO	    28
+#define	MIPS_CP0_DATA_HI	    29
+#define	MIPS_CP0_DESAVE	        31
+
+#define MIPS_CP0_CONFIG_SEL	    0
+#define MIPS_CP0_CONFIG1_SEL    1
+#define MIPS_CP0_CONFIG2_SEL    2
+#define MIPS_CP0_CONFIG3_SEL    3
+
+/* Config0 register bits */
+#define CP0C0_M    31
+#define CP0C0_K23  28
+#define CP0C0_KU   25
+#define CP0C0_MDU  20
+#define CP0C0_MM   17
+#define CP0C0_BM   16
+#define CP0C0_BE   15
+#define CP0C0_AT   13
+#define CP0C0_AR   10
+#define CP0C0_MT   7
+#define CP0C0_VI   3
+#define CP0C0_K0   0
+
+/* Config1 register bits */
+#define CP0C1_M    31
+#define CP0C1_MMU  25
+#define CP0C1_IS   22
+#define CP0C1_IL   19
+#define CP0C1_IA   16
+#define CP0C1_DS   13
+#define CP0C1_DL   10
+#define CP0C1_DA   7
+#define CP0C1_C2   6
+#define CP0C1_MD   5
+#define CP0C1_PC   4
+#define CP0C1_WR   3
+#define CP0C1_CA   2
+#define CP0C1_EP   1
+#define CP0C1_FP   0
+
+/* Config2 Register bits */
+#define CP0C2_M    31
+#define CP0C2_TU   28
+#define CP0C2_TS   24
+#define CP0C2_TL   20
+#define CP0C2_TA   16
+#define CP0C2_SU   12
+#define CP0C2_SS   8
+#define CP0C2_SL   4
+#define CP0C2_SA   0
+
+/* Config3 Register bits */
+#define CP0C3_M    31
+#define CP0C3_ISA_ON_EXC 16
+#define CP0C3_ULRI  13
+#define CP0C3_DSPP 10
+#define CP0C3_LPA  7
+#define CP0C3_VEIC 6
+#define CP0C3_VInt 5
+#define CP0C3_SP   4
+#define CP0C3_MT   2
+#define CP0C3_SM   1
+#define CP0C3_TL   0
+
+/* Have config1, Cacheable, noncoherent, write-back, write allocate*/
+#define MIPS_CONFIG0                                              \
+  ((1 << CP0C0_M) | (0x3 << CP0C0_K0))
+
+/* Have config2, no coprocessor2 attached, no MDMX support attached,
+   no performance counters, watch registers present,
+   no code compression, EJTAG present, no FPU, no watch registers */
+#define MIPS_CONFIG1                                              \
+((1 << CP0C1_M) |                                                 \
+ (0 << CP0C1_C2) | (0 << CP0C1_MD) | (0 << CP0C1_PC) |            \
+ (0 << CP0C1_WR) | (0 << CP0C1_CA) | (1 << CP0C1_EP) |            \
+ (0 << CP0C1_FP))
+
+/* Have config3, no tertiary/secondary caches implemented */
+#define MIPS_CONFIG2                                              \
+((1 << CP0C2_M))
+
+/* No config4, no DSP ASE, no large physaddr (PABITS),
+   no external interrupt controller, no vectored interrupts,
+   no 1kb pages, no SmartMIPS ASE, no trace logic */
+#define MIPS_CONFIG3                                              \
+((0 << CP0C3_M) | (0 << CP0C3_DSPP) | (0 << CP0C3_LPA) |          \
+ (0 << CP0C3_VEIC) | (0 << CP0C3_VInt) | (0 << CP0C3_SP) |        \
+ (0 << CP0C3_SM) | (0 << CP0C3_TL))
+
+/* MMU types, the first four entries have the same layout as the
+   CP0C0_MT field.  */
+enum mips_mmu_types {
+	MMU_TYPE_NONE,
+	MMU_TYPE_R4000,
+	MMU_TYPE_RESERVED,
+	MMU_TYPE_FMT,
+	MMU_TYPE_R3000,
+	MMU_TYPE_R6000,
+	MMU_TYPE_R8000
+};
+
+/*
+ * Trap codes
+ */
+#define T_INT           0	/* Interrupt pending */
+#define T_TLB_MOD       1	/* TLB modified fault */
+#define T_TLB_LD_MISS       2	/* TLB miss on load or ifetch */
+#define T_TLB_ST_MISS       3	/* TLB miss on a store */
+#define T_ADDR_ERR_LD       4	/* Address error on a load or ifetch */
+#define T_ADDR_ERR_ST       5	/* Address error on a store */
+#define T_BUS_ERR_IFETCH    6	/* Bus error on an ifetch */
+#define T_BUS_ERR_LD_ST     7	/* Bus error on a load or store */
+#define T_SYSCALL       8	/* System call */
+#define T_BREAK         9	/* Breakpoint */
+#define T_RES_INST      10	/* Reserved instruction exception */
+#define T_COP_UNUSABLE      11	/* Coprocessor unusable */
+#define T_OVFLOW        12	/* Arithmetic overflow */
+
+/*
+ * Trap definitions added for r4000 port.
+ */
+#define T_TRAP          13	/* Trap instruction */
+#define T_VCEI          14	/* Virtual coherency exception */
+#define T_FPE           15	/* Floating point exception */
+#define T_WATCH         23	/* Watch address reference */
+#define T_VCED          31	/* Virtual coherency data */
+
+/* Resume Flags */
+#define RESUME_FLAG_DR          (1<<0)	/* Reload guest nonvolatile state? */
+#define RESUME_FLAG_HOST        (1<<1)	/* Resume host? */
+
+#define RESUME_GUEST            0
+#define RESUME_GUEST_DR         RESUME_FLAG_DR
+#define RESUME_HOST             RESUME_FLAG_HOST
+
+enum emulation_result {
+	EMULATE_DONE,		/* no further processing */
+	EMULATE_DO_MMIO,	/* kvm_run filled with MMIO request */
+	EMULATE_FAIL,		/* can't emulate this instruction */
+	EMULATE_WAIT,		/* WAIT instruction */
+	EMULATE_PRIV_FAIL,
+};
+
+#define MIPS3_PG_G  0x00000001	/* Global; ignore ASID if in lo0 & lo1 */
+#define MIPS3_PG_V  0x00000002	/* Valid */
+#define MIPS3_PG_NV 0x00000000
+#define MIPS3_PG_D  0x00000004	/* Dirty */
+
+#define mips3_paddr_to_tlbpfn(x) \
+    (((unsigned long)(x) >> MIPS3_PG_SHIFT) & MIPS3_PG_FRAME)
+#define mips3_tlbpfn_to_paddr(x) \
+    ((unsigned long)((x) & MIPS3_PG_FRAME) << MIPS3_PG_SHIFT)
+
+#define MIPS3_PG_SHIFT      6
+#define MIPS3_PG_FRAME      0x3fffffc0
+
+#define VPN2_MASK           0xffffe000
+#define TLB_IS_GLOBAL(x)    (((x).tlb_lo0 & MIPS3_PG_G) && ((x).tlb_lo1 & MIPS3_PG_G))
+#define TLB_VPN2(x)         ((x).tlb_hi & VPN2_MASK)
+#define TLB_ASID(x)         ((x).tlb_hi & ASID_MASK)
+#define TLB_IS_VALID(x, va) (((va) & (1 << PAGE_SHIFT)) ? ((x).tlb_lo1 & MIPS3_PG_V) : ((x).tlb_lo0 & MIPS3_PG_V))
+
+struct kvm_mips_tlb {
+	long tlb_mask;
+	long tlb_hi;
+	long tlb_lo0;
+	long tlb_lo1;
+};
+
+#define KVM_MIPS_GUEST_TLB_SIZE     64
+struct kvm_vcpu_arch {
+	void *host_ebase, *guest_ebase;
+	unsigned long host_stack;
+	unsigned long host_gp;
+
+	/* Host CP0 registers used when handling exits from guest */
+	unsigned long host_cp0_badvaddr;
+	unsigned long host_cp0_cause;
+	unsigned long host_cp0_epc;
+	unsigned long host_cp0_entryhi;
+	uint32_t guest_inst;
+
+	/* GPRS */
+	unsigned long gprs[32];
+	unsigned long hi;
+	unsigned long lo;
+	unsigned long pc;
+
+	/* FPU State */
+	struct mips_fpu_struct fpu;
+
+	/* COP0 State */
+	struct mips_coproc *cop0;
+
+	/* Host KSEG0 address of the EI/DI offset */
+	void *kseg0_commpage;
+
+	u32 io_gpr;		/* GPR used as IO source/target */
+
+	/* Used to calibrate the virutal count register for the guest */
+	int32_t host_cp0_count;
+
+	/* Bitmask of exceptions that are pending */
+	unsigned long pending_exceptions;
+
+	/* Bitmask of pending exceptions to be cleared */
+	unsigned long pending_exceptions_clr;
+
+	unsigned long pending_load_cause;
+
+	/* Save/Restore the entryhi register when are are preempted/scheduled back in */
+	unsigned long preempt_entryhi;
+
+	/* S/W Based TLB for guest */
+	struct kvm_mips_tlb guest_tlb[KVM_MIPS_GUEST_TLB_SIZE];
+
+	/* Cached guest kernel/user ASIDs */
+	uint32_t guest_user_asid[NR_CPUS];
+	uint32_t guest_kernel_asid[NR_CPUS];
+	struct mm_struct guest_kernel_mm, guest_user_mm;
+
+	struct kvm_mips_tlb shadow_tlb[NR_CPUS][KVM_MIPS_GUEST_TLB_SIZE];
+
+
+	struct hrtimer comparecount_timer;
+
+	int last_sched_cpu;
+
+	/* WAIT executed */
+	int wait;
+};
+
+
+#define kvm_read_c0_guest_index(cop0)               (cop0->reg[MIPS_CP0_TLB_INDEX][0])
+#define kvm_write_c0_guest_index(cop0, val)         (cop0->reg[MIPS_CP0_TLB_INDEX][0] = val)
+#define kvm_read_c0_guest_entrylo0(cop0)            (cop0->reg[MIPS_CP0_TLB_LO0][0])
+#define kvm_read_c0_guest_entrylo1(cop0)            (cop0->reg[MIPS_CP0_TLB_LO1][0])
+#define kvm_read_c0_guest_context(cop0)             (cop0->reg[MIPS_CP0_TLB_CONTEXT][0])
+#define kvm_write_c0_guest_context(cop0, val)       (cop0->reg[MIPS_CP0_TLB_CONTEXT][0] = (val))
+#define kvm_read_c0_guest_userlocal(cop0)           (cop0->reg[MIPS_CP0_TLB_CONTEXT][2])
+#define kvm_read_c0_guest_pagemask(cop0)            (cop0->reg[MIPS_CP0_TLB_PG_MASK][0])
+#define kvm_write_c0_guest_pagemask(cop0, val)      (cop0->reg[MIPS_CP0_TLB_PG_MASK][0] = (val))
+#define kvm_read_c0_guest_wired(cop0)               (cop0->reg[MIPS_CP0_TLB_WIRED][0])
+#define kvm_write_c0_guest_wired(cop0, val)         (cop0->reg[MIPS_CP0_TLB_WIRED][0] = (val))
+#define kvm_read_c0_guest_badvaddr(cop0)            (cop0->reg[MIPS_CP0_BAD_VADDR][0])
+#define kvm_write_c0_guest_badvaddr(cop0, val)      (cop0->reg[MIPS_CP0_BAD_VADDR][0] = (val))
+#define kvm_read_c0_guest_count(cop0)               (cop0->reg[MIPS_CP0_COUNT][0])
+#define kvm_write_c0_guest_count(cop0, val)         (cop0->reg[MIPS_CP0_COUNT][0] = (val))
+#define kvm_read_c0_guest_entryhi(cop0)             (cop0->reg[MIPS_CP0_TLB_HI][0])
+#define kvm_write_c0_guest_entryhi(cop0, val)       (cop0->reg[MIPS_CP0_TLB_HI][0] = (val))
+#define kvm_read_c0_guest_compare(cop0)             (cop0->reg[MIPS_CP0_COMPARE][0])
+#define kvm_write_c0_guest_compare(cop0, val)       (cop0->reg[MIPS_CP0_COMPARE][0] = (val))
+#define kvm_read_c0_guest_status(cop0)              (cop0->reg[MIPS_CP0_STATUS][0])
+#define kvm_write_c0_guest_status(cop0, val)        (cop0->reg[MIPS_CP0_STATUS][0] = (val))
+#define kvm_read_c0_guest_intctl(cop0)              (cop0->reg[MIPS_CP0_STATUS][1])
+#define kvm_write_c0_guest_intctl(cop0, val)        (cop0->reg[MIPS_CP0_STATUS][1] = (val))
+#define kvm_read_c0_guest_cause(cop0)               (cop0->reg[MIPS_CP0_CAUSE][0])
+#define kvm_write_c0_guest_cause(cop0, val)         (cop0->reg[MIPS_CP0_CAUSE][0] = (val))
+#define kvm_read_c0_guest_epc(cop0)                 (cop0->reg[MIPS_CP0_EXC_PC][0])
+#define kvm_write_c0_guest_epc(cop0, val)           (cop0->reg[MIPS_CP0_EXC_PC][0] = (val))
+#define kvm_read_c0_guest_prid(cop0)                (cop0->reg[MIPS_CP0_PRID][0])
+#define kvm_write_c0_guest_prid(cop0, val)          (cop0->reg[MIPS_CP0_PRID][0] = (val))
+#define kvm_read_c0_guest_ebase(cop0)               (cop0->reg[MIPS_CP0_PRID][1])
+#define kvm_write_c0_guest_ebase(cop0, val)         (cop0->reg[MIPS_CP0_PRID][1] = (val))
+#define kvm_read_c0_guest_config(cop0)              (cop0->reg[MIPS_CP0_CONFIG][0])
+#define kvm_read_c0_guest_config1(cop0)             (cop0->reg[MIPS_CP0_CONFIG][1])
+#define kvm_read_c0_guest_config2(cop0)             (cop0->reg[MIPS_CP0_CONFIG][2])
+#define kvm_read_c0_guest_config3(cop0)             (cop0->reg[MIPS_CP0_CONFIG][3])
+#define kvm_read_c0_guest_config7(cop0)             (cop0->reg[MIPS_CP0_CONFIG][7])
+#define kvm_write_c0_guest_config(cop0, val)        (cop0->reg[MIPS_CP0_CONFIG][0] = (val))
+#define kvm_write_c0_guest_config1(cop0, val)       (cop0->reg[MIPS_CP0_CONFIG][1] = (val))
+#define kvm_write_c0_guest_config2(cop0, val)       (cop0->reg[MIPS_CP0_CONFIG][2] = (val))
+#define kvm_write_c0_guest_config3(cop0, val)       (cop0->reg[MIPS_CP0_CONFIG][3] = (val))
+#define kvm_write_c0_guest_config7(cop0, val)       (cop0->reg[MIPS_CP0_CONFIG][7] = (val))
+#define kvm_read_c0_guest_errorepc(cop0)            (cop0->reg[MIPS_CP0_ERROR_PC][0])
+#define kvm_write_c0_guest_errorepc(cop0, val)      (cop0->reg[MIPS_CP0_ERROR_PC][0] = (val))
+
+#define kvm_set_c0_guest_status(cop0, val)          (cop0->reg[MIPS_CP0_STATUS][0] |= (val))
+#define kvm_clear_c0_guest_status(cop0, val)        (cop0->reg[MIPS_CP0_STATUS][0] &= ~(val))
+#define kvm_set_c0_guest_cause(cop0, val)           (cop0->reg[MIPS_CP0_CAUSE][0] |= (val))
+#define kvm_clear_c0_guest_cause(cop0, val)         (cop0->reg[MIPS_CP0_CAUSE][0] &= ~(val))
+#define kvm_change_c0_guest_cause(cop0, change, val)  \
+{                                                     \
+    kvm_clear_c0_guest_cause(cop0, change);           \
+    kvm_set_c0_guest_cause(cop0, ((val) & (change))); \
+}
+#define kvm_set_c0_guest_ebase(cop0, val)           (cop0->reg[MIPS_CP0_PRID][1] |= (val))
+#define kvm_clear_c0_guest_ebase(cop0, val)         (cop0->reg[MIPS_CP0_PRID][1] &= ~(val))
+#define kvm_change_c0_guest_ebase(cop0, change, val)  \
+{                                                     \
+    kvm_clear_c0_guest_ebase(cop0, change);           \
+    kvm_set_c0_guest_ebase(cop0, ((val) & (change))); \
+}
+
+
+struct kvm_mips_callbacks {
+	int (*handle_cop_unusable) (struct kvm_vcpu *vcpu);
+	int (*handle_tlb_mod) (struct kvm_vcpu *vcpu);
+	int (*handle_tlb_ld_miss) (struct kvm_vcpu *vcpu);
+	int (*handle_tlb_st_miss) (struct kvm_vcpu *vcpu);
+	int (*handle_addr_err_st) (struct kvm_vcpu *vcpu);
+	int (*handle_addr_err_ld) (struct kvm_vcpu *vcpu);
+	int (*handle_syscall) (struct kvm_vcpu *vcpu);
+	int (*handle_res_inst) (struct kvm_vcpu *vcpu);
+	int (*handle_break) (struct kvm_vcpu *vcpu);
+	int (*vm_init) (struct kvm *kvm);
+	int (*vcpu_init) (struct kvm_vcpu *vcpu);
+	int (*vcpu_setup) (struct kvm_vcpu *vcpu);
+	 gpa_t(*gva_to_gpa) (gva_t gva);
+	void (*queue_timer_int) (struct kvm_vcpu *vcpu);
+	void (*dequeue_timer_int) (struct kvm_vcpu *vcpu);
+	void (*queue_io_int) (struct kvm_vcpu *vcpu,
+			      struct kvm_mips_interrupt *irq);
+	void (*dequeue_io_int) (struct kvm_vcpu *vcpu,
+				struct kvm_mips_interrupt *irq);
+	int (*irq_deliver) (struct kvm_vcpu *vcpu, unsigned int priority,
+			    uint32_t cause);
+	int (*irq_clear) (struct kvm_vcpu *vcpu, unsigned int priority,
+			  uint32_t cause);
+	int (*vcpu_ioctl_get_regs) (struct kvm_vcpu *vcpu,
+				    struct kvm_regs *regs);
+	int (*vcpu_ioctl_set_regs) (struct kvm_vcpu *vcpu,
+				    struct kvm_regs *regs);
+};
+extern struct kvm_mips_callbacks *kvm_mips_callbacks;
+int kvm_mips_emulation_init(struct kvm_mips_callbacks **install_callbacks);
+
+/* Debug: dump vcpu state */
+int kvm_arch_vcpu_dump_regs(struct kvm_vcpu *vcpu);
+
+/* Trampoline ASM routine to start running in "Guest" context */
+extern int __kvm_mips_vcpu_run(struct kvm_run *run, struct kvm_vcpu *vcpu);
+
+/* TLB handling */
+uint32_t kvm_get_kernel_asid(struct kvm_vcpu *vcpu);
+
+uint32_t kvm_get_user_asid(struct kvm_vcpu *vcpu);
+
+uint32_t kvm_get_commpage_asid (struct kvm_vcpu *vcpu);
+
+extern int kvm_mips_handle_kseg0_tlb_fault(unsigned long badbaddr,
+					   struct kvm_vcpu *vcpu);
+
+extern int kvm_mips_handle_commpage_tlb_fault(unsigned long badvaddr,
+					      struct kvm_vcpu *vcpu);
+
+extern int kvm_mips_handle_mapped_seg_tlb_fault(struct kvm_vcpu *vcpu,
+						struct kvm_mips_tlb *tlb,
+						unsigned long *hpa0,
+						unsigned long *hpa1);
+
+extern enum emulation_result kvm_mips_handle_tlbmiss(unsigned long cause,
+						     uint32_t *opc,
+						     struct kvm_run *run,
+						     struct kvm_vcpu *vcpu);
+
+extern enum emulation_result kvm_mips_handle_tlbmod(unsigned long cause,
+						    uint32_t *opc,
+						    struct kvm_run *run,
+						    struct kvm_vcpu *vcpu);
+
+extern void kvm_mips_dump_host_tlbs(void);
+extern void kvm_mips_dump_guest_tlbs(struct kvm_vcpu *vcpu);
+extern void kvm_mips_dump_shadow_tlbs(struct kvm_vcpu *vcpu);
+extern void kvm_mips_flush_host_tlb(int skip_kseg0);
+extern int kvm_mips_host_tlb_inv(struct kvm_vcpu *vcpu, unsigned long entryhi);
+extern int kvm_mips_host_tlb_inv_index(struct kvm_vcpu *vcpu, int index);
+
+extern int kvm_mips_guest_tlb_lookup(struct kvm_vcpu *vcpu,
+				     unsigned long entryhi);
+extern int kvm_mips_host_tlb_lookup(struct kvm_vcpu *vcpu, unsigned long vaddr);
+extern unsigned long kvm_mips_translate_guest_kseg0_to_hpa(struct kvm_vcpu *vcpu,
+						   unsigned long gva);
+extern void kvm_get_new_mmu_context(struct mm_struct *mm, unsigned long cpu,
+				    struct kvm_vcpu *vcpu);
+extern void kvm_shadow_tlb_put(struct kvm_vcpu *vcpu);
+extern void kvm_shadow_tlb_load(struct kvm_vcpu *vcpu);
+extern void kvm_local_flush_tlb_all(void);
+extern void kvm_mips_init_shadow_tlb(struct kvm_vcpu *vcpu);
+extern void kvm_mips_alloc_new_mmu_context(struct kvm_vcpu *vcpu);
+extern void kvm_mips_vcpu_load(struct kvm_vcpu *vcpu, int cpu);
+extern void kvm_mips_vcpu_put(struct kvm_vcpu *vcpu);
+
+/* Emulation */
+uint32_t kvm_get_inst(uint32_t *opc, struct kvm_vcpu *vcpu);
+enum emulation_result update_pc(struct kvm_vcpu *vcpu, uint32_t cause);
+
+extern enum emulation_result kvm_mips_emulate_inst(unsigned long cause,
+						   uint32_t *opc,
+						   struct kvm_run *run,
+						   struct kvm_vcpu *vcpu);
+
+extern enum emulation_result kvm_mips_emulate_syscall(unsigned long cause,
+						      uint32_t *opc,
+						      struct kvm_run *run,
+						      struct kvm_vcpu *vcpu);
+
+extern enum emulation_result kvm_mips_emulate_tlbmiss_ld(unsigned long cause,
+							 uint32_t *opc,
+							 struct kvm_run *run,
+							 struct kvm_vcpu *vcpu);
+
+extern enum emulation_result kvm_mips_emulate_tlbinv_ld(unsigned long cause,
+							uint32_t *opc,
+							struct kvm_run *run,
+							struct kvm_vcpu *vcpu);
+
+extern enum emulation_result kvm_mips_emulate_tlbmiss_st(unsigned long cause,
+							 uint32_t *opc,
+							 struct kvm_run *run,
+							 struct kvm_vcpu *vcpu);
+
+extern enum emulation_result kvm_mips_emulate_tlbinv_st(unsigned long cause,
+							uint32_t *opc,
+							struct kvm_run *run,
+							struct kvm_vcpu *vcpu);
+
+extern enum emulation_result kvm_mips_emulate_tlbmod(unsigned long cause,
+						     uint32_t *opc,
+						     struct kvm_run *run,
+						     struct kvm_vcpu *vcpu);
+
+extern enum emulation_result kvm_mips_emulate_fpu_exc(unsigned long cause,
+						      uint32_t *opc,
+						      struct kvm_run *run,
+						      struct kvm_vcpu *vcpu);
+
+extern enum emulation_result kvm_mips_handle_ri(unsigned long cause,
+						uint32_t *opc,
+						struct kvm_run *run,
+						struct kvm_vcpu *vcpu);
+
+extern enum emulation_result kvm_mips_emulate_ri_exc(unsigned long cause,
+						     uint32_t *opc,
+						     struct kvm_run *run,
+						     struct kvm_vcpu *vcpu);
+
+extern enum emulation_result kvm_mips_emulate_bp_exc(unsigned long cause,
+						     uint32_t *opc,
+						     struct kvm_run *run,
+						     struct kvm_vcpu *vcpu);
+
+extern enum emulation_result kvm_mips_complete_mmio_load(struct kvm_vcpu *vcpu,
+							 struct kvm_run *run);
+
+enum emulation_result kvm_mips_emulate_count(struct kvm_vcpu *vcpu);
+
+enum emulation_result kvm_mips_check_privilege(unsigned long cause,
+					       uint32_t *opc,
+					       struct kvm_run *run,
+					       struct kvm_vcpu *vcpu);
+
+enum emulation_result kvm_mips_emulate_cache(uint32_t inst,
+					     uint32_t *opc,
+					     uint32_t cause,
+					     struct kvm_run *run,
+					     struct kvm_vcpu *vcpu);
+enum emulation_result kvm_mips_emulate_CP0(uint32_t inst,
+					   uint32_t *opc,
+					   uint32_t cause,
+					   struct kvm_run *run,
+					   struct kvm_vcpu *vcpu);
+enum emulation_result kvm_mips_emulate_store(uint32_t inst,
+					     uint32_t cause,
+					     struct kvm_run *run,
+					     struct kvm_vcpu *vcpu);
+enum emulation_result kvm_mips_emulate_load(uint32_t inst,
+					    uint32_t cause,
+					    struct kvm_run *run,
+					    struct kvm_vcpu *vcpu);
+
+/* Dynamic binary translation */
+extern int kvm_mips_trans_cache_index(uint32_t inst, uint32_t *opc,
+				      struct kvm_vcpu *vcpu);
+extern int kvm_mips_trans_cache_va(uint32_t inst, uint32_t *opc,
+				   struct kvm_vcpu *vcpu);
+extern int kvm_mips_trans_mfc0(uint32_t inst, uint32_t *opc,
+			       struct kvm_vcpu *vcpu);
+extern int kvm_mips_trans_mtc0(uint32_t inst, uint32_t *opc,
+			       struct kvm_vcpu *vcpu);
+
+/* Misc */
+extern void mips32_SyncICache(unsigned long addr, unsigned long size);
+extern int kvm_mips_dump_stats(struct kvm_vcpu *vcpu);
+extern unsigned long kvm_mips_get_ramsize(struct kvm *kvm);
+
+
+#endif /* __MIPS_KVM_HOST_H__ */
diff --git a/arch/mips/include/asm/linkage.h b/arch/mips/include/asm/linkage.h
index e9a940d..2767dda 100644
--- a/arch/mips/include/asm/linkage.h
+++ b/arch/mips/include/asm/linkage.h
@@ -6,5 +6,8 @@
 #endif
 
 #define __weak __attribute__((weak))
+#define cond_syscall(x) asm(".weak\t" #x "\n" #x "\t=\tsys_ni_syscall")
+#define SYSCALL_ALIAS(alias, name)					\
+	asm ( #alias " = " #name "\n\t.globl " #alias)
 
 #endif
diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_nvram.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_nvram.h
index 62d6a3b..4e0b6bc 100644
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_nvram.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_nvram.h
@@ -9,10 +9,8 @@
  *
  * Initialized the local nvram copy from the target address and checks
  * its checksum.
- *
- * Returns 0 on success.
  */
-int __init bcm63xx_nvram_init(void *nvram);
+void bcm63xx_nvram_init(void *nvram);
 
 /**
  * bcm63xx_nvram_get_name() - returns the board name according to nvram
diff --git a/arch/mips/include/asm/mach-generic/spaces.h b/arch/mips/include/asm/mach-generic/spaces.h
index 73d717a..5b2f2e6 100644
--- a/arch/mips/include/asm/mach-generic/spaces.h
+++ b/arch/mips/include/asm/mach-generic/spaces.h
@@ -20,14 +20,21 @@
 #endif
 
 #ifdef CONFIG_32BIT
-
+#ifdef CONFIG_KVM_GUEST
+#define CAC_BASE		_AC(0x40000000, UL)
+#else
 #define CAC_BASE		_AC(0x80000000, UL)
+#endif
 #define IO_BASE			_AC(0xa0000000, UL)
 #define UNCAC_BASE		_AC(0xa0000000, UL)
 
 #ifndef MAP_BASE
+#ifdef CONFIG_KVM_GUEST
+#define MAP_BASE		_AC(0x60000000, UL)
+#else
 #define MAP_BASE		_AC(0xc0000000, UL)
 #endif
+#endif
 
 /*
  * Memory above this physical address will be considered highmem.
diff --git a/arch/mips/include/asm/mach-sead3/cpu-feature-overrides.h b/arch/mips/include/asm/mach-sead3/cpu-feature-overrides.h
index d9c8284..193c091 100644
--- a/arch/mips/include/asm/mach-sead3/cpu-feature-overrides.h
+++ b/arch/mips/include/asm/mach-sead3/cpu-feature-overrides.h
@@ -28,11 +28,7 @@
 /* #define cpu_has_prefetch	? */
 #define cpu_has_mcheck		1
 /* #define cpu_has_ejtag	? */
-#ifdef CONFIG_CPU_HAS_LLSC
 #define cpu_has_llsc		1
-#else
-#define cpu_has_llsc		0
-#endif
 /* #define cpu_has_vtag_icache	? */
 /* #define cpu_has_dc_aliases	? */
 /* #define cpu_has_ic_fills_f_dc ? */
diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h
index 12b70c2..f64e17f 100644
--- a/arch/mips/include/asm/mipsregs.h
+++ b/arch/mips/include/asm/mipsregs.h
@@ -623,6 +623,24 @@
 #ifndef __ASSEMBLY__
 
 /*
+ * Macros for handling the ISA mode bit for microMIPS.
+ */
+#define get_isa16_mode(x)		((x) & 0x1)
+#define msk_isa16_mode(x)		((x) & ~0x1)
+#define set_isa16_mode(x)		do { (x) |= 0x1; } while(0)
+
+/*
+ * microMIPS instructions can be 16-bit or 32-bit in length. This
+ * returns a 1 if the instruction is 16-bit and a 0 if 32-bit.
+ */
+static inline int mm_insn_16bit(u16 insn)
+{
+	u16 opcode = (insn >> 10) & 0x7;
+
+	return (opcode >= 1 && opcode <= 3) ? 1 : 0;
+}
+
+/*
  * Functions to access the R10000 performance counters.	 These are basically
  * mfc0 and mtc0 instructions from and to coprocessor register with a 5-bit
  * performance counter number encoded into bits 1 ... 5 of the instruction.
@@ -1166,7 +1184,10 @@ do {									\
 	unsigned int __dspctl;						\
 									\
 	__asm__ __volatile__(						\
+	"	.set push					\n"	\
+	"	.set dsp					\n"	\
 	"	rddsp	%0, %x1					\n"	\
+	"	.set pop					\n"	\
 	: "=r" (__dspctl)						\
 	: "i" (mask));							\
 	__dspctl;							\
@@ -1175,30 +1196,198 @@ do {									\
 #define wrdsp(val, mask)						\
 do {									\
 	__asm__ __volatile__(						\
+	"	.set push					\n"	\
+	"	.set dsp					\n"	\
 	"	wrdsp	%0, %x1					\n"	\
+	"	.set pop					\n"	\
 	:								\
 	: "r" (val), "i" (mask));					\
 } while (0)
 
-#define mflo0() ({ long mflo0; __asm__("mflo %0, $ac0" : "=r" (mflo0)); mflo0;})
-#define mflo1() ({ long mflo1; __asm__("mflo %0, $ac1" : "=r" (mflo1)); mflo1;})
-#define mflo2() ({ long mflo2; __asm__("mflo %0, $ac2" : "=r" (mflo2)); mflo2;})
-#define mflo3() ({ long mflo3; __asm__("mflo %0, $ac3" : "=r" (mflo3)); mflo3;})
-
-#define mfhi0() ({ long mfhi0; __asm__("mfhi %0, $ac0" : "=r" (mfhi0)); mfhi0;})
-#define mfhi1() ({ long mfhi1; __asm__("mfhi %0, $ac1" : "=r" (mfhi1)); mfhi1;})
-#define mfhi2() ({ long mfhi2; __asm__("mfhi %0, $ac2" : "=r" (mfhi2)); mfhi2;})
-#define mfhi3() ({ long mfhi3; __asm__("mfhi %0, $ac3" : "=r" (mfhi3)); mfhi3;})
-
-#define mtlo0(x) __asm__("mtlo %0, $ac0" ::"r" (x))
-#define mtlo1(x) __asm__("mtlo %0, $ac1" ::"r" (x))
-#define mtlo2(x) __asm__("mtlo %0, $ac2" ::"r" (x))
-#define mtlo3(x) __asm__("mtlo %0, $ac3" ::"r" (x))
-
-#define mthi0(x) __asm__("mthi %0, $ac0" ::"r" (x))
-#define mthi1(x) __asm__("mthi %0, $ac1" ::"r" (x))
-#define mthi2(x) __asm__("mthi %0, $ac2" ::"r" (x))
-#define mthi3(x) __asm__("mthi %0, $ac3" ::"r" (x))
+#define mflo0()								\
+({									\
+	long mflo0;							\
+	__asm__(							\
+	"	.set push					\n"	\
+	"	.set dsp					\n"	\
+	"	mflo %0, $ac0					\n"	\
+	"	.set pop					\n" 	\
+	: "=r" (mflo0)); 						\
+	mflo0;								\
+})
+
+#define mflo1()								\
+({									\
+	long mflo1;							\
+	__asm__(							\
+	"	.set push					\n"	\
+	"	.set dsp					\n"	\
+	"	mflo %0, $ac1					\n"	\
+	"	.set pop					\n" 	\
+	: "=r" (mflo1)); 						\
+	mflo1;								\
+})
+
+#define mflo2()								\
+({									\
+	long mflo2;							\
+	__asm__(							\
+	"	.set push					\n"	\
+	"	.set dsp					\n"	\
+	"	mflo %0, $ac2					\n"	\
+	"	.set pop					\n" 	\
+	: "=r" (mflo2)); 						\
+	mflo2;								\
+})
+
+#define mflo3()								\
+({									\
+	long mflo3;							\
+	__asm__(							\
+	"	.set push					\n"	\
+	"	.set dsp					\n"	\
+	"	mflo %0, $ac3					\n"	\
+	"	.set pop					\n" 	\
+	: "=r" (mflo3)); 						\
+	mflo3;								\
+})
+
+#define mfhi0()								\
+({									\
+	long mfhi0;							\
+	__asm__(							\
+	"	.set push					\n"	\
+	"	.set dsp					\n"	\
+	"	mfhi %0, $ac0					\n"	\
+	"	.set pop					\n" 	\
+	: "=r" (mfhi0)); 						\
+	mfhi0;								\
+})
+
+#define mfhi1()								\
+({									\
+	long mfhi1;							\
+	__asm__(							\
+	"	.set push					\n"	\
+	"	.set dsp					\n"	\
+	"	mfhi %0, $ac1					\n"	\
+	"	.set pop					\n" 	\
+	: "=r" (mfhi1)); 						\
+	mfhi1;								\
+})
+
+#define mfhi2()								\
+({									\
+	long mfhi2;							\
+	__asm__(							\
+	"	.set push					\n"	\
+	"	.set dsp					\n"	\
+	"	mfhi %0, $ac2					\n"	\
+	"	.set pop					\n" 	\
+	: "=r" (mfhi2)); 						\
+	mfhi2;								\
+})
+
+#define mfhi3()								\
+({									\
+	long mfhi3;							\
+	__asm__(							\
+	"	.set push					\n"	\
+	"	.set dsp					\n"	\
+	"	mfhi %0, $ac3					\n"	\
+	"	.set pop					\n" 	\
+	: "=r" (mfhi3)); 						\
+	mfhi3;								\
+})
+
+
+#define mtlo0(x)							\
+({									\
+	__asm__(							\
+	"	.set push					\n"	\
+	"	.set dsp					\n"	\
+	"	mtlo %0, $ac0					\n"	\
+	"	.set pop					\n"	\
+	:								\
+	: "r" (x));							\
+})
+
+#define mtlo1(x)							\
+({									\
+	__asm__(							\
+	"	.set push					\n"	\
+	"	.set dsp					\n"	\
+	"	mtlo %0, $ac1					\n"	\
+	"	.set pop					\n"	\
+	:								\
+	: "r" (x));							\
+})
+
+#define mtlo2(x)							\
+({									\
+	__asm__(							\
+	"	.set push					\n"	\
+	"	.set dsp					\n"	\
+	"	mtlo %0, $ac2					\n"	\
+	"	.set pop					\n"	\
+	:								\
+	: "r" (x));							\
+})
+
+#define mtlo3(x)							\
+({									\
+	__asm__(							\
+	"	.set push					\n"	\
+	"	.set dsp					\n"	\
+	"	mtlo %0, $ac3					\n"	\
+	"	.set pop					\n"	\
+	:								\
+	: "r" (x));							\
+})
+
+#define mthi0(x)							\
+({									\
+	__asm__(							\
+	"	.set push					\n"	\
+	"	.set dsp					\n"	\
+	"	mthi %0, $ac0					\n"	\
+	"	.set pop					\n"	\
+	:								\
+	: "r" (x));							\
+})
+
+#define mthi1(x)							\
+({									\
+	__asm__(							\
+	"	.set push					\n"	\
+	"	.set dsp					\n"	\
+	"	mthi %0, $ac1					\n"	\
+	"	.set pop					\n"	\
+	:								\
+	: "r" (x));							\
+})
+
+#define mthi2(x)							\
+({									\
+	__asm__(							\
+	"	.set push					\n"	\
+	"	.set dsp					\n"	\
+	"	mthi %0, $ac2					\n"	\
+	"	.set pop					\n"	\
+	:								\
+	: "r" (x));							\
+})
+
+#define mthi3(x)							\
+({									\
+	__asm__(							\
+	"	.set push					\n"	\
+	"	.set dsp					\n"	\
+	"	mthi %0, $ac3					\n"	\
+	"	.set pop					\n"	\
+	:								\
+	: "r" (x));							\
+})
 
 #else
 
diff --git a/arch/mips/include/asm/mmu_context.h b/arch/mips/include/asm/mmu_context.h
index e81d719..c42562d 100644
--- a/arch/mips/include/asm/mmu_context.h
+++ b/arch/mips/include/asm/mmu_context.h
@@ -106,15 +106,21 @@ static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
 static inline void
 get_new_mmu_context(struct mm_struct *mm, unsigned long cpu)
 {
+	extern void kvm_local_flush_tlb_all(void);
 	unsigned long asid = asid_cache(cpu);
 
 	if (! ((asid += ASID_INC) & ASID_MASK) ) {
 		if (cpu_has_vtag_icache)
 			flush_icache_all();
+#ifdef CONFIG_VIRTUALIZATION
+		kvm_local_flush_tlb_all();      /* start new asid cycle */
+#else
 		local_flush_tlb_all();	/* start new asid cycle */
+#endif
 		if (!asid)		/* fix version if needed */
 			asid = ASID_FIRST_VERSION;
 	}
+
 	cpu_context(cpu, mm) = asid_cache(cpu) = asid;
 }
 
diff --git a/arch/mips/include/asm/processor.h b/arch/mips/include/asm/processor.h
index 2a5fa7a..71686c8 100644
--- a/arch/mips/include/asm/processor.h
+++ b/arch/mips/include/asm/processor.h
@@ -44,11 +44,16 @@ extern unsigned int vced_count, vcei_count;
 #define SPECIAL_PAGES_SIZE PAGE_SIZE
 
 #ifdef CONFIG_32BIT
+#ifdef CONFIG_KVM_GUEST
+/* User space process size is limited to 1GB in KVM Guest Mode */
+#define TASK_SIZE	0x3fff8000UL
+#else
 /*
  * User space process size: 2GB. This is hardcoded into a few places,
  * so don't change it unless you know what you are doing.
  */
 #define TASK_SIZE	0x7fff8000UL
+#endif
 
 #ifdef __KERNEL__
 #define STACK_TOP_MAX	TASK_SIZE
diff --git a/arch/mips/include/asm/signal.h b/arch/mips/include/asm/signal.h
index 197f636..8efe5a9 100644
--- a/arch/mips/include/asm/signal.h
+++ b/arch/mips/include/asm/signal.h
@@ -21,6 +21,6 @@
 #include <asm/sigcontext.h>
 #include <asm/siginfo.h>
 
-#define __ARCH_HAS_ODD_SIGACTION
+#define __ARCH_HAS_IRIX_SIGACTION
 
 #endif /* _ASM_SIGNAL_H */
diff --git a/arch/mips/include/asm/uaccess.h b/arch/mips/include/asm/uaccess.h
index bd87e36..b46caab 100644
--- a/arch/mips/include/asm/uaccess.h
+++ b/arch/mips/include/asm/uaccess.h
@@ -23,7 +23,11 @@
  */
 #ifdef CONFIG_32BIT
 
-#define __UA_LIMIT	0x80000000UL
+#ifdef CONFIG_KVM_GUEST
+#define __UA_LIMIT 0x40000000UL
+#else
+#define __UA_LIMIT 0x80000000UL
+#endif
 
 #define __UA_ADDR	".word"
 #define __UA_LA		"la"
@@ -55,8 +59,13 @@ extern u64 __ua_limit;
  * address in this range it's the process's problem, not ours :-)
  */
 
+#ifdef CONFIG_KVM_GUEST
+#define KERNEL_DS	((mm_segment_t) { 0x80000000UL })
+#define USER_DS		((mm_segment_t) { 0xC0000000UL })
+#else
 #define KERNEL_DS	((mm_segment_t) { 0UL })
 #define USER_DS		((mm_segment_t) { __UA_LIMIT })
+#endif
 
 #define VERIFY_READ    0
 #define VERIFY_WRITE   1
diff --git a/arch/mips/include/asm/uasm.h b/arch/mips/include/asm/uasm.h
index 058e941..f924b87 100644
--- a/arch/mips/include/asm/uasm.h
+++ b/arch/mips/include/asm/uasm.h
@@ -6,7 +6,7 @@
  * Copyright (C) 2004, 2005, 2006, 2008	 Thiemo Seufer
  * Copyright (C) 2005  Maciej W. Rozycki
  * Copyright (C) 2006  Ralf Baechle (ralf@linux-mips.org)
- * Copyright (C) 2012  MIPS Technologies, Inc.
+ * Copyright (C) 2012, 2013  MIPS Technologies, Inc.  All rights reserved.
  */
 
 #include <linux/types.h>
@@ -22,44 +22,61 @@
 #define UASM_EXPORT_SYMBOL(sym)
 #endif
 
+#define _UASM_ISA_CLASSIC	0
+#define _UASM_ISA_MICROMIPS	1
+
+#ifndef UASM_ISA
+#define UASM_ISA	_UASM_ISA_CLASSIC
+#endif
+
+#if (UASM_ISA == _UASM_ISA_CLASSIC)
+#define ISAOPC(op)	uasm_i##op
+#define ISAFUNC(x)	x
+#elif (UASM_ISA == _UASM_ISA_MICROMIPS)
+#define ISAOPC(op)	MM_uasm_i##op
+#define ISAFUNC(x)	MM_##x
+#else
+#error Unsupported micro-assembler ISA!!!
+#endif
+
 #define Ip_u1u2u3(op)							\
 void __uasminit								\
-uasm_i##op(u32 **buf, unsigned int a, unsigned int b, unsigned int c)
+ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, unsigned int c)
 
 #define Ip_u2u1u3(op)							\
 void __uasminit								\
-uasm_i##op(u32 **buf, unsigned int a, unsigned int b, unsigned int c)
+ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, unsigned int c)
 
 #define Ip_u3u1u2(op)							\
 void __uasminit								\
-uasm_i##op(u32 **buf, unsigned int a, unsigned int b, unsigned int c)
+ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, unsigned int c)
 
 #define Ip_u1u2s3(op)							\
 void __uasminit								\
-uasm_i##op(u32 **buf, unsigned int a, unsigned int b, signed int c)
+ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, signed int c)
 
 #define Ip_u2s3u1(op)							\
 void __uasminit								\
-uasm_i##op(u32 **buf, unsigned int a, signed int b, unsigned int c)
+ISAOPC(op)(u32 **buf, unsigned int a, signed int b, unsigned int c)
 
 #define Ip_u2u1s3(op)							\
 void __uasminit								\
-uasm_i##op(u32 **buf, unsigned int a, unsigned int b, signed int c)
+ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, signed int c)
 
 #define Ip_u2u1msbu3(op)						\
 void __uasminit								\
-uasm_i##op(u32 **buf, unsigned int a, unsigned int b, unsigned int c,	\
+ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, unsigned int c,	\
 	   unsigned int d)
 
 #define Ip_u1u2(op)							\
-void __uasminit uasm_i##op(u32 **buf, unsigned int a, unsigned int b)
+void __uasminit ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b)
 
 #define Ip_u1s2(op)							\
-void __uasminit uasm_i##op(u32 **buf, unsigned int a, signed int b)
+void __uasminit ISAOPC(op)(u32 **buf, unsigned int a, signed int b)
 
-#define Ip_u1(op) void __uasminit uasm_i##op(u32 **buf, unsigned int a)
+#define Ip_u1(op) void __uasminit ISAOPC(op)(u32 **buf, unsigned int a)
 
-#define Ip_0(op) void __uasminit uasm_i##op(u32 **buf)
+#define Ip_0(op) void __uasminit ISAOPC(op)(u32 **buf)
 
 Ip_u2u1s3(_addiu);
 Ip_u3u1u2(_addu);
@@ -132,14 +149,15 @@ struct uasm_label {
 	int lab;
 };
 
-void __uasminit uasm_build_label(struct uasm_label **lab, u32 *addr, int lid);
+void __uasminit ISAFUNC(uasm_build_label)(struct uasm_label **lab, u32 *addr,
+			int lid);
 #ifdef CONFIG_64BIT
-int uasm_in_compat_space_p(long addr);
+int ISAFUNC(uasm_in_compat_space_p)(long addr);
 #endif
-int uasm_rel_hi(long val);
-int uasm_rel_lo(long val);
-void UASM_i_LA_mostly(u32 **buf, unsigned int rs, long addr);
-void UASM_i_LA(u32 **buf, unsigned int rs, long addr);
+int ISAFUNC(uasm_rel_hi)(long val);
+int ISAFUNC(uasm_rel_lo)(long val);
+void ISAFUNC(UASM_i_LA_mostly)(u32 **buf, unsigned int rs, long addr);
+void ISAFUNC(UASM_i_LA)(u32 **buf, unsigned int rs, long addr);
 
 #define UASM_L_LA(lb)							\
 static inline void __uasminit uasm_l##lb(struct uasm_label **lab, u32 *addr) \
@@ -196,27 +214,27 @@ static inline void uasm_i_drotr_safe(u32 **p, unsigned int a1,
 				     unsigned int a2, unsigned int a3)
 {
 	if (a3 < 32)
-		uasm_i_drotr(p, a1, a2, a3);
+		ISAOPC(_drotr)(p, a1, a2, a3);
 	else
-		uasm_i_drotr32(p, a1, a2, a3 - 32);
+		ISAOPC(_drotr32)(p, a1, a2, a3 - 32);
 }
 
 static inline void uasm_i_dsll_safe(u32 **p, unsigned int a1,
 				    unsigned int a2, unsigned int a3)
 {
 	if (a3 < 32)
-		uasm_i_dsll(p, a1, a2, a3);
+		ISAOPC(_dsll)(p, a1, a2, a3);
 	else
-		uasm_i_dsll32(p, a1, a2, a3 - 32);
+		ISAOPC(_dsll32)(p, a1, a2, a3 - 32);
 }
 
 static inline void uasm_i_dsrl_safe(u32 **p, unsigned int a1,
 				    unsigned int a2, unsigned int a3)
 {
 	if (a3 < 32)
-		uasm_i_dsrl(p, a1, a2, a3);
+		ISAOPC(_dsrl)(p, a1, a2, a3);
 	else
-		uasm_i_dsrl32(p, a1, a2, a3 - 32);
+		ISAOPC(_dsrl32)(p, a1, a2, a3 - 32);
 }
 
 /* Handle relocations. */
diff --git a/arch/mips/include/asm/unistd.h b/arch/mips/include/asm/unistd.h
index 64f661e..63c9c88 100644
--- a/arch/mips/include/asm/unistd.h
+++ b/arch/mips/include/asm/unistd.h
@@ -63,12 +63,4 @@
 
 #endif /* !__ASSEMBLY__ */
 
-/*
- * "Conditional" syscalls
- *
- * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
- * but it doesn't work on all toolchains, so we just do it by hand
- */
-#define cond_syscall(x) asm(".weak\t" #x "\n" #x "\t=\tsys_ni_syscall")
-
 #endif /* _ASM_UNISTD_H */
diff --git a/arch/mips/include/uapi/asm/inst.h b/arch/mips/include/uapi/asm/inst.h
index 4d07881..4715337 100644
--- a/arch/mips/include/uapi/asm/inst.h
+++ b/arch/mips/include/uapi/asm/inst.h
@@ -7,6 +7,7 @@
  *
  * Copyright (C) 1996, 2000 by Ralf Baechle
  * Copyright (C) 2006 by Thiemo Seufer
+ * Copyright (C) 2012 MIPS Technologies, Inc.  All rights reserved.
  */
 #ifndef _UAPI_ASM_INST_H
 #define _UAPI_ASM_INST_H
@@ -193,6 +194,236 @@ enum lx_func {
 };
 
 /*
+ * (microMIPS) Major opcodes.
+ */
+enum mm_major_op {
+	mm_pool32a_op, mm_pool16a_op, mm_lbu16_op, mm_move16_op,
+	mm_addi32_op, mm_lbu32_op, mm_sb32_op, mm_lb32_op,
+	mm_pool32b_op, mm_pool16b_op, mm_lhu16_op, mm_andi16_op,
+	mm_addiu32_op, mm_lhu32_op, mm_sh32_op, mm_lh32_op,
+	mm_pool32i_op, mm_pool16c_op, mm_lwsp16_op, mm_pool16d_op,
+	mm_ori32_op, mm_pool32f_op, mm_reserved1_op, mm_reserved2_op,
+	mm_pool32c_op, mm_lwgp16_op, mm_lw16_op, mm_pool16e_op,
+	mm_xori32_op, mm_jals32_op, mm_addiupc_op, mm_reserved3_op,
+	mm_reserved4_op, mm_pool16f_op, mm_sb16_op, mm_beqz16_op,
+	mm_slti32_op, mm_beq32_op, mm_swc132_op, mm_lwc132_op,
+	mm_reserved5_op, mm_reserved6_op, mm_sh16_op, mm_bnez16_op,
+	mm_sltiu32_op, mm_bne32_op, mm_sdc132_op, mm_ldc132_op,
+	mm_reserved7_op, mm_reserved8_op, mm_swsp16_op, mm_b16_op,
+	mm_andi32_op, mm_j32_op, mm_sd32_op, mm_ld32_op,
+	mm_reserved11_op, mm_reserved12_op, mm_sw16_op, mm_li16_op,
+	mm_jalx32_op, mm_jal32_op, mm_sw32_op, mm_lw32_op,
+};
+
+/*
+ * (microMIPS) POOL32I minor opcodes.
+ */
+enum mm_32i_minor_op {
+	mm_bltz_op, mm_bltzal_op, mm_bgez_op, mm_bgezal_op,
+	mm_blez_op, mm_bnezc_op, mm_bgtz_op, mm_beqzc_op,
+	mm_tlti_op, mm_tgei_op, mm_tltiu_op, mm_tgeiu_op,
+	mm_tnei_op, mm_lui_op, mm_teqi_op, mm_reserved13_op,
+	mm_synci_op, mm_bltzals_op, mm_reserved14_op, mm_bgezals_op,
+	mm_bc2f_op, mm_bc2t_op, mm_reserved15_op, mm_reserved16_op,
+	mm_reserved17_op, mm_reserved18_op, mm_bposge64_op, mm_bposge32_op,
+	mm_bc1f_op, mm_bc1t_op, mm_reserved19_op, mm_reserved20_op,
+	mm_bc1any2f_op, mm_bc1any2t_op, mm_bc1any4f_op, mm_bc1any4t_op,
+};
+
+/*
+ * (microMIPS) POOL32A minor opcodes.
+ */
+enum mm_32a_minor_op {
+	mm_sll32_op = 0x000,
+	mm_ins_op = 0x00c,
+	mm_ext_op = 0x02c,
+	mm_pool32axf_op = 0x03c,
+	mm_srl32_op = 0x040,
+	mm_sra_op = 0x080,
+	mm_rotr_op = 0x0c0,
+	mm_lwxs_op = 0x118,
+	mm_addu32_op = 0x150,
+	mm_subu32_op = 0x1d0,
+	mm_and_op = 0x250,
+	mm_or32_op = 0x290,
+	mm_xor32_op = 0x310,
+};
+
+/*
+ * (microMIPS) POOL32B functions.
+ */
+enum mm_32b_func {
+	mm_lwc2_func = 0x0,
+	mm_lwp_func = 0x1,
+	mm_ldc2_func = 0x2,
+	mm_ldp_func = 0x4,
+	mm_lwm32_func = 0x5,
+	mm_cache_func = 0x6,
+	mm_ldm_func = 0x7,
+	mm_swc2_func = 0x8,
+	mm_swp_func = 0x9,
+	mm_sdc2_func = 0xa,
+	mm_sdp_func = 0xc,
+	mm_swm32_func = 0xd,
+	mm_sdm_func = 0xf,
+};
+
+/*
+ * (microMIPS) POOL32C functions.
+ */
+enum mm_32c_func {
+	mm_pref_func = 0x2,
+	mm_ll_func = 0x3,
+	mm_swr_func = 0x9,
+	mm_sc_func = 0xb,
+	mm_lwu_func = 0xe,
+};
+
+/*
+ * (microMIPS) POOL32AXF minor opcodes.
+ */
+enum mm_32axf_minor_op {
+	mm_mfc0_op = 0x003,
+	mm_mtc0_op = 0x00b,
+	mm_tlbp_op = 0x00d,
+	mm_jalr_op = 0x03c,
+	mm_tlbr_op = 0x04d,
+	mm_jalrhb_op = 0x07c,
+	mm_tlbwi_op = 0x08d,
+	mm_tlbwr_op = 0x0cd,
+	mm_jalrs_op = 0x13c,
+	mm_jalrshb_op = 0x17c,
+	mm_syscall_op = 0x22d,
+	mm_eret_op = 0x3cd,
+};
+
+/*
+ * (microMIPS) POOL32F minor opcodes.
+ */
+enum mm_32f_minor_op {
+	mm_32f_00_op = 0x00,
+	mm_32f_01_op = 0x01,
+	mm_32f_02_op = 0x02,
+	mm_32f_10_op = 0x08,
+	mm_32f_11_op = 0x09,
+	mm_32f_12_op = 0x0a,
+	mm_32f_20_op = 0x10,
+	mm_32f_30_op = 0x18,
+	mm_32f_40_op = 0x20,
+	mm_32f_41_op = 0x21,
+	mm_32f_42_op = 0x22,
+	mm_32f_50_op = 0x28,
+	mm_32f_51_op = 0x29,
+	mm_32f_52_op = 0x2a,
+	mm_32f_60_op = 0x30,
+	mm_32f_70_op = 0x38,
+	mm_32f_73_op = 0x3b,
+	mm_32f_74_op = 0x3c,
+};
+
+/*
+ * (microMIPS) POOL32F secondary minor opcodes.
+ */
+enum mm_32f_10_minor_op {
+	mm_lwxc1_op = 0x1,
+	mm_swxc1_op,
+	mm_ldxc1_op,
+	mm_sdxc1_op,
+	mm_luxc1_op,
+	mm_suxc1_op,
+};
+
+enum mm_32f_func {
+	mm_lwxc1_func = 0x048,
+	mm_swxc1_func = 0x088,
+	mm_ldxc1_func = 0x0c8,
+	mm_sdxc1_func = 0x108,
+};
+
+/*
+ * (microMIPS) POOL32F secondary minor opcodes.
+ */
+enum mm_32f_40_minor_op {
+	mm_fmovf_op,
+	mm_fmovt_op,
+};
+
+/*
+ * (microMIPS) POOL32F secondary minor opcodes.
+ */
+enum mm_32f_60_minor_op {
+	mm_fadd_op,
+	mm_fsub_op,
+	mm_fmul_op,
+	mm_fdiv_op,
+};
+
+/*
+ * (microMIPS) POOL32F secondary minor opcodes.
+ */
+enum mm_32f_70_minor_op {
+	mm_fmovn_op,
+	mm_fmovz_op,
+};
+
+/*
+ * (microMIPS) POOL32FXF secondary minor opcodes for POOL32F.
+ */
+enum mm_32f_73_minor_op {
+	mm_fmov0_op = 0x01,
+	mm_fcvtl_op = 0x04,
+	mm_movf0_op = 0x05,
+	mm_frsqrt_op = 0x08,
+	mm_ffloorl_op = 0x0c,
+	mm_fabs0_op = 0x0d,
+	mm_fcvtw_op = 0x24,
+	mm_movt0_op = 0x25,
+	mm_fsqrt_op = 0x28,
+	mm_ffloorw_op = 0x2c,
+	mm_fneg0_op = 0x2d,
+	mm_cfc1_op = 0x40,
+	mm_frecip_op = 0x48,
+	mm_fceill_op = 0x4c,
+	mm_fcvtd0_op = 0x4d,
+	mm_ctc1_op = 0x60,
+	mm_fceilw_op = 0x6c,
+	mm_fcvts0_op = 0x6d,
+	mm_mfc1_op = 0x80,
+	mm_fmov1_op = 0x81,
+	mm_movf1_op = 0x85,
+	mm_ftruncl_op = 0x8c,
+	mm_fabs1_op = 0x8d,
+	mm_mtc1_op = 0xa0,
+	mm_movt1_op = 0xa5,
+	mm_ftruncw_op = 0xac,
+	mm_fneg1_op = 0xad,
+	mm_froundl_op = 0xcc,
+	mm_fcvtd1_op = 0xcd,
+	mm_froundw_op = 0xec,
+	mm_fcvts1_op = 0xed,
+};
+
+/*
+ * (microMIPS) POOL16C minor opcodes.
+ */
+enum mm_16c_minor_op {
+	mm_lwm16_op = 0x04,
+	mm_swm16_op = 0x05,
+	mm_jr16_op = 0x18,
+	mm_jrc_op = 0x1a,
+	mm_jalr16_op = 0x1c,
+	mm_jalrs16_op = 0x1e,
+};
+
+/*
+ * (microMIPS) POOL16D minor opcodes.
+ */
+enum mm_16d_minor_op {
+	mm_addius5_func,
+	mm_addiusp_func,
+};
+
+/*
  * Damn ...  bitfields depend from byteorder :-(
  */
 #ifdef __MIPSEB__
@@ -311,6 +542,204 @@ struct v_format {				/* MDMX vector format */
 	;)))))))
 };
 
+/*
+ * microMIPS instruction formats (32-bit length)
+ *
+ * NOTE:
+ *	Parenthesis denote whether the format is a microMIPS instruction or
+ *	if it is MIPS32 instruction re-encoded for use in the microMIPS ASE.
+ */
+struct fb_format {		/* FPU branch format (MIPS32) */
+	BITFIELD_FIELD(unsigned int opcode : 6,
+	BITFIELD_FIELD(unsigned int bc : 5,
+	BITFIELD_FIELD(unsigned int cc : 3,
+	BITFIELD_FIELD(unsigned int flag : 2,
+	BITFIELD_FIELD(signed int simmediate : 16,
+	;)))))
+};
+
+struct fp0_format {		/* FPU multiply and add format (MIPS32) */
+	BITFIELD_FIELD(unsigned int opcode : 6,
+	BITFIELD_FIELD(unsigned int fmt : 5,
+	BITFIELD_FIELD(unsigned int ft : 5,
+	BITFIELD_FIELD(unsigned int fs : 5,
+	BITFIELD_FIELD(unsigned int fd : 5,
+	BITFIELD_FIELD(unsigned int func : 6,
+	;))))))
+};
+
+struct mm_fp0_format {		/* FPU multipy and add format (microMIPS) */
+	BITFIELD_FIELD(unsigned int opcode : 6,
+	BITFIELD_FIELD(unsigned int ft : 5,
+	BITFIELD_FIELD(unsigned int fs : 5,
+	BITFIELD_FIELD(unsigned int fd : 5,
+	BITFIELD_FIELD(unsigned int fmt : 3,
+	BITFIELD_FIELD(unsigned int op : 2,
+	BITFIELD_FIELD(unsigned int func : 6,
+	;)))))))
+};
+
+struct fp1_format {		/* FPU mfc1 and cfc1 format (MIPS32) */
+	BITFIELD_FIELD(unsigned int opcode : 6,
+	BITFIELD_FIELD(unsigned int op : 5,
+	BITFIELD_FIELD(unsigned int rt : 5,
+	BITFIELD_FIELD(unsigned int fs : 5,
+	BITFIELD_FIELD(unsigned int fd : 5,
+	BITFIELD_FIELD(unsigned int func : 6,
+	;))))))
+};
+
+struct mm_fp1_format {		/* FPU mfc1 and cfc1 format (microMIPS) */
+	BITFIELD_FIELD(unsigned int opcode : 6,
+	BITFIELD_FIELD(unsigned int rt : 5,
+	BITFIELD_FIELD(unsigned int fs : 5,
+	BITFIELD_FIELD(unsigned int fmt : 2,
+	BITFIELD_FIELD(unsigned int op : 8,
+	BITFIELD_FIELD(unsigned int func : 6,
+	;))))))
+};
+
+struct mm_fp2_format {		/* FPU movt and movf format (microMIPS) */
+	BITFIELD_FIELD(unsigned int opcode : 6,
+	BITFIELD_FIELD(unsigned int fd : 5,
+	BITFIELD_FIELD(unsigned int fs : 5,
+	BITFIELD_FIELD(unsigned int cc : 3,
+	BITFIELD_FIELD(unsigned int zero : 2,
+	BITFIELD_FIELD(unsigned int fmt : 2,
+	BITFIELD_FIELD(unsigned int op : 3,
+	BITFIELD_FIELD(unsigned int func : 6,
+	;))))))))
+};
+
+struct mm_fp3_format {		/* FPU abs and neg format (microMIPS) */
+	BITFIELD_FIELD(unsigned int opcode : 6,
+	BITFIELD_FIELD(unsigned int rt : 5,
+	BITFIELD_FIELD(unsigned int fs : 5,
+	BITFIELD_FIELD(unsigned int fmt : 3,
+	BITFIELD_FIELD(unsigned int op : 7,
+	BITFIELD_FIELD(unsigned int func : 6,
+	;))))))
+};
+
+struct mm_fp4_format {		/* FPU c.cond format (microMIPS) */
+	BITFIELD_FIELD(unsigned int opcode : 6,
+	BITFIELD_FIELD(unsigned int rt : 5,
+	BITFIELD_FIELD(unsigned int fs : 5,
+	BITFIELD_FIELD(unsigned int cc : 3,
+	BITFIELD_FIELD(unsigned int fmt : 3,
+	BITFIELD_FIELD(unsigned int cond : 4,
+	BITFIELD_FIELD(unsigned int func : 6,
+	;)))))))
+};
+
+struct mm_fp5_format {		/* FPU lwxc1 and swxc1 format (microMIPS) */
+	BITFIELD_FIELD(unsigned int opcode : 6,
+	BITFIELD_FIELD(unsigned int index : 5,
+	BITFIELD_FIELD(unsigned int base : 5,
+	BITFIELD_FIELD(unsigned int fd : 5,
+	BITFIELD_FIELD(unsigned int op : 5,
+	BITFIELD_FIELD(unsigned int func : 6,
+	;))))))
+};
+
+struct fp6_format {		/* FPU madd and msub format (MIPS IV) */
+	BITFIELD_FIELD(unsigned int opcode : 6,
+	BITFIELD_FIELD(unsigned int fr : 5,
+	BITFIELD_FIELD(unsigned int ft : 5,
+	BITFIELD_FIELD(unsigned int fs : 5,
+	BITFIELD_FIELD(unsigned int fd : 5,
+	BITFIELD_FIELD(unsigned int func : 6,
+	;))))))
+};
+
+struct mm_fp6_format {		/* FPU madd and msub format (microMIPS) */
+	BITFIELD_FIELD(unsigned int opcode : 6,
+	BITFIELD_FIELD(unsigned int ft : 5,
+	BITFIELD_FIELD(unsigned int fs : 5,
+	BITFIELD_FIELD(unsigned int fd : 5,
+	BITFIELD_FIELD(unsigned int fr : 5,
+	BITFIELD_FIELD(unsigned int func : 6,
+	;))))))
+};
+
+struct mm_i_format {		/* Immediate format (microMIPS) */
+	BITFIELD_FIELD(unsigned int opcode : 6,
+	BITFIELD_FIELD(unsigned int rt : 5,
+	BITFIELD_FIELD(unsigned int rs : 5,
+	BITFIELD_FIELD(signed int simmediate : 16,
+	;))))
+};
+
+struct mm_m_format {		/* Multi-word load/store format (microMIPS) */
+	BITFIELD_FIELD(unsigned int opcode : 6,
+	BITFIELD_FIELD(unsigned int rd : 5,
+	BITFIELD_FIELD(unsigned int base : 5,
+	BITFIELD_FIELD(unsigned int func : 4,
+	BITFIELD_FIELD(signed int simmediate : 12,
+	;)))))
+};
+
+struct mm_x_format {		/* Scaled indexed load format (microMIPS) */
+	BITFIELD_FIELD(unsigned int opcode : 6,
+	BITFIELD_FIELD(unsigned int index : 5,
+	BITFIELD_FIELD(unsigned int base : 5,
+	BITFIELD_FIELD(unsigned int rd : 5,
+	BITFIELD_FIELD(unsigned int func : 11,
+	;)))))
+};
+
+/*
+ * microMIPS instruction formats (16-bit length)
+ */
+struct mm_b0_format {		/* Unconditional branch format (microMIPS) */
+	BITFIELD_FIELD(unsigned int opcode : 6,
+	BITFIELD_FIELD(signed int simmediate : 10,
+	BITFIELD_FIELD(unsigned int : 16, /* Ignored */
+	;)))
+};
+
+struct mm_b1_format {		/* Conditional branch format (microMIPS) */
+	BITFIELD_FIELD(unsigned int opcode : 6,
+	BITFIELD_FIELD(unsigned int rs : 3,
+	BITFIELD_FIELD(signed int simmediate : 7,
+	BITFIELD_FIELD(unsigned int : 16, /* Ignored */
+	;))))
+};
+
+struct mm16_m_format {		/* Multi-word load/store format */
+	BITFIELD_FIELD(unsigned int opcode : 6,
+	BITFIELD_FIELD(unsigned int func : 4,
+	BITFIELD_FIELD(unsigned int rlist : 2,
+	BITFIELD_FIELD(unsigned int imm : 4,
+	BITFIELD_FIELD(unsigned int : 16, /* Ignored */
+	;)))))
+};
+
+struct mm16_rb_format {		/* Signed immediate format */
+	BITFIELD_FIELD(unsigned int opcode : 6,
+	BITFIELD_FIELD(unsigned int rt : 3,
+	BITFIELD_FIELD(unsigned int base : 3,
+	BITFIELD_FIELD(signed int simmediate : 4,
+	BITFIELD_FIELD(unsigned int : 16, /* Ignored */
+	;)))))
+};
+
+struct mm16_r3_format {		/* Load from global pointer format */
+	BITFIELD_FIELD(unsigned int opcode : 6,
+	BITFIELD_FIELD(unsigned int rt : 3,
+	BITFIELD_FIELD(signed int simmediate : 7,
+	BITFIELD_FIELD(unsigned int : 16, /* Ignored */
+	;))))
+};
+
+struct mm16_r5_format {		/* Load/store from stack pointer format */
+	BITFIELD_FIELD(unsigned int opcode : 6,
+	BITFIELD_FIELD(unsigned int rt : 5,
+	BITFIELD_FIELD(signed int simmediate : 5,
+	BITFIELD_FIELD(unsigned int : 16, /* Ignored */
+	;))))
+};
+
 union mips_instruction {
 	unsigned int word;
 	unsigned short halfword[2];
@@ -326,6 +755,26 @@ union mips_instruction {
 	struct b_format b_format;
 	struct ps_format ps_format;
 	struct v_format v_format;
+	struct fb_format fb_format;
+	struct fp0_format fp0_format;
+	struct mm_fp0_format mm_fp0_format;
+	struct fp1_format fp1_format;
+	struct mm_fp1_format mm_fp1_format;
+	struct mm_fp2_format mm_fp2_format;
+	struct mm_fp3_format mm_fp3_format;
+	struct mm_fp4_format mm_fp4_format;
+	struct mm_fp5_format mm_fp5_format;
+	struct fp6_format fp6_format;
+	struct mm_fp6_format mm_fp6_format;
+	struct mm_i_format mm_i_format;
+	struct mm_m_format mm_m_format;
+	struct mm_x_format mm_x_format;
+	struct mm_b0_format mm_b0_format;
+	struct mm_b1_format mm_b1_format;
+	struct mm16_m_format mm16_m_format ;
+	struct mm16_rb_format mm16_rb_format;
+	struct mm16_r3_format mm16_r3_format;
+	struct mm16_r5_format mm16_r5_format;
 };
 
 #endif /* _UAPI_ASM_INST_H */
diff --git a/arch/mips/include/uapi/asm/socket.h b/arch/mips/include/uapi/asm/socket.h
index 47132f4..3b21150 100644
--- a/arch/mips/include/uapi/asm/socket.h
+++ b/arch/mips/include/uapi/asm/socket.h
@@ -90,4 +90,6 @@
 
 #define SO_LOCK_FILTER		44
 
+#define SO_SELECT_ERR_QUEUE	45
+
 #endif /* _UAPI_ASM_SOCKET_H */
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index f81d98f..de75fb5 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -100,29 +100,16 @@ obj-$(CONFIG_HW_PERF_EVENTS)	+= perf_event_mipsxx.o
 obj-$(CONFIG_JUMP_LABEL)	+= jump_label.o
 
 #
-# DSP ASE supported for MIPS32 or MIPS64 Release 2 cores only. It is safe
-# to enable DSP assembler support here even if the MIPS Release 2 CPU we
-# are targetting does not support DSP because all code-paths making use of
-# it properly check that the running CPU *actually does* support these
-# instructions.
+# DSP ASE supported for MIPS32 or MIPS64 Release 2 cores only. It is not
+# safe to unconditionnaly use the assembler -mdsp / -mdspr2 switches
+# here because the compiler may use DSP ASE instructions (such as lwx) in
+# code paths where we cannot check that the CPU we are running on supports it.
+# Proper abstraction using HAVE_AS_DSP and macros is done in
+# arch/mips/include/asm/mipsregs.h.
 #
 ifeq ($(CONFIG_CPU_MIPSR2), y)
 CFLAGS_DSP 			= -DHAVE_AS_DSP
 
-#
-# Check if assembler supports DSP ASE
-#
-ifeq ($(call cc-option-yn,-mdsp), y)
-CFLAGS_DSP			+= -mdsp
-endif
-
-#
-# Check if assembler supports DSP ASE Rev2
-#
-ifeq ($(call cc-option-yn,-mdspr2), y)
-CFLAGS_DSP			+= -mdspr2
-endif
-
 CFLAGS_signal.o			= $(CFLAGS_DSP)
 CFLAGS_signal32.o		= $(CFLAGS_DSP)
 CFLAGS_process.o		= $(CFLAGS_DSP)
diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c
index 50285b2..0845091 100644
--- a/arch/mips/kernel/asm-offsets.c
+++ b/arch/mips/kernel/asm-offsets.c
@@ -17,6 +17,8 @@
 #include <asm/ptrace.h>
 #include <asm/processor.h>
 
+#include <linux/kvm_host.h>
+
 void output_ptreg_defines(void)
 {
 	COMMENT("MIPS pt_regs offsets.");
@@ -328,3 +330,67 @@ void output_pbe_defines(void)
 	BLANK();
 }
 #endif
+
+void output_kvm_defines(void)
+{
+	COMMENT(" KVM/MIPS Specfic offsets. ");
+	DEFINE(VCPU_ARCH_SIZE, sizeof(struct kvm_vcpu_arch));
+	OFFSET(VCPU_RUN, kvm_vcpu, run);
+	OFFSET(VCPU_HOST_ARCH, kvm_vcpu, arch);
+
+	OFFSET(VCPU_HOST_EBASE, kvm_vcpu_arch, host_ebase);
+	OFFSET(VCPU_GUEST_EBASE, kvm_vcpu_arch, guest_ebase);
+
+	OFFSET(VCPU_HOST_STACK, kvm_vcpu_arch, host_stack);
+	OFFSET(VCPU_HOST_GP, kvm_vcpu_arch, host_gp);
+
+	OFFSET(VCPU_HOST_CP0_BADVADDR, kvm_vcpu_arch, host_cp0_badvaddr);
+	OFFSET(VCPU_HOST_CP0_CAUSE, kvm_vcpu_arch, host_cp0_cause);
+	OFFSET(VCPU_HOST_EPC, kvm_vcpu_arch, host_cp0_epc);
+	OFFSET(VCPU_HOST_ENTRYHI, kvm_vcpu_arch, host_cp0_entryhi);
+
+	OFFSET(VCPU_GUEST_INST, kvm_vcpu_arch, guest_inst);
+
+	OFFSET(VCPU_R0, kvm_vcpu_arch, gprs[0]);
+	OFFSET(VCPU_R1, kvm_vcpu_arch, gprs[1]);
+	OFFSET(VCPU_R2, kvm_vcpu_arch, gprs[2]);
+	OFFSET(VCPU_R3, kvm_vcpu_arch, gprs[3]);
+	OFFSET(VCPU_R4, kvm_vcpu_arch, gprs[4]);
+	OFFSET(VCPU_R5, kvm_vcpu_arch, gprs[5]);
+	OFFSET(VCPU_R6, kvm_vcpu_arch, gprs[6]);
+	OFFSET(VCPU_R7, kvm_vcpu_arch, gprs[7]);
+	OFFSET(VCPU_R8, kvm_vcpu_arch, gprs[8]);
+	OFFSET(VCPU_R9, kvm_vcpu_arch, gprs[9]);
+	OFFSET(VCPU_R10, kvm_vcpu_arch, gprs[10]);
+	OFFSET(VCPU_R11, kvm_vcpu_arch, gprs[11]);
+	OFFSET(VCPU_R12, kvm_vcpu_arch, gprs[12]);
+	OFFSET(VCPU_R13, kvm_vcpu_arch, gprs[13]);
+	OFFSET(VCPU_R14, kvm_vcpu_arch, gprs[14]);
+	OFFSET(VCPU_R15, kvm_vcpu_arch, gprs[15]);
+	OFFSET(VCPU_R16, kvm_vcpu_arch, gprs[16]);
+	OFFSET(VCPU_R17, kvm_vcpu_arch, gprs[17]);
+	OFFSET(VCPU_R18, kvm_vcpu_arch, gprs[18]);
+	OFFSET(VCPU_R19, kvm_vcpu_arch, gprs[19]);
+	OFFSET(VCPU_R20, kvm_vcpu_arch, gprs[20]);
+	OFFSET(VCPU_R21, kvm_vcpu_arch, gprs[21]);
+	OFFSET(VCPU_R22, kvm_vcpu_arch, gprs[22]);
+	OFFSET(VCPU_R23, kvm_vcpu_arch, gprs[23]);
+	OFFSET(VCPU_R24, kvm_vcpu_arch, gprs[24]);
+	OFFSET(VCPU_R25, kvm_vcpu_arch, gprs[25]);
+	OFFSET(VCPU_R26, kvm_vcpu_arch, gprs[26]);
+	OFFSET(VCPU_R27, kvm_vcpu_arch, gprs[27]);
+	OFFSET(VCPU_R28, kvm_vcpu_arch, gprs[28]);
+	OFFSET(VCPU_R29, kvm_vcpu_arch, gprs[29]);
+	OFFSET(VCPU_R30, kvm_vcpu_arch, gprs[30]);
+	OFFSET(VCPU_R31, kvm_vcpu_arch, gprs[31]);
+	OFFSET(VCPU_LO, kvm_vcpu_arch, lo);
+	OFFSET(VCPU_HI, kvm_vcpu_arch, hi);
+	OFFSET(VCPU_PC, kvm_vcpu_arch, pc);
+	OFFSET(VCPU_COP0, kvm_vcpu_arch, cop0);
+	OFFSET(VCPU_GUEST_KERNEL_ASID, kvm_vcpu_arch, guest_kernel_asid);
+	OFFSET(VCPU_GUEST_USER_ASID, kvm_vcpu_arch, guest_user_asid);
+
+	OFFSET(COP0_TLB_HI, mips_coproc, reg[MIPS_CP0_TLB_HI][0]);
+	OFFSET(COP0_STATUS, mips_coproc, reg[MIPS_CP0_STATUS][0]);
+	BLANK();
+}
diff --git a/arch/mips/kernel/binfmt_elfo32.c b/arch/mips/kernel/binfmt_elfo32.c
index 556a435..97c5a16 100644
--- a/arch/mips/kernel/binfmt_elfo32.c
+++ b/arch/mips/kernel/binfmt_elfo32.c
@@ -48,7 +48,11 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
 	__res;								\
 })
 
+#ifdef CONFIG_KVM_GUEST
+#define TASK32_SIZE		0x3fff8000UL
+#else
 #define TASK32_SIZE		0x7fff8000UL
+#endif
 #undef ELF_ET_DYN_BASE
 #define ELF_ET_DYN_BASE		(TASK32_SIZE / 3 * 2)
 
diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c
index 07b847d..fd75d71 100644
--- a/arch/mips/kernel/cevt-r4k.c
+++ b/arch/mips/kernel/cevt-r4k.c
@@ -118,6 +118,10 @@ int c0_compare_int_usable(void)
 	unsigned int delta;
 	unsigned int cnt;
 
+#ifdef CONFIG_KVM_GUEST
+    return 1;
+#endif
+
 	/*
 	 * IP7 already pending?	 Try to clear it by acking the timer.
 	 */
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 6bfccc2..d069a19 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -580,6 +580,9 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
 		c->tlbsize = 48;
 		break;
 	case PRID_IMP_VR41XX:
+		set_isa(c, MIPS_CPU_ISA_III);
+		c->options = R4K_OPTS;
+		c->tlbsize = 32;
 		switch (c->processor_id & 0xf0) {
 		case PRID_REV_VR4111:
 			c->cputype = CPU_VR4111;
@@ -604,6 +607,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
 				__cpu_name[cpu] = "NEC VR4131";
 			} else {
 				c->cputype = CPU_VR4133;
+				c->options |= MIPS_CPU_LLSC;
 				__cpu_name[cpu] = "NEC VR4133";
 			}
 			break;
@@ -613,9 +617,6 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
 			__cpu_name[cpu] = "NEC Vr41xx";
 			break;
 		}
-		set_isa(c, MIPS_CPU_ISA_III);
-		c->options = R4K_OPTS;
-		c->tlbsize = 32;
 		break;
 	case PRID_IMP_R4300:
 		c->cputype = CPU_R4300;
diff --git a/arch/mips/kernel/cpufreq/loongson2_cpufreq.c b/arch/mips/kernel/cpufreq/loongson2_cpufreq.c
index 3237c52..8488957 100644
--- a/arch/mips/kernel/cpufreq/loongson2_cpufreq.c
+++ b/arch/mips/kernel/cpufreq/loongson2_cpufreq.c
@@ -61,9 +61,6 @@ static int loongson2_cpufreq_target(struct cpufreq_policy *policy,
 	struct cpufreq_freqs freqs;
 	unsigned int freq;
 
-	if (!cpu_online(cpu))
-		return -ENODEV;
-
 	cpus_allowed = current->cpus_allowed;
 	set_cpus_allowed_ptr(current, cpumask_of(cpu));
 
@@ -80,7 +77,6 @@ static int loongson2_cpufreq_target(struct cpufreq_policy *policy,
 
 	pr_debug("cpufreq: requested frequency %u Hz\n", target_freq * 1000);
 
-	freqs.cpu = cpu;
 	freqs.old = loongson2_cpufreq_get(cpu);
 	freqs.new = freq;
 	freqs.flags = 0;
@@ -89,7 +85,7 @@ static int loongson2_cpufreq_target(struct cpufreq_policy *policy,
 		return 0;
 
 	/* notifiers */
-	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
 
 	set_cpus_allowed_ptr(current, &cpus_allowed);
 
@@ -97,7 +93,7 @@ static int loongson2_cpufreq_target(struct cpufreq_policy *policy,
 	clk_set_rate(cpuclk, freq);
 
 	/* notifiers */
-	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
 
 	pr_debug("cpufreq: set frequency %u kHz\n", freq);
 
@@ -110,9 +106,6 @@ static int loongson2_cpufreq_cpu_init(struct cpufreq_policy *policy)
 	unsigned long rate;
 	int ret;
 
-	if (!cpu_online(policy->cpu))
-		return -ENODEV;
-
 	cpuclk = clk_get(NULL, "cpu_clk");
 	if (IS_ERR(cpuclk)) {
 		printk(KERN_ERR "cpufreq: couldn't get CPU clk\n");
diff --git a/arch/mips/kernel/early_printk.c b/arch/mips/kernel/early_printk.c
index 9e6440e..505cb77 100644
--- a/arch/mips/kernel/early_printk.c
+++ b/arch/mips/kernel/early_printk.c
@@ -7,7 +7,9 @@
  * Copyright (C) 2007 MIPS Technologies, Inc.
  *   written by Ralf Baechle (ralf@linux-mips.org)
  */
+#include <linux/kernel.h>
 #include <linux/console.h>
+#include <linux/printk.h>
 #include <linux/init.h>
 
 #include <asm/setup.h>
@@ -24,20 +26,18 @@ static void early_console_write(struct console *con, const char *s, unsigned n)
 	}
 }
 
-static struct console early_console = {
+static struct console early_console_prom = {
 	.name	= "early",
 	.write	= early_console_write,
 	.flags	= CON_PRINTBUFFER | CON_BOOT,
 	.index	= -1
 };
 
-static int early_console_initialized __initdata;
-
 void __init setup_early_printk(void)
 {
-	if (early_console_initialized)
+	if (early_console)
 		return;
-	early_console_initialized = 1;
+	early_console = &early_console_prom;
 
-	register_console(&early_console);
+	register_console(&early_console_prom);
 }
diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c
index 8eeee1c..d1d576b 100644
--- a/arch/mips/kernel/linux32.c
+++ b/arch/mips/kernel/linux32.c
@@ -119,99 +119,6 @@ SYSCALL_DEFINE6(32_pwrite, unsigned int, fd, const char __user *, buf,
 	return sys_pwrite64(fd, buf, count, merge_64(a4, a5));
 }
 
-#ifdef CONFIG_SYSVIPC
-
-SYSCALL_DEFINE6(32_ipc, u32, call, long, first, long, second, long, third,
-	unsigned long, ptr, unsigned long, fifth)
-{
-	int version, err;
-
-	version = call >> 16; /* hack for backward compatibility */
-	call &= 0xffff;
-
-	switch (call) {
-	case SEMOP:
-		/* struct sembuf is the same on 32 and 64bit :)) */
-		err = sys_semtimedop(first, compat_ptr(ptr), second, NULL);
-		break;
-	case SEMTIMEDOP:
-		err = compat_sys_semtimedop(first, compat_ptr(ptr), second,
-					    compat_ptr(fifth));
-		break;
-	case SEMGET:
-		err = sys_semget(first, second, third);
-		break;
-	case SEMCTL:
-		err = compat_sys_semctl(first, second, third, compat_ptr(ptr));
-		break;
-	case MSGSND:
-		err = compat_sys_msgsnd(first, second, third, compat_ptr(ptr));
-		break;
-	case MSGRCV:
-		err = compat_sys_msgrcv(first, second, fifth, third,
-					version, compat_ptr(ptr));
-		break;
-	case MSGGET:
-		err = sys_msgget((key_t) first, second);
-		break;
-	case MSGCTL:
-		err = compat_sys_msgctl(first, second, compat_ptr(ptr));
-		break;
-	case SHMAT:
-		err = compat_sys_shmat(first, second, third, version,
-				       compat_ptr(ptr));
-		break;
-	case SHMDT:
-		err = sys_shmdt(compat_ptr(ptr));
-		break;
-	case SHMGET:
-		err = sys_shmget(first, (unsigned)second, third);
-		break;
-	case SHMCTL:
-		err = compat_sys_shmctl(first, second, compat_ptr(ptr));
-		break;
-	default:
-		err = -EINVAL;
-		break;
-	}
-
-	return err;
-}
-
-#else
-
-SYSCALL_DEFINE6(32_ipc, u32, call, int, first, int, second, int, third,
-	u32, ptr, u32, fifth)
-{
-	return -ENOSYS;
-}
-
-#endif /* CONFIG_SYSVIPC */
-
-#ifdef CONFIG_MIPS32_N32
-SYSCALL_DEFINE4(n32_semctl, int, semid, int, semnum, int, cmd, u32, arg)
-{
-	/* compat_sys_semctl expects a pointer to union semun */
-	u32 __user *uptr = compat_alloc_user_space(sizeof(u32));
-	if (put_user(arg, uptr))
-		return -EFAULT;
-	return compat_sys_semctl(semid, semnum, cmd, uptr);
-}
-
-SYSCALL_DEFINE4(n32_msgsnd, int, msqid, u32, msgp, unsigned int, msgsz,
-	int, msgflg)
-{
-	return compat_sys_msgsnd(msqid, msgsz, msgflg, compat_ptr(msgp));
-}
-
-SYSCALL_DEFINE5(n32_msgrcv, int, msqid, u32, msgp, size_t, msgsz,
-	int, msgtyp, int, msgflg)
-{
-	return compat_sys_msgrcv(msqid, msgsz, msgtyp, msgflg, IPC_64,
-				 compat_ptr(msgp));
-}
-#endif
-
 SYSCALL_DEFINE1(32_personality, unsigned long, personality)
 {
 	unsigned int p = personality & 0xffffffff;
@@ -226,26 +133,6 @@ SYSCALL_DEFINE1(32_personality, unsigned long, personality)
 	return ret;
 }
 
-SYSCALL_DEFINE4(32_sendfile, long, out_fd, long, in_fd,
-	compat_off_t __user *, offset, s32, count)
-{
-	mm_segment_t old_fs = get_fs();
-	int ret;
-	off_t of;
-
-	if (offset && get_user(of, offset))
-		return -EFAULT;
-
-	set_fs(KERNEL_DS);
-	ret = sys_sendfile(out_fd, in_fd, offset ? (off_t __user *)&of : NULL, count);
-	set_fs(old_fs);
-
-	if (offset && put_user(of, offset))
-		return -EFAULT;
-
-	return ret;
-}
-
 asmlinkage ssize_t sys32_readahead(int fd, u32 pad0, u64 a2, u64 a3,
 				   size_t count)
 {
@@ -279,12 +166,6 @@ asmlinkage long sys32_fallocate(int fd, int mode, unsigned offset_a2,
 			     merge_64(len_a4, len_a5));
 }
 
-asmlinkage long sys32_lookup_dcookie(u32 a0, u32 a1, char __user *buf,
-	size_t len)
-{
-	return sys_lookup_dcookie(merge_64(a0, a1), buf, len);
-}
-
 SYSCALL_DEFINE6(32_fanotify_mark, int, fanotify_fd, unsigned int, flags,
 		u64, a3, u64, a4, int, dfd, const char	__user *, pathname)
 {
diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c
index 135c4aa..7a54f74 100644
--- a/arch/mips/kernel/proc.c
+++ b/arch/mips/kernel/proc.c
@@ -67,7 +67,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
 	if (cpu_has_mips_r) {
 		seq_printf(m, "isa\t\t\t:");
 		if (cpu_has_mips_1)
-			seq_printf(m, "%s", "mips1");
+			seq_printf(m, "%s", " mips1");
 		if (cpu_has_mips_2)
 			seq_printf(m, "%s", " mips2");
 		if (cpu_has_mips_3)
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index 693d60b..edcb659 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -143,7 +143,7 @@ EXPORT(sysn32_call_table)
 	PTR	compat_sys_setitimer
 	PTR	sys_alarm
 	PTR	sys_getpid
-	PTR	sys_32_sendfile
+	PTR	compat_sys_sendfile
 	PTR	sys_socket			/* 6040 */
 	PTR	sys_connect
 	PTR	sys_accept
@@ -168,11 +168,11 @@ EXPORT(sysn32_call_table)
 	PTR	sys_newuname
 	PTR	sys_semget
 	PTR	sys_semop
-	PTR	sys_n32_semctl
+	PTR	compat_sys_semctl
 	PTR	sys_shmdt			/* 6065 */
 	PTR	sys_msgget
-	PTR	sys_n32_msgsnd
-	PTR	sys_n32_msgrcv
+	PTR	compat_sys_msgsnd
+	PTR	compat_sys_msgrcv
 	PTR	compat_sys_msgctl
 	PTR	compat_sys_fcntl		/* 6070 */
 	PTR	sys_flock
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
index af8887f..103bfe5 100644
--- a/arch/mips/kernel/scall64-o32.S
+++ b/arch/mips/kernel/scall64-o32.S
@@ -309,7 +309,7 @@ sys_call_table:
 	PTR	compat_sys_wait4
 	PTR	sys_swapoff			/* 4115 */
 	PTR	compat_sys_sysinfo
-	PTR	sys_32_ipc
+	PTR	compat_sys_ipc
 	PTR	sys_fsync
 	PTR	sys32_sigreturn
 	PTR	__sys_clone			/* 4120 */
@@ -399,7 +399,7 @@ sys_call_table:
 	PTR	sys_capget
 	PTR	sys_capset			/* 4205 */
 	PTR	compat_sys_sigaltstack
-	PTR	sys_32_sendfile
+	PTR	compat_sys_sendfile
 	PTR	sys_ni_syscall
 	PTR	sys_ni_syscall
 	PTR	sys_mips_mmap2			/* 4210 */
@@ -439,7 +439,7 @@ sys_call_table:
 	PTR	compat_sys_io_submit
 	PTR	sys_io_cancel			/* 4245 */
 	PTR	sys_exit_group
-	PTR	sys32_lookup_dcookie
+	PTR	compat_sys_lookup_dcookie
 	PTR	sys_epoll_create
 	PTR	sys_epoll_ctl
 	PTR	sys_epoll_wait			/* 4250 */
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index 66bf4e2..596620d 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -83,6 +83,7 @@ static inline void set_cpu_sibling_map(int cpu)
 }
 
 struct plat_smp_ops *mp_ops;
+EXPORT_SYMBOL(mp_ops);
 
 __cpuinit void register_smp_ops(struct plat_smp_ops *ops)
 {
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index a200b5b..59351e5 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -1713,7 +1713,12 @@ void __init trap_init(void)
 		ebase = (unsigned long)
 			__alloc_bootmem(size, 1 << fls(size), 0);
 	} else {
-		ebase = CKSEG0;
+#ifdef CONFIG_KVM_GUEST
+#define KVM_GUEST_KSEG0     0x40000000
+        ebase = KVM_GUEST_KSEG0;
+#else
+        ebase = CKSEG0;
+#endif
 		if (cpu_has_mips_r2)
 			ebase += (read_c0_ebase() & 0x3ffff000);
 	}
diff --git a/arch/mips/kvm/00README.txt b/arch/mips/kvm/00README.txt
new file mode 100644
index 0000000..51617e4
--- /dev/null
+++ b/arch/mips/kvm/00README.txt
@@ -0,0 +1,31 @@
+KVM/MIPS Trap & Emulate Release Notes
+=====================================
+
+(1) KVM/MIPS should support MIPS32R2 and beyond. It has been tested on the following platforms:
+    Malta Board with FPGA based 34K
+    Sigma Designs TangoX board with a 24K based 8654 SoC.
+    Malta Board with 74K @ 1GHz
+
+(2) Both Guest kernel and Guest Userspace execute in UM.
+    Guest User address space:   0x00000000 -> 0x40000000
+    Guest Kernel Unmapped:      0x40000000 -> 0x60000000
+    Guest Kernel Mapped:        0x60000000 -> 0x80000000
+
+    Guest Usermode virtual memory is limited to 1GB.
+
+(2) 16K Page Sizes: Both Host Kernel and Guest Kernel should have the same page size, currently at least 16K.
+    Note that due to cache aliasing issues, 4K page sizes are NOT supported.
+
+(3) No HugeTLB Support
+    Both the host kernel and Guest kernel should have the page size set to 16K.
+    This will be implemented in a future release.
+
+(4) KVM/MIPS does not have support for SMP Guests
+    Linux-3.7-rc2 based SMP guest hangs due to the following code sequence in the generated TLB handlers:
+	LL/TLBP/SC.  Since the TLBP instruction causes a trap the reservation gets cleared
+	when we ERET back to the guest. This causes the guest to hang in an infinite loop.
+	This will be fixed in a future release.
+
+(5) Use Host FPU
+    Currently KVM/MIPS emulates a 24K CPU without a FPU.
+    This will be fixed in a future release
diff --git a/arch/mips/kvm/Kconfig b/arch/mips/kvm/Kconfig
new file mode 100644
index 0000000..2c15590
--- /dev/null
+++ b/arch/mips/kvm/Kconfig
@@ -0,0 +1,49 @@
+#
+# KVM configuration
+#
+source "virt/kvm/Kconfig"
+
+menuconfig VIRTUALIZATION
+	bool "Virtualization"
+	depends on HAVE_KVM
+	---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
+
+config KVM
+	tristate "Kernel-based Virtual Machine (KVM) support"
+	depends on HAVE_KVM
+	select PREEMPT_NOTIFIERS
+	select ANON_INODES
+	select KVM_MMIO
+	---help---
+	  Support for hosting Guest kernels.
+	  Currently supported on MIPS32 processors.
+
+config KVM_MIPS_DYN_TRANS
+	bool "KVM/MIPS: Dynamic binary translation to reduce traps"
+	depends on KVM
+	---help---
+	  When running in Trap & Emulate mode patch privileged
+	  instructions to reduce the number of traps.
+
+	  If unsure, say Y.
+
+config KVM_MIPS_DEBUG_COP0_COUNTERS
+	bool "Maintain counters for COP0 accesses"
+	depends on KVM
+	---help---
+	  Maintain statistics for Guest COP0 accesses.
+	  A histogram of COP0 accesses is printed when the VM is
+	  shutdown.
+
+	  If unsure, say N.
+
+source drivers/vhost/Kconfig
+
+endif # VIRTUALIZATION
diff --git a/arch/mips/kvm/Makefile b/arch/mips/kvm/Makefile
new file mode 100644
index 0000000..78d87bb
--- /dev/null
+++ b/arch/mips/kvm/Makefile
@@ -0,0 +1,13 @@
+# Makefile for KVM support for MIPS
+#
+
+common-objs = $(addprefix ../../../virt/kvm/, kvm_main.o coalesced_mmio.o)
+
+EXTRA_CFLAGS += -Ivirt/kvm -Iarch/mips/kvm
+
+kvm-objs := $(common-objs) kvm_mips.o kvm_mips_emul.o kvm_locore.o \
+	    kvm_mips_int.o kvm_mips_stats.o kvm_mips_commpage.o \
+	    kvm_mips_dyntrans.o kvm_trap_emul.o
+
+obj-$(CONFIG_KVM)	+= kvm.o
+obj-y			+= kvm_cb.o kvm_tlb.o
diff --git a/arch/mips/kvm/kvm_cb.c b/arch/mips/kvm/kvm_cb.c
new file mode 100644
index 0000000..313c2e3
--- /dev/null
+++ b/arch/mips/kvm/kvm_cb.c
@@ -0,0 +1,14 @@
+/*
+ * 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) 2012  MIPS Technologies, Inc.  All rights reserved.
+ * Authors: Yann Le Du <ledu@kymasys.com>
+ */
+
+#include <linux/export.h>
+#include <linux/kvm_host.h>
+
+struct kvm_mips_callbacks *kvm_mips_callbacks;
+EXPORT_SYMBOL(kvm_mips_callbacks);
diff --git a/arch/mips/kvm/kvm_locore.S b/arch/mips/kvm/kvm_locore.S
new file mode 100644
index 0000000..dca2aa6
--- /dev/null
+++ b/arch/mips/kvm/kvm_locore.S
@@ -0,0 +1,650 @@
+/*
+* 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.
+*
+* Main entry point for the guest, exception handling.
+*
+* Copyright (C) 2012  MIPS Technologies, Inc.  All rights reserved.
+* Authors: Sanjay Lal <sanjayl@kymasys.com>
+*/
+
+#include <asm/asm.h>
+#include <asm/asmmacro.h>
+#include <asm/regdef.h>
+#include <asm/mipsregs.h>
+#include <asm/stackframe.h>
+#include <asm/asm-offsets.h>
+
+
+#define _C_LABEL(x)     x
+#define MIPSX(name)     mips32_ ## name
+#define CALLFRAME_SIZ   32
+
+/*
+ * VECTOR
+ *  exception vector entrypoint
+ */
+#define VECTOR(x, regmask)      \
+    .ent    _C_LABEL(x),0;      \
+    EXPORT(x);
+
+#define VECTOR_END(x)      \
+    EXPORT(x);
+
+/* Overload, Danger Will Robinson!! */
+#define PT_HOST_ASID        PT_BVADDR
+#define PT_HOST_USERLOCAL   PT_EPC
+
+#define CP0_DDATA_LO        $28,3
+#define CP0_EBASE           $15,1
+
+#define CP0_INTCTL          $12,1
+#define CP0_SRSCTL          $12,2
+#define CP0_SRSMAP          $12,3
+#define CP0_HWRENA          $7,0
+
+/* Resume Flags */
+#define RESUME_FLAG_HOST        (1<<1)  /* Resume host? */
+
+#define RESUME_GUEST            0
+#define RESUME_HOST             RESUME_FLAG_HOST
+
+/*
+ * __kvm_mips_vcpu_run: entry point to the guest
+ * a0: run
+ * a1: vcpu
+ */
+
+FEXPORT(__kvm_mips_vcpu_run)
+    .set    push
+    .set    noreorder
+    .set    noat
+
+    /* k0/k1 not being used in host kernel context */
+	addiu  		k1,sp, -PT_SIZE
+    LONG_S	    $0, PT_R0(k1)
+    LONG_S     	$1, PT_R1(k1)
+    LONG_S     	$2, PT_R2(k1)
+    LONG_S     	$3, PT_R3(k1)
+
+    LONG_S     	$4, PT_R4(k1)
+    LONG_S     	$5, PT_R5(k1)
+    LONG_S     	$6, PT_R6(k1)
+    LONG_S     	$7, PT_R7(k1)
+
+    LONG_S     	$8,  PT_R8(k1)
+    LONG_S     	$9,  PT_R9(k1)
+    LONG_S     	$10, PT_R10(k1)
+    LONG_S     	$11, PT_R11(k1)
+    LONG_S     	$12, PT_R12(k1)
+    LONG_S     	$13, PT_R13(k1)
+    LONG_S     	$14, PT_R14(k1)
+    LONG_S     	$15, PT_R15(k1)
+    LONG_S     	$16, PT_R16(k1)
+    LONG_S     	$17, PT_R17(k1)
+
+    LONG_S     	$18, PT_R18(k1)
+    LONG_S     	$19, PT_R19(k1)
+    LONG_S     	$20, PT_R20(k1)
+    LONG_S     	$21, PT_R21(k1)
+    LONG_S     	$22, PT_R22(k1)
+    LONG_S     	$23, PT_R23(k1)
+    LONG_S     	$24, PT_R24(k1)
+    LONG_S     	$25, PT_R25(k1)
+
+	/* XXXKYMA k0/k1 not saved, not being used if we got here through an ioctl() */
+
+    LONG_S     	$28, PT_R28(k1)
+    LONG_S     	$29, PT_R29(k1)
+    LONG_S     	$30, PT_R30(k1)
+    LONG_S     	$31, PT_R31(k1)
+
+    /* Save hi/lo */
+	mflo		v0
+	LONG_S		v0, PT_LO(k1)
+	mfhi   		v1
+	LONG_S		v1, PT_HI(k1)
+
+	/* Save host status */
+	mfc0		v0, CP0_STATUS
+	LONG_S		v0, PT_STATUS(k1)
+
+	/* Save host ASID, shove it into the BVADDR location */
+	mfc0 		v1,CP0_ENTRYHI
+	andi		v1, 0xff
+	LONG_S		v1, PT_HOST_ASID(k1)
+
+    /* Save DDATA_LO, will be used to store pointer to vcpu */
+    mfc0        v1, CP0_DDATA_LO
+    LONG_S      v1, PT_HOST_USERLOCAL(k1)
+
+    /* DDATA_LO has pointer to vcpu */
+    mtc0        a1,CP0_DDATA_LO
+
+    /* Offset into vcpu->arch */
+	addiu		k1, a1, VCPU_HOST_ARCH
+
+    /* Save the host stack to VCPU, used for exception processing when we exit from the Guest */
+    LONG_S      sp, VCPU_HOST_STACK(k1)
+
+    /* Save the kernel gp as well */
+    LONG_S      gp, VCPU_HOST_GP(k1)
+
+	/* Setup status register for running the guest in UM, interrupts are disabled */
+	li			k0,(ST0_EXL | KSU_USER| ST0_BEV)
+	mtc0		k0,CP0_STATUS
+    ehb
+
+    /* load up the new EBASE */
+    LONG_L      k0, VCPU_GUEST_EBASE(k1)
+    mtc0        k0,CP0_EBASE
+
+    /* Now that the new EBASE has been loaded, unset BEV, set interrupt mask as it was
+     * but make sure that timer interrupts are enabled
+     */
+    li          k0,(ST0_EXL | KSU_USER | ST0_IE)
+    andi        v0, v0, ST0_IM
+    or          k0, k0, v0
+    mtc0        k0,CP0_STATUS
+    ehb
+
+
+	/* Set Guest EPC */
+	LONG_L		t0, VCPU_PC(k1)
+	mtc0		t0, CP0_EPC
+
+FEXPORT(__kvm_mips_load_asid)
+    /* Set the ASID for the Guest Kernel */
+    sll         t0, t0, 1                       /* with kseg0 @ 0x40000000, kernel */
+                                                /* addresses shift to 0x80000000 */
+    bltz        t0, 1f                          /* If kernel */
+	addiu       t1, k1, VCPU_GUEST_KERNEL_ASID  /* (BD)  */
+    addiu       t1, k1, VCPU_GUEST_USER_ASID    /* else user */
+1:
+    /* t1: contains the base of the ASID array, need to get the cpu id  */
+    LONG_L      t2, TI_CPU($28)             /* smp_processor_id */
+    sll         t2, t2, 2                   /* x4 */
+    addu        t3, t1, t2
+    LONG_L      k0, (t3)
+    andi        k0, k0, 0xff
+	mtc0		k0,CP0_ENTRYHI
+    ehb
+
+    /* Disable RDHWR access */
+    mtc0    zero,  CP0_HWRENA
+
+    /* Now load up the Guest Context from VCPU */
+    LONG_L     	$1, VCPU_R1(k1)
+    LONG_L     	$2, VCPU_R2(k1)
+    LONG_L     	$3, VCPU_R3(k1)
+
+    LONG_L     	$4, VCPU_R4(k1)
+    LONG_L     	$5, VCPU_R5(k1)
+    LONG_L     	$6, VCPU_R6(k1)
+    LONG_L     	$7, VCPU_R7(k1)
+
+    LONG_L     	$8,  VCPU_R8(k1)
+    LONG_L     	$9,  VCPU_R9(k1)
+    LONG_L     	$10, VCPU_R10(k1)
+    LONG_L     	$11, VCPU_R11(k1)
+    LONG_L     	$12, VCPU_R12(k1)
+    LONG_L     	$13, VCPU_R13(k1)
+    LONG_L     	$14, VCPU_R14(k1)
+    LONG_L     	$15, VCPU_R15(k1)
+    LONG_L     	$16, VCPU_R16(k1)
+    LONG_L     	$17, VCPU_R17(k1)
+    LONG_L     	$18, VCPU_R18(k1)
+    LONG_L     	$19, VCPU_R19(k1)
+    LONG_L     	$20, VCPU_R20(k1)
+    LONG_L     	$21, VCPU_R21(k1)
+    LONG_L     	$22, VCPU_R22(k1)
+    LONG_L     	$23, VCPU_R23(k1)
+    LONG_L     	$24, VCPU_R24(k1)
+    LONG_L     	$25, VCPU_R25(k1)
+
+    /* k0/k1 loaded up later */
+
+    LONG_L     	$28, VCPU_R28(k1)
+    LONG_L     	$29, VCPU_R29(k1)
+    LONG_L     	$30, VCPU_R30(k1)
+    LONG_L     	$31, VCPU_R31(k1)
+
+    /* Restore hi/lo */
+	LONG_L		k0, VCPU_LO(k1)
+	mtlo		k0
+
+	LONG_L		k0, VCPU_HI(k1)
+	mthi   		k0
+
+FEXPORT(__kvm_mips_load_k0k1)
+	/* Restore the guest's k0/k1 registers */
+    LONG_L     	k0, VCPU_R26(k1)
+    LONG_L     	k1, VCPU_R27(k1)
+
+    /* Jump to guest */
+	eret
+	.set	pop
+
+VECTOR(MIPSX(exception), unknown)
+/*
+ * Find out what mode we came from and jump to the proper handler.
+ */
+    .set    push
+	.set	noat
+    .set    noreorder
+    mtc0    k0, CP0_ERROREPC    #01: Save guest k0
+    ehb                         #02:
+
+    mfc0    k0, CP0_EBASE       #02: Get EBASE
+    srl     k0, k0, 10          #03: Get rid of CPUNum
+    sll     k0, k0, 10          #04
+    LONG_S  k1, 0x3000(k0)      #05: Save k1 @ offset 0x3000
+    addiu   k0, k0, 0x2000      #06: Exception handler is installed @ offset 0x2000
+	j	k0				        #07: jump to the function
+	nop				        	#08: branch delay slot
+	.set	push
+VECTOR_END(MIPSX(exceptionEnd))
+.end MIPSX(exception)
+
+/*
+ * Generic Guest exception handler. We end up here when the guest
+ * does something that causes a trap to kernel mode.
+ *
+ */
+NESTED (MIPSX(GuestException), CALLFRAME_SIZ, ra)
+    .set    push
+    .set    noat
+    .set    noreorder
+
+    /* Get the VCPU pointer from DDTATA_LO */
+    mfc0        k1, CP0_DDATA_LO
+	addiu		k1, k1, VCPU_HOST_ARCH
+
+    /* Start saving Guest context to VCPU */
+    LONG_S  $0, VCPU_R0(k1)
+    LONG_S  $1, VCPU_R1(k1)
+    LONG_S  $2, VCPU_R2(k1)
+    LONG_S  $3, VCPU_R3(k1)
+    LONG_S  $4, VCPU_R4(k1)
+    LONG_S  $5, VCPU_R5(k1)
+    LONG_S  $6, VCPU_R6(k1)
+    LONG_S  $7, VCPU_R7(k1)
+    LONG_S  $8, VCPU_R8(k1)
+    LONG_S  $9, VCPU_R9(k1)
+    LONG_S  $10, VCPU_R10(k1)
+    LONG_S  $11, VCPU_R11(k1)
+    LONG_S  $12, VCPU_R12(k1)
+    LONG_S  $13, VCPU_R13(k1)
+    LONG_S  $14, VCPU_R14(k1)
+    LONG_S  $15, VCPU_R15(k1)
+    LONG_S  $16, VCPU_R16(k1)
+    LONG_S  $17,VCPU_R17(k1)
+    LONG_S  $18, VCPU_R18(k1)
+    LONG_S  $19, VCPU_R19(k1)
+    LONG_S  $20, VCPU_R20(k1)
+    LONG_S  $21, VCPU_R21(k1)
+    LONG_S  $22, VCPU_R22(k1)
+    LONG_S  $23, VCPU_R23(k1)
+    LONG_S  $24, VCPU_R24(k1)
+    LONG_S  $25, VCPU_R25(k1)
+
+    /* Guest k0/k1 saved later */
+
+    LONG_S  $28, VCPU_R28(k1)
+    LONG_S  $29, VCPU_R29(k1)
+    LONG_S  $30, VCPU_R30(k1)
+    LONG_S  $31, VCPU_R31(k1)
+
+    /* We need to save hi/lo and restore them on
+     * the way out
+     */
+    mfhi    t0
+    LONG_S  t0, VCPU_HI(k1)
+
+    mflo    t0
+    LONG_S  t0, VCPU_LO(k1)
+
+    /* Finally save guest k0/k1 to VCPU */
+    mfc0    t0, CP0_ERROREPC
+    LONG_S  t0, VCPU_R26(k1)
+
+    /* Get GUEST k1 and save it in VCPU */
+    la      t1, ~0x2ff
+    mfc0    t0, CP0_EBASE
+    and     t0, t0, t1
+    LONG_L  t0, 0x3000(t0)
+    LONG_S  t0, VCPU_R27(k1)
+
+    /* Now that context has been saved, we can use other registers */
+
+    /* Restore vcpu */
+    mfc0        a1, CP0_DDATA_LO
+    move        s1, a1
+
+   /* Restore run (vcpu->run) */
+    LONG_L      a0, VCPU_RUN(a1)
+    /* Save pointer to run in s0, will be saved by the compiler */
+    move        s0, a0
+
+
+    /* Save Host level EPC, BadVaddr and Cause to VCPU, useful to process the exception */
+    mfc0    k0,CP0_EPC
+    LONG_S  k0, VCPU_PC(k1)
+
+    mfc0    k0, CP0_BADVADDR
+    LONG_S  k0, VCPU_HOST_CP0_BADVADDR(k1)
+
+    mfc0    k0, CP0_CAUSE
+    LONG_S  k0, VCPU_HOST_CP0_CAUSE(k1)
+
+    mfc0    k0, CP0_ENTRYHI
+    LONG_S  k0, VCPU_HOST_ENTRYHI(k1)
+
+    /* Now restore the host state just enough to run the handlers */
+
+    /* Swtich EBASE to the one used by Linux */
+    /* load up the host EBASE */
+    mfc0        v0, CP0_STATUS
+
+    .set at
+	or          k0, v0, ST0_BEV
+    .set noat
+
+    mtc0        k0, CP0_STATUS
+    ehb
+
+    LONG_L      k0, VCPU_HOST_EBASE(k1)
+    mtc0        k0,CP0_EBASE
+
+
+    /* Now that the new EBASE has been loaded, unset BEV and KSU_USER */
+    .set at
+	and         v0, v0, ~(ST0_EXL | KSU_USER | ST0_IE)
+    or          v0, v0, ST0_CU0
+    .set noat
+    mtc0        v0, CP0_STATUS
+    ehb
+
+    /* Load up host GP */
+    LONG_L  gp, VCPU_HOST_GP(k1)
+
+    /* Need a stack before we can jump to "C" */
+    LONG_L  sp, VCPU_HOST_STACK(k1)
+
+    /* Saved host state */
+    addiu   sp,sp, -PT_SIZE
+
+    /* XXXKYMA do we need to load the host ASID, maybe not because the
+     * kernel entries are marked GLOBAL, need to verify
+     */
+
+    /* Restore host DDATA_LO */
+    LONG_L      k0, PT_HOST_USERLOCAL(sp)
+    mtc0        k0, CP0_DDATA_LO
+
+    /* Restore RDHWR access */
+    la      k0, 0x2000000F
+    mtc0    k0,  CP0_HWRENA
+
+    /* Jump to handler */
+FEXPORT(__kvm_mips_jump_to_handler)
+    /* XXXKYMA: not sure if this is safe, how large is the stack?? */
+    /* Now jump to the kvm_mips_handle_exit() to see if we can deal with this in the kernel */
+    la          t9,kvm_mips_handle_exit
+    jalr.hb     t9
+    addiu       sp,sp, -CALLFRAME_SIZ           /* BD Slot */
+
+    /* Return from handler Make sure interrupts are disabled */
+    di
+    ehb
+
+    /* XXXKYMA: k0/k1 could have been blown away if we processed an exception
+     * while we were handling the exception from the guest, reload k1
+     */
+    move        k1, s1
+	addiu		k1, k1, VCPU_HOST_ARCH
+
+    /* Check return value, should tell us if we are returning to the host (handle I/O etc)
+     * or resuming the guest
+     */
+    andi        t0, v0, RESUME_HOST
+    bnez        t0, __kvm_mips_return_to_host
+    nop
+
+__kvm_mips_return_to_guest:
+    /* Put the saved pointer to vcpu (s1) back into the DDATA_LO Register */
+    mtc0        s1, CP0_DDATA_LO
+
+    /* Load up the Guest EBASE to minimize the window where BEV is set */
+    LONG_L      t0, VCPU_GUEST_EBASE(k1)
+
+    /* Switch EBASE back to the one used by KVM */
+    mfc0        v1, CP0_STATUS
+    .set at
+	or          k0, v1, ST0_BEV
+    .set noat
+    mtc0        k0, CP0_STATUS
+    ehb
+    mtc0        t0,CP0_EBASE
+
+    /* Setup status register for running guest in UM */
+    .set at
+    or     v1, v1, (ST0_EXL | KSU_USER | ST0_IE)
+    and     v1, v1, ~ST0_CU0
+    .set noat
+    mtc0    v1, CP0_STATUS
+    ehb
+
+
+	/* Set Guest EPC */
+	LONG_L		t0, VCPU_PC(k1)
+	mtc0		t0, CP0_EPC
+
+    /* Set the ASID for the Guest Kernel */
+    sll         t0, t0, 1                       /* with kseg0 @ 0x40000000, kernel */
+                                                /* addresses shift to 0x80000000 */
+    bltz        t0, 1f                          /* If kernel */
+	addiu       t1, k1, VCPU_GUEST_KERNEL_ASID  /* (BD)  */
+    addiu       t1, k1, VCPU_GUEST_USER_ASID    /* else user */
+1:
+    /* t1: contains the base of the ASID array, need to get the cpu id  */
+    LONG_L      t2, TI_CPU($28)             /* smp_processor_id */
+    sll         t2, t2, 2                   /* x4 */
+    addu        t3, t1, t2
+    LONG_L      k0, (t3)
+    andi        k0, k0, 0xff
+	mtc0		k0,CP0_ENTRYHI
+    ehb
+
+    /* Disable RDHWR access */
+    mtc0    zero,  CP0_HWRENA
+
+    /* load the guest context from VCPU and return */
+    LONG_L  $0, VCPU_R0(k1)
+    LONG_L  $1, VCPU_R1(k1)
+    LONG_L  $2, VCPU_R2(k1)
+    LONG_L  $3, VCPU_R3(k1)
+    LONG_L  $4, VCPU_R4(k1)
+    LONG_L  $5, VCPU_R5(k1)
+    LONG_L  $6, VCPU_R6(k1)
+    LONG_L  $7, VCPU_R7(k1)
+    LONG_L  $8, VCPU_R8(k1)
+    LONG_L  $9, VCPU_R9(k1)
+    LONG_L  $10, VCPU_R10(k1)
+    LONG_L  $11, VCPU_R11(k1)
+    LONG_L  $12, VCPU_R12(k1)
+    LONG_L  $13, VCPU_R13(k1)
+    LONG_L  $14, VCPU_R14(k1)
+    LONG_L  $15, VCPU_R15(k1)
+    LONG_L  $16, VCPU_R16(k1)
+    LONG_L  $17, VCPU_R17(k1)
+    LONG_L  $18, VCPU_R18(k1)
+    LONG_L  $19, VCPU_R19(k1)
+    LONG_L  $20, VCPU_R20(k1)
+    LONG_L  $21, VCPU_R21(k1)
+    LONG_L  $22, VCPU_R22(k1)
+    LONG_L  $23, VCPU_R23(k1)
+    LONG_L  $24, VCPU_R24(k1)
+    LONG_L  $25, VCPU_R25(k1)
+
+    /* $/k1 loaded later */
+    LONG_L  $28, VCPU_R28(k1)
+    LONG_L  $29, VCPU_R29(k1)
+    LONG_L  $30, VCPU_R30(k1)
+    LONG_L  $31, VCPU_R31(k1)
+
+FEXPORT(__kvm_mips_skip_guest_restore)
+    LONG_L  k0, VCPU_HI(k1)
+    mthi    k0
+
+    LONG_L  k0, VCPU_LO(k1)
+    mtlo    k0
+
+    LONG_L  k0, VCPU_R26(k1)
+    LONG_L  k1, VCPU_R27(k1)
+
+    eret
+
+__kvm_mips_return_to_host:
+    /* EBASE is already pointing to Linux */
+    LONG_L  k1, VCPU_HOST_STACK(k1)
+	addiu  	k1,k1, -PT_SIZE
+
+    /* Restore host DDATA_LO */
+    LONG_L      k0, PT_HOST_USERLOCAL(k1)
+    mtc0        k0, CP0_DDATA_LO
+
+    /* Restore host ASID */
+    LONG_L      k0, PT_HOST_ASID(sp)
+    andi        k0, 0xff
+    mtc0        k0,CP0_ENTRYHI
+    ehb
+
+    /* Load context saved on the host stack */
+    LONG_L  $0, PT_R0(k1)
+    LONG_L  $1, PT_R1(k1)
+
+    /* r2/v0 is the return code, shift it down by 2 (arithmetic) to recover the err code  */
+    sra     k0, v0, 2
+    move    $2, k0
+
+    LONG_L  $3, PT_R3(k1)
+    LONG_L  $4, PT_R4(k1)
+    LONG_L  $5, PT_R5(k1)
+    LONG_L  $6, PT_R6(k1)
+    LONG_L  $7, PT_R7(k1)
+    LONG_L  $8, PT_R8(k1)
+    LONG_L  $9, PT_R9(k1)
+    LONG_L  $10, PT_R10(k1)
+    LONG_L  $11, PT_R11(k1)
+    LONG_L  $12, PT_R12(k1)
+    LONG_L  $13, PT_R13(k1)
+    LONG_L  $14, PT_R14(k1)
+    LONG_L  $15, PT_R15(k1)
+    LONG_L  $16, PT_R16(k1)
+    LONG_L  $17, PT_R17(k1)
+    LONG_L  $18, PT_R18(k1)
+    LONG_L  $19, PT_R19(k1)
+    LONG_L  $20, PT_R20(k1)
+    LONG_L  $21, PT_R21(k1)
+    LONG_L  $22, PT_R22(k1)
+    LONG_L  $23, PT_R23(k1)
+    LONG_L  $24, PT_R24(k1)
+    LONG_L  $25, PT_R25(k1)
+
+    /* Host k0/k1 were not saved */
+
+    LONG_L  $28, PT_R28(k1)
+    LONG_L  $29, PT_R29(k1)
+    LONG_L  $30, PT_R30(k1)
+
+    LONG_L  k0, PT_HI(k1)
+    mthi    k0
+
+    LONG_L  k0, PT_LO(k1)
+    mtlo    k0
+
+    /* Restore RDHWR access */
+    la      k0, 0x2000000F
+    mtc0    k0,  CP0_HWRENA
+
+
+    /* Restore RA, which is the address we will return to */
+    LONG_L  ra, PT_R31(k1)
+    j       ra
+    nop
+
+    .set    pop
+VECTOR_END(MIPSX(GuestExceptionEnd))
+.end MIPSX(GuestException)
+
+MIPSX(exceptions):
+	####
+	##### The exception handlers.
+	#####
+	.word _C_LABEL(MIPSX(GuestException))	#  0
+	.word _C_LABEL(MIPSX(GuestException))	#  1
+	.word _C_LABEL(MIPSX(GuestException))	#  2
+	.word _C_LABEL(MIPSX(GuestException))	#  3
+	.word _C_LABEL(MIPSX(GuestException))	#  4
+	.word _C_LABEL(MIPSX(GuestException))	#  5
+	.word _C_LABEL(MIPSX(GuestException))	#  6
+	.word _C_LABEL(MIPSX(GuestException))	#  7
+	.word _C_LABEL(MIPSX(GuestException))	#  8
+	.word _C_LABEL(MIPSX(GuestException))	#  9
+	.word _C_LABEL(MIPSX(GuestException))	# 10
+	.word _C_LABEL(MIPSX(GuestException))	# 11
+	.word _C_LABEL(MIPSX(GuestException))	# 12
+	.word _C_LABEL(MIPSX(GuestException))	# 13
+	.word _C_LABEL(MIPSX(GuestException))	# 14
+	.word _C_LABEL(MIPSX(GuestException))	# 15
+	.word _C_LABEL(MIPSX(GuestException))	# 16
+	.word _C_LABEL(MIPSX(GuestException))	# 17
+	.word _C_LABEL(MIPSX(GuestException))	# 18
+	.word _C_LABEL(MIPSX(GuestException))	# 19
+	.word _C_LABEL(MIPSX(GuestException))	# 20
+	.word _C_LABEL(MIPSX(GuestException))	# 21
+	.word _C_LABEL(MIPSX(GuestException))	# 22
+	.word _C_LABEL(MIPSX(GuestException))	# 23
+	.word _C_LABEL(MIPSX(GuestException))	# 24
+	.word _C_LABEL(MIPSX(GuestException))	# 25
+	.word _C_LABEL(MIPSX(GuestException))	# 26
+	.word _C_LABEL(MIPSX(GuestException))	# 27
+	.word _C_LABEL(MIPSX(GuestException))	# 28
+	.word _C_LABEL(MIPSX(GuestException))	# 29
+	.word _C_LABEL(MIPSX(GuestException))	# 30
+	.word _C_LABEL(MIPSX(GuestException))	# 31
+
+
+/* This routine makes changes to the instruction stream effective to the hardware.
+ * It should be called after the instruction stream is written.
+ * On return, the new instructions are effective.
+ * Inputs:
+ * a0 = Start address of new instruction stream
+ * a1 = Size, in bytes, of new instruction stream
+ */
+
+#define HW_SYNCI_Step       $1
+LEAF(MIPSX(SyncICache))
+    .set    push
+	.set	mips32r2
+    beq     a1, zero, 20f
+    nop
+    addu    a1, a0, a1
+    rdhwr   v0, HW_SYNCI_Step
+    beq     v0, zero, 20f
+    nop
+
+10:
+    synci   0(a0)
+    addu    a0, a0, v0
+    sltu    v1, a0, a1
+    bne     v1, zero, 10b
+    nop
+    sync
+20:
+    jr.hb   ra
+    nop
+    .set pop
+END(MIPSX(SyncICache))
diff --git a/arch/mips/kvm/kvm_mips.c b/arch/mips/kvm/kvm_mips.c
new file mode 100644
index 0000000..15ee558
--- /dev/null
+++ b/arch/mips/kvm/kvm_mips.c
@@ -0,0 +1,966 @@
+/*
+ * 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.
+ *
+ * KVM/MIPS: MIPS specific KVM APIs
+ *
+ * Copyright (C) 2012  MIPS Technologies, Inc.  All rights reserved.
+ * Authors: Sanjay Lal <sanjayl@kymasys.com>
+*/
+
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+#include <linux/fs.h>
+#include <linux/bootmem.h>
+#include <asm/page.h>
+#include <asm/cacheflush.h>
+#include <asm/mmu_context.h>
+
+#include <linux/kvm_host.h>
+
+#include "kvm_mips_int.h"
+#include "kvm_mips_comm.h"
+
+#define CREATE_TRACE_POINTS
+#include "trace.h"
+
+#ifndef VECTORSPACING
+#define VECTORSPACING 0x100	/* for EI/VI mode */
+#endif
+
+#define VCPU_STAT(x) offsetof(struct kvm_vcpu, stat.x), KVM_STAT_VCPU
+struct kvm_stats_debugfs_item debugfs_entries[] = {
+	{ "wait", VCPU_STAT(wait_exits) },
+	{ "cache", VCPU_STAT(cache_exits) },
+	{ "signal", VCPU_STAT(signal_exits) },
+	{ "interrupt", VCPU_STAT(int_exits) },
+	{ "cop_unsuable", VCPU_STAT(cop_unusable_exits) },
+	{ "tlbmod", VCPU_STAT(tlbmod_exits) },
+	{ "tlbmiss_ld", VCPU_STAT(tlbmiss_ld_exits) },
+	{ "tlbmiss_st", VCPU_STAT(tlbmiss_st_exits) },
+	{ "addrerr_st", VCPU_STAT(addrerr_st_exits) },
+	{ "addrerr_ld", VCPU_STAT(addrerr_ld_exits) },
+	{ "syscall", VCPU_STAT(syscall_exits) },
+	{ "resvd_inst", VCPU_STAT(resvd_inst_exits) },
+	{ "break_inst", VCPU_STAT(break_inst_exits) },
+	{ "flush_dcache", VCPU_STAT(flush_dcache_exits) },
+	{ "halt_wakeup", VCPU_STAT(halt_wakeup) },
+	{NULL}
+};
+
+static int kvm_mips_reset_vcpu(struct kvm_vcpu *vcpu)
+{
+	int i;
+	for_each_possible_cpu(i) {
+		vcpu->arch.guest_kernel_asid[i] = 0;
+		vcpu->arch.guest_user_asid[i] = 0;
+	}
+	return 0;
+}
+
+gfn_t unalias_gfn(struct kvm *kvm, gfn_t gfn)
+{
+	return gfn;
+}
+
+/* XXXKYMA: We are simulatoring a processor that has the WII bit set in Config7, so we
+ * are "runnable" if interrupts are pending
+ */
+int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu)
+{
+	return !!(vcpu->arch.pending_exceptions);
+}
+
+int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu)
+{
+	return 1;
+}
+
+int kvm_arch_hardware_enable(void *garbage)
+{
+	return 0;
+}
+
+void kvm_arch_hardware_disable(void *garbage)
+{
+}
+
+int kvm_arch_hardware_setup(void)
+{
+	return 0;
+}
+
+void kvm_arch_hardware_unsetup(void)
+{
+}
+
+void kvm_arch_check_processor_compat(void *rtn)
+{
+	int *r = (int *)rtn;
+	*r = 0;
+	return;
+}
+
+static void kvm_mips_init_tlbs(struct kvm *kvm)
+{
+	unsigned long wired;
+
+	/* Add a wired entry to the TLB, it is used to map the commpage to the Guest kernel */
+	wired = read_c0_wired();
+	write_c0_wired(wired + 1);
+	mtc0_tlbw_hazard();
+	kvm->arch.commpage_tlb = wired;
+
+	kvm_debug("[%d] commpage TLB: %d\n", smp_processor_id(),
+		  kvm->arch.commpage_tlb);
+}
+
+static void kvm_mips_init_vm_percpu(void *arg)
+{
+	struct kvm *kvm = (struct kvm *)arg;
+
+	kvm_mips_init_tlbs(kvm);
+	kvm_mips_callbacks->vm_init(kvm);
+
+}
+
+int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
+{
+	if (atomic_inc_return(&kvm_mips_instance) == 1) {
+		kvm_info("%s: 1st KVM instance, setup host TLB parameters\n",
+			 __func__);
+		on_each_cpu(kvm_mips_init_vm_percpu, kvm, 1);
+	}
+
+
+	return 0;
+}
+
+void kvm_mips_free_vcpus(struct kvm *kvm)
+{
+	unsigned int i;
+	struct kvm_vcpu *vcpu;
+
+	/* Put the pages we reserved for the guest pmap */
+	for (i = 0; i < kvm->arch.guest_pmap_npages; i++) {
+		if (kvm->arch.guest_pmap[i] != KVM_INVALID_PAGE)
+			kvm_mips_release_pfn_clean(kvm->arch.guest_pmap[i]);
+	}
+
+	if (kvm->arch.guest_pmap)
+		kfree(kvm->arch.guest_pmap);
+
+	kvm_for_each_vcpu(i, vcpu, kvm) {
+		kvm_arch_vcpu_free(vcpu);
+	}
+
+	mutex_lock(&kvm->lock);
+
+	for (i = 0; i < atomic_read(&kvm->online_vcpus); i++)
+		kvm->vcpus[i] = NULL;
+
+	atomic_set(&kvm->online_vcpus, 0);
+
+	mutex_unlock(&kvm->lock);
+}
+
+void kvm_arch_sync_events(struct kvm *kvm)
+{
+}
+
+static void kvm_mips_uninit_tlbs(void *arg)
+{
+	/* Restore wired count */
+	write_c0_wired(0);
+	mtc0_tlbw_hazard();
+	/* Clear out all the TLBs */
+	kvm_local_flush_tlb_all();
+}
+
+void kvm_arch_destroy_vm(struct kvm *kvm)
+{
+	kvm_mips_free_vcpus(kvm);
+
+	/* If this is the last instance, restore wired count */
+	if (atomic_dec_return(&kvm_mips_instance) == 0) {
+		kvm_info("%s: last KVM instance, restoring TLB parameters\n",
+			 __func__);
+		on_each_cpu(kvm_mips_uninit_tlbs, NULL, 1);
+	}
+}
+
+long
+kvm_arch_dev_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
+{
+	return -EINVAL;
+}
+
+int
+kvm_arch_set_memory_region(struct kvm *kvm,
+			   struct kvm_userspace_memory_region *mem,
+			   struct kvm_memory_slot old, int user_alloc)
+{
+	return 0;
+}
+
+void kvm_arch_free_memslot(struct kvm_memory_slot *free,
+			   struct kvm_memory_slot *dont)
+{
+}
+
+int kvm_arch_create_memslot(struct kvm_memory_slot *slot, unsigned long npages)
+{
+	return 0;
+}
+
+int kvm_arch_prepare_memory_region(struct kvm *kvm,
+				   struct kvm_memory_slot *memslot,
+				   struct kvm_memory_slot old,
+				   struct kvm_userspace_memory_region *mem,
+				   int user_alloc)
+{
+	return 0;
+}
+
+void kvm_arch_commit_memory_region(struct kvm *kvm,
+				   struct kvm_userspace_memory_region *mem,
+				   struct kvm_memory_slot old, int user_alloc)
+{
+	unsigned long npages = 0;
+	int i, err = 0;
+
+	kvm_debug("%s: kvm: %p slot: %d, GPA: %llx, size: %llx, QVA: %llx\n",
+		  __func__, kvm, mem->slot, mem->guest_phys_addr,
+		  mem->memory_size, mem->userspace_addr);
+
+	/* Setup Guest PMAP table */
+	if (!kvm->arch.guest_pmap) {
+		if (mem->slot == 0)
+			npages = mem->memory_size >> PAGE_SHIFT;
+
+		if (npages) {
+			kvm->arch.guest_pmap_npages = npages;
+			kvm->arch.guest_pmap =
+			    kzalloc(npages * sizeof(unsigned long), GFP_KERNEL);
+
+			if (!kvm->arch.guest_pmap) {
+				kvm_err("Failed to allocate guest PMAP");
+				err = -ENOMEM;
+				goto out;
+			}
+
+			kvm_info
+			    ("Allocated space for Guest PMAP Table (%ld pages) @ %p\n",
+			     npages, kvm->arch.guest_pmap);
+
+			/* Now setup the page table */
+			for (i = 0; i < npages; i++) {
+				kvm->arch.guest_pmap[i] = KVM_INVALID_PAGE;
+			}
+		}
+	}
+out:
+	return;
+}
+
+void kvm_arch_flush_shadow_all(struct kvm *kvm)
+{
+}
+
+void kvm_arch_flush_shadow_memslot(struct kvm *kvm,
+				   struct kvm_memory_slot *slot)
+{
+}
+
+void kvm_arch_flush_shadow(struct kvm *kvm)
+{
+}
+
+struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id)
+{
+	extern char mips32_exception[], mips32_exceptionEnd[];
+	extern char mips32_GuestException[], mips32_GuestExceptionEnd[];
+	int err, size, offset;
+	void *gebase;
+	int i;
+
+	struct kvm_vcpu *vcpu = kzalloc(sizeof(struct kvm_vcpu), GFP_KERNEL);
+
+	if (!vcpu) {
+		err = -ENOMEM;
+		goto out;
+	}
+
+	err = kvm_vcpu_init(vcpu, kvm, id);
+
+	if (err)
+		goto out_free_cpu;
+
+	kvm_info("kvm @ %p: create cpu %d at %p\n", kvm, id, vcpu);
+
+	/* Allocate space for host mode exception handlers that handle
+	 * guest mode exits
+	 */
+	if (cpu_has_veic || cpu_has_vint) {
+		size = 0x200 + VECTORSPACING * 64;
+	} else {
+		size = 0x200;
+	}
+
+	/* Save Linux EBASE */
+	vcpu->arch.host_ebase = (void *)read_c0_ebase();
+
+	gebase = kzalloc(ALIGN(size, PAGE_SIZE), GFP_KERNEL);
+
+	if (!gebase) {
+		err = -ENOMEM;
+		goto out_free_cpu;
+	}
+	kvm_info("Allocated %d bytes for KVM Exception Handlers @ %p\n",
+		 ALIGN(size, PAGE_SIZE), gebase);
+
+	/* Save new ebase */
+	vcpu->arch.guest_ebase = gebase;
+
+	/* Copy L1 Guest Exception handler to correct offset */
+
+	/* TLB Refill, EXL = 0 */
+	memcpy(gebase, mips32_exception,
+	       mips32_exceptionEnd - mips32_exception);
+
+	/* General Exception Entry point */
+	memcpy(gebase + 0x180, mips32_exception,
+	       mips32_exceptionEnd - mips32_exception);
+
+	/* For vectored interrupts poke the exception code @ all offsets 0-7 */
+	for (i = 0; i < 8; i++) {
+		kvm_debug("L1 Vectored handler @ %p\n",
+			  gebase + 0x200 + (i * VECTORSPACING));
+		memcpy(gebase + 0x200 + (i * VECTORSPACING), mips32_exception,
+		       mips32_exceptionEnd - mips32_exception);
+	}
+
+	/* General handler, relocate to unmapped space for sanity's sake */
+	offset = 0x2000;
+	kvm_info("Installing KVM Exception handlers @ %p, %#x bytes\n",
+		 gebase + offset,
+		 mips32_GuestExceptionEnd - mips32_GuestException);
+
+	memcpy(gebase + offset, mips32_GuestException,
+	       mips32_GuestExceptionEnd - mips32_GuestException);
+
+	/* Invalidate the icache for these ranges */
+	mips32_SyncICache((unsigned long) gebase, ALIGN(size, PAGE_SIZE));
+
+	/* Allocate comm page for guest kernel, a TLB will be reserved for mapping GVA @ 0xFFFF8000 to this page */
+	vcpu->arch.kseg0_commpage = kzalloc(PAGE_SIZE << 1, GFP_KERNEL);
+
+	if (!vcpu->arch.kseg0_commpage) {
+		err = -ENOMEM;
+		goto out_free_gebase;
+	}
+
+	kvm_info("Allocated COMM page @ %p\n", vcpu->arch.kseg0_commpage);
+	kvm_mips_commpage_init(vcpu);
+
+	/* Init */
+	vcpu->arch.last_sched_cpu = -1;
+
+	/* Start off the timer */
+	kvm_mips_emulate_count(vcpu);
+
+	return vcpu;
+
+out_free_gebase:
+	kfree(gebase);
+
+out_free_cpu:
+	kfree(vcpu);
+
+out:
+	return ERR_PTR(err);
+}
+
+void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu)
+{
+	hrtimer_cancel(&vcpu->arch.comparecount_timer);
+
+	kvm_vcpu_uninit(vcpu);
+
+	kvm_mips_dump_stats(vcpu);
+
+	if (vcpu->arch.guest_ebase)
+		kfree(vcpu->arch.guest_ebase);
+
+	if (vcpu->arch.kseg0_commpage)
+		kfree(vcpu->arch.kseg0_commpage);
+
+}
+
+void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
+{
+	kvm_arch_vcpu_free(vcpu);
+}
+
+int
+kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu,
+				    struct kvm_guest_debug *dbg)
+{
+	return -EINVAL;
+}
+
+int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+	int r = 0;
+	sigset_t sigsaved;
+
+	if (vcpu->sigset_active)
+		sigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved);
+
+	if (vcpu->mmio_needed) {
+		if (!vcpu->mmio_is_write)
+			kvm_mips_complete_mmio_load(vcpu, run);
+		vcpu->mmio_needed = 0;
+	}
+
+	/* Check if we have any exceptions/interrupts pending */
+	kvm_mips_deliver_interrupts(vcpu,
+				    kvm_read_c0_guest_cause(vcpu->arch.cop0));
+
+	local_irq_disable();
+	kvm_guest_enter();
+
+	r = __kvm_mips_vcpu_run(run, vcpu);
+
+	kvm_guest_exit();
+	local_irq_enable();
+
+	if (vcpu->sigset_active)
+		sigprocmask(SIG_SETMASK, &sigsaved, NULL);
+
+	return r;
+}
+
+int
+kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu, struct kvm_mips_interrupt *irq)
+{
+	int intr = (int)irq->irq;
+	struct kvm_vcpu *dvcpu = NULL;
+
+	if (intr == 3 || intr == -3 || intr == 4 || intr == -4)
+		kvm_debug("%s: CPU: %d, INTR: %d\n", __func__, irq->cpu,
+			  (int)intr);
+
+	if (irq->cpu == -1)
+		dvcpu = vcpu;
+	else
+		dvcpu = vcpu->kvm->vcpus[irq->cpu];
+
+	if (intr == 2 || intr == 3 || intr == 4) {
+		kvm_mips_callbacks->queue_io_int(dvcpu, irq);
+
+	} else if (intr == -2 || intr == -3 || intr == -4) {
+		kvm_mips_callbacks->dequeue_io_int(dvcpu, irq);
+	} else {
+		kvm_err("%s: invalid interrupt ioctl (%d:%d)\n", __func__,
+			irq->cpu, irq->irq);
+		return -EINVAL;
+	}
+
+	dvcpu->arch.wait = 0;
+
+	if (waitqueue_active(&dvcpu->wq)) {
+		wake_up_interruptible(&dvcpu->wq);
+	}
+
+	return 0;
+}
+
+int
+kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu,
+				struct kvm_mp_state *mp_state)
+{
+	return -EINVAL;
+}
+
+int
+kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
+				struct kvm_mp_state *mp_state)
+{
+	return -EINVAL;
+}
+
+long
+kvm_arch_vcpu_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
+{
+	struct kvm_vcpu *vcpu = filp->private_data;
+	void __user *argp = (void __user *)arg;
+	long r;
+	int intr;
+
+	switch (ioctl) {
+	case KVM_NMI:
+		/* Treat the NMI as a CPU reset */
+		r = kvm_mips_reset_vcpu(vcpu);
+		break;
+	case KVM_INTERRUPT:
+		{
+			struct kvm_mips_interrupt irq;
+			r = -EFAULT;
+			if (copy_from_user(&irq, argp, sizeof(irq)))
+				goto out;
+
+			intr = (int)irq.irq;
+
+			kvm_debug("[%d] %s: irq: %d\n", vcpu->vcpu_id, __func__,
+				  irq.irq);
+
+			r = kvm_vcpu_ioctl_interrupt(vcpu, &irq);
+			break;
+		}
+	default:
+		r = -EINVAL;
+	}
+
+out:
+	return r;
+}
+
+/*
+ * Get (and clear) the dirty memory log for a memory slot.
+ */
+int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log)
+{
+	struct kvm_memory_slot *memslot;
+	unsigned long ga, ga_end;
+	int is_dirty = 0;
+	int r;
+	unsigned long n;
+
+	mutex_lock(&kvm->slots_lock);
+
+	r = kvm_get_dirty_log(kvm, log, &is_dirty);
+	if (r)
+		goto out;
+
+	/* If nothing is dirty, don't bother messing with page tables. */
+	if (is_dirty) {
+		memslot = &kvm->memslots->memslots[log->slot];
+
+		ga = memslot->base_gfn << PAGE_SHIFT;
+		ga_end = ga + (memslot->npages << PAGE_SHIFT);
+
+		printk("%s: dirty, ga: %#lx, ga_end %#lx\n", __func__, ga,
+		       ga_end);
+
+		n = kvm_dirty_bitmap_bytes(memslot);
+		memset(memslot->dirty_bitmap, 0, n);
+	}
+
+	r = 0;
+out:
+	mutex_unlock(&kvm->slots_lock);
+	return r;
+
+}
+
+long kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
+{
+	long r;
+
+	switch (ioctl) {
+	default:
+		r = -EINVAL;
+	}
+
+	return r;
+}
+
+int kvm_arch_init(void *opaque)
+{
+	int ret;
+
+	if (kvm_mips_callbacks) {
+		kvm_err("kvm: module already exists\n");
+		return -EEXIST;
+	}
+
+	ret = kvm_mips_emulation_init(&kvm_mips_callbacks);
+
+	return ret;
+}
+
+void kvm_arch_exit(void)
+{
+	kvm_mips_callbacks = NULL;
+}
+
+int
+kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs)
+{
+	return -ENOTSUPP;
+}
+
+int
+kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs)
+{
+	return -ENOTSUPP;
+}
+
+int kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
+{
+	return 0;
+}
+
+int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
+{
+	return -ENOTSUPP;
+}
+
+int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
+{
+	return -ENOTSUPP;
+}
+
+int kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf)
+{
+	return VM_FAULT_SIGBUS;
+}
+
+int kvm_dev_ioctl_check_extension(long ext)
+{
+	int r;
+
+	switch (ext) {
+	case KVM_CAP_COALESCED_MMIO:
+		r = KVM_COALESCED_MMIO_PAGE_OFFSET;
+		break;
+	default:
+		r = 0;
+		break;
+	}
+	return r;
+
+}
+
+int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)
+{
+	return kvm_mips_pending_timer(vcpu);
+}
+
+int kvm_arch_vcpu_dump_regs(struct kvm_vcpu *vcpu)
+{
+	int i;
+	struct mips_coproc *cop0;
+
+	if (!vcpu)
+		return -1;
+
+	printk("VCPU Register Dump:\n");
+	printk("\tpc = 0x%08lx\n", vcpu->arch.pc);;
+	printk("\texceptions: %08lx\n", vcpu->arch.pending_exceptions);
+
+	for (i = 0; i < 32; i += 4) {
+		printk("\tgpr%02d: %08lx %08lx %08lx %08lx\n", i,
+		       vcpu->arch.gprs[i],
+		       vcpu->arch.gprs[i + 1],
+		       vcpu->arch.gprs[i + 2], vcpu->arch.gprs[i + 3]);
+	}
+	printk("\thi: 0x%08lx\n", vcpu->arch.hi);
+	printk("\tlo: 0x%08lx\n", vcpu->arch.lo);
+
+	cop0 = vcpu->arch.cop0;
+	printk("\tStatus: 0x%08lx, Cause: 0x%08lx\n",
+	       kvm_read_c0_guest_status(cop0), kvm_read_c0_guest_cause(cop0));
+
+	printk("\tEPC: 0x%08lx\n", kvm_read_c0_guest_epc(cop0));
+
+	return 0;
+}
+
+int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
+{
+	int i;
+
+	for (i = 0; i < 32; i++)
+		vcpu->arch.gprs[i] = regs->gprs[i];
+
+	vcpu->arch.hi = regs->hi;
+	vcpu->arch.lo = regs->lo;
+	vcpu->arch.pc = regs->pc;
+
+	return kvm_mips_callbacks->vcpu_ioctl_set_regs(vcpu, regs);
+}
+
+int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
+{
+	int i;
+
+	for (i = 0; i < 32; i++)
+		regs->gprs[i] = vcpu->arch.gprs[i];
+
+	regs->hi = vcpu->arch.hi;
+	regs->lo = vcpu->arch.lo;
+	regs->pc = vcpu->arch.pc;
+
+	return kvm_mips_callbacks->vcpu_ioctl_get_regs(vcpu, regs);
+}
+
+void kvm_mips_comparecount_func(unsigned long data)
+{
+	struct kvm_vcpu *vcpu = (struct kvm_vcpu *)data;
+
+	kvm_mips_callbacks->queue_timer_int(vcpu);
+
+	vcpu->arch.wait = 0;
+	if (waitqueue_active(&vcpu->wq)) {
+		wake_up_interruptible(&vcpu->wq);
+	}
+}
+
+/*
+ * low level hrtimer wake routine.
+ */
+enum hrtimer_restart kvm_mips_comparecount_wakeup(struct hrtimer *timer)
+{
+	struct kvm_vcpu *vcpu;
+
+	vcpu = container_of(timer, struct kvm_vcpu, arch.comparecount_timer);
+	kvm_mips_comparecount_func((unsigned long) vcpu);
+	hrtimer_forward_now(&vcpu->arch.comparecount_timer,
+			    ktime_set(0, MS_TO_NS(10)));
+	return HRTIMER_RESTART;
+}
+
+int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
+{
+	kvm_mips_callbacks->vcpu_init(vcpu);
+	hrtimer_init(&vcpu->arch.comparecount_timer, CLOCK_MONOTONIC,
+		     HRTIMER_MODE_REL);
+	vcpu->arch.comparecount_timer.function = kvm_mips_comparecount_wakeup;
+	kvm_mips_init_shadow_tlb(vcpu);
+	return 0;
+}
+
+void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu)
+{
+	return;
+}
+
+int
+kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu, struct kvm_translation *tr)
+{
+	return 0;
+}
+
+/* Initial guest state */
+int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
+{
+	return kvm_mips_callbacks->vcpu_setup(vcpu);
+}
+
+static
+void kvm_mips_set_c0_status(void)
+{
+	uint32_t status = read_c0_status();
+
+	if (cpu_has_fpu)
+		status |= (ST0_CU1);
+
+	if (cpu_has_dsp)
+		status |= (ST0_MX);
+
+	write_c0_status(status);
+	ehb();
+}
+
+/*
+ * Return value is in the form (errcode<<2 | RESUME_FLAG_HOST | RESUME_FLAG_NV)
+ */
+int kvm_mips_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu)
+{
+	uint32_t cause = vcpu->arch.host_cp0_cause;
+	uint32_t exccode = (cause >> CAUSEB_EXCCODE) & 0x1f;
+	uint32_t __user *opc = (uint32_t __user *) vcpu->arch.pc;
+	unsigned long badvaddr = vcpu->arch.host_cp0_badvaddr;
+	enum emulation_result er = EMULATE_DONE;
+	int ret = RESUME_GUEST;
+
+	/* Set a default exit reason */
+	run->exit_reason = KVM_EXIT_UNKNOWN;
+	run->ready_for_interrupt_injection = 1;
+
+	/* Set the appropriate status bits based on host CPU features, before we hit the scheduler */
+	kvm_mips_set_c0_status();
+
+	local_irq_enable();
+
+	kvm_debug("kvm_mips_handle_exit: cause: %#x, PC: %p, kvm_run: %p, kvm_vcpu: %p\n",
+			cause, opc, run, vcpu);
+
+	/* Do a privilege check, if in UM most of these exit conditions end up
+	 * causing an exception to be delivered to the Guest Kernel
+	 */
+	er = kvm_mips_check_privilege(cause, opc, run, vcpu);
+	if (er == EMULATE_PRIV_FAIL) {
+		goto skip_emul;
+	} else if (er == EMULATE_FAIL) {
+		run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+		ret = RESUME_HOST;
+		goto skip_emul;
+	}
+
+	switch (exccode) {
+	case T_INT:
+		kvm_debug("[%d]T_INT @ %p\n", vcpu->vcpu_id, opc);
+
+		++vcpu->stat.int_exits;
+		trace_kvm_exit(vcpu, INT_EXITS);
+
+		if (need_resched()) {
+			cond_resched();
+		}
+
+		ret = RESUME_GUEST;
+		break;
+
+	case T_COP_UNUSABLE:
+		kvm_debug("T_COP_UNUSABLE: @ PC: %p\n", opc);
+
+		++vcpu->stat.cop_unusable_exits;
+		trace_kvm_exit(vcpu, COP_UNUSABLE_EXITS);
+		ret = kvm_mips_callbacks->handle_cop_unusable(vcpu);
+		/* XXXKYMA: Might need to return to user space */
+		if (run->exit_reason == KVM_EXIT_IRQ_WINDOW_OPEN) {
+			ret = RESUME_HOST;
+		}
+		break;
+
+	case T_TLB_MOD:
+		++vcpu->stat.tlbmod_exits;
+		trace_kvm_exit(vcpu, TLBMOD_EXITS);
+		ret = kvm_mips_callbacks->handle_tlb_mod(vcpu);
+		break;
+
+	case T_TLB_ST_MISS:
+		kvm_debug
+		    ("TLB ST fault:  cause %#x, status %#lx, PC: %p, BadVaddr: %#lx\n",
+		     cause, kvm_read_c0_guest_status(vcpu->arch.cop0), opc,
+		     badvaddr);
+
+		++vcpu->stat.tlbmiss_st_exits;
+		trace_kvm_exit(vcpu, TLBMISS_ST_EXITS);
+		ret = kvm_mips_callbacks->handle_tlb_st_miss(vcpu);
+		break;
+
+	case T_TLB_LD_MISS:
+		kvm_debug("TLB LD fault: cause %#x, PC: %p, BadVaddr: %#lx\n",
+			  cause, opc, badvaddr);
+
+		++vcpu->stat.tlbmiss_ld_exits;
+		trace_kvm_exit(vcpu, TLBMISS_LD_EXITS);
+		ret = kvm_mips_callbacks->handle_tlb_ld_miss(vcpu);
+		break;
+
+	case T_ADDR_ERR_ST:
+		++vcpu->stat.addrerr_st_exits;
+		trace_kvm_exit(vcpu, ADDRERR_ST_EXITS);
+		ret = kvm_mips_callbacks->handle_addr_err_st(vcpu);
+		break;
+
+	case T_ADDR_ERR_LD:
+		++vcpu->stat.addrerr_ld_exits;
+		trace_kvm_exit(vcpu, ADDRERR_LD_EXITS);
+		ret = kvm_mips_callbacks->handle_addr_err_ld(vcpu);
+		break;
+
+	case T_SYSCALL:
+		++vcpu->stat.syscall_exits;
+		trace_kvm_exit(vcpu, SYSCALL_EXITS);
+		ret = kvm_mips_callbacks->handle_syscall(vcpu);
+		break;
+
+	case T_RES_INST:
+		++vcpu->stat.resvd_inst_exits;
+		trace_kvm_exit(vcpu, RESVD_INST_EXITS);
+		ret = kvm_mips_callbacks->handle_res_inst(vcpu);
+		break;
+
+	case T_BREAK:
+		++vcpu->stat.break_inst_exits;
+		trace_kvm_exit(vcpu, BREAK_INST_EXITS);
+		ret = kvm_mips_callbacks->handle_break(vcpu);
+		break;
+
+	default:
+		kvm_err
+		    ("Exception Code: %d, not yet handled, @ PC: %p, inst: 0x%08x  BadVaddr: %#lx Status: %#lx\n",
+		     exccode, opc, kvm_get_inst(opc, vcpu), badvaddr,
+		     kvm_read_c0_guest_status(vcpu->arch.cop0));
+		kvm_arch_vcpu_dump_regs(vcpu);
+		run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+		ret = RESUME_HOST;
+		break;
+
+	}
+
+skip_emul:
+	local_irq_disable();
+
+	if (er == EMULATE_DONE && !(ret & RESUME_HOST))
+		kvm_mips_deliver_interrupts(vcpu, cause);
+
+	if (!(ret & RESUME_HOST)) {
+		/* Only check for signals if not already exiting to userspace  */
+		if (signal_pending(current)) {
+			run->exit_reason = KVM_EXIT_INTR;
+			ret = (-EINTR << 2) | RESUME_HOST;
+			++vcpu->stat.signal_exits;
+			trace_kvm_exit(vcpu, SIGNAL_EXITS);
+		}
+	}
+
+	return ret;
+}
+
+int __init kvm_mips_init(void)
+{
+	int ret;
+
+	ret = kvm_init(NULL, sizeof(struct kvm_vcpu), 0, THIS_MODULE);
+
+	if (ret)
+		return ret;
+
+	/* On MIPS, kernel modules are executed from "mapped space", which requires TLBs.
+	 * The TLB handling code is statically linked with the rest of the kernel (kvm_tlb.c)
+	 * to avoid the possibility of double faulting. The issue is that the TLB code
+	 * references routines that are part of the the KVM module,
+	 * which are only available once the module is loaded.
+	 */
+	kvm_mips_gfn_to_pfn = gfn_to_pfn;
+	kvm_mips_release_pfn_clean = kvm_release_pfn_clean;
+	kvm_mips_is_error_pfn = is_error_pfn;
+
+	pr_info("KVM/MIPS Initialized\n");
+	return 0;
+}
+
+void __exit kvm_mips_exit(void)
+{
+	kvm_exit();
+
+	kvm_mips_gfn_to_pfn = NULL;
+	kvm_mips_release_pfn_clean = NULL;
+	kvm_mips_is_error_pfn = NULL;
+
+	pr_info("KVM/MIPS unloaded\n");
+}
+
+module_init(kvm_mips_init);
+module_exit(kvm_mips_exit);
+
+EXPORT_TRACEPOINT_SYMBOL(kvm_exit);
diff --git a/arch/mips/kvm/kvm_mips_comm.h b/arch/mips/kvm/kvm_mips_comm.h
new file mode 100644
index 0000000..a4a8c85
--- /dev/null
+++ b/arch/mips/kvm/kvm_mips_comm.h
@@ -0,0 +1,23 @@
+/*
+* 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.
+*
+* KVM/MIPS: commpage: mapped into get kernel space
+*
+* Copyright (C) 2012  MIPS Technologies, Inc.  All rights reserved.
+* Authors: Sanjay Lal <sanjayl@kymasys.com>
+*/
+
+#ifndef __KVM_MIPS_COMMPAGE_H__
+#define __KVM_MIPS_COMMPAGE_H__
+
+struct kvm_mips_commpage {
+	struct mips_coproc cop0;	/* COP0 state is mapped into Guest kernel via commpage */
+};
+
+#define KVM_MIPS_COMM_EIDI_OFFSET       0x0
+
+extern void kvm_mips_commpage_init(struct kvm_vcpu *vcpu);
+
+#endif /* __KVM_MIPS_COMMPAGE_H__ */
diff --git a/arch/mips/kvm/kvm_mips_commpage.c b/arch/mips/kvm/kvm_mips_commpage.c
new file mode 100644
index 0000000..3873b1e
--- /dev/null
+++ b/arch/mips/kvm/kvm_mips_commpage.c
@@ -0,0 +1,37 @@
+/*
+* 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.
+*
+* commpage, currently used for Virtual COP0 registers.
+* Mapped into the guest kernel @ 0x0.
+*
+* Copyright (C) 2012  MIPS Technologies, Inc.  All rights reserved.
+* Authors: Sanjay Lal <sanjayl@kymasys.com>
+*/
+
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+#include <linux/fs.h>
+#include <linux/bootmem.h>
+#include <asm/page.h>
+#include <asm/cacheflush.h>
+#include <asm/mmu_context.h>
+
+#include <linux/kvm_host.h>
+
+#include "kvm_mips_comm.h"
+
+void kvm_mips_commpage_init(struct kvm_vcpu *vcpu)
+{
+	struct kvm_mips_commpage *page = vcpu->arch.kseg0_commpage;
+	memset(page, 0, sizeof(struct kvm_mips_commpage));
+
+	/* Specific init values for fields */
+	vcpu->arch.cop0 = &page->cop0;
+	memset(vcpu->arch.cop0, 0, sizeof(struct mips_coproc));
+
+	return;
+}
diff --git a/arch/mips/kvm/kvm_mips_dyntrans.c b/arch/mips/kvm/kvm_mips_dyntrans.c
new file mode 100644
index 0000000..96528e2
--- /dev/null
+++ b/arch/mips/kvm/kvm_mips_dyntrans.c
@@ -0,0 +1,149 @@
+/*
+* 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.
+*
+* KVM/MIPS: Binary Patching for privileged instructions, reduces traps.
+*
+* Copyright (C) 2012  MIPS Technologies, Inc.  All rights reserved.
+* Authors: Sanjay Lal <sanjayl@kymasys.com>
+*/
+
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/kvm_host.h>
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+#include <linux/fs.h>
+#include <linux/bootmem.h>
+
+#include "kvm_mips_comm.h"
+
+#define SYNCI_TEMPLATE  0x041f0000
+#define SYNCI_BASE(x)   (((x) >> 21) & 0x1f)
+#define SYNCI_OFFSET    ((x) & 0xffff)
+
+#define LW_TEMPLATE     0x8c000000
+#define CLEAR_TEMPLATE  0x00000020
+#define SW_TEMPLATE     0xac000000
+
+int
+kvm_mips_trans_cache_index(uint32_t inst, uint32_t *opc,
+			   struct kvm_vcpu *vcpu)
+{
+	int result = 0;
+	unsigned long kseg0_opc;
+	uint32_t synci_inst = 0x0;
+
+	/* Replace the CACHE instruction, with a NOP */
+	kseg0_opc =
+	    CKSEG0ADDR(kvm_mips_translate_guest_kseg0_to_hpa
+		       (vcpu, (unsigned long) opc));
+	memcpy((void *)kseg0_opc, (void *)&synci_inst, sizeof(uint32_t));
+	mips32_SyncICache(kseg0_opc, 32);
+
+	return result;
+}
+
+/*
+ *  Address based CACHE instructions are transformed into synci(s). A little heavy
+ * for just D-cache invalidates, but avoids an expensive trap
+ */
+int
+kvm_mips_trans_cache_va(uint32_t inst, uint32_t *opc,
+			struct kvm_vcpu *vcpu)
+{
+	int result = 0;
+	unsigned long kseg0_opc;
+	uint32_t synci_inst = SYNCI_TEMPLATE, base, offset;
+
+	base = (inst >> 21) & 0x1f;
+	offset = inst & 0xffff;
+	synci_inst |= (base << 21);
+	synci_inst |= offset;
+
+	kseg0_opc =
+	    CKSEG0ADDR(kvm_mips_translate_guest_kseg0_to_hpa
+		       (vcpu, (unsigned long) opc));
+	memcpy((void *)kseg0_opc, (void *)&synci_inst, sizeof(uint32_t));
+	mips32_SyncICache(kseg0_opc, 32);
+
+	return result;
+}
+
+int
+kvm_mips_trans_mfc0(uint32_t inst, uint32_t *opc, struct kvm_vcpu *vcpu)
+{
+	int32_t rt, rd, sel;
+	uint32_t mfc0_inst;
+	unsigned long kseg0_opc, flags;
+
+	rt = (inst >> 16) & 0x1f;
+	rd = (inst >> 11) & 0x1f;
+	sel = inst & 0x7;
+
+	if ((rd == MIPS_CP0_ERRCTL) && (sel == 0)) {
+		mfc0_inst = CLEAR_TEMPLATE;
+		mfc0_inst |= ((rt & 0x1f) << 16);
+	} else {
+		mfc0_inst = LW_TEMPLATE;
+		mfc0_inst |= ((rt & 0x1f) << 16);
+		mfc0_inst |=
+		    offsetof(struct mips_coproc,
+			     reg[rd][sel]) + offsetof(struct kvm_mips_commpage,
+						      cop0);
+	}
+
+	if (KVM_GUEST_KSEGX(opc) == KVM_GUEST_KSEG0) {
+		kseg0_opc =
+		    CKSEG0ADDR(kvm_mips_translate_guest_kseg0_to_hpa
+			       (vcpu, (unsigned long) opc));
+		memcpy((void *)kseg0_opc, (void *)&mfc0_inst, sizeof(uint32_t));
+		mips32_SyncICache(kseg0_opc, 32);
+	} else if (KVM_GUEST_KSEGX((unsigned long) opc) == KVM_GUEST_KSEG23) {
+		local_irq_save(flags);
+		memcpy((void *)opc, (void *)&mfc0_inst, sizeof(uint32_t));
+		mips32_SyncICache((unsigned long) opc, 32);
+		local_irq_restore(flags);
+	} else {
+		kvm_err("%s: Invalid address: %p\n", __func__, opc);
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+int
+kvm_mips_trans_mtc0(uint32_t inst, uint32_t *opc, struct kvm_vcpu *vcpu)
+{
+	int32_t rt, rd, sel;
+	uint32_t mtc0_inst = SW_TEMPLATE;
+	unsigned long kseg0_opc, flags;
+
+	rt = (inst >> 16) & 0x1f;
+	rd = (inst >> 11) & 0x1f;
+	sel = inst & 0x7;
+
+	mtc0_inst |= ((rt & 0x1f) << 16);
+	mtc0_inst |=
+	    offsetof(struct mips_coproc,
+		     reg[rd][sel]) + offsetof(struct kvm_mips_commpage, cop0);
+
+	if (KVM_GUEST_KSEGX(opc) == KVM_GUEST_KSEG0) {
+		kseg0_opc =
+		    CKSEG0ADDR(kvm_mips_translate_guest_kseg0_to_hpa
+			       (vcpu, (unsigned long) opc));
+		memcpy((void *)kseg0_opc, (void *)&mtc0_inst, sizeof(uint32_t));
+		mips32_SyncICache(kseg0_opc, 32);
+	} else if (KVM_GUEST_KSEGX((unsigned long) opc) == KVM_GUEST_KSEG23) {
+		local_irq_save(flags);
+		memcpy((void *)opc, (void *)&mtc0_inst, sizeof(uint32_t));
+		mips32_SyncICache((unsigned long) opc, 32);
+		local_irq_restore(flags);
+	} else {
+		kvm_err("%s: Invalid address: %p\n", __func__, opc);
+		return -EFAULT;
+	}
+
+	return 0;
+}
diff --git a/arch/mips/kvm/kvm_mips_emul.c b/arch/mips/kvm/kvm_mips_emul.c
new file mode 100644
index 0000000..4b6274b
--- /dev/null
+++ b/arch/mips/kvm/kvm_mips_emul.c
@@ -0,0 +1,1829 @@
+/*
+* 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.
+*
+* KVM/MIPS: Instruction/Exception emulation
+*
+* Copyright (C) 2012  MIPS Technologies, Inc.  All rights reserved.
+* Authors: Sanjay Lal <sanjayl@kymasys.com>
+*/
+
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/kvm_host.h>
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+#include <linux/fs.h>
+#include <linux/bootmem.h>
+#include <linux/random.h>
+#include <asm/page.h>
+#include <asm/cacheflush.h>
+#include <asm/cpu-info.h>
+#include <asm/mmu_context.h>
+#include <asm/tlbflush.h>
+#include <asm/inst.h>
+
+#undef CONFIG_MIPS_MT
+#include <asm/r4kcache.h>
+#define CONFIG_MIPS_MT
+
+#include "kvm_mips_opcode.h"
+#include "kvm_mips_int.h"
+#include "kvm_mips_comm.h"
+
+#include "trace.h"
+
+/*
+ * Compute the return address and do emulate branch simulation, if required.
+ * This function should be called only in branch delay slot active.
+ */
+unsigned long kvm_compute_return_epc(struct kvm_vcpu *vcpu,
+	unsigned long instpc)
+{
+	unsigned int dspcontrol;
+	union mips_instruction insn;
+	struct kvm_vcpu_arch *arch = &vcpu->arch;
+	long epc = instpc;
+	long nextpc = KVM_INVALID_INST;
+
+	if (epc & 3)
+		goto unaligned;
+
+	/*
+	 * Read the instruction
+	 */
+	insn.word = kvm_get_inst((uint32_t *) epc, vcpu);
+
+	if (insn.word == KVM_INVALID_INST)
+		return KVM_INVALID_INST;
+
+	switch (insn.i_format.opcode) {
+		/*
+		 * jr and jalr are in r_format format.
+		 */
+	case spec_op:
+		switch (insn.r_format.func) {
+		case jalr_op:
+			arch->gprs[insn.r_format.rd] = epc + 8;
+			/* Fall through */
+		case jr_op:
+			nextpc = arch->gprs[insn.r_format.rs];
+			break;
+		}
+		break;
+
+		/*
+		 * This group contains:
+		 * bltz_op, bgez_op, bltzl_op, bgezl_op,
+		 * bltzal_op, bgezal_op, bltzall_op, bgezall_op.
+		 */
+	case bcond_op:
+		switch (insn.i_format.rt) {
+		case bltz_op:
+		case bltzl_op:
+			if ((long)arch->gprs[insn.i_format.rs] < 0)
+				epc = epc + 4 + (insn.i_format.simmediate << 2);
+			else
+				epc += 8;
+			nextpc = epc;
+			break;
+
+		case bgez_op:
+		case bgezl_op:
+			if ((long)arch->gprs[insn.i_format.rs] >= 0)
+				epc = epc + 4 + (insn.i_format.simmediate << 2);
+			else
+				epc += 8;
+			nextpc = epc;
+			break;
+
+		case bltzal_op:
+		case bltzall_op:
+			arch->gprs[31] = epc + 8;
+			if ((long)arch->gprs[insn.i_format.rs] < 0)
+				epc = epc + 4 + (insn.i_format.simmediate << 2);
+			else
+				epc += 8;
+			nextpc = epc;
+			break;
+
+		case bgezal_op:
+		case bgezall_op:
+			arch->gprs[31] = epc + 8;
+			if ((long)arch->gprs[insn.i_format.rs] >= 0)
+				epc = epc + 4 + (insn.i_format.simmediate << 2);
+			else
+				epc += 8;
+			nextpc = epc;
+			break;
+		case bposge32_op:
+			if (!cpu_has_dsp)
+				goto sigill;
+
+			dspcontrol = rddsp(0x01);
+
+			if (dspcontrol >= 32) {
+				epc = epc + 4 + (insn.i_format.simmediate << 2);
+			} else
+				epc += 8;
+			nextpc = epc;
+			break;
+		}
+		break;
+
+		/*
+		 * These are unconditional and in j_format.
+		 */
+	case jal_op:
+		arch->gprs[31] = instpc + 8;
+	case j_op:
+		epc += 4;
+		epc >>= 28;
+		epc <<= 28;
+		epc |= (insn.j_format.target << 2);
+		nextpc = epc;
+		break;
+
+		/*
+		 * These are conditional and in i_format.
+		 */
+	case beq_op:
+	case beql_op:
+		if (arch->gprs[insn.i_format.rs] ==
+		    arch->gprs[insn.i_format.rt])
+			epc = epc + 4 + (insn.i_format.simmediate << 2);
+		else
+			epc += 8;
+		nextpc = epc;
+		break;
+
+	case bne_op:
+	case bnel_op:
+		if (arch->gprs[insn.i_format.rs] !=
+		    arch->gprs[insn.i_format.rt])
+			epc = epc + 4 + (insn.i_format.simmediate << 2);
+		else
+			epc += 8;
+		nextpc = epc;
+		break;
+
+	case blez_op:		/* not really i_format */
+	case blezl_op:
+		/* rt field assumed to be zero */
+		if ((long)arch->gprs[insn.i_format.rs] <= 0)
+			epc = epc + 4 + (insn.i_format.simmediate << 2);
+		else
+			epc += 8;
+		nextpc = epc;
+		break;
+
+	case bgtz_op:
+	case bgtzl_op:
+		/* rt field assumed to be zero */
+		if ((long)arch->gprs[insn.i_format.rs] > 0)
+			epc = epc + 4 + (insn.i_format.simmediate << 2);
+		else
+			epc += 8;
+		nextpc = epc;
+		break;
+
+		/*
+		 * And now the FPA/cp1 branch instructions.
+		 */
+	case cop1_op:
+		printk("%s: unsupported cop1_op\n", __func__);
+		break;
+	}
+
+	return nextpc;
+
+unaligned:
+	printk("%s: unaligned epc\n", __func__);
+	return nextpc;
+
+sigill:
+	printk("%s: DSP branch but not DSP ASE\n", __func__);
+	return nextpc;
+}
+
+enum emulation_result update_pc(struct kvm_vcpu *vcpu, uint32_t cause)
+{
+	unsigned long branch_pc;
+	enum emulation_result er = EMULATE_DONE;
+
+	if (cause & CAUSEF_BD) {
+		branch_pc = kvm_compute_return_epc(vcpu, vcpu->arch.pc);
+		if (branch_pc == KVM_INVALID_INST) {
+			er = EMULATE_FAIL;
+		} else {
+			vcpu->arch.pc = branch_pc;
+			kvm_debug("BD update_pc(): New PC: %#lx\n", vcpu->arch.pc);
+		}
+	} else
+		vcpu->arch.pc += 4;
+
+	kvm_debug("update_pc(): New PC: %#lx\n", vcpu->arch.pc);
+
+	return er;
+}
+
+/* Everytime the compare register is written to, we need to decide when to fire
+ * the timer that represents timer ticks to the GUEST.
+ *
+ */
+enum emulation_result kvm_mips_emulate_count(struct kvm_vcpu *vcpu)
+{
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+	enum emulation_result er = EMULATE_DONE;
+
+	/* If COUNT is enabled */
+	if (!(kvm_read_c0_guest_cause(cop0) & CAUSEF_DC)) {
+		hrtimer_try_to_cancel(&vcpu->arch.comparecount_timer);
+		hrtimer_start(&vcpu->arch.comparecount_timer,
+			      ktime_set(0, MS_TO_NS(10)), HRTIMER_MODE_REL);
+	} else {
+		hrtimer_try_to_cancel(&vcpu->arch.comparecount_timer);
+	}
+
+	return er;
+}
+
+enum emulation_result kvm_mips_emul_eret(struct kvm_vcpu *vcpu)
+{
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+	enum emulation_result er = EMULATE_DONE;
+
+	if (kvm_read_c0_guest_status(cop0) & ST0_EXL) {
+		kvm_debug("[%#lx] ERET to %#lx\n", vcpu->arch.pc,
+			  kvm_read_c0_guest_epc(cop0));
+		kvm_clear_c0_guest_status(cop0, ST0_EXL);
+		vcpu->arch.pc = kvm_read_c0_guest_epc(cop0);
+
+	} else if (kvm_read_c0_guest_status(cop0) & ST0_ERL) {
+		kvm_clear_c0_guest_status(cop0, ST0_ERL);
+		vcpu->arch.pc = kvm_read_c0_guest_errorepc(cop0);
+	} else {
+		printk("[%#lx] ERET when MIPS_SR_EXL|MIPS_SR_ERL == 0\n",
+		       vcpu->arch.pc);
+		er = EMULATE_FAIL;
+	}
+
+	return er;
+}
+
+enum emulation_result kvm_mips_emul_wait(struct kvm_vcpu *vcpu)
+{
+	enum emulation_result er = EMULATE_DONE;
+
+	kvm_debug("[%#lx] !!!WAIT!!! (%#lx)\n", vcpu->arch.pc,
+		  vcpu->arch.pending_exceptions);
+
+	++vcpu->stat.wait_exits;
+	trace_kvm_exit(vcpu, WAIT_EXITS);
+	if (!vcpu->arch.pending_exceptions) {
+		vcpu->arch.wait = 1;
+		kvm_vcpu_block(vcpu);
+
+		/* We we are runnable, then definitely go off to user space to check if any
+		 * I/O interrupts are pending.
+		 */
+		if (kvm_check_request(KVM_REQ_UNHALT, vcpu)) {
+			clear_bit(KVM_REQ_UNHALT, &vcpu->requests);
+			vcpu->run->exit_reason = KVM_EXIT_IRQ_WINDOW_OPEN;
+		}
+	}
+
+	return er;
+}
+
+/* XXXKYMA: Linux doesn't seem to use TLBR, return EMULATE_FAIL for now so that we can catch
+ * this, if things ever change
+ */
+enum emulation_result kvm_mips_emul_tlbr(struct kvm_vcpu *vcpu)
+{
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+	enum emulation_result er = EMULATE_FAIL;
+	uint32_t pc = vcpu->arch.pc;
+
+	printk("[%#x] COP0_TLBR [%ld]\n", pc, kvm_read_c0_guest_index(cop0));
+	return er;
+}
+
+/* Write Guest TLB Entry @ Index */
+enum emulation_result kvm_mips_emul_tlbwi(struct kvm_vcpu *vcpu)
+{
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+	int index = kvm_read_c0_guest_index(cop0);
+	enum emulation_result er = EMULATE_DONE;
+	struct kvm_mips_tlb *tlb = NULL;
+	uint32_t pc = vcpu->arch.pc;
+
+	if (index < 0 || index >= KVM_MIPS_GUEST_TLB_SIZE) {
+		printk("%s: illegal index: %d\n", __func__, index);
+		printk
+		    ("[%#x] COP0_TLBWI [%d] (entryhi: %#lx, entrylo0: %#lx entrylo1: %#lx, mask: %#lx)\n",
+		     pc, index, kvm_read_c0_guest_entryhi(cop0),
+		     kvm_read_c0_guest_entrylo0(cop0),
+		     kvm_read_c0_guest_entrylo1(cop0),
+		     kvm_read_c0_guest_pagemask(cop0));
+		index = (index & ~0x80000000) % KVM_MIPS_GUEST_TLB_SIZE;
+	}
+
+	tlb = &vcpu->arch.guest_tlb[index];
+#if 1
+	/* Probe the shadow host TLB for the entry being overwritten, if one matches, invalidate it */
+	kvm_mips_host_tlb_inv(vcpu, tlb->tlb_hi);
+#endif
+
+	tlb->tlb_mask = kvm_read_c0_guest_pagemask(cop0);
+	tlb->tlb_hi = kvm_read_c0_guest_entryhi(cop0);
+	tlb->tlb_lo0 = kvm_read_c0_guest_entrylo0(cop0);
+	tlb->tlb_lo1 = kvm_read_c0_guest_entrylo1(cop0);
+
+	kvm_debug
+	    ("[%#x] COP0_TLBWI [%d] (entryhi: %#lx, entrylo0: %#lx entrylo1: %#lx, mask: %#lx)\n",
+	     pc, index, kvm_read_c0_guest_entryhi(cop0),
+	     kvm_read_c0_guest_entrylo0(cop0), kvm_read_c0_guest_entrylo1(cop0),
+	     kvm_read_c0_guest_pagemask(cop0));
+
+	return er;
+}
+
+/* Write Guest TLB Entry @ Random Index */
+enum emulation_result kvm_mips_emul_tlbwr(struct kvm_vcpu *vcpu)
+{
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+	enum emulation_result er = EMULATE_DONE;
+	struct kvm_mips_tlb *tlb = NULL;
+	uint32_t pc = vcpu->arch.pc;
+	int index;
+
+#if 1
+	get_random_bytes(&index, sizeof(index));
+	index &= (KVM_MIPS_GUEST_TLB_SIZE - 1);
+#else
+	index = jiffies % KVM_MIPS_GUEST_TLB_SIZE;
+#endif
+
+	if (index < 0 || index >= KVM_MIPS_GUEST_TLB_SIZE) {
+		printk("%s: illegal index: %d\n", __func__, index);
+		return EMULATE_FAIL;
+	}
+
+	tlb = &vcpu->arch.guest_tlb[index];
+
+#if 1
+	/* Probe the shadow host TLB for the entry being overwritten, if one matches, invalidate it */
+	kvm_mips_host_tlb_inv(vcpu, tlb->tlb_hi);
+#endif
+
+	tlb->tlb_mask = kvm_read_c0_guest_pagemask(cop0);
+	tlb->tlb_hi = kvm_read_c0_guest_entryhi(cop0);
+	tlb->tlb_lo0 = kvm_read_c0_guest_entrylo0(cop0);
+	tlb->tlb_lo1 = kvm_read_c0_guest_entrylo1(cop0);
+
+	kvm_debug
+	    ("[%#x] COP0_TLBWR[%d] (entryhi: %#lx, entrylo0: %#lx entrylo1: %#lx)\n",
+	     pc, index, kvm_read_c0_guest_entryhi(cop0),
+	     kvm_read_c0_guest_entrylo0(cop0),
+	     kvm_read_c0_guest_entrylo1(cop0));
+
+	return er;
+}
+
+enum emulation_result kvm_mips_emul_tlbp(struct kvm_vcpu *vcpu)
+{
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+	long entryhi = kvm_read_c0_guest_entryhi(cop0);
+	enum emulation_result er = EMULATE_DONE;
+	uint32_t pc = vcpu->arch.pc;
+	int index = -1;
+
+	index = kvm_mips_guest_tlb_lookup(vcpu, entryhi);
+
+	kvm_write_c0_guest_index(cop0, index);
+
+	kvm_debug("[%#x] COP0_TLBP (entryhi: %#lx), index: %d\n", pc, entryhi,
+		  index);
+
+	return er;
+}
+
+enum emulation_result
+kvm_mips_emulate_CP0(uint32_t inst, uint32_t *opc, uint32_t cause,
+		     struct kvm_run *run, struct kvm_vcpu *vcpu)
+{
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+	enum emulation_result er = EMULATE_DONE;
+	int32_t rt, rd, copz, sel, co_bit, op;
+	uint32_t pc = vcpu->arch.pc;
+	unsigned long curr_pc;
+
+	/*
+	 * Update PC and hold onto current PC in case there is
+	 * an error and we want to rollback the PC
+	 */
+	curr_pc = vcpu->arch.pc;
+	er = update_pc(vcpu, cause);
+	if (er == EMULATE_FAIL) {
+		return er;
+	}
+
+	copz = (inst >> 21) & 0x1f;
+	rt = (inst >> 16) & 0x1f;
+	rd = (inst >> 11) & 0x1f;
+	sel = inst & 0x7;
+	co_bit = (inst >> 25) & 1;
+
+	/* Verify that the register is valid */
+	if (rd > MIPS_CP0_DESAVE) {
+		printk("Invalid rd: %d\n", rd);
+		er = EMULATE_FAIL;
+		goto done;
+	}
+
+	if (co_bit) {
+		op = (inst) & 0xff;
+
+		switch (op) {
+		case tlbr_op:	/*  Read indexed TLB entry  */
+			er = kvm_mips_emul_tlbr(vcpu);
+			break;
+		case tlbwi_op:	/*  Write indexed  */
+			er = kvm_mips_emul_tlbwi(vcpu);
+			break;
+		case tlbwr_op:	/*  Write random  */
+			er = kvm_mips_emul_tlbwr(vcpu);
+			break;
+		case tlbp_op:	/* TLB Probe */
+			er = kvm_mips_emul_tlbp(vcpu);
+			break;
+		case rfe_op:
+			printk("!!!COP0_RFE!!!\n");
+			break;
+		case eret_op:
+			er = kvm_mips_emul_eret(vcpu);
+			goto dont_update_pc;
+			break;
+		case wait_op:
+			er = kvm_mips_emul_wait(vcpu);
+			break;
+		}
+	} else {
+		switch (copz) {
+		case mfc_op:
+#ifdef CONFIG_KVM_MIPS_DEBUG_COP0_COUNTERS
+			cop0->stat[rd][sel]++;
+#endif
+			/* Get reg */
+			if ((rd == MIPS_CP0_COUNT) && (sel == 0)) {
+				/* XXXKYMA: Run the Guest count register @ 1/4 the rate of the host */
+				vcpu->arch.gprs[rt] = (read_c0_count() >> 2);
+			} else if ((rd == MIPS_CP0_ERRCTL) && (sel == 0)) {
+				vcpu->arch.gprs[rt] = 0x0;
+#ifdef CONFIG_KVM_MIPS_DYN_TRANS
+				kvm_mips_trans_mfc0(inst, opc, vcpu);
+#endif
+			}
+			else {
+				vcpu->arch.gprs[rt] = cop0->reg[rd][sel];
+
+#ifdef CONFIG_KVM_MIPS_DYN_TRANS
+				kvm_mips_trans_mfc0(inst, opc, vcpu);
+#endif
+			}
+
+			kvm_debug
+			    ("[%#x] MFCz[%d][%d], vcpu->arch.gprs[%d]: %#lx\n",
+			     pc, rd, sel, rt, vcpu->arch.gprs[rt]);
+
+			break;
+
+		case dmfc_op:
+			vcpu->arch.gprs[rt] = cop0->reg[rd][sel];
+			break;
+
+		case mtc_op:
+#ifdef CONFIG_KVM_MIPS_DEBUG_COP0_COUNTERS
+			cop0->stat[rd][sel]++;
+#endif
+			if ((rd == MIPS_CP0_TLB_INDEX)
+			    && (vcpu->arch.gprs[rt] >=
+				KVM_MIPS_GUEST_TLB_SIZE)) {
+				printk("Invalid TLB Index: %ld",
+				       vcpu->arch.gprs[rt]);
+				er = EMULATE_FAIL;
+				break;
+			}
+#define C0_EBASE_CORE_MASK 0xff
+			if ((rd == MIPS_CP0_PRID) && (sel == 1)) {
+				/* Preserve CORE number */
+				kvm_change_c0_guest_ebase(cop0,
+							  ~(C0_EBASE_CORE_MASK),
+							  vcpu->arch.gprs[rt]);
+				printk("MTCz, cop0->reg[EBASE]: %#lx\n",
+				       kvm_read_c0_guest_ebase(cop0));
+			} else if (rd == MIPS_CP0_TLB_HI && sel == 0) {
+				uint32_t nasid =
+				    vcpu->arch.gprs[rt] & ASID_MASK;
+				if ((KSEGX(vcpu->arch.gprs[rt]) != CKSEG0)
+				    &&
+				    ((kvm_read_c0_guest_entryhi(cop0) &
+				      ASID_MASK) != nasid)) {
+
+					kvm_debug
+					    ("MTCz, change ASID from %#lx to %#lx\n",
+					     kvm_read_c0_guest_entryhi(cop0) &
+					     ASID_MASK,
+					     vcpu->arch.gprs[rt] & ASID_MASK);
+
+					/* Blow away the shadow host TLBs */
+					kvm_mips_flush_host_tlb(1);
+				}
+				kvm_write_c0_guest_entryhi(cop0,
+							   vcpu->arch.gprs[rt]);
+			}
+			/* Are we writing to COUNT */
+			else if ((rd == MIPS_CP0_COUNT) && (sel == 0)) {
+				/* Linux doesn't seem to write into COUNT, we throw an error
+				 * if we notice a write to COUNT
+				 */
+				/*er = EMULATE_FAIL; */
+				goto done;
+			} else if ((rd == MIPS_CP0_COMPARE) && (sel == 0)) {
+				kvm_debug("[%#x] MTCz, COMPARE %#lx <- %#lx\n",
+					  pc, kvm_read_c0_guest_compare(cop0),
+					  vcpu->arch.gprs[rt]);
+
+				/* If we are writing to COMPARE */
+				/* Clear pending timer interrupt, if any */
+				kvm_mips_callbacks->dequeue_timer_int(vcpu);
+				kvm_write_c0_guest_compare(cop0,
+							   vcpu->arch.gprs[rt]);
+			} else if ((rd == MIPS_CP0_STATUS) && (sel == 0)) {
+				kvm_write_c0_guest_status(cop0,
+							  vcpu->arch.gprs[rt]);
+				/* Make sure that CU1 and NMI bits are never set */
+				kvm_clear_c0_guest_status(cop0,
+							  (ST0_CU1 | ST0_NMI));
+
+#ifdef CONFIG_KVM_MIPS_DYN_TRANS
+				kvm_mips_trans_mtc0(inst, opc, vcpu);
+#endif
+			} else {
+				cop0->reg[rd][sel] = vcpu->arch.gprs[rt];
+#ifdef CONFIG_KVM_MIPS_DYN_TRANS
+				kvm_mips_trans_mtc0(inst, opc, vcpu);
+#endif
+			}
+
+			kvm_debug("[%#x] MTCz, cop0->reg[%d][%d]: %#lx\n", pc,
+				  rd, sel, cop0->reg[rd][sel]);
+			break;
+
+		case dmtc_op:
+			printk
+			    ("!!!!!!![%#lx]dmtc_op: rt: %d, rd: %d, sel: %d!!!!!!\n",
+			     vcpu->arch.pc, rt, rd, sel);
+			er = EMULATE_FAIL;
+			break;
+
+		case mfmcz_op:
+#ifdef KVM_MIPS_DEBUG_COP0_COUNTERS
+			cop0->stat[MIPS_CP0_STATUS][0]++;
+#endif
+			if (rt != 0) {
+				vcpu->arch.gprs[rt] =
+				    kvm_read_c0_guest_status(cop0);
+			}
+			/* EI */
+			if (inst & 0x20) {
+				kvm_debug("[%#lx] mfmcz_op: EI\n",
+					  vcpu->arch.pc);
+				kvm_set_c0_guest_status(cop0, ST0_IE);
+			} else {
+				kvm_debug("[%#lx] mfmcz_op: DI\n",
+					  vcpu->arch.pc);
+				kvm_clear_c0_guest_status(cop0, ST0_IE);
+			}
+
+			break;
+
+		case wrpgpr_op:
+			{
+				uint32_t css =
+				    cop0->reg[MIPS_CP0_STATUS][2] & 0xf;
+				uint32_t pss =
+				    (cop0->reg[MIPS_CP0_STATUS][2] >> 6) & 0xf;
+				/* We don't support any shadow register sets, so SRSCtl[PSS] == SRSCtl[CSS] = 0 */
+				if (css || pss) {
+					er = EMULATE_FAIL;
+					break;
+				}
+				kvm_debug("WRPGPR[%d][%d] = %#lx\n", pss, rd,
+					  vcpu->arch.gprs[rt]);
+				vcpu->arch.gprs[rd] = vcpu->arch.gprs[rt];
+			}
+			break;
+		default:
+			printk
+			    ("[%#lx]MachEmulateCP0: unsupported COP0, copz: 0x%x\n",
+			     vcpu->arch.pc, copz);
+			er = EMULATE_FAIL;
+			break;
+		}
+	}
+
+done:
+	/*
+	 * Rollback PC only if emulation was unsuccessful
+	 */
+	if (er == EMULATE_FAIL) {
+		vcpu->arch.pc = curr_pc;
+	}
+
+dont_update_pc:
+	/*
+	 * This is for special instructions whose emulation
+	 * updates the PC, so do not overwrite the PC under
+	 * any circumstances
+	 */
+
+	return er;
+}
+
+enum emulation_result
+kvm_mips_emulate_store(uint32_t inst, uint32_t cause,
+		       struct kvm_run *run, struct kvm_vcpu *vcpu)
+{
+	enum emulation_result er = EMULATE_DO_MMIO;
+	int32_t op, base, rt, offset;
+	uint32_t bytes;
+	void *data = run->mmio.data;
+	unsigned long curr_pc;
+
+	/*
+	 * Update PC and hold onto current PC in case there is
+	 * an error and we want to rollback the PC
+	 */
+	curr_pc = vcpu->arch.pc;
+	er = update_pc(vcpu, cause);
+	if (er == EMULATE_FAIL)
+		return er;
+
+	rt = (inst >> 16) & 0x1f;
+	base = (inst >> 21) & 0x1f;
+	offset = inst & 0xffff;
+	op = (inst >> 26) & 0x3f;
+
+	switch (op) {
+	case sb_op:
+		bytes = 1;
+		if (bytes > sizeof(run->mmio.data)) {
+			kvm_err("%s: bad MMIO length: %d\n", __func__,
+			       run->mmio.len);
+		}
+		run->mmio.phys_addr =
+		    kvm_mips_callbacks->gva_to_gpa(vcpu->arch.
+						   host_cp0_badvaddr);
+		if (run->mmio.phys_addr == KVM_INVALID_ADDR) {
+			er = EMULATE_FAIL;
+			break;
+		}
+		run->mmio.len = bytes;
+		run->mmio.is_write = 1;
+		vcpu->mmio_needed = 1;
+		vcpu->mmio_is_write = 1;
+		*(u8 *) data = vcpu->arch.gprs[rt];
+		kvm_debug("OP_SB: eaddr: %#lx, gpr: %#lx, data: %#x\n",
+			  vcpu->arch.host_cp0_badvaddr, vcpu->arch.gprs[rt],
+			  *(uint8_t *) data);
+
+		break;
+
+	case sw_op:
+		bytes = 4;
+		if (bytes > sizeof(run->mmio.data)) {
+			kvm_err("%s: bad MMIO length: %d\n", __func__,
+			       run->mmio.len);
+		}
+		run->mmio.phys_addr =
+		    kvm_mips_callbacks->gva_to_gpa(vcpu->arch.
+						   host_cp0_badvaddr);
+		if (run->mmio.phys_addr == KVM_INVALID_ADDR) {
+			er = EMULATE_FAIL;
+			break;
+		}
+
+		run->mmio.len = bytes;
+		run->mmio.is_write = 1;
+		vcpu->mmio_needed = 1;
+		vcpu->mmio_is_write = 1;
+		*(uint32_t *) data = vcpu->arch.gprs[rt];
+
+		kvm_debug("[%#lx] OP_SW: eaddr: %#lx, gpr: %#lx, data: %#x\n",
+			  vcpu->arch.pc, vcpu->arch.host_cp0_badvaddr,
+			  vcpu->arch.gprs[rt], *(uint32_t *) data);
+		break;
+
+	case sh_op:
+		bytes = 2;
+		if (bytes > sizeof(run->mmio.data)) {
+			kvm_err("%s: bad MMIO length: %d\n", __func__,
+			       run->mmio.len);
+		}
+		run->mmio.phys_addr =
+		    kvm_mips_callbacks->gva_to_gpa(vcpu->arch.
+						   host_cp0_badvaddr);
+		if (run->mmio.phys_addr == KVM_INVALID_ADDR) {
+			er = EMULATE_FAIL;
+			break;
+		}
+
+		run->mmio.len = bytes;
+		run->mmio.is_write = 1;
+		vcpu->mmio_needed = 1;
+		vcpu->mmio_is_write = 1;
+		*(uint16_t *) data = vcpu->arch.gprs[rt];
+
+		kvm_debug("[%#lx] OP_SH: eaddr: %#lx, gpr: %#lx, data: %#x\n",
+			  vcpu->arch.pc, vcpu->arch.host_cp0_badvaddr,
+			  vcpu->arch.gprs[rt], *(uint32_t *) data);
+		break;
+
+	default:
+		printk("Store not yet supported");
+		er = EMULATE_FAIL;
+		break;
+	}
+
+	/*
+	 * Rollback PC if emulation was unsuccessful
+	 */
+	if (er == EMULATE_FAIL) {
+		vcpu->arch.pc = curr_pc;
+	}
+
+	return er;
+}
+
+enum emulation_result
+kvm_mips_emulate_load(uint32_t inst, uint32_t cause,
+		      struct kvm_run *run, struct kvm_vcpu *vcpu)
+{
+	enum emulation_result er = EMULATE_DO_MMIO;
+	int32_t op, base, rt, offset;
+	uint32_t bytes;
+
+	rt = (inst >> 16) & 0x1f;
+	base = (inst >> 21) & 0x1f;
+	offset = inst & 0xffff;
+	op = (inst >> 26) & 0x3f;
+
+	vcpu->arch.pending_load_cause = cause;
+	vcpu->arch.io_gpr = rt;
+
+	switch (op) {
+	case lw_op:
+		bytes = 4;
+		if (bytes > sizeof(run->mmio.data)) {
+			kvm_err("%s: bad MMIO length: %d\n", __func__,
+			       run->mmio.len);
+			er = EMULATE_FAIL;
+			break;
+		}
+		run->mmio.phys_addr =
+		    kvm_mips_callbacks->gva_to_gpa(vcpu->arch.
+						   host_cp0_badvaddr);
+		if (run->mmio.phys_addr == KVM_INVALID_ADDR) {
+			er = EMULATE_FAIL;
+			break;
+		}
+
+		run->mmio.len = bytes;
+		run->mmio.is_write = 0;
+		vcpu->mmio_needed = 1;
+		vcpu->mmio_is_write = 0;
+		break;
+
+	case lh_op:
+	case lhu_op:
+		bytes = 2;
+		if (bytes > sizeof(run->mmio.data)) {
+			kvm_err("%s: bad MMIO length: %d\n", __func__,
+			       run->mmio.len);
+			er = EMULATE_FAIL;
+			break;
+		}
+		run->mmio.phys_addr =
+		    kvm_mips_callbacks->gva_to_gpa(vcpu->arch.
+						   host_cp0_badvaddr);
+		if (run->mmio.phys_addr == KVM_INVALID_ADDR) {
+			er = EMULATE_FAIL;
+			break;
+		}
+
+		run->mmio.len = bytes;
+		run->mmio.is_write = 0;
+		vcpu->mmio_needed = 1;
+		vcpu->mmio_is_write = 0;
+
+		if (op == lh_op)
+			vcpu->mmio_needed = 2;
+		else
+			vcpu->mmio_needed = 1;
+
+		break;
+
+	case lbu_op:
+	case lb_op:
+		bytes = 1;
+		if (bytes > sizeof(run->mmio.data)) {
+			kvm_err("%s: bad MMIO length: %d\n", __func__,
+			       run->mmio.len);
+			er = EMULATE_FAIL;
+			break;
+		}
+		run->mmio.phys_addr =
+		    kvm_mips_callbacks->gva_to_gpa(vcpu->arch.
+						   host_cp0_badvaddr);
+		if (run->mmio.phys_addr == KVM_INVALID_ADDR) {
+			er = EMULATE_FAIL;
+			break;
+		}
+
+		run->mmio.len = bytes;
+		run->mmio.is_write = 0;
+		vcpu->mmio_is_write = 0;
+
+		if (op == lb_op)
+			vcpu->mmio_needed = 2;
+		else
+			vcpu->mmio_needed = 1;
+
+		break;
+
+	default:
+		printk("Load not yet supported");
+		er = EMULATE_FAIL;
+		break;
+	}
+
+	return er;
+}
+
+int kvm_mips_sync_icache(unsigned long va, struct kvm_vcpu *vcpu)
+{
+	unsigned long offset = (va & ~PAGE_MASK);
+	struct kvm *kvm = vcpu->kvm;
+	unsigned long pa;
+	gfn_t gfn;
+	pfn_t pfn;
+
+	gfn = va >> PAGE_SHIFT;
+
+	if (gfn >= kvm->arch.guest_pmap_npages) {
+		printk("%s: Invalid gfn: %#llx\n", __func__, gfn);
+		kvm_mips_dump_host_tlbs();
+		kvm_arch_vcpu_dump_regs(vcpu);
+		return -1;
+	}
+	pfn = kvm->arch.guest_pmap[gfn];
+	pa = (pfn << PAGE_SHIFT) | offset;
+
+	printk("%s: va: %#lx, unmapped: %#x\n", __func__, va, CKSEG0ADDR(pa));
+
+	mips32_SyncICache(CKSEG0ADDR(pa), 32);
+	return 0;
+}
+
+#define MIPS_CACHE_OP_INDEX_INV         0x0
+#define MIPS_CACHE_OP_INDEX_LD_TAG      0x1
+#define MIPS_CACHE_OP_INDEX_ST_TAG      0x2
+#define MIPS_CACHE_OP_IMP               0x3
+#define MIPS_CACHE_OP_HIT_INV           0x4
+#define MIPS_CACHE_OP_FILL_WB_INV       0x5
+#define MIPS_CACHE_OP_HIT_HB            0x6
+#define MIPS_CACHE_OP_FETCH_LOCK        0x7
+
+#define MIPS_CACHE_ICACHE               0x0
+#define MIPS_CACHE_DCACHE               0x1
+#define MIPS_CACHE_SEC                  0x3
+
+enum emulation_result
+kvm_mips_emulate_cache(uint32_t inst, uint32_t *opc, uint32_t cause,
+		       struct kvm_run *run, struct kvm_vcpu *vcpu)
+{
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+	extern void (*r4k_blast_dcache) (void);
+	extern void (*r4k_blast_icache) (void);
+	enum emulation_result er = EMULATE_DONE;
+	int32_t offset, cache, op_inst, op, base;
+	struct kvm_vcpu_arch *arch = &vcpu->arch;
+	unsigned long va;
+	unsigned long curr_pc;
+
+	/*
+	 * Update PC and hold onto current PC in case there is
+	 * an error and we want to rollback the PC
+	 */
+	curr_pc = vcpu->arch.pc;
+	er = update_pc(vcpu, cause);
+	if (er == EMULATE_FAIL)
+		return er;
+
+	base = (inst >> 21) & 0x1f;
+	op_inst = (inst >> 16) & 0x1f;
+	offset = inst & 0xffff;
+	cache = (inst >> 16) & 0x3;
+	op = (inst >> 18) & 0x7;
+
+	va = arch->gprs[base] + offset;
+
+	kvm_debug("CACHE (cache: %#x, op: %#x, base[%d]: %#lx, offset: %#x\n",
+		  cache, op, base, arch->gprs[base], offset);
+
+	/* Treat INDEX_INV as a nop, basically issued by Linux on startup to invalidate
+	 * the caches entirely by stepping through all the ways/indexes
+	 */
+	if (op == MIPS_CACHE_OP_INDEX_INV) {
+		kvm_debug
+		    ("@ %#lx/%#lx CACHE (cache: %#x, op: %#x, base[%d]: %#lx, offset: %#x\n",
+		     vcpu->arch.pc, vcpu->arch.gprs[31], cache, op, base,
+		     arch->gprs[base], offset);
+
+		if (cache == MIPS_CACHE_DCACHE)
+			r4k_blast_dcache();
+		else if (cache == MIPS_CACHE_ICACHE)
+			r4k_blast_icache();
+		else {
+			printk("%s: unsupported CACHE INDEX operation\n",
+			       __func__);
+			return EMULATE_FAIL;
+		}
+
+#ifdef CONFIG_KVM_MIPS_DYN_TRANS
+		kvm_mips_trans_cache_index(inst, opc, vcpu);
+#endif
+		goto done;
+	}
+
+	preempt_disable();
+	if (KVM_GUEST_KSEGX(va) == KVM_GUEST_KSEG0) {
+
+		if (kvm_mips_host_tlb_lookup(vcpu, va) < 0) {
+			kvm_mips_handle_kseg0_tlb_fault(va, vcpu);
+		}
+	} else if ((KVM_GUEST_KSEGX(va) < KVM_GUEST_KSEG0) ||
+		   KVM_GUEST_KSEGX(va) == KVM_GUEST_KSEG23) {
+		int index;
+
+		/* If an entry already exists then skip */
+		if (kvm_mips_host_tlb_lookup(vcpu, va) >= 0) {
+			goto skip_fault;
+		}
+
+		/* If address not in the guest TLB, then give the guest a fault, the
+		 * resulting handler will do the right thing
+		 */
+		index = kvm_mips_guest_tlb_lookup(vcpu, (va & VPN2_MASK) |
+						  (kvm_read_c0_guest_entryhi
+						   (cop0) & ASID_MASK));
+
+		if (index < 0) {
+			vcpu->arch.host_cp0_entryhi = (va & VPN2_MASK);
+			vcpu->arch.host_cp0_badvaddr = va;
+			er = kvm_mips_emulate_tlbmiss_ld(cause, NULL, run,
+							 vcpu);
+			preempt_enable();
+			goto dont_update_pc;
+		} else {
+			struct kvm_mips_tlb *tlb = &vcpu->arch.guest_tlb[index];
+			/* Check if the entry is valid, if not then setup a TLB invalid exception to the guest */
+			if (!TLB_IS_VALID(*tlb, va)) {
+				er = kvm_mips_emulate_tlbinv_ld(cause, NULL,
+								run, vcpu);
+				preempt_enable();
+				goto dont_update_pc;
+			} else {
+				/* We fault an entry from the guest tlb to the shadow host TLB */
+				kvm_mips_handle_mapped_seg_tlb_fault(vcpu, tlb,
+								     NULL,
+								     NULL);
+			}
+		}
+	} else {
+		printk
+		    ("INVALID CACHE INDEX/ADDRESS (cache: %#x, op: %#x, base[%d]: %#lx, offset: %#x\n",
+		     cache, op, base, arch->gprs[base], offset);
+		er = EMULATE_FAIL;
+		preempt_enable();
+		goto dont_update_pc;
+
+	}
+
+skip_fault:
+	/* XXXKYMA: Only a subset of cache ops are supported, used by Linux */
+	if (cache == MIPS_CACHE_DCACHE
+	    && (op == MIPS_CACHE_OP_FILL_WB_INV
+		|| op == MIPS_CACHE_OP_HIT_INV)) {
+		flush_dcache_line(va);
+
+#ifdef CONFIG_KVM_MIPS_DYN_TRANS
+		/* Replace the CACHE instruction, with a SYNCI, not the same, but avoids a trap */
+		kvm_mips_trans_cache_va(inst, opc, vcpu);
+#endif
+	} else if (op == MIPS_CACHE_OP_HIT_INV && cache == MIPS_CACHE_ICACHE) {
+		flush_dcache_line(va);
+		flush_icache_line(va);
+
+#ifdef CONFIG_KVM_MIPS_DYN_TRANS
+		/* Replace the CACHE instruction, with a SYNCI */
+		kvm_mips_trans_cache_va(inst, opc, vcpu);
+#endif
+	} else {
+		printk
+		    ("NO-OP CACHE (cache: %#x, op: %#x, base[%d]: %#lx, offset: %#x\n",
+		     cache, op, base, arch->gprs[base], offset);
+		er = EMULATE_FAIL;
+		preempt_enable();
+		goto dont_update_pc;
+	}
+
+	preempt_enable();
+
+      dont_update_pc:
+	/*
+	 * Rollback PC
+	 */
+	vcpu->arch.pc = curr_pc;
+      done:
+	return er;
+}
+
+enum emulation_result
+kvm_mips_emulate_inst(unsigned long cause, uint32_t *opc,
+		      struct kvm_run *run, struct kvm_vcpu *vcpu)
+{
+	enum emulation_result er = EMULATE_DONE;
+	uint32_t inst;
+
+	/*
+	 *  Fetch the instruction.
+	 */
+	if (cause & CAUSEF_BD) {
+		opc += 1;
+	}
+
+	inst = kvm_get_inst(opc, vcpu);
+
+	switch (((union mips_instruction)inst).r_format.opcode) {
+	case cop0_op:
+		er = kvm_mips_emulate_CP0(inst, opc, cause, run, vcpu);
+		break;
+	case sb_op:
+	case sh_op:
+	case sw_op:
+		er = kvm_mips_emulate_store(inst, cause, run, vcpu);
+		break;
+	case lb_op:
+	case lbu_op:
+	case lhu_op:
+	case lh_op:
+	case lw_op:
+		er = kvm_mips_emulate_load(inst, cause, run, vcpu);
+		break;
+
+	case cache_op:
+		++vcpu->stat.cache_exits;
+		trace_kvm_exit(vcpu, CACHE_EXITS);
+		er = kvm_mips_emulate_cache(inst, opc, cause, run, vcpu);
+		break;
+
+	default:
+		printk("Instruction emulation not supported (%p/%#x)\n", opc,
+		       inst);
+		kvm_arch_vcpu_dump_regs(vcpu);
+		er = EMULATE_FAIL;
+		break;
+	}
+
+	return er;
+}
+
+enum emulation_result
+kvm_mips_emulate_syscall(unsigned long cause, uint32_t *opc,
+			 struct kvm_run *run, struct kvm_vcpu *vcpu)
+{
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+	struct kvm_vcpu_arch *arch = &vcpu->arch;
+	enum emulation_result er = EMULATE_DONE;
+
+	if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
+		/* save old pc */
+		kvm_write_c0_guest_epc(cop0, arch->pc);
+		kvm_set_c0_guest_status(cop0, ST0_EXL);
+
+		if (cause & CAUSEF_BD)
+			kvm_set_c0_guest_cause(cop0, CAUSEF_BD);
+		else
+			kvm_clear_c0_guest_cause(cop0, CAUSEF_BD);
+
+		kvm_debug("Delivering SYSCALL @ pc %#lx\n", arch->pc);
+
+		kvm_change_c0_guest_cause(cop0, (0xff),
+					  (T_SYSCALL << CAUSEB_EXCCODE));
+
+		/* Set PC to the exception entry point */
+		arch->pc = KVM_GUEST_KSEG0 + 0x180;
+
+	} else {
+		printk("Trying to deliver SYSCALL when EXL is already set\n");
+		er = EMULATE_FAIL;
+	}
+
+	return er;
+}
+
+enum emulation_result
+kvm_mips_emulate_tlbmiss_ld(unsigned long cause, uint32_t *opc,
+			    struct kvm_run *run, struct kvm_vcpu *vcpu)
+{
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+	struct kvm_vcpu_arch *arch = &vcpu->arch;
+	enum emulation_result er = EMULATE_DONE;
+	unsigned long entryhi = (vcpu->arch.  host_cp0_badvaddr & VPN2_MASK) |
+				(kvm_read_c0_guest_entryhi(cop0) & ASID_MASK);
+
+	if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
+		/* save old pc */
+		kvm_write_c0_guest_epc(cop0, arch->pc);
+		kvm_set_c0_guest_status(cop0, ST0_EXL);
+
+		if (cause & CAUSEF_BD)
+			kvm_set_c0_guest_cause(cop0, CAUSEF_BD);
+		else
+			kvm_clear_c0_guest_cause(cop0, CAUSEF_BD);
+
+		kvm_debug("[EXL == 0] delivering TLB MISS @ pc %#lx\n",
+			  arch->pc);
+
+		/* set pc to the exception entry point */
+		arch->pc = KVM_GUEST_KSEG0 + 0x0;
+
+	} else {
+		kvm_debug("[EXL == 1] delivering TLB MISS @ pc %#lx\n",
+			  arch->pc);
+
+		arch->pc = KVM_GUEST_KSEG0 + 0x180;
+	}
+
+	kvm_change_c0_guest_cause(cop0, (0xff),
+				  (T_TLB_LD_MISS << CAUSEB_EXCCODE));
+
+	/* setup badvaddr, context and entryhi registers for the guest */
+	kvm_write_c0_guest_badvaddr(cop0, vcpu->arch.host_cp0_badvaddr);
+	/* XXXKYMA: is the context register used by linux??? */
+	kvm_write_c0_guest_entryhi(cop0, entryhi);
+	/* Blow away the shadow host TLBs */
+	kvm_mips_flush_host_tlb(1);
+
+	return er;
+}
+
+enum emulation_result
+kvm_mips_emulate_tlbinv_ld(unsigned long cause, uint32_t *opc,
+			   struct kvm_run *run, struct kvm_vcpu *vcpu)
+{
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+	struct kvm_vcpu_arch *arch = &vcpu->arch;
+	enum emulation_result er = EMULATE_DONE;
+	unsigned long entryhi =
+		(vcpu->arch.host_cp0_badvaddr & VPN2_MASK) |
+		(kvm_read_c0_guest_entryhi(cop0) & ASID_MASK);
+
+	if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
+		/* save old pc */
+		kvm_write_c0_guest_epc(cop0, arch->pc);
+		kvm_set_c0_guest_status(cop0, ST0_EXL);
+
+		if (cause & CAUSEF_BD)
+			kvm_set_c0_guest_cause(cop0, CAUSEF_BD);
+		else
+			kvm_clear_c0_guest_cause(cop0, CAUSEF_BD);
+
+		kvm_debug("[EXL == 0] delivering TLB INV @ pc %#lx\n",
+			  arch->pc);
+
+		/* set pc to the exception entry point */
+		arch->pc = KVM_GUEST_KSEG0 + 0x180;
+
+	} else {
+		kvm_debug("[EXL == 1] delivering TLB MISS @ pc %#lx\n",
+			  arch->pc);
+		arch->pc = KVM_GUEST_KSEG0 + 0x180;
+	}
+
+	kvm_change_c0_guest_cause(cop0, (0xff),
+				  (T_TLB_LD_MISS << CAUSEB_EXCCODE));
+
+	/* setup badvaddr, context and entryhi registers for the guest */
+	kvm_write_c0_guest_badvaddr(cop0, vcpu->arch.host_cp0_badvaddr);
+	/* XXXKYMA: is the context register used by linux??? */
+	kvm_write_c0_guest_entryhi(cop0, entryhi);
+	/* Blow away the shadow host TLBs */
+	kvm_mips_flush_host_tlb(1);
+
+	return er;
+}
+
+enum emulation_result
+kvm_mips_emulate_tlbmiss_st(unsigned long cause, uint32_t *opc,
+			    struct kvm_run *run, struct kvm_vcpu *vcpu)
+{
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+	struct kvm_vcpu_arch *arch = &vcpu->arch;
+	enum emulation_result er = EMULATE_DONE;
+	unsigned long entryhi = (vcpu->arch.host_cp0_badvaddr & VPN2_MASK) |
+				(kvm_read_c0_guest_entryhi(cop0) & ASID_MASK);
+
+	if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
+		/* save old pc */
+		kvm_write_c0_guest_epc(cop0, arch->pc);
+		kvm_set_c0_guest_status(cop0, ST0_EXL);
+
+		if (cause & CAUSEF_BD)
+			kvm_set_c0_guest_cause(cop0, CAUSEF_BD);
+		else
+			kvm_clear_c0_guest_cause(cop0, CAUSEF_BD);
+
+		kvm_debug("[EXL == 0] Delivering TLB MISS @ pc %#lx\n",
+			  arch->pc);
+
+		/* Set PC to the exception entry point */
+		arch->pc = KVM_GUEST_KSEG0 + 0x0;
+	} else {
+		kvm_debug("[EXL == 1] Delivering TLB MISS @ pc %#lx\n",
+			  arch->pc);
+		arch->pc = KVM_GUEST_KSEG0 + 0x180;
+	}
+
+	kvm_change_c0_guest_cause(cop0, (0xff),
+				  (T_TLB_ST_MISS << CAUSEB_EXCCODE));
+
+	/* setup badvaddr, context and entryhi registers for the guest */
+	kvm_write_c0_guest_badvaddr(cop0, vcpu->arch.host_cp0_badvaddr);
+	/* XXXKYMA: is the context register used by linux??? */
+	kvm_write_c0_guest_entryhi(cop0, entryhi);
+	/* Blow away the shadow host TLBs */
+	kvm_mips_flush_host_tlb(1);
+
+	return er;
+}
+
+enum emulation_result
+kvm_mips_emulate_tlbinv_st(unsigned long cause, uint32_t *opc,
+			   struct kvm_run *run, struct kvm_vcpu *vcpu)
+{
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+	struct kvm_vcpu_arch *arch = &vcpu->arch;
+	enum emulation_result er = EMULATE_DONE;
+	unsigned long entryhi = (vcpu->arch.host_cp0_badvaddr & VPN2_MASK) |
+		(kvm_read_c0_guest_entryhi(cop0) & ASID_MASK);
+
+	if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
+		/* save old pc */
+		kvm_write_c0_guest_epc(cop0, arch->pc);
+		kvm_set_c0_guest_status(cop0, ST0_EXL);
+
+		if (cause & CAUSEF_BD)
+			kvm_set_c0_guest_cause(cop0, CAUSEF_BD);
+		else
+			kvm_clear_c0_guest_cause(cop0, CAUSEF_BD);
+
+		kvm_debug("[EXL == 0] Delivering TLB MISS @ pc %#lx\n",
+			  arch->pc);
+
+		/* Set PC to the exception entry point */
+		arch->pc = KVM_GUEST_KSEG0 + 0x180;
+	} else {
+		kvm_debug("[EXL == 1] Delivering TLB MISS @ pc %#lx\n",
+			  arch->pc);
+		arch->pc = KVM_GUEST_KSEG0 + 0x180;
+	}
+
+	kvm_change_c0_guest_cause(cop0, (0xff),
+				  (T_TLB_ST_MISS << CAUSEB_EXCCODE));
+
+	/* setup badvaddr, context and entryhi registers for the guest */
+	kvm_write_c0_guest_badvaddr(cop0, vcpu->arch.host_cp0_badvaddr);
+	/* XXXKYMA: is the context register used by linux??? */
+	kvm_write_c0_guest_entryhi(cop0, entryhi);
+	/* Blow away the shadow host TLBs */
+	kvm_mips_flush_host_tlb(1);
+
+	return er;
+}
+
+/* TLBMOD: store into address matching TLB with Dirty bit off */
+enum emulation_result
+kvm_mips_handle_tlbmod(unsigned long cause, uint32_t *opc,
+		       struct kvm_run *run, struct kvm_vcpu *vcpu)
+{
+	enum emulation_result er = EMULATE_DONE;
+
+#ifdef DEBUG
+	/*
+	 * If address not in the guest TLB, then we are in trouble
+	 */
+	index = kvm_mips_guest_tlb_lookup(vcpu, entryhi);
+	if (index < 0) {
+		/* XXXKYMA Invalidate and retry */
+		kvm_mips_host_tlb_inv(vcpu, vcpu->arch.host_cp0_badvaddr);
+		kvm_err("%s: host got TLBMOD for %#lx but entry not present in Guest TLB\n",
+		     __func__, entryhi);
+		kvm_mips_dump_guest_tlbs(vcpu);
+		kvm_mips_dump_host_tlbs();
+		return EMULATE_FAIL;
+	}
+#endif
+
+	er = kvm_mips_emulate_tlbmod(cause, opc, run, vcpu);
+	return er;
+}
+
+enum emulation_result
+kvm_mips_emulate_tlbmod(unsigned long cause, uint32_t *opc,
+			struct kvm_run *run, struct kvm_vcpu *vcpu)
+{
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+	unsigned long entryhi = (vcpu->arch.host_cp0_badvaddr & VPN2_MASK) |
+				(kvm_read_c0_guest_entryhi(cop0) & ASID_MASK);
+	struct kvm_vcpu_arch *arch = &vcpu->arch;
+	enum emulation_result er = EMULATE_DONE;
+
+	if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
+		/* save old pc */
+		kvm_write_c0_guest_epc(cop0, arch->pc);
+		kvm_set_c0_guest_status(cop0, ST0_EXL);
+
+		if (cause & CAUSEF_BD)
+			kvm_set_c0_guest_cause(cop0, CAUSEF_BD);
+		else
+			kvm_clear_c0_guest_cause(cop0, CAUSEF_BD);
+
+		kvm_debug("[EXL == 0] Delivering TLB MOD @ pc %#lx\n",
+			  arch->pc);
+
+		arch->pc = KVM_GUEST_KSEG0 + 0x180;
+	} else {
+		kvm_debug("[EXL == 1] Delivering TLB MOD @ pc %#lx\n",
+			  arch->pc);
+		arch->pc = KVM_GUEST_KSEG0 + 0x180;
+	}
+
+	kvm_change_c0_guest_cause(cop0, (0xff), (T_TLB_MOD << CAUSEB_EXCCODE));
+
+	/* setup badvaddr, context and entryhi registers for the guest */
+	kvm_write_c0_guest_badvaddr(cop0, vcpu->arch.host_cp0_badvaddr);
+	/* XXXKYMA: is the context register used by linux??? */
+	kvm_write_c0_guest_entryhi(cop0, entryhi);
+	/* Blow away the shadow host TLBs */
+	kvm_mips_flush_host_tlb(1);
+
+	return er;
+}
+
+enum emulation_result
+kvm_mips_emulate_fpu_exc(unsigned long cause, uint32_t *opc,
+			 struct kvm_run *run, struct kvm_vcpu *vcpu)
+{
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+	struct kvm_vcpu_arch *arch = &vcpu->arch;
+	enum emulation_result er = EMULATE_DONE;
+
+	if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
+		/* save old pc */
+		kvm_write_c0_guest_epc(cop0, arch->pc);
+		kvm_set_c0_guest_status(cop0, ST0_EXL);
+
+		if (cause & CAUSEF_BD)
+			kvm_set_c0_guest_cause(cop0, CAUSEF_BD);
+		else
+			kvm_clear_c0_guest_cause(cop0, CAUSEF_BD);
+
+	}
+
+	arch->pc = KVM_GUEST_KSEG0 + 0x180;
+
+	kvm_change_c0_guest_cause(cop0, (0xff),
+				  (T_COP_UNUSABLE << CAUSEB_EXCCODE));
+	kvm_change_c0_guest_cause(cop0, (CAUSEF_CE), (0x1 << CAUSEB_CE));
+
+	return er;
+}
+
+enum emulation_result
+kvm_mips_emulate_ri_exc(unsigned long cause, uint32_t *opc,
+			struct kvm_run *run, struct kvm_vcpu *vcpu)
+{
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+	struct kvm_vcpu_arch *arch = &vcpu->arch;
+	enum emulation_result er = EMULATE_DONE;
+
+	if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
+		/* save old pc */
+		kvm_write_c0_guest_epc(cop0, arch->pc);
+		kvm_set_c0_guest_status(cop0, ST0_EXL);
+
+		if (cause & CAUSEF_BD)
+			kvm_set_c0_guest_cause(cop0, CAUSEF_BD);
+		else
+			kvm_clear_c0_guest_cause(cop0, CAUSEF_BD);
+
+		kvm_debug("Delivering RI @ pc %#lx\n", arch->pc);
+
+		kvm_change_c0_guest_cause(cop0, (0xff),
+					  (T_RES_INST << CAUSEB_EXCCODE));
+
+		/* Set PC to the exception entry point */
+		arch->pc = KVM_GUEST_KSEG0 + 0x180;
+
+	} else {
+		kvm_err("Trying to deliver RI when EXL is already set\n");
+		er = EMULATE_FAIL;
+	}
+
+	return er;
+}
+
+enum emulation_result
+kvm_mips_emulate_bp_exc(unsigned long cause, uint32_t *opc,
+			struct kvm_run *run, struct kvm_vcpu *vcpu)
+{
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+	struct kvm_vcpu_arch *arch = &vcpu->arch;
+	enum emulation_result er = EMULATE_DONE;
+
+	if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
+		/* save old pc */
+		kvm_write_c0_guest_epc(cop0, arch->pc);
+		kvm_set_c0_guest_status(cop0, ST0_EXL);
+
+		if (cause & CAUSEF_BD)
+			kvm_set_c0_guest_cause(cop0, CAUSEF_BD);
+		else
+			kvm_clear_c0_guest_cause(cop0, CAUSEF_BD);
+
+		kvm_debug("Delivering BP @ pc %#lx\n", arch->pc);
+
+		kvm_change_c0_guest_cause(cop0, (0xff),
+					  (T_BREAK << CAUSEB_EXCCODE));
+
+		/* Set PC to the exception entry point */
+		arch->pc = KVM_GUEST_KSEG0 + 0x180;
+
+	} else {
+		printk("Trying to deliver BP when EXL is already set\n");
+		er = EMULATE_FAIL;
+	}
+
+	return er;
+}
+
+/*
+ * ll/sc, rdhwr, sync emulation
+ */
+
+#define OPCODE 0xfc000000
+#define BASE   0x03e00000
+#define RT     0x001f0000
+#define OFFSET 0x0000ffff
+#define LL     0xc0000000
+#define SC     0xe0000000
+#define SPEC0  0x00000000
+#define SPEC3  0x7c000000
+#define RD     0x0000f800
+#define FUNC   0x0000003f
+#define SYNC   0x0000000f
+#define RDHWR  0x0000003b
+
+enum emulation_result
+kvm_mips_handle_ri(unsigned long cause, uint32_t *opc,
+		   struct kvm_run *run, struct kvm_vcpu *vcpu)
+{
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+	struct kvm_vcpu_arch *arch = &vcpu->arch;
+	enum emulation_result er = EMULATE_DONE;
+	unsigned long curr_pc;
+	uint32_t inst;
+
+	/*
+	 * Update PC and hold onto current PC in case there is
+	 * an error and we want to rollback the PC
+	 */
+	curr_pc = vcpu->arch.pc;
+	er = update_pc(vcpu, cause);
+	if (er == EMULATE_FAIL)
+		return er;
+
+	/*
+	 *  Fetch the instruction.
+	 */
+	if (cause & CAUSEF_BD)
+		opc += 1;
+
+	inst = kvm_get_inst(opc, vcpu);
+
+	if (inst == KVM_INVALID_INST) {
+		printk("%s: Cannot get inst @ %p\n", __func__, opc);
+		return EMULATE_FAIL;
+	}
+
+	if ((inst & OPCODE) == SPEC3 && (inst & FUNC) == RDHWR) {
+		int rd = (inst & RD) >> 11;
+		int rt = (inst & RT) >> 16;
+		switch (rd) {
+		case 0:	/* CPU number */
+			arch->gprs[rt] = 0;
+			break;
+		case 1:	/* SYNCI length */
+			arch->gprs[rt] = min(current_cpu_data.dcache.linesz,
+					     current_cpu_data.icache.linesz);
+			break;
+		case 2:	/* Read count register */
+			printk("RDHWR: Cont register\n");
+			arch->gprs[rt] = kvm_read_c0_guest_count(cop0);
+			break;
+		case 3:	/* Count register resolution */
+			switch (current_cpu_data.cputype) {
+			case CPU_20KC:
+			case CPU_25KF:
+				arch->gprs[rt] = 1;
+				break;
+			default:
+				arch->gprs[rt] = 2;
+			}
+			break;
+		case 29:
+#if 1
+			arch->gprs[rt] = kvm_read_c0_guest_userlocal(cop0);
+#else
+			/* UserLocal not implemented */
+			er = kvm_mips_emulate_ri_exc(cause, opc, run, vcpu);
+#endif
+			break;
+
+		default:
+			printk("RDHWR not supported\n");
+			er = EMULATE_FAIL;
+			break;
+		}
+	} else {
+		printk("Emulate RI not supported @ %p: %#x\n", opc, inst);
+		er = EMULATE_FAIL;
+	}
+
+	/*
+	 * Rollback PC only if emulation was unsuccessful
+	 */
+	if (er == EMULATE_FAIL) {
+		vcpu->arch.pc = curr_pc;
+	}
+	return er;
+}
+
+enum emulation_result
+kvm_mips_complete_mmio_load(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+	unsigned long *gpr = &vcpu->arch.gprs[vcpu->arch.io_gpr];
+	enum emulation_result er = EMULATE_DONE;
+	unsigned long curr_pc;
+
+	if (run->mmio.len > sizeof(*gpr)) {
+		printk("Bad MMIO length: %d", run->mmio.len);
+		er = EMULATE_FAIL;
+		goto done;
+	}
+
+	/*
+	 * Update PC and hold onto current PC in case there is
+	 * an error and we want to rollback the PC
+	 */
+	curr_pc = vcpu->arch.pc;
+	er = update_pc(vcpu, vcpu->arch.pending_load_cause);
+	if (er == EMULATE_FAIL)
+		return er;
+
+	switch (run->mmio.len) {
+	case 4:
+		*gpr = *(int32_t *) run->mmio.data;
+		break;
+
+	case 2:
+		if (vcpu->mmio_needed == 2)
+			*gpr = *(int16_t *) run->mmio.data;
+		else
+			*gpr = *(int16_t *) run->mmio.data;
+
+		break;
+	case 1:
+		if (vcpu->mmio_needed == 2)
+			*gpr = *(int8_t *) run->mmio.data;
+		else
+			*gpr = *(u8 *) run->mmio.data;
+		break;
+	}
+
+	if (vcpu->arch.pending_load_cause & CAUSEF_BD)
+		kvm_debug
+		    ("[%#lx] Completing %d byte BD Load to gpr %d (0x%08lx) type %d\n",
+		     vcpu->arch.pc, run->mmio.len, vcpu->arch.io_gpr, *gpr,
+		     vcpu->mmio_needed);
+
+done:
+	return er;
+}
+
+static enum emulation_result
+kvm_mips_emulate_exc(unsigned long cause, uint32_t *opc,
+		     struct kvm_run *run, struct kvm_vcpu *vcpu)
+{
+	uint32_t exccode = (cause >> CAUSEB_EXCCODE) & 0x1f;
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+	struct kvm_vcpu_arch *arch = &vcpu->arch;
+	enum emulation_result er = EMULATE_DONE;
+
+	if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
+		/* save old pc */
+		kvm_write_c0_guest_epc(cop0, arch->pc);
+		kvm_set_c0_guest_status(cop0, ST0_EXL);
+
+		if (cause & CAUSEF_BD)
+			kvm_set_c0_guest_cause(cop0, CAUSEF_BD);
+		else
+			kvm_clear_c0_guest_cause(cop0, CAUSEF_BD);
+
+		kvm_change_c0_guest_cause(cop0, (0xff),
+					  (exccode << CAUSEB_EXCCODE));
+
+		/* Set PC to the exception entry point */
+		arch->pc = KVM_GUEST_KSEG0 + 0x180;
+		kvm_write_c0_guest_badvaddr(cop0, vcpu->arch.host_cp0_badvaddr);
+
+		kvm_debug("Delivering EXC %d @ pc %#lx, badVaddr: %#lx\n",
+			  exccode, kvm_read_c0_guest_epc(cop0),
+			  kvm_read_c0_guest_badvaddr(cop0));
+	} else {
+		printk("Trying to deliver EXC when EXL is already set\n");
+		er = EMULATE_FAIL;
+	}
+
+	return er;
+}
+
+enum emulation_result
+kvm_mips_check_privilege(unsigned long cause, uint32_t *opc,
+			 struct kvm_run *run, struct kvm_vcpu *vcpu)
+{
+	enum emulation_result er = EMULATE_DONE;
+	uint32_t exccode = (cause >> CAUSEB_EXCCODE) & 0x1f;
+	unsigned long badvaddr = vcpu->arch.host_cp0_badvaddr;
+
+	int usermode = !KVM_GUEST_KERNEL_MODE(vcpu);
+
+	if (usermode) {
+		switch (exccode) {
+		case T_INT:
+		case T_SYSCALL:
+		case T_BREAK:
+		case T_RES_INST:
+			break;
+
+		case T_COP_UNUSABLE:
+			if (((cause & CAUSEF_CE) >> CAUSEB_CE) == 0)
+				er = EMULATE_PRIV_FAIL;
+			break;
+
+		case T_TLB_MOD:
+			break;
+
+		case T_TLB_LD_MISS:
+			/* We we are accessing Guest kernel space, then send an address error exception to the guest */
+			if (badvaddr >= (unsigned long) KVM_GUEST_KSEG0) {
+				printk("%s: LD MISS @ %#lx\n", __func__,
+				       badvaddr);
+				cause &= ~0xff;
+				cause |= (T_ADDR_ERR_LD << CAUSEB_EXCCODE);
+				er = EMULATE_PRIV_FAIL;
+			}
+			break;
+
+		case T_TLB_ST_MISS:
+			/* We we are accessing Guest kernel space, then send an address error exception to the guest */
+			if (badvaddr >= (unsigned long) KVM_GUEST_KSEG0) {
+				printk("%s: ST MISS @ %#lx\n", __func__,
+				       badvaddr);
+				cause &= ~0xff;
+				cause |= (T_ADDR_ERR_ST << CAUSEB_EXCCODE);
+				er = EMULATE_PRIV_FAIL;
+			}
+			break;
+
+		case T_ADDR_ERR_ST:
+			printk("%s: address error ST @ %#lx\n", __func__,
+			       badvaddr);
+			if ((badvaddr & PAGE_MASK) == KVM_GUEST_COMMPAGE_ADDR) {
+				cause &= ~0xff;
+				cause |= (T_TLB_ST_MISS << CAUSEB_EXCCODE);
+			}
+			er = EMULATE_PRIV_FAIL;
+			break;
+		case T_ADDR_ERR_LD:
+			printk("%s: address error LD @ %#lx\n", __func__,
+			       badvaddr);
+			if ((badvaddr & PAGE_MASK) == KVM_GUEST_COMMPAGE_ADDR) {
+				cause &= ~0xff;
+				cause |= (T_TLB_LD_MISS << CAUSEB_EXCCODE);
+			}
+			er = EMULATE_PRIV_FAIL;
+			break;
+		default:
+			er = EMULATE_PRIV_FAIL;
+			break;
+		}
+	}
+
+	if (er == EMULATE_PRIV_FAIL) {
+		kvm_mips_emulate_exc(cause, opc, run, vcpu);
+	}
+	return er;
+}
+
+/* User Address (UA) fault, this could happen if
+ * (1) TLB entry not present/valid in both Guest and shadow host TLBs, in this
+ *     case we pass on the fault to the guest kernel and let it handle it.
+ * (2) TLB entry is present in the Guest TLB but not in the shadow, in this
+ *     case we inject the TLB from the Guest TLB into the shadow host TLB
+ */
+enum emulation_result
+kvm_mips_handle_tlbmiss(unsigned long cause, uint32_t *opc,
+			struct kvm_run *run, struct kvm_vcpu *vcpu)
+{
+	enum emulation_result er = EMULATE_DONE;
+	uint32_t exccode = (cause >> CAUSEB_EXCCODE) & 0x1f;
+	unsigned long va = vcpu->arch.host_cp0_badvaddr;
+	int index;
+
+	kvm_debug("kvm_mips_handle_tlbmiss: badvaddr: %#lx, entryhi: %#lx\n",
+		  vcpu->arch.host_cp0_badvaddr, vcpu->arch.host_cp0_entryhi);
+
+	/* KVM would not have got the exception if this entry was valid in the shadow host TLB
+	 * Check the Guest TLB, if the entry is not there then send the guest an
+	 * exception. The guest exc handler should then inject an entry into the
+	 * guest TLB
+	 */
+	index = kvm_mips_guest_tlb_lookup(vcpu,
+					  (va & VPN2_MASK) |
+					  (kvm_read_c0_guest_entryhi
+					   (vcpu->arch.cop0) & ASID_MASK));
+	if (index < 0) {
+		if (exccode == T_TLB_LD_MISS) {
+			er = kvm_mips_emulate_tlbmiss_ld(cause, opc, run, vcpu);
+		} else if (exccode == T_TLB_ST_MISS) {
+			er = kvm_mips_emulate_tlbmiss_st(cause, opc, run, vcpu);
+		} else {
+			printk("%s: invalid exc code: %d\n", __func__, exccode);
+			er = EMULATE_FAIL;
+		}
+	} else {
+		struct kvm_mips_tlb *tlb = &vcpu->arch.guest_tlb[index];
+
+		/* Check if the entry is valid, if not then setup a TLB invalid exception to the guest */
+		if (!TLB_IS_VALID(*tlb, va)) {
+			if (exccode == T_TLB_LD_MISS) {
+				er = kvm_mips_emulate_tlbinv_ld(cause, opc, run,
+								vcpu);
+			} else if (exccode == T_TLB_ST_MISS) {
+				er = kvm_mips_emulate_tlbinv_st(cause, opc, run,
+								vcpu);
+			} else {
+				printk("%s: invalid exc code: %d\n", __func__,
+				       exccode);
+				er = EMULATE_FAIL;
+			}
+		} else {
+#ifdef DEBUG
+			kvm_debug
+			    ("Injecting hi: %#lx, lo0: %#lx, lo1: %#lx into shadow host TLB\n",
+			     tlb->tlb_hi, tlb->tlb_lo0, tlb->tlb_lo1);
+#endif
+			/* OK we have a Guest TLB entry, now inject it into the shadow host TLB */
+			kvm_mips_handle_mapped_seg_tlb_fault(vcpu, tlb, NULL,
+							     NULL);
+		}
+	}
+
+	return er;
+}
diff --git a/arch/mips/kvm/kvm_mips_int.c b/arch/mips/kvm/kvm_mips_int.c
new file mode 100644
index 0000000..1e5de16
--- /dev/null
+++ b/arch/mips/kvm/kvm_mips_int.c
@@ -0,0 +1,243 @@
+/*
+* 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.
+*
+* KVM/MIPS: Interrupt delivery
+*
+* Copyright (C) 2012  MIPS Technologies, Inc.  All rights reserved.
+* Authors: Sanjay Lal <sanjayl@kymasys.com>
+*/
+
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+#include <linux/fs.h>
+#include <linux/bootmem.h>
+#include <asm/page.h>
+#include <asm/cacheflush.h>
+
+#include <linux/kvm_host.h>
+
+#include "kvm_mips_int.h"
+
+void kvm_mips_queue_irq(struct kvm_vcpu *vcpu, uint32_t priority)
+{
+	set_bit(priority, &vcpu->arch.pending_exceptions);
+}
+
+void kvm_mips_dequeue_irq(struct kvm_vcpu *vcpu, uint32_t priority)
+{
+	clear_bit(priority, &vcpu->arch.pending_exceptions);
+}
+
+void kvm_mips_queue_timer_int_cb(struct kvm_vcpu *vcpu)
+{
+	/* Cause bits to reflect the pending timer interrupt,
+	 * the EXC code will be set when we are actually
+	 * delivering the interrupt:
+	 */
+	kvm_set_c0_guest_cause(vcpu->arch.cop0, (C_IRQ5 | C_TI));
+
+	/* Queue up an INT exception for the core */
+	kvm_mips_queue_irq(vcpu, MIPS_EXC_INT_TIMER);
+
+}
+
+void kvm_mips_dequeue_timer_int_cb(struct kvm_vcpu *vcpu)
+{
+	kvm_clear_c0_guest_cause(vcpu->arch.cop0, (C_IRQ5 | C_TI));
+	kvm_mips_dequeue_irq(vcpu, MIPS_EXC_INT_TIMER);
+}
+
+void
+kvm_mips_queue_io_int_cb(struct kvm_vcpu *vcpu, struct kvm_mips_interrupt *irq)
+{
+	int intr = (int)irq->irq;
+
+	/* Cause bits to reflect the pending IO interrupt,
+	 * the EXC code will be set when we are actually
+	 * delivering the interrupt:
+	 */
+	switch (intr) {
+	case 2:
+		kvm_set_c0_guest_cause(vcpu->arch.cop0, (C_IRQ0));
+		/* Queue up an INT exception for the core */
+		kvm_mips_queue_irq(vcpu, MIPS_EXC_INT_IO);
+		break;
+
+	case 3:
+		kvm_set_c0_guest_cause(vcpu->arch.cop0, (C_IRQ1));
+		kvm_mips_queue_irq(vcpu, MIPS_EXC_INT_IPI_1);
+		break;
+
+	case 4:
+		kvm_set_c0_guest_cause(vcpu->arch.cop0, (C_IRQ2));
+		kvm_mips_queue_irq(vcpu, MIPS_EXC_INT_IPI_2);
+		break;
+
+	default:
+		break;
+	}
+
+}
+
+void
+kvm_mips_dequeue_io_int_cb(struct kvm_vcpu *vcpu,
+			   struct kvm_mips_interrupt *irq)
+{
+	int intr = (int)irq->irq;
+	switch (intr) {
+	case -2:
+		kvm_clear_c0_guest_cause(vcpu->arch.cop0, (C_IRQ0));
+		kvm_mips_dequeue_irq(vcpu, MIPS_EXC_INT_IO);
+		break;
+
+	case -3:
+		kvm_clear_c0_guest_cause(vcpu->arch.cop0, (C_IRQ1));
+		kvm_mips_dequeue_irq(vcpu, MIPS_EXC_INT_IPI_1);
+		break;
+
+	case -4:
+		kvm_clear_c0_guest_cause(vcpu->arch.cop0, (C_IRQ2));
+		kvm_mips_dequeue_irq(vcpu, MIPS_EXC_INT_IPI_2);
+		break;
+
+	default:
+		break;
+	}
+
+}
+
+/* Deliver the interrupt of the corresponding priority, if possible. */
+int
+kvm_mips_irq_deliver_cb(struct kvm_vcpu *vcpu, unsigned int priority,
+			uint32_t cause)
+{
+	int allowed = 0;
+	uint32_t exccode;
+
+	struct kvm_vcpu_arch *arch = &vcpu->arch;
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+
+	switch (priority) {
+	case MIPS_EXC_INT_TIMER:
+		if ((kvm_read_c0_guest_status(cop0) & ST0_IE)
+		    && (!(kvm_read_c0_guest_status(cop0) & (ST0_EXL | ST0_ERL)))
+		    && (kvm_read_c0_guest_status(cop0) & IE_IRQ5)) {
+			allowed = 1;
+			exccode = T_INT;
+		}
+		break;
+
+	case MIPS_EXC_INT_IO:
+		if ((kvm_read_c0_guest_status(cop0) & ST0_IE)
+		    && (!(kvm_read_c0_guest_status(cop0) & (ST0_EXL | ST0_ERL)))
+		    && (kvm_read_c0_guest_status(cop0) & IE_IRQ0)) {
+			allowed = 1;
+			exccode = T_INT;
+		}
+		break;
+
+	case MIPS_EXC_INT_IPI_1:
+		if ((kvm_read_c0_guest_status(cop0) & ST0_IE)
+		    && (!(kvm_read_c0_guest_status(cop0) & (ST0_EXL | ST0_ERL)))
+		    && (kvm_read_c0_guest_status(cop0) & IE_IRQ1)) {
+			allowed = 1;
+			exccode = T_INT;
+		}
+		break;
+
+	case MIPS_EXC_INT_IPI_2:
+		if ((kvm_read_c0_guest_status(cop0) & ST0_IE)
+		    && (!(kvm_read_c0_guest_status(cop0) & (ST0_EXL | ST0_ERL)))
+		    && (kvm_read_c0_guest_status(cop0) & IE_IRQ2)) {
+			allowed = 1;
+			exccode = T_INT;
+		}
+		break;
+
+	default:
+		break;
+	}
+
+	/* Are we allowed to deliver the interrupt ??? */
+	if (allowed) {
+
+		if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
+			/* save old pc */
+			kvm_write_c0_guest_epc(cop0, arch->pc);
+			kvm_set_c0_guest_status(cop0, ST0_EXL);
+
+			if (cause & CAUSEF_BD)
+				kvm_set_c0_guest_cause(cop0, CAUSEF_BD);
+			else
+				kvm_clear_c0_guest_cause(cop0, CAUSEF_BD);
+
+			kvm_debug("Delivering INT @ pc %#lx\n", arch->pc);
+
+		} else
+			kvm_err("Trying to deliver interrupt when EXL is already set\n");
+
+		kvm_change_c0_guest_cause(cop0, CAUSEF_EXCCODE,
+					  (exccode << CAUSEB_EXCCODE));
+
+		/* XXXSL Set PC to the interrupt exception entry point */
+		if (kvm_read_c0_guest_cause(cop0) & CAUSEF_IV)
+			arch->pc = KVM_GUEST_KSEG0 + 0x200;
+		else
+			arch->pc = KVM_GUEST_KSEG0 + 0x180;
+
+		clear_bit(priority, &vcpu->arch.pending_exceptions);
+	}
+
+	return allowed;
+}
+
+int
+kvm_mips_irq_clear_cb(struct kvm_vcpu *vcpu, unsigned int priority,
+		      uint32_t cause)
+{
+	return 1;
+}
+
+void kvm_mips_deliver_interrupts(struct kvm_vcpu *vcpu, uint32_t cause)
+{
+	unsigned long *pending = &vcpu->arch.pending_exceptions;
+	unsigned long *pending_clr = &vcpu->arch.pending_exceptions_clr;
+	unsigned int priority;
+
+	if (!(*pending) && !(*pending_clr))
+		return;
+
+	priority = __ffs(*pending_clr);
+	while (priority <= MIPS_EXC_MAX) {
+		if (kvm_mips_callbacks->irq_clear(vcpu, priority, cause)) {
+			if (!KVM_MIPS_IRQ_CLEAR_ALL_AT_ONCE)
+				break;
+		}
+
+		priority = find_next_bit(pending_clr,
+					 BITS_PER_BYTE * sizeof(*pending_clr),
+					 priority + 1);
+	}
+
+	priority = __ffs(*pending);
+	while (priority <= MIPS_EXC_MAX) {
+		if (kvm_mips_callbacks->irq_deliver(vcpu, priority, cause)) {
+			if (!KVM_MIPS_IRQ_DELIVER_ALL_AT_ONCE)
+				break;
+		}
+
+		priority = find_next_bit(pending,
+					 BITS_PER_BYTE * sizeof(*pending),
+					 priority + 1);
+	}
+
+}
+
+int kvm_mips_pending_timer(struct kvm_vcpu *vcpu)
+{
+	return test_bit(MIPS_EXC_INT_TIMER, &vcpu->arch.pending_exceptions);
+}
diff --git a/arch/mips/kvm/kvm_mips_int.h b/arch/mips/kvm/kvm_mips_int.h
new file mode 100644
index 0000000..20da7d2
--- /dev/null
+++ b/arch/mips/kvm/kvm_mips_int.h
@@ -0,0 +1,49 @@
+/*
+* 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.
+*
+* KVM/MIPS: Interrupts
+* Copyright (C) 2012  MIPS Technologies, Inc.  All rights reserved.
+* Authors: Sanjay Lal <sanjayl@kymasys.com>
+*/
+
+/* MIPS Exception Priorities, exceptions (including interrupts) are queued up
+ * for the guest in the order specified by their priorities
+ */
+
+#define MIPS_EXC_RESET              0
+#define MIPS_EXC_SRESET             1
+#define MIPS_EXC_DEBUG_ST           2
+#define MIPS_EXC_DEBUG              3
+#define MIPS_EXC_DDB                4
+#define MIPS_EXC_NMI                5
+#define MIPS_EXC_MCHK               6
+#define MIPS_EXC_INT_TIMER          7
+#define MIPS_EXC_INT_IO             8
+#define MIPS_EXC_EXECUTE            9
+#define MIPS_EXC_INT_IPI_1          10
+#define MIPS_EXC_INT_IPI_2          11
+#define MIPS_EXC_MAX                12
+/* XXXSL More to follow */
+
+#define C_TI        (_ULCAST_(1) << 30)
+
+#define KVM_MIPS_IRQ_DELIVER_ALL_AT_ONCE (0)
+#define KVM_MIPS_IRQ_CLEAR_ALL_AT_ONCE   (0)
+
+void kvm_mips_queue_irq(struct kvm_vcpu *vcpu, uint32_t priority);
+void kvm_mips_dequeue_irq(struct kvm_vcpu *vcpu, uint32_t priority);
+int kvm_mips_pending_timer(struct kvm_vcpu *vcpu);
+
+void kvm_mips_queue_timer_int_cb(struct kvm_vcpu *vcpu);
+void kvm_mips_dequeue_timer_int_cb(struct kvm_vcpu *vcpu);
+void kvm_mips_queue_io_int_cb(struct kvm_vcpu *vcpu,
+			      struct kvm_mips_interrupt *irq);
+void kvm_mips_dequeue_io_int_cb(struct kvm_vcpu *vcpu,
+				struct kvm_mips_interrupt *irq);
+int kvm_mips_irq_deliver_cb(struct kvm_vcpu *vcpu, unsigned int priority,
+			    uint32_t cause);
+int kvm_mips_irq_clear_cb(struct kvm_vcpu *vcpu, unsigned int priority,
+			  uint32_t cause);
+void kvm_mips_deliver_interrupts(struct kvm_vcpu *vcpu, uint32_t cause);
diff --git a/arch/mips/kvm/kvm_mips_opcode.h b/arch/mips/kvm/kvm_mips_opcode.h
new file mode 100644
index 0000000..86d3b4c
--- /dev/null
+++ b/arch/mips/kvm/kvm_mips_opcode.h
@@ -0,0 +1,24 @@
+/*
+* 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) 2012  MIPS Technologies, Inc.  All rights reserved.
+* Authors: Sanjay Lal <sanjayl@kymasys.com>
+*/
+
+/*
+ * Define opcode values not defined in <asm/isnt.h>
+ */
+
+#ifndef __KVM_MIPS_OPCODE_H__
+#define __KVM_MIPS_OPCODE_H__
+
+/* COP0 Ops */
+#define     mfmcz_op         0x0b	/*  01011  */
+#define     wrpgpr_op        0x0e	/*  01110  */
+
+/*  COP0 opcodes (only if COP0 and CO=1):  */
+#define     wait_op               0x20	/*  100000  */
+
+#endif /* __KVM_MIPS_OPCODE_H__ */
diff --git a/arch/mips/kvm/kvm_mips_stats.c b/arch/mips/kvm/kvm_mips_stats.c
new file mode 100644
index 0000000..075904b
--- /dev/null
+++ b/arch/mips/kvm/kvm_mips_stats.c
@@ -0,0 +1,82 @@
+/*
+* 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.
+*
+* KVM/MIPS: COP0 access histogram
+*
+* Copyright (C) 2012  MIPS Technologies, Inc.  All rights reserved.
+* Authors: Sanjay Lal <sanjayl@kymasys.com>
+*/
+
+#include <linux/kvm_host.h>
+
+char *kvm_mips_exit_types_str[MAX_KVM_MIPS_EXIT_TYPES] = {
+	"WAIT",
+	"CACHE",
+	"Signal",
+	"Interrupt",
+	"COP0/1 Unusable",
+	"TLB Mod",
+	"TLB Miss (LD)",
+	"TLB Miss (ST)",
+	"Address Err (ST)",
+	"Address Error (LD)",
+	"System Call",
+	"Reserved Inst",
+	"Break Inst",
+	"D-Cache Flushes",
+};
+
+char *kvm_cop0_str[N_MIPS_COPROC_REGS] = {
+	"Index",
+	"Random",
+	"EntryLo0",
+	"EntryLo1",
+	"Context",
+	"PG Mask",
+	"Wired",
+	"HWREna",
+	"BadVAddr",
+	"Count",
+	"EntryHI",
+	"Compare",
+	"Status",
+	"Cause",
+	"EXC PC",
+	"PRID",
+	"Config",
+	"LLAddr",
+	"Watch Lo",
+	"Watch Hi",
+	"X Context",
+	"Reserved",
+	"Impl Dep",
+	"Debug",
+	"DEPC",
+	"PerfCnt",
+	"ErrCtl",
+	"CacheErr",
+	"TagLo",
+	"TagHi",
+	"ErrorEPC",
+	"DESAVE"
+};
+
+int kvm_mips_dump_stats(struct kvm_vcpu *vcpu)
+{
+#ifdef CONFIG_KVM_MIPS_DEBUG_COP0_COUNTERS
+	int i, j;
+
+	printk("\nKVM VCPU[%d] COP0 Access Profile:\n", vcpu->vcpu_id);
+	for (i = 0; i < N_MIPS_COPROC_REGS; i++) {
+		for (j = 0; j < N_MIPS_COPROC_SEL; j++) {
+			if (vcpu->arch.cop0->stat[i][j])
+				printk("%s[%d]: %lu\n", kvm_cop0_str[i], j,
+				       vcpu->arch.cop0->stat[i][j]);
+		}
+	}
+#endif
+
+	return 0;
+}
diff --git a/arch/mips/kvm/kvm_tlb.c b/arch/mips/kvm/kvm_tlb.c
new file mode 100644
index 0000000..e3f0d9b
--- /dev/null
+++ b/arch/mips/kvm/kvm_tlb.c
@@ -0,0 +1,932 @@
+/*
+* 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.
+*
+* KVM/MIPS TLB handling, this file is part of the Linux host kernel so that
+* TLB handlers run from KSEG0
+*
+* Copyright (C) 2012  MIPS Technologies, Inc.  All rights reserved.
+* Authors: Sanjay Lal <sanjayl@kymasys.com>
+*/
+
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/kvm_host.h>
+
+#include <asm/cpu.h>
+#include <asm/bootinfo.h>
+#include <asm/mmu_context.h>
+#include <asm/pgtable.h>
+#include <asm/cacheflush.h>
+
+#undef CONFIG_MIPS_MT
+#include <asm/r4kcache.h>
+#define CONFIG_MIPS_MT
+
+#define KVM_GUEST_PC_TLB    0
+#define KVM_GUEST_SP_TLB    1
+
+#define PRIx64 "llx"
+
+/* Use VZ EntryHi.EHINV to invalidate TLB entries */
+#define UNIQUE_ENTRYHI(idx) (CKSEG0 + ((idx) << (PAGE_SHIFT + 1)))
+
+atomic_t kvm_mips_instance;
+EXPORT_SYMBOL(kvm_mips_instance);
+
+/* These function pointers are initialized once the KVM module is loaded */
+pfn_t(*kvm_mips_gfn_to_pfn) (struct kvm *kvm, gfn_t gfn);
+EXPORT_SYMBOL(kvm_mips_gfn_to_pfn);
+
+void (*kvm_mips_release_pfn_clean) (pfn_t pfn);
+EXPORT_SYMBOL(kvm_mips_release_pfn_clean);
+
+bool(*kvm_mips_is_error_pfn) (pfn_t pfn);
+EXPORT_SYMBOL(kvm_mips_is_error_pfn);
+
+uint32_t kvm_mips_get_kernel_asid(struct kvm_vcpu *vcpu)
+{
+	return vcpu->arch.guest_kernel_asid[smp_processor_id()] & ASID_MASK;
+}
+
+
+uint32_t kvm_mips_get_user_asid(struct kvm_vcpu *vcpu)
+{
+	return vcpu->arch.guest_user_asid[smp_processor_id()] & ASID_MASK;
+}
+
+inline uint32_t kvm_mips_get_commpage_asid (struct kvm_vcpu *vcpu)
+{
+	return vcpu->kvm->arch.commpage_tlb;
+}
+
+
+/*
+ * Structure defining an tlb entry data set.
+ */
+
+void kvm_mips_dump_host_tlbs(void)
+{
+	unsigned long old_entryhi;
+	unsigned long old_pagemask;
+	struct kvm_mips_tlb tlb;
+	unsigned long flags;
+	int i;
+
+	local_irq_save(flags);
+
+	old_entryhi = read_c0_entryhi();
+	old_pagemask = read_c0_pagemask();
+
+	printk("HOST TLBs:\n");
+	printk("ASID: %#lx\n", read_c0_entryhi() & ASID_MASK);
+
+	for (i = 0; i < current_cpu_data.tlbsize; i++) {
+		write_c0_index(i);
+		mtc0_tlbw_hazard();
+
+		tlb_read();
+		tlbw_use_hazard();
+
+		tlb.tlb_hi = read_c0_entryhi();
+		tlb.tlb_lo0 = read_c0_entrylo0();
+		tlb.tlb_lo1 = read_c0_entrylo1();
+		tlb.tlb_mask = read_c0_pagemask();
+
+		printk("TLB%c%3d Hi 0x%08lx ",
+		       (tlb.tlb_lo0 | tlb.tlb_lo1) & MIPS3_PG_V ? ' ' : '*',
+		       i, tlb.tlb_hi);
+		printk("Lo0=0x%09" PRIx64 " %c%c attr %lx ",
+		       (uint64_t) mips3_tlbpfn_to_paddr(tlb.tlb_lo0),
+		       (tlb.tlb_lo0 & MIPS3_PG_D) ? 'D' : ' ',
+		       (tlb.tlb_lo0 & MIPS3_PG_G) ? 'G' : ' ',
+		       (tlb.tlb_lo0 >> 3) & 7);
+		printk("Lo1=0x%09" PRIx64 " %c%c attr %lx sz=%lx\n",
+		       (uint64_t) mips3_tlbpfn_to_paddr(tlb.tlb_lo1),
+		       (tlb.tlb_lo1 & MIPS3_PG_D) ? 'D' : ' ',
+		       (tlb.tlb_lo1 & MIPS3_PG_G) ? 'G' : ' ',
+		       (tlb.tlb_lo1 >> 3) & 7, tlb.tlb_mask);
+	}
+	write_c0_entryhi(old_entryhi);
+	write_c0_pagemask(old_pagemask);
+	mtc0_tlbw_hazard();
+	local_irq_restore(flags);
+}
+
+void kvm_mips_dump_guest_tlbs(struct kvm_vcpu *vcpu)
+{
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+	struct kvm_mips_tlb tlb;
+	int i;
+
+	printk("Guest TLBs:\n");
+	printk("Guest EntryHi: %#lx\n", kvm_read_c0_guest_entryhi(cop0));
+
+	for (i = 0; i < KVM_MIPS_GUEST_TLB_SIZE; i++) {
+		tlb = vcpu->arch.guest_tlb[i];
+		printk("TLB%c%3d Hi 0x%08lx ",
+		       (tlb.tlb_lo0 | tlb.tlb_lo1) & MIPS3_PG_V ? ' ' : '*',
+		       i, tlb.tlb_hi);
+		printk("Lo0=0x%09" PRIx64 " %c%c attr %lx ",
+		       (uint64_t) mips3_tlbpfn_to_paddr(tlb.tlb_lo0),
+		       (tlb.tlb_lo0 & MIPS3_PG_D) ? 'D' : ' ',
+		       (tlb.tlb_lo0 & MIPS3_PG_G) ? 'G' : ' ',
+		       (tlb.tlb_lo0 >> 3) & 7);
+		printk("Lo1=0x%09" PRIx64 " %c%c attr %lx sz=%lx\n",
+		       (uint64_t) mips3_tlbpfn_to_paddr(tlb.tlb_lo1),
+		       (tlb.tlb_lo1 & MIPS3_PG_D) ? 'D' : ' ',
+		       (tlb.tlb_lo1 & MIPS3_PG_G) ? 'G' : ' ',
+		       (tlb.tlb_lo1 >> 3) & 7, tlb.tlb_mask);
+	}
+}
+
+void kvm_mips_dump_shadow_tlbs(struct kvm_vcpu *vcpu)
+{
+	int i;
+	volatile struct kvm_mips_tlb tlb;
+
+	printk("Shadow TLBs:\n");
+	for (i = 0; i < KVM_MIPS_GUEST_TLB_SIZE; i++) {
+		tlb = vcpu->arch.shadow_tlb[smp_processor_id()][i];
+		printk("TLB%c%3d Hi 0x%08lx ",
+		       (tlb.tlb_lo0 | tlb.tlb_lo1) & MIPS3_PG_V ? ' ' : '*',
+		       i, tlb.tlb_hi);
+		printk("Lo0=0x%09" PRIx64 " %c%c attr %lx ",
+		       (uint64_t) mips3_tlbpfn_to_paddr(tlb.tlb_lo0),
+		       (tlb.tlb_lo0 & MIPS3_PG_D) ? 'D' : ' ',
+		       (tlb.tlb_lo0 & MIPS3_PG_G) ? 'G' : ' ',
+		       (tlb.tlb_lo0 >> 3) & 7);
+		printk("Lo1=0x%09" PRIx64 " %c%c attr %lx sz=%lx\n",
+		       (uint64_t) mips3_tlbpfn_to_paddr(tlb.tlb_lo1),
+		       (tlb.tlb_lo1 & MIPS3_PG_D) ? 'D' : ' ',
+		       (tlb.tlb_lo1 & MIPS3_PG_G) ? 'G' : ' ',
+		       (tlb.tlb_lo1 >> 3) & 7, tlb.tlb_mask);
+	}
+}
+
+static void kvm_mips_map_page(struct kvm *kvm, gfn_t gfn)
+{
+	pfn_t pfn;
+
+	if (kvm->arch.guest_pmap[gfn] != KVM_INVALID_PAGE)
+		return;
+
+	pfn = kvm_mips_gfn_to_pfn(kvm, gfn);
+
+	if (kvm_mips_is_error_pfn(pfn)) {
+		panic("Couldn't get pfn for gfn %#" PRIx64 "!\n", gfn);
+	}
+
+	kvm->arch.guest_pmap[gfn] = pfn;
+	return;
+}
+
+/* Translate guest KSEG0 addresses to Host PA */
+unsigned long kvm_mips_translate_guest_kseg0_to_hpa(struct kvm_vcpu *vcpu,
+	unsigned long gva)
+{
+	gfn_t gfn;
+	uint32_t offset = gva & ~PAGE_MASK;
+	struct kvm *kvm = vcpu->kvm;
+
+	if (KVM_GUEST_KSEGX(gva) != KVM_GUEST_KSEG0) {
+		kvm_err("%s/%p: Invalid gva: %#lx\n", __func__,
+			__builtin_return_address(0), gva);
+		return KVM_INVALID_PAGE;
+	}
+
+	gfn = (KVM_GUEST_CPHYSADDR(gva) >> PAGE_SHIFT);
+
+	if (gfn >= kvm->arch.guest_pmap_npages) {
+		kvm_err("%s: Invalid gfn: %#llx, GVA: %#lx\n", __func__, gfn,
+			gva);
+		return KVM_INVALID_PAGE;
+	}
+	kvm_mips_map_page(vcpu->kvm, gfn);
+	return (kvm->arch.guest_pmap[gfn] << PAGE_SHIFT) + offset;
+}
+
+/* XXXKYMA: Must be called with interrupts disabled */
+/* set flush_dcache_mask == 0 if no dcache flush required */
+int
+kvm_mips_host_tlb_write(struct kvm_vcpu *vcpu, unsigned long entryhi,
+	unsigned long entrylo0, unsigned long entrylo1, int flush_dcache_mask)
+{
+	unsigned long flags;
+	unsigned long old_entryhi;
+	volatile int idx;
+
+	local_irq_save(flags);
+
+
+	old_entryhi = read_c0_entryhi();
+	write_c0_entryhi(entryhi);
+	mtc0_tlbw_hazard();
+
+	tlb_probe();
+	tlb_probe_hazard();
+	idx = read_c0_index();
+
+	if (idx > current_cpu_data.tlbsize) {
+		kvm_err("%s: Invalid Index: %d\n", __func__, idx);
+		kvm_mips_dump_host_tlbs();
+		return -1;
+	}
+
+	if (idx < 0) {
+		idx = read_c0_random() % current_cpu_data.tlbsize;
+		write_c0_index(idx);
+		mtc0_tlbw_hazard();
+	}
+	write_c0_entrylo0(entrylo0);
+	write_c0_entrylo1(entrylo1);
+	mtc0_tlbw_hazard();
+
+	tlb_write_indexed();
+	tlbw_use_hazard();
+
+#ifdef DEBUG
+	if (debug) {
+		kvm_debug("@ %#lx idx: %2d [entryhi(R): %#lx] "
+			  "entrylo0(R): 0x%08lx, entrylo1(R): 0x%08lx\n",
+			  vcpu->arch.pc, idx, read_c0_entryhi(),
+			  read_c0_entrylo0(), read_c0_entrylo1());
+	}
+#endif
+
+	/* Flush D-cache */
+	if (flush_dcache_mask) {
+		if (entrylo0 & MIPS3_PG_V) {
+			++vcpu->stat.flush_dcache_exits;
+			flush_data_cache_page((entryhi & VPN2_MASK) & ~flush_dcache_mask);
+		}
+		if (entrylo1 & MIPS3_PG_V) {
+			++vcpu->stat.flush_dcache_exits;
+			flush_data_cache_page(((entryhi & VPN2_MASK) & ~flush_dcache_mask) |
+				(0x1 << PAGE_SHIFT));
+		}
+	}
+
+	/* Restore old ASID */
+	write_c0_entryhi(old_entryhi);
+	mtc0_tlbw_hazard();
+	tlbw_use_hazard();
+	local_irq_restore(flags);
+	return 0;
+}
+
+
+/* XXXKYMA: Must be called with interrupts disabled */
+int kvm_mips_handle_kseg0_tlb_fault(unsigned long badvaddr,
+	struct kvm_vcpu *vcpu)
+{
+	gfn_t gfn;
+	pfn_t pfn0, pfn1;
+	unsigned long vaddr = 0;
+	unsigned long entryhi = 0, entrylo0 = 0, entrylo1 = 0;
+	int even;
+	struct kvm *kvm = vcpu->kvm;
+	const int flush_dcache_mask = 0;
+
+
+	if (KVM_GUEST_KSEGX(badvaddr) != KVM_GUEST_KSEG0) {
+		kvm_err("%s: Invalid BadVaddr: %#lx\n", __func__, badvaddr);
+		kvm_mips_dump_host_tlbs();
+		return -1;
+	}
+
+	gfn = (KVM_GUEST_CPHYSADDR(badvaddr) >> PAGE_SHIFT);
+	if (gfn >= kvm->arch.guest_pmap_npages) {
+		kvm_err("%s: Invalid gfn: %#llx, BadVaddr: %#lx\n", __func__,
+			gfn, badvaddr);
+		kvm_mips_dump_host_tlbs();
+		return -1;
+	}
+	even = !(gfn & 0x1);
+	vaddr = badvaddr & (PAGE_MASK << 1);
+
+	kvm_mips_map_page(vcpu->kvm, gfn);
+	kvm_mips_map_page(vcpu->kvm, gfn ^ 0x1);
+
+	if (even) {
+		pfn0 = kvm->arch.guest_pmap[gfn];
+		pfn1 = kvm->arch.guest_pmap[gfn ^ 0x1];
+	} else {
+		pfn0 = kvm->arch.guest_pmap[gfn ^ 0x1];
+		pfn1 = kvm->arch.guest_pmap[gfn];
+	}
+
+	entryhi = (vaddr | kvm_mips_get_kernel_asid(vcpu));
+	entrylo0 = mips3_paddr_to_tlbpfn(pfn0 << PAGE_SHIFT) | (0x3 << 3) | (1 << 2) |
+			(0x1 << 1);
+	entrylo1 = mips3_paddr_to_tlbpfn(pfn1 << PAGE_SHIFT) | (0x3 << 3) | (1 << 2) |
+			(0x1 << 1);
+
+	return kvm_mips_host_tlb_write(vcpu, entryhi, entrylo0, entrylo1,
+				       flush_dcache_mask);
+}
+
+int kvm_mips_handle_commpage_tlb_fault(unsigned long badvaddr,
+	struct kvm_vcpu *vcpu)
+{
+	pfn_t pfn0, pfn1;
+	unsigned long flags, old_entryhi = 0, vaddr = 0;
+	unsigned long entrylo0 = 0, entrylo1 = 0;
+
+
+	pfn0 = CPHYSADDR(vcpu->arch.kseg0_commpage) >> PAGE_SHIFT;
+	pfn1 = 0;
+	entrylo0 = mips3_paddr_to_tlbpfn(pfn0 << PAGE_SHIFT) | (0x3 << 3) | (1 << 2) |
+			(0x1 << 1);
+	entrylo1 = 0;
+
+	local_irq_save(flags);
+
+	old_entryhi = read_c0_entryhi();
+	vaddr = badvaddr & (PAGE_MASK << 1);
+	write_c0_entryhi(vaddr | kvm_mips_get_kernel_asid(vcpu));
+	mtc0_tlbw_hazard();
+	write_c0_entrylo0(entrylo0);
+	mtc0_tlbw_hazard();
+	write_c0_entrylo1(entrylo1);
+	mtc0_tlbw_hazard();
+	write_c0_index(kvm_mips_get_commpage_asid(vcpu));
+	mtc0_tlbw_hazard();
+	tlb_write_indexed();
+	mtc0_tlbw_hazard();
+	tlbw_use_hazard();
+
+#ifdef DEBUG
+	kvm_debug ("@ %#lx idx: %2d [entryhi(R): %#lx] entrylo0 (R): 0x%08lx, entrylo1(R): 0x%08lx\n",
+	     vcpu->arch.pc, read_c0_index(), read_c0_entryhi(),
+	     read_c0_entrylo0(), read_c0_entrylo1());
+#endif
+
+	/* Restore old ASID */
+	write_c0_entryhi(old_entryhi);
+	mtc0_tlbw_hazard();
+	tlbw_use_hazard();
+	local_irq_restore(flags);
+
+	return 0;
+}
+
+int
+kvm_mips_handle_mapped_seg_tlb_fault(struct kvm_vcpu *vcpu,
+	struct kvm_mips_tlb *tlb, unsigned long *hpa0, unsigned long *hpa1)
+{
+	unsigned long entryhi = 0, entrylo0 = 0, entrylo1 = 0;
+	struct kvm *kvm = vcpu->kvm;
+	pfn_t pfn0, pfn1;
+
+
+	if ((tlb->tlb_hi & VPN2_MASK) == 0) {
+		pfn0 = 0;
+		pfn1 = 0;
+	} else {
+		kvm_mips_map_page(kvm, mips3_tlbpfn_to_paddr(tlb->tlb_lo0) >> PAGE_SHIFT);
+		kvm_mips_map_page(kvm, mips3_tlbpfn_to_paddr(tlb->tlb_lo1) >> PAGE_SHIFT);
+
+		pfn0 = kvm->arch.guest_pmap[mips3_tlbpfn_to_paddr(tlb->tlb_lo0) >> PAGE_SHIFT];
+		pfn1 = kvm->arch.guest_pmap[mips3_tlbpfn_to_paddr(tlb->tlb_lo1) >> PAGE_SHIFT];
+	}
+
+	if (hpa0)
+		*hpa0 = pfn0 << PAGE_SHIFT;
+
+	if (hpa1)
+		*hpa1 = pfn1 << PAGE_SHIFT;
+
+	/* Get attributes from the Guest TLB */
+	entryhi = (tlb->tlb_hi & VPN2_MASK) | (KVM_GUEST_KERNEL_MODE(vcpu) ?
+			kvm_mips_get_kernel_asid(vcpu) : kvm_mips_get_user_asid(vcpu));
+	entrylo0 = mips3_paddr_to_tlbpfn(pfn0 << PAGE_SHIFT) | (0x3 << 3) |
+			(tlb->tlb_lo0 & MIPS3_PG_D) | (tlb->tlb_lo0 & MIPS3_PG_V);
+	entrylo1 = mips3_paddr_to_tlbpfn(pfn1 << PAGE_SHIFT) | (0x3 << 3) |
+			(tlb->tlb_lo1 & MIPS3_PG_D) | (tlb->tlb_lo1 & MIPS3_PG_V);
+
+#ifdef DEBUG
+	kvm_debug("@ %#lx tlb_lo0: 0x%08lx tlb_lo1: 0x%08lx\n", vcpu->arch.pc,
+		  tlb->tlb_lo0, tlb->tlb_lo1);
+#endif
+
+	return kvm_mips_host_tlb_write(vcpu, entryhi, entrylo0, entrylo1,
+				       tlb->tlb_mask);
+}
+
+int kvm_mips_guest_tlb_lookup(struct kvm_vcpu *vcpu, unsigned long entryhi)
+{
+	int i;
+	int index = -1;
+	struct kvm_mips_tlb *tlb = vcpu->arch.guest_tlb;
+
+
+	for (i = 0; i < KVM_MIPS_GUEST_TLB_SIZE; i++) {
+		if (((TLB_VPN2(tlb[i]) & ~tlb[i].tlb_mask) == ((entryhi & VPN2_MASK) & ~tlb[i].tlb_mask)) &&
+			(TLB_IS_GLOBAL(tlb[i]) || (TLB_ASID(tlb[i]) == (entryhi & ASID_MASK)))) {
+			index = i;
+			break;
+		}
+	}
+
+#ifdef DEBUG
+	kvm_debug("%s: entryhi: %#lx, index: %d lo0: %#lx, lo1: %#lx\n",
+		  __func__, entryhi, index, tlb[i].tlb_lo0, tlb[i].tlb_lo1);
+#endif
+
+	return index;
+}
+
+int kvm_mips_host_tlb_lookup(struct kvm_vcpu *vcpu, unsigned long vaddr)
+{
+	unsigned long old_entryhi, flags;
+	volatile int idx;
+
+
+	local_irq_save(flags);
+
+	old_entryhi = read_c0_entryhi();
+
+	if (KVM_GUEST_KERNEL_MODE(vcpu))
+		write_c0_entryhi((vaddr & VPN2_MASK) | kvm_mips_get_kernel_asid(vcpu));
+	else {
+		write_c0_entryhi((vaddr & VPN2_MASK) | kvm_mips_get_user_asid(vcpu));
+	}
+
+	mtc0_tlbw_hazard();
+
+	tlb_probe();
+	tlb_probe_hazard();
+	idx = read_c0_index();
+
+	/* Restore old ASID */
+	write_c0_entryhi(old_entryhi);
+	mtc0_tlbw_hazard();
+	tlbw_use_hazard();
+
+	local_irq_restore(flags);
+
+#ifdef DEBUG
+	kvm_debug("Host TLB lookup, %#lx, idx: %2d\n", vaddr, idx);
+#endif
+
+	return idx;
+}
+
+int kvm_mips_host_tlb_inv(struct kvm_vcpu *vcpu, unsigned long va)
+{
+	int idx;
+	unsigned long flags, old_entryhi;
+
+	local_irq_save(flags);
+
+
+	old_entryhi = read_c0_entryhi();
+
+	write_c0_entryhi((va & VPN2_MASK) | kvm_mips_get_user_asid(vcpu));
+	mtc0_tlbw_hazard();
+
+	tlb_probe();
+	tlb_probe_hazard();
+	idx = read_c0_index();
+
+	if (idx >= current_cpu_data.tlbsize)
+		BUG();
+
+	if (idx > 0) {
+		write_c0_entryhi(UNIQUE_ENTRYHI(idx));
+		mtc0_tlbw_hazard();
+
+		write_c0_entrylo0(0);
+		mtc0_tlbw_hazard();
+
+		write_c0_entrylo1(0);
+		mtc0_tlbw_hazard();
+
+		tlb_write_indexed();
+		mtc0_tlbw_hazard();
+	}
+
+	write_c0_entryhi(old_entryhi);
+	mtc0_tlbw_hazard();
+	tlbw_use_hazard();
+
+	local_irq_restore(flags);
+
+#ifdef DEBUG
+	if (idx > 0) {
+		kvm_debug("%s: Invalidated entryhi %#lx @ idx %d\n", __func__,
+			  (va & VPN2_MASK) | (vcpu->arch.asid_map[va & ASID_MASK] & ASID_MASK), idx);
+	}
+#endif
+
+	return 0;
+}
+
+/* XXXKYMA: Fix Guest USER/KERNEL no longer share the same ASID*/
+int kvm_mips_host_tlb_inv_index(struct kvm_vcpu *vcpu, int index)
+{
+	unsigned long flags, old_entryhi;
+
+	if (index >= current_cpu_data.tlbsize)
+		BUG();
+
+	local_irq_save(flags);
+
+
+	old_entryhi = read_c0_entryhi();
+
+	write_c0_entryhi(UNIQUE_ENTRYHI(index));
+	mtc0_tlbw_hazard();
+
+	write_c0_index(index);
+	mtc0_tlbw_hazard();
+
+	write_c0_entrylo0(0);
+	mtc0_tlbw_hazard();
+
+	write_c0_entrylo1(0);
+	mtc0_tlbw_hazard();
+
+	tlb_write_indexed();
+	mtc0_tlbw_hazard();
+	tlbw_use_hazard();
+
+	write_c0_entryhi(old_entryhi);
+	mtc0_tlbw_hazard();
+	tlbw_use_hazard();
+
+	local_irq_restore(flags);
+
+	return 0;
+}
+
+void kvm_mips_flush_host_tlb(int skip_kseg0)
+{
+	unsigned long flags;
+	unsigned long old_entryhi, entryhi;
+	unsigned long old_pagemask;
+	int entry = 0;
+	int maxentry = current_cpu_data.tlbsize;
+
+
+	local_irq_save(flags);
+
+	old_entryhi = read_c0_entryhi();
+	old_pagemask = read_c0_pagemask();
+
+	/* Blast 'em all away. */
+	for (entry = 0; entry < maxentry; entry++) {
+
+		write_c0_index(entry);
+		mtc0_tlbw_hazard();
+
+		if (skip_kseg0) {
+			tlb_read();
+			tlbw_use_hazard();
+
+			entryhi = read_c0_entryhi();
+
+			/* Don't blow away guest kernel entries */
+			if (KVM_GUEST_KSEGX(entryhi) == KVM_GUEST_KSEG0) {
+				continue;
+			}
+		}
+
+		/* Make sure all entries differ. */
+		write_c0_entryhi(UNIQUE_ENTRYHI(entry));
+		mtc0_tlbw_hazard();
+		write_c0_entrylo0(0);
+		mtc0_tlbw_hazard();
+		write_c0_entrylo1(0);
+		mtc0_tlbw_hazard();
+
+		tlb_write_indexed();
+		mtc0_tlbw_hazard();
+	}
+
+	tlbw_use_hazard();
+
+	write_c0_entryhi(old_entryhi);
+	write_c0_pagemask(old_pagemask);
+	mtc0_tlbw_hazard();
+	tlbw_use_hazard();
+
+	local_irq_restore(flags);
+}
+
+void
+kvm_get_new_mmu_context(struct mm_struct *mm, unsigned long cpu,
+			struct kvm_vcpu *vcpu)
+{
+	unsigned long asid = asid_cache(cpu);
+
+	if (!((asid += ASID_INC) & ASID_MASK)) {
+		if (cpu_has_vtag_icache) {
+			flush_icache_all();
+		}
+
+		kvm_local_flush_tlb_all();      /* start new asid cycle */
+
+		if (!asid)      /* fix version if needed */
+			asid = ASID_FIRST_VERSION;
+	}
+
+	cpu_context(cpu, mm) = asid_cache(cpu) = asid;
+}
+
+void kvm_shadow_tlb_put(struct kvm_vcpu *vcpu)
+{
+	unsigned long flags;
+	unsigned long old_entryhi;
+	unsigned long old_pagemask;
+	int entry = 0;
+	int cpu = smp_processor_id();
+
+	local_irq_save(flags);
+
+	old_entryhi = read_c0_entryhi();
+	old_pagemask = read_c0_pagemask();
+
+	for (entry = 0; entry < current_cpu_data.tlbsize; entry++) {
+		write_c0_index(entry);
+		mtc0_tlbw_hazard();
+		tlb_read();
+		tlbw_use_hazard();
+
+		vcpu->arch.shadow_tlb[cpu][entry].tlb_hi = read_c0_entryhi();
+		vcpu->arch.shadow_tlb[cpu][entry].tlb_lo0 = read_c0_entrylo0();
+		vcpu->arch.shadow_tlb[cpu][entry].tlb_lo1 = read_c0_entrylo1();
+		vcpu->arch.shadow_tlb[cpu][entry].tlb_mask = read_c0_pagemask();
+	}
+
+	write_c0_entryhi(old_entryhi);
+	write_c0_pagemask(old_pagemask);
+	mtc0_tlbw_hazard();
+
+	local_irq_restore(flags);
+
+}
+
+void kvm_shadow_tlb_load(struct kvm_vcpu *vcpu)
+{
+	unsigned long flags;
+	unsigned long old_ctx;
+	int entry;
+	int cpu = smp_processor_id();
+
+	local_irq_save(flags);
+
+	old_ctx = read_c0_entryhi();
+
+	for (entry = 0; entry < current_cpu_data.tlbsize; entry++) {
+		write_c0_entryhi(vcpu->arch.shadow_tlb[cpu][entry].tlb_hi);
+		mtc0_tlbw_hazard();
+		write_c0_entrylo0(vcpu->arch.shadow_tlb[cpu][entry].tlb_lo0);
+		write_c0_entrylo1(vcpu->arch.shadow_tlb[cpu][entry].tlb_lo1);
+
+		write_c0_index(entry);
+		mtc0_tlbw_hazard();
+
+		tlb_write_indexed();
+		tlbw_use_hazard();
+	}
+
+	tlbw_use_hazard();
+	write_c0_entryhi(old_ctx);
+	mtc0_tlbw_hazard();
+	local_irq_restore(flags);
+}
+
+
+void kvm_local_flush_tlb_all(void)
+{
+	unsigned long flags;
+	unsigned long old_ctx;
+	int entry = 0;
+
+	local_irq_save(flags);
+	/* Save old context and create impossible VPN2 value */
+	old_ctx = read_c0_entryhi();
+	write_c0_entrylo0(0);
+	write_c0_entrylo1(0);
+
+	/* Blast 'em all away. */
+	while (entry < current_cpu_data.tlbsize) {
+		/* Make sure all entries differ. */
+		write_c0_entryhi(UNIQUE_ENTRYHI(entry));
+		write_c0_index(entry);
+		mtc0_tlbw_hazard();
+		tlb_write_indexed();
+		entry++;
+	}
+	tlbw_use_hazard();
+	write_c0_entryhi(old_ctx);
+	mtc0_tlbw_hazard();
+
+	local_irq_restore(flags);
+}
+
+void kvm_mips_init_shadow_tlb(struct kvm_vcpu *vcpu)
+{
+	int cpu, entry;
+
+	for_each_possible_cpu(cpu) {
+		for (entry = 0; entry < current_cpu_data.tlbsize; entry++) {
+			vcpu->arch.shadow_tlb[cpu][entry].tlb_hi =
+			    UNIQUE_ENTRYHI(entry);
+			vcpu->arch.shadow_tlb[cpu][entry].tlb_lo0 = 0x0;
+			vcpu->arch.shadow_tlb[cpu][entry].tlb_lo1 = 0x0;
+			vcpu->arch.shadow_tlb[cpu][entry].tlb_mask =
+			    read_c0_pagemask();
+#ifdef DEBUG
+			kvm_debug
+			    ("shadow_tlb[%d][%d]: tlb_hi: %#lx, lo0: %#lx, lo1: %#lx\n",
+			     cpu, entry,
+			     vcpu->arch.shadow_tlb[cpu][entry].tlb_hi,
+			     vcpu->arch.shadow_tlb[cpu][entry].tlb_lo0,
+			     vcpu->arch.shadow_tlb[cpu][entry].tlb_lo1);
+#endif
+		}
+	}
+}
+
+/* Restore ASID once we are scheduled back after preemption */
+void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
+{
+	unsigned long flags;
+	int newasid = 0;
+
+#ifdef DEBUG
+	kvm_debug("%s: vcpu %p, cpu: %d\n", __func__, vcpu, cpu);
+#endif
+
+	/* Alocate new kernel and user ASIDs if needed */
+
+	local_irq_save(flags);
+
+	if (((vcpu->arch.
+	      guest_kernel_asid[cpu] ^ asid_cache(cpu)) & ASID_VERSION_MASK)) {
+		kvm_get_new_mmu_context(&vcpu->arch.guest_kernel_mm, cpu, vcpu);
+		vcpu->arch.guest_kernel_asid[cpu] =
+		    vcpu->arch.guest_kernel_mm.context.asid[cpu];
+		kvm_get_new_mmu_context(&vcpu->arch.guest_user_mm, cpu, vcpu);
+		vcpu->arch.guest_user_asid[cpu] =
+		    vcpu->arch.guest_user_mm.context.asid[cpu];
+		newasid++;
+
+		kvm_info("[%d]: cpu_context: %#lx\n", cpu,
+			 cpu_context(cpu, current->mm));
+		kvm_info("[%d]: Allocated new ASID for Guest Kernel: %#x\n",
+			 cpu, vcpu->arch.guest_kernel_asid[cpu]);
+		kvm_info("[%d]: Allocated new ASID for Guest User: %#x\n", cpu,
+			 vcpu->arch.guest_user_asid[cpu]);
+	}
+
+	if (vcpu->arch.last_sched_cpu != cpu) {
+		kvm_info("[%d->%d]KVM VCPU[%d] switch\n",
+			 vcpu->arch.last_sched_cpu, cpu, vcpu->vcpu_id);
+	}
+
+	/* Only reload shadow host TLB if new ASIDs haven't been allocated */
+#if 0
+	if ((atomic_read(&kvm_mips_instance) > 1) && !newasid) {
+		kvm_mips_flush_host_tlb(0);
+		kvm_shadow_tlb_load(vcpu);
+	}
+#endif
+
+	if (!newasid) {
+		/* If we preempted while the guest was executing, then reload the pre-empted ASID */
+		if (current->flags & PF_VCPU) {
+			write_c0_entryhi(vcpu->arch.
+					 preempt_entryhi & ASID_MASK);
+			ehb();
+		}
+	} else {
+		/* New ASIDs were allocated for the VM */
+
+		/* Were we in guest context? If so then the pre-empted ASID is no longer
+		 * valid, we need to set it to what it should be based on the mode of
+		 * the Guest (Kernel/User)
+		 */
+		if (current->flags & PF_VCPU) {
+			if (KVM_GUEST_KERNEL_MODE(vcpu))
+				write_c0_entryhi(vcpu->arch.
+						 guest_kernel_asid[cpu] &
+						 ASID_MASK);
+			else
+				write_c0_entryhi(vcpu->arch.
+						 guest_user_asid[cpu] &
+						 ASID_MASK);
+			ehb();
+		}
+	}
+
+	local_irq_restore(flags);
+
+}
+
+/* ASID can change if another task is scheduled during preemption */
+void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
+{
+	unsigned long flags;
+	uint32_t cpu;
+
+	local_irq_save(flags);
+
+	cpu = smp_processor_id();
+
+
+	vcpu->arch.preempt_entryhi = read_c0_entryhi();
+	vcpu->arch.last_sched_cpu = cpu;
+
+#if 0
+	if ((atomic_read(&kvm_mips_instance) > 1)) {
+		kvm_shadow_tlb_put(vcpu);
+	}
+#endif
+
+	if (((cpu_context(cpu, current->mm) ^ asid_cache(cpu)) &
+	     ASID_VERSION_MASK)) {
+		kvm_debug("%s: Dropping MMU Context:  %#lx\n", __func__,
+			  cpu_context(cpu, current->mm));
+		drop_mmu_context(current->mm, cpu);
+	}
+	write_c0_entryhi(cpu_asid(cpu, current->mm));
+	ehb();
+
+	local_irq_restore(flags);
+}
+
+uint32_t kvm_get_inst(uint32_t *opc, struct kvm_vcpu *vcpu)
+{
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+	unsigned long paddr, flags;
+	uint32_t inst;
+	int index;
+
+	if (KVM_GUEST_KSEGX((unsigned long) opc) < KVM_GUEST_KSEG0 ||
+	    KVM_GUEST_KSEGX((unsigned long) opc) == KVM_GUEST_KSEG23) {
+		local_irq_save(flags);
+		index = kvm_mips_host_tlb_lookup(vcpu, (unsigned long) opc);
+		if (index >= 0) {
+			inst = *(opc);
+		} else {
+			index =
+			    kvm_mips_guest_tlb_lookup(vcpu,
+						      ((unsigned long) opc & VPN2_MASK)
+						      |
+						      (kvm_read_c0_guest_entryhi
+						       (cop0) & ASID_MASK));
+			if (index < 0) {
+				kvm_err
+				    ("%s: get_user_failed for %p, vcpu: %p, ASID: %#lx\n",
+				     __func__, opc, vcpu, read_c0_entryhi());
+				kvm_mips_dump_host_tlbs();
+				local_irq_restore(flags);
+				return KVM_INVALID_INST;
+			}
+			kvm_mips_handle_mapped_seg_tlb_fault(vcpu,
+							     &vcpu->arch.
+							     guest_tlb[index],
+							     NULL, NULL);
+			inst = *(opc);
+		}
+		local_irq_restore(flags);
+	} else if (KVM_GUEST_KSEGX(opc) == KVM_GUEST_KSEG0) {
+		paddr =
+		    kvm_mips_translate_guest_kseg0_to_hpa(vcpu,
+							 (unsigned long) opc);
+		inst = *(uint32_t *) CKSEG0ADDR(paddr);
+	} else {
+		kvm_err("%s: illegal address: %p\n", __func__, opc);
+		return KVM_INVALID_INST;
+	}
+
+	return inst;
+}
+
+EXPORT_SYMBOL(kvm_local_flush_tlb_all);
+EXPORT_SYMBOL(kvm_shadow_tlb_put);
+EXPORT_SYMBOL(kvm_mips_handle_mapped_seg_tlb_fault);
+EXPORT_SYMBOL(kvm_mips_handle_commpage_tlb_fault);
+EXPORT_SYMBOL(kvm_mips_init_shadow_tlb);
+EXPORT_SYMBOL(kvm_mips_dump_host_tlbs);
+EXPORT_SYMBOL(kvm_mips_handle_kseg0_tlb_fault);
+EXPORT_SYMBOL(kvm_mips_host_tlb_lookup);
+EXPORT_SYMBOL(kvm_mips_flush_host_tlb);
+EXPORT_SYMBOL(kvm_mips_guest_tlb_lookup);
+EXPORT_SYMBOL(kvm_mips_host_tlb_inv);
+EXPORT_SYMBOL(kvm_mips_translate_guest_kseg0_to_hpa);
+EXPORT_SYMBOL(kvm_shadow_tlb_load);
+EXPORT_SYMBOL(kvm_mips_dump_shadow_tlbs);
+EXPORT_SYMBOL(kvm_mips_dump_guest_tlbs);
+EXPORT_SYMBOL(kvm_get_inst);
+EXPORT_SYMBOL(kvm_arch_vcpu_load);
+EXPORT_SYMBOL(kvm_arch_vcpu_put);
diff --git a/arch/mips/kvm/kvm_trap_emul.c b/arch/mips/kvm/kvm_trap_emul.c
new file mode 100644
index 0000000..466aeef
--- /dev/null
+++ b/arch/mips/kvm/kvm_trap_emul.c
@@ -0,0 +1,482 @@
+/*
+* 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.
+*
+* KVM/MIPS: Deliver/Emulate exceptions to the guest kernel
+*
+* Copyright (C) 2012  MIPS Technologies, Inc.  All rights reserved.
+* Authors: Sanjay Lal <sanjayl@kymasys.com>
+*/
+
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+
+#include <linux/kvm_host.h>
+
+#include "kvm_mips_opcode.h"
+#include "kvm_mips_int.h"
+
+static gpa_t kvm_trap_emul_gva_to_gpa_cb(gva_t gva)
+{
+	gpa_t gpa;
+	uint32_t kseg = KSEGX(gva);
+
+	if ((kseg == CKSEG0) || (kseg == CKSEG1))
+		gpa = CPHYSADDR(gva);
+	else {
+		printk("%s: cannot find GPA for GVA: %#lx\n", __func__, gva);
+		kvm_mips_dump_host_tlbs();
+		gpa = KVM_INVALID_ADDR;
+	}
+
+#ifdef DEBUG
+	kvm_debug("%s: gva %#lx, gpa: %#llx\n", __func__, gva, gpa);
+#endif
+
+	return gpa;
+}
+
+
+static int kvm_trap_emul_handle_cop_unusable(struct kvm_vcpu *vcpu)
+{
+	struct kvm_run *run = vcpu->run;
+	uint32_t __user *opc = (uint32_t __user *) vcpu->arch.pc;
+	unsigned long cause = vcpu->arch.host_cp0_cause;
+	enum emulation_result er = EMULATE_DONE;
+	int ret = RESUME_GUEST;
+
+	if (((cause & CAUSEF_CE) >> CAUSEB_CE) == 1) {
+		er = kvm_mips_emulate_fpu_exc(cause, opc, run, vcpu);
+	} else
+		er = kvm_mips_emulate_inst(cause, opc, run, vcpu);
+
+	switch (er) {
+	case EMULATE_DONE:
+		ret = RESUME_GUEST;
+		break;
+
+	case EMULATE_FAIL:
+		run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+		ret = RESUME_HOST;
+		break;
+
+	case EMULATE_WAIT:
+		run->exit_reason = KVM_EXIT_INTR;
+		ret = RESUME_HOST;
+		break;
+
+	default:
+		BUG();
+	}
+	return ret;
+}
+
+static int kvm_trap_emul_handle_tlb_mod(struct kvm_vcpu *vcpu)
+{
+	struct kvm_run *run = vcpu->run;
+	uint32_t __user *opc = (uint32_t __user *) vcpu->arch.pc;
+	unsigned long badvaddr = vcpu->arch.host_cp0_badvaddr;
+	unsigned long cause = vcpu->arch.host_cp0_cause;
+	enum emulation_result er = EMULATE_DONE;
+	int ret = RESUME_GUEST;
+
+	if (KVM_GUEST_KSEGX(badvaddr) < KVM_GUEST_KSEG0
+	    || KVM_GUEST_KSEGX(badvaddr) == KVM_GUEST_KSEG23) {
+#ifdef DEBUG
+		kvm_debug
+		    ("USER/KSEG23 ADDR TLB MOD fault: cause %#lx, PC: %p, BadVaddr: %#lx\n",
+		     cause, opc, badvaddr);
+#endif
+		er = kvm_mips_handle_tlbmod(cause, opc, run, vcpu);
+
+		if (er == EMULATE_DONE)
+			ret = RESUME_GUEST;
+		else {
+			run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+			ret = RESUME_HOST;
+		}
+	} else if (KVM_GUEST_KSEGX(badvaddr) == KVM_GUEST_KSEG0) {
+		/* XXXKYMA: The guest kernel does not expect to get this fault when we are not
+		 * using HIGHMEM. Need to address this in a HIGHMEM kernel
+		 */
+		printk
+		    ("TLB MOD fault not handled, cause %#lx, PC: %p, BadVaddr: %#lx\n",
+		     cause, opc, badvaddr);
+		kvm_mips_dump_host_tlbs();
+		kvm_arch_vcpu_dump_regs(vcpu);
+		run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+		ret = RESUME_HOST;
+	} else {
+		printk
+		    ("Illegal TLB Mod fault address , cause %#lx, PC: %p, BadVaddr: %#lx\n",
+		     cause, opc, badvaddr);
+		kvm_mips_dump_host_tlbs();
+		kvm_arch_vcpu_dump_regs(vcpu);
+		run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+		ret = RESUME_HOST;
+	}
+	return ret;
+}
+
+static int kvm_trap_emul_handle_tlb_st_miss(struct kvm_vcpu *vcpu)
+{
+	struct kvm_run *run = vcpu->run;
+	uint32_t __user *opc = (uint32_t __user *) vcpu->arch.pc;
+	unsigned long badvaddr = vcpu->arch.host_cp0_badvaddr;
+	unsigned long cause = vcpu->arch.host_cp0_cause;
+	enum emulation_result er = EMULATE_DONE;
+	int ret = RESUME_GUEST;
+
+	if (((badvaddr & PAGE_MASK) == KVM_GUEST_COMMPAGE_ADDR)
+	    && KVM_GUEST_KERNEL_MODE(vcpu)) {
+		if (kvm_mips_handle_commpage_tlb_fault(badvaddr, vcpu) < 0) {
+			run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+			ret = RESUME_HOST;
+		}
+	} else if (KVM_GUEST_KSEGX(badvaddr) < KVM_GUEST_KSEG0
+		   || KVM_GUEST_KSEGX(badvaddr) == KVM_GUEST_KSEG23) {
+#ifdef DEBUG
+		kvm_debug
+		    ("USER ADDR TLB LD fault: cause %#lx, PC: %p, BadVaddr: %#lx\n",
+		     cause, opc, badvaddr);
+#endif
+		er = kvm_mips_handle_tlbmiss(cause, opc, run, vcpu);
+		if (er == EMULATE_DONE)
+			ret = RESUME_GUEST;
+		else {
+			run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+			ret = RESUME_HOST;
+		}
+	} else if (KVM_GUEST_KSEGX(badvaddr) == KVM_GUEST_KSEG0) {
+		/* All KSEG0 faults are handled by KVM, as the guest kernel does not
+		 * expect to ever get them
+		 */
+		if (kvm_mips_handle_kseg0_tlb_fault
+		    (vcpu->arch.host_cp0_badvaddr, vcpu) < 0) {
+			run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+			ret = RESUME_HOST;
+		}
+	} else {
+		kvm_err
+		    ("Illegal TLB LD fault address , cause %#lx, PC: %p, BadVaddr: %#lx\n",
+		     cause, opc, badvaddr);
+		kvm_mips_dump_host_tlbs();
+		kvm_arch_vcpu_dump_regs(vcpu);
+		run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+		ret = RESUME_HOST;
+	}
+	return ret;
+}
+
+static int kvm_trap_emul_handle_tlb_ld_miss(struct kvm_vcpu *vcpu)
+{
+	struct kvm_run *run = vcpu->run;
+	uint32_t __user *opc = (uint32_t __user *) vcpu->arch.pc;
+	unsigned long badvaddr = vcpu->arch.host_cp0_badvaddr;
+	unsigned long cause = vcpu->arch.host_cp0_cause;
+	enum emulation_result er = EMULATE_DONE;
+	int ret = RESUME_GUEST;
+
+	if (((badvaddr & PAGE_MASK) == KVM_GUEST_COMMPAGE_ADDR)
+	    && KVM_GUEST_KERNEL_MODE(vcpu)) {
+		if (kvm_mips_handle_commpage_tlb_fault(badvaddr, vcpu) < 0) {
+			run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+			ret = RESUME_HOST;
+		}
+	} else if (KVM_GUEST_KSEGX(badvaddr) < KVM_GUEST_KSEG0
+		   || KVM_GUEST_KSEGX(badvaddr) == KVM_GUEST_KSEG23) {
+#ifdef DEBUG
+		kvm_debug("USER ADDR TLB ST fault: PC: %#lx, BadVaddr: %#lx\n",
+			  vcpu->arch.pc, badvaddr);
+#endif
+
+		/* User Address (UA) fault, this could happen if
+		 * (1) TLB entry not present/valid in both Guest and shadow host TLBs, in this
+		 *     case we pass on the fault to the guest kernel and let it handle it.
+		 * (2) TLB entry is present in the Guest TLB but not in the shadow, in this
+		 *     case we inject the TLB from the Guest TLB into the shadow host TLB
+		 */
+
+		er = kvm_mips_handle_tlbmiss(cause, opc, run, vcpu);
+		if (er == EMULATE_DONE)
+			ret = RESUME_GUEST;
+		else {
+			run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+			ret = RESUME_HOST;
+		}
+	} else if (KVM_GUEST_KSEGX(badvaddr) == KVM_GUEST_KSEG0) {
+		if (kvm_mips_handle_kseg0_tlb_fault
+		    (vcpu->arch.host_cp0_badvaddr, vcpu) < 0) {
+			run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+			ret = RESUME_HOST;
+		}
+	} else {
+		printk
+		    ("Illegal TLB ST fault address , cause %#lx, PC: %p, BadVaddr: %#lx\n",
+		     cause, opc, badvaddr);
+		kvm_mips_dump_host_tlbs();
+		kvm_arch_vcpu_dump_regs(vcpu);
+		run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+		ret = RESUME_HOST;
+	}
+	return ret;
+}
+
+static int kvm_trap_emul_handle_addr_err_st(struct kvm_vcpu *vcpu)
+{
+	struct kvm_run *run = vcpu->run;
+	uint32_t __user *opc = (uint32_t __user *) vcpu->arch.pc;
+	unsigned long badvaddr = vcpu->arch.host_cp0_badvaddr;
+	unsigned long cause = vcpu->arch.host_cp0_cause;
+	enum emulation_result er = EMULATE_DONE;
+	int ret = RESUME_GUEST;
+
+	if (KVM_GUEST_KERNEL_MODE(vcpu)
+	    && (KSEGX(badvaddr) == CKSEG0 || KSEGX(badvaddr) == CKSEG1)) {
+#ifdef DEBUG
+		kvm_debug("Emulate Store to MMIO space\n");
+#endif
+		er = kvm_mips_emulate_inst(cause, opc, run, vcpu);
+		if (er == EMULATE_FAIL) {
+			printk("Emulate Store to MMIO space failed\n");
+			run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+			ret = RESUME_HOST;
+		} else {
+			run->exit_reason = KVM_EXIT_MMIO;
+			ret = RESUME_HOST;
+		}
+	} else {
+		printk
+		    ("Address Error (STORE): cause %#lx, PC: %p, BadVaddr: %#lx\n",
+		     cause, opc, badvaddr);
+		run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+		ret = RESUME_HOST;
+	}
+	return ret;
+}
+
+static int kvm_trap_emul_handle_addr_err_ld(struct kvm_vcpu *vcpu)
+{
+	struct kvm_run *run = vcpu->run;
+	uint32_t __user *opc = (uint32_t __user *) vcpu->arch.pc;
+	unsigned long badvaddr = vcpu->arch.host_cp0_badvaddr;
+	unsigned long cause = vcpu->arch.host_cp0_cause;
+	enum emulation_result er = EMULATE_DONE;
+	int ret = RESUME_GUEST;
+
+	if (KSEGX(badvaddr) == CKSEG0 || KSEGX(badvaddr) == CKSEG1) {
+#ifdef DEBUG
+		kvm_debug("Emulate Load from MMIO space @ %#lx\n", badvaddr);
+#endif
+		er = kvm_mips_emulate_inst(cause, opc, run, vcpu);
+		if (er == EMULATE_FAIL) {
+			printk("Emulate Load from MMIO space failed\n");
+			run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+			ret = RESUME_HOST;
+		} else {
+			run->exit_reason = KVM_EXIT_MMIO;
+			ret = RESUME_HOST;
+		}
+	} else {
+		printk
+		    ("Address Error (LOAD): cause %#lx, PC: %p, BadVaddr: %#lx\n",
+		     cause, opc, badvaddr);
+		run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+		ret = RESUME_HOST;
+		er = EMULATE_FAIL;
+	}
+	return ret;
+}
+
+static int kvm_trap_emul_handle_syscall(struct kvm_vcpu *vcpu)
+{
+	struct kvm_run *run = vcpu->run;
+	uint32_t __user *opc = (uint32_t __user *) vcpu->arch.pc;
+	unsigned long cause = vcpu->arch.host_cp0_cause;
+	enum emulation_result er = EMULATE_DONE;
+	int ret = RESUME_GUEST;
+
+	er = kvm_mips_emulate_syscall(cause, opc, run, vcpu);
+	if (er == EMULATE_DONE)
+		ret = RESUME_GUEST;
+	else {
+		run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+		ret = RESUME_HOST;
+	}
+	return ret;
+}
+
+static int kvm_trap_emul_handle_res_inst(struct kvm_vcpu *vcpu)
+{
+	struct kvm_run *run = vcpu->run;
+	uint32_t __user *opc = (uint32_t __user *) vcpu->arch.pc;
+	unsigned long cause = vcpu->arch.host_cp0_cause;
+	enum emulation_result er = EMULATE_DONE;
+	int ret = RESUME_GUEST;
+
+	er = kvm_mips_handle_ri(cause, opc, run, vcpu);
+	if (er == EMULATE_DONE)
+		ret = RESUME_GUEST;
+	else {
+		run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+		ret = RESUME_HOST;
+	}
+	return ret;
+}
+
+static int kvm_trap_emul_handle_break(struct kvm_vcpu *vcpu)
+{
+	struct kvm_run *run = vcpu->run;
+	uint32_t __user *opc = (uint32_t __user *) vcpu->arch.pc;
+	unsigned long cause = vcpu->arch.host_cp0_cause;
+	enum emulation_result er = EMULATE_DONE;
+	int ret = RESUME_GUEST;
+
+	er = kvm_mips_emulate_bp_exc(cause, opc, run, vcpu);
+	if (er == EMULATE_DONE)
+		ret = RESUME_GUEST;
+	else {
+		run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+		ret = RESUME_HOST;
+	}
+	return ret;
+}
+
+static int
+kvm_trap_emul_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
+{
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+
+	kvm_write_c0_guest_index(cop0, regs->cp0reg[MIPS_CP0_TLB_INDEX][0]);
+	kvm_write_c0_guest_context(cop0, regs->cp0reg[MIPS_CP0_TLB_CONTEXT][0]);
+	kvm_write_c0_guest_badvaddr(cop0, regs->cp0reg[MIPS_CP0_BAD_VADDR][0]);
+	kvm_write_c0_guest_entryhi(cop0, regs->cp0reg[MIPS_CP0_TLB_HI][0]);
+	kvm_write_c0_guest_epc(cop0, regs->cp0reg[MIPS_CP0_EXC_PC][0]);
+
+	kvm_write_c0_guest_status(cop0, regs->cp0reg[MIPS_CP0_STATUS][0]);
+	kvm_write_c0_guest_cause(cop0, regs->cp0reg[MIPS_CP0_CAUSE][0]);
+	kvm_write_c0_guest_pagemask(cop0,
+				    regs->cp0reg[MIPS_CP0_TLB_PG_MASK][0]);
+	kvm_write_c0_guest_wired(cop0, regs->cp0reg[MIPS_CP0_TLB_WIRED][0]);
+	kvm_write_c0_guest_errorepc(cop0, regs->cp0reg[MIPS_CP0_ERROR_PC][0]);
+
+	return 0;
+}
+
+static int
+kvm_trap_emul_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
+{
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+
+	regs->cp0reg[MIPS_CP0_TLB_INDEX][0] = kvm_read_c0_guest_index(cop0);
+	regs->cp0reg[MIPS_CP0_TLB_CONTEXT][0] = kvm_read_c0_guest_context(cop0);
+	regs->cp0reg[MIPS_CP0_BAD_VADDR][0] = kvm_read_c0_guest_badvaddr(cop0);
+	regs->cp0reg[MIPS_CP0_TLB_HI][0] = kvm_read_c0_guest_entryhi(cop0);
+	regs->cp0reg[MIPS_CP0_EXC_PC][0] = kvm_read_c0_guest_epc(cop0);
+
+	regs->cp0reg[MIPS_CP0_STATUS][0] = kvm_read_c0_guest_status(cop0);
+	regs->cp0reg[MIPS_CP0_CAUSE][0] = kvm_read_c0_guest_cause(cop0);
+	regs->cp0reg[MIPS_CP0_TLB_PG_MASK][0] =
+	    kvm_read_c0_guest_pagemask(cop0);
+	regs->cp0reg[MIPS_CP0_TLB_WIRED][0] = kvm_read_c0_guest_wired(cop0);
+	regs->cp0reg[MIPS_CP0_ERROR_PC][0] = kvm_read_c0_guest_errorepc(cop0);
+
+	regs->cp0reg[MIPS_CP0_CONFIG][0] = kvm_read_c0_guest_config(cop0);
+	regs->cp0reg[MIPS_CP0_CONFIG][1] = kvm_read_c0_guest_config1(cop0);
+	regs->cp0reg[MIPS_CP0_CONFIG][2] = kvm_read_c0_guest_config2(cop0);
+	regs->cp0reg[MIPS_CP0_CONFIG][3] = kvm_read_c0_guest_config3(cop0);
+	regs->cp0reg[MIPS_CP0_CONFIG][7] = kvm_read_c0_guest_config7(cop0);
+
+	return 0;
+}
+
+static int kvm_trap_emul_vm_init(struct kvm *kvm)
+{
+	return 0;
+}
+
+static int kvm_trap_emul_vcpu_init(struct kvm_vcpu *vcpu)
+{
+	return 0;
+}
+
+static int kvm_trap_emul_vcpu_setup(struct kvm_vcpu *vcpu)
+{
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+	uint32_t config1;
+	int vcpu_id = vcpu->vcpu_id;
+
+	/* Arch specific stuff, set up config registers properly so that the
+	 * guest will come up as expected, for now we simulate a
+	 * MIPS 24kc
+	 */
+	kvm_write_c0_guest_prid(cop0, 0x00019300);
+	kvm_write_c0_guest_config(cop0,
+				  MIPS_CONFIG0 | (0x1 << CP0C0_AR) |
+				  (MMU_TYPE_R4000 << CP0C0_MT));
+
+	/* Read the cache characteristics from the host Config1 Register */
+	config1 = (read_c0_config1() & ~0x7f);
+
+	/* Set up MMU size */
+	config1 &= ~(0x3f << 25);
+	config1 |= ((KVM_MIPS_GUEST_TLB_SIZE - 1) << 25);
+
+	/* We unset some bits that we aren't emulating */
+	config1 &=
+	    ~((1 << CP0C1_C2) | (1 << CP0C1_MD) | (1 << CP0C1_PC) |
+	      (1 << CP0C1_WR) | (1 << CP0C1_CA));
+	kvm_write_c0_guest_config1(cop0, config1);
+
+	kvm_write_c0_guest_config2(cop0, MIPS_CONFIG2);
+	/* MIPS_CONFIG2 | (read_c0_config2() & 0xfff) */
+	kvm_write_c0_guest_config3(cop0,
+				   MIPS_CONFIG3 | (0 << CP0C3_VInt) | (1 <<
+								       CP0C3_ULRI));
+
+	/* Set Wait IE/IXMT Ignore in Config7, IAR, AR */
+	kvm_write_c0_guest_config7(cop0, (MIPS_CONF7_WII) | (1 << 10));
+
+	/* Setup IntCtl defaults, compatibilty mode for timer interrupts (HW5) */
+	kvm_write_c0_guest_intctl(cop0, 0xFC000000);
+
+	/* Put in vcpu id as CPUNum into Ebase Reg to handle SMP Guests */
+	kvm_write_c0_guest_ebase(cop0, KVM_GUEST_KSEG0 | (vcpu_id & 0xFF));
+
+	return 0;
+}
+
+static struct kvm_mips_callbacks kvm_trap_emul_callbacks = {
+	/* exit handlers */
+	.handle_cop_unusable = kvm_trap_emul_handle_cop_unusable,
+	.handle_tlb_mod = kvm_trap_emul_handle_tlb_mod,
+	.handle_tlb_st_miss = kvm_trap_emul_handle_tlb_st_miss,
+	.handle_tlb_ld_miss = kvm_trap_emul_handle_tlb_ld_miss,
+	.handle_addr_err_st = kvm_trap_emul_handle_addr_err_st,
+	.handle_addr_err_ld = kvm_trap_emul_handle_addr_err_ld,
+	.handle_syscall = kvm_trap_emul_handle_syscall,
+	.handle_res_inst = kvm_trap_emul_handle_res_inst,
+	.handle_break = kvm_trap_emul_handle_break,
+
+	.vm_init = kvm_trap_emul_vm_init,
+	.vcpu_init = kvm_trap_emul_vcpu_init,
+	.vcpu_setup = kvm_trap_emul_vcpu_setup,
+	.gva_to_gpa = kvm_trap_emul_gva_to_gpa_cb,
+	.queue_timer_int = kvm_mips_queue_timer_int_cb,
+	.dequeue_timer_int = kvm_mips_dequeue_timer_int_cb,
+	.queue_io_int = kvm_mips_queue_io_int_cb,
+	.dequeue_io_int = kvm_mips_dequeue_io_int_cb,
+	.irq_deliver = kvm_mips_irq_deliver_cb,
+	.irq_clear = kvm_mips_irq_clear_cb,
+	.vcpu_ioctl_get_regs = kvm_trap_emul_ioctl_get_regs,
+	.vcpu_ioctl_set_regs = kvm_trap_emul_ioctl_set_regs,
+};
+
+int kvm_mips_emulation_init(struct kvm_mips_callbacks **install_callbacks)
+{
+	*install_callbacks = &kvm_trap_emul_callbacks;
+	return 0;
+}
diff --git a/arch/mips/kvm/trace.h b/arch/mips/kvm/trace.h
new file mode 100644
index 0000000..bc9e0f4
--- /dev/null
+++ b/arch/mips/kvm/trace.h
@@ -0,0 +1,46 @@
+/*
+* 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) 2012  MIPS Technologies, Inc.  All rights reserved.
+* Authors: Sanjay Lal <sanjayl@kymasys.com>
+*/
+
+#if !defined(_TRACE_KVM_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_KVM_H
+
+#include <linux/tracepoint.h>
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM kvm
+#define TRACE_INCLUDE_PATH .
+#define TRACE_INCLUDE_FILE trace
+
+/*
+ * Tracepoints for VM eists
+ */
+extern char *kvm_mips_exit_types_str[MAX_KVM_MIPS_EXIT_TYPES];
+
+TRACE_EVENT(kvm_exit,
+	    TP_PROTO(struct kvm_vcpu *vcpu, unsigned int reason),
+	    TP_ARGS(vcpu, reason),
+	    TP_STRUCT__entry(
+			__field(struct kvm_vcpu *, vcpu)
+			__field(unsigned int, reason)
+	    ),
+
+	    TP_fast_assign(
+			__entry->vcpu = vcpu;
+			__entry->reason = reason;
+	    ),
+
+	    TP_printk("[%s]PC: 0x%08lx",
+		      kvm_mips_exit_types_str[__entry->reason],
+		      __entry->vcpu->arch.pc)
+);
+
+#endif /* _TRACE_KVM_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/arch/mips/lasat/picvue_proc.c b/arch/mips/lasat/picvue_proc.c
index c592bc8..638c5db 100644
--- a/arch/mips/lasat/picvue_proc.c
+++ b/arch/mips/lasat/picvue_proc.c
@@ -58,13 +58,13 @@ static int pvc_line_proc_show(struct seq_file *m, void *v)
 
 static int pvc_line_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, pvc_line_proc_show, PDE(inode)->data);
+	return single_open(file, pvc_line_proc_show, PDE_DATA(inode));
 }
 
 static ssize_t pvc_line_proc_write(struct file *file, const char __user *buf,
 				   size_t count, loff_t *pos)
 {
-	int lineno = *(int *)PDE(file_inode(file))->data;
+	int lineno = *(int *)PDE_DATA(file_inode(file));
 	char kbuf[PVC_LINELEN];
 	size_t len;
 
diff --git a/arch/mips/lib/bitops.c b/arch/mips/lib/bitops.c
index 81f1dcf..a64daee 100644
--- a/arch/mips/lib/bitops.c
+++ b/arch/mips/lib/bitops.c
@@ -90,12 +90,12 @@ int __mips_test_and_set_bit(unsigned long nr,
 	unsigned bit = nr & SZLONG_MASK;
 	unsigned long mask;
 	unsigned long flags;
-	unsigned long res;
+	int res;
 
 	a += nr >> SZLONG_LOG;
 	mask = 1UL << bit;
 	raw_local_irq_save(flags);
-	res = (mask & *a);
+	res = (mask & *a) != 0;
 	*a |= mask;
 	raw_local_irq_restore(flags);
 	return res;
@@ -116,12 +116,12 @@ int __mips_test_and_set_bit_lock(unsigned long nr,
 	unsigned bit = nr & SZLONG_MASK;
 	unsigned long mask;
 	unsigned long flags;
-	unsigned long res;
+	int res;
 
 	a += nr >> SZLONG_LOG;
 	mask = 1UL << bit;
 	raw_local_irq_save(flags);
-	res = (mask & *a);
+	res = (mask & *a) != 0;
 	*a |= mask;
 	raw_local_irq_restore(flags);
 	return res;
@@ -141,12 +141,12 @@ int __mips_test_and_clear_bit(unsigned long nr, volatile unsigned long *addr)
 	unsigned bit = nr & SZLONG_MASK;
 	unsigned long mask;
 	unsigned long flags;
-	unsigned long res;
+	int res;
 
 	a += nr >> SZLONG_LOG;
 	mask = 1UL << bit;
 	raw_local_irq_save(flags);
-	res = (mask & *a);
+	res = (mask & *a) != 0;
 	*a &= ~mask;
 	raw_local_irq_restore(flags);
 	return res;
@@ -166,12 +166,12 @@ int __mips_test_and_change_bit(unsigned long nr, volatile unsigned long *addr)
 	unsigned bit = nr & SZLONG_MASK;
 	unsigned long mask;
 	unsigned long flags;
-	unsigned long res;
+	int res;
 
 	a += nr >> SZLONG_LOG;
 	mask = 1UL << bit;
 	raw_local_irq_save(flags);
-	res = (mask & *a);
+	res = (mask & *a) != 0;
 	*a ^= mask;
 	raw_local_irq_restore(flags);
 	return res;
diff --git a/arch/mips/lib/csum_partial.S b/arch/mips/lib/csum_partial.S
index 507147a..a6adffb 100644
--- a/arch/mips/lib/csum_partial.S
+++ b/arch/mips/lib/csum_partial.S
@@ -270,7 +270,7 @@ LEAF(csum_partial)
 #endif
 
 	/* odd buffer alignment? */
-#ifdef CPU_MIPSR2
+#ifdef CONFIG_CPU_MIPSR2
 	wsbh	v1, sum
 	movn	sum, v1, t7
 #else
@@ -670,7 +670,7 @@ EXC(	sb	t0, NBYTES-2(dst), .Ls_exc)
 	addu	sum, v1
 #endif
 
-#ifdef CPU_MIPSR2
+#ifdef CONFIG_CPU_MIPSR2
 	wsbh	v1, sum
 	movn	sum, v1, odd
 #else
diff --git a/arch/mips/loongson/common/Makefile b/arch/mips/loongson/common/Makefile
index e526488..4c57b3e 100644
--- a/arch/mips/loongson/common/Makefile
+++ b/arch/mips/loongson/common/Makefile
@@ -4,7 +4,7 @@
 
 obj-y += setup.o init.o cmdline.o env.o time.o reset.o irq.o \
     pci.o bonito-irq.o mem.o machtype.o platform.o
-obj-$(CONFIG_GENERIC_GPIO) += gpio.o
+obj-$(CONFIG_GPIOLIB) += gpio.o
 
 #
 # Serial port support
diff --git a/arch/mips/mm/Makefile b/arch/mips/mm/Makefile
index 1dcec30..e87aae1 100644
--- a/arch/mips/mm/Makefile
+++ b/arch/mips/mm/Makefile
@@ -4,7 +4,7 @@
 
 obj-y				+= cache.o dma-default.o extable.o fault.o \
 				   gup.o init.o mmap.o page.o page-funcs.o \
-				   tlbex.o tlbex-fault.o uasm.o
+				   tlbex.o tlbex-fault.o uasm-mips.o
 
 obj-$(CONFIG_32BIT)		+= ioremap.o pgtable-32.o
 obj-$(CONFIG_64BIT)		+= pgtable-64.o
@@ -22,3 +22,5 @@ obj-$(CONFIG_IP22_CPU_SCACHE)	+= sc-ip22.o
 obj-$(CONFIG_R5000_CPU_SCACHE)	+= sc-r5k.o
 obj-$(CONFIG_RM7000_CPU_SCACHE) += sc-rm7k.o
 obj-$(CONFIG_MIPS_CPU_SCACHE)	+= sc-mips.o
+
+obj-$(CONFIG_SYS_SUPPORTS_MICROMIPS) += uasm-micromips.o
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index ecca559..b5aedb2 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -136,7 +136,8 @@ static void __cpuinit r4k_blast_dcache_page_indexed_setup(void)
 		r4k_blast_dcache_page_indexed = blast_dcache64_page_indexed;
 }
 
-static void (* r4k_blast_dcache)(void);
+void (* r4k_blast_dcache)(void);
+EXPORT_SYMBOL(r4k_blast_dcache);
 
 static void __cpuinit r4k_blast_dcache_setup(void)
 {
@@ -264,7 +265,8 @@ static void __cpuinit r4k_blast_icache_page_indexed_setup(void)
 		r4k_blast_icache_page_indexed = blast_icache64_page_indexed;
 }
 
-static void (* r4k_blast_icache)(void);
+void (* r4k_blast_icache)(void);
+EXPORT_SYMBOL(r4k_blast_icache);
 
 static void __cpuinit r4k_blast_icache_setup(void)
 {
diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c
index 07cec44..5aeb3eb 100644
--- a/arch/mips/mm/cache.c
+++ b/arch/mips/mm/cache.c
@@ -48,6 +48,7 @@ void (*flush_icache_all)(void);
 
 EXPORT_SYMBOL_GPL(local_flush_data_cache_page);
 EXPORT_SYMBOL(flush_data_cache_page);
+EXPORT_SYMBOL(flush_icache_all);
 
 #ifdef CONFIG_DMA_NONCOHERENT
 
diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c
index 6792925..3d0346d 100644
--- a/arch/mips/mm/init.c
+++ b/arch/mips/mm/init.c
@@ -77,10 +77,9 @@ EXPORT_SYMBOL_GPL(empty_zero_page);
 /*
  * Not static inline because used by IP27 special magic initialization code
  */
-unsigned long setup_zero_pages(void)
+void setup_zero_pages(void)
 {
-	unsigned int order;
-	unsigned long size;
+	unsigned int order, i;
 	struct page *page;
 
 	if (cpu_has_vce)
@@ -94,15 +93,10 @@ unsigned long setup_zero_pages(void)
 
 	page = virt_to_page((void *)empty_zero_page);
 	split_page(page, order);
-	while (page < virt_to_page((void *)(empty_zero_page + (PAGE_SIZE << order)))) {
-		SetPageReserved(page);
-		page++;
-	}
-
-	size = PAGE_SIZE << order;
-	zero_page_mask = (size - 1) & PAGE_MASK;
+	for (i = 0; i < (1 << order); i++, page++)
+		mark_page_reserved(page);
 
-	return 1UL << order;
+	zero_page_mask = ((PAGE_SIZE << order) - 1) & PAGE_MASK;
 }
 
 #ifdef CONFIG_MIPS_MT_SMTC
@@ -380,7 +374,7 @@ void __init mem_init(void)
 	high_memory = (void *) __va(max_low_pfn << PAGE_SHIFT);
 
 	totalram_pages += free_all_bootmem();
-	totalram_pages -= setup_zero_pages();	/* Setup zeroed pages.	*/
+	setup_zero_pages();	/* Setup zeroed pages.  */
 
 	reservedpages = ram = 0;
 	for (tmp = 0; tmp < max_low_pfn; tmp++)
@@ -399,12 +393,8 @@ void __init mem_init(void)
 			SetPageReserved(page);
 			continue;
 		}
-		ClearPageReserved(page);
-		init_page_count(page);
-		__free_page(page);
-		totalhigh_pages++;
+		free_highmem_page(page);
 	}
-	totalram_pages += totalhigh_pages;
 	num_physpages += totalhigh_pages;
 #endif
 
@@ -440,11 +430,8 @@ void free_init_pages(const char *what, unsigned long begin, unsigned long end)
 		struct page *page = pfn_to_page(pfn);
 		void *addr = phys_to_virt(PFN_PHYS(pfn));
 
-		ClearPageReserved(page);
-		init_page_count(page);
 		memset(addr, POISON_FREE_INITMEM, PAGE_SIZE);
-		__free_page(page);
-		totalram_pages++;
+		free_reserved_page(page);
 	}
 	printk(KERN_INFO "Freeing %s: %ldk freed\n", what, (end - begin) >> 10);
 }
@@ -452,18 +439,14 @@ void free_init_pages(const char *what, unsigned long begin, unsigned long end)
 #ifdef CONFIG_BLK_DEV_INITRD
 void free_initrd_mem(unsigned long start, unsigned long end)
 {
-	free_init_pages("initrd memory",
-			virt_to_phys((void *)start),
-			virt_to_phys((void *)end));
+	free_reserved_area(start, end, POISON_FREE_INITMEM, "initrd");
 }
 #endif
 
 void __init_refok free_initmem(void)
 {
 	prom_free_prom_memory();
-	free_init_pages("unused kernel memory",
-			__pa_symbol(&__init_begin),
-			__pa_symbol(&__init_end));
+	free_initmem_default(POISON_FREE_INITMEM);
 }
 
 #ifndef CONFIG_MIPS_PGD_C0_CONTEXT
diff --git a/arch/mips/mm/mmap.c b/arch/mips/mm/mmap.c
index 7e5fe27..f1baadd 100644
--- a/arch/mips/mm/mmap.c
+++ b/arch/mips/mm/mmap.c
@@ -158,11 +158,9 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
 	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;
 	}
 }
 
diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c
index 493131c..c643de4 100644
--- a/arch/mips/mm/tlb-r4k.c
+++ b/arch/mips/mm/tlb-r4k.c
@@ -13,6 +13,7 @@
 #include <linux/smp.h>
 #include <linux/mm.h>
 #include <linux/hugetlb.h>
+#include <linux/module.h>
 
 #include <asm/cpu.h>
 #include <asm/bootinfo.h>
@@ -94,6 +95,7 @@ void local_flush_tlb_all(void)
 	FLUSH_ITLB;
 	EXIT_CRITICAL(flags);
 }
+EXPORT_SYMBOL(local_flush_tlb_all);
 
 /* All entries common to a mm share an asid.  To effectively flush
    these entries, we just bump the asid. */
diff --git a/arch/mips/mm/uasm-micromips.c b/arch/mips/mm/uasm-micromips.c
new file mode 100644
index 0000000..476d50c
--- /dev/null
+++ b/arch/mips/mm/uasm-micromips.c
@@ -0,0 +1,220 @@
+/*
+ * 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.
+ *
+ * A small micro-assembler. It is intentionally kept simple, does only
+ * support a subset of instructions, and does not try to hide pipeline
+ * effects like branch delay slots.
+ *
+ * Copyright (C) 2004, 2005, 2006, 2008	 Thiemo Seufer
+ * Copyright (C) 2005, 2007  Maciej W. Rozycki
+ * Copyright (C) 2006  Ralf Baechle (ralf@linux-mips.org)
+ * Copyright (C) 2012, 2013   MIPS Technologies, Inc.  All rights reserved.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+
+#include <asm/inst.h>
+#include <asm/elf.h>
+#include <asm/bugs.h>
+#define UASM_ISA	_UASM_ISA_MICROMIPS
+#include <asm/uasm.h>
+
+#define RS_MASK		0x1f
+#define RS_SH		16
+#define RT_MASK		0x1f
+#define RT_SH		21
+#define SCIMM_MASK	0x3ff
+#define SCIMM_SH	16
+
+/* This macro sets the non-variable bits of an instruction. */
+#define M(a, b, c, d, e, f)					\
+	((a) << OP_SH						\
+	 | (b) << RT_SH						\
+	 | (c) << RS_SH						\
+	 | (d) << RD_SH						\
+	 | (e) << RE_SH						\
+	 | (f) << FUNC_SH)
+
+/* Define these when we are not the ISA the kernel is being compiled with. */
+#ifndef CONFIG_CPU_MICROMIPS
+#define MM_uasm_i_b(buf, off) ISAOPC(_beq)(buf, 0, 0, off)
+#define MM_uasm_i_beqz(buf, rs, off) ISAOPC(_beq)(buf, rs, 0, off)
+#define MM_uasm_i_beqzl(buf, rs, off) ISAOPC(_beql)(buf, rs, 0, off)
+#define MM_uasm_i_bnez(buf, rs, off) ISAOPC(_bne)(buf, rs, 0, off)
+#endif
+
+#include "uasm.c"
+
+static struct insn insn_table_MM[] __uasminitdata = {
+	{ insn_addu, M(mm_pool32a_op, 0, 0, 0, 0, mm_addu32_op), RT | RS | RD },
+	{ insn_addiu, M(mm_addiu32_op, 0, 0, 0, 0, 0), RT | RS | SIMM },
+	{ insn_and, M(mm_pool32a_op, 0, 0, 0, 0, mm_and_op), RT | RS | RD },
+	{ insn_andi, M(mm_andi32_op, 0, 0, 0, 0, 0), RT | RS | UIMM },
+	{ insn_beq, M(mm_beq32_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
+	{ insn_beql, 0, 0 },
+	{ insn_bgez, M(mm_pool32i_op, mm_bgez_op, 0, 0, 0, 0), RS | BIMM },
+	{ insn_bgezl, 0, 0 },
+	{ insn_bltz, M(mm_pool32i_op, mm_bltz_op, 0, 0, 0, 0), RS | BIMM },
+	{ insn_bltzl, 0, 0 },
+	{ insn_bne, M(mm_bne32_op, 0, 0, 0, 0, 0), RT | RS | BIMM },
+	{ insn_cache, M(mm_pool32b_op, 0, 0, mm_cache_func, 0, 0), RT | RS | SIMM },
+	{ insn_daddu, 0, 0 },
+	{ insn_daddiu, 0, 0 },
+	{ insn_dmfc0, 0, 0 },
+	{ insn_dmtc0, 0, 0 },
+	{ insn_dsll, 0, 0 },
+	{ insn_dsll32, 0, 0 },
+	{ insn_dsra, 0, 0 },
+	{ insn_dsrl, 0, 0 },
+	{ insn_dsrl32, 0, 0 },
+	{ insn_drotr, 0, 0 },
+	{ insn_drotr32, 0, 0 },
+	{ insn_dsubu, 0, 0 },
+	{ insn_eret, M(mm_pool32a_op, 0, 0, 0, mm_eret_op, mm_pool32axf_op), 0 },
+	{ insn_ins, M(mm_pool32a_op, 0, 0, 0, 0, mm_ins_op), RT | RS | RD | RE },
+	{ insn_ext, M(mm_pool32a_op, 0, 0, 0, 0, mm_ext_op), RT | RS | RD | RE },
+	{ insn_j, M(mm_j32_op, 0, 0, 0, 0, 0), JIMM },
+	{ insn_jal, M(mm_jal32_op, 0, 0, 0, 0, 0), JIMM },
+	{ insn_jr, M(mm_pool32a_op, 0, 0, 0, mm_jalr_op, mm_pool32axf_op), RS },
+	{ insn_ld, 0, 0 },
+	{ insn_ll, M(mm_pool32c_op, 0, 0, (mm_ll_func << 1), 0, 0), RS | RT | SIMM },
+	{ insn_lld, 0, 0 },
+	{ insn_lui, M(mm_pool32i_op, mm_lui_op, 0, 0, 0, 0), RS | SIMM },
+	{ insn_lw, M(mm_lw32_op, 0, 0, 0, 0, 0), RT | RS | SIMM },
+	{ insn_mfc0, M(mm_pool32a_op, 0, 0, 0, mm_mfc0_op, mm_pool32axf_op), RT | RS | RD },
+	{ insn_mtc0, M(mm_pool32a_op, 0, 0, 0, mm_mtc0_op, mm_pool32axf_op), RT | RS | RD },
+	{ insn_or, M(mm_pool32a_op, 0, 0, 0, 0, mm_or32_op), RT | RS | RD },
+	{ insn_ori, M(mm_ori32_op, 0, 0, 0, 0, 0), RT | RS | UIMM },
+	{ insn_pref, M(mm_pool32c_op, 0, 0, (mm_pref_func << 1), 0, 0), RT | RS | SIMM },
+	{ insn_rfe, 0, 0 },
+	{ insn_sc, M(mm_pool32c_op, 0, 0, (mm_sc_func << 1), 0, 0), RT | RS | SIMM },
+	{ insn_scd, 0, 0 },
+	{ insn_sd, 0, 0 },
+	{ insn_sll, M(mm_pool32a_op, 0, 0, 0, 0, mm_sll32_op), RT | RS | RD },
+	{ insn_sra, M(mm_pool32a_op, 0, 0, 0, 0, mm_sra_op), RT | RS | RD },
+	{ insn_srl, M(mm_pool32a_op, 0, 0, 0, 0, mm_srl32_op), RT | RS | RD },
+	{ insn_rotr, M(mm_pool32a_op, 0, 0, 0, 0, mm_rotr_op), RT | RS | RD },
+	{ insn_subu, M(mm_pool32a_op, 0, 0, 0, 0, mm_subu32_op), RT | RS | RD },
+	{ insn_sw, M(mm_sw32_op, 0, 0, 0, 0, 0), RT | RS | SIMM },
+	{ insn_tlbp, M(mm_pool32a_op, 0, 0, 0, mm_tlbp_op, mm_pool32axf_op), 0 },
+	{ insn_tlbr, M(mm_pool32a_op, 0, 0, 0, mm_tlbr_op, mm_pool32axf_op), 0 },
+	{ insn_tlbwi, M(mm_pool32a_op, 0, 0, 0, mm_tlbwi_op, mm_pool32axf_op), 0 },
+	{ insn_tlbwr, M(mm_pool32a_op, 0, 0, 0, mm_tlbwr_op, mm_pool32axf_op), 0 },
+	{ insn_xor, M(mm_pool32a_op, 0, 0, 0, 0, mm_xor32_op), RT | RS | RD },
+	{ insn_xori, M(mm_xori32_op, 0, 0, 0, 0, 0), RT | RS | UIMM },
+	{ insn_dins, 0, 0 },
+	{ insn_dinsm, 0, 0 },
+	{ insn_syscall, M(mm_pool32a_op, 0, 0, 0, mm_syscall_op, mm_pool32axf_op), SCIMM},
+	{ insn_bbit0, 0, 0 },
+	{ insn_bbit1, 0, 0 },
+	{ insn_lwx, 0, 0 },
+	{ insn_ldx, 0, 0 },
+	{ insn_invalid, 0, 0 }
+};
+
+#undef M
+
+static inline __uasminit u32 build_bimm(s32 arg)
+{
+	WARN(arg > 0xffff || arg < -0x10000,
+	     KERN_WARNING "Micro-assembler field overflow\n");
+
+	WARN(arg & 0x3, KERN_WARNING "Invalid micro-assembler branch target\n");
+
+	return ((arg < 0) ? (1 << 15) : 0) | ((arg >> 1) & 0x7fff);
+}
+
+static inline __uasminit u32 build_jimm(u32 arg)
+{
+	WARN(arg & ~(JIMM_MASK << 2),
+	     KERN_WARNING "Micro-assembler field overflow\n");
+
+	return (arg >> 1) & JIMM_MASK;
+}
+
+/*
+ * The order of opcode arguments is implicitly left to right,
+ * starting with RS and ending with FUNC or IMM.
+ */
+static void __uasminit build_insn(u32 **buf, enum opcode opc, ...)
+{
+	struct insn *ip = NULL;
+	unsigned int i;
+	va_list ap;
+	u32 op;
+
+	for (i = 0; insn_table_MM[i].opcode != insn_invalid; i++)
+		if (insn_table_MM[i].opcode == opc) {
+			ip = &insn_table_MM[i];
+			break;
+		}
+
+	if (!ip || (opc == insn_daddiu && r4k_daddiu_bug()))
+		panic("Unsupported Micro-assembler instruction %d", opc);
+
+	op = ip->match;
+	va_start(ap, opc);
+	if (ip->fields & RS) {
+		if (opc == insn_mfc0 || opc == insn_mtc0)
+			op |= build_rt(va_arg(ap, u32));
+		else
+			op |= build_rs(va_arg(ap, u32));
+	}
+	if (ip->fields & RT) {
+		if (opc == insn_mfc0 || opc == insn_mtc0)
+			op |= build_rs(va_arg(ap, u32));
+		else
+			op |= build_rt(va_arg(ap, u32));
+	}
+	if (ip->fields & RD)
+		op |= build_rd(va_arg(ap, u32));
+	if (ip->fields & RE)
+		op |= build_re(va_arg(ap, u32));
+	if (ip->fields & SIMM)
+		op |= build_simm(va_arg(ap, s32));
+	if (ip->fields & UIMM)
+		op |= build_uimm(va_arg(ap, u32));
+	if (ip->fields & BIMM)
+		op |= build_bimm(va_arg(ap, s32));
+	if (ip->fields & JIMM)
+		op |= build_jimm(va_arg(ap, u32));
+	if (ip->fields & FUNC)
+		op |= build_func(va_arg(ap, u32));
+	if (ip->fields & SET)
+		op |= build_set(va_arg(ap, u32));
+	if (ip->fields & SCIMM)
+		op |= build_scimm(va_arg(ap, u32));
+	va_end(ap);
+
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+	**buf = ((op & 0xffff) << 16) | (op >> 16);
+#else
+	**buf = op;
+#endif
+	(*buf)++;
+}
+
+static inline void __uasminit
+__resolve_relocs(struct uasm_reloc *rel, struct uasm_label *lab)
+{
+	long laddr = (long)lab->addr;
+	long raddr = (long)rel->addr;
+
+	switch (rel->type) {
+	case R_MIPS_PC16:
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+		*rel->addr |= (build_bimm(laddr - (raddr + 4)) << 16);
+#else
+		*rel->addr |= build_bimm(laddr - (raddr + 4));
+#endif
+		break;
+
+	default:
+		panic("Unsupported Micro-assembler relocation %d",
+		      rel->type);
+	}
+}
diff --git a/arch/mips/mm/uasm-mips.c b/arch/mips/mm/uasm-mips.c
new file mode 100644
index 0000000..e78e74d
--- /dev/null
+++ b/arch/mips/mm/uasm-mips.c
@@ -0,0 +1,196 @@
+/*
+ * 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.
+ *
+ * A small micro-assembler. It is intentionally kept simple, does only
+ * support a subset of instructions, and does not try to hide pipeline
+ * effects like branch delay slots.
+ *
+ * Copyright (C) 2004, 2005, 2006, 2008	 Thiemo Seufer
+ * Copyright (C) 2005, 2007  Maciej W. Rozycki
+ * Copyright (C) 2006  Ralf Baechle (ralf@linux-mips.org)
+ * Copyright (C) 2012, 2013  MIPS Technologies, Inc.  All rights reserved.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+
+#include <asm/inst.h>
+#include <asm/elf.h>
+#include <asm/bugs.h>
+#include <asm/uasm.h>
+
+#define RS_MASK		0x1f
+#define RS_SH		21
+#define RT_MASK		0x1f
+#define RT_SH		16
+#define SCIMM_MASK	0xfffff
+#define SCIMM_SH	6
+
+/* This macro sets the non-variable bits of an instruction. */
+#define M(a, b, c, d, e, f)					\
+	((a) << OP_SH						\
+	 | (b) << RS_SH						\
+	 | (c) << RT_SH						\
+	 | (d) << RD_SH						\
+	 | (e) << RE_SH						\
+	 | (f) << FUNC_SH)
+
+#include "uasm.c"
+
+static struct insn insn_table[] __uasminitdata = {
+	{ insn_addiu, M(addiu_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
+	{ insn_addu, M(spec_op, 0, 0, 0, 0, addu_op), RS | RT | RD },
+	{ insn_andi, M(andi_op, 0, 0, 0, 0, 0), RS | RT | UIMM },
+	{ insn_and, M(spec_op, 0, 0, 0, 0, and_op), RS | RT | RD },
+	{ insn_bbit0, M(lwc2_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
+	{ insn_bbit1, M(swc2_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
+	{ insn_beql, M(beql_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
+	{ insn_beq, M(beq_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
+	{ insn_bgezl, M(bcond_op, 0, bgezl_op, 0, 0, 0), RS | BIMM },
+	{ insn_bgez, M(bcond_op, 0, bgez_op, 0, 0, 0), RS | BIMM },
+	{ insn_bltzl, M(bcond_op, 0, bltzl_op, 0, 0, 0), RS | BIMM },
+	{ insn_bltz, M(bcond_op, 0, bltz_op, 0, 0, 0), RS | BIMM },
+	{ insn_bne, M(bne_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
+	{ insn_cache,  M(cache_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
+	{ insn_daddiu, M(daddiu_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
+	{ insn_daddu, M(spec_op, 0, 0, 0, 0, daddu_op), RS | RT | RD },
+	{ insn_dinsm, M(spec3_op, 0, 0, 0, 0, dinsm_op), RS | RT | RD | RE },
+	{ insn_dins, M(spec3_op, 0, 0, 0, 0, dins_op), RS | RT | RD | RE },
+	{ insn_dmfc0, M(cop0_op, dmfc_op, 0, 0, 0, 0), RT | RD | SET},
+	{ insn_dmtc0, M(cop0_op, dmtc_op, 0, 0, 0, 0), RT | RD | SET},
+	{ insn_drotr32, M(spec_op, 1, 0, 0, 0, dsrl32_op), RT | RD | RE },
+	{ insn_drotr, M(spec_op, 1, 0, 0, 0, dsrl_op), RT | RD | RE },
+	{ insn_dsll32, M(spec_op, 0, 0, 0, 0, dsll32_op), RT | RD | RE },
+	{ insn_dsll, M(spec_op, 0, 0, 0, 0, dsll_op), RT | RD | RE },
+	{ insn_dsra, M(spec_op, 0, 0, 0, 0, dsra_op), RT | RD | RE },
+	{ insn_dsrl32, M(spec_op, 0, 0, 0, 0, dsrl32_op), RT | RD | RE },
+	{ insn_dsrl, M(spec_op, 0, 0, 0, 0, dsrl_op), RT | RD | RE },
+	{ insn_dsubu, M(spec_op, 0, 0, 0, 0, dsubu_op), RS | RT | RD },
+	{ insn_eret,  M(cop0_op, cop_op, 0, 0, 0, eret_op),  0 },
+	{ insn_ext, M(spec3_op, 0, 0, 0, 0, ext_op), RS | RT | RD | RE },
+	{ insn_ins, M(spec3_op, 0, 0, 0, 0, ins_op), RS | RT | RD | RE },
+	{ insn_j,  M(j_op, 0, 0, 0, 0, 0),  JIMM },
+	{ insn_jal,  M(jal_op, 0, 0, 0, 0, 0),	JIMM },
+	{ insn_j,  M(j_op, 0, 0, 0, 0, 0),  JIMM },
+	{ insn_jr,  M(spec_op, 0, 0, 0, 0, jr_op),  RS },
+	{ insn_ld,  M(ld_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
+	{ insn_ldx, M(spec3_op, 0, 0, 0, ldx_op, lx_op), RS | RT | RD },
+	{ insn_lld,  M(lld_op, 0, 0, 0, 0, 0),	RS | RT | SIMM },
+	{ insn_ll,  M(ll_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
+	{ insn_lui,  M(lui_op, 0, 0, 0, 0, 0),	RT | SIMM },
+	{ insn_lw,  M(lw_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
+	{ insn_lwx, M(spec3_op, 0, 0, 0, lwx_op, lx_op), RS | RT | RD },
+	{ insn_mfc0,  M(cop0_op, mfc_op, 0, 0, 0, 0),  RT | RD | SET},
+	{ insn_mtc0,  M(cop0_op, mtc_op, 0, 0, 0, 0),  RT | RD | SET},
+	{ insn_ori,  M(ori_op, 0, 0, 0, 0, 0),	RS | RT | UIMM },
+	{ insn_or,  M(spec_op, 0, 0, 0, 0, or_op),  RS | RT | RD },
+	{ insn_pref,  M(pref_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
+	{ insn_rfe,  M(cop0_op, cop_op, 0, 0, 0, rfe_op),  0 },
+	{ insn_rotr,  M(spec_op, 1, 0, 0, 0, srl_op),  RT | RD | RE },
+	{ insn_scd,  M(scd_op, 0, 0, 0, 0, 0),	RS | RT | SIMM },
+	{ insn_sc,  M(sc_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
+	{ insn_sd,  M(sd_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
+	{ insn_sll,  M(spec_op, 0, 0, 0, 0, sll_op),  RT | RD | RE },
+	{ insn_sra,  M(spec_op, 0, 0, 0, 0, sra_op),  RT | RD | RE },
+	{ insn_srl,  M(spec_op, 0, 0, 0, 0, srl_op),  RT | RD | RE },
+	{ insn_subu,  M(spec_op, 0, 0, 0, 0, subu_op),	RS | RT | RD },
+	{ insn_sw,  M(sw_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
+	{ insn_syscall, M(spec_op, 0, 0, 0, 0, syscall_op), SCIMM},
+	{ insn_tlbp,  M(cop0_op, cop_op, 0, 0, 0, tlbp_op),  0 },
+	{ insn_tlbr,  M(cop0_op, cop_op, 0, 0, 0, tlbr_op),  0 },
+	{ insn_tlbwi,  M(cop0_op, cop_op, 0, 0, 0, tlbwi_op),  0 },
+	{ insn_tlbwr,  M(cop0_op, cop_op, 0, 0, 0, tlbwr_op),  0 },
+	{ insn_xori,  M(xori_op, 0, 0, 0, 0, 0),  RS | RT | UIMM },
+	{ insn_xor,  M(spec_op, 0, 0, 0, 0, xor_op),  RS | RT | RD },
+	{ insn_invalid, 0, 0 }
+};
+
+#undef M
+
+static inline __uasminit u32 build_bimm(s32 arg)
+{
+	WARN(arg > 0x1ffff || arg < -0x20000,
+	     KERN_WARNING "Micro-assembler field overflow\n");
+
+	WARN(arg & 0x3, KERN_WARNING "Invalid micro-assembler branch target\n");
+
+	return ((arg < 0) ? (1 << 15) : 0) | ((arg >> 2) & 0x7fff);
+}
+
+static inline __uasminit u32 build_jimm(u32 arg)
+{
+	WARN(arg & ~(JIMM_MASK << 2),
+	     KERN_WARNING "Micro-assembler field overflow\n");
+
+	return (arg >> 2) & JIMM_MASK;
+}
+
+/*
+ * The order of opcode arguments is implicitly left to right,
+ * starting with RS and ending with FUNC or IMM.
+ */
+static void __uasminit build_insn(u32 **buf, enum opcode opc, ...)
+{
+	struct insn *ip = NULL;
+	unsigned int i;
+	va_list ap;
+	u32 op;
+
+	for (i = 0; insn_table[i].opcode != insn_invalid; i++)
+		if (insn_table[i].opcode == opc) {
+			ip = &insn_table[i];
+			break;
+		}
+
+	if (!ip || (opc == insn_daddiu && r4k_daddiu_bug()))
+		panic("Unsupported Micro-assembler instruction %d", opc);
+
+	op = ip->match;
+	va_start(ap, opc);
+	if (ip->fields & RS)
+		op |= build_rs(va_arg(ap, u32));
+	if (ip->fields & RT)
+		op |= build_rt(va_arg(ap, u32));
+	if (ip->fields & RD)
+		op |= build_rd(va_arg(ap, u32));
+	if (ip->fields & RE)
+		op |= build_re(va_arg(ap, u32));
+	if (ip->fields & SIMM)
+		op |= build_simm(va_arg(ap, s32));
+	if (ip->fields & UIMM)
+		op |= build_uimm(va_arg(ap, u32));
+	if (ip->fields & BIMM)
+		op |= build_bimm(va_arg(ap, s32));
+	if (ip->fields & JIMM)
+		op |= build_jimm(va_arg(ap, u32));
+	if (ip->fields & FUNC)
+		op |= build_func(va_arg(ap, u32));
+	if (ip->fields & SET)
+		op |= build_set(va_arg(ap, u32));
+	if (ip->fields & SCIMM)
+		op |= build_scimm(va_arg(ap, u32));
+	va_end(ap);
+
+	**buf = op;
+	(*buf)++;
+}
+
+static inline void __uasminit
+__resolve_relocs(struct uasm_reloc *rel, struct uasm_label *lab)
+{
+	long laddr = (long)lab->addr;
+	long raddr = (long)rel->addr;
+
+	switch (rel->type) {
+	case R_MIPS_PC16:
+		*rel->addr |= build_bimm(laddr - (raddr + 4));
+		break;
+
+	default:
+		panic("Unsupported Micro-assembler relocation %d",
+		      rel->type);
+	}
+}
diff --git a/arch/mips/mm/uasm.c b/arch/mips/mm/uasm.c
index 942ff6c..7eb5e43 100644
--- a/arch/mips/mm/uasm.c
+++ b/arch/mips/mm/uasm.c
@@ -10,17 +10,9 @@
  * Copyright (C) 2004, 2005, 2006, 2008	 Thiemo Seufer
  * Copyright (C) 2005, 2007  Maciej W. Rozycki
  * Copyright (C) 2006  Ralf Baechle (ralf@linux-mips.org)
+ * Copyright (C) 2012, 2013  MIPS Technologies, Inc.  All rights reserved.
  */
 
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/init.h>
-
-#include <asm/inst.h>
-#include <asm/elf.h>
-#include <asm/bugs.h>
-#include <asm/uasm.h>
-
 enum fields {
 	RS = 0x001,
 	RT = 0x002,
@@ -37,10 +29,6 @@ enum fields {
 
 #define OP_MASK		0x3f
 #define OP_SH		26
-#define RS_MASK		0x1f
-#define RS_SH		21
-#define RT_MASK		0x1f
-#define RT_SH		16
 #define RD_MASK		0x1f
 #define RD_SH		11
 #define RE_MASK		0x1f
@@ -53,8 +41,6 @@ enum fields {
 #define FUNC_SH		0
 #define SET_MASK	0x7
 #define SET_SH		0
-#define SCIMM_MASK	0xfffff
-#define SCIMM_SH	6
 
 enum opcode {
 	insn_invalid,
@@ -77,85 +63,6 @@ struct insn {
 	enum fields fields;
 };
 
-/* This macro sets the non-variable bits of an instruction. */
-#define M(a, b, c, d, e, f)					\
-	((a) << OP_SH						\
-	 | (b) << RS_SH						\
-	 | (c) << RT_SH						\
-	 | (d) << RD_SH						\
-	 | (e) << RE_SH						\
-	 | (f) << FUNC_SH)
-
-static struct insn insn_table[] __uasminitdata = {
-	{ insn_addiu, M(addiu_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
-	{ insn_addu, M(spec_op, 0, 0, 0, 0, addu_op), RS | RT | RD },
-	{ insn_andi, M(andi_op, 0, 0, 0, 0, 0), RS | RT | UIMM },
-	{ insn_and, M(spec_op, 0, 0, 0, 0, and_op), RS | RT | RD },
-	{ insn_bbit0, M(lwc2_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
-	{ insn_bbit1, M(swc2_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
-	{ insn_beql, M(beql_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
-	{ insn_beq, M(beq_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
-	{ insn_bgezl, M(bcond_op, 0, bgezl_op, 0, 0, 0), RS | BIMM },
-	{ insn_bgez, M(bcond_op, 0, bgez_op, 0, 0, 0), RS | BIMM },
-	{ insn_bltzl, M(bcond_op, 0, bltzl_op, 0, 0, 0), RS | BIMM },
-	{ insn_bltz, M(bcond_op, 0, bltz_op, 0, 0, 0), RS | BIMM },
-	{ insn_bne, M(bne_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
-	{ insn_cache,  M(cache_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
-	{ insn_daddiu, M(daddiu_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
-	{ insn_daddu, M(spec_op, 0, 0, 0, 0, daddu_op), RS | RT | RD },
-	{ insn_dinsm, M(spec3_op, 0, 0, 0, 0, dinsm_op), RS | RT | RD | RE },
-	{ insn_dins, M(spec3_op, 0, 0, 0, 0, dins_op), RS | RT | RD | RE },
-	{ insn_dmfc0, M(cop0_op, dmfc_op, 0, 0, 0, 0), RT | RD | SET},
-	{ insn_dmtc0, M(cop0_op, dmtc_op, 0, 0, 0, 0), RT | RD | SET},
-	{ insn_drotr32, M(spec_op, 1, 0, 0, 0, dsrl32_op), RT | RD | RE },
-	{ insn_drotr, M(spec_op, 1, 0, 0, 0, dsrl_op), RT | RD | RE },
-	{ insn_dsll32, M(spec_op, 0, 0, 0, 0, dsll32_op), RT | RD | RE },
-	{ insn_dsll, M(spec_op, 0, 0, 0, 0, dsll_op), RT | RD | RE },
-	{ insn_dsra, M(spec_op, 0, 0, 0, 0, dsra_op), RT | RD | RE },
-	{ insn_dsrl32, M(spec_op, 0, 0, 0, 0, dsrl32_op), RT | RD | RE },
-	{ insn_dsrl, M(spec_op, 0, 0, 0, 0, dsrl_op), RT | RD | RE },
-	{ insn_dsubu, M(spec_op, 0, 0, 0, 0, dsubu_op), RS | RT | RD },
-	{ insn_eret,  M(cop0_op, cop_op, 0, 0, 0, eret_op),  0 },
-	{ insn_ext, M(spec3_op, 0, 0, 0, 0, ext_op), RS | RT | RD | RE },
-	{ insn_ins, M(spec3_op, 0, 0, 0, 0, ins_op), RS | RT | RD | RE },
-	{ insn_j,  M(j_op, 0, 0, 0, 0, 0),  JIMM },
-	{ insn_jal,  M(jal_op, 0, 0, 0, 0, 0),	JIMM },
-	{ insn_j,  M(j_op, 0, 0, 0, 0, 0),  JIMM },
-	{ insn_jr,  M(spec_op, 0, 0, 0, 0, jr_op),  RS },
-	{ insn_ld,  M(ld_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
-	{ insn_ldx, M(spec3_op, 0, 0, 0, ldx_op, lx_op), RS | RT | RD },
-	{ insn_lld,  M(lld_op, 0, 0, 0, 0, 0),	RS | RT | SIMM },
-	{ insn_ll,  M(ll_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
-	{ insn_lui,  M(lui_op, 0, 0, 0, 0, 0),	RT | SIMM },
-	{ insn_lw,  M(lw_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
-	{ insn_lwx, M(spec3_op, 0, 0, 0, lwx_op, lx_op), RS | RT | RD },
-	{ insn_mfc0,  M(cop0_op, mfc_op, 0, 0, 0, 0),  RT | RD | SET},
-	{ insn_mtc0,  M(cop0_op, mtc_op, 0, 0, 0, 0),  RT | RD | SET},
-	{ insn_ori,  M(ori_op, 0, 0, 0, 0, 0),	RS | RT | UIMM },
-	{ insn_or,  M(spec_op, 0, 0, 0, 0, or_op),  RS | RT | RD },
-	{ insn_pref,  M(pref_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
-	{ insn_rfe,  M(cop0_op, cop_op, 0, 0, 0, rfe_op),  0 },
-	{ insn_rotr,  M(spec_op, 1, 0, 0, 0, srl_op),  RT | RD | RE },
-	{ insn_scd,  M(scd_op, 0, 0, 0, 0, 0),	RS | RT | SIMM },
-	{ insn_sc,  M(sc_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
-	{ insn_sd,  M(sd_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
-	{ insn_sll,  M(spec_op, 0, 0, 0, 0, sll_op),  RT | RD | RE },
-	{ insn_sra,  M(spec_op, 0, 0, 0, 0, sra_op),  RT | RD | RE },
-	{ insn_srl,  M(spec_op, 0, 0, 0, 0, srl_op),  RT | RD | RE },
-	{ insn_subu,  M(spec_op, 0, 0, 0, 0, subu_op),	RS | RT | RD },
-	{ insn_sw,  M(sw_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
-	{ insn_syscall, M(spec_op, 0, 0, 0, 0, syscall_op), SCIMM},
-	{ insn_tlbp,  M(cop0_op, cop_op, 0, 0, 0, tlbp_op),  0 },
-	{ insn_tlbr,  M(cop0_op, cop_op, 0, 0, 0, tlbr_op),  0 },
-	{ insn_tlbwi,  M(cop0_op, cop_op, 0, 0, 0, tlbwi_op),  0 },
-	{ insn_tlbwr,  M(cop0_op, cop_op, 0, 0, 0, tlbwr_op),  0 },
-	{ insn_xori,  M(xori_op, 0, 0, 0, 0, 0),  RS | RT | UIMM },
-	{ insn_xor,  M(spec_op, 0, 0, 0, 0, xor_op),  RS | RT | RD },
-	{ insn_invalid, 0, 0 }
-};
-
-#undef M
-
 static inline __uasminit u32 build_rs(u32 arg)
 {
 	WARN(arg & ~RS_MASK, KERN_WARNING "Micro-assembler field overflow\n");
@@ -199,24 +106,6 @@ static inline __uasminit u32 build_uimm(u32 arg)
 	return arg & IMM_MASK;
 }
 
-static inline __uasminit u32 build_bimm(s32 arg)
-{
-	WARN(arg > 0x1ffff || arg < -0x20000,
-	     KERN_WARNING "Micro-assembler field overflow\n");
-
-	WARN(arg & 0x3, KERN_WARNING "Invalid micro-assembler branch target\n");
-
-	return ((arg < 0) ? (1 << 15) : 0) | ((arg >> 2) & 0x7fff);
-}
-
-static inline __uasminit u32 build_jimm(u32 arg)
-{
-	WARN(arg & ~(JIMM_MASK << 2),
-	     KERN_WARNING "Micro-assembler field overflow\n");
-
-	return (arg >> 2) & JIMM_MASK;
-}
-
 static inline __uasminit u32 build_scimm(u32 arg)
 {
 	WARN(arg & ~SCIMM_MASK,
@@ -239,55 +128,7 @@ static inline __uasminit u32 build_set(u32 arg)
 	return arg & SET_MASK;
 }
 
-/*
- * The order of opcode arguments is implicitly left to right,
- * starting with RS and ending with FUNC or IMM.
- */
-static void __uasminit build_insn(u32 **buf, enum opcode opc, ...)
-{
-	struct insn *ip = NULL;
-	unsigned int i;
-	va_list ap;
-	u32 op;
-
-	for (i = 0; insn_table[i].opcode != insn_invalid; i++)
-		if (insn_table[i].opcode == opc) {
-			ip = &insn_table[i];
-			break;
-		}
-
-	if (!ip || (opc == insn_daddiu && r4k_daddiu_bug()))
-		panic("Unsupported Micro-assembler instruction %d", opc);
-
-	op = ip->match;
-	va_start(ap, opc);
-	if (ip->fields & RS)
-		op |= build_rs(va_arg(ap, u32));
-	if (ip->fields & RT)
-		op |= build_rt(va_arg(ap, u32));
-	if (ip->fields & RD)
-		op |= build_rd(va_arg(ap, u32));
-	if (ip->fields & RE)
-		op |= build_re(va_arg(ap, u32));
-	if (ip->fields & SIMM)
-		op |= build_simm(va_arg(ap, s32));
-	if (ip->fields & UIMM)
-		op |= build_uimm(va_arg(ap, u32));
-	if (ip->fields & BIMM)
-		op |= build_bimm(va_arg(ap, s32));
-	if (ip->fields & JIMM)
-		op |= build_jimm(va_arg(ap, u32));
-	if (ip->fields & FUNC)
-		op |= build_func(va_arg(ap, u32));
-	if (ip->fields & SET)
-		op |= build_set(va_arg(ap, u32));
-	if (ip->fields & SCIMM)
-		op |= build_scimm(va_arg(ap, u32));
-	va_end(ap);
-
-	**buf = op;
-	(*buf)++;
-}
+static void __uasminit build_insn(u32 **buf, enum opcode opc, ...);
 
 #define I_u1u2u3(op)					\
 Ip_u1u2u3(op)						\
@@ -445,7 +286,7 @@ I_u3u1u2(_ldx)
 
 #ifdef CONFIG_CPU_CAVIUM_OCTEON
 #include <asm/octeon/octeon.h>
-void __uasminit uasm_i_pref(u32 **buf, unsigned int a, signed int b,
+void __uasminit ISAFUNC(uasm_i_pref)(u32 **buf, unsigned int a, signed int b,
 			    unsigned int c)
 {
 	if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X) && a <= 24 && a != 5)
@@ -457,21 +298,21 @@ void __uasminit uasm_i_pref(u32 **buf, unsigned int a, signed int b,
 	else
 		build_insn(buf, insn_pref, c, a, b);
 }
-UASM_EXPORT_SYMBOL(uasm_i_pref);
+UASM_EXPORT_SYMBOL(ISAFUNC(uasm_i_pref));
 #else
 I_u2s3u1(_pref)
 #endif
 
 /* Handle labels. */
-void __uasminit uasm_build_label(struct uasm_label **lab, u32 *addr, int lid)
+void __uasminit ISAFUNC(uasm_build_label)(struct uasm_label **lab, u32 *addr, int lid)
 {
 	(*lab)->addr = addr;
 	(*lab)->lab = lid;
 	(*lab)++;
 }
-UASM_EXPORT_SYMBOL(uasm_build_label);
+UASM_EXPORT_SYMBOL(ISAFUNC(uasm_build_label));
 
-int __uasminit uasm_in_compat_space_p(long addr)
+int __uasminit ISAFUNC(uasm_in_compat_space_p)(long addr)
 {
 	/* Is this address in 32bit compat space? */
 #ifdef CONFIG_64BIT
@@ -480,7 +321,7 @@ int __uasminit uasm_in_compat_space_p(long addr)
 	return 1;
 #endif
 }
-UASM_EXPORT_SYMBOL(uasm_in_compat_space_p);
+UASM_EXPORT_SYMBOL(ISAFUNC(uasm_in_compat_space_p));
 
 static int __uasminit uasm_rel_highest(long val)
 {
@@ -500,77 +341,66 @@ static int __uasminit uasm_rel_higher(long val)
 #endif
 }
 
-int __uasminit uasm_rel_hi(long val)
+int __uasminit ISAFUNC(uasm_rel_hi)(long val)
 {
 	return ((((val + 0x8000L) >> 16) & 0xffff) ^ 0x8000) - 0x8000;
 }
-UASM_EXPORT_SYMBOL(uasm_rel_hi);
+UASM_EXPORT_SYMBOL(ISAFUNC(uasm_rel_hi));
 
-int __uasminit uasm_rel_lo(long val)
+int __uasminit ISAFUNC(uasm_rel_lo)(long val)
 {
 	return ((val & 0xffff) ^ 0x8000) - 0x8000;
 }
-UASM_EXPORT_SYMBOL(uasm_rel_lo);
+UASM_EXPORT_SYMBOL(ISAFUNC(uasm_rel_lo));
 
-void __uasminit UASM_i_LA_mostly(u32 **buf, unsigned int rs, long addr)
+void __uasminit ISAFUNC(UASM_i_LA_mostly)(u32 **buf, unsigned int rs, long addr)
 {
-	if (!uasm_in_compat_space_p(addr)) {
-		uasm_i_lui(buf, rs, uasm_rel_highest(addr));
+	if (!ISAFUNC(uasm_in_compat_space_p)(addr)) {
+		ISAFUNC(uasm_i_lui)(buf, rs, uasm_rel_highest(addr));
 		if (uasm_rel_higher(addr))
-			uasm_i_daddiu(buf, rs, rs, uasm_rel_higher(addr));
-		if (uasm_rel_hi(addr)) {
-			uasm_i_dsll(buf, rs, rs, 16);
-			uasm_i_daddiu(buf, rs, rs, uasm_rel_hi(addr));
-			uasm_i_dsll(buf, rs, rs, 16);
+			ISAFUNC(uasm_i_daddiu)(buf, rs, rs, uasm_rel_higher(addr));
+		if (ISAFUNC(uasm_rel_hi(addr))) {
+			ISAFUNC(uasm_i_dsll)(buf, rs, rs, 16);
+			ISAFUNC(uasm_i_daddiu)(buf, rs, rs,
+					ISAFUNC(uasm_rel_hi)(addr));
+			ISAFUNC(uasm_i_dsll)(buf, rs, rs, 16);
 		} else
-			uasm_i_dsll32(buf, rs, rs, 0);
+			ISAFUNC(uasm_i_dsll32)(buf, rs, rs, 0);
 	} else
-		uasm_i_lui(buf, rs, uasm_rel_hi(addr));
+		ISAFUNC(uasm_i_lui)(buf, rs, ISAFUNC(uasm_rel_hi(addr)));
 }
-UASM_EXPORT_SYMBOL(UASM_i_LA_mostly);
+UASM_EXPORT_SYMBOL(ISAFUNC(UASM_i_LA_mostly));
 
-void __uasminit UASM_i_LA(u32 **buf, unsigned int rs, long addr)
+void __uasminit ISAFUNC(UASM_i_LA)(u32 **buf, unsigned int rs, long addr)
 {
-	UASM_i_LA_mostly(buf, rs, addr);
-	if (uasm_rel_lo(addr)) {
-		if (!uasm_in_compat_space_p(addr))
-			uasm_i_daddiu(buf, rs, rs, uasm_rel_lo(addr));
+	ISAFUNC(UASM_i_LA_mostly)(buf, rs, addr);
+	if (ISAFUNC(uasm_rel_lo(addr))) {
+		if (!ISAFUNC(uasm_in_compat_space_p)(addr))
+			ISAFUNC(uasm_i_daddiu)(buf, rs, rs,
+					ISAFUNC(uasm_rel_lo(addr)));
 		else
-			uasm_i_addiu(buf, rs, rs, uasm_rel_lo(addr));
+			ISAFUNC(uasm_i_addiu)(buf, rs, rs,
+					ISAFUNC(uasm_rel_lo(addr)));
 	}
 }
-UASM_EXPORT_SYMBOL(UASM_i_LA);
+UASM_EXPORT_SYMBOL(ISAFUNC(UASM_i_LA));
 
 /* Handle relocations. */
 void __uasminit
-uasm_r_mips_pc16(struct uasm_reloc **rel, u32 *addr, int lid)
+ISAFUNC(uasm_r_mips_pc16)(struct uasm_reloc **rel, u32 *addr, int lid)
 {
 	(*rel)->addr = addr;
 	(*rel)->type = R_MIPS_PC16;
 	(*rel)->lab = lid;
 	(*rel)++;
 }
-UASM_EXPORT_SYMBOL(uasm_r_mips_pc16);
+UASM_EXPORT_SYMBOL(ISAFUNC(uasm_r_mips_pc16));
 
 static inline void __uasminit
-__resolve_relocs(struct uasm_reloc *rel, struct uasm_label *lab)
-{
-	long laddr = (long)lab->addr;
-	long raddr = (long)rel->addr;
-
-	switch (rel->type) {
-	case R_MIPS_PC16:
-		*rel->addr |= build_bimm(laddr - (raddr + 4));
-		break;
-
-	default:
-		panic("Unsupported Micro-assembler relocation %d",
-		      rel->type);
-	}
-}
+__resolve_relocs(struct uasm_reloc *rel, struct uasm_label *lab);
 
 void __uasminit
-uasm_resolve_relocs(struct uasm_reloc *rel, struct uasm_label *lab)
+ISAFUNC(uasm_resolve_relocs)(struct uasm_reloc *rel, struct uasm_label *lab)
 {
 	struct uasm_label *l;
 
@@ -579,40 +409,40 @@ uasm_resolve_relocs(struct uasm_reloc *rel, struct uasm_label *lab)
 			if (rel->lab == l->lab)
 				__resolve_relocs(rel, l);
 }
-UASM_EXPORT_SYMBOL(uasm_resolve_relocs);
+UASM_EXPORT_SYMBOL(ISAFUNC(uasm_resolve_relocs));
 
 void __uasminit
-uasm_move_relocs(struct uasm_reloc *rel, u32 *first, u32 *end, long off)
+ISAFUNC(uasm_move_relocs)(struct uasm_reloc *rel, u32 *first, u32 *end, long off)
 {
 	for (; rel->lab != UASM_LABEL_INVALID; rel++)
 		if (rel->addr >= first && rel->addr < end)
 			rel->addr += off;
 }
-UASM_EXPORT_SYMBOL(uasm_move_relocs);
+UASM_EXPORT_SYMBOL(ISAFUNC(uasm_move_relocs));
 
 void __uasminit
-uasm_move_labels(struct uasm_label *lab, u32 *first, u32 *end, long off)
+ISAFUNC(uasm_move_labels)(struct uasm_label *lab, u32 *first, u32 *end, long off)
 {
 	for (; lab->lab != UASM_LABEL_INVALID; lab++)
 		if (lab->addr >= first && lab->addr < end)
 			lab->addr += off;
 }
-UASM_EXPORT_SYMBOL(uasm_move_labels);
+UASM_EXPORT_SYMBOL(ISAFUNC(uasm_move_labels));
 
 void __uasminit
-uasm_copy_handler(struct uasm_reloc *rel, struct uasm_label *lab, u32 *first,
+ISAFUNC(uasm_copy_handler)(struct uasm_reloc *rel, struct uasm_label *lab, u32 *first,
 		  u32 *end, u32 *target)
 {
 	long off = (long)(target - first);
 
 	memcpy(target, first, (end - first) * sizeof(u32));
 
-	uasm_move_relocs(rel, first, end, off);
-	uasm_move_labels(lab, first, end, off);
+	ISAFUNC(uasm_move_relocs(rel, first, end, off));
+	ISAFUNC(uasm_move_labels(lab, first, end, off));
 }
-UASM_EXPORT_SYMBOL(uasm_copy_handler);
+UASM_EXPORT_SYMBOL(ISAFUNC(uasm_copy_handler));
 
-int __uasminit uasm_insn_has_bdelay(struct uasm_reloc *rel, u32 *addr)
+int __uasminit ISAFUNC(uasm_insn_has_bdelay)(struct uasm_reloc *rel, u32 *addr)
 {
 	for (; rel->lab != UASM_LABEL_INVALID; rel++) {
 		if (rel->addr == addr
@@ -623,88 +453,88 @@ int __uasminit uasm_insn_has_bdelay(struct uasm_reloc *rel, u32 *addr)
 
 	return 0;
 }
-UASM_EXPORT_SYMBOL(uasm_insn_has_bdelay);
+UASM_EXPORT_SYMBOL(ISAFUNC(uasm_insn_has_bdelay));
 
 /* Convenience functions for labeled branches. */
 void __uasminit
-uasm_il_bltz(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid)
+ISAFUNC(uasm_il_bltz)(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid)
 {
 	uasm_r_mips_pc16(r, *p, lid);
-	uasm_i_bltz(p, reg, 0);
+	ISAFUNC(uasm_i_bltz)(p, reg, 0);
 }
-UASM_EXPORT_SYMBOL(uasm_il_bltz);
+UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_bltz));
 
 void __uasminit
-uasm_il_b(u32 **p, struct uasm_reloc **r, int lid)
+ISAFUNC(uasm_il_b)(u32 **p, struct uasm_reloc **r, int lid)
 {
 	uasm_r_mips_pc16(r, *p, lid);
-	uasm_i_b(p, 0);
+	ISAFUNC(uasm_i_b)(p, 0);
 }
-UASM_EXPORT_SYMBOL(uasm_il_b);
+UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_b));
 
 void __uasminit
-uasm_il_beqz(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid)
+ISAFUNC(uasm_il_beqz)(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid)
 {
 	uasm_r_mips_pc16(r, *p, lid);
-	uasm_i_beqz(p, reg, 0);
+	ISAFUNC(uasm_i_beqz)(p, reg, 0);
 }
-UASM_EXPORT_SYMBOL(uasm_il_beqz);
+UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_beqz));
 
 void __uasminit
-uasm_il_beqzl(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid)
+ISAFUNC(uasm_il_beqzl)(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid)
 {
 	uasm_r_mips_pc16(r, *p, lid);
-	uasm_i_beqzl(p, reg, 0);
+	ISAFUNC(uasm_i_beqzl)(p, reg, 0);
 }
-UASM_EXPORT_SYMBOL(uasm_il_beqzl);
+UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_beqzl));
 
 void __uasminit
-uasm_il_bne(u32 **p, struct uasm_reloc **r, unsigned int reg1,
+ISAFUNC(uasm_il_bne)(u32 **p, struct uasm_reloc **r, unsigned int reg1,
 	unsigned int reg2, int lid)
 {
 	uasm_r_mips_pc16(r, *p, lid);
-	uasm_i_bne(p, reg1, reg2, 0);
+	ISAFUNC(uasm_i_bne)(p, reg1, reg2, 0);
 }
-UASM_EXPORT_SYMBOL(uasm_il_bne);
+UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_bne));
 
 void __uasminit
-uasm_il_bnez(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid)
+ISAFUNC(uasm_il_bnez)(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid)
 {
 	uasm_r_mips_pc16(r, *p, lid);
-	uasm_i_bnez(p, reg, 0);
+	ISAFUNC(uasm_i_bnez)(p, reg, 0);
 }
-UASM_EXPORT_SYMBOL(uasm_il_bnez);
+UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_bnez));
 
 void __uasminit
-uasm_il_bgezl(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid)
+ISAFUNC(uasm_il_bgezl)(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid)
 {
 	uasm_r_mips_pc16(r, *p, lid);
-	uasm_i_bgezl(p, reg, 0);
+	ISAFUNC(uasm_i_bgezl)(p, reg, 0);
 }
-UASM_EXPORT_SYMBOL(uasm_il_bgezl);
+UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_bgezl));
 
 void __uasminit
-uasm_il_bgez(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid)
+ISAFUNC(uasm_il_bgez)(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid)
 {
 	uasm_r_mips_pc16(r, *p, lid);
-	uasm_i_bgez(p, reg, 0);
+	ISAFUNC(uasm_i_bgez)(p, reg, 0);
 }
-UASM_EXPORT_SYMBOL(uasm_il_bgez);
+UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_bgez));
 
 void __uasminit
-uasm_il_bbit0(u32 **p, struct uasm_reloc **r, unsigned int reg,
+ISAFUNC(uasm_il_bbit0)(u32 **p, struct uasm_reloc **r, unsigned int reg,
 	      unsigned int bit, int lid)
 {
 	uasm_r_mips_pc16(r, *p, lid);
-	uasm_i_bbit0(p, reg, bit, 0);
+	ISAFUNC(uasm_i_bbit0)(p, reg, bit, 0);
 }
-UASM_EXPORT_SYMBOL(uasm_il_bbit0);
+UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_bbit0));
 
 void __uasminit
-uasm_il_bbit1(u32 **p, struct uasm_reloc **r, unsigned int reg,
+ISAFUNC(uasm_il_bbit1)(u32 **p, struct uasm_reloc **r, unsigned int reg,
 	      unsigned int bit, int lid)
 {
 	uasm_r_mips_pc16(r, *p, lid);
-	uasm_i_bbit1(p, reg, bit, 0);
+	ISAFUNC(uasm_i_bbit1)(p, reg, bit, 0);
 }
-UASM_EXPORT_SYMBOL(uasm_il_bbit1);
+UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_bbit1));
diff --git a/arch/mips/mti-malta/Platform b/arch/mips/mti-malta/Platform
index 5b548b5..2cc72c9 100644
--- a/arch/mips/mti-malta/Platform
+++ b/arch/mips/mti-malta/Platform
@@ -3,5 +3,9 @@
 #
 platform-$(CONFIG_MIPS_MALTA)	+= mti-malta/
 cflags-$(CONFIG_MIPS_MALTA)	+= -I$(srctree)/arch/mips/include/asm/mach-malta
-load-$(CONFIG_MIPS_MALTA)	+= 0xffffffff80100000
+ifdef CONFIG_KVM_GUEST
+    load-$(CONFIG_MIPS_MALTA)	+= 0x0000000040100000
+else
+    load-$(CONFIG_MIPS_MALTA)	+= 0xffffffff80100000
+endif
 all-$(CONFIG_MIPS_MALTA)	:= $(COMPRESSION_FNAME).bin
diff --git a/arch/mips/mti-malta/malta-time.c b/arch/mips/mti-malta/malta-time.c
index a144b89..5681994 100644
--- a/arch/mips/mti-malta/malta-time.c
+++ b/arch/mips/mti-malta/malta-time.c
@@ -76,6 +76,19 @@ static void __init estimate_frequencies(void)
 	unsigned int count, start;
 	unsigned int giccount = 0, gicstart = 0;
 
+#if defined (CONFIG_KVM_GUEST) && defined (CONFIG_KVM_HOST_FREQ)
+	/*
+	 * XXXKYMA: hardwire the CPU frequency to Host Freq/4
+	 */
+	count = (CONFIG_KVM_HOST_FREQ * 1000000) >> 3;
+	if ((prid != (PRID_COMP_MIPS | PRID_IMP_20KC)) &&
+	    (prid != (PRID_COMP_MIPS | PRID_IMP_25KF)))
+		count *= 2;
+
+	mips_hpt_frequency = count;
+	return count;
+#endif
+
 	local_irq_save(flags);
 
 	/* Start counter exactly on falling edge of update flag. */
diff --git a/arch/mips/sgi-ip27/ip27-memory.c b/arch/mips/sgi-ip27/ip27-memory.c
index 3505d08..5f2bddb 100644
--- a/arch/mips/sgi-ip27/ip27-memory.c
+++ b/arch/mips/sgi-ip27/ip27-memory.c
@@ -457,7 +457,7 @@ void __init prom_free_prom_memory(void)
 	/* We got nothing to free here ...  */
 }
 
-extern unsigned long setup_zero_pages(void);
+extern void setup_zero_pages(void);
 
 void __init paging_init(void)
 {
@@ -492,7 +492,7 @@ void __init mem_init(void)
 		totalram_pages += free_all_bootmem_node(NODE_DATA(node));
 	}
 
-	totalram_pages -= setup_zero_pages();	/* This comes from node 0 */
+	setup_zero_pages();	/* This comes from node 0 */
 
 	codesize =  (unsigned long) &_etext - (unsigned long) &_text;
 	datasize =  (unsigned long) &_edata - (unsigned long) &_etext;
diff --git a/arch/mips/txx9/generic/setup.c b/arch/mips/txx9/generic/setup.c
index 5524f2c..5364aab 100644
--- a/arch/mips/txx9/generic/setup.c
+++ b/arch/mips/txx9/generic/setup.c
@@ -118,7 +118,7 @@ EXPORT_SYMBOL(clk_put);
 
 /* GPIO support */
 
-#ifdef CONFIG_GENERIC_GPIO
+#ifdef CONFIG_GPIOLIB
 int gpio_to_irq(unsigned gpio)
 {
 	return -EINVAL;
diff --git a/arch/mn10300/include/asm/unistd.h b/arch/mn10300/include/asm/unistd.h
index 7f9d9ad..9d4e2d1 100644
--- a/arch/mn10300/include/asm/unistd.h
+++ b/arch/mn10300/include/asm/unistd.h
@@ -45,14 +45,4 @@
 #define __ARCH_WANT_SYS_VFORK
 #define __ARCH_WANT_SYS_CLONE
 
-/*
- * "Conditional" syscalls
- *
- * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
- * but it doesn't work on all toolchains, so we just do it by hand
- */
-#ifndef cond_syscall
-#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
-#endif
-
 #endif /* _ASM_UNISTD_H */
diff --git a/arch/mn10300/include/uapi/asm/socket.h b/arch/mn10300/include/uapi/asm/socket.h
index 5c7c7c9..b4ce844 100644
--- a/arch/mn10300/include/uapi/asm/socket.h
+++ b/arch/mn10300/include/uapi/asm/socket.h
@@ -72,4 +72,6 @@
 
 #define SO_LOCK_FILTER		44
 
+#define SO_SELECT_ERR_QUEUE	45
+
 #endif /* _ASM_SOCKET_H */
diff --git a/arch/mn10300/mm/init.c b/arch/mn10300/mm/init.c
index e57e5bc..5a8ace6 100644
--- a/arch/mn10300/mm/init.c
+++ b/arch/mn10300/mm/init.c
@@ -139,30 +139,11 @@ void __init mem_init(void)
 }
 
 /*
- *
- */
-void free_init_pages(char *what, unsigned long begin, unsigned long end)
-{
-	unsigned long addr;
-
-	for (addr = begin; addr < end; addr += PAGE_SIZE) {
-		ClearPageReserved(virt_to_page(addr));
-		init_page_count(virt_to_page(addr));
-		memset((void *) addr, 0xcc, PAGE_SIZE);
-		free_page(addr);
-		totalram_pages++;
-	}
-	printk(KERN_INFO "Freeing %s: %ldk freed\n", what, (end - begin) >> 10);
-}
-
-/*
  * recycle memory containing stuff only required for initialisation
  */
 void free_initmem(void)
 {
-	free_init_pages("unused kernel memory",
-			(unsigned long) &__init_begin,
-			(unsigned long) &__init_end);
+	free_initmem_default(POISON_FREE_INITMEM);
 }
 
 /*
@@ -171,6 +152,6 @@ void free_initmem(void)
 #ifdef CONFIG_BLK_DEV_INITRD
 void free_initrd_mem(unsigned long start, unsigned long end)
 {
-	free_init_pages("initrd memory", start, end);
+	free_reserved_area(start, end, POISON_FREE_INITMEM, "initrd");
 }
 #endif
diff --git a/arch/openrisc/Kconfig b/arch/openrisc/Kconfig
index 9ab3bf2..df469d7 100644
--- a/arch/openrisc/Kconfig
+++ b/arch/openrisc/Kconfig
@@ -45,7 +45,7 @@ config NO_IOPORT
 	def_bool y
 
 config GENERIC_GPIO
-	def_bool y
+	def_bool n
 
 config TRACE_IRQFLAGS_SUPPORT
         def_bool y
@@ -55,9 +55,6 @@ config TRACE_IRQFLAGS_SUPPORT
 config GENERIC_CSUM
         def_bool y
 
-config GENERIC_FIND_NEXT_BIT
-	def_bool y
-
 source "init/Kconfig"
 
 
diff --git a/arch/openrisc/mm/init.c b/arch/openrisc/mm/init.c
index e7fdc50..b3cbc67 100644
--- a/arch/openrisc/mm/init.c
+++ b/arch/openrisc/mm/init.c
@@ -43,6 +43,7 @@
 #include <asm/kmap_types.h>
 #include <asm/fixmap.h>
 #include <asm/tlbflush.h>
+#include <asm/sections.h>
 
 int mem_init_done;
 
@@ -201,9 +202,6 @@ void __init paging_init(void)
 
 /* 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;
@@ -263,30 +261,11 @@ void __init mem_init(void)
 #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++;
-	}
+	free_reserved_area(start, end, 0, "initrd");
 }
 #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);
+	free_initmem_default(0);
 }
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
index 0339181..433e75a 100644
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -1,5 +1,6 @@
 config PARISC
 	def_bool y
+	select ARCH_HAS_DEBUG_STRICT_USER_COPY_CHECKS
 	select HAVE_IDE
 	select HAVE_OPROFILE
 	select HAVE_FUNCTION_TRACER if 64BIT
diff --git a/arch/parisc/Kconfig.debug b/arch/parisc/Kconfig.debug
index 7305ac8..bc989e5 100644
--- a/arch/parisc/Kconfig.debug
+++ b/arch/parisc/Kconfig.debug
@@ -12,18 +12,4 @@ config DEBUG_RODATA
          portion of the kernel code won't be covered by a TLB anymore.
          If in doubt, say "N".
 
-config DEBUG_STRICT_USER_COPY_CHECKS
-	bool "Strict copy size checks"
-	depends on DEBUG_KERNEL && !TRACE_BRANCH_PROFILING
-	---help---
-	  Enabling this option turns a certain set of sanity checks for user
-	  copy operations into compile time failures.
-
-	  The copy_from_user() etc checks are there to help test if there
-	  are sufficient security checks on the length argument of
-	  the copy operation, by having gcc prove that the argument is
-	  within bounds.
-
-	  If unsure, or if you run an older (pre 4.4) gcc, say N.
-
 endmenu
diff --git a/arch/parisc/include/asm/unistd.h b/arch/parisc/include/asm/unistd.h
index ae9a46c..74d8358 100644
--- a/arch/parisc/include/asm/unistd.h
+++ b/arch/parisc/include/asm/unistd.h
@@ -170,12 +170,4 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5)	\
 
 #undef STR
 
-/*
- * "Conditional" syscalls
- *
- * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
- * but it doesn't work on all toolchains, so we just do it by hand
- */
-#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
-
 #endif /* _ASM_PARISC_UNISTD_H_ */
diff --git a/arch/parisc/include/uapi/asm/socket.h b/arch/parisc/include/uapi/asm/socket.h
index 526e4b9..70c512a 100644
--- a/arch/parisc/include/uapi/asm/socket.h
+++ b/arch/parisc/include/uapi/asm/socket.h
@@ -71,6 +71,8 @@
 
 #define SO_LOCK_FILTER		0x4025
 
+#define SO_SELECT_ERR_QUEUE	0x4026
+
 /* O_NONBLOCK clashes with the bits used for socket types.  Therefore we
  * have to define SOCK_NONBLOCK to a different value here.
  */
diff --git a/arch/parisc/kernel/sys_parisc32.c b/arch/parisc/kernel/sys_parisc32.c
index 051c8b9..f517e08 100644
--- a/arch/parisc/kernel/sys_parisc32.c
+++ b/arch/parisc/kernel/sys_parisc32.c
@@ -60,47 +60,6 @@ asmlinkage long sys32_unimplemented(int r26, int r25, int r24, int r23,
     return -ENOSYS;
 }
 
-/* Note: it is necessary to treat out_fd and in_fd as unsigned ints, with the
- * corresponding cast to a signed int to insure that the proper conversion
- * (sign extension) between the register representation of a signed int (msr in
- * 32-bit mode) and the register representation of a signed int (msr in 64-bit
- * mode) is performed.
- */
-asmlinkage long sys32_sendfile(u32 out_fd, u32 in_fd,
-			       compat_off_t __user *offset, compat_size_t count)
-{
-	return compat_sys_sendfile((int)out_fd, (int)in_fd, offset, count);
-}
-
-asmlinkage long sys32_sendfile64(u32 out_fd, u32 in_fd,
-				 compat_loff_t __user *offset, compat_size_t count)
-{
-	return sys_sendfile64((int)out_fd, (int)in_fd,
-				(loff_t __user *)offset, count);
-}
-
-asmlinkage long sys32_semctl(int semid, int semnum, int cmd, union semun arg)
-{
-        union semun u;
-	
-        if (cmd == SETVAL) {
-                /* Ugh.  arg is a union of int,ptr,ptr,ptr, so is 8 bytes.
-                 * The int should be in the first 4, but our argument
-                 * frobbing has left it in the last 4.
-                 */
-                u.val = *((int *)&arg + 1);
-                return sys_semctl (semid, semnum, cmd, u);
-	}
-	return sys_semctl (semid, semnum, cmd, arg);
-}
-
-long sys32_lookup_dcookie(u32 cookie_high, u32 cookie_low, char __user *buf,
-			  size_t len)
-{
-	return sys_lookup_dcookie((u64)cookie_high << 32 | cookie_low,
-				  buf, len);
-}
-
 asmlinkage long compat_sys_fanotify_mark(int fan_fd, int flags, u32 mask_hi,
 					 u32 mask_lo, int fd,
 					 const char __user *pathname)
diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S
index f57dc13..0c91072 100644
--- a/arch/parisc/kernel/syscall_table.S
+++ b/arch/parisc/kernel/syscall_table.S
@@ -198,7 +198,7 @@
 	ENTRY_SAME(madvise)
 	ENTRY_SAME(clone_wrapper)	/* 120 */
 	ENTRY_SAME(setdomainname)
-	ENTRY_DIFF(sendfile)
+	ENTRY_COMP(sendfile)
 	/* struct sockaddr... */
 	ENTRY_SAME(recvfrom)
 	/* struct timex contains longs */
@@ -282,7 +282,7 @@
 	ENTRY_COMP(recvmsg)
 	ENTRY_SAME(semop)		/* 185 */
 	ENTRY_SAME(semget)
-	ENTRY_DIFF(semctl)
+	ENTRY_COMP(semctl)
 	ENTRY_COMP(msgsnd)
 	ENTRY_COMP(msgrcv)
 	ENTRY_SAME(msgget)		/* 190 */
@@ -304,7 +304,7 @@
 	ENTRY_SAME(gettid)
 	ENTRY_OURS(readahead)
 	ENTRY_SAME(tkill)
-	ENTRY_DIFF(sendfile64)
+	ENTRY_COMP(sendfile64)
 	ENTRY_COMP(futex)		/* 210 */
 	ENTRY_COMP(sched_setaffinity)
 	ENTRY_COMP(sched_getaffinity)
@@ -318,7 +318,7 @@
 	ENTRY_SAME(alloc_hugepages)	/* 220 */
 	ENTRY_SAME(free_hugepages)
 	ENTRY_SAME(exit_group)
-	ENTRY_DIFF(lookup_dcookie)
+	ENTRY_COMP(lookup_dcookie)
 	ENTRY_SAME(epoll_create)
 	ENTRY_SAME(epoll_ctl)		/* 225 */
 	ENTRY_SAME(epoll_wait)
diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c
index 3ac462d..157b931 100644
--- a/arch/parisc/mm/init.c
+++ b/arch/parisc/mm/init.c
@@ -505,7 +505,6 @@ static void __init map_pages(unsigned long start_vaddr,
 
 void free_initmem(void)
 {
-	unsigned long addr;
 	unsigned long init_begin = (unsigned long)__init_begin;
 	unsigned long init_end = (unsigned long)__init_end;
 
@@ -533,19 +532,10 @@ void free_initmem(void)
 	 * pages are no-longer executable */
 	flush_icache_range(init_begin, init_end);
 	
-	for (addr = init_begin; addr < init_end; addr += PAGE_SIZE) {
-		ClearPageReserved(virt_to_page(addr));
-		init_page_count(virt_to_page(addr));
-		free_page(addr);
-		num_physpages++;
-		totalram_pages++;
-	}
+	num_physpages += free_initmem_default(0);
 
 	/* set up a new led state on systems shipped LED State panel */
 	pdc_chassis_send_status(PDC_CHASSIS_DIRECT_BCOMPLETE);
-	
-	printk(KERN_INFO "Freeing unused kernel memory: %luk freed\n",
-		(init_end - init_begin) >> 10);
 }
 
 
@@ -697,6 +687,8 @@ void show_mem(unsigned int filter)
 
 	printk(KERN_INFO "Mem-info:\n");
 	show_free_areas(filter);
+	if (filter & SHOW_MEM_FILTER_PAGE_COUNT)
+		return;
 #ifndef CONFIG_DISCONTIGMEM
 	i = max_mapnr;
 	while (i-- > 0) {
@@ -1107,15 +1099,6 @@ void flush_tlb_all(void)
 #ifdef CONFIG_BLK_DEV_INITRD
 void free_initrd_mem(unsigned long start, unsigned long end)
 {
-	if (start >= end)
-		return;
-	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);
-		num_physpages++;
-		totalram_pages++;
-	}
+	num_physpages += free_reserved_area(start, end, 0, "initrd");
 }
 #endif
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index ea5bb04..0ac9f61 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -114,7 +114,6 @@ config PPC
 	select USE_GENERIC_SMP_HELPERS if SMP
 	select HAVE_OPROFILE
 	select HAVE_DEBUG_KMEMLEAK
-	select HAVE_SYSCALL_WRAPPERS if PPC64
 	select GENERIC_ATOMIC64 if PPC32
 	select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
 	select HAVE_PERF_EVENTS
@@ -686,7 +685,6 @@ config SBUS
 config FSL_SOC
 	bool
 	select HAVE_CAN_FLEXCAN if NET && CAN
-	select PPC_CLOCK
 
 config FSL_PCI
  	bool
@@ -775,11 +773,6 @@ config PCI_8260
 	select PPC_INDIRECT_PCI
 	default y
 
-config 8260_PCI9
-	bool "Enable workaround for MPC826x erratum PCI 9"
-	depends on PCI_8260 && !8272
-	default y
-
 source "drivers/pci/pcie/Kconfig"
 
 source "drivers/pci/Kconfig"
diff --git a/arch/powerpc/boot/dts/fsl/e500mc_power_isa.dtsi b/arch/powerpc/boot/dts/fsl/e500mc_power_isa.dtsi
index 870c653..ea145c9 100644
--- a/arch/powerpc/boot/dts/fsl/e500mc_power_isa.dtsi
+++ b/arch/powerpc/boot/dts/fsl/e500mc_power_isa.dtsi
@@ -53,6 +53,7 @@
 		power-isa-mmc;		// Memory Coherence
 		power-isa-scpm;		// Store Conditional Page Mobility
 		power-isa-wt;		// Wait
+		fsl,eref-deo;		// Data Cache Extended Operations
 		mmu-type = "power-embedded";
 	};
 };
diff --git a/arch/powerpc/boot/dts/fsl/e5500_power_isa.dtsi b/arch/powerpc/boot/dts/fsl/e5500_power_isa.dtsi
index 3230212..c254c98 100644
--- a/arch/powerpc/boot/dts/fsl/e5500_power_isa.dtsi
+++ b/arch/powerpc/boot/dts/fsl/e5500_power_isa.dtsi
@@ -54,6 +54,7 @@
 		power-isa-scpm;		// Store Conditional Page Mobility
 		power-isa-wt;		// Wait
 		power-isa-64;		// 64-bit
+		fsl,eref-deo;		// Data Cache Extended Operations
 		mmu-type = "power-embedded";
 	};
 };
diff --git a/arch/powerpc/boot/dts/fsl/e6500_power_isa.dtsi b/arch/powerpc/boot/dts/fsl/e6500_power_isa.dtsi
new file mode 100644
index 0000000..a912dbe
--- /dev/null
+++ b/arch/powerpc/boot/dts/fsl/e6500_power_isa.dtsi
@@ -0,0 +1,65 @@
+/*
+ * e6500 Power ISA Device Tree Source (include)
+ *
+ * Copyright 2013 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.
+ */
+
+/ {
+	cpus {
+		power-isa-version = "2.06";
+		power-isa-b;		// Base
+		power-isa-e;		// Embedded
+		power-isa-atb;		// Alternate Time Base
+		power-isa-cs;		// Cache Specification
+		power-isa-ds;		// Decorated Storage
+		power-isa-e.ed;		// Embedded.Enhanced Debug
+		power-isa-e.pd;		// Embedded.External PID
+		power-isa-e.hv;		// Embedded.Hypervisor
+		power-isa-e.le;		// Embedded.Little-Endian
+		power-isa-e.pm;		// Embedded.Performance Monitor
+		power-isa-e.pc;		// Embedded.Processor Control
+		power-isa-ecl;		// Embedded Cache Locking
+		power-isa-exp;		// External Proxy
+		power-isa-fp;		// Floating Point
+		power-isa-fp.r;		// Floating Point.Record
+		power-isa-mmc;		// Memory Coherence
+		power-isa-scpm;		// Store Conditional Page Mobility
+		power-isa-wt;		// Wait
+		power-isa-64;		// 64-bit
+		power-isa-e.pt;		// Embedded.Page Table
+		power-isa-e.hv.lrat;	// Embedded.Hypervisor.LRAT
+		power-isa-e.em;		// Embedded Multi-Threading
+		power-isa-v;		// Vector (AltiVec)
+		fsl,eref-er;		// Enhanced Reservations (Load and Reserve and Store Cond.)
+		fsl,eref-deo;		// Data Cache Extended Operations
+		mmu-type = "power-embedded";
+	};
+};
diff --git a/arch/powerpc/boot/dts/fsl/p2041si-post.dtsi b/arch/powerpc/boot/dts/fsl/p2041si-post.dtsi
index 69ac1ac..dc6cc5a 100644
--- a/arch/powerpc/boot/dts/fsl/p2041si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/p2041si-post.dtsi
@@ -155,7 +155,7 @@
 	compatible = "fsl,dcsr", "simple-bus";
 
 	dcsr-epu@0 {
-		compatible = "fsl,dcsr-epu";
+		compatible = "fsl,p2041-dcsr-epu", "fsl,dcsr-epu";
 		interrupts = <52 2 0 0
 			      84 2 0 0
 			      85 2 0 0>;
diff --git a/arch/powerpc/boot/dts/fsl/p3041si-post.dtsi b/arch/powerpc/boot/dts/fsl/p3041si-post.dtsi
index 9b5a81a..3fa1e22 100644
--- a/arch/powerpc/boot/dts/fsl/p3041si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/p3041si-post.dtsi
@@ -182,7 +182,7 @@
 	compatible = "fsl,dcsr", "simple-bus";
 
 	dcsr-epu@0 {
-		compatible = "fsl,dcsr-epu";
+		compatible = "fsl,p3041-dcsr-epu", "fsl,dcsr-epu";
 		interrupts = <52 2 0 0
 			      84 2 0 0
 			      85 2 0 0>;
diff --git a/arch/powerpc/boot/dts/fsl/p4080si-post.dtsi b/arch/powerpc/boot/dts/fsl/p4080si-post.dtsi
index 19859ad..34769a7 100644
--- a/arch/powerpc/boot/dts/fsl/p4080si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/p4080si-post.dtsi
@@ -156,7 +156,7 @@
 	compatible = "fsl,dcsr", "simple-bus";
 
 	dcsr-epu@0 {
-		compatible = "fsl,dcsr-epu";
+		compatible = "fsl,p4080-dcsr-epu", "fsl,dcsr-epu";
 		interrupts = <52 2 0 0
 			      84 2 0 0
 			      85 2 0 0>;
diff --git a/arch/powerpc/boot/dts/fsl/p5020si-post.dtsi b/arch/powerpc/boot/dts/fsl/p5020si-post.dtsi
index 9ea77c3..bc3ae5a 100644
--- a/arch/powerpc/boot/dts/fsl/p5020si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/p5020si-post.dtsi
@@ -184,7 +184,7 @@
 	compatible = "fsl,dcsr", "simple-bus";
 
 	dcsr-epu@0 {
-		compatible = "fsl,dcsr-epu";
+		compatible = "fsl,p5020-dcsr-epu", "fsl,dcsr-epu";
 		interrupts = <52 2 0 0
 			      84 2 0 0
 			      85 2 0 0>;
diff --git a/arch/powerpc/boot/dts/fsl/p5040si-post.dtsi b/arch/powerpc/boot/dts/fsl/p5040si-post.dtsi
index 97f8c26..a91897f 100644
--- a/arch/powerpc/boot/dts/fsl/p5040si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/p5040si-post.dtsi
@@ -129,7 +129,7 @@
 	compatible = "fsl,dcsr", "simple-bus";
 
 	dcsr-epu@0 {
-		compatible = "fsl,dcsr-epu";
+		compatible = "fsl,p5040-dcsr-epu", "fsl,dcsr-epu";
 		interrupts = <52 2 0 0
 			      84 2 0 0
 			      85 2 0 0>;
diff --git a/arch/powerpc/boot/dts/fsl/qonverge-usb2-dr-0.dtsi b/arch/powerpc/boot/dts/fsl/qonverge-usb2-dr-0.dtsi
new file mode 100644
index 0000000..29dad72
--- /dev/null
+++ b/arch/powerpc/boot/dts/fsl/qonverge-usb2-dr-0.dtsi
@@ -0,0 +1,41 @@
+/*
+ * QorIQ Qonverge USB Host device tree stub [ controller @ offset 0x210000 ]
+ *
+ * Copyright 2013 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.
+ */
+
+usb@210000 {
+	compatible = "fsl-usb2-dr";
+	reg = <0x210000 0x1000>;
+	#address-cells = <1>;
+	#size-cells = <0>;
+	interrupts = <44 0x2 0 0>;
+};
diff --git a/arch/powerpc/boot/dts/fsl/qoriq-gpio-1.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-gpio-1.dtsi
new file mode 100644
index 0000000..c2f9cda
--- /dev/null
+++ b/arch/powerpc/boot/dts/fsl/qoriq-gpio-1.dtsi
@@ -0,0 +1,41 @@
+/*
+ * QorIQ GPIO device tree stub [ controller @ offset 0x131000 ]
+ *
+ * Copyright 2013 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.
+ */
+
+gpio1: gpio@131000 {
+	compatible = "fsl,qoriq-gpio";
+	reg = <0x131000 0x1000>;
+	interrupts = <54 2 0 0>;
+	#gpio-cells = <2>;
+	gpio-controller;
+};
diff --git a/arch/powerpc/boot/dts/fsl/qoriq-gpio-2.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-gpio-2.dtsi
new file mode 100644
index 0000000..33f3ccb
--- /dev/null
+++ b/arch/powerpc/boot/dts/fsl/qoriq-gpio-2.dtsi
@@ -0,0 +1,41 @@
+/*
+ * QorIQ GPIO device tree stub [ controller @ offset 0x132000 ]
+ *
+ * Copyright 2013 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.
+ */
+
+gpio2: gpio@132000 {
+	compatible = "fsl,qoriq-gpio";
+	reg = <0x132000 0x1000>;
+	interrupts = <86 2 0 0>;
+	#gpio-cells = <2>;
+	gpio-controller;
+};
diff --git a/arch/powerpc/boot/dts/fsl/qoriq-gpio-3.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-gpio-3.dtsi
new file mode 100644
index 0000000..86954e9
--- /dev/null
+++ b/arch/powerpc/boot/dts/fsl/qoriq-gpio-3.dtsi
@@ -0,0 +1,41 @@
+/*
+ * QorIQ GPIO device tree stub [ controller @ offset 0x133000 ]
+ *
+ * Copyright 2013 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.
+ */
+
+gpio3: gpio@133000 {
+	compatible = "fsl,qoriq-gpio";
+	reg = <0x133000 0x1000>;
+	interrupts = <87 2 0 0>;
+	#gpio-cells = <2>;
+	gpio-controller;
+};
diff --git a/arch/powerpc/boot/dts/fsl/qoriq-sec5.0-0.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-sec5.0-0.dtsi
new file mode 100644
index 0000000..ffd458f
--- /dev/null
+++ b/arch/powerpc/boot/dts/fsl/qoriq-sec5.0-0.dtsi
@@ -0,0 +1,109 @@
+/*
+ * QorIQ Sec/Crypto 5.0 device tree stub [ controller @ offset 0x300000 ]
+ *
+ * Copyright 2012 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.
+ */
+
+crypto: crypto@300000 {
+	compatible = "fsl,sec-v5.0", "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-v5.0-job-ring",
+			     "fsl,sec-v4.0-job-ring";
+		reg = <0x1000 0x1000>;
+		interrupts = <88 2 0 0>;
+	};
+
+	sec_jr1: jr@2000 {
+		compatible = "fsl,sec-v5.0-job-ring",
+			     "fsl,sec-v4.0-job-ring";
+		reg = <0x2000 0x1000>;
+		interrupts = <89 2 0 0>;
+	};
+
+	sec_jr2: jr@3000 {
+		compatible = "fsl,sec-v5.0-job-ring",
+			     "fsl,sec-v4.0-job-ring";
+		reg = <0x3000 0x1000>;
+		interrupts = <90 2 0 0>;
+	};
+
+	sec_jr3: jr@4000 {
+		compatible = "fsl,sec-v5.0-job-ring",
+			     "fsl,sec-v4.0-job-ring";
+		reg = <0x4000 0x1000>;
+		interrupts = <91 2 0 0>;
+	};
+
+	rtic@6000 {
+		compatible = "fsl,sec-v5.0-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-v5.0-rtic-memory",
+				     "fsl,sec-v4.0-rtic-memory";
+			reg = <0x00 0x20 0x100 0x80>;
+		};
+
+		rtic_b: rtic-b@20 {
+			compatible = "fsl,sec-v5.0-rtic-memory",
+				     "fsl,sec-v4.0-rtic-memory";
+			reg = <0x20 0x20 0x200 0x80>;
+		};
+
+		rtic_c: rtic-c@40 {
+			compatible = "fsl,sec-v5.0-rtic-memory",
+				     "fsl,sec-v4.0-rtic-memory";
+			reg = <0x40 0x20 0x300 0x80>;
+		};
+
+		rtic_d: rtic-d@60 {
+			compatible = "fsl,sec-v5.0-rtic-memory",
+				     "fsl,sec-v4.0-rtic-memory";
+			reg = <0x60 0x20 0x500 0x80>;
+		};
+	};
+};
+
+sec_mon: sec_mon@314000 {
+	compatible = "fsl,sec-v5.0-mon", "fsl,sec-v4.0-mon";
+	reg = <0x314000 0x1000>;
+	interrupts = <93 2 0 0>;
+};
diff --git a/arch/powerpc/boot/dts/fsl/qoriq-sec5.3-0.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-sec5.3-0.dtsi
new file mode 100644
index 0000000..0339825
--- /dev/null
+++ b/arch/powerpc/boot/dts/fsl/qoriq-sec5.3-0.dtsi
@@ -0,0 +1,118 @@
+/*
+ * QorIQ Sec/Crypto 5.3 device tree stub [ controller @ offset 0x300000 ]
+ *
+ * Copyright 2012 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.
+ */
+
+crypto: crypto@300000 {
+	compatible = "fsl,sec-v5.3", "fsl,sec-v5.0", "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-v5.3-job-ring",
+			     "fsl,sec-v5.0-job-ring",
+			     "fsl,sec-v4.0-job-ring";
+		reg = <0x1000 0x1000>;
+		interrupts = <88 2 0 0>;
+	};
+
+	sec_jr1: jr@2000 {
+		compatible = "fsl,sec-v5.3-job-ring",
+			     "fsl,sec-v5.0-job-ring",
+			     "fsl,sec-v4.0-job-ring";
+		reg = <0x2000 0x1000>;
+		interrupts = <89 2 0 0>;
+	};
+
+	sec_jr2: jr@3000 {
+		compatible = "fsl,sec-v5.3-job-ring",
+			     "fsl,sec-v5.0-job-ring",
+			     "fsl,sec-v4.0-job-ring";
+		reg = <0x3000 0x1000>;
+		interrupts = <90 2 0 0>;
+	};
+
+	sec_jr3: jr@4000 {
+		compatible = "fsl,sec-v5.3-job-ring",
+			     "fsl,sec-v5.0-job-ring",
+			     "fsl,sec-v4.0-job-ring";
+		reg = <0x4000 0x1000>;
+		interrupts = <91 2 0 0>;
+	};
+
+	rtic@6000 {
+		compatible = "fsl,sec-v5.3-rtic",
+			     "fsl,sec-v5.0-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-v5.3-rtic-memory",
+				     "fsl,sec-v5.0-rtic-memory",
+				     "fsl,sec-v4.0-rtic-memory";
+			reg = <0x00 0x20 0x100 0x80>;
+		};
+
+		rtic_b: rtic-b@20 {
+			compatible = "fsl,sec-v5.3-rtic-memory",
+				     "fsl,sec-v5.0-rtic-memory",
+				     "fsl,sec-v4.0-rtic-memory";
+			reg = <0x20 0x20 0x200 0x80>;
+		};
+
+		rtic_c: rtic-c@40 {
+			compatible = "fsl,sec-v5.3-rtic-memory",
+				     "fsl,sec-v5.0-rtic-memory",
+				     "fsl,sec-v4.0-rtic-memory";
+			reg = <0x40 0x20 0x300 0x80>;
+		};
+
+		rtic_d: rtic-d@60 {
+			compatible = "fsl,sec-v5.3-rtic-memory",
+				     "fsl,sec-v5.0-rtic-memory",
+				     "fsl,sec-v4.0-rtic-memory";
+			reg = <0x60 0x20 0x500 0x80>;
+		};
+	};
+};
+
+sec_mon: sec_mon@314000 {
+	compatible = "fsl,sec-v5.3-mon", "fsl,sec-v5.0-mon", "fsl,sec-v4.0-mon";
+	reg = <0x314000 0x1000>;
+	interrupts = <93 2 0 0>;
+};
diff --git a/arch/powerpc/boot/dts/fsl/t4240si-post.dtsi b/arch/powerpc/boot/dts/fsl/t4240si-post.dtsi
new file mode 100644
index 0000000..1d72926
--- /dev/null
+++ b/arch/powerpc/boot/dts/fsl/t4240si-post.dtsi
@@ -0,0 +1,438 @@
+/*
+ * T4240 Silicon/SoC Device Tree Source (post include)
+ *
+ * Copyright 2012 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.
+ */
+
+&ifc {
+	#address-cells = <2>;
+	#size-cells = <1>;
+	compatible = "fsl,ifc", "simple-bus";
+	interrupts = <25 2 0 0>;
+};
+
+/* controller at 0x240000 */
+&pci0 {
+	compatible = "fsl,t4240-pcie", "fsl,qoriq-pcie-v3.0";
+	device_type = "pci";
+	#size-cells = <2>;
+	#address-cells = <3>;
+	bus-range = <0x0 0xff>;
+	interrupts = <20 2 0 0>;
+	pcie@0 {
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		device_type = "pci";
+		interrupts = <20 2 0 0>;
+		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
+			>;
+	};
+};
+
+/* controller at 0x250000 */
+&pci1 {
+	compatible = "fsl,t4240-pcie", "fsl,qoriq-pcie-v3.0";
+	device_type = "pci";
+	#size-cells = <2>;
+	#address-cells = <3>;
+	bus-range = <0 0xff>;
+	interrupts = <21 2 0 0>;
+	pcie@0 {
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		device_type = "pci";
+		interrupts = <21 2 0 0>;
+		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
+			>;
+	};
+};
+
+/* controller at 0x260000 */
+&pci2 {
+	compatible = "fsl,t4240-pcie", "fsl,qoriq-pcie-v3.0";
+	device_type = "pci";
+	#size-cells = <2>;
+	#address-cells = <3>;
+	bus-range = <0x0 0xff>;
+	interrupts = <22 2 0 0>;
+	pcie@0 {
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		device_type = "pci";
+		interrupts = <22 2 0 0>;
+		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
+			>;
+	};
+};
+
+/* controller at 0x270000 */
+&pci3 {
+	compatible = "fsl,t4240-pcie", "fsl,qoriq-pcie-v3.0";
+	device_type = "pci";
+	#size-cells = <2>;
+	#address-cells = <3>;
+	bus-range = <0x0 0xff>;
+	interrupts = <23 2 0 0>;
+	pcie@0 {
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		device_type = "pci";
+		interrupts = <23 2 0 0>;
+		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
+			>;
+	};
+};
+
+&rio {
+	compatible = "fsl,srio";
+	interrupts = <16 2 1 11>;
+	#address-cells = <2>;
+	#size-cells = <2>;
+	ranges;
+
+	port1 {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		cell-index = <1>;
+	};
+
+	port2 {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		cell-index = <2>;
+	};
+};
+
+&dcsr {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	compatible = "fsl,dcsr", "simple-bus";
+
+	dcsr-epu@0 {
+		compatible = "fsl,t4240-dcsr-epu", "fsl,dcsr-epu";
+		interrupts = <52 2 0 0
+			      84 2 0 0
+			      85 2 0 0
+			      94 2 0 0
+			      95 2 0 0>;
+		reg = <0x0 0x1000>;
+	};
+	dcsr-npc {
+		compatible = "fsl,t4240-dcsr-cnpc", "fsl,dcsr-cnpc";
+		reg = <0x1000 0x1000 0x1002000 0x10000>;
+	};
+	dcsr-nxc@2000 {
+		compatible = "fsl,dcsr-nxc";
+		reg = <0x2000 0x1000>;
+	};
+	dcsr-corenet {
+		compatible = "fsl,dcsr-corenet";
+		reg = <0x8000 0x1000 0x1A000 0x1000>;
+	};
+	dcsr-dpaa@9000 {
+		compatible = "fsl,t4240-dcsr-dpaa", "fsl,dcsr-dpaa";
+		reg = <0x9000 0x1000>;
+	};
+	dcsr-ocn@11000 {
+		compatible = "fsl,t4240-dcsr-ocn", "fsl,dcsr-ocn";
+		reg = <0x11000 0x1000>;
+	};
+	dcsr-ddr@12000 {
+		compatible = "fsl,dcsr-ddr";
+		dev-handle = <&ddr1>;
+		reg = <0x12000 0x1000>;
+	};
+	dcsr-ddr@13000 {
+		compatible = "fsl,dcsr-ddr";
+		dev-handle = <&ddr2>;
+		reg = <0x13000 0x1000>;
+	};
+	dcsr-ddr@14000 {
+		compatible = "fsl,dcsr-ddr";
+		dev-handle = <&ddr3>;
+		reg = <0x14000 0x1000>;
+	};
+	dcsr-nal@18000 {
+		compatible = "fsl,t4240-dcsr-nal", "fsl,dcsr-nal";
+		reg = <0x18000 0x1000>;
+	};
+	dcsr-rcpm@22000 {
+		compatible = "fsl,t4240-dcsr-rcpm", "fsl,dcsr-rcpm";
+		reg = <0x22000 0x1000>;
+	};
+	dcsr-snpc@30000 {
+		compatible = "fsl,t4240-dcsr-snpc", "fsl,dcsr-snpc";
+		reg = <0x30000 0x1000 0x1022000 0x10000>;
+	};
+	dcsr-snpc@31000 {
+		compatible = "fsl,t4240-dcsr-snpc", "fsl,dcsr-snpc";
+		reg = <0x31000 0x1000 0x1042000 0x10000>;
+	};
+	dcsr-snpc@32000 {
+		compatible = "fsl,t4240-dcsr-snpc", "fsl,dcsr-snpc";
+		reg = <0x32000 0x1000 0x1062000 0x10000>;
+	};
+	dcsr-cpu-sb-proxy@100000 {
+		compatible = "fsl,dcsr-e6500-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+		cpu-handle = <&cpu0>;
+		reg = <0x100000 0x1000 0x101000 0x1000>;
+	};
+	dcsr-cpu-sb-proxy@108000 {
+		compatible = "fsl,dcsr-e6500-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+		cpu-handle = <&cpu1>;
+		reg = <0x108000 0x1000 0x109000 0x1000>;
+	};
+	dcsr-cpu-sb-proxy@110000 {
+		compatible = "fsl,dcsr-e6500-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+		cpu-handle = <&cpu2>;
+		reg = <0x110000 0x1000 0x111000 0x1000>;
+	};
+	dcsr-cpu-sb-proxy@118000 {
+		compatible = "fsl,dcsr-e6500-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+		cpu-handle = <&cpu3>;
+		reg = <0x118000 0x1000 0x119000 0x1000>;
+	};
+	dcsr-cpu-sb-proxy@120000 {
+		compatible = "fsl,dcsr-e6500-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+		cpu-handle = <&cpu4>;
+		reg = <0x120000 0x1000 0x121000 0x1000>;
+	};
+	dcsr-cpu-sb-proxy@128000 {
+		compatible = "fsl,dcsr-e6500-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+		cpu-handle = <&cpu5>;
+		reg = <0x128000 0x1000 0x129000 0x1000>;
+	};
+	dcsr-cpu-sb-proxy@130000 {
+		compatible = "fsl,dcsr-e6500-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+		cpu-handle = <&cpu6>;
+		reg = <0x130000 0x1000 0x131000 0x1000>;
+	};
+	dcsr-cpu-sb-proxy@138000 {
+		compatible = "fsl,dcsr-e6500-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+		cpu-handle = <&cpu7>;
+		reg = <0x138000 0x1000 0x139000 0x1000>;
+	};
+	dcsr-cpu-sb-proxy@140000 {
+		compatible = "fsl,dcsr-e6500-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+		cpu-handle = <&cpu8>;
+		reg = <0x140000 0x1000 0x141000 0x1000>;
+	};
+	dcsr-cpu-sb-proxy@148000 {
+		compatible = "fsl,dcsr-e6500-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+		cpu-handle = <&cpu9>;
+		reg = <0x148000 0x1000 0x149000 0x1000>;
+	};
+	dcsr-cpu-sb-proxy@150000 {
+		compatible = "fsl,dcsr-e6500-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+		cpu-handle = <&cpu10>;
+		reg = <0x150000 0x1000 0x151000 0x1000>;
+	};
+	dcsr-cpu-sb-proxy@158000 {
+		compatible = "fsl,dcsr-e6500-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+		cpu-handle = <&cpu11>;
+		reg = <0x158000 0x1000 0x159000 0x1000>;
+	};
+};
+
+&soc {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	device_type = "soc";
+	compatible = "simple-bus";
+
+	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>;
+	};
+
+	ddr1: memory-controller@8000 {
+		compatible = "fsl,qoriq-memory-controller-v4.7",
+				"fsl,qoriq-memory-controller";
+		reg = <0x8000 0x1000>;
+		interrupts = <16 2 1 23>;
+	};
+
+	ddr2: memory-controller@9000 {
+		compatible = "fsl,qoriq-memory-controller-v4.7",
+				"fsl,qoriq-memory-controller";
+		reg = <0x9000 0x1000>;
+		interrupts = <16 2 1 22>;
+	};
+
+	ddr3: memory-controller@a000 {
+		compatible = "fsl,qoriq-memory-controller-v4.7",
+				"fsl,qoriq-memory-controller";
+		reg = <0xa000 0x1000>;
+		interrupts = <16 2 1 21>;
+	};
+
+	cpc: l3-cache-controller@10000 {
+		compatible = "fsl,t4240-l3-cache-controller", "cache";
+		reg = <0x10000 0x1000
+		       0x11000 0x1000
+		       0x12000 0x1000>;
+		interrupts = <16 2 1 27
+			      16 2 1 26
+			      16 2 1 25>;
+	};
+
+	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 0x6000>;
+		interrupts = <
+			24 2 0 0
+			16 2 1 30>;
+	};
+
+/include/ "qoriq-mpic.dtsi"
+
+	guts: global-utilities@e0000 {
+		compatible = "fsl,t4240-device-config", "fsl,qoriq-device-config-2.0";
+		reg = <0xe0000 0xe00>;
+		fsl,has-rstcr;
+		fsl,liodn-bits = <12>;
+	};
+
+	clockgen: global-utilities@e1000 {
+		compatible = "fsl,t4240-clockgen", "fsl,qoriq-clockgen-2";
+		reg = <0xe1000 0x1000>;
+	};
+
+	rcpm: global-utilities@e2000 {
+		compatible = "fsl,t4240-rcpm", "fsl,qoriq-rcpm-2";
+		reg = <0xe2000 0x1000>;
+	};
+
+	sfp: sfp@e8000 {
+		compatible = "fsl,t4240-sfp";
+		reg	   = <0xe8000 0x1000>;
+	};
+
+	serdes: serdes@ea000 {
+		compatible = "fsl,t4240-serdes";
+		reg	   = <0xea000 0x4000>;
+	};
+
+/include/ "qoriq-dma-0.dtsi"
+/include/ "qoriq-dma-1.dtsi"
+
+/include/ "qoriq-espi-0.dtsi"
+	spi@110000 {
+		fsl,espi-num-chipselects = <4>;
+	};
+
+/include/ "qoriq-esdhc-0.dtsi"
+	sdhc@114000 {
+		compatible = "fsl,t4240-esdhc", "fsl,esdhc";
+		sdhci,auto-cmd12;
+	};
+/include/ "qoriq-i2c-0.dtsi"
+/include/ "qoriq-i2c-1.dtsi"
+/include/ "qoriq-duart-0.dtsi"
+/include/ "qoriq-duart-1.dtsi"
+/include/ "qoriq-gpio-0.dtsi"
+/include/ "qoriq-gpio-1.dtsi"
+/include/ "qoriq-gpio-2.dtsi"
+/include/ "qoriq-gpio-3.dtsi"
+/include/ "qoriq-usb2-mph-0.dtsi"
+		usb0: usb@210000 {
+			compatible = "fsl-usb2-mph-v2.4", "fsl-usb2-mph";
+			phy_type = "utmi";
+			port0;
+		};
+/include/ "qoriq-usb2-dr-0.dtsi"
+		usb1: usb@211000 {
+			compatible = "fsl-usb2-dr-v2.4", "fsl-usb2-dr";
+			dr_mode = "host";
+			phy_type = "utmi";
+		};
+/include/ "qoriq-sata2-0.dtsi"
+/include/ "qoriq-sata2-1.dtsi"
+/include/ "qoriq-sec5.0-0.dtsi"
+
+	L2_1: l2-cache-controller@c20000 {
+		compatible = "fsl,t4240-l2-cache-controller";
+		reg = <0xc20000 0x40000>;
+		next-level-cache = <&cpc>;
+	};
+	L2_2: l2-cache-controller@c60000 {
+		compatible = "fsl,t4240-l2-cache-controller";
+		reg = <0xc60000 0x40000>;
+		next-level-cache = <&cpc>;
+	};
+	L2_3: l2-cache-controller@ca0000 {
+		compatible = "fsl,t4240-l2-cache-controller";
+		reg = <0xca0000 0x40000>;
+		next-level-cache = <&cpc>;
+	};
+};
diff --git a/arch/powerpc/boot/dts/fsl/t4240si-pre.dtsi b/arch/powerpc/boot/dts/fsl/t4240si-pre.dtsi
new file mode 100644
index 0000000..9b39a43
--- /dev/null
+++ b/arch/powerpc/boot/dts/fsl/t4240si-pre.dtsi
@@ -0,0 +1,128 @@
+/*
+ * T4240 Silicon/SoC Device Tree Source (pre include)
+ *
+ * Copyright 2012 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/;
+
+/include/ "e6500_power_isa.dtsi"
+
+/ {
+	compatible = "fsl,T4240";
+	#address-cells = <2>;
+	#size-cells = <2>;
+	interrupt-parent = <&mpic>;
+
+	aliases {
+		ccsr = &soc;
+		dcsr = &dcsr;
+
+		serial0 = &serial0;
+		serial1 = &serial1;
+		serial2 = &serial2;
+		serial3 = &serial3;
+		crypto = &crypto;
+		pci0 = &pci0;
+		pci1 = &pci1;
+		pci2 = &pci2;
+		pci3 = &pci3;
+		dma0 = &dma0;
+		dma1 = &dma1;
+		sdhc = &sdhc;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu0: PowerPC,e6500@0 {
+			device_type = "cpu";
+			reg = <0 1>;
+			next-level-cache = <&L2_1>;
+		};
+		cpu1: PowerPC,e6500@1 {
+			device_type = "cpu";
+			reg = <2 3>;
+			next-level-cache = <&L2_1>;
+		};
+		cpu2: PowerPC,e6500@2 {
+			device_type = "cpu";
+			reg = <4 5>;
+			next-level-cache = <&L2_1>;
+		};
+		cpu3: PowerPC,e6500@3 {
+			device_type = "cpu";
+			reg = <6 7>;
+			next-level-cache = <&L2_1>;
+		};
+		cpu4: PowerPC,e6500@4 {
+			device_type = "cpu";
+			reg = <8 9>;
+			next-level-cache = <&L2_2>;
+		};
+		cpu5: PowerPC,e6500@5 {
+			device_type = "cpu";
+			reg = <10 11>;
+			next-level-cache = <&L2_2>;
+		};
+		cpu6: PowerPC,e6500@6 {
+			device_type = "cpu";
+			reg = <12 13>;
+			next-level-cache = <&L2_2>;
+		};
+		cpu7: PowerPC,e6500@7 {
+			device_type = "cpu";
+			reg = <14 15>;
+			next-level-cache = <&L2_2>;
+		};
+		cpu8: PowerPC,e6500@8 {
+			device_type = "cpu";
+			reg = <16 17>;
+			next-level-cache = <&L2_3>;
+		};
+		cpu9: PowerPC,e6500@9 {
+			device_type = "cpu";
+			reg = <18 19>;
+			next-level-cache = <&L2_3>;
+		};
+		cpu10: PowerPC,e6500@10 {
+			device_type = "cpu";
+			reg = <20 21>;
+			next-level-cache = <&L2_3>;
+		};
+		cpu11: PowerPC,e6500@11 {
+			device_type = "cpu";
+			reg = <22 23>;
+			next-level-cache = <&L2_3>;
+		};
+	};
+};
diff --git a/arch/powerpc/boot/dts/p1021rdb-pc.dtsi b/arch/powerpc/boot/dts/p1021rdb-pc.dtsi
index c13abfb..d6274c5 100644
--- a/arch/powerpc/boot/dts/p1021rdb-pc.dtsi
+++ b/arch/powerpc/boot/dts/p1021rdb-pc.dtsi
@@ -62,11 +62,19 @@
 		};
 
 		partition@400000 {
-			/* 11MB for JFFS2 based Root file System */
-			reg = <0x00400000 0x00b00000>;
+			/* 10.75MB for JFFS2 based Root file System */
+			reg = <0x00400000 0x00ac0000>;
 			label = "NOR JFFS2 Root File System";
 		};
 
+		partition@ec0000 {
+			/* This location must not be altered  */
+			/* 256KB for QE ucode firmware*/
+			reg = <0x00ec0000 0x00040000>;
+			label = "NOR QE microcode firmware";
+			read-only;
+		};
+
 		partition@f00000 {
 			/* This location must not be altered  */
 			/* 512KB for u-boot Bootloader Image */
diff --git a/arch/powerpc/boot/dts/t4240qds.dts b/arch/powerpc/boot/dts/t4240qds.dts
new file mode 100644
index 0000000..0555976
--- /dev/null
+++ b/arch/powerpc/boot/dts/t4240qds.dts
@@ -0,0 +1,224 @@
+/*
+ * T4240QDS Device Tree Source
+ *
+ * Copyright 2012 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/ "fsl/t4240si-pre.dtsi"
+
+/ {
+	model = "fsl,T4240QDS";
+	compatible = "fsl,T4240QDS";
+	#address-cells = <2>;
+	#size-cells = <2>;
+	interrupt-parent = <&mpic>;
+
+	ifc: localbus@ffe124000 {
+		reg = <0xf 0xfe124000 0 0x2000>;
+		ranges = <0 0 0xf 0xe8000000 0x08000000
+			  2 0 0xf 0xff800000 0x00010000
+			  3 0 0xf 0xffdf0000 0x00008000>;
+
+		nor@0,0 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "cfi-flash";
+			reg = <0x0 0x0 0x8000000>;
+
+			bank-width = <2>;
+			device-width = <1>;
+		};
+
+		nand@2,0 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,ifc-nand";
+			reg = <0x2 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 {
+				/* 10MB for Linux Kernel Image */
+				reg = <0x00200000 0x00A00000>;
+				label = "NAND Linux Kernel Image";
+			};
+
+			partition@C00000 {
+				/* 500MB for Root file System Image */
+				reg = <0x00c00000 0x1F400000>;
+				label = "NAND RFS Image";
+			};
+		};
+
+		board-control@3,0 {
+			compatible = "fsl,t4240qds-fpga", "fsl,fpga-qixis";
+			reg = <3 0 0x300>;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+	};
+
+	dcsr: dcsr@f00000000 {
+		ranges = <0x00000000 0xf 0x00000000 0x01072000>;
+	};
+
+	soc: soc@ffe000000 {
+		ranges = <0x00000000 0xf 0xfe000000 0x1000000>;
+		reg = <0xf 0xfe000000 0 0x00001000>;
+		spi@110000 {
+			flash@0 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "sst,sst25wf040";
+				reg = <0>;
+				spi-max-frequency = <40000000>; /* input clock */
+			};
+		};
+
+		i2c@118000 {
+			eeprom@51 {
+				compatible = "at24,24c256";
+				reg = <0x51>;
+			};
+			eeprom@52 {
+				compatible = "at24,24c256";
+				reg = <0x52>;
+			};
+			eeprom@53 {
+				compatible = "at24,24c256";
+				reg = <0x53>;
+			};
+			eeprom@54 {
+				compatible = "at24,24c256";
+				reg = <0x54>;
+			};
+			eeprom@55 {
+				compatible = "at24,24c256";
+				reg = <0x55>;
+			};
+			eeprom@56 {
+				compatible = "at24,24c256";
+				reg = <0x56>;
+			};
+			rtc@68 {
+				compatible = "dallas,ds3232";
+				reg = <0x68>;
+				interrupts = <0x1 0x1 0 0>;
+			};
+		};
+	};
+
+	pci0: pcie@ffe240000 {
+		reg = <0xf 0xfe240000 0 0x10000>;
+		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@ffe250000 {
+		reg = <0xf 0xfe250000 0 0x10000>;
+		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@ffe260000 {
+		reg = <0xf 0xfe260000 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@ffe270000 {
+		reg = <0xf 0xfe270000 0 0x10000>;
+		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>;
+		};
+	};
+	rio: rapidio@ffe0c0000 {
+		reg = <0xf 0xfe0c0000 0 0x11000>;
+
+		port1 {
+			ranges = <0 0 0xc 0x20000000 0 0x10000000>;
+		};
+		port2 {
+			ranges = <0 0 0xc 0x30000000 0 0x10000000>;
+		};
+	};
+};
+
+/include/ "fsl/t4240si-post.dtsi"
diff --git a/arch/powerpc/configs/corenet64_smp_defconfig b/arch/powerpc/configs/corenet64_smp_defconfig
index 3d139fa..1c6eb66 100644
--- a/arch/powerpc/configs/corenet64_smp_defconfig
+++ b/arch/powerpc/configs/corenet64_smp_defconfig
@@ -1,14 +1,13 @@
 CONFIG_PPC64=y
 CONFIG_PPC_BOOK3E_64=y
-# CONFIG_VIRT_CPU_ACCOUNTING_NATIVE is not set
+CONFIG_ALTIVEC=y
 CONFIG_SMP=y
-CONFIG_NR_CPUS=2
-CONFIG_EXPERIMENTAL=y
+CONFIG_NR_CPUS=24
 CONFIG_SYSVIPC=y
-CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_IRQ_DOMAIN_DEBUG=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
+CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
@@ -24,8 +23,10 @@ CONFIG_PARTITION_ADVANCED=y
 CONFIG_MAC_PARTITION=y
 CONFIG_P5020_DS=y
 CONFIG_P5040_DS=y
+CONFIG_T4240_QDS=y
 # CONFIG_PPC_OF_BOOT_TRAMPOLINE is not set
 CONFIG_BINFMT_MISC=m
+CONFIG_FSL_IFC=y
 CONFIG_PCIEPORTBUS=y
 CONFIG_PCI_MSI=y
 CONFIG_RAPIDIO=y
@@ -58,16 +59,33 @@ CONFIG_IP_SCTP=m
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_DEVTMPFS=y
 CONFIG_MTD=y
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_OF_PARTS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
 CONFIG_MTD_BLOCK=y
+CONFIG_FTL=y
 CONFIG_MTD_CFI=y
+CONFIG_MTD_GEN_PROBE=y
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+CONFIG_MTD_CFI_INTELEXT=y
 CONFIG_MTD_CFI_AMDSTD=y
 CONFIG_MTD_PHYSMAP_OF=y
 CONFIG_MTD_M25P80=y
+CONFIG_MTD_CFI_UTIL=y
+CONFIG_MTD_NAND_ECC=y
 CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_IDS=y
 CONFIG_MTD_NAND_FSL_ELBC=y
 CONFIG_MTD_NAND_FSL_IFC=y
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_RESERVE=1
 CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
@@ -78,6 +96,7 @@ CONFIG_SATA_FSL=y
 CONFIG_SATA_SIL24=y
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=y
+CONFIG_E1000E=y
 CONFIG_INPUT_FF_MEMLESS=m
 # CONFIG_INPUT_MOUSEDEV is not set
 # CONFIG_INPUT_KEYBOARD is not set
@@ -121,7 +140,16 @@ CONFIG_NTFS_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_TMPFS=y
 CONFIG_HUGETLBFS=y
-# CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_MISC_FILESYSTEMS=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=1
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+CONFIG_UBIFS_FS=y
+CONFIG_UBIFS_FS_XATTR=y
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
 CONFIG_NFS_FS=y
 CONFIG_NFS_V4=y
 CONFIG_ROOT_NFS=y
@@ -129,6 +157,12 @@ CONFIG_NFSD=m
 CONFIG_NLS_ISO8859_1=y
 CONFIG_NLS_UTF8=m
 CONFIG_CRC_T10DIF=y
+CONFIG_CRC16=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_LZO=y
 CONFIG_FRAME_WARN=1024
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_FS=y
@@ -140,6 +174,5 @@ 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
 CONFIG_CRYPTO_DEV_FSL_CAAM=y
diff --git a/arch/powerpc/configs/mpc512x_defconfig b/arch/powerpc/configs/mpc512x_defconfig
index 211fcc9..0d0d981 100644
--- a/arch/powerpc/configs/mpc512x_defconfig
+++ b/arch/powerpc/configs/mpc512x_defconfig
@@ -13,7 +13,7 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_PPC_CHRP is not set
 CONFIG_PPC_MPC512x=y
 CONFIG_MPC5121_ADS=y
-CONFIG_MPC5121_GENERIC=y
+CONFIG_MPC512x_GENERIC=y
 CONFIG_PDM360NG=y
 # CONFIG_PPC_PMAC is not set
 CONFIG_NO_HZ=y
diff --git a/arch/powerpc/configs/mpc85xx_defconfig b/arch/powerpc/configs/mpc85xx_defconfig
index cf815e8..37812b4 100644
--- a/arch/powerpc/configs/mpc85xx_defconfig
+++ b/arch/powerpc/configs/mpc85xx_defconfig
@@ -1,13 +1,12 @@
 CONFIG_PPC_85xx=y
 CONFIG_PHYS_64BIT=y
-CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
-CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_AUDIT=y
 CONFIG_IRQ_DOMAIN_DEBUG=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
+CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
@@ -48,6 +47,7 @@ CONFIG_HIGHMEM=y
 CONFIG_BINFMT_MISC=m
 CONFIG_MATH_EMULATION=y
 CONFIG_FORCE_MAX_ZONEORDER=12
+CONFIG_FSL_IFC=y
 CONFIG_PCI=y
 CONFIG_PCI_MSI=y
 CONFIG_RAPIDIO=y
@@ -79,18 +79,33 @@ CONFIG_IP_SCTP=m
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_DEVTMPFS=y
 CONFIG_MTD=y
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_OF_PARTS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
 CONFIG_MTD_BLOCK=y
 CONFIG_FTL=y
 CONFIG_MTD_CFI=y
+CONFIG_MTD_GEN_PROBE=y
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
 CONFIG_MTD_CFI_INTELEXT=y
 CONFIG_MTD_CFI_AMDSTD=y
 CONFIG_MTD_PHYSMAP_OF=y
 CONFIG_MTD_M25P80=y
+CONFIG_MTD_CFI_UTIL=y
+CONFIG_MTD_NAND_ECC=y
 CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_IDS=y
 CONFIG_MTD_NAND_FSL_ELBC=y
 CONFIG_MTD_NAND_FSL_IFC=y
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_RESERVE=1
 CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_NBD=y
@@ -113,6 +128,9 @@ CONFIG_DUMMY=y
 CONFIG_FS_ENET=y
 CONFIG_UCC_GETH=y
 CONFIG_GIANFAR=y
+CONFIG_E1000=y
+CONFIG_E1000E=y
+CONFIG_IGB=y
 CONFIG_MARVELL_PHY=y
 CONFIG_DAVICOM_PHY=y
 CONFIG_CICADA_PHY=y
@@ -132,7 +150,6 @@ CONFIG_SERIAL_8250_DETECT_IRQ=y
 CONFIG_SERIAL_8250_RSA=y
 CONFIG_SERIAL_QE=m
 CONFIG_NVRAM=y
-CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_CPM=m
 CONFIG_I2C_MPC=y
@@ -206,6 +223,15 @@ CONFIG_NTFS_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_TMPFS=y
 CONFIG_HUGETLBFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=1
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+CONFIG_UBIFS_FS=y
+CONFIG_UBIFS_FS_XATTR=y
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
 CONFIG_ADFS_FS=m
 CONFIG_AFFS_FS=m
 CONFIG_HFS_FS=m
@@ -224,13 +250,18 @@ CONFIG_NFS_V4=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=y
 CONFIG_CRC_T10DIF=y
+CONFIG_CRC16=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_LZO=y
 CONFIG_DEBUG_FS=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_DEBUG_INFO=y
 CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_SHA256=y
 CONFIG_CRYPTO_SHA512=y
-CONFIG_CRYPTO_AES=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_DEV_FSL_CAAM=y
 CONFIG_CRYPTO_DEV_TALITOS=y
diff --git a/arch/powerpc/configs/mpc85xx_smp_defconfig b/arch/powerpc/configs/mpc85xx_smp_defconfig
index 8d00ea5b..7fc3e6f 100644
--- a/arch/powerpc/configs/mpc85xx_smp_defconfig
+++ b/arch/powerpc/configs/mpc85xx_smp_defconfig
@@ -50,6 +50,7 @@ CONFIG_HIGHMEM=y
 CONFIG_BINFMT_MISC=m
 CONFIG_MATH_EMULATION=y
 CONFIG_FORCE_MAX_ZONEORDER=12
+CONFIG_FSL_IFC=y
 CONFIG_PCI=y
 CONFIG_PCI_MSI=y
 CONFIG_RAPIDIO=y
@@ -81,18 +82,33 @@ CONFIG_IP_SCTP=m
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_DEVTMPFS=y
 CONFIG_MTD=y
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_OF_PARTS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
 CONFIG_MTD_BLOCK=y
 CONFIG_FTL=y
 CONFIG_MTD_CFI=y
+CONFIG_MTD_GEN_PROBE=y
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
 CONFIG_MTD_CFI_INTELEXT=y
 CONFIG_MTD_CFI_AMDSTD=y
 CONFIG_MTD_PHYSMAP_OF=y
 CONFIG_MTD_M25P80=y
+CONFIG_MTD_CFI_UTIL=y
+CONFIG_MTD_NAND_ECC=y
 CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_IDS=y
 CONFIG_MTD_NAND_FSL_ELBC=y
 CONFIG_MTD_NAND_FSL_IFC=y
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_RESERVE=1
 CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_NBD=y
@@ -207,6 +223,15 @@ CONFIG_NTFS_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_TMPFS=y
 CONFIG_HUGETLBFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=1
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+CONFIG_UBIFS_FS=y
+CONFIG_UBIFS_FS_XATTR=y
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
 CONFIG_ADFS_FS=m
 CONFIG_AFFS_FS=m
 CONFIG_HFS_FS=m
@@ -225,6 +250,12 @@ CONFIG_NFS_V4=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=y
 CONFIG_CRC_T10DIF=y
+CONFIG_CRC16=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_LZO=y
 CONFIG_DEBUG_FS=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_DEBUG_INFO=y
diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h
index fb3245e..f326444 100644
--- a/arch/powerpc/include/asm/cputable.h
+++ b/arch/powerpc/include/asm/cputable.h
@@ -374,7 +374,7 @@ extern const char *powerpc_base_platform;
 #define CPU_FTRS_E6500	(CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN | \
 	    CPU_FTR_L2CSR | CPU_FTR_LWSYNC | CPU_FTR_NOEXECUTE | \
 	    CPU_FTR_DBELL | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \
-	    CPU_FTR_DEBUG_LVL_EXC | CPU_FTR_EMB_HV)
+	    CPU_FTR_DEBUG_LVL_EXC | CPU_FTR_EMB_HV | CPU_FTR_ALTIVEC_COMP)
 #define CPU_FTRS_GENERIC_32	(CPU_FTR_COMMON | CPU_FTR_NODSISRALIGN)
 
 /* 64-bit CPUs */
diff --git a/arch/powerpc/include/asm/hugetlb.h b/arch/powerpc/include/asm/hugetlb.h
index 62e11a3..4fcbd6b 100644
--- a/arch/powerpc/include/asm/hugetlb.h
+++ b/arch/powerpc/include/asm/hugetlb.h
@@ -3,6 +3,7 @@
 
 #ifdef CONFIG_HUGETLB_PAGE
 #include <asm/page.h>
+#include <asm-generic/hugetlb.h>
 
 extern struct kmem_cache *hugepte_cache;
 
diff --git a/arch/powerpc/include/asm/kvm_asm.h b/arch/powerpc/include/asm/kvm_asm.h
index aabcdba..b9dd382 100644
--- a/arch/powerpc/include/asm/kvm_asm.h
+++ b/arch/powerpc/include/asm/kvm_asm.h
@@ -67,6 +67,10 @@
 #define BOOKE_INTERRUPT_HV_SYSCALL 40
 #define BOOKE_INTERRUPT_HV_PRIV 41
 
+/* altivec */
+#define BOOKE_INTERRUPT_ALTIVEC_UNAVAIL 42
+#define BOOKE_INTERRUPT_ALTIVEC_ASSIST 43
+
 /* book3s */
 
 #define BOOK3S_INTERRUPT_SYSTEM_RESET	0x100
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index d1bb860..e34f8fe 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -504,6 +504,7 @@ struct kvm_vcpu_arch {
 	u32 tlbcfg[4];
 	u32 mmucfg;
 	u32 epr;
+	u32 crit_save;
 	struct kvmppc_booke_debug_reg dbg_reg;
 #endif
 	gpa_t paddr_accessed;
diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h
index 44a657a..f589307 100644
--- a/arch/powerpc/include/asm/kvm_ppc.h
+++ b/arch/powerpc/include/asm/kvm_ppc.h
@@ -104,8 +104,7 @@ extern void kvmppc_core_queue_dec(struct kvm_vcpu *vcpu);
 extern void kvmppc_core_dequeue_dec(struct kvm_vcpu *vcpu);
 extern void kvmppc_core_queue_external(struct kvm_vcpu *vcpu,
                                        struct kvm_interrupt *irq);
-extern void kvmppc_core_dequeue_external(struct kvm_vcpu *vcpu,
-                                         struct kvm_interrupt *irq);
+extern void kvmppc_core_dequeue_external(struct kvm_vcpu *vcpu);
 extern void kvmppc_core_flush_tlb(struct kvm_vcpu *vcpu);
 
 extern int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
@@ -152,7 +151,7 @@ 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,
-				struct kvm_memory_slot old);
+				const struct kvm_memory_slot *old);
 extern int kvm_vm_ioctl_get_smmu_info(struct kvm *kvm,
 				      struct kvm_ppc_smmu_info *info);
 extern void kvmppc_core_flush_memslot(struct kvm *kvm,
diff --git a/arch/powerpc/include/asm/linkage.h b/arch/powerpc/include/asm/linkage.h
new file mode 100644
index 0000000..b36f650
--- /dev/null
+++ b/arch/powerpc/include/asm/linkage.h
@@ -0,0 +1,13 @@
+#ifndef _ASM_POWERPC_LINKAGE_H
+#define _ASM_POWERPC_LINKAGE_H
+
+#ifdef CONFIG_PPC64
+#define cond_syscall(x) \
+	asm ("\t.weak " #x "\n\t.set " #x ", sys_ni_syscall\n"		\
+	     "\t.weak ." #x "\n\t.set ." #x ", .sys_ni_syscall\n")
+#define SYSCALL_ALIAS(alias, name)					\
+	asm ("\t.globl " #alias "\n\t.set " #alias ", " #name "\n"	\
+	     "\t.globl ." #alias "\n\t.set ." #alias ", ." #name)
+#endif
+
+#endif	/* _ASM_POWERPC_LINKAGE_H */
diff --git a/arch/powerpc/include/asm/page_64.h b/arch/powerpc/include/asm/page_64.h
index cd915d6..88693ce 100644
--- a/arch/powerpc/include/asm/page_64.h
+++ b/arch/powerpc/include/asm/page_64.h
@@ -99,8 +99,7 @@ extern unsigned long slice_get_unmapped_area(unsigned long addr,
 					     unsigned long len,
 					     unsigned long flags,
 					     unsigned int psize,
-					     int topdown,
-					     int use_cache);
+					     int topdown);
 
 extern unsigned int get_slice_psize(struct mm_struct *mm,
 				    unsigned long addr);
diff --git a/arch/powerpc/include/asm/systbl.h b/arch/powerpc/include/asm/systbl.h
index ebbec52..43523fe 100644
--- a/arch/powerpc/include/asm/systbl.h
+++ b/arch/powerpc/include/asm/systbl.h
@@ -190,7 +190,7 @@ SYSCALL_SPU(getcwd)
 SYSCALL_SPU(capget)
 SYSCALL_SPU(capset)
 COMPAT_SYS(sigaltstack)
-SYSX_SPU(sys_sendfile,compat_sys_sendfile_wrapper,sys_sendfile)
+COMPAT_SYS_SPU(sendfile)
 SYSCALL(ni_syscall)
 SYSCALL(ni_syscall)
 PPC_SYS(vfork)
@@ -230,7 +230,7 @@ COMPAT_SYS_SPU(sched_setaffinity)
 COMPAT_SYS_SPU(sched_getaffinity)
 SYSCALL(ni_syscall)
 SYSCALL(ni_syscall)
-SYSX(sys_ni_syscall,compat_sys_sendfile64_wrapper,sys_sendfile64)
+SYS32ONLY(sendfile64)
 COMPAT_SYS_SPU(io_setup)
 SYSCALL_SPU(io_destroy)
 COMPAT_SYS_SPU(io_getevents)
@@ -239,7 +239,7 @@ SYSCALL_SPU(io_cancel)
 SYSCALL(set_tid_address)
 SYSX_SPU(sys_fadvise64,ppc32_fadvise64,sys_fadvise64)
 SYSCALL(exit_group)
-SYSX(sys_lookup_dcookie,ppc32_lookup_dcookie,sys_lookup_dcookie)
+COMPAT_SYS(lookup_dcookie)
 SYSCALL_SPU(epoll_create)
 SYSCALL_SPU(epoll_ctl)
 SYSCALL_SPU(epoll_wait)
@@ -273,8 +273,8 @@ COMPAT_SYS(mq_timedreceive)
 COMPAT_SYS(mq_notify)
 COMPAT_SYS(mq_getsetattr)
 COMPAT_SYS(kexec_load)
-COMPAT_SYS(add_key)
-COMPAT_SYS(request_key)
+SYSCALL(add_key)
+SYSCALL(request_key)
 COMPAT_SYS(keyctl)
 COMPAT_SYS(waitid)
 SYSCALL(ioprio_set)
diff --git a/arch/powerpc/include/asm/unistd.h b/arch/powerpc/include/asm/unistd.h
index 1487f0f..3ca819f 100644
--- a/arch/powerpc/include/asm/unistd.h
+++ b/arch/powerpc/include/asm/unistd.h
@@ -56,11 +56,5 @@
 #define __ARCH_WANT_SYS_VFORK
 #define __ARCH_WANT_SYS_CLONE
 
-/*
- * "Conditional" syscalls
- */
-#define cond_syscall(x) \
-	asmlinkage long x (void) __attribute__((weak,alias("sys_ni_syscall")))
-
 #endif		/* __ASSEMBLY__ */
 #endif /* _ASM_POWERPC_UNISTD_H_ */
diff --git a/arch/powerpc/include/uapi/asm/kvm.h b/arch/powerpc/include/uapi/asm/kvm.h
index 16064d0..ef072b1 100644
--- a/arch/powerpc/include/uapi/asm/kvm.h
+++ b/arch/powerpc/include/uapi/asm/kvm.h
@@ -417,4 +417,9 @@ struct kvm_get_htab_header {
 #define KVM_REG_PPC_EPCR	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x85)
 #define KVM_REG_PPC_EPR		(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x86)
 
+/* Timer Status Register OR/CLEAR interface */
+#define KVM_REG_PPC_OR_TSR	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x87)
+#define KVM_REG_PPC_CLEAR_TSR	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x88)
+#define KVM_REG_PPC_TCR		(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x89)
+#define KVM_REG_PPC_TSR		(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x8a)
 #endif /* __LINUX_KVM_POWERPC_H */
diff --git a/arch/powerpc/include/uapi/asm/linkage.h b/arch/powerpc/include/uapi/asm/linkage.h
deleted file mode 100644
index e1c4ac1..0000000
--- a/arch/powerpc/include/uapi/asm/linkage.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_POWERPC_LINKAGE_H
-#define _ASM_POWERPC_LINKAGE_H
-
-/* Nothing to see here... */
-
-#endif	/* _ASM_POWERPC_LINKAGE_H */
diff --git a/arch/powerpc/include/uapi/asm/socket.h b/arch/powerpc/include/uapi/asm/socket.h
index a26dcae..a36daf3 100644
--- a/arch/powerpc/include/uapi/asm/socket.h
+++ b/arch/powerpc/include/uapi/asm/socket.h
@@ -79,4 +79,6 @@
 
 #define SO_LOCK_FILTER		44
 
+#define SO_SELECT_ERR_QUEUE	45
+
 #endif	/* _ASM_POWERPC_SOCKET_H */
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index b6c17ec..d87c908 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -596,6 +596,7 @@ int main(void)
 	DEFINE(VCPU_LAST_INST, offsetof(struct kvm_vcpu, arch.last_inst));
 	DEFINE(VCPU_FAULT_DEAR, offsetof(struct kvm_vcpu, arch.fault_dear));
 	DEFINE(VCPU_FAULT_ESR, offsetof(struct kvm_vcpu, arch.fault_esr));
+	DEFINE(VCPU_CRIT_SAVE, offsetof(struct kvm_vcpu, arch.crit_save));
 #endif /* CONFIG_PPC_BOOK3S */
 #endif /* CONFIG_KVM */
 
diff --git a/arch/powerpc/kernel/cpu_setup_fsl_booke.S b/arch/powerpc/kernel/cpu_setup_fsl_booke.S
index dcd8819..0b9af01 100644
--- a/arch/powerpc/kernel/cpu_setup_fsl_booke.S
+++ b/arch/powerpc/kernel/cpu_setup_fsl_booke.S
@@ -53,6 +53,15 @@ _GLOBAL(__e500_dcache_setup)
 	isync
 	blr
 
+_GLOBAL(__setup_cpu_e6500)
+	mflr	r6
+#ifdef CONFIG_PPC64
+	bl	.setup_altivec_ivors
+#endif
+	bl	__setup_cpu_e5500
+	mtlr	r6
+	blr
+
 #ifdef CONFIG_PPC32
 _GLOBAL(__setup_cpu_e200)
 	/* enable dedicated debug exception handling resources (Debug APU) */
@@ -107,6 +116,13 @@ _GLOBAL(__setup_cpu_e5500)
 #endif
 
 #ifdef CONFIG_PPC_BOOK3E_64
+_GLOBAL(__restore_cpu_e6500)
+	mflr	r5
+	bl	.setup_altivec_ivors
+	bl	__restore_cpu_e5500
+	mtlr	r5
+	blr
+
 _GLOBAL(__restore_cpu_e5500)
 	mflr	r4
 	bl	__e500_icache_setup
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index 19599ef..ae9f433 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -74,7 +74,9 @@ extern void __restore_cpu_a2(void);
 #endif /* CONFIG_PPC64 */
 #if defined(CONFIG_E500)
 extern void __setup_cpu_e5500(unsigned long offset, struct cpu_spec* spec);
+extern void __setup_cpu_e6500(unsigned long offset, struct cpu_spec* spec);
 extern void __restore_cpu_e5500(void);
+extern void __restore_cpu_e6500(void);
 #endif /* CONFIG_E500 */
 
 /* This table only contains "desktop" CPUs, it need to be filled with embedded
@@ -2065,7 +2067,8 @@ static struct cpu_spec __initdata cpu_specs[] = {
 		.pvr_value		= 0x80400000,
 		.cpu_name		= "e6500",
 		.cpu_features		= CPU_FTRS_E6500,
-		.cpu_user_features	= COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU,
+		.cpu_user_features	= COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU |
+			PPC_FEATURE_HAS_ALTIVEC_COMP,
 		.mmu_features		= MMU_FTR_TYPE_FSL_E | MMU_FTR_BIG_PHYS |
 			MMU_FTR_USE_TLBILX,
 		.icache_bsize		= 64,
@@ -2073,9 +2076,9 @@ static struct cpu_spec __initdata cpu_specs[] = {
 		.num_pmcs		= 4,
 		.oprofile_cpu_type	= "ppc/e6500",
 		.oprofile_type		= PPC_OPROFILE_FSL_EMB,
-		.cpu_setup		= __setup_cpu_e5500,
+		.cpu_setup		= __setup_cpu_e6500,
 #ifndef CONFIG_PPC32
-		.cpu_restore		= __restore_cpu_e5500,
+		.cpu_restore		= __restore_cpu_e6500,
 #endif
 		.machine_check		= machine_check_e500mc,
 		.platform		= "ppce6500",
diff --git a/arch/powerpc/kernel/crash_dump.c b/arch/powerpc/kernel/crash_dump.c
index b3ba516..9ec3fe1 100644
--- a/arch/powerpc/kernel/crash_dump.c
+++ b/arch/powerpc/kernel/crash_dump.c
@@ -150,10 +150,7 @@ void crash_free_reserved_phys_range(unsigned long begin, unsigned long end)
 		if (addr <= rtas_end && ((addr + PAGE_SIZE) > rtas_start))
 			continue;
 
-		ClearPageReserved(pfn_to_page(addr >> PAGE_SHIFT));
-		init_page_count(pfn_to_page(addr >> PAGE_SHIFT));
-		free_page((unsigned long)__va(addr));
-		totalram_pages++;
+		free_reserved_page(pfn_to_page(addr >> PAGE_SHIFT));
 	}
 }
 #endif
diff --git a/arch/powerpc/kernel/epapr_hcalls.S b/arch/powerpc/kernel/epapr_hcalls.S
index 62c0dc2..9f1ebf7 100644
--- a/arch/powerpc/kernel/epapr_hcalls.S
+++ b/arch/powerpc/kernel/epapr_hcalls.S
@@ -17,6 +17,7 @@
 #include <asm/asm-compat.h>
 #include <asm/asm-offsets.h>
 
+#ifndef CONFIG_PPC64
 /* epapr_ev_idle() was derived from e500_idle() */
 _GLOBAL(epapr_ev_idle)
 	CURRENT_THREAD_INFO(r3, r1)
@@ -42,6 +43,7 @@ epapr_ev_idle_start:
 	 * _TLF_NAPPING.
 	 */
 	b	idle_loop
+#endif
 
 /* Hypercall entry point. Will be patched with device tree instructions. */
 .global epapr_hypercall_start
diff --git a/arch/powerpc/kernel/exceptions-64e.S b/arch/powerpc/kernel/exceptions-64e.S
index ae54553..42a756e 100644
--- a/arch/powerpc/kernel/exceptions-64e.S
+++ b/arch/powerpc/kernel/exceptions-64e.S
@@ -299,6 +299,8 @@ interrupt_base_book3e:					/* fake trap */
 	EXCEPTION_STUB(0x1a0, watchdog)			/* 0x09f0 */
 	EXCEPTION_STUB(0x1c0, data_tlb_miss)
 	EXCEPTION_STUB(0x1e0, instruction_tlb_miss)
+	EXCEPTION_STUB(0x200, altivec_unavailable)	/* 0x0f20 */
+	EXCEPTION_STUB(0x220, altivec_assist)		/* 0x1700 */
 	EXCEPTION_STUB(0x260, perfmon)
 	EXCEPTION_STUB(0x280, doorbell)
 	EXCEPTION_STUB(0x2a0, doorbell_crit)
@@ -395,6 +397,45 @@ interrupt_end_book3e:
 	bl	.kernel_fp_unavailable_exception
 	b	.ret_from_except
 
+/* Altivec Unavailable Interrupt */
+	START_EXCEPTION(altivec_unavailable);
+	NORMAL_EXCEPTION_PROLOG(0x200, BOOKE_INTERRUPT_ALTIVEC_UNAVAIL,
+				PROLOG_ADDITION_NONE)
+	/* we can probably do a shorter exception entry for that one... */
+	EXCEPTION_COMMON(0x200, PACA_EXGEN, INTS_KEEP)
+#ifdef CONFIG_ALTIVEC
+BEGIN_FTR_SECTION
+	ld	r12,_MSR(r1)
+	andi.	r0,r12,MSR_PR;
+	beq-	1f
+	bl	.load_up_altivec
+	b	fast_exception_return
+1:
+END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
+#endif
+	INTS_DISABLE
+	bl	.save_nvgprs
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	bl	.altivec_unavailable_exception
+	b	.ret_from_except
+
+/* AltiVec Assist */
+	START_EXCEPTION(altivec_assist);
+	NORMAL_EXCEPTION_PROLOG(0x220, BOOKE_INTERRUPT_ALTIVEC_ASSIST,
+				PROLOG_ADDITION_NONE)
+	EXCEPTION_COMMON(0x220, PACA_EXGEN, INTS_DISABLE)
+	bl	.save_nvgprs
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+#ifdef CONFIG_ALTIVEC
+BEGIN_FTR_SECTION
+	bl	.altivec_assist_exception
+END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
+#else
+	bl	.unknown_exception
+#endif
+	b	.ret_from_except
+
+
 /* Decrementer Interrupt */
 	MASKABLE_EXCEPTION(0x900, BOOKE_INTERRUPT_DECREMENTER,
 			   decrementer, .timer_interrupt, ACK_DEC)
@@ -807,6 +848,7 @@ fast_exception_return:
 BAD_STACK_TRAMPOLINE(0x000)
 BAD_STACK_TRAMPOLINE(0x100)
 BAD_STACK_TRAMPOLINE(0x200)
+BAD_STACK_TRAMPOLINE(0x220)
 BAD_STACK_TRAMPOLINE(0x260)
 BAD_STACK_TRAMPOLINE(0x280)
 BAD_STACK_TRAMPOLINE(0x2a0)
@@ -1350,6 +1392,11 @@ _GLOBAL(__setup_base_ivors)
 
 	blr
 
+_GLOBAL(setup_altivec_ivors)
+	SET_IVOR(32, 0x200) /* AltiVec Unavailable */
+	SET_IVOR(33, 0x220) /* AltiVec Assist */
+	blr
+
 _GLOBAL(setup_perfmon_ivor)
 	SET_IVOR(35, 0x260) /* Performance Monitor */
 	blr
diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c
index 06c8202..2230fd0 100644
--- a/arch/powerpc/kernel/fadump.c
+++ b/arch/powerpc/kernel/fadump.c
@@ -1045,10 +1045,7 @@ static void fadump_release_memory(unsigned long begin, unsigned long end)
 		if (addr <= ra_end && ((addr + PAGE_SIZE) > ra_start))
 			continue;
 
-		ClearPageReserved(pfn_to_page(addr >> PAGE_SHIFT));
-		init_page_count(pfn_to_page(addr >> PAGE_SHIFT));
-		free_page((unsigned long)__va(addr));
-		totalram_pages++;
+		free_reserved_page(pfn_to_page(addr >> PAGE_SHIFT));
 	}
 }
 
diff --git a/arch/powerpc/kernel/idle_book3e.S b/arch/powerpc/kernel/idle_book3e.S
index 4c7cb400..bfb73cc 100644
--- a/arch/powerpc/kernel/idle_book3e.S
+++ b/arch/powerpc/kernel/idle_book3e.S
@@ -16,11 +16,13 @@
 #include <asm/ppc-opcode.h>
 #include <asm/processor.h>
 #include <asm/thread_info.h>
+#include <asm/epapr_hcalls.h>
 
 /* 64-bit version only for now */
 #ifdef CONFIG_PPC64
 
-_GLOBAL(book3e_idle)
+.macro BOOK3E_IDLE name loop
+_GLOBAL(\name)
 	/* Save LR for later */
 	mflr	r0
 	std	r0,16(r1)
@@ -67,7 +69,33 @@ _GLOBAL(book3e_idle)
 
 	/* We can now re-enable hard interrupts and go to sleep */
 	wrteei	1
-1:	PPC_WAIT(0)
+	\loop
+
+.endm
+
+.macro BOOK3E_IDLE_LOOP
+1:
+	PPC_WAIT(0)
 	b	1b
+.endm
+
+/* epapr_ev_idle_start below is patched with the proper hcall
+   opcodes during kernel initialization */
+.macro EPAPR_EV_IDLE_LOOP
+idle_loop:
+	LOAD_REG_IMMEDIATE(r11, EV_HCALL_TOKEN(EV_IDLE))
+
+.global epapr_ev_idle_start
+epapr_ev_idle_start:
+	li      r3, -1
+	nop
+	nop
+	nop
+	b       idle_loop
+.endm
+
+BOOK3E_IDLE epapr_ev_idle EPAPR_EV_IDLE_LOOP
+
+BOOK3E_IDLE book3e_idle BOOK3E_IDLE_LOOP
 
 #endif /* CONFIG_PPC64 */
diff --git a/arch/powerpc/kernel/kvm.c b/arch/powerpc/kernel/kvm.c
index a61b133..6782221 100644
--- a/arch/powerpc/kernel/kvm.c
+++ b/arch/powerpc/kernel/kvm.c
@@ -756,12 +756,7 @@ static __init void kvm_free_tmp(void)
 	end = (ulong)&kvm_tmp[ARRAY_SIZE(kvm_tmp)] & PAGE_MASK;
 
 	/* Free the tmp space we don't need */
-	for (; start < end; start += PAGE_SIZE) {
-		ClearPageReserved(virt_to_page(start));
-		init_page_count(virt_to_page(start));
-		free_page(start);
-		totalram_pages++;
-	}
+	free_reserved_area(start, end, 0, NULL);
 }
 
 static int __init kvm_guest_init(void)
diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c
index f5725bc..801a757 100644
--- a/arch/powerpc/kernel/lparcfg.c
+++ b/arch/powerpc/kernel/lparcfg.c
@@ -41,8 +41,6 @@
 
 /* #define LPARCFG_DEBUG */
 
-static struct proc_dir_entry *proc_ppc64_lparcfg;
-
 /*
  * Track sum of all purrs across all processors. This is used to further
  * calculate usage values by different applications
@@ -688,27 +686,22 @@ static const struct file_operations lparcfg_fops = {
 
 static int __init lparcfg_init(void)
 {
-	struct proc_dir_entry *ent;
 	umode_t mode = S_IRUSR | S_IRGRP | S_IROTH;
 
 	/* Allow writing if we have FW_FEATURE_SPLPAR */
 	if (firmware_has_feature(FW_FEATURE_SPLPAR))
 		mode |= S_IWUSR;
 
-	ent = proc_create("powerpc/lparcfg", mode, NULL, &lparcfg_fops);
-	if (!ent) {
+	if (!proc_create("powerpc/lparcfg", mode, NULL, &lparcfg_fops)) {
 		printk(KERN_ERR "Failed to create powerpc/lparcfg\n");
 		return -EIO;
 	}
-
-	proc_ppc64_lparcfg = ent;
 	return 0;
 }
 
 static void __exit lparcfg_cleanup(void)
 {
-	if (proc_ppc64_lparcfg)
-		remove_proc_entry("lparcfg", proc_ppc64_lparcfg->parent);
+	remove_proc_subtree("powerpc/lparcfg", NULL);
 }
 
 module_init(lparcfg_init);
diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c
index bec1e93..48fbc2b 100644
--- a/arch/powerpc/kernel/nvram_64.c
+++ b/arch/powerpc/kernel/nvram_64.c
@@ -511,8 +511,7 @@ int __init nvram_scan_partitions(void)
 			       "detected: 0-length partition\n");
 			goto out;
 		}
-		tmp_part = (struct nvram_partition *)
-			kmalloc(sizeof(struct nvram_partition), GFP_KERNEL);
+		tmp_part = kmalloc(sizeof(struct nvram_partition), GFP_KERNEL);
 		err = -ENOMEM;
 		if (!tmp_part) {
 			printk(KERN_ERR "nvram_scan_partitions: kmalloc failed\n");
diff --git a/arch/powerpc/kernel/proc_powerpc.c b/arch/powerpc/kernel/proc_powerpc.c
index f19d0bd..41d8ee9 100644
--- a/arch/powerpc/kernel/proc_powerpc.c
+++ b/arch/powerpc/kernel/proc_powerpc.c
@@ -32,8 +32,6 @@
 static loff_t page_map_seek( struct file *file, loff_t off, int whence)
 {
 	loff_t new;
-	struct proc_dir_entry *dp = PDE(file_inode(file));
-
 	switch(whence) {
 	case 0:
 		new = off;
@@ -42,12 +40,12 @@ static loff_t page_map_seek( struct file *file, loff_t off, int whence)
 		new = file->f_pos + off;
 		break;
 	case 2:
-		new = dp->size + off;
+		new = PAGE_SIZE + off;
 		break;
 	default:
 		return -EINVAL;
 	}
-	if ( new < 0 || new > dp->size )
+	if ( new < 0 || new > PAGE_SIZE )
 		return -EINVAL;
 	return (file->f_pos = new);
 }
@@ -55,19 +53,18 @@ static loff_t page_map_seek( struct file *file, loff_t off, int whence)
 static ssize_t page_map_read( struct file *file, char __user *buf, size_t nbytes,
 			      loff_t *ppos)
 {
-	struct proc_dir_entry *dp = PDE(file_inode(file));
-	return simple_read_from_buffer(buf, nbytes, ppos, dp->data, dp->size);
+	return simple_read_from_buffer(buf, nbytes, ppos,
+			PDE_DATA(file_inode(file)), PAGE_SIZE);
 }
 
 static int page_map_mmap( struct file *file, struct vm_area_struct *vma )
 {
-	struct proc_dir_entry *dp = PDE(file_inode(file));
-
-	if ((vma->vm_end - vma->vm_start) > dp->size)
+	if ((vma->vm_end - vma->vm_start) > PAGE_SIZE)
 		return -EINVAL;
 
-	remap_pfn_range(vma, vma->vm_start, __pa(dp->data) >> PAGE_SHIFT,
-						dp->size, vma->vm_page_prot);
+	remap_pfn_range(vma, vma->vm_start,
+			__pa(PDE_DATA(file_inode(file))) >> PAGE_SHIFT,
+			PAGE_SIZE, vma->vm_page_prot);
 	return 0;
 }
 
diff --git a/arch/powerpc/kernel/sys_ppc32.c b/arch/powerpc/kernel/sys_ppc32.c
index d0bafc0..cd6e19d 100644
--- a/arch/powerpc/kernel/sys_ppc32.c
+++ b/arch/powerpc/kernel/sys_ppc32.c
@@ -61,91 +61,6 @@ asmlinkage long ppc32_select(u32 n, compat_ulong_t __user *inp,
 	return compat_sys_select((int)n, inp, outp, exp, compat_ptr(tvp_x));
 }
 
-#ifdef CONFIG_SYSVIPC
-long compat_sys_ipc(u32 call, u32 first, u32 second, u32 third, compat_uptr_t ptr,
-	       u32 fifth)
-{
-	int version;
-
-	version = call >> 16; /* hack for backward compatibility */
-	call &= 0xffff;
-
-	switch (call) {
-
-	case SEMTIMEDOP:
-		if (fifth)
-			/* sign extend semid */
-			return compat_sys_semtimedop((int)first,
-						     compat_ptr(ptr), second,
-						     compat_ptr(fifth));
-		/* else fall through for normal semop() */
-	case SEMOP:
-		/* struct sembuf is the same on 32 and 64bit :)) */
-		/* sign extend semid */
-		return sys_semtimedop((int)first, compat_ptr(ptr), second,
-				      NULL);
-	case SEMGET:
-		/* sign extend key, nsems */
-		return sys_semget((int)first, (int)second, third);
-	case SEMCTL:
-		/* sign extend semid, semnum */
-		return compat_sys_semctl((int)first, (int)second, third,
-					 compat_ptr(ptr));
-
-	case MSGSND:
-		/* sign extend msqid */
-		return compat_sys_msgsnd((int)first, (int)second, third,
-					 compat_ptr(ptr));
-	case MSGRCV:
-		/* sign extend msqid, msgtyp */
-		return compat_sys_msgrcv((int)first, second, (int)fifth,
-					 third, version, compat_ptr(ptr));
-	case MSGGET:
-		/* sign extend key */
-		return sys_msgget((int)first, second);
-	case MSGCTL:
-		/* sign extend msqid */
-		return compat_sys_msgctl((int)first, second, compat_ptr(ptr));
-
-	case SHMAT:
-		/* sign extend shmid */
-		return compat_sys_shmat((int)first, second, third, version,
-					compat_ptr(ptr));
-	case SHMDT:
-		return sys_shmdt(compat_ptr(ptr));
-	case SHMGET:
-		/* sign extend key_t */
-		return sys_shmget((int)first, second, third);
-	case SHMCTL:
-		/* sign extend shmid */
-		return compat_sys_shmctl((int)first, second, compat_ptr(ptr));
-
-	default:
-		return -ENOSYS;
-	}
-
-	return -ENOSYS;
-}
-#endif
-
-/* Note: it is necessary to treat out_fd and in_fd as unsigned ints, 
- * with the corresponding cast to a signed int to insure that the 
- * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
- * and the register representation of a signed int (msr in 64-bit mode) is performed.
- */
-asmlinkage long compat_sys_sendfile_wrapper(u32 out_fd, u32 in_fd,
-					    compat_off_t __user *offset, u32 count)
-{
-	return compat_sys_sendfile((int)out_fd, (int)in_fd, offset, count);
-}
-
-asmlinkage long compat_sys_sendfile64_wrapper(u32 out_fd, u32 in_fd,
-					      compat_loff_t __user *offset, u32 count)
-{
-	return sys_sendfile((int)out_fd, (int)in_fd,
-			    (off_t __user *)offset, count);
-}
-
 unsigned long compat_sys_mmap2(unsigned long addr, size_t len,
 			  unsigned long prot, unsigned long flags,
 			  unsigned long fd, unsigned long pgoff)
@@ -195,13 +110,6 @@ asmlinkage int compat_sys_ftruncate64(unsigned int fd, u32 reg4, unsigned long h
 	return sys_ftruncate(fd, (high << 32) | low);
 }
 
-long ppc32_lookup_dcookie(u32 cookie_high, u32 cookie_low, char __user *buf,
-			  size_t len)
-{
-	return sys_lookup_dcookie((u64)cookie_high << 32 | cookie_low,
-				  buf, len);
-}
-
 long ppc32_fadvise64(int fd, u32 unused, u32 offset_high, u32 offset_low,
 		     size_t len, int advice)
 {
@@ -209,23 +117,6 @@ long ppc32_fadvise64(int fd, u32 unused, u32 offset_high, u32 offset_low,
 			     advice);
 }
 
-asmlinkage long compat_sys_add_key(const char __user *_type,
-			      const char __user *_description,
-			      const void __user *_payload,
-			      u32 plen,
-			      u32 ringid)
-{
-	return sys_add_key(_type, _description, _payload, plen, ringid);
-}
-
-asmlinkage long compat_sys_request_key(const char __user *_type,
-				  const char __user *_description,
-				  const char __user *_callout_info,
-				  u32 destringid)
-{
-	return sys_request_key(_type, _description, _callout_info, destringid);
-}
-
 asmlinkage long compat_sys_sync_file_range2(int fd, unsigned int flags,
 				   unsigned offset_hi, unsigned offset_lo,
 				   unsigned nbytes_hi, unsigned nbytes_lo)
diff --git a/arch/powerpc/kernel/udbg.c b/arch/powerpc/kernel/udbg.c
index f974849..13b8670 100644
--- a/arch/powerpc/kernel/udbg.c
+++ b/arch/powerpc/kernel/udbg.c
@@ -156,15 +156,13 @@ static struct console udbg_console = {
 	.index	= 0,
 };
 
-static int early_console_initialized;
-
 /*
  * Called by setup_system after ppc_md->probe and ppc_md->early_init.
  * Call it again after setting udbg_putc in ppc_md->setup_arch.
  */
 void __init register_early_udbg_console(void)
 {
-	if (early_console_initialized)
+	if (early_console)
 		return;
 
 	if (!udbg_putc)
@@ -174,7 +172,7 @@ void __init register_early_udbg_console(void)
 		printk(KERN_INFO "early console immortal !\n");
 		udbg_console.flags &= ~CON_BOOT;
 	}
-	early_console_initialized = 1;
+	early_console = &udbg_console;
 	register_console(&udbg_console);
 }
 
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
index a4b6452..6548445 100644
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -160,8 +160,7 @@ void kvmppc_core_queue_external(struct kvm_vcpu *vcpu,
 	kvmppc_book3s_queue_irqprio(vcpu, vec);
 }
 
-void kvmppc_core_dequeue_external(struct kvm_vcpu *vcpu,
-                                  struct kvm_interrupt *irq)
+void kvmppc_core_dequeue_external(struct kvm_vcpu *vcpu)
 {
 	kvmppc_book3s_dequeue_irqprio(vcpu, BOOK3S_INTERRUPT_EXTERNAL);
 	kvmppc_book3s_dequeue_irqprio(vcpu, BOOK3S_INTERRUPT_EXTERNAL_LEVEL);
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index 80dcc53..1e521ba 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -1639,12 +1639,12 @@ int kvmppc_core_prepare_memory_region(struct kvm *kvm,
 
 void kvmppc_core_commit_memory_region(struct kvm *kvm,
 				      struct kvm_userspace_memory_region *mem,
-				      struct kvm_memory_slot old)
+				      const struct kvm_memory_slot *old)
 {
 	unsigned long npages = mem->memory_size >> PAGE_SHIFT;
 	struct kvm_memory_slot *memslot;
 
-	if (npages && old.npages) {
+	if (npages && old->npages) {
 		/*
 		 * If modifying a memslot, reset all the rmap dirty bits.
 		 * If this is a new memslot, we don't need to do anything
diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c
index 5e93438..da55efe 100644
--- a/arch/powerpc/kvm/book3s_pr.c
+++ b/arch/powerpc/kvm/book3s_pr.c
@@ -1039,7 +1039,7 @@ struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id)
 	if (!vcpu_book3s)
 		goto out;
 
-	vcpu_book3s->shadow_vcpu = (struct kvmppc_book3s_shadow_vcpu *)
+	vcpu_book3s->shadow_vcpu =
 		kzalloc(sizeof(*vcpu_book3s->shadow_vcpu), GFP_KERNEL);
 	if (!vcpu_book3s->shadow_vcpu)
 		goto free_vcpu;
@@ -1283,7 +1283,7 @@ int kvmppc_core_prepare_memory_region(struct kvm *kvm,
 
 void kvmppc_core_commit_memory_region(struct kvm *kvm,
 				struct kvm_userspace_memory_region *mem,
-				struct kvm_memory_slot old)
+				const struct kvm_memory_slot *old)
 {
 }
 
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index 020923e..58057d6 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -222,8 +222,7 @@ void kvmppc_core_queue_external(struct kvm_vcpu *vcpu,
 	kvmppc_booke_queue_irqprio(vcpu, prio);
 }
 
-void kvmppc_core_dequeue_external(struct kvm_vcpu *vcpu,
-                                  struct kvm_interrupt *irq)
+void kvmppc_core_dequeue_external(struct kvm_vcpu *vcpu)
 {
 	clear_bit(BOOKE_IRQPRIO_EXTERNAL, &vcpu->arch.pending_exceptions);
 	clear_bit(BOOKE_IRQPRIO_EXTERNAL_LEVEL, &vcpu->arch.pending_exceptions);
@@ -1148,6 +1147,18 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
 	return r;
 }
 
+static void kvmppc_set_tsr(struct kvm_vcpu *vcpu, u32 new_tsr)
+{
+	u32 old_tsr = vcpu->arch.tsr;
+
+	vcpu->arch.tsr = new_tsr;
+
+	if ((old_tsr ^ vcpu->arch.tsr) & (TSR_ENW | TSR_WIS))
+		arm_next_watchdog(vcpu);
+
+	update_timer_ints(vcpu);
+}
+
 /* Initial guest state: 16MB mapping 0 -> 0, PC = 0, MSR = 0, R1 = 16MB */
 int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
 {
@@ -1287,16 +1298,8 @@ static int set_sregs_base(struct kvm_vcpu *vcpu,
 		kvmppc_emulate_dec(vcpu);
 	}
 
-	if (sregs->u.e.update_special & KVM_SREGS_E_UPDATE_TSR) {
-		u32 old_tsr = vcpu->arch.tsr;
-
-		vcpu->arch.tsr = sregs->u.e.tsr;
-
-		if ((old_tsr ^ vcpu->arch.tsr) & (TSR_ENW | TSR_WIS))
-			arm_next_watchdog(vcpu);
-
-		update_timer_ints(vcpu);
-	}
+	if (sregs->u.e.update_special & KVM_SREGS_E_UPDATE_TSR)
+		kvmppc_set_tsr(vcpu, sregs->u.e.tsr);
 
 	return 0;
 }
@@ -1438,6 +1441,12 @@ int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
 		r = put_user(vcpu->arch.epcr, (u32 __user *)(long)reg->addr);
 		break;
 #endif
+	case KVM_REG_PPC_TCR:
+		r = put_user(vcpu->arch.tcr, (u32 __user *)(long)reg->addr);
+		break;
+	case KVM_REG_PPC_TSR:
+		r = put_user(vcpu->arch.tsr, (u32 __user *)(long)reg->addr);
+		break;
 	default:
 		break;
 	}
@@ -1481,6 +1490,30 @@ int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
 		break;
 	}
 #endif
+	case KVM_REG_PPC_OR_TSR: {
+		u32 tsr_bits;
+		r = get_user(tsr_bits, (u32 __user *)(long)reg->addr);
+		kvmppc_set_tsr_bits(vcpu, tsr_bits);
+		break;
+	}
+	case KVM_REG_PPC_CLEAR_TSR: {
+		u32 tsr_bits;
+		r = get_user(tsr_bits, (u32 __user *)(long)reg->addr);
+		kvmppc_clr_tsr_bits(vcpu, tsr_bits);
+		break;
+	}
+	case KVM_REG_PPC_TSR: {
+		u32 tsr;
+		r = get_user(tsr, (u32 __user *)(long)reg->addr);
+		kvmppc_set_tsr(vcpu, tsr);
+		break;
+	}
+	case KVM_REG_PPC_TCR: {
+		u32 tcr;
+		r = get_user(tcr, (u32 __user *)(long)reg->addr);
+		kvmppc_set_tcr(vcpu, tcr);
+		break;
+	}
 	default:
 		break;
 	}
@@ -1531,7 +1564,7 @@ int kvmppc_core_prepare_memory_region(struct kvm *kvm,
 
 void kvmppc_core_commit_memory_region(struct kvm *kvm,
 				struct kvm_userspace_memory_region *mem,
-				struct kvm_memory_slot old)
+				const struct kvm_memory_slot *old)
 {
 }
 
diff --git a/arch/powerpc/kvm/booke_interrupts.S b/arch/powerpc/kvm/booke_interrupts.S
index f4bb55c..2c6deb5ef 100644
--- a/arch/powerpc/kvm/booke_interrupts.S
+++ b/arch/powerpc/kvm/booke_interrupts.S
@@ -54,8 +54,7 @@
                        (1<<BOOKE_INTERRUPT_DTLB_MISS) | \
                        (1<<BOOKE_INTERRUPT_ALIGNMENT))
 
-.macro KVM_HANDLER ivor_nr scratch srr0
-_GLOBAL(kvmppc_handler_\ivor_nr)
+.macro __KVM_HANDLER ivor_nr scratch srr0
 	/* Get pointer to vcpu and record exit number. */
 	mtspr	\scratch , r4
 	mfspr   r4, SPRN_SPRG_THREAD
@@ -76,6 +75,43 @@ _GLOBAL(kvmppc_handler_\ivor_nr)
 	bctr
 .endm
 
+.macro KVM_HANDLER ivor_nr scratch srr0
+_GLOBAL(kvmppc_handler_\ivor_nr)
+	__KVM_HANDLER \ivor_nr \scratch \srr0
+.endm
+
+.macro KVM_DBG_HANDLER ivor_nr scratch srr0
+_GLOBAL(kvmppc_handler_\ivor_nr)
+	mtspr   \scratch, r4
+	mfspr	r4, SPRN_SPRG_THREAD
+	lwz	r4, THREAD_KVM_VCPU(r4)
+	stw	r3, VCPU_CRIT_SAVE(r4)
+	mfcr	r3
+	mfspr	r4, SPRN_CSRR1
+	andi.	r4, r4, MSR_PR
+	bne	1f
+	/* debug interrupt happened in enter/exit path */
+	mfspr   r4, SPRN_CSRR1
+	rlwinm  r4, r4, 0, ~MSR_DE
+	mtspr   SPRN_CSRR1, r4
+	lis	r4, 0xffff
+	ori	r4, r4, 0xffff
+	mtspr	SPRN_DBSR, r4
+	mfspr	r4, SPRN_SPRG_THREAD
+	lwz	r4, THREAD_KVM_VCPU(r4)
+	mtcr	r3
+	lwz     r3, VCPU_CRIT_SAVE(r4)
+	mfspr   r4, \scratch
+	rfci
+1:	/* debug interrupt happened in guest */
+	mtcr	r3
+	mfspr	r4, SPRN_SPRG_THREAD
+	lwz	r4, THREAD_KVM_VCPU(r4)
+	lwz     r3, VCPU_CRIT_SAVE(r4)
+	mfspr   r4, \scratch
+	__KVM_HANDLER \ivor_nr \scratch \srr0
+.endm
+
 .macro KVM_HANDLER_ADDR ivor_nr
 	.long	kvmppc_handler_\ivor_nr
 .endm
@@ -100,7 +136,7 @@ KVM_HANDLER BOOKE_INTERRUPT_FIT SPRN_SPRG_RSCRATCH0 SPRN_SRR0
 KVM_HANDLER BOOKE_INTERRUPT_WATCHDOG SPRN_SPRG_RSCRATCH_CRIT SPRN_CSRR0
 KVM_HANDLER BOOKE_INTERRUPT_DTLB_MISS SPRN_SPRG_RSCRATCH0 SPRN_SRR0
 KVM_HANDLER BOOKE_INTERRUPT_ITLB_MISS SPRN_SPRG_RSCRATCH0 SPRN_SRR0
-KVM_HANDLER BOOKE_INTERRUPT_DEBUG SPRN_SPRG_RSCRATCH_CRIT SPRN_CSRR0
+KVM_DBG_HANDLER BOOKE_INTERRUPT_DEBUG SPRN_SPRG_RSCRATCH_CRIT SPRN_CSRR0
 KVM_HANDLER BOOKE_INTERRUPT_SPE_UNAVAIL SPRN_SPRG_RSCRATCH0 SPRN_SRR0
 KVM_HANDLER BOOKE_INTERRUPT_SPE_FP_DATA SPRN_SPRG_RSCRATCH0 SPRN_SRR0
 KVM_HANDLER BOOKE_INTERRUPT_SPE_FP_ROUND SPRN_SPRG_RSCRATCH0 SPRN_SRR0
diff --git a/arch/powerpc/kvm/e500.h b/arch/powerpc/kvm/e500.h
index 41cefd4..33db48a 100644
--- a/arch/powerpc/kvm/e500.h
+++ b/arch/powerpc/kvm/e500.h
@@ -26,17 +26,20 @@
 #define E500_PID_NUM   3
 #define E500_TLB_NUM   2
 
-#define E500_TLB_VALID 1
-#define E500_TLB_BITMAP 2
+/* entry is mapped somewhere in host TLB */
+#define E500_TLB_VALID		(1 << 0)
+/* TLB1 entry is mapped by host TLB1, tracked by bitmaps */
+#define E500_TLB_BITMAP		(1 << 1)
+/* TLB1 entry is mapped by host TLB0 */
 #define E500_TLB_TLB0		(1 << 2)
 
 struct tlbe_ref {
-	pfn_t pfn;
-	unsigned int flags; /* E500_TLB_* */
+	pfn_t pfn;		/* valid only for TLB0, except briefly */
+	unsigned int flags;	/* E500_TLB_* */
 };
 
 struct tlbe_priv {
-	struct tlbe_ref ref; /* TLB0 only -- TLB1 uses tlb_refs */
+	struct tlbe_ref ref;
 };
 
 #ifdef CONFIG_KVM_E500V2
@@ -63,17 +66,6 @@ struct kvmppc_vcpu_e500 {
 
 	unsigned int gtlb_nv[E500_TLB_NUM];
 
-	/*
-	 * information associated with each host TLB entry --
-	 * TLB1 only for now.  If/when guest TLB1 entries can be
-	 * mapped with host TLB0, this will be used for that too.
-	 *
-	 * We don't want to use this for guest TLB0 because then we'd
-	 * have the overhead of doing the translation again even if
-	 * the entry is still in the guest TLB (e.g. we swapped out
-	 * and back, and our host TLB entries got evicted).
-	 */
-	struct tlbe_ref *tlb_refs[E500_TLB_NUM];
 	unsigned int host_tlb1_nv;
 
 	u32 svr;
diff --git a/arch/powerpc/kvm/e500_mmu_host.c b/arch/powerpc/kvm/e500_mmu_host.c
index a222edf..1c6a9d72 100644
--- a/arch/powerpc/kvm/e500_mmu_host.c
+++ b/arch/powerpc/kvm/e500_mmu_host.c
@@ -193,8 +193,11 @@ void inval_gtlbe_on_host(struct kvmppc_vcpu_e500 *vcpu_e500, int tlbsel,
 	struct tlbe_ref *ref = &vcpu_e500->gtlb_priv[tlbsel][esel].ref;
 
 	/* Don't bother with unmapped entries */
-	if (!(ref->flags & E500_TLB_VALID))
-		return;
+	if (!(ref->flags & E500_TLB_VALID)) {
+		WARN(ref->flags & (E500_TLB_BITMAP | E500_TLB_TLB0),
+		     "%s: flags %x\n", __func__, ref->flags);
+		WARN_ON(tlbsel == 1 && vcpu_e500->g2h_tlb1_map[esel]);
+	}
 
 	if (tlbsel == 1 && ref->flags & E500_TLB_BITMAP) {
 		u64 tmp = vcpu_e500->g2h_tlb1_map[esel];
@@ -248,7 +251,7 @@ static inline void kvmppc_e500_ref_setup(struct tlbe_ref *ref,
 					 pfn_t pfn)
 {
 	ref->pfn = pfn;
-	ref->flags = E500_TLB_VALID;
+	ref->flags |= E500_TLB_VALID;
 
 	if (tlbe_is_writable(gtlbe))
 		kvm_set_pfn_dirty(pfn);
@@ -257,6 +260,7 @@ static inline void kvmppc_e500_ref_setup(struct tlbe_ref *ref,
 static inline void kvmppc_e500_ref_release(struct tlbe_ref *ref)
 {
 	if (ref->flags & E500_TLB_VALID) {
+		/* FIXME: don't log bogus pfn for TLB1 */
 		trace_kvm_booke206_ref_release(ref->pfn, ref->flags);
 		ref->flags = 0;
 	}
@@ -274,36 +278,23 @@ static void clear_tlb1_bitmap(struct kvmppc_vcpu_e500 *vcpu_e500)
 
 static void clear_tlb_privs(struct kvmppc_vcpu_e500 *vcpu_e500)
 {
-	int tlbsel = 0;
-	int i;
-
-	for (i = 0; i < vcpu_e500->gtlb_params[tlbsel].entries; i++) {
-		struct tlbe_ref *ref =
-			&vcpu_e500->gtlb_priv[tlbsel][i].ref;
-		kvmppc_e500_ref_release(ref);
-	}
-}
-
-static void clear_tlb_refs(struct kvmppc_vcpu_e500 *vcpu_e500)
-{
-	int stlbsel = 1;
+	int tlbsel;
 	int i;
 
-	kvmppc_e500_tlbil_all(vcpu_e500);
-
-	for (i = 0; i < host_tlb_params[stlbsel].entries; i++) {
-		struct tlbe_ref *ref =
-			&vcpu_e500->tlb_refs[stlbsel][i];
-		kvmppc_e500_ref_release(ref);
+	for (tlbsel = 0; tlbsel <= 1; tlbsel++) {
+		for (i = 0; i < vcpu_e500->gtlb_params[tlbsel].entries; i++) {
+			struct tlbe_ref *ref =
+				&vcpu_e500->gtlb_priv[tlbsel][i].ref;
+			kvmppc_e500_ref_release(ref);
+		}
 	}
-
-	clear_tlb_privs(vcpu_e500);
 }
 
 void kvmppc_core_flush_tlb(struct kvm_vcpu *vcpu)
 {
 	struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
-	clear_tlb_refs(vcpu_e500);
+	kvmppc_e500_tlbil_all(vcpu_e500);
+	clear_tlb_privs(vcpu_e500);
 	clear_tlb1_bitmap(vcpu_e500);
 }
 
@@ -458,8 +449,6 @@ static inline int kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
 		gvaddr &= ~((tsize_pages << PAGE_SHIFT) - 1);
 	}
 
-	/* Drop old ref and setup new one. */
-	kvmppc_e500_ref_release(ref);
 	kvmppc_e500_ref_setup(ref, gtlbe, pfn);
 
 	kvmppc_e500_setup_stlbe(&vcpu_e500->vcpu, gtlbe, tsize,
@@ -507,14 +496,15 @@ static int kvmppc_e500_tlb1_map_tlb1(struct kvmppc_vcpu_e500 *vcpu_e500,
 	if (unlikely(vcpu_e500->host_tlb1_nv >= tlb1_max_shadow_size()))
 		vcpu_e500->host_tlb1_nv = 0;
 
-	vcpu_e500->tlb_refs[1][sesel] = *ref;
-	vcpu_e500->g2h_tlb1_map[esel] |= (u64)1 << sesel;
-	vcpu_e500->gtlb_priv[1][esel].ref.flags |= E500_TLB_BITMAP;
 	if (vcpu_e500->h2g_tlb1_rmap[sesel]) {
-		unsigned int idx = vcpu_e500->h2g_tlb1_rmap[sesel];
+		unsigned int idx = vcpu_e500->h2g_tlb1_rmap[sesel] - 1;
 		vcpu_e500->g2h_tlb1_map[idx] &= ~(1ULL << sesel);
 	}
-	vcpu_e500->h2g_tlb1_rmap[sesel] = esel;
+
+	vcpu_e500->gtlb_priv[1][esel].ref.flags |= E500_TLB_BITMAP;
+	vcpu_e500->g2h_tlb1_map[esel] |= (u64)1 << sesel;
+	vcpu_e500->h2g_tlb1_rmap[sesel] = esel + 1;
+	WARN_ON(!(ref->flags & E500_TLB_VALID));
 
 	return sesel;
 }
@@ -526,13 +516,12 @@ static int kvmppc_e500_tlb1_map(struct kvmppc_vcpu_e500 *vcpu_e500,
 		u64 gvaddr, gfn_t gfn, struct kvm_book3e_206_tlb_entry *gtlbe,
 		struct kvm_book3e_206_tlb_entry *stlbe, int esel)
 {
-	struct tlbe_ref ref;
+	struct tlbe_ref *ref = &vcpu_e500->gtlb_priv[1][esel].ref;
 	int sesel;
 	int r;
 
-	ref.flags = 0;
 	r = kvmppc_e500_shadow_map(vcpu_e500, gvaddr, gfn, gtlbe, 1, stlbe,
-				   &ref);
+				   ref);
 	if (r)
 		return r;
 
@@ -544,7 +533,7 @@ static int kvmppc_e500_tlb1_map(struct kvmppc_vcpu_e500 *vcpu_e500,
 	}
 
 	/* Otherwise map into TLB1 */
-	sesel = kvmppc_e500_tlb1_map_tlb1(vcpu_e500, &ref, esel);
+	sesel = kvmppc_e500_tlb1_map_tlb1(vcpu_e500, ref, esel);
 	write_stlbe(vcpu_e500, gtlbe, stlbe, 1, sesel);
 
 	return 0;
@@ -565,7 +554,7 @@ void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 eaddr, gpa_t gpaddr,
 	case 0:
 		priv = &vcpu_e500->gtlb_priv[tlbsel][esel];
 
-		/* Triggers after clear_tlb_refs or on initial mapping */
+		/* Triggers after clear_tlb_privs or on initial mapping */
 		if (!(priv->ref.flags & E500_TLB_VALID)) {
 			kvmppc_e500_tlb0_map(vcpu_e500, esel, &stlbe);
 		} else {
@@ -665,35 +654,16 @@ int e500_mmu_host_init(struct kvmppc_vcpu_e500 *vcpu_e500)
 		host_tlb_params[0].entries / host_tlb_params[0].ways;
 	host_tlb_params[1].sets = 1;
 
-	vcpu_e500->tlb_refs[0] =
-		kzalloc(sizeof(struct tlbe_ref) * host_tlb_params[0].entries,
-			GFP_KERNEL);
-	if (!vcpu_e500->tlb_refs[0])
-		goto err;
-
-	vcpu_e500->tlb_refs[1] =
-		kzalloc(sizeof(struct tlbe_ref) * host_tlb_params[1].entries,
-			GFP_KERNEL);
-	if (!vcpu_e500->tlb_refs[1])
-		goto err;
-
 	vcpu_e500->h2g_tlb1_rmap = kzalloc(sizeof(unsigned int) *
 					   host_tlb_params[1].entries,
 					   GFP_KERNEL);
 	if (!vcpu_e500->h2g_tlb1_rmap)
-		goto err;
+		return -EINVAL;
 
 	return 0;
-
-err:
-	kfree(vcpu_e500->tlb_refs[0]);
-	kfree(vcpu_e500->tlb_refs[1]);
-	return -EINVAL;
 }
 
 void e500_mmu_host_uninit(struct kvmppc_vcpu_e500 *vcpu_e500)
 {
 	kfree(vcpu_e500->h2g_tlb1_rmap);
-	kfree(vcpu_e500->tlb_refs[0]);
-	kfree(vcpu_e500->tlb_refs[1]);
 }
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index 934413c..16b4595 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -411,18 +411,17 @@ int kvm_arch_create_memslot(struct kvm_memory_slot *slot, unsigned long npages)
 }
 
 int kvm_arch_prepare_memory_region(struct kvm *kvm,
-                                   struct kvm_memory_slot *memslot,
-                                   struct kvm_memory_slot old,
-                                   struct kvm_userspace_memory_region *mem,
-                                   bool user_alloc)
+				   struct kvm_memory_slot *memslot,
+				   struct kvm_userspace_memory_region *mem,
+				   enum kvm_mr_change change)
 {
 	return kvmppc_core_prepare_memory_region(kvm, memslot, mem);
 }
 
 void kvm_arch_commit_memory_region(struct kvm *kvm,
-               struct kvm_userspace_memory_region *mem,
-               struct kvm_memory_slot old,
-               bool user_alloc)
+				   struct kvm_userspace_memory_region *mem,
+				   const struct kvm_memory_slot *old,
+				   enum kvm_mr_change change)
 {
 	kvmppc_core_commit_memory_region(kvm, mem, old);
 }
@@ -740,7 +739,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
 int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu, struct kvm_interrupt *irq)
 {
 	if (irq->irq == KVM_INTERRUPT_UNSET) {
-		kvmppc_core_dequeue_external(vcpu, irq);
+		kvmppc_core_dequeue_external(vcpu);
 		return 0;
 	}
 
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c
index 1a6de0a..5dc52d8 100644
--- a/arch/powerpc/mm/hugetlbpage.c
+++ b/arch/powerpc/mm/hugetlbpage.c
@@ -742,7 +742,7 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
 	struct hstate *hstate = hstate_file(file);
 	int mmu_psize = shift_to_mmu_psize(huge_page_shift(hstate));
 
-	return slice_get_unmapped_area(addr, len, flags, mmu_psize, 1, 0);
+	return slice_get_unmapped_area(addr, len, flags, mmu_psize, 1);
 }
 #endif
 
diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c
index 7e2246f..5a535b7 100644
--- a/arch/powerpc/mm/init_64.c
+++ b/arch/powerpc/mm/init_64.c
@@ -263,19 +263,14 @@ static __meminit void vmemmap_list_populate(unsigned long phys,
 	vmemmap_list = vmem_back;
 }
 
-int __meminit vmemmap_populate(struct page *start_page,
-			       unsigned long nr_pages, int node)
+int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node)
 {
-	unsigned long start = (unsigned long)start_page;
-	unsigned long end = (unsigned long)(start_page + nr_pages);
 	unsigned long page_size = 1 << mmu_psize_defs[mmu_vmemmap_psize].shift;
 
 	/* Align to the page size of the linear mapping. */
 	start = _ALIGN_DOWN(start, page_size);
 
-	pr_debug("vmemmap_populate page %p, %ld pages, node %d\n",
-		 start_page, nr_pages, node);
-	pr_debug(" -> map %lx..%lx\n", start, end);
+	pr_debug("vmemmap_populate %lx..%lx, node %d\n", start, end, node);
 
 	for (; start < end; start += page_size) {
 		void *p;
@@ -298,7 +293,7 @@ int __meminit vmemmap_populate(struct page *start_page,
 	return 0;
 }
 
-void vmemmap_free(struct page *memmap, unsigned long nr_pages)
+void vmemmap_free(unsigned long start, unsigned long end)
 {
 }
 
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
index f1f7409..cd76c45 100644
--- a/arch/powerpc/mm/mem.c
+++ b/arch/powerpc/mm/mem.c
@@ -352,13 +352,9 @@ void __init mem_init(void)
 			struct page *page = pfn_to_page(pfn);
 			if (memblock_is_reserved(paddr))
 				continue;
-			ClearPageReserved(page);
-			init_page_count(page);
-			__free_page(page);
-			totalhigh_pages++;
+			free_highmem_page(page);
 			reservedpages--;
 		}
-		totalram_pages += totalhigh_pages;
 		printk(KERN_DEBUG "High memory: %luk\n",
 		       totalhigh_pages << (PAGE_SHIFT-10));
 	}
@@ -405,39 +401,14 @@ void __init mem_init(void)
 
 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);
+	free_initmem_default(POISON_FREE_INITMEM);
 }
 
 #ifdef CONFIG_BLK_DEV_INITRD
 void __init free_initrd_mem(unsigned long start, unsigned long end)
 {
-	if (start >= end)
-		return;
-
-	start = _ALIGN_DOWN(start, PAGE_SIZE);
-	end = _ALIGN_UP(end, PAGE_SIZE);
-	pr_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++;
-	}
+	free_reserved_area(start, end, 0, "initrd");
 }
 #endif
 
diff --git a/arch/powerpc/mm/mmap_64.c b/arch/powerpc/mm/mmap_64.c
index 67a42ed..cb8bdbe 100644
--- a/arch/powerpc/mm/mmap_64.c
+++ b/arch/powerpc/mm/mmap_64.c
@@ -92,10 +92,8 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
 	if (mmap_is_legacy()) {
 		mm->mmap_base = TASK_UNMAPPED_BASE;
 		mm->get_unmapped_area = arch_get_unmapped_area;
-		mm->unmap_area = arch_unmap_area;
 	} else {
 		mm->mmap_base = mmap_base();
 		mm->get_unmapped_area = arch_get_unmapped_area_topdown;
-		mm->unmap_area = arch_unmap_area_topdown;
 	}
 }
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index bba87ca..b8020dc 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -62,14 +62,11 @@ static int distance_lookup_table[MAX_NUMNODES][MAX_DISTANCE_REF_POINTS];
  */
 static void __init setup_node_to_cpumask_map(void)
 {
-	unsigned int node, num = 0;
+	unsigned int node;
 
 	/* setup nr_node_ids if not done yet */
-	if (nr_node_ids == MAX_NUMNODES) {
-		for_each_node_mask(node, node_possible_map)
-			num = node;
-		nr_node_ids = num + 1;
-	}
+	if (nr_node_ids == MAX_NUMNODES)
+		setup_nr_node_ids();
 
 	/* allocate the map */
 	for (node = 0; node < nr_node_ids; node++)
diff --git a/arch/powerpc/mm/slice.c b/arch/powerpc/mm/slice.c
index cf9dada..3e99c14 100644
--- a/arch/powerpc/mm/slice.c
+++ b/arch/powerpc/mm/slice.c
@@ -237,134 +237,112 @@ static void slice_convert(struct mm_struct *mm, struct slice_mask mask, int psiz
 #endif
 }
 
+/*
+ * Compute which slice addr is part of;
+ * set *boundary_addr to the start or end boundary of that slice
+ * (depending on 'end' parameter);
+ * return boolean indicating if the slice is marked as available in the
+ * 'available' slice_mark.
+ */
+static bool slice_scan_available(unsigned long addr,
+				 struct slice_mask available,
+				 int end,
+				 unsigned long *boundary_addr)
+{
+	unsigned long slice;
+	if (addr < SLICE_LOW_TOP) {
+		slice = GET_LOW_SLICE_INDEX(addr);
+		*boundary_addr = (slice + end) << SLICE_LOW_SHIFT;
+		return !!(available.low_slices & (1u << slice));
+	} else {
+		slice = GET_HIGH_SLICE_INDEX(addr);
+		*boundary_addr = (slice + end) ?
+			((slice + end) << SLICE_HIGH_SHIFT) : SLICE_LOW_TOP;
+		return !!(available.high_slices & (1u << slice));
+	}
+}
+
 static unsigned long slice_find_area_bottomup(struct mm_struct *mm,
 					      unsigned long len,
 					      struct slice_mask available,
-					      int psize, int use_cache)
+					      int psize)
 {
-	struct vm_area_struct *vma;
-	unsigned long start_addr, addr;
-	struct slice_mask mask;
 	int pshift = max_t(int, mmu_psize_defs[psize].shift, PAGE_SHIFT);
-
-	if (use_cache) {
-		if (len <= mm->cached_hole_size) {
-			start_addr = addr = TASK_UNMAPPED_BASE;
-			mm->cached_hole_size = 0;
-		} else
-			start_addr = addr = mm->free_area_cache;
-	} else
-		start_addr = addr = TASK_UNMAPPED_BASE;
-
-full_search:
-	for (;;) {
-		addr = _ALIGN_UP(addr, 1ul << pshift);
-		if ((TASK_SIZE - len) < addr)
-			break;
-		vma = find_vma(mm, addr);
-		BUG_ON(vma && (addr >= vma->vm_end));
-
-		mask = slice_range_to_mask(addr, len);
-		if (!slice_check_fit(mask, available)) {
-			if (addr < SLICE_LOW_TOP)
-				addr = _ALIGN_UP(addr + 1,  1ul << SLICE_LOW_SHIFT);
-			else
-				addr = _ALIGN_UP(addr + 1,  1ul << SLICE_HIGH_SHIFT);
+	unsigned long addr, found, next_end;
+	struct vm_unmapped_area_info info;
+
+	info.flags = 0;
+	info.length = len;
+	info.align_mask = PAGE_MASK & ((1ul << pshift) - 1);
+	info.align_offset = 0;
+
+	addr = TASK_UNMAPPED_BASE;
+	while (addr < TASK_SIZE) {
+		info.low_limit = addr;
+		if (!slice_scan_available(addr, available, 1, &addr))
 			continue;
+
+ next_slice:
+		/*
+		 * At this point [info.low_limit; addr) covers
+		 * available slices only and ends at a slice boundary.
+		 * Check if we need to reduce the range, or if we can
+		 * extend it to cover the next available slice.
+		 */
+		if (addr >= TASK_SIZE)
+			addr = TASK_SIZE;
+		else if (slice_scan_available(addr, available, 1, &next_end)) {
+			addr = next_end;
+			goto next_slice;
 		}
-		if (!vma || addr + len <= vma->vm_start) {
-			/*
-			 * Remember the place where we stopped the search:
-			 */
-			if (use_cache)
-				mm->free_area_cache = addr + len;
-			return addr;
-		}
-		if (use_cache && (addr + mm->cached_hole_size) < vma->vm_start)
-		        mm->cached_hole_size = vma->vm_start - addr;
-		addr = vma->vm_end;
-	}
+		info.high_limit = addr;
 
-	/* Make sure we didn't miss any holes */
-	if (use_cache && start_addr != TASK_UNMAPPED_BASE) {
-		start_addr = addr = TASK_UNMAPPED_BASE;
-		mm->cached_hole_size = 0;
-		goto full_search;
+		found = vm_unmapped_area(&info);
+		if (!(found & ~PAGE_MASK))
+			return found;
 	}
+
 	return -ENOMEM;
 }
 
 static unsigned long slice_find_area_topdown(struct mm_struct *mm,
 					     unsigned long len,
 					     struct slice_mask available,
-					     int psize, int use_cache)
+					     int psize)
 {
-	struct vm_area_struct *vma;
-	unsigned long addr;
-	struct slice_mask mask;
 	int pshift = max_t(int, mmu_psize_defs[psize].shift, PAGE_SHIFT);
+	unsigned long addr, found, prev;
+	struct vm_unmapped_area_info info;
 
-	/* check if free_area_cache is useful for us */
-	if (use_cache) {
-		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;
-
-		/* make sure it can fit in the remaining address space */
-		if (addr > len) {
-			addr = _ALIGN_DOWN(addr - len, 1ul << pshift);
-			mask = slice_range_to_mask(addr, len);
-			if (slice_check_fit(mask, available) &&
-			    slice_area_is_free(mm, addr, len))
-					/* remember the address as a hint for
-					 * next time
-					 */
-					return (mm->free_area_cache = addr);
-		}
-	}
+	info.flags = VM_UNMAPPED_AREA_TOPDOWN;
+	info.length = len;
+	info.align_mask = PAGE_MASK & ((1ul << pshift) - 1);
+	info.align_offset = 0;
 
 	addr = mm->mmap_base;
-	while (addr > len) {
-		/* Go down by chunk size */
-		addr = _ALIGN_DOWN(addr - len, 1ul << pshift);
-
-		/* Check for hit with different page size */
-		mask = slice_range_to_mask(addr, len);
-		if (!slice_check_fit(mask, available)) {
-			if (addr < SLICE_LOW_TOP)
-				addr = _ALIGN_DOWN(addr, 1ul << SLICE_LOW_SHIFT);
-			else if (addr < (1ul << SLICE_HIGH_SHIFT))
-				addr = SLICE_LOW_TOP;
-			else
-				addr = _ALIGN_DOWN(addr, 1ul << SLICE_HIGH_SHIFT);
+	while (addr > PAGE_SIZE) {
+		info.high_limit = addr;
+		if (!slice_scan_available(addr - 1, available, 0, &addr))
 			continue;
-		}
 
+ prev_slice:
 		/*
-		 * Lookup failure means no vma is above this address,
-		 * else if new region fits below vma->vm_start,
-		 * return with success:
+		 * At this point [addr; info.high_limit) covers
+		 * available slices only and starts at a slice boundary.
+		 * Check if we need to reduce the range, or if we can
+		 * extend it to cover the previous available slice.
 		 */
-		vma = find_vma(mm, addr);
-		if (!vma || (addr + len) <= vma->vm_start) {
-			/* remember the address as a hint for next time */
-			if (use_cache)
-				mm->free_area_cache = addr;
-			return addr;
+		if (addr < PAGE_SIZE)
+			addr = PAGE_SIZE;
+		else if (slice_scan_available(addr - 1, available, 0, &prev)) {
+			addr = prev;
+			goto prev_slice;
 		}
+		info.low_limit = addr;
 
-		/* remember the largest hole we saw so far */
-		if (use_cache && (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;
+		found = vm_unmapped_area(&info);
+		if (!(found & ~PAGE_MASK))
+			return found;
 	}
 
 	/*
@@ -373,28 +351,18 @@ static unsigned long slice_find_area_topdown(struct mm_struct *mm,
 	 * can happen with large stack limits and large mmap()
 	 * allocations.
 	 */
-	addr = slice_find_area_bottomup(mm, len, available, psize, 0);
-
-	/*
-	 * Restore the topdown base:
-	 */
-	if (use_cache) {
-		mm->free_area_cache = mm->mmap_base;
-		mm->cached_hole_size = ~0UL;
-	}
-
-	return addr;
+	return slice_find_area_bottomup(mm, len, available, psize);
 }
 
 
 static unsigned long slice_find_area(struct mm_struct *mm, unsigned long len,
 				     struct slice_mask mask, int psize,
-				     int topdown, int use_cache)
+				     int topdown)
 {
 	if (topdown)
-		return slice_find_area_topdown(mm, len, mask, psize, use_cache);
+		return slice_find_area_topdown(mm, len, mask, psize);
 	else
-		return slice_find_area_bottomup(mm, len, mask, psize, use_cache);
+		return slice_find_area_bottomup(mm, len, mask, psize);
 }
 
 #define or_mask(dst, src)	do {			\
@@ -415,7 +383,7 @@ static unsigned long slice_find_area(struct mm_struct *mm, unsigned long len,
 
 unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
 				      unsigned long flags, unsigned int psize,
-				      int topdown, int use_cache)
+				      int topdown)
 {
 	struct slice_mask mask = {0, 0};
 	struct slice_mask good_mask;
@@ -430,8 +398,8 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
 	BUG_ON(mm->task_size == 0);
 
 	slice_dbg("slice_get_unmapped_area(mm=%p, psize=%d...\n", mm, psize);
-	slice_dbg(" addr=%lx, len=%lx, flags=%lx, topdown=%d, use_cache=%d\n",
-		  addr, len, flags, topdown, use_cache);
+	slice_dbg(" addr=%lx, len=%lx, flags=%lx, topdown=%d\n",
+		  addr, len, flags, topdown);
 
 	if (len > mm->task_size)
 		return -ENOMEM;
@@ -503,8 +471,7 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
 		/* Now let's see if we can find something in the existing
 		 * slices for that size
 		 */
-		newaddr = slice_find_area(mm, len, good_mask, psize, topdown,
-					  use_cache);
+		newaddr = slice_find_area(mm, len, good_mask, psize, topdown);
 		if (newaddr != -ENOMEM) {
 			/* Found within the good mask, we don't have to setup,
 			 * we thus return directly
@@ -536,8 +503,7 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
 	 * anywhere in the good area.
 	 */
 	if (addr) {
-		addr = slice_find_area(mm, len, good_mask, psize, topdown,
-				       use_cache);
+		addr = slice_find_area(mm, len, good_mask, psize, topdown);
 		if (addr != -ENOMEM) {
 			slice_dbg(" found area at 0x%lx\n", addr);
 			return addr;
@@ -547,15 +513,14 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
 	/* Now let's see if we can find something in the existing slices
 	 * for that size plus free slices
 	 */
-	addr = slice_find_area(mm, len, potential_mask, psize, topdown,
-			       use_cache);
+	addr = slice_find_area(mm, len, potential_mask, psize, topdown);
 
 #ifdef CONFIG_PPC_64K_PAGES
 	if (addr == -ENOMEM && psize == MMU_PAGE_64K) {
 		/* retry the search with 4k-page slices included */
 		or_mask(potential_mask, compat_mask);
 		addr = slice_find_area(mm, len, potential_mask, psize,
-				       topdown, use_cache);
+				       topdown);
 	}
 #endif
 
@@ -586,8 +551,7 @@ unsigned long arch_get_unmapped_area(struct file *filp,
 				     unsigned long flags)
 {
 	return slice_get_unmapped_area(addr, len, flags,
-				       current->mm->context.user_psize,
-				       0, 1);
+				       current->mm->context.user_psize, 0);
 }
 
 unsigned long arch_get_unmapped_area_topdown(struct file *filp,
@@ -597,8 +561,7 @@ unsigned long arch_get_unmapped_area_topdown(struct file *filp,
 					     const unsigned long flags)
 {
 	return slice_get_unmapped_area(addr0, len, flags,
-				       current->mm->context.user_psize,
-				       1, 1);
+				       current->mm->context.user_psize, 1);
 }
 
 unsigned int get_slice_psize(struct mm_struct *mm, unsigned long addr)
diff --git a/arch/powerpc/mm/tlb_nohash.c b/arch/powerpc/mm/tlb_nohash.c
index df32a83..6888cad 100644
--- a/arch/powerpc/mm/tlb_nohash.c
+++ b/arch/powerpc/mm/tlb_nohash.c
@@ -414,9 +414,9 @@ static void setup_page_sizes(void)
 
 #ifdef CONFIG_PPC_FSL_BOOK3E
 	unsigned int mmucfg = mfspr(SPRN_MMUCFG);
+	int fsl_mmu = mmu_has_feature(MMU_FTR_TYPE_FSL_E);
 
-	if (((mmucfg & MMUCFG_MAVN) == MMUCFG_MAVN_V1) &&
-		(mmu_has_feature(MMU_FTR_TYPE_FSL_E))) {
+	if (fsl_mmu && (mmucfg & MMUCFG_MAVN) == MMUCFG_MAVN_V1) {
 		unsigned int tlb1cfg = mfspr(SPRN_TLB1CFG);
 		unsigned int min_pg, max_pg;
 
@@ -442,6 +442,20 @@ static void setup_page_sizes(void)
 
 		goto no_indirect;
 	}
+
+	if (fsl_mmu && (mmucfg & MMUCFG_MAVN) == MMUCFG_MAVN_V2) {
+		u32 tlb1ps = mfspr(SPRN_TLB1PS);
+
+		for (psize = 0; psize < MMU_PAGE_COUNT; ++psize) {
+			struct mmu_psize_def *def = &mmu_psize_defs[psize];
+
+			if (tlb1ps & (1U << (def->shift - 10))) {
+				def->flags |= MMU_PAGE_SIZE_DIRECT;
+			}
+		}
+
+		goto no_indirect;
+	}
 #endif
 
 	tlb0cfg = mfspr(SPRN_TLB0CFG);
diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
index e834f1e..c427ae3 100644
--- a/arch/powerpc/net/bpf_jit_comp.c
+++ b/arch/powerpc/net/bpf_jit_comp.c
@@ -671,16 +671,12 @@ void bpf_jit_compile(struct sk_filter *fp)
 	}
 
 	if (bpf_jit_enable > 1)
-		pr_info("flen=%d proglen=%u pass=%d image=%p\n",
-		       flen, proglen, pass, image);
+		/* Note that we output the base address of the code_base
+		 * rather than image, since opcodes are in code_base.
+		 */
+		bpf_jit_dump(flen, proglen, pass, code_base);
 
 	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;
diff --git a/arch/powerpc/platforms/40x/Kconfig b/arch/powerpc/platforms/40x/Kconfig
index a392d12..d0b46a2 100644
--- a/arch/powerpc/platforms/40x/Kconfig
+++ b/arch/powerpc/platforms/40x/Kconfig
@@ -145,7 +145,6 @@ config PPC4xx_GPIO
 	bool "PPC4xx GPIO support"
 	depends on 40x
 	select ARCH_REQUIRE_GPIOLIB
-	select GENERIC_GPIO
 	help
 	  Enable gpiolib support for ppc40x based boards
 
diff --git a/arch/powerpc/platforms/44x/Kconfig b/arch/powerpc/platforms/44x/Kconfig
index 0effe9f..50306b8 100644
--- a/arch/powerpc/platforms/44x/Kconfig
+++ b/arch/powerpc/platforms/44x/Kconfig
@@ -248,7 +248,6 @@ config PPC4xx_GPIO
 	bool "PPC4xx GPIO support"
 	depends on 44x
 	select ARCH_REQUIRE_GPIOLIB
-	select GENERIC_GPIO
 	help
 	  Enable gpiolib support for ppc440 based boards
 
diff --git a/arch/powerpc/platforms/512x/Kconfig b/arch/powerpc/platforms/512x/Kconfig
index c169998..eb46203 100644
--- a/arch/powerpc/platforms/512x/Kconfig
+++ b/arch/powerpc/platforms/512x/Kconfig
@@ -15,16 +15,16 @@ config MPC5121_ADS
 	help
 	  This option enables support for the MPC5121E ADS board.
 
-config MPC5121_GENERIC
-	bool "Generic support for simple MPC5121 based boards"
+config MPC512x_GENERIC
+	bool "Generic support for simple MPC512x based boards"
 	depends on PPC_MPC512x
 	select DEFAULT_UIMAGE
 	help
-	  This option enables support for simple MPC5121 based boards
+	  This option enables support for simple MPC512x based boards
 	  which do not need custom platform specific setup.
 
 	  Compatible boards include:  Protonic LVT base boards (ZANMCU
-	  and VICVT2).
+	  and VICVT2), Freescale MPC5125 Tower system.
 
 config PDM360NG
 	bool "ifm PDM360NG board"
diff --git a/arch/powerpc/platforms/512x/Makefile b/arch/powerpc/platforms/512x/Makefile
index 4efc1c4..72fb934 100644
--- a/arch/powerpc/platforms/512x/Makefile
+++ b/arch/powerpc/platforms/512x/Makefile
@@ -3,5 +3,5 @@
 #
 obj-y				+= clock.o mpc512x_shared.o
 obj-$(CONFIG_MPC5121_ADS)	+= mpc5121_ads.o mpc5121_ads_cpld.o
-obj-$(CONFIG_MPC5121_GENERIC)	+= mpc5121_generic.o
+obj-$(CONFIG_MPC512x_GENERIC)	+= mpc512x_generic.o
 obj-$(CONFIG_PDM360NG)		+= pdm360ng.o
diff --git a/arch/powerpc/platforms/512x/mpc5121_generic.c b/arch/powerpc/platforms/512x/mpc5121_generic.c
deleted file mode 100644
index ca1ca66..0000000
--- a/arch/powerpc/platforms/512x/mpc5121_generic.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2007,2008 Freescale Semiconductor, Inc. All rights reserved.
- *
- * Author: John Rigby, <jrigby@freescale.com>
- *
- * Description:
- * MPC5121 SoC setup
- *
- * 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.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/of_platform.h>
-
-#include <asm/machdep.h>
-#include <asm/ipic.h>
-#include <asm/prom.h>
-#include <asm/time.h>
-
-#include "mpc512x.h"
-
-/*
- * list of supported boards
- */
-static const char * const board[] __initconst = {
-	"prt,prtlvt",
-	NULL
-};
-
-/*
- * Called very early, MMU is off, device-tree isn't unflattened
- */
-static int __init mpc5121_generic_probe(void)
-{
-	return of_flat_dt_match(of_get_flat_dt_root(), board);
-}
-
-define_machine(mpc5121_generic) {
-	.name			= "MPC5121 generic",
-	.probe			= mpc5121_generic_probe,
-	.init			= mpc512x_init,
-	.init_early		= mpc512x_init_diu,
-	.setup_arch		= mpc512x_setup_diu,
-	.init_IRQ		= mpc512x_init_IRQ,
-	.get_irq		= ipic_get_irq,
-	.calibrate_decr		= generic_calibrate_decr,
-	.restart		= mpc512x_restart,
-};
diff --git a/arch/powerpc/platforms/512x/mpc512x_generic.c b/arch/powerpc/platforms/512x/mpc512x_generic.c
new file mode 100644
index 0000000..d53fa4f
--- /dev/null
+++ b/arch/powerpc/platforms/512x/mpc512x_generic.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2007,2008 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * Author: John Rigby, <jrigby@freescale.com>
+ *
+ * Description:
+ * MPC512x SoC setup
+ *
+ * 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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/of_platform.h>
+
+#include <asm/machdep.h>
+#include <asm/ipic.h>
+#include <asm/prom.h>
+#include <asm/time.h>
+
+#include "mpc512x.h"
+
+/*
+ * list of supported boards
+ */
+static const char * const board[] __initconst = {
+	"prt,prtlvt",
+	NULL
+};
+
+/*
+ * Called very early, MMU is off, device-tree isn't unflattened
+ */
+static int __init mpc512x_generic_probe(void)
+{
+	return of_flat_dt_match(of_get_flat_dt_root(), board);
+}
+
+define_machine(mpc512x_generic) {
+	.name			= "MPC512x generic",
+	.probe			= mpc512x_generic_probe,
+	.init			= mpc512x_init,
+	.init_early		= mpc512x_init_diu,
+	.setup_arch		= mpc512x_setup_diu,
+	.init_IRQ		= mpc512x_init_IRQ,
+	.get_irq		= ipic_get_irq,
+	.calibrate_decr		= generic_calibrate_decr,
+	.restart		= mpc512x_restart,
+};
diff --git a/arch/powerpc/platforms/512x/mpc512x_shared.c b/arch/powerpc/platforms/512x/mpc512x_shared.c
index d30235b..76885d5 100644
--- a/arch/powerpc/platforms/512x/mpc512x_shared.c
+++ b/arch/powerpc/platforms/512x/mpc512x_shared.c
@@ -172,12 +172,9 @@ static struct fsl_diu_shared_fb __attribute__ ((__aligned__(8))) diu_shared_fb;
 
 static inline void mpc512x_free_bootmem(struct page *page)
 {
-	__ClearPageReserved(page);
 	BUG_ON(PageTail(page));
 	BUG_ON(atomic_read(&page->_count) > 1);
-	atomic_set(&page->_count, 1);
-	__free_page(page);
-	totalram_pages++;
+	free_reserved_page(page);
 }
 
 void mpc512x_release_bootmem(void)
@@ -330,22 +327,19 @@ void __init mpc512x_init_IRQ(void)
 static struct of_device_id __initdata of_bus_ids[] = {
 	{ .compatible = "fsl,mpc5121-immr", },
 	{ .compatible = "fsl,mpc5121-localbus", },
+	{ .compatible = "fsl,mpc5121-mbx", },
+	{ .compatible = "fsl,mpc5121-nfc", },
+	{ .compatible = "fsl,mpc5121-sram", },
+	{ .compatible = "fsl,mpc5121-pci", },
+	{ .compatible = "gpio-leds", },
 	{},
 };
 
 void __init mpc512x_declare_of_platform_devices(void)
 {
-	struct device_node *np;
-
 	if (of_platform_bus_probe(NULL, of_bus_ids, NULL))
 		printk(KERN_ERR __FILE__ ": "
 			"Error while probing of_platform bus\n");
-
-	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-nfc");
-	if (np) {
-		of_platform_device_create(np, NULL, NULL);
-		of_node_put(np);
-	}
 }
 
 #define DEFAULT_FIFO_SIZE 16
diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig
index a0dcd57..6dc7ba5 100644
--- a/arch/powerpc/platforms/85xx/Kconfig
+++ b/arch/powerpc/platforms/85xx/Kconfig
@@ -203,7 +203,6 @@ config GE_IMP3A
 	select DEFAULT_UIMAGE
 	select SWIOTLB
 	select MMIO_NVRAM
-	select GENERIC_GPIO
 	select ARCH_REQUIRE_GPIOLIB
 	select GE_FPGA
 	help
@@ -305,6 +304,23 @@ config PPC_QEMU_E500
 	  unset based on the emulated CPU (or actual host CPU in the case
 	  of KVM).
 
+if PPC64
+
+config T4240_QDS
+	bool "Freescale T4240 QDS"
+	select DEFAULT_UIMAGE
+	select E500
+	select PPC_E500MC
+	select PHYS_64BIT
+	select SWIOTLB
+	select ARCH_REQUIRE_GPIOLIB
+	select GPIO_MPC8XXX
+	select HAS_RAPIDIO
+	select PPC_EPAPR_HV_PIC
+	help
+	  This option enables support for the T4240 QDS board
+
+endif
 endif # FSL_SOC_BOOKE
 
 config TQM85xx
diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile
index 07d0dbb..712e233 100644
--- a/arch/powerpc/platforms/85xx/Makefile
+++ b/arch/powerpc/platforms/85xx/Makefile
@@ -22,6 +22,7 @@ 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
 obj-$(CONFIG_P5040_DS)    += p5040_ds.o corenet_ds.o
+obj-$(CONFIG_T4240_QDS)   += t4240_qds.o corenet_ds.o
 obj-$(CONFIG_STX_GP3)	  += stx_gp3.o
 obj-$(CONFIG_TQM85xx)	  += tqm85xx.o
 obj-$(CONFIG_SBC8548)     += sbc8548.o
diff --git a/arch/powerpc/platforms/85xx/corenet_ds.c b/arch/powerpc/platforms/85xx/corenet_ds.c
index 6f355d8..c59c617 100644
--- a/arch/powerpc/platforms/85xx/corenet_ds.c
+++ b/arch/powerpc/platforms/85xx/corenet_ds.c
@@ -40,7 +40,7 @@ void __init corenet_ds_pic_init(void)
 	if (ppc_md.get_irq == mpic_get_coreint_irq)
 		flags |= MPIC_ENABLE_COREINT;
 
-	mpic = mpic_alloc(NULL, 0, flags, 0, 256, " OpenPIC  ");
+	mpic = mpic_alloc(NULL, 0, flags, 0, 512, " OpenPIC  ");
 	BUG_ON(mpic == NULL);
 
 	mpic_init(mpic);
@@ -83,6 +83,9 @@ static const struct of_device_id of_device_ids[] = {
 	{
 		.compatible	= "fsl,qoriq-pcie-v2.4",
 	},
+	{
+		.compatible	= "fsl,qoriq-pcie-v3.0",
+	},
 	/* The following two are for the Freescale hypervisor */
 	{
 		.name		= "hypervisor",
diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c
index 148c2f2..6a17599 100644
--- a/arch/powerpc/platforms/85xx/smp.c
+++ b/arch/powerpc/platforms/85xx/smp.c
@@ -201,7 +201,7 @@ static int __cpuinit smp_85xx_kick_cpu(int nr)
 		 * We don't set the BPTR register here since it already points
 		 * to the boot page properly.
 		 */
-		mpic_reset_core(hw_cpu);
+		mpic_reset_core(nr);
 
 		/*
 		 * wait until core is ready...
diff --git a/arch/powerpc/platforms/85xx/t4240_qds.c b/arch/powerpc/platforms/85xx/t4240_qds.c
new file mode 100644
index 0000000..5998e9f
--- /dev/null
+++ b/arch/powerpc/platforms/85xx/t4240_qds.c
@@ -0,0 +1,98 @@
+/*
+ * T4240 QDS Setup
+ *
+ * Maintained by Kumar Gala (see MAINTAINERS for contact information)
+ *
+ * Copyright 2012 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/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 t4240_qds_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,T4240QDS"))
+		return 1;
+
+	/* Check if we're running under the Freescale hypervisor */
+	if (of_flat_dt_is_compatible(root, "fsl,T4240QDS-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(t4240_qds) {
+	.name			= "T4240 QDS",
+	.probe			= t4240_qds_probe,
+	.setup_arch		= corenet_ds_setup_arch,
+	.init_IRQ		= corenet_ds_pic_init,
+#ifdef CONFIG_PCI
+	.pcibios_fixup_bus	= fsl_pcibios_fixup_bus,
+#endif
+/* coreint doesn't play nice with lazy EE, use legacy mpic for now */
+#ifdef CONFIG_PPC64
+	.get_irq		= mpic_get_irq,
+#else
+	.get_irq		= mpic_get_coreint_irq,
+#endif
+	.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_arch_initcall(t4240_qds, corenet_ds_publish_devices);
+
+#ifdef CONFIG_SWIOTLB
+machine_arch_initcall(t4240_qds, swiotlb_setup_bus_notifier);
+#endif
diff --git a/arch/powerpc/platforms/86xx/Kconfig b/arch/powerpc/platforms/86xx/Kconfig
index 7a6279e..1afd1e4 100644
--- a/arch/powerpc/platforms/86xx/Kconfig
+++ b/arch/powerpc/platforms/86xx/Kconfig
@@ -37,7 +37,6 @@ config GEF_PPC9A
 	bool "GE PPC9A"
 	select DEFAULT_UIMAGE
 	select MMIO_NVRAM
-	select GENERIC_GPIO
 	select ARCH_REQUIRE_GPIOLIB
 	select GE_FPGA
 	help
@@ -47,7 +46,6 @@ config GEF_SBC310
 	bool "GE SBC310"
 	select DEFAULT_UIMAGE
 	select MMIO_NVRAM
-	select GENERIC_GPIO
 	select ARCH_REQUIRE_GPIOLIB
 	select GE_FPGA
 	help
@@ -57,7 +55,6 @@ config GEF_SBC610
 	bool "GE SBC610"
 	select DEFAULT_UIMAGE
 	select MMIO_NVRAM
-	select GENERIC_GPIO
 	select ARCH_REQUIRE_GPIOLIB
 	select GE_FPGA
 	select HAS_RAPIDIO
diff --git a/arch/powerpc/platforms/8xx/Kconfig b/arch/powerpc/platforms/8xx/Kconfig
index 1fb0b3c..8dec3c0 100644
--- a/arch/powerpc/platforms/8xx/Kconfig
+++ b/arch/powerpc/platforms/8xx/Kconfig
@@ -114,7 +114,6 @@ config 8xx_COPYBACK
 
 config 8xx_GPIO
 	bool "GPIO API Support"
-	select GENERIC_GPIO
 	select ARCH_REQUIRE_GPIOLIB
 	help
 	  Saying Y here will cause the ports on an MPC8xx processor to be used
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig
index 52de8bc..6c9c315 100644
--- a/arch/powerpc/platforms/Kconfig
+++ b/arch/powerpc/platforms/Kconfig
@@ -303,7 +303,6 @@ config QUICC_ENGINE
 config QE_GPIO
 	bool "QE GPIO support"
 	depends on QUICC_ENGINE
-	select GENERIC_GPIO
 	select ARCH_REQUIRE_GPIOLIB
 	help
 	  Say Y here if you're going to use hardware that connects to the
@@ -316,7 +315,6 @@ config CPM2
 	select PPC_LIB_RHEAP
 	select PPC_PCI_CHOICE
 	select ARCH_REQUIRE_GPIOLIB
-	select GENERIC_GPIO
 	help
 	  The CPM2 (Communications Processor Module) is a coprocessor on
 	  embedded CPUs made by Freescale.  Selecting this option means that
@@ -344,7 +342,6 @@ config FSL_ULI1575
 
 config CPM
 	bool
-	select PPC_CLOCK
 
 config OF_RTC
 	bool
@@ -355,7 +352,6 @@ config OF_RTC
 config SIMPLE_GPIO
 	bool "Support for simple, memory-mapped GPIO controllers"
 	depends on PPC
-	select GENERIC_GPIO
 	select ARCH_REQUIRE_GPIOLIB
 	help
 	  Say Y here to support simple, memory-mapped GPIO controllers.
@@ -366,7 +362,6 @@ config SIMPLE_GPIO
 config MCU_MPC8349EMITX
 	bool "MPC8349E-mITX MCU driver"
 	depends on I2C=y && PPC_83xx
-	select GENERIC_GPIO
 	select ARCH_REQUIRE_GPIOLIB
 	help
 	  Say Y here to enable soft power-off functionality on the Freescale
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype
index 18e3b76..54f3936 100644
--- a/arch/powerpc/platforms/Kconfig.cputype
+++ b/arch/powerpc/platforms/Kconfig.cputype
@@ -230,7 +230,7 @@ config PHYS_64BIT
 
 config ALTIVEC
 	bool "AltiVec Support"
-	depends on 6xx || POWER4
+	depends on 6xx || POWER4 || (PPC_E500MC && PPC64)
 	---help---
 	  This option enables kernel support for the Altivec extensions to the
 	  PowerPC processor. The kernel currently supports saving and restoring
diff --git a/arch/powerpc/platforms/cell/cbe_cpufreq.c b/arch/powerpc/platforms/cell/cbe_cpufreq.c
index d4c39e3..718c6a3 100644
--- a/arch/powerpc/platforms/cell/cbe_cpufreq.c
+++ b/arch/powerpc/platforms/cell/cbe_cpufreq.c
@@ -156,10 +156,9 @@ static int cbe_cpufreq_target(struct cpufreq_policy *policy,
 
 	freqs.old = policy->cur;
 	freqs.new = cbe_freqs[cbe_pmode_new].frequency;
-	freqs.cpu = policy->cpu;
 
 	mutex_lock(&cbe_switch_mutex);
-	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
 
 	pr_debug("setting frequency for cpu %d to %d kHz, " \
 		 "1/%d of max frequency\n",
@@ -169,7 +168,7 @@ static int cbe_cpufreq_target(struct cpufreq_policy *policy,
 
 	rc = set_pmode(policy->cpu, cbe_pmode_new);
 
-	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
 	mutex_unlock(&cbe_switch_mutex);
 
 	return rc;
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index 68c57d3..9098692 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -149,7 +149,6 @@ static int __fops ## _open(struct inode *inode, struct file *file)	\
 	return spufs_attr_open(inode, file, __get, __set, __fmt);	\
 }									\
 static const struct file_operations __fops = {				\
-	.owner	 = THIS_MODULE,						\
 	.open	 = __fops ## _open,					\
 	.release = spufs_attr_release,					\
 	.read	 = spufs_attr_read,					\
@@ -352,7 +351,7 @@ static unsigned long spufs_get_unmapped_area(struct file *file,
 
 	/* Else, try to obtain a 64K pages slice */
 	return slice_get_unmapped_area(addr, len, flags,
-				       MMU_PAGE_64K, 1, 0);
+				       MMU_PAGE_64K, 1);
 }
 #endif /* CONFIG_SPU_FS_64K_LS */
 
@@ -2591,7 +2590,6 @@ static unsigned int spufs_switch_log_poll(struct file *file, poll_table *wait)
 }
 
 static const struct file_operations spufs_switch_log_fops = {
-	.owner		= THIS_MODULE,
 	.open		= spufs_switch_log_open,
 	.read		= spufs_switch_log_read,
 	.poll		= spufs_switch_log_poll,
diff --git a/arch/powerpc/platforms/chrp/pegasos_eth.c b/arch/powerpc/platforms/chrp/pegasos_eth.c
index 039fc8e..2b4dc6a 100644
--- a/arch/powerpc/platforms/chrp/pegasos_eth.c
+++ b/arch/powerpc/platforms/chrp/pegasos_eth.c
@@ -47,6 +47,25 @@ static struct platform_device mv643xx_eth_shared_device = {
 	.resource	= mv643xx_eth_shared_resources,
 };
 
+/*
+ * The orion mdio driver only covers shared + 0x4 up to shared + 0x84 - 1
+ */
+static struct resource mv643xx_eth_mvmdio_resources[] = {
+	[0] = {
+		.name	= "ethernet mdio base",
+		.start	= 0xf1000000 + MV643XX_ETH_SHARED_REGS + 0x4,
+		.end	= 0xf1000000 + MV643XX_ETH_SHARED_REGS + 0x83,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device mv643xx_eth_mvmdio_device = {
+	.name		= "orion-mdio",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(mv643xx_eth_mvmdio_resources),
+	.resource	= mv643xx_eth_shared_resources,
+};
+
 static struct resource mv643xx_eth_port1_resources[] = {
 	[0] = {
 		.name	= "eth port1 irq",
@@ -82,6 +101,7 @@ static struct platform_device eth_port1_device = {
 
 static struct platform_device *mv643xx_eth_pd_devs[] __initdata = {
 	&mv643xx_eth_shared_device,
+	&mv643xx_eth_mvmdio_device,
 	&eth_port1_device,
 };
 
diff --git a/arch/powerpc/platforms/pasemi/cpufreq.c b/arch/powerpc/platforms/pasemi/cpufreq.c
index 890f30e..be1e795 100644
--- a/arch/powerpc/platforms/pasemi/cpufreq.c
+++ b/arch/powerpc/platforms/pasemi/cpufreq.c
@@ -273,10 +273,9 @@ static int pas_cpufreq_target(struct cpufreq_policy *policy,
 
 	freqs.old = policy->cur;
 	freqs.new = pas_freqs[pas_astate_new].frequency;
-	freqs.cpu = policy->cpu;
 
 	mutex_lock(&pas_switch_mutex);
-	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
 
 	pr_debug("setting frequency for cpu %d to %d kHz, 1/%d of max frequency\n",
 		 policy->cpu,
@@ -288,7 +287,7 @@ static int pas_cpufreq_target(struct cpufreq_policy *policy,
 	for_each_online_cpu(i)
 		set_astate(i, pas_astate_new);
 
-	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
 	mutex_unlock(&pas_switch_mutex);
 
 	ppc_proc_freq = freqs.new * 1000ul;
diff --git a/arch/powerpc/platforms/powermac/cpufreq_32.c b/arch/powerpc/platforms/powermac/cpufreq_32.c
index 311b804..3104fad 100644
--- a/arch/powerpc/platforms/powermac/cpufreq_32.c
+++ b/arch/powerpc/platforms/powermac/cpufreq_32.c
@@ -335,7 +335,8 @@ static int pmu_set_cpu_speed(int low_speed)
 	return 0;
 }
 
-static int do_set_cpu_speed(int speed_mode, int notify)
+static int do_set_cpu_speed(struct cpufreq_policy *policy, int speed_mode,
+		int notify)
 {
 	struct cpufreq_freqs freqs;
 	unsigned long l3cr;
@@ -343,13 +344,12 @@ static int do_set_cpu_speed(int speed_mode, int notify)
 
 	freqs.old = cur_freq;
 	freqs.new = (speed_mode == CPUFREQ_HIGH) ? hi_freq : low_freq;
-	freqs.cpu = smp_processor_id();
 
 	if (freqs.old == freqs.new)
 		return 0;
 
 	if (notify)
-		cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+		cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
 	if (speed_mode == CPUFREQ_LOW &&
 	    cpu_has_feature(CPU_FTR_L3CR)) {
 		l3cr = _get_L3CR();
@@ -366,7 +366,7 @@ static int do_set_cpu_speed(int speed_mode, int notify)
 			_set_L3CR(prev_l3cr);
 	}
 	if (notify)
-		cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+		cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
 	cur_freq = (speed_mode == CPUFREQ_HIGH) ? hi_freq : low_freq;
 
 	return 0;
@@ -393,7 +393,7 @@ static int pmac_cpufreq_target(	struct cpufreq_policy *policy,
 			target_freq, relation, &newstate))
 		return -EINVAL;
 
-	rc = do_set_cpu_speed(newstate, 1);
+	rc = do_set_cpu_speed(policy, newstate, 1);
 
 	ppc_proc_freq = cur_freq * 1000ul;
 	return rc;
@@ -442,7 +442,7 @@ static int pmac_cpufreq_suspend(struct cpufreq_policy *policy)
 	no_schedule = 1;
 	sleep_freq = cur_freq;
 	if (cur_freq == low_freq && !is_pmu_based)
-		do_set_cpu_speed(CPUFREQ_HIGH, 0);
+		do_set_cpu_speed(policy, CPUFREQ_HIGH, 0);
 	return 0;
 }
 
@@ -458,7 +458,7 @@ static int pmac_cpufreq_resume(struct cpufreq_policy *policy)
 	 * is that we force a switch to whatever it was, which is
 	 * probably high speed due to our suspend() routine
 	 */
-	do_set_cpu_speed(sleep_freq == low_freq ?
+	do_set_cpu_speed(policy, sleep_freq == low_freq ?
 			 CPUFREQ_LOW : CPUFREQ_HIGH, 0);
 
 	ppc_proc_freq = cur_freq * 1000ul;
diff --git a/arch/powerpc/platforms/powermac/cpufreq_64.c b/arch/powerpc/platforms/powermac/cpufreq_64.c
index 9650c60..7ba4234 100644
--- a/arch/powerpc/platforms/powermac/cpufreq_64.c
+++ b/arch/powerpc/platforms/powermac/cpufreq_64.c
@@ -339,11 +339,10 @@ static int g5_cpufreq_target(struct cpufreq_policy *policy,
 
 	freqs.old = g5_cpu_freqs[g5_pmode_cur].frequency;
 	freqs.new = g5_cpu_freqs[newstate].frequency;
-	freqs.cpu = 0;
 
-	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
 	rc = g5_switch_freq(newstate);
-	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
 
 	mutex_unlock(&g5_switch_mutex);
 
diff --git a/arch/powerpc/platforms/pseries/scanlog.c b/arch/powerpc/platforms/pseries/scanlog.c
index 47f3cda..cc220d2 100644
--- a/arch/powerpc/platforms/pseries/scanlog.c
+++ b/arch/powerpc/platforms/pseries/scanlog.c
@@ -46,8 +46,7 @@ static struct proc_dir_entry *proc_ppc64_scan_log_dump;	/* The proc file */
 static ssize_t scanlog_read(struct file *file, char __user *buf,
 			    size_t count, loff_t *ppos)
 {
-	struct proc_dir_entry *dp = PDE(file_inode(file));
-	unsigned int *data = (unsigned int *)dp->data;
+	unsigned int *data = PDE_DATA(file_inode(file));
 	int status;
 	unsigned long len, off;
 	unsigned int wait_time;
@@ -135,8 +134,7 @@ static ssize_t scanlog_write(struct file * file, const char __user * buf,
 
 static int scanlog_open(struct inode * inode, struct file * file)
 {
-	struct proc_dir_entry *dp = PDE(inode);
-	unsigned int *data = (unsigned int *)dp->data;
+	unsigned int *data = PDE_DATA(file_inode(file));
 
 	if (data[0] != 0) {
 		/* This imperfect test stops a second copy of the
@@ -152,8 +150,7 @@ static int scanlog_open(struct inode * inode, struct file * file)
 
 static int scanlog_release(struct inode * inode, struct file * file)
 {
-	struct proc_dir_entry *dp = PDE(inode);
-	unsigned int *data = (unsigned int *)dp->data;
+	unsigned int *data = PDE_DATA(file_inode(file));
 
 	data[0] = 0;
 
diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c
index 178c994..ab02db3 100644
--- a/arch/powerpc/sysdev/fsl_msi.c
+++ b/arch/powerpc/sysdev/fsl_msi.c
@@ -333,6 +333,8 @@ static int fsl_of_msi_remove(struct platform_device *ofdev)
 	return 0;
 }
 
+static struct lock_class_key fsl_msi_irq_class;
+
 static int fsl_msi_setup_hwirq(struct fsl_msi *msi, struct platform_device *dev,
 			       int offset, int irq_index)
 {
@@ -351,7 +353,7 @@ static int fsl_msi_setup_hwirq(struct fsl_msi *msi, struct platform_device *dev,
 		dev_err(&dev->dev, "No memory for MSI cascade data\n");
 		return -ENOMEM;
 	}
-
+	irq_set_lockdep_class(virt_msir, &fsl_msi_irq_class);
 	msi->msi_virqs[irq_index] = virt_msir;
 	cascade_data->index = offset;
 	cascade_data->msi_data = msi;
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index 682084d..e7ec337 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -54,13 +54,35 @@ static void quirk_fsl_pcie_header(struct pci_dev *dev)
 	return;
 }
 
-static int __init fsl_pcie_check_link(struct pci_controller *hose)
+static int __init fsl_pcie_check_link(struct pci_controller *hose,
+				  struct resource *rsrc)
 {
+	struct ccsr_pci __iomem *pci = NULL;
 	u32 val;
 
+	/* for PCIe IP rev 3.0 or greater use CSR0 for link state */
+	if (rsrc) {
+		pr_debug("PCI memory map start 0x%016llx, size 0x%016llx\n",
+		    (u64)rsrc->start, (u64)rsrc->end - (u64)rsrc->start + 1);
+		pci = ioremap(rsrc->start, rsrc->end - rsrc->start + 1);
+		if (!pci) {
+			dev_err(hose->parent, "Unable to map PCIe registers\n");
+			return -ENOMEM;
+		}
+		if (in_be32(&pci->block_rev1) >= PCIE_IP_REV_3_0) {
+			val = (in_be32(&pci->pex_csr0) & PEX_CSR0_LTSSM_MASK)
+					>> PEX_CSR0_LTSSM_SHIFT;
+			if (val != PEX_CSR0_LTSSM_L0)
+				return 1;
+			iounmap(pci);
+			return 0;
+		}
+		iounmap(pci);
+	}
 	early_read_config_dword(hose, 0, 0, PCIE_LTSSM, &val);
 	if (val < PCIE_LTSSM_L0)
 		return 1;
+
 	return 0;
 }
 
@@ -106,7 +128,7 @@ static int setup_one_atmu(struct ccsr_pci __iomem *pci,
 		flags |= 0x10000000; /* enable relaxed ordering */
 
 	for (i = 0; size > 0; i++) {
-		unsigned int bits = min(__ilog2(size),
+		unsigned int bits = min(ilog2(size),
 					__ffs(pci_addr | phys_addr));
 
 		if (index + i >= 5)
@@ -196,7 +218,7 @@ static void setup_pci_atmu(struct pci_controller *hose,
 			out_be32(&pci->pow[j].powbar, (hose->io_base_phys >> 12));
 			/* Enable, IO R/W */
 			out_be32(&pci->pow[j].powar, 0x80088000
-				| (__ilog2(hose->io_resource.end
+				| (ilog2(hose->io_resource.end
 				- hose->io_resource.start + 1) - 1));
 		}
 	}
@@ -261,7 +283,7 @@ static void setup_pci_atmu(struct pci_controller *hose,
 	}
 
 	sz = min(mem, paddr_lo);
-	mem_log = __ilog2_u64(sz);
+	mem_log = ilog2(sz);
 
 	/* PCIe can overmap inbound & outbound since RX & TX are separated */
 	if (early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP)) {
@@ -290,7 +312,7 @@ static void setup_pci_atmu(struct pci_controller *hose,
 		 * SWIOTLB and access the full range of memory
 		 */
 		if (sz != mem) {
-			mem_log = __ilog2_u64(mem);
+			mem_log = ilog2(mem);
 
 			/* Size window up if we dont fit in exact power-of-2 */
 			if ((1ull << mem_log) != mem)
@@ -327,7 +349,7 @@ static void setup_pci_atmu(struct pci_controller *hose,
 		sz -= 1ull << mem_log;
 
 		if (sz) {
-			mem_log = __ilog2_u64(sz);
+			mem_log = ilog2(sz);
 			piwar |= (mem_log - 1);
 
 			out_be32(&pci->piw[win_idx].pitar,  paddr >> 12);
@@ -483,7 +505,7 @@ int __init fsl_add_bridge(struct platform_device *pdev, int is_primary)
 	if (early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP)) {
 		hose->indirect_type |= PPC_INDIRECT_TYPE_EXT_REG |
 			PPC_INDIRECT_TYPE_SURPRESS_PRIMARY_BUS;
-		if (fsl_pcie_check_link(hose))
+		if (fsl_pcie_check_link(hose, &rsrc))
 			hose->indirect_type |= PPC_INDIRECT_TYPE_NO_PCIE_LINK;
 	}
 
@@ -685,7 +707,7 @@ static int __init mpc83xx_pcie_setup(struct pci_controller *hose,
 	out_le32(pcie->cfg_type0 + PEX_OUTWIN0_TAH, 0);
 	out_le32(pcie->cfg_type0 + PEX_OUTWIN0_TAL, 0);
 
-	if (fsl_pcie_check_link(hose))
+	if (fsl_pcie_check_link(hose, NULL))
 		hose->indirect_type |= PPC_INDIRECT_TYPE_NO_PCIE_LINK;
 
 	return 0;
@@ -836,6 +858,7 @@ static const struct of_device_id pci_ids[] = {
 	{ .compatible = "fsl,qoriq-pcie-v2.2", },
 	{ .compatible = "fsl,qoriq-pcie-v2.3", },
 	{ .compatible = "fsl,qoriq-pcie-v2.4", },
+	{ .compatible = "fsl,qoriq-pcie-v3.0", },
 
 	/*
 	 * The following entries are for compatibility with older device
diff --git a/arch/powerpc/sysdev/fsl_pci.h b/arch/powerpc/sysdev/fsl_pci.h
index c495c00..72b5625 100644
--- a/arch/powerpc/sysdev/fsl_pci.h
+++ b/arch/powerpc/sysdev/fsl_pci.h
@@ -14,9 +14,12 @@
 #ifndef __POWERPC_FSL_PCI_H
 #define __POWERPC_FSL_PCI_H
 
+struct platform_device;
+
 #define PCIE_LTSSM	0x0404		/* PCIE Link Training and Status */
 #define PCIE_LTSSM_L0	0x16		/* L0 state */
 #define PCIE_IP_REV_2_2		0x02080202 /* PCIE IP block version Rev2.2 */
+#define PCIE_IP_REV_3_0		0x02080300 /* PCIE IP block version Rev3.0 */
 #define PIWAR_EN		0x80000000	/* Enable */
 #define PIWAR_PF		0x20000000	/* prefetch */
 #define PIWAR_TGI_LOCAL		0x00f00000	/* target - local memory */
@@ -89,6 +92,16 @@ struct ccsr_pci {
 	__be32	pex_err_cap_r1;		/* 0x.e2c - PCIE error capture register 0 */
 	__be32	pex_err_cap_r2;		/* 0x.e30 - PCIE error capture register 0 */
 	__be32	pex_err_cap_r3;		/* 0x.e34 - PCIE error capture register 0 */
+	u8	res_e38[200];
+	__be32	pdb_stat;		/* 0x.f00 - PCIE Debug Status */
+	u8	res_f04[16];
+	__be32	pex_csr0;		/* 0x.f14 - PEX Control/Status register 0*/
+#define PEX_CSR0_LTSSM_MASK	0xFC
+#define PEX_CSR0_LTSSM_SHIFT	2
+#define PEX_CSR0_LTSSM_L0	0x11
+	__be32	pex_csr1;		/* 0x.f18 - PEX Control/Status register 1*/
+	u8	res_f1c[228];
+
 };
 
 extern int fsl_add_bridge(struct platform_device *pdev, int is_primary);
diff --git a/arch/powerpc/sysdev/mv64x60_dev.c b/arch/powerpc/sysdev/mv64x60_dev.c
index 0f6af41..4a25c26 100644
--- a/arch/powerpc/sysdev/mv64x60_dev.c
+++ b/arch/powerpc/sysdev/mv64x60_dev.c
@@ -214,15 +214,27 @@ static struct platform_device * __init mv64x60_eth_register_shared_pdev(
 						struct device_node *np, int id)
 {
 	struct platform_device *pdev;
-	struct resource r[1];
+	struct resource r[2];
 	int err;
 
 	err = of_address_to_resource(np, 0, &r[0]);
 	if (err)
 		return ERR_PTR(err);
 
+	/* register an orion mdio bus driver */
+	r[1].start = r[0].start + 0x4;
+	r[1].end = r[0].start + 0x84 - 1;
+	r[1].flags = IORESOURCE_MEM;
+
+	if (id == 0) {
+		pdev = platform_device_register_simple("orion-mdio", -1, &r[1], 1);
+		if (!pdev)
+			return pdev;
+	}
+
 	pdev = platform_device_register_simple(MV643XX_ETH_SHARED_NAME, id,
-					       r, 1);
+					       &r[0], 1);
+
 	return pdev;
 }
 
diff --git a/arch/powerpc/sysdev/qe_lib/Kconfig b/arch/powerpc/sysdev/qe_lib/Kconfig
index 41ac3df..3c25199 100644
--- a/arch/powerpc/sysdev/qe_lib/Kconfig
+++ b/arch/powerpc/sysdev/qe_lib/Kconfig
@@ -22,6 +22,6 @@ config UCC
 
 config QE_USB
 	bool
-	default y if USB_GADGET_FSL_QE
+	default y if USB_FSL_QE
 	help
 	  QE USB Controller support
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index eb8fb62..6a94c39 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -91,6 +91,7 @@ config S390
 	select ARCH_INLINE_WRITE_UNLOCK_BH
 	select ARCH_INLINE_WRITE_UNLOCK_IRQ
 	select ARCH_INLINE_WRITE_UNLOCK_IRQRESTORE
+	select ARCH_HAS_DEBUG_STRICT_USER_COPY_CHECKS
 	select ARCH_SAVE_PAGE_KEYS if HIBERNATION
 	select ARCH_WANT_IPC_PARSE_VERSION
 	select BUILDTIME_EXTABLE_SORT
@@ -131,7 +132,6 @@ config S390
 	select HAVE_PERF_EVENTS
 	select HAVE_REGS_AND_STACK_ACCESS_API
 	select HAVE_SYSCALL_TRACEPOINTS
-	select HAVE_SYSCALL_WRAPPERS
 	select HAVE_UID16 if 32BIT
 	select HAVE_VIRT_CPU_ACCOUNTING
 	select VIRT_TO_BUS
diff --git a/arch/s390/Kconfig.debug b/arch/s390/Kconfig.debug
index fc32a2d..c56878e 100644
--- a/arch/s390/Kconfig.debug
+++ b/arch/s390/Kconfig.debug
@@ -17,20 +17,6 @@ config STRICT_DEVMEM
 
 	  If you are unsure, say Y.
 
-config DEBUG_STRICT_USER_COPY_CHECKS
-	def_bool n
-	prompt "Strict user copy size checks"
-	---help---
-	  Enabling this option turns a certain set of sanity checks for user
-	  copy operations into compile time warnings.
-
-	  The copy_from_user() etc checks are there to help test if there
-	  are sufficient security checks on the length argument of
-	  the copy operation, by having gcc prove that the argument is
-	  within bounds.
-
-	  If unsure, or if you run an older (pre 4.4) gcc, say N.
-
 config S390_PTDUMP
 	bool "Export kernel pagetable layout to userspace via debugfs"
 	depends on DEBUG_KERNEL
diff --git a/arch/s390/hypfs/hypfs_dbfs.c b/arch/s390/hypfs/hypfs_dbfs.c
index 9fd4a40..bb5dd49 100644
--- a/arch/s390/hypfs/hypfs_dbfs.c
+++ b/arch/s390/hypfs/hypfs_dbfs.c
@@ -105,9 +105,7 @@ void hypfs_dbfs_remove_file(struct hypfs_dbfs_file *df)
 int hypfs_dbfs_init(void)
 {
 	dbfs_dir = debugfs_create_dir("s390_hypfs", NULL);
-	if (IS_ERR(dbfs_dir))
-		return PTR_ERR(dbfs_dir);
-	return 0;
+	return PTR_RET(dbfs_dir);
 }
 
 void hypfs_dbfs_exit(void)
diff --git a/arch/s390/hypfs/inode.c b/arch/s390/hypfs/inode.c
index 5f7d7ba..7a539f4 100644
--- a/arch/s390/hypfs/inode.c
+++ b/arch/s390/hypfs/inode.c
@@ -21,6 +21,7 @@
 #include <linux/module.h>
 #include <linux/seq_file.h>
 #include <linux/mount.h>
+#include <linux/aio.h>
 #include <asm/ebcdic.h>
 #include "hypfs.h"
 
diff --git a/arch/s390/include/asm/bitops.h b/arch/s390/include/asm/bitops.h
index 1542293..4d8604e 100644
--- a/arch/s390/include/asm/bitops.h
+++ b/arch/s390/include/asm/bitops.h
@@ -61,8 +61,6 @@ extern const char _sb_findmap[];
 
 #ifndef CONFIG_64BIT
 
-#define __BITOPS_ALIGN		3
-#define __BITOPS_WORDSIZE	32
 #define __BITOPS_OR		"or"
 #define __BITOPS_AND		"nr"
 #define __BITOPS_XOR		"xr"
@@ -81,8 +79,6 @@ extern const char _sb_findmap[];
 
 #else /* CONFIG_64BIT */
 
-#define __BITOPS_ALIGN		7
-#define __BITOPS_WORDSIZE	64
 #define __BITOPS_OR		"ogr"
 #define __BITOPS_AND		"ngr"
 #define __BITOPS_XOR		"xgr"
@@ -101,8 +97,7 @@ extern const char _sb_findmap[];
 
 #endif /* CONFIG_64BIT */
 
-#define __BITOPS_WORDS(bits) (((bits)+__BITOPS_WORDSIZE-1)/__BITOPS_WORDSIZE)
-#define __BITOPS_BARRIER() asm volatile("" : : : "memory")
+#define __BITOPS_WORDS(bits) (((bits) + BITS_PER_LONG - 1) / BITS_PER_LONG)
 
 #ifdef CONFIG_SMP
 /*
@@ -114,9 +109,9 @@ static inline void set_bit_cs(unsigned long nr, volatile unsigned long *ptr)
 
 	addr = (unsigned long) ptr;
 	/* calculate address for CS */
-	addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3;
+	addr += (nr ^ (nr & (BITS_PER_LONG - 1))) >> 3;
 	/* make OR mask */
-	mask = 1UL << (nr & (__BITOPS_WORDSIZE - 1));
+	mask = 1UL << (nr & (BITS_PER_LONG - 1));
 	/* Do the atomic update. */
 	__BITOPS_LOOP(old, new, addr, mask, __BITOPS_OR);
 }
@@ -130,9 +125,9 @@ static inline void clear_bit_cs(unsigned long nr, volatile unsigned long *ptr)
 
 	addr = (unsigned long) ptr;
 	/* calculate address for CS */
-	addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3;
+	addr += (nr ^ (nr & (BITS_PER_LONG - 1))) >> 3;
 	/* make AND mask */
-	mask = ~(1UL << (nr & (__BITOPS_WORDSIZE - 1)));
+	mask = ~(1UL << (nr & (BITS_PER_LONG - 1)));
 	/* Do the atomic update. */
 	__BITOPS_LOOP(old, new, addr, mask, __BITOPS_AND);
 }
@@ -146,9 +141,9 @@ static inline void change_bit_cs(unsigned long nr, volatile unsigned long *ptr)
 
 	addr = (unsigned long) ptr;
 	/* calculate address for CS */
-	addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3;
+	addr += (nr ^ (nr & (BITS_PER_LONG - 1))) >> 3;
 	/* make XOR mask */
-	mask = 1UL << (nr & (__BITOPS_WORDSIZE - 1));
+	mask = 1UL << (nr & (BITS_PER_LONG - 1));
 	/* Do the atomic update. */
 	__BITOPS_LOOP(old, new, addr, mask, __BITOPS_XOR);
 }
@@ -163,12 +158,12 @@ test_and_set_bit_cs(unsigned long nr, volatile unsigned long *ptr)
 
 	addr = (unsigned long) ptr;
 	/* calculate address for CS */
-	addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3;
+	addr += (nr ^ (nr & (BITS_PER_LONG - 1))) >> 3;
 	/* make OR/test mask */
-	mask = 1UL << (nr & (__BITOPS_WORDSIZE - 1));
+	mask = 1UL << (nr & (BITS_PER_LONG - 1));
 	/* Do the atomic update. */
 	__BITOPS_LOOP(old, new, addr, mask, __BITOPS_OR);
-	__BITOPS_BARRIER();
+	barrier();
 	return (old & mask) != 0;
 }
 
@@ -182,12 +177,12 @@ test_and_clear_bit_cs(unsigned long nr, volatile unsigned long *ptr)
 
 	addr = (unsigned long) ptr;
 	/* calculate address for CS */
-	addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3;
+	addr += (nr ^ (nr & (BITS_PER_LONG - 1))) >> 3;
 	/* make AND/test mask */
-	mask = ~(1UL << (nr & (__BITOPS_WORDSIZE - 1)));
+	mask = ~(1UL << (nr & (BITS_PER_LONG - 1)));
 	/* Do the atomic update. */
 	__BITOPS_LOOP(old, new, addr, mask, __BITOPS_AND);
-	__BITOPS_BARRIER();
+	barrier();
 	return (old ^ new) != 0;
 }
 
@@ -201,12 +196,12 @@ test_and_change_bit_cs(unsigned long nr, volatile unsigned long *ptr)
 
 	addr = (unsigned long) ptr;
 	/* calculate address for CS */
-	addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3;
+	addr += (nr ^ (nr & (BITS_PER_LONG - 1))) >> 3;
 	/* make XOR/test mask */
-	mask = 1UL << (nr & (__BITOPS_WORDSIZE - 1));
+	mask = 1UL << (nr & (BITS_PER_LONG - 1));
 	/* Do the atomic update. */
 	__BITOPS_LOOP(old, new, addr, mask, __BITOPS_XOR);
-	__BITOPS_BARRIER();
+	barrier();
 	return (old & mask) != 0;
 }
 #endif /* CONFIG_SMP */
@@ -218,7 +213,7 @@ static inline void __set_bit(unsigned long nr, volatile unsigned long *ptr)
 {
 	unsigned long addr;
 
-	addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
+	addr = (unsigned long) ptr + ((nr ^ (BITS_PER_LONG - 8)) >> 3);
 	asm volatile(
 		"	oc	%O0(1,%R0),%1"
 		: "=Q" (*(char *) addr) : "Q" (_oi_bitmap[nr & 7]) : "cc" );
@@ -229,7 +224,7 @@ __constant_set_bit(const unsigned long nr, volatile unsigned long *ptr)
 {
 	unsigned long addr;
 
-	addr = ((unsigned long) ptr) + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
+	addr = ((unsigned long) ptr) + ((nr ^ (BITS_PER_LONG - 8)) >> 3);
 	*(unsigned char *) addr |= 1 << (nr & 7);
 }
 
@@ -246,7 +241,7 @@ __clear_bit(unsigned long nr, volatile unsigned long *ptr)
 {
 	unsigned long addr;
 
-	addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
+	addr = (unsigned long) ptr + ((nr ^ (BITS_PER_LONG - 8)) >> 3);
 	asm volatile(
 		"	nc	%O0(1,%R0),%1"
 		: "=Q" (*(char *) addr) : "Q" (_ni_bitmap[nr & 7]) : "cc" );
@@ -257,7 +252,7 @@ __constant_clear_bit(const unsigned long nr, volatile unsigned long *ptr)
 {
 	unsigned long addr;
 
-	addr = ((unsigned long) ptr) + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
+	addr = ((unsigned long) ptr) + ((nr ^ (BITS_PER_LONG - 8)) >> 3);
 	*(unsigned char *) addr &= ~(1 << (nr & 7));
 }
 
@@ -273,7 +268,7 @@ static inline void __change_bit(unsigned long nr, volatile unsigned long *ptr)
 {
 	unsigned long addr;
 
-	addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
+	addr = (unsigned long) ptr + ((nr ^ (BITS_PER_LONG - 8)) >> 3);
 	asm volatile(
 		"	xc	%O0(1,%R0),%1"
 		: "=Q" (*(char *) addr) : "Q" (_oi_bitmap[nr & 7]) : "cc" );
@@ -284,7 +279,7 @@ __constant_change_bit(const unsigned long nr, volatile unsigned long *ptr)
 {
 	unsigned long addr;
 
-	addr = ((unsigned long) ptr) + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
+	addr = ((unsigned long) ptr) + ((nr ^ (BITS_PER_LONG - 8)) >> 3);
 	*(unsigned char *) addr ^= 1 << (nr & 7);
 }
 
@@ -302,7 +297,7 @@ test_and_set_bit_simple(unsigned long nr, volatile unsigned long *ptr)
 	unsigned long addr;
 	unsigned char ch;
 
-	addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
+	addr = (unsigned long) ptr + ((nr ^ (BITS_PER_LONG - 8)) >> 3);
 	ch = *(unsigned char *) addr;
 	asm volatile(
 		"	oc	%O0(1,%R0),%1"
@@ -321,7 +316,7 @@ test_and_clear_bit_simple(unsigned long nr, volatile unsigned long *ptr)
 	unsigned long addr;
 	unsigned char ch;
 
-	addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
+	addr = (unsigned long) ptr + ((nr ^ (BITS_PER_LONG - 8)) >> 3);
 	ch = *(unsigned char *) addr;
 	asm volatile(
 		"	nc	%O0(1,%R0),%1"
@@ -340,7 +335,7 @@ test_and_change_bit_simple(unsigned long nr, volatile unsigned long *ptr)
 	unsigned long addr;
 	unsigned char ch;
 
-	addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
+	addr = (unsigned long) ptr + ((nr ^ (BITS_PER_LONG - 8)) >> 3);
 	ch = *(unsigned char *) addr;
 	asm volatile(
 		"	xc	%O0(1,%R0),%1"
@@ -376,7 +371,7 @@ static inline int __test_bit(unsigned long nr, const volatile unsigned long *ptr
 	unsigned long addr;
 	unsigned char ch;
 
-	addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
+	addr = (unsigned long) ptr + ((nr ^ (BITS_PER_LONG - 8)) >> 3);
 	ch = *(volatile unsigned char *) addr;
 	return (ch >> (nr & 7)) & 1;
 }
@@ -384,7 +379,7 @@ static inline int __test_bit(unsigned long nr, const volatile unsigned long *ptr
 static inline int 
 __constant_test_bit(unsigned long nr, const volatile unsigned long *addr) {
     return (((volatile char *) addr)
-	    [(nr^(__BITOPS_WORDSIZE-8))>>3] & (1<<(nr&7))) != 0;
+	    [(nr^(BITS_PER_LONG-8))>>3] & (1<<(nr&7))) != 0;
 }
 
 #define test_bit(nr,addr) \
@@ -693,18 +688,18 @@ static inline int find_next_bit_left(const unsigned long *addr,
 
 	if (offset >= size)
 		return size;
-	bit = offset & (__BITOPS_WORDSIZE - 1);
+	bit = offset & (BITS_PER_LONG - 1);
 	offset -= bit;
 	size -= offset;
-	p = addr + offset / __BITOPS_WORDSIZE;
+	p = addr + offset / BITS_PER_LONG;
 	if (bit) {
 		set = __flo_word(0, *p & (~0UL << bit));
 		if (set >= size)
 			return size + offset;
-		if (set < __BITOPS_WORDSIZE)
+		if (set < BITS_PER_LONG)
 			return set + offset;
-		offset += __BITOPS_WORDSIZE;
-		size -= __BITOPS_WORDSIZE;
+		offset += BITS_PER_LONG;
+		size -= BITS_PER_LONG;
 		p++;
 	}
 	return offset + find_first_bit_left(p, size);
@@ -736,22 +731,22 @@ static inline int find_next_zero_bit (const unsigned long * addr,
 
 	if (offset >= size)
 		return size;
-	bit = offset & (__BITOPS_WORDSIZE - 1);
+	bit = offset & (BITS_PER_LONG - 1);
 	offset -= bit;
 	size -= offset;
-	p = addr + offset / __BITOPS_WORDSIZE;
+	p = addr + offset / BITS_PER_LONG;
 	if (bit) {
 		/*
-		 * __ffz_word returns __BITOPS_WORDSIZE
+		 * __ffz_word returns BITS_PER_LONG
 		 * if no zero bit is present in the word.
 		 */
 		set = __ffz_word(bit, *p >> bit);
 		if (set >= size)
 			return size + offset;
-		if (set < __BITOPS_WORDSIZE)
+		if (set < BITS_PER_LONG)
 			return set + offset;
-		offset += __BITOPS_WORDSIZE;
-		size -= __BITOPS_WORDSIZE;
+		offset += BITS_PER_LONG;
+		size -= BITS_PER_LONG;
 		p++;
 	}
 	return offset + find_first_zero_bit(p, size);
@@ -773,22 +768,22 @@ static inline int find_next_bit (const unsigned long * addr,
 
 	if (offset >= size)
 		return size;
-	bit = offset & (__BITOPS_WORDSIZE - 1);
+	bit = offset & (BITS_PER_LONG - 1);
 	offset -= bit;
 	size -= offset;
-	p = addr + offset / __BITOPS_WORDSIZE;
+	p = addr + offset / BITS_PER_LONG;
 	if (bit) {
 		/*
-		 * __ffs_word returns __BITOPS_WORDSIZE
+		 * __ffs_word returns BITS_PER_LONG
 		 * if no one bit is present in the word.
 		 */
 		set = __ffs_word(0, *p & (~0UL << bit));
 		if (set >= size)
 			return size + offset;
-		if (set < __BITOPS_WORDSIZE)
+		if (set < BITS_PER_LONG)
 			return set + offset;
-		offset += __BITOPS_WORDSIZE;
-		size -= __BITOPS_WORDSIZE;
+		offset += BITS_PER_LONG;
+		size -= BITS_PER_LONG;
 		p++;
 	}
 	return offset + find_first_bit(p, size);
@@ -843,22 +838,22 @@ static inline int find_next_zero_bit_le(void *vaddr, unsigned long size,
 
         if (offset >= size)
                 return size;
-	bit = offset & (__BITOPS_WORDSIZE - 1);
+	bit = offset & (BITS_PER_LONG - 1);
 	offset -= bit;
 	size -= offset;
-	p = addr + offset / __BITOPS_WORDSIZE;
+	p = addr + offset / BITS_PER_LONG;
         if (bit) {
 		/*
-		 * s390 version of ffz returns __BITOPS_WORDSIZE
+		 * s390 version of ffz returns BITS_PER_LONG
 		 * if no zero bit is present in the word.
 		 */
 		set = __ffz_word(bit, __load_ulong_le(p, 0) >> bit);
 		if (set >= size)
 			return size + offset;
-		if (set < __BITOPS_WORDSIZE)
+		if (set < BITS_PER_LONG)
 			return set + offset;
-		offset += __BITOPS_WORDSIZE;
-		size -= __BITOPS_WORDSIZE;
+		offset += BITS_PER_LONG;
+		size -= BITS_PER_LONG;
 		p++;
         }
 	return offset + find_first_zero_bit_le(p, size);
@@ -885,22 +880,22 @@ static inline int find_next_bit_le(void *vaddr, unsigned long size,
 
 	if (offset >= size)
 		return size;
-	bit = offset & (__BITOPS_WORDSIZE - 1);
+	bit = offset & (BITS_PER_LONG - 1);
 	offset -= bit;
 	size -= offset;
-	p = addr + offset / __BITOPS_WORDSIZE;
+	p = addr + offset / BITS_PER_LONG;
 	if (bit) {
 		/*
-		 * s390 version of ffz returns __BITOPS_WORDSIZE
+		 * s390 version of ffz returns BITS_PER_LONG
 		 * if no zero bit is present in the word.
 		 */
 		set = __ffs_word(0, __load_ulong_le(p, 0) & (~0UL << bit));
 		if (set >= size)
 			return size + offset;
-		if (set < __BITOPS_WORDSIZE)
+		if (set < BITS_PER_LONG)
 			return set + offset;
-		offset += __BITOPS_WORDSIZE;
-		size -= __BITOPS_WORDSIZE;
+		offset += BITS_PER_LONG;
+		size -= BITS_PER_LONG;
 		p++;
 	}
 	return offset + find_first_bit_le(p, size);
diff --git a/arch/s390/include/asm/hugetlb.h b/arch/s390/include/asm/hugetlb.h
index 593753e..bd90359 100644
--- a/arch/s390/include/asm/hugetlb.h
+++ b/arch/s390/include/asm/hugetlb.h
@@ -114,7 +114,7 @@ static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
 #define huge_ptep_set_wrprotect(__mm, __addr, __ptep)			\
 ({									\
 	pte_t __pte = huge_ptep_get(__ptep);				\
-	if (pte_write(__pte)) {						\
+	if (huge_pte_write(__pte)) {					\
 		huge_ptep_invalidate(__mm, __addr, __ptep);		\
 		set_huge_pte_at(__mm, __addr, __ptep,			\
 				huge_pte_wrprotect(__pte));		\
@@ -127,4 +127,58 @@ static inline void huge_ptep_clear_flush(struct vm_area_struct *vma,
 	huge_ptep_invalidate(vma->vm_mm, address, ptep);
 }
 
+static inline pte_t mk_huge_pte(struct page *page, pgprot_t pgprot)
+{
+	pte_t pte;
+	pmd_t pmd;
+
+	pmd = mk_pmd_phys(page_to_phys(page), pgprot);
+	pte_val(pte) = pmd_val(pmd);
+	return pte;
+}
+
+static inline int huge_pte_write(pte_t pte)
+{
+	pmd_t pmd;
+
+	pmd_val(pmd) = pte_val(pte);
+	return pmd_write(pmd);
+}
+
+static inline int huge_pte_dirty(pte_t pte)
+{
+	/* No dirty bit in the segment table entry. */
+	return 0;
+}
+
+static inline pte_t huge_pte_mkwrite(pte_t pte)
+{
+	pmd_t pmd;
+
+	pmd_val(pmd) = pte_val(pte);
+	pte_val(pte) = pmd_val(pmd_mkwrite(pmd));
+	return pte;
+}
+
+static inline pte_t huge_pte_mkdirty(pte_t pte)
+{
+	/* No dirty bit in the segment table entry. */
+	return pte;
+}
+
+static inline pte_t huge_pte_modify(pte_t pte, pgprot_t newprot)
+{
+	pmd_t pmd;
+
+	pmd_val(pmd) = pte_val(pte);
+	pte_val(pte) = pmd_val(pmd_modify(pmd, newprot));
+	return pte;
+}
+
+static inline void huge_pte_clear(struct mm_struct *mm, unsigned long addr,
+				  pte_t *ptep)
+{
+	pmd_clear((pmd_t *) ptep);
+}
+
 #endif /* _ASM_S390_HUGETLB_H */
diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h
index 4a29308..4af1b6f 100644
--- a/arch/s390/include/asm/pgtable.h
+++ b/arch/s390/include/asm/pgtable.h
@@ -344,6 +344,7 @@ extern unsigned long MODULES_END;
 #define _REGION3_ENTRY_CO	0x100	/* change-recording override	    */
 
 /* Bits in the segment table entry */
+#define _SEGMENT_ENTRY_ORIGIN_LARGE ~0xfffffUL /* large page address	    */
 #define _SEGMENT_ENTRY_ORIGIN	~0x7ffUL/* segment table origin		    */
 #define _SEGMENT_ENTRY_RO	0x200	/* page protection bit		    */
 #define _SEGMENT_ENTRY_INV	0x20	/* invalid segment table entry	    */
@@ -419,6 +420,13 @@ extern unsigned long MODULES_END;
 #define __S110	PAGE_RW
 #define __S111	PAGE_RW
 
+/*
+ * Segment entry (large page) protection definitions.
+ */
+#define SEGMENT_NONE	__pgprot(_HPAGE_TYPE_NONE)
+#define SEGMENT_RO	__pgprot(_HPAGE_TYPE_RO)
+#define SEGMENT_RW	__pgprot(_HPAGE_TYPE_RW)
+
 static inline int mm_exclusive(struct mm_struct *mm)
 {
 	return likely(mm == current->active_mm &&
@@ -759,6 +767,8 @@ 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_translate(unsigned long address, struct gmap *);
+unsigned long gmap_translate(unsigned long address, struct gmap *);
 unsigned long __gmap_fault(unsigned long address, struct gmap *);
 unsigned long gmap_fault(unsigned long address, struct gmap *);
 void gmap_discard(unsigned long from, unsigned long to, struct gmap *);
@@ -907,26 +917,6 @@ static inline pte_t pte_mkspecial(pte_t pte)
 #ifdef CONFIG_HUGETLB_PAGE
 static inline pte_t pte_mkhuge(pte_t pte)
 {
-	/*
-	 * PROT_NONE needs to be remapped from the pte type to the ste type.
-	 * The HW invalid bit is also different for pte and ste. The pte
-	 * invalid bit happens to be the same as the ste _SEGMENT_ENTRY_LARGE
-	 * bit, so we don't have to clear it.
-	 */
-	if (pte_val(pte) & _PAGE_INVALID) {
-		if (pte_val(pte) & _PAGE_SWT)
-			pte_val(pte) |= _HPAGE_TYPE_NONE;
-		pte_val(pte) |= _SEGMENT_ENTRY_INV;
-	}
-	/*
-	 * Clear SW pte bits, there are no SW bits in a segment table entry.
-	 */
-	pte_val(pte) &= ~(_PAGE_SWT | _PAGE_SWX | _PAGE_SWC |
-			  _PAGE_SWR | _PAGE_SWW);
-	/*
-	 * Also set the change-override bit because we don't need dirty bit
-	 * tracking for hugetlbfs pages.
-	 */
 	pte_val(pte) |= (_SEGMENT_ENTRY_LARGE | _SEGMENT_ENTRY_CO);
 	return pte;
 }
@@ -1271,31 +1261,7 @@ static inline void __pmd_idte(unsigned long address, pmd_t *pmdp)
 	}
 }
 
-#ifdef CONFIG_TRANSPARENT_HUGEPAGE
-
-#define SEGMENT_NONE	__pgprot(_HPAGE_TYPE_NONE)
-#define SEGMENT_RO	__pgprot(_HPAGE_TYPE_RO)
-#define SEGMENT_RW	__pgprot(_HPAGE_TYPE_RW)
-
-#define __HAVE_ARCH_PGTABLE_DEPOSIT
-extern void pgtable_trans_huge_deposit(struct mm_struct *mm, pgtable_t pgtable);
-
-#define __HAVE_ARCH_PGTABLE_WITHDRAW
-extern pgtable_t pgtable_trans_huge_withdraw(struct mm_struct *mm);
-
-static inline int pmd_trans_splitting(pmd_t pmd)
-{
-	return pmd_val(pmd) & _SEGMENT_ENTRY_SPLIT;
-}
-
-static inline void set_pmd_at(struct mm_struct *mm, unsigned long addr,
-			      pmd_t *pmdp, pmd_t entry)
-{
-	if (!(pmd_val(entry) & _SEGMENT_ENTRY_INV) && MACHINE_HAS_EDAT1)
-		pmd_val(entry) |= _SEGMENT_ENTRY_CO;
-	*pmdp = entry;
-}
-
+#if defined(CONFIG_TRANSPARENT_HUGEPAGE) || defined(CONFIG_HUGETLB_PAGE)
 static inline unsigned long massage_pgprot_pmd(pgprot_t pgprot)
 {
 	/*
@@ -1316,10 +1282,11 @@ static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
 	return pmd;
 }
 
-static inline pmd_t pmd_mkhuge(pmd_t pmd)
+static inline pmd_t mk_pmd_phys(unsigned long physpage, pgprot_t pgprot)
 {
-	pmd_val(pmd) |= _SEGMENT_ENTRY_LARGE;
-	return pmd;
+	pmd_t __pmd;
+	pmd_val(__pmd) = physpage + massage_pgprot_pmd(pgprot);
+	return __pmd;
 }
 
 static inline pmd_t pmd_mkwrite(pmd_t pmd)
@@ -1329,6 +1296,34 @@ static inline pmd_t pmd_mkwrite(pmd_t pmd)
 		pmd_val(pmd) &= ~_SEGMENT_ENTRY_RO;
 	return pmd;
 }
+#endif /* CONFIG_TRANSPARENT_HUGEPAGE || CONFIG_HUGETLB_PAGE */
+
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+
+#define __HAVE_ARCH_PGTABLE_DEPOSIT
+extern void pgtable_trans_huge_deposit(struct mm_struct *mm, pgtable_t pgtable);
+
+#define __HAVE_ARCH_PGTABLE_WITHDRAW
+extern pgtable_t pgtable_trans_huge_withdraw(struct mm_struct *mm);
+
+static inline int pmd_trans_splitting(pmd_t pmd)
+{
+	return pmd_val(pmd) & _SEGMENT_ENTRY_SPLIT;
+}
+
+static inline void set_pmd_at(struct mm_struct *mm, unsigned long addr,
+			      pmd_t *pmdp, pmd_t entry)
+{
+	if (!(pmd_val(entry) & _SEGMENT_ENTRY_INV) && MACHINE_HAS_EDAT1)
+		pmd_val(entry) |= _SEGMENT_ENTRY_CO;
+	*pmdp = entry;
+}
+
+static inline pmd_t pmd_mkhuge(pmd_t pmd)
+{
+	pmd_val(pmd) |= _SEGMENT_ENTRY_LARGE;
+	return pmd;
+}
 
 static inline pmd_t pmd_wrprotect(pmd_t pmd)
 {
@@ -1425,13 +1420,6 @@ static inline void pmdp_set_wrprotect(struct mm_struct *mm,
 	}
 }
 
-static inline pmd_t mk_pmd_phys(unsigned long physpage, pgprot_t pgprot)
-{
-	pmd_t __pmd;
-	pmd_val(__pmd) = physpage + massage_pgprot_pmd(pgprot);
-	return __pmd;
-}
-
 #define pfn_pmd(pfn, pgprot)	mk_pmd_phys(__pa((pfn) << PAGE_SHIFT), (pgprot))
 #define mk_pmd(page, pgprot)	pfn_pmd(page_to_pfn(page), (pgprot))
 
@@ -1531,7 +1519,8 @@ extern int s390_enable_sie(void);
 /*
  * No page table caches to initialise
  */
-#define pgtable_cache_init()	do { } while (0)
+static inline void pgtable_cache_init(void) { }
+static inline void check_pgt_cache(void) { }
 
 #include <asm-generic/pgtable.h>
 
diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h
index 94e749c..6b49987 100644
--- a/arch/s390/include/asm/processor.h
+++ b/arch/s390/include/asm/processor.h
@@ -161,7 +161,8 @@ extern unsigned long thread_saved_pc(struct task_struct *t);
 
 extern void show_code(struct pt_regs *regs);
 extern void print_fn_code(unsigned char *code, unsigned long len);
-extern int insn_to_mnemonic(unsigned char *instruction, char buf[8]);
+extern int insn_to_mnemonic(unsigned char *instruction, char *buf,
+			    unsigned int len);
 
 unsigned long get_wchan(struct task_struct *p);
 #define task_pt_regs(tsk) ((struct pt_regs *) \
diff --git a/arch/s390/include/asm/unistd.h b/arch/s390/include/asm/unistd.h
index a6667a9..6518863 100644
--- a/arch/s390/include/asm/unistd.h
+++ b/arch/s390/include/asm/unistd.h
@@ -54,12 +54,4 @@
 #define __ARCH_WANT_SYS_VFORK
 #define __ARCH_WANT_SYS_CLONE
 
-/*
- * "Conditional" syscalls
- *
- * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
- * but it doesn't work on all toolchains, so we just do it by hand
- */
-#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
-
 #endif /* _ASM_S390_UNISTD_H_ */
diff --git a/arch/s390/include/uapi/asm/Kbuild b/arch/s390/include/uapi/asm/Kbuild
index 7bf68ff..9ccd190 100644
--- a/arch/s390/include/uapi/asm/Kbuild
+++ b/arch/s390/include/uapi/asm/Kbuild
@@ -44,5 +44,6 @@ header-y += termios.h
 header-y += types.h
 header-y += ucontext.h
 header-y += unistd.h
+header-y += virtio-ccw.h
 header-y += vtoc.h
 header-y += zcrypt.h
diff --git a/arch/s390/include/uapi/asm/socket.h b/arch/s390/include/uapi/asm/socket.h
index f99eea7..2dacb306 100644
--- a/arch/s390/include/uapi/asm/socket.h
+++ b/arch/s390/include/uapi/asm/socket.h
@@ -78,4 +78,6 @@
 
 #define SO_LOCK_FILTER		44
 
+#define SO_SELECT_ERR_QUEUE	45
+
 #endif /* _ASM_SOCKET_H */
diff --git a/arch/s390/include/uapi/asm/virtio-ccw.h b/arch/s390/include/uapi/asm/virtio-ccw.h
new file mode 100644
index 0000000..a9a4ebf
--- /dev/null
+++ b/arch/s390/include/uapi/asm/virtio-ccw.h
@@ -0,0 +1,21 @@
+/*
+ * Definitions for virtio-ccw devices.
+ *
+ * Copyright IBM Corp. 2013
+ *
+ * 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): Cornelia Huck <cornelia.huck@de.ibm.com>
+ */
+#ifndef __KVM_VIRTIO_CCW_H
+#define __KVM_VIRTIO_CCW_H
+
+/* Alignment of vring buffers. */
+#define KVM_VIRTIO_CCW_RING_ALIGN 4096
+
+/* Subcode for diagnose 500 (virtio hypercall). */
+#define KVM_S390_VIRTIO_CCW_NOTIFY 3
+
+#endif
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
index 2ac311e..1386fca 100644
--- a/arch/s390/kernel/Makefile
+++ b/arch/s390/kernel/Makefile
@@ -14,16 +14,25 @@ endif
 CFLAGS_smp.o	:= -Wno-nonnull
 
 #
+# Disable tailcall optimizations for stack / callchain walking functions
+# since this might generate broken code when accessing register 15 and
+# passing its content to other functions.
+#
+CFLAGS_stacktrace.o	+= -fno-optimize-sibling-calls
+CFLAGS_dumpstack.o	+= -fno-optimize-sibling-calls
+
+#
 # Pass UTS_MACHINE for user_regset definition
 #
 CFLAGS_ptrace.o		+= -DUTS_MACHINE='"$(UTS_MACHINE)"'
 
 CFLAGS_sysinfo.o += -Iinclude/math-emu -Iarch/s390/math-emu -w
 
-obj-y	:=  bitmap.o traps.o time.o process.o base.o early.o setup.o vtime.o \
-	    processor.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o nmi.o \
-	    debug.o irq.o ipl.o dis.o diag.o mem_detect.o sclp.o vdso.o \
-	    sysinfo.o jump_label.o lgr.o os_info.o machine_kexec.o pgm_check.o
+obj-y	:= bitmap.o traps.o time.o process.o base.o early.o setup.o vtime.o
+obj-y	+= processor.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o nmi.o
+obj-y	+= debug.o irq.o ipl.o dis.o diag.o mem_detect.o sclp.o vdso.o
+obj-y	+= sysinfo.o jump_label.o lgr.o os_info.o machine_kexec.o pgm_check.o
+obj-y	+= dumpstack.o
 
 obj-y	+= $(if $(CONFIG_64BIT),entry64.o,entry.o)
 obj-y	+= $(if $(CONFIG_64BIT),reipl64.o,reipl.o)
diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c
index 19f26de..8b6e4f5 100644
--- a/arch/s390/kernel/compat_linux.c
+++ b/arch/s390/kernel/compat_linux.c
@@ -288,51 +288,13 @@ asmlinkage long sys32_getegid16(void)
 	return high2lowgid(from_kgid_munged(current_user_ns(), current_egid()));
 }
 
-/*
- * sys32_ipc() is the de-multiplexer for the SysV IPC calls in 32bit emulation.
- *
- * This is really horribly ugly.
- */
 #ifdef CONFIG_SYSVIPC
-asmlinkage long sys32_ipc(u32 call, int first, int second, int third, u32 ptr)
+COMPAT_SYSCALL_DEFINE5(s390_ipc, uint, call, int, first, unsigned long, second,
+		unsigned long, third, compat_uptr_t, ptr)
 {
 	if (call >> 16)		/* hack for backward compatibility */
 		return -EINVAL;
-	switch (call) {
-	case SEMTIMEDOP:
-		return compat_sys_semtimedop(first, compat_ptr(ptr),
-					     second, compat_ptr(third));
-	case SEMOP:
-		/* struct sembuf is the same on 32 and 64bit :)) */
-		return sys_semtimedop(first, compat_ptr(ptr),
-				      second, NULL);
-	case SEMGET:
-		return sys_semget(first, second, third);
-	case SEMCTL:
-		return compat_sys_semctl(first, second, third,
-					 compat_ptr(ptr));
-	case MSGSND:
-		return compat_sys_msgsnd(first, second, third,
-					 compat_ptr(ptr));
-	case MSGRCV:
-		return compat_sys_msgrcv(first, second, 0, third,
-					 0, compat_ptr(ptr));
-	case MSGGET:
-		return sys_msgget((key_t) first, second);
-	case MSGCTL:
-		return compat_sys_msgctl(first, second, compat_ptr(ptr));
-	case SHMAT:
-		return compat_sys_shmat(first, second, third,
-					0, compat_ptr(ptr));
-	case SHMDT:
-		return sys_shmdt(compat_ptr(ptr));
-	case SHMGET:
-		return sys_shmget(first, (unsigned)second, third);
-	case SHMCTL:
-		return compat_sys_shmctl(first, second, compat_ptr(ptr));
-	}
-
-	return -ENOSYS;
+	return compat_sys_ipc(call, first, second, third, ptr, third);
 }
 #endif
 
@@ -373,48 +335,6 @@ asmlinkage compat_ssize_t sys32_readahead(int fd, u32 offhi, u32 offlo, s32 coun
 	return sys_readahead(fd, ((loff_t)AA(offhi) << 32) | AA(offlo), count);
 }
 
-asmlinkage long sys32_sendfile(int out_fd, int in_fd, compat_off_t __user *offset, size_t count)
-{
-	mm_segment_t old_fs = get_fs();
-	int ret;
-	off_t of;
-	
-	if (offset && get_user(of, offset))
-		return -EFAULT;
-		
-	set_fs(KERNEL_DS);
-	ret = sys_sendfile(out_fd, in_fd,
-			   offset ? (off_t __force __user *) &of : NULL, count);
-	set_fs(old_fs);
-	
-	if (offset && put_user(of, offset))
-		return -EFAULT;
-		
-	return ret;
-}
-
-asmlinkage long sys32_sendfile64(int out_fd, int in_fd,
-				compat_loff_t __user *offset, s32 count)
-{
-	mm_segment_t old_fs = get_fs();
-	int ret;
-	loff_t lof;
-	
-	if (offset && get_user(lof, offset))
-		return -EFAULT;
-		
-	set_fs(KERNEL_DS);
-	ret = sys_sendfile64(out_fd, in_fd,
-			     offset ? (loff_t __force __user *) &lof : NULL,
-			     count);
-	set_fs(old_fs);
-	
-	if (offset && put_user(lof, offset))
-		return -EFAULT;
-		
-	return ret;
-}
-
 struct stat64_emu31 {
 	unsigned long long  st_dev;
 	unsigned int    __pad1;
diff --git a/arch/s390/kernel/compat_linux.h b/arch/s390/kernel/compat_linux.h
index 00d92a5..976518c 100644
--- a/arch/s390/kernel/compat_linux.h
+++ b/arch/s390/kernel/compat_linux.h
@@ -94,7 +94,6 @@ long sys32_getuid16(void);
 long sys32_geteuid16(void);
 long sys32_getgid16(void);
 long sys32_getegid16(void);
-long sys32_ipc(u32 call, int first, int second, int third, u32 ptr);
 long sys32_truncate64(const char __user * path, unsigned long high,
 		      unsigned long low);
 long sys32_ftruncate64(unsigned int fd, unsigned long high, unsigned long low);
@@ -106,10 +105,6 @@ long sys32_pread64(unsigned int fd, char __user *ubuf, size_t count,
 long sys32_pwrite64(unsigned int fd, const char __user *ubuf,
 		    size_t count, u32 poshi, u32 poslo);
 compat_ssize_t sys32_readahead(int fd, u32 offhi, u32 offlo, s32 count);
-long sys32_sendfile(int out_fd, int in_fd, compat_off_t __user *offset,
-		    size_t count);
-long sys32_sendfile64(int out_fd, int in_fd, compat_loff_t __user *offset,
-		      s32 count);
 long sys32_stat64(const char __user * filename, struct stat64_emu31 __user * statbuf);
 long sys32_lstat64(const char __user * filename,
 		   struct stat64_emu31 __user * statbuf);
diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S
index 3c98c4d..2d72d9e 100644
--- a/arch/s390/kernel/compat_wrapper.S
+++ b/arch/s390/kernel/compat_wrapper.S
@@ -258,11 +258,6 @@ ENTRY(sys32_mmap2_wrapper)
 	llgtr	%r2,%r2			# struct mmap_arg_struct_emu31 *
 	jg	sys32_mmap2			# branch to system call
 
-ENTRY(compat_sys_getrusage_wrapper)
-	lgfr	%r2,%r2			# int
-	llgtr	%r3,%r3			# struct rusage_emu31 *
-	jg	compat_sys_getrusage	# branch to system call
-
 ENTRY(compat_sys_gettimeofday_wrapper)
 	llgtr	%r2,%r2			# struct timeval_emu31 *
 	llgtr	%r3,%r3			# struct timezone *
@@ -393,14 +388,6 @@ ENTRY(compat_sys_sysinfo_wrapper)
 	llgtr	%r2,%r2			# struct sysinfo_emu31 *
 	jg	compat_sys_sysinfo	# branch to system call
 
-ENTRY(sys32_ipc_wrapper)
-	llgfr	%r2,%r2			# uint
-	lgfr	%r3,%r3			# int
-	lgfr	%r4,%r4			# int
-	lgfr	%r5,%r5			# int
-	llgfr	%r6,%r6			# u32
-	jg	sys32_ipc		# branch to system call
-
 ENTRY(sys32_fsync_wrapper)
 	llgfr	%r2,%r2			# unsigned int
 	jg	sys_fsync		# branch to system call
@@ -666,13 +653,6 @@ ENTRY(sys32_capset_wrapper)
 	llgtr	%r3,%r3			# const cap_user_data_t
 	jg	sys_capset		# branch to system call
 
-ENTRY(sys32_sendfile_wrapper)
-	lgfr	%r2,%r2			# int
-	lgfr	%r3,%r3			# int
-	llgtr	%r4,%r4			# __kernel_off_emu31_t *
-	llgfr	%r5,%r5			# size_t
-	jg	sys32_sendfile		# branch to system call
-
 #sys32_vfork_wrapper			# done in vfork_glue
 
 ENTRY(sys32_truncate64_wrapper)
@@ -938,13 +918,6 @@ ENTRY(sys_epoll_wait_wrapper)
 	lgfr	%r5,%r5			# int
 	jg	sys_epoll_wait		# branch to system call
 
-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
-
 ENTRY(sys32_fadvise64_wrapper)
 	lgfr	%r2,%r2			# int
 	sllg	%r3,%r3,32		# get high word of 64bit loff_t
@@ -1264,29 +1237,12 @@ ENTRY(sys_tee_wrapper)
 	llgfr	%r5,%r5			# unsigned int
 	jg	sys_tee
 
-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
-
 ENTRY(sys_getcpu_wrapper)
 	llgtr	%r2,%r2			# unsigned *
 	llgtr	%r3,%r3			# unsigned *
 	llgtr	%r4,%r4			# struct getcpu_cache *
 	jg	sys_getcpu
 
-ENTRY(compat_sys_epoll_pwait_wrapper)
-	lgfr	%r2,%r2			# int
-	llgtr	%r3,%r3			# struct compat_epoll_event *
-	lgfr	%r4,%r4			# int
-	lgfr	%r5,%r5			# int
-	llgtr	%r6,%r6			# compat_sigset_t *
-	llgf	%r0,164(%r15)		# compat_size_t
-	stg	%r0,160(%r15)
-	jg	compat_sys_epoll_pwait
-
 ENTRY(compat_sys_utimes_wrapper)
 	llgtr	%r2,%r2			# char *
 	llgtr	%r3,%r3			# struct compat_timeval *
@@ -1299,12 +1255,6 @@ ENTRY(compat_sys_utimensat_wrapper)
 	lgfr	%r5,%r5			# int
 	jg	compat_sys_utimensat
 
-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
-
 ENTRY(sys_eventfd_wrapper)
 	llgfr	%r2,%r2			# unsigned int
 	jg	sys_eventfd
@@ -1323,13 +1273,6 @@ ENTRY(sys_timerfd_create_wrapper)
 	lgfr	%r3,%r3			# int
 	jg	sys_timerfd_create
 
-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
-
 ENTRY(sys_eventfd2_wrapper)
 	llgfr	%r2,%r2			# unsigned int
 	lgfr	%r3,%r3			# int
@@ -1361,13 +1304,6 @@ ENTRY(sys32_readahead_wrapper)
 	lgfr	%r5,%r5			# s32
 	jg	sys32_readahead		# branch to system call
 
-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
-
 ENTRY(sys_tkill_wrapper)
 	lgfr	%r2,%r2			# pid_t
 	lgfr	%r3,%r3			# int
@@ -1387,22 +1323,6 @@ ENTRY(compat_sys_keyctl_wrapper)
 	llgfr	%r6,%r6			# u32
 	jg	compat_sys_keyctl	# branch to system call
 
-ENTRY(compat_sys_preadv_wrapper)
-	llgfr	%r2,%r2			# unsigned long
-	llgtr	%r3,%r3			# compat_iovec *
-	llgfr	%r4,%r4			# unsigned long
-	llgfr	%r5,%r5			# u32
-	llgfr	%r6,%r6			# u32
-	jg	compat_sys_preadv	# branch to system call
-
-ENTRY(compat_sys_pwritev_wrapper)
-	llgfr	%r2,%r2			# unsigned long
-	llgtr	%r3,%r3			# compat_iovec *
-	llgfr	%r4,%r4			# unsigned long
-	llgfr	%r5,%r5			# u32
-	llgfr	%r6,%r6			# u32
-	jg	compat_sys_pwritev	# branch to system call
-
 ENTRY(sys_perf_event_open_wrapper)
 	llgtr	%r2,%r2			# const struct perf_event_attr *
 	lgfr	%r3,%r3			# pid_t
diff --git a/arch/s390/kernel/dis.c b/arch/s390/kernel/dis.c
index 3ad5e95..7f4a4a8 100644
--- a/arch/s390/kernel/dis.c
+++ b/arch/s390/kernel/dis.c
@@ -1696,14 +1696,15 @@ static struct insn *find_insn(unsigned char *code)
  * insn_to_mnemonic - decode an s390 instruction
  * @instruction: instruction to decode
  * @buf: buffer to fill with mnemonic
+ * @len: length of buffer
  *
  * Decode the instruction at @instruction and store the corresponding
- * mnemonic into @buf.
+ * mnemonic into @buf of length @len.
  * @buf is left unchanged if the instruction could not be decoded.
  * Returns:
  *  %0 on success, %-ENOENT if the instruction was not found.
  */
-int insn_to_mnemonic(unsigned char *instruction, char buf[8])
+int insn_to_mnemonic(unsigned char *instruction, char *buf, unsigned int len)
 {
 	struct insn *insn;
 
@@ -1711,10 +1712,10 @@ int insn_to_mnemonic(unsigned char *instruction, char buf[8])
 	if (!insn)
 		return -ENOENT;
 	if (insn->name[0] == '\0')
-		snprintf(buf, 8, "%s",
+		snprintf(buf, len, "%s",
 			 long_insn_name[(int) insn->name[1]]);
 	else
-		snprintf(buf, 8, "%.5s", insn->name);
+		snprintf(buf, len, "%.5s", insn->name);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(insn_to_mnemonic);
diff --git a/arch/s390/kernel/dumpstack.c b/arch/s390/kernel/dumpstack.c
new file mode 100644
index 0000000..03dce39
--- /dev/null
+++ b/arch/s390/kernel/dumpstack.c
@@ -0,0 +1,236 @@
+/*
+ * Stack dumping functions
+ *
+ *  Copyright IBM Corp. 1999, 2013
+ */
+
+#include <linux/kallsyms.h>
+#include <linux/hardirq.h>
+#include <linux/kprobes.h>
+#include <linux/utsname.h>
+#include <linux/export.h>
+#include <linux/kdebug.h>
+#include <linux/ptrace.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <asm/processor.h>
+#include <asm/debug.h>
+#include <asm/ipl.h>
+
+#ifndef CONFIG_64BIT
+#define LONG "%08lx "
+#define FOURLONG "%08lx %08lx %08lx %08lx\n"
+static int kstack_depth_to_print = 12;
+#else /* CONFIG_64BIT */
+#define LONG "%016lx "
+#define FOURLONG "%016lx %016lx %016lx %016lx\n"
+static int kstack_depth_to_print = 20;
+#endif /* CONFIG_64BIT */
+
+/*
+ * For show_trace we have tree different stack to consider:
+ *   - the panic stack which is used if the kernel stack has overflown
+ *   - the asynchronous interrupt stack (cpu related)
+ *   - the synchronous kernel stack (process related)
+ * The stack trace can start at any of the three stack and can potentially
+ * touch all of them. The order is: panic stack, async stack, sync stack.
+ */
+static unsigned long
+__show_trace(unsigned long sp, unsigned long low, unsigned long high)
+{
+	struct stack_frame *sf;
+	struct pt_regs *regs;
+
+	while (1) {
+		sp = sp & PSW_ADDR_INSN;
+		if (sp < low || sp > high - sizeof(*sf))
+			return sp;
+		sf = (struct stack_frame *) sp;
+		printk("([<%016lx>] ", sf->gprs[8] & PSW_ADDR_INSN);
+		print_symbol("%s)\n", sf->gprs[8] & PSW_ADDR_INSN);
+		/* Follow the backchain. */
+		while (1) {
+			low = sp;
+			sp = sf->back_chain & PSW_ADDR_INSN;
+			if (!sp)
+				break;
+			if (sp <= low || sp > high - sizeof(*sf))
+				return sp;
+			sf = (struct stack_frame *) sp;
+			printk(" [<%016lx>] ", sf->gprs[8] & PSW_ADDR_INSN);
+			print_symbol("%s\n", sf->gprs[8] & PSW_ADDR_INSN);
+		}
+		/* Zero backchain detected, check for interrupt frame. */
+		sp = (unsigned long) (sf + 1);
+		if (sp <= low || sp > high - sizeof(*regs))
+			return sp;
+		regs = (struct pt_regs *) sp;
+		printk(" [<%016lx>] ", regs->psw.addr & PSW_ADDR_INSN);
+		print_symbol("%s\n", regs->psw.addr & PSW_ADDR_INSN);
+		low = sp;
+		sp = regs->gprs[15];
+	}
+}
+
+static void show_trace(struct task_struct *task, unsigned long *stack)
+{
+	register unsigned long __r15 asm ("15");
+	unsigned long sp;
+
+	sp = (unsigned long) stack;
+	if (!sp)
+		sp = task ? task->thread.ksp : __r15;
+	printk("Call Trace:\n");
+#ifdef CONFIG_CHECK_STACK
+	sp = __show_trace(sp, S390_lowcore.panic_stack - 4096,
+			  S390_lowcore.panic_stack);
+#endif
+	sp = __show_trace(sp, S390_lowcore.async_stack - ASYNC_SIZE,
+			  S390_lowcore.async_stack);
+	if (task)
+		__show_trace(sp, (unsigned long) task_stack_page(task),
+			     (unsigned long) task_stack_page(task) + THREAD_SIZE);
+	else
+		__show_trace(sp, S390_lowcore.thread_info,
+			     S390_lowcore.thread_info + THREAD_SIZE);
+	if (!task)
+		task = current;
+	debug_show_held_locks(task);
+}
+
+void show_stack(struct task_struct *task, unsigned long *sp)
+{
+	register unsigned long *__r15 asm ("15");
+	unsigned long *stack;
+	int i;
+
+	if (!sp)
+		stack = task ? (unsigned long *) task->thread.ksp : __r15;
+	else
+		stack = sp;
+
+	for (i = 0; i < kstack_depth_to_print; i++) {
+		if (((addr_t) stack & (THREAD_SIZE-1)) == 0)
+			break;
+		if ((i * sizeof(long) % 32) == 0)
+			printk("%s       ", i == 0 ? "" : "\n");
+		printk(LONG, *stack++);
+	}
+	printk("\n");
+	show_trace(task, sp);
+}
+
+static void show_last_breaking_event(struct pt_regs *regs)
+{
+#ifdef CONFIG_64BIT
+	printk("Last Breaking-Event-Address:\n");
+	printk(" [<%016lx>] ", regs->args[0] & PSW_ADDR_INSN);
+	print_symbol("%s\n", regs->args[0] & PSW_ADDR_INSN);
+#endif
+}
+
+/*
+ * The architecture-independent dump_stack generator
+ */
+void dump_stack(void)
+{
+	printk("CPU: %d %s %s %.*s\n",
+	       task_thread_info(current)->cpu, print_tainted(),
+	       init_utsname()->release,
+	       (int)strcspn(init_utsname()->version, " "),
+	       init_utsname()->version);
+	printk("Process %s (pid: %d, task: %p, ksp: %p)\n",
+	       current->comm, current->pid, current,
+	       (void *) current->thread.ksp);
+	show_stack(NULL, NULL);
+}
+EXPORT_SYMBOL(dump_stack);
+
+static inline int mask_bits(struct pt_regs *regs, unsigned long bits)
+{
+	return (regs->psw.mask & bits) / ((~bits + 1) & bits);
+}
+
+void show_registers(struct pt_regs *regs)
+{
+	char *mode;
+
+	mode = user_mode(regs) ? "User" : "Krnl";
+	printk("%s PSW : %p %p",
+	       mode, (void *) regs->psw.mask,
+	       (void *) regs->psw.addr);
+	print_symbol(" (%s)\n", regs->psw.addr & PSW_ADDR_INSN);
+	printk("           R:%x T:%x IO:%x EX:%x Key:%x M:%x W:%x "
+	       "P:%x AS:%x CC:%x PM:%x", mask_bits(regs, PSW_MASK_PER),
+	       mask_bits(regs, PSW_MASK_DAT), mask_bits(regs, PSW_MASK_IO),
+	       mask_bits(regs, PSW_MASK_EXT), mask_bits(regs, PSW_MASK_KEY),
+	       mask_bits(regs, PSW_MASK_MCHECK), mask_bits(regs, PSW_MASK_WAIT),
+	       mask_bits(regs, PSW_MASK_PSTATE), mask_bits(regs, PSW_MASK_ASC),
+	       mask_bits(regs, PSW_MASK_CC), mask_bits(regs, PSW_MASK_PM));
+#ifdef CONFIG_64BIT
+	printk(" EA:%x", mask_bits(regs, PSW_MASK_EA | PSW_MASK_BA));
+#endif
+	printk("\n%s GPRS: " FOURLONG, mode,
+	       regs->gprs[0], regs->gprs[1], regs->gprs[2], regs->gprs[3]);
+	printk("           " FOURLONG,
+	       regs->gprs[4], regs->gprs[5], regs->gprs[6], regs->gprs[7]);
+	printk("           " FOURLONG,
+	       regs->gprs[8], regs->gprs[9], regs->gprs[10], regs->gprs[11]);
+	printk("           " FOURLONG,
+	       regs->gprs[12], regs->gprs[13], regs->gprs[14], regs->gprs[15]);
+	show_code(regs);
+}
+
+void show_regs(struct pt_regs *regs)
+{
+	printk("CPU: %d %s %s %.*s\n",
+	       task_thread_info(current)->cpu, print_tainted(),
+	       init_utsname()->release,
+	       (int)strcspn(init_utsname()->version, " "),
+	       init_utsname()->version);
+	printk("Process %s (pid: %d, task: %p, ksp: %p)\n",
+	       current->comm, current->pid, current,
+	       (void *) current->thread.ksp);
+	show_registers(regs);
+	/* Show stack backtrace if pt_regs is from kernel mode */
+	if (!user_mode(regs))
+		show_trace(NULL, (unsigned long *) regs->gprs[15]);
+	show_last_breaking_event(regs);
+}
+
+static DEFINE_SPINLOCK(die_lock);
+
+void die(struct pt_regs *regs, const char *str)
+{
+	static int die_counter;
+
+	oops_enter();
+	lgr_info_log();
+	debug_stop_all();
+	console_verbose();
+	spin_lock_irq(&die_lock);
+	bust_spinlocks(1);
+	printk("%s: %04x [#%d] ", str, regs->int_code & 0xffff, ++die_counter);
+#ifdef CONFIG_PREEMPT
+	printk("PREEMPT ");
+#endif
+#ifdef CONFIG_SMP
+	printk("SMP ");
+#endif
+#ifdef CONFIG_DEBUG_PAGEALLOC
+	printk("DEBUG_PAGEALLOC");
+#endif
+	printk("\n");
+	notify_die(DIE_OOPS, str, regs, 0, regs->int_code & 0xffff, SIGSEGV);
+	print_modules();
+	show_regs(regs);
+	bust_spinlocks(0);
+	add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE);
+	spin_unlock_irq(&die_lock);
+	if (in_interrupt())
+		panic("Fatal exception in interrupt");
+	if (panic_on_oops)
+		panic("Fatal exception: panic_on_oops");
+	oops_exit();
+	do_exit(SIGSEGV);
+}
diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c
index 1630f43..f7fb589 100644
--- a/arch/s390/kernel/irq.c
+++ b/arch/s390/kernel/irq.c
@@ -33,7 +33,7 @@ struct irq_class {
 };
 
 /*
- * The list of "main" irq classes on s390. This is the list of interrrupts
+ * The list of "main" irq classes on s390. This is the list of interrupts
  * that appear both in /proc/stat ("intr" line) and /proc/interrupts.
  * Historically only external and I/O interrupts have been part of /proc/stat.
  * We can't add the split external and I/O sub classes since the first field
@@ -162,10 +162,8 @@ asmlinkage void do_softirq(void)
 #ifdef CONFIG_PROC_FS
 void init_irq_proc(void)
 {
-	struct proc_dir_entry *root_irq_dir;
-
-	root_irq_dir = proc_mkdir("irq", NULL);
-	create_prof_cpu_mask(root_irq_dir);
+	if (proc_mkdir("irq", NULL))
+		create_prof_cpu_mask();
 }
 #endif
 
diff --git a/arch/s390/kernel/sys_s390.c b/arch/s390/kernel/sys_s390.c
index d0964d2..23eb222 100644
--- a/arch/s390/kernel/sys_s390.c
+++ b/arch/s390/kernel/sys_s390.c
@@ -132,19 +132,9 @@ SYSCALL_DEFINE1(s390_fadvise64_64, struct fadvise64_64_args __user *, args)
  * to
  *   %r2: fd, %r3: mode, %r4/%r5: offset, 96(%r15)-103(%r15): len
  */
-SYSCALL_DEFINE(s390_fallocate)(int fd, int mode, loff_t offset,
-			       u32 len_high, u32 len_low)
+SYSCALL_DEFINE5(s390_fallocate, int, fd, int, mode, loff_t, offset,
+			       u32, len_high, u32, len_low)
 {
 	return sys_fallocate(fd, mode, offset, ((u64)len_high << 32) | len_low);
 }
-#ifdef CONFIG_HAVE_SYSCALL_WRAPPERS
-asmlinkage long SyS_s390_fallocate(long fd, long mode, loff_t offset,
-				   long len_high, long len_low)
-{
-	return SYSC_s390_fallocate((int) fd, (int) mode, offset,
-				   (u32) len_high, (u32) len_low);
-}
-SYSCALL_ALIAS(sys_s390_fallocate, SyS_s390_fallocate);
-#endif
-
 #endif
diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S
index 630b935..9f214e9 100644
--- a/arch/s390/kernel/syscalls.S
+++ b/arch/s390/kernel/syscalls.S
@@ -85,7 +85,7 @@ SYSCALL(sys_sigpending,sys_sigpending,compat_sys_sigpending_wrapper)
 SYSCALL(sys_sethostname,sys_sethostname,sys32_sethostname_wrapper)
 SYSCALL(sys_setrlimit,sys_setrlimit,compat_sys_setrlimit_wrapper)	/* 75 */
 SYSCALL(sys_old_getrlimit,sys_getrlimit,compat_sys_old_getrlimit_wrapper)
-SYSCALL(sys_getrusage,sys_getrusage,compat_sys_getrusage_wrapper)
+SYSCALL(sys_getrusage,sys_getrusage,compat_sys_getrusage)
 SYSCALL(sys_gettimeofday,sys_gettimeofday,compat_sys_gettimeofday_wrapper)
 SYSCALL(sys_settimeofday,sys_settimeofday,compat_sys_settimeofday_wrapper)
 SYSCALL(sys_getgroups16,sys_ni_syscall,sys32_getgroups16_wrapper)	/* 80 old getgroups16 syscall */
@@ -118,14 +118,14 @@ SYSCALL(sys_newstat,sys_newstat,compat_sys_newstat_wrapper)
 SYSCALL(sys_newlstat,sys_newlstat,compat_sys_newlstat_wrapper)
 SYSCALL(sys_newfstat,sys_newfstat,compat_sys_newfstat_wrapper)
 NI_SYSCALL							/* old uname syscall */
-SYSCALL(sys_lookup_dcookie,sys_lookup_dcookie,sys32_lookup_dcookie_wrapper)	/* 110 */
+SYSCALL(sys_lookup_dcookie,sys_lookup_dcookie,compat_sys_lookup_dcookie)	/* 110 */
 SYSCALL(sys_vhangup,sys_vhangup,sys_vhangup)
 NI_SYSCALL							/* old "idle" system call */
 NI_SYSCALL							/* vm86old for i386 */
 SYSCALL(sys_wait4,sys_wait4,compat_sys_wait4)
 SYSCALL(sys_swapoff,sys_swapoff,sys32_swapoff_wrapper)		/* 115 */
 SYSCALL(sys_sysinfo,sys_sysinfo,compat_sys_sysinfo_wrapper)
-SYSCALL(sys_s390_ipc,sys_s390_ipc,sys32_ipc_wrapper)
+SYSCALL(sys_s390_ipc,sys_s390_ipc,compat_sys_s390_ipc)
 SYSCALL(sys_fsync,sys_fsync,sys32_fsync_wrapper)
 SYSCALL(sys_sigreturn,sys_sigreturn,sys32_sigreturn)
 SYSCALL(sys_clone,sys_clone,sys_clone_wrapper)			/* 120 */
@@ -195,7 +195,7 @@ SYSCALL(sys_getcwd,sys_getcwd,sys32_getcwd_wrapper)
 SYSCALL(sys_capget,sys_capget,sys32_capget_wrapper)
 SYSCALL(sys_capset,sys_capset,sys32_capset_wrapper)		/* 185 */
 SYSCALL(sys_sigaltstack,sys_sigaltstack,compat_sys_sigaltstack)
-SYSCALL(sys_sendfile,sys_sendfile64,sys32_sendfile_wrapper)
+SYSCALL(sys_sendfile,sys_sendfile64,compat_sys_sendfile)
 NI_SYSCALL							/* streams1 */
 NI_SYSCALL							/* streams2 */
 SYSCALL(sys_vfork,sys_vfork,sys_vfork)				/* 190 */
@@ -231,7 +231,7 @@ SYSCALL(sys_madvise,sys_madvise,sys32_madvise_wrapper)
 SYSCALL(sys_getdents64,sys_getdents64,sys32_getdents64_wrapper)	/* 220 */
 SYSCALL(sys_fcntl64,sys_ni_syscall,compat_sys_fcntl64_wrapper)
 SYSCALL(sys_readahead,sys_readahead,sys32_readahead_wrapper)
-SYSCALL(sys_sendfile64,sys_ni_syscall,sys32_sendfile64_wrapper)
+SYSCALL(sys_sendfile64,sys_ni_syscall,compat_sys_sendfile64)
 SYSCALL(sys_setxattr,sys_setxattr,sys32_setxattr_wrapper)
 SYSCALL(sys_lsetxattr,sys_lsetxattr,sys32_lsetxattr_wrapper)	/* 225 */
 SYSCALL(sys_fsetxattr,sys_fsetxattr,sys32_fsetxattr_wrapper)
@@ -317,27 +317,27 @@ SYSCALL(sys_get_robust_list,sys_get_robust_list,compat_sys_get_robust_list)
 SYSCALL(sys_splice,sys_splice,sys_splice_wrapper)
 SYSCALL(sys_sync_file_range,sys_sync_file_range,sys_sync_file_range_wrapper)
 SYSCALL(sys_tee,sys_tee,sys_tee_wrapper)
-SYSCALL(sys_vmsplice,sys_vmsplice,compat_sys_vmsplice_wrapper)
+SYSCALL(sys_vmsplice,sys_vmsplice,compat_sys_vmsplice)
 NI_SYSCALL							/* 310 sys_move_pages */
 SYSCALL(sys_getcpu,sys_getcpu,sys_getcpu_wrapper)
-SYSCALL(sys_epoll_pwait,sys_epoll_pwait,compat_sys_epoll_pwait_wrapper)
+SYSCALL(sys_epoll_pwait,sys_epoll_pwait,compat_sys_epoll_pwait)
 SYSCALL(sys_utimes,sys_utimes,compat_sys_utimes_wrapper)
 SYSCALL(sys_s390_fallocate,sys_fallocate,sys_fallocate_wrapper)
 SYSCALL(sys_utimensat,sys_utimensat,compat_sys_utimensat_wrapper)	/* 315 */
-SYSCALL(sys_signalfd,sys_signalfd,compat_sys_signalfd_wrapper)
+SYSCALL(sys_signalfd,sys_signalfd,compat_sys_signalfd)
 NI_SYSCALL						/* 317 old sys_timer_fd */
 SYSCALL(sys_eventfd,sys_eventfd,sys_eventfd_wrapper)
 SYSCALL(sys_timerfd_create,sys_timerfd_create,sys_timerfd_create_wrapper)
 SYSCALL(sys_timerfd_settime,sys_timerfd_settime,compat_sys_timerfd_settime) /* 320 */
 SYSCALL(sys_timerfd_gettime,sys_timerfd_gettime,compat_sys_timerfd_gettime)
-SYSCALL(sys_signalfd4,sys_signalfd4,compat_sys_signalfd4_wrapper)
+SYSCALL(sys_signalfd4,sys_signalfd4,compat_sys_signalfd4)
 SYSCALL(sys_eventfd2,sys_eventfd2,sys_eventfd2_wrapper)
 SYSCALL(sys_inotify_init1,sys_inotify_init1,sys_inotify_init1_wrapper)
 SYSCALL(sys_pipe2,sys_pipe2,sys_pipe2_wrapper) /* 325 */
 SYSCALL(sys_dup3,sys_dup3,sys_dup3_wrapper)
 SYSCALL(sys_epoll_create1,sys_epoll_create1,sys_epoll_create1_wrapper)
-SYSCALL(sys_preadv,sys_preadv,compat_sys_preadv_wrapper)
-SYSCALL(sys_pwritev,sys_pwritev,compat_sys_pwritev_wrapper)
+SYSCALL(sys_preadv,sys_preadv,compat_sys_preadv)
+SYSCALL(sys_pwritev,sys_pwritev,compat_sys_pwritev)
 SYSCALL(sys_rt_tgsigqueueinfo,sys_rt_tgsigqueueinfo,compat_sys_rt_tgsigqueueinfo) /* 330 */
 SYSCALL(sys_perf_event_open,sys_perf_event_open,sys_perf_event_open_wrapper)
 SYSCALL(sys_fanotify_init,sys_fanotify_init,sys_fanotify_init_wrapper)
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
index 13dd63f..c576232 100644
--- a/arch/s390/kernel/traps.c
+++ b/arch/s390/kernel/traps.c
@@ -12,49 +12,16 @@
  * 'Traps.c' handles hardware traps and faults after we have saved some
  * state in 'asm.s'.
  */
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/errno.h>
+#include <linux/kprobes.h>
+#include <linux/kdebug.h>
+#include <linux/module.h>
 #include <linux/ptrace.h>
-#include <linux/timer.h>
+#include <linux/sched.h>
 #include <linux/mm.h>
-#include <linux/smp.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/seq_file.h>
-#include <linux/delay.h>
-#include <linux/module.h>
-#include <linux/kdebug.h>
-#include <linux/kallsyms.h>
-#include <linux/reboot.h>
-#include <linux/kprobes.h>
-#include <linux/bug.h>
-#include <linux/utsname.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <linux/atomic.h>
-#include <asm/mathemu.h>
-#include <asm/cpcmd.h>
-#include <asm/lowcore.h>
-#include <asm/debug.h>
-#include <asm/ipl.h>
 #include "entry.h"
 
 int show_unhandled_signals = 1;
 
-#define stack_pointer ({ void **sp; asm("la %0,0(15)" : "=&d" (sp)); sp; })
-
-#ifndef CONFIG_64BIT
-#define LONG "%08lx "
-#define FOURLONG "%08lx %08lx %08lx %08lx\n"
-static int kstack_depth_to_print = 12;
-#else /* CONFIG_64BIT */
-#define LONG "%016lx "
-#define FOURLONG "%016lx %016lx %016lx %016lx\n"
-static int kstack_depth_to_print = 20;
-#endif /* CONFIG_64BIT */
-
 static inline void __user *get_trap_ip(struct pt_regs *regs)
 {
 #ifdef CONFIG_64BIT
@@ -72,215 +39,6 @@ static inline void __user *get_trap_ip(struct pt_regs *regs)
 #endif
 }
 
-/*
- * For show_trace we have tree different stack to consider:
- *   - the panic stack which is used if the kernel stack has overflown
- *   - the asynchronous interrupt stack (cpu related)
- *   - the synchronous kernel stack (process related)
- * The stack trace can start at any of the three stack and can potentially
- * touch all of them. The order is: panic stack, async stack, sync stack.
- */
-static unsigned long
-__show_trace(unsigned long sp, unsigned long low, unsigned long high)
-{
-	struct stack_frame *sf;
-	struct pt_regs *regs;
-
-	while (1) {
-		sp = sp & PSW_ADDR_INSN;
-		if (sp < low || sp > high - sizeof(*sf))
-			return sp;
-		sf = (struct stack_frame *) sp;
-		printk("([<%016lx>] ", sf->gprs[8] & PSW_ADDR_INSN);
-		print_symbol("%s)\n", sf->gprs[8] & PSW_ADDR_INSN);
-		/* Follow the backchain. */
-		while (1) {
-			low = sp;
-			sp = sf->back_chain & PSW_ADDR_INSN;
-			if (!sp)
-				break;
-			if (sp <= low || sp > high - sizeof(*sf))
-				return sp;
-			sf = (struct stack_frame *) sp;
-			printk(" [<%016lx>] ", sf->gprs[8] & PSW_ADDR_INSN);
-			print_symbol("%s\n", sf->gprs[8] & PSW_ADDR_INSN);
-		}
-		/* Zero backchain detected, check for interrupt frame. */
-		sp = (unsigned long) (sf + 1);
-		if (sp <= low || sp > high - sizeof(*regs))
-			return sp;
-		regs = (struct pt_regs *) sp;
-		printk(" [<%016lx>] ", regs->psw.addr & PSW_ADDR_INSN);
-		print_symbol("%s\n", regs->psw.addr & PSW_ADDR_INSN);
-		low = sp;
-		sp = regs->gprs[15];
-	}
-}
-
-static void show_trace(struct task_struct *task, unsigned long *stack)
-{
-	register unsigned long __r15 asm ("15");
-	unsigned long sp;
-
-	sp = (unsigned long) stack;
-	if (!sp)
-		sp = task ? task->thread.ksp : __r15;
-	printk("Call Trace:\n");
-#ifdef CONFIG_CHECK_STACK
-	sp = __show_trace(sp, S390_lowcore.panic_stack - 4096,
-			  S390_lowcore.panic_stack);
-#endif
-	sp = __show_trace(sp, S390_lowcore.async_stack - ASYNC_SIZE,
-			  S390_lowcore.async_stack);
-	if (task)
-		__show_trace(sp, (unsigned long) task_stack_page(task),
-			     (unsigned long) task_stack_page(task) + THREAD_SIZE);
-	else
-		__show_trace(sp, S390_lowcore.thread_info,
-			     S390_lowcore.thread_info + THREAD_SIZE);
-	if (!task)
-		task = current;
-	debug_show_held_locks(task);
-}
-
-void show_stack(struct task_struct *task, unsigned long *sp)
-{
-	register unsigned long * __r15 asm ("15");
-	unsigned long *stack;
-	int i;
-
-	if (!sp)
-		stack = task ? (unsigned long *) task->thread.ksp : __r15;
-	else
-		stack = sp;
-
-	for (i = 0; i < kstack_depth_to_print; i++) {
-		if (((addr_t) stack & (THREAD_SIZE-1)) == 0)
-			break;
-		if ((i * sizeof(long) % 32) == 0)
-			printk("%s       ", i == 0 ? "" : "\n");
-		printk(LONG, *stack++);
-	}
-	printk("\n");
-	show_trace(task, sp);
-}
-
-static void show_last_breaking_event(struct pt_regs *regs)
-{
-#ifdef CONFIG_64BIT
-	printk("Last Breaking-Event-Address:\n");
-	printk(" [<%016lx>] ", regs->args[0] & PSW_ADDR_INSN);
-	print_symbol("%s\n", regs->args[0] & PSW_ADDR_INSN);
-#endif
-}
-
-/*
- * The architecture-independent dump_stack generator
- */
-void dump_stack(void)
-{
-	printk("CPU: %d %s %s %.*s\n",
-	       task_thread_info(current)->cpu, print_tainted(),
-	       init_utsname()->release,
-	       (int)strcspn(init_utsname()->version, " "),
-	       init_utsname()->version);
-	printk("Process %s (pid: %d, task: %p, ksp: %p)\n",
-	       current->comm, current->pid, current,
-	       (void *) current->thread.ksp);
-	show_stack(NULL, NULL);
-}
-EXPORT_SYMBOL(dump_stack);
-
-static inline int mask_bits(struct pt_regs *regs, unsigned long bits)
-{
-	return (regs->psw.mask & bits) / ((~bits + 1) & bits);
-}
-
-void show_registers(struct pt_regs *regs)
-{
-	char *mode;
-
-	mode = user_mode(regs) ? "User" : "Krnl";
-	printk("%s PSW : %p %p",
-	       mode, (void *) regs->psw.mask,
-	       (void *) regs->psw.addr);
-	print_symbol(" (%s)\n", regs->psw.addr & PSW_ADDR_INSN);
-	printk("           R:%x T:%x IO:%x EX:%x Key:%x M:%x W:%x "
-	       "P:%x AS:%x CC:%x PM:%x", mask_bits(regs, PSW_MASK_PER),
-	       mask_bits(regs, PSW_MASK_DAT), mask_bits(regs, PSW_MASK_IO),
-	       mask_bits(regs, PSW_MASK_EXT), mask_bits(regs, PSW_MASK_KEY),
-	       mask_bits(regs, PSW_MASK_MCHECK), mask_bits(regs, PSW_MASK_WAIT),
-	       mask_bits(regs, PSW_MASK_PSTATE), mask_bits(regs, PSW_MASK_ASC),
-	       mask_bits(regs, PSW_MASK_CC), mask_bits(regs, PSW_MASK_PM));
-#ifdef CONFIG_64BIT
-	printk(" EA:%x", mask_bits(regs, PSW_MASK_EA | PSW_MASK_BA));
-#endif
-	printk("\n%s GPRS: " FOURLONG, mode,
-	       regs->gprs[0], regs->gprs[1], regs->gprs[2], regs->gprs[3]);
-	printk("           " FOURLONG,
-	       regs->gprs[4], regs->gprs[5], regs->gprs[6], regs->gprs[7]);
-	printk("           " FOURLONG,
-	       regs->gprs[8], regs->gprs[9], regs->gprs[10], regs->gprs[11]);
-	printk("           " FOURLONG,
-	       regs->gprs[12], regs->gprs[13], regs->gprs[14], regs->gprs[15]);
-
-	show_code(regs);
-}	
-
-void show_regs(struct pt_regs *regs)
-{
-	printk("CPU: %d %s %s %.*s\n",
-	       task_thread_info(current)->cpu, print_tainted(),
-	       init_utsname()->release,
-	       (int)strcspn(init_utsname()->version, " "),
-	       init_utsname()->version);
-	printk("Process %s (pid: %d, task: %p, ksp: %p)\n",
-	       current->comm, current->pid, current,
-	       (void *) current->thread.ksp);
-	show_registers(regs);
-	/* Show stack backtrace if pt_regs is from kernel mode */
-	if (!user_mode(regs))
-		show_trace(NULL, (unsigned long *) regs->gprs[15]);
-	show_last_breaking_event(regs);
-}
-
-static DEFINE_SPINLOCK(die_lock);
-
-void die(struct pt_regs *regs, const char *str)
-{
-	static int die_counter;
-
-	oops_enter();
-	lgr_info_log();
-	debug_stop_all();
-	console_verbose();
-	spin_lock_irq(&die_lock);
-	bust_spinlocks(1);
-	printk("%s: %04x [#%d] ", str, regs->int_code & 0xffff, ++die_counter);
-#ifdef CONFIG_PREEMPT
-	printk("PREEMPT ");
-#endif
-#ifdef CONFIG_SMP
-	printk("SMP ");
-#endif
-#ifdef CONFIG_DEBUG_PAGEALLOC
-	printk("DEBUG_PAGEALLOC");
-#endif
-	printk("\n");
-	notify_die(DIE_OOPS, str, regs, 0, regs->int_code & 0xffff, SIGSEGV);
-	print_modules();
-	show_regs(regs);
-	bust_spinlocks(0);
-	add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE);
-	spin_unlock_irq(&die_lock);
-	if (in_interrupt())
-		panic("Fatal exception in interrupt");
-	if (panic_on_oops)
-		panic("Fatal exception: panic_on_oops");
-	oops_exit();
-	do_exit(SIGSEGV);
-}
-
 static inline void report_user_fault(struct pt_regs *regs, int signr)
 {
 	if ((task_pid_nr(current) > 1) && !show_unhandled_signals)
diff --git a/arch/s390/kvm/Kconfig b/arch/s390/kvm/Kconfig
index 60f9f8a..70b46ea 100644
--- a/arch/s390/kvm/Kconfig
+++ b/arch/s390/kvm/Kconfig
@@ -22,6 +22,7 @@ config KVM
 	select PREEMPT_NOTIFIERS
 	select ANON_INODES
 	select HAVE_KVM_CPU_RELAX_INTERCEPT
+	select HAVE_KVM_EVENTFD
 	---help---
 	  Support hosting paravirtualized guest machines using the SIE
 	  virtualization capability on the mainframe. This should work
diff --git a/arch/s390/kvm/Makefile b/arch/s390/kvm/Makefile
index 3975722..8fe9d65 100644
--- a/arch/s390/kvm/Makefile
+++ b/arch/s390/kvm/Makefile
@@ -6,7 +6,7 @@
 # it under the terms of the GNU General Public License (version 2 only)
 # as published by the Free Software Foundation.
 
-common-objs = $(addprefix ../../../virt/kvm/, kvm_main.o)
+common-objs = $(addprefix ../../../virt/kvm/, kvm_main.o eventfd.o)
 
 ccflags-y := -Ivirt/kvm -Iarch/s390/kvm
 
diff --git a/arch/s390/kvm/diag.c b/arch/s390/kvm/diag.c
index a390687..1c01a99 100644
--- a/arch/s390/kvm/diag.c
+++ b/arch/s390/kvm/diag.c
@@ -13,6 +13,7 @@
 
 #include <linux/kvm.h>
 #include <linux/kvm_host.h>
+#include <asm/virtio-ccw.h>
 #include "kvm-s390.h"
 #include "trace.h"
 #include "trace-s390.h"
@@ -104,6 +105,29 @@ static int __diag_ipl_functions(struct kvm_vcpu *vcpu)
 	return -EREMOTE;
 }
 
+static int __diag_virtio_hypercall(struct kvm_vcpu *vcpu)
+{
+	int ret, idx;
+
+	/* No virtio-ccw notification? Get out quickly. */
+	if (!vcpu->kvm->arch.css_support ||
+	    (vcpu->run->s.regs.gprs[1] != KVM_S390_VIRTIO_CCW_NOTIFY))
+		return -EOPNOTSUPP;
+
+	idx = srcu_read_lock(&vcpu->kvm->srcu);
+	/*
+	 * The layout is as follows:
+	 * - gpr 2 contains the subchannel id (passed as addr)
+	 * - gpr 3 contains the virtqueue index (passed as datamatch)
+	 */
+	ret = kvm_io_bus_write(vcpu->kvm, KVM_VIRTIO_CCW_NOTIFY_BUS,
+				vcpu->run->s.regs.gprs[2],
+				8, &vcpu->run->s.regs.gprs[3]);
+	srcu_read_unlock(&vcpu->kvm->srcu, idx);
+	/* kvm_io_bus_write returns -EOPNOTSUPP if it found no match. */
+	return ret < 0 ? ret : 0;
+}
+
 int kvm_s390_handle_diag(struct kvm_vcpu *vcpu)
 {
 	int code = (vcpu->arch.sie_block->ipb & 0xfff0000) >> 16;
@@ -118,6 +142,8 @@ int kvm_s390_handle_diag(struct kvm_vcpu *vcpu)
 		return __diag_time_slice_end_directed(vcpu);
 	case 0x308:
 		return __diag_ipl_functions(vcpu);
+	case 0x500:
+		return __diag_virtio_hypercall(vcpu);
 	default:
 		return -EOPNOTSUPP;
 	}
diff --git a/arch/s390/kvm/gaccess.h b/arch/s390/kvm/gaccess.h
index 4703f12..302e0e5 100644
--- a/arch/s390/kvm/gaccess.h
+++ b/arch/s390/kvm/gaccess.h
@@ -18,369 +18,86 @@
 #include <asm/uaccess.h>
 #include "kvm-s390.h"
 
-static inline void __user *__guestaddr_to_user(struct kvm_vcpu *vcpu,
-					       unsigned long guestaddr)
+static inline void __user *__gptr_to_uptr(struct kvm_vcpu *vcpu,
+					  void __user *gptr,
+					  int prefixing)
 {
 	unsigned long prefix  = vcpu->arch.sie_block->prefix;
-
-	if (guestaddr < 2 * PAGE_SIZE)
-		guestaddr += prefix;
-	else if ((guestaddr >= prefix) && (guestaddr < prefix + 2 * PAGE_SIZE))
-		guestaddr -= prefix;
-
-	return (void __user *) gmap_fault(guestaddr, vcpu->arch.gmap);
-}
-
-static inline int get_guest_u64(struct kvm_vcpu *vcpu, unsigned long guestaddr,
-				u64 *result)
-{
-	void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
-
-	BUG_ON(guestaddr & 7);
-
-	if (IS_ERR((void __force *) uptr))
-		return PTR_ERR((void __force *) uptr);
-
-	return get_user(*result, (unsigned long __user *) uptr);
-}
-
-static inline int get_guest_u32(struct kvm_vcpu *vcpu, unsigned long guestaddr,
-				u32 *result)
-{
-	void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
-
-	BUG_ON(guestaddr & 3);
-
-	if (IS_ERR((void __force *) uptr))
-		return PTR_ERR((void __force *) uptr);
-
-	return get_user(*result, (u32 __user *) uptr);
-}
-
-static inline int get_guest_u16(struct kvm_vcpu *vcpu, unsigned long guestaddr,
-				u16 *result)
-{
-	void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
-
-	BUG_ON(guestaddr & 1);
-
-	if (IS_ERR(uptr))
-		return PTR_ERR(uptr);
-
-	return get_user(*result, (u16 __user *) uptr);
-}
-
-static inline int get_guest_u8(struct kvm_vcpu *vcpu, unsigned long guestaddr,
-			       u8 *result)
-{
-	void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
-
-	if (IS_ERR((void __force *) uptr))
-		return PTR_ERR((void __force *) uptr);
-
-	return get_user(*result, (u8 __user *) uptr);
-}
-
-static inline int put_guest_u64(struct kvm_vcpu *vcpu, unsigned long guestaddr,
-				u64 value)
-{
-	void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
-
-	BUG_ON(guestaddr & 7);
-
-	if (IS_ERR((void __force *) uptr))
-		return PTR_ERR((void __force *) uptr);
-
-	return put_user(value, (u64 __user *) uptr);
-}
-
-static inline int put_guest_u32(struct kvm_vcpu *vcpu, unsigned long guestaddr,
-				u32 value)
-{
-	void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
-
-	BUG_ON(guestaddr & 3);
-
-	if (IS_ERR((void __force *) uptr))
-		return PTR_ERR((void __force *) uptr);
-
-	return put_user(value, (u32 __user *) uptr);
-}
-
-static inline int put_guest_u16(struct kvm_vcpu *vcpu, unsigned long guestaddr,
-				u16 value)
-{
-	void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
-
-	BUG_ON(guestaddr & 1);
-
-	if (IS_ERR((void __force *) uptr))
-		return PTR_ERR((void __force *) uptr);
-
-	return put_user(value, (u16 __user *) uptr);
-}
-
-static inline int put_guest_u8(struct kvm_vcpu *vcpu, unsigned long guestaddr,
-			       u8 value)
-{
-	void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
-
-	if (IS_ERR((void __force *) uptr))
-		return PTR_ERR((void __force *) uptr);
-
-	return put_user(value, (u8 __user *) uptr);
-}
-
-
-static inline int __copy_to_guest_slow(struct kvm_vcpu *vcpu,
-				       unsigned long guestdest,
-				       void *from, unsigned long n)
-{
-	int rc;
-	unsigned long i;
-	u8 *data = from;
-
-	for (i = 0; i < n; i++) {
-		rc = put_guest_u8(vcpu, guestdest++, *(data++));
-		if (rc < 0)
-			return rc;
+	unsigned long gaddr = (unsigned long) gptr;
+	unsigned long uaddr;
+
+	if (prefixing) {
+		if (gaddr < 2 * PAGE_SIZE)
+			gaddr += prefix;
+		else if ((gaddr >= prefix) && (gaddr < prefix + 2 * PAGE_SIZE))
+			gaddr -= prefix;
 	}
-	return 0;
-}
-
-static inline int __copy_to_guest_fast(struct kvm_vcpu *vcpu,
-				       unsigned long guestdest,
-				       void *from, unsigned long n)
-{
-	int r;
+	uaddr = gmap_fault(gaddr, vcpu->arch.gmap);
+	if (IS_ERR_VALUE(uaddr))
+		uaddr = -EFAULT;
+	return (void __user *)uaddr;
+}
+
+#define get_guest(vcpu, x, gptr)				\
+({								\
+	__typeof__(gptr) __uptr = __gptr_to_uptr(vcpu, gptr, 1);\
+	int __mask = sizeof(__typeof__(*(gptr))) - 1;		\
+	int __ret = PTR_RET((void __force *)__uptr);		\
+								\
+	if (!__ret) {						\
+		BUG_ON((unsigned long)__uptr & __mask);		\
+		__ret = get_user(x, __uptr);			\
+	}							\
+	__ret;							\
+})
+
+#define put_guest(vcpu, x, gptr)				\
+({								\
+	__typeof__(gptr) __uptr = __gptr_to_uptr(vcpu, gptr, 1);\
+	int __mask = sizeof(__typeof__(*(gptr))) - 1;		\
+	int __ret = PTR_RET((void __force *)__uptr);		\
+								\
+	if (!__ret) {						\
+		BUG_ON((unsigned long)__uptr & __mask);		\
+		__ret = put_user(x, __uptr);			\
+	}							\
+	__ret;							\
+})
+
+static inline int __copy_guest(struct kvm_vcpu *vcpu, unsigned long to,
+			       unsigned long from, unsigned long len,
+			       int to_guest, int prefixing)
+{
+	unsigned long _len, rc;
 	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,
-				void *from, unsigned long n)
-{
-	unsigned long prefix  = vcpu->arch.sie_block->prefix;
-
-	if ((guestdest < 2 * PAGE_SIZE) && (guestdest + n > 2 * PAGE_SIZE))
-		goto slowpath;
-
-	if ((guestdest < prefix) && (guestdest + n > prefix))
-		goto slowpath;
-
-	if ((guestdest < prefix + 2 * PAGE_SIZE)
-	    && (guestdest + n > prefix + 2 * PAGE_SIZE))
-		goto slowpath;
-
-	if (guestdest < 2 * PAGE_SIZE)
-		guestdest += prefix;
-	else if ((guestdest >= prefix) && (guestdest < prefix + 2 * PAGE_SIZE))
-		guestdest -= prefix;
-
-	return __copy_to_guest_fast(vcpu, guestdest, from, n);
-slowpath:
-	return __copy_to_guest_slow(vcpu, guestdest, from, n);
-}
-
-static inline int __copy_from_guest_slow(struct kvm_vcpu *vcpu, void *to,
-					 unsigned long guestsrc,
-					 unsigned long n)
-{
-	int rc;
-	unsigned long i;
-	u8 *data = to;
-
-	for (i = 0; i < n; i++) {
-		rc = get_guest_u8(vcpu, guestsrc++, data++);
-		if (rc < 0)
-			return rc;
+	while (len) {
+		uptr = to_guest ? (void __user *)to : (void __user *)from;
+		uptr = __gptr_to_uptr(vcpu, uptr, prefixing);
+		if (IS_ERR((void __force *)uptr))
+			return -EFAULT;
+		_len = PAGE_SIZE - ((unsigned long)uptr & (PAGE_SIZE - 1));
+		_len = min(_len, len);
+		if (to_guest)
+			rc = copy_to_user((void __user *) uptr, (void *)from, _len);
+		else
+			rc = copy_from_user((void *)to, (void __user *)uptr, _len);
+		if (rc)
+			return -EFAULT;
+		len -= _len;
+		from += _len;
+		to += _len;
 	}
 	return 0;
 }
 
-static inline int __copy_from_guest_fast(struct kvm_vcpu *vcpu, void *to,
-					 unsigned long guestsrc,
-					 unsigned long n)
-{
-	int r;
-	void __user *uptr;
-	unsigned long size;
-
-	if (guestsrc + n < guestsrc)
-		return -EFAULT;
-
-	/* 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 (IS_ERR((void __force *) uptr))
-			return PTR_ERR((void __force *) uptr);
-
-		r = copy_from_user(to, uptr, n);
-
-		if (r)
-			r = -EFAULT;
-
-		goto out;
-	}
-
-	/* copy first segment */
-	uptr = (void __user *)gmap_fault(guestsrc, vcpu->arch.gmap);
-
-	if (IS_ERR((void __force *) uptr))
-		return PTR_ERR((void __force *) uptr);
-
-	size = PMD_SIZE - (guestsrc & ~PMD_MASK);
-
-	r = copy_from_user(to, uptr, size);
-
-	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);
-
-		if (IS_ERR((void __force *) uptr))
-			return PTR_ERR((void __force *) uptr);
-
-		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)
-{
-	return __copy_from_guest_fast(vcpu, to, guestsrc, n);
-}
-
-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 < 2 * PAGE_SIZE) && (guestsrc + n > 2 * PAGE_SIZE))
-		goto slowpath;
+#define copy_to_guest(vcpu, to, from, size) \
+	__copy_guest(vcpu, to, (unsigned long)from, size, 1, 1)
+#define copy_from_guest(vcpu, to, from, size) \
+	__copy_guest(vcpu, (unsigned long)to, from, size, 0, 1)
+#define copy_to_guest_absolute(vcpu, to, from, size) \
+	__copy_guest(vcpu, to, (unsigned long)from, size, 1, 0)
+#define copy_from_guest_absolute(vcpu, to, from, size) \
+	__copy_guest(vcpu, (unsigned long)to, from, size, 0, 0)
 
-	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_guest_fast(vcpu, to, guestsrc, n);
-slowpath:
-	return __copy_from_guest_slow(vcpu, to, guestsrc, n);
-}
-#endif
+#endif /* __KVM_S390_GACCESS_H */
diff --git a/arch/s390/kvm/intercept.c b/arch/s390/kvm/intercept.c
index f26ff1e..c6ba4df 100644
--- a/arch/s390/kvm/intercept.c
+++ b/arch/s390/kvm/intercept.c
@@ -43,9 +43,9 @@ static int handle_lctlg(struct kvm_vcpu *vcpu)
 	trace_kvm_s390_handle_lctl(vcpu, 1, reg1, reg3, useraddr);
 
 	do {
-		rc = get_guest_u64(vcpu, useraddr,
-				   &vcpu->arch.sie_block->gcr[reg]);
-		if (rc == -EFAULT) {
+		rc = get_guest(vcpu, vcpu->arch.sie_block->gcr[reg],
+			       (u64 __user *) useraddr);
+		if (rc) {
 			kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
 			break;
 		}
@@ -78,8 +78,8 @@ static int handle_lctl(struct kvm_vcpu *vcpu)
 
 	reg = reg1;
 	do {
-		rc = get_guest_u32(vcpu, useraddr, &val);
-		if (rc == -EFAULT) {
+		rc = get_guest(vcpu, val, (u32 __user *) useraddr);
+		if (rc) {
 			kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
 			break;
 		}
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
index 37116a7..5c94817 100644
--- a/arch/s390/kvm/interrupt.c
+++ b/arch/s390/kvm/interrupt.c
@@ -180,7 +180,7 @@ static void __do_deliver_interrupt(struct kvm_vcpu *vcpu,
 				   struct kvm_s390_interrupt_info *inti)
 {
 	const unsigned short table[] = { 2, 4, 4, 6 };
-	int rc, exception = 0;
+	int rc = 0;
 
 	switch (inti->type) {
 	case KVM_S390_INT_EMERGENCY:
@@ -188,74 +188,41 @@ static void __do_deliver_interrupt(struct kvm_vcpu *vcpu,
 		vcpu->stat.deliver_emergency_signal++;
 		trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type,
 						 inti->emerg.code, 0);
-		rc = put_guest_u16(vcpu, __LC_EXT_INT_CODE, 0x1201);
-		if (rc == -EFAULT)
-			exception = 1;
-
-		rc = put_guest_u16(vcpu, __LC_EXT_CPU_ADDR, 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)
-			exception = 1;
-
-		rc = copy_from_guest(vcpu, &vcpu->arch.sie_block->gpsw,
-			__LC_EXT_NEW_PSW, sizeof(psw_t));
-		if (rc == -EFAULT)
-			exception = 1;
+		rc  = put_guest(vcpu, 0x1201, (u16 __user *)__LC_EXT_INT_CODE);
+		rc |= put_guest(vcpu, inti->emerg.code,
+				(u16 __user *)__LC_EXT_CPU_ADDR);
+		rc |= copy_to_guest(vcpu, __LC_EXT_OLD_PSW,
+				    &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
+		rc |= copy_from_guest(vcpu, &vcpu->arch.sie_block->gpsw,
+				      __LC_EXT_NEW_PSW, sizeof(psw_t));
 		break;
-
 	case KVM_S390_INT_EXTERNAL_CALL:
 		VCPU_EVENT(vcpu, 4, "%s", "interrupt: sigp ext call");
 		vcpu->stat.deliver_external_call++;
 		trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type,
 						 inti->extcall.code, 0);
-		rc = put_guest_u16(vcpu, __LC_EXT_INT_CODE, 0x1202);
-		if (rc == -EFAULT)
-			exception = 1;
-
-		rc = put_guest_u16(vcpu, __LC_EXT_CPU_ADDR, inti->extcall.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)
-			exception = 1;
-
-		rc = copy_from_guest(vcpu, &vcpu->arch.sie_block->gpsw,
-			__LC_EXT_NEW_PSW, sizeof(psw_t));
-		if (rc == -EFAULT)
-			exception = 1;
+		rc  = put_guest(vcpu, 0x1202, (u16 __user *)__LC_EXT_INT_CODE);
+		rc |= put_guest(vcpu, inti->extcall.code,
+				(u16 __user *)__LC_EXT_CPU_ADDR);
+		rc |= copy_to_guest(vcpu, __LC_EXT_OLD_PSW,
+				    &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
+		rc |= copy_from_guest(vcpu, &vcpu->arch.sie_block->gpsw,
+				      __LC_EXT_NEW_PSW, sizeof(psw_t));
 		break;
-
 	case KVM_S390_INT_SERVICE:
 		VCPU_EVENT(vcpu, 4, "interrupt: sclp parm:%x",
 			   inti->ext.ext_params);
 		vcpu->stat.deliver_service_signal++;
 		trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type,
 						 inti->ext.ext_params, 0);
-		rc = put_guest_u16(vcpu, __LC_EXT_INT_CODE, 0x2401);
-		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)
-			exception = 1;
-
-		rc = copy_from_guest(vcpu, &vcpu->arch.sie_block->gpsw,
-			__LC_EXT_NEW_PSW, sizeof(psw_t));
-		if (rc == -EFAULT)
-			exception = 1;
-
-		rc = put_guest_u32(vcpu, __LC_EXT_PARAMS, inti->ext.ext_params);
-		if (rc == -EFAULT)
-			exception = 1;
+		rc  = put_guest(vcpu, 0x2401, (u16 __user *)__LC_EXT_INT_CODE);
+		rc |= copy_to_guest(vcpu, __LC_EXT_OLD_PSW,
+				    &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
+		rc |= copy_from_guest(vcpu, &vcpu->arch.sie_block->gpsw,
+				      __LC_EXT_NEW_PSW, sizeof(psw_t));
+		rc |= put_guest(vcpu, inti->ext.ext_params,
+				(u32 __user *)__LC_EXT_PARAMS);
 		break;
-
 	case KVM_S390_INT_VIRTIO:
 		VCPU_EVENT(vcpu, 4, "interrupt: virtio parm:%x,parm64:%llx",
 			   inti->ext.ext_params, inti->ext.ext_params2);
@@ -263,34 +230,17 @@ static void __do_deliver_interrupt(struct kvm_vcpu *vcpu,
 		trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type,
 						 inti->ext.ext_params,
 						 inti->ext.ext_params2);
-		rc = put_guest_u16(vcpu, __LC_EXT_INT_CODE, 0x2603);
-		if (rc == -EFAULT)
-			exception = 1;
-
-		rc = put_guest_u16(vcpu, __LC_EXT_CPU_ADDR, 0x0d00);
-		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)
-			exception = 1;
-
-		rc = copy_from_guest(vcpu, &vcpu->arch.sie_block->gpsw,
-			__LC_EXT_NEW_PSW, sizeof(psw_t));
-		if (rc == -EFAULT)
-			exception = 1;
-
-		rc = put_guest_u32(vcpu, __LC_EXT_PARAMS, inti->ext.ext_params);
-		if (rc == -EFAULT)
-			exception = 1;
-
-		rc = put_guest_u64(vcpu, __LC_EXT_PARAMS2,
-				   inti->ext.ext_params2);
-		if (rc == -EFAULT)
-			exception = 1;
+		rc  = put_guest(vcpu, 0x2603, (u16 __user *)__LC_EXT_INT_CODE);
+		rc |= put_guest(vcpu, 0x0d00, (u16 __user *)__LC_EXT_CPU_ADDR);
+		rc |= copy_to_guest(vcpu, __LC_EXT_OLD_PSW,
+				    &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
+		rc |= copy_from_guest(vcpu, &vcpu->arch.sie_block->gpsw,
+				      __LC_EXT_NEW_PSW, sizeof(psw_t));
+		rc |= put_guest(vcpu, inti->ext.ext_params,
+				(u32 __user *)__LC_EXT_PARAMS);
+		rc |= put_guest(vcpu, inti->ext.ext_params2,
+				(u64 __user *)__LC_EXT_PARAMS2);
 		break;
-
 	case KVM_S390_SIGP_STOP:
 		VCPU_EVENT(vcpu, 4, "%s", "interrupt: cpu stop");
 		vcpu->stat.deliver_stop_signal++;
@@ -313,18 +263,14 @@ static void __do_deliver_interrupt(struct kvm_vcpu *vcpu,
 		vcpu->stat.deliver_restart_signal++;
 		trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type,
 						 0, 0);
-		rc = copy_to_guest(vcpu, offsetof(struct _lowcore,
-		  restart_old_psw), &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
-		if (rc == -EFAULT)
-			exception = 1;
-
-		rc = copy_from_guest(vcpu, &vcpu->arch.sie_block->gpsw,
-			offsetof(struct _lowcore, restart_psw), sizeof(psw_t));
-		if (rc == -EFAULT)
-			exception = 1;
+		rc  = copy_to_guest(vcpu,
+				    offsetof(struct _lowcore, restart_old_psw),
+				    &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
+		rc |= copy_from_guest(vcpu, &vcpu->arch.sie_block->gpsw,
+				      offsetof(struct _lowcore, restart_psw),
+				      sizeof(psw_t));
 		atomic_clear_mask(CPUSTAT_STOPPED, &vcpu->arch.sie_block->cpuflags);
 		break;
-
 	case KVM_S390_PROGRAM_INT:
 		VCPU_EVENT(vcpu, 4, "interrupt: pgm check code:%x, ilc:%x",
 			   inti->pgm.code,
@@ -332,24 +278,13 @@ static void __do_deliver_interrupt(struct kvm_vcpu *vcpu,
 		vcpu->stat.deliver_program_int++;
 		trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type,
 						 inti->pgm.code, 0);
-		rc = put_guest_u16(vcpu, __LC_PGM_INT_CODE, inti->pgm.code);
-		if (rc == -EFAULT)
-			exception = 1;
-
-		rc = put_guest_u16(vcpu, __LC_PGM_ILC,
-			table[vcpu->arch.sie_block->ipa >> 14]);
-		if (rc == -EFAULT)
-			exception = 1;
-
-		rc = copy_to_guest(vcpu, __LC_PGM_OLD_PSW,
-			 &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
-		if (rc == -EFAULT)
-			exception = 1;
-
-		rc = copy_from_guest(vcpu, &vcpu->arch.sie_block->gpsw,
-			__LC_PGM_NEW_PSW, sizeof(psw_t));
-		if (rc == -EFAULT)
-			exception = 1;
+		rc  = put_guest(vcpu, inti->pgm.code, (u16 __user *)__LC_PGM_INT_CODE);
+		rc |= put_guest(vcpu, table[vcpu->arch.sie_block->ipa >> 14],
+				(u16 __user *)__LC_PGM_ILC);
+		rc |= copy_to_guest(vcpu, __LC_PGM_OLD_PSW,
+				    &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
+		rc |= copy_from_guest(vcpu, &vcpu->arch.sie_block->gpsw,
+				      __LC_PGM_NEW_PSW, sizeof(psw_t));
 		break;
 
 	case KVM_S390_MCHK:
@@ -358,24 +293,13 @@ static void __do_deliver_interrupt(struct kvm_vcpu *vcpu,
 		trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type,
 						 inti->mchk.cr14,
 						 inti->mchk.mcic);
-		rc = kvm_s390_vcpu_store_status(vcpu,
-						KVM_S390_STORE_STATUS_PREFIXED);
-		if (rc == -EFAULT)
-			exception = 1;
-
-		rc = put_guest_u64(vcpu, __LC_MCCK_CODE, inti->mchk.mcic);
-		if (rc == -EFAULT)
-			exception = 1;
-
-		rc = copy_to_guest(vcpu, __LC_MCK_OLD_PSW,
-				   &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
-		if (rc == -EFAULT)
-			exception = 1;
-
-		rc = copy_from_guest(vcpu, &vcpu->arch.sie_block->gpsw,
-				     __LC_MCK_NEW_PSW, sizeof(psw_t));
-		if (rc == -EFAULT)
-			exception = 1;
+		rc  = kvm_s390_vcpu_store_status(vcpu,
+						 KVM_S390_STORE_STATUS_PREFIXED);
+		rc |= put_guest(vcpu, inti->mchk.mcic, (u64 __user *) __LC_MCCK_CODE);
+		rc |= copy_to_guest(vcpu, __LC_MCK_OLD_PSW,
+				    &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
+		rc |= copy_from_guest(vcpu, &vcpu->arch.sie_block->gpsw,
+				      __LC_MCK_NEW_PSW, sizeof(psw_t));
 		break;
 
 	case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX:
@@ -388,67 +312,44 @@ static void __do_deliver_interrupt(struct kvm_vcpu *vcpu,
 		vcpu->stat.deliver_io_int++;
 		trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type,
 						 param0, param1);
-		rc = put_guest_u16(vcpu, __LC_SUBCHANNEL_ID,
-				   inti->io.subchannel_id);
-		if (rc == -EFAULT)
-			exception = 1;
-
-		rc = put_guest_u16(vcpu, __LC_SUBCHANNEL_NR,
-				   inti->io.subchannel_nr);
-		if (rc == -EFAULT)
-			exception = 1;
-
-		rc = put_guest_u32(vcpu, __LC_IO_INT_PARM,
-				   inti->io.io_int_parm);
-		if (rc == -EFAULT)
-			exception = 1;
-
-		rc = put_guest_u32(vcpu, __LC_IO_INT_WORD,
-				   inti->io.io_int_word);
-		if (rc == -EFAULT)
-			exception = 1;
-
-		rc = copy_to_guest(vcpu, __LC_IO_OLD_PSW,
-				   &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
-		if (rc == -EFAULT)
-			exception = 1;
-
-		rc = copy_from_guest(vcpu, &vcpu->arch.sie_block->gpsw,
-				     __LC_IO_NEW_PSW, sizeof(psw_t));
-		if (rc == -EFAULT)
-			exception = 1;
+		rc  = put_guest(vcpu, inti->io.subchannel_id,
+				(u16 __user *) __LC_SUBCHANNEL_ID);
+		rc |= put_guest(vcpu, inti->io.subchannel_nr,
+				(u16 __user *) __LC_SUBCHANNEL_NR);
+		rc |= put_guest(vcpu, inti->io.io_int_parm,
+				(u32 __user *) __LC_IO_INT_PARM);
+		rc |= put_guest(vcpu, inti->io.io_int_word,
+				(u32 __user *) __LC_IO_INT_WORD);
+		rc |= copy_to_guest(vcpu, __LC_IO_OLD_PSW,
+				    &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
+		rc |= copy_from_guest(vcpu, &vcpu->arch.sie_block->gpsw,
+				      __LC_IO_NEW_PSW, sizeof(psw_t));
 		break;
 	}
 	default:
 		BUG();
 	}
-	if (exception) {
+	if (rc) {
 		printk("kvm: The guest lowcore is not mapped during interrupt "
-			"delivery, killing userspace\n");
+		       "delivery, killing userspace\n");
 		do_exit(SIGKILL);
 	}
 }
 
 static int __try_deliver_ckc_interrupt(struct kvm_vcpu *vcpu)
 {
-	int rc, exception = 0;
+	int rc;
 
 	if (psw_extint_disabled(vcpu))
 		return 0;
 	if (!(vcpu->arch.sie_block->gcr[0] & 0x800ul))
 		return 0;
-	rc = put_guest_u16(vcpu, __LC_EXT_INT_CODE, 0x1004);
-	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)
-		exception = 1;
-	rc = copy_from_guest(vcpu, &vcpu->arch.sie_block->gpsw,
-		__LC_EXT_NEW_PSW, sizeof(psw_t));
-	if (rc == -EFAULT)
-		exception = 1;
-	if (exception) {
+	rc  = put_guest(vcpu, 0x1004, (u16 __user *)__LC_EXT_INT_CODE);
+	rc |= copy_to_guest(vcpu, __LC_EXT_OLD_PSW,
+			    &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
+	rc |= copy_from_guest(vcpu, &vcpu->arch.sie_block->gpsw,
+			      __LC_EXT_NEW_PSW, sizeof(psw_t));
+	if (rc) {
 		printk("kvm: The guest lowcore is not mapped during interrupt "
 			"delivery, killing userspace\n");
 		do_exit(SIGKILL);
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index 4cf35a0..33161b4 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -142,6 +142,7 @@ int kvm_dev_ioctl_check_extension(long ext)
 	case KVM_CAP_ONE_REG:
 	case KVM_CAP_ENABLE_CAP:
 	case KVM_CAP_S390_CSS_SUPPORT:
+	case KVM_CAP_IOEVENTFD:
 		r = 1;
 		break;
 	case KVM_CAP_NR_VCPUS:
@@ -974,9 +975,8 @@ int kvm_arch_create_memslot(struct kvm_memory_slot *slot, unsigned long npages)
 /* Section: memory related */
 int kvm_arch_prepare_memory_region(struct kvm *kvm,
 				   struct kvm_memory_slot *memslot,
-				   struct kvm_memory_slot old,
 				   struct kvm_userspace_memory_region *mem,
-				   bool user_alloc)
+				   enum kvm_mr_change change)
 {
 	/* A few sanity checks. We can have exactly one memory slot which has
 	   to start at guest virtual zero and which has to be located at a
@@ -997,16 +997,13 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
 	if (mem->memory_size & 0xffffful)
 		return -EINVAL;
 
-	if (!user_alloc)
-		return -EINVAL;
-
 	return 0;
 }
 
 void kvm_arch_commit_memory_region(struct kvm *kvm,
 				struct kvm_userspace_memory_region *mem,
-				struct kvm_memory_slot old,
-				bool user_alloc)
+				const struct kvm_memory_slot *old,
+				enum kvm_mr_change change)
 {
 	int rc;
 
diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c
index 0ef9894..7db2ad0 100644
--- a/arch/s390/kvm/priv.c
+++ b/arch/s390/kvm/priv.c
@@ -14,6 +14,7 @@
 #include <linux/kvm.h>
 #include <linux/gfp.h>
 #include <linux/errno.h>
+#include <asm/asm-offsets.h>
 #include <asm/current.h>
 #include <asm/debug.h>
 #include <asm/ebcdic.h>
@@ -41,7 +42,7 @@ static int handle_set_prefix(struct kvm_vcpu *vcpu)
 	}
 
 	/* get the value */
-	if (get_guest_u32(vcpu, operand2, &address)) {
+	if (get_guest(vcpu, address, (u32 __user *) operand2)) {
 		kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
 		goto out;
 	}
@@ -82,7 +83,7 @@ static int handle_store_prefix(struct kvm_vcpu *vcpu)
 	address = address & 0x7fffe000u;
 
 	/* get the value */
-	if (put_guest_u32(vcpu, operand2, address)) {
+	if (put_guest(vcpu, address, (u32 __user *)operand2)) {
 		kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
 		goto out;
 	}
@@ -107,8 +108,8 @@ static int handle_store_cpu_address(struct kvm_vcpu *vcpu)
 		goto out;
 	}
 
-	rc = put_guest_u16(vcpu, useraddr, vcpu->vcpu_id);
-	if (rc == -EFAULT) {
+	rc = put_guest(vcpu, vcpu->vcpu_id, (u16 __user *)useraddr);
+	if (rc) {
 		kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
 		goto out;
 	}
@@ -129,39 +130,44 @@ static int handle_skey(struct kvm_vcpu *vcpu)
 
 static int handle_tpi(struct kvm_vcpu *vcpu)
 {
-	u64 addr;
 	struct kvm_s390_interrupt_info *inti;
+	u64 addr;
 	int cc;
 
 	addr = kvm_s390_get_base_disp_s(vcpu);
-
+	if (addr & 3) {
+		kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
+		goto out;
+	}
+	cc = 0;
 	inti = kvm_s390_get_io_int(vcpu->kvm, vcpu->run->s.regs.crs[6], 0);
-	if (inti) {
-		if (addr) {
-			/*
-			 * Store the two-word I/O interruption code into the
-			 * provided area.
-			 */
-			put_guest_u16(vcpu, addr, inti->io.subchannel_id);
-			put_guest_u16(vcpu, addr + 2, inti->io.subchannel_nr);
-			put_guest_u32(vcpu, addr + 4, inti->io.io_int_parm);
-		} else {
-			/*
-			 * Store the three-word I/O interruption code into
-			 * the appropriate lowcore area.
-			 */
-			put_guest_u16(vcpu, 184, inti->io.subchannel_id);
-			put_guest_u16(vcpu, 186, inti->io.subchannel_nr);
-			put_guest_u32(vcpu, 188, inti->io.io_int_parm);
-			put_guest_u32(vcpu, 192, inti->io.io_int_word);
-		}
-		cc = 1;
-	} else
-		cc = 0;
+	if (!inti)
+		goto no_interrupt;
+	cc = 1;
+	if (addr) {
+		/*
+		 * Store the two-word I/O interruption code into the
+		 * provided area.
+		 */
+		put_guest(vcpu, inti->io.subchannel_id, (u16 __user *) addr);
+		put_guest(vcpu, inti->io.subchannel_nr, (u16 __user *) (addr + 2));
+		put_guest(vcpu, inti->io.io_int_parm, (u32 __user *) (addr + 4));
+	} else {
+		/*
+		 * Store the three-word I/O interruption code into
+		 * the appropriate lowcore area.
+		 */
+		put_guest(vcpu, inti->io.subchannel_id, (u16 __user *) __LC_SUBCHANNEL_ID);
+		put_guest(vcpu, inti->io.subchannel_nr, (u16 __user *) __LC_SUBCHANNEL_NR);
+		put_guest(vcpu, inti->io.io_int_parm, (u32 __user *) __LC_IO_INT_PARM);
+		put_guest(vcpu, inti->io.io_int_word, (u32 __user *) __LC_IO_INT_WORD);
+	}
 	kfree(inti);
+no_interrupt:
 	/* Set condition code and we're done. */
 	vcpu->arch.sie_block->gpsw.mask &= ~(3ul << 44);
 	vcpu->arch.sie_block->gpsw.mask |= (cc & 3ul) << 44;
+out:
 	return 0;
 }
 
@@ -230,7 +236,7 @@ static int handle_stfl(struct kvm_vcpu *vcpu)
 
 	rc = copy_to_guest(vcpu, offsetof(struct _lowcore, stfl_fac_list),
 			   &facility_list, sizeof(facility_list));
-	if (rc == -EFAULT)
+	if (rc)
 		kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
 	else {
 		VCPU_EVENT(vcpu, 5, "store facility list value %x",
@@ -347,8 +353,8 @@ static int handle_stidp(struct kvm_vcpu *vcpu)
 		goto out;
 	}
 
-	rc = put_guest_u64(vcpu, operand2, vcpu->arch.stidp_data);
-	if (rc == -EFAULT) {
+	rc = put_guest(vcpu, vcpu->arch.stidp_data, (u64 __user *)operand2);
+	if (rc) {
 		kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
 		goto out;
 	}
@@ -575,20 +581,13 @@ static int handle_tprot(struct kvm_vcpu *vcpu)
 	if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_DAT)
 		return -EOPNOTSUPP;
 
-
-	/* we must resolve the address without holding the mmap semaphore.
-	 * This is ok since the userspace hypervisor is not supposed to change
-	 * the mapping while the guest queries the memory. Otherwise the guest
-	 * might crash or get wrong info anyway. */
-	user_address = (unsigned long) __guestaddr_to_user(vcpu, address1);
-
 	down_read(&current->mm->mmap_sem);
+	user_address = __gmap_translate(address1, vcpu->arch.gmap);
+	if (IS_ERR_VALUE(user_address))
+		goto out_inject;
 	vma = find_vma(current->mm, user_address);
-	if (!vma) {
-		up_read(&current->mm->mmap_sem);
-		return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
-	}
-
+	if (!vma)
+		goto out_inject;
 	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);
@@ -597,6 +596,10 @@ static int handle_tprot(struct kvm_vcpu *vcpu)
 
 	up_read(&current->mm->mmap_sem);
 	return 0;
+
+out_inject:
+	up_read(&current->mm->mmap_sem);
+	return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
 }
 
 int kvm_s390_handle_e5(struct kvm_vcpu *vcpu)
diff --git a/arch/s390/kvm/trace.h b/arch/s390/kvm/trace.h
index 2b29e62..c2f582bb1c 100644
--- a/arch/s390/kvm/trace.h
+++ b/arch/s390/kvm/trace.h
@@ -67,7 +67,7 @@ TRACE_EVENT(kvm_s390_sie_fault,
 #define sie_intercept_code				\
 	{0x04, "Instruction"},				\
 	{0x08, "Program interruption"},			\
-	{0x0C, "Instruction and program interuption"},	\
+	{0x0C, "Instruction and program interruption"},	\
 	{0x10, "External request"},			\
 	{0x14, "External interruption"},		\
 	{0x18, "I/O request"},				\
@@ -117,7 +117,7 @@ TRACE_EVENT(kvm_s390_intercept_instruction,
 			   __entry->instruction,
 			   insn_to_mnemonic((unsigned char *)
 					    &__entry->instruction,
-					 __entry->insn) ?
+					 __entry->insn, sizeof(__entry->insn)) ?
 			   "unknown" : __entry->insn)
 	);
 
diff --git a/arch/s390/lib/Makefile b/arch/s390/lib/Makefile
index 6ab0d0b..20b0e97 100644
--- a/arch/s390/lib/Makefile
+++ b/arch/s390/lib/Makefile
@@ -3,7 +3,6 @@
 #
 
 lib-y += delay.o string.o uaccess_std.o uaccess_pt.o
-obj-y += usercopy.o
 obj-$(CONFIG_32BIT) += div64.o qrnnd.o ucmpdi2.o mem32.o
 obj-$(CONFIG_64BIT) += mem64.o
 lib-$(CONFIG_64BIT) += uaccess_mvcos.o
diff --git a/arch/s390/lib/uaccess_pt.c b/arch/s390/lib/uaccess_pt.c
index dff631d..466fb33 100644
--- a/arch/s390/lib/uaccess_pt.c
+++ b/arch/s390/lib/uaccess_pt.c
@@ -77,42 +77,69 @@ static size_t copy_in_kernel(size_t count, void __user *to,
  * >= -4095 (IS_ERR_VALUE(x) returns true), a fault has occured and the address
  * contains the (negative) exception code.
  */
-static __always_inline unsigned long follow_table(struct mm_struct *mm,
-						  unsigned long addr, int write)
+#ifdef CONFIG_64BIT
+static unsigned long follow_table(struct mm_struct *mm,
+				  unsigned long address, int write)
 {
-	pgd_t *pgd;
-	pud_t *pud;
-	pmd_t *pmd;
-	pte_t *ptep;
+	unsigned long *table = (unsigned long *)__pa(mm->pgd);
+
+	switch (mm->context.asce_bits & _ASCE_TYPE_MASK) {
+	case _ASCE_TYPE_REGION1:
+		table = table + ((address >> 53) & 0x7ff);
+		if (unlikely(*table & _REGION_ENTRY_INV))
+			return -0x39UL;
+		table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
+	case _ASCE_TYPE_REGION2:
+		table = table + ((address >> 42) & 0x7ff);
+		if (unlikely(*table & _REGION_ENTRY_INV))
+			return -0x3aUL;
+		table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
+	case _ASCE_TYPE_REGION3:
+		table = table + ((address >> 31) & 0x7ff);
+		if (unlikely(*table & _REGION_ENTRY_INV))
+			return -0x3bUL;
+		table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
+	case _ASCE_TYPE_SEGMENT:
+		table = table + ((address >> 20) & 0x7ff);
+		if (unlikely(*table & _SEGMENT_ENTRY_INV))
+			return -0x10UL;
+		if (unlikely(*table & _SEGMENT_ENTRY_LARGE)) {
+			if (write && (*table & _SEGMENT_ENTRY_RO))
+				return -0x04UL;
+			return (*table & _SEGMENT_ENTRY_ORIGIN_LARGE) +
+				(address & ~_SEGMENT_ENTRY_ORIGIN_LARGE);
+		}
+		table = (unsigned long *)(*table & _SEGMENT_ENTRY_ORIGIN);
+	}
+	table = table + ((address >> 12) & 0xff);
+	if (unlikely(*table & _PAGE_INVALID))
+		return -0x11UL;
+	if (write && (*table & _PAGE_RO))
+		return -0x04UL;
+	return (*table & PAGE_MASK) + (address & ~PAGE_MASK);
+}
 
-	pgd = pgd_offset(mm, addr);
-	if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd)))
-		return -0x3aUL;
+#else /* CONFIG_64BIT */
 
-	pud = pud_offset(pgd, addr);
-	if (pud_none(*pud) || unlikely(pud_bad(*pud)))
-		return -0x3bUL;
+static unsigned long follow_table(struct mm_struct *mm,
+				  unsigned long address, int write)
+{
+	unsigned long *table = (unsigned long *)__pa(mm->pgd);
 
-	pmd = pmd_offset(pud, addr);
-	if (pmd_none(*pmd))
+	table = table + ((address >> 20) & 0x7ff);
+	if (unlikely(*table & _SEGMENT_ENTRY_INV))
 		return -0x10UL;
-	if (pmd_large(*pmd)) {
-		if (write && (pmd_val(*pmd) & _SEGMENT_ENTRY_RO))
-			return -0x04UL;
-		return (pmd_val(*pmd) & HPAGE_MASK) + (addr & ~HPAGE_MASK);
-	}
-	if (unlikely(pmd_bad(*pmd)))
-		return -0x10UL;
-
-	ptep = pte_offset_map(pmd, addr);
-	if (!pte_present(*ptep))
+	table = (unsigned long *)(*table & _SEGMENT_ENTRY_ORIGIN);
+	table = table + ((address >> 12) & 0xff);
+	if (unlikely(*table & _PAGE_INVALID))
 		return -0x11UL;
-	if (write && (!pte_write(*ptep) || !pte_dirty(*ptep)))
+	if (write && (*table & _PAGE_RO))
 		return -0x04UL;
-
-	return (pte_val(*ptep) & PAGE_MASK) + (addr & ~PAGE_MASK);
+	return (*table & PAGE_MASK) + (address & ~PAGE_MASK);
 }
 
+#endif /* CONFIG_64BIT */
+
 static __always_inline size_t __user_copy_pt(unsigned long uaddr, void *kptr,
 					     size_t n, int write_user)
 {
@@ -197,7 +224,7 @@ size_t copy_to_user_pt(size_t n, void __user *to, const void *from)
 
 static size_t clear_user_pt(size_t n, void __user *to)
 {
-	void *zpage = &empty_zero_page;
+	void *zpage = (void *) empty_zero_page;
 	long done, size, ret;
 
 	done = 0;
diff --git a/arch/s390/lib/usercopy.c b/arch/s390/lib/usercopy.c
deleted file mode 100644
index 14b363f..0000000
--- a/arch/s390/lib/usercopy.c
+++ /dev/null
@@ -1,8 +0,0 @@
-#include <linux/module.h>
-#include <linux/bug.h>
-
-void copy_from_user_overflow(void)
-{
-	WARN(1, "Buffer overflow detected!\n");
-}
-EXPORT_SYMBOL(copy_from_user_overflow);
diff --git a/arch/s390/mm/cmm.c b/arch/s390/mm/cmm.c
index 479e942..9d84a1f 100644
--- a/arch/s390/mm/cmm.c
+++ b/arch/s390/mm/cmm.c
@@ -458,12 +458,10 @@ static int __init cmm_init(void)
 	if (rc)
 		goto out_pm;
 	cmm_thread_ptr = kthread_run(cmm_thread, NULL, "cmmthread");
-	rc = IS_ERR(cmm_thread_ptr) ? PTR_ERR(cmm_thread_ptr) : 0;
-	if (rc)
-		goto out_kthread;
-	return 0;
+	if (!IS_ERR(cmm_thread_ptr))
+		return 0;
 
-out_kthread:
+	rc = PTR_ERR(cmm_thread_ptr);
 	unregister_pm_notifier(&cmm_power_notifier);
 out_pm:
 	unregister_oom_notifier(&cmm_oom_nb);
diff --git a/arch/s390/mm/hugetlbpage.c b/arch/s390/mm/hugetlbpage.c
index 532525e..121089d 100644
--- a/arch/s390/mm/hugetlbpage.c
+++ b/arch/s390/mm/hugetlbpage.c
@@ -39,7 +39,7 @@ int arch_prepare_hugepage(struct page *page)
 	if (!ptep)
 		return -ENOMEM;
 
-	pte = mk_pte(page, PAGE_RW);
+	pte_val(pte) = addr;
 	for (i = 0; i < PTRS_PER_PTE; i++) {
 		set_pte_at(&init_mm, addr + i * PAGE_SIZE, ptep + i, pte);
 		pte_val(pte) += PAGE_SIZE;
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c
index 49ce6bb..0b09b23 100644
--- a/arch/s390/mm/init.c
+++ b/arch/s390/mm/init.c
@@ -42,11 +42,10 @@ pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__((__aligned__(PAGE_SIZE)));
 unsigned long empty_zero_page, zero_page_mask;
 EXPORT_SYMBOL(empty_zero_page);
 
-static unsigned long __init setup_zero_pages(void)
+static void __init setup_zero_pages(void)
 {
 	struct cpuid cpu_id;
 	unsigned int order;
-	unsigned long size;
 	struct page *page;
 	int i;
 
@@ -63,10 +62,18 @@ static unsigned long __init setup_zero_pages(void)
 		break;
 	case 0x2097:	/* z10 */
 	case 0x2098:	/* z10 */
-	default:
+	case 0x2817:	/* z196 */
+	case 0x2818:	/* z196 */
 		order = 2;
 		break;
+	case 0x2827:	/* zEC12 */
+	default:
+		order = 5;
+		break;
 	}
+	/* Limit number of empty zero pages for small memory sizes */
+	if (order > 2 && totalram_pages <= 16384)
+		order = 2;
 
 	empty_zero_page = __get_free_pages(GFP_KERNEL | __GFP_ZERO, order);
 	if (!empty_zero_page)
@@ -75,14 +82,11 @@ static unsigned long __init setup_zero_pages(void)
 	page = virt_to_page((void *) empty_zero_page);
 	split_page(page, order);
 	for (i = 1 << order; i > 0; i--) {
-		SetPageReserved(page);
+		mark_page_reserved(page);
 		page++;
 	}
 
-	size = PAGE_SIZE << order;
-	zero_page_mask = (size - 1) & PAGE_MASK;
-
-	return 1UL << order;
+	zero_page_mask = ((PAGE_SIZE << order) - 1) & PAGE_MASK;
 }
 
 /*
@@ -139,7 +143,7 @@ void __init mem_init(void)
 
 	/* this will put all low memory onto the freelists */
 	totalram_pages += free_all_bootmem();
-	totalram_pages -= setup_zero_pages();	/* Setup zeroed pages. */
+	setup_zero_pages();	/* Setup zeroed pages. */
 
 	reservedpages = 0;
 
@@ -158,34 +162,15 @@ void __init mem_init(void)
 	       PFN_ALIGN((unsigned long)&_eshared) - 1);
 }
 
-void free_init_pages(char *what, unsigned long begin, unsigned long end)
-{
-	unsigned long addr = begin;
-
-	if (begin >= end)
-		return;
-	for (; addr < end; addr += PAGE_SIZE) {
-		ClearPageReserved(virt_to_page(addr));
-		init_page_count(virt_to_page(addr));
-		memset((void *)(addr & PAGE_MASK), POISON_FREE_INITMEM,
-		       PAGE_SIZE);
-		free_page(addr);
-		totalram_pages++;
-	}
-	printk(KERN_INFO "Freeing %s: %luk freed\n", what, (end - begin) >> 10);
-}
-
 void free_initmem(void)
 {
-	free_init_pages("unused kernel memory",
-			(unsigned long)&__init_begin,
-			(unsigned long)&__init_end);
+	free_initmem_default(0);
 }
 
 #ifdef CONFIG_BLK_DEV_INITRD
 void __init free_initrd_mem(unsigned long start, unsigned long end)
 {
-	free_init_pages("initrd memory", start, end);
+	free_reserved_area(start, end, POISON_FREE_INITMEM, "initrd");
 }
 #endif
 
diff --git a/arch/s390/mm/mmap.c b/arch/s390/mm/mmap.c
index 06bafec..4002329 100644
--- a/arch/s390/mm/mmap.c
+++ b/arch/s390/mm/mmap.c
@@ -91,11 +91,9 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
 	if (mmap_is_legacy()) {
 		mm->mmap_base = TASK_UNMAPPED_BASE;
 		mm->get_unmapped_area = arch_get_unmapped_area;
-		mm->unmap_area = arch_unmap_area;
 	} else {
 		mm->mmap_base = mmap_base();
 		mm->get_unmapped_area = arch_get_unmapped_area_topdown;
-		mm->unmap_area = arch_unmap_area_topdown;
 	}
 }
 
@@ -176,11 +174,9 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
 	if (mmap_is_legacy()) {
 		mm->mmap_base = TASK_UNMAPPED_BASE;
 		mm->get_unmapped_area = s390_get_unmapped_area;
-		mm->unmap_area = arch_unmap_area;
 	} else {
 		mm->mmap_base = mmap_base();
 		mm->get_unmapped_area = s390_get_unmapped_area_topdown;
-		mm->unmap_area = arch_unmap_area_topdown;
 	}
 }
 
diff --git a/arch/s390/mm/pageattr.c b/arch/s390/mm/pageattr.c
index d21040e..80adfbf 100644
--- a/arch/s390/mm/pageattr.c
+++ b/arch/s390/mm/pageattr.c
@@ -9,31 +9,25 @@
 #include <asm/pgtable.h>
 #include <asm/page.h>
 
+static inline unsigned long sske_frame(unsigned long addr, unsigned char skey)
+{
+	asm volatile(".insn rrf,0xb22b0000,%[skey],%[addr],9,0"
+		     : [addr] "+a" (addr) : [skey] "d" (skey));
+	return addr;
+}
+
 void storage_key_init_range(unsigned long start, unsigned long end)
 {
-	unsigned long boundary, function, size;
+	unsigned long boundary, size;
 
 	while (start < end) {
-		if (MACHINE_HAS_EDAT2) {
-			/* set storage keys for a 2GB frame */
-			function = 0x22000 | PAGE_DEFAULT_KEY;
-			size = 1UL << 31;
-			boundary = (start + size) & ~(size - 1);
-			if (boundary <= end) {
-				do {
-					start = pfmf(function, start);
-				} while (start < boundary);
-				continue;
-			}
-		}
 		if (MACHINE_HAS_EDAT1) {
 			/* set storage keys for a 1MB frame */
-			function = 0x21000 | PAGE_DEFAULT_KEY;
 			size = 1UL << 20;
 			boundary = (start + size) & ~(size - 1);
 			if (boundary <= end) {
 				do {
-					start = pfmf(function, start);
+					start = sske_frame(start, PAGE_DEFAULT_KEY);
 				} while (start < boundary);
 				continue;
 			}
diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c
index ae44d2a..2accf71 100644
--- a/arch/s390/mm/pgtable.c
+++ b/arch/s390/mm/pgtable.c
@@ -379,45 +379,108 @@ out_unmap:
 }
 EXPORT_SYMBOL_GPL(gmap_map_segment);
 
+static unsigned long *gmap_table_walk(unsigned long address, struct gmap *gmap)
+{
+	unsigned long *table;
+
+	table = gmap->table + ((address >> 53) & 0x7ff);
+	if (unlikely(*table & _REGION_ENTRY_INV))
+		return ERR_PTR(-EFAULT);
+	table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
+	table = table + ((address >> 42) & 0x7ff);
+	if (unlikely(*table & _REGION_ENTRY_INV))
+		return ERR_PTR(-EFAULT);
+	table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
+	table = table + ((address >> 31) & 0x7ff);
+	if (unlikely(*table & _REGION_ENTRY_INV))
+		return ERR_PTR(-EFAULT);
+	table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
+	table = table + ((address >> 20) & 0x7ff);
+	return table;
+}
+
+/**
+ * __gmap_translate - translate a guest address to a user space address
+ * @address: guest address
+ * @gmap: pointer to guest mapping meta data structure
+ *
+ * Returns user space address which corresponds to the guest address or
+ * -EFAULT if no such mapping exists.
+ * This function does not establish potentially missing page table entries.
+ * The mmap_sem of the mm that belongs to the address space must be held
+ * when this function gets called.
+ */
+unsigned long __gmap_translate(unsigned long address, struct gmap *gmap)
+{
+	unsigned long *segment_ptr, vmaddr, segment;
+	struct gmap_pgtable *mp;
+	struct page *page;
+
+	current->thread.gmap_addr = address;
+	segment_ptr = gmap_table_walk(address, gmap);
+	if (IS_ERR(segment_ptr))
+		return PTR_ERR(segment_ptr);
+	/* Convert the gmap address to an mm address. */
+	segment = *segment_ptr;
+	if (!(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;
+		return vmaddr | (address & ~PMD_MASK);
+	}
+	return -EFAULT;
+}
+EXPORT_SYMBOL_GPL(__gmap_translate);
+
+/**
+ * gmap_translate - translate a guest address to a user space address
+ * @address: guest address
+ * @gmap: pointer to guest mapping meta data structure
+ *
+ * Returns user space address which corresponds to the guest address or
+ * -EFAULT if no such mapping exists.
+ * This function does not establish potentially missing page table entries.
+ */
+unsigned long gmap_translate(unsigned long address, struct gmap *gmap)
+{
+	unsigned long rc;
+
+	down_read(&gmap->mm->mmap_sem);
+	rc = __gmap_translate(address, gmap);
+	up_read(&gmap->mm->mmap_sem);
+	return rc;
+}
+EXPORT_SYMBOL_GPL(gmap_translate);
+
 /*
  * this function is assumed to be called with mmap_sem held
  */
 unsigned long __gmap_fault(unsigned long address, struct gmap *gmap)
 {
-	unsigned long *table, vmaddr, segment;
-	struct mm_struct *mm;
+	unsigned long *segment_ptr, vmaddr, segment;
+	struct vm_area_struct *vma;
 	struct gmap_pgtable *mp;
 	struct gmap_rmap *rmap;
-	struct vm_area_struct *vma;
+	struct mm_struct *mm;
 	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))
+	segment_ptr = gmap_table_walk(address, gmap);
+	if (IS_ERR(segment_ptr))
 		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))) {
+	segment = *segment_ptr;
+	if (!(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) {
+		mm = gmap->mm;
 		vmaddr = segment & _SEGMENT_ENTRY_ORIGIN;
 		vma = find_vma(mm, vmaddr);
 		if (!vma || vma->vm_start > vmaddr)
@@ -441,12 +504,12 @@ unsigned long __gmap_fault(unsigned long address, struct gmap *gmap)
 		/* Link gmap segment table entry location to page table. */
 		page = pmd_page(*pmd);
 		mp = (struct gmap_pgtable *) page->index;
-		rmap->entry = table;
+		rmap->entry = segment_ptr;
 		spin_lock(&mm->page_table_lock);
 		list_add(&rmap->list, &mp->mapper);
 		spin_unlock(&mm->page_table_lock);
 		/* Set gmap segment table entry to page table. */
-		*table = pmd_val(*pmd) & PAGE_MASK;
+		*segment_ptr = pmd_val(*pmd) & PAGE_MASK;
 		return vmaddr | (address & ~PMD_MASK);
 	}
 	return -EFAULT;
diff --git a/arch/s390/mm/vmem.c b/arch/s390/mm/vmem.c
index ffab84d..3583705 100644
--- a/arch/s390/mm/vmem.c
+++ b/arch/s390/mm/vmem.c
@@ -191,19 +191,16 @@ static void vmem_remove_range(unsigned long start, unsigned long size)
 /*
  * Add a backed mem_map array to the virtual mem_map array.
  */
-int __meminit vmemmap_populate(struct page *start, unsigned long nr, int node)
+int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node)
 {
-	unsigned long address, start_addr, end_addr;
+	unsigned long address = start;
 	pgd_t *pg_dir;
 	pud_t *pu_dir;
 	pmd_t *pm_dir;
 	pte_t *pt_dir;
 	int ret = -ENOMEM;
 
-	start_addr = (unsigned long) start;
-	end_addr = (unsigned long) (start + nr);
-
-	for (address = start_addr; address < end_addr;) {
+	for (address = start; address < end;) {
 		pg_dir = pgd_offset_k(address);
 		if (pgd_none(*pg_dir)) {
 			pu_dir = vmem_pud_alloc();
@@ -262,14 +259,14 @@ int __meminit vmemmap_populate(struct page *start, unsigned long nr, int node)
 		}
 		address += PAGE_SIZE;
 	}
-	memset(start, 0, nr * sizeof(struct page));
+	memset((void *)start, 0, end - start);
 	ret = 0;
 out:
-	flush_tlb_kernel_range(start_addr, end_addr);
+	flush_tlb_kernel_range(start, end);
 	return ret;
 }
 
-void vmemmap_free(struct page *memmap, unsigned long nr_pages)
+void vmemmap_free(unsigned long start, unsigned long end)
 {
 }
 
diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c
index 0972e91..82f165f 100644
--- a/arch/s390/net/bpf_jit_comp.c
+++ b/arch/s390/net/bpf_jit_comp.c
@@ -747,10 +747,9 @@ void bpf_jit_compile(struct sk_filter *fp)
 
 	if (!bpf_jit_enable)
 		return;
-	addrs = kmalloc(fp->len * sizeof(*addrs), GFP_KERNEL);
+	addrs = kcalloc(fp->len, sizeof(*addrs), GFP_KERNEL);
 	if (addrs == NULL)
 		return;
-	memset(addrs, 0, fp->len * sizeof(*addrs));
 	memset(&jit, 0, sizeof(cjit));
 	memset(&cjit, 0, sizeof(cjit));
 
diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c
index 27b4c17..fddf847 100644
--- a/arch/s390/pci/pci.c
+++ b/arch/s390/pci/pci.c
@@ -249,10 +249,9 @@ int zpci_fmb_enable_device(struct zpci_dev *zdev)
 	if (zdev->fmb)
 		return -EINVAL;
 
-	zdev->fmb = kmem_cache_alloc(zdev_fmb_cache, GFP_KERNEL);
+	zdev->fmb = kmem_cache_zalloc(zdev_fmb_cache, GFP_KERNEL);
 	if (!zdev->fmb)
 		return -ENOMEM;
-	memset(zdev->fmb, 0, sizeof(*zdev->fmb));
 	WARN_ON((u64) zdev->fmb & 0xf);
 
 	args.fmb_addr = virt_to_phys(zdev->fmb);
diff --git a/arch/score/mm/init.c b/arch/score/mm/init.c
index cee6bce..1592aad 100644
--- a/arch/score/mm/init.c
+++ b/arch/score/mm/init.c
@@ -43,7 +43,7 @@ EXPORT_SYMBOL_GPL(empty_zero_page);
 
 static struct kcore_list kcore_mem, kcore_vmalloc;
 
-static unsigned long setup_zero_page(void)
+static void setup_zero_page(void)
 {
 	struct page *page;
 
@@ -52,9 +52,7 @@ static unsigned long setup_zero_page(void)
 		panic("Oh boy, that early out of memory?");
 
 	page = virt_to_page((void *) empty_zero_page);
-	SetPageReserved(page);
-
-	return 1UL;
+	mark_page_reserved(page);
 }
 
 #ifndef CONFIG_NEED_MULTIPLE_NODES
@@ -84,7 +82,7 @@ void __init mem_init(void)
 
 	high_memory = (void *) __va(max_low_pfn << PAGE_SHIFT);
 	totalram_pages += free_all_bootmem();
-	totalram_pages -= setup_zero_page();	/* Setup zeroed pages. */
+	setup_zero_page();	/* Setup zeroed pages. */
 	reservedpages = 0;
 
 	for (tmp = 0; tmp < max_low_pfn; tmp++)
@@ -109,37 +107,16 @@ void __init mem_init(void)
 }
 #endif /* !CONFIG_NEED_MULTIPLE_NODES */
 
-static void free_init_pages(const char *what, unsigned long begin, unsigned long end)
-{
-	unsigned long pfn;
-
-	for (pfn = PFN_UP(begin); pfn < PFN_DOWN(end); pfn++) {
-		struct page *page = pfn_to_page(pfn);
-		void *addr = phys_to_virt(PFN_PHYS(pfn));
-
-		ClearPageReserved(page);
-		init_page_count(page);
-		memset(addr, POISON_FREE_INITMEM, PAGE_SIZE);
-		__free_page(page);
-		totalram_pages++;
-	}
-	printk(KERN_INFO "Freeing %s: %ldk freed\n", what, (end - begin) >> 10);
-}
-
 #ifdef CONFIG_BLK_DEV_INITRD
 void free_initrd_mem(unsigned long start, unsigned long end)
 {
-	free_init_pages("initrd memory",
-		virt_to_phys((void *) start),
-		virt_to_phys((void *) end));
+	free_reserved_area(start, end, POISON_FREE_INITMEM, "initrd");
 }
 #endif
 
 void __init_refok free_initmem(void)
 {
-	free_init_pages("unused kernel memory",
-	__pa(&__init_begin),
-	__pa(&__init_end));
+	free_initmem_default(POISON_FREE_INITMEM);
 }
 
 unsigned long pgd_current;
diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c
index aaff767..764530c 100644
--- a/arch/sh/boards/mach-ecovec24/setup.c
+++ b/arch/sh/boards/mach-ecovec24/setup.c
@@ -254,11 +254,13 @@ static int usbhs_get_id(struct platform_device *pdev)
 	return gpio_get_value(GPIO_PTB3);
 }
 
-static void usbhs_phy_reset(struct platform_device *pdev)
+static int usbhs_phy_reset(struct platform_device *pdev)
 {
 	/* enable vbus if HOST */
 	if (!gpio_get_value(GPIO_PTB3))
 		gpio_set_value(GPIO_PTB5, 1);
+
+	return 0;
 }
 
 static struct renesas_usbhs_platform_info usbhs_info = {
diff --git a/arch/sh/boards/mach-sdk7786/Makefile b/arch/sh/boards/mach-sdk7786/Makefile
index 8ae56e9..45d32e3 100644
--- a/arch/sh/boards/mach-sdk7786/Makefile
+++ b/arch/sh/boards/mach-sdk7786/Makefile
@@ -1,4 +1,4 @@
 obj-y	:= fpga.o irq.o nmi.o setup.o
 
-obj-$(CONFIG_GENERIC_GPIO)	+= gpio.o
+obj-$(CONFIG_GPIOLIB)		+= gpio.o
 obj-$(CONFIG_HAVE_SRAM_POOL)	+= sram.o
diff --git a/arch/sh/boards/mach-x3proto/Makefile b/arch/sh/boards/mach-x3proto/Makefile
index 708c21c..0cbe3d0 100644
--- a/arch/sh/boards/mach-x3proto/Makefile
+++ b/arch/sh/boards/mach-x3proto/Makefile
@@ -1,3 +1,3 @@
 obj-y += setup.o ilsel.o
 
-obj-$(CONFIG_GENERIC_GPIO)	+= gpio.o
+obj-$(CONFIG_GPIOLIB)		+= gpio.o
diff --git a/arch/sh/drivers/pci/pcie-sh7786.c b/arch/sh/drivers/pci/pcie-sh7786.c
index c2c85f6..a162a7f 100644
--- a/arch/sh/drivers/pci/pcie-sh7786.c
+++ b/arch/sh/drivers/pci/pcie-sh7786.c
@@ -35,7 +35,7 @@ static unsigned int nr_ports;
 
 static struct sh7786_pcie_hwops {
 	int (*core_init)(void);
-	async_func_ptr *port_init_hw;
+	async_func_t port_init_hw;
 } *sh7786_pcie_hwops;
 
 static struct resource sh7786_pci0_resources[] = {
diff --git a/arch/sh/include/asm/hugetlb.h b/arch/sh/include/asm/hugetlb.h
index b3808c7..699255d 100644
--- a/arch/sh/include/asm/hugetlb.h
+++ b/arch/sh/include/asm/hugetlb.h
@@ -3,6 +3,7 @@
 
 #include <asm/cacheflush.h>
 #include <asm/page.h>
+#include <asm-generic/hugetlb.h>
 
 
 static inline int is_hugepage_only_range(struct mm_struct *mm,
diff --git a/arch/sh/include/asm/hw_breakpoint.h b/arch/sh/include/asm/hw_breakpoint.h
index ec9ad59..01a3869 100644
--- a/arch/sh/include/asm/hw_breakpoint.h
+++ b/arch/sh/include/asm/hw_breakpoint.h
@@ -7,6 +7,7 @@
 
 #include <linux/kdebug.h>
 #include <linux/types.h>
+#include <cpu/ubc.h>
 
 struct arch_hw_breakpoint {
 	char		*name; /* Contains name of the symbol to set bkpt */
@@ -15,17 +16,6 @@ struct arch_hw_breakpoint {
 	u16		type;
 };
 
-enum {
-	SH_BREAKPOINT_READ	= (1 << 1),
-	SH_BREAKPOINT_WRITE	= (1 << 2),
-	SH_BREAKPOINT_RW	= SH_BREAKPOINT_READ | SH_BREAKPOINT_WRITE,
-
-	SH_BREAKPOINT_LEN_1	= (1 << 12),
-	SH_BREAKPOINT_LEN_2	= (1 << 13),
-	SH_BREAKPOINT_LEN_4	= SH_BREAKPOINT_LEN_1 | SH_BREAKPOINT_LEN_2,
-	SH_BREAKPOINT_LEN_8	= (1 << 14),
-};
-
 struct sh_ubc {
 	const char	*name;
 	unsigned int	num_events;
diff --git a/arch/sh/include/asm/unistd.h b/arch/sh/include/asm/unistd.h
index 5e90fa2..e77816c 100644
--- a/arch/sh/include/asm/unistd.h
+++ b/arch/sh/include/asm/unistd.h
@@ -30,12 +30,4 @@
 # define __ARCH_WANT_SYS_VFORK
 # define __ARCH_WANT_SYS_CLONE
 
-/*
- * "Conditional" syscalls
- *
- * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
- * but it doesn't work on all toolchains, so we just do it by hand
- */
-# define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
-
 #include <uapi/asm/unistd.h>
diff --git a/arch/sh/include/cpu-common/cpu/ubc.h b/arch/sh/include/cpu-common/cpu/ubc.h
new file mode 100644
index 0000000..b604619
--- /dev/null
+++ b/arch/sh/include/cpu-common/cpu/ubc.h
@@ -0,0 +1,17 @@
+#ifndef __ARCH_SH_CPU_UBC_H__
+#define __ARCH_SH_CPU_UBC_H__
+
+enum {
+	SH_BREAKPOINT_READ	= (1 << 1),
+	SH_BREAKPOINT_WRITE	= (1 << 2),
+	SH_BREAKPOINT_RW	= SH_BREAKPOINT_READ | SH_BREAKPOINT_WRITE,
+
+	SH_BREAKPOINT_LEN_1	= (1 << 12),
+	SH_BREAKPOINT_LEN_2	= (1 << 13),
+	SH_BREAKPOINT_LEN_4	= SH_BREAKPOINT_LEN_1 | SH_BREAKPOINT_LEN_2,
+	SH_BREAKPOINT_LEN_8	= (1 << 14),
+};
+
+#define UBC_64BIT	1
+
+#endif /* __ARCH_SH_CPU_UBC_H__ */
diff --git a/arch/sh/include/cpu-sh2a/cpu/ubc.h b/arch/sh/include/cpu-sh2a/cpu/ubc.h
new file mode 100644
index 0000000..3371f90
--- /dev/null
+++ b/arch/sh/include/cpu-sh2a/cpu/ubc.h
@@ -0,0 +1,14 @@
+#ifndef __ARCH_SH_CPU_UBC_H__
+#define __ARCH_SH_CPU_UBC_H__
+
+enum {
+	SH_BREAKPOINT_READ	= (1 << 2),
+	SH_BREAKPOINT_WRITE	= (1 << 3),
+	SH_BREAKPOINT_RW	= SH_BREAKPOINT_READ | SH_BREAKPOINT_WRITE,
+
+	SH_BREAKPOINT_LEN_1	= (1 << 0),
+	SH_BREAKPOINT_LEN_2	= (1 << 1),
+	SH_BREAKPOINT_LEN_4	= SH_BREAKPOINT_LEN_1 | SH_BREAKPOINT_LEN_2,
+};
+
+#endif /* __ARCH_SH_CPU_UBC_H__ */
diff --git a/arch/sh/kernel/cpu/sh2a/Makefile b/arch/sh/kernel/cpu/sh2a/Makefile
index 7fdc102..92f0da4 100644
--- a/arch/sh/kernel/cpu/sh2a/Makefile
+++ b/arch/sh/kernel/cpu/sh2a/Makefile
@@ -21,4 +21,5 @@ pinmux-$(CONFIG_CPU_SUBTYPE_SH7203)	:= pinmux-sh7203.o
 pinmux-$(CONFIG_CPU_SUBTYPE_SH7264)	:= pinmux-sh7264.o
 pinmux-$(CONFIG_CPU_SUBTYPE_SH7269)	:= pinmux-sh7269.o
 
-obj-$(CONFIG_GENERIC_GPIO)	+= $(pinmux-y)
+obj-$(CONFIG_GPIOLIB)			+= $(pinmux-y)
+obj-$(CONFIG_HAVE_HW_BREAKPOINT)	+= ubc.o
diff --git a/arch/sh/kernel/cpu/sh2a/pinmux-sh7203.c b/arch/sh/kernel/cpu/sh2a/pinmux-sh7203.c
index 96c6c26..eef17dc 100644
--- a/arch/sh/kernel/cpu/sh2a/pinmux-sh7203.c
+++ b/arch/sh/kernel/cpu/sh2a/pinmux-sh7203.c
@@ -8,12 +8,23 @@
  * for more details.
  */
 
+#include <linux/bug.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/ioport.h>
 #include <cpu/pfc.h>
 
+static struct resource sh7203_pfc_resources[] = {
+	[0] = {
+		.start	= 0xfffe3800,
+		.end	= 0xfffe3a9f,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
 static int __init plat_pinmux_setup(void)
 {
-	return sh_pfc_register("pfc-sh7203", NULL, 0);
+	return sh_pfc_register("pfc-sh7203", sh7203_pfc_resources,
+			       ARRAY_SIZE(sh7203_pfc_resources));
 }
 arch_initcall(plat_pinmux_setup);
diff --git a/arch/sh/kernel/cpu/sh2a/pinmux-sh7264.c b/arch/sh/kernel/cpu/sh2a/pinmux-sh7264.c
index b1b7c1b..569decb 100644
--- a/arch/sh/kernel/cpu/sh2a/pinmux-sh7264.c
+++ b/arch/sh/kernel/cpu/sh2a/pinmux-sh7264.c
@@ -8,12 +8,23 @@
  * for more details.
  */
 
+#include <linux/bug.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/ioport.h>
 #include <cpu/pfc.h>
 
+static struct resource sh7264_pfc_resources[] = {
+	[0] = {
+		.start	= 0xfffe3800,
+		.end	= 0xfffe393f,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
 static int __init plat_pinmux_setup(void)
 {
-	return sh_pfc_register("pfc-sh7264", NULL, 0);
+	return sh_pfc_register("pfc-sh7264", sh7264_pfc_resources,
+			       ARRAY_SIZE(sh7264_pfc_resources));
 }
 arch_initcall(plat_pinmux_setup);
diff --git a/arch/sh/kernel/cpu/sh2a/pinmux-sh7269.c b/arch/sh/kernel/cpu/sh2a/pinmux-sh7269.c
index dc2a868..4c17fb6 100644
--- a/arch/sh/kernel/cpu/sh2a/pinmux-sh7269.c
+++ b/arch/sh/kernel/cpu/sh2a/pinmux-sh7269.c
@@ -9,12 +9,23 @@
  * for more details.
  */
 
+#include <linux/bug.h>
 #include <linux/init.h>
+#include <linux/ioport.h>
 #include <linux/kernel.h>
 #include <cpu/pfc.h>
 
+static struct resource sh7269_pfc_resources[] = {
+	[0] = {
+		.start	= 0xfffe3800,
+		.end	= 0xfffe391f,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
 static int __init plat_pinmux_setup(void)
 {
-	return sh_pfc_register("pfc-sh7269", NULL, 0);
+	return sh_pfc_register("pfc-sh7269", sh7269_pfc_resources,
+			       ARRAY_SIZE(sh7269_pfc_resources));
 }
 arch_initcall(plat_pinmux_setup);
diff --git a/arch/sh/kernel/cpu/sh2a/ubc.c b/arch/sh/kernel/cpu/sh2a/ubc.c
new file mode 100644
index 0000000..ef95a9b
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh2a/ubc.c
@@ -0,0 +1,154 @@
+/*
+ * arch/sh/kernel/cpu/sh2a/ubc.c
+ *
+ * On-chip UBC support for SH-2A CPUs.
+ *
+ * Copyright (C) 2009 - 2010  Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <asm/hw_breakpoint.h>
+
+#define UBC_BAR(idx)	(0xfffc0400 + (0x10 * idx))
+#define UBC_BAMR(idx)	(0xfffc0404 + (0x10 * idx))
+#define UBC_BBR(idx)	(0xfffc04A0 + (0x10 * idx))
+#define UBC_BDR(idx)	(0xfffc0408 + (0x10 * idx))
+#define UBC_BDMR(idx)	(0xfffc040C + (0x10 * idx))
+
+#define UBC_BRCR	0xfffc04C0
+
+/* BBR */
+#define UBC_BBR_UBID	(1 << 13)     /* User Break Interrupt Disable */
+#define UBC_BBR_DBE	(1 << 12)     /* Data Break Enable */
+#define UBC_BBR_CD_C	(1 << 6)      /* C Bus Cycle */
+#define UBC_BBR_CD_I	(2 << 6)      /* I Bus Cycle */
+#define UBC_BBR_ID_I	(1 << 4)      /* Break Condition is instruction fetch cycle */
+#define UBC_BBR_ID_D	(2 << 4)      /* Break Condition is data access cycle */
+#define UBC_BBR_ID_ID	(3 << 4)      /* Break Condition is instruction fetch or data access cycle */
+
+#define UBC_CRR_BIE	(1 << 0)
+
+/* CBR */
+#define UBC_CBR_CE	(1 << 0)
+
+static struct sh_ubc sh2a_ubc;
+
+static void sh2a_ubc_enable(struct arch_hw_breakpoint *info, int idx)
+{
+	__raw_writel(UBC_BBR_DBE | UBC_BBR_CD_C | UBC_BBR_ID_ID |
+		     info->len | info->type, UBC_BBR(idx));
+	__raw_writel(info->address, UBC_BAR(idx));
+}
+
+static void sh2a_ubc_disable(struct arch_hw_breakpoint *info, int idx)
+{
+	__raw_writel(UBC_BBR_UBID, UBC_BBR(idx));
+	__raw_writel(0, UBC_BAR(idx));
+}
+
+static void sh2a_ubc_enable_all(unsigned long mask)
+{
+	int i;
+
+	for (i = 0; i < sh2a_ubc.num_events; i++)
+		if (mask & (1 << i))
+			__raw_writel(__raw_readl(UBC_BBR(i)) & ~UBC_BBR_UBID,
+				     UBC_BBR(i));
+}
+
+static void sh2a_ubc_disable_all(void)
+{
+	int i;
+	
+	for (i = 0; i < sh2a_ubc.num_events; i++)
+		__raw_writel(__raw_readl(UBC_BBR(i)) | UBC_BBR_UBID,
+			     UBC_BBR(i));
+}
+
+static unsigned long sh2a_ubc_active_mask(void)
+{
+	unsigned long active = 0;
+	int i;
+
+	for (i = 0; i < sh2a_ubc.num_events; i++)
+		if (!(__raw_readl(UBC_BBR(i)) & UBC_BBR_UBID))
+			active |= (1 << i);
+
+	return active;
+}
+
+static unsigned long sh2a_ubc_triggered_mask(void)
+{
+	unsigned int ret, mask;
+	
+	mask = 0;
+	ret = __raw_readl(UBC_BRCR);
+	if ((ret & (1 << 15)) || (ret & (1 << 13))) {
+		mask |= (1 << 0); /* Match condition for channel 0 */
+	} else 
+		mask &= ~(1 << 0);
+	
+	if ((ret & (1 << 14)) || (ret & (1 << 12))) {
+		mask |= (1 << 1); /* Match condition for channel 1 */
+	} else 
+		mask &= ~(1 << 1);
+
+	return mask;
+}
+
+static void sh2a_ubc_clear_triggered_mask(unsigned long mask)
+{
+	if (mask & (1 << 0)) /* Channel 0 statisfied break condition */
+		__raw_writel(__raw_readl(UBC_BRCR) &
+			     ~((1 << 15) | (1 << 13)), UBC_BRCR);
+	
+	if (mask & (1 << 1)) /* Channel 1 statisfied break condition */
+		__raw_writel(__raw_readl(UBC_BRCR) &
+			     ~((1 << 14) | (1 << 12)), UBC_BRCR);
+}
+
+static struct sh_ubc sh2a_ubc = {
+	.name			= "SH-2A",
+	.num_events		= 2,
+	.trap_nr		= 0x1e0,
+	.enable			= sh2a_ubc_enable,
+	.disable		= sh2a_ubc_disable,
+	.enable_all		= sh2a_ubc_enable_all,
+	.disable_all		= sh2a_ubc_disable_all,
+	.active_mask		= sh2a_ubc_active_mask,
+	.triggered_mask		= sh2a_ubc_triggered_mask,
+	.clear_triggered_mask	= sh2a_ubc_clear_triggered_mask,
+};
+
+static int __init sh2a_ubc_init(void)
+{
+	struct clk *ubc_iclk = clk_get(NULL, "ubc0");
+	int i;
+
+	/*
+	 * The UBC MSTP bit is optional, as not all platforms will have
+	 * it. Just ignore it if we can't find it.
+	 */
+	if (IS_ERR(ubc_iclk))
+		ubc_iclk = NULL;
+
+	clk_enable(ubc_iclk);
+
+	for (i = 0; i < sh2a_ubc.num_events; i++) {
+		__raw_writel(0, UBC_BAMR(i));
+		__raw_writel(0, UBC_BBR(i));
+	}
+
+	clk_disable(ubc_iclk);
+
+	sh2a_ubc.clk = ubc_iclk;
+
+	return register_sh_ubc(&sh2a_ubc);
+}
+arch_initcall(sh2a_ubc_init);
diff --git a/arch/sh/kernel/cpu/sh3/Makefile b/arch/sh/kernel/cpu/sh3/Makefile
index 6f13f33..d3634ae 100644
--- a/arch/sh/kernel/cpu/sh3/Makefile
+++ b/arch/sh/kernel/cpu/sh3/Makefile
@@ -30,4 +30,4 @@ clock-$(CONFIG_CPU_SUBTYPE_SH7712)	:= clock-sh7712.o
 pinmux-$(CONFIG_CPU_SUBTYPE_SH7720)	:= pinmux-sh7720.o
 
 obj-y	+= $(clock-y)
-obj-$(CONFIG_GENERIC_GPIO)	+= $(pinmux-y)
+obj-$(CONFIG_GPIOLIB)			+= $(pinmux-y)
diff --git a/arch/sh/kernel/cpu/sh3/pinmux-sh7720.c b/arch/sh/kernel/cpu/sh3/pinmux-sh7720.c
index 7d3744a..26e90a6 100644
--- a/arch/sh/kernel/cpu/sh3/pinmux-sh7720.c
+++ b/arch/sh/kernel/cpu/sh3/pinmux-sh7720.c
@@ -8,13 +8,23 @@
  * for more details.
  */
 
+#include <linux/bug.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/ioport.h>
 #include <cpu/pfc.h>
 
+static struct resource sh7720_pfc_resources[] = {
+	[0] = {
+		.start	= 0xa4050100,
+		.end	= 0xa405016f,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
 static int __init plat_pinmux_setup(void)
 {
-	return sh_pfc_register("pfc-sh7720", NULL, 0);
+	return sh_pfc_register("pfc-sh7720", sh7720_pfc_resources,
+			       ARRAY_SIZE(sh7720_pfc_resources));
 }
-
 arch_initcall(plat_pinmux_setup);
diff --git a/arch/sh/kernel/cpu/sh4a/Makefile b/arch/sh/kernel/cpu/sh4a/Makefile
index 8fc6ec2..0705df7 100644
--- a/arch/sh/kernel/cpu/sh4a/Makefile
+++ b/arch/sh/kernel/cpu/sh4a/Makefile
@@ -47,6 +47,6 @@ pinmux-$(CONFIG_CPU_SUBTYPE_SHX3)	:= pinmux-shx3.o
 
 obj-y					+= $(clock-y)
 obj-$(CONFIG_SMP)			+= $(smp-y)
-obj-$(CONFIG_GENERIC_GPIO)		+= $(pinmux-y)
+obj-$(CONFIG_GPIOLIB)			+= $(pinmux-y)
 obj-$(CONFIG_PERF_EVENTS)		+= perf_event.o
 obj-$(CONFIG_HAVE_HW_BREAKPOINT)	+= ubc.o
diff --git a/arch/sh/kernel/cpu/sh4a/pinmux-sh7722.c b/arch/sh/kernel/cpu/sh4a/pinmux-sh7722.c
index d9bcc42..271bbc8 100644
--- a/arch/sh/kernel/cpu/sh4a/pinmux-sh7722.c
+++ b/arch/sh/kernel/cpu/sh4a/pinmux-sh7722.c
@@ -1,10 +1,20 @@
+#include <linux/bug.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/ioport.h>
 #include <cpu/pfc.h>
 
+static struct resource sh7722_pfc_resources[] = {
+	[0] = {
+		.start	= 0xa4050100,
+		.end	= 0xa405018f,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
 static int __init plat_pinmux_setup(void)
 {
-	return sh_pfc_register("pfc-sh7722", NULL, 0);
+	return sh_pfc_register("pfc-sh7722", sh7722_pfc_resources,
+			       ARRAY_SIZE(sh7722_pfc_resources));
 }
-
 arch_initcall(plat_pinmux_setup);
diff --git a/arch/sh/kernel/cpu/sh4a/pinmux-sh7723.c b/arch/sh/kernel/cpu/sh4a/pinmux-sh7723.c
index bcec7ad..99c637d 100644
--- a/arch/sh/kernel/cpu/sh4a/pinmux-sh7723.c
+++ b/arch/sh/kernel/cpu/sh4a/pinmux-sh7723.c
@@ -8,13 +8,23 @@
  * for more details.
  */
 
+#include <linux/bug.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/ioport.h>
 #include <cpu/pfc.h>
 
+static struct resource sh7723_pfc_resources[] = {
+	[0] = {
+		.start	= 0xa4050100,
+		.end	= 0xa405016f,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
 static int __init plat_pinmux_setup(void)
 {
-	return sh_pfc_register("pfc-sh7723", NULL, 0);
+	return sh_pfc_register("pfc-sh7723", sh7723_pfc_resources,
+			       ARRAY_SIZE(sh7723_pfc_resources));
 }
-
 arch_initcall(plat_pinmux_setup);
diff --git a/arch/sh/kernel/cpu/sh4a/pinmux-sh7724.c b/arch/sh/kernel/cpu/sh4a/pinmux-sh7724.c
index 5c3541d..63be474 100644
--- a/arch/sh/kernel/cpu/sh4a/pinmux-sh7724.c
+++ b/arch/sh/kernel/cpu/sh4a/pinmux-sh7724.c
@@ -13,12 +13,23 @@
  * for more details.
  */
 
+#include <linux/bug.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/ioport.h>
 #include <cpu/pfc.h>
 
+static struct resource sh7724_pfc_resources[] = {
+	[0] = {
+		.start	= 0xa4050100,
+		.end	= 0xa405016f,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
 static int __init plat_pinmux_setup(void)
 {
-	return sh_pfc_register("pfc-sh7724", NULL, 0);
+	return sh_pfc_register("pfc-sh7724", sh7724_pfc_resources,
+			       ARRAY_SIZE(sh7724_pfc_resources));
 }
 arch_initcall(plat_pinmux_setup);
diff --git a/arch/sh/kernel/cpu/sh4a/pinmux-sh7757.c b/arch/sh/kernel/cpu/sh4a/pinmux-sh7757.c
index cda6bd1..567745d 100644
--- a/arch/sh/kernel/cpu/sh4a/pinmux-sh7757.c
+++ b/arch/sh/kernel/cpu/sh4a/pinmux-sh7757.c
@@ -13,12 +13,23 @@
  * for more details.
  */
 
+#include <linux/bug.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/ioport.h>
 #include <cpu/pfc.h>
 
+static struct resource sh7757_pfc_resources[] = {
+	[0] = {
+		.start	= 0xffec0000,
+		.end	= 0xffec008f,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
 static int __init plat_pinmux_setup(void)
 {
-	return sh_pfc_register("pfc-sh7757", NULL, 0);
+	return sh_pfc_register("pfc-sh7757", sh7757_pfc_resources,
+			       ARRAY_SIZE(sh7757_pfc_resources));
 }
 arch_initcall(plat_pinmux_setup);
diff --git a/arch/sh/kernel/cpu/sh4a/pinmux-sh7785.c b/arch/sh/kernel/cpu/sh4a/pinmux-sh7785.c
index 01055b8..e336ab8 100644
--- a/arch/sh/kernel/cpu/sh4a/pinmux-sh7785.c
+++ b/arch/sh/kernel/cpu/sh4a/pinmux-sh7785.c
@@ -8,13 +8,23 @@
  * for more details.
  */
 
+#include <linux/bug.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/ioport.h>
 #include <cpu/pfc.h>
 
+static struct resource sh7785_pfc_resources[] = {
+	[0] = {
+		.start	= 0xffe70000,
+		.end	= 0xffe7008f,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
 static int __init plat_pinmux_setup(void)
 {
-	return sh_pfc_register("pfc-sh7785", NULL, 0);
+	return sh_pfc_register("pfc-sh7785", sh7785_pfc_resources,
+			       ARRAY_SIZE(sh7785_pfc_resources));
 }
-
 arch_initcall(plat_pinmux_setup);
diff --git a/arch/sh/kernel/cpu/sh4a/pinmux-sh7786.c b/arch/sh/kernel/cpu/sh4a/pinmux-sh7786.c
index 3061778..9a45955 100644
--- a/arch/sh/kernel/cpu/sh4a/pinmux-sh7786.c
+++ b/arch/sh/kernel/cpu/sh4a/pinmux-sh7786.c
@@ -13,13 +13,23 @@
  * for more details.
  */
 
+#include <linux/bug.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/ioport.h>
 #include <cpu/pfc.h>
 
+static struct resource sh7786_pfc_resources[] = {
+	[0] = {
+		.start	= 0xffcc0000,
+		.end	= 0xffcc008f,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
 static int __init plat_pinmux_setup(void)
 {
-	return sh_pfc_register("pfc-sh7786", NULL, 0);
+	return sh_pfc_register("pfc-sh7786", sh7786_pfc_resources,
+			       ARRAY_SIZE(sh7786_pfc_resources));
 }
-
 arch_initcall(plat_pinmux_setup);
diff --git a/arch/sh/kernel/cpu/sh4a/pinmux-shx3.c b/arch/sh/kernel/cpu/sh4a/pinmux-shx3.c
index ace84ac..444bf25 100644
--- a/arch/sh/kernel/cpu/sh4a/pinmux-shx3.c
+++ b/arch/sh/kernel/cpu/sh4a/pinmux-shx3.c
@@ -7,12 +7,23 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  */
+#include <linux/bug.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/ioport.h>
 #include <cpu/pfc.h>
 
-static int __init shx3_pinmux_setup(void)
+static struct resource shx3_pfc_resources[] = {
+	[0] = {
+		.start	= 0xffc70000,
+		.end	= 0xffc7001f,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static int __init plat_pinmux_setup(void)
 {
-	return sh_pfc_register("pfc-shx3", NULL, 0);
+	return sh_pfc_register("pfc-shx3", shx3_pfc_resources,
+			       ARRAY_SIZE(shx3_pfc_resources));
 }
-arch_initcall(shx3_pinmux_setup);
+arch_initcall(plat_pinmux_setup);
diff --git a/arch/sh/kernel/cpufreq.c b/arch/sh/kernel/cpufreq.c
index e68b45b..88c8fee 100644
--- a/arch/sh/kernel/cpufreq.c
+++ b/arch/sh/kernel/cpufreq.c
@@ -51,9 +51,6 @@ static int sh_cpufreq_target(struct cpufreq_policy *policy,
 	struct device *dev;
 	long freq;
 
-	if (!cpu_online(cpu))
-		return -ENODEV;
-
 	cpus_allowed = current->cpus_allowed;
 	set_cpus_allowed_ptr(current, cpumask_of(cpu));
 
@@ -69,15 +66,14 @@ static int sh_cpufreq_target(struct cpufreq_policy *policy,
 
 	dev_dbg(dev, "requested frequency %u Hz\n", target_freq * 1000);
 
-	freqs.cpu	= cpu;
 	freqs.old	= sh_cpufreq_get(cpu);
 	freqs.new	= (freq + 500) / 1000;
 	freqs.flags	= 0;
 
-	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
 	set_cpus_allowed_ptr(current, &cpus_allowed);
 	clk_set_rate(cpuclk, freq);
-	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
 
 	dev_dbg(dev, "set frequency %lu Hz\n", freq);
 
@@ -112,9 +108,6 @@ static int sh_cpufreq_cpu_init(struct cpufreq_policy *policy)
 	struct cpufreq_frequency_table *freq_table;
 	struct device *dev;
 
-	if (!cpu_online(cpu))
-		return -ENODEV;
-
 	dev = get_cpu_device(cpu);
 
 	cpuclk = clk_get(dev, "cpu_clk");
@@ -123,7 +116,7 @@ static int sh_cpufreq_cpu_init(struct cpufreq_policy *policy)
 		return PTR_ERR(cpuclk);
 	}
 
-	policy->cur = policy->min = policy->max = sh_cpufreq_get(cpu);
+	policy->cur = sh_cpufreq_get(cpu);
 
 	freq_table = cpuclk->nr_freqs ? cpuclk->freq_table : NULL;
 	if (freq_table) {
@@ -136,15 +129,12 @@ static int sh_cpufreq_cpu_init(struct cpufreq_policy *policy)
 		dev_notice(dev, "no frequency table found, falling back "
 			   "to rate rounding.\n");
 
-		policy->cpuinfo.min_freq =
+		policy->min = policy->cpuinfo.min_freq =
 			(clk_round_rate(cpuclk, 1) + 500) / 1000;
-		policy->cpuinfo.max_freq =
+		policy->max = policy->cpuinfo.max_freq =
 			(clk_round_rate(cpuclk, ~0UL) + 500) / 1000;
 	}
 
-	policy->min = policy->cpuinfo.min_freq;
-	policy->max = policy->cpuinfo.max_freq;
-
 	policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
 
 	dev_info(dev, "CPU Frequencies - Minimum %u.%03u MHz, "
diff --git a/arch/sh/kernel/hw_breakpoint.c b/arch/sh/kernel/hw_breakpoint.c
index f917376..ac4922a 100644
--- a/arch/sh/kernel/hw_breakpoint.c
+++ b/arch/sh/kernel/hw_breakpoint.c
@@ -113,9 +113,11 @@ static int get_hbp_len(u16 hbp_len)
 	case SH_BREAKPOINT_LEN_4:
 		len_in_bytes = 4;
 		break;
+#ifdef UBC_64BIT
 	case SH_BREAKPOINT_LEN_8:
 		len_in_bytes = 8;
 		break;
+#endif
 	}
 	return len_in_bytes;
 }
@@ -149,9 +151,11 @@ int arch_bp_generic_fields(int sh_len, int sh_type,
 	case SH_BREAKPOINT_LEN_4:
 		*gen_len = HW_BREAKPOINT_LEN_4;
 		break;
+#ifdef UBC_64BIT
 	case SH_BREAKPOINT_LEN_8:
 		*gen_len = HW_BREAKPOINT_LEN_8;
 		break;
+#endif
 	default:
 		return -EINVAL;
 	}
@@ -190,9 +194,11 @@ static int arch_build_bp_info(struct perf_event *bp)
 	case HW_BREAKPOINT_LEN_4:
 		info->len = SH_BREAKPOINT_LEN_4;
 		break;
+#ifdef UBC_64BIT
 	case HW_BREAKPOINT_LEN_8:
 		info->len = SH_BREAKPOINT_LEN_8;
 		break;
+#endif
 	default:
 		return -EINVAL;
 	}
@@ -240,9 +246,11 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp)
 	case SH_BREAKPOINT_LEN_4:
 		align = 3;
 		break;
+#ifdef UBC_64BIT
 	case SH_BREAKPOINT_LEN_8:
 		align = 7;
 		break;
+#endif
 	default:
 		return ret;
 	}
diff --git a/arch/sh/kernel/sh_bios.c b/arch/sh/kernel/sh_bios.c
index 47475cc..a5b51b9 100644
--- a/arch/sh/kernel/sh_bios.c
+++ b/arch/sh/kernel/sh_bios.c
@@ -144,8 +144,6 @@ static struct console bios_console = {
 	.index		= -1,
 };
 
-static struct console *early_console;
-
 static int __init setup_early_printk(char *buf)
 {
 	int keep_early = 0;
diff --git a/arch/sh/mm/alignment.c b/arch/sh/mm/alignment.c
index aea1485..ec2b253 100644
--- a/arch/sh/mm/alignment.c
+++ b/arch/sh/mm/alignment.c
@@ -140,7 +140,7 @@ static int alignment_proc_open(struct inode *inode, struct file *file)
 static ssize_t alignment_proc_write(struct file *file,
 		const char __user *buffer, size_t count, loff_t *pos)
 {
-	int *data = PDE(file_inode(file))->data;
+	int *data = PDE_DATA(file_inode(file));
 	char mode;
 
 	if (count > 0) {
diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c
index 1057940..20f9ead 100644
--- a/arch/sh/mm/init.c
+++ b/arch/sh/mm/init.c
@@ -417,15 +417,13 @@ void __init mem_init(void)
 
 	for_each_online_node(nid) {
 		pg_data_t *pgdat = NODE_DATA(nid);
-		unsigned long node_pages = 0;
 		void *node_high_memory;
 
 		num_physpages += pgdat->node_present_pages;
 
 		if (pgdat->node_spanned_pages)
-			node_pages = free_all_bootmem_node(pgdat);
+			totalram_pages += free_all_bootmem_node(pgdat);
 
-		totalram_pages += node_pages;
 
 		node_high_memory = (void *)__va((pgdat->node_start_pfn +
 						 pgdat->node_spanned_pages) <<
@@ -501,31 +499,13 @@ void __init mem_init(void)
 
 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("Freeing unused kernel memory: %ldk freed\n",
-	       ((unsigned long)&__init_end -
-	        (unsigned long)&__init_begin) >> 10);
+	free_initmem_default(0);
 }
 
 #ifdef CONFIG_BLK_DEV_INITRD
 void free_initrd_mem(unsigned long start, unsigned long end)
 {
-	unsigned long p;
-	for (p = start; p < end; p += PAGE_SIZE) {
-		ClearPageReserved(virt_to_page(p));
-		init_page_count(virt_to_page(p));
-		free_page(p);
-		totalram_pages++;
-	}
-	printk("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
+	free_reserved_area(start, end, 0, "initrd");
 }
 #endif
 
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 3d361f2..91cf75d 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -62,7 +62,6 @@ config SPARC64
 	select HAVE_RCU_TABLE_FREE if SMP
 	select HAVE_MEMBLOCK
 	select HAVE_MEMBLOCK_NODE_MAP
-	select HAVE_SYSCALL_WRAPPERS
 	select HAVE_ARCH_TRANSPARENT_HUGEPAGE
 	select HAVE_DYNAMIC_FTRACE
 	select HAVE_FTRACE_MCOUNT_RECORD
@@ -100,6 +99,9 @@ config HAVE_LATENCYTOP_SUPPORT
 	bool
 	default y if SPARC64
 
+config ARCH_HIBERNATION_POSSIBLE
+	def_bool y if SPARC64
+
 config AUDIT_ARCH
 	bool
 	default y
@@ -327,6 +329,10 @@ config ARCH_SPARSEMEM_DEFAULT
 
 source "mm/Kconfig"
 
+if SPARC64
+source "kernel/power/Kconfig"
+endif
+
 config SCHED_SMT
 	bool "SMT (Hyperthreading) scheduler support"
 	depends on SPARC64 && SMP
@@ -494,7 +500,18 @@ config LEON_PCI
 	depends on PCI && SPARC_LEON
 	default y
 
-config GRPCI2
+config SPARC_GRPCI1
+	bool "GRPCI Host Bridge Support"
+	depends on LEON_PCI
+	default y
+	help
+	  Say Y here to include the GRPCI Host Bridge Driver. The GRPCI
+	  PCI host controller is typically found in GRLIB SPARC32/LEON
+	  systems. The driver has one property (all_pci_errors) controlled
+	  from the bootloader that makes the GRPCI to generate interrupts
+	  on detected PCI Parity and System errors.
+
+config SPARC_GRPCI2
 	bool "GRPCI2 Host Bridge Support"
 	depends on LEON_PCI
 	default y
diff --git a/arch/sparc/Makefile b/arch/sparc/Makefile
index 541b8b0..9ff4236 100644
--- a/arch/sparc/Makefile
+++ b/arch/sparc/Makefile
@@ -57,6 +57,7 @@ core-y                 += arch/sparc/
 libs-y                 += arch/sparc/prom/
 libs-y                 += arch/sparc/lib/
 
+drivers-$(CONFIG_PM) += arch/sparc/power/
 drivers-$(CONFIG_OPROFILE)	+= arch/sparc/oprofile/
 
 boot := arch/sparc/boot
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild
index e26d430..ff18e3c 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -2,11 +2,16 @@
 
 
 generic-y += clkdev.h
+generic-y += cputime.h
 generic-y += div64.h
+generic-y += emergency-restart.h
 generic-y += exec.h
 generic-y += local64.h
+generic-y += mutex.h
 generic-y += irq_regs.h
 generic-y += local.h
 generic-y += module.h
+generic-y += serial.h
 generic-y += trace_clock.h
+generic-y += types.h
 generic-y += word-at-a-time.h
diff --git a/arch/sparc/include/asm/cmpxchg_64.h b/arch/sparc/include/asm/cmpxchg_64.h
index b30eb37..4adefe8 100644
--- a/arch/sparc/include/asm/cmpxchg_64.h
+++ b/arch/sparc/include/asm/cmpxchg_64.h
@@ -141,5 +141,6 @@ static inline unsigned long __cmpxchg_local(volatile void *ptr,
 	BUILD_BUG_ON(sizeof(*(ptr)) != 8);				\
 	cmpxchg_local((ptr), (o), (n));					\
   })
+#define cmpxchg64(ptr, o, n)	cmpxchg64_local((ptr), (o), (n))
 
 #endif /* __ARCH_SPARC64_CMPXCHG__ */
diff --git a/arch/sparc/include/asm/cputime.h b/arch/sparc/include/asm/cputime.h
deleted file mode 100644
index 1a642b8..0000000
--- a/arch/sparc/include/asm/cputime.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __SPARC_CPUTIME_H
-#define __SPARC_CPUTIME_H
-
-#include <asm-generic/cputime.h>
-
-#endif /* __SPARC_CPUTIME_H */
diff --git a/arch/sparc/include/asm/emergency-restart.h b/arch/sparc/include/asm/emergency-restart.h
deleted file mode 100644
index 108d8c4..0000000
--- a/arch/sparc/include/asm/emergency-restart.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_EMERGENCY_RESTART_H
-#define _ASM_EMERGENCY_RESTART_H
-
-#include <asm-generic/emergency-restart.h>
-
-#endif /* _ASM_EMERGENCY_RESTART_H */
diff --git a/arch/sparc/include/asm/hibernate.h b/arch/sparc/include/asm/hibernate.h
new file mode 100644
index 0000000..2ec34f8
--- /dev/null
+++ b/arch/sparc/include/asm/hibernate.h
@@ -0,0 +1,23 @@
+/*
+ * hibernate.h:  Hibernaton support specific for sparc64.
+ *
+ * Copyright (C) 2013 Kirill V Tkhai (tkhai@yandex.ru)
+ */
+
+#ifndef ___SPARC_HIBERNATE_H
+#define ___SPARC_HIBERNATE_H
+
+struct saved_context {
+	unsigned long fp;
+	unsigned long cwp;
+	unsigned long wstate;
+
+	unsigned long tick;
+	unsigned long pstate;
+
+	unsigned long g4;
+	unsigned long g5;
+	unsigned long g6;
+};
+
+#endif
diff --git a/arch/sparc/include/asm/hugetlb.h b/arch/sparc/include/asm/hugetlb.h
index 7eb57d2..e4cab46 100644
--- a/arch/sparc/include/asm/hugetlb.h
+++ b/arch/sparc/include/asm/hugetlb.h
@@ -2,6 +2,7 @@
 #define _ASM_SPARC64_HUGETLB_H
 
 #include <asm/page.h>
+#include <asm-generic/hugetlb.h>
 
 
 void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
diff --git a/arch/sparc/include/asm/leon_pci.h b/arch/sparc/include/asm/leon_pci.h
index f48527e..bfd3ab3 100644
--- a/arch/sparc/include/asm/leon_pci.h
+++ b/arch/sparc/include/asm/leon_pci.h
@@ -12,6 +12,7 @@ struct leon_pci_info {
 	struct pci_ops *ops;
 	struct resource	io_space;
 	struct resource	mem_space;
+	struct resource	busn;
 	int (*map_irq)(const struct pci_dev *dev, u8 slot, u8 pin);
 };
 
diff --git a/arch/sparc/include/asm/mutex.h b/arch/sparc/include/asm/mutex.h
deleted file mode 100644
index 458c1f7..0000000
--- a/arch/sparc/include/asm/mutex.h
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
- * 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/sparc/include/asm/processor_64.h b/arch/sparc/include/asm/processor_64.h
index cce72ce..4c3f7f0 100644
--- a/arch/sparc/include/asm/processor_64.h
+++ b/arch/sparc/include/asm/processor_64.h
@@ -18,9 +18,6 @@
 #include <asm/ptrace.h>
 #include <asm/page.h>
 
-/* Don't hold the runqueue lock over context switch */
-#define __ARCH_WANT_UNLOCKED_CTXSW
-
 /* The sparc has no problems with write protection */
 #define wp_works_ok 1
 #define wp_works_ok__is_a_macro /* for versions in ksyms.c */
diff --git a/arch/sparc/include/asm/serial.h b/arch/sparc/include/asm/serial.h
deleted file mode 100644
index f90d61c..0000000
--- a/arch/sparc/include/asm/serial.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __SPARC_SERIAL_H
-#define __SPARC_SERIAL_H
-
-#define BASE_BAUD ( 1843200 / 16 )
-
-#endif /* __SPARC_SERIAL_H */
diff --git a/arch/sparc/include/asm/smp_32.h b/arch/sparc/include/asm/smp_32.h
index b73da3c..3c8917f 100644
--- a/arch/sparc/include/asm/smp_32.h
+++ b/arch/sparc/include/asm/smp_32.h
@@ -36,7 +36,6 @@ typedef void (*smpfunc_t)(unsigned long, unsigned long, unsigned long,
 		       unsigned long, unsigned long);
 
 void cpu_panic(void);
-extern void smp4m_irq_rotate(int cpu);
 
 /*
  *	General functions that each host system must provide.
@@ -46,7 +45,6 @@ void sun4m_init_smp(void);
 void sun4d_init_smp(void);
 
 void smp_callin(void);
-void smp_boot_cpus(void);
 void smp_store_cpu_info(int);
 
 void smp_resched_interrupt(void);
@@ -107,9 +105,6 @@ extern int hard_smp_processor_id(void);
 
 #define raw_smp_processor_id()		(current_thread_info()->cpu)
 
-#define prof_multiplier(__cpu)		cpu_data(__cpu).multiplier
-#define prof_counter(__cpu)		cpu_data(__cpu).counter
-
 void smp_setup_cpu_possible_map(void);
 
 #endif /* !(__ASSEMBLY__) */
diff --git a/arch/sparc/include/asm/unistd.h b/arch/sparc/include/asm/unistd.h
index 5356810..dfa53fd 100644
--- a/arch/sparc/include/asm/unistd.h
+++ b/arch/sparc/include/asm/unistd.h
@@ -45,12 +45,4 @@
 #define __ARCH_WANT_COMPAT_SYS_SENDFILE
 #endif
 
-/*
- * "Conditional" syscalls
- *
- * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
- * but it doesn't work on all toolchains, so we just do it by hand
- */
-#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
-
 #endif /* _SPARC_UNISTD_H */
diff --git a/arch/sparc/include/uapi/asm/Kbuild b/arch/sparc/include/uapi/asm/Kbuild
index ce175af..b5843ee 100644
--- a/arch/sparc/include/uapi/asm/Kbuild
+++ b/arch/sparc/include/uapi/asm/Kbuild
@@ -44,7 +44,6 @@ header-y += swab.h
 header-y += termbits.h
 header-y += termios.h
 header-y += traps.h
-header-y += types.h
 header-y += uctx.h
 header-y += unistd.h
 header-y += utrap.h
diff --git a/arch/sparc/include/uapi/asm/socket.h b/arch/sparc/include/uapi/asm/socket.h
index cbbad74..89f49b6 100644
--- a/arch/sparc/include/uapi/asm/socket.h
+++ b/arch/sparc/include/uapi/asm/socket.h
@@ -68,6 +68,8 @@
 
 #define SO_LOCK_FILTER		0x0028
 
+#define SO_SELECT_ERR_QUEUE	0x0029
+
 /* Security levels - as per NRL IPv6 - don't actually do anything */
 #define SO_SECURITY_AUTHENTICATION		0x5001
 #define SO_SECURITY_ENCRYPTION_TRANSPORT	0x5002
diff --git a/arch/sparc/include/uapi/asm/types.h b/arch/sparc/include/uapi/asm/types.h
deleted file mode 100644
index 383d156..0000000
--- a/arch/sparc/include/uapi/asm/types.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef _SPARC_TYPES_H
-#define _SPARC_TYPES_H
-/*
- * This file is never included by application software unless
- * explicitly requested (e.g., via linux/types.h) in which case the
- * application is Linux specific so (user-) name space pollution is
- * not a major issue.  However, for interoperability, libraries still
- * need to be careful to avoid a name clashes.
- */
-
-#if defined(__sparc__)
-
-#include <asm-generic/int-ll64.h>
-
-#endif /* defined(__sparc__) */
-
-#endif /* defined(_SPARC_TYPES_H) */
diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile
index 6cf591b..d2936d0 100644
--- a/arch/sparc/kernel/Makefile
+++ b/arch/sparc/kernel/Makefile
@@ -74,7 +74,8 @@ obj-y                     += dma.o
 
 obj-$(CONFIG_PCIC_PCI)    += pcic.o
 obj-$(CONFIG_LEON_PCI)    += leon_pci.o
-obj-$(CONFIG_GRPCI2)      += leon_pci_grpci2.o
+obj-$(CONFIG_SPARC_GRPCI2)+= leon_pci_grpci2.o
+obj-$(CONFIG_SPARC_GRPCI1)+= leon_pci_grpci1.o
 
 obj-$(CONFIG_SMP)         += trampoline_$(BITS).o smp_$(BITS).o
 obj-$(CONFIG_SPARC32_SMP) += sun4m_smp.o sun4d_smp.o leon_smp.o
diff --git a/arch/sparc/kernel/asm-offsets.c b/arch/sparc/kernel/asm-offsets.c
index 68f7e11..961b87f 100644
--- a/arch/sparc/kernel/asm-offsets.c
+++ b/arch/sparc/kernel/asm-offsets.c
@@ -14,6 +14,8 @@
 // #include <linux/mm.h>
 #include <linux/kbuild.h>
 
+#include <asm/hibernate.h>
+
 #ifdef CONFIG_SPARC32
 int sparc32_foo(void)
 {
@@ -24,6 +26,19 @@ int sparc32_foo(void)
 #else
 int sparc64_foo(void)
 {
+#ifdef CONFIG_HIBERNATION
+	BLANK();
+	OFFSET(SC_REG_FP, saved_context, fp);
+	OFFSET(SC_REG_CWP, saved_context, cwp);
+	OFFSET(SC_REG_WSTATE, saved_context, wstate);
+
+	OFFSET(SC_REG_TICK, saved_context, tick);
+	OFFSET(SC_REG_PSTATE, saved_context, pstate);
+
+	OFFSET(SC_REG_G4, saved_context, g4);
+	OFFSET(SC_REG_G5, saved_context, g5);
+	OFFSET(SC_REG_G6, saved_context, g6);
+#endif
 	return 0;
 }
 #endif
diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c
index 0f094db..2096468 100644
--- a/arch/sparc/kernel/ioport.c
+++ b/arch/sparc/kernel/ioport.c
@@ -693,7 +693,7 @@ static int sparc_io_proc_show(struct seq_file *m, void *v)
 
 static int sparc_io_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, sparc_io_proc_show, PDE(inode)->data);
+	return single_open(file, sparc_io_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations sparc_io_proc_fops = {
diff --git a/arch/sparc/kernel/leon_pci.c b/arch/sparc/kernel/leon_pci.c
index 852dc84..88aaaa5 100644
--- a/arch/sparc/kernel/leon_pci.c
+++ b/arch/sparc/kernel/leon_pci.c
@@ -29,6 +29,8 @@ void leon_pci_init(struct platform_device *ofdev, struct leon_pci_info *info)
 	pci_add_resource_offset(&resources, &info->io_space,
 				info->io_space.start - 0x1000);
 	pci_add_resource(&resources, &info->mem_space);
+	info->busn.flags = IORESOURCE_BUS;
+	pci_add_resource(&resources, &info->busn);
 
 	root_bus = pci_scan_root_bus(&ofdev->dev, 0, info->ops, info,
 				     &resources);
diff --git a/arch/sparc/kernel/leon_pci_grpci1.c b/arch/sparc/kernel/leon_pci_grpci1.c
new file mode 100644
index 0000000..7739a54
--- /dev/null
+++ b/arch/sparc/kernel/leon_pci_grpci1.c
@@ -0,0 +1,724 @@
+/*
+ * leon_pci_grpci1.c: GRPCI1 Host PCI driver
+ *
+ * Copyright (C) 2013 Aeroflex Gaisler AB
+ *
+ * This GRPCI1 driver does not support PCI interrupts taken from
+ * GPIO pins. Interrupt generation at PCI parity and system error
+ * detection is by default turned off since some GRPCI1 cores does
+ * not support detection. It can be turned on from the bootloader
+ * using the all_pci_errors property.
+ *
+ * Contributors: Daniel Hellstrom <daniel@gaisler.com>
+ */
+
+#include <linux/of_device.h>
+#include <linux/export.h>
+#include <linux/kernel.h>
+#include <linux/of_irq.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+
+#include <asm/leon_pci.h>
+#include <asm/sections.h>
+#include <asm/vaddrs.h>
+#include <asm/leon.h>
+#include <asm/io.h>
+
+#include "irq.h"
+
+/* Enable/Disable Debugging Configuration Space Access */
+#undef GRPCI1_DEBUG_CFGACCESS
+
+/*
+ * GRPCI1 APB Register MAP
+ */
+struct grpci1_regs {
+	unsigned int cfg_stat;		/* 0x00 Configuration / Status */
+	unsigned int bar0;		/* 0x04 BAR0 (RO) */
+	unsigned int page0;		/* 0x08 PAGE0 (RO) */
+	unsigned int bar1;		/* 0x0C BAR1 (RO) */
+	unsigned int page1;		/* 0x10 PAGE1 */
+	unsigned int iomap;		/* 0x14 IO Map */
+	unsigned int stat_cmd;		/* 0x18 PCI Status & Command (RO) */
+	unsigned int irq;		/* 0x1C Interrupt register */
+};
+
+#define REGLOAD(a)	(be32_to_cpu(__raw_readl(&(a))))
+#define REGSTORE(a, v)	(__raw_writel(cpu_to_be32(v), &(a)))
+
+#define PAGE0_BTEN_BIT    0
+#define PAGE0_BTEN        (1 << PAGE0_BTEN_BIT)
+
+#define CFGSTAT_HOST_BIT  13
+#define CFGSTAT_CTO_BIT   8
+#define CFGSTAT_HOST      (1 << CFGSTAT_HOST_BIT)
+#define CFGSTAT_CTO       (1 << CFGSTAT_CTO_BIT)
+
+#define IRQ_DPE (1 << 9)
+#define IRQ_SSE (1 << 8)
+#define IRQ_RMA (1 << 7)
+#define IRQ_RTA (1 << 6)
+#define IRQ_STA (1 << 5)
+#define IRQ_DPED (1 << 4)
+#define IRQ_INTD (1 << 3)
+#define IRQ_INTC (1 << 2)
+#define IRQ_INTB (1 << 1)
+#define IRQ_INTA (1 << 0)
+#define IRQ_DEF_ERRORS (IRQ_RMA | IRQ_RTA | IRQ_STA)
+#define IRQ_ALL_ERRORS (IRQ_DPED | IRQ_DEF_ERRORS | IRQ_SSE | IRQ_DPE)
+#define IRQ_INTX (IRQ_INTA | IRQ_INTB | IRQ_INTC | IRQ_INTD)
+#define IRQ_MASK_BIT 16
+
+#define DEF_PCI_ERRORS (PCI_STATUS_SIG_TARGET_ABORT | \
+			PCI_STATUS_REC_TARGET_ABORT | \
+			PCI_STATUS_REC_MASTER_ABORT)
+#define ALL_PCI_ERRORS (PCI_STATUS_PARITY | PCI_STATUS_DETECTED_PARITY | \
+			PCI_STATUS_SIG_SYSTEM_ERROR | DEF_PCI_ERRORS)
+
+#define TGT 256
+
+struct grpci1_priv {
+	struct leon_pci_info	info; /* must be on top of this structure */
+	struct grpci1_regs	*regs;		/* GRPCI register map */
+	struct device		*dev;
+	int			pci_err_mask;	/* STATUS register error mask */
+	int			irq;		/* LEON irqctrl GRPCI IRQ */
+	unsigned char		irq_map[4];	/* GRPCI nexus PCI INTX# IRQs */
+	unsigned int		irq_err;	/* GRPCI nexus Virt Error IRQ */
+
+	/* AHB PCI Windows */
+	unsigned long		pci_area;	/* MEMORY */
+	unsigned long		pci_area_end;
+	unsigned long		pci_io;		/* I/O */
+	unsigned long		pci_conf;	/* CONFIGURATION */
+	unsigned long		pci_conf_end;
+	unsigned long		pci_io_va;
+};
+
+static struct grpci1_priv *grpci1priv;
+
+static int grpci1_cfg_w32(struct grpci1_priv *priv, unsigned int bus,
+				unsigned int devfn, int where, u32 val);
+
+int grpci1_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+	struct grpci1_priv *priv = dev->bus->sysdata;
+	int irq_group;
+
+	/* Use default IRQ decoding on PCI BUS0 according slot numbering */
+	irq_group = slot & 0x3;
+	pin = ((pin - 1) + irq_group) & 0x3;
+
+	return priv->irq_map[pin];
+}
+
+static int grpci1_cfg_r32(struct grpci1_priv *priv, unsigned int bus,
+				unsigned int devfn, int where, u32 *val)
+{
+	u32 *pci_conf, tmp, cfg;
+
+	if (where & 0x3)
+		return -EINVAL;
+
+	if (bus == 0) {
+		devfn += (0x8 * 6); /* start at AD16=Device0 */
+	} else if (bus == TGT) {
+		bus = 0;
+		devfn = 0; /* special case: bridge controller itself */
+	}
+
+	/* Select bus */
+	cfg = REGLOAD(priv->regs->cfg_stat);
+	REGSTORE(priv->regs->cfg_stat, (cfg & ~(0xf << 23)) | (bus << 23));
+
+	/* do read access */
+	pci_conf = (u32 *) (priv->pci_conf | (devfn << 8) | (where & 0xfc));
+	tmp = LEON3_BYPASS_LOAD_PA(pci_conf);
+
+	/* check if master abort was received */
+	if (REGLOAD(priv->regs->cfg_stat) & CFGSTAT_CTO) {
+		*val = 0xffffffff;
+		/* Clear Master abort bit in PCI cfg space (is set) */
+		tmp = REGLOAD(priv->regs->stat_cmd);
+		grpci1_cfg_w32(priv, TGT, 0, PCI_COMMAND, tmp);
+	} else {
+		/* Bus always little endian (unaffected by byte-swapping) */
+		*val = flip_dword(tmp);
+	}
+
+	return 0;
+}
+
+static int grpci1_cfg_r16(struct grpci1_priv *priv, unsigned int bus,
+				unsigned int devfn, int where, u32 *val)
+{
+	u32 v;
+	int ret;
+
+	if (where & 0x1)
+		return -EINVAL;
+	ret = grpci1_cfg_r32(priv, bus, devfn, where & ~0x3, &v);
+	*val = 0xffff & (v >> (8 * (where & 0x3)));
+	return ret;
+}
+
+static int grpci1_cfg_r8(struct grpci1_priv *priv, unsigned int bus,
+				unsigned int devfn, int where, u32 *val)
+{
+	u32 v;
+	int ret;
+
+	ret = grpci1_cfg_r32(priv, bus, devfn, where & ~0x3, &v);
+	*val = 0xff & (v >> (8 * (where & 3)));
+
+	return ret;
+}
+
+static int grpci1_cfg_w32(struct grpci1_priv *priv, unsigned int bus,
+				unsigned int devfn, int where, u32 val)
+{
+	unsigned int *pci_conf;
+	u32 cfg;
+
+	if (where & 0x3)
+		return -EINVAL;
+
+	if (bus == 0) {
+		devfn += (0x8 * 6); /* start at AD16=Device0 */
+	} else if (bus == TGT) {
+		bus = 0;
+		devfn = 0; /* special case: bridge controller itself */
+	}
+
+	/* Select bus */
+	cfg = REGLOAD(priv->regs->cfg_stat);
+	REGSTORE(priv->regs->cfg_stat, (cfg & ~(0xf << 23)) | (bus << 23));
+
+	pci_conf = (unsigned int *) (priv->pci_conf |
+						(devfn << 8) | (where & 0xfc));
+	LEON3_BYPASS_STORE_PA(pci_conf, flip_dword(val));
+
+	return 0;
+}
+
+static int grpci1_cfg_w16(struct grpci1_priv *priv, unsigned int bus,
+				unsigned int devfn, int where, u32 val)
+{
+	int ret;
+	u32 v;
+
+	if (where & 0x1)
+		return -EINVAL;
+	ret = grpci1_cfg_r32(priv, bus, devfn, where&~3, &v);
+	if (ret)
+		return ret;
+	v = (v & ~(0xffff << (8 * (where & 0x3)))) |
+	    ((0xffff & val) << (8 * (where & 0x3)));
+	return grpci1_cfg_w32(priv, bus, devfn, where & ~0x3, v);
+}
+
+static int grpci1_cfg_w8(struct grpci1_priv *priv, unsigned int bus,
+				unsigned int devfn, int where, u32 val)
+{
+	int ret;
+	u32 v;
+
+	ret = grpci1_cfg_r32(priv, bus, devfn, where & ~0x3, &v);
+	if (ret != 0)
+		return ret;
+	v = (v & ~(0xff << (8 * (where & 0x3)))) |
+	    ((0xff & val) << (8 * (where & 0x3)));
+	return grpci1_cfg_w32(priv, bus, devfn, where & ~0x3, v);
+}
+
+/* Read from Configuration Space. When entering here the PCI layer has taken
+ * the pci_lock spinlock and IRQ is off.
+ */
+static int grpci1_read_config(struct pci_bus *bus, unsigned int devfn,
+			      int where, int size, u32 *val)
+{
+	struct grpci1_priv *priv = grpci1priv;
+	unsigned int busno = bus->number;
+	int ret;
+
+	if (PCI_SLOT(devfn) > 15 || busno > 15) {
+		*val = ~0;
+		return 0;
+	}
+
+	switch (size) {
+	case 1:
+		ret = grpci1_cfg_r8(priv, busno, devfn, where, val);
+		break;
+	case 2:
+		ret = grpci1_cfg_r16(priv, busno, devfn, where, val);
+		break;
+	case 4:
+		ret = grpci1_cfg_r32(priv, busno, devfn, where, val);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+#ifdef GRPCI1_DEBUG_CFGACCESS
+	printk(KERN_INFO
+		"grpci1_read_config: [%02x:%02x:%x] ofs=%d val=%x size=%d\n",
+		busno, PCI_SLOT(devfn), PCI_FUNC(devfn), where, *val, size);
+#endif
+
+	return ret;
+}
+
+/* Write to Configuration Space. When entering here the PCI layer has taken
+ * the pci_lock spinlock and IRQ is off.
+ */
+static int grpci1_write_config(struct pci_bus *bus, unsigned int devfn,
+			       int where, int size, u32 val)
+{
+	struct grpci1_priv *priv = grpci1priv;
+	unsigned int busno = bus->number;
+
+	if (PCI_SLOT(devfn) > 15 || busno > 15)
+		return 0;
+
+#ifdef GRPCI1_DEBUG_CFGACCESS
+	printk(KERN_INFO
+		"grpci1_write_config: [%02x:%02x:%x] ofs=%d size=%d val=%x\n",
+		busno, PCI_SLOT(devfn), PCI_FUNC(devfn), where, size, val);
+#endif
+
+	switch (size) {
+	default:
+		return -EINVAL;
+	case 1:
+		return grpci1_cfg_w8(priv, busno, devfn, where, val);
+	case 2:
+		return grpci1_cfg_w16(priv, busno, devfn, where, val);
+	case 4:
+		return grpci1_cfg_w32(priv, busno, devfn, where, val);
+	}
+}
+
+static struct pci_ops grpci1_ops = {
+	.read =		grpci1_read_config,
+	.write =	grpci1_write_config,
+};
+
+/* GENIRQ IRQ chip implementation for grpci1 irqmode=0..2. In configuration
+ * 3 where all PCI Interrupts has a separate IRQ on the system IRQ controller
+ * this is not needed and the standard IRQ controller can be used.
+ */
+
+static void grpci1_mask_irq(struct irq_data *data)
+{
+	u32 irqidx;
+	struct grpci1_priv *priv = grpci1priv;
+
+	irqidx = (u32)data->chip_data - 1;
+	if (irqidx > 3) /* only mask PCI interrupts here */
+		return;
+	irqidx += IRQ_MASK_BIT;
+
+	REGSTORE(priv->regs->irq, REGLOAD(priv->regs->irq) & ~(1 << irqidx));
+}
+
+static void grpci1_unmask_irq(struct irq_data *data)
+{
+	u32 irqidx;
+	struct grpci1_priv *priv = grpci1priv;
+
+	irqidx = (u32)data->chip_data - 1;
+	if (irqidx > 3) /* only unmask PCI interrupts here */
+		return;
+	irqidx += IRQ_MASK_BIT;
+
+	REGSTORE(priv->regs->irq, REGLOAD(priv->regs->irq) | (1 << irqidx));
+}
+
+static unsigned int grpci1_startup_irq(struct irq_data *data)
+{
+	grpci1_unmask_irq(data);
+	return 0;
+}
+
+static void grpci1_shutdown_irq(struct irq_data *data)
+{
+	grpci1_mask_irq(data);
+}
+
+static struct irq_chip grpci1_irq = {
+	.name		= "grpci1",
+	.irq_startup	= grpci1_startup_irq,
+	.irq_shutdown	= grpci1_shutdown_irq,
+	.irq_mask	= grpci1_mask_irq,
+	.irq_unmask	= grpci1_unmask_irq,
+};
+
+/* Handle one or multiple IRQs from the PCI core */
+static void grpci1_pci_flow_irq(unsigned int irq, struct irq_desc *desc)
+{
+	struct grpci1_priv *priv = grpci1priv;
+	int i, ack = 0;
+	unsigned int irqreg;
+
+	irqreg = REGLOAD(priv->regs->irq);
+	irqreg = (irqreg >> IRQ_MASK_BIT) & irqreg;
+
+	/* Error Interrupt? */
+	if (irqreg & IRQ_ALL_ERRORS) {
+		generic_handle_irq(priv->irq_err);
+		ack = 1;
+	}
+
+	/* PCI Interrupt? */
+	if (irqreg & IRQ_INTX) {
+		/* Call respective PCI Interrupt handler */
+		for (i = 0; i < 4; i++) {
+			if (irqreg & (1 << i))
+				generic_handle_irq(priv->irq_map[i]);
+		}
+		ack = 1;
+	}
+
+	/*
+	 * Call "first level" IRQ chip end-of-irq handler. It will ACK LEON IRQ
+	 * Controller, this must be done after IRQ sources have been handled to
+	 * avoid double IRQ generation
+	 */
+	if (ack)
+		desc->irq_data.chip->irq_eoi(&desc->irq_data);
+}
+
+/* Create a virtual IRQ */
+static unsigned int grpci1_build_device_irq(unsigned int irq)
+{
+	unsigned int virq = 0, pil;
+
+	pil = 1 << 8;
+	virq = irq_alloc(irq, pil);
+	if (virq == 0)
+		goto out;
+
+	irq_set_chip_and_handler_name(virq, &grpci1_irq, handle_simple_irq,
+				      "pcilvl");
+	irq_set_chip_data(virq, (void *)irq);
+
+out:
+	return virq;
+}
+
+/*
+ * Initialize mappings AMBA<->PCI, clear IRQ state, setup PCI interface
+ *
+ * Target BARs:
+ *  BAR0: unused in this implementation
+ *  BAR1: peripheral DMA to host's memory (size at least 256MByte)
+ *  BAR2..BAR5: not implemented in hardware
+ */
+void grpci1_hw_init(struct grpci1_priv *priv)
+{
+	u32 ahbadr, bar_sz, data, pciadr;
+	struct grpci1_regs *regs = priv->regs;
+
+	/* set 1:1 mapping between AHB -> PCI memory space */
+	REGSTORE(regs->cfg_stat, priv->pci_area & 0xf0000000);
+
+	/* map PCI accesses to target BAR1 to Linux kernel memory 1:1 */
+	ahbadr = 0xf0000000 & (u32)__pa(PAGE_ALIGN((unsigned long) &_end));
+	REGSTORE(regs->page1, ahbadr);
+
+	/* translate I/O accesses to 0, I/O Space always @ PCI low 64Kbytes */
+	REGSTORE(regs->iomap, REGLOAD(regs->iomap) & 0x0000ffff);
+
+	/* disable and clear pending interrupts */
+	REGSTORE(regs->irq, 0);
+
+	/* Setup BAR0 outside access range so that it does not conflict with
+	 * peripheral DMA. There is no need to set up the PAGE0 register.
+	 */
+	grpci1_cfg_w32(priv, TGT, 0, PCI_BASE_ADDRESS_0, 0xffffffff);
+	grpci1_cfg_r32(priv, TGT, 0, PCI_BASE_ADDRESS_0, &bar_sz);
+	bar_sz = ~bar_sz + 1;
+	pciadr = priv->pci_area - bar_sz;
+	grpci1_cfg_w32(priv, TGT, 0, PCI_BASE_ADDRESS_0, pciadr);
+
+	/*
+	 * Setup the Host's PCI Target BAR1 for other peripherals to access,
+	 * and do DMA to the host's memory.
+	 */
+	grpci1_cfg_w32(priv, TGT, 0, PCI_BASE_ADDRESS_1, ahbadr);
+
+	/*
+	 * Setup Latency Timer and cache line size. Default cache line
+	 * size will result in poor performance (256 word fetches), 0xff
+	 * will set it according to the max size of the PCI FIFO.
+	 */
+	grpci1_cfg_w8(priv, TGT, 0, PCI_CACHE_LINE_SIZE, 0xff);
+	grpci1_cfg_w8(priv, TGT, 0, PCI_LATENCY_TIMER, 0x40);
+
+	/* set as bus master, enable pci memory responses, clear status bits */
+	grpci1_cfg_r32(priv, TGT, 0, PCI_COMMAND, &data);
+	data |= (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+	grpci1_cfg_w32(priv, TGT, 0, PCI_COMMAND, data);
+}
+
+static irqreturn_t grpci1_jump_interrupt(int irq, void *arg)
+{
+	struct grpci1_priv *priv = arg;
+	dev_err(priv->dev, "Jump IRQ happened\n");
+	return IRQ_NONE;
+}
+
+/* Handle GRPCI1 Error Interrupt */
+static irqreturn_t grpci1_err_interrupt(int irq, void *arg)
+{
+	struct grpci1_priv *priv = arg;
+	u32 status;
+
+	grpci1_cfg_r16(priv, TGT, 0, PCI_STATUS, &status);
+	status &= priv->pci_err_mask;
+
+	if (status == 0)
+		return IRQ_NONE;
+
+	if (status & PCI_STATUS_PARITY)
+		dev_err(priv->dev, "Data Parity Error\n");
+
+	if (status & PCI_STATUS_SIG_TARGET_ABORT)
+		dev_err(priv->dev, "Signalled Target Abort\n");
+
+	if (status & PCI_STATUS_REC_TARGET_ABORT)
+		dev_err(priv->dev, "Received Target Abort\n");
+
+	if (status & PCI_STATUS_REC_MASTER_ABORT)
+		dev_err(priv->dev, "Received Master Abort\n");
+
+	if (status & PCI_STATUS_SIG_SYSTEM_ERROR)
+		dev_err(priv->dev, "Signalled System Error\n");
+
+	if (status & PCI_STATUS_DETECTED_PARITY)
+		dev_err(priv->dev, "Parity Error\n");
+
+	/* Clear handled INT TYPE IRQs */
+	grpci1_cfg_w16(priv, TGT, 0, PCI_STATUS, status);
+
+	return IRQ_HANDLED;
+}
+
+static int grpci1_of_probe(struct platform_device *ofdev)
+{
+	struct grpci1_regs *regs;
+	struct grpci1_priv *priv;
+	int err, len;
+	const int *tmp;
+	u32 cfg, size, err_mask;
+	struct resource *res;
+
+	if (grpci1priv) {
+		dev_err(&ofdev->dev, "only one GRPCI1 supported\n");
+		return -ENODEV;
+	}
+
+	if (ofdev->num_resources < 3) {
+		dev_err(&ofdev->dev, "not enough APB/AHB resources\n");
+		return -EIO;
+	}
+
+	priv = devm_kzalloc(&ofdev->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		dev_err(&ofdev->dev, "memory allocation failed\n");
+		return -ENOMEM;
+	}
+	platform_set_drvdata(ofdev, priv);
+	priv->dev = &ofdev->dev;
+
+	/* find device register base address */
+	res = platform_get_resource(ofdev, IORESOURCE_MEM, 0);
+	regs = devm_request_and_ioremap(&ofdev->dev, res);
+	if (!regs) {
+		dev_err(&ofdev->dev, "io-regs mapping failed\n");
+		return -EADDRNOTAVAIL;
+	}
+
+	/*
+	 * check that we're in Host Slot and that we can act as a Host Bridge
+	 * and not only as target/peripheral.
+	 */
+	cfg = REGLOAD(regs->cfg_stat);
+	if ((cfg & CFGSTAT_HOST) == 0) {
+		dev_err(&ofdev->dev, "not in host system slot\n");
+		return -EIO;
+	}
+
+	/* check that BAR1 support 256 MByte so that we can map kernel space */
+	REGSTORE(regs->page1, 0xffffffff);
+	size = ~REGLOAD(regs->page1) + 1;
+	if (size < 0x10000000) {
+		dev_err(&ofdev->dev, "BAR1 must be at least 256MByte\n");
+		return -EIO;
+	}
+
+	/* hardware must support little-endian PCI (byte-twisting) */
+	if ((REGLOAD(regs->page0) & PAGE0_BTEN) == 0) {
+		dev_err(&ofdev->dev, "byte-twisting is required\n");
+		return -EIO;
+	}
+
+	priv->regs = regs;
+	priv->irq = irq_of_parse_and_map(ofdev->dev.of_node, 0);
+	dev_info(&ofdev->dev, "host found at 0x%p, irq%d\n", regs, priv->irq);
+
+	/* Find PCI Memory, I/O and Configuration Space Windows */
+	priv->pci_area = ofdev->resource[1].start;
+	priv->pci_area_end = ofdev->resource[1].end+1;
+	priv->pci_io = ofdev->resource[2].start;
+	priv->pci_conf = ofdev->resource[2].start + 0x10000;
+	priv->pci_conf_end = priv->pci_conf + 0x10000;
+	priv->pci_io_va = (unsigned long)ioremap(priv->pci_io, 0x10000);
+	if (!priv->pci_io_va) {
+		dev_err(&ofdev->dev, "unable to map PCI I/O area\n");
+		return -EIO;
+	}
+
+	printk(KERN_INFO
+		"GRPCI1: MEMORY SPACE [0x%08lx - 0x%08lx]\n"
+		"        I/O    SPACE [0x%08lx - 0x%08lx]\n"
+		"        CONFIG SPACE [0x%08lx - 0x%08lx]\n",
+		priv->pci_area, priv->pci_area_end-1,
+		priv->pci_io, priv->pci_conf-1,
+		priv->pci_conf, priv->pci_conf_end-1);
+
+	/*
+	 * I/O Space resources in I/O Window mapped into Virtual Adr Space
+	 * We never use low 4KB because some devices seem have problems using
+	 * address 0.
+	 */
+	priv->info.io_space.name = "GRPCI1 PCI I/O Space";
+	priv->info.io_space.start = priv->pci_io_va + 0x1000;
+	priv->info.io_space.end = priv->pci_io_va + 0x10000 - 1;
+	priv->info.io_space.flags = IORESOURCE_IO;
+
+	/*
+	 * grpci1 has no prefetchable memory, map everything as
+	 * non-prefetchable memory
+	 */
+	priv->info.mem_space.name = "GRPCI1 PCI MEM Space";
+	priv->info.mem_space.start = priv->pci_area;
+	priv->info.mem_space.end = priv->pci_area_end - 1;
+	priv->info.mem_space.flags = IORESOURCE_MEM;
+
+	if (request_resource(&iomem_resource, &priv->info.mem_space) < 0) {
+		dev_err(&ofdev->dev, "unable to request PCI memory area\n");
+		err = -ENOMEM;
+		goto err1;
+	}
+
+	if (request_resource(&ioport_resource, &priv->info.io_space) < 0) {
+		dev_err(&ofdev->dev, "unable to request PCI I/O area\n");
+		err = -ENOMEM;
+		goto err2;
+	}
+
+	/* setup maximum supported PCI buses */
+	priv->info.busn.name = "GRPCI1 busn";
+	priv->info.busn.start = 0;
+	priv->info.busn.end = 15;
+
+	grpci1priv = priv;
+
+	/* Initialize hardware */
+	grpci1_hw_init(priv);
+
+	/*
+	 * Get PCI Interrupt to System IRQ mapping and setup IRQ handling
+	 * Error IRQ. All PCI and PCI-Error interrupts are shared using the
+	 * same system IRQ.
+	 */
+	leon_update_virq_handling(priv->irq, grpci1_pci_flow_irq, "pcilvl", 0);
+
+	priv->irq_map[0] = grpci1_build_device_irq(1);
+	priv->irq_map[1] = grpci1_build_device_irq(2);
+	priv->irq_map[2] = grpci1_build_device_irq(3);
+	priv->irq_map[3] = grpci1_build_device_irq(4);
+	priv->irq_err = grpci1_build_device_irq(5);
+
+	printk(KERN_INFO "        PCI INTA..D#: IRQ%d, IRQ%d, IRQ%d, IRQ%d\n",
+		priv->irq_map[0], priv->irq_map[1], priv->irq_map[2],
+		priv->irq_map[3]);
+
+	/* Enable IRQs on LEON IRQ controller */
+	err = devm_request_irq(&ofdev->dev, priv->irq, grpci1_jump_interrupt, 0,
+				"GRPCI1_JUMP", priv);
+	if (err) {
+		dev_err(&ofdev->dev, "ERR IRQ request failed: %d\n", err);
+		goto err3;
+	}
+
+	/* Setup IRQ handler for access errors */
+	err = devm_request_irq(&ofdev->dev, priv->irq_err,
+				grpci1_err_interrupt, IRQF_SHARED, "GRPCI1_ERR",
+				priv);
+	if (err) {
+		dev_err(&ofdev->dev, "ERR VIRQ request failed: %d\n", err);
+		goto err3;
+	}
+
+	tmp = of_get_property(ofdev->dev.of_node, "all_pci_errors", &len);
+	if (tmp && (len == 4)) {
+		priv->pci_err_mask = ALL_PCI_ERRORS;
+		err_mask = IRQ_ALL_ERRORS << IRQ_MASK_BIT;
+	} else {
+		priv->pci_err_mask = DEF_PCI_ERRORS;
+		err_mask = IRQ_DEF_ERRORS << IRQ_MASK_BIT;
+	}
+
+	/*
+	 * Enable Error Interrupts. PCI interrupts are unmasked once request_irq
+	 * is called by the PCI Device drivers
+	 */
+	REGSTORE(regs->irq, err_mask);
+
+	/* Init common layer and scan buses */
+	priv->info.ops = &grpci1_ops;
+	priv->info.map_irq = grpci1_map_irq;
+	leon_pci_init(ofdev, &priv->info);
+
+	return 0;
+
+err3:
+	release_resource(&priv->info.io_space);
+err2:
+	release_resource(&priv->info.mem_space);
+err1:
+	iounmap((void *)priv->pci_io_va);
+	grpci1priv = NULL;
+	return err;
+}
+
+static struct of_device_id grpci1_of_match[] = {
+	{
+	 .name = "GAISLER_PCIFBRG",
+	 },
+	{
+	 .name = "01_014",
+	 },
+	{},
+};
+
+static struct platform_driver grpci1_of_driver = {
+	.driver = {
+		.name = "grpci1",
+		.owner = THIS_MODULE,
+		.of_match_table = grpci1_of_match,
+	},
+	.probe = grpci1_of_probe,
+};
+
+static int __init grpci1_init(void)
+{
+	return platform_driver_register(&grpci1_of_driver);
+}
+
+subsys_initcall(grpci1_init);
diff --git a/arch/sparc/kernel/leon_pci_grpci2.c b/arch/sparc/kernel/leon_pci_grpci2.c
index 4d14871..5f0402a 100644
--- a/arch/sparc/kernel/leon_pci_grpci2.c
+++ b/arch/sparc/kernel/leon_pci_grpci2.c
@@ -799,6 +799,11 @@ static int grpci2_of_probe(struct platform_device *ofdev)
 	if (request_resource(&ioport_resource, &priv->info.io_space) < 0)
 		goto err4;
 
+	/* setup maximum supported PCI buses */
+	priv->info.busn.name = "GRPCI2 busn";
+	priv->info.busn.start = 0;
+	priv->info.busn.end = 255;
+
 	grpci2_hw_init(priv);
 
 	/*
diff --git a/arch/sparc/kernel/leon_smp.c b/arch/sparc/kernel/leon_smp.c
index 9b40c9c..6cfc1b0 100644
--- a/arch/sparc/kernel/leon_smp.c
+++ b/arch/sparc/kernel/leon_smp.c
@@ -253,24 +253,15 @@ void __init leon_smp_done(void)
 
 	/* Free unneeded trap tables */
 	if (!cpu_present(1)) {
-		ClearPageReserved(virt_to_page(&trapbase_cpu1));
-		init_page_count(virt_to_page(&trapbase_cpu1));
-		free_page((unsigned long)&trapbase_cpu1);
-		totalram_pages++;
+		free_reserved_page(virt_to_page(&trapbase_cpu1));
 		num_physpages++;
 	}
 	if (!cpu_present(2)) {
-		ClearPageReserved(virt_to_page(&trapbase_cpu2));
-		init_page_count(virt_to_page(&trapbase_cpu2));
-		free_page((unsigned long)&trapbase_cpu2);
-		totalram_pages++;
+		free_reserved_page(virt_to_page(&trapbase_cpu2));
 		num_physpages++;
 	}
 	if (!cpu_present(3)) {
-		ClearPageReserved(virt_to_page(&trapbase_cpu3));
-		init_page_count(virt_to_page(&trapbase_cpu3));
-		free_page((unsigned long)&trapbase_cpu3);
-		totalram_pages++;
+		free_reserved_page(virt_to_page(&trapbase_cpu3));
 		num_physpages++;
 	}
 	/* Ok, they are spinning and ready to go. */
diff --git a/arch/sparc/kernel/sys32.S b/arch/sparc/kernel/sys32.S
index 240a3ce..2e680b5 100644
--- a/arch/sparc/kernel/sys32.S
+++ b/arch/sparc/kernel/sys32.S
@@ -36,7 +36,6 @@ STUB:	sra	REG1, 0, REG1; \
 	jmpl	%g1 + %lo(SYSCALL), %g0; \
 	sra	REG3, 0, REG3
 
-SIGN1(sys32_getrusage, compat_sys_getrusage, %o0)
 SIGN1(sys32_readahead, compat_sys_readahead, %o0)
 SIGN2(sys32_fadvise64, compat_sys_fadvise64, %o0, %o4)
 SIGN2(sys32_fadvise64_64, compat_sys_fadvise64_64, %o0, %o5)
@@ -46,12 +45,9 @@ SIGN1(sys32_io_submit, compat_sys_io_submit, %o1)
 SIGN1(sys32_mq_open, compat_sys_mq_open, %o1)
 SIGN1(sys32_select, compat_sys_select, %o0)
 SIGN3(sys32_futex, compat_sys_futex, %o1, %o2, %o5)
-SIGN2(sys32_sendfile, compat_sys_sendfile, %o0, %o1)
 SIGN1(sys32_recvfrom, compat_sys_recvfrom, %o0)
 SIGN1(sys32_recvmsg, compat_sys_recvmsg, %o0)
 SIGN1(sys32_sendmsg, compat_sys_sendmsg, %o0)
-SIGN2(sys32_sync_file_range, compat_sync_file_range, %o0, %o5)
-SIGN1(sys32_vmsplice, compat_sys_vmsplice, %o0)
 
 	.globl		sys32_mmap2
 sys32_mmap2:
diff --git a/arch/sparc/kernel/sys_sparc32.c b/arch/sparc/kernel/sys_sparc32.c
index f38f228..3d0ddbc 100644
--- a/arch/sparc/kernel/sys_sparc32.c
+++ b/arch/sparc/kernel/sys_sparc32.c
@@ -49,71 +49,6 @@
 #include <asm/mmu_context.h>
 #include <asm/compat_signal.h>
 
-#ifdef CONFIG_SYSVIPC                                                        
-asmlinkage long compat_sys_ipc(u32 call, u32 first, u32 second, u32 third, compat_uptr_t ptr, u32 fifth)
-{
-	int version;
-
-	version = call >> 16; /* hack for backward compatibility */
-	call &= 0xffff;
-
-	switch (call) {
-	case SEMTIMEDOP:
-		if (fifth)
-			/* sign extend semid */
-			return compat_sys_semtimedop((int)first,
-						     compat_ptr(ptr), second,
-						     compat_ptr(fifth));
-		/* else fall through for normal semop() */
-	case SEMOP:
-		/* struct sembuf is the same on 32 and 64bit :)) */
-		/* sign extend semid */
-		return sys_semtimedop((int)first, compat_ptr(ptr), second,
-				      NULL);
-	case SEMGET:
-		/* sign extend key, nsems */
-		return sys_semget((int)first, (int)second, third);
-	case SEMCTL:
-		/* sign extend semid, semnum */
-		return compat_sys_semctl((int)first, (int)second, third,
-					 compat_ptr(ptr));
-
-	case MSGSND:
-		/* sign extend msqid */
-		return compat_sys_msgsnd((int)first, (int)second, third,
-					 compat_ptr(ptr));
-	case MSGRCV:
-		/* sign extend msqid, msgtyp */
-		return compat_sys_msgrcv((int)first, second, (int)fifth,
-					 third, version, compat_ptr(ptr));
-	case MSGGET:
-		/* sign extend key */
-		return sys_msgget((int)first, second);
-	case MSGCTL:
-		/* sign extend msqid */
-		return compat_sys_msgctl((int)first, second, compat_ptr(ptr));
-
-	case SHMAT:
-		/* sign extend shmid */
-		return compat_sys_shmat((int)first, second, third, version,
-					compat_ptr(ptr));
-	case SHMDT:
-		return sys_shmdt(compat_ptr(ptr));
-	case SHMGET:
-		/* sign extend key_t */
-		return sys_shmget((int)first, second, third);
-	case SHMCTL:
-		/* sign extend shmid */
-		return compat_sys_shmctl((int)first, second, compat_ptr(ptr));
-
-	default:
-		return -ENOSYS;
-	}
-
-	return -ENOSYS;
-}
-#endif
-
 asmlinkage long sys32_truncate64(const char __user * path, unsigned long high, unsigned long low)
 {
 	if ((int)high < 0)
@@ -303,15 +238,7 @@ long compat_sys_fadvise64_64(int fd,
 				advice);
 }
 
-long sys32_lookup_dcookie(unsigned long cookie_high,
-			  unsigned long cookie_low,
-			  char __user *buf, size_t len)
-{
-	return sys_lookup_dcookie((cookie_high << 32) | cookie_low,
-				  buf, len);
-}
-
-long compat_sync_file_range(int fd, unsigned long off_high, unsigned long off_low, unsigned long nb_high, unsigned long nb_low, int flags)
+long sys32_sync_file_range(unsigned int fd, unsigned long off_high, unsigned long off_low, unsigned long nb_high, unsigned long nb_low, unsigned int flags)
 {
 	return sys_sync_file_range(fd,
 				   (off_high << 32) | off_low,
diff --git a/arch/sparc/kernel/sys_sparc_64.c b/arch/sparc/kernel/sys_sparc_64.c
index 708bc29..51561b8 100644
--- a/arch/sparc/kernel/sys_sparc_64.c
+++ b/arch/sparc/kernel/sys_sparc_64.c
@@ -290,7 +290,6 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
 	    sysctl_legacy_va_layout) {
 		mm->mmap_base = TASK_UNMAPPED_BASE + random_factor;
 		mm->get_unmapped_area = arch_get_unmapped_area;
-		mm->unmap_area = arch_unmap_area;
 	} else {
 		/* We know it's 32-bit */
 		unsigned long task_size = STACK_TOP32;
@@ -302,7 +301,6 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
 
 		mm->mmap_base = PAGE_ALIGN(task_size - gap - random_factor);
 		mm->get_unmapped_area = arch_get_unmapped_area_topdown;
-		mm->unmap_area = arch_unmap_area_topdown;
 	}
 }
 
@@ -353,7 +351,7 @@ SYSCALL_DEFINE6(sparc_ipc, unsigned int, call, int, first, unsigned long, second
 		case SEMCTL: {
 			err = sys_semctl(first, second,
 					 (int)third | IPC_64,
-					 (union semun) ptr);
+					 (unsigned long) ptr);
 			goto out;
 		}
 		default:
@@ -470,10 +468,6 @@ SYSCALL_DEFINE2(64_munmap, unsigned long, addr, size_t, len)
 
 	return vm_munmap(addr, len);
 }
-
-extern unsigned long do_mremap(unsigned long addr,
-	unsigned long old_len, unsigned long new_len,
-	unsigned long flags, unsigned long new_addr);
                 
 SYSCALL_DEFINE5(64_mremap, unsigned long, addr,	unsigned long, old_len,
 		unsigned long, new_len, unsigned long, flags,
diff --git a/arch/sparc/kernel/systbls_64.S b/arch/sparc/kernel/systbls_64.S
index 0881348..8fd9320 100644
--- a/arch/sparc/kernel/systbls_64.S
+++ b/arch/sparc/kernel/systbls_64.S
@@ -23,9 +23,9 @@ sys_call_table32:
 /*10*/  .word sys_unlink, sunos_execv, sys_chdir, sys_chown16, sys_mknod
 /*15*/	.word sys_chmod, sys_lchown16, sys_brk, sys_nis_syscall, compat_sys_lseek
 /*20*/	.word sys_getpid, sys_capget, sys_capset, sys_setuid16, sys_getuid16
-/*25*/	.word sys32_vmsplice, compat_sys_ptrace, sys_alarm, compat_sys_sigaltstack, sys_pause
+/*25*/	.word compat_sys_vmsplice, compat_sys_ptrace, sys_alarm, compat_sys_sigaltstack, sys_pause
 /*30*/	.word compat_sys_utime, sys_lchown, sys_fchown, sys_access, sys_nice
-	.word sys_chown, sys_sync, sys_kill, compat_sys_newstat, sys32_sendfile
+	.word sys_chown, sys_sync, sys_kill, compat_sys_newstat, compat_sys_sendfile
 /*40*/	.word compat_sys_newlstat, sys_dup, sys_sparc_pipe, compat_sys_times, sys_getuid
 	.word sys_umount, sys_setgid16, sys_getgid16, sys_signal, sys_geteuid16
 /*50*/	.word sys_getegid16, sys_acct, sys_nis_syscall, sys_getgid, compat_sys_ioctl
@@ -41,7 +41,7 @@ sys_call_table32:
 /*100*/ .word sys_getpriority, sys32_rt_sigreturn, compat_sys_rt_sigaction, compat_sys_rt_sigprocmask, compat_sys_rt_sigpending
 	.word compat_sys_rt_sigtimedwait, compat_sys_rt_sigqueueinfo, compat_sys_rt_sigsuspend, sys_setresuid, sys_getresuid
 /*110*/	.word sys_setresgid, sys_getresgid, sys_setregid, sys_nis_syscall, sys_nis_syscall
-	.word sys_getgroups, compat_sys_gettimeofday, sys32_getrusage, sys_nis_syscall, sys_getcwd
+	.word sys_getgroups, compat_sys_gettimeofday, compat_sys_getrusage, sys_nis_syscall, sys_getcwd
 /*120*/	.word compat_sys_readv, compat_sys_writev, compat_sys_settimeofday, sys_fchown16, sys_fchmod
 	.word sys_nis_syscall, sys_setreuid16, sys_setregid16, sys_rename, compat_sys_truncate
 /*130*/	.word compat_sys_ftruncate, sys_flock, compat_sys_lstat64, sys_nis_syscall, sys_nis_syscall
@@ -59,7 +59,7 @@ sys_call_table32:
 /*190*/	.word sys_init_module, sys_sparc64_personality, sys_remap_file_pages, sys_epoll_create, sys_epoll_ctl
 	.word sys_epoll_wait, sys_ioprio_set, sys_getppid, compat_sys_sparc_sigaction, sys_sgetmask
 /*200*/	.word sys_ssetmask, sys_sigsuspend, compat_sys_newlstat, sys_uselib, compat_sys_old_readdir
-	.word sys32_readahead, sys32_socketcall, sys_syslog, sys32_lookup_dcookie, sys32_fadvise64
+	.word sys32_readahead, sys32_socketcall, sys_syslog, compat_sys_lookup_dcookie, sys32_fadvise64
 /*210*/	.word sys32_fadvise64_64, sys_tgkill, sys_waitpid, sys_swapoff, compat_sys_sysinfo
 	.word compat_sys_ipc, sys32_sigreturn, sys_clone, sys_ioprio_get, compat_sys_adjtimex
 /*220*/	.word compat_sys_sigprocmask, sys_ni_syscall, sys_delete_module, sys_ni_syscall, sys_getpgid
diff --git a/arch/sparc/kernel/us2e_cpufreq.c b/arch/sparc/kernel/us2e_cpufreq.c
index 489fc15..306ae46 100644
--- a/arch/sparc/kernel/us2e_cpufreq.c
+++ b/arch/sparc/kernel/us2e_cpufreq.c
@@ -234,9 +234,6 @@ static unsigned int us2e_freq_get(unsigned int cpu)
 	cpumask_t cpus_allowed;
 	unsigned long clock_tick, estar;
 
-	if (!cpu_online(cpu))
-		return 0;
-
 	cpumask_copy(&cpus_allowed, tsk_cpus_allowed(current));
 	set_cpus_allowed_ptr(current, cpumask_of(cpu));
 
@@ -248,16 +245,15 @@ static unsigned int us2e_freq_get(unsigned int cpu)
 	return clock_tick / estar_to_divisor(estar);
 }
 
-static void us2e_set_cpu_divider_index(unsigned int cpu, unsigned int index)
+static void us2e_set_cpu_divider_index(struct cpufreq_policy *policy,
+		unsigned int index)
 {
+	unsigned int cpu = policy->cpu;
 	unsigned long new_bits, new_freq;
 	unsigned long clock_tick, divisor, old_divisor, estar;
 	cpumask_t cpus_allowed;
 	struct cpufreq_freqs freqs;
 
-	if (!cpu_online(cpu))
-		return;
-
 	cpumask_copy(&cpus_allowed, tsk_cpus_allowed(current));
 	set_cpus_allowed_ptr(current, cpumask_of(cpu));
 
@@ -272,14 +268,13 @@ static void us2e_set_cpu_divider_index(unsigned int cpu, unsigned int index)
 
 	freqs.old = clock_tick / old_divisor;
 	freqs.new = new_freq;
-	freqs.cpu = cpu;
-	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
 
 	if (old_divisor != divisor)
 		us2e_transition(estar, new_bits, clock_tick * 1000,
 				old_divisor, divisor);
 
-	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
 
 	set_cpus_allowed_ptr(current, &cpus_allowed);
 }
@@ -295,7 +290,7 @@ static int us2e_freq_target(struct cpufreq_policy *policy,
 					   target_freq, relation, &new_index))
 		return -EINVAL;
 
-	us2e_set_cpu_divider_index(policy->cpu, new_index);
+	us2e_set_cpu_divider_index(policy, new_index);
 
 	return 0;
 }
@@ -335,7 +330,7 @@ static int __init us2e_freq_cpu_init(struct cpufreq_policy *policy)
 static int us2e_freq_cpu_exit(struct cpufreq_policy *policy)
 {
 	if (cpufreq_us2e_driver)
-		us2e_set_cpu_divider_index(policy->cpu, 0);
+		us2e_set_cpu_divider_index(policy, 0);
 
 	return 0;
 }
diff --git a/arch/sparc/kernel/us3_cpufreq.c b/arch/sparc/kernel/us3_cpufreq.c
index eb1624b..c71ee14 100644
--- a/arch/sparc/kernel/us3_cpufreq.c
+++ b/arch/sparc/kernel/us3_cpufreq.c
@@ -82,9 +82,6 @@ static unsigned int us3_freq_get(unsigned int cpu)
 	unsigned long reg;
 	unsigned int ret;
 
-	if (!cpu_online(cpu))
-		return 0;
-
 	cpumask_copy(&cpus_allowed, tsk_cpus_allowed(current));
 	set_cpus_allowed_ptr(current, cpumask_of(cpu));
 
@@ -96,15 +93,14 @@ static unsigned int us3_freq_get(unsigned int cpu)
 	return ret;
 }
 
-static void us3_set_cpu_divider_index(unsigned int cpu, unsigned int index)
+static void us3_set_cpu_divider_index(struct cpufreq_policy *policy,
+		unsigned int index)
 {
+	unsigned int cpu = policy->cpu;
 	unsigned long new_bits, new_freq, reg;
 	cpumask_t cpus_allowed;
 	struct cpufreq_freqs freqs;
 
-	if (!cpu_online(cpu))
-		return;
-
 	cpumask_copy(&cpus_allowed, tsk_cpus_allowed(current));
 	set_cpus_allowed_ptr(current, cpumask_of(cpu));
 
@@ -131,14 +127,13 @@ static void us3_set_cpu_divider_index(unsigned int cpu, unsigned int index)
 
 	freqs.old = get_current_freq(cpu, reg);
 	freqs.new = new_freq;
-	freqs.cpu = cpu;
-	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
 
 	reg &= ~SAFARI_CFG_DIV_MASK;
 	reg |= new_bits;
 	write_safari_cfg(reg);
 
-	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
 
 	set_cpus_allowed_ptr(current, &cpus_allowed);
 }
@@ -156,7 +151,7 @@ static int us3_freq_target(struct cpufreq_policy *policy,
 					   &new_index))
 		return -EINVAL;
 
-	us3_set_cpu_divider_index(policy->cpu, new_index);
+	us3_set_cpu_divider_index(policy, new_index);
 
 	return 0;
 }
@@ -192,7 +187,7 @@ static int __init us3_freq_cpu_init(struct cpufreq_policy *policy)
 static int us3_freq_cpu_exit(struct cpufreq_policy *policy)
 {
 	if (cpufreq_us3_driver)
-		us3_set_cpu_divider_index(policy->cpu, 0);
+		us3_set_cpu_divider_index(policy, 0);
 
 	return 0;
 }
diff --git a/arch/sparc/lib/Makefile b/arch/sparc/lib/Makefile
index 8410065f2..dbe119b 100644
--- a/arch/sparc/lib/Makefile
+++ b/arch/sparc/lib/Makefile
@@ -45,4 +45,3 @@ obj-y                 += iomap.o
 obj-$(CONFIG_SPARC32) += atomic32.o ucmpdi2.o
 obj-y                 += ksyms.o
 obj-$(CONFIG_SPARC64) += PeeCeeI.o
-obj-y                 += usercopy.o
diff --git a/arch/sparc/lib/bitext.c b/arch/sparc/lib/bitext.c
index 48d00e7..8ec4e9c 100644
--- a/arch/sparc/lib/bitext.c
+++ b/arch/sparc/lib/bitext.c
@@ -119,11 +119,7 @@ void bit_map_clear(struct bit_map *t, int offset, int len)
 
 void bit_map_init(struct bit_map *t, unsigned long *map, int size)
 {
-
-	if ((size & 07) != 0)
-		BUG();
-	memset(map, 0, size>>3);
-
+	bitmap_zero(map, size);
 	memset(t, 0, sizeof *t);
 	spin_lock_init(&t->lock);
 	t->map = map;
diff --git a/arch/sparc/lib/usercopy.c b/arch/sparc/lib/usercopy.c
deleted file mode 100644
index 5c4284c..0000000
--- a/arch/sparc/lib/usercopy.c
+++ /dev/null
@@ -1,9 +0,0 @@
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/bug.h>
-
-void copy_from_user_overflow(void)
-{
-	WARN(1, "Buffer overflow detected!\n");
-}
-EXPORT_SYMBOL(copy_from_user_overflow);
diff --git a/arch/sparc/mm/init_32.c b/arch/sparc/mm/init_32.c
index 48e0c03..af472cf 100644
--- a/arch/sparc/mm/init_32.c
+++ b/arch/sparc/mm/init_32.c
@@ -282,14 +282,8 @@ static void map_high_region(unsigned long start_pfn, unsigned long end_pfn)
 	printk("mapping high region %08lx - %08lx\n", start_pfn, end_pfn);
 #endif
 
-	for (tmp = start_pfn; tmp < end_pfn; tmp++) {
-		struct page *page = pfn_to_page(tmp);
-
-		ClearPageReserved(page);
-		init_page_count(page);
-		__free_page(page);
-		totalhigh_pages++;
-	}
+	for (tmp = start_pfn; tmp < end_pfn; tmp++)
+		free_highmem_page(pfn_to_page(tmp));
 }
 
 void __init mem_init(void)
@@ -347,8 +341,6 @@ void __init mem_init(void)
 		map_high_region(start_pfn, end_pfn);
 	}
 	
-	totalram_pages += totalhigh_pages;
-
 	codepages = (((unsigned long) &_etext) - ((unsigned long)&_start));
 	codepages = PAGE_ALIGN(codepages) >> PAGE_SHIFT;
 	datapages = (((unsigned long) &_edata) - ((unsigned long)&_etext));
@@ -374,45 +366,14 @@ void __init mem_init(void)
 
 void free_initmem (void)
 {
-	unsigned long addr;
-	unsigned long freed;
-
-	addr = (unsigned long)(&__init_begin);
-	freed = (unsigned long)(&__init_end) - addr;
-	for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) {
-		struct page *p;
-
-		memset((void *)addr, POISON_FREE_INITMEM, PAGE_SIZE);
-		p = virt_to_page(addr);
-
-		ClearPageReserved(p);
-		init_page_count(p);
-		__free_page(p);
-		totalram_pages++;
-		num_physpages++;
-	}
-	printk(KERN_INFO "Freeing unused kernel memory: %ldk freed\n",
-		freed >> 10);
+	num_physpages += free_initmem_default(POISON_FREE_INITMEM);
 }
 
 #ifdef CONFIG_BLK_DEV_INITRD
 void free_initrd_mem(unsigned long start, unsigned long end)
 {
-	if (start < end)
-		printk(KERN_INFO "Freeing initrd memory: %ldk freed\n",
-			(end - start) >> 10);
-	for (; start < end; start += PAGE_SIZE) {
-		struct page *p;
-
-		memset((void *)start, POISON_FREE_INITMEM, PAGE_SIZE);
-		p = virt_to_page(start);
-
-		ClearPageReserved(p);
-		init_page_count(p);
-		__free_page(p);
-		totalram_pages++;
-		num_physpages++;
-	}
+	num_physpages += free_reserved_area(start, end, POISON_FREE_INITMEM,
+					    "initrd");
 }
 #endif
 
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
index 1588d33..63ddf47 100644
--- a/arch/sparc/mm/init_64.c
+++ b/arch/sparc/mm/init_64.c
@@ -2060,8 +2060,7 @@ void __init mem_init(void)
 	/* We subtract one to account for the mem_map_zero page
 	 * allocated below.
 	 */
-	totalram_pages -= 1;
-	num_physpages = totalram_pages;
+	num_physpages = totalram_pages - 1;
 
 	/*
 	 * Set up the zero page, mark it reserved, so that page count
@@ -2072,7 +2071,7 @@ void __init mem_init(void)
 		prom_printf("paging_init: Cannot alloc zero page.\n");
 		prom_halt();
 	}
-	SetPageReserved(mem_map_zero);
+	mark_page_reserved(mem_map_zero);
 
 	codepages = (((unsigned long) _etext) - ((unsigned long) _start));
 	codepages = PAGE_ALIGN(codepages) >> PAGE_SHIFT;
@@ -2112,39 +2111,22 @@ void free_initmem(void)
 	initend = (unsigned long)(__init_end) & PAGE_MASK;
 	for (; addr < initend; addr += PAGE_SIZE) {
 		unsigned long page;
-		struct page *p;
 
 		page = (addr +
 			((unsigned long) __va(kern_base)) -
 			((unsigned long) KERNBASE));
 		memset((void *)addr, POISON_FREE_INITMEM, PAGE_SIZE);
 
-		if (do_free) {
-			p = virt_to_page(page);
-
-			ClearPageReserved(p);
-			init_page_count(p);
-			__free_page(p);
-			num_physpages++;
-			totalram_pages++;
-		}
+		if (do_free)
+			free_reserved_page(virt_to_page(page));
 	}
 }
 
 #ifdef CONFIG_BLK_DEV_INITRD
 void free_initrd_mem(unsigned long start, unsigned long end)
 {
-	if (start < end)
-		printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
-	for (; start < end; start += PAGE_SIZE) {
-		struct page *p = virt_to_page(start);
-
-		ClearPageReserved(p);
-		init_page_count(p);
-		__free_page(p);
-		num_physpages++;
-		totalram_pages++;
-	}
+	num_physpages += free_reserved_area(start, end, POISON_FREE_INITMEM,
+					    "initrd");
 }
 #endif
 
@@ -2181,10 +2163,9 @@ unsigned long vmemmap_table[VMEMMAP_SIZE];
 static long __meminitdata addr_start, addr_end;
 static int __meminitdata node_start;
 
-int __meminit vmemmap_populate(struct page *start, unsigned long nr, int node)
+int __meminit vmemmap_populate(unsigned long vstart, unsigned long vend,
+			       int node)
 {
-	unsigned long vstart = (unsigned long) start;
-	unsigned long vend = (unsigned long) (start + nr);
 	unsigned long phys_start = (vstart - VMEMMAP_BASE);
 	unsigned long phys_end = (vend - VMEMMAP_BASE);
 	unsigned long addr = phys_start & VMEMMAP_CHUNK_MASK;
@@ -2236,7 +2217,7 @@ void __meminit vmemmap_populate_print_last(void)
 	}
 }
 
-void vmemmap_free(struct page *memmap, unsigned long nr_pages)
+void vmemmap_free(unsigned long start, unsigned long end)
 {
 }
 
diff --git a/arch/sparc/mm/iommu.c b/arch/sparc/mm/iommu.c
index 0f4f719..28f96f2 100644
--- a/arch/sparc/mm/iommu.c
+++ b/arch/sparc/mm/iommu.c
@@ -34,7 +34,7 @@
 #define IOMMU_RNGE	IOMMU_RNGE_256MB
 #define IOMMU_START	0xF0000000
 #define IOMMU_WINSIZE	(256*1024*1024U)
-#define IOMMU_NPTES	(IOMMU_WINSIZE/PAGE_SIZE)	/* 64K PTEs, 265KB */
+#define IOMMU_NPTES	(IOMMU_WINSIZE/PAGE_SIZE)	/* 64K PTEs, 256KB */
 #define IOMMU_ORDER	6				/* 4096 * (1<<6) */
 
 /* srmmu.c */
diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c
index c38bb72..036c279 100644
--- a/arch/sparc/mm/srmmu.c
+++ b/arch/sparc/mm/srmmu.c
@@ -280,7 +280,9 @@ static void __init srmmu_nocache_init(void)
 		SRMMU_NOCACHE_ALIGN_MAX, 0UL);
 	memset(srmmu_nocache_pool, 0, srmmu_nocache_size);
 
-	srmmu_nocache_bitmap = __alloc_bootmem(bitmap_bits >> 3, SMP_CACHE_BYTES, 0UL);
+	srmmu_nocache_bitmap =
+		__alloc_bootmem(BITS_TO_LONGS(bitmap_bits) * sizeof(long),
+				SMP_CACHE_BYTES, 0UL);
 	bit_map_init(&srmmu_nocache_map, srmmu_nocache_bitmap, bitmap_bits);
 
 	srmmu_swapper_pg_dir = __srmmu_get_nocache(SRMMU_PGD_TABLE_SIZE, SRMMU_PGD_TABLE_SIZE);
diff --git a/arch/sparc/net/bpf_jit_comp.c b/arch/sparc/net/bpf_jit_comp.c
index 3109ca6..d36a85e 100644
--- a/arch/sparc/net/bpf_jit_comp.c
+++ b/arch/sparc/net/bpf_jit_comp.c
@@ -795,13 +795,9 @@ cond_branch:			f_offset = addrs[i + filter[i].jf];
 	}
 
 	if (bpf_jit_enable > 1)
-		pr_err("flen=%d proglen=%u pass=%d image=%p\n",
-		       flen, proglen, pass, image);
+		bpf_jit_dump(flen, proglen, pass, image);
 
 	if (image) {
-		if (bpf_jit_enable > 1)
-			print_hex_dump(KERN_ERR, "JIT code: ", DUMP_PREFIX_ADDRESS,
-				       16, 1, image, proglen, false);
 		bpf_flush_icache(image, image + proglen);
 		fp->bpf_func = (void *)image;
 	}
diff --git a/arch/sparc/power/Makefile b/arch/sparc/power/Makefile
new file mode 100644
index 0000000..3201ace
--- /dev/null
+++ b/arch/sparc/power/Makefile
@@ -0,0 +1,3 @@
+# Makefile for Sparc-specific hibernate files.
+
+obj-$(CONFIG_HIBERNATION)	+= hibernate.o hibernate_asm.o
diff --git a/arch/sparc/power/hibernate.c b/arch/sparc/power/hibernate.c
new file mode 100644
index 0000000..42b0b8c
--- /dev/null
+++ b/arch/sparc/power/hibernate.c
@@ -0,0 +1,42 @@
+/*
+ * hibernate.c:  Hibernaton support specific for sparc64.
+ *
+ * Copyright (C) 2013 Kirill V Tkhai (tkhai@yandex.ru)
+ */
+
+#include <linux/mm.h>
+
+#include <asm/hibernate.h>
+#include <asm/visasm.h>
+#include <asm/page.h>
+#include <asm/tlb.h>
+
+/* References to section boundaries */
+extern const void __nosave_begin, __nosave_end;
+
+struct saved_context saved_context;
+
+/*
+ *	pfn_is_nosave - check if given pfn is in the 'nosave' section
+ */
+
+int pfn_is_nosave(unsigned long pfn)
+{
+	unsigned long nosave_begin_pfn = PFN_DOWN((unsigned long)&__nosave_begin);
+	unsigned long nosave_end_pfn = PFN_DOWN((unsigned long)&__nosave_end);
+
+	return (pfn >= nosave_begin_pfn) && (pfn < nosave_end_pfn);
+}
+
+void save_processor_state(void)
+{
+	save_and_clear_fpu();
+}
+
+void restore_processor_state(void)
+{
+	struct mm_struct *mm = current->active_mm;
+
+	load_secondary_context(mm);
+	tsb_context_switch(mm);
+}
diff --git a/arch/sparc/power/hibernate_asm.S b/arch/sparc/power/hibernate_asm.S
new file mode 100644
index 0000000..7994216
--- /dev/null
+++ b/arch/sparc/power/hibernate_asm.S
@@ -0,0 +1,131 @@
+/*
+ * hibernate_asm.S:  Hibernaton support specific for sparc64.
+ *
+ * Copyright (C) 2013 Kirill V Tkhai (tkhai@yandex.ru)
+ */
+
+#include <linux/linkage.h>
+
+#include <asm/asm-offsets.h>
+#include <asm/cpudata.h>
+#include <asm/page.h>
+
+ENTRY(swsusp_arch_suspend)
+	save	%sp, -128, %sp
+	save	%sp, -128, %sp
+	flushw
+
+	setuw	saved_context, %g3
+
+	/* Save window regs */
+	rdpr	%cwp, %g2
+	stx	%g2, [%g3 + SC_REG_CWP]
+	rdpr	%wstate, %g2
+	stx	%g2, [%g3 + SC_REG_WSTATE]
+	stx	%fp, [%g3 + SC_REG_FP]
+
+	/* Save state regs */
+	rdpr	%tick, %g2
+	stx	%g2, [%g3 + SC_REG_TICK]
+	rdpr	%pstate, %g2
+	stx	%g2, [%g3 + SC_REG_PSTATE]
+
+	/* Save global regs */
+	stx	%g4, [%g3 + SC_REG_G4]
+	stx	%g5, [%g3 + SC_REG_G5]
+	stx	%g6, [%g3 + SC_REG_G6]
+
+	call	swsusp_save
+	 nop
+
+	mov	%o0, %i0
+	restore
+
+	mov	%o0, %i0
+	ret
+	 restore
+
+ENTRY(swsusp_arch_resume)
+	/* Write restore_pblist to %l0 */
+	sethi	%hi(restore_pblist), %l0
+	ldx	[%l0 + %lo(restore_pblist)], %l0
+
+	call	__flush_tlb_all
+	 nop
+
+	/* Write PAGE_OFFSET to %g7 */
+	sethi	%uhi(PAGE_OFFSET), %g7
+	sllx	%g7, 32, %g7
+
+	setuw	(PAGE_SIZE-8), %g3
+
+	/* Use MMU Bypass */
+	rd	%asi, %g1
+	wr	%g0, ASI_PHYS_USE_EC, %asi
+
+	ba	fill_itlb
+	 nop
+
+pbe_loop:
+	cmp	%l0, %g0
+	be	restore_ctx
+	 sub	%l0, %g7, %l0
+
+	ldxa	[%l0    ] %asi, %l1 /* address */
+	ldxa	[%l0 + 8] %asi, %l2 /* orig_address */
+
+	/* phys addr */
+	sub	%l1, %g7, %l1
+	sub	%l2, %g7, %l2
+
+	mov	%g3, %l3 /* PAGE_SIZE-8 */
+copy_loop:
+	ldxa	[%l1 + %l3] ASI_PHYS_USE_EC, %g2
+	stxa	%g2, [%l2 + %l3] ASI_PHYS_USE_EC
+	cmp	%l3, %g0
+	bne	copy_loop
+	 sub	%l3, 8, %l3
+
+	/* next pbe */
+	ba	pbe_loop
+	 ldxa	[%l0 + 16] %asi, %l0
+
+restore_ctx:
+	setuw	saved_context, %g3
+
+	/* Restore window regs */
+	wrpr    %g0, 0, %canrestore
+	wrpr    %g0, 0, %otherwin
+	wrpr	%g0, 6, %cansave
+	wrpr    %g0, 0, %cleanwin
+
+	ldxa	[%g3 + SC_REG_CWP] %asi, %g2
+	wrpr	%g2, %cwp
+	ldxa	[%g3 + SC_REG_WSTATE] %asi, %g2
+	wrpr	%g2, %wstate
+	ldxa	[%g3 + SC_REG_FP] %asi, %fp
+
+	/* Restore state regs */
+	ldxa	[%g3 + SC_REG_PSTATE] %asi, %g2
+	wrpr	%g2, %pstate
+	ldxa	[%g3 + SC_REG_TICK] %asi, %g2
+	wrpr	%g2, %tick
+
+	/* Restore global regs */
+	ldxa	[%g3 + SC_REG_G4] %asi, %g4
+	ldxa	[%g3 + SC_REG_G5] %asi, %g5
+	ldxa	[%g3 + SC_REG_G6] %asi, %g6
+
+	wr	%g1, %g0, %asi
+
+	restore
+	restore
+
+	wrpr	%g0, 14, %pil
+
+	retl
+	 mov	%g0, %o0
+
+fill_itlb:
+	ba	pbe_loop
+	 wrpr	%g0, 15, %pil
diff --git a/arch/tile/Kconfig b/arch/tile/Kconfig
index 25877ae..5b6a40d 100644
--- a/arch/tile/Kconfig
+++ b/arch/tile/Kconfig
@@ -16,12 +16,15 @@ config TILE
 	select GENERIC_PENDING_IRQ if SMP
 	select GENERIC_IRQ_SHOW
 	select HAVE_DEBUG_BUGVERBOSE
-	select HAVE_SYSCALL_WRAPPERS if TILEGX
 	select VIRT_TO_BUS
 	select SYS_HYPERVISOR
+	select ARCH_HAS_DEBUG_STRICT_USER_COPY_CHECKS
 	select ARCH_HAVE_NMI_SAFE_CMPXCHG
 	select GENERIC_CLOCKEVENTS
 	select MODULES_USE_ELF_RELA
+	select HAVE_ARCH_TRACEHOOK
+	select HAVE_SYSCALL_TRACEPOINTS
+	select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
 
 # FIXME: investigate whether we need/want these options.
 #	select HAVE_IOREMAP_PROT
@@ -40,9 +43,6 @@ config MMU
 config GENERIC_CSUM
 	def_bool y
 
-config SEMAPHORE_SLEEPERS
-	def_bool y
-
 config HAVE_ARCH_ALLOC_REMAP
 	def_bool y
 
@@ -67,12 +67,6 @@ config HUGETLB_SUPER_PAGES
 config RWSEM_GENERIC_SPINLOCK
 	def_bool y
 
-# We have a very flat architecture from a migration point of view,
-# so save boot time by presetting this (particularly useful on tile-sim).
-config DEFAULT_MIGRATION_COST
-	int
-	default "10000000"
-
 # We only support gcc 4.4 and above, so this should work.
 config ARCH_SUPPORTS_OPTIMIZED_INLINING
 	def_bool y
@@ -114,13 +108,6 @@ config STRICT_DEVMEM
 config SMP
 	def_bool y
 
-# Allow checking for compile-time determined overflow errors in
-# copy_from_user().  There are still unprovable places in the
-# generic code as of 2.6.34, so this option is not really compatible
-# with -Werror, which is more useful in general.
-config DEBUG_COPY_FROM_USER
-	def_bool n
-
 config HVC_TILE
 	depends on TTY
 	select HVC_DRIVER
@@ -420,11 +407,6 @@ endmenu
 
 menu "Executable file formats"
 
-# only elf supported
-config KCORE_ELF
-	def_bool y
-	depends on PROC_FS
-
 source "fs/Kconfig.binfmt"
 
 endmenu
diff --git a/arch/tile/include/asm/atomic.h b/arch/tile/include/asm/atomic.h
index f246142..e71387a 100644
--- a/arch/tile/include/asm/atomic.h
+++ b/arch/tile/include/asm/atomic.h
@@ -131,4 +131,25 @@ static inline int atomic_read(const atomic_t *v)
 #include <asm/atomic_64.h>
 #endif
 
+#ifndef __ASSEMBLY__
+
+static inline long long atomic64_dec_if_positive(atomic64_t *v)
+{
+	long long c, old, dec;
+
+	c = atomic64_read(v);
+	for (;;) {
+		dec = c - 1;
+		if (unlikely(dec < 0))
+			break;
+		old = atomic64_cmpxchg((v), c, dec);
+		if (likely(old == c))
+			break;
+		c = old;
+	}
+	return dec;
+}
+
+#endif /* __ASSEMBLY__ */
+
 #endif /* _ASM_TILE_ATOMIC_H */
diff --git a/arch/tile/include/asm/hugetlb.h b/arch/tile/include/asm/hugetlb.h
index 0f885af..3257733 100644
--- a/arch/tile/include/asm/hugetlb.h
+++ b/arch/tile/include/asm/hugetlb.h
@@ -16,6 +16,7 @@
 #define _ASM_TILE_HUGETLB_H
 
 #include <asm/page.h>
+#include <asm-generic/hugetlb.h>
 
 
 static inline int is_hugepage_only_range(struct mm_struct *mm,
diff --git a/arch/tile/include/asm/ptrace.h b/arch/tile/include/asm/ptrace.h
index 2e83fc1..fd41226 100644
--- a/arch/tile/include/asm/ptrace.h
+++ b/arch/tile/include/asm/ptrace.h
@@ -44,7 +44,8 @@ typedef unsigned long pt_reg_t;
 struct pt_regs *get_pt_regs(struct pt_regs *);
 
 /* Trace the current syscall. */
-extern void do_syscall_trace(void);
+extern int do_syscall_trace_enter(struct pt_regs *regs);
+extern void do_syscall_trace_exit(struct pt_regs *regs);
 
 #define arch_has_single_step()	(1)
 
diff --git a/arch/tile/include/asm/syscall.h b/arch/tile/include/asm/syscall.h
index d35e0dc..9644b88 100644
--- a/arch/tile/include/asm/syscall.h
+++ b/arch/tile/include/asm/syscall.h
@@ -22,6 +22,12 @@
 #include <linux/err.h>
 #include <arch/abi.h>
 
+/* The array of function pointers for syscalls. */
+extern void *sys_call_table[];
+#ifdef CONFIG_COMPAT
+extern void *compat_sys_call_table[];
+#endif
+
 /*
  * Only the low 32 bits of orig_r0 are meaningful, so we return int.
  * This importantly ignores the high bits on 64-bit, so comparisons
diff --git a/arch/tile/include/asm/syscalls.h b/arch/tile/include/asm/syscalls.h
index 78886e2..07b2984 100644
--- a/arch/tile/include/asm/syscalls.h
+++ b/arch/tile/include/asm/syscalls.h
@@ -24,12 +24,6 @@
 #include <linux/types.h>
 #include <linux/compat.h>
 
-/* The array of function pointers for syscalls. */
-extern void *sys_call_table[];
-#ifdef CONFIG_COMPAT
-extern void *compat_sys_call_table[];
-#endif
-
 /*
  * Note that by convention, any syscall which requires the current
  * register set takes an additional "struct pt_regs *" pointer; a
diff --git a/arch/tile/include/asm/thread_info.h b/arch/tile/include/asm/thread_info.h
index e9c670d..c96331e 100644
--- a/arch/tile/include/asm/thread_info.h
+++ b/arch/tile/include/asm/thread_info.h
@@ -124,6 +124,7 @@ extern void _cpu_idle(void);
 #define TIF_SECCOMP		6	/* secure computing */
 #define TIF_MEMDIE		7	/* OOM killer at work */
 #define TIF_NOTIFY_RESUME	8	/* callback before returning to user */
+#define TIF_SYSCALL_TRACEPOINT	9	/* syscall tracepoint instrumentation */
 
 #define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
@@ -134,12 +135,19 @@ extern void _cpu_idle(void);
 #define _TIF_SECCOMP		(1<<TIF_SECCOMP)
 #define _TIF_MEMDIE		(1<<TIF_MEMDIE)
 #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
+#define _TIF_SYSCALL_TRACEPOINT	(1<<TIF_SYSCALL_TRACEPOINT)
 
 /* Work to do on any return to user space. */
 #define _TIF_ALLWORK_MASK \
   (_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_SINGLESTEP|\
    _TIF_ASYNC_TLB|_TIF_NOTIFY_RESUME)
 
+/* Work to do at syscall entry. */
+#define _TIF_SYSCALL_ENTRY_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_TRACEPOINT)
+
+/* Work to do at syscall exit. */
+#define _TIF_SYSCALL_EXIT_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_TRACEPOINT)
+
 /*
  * Thread-synchronous status.
  *
diff --git a/arch/tile/include/asm/uaccess.h b/arch/tile/include/asm/uaccess.h
index 9ab078a..8a082bc 100644
--- a/arch/tile/include/asm/uaccess.h
+++ b/arch/tile/include/asm/uaccess.h
@@ -395,7 +395,12 @@ _copy_from_user(void *to, const void __user *from, unsigned long n)
 	return n;
 }
 
-#ifdef CONFIG_DEBUG_COPY_FROM_USER
+#ifdef CONFIG_DEBUG_STRICT_USER_COPY_CHECKS
+/*
+ * There are still unprovable places in the generic code as of 2.6.34, so this
+ * option is not really compatible with -Werror, which is more useful in
+ * general.
+ */
 extern void copy_from_user_overflow(void)
 	__compiletime_warning("copy_from_user() size is not provably correct");
 
diff --git a/arch/tile/include/uapi/asm/unistd.h b/arch/tile/include/uapi/asm/unistd.h
index cd7b6dd..3866397 100644
--- a/arch/tile/include/uapi/asm/unistd.h
+++ b/arch/tile/include/uapi/asm/unistd.h
@@ -20,6 +20,8 @@
 /* Use the standard ABI for syscalls. */
 #include <asm-generic/unistd.h>
 
+#define NR_syscalls __NR_syscalls
+
 /* Additional Tilera-specific syscalls. */
 #define __NR_cacheflush	(__NR_arch_specific_syscall + 1)
 __SYSCALL(__NR_cacheflush, sys_cacheflush)
diff --git a/arch/tile/kernel/compat.c b/arch/tile/kernel/compat.c
index 6ea4cdb..ed37841 100644
--- a/arch/tile/kernel/compat.c
+++ b/arch/tile/kernel/compat.c
@@ -56,12 +56,6 @@ COMPAT_SYSCALL_DEFINE6(pwrite64, unsigned int, fd, char __user *, ubuf,
 	return sys_pwrite64(fd, ubuf, count, ((loff_t)high << 32) | low);
 }
 
-COMPAT_SYSCALL_DEFINE4(lookup_dcookie, u32, low, u32, high,
-                       char __user *, buf, size_t, len)
-{
-	return sys_lookup_dcookie(((loff_t)high << 32) | low, buf, len);
-}
-
 COMPAT_SYSCALL_DEFINE6(sync_file_range2, int, fd, unsigned int, flags,
                        u32, offset_lo, u32, offset_hi,
                        u32, nbytes_lo, u32, nbytes_hi)
diff --git a/arch/tile/kernel/early_printk.c b/arch/tile/kernel/early_printk.c
index afb9c9a..34d72a1 100644
--- a/arch/tile/kernel/early_printk.c
+++ b/arch/tile/kernel/early_printk.c
@@ -17,6 +17,7 @@
 #include <linux/init.h>
 #include <linux/string.h>
 #include <linux/irqflags.h>
+#include <linux/printk.h>
 #include <asm/setup.h>
 #include <hv/hypervisor.h>
 
@@ -33,25 +34,8 @@ static struct console early_hv_console = {
 };
 
 /* Direct interface for emergencies */
-static struct console *early_console = &early_hv_console;
-static int early_console_initialized;
 static int early_console_complete;
 
-static void early_vprintk(const char *fmt, va_list ap)
-{
-	char buf[512];
-	int n = vscnprintf(buf, sizeof(buf), fmt, ap);
-	early_console->write(early_console, buf, n);
-}
-
-void early_printk(const char *fmt, ...)
-{
-	va_list ap;
-	va_start(ap, fmt);
-	early_vprintk(fmt, ap);
-	va_end(ap);
-}
-
 void early_panic(const char *fmt, ...)
 {
 	va_list ap;
@@ -69,14 +53,13 @@ static int __initdata keep_early;
 
 static int __init setup_early_printk(char *str)
 {
-	if (early_console_initialized)
+	if (early_console)
 		return 1;
 
 	if (str != NULL && strncmp(str, "keep", 4) == 0)
 		keep_early = 1;
 
 	early_console = &early_hv_console;
-	early_console_initialized = 1;
 	register_console(early_console);
 
 	return 0;
@@ -85,12 +68,12 @@ static int __init setup_early_printk(char *str)
 void __init disable_early_printk(void)
 {
 	early_console_complete = 1;
-	if (!early_console_initialized || !early_console)
+	if (!early_console)
 		return;
 	if (!keep_early) {
 		early_printk("disabling early console\n");
 		unregister_console(early_console);
-		early_console_initialized = 0;
+		early_console = NULL;
 	} else {
 		early_printk("keeping early console\n");
 	}
@@ -98,7 +81,7 @@ void __init disable_early_printk(void)
 
 void warn_early_printk(void)
 {
-	if (early_console_complete || early_console_initialized)
+	if (early_console_complete || early_console)
 		return;
 	early_printk("\
 Machine shutting down before console output is fully initialized.\n\
diff --git a/arch/tile/kernel/hardwall.c b/arch/tile/kernel/hardwall.c
index 20273ee..38ac189 100644
--- a/arch/tile/kernel/hardwall.c
+++ b/arch/tile/kernel/hardwall.c
@@ -914,7 +914,7 @@ static int hardwall_proc_show(struct seq_file *sf, void *v)
 static int hardwall_proc_open(struct inode *inode,
 			      struct file *file)
 {
-	return single_open(file, hardwall_proc_show, PDE(inode)->data);
+	return single_open(file, hardwall_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations hardwall_proc_fops = {
diff --git a/arch/tile/kernel/intvec_32.S b/arch/tile/kernel/intvec_32.S
index f212bf7..cb52d66 100644
--- a/arch/tile/kernel/intvec_32.S
+++ b/arch/tile/kernel/intvec_32.S
@@ -1201,7 +1201,10 @@ handle_syscall:
 	lw	r30, r31
 	andi    r30, r30, _TIF_SYSCALL_TRACE
 	bzt	r30, .Lrestore_syscall_regs
-	jal	do_syscall_trace
+	{
+	 PTREGS_PTR(r0, PTREGS_OFFSET_BASE)
+	 jal    do_syscall_trace_enter
+	}
 	FEEDBACK_REENTER(handle_syscall)
 
 	/*
@@ -1252,7 +1255,10 @@ handle_syscall:
 	lw	r30, r31
 	andi    r30, r30, _TIF_SYSCALL_TRACE
 	bzt     r30, 1f
-	jal	do_syscall_trace
+	{
+	 PTREGS_PTR(r0, PTREGS_OFFSET_BASE)
+	 jal    do_syscall_trace_exit
+	}
 	FEEDBACK_REENTER(handle_syscall)
 1:	{
 	 movei  r30, 0               /* not an NMI */
diff --git a/arch/tile/kernel/intvec_64.S b/arch/tile/kernel/intvec_64.S
index 4ea0809..85d4839 100644
--- a/arch/tile/kernel/intvec_64.S
+++ b/arch/tile/kernel/intvec_64.S
@@ -1000,13 +1000,19 @@ handle_syscall:
 
 	/* Trace syscalls, if requested. */
 	addi	r31, r31, THREAD_INFO_FLAGS_OFFSET
-	ld	r30, r31
-	andi    r30, r30, _TIF_SYSCALL_TRACE
+	{
+	 ld     r30, r31
+	 moveli r32, _TIF_SYSCALL_ENTRY_WORK
+	}
+	and     r30, r30, r32
 	{
 	 addi   r30, r31, THREAD_INFO_STATUS_OFFSET - THREAD_INFO_FLAGS_OFFSET
 	 beqzt	r30, .Lrestore_syscall_regs
 	}
-	jal	do_syscall_trace
+	{
+	 PTREGS_PTR(r0, PTREGS_OFFSET_BASE)
+	 jal    do_syscall_trace_enter
+	}
 	FEEDBACK_REENTER(handle_syscall)
 
 	/*
@@ -1071,13 +1077,19 @@ handle_syscall:
 	FEEDBACK_REENTER(handle_syscall)
 
 	/* Do syscall trace again, if requested. */
-	ld	r30, r31
-	andi    r0, r30, _TIF_SYSCALL_TRACE
+	{
+	 ld      r30, r31
+	 moveli  r32, _TIF_SYSCALL_EXIT_WORK
+	}
+	and      r0, r30, r32
 	{
 	 andi    r0, r30, _TIF_SINGLESTEP
 	 beqzt   r0, 1f
 	}
-	jal	do_syscall_trace
+	{
+	 PTREGS_PTR(r0, PTREGS_OFFSET_BASE)
+	 jal    do_syscall_trace_exit
+	}
 	FEEDBACK_REENTER(handle_syscall)
 	andi    r0, r30, _TIF_SINGLESTEP
 
diff --git a/arch/tile/kernel/ptrace.c b/arch/tile/kernel/ptrace.c
index 9835312..363b2dd 100644
--- a/arch/tile/kernel/ptrace.c
+++ b/arch/tile/kernel/ptrace.c
@@ -21,9 +21,13 @@
 #include <linux/uaccess.h>
 #include <linux/regset.h>
 #include <linux/elf.h>
+#include <linux/tracehook.h>
 #include <asm/traps.h>
 #include <arch/chip.h>
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/syscalls.h>
+
 void user_enable_single_step(struct task_struct *child)
 {
 	set_tsk_thread_flag(child, TIF_SINGLESTEP);
@@ -246,29 +250,26 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
 }
 #endif
 
-void do_syscall_trace(void)
+int do_syscall_trace_enter(struct pt_regs *regs)
 {
-	if (!test_thread_flag(TIF_SYSCALL_TRACE))
-		return;
+	if (test_thread_flag(TIF_SYSCALL_TRACE)) {
+		if (tracehook_report_syscall_entry(regs))
+			regs->regs[TREG_SYSCALL_NR] = -1;
+	}
 
-	if (!(current->ptrace & PT_PTRACED))
-		return;
+	if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
+		trace_sys_enter(regs, regs->regs[TREG_SYSCALL_NR]);
 
-	/*
-	 * The 0x80 provides a way for the tracing parent to distinguish
-	 * between a syscall stop and SIGTRAP delivery
-	 */
-	ptrace_notify(SIGTRAP|((current->ptrace & PT_TRACESYSGOOD) ? 0x80 : 0));
+	return regs->regs[TREG_SYSCALL_NR];
+}
 
-	/*
-	 * this isn't the same as continuing with a signal, but it will do
-	 * for normal use.  strace only continues with a signal if the
-	 * stopping signal is not SIGTRAP.  -brl
-	 */
-	if (current->exit_code) {
-		send_sig(current->exit_code, current, 1);
-		current->exit_code = 0;
-	}
+void do_syscall_trace_exit(struct pt_regs *regs)
+{
+	if (test_thread_flag(TIF_SYSCALL_TRACE))
+		tracehook_report_syscall_exit(regs, 0);
+
+	if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
+		trace_sys_exit(regs, regs->regs[TREG_SYSCALL_NR]);
 }
 
 void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int error_code)
diff --git a/arch/tile/kernel/setup.c b/arch/tile/kernel/setup.c
index d1e15f7..7a5aa1a 100644
--- a/arch/tile/kernel/setup.c
+++ b/arch/tile/kernel/setup.c
@@ -1004,15 +1004,8 @@ void __cpuinit setup_cpu(int boot)
 
 #ifdef CONFIG_BLK_DEV_INITRD
 
-/*
- * Note that the kernel can potentially support other compression
- * techniques than gz, though we don't do so by default.  If we ever
- * decide to do so we can either look for other filename extensions,
- * or just allow a file with this name to be compressed with an
- * arbitrary compressor (somewhat counterintuitively).
- */
 static int __initdata set_initramfs_file;
-static char __initdata initramfs_file[128] = "initramfs.cpio.gz";
+static char __initdata initramfs_file[128] = "initramfs";
 
 static int __init setup_initramfs_file(char *str)
 {
@@ -1026,9 +1019,9 @@ static int __init setup_initramfs_file(char *str)
 early_param("initramfs_file", setup_initramfs_file);
 
 /*
- * We look for an "initramfs.cpio.gz" file in the hvfs.
- * If there is one, we allocate some memory for it and it will be
- * unpacked to the initramfs.
+ * We look for a file called "initramfs" in the hvfs.  If there is one, we
+ * allocate some memory for it and it will be unpacked to the initramfs.
+ * If it's compressed, the initd code will uncompress it first.
  */
 static void __init load_hv_initrd(void)
 {
@@ -1038,10 +1031,16 @@ static void __init load_hv_initrd(void)
 
 	fd = hv_fs_findfile((HV_VirtAddr) initramfs_file);
 	if (fd == HV_ENOENT) {
-		if (set_initramfs_file)
+		if (set_initramfs_file) {
 			pr_warning("No such hvfs initramfs file '%s'\n",
 				   initramfs_file);
-		return;
+			return;
+		} else {
+			/* Try old backwards-compatible name. */
+			fd = hv_fs_findfile((HV_VirtAddr)"initramfs.cpio.gz");
+			if (fd == HV_ENOENT)
+				return;
+		}
 	}
 	BUG_ON(fd < 0);
 	stat = hv_fs_fstat(fd);
diff --git a/arch/tile/kernel/time.c b/arch/tile/kernel/time.c
index f6f50f2a..5ac397e 100644
--- a/arch/tile/kernel/time.c
+++ b/arch/tile/kernel/time.c
@@ -230,6 +230,10 @@ int setup_profiling_timer(unsigned int multiplier)
  */
 cycles_t ns2cycles(unsigned long nsecs)
 {
-	struct clock_event_device *dev = &__get_cpu_var(tile_timer);
+	/*
+	 * We do not have to disable preemption here as each core has the same
+	 * clock frequency.
+	 */
+	struct clock_event_device *dev = &__raw_get_cpu_var(tile_timer);
 	return ((u64)nsecs * dev->mult) >> dev->shift;
 }
diff --git a/arch/tile/lib/uaccess.c b/arch/tile/lib/uaccess.c
index f8d398c..030abe3 100644
--- a/arch/tile/lib/uaccess.c
+++ b/arch/tile/lib/uaccess.c
@@ -22,11 +22,3 @@ int __range_ok(unsigned long addr, unsigned long size)
 		 is_arch_mappable_range(addr, size));
 }
 EXPORT_SYMBOL(__range_ok);
-
-#ifdef CONFIG_DEBUG_COPY_FROM_USER
-void copy_from_user_overflow(void)
-{
-       WARN(1, "Buffer overflow detected!\n");
-}
-EXPORT_SYMBOL(copy_from_user_overflow);
-#endif
diff --git a/arch/tile/mm/mmap.c b/arch/tile/mm/mmap.c
index f96f4ce..d67d91e 100644
--- a/arch/tile/mm/mmap.c
+++ b/arch/tile/mm/mmap.c
@@ -66,10 +66,8 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
 	if (!is_32bit || rlimit(RLIMIT_STACK) == RLIM_INFINITY) {
 		mm->mmap_base = TASK_UNMAPPED_BASE;
 		mm->get_unmapped_area = arch_get_unmapped_area;
-		mm->unmap_area = arch_unmap_area;
 	} else {
 		mm->mmap_base = mmap_base(mm);
 		mm->get_unmapped_area = arch_get_unmapped_area_topdown;
-		mm->unmap_area = arch_unmap_area_topdown;
 	}
 }
diff --git a/arch/tile/mm/pgtable.c b/arch/tile/mm/pgtable.c
index b3b4972..dfd63ce 100644
--- a/arch/tile/mm/pgtable.c
+++ b/arch/tile/mm/pgtable.c
@@ -592,12 +592,7 @@ void iounmap(volatile void __iomem *addr_in)
 	   in parallel. Reuse of the virtual address is prevented by
 	   leaving it in the global lists until we're done with it.
 	   cpa takes care of the direct mappings. */
-	read_lock(&vmlist_lock);
-	for (p = vmlist; p; p = p->next) {
-		if (p->addr == addr)
-			break;
-	}
-	read_unlock(&vmlist_lock);
+	p = find_vm_area((void *)addr);
 
 	if (!p) {
 		pr_err("iounmap: bad address %p\n", addr);
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c
index 80b47cb..acbe6c6 100644
--- a/arch/um/drivers/chan_kern.c
+++ b/arch/um/drivers/chan_kern.c
@@ -568,11 +568,7 @@ void chan_interrupt(struct line *line, int irq)
 		reactivate_fd(chan->fd, irq);
 	if (err == -EIO) {
 		if (chan->primary) {
-			struct tty_struct *tty = tty_port_tty_get(&line->port);
-			if (tty != NULL) {
-				tty_hangup(tty);
-				tty_kref_put(tty);
-			}
+			tty_port_tty_hangup(&line->port, false);
 			if (line->chan_out != chan)
 				close_one_chan(line->chan_out, 1);
 		}
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index be541cf..8035145 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -248,7 +248,6 @@ static irqreturn_t line_write_interrupt(int irq, void *data)
 {
 	struct chan *chan = data;
 	struct line *line = chan->line;
-	struct tty_struct *tty;
 	int err;
 
 	/*
@@ -267,12 +266,7 @@ static irqreturn_t line_write_interrupt(int irq, void *data)
 	}
 	spin_unlock(&line->lock);
 
-	tty = tty_port_tty_get(&line->port);
-	if (tty == NULL)
-		return IRQ_NONE;
-
-	tty_wakeup(tty);
-	tty_kref_put(tty);
+	tty_port_tty_wakeup(&line->port);
 
 	return IRQ_HANDLED;
 }
diff --git a/arch/um/kernel/early_printk.c b/arch/um/kernel/early_printk.c
index 49480f0..4a0800b 100644
--- a/arch/um/kernel/early_printk.c
+++ b/arch/um/kernel/early_printk.c
@@ -16,7 +16,7 @@ static void early_console_write(struct console *con, const char *s, unsigned int
 	um_early_printk(s, n);
 }
 
-static struct console early_console = {
+static struct console early_console_dev = {
 	.name = "earlycon",
 	.write = early_console_write,
 	.flags = CON_BOOT,
@@ -25,8 +25,10 @@ static struct console early_console = {
 
 static int __init setup_early_printk(char *buf)
 {
-	register_console(&early_console);
-
+	if (!early_console) {
+		early_console = &early_console_dev;
+		register_console(&early_console_dev);
+	}
 	return 0;
 }
 
diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c
index 5abcbfb..9df292b 100644
--- a/arch/um/kernel/mem.c
+++ b/arch/um/kernel/mem.c
@@ -42,17 +42,12 @@ static unsigned long brk_end;
 static void setup_highmem(unsigned long highmem_start,
 			  unsigned long highmem_len)
 {
-	struct page *page;
 	unsigned long highmem_pfn;
 	int i;
 
 	highmem_pfn = __pa(highmem_start) >> PAGE_SHIFT;
-	for (i = 0; i < highmem_len >> PAGE_SHIFT; i++) {
-		page = &mem_map[highmem_pfn + i];
-		ClearPageReserved(page);
-		init_page_count(page);
-		__free_page(page);
-	}
+	for (i = 0; i < highmem_len >> PAGE_SHIFT; i++)
+		free_highmem_page(&mem_map[highmem_pfn + i]);
 }
 #endif
 
@@ -73,18 +68,13 @@ void __init mem_init(void)
 	totalram_pages = free_all_bootmem();
 	max_low_pfn = totalram_pages;
 #ifdef CONFIG_HIGHMEM
-	totalhigh_pages = highmem >> PAGE_SHIFT;
-	totalram_pages += totalhigh_pages;
+	setup_highmem(end_iomem, highmem);
 #endif
 	num_physpages = totalram_pages;
 	max_pfn = totalram_pages;
 	printk(KERN_INFO "Memory: %luk available\n",
 	       nr_free_pages() << (PAGE_SHIFT-10));
 	kmalloc_ok = 1;
-
-#ifdef CONFIG_HIGHMEM
-	setup_highmem(end_iomem, highmem);
-#endif
 }
 
 /*
@@ -254,15 +244,7 @@ void free_initmem(void)
 #ifdef CONFIG_BLK_DEV_INITRD
 void free_initrd_mem(unsigned long start, unsigned long end)
 {
-	if (start < 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++;
-	}
+	free_reserved_area(start, end, 0, "initrd");
 }
 #endif
 
diff --git a/arch/unicore32/Kconfig b/arch/unicore32/Kconfig
index 2943e3a..63521dc 100644
--- a/arch/unicore32/Kconfig
+++ b/arch/unicore32/Kconfig
@@ -24,7 +24,7 @@ config UNICORE32
 	  Please see web page at <http://www.pkunity.com/>.
 
 config GENERIC_GPIO
-	def_bool y
+	bool
 
 config GENERIC_CSUM
 	def_bool y
@@ -219,7 +219,6 @@ if ARCH_PUV3
 config PUV3_GPIO
 	bool
 	depends on !ARCH_FPGA
-	select GENERIC_GPIO
 	select GPIO_SYSFS
 	default y
 
diff --git a/arch/unicore32/kernel/cpu-ucv2.c b/arch/unicore32/kernel/cpu-ucv2.c
index 4a99f62..ba5a71c 100644
--- a/arch/unicore32/kernel/cpu-ucv2.c
+++ b/arch/unicore32/kernel/cpu-ucv2.c
@@ -52,15 +52,14 @@ static int ucv2_target(struct cpufreq_policy *policy,
 	struct cpufreq_freqs freqs;
 	struct clk *mclk = clk_get(NULL, "MAIN_CLK");
 
-	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
 
 	if (!clk_set_rate(mclk, target_freq * 1000)) {
 		freqs.old = cur;
 		freqs.new = target_freq;
-		freqs.cpu = 0;
 	}
 
-	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
 
 	return 0;
 }
diff --git a/arch/unicore32/kernel/early_printk.c b/arch/unicore32/kernel/early_printk.c
index 3922255..9be0d5d 100644
--- a/arch/unicore32/kernel/early_printk.c
+++ b/arch/unicore32/kernel/early_printk.c
@@ -33,21 +33,17 @@ static struct console early_ocd_console = {
 	.index =	-1,
 };
 
-/* Direct interface for emergencies */
-static struct console *early_console = &early_ocd_console;
-
-static int __initdata keep_early;
-
 static int __init setup_early_printk(char *buf)
 {
-	if (!buf)
+	int keep_early;
+
+	if (!buf || early_console)
 		return 0;
 
 	if (strstr(buf, "keep"))
 		keep_early = 1;
 
-	if (!strncmp(buf, "ocd", 3))
-		early_console = &early_ocd_console;
+	early_console = &early_ocd_console;
 
 	if (keep_early)
 		early_console->flags &= ~CON_BOOT;
diff --git a/arch/unicore32/mm/init.c b/arch/unicore32/mm/init.c
index de186bd..63df12d 100644
--- a/arch/unicore32/mm/init.c
+++ b/arch/unicore32/mm/init.c
@@ -66,6 +66,9 @@ void show_mem(unsigned int filter)
 	printk(KERN_DEFAULT "Mem-info:\n");
 	show_free_areas(filter);
 
+	if (filter & SHOW_MEM_FILTER_PAGE_COUNT)
+		return;
+
 	for_each_bank(i, mi) {
 		struct membank *bank = &mi->bank[i];
 		unsigned int pfn1, pfn2;
@@ -313,24 +316,6 @@ void __init bootmem_init(void)
 	max_pfn = max_high - PHYS_PFN_OFFSET;
 }
 
-static inline int free_area(unsigned long pfn, unsigned long end, char *s)
-{
-	unsigned int pages = 0, size = (end - pfn) << (PAGE_SHIFT - 10);
-
-	for (; pfn < end; pfn++) {
-		struct page *page = pfn_to_page(pfn);
-		ClearPageReserved(page);
-		init_page_count(page);
-		__free_page(page);
-		pages++;
-	}
-
-	if (size && s)
-		printk(KERN_INFO "Freeing %s memory: %dK\n", s, size);
-
-	return pages;
-}
-
 static inline void
 free_memmap(unsigned long start_pfn, unsigned long end_pfn)
 {
@@ -404,9 +389,9 @@ void __init mem_init(void)
 
 	max_mapnr   = pfn_to_page(max_pfn + PHYS_PFN_OFFSET) - mem_map;
 
-	/* this will put all unused low memory onto the freelists */
 	free_unused_memmap(&meminfo);
 
+	/* this will put all unused low memory onto the freelists */
 	totalram_pages += free_all_bootmem();
 
 	reserved_pages = free_pages = 0;
@@ -491,9 +476,7 @@ void __init mem_init(void)
 
 void free_initmem(void)
 {
-	totalram_pages += free_area(__phys_to_pfn(__pa(__init_begin)),
-				    __phys_to_pfn(__pa(__init_end)),
-				    "init");
+	free_initmem_default(0);
 }
 
 #ifdef CONFIG_BLK_DEV_INITRD
@@ -503,9 +486,7 @@ static int keep_initrd;
 void free_initrd_mem(unsigned long start, unsigned long end)
 {
 	if (!keep_initrd)
-		totalram_pages += free_area(__phys_to_pfn(__pa(start)),
-					    __phys_to_pfn(__pa(end)),
-					    "initrd");
+		free_reserved_area(start, end, 0, "initrd");
 }
 
 static int __init keepinitrd_setup(char *__unused)
diff --git a/arch/unicore32/mm/ioremap.c b/arch/unicore32/mm/ioremap.c
index b7a6055..13068ee 100644
--- a/arch/unicore32/mm/ioremap.c
+++ b/arch/unicore32/mm/ioremap.c
@@ -235,7 +235,7 @@ EXPORT_SYMBOL(__uc32_ioremap_cached);
 void __uc32_iounmap(volatile void __iomem *io_addr)
 {
 	void *addr = (void *)(PAGE_MASK & (unsigned long)io_addr);
-	struct vm_struct **p, *tmp;
+	struct vm_struct *vm;
 
 	/*
 	 * If this is a section based mapping we need to handle it
@@ -244,17 +244,10 @@ void __uc32_iounmap(volatile void __iomem *io_addr)
 	 * all the mappings before the area can be reclaimed
 	 * by someone else.
 	 */
-	write_lock(&vmlist_lock);
-	for (p = &vmlist ; (tmp = *p) ; p = &tmp->next) {
-		if ((tmp->flags & VM_IOREMAP) && (tmp->addr == addr)) {
-			if (tmp->flags & VM_UNICORE_SECTION_MAPPING) {
-				unmap_area_sections((unsigned long)tmp->addr,
-						    tmp->size);
-			}
-			break;
-		}
-	}
-	write_unlock(&vmlist_lock);
+	vm = find_vm_area(addr);
+	if (vm && (vm->flags & VM_IOREMAP) &&
+		(vm->flags & VM_UNICORE_SECTION_MAPPING))
+		unmap_area_sections((unsigned long)vm->addr, vm->size);
 
 	vunmap(addr);
 }
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 70c0f3d..75267ec 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -20,6 +20,7 @@ config X86_64
 ### Arch settings
 config X86
 	def_bool y
+	select ARCH_HAS_DEBUG_STRICT_USER_COPY_CHECKS
 	select HAVE_AOUT if X86_32
 	select HAVE_UNSTABLE_SCHED_CLOCK
 	select ARCH_SUPPORTS_NUMA_BALANCING
@@ -64,6 +65,7 @@ config X86
 	select HAVE_KERNEL_LZMA
 	select HAVE_KERNEL_XZ
 	select HAVE_KERNEL_LZO
+	select HAVE_KERNEL_LZ4
 	select HAVE_HW_BREAKPOINT
 	select HAVE_MIXED_BREAKPOINTS_REGS
 	select PERF_EVENTS
@@ -389,7 +391,7 @@ config X86_NUMACHIP
 
 config X86_VSMP
 	bool "ScaleMP vSMP"
-	select PARAVIRT_GUEST
+	select HYPERVISOR_GUEST
 	select PARAVIRT
 	depends on X86_64 && PCI
 	depends on X86_EXTENDED_PLATFORM
@@ -596,44 +598,17 @@ config SCHED_OMIT_FRAME_POINTER
 
 	  If in doubt, say "Y".
 
-menuconfig PARAVIRT_GUEST
-	bool "Paravirtualized guest support"
+menuconfig HYPERVISOR_GUEST
+	bool "Linux guest support"
 	---help---
-	  Say Y here to get to see options related to running Linux under
-	  various hypervisors.  This option alone does not add any kernel code.
+	  Say Y here to enable options for running Linux under various hyper-
+	  visors. This option enables basic hypervisor detection and platform
+	  setup.
 
-	  If you say N, all options in this submenu will be skipped and disabled.
+	  If you say N, all options in this submenu will be skipped and
+	  disabled, and Linux guest support won't be built in.
 
-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_GUEST
-	bool "KVM Guest support (including kvmclock)"
-	select PARAVIRT
-	select PARAVIRT
-	select PARAVIRT_CLOCK
-	default y if PARAVIRT_GUEST
-	---help---
-	  This option enables various optimizations for running under the KVM
-	  hypervisor. It includes a paravirtualized clock, so that instead
-	  of relying on a PIT (or probably other) emulation by the
-	  underlying device model, the host provides the guest with
-	  timing infrastructure such as time of day, and system time
-
-source "arch/x86/lguest/Kconfig"
+if HYPERVISOR_GUEST
 
 config PARAVIRT
 	bool "Enable paravirtualization code"
@@ -643,6 +618,13 @@ config PARAVIRT
 	  over full virtualization.  However, when run without a hypervisor
 	  the kernel is theoretically slower and slightly larger.
 
+config PARAVIRT_DEBUG
+	bool "paravirt-ops debugging"
+	depends on PARAVIRT && DEBUG_KERNEL
+	---help---
+	  Enable to debug paravirt_ops internals.  Specifically, BUG if
+	  a paravirt_op is missing when it is called.
+
 config PARAVIRT_SPINLOCKS
 	bool "Paravirtualization layer for spinlocks"
 	depends on PARAVIRT && SMP
@@ -656,17 +638,38 @@ config PARAVIRT_SPINLOCKS
 
 	  If you are unsure how to answer this question, answer N.
 
-config PARAVIRT_CLOCK
-	bool
+source "arch/x86/xen/Kconfig"
 
-endif
+config KVM_GUEST
+	bool "KVM Guest support (including kvmclock)"
+	depends on PARAVIRT
+	select PARAVIRT_CLOCK
+	default y
+	---help---
+	  This option enables various optimizations for running under the KVM
+	  hypervisor. It includes a paravirtualized clock, so that instead
+	  of relying on a PIT (or probably other) emulation by the
+	  underlying device model, the host provides the guest with
+	  timing infrastructure such as time of day, and system time
 
-config PARAVIRT_DEBUG
-	bool "paravirt-ops debugging"
-	depends on PARAVIRT && DEBUG_KERNEL
+source "arch/x86/lguest/Kconfig"
+
+config PARAVIRT_TIME_ACCOUNTING
+	bool "Paravirtual steal time accounting"
+	depends on PARAVIRT
+	default n
 	---help---
-	  Enable to debug paravirt_ops internals.  Specifically, BUG if
-	  a paravirt_op is missing when it is called.
+	  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.
+
+config PARAVIRT_CLOCK
+	bool
+
+endif #HYPERVISOR_GUEST
 
 config NO_BOOTMEM
 	def_bool y
diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug
index b322f12..dea0da5 100644
--- a/arch/x86/Kconfig.debug
+++ b/arch/x86/Kconfig.debug
@@ -292,20 +292,6 @@ config OPTIMIZE_INLINING
 
 	  If unsure, say N.
 
-config DEBUG_STRICT_USER_COPY_CHECKS
-	bool "Strict copy size checks"
-	depends on DEBUG_KERNEL && !TRACE_BRANCH_PROFILING
-	---help---
-	  Enabling this option turns a certain set of sanity checks for user
-	  copy operations into compile time failures.
-
-	  The copy_from_user() etc checks are there to help test if there
-	  are sufficient security checks on the length argument of
-	  the copy operation, by having gcc prove that the argument is
-	  within bounds.
-
-	  If unsure, or if you run an older (pre 4.4) gcc, say N.
-
 config DEBUG_NMI_SELFTEST
 	bool "NMI Selftest"
 	depends on DEBUG_KERNEL && X86_LOCAL_APIC
diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
index 8a84501..c275db5 100644
--- a/arch/x86/boot/compressed/Makefile
+++ b/arch/x86/boot/compressed/Makefile
@@ -4,7 +4,7 @@
 # create a compressed vmlinux image from the original vmlinux
 #
 
-targets := vmlinux.lds vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma vmlinux.bin.xz vmlinux.bin.lzo head_$(BITS).o misc.o string.o cmdline.o early_serial_console.o piggy.o
+targets := vmlinux.lds vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma vmlinux.bin.xz vmlinux.bin.lzo vmlinux.bin.lz4 head_$(BITS).o misc.o string.o cmdline.o early_serial_console.o piggy.o
 
 KBUILD_CFLAGS := -m$(BITS) -D__KERNEL__ $(LINUX_INCLUDE) -O2
 KBUILD_CFLAGS += -fno-strict-aliasing -fPIC
@@ -64,12 +64,15 @@ $(obj)/vmlinux.bin.xz: $(vmlinux.bin.all-y) FORCE
 	$(call if_changed,xzkern)
 $(obj)/vmlinux.bin.lzo: $(vmlinux.bin.all-y) FORCE
 	$(call if_changed,lzo)
+$(obj)/vmlinux.bin.lz4: $(vmlinux.bin.all-y) FORCE
+	$(call if_changed,lz4)
 
 suffix-$(CONFIG_KERNEL_GZIP)	:= gz
 suffix-$(CONFIG_KERNEL_BZIP2)	:= bz2
 suffix-$(CONFIG_KERNEL_LZMA)	:= lzma
 suffix-$(CONFIG_KERNEL_XZ)	:= xz
 suffix-$(CONFIG_KERNEL_LZO) 	:= lzo
+suffix-$(CONFIG_KERNEL_LZ4) 	:= lz4
 
 quiet_cmd_mkpiggy = MKPIGGY $@
       cmd_mkpiggy = $(obj)/mkpiggy $< > $@ || ( rm -f $@ ; false )
diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
index c1d383d..16f24e6 100644
--- a/arch/x86/boot/compressed/head_64.S
+++ b/arch/x86/boot/compressed/head_64.S
@@ -52,7 +52,7 @@ ENTRY(startup_32)
 	jnz 1f
 
 	cli
-	movl	$(__KERNEL_DS), %eax
+	movl	$(__BOOT_DS), %eax
 	movl	%eax, %ds
 	movl	%eax, %es
 	movl	%eax, %ss
diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c
index 7cb56c6..0319c88 100644
--- a/arch/x86/boot/compressed/misc.c
+++ b/arch/x86/boot/compressed/misc.c
@@ -145,6 +145,10 @@ static int lines, cols;
 #include "../../../../lib/decompress_unlzo.c"
 #endif
 
+#ifdef CONFIG_KERNEL_LZ4
+#include "../../../../lib/decompress_unlz4.c"
+#endif
+
 static void scroll(void)
 {
 	int i;
diff --git a/arch/x86/crypto/Makefile b/arch/x86/crypto/Makefile
index 63947a8..03cd731 100644
--- a/arch/x86/crypto/Makefile
+++ b/arch/x86/crypto/Makefile
@@ -2,6 +2,8 @@
 # Arch-specific CryptoAPI modules.
 #
 
+avx_supported := $(call as-instr,vpxor %xmm0$(comma)%xmm0$(comma)%xmm0,yes,no)
+
 obj-$(CONFIG_CRYPTO_ABLK_HELPER_X86) += ablk_helper.o
 obj-$(CONFIG_CRYPTO_GLUE_HELPER_X86) += glue_helper.o
 
@@ -12,22 +14,29 @@ obj-$(CONFIG_CRYPTO_SERPENT_SSE2_586) += serpent-sse2-i586.o
 
 obj-$(CONFIG_CRYPTO_AES_X86_64) += aes-x86_64.o
 obj-$(CONFIG_CRYPTO_CAMELLIA_X86_64) += camellia-x86_64.o
-obj-$(CONFIG_CRYPTO_CAMELLIA_AESNI_AVX_X86_64) += camellia-aesni-avx-x86_64.o
-obj-$(CONFIG_CRYPTO_CAST5_AVX_X86_64) += cast5-avx-x86_64.o
-obj-$(CONFIG_CRYPTO_CAST6_AVX_X86_64) += cast6-avx-x86_64.o
 obj-$(CONFIG_CRYPTO_BLOWFISH_X86_64) += blowfish-x86_64.o
 obj-$(CONFIG_CRYPTO_TWOFISH_X86_64) += twofish-x86_64.o
 obj-$(CONFIG_CRYPTO_TWOFISH_X86_64_3WAY) += twofish-x86_64-3way.o
-obj-$(CONFIG_CRYPTO_TWOFISH_AVX_X86_64) += twofish-avx-x86_64.o
 obj-$(CONFIG_CRYPTO_SALSA20_X86_64) += salsa20-x86_64.o
 obj-$(CONFIG_CRYPTO_SERPENT_SSE2_X86_64) += serpent-sse2-x86_64.o
-obj-$(CONFIG_CRYPTO_SERPENT_AVX_X86_64) += serpent-avx-x86_64.o
 obj-$(CONFIG_CRYPTO_AES_NI_INTEL) += aesni-intel.o
 obj-$(CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL) += ghash-clmulni-intel.o
 
 obj-$(CONFIG_CRYPTO_CRC32C_INTEL) += crc32c-intel.o
 obj-$(CONFIG_CRYPTO_SHA1_SSSE3) += sha1-ssse3.o
 obj-$(CONFIG_CRYPTO_CRC32_PCLMUL) += crc32-pclmul.o
+obj-$(CONFIG_CRYPTO_SHA256_SSSE3) += sha256-ssse3.o
+obj-$(CONFIG_CRYPTO_SHA512_SSSE3) += sha512-ssse3.o
+
+# These modules require assembler to support AVX.
+ifeq ($(avx_supported),yes)
+	obj-$(CONFIG_CRYPTO_CAMELLIA_AESNI_AVX_X86_64) += \
+						camellia-aesni-avx-x86_64.o
+	obj-$(CONFIG_CRYPTO_CAST5_AVX_X86_64) += cast5-avx-x86_64.o
+	obj-$(CONFIG_CRYPTO_CAST6_AVX_X86_64) += cast6-avx-x86_64.o
+	obj-$(CONFIG_CRYPTO_TWOFISH_AVX_X86_64) += twofish-avx-x86_64.o
+	obj-$(CONFIG_CRYPTO_SERPENT_AVX_X86_64) += serpent-avx-x86_64.o
+endif
 
 aes-i586-y := aes-i586-asm_32.o aes_glue.o
 twofish-i586-y := twofish-i586-asm_32.o twofish_glue.o
@@ -36,21 +45,28 @@ serpent-sse2-i586-y := serpent-sse2-i586-asm_32.o serpent_sse2_glue.o
 
 aes-x86_64-y := aes-x86_64-asm_64.o aes_glue.o
 camellia-x86_64-y := camellia-x86_64-asm_64.o camellia_glue.o
-camellia-aesni-avx-x86_64-y := camellia-aesni-avx-asm_64.o \
-			       camellia_aesni_avx_glue.o
-cast5-avx-x86_64-y := cast5-avx-x86_64-asm_64.o cast5_avx_glue.o
-cast6-avx-x86_64-y := cast6-avx-x86_64-asm_64.o cast6_avx_glue.o
 blowfish-x86_64-y := blowfish-x86_64-asm_64.o blowfish_glue.o
 twofish-x86_64-y := twofish-x86_64-asm_64.o twofish_glue.o
 twofish-x86_64-3way-y := twofish-x86_64-asm_64-3way.o twofish_glue_3way.o
-twofish-avx-x86_64-y := twofish-avx-x86_64-asm_64.o twofish_avx_glue.o
 salsa20-x86_64-y := salsa20-x86_64-asm_64.o salsa20_glue.o
 serpent-sse2-x86_64-y := serpent-sse2-x86_64-asm_64.o serpent_sse2_glue.o
-serpent-avx-x86_64-y := serpent-avx-x86_64-asm_64.o serpent_avx_glue.o
+
+ifeq ($(avx_supported),yes)
+	camellia-aesni-avx-x86_64-y := camellia-aesni-avx-asm_64.o \
+					camellia_aesni_avx_glue.o
+	cast5-avx-x86_64-y := cast5-avx-x86_64-asm_64.o cast5_avx_glue.o
+	cast6-avx-x86_64-y := cast6-avx-x86_64-asm_64.o cast6_avx_glue.o
+	twofish-avx-x86_64-y := twofish-avx-x86_64-asm_64.o \
+				twofish_avx_glue.o
+	serpent-avx-x86_64-y := serpent-avx-x86_64-asm_64.o \
+				serpent_avx_glue.o
+endif
 
 aesni-intel-y := aesni-intel_asm.o aesni-intel_glue.o fpu.o
 ghash-clmulni-intel-y := ghash-clmulni-intel_asm.o ghash-clmulni-intel_glue.o
 sha1-ssse3-y := sha1_ssse3_asm.o sha1_ssse3_glue.o
 crc32c-intel-y := crc32c-intel_glue.o
-crc32c-intel-$(CONFIG_CRYPTO_CRC32C_X86_64) += crc32c-pcl-intel-asm_64.o
+crc32c-intel-$(CONFIG_64BIT) += crc32c-pcl-intel-asm_64.o
 crc32-pclmul-y := crc32-pclmul_asm.o crc32-pclmul_glue.o
+sha256-ssse3-y := sha256-ssse3-asm.o sha256-avx-asm.o sha256-avx2-asm.o sha256_ssse3_glue.o
+sha512-ssse3-y := sha512-ssse3-asm.o sha512-avx-asm.o sha512-avx2-asm.o sha512_ssse3_glue.o
diff --git a/arch/x86/crypto/crc32-pclmul_asm.S b/arch/x86/crypto/crc32-pclmul_asm.S
index c8335014..94c27df 100644
--- a/arch/x86/crypto/crc32-pclmul_asm.S
+++ b/arch/x86/crypto/crc32-pclmul_asm.S
@@ -101,9 +101,8 @@
  *      uint crc32_pclmul_le_16(unsigned char const *buffer,
  *	                     size_t len, uint crc32)
  */
-.globl crc32_pclmul_le_16
-.align 4, 0x90
-crc32_pclmul_le_16:/* buffer and buffer size are 16 bytes aligned */
+
+ENTRY(crc32_pclmul_le_16) /* buffer and buffer size are 16 bytes aligned */
 	movdqa  (BUF), %xmm1
 	movdqa  0x10(BUF), %xmm2
 	movdqa  0x20(BUF), %xmm3
@@ -244,3 +243,4 @@ fold_64:
 	pextrd  $0x01, %xmm1, %eax
 
 	ret
+ENDPROC(crc32_pclmul_le_16)
diff --git a/arch/x86/crypto/crc32c-pcl-intel-asm_64.S b/arch/x86/crypto/crc32c-pcl-intel-asm_64.S
index cf1a7ec..dbc4339 100644
--- a/arch/x86/crypto/crc32c-pcl-intel-asm_64.S
+++ b/arch/x86/crypto/crc32c-pcl-intel-asm_64.S
@@ -1,9 +1,10 @@
 /*
  * Implement fast CRC32C with PCLMULQDQ instructions. (x86_64)
  *
- * The white paper on CRC32C calculations with PCLMULQDQ instruction can be
+ * The white papers on CRC32C calculations with PCLMULQDQ instruction can be
  * downloaded from:
- * http://download.intel.com/design/intarch/papers/323405.pdf
+ * http://www.intel.com/content/dam/www/public/us/en/documents/white-papers/crc-iscsi-polynomial-crc32-instruction-paper.pdf
+ * http://www.intel.com/content/dam/www/public/us/en/documents/white-papers/fast-crc-computation-paper.pdf
  *
  * Copyright (C) 2012 Intel Corporation.
  *
@@ -42,6 +43,7 @@
  * SOFTWARE.
  */
 
+#include <asm/inst.h>
 #include <linux/linkage.h>
 
 ## ISCSI CRC 32 Implementation with crc32 and pclmulqdq Instruction
@@ -225,10 +227,10 @@ LABEL crc_ %i
 	movdqa  (bufp), %xmm0			# 2 consts: K1:K2
 
 	movq    crc_init, %xmm1			# CRC for block 1
-	pclmulqdq $0x00,%xmm0,%xmm1		# Multiply by K2
+	PCLMULQDQ 0x00,%xmm0,%xmm1		# Multiply by K2
 
 	movq    crc1, %xmm2			# CRC for block 2
-	pclmulqdq $0x10, %xmm0, %xmm2		# Multiply by K1
+	PCLMULQDQ 0x10, %xmm0, %xmm2		# Multiply by K1
 
 	pxor    %xmm2,%xmm1
 	movq    %xmm1, %rax
diff --git a/arch/x86/crypto/sha256-avx-asm.S b/arch/x86/crypto/sha256-avx-asm.S
new file mode 100644
index 0000000..56610c4
--- /dev/null
+++ b/arch/x86/crypto/sha256-avx-asm.S
@@ -0,0 +1,496 @@
+########################################################################
+# Implement fast SHA-256 with AVX1 instructions. (x86_64)
+#
+# Copyright (C) 2013 Intel Corporation.
+#
+# Authors:
+#     James Guilford <james.guilford@intel.com>
+#     Kirk Yap <kirk.s.yap@intel.com>
+#     Tim Chen <tim.c.chen@linux.intel.com>
+#
+# 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.
+########################################################################
+#
+# This code is described in an Intel White-Paper:
+# "Fast SHA-256 Implementations on Intel Architecture Processors"
+#
+# To find it, surf to http://www.intel.com/p/en_US/embedded
+# and search for that title.
+#
+########################################################################
+# This code schedules 1 block at a time, with 4 lanes per block
+########################################################################
+
+#ifdef CONFIG_AS_AVX
+#include <linux/linkage.h>
+
+## assume buffers not aligned
+#define    VMOVDQ vmovdqu
+
+################################ Define Macros
+
+# addm [mem], reg
+# Add reg to mem using reg-mem add and store
+.macro addm p1 p2
+	add     \p1, \p2
+	mov     \p2, \p1
+.endm
+
+
+.macro MY_ROR p1 p2
+	shld    $(32-(\p1)), \p2, \p2
+.endm
+
+################################
+
+# COPY_XMM_AND_BSWAP xmm, [mem], byte_flip_mask
+# Load xmm with mem and byte swap each dword
+.macro COPY_XMM_AND_BSWAP p1 p2 p3
+	VMOVDQ \p2, \p1
+	vpshufb \p3, \p1, \p1
+.endm
+
+################################
+
+X0 = %xmm4
+X1 = %xmm5
+X2 = %xmm6
+X3 = %xmm7
+
+XTMP0 = %xmm0
+XTMP1 = %xmm1
+XTMP2 = %xmm2
+XTMP3 = %xmm3
+XTMP4 = %xmm8
+XFER = %xmm9
+XTMP5 = %xmm11
+
+SHUF_00BA = %xmm10      # shuffle xBxA -> 00BA
+SHUF_DC00 = %xmm12      # shuffle xDxC -> DC00
+BYTE_FLIP_MASK = %xmm13
+
+NUM_BLKS = %rdx   # 3rd arg
+CTX = %rsi        # 2nd arg
+INP = %rdi        # 1st arg
+
+SRND = %rdi       # clobbers INP
+c = %ecx
+d = %r8d
+e = %edx
+TBL = %rbp
+a = %eax
+b = %ebx
+
+f = %r9d
+g = %r10d
+h = %r11d
+
+y0 = %r13d
+y1 = %r14d
+y2 = %r15d
+
+
+_INP_END_SIZE = 8
+_INP_SIZE = 8
+_XFER_SIZE = 8
+_XMM_SAVE_SIZE = 0
+
+_INP_END = 0
+_INP            = _INP_END  + _INP_END_SIZE
+_XFER           = _INP      + _INP_SIZE
+_XMM_SAVE       = _XFER     + _XFER_SIZE
+STACK_SIZE      = _XMM_SAVE + _XMM_SAVE_SIZE
+
+# rotate_Xs
+# Rotate values of symbols X0...X3
+.macro rotate_Xs
+X_ = X0
+X0 = X1
+X1 = X2
+X2 = X3
+X3 = X_
+.endm
+
+# ROTATE_ARGS
+# Rotate values of symbols a...h
+.macro ROTATE_ARGS
+TMP_ = h
+h = g
+g = f
+f = e
+e = d
+d = c
+c = b
+b = a
+a = TMP_
+.endm
+
+.macro FOUR_ROUNDS_AND_SCHED
+	## compute s0 four at a time and s1 two at a time
+	## compute W[-16] + W[-7] 4 at a time
+
+	mov     e, y0			# y0 = e
+	MY_ROR  (25-11), y0             # y0 = e >> (25-11)
+	mov     a, y1                   # y1 = a
+	vpalignr $4, X2, X3, XTMP0      # XTMP0 = W[-7]
+	MY_ROR  (22-13), y1             # y1 = a >> (22-13)
+	xor     e, y0                   # y0 = e ^ (e >> (25-11))
+	mov     f, y2                   # y2 = f
+	MY_ROR  (11-6), y0              # y0 = (e >> (11-6)) ^ (e >> (25-6))
+	xor     a, y1                   # y1 = a ^ (a >> (22-13)
+	xor     g, y2                   # y2 = f^g
+	vpaddd  X0, XTMP0, XTMP0        # XTMP0 = W[-7] + W[-16]
+	xor     e, y0                   # y0 = e ^ (e >> (11-6)) ^ (e >> (25-6))
+	and     e, y2                   # y2 = (f^g)&e
+	MY_ROR  (13-2), y1              # y1 = (a >> (13-2)) ^ (a >> (22-2))
+	## compute s0
+	vpalignr $4, X0, X1, XTMP1      # XTMP1 = W[-15]
+	xor     a, y1                   # y1 = a ^ (a >> (13-2)) ^ (a >> (22-2))
+	MY_ROR  6, y0                   # y0 = S1 = (e>>6) & (e>>11) ^ (e>>25)
+	xor     g, y2                   # y2 = CH = ((f^g)&e)^g
+	MY_ROR  2, y1                   # y1 = S0 = (a>>2) ^ (a>>13) ^ (a>>22)
+	add     y0, y2                  # y2 = S1 + CH
+	add     _XFER(%rsp), y2         # y2 = k + w + S1 + CH
+	mov     a, y0                   # y0 = a
+	add     y2, h                   # h = h + S1 + CH + k + w
+	mov     a, y2                   # y2 = a
+	vpsrld  $7, XTMP1, XTMP2
+	or      c, y0                   # y0 = a|c
+	add     h, d                    # d = d + h + S1 + CH + k + w
+	and     c, y2                   # y2 = a&c
+	vpslld  $(32-7), XTMP1, XTMP3
+	and     b, y0                   # y0 = (a|c)&b
+	add     y1, h                   # h = h + S1 + CH + k + w + S0
+	vpor    XTMP2, XTMP3, XTMP3     # XTMP1 = W[-15] MY_ROR 7
+	or      y2, y0                  # y0 = MAJ = (a|c)&b)|(a&c)
+	add     y0, h                   # h = h + S1 + CH + k + w + S0 + MAJ
+	ROTATE_ARGS
+	mov     e, y0                   # y0 = e
+	mov     a, y1                   # y1 = a
+	MY_ROR  (25-11), y0             # y0 = e >> (25-11)
+	xor     e, y0                   # y0 = e ^ (e >> (25-11))
+	mov     f, y2                   # y2 = f
+	MY_ROR  (22-13), y1             # y1 = a >> (22-13)
+	vpsrld  $18, XTMP1, XTMP2       #
+	xor     a, y1                   # y1 = a ^ (a >> (22-13)
+	MY_ROR  (11-6), y0              # y0 = (e >> (11-6)) ^ (e >> (25-6))
+	xor     g, y2                   # y2 = f^g
+	vpsrld  $3, XTMP1, XTMP4        # XTMP4 = W[-15] >> 3
+	MY_ROR  (13-2), y1              # y1 = (a >> (13-2)) ^ (a >> (22-2))
+	xor     e, y0                   # y0 = e ^ (e >> (11-6)) ^ (e >> (25-6))
+	and     e, y2                   # y2 = (f^g)&e
+	MY_ROR  6, y0                   # y0 = S1 = (e>>6) & (e>>11) ^ (e>>25)
+	vpslld  $(32-18), XTMP1, XTMP1
+	xor     a, y1                   # y1 = a ^ (a >> (13-2)) ^ (a >> (22-2))
+	xor     g, y2                   # y2 = CH = ((f^g)&e)^g
+	vpxor   XTMP1, XTMP3, XTMP3     #
+	add     y0, y2                  # y2 = S1 + CH
+	add     (1*4 + _XFER)(%rsp), y2 # y2 = k + w + S1 + CH
+	MY_ROR  2, y1                   # y1 = S0 = (a>>2) ^ (a>>13) ^ (a>>22)
+	vpxor   XTMP2, XTMP3, XTMP3     # XTMP1 = W[-15] MY_ROR 7 ^ W[-15] MY_ROR
+	mov     a, y0                   # y0 = a
+	add     y2, h                   # h = h + S1 + CH + k + w
+	mov     a, y2                   # y2 = a
+	vpxor   XTMP4, XTMP3, XTMP1     # XTMP1 = s0
+	or      c, y0                   # y0 = a|c
+	add     h, d                    # d = d + h + S1 + CH + k + w
+	and     c, y2                   # y2 = a&c
+	## compute low s1
+	vpshufd $0b11111010, X3, XTMP2  # XTMP2 = W[-2] {BBAA}
+	and     b, y0                   # y0 = (a|c)&b
+	add     y1, h                   # h = h + S1 + CH + k + w + S0
+	vpaddd  XTMP1, XTMP0, XTMP0     # XTMP0 = W[-16] + W[-7] + s0
+	or      y2, y0                  # y0 = MAJ = (a|c)&b)|(a&c)
+	add     y0, h                   # h = h + S1 + CH + k + w + S0 + MAJ
+	ROTATE_ARGS
+	mov     e, y0                   # y0 = e
+	mov     a, y1                   # y1 = a
+	MY_ROR  (25-11), y0             # y0 = e >> (25-11)
+	xor     e, y0                   # y0 = e ^ (e >> (25-11))
+	MY_ROR  (22-13), y1             # y1 = a >> (22-13)
+	mov     f, y2                   # y2 = f
+	xor     a, y1                   # y1 = a ^ (a >> (22-13)
+	MY_ROR  (11-6), y0              # y0 = (e >> (11-6)) ^ (e >> (25-6))
+	vpsrld  $10, XTMP2, XTMP4       # XTMP4 = W[-2] >> 10 {BBAA}
+	xor     g, y2                   # y2 = f^g
+	vpsrlq  $19, XTMP2, XTMP3       # XTMP3 = W[-2] MY_ROR 19 {xBxA}
+	xor     e, y0                   # y0 = e ^ (e >> (11-6)) ^ (e >> (25-6))
+	and     e, y2                   # y2 = (f^g)&e
+	vpsrlq  $17, XTMP2, XTMP2       # XTMP2 = W[-2] MY_ROR 17 {xBxA}
+	MY_ROR  (13-2), y1              # y1 = (a >> (13-2)) ^ (a >> (22-2))
+	xor     a, y1                   # y1 = a ^ (a >> (13-2)) ^ (a >> (22-2))
+	xor     g, y2                   # y2 = CH = ((f^g)&e)^g
+	MY_ROR  6, y0                   # y0 = S1 = (e>>6) & (e>>11) ^ (e>>25)
+	vpxor   XTMP3, XTMP2, XTMP2     #
+	add     y0, y2                  # y2 = S1 + CH
+	MY_ROR  2, y1                   # y1 = S0 = (a>>2) ^ (a>>13) ^ (a>>22)
+	add     (2*4 + _XFER)(%rsp), y2 # y2 = k + w + S1 + CH
+	vpxor   XTMP2, XTMP4, XTMP4     # XTMP4 = s1 {xBxA}
+	mov     a, y0                   # y0 = a
+	add     y2, h                   # h = h + S1 + CH + k + w
+	mov     a, y2                   # y2 = a
+	vpshufb SHUF_00BA, XTMP4, XTMP4 # XTMP4 = s1 {00BA}
+	or      c, y0                   # y0 = a|c
+	add     h, d                    # d = d + h + S1 + CH + k + w
+	and     c, y2                   # y2 = a&c
+	vpaddd  XTMP4, XTMP0, XTMP0     # XTMP0 = {..., ..., W[1], W[0]}
+	and     b, y0                   # y0 = (a|c)&b
+	add     y1, h                   # h = h + S1 + CH + k + w + S0
+	## compute high s1
+	vpshufd $0b01010000, XTMP0, XTMP2 # XTMP2 = W[-2] {DDCC}
+	or      y2, y0                  # y0 = MAJ = (a|c)&b)|(a&c)
+	add     y0, h                   # h = h + S1 + CH + k + w + S0 + MAJ
+	ROTATE_ARGS
+	mov     e, y0                   # y0 = e
+	MY_ROR  (25-11), y0             # y0 = e >> (25-11)
+	mov     a, y1                   # y1 = a
+	MY_ROR  (22-13), y1             # y1 = a >> (22-13)
+	xor     e, y0                   # y0 = e ^ (e >> (25-11))
+	mov     f, y2                   # y2 = f
+	MY_ROR  (11-6), y0              # y0 = (e >> (11-6)) ^ (e >> (25-6))
+	vpsrld  $10, XTMP2, XTMP5       # XTMP5 = W[-2] >> 10 {DDCC}
+	xor     a, y1                   # y1 = a ^ (a >> (22-13)
+	xor     g, y2                   # y2 = f^g
+	vpsrlq  $19, XTMP2, XTMP3       # XTMP3 = W[-2] MY_ROR 19 {xDxC}
+	xor     e, y0                   # y0 = e ^ (e >> (11-6)) ^ (e >> (25-6))
+	and     e, y2                   # y2 = (f^g)&e
+	MY_ROR  (13-2), y1              # y1 = (a >> (13-2)) ^ (a >> (22-2))
+	vpsrlq  $17, XTMP2, XTMP2       # XTMP2 = W[-2] MY_ROR 17 {xDxC}
+	xor     a, y1                   # y1 = a ^ (a >> (13-2)) ^ (a >> (22-2))
+	MY_ROR  6, y0                   # y0 = S1 = (e>>6) & (e>>11) ^ (e>>25)
+	xor     g, y2                   # y2 = CH = ((f^g)&e)^g
+	vpxor   XTMP3, XTMP2, XTMP2
+	MY_ROR  2, y1                   # y1 = S0 = (a>>2) ^ (a>>13) ^ (a>>22)
+	add     y0, y2                  # y2 = S1 + CH
+	add     (3*4 + _XFER)(%rsp), y2 # y2 = k + w + S1 + CH
+	vpxor   XTMP2, XTMP5, XTMP5     # XTMP5 = s1 {xDxC}
+	mov     a, y0                   # y0 = a
+	add     y2, h                   # h = h + S1 + CH + k + w
+	mov     a, y2                   # y2 = a
+	vpshufb SHUF_DC00, XTMP5, XTMP5 # XTMP5 = s1 {DC00}
+	or      c, y0                   # y0 = a|c
+	add     h, d                    # d = d + h + S1 + CH + k + w
+	and     c, y2                   # y2 = a&c
+	vpaddd  XTMP0, XTMP5, X0        # X0 = {W[3], W[2], W[1], W[0]}
+	and     b, y0                   # y0 = (a|c)&b
+	add     y1, h                   # h = h + S1 + CH + k + w + S0
+	or      y2, y0                  # y0 = MAJ = (a|c)&b)|(a&c)
+	add     y0, h                   # h = h + S1 + CH + k + w + S0 + MAJ
+	ROTATE_ARGS
+	rotate_Xs
+.endm
+
+## input is [rsp + _XFER + %1 * 4]
+.macro DO_ROUND round
+	mov	e, y0			# y0 = e
+        MY_ROR  (25-11), y0             # y0 = e >> (25-11)
+        mov     a, y1                   # y1 = a
+        xor     e, y0                   # y0 = e ^ (e >> (25-11))
+        MY_ROR  (22-13), y1             # y1 = a >> (22-13)
+        mov     f, y2                   # y2 = f
+        xor     a, y1                   # y1 = a ^ (a >> (22-13)
+        MY_ROR  (11-6), y0              # y0 = (e >> (11-6)) ^ (e >> (25-6))
+        xor     g, y2                   # y2 = f^g
+        xor     e, y0                   # y0 = e ^ (e >> (11-6)) ^ (e >> (25-6))
+        MY_ROR  (13-2), y1              # y1 = (a >> (13-2)) ^ (a >> (22-2))
+        and     e, y2                   # y2 = (f^g)&e
+        xor     a, y1                   # y1 = a ^ (a >> (13-2)) ^ (a >> (22-2))
+        MY_ROR  6, y0                   # y0 = S1 = (e>>6) & (e>>11) ^ (e>>25)
+        xor     g, y2                   # y2 = CH = ((f^g)&e)^g
+        add     y0, y2                  # y2 = S1 + CH
+        MY_ROR  2, y1                   # y1 = S0 = (a>>2) ^ (a>>13) ^ (a>>22)
+        offset = \round * 4 + _XFER     #
+        add     offset(%rsp), y2	# y2 = k + w + S1 + CH
+        mov     a, y0			# y0 = a
+        add     y2, h                   # h = h + S1 + CH + k + w
+        mov     a, y2                   # y2 = a
+        or      c, y0                   # y0 = a|c
+        add     h, d                    # d = d + h + S1 + CH + k + w
+        and     c, y2                   # y2 = a&c
+        and     b, y0                   # y0 = (a|c)&b
+        add     y1, h                   # h = h + S1 + CH + k + w + S0
+        or      y2, y0                  # y0 = MAJ = (a|c)&b)|(a&c)
+        add     y0, h                   # h = h + S1 + CH + k + w + S0 + MAJ
+        ROTATE_ARGS
+.endm
+
+########################################################################
+## void sha256_transform_avx(void *input_data, UINT32 digest[8], UINT64 num_blks)
+## arg 1 : pointer to input data
+## arg 2 : pointer to digest
+## arg 3 : Num blocks
+########################################################################
+.text
+ENTRY(sha256_transform_avx)
+.align 32
+	pushq   %rbx
+	pushq   %rbp
+	pushq   %r13
+	pushq   %r14
+	pushq   %r15
+	pushq   %r12
+
+	mov	%rsp, %r12
+	subq    $STACK_SIZE, %rsp	# allocate stack space
+	and	$~15, %rsp		# align stack pointer
+
+	shl     $6, NUM_BLKS		# convert to bytes
+	jz      done_hash
+	add     INP, NUM_BLKS		# pointer to end of data
+	mov     NUM_BLKS, _INP_END(%rsp)
+
+	## load initial digest
+	mov     4*0(CTX), a
+	mov     4*1(CTX), b
+	mov     4*2(CTX), c
+	mov     4*3(CTX), d
+	mov     4*4(CTX), e
+	mov     4*5(CTX), f
+	mov     4*6(CTX), g
+	mov     4*7(CTX), h
+
+	vmovdqa  PSHUFFLE_BYTE_FLIP_MASK(%rip), BYTE_FLIP_MASK
+	vmovdqa  _SHUF_00BA(%rip), SHUF_00BA
+	vmovdqa  _SHUF_DC00(%rip), SHUF_DC00
+loop0:
+	lea     K256(%rip), TBL
+
+	## byte swap first 16 dwords
+	COPY_XMM_AND_BSWAP      X0, 0*16(INP), BYTE_FLIP_MASK
+	COPY_XMM_AND_BSWAP      X1, 1*16(INP), BYTE_FLIP_MASK
+	COPY_XMM_AND_BSWAP      X2, 2*16(INP), BYTE_FLIP_MASK
+	COPY_XMM_AND_BSWAP      X3, 3*16(INP), BYTE_FLIP_MASK
+
+	mov     INP, _INP(%rsp)
+
+	## schedule 48 input dwords, by doing 3 rounds of 16 each
+	mov     $3, SRND
+.align 16
+loop1:
+	vpaddd  (TBL), X0, XFER
+	vmovdqa XFER, _XFER(%rsp)
+	FOUR_ROUNDS_AND_SCHED
+
+	vpaddd  1*16(TBL), X0, XFER
+	vmovdqa XFER, _XFER(%rsp)
+	FOUR_ROUNDS_AND_SCHED
+
+	vpaddd  2*16(TBL), X0, XFER
+	vmovdqa XFER, _XFER(%rsp)
+	FOUR_ROUNDS_AND_SCHED
+
+	vpaddd  3*16(TBL), X0, XFER
+	vmovdqa XFER, _XFER(%rsp)
+	add	$4*16, TBL
+	FOUR_ROUNDS_AND_SCHED
+
+	sub     $1, SRND
+	jne     loop1
+
+	mov     $2, SRND
+loop2:
+	vpaddd  (TBL), X0, XFER
+	vmovdqa XFER, _XFER(%rsp)
+	DO_ROUND        0
+	DO_ROUND        1
+	DO_ROUND        2
+	DO_ROUND        3
+
+	vpaddd  1*16(TBL), X1, XFER
+	vmovdqa XFER, _XFER(%rsp)
+	add     $2*16, TBL
+	DO_ROUND        0
+	DO_ROUND        1
+	DO_ROUND        2
+	DO_ROUND        3
+
+	vmovdqa X2, X0
+	vmovdqa X3, X1
+
+	sub     $1, SRND
+	jne     loop2
+
+	addm    (4*0)(CTX),a
+	addm    (4*1)(CTX),b
+	addm    (4*2)(CTX),c
+	addm    (4*3)(CTX),d
+	addm    (4*4)(CTX),e
+	addm    (4*5)(CTX),f
+	addm    (4*6)(CTX),g
+	addm    (4*7)(CTX),h
+
+	mov     _INP(%rsp), INP
+	add     $64, INP
+	cmp     _INP_END(%rsp), INP
+	jne     loop0
+
+done_hash:
+
+	mov	%r12, %rsp
+
+	popq	%r12
+	popq    %r15
+	popq    %r14
+	popq    %r13
+	popq    %rbp
+	popq    %rbx
+	ret
+ENDPROC(sha256_transform_avx)
+
+.data
+.align 64
+K256:
+	.long 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5
+	.long 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5
+	.long 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3
+	.long 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174
+	.long 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc
+	.long 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da
+	.long 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7
+	.long 0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967
+	.long 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13
+	.long 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85
+	.long 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3
+	.long 0xd192e819,0xd6990624,0xf40e3585,0x106aa070
+	.long 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5
+	.long 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3
+	.long 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208
+	.long 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
+
+PSHUFFLE_BYTE_FLIP_MASK:
+	.octa 0x0c0d0e0f08090a0b0405060700010203
+
+# shuffle xBxA -> 00BA
+_SHUF_00BA:
+	.octa 0xFFFFFFFFFFFFFFFF0b0a090803020100
+
+# shuffle xDxC -> DC00
+_SHUF_DC00:
+	.octa 0x0b0a090803020100FFFFFFFFFFFFFFFF
+#endif
diff --git a/arch/x86/crypto/sha256-avx2-asm.S b/arch/x86/crypto/sha256-avx2-asm.S
new file mode 100644
index 0000000..9e86944
--- /dev/null
+++ b/arch/x86/crypto/sha256-avx2-asm.S
@@ -0,0 +1,772 @@
+########################################################################
+# Implement fast SHA-256 with AVX2 instructions. (x86_64)
+#
+# Copyright (C) 2013 Intel Corporation.
+#
+# Authors:
+#     James Guilford <james.guilford@intel.com>
+#     Kirk Yap <kirk.s.yap@intel.com>
+#     Tim Chen <tim.c.chen@linux.intel.com>
+#
+# 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.
+#
+########################################################################
+#
+# This code is described in an Intel White-Paper:
+# "Fast SHA-256 Implementations on Intel Architecture Processors"
+#
+# To find it, surf to http://www.intel.com/p/en_US/embedded
+# and search for that title.
+#
+########################################################################
+# This code schedules 2 blocks at a time, with 4 lanes per block
+########################################################################
+
+#ifdef CONFIG_AS_AVX2
+#include <linux/linkage.h>
+
+## assume buffers not aligned
+#define	VMOVDQ vmovdqu
+
+################################ Define Macros
+
+# addm [mem], reg
+# Add reg to mem using reg-mem add and store
+.macro addm p1 p2
+	add	\p1, \p2
+	mov	\p2, \p1
+.endm
+
+################################
+
+X0 = %ymm4
+X1 = %ymm5
+X2 = %ymm6
+X3 = %ymm7
+
+# XMM versions of above
+XWORD0 = %xmm4
+XWORD1 = %xmm5
+XWORD2 = %xmm6
+XWORD3 = %xmm7
+
+XTMP0 = %ymm0
+XTMP1 = %ymm1
+XTMP2 = %ymm2
+XTMP3 = %ymm3
+XTMP4 = %ymm8
+XFER  = %ymm9
+XTMP5 = %ymm11
+
+SHUF_00BA =	%ymm10 # shuffle xBxA -> 00BA
+SHUF_DC00 =	%ymm12 # shuffle xDxC -> DC00
+BYTE_FLIP_MASK = %ymm13
+
+X_BYTE_FLIP_MASK = %xmm13 # XMM version of BYTE_FLIP_MASK
+
+NUM_BLKS = %rdx	# 3rd arg
+CTX	= %rsi  # 2nd arg
+INP	= %rdi	# 1st arg
+c	= %ecx
+d	= %r8d
+e       = %edx	# clobbers NUM_BLKS
+y3	= %edi	# clobbers INP
+
+
+TBL	= %rbp
+SRND	= CTX	# SRND is same register as CTX
+
+a = %eax
+b = %ebx
+f = %r9d
+g = %r10d
+h = %r11d
+old_h = %r11d
+
+T1 = %r12d
+y0 = %r13d
+y1 = %r14d
+y2 = %r15d
+
+
+_XFER_SIZE	= 2*64*4	# 2 blocks, 64 rounds, 4 bytes/round
+_XMM_SAVE_SIZE	= 0
+_INP_END_SIZE	= 8
+_INP_SIZE	= 8
+_CTX_SIZE	= 8
+_RSP_SIZE	= 8
+
+_XFER		= 0
+_XMM_SAVE	= _XFER     + _XFER_SIZE
+_INP_END	= _XMM_SAVE + _XMM_SAVE_SIZE
+_INP		= _INP_END  + _INP_END_SIZE
+_CTX		= _INP      + _INP_SIZE
+_RSP		= _CTX      + _CTX_SIZE
+STACK_SIZE	= _RSP      + _RSP_SIZE
+
+# rotate_Xs
+# Rotate values of symbols X0...X3
+.macro rotate_Xs
+	X_ = X0
+	X0 = X1
+	X1 = X2
+	X2 = X3
+	X3 = X_
+.endm
+
+# ROTATE_ARGS
+# Rotate values of symbols a...h
+.macro ROTATE_ARGS
+	old_h = h
+	TMP_ = h
+	h = g
+	g = f
+	f = e
+	e = d
+	d = c
+	c = b
+	b = a
+	a = TMP_
+.endm
+
+.macro FOUR_ROUNDS_AND_SCHED disp
+################################### RND N + 0 ############################
+
+	mov	a, y3		# y3 = a                                # MAJA
+	rorx	$25, e, y0	# y0 = e >> 25				# S1A
+	rorx	$11, e, y1	# y1 = e >> 11				# S1B
+
+	addl	\disp(%rsp, SRND), h		# h = k + w + h         # --
+	or	c, y3		# y3 = a|c                              # MAJA
+	vpalignr $4, X2, X3, XTMP0 # XTMP0 = W[-7]
+	mov	f, y2		# y2 = f                                # CH
+	rorx	$13, a, T1	# T1 = a >> 13				# S0B
+
+	xor	y1, y0		# y0 = (e>>25) ^ (e>>11)		# S1
+	xor	g, y2		# y2 = f^g                              # CH
+	vpaddd	X0, XTMP0, XTMP0 # XTMP0 = W[-7] + W[-16]# y1 = (e >> 6)# S1
+	rorx	$6, e, y1	# y1 = (e >> 6)				# S1
+
+	and	e, y2		# y2 = (f^g)&e                          # CH
+	xor	y1, y0		# y0 = (e>>25) ^ (e>>11) ^ (e>>6)	# S1
+	rorx	$22, a, y1	# y1 = a >> 22				# S0A
+	add	h, d		# d = k + w + h + d                     # --
+
+	and	b, y3		# y3 = (a|c)&b                          # MAJA
+	vpalignr $4, X0, X1, XTMP1	# XTMP1 = W[-15]
+	xor	T1, y1		# y1 = (a>>22) ^ (a>>13)		# S0
+	rorx	$2, a, T1	# T1 = (a >> 2)				# S0
+
+	xor	g, y2		# y2 = CH = ((f^g)&e)^g                 # CH
+	vpsrld	$7, XTMP1, XTMP2
+	xor	T1, y1		# y1 = (a>>22) ^ (a>>13) ^ (a>>2)	# S0
+	mov	a, T1		# T1 = a                                # MAJB
+	and	c, T1		# T1 = a&c                              # MAJB
+
+	add	y0, y2		# y2 = S1 + CH                          # --
+	vpslld	$(32-7), XTMP1, XTMP3
+	or	T1, y3		# y3 = MAJ = (a|c)&b)|(a&c)             # MAJ
+	add	y1, h		# h = k + w + h + S0                    # --
+
+	add	y2, d		# d = k + w + h + d + S1 + CH = d + t1  # --
+	vpor	XTMP2, XTMP3, XTMP3	# XTMP3 = W[-15] ror 7
+
+	vpsrld	$18, XTMP1, XTMP2
+	add	y2, h		# h = k + w + h + S0 + S1 + CH = t1 + S0# --
+	add	y3, h		# h = t1 + S0 + MAJ                     # --
+
+
+	ROTATE_ARGS
+
+################################### RND N + 1 ############################
+
+	mov	a, y3		# y3 = a                                # MAJA
+	rorx	$25, e, y0	# y0 = e >> 25				# S1A
+	rorx	$11, e, y1	# y1 = e >> 11				# S1B
+	offset = \disp + 1*4
+	addl	offset(%rsp, SRND), h	# h = k + w + h         # --
+	or	c, y3		# y3 = a|c                              # MAJA
+
+
+	vpsrld	$3, XTMP1, XTMP4 # XTMP4 = W[-15] >> 3
+	mov	f, y2		# y2 = f                                # CH
+	rorx	$13, a, T1	# T1 = a >> 13				# S0B
+	xor	y1, y0		# y0 = (e>>25) ^ (e>>11)		# S1
+	xor	g, y2		# y2 = f^g                              # CH
+
+
+	rorx	$6, e, y1	# y1 = (e >> 6)				# S1
+	xor	y1, y0		# y0 = (e>>25) ^ (e>>11) ^ (e>>6)	# S1
+	rorx	$22, a, y1	# y1 = a >> 22				# S0A
+	and	e, y2		# y2 = (f^g)&e                          # CH
+	add	h, d		# d = k + w + h + d                     # --
+
+	vpslld	$(32-18), XTMP1, XTMP1
+	and	b, y3		# y3 = (a|c)&b                          # MAJA
+	xor	T1, y1		# y1 = (a>>22) ^ (a>>13)		# S0
+
+	vpxor	XTMP1, XTMP3, XTMP3
+	rorx	$2, a, T1	# T1 = (a >> 2)				# S0
+	xor	g, y2		# y2 = CH = ((f^g)&e)^g                 # CH
+
+	vpxor	XTMP2, XTMP3, XTMP3	# XTMP3 = W[-15] ror 7 ^ W[-15] ror 18
+	xor	T1, y1		# y1 = (a>>22) ^ (a>>13) ^ (a>>2)	# S0
+	mov	a, T1		# T1 = a                                # MAJB
+	and	c, T1		# T1 = a&c                              # MAJB
+	add	y0, y2		# y2 = S1 + CH                          # --
+
+	vpxor	XTMP4, XTMP3, XTMP1	# XTMP1 = s0
+	vpshufd	$0b11111010, X3, XTMP2	# XTMP2 = W[-2] {BBAA}
+	or	T1, y3		# y3 = MAJ = (a|c)&b)|(a&c)             # MAJ
+	add	y1, h		# h = k + w + h + S0                    # --
+
+	vpaddd	XTMP1, XTMP0, XTMP0	# XTMP0 = W[-16] + W[-7] + s0
+	add	y2, d		# d = k + w + h + d + S1 + CH = d + t1  # --
+	add	y2, h		# h = k + w + h + S0 + S1 + CH = t1 + S0# --
+	add	y3, h		# h = t1 + S0 + MAJ                     # --
+
+	vpsrld	$10, XTMP2, XTMP4 # XTMP4 = W[-2] >> 10 {BBAA}
+
+
+	ROTATE_ARGS
+
+################################### RND N + 2 ############################
+
+	mov	a, y3		# y3 = a                                # MAJA
+	rorx	$25, e, y0	# y0 = e >> 25				# S1A
+	offset = \disp + 2*4
+	addl	offset(%rsp, SRND), h	# h = k + w + h         # --
+
+	vpsrlq	$19, XTMP2, XTMP3 # XTMP3 = W[-2] ror 19 {xBxA}
+	rorx	$11, e, y1	# y1 = e >> 11				# S1B
+	or	c, y3		# y3 = a|c                              # MAJA
+	mov	f, y2		# y2 = f                                # CH
+	xor	g, y2		# y2 = f^g                              # CH
+
+	rorx	$13, a, T1	# T1 = a >> 13				# S0B
+	xor	y1, y0		# y0 = (e>>25) ^ (e>>11)		# S1
+	vpsrlq	$17, XTMP2, XTMP2	# XTMP2 = W[-2] ror 17 {xBxA}
+	and	e, y2		# y2 = (f^g)&e                          # CH
+
+	rorx	$6, e, y1	# y1 = (e >> 6)				# S1
+	vpxor	XTMP3, XTMP2, XTMP2
+	add	h, d		# d = k + w + h + d                     # --
+	and	b, y3		# y3 = (a|c)&b                          # MAJA
+
+	xor	y1, y0		# y0 = (e>>25) ^ (e>>11) ^ (e>>6)	# S1
+	rorx	$22, a, y1	# y1 = a >> 22				# S0A
+	vpxor	XTMP2, XTMP4, XTMP4	# XTMP4 = s1 {xBxA}
+	xor	g, y2		# y2 = CH = ((f^g)&e)^g                 # CH
+
+	vpshufb	SHUF_00BA, XTMP4, XTMP4	# XTMP4 = s1 {00BA}
+	xor	T1, y1		# y1 = (a>>22) ^ (a>>13)		# S0
+	rorx	$2, a ,T1	# T1 = (a >> 2)				# S0
+	vpaddd	XTMP4, XTMP0, XTMP0	# XTMP0 = {..., ..., W[1], W[0]}
+
+	xor	T1, y1		# y1 = (a>>22) ^ (a>>13) ^ (a>>2)	# S0
+	mov	a, T1		# T1 = a                                # MAJB
+	and	c, T1		# T1 = a&c                              # MAJB
+	add	y0, y2		# y2 = S1 + CH                          # --
+	vpshufd	$0b01010000, XTMP0, XTMP2	# XTMP2 = W[-2] {DDCC}
+
+	or	T1, y3		# y3 = MAJ = (a|c)&b)|(a&c)             # MAJ
+	add	y1,h		# h = k + w + h + S0                    # --
+	add	y2,d		# d = k + w + h + d + S1 + CH = d + t1  # --
+	add	y2,h		# h = k + w + h + S0 + S1 + CH = t1 + S0# --
+
+	add	y3,h		# h = t1 + S0 + MAJ                     # --
+
+
+	ROTATE_ARGS
+
+################################### RND N + 3 ############################
+
+	mov	a, y3		# y3 = a                                # MAJA
+	rorx	$25, e, y0	# y0 = e >> 25				# S1A
+	rorx	$11, e, y1	# y1 = e >> 11				# S1B
+	offset = \disp + 3*4
+	addl	offset(%rsp, SRND), h	# h = k + w + h         # --
+	or	c, y3		# y3 = a|c                              # MAJA
+
+
+	vpsrld	$10, XTMP2, XTMP5	# XTMP5 = W[-2] >> 10 {DDCC}
+	mov	f, y2		# y2 = f                                # CH
+	rorx	$13, a, T1	# T1 = a >> 13				# S0B
+	xor	y1, y0		# y0 = (e>>25) ^ (e>>11)		# S1
+	xor	g, y2		# y2 = f^g                              # CH
+
+
+	vpsrlq	$19, XTMP2, XTMP3	# XTMP3 = W[-2] ror 19 {xDxC}
+	rorx	$6, e, y1	# y1 = (e >> 6)				# S1
+	and	e, y2		# y2 = (f^g)&e                          # CH
+	add	h, d		# d = k + w + h + d                     # --
+	and	b, y3		# y3 = (a|c)&b                          # MAJA
+
+	vpsrlq	$17, XTMP2, XTMP2	# XTMP2 = W[-2] ror 17 {xDxC}
+	xor	y1, y0		# y0 = (e>>25) ^ (e>>11) ^ (e>>6)	# S1
+	xor	g, y2		# y2 = CH = ((f^g)&e)^g                 # CH
+
+	vpxor	XTMP3, XTMP2, XTMP2
+	rorx	$22, a, y1	# y1 = a >> 22				# S0A
+	add	y0, y2		# y2 = S1 + CH                          # --
+
+	vpxor	XTMP2, XTMP5, XTMP5	# XTMP5 = s1 {xDxC}
+	xor	T1, y1		# y1 = (a>>22) ^ (a>>13)		# S0
+	add	y2, d		# d = k + w + h + d + S1 + CH = d + t1  # --
+
+	rorx	$2, a, T1	# T1 = (a >> 2)				# S0
+	vpshufb	SHUF_DC00, XTMP5, XTMP5	# XTMP5 = s1 {DC00}
+
+	vpaddd	XTMP0, XTMP5, X0	# X0 = {W[3], W[2], W[1], W[0]}
+	xor	T1, y1		# y1 = (a>>22) ^ (a>>13) ^ (a>>2)	# S0
+	mov	a, T1		# T1 = a                                # MAJB
+	and	c, T1		# T1 = a&c                              # MAJB
+	or	T1, y3		# y3 = MAJ = (a|c)&b)|(a&c)             # MAJ
+
+	add	y1, h		# h = k + w + h + S0                    # --
+	add	y2, h		# h = k + w + h + S0 + S1 + CH = t1 + S0# --
+	add	y3, h		# h = t1 + S0 + MAJ                     # --
+
+	ROTATE_ARGS
+	rotate_Xs
+.endm
+
+.macro DO_4ROUNDS disp
+################################### RND N + 0 ###########################
+
+	mov	f, y2		# y2 = f                                # CH
+	rorx	$25, e, y0	# y0 = e >> 25				# S1A
+	rorx	$11, e, y1	# y1 = e >> 11				# S1B
+	xor	g, y2		# y2 = f^g                              # CH
+
+	xor	y1, y0		# y0 = (e>>25) ^ (e>>11)		# S1
+	rorx	$6, e, y1	# y1 = (e >> 6)				# S1
+	and	e, y2		# y2 = (f^g)&e                          # CH
+
+	xor	y1, y0		# y0 = (e>>25) ^ (e>>11) ^ (e>>6)	# S1
+	rorx	$13, a, T1	# T1 = a >> 13				# S0B
+	xor	g, y2		# y2 = CH = ((f^g)&e)^g                 # CH
+	rorx	$22, a, y1	# y1 = a >> 22				# S0A
+	mov	a, y3		# y3 = a                                # MAJA
+
+	xor	T1, y1		# y1 = (a>>22) ^ (a>>13)		# S0
+	rorx	$2, a, T1	# T1 = (a >> 2)				# S0
+	addl	\disp(%rsp, SRND), h		# h = k + w + h # --
+	or	c, y3		# y3 = a|c                              # MAJA
+
+	xor	T1, y1		# y1 = (a>>22) ^ (a>>13) ^ (a>>2)	# S0
+	mov	a, T1		# T1 = a                                # MAJB
+	and	b, y3		# y3 = (a|c)&b                          # MAJA
+	and	c, T1		# T1 = a&c                              # MAJB
+	add	y0, y2		# y2 = S1 + CH                          # --
+
+
+	add	h, d		# d = k + w + h + d                     # --
+	or	T1, y3		# y3 = MAJ = (a|c)&b)|(a&c)             # MAJ
+	add	y1, h		# h = k + w + h + S0                    # --
+	add	y2, d		# d = k + w + h + d + S1 + CH = d + t1  # --
+
+	ROTATE_ARGS
+
+################################### RND N + 1 ###########################
+
+	add	y2, old_h	# h = k + w + h + S0 + S1 + CH = t1 + S0# --
+	mov	f, y2		# y2 = f                                # CH
+	rorx	$25, e, y0	# y0 = e >> 25				# S1A
+	rorx	$11, e, y1	# y1 = e >> 11				# S1B
+	xor	g, y2		# y2 = f^g                              # CH
+
+	xor	y1, y0		# y0 = (e>>25) ^ (e>>11)		# S1
+	rorx	$6, e, y1	# y1 = (e >> 6)				# S1
+	and	e, y2		# y2 = (f^g)&e                          # CH
+	add	y3, old_h	# h = t1 + S0 + MAJ                     # --
+
+	xor	y1, y0		# y0 = (e>>25) ^ (e>>11) ^ (e>>6)	# S1
+	rorx	$13, a, T1	# T1 = a >> 13				# S0B
+	xor	g, y2		# y2 = CH = ((f^g)&e)^g                 # CH
+	rorx	$22, a, y1	# y1 = a >> 22				# S0A
+	mov	a, y3		# y3 = a                                # MAJA
+
+	xor	T1, y1		# y1 = (a>>22) ^ (a>>13)		# S0
+	rorx	$2, a, T1	# T1 = (a >> 2)				# S0
+	offset = 4*1 + \disp
+	addl	offset(%rsp, SRND), h		# h = k + w + h # --
+	or	c, y3		# y3 = a|c                              # MAJA
+
+	xor	T1, y1		# y1 = (a>>22) ^ (a>>13) ^ (a>>2)	# S0
+	mov	a, T1		# T1 = a                                # MAJB
+	and	b, y3		# y3 = (a|c)&b                          # MAJA
+	and	c, T1		# T1 = a&c                              # MAJB
+	add	y0, y2		# y2 = S1 + CH                          # --
+
+
+	add	h, d		# d = k + w + h + d                     # --
+	or	T1, y3		# y3 = MAJ = (a|c)&b)|(a&c)             # MAJ
+	add	y1, h		# h = k + w + h + S0                    # --
+
+	add	y2, d		# d = k + w + h + d + S1 + CH = d + t1  # --
+
+	ROTATE_ARGS
+
+################################### RND N + 2 ##############################
+
+	add	y2, old_h	# h = k + w + h + S0 + S1 + CH = t1 + S0# --
+	mov	f, y2		# y2 = f                                # CH
+	rorx	$25, e, y0	# y0 = e >> 25				# S1A
+	rorx	$11, e, y1	# y1 = e >> 11				# S1B
+	xor	g, y2		# y2 = f^g                              # CH
+
+	xor	y1, y0		# y0 = (e>>25) ^ (e>>11)		# S1
+	rorx	$6, e, y1	# y1 = (e >> 6)				# S1
+	and	e, y2		# y2 = (f^g)&e                          # CH
+	add	y3, old_h	# h = t1 + S0 + MAJ                     # --
+
+	xor	y1, y0		# y0 = (e>>25) ^ (e>>11) ^ (e>>6)	# S1
+	rorx	$13, a, T1	# T1 = a >> 13				# S0B
+	xor	g, y2		# y2 = CH = ((f^g)&e)^g                 # CH
+	rorx	$22, a, y1	# y1 = a >> 22				# S0A
+	mov	a, y3		# y3 = a                                # MAJA
+
+	xor	T1, y1		# y1 = (a>>22) ^ (a>>13)		# S0
+	rorx	$2, a, T1	# T1 = (a >> 2)				# S0
+	offset = 4*2 + \disp
+	addl	offset(%rsp, SRND), h		# h = k + w + h # --
+	or	c, y3		# y3 = a|c                              # MAJA
+
+	xor	T1, y1		# y1 = (a>>22) ^ (a>>13) ^ (a>>2)	# S0
+	mov	a, T1		# T1 = a                                # MAJB
+	and	b, y3		# y3 = (a|c)&b                          # MAJA
+	and	c, T1		# T1 = a&c                              # MAJB
+	add	y0, y2		# y2 = S1 + CH                          # --
+
+
+	add	h, d		# d = k + w + h + d                     # --
+	or	T1, y3		# y3 = MAJ = (a|c)&b)|(a&c)             # MAJ
+	add	y1, h		# h = k + w + h + S0                    # --
+
+	add	y2, d		# d = k + w + h + d + S1 + CH = d + t1  # --
+
+	ROTATE_ARGS
+
+################################### RND N + 3 ###########################
+
+	add	y2, old_h	# h = k + w + h + S0 + S1 + CH = t1 + S0# --
+	mov	f, y2		# y2 = f                                # CH
+	rorx	$25, e, y0	# y0 = e >> 25				# S1A
+	rorx	$11, e, y1	# y1 = e >> 11				# S1B
+	xor	g, y2		# y2 = f^g                              # CH
+
+	xor	y1, y0		# y0 = (e>>25) ^ (e>>11)		# S1
+	rorx	$6, e, y1	# y1 = (e >> 6)				# S1
+	and	e, y2		# y2 = (f^g)&e                          # CH
+	add	y3, old_h	# h = t1 + S0 + MAJ                     # --
+
+	xor	y1, y0		# y0 = (e>>25) ^ (e>>11) ^ (e>>6)	# S1
+	rorx	$13, a, T1	# T1 = a >> 13				# S0B
+	xor	g, y2		# y2 = CH = ((f^g)&e)^g                 # CH
+	rorx	$22, a, y1	# y1 = a >> 22				# S0A
+	mov	a, y3		# y3 = a                                # MAJA
+
+	xor	T1, y1		# y1 = (a>>22) ^ (a>>13)		# S0
+	rorx	$2, a, T1	# T1 = (a >> 2)				# S0
+	offset = 4*3 + \disp
+	addl	offset(%rsp, SRND), h		# h = k + w + h # --
+	or	c, y3		# y3 = a|c                              # MAJA
+
+	xor	T1, y1		# y1 = (a>>22) ^ (a>>13) ^ (a>>2)	# S0
+	mov	a, T1		# T1 = a                                # MAJB
+	and	b, y3		# y3 = (a|c)&b                          # MAJA
+	and	c, T1		# T1 = a&c                              # MAJB
+	add	y0, y2		# y2 = S1 + CH                          # --
+
+
+	add	h, d		# d = k + w + h + d                     # --
+	or	T1, y3		# y3 = MAJ = (a|c)&b)|(a&c)             # MAJ
+	add	y1, h		# h = k + w + h + S0                    # --
+
+	add	y2, d		# d = k + w + h + d + S1 + CH = d + t1  # --
+
+
+	add	y2, h		# h = k + w + h + S0 + S1 + CH = t1 + S0# --
+
+	add	y3, h		# h = t1 + S0 + MAJ                     # --
+
+	ROTATE_ARGS
+
+.endm
+
+########################################################################
+## void sha256_transform_rorx(void *input_data, UINT32 digest[8], UINT64 num_blks)
+## arg 1 : pointer to input data
+## arg 2 : pointer to digest
+## arg 3 : Num blocks
+########################################################################
+.text
+ENTRY(sha256_transform_rorx)
+.align 32
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+
+	mov	%rsp, %rax
+	subq	$STACK_SIZE, %rsp
+	and	$-32, %rsp	# align rsp to 32 byte boundary
+	mov	%rax, _RSP(%rsp)
+
+
+	shl	$6, NUM_BLKS	# convert to bytes
+	jz	done_hash
+	lea	-64(INP, NUM_BLKS), NUM_BLKS # pointer to last block
+	mov	NUM_BLKS, _INP_END(%rsp)
+
+	cmp	NUM_BLKS, INP
+	je	only_one_block
+
+	## load initial digest
+	mov	(CTX), a
+	mov	4*1(CTX), b
+	mov	4*2(CTX), c
+	mov	4*3(CTX), d
+	mov	4*4(CTX), e
+	mov	4*5(CTX), f
+	mov	4*6(CTX), g
+	mov	4*7(CTX), h
+
+	vmovdqa  PSHUFFLE_BYTE_FLIP_MASK(%rip), BYTE_FLIP_MASK
+	vmovdqa  _SHUF_00BA(%rip), SHUF_00BA
+	vmovdqa  _SHUF_DC00(%rip), SHUF_DC00
+
+	mov	CTX, _CTX(%rsp)
+
+loop0:
+	lea     K256(%rip), TBL
+
+	## Load first 16 dwords from two blocks
+	VMOVDQ	0*32(INP),XTMP0
+	VMOVDQ	1*32(INP),XTMP1
+	VMOVDQ	2*32(INP),XTMP2
+	VMOVDQ	3*32(INP),XTMP3
+
+	## byte swap data
+	vpshufb	BYTE_FLIP_MASK, XTMP0, XTMP0
+	vpshufb	BYTE_FLIP_MASK, XTMP1, XTMP1
+	vpshufb	BYTE_FLIP_MASK, XTMP2, XTMP2
+	vpshufb	BYTE_FLIP_MASK, XTMP3, XTMP3
+
+	## transpose data into high/low halves
+	vperm2i128	$0x20, XTMP2, XTMP0, X0
+	vperm2i128	$0x31, XTMP2, XTMP0, X1
+	vperm2i128	$0x20, XTMP3, XTMP1, X2
+	vperm2i128	$0x31, XTMP3, XTMP1, X3
+
+last_block_enter:
+	add	$64, INP
+	mov	INP, _INP(%rsp)
+
+	## schedule 48 input dwords, by doing 3 rounds of 12 each
+	xor	SRND, SRND
+
+.align 16
+loop1:
+	vpaddd	0*32(TBL, SRND), X0, XFER
+	vmovdqa XFER, 0*32+_XFER(%rsp, SRND)
+	FOUR_ROUNDS_AND_SCHED	_XFER + 0*32
+
+	vpaddd	1*32(TBL, SRND), X0, XFER
+	vmovdqa XFER, 1*32+_XFER(%rsp, SRND)
+	FOUR_ROUNDS_AND_SCHED	_XFER + 1*32
+
+	vpaddd	2*32(TBL, SRND), X0, XFER
+	vmovdqa XFER, 2*32+_XFER(%rsp, SRND)
+	FOUR_ROUNDS_AND_SCHED	_XFER + 2*32
+
+	vpaddd	3*32(TBL, SRND), X0, XFER
+	vmovdqa XFER, 3*32+_XFER(%rsp, SRND)
+	FOUR_ROUNDS_AND_SCHED	_XFER + 3*32
+
+	add	$4*32, SRND
+	cmp	$3*4*32, SRND
+	jb	loop1
+
+loop2:
+	## Do last 16 rounds with no scheduling
+	vpaddd	0*32(TBL, SRND), X0, XFER
+	vmovdqa XFER, 0*32+_XFER(%rsp, SRND)
+	DO_4ROUNDS	_XFER + 0*32
+	vpaddd	1*32(TBL, SRND), X1, XFER
+	vmovdqa XFER, 1*32+_XFER(%rsp, SRND)
+	DO_4ROUNDS	_XFER + 1*32
+	add	$2*32, SRND
+
+	vmovdqa	X2, X0
+	vmovdqa	X3, X1
+
+	cmp	$4*4*32, SRND
+	jb	loop2
+
+	mov	_CTX(%rsp), CTX
+	mov	_INP(%rsp), INP
+
+	addm    (4*0)(CTX),a
+	addm    (4*1)(CTX),b
+	addm    (4*2)(CTX),c
+	addm    (4*3)(CTX),d
+	addm    (4*4)(CTX),e
+	addm    (4*5)(CTX),f
+	addm    (4*6)(CTX),g
+	addm    (4*7)(CTX),h
+
+	cmp	_INP_END(%rsp), INP
+	ja	done_hash
+
+	#### Do second block using previously scheduled results
+	xor	SRND, SRND
+.align 16
+loop3:
+	DO_4ROUNDS	 _XFER + 0*32 + 16
+	DO_4ROUNDS	 _XFER + 1*32 + 16
+	add	$2*32, SRND
+	cmp	$4*4*32, SRND
+	jb	loop3
+
+	mov	_CTX(%rsp), CTX
+	mov	_INP(%rsp), INP
+	add	$64, INP
+
+	addm    (4*0)(CTX),a
+	addm    (4*1)(CTX),b
+	addm    (4*2)(CTX),c
+	addm    (4*3)(CTX),d
+	addm    (4*4)(CTX),e
+	addm    (4*5)(CTX),f
+	addm    (4*6)(CTX),g
+	addm    (4*7)(CTX),h
+
+	cmp	_INP_END(%rsp), INP
+	jb	loop0
+	ja	done_hash
+
+do_last_block:
+	#### do last block
+	lea	K256(%rip), TBL
+
+	VMOVDQ	0*16(INP),XWORD0
+	VMOVDQ	1*16(INP),XWORD1
+	VMOVDQ	2*16(INP),XWORD2
+	VMOVDQ	3*16(INP),XWORD3
+
+	vpshufb	X_BYTE_FLIP_MASK, XWORD0, XWORD0
+	vpshufb	X_BYTE_FLIP_MASK, XWORD1, XWORD1
+	vpshufb	X_BYTE_FLIP_MASK, XWORD2, XWORD2
+	vpshufb	X_BYTE_FLIP_MASK, XWORD3, XWORD3
+
+	jmp	last_block_enter
+
+only_one_block:
+
+	## load initial digest
+	mov	(4*0)(CTX),a
+	mov	(4*1)(CTX),b
+	mov	(4*2)(CTX),c
+	mov	(4*3)(CTX),d
+	mov	(4*4)(CTX),e
+	mov	(4*5)(CTX),f
+	mov	(4*6)(CTX),g
+	mov	(4*7)(CTX),h
+
+	vmovdqa	PSHUFFLE_BYTE_FLIP_MASK(%rip), BYTE_FLIP_MASK
+	vmovdqa	_SHUF_00BA(%rip), SHUF_00BA
+	vmovdqa	_SHUF_DC00(%rip), SHUF_DC00
+
+	mov	CTX, _CTX(%rsp)
+	jmp	do_last_block
+
+done_hash:
+
+	mov	_RSP(%rsp), %rsp
+
+	popq	%r15
+	popq	%r14
+	popq	%r13
+	popq	%r12
+	popq	%rbp
+	popq	%rbx
+	ret
+ENDPROC(sha256_transform_rorx)
+
+.data
+.align 64
+K256:
+	.long	0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5
+	.long	0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5
+	.long	0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5
+	.long	0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5
+	.long	0xd807aa98,0x12835b01,0x243185be,0x550c7dc3
+	.long	0xd807aa98,0x12835b01,0x243185be,0x550c7dc3
+	.long	0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174
+	.long	0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174
+	.long	0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc
+	.long	0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc
+	.long	0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da
+	.long	0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da
+	.long	0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7
+	.long	0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7
+	.long	0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967
+	.long	0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967
+	.long	0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13
+	.long	0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13
+	.long	0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85
+	.long	0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85
+	.long	0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3
+	.long	0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3
+	.long	0xd192e819,0xd6990624,0xf40e3585,0x106aa070
+	.long	0xd192e819,0xd6990624,0xf40e3585,0x106aa070
+	.long	0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5
+	.long	0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5
+	.long	0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3
+	.long	0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3
+	.long	0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208
+	.long	0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208
+	.long	0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
+	.long	0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
+
+PSHUFFLE_BYTE_FLIP_MASK:
+	.octa 0x0c0d0e0f08090a0b0405060700010203,0x0c0d0e0f08090a0b0405060700010203
+
+# shuffle xBxA -> 00BA
+_SHUF_00BA:
+	.octa 0xFFFFFFFFFFFFFFFF0b0a090803020100,0xFFFFFFFFFFFFFFFF0b0a090803020100
+
+# shuffle xDxC -> DC00
+_SHUF_DC00:
+	.octa 0x0b0a090803020100FFFFFFFFFFFFFFFF,0x0b0a090803020100FFFFFFFFFFFFFFFF
+#endif
diff --git a/arch/x86/crypto/sha256-ssse3-asm.S b/arch/x86/crypto/sha256-ssse3-asm.S
new file mode 100644
index 0000000..98d3c39
--- /dev/null
+++ b/arch/x86/crypto/sha256-ssse3-asm.S
@@ -0,0 +1,506 @@
+########################################################################
+# Implement fast SHA-256 with SSSE3 instructions. (x86_64)
+#
+# Copyright (C) 2013 Intel Corporation.
+#
+# Authors:
+#     James Guilford <james.guilford@intel.com>
+#     Kirk Yap <kirk.s.yap@intel.com>
+#     Tim Chen <tim.c.chen@linux.intel.com>
+#
+# 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.
+#
+########################################################################
+#
+# This code is described in an Intel White-Paper:
+# "Fast SHA-256 Implementations on Intel Architecture Processors"
+#
+# To find it, surf to http://www.intel.com/p/en_US/embedded
+# and search for that title.
+#
+########################################################################
+
+#include <linux/linkage.h>
+
+## assume buffers not aligned
+#define    MOVDQ movdqu
+
+################################ Define Macros
+
+# addm [mem], reg
+# Add reg to mem using reg-mem add and store
+.macro addm p1 p2
+        add     \p1, \p2
+        mov     \p2, \p1
+.endm
+
+################################
+
+# COPY_XMM_AND_BSWAP xmm, [mem], byte_flip_mask
+# Load xmm with mem and byte swap each dword
+.macro COPY_XMM_AND_BSWAP p1 p2 p3
+        MOVDQ \p2, \p1
+        pshufb \p3, \p1
+.endm
+
+################################
+
+X0 = %xmm4
+X1 = %xmm5
+X2 = %xmm6
+X3 = %xmm7
+
+XTMP0 = %xmm0
+XTMP1 = %xmm1
+XTMP2 = %xmm2
+XTMP3 = %xmm3
+XTMP4 = %xmm8
+XFER = %xmm9
+
+SHUF_00BA = %xmm10      # shuffle xBxA -> 00BA
+SHUF_DC00 = %xmm11      # shuffle xDxC -> DC00
+BYTE_FLIP_MASK = %xmm12
+
+NUM_BLKS = %rdx   # 3rd arg
+CTX = %rsi        # 2nd arg
+INP = %rdi        # 1st arg
+
+SRND = %rdi       # clobbers INP
+c = %ecx
+d = %r8d
+e = %edx
+TBL = %rbp
+a = %eax
+b = %ebx
+
+f = %r9d
+g = %r10d
+h = %r11d
+
+y0 = %r13d
+y1 = %r14d
+y2 = %r15d
+
+
+
+_INP_END_SIZE = 8
+_INP_SIZE = 8
+_XFER_SIZE = 8
+_XMM_SAVE_SIZE = 0
+
+_INP_END = 0
+_INP            = _INP_END  + _INP_END_SIZE
+_XFER           = _INP      + _INP_SIZE
+_XMM_SAVE       = _XFER     + _XFER_SIZE
+STACK_SIZE      = _XMM_SAVE + _XMM_SAVE_SIZE
+
+# rotate_Xs
+# Rotate values of symbols X0...X3
+.macro rotate_Xs
+X_ = X0
+X0 = X1
+X1 = X2
+X2 = X3
+X3 = X_
+.endm
+
+# ROTATE_ARGS
+# Rotate values of symbols a...h
+.macro ROTATE_ARGS
+TMP_ = h
+h = g
+g = f
+f = e
+e = d
+d = c
+c = b
+b = a
+a = TMP_
+.endm
+
+.macro FOUR_ROUNDS_AND_SCHED
+	## compute s0 four at a time and s1 two at a time
+	## compute W[-16] + W[-7] 4 at a time
+	movdqa  X3, XTMP0
+	mov     e, y0			# y0 = e
+	ror     $(25-11), y0            # y0 = e >> (25-11)
+	mov     a, y1                   # y1 = a
+	palignr $4, X2, XTMP0           # XTMP0 = W[-7]
+	ror     $(22-13), y1            # y1 = a >> (22-13)
+	xor     e, y0                   # y0 = e ^ (e >> (25-11))
+	mov     f, y2                   # y2 = f
+	ror     $(11-6), y0             # y0 = (e >> (11-6)) ^ (e >> (25-6))
+	movdqa  X1, XTMP1
+	xor     a, y1                   # y1 = a ^ (a >> (22-13)
+	xor     g, y2                   # y2 = f^g
+	paddd   X0, XTMP0               # XTMP0 = W[-7] + W[-16]
+	xor     e, y0                   # y0 = e ^ (e >> (11-6)) ^ (e >> (25-6))
+	and     e, y2                   # y2 = (f^g)&e
+	ror     $(13-2), y1             # y1 = (a >> (13-2)) ^ (a >> (22-2))
+	## compute s0
+	palignr $4, X0, XTMP1           # XTMP1 = W[-15]
+	xor     a, y1                   # y1 = a ^ (a >> (13-2)) ^ (a >> (22-2))
+	ror     $6, y0                  # y0 = S1 = (e>>6) & (e>>11) ^ (e>>25)
+	xor     g, y2                   # y2 = CH = ((f^g)&e)^g
+	movdqa  XTMP1, XTMP2            # XTMP2 = W[-15]
+	ror     $2, y1                  # y1 = S0 = (a>>2) ^ (a>>13) ^ (a>>22)
+	add     y0, y2                  # y2 = S1 + CH
+	add     _XFER(%rsp) , y2        # y2 = k + w + S1 + CH
+	movdqa  XTMP1, XTMP3            # XTMP3 = W[-15]
+	mov     a, y0                   # y0 = a
+	add     y2, h                   # h = h + S1 + CH + k + w
+	mov     a, y2                   # y2 = a
+	pslld   $(32-7), XTMP1          #
+	or      c, y0                   # y0 = a|c
+	add     h, d                    # d = d + h + S1 + CH + k + w
+	and     c, y2                   # y2 = a&c
+	psrld   $7, XTMP2               #
+	and     b, y0                   # y0 = (a|c)&b
+	add     y1, h                   # h = h + S1 + CH + k + w + S0
+	por     XTMP2, XTMP1            # XTMP1 = W[-15] ror 7
+	or      y2, y0                  # y0 = MAJ = (a|c)&b)|(a&c)
+	add     y0, h                   # h = h + S1 + CH + k + w + S0 + MAJ
+					#
+	ROTATE_ARGS                     #
+	movdqa  XTMP3, XTMP2            # XTMP2 = W[-15]
+	mov     e, y0                   # y0 = e
+	mov     a, y1                   # y1 = a
+	movdqa  XTMP3, XTMP4            # XTMP4 = W[-15]
+	ror     $(25-11), y0            # y0 = e >> (25-11)
+	xor     e, y0                   # y0 = e ^ (e >> (25-11))
+	mov     f, y2                   # y2 = f
+	ror     $(22-13), y1            # y1 = a >> (22-13)
+	pslld   $(32-18), XTMP3         #
+	xor     a, y1                   # y1 = a ^ (a >> (22-13)
+	ror     $(11-6), y0             # y0 = (e >> (11-6)) ^ (e >> (25-6))
+	xor     g, y2                   # y2 = f^g
+	psrld   $18, XTMP2              #
+	ror     $(13-2), y1             # y1 = (a >> (13-2)) ^ (a >> (22-2))
+	xor     e, y0                   # y0 = e ^ (e >> (11-6)) ^ (e >> (25-6))
+	and     e, y2                   # y2 = (f^g)&e
+	ror     $6, y0                  # y0 = S1 = (e>>6) & (e>>11) ^ (e>>25)
+	pxor    XTMP3, XTMP1
+	xor     a, y1                   # y1 = a ^ (a >> (13-2)) ^ (a >> (22-2))
+	xor     g, y2                   # y2 = CH = ((f^g)&e)^g
+	psrld   $3, XTMP4               # XTMP4 = W[-15] >> 3
+	add     y0, y2                  # y2 = S1 + CH
+	add     (1*4 + _XFER)(%rsp), y2 # y2 = k + w + S1 + CH
+	ror     $2, y1                  # y1 = S0 = (a>>2) ^ (a>>13) ^ (a>>22)
+	pxor    XTMP2, XTMP1            # XTMP1 = W[-15] ror 7 ^ W[-15] ror 18
+	mov     a, y0                   # y0 = a
+	add     y2, h                   # h = h + S1 + CH + k + w
+	mov     a, y2                   # y2 = a
+	pxor    XTMP4, XTMP1            # XTMP1 = s0
+	or      c, y0                   # y0 = a|c
+	add     h, d                    # d = d + h + S1 + CH + k + w
+	and     c, y2                   # y2 = a&c
+	## compute low s1
+	pshufd  $0b11111010, X3, XTMP2   # XTMP2 = W[-2] {BBAA}
+	and     b, y0			# y0 = (a|c)&b
+	add     y1, h                   # h = h + S1 + CH + k + w + S0
+	paddd   XTMP1, XTMP0            # XTMP0 = W[-16] + W[-7] + s0
+	or      y2, y0                  # y0 = MAJ = (a|c)&b)|(a&c)
+	add     y0, h                   # h = h + S1 + CH + k + w + S0 + MAJ
+
+	ROTATE_ARGS
+	movdqa  XTMP2, XTMP3            # XTMP3 = W[-2] {BBAA}
+	mov     e, y0                   # y0 = e
+	mov     a, y1                   # y1 = a
+	ror     $(25-11), y0            # y0 = e >> (25-11)
+	movdqa  XTMP2, XTMP4            # XTMP4 = W[-2] {BBAA}
+	xor     e, y0                   # y0 = e ^ (e >> (25-11))
+	ror     $(22-13), y1            # y1 = a >> (22-13)
+	mov     f, y2                   # y2 = f
+	xor     a, y1                   # y1 = a ^ (a >> (22-13)
+	ror     $(11-6), y0             # y0 = (e >> (11-6)) ^ (e >> (25-6))
+	psrlq   $17, XTMP2              # XTMP2 = W[-2] ror 17 {xBxA}
+	xor     g, y2                   # y2 = f^g
+	psrlq   $19, XTMP3              # XTMP3 = W[-2] ror 19 {xBxA}
+	xor     e, y0                   # y0 = e ^ (e >> (11-6)) ^ (e >> (25-6))
+	and     e, y2                   # y2 = (f^g)&e
+	psrld   $10, XTMP4              # XTMP4 = W[-2] >> 10 {BBAA}
+	ror     $(13-2), y1             # y1 = (a >> (13-2)) ^ (a >> (22-2))
+	xor     a, y1                   # y1 = a ^ (a >> (13-2)) ^ (a >> (22-2))
+	xor     g, y2                   # y2 = CH = ((f^g)&e)^g
+	ror     $6, y0                  # y0 = S1 = (e>>6) & (e>>11) ^ (e>>25)
+	pxor    XTMP3, XTMP2
+	add     y0, y2                  # y2 = S1 + CH
+	ror     $2, y1                  # y1 = S0 = (a>>2) ^ (a>>13) ^ (a>>22)
+	add     (2*4 + _XFER)(%rsp), y2 # y2 = k + w + S1 + CH
+	pxor    XTMP2, XTMP4            # XTMP4 = s1 {xBxA}
+	mov     a, y0                   # y0 = a
+	add     y2, h                   # h = h + S1 + CH + k + w
+	mov     a, y2                   # y2 = a
+	pshufb  SHUF_00BA, XTMP4        # XTMP4 = s1 {00BA}
+	or      c, y0                   # y0 = a|c
+	add     h, d                    # d = d + h + S1 + CH + k + w
+	and     c, y2                   # y2 = a&c
+	paddd   XTMP4, XTMP0            # XTMP0 = {..., ..., W[1], W[0]}
+	and     b, y0                   # y0 = (a|c)&b
+	add     y1, h                   # h = h + S1 + CH + k + w + S0
+	## compute high s1
+	pshufd  $0b01010000, XTMP0, XTMP2 # XTMP2 = W[-2] {BBAA}
+	or      y2, y0                  # y0 = MAJ = (a|c)&b)|(a&c)
+	add     y0, h                   # h = h + S1 + CH + k + w + S0 + MAJ
+					#
+	ROTATE_ARGS                     #
+	movdqa  XTMP2, XTMP3            # XTMP3 = W[-2] {DDCC}
+	mov     e, y0                   # y0 = e
+	ror     $(25-11), y0            # y0 = e >> (25-11)
+	mov     a, y1                   # y1 = a
+	movdqa  XTMP2, X0               # X0    = W[-2] {DDCC}
+	ror     $(22-13), y1            # y1 = a >> (22-13)
+	xor     e, y0                   # y0 = e ^ (e >> (25-11))
+	mov     f, y2                   # y2 = f
+	ror     $(11-6), y0             # y0 = (e >> (11-6)) ^ (e >> (25-6))
+	psrlq   $17, XTMP2              # XTMP2 = W[-2] ror 17 {xDxC}
+	xor     a, y1                   # y1 = a ^ (a >> (22-13)
+	xor     g, y2                   # y2 = f^g
+	psrlq   $19, XTMP3              # XTMP3 = W[-2] ror 19 {xDxC}
+	xor     e, y0                   # y0 = e ^ (e >> (11-6)) ^ (e >> (25
+	and     e, y2                   # y2 = (f^g)&e
+	ror     $(13-2), y1             # y1 = (a >> (13-2)) ^ (a >> (22-2))
+	psrld   $10, X0                 # X0 = W[-2] >> 10 {DDCC}
+	xor     a, y1                   # y1 = a ^ (a >> (13-2)) ^ (a >> (22
+	ror     $6, y0                  # y0 = S1 = (e>>6) & (e>>11) ^ (e>>2
+	xor     g, y2                   # y2 = CH = ((f^g)&e)^g
+	pxor    XTMP3, XTMP2            #
+	ror     $2, y1                  # y1 = S0 = (a>>2) ^ (a>>13) ^ (a>>2
+	add     y0, y2                  # y2 = S1 + CH
+	add     (3*4 + _XFER)(%rsp), y2 # y2 = k + w + S1 + CH
+	pxor    XTMP2, X0               # X0 = s1 {xDxC}
+	mov     a, y0                   # y0 = a
+	add     y2, h                   # h = h + S1 + CH + k + w
+	mov     a, y2                   # y2 = a
+	pshufb  SHUF_DC00, X0           # X0 = s1 {DC00}
+	or      c, y0                   # y0 = a|c
+	add     h, d                    # d = d + h + S1 + CH + k + w
+	and     c, y2                   # y2 = a&c
+	paddd   XTMP0, X0               # X0 = {W[3], W[2], W[1], W[0]}
+	and     b, y0                   # y0 = (a|c)&b
+	add     y1, h                   # h = h + S1 + CH + k + w + S0
+	or      y2, y0                  # y0 = MAJ = (a|c)&b)|(a&c)
+	add     y0, h                   # h = h + S1 + CH + k + w + S0 + MAJ
+
+	ROTATE_ARGS
+	rotate_Xs
+.endm
+
+## input is [rsp + _XFER + %1 * 4]
+.macro DO_ROUND round
+	mov     e, y0                 # y0 = e
+	ror     $(25-11), y0          # y0 = e >> (25-11)
+	mov     a, y1                 # y1 = a
+	xor     e, y0                 # y0 = e ^ (e >> (25-11))
+	ror     $(22-13), y1          # y1 = a >> (22-13)
+	mov     f, y2                 # y2 = f
+	xor     a, y1                 # y1 = a ^ (a >> (22-13)
+	ror     $(11-6), y0           # y0 = (e >> (11-6)) ^ (e >> (25-6))
+	xor     g, y2                 # y2 = f^g
+	xor     e, y0                 # y0 = e ^ (e >> (11-6)) ^ (e >> (25-6))
+	ror     $(13-2), y1           # y1 = (a >> (13-2)) ^ (a >> (22-2))
+	and     e, y2                 # y2 = (f^g)&e
+	xor     a, y1                 # y1 = a ^ (a >> (13-2)) ^ (a >> (22-2))
+	ror     $6, y0                # y0 = S1 = (e>>6) & (e>>11) ^ (e>>25)
+	xor     g, y2                 # y2 = CH = ((f^g)&e)^g
+	add     y0, y2                # y2 = S1 + CH
+	ror     $2, y1                # y1 = S0 = (a>>2) ^ (a>>13) ^ (a>>22)
+	offset = \round * 4 + _XFER
+	add     offset(%rsp), y2      # y2 = k + w + S1 + CH
+	mov     a, y0                 # y0 = a
+	add     y2, h                 # h = h + S1 + CH + k + w
+	mov     a, y2                 # y2 = a
+	or      c, y0                 # y0 = a|c
+	add     h, d                  # d = d + h + S1 + CH + k + w
+	and     c, y2                 # y2 = a&c
+	and     b, y0                 # y0 = (a|c)&b
+	add     y1, h                 # h = h + S1 + CH + k + w + S0
+	or      y2, y0		      # y0 = MAJ = (a|c)&b)|(a&c)
+	add     y0, h		      # h = h + S1 + CH + k + w + S0 + MAJ
+	ROTATE_ARGS
+.endm
+
+########################################################################
+## void sha256_transform_ssse3(void *input_data, UINT32 digest[8], UINT64 num_blks)
+## arg 1 : pointer to input data
+## arg 2 : pointer to digest
+## arg 3 : Num blocks
+########################################################################
+.text
+ENTRY(sha256_transform_ssse3)
+.align 32
+	pushq   %rbx
+	pushq   %rbp
+	pushq   %r13
+	pushq   %r14
+	pushq   %r15
+	pushq   %r12
+
+	mov	%rsp, %r12
+	subq    $STACK_SIZE, %rsp
+	and	$~15, %rsp
+
+	shl     $6, NUM_BLKS		 # convert to bytes
+	jz      done_hash
+	add     INP, NUM_BLKS
+	mov     NUM_BLKS, _INP_END(%rsp) # pointer to end of data
+
+	## load initial digest
+	mov     4*0(CTX), a
+	mov     4*1(CTX), b
+	mov     4*2(CTX), c
+	mov     4*3(CTX), d
+	mov     4*4(CTX), e
+	mov     4*5(CTX), f
+	mov     4*6(CTX), g
+	mov     4*7(CTX), h
+
+	movdqa  PSHUFFLE_BYTE_FLIP_MASK(%rip), BYTE_FLIP_MASK
+	movdqa  _SHUF_00BA(%rip), SHUF_00BA
+	movdqa  _SHUF_DC00(%rip), SHUF_DC00
+
+loop0:
+	lea     K256(%rip), TBL
+
+	## byte swap first 16 dwords
+	COPY_XMM_AND_BSWAP      X0, 0*16(INP), BYTE_FLIP_MASK
+	COPY_XMM_AND_BSWAP      X1, 1*16(INP), BYTE_FLIP_MASK
+	COPY_XMM_AND_BSWAP      X2, 2*16(INP), BYTE_FLIP_MASK
+	COPY_XMM_AND_BSWAP      X3, 3*16(INP), BYTE_FLIP_MASK
+
+	mov     INP, _INP(%rsp)
+
+	## schedule 48 input dwords, by doing 3 rounds of 16 each
+	mov     $3, SRND
+.align 16
+loop1:
+	movdqa  (TBL), XFER
+	paddd   X0, XFER
+	movdqa  XFER, _XFER(%rsp)
+	FOUR_ROUNDS_AND_SCHED
+
+	movdqa  1*16(TBL), XFER
+	paddd   X0, XFER
+	movdqa  XFER, _XFER(%rsp)
+	FOUR_ROUNDS_AND_SCHED
+
+	movdqa  2*16(TBL), XFER
+	paddd   X0, XFER
+	movdqa  XFER, _XFER(%rsp)
+	FOUR_ROUNDS_AND_SCHED
+
+	movdqa  3*16(TBL), XFER
+	paddd   X0, XFER
+	movdqa  XFER, _XFER(%rsp)
+	add     $4*16, TBL
+	FOUR_ROUNDS_AND_SCHED
+
+	sub     $1, SRND
+	jne     loop1
+
+	mov     $2, SRND
+loop2:
+	paddd   (TBL), X0
+	movdqa  X0, _XFER(%rsp)
+	DO_ROUND        0
+	DO_ROUND        1
+	DO_ROUND        2
+	DO_ROUND        3
+	paddd   1*16(TBL), X1
+	movdqa  X1, _XFER(%rsp)
+	add     $2*16, TBL
+	DO_ROUND        0
+	DO_ROUND        1
+	DO_ROUND        2
+	DO_ROUND        3
+
+	movdqa  X2, X0
+	movdqa  X3, X1
+
+	sub     $1, SRND
+	jne     loop2
+
+	addm    (4*0)(CTX),a
+	addm    (4*1)(CTX),b
+	addm    (4*2)(CTX),c
+	addm    (4*3)(CTX),d
+	addm    (4*4)(CTX),e
+	addm    (4*5)(CTX),f
+	addm    (4*6)(CTX),g
+	addm    (4*7)(CTX),h
+
+	mov     _INP(%rsp), INP
+	add     $64, INP
+	cmp     _INP_END(%rsp), INP
+	jne     loop0
+
+done_hash:
+
+	mov	%r12, %rsp
+
+	popq    %r12
+	popq    %r15
+	popq    %r14
+	popq    %r13
+	popq    %rbp
+	popq    %rbx
+
+	ret
+ENDPROC(sha256_transform_ssse3)
+
+.data
+.align 64
+K256:
+        .long 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5
+        .long 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5
+        .long 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3
+        .long 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174
+        .long 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc
+        .long 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da
+        .long 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7
+        .long 0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967
+        .long 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13
+        .long 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85
+        .long 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3
+        .long 0xd192e819,0xd6990624,0xf40e3585,0x106aa070
+        .long 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5
+        .long 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3
+        .long 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208
+        .long 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
+
+PSHUFFLE_BYTE_FLIP_MASK:
+	.octa 0x0c0d0e0f08090a0b0405060700010203
+
+# shuffle xBxA -> 00BA
+_SHUF_00BA:
+	.octa 0xFFFFFFFFFFFFFFFF0b0a090803020100
+
+# shuffle xDxC -> DC00
+_SHUF_DC00:
+	.octa 0x0b0a090803020100FFFFFFFFFFFFFFFF
diff --git a/arch/x86/crypto/sha256_ssse3_glue.c b/arch/x86/crypto/sha256_ssse3_glue.c
new file mode 100644
index 0000000..fa65453
--- /dev/null
+++ b/arch/x86/crypto/sha256_ssse3_glue.c
@@ -0,0 +1,275 @@
+/*
+ * Cryptographic API.
+ *
+ * Glue code for the SHA256 Secure Hash Algorithm assembler
+ * implementation using supplemental SSE3 / AVX / AVX2 instructions.
+ *
+ * This file is based on sha256_generic.c
+ *
+ * Copyright (C) 2013 Intel Corporation.
+ *
+ * Author:
+ *     Tim Chen <tim.c.chen@linux.intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * 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 pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
+
+#include <crypto/internal/hash.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/cryptohash.h>
+#include <linux/types.h>
+#include <crypto/sha.h>
+#include <asm/byteorder.h>
+#include <asm/i387.h>
+#include <asm/xcr.h>
+#include <asm/xsave.h>
+#include <linux/string.h>
+
+asmlinkage void sha256_transform_ssse3(const char *data, u32 *digest,
+				     u64 rounds);
+#ifdef CONFIG_AS_AVX
+asmlinkage void sha256_transform_avx(const char *data, u32 *digest,
+				     u64 rounds);
+#endif
+#ifdef CONFIG_AS_AVX2
+asmlinkage void sha256_transform_rorx(const char *data, u32 *digest,
+				     u64 rounds);
+#endif
+
+asmlinkage void (*sha256_transform_asm)(const char *, u32 *, u64);
+
+
+static int sha256_ssse3_init(struct shash_desc *desc)
+{
+	struct sha256_state *sctx = shash_desc_ctx(desc);
+
+	sctx->state[0] = SHA256_H0;
+	sctx->state[1] = SHA256_H1;
+	sctx->state[2] = SHA256_H2;
+	sctx->state[3] = SHA256_H3;
+	sctx->state[4] = SHA256_H4;
+	sctx->state[5] = SHA256_H5;
+	sctx->state[6] = SHA256_H6;
+	sctx->state[7] = SHA256_H7;
+	sctx->count = 0;
+
+	return 0;
+}
+
+static int __sha256_ssse3_update(struct shash_desc *desc, const u8 *data,
+			       unsigned int len, unsigned int partial)
+{
+	struct sha256_state *sctx = shash_desc_ctx(desc);
+	unsigned int done = 0;
+
+	sctx->count += len;
+
+	if (partial) {
+		done = SHA256_BLOCK_SIZE - partial;
+		memcpy(sctx->buf + partial, data, done);
+		sha256_transform_asm(sctx->buf, sctx->state, 1);
+	}
+
+	if (len - done >= SHA256_BLOCK_SIZE) {
+		const unsigned int rounds = (len - done) / SHA256_BLOCK_SIZE;
+
+		sha256_transform_asm(data + done, sctx->state, (u64) rounds);
+
+		done += rounds * SHA256_BLOCK_SIZE;
+	}
+
+	memcpy(sctx->buf, data + done, len - done);
+
+	return 0;
+}
+
+static int sha256_ssse3_update(struct shash_desc *desc, const u8 *data,
+			     unsigned int len)
+{
+	struct sha256_state *sctx = shash_desc_ctx(desc);
+	unsigned int partial = sctx->count % SHA256_BLOCK_SIZE;
+	int res;
+
+	/* Handle the fast case right here */
+	if (partial + len < SHA256_BLOCK_SIZE) {
+		sctx->count += len;
+		memcpy(sctx->buf + partial, data, len);
+
+		return 0;
+	}
+
+	if (!irq_fpu_usable()) {
+		res = crypto_sha256_update(desc, data, len);
+	} else {
+		kernel_fpu_begin();
+		res = __sha256_ssse3_update(desc, data, len, partial);
+		kernel_fpu_end();
+	}
+
+	return res;
+}
+
+
+/* Add padding and return the message digest. */
+static int sha256_ssse3_final(struct shash_desc *desc, u8 *out)
+{
+	struct sha256_state *sctx = shash_desc_ctx(desc);
+	unsigned int i, index, padlen;
+	__be32 *dst = (__be32 *)out;
+	__be64 bits;
+	static const u8 padding[SHA256_BLOCK_SIZE] = { 0x80, };
+
+	bits = cpu_to_be64(sctx->count << 3);
+
+	/* Pad out to 56 mod 64 and append length */
+	index = sctx->count % SHA256_BLOCK_SIZE;
+	padlen = (index < 56) ? (56 - index) : ((SHA256_BLOCK_SIZE+56)-index);
+
+	if (!irq_fpu_usable()) {
+		crypto_sha256_update(desc, padding, padlen);
+		crypto_sha256_update(desc, (const u8 *)&bits, sizeof(bits));
+	} else {
+		kernel_fpu_begin();
+		/* We need to fill a whole block for __sha256_ssse3_update() */
+		if (padlen <= 56) {
+			sctx->count += padlen;
+			memcpy(sctx->buf + index, padding, padlen);
+		} else {
+			__sha256_ssse3_update(desc, padding, padlen, index);
+		}
+		__sha256_ssse3_update(desc, (const u8 *)&bits,
+					sizeof(bits), 56);
+		kernel_fpu_end();
+	}
+
+	/* Store state in digest */
+	for (i = 0; i < 8; i++)
+		dst[i] = cpu_to_be32(sctx->state[i]);
+
+	/* Wipe context */
+	memset(sctx, 0, sizeof(*sctx));
+
+	return 0;
+}
+
+static int sha256_ssse3_export(struct shash_desc *desc, void *out)
+{
+	struct sha256_state *sctx = shash_desc_ctx(desc);
+
+	memcpy(out, sctx, sizeof(*sctx));
+
+	return 0;
+}
+
+static int sha256_ssse3_import(struct shash_desc *desc, const void *in)
+{
+	struct sha256_state *sctx = shash_desc_ctx(desc);
+
+	memcpy(sctx, in, sizeof(*sctx));
+
+	return 0;
+}
+
+static struct shash_alg alg = {
+	.digestsize	=	SHA256_DIGEST_SIZE,
+	.init		=	sha256_ssse3_init,
+	.update		=	sha256_ssse3_update,
+	.final		=	sha256_ssse3_final,
+	.export		=	sha256_ssse3_export,
+	.import		=	sha256_ssse3_import,
+	.descsize	=	sizeof(struct sha256_state),
+	.statesize	=	sizeof(struct sha256_state),
+	.base		=	{
+		.cra_name	=	"sha256",
+		.cra_driver_name =	"sha256-ssse3",
+		.cra_priority	=	150,
+		.cra_flags	=	CRYPTO_ALG_TYPE_SHASH,
+		.cra_blocksize	=	SHA256_BLOCK_SIZE,
+		.cra_module	=	THIS_MODULE,
+	}
+};
+
+#ifdef CONFIG_AS_AVX
+static bool __init avx_usable(void)
+{
+	u64 xcr0;
+
+	if (!cpu_has_avx || !cpu_has_osxsave)
+		return false;
+
+	xcr0 = xgetbv(XCR_XFEATURE_ENABLED_MASK);
+	if ((xcr0 & (XSTATE_SSE | XSTATE_YMM)) != (XSTATE_SSE | XSTATE_YMM)) {
+		pr_info("AVX detected but unusable.\n");
+
+		return false;
+	}
+
+	return true;
+}
+#endif
+
+static int __init sha256_ssse3_mod_init(void)
+{
+	/* test for SSE3 first */
+	if (cpu_has_ssse3)
+		sha256_transform_asm = sha256_transform_ssse3;
+
+#ifdef CONFIG_AS_AVX
+	/* allow AVX to override SSSE3, it's a little faster */
+	if (avx_usable()) {
+#ifdef CONFIG_AS_AVX2
+		if (boot_cpu_has(X86_FEATURE_AVX2))
+			sha256_transform_asm = sha256_transform_rorx;
+		else
+#endif
+			sha256_transform_asm = sha256_transform_avx;
+	}
+#endif
+
+	if (sha256_transform_asm) {
+#ifdef CONFIG_AS_AVX
+		if (sha256_transform_asm == sha256_transform_avx)
+			pr_info("Using AVX optimized SHA-256 implementation\n");
+#ifdef CONFIG_AS_AVX2
+		else if (sha256_transform_asm == sha256_transform_rorx)
+			pr_info("Using AVX2 optimized SHA-256 implementation\n");
+#endif
+		else
+#endif
+			pr_info("Using SSSE3 optimized SHA-256 implementation\n");
+		return crypto_register_shash(&alg);
+	}
+	pr_info("Neither AVX nor SSSE3 is available/usable.\n");
+
+	return -ENODEV;
+}
+
+static void __exit sha256_ssse3_mod_fini(void)
+{
+	crypto_unregister_shash(&alg);
+}
+
+module_init(sha256_ssse3_mod_init);
+module_exit(sha256_ssse3_mod_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("SHA256 Secure Hash Algorithm, Supplemental SSE3 accelerated");
+
+MODULE_ALIAS("sha256");
diff --git a/arch/x86/crypto/sha512-avx-asm.S b/arch/x86/crypto/sha512-avx-asm.S
new file mode 100644
index 0000000..974dde9
--- /dev/null
+++ b/arch/x86/crypto/sha512-avx-asm.S
@@ -0,0 +1,423 @@
+########################################################################
+# Implement fast SHA-512 with AVX instructions. (x86_64)
+#
+# Copyright (C) 2013 Intel Corporation.
+#
+# Authors:
+#     James Guilford <james.guilford@intel.com>
+#     Kirk Yap <kirk.s.yap@intel.com>
+#     David Cote <david.m.cote@intel.com>
+#     Tim Chen <tim.c.chen@linux.intel.com>
+#
+# 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.
+#
+########################################################################
+#
+# This code is described in an Intel White-Paper:
+# "Fast SHA-512 Implementations on Intel Architecture Processors"
+#
+# To find it, surf to http://www.intel.com/p/en_US/embedded
+# and search for that title.
+#
+########################################################################
+
+#ifdef CONFIG_AS_AVX
+#include <linux/linkage.h>
+
+.text
+
+# Virtual Registers
+# ARG1
+msg	= %rdi
+# ARG2
+digest	= %rsi
+# ARG3
+msglen	= %rdx
+T1	= %rcx
+T2	= %r8
+a_64	= %r9
+b_64	= %r10
+c_64	= %r11
+d_64	= %r12
+e_64	= %r13
+f_64	= %r14
+g_64	= %r15
+h_64	= %rbx
+tmp0	= %rax
+
+# Local variables (stack frame)
+
+# Message Schedule
+W_SIZE = 80*8
+# W[t] + K[t] | W[t+1] + K[t+1]
+WK_SIZE = 2*8
+RSPSAVE_SIZE = 1*8
+GPRSAVE_SIZE = 5*8
+
+frame_W = 0
+frame_WK = frame_W + W_SIZE
+frame_RSPSAVE = frame_WK + WK_SIZE
+frame_GPRSAVE = frame_RSPSAVE + RSPSAVE_SIZE
+frame_size = frame_GPRSAVE + GPRSAVE_SIZE
+
+# Useful QWORD "arrays" for simpler memory references
+# MSG, DIGEST, K_t, W_t are arrays
+# WK_2(t) points to 1 of 2 qwords at frame.WK depdending on t being odd/even
+
+# Input message (arg1)
+#define MSG(i)    8*i(msg)
+
+# Output Digest (arg2)
+#define DIGEST(i) 8*i(digest)
+
+# SHA Constants (static mem)
+#define K_t(i)    8*i+K512(%rip)
+
+# Message Schedule (stack frame)
+#define W_t(i)    8*i+frame_W(%rsp)
+
+# W[t]+K[t] (stack frame)
+#define WK_2(i)   8*((i%2))+frame_WK(%rsp)
+
+.macro RotateState
+	# Rotate symbols a..h right
+	TMP   = h_64
+	h_64  = g_64
+	g_64  = f_64
+	f_64  = e_64
+	e_64  = d_64
+	d_64  = c_64
+	c_64  = b_64
+	b_64  = a_64
+	a_64  = TMP
+.endm
+
+.macro RORQ p1 p2
+	# shld is faster than ror on Sandybridge
+	shld	$(64-\p2), \p1, \p1
+.endm
+
+.macro SHA512_Round rnd
+	# Compute Round %%t
+	mov     f_64, T1          # T1 = f
+	mov     e_64, tmp0        # tmp = e
+	xor     g_64, T1          # T1 = f ^ g
+	RORQ    tmp0, 23   # 41    # tmp = e ror 23
+	and     e_64, T1          # T1 = (f ^ g) & e
+	xor     e_64, tmp0        # tmp = (e ror 23) ^ e
+	xor     g_64, T1          # T1 = ((f ^ g) & e) ^ g = CH(e,f,g)
+	idx = \rnd
+	add     WK_2(idx), T1     # W[t] + K[t] from message scheduler
+	RORQ    tmp0, 4   # 18    # tmp = ((e ror 23) ^ e) ror 4
+	xor     e_64, tmp0        # tmp = (((e ror 23) ^ e) ror 4) ^ e
+	mov     a_64, T2          # T2 = a
+	add     h_64, T1          # T1 = CH(e,f,g) + W[t] + K[t] + h
+	RORQ    tmp0, 14  # 14    # tmp = ((((e ror23)^e)ror4)^e)ror14 = S1(e)
+	add     tmp0, T1          # T1 = CH(e,f,g) + W[t] + K[t] + S1(e)
+	mov     a_64, tmp0        # tmp = a
+	xor     c_64, T2          # T2 = a ^ c
+	and     c_64, tmp0        # tmp = a & c
+	and     b_64, T2          # T2 = (a ^ c) & b
+	xor     tmp0, T2          # T2 = ((a ^ c) & b) ^ (a & c) = Maj(a,b,c)
+	mov     a_64, tmp0        # tmp = a
+	RORQ    tmp0, 5  # 39     # tmp = a ror 5
+	xor     a_64, tmp0        # tmp = (a ror 5) ^ a
+	add     T1, d_64          # e(next_state) = d + T1
+	RORQ    tmp0, 6  # 34     # tmp = ((a ror 5) ^ a) ror 6
+	xor     a_64, tmp0        # tmp = (((a ror 5) ^ a) ror 6) ^ a
+	lea     (T1, T2), h_64    # a(next_state) = T1 + Maj(a,b,c)
+	RORQ    tmp0, 28  # 28    # tmp = ((((a ror5)^a)ror6)^a)ror28 = S0(a)
+	add     tmp0, h_64        # a(next_state) = T1 + Maj(a,b,c) S0(a)
+	RotateState
+.endm
+
+.macro SHA512_2Sched_2Round_avx rnd
+	# Compute rounds t-2 and t-1
+	# Compute message schedule QWORDS t and t+1
+
+	#   Two rounds are computed based on the values for K[t-2]+W[t-2] and
+	# K[t-1]+W[t-1] which were previously stored at WK_2 by the message
+	# scheduler.
+	#   The two new schedule QWORDS are stored at [W_t(t)] and [W_t(t+1)].
+	# They are then added to their respective SHA512 constants at
+	# [K_t(t)] and [K_t(t+1)] and stored at dqword [WK_2(t)]
+	#   For brievity, the comments following vectored instructions only refer to
+	# the first of a pair of QWORDS.
+	# Eg. XMM4=W[t-2] really means XMM4={W[t-2]|W[t-1]}
+	#   The computation of the message schedule and the rounds are tightly
+	# stitched to take advantage of instruction-level parallelism.
+
+	idx = \rnd - 2
+	vmovdqa	W_t(idx), %xmm4		# XMM4 = W[t-2]
+	idx = \rnd - 15
+	vmovdqu	W_t(idx), %xmm5		# XMM5 = W[t-15]
+	mov	f_64, T1
+	vpsrlq	$61, %xmm4, %xmm0	# XMM0 = W[t-2]>>61
+	mov	e_64, tmp0
+	vpsrlq	$1, %xmm5, %xmm6	# XMM6 = W[t-15]>>1
+	xor	g_64, T1
+	RORQ	tmp0, 23 # 41
+	vpsrlq	$19, %xmm4, %xmm1	# XMM1 = W[t-2]>>19
+	and	e_64, T1
+	xor	e_64, tmp0
+	vpxor	%xmm1, %xmm0, %xmm0	# XMM0 = W[t-2]>>61 ^ W[t-2]>>19
+	xor	g_64, T1
+	idx = \rnd
+	add	WK_2(idx), T1#
+	vpsrlq	$8, %xmm5, %xmm7	# XMM7 = W[t-15]>>8
+	RORQ	tmp0, 4 # 18
+	vpsrlq	$6, %xmm4, %xmm2	# XMM2 = W[t-2]>>6
+	xor	e_64, tmp0
+	mov	a_64, T2
+	add	h_64, T1
+	vpxor	%xmm7, %xmm6, %xmm6	# XMM6 = W[t-15]>>1 ^ W[t-15]>>8
+	RORQ	tmp0, 14 # 14
+	add	tmp0, T1
+	vpsrlq	$7, %xmm5, %xmm8	# XMM8 = W[t-15]>>7
+	mov	a_64, tmp0
+	xor	c_64, T2
+	vpsllq	$(64-61), %xmm4, %xmm3  # XMM3 = W[t-2]<<3
+	and	c_64, tmp0
+	and	b_64, T2
+	vpxor	%xmm3, %xmm2, %xmm2	# XMM2 = W[t-2]>>6 ^ W[t-2]<<3
+	xor	tmp0, T2
+	mov	a_64, tmp0
+	vpsllq	$(64-1), %xmm5, %xmm9	# XMM9 = W[t-15]<<63
+	RORQ	tmp0, 5 # 39
+	vpxor	%xmm9, %xmm8, %xmm8	# XMM8 = W[t-15]>>7 ^ W[t-15]<<63
+	xor	a_64, tmp0
+	add	T1, d_64
+	RORQ	tmp0, 6 # 34
+	xor	a_64, tmp0
+	vpxor	%xmm8, %xmm6, %xmm6	# XMM6 = W[t-15]>>1 ^ W[t-15]>>8 ^
+					#  W[t-15]>>7 ^ W[t-15]<<63
+	lea	(T1, T2), h_64
+	RORQ	tmp0, 28 # 28
+	vpsllq	$(64-19), %xmm4, %xmm4  # XMM4 = W[t-2]<<25
+	add	tmp0, h_64
+	RotateState
+	vpxor	%xmm4, %xmm0, %xmm0     # XMM0 = W[t-2]>>61 ^ W[t-2]>>19 ^
+					#        W[t-2]<<25
+	mov	f_64, T1
+	vpxor	%xmm2, %xmm0, %xmm0     # XMM0 = s1(W[t-2])
+	mov	e_64, tmp0
+	xor	g_64, T1
+	idx = \rnd - 16
+	vpaddq	W_t(idx), %xmm0, %xmm0  # XMM0 = s1(W[t-2]) + W[t-16]
+	idx = \rnd - 7
+	vmovdqu	W_t(idx), %xmm1		# XMM1 = W[t-7]
+	RORQ	tmp0, 23 # 41
+	and	e_64, T1
+	xor	e_64, tmp0
+	xor	g_64, T1
+	vpsllq	$(64-8), %xmm5, %xmm5   # XMM5 = W[t-15]<<56
+	idx = \rnd + 1
+	add	WK_2(idx), T1
+	vpxor	%xmm5, %xmm6, %xmm6     # XMM6 = s0(W[t-15])
+	RORQ	tmp0, 4 # 18
+	vpaddq	%xmm6, %xmm0, %xmm0     # XMM0 = s1(W[t-2]) + W[t-16] + s0(W[t-15])
+	xor	e_64, tmp0
+	vpaddq	%xmm1, %xmm0, %xmm0     # XMM0 = W[t] = s1(W[t-2]) + W[t-7] +
+					#               s0(W[t-15]) + W[t-16]
+	mov	a_64, T2
+	add	h_64, T1
+	RORQ	tmp0, 14 # 14
+	add	tmp0, T1
+	idx = \rnd
+	vmovdqa	%xmm0, W_t(idx)		# Store W[t]
+	vpaddq	K_t(idx), %xmm0, %xmm0  # Compute W[t]+K[t]
+	vmovdqa	%xmm0, WK_2(idx)	# Store W[t]+K[t] for next rounds
+	mov	a_64, tmp0
+	xor	c_64, T2
+	and	c_64, tmp0
+	and	b_64, T2
+	xor	tmp0, T2
+	mov	a_64, tmp0
+	RORQ	tmp0, 5 # 39
+	xor	a_64, tmp0
+	add	T1, d_64
+	RORQ	tmp0, 6 # 34
+	xor	a_64, tmp0
+	lea	(T1, T2), h_64
+	RORQ	tmp0, 28 # 28
+	add	tmp0, h_64
+	RotateState
+.endm
+
+########################################################################
+# void sha512_transform_avx(const void* M, void* D, u64 L)
+# Purpose: Updates the SHA512 digest stored at D with the message stored in M.
+# The size of the message pointed to by M must be an integer multiple of SHA512
+# message blocks.
+# L is the message length in SHA512 blocks
+########################################################################
+ENTRY(sha512_transform_avx)
+	cmp $0, msglen
+	je nowork
+
+	# Allocate Stack Space
+	mov	%rsp, %rax
+	sub     $frame_size, %rsp
+	and	$~(0x20 - 1), %rsp
+	mov	%rax, frame_RSPSAVE(%rsp)
+
+	# Save GPRs
+	mov     %rbx, frame_GPRSAVE(%rsp)
+	mov     %r12, frame_GPRSAVE +8*1(%rsp)
+	mov     %r13, frame_GPRSAVE +8*2(%rsp)
+	mov     %r14, frame_GPRSAVE +8*3(%rsp)
+	mov     %r15, frame_GPRSAVE +8*4(%rsp)
+
+updateblock:
+
+	# Load state variables
+	mov     DIGEST(0), a_64
+	mov     DIGEST(1), b_64
+	mov     DIGEST(2), c_64
+	mov     DIGEST(3), d_64
+	mov     DIGEST(4), e_64
+	mov     DIGEST(5), f_64
+	mov     DIGEST(6), g_64
+	mov     DIGEST(7), h_64
+
+	t = 0
+	.rept 80/2 + 1
+	# (80 rounds) / (2 rounds/iteration) + (1 iteration)
+	# +1 iteration because the scheduler leads hashing by 1 iteration
+		.if t < 2
+			# BSWAP 2 QWORDS
+			vmovdqa  XMM_QWORD_BSWAP(%rip), %xmm1
+			vmovdqu  MSG(t), %xmm0
+			vpshufb  %xmm1, %xmm0, %xmm0    # BSWAP
+			vmovdqa  %xmm0, W_t(t) # Store Scheduled Pair
+			vpaddq   K_t(t), %xmm0, %xmm0 # Compute W[t]+K[t]
+			vmovdqa  %xmm0, WK_2(t) # Store into WK for rounds
+		.elseif t < 16
+			# BSWAP 2 QWORDS# Compute 2 Rounds
+			vmovdqu  MSG(t), %xmm0
+			vpshufb  %xmm1, %xmm0, %xmm0    # BSWAP
+			SHA512_Round t-2    # Round t-2
+			vmovdqa  %xmm0, W_t(t) # Store Scheduled Pair
+			vpaddq   K_t(t), %xmm0, %xmm0 # Compute W[t]+K[t]
+			SHA512_Round t-1    # Round t-1
+			vmovdqa  %xmm0, WK_2(t)# Store W[t]+K[t] into WK
+		.elseif t < 79
+			# Schedule 2 QWORDS# Compute 2 Rounds
+			SHA512_2Sched_2Round_avx t
+		.else
+			# Compute 2 Rounds
+			SHA512_Round t-2
+			SHA512_Round t-1
+		.endif
+		t = t+2
+	.endr
+
+	# Update digest
+	add     a_64, DIGEST(0)
+	add     b_64, DIGEST(1)
+	add     c_64, DIGEST(2)
+	add     d_64, DIGEST(3)
+	add     e_64, DIGEST(4)
+	add     f_64, DIGEST(5)
+	add     g_64, DIGEST(6)
+	add     h_64, DIGEST(7)
+
+	# Advance to next message block
+	add     $16*8, msg
+	dec     msglen
+	jnz     updateblock
+
+	# Restore GPRs
+	mov     frame_GPRSAVE(%rsp),      %rbx
+	mov     frame_GPRSAVE +8*1(%rsp), %r12
+	mov     frame_GPRSAVE +8*2(%rsp), %r13
+	mov     frame_GPRSAVE +8*3(%rsp), %r14
+	mov     frame_GPRSAVE +8*4(%rsp), %r15
+
+	# Restore Stack Pointer
+	mov	frame_RSPSAVE(%rsp), %rsp
+
+nowork:
+	ret
+ENDPROC(sha512_transform_avx)
+
+########################################################################
+### Binary Data
+
+.data
+
+.align 16
+
+# Mask for byte-swapping a couple of qwords in an XMM register using (v)pshufb.
+XMM_QWORD_BSWAP:
+	.octa 0x08090a0b0c0d0e0f0001020304050607
+
+# K[t] used in SHA512 hashing
+K512:
+	.quad 0x428a2f98d728ae22,0x7137449123ef65cd
+	.quad 0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc
+	.quad 0x3956c25bf348b538,0x59f111f1b605d019
+	.quad 0x923f82a4af194f9b,0xab1c5ed5da6d8118
+	.quad 0xd807aa98a3030242,0x12835b0145706fbe
+	.quad 0x243185be4ee4b28c,0x550c7dc3d5ffb4e2
+	.quad 0x72be5d74f27b896f,0x80deb1fe3b1696b1
+	.quad 0x9bdc06a725c71235,0xc19bf174cf692694
+	.quad 0xe49b69c19ef14ad2,0xefbe4786384f25e3
+	.quad 0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65
+	.quad 0x2de92c6f592b0275,0x4a7484aa6ea6e483
+	.quad 0x5cb0a9dcbd41fbd4,0x76f988da831153b5
+	.quad 0x983e5152ee66dfab,0xa831c66d2db43210
+	.quad 0xb00327c898fb213f,0xbf597fc7beef0ee4
+	.quad 0xc6e00bf33da88fc2,0xd5a79147930aa725
+	.quad 0x06ca6351e003826f,0x142929670a0e6e70
+	.quad 0x27b70a8546d22ffc,0x2e1b21385c26c926
+	.quad 0x4d2c6dfc5ac42aed,0x53380d139d95b3df
+	.quad 0x650a73548baf63de,0x766a0abb3c77b2a8
+	.quad 0x81c2c92e47edaee6,0x92722c851482353b
+	.quad 0xa2bfe8a14cf10364,0xa81a664bbc423001
+	.quad 0xc24b8b70d0f89791,0xc76c51a30654be30
+	.quad 0xd192e819d6ef5218,0xd69906245565a910
+	.quad 0xf40e35855771202a,0x106aa07032bbd1b8
+	.quad 0x19a4c116b8d2d0c8,0x1e376c085141ab53
+	.quad 0x2748774cdf8eeb99,0x34b0bcb5e19b48a8
+	.quad 0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb
+	.quad 0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3
+	.quad 0x748f82ee5defb2fc,0x78a5636f43172f60
+	.quad 0x84c87814a1f0ab72,0x8cc702081a6439ec
+	.quad 0x90befffa23631e28,0xa4506cebde82bde9
+	.quad 0xbef9a3f7b2c67915,0xc67178f2e372532b
+	.quad 0xca273eceea26619c,0xd186b8c721c0c207
+	.quad 0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178
+	.quad 0x06f067aa72176fba,0x0a637dc5a2c898a6
+	.quad 0x113f9804bef90dae,0x1b710b35131c471b
+	.quad 0x28db77f523047d84,0x32caab7b40c72493
+	.quad 0x3c9ebe0a15c9bebc,0x431d67c49c100d4c
+	.quad 0x4cc5d4becb3e42b6,0x597f299cfc657e2a
+	.quad 0x5fcb6fab3ad6faec,0x6c44198c4a475817
+#endif
diff --git a/arch/x86/crypto/sha512-avx2-asm.S b/arch/x86/crypto/sha512-avx2-asm.S
new file mode 100644
index 0000000..568b961
--- /dev/null
+++ b/arch/x86/crypto/sha512-avx2-asm.S
@@ -0,0 +1,743 @@
+########################################################################
+# Implement fast SHA-512 with AVX2 instructions. (x86_64)
+#
+# Copyright (C) 2013 Intel Corporation.
+#
+# Authors:
+#     James Guilford <james.guilford@intel.com>
+#     Kirk Yap <kirk.s.yap@intel.com>
+#     David Cote <david.m.cote@intel.com>
+#     Tim Chen <tim.c.chen@linux.intel.com>
+#
+# 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.
+#
+########################################################################
+#
+# This code is described in an Intel White-Paper:
+# "Fast SHA-512 Implementations on Intel Architecture Processors"
+#
+# To find it, surf to http://www.intel.com/p/en_US/embedded
+# and search for that title.
+#
+########################################################################
+# This code schedules 1 blocks at a time, with 4 lanes per block
+########################################################################
+
+#ifdef CONFIG_AS_AVX2
+#include <linux/linkage.h>
+
+.text
+
+# Virtual Registers
+Y_0 = %ymm4
+Y_1 = %ymm5
+Y_2 = %ymm6
+Y_3 = %ymm7
+
+YTMP0 = %ymm0
+YTMP1 = %ymm1
+YTMP2 = %ymm2
+YTMP3 = %ymm3
+YTMP4 = %ymm8
+XFER  = YTMP0
+
+BYTE_FLIP_MASK  = %ymm9
+
+# 1st arg
+INP         = %rdi
+# 2nd arg
+CTX         = %rsi
+# 3rd arg
+NUM_BLKS    = %rdx
+
+c           = %rcx
+d           = %r8
+e           = %rdx
+y3          = %rdi
+
+TBL   = %rbp
+
+a     = %rax
+b     = %rbx
+
+f     = %r9
+g     = %r10
+h     = %r11
+old_h = %r11
+
+T1    = %r12
+y0    = %r13
+y1    = %r14
+y2    = %r15
+
+y4    = %r12
+
+# Local variables (stack frame)
+XFER_SIZE = 4*8
+SRND_SIZE = 1*8
+INP_SIZE = 1*8
+INPEND_SIZE = 1*8
+RSPSAVE_SIZE = 1*8
+GPRSAVE_SIZE = 6*8
+
+frame_XFER = 0
+frame_SRND = frame_XFER + XFER_SIZE
+frame_INP = frame_SRND + SRND_SIZE
+frame_INPEND = frame_INP + INP_SIZE
+frame_RSPSAVE = frame_INPEND + INPEND_SIZE
+frame_GPRSAVE = frame_RSPSAVE + RSPSAVE_SIZE
+frame_size = frame_GPRSAVE + GPRSAVE_SIZE
+
+## assume buffers not aligned
+#define	VMOVDQ vmovdqu
+
+# addm [mem], reg
+# Add reg to mem using reg-mem add and store
+.macro addm p1 p2
+	add	\p1, \p2
+	mov	\p2, \p1
+.endm
+
+
+# COPY_YMM_AND_BSWAP ymm, [mem], byte_flip_mask
+# Load ymm with mem and byte swap each dword
+.macro COPY_YMM_AND_BSWAP p1 p2 p3
+	VMOVDQ \p2, \p1
+	vpshufb \p3, \p1, \p1
+.endm
+# rotate_Ys
+# Rotate values of symbols Y0...Y3
+.macro rotate_Ys
+	Y_ = Y_0
+	Y_0 = Y_1
+	Y_1 = Y_2
+	Y_2 = Y_3
+	Y_3 = Y_
+.endm
+
+# RotateState
+.macro RotateState
+	# Rotate symbols a..h right
+	old_h  = h
+	TMP_   = h
+	h      = g
+	g      = f
+	f      = e
+	e      = d
+	d      = c
+	c      = b
+	b      = a
+	a      = TMP_
+.endm
+
+# macro MY_VPALIGNR	YDST, YSRC1, YSRC2, RVAL
+# YDST = {YSRC1, YSRC2} >> RVAL*8
+.macro MY_VPALIGNR YDST YSRC1 YSRC2 RVAL
+	vperm2f128      $0x3, \YSRC2, \YSRC1, \YDST     # YDST = {YS1_LO, YS2_HI}
+	vpalignr        $\RVAL, \YSRC2, \YDST, \YDST    # YDST = {YDS1, YS2} >> RVAL*8
+.endm
+
+.macro FOUR_ROUNDS_AND_SCHED
+################################### RND N + 0 #########################################
+
+	# Extract w[t-7]
+	MY_VPALIGNR	YTMP0, Y_3, Y_2, 8		# YTMP0 = W[-7]
+	# Calculate w[t-16] + w[t-7]
+	vpaddq		Y_0, YTMP0, YTMP0		# YTMP0 = W[-7] + W[-16]
+	# Extract w[t-15]
+	MY_VPALIGNR	YTMP1, Y_1, Y_0, 8		# YTMP1 = W[-15]
+
+	# Calculate sigma0
+
+	# Calculate w[t-15] ror 1
+	vpsrlq		$1, YTMP1, YTMP2
+	vpsllq		$(64-1), YTMP1, YTMP3
+	vpor		YTMP2, YTMP3, YTMP3		# YTMP3 = W[-15] ror 1
+	# Calculate w[t-15] shr 7
+	vpsrlq		$7, YTMP1, YTMP4		# YTMP4 = W[-15] >> 7
+
+	mov	a, y3		# y3 = a                                # MAJA
+	rorx	$41, e, y0	# y0 = e >> 41				# S1A
+	rorx	$18, e, y1	# y1 = e >> 18				# S1B
+	add	frame_XFER(%rsp),h		# h = k + w + h         # --
+	or	c, y3		# y3 = a|c                              # MAJA
+	mov	f, y2		# y2 = f                                # CH
+	rorx	$34, a, T1	# T1 = a >> 34				# S0B
+
+	xor	y1, y0		# y0 = (e>>41) ^ (e>>18)		# S1
+	xor	g, y2		# y2 = f^g                              # CH
+	rorx	$14, e, y1	# y1 = (e >> 14)			# S1
+
+	and	e, y2		# y2 = (f^g)&e                          # CH
+	xor	y1, y0		# y0 = (e>>41) ^ (e>>18) ^ (e>>14)	# S1
+	rorx	$39, a, y1	# y1 = a >> 39				# S0A
+	add	h, d		# d = k + w + h + d                     # --
+
+	and	b, y3		# y3 = (a|c)&b                          # MAJA
+	xor	T1, y1		# y1 = (a>>39) ^ (a>>34)		# S0
+	rorx	$28, a, T1	# T1 = (a >> 28)			# S0
+
+	xor	g, y2		# y2 = CH = ((f^g)&e)^g                 # CH
+	xor	T1, y1		# y1 = (a>>39) ^ (a>>34) ^ (a>>28)	# S0
+	mov	a, T1		# T1 = a                                # MAJB
+	and	c, T1		# T1 = a&c                              # MAJB
+
+	add	y0, y2		# y2 = S1 + CH                          # --
+	or	T1, y3		# y3 = MAJ = (a|c)&b)|(a&c)             # MAJ
+	add	y1, h		# h = k + w + h + S0                    # --
+
+	add	y2, d		# d = k + w + h + d + S1 + CH = d + t1  # --
+
+	add	y2, h		# h = k + w + h + S0 + S1 + CH = t1 + S0# --
+	add	y3, h		# h = t1 + S0 + MAJ                     # --
+
+	RotateState
+
+################################### RND N + 1 #########################################
+
+	# Calculate w[t-15] ror 8
+	vpsrlq		$8, YTMP1, YTMP2
+	vpsllq		$(64-8), YTMP1, YTMP1
+	vpor		YTMP2, YTMP1, YTMP1		# YTMP1 = W[-15] ror 8
+	# XOR the three components
+	vpxor		YTMP4, YTMP3, YTMP3		# YTMP3 = W[-15] ror 1 ^ W[-15] >> 7
+	vpxor		YTMP1, YTMP3, YTMP1		# YTMP1 = s0
+
+
+	# Add three components, w[t-16], w[t-7] and sigma0
+	vpaddq		YTMP1, YTMP0, YTMP0		# YTMP0 = W[-16] + W[-7] + s0
+	# Move to appropriate lanes for calculating w[16] and w[17]
+	vperm2f128	$0x0, YTMP0, YTMP0, Y_0		# Y_0 = W[-16] + W[-7] + s0 {BABA}
+	# Move to appropriate lanes for calculating w[18] and w[19]
+	vpand		MASK_YMM_LO(%rip), YTMP0, YTMP0	# YTMP0 = W[-16] + W[-7] + s0 {DC00}
+
+	# Calculate w[16] and w[17] in both 128 bit lanes
+
+	# Calculate sigma1 for w[16] and w[17] on both 128 bit lanes
+	vperm2f128	$0x11, Y_3, Y_3, YTMP2		# YTMP2 = W[-2] {BABA}
+	vpsrlq		$6, YTMP2, YTMP4		# YTMP4 = W[-2] >> 6 {BABA}
+
+
+	mov	a, y3		# y3 = a                                # MAJA
+	rorx	$41, e, y0	# y0 = e >> 41				# S1A
+	rorx	$18, e, y1	# y1 = e >> 18				# S1B
+	add	1*8+frame_XFER(%rsp), h		# h = k + w + h         # --
+	or	c, y3		# y3 = a|c                              # MAJA
+
+
+	mov	f, y2		# y2 = f                                # CH
+	rorx	$34, a, T1	# T1 = a >> 34				# S0B
+	xor	y1, y0		# y0 = (e>>41) ^ (e>>18)		# S1
+	xor	g, y2		# y2 = f^g                              # CH
+
+
+	rorx	$14, e, y1	# y1 = (e >> 14)			# S1
+	xor	y1, y0		# y0 = (e>>41) ^ (e>>18) ^ (e>>14)	# S1
+	rorx	$39, a, y1	# y1 = a >> 39				# S0A
+	and	e, y2		# y2 = (f^g)&e                          # CH
+	add	h, d		# d = k + w + h + d                     # --
+
+	and	b, y3		# y3 = (a|c)&b                          # MAJA
+	xor	T1, y1		# y1 = (a>>39) ^ (a>>34)		# S0
+
+	rorx	$28, a, T1	# T1 = (a >> 28)			# S0
+	xor	g, y2		# y2 = CH = ((f^g)&e)^g                 # CH
+
+	xor	T1, y1		# y1 = (a>>39) ^ (a>>34) ^ (a>>28)	# S0
+	mov	a, T1		# T1 = a                                # MAJB
+	and	c, T1		# T1 = a&c                              # MAJB
+	add	y0, y2		# y2 = S1 + CH                          # --
+
+	or	T1, y3		# y3 = MAJ = (a|c)&b)|(a&c)             # MAJ
+	add	y1, h		# h = k + w + h + S0                    # --
+
+	add	y2, d		# d = k + w + h + d + S1 + CH = d + t1  # --
+	add	y2, h		# h = k + w + h + S0 + S1 + CH = t1 + S0# --
+	add	y3, h		# h = t1 + S0 + MAJ                     # --
+
+	RotateState
+
+
+################################### RND N + 2 #########################################
+
+	vpsrlq		$19, YTMP2, YTMP3		# YTMP3 = W[-2] >> 19 {BABA}
+	vpsllq		$(64-19), YTMP2, YTMP1		# YTMP1 = W[-2] << 19 {BABA}
+	vpor		YTMP1, YTMP3, YTMP3		# YTMP3 = W[-2] ror 19 {BABA}
+	vpxor		YTMP3, YTMP4, YTMP4		# YTMP4 = W[-2] ror 19 ^ W[-2] >> 6 {BABA}
+	vpsrlq		$61, YTMP2, YTMP3		# YTMP3 = W[-2] >> 61 {BABA}
+	vpsllq		$(64-61), YTMP2, YTMP1		# YTMP1 = W[-2] << 61 {BABA}
+	vpor		YTMP1, YTMP3, YTMP3		# YTMP3 = W[-2] ror 61 {BABA}
+	vpxor		YTMP3, YTMP4, YTMP4		# YTMP4 = s1 = (W[-2] ror 19) ^
+							#  (W[-2] ror 61) ^ (W[-2] >> 6) {BABA}
+
+	# Add sigma1 to the other compunents to get w[16] and w[17]
+	vpaddq		YTMP4, Y_0, Y_0			# Y_0 = {W[1], W[0], W[1], W[0]}
+
+	# Calculate sigma1 for w[18] and w[19] for upper 128 bit lane
+	vpsrlq		$6, Y_0, YTMP4			# YTMP4 = W[-2] >> 6 {DC--}
+
+	mov	a, y3		# y3 = a                                # MAJA
+	rorx	$41, e, y0	# y0 = e >> 41				# S1A
+	add	2*8+frame_XFER(%rsp), h		# h = k + w + h         # --
+
+	rorx	$18, e, y1	# y1 = e >> 18				# S1B
+	or	c, y3		# y3 = a|c                              # MAJA
+	mov	f, y2		# y2 = f                                # CH
+	xor	g, y2		# y2 = f^g                              # CH
+
+	rorx	$34, a, T1	# T1 = a >> 34				# S0B
+	xor	y1, y0		# y0 = (e>>41) ^ (e>>18)		# S1
+	and	e, y2		# y2 = (f^g)&e                          # CH
+
+	rorx	$14, e, y1	# y1 = (e >> 14)			# S1
+	add	h, d		# d = k + w + h + d                     # --
+	and	b, y3		# y3 = (a|c)&b                          # MAJA
+
+	xor	y1, y0		# y0 = (e>>41) ^ (e>>18) ^ (e>>14)	# S1
+	rorx	$39, a, y1	# y1 = a >> 39				# S0A
+	xor	g, y2		# y2 = CH = ((f^g)&e)^g                 # CH
+
+	xor	T1, y1		# y1 = (a>>39) ^ (a>>34)		# S0
+	rorx	$28, a, T1	# T1 = (a >> 28)			# S0
+
+	xor	T1, y1		# y1 = (a>>39) ^ (a>>34) ^ (a>>28)	# S0
+	mov	a, T1		# T1 = a                                # MAJB
+	and	c, T1		# T1 = a&c                              # MAJB
+	add	y0, y2		# y2 = S1 + CH                          # --
+
+	or	T1, y3		# y3 = MAJ = (a|c)&b)|(a&c)             # MAJ
+	add	y1, h		# h = k + w + h + S0                    # --
+	add	y2, d		# d = k + w + h + d + S1 + CH = d + t1  # --
+	add	y2, h		# h = k + w + h + S0 + S1 + CH = t1 + S0# --
+
+	add	y3, h		# h = t1 + S0 + MAJ                     # --
+
+	RotateState
+
+################################### RND N + 3 #########################################
+
+	vpsrlq		$19, Y_0, YTMP3			# YTMP3 = W[-2] >> 19 {DC--}
+	vpsllq		$(64-19), Y_0, YTMP1		# YTMP1 = W[-2] << 19 {DC--}
+	vpor		YTMP1, YTMP3, YTMP3		# YTMP3 = W[-2] ror 19 {DC--}
+	vpxor		YTMP3, YTMP4, YTMP4		# YTMP4 = W[-2] ror 19 ^ W[-2] >> 6 {DC--}
+	vpsrlq		$61, Y_0, YTMP3			# YTMP3 = W[-2] >> 61 {DC--}
+	vpsllq		$(64-61), Y_0, YTMP1		# YTMP1 = W[-2] << 61 {DC--}
+	vpor		YTMP1, YTMP3, YTMP3		# YTMP3 = W[-2] ror 61 {DC--}
+	vpxor		YTMP3, YTMP4, YTMP4		# YTMP4 = s1 = (W[-2] ror 19) ^
+							#  (W[-2] ror 61) ^ (W[-2] >> 6) {DC--}
+
+	# Add the sigma0 + w[t-7] + w[t-16] for w[18] and w[19]
+	# to newly calculated sigma1 to get w[18] and w[19]
+	vpaddq		YTMP4, YTMP0, YTMP2		# YTMP2 = {W[3], W[2], --, --}
+
+	# Form w[19, w[18], w17], w[16]
+	vpblendd		$0xF0, YTMP2, Y_0, Y_0		# Y_0 = {W[3], W[2], W[1], W[0]}
+
+	mov	a, y3		# y3 = a                                # MAJA
+	rorx	$41, e, y0	# y0 = e >> 41				# S1A
+	rorx	$18, e, y1	# y1 = e >> 18				# S1B
+	add	3*8+frame_XFER(%rsp), h		# h = k + w + h         # --
+	or	c, y3		# y3 = a|c                              # MAJA
+
+
+	mov	f, y2		# y2 = f                                # CH
+	rorx	$34, a, T1	# T1 = a >> 34				# S0B
+	xor	y1, y0		# y0 = (e>>41) ^ (e>>18)		# S1
+	xor	g, y2		# y2 = f^g                              # CH
+
+
+	rorx	$14, e, y1	# y1 = (e >> 14)			# S1
+	and	e, y2		# y2 = (f^g)&e                          # CH
+	add	h, d		# d = k + w + h + d                     # --
+	and	b, y3		# y3 = (a|c)&b                          # MAJA
+
+	xor	y1, y0		# y0 = (e>>41) ^ (e>>18) ^ (e>>14)	# S1
+	xor	g, y2		# y2 = CH = ((f^g)&e)^g                 # CH
+
+	rorx	$39, a, y1	# y1 = a >> 39				# S0A
+	add	y0, y2		# y2 = S1 + CH                          # --
+
+	xor	T1, y1		# y1 = (a>>39) ^ (a>>34)		# S0
+	add	y2, d		# d = k + w + h + d + S1 + CH = d + t1  # --
+
+	rorx	$28, a, T1	# T1 = (a >> 28)			# S0
+
+	xor	T1, y1		# y1 = (a>>39) ^ (a>>34) ^ (a>>28)	# S0
+	mov	a, T1		# T1 = a                                # MAJB
+	and	c, T1		# T1 = a&c                              # MAJB
+	or	T1, y3		# y3 = MAJ = (a|c)&b)|(a&c)             # MAJ
+
+	add	y1, h		# h = k + w + h + S0                    # --
+	add	y2, h		# h = k + w + h + S0 + S1 + CH = t1 + S0# --
+	add	y3, h		# h = t1 + S0 + MAJ                     # --
+
+	RotateState
+
+	rotate_Ys
+.endm
+
+.macro DO_4ROUNDS
+
+################################### RND N + 0 #########################################
+
+	mov	f, y2		# y2 = f                                # CH
+	rorx	$41, e, y0	# y0 = e >> 41				# S1A
+	rorx	$18, e, y1	# y1 = e >> 18				# S1B
+	xor	g, y2		# y2 = f^g                              # CH
+
+	xor	y1, y0		# y0 = (e>>41) ^ (e>>18)		# S1
+	rorx	$14, e, y1	# y1 = (e >> 14)			# S1
+	and	e, y2		# y2 = (f^g)&e                          # CH
+
+	xor	y1, y0		# y0 = (e>>41) ^ (e>>18) ^ (e>>14)	# S1
+	rorx	$34, a, T1	# T1 = a >> 34				# S0B
+	xor	g, y2		# y2 = CH = ((f^g)&e)^g                 # CH
+	rorx	$39, a, y1	# y1 = a >> 39				# S0A
+	mov	a, y3		# y3 = a                                # MAJA
+
+	xor	T1, y1		# y1 = (a>>39) ^ (a>>34)		# S0
+	rorx	$28, a, T1	# T1 = (a >> 28)			# S0
+	add	frame_XFER(%rsp), h		# h = k + w + h         # --
+	or	c, y3		# y3 = a|c                              # MAJA
+
+	xor	T1, y1		# y1 = (a>>39) ^ (a>>34) ^ (a>>28)	# S0
+	mov	a, T1		# T1 = a                                # MAJB
+	and	b, y3		# y3 = (a|c)&b                          # MAJA
+	and	c, T1		# T1 = a&c                              # MAJB
+	add	y0, y2		# y2 = S1 + CH                          # --
+
+	add	h, d		# d = k + w + h + d                     # --
+	or	T1, y3		# y3 = MAJ = (a|c)&b)|(a&c)             # MAJ
+	add	y1, h		# h = k + w + h + S0                    # --
+
+	add	y2, d		# d = k + w + h + d + S1 + CH = d + t1  # --
+
+	RotateState
+
+################################### RND N + 1 #########################################
+
+	add	y2, old_h	# h = k + w + h + S0 + S1 + CH = t1 + S0# --
+	mov	f, y2		# y2 = f                                # CH
+	rorx	$41, e, y0	# y0 = e >> 41				# S1A
+	rorx	$18, e, y1	# y1 = e >> 18				# S1B
+	xor	g, y2		# y2 = f^g                              # CH
+
+	xor	y1, y0		# y0 = (e>>41) ^ (e>>18)		# S1
+	rorx	$14, e, y1	# y1 = (e >> 14)			# S1
+	and	e, y2		# y2 = (f^g)&e                          # CH
+	add	y3, old_h	# h = t1 + S0 + MAJ                     # --
+
+	xor	y1, y0		# y0 = (e>>41) ^ (e>>18) ^ (e>>14)	# S1
+	rorx	$34, a, T1	# T1 = a >> 34				# S0B
+	xor	g, y2		# y2 = CH = ((f^g)&e)^g                 # CH
+	rorx	$39, a, y1	# y1 = a >> 39				# S0A
+	mov	a, y3		# y3 = a                                # MAJA
+
+	xor	T1, y1		# y1 = (a>>39) ^ (a>>34)		# S0
+	rorx	$28, a, T1	# T1 = (a >> 28)			# S0
+	add	8*1+frame_XFER(%rsp), h		# h = k + w + h         # --
+	or	c, y3		# y3 = a|c                              # MAJA
+
+	xor	T1, y1		# y1 = (a>>39) ^ (a>>34) ^ (a>>28)	# S0
+	mov	a, T1		# T1 = a                                # MAJB
+	and	b, y3		# y3 = (a|c)&b                          # MAJA
+	and	c, T1		# T1 = a&c                              # MAJB
+	add	y0, y2		# y2 = S1 + CH                          # --
+
+	add	h, d		# d = k + w + h + d                     # --
+	or	T1, y3		# y3 = MAJ = (a|c)&b)|(a&c)             # MAJ
+	add	y1, h		# h = k + w + h + S0                    # --
+
+	add	y2, d		# d = k + w + h + d + S1 + CH = d + t1  # --
+
+	RotateState
+
+################################### RND N + 2 #########################################
+
+	add	y2, old_h	# h = k + w + h + S0 + S1 + CH = t1 + S0# --
+	mov	f, y2		# y2 = f                                # CH
+	rorx	$41, e, y0	# y0 = e >> 41				# S1A
+	rorx	$18, e, y1	# y1 = e >> 18				# S1B
+	xor	g, y2		# y2 = f^g                              # CH
+
+	xor	y1, y0		# y0 = (e>>41) ^ (e>>18)		# S1
+	rorx	$14, e, y1	# y1 = (e >> 14)			# S1
+	and	e, y2		# y2 = (f^g)&e                          # CH
+	add	y3, old_h	# h = t1 + S0 + MAJ                     # --
+
+	xor	y1, y0		# y0 = (e>>41) ^ (e>>18) ^ (e>>14)	# S1
+	rorx	$34, a, T1	# T1 = a >> 34				# S0B
+	xor	g, y2		# y2 = CH = ((f^g)&e)^g                 # CH
+	rorx	$39, a, y1	# y1 = a >> 39				# S0A
+	mov	a, y3		# y3 = a                                # MAJA
+
+	xor	T1, y1		# y1 = (a>>39) ^ (a>>34)		# S0
+	rorx	$28, a, T1	# T1 = (a >> 28)			# S0
+	add	8*2+frame_XFER(%rsp), h		# h = k + w + h         # --
+	or	c, y3		# y3 = a|c                              # MAJA
+
+	xor	T1, y1		# y1 = (a>>39) ^ (a>>34) ^ (a>>28)	# S0
+	mov	a, T1		# T1 = a                                # MAJB
+	and	b, y3		# y3 = (a|c)&b                          # MAJA
+	and	c, T1		# T1 = a&c                              # MAJB
+	add	y0, y2		# y2 = S1 + CH                          # --
+
+	add	h, d		# d = k + w + h + d                     # --
+	or	T1, y3		# y3 = MAJ = (a|c)&b)|(a&c)             # MAJ
+	add	y1, h		# h = k + w + h + S0                    # --
+
+	add	y2, d		# d = k + w + h + d + S1 + CH = d + t1  # --
+
+	RotateState
+
+################################### RND N + 3 #########################################
+
+	add	y2, old_h	# h = k + w + h + S0 + S1 + CH = t1 + S0# --
+	mov	f, y2		# y2 = f                                # CH
+	rorx	$41, e, y0	# y0 = e >> 41				# S1A
+	rorx	$18, e, y1	# y1 = e >> 18				# S1B
+	xor	g, y2		# y2 = f^g                              # CH
+
+	xor	y1, y0		# y0 = (e>>41) ^ (e>>18)		# S1
+	rorx	$14, e, y1	# y1 = (e >> 14)			# S1
+	and	e, y2		# y2 = (f^g)&e                          # CH
+	add	y3, old_h	# h = t1 + S0 + MAJ                     # --
+
+	xor	y1, y0		# y0 = (e>>41) ^ (e>>18) ^ (e>>14)	# S1
+	rorx	$34, a, T1	# T1 = a >> 34				# S0B
+	xor	g, y2		# y2 = CH = ((f^g)&e)^g                 # CH
+	rorx	$39, a, y1	# y1 = a >> 39				# S0A
+	mov	a, y3		# y3 = a                                # MAJA
+
+	xor	T1, y1		# y1 = (a>>39) ^ (a>>34)		# S0
+	rorx	$28, a, T1	# T1 = (a >> 28)			# S0
+	add	8*3+frame_XFER(%rsp), h		# h = k + w + h         # --
+	or	c, y3		# y3 = a|c                              # MAJA
+
+	xor	T1, y1		# y1 = (a>>39) ^ (a>>34) ^ (a>>28)	# S0
+	mov	a, T1		# T1 = a                                # MAJB
+	and	b, y3		# y3 = (a|c)&b                          # MAJA
+	and	c, T1		# T1 = a&c                              # MAJB
+	add	y0, y2		# y2 = S1 + CH                          # --
+
+
+	add	h, d		# d = k + w + h + d                     # --
+	or	T1, y3		# y3 = MAJ = (a|c)&b)|(a&c)             # MAJ
+	add	y1, h		# h = k + w + h + S0                    # --
+
+	add	y2, d		# d = k + w + h + d + S1 + CH = d + t1  # --
+
+	add	y2, h		# h = k + w + h + S0 + S1 + CH = t1 + S0# --
+
+	add	y3, h		# h = t1 + S0 + MAJ                     # --
+
+	RotateState
+
+.endm
+
+########################################################################
+# void sha512_transform_rorx(const void* M, void* D, uint64_t L)#
+# Purpose: Updates the SHA512 digest stored at D with the message stored in M.
+# The size of the message pointed to by M must be an integer multiple of SHA512
+#   message blocks.
+# L is the message length in SHA512 blocks
+########################################################################
+ENTRY(sha512_transform_rorx)
+	# Allocate Stack Space
+	mov	%rsp, %rax
+	sub	$frame_size, %rsp
+	and	$~(0x20 - 1), %rsp
+	mov	%rax, frame_RSPSAVE(%rsp)
+
+	# Save GPRs
+	mov	%rbp, frame_GPRSAVE(%rsp)
+	mov	%rbx, 8*1+frame_GPRSAVE(%rsp)
+	mov	%r12, 8*2+frame_GPRSAVE(%rsp)
+	mov	%r13, 8*3+frame_GPRSAVE(%rsp)
+	mov	%r14, 8*4+frame_GPRSAVE(%rsp)
+	mov	%r15, 8*5+frame_GPRSAVE(%rsp)
+
+	shl	$7, NUM_BLKS	# convert to bytes
+	jz	done_hash
+	add	INP, NUM_BLKS	# pointer to end of data
+	mov	NUM_BLKS, frame_INPEND(%rsp)
+
+	## load initial digest
+	mov	8*0(CTX),a
+	mov	8*1(CTX),b
+	mov	8*2(CTX),c
+	mov	8*3(CTX),d
+	mov	8*4(CTX),e
+	mov	8*5(CTX),f
+	mov	8*6(CTX),g
+	mov	8*7(CTX),h
+
+	vmovdqa	PSHUFFLE_BYTE_FLIP_MASK(%rip), BYTE_FLIP_MASK
+
+loop0:
+	lea	K512(%rip), TBL
+
+	## byte swap first 16 dwords
+	COPY_YMM_AND_BSWAP	Y_0, (INP), BYTE_FLIP_MASK
+	COPY_YMM_AND_BSWAP	Y_1, 1*32(INP), BYTE_FLIP_MASK
+	COPY_YMM_AND_BSWAP	Y_2, 2*32(INP), BYTE_FLIP_MASK
+	COPY_YMM_AND_BSWAP	Y_3, 3*32(INP), BYTE_FLIP_MASK
+
+	mov	INP, frame_INP(%rsp)
+
+	## schedule 64 input dwords, by doing 12 rounds of 4 each
+	movq	$4, frame_SRND(%rsp)
+
+.align 16
+loop1:
+	vpaddq	(TBL), Y_0, XFER
+	vmovdqa XFER, frame_XFER(%rsp)
+	FOUR_ROUNDS_AND_SCHED
+
+	vpaddq	1*32(TBL), Y_0, XFER
+	vmovdqa XFER, frame_XFER(%rsp)
+	FOUR_ROUNDS_AND_SCHED
+
+	vpaddq	2*32(TBL), Y_0, XFER
+	vmovdqa XFER, frame_XFER(%rsp)
+	FOUR_ROUNDS_AND_SCHED
+
+	vpaddq	3*32(TBL), Y_0, XFER
+	vmovdqa XFER, frame_XFER(%rsp)
+	add	$(4*32), TBL
+	FOUR_ROUNDS_AND_SCHED
+
+	subq	$1, frame_SRND(%rsp)
+	jne	loop1
+
+	movq	$2, frame_SRND(%rsp)
+loop2:
+	vpaddq	(TBL), Y_0, XFER
+	vmovdqa XFER, frame_XFER(%rsp)
+	DO_4ROUNDS
+	vpaddq	1*32(TBL), Y_1, XFER
+	vmovdqa XFER, frame_XFER(%rsp)
+	add	$(2*32), TBL
+	DO_4ROUNDS
+
+	vmovdqa	Y_2, Y_0
+	vmovdqa	Y_3, Y_1
+
+	subq	$1, frame_SRND(%rsp)
+	jne	loop2
+
+	addm	8*0(CTX),a
+	addm	8*1(CTX),b
+	addm	8*2(CTX),c
+	addm	8*3(CTX),d
+	addm	8*4(CTX),e
+	addm	8*5(CTX),f
+	addm	8*6(CTX),g
+	addm	8*7(CTX),h
+
+	mov	frame_INP(%rsp), INP
+	add	$128, INP
+	cmp	frame_INPEND(%rsp), INP
+	jne	loop0
+
+done_hash:
+
+# Restore GPRs
+	mov	frame_GPRSAVE(%rsp)     ,%rbp
+	mov	8*1+frame_GPRSAVE(%rsp) ,%rbx
+	mov	8*2+frame_GPRSAVE(%rsp) ,%r12
+	mov	8*3+frame_GPRSAVE(%rsp) ,%r13
+	mov	8*4+frame_GPRSAVE(%rsp) ,%r14
+	mov	8*5+frame_GPRSAVE(%rsp) ,%r15
+
+	# Restore Stack Pointer
+	mov	frame_RSPSAVE(%rsp), %rsp
+	ret
+ENDPROC(sha512_transform_rorx)
+
+########################################################################
+### Binary Data
+
+.data
+
+.align 64
+# K[t] used in SHA512 hashing
+K512:
+	.quad	0x428a2f98d728ae22,0x7137449123ef65cd
+	.quad	0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc
+	.quad	0x3956c25bf348b538,0x59f111f1b605d019
+	.quad	0x923f82a4af194f9b,0xab1c5ed5da6d8118
+	.quad	0xd807aa98a3030242,0x12835b0145706fbe
+	.quad	0x243185be4ee4b28c,0x550c7dc3d5ffb4e2
+	.quad	0x72be5d74f27b896f,0x80deb1fe3b1696b1
+	.quad	0x9bdc06a725c71235,0xc19bf174cf692694
+	.quad	0xe49b69c19ef14ad2,0xefbe4786384f25e3
+	.quad	0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65
+	.quad	0x2de92c6f592b0275,0x4a7484aa6ea6e483
+	.quad	0x5cb0a9dcbd41fbd4,0x76f988da831153b5
+	.quad	0x983e5152ee66dfab,0xa831c66d2db43210
+	.quad	0xb00327c898fb213f,0xbf597fc7beef0ee4
+	.quad	0xc6e00bf33da88fc2,0xd5a79147930aa725
+	.quad	0x06ca6351e003826f,0x142929670a0e6e70
+	.quad	0x27b70a8546d22ffc,0x2e1b21385c26c926
+	.quad	0x4d2c6dfc5ac42aed,0x53380d139d95b3df
+	.quad	0x650a73548baf63de,0x766a0abb3c77b2a8
+	.quad	0x81c2c92e47edaee6,0x92722c851482353b
+	.quad	0xa2bfe8a14cf10364,0xa81a664bbc423001
+	.quad	0xc24b8b70d0f89791,0xc76c51a30654be30
+	.quad	0xd192e819d6ef5218,0xd69906245565a910
+	.quad	0xf40e35855771202a,0x106aa07032bbd1b8
+	.quad	0x19a4c116b8d2d0c8,0x1e376c085141ab53
+	.quad	0x2748774cdf8eeb99,0x34b0bcb5e19b48a8
+	.quad	0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb
+	.quad	0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3
+	.quad	0x748f82ee5defb2fc,0x78a5636f43172f60
+	.quad	0x84c87814a1f0ab72,0x8cc702081a6439ec
+	.quad	0x90befffa23631e28,0xa4506cebde82bde9
+	.quad	0xbef9a3f7b2c67915,0xc67178f2e372532b
+	.quad	0xca273eceea26619c,0xd186b8c721c0c207
+	.quad	0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178
+	.quad	0x06f067aa72176fba,0x0a637dc5a2c898a6
+	.quad	0x113f9804bef90dae,0x1b710b35131c471b
+	.quad	0x28db77f523047d84,0x32caab7b40c72493
+	.quad	0x3c9ebe0a15c9bebc,0x431d67c49c100d4c
+	.quad	0x4cc5d4becb3e42b6,0x597f299cfc657e2a
+	.quad	0x5fcb6fab3ad6faec,0x6c44198c4a475817
+
+.align 32
+
+# Mask for byte-swapping a couple of qwords in an XMM register using (v)pshufb.
+PSHUFFLE_BYTE_FLIP_MASK:
+	.octa 0x08090a0b0c0d0e0f0001020304050607
+	.octa 0x18191a1b1c1d1e1f1011121314151617
+
+MASK_YMM_LO:
+	.octa 0x00000000000000000000000000000000
+	.octa 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+#endif
diff --git a/arch/x86/crypto/sha512-ssse3-asm.S b/arch/x86/crypto/sha512-ssse3-asm.S
new file mode 100644
index 0000000..fb56855
--- /dev/null
+++ b/arch/x86/crypto/sha512-ssse3-asm.S
@@ -0,0 +1,421 @@
+########################################################################
+# Implement fast SHA-512 with SSSE3 instructions. (x86_64)
+#
+# Copyright (C) 2013 Intel Corporation.
+#
+# Authors:
+#     James Guilford <james.guilford@intel.com>
+#     Kirk Yap <kirk.s.yap@intel.com>
+#     David Cote <david.m.cote@intel.com>
+#     Tim Chen <tim.c.chen@linux.intel.com>
+#
+# 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.
+#
+########################################################################
+#
+# This code is described in an Intel White-Paper:
+# "Fast SHA-512 Implementations on Intel Architecture Processors"
+#
+# To find it, surf to http://www.intel.com/p/en_US/embedded
+# and search for that title.
+#
+########################################################################
+
+#include <linux/linkage.h>
+
+.text
+
+# Virtual Registers
+# ARG1
+msg =		%rdi
+# ARG2
+digest =	%rsi
+# ARG3
+msglen =	%rdx
+T1 =		%rcx
+T2 =		%r8
+a_64 =		%r9
+b_64 =		%r10
+c_64 =		%r11
+d_64 =		%r12
+e_64 =		%r13
+f_64 =		%r14
+g_64 =		%r15
+h_64 =		%rbx
+tmp0 =		%rax
+
+# Local variables (stack frame)
+
+W_SIZE = 80*8
+WK_SIZE = 2*8
+RSPSAVE_SIZE = 1*8
+GPRSAVE_SIZE = 5*8
+
+frame_W = 0
+frame_WK = frame_W + W_SIZE
+frame_RSPSAVE = frame_WK + WK_SIZE
+frame_GPRSAVE = frame_RSPSAVE + RSPSAVE_SIZE
+frame_size = frame_GPRSAVE + GPRSAVE_SIZE
+
+# Useful QWORD "arrays" for simpler memory references
+# MSG, DIGEST, K_t, W_t are arrays
+# WK_2(t) points to 1 of 2 qwords at frame.WK depdending on t being odd/even
+
+# Input message (arg1)
+#define MSG(i)    8*i(msg)
+
+# Output Digest (arg2)
+#define DIGEST(i) 8*i(digest)
+
+# SHA Constants (static mem)
+#define K_t(i)    8*i+K512(%rip)
+
+# Message Schedule (stack frame)
+#define W_t(i)    8*i+frame_W(%rsp)
+
+# W[t]+K[t] (stack frame)
+#define WK_2(i)   8*((i%2))+frame_WK(%rsp)
+
+.macro RotateState
+	# Rotate symbols a..h right
+	TMP   = h_64
+	h_64  = g_64
+	g_64  = f_64
+	f_64  = e_64
+	e_64  = d_64
+	d_64  = c_64
+	c_64  = b_64
+	b_64  = a_64
+	a_64  = TMP
+.endm
+
+.macro SHA512_Round rnd
+
+	# Compute Round %%t
+	mov	f_64, T1          # T1 = f
+	mov	e_64, tmp0        # tmp = e
+	xor	g_64, T1          # T1 = f ^ g
+	ror	$23, tmp0 # 41    # tmp = e ror 23
+	and	e_64, T1          # T1 = (f ^ g) & e
+	xor	e_64, tmp0        # tmp = (e ror 23) ^ e
+	xor	g_64, T1          # T1 = ((f ^ g) & e) ^ g = CH(e,f,g)
+	idx = \rnd
+	add	WK_2(idx), T1     # W[t] + K[t] from message scheduler
+	ror	$4, tmp0  # 18    # tmp = ((e ror 23) ^ e) ror 4
+	xor	e_64, tmp0        # tmp = (((e ror 23) ^ e) ror 4) ^ e
+	mov	a_64, T2          # T2 = a
+	add	h_64, T1          # T1 = CH(e,f,g) + W[t] + K[t] + h
+	ror	$14, tmp0 # 14    # tmp = ((((e ror23)^e)ror4)^e)ror14 = S1(e)
+	add	tmp0, T1          # T1 = CH(e,f,g) + W[t] + K[t] + S1(e)
+	mov	a_64, tmp0        # tmp = a
+	xor	c_64, T2          # T2 = a ^ c
+	and	c_64, tmp0        # tmp = a & c
+	and	b_64, T2          # T2 = (a ^ c) & b
+	xor	tmp0, T2          # T2 = ((a ^ c) & b) ^ (a & c) = Maj(a,b,c)
+	mov	a_64, tmp0        # tmp = a
+	ror	$5, tmp0 # 39     # tmp = a ror 5
+	xor	a_64, tmp0        # tmp = (a ror 5) ^ a
+	add	T1, d_64          # e(next_state) = d + T1
+	ror	$6, tmp0 # 34     # tmp = ((a ror 5) ^ a) ror 6
+	xor	a_64, tmp0        # tmp = (((a ror 5) ^ a) ror 6) ^ a
+	lea	(T1, T2), h_64    # a(next_state) = T1 + Maj(a,b,c)
+	ror	$28, tmp0 # 28    # tmp = ((((a ror5)^a)ror6)^a)ror28 = S0(a)
+	add	tmp0, h_64        # a(next_state) = T1 + Maj(a,b,c) S0(a)
+	RotateState
+.endm
+
+.macro SHA512_2Sched_2Round_sse rnd
+
+	# Compute rounds t-2 and t-1
+	# Compute message schedule QWORDS t and t+1
+
+	#   Two rounds are computed based on the values for K[t-2]+W[t-2] and
+	# K[t-1]+W[t-1] which were previously stored at WK_2 by the message
+	# scheduler.
+	#   The two new schedule QWORDS are stored at [W_t(%%t)] and [W_t(%%t+1)].
+	# They are then added to their respective SHA512 constants at
+	# [K_t(%%t)] and [K_t(%%t+1)] and stored at dqword [WK_2(%%t)]
+	#   For brievity, the comments following vectored instructions only refer to
+	# the first of a pair of QWORDS.
+	# Eg. XMM2=W[t-2] really means XMM2={W[t-2]|W[t-1]}
+	#   The computation of the message schedule and the rounds are tightly
+	# stitched to take advantage of instruction-level parallelism.
+	# For clarity, integer instructions (for the rounds calculation) are indented
+	# by one tab. Vectored instructions (for the message scheduler) are indented
+	# by two tabs.
+
+	mov	f_64, T1
+	idx = \rnd -2
+	movdqa	W_t(idx), %xmm2		    # XMM2 = W[t-2]
+	xor	g_64, T1
+	and	e_64, T1
+	movdqa	%xmm2, %xmm0	            # XMM0 = W[t-2]
+	xor	g_64, T1
+	idx = \rnd
+	add	WK_2(idx), T1
+	idx = \rnd - 15
+	movdqu	W_t(idx), %xmm5		    # XMM5 = W[t-15]
+	mov	e_64, tmp0
+	ror	$23, tmp0 # 41
+	movdqa	%xmm5, %xmm3	            # XMM3 = W[t-15]
+	xor	e_64, tmp0
+	ror	$4, tmp0 # 18
+	psrlq	$61-19, %xmm0		    # XMM0 = W[t-2] >> 42
+	xor	e_64, tmp0
+	ror	$14, tmp0 # 14
+	psrlq	$(8-7), %xmm3		    # XMM3 = W[t-15] >> 1
+	add	tmp0, T1
+	add	h_64, T1
+	pxor	%xmm2, %xmm0                # XMM0 = (W[t-2] >> 42) ^ W[t-2]
+	mov	a_64, T2
+	xor	c_64, T2
+	pxor	%xmm5, %xmm3                # XMM3 = (W[t-15] >> 1) ^ W[t-15]
+	and	b_64, T2
+	mov	a_64, tmp0
+	psrlq	$(19-6), %xmm0		    # XMM0 = ((W[t-2]>>42)^W[t-2])>>13
+	and	c_64, tmp0
+	xor	tmp0, T2
+	psrlq	$(7-1), %xmm3		    # XMM3 = ((W[t-15]>>1)^W[t-15])>>6
+	mov	a_64, tmp0
+	ror	$5, tmp0 # 39
+	pxor	%xmm2, %xmm0	            # XMM0 = (((W[t-2]>>42)^W[t-2])>>13)^W[t-2]
+	xor	a_64, tmp0
+	ror	$6, tmp0 # 34
+	pxor	%xmm5, %xmm3                # XMM3 = (((W[t-15]>>1)^W[t-15])>>6)^W[t-15]
+	xor	a_64, tmp0
+	ror	$28, tmp0 # 28
+	psrlq	$6, %xmm0                   # XMM0 = ((((W[t-2]>>42)^W[t-2])>>13)^W[t-2])>>6
+	add	tmp0, T2
+	add	T1, d_64
+	psrlq	$1, %xmm3                   # XMM3 = (((W[t-15]>>1)^W[t-15])>>6)^W[t-15]>>1
+	lea	(T1, T2), h_64
+	RotateState
+	movdqa	%xmm2, %xmm1	            # XMM1 = W[t-2]
+	mov	f_64, T1
+	xor	g_64, T1
+	movdqa	%xmm5, %xmm4		    # XMM4 = W[t-15]
+	and	e_64, T1
+	xor	g_64, T1
+	psllq	$(64-19)-(64-61) , %xmm1    # XMM1 = W[t-2] << 42
+	idx = \rnd + 1
+	add	WK_2(idx), T1
+	mov	e_64, tmp0
+	psllq	$(64-1)-(64-8), %xmm4	    # XMM4 = W[t-15] << 7
+	ror	$23, tmp0 # 41
+	xor	e_64, tmp0
+	pxor	%xmm2, %xmm1		    # XMM1 = (W[t-2] << 42)^W[t-2]
+	ror	$4, tmp0 # 18
+	xor	e_64, tmp0
+	pxor	%xmm5, %xmm4		    # XMM4 = (W[t-15]<<7)^W[t-15]
+	ror	$14, tmp0 # 14
+	add	tmp0, T1
+	psllq	$(64-61), %xmm1		    # XMM1 = ((W[t-2] << 42)^W[t-2])<<3
+	add	h_64, T1
+	mov	a_64, T2
+	psllq	$(64-8), %xmm4		    # XMM4 = ((W[t-15]<<7)^W[t-15])<<56
+	xor	c_64, T2
+	and	b_64, T2
+	pxor	%xmm1, %xmm0		    # XMM0 = s1(W[t-2])
+	mov	a_64, tmp0
+	and	c_64, tmp0
+	idx = \rnd - 7
+	movdqu	W_t(idx), %xmm1		    # XMM1 = W[t-7]
+	xor	tmp0, T2
+	pxor	%xmm4, %xmm3                # XMM3 = s0(W[t-15])
+	mov	a_64, tmp0
+	paddq	%xmm3, %xmm0		    # XMM0 = s1(W[t-2]) + s0(W[t-15])
+	ror	$5, tmp0 # 39
+	idx =\rnd-16
+	paddq	W_t(idx), %xmm0		    # XMM0 = s1(W[t-2]) + s0(W[t-15]) + W[t-16]
+	xor	a_64, tmp0
+	paddq	%xmm1, %xmm0	            # XMM0 = s1(W[t-2]) + W[t-7] + s0(W[t-15]) + W[t-16]
+	ror	$6, tmp0 # 34
+	movdqa	%xmm0, W_t(\rnd)	    # Store scheduled qwords
+	xor	a_64, tmp0
+	paddq	K_t(\rnd), %xmm0	    # Compute W[t]+K[t]
+	ror	$28, tmp0 # 28
+	idx = \rnd
+	movdqa	%xmm0, WK_2(idx)	    # Store W[t]+K[t] for next rounds
+	add	tmp0, T2
+	add	T1, d_64
+	lea	(T1, T2), h_64
+	RotateState
+.endm
+
+########################################################################
+# void sha512_transform_ssse3(const void* M, void* D, u64 L)#
+# Purpose: Updates the SHA512 digest stored at D with the message stored in M.
+# The size of the message pointed to by M must be an integer multiple of SHA512
+#   message blocks.
+# L is the message length in SHA512 blocks.
+########################################################################
+ENTRY(sha512_transform_ssse3)
+
+	cmp $0, msglen
+	je nowork
+
+	# Allocate Stack Space
+	mov	%rsp, %rax
+	sub	$frame_size, %rsp
+	and	$~(0x20 - 1), %rsp
+	mov	%rax, frame_RSPSAVE(%rsp)
+
+	# Save GPRs
+	mov	%rbx, frame_GPRSAVE(%rsp)
+	mov	%r12, frame_GPRSAVE +8*1(%rsp)
+	mov	%r13, frame_GPRSAVE +8*2(%rsp)
+	mov	%r14, frame_GPRSAVE +8*3(%rsp)
+	mov	%r15, frame_GPRSAVE +8*4(%rsp)
+
+updateblock:
+
+# Load state variables
+	mov	DIGEST(0), a_64
+	mov	DIGEST(1), b_64
+	mov	DIGEST(2), c_64
+	mov	DIGEST(3), d_64
+	mov	DIGEST(4), e_64
+	mov	DIGEST(5), f_64
+	mov	DIGEST(6), g_64
+	mov	DIGEST(7), h_64
+
+	t = 0
+	.rept 80/2 + 1
+	# (80 rounds) / (2 rounds/iteration) + (1 iteration)
+	# +1 iteration because the scheduler leads hashing by 1 iteration
+		.if t < 2
+			# BSWAP 2 QWORDS
+			movdqa	XMM_QWORD_BSWAP(%rip), %xmm1
+			movdqu	MSG(t), %xmm0
+			pshufb	%xmm1, %xmm0	# BSWAP
+			movdqa	%xmm0, W_t(t)	# Store Scheduled Pair
+			paddq	K_t(t), %xmm0	# Compute W[t]+K[t]
+			movdqa	%xmm0, WK_2(t)	# Store into WK for rounds
+		.elseif t < 16
+			# BSWAP 2 QWORDS# Compute 2 Rounds
+			movdqu	MSG(t), %xmm0
+			pshufb	%xmm1, %xmm0	# BSWAP
+			SHA512_Round t-2	# Round t-2
+			movdqa	%xmm0, W_t(t)	# Store Scheduled Pair
+			paddq	K_t(t), %xmm0	# Compute W[t]+K[t]
+			SHA512_Round t-1	# Round t-1
+			movdqa	%xmm0, WK_2(t)	# Store W[t]+K[t] into WK
+		.elseif t < 79
+			# Schedule 2 QWORDS# Compute 2 Rounds
+			SHA512_2Sched_2Round_sse t
+		.else
+			# Compute 2 Rounds
+			SHA512_Round t-2
+			SHA512_Round t-1
+		.endif
+		t = t+2
+	.endr
+
+	# Update digest
+	add	a_64, DIGEST(0)
+	add	b_64, DIGEST(1)
+	add	c_64, DIGEST(2)
+	add	d_64, DIGEST(3)
+	add	e_64, DIGEST(4)
+	add	f_64, DIGEST(5)
+	add	g_64, DIGEST(6)
+	add	h_64, DIGEST(7)
+
+	# Advance to next message block
+	add	$16*8, msg
+	dec	msglen
+	jnz	updateblock
+
+	# Restore GPRs
+	mov	frame_GPRSAVE(%rsp),      %rbx
+	mov	frame_GPRSAVE +8*1(%rsp), %r12
+	mov	frame_GPRSAVE +8*2(%rsp), %r13
+	mov	frame_GPRSAVE +8*3(%rsp), %r14
+	mov	frame_GPRSAVE +8*4(%rsp), %r15
+
+	# Restore Stack Pointer
+	mov	frame_RSPSAVE(%rsp), %rsp
+
+nowork:
+	ret
+ENDPROC(sha512_transform_ssse3)
+
+########################################################################
+### Binary Data
+
+.data
+
+.align 16
+
+# Mask for byte-swapping a couple of qwords in an XMM register using (v)pshufb.
+XMM_QWORD_BSWAP:
+	.octa 0x08090a0b0c0d0e0f0001020304050607
+
+# K[t] used in SHA512 hashing
+K512:
+	.quad 0x428a2f98d728ae22,0x7137449123ef65cd
+	.quad 0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc
+	.quad 0x3956c25bf348b538,0x59f111f1b605d019
+	.quad 0x923f82a4af194f9b,0xab1c5ed5da6d8118
+	.quad 0xd807aa98a3030242,0x12835b0145706fbe
+	.quad 0x243185be4ee4b28c,0x550c7dc3d5ffb4e2
+	.quad 0x72be5d74f27b896f,0x80deb1fe3b1696b1
+	.quad 0x9bdc06a725c71235,0xc19bf174cf692694
+	.quad 0xe49b69c19ef14ad2,0xefbe4786384f25e3
+	.quad 0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65
+	.quad 0x2de92c6f592b0275,0x4a7484aa6ea6e483
+	.quad 0x5cb0a9dcbd41fbd4,0x76f988da831153b5
+	.quad 0x983e5152ee66dfab,0xa831c66d2db43210
+	.quad 0xb00327c898fb213f,0xbf597fc7beef0ee4
+	.quad 0xc6e00bf33da88fc2,0xd5a79147930aa725
+	.quad 0x06ca6351e003826f,0x142929670a0e6e70
+	.quad 0x27b70a8546d22ffc,0x2e1b21385c26c926
+	.quad 0x4d2c6dfc5ac42aed,0x53380d139d95b3df
+	.quad 0x650a73548baf63de,0x766a0abb3c77b2a8
+	.quad 0x81c2c92e47edaee6,0x92722c851482353b
+	.quad 0xa2bfe8a14cf10364,0xa81a664bbc423001
+	.quad 0xc24b8b70d0f89791,0xc76c51a30654be30
+	.quad 0xd192e819d6ef5218,0xd69906245565a910
+	.quad 0xf40e35855771202a,0x106aa07032bbd1b8
+	.quad 0x19a4c116b8d2d0c8,0x1e376c085141ab53
+	.quad 0x2748774cdf8eeb99,0x34b0bcb5e19b48a8
+	.quad 0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb
+	.quad 0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3
+	.quad 0x748f82ee5defb2fc,0x78a5636f43172f60
+	.quad 0x84c87814a1f0ab72,0x8cc702081a6439ec
+	.quad 0x90befffa23631e28,0xa4506cebde82bde9
+	.quad 0xbef9a3f7b2c67915,0xc67178f2e372532b
+	.quad 0xca273eceea26619c,0xd186b8c721c0c207
+	.quad 0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178
+	.quad 0x06f067aa72176fba,0x0a637dc5a2c898a6
+	.quad 0x113f9804bef90dae,0x1b710b35131c471b
+	.quad 0x28db77f523047d84,0x32caab7b40c72493
+	.quad 0x3c9ebe0a15c9bebc,0x431d67c49c100d4c
+	.quad 0x4cc5d4becb3e42b6,0x597f299cfc657e2a
+	.quad 0x5fcb6fab3ad6faec,0x6c44198c4a475817
diff --git a/arch/x86/crypto/sha512_ssse3_glue.c b/arch/x86/crypto/sha512_ssse3_glue.c
new file mode 100644
index 0000000..295f790
--- /dev/null
+++ b/arch/x86/crypto/sha512_ssse3_glue.c
@@ -0,0 +1,282 @@
+/*
+ * Cryptographic API.
+ *
+ * Glue code for the SHA512 Secure Hash Algorithm assembler
+ * implementation using supplemental SSE3 / AVX / AVX2 instructions.
+ *
+ * This file is based on sha512_generic.c
+ *
+ * Copyright (C) 2013 Intel Corporation
+ * Author: Tim Chen <tim.c.chen@linux.intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * 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 pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
+
+#include <crypto/internal/hash.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/cryptohash.h>
+#include <linux/types.h>
+#include <crypto/sha.h>
+#include <asm/byteorder.h>
+#include <asm/i387.h>
+#include <asm/xcr.h>
+#include <asm/xsave.h>
+
+#include <linux/string.h>
+
+asmlinkage void sha512_transform_ssse3(const char *data, u64 *digest,
+				     u64 rounds);
+#ifdef CONFIG_AS_AVX
+asmlinkage void sha512_transform_avx(const char *data, u64 *digest,
+				     u64 rounds);
+#endif
+#ifdef CONFIG_AS_AVX2
+asmlinkage void sha512_transform_rorx(const char *data, u64 *digest,
+				     u64 rounds);
+#endif
+
+asmlinkage void (*sha512_transform_asm)(const char *, u64 *, u64);
+
+
+static int sha512_ssse3_init(struct shash_desc *desc)
+{
+	struct sha512_state *sctx = shash_desc_ctx(desc);
+
+	sctx->state[0] = SHA512_H0;
+	sctx->state[1] = SHA512_H1;
+	sctx->state[2] = SHA512_H2;
+	sctx->state[3] = SHA512_H3;
+	sctx->state[4] = SHA512_H4;
+	sctx->state[5] = SHA512_H5;
+	sctx->state[6] = SHA512_H6;
+	sctx->state[7] = SHA512_H7;
+	sctx->count[0] = sctx->count[1] = 0;
+
+	return 0;
+}
+
+static int __sha512_ssse3_update(struct shash_desc *desc, const u8 *data,
+			       unsigned int len, unsigned int partial)
+{
+	struct sha512_state *sctx = shash_desc_ctx(desc);
+	unsigned int done = 0;
+
+	sctx->count[0] += len;
+	if (sctx->count[0] < len)
+		sctx->count[1]++;
+
+	if (partial) {
+		done = SHA512_BLOCK_SIZE - partial;
+		memcpy(sctx->buf + partial, data, done);
+		sha512_transform_asm(sctx->buf, sctx->state, 1);
+	}
+
+	if (len - done >= SHA512_BLOCK_SIZE) {
+		const unsigned int rounds = (len - done) / SHA512_BLOCK_SIZE;
+
+		sha512_transform_asm(data + done, sctx->state, (u64) rounds);
+
+		done += rounds * SHA512_BLOCK_SIZE;
+	}
+
+	memcpy(sctx->buf, data + done, len - done);
+
+	return 0;
+}
+
+static int sha512_ssse3_update(struct shash_desc *desc, const u8 *data,
+			     unsigned int len)
+{
+	struct sha512_state *sctx = shash_desc_ctx(desc);
+	unsigned int partial = sctx->count[0] % SHA512_BLOCK_SIZE;
+	int res;
+
+	/* Handle the fast case right here */
+	if (partial + len < SHA512_BLOCK_SIZE) {
+		sctx->count[0] += len;
+		if (sctx->count[0] < len)
+			sctx->count[1]++;
+		memcpy(sctx->buf + partial, data, len);
+
+		return 0;
+	}
+
+	if (!irq_fpu_usable()) {
+		res = crypto_sha512_update(desc, data, len);
+	} else {
+		kernel_fpu_begin();
+		res = __sha512_ssse3_update(desc, data, len, partial);
+		kernel_fpu_end();
+	}
+
+	return res;
+}
+
+
+/* Add padding and return the message digest. */
+static int sha512_ssse3_final(struct shash_desc *desc, u8 *out)
+{
+	struct sha512_state *sctx = shash_desc_ctx(desc);
+	unsigned int i, index, padlen;
+	__be64 *dst = (__be64 *)out;
+	__be64 bits[2];
+	static const u8 padding[SHA512_BLOCK_SIZE] = { 0x80, };
+
+	/* save number of bits */
+	bits[1] = cpu_to_be64(sctx->count[0] << 3);
+	bits[0] = cpu_to_be64(sctx->count[1] << 3) | sctx->count[0] >> 61;
+
+	/* Pad out to 112 mod 128 and append length */
+	index = sctx->count[0] & 0x7f;
+	padlen = (index < 112) ? (112 - index) : ((128+112) - index);
+
+	if (!irq_fpu_usable()) {
+		crypto_sha512_update(desc, padding, padlen);
+		crypto_sha512_update(desc, (const u8 *)&bits, sizeof(bits));
+	} else {
+		kernel_fpu_begin();
+		/* We need to fill a whole block for __sha512_ssse3_update() */
+		if (padlen <= 112) {
+			sctx->count[0] += padlen;
+			if (sctx->count[0] < padlen)
+				sctx->count[1]++;
+			memcpy(sctx->buf + index, padding, padlen);
+		} else {
+			__sha512_ssse3_update(desc, padding, padlen, index);
+		}
+		__sha512_ssse3_update(desc, (const u8 *)&bits,
+					sizeof(bits), 112);
+		kernel_fpu_end();
+	}
+
+	/* Store state in digest */
+	for (i = 0; i < 8; i++)
+		dst[i] = cpu_to_be64(sctx->state[i]);
+
+	/* Wipe context */
+	memset(sctx, 0, sizeof(*sctx));
+
+	return 0;
+}
+
+static int sha512_ssse3_export(struct shash_desc *desc, void *out)
+{
+	struct sha512_state *sctx = shash_desc_ctx(desc);
+
+	memcpy(out, sctx, sizeof(*sctx));
+
+	return 0;
+}
+
+static int sha512_ssse3_import(struct shash_desc *desc, const void *in)
+{
+	struct sha512_state *sctx = shash_desc_ctx(desc);
+
+	memcpy(sctx, in, sizeof(*sctx));
+
+	return 0;
+}
+
+static struct shash_alg alg = {
+	.digestsize	=	SHA512_DIGEST_SIZE,
+	.init		=	sha512_ssse3_init,
+	.update		=	sha512_ssse3_update,
+	.final		=	sha512_ssse3_final,
+	.export		=	sha512_ssse3_export,
+	.import		=	sha512_ssse3_import,
+	.descsize	=	sizeof(struct sha512_state),
+	.statesize	=	sizeof(struct sha512_state),
+	.base		=	{
+		.cra_name	=	"sha512",
+		.cra_driver_name =	"sha512-ssse3",
+		.cra_priority	=	150,
+		.cra_flags	=	CRYPTO_ALG_TYPE_SHASH,
+		.cra_blocksize	=	SHA512_BLOCK_SIZE,
+		.cra_module	=	THIS_MODULE,
+	}
+};
+
+#ifdef CONFIG_AS_AVX
+static bool __init avx_usable(void)
+{
+	u64 xcr0;
+
+	if (!cpu_has_avx || !cpu_has_osxsave)
+		return false;
+
+	xcr0 = xgetbv(XCR_XFEATURE_ENABLED_MASK);
+	if ((xcr0 & (XSTATE_SSE | XSTATE_YMM)) != (XSTATE_SSE | XSTATE_YMM)) {
+		pr_info("AVX detected but unusable.\n");
+
+		return false;
+	}
+
+	return true;
+}
+#endif
+
+static int __init sha512_ssse3_mod_init(void)
+{
+	/* test for SSE3 first */
+	if (cpu_has_ssse3)
+		sha512_transform_asm = sha512_transform_ssse3;
+
+#ifdef CONFIG_AS_AVX
+	/* allow AVX to override SSSE3, it's a little faster */
+	if (avx_usable()) {
+#ifdef CONFIG_AS_AVX2
+		if (boot_cpu_has(X86_FEATURE_AVX2))
+			sha512_transform_asm = sha512_transform_rorx;
+		else
+#endif
+			sha512_transform_asm = sha512_transform_avx;
+	}
+#endif
+
+	if (sha512_transform_asm) {
+#ifdef CONFIG_AS_AVX
+		if (sha512_transform_asm == sha512_transform_avx)
+			pr_info("Using AVX optimized SHA-512 implementation\n");
+#ifdef CONFIG_AS_AVX2
+		else if (sha512_transform_asm == sha512_transform_rorx)
+			pr_info("Using AVX2 optimized SHA-512 implementation\n");
+#endif
+		else
+#endif
+			pr_info("Using SSSE3 optimized SHA-512 implementation\n");
+		return crypto_register_shash(&alg);
+	}
+	pr_info("Neither AVX nor SSSE3 is available/usable.\n");
+
+	return -ENODEV;
+}
+
+static void __exit sha512_ssse3_mod_fini(void)
+{
+	crypto_unregister_shash(&alg);
+}
+
+module_init(sha512_ssse3_mod_init);
+module_exit(sha512_ssse3_mod_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("SHA512 Secure Hash Algorithm, Supplemental SSE3 accelerated");
+
+MODULE_ALIAS("sha512");
diff --git a/arch/x86/ia32/Makefile b/arch/x86/ia32/Makefile
index 455646e..e785b42 100644
--- a/arch/x86/ia32/Makefile
+++ b/arch/x86/ia32/Makefile
@@ -5,9 +5,6 @@
 obj-$(CONFIG_IA32_EMULATION) := ia32entry.o sys_ia32.o ia32_signal.o
 obj-$(CONFIG_IA32_EMULATION) += nosyscall.o syscall_ia32.o
 
-sysv-$(CONFIG_SYSVIPC) := ipc32.o
-obj-$(CONFIG_IA32_EMULATION) += $(sysv-y)
-
 obj-$(CONFIG_IA32_AOUT) += ia32_aout.o
 
 audit-class-$(CONFIG_AUDIT) := audit.o
diff --git a/arch/x86/ia32/ia32_aout.c b/arch/x86/ia32/ia32_aout.c
index 03abf9b..0f9a472 100644
--- a/arch/x86/ia32/ia32_aout.c
+++ b/arch/x86/ia32/ia32_aout.c
@@ -162,7 +162,6 @@ static int aout_core_dump(long signr, struct pt_regs *regs, struct file *file,
 	fs = get_fs();
 	set_fs(KERNEL_DS);
 	has_dumped = 1;
-	current->flags |= PF_DUMPCORE;
 	strncpy(dump.u_comm, current->comm, sizeof(current->comm));
 	dump.u_ar0 = offsetof(struct user32, regs);
 	dump.signal = signr;
@@ -309,8 +308,6 @@ static int load_aout_binary(struct linux_binprm *bprm)
 		(current->mm->start_data = N_DATADDR(ex));
 	current->mm->brk = ex.a_bss +
 		(current->mm->start_brk = N_BSSADDR(ex));
-	current->mm->free_area_cache = TASK_UNMAPPED_BASE;
-	current->mm->cached_hole_size = 0;
 
 	retval = setup_arg_pages(bprm, IA32_STACK_TOP, EXSTACK_DEFAULT);
 	if (retval < 0) {
diff --git a/arch/x86/ia32/ipc32.c b/arch/x86/ia32/ipc32.c
deleted file mode 100644
index 29cdcd0..0000000
--- a/arch/x86/ia32/ipc32.c
+++ /dev/null
@@ -1,54 +0,0 @@
-#include <linux/kernel.h>
-#include <linux/spinlock.h>
-#include <linux/list.h>
-#include <linux/syscalls.h>
-#include <linux/time.h>
-#include <linux/sem.h>
-#include <linux/msg.h>
-#include <linux/shm.h>
-#include <linux/ipc.h>
-#include <linux/compat.h>
-#include <asm/sys_ia32.h>
-
-asmlinkage long sys32_ipc(u32 call, int first, int second, int third,
-			  compat_uptr_t ptr, u32 fifth)
-{
-	int version;
-
-	version = call >> 16; /* hack for backward compatibility */
-	call &= 0xffff;
-
-	switch (call) {
-	case SEMOP:
-		/* struct sembuf is the same on 32 and 64bit :)) */
-		return sys_semtimedop(first, compat_ptr(ptr), second, NULL);
-	case SEMTIMEDOP:
-		return compat_sys_semtimedop(first, compat_ptr(ptr), second,
-						compat_ptr(fifth));
-	case SEMGET:
-		return sys_semget(first, second, third);
-	case SEMCTL:
-		return compat_sys_semctl(first, second, third, compat_ptr(ptr));
-
-	case MSGSND:
-		return compat_sys_msgsnd(first, second, third, compat_ptr(ptr));
-	case MSGRCV:
-		return compat_sys_msgrcv(first, second, fifth, third,
-					 version, compat_ptr(ptr));
-	case MSGGET:
-		return sys_msgget((key_t) first, second);
-	case MSGCTL:
-		return compat_sys_msgctl(first, second, compat_ptr(ptr));
-
-	case SHMAT:
-		return compat_sys_shmat(first, second, third, version,
-					compat_ptr(ptr));
-	case SHMDT:
-		return sys_shmdt(compat_ptr(ptr));
-	case SHMGET:
-		return sys_shmget(first, (unsigned)second, third);
-	case SHMCTL:
-		return compat_sys_shmctl(first, second, compat_ptr(ptr));
-	}
-	return -ENOSYS;
-}
diff --git a/arch/x86/ia32/sys_ia32.c b/arch/x86/ia32/sys_ia32.c
index ad7a20c..4e4907c 100644
--- a/arch/x86/ia32/sys_ia32.c
+++ b/arch/x86/ia32/sys_ia32.c
@@ -166,12 +166,6 @@ asmlinkage long sys32_mmap(struct mmap_arg_struct32 __user *arg)
 			       a.offset>>PAGE_SHIFT);
 }
 
-asmlinkage long sys32_mprotect(unsigned long start, size_t len,
-			       unsigned long prot)
-{
-	return sys_mprotect(start, len, prot);
-}
-
 asmlinkage long sys32_waitpid(compat_pid_t pid, unsigned int __user *stat_addr,
 			      int options)
 {
@@ -194,35 +188,10 @@ asmlinkage long sys32_pwrite(unsigned int fd, const char __user *ubuf,
 }
 
 
-asmlinkage long sys32_sendfile(int out_fd, int in_fd,
-			       compat_off_t __user *offset, s32 count)
-{
-	mm_segment_t old_fs = get_fs();
-	int ret;
-	off_t of;
-
-	if (offset && get_user(of, offset))
-		return -EFAULT;
-
-	set_fs(KERNEL_DS);
-	ret = sys_sendfile(out_fd, in_fd, offset ? (off_t __user *)&of : NULL,
-			   count);
-	set_fs(old_fs);
-
-	if (offset && put_user(of, offset))
-		return -EFAULT;
-	return ret;
-}
-
 /*
  * Some system calls that need sign extended arguments. This could be
  * done by a generic wrapper.
  */
-long sys32_kill(int pid, int sig)
-{
-	return sys_kill(pid, sig);
-}
-
 long sys32_fadvise64_64(int fd, __u32 offset_low, __u32 offset_high,
 			__u32 len_low, __u32 len_high, int advice)
 {
@@ -246,12 +215,6 @@ long sys32_vm86_warning(void)
 	return -ENOSYS;
 }
 
-long sys32_lookup_dcookie(u32 addr_low, u32 addr_high,
-			  char __user *buf, size_t len)
-{
-	return sys_lookup_dcookie(((u64)addr_high << 32) | addr_low, buf, len);
-}
-
 asmlinkage ssize_t sys32_readahead(int fd, unsigned off_lo, unsigned off_hi,
 				   size_t count)
 {
diff --git a/arch/x86/include/asm/context_tracking.h b/arch/x86/include/asm/context_tracking.h
index 1616562..1fe4970 100644
--- a/arch/x86/include/asm/context_tracking.h
+++ b/arch/x86/include/asm/context_tracking.h
@@ -1,31 +1,10 @@
 #ifndef _ASM_X86_CONTEXT_TRACKING_H
 #define _ASM_X86_CONTEXT_TRACKING_H
 
-#ifndef __ASSEMBLY__
-#include <linux/context_tracking.h>
-#include <asm/ptrace.h>
-
-static inline void exception_enter(struct pt_regs *regs)
-{
-	user_exit();
-}
-
-static inline void exception_exit(struct pt_regs *regs)
-{
-#ifdef CONFIG_CONTEXT_TRACKING
-	if (user_mode(regs))
-		user_enter();
-#endif
-}
-
-#else /* __ASSEMBLY__ */
-
 #ifdef CONFIG_CONTEXT_TRACKING
 # define SCHEDULE_USER call schedule_user
 #else
 # define SCHEDULE_USER call schedule
 #endif
 
-#endif /* !__ASSEMBLY__ */
-
 #endif
diff --git a/arch/x86/include/asm/e820.h b/arch/x86/include/asm/e820.h
index cccd07f..b8e9224 100644
--- a/arch/x86/include/asm/e820.h
+++ b/arch/x86/include/asm/e820.h
@@ -17,6 +17,8 @@ extern unsigned long pci_mem_start;
 extern int e820_any_mapped(u64 start, u64 end, unsigned type);
 extern int e820_all_mapped(u64 start, u64 end, unsigned type);
 extern void e820_add_region(u64 start, u64 size, int type);
+extern void e820_add_limit_region(u64 start, u64 size, int type);
+extern void e820_adjust_region(u64 *start, u64 *size);
 extern void e820_print_map(char *who);
 extern int
 sanitize_e820_map(struct e820entry *biosmap, int max_nr_map, u32 *pnr_map);
diff --git a/arch/x86/include/asm/hugetlb.h b/arch/x86/include/asm/hugetlb.h
index bdd35db..a809121 100644
--- a/arch/x86/include/asm/hugetlb.h
+++ b/arch/x86/include/asm/hugetlb.h
@@ -2,6 +2,7 @@
 #define _ASM_X86_HUGETLB_H
 
 #include <asm/page.h>
+#include <asm-generic/hugetlb.h>
 
 
 static inline int is_hugepage_only_range(struct mm_struct *mm,
diff --git a/arch/x86/include/asm/hypervisor.h b/arch/x86/include/asm/hypervisor.h
index 86095ed..2d4b5e6 100644
--- a/arch/x86/include/asm/hypervisor.h
+++ b/arch/x86/include/asm/hypervisor.h
@@ -20,13 +20,11 @@
 #ifndef _ASM_X86_HYPERVISOR_H
 #define _ASM_X86_HYPERVISOR_H
 
+#ifdef CONFIG_HYPERVISOR_GUEST
+
 #include <asm/kvm_para.h>
 #include <asm/xen/hypervisor.h>
 
-extern void init_hypervisor(struct cpuinfo_x86 *c);
-extern void init_hypervisor_platform(void);
-extern bool hypervisor_x2apic_available(void);
-
 /*
  * x86 hypervisor information
  */
@@ -55,4 +53,12 @@ extern const struct hypervisor_x86 x86_hyper_ms_hyperv;
 extern const struct hypervisor_x86 x86_hyper_xen_hvm;
 extern const struct hypervisor_x86 x86_hyper_kvm;
 
-#endif
+extern void init_hypervisor(struct cpuinfo_x86 *c);
+extern void init_hypervisor_platform(void);
+extern bool hypervisor_x2apic_available(void);
+#else
+static inline void init_hypervisor(struct cpuinfo_x86 *c) { }
+static inline void init_hypervisor_platform(void) { }
+static inline bool hypervisor_x2apic_available(void) { return false; }
+#endif /* CONFIG_HYPERVISOR_GUEST */
+#endif /* _ASM_X86_HYPERVISOR_H */
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 4979778..b5a6462 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -230,6 +230,7 @@ struct kvm_mmu_page {
 #endif
 
 	int write_flooding_count;
+	bool mmio_cached;
 };
 
 struct kvm_pio_request {
@@ -345,7 +346,6 @@ struct kvm_vcpu_arch {
 	unsigned long apic_attention;
 	int32_t apic_arb_prio;
 	int mp_state;
-	int sipi_vector;
 	u64 ia32_misc_enable_msr;
 	bool tpr_access_reporting;
 
@@ -643,7 +643,7 @@ struct kvm_x86_ops {
 	/* Create, but do not attach this VCPU */
 	struct kvm_vcpu *(*vcpu_create)(struct kvm *kvm, unsigned id);
 	void (*vcpu_free)(struct kvm_vcpu *vcpu);
-	int (*vcpu_reset)(struct kvm_vcpu *vcpu);
+	void (*vcpu_reset)(struct kvm_vcpu *vcpu);
 
 	void (*prepare_guest_switch)(struct kvm_vcpu *vcpu);
 	void (*vcpu_load)(struct kvm_vcpu *vcpu, int cpu);
@@ -767,6 +767,7 @@ void kvm_mmu_write_protect_pt_masked(struct kvm *kvm,
 				     struct kvm_memory_slot *slot,
 				     gfn_t gfn_offset, unsigned long mask);
 void kvm_mmu_zap_all(struct kvm *kvm);
+void kvm_mmu_zap_mmio_sptes(struct kvm *kvm);
 unsigned int kvm_mmu_calculate_mmu_pages(struct kvm *kvm);
 void kvm_mmu_change_mmu_pages(struct kvm *kvm, unsigned int kvm_nr_mmu_pages);
 
@@ -819,6 +820,7 @@ int kvm_emulate_wbinvd(struct kvm_vcpu *vcpu);
 
 void kvm_get_segment(struct kvm_vcpu *vcpu, struct kvm_segment *var, int seg);
 int kvm_load_segment_descriptor(struct kvm_vcpu *vcpu, u16 selector, int seg);
+void kvm_vcpu_deliver_sipi_vector(struct kvm_vcpu *vcpu, unsigned int vector);
 
 int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int idt_index,
 		    int reason, bool has_error_code, u32 error_code);
@@ -1002,6 +1004,7 @@ int kvm_cpu_has_injectable_intr(struct kvm_vcpu *v);
 int kvm_cpu_has_interrupt(struct kvm_vcpu *vcpu);
 int kvm_arch_interrupt_allowed(struct kvm_vcpu *vcpu);
 int kvm_cpu_get_interrupt(struct kvm_vcpu *v);
+void kvm_vcpu_reset(struct kvm_vcpu *vcpu);
 
 void kvm_define_shared_msr(unsigned index, u32 msr);
 void kvm_set_shared_msr(unsigned index, u64 val, u64 mask);
diff --git a/arch/x86/include/asm/sys_ia32.h b/arch/x86/include/asm/sys_ia32.h
index 8459efc..0ef202e 100644
--- a/arch/x86/include/asm/sys_ia32.h
+++ b/arch/x86/include/asm/sys_ia32.h
@@ -30,23 +30,14 @@ asmlinkage long sys32_fstatat(unsigned int, const char __user *,
 			      struct stat64 __user *, int);
 struct mmap_arg_struct32;
 asmlinkage long sys32_mmap(struct mmap_arg_struct32 __user *);
-asmlinkage long sys32_mprotect(unsigned long, size_t, unsigned long);
-
-asmlinkage long sys32_alarm(unsigned int);
 
 asmlinkage long sys32_waitpid(compat_pid_t, unsigned int __user *, int);
-asmlinkage long sys32_sysfs(int, u32, u32);
 
 asmlinkage long sys32_pread(unsigned int, char __user *, u32, u32, u32);
 asmlinkage long sys32_pwrite(unsigned int, const char __user *, u32, u32, u32);
 
-asmlinkage long sys32_personality(unsigned long);
-asmlinkage long sys32_sendfile(int, int, compat_off_t __user *, s32);
-
-long sys32_kill(int, int);
 long sys32_fadvise64_64(int, __u32, __u32, __u32, __u32, int);
 long sys32_vm86_warning(void);
-long sys32_lookup_dcookie(u32, u32, char __user *, size_t);
 
 asmlinkage ssize_t sys32_readahead(int, unsigned, unsigned, size_t);
 asmlinkage long sys32_sync_file_range(int, unsigned, unsigned,
@@ -59,9 +50,6 @@ asmlinkage long sys32_fallocate(int, int, unsigned,
 asmlinkage long sys32_sigreturn(void);
 asmlinkage long sys32_rt_sigreturn(void);
 
-/* ia32/ipc32.c */
-asmlinkage long sys32_ipc(u32, int, int, int, compat_uptr_t, u32);
-
 asmlinkage long sys32_fanotify_mark(int, unsigned int, u32, u32, int,
 				    const char __user *);
 
diff --git a/arch/x86/include/asm/syscalls.h b/arch/x86/include/asm/syscalls.h
index 6cf0a9c..5f87b35 100644
--- a/arch/x86/include/asm/syscalls.h
+++ b/arch/x86/include/asm/syscalls.h
@@ -27,8 +27,8 @@ asmlinkage int sys_modify_ldt(int, void __user *, unsigned long);
 long sys_rt_sigreturn(void);
 
 /* kernel/tls.c */
-asmlinkage int sys_set_thread_area(struct user_desc __user *);
-asmlinkage int sys_get_thread_area(struct user_desc __user *);
+asmlinkage long sys_set_thread_area(struct user_desc __user *);
+asmlinkage long sys_get_thread_area(struct user_desc __user *);
 
 /* X86_32 only */
 #ifdef CONFIG_X86_32
diff --git a/arch/x86/include/asm/unistd.h b/arch/x86/include/asm/unistd.h
index 3d5df1c..c2a4813 100644
--- a/arch/x86/include/asm/unistd.h
+++ b/arch/x86/include/asm/unistd.h
@@ -50,12 +50,4 @@
 # define __ARCH_WANT_SYS_VFORK
 # define __ARCH_WANT_SYS_CLONE
 
-/*
- * "Conditional" syscalls
- *
- * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
- * but it doesn't work on all toolchains, so we just do it by hand
- */
-# define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
-
 #endif /* _ASM_X86_UNISTD_H */
diff --git a/arch/x86/include/asm/vmx.h b/arch/x86/include/asm/vmx.h
index b6fbf86..fc1c313 100644
--- a/arch/x86/include/asm/vmx.h
+++ b/arch/x86/include/asm/vmx.h
@@ -70,6 +70,9 @@
 #define PIN_BASED_EXT_INTR_MASK                 0x00000001
 #define PIN_BASED_NMI_EXITING                   0x00000008
 #define PIN_BASED_VIRTUAL_NMIS                  0x00000020
+#define PIN_BASED_VMX_PREEMPTION_TIMER          0x00000040
+
+#define PIN_BASED_ALWAYSON_WITHOUT_TRUE_MSR	0x00000016
 
 #define VM_EXIT_SAVE_DEBUG_CONTROLS             0x00000002
 #define VM_EXIT_HOST_ADDR_SPACE_SIZE            0x00000200
@@ -81,6 +84,8 @@
 #define VM_EXIT_LOAD_IA32_EFER                  0x00200000
 #define VM_EXIT_SAVE_VMX_PREEMPTION_TIMER       0x00400000
 
+#define VM_EXIT_ALWAYSON_WITHOUT_TRUE_MSR	0x00036dff
+
 #define VM_ENTRY_LOAD_DEBUG_CONTROLS            0x00000002
 #define VM_ENTRY_IA32E_MODE                     0x00000200
 #define VM_ENTRY_SMM                            0x00000400
@@ -89,6 +94,11 @@
 #define VM_ENTRY_LOAD_IA32_PAT			0x00004000
 #define VM_ENTRY_LOAD_IA32_EFER                 0x00008000
 
+#define VM_ENTRY_ALWAYSON_WITHOUT_TRUE_MSR	0x000011ff
+
+#define VMX_MISC_PREEMPTION_TIMER_RATE_MASK	0x0000001f
+#define VMX_MISC_SAVE_EFER_LMA			0x00000020
+
 /* VMCS Encodings */
 enum vmcs_field {
 	VIRTUAL_PROCESSOR_ID            = 0x00000000,
@@ -209,6 +219,7 @@ enum vmcs_field {
 	GUEST_INTERRUPTIBILITY_INFO     = 0x00004824,
 	GUEST_ACTIVITY_STATE            = 0X00004826,
 	GUEST_SYSENTER_CS               = 0x0000482A,
+	VMX_PREEMPTION_TIMER_VALUE      = 0x0000482E,
 	HOST_IA32_SYSENTER_CS           = 0x00004c00,
 	CR0_GUEST_HOST_MASK             = 0x00006000,
 	CR4_GUEST_HOST_MASK             = 0x00006002,
diff --git a/arch/x86/include/asm/xen/interface.h b/arch/x86/include/asm/xen/interface.h
index fd9cb76..20e738a 100644
--- a/arch/x86/include/asm/xen/interface.h
+++ b/arch/x86/include/asm/xen/interface.h
@@ -145,7 +145,16 @@ struct vcpu_guest_context {
     struct cpu_user_regs user_regs;         /* User-level CPU registers     */
     struct trap_info trap_ctxt[256];        /* Virtual IDT                  */
     unsigned long ldt_base, ldt_ents;       /* LDT (linear address, # ents) */
-    unsigned long gdt_frames[16], gdt_ents; /* GDT (machine frames, # ents) */
+    union {
+	struct {
+		/* PV: GDT (machine frames, # ents).*/
+		unsigned long gdt_frames[16], gdt_ents;
+	} pv;
+	struct {
+		/* PVH: GDTR addr and size */
+		unsigned long gdtaddr, gdtsz;
+	} pvh;
+    } u;
     unsigned long kernel_ss, kernel_sp;     /* Virtual TSS (only SS1/SP1)   */
     /* NB. User pagetable on x86/64 is placed in ctrlreg[1]. */
     unsigned long ctrlreg[8];               /* CR0-CR7 (control registers)  */
diff --git a/arch/x86/include/asm/xen/page.h b/arch/x86/include/asm/xen/page.h
index 6aef9fb..3143a8a 100644
--- a/arch/x86/include/asm/xen/page.h
+++ b/arch/x86/include/asm/xen/page.h
@@ -159,6 +159,9 @@ static inline xpaddr_t machine_to_phys(xmaddr_t machine)
 static inline unsigned long mfn_to_local_pfn(unsigned long mfn)
 {
 	unsigned long pfn = mfn_to_pfn(mfn);
+
+	if (xen_feature(XENFEAT_auto_translated_physmap))
+		return mfn;
 	if (get_phys_to_machine(pfn) != mfn)
 		return -1; /* force !pfn_valid() */
 	return pfn;
diff --git a/arch/x86/include/uapi/asm/vmx.h b/arch/x86/include/uapi/asm/vmx.h
index 2871fcc..d651082 100644
--- a/arch/x86/include/uapi/asm/vmx.h
+++ b/arch/x86/include/uapi/asm/vmx.h
@@ -65,6 +65,7 @@
 #define EXIT_REASON_EOI_INDUCED         45
 #define EXIT_REASON_EPT_VIOLATION       48
 #define EXIT_REASON_EPT_MISCONFIG       49
+#define EXIT_REASON_PREEMPTION_TIMER    52
 #define EXIT_REASON_WBINVD              54
 #define EXIT_REASON_XSETBV              55
 #define EXIT_REASON_APIC_WRITE          56
@@ -110,7 +111,7 @@
 	{ EXIT_REASON_EOI_INDUCED,           "EOI_INDUCED" }, \
 	{ EXIT_REASON_INVALID_STATE,         "INVALID_STATE" }, \
 	{ EXIT_REASON_INVD,                  "INVD" }, \
-	{ EXIT_REASON_INVPCID,               "INVPCID" }
-
+	{ EXIT_REASON_INVPCID,               "INVPCID" }, \
+	{ EXIT_REASON_PREEMPTION_TIMER,      "PREEMPTION_TIMER" }
 
 #endif /* _UAPIVMX_H */
diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile
index a0e067d..895f62e 100644
--- a/arch/x86/kernel/cpu/Makefile
+++ b/arch/x86/kernel/cpu/Makefile
@@ -14,7 +14,6 @@ CFLAGS_common.o		:= $(nostackp)
 
 obj-y			:= intel_cacheinfo.o scattered.o topology.o
 obj-y			+= proc.o capflags.o powerflags.o common.o
-obj-y			+= vmware.o hypervisor.o mshyperv.o
 obj-y			+= rdrand.o
 obj-y			+= match.o
 
@@ -42,11 +41,13 @@ obj-$(CONFIG_MTRR)			+= mtrr/
 
 obj-$(CONFIG_X86_LOCAL_APIC)		+= perfctr-watchdog.o perf_event_amd_ibs.o
 
+obj-$(CONFIG_HYPERVISOR_GUEST)		+= vmware.o hypervisor.o mshyperv.o
+
 quiet_cmd_mkcapflags = MKCAP   $@
-      cmd_mkcapflags = $(PERL) $(srctree)/$(src)/mkcapflags.pl $< $@
+      cmd_mkcapflags = $(CONFIG_SHELL) $(srctree)/$(src)/mkcapflags.sh $< $@
 
 cpufeature = $(src)/../../include/asm/cpufeature.h
 
 targets += capflags.c
-$(obj)/capflags.c: $(cpufeature) $(src)/mkcapflags.pl FORCE
+$(obj)/capflags.c: $(cpufeature) $(src)/mkcapflags.sh FORCE
 	$(call if_changed,mkcapflags)
diff --git a/arch/x86/kernel/cpu/mkcapflags.pl b/arch/x86/kernel/cpu/mkcapflags.pl
deleted file mode 100644
index 091972e..0000000
--- a/arch/x86/kernel/cpu/mkcapflags.pl
+++ /dev/null
@@ -1,48 +0,0 @@
-#!/usr/bin/perl -w
-#
-# Generate the x86_cap_flags[] array from include/asm-x86/cpufeature.h
-#
-
-($in, $out) = @ARGV;
-
-open(IN, "< $in\0")   or die "$0: cannot open: $in: $!\n";
-open(OUT, "> $out\0") or die "$0: cannot create: $out: $!\n";
-
-print OUT "#ifndef _ASM_X86_CPUFEATURE_H\n";
-print OUT "#include <asm/cpufeature.h>\n";
-print OUT "#endif\n";
-print OUT "\n";
-print OUT "const char * const x86_cap_flags[NCAPINTS*32] = {\n";
-
-%features = ();
-$err = 0;
-
-while (defined($line = <IN>)) {
-	if ($line =~ /^\s*\#\s*define\s+(X86_FEATURE_(\S+))\s+(.*)$/) {
-		$macro = $1;
-		$feature = "\L$2";
-		$tail = $3;
-		if ($tail =~ /\/\*\s*\"([^"]*)\".*\*\//) {
-			$feature = "\L$1";
-		}
-
-		next if ($feature eq '');
-
-		if ($features{$feature}++) {
-			print STDERR "$in: duplicate feature name: $feature\n";
-			$err++;
-		}
-		printf OUT "\t%-32s = \"%s\",\n", "[$macro]", $feature;
-	}
-}
-print OUT "};\n";
-
-close(IN);
-close(OUT);
-
-if ($err) {
-	unlink($out);
-	exit(1);
-}
-
-exit(0);
diff --git a/arch/x86/kernel/cpu/mkcapflags.sh b/arch/x86/kernel/cpu/mkcapflags.sh
new file mode 100644
index 0000000..2bf6165
--- /dev/null
+++ b/arch/x86/kernel/cpu/mkcapflags.sh
@@ -0,0 +1,41 @@
+#!/bin/sh
+#
+# Generate the x86_cap_flags[] array from include/asm/cpufeature.h
+#
+
+IN=$1
+OUT=$2
+
+TABS="$(printf '\t\t\t\t\t')"
+trap 'rm "$OUT"' EXIT
+
+(
+	echo "#ifndef _ASM_X86_CPUFEATURE_H"
+	echo "#include <asm/cpufeature.h>"
+	echo "#endif"
+	echo ""
+	echo "const char * const x86_cap_flags[NCAPINTS*32] = {"
+
+	# Iterate through any input lines starting with #define X86_FEATURE_
+	sed -n -e 's/\t/ /g' -e 's/^ *# *define *X86_FEATURE_//p' $IN |
+	while read i
+	do
+		# Name is everything up to the first whitespace
+		NAME="$(echo "$i" | sed 's/ .*//')"
+
+		# If the /* comment */ starts with a quote string, grab that.
+		VALUE="$(echo "$i" | sed -n 's@.*/\* *\("[^"]*"\).*\*/@\1@p')"
+		[ -z "$VALUE" ] && VALUE="\"$NAME\""
+		[ "$VALUE" == '""' ] && continue
+
+		# Name is uppercase, VALUE is all lowercase
+		VALUE="$(echo "$VALUE" | tr A-Z a-z)"
+
+		TABCOUNT=$(( ( 5*8 - 14 - $(echo "$NAME" | wc -c) ) / 8 ))
+		printf "\t[%s]%.*s = %s,\n" \
+			"X86_FEATURE_$NAME" "$TABCOUNT" "$TABS" "$VALUE"
+	done
+	echo "};"
+) > $OUT
+
+trap - EXIT
diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c
index d32abea..0d5bb68 100644
--- a/arch/x86/kernel/e820.c
+++ b/arch/x86/kernel/e820.c
@@ -47,6 +47,7 @@ unsigned long pci_mem_start = 0xaeedbabe;
 #ifdef CONFIG_PCI
 EXPORT_SYMBOL(pci_mem_start);
 #endif
+static u64 mem_limit = ~0ULL;
 
 /*
  * This function checks if any part of the range <start,end> is mapped
@@ -108,7 +109,7 @@ int __init e820_all_mapped(u64 start, u64 end, unsigned type)
  * Add a memory region to the kernel e820 map.
  */
 static void __init __e820_add_region(struct e820map *e820x, u64 start, u64 size,
-					 int type)
+					 int type, bool limited)
 {
 	int x = e820x->nr_map;
 
@@ -119,6 +120,22 @@ static void __init __e820_add_region(struct e820map *e820x, u64 start, u64 size,
 		return;
 	}
 
+	if (limited) {
+		if (start >= mem_limit) {
+			printk(KERN_ERR "e820: ignoring [mem %#010llx-%#010llx]\n",
+			       (unsigned long long)start,
+			       (unsigned long long)(start + size - 1));
+			return;
+		}
+
+		if (mem_limit - start < size) {
+			printk(KERN_ERR "e820: ignoring [mem %#010llx-%#010llx]\n",
+			       (unsigned long long)mem_limit,
+			       (unsigned long long)(start + size - 1));
+			size = mem_limit - start;
+		}
+	}
+
 	e820x->map[x].addr = start;
 	e820x->map[x].size = size;
 	e820x->map[x].type = type;
@@ -127,7 +144,37 @@ static void __init __e820_add_region(struct e820map *e820x, u64 start, u64 size,
 
 void __init e820_add_region(u64 start, u64 size, int type)
 {
-	__e820_add_region(&e820, start, size, type);
+	__e820_add_region(&e820, start, size, type, false);
+}
+
+/*
+ * do_add_efi_memmap() calls this function().
+ *
+ * Note: BOOT_SERVICES_{CODE,DATA} regions on some efi machines are marked
+ * as E820_RAM, and they are needed to be mapped. Please use e820_add_region()
+ * to add BOOT_SERVICES_{CODE,DATA} regions.
+ */
+void __init e820_add_limit_region(u64 start, u64 size, int type)
+{
+	/*
+	 * efi_init() is called after finish_e820_parsing(), so we should
+	 * check whether [start, start + size) contains address above
+	 * mem_limit if the type is E820_RAM.
+	 */
+	__e820_add_region(&e820, start, size, type, type == E820_RAM);
+}
+
+void __init e820_adjust_region(u64 *start, u64 *size)
+{
+	if (*start >= mem_limit) {
+		*size = 0;
+		return;
+	}
+
+	if (mem_limit - *start < *size)
+		*size = mem_limit - *start;
+
+	return;
 }
 
 static void __init e820_print_type(u32 type)
@@ -455,8 +502,9 @@ static u64 __init __e820_update_range(struct e820map *e820x, u64 start,
 
 		/* new range is totally covered? */
 		if (ei->addr < start && ei_end > end) {
-			__e820_add_region(e820x, start, size, new_type);
-			__e820_add_region(e820x, end, ei_end - end, ei->type);
+			__e820_add_region(e820x, start, size, new_type, false);
+			__e820_add_region(e820x, end, ei_end - end, ei->type,
+					  false);
 			ei->size = start - ei->addr;
 			real_updated_size += size;
 			continue;
@@ -469,7 +517,7 @@ static u64 __init __e820_update_range(struct e820map *e820x, u64 start,
 			continue;
 
 		__e820_add_region(e820x, final_start, final_end - final_start,
-				  new_type);
+				  new_type, false);
 
 		real_updated_size += final_end - final_start;
 
@@ -809,7 +857,7 @@ static int userdef __initdata;
 /* "mem=nopentium" disables the 4MB page tables. */
 static int __init parse_memopt(char *p)
 {
-	u64 mem_size;
+	char *oldp;
 
 	if (!p)
 		return -EINVAL;
@@ -825,11 +873,11 @@ static int __init parse_memopt(char *p)
 	}
 
 	userdef = 1;
-	mem_size = memparse(p, &p);
+	oldp = p;
+	mem_limit = memparse(p, &p);
 	/* don't remove all of memory when handling "mem={invalid}" param */
-	if (mem_size == 0)
+	if (mem_limit == 0 || p == oldp)
 		return -EINVAL;
-	e820_remove_range(mem_size, ULLONG_MAX - mem_size, E820_RAM, 1);
 
 	return 0;
 }
@@ -895,6 +943,12 @@ early_param("memmap", parse_memmap_opt);
 
 void __init finish_e820_parsing(void)
 {
+	if (mem_limit != ~0ULL) {
+		userdef = 1;
+		e820_remove_range(mem_limit, ULLONG_MAX - mem_limit,
+				  E820_RAM, 1);
+	}
+
 	if (userdef) {
 		u32 nr = e820.nr_map;
 
diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c
index 9b9f18b..d15f575 100644
--- a/arch/x86/kernel/early_printk.c
+++ b/arch/x86/kernel/early_printk.c
@@ -169,25 +169,9 @@ static struct console early_serial_console = {
 	.index =	-1,
 };
 
-/* Direct interface for emergencies */
-static struct console *early_console = &early_vga_console;
-static int __initdata early_console_initialized;
-
-asmlinkage void early_printk(const char *fmt, ...)
-{
-	char buf[512];
-	int n;
-	va_list ap;
-
-	va_start(ap, fmt);
-	n = vscnprintf(buf, sizeof(buf), fmt, ap);
-	early_console->write(early_console, buf, n);
-	va_end(ap);
-}
-
 static inline void early_console_register(struct console *con, int keep_early)
 {
-	if (early_console->index != -1) {
+	if (con->index != -1) {
 		printk(KERN_CRIT "ERROR: earlyprintk= %s already used\n",
 		       con->name);
 		return;
@@ -207,9 +191,8 @@ static int __init setup_early_printk(char *buf)
 	if (!buf)
 		return 0;
 
-	if (early_console_initialized)
+	if (early_console)
 		return 0;
-	early_console_initialized = 1;
 
 	keep = (strstr(buf, "keep") != NULL);
 
diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c
index b686a90..cd6d9a5 100644
--- a/arch/x86/kernel/kvm.c
+++ b/arch/x86/kernel/kvm.c
@@ -20,6 +20,7 @@
  *   Authors: Anthony Liguori <aliguori@us.ibm.com>
  */
 
+#include <linux/context_tracking.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/kvm_para.h>
@@ -43,7 +44,6 @@
 #include <asm/apicdef.h>
 #include <asm/hypervisor.h>
 #include <asm/kvm_guest.h>
-#include <asm/context_tracking.h>
 
 static int kvmapf = 1;
 
@@ -254,16 +254,18 @@ EXPORT_SYMBOL_GPL(kvm_read_and_reset_pf_reason);
 dotraplinkage void __kprobes
 do_async_page_fault(struct pt_regs *regs, unsigned long error_code)
 {
+	enum ctx_state prev_state;
+
 	switch (kvm_read_and_reset_pf_reason()) {
 	default:
 		do_page_fault(regs, error_code);
 		break;
 	case KVM_PV_REASON_PAGE_NOT_PRESENT:
 		/* page is swapped out by the host. */
-		exception_enter(regs);
+		prev_state = exception_enter();
 		exit_idle();
 		kvm_async_pf_task_wait((u32)read_cr2());
-		exception_exit(regs);
+		exception_exit(prev_state);
 		break;
 	case KVM_PV_REASON_PAGE_READY:
 		rcu_irq_enter();
diff --git a/arch/x86/kernel/kvmclock.c b/arch/x86/kernel/kvmclock.c
index 0732f00..d2c3812 100644
--- a/arch/x86/kernel/kvmclock.c
+++ b/arch/x86/kernel/kvmclock.c
@@ -160,8 +160,12 @@ int kvm_register_clock(char *txt)
 {
 	int cpu = smp_processor_id();
 	int low, high, ret;
-	struct pvclock_vcpu_time_info *src = &hv_clock[cpu].pvti;
+	struct pvclock_vcpu_time_info *src;
+
+	if (!hv_clock)
+		return 0;
 
+	src = &hv_clock[cpu].pvti;
 	low = (int)slow_virt_to_phys(src) | 1;
 	high = ((u64)slow_virt_to_phys(src) >> 32);
 	ret = native_write_msr_safe(msr_kvm_system_time, low, high);
@@ -276,6 +280,9 @@ int __init kvm_setup_vsyscall_timeinfo(void)
 	struct pvclock_vcpu_time_info *vcpu_time;
 	unsigned int size;
 
+	if (!hv_clock)
+		return 0;
+
 	size = PAGE_ALIGN(sizeof(struct pvclock_vsyscall_time_info)*NR_CPUS);
 
 	preempt_disable();
diff --git a/arch/x86/kernel/tls.c b/arch/x86/kernel/tls.c
index 9d9d2f9..f7fec09 100644
--- a/arch/x86/kernel/tls.c
+++ b/arch/x86/kernel/tls.c
@@ -3,13 +3,13 @@
 #include <linux/sched.h>
 #include <linux/user.h>
 #include <linux/regset.h>
+#include <linux/syscalls.h>
 
 #include <asm/uaccess.h>
 #include <asm/desc.h>
 #include <asm/ldt.h>
 #include <asm/processor.h>
 #include <asm/proto.h>
-#include <asm/syscalls.h>
 
 #include "tls.h"
 
@@ -89,11 +89,9 @@ int do_set_thread_area(struct task_struct *p, int idx,
 	return 0;
 }
 
-asmlinkage int sys_set_thread_area(struct user_desc __user *u_info)
+SYSCALL_DEFINE1(set_thread_area, struct user_desc __user *, u_info)
 {
-	int ret = do_set_thread_area(current, -1, u_info, 1);
-	asmlinkage_protect(1, ret, u_info);
-	return ret;
+	return do_set_thread_area(current, -1, u_info, 1);
 }
 
 
@@ -139,11 +137,9 @@ int do_get_thread_area(struct task_struct *p, int idx,
 	return 0;
 }
 
-asmlinkage int sys_get_thread_area(struct user_desc __user *u_info)
+SYSCALL_DEFINE1(get_thread_area, struct user_desc __user *, u_info)
 {
-	int ret = do_get_thread_area(current, -1, u_info);
-	asmlinkage_protect(1, ret, u_info);
-	return ret;
+	return do_get_thread_area(current, -1, u_info);
 }
 
 int regset_tls_active(struct task_struct *target,
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index 68bda7a..ff6d227 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -12,6 +12,7 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include <linux/context_tracking.h>
 #include <linux/interrupt.h>
 #include <linux/kallsyms.h>
 #include <linux/spinlock.h>
@@ -55,8 +56,6 @@
 #include <asm/i387.h>
 #include <asm/fpu-internal.h>
 #include <asm/mce.h>
-#include <asm/context_tracking.h>
-
 #include <asm/mach_traps.h>
 
 #ifdef CONFIG_X86_64
@@ -176,34 +175,38 @@ do_trap(int trapnr, int signr, char *str, struct pt_regs *regs,
 #define DO_ERROR(trapnr, signr, str, name)				\
 dotraplinkage void do_##name(struct pt_regs *regs, long error_code)	\
 {									\
-	exception_enter(regs);						\
+	enum ctx_state prev_state;					\
+									\
+	prev_state = exception_enter();					\
 	if (notify_die(DIE_TRAP, str, regs, error_code,			\
 			trapnr, signr) == NOTIFY_STOP) {		\
-		exception_exit(regs);					\
+		exception_exit(prev_state);				\
 		return;							\
 	}								\
 	conditional_sti(regs);						\
 	do_trap(trapnr, signr, str, regs, error_code, NULL);		\
-	exception_exit(regs);						\
+	exception_exit(prev_state);					\
 }
 
 #define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr)		\
 dotraplinkage void do_##name(struct pt_regs *regs, long error_code)	\
 {									\
 	siginfo_t info;							\
+	enum ctx_state prev_state;					\
+									\
 	info.si_signo = signr;						\
 	info.si_errno = 0;						\
 	info.si_code = sicode;						\
 	info.si_addr = (void __user *)siaddr;				\
-	exception_enter(regs);						\
+	prev_state = exception_enter();					\
 	if (notify_die(DIE_TRAP, str, regs, error_code,			\
 			trapnr, signr) == NOTIFY_STOP) {		\
-		exception_exit(regs);					\
+		exception_exit(prev_state);				\
 		return;							\
 	}								\
 	conditional_sti(regs);						\
 	do_trap(trapnr, signr, str, regs, error_code, &info);		\
-	exception_exit(regs);						\
+	exception_exit(prev_state);					\
 }
 
 DO_ERROR_INFO(X86_TRAP_DE, SIGFPE, "divide error", divide_error, FPE_INTDIV,
@@ -226,14 +229,16 @@ DO_ERROR_INFO(X86_TRAP_AC, SIGBUS, "alignment check", alignment_check,
 /* Runs on IST stack */
 dotraplinkage void do_stack_segment(struct pt_regs *regs, long error_code)
 {
-	exception_enter(regs);
+	enum ctx_state prev_state;
+
+	prev_state = exception_enter();
 	if (notify_die(DIE_TRAP, "stack segment", regs, error_code,
 		       X86_TRAP_SS, SIGBUS) != NOTIFY_STOP) {
 		preempt_conditional_sti(regs);
 		do_trap(X86_TRAP_SS, SIGBUS, "stack segment", regs, error_code, NULL);
 		preempt_conditional_cli(regs);
 	}
-	exception_exit(regs);
+	exception_exit(prev_state);
 }
 
 dotraplinkage void do_double_fault(struct pt_regs *regs, long error_code)
@@ -241,7 +246,7 @@ dotraplinkage void do_double_fault(struct pt_regs *regs, long error_code)
 	static const char str[] = "double fault";
 	struct task_struct *tsk = current;
 
-	exception_enter(regs);
+	exception_enter();
 	/* Return not checked because double check cannot be ignored */
 	notify_die(DIE_TRAP, str, regs, error_code, X86_TRAP_DF, SIGSEGV);
 
@@ -261,8 +266,9 @@ dotraplinkage void __kprobes
 do_general_protection(struct pt_regs *regs, long error_code)
 {
 	struct task_struct *tsk;
+	enum ctx_state prev_state;
 
-	exception_enter(regs);
+	prev_state = exception_enter();
 	conditional_sti(regs);
 
 #ifdef CONFIG_X86_32
@@ -300,12 +306,14 @@ do_general_protection(struct pt_regs *regs, long error_code)
 
 	force_sig(SIGSEGV, tsk);
 exit:
-	exception_exit(regs);
+	exception_exit(prev_state);
 }
 
 /* May run on IST stack. */
 dotraplinkage void __kprobes notrace do_int3(struct pt_regs *regs, long error_code)
 {
+	enum ctx_state prev_state;
+
 #ifdef CONFIG_DYNAMIC_FTRACE
 	/*
 	 * ftrace must be first, everything else may cause a recursive crash.
@@ -315,7 +323,7 @@ dotraplinkage void __kprobes notrace do_int3(struct pt_regs *regs, long error_co
 	    ftrace_int3_handler(regs))
 		return;
 #endif
-	exception_enter(regs);
+	prev_state = exception_enter();
 #ifdef CONFIG_KGDB_LOW_LEVEL_TRAP
 	if (kgdb_ll_trap(DIE_INT3, "int3", regs, error_code, X86_TRAP_BP,
 				SIGTRAP) == NOTIFY_STOP)
@@ -336,7 +344,7 @@ dotraplinkage void __kprobes notrace do_int3(struct pt_regs *regs, long error_co
 	preempt_conditional_cli(regs);
 	debug_stack_usage_dec();
 exit:
-	exception_exit(regs);
+	exception_exit(prev_state);
 }
 
 #ifdef CONFIG_X86_64
@@ -393,11 +401,12 @@ asmlinkage __kprobes struct pt_regs *sync_regs(struct pt_regs *eregs)
 dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code)
 {
 	struct task_struct *tsk = current;
+	enum ctx_state prev_state;
 	int user_icebp = 0;
 	unsigned long dr6;
 	int si_code;
 
-	exception_enter(regs);
+	prev_state = exception_enter();
 
 	get_debugreg(dr6, 6);
 
@@ -467,7 +476,7 @@ dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code)
 	debug_stack_usage_dec();
 
 exit:
-	exception_exit(regs);
+	exception_exit(prev_state);
 }
 
 /*
@@ -561,17 +570,21 @@ void math_error(struct pt_regs *regs, int error_code, int trapnr)
 
 dotraplinkage void do_coprocessor_error(struct pt_regs *regs, long error_code)
 {
-	exception_enter(regs);
+	enum ctx_state prev_state;
+
+	prev_state = exception_enter();
 	math_error(regs, error_code, X86_TRAP_MF);
-	exception_exit(regs);
+	exception_exit(prev_state);
 }
 
 dotraplinkage void
 do_simd_coprocessor_error(struct pt_regs *regs, long error_code)
 {
-	exception_enter(regs);
+	enum ctx_state prev_state;
+
+	prev_state = exception_enter();
 	math_error(regs, error_code, X86_TRAP_XF);
-	exception_exit(regs);
+	exception_exit(prev_state);
 }
 
 dotraplinkage void
@@ -639,7 +652,9 @@ EXPORT_SYMBOL_GPL(math_state_restore);
 dotraplinkage void __kprobes
 do_device_not_available(struct pt_regs *regs, long error_code)
 {
-	exception_enter(regs);
+	enum ctx_state prev_state;
+
+	prev_state = exception_enter();
 	BUG_ON(use_eager_fpu());
 
 #ifdef CONFIG_MATH_EMULATION
@@ -650,7 +665,7 @@ do_device_not_available(struct pt_regs *regs, long error_code)
 
 		info.regs = regs;
 		math_emulate(&info);
-		exception_exit(regs);
+		exception_exit(prev_state);
 		return;
 	}
 #endif
@@ -658,15 +673,16 @@ do_device_not_available(struct pt_regs *regs, long error_code)
 #ifdef CONFIG_X86_32
 	conditional_sti(regs);
 #endif
-	exception_exit(regs);
+	exception_exit(prev_state);
 }
 
 #ifdef CONFIG_X86_32
 dotraplinkage void do_iret_error(struct pt_regs *regs, long error_code)
 {
 	siginfo_t info;
+	enum ctx_state prev_state;
 
-	exception_enter(regs);
+	prev_state = exception_enter();
 	local_irq_enable();
 
 	info.si_signo = SIGILL;
@@ -678,7 +694,7 @@ dotraplinkage void do_iret_error(struct pt_regs *regs, long error_code)
 		do_trap(X86_TRAP_IRET, SIGILL, "iret exception", regs, error_code,
 			&info);
 	}
-	exception_exit(regs);
+	exception_exit(prev_state);
 }
 #endif
 
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 02b51dd..a8e9369 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -731,7 +731,11 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
 	case APIC_DM_INIT:
 		if (!trig_mode || level) {
 			result = 1;
-			vcpu->arch.mp_state = KVM_MP_STATE_INIT_RECEIVED;
+			/* assumes that there are only KVM_APIC_INIT/SIPI */
+			apic->pending_events = (1UL << KVM_APIC_INIT);
+			/* make sure pending_events is visible before sending
+			 * the request */
+			smp_wmb();
 			kvm_make_request(KVM_REQ_EVENT, vcpu);
 			kvm_vcpu_kick(vcpu);
 		} else {
@@ -743,13 +747,13 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
 	case APIC_DM_STARTUP:
 		apic_debug("SIPI to vcpu %d vector 0x%02x\n",
 			   vcpu->vcpu_id, vector);
-		if (vcpu->arch.mp_state == KVM_MP_STATE_INIT_RECEIVED) {
-			result = 1;
-			vcpu->arch.sipi_vector = vector;
-			vcpu->arch.mp_state = KVM_MP_STATE_SIPI_RECEIVED;
-			kvm_make_request(KVM_REQ_EVENT, vcpu);
-			kvm_vcpu_kick(vcpu);
-		}
+		result = 1;
+		apic->sipi_vector = vector;
+		/* make sure sipi_vector is visible for the receiver */
+		smp_wmb();
+		set_bit(KVM_APIC_SIPI, &apic->pending_events);
+		kvm_make_request(KVM_REQ_EVENT, vcpu);
+		kvm_vcpu_kick(vcpu);
 		break;
 
 	case APIC_DM_EXTINT:
@@ -1860,6 +1864,34 @@ int kvm_lapic_enable_pv_eoi(struct kvm_vcpu *vcpu, u64 data)
 					 addr);
 }
 
+void kvm_apic_accept_events(struct kvm_vcpu *vcpu)
+{
+	struct kvm_lapic *apic = vcpu->arch.apic;
+	unsigned int sipi_vector;
+
+	if (!kvm_vcpu_has_lapic(vcpu))
+		return;
+
+	if (test_and_clear_bit(KVM_APIC_INIT, &apic->pending_events)) {
+		kvm_lapic_reset(vcpu);
+		kvm_vcpu_reset(vcpu);
+		if (kvm_vcpu_is_bsp(apic->vcpu))
+			vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
+		else
+			vcpu->arch.mp_state = KVM_MP_STATE_INIT_RECEIVED;
+	}
+	if (test_and_clear_bit(KVM_APIC_SIPI, &apic->pending_events) &&
+	    vcpu->arch.mp_state == KVM_MP_STATE_INIT_RECEIVED) {
+		/* evaluate pending_events before reading the vector */
+		smp_rmb();
+		sipi_vector = apic->sipi_vector;
+		pr_debug("vcpu %d received sipi with vector # %x\n",
+			 vcpu->vcpu_id, sipi_vector);
+		kvm_vcpu_deliver_sipi_vector(vcpu, sipi_vector);
+		vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
+	}
+}
+
 void kvm_lapic_init(void)
 {
 	/* do not patch jump label more than once per second */
diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h
index 1676d34..2c721b9 100644
--- a/arch/x86/kvm/lapic.h
+++ b/arch/x86/kvm/lapic.h
@@ -5,6 +5,9 @@
 
 #include <linux/kvm_host.h>
 
+#define KVM_APIC_INIT		0
+#define KVM_APIC_SIPI		1
+
 struct kvm_timer {
 	struct hrtimer timer;
 	s64 period; 				/* unit: ns */
@@ -32,6 +35,8 @@ struct kvm_lapic {
 	void *regs;
 	gpa_t vapic_addr;
 	struct page *vapic_page;
+	unsigned long pending_events;
+	unsigned int sipi_vector;
 };
 int kvm_create_lapic(struct kvm_vcpu *vcpu);
 void kvm_free_lapic(struct kvm_vcpu *vcpu);
@@ -39,6 +44,7 @@ void kvm_free_lapic(struct kvm_vcpu *vcpu);
 int kvm_apic_has_interrupt(struct kvm_vcpu *vcpu);
 int kvm_apic_accept_pic_intr(struct kvm_vcpu *vcpu);
 int kvm_get_apic_interrupt(struct kvm_vcpu *vcpu);
+void kvm_apic_accept_events(struct kvm_vcpu *vcpu);
 void kvm_lapic_reset(struct kvm_vcpu *vcpu);
 u64 kvm_lapic_get_cr8(struct kvm_vcpu *vcpu);
 void kvm_lapic_set_tpr(struct kvm_vcpu *vcpu, unsigned long cr8);
@@ -158,4 +164,9 @@ void kvm_calculate_eoi_exitmap(struct kvm_vcpu *vcpu,
 				struct kvm_lapic_irq *irq,
 				u64 *eoi_bitmap);
 
+static inline bool kvm_apic_has_events(struct kvm_vcpu *vcpu)
+{
+	return vcpu->arch.apic->pending_events;
+}
+
 #endif
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index 956ca35..633e30c 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -199,8 +199,11 @@ EXPORT_SYMBOL_GPL(kvm_mmu_set_mmio_spte_mask);
 
 static void mark_mmio_spte(u64 *sptep, u64 gfn, unsigned access)
 {
+	struct kvm_mmu_page *sp =  page_header(__pa(sptep));
+
 	access &= ACC_WRITE_MASK | ACC_USER_MASK;
 
+	sp->mmio_cached = true;
 	trace_mark_mmio_spte(sptep, gfn, access);
 	mmu_spte_set(sptep, shadow_mmio_mask | access | gfn << PAGE_SHIFT);
 }
@@ -1498,10 +1501,15 @@ static void drop_parent_pte(struct kvm_mmu_page *sp,
 	mmu_spte_clear_no_track(parent_pte);
 }
 
+static void make_mmu_pages_available(struct kvm_vcpu *vcpu);
+
 static struct kvm_mmu_page *kvm_mmu_alloc_page(struct kvm_vcpu *vcpu,
 					       u64 *parent_pte, int direct)
 {
 	struct kvm_mmu_page *sp;
+
+	make_mmu_pages_available(vcpu);
+
 	sp = mmu_memory_cache_alloc(&vcpu->arch.mmu_page_header_cache);
 	sp->spt = mmu_memory_cache_alloc(&vcpu->arch.mmu_page_cache);
 	if (!direct)
@@ -1644,16 +1652,14 @@ static int kvm_mmu_prepare_zap_page(struct kvm *kvm, struct kvm_mmu_page *sp,
 static void kvm_mmu_commit_zap_page(struct kvm *kvm,
 				    struct list_head *invalid_list);
 
-#define for_each_gfn_sp(kvm, sp, gfn)					\
-  hlist_for_each_entry(sp,						\
-   &(kvm)->arch.mmu_page_hash[kvm_page_table_hashfn(gfn)], hash_link)	\
-	if ((sp)->gfn != (gfn)) {} else
+#define for_each_gfn_sp(_kvm, _sp, _gfn)				\
+	hlist_for_each_entry(_sp,					\
+	  &(_kvm)->arch.mmu_page_hash[kvm_page_table_hashfn(_gfn)], hash_link) \
+		if ((_sp)->gfn != (_gfn)) {} else
 
-#define for_each_gfn_indirect_valid_sp(kvm, sp, gfn)			\
-  hlist_for_each_entry(sp,						\
-   &(kvm)->arch.mmu_page_hash[kvm_page_table_hashfn(gfn)], hash_link)	\
-		if ((sp)->gfn != (gfn) || (sp)->role.direct ||		\
-			(sp)->role.invalid) {} else
+#define for_each_gfn_indirect_valid_sp(_kvm, _sp, _gfn)			\
+	for_each_gfn_sp(_kvm, _sp, _gfn)				\
+		if ((_sp)->role.direct || (_sp)->role.invalid) {} else
 
 /* @sp->gfn should be write-protected at the call site */
 static int __kvm_sync_page(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp,
@@ -2089,7 +2095,7 @@ static int kvm_mmu_prepare_zap_page(struct kvm *kvm, struct kvm_mmu_page *sp,
 static void kvm_mmu_commit_zap_page(struct kvm *kvm,
 				    struct list_head *invalid_list)
 {
-	struct kvm_mmu_page *sp;
+	struct kvm_mmu_page *sp, *nsp;
 
 	if (list_empty(invalid_list))
 		return;
@@ -2106,11 +2112,25 @@ static void kvm_mmu_commit_zap_page(struct kvm *kvm,
 	 */
 	kvm_flush_remote_tlbs(kvm);
 
-	do {
-		sp = list_first_entry(invalid_list, struct kvm_mmu_page, link);
+	list_for_each_entry_safe(sp, nsp, invalid_list, link) {
 		WARN_ON(!sp->role.invalid || sp->root_count);
 		kvm_mmu_free_page(sp);
-	} while (!list_empty(invalid_list));
+	}
+}
+
+static bool prepare_zap_oldest_mmu_page(struct kvm *kvm,
+					struct list_head *invalid_list)
+{
+	struct kvm_mmu_page *sp;
+
+	if (list_empty(&kvm->arch.active_mmu_pages))
+		return false;
+
+	sp = list_entry(kvm->arch.active_mmu_pages.prev,
+			struct kvm_mmu_page, link);
+	kvm_mmu_prepare_zap_page(kvm, sp, invalid_list);
+
+	return true;
 }
 
 /*
@@ -2120,23 +2140,15 @@ static void kvm_mmu_commit_zap_page(struct kvm *kvm,
 void kvm_mmu_change_mmu_pages(struct kvm *kvm, unsigned int goal_nr_mmu_pages)
 {
 	LIST_HEAD(invalid_list);
-	/*
-	 * If we set the number of mmu pages to be smaller be than the
-	 * number of actived pages , we must to free some mmu pages before we
-	 * change the value
-	 */
 
 	spin_lock(&kvm->mmu_lock);
 
 	if (kvm->arch.n_used_mmu_pages > goal_nr_mmu_pages) {
-		while (kvm->arch.n_used_mmu_pages > goal_nr_mmu_pages &&
-			!list_empty(&kvm->arch.active_mmu_pages)) {
-			struct kvm_mmu_page *page;
+		/* Need to free some mmu pages to achieve the goal. */
+		while (kvm->arch.n_used_mmu_pages > goal_nr_mmu_pages)
+			if (!prepare_zap_oldest_mmu_page(kvm, &invalid_list))
+				break;
 
-			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);
 		goal_nr_mmu_pages = kvm->arch.n_used_mmu_pages;
 	}
@@ -2835,7 +2847,6 @@ static int nonpaging_map(struct kvm_vcpu *vcpu, gva_t v, u32 error_code,
 	spin_lock(&vcpu->kvm->mmu_lock);
 	if (mmu_notifier_retry(vcpu->kvm, mmu_seq))
 		goto out_unlock;
-	kvm_mmu_free_some_pages(vcpu);
 	if (likely(!force_pt_level))
 		transparent_hugepage_adjust(vcpu, &gfn, &pfn, &level);
 	r = __direct_map(vcpu, v, write, map_writable, level, gfn, pfn,
@@ -2913,7 +2924,6 @@ static int mmu_alloc_direct_roots(struct kvm_vcpu *vcpu)
 
 	if (vcpu->arch.mmu.shadow_root_level == PT64_ROOT_LEVEL) {
 		spin_lock(&vcpu->kvm->mmu_lock);
-		kvm_mmu_free_some_pages(vcpu);
 		sp = kvm_mmu_get_page(vcpu, 0, 0, PT64_ROOT_LEVEL,
 				      1, ACC_ALL, NULL);
 		++sp->root_count;
@@ -2925,7 +2935,6 @@ static int mmu_alloc_direct_roots(struct kvm_vcpu *vcpu)
 
 			ASSERT(!VALID_PAGE(root));
 			spin_lock(&vcpu->kvm->mmu_lock);
-			kvm_mmu_free_some_pages(vcpu);
 			sp = kvm_mmu_get_page(vcpu, i << (30 - PAGE_SHIFT),
 					      i << 30,
 					      PT32_ROOT_LEVEL, 1, ACC_ALL,
@@ -2964,7 +2973,6 @@ static int mmu_alloc_shadow_roots(struct kvm_vcpu *vcpu)
 		ASSERT(!VALID_PAGE(root));
 
 		spin_lock(&vcpu->kvm->mmu_lock);
-		kvm_mmu_free_some_pages(vcpu);
 		sp = kvm_mmu_get_page(vcpu, root_gfn, 0, PT64_ROOT_LEVEL,
 				      0, ACC_ALL, NULL);
 		root = __pa(sp->spt);
@@ -2998,7 +3006,6 @@ static int mmu_alloc_shadow_roots(struct kvm_vcpu *vcpu)
 				return 1;
 		}
 		spin_lock(&vcpu->kvm->mmu_lock);
-		kvm_mmu_free_some_pages(vcpu);
 		sp = kvm_mmu_get_page(vcpu, root_gfn, i << 30,
 				      PT32_ROOT_LEVEL, 0,
 				      ACC_ALL, NULL);
@@ -3304,7 +3311,6 @@ static int tdp_page_fault(struct kvm_vcpu *vcpu, gva_t gpa, u32 error_code,
 	spin_lock(&vcpu->kvm->mmu_lock);
 	if (mmu_notifier_retry(vcpu->kvm, mmu_seq))
 		goto out_unlock;
-	kvm_mmu_free_some_pages(vcpu);
 	if (likely(!force_pt_level))
 		transparent_hugepage_adjust(vcpu, &gfn, &pfn, &level);
 	r = __direct_map(vcpu, gpa, write, map_writable,
@@ -4006,17 +4012,17 @@ int kvm_mmu_unprotect_page_virt(struct kvm_vcpu *vcpu, gva_t gva)
 }
 EXPORT_SYMBOL_GPL(kvm_mmu_unprotect_page_virt);
 
-void __kvm_mmu_free_some_pages(struct kvm_vcpu *vcpu)
+static void make_mmu_pages_available(struct kvm_vcpu *vcpu)
 {
 	LIST_HEAD(invalid_list);
 
-	while (kvm_mmu_available_pages(vcpu->kvm) < KVM_REFILL_PAGES &&
-	       !list_empty(&vcpu->kvm->arch.active_mmu_pages)) {
-		struct kvm_mmu_page *sp;
+	if (likely(kvm_mmu_available_pages(vcpu->kvm) >= KVM_MIN_FREE_MMU_PAGES))
+		return;
+
+	while (kvm_mmu_available_pages(vcpu->kvm) < KVM_REFILL_PAGES) {
+		if (!prepare_zap_oldest_mmu_page(vcpu->kvm, &invalid_list))
+			break;
 
-		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);
 		++vcpu->kvm->stat.mmu_recycled;
 	}
 	kvm_mmu_commit_zap_page(vcpu->kvm, &invalid_list);
@@ -4185,17 +4191,22 @@ restart:
 	spin_unlock(&kvm->mmu_lock);
 }
 
-static void kvm_mmu_remove_some_alloc_mmu_pages(struct kvm *kvm,
-						struct list_head *invalid_list)
+void kvm_mmu_zap_mmio_sptes(struct kvm *kvm)
 {
-	struct kvm_mmu_page *page;
+	struct kvm_mmu_page *sp, *node;
+	LIST_HEAD(invalid_list);
 
-	if (list_empty(&kvm->arch.active_mmu_pages))
-		return;
+	spin_lock(&kvm->mmu_lock);
+restart:
+	list_for_each_entry_safe(sp, node, &kvm->arch.active_mmu_pages, link) {
+		if (!sp->mmio_cached)
+			continue;
+		if (kvm_mmu_prepare_zap_page(kvm, sp, &invalid_list))
+			goto restart;
+	}
 
-	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);
+	spin_unlock(&kvm->mmu_lock);
 }
 
 static int mmu_shrink(struct shrinker *shrink, struct shrink_control *sc)
@@ -4232,7 +4243,7 @@ static int mmu_shrink(struct shrinker *shrink, struct shrink_control *sc)
 		idx = srcu_read_lock(&kvm->srcu);
 		spin_lock(&kvm->mmu_lock);
 
-		kvm_mmu_remove_some_alloc_mmu_pages(kvm, &invalid_list);
+		prepare_zap_oldest_mmu_page(kvm, &invalid_list);
 		kvm_mmu_commit_zap_page(kvm, &invalid_list);
 
 		spin_unlock(&kvm->mmu_lock);
diff --git a/arch/x86/kvm/mmu.h b/arch/x86/kvm/mmu.h
index 6987108..2adcbc2 100644
--- a/arch/x86/kvm/mmu.h
+++ b/arch/x86/kvm/mmu.h
@@ -57,14 +57,11 @@ int kvm_init_shadow_mmu(struct kvm_vcpu *vcpu, struct kvm_mmu *context);
 
 static inline unsigned int kvm_mmu_available_pages(struct kvm *kvm)
 {
-	return kvm->arch.n_max_mmu_pages -
-		kvm->arch.n_used_mmu_pages;
-}
+	if (kvm->arch.n_max_mmu_pages > kvm->arch.n_used_mmu_pages)
+		return kvm->arch.n_max_mmu_pages -
+			kvm->arch.n_used_mmu_pages;
 
-static inline void kvm_mmu_free_some_pages(struct kvm_vcpu *vcpu)
-{
-	if (unlikely(kvm_mmu_available_pages(vcpu->kvm)< KVM_MIN_FREE_MMU_PAGES))
-		__kvm_mmu_free_some_pages(vcpu);
+	return 0;
 }
 
 static inline int kvm_mmu_reload(struct kvm_vcpu *vcpu)
diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h
index 105dd5b..af143f0 100644
--- a/arch/x86/kvm/paging_tmpl.h
+++ b/arch/x86/kvm/paging_tmpl.h
@@ -627,7 +627,6 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr, u32 error_code,
 		goto out_unlock;
 
 	kvm_mmu_audit(vcpu, AUDIT_PRE_PAGE_FAULT);
-	kvm_mmu_free_some_pages(vcpu);
 	if (!force_pt_level)
 		transparent_hugepage_adjust(vcpu, &walker.gfn, &pfn, &level);
 	r = FNAME(fetch)(vcpu, addr, &walker, write_fault,
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index e1b1ce2..7a46c1f 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -1131,17 +1131,11 @@ static void init_vmcb(struct vcpu_svm *svm)
 	init_seg(&save->gs);
 
 	save->cs.selector = 0xf000;
+	save->cs.base = 0xffff0000;
 	/* Executable/Readable Code Segment */
 	save->cs.attrib = SVM_SELECTOR_READ_MASK | SVM_SELECTOR_P_MASK |
 		SVM_SELECTOR_S_MASK | SVM_SELECTOR_CODE_MASK;
 	save->cs.limit = 0xffff;
-	/*
-	 * cs.base should really be 0xffff0000, but vmx can't handle that, so
-	 * be consistent with it.
-	 *
-	 * Replace when we have real mode working for vmx.
-	 */
-	save->cs.base = 0xf0000;
 
 	save->gdtr.limit = 0xffff;
 	save->idtr.limit = 0xffff;
@@ -1191,7 +1185,7 @@ static void init_vmcb(struct vcpu_svm *svm)
 	enable_gif(svm);
 }
 
-static int svm_vcpu_reset(struct kvm_vcpu *vcpu)
+static void svm_vcpu_reset(struct kvm_vcpu *vcpu)
 {
 	struct vcpu_svm *svm = to_svm(vcpu);
 	u32 dummy;
@@ -1199,16 +1193,8 @@ static int svm_vcpu_reset(struct kvm_vcpu *vcpu)
 
 	init_vmcb(svm);
 
-	if (!kvm_vcpu_is_bsp(vcpu)) {
-		kvm_rip_write(vcpu, 0);
-		svm->vmcb->save.cs.base = svm->vcpu.arch.sipi_vector << 12;
-		svm->vmcb->save.cs.selector = svm->vcpu.arch.sipi_vector << 8;
-	}
-
 	kvm_cpuid(vcpu, &eax, &dummy, &dummy, &dummy);
 	kvm_register_write(vcpu, VCPU_REGS_RDX, eax);
-
-	return 0;
 }
 
 static struct kvm_vcpu *svm_create_vcpu(struct kvm *kvm, unsigned int id)
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 6667042..312575c 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -298,7 +298,8 @@ struct __packed vmcs12 {
 	u32 guest_activity_state;
 	u32 guest_sysenter_cs;
 	u32 host_ia32_sysenter_cs;
-	u32 padding32[8]; /* room for future expansion */
+	u32 vmx_preemption_timer_value;
+	u32 padding32[7]; /* room for future expansion */
 	u16 virtual_processor_id;
 	u16 guest_es_selector;
 	u16 guest_cs_selector;
@@ -537,6 +538,7 @@ static const unsigned short vmcs_field_to_offset_table[] = {
 	FIELD(GUEST_ACTIVITY_STATE, guest_activity_state),
 	FIELD(GUEST_SYSENTER_CS, guest_sysenter_cs),
 	FIELD(HOST_IA32_SYSENTER_CS, host_ia32_sysenter_cs),
+	FIELD(VMX_PREEMPTION_TIMER_VALUE, vmx_preemption_timer_value),
 	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),
@@ -2022,6 +2024,7 @@ 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 u32 nested_vmx_misc_low, nested_vmx_misc_high;
 static __init void nested_vmx_setup_ctls_msrs(void)
 {
 	/*
@@ -2040,30 +2043,40 @@ static __init void nested_vmx_setup_ctls_msrs(void)
 	 */
 
 	/* pin-based controls */
+	rdmsr(MSR_IA32_VMX_PINBASED_CTLS,
+	      nested_vmx_pinbased_ctls_low, nested_vmx_pinbased_ctls_high);
 	/*
 	 * 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;
+	nested_vmx_pinbased_ctls_low |= PIN_BASED_ALWAYSON_WITHOUT_TRUE_MSR;
+	nested_vmx_pinbased_ctls_high &= PIN_BASED_EXT_INTR_MASK |
+		PIN_BASED_NMI_EXITING | PIN_BASED_VIRTUAL_NMIS |
+		PIN_BASED_VMX_PREEMPTION_TIMER;
+	nested_vmx_pinbased_ctls_high |= PIN_BASED_ALWAYSON_WITHOUT_TRUE_MSR;
 
-	/* exit controls */
-	nested_vmx_exit_ctls_low = 0;
+	/*
+	 * Exit controls
+	 * If bit 55 of VMX_BASIC is off, bits 0-8 and 10, 11, 13, 14, 16 and
+	 * 17 must be 1.
+	 */
+	nested_vmx_exit_ctls_low = VM_EXIT_ALWAYSON_WITHOUT_TRUE_MSR;
 	/* 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
+	nested_vmx_exit_ctls_high |= VM_EXIT_ALWAYSON_WITHOUT_TRUE_MSR;
 
 	/* entry controls */
 	rdmsr(MSR_IA32_VMX_ENTRY_CTLS,
 		nested_vmx_entry_ctls_low, nested_vmx_entry_ctls_high);
-	nested_vmx_entry_ctls_low = 0;
+	/* If bit 55 of VMX_BASIC is off, bits 0-8 and 12 must be 1. */
+	nested_vmx_entry_ctls_low = VM_ENTRY_ALWAYSON_WITHOUT_TRUE_MSR;
 	nested_vmx_entry_ctls_high &=
 		VM_ENTRY_LOAD_IA32_PAT | VM_ENTRY_IA32E_MODE;
+	nested_vmx_entry_ctls_high |= VM_ENTRY_ALWAYSON_WITHOUT_TRUE_MSR;
 
 	/* cpu-based controls */
 	rdmsr(MSR_IA32_VMX_PROCBASED_CTLS,
@@ -2080,6 +2093,7 @@ static __init void nested_vmx_setup_ctls_msrs(void)
 		CPU_BASED_MOV_DR_EXITING | CPU_BASED_UNCOND_IO_EXITING |
 		CPU_BASED_USE_IO_BITMAPS | CPU_BASED_MONITOR_EXITING |
 		CPU_BASED_RDPMC_EXITING | CPU_BASED_RDTSC_EXITING |
+		CPU_BASED_PAUSE_EXITING |
 		CPU_BASED_ACTIVATE_SECONDARY_CONTROLS;
 	/*
 	 * We can allow some features even when not supported by the
@@ -2094,7 +2108,14 @@ static __init void nested_vmx_setup_ctls_msrs(void)
 		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;
+		SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES |
+		SECONDARY_EXEC_WBINVD_EXITING;
+
+	/* miscellaneous data */
+	rdmsr(MSR_IA32_VMX_MISC, nested_vmx_misc_low, nested_vmx_misc_high);
+	nested_vmx_misc_low &= VMX_MISC_PREEMPTION_TIMER_RATE_MASK |
+		VMX_MISC_SAVE_EFER_LMA;
+	nested_vmx_misc_high = 0;
 }
 
 static inline bool vmx_control_verify(u32 control, u32 low, u32 high)
@@ -2165,7 +2186,8 @@ static int vmx_get_vmx_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata)
 					nested_vmx_entry_ctls_high);
 		break;
 	case MSR_IA32_VMX_MISC:
-		*pdata = 0;
+		*pdata = vmx_control_msr(nested_vmx_misc_low,
+					 nested_vmx_misc_high);
 		break;
 	/*
 	 * These MSRs specify bits which the guest must keep fixed (on or off)
@@ -2876,22 +2898,6 @@ static void enter_pmode(struct kvm_vcpu *vcpu)
 	vmx->cpl = 0;
 }
 
-static gva_t rmode_tss_base(struct kvm *kvm)
-{
-	if (!kvm->arch.tss_addr) {
-		struct kvm_memslots *slots;
-		struct kvm_memory_slot *slot;
-		gfn_t base_gfn;
-
-		slots = kvm_memslots(kvm);
-		slot = id_to_memslot(slots, 0);
-		base_gfn = slot->base_gfn + slot->npages - 3;
-
-		return base_gfn << PAGE_SHIFT;
-	}
-	return kvm->arch.tss_addr;
-}
-
 static void fix_rmode_seg(int seg, struct kvm_segment *save)
 {
 	const struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg];
@@ -2942,19 +2948,15 @@ static void enter_rmode(struct kvm_vcpu *vcpu)
 
 	/*
 	 * Very old userspace does not call KVM_SET_TSS_ADDR before entering
-	 * vcpu. Call it here with phys address pointing 16M below 4G.
+	 * vcpu. Warn the user that an update is overdue.
 	 */
-	if (!vcpu->kvm->arch.tss_addr) {
+	if (!vcpu->kvm->arch.tss_addr)
 		printk_once(KERN_WARNING "kvm: KVM_SET_TSS_ADDR need to be "
 			     "called before entering vcpu\n");
-		srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx);
-		vmx_set_tss_addr(vcpu->kvm, 0xfeffd000);
-		vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
-	}
 
 	vmx_segment_cache_clear(vmx);
 
-	vmcs_writel(GUEST_TR_BASE, rmode_tss_base(vcpu->kvm));
+	vmcs_writel(GUEST_TR_BASE, vcpu->kvm->arch.tss_addr);
 	vmcs_write32(GUEST_TR_LIMIT, RMODE_TSS_SIZE - 1);
 	vmcs_write32(GUEST_TR_AR_BYTES, 0x008b);
 
@@ -3214,7 +3216,9 @@ static int vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
 		 */
 		if (!nested_vmx_allowed(vcpu))
 			return 1;
-	} else if (to_vmx(vcpu)->nested.vmxon)
+	}
+	if (to_vmx(vcpu)->nested.vmxon &&
+	    ((cr4 & VMXON_CR4_ALWAYSON) != VMXON_CR4_ALWAYSON))
 		return 1;
 
 	vcpu->arch.cr4 = cr4;
@@ -3599,7 +3603,7 @@ static int init_rmode_tss(struct kvm *kvm)
 	int r, idx, ret = 0;
 
 	idx = srcu_read_lock(&kvm->srcu);
-	fn = rmode_tss_base(kvm) >> PAGE_SHIFT;
+	fn = kvm->arch.tss_addr >> PAGE_SHIFT;
 	r = kvm_clear_guest_page(kvm, fn, 0, PAGE_SIZE);
 	if (r < 0)
 		goto out;
@@ -3692,7 +3696,7 @@ static int alloc_apic_access_page(struct kvm *kvm)
 	kvm_userspace_mem.flags = 0;
 	kvm_userspace_mem.guest_phys_addr = 0xfee00000ULL;
 	kvm_userspace_mem.memory_size = PAGE_SIZE;
-	r = __kvm_set_memory_region(kvm, &kvm_userspace_mem, false);
+	r = __kvm_set_memory_region(kvm, &kvm_userspace_mem);
 	if (r)
 		goto out;
 
@@ -3722,7 +3726,7 @@ static int alloc_identity_pagetable(struct kvm *kvm)
 	kvm_userspace_mem.guest_phys_addr =
 		kvm->arch.ept_identity_map_addr;
 	kvm_userspace_mem.memory_size = PAGE_SIZE;
-	r = __kvm_set_memory_region(kvm, &kvm_userspace_mem, false);
+	r = __kvm_set_memory_region(kvm, &kvm_userspace_mem);
 	if (r)
 		goto out;
 
@@ -4089,11 +4093,10 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
 	return 0;
 }
 
-static int vmx_vcpu_reset(struct kvm_vcpu *vcpu)
+static void vmx_vcpu_reset(struct kvm_vcpu *vcpu)
 {
 	struct vcpu_vmx *vmx = to_vmx(vcpu);
 	u64 msr;
-	int ret;
 
 	vmx->rmode.vm86_active = 0;
 
@@ -4109,12 +4112,8 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu)
 	vmx_segment_cache_clear(vmx);
 
 	seg_setup(VCPU_SREG_CS);
-	if (kvm_vcpu_is_bsp(&vmx->vcpu))
-		vmcs_write16(GUEST_CS_SELECTOR, 0xf000);
-	else {
-		vmcs_write16(GUEST_CS_SELECTOR, vmx->vcpu.arch.sipi_vector << 8);
-		vmcs_writel(GUEST_CS_BASE, vmx->vcpu.arch.sipi_vector << 12);
-	}
+	vmcs_write16(GUEST_CS_SELECTOR, 0xf000);
+	vmcs_write32(GUEST_CS_BASE, 0xffff0000);
 
 	seg_setup(VCPU_SREG_DS);
 	seg_setup(VCPU_SREG_ES);
@@ -4137,10 +4136,7 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu)
 	vmcs_writel(GUEST_SYSENTER_EIP, 0);
 
 	vmcs_writel(GUEST_RFLAGS, 0x02);
-	if (kvm_vcpu_is_bsp(&vmx->vcpu))
-		kvm_rip_write(vcpu, 0xfff0);
-	else
-		kvm_rip_write(vcpu, 0);
+	kvm_rip_write(vcpu, 0xfff0);
 
 	vmcs_writel(GUEST_GDTR_BASE, 0);
 	vmcs_write32(GUEST_GDTR_LIMIT, 0xffff);
@@ -4175,19 +4171,13 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu)
 		vmcs_write16(VIRTUAL_PROCESSOR_ID, vmx->vpid);
 
 	vmx->vcpu.arch.cr0 = X86_CR0_NW | X86_CR0_CD | X86_CR0_ET;
-	vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
 	vmx_set_cr0(&vmx->vcpu, kvm_read_cr0(vcpu)); /* enter rmode */
-	srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx);
 	vmx_set_cr4(&vmx->vcpu, 0);
 	vmx_set_efer(&vmx->vcpu, 0);
 	vmx_fpu_activate(&vmx->vcpu);
 	update_exception_bitmap(&vmx->vcpu);
 
 	vpid_sync_context(vmx);
-
-	ret = 0;
-
-	return ret;
 }
 
 /*
@@ -4362,7 +4352,7 @@ static int vmx_set_tss_addr(struct kvm *kvm, unsigned int addr)
 		.flags = 0,
 	};
 
-	ret = kvm_set_memory_region(kvm, &tss_mem, false);
+	ret = kvm_set_memory_region(kvm, &tss_mem);
 	if (ret)
 		return ret;
 	kvm->arch.tss_addr = addr;
@@ -4603,34 +4593,50 @@ vmx_patch_hypercall(struct kvm_vcpu *vcpu, unsigned char *hypercall)
 /* called to set cr0 as appropriate 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)) {
+		struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
+		unsigned long orig_val = val;
+
 		/*
 		 * 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.
+		 * but did change L0 shadowed bits. So we first calculate the
+		 * effective cr0 value that L1 would like to write into the
+		 * hardware. It consists of the L2-owned bits from the new
+		 * value combined with the L1-owned bits from L1's guest_cr0.
 		 */
-		if (kvm_set_cr0(vcpu, (val & vcpu->arch.cr0_guest_owned_bits) |
-			 (vcpu->arch.cr0 & ~vcpu->arch.cr0_guest_owned_bits)))
+		val = (val & ~vmcs12->cr0_guest_host_mask) |
+			(vmcs12->guest_cr0 & vmcs12->cr0_guest_host_mask);
+
+		/* TODO: will have to take unrestricted guest mode into
+		 * account */
+		if ((val & VMXON_CR0_ALWAYSON) != VMXON_CR0_ALWAYSON)
 			return 1;
-		vmcs_writel(CR0_READ_SHADOW, val);
+
+		if (kvm_set_cr0(vcpu, val))
+			return 1;
+		vmcs_writel(CR0_READ_SHADOW, orig_val);
 		return 0;
-	} else
+	} else {
+		if (to_vmx(vcpu)->nested.vmxon &&
+		    ((val & VMXON_CR0_ALWAYSON) != VMXON_CR0_ALWAYSON))
+			return 1;
 		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)))
+		struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
+		unsigned long orig_val = val;
+
+		/* analogously to handle_set_cr0 */
+		val = (val & ~vmcs12->cr4_guest_host_mask) |
+			(vmcs12->guest_cr4 & vmcs12->cr4_guest_host_mask);
+		if (kvm_set_cr4(vcpu, val))
 			return 1;
-		vmcs_writel(CR4_READ_SHADOW, val);
+		vmcs_writel(CR4_READ_SHADOW, orig_val);
 		return 0;
 	} else
 		return kvm_set_cr4(vcpu, val);
@@ -5127,6 +5133,10 @@ static int handle_ept_misconfig(struct kvm_vcpu *vcpu)
 	gpa_t gpa;
 
 	gpa = vmcs_read64(GUEST_PHYSICAL_ADDRESS);
+	if (!kvm_io_bus_write(vcpu->kvm, KVM_PV_MMIO_BUS, gpa, 0, NULL)) {
+		skip_emulated_instruction(vcpu);
+		return 1;
+	}
 
 	ret = handle_mmio_page_fault_common(vcpu, gpa, true);
 	if (likely(ret == 1))
@@ -5259,8 +5269,7 @@ static struct loaded_vmcs *nested_get_current_vmcs02(struct vcpu_vmx *vmx)
 	}
 
 	/* Create a new VMCS */
-	item = (struct vmcs02_list *)
-		kmalloc(sizeof(struct vmcs02_list), GFP_KERNEL);
+	item = kmalloc(sizeof(struct vmcs02_list), GFP_KERNEL);
 	if (!item)
 		return NULL;
 	item->vmcs02.vmcs = alloc_vmcs();
@@ -5908,6 +5917,52 @@ static int (*const kvm_vmx_exit_handlers[])(struct kvm_vcpu *vcpu) = {
 static const int kvm_vmx_max_exit_handlers =
 	ARRAY_SIZE(kvm_vmx_exit_handlers);
 
+static bool nested_vmx_exit_handled_io(struct kvm_vcpu *vcpu,
+				       struct vmcs12 *vmcs12)
+{
+	unsigned long exit_qualification;
+	gpa_t bitmap, last_bitmap;
+	unsigned int port;
+	int size;
+	u8 b;
+
+	if (nested_cpu_has(vmcs12, CPU_BASED_UNCOND_IO_EXITING))
+		return 1;
+
+	if (!nested_cpu_has(vmcs12, CPU_BASED_USE_IO_BITMAPS))
+		return 0;
+
+	exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
+
+	port = exit_qualification >> 16;
+	size = (exit_qualification & 7) + 1;
+
+	last_bitmap = (gpa_t)-1;
+	b = -1;
+
+	while (size > 0) {
+		if (port < 0x8000)
+			bitmap = vmcs12->io_bitmap_a;
+		else if (port < 0x10000)
+			bitmap = vmcs12->io_bitmap_b;
+		else
+			return 1;
+		bitmap += (port & 0x7fff) / 8;
+
+		if (last_bitmap != bitmap)
+			if (kvm_read_guest(vcpu->kvm, bitmap, &b, 1))
+				return 1;
+		if (b & (1 << (port & 7)))
+			return 1;
+
+		port++;
+		size--;
+		last_bitmap = bitmap;
+	}
+
+	return 0;
+}
+
 /*
  * 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
@@ -5939,7 +5994,8 @@ static bool nested_vmx_exit_handled_msr(struct kvm_vcpu *vcpu,
 	/* 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);
+		if (kvm_read_guest(vcpu->kvm, bitmap + msr_index/8, &b, 1))
+			return 1;
 		return 1 & (b >> (msr_index & 7));
 	} else
 		return 1; /* let L1 handle the wrong parameter */
@@ -6033,10 +6089,10 @@ static bool nested_vmx_exit_handled_cr(struct kvm_vcpu *vcpu,
  */
 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);
+	u32 exit_reason = vmx->exit_reason;
 
 	if (vmx->nested.nested_run_pending)
 		return 0;
@@ -6097,8 +6153,7 @@ static bool nested_vmx_exit_handled(struct kvm_vcpu *vcpu)
 	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;
+		return nested_vmx_exit_handled_io(vcpu, vmcs12);
 	case EXIT_REASON_MSR_READ:
 	case EXIT_REASON_MSR_WRITE:
 		return nested_vmx_exit_handled_msr(vcpu, vmcs12, exit_reason);
@@ -6122,6 +6177,9 @@ static bool nested_vmx_exit_handled(struct kvm_vcpu *vcpu)
 	case EXIT_REASON_EPT_VIOLATION:
 	case EXIT_REASON_EPT_MISCONFIG:
 		return 0;
+	case EXIT_REASON_PREEMPTION_TIMER:
+		return vmcs12->pin_based_vm_exec_control &
+			PIN_BASED_VMX_PREEMPTION_TIMER;
 	case EXIT_REASON_WBINVD:
 		return nested_cpu_has2(vmcs12, SECONDARY_EXEC_WBINVD_EXITING);
 	case EXIT_REASON_XSETBV:
@@ -6388,7 +6446,7 @@ static void vmx_recover_nmi_blocking(struct vcpu_vmx *vmx)
 			ktime_to_ns(ktime_sub(ktime_get(), vmx->entry_time));
 }
 
-static void __vmx_complete_interrupts(struct vcpu_vmx *vmx,
+static void __vmx_complete_interrupts(struct kvm_vcpu *vcpu,
 				      u32 idt_vectoring_info,
 				      int instr_len_field,
 				      int error_code_field)
@@ -6399,46 +6457,43 @@ static void __vmx_complete_interrupts(struct vcpu_vmx *vmx,
 
 	idtv_info_valid = idt_vectoring_info & VECTORING_INFO_VALID_MASK;
 
-	vmx->vcpu.arch.nmi_injected = false;
-	kvm_clear_exception_queue(&vmx->vcpu);
-	kvm_clear_interrupt_queue(&vmx->vcpu);
+	vcpu->arch.nmi_injected = false;
+	kvm_clear_exception_queue(vcpu);
+	kvm_clear_interrupt_queue(vcpu);
 
 	if (!idtv_info_valid)
 		return;
 
-	kvm_make_request(KVM_REQ_EVENT, &vmx->vcpu);
+	kvm_make_request(KVM_REQ_EVENT, vcpu);
 
 	vector = idt_vectoring_info & VECTORING_INFO_VECTOR_MASK;
 	type = idt_vectoring_info & VECTORING_INFO_TYPE_MASK;
 
 	switch (type) {
 	case INTR_TYPE_NMI_INTR:
-		vmx->vcpu.arch.nmi_injected = true;
+		vcpu->arch.nmi_injected = true;
 		/*
 		 * SDM 3: 27.7.1.2 (September 2008)
 		 * Clear bit "block by NMI" before VM entry if a NMI
 		 * delivery faulted.
 		 */
-		vmx_set_nmi_mask(&vmx->vcpu, false);
+		vmx_set_nmi_mask(vcpu, false);
 		break;
 	case INTR_TYPE_SOFT_EXCEPTION:
-		vmx->vcpu.arch.event_exit_inst_len =
-			vmcs_read32(instr_len_field);
+		vcpu->arch.event_exit_inst_len = vmcs_read32(instr_len_field);
 		/* fall through */
 	case INTR_TYPE_HARD_EXCEPTION:
 		if (idt_vectoring_info & VECTORING_INFO_DELIVER_CODE_MASK) {
 			u32 err = vmcs_read32(error_code_field);
-			kvm_queue_exception_e(&vmx->vcpu, vector, err);
+			kvm_queue_exception_e(vcpu, vector, err);
 		} else
-			kvm_queue_exception(&vmx->vcpu, vector);
+			kvm_queue_exception(vcpu, vector);
 		break;
 	case INTR_TYPE_SOFT_INTR:
-		vmx->vcpu.arch.event_exit_inst_len =
-			vmcs_read32(instr_len_field);
+		vcpu->arch.event_exit_inst_len = vmcs_read32(instr_len_field);
 		/* fall through */
 	case INTR_TYPE_EXT_INTR:
-		kvm_queue_interrupt(&vmx->vcpu, vector,
-			type == INTR_TYPE_SOFT_INTR);
+		kvm_queue_interrupt(vcpu, vector, type == INTR_TYPE_SOFT_INTR);
 		break;
 	default:
 		break;
@@ -6449,7 +6504,7 @@ static void vmx_complete_interrupts(struct vcpu_vmx *vmx)
 {
 	if (is_guest_mode(&vmx->vcpu))
 		return;
-	__vmx_complete_interrupts(vmx, vmx->idt_vectoring_info,
+	__vmx_complete_interrupts(&vmx->vcpu, vmx->idt_vectoring_info,
 				  VM_EXIT_INSTRUCTION_LEN,
 				  IDT_VECTORING_ERROR_CODE);
 }
@@ -6458,7 +6513,7 @@ static void vmx_cancel_injection(struct kvm_vcpu *vcpu)
 {
 	if (is_guest_mode(vcpu))
 		return;
-	__vmx_complete_interrupts(to_vmx(vcpu),
+	__vmx_complete_interrupts(vcpu,
 				  vmcs_read32(VM_ENTRY_INTR_INFO_FIELD),
 				  VM_ENTRY_INSTRUCTION_LEN,
 				  VM_ENTRY_EXCEPTION_ERROR_CODE);
@@ -6933,7 +6988,7 @@ static void prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
 		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);
+	kvm_set_dr(vcpu, 7, vmcs12->guest_dr7);
 	vmcs_writel(GUEST_RFLAGS, vmcs12->guest_rflags);
 	vmcs_writel(GUEST_PENDING_DBG_EXCEPTIONS,
 		vmcs12->guest_pending_dbg_exceptions);
@@ -6946,6 +7001,10 @@ static void prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
 		(vmcs_config.pin_based_exec_ctrl |
 		 vmcs12->pin_based_vm_exec_control));
 
+	if (vmcs12->pin_based_vm_exec_control & PIN_BASED_VMX_PREEMPTION_TIMER)
+		vmcs_write32(VMX_PREEMPTION_TIMER_VALUE,
+			     vmcs12->vmx_preemption_timer_value);
+
 	/*
 	 * Whether page-faults are trapped is determined by a combination of
 	 * 3 settings: PFEC_MASK, PFEC_MATCH and EXCEPTION_BITMAP.PF.
@@ -7223,6 +7282,8 @@ static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch)
 	vcpu->cpu = cpu;
 	put_cpu();
 
+	vmx_segment_cache_clear(vmx);
+
 	vmcs12->launch_state = 1;
 
 	prepare_vmcs02(vcpu, vmcs12);
@@ -7284,7 +7345,7 @@ vmcs12_guest_cr4(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
  * 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)
+static void prepare_vmcs12(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
 {
 	/* update guest state fields: */
 	vmcs12->guest_cr0 = vmcs12_guest_cr0(vcpu, vmcs12);
@@ -7338,6 +7399,10 @@ void prepare_vmcs12(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
 	vmcs12->guest_pending_dbg_exceptions =
 		vmcs_readl(GUEST_PENDING_DBG_EXCEPTIONS);
 
+	vmcs12->vm_entry_controls =
+		(vmcs12->vm_entry_controls & ~VM_ENTRY_IA32E_MODE) |
+		(vmcs_read32(VM_ENTRY_CONTROLS) & VM_ENTRY_IA32E_MODE);
+
 	/* 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);
@@ -7349,13 +7414,12 @@ void prepare_vmcs12(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
 
 	/* update exit information fields: */
 
-	vmcs12->vm_exit_reason  = vmcs_read32(VM_EXIT_REASON);
+	vmcs12->vm_exit_reason  = to_vmx(vcpu)->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_info_field = to_vmx(vcpu)->idt_vectoring_info;
 	vmcs12->idt_vectoring_error_code =
 		vmcs_read32(IDT_VECTORING_ERROR_CODE);
 	vmcs12->vm_exit_instruction_len = vmcs_read32(VM_EXIT_INSTRUCTION_LEN);
@@ -7375,7 +7439,8 @@ void prepare_vmcs12(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
  * 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)
+static 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;
@@ -7387,6 +7452,7 @@ void load_vmcs12_host_state(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
 
 	kvm_register_write(vcpu, VCPU_REGS_RSP, vmcs12->host_rsp);
 	kvm_register_write(vcpu, VCPU_REGS_RIP, vmcs12->host_rip);
+	vmx_set_rflags(vcpu, X86_EFLAGS_BIT1);
 	/*
 	 * Note that calling vmx_set_cr0 is important, even if cr0 hasn't
 	 * actually changed, because it depends on the current state of
@@ -7445,6 +7511,9 @@ void load_vmcs12_host_state(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
 	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);
+
+	kvm_set_dr(vcpu, 7, 0x400);
+	vmcs_write64(GUEST_IA32_DEBUGCTL, 0);
 }
 
 /*
@@ -7468,6 +7537,8 @@ static void nested_vmx_vmexit(struct kvm_vcpu *vcpu)
 	vcpu->cpu = cpu;
 	put_cpu();
 
+	vmx_segment_cache_clear(vmx);
+
 	/* if no vmcs02 cache requested, remove the one we used */
 	if (VMCS02_POOL_SIZE == 0)
 		nested_free_vmcs02(vmx, vmx->nested.current_vmptr);
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index f19ac0a..622d7fb 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -162,8 +162,6 @@ u64 __read_mostly host_xcr0;
 
 static int emulator_fix_hypercall(struct x86_emulate_ctxt *ctxt);
 
-static int kvm_vcpu_reset(struct kvm_vcpu *vcpu);
-
 static inline void kvm_async_pf_hash_reset(struct kvm_vcpu *vcpu)
 {
 	int i;
@@ -1079,6 +1077,10 @@ static void kvm_set_tsc_khz(struct kvm_vcpu *vcpu, u32 this_tsc_khz)
 	u32 thresh_lo, thresh_hi;
 	int use_scaling = 0;
 
+	/* tsc_khz can be zero if TSC calibration fails */
+	if (this_tsc_khz == 0)
+		return;
+
 	/* Compute a scale to convert nanoseconds in TSC cycles */
 	kvm_get_time_scale(this_tsc_khz, NSEC_PER_SEC / 1000,
 			   &vcpu->arch.virtual_tsc_shift,
@@ -1156,20 +1158,23 @@ void kvm_write_tsc(struct kvm_vcpu *vcpu, struct msr_data *msr)
 	ns = get_kernel_ns();
 	elapsed = ns - kvm->arch.last_tsc_nsec;
 
-	/* n.b - signed multiplication and division required */
-	usdiff = data - kvm->arch.last_tsc_write;
+	if (vcpu->arch.virtual_tsc_khz) {
+		/* n.b - signed multiplication and division required */
+		usdiff = data - kvm->arch.last_tsc_write;
 #ifdef CONFIG_X86_64
-	usdiff = (usdiff * 1000) / vcpu->arch.virtual_tsc_khz;
+		usdiff = (usdiff * 1000) / vcpu->arch.virtual_tsc_khz;
 #else
-	/* do_div() only does unsigned */
-	asm("idivl %2; xor %%edx, %%edx"
-	    : "=A"(usdiff)
-	    : "A"(usdiff * 1000), "rm"(vcpu->arch.virtual_tsc_khz));
+		/* do_div() only does unsigned */
+		asm("idivl %2; xor %%edx, %%edx"
+		: "=A"(usdiff)
+		: "A"(usdiff * 1000), "rm"(vcpu->arch.virtual_tsc_khz));
 #endif
-	do_div(elapsed, 1000);
-	usdiff -= elapsed;
-	if (usdiff < 0)
-		usdiff = -usdiff;
+		do_div(elapsed, 1000);
+		usdiff -= elapsed;
+		if (usdiff < 0)
+			usdiff = -usdiff;
+	} else
+		usdiff = USEC_PER_SEC; /* disable TSC match window below */
 
 	/*
 	 * Special case: TSC write with a small delta (1 second) of virtual
@@ -2483,6 +2488,7 @@ int kvm_dev_ioctl_check_extension(long ext)
 	case KVM_CAP_ASSIGN_DEV_IRQ:
 	case KVM_CAP_IRQFD:
 	case KVM_CAP_IOEVENTFD:
+	case KVM_CAP_IOEVENTFD_PV_MMIO:
 	case KVM_CAP_PIT2:
 	case KVM_CAP_PIT_STATE2:
 	case KVM_CAP_SET_IDENTITY_MAP_ADDR:
@@ -2697,7 +2703,7 @@ static int kvm_vcpu_ioctl_set_lapic(struct kvm_vcpu *vcpu,
 static int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu,
 				    struct kvm_interrupt *irq)
 {
-	if (irq->irq < 0 || irq->irq >= KVM_NR_INTERRUPTS)
+	if (irq->irq >= KVM_NR_INTERRUPTS)
 		return -EINVAL;
 	if (irqchip_in_kernel(vcpu->kvm))
 		return -ENXIO;
@@ -2820,10 +2826,9 @@ static void kvm_vcpu_ioctl_x86_get_vcpu_events(struct kvm_vcpu *vcpu,
 	events->nmi.masked = kvm_x86_ops->get_nmi_mask(vcpu);
 	events->nmi.pad = 0;
 
-	events->sipi_vector = vcpu->arch.sipi_vector;
+	events->sipi_vector = 0; /* never valid when reporting to user space */
 
 	events->flags = (KVM_VCPUEVENT_VALID_NMI_PENDING
-			 | KVM_VCPUEVENT_VALID_SIPI_VECTOR
 			 | KVM_VCPUEVENT_VALID_SHADOW);
 	memset(&events->reserved, 0, sizeof(events->reserved));
 }
@@ -2854,8 +2859,9 @@ static int kvm_vcpu_ioctl_x86_set_vcpu_events(struct kvm_vcpu *vcpu,
 		vcpu->arch.nmi_pending = events->nmi.pending;
 	kvm_x86_ops->set_nmi_mask(vcpu, events->nmi.masked);
 
-	if (events->flags & KVM_VCPUEVENT_VALID_SIPI_VECTOR)
-		vcpu->arch.sipi_vector = events->sipi_vector;
+	if (events->flags & KVM_VCPUEVENT_VALID_SIPI_VECTOR &&
+	    kvm_vcpu_has_lapic(vcpu))
+		vcpu->arch.apic->sipi_vector = events->sipi_vector;
 
 	kvm_make_request(KVM_REQ_EVENT, vcpu);
 
@@ -5710,6 +5716,12 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
 	}
 
 	if (kvm_check_request(KVM_REQ_EVENT, vcpu) || req_int_win) {
+		kvm_apic_accept_events(vcpu);
+		if (vcpu->arch.mp_state == KVM_MP_STATE_INIT_RECEIVED) {
+			r = 1;
+			goto out;
+		}
+
 		inject_pending_event(vcpu);
 
 		/* enable NMI/IRQ window open exits if needed */
@@ -5844,16 +5856,6 @@ static int __vcpu_run(struct kvm_vcpu *vcpu)
 	int r;
 	struct kvm *kvm = vcpu->kvm;
 
-	if (unlikely(vcpu->arch.mp_state == KVM_MP_STATE_SIPI_RECEIVED)) {
-		pr_debug("vcpu %d received sipi with vector # %x\n",
-			 vcpu->vcpu_id, vcpu->arch.sipi_vector);
-		kvm_lapic_reset(vcpu);
-		r = kvm_vcpu_reset(vcpu);
-		if (r)
-			return r;
-		vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
-	}
-
 	vcpu->srcu_idx = srcu_read_lock(&kvm->srcu);
 	r = vapic_enter(vcpu);
 	if (r) {
@@ -5870,8 +5872,8 @@ static int __vcpu_run(struct kvm_vcpu *vcpu)
 			srcu_read_unlock(&kvm->srcu, vcpu->srcu_idx);
 			kvm_vcpu_block(vcpu);
 			vcpu->srcu_idx = srcu_read_lock(&kvm->srcu);
-			if (kvm_check_request(KVM_REQ_UNHALT, vcpu))
-			{
+			if (kvm_check_request(KVM_REQ_UNHALT, vcpu)) {
+				kvm_apic_accept_events(vcpu);
 				switch(vcpu->arch.mp_state) {
 				case KVM_MP_STATE_HALTED:
 					vcpu->arch.mp_state =
@@ -5879,7 +5881,8 @@ static int __vcpu_run(struct kvm_vcpu *vcpu)
 				case KVM_MP_STATE_RUNNABLE:
 					vcpu->arch.apf.halted = false;
 					break;
-				case KVM_MP_STATE_SIPI_RECEIVED:
+				case KVM_MP_STATE_INIT_RECEIVED:
+					break;
 				default:
 					r = -EINTR;
 					break;
@@ -6014,6 +6017,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 
 	if (unlikely(vcpu->arch.mp_state == KVM_MP_STATE_UNINITIALIZED)) {
 		kvm_vcpu_block(vcpu);
+		kvm_apic_accept_events(vcpu);
 		clear_bit(KVM_REQ_UNHALT, &vcpu->requests);
 		r = -EAGAIN;
 		goto out;
@@ -6170,6 +6174,7 @@ int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
 int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu,
 				    struct kvm_mp_state *mp_state)
 {
+	kvm_apic_accept_events(vcpu);
 	mp_state->mp_state = vcpu->arch.mp_state;
 	return 0;
 }
@@ -6177,7 +6182,15 @@ int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu,
 int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
 				    struct kvm_mp_state *mp_state)
 {
-	vcpu->arch.mp_state = mp_state->mp_state;
+	if (!kvm_vcpu_has_lapic(vcpu) &&
+	    mp_state->mp_state != KVM_MP_STATE_RUNNABLE)
+		return -EINVAL;
+
+	if (mp_state->mp_state == KVM_MP_STATE_SIPI_RECEIVED) {
+		vcpu->arch.mp_state = KVM_MP_STATE_INIT_RECEIVED;
+		set_bit(KVM_APIC_SIPI, &vcpu->arch.apic->pending_events);
+	} else
+		vcpu->arch.mp_state = mp_state->mp_state;
 	kvm_make_request(KVM_REQ_EVENT, vcpu);
 	return 0;
 }
@@ -6476,9 +6489,8 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
 	r = vcpu_load(vcpu);
 	if (r)
 		return r;
-	r = kvm_vcpu_reset(vcpu);
-	if (r == 0)
-		r = kvm_mmu_setup(vcpu);
+	kvm_vcpu_reset(vcpu);
+	r = kvm_mmu_setup(vcpu);
 	vcpu_put(vcpu);
 
 	return r;
@@ -6515,7 +6527,7 @@ void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
 	kvm_x86_ops->vcpu_free(vcpu);
 }
 
-static int kvm_vcpu_reset(struct kvm_vcpu *vcpu)
+void kvm_vcpu_reset(struct kvm_vcpu *vcpu)
 {
 	atomic_set(&vcpu->arch.nmi_queued, 0);
 	vcpu->arch.nmi_pending = 0;
@@ -6542,7 +6554,18 @@ static int kvm_vcpu_reset(struct kvm_vcpu *vcpu)
 	vcpu->arch.regs_avail = ~0;
 	vcpu->arch.regs_dirty = ~0;
 
-	return kvm_x86_ops->vcpu_reset(vcpu);
+	kvm_x86_ops->vcpu_reset(vcpu);
+}
+
+void kvm_vcpu_deliver_sipi_vector(struct kvm_vcpu *vcpu, unsigned int vector)
+{
+	struct kvm_segment cs;
+
+	kvm_get_segment(vcpu, &cs, VCPU_SREG_CS);
+	cs.selector = vector << 8;
+	cs.base = vector << 12;
+	kvm_set_segment(vcpu, &cs, VCPU_SREG_CS);
+	kvm_rip_write(vcpu, 0);
 }
 
 int kvm_arch_hardware_enable(void *garbage)
@@ -6904,24 +6927,21 @@ out_free:
 
 int kvm_arch_prepare_memory_region(struct kvm *kvm,
 				struct kvm_memory_slot *memslot,
-				struct kvm_memory_slot old,
 				struct kvm_userspace_memory_region *mem,
-				bool user_alloc)
+				enum kvm_mr_change change)
 {
-	int npages = memslot->npages;
-
 	/*
 	 * Only private memory slots need to be mapped here since
 	 * KVM_SET_MEMORY_REGION ioctl is no longer supported.
 	 */
-	if ((memslot->id >= KVM_USER_MEM_SLOTS) && npages && !old.npages) {
+	if ((memslot->id >= KVM_USER_MEM_SLOTS) && (change == KVM_MR_CREATE)) {
 		unsigned long userspace_addr;
 
 		/*
 		 * MAP_SHARED to prevent internal slot pages from being moved
 		 * by fork()/COW.
 		 */
-		userspace_addr = vm_mmap(NULL, 0, npages * PAGE_SIZE,
+		userspace_addr = vm_mmap(NULL, 0, memslot->npages * PAGE_SIZE,
 					 PROT_READ | PROT_WRITE,
 					 MAP_SHARED | MAP_ANONYMOUS, 0);
 
@@ -6936,17 +6956,17 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
 
 void kvm_arch_commit_memory_region(struct kvm *kvm,
 				struct kvm_userspace_memory_region *mem,
-				struct kvm_memory_slot old,
-				bool user_alloc)
+				const struct kvm_memory_slot *old,
+				enum kvm_mr_change change)
 {
 
-	int nr_mmu_pages = 0, npages = mem->memory_size >> PAGE_SHIFT;
+	int nr_mmu_pages = 0;
 
-	if ((mem->slot >= KVM_USER_MEM_SLOTS) && old.npages && !npages) {
+	if ((mem->slot >= KVM_USER_MEM_SLOTS) && (change == KVM_MR_DELETE)) {
 		int ret;
 
-		ret = vm_munmap(old.userspace_addr,
-				old.npages * PAGE_SIZE);
+		ret = vm_munmap(old->userspace_addr,
+				old->npages * PAGE_SIZE);
 		if (ret < 0)
 			printk(KERN_WARNING
 			       "kvm_vm_ioctl_set_memory_region: "
@@ -6963,14 +6983,14 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
 	 * Existing largepage mappings are destroyed here and new ones will
 	 * not be created until the end of the logging.
 	 */
-	if (npages && (mem->flags & KVM_MEM_LOG_DIRTY_PAGES))
+	if ((change != KVM_MR_DELETE) && (mem->flags & KVM_MEM_LOG_DIRTY_PAGES))
 		kvm_mmu_slot_remove_write_access(kvm, mem->slot);
 	/*
 	 * If memory slot is created, or moved, we need to clear all
 	 * mmio sptes.
 	 */
-	if (npages && old.base_gfn != mem->guest_phys_addr >> PAGE_SHIFT) {
-		kvm_mmu_zap_all(kvm);
+	if ((change == KVM_MR_CREATE) || (change == KVM_MR_MOVE)) {
+		kvm_mmu_zap_mmio_sptes(kvm);
 		kvm_reload_remote_mmus(kvm);
 	}
 }
@@ -6992,7 +7012,7 @@ int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu)
 	return (vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE &&
 		!vcpu->arch.apf.halted)
 		|| !list_empty_careful(&vcpu->async_pf.done)
-		|| vcpu->arch.mp_state == KVM_MP_STATE_SIPI_RECEIVED
+		|| kvm_apic_has_events(vcpu)
 		|| atomic_read(&vcpu->arch.nmi_queued) ||
 		(kvm_arch_interrupt_allowed(vcpu) &&
 		 kvm_cpu_has_interrupt(vcpu));
diff --git a/arch/x86/lguest/Kconfig b/arch/x86/lguest/Kconfig
index 29043d2..4a0890f 100644
--- a/arch/x86/lguest/Kconfig
+++ b/arch/x86/lguest/Kconfig
@@ -1,7 +1,6 @@
 config LGUEST_GUEST
 	bool "Lguest guest support"
-	select PARAVIRT
-	depends on X86_32
+	depends on X86_32 && PARAVIRT
 	select TTY
 	select VIRTUALIZATION
 	select VIRTIO
diff --git a/arch/x86/lib/usercopy_32.c b/arch/x86/lib/usercopy_32.c
index f0312d7..3eb18ac 100644
--- a/arch/x86/lib/usercopy_32.c
+++ b/arch/x86/lib/usercopy_32.c
@@ -689,9 +689,3 @@ _copy_from_user(void *to, const void __user *from, unsigned long n)
 	return n;
 }
 EXPORT_SYMBOL(_copy_from_user);
-
-void copy_from_user_overflow(void)
-{
-	WARN(1, "Buffer overflow detected!\n");
-}
-EXPORT_SYMBOL(copy_from_user_overflow);
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index 2b97525..fa8c02d 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -13,12 +13,12 @@
 #include <linux/perf_event.h>		/* perf_sw_event		*/
 #include <linux/hugetlb.h>		/* hstate_index_to_shift	*/
 #include <linux/prefetch.h>		/* prefetchw			*/
+#include <linux/context_tracking.h>	/* exception_enter(), ...	*/
 
 #include <asm/traps.h>			/* dotraplinkage, ...		*/
 #include <asm/pgalloc.h>		/* pgd_*(), ...			*/
 #include <asm/kmemcheck.h>		/* kmemcheck_*(), ...		*/
 #include <asm/fixmap.h>			/* VSYSCALL_START		*/
-#include <asm/context_tracking.h>	/* exception_enter(), ...	*/
 
 /*
  * Page fault error code bits:
@@ -1222,7 +1222,9 @@ good_area:
 dotraplinkage void __kprobes
 do_page_fault(struct pt_regs *regs, unsigned long error_code)
 {
-	exception_enter(regs);
+	enum ctx_state prev_state;
+
+	prev_state = exception_enter();
 	__do_page_fault(regs, error_code);
-	exception_exit(regs);
+	exception_exit(prev_state);
 }
diff --git a/arch/x86/mm/highmem_32.c b/arch/x86/mm/highmem_32.c
index 6f31ee5..252b8f5 100644
--- a/arch/x86/mm/highmem_32.c
+++ b/arch/x86/mm/highmem_32.c
@@ -137,5 +137,4 @@ void __init set_highmem_pages_init(void)
 		add_highpages_with_active_regions(nid, zone_start_pfn,
 				 zone_end_pfn);
 	}
-	totalram_pages += totalhigh_pages;
 }
diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c
index 59b7fc4..fdc5dca 100644
--- a/arch/x86/mm/init.c
+++ b/arch/x86/mm/init.c
@@ -515,11 +515,8 @@ void free_init_pages(char *what, unsigned long begin, unsigned long end)
 	printk(KERN_INFO "Freeing %s: %luk freed\n", what, (end - begin) >> 10);
 
 	for (; addr < end; addr += PAGE_SIZE) {
-		ClearPageReserved(virt_to_page(addr));
-		init_page_count(virt_to_page(addr));
 		memset((void *)addr, POISON_FREE_INITMEM, PAGE_SIZE);
-		free_page(addr);
-		totalram_pages++;
+		free_reserved_page(virt_to_page(addr));
 	}
 #endif
 }
diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c
index 2d19001..3ac7e31 100644
--- a/arch/x86/mm/init_32.c
+++ b/arch/x86/mm/init_32.c
@@ -427,14 +427,6 @@ static void __init permanent_kmaps_init(pgd_t *pgd_base)
 	pkmap_page_table = pte;
 }
 
-static void __init add_one_highpage_init(struct page *page)
-{
-	ClearPageReserved(page);
-	init_page_count(page);
-	__free_page(page);
-	totalhigh_pages++;
-}
-
 void __init add_highpages_with_active_regions(int nid,
 			 unsigned long start_pfn, unsigned long end_pfn)
 {
@@ -448,7 +440,7 @@ void __init add_highpages_with_active_regions(int nid,
 					      start_pfn, end_pfn);
 		for ( ; pfn < e_pfn; pfn++)
 			if (pfn_valid(pfn))
-				add_one_highpage_init(pfn_to_page(pfn));
+				free_highmem_page(pfn_to_page(pfn));
 	}
 }
 #else
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index 474e28f..caad9a0 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -1011,14 +1011,12 @@ remove_pagetable(unsigned long start, unsigned long end, bool direct)
 	flush_tlb_all();
 }
 
-void __ref vmemmap_free(struct page *memmap, unsigned long nr_pages)
+void __ref vmemmap_free(unsigned long start, unsigned long end)
 {
-	unsigned long start = (unsigned long)memmap;
-	unsigned long end = (unsigned long)(memmap + nr_pages);
-
 	remove_pagetable(start, end, false);
 }
 
+#ifdef CONFIG_MEMORY_HOTREMOVE
 static void __meminit
 kernel_physical_mapping_remove(unsigned long start, unsigned long end)
 {
@@ -1028,7 +1026,6 @@ kernel_physical_mapping_remove(unsigned long start, unsigned long end)
 	remove_pagetable(start, end, true);
 }
 
-#ifdef CONFIG_MEMORY_HOTREMOVE
 int __ref arch_remove_memory(u64 start, u64 size)
 {
 	unsigned long start_pfn = start >> PAGE_SHIFT;
@@ -1067,10 +1064,9 @@ void __init mem_init(void)
 
 	/* clear_bss() already clear the empty_zero_page */
 
-	reservedpages = 0;
-
-	/* this will put all low memory onto the freelists */
 	register_page_bootmem_info();
+
+	/* this will put all memory onto the freelists */
 	totalram_pages = free_all_bootmem();
 
 	absent_pages = absent_pages_in_range(0, max_pfn);
@@ -1285,18 +1281,17 @@ static long __meminitdata addr_start, addr_end;
 static void __meminitdata *p_start, *p_end;
 static int __meminitdata node_start;
 
-int __meminit
-vmemmap_populate(struct page *start_page, unsigned long size, int node)
+static int __meminit vmemmap_populate_hugepages(unsigned long start,
+						unsigned long end, int node)
 {
-	unsigned long addr = (unsigned long)start_page;
-	unsigned long end = (unsigned long)(start_page + size);
+	unsigned long addr;
 	unsigned long next;
 	pgd_t *pgd;
 	pud_t *pud;
 	pmd_t *pmd;
 
-	for (; addr < end; addr = next) {
-		void *p = NULL;
+	for (addr = start; addr < end; addr = next) {
+		next = pmd_addr_end(addr, end);
 
 		pgd = vmemmap_pgd_populate(addr, node);
 		if (!pgd)
@@ -1306,31 +1301,14 @@ vmemmap_populate(struct page *start_page, unsigned long size, int node)
 		if (!pud)
 			return -ENOMEM;
 
-		if (!cpu_has_pse) {
-			next = (addr + PAGE_SIZE) & PAGE_MASK;
-			pmd = vmemmap_pmd_populate(pud, addr, node);
-
-			if (!pmd)
-				return -ENOMEM;
-
-			p = vmemmap_pte_populate(pmd, addr, node);
+		pmd = pmd_offset(pud, addr);
+		if (pmd_none(*pmd)) {
+			void *p;
 
-			if (!p)
-				return -ENOMEM;
-
-			addr_end = addr + PAGE_SIZE;
-			p_end = p + PAGE_SIZE;
-		} else {
-			next = pmd_addr_end(addr, end);
-
-			pmd = pmd_offset(pud, addr);
-			if (pmd_none(*pmd)) {
+			p = vmemmap_alloc_block_buf(PMD_SIZE, node);
+			if (p) {
 				pte_t entry;
 
-				p = vmemmap_alloc_block_buf(PMD_SIZE, node);
-				if (!p)
-					return -ENOMEM;
-
 				entry = pfn_pte(__pa(p) >> PAGE_SHIFT,
 						PAGE_KERNEL_LARGE);
 				set_pmd(pmd, __pmd(pte_val(entry)));
@@ -1347,15 +1325,32 @@ vmemmap_populate(struct page *start_page, unsigned long size, int node)
 
 				addr_end = addr + PMD_SIZE;
 				p_end = p + PMD_SIZE;
-			} else
-				vmemmap_verify((pte_t *)pmd, node, addr, next);
+				continue;
+			}
+		} else if (pmd_large(*pmd)) {
+			vmemmap_verify((pte_t *)pmd, node, addr, next);
+			continue;
 		}
-
+		pr_warn_once("vmemmap: falling back to regular page backing\n");
+		if (vmemmap_populate_basepages(addr, next, node))
+			return -ENOMEM;
 	}
-	sync_global_pgds((unsigned long)start_page, end - 1);
 	return 0;
 }
 
+int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node)
+{
+	int err;
+
+	if (cpu_has_pse)
+		err = vmemmap_populate_hugepages(start, end, node);
+	else
+		err = vmemmap_populate_basepages(start, end, node);
+	if (!err)
+		sync_global_pgds(start, end - 1);
+	return err;
+}
+
 #if defined(CONFIG_MEMORY_HOTPLUG_SPARSE) && defined(CONFIG_HAVE_BOOTMEM_INFO_NODE)
 void register_page_bootmem_memmap(unsigned long section_nr,
 				  struct page *start_page, unsigned long size)
diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
index 78fe3f1..9a1e658 100644
--- a/arch/x86/mm/ioremap.c
+++ b/arch/x86/mm/ioremap.c
@@ -282,12 +282,7 @@ void iounmap(volatile void __iomem *addr)
 	   in parallel. Reuse of the virtual address is prevented by
 	   leaving it in the global lists until we're done with it.
 	   cpa takes care of the direct mappings. */
-	read_lock(&vmlist_lock);
-	for (p = vmlist; p; p = p->next) {
-		if (p->addr == (void __force *)addr)
-			break;
-	}
-	read_unlock(&vmlist_lock);
+	p = find_vm_area((void __force *)addr);
 
 	if (!p) {
 		printk(KERN_ERR "iounmap: bad address %p\n", addr);
diff --git a/arch/x86/mm/mmap.c b/arch/x86/mm/mmap.c
index 845df68..62c29a5 100644
--- a/arch/x86/mm/mmap.c
+++ b/arch/x86/mm/mmap.c
@@ -115,10 +115,8 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
 	if (mmap_is_legacy()) {
 		mm->mmap_base = mmap_legacy_base();
 		mm->get_unmapped_area = arch_get_unmapped_area;
-		mm->unmap_area = arch_unmap_area;
 	} else {
 		mm->mmap_base = mmap_base();
 		mm->get_unmapped_area = arch_get_unmapped_area_topdown;
-		mm->unmap_area = arch_unmap_area_topdown;
 	}
 }
diff --git a/arch/x86/mm/numa.c b/arch/x86/mm/numa.c
index 72fe01e..a71c4e2 100644
--- a/arch/x86/mm/numa.c
+++ b/arch/x86/mm/numa.c
@@ -114,14 +114,11 @@ void numa_clear_node(int cpu)
  */
 void __init setup_node_to_cpumask_map(void)
 {
-	unsigned int node, num = 0;
+	unsigned int node;
 
 	/* setup nr_node_ids if not done yet */
-	if (nr_node_ids == MAX_NUMNODES) {
-		for_each_node_mask(node, node_possible_map)
-			num = node;
-		nr_node_ids = num + 1;
-	}
+	if (nr_node_ids == MAX_NUMNODES)
+		setup_nr_node_ids();
 
 	/* allocate the map */
 	for (node = 0; node < nr_node_ids; node++)
diff --git a/arch/x86/mm/pageattr-test.c b/arch/x86/mm/pageattr-test.c
index b008656..9346108 100644
--- a/arch/x86/mm/pageattr-test.c
+++ b/arch/x86/mm/pageattr-test.c
@@ -130,13 +130,12 @@ static int pageattr_test(void)
 	}
 
 	failed += print_split(&sa);
-	srandom32(100);
 
 	for (i = 0; i < NTEST; i++) {
-		unsigned long pfn = random32() % max_pfn_mapped;
+		unsigned long pfn = prandom_u32() % max_pfn_mapped;
 
 		addr[i] = (unsigned long)__va(pfn << PAGE_SHIFT);
-		len[i] = random32() % 100;
+		len[i] = prandom_u32() % 100;
 		len[i] = min_t(unsigned long, len[i], max_pfn_mapped - pfn - 1);
 
 		if (len[i] == 0)
diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
index 3cbe4538..f66b540 100644
--- a/arch/x86/net/bpf_jit_comp.c
+++ b/arch/x86/net/bpf_jit_comp.c
@@ -725,17 +725,12 @@ cond_branch:			f_offset = addrs[i + filter[i].jf] - addrs[i];
 		}
 		oldproglen = proglen;
 	}
+
 	if (bpf_jit_enable > 1)
-		pr_err("flen=%d proglen=%u pass=%d image=%p\n",
-		       flen, proglen, pass, image);
+		bpf_jit_dump(flen, proglen, pass, image);
 
 	if (image) {
-		if (bpf_jit_enable > 1)
-			print_hex_dump(KERN_ERR, "JIT code: ", DUMP_PREFIX_ADDRESS,
-				       16, 1, image, proglen, false);
-
 		bpf_flush_icache(image, image + proglen);
-
 		fp->bpf_func = (void *)image;
 	}
 out:
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index 5f2ecaf..4f65e1d 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -316,10 +316,17 @@ static void __init do_add_efi_memmap(void)
 		int e820_type;
 
 		switch (md->type) {
-		case EFI_LOADER_CODE:
-		case EFI_LOADER_DATA:
 		case EFI_BOOT_SERVICES_CODE:
 		case EFI_BOOT_SERVICES_DATA:
+			/* EFI_BOOT_SERVICES_{CODE,DATA} needs to be mapped */
+			if (md->attribute & EFI_MEMORY_WB)
+				e820_type = E820_RAM;
+			else
+				e820_type = E820_RESERVED;
+			e820_add_region(start, size, e820_type);
+			continue;
+		case EFI_LOADER_CODE:
+		case EFI_LOADER_DATA:
 		case EFI_CONVENTIONAL_MEMORY:
 			if (md->attribute & EFI_MEMORY_WB)
 				e820_type = E820_RAM;
@@ -344,7 +351,7 @@ static void __init do_add_efi_memmap(void)
 			e820_type = E820_RESERVED;
 			break;
 		}
-		e820_add_region(start, size, e820_type);
+		e820_add_limit_region(start, size, e820_type);
 	}
 	sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
 }
@@ -451,6 +458,8 @@ void __init efi_free_boot_services(void)
 		    md->type != EFI_BOOT_SERVICES_DATA)
 			continue;
 
+		e820_adjust_region(&start, &size);
+
 		/* Could not reserve boot area */
 		if (!size)
 			continue;
diff --git a/arch/x86/platform/uv/uv_time.c b/arch/x86/platform/uv/uv_time.c
index 98718f6..5c86786 100644
--- a/arch/x86/platform/uv/uv_time.c
+++ b/arch/x86/platform/uv/uv_time.c
@@ -159,10 +159,9 @@ static __init int uv_rtc_allocate_timers(void)
 {
 	int cpu;
 
-	blade_info = kmalloc(uv_possible_blades * sizeof(void *), GFP_KERNEL);
+	blade_info = kzalloc(uv_possible_blades * sizeof(void *), GFP_KERNEL);
 	if (!blade_info)
 		return -ENOMEM;
-	memset(blade_info, 0, uv_possible_blades * sizeof(void *));
 
 	for_each_present_cpu(cpu) {
 		int nid = cpu_to_node(cpu);
diff --git a/arch/x86/syscalls/syscall_32.tbl b/arch/x86/syscalls/syscall_32.tbl
index e6d55f0..d0d59bf 100644
--- a/arch/x86/syscalls/syscall_32.tbl
+++ b/arch/x86/syscalls/syscall_32.tbl
@@ -43,7 +43,7 @@
 34	i386	nice			sys_nice
 35	i386	ftime
 36	i386	sync			sys_sync
-37	i386	kill			sys_kill			sys32_kill
+37	i386	kill			sys_kill
 38	i386	rename			sys_rename
 39	i386	mkdir			sys_mkdir
 40	i386	rmdir			sys_rmdir
@@ -123,7 +123,7 @@
 114	i386	wait4			sys_wait4			compat_sys_wait4
 115	i386	swapoff			sys_swapoff
 116	i386	sysinfo			sys_sysinfo			compat_sys_sysinfo
-117	i386	ipc			sys_ipc				sys32_ipc
+117	i386	ipc			sys_ipc				compat_sys_ipc
 118	i386	fsync			sys_fsync
 119	i386	sigreturn		sys_sigreturn			stub32_sigreturn
 120	i386	clone			sys_clone			stub32_clone
@@ -131,7 +131,7 @@
 122	i386	uname			sys_newuname
 123	i386	modify_ldt		sys_modify_ldt
 124	i386	adjtimex		sys_adjtimex			compat_sys_adjtimex
-125	i386	mprotect		sys_mprotect			sys32_mprotect
+125	i386	mprotect		sys_mprotect
 126	i386	sigprocmask		sys_sigprocmask			compat_sys_sigprocmask
 127	i386	create_module
 128	i386	init_module		sys_init_module
@@ -193,7 +193,7 @@
 184	i386	capget			sys_capget
 185	i386	capset			sys_capset
 186	i386	sigaltstack		sys_sigaltstack			compat_sys_sigaltstack
-187	i386	sendfile		sys_sendfile			sys32_sendfile
+187	i386	sendfile		sys_sendfile			compat_sys_sendfile
 188	i386	getpmsg
 189	i386	putpmsg
 190	i386	vfork			sys_vfork			stub32_vfork
@@ -259,7 +259,7 @@
 250	i386	fadvise64		sys_fadvise64			sys32_fadvise64
 # 251 is available for reuse (was briefly sys_set_zone_reclaim)
 252	i386	exit_group		sys_exit_group
-253	i386	lookup_dcookie		sys_lookup_dcookie		sys32_lookup_dcookie
+253	i386	lookup_dcookie		sys_lookup_dcookie		compat_sys_lookup_dcookie
 254	i386	epoll_create		sys_epoll_create
 255	i386	epoll_ctl		sys_epoll_ctl
 256	i386	epoll_wait		sys_epoll_wait
diff --git a/arch/x86/um/tls_32.c b/arch/x86/um/tls_32.c
index 5f5feff..80ffa5b 100644
--- a/arch/x86/um/tls_32.c
+++ b/arch/x86/um/tls_32.c
@@ -5,6 +5,7 @@
 
 #include <linux/percpu.h>
 #include <linux/sched.h>
+#include <linux/syscalls.h>
 #include <asm/uaccess.h>
 #include <os.h>
 #include <skas.h>
@@ -274,7 +275,7 @@ clear:
 	goto out;
 }
 
-int sys_set_thread_area(struct user_desc __user *user_desc)
+SYSCALL_DEFINE1(set_thread_area, struct user_desc __user *, user_desc)
 {
 	struct user_desc info;
 	int idx, ret;
@@ -322,7 +323,7 @@ int ptrace_set_thread_area(struct task_struct *child, int idx,
 	return set_tls_entry(child, &info, idx, 0);
 }
 
-int sys_get_thread_area(struct user_desc __user *user_desc)
+SYSCALL_DEFINE1(get_thread_area, struct user_desc __user *, user_desc)
 {
 	struct user_desc info;
 	int idx, ret;
diff --git a/arch/x86/xen/Kconfig b/arch/x86/xen/Kconfig
index 131dacd..47316b9 100644
--- a/arch/x86/xen/Kconfig
+++ b/arch/x86/xen/Kconfig
@@ -4,7 +4,7 @@
 
 config XEN
 	bool "Xen guest support"
-	select PARAVIRT
+	depends on PARAVIRT
 	select PARAVIRT_CLOCK
 	select XEN_HAVE_PVMMU
 	depends on X86_64 || (X86_32 && X86_PAE && !X86_VISWS)
@@ -51,3 +51,11 @@ config XEN_DEBUG_FS
 	  Enable statistics output and various tuning options in debugfs.
 	  Enabling this option may incur a significant performance overhead.
 
+config XEN_X86_PVH
+	bool "Support for running as a PVH guest"
+	depends on X86_64 && XEN
+	default n
+	help
+	   This option enables support for running as a PVH guest (PV guest
+	   using hardware extensions) under a suitably capable hypervisor.
+	   If unsure, say N.
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index c8e1c7b..a7ee39f 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -106,6 +106,9 @@ RESERVE_BRK(shared_info_page_brk, PAGE_SIZE);
 __read_mostly int xen_have_vector_callback;
 EXPORT_SYMBOL_GPL(xen_have_vector_callback);
 
+#define xen_pvh_domain() (xen_pv_domain() && \
+			  xen_feature(XENFEAT_auto_translated_physmap) && \
+			  xen_have_vector_callback)
 /*
  * Point at some empty memory to start with. We map the real shared_info
  * page as soon as fixmap is up and running.
@@ -219,8 +222,9 @@ static void __init xen_banner(void)
 	struct xen_extraversion extra;
 	HYPERVISOR_xen_version(XENVER_extraversion, &extra);
 
-	printk(KERN_INFO "Booting paravirtualized kernel on %s\n",
-	       pv_info.name);
+	pr_info("Booting paravirtualized kernel %son %s\n",
+		xen_feature(XENFEAT_auto_translated_physmap) ?
+			"with PVH extensions " : "", pv_info.name);
 	printk(KERN_INFO "Xen version: %d.%d%s%s\n",
 	       version >> 16, version & 0xffff, extra.extraversion,
 	       xen_feature(XENFEAT_mmu_pt_update_preserve_ad) ? " (preserve-AD)" : "");
@@ -288,12 +292,15 @@ static void xen_cpuid(unsigned int *ax, unsigned int *bx,
 		break;
 	}
 
-	asm(XEN_EMULATE_PREFIX "cpuid"
-		: "=a" (*ax),
-		  "=b" (*bx),
-		  "=c" (*cx),
-		  "=d" (*dx)
-		: "0" (*ax), "2" (*cx));
+	if (xen_pvh_domain())
+		native_cpuid(ax, bx, cx, dx);
+	else
+		asm(XEN_EMULATE_PREFIX "cpuid"
+			: "=a" (*ax),
+			"=b" (*bx),
+			"=c" (*cx),
+			"=d" (*dx)
+			: "0" (*ax), "2" (*cx));
 
 	*bx &= maskebx;
 	*cx &= maskecx;
@@ -1076,6 +1083,10 @@ void xen_setup_shared_info(void)
 		HYPERVISOR_shared_info =
 			(struct shared_info *)__va(xen_start_info->shared_info);
 
+	/* PVH TBD/FIXME: vcpu info placement in phase 2 */
+	if (xen_pvh_domain())
+		return;
+
 #ifndef CONFIG_SMP
 	/* In UP this is as good a place as any to set up shared info */
 	xen_setup_vcpu_info_placement();
@@ -1313,6 +1324,11 @@ static const struct machine_ops xen_machine_ops __initconst = {
  */
 static void __init xen_setup_stackprotector(void)
 {
+	/* PVH TBD/FIXME: investigate setup_stack_canary_segment */
+	if (xen_feature(XENFEAT_auto_translated_physmap)) {
+		switch_to_new_gdt(0);
+		return;
+	}
 	pv_cpu_ops.write_gdt_entry = xen_write_gdt_entry_boot;
 	pv_cpu_ops.load_gdt = xen_load_gdt_boot;
 
@@ -1323,6 +1339,19 @@ static void __init xen_setup_stackprotector(void)
 	pv_cpu_ops.load_gdt = xen_load_gdt;
 }
 
+static void __init xen_pvh_early_guest_init(void)
+{
+	if (xen_feature(XENFEAT_hvm_callback_vector))
+		xen_have_vector_callback = 1;
+
+#ifdef CONFIG_X86_32
+	if (xen_feature(XENFEAT_auto_translated_physmap)) {
+		xen_raw_printk("ERROR: 32bit PVH guests are not supported\n");
+		BUG();
+	}
+#endif
+}
+
 /* First C function to be called on Xen boot */
 asmlinkage void __init xen_start_kernel(void)
 {
@@ -1334,13 +1363,18 @@ asmlinkage void __init xen_start_kernel(void)
 
 	xen_domain_type = XEN_PV_DOMAIN;
 
+	xen_setup_features();
+	xen_pvh_early_guest_init();
 	xen_setup_machphys_mapping();
 
 	/* Install Xen paravirt ops */
 	pv_info = xen_info;
 	pv_init_ops = xen_init_ops;
-	pv_cpu_ops = xen_cpu_ops;
 	pv_apic_ops = xen_apic_ops;
+	if (xen_pvh_domain())
+		pv_cpu_ops.cpuid = xen_cpuid;
+	else
+		pv_cpu_ops = xen_cpu_ops;
 
 	x86_init.resources.memory_setup = xen_memory_setup;
 	x86_init.oem.arch_setup = xen_arch_setup;
@@ -1372,8 +1406,6 @@ asmlinkage void __init xen_start_kernel(void)
 	/* Work out if we support NX */
 	x86_configure_nx();
 
-	xen_setup_features();
-
 	/* Get mfn list */
 	if (!xen_feature(XENFEAT_auto_translated_physmap))
 		xen_build_dynamic_phys_to_machine();
@@ -1451,14 +1483,18 @@ asmlinkage void __init xen_start_kernel(void)
 	/* set the limit of our address space */
 	xen_reserve_top();
 
-	/* We used to do this in xen_arch_setup, but that is too late on AMD
-	 * were early_cpu_init (run before ->arch_setup()) calls early_amd_init
-	 * which pokes 0xcf8 port.
-	 */
-	set_iopl.iopl = 1;
-	rc = HYPERVISOR_physdev_op(PHYSDEVOP_set_iopl, &set_iopl);
-	if (rc != 0)
-		xen_raw_printk("physdev_op failed %d\n", rc);
+	/* PVH: runs at default kernel iopl of 0 */
+	if (!xen_pvh_domain()) {
+		/*
+		 * We used to do this in xen_arch_setup, but that is too late
+		 * on AMD were early_cpu_init (run before ->arch_setup()) calls
+		 * early_amd_init which pokes 0xcf8 port.
+		 */
+		set_iopl.iopl = 1;
+		rc = HYPERVISOR_physdev_op(PHYSDEVOP_set_iopl, &set_iopl);
+		if (rc != 0)
+			xen_raw_printk("physdev_op failed %d\n", rc);
+	}
 
 #ifdef CONFIG_X86_32
 	/* set up basic CPUID stuff */
@@ -1526,6 +1562,8 @@ asmlinkage void __init xen_start_kernel(void)
 }
 
 void __ref xen_hvm_init_shared_info(void)
+/* Use a pfn in RAM, may move to MMIO before kexec.
+ * This function also called for PVH dom0 */
 {
 	int cpu;
 	struct xen_add_to_physmap xatp;
diff --git a/arch/x86/xen/irq.c b/arch/x86/xen/irq.c
index 01a4dc0..fcbe56a 100644
--- a/arch/x86/xen/irq.c
+++ b/arch/x86/xen/irq.c
@@ -5,6 +5,7 @@
 #include <xen/interface/xen.h>
 #include <xen/interface/sched.h>
 #include <xen/interface/vcpu.h>
+#include <xen/features.h>
 #include <xen/events.h>
 
 #include <asm/xen/hypercall.h>
@@ -129,6 +130,8 @@ static const struct pv_irq_ops xen_irq_ops __initconst = {
 
 void __init xen_init_irq_ops(void)
 {
-	pv_irq_ops = xen_irq_ops;
+	/* For PVH we use default pv_irq_ops settings */
+	if (!xen_feature(XENFEAT_hvm_callback_vector))
+		pv_irq_ops = xen_irq_ops;
 	x86_init.irqs.intr_init = xen_init_IRQ;
 }
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
index 6afbb2c..0faa744 100644
--- a/arch/x86/xen/mmu.c
+++ b/arch/x86/xen/mmu.c
@@ -74,6 +74,7 @@
 #include <xen/interface/version.h>
 #include <xen/interface/memory.h>
 #include <xen/hvc-console.h>
+#include <xen/balloon.h>
 
 #include "multicalls.h"
 #include "mmu.h"
@@ -1207,6 +1208,8 @@ static void __init xen_pagetable_init(void)
 #endif
 	paging_init();
 	xen_setup_shared_info();
+	if (xen_feature(XENFEAT_auto_translated_physmap))
+		return;
 #ifdef CONFIG_X86_64
 	if (!xen_feature(XENFEAT_auto_translated_physmap)) {
 		unsigned long new_mfn_list;
@@ -1491,7 +1494,8 @@ static int xen_pgd_alloc(struct mm_struct *mm)
 
 		if (user_pgd != NULL) {
 			user_pgd[pgd_index(VSYSCALL_START)] =
-				__pgd(__pa(level3_user_vsyscall) | _PAGE_TABLE);
+				__pgd(__pa_symbol(level3_user_vsyscall) |
+				      _PAGE_TABLE);
 			ret = 0;
 		}
 
@@ -1556,6 +1560,10 @@ static void __init xen_set_pte_init(pte_t *ptep, pte_t pte)
 static void pin_pagetable_pfn(unsigned cmd, unsigned long pfn)
 {
 	struct mmuext_op op;
+
+	if (xen_feature(XENFEAT_writable_page_tables))
+		return;
+
 	op.cmd = cmd;
 	op.arg1.mfn = pfn_to_mfn(pfn);
 	if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF))
@@ -1748,14 +1756,22 @@ static void *m2v(phys_addr_t maddr)
 }
 
 /* Set the page permissions on an identity-mapped pages */
-static void set_page_prot(void *addr, pgprot_t prot)
+static void set_page_prot_flags(void *addr, pgprot_t prot, unsigned long flags)
 {
 	unsigned long pfn = __pa(addr) >> PAGE_SHIFT;
 	pte_t pte = pfn_pte(pfn, prot);
 
-	if (HYPERVISOR_update_va_mapping((unsigned long)addr, pte, 0))
+	/* recall for PVH, page tables are native. */
+	if (xen_feature(XENFEAT_auto_translated_physmap))
+		return;
+
+	if (HYPERVISOR_update_va_mapping((unsigned long)addr, pte, flags))
 		BUG();
 }
+static void set_page_prot(void *addr, pgprot_t prot)
+{
+	return set_page_prot_flags(addr, prot, UVMF_NONE);
+}
 #ifdef CONFIG_X86_32
 static void __init xen_map_identity_early(pmd_t *pmd, unsigned long max_pfn)
 {
@@ -1830,6 +1846,9 @@ static void convert_pfn_mfn(void *v)
 	pte_t *pte = v;
 	int i;
 
+	if (xen_feature(XENFEAT_auto_translated_physmap))
+		return;
+
 	/* All levels are converted the same way, so just treat them
 	   as ptes. */
 	for (i = 0; i < PTRS_PER_PTE; i++)
@@ -1839,16 +1858,17 @@ static void __init check_pt_base(unsigned long *pt_base, unsigned long *pt_end,
 				 unsigned long addr)
 {
 	if (*pt_base == PFN_DOWN(__pa(addr))) {
-		set_page_prot((void *)addr, PAGE_KERNEL);
+		set_page_prot_flags((void *)addr, PAGE_KERNEL, UVMF_INVLPG);
 		clear_page((void *)addr);
 		(*pt_base)++;
 	}
 	if (*pt_end == PFN_DOWN(__pa(addr))) {
-		set_page_prot((void *)addr, PAGE_KERNEL);
+		set_page_prot_flags((void *)addr, PAGE_KERNEL, UVMF_INVLPG);
 		clear_page((void *)addr);
 		(*pt_end)--;
 	}
 }
+
 /*
  * Set up the initial kernel pagetable.
  *
@@ -1859,6 +1879,7 @@ static void __init check_pt_base(unsigned long *pt_base, unsigned long *pt_end,
  * but that's enough to get __va working.  We need to fill in the rest
  * of the physical mapping once some sort of allocator has been set
  * up.
+ * NOTE: for PVH, the page tables are native.
  */
 void __init xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn)
 {
@@ -1936,10 +1957,13 @@ void __init xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn)
 	 * structure to attach it to, so make sure we just set kernel
 	 * pgd.
 	 */
-	xen_mc_batch();
-	__xen_write_cr3(true, __pa(init_level4_pgt));
-	xen_mc_issue(PARAVIRT_LAZY_CPU);
-
+	if (xen_feature(XENFEAT_writable_page_tables)) {
+		native_write_cr3(__pa_symbol(init_level4_pgt));
+	} else {
+		xen_mc_batch();
+		__xen_write_cr3(true, __pa_symbol(init_level4_pgt));
+		xen_mc_issue(PARAVIRT_LAZY_CPU);
+	}
 	/* We can't that easily rip out L3 and L2, as the Xen pagetables are
 	 * set out this way: [L4], [L1], [L2], [L3], [L1], [L1] ...  for
 	 * the initial domain. For guests using the toolstack, they are in:
@@ -1960,10 +1984,10 @@ static RESERVE_BRK_ARRAY(pmd_t, swapper_kernel_pmd, PTRS_PER_PMD);
 
 static void __init xen_write_cr3_init(unsigned long cr3)
 {
-	unsigned long pfn = PFN_DOWN(__pa(swapper_pg_dir));
+	unsigned long pfn = PFN_DOWN(__pa_symbol(swapper_pg_dir));
 
-	BUG_ON(read_cr3() != __pa(initial_page_table));
-	BUG_ON(cr3 != __pa(swapper_pg_dir));
+	BUG_ON(read_cr3() != __pa_symbol(initial_page_table));
+	BUG_ON(cr3 != __pa_symbol(swapper_pg_dir));
 
 	/*
 	 * We are switching to swapper_pg_dir for the first time (from
@@ -1987,7 +2011,7 @@ static void __init xen_write_cr3_init(unsigned long cr3)
 	pin_pagetable_pfn(MMUEXT_PIN_L3_TABLE, pfn);
 
 	pin_pagetable_pfn(MMUEXT_UNPIN_TABLE,
-			  PFN_DOWN(__pa(initial_page_table)));
+			  PFN_DOWN(__pa_symbol(initial_page_table)));
 	set_page_prot(initial_page_table, PAGE_KERNEL);
 	set_page_prot(initial_kernel_pmd, PAGE_KERNEL);
 
@@ -2012,7 +2036,7 @@ void __init xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn)
 
 	copy_page(initial_page_table, pgd);
 	initial_page_table[KERNEL_PGD_BOUNDARY] =
-		__pgd(__pa(initial_kernel_pmd) | _PAGE_PRESENT);
+		__pgd(__pa_symbol(initial_kernel_pmd) | _PAGE_PRESENT);
 
 	set_page_prot(initial_kernel_pmd, PAGE_KERNEL_RO);
 	set_page_prot(initial_page_table, PAGE_KERNEL_RO);
@@ -2021,8 +2045,8 @@ void __init xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn)
 	pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, PFN_DOWN(__pa(pgd)));
 
 	pin_pagetable_pfn(MMUEXT_PIN_L3_TABLE,
-			  PFN_DOWN(__pa(initial_page_table)));
-	xen_write_cr3(__pa(initial_page_table));
+			  PFN_DOWN(__pa_symbol(initial_page_table)));
+	xen_write_cr3(__pa_symbol(initial_page_table));
 
 	memblock_reserve(__pa(xen_start_info->pt_base),
 			 xen_start_info->nr_pt_frames * PAGE_SIZE);
@@ -2204,6 +2228,11 @@ static const struct pv_mmu_ops xen_mmu_ops __initconst = {
 void __init xen_init_mmu_ops(void)
 {
 	x86_init.paging.pagetable_init = xen_pagetable_init;
+
+	if (xen_feature(XENFEAT_auto_translated_physmap)) {
+		pv_mmu_ops.flush_tlb_others = xen_flush_tlb_others;
+		return;
+	}
 	pv_mmu_ops = xen_mmu_ops;
 
 	memset(dummy_mapping, 0xff, PAGE_SIZE);
@@ -2479,6 +2508,97 @@ void __init xen_hvm_init_mmu_ops(void)
 }
 #endif
 
+/* Map foreign gmfn, fgmfn, to local pfn, lpfn. This for the user space
+ * creating new guest on PVH dom0 and needs to map domU pages.
+ */
+static int pvh_add_to_xen_p2m(unsigned long lpfn, unsigned long fgmfn,
+			      unsigned int domid)
+{
+	int rc;
+	struct xen_add_to_physmap_range xatp = {
+		.domid = DOMID_SELF,
+		.foreign_domid = domid,
+		.size = 1,
+		.space = XENMAPSPACE_gmfn_foreign,
+	};
+	xen_ulong_t idx = fgmfn;
+	xen_pfn_t gpfn = lpfn;
+	int err = 0;
+
+	set_xen_guest_handle(xatp.idxs, &idx);
+	set_xen_guest_handle(xatp.gpfns, &gpfn);
+	set_xen_guest_handle(xatp.errs, &err);
+
+	rc = HYPERVISOR_memory_op(XENMEM_add_to_physmap_range, &xatp);
+	if (rc || err)
+		pr_warn("d0: Failed to map pfn (0x%lx) to mfn (0x%lx) rc:%d:%d\n",
+			lpfn, fgmfn, rc, err);
+	return rc;
+}
+
+static int pvh_rem_xen_p2m(unsigned long spfn, int count)
+{
+	struct xen_remove_from_physmap xrp;
+	int i, rc;
+
+	for (i = 0; i < count; i++) {
+		xrp.domid = DOMID_SELF;
+		xrp.gpfn = spfn+i;
+		rc = HYPERVISOR_memory_op(XENMEM_remove_from_physmap, &xrp);
+		if (rc) {
+			pr_warn("Failed to unmap pfn:%lx rc:%d done:%d\n",
+				spfn+i, rc, i);
+			return 1;
+		}
+	}
+	return 0;
+}
+
+struct pvh_remap_data {
+	unsigned long fgmfn;		/* foreign domain's gmfn */
+	pgprot_t prot;
+	domid_t  domid;
+	int	 index;
+	struct page **pages;
+};
+
+static int pvh_map_pte_fn(pte_t *ptep, pgtable_t token, unsigned long addr,
+			void *data)
+{
+	int rc;
+	struct pvh_remap_data *remap = data;
+	unsigned long pfn = page_to_pfn(remap->pages[remap->index++]);
+	pte_t pteval = pte_mkspecial(pfn_pte(pfn, remap->prot));
+
+	rc = pvh_add_to_xen_p2m(pfn, remap->fgmfn, remap->domid);
+	if (rc)
+		return rc;
+	native_set_pte(ptep, pteval);
+
+	return 0;
+}
+
+static int pvh_remap_gmfn_range(struct vm_area_struct *vma,
+				unsigned long addr, unsigned long mfn, int nr,
+				pgprot_t prot, unsigned domid,
+				struct page **pages)
+{
+	int err;
+	struct pvh_remap_data pvhdata;
+
+	BUG_ON(!pages);
+
+	pvhdata.fgmfn = mfn;
+	pvhdata.prot = prot;
+	pvhdata.domid = domid;
+	pvhdata.index = 0;
+	pvhdata.pages = pages;
+	err = apply_to_page_range(vma->vm_mm, addr, nr << PAGE_SHIFT,
+				  pvh_map_pte_fn, &pvhdata);
+	flush_tlb_all();
+	return err;
+}
+
 #define REMAP_BATCH_SIZE 16
 
 struct remap_data {
@@ -2520,6 +2640,10 @@ int xen_remap_domain_mfn_range(struct vm_area_struct *vma,
 
 	BUG_ON(!((vma->vm_flags & (VM_PFNMAP | VM_IO)) == (VM_PFNMAP | VM_IO)));
 
+	if (xen_feature(XENFEAT_auto_translated_physmap)) {
+		/* We need to update the local page tables and the xen HAP */
+		return pvh_remap_gmfn_range(vma, addr, mfn, nr, prot, domid, pages);
+	}
 	rmd.mfn = mfn;
 	rmd.prot = prot;
 
@@ -2557,6 +2681,18 @@ int xen_unmap_domain_mfn_range(struct vm_area_struct *vma,
 	if (!pages || !xen_feature(XENFEAT_auto_translated_physmap))
 		return 0;
 
-	return -EINVAL;
+	while (numpgs--) {
+
+		/* the mmu has already cleaned up the process mmu resources at
+		 * this point (lookup_address will return NULL). */
+		unsigned long pfn = page_to_pfn(pages[numpgs]);
+
+		pvh_rem_xen_p2m(pfn, 1);
+	}
+	/* We don't need to flush tlbs because as part of pvh_rem_xen_p2m(),
+	 * the hypervisor will do tlb flushes after removing the p2m entries
+	 * from the EPT/NPT */
+
+	return 0;
 }
 EXPORT_SYMBOL_GPL(xen_unmap_domain_mfn_range);
diff --git a/arch/x86/xen/mmu.h b/arch/x86/xen/mmu.h
index 73809bb..6d0bb56 100644
--- a/arch/x86/xen/mmu.h
+++ b/arch/x86/xen/mmu.h
@@ -23,4 +23,6 @@ unsigned long xen_read_cr2_direct(void);
 
 extern void xen_init_mmu_ops(void);
 extern void xen_hvm_init_mmu_ops(void);
+extern void xen_set_clr_mmio_pvh_pte(unsigned long pfn, unsigned long mfn,
+				     int nr_mfns, int add_mapping);
 #endif	/* _XEN_MMU_H */
diff --git a/arch/x86/xen/p2m.c b/arch/x86/xen/p2m.c
index 95fb2aa..ea553c8 100644
--- a/arch/x86/xen/p2m.c
+++ b/arch/x86/xen/p2m.c
@@ -798,7 +798,7 @@ bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn)
 {
 	unsigned topidx, mididx, idx;
 
-	if (unlikely(xen_feature(XENFEAT_auto_translated_physmap))) {
+	if (xen_feature(XENFEAT_auto_translated_physmap)) {
 		BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY);
 		return true;
 	}
diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c
index 94eac5c..c4874c0 100644
--- a/arch/x86/xen/setup.c
+++ b/arch/x86/xen/setup.c
@@ -27,6 +27,7 @@
 #include <xen/interface/memory.h>
 #include <xen/interface/physdev.h>
 #include <xen/features.h>
+#include "mmu.h"
 #include "xen-ops.h"
 #include "vdso.h"
 
@@ -78,6 +79,9 @@ static void __init xen_add_extra_mem(u64 start, u64 size)
 
 	memblock_reserve(start, size);
 
+	if (xen_feature(XENFEAT_auto_translated_physmap))
+		return;
+
 	xen_max_p2m_pfn = PFN_DOWN(start + size);
 	for (pfn = PFN_DOWN(start); pfn < xen_max_p2m_pfn; pfn++) {
 		unsigned long mfn = pfn_to_mfn(pfn);
@@ -100,6 +104,7 @@ static unsigned long __init xen_do_chunk(unsigned long start,
 		.domid        = DOMID_SELF
 	};
 	unsigned long len = 0;
+	int xlated_phys = xen_feature(XENFEAT_auto_translated_physmap);
 	unsigned long pfn;
 	int ret;
 
@@ -113,7 +118,7 @@ static unsigned long __init xen_do_chunk(unsigned long start,
 				continue;
 			frame = mfn;
 		} else {
-			if (mfn != INVALID_P2M_ENTRY)
+			if (!xlated_phys && mfn != INVALID_P2M_ENTRY)
 				continue;
 			frame = pfn;
 		}
@@ -230,6 +235,22 @@ static void __init xen_set_identity_and_release_chunk(
 	*identity += set_phys_range_identity(start_pfn, end_pfn);
 }
 
+
+/*
+ * PVH: xen has already mapped the IO space in the EPT/NPT for us, so we
+ * just need to adjust the released and identity count.
+ */
+static void __init xen_pvh_adjust_stats(unsigned long start_pfn,
+		unsigned long end_pfn, unsigned long *released,
+		unsigned long *identity, unsigned long max_pfn)
+{
+	if (start_pfn <= max_pfn) {
+		unsigned long end = min(max_pfn_mapped, end_pfn);
+		*released += end - start_pfn;
+	}
+	*identity += end_pfn - start_pfn;
+}
+
 static unsigned long __init xen_set_identity_and_release(
 	const struct e820entry *list, size_t map_size, unsigned long nr_pages)
 {
@@ -238,6 +259,7 @@ static unsigned long __init xen_set_identity_and_release(
 	unsigned long identity = 0;
 	const struct e820entry *entry;
 	int i;
+	int xlated_phys = xen_feature(XENFEAT_auto_translated_physmap);
 
 	/*
 	 * Combine non-RAM regions and gaps until a RAM region (or the
@@ -259,11 +281,17 @@ static unsigned long __init xen_set_identity_and_release(
 			if (entry->type == E820_RAM)
 				end_pfn = PFN_UP(entry->addr);
 
-			if (start_pfn < end_pfn)
-				xen_set_identity_and_release_chunk(
-					start_pfn, end_pfn, nr_pages,
-					&released, &identity);
-
+			if (start_pfn < end_pfn) {
+				if (xlated_phys) {
+					xen_pvh_adjust_stats(start_pfn,
+						end_pfn, &released, &identity,
+						nr_pages);
+				} else {
+					xen_set_identity_and_release_chunk(
+						start_pfn, end_pfn, nr_pages,
+						&released, &identity);
+				}
+			}
 			start = end;
 		}
 	}
@@ -526,16 +554,14 @@ void __cpuinit xen_enable_syscall(void)
 #endif /* CONFIG_X86_64 */
 }
 
-void __init xen_arch_setup(void)
+/* Non auto translated PV domain, ie, it's not PVH. */
+static __init void xen_pvmmu_arch_setup(void)
 {
-	xen_panic_handler_init();
-
 	HYPERVISOR_vm_assist(VMASST_CMD_enable, VMASST_TYPE_4gb_segments);
 	HYPERVISOR_vm_assist(VMASST_CMD_enable, VMASST_TYPE_writable_pagetables);
 
-	if (!xen_feature(XENFEAT_auto_translated_physmap))
-		HYPERVISOR_vm_assist(VMASST_CMD_enable,
-				     VMASST_TYPE_pae_extended_cr3);
+	HYPERVISOR_vm_assist(VMASST_CMD_enable,
+			     VMASST_TYPE_pae_extended_cr3);
 
 	if (register_callback(CALLBACKTYPE_event, xen_hypervisor_callback) ||
 	    register_callback(CALLBACKTYPE_failsafe, xen_failsafe_callback))
@@ -543,6 +569,15 @@ void __init xen_arch_setup(void)
 
 	xen_enable_sysenter();
 	xen_enable_syscall();
+}
+
+/* This function not called for HVM domain */
+void __init xen_arch_setup(void)
+{
+	xen_panic_handler_init();
+
+	if (!xen_feature(XENFEAT_auto_translated_physmap))
+		xen_pvmmu_arch_setup();
 
 #ifdef CONFIG_ACPI
 	if (!(xen_start_info->flags & SIF_INITDOMAIN)) {
diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c
index 09ea61d..222d737 100644
--- a/arch/x86/xen/smp.c
+++ b/arch/x86/xen/smp.c
@@ -68,9 +68,11 @@ static void __cpuinit cpu_bringup(void)
 	touch_softlockup_watchdog();
 	preempt_disable();
 
-	xen_enable_sysenter();
-	xen_enable_syscall();
-
+	/* PVH runs in ring 0 and allows us to do native syscalls. Yay! */
+	if (!xen_feature(XENFEAT_supervisor_mode_kernel)) {
+		xen_enable_sysenter();
+		xen_enable_syscall();
+	}
 	cpu = smp_processor_id();
 	smp_store_cpu_info(cpu);
 	cpu_data(cpu).x86_max_cores = 1;
@@ -230,10 +232,11 @@ static void __init xen_smp_prepare_boot_cpu(void)
 	BUG_ON(smp_processor_id() != 0);
 	native_smp_prepare_boot_cpu();
 
-	/* We've switched to the "real" per-cpu gdt, so make sure the
-	   old memory can be recycled */
-	make_lowmem_page_readwrite(xen_initial_gdt);
-
+	if (!xen_feature(XENFEAT_writable_page_tables)) {
+		/* We've switched to the "real" per-cpu gdt, so make sure the
+		 * old memory can be recycled */
+		make_lowmem_page_readwrite(xen_initial_gdt);
+	}
 	xen_filter_cpu_maps();
 	xen_setup_vcpu_info_placement();
 }
@@ -311,7 +314,23 @@ cpu_initialize_context(unsigned int cpu, struct task_struct *idle)
 
 	memset(&ctxt->fpu_ctxt, 0, sizeof(ctxt->fpu_ctxt));
 
-	{
+	if (xen_feature(XENFEAT_auto_translated_physmap) &&
+	    xen_feature(XENFEAT_supervisor_mode_kernel)) {
+		/* Note: PVH is not supported on x86_32. */
+#ifdef CONFIG_X86_64
+		ctxt->user_regs.ds = __KERNEL_DS;
+		ctxt->user_regs.es = 0;
+		ctxt->user_regs.gs = 0;
+
+		/* GUEST_GDTR_BASE and */
+		ctxt->u.pvh.gdtaddr = (unsigned long)gdt;
+		/* GUEST_GDTR_LIMIT in the VMCS. */
+		ctxt->u.pvh.gdtsz = (unsigned long)(GDT_SIZE - 1);
+
+		ctxt->gs_base_user = (unsigned long)
+					per_cpu(irq_stack_union.gs_base, cpu);
+#endif
+	} else {
 		ctxt->user_regs.eflags = 0x1000; /* IOPL_RING1 */
 		ctxt->user_regs.ds = __USER_DS;
 		ctxt->user_regs.es = __USER_DS;
@@ -326,8 +345,8 @@ cpu_initialize_context(unsigned int cpu, struct task_struct *idle)
 		make_lowmem_page_readonly(gdt);
 		make_lowmem_page_readonly(mfn_to_virt(gdt_mfn));
 
-		ctxt->gdt_frames[0] = gdt_mfn;
-		ctxt->gdt_ents      = GDT_ENTRIES;
+		ctxt->u.pv.gdt_frames[0] = gdt_mfn;
+		ctxt->u.pv.gdt_ents      = GDT_ENTRIES;
 
 		ctxt->kernel_ss = __KERNEL_DS;
 		ctxt->kernel_sp = idle->thread.sp0;
diff --git a/arch/x86/xen/xen-head.S b/arch/x86/xen/xen-head.S
index 7faed58..45226cb 100644
--- a/arch/x86/xen/xen-head.S
+++ b/arch/x86/xen/xen-head.S
@@ -13,6 +13,14 @@
 #include <xen/interface/elfnote.h>
 #include <asm/xen/interface.h>
 
+#ifdef CONFIG_XEN_X86_PVH
+
+#define PVH_FEATURES_STR  "|writable_descriptor_tables|auto_translated_physmap|supervisor_mode_kernel|hvm_callback_vector"
+
+#else
+#define PVH_FEATURES_STR  ""
+#endif
+
 	__INIT
 ENTRY(startup_xen)
 	cld
@@ -95,7 +103,7 @@ NEXT_HYPERCALL(arch_6)
 #endif
 	ELFNOTE(Xen, XEN_ELFNOTE_ENTRY,          _ASM_PTR startup_xen)
 	ELFNOTE(Xen, XEN_ELFNOTE_HYPERCALL_PAGE, _ASM_PTR hypercall_page)
-	ELFNOTE(Xen, XEN_ELFNOTE_FEATURES,       .asciz "!writable_page_tables|pae_pgdir_above_4gb")
+        ELFNOTE(Xen, XEN_ELFNOTE_FEATURES,       .ascii "!writable_page_tables|pae_pgdir_above_4gb"; .asciz PVH_FEATURES_STR);
 	ELFNOTE(Xen, XEN_ELFNOTE_PAE_MODE,       .asciz "yes")
 	ELFNOTE(Xen, XEN_ELFNOTE_LOADER,         .asciz "generic")
 	ELFNOTE(Xen, XEN_ELFNOTE_L1_MFN_VALID,
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig
index b09de49..a9bdb1c 100644
--- a/arch/xtensa/Kconfig
+++ b/arch/xtensa/Kconfig
@@ -103,6 +103,35 @@ config MATH_EMULATION
 	help
 	Can we use information of configuration file?
 
+config INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX
+	bool "Initialize Xtensa MMU inside the Linux kernel code"
+	default y
+	help
+	  Earlier version initialized the MMU in the exception vector
+	  before jumping to _startup in head.S and had an advantage that
+	  it was possible to place a software breakpoint at 'reset' and
+	  then enter your normal kernel breakpoints once the MMU was mapped
+	  to the kernel mappings (0XC0000000).
+
+	  This unfortunately doesn't work for U-Boot and likley also wont
+	  work for using KEXEC to have a hot kernel ready for doing a
+	  KDUMP.
+
+	  So now the MMU is initialized in head.S but it's necessary to
+	  use hardware breakpoints (gdb 'hbreak' cmd) to break at _startup.
+	  xt-gdb can't place a Software Breakpoint in the  0XD region prior
+	  to mapping the MMU and after mapping even if the area of low memory
+	  was mapped gdb wouldn't remove the breakpoint on hitting it as the
+	  PC wouldn't match. Since Hardware Breakpoints are recommended for
+	  Linux configurations it seems reasonable to just assume they exist
+	  and leave this older mechanism for unfortunate souls that choose
+	  not to follow Tensilica's recommendation.
+
+	  Selecting this will cause U-Boot to set the KERNEL Load and Entry
+	  address at 0x00003000 instead of the mapped std of 0xD0003000.
+
+	  If in doubt, say Y.
+
 endmenu
 
 config XTENSA_CALIBRATE_CCOUNT
@@ -252,21 +281,6 @@ endmenu
 
 menu "Executable file formats"
 
-# only elf supported
-config KCORE_ELF
-	def_bool y
-        depends on PROC_FS
-        help
-          If you enabled support for /proc file system then the file
-          /proc/kcore will contain the kernel core image in ELF format. This
-          can be used in gdb:
-
-          $ cd /usr/src/linux ; gdb vmlinux /proc/kcore
-
-          This is especially useful if you have compiled the kernel with the
-          "-g" option to preserve debugging information. It is mainly used
-	  for examining kernel data structures on the live kernel.
-
 source "fs/Kconfig.binfmt"
 
 endmenu
diff --git a/arch/xtensa/boot/boot-elf/Makefile b/arch/xtensa/boot/boot-elf/Makefile
index 1fe01b7..89db089 100644
--- a/arch/xtensa/boot/boot-elf/Makefile
+++ b/arch/xtensa/boot/boot-elf/Makefile
@@ -12,6 +12,7 @@ endif
 
 export OBJCOPY_ARGS
 export CPPFLAGS_boot.lds += -P -C
+export KBUILD_AFLAGS += -mtext-section-literals
 
 boot-y		:= bootstrap.o
 
diff --git a/arch/xtensa/boot/boot-elf/boot.lds.S b/arch/xtensa/boot/boot-elf/boot.lds.S
index 7b646e0..932b58e 100644
--- a/arch/xtensa/boot/boot-elf/boot.lds.S
+++ b/arch/xtensa/boot/boot-elf/boot.lds.S
@@ -1,41 +1,29 @@
-#include <variant/core.h>
+/*
+ *  linux/arch/xtensa/boot/boot-elf/boot.lds.S
+ *
+ *  Copyright (C) 2008 - 2013 by Tensilica Inc.
+ *
+ *  Chris Zankel <chris@zankel.net>
+ *  Marc Gauthier <marc@tensilica.com
+ *  Pete Delaney <piet@tensilica.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <asm/vectors.h>
 OUTPUT_ARCH(xtensa)
 ENTRY(_ResetVector)
 
 SECTIONS
 {
-	.start 0xD0000000 : { *(.start) }
-
-	.text 0xD0000000:
-	{
-		__reloc_start = . ;
-		_text_start = . ;
-		*(.literal .text.literal .text)
-		_text_end = . ;
-	}
-
-	.rodata ALIGN(0x04):
-	{
-		*(.rodata)
-		*(.rodata1)
-	}
-
-	.data ALIGN(0x04):
+	.ResetVector.text XCHAL_RESET_VECTOR_VADDR :
 	{
-		*(.data)
-		*(.data1)
-		*(.sdata)
-		*(.sdata2)
-		*(.got.plt)
-		*(.got)
-		*(.dynamic)
+		*(.ResetVector.text)
 	}
 
-	__reloc_end = . ;
-
-	. = ALIGN(0x10);
-	__image_load = . ;
-	.image 0xd0001000:
+	.image KERNELOFFSET: AT (LOAD_MEMORY_ADDRESS)
 	{
 		_image_start = .;
 		*(image)
@@ -43,7 +31,6 @@ SECTIONS
 		_image_end = .	;
 	}
 
-
 	.bss ((LOADADDR(.image) + SIZEOF(.image) + 3) & ~ 3):
 	{
 		__bss_start = .;
@@ -53,14 +40,15 @@ SECTIONS
 		*(.bss)
 		__bss_end = .;
 	}
-	_end = .;
-	_param_start = .;
 
-	.ResetVector.text XCHAL_RESET_VECTOR_VADDR :
+	/*
+	 * This is a remapped copy of the Reset Vector Code.
+	 * It keeps gdb in sync with the PC after switching
+	 * to the temporary mapping used while setting up
+	 * the V2 MMU mappings for Linux.
+	 */
+	.ResetVector.remapped_text 0x46000000 (INFO):
 	{
-		*(.ResetVector.text)
+		*(.ResetVector.remapped_text)
 	}
-
-
-	PROVIDE (end = .);
 }
diff --git a/arch/xtensa/boot/boot-elf/bootstrap.S b/arch/xtensa/boot/boot-elf/bootstrap.S
index 464298b..1388a49 100644
--- a/arch/xtensa/boot/boot-elf/bootstrap.S
+++ b/arch/xtensa/boot/boot-elf/bootstrap.S
@@ -1,18 +1,77 @@
+/*
+ * arch/xtensa/boot/boot-elf/bootstrap.S
+ *
+ * Low-level exception handling
+ *
+ * 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) 2004 - 2013 by Tensilica Inc.
+ *
+ * Chris Zankel <chris@zankel.net>
+ * Marc Gauthier <marc@tensilica.com>
+ * Piet Delaney <piet@tensilica.com>
+ */
 
 #include <asm/bootparam.h>
+#include <asm/processor.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/cacheasm.h>
+#include <asm/initialize_mmu.h>
+#include <linux/linkage.h>
 
-
-/* ResetVector
- */
-	.section        .ResetVector.text, "ax"
+	.section	.ResetVector.text, "ax"
 	.global         _ResetVector
+	.global         reset
+
 _ResetVector:
-	_j reset
+	_j _SetupMMU
+
+	.begin  no-absolute-literals
+	.literal_position
+
 	.align 4
 RomInitAddr:
-	.word 0xd0001000
+#if defined(CONFIG_INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX) && \
+	XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY
+	.word 0x00003000
+#else
+	.word 0xd0003000
+#endif
 RomBootParam:
 	.word _bootparam
+_bootparam:
+	.short	BP_TAG_FIRST
+	.short	4
+	.long	BP_VERSION
+	.short	BP_TAG_LAST
+	.short	0
+	.long	0
+
+	.align  4
+_SetupMMU:
+	movi	a0, 0
+	wsr	a0, windowbase
+	rsync
+	movi	a0, 1
+	wsr	a0, windowstart
+	rsync
+	movi	a0, 0x1F
+	wsr	a0, ps
+	rsync
+
+	Offset = _SetupMMU - _ResetVector
+
+#ifndef CONFIG_INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX
+	initialize_mmu
+#endif
+
+	.end    no-absolute-literals
+
+	rsil    a0, XCHAL_DEBUGLEVEL-1
+	rsync
 reset:
 	l32r    a0, RomInitAddr
 	l32r	a2, RomBootParam
@@ -21,13 +80,25 @@ reset:
 	jx      a0
 
 	.align 4
-	.section .bootstrap.data, "aw"
 
-	.globl _bootparam
-_bootparam:
-	.short	BP_TAG_FIRST
-	.short	4
-	.long	BP_VERSION
-	.short	BP_TAG_LAST
-	.short	0
-	.long	0
+	.section	.ResetVector.remapped_text, "x"
+	.global         _RemappedResetVector
+
+	/* Do org before literals */
+	.org 0
+
+_RemappedResetVector:
+	.begin  no-absolute-literals
+	.literal_position
+
+	_j	_RemappedSetupMMU
+
+	/* Position Remapped code at the same location as the original code */
+	. = _RemappedResetVector + Offset
+
+_RemappedSetupMMU:
+#ifndef CONFIG_INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX
+	initialize_mmu
+#endif
+
+	.end    no-absolute-literals
diff --git a/arch/xtensa/boot/boot-uboot/Makefile b/arch/xtensa/boot/boot-uboot/Makefile
index bfbf8af..5457598 100644
--- a/arch/xtensa/boot/boot-uboot/Makefile
+++ b/arch/xtensa/boot/boot-uboot/Makefile
@@ -4,7 +4,11 @@
 # for more details.
 #
 
-UIMAGE_LOADADDR = 0xd0001000
+ifdef CONFIG_INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX
+UIMAGE_LOADADDR = 0x00003000
+else
+UIMAGE_LOADADDR = 0xd0003000
+endif
 UIMAGE_COMPRESSION = gzip
 
 $(obj)/../uImage: vmlinux.bin.gz FORCE
diff --git a/arch/xtensa/configs/iss_defconfig b/arch/xtensa/configs/iss_defconfig
index ddab37b..77c52f8 100644
--- a/arch/xtensa/configs/iss_defconfig
+++ b/arch/xtensa/configs/iss_defconfig
@@ -10,7 +10,6 @@ CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_GPIO=y
 # CONFIG_ARCH_HAS_ILOG2_U32 is not set
 # CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_NO_IOPORT=y
diff --git a/arch/xtensa/configs/s6105_defconfig b/arch/xtensa/configs/s6105_defconfig
index eaf1b8f..4799c6a 100644
--- a/arch/xtensa/configs/s6105_defconfig
+++ b/arch/xtensa/configs/s6105_defconfig
@@ -10,7 +10,6 @@ CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_GPIO=y
 # CONFIG_ARCH_HAS_ILOG2_U32 is not set
 # CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_NO_IOPORT=y
diff --git a/arch/xtensa/include/asm/initialize_mmu.h b/arch/xtensa/include/asm/initialize_mmu.h
index e1f8ba4..722553f 100644
--- a/arch/xtensa/include/asm/initialize_mmu.h
+++ b/arch/xtensa/include/asm/initialize_mmu.h
@@ -23,6 +23,9 @@
 #ifndef _XTENSA_INITIALIZE_MMU_H
 #define _XTENSA_INITIALIZE_MMU_H
 
+#include <asm/pgtable.h>
+#include <asm/vectors.h>
+
 #ifdef __ASSEMBLY__
 
 #define XTENSA_HWVERSION_RC_2009_0 230000
@@ -48,6 +51,110 @@
 	 * (XCHAL_HW_MIN_VERSION >= XTENSA_HWVERSION_RC_2009_0)
 	 */
 
+#if defined(CONFIG_MMU) && XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY
+/*
+ * Have MMU v3
+ */
+
+#if !XCHAL_HAVE_VECBASE
+# error "MMU v3 requires reloc vectors"
+#endif
+
+	movi	a1, 0
+	_call0	1f
+	_j	2f
+
+	.align	4
+1:	movi	a2, 0x10000000
+	movi	a3, 0x18000000
+	add	a2, a2, a0
+9:	bgeu	a2, a3, 9b	/* PC is out of the expected range */
+
+	/* Step 1: invalidate mapping at 0x40000000..0x5FFFFFFF. */
+
+	movi	a2, 0x40000006
+	idtlb	a2
+	iitlb	a2
+	isync
+
+	/* Step 2: map 0x40000000..0x47FFFFFF to paddr containing this code
+	 * and jump to the new mapping.
+	 */
+#define CA_BYPASS	(_PAGE_CA_BYPASS | _PAGE_HW_WRITE | _PAGE_HW_EXEC)
+#define CA_WRITEBACK	(_PAGE_CA_WB     | _PAGE_HW_WRITE | _PAGE_HW_EXEC)
+
+	srli	a3, a0, 27
+	slli	a3, a3, 27
+	addi	a3, a3, CA_BYPASS
+	addi	a7, a2, -1
+	wdtlb	a3, a7
+	witlb	a3, a7
+	isync
+
+	slli	a4, a0, 5
+	srli	a4, a4, 5
+	addi	a5, a2, -6
+	add	a4, a4, a5
+	jx	a4
+
+	/* Step 3: unmap everything other than current area.
+	 *	   Start at 0x60000000, wrap around, and end with 0x20000000
+	 */
+2:	movi	a4, 0x20000000
+	add	a5, a2, a4
+3:	idtlb	a5
+	iitlb	a5
+	add	a5, a5, a4
+	bne	a5, a2, 3b
+
+	/* Step 4: Setup MMU with the old V2 mappings. */
+	movi	a6, 0x01000000
+	wsr	a6, ITLBCFG
+	wsr	a6, DTLBCFG
+	isync
+
+	movi	a5, 0xd0000005
+	movi	a4, CA_WRITEBACK
+	wdtlb	a4, a5
+	witlb	a4, a5
+
+	movi	a5, 0xd8000005
+	movi	a4, CA_BYPASS
+	wdtlb	a4, a5
+	witlb	a4, a5
+
+	movi	a5, 0xe0000006
+	movi	a4, 0xf0000000 + CA_WRITEBACK
+	wdtlb	a4, a5
+	witlb	a4, a5
+
+	movi	a5, 0xf0000006
+	movi	a4, 0xf0000000 + CA_BYPASS
+	wdtlb	a4, a5
+	witlb	a4, a5
+
+	isync
+
+	/* Jump to self, using MMU v2 mappings. */
+	movi	a4, 1f
+	jx	a4
+
+1:
+	movi    a2, VECBASE_RESET_VADDR
+	wsr	a2, vecbase
+
+	/* Step 5: remove temporary mapping. */
+	idtlb	a7
+	iitlb	a7
+	isync
+
+	movi	a0, 0
+	wsr	a0, ptevaddr
+	rsync
+
+#endif /* defined(CONFIG_MMU) && XCHAL_HAVE_PTP_MMU &&
+	  XCHAL_HAVE_SPANNING_WAY */
+
 	.endm
 
 #endif /*__ASSEMBLY__*/
diff --git a/arch/xtensa/include/asm/unistd.h b/arch/xtensa/include/asm/unistd.h
index c38834d..cb4c2ce 100644
--- a/arch/xtensa/include/asm/unistd.h
+++ b/arch/xtensa/include/asm/unistd.h
@@ -4,14 +4,6 @@
 #define __ARCH_WANT_SYS_CLONE
 #include <uapi/asm/unistd.h>
 
-/*
- * "Conditional" syscalls
- *
- * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
- * but it doesn't work on all toolchains, so we just do it by hand
- */
-#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
-
 #define __ARCH_WANT_STAT64
 #define __ARCH_WANT_SYS_UTIME
 #define __ARCH_WANT_SYS_LLSEEK
diff --git a/arch/xtensa/include/asm/vectors.h b/arch/xtensa/include/asm/vectors.h
new file mode 100644
index 0000000..c52b656
--- /dev/null
+++ b/arch/xtensa/include/asm/vectors.h
@@ -0,0 +1,125 @@
+/*
+ * arch/xtensa/include/asm/xchal_vaddr_remap.h
+ *
+ * Xtensa macros for MMU V3 Support. Deals with re-mapping the Virtual
+ * Memory Addresses from "Virtual == Physical" to their prevvious V2 MMU
+ * mappings (KSEG at 0xD0000000 and KIO at 0XF0000000).
+ *
+ * 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) 2008 - 2012 Tensilica Inc.
+ *
+ * Pete Delaney <piet@tensilica.com>
+ * Marc Gauthier <marc@tensilica.com
+ */
+
+#ifndef _XTENSA_VECTORS_H
+#define _XTENSA_VECTORS_H
+
+#include <variant/core.h>
+
+#if defined(CONFIG_MMU)
+
+/* Will Become VECBASE */
+#define VIRTUAL_MEMORY_ADDRESS		0xD0000000
+
+/* Image Virtual Start Address */
+#define KERNELOFFSET			0xD0003000
+
+#if defined(XCHAL_HAVE_PTP_MMU) && XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY
+  /* MMU v3  - XCHAL_HAVE_PTP_MMU  == 1 */
+  #define PHYSICAL_MEMORY_ADDRESS	0x00000000
+  #define LOAD_MEMORY_ADDRESS		0x00003000
+#else
+  /* MMU V2 -  XCHAL_HAVE_PTP_MMU  == 0 */
+  #define PHYSICAL_MEMORY_ADDRESS	0xD0000000
+  #define LOAD_MEMORY_ADDRESS		0xD0003000
+#endif
+
+#else /* !defined(CONFIG_MMU) */
+  /* MMU Not being used - Virtual == Physical */
+
+  /* VECBASE */
+  #define VIRTUAL_MEMORY_ADDRESS	0x00002000
+
+  /* Location of the start of the kernel text, _start */
+  #define KERNELOFFSET			0x00003000
+  #define PHYSICAL_MEMORY_ADDRESS	0x00000000
+
+  /* Loaded just above possibly live vectors */
+  #define LOAD_MEMORY_ADDRESS		0x00003000
+
+#endif /* CONFIG_MMU */
+
+#define XC_VADDR(offset)		(VIRTUAL_MEMORY_ADDRESS  + offset)
+#define XC_PADDR(offset)		(PHYSICAL_MEMORY_ADDRESS + offset)
+
+/* Used to set VECBASE register */
+#define VECBASE_RESET_VADDR		VIRTUAL_MEMORY_ADDRESS
+
+#define RESET_VECTOR_VECOFS		(XCHAL_RESET_VECTOR_VADDR - \
+						VECBASE_RESET_VADDR)
+#define RESET_VECTOR_VADDR		XC_VADDR(RESET_VECTOR_VECOFS)
+
+#define RESET_VECTOR1_VECOFS		(XCHAL_RESET_VECTOR1_VADDR - \
+						VECBASE_RESET_VADDR)
+#define RESET_VECTOR1_VADDR		XC_VADDR(RESET_VECTOR1_VECOFS)
+
+#if XCHAL_HAVE_VECBASE
+
+#define USER_VECTOR_VADDR		XC_VADDR(XCHAL_USER_VECOFS)
+#define KERNEL_VECTOR_VADDR		XC_VADDR(XCHAL_KERNEL_VECOFS)
+#define DOUBLEEXC_VECTOR_VADDR		XC_VADDR(XCHAL_DOUBLEEXC_VECOFS)
+#define WINDOW_VECTORS_VADDR		XC_VADDR(XCHAL_WINDOW_OF4_VECOFS)
+#define INTLEVEL2_VECTOR_VADDR		XC_VADDR(XCHAL_INTLEVEL2_VECOFS)
+#define INTLEVEL3_VECTOR_VADDR		XC_VADDR(XCHAL_INTLEVEL3_VECOFS)
+#define INTLEVEL4_VECTOR_VADDR		XC_VADDR(XCHAL_INTLEVEL4_VECOFS)
+#define INTLEVEL5_VECTOR_VADDR		XC_VADDR(XCHAL_INTLEVEL5_VECOFS)
+#define INTLEVEL6_VECTOR_VADDR		XC_VADDR(XCHAL_INTLEVEL6_VECOFS)
+
+#define DEBUG_VECTOR_VADDR		XC_VADDR(XCHAL_DEBUG_VECOFS)
+
+#undef  XCHAL_NMI_VECTOR_VADDR
+#define XCHAL_NMI_VECTOR_VADDR		XC_VADDR(XCHAL_NMI_VECOFS)
+
+#undef  XCHAL_INTLEVEL7_VECTOR_VADDR
+#define XCHAL_INTLEVEL7_VECTOR_VADDR	XC_VADDR(XCHAL_INTLEVEL7_VECOFS)
+
+/*
+ * These XCHAL_* #defines from varian/core.h
+ * are not valid to use with V3 MMU. Non-XCHAL
+ * constants are defined above and should be used.
+ */
+#undef  XCHAL_VECBASE_RESET_VADDR
+#undef  XCHAL_RESET_VECTOR0_VADDR
+#undef  XCHAL_USER_VECTOR_VADDR
+#undef  XCHAL_KERNEL_VECTOR_VADDR
+#undef  XCHAL_DOUBLEEXC_VECTOR_VADDR
+#undef  XCHAL_WINDOW_VECTORS_VADDR
+#undef  XCHAL_INTLEVEL2_VECTOR_VADDR
+#undef  XCHAL_INTLEVEL3_VECTOR_VADDR
+#undef  XCHAL_INTLEVEL4_VECTOR_VADDR
+#undef  XCHAL_INTLEVEL5_VECTOR_VADDR
+#undef  XCHAL_INTLEVEL6_VECTOR_VADDR
+#undef  XCHAL_DEBUG_VECTOR_VADDR
+#undef  XCHAL_NMI_VECTOR_VADDR
+#undef  XCHAL_INTLEVEL7_VECTOR_VADDR
+
+#else
+
+#define USER_VECTOR_VADDR		XCHAL_USER_VECTOR_VADDR
+#define KERNEL_VECTOR_VADDR		XCHAL_KERNEL_VECTOR_VADDR
+#define DOUBLEEXC_VECTOR_VADDR		XCHAL_DOUBLEEXC_VECTOR_VADDR
+#define WINDOW_VECTORS_VADDR		XCHAL_WINDOW_VECTORS_VADDR
+#define INTLEVEL2_VECTOR_VADDR		XCHAL_INTLEVEL2_VECTOR_VADDR
+#define INTLEVEL3_VECTOR_VADDR		XCHAL_INTLEVEL3_VECTOR_VADDR
+#define INTLEVEL4_VECTOR_VADDR		XCHAL_INTLEVEL4_VECTOR_VADDR
+#define INTLEVEL5_VECTOR_VADDR		XCHAL_INTLEVEL5_VECTOR_VADDR
+#define INTLEVEL6_VECTOR_VADDR		XCHAL_INTLEVEL6_VECTOR_VADDR
+#define DEBUG_VECTOR_VADDR		XCHAL_DEBUG_VECTOR_VADDR
+
+#endif
+
+#endif /* _XTENSA_VECTORS_H */
diff --git a/arch/xtensa/include/uapi/asm/socket.h b/arch/xtensa/include/uapi/asm/socket.h
index 35905cb..a8f44f5 100644
--- a/arch/xtensa/include/uapi/asm/socket.h
+++ b/arch/xtensa/include/uapi/asm/socket.h
@@ -83,4 +83,6 @@
 
 #define SO_LOCK_FILTER		44
 
+#define SO_SELECT_ERR_QUEUE	45
+
 #endif	/* _XTENSA_SOCKET_H */
diff --git a/arch/xtensa/kernel/Makefile b/arch/xtensa/kernel/Makefile
index c3a59d9..c433a56 100644
--- a/arch/xtensa/kernel/Makefile
+++ b/arch/xtensa/kernel/Makefile
@@ -12,6 +12,8 @@ obj-$(CONFIG_KGDB) += xtensa-stub.o
 obj-$(CONFIG_PCI) += pci.o
 obj-$(CONFIG_MODULES) += xtensa_ksyms.o module.o
 
+AFLAGS_head.o += -mtext-section-literals
+
 # In the Xtensa architecture, assembly generates literals which must always
 # precede the L32R instruction with a relative offset less than 256 kB.
 # Therefore, the .text and .literal section must be combined in parenthesis
diff --git a/arch/xtensa/kernel/head.S b/arch/xtensa/kernel/head.S
index df88f98..ef12c0e 100644
--- a/arch/xtensa/kernel/head.S
+++ b/arch/xtensa/kernel/head.S
@@ -48,17 +48,36 @@
 	 */
 
 	__HEAD
+	.begin	no-absolute-literals
+
 ENTRY(_start)
 
-	_j	2f
+	/* Preserve the pointer to the boot parameter list in EXCSAVE_1 */
+	wsr     a2, excsave1
+	_j	_SetupMMU
+
+	.align	4
+	.literal_position
+.Lstartup:
+	.word	_startup
+
 	.align	4
-1:	.word	_startup
-2:	l32r	a0, 1b
+	.global _SetupMMU
+_SetupMMU:
+	Offset = _SetupMMU - _start
+
+#ifdef CONFIG_INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX
+	initialize_mmu
+#endif
+	.end	no-absolute-literals
+
+	l32r	a0, .Lstartup
 	jx	a0
 
 ENDPROC(_start)
 
-	.section .init.text, "ax"
+	__INIT
+	.literal_position
 
 ENTRY(_startup)
 
@@ -67,10 +86,6 @@ ENTRY(_startup)
 	movi	a0, LOCKLEVEL
 	wsr	a0, ps
 
-	/* Preserve the pointer to the boot parameter list in EXCSAVE_1 */
-
-	wsr	a2, excsave1
-
 	/* Start with a fresh windowbase and windowstart.  */
 
 	movi	a1, 1
@@ -86,7 +101,9 @@ ENTRY(_startup)
 	/* Clear debugging registers. */
 
 #if XCHAL_HAVE_DEBUG
+#if XCHAL_NUM_IBREAK > 0
 	wsr	a0, ibreakenable
+#endif
 	wsr	a0, icount
 	movi	a1, 15
 	wsr	a0, icountlevel
@@ -156,8 +173,6 @@ ENTRY(_startup)
 
 	isync
 
-	initialize_mmu
-
 	/* Unpack data sections
 	 *
 	 * The linker script used to build the Linux kernel image
@@ -205,6 +220,10 @@ ENTRY(_startup)
 
 	___flush_dcache_all a2 a3
 #endif
+	memw
+	isync
+	___invalidate_icache_all a2 a3
+	isync
 
 	/* Setup stack and enable window exceptions (keep irqs disabled) */
 
diff --git a/arch/xtensa/kernel/platform.c b/arch/xtensa/kernel/platform.c
index 44bf21c..2bd6c35 100644
--- a/arch/xtensa/kernel/platform.c
+++ b/arch/xtensa/kernel/platform.c
@@ -36,6 +36,7 @@ _F(void, power_off, (void), { while(1); });
 _F(void, idle, (void), { __asm__ __volatile__ ("waiti 0" ::: "memory"); });
 _F(void, heartbeat, (void), { });
 _F(int,  pcibios_fixup, (void), { return 0; });
+_F(void, pcibios_init, (void), { });
 
 #ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT
 _F(void, calibrate_ccount, (void),
diff --git a/arch/xtensa/kernel/vectors.S b/arch/xtensa/kernel/vectors.S
index 82109b42..a7e1d08 100644
--- a/arch/xtensa/kernel/vectors.S
+++ b/arch/xtensa/kernel/vectors.S
@@ -50,6 +50,7 @@
 #include <asm/processor.h>
 #include <asm/page.h>
 #include <asm/thread_info.h>
+#include <asm/vectors.h>
 
 #define WINDOW_VECTORS_SIZE   0x180
 
@@ -220,7 +221,7 @@ ENTRY(_DoubleExceptionVector)
 
 	xsr	a0, depc		# get DEPC, save a0
 
-	movi	a3, XCHAL_WINDOW_VECTORS_VADDR
+	movi	a3, WINDOW_VECTORS_VADDR
 	_bltu	a0, a3, .Lfixup
 	addi	a3, a3, WINDOW_VECTORS_SIZE
 	_bgeu	a0, a3, .Lfixup
diff --git a/arch/xtensa/kernel/vmlinux.lds.S b/arch/xtensa/kernel/vmlinux.lds.S
index 1469524..21acd11 100644
--- a/arch/xtensa/kernel/vmlinux.lds.S
+++ b/arch/xtensa/kernel/vmlinux.lds.S
@@ -18,6 +18,7 @@
 #include <asm/page.h>
 #include <asm/thread_info.h>
 
+#include <asm/vectors.h>
 #include <variant/core.h>
 #include <platform/hardware.h>
 OUTPUT_ARCH(xtensa)
@@ -30,7 +31,7 @@ jiffies = jiffies_64;
 #endif
 
 #ifndef KERNELOFFSET
-#define KERNELOFFSET 0xd0001000
+#define KERNELOFFSET 0xd0003000
 #endif
 
 /* Note: In the following macros, it would be nice to specify only the
@@ -185,16 +186,16 @@ SECTIONS
 
   SECTION_VECTOR (_WindowVectors_text,
 		  .WindowVectors.text,
-		  XCHAL_WINDOW_VECTORS_VADDR, 4,
+		  WINDOW_VECTORS_VADDR, 4,
 		  .dummy)
   SECTION_VECTOR (_DebugInterruptVector_literal,
 		  .DebugInterruptVector.literal,
-		  XCHAL_DEBUG_VECTOR_VADDR - 4,
+		  DEBUG_VECTOR_VADDR - 4,
 		  SIZEOF(.WindowVectors.text),
 		  .WindowVectors.text)
   SECTION_VECTOR (_DebugInterruptVector_text,
 		  .DebugInterruptVector.text,
-		  XCHAL_DEBUG_VECTOR_VADDR,
+		  DEBUG_VECTOR_VADDR,
 		  4,
 		  .DebugInterruptVector.literal)
 #undef LAST
@@ -202,7 +203,7 @@ SECTIONS
 #if XCHAL_EXCM_LEVEL >= 2
   SECTION_VECTOR (_Level2InterruptVector_text,
 		  .Level2InterruptVector.text,
-		  XCHAL_INTLEVEL2_VECTOR_VADDR,
+		  INTLEVEL2_VECTOR_VADDR,
 		  SIZEOF(LAST), LAST)
 # undef LAST
 # define LAST	.Level2InterruptVector.text
@@ -210,7 +211,7 @@ SECTIONS
 #if XCHAL_EXCM_LEVEL >= 3
   SECTION_VECTOR (_Level3InterruptVector_text,
 		  .Level3InterruptVector.text,
-		  XCHAL_INTLEVEL3_VECTOR_VADDR,
+		  INTLEVEL3_VECTOR_VADDR,
 		  SIZEOF(LAST), LAST)
 # undef LAST
 # define LAST	.Level3InterruptVector.text
@@ -218,7 +219,7 @@ SECTIONS
 #if XCHAL_EXCM_LEVEL >= 4
   SECTION_VECTOR (_Level4InterruptVector_text,
 		  .Level4InterruptVector.text,
-		  XCHAL_INTLEVEL4_VECTOR_VADDR,
+		  INTLEVEL4_VECTOR_VADDR,
 		  SIZEOF(LAST), LAST)
 # undef LAST
 # define LAST	.Level4InterruptVector.text
@@ -226,7 +227,7 @@ SECTIONS
 #if XCHAL_EXCM_LEVEL >= 5
   SECTION_VECTOR (_Level5InterruptVector_text,
 		  .Level5InterruptVector.text,
-		  XCHAL_INTLEVEL5_VECTOR_VADDR,
+		  INTLEVEL5_VECTOR_VADDR,
 		  SIZEOF(LAST), LAST)
 # undef LAST
 # define LAST	.Level5InterruptVector.text
@@ -234,39 +235,39 @@ SECTIONS
 #if XCHAL_EXCM_LEVEL >= 6
   SECTION_VECTOR (_Level6InterruptVector_text,
 		  .Level6InterruptVector.text,
-		  XCHAL_INTLEVEL6_VECTOR_VADDR,
+		  INTLEVEL6_VECTOR_VADDR,
 		  SIZEOF(LAST), LAST)
 # undef LAST
 # define LAST	.Level6InterruptVector.text
 #endif
   SECTION_VECTOR (_KernelExceptionVector_literal,
 		  .KernelExceptionVector.literal,
-		  XCHAL_KERNEL_VECTOR_VADDR - 4,
+		  KERNEL_VECTOR_VADDR - 4,
 		  SIZEOF(LAST), LAST)
 #undef LAST
   SECTION_VECTOR (_KernelExceptionVector_text,
 		  .KernelExceptionVector.text,
-		  XCHAL_KERNEL_VECTOR_VADDR,
+		  KERNEL_VECTOR_VADDR,
 		  4,
 		  .KernelExceptionVector.literal)
   SECTION_VECTOR (_UserExceptionVector_literal,
 		  .UserExceptionVector.literal,
-		  XCHAL_USER_VECTOR_VADDR - 4,
+		  USER_VECTOR_VADDR - 4,
 		  SIZEOF(.KernelExceptionVector.text),
 		  .KernelExceptionVector.text)
   SECTION_VECTOR (_UserExceptionVector_text,
 		  .UserExceptionVector.text,
-		  XCHAL_USER_VECTOR_VADDR,
+		  USER_VECTOR_VADDR,
 		  4,
 		  .UserExceptionVector.literal)
   SECTION_VECTOR (_DoubleExceptionVector_literal,
 		  .DoubleExceptionVector.literal,
-		  XCHAL_DOUBLEEXC_VECTOR_VADDR - 16,
+		  DOUBLEEXC_VECTOR_VADDR - 16,
 		  SIZEOF(.UserExceptionVector.text),
 		  .UserExceptionVector.text)
   SECTION_VECTOR (_DoubleExceptionVector_text,
 		  .DoubleExceptionVector.text,
-		  XCHAL_DOUBLEEXC_VECTOR_VADDR,
+		  DOUBLEEXC_VECTOR_VADDR,
 		  32,
 		  .DoubleExceptionVector.literal)
 
@@ -284,11 +285,26 @@ SECTIONS
   . = ALIGN(0x10);
   .bootstrap : { *(.bootstrap.literal .bootstrap.text .bootstrap.data) }
 
-  .ResetVector.text XCHAL_RESET_VECTOR_VADDR :
+  .ResetVector.text RESET_VECTOR_VADDR :
   {
     *(.ResetVector.text)
   }
 
+
+  /*
+   * This is a remapped copy of the Secondary Reset Vector Code.
+   * It keeps gdb in sync with the PC after switching
+   * to the temporary mapping used while setting up
+   * the V2 MMU mappings for Linux.
+   *
+   * Only debug information about this section is put in the kernel image.
+   */
+  .SecondaryResetVector.remapped_text 0x46000000 (INFO):
+  {
+	*(.SecondaryResetVector.remapped_text)
+  }
+
+
   .xt.lit : { *(.xt.lit) }
   .xt.prop : { *(.xt.prop) }
 
diff --git a/arch/xtensa/kernel/xtensa_ksyms.c b/arch/xtensa/kernel/xtensa_ksyms.c
index afe058b..42c53c87 100644
--- a/arch/xtensa/kernel/xtensa_ksyms.c
+++ b/arch/xtensa/kernel/xtensa_ksyms.c
@@ -119,3 +119,8 @@ EXPORT_SYMBOL(outsl);
 EXPORT_SYMBOL(insb);
 EXPORT_SYMBOL(insw);
 EXPORT_SYMBOL(insl);
+
+extern long common_exception_return;
+extern long _spill_registers;
+EXPORT_SYMBOL(common_exception_return);
+EXPORT_SYMBOL(_spill_registers);
diff --git a/arch/xtensa/mm/init.c b/arch/xtensa/mm/init.c
index 7a5156f..bba125b 100644
--- a/arch/xtensa/mm/init.c
+++ b/arch/xtensa/mm/init.c
@@ -208,32 +208,17 @@ void __init mem_init(void)
 	       highmemsize >> 10);
 }
 
-void
-free_reserved_mem(void *start, void *end)
-{
-	for (; start < end; start += PAGE_SIZE) {
-		ClearPageReserved(virt_to_page(start));
-		init_page_count(virt_to_page(start));
-		free_page((unsigned long)start);
-		totalram_pages++;
-	}
-}
-
 #ifdef CONFIG_BLK_DEV_INITRD
 extern int initrd_is_mapped;
 
 void free_initrd_mem(unsigned long start, unsigned long end)
 {
-	if (initrd_is_mapped) {
-		free_reserved_mem((void*)start, (void*)end);
-		printk ("Freeing initrd memory: %ldk freed\n",(end-start)>>10);
-	}
+	if (initrd_is_mapped)
+		free_reserved_area(start, end, 0, "initrd");
 }
 #endif
 
 void free_initmem(void)
 {
-	free_reserved_mem(__init_begin, __init_end);
-	printk("Freeing unused kernel memory: %zuk freed\n",
-	       (__init_end - __init_begin) >> 10);
+	free_initmem_default(0);
 }
diff --git a/arch/xtensa/mm/mmu.c b/arch/xtensa/mm/mmu.c
index 0f77f9d..a107757 100644
--- a/arch/xtensa/mm/mmu.c
+++ b/arch/xtensa/mm/mmu.c
@@ -24,15 +24,19 @@ void __init paging_init(void)
  */
 void __init init_mmu(void)
 {
-	/* Writing zeros to the <t>TLBCFG special registers ensure
-	 * that valid values exist in the register.  For existing
-	 * PGSZID<w> fields, zero selects the first element of the
-	 * page-size array.  For nonexistent PGSZID<w> fields, zero is
-	 * the best value to write.  Also, when changing PGSZID<w>
+#if !(XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY)
+	/*
+	 * Writing zeros to the instruction and data TLBCFG special
+	 * registers ensure that valid values exist in the register.
+	 *
+	 * For existing PGSZID<w> fields, zero selects the first element
+	 * of the page-size array.  For nonexistent PGSZID<w> fields,
+	 * zero is the best value to write.  Also, when changing PGSZID<w>
 	 * fields, the corresponding TLB must be flushed.
 	 */
 	set_itlbcfg_register(0);
 	set_dtlbcfg_register(0);
+#endif
 	flush_tlb_all();
 
 	/* Set rasid register to a known value. */
diff --git a/arch/xtensa/oprofile/backtrace.c b/arch/xtensa/oprofile/backtrace.c
index 66f32ee..5f03a59 100644
--- a/arch/xtensa/oprofile/backtrace.c
+++ b/arch/xtensa/oprofile/backtrace.c
@@ -132,9 +132,7 @@ static void xtensa_backtrace_kernel(struct pt_regs *regs, unsigned int depth)
 		pc = MAKE_PC_FROM_RA(a0, pc);
 
 		/* Add the PC to the trace. */
-		if (kernel_text_address(pc))
-			oprofile_add_trace(pc);
-
+		oprofile_add_trace(pc);
 		if (pc == (unsigned long) &common_exception_return) {
 			regs = (struct pt_regs *)a1;
 			if (user_mode(regs)) {
diff --git a/arch/xtensa/platforms/iss/setup.c b/arch/xtensa/platforms/iss/setup.c
index e170010..da7d182 100644
--- a/arch/xtensa/platforms/iss/setup.c
+++ b/arch/xtensa/platforms/iss/setup.c
@@ -38,12 +38,6 @@ void __init platform_init(bp_tag_t* bootparam)
 
 }
 
-#ifdef CONFIG_PCI
-void platform_pcibios_init(void)
-{
-}
-#endif
-
 void platform_halt(void)
 {
 	pr_info(" ** Called platform_halt() **\n");
@@ -64,7 +58,9 @@ void platform_restart(void)
 			     "wsr	a2, icountlevel\n\t"
 			     "movi	a2, 0\n\t"
 			     "wsr	a2, icount\n\t"
+#if XCHAL_NUM_IBREAK > 0
 			     "wsr	a2, ibreakenable\n\t"
+#endif
 			     "wsr	a2, lcount\n\t"
 			     "movi	a2, 0x1f\n\t"
 			     "wsr	a2, ps\n\t"
diff --git a/arch/xtensa/platforms/iss/simdisk.c b/arch/xtensa/platforms/iss/simdisk.c
index f58ffc3..4a06d70 100644
--- a/arch/xtensa/platforms/iss/simdisk.c
+++ b/arch/xtensa/platforms/iss/simdisk.c
@@ -214,20 +214,27 @@ static int simdisk_detach(struct simdisk *dev)
 	return err;
 }
 
-static int proc_read_simdisk(char *page, char **start, off_t off,
-		int count, int *eof, void *data)
+static ssize_t proc_read_simdisk(struct file *file, char __user *buf,
+			size_t size, loff_t *ppos)
 {
-	int len;
-	struct simdisk *dev = (struct simdisk *) data;
-	len = sprintf(page, "%s\n", dev->filename ? dev->filename : "");
-	return len;
+	struct simdisk *dev = PDE_DATA(file_inode(file));
+	char *s = dev->filename;
+	if (s) {
+		ssize_t n = simple_read_from_buffer(buf, size, ppos,
+							s, strlen(s));
+		if (n < 0)
+			return n;
+		buf += n;
+		size -= n;
+	}
+	return simple_read_from_buffer(buf, size, ppos, "\n", 1);
 }
 
-static int proc_write_simdisk(struct file *file, const char *buffer,
-		unsigned long count, void *data)
+static ssize_t proc_write_simdisk(struct file *file, const char __user *buf,
+			size_t size, loff_t *ppos)
 {
 	char *tmp = kmalloc(count + 1, GFP_KERNEL);
-	struct simdisk *dev = (struct simdisk *) data;
+	struct simdisk *dev = PDE_DATA(file_inode(file));
 	int err;
 
 	if (tmp == NULL)
@@ -256,6 +263,12 @@ out_free:
 	return err;
 }
 
+static const struct file_operations fops = {
+	.read = proc_read_simdisk,
+	.write = proc_write_simdisk,
+	.llseek = default_llseek,
+};
+
 static int __init simdisk_setup(struct simdisk *dev, int which,
 		struct proc_dir_entry *procdir)
 {
@@ -289,10 +302,7 @@ static int __init simdisk_setup(struct simdisk *dev, int which,
 	set_capacity(dev->gd, 0);
 	add_disk(dev->gd);
 
-	dev->procfile = create_proc_entry(tmp, 0644, procdir);
-	dev->procfile->data = dev;
-	dev->procfile->read_proc = proc_read_simdisk;
-	dev->procfile->write_proc = proc_write_simdisk;
+	dev->procfile = proc_create_data(tmp, 0644, procdir, &fops, dev);
 	return 0;
 
 out_alloc_disk:
diff --git a/arch/xtensa/platforms/xt2000/setup.c b/arch/xtensa/platforms/xt2000/setup.c
index c7d90f1..f9bc879 100644
--- a/arch/xtensa/platforms/xt2000/setup.c
+++ b/arch/xtensa/platforms/xt2000/setup.c
@@ -69,7 +69,9 @@ void platform_restart(void)
 			      "wsr	a2, icountlevel\n\t"
 			      "movi	a2, 0\n\t"
 			      "wsr	a2, icount\n\t"
+#if XCHAL_NUM_IBREAK > 0
 			      "wsr	a2, ibreakenable\n\t"
+#endif
 			      "wsr	a2, lcount\n\t"
 			      "movi	a2, 0x1f\n\t"
 			      "wsr	a2, ps\n\t"
diff --git a/arch/xtensa/platforms/xtfpga/setup.c b/arch/xtensa/platforms/xtfpga/setup.c
index 9d888a2..96ef8ee 100644
--- a/arch/xtensa/platforms/xtfpga/setup.c
+++ b/arch/xtensa/platforms/xtfpga/setup.c
@@ -60,7 +60,9 @@ void platform_restart(void)
 			      "wsr	a2, icountlevel\n\t"
 			      "movi	a2, 0\n\t"
 			      "wsr	a2, icount\n\t"
+#if XCHAL_NUM_IBREAK > 0
 			      "wsr	a2, ibreakenable\n\t"
+#endif
 			      "wsr	a2, lcount\n\t"
 			      "movi	a2, 0x1f\n\t"
 			      "wsr	a2, ps\n\t"
diff --git a/block/blk-cgroup.h b/block/blk-cgroup.h
index f2b2929..4e595ee 100644
--- a/block/blk-cgroup.h
+++ b/block/blk-cgroup.h
@@ -247,9 +247,7 @@ static inline int blkg_path(struct blkcg_gq *blkg, char *buf, int buflen)
 {
 	int ret;
 
-	rcu_read_lock();
 	ret = cgroup_path(blkg->blkcg->css.cgroup, buf, buflen);
-	rcu_read_unlock();
 	if (ret)
 		strncpy(buf, "<unavailable>", buflen);
 	return ret;
diff --git a/block/blk-core.c b/block/blk-core.c
index 074b758..492242f 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -30,6 +30,7 @@
 #include <linux/list_sort.h>
 #include <linux/delay.h>
 #include <linux/ratelimit.h>
+#include <linux/pm_runtime.h>
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/block.h>
@@ -151,31 +152,22 @@ void blk_rq_init(struct request_queue *q, struct request *rq)
 EXPORT_SYMBOL(blk_rq_init);
 
 static void req_bio_endio(struct request *rq, struct bio *bio,
-			  unsigned int nbytes, int error)
+			  unsigned int nbytes, int error,
+			  struct batch_complete *batch)
 {
 	if (error)
 		clear_bit(BIO_UPTODATE, &bio->bi_flags);
 	else if (!test_bit(BIO_UPTODATE, &bio->bi_flags))
 		error = -EIO;
 
-	if (unlikely(nbytes > bio->bi_size)) {
-		printk(KERN_ERR "%s: want %u bytes done, %u left\n",
-		       __func__, nbytes, bio->bi_size);
-		nbytes = bio->bi_size;
-	}
-
 	if (unlikely(rq->cmd_flags & REQ_QUIET))
 		set_bit(BIO_QUIET, &bio->bi_flags);
 
-	bio->bi_size -= nbytes;
-	bio->bi_sector += (nbytes >> 9);
-
-	if (bio_integrity(bio))
-		bio_integrity_advance(bio, nbytes);
+	bio_advance(bio, nbytes);
 
 	/* don't actually finish bio if it's part of flush sequence */
 	if (bio->bi_size == 0 && !(rq->cmd_flags & REQ_FLUSH_SEQ))
-		bio_endio(bio, error);
+		bio_endio_batch(bio, error, batch);
 }
 
 void blk_dump_rq_flags(struct request *rq, char *msg)
@@ -1263,6 +1255,16 @@ void part_round_stats(int cpu, struct hd_struct *part)
 }
 EXPORT_SYMBOL_GPL(part_round_stats);
 
+#ifdef CONFIG_PM_RUNTIME
+static void blk_pm_put_request(struct request *rq)
+{
+	if (rq->q->dev && !(rq->cmd_flags & REQ_PM) && !--rq->q->nr_pending)
+		pm_runtime_mark_last_busy(rq->q->dev);
+}
+#else
+static inline void blk_pm_put_request(struct request *rq) {}
+#endif
+
 /*
  * queue lock must be held
  */
@@ -1273,6 +1275,8 @@ void __blk_put_request(struct request_queue *q, struct request *req)
 	if (unlikely(--req->ref_count))
 		return;
 
+	blk_pm_put_request(req);
+
 	elv_completed_request(q, req);
 
 	/* this is a bio leak */
@@ -1596,7 +1600,7 @@ static void handle_bad_sector(struct bio *bio)
 	printk(KERN_INFO "%s: rw=%ld, want=%Lu, limit=%Lu\n",
 			bdevname(bio->bi_bdev, b),
 			bio->bi_rw,
-			(unsigned long long)bio->bi_sector + bio_sectors(bio),
+			(unsigned long long)bio_end_sector(bio),
 			(long long)(i_size_read(bio->bi_bdev->bd_inode) >> 9));
 
 	set_bit(BIO_EOF, &bio->bi_flags);
@@ -2052,6 +2056,28 @@ static void blk_account_io_done(struct request *req)
 	}
 }
 
+#ifdef CONFIG_PM_RUNTIME
+/*
+ * Don't process normal requests when queue is suspended
+ * or in the process of suspending/resuming
+ */
+static struct request *blk_pm_peek_request(struct request_queue *q,
+					   struct request *rq)
+{
+	if (q->dev && (q->rpm_status == RPM_SUSPENDED ||
+	    (q->rpm_status != RPM_ACTIVE && !(rq->cmd_flags & REQ_PM))))
+		return NULL;
+	else
+		return rq;
+}
+#else
+static inline struct request *blk_pm_peek_request(struct request_queue *q,
+						  struct request *rq)
+{
+	return rq;
+}
+#endif
+
 /**
  * blk_peek_request - peek at the top of a request queue
  * @q: request queue to peek at
@@ -2074,6 +2100,11 @@ struct request *blk_peek_request(struct request_queue *q)
 	int ret;
 
 	while ((rq = __elv_next_request(q)) != NULL) {
+
+		rq = blk_pm_peek_request(q, rq);
+		if (!rq)
+			break;
+
 		if (!(rq->cmd_flags & REQ_STARTED)) {
 			/*
 			 * This is the first time the device driver
@@ -2250,10 +2281,10 @@ EXPORT_SYMBOL(blk_fetch_request);
  *     %false - this request doesn't have any more data
  *     %true  - this request has more data
  **/
-bool blk_update_request(struct request *req, int error, unsigned int nr_bytes)
+bool blk_update_request(struct request *req, int error, unsigned int nr_bytes,
+			struct batch_complete *batch)
 {
-	int total_bytes, bio_nbytes, next_idx = 0;
-	struct bio *bio;
+	int total_bytes;
 
 	if (!req->bio)
 		return false;
@@ -2299,56 +2330,21 @@ bool blk_update_request(struct request *req, int error, unsigned int nr_bytes)
 
 	blk_account_io_completion(req, nr_bytes);
 
-	total_bytes = bio_nbytes = 0;
-	while ((bio = req->bio) != NULL) {
-		int nbytes;
+	total_bytes = 0;
+	while (req->bio) {
+		struct bio *bio = req->bio;
+		unsigned bio_bytes = min(bio->bi_size, nr_bytes);
 
-		if (nr_bytes >= bio->bi_size) {
+		if (bio_bytes == bio->bi_size)
 			req->bio = bio->bi_next;
-			nbytes = bio->bi_size;
-			req_bio_endio(req, bio, nbytes, error);
-			next_idx = 0;
-			bio_nbytes = 0;
-		} else {
-			int idx = bio->bi_idx + next_idx;
 
-			if (unlikely(idx >= bio->bi_vcnt)) {
-				blk_dump_rq_flags(req, "__end_that");
-				printk(KERN_ERR "%s: bio idx %d >= vcnt %d\n",
-				       __func__, idx, bio->bi_vcnt);
-				break;
-			}
+		req_bio_endio(req, bio, bio_bytes, error, batch);
 
-			nbytes = bio_iovec_idx(bio, idx)->bv_len;
-			BIO_BUG_ON(nbytes > bio->bi_size);
+		total_bytes += bio_bytes;
+		nr_bytes -= bio_bytes;
 
-			/*
-			 * not a complete bvec done
-			 */
-			if (unlikely(nbytes > nr_bytes)) {
-				bio_nbytes += nr_bytes;
-				total_bytes += nr_bytes;
-				break;
-			}
-
-			/*
-			 * advance to the next vector
-			 */
-			next_idx++;
-			bio_nbytes += nbytes;
-		}
-
-		total_bytes += nbytes;
-		nr_bytes -= nbytes;
-
-		bio = req->bio;
-		if (bio) {
-			/*
-			 * end more in this run, or just return 'not-done'
-			 */
-			if (unlikely(nr_bytes <= 0))
-				break;
-		}
+		if (!nr_bytes)
+			break;
 	}
 
 	/*
@@ -2364,16 +2360,6 @@ bool blk_update_request(struct request *req, int error, unsigned int nr_bytes)
 		return false;
 	}
 
-	/*
-	 * if the request wasn't completed, update state
-	 */
-	if (bio_nbytes) {
-		req_bio_endio(req, bio, bio_nbytes, error);
-		bio->bi_idx += next_idx;
-		bio_iovec(bio)->bv_offset += nr_bytes;
-		bio_iovec(bio)->bv_len -= nr_bytes;
-	}
-
 	req->__data_len -= total_bytes;
 	req->buffer = bio_data(req->bio);
 
@@ -2405,14 +2391,15 @@ EXPORT_SYMBOL_GPL(blk_update_request);
 
 static bool blk_update_bidi_request(struct request *rq, int error,
 				    unsigned int nr_bytes,
-				    unsigned int bidi_bytes)
+				    unsigned int bidi_bytes,
+				    struct batch_complete *batch)
 {
-	if (blk_update_request(rq, error, nr_bytes))
+	if (blk_update_request(rq, error, nr_bytes, batch))
 		return true;
 
 	/* Bidi request must be completed as a whole */
 	if (unlikely(blk_bidi_rq(rq)) &&
-	    blk_update_request(rq->next_rq, error, bidi_bytes))
+	    blk_update_request(rq->next_rq, error, bidi_bytes, batch))
 		return true;
 
 	if (blk_queue_add_random(rq->q))
@@ -2495,7 +2482,7 @@ static bool blk_end_bidi_request(struct request *rq, int error,
 	struct request_queue *q = rq->q;
 	unsigned long flags;
 
-	if (blk_update_bidi_request(rq, error, nr_bytes, bidi_bytes))
+	if (blk_update_bidi_request(rq, error, nr_bytes, bidi_bytes, NULL))
 		return true;
 
 	spin_lock_irqsave(q->queue_lock, flags);
@@ -2521,9 +2508,11 @@ static bool blk_end_bidi_request(struct request *rq, int error,
  *     %true  - still buffers pending for this request
  **/
 bool __blk_end_bidi_request(struct request *rq, int error,
-				   unsigned int nr_bytes, unsigned int bidi_bytes)
+				   unsigned int nr_bytes,
+				   unsigned int bidi_bytes,
+				   struct batch_complete *batch)
 {
-	if (blk_update_bidi_request(rq, error, nr_bytes, bidi_bytes))
+	if (blk_update_bidi_request(rq, error, nr_bytes, bidi_bytes, batch))
 		return true;
 
 	blk_finish_request(rq, error);
@@ -2624,7 +2613,7 @@ EXPORT_SYMBOL_GPL(blk_end_request_err);
  **/
 bool __blk_end_request(struct request *rq, int error, unsigned int nr_bytes)
 {
-	return __blk_end_bidi_request(rq, error, nr_bytes, 0);
+	return __blk_end_bidi_request(rq, error, nr_bytes, 0, NULL);
 }
 EXPORT_SYMBOL(__blk_end_request);
 
@@ -2636,7 +2625,8 @@ EXPORT_SYMBOL(__blk_end_request);
  * Description:
  *     Completely finish @rq.  Must be called with queue lock held.
  */
-void __blk_end_request_all(struct request *rq, int error)
+void blk_end_request_all_batch(struct request *rq, int error,
+			       struct batch_complete *batch)
 {
 	bool pending;
 	unsigned int bidi_bytes = 0;
@@ -2644,10 +2634,11 @@ void __blk_end_request_all(struct request *rq, int error)
 	if (unlikely(blk_bidi_rq(rq)))
 		bidi_bytes = blk_rq_bytes(rq->next_rq);
 
-	pending = __blk_end_bidi_request(rq, error, blk_rq_bytes(rq), bidi_bytes);
+	pending = __blk_end_bidi_request(rq, error, blk_rq_bytes(rq),
+					 bidi_bytes, batch);
 	BUG_ON(pending);
 }
-EXPORT_SYMBOL(__blk_end_request_all);
+EXPORT_SYMBOL(blk_end_request_all_batch);
 
 /**
  * __blk_end_request_cur - Helper function to finish the current request chunk.
@@ -3045,6 +3036,149 @@ void blk_finish_plug(struct blk_plug *plug)
 }
 EXPORT_SYMBOL(blk_finish_plug);
 
+#ifdef CONFIG_PM_RUNTIME
+/**
+ * blk_pm_runtime_init - Block layer runtime PM initialization routine
+ * @q: the queue of the device
+ * @dev: the device the queue belongs to
+ *
+ * Description:
+ *    Initialize runtime-PM-related fields for @q and start auto suspend for
+ *    @dev. Drivers that want to take advantage of request-based runtime PM
+ *    should call this function after @dev has been initialized, and its
+ *    request queue @q has been allocated, and runtime PM for it can not happen
+ *    yet(either due to disabled/forbidden or its usage_count > 0). In most
+ *    cases, driver should call this function before any I/O has taken place.
+ *
+ *    This function takes care of setting up using auto suspend for the device,
+ *    the autosuspend delay is set to -1 to make runtime suspend impossible
+ *    until an updated value is either set by user or by driver. Drivers do
+ *    not need to touch other autosuspend settings.
+ *
+ *    The block layer runtime PM is request based, so only works for drivers
+ *    that use request as their IO unit instead of those directly use bio's.
+ */
+void blk_pm_runtime_init(struct request_queue *q, struct device *dev)
+{
+	q->dev = dev;
+	q->rpm_status = RPM_ACTIVE;
+	pm_runtime_set_autosuspend_delay(q->dev, -1);
+	pm_runtime_use_autosuspend(q->dev);
+}
+EXPORT_SYMBOL(blk_pm_runtime_init);
+
+/**
+ * blk_pre_runtime_suspend - Pre runtime suspend check
+ * @q: the queue of the device
+ *
+ * Description:
+ *    This function will check if runtime suspend is allowed for the device
+ *    by examining if there are any requests pending in the queue. If there
+ *    are requests pending, the device can not be runtime suspended; otherwise,
+ *    the queue's status will be updated to SUSPENDING and the driver can
+ *    proceed to suspend the device.
+ *
+ *    For the not allowed case, we mark last busy for the device so that
+ *    runtime PM core will try to autosuspend it some time later.
+ *
+ *    This function should be called near the start of the device's
+ *    runtime_suspend callback.
+ *
+ * Return:
+ *    0		- OK to runtime suspend the device
+ *    -EBUSY	- Device should not be runtime suspended
+ */
+int blk_pre_runtime_suspend(struct request_queue *q)
+{
+	int ret = 0;
+
+	spin_lock_irq(q->queue_lock);
+	if (q->nr_pending) {
+		ret = -EBUSY;
+		pm_runtime_mark_last_busy(q->dev);
+	} else {
+		q->rpm_status = RPM_SUSPENDING;
+	}
+	spin_unlock_irq(q->queue_lock);
+	return ret;
+}
+EXPORT_SYMBOL(blk_pre_runtime_suspend);
+
+/**
+ * blk_post_runtime_suspend - Post runtime suspend processing
+ * @q: the queue of the device
+ * @err: return value of the device's runtime_suspend function
+ *
+ * Description:
+ *    Update the queue's runtime status according to the return value of the
+ *    device's runtime suspend function and mark last busy for the device so
+ *    that PM core will try to auto suspend the device at a later time.
+ *
+ *    This function should be called near the end of the device's
+ *    runtime_suspend callback.
+ */
+void blk_post_runtime_suspend(struct request_queue *q, int err)
+{
+	spin_lock_irq(q->queue_lock);
+	if (!err) {
+		q->rpm_status = RPM_SUSPENDED;
+	} else {
+		q->rpm_status = RPM_ACTIVE;
+		pm_runtime_mark_last_busy(q->dev);
+	}
+	spin_unlock_irq(q->queue_lock);
+}
+EXPORT_SYMBOL(blk_post_runtime_suspend);
+
+/**
+ * blk_pre_runtime_resume - Pre runtime resume processing
+ * @q: the queue of the device
+ *
+ * Description:
+ *    Update the queue's runtime status to RESUMING in preparation for the
+ *    runtime resume of the device.
+ *
+ *    This function should be called near the start of the device's
+ *    runtime_resume callback.
+ */
+void blk_pre_runtime_resume(struct request_queue *q)
+{
+	spin_lock_irq(q->queue_lock);
+	q->rpm_status = RPM_RESUMING;
+	spin_unlock_irq(q->queue_lock);
+}
+EXPORT_SYMBOL(blk_pre_runtime_resume);
+
+/**
+ * blk_post_runtime_resume - Post runtime resume processing
+ * @q: the queue of the device
+ * @err: return value of the device's runtime_resume function
+ *
+ * Description:
+ *    Update the queue's runtime status according to the return value of the
+ *    device's runtime_resume function. If it is successfully resumed, process
+ *    the requests that are queued into the device's queue when it is resuming
+ *    and then mark last busy and initiate autosuspend for it.
+ *
+ *    This function should be called near the end of the device's
+ *    runtime_resume callback.
+ */
+void blk_post_runtime_resume(struct request_queue *q, int err)
+{
+	spin_lock_irq(q->queue_lock);
+	if (!err) {
+		q->rpm_status = RPM_ACTIVE;
+		__blk_run_queue(q);
+		pm_runtime_mark_last_busy(q->dev);
+		pm_runtime_autosuspend(q->dev);
+	} else {
+		q->rpm_status = RPM_SUSPENDED;
+	}
+	spin_unlock_irq(q->queue_lock);
+}
+EXPORT_SYMBOL(blk_post_runtime_resume);
+#endif
+
 int __init blk_dev_init(void)
 {
 	BUILD_BUG_ON(__REQ_NR_BITS > 8 *
diff --git a/block/blk-flush.c b/block/blk-flush.c
index cc2b827..ab0ed23 100644
--- a/block/blk-flush.c
+++ b/block/blk-flush.c
@@ -316,7 +316,7 @@ void blk_insert_flush(struct request *rq)
 	 * complete the request.
 	 */
 	if (!policy) {
-		__blk_end_bidi_request(rq, 0, 0, 0);
+		__blk_end_bidi_request(rq, 0, 0, 0, NULL);
 		return;
 	}
 
@@ -384,7 +384,8 @@ void blk_abort_flushes(struct request_queue *q)
 	}
 }
 
-static void bio_end_flush(struct bio *bio, int err)
+static void bio_end_flush(struct bio *bio, int err,
+			  struct batch_complete *batch)
 {
 	if (err)
 		clear_bit(BIO_UPTODATE, &bio->bi_flags);
diff --git a/block/blk-integrity.c b/block/blk-integrity.c
index dabd221..03cf717 100644
--- a/block/blk-integrity.c
+++ b/block/blk-integrity.c
@@ -110,7 +110,7 @@ new_segment:
 			if (!sg)
 				sg = sglist;
 			else {
-				sg->page_link &= ~0x02;
+				sg_unmark_end(sg);
 				sg = sg_next(sg);
 			}
 
diff --git a/block/blk-lib.c b/block/blk-lib.c
index d6f50d5..279f9de 100644
--- a/block/blk-lib.c
+++ b/block/blk-lib.c
@@ -15,7 +15,8 @@ struct bio_batch {
 	struct completion	*wait;
 };
 
-static void bio_batch_end_io(struct bio *bio, int err)
+static void bio_batch_end_io(struct bio *bio, int err,
+			     struct batch_complete *batch)
 {
 	struct bio_batch *bb = bio->bi_private;
 
diff --git a/block/blk-merge.c b/block/blk-merge.c
index 936a110..5f24482 100644
--- a/block/blk-merge.c
+++ b/block/blk-merge.c
@@ -143,7 +143,7 @@ new_segment:
 			 * termination bit to avoid doing a full
 			 * sg_init_table() in drivers for each command.
 			 */
-			(*sg)->page_link &= ~0x02;
+			sg_unmark_end(*sg);
 			*sg = sg_next(*sg);
 		}
 
diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c
index 6206a93..5efc5a6 100644
--- a/block/blk-sysfs.c
+++ b/block/blk-sysfs.c
@@ -229,6 +229,8 @@ queue_store_##name(struct request_queue *q, const char *page, size_t count) \
 	unsigned long val;						\
 	ssize_t ret;							\
 	ret = queue_var_store(&val, page, count);			\
+	if (ret < 0)							\
+		 return ret;						\
 	if (neg)							\
 		val = !val;						\
 									\
diff --git a/block/blk.h b/block/blk.h
index e837b8f..dc8fee6 100644
--- a/block/blk.h
+++ b/block/blk.h
@@ -31,7 +31,8 @@ void blk_queue_bypass_end(struct request_queue *q);
 void blk_dequeue_request(struct request *rq);
 void __blk_queue_free_tags(struct request_queue *q);
 bool __blk_end_bidi_request(struct request *rq, int error,
-			    unsigned int nr_bytes, unsigned int bidi_bytes);
+			    unsigned int nr_bytes, unsigned int bidi_bytes,
+			    struct batch_complete *batch);
 
 void blk_rq_timed_out_timer(unsigned long data);
 void blk_delete_timer(struct request *);
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index 4f0ade7..d5cd313 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -2270,11 +2270,8 @@ cfq_find_rq_fmerge(struct cfq_data *cfqd, struct bio *bio)
 		return NULL;
 
 	cfqq = cic_to_cfqq(cic, cfq_bio_sync(bio));
-	if (cfqq) {
-		sector_t sector = bio->bi_sector + bio_sectors(bio);
-
-		return elv_rb_find(&cfqq->sort_list, sector);
-	}
+	if (cfqq)
+		return elv_rb_find(&cfqq->sort_list, bio_end_sector(bio));
 
 	return NULL;
 }
diff --git a/block/deadline-iosched.c b/block/deadline-iosched.c
index 90037b5..ba19a3a 100644
--- a/block/deadline-iosched.c
+++ b/block/deadline-iosched.c
@@ -132,7 +132,7 @@ deadline_merge(struct request_queue *q, struct request **req, struct bio *bio)
 	 * check for front merge
 	 */
 	if (dd->front_merges) {
-		sector_t sector = bio->bi_sector + bio_sectors(bio);
+		sector_t sector = bio_end_sector(bio);
 
 		__rq = elv_rb_find(&dd->sort_list[bio_data_dir(bio)], sector);
 		if (__rq) {
diff --git a/block/elevator.c b/block/elevator.c
index a0ffdd9..eba5b04 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -34,6 +34,7 @@
 #include <linux/blktrace_api.h>
 #include <linux/hash.h>
 #include <linux/uaccess.h>
+#include <linux/pm_runtime.h>
 
 #include <trace/events/block.h>
 
@@ -536,6 +537,27 @@ void elv_bio_merged(struct request_queue *q, struct request *rq,
 		e->type->ops.elevator_bio_merged_fn(q, rq, bio);
 }
 
+#ifdef CONFIG_PM_RUNTIME
+static void blk_pm_requeue_request(struct request *rq)
+{
+	if (rq->q->dev && !(rq->cmd_flags & REQ_PM))
+		rq->q->nr_pending--;
+}
+
+static void blk_pm_add_request(struct request_queue *q, struct request *rq)
+{
+	if (q->dev && !(rq->cmd_flags & REQ_PM) && q->nr_pending++ == 0 &&
+	    (q->rpm_status == RPM_SUSPENDED || q->rpm_status == RPM_SUSPENDING))
+		pm_request_resume(q->dev);
+}
+#else
+static inline void blk_pm_requeue_request(struct request *rq) {}
+static inline void blk_pm_add_request(struct request_queue *q,
+				      struct request *rq)
+{
+}
+#endif
+
 void elv_requeue_request(struct request_queue *q, struct request *rq)
 {
 	/*
@@ -550,6 +572,8 @@ void elv_requeue_request(struct request_queue *q, struct request *rq)
 
 	rq->cmd_flags &= ~REQ_STARTED;
 
+	blk_pm_requeue_request(rq);
+
 	__elv_add_request(q, rq, ELEVATOR_INSERT_REQUEUE);
 }
 
@@ -572,6 +596,8 @@ void __elv_add_request(struct request_queue *q, struct request *rq, int where)
 {
 	trace_block_rq_insert(q, rq);
 
+	blk_pm_add_request(q, rq);
+
 	rq->q = q;
 
 	if (rq->cmd_flags & REQ_SOFTBARRIER) {
diff --git a/block/genhd.c b/block/genhd.c
index 3c001fb..a1ed52a 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -849,7 +849,7 @@ static int show_partition(struct seq_file *seqf, void *v)
 	char buf[BDEVNAME_SIZE];
 
 	/* Don't show non-partitionable removeable devices or empty devices */
-	if (!get_capacity(sgp) || (!disk_max_parts(sgp) &&
+	if (!get_capacity(sgp) || (!(disk_max_parts(sgp) > 1) &&
 				   (sgp->flags & GENHD_FL_REMOVABLE)))
 		return 0;
 	if (sgp->flags & GENHD_FL_SUPPRESS_PARTITION_INFO)
diff --git a/block/partitions/Makefile b/block/partitions/Makefile
index 03af8ea..bf26d4a 100644
--- a/block/partitions/Makefile
+++ b/block/partitions/Makefile
@@ -18,3 +18,4 @@ obj-$(CONFIG_IBM_PARTITION) += ibm.o
 obj-$(CONFIG_EFI_PARTITION) += efi.o
 obj-$(CONFIG_KARMA_PARTITION) += karma.o
 obj-$(CONFIG_SYSV68_PARTITION) += sysv68.o
+obj-$(CONFIG_BLOCKCONSOLE) += blockconsole.o
diff --git a/block/partitions/blockconsole.c b/block/partitions/blockconsole.c
new file mode 100644
index 0000000..79796a8
--- /dev/null
+++ b/block/partitions/blockconsole.c
@@ -0,0 +1,22 @@
+#include <linux/blockconsole.h>
+
+#include "check.h"
+
+int blockconsole_partition(struct parsed_partitions *state)
+{
+	Sector sect;
+	void *data;
+	int err = 0;
+
+	data = read_part_sector(state, 0, &sect);
+	if (!data)
+		return -EIO;
+	if (!bcon_magic_present(data))
+		goto out;
+
+	bcon_add(state->name);
+	err = 1;
+out:
+	put_dev_sector(sect);
+	return err;
+}
diff --git a/block/partitions/check.c b/block/partitions/check.c
index 19ba207..21786ed 100644
--- a/block/partitions/check.c
+++ b/block/partitions/check.c
@@ -42,6 +42,9 @@ static int (*check_part[])(struct parsed_partitions *) = {
 	 * Probe partition formats with tables at disk address 0
 	 * that also have an ADFS boot block at 0xdc0.
 	 */
+#ifdef CONFIG_BLOCKCONSOLE
+	blockconsole_partition,
+#endif
 #ifdef CONFIG_ACORN_PARTITION_ICS
 	adfspart_check_ICS,
 #endif
diff --git a/block/partitions/check.h b/block/partitions/check.h
index eade17e..bca9624 100644
--- a/block/partitions/check.h
+++ b/block/partitions/check.h
@@ -52,3 +52,6 @@ put_partition(struct parsed_partitions *p, int n, sector_t from, sector_t size)
 
 extern int warn_no_part;
 
+#ifdef CONFIG_BLOCKCONSOLE
+int blockconsole_partition(struct parsed_partitions *state);
+#endif
diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
index 9a87daa..a5ffcc9 100644
--- a/block/scsi_ioctl.c
+++ b/block/scsi_ioctl.c
@@ -27,6 +27,7 @@
 #include <linux/ratelimit.h>
 #include <linux/slab.h>
 #include <linux/times.h>
+#include <linux/uio.h>
 #include <asm/uaccess.h>
 
 #include <scsi/scsi.h>
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 05c0ce5..f28204a 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -322,19 +322,9 @@ config CRYPTO_CRC32C
 	  by iSCSI for header and data digests and by others.
 	  See Castagnoli93.  Module will be crc32c.
 
-config CRYPTO_CRC32C_X86_64
-	bool
-	depends on X86 && 64BIT
-	select CRYPTO_HASH
-	help
-	  In Intel processor with SSE4.2 supported, the processor will
-	  support CRC32C calculation using hardware accelerated CRC32
-	  instruction optimized with PCLMULQDQ instruction when available.
-
 config CRYPTO_CRC32C_INTEL
 	tristate "CRC32c INTEL hardware acceleration"
 	depends on X86
-	select CRYPTO_CRC32C_X86_64 if 64BIT
 	select CRYPTO_HASH
 	help
 	  In Intel processor with SSE4.2 supported, the processor will
@@ -480,6 +470,28 @@ config CRYPTO_SHA1_SSSE3
 	  using Supplemental SSE3 (SSSE3) instructions or Advanced Vector
 	  Extensions (AVX), when available.
 
+config CRYPTO_SHA256_SSSE3
+	tristate "SHA256 digest algorithm (SSSE3/AVX/AVX2)"
+	depends on X86 && 64BIT
+	select CRYPTO_SHA256
+	select CRYPTO_HASH
+	help
+	  SHA-256 secure hash standard (DFIPS 180-2) implemented
+	  using Supplemental SSE3 (SSSE3) instructions, or Advanced Vector
+	  Extensions version 1 (AVX1), or Advanced Vector Extensions
+	  version 2 (AVX2) instructions, when available.
+
+config CRYPTO_SHA512_SSSE3
+	tristate "SHA512 digest algorithm (SSSE3/AVX/AVX2)"
+	depends on X86 && 64BIT
+	select CRYPTO_SHA512
+	select CRYPTO_HASH
+	help
+	  SHA-512 secure hash standard (DFIPS 180-2) implemented
+	  using Supplemental SSE3 (SSSE3) instructions, or Advanced Vector
+	  Extensions version 1 (AVX1), or Advanced Vector Extensions
+	  version 2 (AVX2) instructions, when available.
+
 config CRYPTO_SHA1_SPARC64
 	tristate "SHA1 digest algorithm (SPARC64)"
 	depends on SPARC64
@@ -1246,6 +1258,22 @@ config CRYPTO_842
 	help
 	  This is the 842 algorithm.
 
+config CRYPTO_LZ4
+	tristate "LZ4 compression algorithm"
+	select CRYPTO_ALGAPI
+	select LZ4_COMPRESS
+	select LZ4_DECOMPRESS
+	help
+	  This is the LZ4 algorithm.
+
+config CRYPTO_LZ4HC
+	tristate "LZ4HC compression algorithm"
+	select CRYPTO_ALGAPI
+	select LZ4HC_COMPRESS
+	select LZ4_DECOMPRESS
+	help
+	  This is the LZ4 high compression mode algorithm.
+
 comment "Random Number Generation"
 
 config CRYPTO_ANSI_CPRNG
diff --git a/crypto/Makefile b/crypto/Makefile
index be1a1be..af87faa 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -84,6 +84,8 @@ obj-$(CONFIG_CRYPTO_CRC32C) += crc32c.o
 obj-$(CONFIG_CRYPTO_CRC32) += crc32.o
 obj-$(CONFIG_CRYPTO_AUTHENC) += authenc.o authencesn.o
 obj-$(CONFIG_CRYPTO_LZO) += lzo.o
+obj-$(CONFIG_CRYPTO_LZ4) += lz4.o
+obj-$(CONFIG_CRYPTO_LZ4HC) += lz4hc.o
 obj-$(CONFIG_CRYPTO_842) += 842.o
 obj-$(CONFIG_CRYPTO_RNG2) += rng.o
 obj-$(CONFIG_CRYPTO_RNG2) += krng.o
diff --git a/crypto/async_tx/raid6test.c b/crypto/async_tx/raid6test.c
index aa2b027..4a92bac 100644
--- a/crypto/async_tx/raid6test.c
+++ b/crypto/async_tx/raid6test.c
@@ -46,15 +46,10 @@ static void callback(void *param)
 
 static void makedata(int disks)
 {
-	int i, j;
+	int i;
 
 	for (i = 0; i < disks; i++) {
-		for (j = 0; j < PAGE_SIZE/sizeof(u32); j += sizeof(u32)) {
-			u32 *p = page_address(data[i]) + j;
-
-			*p = random32();
-		}
-
+		prandom_bytes(page_address(data[i]), PAGE_SIZE);
 		dataptrs[i] = data[i];
 	}
 }
diff --git a/crypto/crypto_user.c b/crypto/crypto_user.c
index dfd511f..1512e41 100644
--- a/crypto/crypto_user.c
+++ b/crypto/crypto_user.c
@@ -440,7 +440,7 @@ static const struct nla_policy crypto_policy[CRYPTOCFGA_MAX+1] = {
 
 #undef MSGSIZE
 
-static struct crypto_link {
+static const struct crypto_link {
 	int (*doit)(struct sk_buff *, struct nlmsghdr *, struct nlattr **);
 	int (*dump)(struct sk_buff *, struct netlink_callback *);
 	int (*done)(struct netlink_callback *);
@@ -456,7 +456,7 @@ static struct crypto_link {
 static int crypto_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 {
 	struct nlattr *attrs[CRYPTOCFGA_MAX+1];
-	struct crypto_link *link;
+	const struct crypto_link *link;
 	int type, err;
 
 	type = nlh->nlmsg_type;
diff --git a/crypto/gcm.c b/crypto/gcm.c
index 137ad1e..13ccbda 100644
--- a/crypto/gcm.c
+++ b/crypto/gcm.c
@@ -44,6 +44,7 @@ struct crypto_rfc4543_ctx {
 
 struct crypto_rfc4543_req_ctx {
 	u8 auth_tag[16];
+	u8 assocbuf[32];
 	struct scatterlist cipher[1];
 	struct scatterlist payload[2];
 	struct scatterlist assoc[2];
@@ -1133,9 +1134,19 @@ static struct aead_request *crypto_rfc4543_crypt(struct aead_request *req,
 	scatterwalk_crypto_chain(payload, dst, vdst == req->iv + 8, 2);
 	assoclen += 8 + req->cryptlen - (enc ? 0 : authsize);
 
-	sg_init_table(assoc, 2);
-	sg_set_page(assoc, sg_page(req->assoc), req->assoc->length,
-		    req->assoc->offset);
+	if (req->assoc->length == req->assoclen) {
+		sg_init_table(assoc, 2);
+		sg_set_page(assoc, sg_page(req->assoc), req->assoc->length,
+			    req->assoc->offset);
+	} else {
+		BUG_ON(req->assoclen > sizeof(rctx->assocbuf));
+
+		scatterwalk_map_and_copy(rctx->assocbuf, req->assoc, 0,
+					 req->assoclen, 0);
+
+		sg_init_table(assoc, 2);
+		sg_set_buf(assoc, rctx->assocbuf, req->assoclen);
+	}
 	scatterwalk_crypto_chain(assoc, payload, 0, 2);
 
 	aead_request_set_tfm(subreq, ctx->child);
diff --git a/crypto/lz4.c b/crypto/lz4.c
new file mode 100644
index 0000000..4586dd1
--- /dev/null
+++ b/crypto/lz4.c
@@ -0,0 +1,106 @@
+/*
+ * Cryptographic API.
+ *
+ * Copyright (c) 2013 Chanho Min <chanho.min@lge.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/crypto.h>
+#include <linux/vmalloc.h>
+#include <linux/lz4.h>
+
+struct lz4_ctx {
+	void *lz4_comp_mem;
+};
+
+static int lz4_init(struct crypto_tfm *tfm)
+{
+	struct lz4_ctx *ctx = crypto_tfm_ctx(tfm);
+
+	ctx->lz4_comp_mem = vmalloc(LZ4_MEM_COMPRESS);
+	if (!ctx->lz4_comp_mem)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static void lz4_exit(struct crypto_tfm *tfm)
+{
+	struct lz4_ctx *ctx = crypto_tfm_ctx(tfm);
+	vfree(ctx->lz4_comp_mem);
+}
+
+static int lz4_compress_crypto(struct crypto_tfm *tfm, const u8 *src,
+			    unsigned int slen, u8 *dst, unsigned int *dlen)
+{
+	struct lz4_ctx *ctx = crypto_tfm_ctx(tfm);
+	size_t tmp_len = *dlen;
+	int err;
+
+	err = lz4_compress(src, slen, dst, &tmp_len, ctx->lz4_comp_mem);
+
+	if (err < 0)
+		return -EINVAL;
+
+	*dlen = tmp_len;
+	return 0;
+}
+
+static int lz4_decompress_crypto(struct crypto_tfm *tfm, const u8 *src,
+			      unsigned int slen, u8 *dst, unsigned int *dlen)
+{
+	int err;
+	size_t tmp_len = *dlen;
+	size_t __slen = slen;
+
+	err = lz4_decompress(src, &__slen, dst, tmp_len);
+	if (err < 0)
+		return -EINVAL;
+
+	*dlen = tmp_len;
+	return err;
+}
+
+static struct crypto_alg alg_lz4 = {
+	.cra_name		= "lz4",
+	.cra_flags		= CRYPTO_ALG_TYPE_COMPRESS,
+	.cra_ctxsize		= sizeof(struct lz4_ctx),
+	.cra_module		= THIS_MODULE,
+	.cra_list		= LIST_HEAD_INIT(alg_lz4.cra_list),
+	.cra_init		= lz4_init,
+	.cra_exit		= lz4_exit,
+	.cra_u			= { .compress = {
+	.coa_compress		= lz4_compress_crypto,
+	.coa_decompress		= lz4_decompress_crypto } }
+};
+
+static int __init lz4_mod_init(void)
+{
+	return crypto_register_alg(&alg_lz4);
+}
+
+static void __exit lz4_mod_fini(void)
+{
+	crypto_unregister_alg(&alg_lz4);
+}
+
+module_init(lz4_mod_init);
+module_exit(lz4_mod_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("LZ4 Compression Algorithm");
diff --git a/crypto/lz4hc.c b/crypto/lz4hc.c
new file mode 100644
index 0000000..151ba31
--- /dev/null
+++ b/crypto/lz4hc.c
@@ -0,0 +1,106 @@
+/*
+ * Cryptographic API.
+ *
+ * Copyright (c) 2013 Chanho Min <chanho.min@lge.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/crypto.h>
+#include <linux/vmalloc.h>
+#include <linux/lz4.h>
+
+struct lz4hc_ctx {
+	void *lz4hc_comp_mem;
+};
+
+static int lz4hc_init(struct crypto_tfm *tfm)
+{
+	struct lz4hc_ctx *ctx = crypto_tfm_ctx(tfm);
+
+	ctx->lz4hc_comp_mem = vmalloc(LZ4HC_MEM_COMPRESS);
+	if (!ctx->lz4hc_comp_mem)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static void lz4hc_exit(struct crypto_tfm *tfm)
+{
+	struct lz4hc_ctx *ctx = crypto_tfm_ctx(tfm);
+
+	vfree(ctx->lz4hc_comp_mem);
+}
+
+static int lz4hc_compress_crypto(struct crypto_tfm *tfm, const u8 *src,
+			    unsigned int slen, u8 *dst, unsigned int *dlen)
+{
+	struct lz4hc_ctx *ctx = crypto_tfm_ctx(tfm);
+	size_t tmp_len = *dlen;
+	int err;
+
+	err = lz4hc_compress(src, slen, dst, &tmp_len, ctx->lz4hc_comp_mem);
+
+	if (err < 0)
+		return -EINVAL;
+
+	*dlen = tmp_len;
+	return 0;
+}
+
+static int lz4hc_decompress_crypto(struct crypto_tfm *tfm, const u8 *src,
+			      unsigned int slen, u8 *dst, unsigned int *dlen)
+{
+	int err;
+	size_t tmp_len = *dlen;
+	size_t __slen = slen;
+
+	err = lz4_decompress(src, &__slen, dst, tmp_len);
+	if (err < 0)
+		return -EINVAL;
+
+	*dlen = tmp_len;
+	return err;
+}
+
+static struct crypto_alg alg_lz4hc = {
+	.cra_name		= "lz4hc",
+	.cra_flags		= CRYPTO_ALG_TYPE_COMPRESS,
+	.cra_ctxsize		= sizeof(struct lz4hc_ctx),
+	.cra_module		= THIS_MODULE,
+	.cra_list		= LIST_HEAD_INIT(alg_lz4hc.cra_list),
+	.cra_init		= lz4hc_init,
+	.cra_exit		= lz4hc_exit,
+	.cra_u			= { .compress = {
+	.coa_compress		= lz4hc_compress_crypto,
+	.coa_decompress		= lz4hc_decompress_crypto } }
+};
+
+static int __init lz4hc_mod_init(void)
+{
+	return crypto_register_alg(&alg_lz4hc);
+}
+
+static void __exit lz4hc_mod_fini(void)
+{
+	crypto_unregister_alg(&alg_lz4hc);
+}
+
+module_init(lz4hc_mod_init);
+module_exit(lz4hc_mod_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("LZ4HC Compression Algorithm");
diff --git a/crypto/sha256_generic.c b/crypto/sha256_generic.c
index c3ed4ec..5433667 100644
--- a/crypto/sha256_generic.c
+++ b/crypto/sha256_generic.c
@@ -246,7 +246,7 @@ static int sha256_init(struct shash_desc *desc)
 	return 0;
 }
 
-static int sha256_update(struct shash_desc *desc, const u8 *data,
+int crypto_sha256_update(struct shash_desc *desc, const u8 *data,
 			  unsigned int len)
 {
 	struct sha256_state *sctx = shash_desc_ctx(desc);
@@ -277,6 +277,7 @@ static int sha256_update(struct shash_desc *desc, const u8 *data,
 
 	return 0;
 }
+EXPORT_SYMBOL(crypto_sha256_update);
 
 static int sha256_final(struct shash_desc *desc, u8 *out)
 {
@@ -293,10 +294,10 @@ static int sha256_final(struct shash_desc *desc, u8 *out)
 	/* Pad out to 56 mod 64. */
 	index = sctx->count & 0x3f;
 	pad_len = (index < 56) ? (56 - index) : ((64+56) - index);
-	sha256_update(desc, padding, pad_len);
+	crypto_sha256_update(desc, padding, pad_len);
 
 	/* Append length (before padding) */
-	sha256_update(desc, (const u8 *)&bits, sizeof(bits));
+	crypto_sha256_update(desc, (const u8 *)&bits, sizeof(bits));
 
 	/* Store state in digest */
 	for (i = 0; i < 8; i++)
@@ -339,7 +340,7 @@ static int sha256_import(struct shash_desc *desc, const void *in)
 static struct shash_alg sha256_algs[2] = { {
 	.digestsize	=	SHA256_DIGEST_SIZE,
 	.init		=	sha256_init,
-	.update		=	sha256_update,
+	.update		=	crypto_sha256_update,
 	.final		=	sha256_final,
 	.export		=	sha256_export,
 	.import		=	sha256_import,
@@ -355,7 +356,7 @@ static struct shash_alg sha256_algs[2] = { {
 }, {
 	.digestsize	=	SHA224_DIGEST_SIZE,
 	.init		=	sha224_init,
-	.update		=	sha256_update,
+	.update		=	crypto_sha256_update,
 	.final		=	sha224_final,
 	.descsize	=	sizeof(struct sha256_state),
 	.base		=	{
diff --git a/crypto/sha512_generic.c b/crypto/sha512_generic.c
index 71fcf36..4c58620 100644
--- a/crypto/sha512_generic.c
+++ b/crypto/sha512_generic.c
@@ -163,8 +163,8 @@ sha384_init(struct shash_desc *desc)
 	return 0;
 }
 
-static int
-sha512_update(struct shash_desc *desc, const u8 *data, unsigned int len)
+int crypto_sha512_update(struct shash_desc *desc, const u8 *data,
+			unsigned int len)
 {
 	struct sha512_state *sctx = shash_desc_ctx(desc);
 
@@ -197,6 +197,7 @@ sha512_update(struct shash_desc *desc, const u8 *data, unsigned int len)
 
 	return 0;
 }
+EXPORT_SYMBOL(crypto_sha512_update);
 
 static int
 sha512_final(struct shash_desc *desc, u8 *hash)
@@ -215,10 +216,10 @@ sha512_final(struct shash_desc *desc, u8 *hash)
 	/* Pad out to 112 mod 128. */
 	index = sctx->count[0] & 0x7f;
 	pad_len = (index < 112) ? (112 - index) : ((128+112) - index);
-	sha512_update(desc, padding, pad_len);
+	crypto_sha512_update(desc, padding, pad_len);
 
 	/* Append length (before padding) */
-	sha512_update(desc, (const u8 *)bits, sizeof(bits));
+	crypto_sha512_update(desc, (const u8 *)bits, sizeof(bits));
 
 	/* Store state in digest */
 	for (i = 0; i < 8; i++)
@@ -245,7 +246,7 @@ static int sha384_final(struct shash_desc *desc, u8 *hash)
 static struct shash_alg sha512_algs[2] = { {
 	.digestsize	=	SHA512_DIGEST_SIZE,
 	.init		=	sha512_init,
-	.update		=	sha512_update,
+	.update		=	crypto_sha512_update,
 	.final		=	sha512_final,
 	.descsize	=	sizeof(struct sha512_state),
 	.base		=	{
@@ -257,7 +258,7 @@ static struct shash_alg sha512_algs[2] = { {
 }, {
 	.digestsize	=	SHA384_DIGEST_SIZE,
 	.init		=	sha384_init,
-	.update		=	sha512_update,
+	.update		=	crypto_sha512_update,
 	.final		=	sha384_final,
 	.descsize	=	sizeof(struct sha512_state),
 	.base		=	{
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 202fa6d..9953a42 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -52,6 +52,8 @@ source "drivers/i2c/Kconfig"
 
 source "drivers/spi/Kconfig"
 
+source "drivers/ssbi/Kconfig"
+
 source "drivers/hsi/Kconfig"
 
 source "drivers/pps/Kconfig"
@@ -118,6 +120,8 @@ source "drivers/vfio/Kconfig"
 
 source "drivers/vlynq/Kconfig"
 
+source "drivers/virt/Kconfig"
+
 source "drivers/virtio/Kconfig"
 
 source "drivers/hv/Kconfig"
@@ -142,8 +146,6 @@ source "drivers/remoteproc/Kconfig"
 
 source "drivers/rpmsg/Kconfig"
 
-source "drivers/virt/Kconfig"
-
 source "drivers/devfreq/Kconfig"
 
 source "drivers/extcon/Kconfig"
@@ -162,4 +164,6 @@ source "drivers/irqchip/Kconfig"
 
 source "drivers/ipack/Kconfig"
 
+source "drivers/reset/Kconfig"
+
 endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index dce39a9..130abc1 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -37,6 +37,9 @@ obj-$(CONFIG_XEN)		+= xen/
 # regulators early, since some subsystems rely on them to initialize
 obj-$(CONFIG_REGULATOR)		+= regulator/
 
+# reset controllers early, since gpu drivers might rely on them to initialize
+obj-$(CONFIG_RESET_CONTROLLER)	+= reset/
+
 # tty/ comes before char/ so that the VT console is the boot-time
 # default.
 obj-y				+= tty/
@@ -79,7 +82,7 @@ obj-$(CONFIG_ATA_OVER_ETH)	+= block/aoe/
 obj-$(CONFIG_PARIDE) 		+= block/paride/
 obj-$(CONFIG_TC)		+= tc/
 obj-$(CONFIG_UWB)		+= uwb/
-obj-$(CONFIG_USB_OTG_UTILS)	+= usb/
+obj-$(CONFIG_USB_PHY)		+= usb/
 obj-$(CONFIG_USB)		+= usb/
 obj-$(CONFIG_PCI)		+= usb/
 obj-$(CONFIG_USB_GADGET)	+= usb/
@@ -114,6 +117,7 @@ obj-y				+= firmware/
 obj-$(CONFIG_CRYPTO)		+= crypto/
 obj-$(CONFIG_SUPERH)		+= sh/
 obj-$(CONFIG_ARCH_SHMOBILE)	+= sh/
+obj-$(CONFIG_SSBI)		+= ssbi/
 ifndef CONFIG_ARCH_USES_GETTIMEOFFSET
 obj-y				+= clocksource/
 endif
@@ -123,7 +127,7 @@ obj-$(CONFIG_PPC_PS3)		+= ps3/
 obj-$(CONFIG_OF)		+= of/
 obj-$(CONFIG_SSB)		+= ssb/
 obj-$(CONFIG_BCMA)		+= bcma/
-obj-$(CONFIG_VHOST_NET)		+= vhost/
+obj-$(CONFIG_VHOST_RING)	+= vhost/
 obj-$(CONFIG_VLYNQ)		+= vlynq/
 obj-$(CONFIG_STAGING)		+= staging/
 obj-y				+= platform/
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 92ed969..8fcae6d 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -334,7 +334,7 @@ config X86_PM_TIMER
 
 config ACPI_CONTAINER
 	bool "Container and Module Devices"
-	default (ACPI_HOTPLUG_MEMORY || ACPI_HOTPLUG_CPU || ACPI_HOTPLUG_IO)
+	default (ACPI_HOTPLUG_MEMORY || ACPI_HOTPLUG_CPU)
 	help
 	  This driver supports ACPI Container and Module devices (IDs
 	  ACPI0004, PNP0A05, and PNP0A06).
@@ -345,9 +345,8 @@ config ACPI_CONTAINER
 	  the module will be called container.
 
 config ACPI_HOTPLUG_MEMORY
-	tristate "Memory Hotplug"
+	bool "Memory Hotplug"
 	depends on MEMORY_HOTPLUG
-	default n
 	help
 	  This driver supports ACPI memory hotplug.  The driver
 	  fields notifications on ACPI memory devices (PNP0C80),
@@ -396,7 +395,7 @@ config ACPI_CUSTOM_METHOD
 
 config ACPI_BGRT
 	bool "Boottime Graphics Resource Table support"
-	depends on EFI
+	depends on EFI && X86
         help
 	  This driver adds support for exposing the ACPI Boottime Graphics
 	  Resource Table, which allows the operating system to obtain
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 474fcfe..ecb743b 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -39,6 +39,7 @@ acpi-y				+= ec.o
 acpi-$(CONFIG_ACPI_DOCK)	+= dock.o
 acpi-y				+= pci_root.o pci_link.o pci_irq.o
 acpi-y				+= csrt.o
+acpi-$(CONFIG_X86_INTEL_LPSS)	+= acpi_lpss.o
 acpi-y				+= acpi_platform.o
 acpi-y				+= power.o
 acpi-y				+= event.o
diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c
index 6d5bf64..00d2efd 100644
--- a/drivers/acpi/ac.c
+++ b/drivers/acpi/ac.c
@@ -194,7 +194,7 @@ static int acpi_ac_seq_show(struct seq_file *seq, void *offset)
 
 static int acpi_ac_open_fs(struct inode *inode, struct file *file)
 {
-	return single_open(file, acpi_ac_seq_show, PDE(inode)->data);
+	return single_open(file, acpi_ac_seq_show, PDE_DATA(inode));
 }
 
 static int acpi_ac_add_fs(struct acpi_device *device)
diff --git a/drivers/acpi/acpi_i2c.c b/drivers/acpi/acpi_i2c.c
index 82045e3..a82c762 100644
--- a/drivers/acpi/acpi_i2c.c
+++ b/drivers/acpi/acpi_i2c.c
@@ -90,7 +90,7 @@ void acpi_i2c_register_devices(struct i2c_adapter *adapter)
 	acpi_handle handle;
 	acpi_status status;
 
-	handle = ACPI_HANDLE(&adapter->dev);
+	handle = ACPI_HANDLE(adapter->dev.parent);
 	if (!handle)
 		return;
 
diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c
new file mode 100644
index 0000000..b1c9542
--- /dev/null
+++ b/drivers/acpi/acpi_lpss.c
@@ -0,0 +1,292 @@
+/*
+ * ACPI support for Intel Lynxpoint LPSS.
+ *
+ * Copyright (C) 2013, Intel Corporation
+ * Authors: Mika Westerberg <mika.westerberg@linux.intel.com>
+ *          Rafael J. Wysocki <rafael.j.wysocki@intel.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/acpi.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/platform_data/clk-lpss.h>
+#include <linux/pm_runtime.h>
+
+#include "internal.h"
+
+ACPI_MODULE_NAME("acpi_lpss");
+
+#define LPSS_CLK_SIZE	0x04
+#define LPSS_LTR_SIZE	0x18
+
+/* Offsets relative to LPSS_PRIVATE_OFFSET */
+#define LPSS_GENERAL			0x08
+#define LPSS_GENERAL_LTR_MODE_SW	BIT(2)
+#define LPSS_SW_LTR			0x10
+#define LPSS_AUTO_LTR			0x14
+
+struct lpss_device_desc {
+	bool clk_required;
+	const char *clk_parent;
+	bool ltr_required;
+	unsigned int prv_offset;
+};
+
+struct lpss_private_data {
+	void __iomem *mmio_base;
+	resource_size_t mmio_size;
+	struct clk *clk;
+	const struct lpss_device_desc *dev_desc;
+};
+
+static struct lpss_device_desc lpt_dev_desc = {
+	.clk_required = true,
+	.clk_parent = "lpss_clk",
+	.prv_offset = 0x800,
+	.ltr_required = true,
+};
+
+static struct lpss_device_desc lpt_sdio_dev_desc = {
+	.prv_offset = 0x1000,
+	.ltr_required = true,
+};
+
+static const struct acpi_device_id acpi_lpss_device_ids[] = {
+	/* Lynxpoint LPSS devices */
+	{ "INT33C0", (unsigned long)&lpt_dev_desc },
+	{ "INT33C1", (unsigned long)&lpt_dev_desc },
+	{ "INT33C2", (unsigned long)&lpt_dev_desc },
+	{ "INT33C3", (unsigned long)&lpt_dev_desc },
+	{ "INT33C4", (unsigned long)&lpt_dev_desc },
+	{ "INT33C5", (unsigned long)&lpt_dev_desc },
+	{ "INT33C6", (unsigned long)&lpt_sdio_dev_desc },
+	{ "INT33C7", },
+
+	{ }
+};
+
+static int is_memory(struct acpi_resource *res, void *not_used)
+{
+	struct resource r;
+	return !acpi_dev_resource_memory(res, &r);
+}
+
+/* LPSS main clock device. */
+static struct platform_device *lpss_clk_dev;
+
+static inline void lpt_register_clock_device(void)
+{
+	lpss_clk_dev = platform_device_register_simple("clk-lpt", -1, NULL, 0);
+}
+
+static int register_device_clock(struct acpi_device *adev,
+				 struct lpss_private_data *pdata)
+{
+	const struct lpss_device_desc *dev_desc = pdata->dev_desc;
+
+	if (!lpss_clk_dev)
+		lpt_register_clock_device();
+
+	if (!dev_desc->clk_parent || !pdata->mmio_base
+	    || pdata->mmio_size < dev_desc->prv_offset + LPSS_CLK_SIZE)
+		return -ENODATA;
+
+	pdata->clk = clk_register_gate(NULL, dev_name(&adev->dev),
+				       dev_desc->clk_parent, 0,
+				       pdata->mmio_base + dev_desc->prv_offset,
+				       0, 0, NULL);
+	if (IS_ERR(pdata->clk))
+		return PTR_ERR(pdata->clk);
+
+	clk_register_clkdev(pdata->clk, NULL, dev_name(&adev->dev));
+	return 0;
+}
+
+static int acpi_lpss_create_device(struct acpi_device *adev,
+				   const struct acpi_device_id *id)
+{
+	struct lpss_device_desc *dev_desc;
+	struct lpss_private_data *pdata;
+	struct resource_list_entry *rentry;
+	struct list_head resource_list;
+	int ret;
+
+	dev_desc = (struct lpss_device_desc *)id->driver_data;
+	if (!dev_desc)
+		return acpi_create_platform_device(adev, id);
+
+	pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+	if (!pdata)
+		return -ENOMEM;
+
+	INIT_LIST_HEAD(&resource_list);
+	ret = acpi_dev_get_resources(adev, &resource_list, is_memory, NULL);
+	if (ret < 0)
+		goto err_out;
+
+	list_for_each_entry(rentry, &resource_list, node)
+		if (resource_type(&rentry->res) == IORESOURCE_MEM) {
+			pdata->mmio_size = resource_size(&rentry->res);
+			pdata->mmio_base = ioremap(rentry->res.start,
+						   pdata->mmio_size);
+			pdata->dev_desc = dev_desc;
+			break;
+		}
+
+	acpi_dev_free_resource_list(&resource_list);
+
+	if (dev_desc->clk_required) {
+		ret = register_device_clock(adev, pdata);
+		if (ret) {
+			/*
+			 * Skip the device, but don't terminate the namespace
+			 * scan.
+			 */
+			kfree(pdata);
+			return 0;
+		}
+	}
+
+	adev->driver_data = pdata;
+	ret = acpi_create_platform_device(adev, id);
+	if (ret > 0)
+		return ret;
+
+	adev->driver_data = NULL;
+
+ err_out:
+	kfree(pdata);
+	return ret;
+}
+
+static int lpss_reg_read(struct device *dev, unsigned int reg, u32 *val)
+{
+	struct acpi_device *adev;
+	struct lpss_private_data *pdata;
+	unsigned long flags;
+	int ret;
+
+	ret = acpi_bus_get_device(ACPI_HANDLE(dev), &adev);
+	if (WARN_ON(ret))
+		return ret;
+
+	spin_lock_irqsave(&dev->power.lock, flags);
+	if (pm_runtime_suspended(dev)) {
+		ret = -EAGAIN;
+		goto out;
+	}
+	pdata = acpi_driver_data(adev);
+	if (WARN_ON(!pdata || !pdata->mmio_base)) {
+		ret = -ENODEV;
+		goto out;
+	}
+	*val = readl(pdata->mmio_base + pdata->dev_desc->prv_offset + reg);
+
+ out:
+	spin_unlock_irqrestore(&dev->power.lock, flags);
+	return ret;
+}
+
+static ssize_t lpss_ltr_show(struct device *dev, struct device_attribute *attr,
+			     char *buf)
+{
+	u32 ltr_value = 0;
+	unsigned int reg;
+	int ret;
+
+	reg = strcmp(attr->attr.name, "auto_ltr") ? LPSS_SW_LTR : LPSS_AUTO_LTR;
+	ret = lpss_reg_read(dev, reg, &ltr_value);
+	if (ret)
+		return ret;
+
+	return snprintf(buf, PAGE_SIZE, "%08x\n", ltr_value);
+}
+
+static ssize_t lpss_ltr_mode_show(struct device *dev,
+				  struct device_attribute *attr, char *buf)
+{
+	u32 ltr_mode = 0;
+	char *outstr;
+	int ret;
+
+	ret = lpss_reg_read(dev, LPSS_GENERAL, &ltr_mode);
+	if (ret)
+		return ret;
+
+	outstr = (ltr_mode & LPSS_GENERAL_LTR_MODE_SW) ? "sw" : "auto";
+	return sprintf(buf, "%s\n", outstr);
+}
+
+static DEVICE_ATTR(auto_ltr, S_IRUSR, lpss_ltr_show, NULL);
+static DEVICE_ATTR(sw_ltr, S_IRUSR, lpss_ltr_show, NULL);
+static DEVICE_ATTR(ltr_mode, S_IRUSR, lpss_ltr_mode_show, NULL);
+
+static struct attribute *lpss_attrs[] = {
+	&dev_attr_auto_ltr.attr,
+	&dev_attr_sw_ltr.attr,
+	&dev_attr_ltr_mode.attr,
+	NULL,
+};
+
+static struct attribute_group lpss_attr_group = {
+	.attrs = lpss_attrs,
+	.name = "lpss_ltr",
+};
+
+static int acpi_lpss_platform_notify(struct notifier_block *nb,
+				     unsigned long action, void *data)
+{
+	struct platform_device *pdev = to_platform_device(data);
+	struct lpss_private_data *pdata;
+	struct acpi_device *adev;
+	const struct acpi_device_id *id;
+	int ret = 0;
+
+	id = acpi_match_device(acpi_lpss_device_ids, &pdev->dev);
+	if (!id || !id->driver_data)
+		return 0;
+
+	if (acpi_bus_get_device(ACPI_HANDLE(&pdev->dev), &adev))
+		return 0;
+
+	pdata = acpi_driver_data(adev);
+	if (!pdata || !pdata->mmio_base || !pdata->dev_desc->ltr_required)
+		return 0;
+
+	if (pdata->mmio_size < pdata->dev_desc->prv_offset + LPSS_LTR_SIZE) {
+		dev_err(&pdev->dev, "MMIO size insufficient to access LTR\n");
+		return 0;
+	}
+
+	if (action == BUS_NOTIFY_ADD_DEVICE)
+		ret = sysfs_create_group(&pdev->dev.kobj, &lpss_attr_group);
+	else if (action == BUS_NOTIFY_DEL_DEVICE)
+		sysfs_remove_group(&pdev->dev.kobj, &lpss_attr_group);
+
+	return ret;
+}
+
+static struct notifier_block acpi_lpss_nb = {
+	.notifier_call = acpi_lpss_platform_notify,
+};
+
+static struct acpi_scan_handler lpss_handler = {
+	.ids = acpi_lpss_device_ids,
+	.attach = acpi_lpss_create_device,
+};
+
+void __init acpi_lpss_init(void)
+{
+	if (!lpt_clk_init()) {
+		bus_register_notifier(&platform_bus_type, &acpi_lpss_nb);
+		acpi_scan_add_handler(&lpss_handler);
+	}
+}
diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c
index da1f82b4..5e6301e 100644
--- a/drivers/acpi/acpi_memhotplug.c
+++ b/drivers/acpi/acpi_memhotplug.c
@@ -1,5 +1,7 @@
 /*
- * Copyright (C) 2004 Intel Corporation <naveen.b.s@intel.com>
+ * Copyright (C) 2004, 2013 Intel Corporation
+ * Author: Naveen B S <naveen.b.s@intel.com>
+ * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
  *
  * All rights reserved.
  *
@@ -25,14 +27,10 @@
  * ranges.
  */
 
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/memory_hotplug.h>
-#include <linux/slab.h>
 #include <linux/acpi.h>
-#include <acpi/acpi_drivers.h>
+#include <linux/memory_hotplug.h>
+
+#include "internal.h"
 
 #define ACPI_MEMORY_DEVICE_CLASS		"memory"
 #define ACPI_MEMORY_DEVICE_HID			"PNP0C80"
@@ -44,32 +42,28 @@
 #define 	PREFIX		"ACPI:memory_hp:"
 
 ACPI_MODULE_NAME("acpi_memhotplug");
-MODULE_AUTHOR("Naveen B S <naveen.b.s@intel.com>");
-MODULE_DESCRIPTION("Hotplug Mem Driver");
-MODULE_LICENSE("GPL");
 
 /* Memory Device States */
 #define MEMORY_INVALID_STATE	0
 #define MEMORY_POWER_ON_STATE	1
 #define MEMORY_POWER_OFF_STATE	2
 
-static int acpi_memory_device_add(struct acpi_device *device);
-static int acpi_memory_device_remove(struct acpi_device *device);
+static int acpi_memory_device_add(struct acpi_device *device,
+				  const struct acpi_device_id *not_used);
+static void acpi_memory_device_remove(struct acpi_device *device);
 
 static const struct acpi_device_id memory_device_ids[] = {
 	{ACPI_MEMORY_DEVICE_HID, 0},
 	{"", 0},
 };
-MODULE_DEVICE_TABLE(acpi, memory_device_ids);
 
-static struct acpi_driver acpi_memory_device_driver = {
-	.name = "acpi_memhotplug",
-	.class = ACPI_MEMORY_DEVICE_CLASS,
+static struct acpi_scan_handler memory_device_handler = {
 	.ids = memory_device_ids,
-	.ops = {
-		.add = acpi_memory_device_add,
-		.remove = acpi_memory_device_remove,
-		},
+	.attach = acpi_memory_device_add,
+	.detach = acpi_memory_device_remove,
+	.hotplug = {
+		.enabled = true,
+	},
 };
 
 struct acpi_memory_info {
@@ -79,7 +73,6 @@ struct acpi_memory_info {
 	unsigned short caching;	/* memory cache attribute */
 	unsigned short write_protect;	/* memory read/write attribute */
 	unsigned int enabled:1;
-	unsigned int failed:1;
 };
 
 struct acpi_memory_device {
@@ -153,48 +146,6 @@ acpi_memory_get_device_resources(struct acpi_memory_device *mem_device)
 	return 0;
 }
 
-static int acpi_memory_get_device(acpi_handle handle,
-				  struct acpi_memory_device **mem_device)
-{
-	struct acpi_device *device = NULL;
-	int result = 0;
-
-	acpi_scan_lock_acquire();
-
-	acpi_bus_get_device(handle, &device);
-	if (device)
-		goto end;
-
-	/*
-	 * Now add the notified device.  This creates the acpi_device
-	 * and invokes .add function
-	 */
-	result = acpi_bus_scan(handle);
-	if (result) {
-		acpi_handle_warn(handle, "ACPI namespace scan failed\n");
-		result = -EINVAL;
-		goto out;
-	}
-	result = acpi_bus_get_device(handle, &device);
-	if (result) {
-		acpi_handle_warn(handle, "Missing device object\n");
-		result = -EINVAL;
-		goto out;
-	}
-
- end:
-	*mem_device = acpi_driver_data(device);
-	if (!(*mem_device)) {
-		dev_err(&device->dev, "driver data not found\n");
-		result = -ENODEV;
-		goto out;
-	}
-
- out:
-	acpi_scan_lock_release();
-	return result;
-}
-
 static int acpi_memory_check_device(struct acpi_memory_device *mem_device)
 {
 	unsigned long long current_status;
@@ -249,13 +200,11 @@ static int acpi_memory_enable_device(struct acpi_memory_device *mem_device)
 		 * returns -EEXIST. If add_memory() returns the other error, it
 		 * means that this memory block is not used by the kernel.
 		 */
-		if (result && result != -EEXIST) {
-			info->failed = 1;
+		if (result && result != -EEXIST)
 			continue;
-		}
 
-		if (!result)
-			info->enabled = 1;
+		info->enabled = 1;
+
 		/*
 		 * Add num_enable even if add_memory() returns -EEXIST, so the
 		 * device is bound to this driver.
@@ -286,16 +235,8 @@ static int acpi_memory_remove_memory(struct acpi_memory_device *mem_device)
 	nid = acpi_get_node(mem_device->device->handle);
 
 	list_for_each_entry_safe(info, n, &mem_device->res_list, list) {
-		if (info->failed)
-			/* The kernel does not use this memory block */
-			continue;
-
 		if (!info->enabled)
-			/*
-			 * The kernel uses this memory block, but it may be not
-			 * managed by us.
-			 */
-			return -EBUSY;
+			continue;
 
 		if (nid < 0)
 			nid = memory_add_physaddr_to_nid(info->start_addr);
@@ -310,95 +251,21 @@ static int acpi_memory_remove_memory(struct acpi_memory_device *mem_device)
 	return result;
 }
 
-static void acpi_memory_device_notify(acpi_handle handle, u32 event, void *data)
-{
-	struct acpi_memory_device *mem_device;
-	struct acpi_device *device;
-	struct acpi_eject_event *ej_event = NULL;
-	u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */
-	acpi_status status;
-
-	switch (event) {
-	case ACPI_NOTIFY_BUS_CHECK:
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-				  "\nReceived BUS CHECK notification for device\n"));
-		/* Fall Through */
-	case ACPI_NOTIFY_DEVICE_CHECK:
-		if (event == ACPI_NOTIFY_DEVICE_CHECK)
-			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-					  "\nReceived DEVICE CHECK notification for device\n"));
-		if (acpi_memory_get_device(handle, &mem_device)) {
-			acpi_handle_err(handle, "Cannot find driver data\n");
-			break;
-		}
-
-		ost_code = ACPI_OST_SC_SUCCESS;
-		break;
-
-	case ACPI_NOTIFY_EJECT_REQUEST:
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-				  "\nReceived EJECT REQUEST notification for device\n"));
-
-		status = AE_ERROR;
-		acpi_scan_lock_acquire();
-
-		if (acpi_bus_get_device(handle, &device)) {
-			acpi_handle_err(handle, "Device doesn't exist\n");
-			goto unlock;
-		}
-		mem_device = acpi_driver_data(device);
-		if (!mem_device) {
-			acpi_handle_err(handle, "Driver Data is NULL\n");
-			goto unlock;
-		}
-
-		ej_event = kmalloc(sizeof(*ej_event), GFP_KERNEL);
-		if (!ej_event) {
-			pr_err(PREFIX "No memory, dropping EJECT\n");
-			goto unlock;
-		}
-
-		get_device(&device->dev);
-		ej_event->device = device;
-		ej_event->event = ACPI_NOTIFY_EJECT_REQUEST;
-		/* The eject is carried out asynchronously. */
-		status = acpi_os_hotplug_execute(acpi_bus_hot_remove_device,
-						 ej_event);
-		if (ACPI_FAILURE(status)) {
-			put_device(&device->dev);
-			kfree(ej_event);
-		}
-
- unlock:
-		acpi_scan_lock_release();
-		if (ACPI_SUCCESS(status))
-			return;
-	default:
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-				  "Unsupported event [0x%x]\n", event));
-
-		/* non-hotplug event; possibly handled by other handler */
-		return;
-	}
-
-	/* Inform firmware that the hotplug operation has completed */
-	(void) acpi_evaluate_hotplug_ost(handle, event, ost_code, NULL);
-}
-
 static void acpi_memory_device_free(struct acpi_memory_device *mem_device)
 {
 	if (!mem_device)
 		return;
 
 	acpi_memory_free_device_resources(mem_device);
+	mem_device->device->driver_data = NULL;
 	kfree(mem_device);
 }
 
-static int acpi_memory_device_add(struct acpi_device *device)
+static int acpi_memory_device_add(struct acpi_device *device,
+				  const struct acpi_device_id *not_used)
 {
+	struct acpi_memory_device *mem_device;
 	int result;
-	struct acpi_memory_device *mem_device = NULL;
-
 
 	if (!device)
 		return -EINVAL;
@@ -423,147 +290,36 @@ static int acpi_memory_device_add(struct acpi_device *device)
 	/* Set the device state */
 	mem_device->state = MEMORY_POWER_ON_STATE;
 
-	pr_debug("%s\n", acpi_device_name(device));
+	result = acpi_memory_check_device(mem_device);
+	if (result) {
+		acpi_memory_device_free(mem_device);
+		return 0;
+	}
 
-	if (!acpi_memory_check_device(mem_device)) {
-		/* call add_memory func */
-		result = acpi_memory_enable_device(mem_device);
-		if (result) {
-			dev_err(&device->dev,
-				"Error in acpi_memory_enable_device\n");
-			acpi_memory_device_free(mem_device);
-		}
+	result = acpi_memory_enable_device(mem_device);
+	if (result) {
+		dev_err(&device->dev, "acpi_memory_enable_device() error\n");
+		acpi_memory_device_free(mem_device);
+		return -ENODEV;
 	}
-	return result;
+
+	dev_dbg(&device->dev, "Memory device configured by ACPI\n");
+	return 1;
 }
 
-static int acpi_memory_device_remove(struct acpi_device *device)
+static void acpi_memory_device_remove(struct acpi_device *device)
 {
-	struct acpi_memory_device *mem_device = NULL;
-	int result;
+	struct acpi_memory_device *mem_device;
 
 	if (!device || !acpi_driver_data(device))
-		return -EINVAL;
+		return;
 
 	mem_device = acpi_driver_data(device);
-
-	result = acpi_memory_remove_memory(mem_device);
-	if (result)
-		return result;
-
+	acpi_memory_remove_memory(mem_device);
 	acpi_memory_device_free(mem_device);
-
-	return 0;
-}
-
-/*
- * Helper function to check for memory device
- */
-static acpi_status is_memory_device(acpi_handle handle)
-{
-	char *hardware_id;
-	acpi_status status;
-	struct acpi_device_info *info;
-
-	status = acpi_get_object_info(handle, &info);
-	if (ACPI_FAILURE(status))
-		return status;
-
-	if (!(info->valid & ACPI_VALID_HID)) {
-		kfree(info);
-		return AE_ERROR;
-	}
-
-	hardware_id = info->hardware_id.string;
-	if ((hardware_id == NULL) ||
-	    (strcmp(hardware_id, ACPI_MEMORY_DEVICE_HID)))
-		status = AE_ERROR;
-
-	kfree(info);
-	return status;
-}
-
-static acpi_status
-acpi_memory_register_notify_handler(acpi_handle handle,
-				    u32 level, void *ctxt, void **retv)
-{
-	acpi_status status;
-
-
-	status = is_memory_device(handle);
-	if (ACPI_FAILURE(status))
-		return AE_OK;	/* continue */
-
-	status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
-					     acpi_memory_device_notify, NULL);
-	/* continue */
-	return AE_OK;
-}
-
-static acpi_status
-acpi_memory_deregister_notify_handler(acpi_handle handle,
-				      u32 level, void *ctxt, void **retv)
-{
-	acpi_status status;
-
-
-	status = is_memory_device(handle);
-	if (ACPI_FAILURE(status))
-		return AE_OK;	/* continue */
-
-	status = acpi_remove_notify_handler(handle,
-					    ACPI_SYSTEM_NOTIFY,
-					    acpi_memory_device_notify);
-
-	return AE_OK;	/* continue */
-}
-
-static int __init acpi_memory_device_init(void)
-{
-	int result;
-	acpi_status status;
-
-
-	result = acpi_bus_register_driver(&acpi_memory_device_driver);
-
-	if (result < 0)
-		return -ENODEV;
-
-	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
-				     ACPI_UINT32_MAX,
-				     acpi_memory_register_notify_handler, NULL,
-				     NULL, NULL);
-
-	if (ACPI_FAILURE(status)) {
-		ACPI_EXCEPTION((AE_INFO, status, "walk_namespace failed"));
-		acpi_bus_unregister_driver(&acpi_memory_device_driver);
-		return -ENODEV;
-	}
-
-	return 0;
 }
 
-static void __exit acpi_memory_device_exit(void)
+void __init acpi_memory_hotplug_init(void)
 {
-	acpi_status status;
-
-
-	/*
-	 * Adding this to un-install notification handlers for all the device
-	 * handles.
-	 */
-	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
-				     ACPI_UINT32_MAX,
-				     acpi_memory_deregister_notify_handler, NULL,
-				     NULL, NULL);
-
-	if (ACPI_FAILURE(status))
-		ACPI_EXCEPTION((AE_INFO, status, "walk_namespace failed"));
-
-	acpi_bus_unregister_driver(&acpi_memory_device_driver);
-
-	return;
+	acpi_scan_add_handler_with_hotplug(&memory_device_handler, "memory");
 }
-
-module_init(acpi_memory_device_init);
-module_exit(acpi_memory_device_exit);
diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c
index 31de104..27bb6a9 100644
--- a/drivers/acpi/acpi_pad.c
+++ b/drivers/acpi/acpi_pad.c
@@ -236,7 +236,7 @@ static int create_power_saving_task(void)
 	ps_tsks[ps_tsk_num] = kthread_run(power_saving_thread,
 		(void *)(unsigned long)ps_tsk_num,
 		"acpi_pad/%d", ps_tsk_num);
-	rc = IS_ERR(ps_tsks[ps_tsk_num]) ? PTR_ERR(ps_tsks[ps_tsk_num]) : 0;
+	rc = PTR_RET(ps_tsks[ps_tsk_num]);
 	if (!rc)
 		ps_tsk_num++;
 	else
diff --git a/drivers/acpi/acpi_platform.c b/drivers/acpi/acpi_platform.c
index 26fce4b..fafec5d 100644
--- a/drivers/acpi/acpi_platform.c
+++ b/drivers/acpi/acpi_platform.c
@@ -22,9 +22,6 @@
 
 ACPI_MODULE_NAME("platform");
 
-/* Flags for acpi_create_platform_device */
-#define ACPI_PLATFORM_CLK	BIT(0)
-
 /*
  * The following ACPI IDs are known to be suitable for representing as
  * platform devices.
@@ -33,33 +30,9 @@ static const struct acpi_device_id acpi_platform_device_ids[] = {
 
 	{ "PNP0D40" },
 
-	/* Haswell LPSS devices */
-	{ "INT33C0", ACPI_PLATFORM_CLK },
-	{ "INT33C1", ACPI_PLATFORM_CLK },
-	{ "INT33C2", ACPI_PLATFORM_CLK },
-	{ "INT33C3", ACPI_PLATFORM_CLK },
-	{ "INT33C4", ACPI_PLATFORM_CLK },
-	{ "INT33C5", ACPI_PLATFORM_CLK },
-	{ "INT33C6", ACPI_PLATFORM_CLK },
-	{ "INT33C7", ACPI_PLATFORM_CLK },
-
 	{ }
 };
 
-static int acpi_create_platform_clks(struct acpi_device *adev)
-{
-	static struct platform_device *pdev;
-
-	/* Create Lynxpoint LPSS clocks */
-	if (!pdev && !strncmp(acpi_device_hid(adev), "INT33C", 6)) {
-		pdev = platform_device_register_simple("clk-lpt", -1, NULL, 0);
-		if (IS_ERR(pdev))
-			return PTR_ERR(pdev);
-	}
-
-	return 0;
-}
-
 /**
  * acpi_create_platform_device - Create platform device for ACPI device node
  * @adev: ACPI device node to create a platform device for.
@@ -71,10 +44,9 @@ static int acpi_create_platform_clks(struct acpi_device *adev)
  *
  * Name of the platform device will be the same as @adev's.
  */
-static int acpi_create_platform_device(struct acpi_device *adev,
-				       const struct acpi_device_id *id)
+int acpi_create_platform_device(struct acpi_device *adev,
+				const struct acpi_device_id *id)
 {
-	unsigned long flags = id->driver_data;
 	struct platform_device *pdev = NULL;
 	struct acpi_device *acpi_parent;
 	struct platform_device_info pdevinfo;
@@ -83,14 +55,6 @@ static int acpi_create_platform_device(struct acpi_device *adev,
 	struct resource *resources;
 	int count;
 
-	if (flags & ACPI_PLATFORM_CLK) {
-		int ret = acpi_create_platform_clks(adev);
-		if (ret) {
-			dev_err(&adev->dev, "failed to create clocks\n");
-			return ret;
-		}
-	}
-
 	/* If the ACPI node already has a physical device attached, skip it. */
 	if (adev->physical_node_count)
 		return 0;
diff --git a/drivers/acpi/acpica/Makefile b/drivers/acpi/acpica/Makefile
index a1b9bf5..5a542c8 100644
--- a/drivers/acpi/acpica/Makefile
+++ b/drivers/acpi/acpica/Makefile
@@ -83,6 +83,7 @@ acpi-$(ACPI_FUTURE_USAGE) += hwtimer.o
 acpi-y +=		\
 	nsaccess.o	\
 	nsalloc.o	\
+	nsconvert.o	\
 	nsdump.o	\
 	nseval.o	\
 	nsinit.o	\
diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h
index ecb4992..833fbc5 100644
--- a/drivers/acpi/acpica/acglobal.h
+++ b/drivers/acpi/acpica/acglobal.h
@@ -413,10 +413,12 @@ ACPI_EXTERN u8 acpi_gbl_db_output_flags;
 
 #ifdef ACPI_DISASSEMBLER
 
-u8 ACPI_INIT_GLOBAL(acpi_gbl_ignore_noop_operator, FALSE);
+ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_ignore_noop_operator, FALSE);
 
 ACPI_EXTERN u8 acpi_gbl_db_opt_disasm;
 ACPI_EXTERN u8 acpi_gbl_db_opt_verbose;
+ACPI_EXTERN u8 acpi_gbl_num_external_methods;
+ACPI_EXTERN u32 acpi_gbl_resolved_external_methods;
 ACPI_EXTERN struct acpi_external_list *acpi_gbl_external_list;
 ACPI_EXTERN struct acpi_external_file *acpi_gbl_external_file_list;
 #endif
diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h
index 805f419..636658f 100644
--- a/drivers/acpi/acpica/aclocal.h
+++ b/drivers/acpi/acpica/aclocal.h
@@ -363,6 +363,7 @@ struct acpi_predefined_data {
 	union acpi_operand_object *parent_package;
 	struct acpi_namespace_node *node;
 	u32 flags;
+	u32 return_btype;
 	u8 node_flags;
 };
 
@@ -371,6 +372,20 @@ struct acpi_predefined_data {
 #define ACPI_OBJECT_REPAIRED    1
 #define ACPI_OBJECT_WRAPPED     2
 
+/* Return object auto-repair info */
+
+typedef acpi_status(*acpi_object_converter) (union acpi_operand_object
+					     *original_object,
+					     union acpi_operand_object
+					     **converted_object);
+
+struct acpi_simple_repair_info {
+	char name[ACPI_NAME_SIZE];
+	u32 unexpected_btypes;
+	u32 package_index;
+	acpi_object_converter object_converter;
+};
+
 /*
  * Bitmapped return value types
  * Note: the actual data types must be contiguous, a loop in nspredef.c
@@ -1037,6 +1052,7 @@ struct acpi_external_list {
 	u16 length;
 	u8 type;
 	u8 flags;
+	u8 resolved;
 };
 
 /* Values for Flags field above */
diff --git a/drivers/acpi/acpica/acmacros.h b/drivers/acpi/acpica/acmacros.h
index ed7943b..53666bd 100644
--- a/drivers/acpi/acpica/acmacros.h
+++ b/drivers/acpi/acpica/acmacros.h
@@ -322,10 +322,12 @@
  * where a pointer to an object of type union acpi_operand_object can also
  * appear. This macro is used to distinguish them.
  *
- * The "Descriptor" field is the first field in both structures.
+ * The "DescriptorType" field is the second field in both structures.
  */
+#define ACPI_GET_DESCRIPTOR_PTR(d)      (((union acpi_descriptor *)(void *)(d))->common.common_pointer)
+#define ACPI_SET_DESCRIPTOR_PTR(d, p)   (((union acpi_descriptor *)(void *)(d))->common.common_pointer = (p))
 #define ACPI_GET_DESCRIPTOR_TYPE(d)     (((union acpi_descriptor *)(void *)(d))->common.descriptor_type)
-#define ACPI_SET_DESCRIPTOR_TYPE(d, t)  (((union acpi_descriptor *)(void *)(d))->common.descriptor_type = t)
+#define ACPI_SET_DESCRIPTOR_TYPE(d, t)  (((union acpi_descriptor *)(void *)(d))->common.descriptor_type = (t))
 
 /*
  * Macros for the master AML opcode table
diff --git a/drivers/acpi/acpica/acnamesp.h b/drivers/acpi/acpica/acnamesp.h
index 02cd548..6475962 100644
--- a/drivers/acpi/acpica/acnamesp.h
+++ b/drivers/acpi/acpica/acnamesp.h
@@ -167,6 +167,29 @@ void acpi_ns_delete_children(struct acpi_namespace_node *parent);
 int acpi_ns_compare_names(char *name1, char *name2);
 
 /*
+ * nsconvert - Dynamic object conversion routines
+ */
+acpi_status
+acpi_ns_convert_to_integer(union acpi_operand_object *original_object,
+			   union acpi_operand_object **return_object);
+
+acpi_status
+acpi_ns_convert_to_string(union acpi_operand_object *original_object,
+			  union acpi_operand_object **return_object);
+
+acpi_status
+acpi_ns_convert_to_buffer(union acpi_operand_object *original_object,
+			  union acpi_operand_object **return_object);
+
+acpi_status
+acpi_ns_convert_to_unicode(union acpi_operand_object *original_object,
+			   union acpi_operand_object **return_object);
+
+acpi_status
+acpi_ns_convert_to_resource(union acpi_operand_object *original_object,
+			    union acpi_operand_object **return_object);
+
+/*
  * nsdump - Namespace dump/print utilities
  */
 #ifdef	ACPI_FUTURE_USAGE
@@ -289,7 +312,7 @@ acpi_ns_get_attached_data(struct acpi_namespace_node *node,
  * predefined methods/objects
  */
 acpi_status
-acpi_ns_repair_object(struct acpi_predefined_data *data,
+acpi_ns_simple_repair(struct acpi_predefined_data *data,
 		      u32 expected_btypes,
 		      u32 package_index,
 		      union acpi_operand_object **return_object_ptr);
diff --git a/drivers/acpi/acpica/acutils.h b/drivers/acpi/acpica/acutils.h
index 0082fa0..c01f1a1 100644
--- a/drivers/acpi/acpica/acutils.h
+++ b/drivers/acpi/acpica/acutils.h
@@ -483,7 +483,8 @@ acpi_ut_short_divide(u64 in_dividend,
 /*
  * utmisc
  */
-const char *acpi_ut_validate_exception(acpi_status status);
+const struct acpi_exception_info *acpi_ut_validate_exception(acpi_status
+							     status);
 
 u8 acpi_ut_is_pci_root_bridge(char *id);
 
diff --git a/drivers/acpi/acpica/dsutils.c b/drivers/acpi/acpica/dsutils.c
index 4d8c992..9977899 100644
--- a/drivers/acpi/acpica/dsutils.c
+++ b/drivers/acpi/acpica/dsutils.c
@@ -178,7 +178,7 @@ acpi_ds_is_result_used(union acpi_parse_object * op,
 
 	if (!op) {
 		ACPI_ERROR((AE_INFO, "Null Op"));
-		return_VALUE(TRUE);
+		return_UINT8(TRUE);
 	}
 
 	/*
@@ -210,7 +210,7 @@ acpi_ds_is_result_used(union acpi_parse_object * op,
 				  "At Method level, result of [%s] not used\n",
 				  acpi_ps_get_opcode_name(op->common.
 							  aml_opcode)));
-		return_VALUE(FALSE);
+		return_UINT8(FALSE);
 	}
 
 	/* Get info on the parent. The root_op is AML_SCOPE */
@@ -219,7 +219,7 @@ acpi_ds_is_result_used(union acpi_parse_object * op,
 	    acpi_ps_get_opcode_info(op->common.parent->common.aml_opcode);
 	if (parent_info->class == AML_CLASS_UNKNOWN) {
 		ACPI_ERROR((AE_INFO, "Unknown parent opcode Op=%p", op));
-		return_VALUE(FALSE);
+		return_UINT8(FALSE);
 	}
 
 	/*
@@ -307,7 +307,7 @@ acpi_ds_is_result_used(union acpi_parse_object * op,
 			  acpi_ps_get_opcode_name(op->common.parent->common.
 						  aml_opcode), op));
 
-	return_VALUE(TRUE);
+	return_UINT8(TRUE);
 
       result_not_used:
 	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
@@ -316,7 +316,7 @@ acpi_ds_is_result_used(union acpi_parse_object * op,
 			  acpi_ps_get_opcode_name(op->common.parent->common.
 						  aml_opcode), op));
 
-	return_VALUE(FALSE);
+	return_UINT8(FALSE);
 }
 
 /*******************************************************************************
diff --git a/drivers/acpi/acpica/evevent.c b/drivers/acpi/acpica/evevent.c
index b8ea0b26..02219ff 100644
--- a/drivers/acpi/acpica/evevent.c
+++ b/drivers/acpi/acpica/evevent.c
@@ -257,6 +257,8 @@ u32 acpi_ev_fixed_event_detect(void)
  *
  * DESCRIPTION: Clears the status bit for the requested event, calls the
  *              handler that previously registered for the event.
+ *              NOTE: If there is no handler for the event, the event is
+ *              disabled to prevent futher interrupts.
  *
  ******************************************************************************/
 
@@ -271,17 +273,17 @@ static u32 acpi_ev_fixed_event_dispatch(u32 event)
 				      status_register_id, ACPI_CLEAR_STATUS);
 
 	/*
-	 * Make sure we've got a handler. If not, report an error. The event is
-	 * disabled to prevent further interrupts.
+	 * Make sure that a handler exists. If not, report an error
+	 * and disable the event to prevent further interrupts.
 	 */
-	if (NULL == acpi_gbl_fixed_event_handlers[event].handler) {
+	if (!acpi_gbl_fixed_event_handlers[event].handler) {
 		(void)acpi_write_bit_register(acpi_gbl_fixed_event_info[event].
 					      enable_register_id,
 					      ACPI_DISABLE_EVENT);
 
 		ACPI_ERROR((AE_INFO,
-			    "No installed handler for fixed event [0x%08X]",
-			    event));
+			    "No installed handler for fixed event - %s (%u), disabling",
+			    acpi_ut_get_event_name(event), event));
 
 		return (ACPI_INTERRUPT_NOT_HANDLED);
 	}
diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c
index b9adb9a..a493b52 100644
--- a/drivers/acpi/acpica/evgpe.c
+++ b/drivers/acpi/acpica/evgpe.c
@@ -707,7 +707,7 @@ acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device,
 		if (ACPI_FAILURE(status)) {
 			ACPI_EXCEPTION((AE_INFO, status,
 					"Unable to clear GPE%02X", gpe_number));
-			return_VALUE(ACPI_INTERRUPT_NOT_HANDLED);
+			return_UINT32(ACPI_INTERRUPT_NOT_HANDLED);
 		}
 	}
 
@@ -724,7 +724,7 @@ acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device,
 	if (ACPI_FAILURE(status)) {
 		ACPI_EXCEPTION((AE_INFO, status,
 				"Unable to disable GPE%02X", gpe_number));
-		return_VALUE(ACPI_INTERRUPT_NOT_HANDLED);
+		return_UINT32(ACPI_INTERRUPT_NOT_HANDLED);
 	}
 
 	/*
@@ -784,7 +784,7 @@ acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device,
 		break;
 	}
 
-	return_VALUE(ACPI_INTERRUPT_HANDLED);
+	return_UINT32(ACPI_INTERRUPT_HANDLED);
 }
 
 #endif				/* !ACPI_REDUCED_HARDWARE */
diff --git a/drivers/acpi/acpica/evsci.c b/drivers/acpi/acpica/evsci.c
index f4b43be..b905acf 100644
--- a/drivers/acpi/acpica/evsci.c
+++ b/drivers/acpi/acpica/evsci.c
@@ -89,7 +89,7 @@ static u32 ACPI_SYSTEM_XFACE acpi_ev_sci_xrupt_handler(void *context)
 	 */
 	interrupt_handled |= acpi_ev_gpe_detect(gpe_xrupt_list);
 
-	return_VALUE(interrupt_handled);
+	return_UINT32(interrupt_handled);
 }
 
 /*******************************************************************************
@@ -120,7 +120,7 @@ u32 ACPI_SYSTEM_XFACE acpi_ev_gpe_xrupt_handler(void *context)
 
 	interrupt_handled |= acpi_ev_gpe_detect(gpe_xrupt_list);
 
-	return_VALUE(interrupt_handled);
+	return_UINT32(interrupt_handled);
 }
 
 /******************************************************************************
diff --git a/drivers/acpi/acpica/evxface.c b/drivers/acpi/acpica/evxface.c
index ddffd68..ca5fba9 100644
--- a/drivers/acpi/acpica/evxface.c
+++ b/drivers/acpi/acpica/evxface.c
@@ -467,9 +467,9 @@ acpi_install_fixed_event_handler(u32 event,
 		return_ACPI_STATUS(status);
 	}
 
-	/* Don't allow two handlers. */
+	/* Do not allow multiple handlers */
 
-	if (NULL != acpi_gbl_fixed_event_handlers[event].handler) {
+	if (acpi_gbl_fixed_event_handlers[event].handler) {
 		status = AE_ALREADY_EXISTS;
 		goto cleanup;
 	}
@@ -483,8 +483,9 @@ acpi_install_fixed_event_handler(u32 event,
 	if (ACPI_SUCCESS(status))
 		status = acpi_enable_event(event, 0);
 	if (ACPI_FAILURE(status)) {
-		ACPI_WARNING((AE_INFO, "Could not enable fixed event 0x%X",
-			      event));
+		ACPI_WARNING((AE_INFO,
+			      "Could not enable fixed event - %s (%u)",
+			      acpi_ut_get_event_name(event), event));
 
 		/* Remove the handler */
 
@@ -492,7 +493,8 @@ acpi_install_fixed_event_handler(u32 event,
 		acpi_gbl_fixed_event_handlers[event].context = NULL;
 	} else {
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-				  "Enabled fixed event %X, Handler=%p\n", event,
+				  "Enabled fixed event %s (%X), Handler=%p\n",
+				  acpi_ut_get_event_name(event), event,
 				  handler));
 	}
 
@@ -544,11 +546,12 @@ acpi_remove_fixed_event_handler(u32 event, acpi_event_handler handler)
 
 	if (ACPI_FAILURE(status)) {
 		ACPI_WARNING((AE_INFO,
-			      "Could not write to fixed event enable register 0x%X",
-			      event));
+			      "Could not disable fixed event - %s (%u)",
+			      acpi_ut_get_event_name(event), event));
 	} else {
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Disabled fixed event %X\n",
-				  event));
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+				  "Disabled fixed event - %s (%X)\n",
+				  acpi_ut_get_event_name(event), event));
 	}
 
 	(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
diff --git a/drivers/acpi/acpica/evxfevnt.c b/drivers/acpi/acpica/evxfevnt.c
index d6e4e42..7039606 100644
--- a/drivers/acpi/acpica/evxfevnt.c
+++ b/drivers/acpi/acpica/evxfevnt.c
@@ -74,6 +74,12 @@ acpi_status acpi_enable(void)
 		return_ACPI_STATUS(AE_NO_ACPI_TABLES);
 	}
 
+	/* If the Hardware Reduced flag is set, machine is always in acpi mode */
+
+	if (acpi_gbl_reduced_hardware) {
+		return_ACPI_STATUS(AE_OK);
+	}
+
 	/* Check current mode */
 
 	if (acpi_hw_get_mode() == ACPI_SYS_MODE_ACPI) {
@@ -126,6 +132,12 @@ acpi_status acpi_disable(void)
 
 	ACPI_FUNCTION_TRACE(acpi_disable);
 
+	/* If the Hardware Reduced flag is set, machine is always in acpi mode */
+
+	if (acpi_gbl_reduced_hardware) {
+		return_ACPI_STATUS(AE_OK);
+	}
+
 	if (acpi_hw_get_mode() == ACPI_SYS_MODE_LEGACY) {
 		ACPI_DEBUG_PRINT((ACPI_DB_INIT,
 				  "System is already in legacy (non-ACPI) mode\n"));
diff --git a/drivers/acpi/acpica/exprep.c b/drivers/acpi/acpica/exprep.c
index d6eab81..6b728ae 100644
--- a/drivers/acpi/acpica/exprep.c
+++ b/drivers/acpi/acpica/exprep.c
@@ -276,7 +276,7 @@ acpi_ex_decode_field_access(union acpi_operand_object *obj_desc,
 		/* Invalid field access type */
 
 		ACPI_ERROR((AE_INFO, "Unknown field access type 0x%X", access));
-		return_VALUE(0);
+		return_UINT32(0);
 	}
 
 	if (obj_desc->common.type == ACPI_TYPE_BUFFER_FIELD) {
@@ -289,7 +289,7 @@ acpi_ex_decode_field_access(union acpi_operand_object *obj_desc,
 	}
 
 	*return_byte_alignment = byte_alignment;
-	return_VALUE(bit_length);
+	return_UINT32(bit_length);
 }
 
 /*******************************************************************************
diff --git a/drivers/acpi/acpica/exutils.c b/drivers/acpi/acpica/exutils.c
index b205cbb..99dc7b2 100644
--- a/drivers/acpi/acpica/exutils.c
+++ b/drivers/acpi/acpica/exutils.c
@@ -340,7 +340,7 @@ static u32 acpi_ex_digits_needed(u64 value, u32 base)
 	/* u64 is unsigned, so we don't worry about a '-' prefix */
 
 	if (value == 0) {
-		return_VALUE(1);
+		return_UINT32(1);
 	}
 
 	current_value = value;
@@ -354,7 +354,7 @@ static u32 acpi_ex_digits_needed(u64 value, u32 base)
 		num_digits++;
 	}
 
-	return_VALUE(num_digits);
+	return_UINT32(num_digits);
 }
 
 /*******************************************************************************
diff --git a/drivers/acpi/acpica/hwacpi.c b/drivers/acpi/acpica/hwacpi.c
index deb3f61..579c3a5 100644
--- a/drivers/acpi/acpica/hwacpi.c
+++ b/drivers/acpi/acpica/hwacpi.c
@@ -66,6 +66,12 @@ acpi_status acpi_hw_set_mode(u32 mode)
 
 	ACPI_FUNCTION_TRACE(hw_set_mode);
 
+	/* If the Hardware Reduced flag is set, machine is always in acpi mode */
+
+	if (acpi_gbl_reduced_hardware) {
+		return_ACPI_STATUS(AE_OK);
+	}
+
 	/*
 	 * ACPI 2.0 clarified that if SMI_CMD in FADT is zero,
 	 * system does not support mode transition.
@@ -146,23 +152,29 @@ u32 acpi_hw_get_mode(void)
 
 	ACPI_FUNCTION_TRACE(hw_get_mode);
 
+	/* If the Hardware Reduced flag is set, machine is always in acpi mode */
+
+	if (acpi_gbl_reduced_hardware) {
+		return_UINT32(ACPI_SYS_MODE_ACPI);
+	}
+
 	/*
 	 * ACPI 2.0 clarified that if SMI_CMD in FADT is zero,
 	 * system does not support mode transition.
 	 */
 	if (!acpi_gbl_FADT.smi_command) {
-		return_VALUE(ACPI_SYS_MODE_ACPI);
+		return_UINT32(ACPI_SYS_MODE_ACPI);
 	}
 
 	status = acpi_read_bit_register(ACPI_BITREG_SCI_ENABLE, &value);
 	if (ACPI_FAILURE(status)) {
-		return_VALUE(ACPI_SYS_MODE_LEGACY);
+		return_UINT32(ACPI_SYS_MODE_LEGACY);
 	}
 
 	if (value) {
-		return_VALUE(ACPI_SYS_MODE_ACPI);
+		return_UINT32(ACPI_SYS_MODE_ACPI);
 	} else {
-		return_VALUE(ACPI_SYS_MODE_LEGACY);
+		return_UINT32(ACPI_SYS_MODE_LEGACY);
 	}
 }
 
diff --git a/drivers/acpi/acpica/nsconvert.c b/drivers/acpi/acpica/nsconvert.c
new file mode 100644
index 0000000..8f79a9d
--- /dev/null
+++ b/drivers/acpi/acpica/nsconvert.c
@@ -0,0 +1,443 @@
+/******************************************************************************
+ *
+ * Module Name: nsconvert - Object conversions for objects returned by
+ *                          predefined methods
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2013, Intel Corp.
+ * 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, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    substantially similar to the "NO WARRANTY" disclaimer below
+ *    ("Disclaimer") and any redistribution must be conditioned upon
+ *    including a substantially similar Disclaimer requirement for further
+ *    binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ *    of any 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") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * 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 MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ */
+
+#include <acpi/acpi.h>
+#include "accommon.h"
+#include "acnamesp.h"
+#include "acinterp.h"
+#include "acpredef.h"
+#include "amlresrc.h"
+
+#define _COMPONENT          ACPI_NAMESPACE
+ACPI_MODULE_NAME("nsconvert")
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ns_convert_to_integer
+ *
+ * PARAMETERS:  original_object     - Object to be converted
+ *              return_object       - Where the new converted object is returned
+ *
+ * RETURN:      Status. AE_OK if conversion was successful.
+ *
+ * DESCRIPTION: Attempt to convert a String/Buffer object to an Integer.
+ *
+ ******************************************************************************/
+acpi_status
+acpi_ns_convert_to_integer(union acpi_operand_object *original_object,
+			   union acpi_operand_object **return_object)
+{
+	union acpi_operand_object *new_object;
+	acpi_status status;
+	u64 value = 0;
+	u32 i;
+
+	switch (original_object->common.type) {
+	case ACPI_TYPE_STRING:
+
+		/* String-to-Integer conversion */
+
+		status = acpi_ut_strtoul64(original_object->string.pointer,
+					   ACPI_ANY_BASE, &value);
+		if (ACPI_FAILURE(status)) {
+			return (status);
+		}
+		break;
+
+	case ACPI_TYPE_BUFFER:
+
+		/* Buffer-to-Integer conversion. Max buffer size is 64 bits. */
+
+		if (original_object->buffer.length > 8) {
+			return (AE_AML_OPERAND_TYPE);
+		}
+
+		/* Extract each buffer byte to create the integer */
+
+		for (i = 0; i < original_object->buffer.length; i++) {
+			value |=
+			    ((u64)original_object->buffer.
+			     pointer[i] << (i * 8));
+		}
+		break;
+
+	default:
+		return (AE_AML_OPERAND_TYPE);
+	}
+
+	new_object = acpi_ut_create_integer_object(value);
+	if (!new_object) {
+		return (AE_NO_MEMORY);
+	}
+
+	*return_object = new_object;
+	return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ns_convert_to_string
+ *
+ * PARAMETERS:  original_object     - Object to be converted
+ *              return_object       - Where the new converted object is returned
+ *
+ * RETURN:      Status. AE_OK if conversion was successful.
+ *
+ * DESCRIPTION: Attempt to convert a Integer/Buffer object to a String.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ns_convert_to_string(union acpi_operand_object *original_object,
+			  union acpi_operand_object **return_object)
+{
+	union acpi_operand_object *new_object;
+	acpi_size length;
+	acpi_status status;
+
+	switch (original_object->common.type) {
+	case ACPI_TYPE_INTEGER:
+		/*
+		 * Integer-to-String conversion. Commonly, convert
+		 * an integer of value 0 to a NULL string. The last element of
+		 * _BIF and _BIX packages occasionally need this fix.
+		 */
+		if (original_object->integer.value == 0) {
+
+			/* Allocate a new NULL string object */
+
+			new_object = acpi_ut_create_string_object(0);
+			if (!new_object) {
+				return (AE_NO_MEMORY);
+			}
+		} else {
+			status =
+			    acpi_ex_convert_to_string(original_object,
+						      &new_object,
+						      ACPI_IMPLICIT_CONVERT_HEX);
+			if (ACPI_FAILURE(status)) {
+				return (status);
+			}
+		}
+		break;
+
+	case ACPI_TYPE_BUFFER:
+		/*
+		 * Buffer-to-String conversion. Use a to_string
+		 * conversion, no transform performed on the buffer data. The best
+		 * example of this is the _BIF method, where the string data from
+		 * the battery is often (incorrectly) returned as buffer object(s).
+		 */
+		length = 0;
+		while ((length < original_object->buffer.length) &&
+		       (original_object->buffer.pointer[length])) {
+			length++;
+		}
+
+		/* Allocate a new string object */
+
+		new_object = acpi_ut_create_string_object(length);
+		if (!new_object) {
+			return (AE_NO_MEMORY);
+		}
+
+		/*
+		 * Copy the raw buffer data with no transform. String is already NULL
+		 * terminated at Length+1.
+		 */
+		ACPI_MEMCPY(new_object->string.pointer,
+			    original_object->buffer.pointer, length);
+		break;
+
+	default:
+		return (AE_AML_OPERAND_TYPE);
+	}
+
+	*return_object = new_object;
+	return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ns_convert_to_buffer
+ *
+ * PARAMETERS:  original_object     - Object to be converted
+ *              return_object       - Where the new converted object is returned
+ *
+ * RETURN:      Status. AE_OK if conversion was successful.
+ *
+ * DESCRIPTION: Attempt to convert a Integer/String/Package object to a Buffer.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ns_convert_to_buffer(union acpi_operand_object *original_object,
+			  union acpi_operand_object **return_object)
+{
+	union acpi_operand_object *new_object;
+	acpi_status status;
+	union acpi_operand_object **elements;
+	u32 *dword_buffer;
+	u32 count;
+	u32 i;
+
+	switch (original_object->common.type) {
+	case ACPI_TYPE_INTEGER:
+		/*
+		 * Integer-to-Buffer conversion.
+		 * Convert the Integer to a packed-byte buffer. _MAT and other
+		 * objects need this sometimes, if a read has been performed on a
+		 * Field object that is less than or equal to the global integer
+		 * size (32 or 64 bits).
+		 */
+		status =
+		    acpi_ex_convert_to_buffer(original_object, &new_object);
+		if (ACPI_FAILURE(status)) {
+			return (status);
+		}
+		break;
+
+	case ACPI_TYPE_STRING:
+
+		/* String-to-Buffer conversion. Simple data copy */
+
+		new_object =
+		    acpi_ut_create_buffer_object(original_object->string.
+						 length);
+		if (!new_object) {
+			return (AE_NO_MEMORY);
+		}
+
+		ACPI_MEMCPY(new_object->buffer.pointer,
+			    original_object->string.pointer,
+			    original_object->string.length);
+		break;
+
+	case ACPI_TYPE_PACKAGE:
+		/*
+		 * This case is often seen for predefined names that must return a
+		 * Buffer object with multiple DWORD integers within. For example,
+		 * _FDE and _GTM. The Package can be converted to a Buffer.
+		 */
+
+		/* All elements of the Package must be integers */
+
+		elements = original_object->package.elements;
+		count = original_object->package.count;
+
+		for (i = 0; i < count; i++) {
+			if ((!*elements) ||
+			    ((*elements)->common.type != ACPI_TYPE_INTEGER)) {
+				return (AE_AML_OPERAND_TYPE);
+			}
+			elements++;
+		}
+
+		/* Create the new buffer object to replace the Package */
+
+		new_object = acpi_ut_create_buffer_object(ACPI_MUL_4(count));
+		if (!new_object) {
+			return (AE_NO_MEMORY);
+		}
+
+		/* Copy the package elements (integers) to the buffer as DWORDs */
+
+		elements = original_object->package.elements;
+		dword_buffer = ACPI_CAST_PTR(u32, new_object->buffer.pointer);
+
+		for (i = 0; i < count; i++) {
+			*dword_buffer = (u32)(*elements)->integer.value;
+			dword_buffer++;
+			elements++;
+		}
+		break;
+
+	default:
+		return (AE_AML_OPERAND_TYPE);
+	}
+
+	*return_object = new_object;
+	return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ns_convert_to_unicode
+ *
+ * PARAMETERS:  original_object     - ASCII String Object to be converted
+ *              return_object       - Where the new converted object is returned
+ *
+ * RETURN:      Status. AE_OK if conversion was successful.
+ *
+ * DESCRIPTION: Attempt to convert a String object to a Unicode string Buffer.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ns_convert_to_unicode(union acpi_operand_object *original_object,
+			   union acpi_operand_object **return_object)
+{
+	union acpi_operand_object *new_object;
+	char *ascii_string;
+	u16 *unicode_buffer;
+	u32 unicode_length;
+	u32 i;
+
+	if (!original_object) {
+		return (AE_OK);
+	}
+
+	/* If a Buffer was returned, it must be at least two bytes long */
+
+	if (original_object->common.type == ACPI_TYPE_BUFFER) {
+		if (original_object->buffer.length < 2) {
+			return (AE_AML_OPERAND_VALUE);
+		}
+
+		*return_object = NULL;
+		return (AE_OK);
+	}
+
+	/*
+	 * The original object is an ASCII string. Convert this string to
+	 * a unicode buffer.
+	 */
+	ascii_string = original_object->string.pointer;
+	unicode_length = (original_object->string.length * 2) + 2;
+
+	/* Create a new buffer object for the Unicode data */
+
+	new_object = acpi_ut_create_buffer_object(unicode_length);
+	if (!new_object) {
+		return (AE_NO_MEMORY);
+	}
+
+	unicode_buffer = ACPI_CAST_PTR(u16, new_object->buffer.pointer);
+
+	/* Convert ASCII to Unicode */
+
+	for (i = 0; i < original_object->string.length; i++) {
+		unicode_buffer[i] = (u16)ascii_string[i];
+	}
+
+	*return_object = new_object;
+	return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ns_convert_to_resource
+ *
+ * PARAMETERS:  original_object     - Object to be converted
+ *              return_object       - Where the new converted object is returned
+ *
+ * RETURN:      Status. AE_OK if conversion was successful
+ *
+ * DESCRIPTION: Attempt to convert a Integer object to a resource_template
+ *              Buffer.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ns_convert_to_resource(union acpi_operand_object *original_object,
+			    union acpi_operand_object **return_object)
+{
+	union acpi_operand_object *new_object;
+	u8 *buffer;
+
+	/*
+	 * We can fix the following cases for an expected resource template:
+	 * 1. No return value (interpreter slack mode is disabled)
+	 * 2. A "Return (Zero)" statement
+	 * 3. A "Return empty buffer" statement
+	 *
+	 * We will return a buffer containing a single end_tag
+	 * resource descriptor.
+	 */
+	if (original_object) {
+		switch (original_object->common.type) {
+		case ACPI_TYPE_INTEGER:
+
+			/* We can only repair an Integer==0 */
+
+			if (original_object->integer.value) {
+				return (AE_AML_OPERAND_TYPE);
+			}
+			break;
+
+		case ACPI_TYPE_BUFFER:
+
+			if (original_object->buffer.length) {
+
+				/* Additional checks can be added in the future */
+
+				*return_object = NULL;
+				return (AE_OK);
+			}
+			break;
+
+		case ACPI_TYPE_STRING:
+		default:
+
+			return (AE_AML_OPERAND_TYPE);
+		}
+	}
+
+	/* Create the new buffer object for the resource descriptor */
+
+	new_object = acpi_ut_create_buffer_object(2);
+	if (!new_object) {
+		return (AE_NO_MEMORY);
+	}
+
+	buffer = ACPI_CAST_PTR(u8, new_object->buffer.pointer);
+
+	/* Initialize the Buffer with a single end_tag descriptor */
+
+	buffer[0] = (ACPI_RESOURCE_NAME_END_TAG | ASL_RDESC_END_TAG_SIZE);
+	buffer[1] = 0x00;
+
+	*return_object = new_object;
+	return (AE_OK);
+}
diff --git a/drivers/acpi/acpica/nspredef.c b/drivers/acpi/acpica/nspredef.c
index 224c300..36f7240 100644
--- a/drivers/acpi/acpica/nspredef.c
+++ b/drivers/acpi/acpica/nspredef.c
@@ -78,6 +78,8 @@ acpi_ns_check_reference(struct acpi_predefined_data *data,
 
 static void acpi_ns_get_expected_types(char *buffer, u32 expected_btypes);
 
+static u32 acpi_ns_get_bitmapped_type(union acpi_operand_object *return_object);
+
 /*
  * Names for the types that can be returned by the predefined objects.
  * Used for warning messages. Must be in the same order as the ACPI_RTYPEs
@@ -112,7 +114,6 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
 			       acpi_status return_status,
 			       union acpi_operand_object **return_object_ptr)
 {
-	union acpi_operand_object *return_object = *return_object_ptr;
 	acpi_status status = AE_OK;
 	const union acpi_predefined_info *predefined;
 	char *pathname;
@@ -152,25 +153,6 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
 	}
 
 	/*
-	 * If there is no return value, check if we require a return value for
-	 * this predefined name. Either one return value is expected, or none,
-	 * for both methods and other objects.
-	 *
-	 * Exit now if there is no return object. Warning if one was expected.
-	 */
-	if (!return_object) {
-		if ((predefined->info.expected_btypes) &&
-		    (!(predefined->info.expected_btypes & ACPI_RTYPE_NONE))) {
-			ACPI_WARN_PREDEFINED((AE_INFO, pathname,
-					      ACPI_WARN_ALWAYS,
-					      "Missing expected return value"));
-
-			status = AE_AML_NO_RETURN_VALUE;
-		}
-		goto cleanup;
-	}
-
-	/*
 	 * Return value validation and possible repair.
 	 *
 	 * 1) Don't perform return value validation/repair if this feature
@@ -410,28 +392,12 @@ acpi_ns_check_object_type(struct acpi_predefined_data *data,
 {
 	union acpi_operand_object *return_object = *return_object_ptr;
 	acpi_status status = AE_OK;
-	u32 return_btype;
 	char type_buffer[48];	/* Room for 5 types */
 
-	/*
-	 * If we get a NULL return_object here, it is a NULL package element.
-	 * Since all extraneous NULL package elements were removed earlier by a
-	 * call to acpi_ns_remove_null_elements, this is an unexpected NULL element.
-	 * We will attempt to repair it.
-	 */
-	if (!return_object) {
-		status = acpi_ns_repair_null_element(data, expected_btypes,
-						     package_index,
-						     return_object_ptr);
-		if (ACPI_SUCCESS(status)) {
-			return (AE_OK);	/* Repair was successful */
-		}
-		goto type_error_exit;
-	}
-
 	/* A Namespace node should not get here, but make sure */
 
-	if (ACPI_GET_DESCRIPTOR_TYPE(return_object) == ACPI_DESC_TYPE_NAMED) {
+	if (return_object &&
+	    ACPI_GET_DESCRIPTOR_TYPE(return_object) == ACPI_DESC_TYPE_NAMED) {
 		ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags,
 				      "Invalid return type - Found a Namespace node [%4.4s] type %s",
 				      return_object->node.name.ascii,
@@ -448,53 +414,25 @@ acpi_ns_check_object_type(struct acpi_predefined_data *data,
 	 * from all of the predefined names (including elements of returned
 	 * packages)
 	 */
-	switch (return_object->common.type) {
-	case ACPI_TYPE_INTEGER:
-		return_btype = ACPI_RTYPE_INTEGER;
-		break;
-
-	case ACPI_TYPE_BUFFER:
-		return_btype = ACPI_RTYPE_BUFFER;
-		break;
-
-	case ACPI_TYPE_STRING:
-		return_btype = ACPI_RTYPE_STRING;
-		break;
+	data->return_btype = acpi_ns_get_bitmapped_type(return_object);
+	if (data->return_btype == ACPI_RTYPE_ANY) {
 
-	case ACPI_TYPE_PACKAGE:
-		return_btype = ACPI_RTYPE_PACKAGE;
-		break;
-
-	case ACPI_TYPE_LOCAL_REFERENCE:
-		return_btype = ACPI_RTYPE_REFERENCE;
-		break;
-
-	default:
 		/* Not one of the supported objects, must be incorrect */
-
 		goto type_error_exit;
 	}
 
-	/* Is the object one of the expected types? */
-
-	if (return_btype & expected_btypes) {
-
-		/* For reference objects, check that the reference type is correct */
-
-		if (return_object->common.type == ACPI_TYPE_LOCAL_REFERENCE) {
-			status = acpi_ns_check_reference(data, return_object);
-		}
+	/* For reference objects, check that the reference type is correct */
 
+	if ((data->return_btype & expected_btypes) == ACPI_RTYPE_REFERENCE) {
+		status = acpi_ns_check_reference(data, return_object);
 		return (status);
 	}
 
-	/* Type mismatch -- attempt repair of the returned object */
+	/* Attempt simple repair of the returned object if necessary */
 
-	status = acpi_ns_repair_object(data, expected_btypes,
+	status = acpi_ns_simple_repair(data, expected_btypes,
 				       package_index, return_object_ptr);
-	if (ACPI_SUCCESS(status)) {
-		return (AE_OK);	/* Repair was successful */
-	}
+	return (status);
 
       type_error_exit:
 
@@ -558,6 +496,61 @@ acpi_ns_check_reference(struct acpi_predefined_data *data,
 
 /*******************************************************************************
  *
+ * FUNCTION:    acpi_ns_get_bitmapped_type
+ *
+ * PARAMETERS:  return_object   - Object returned from method/obj evaluation
+ *
+ * RETURN:      Object return type. ACPI_RTYPE_ANY indicates that the object
+ *              type is not supported. ACPI_RTYPE_NONE indicates that no
+ *              object was returned (return_object is NULL).
+ *
+ * DESCRIPTION: Convert object type into a bitmapped object return type.
+ *
+ ******************************************************************************/
+
+static u32 acpi_ns_get_bitmapped_type(union acpi_operand_object *return_object)
+{
+	u32 return_btype;
+
+	if (!return_object) {
+		return (ACPI_RTYPE_NONE);
+	}
+
+	/* Map acpi_object_type to internal bitmapped type */
+
+	switch (return_object->common.type) {
+	case ACPI_TYPE_INTEGER:
+		return_btype = ACPI_RTYPE_INTEGER;
+		break;
+
+	case ACPI_TYPE_BUFFER:
+		return_btype = ACPI_RTYPE_BUFFER;
+		break;
+
+	case ACPI_TYPE_STRING:
+		return_btype = ACPI_RTYPE_STRING;
+		break;
+
+	case ACPI_TYPE_PACKAGE:
+		return_btype = ACPI_RTYPE_PACKAGE;
+		break;
+
+	case ACPI_TYPE_LOCAL_REFERENCE:
+		return_btype = ACPI_RTYPE_REFERENCE;
+		break;
+
+	default:
+		/* Not one of the supported objects, must be incorrect */
+
+		return_btype = ACPI_RTYPE_ANY;
+		break;
+	}
+
+	return (return_btype);
+}
+
+/*******************************************************************************
+ *
  * FUNCTION:    acpi_ns_get_expected_types
  *
  * PARAMETERS:  buffer          - Pointer to where the string is returned
diff --git a/drivers/acpi/acpica/nsprepkg.c b/drivers/acpi/acpica/nsprepkg.c
index a401554..77cdd53 100644
--- a/drivers/acpi/acpica/nsprepkg.c
+++ b/drivers/acpi/acpica/nsprepkg.c
@@ -112,9 +112,15 @@ acpi_ns_check_package(struct acpi_predefined_data *data,
 	elements = return_object->package.elements;
 	count = return_object->package.count;
 
-	/* The package must have at least one element, else invalid */
-
+	/*
+	 * Most packages must have at least one element. The only exception
+	 * is the variable-length package (ACPI_PTYPE1_VAR).
+	 */
 	if (!count) {
+		if (package->ret_info.type == ACPI_PTYPE1_VAR) {
+			return (AE_OK);
+		}
+
 		ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags,
 				      "Return Package has no elements (empty)"));
 
diff --git a/drivers/acpi/acpica/nsrepair.c b/drivers/acpi/acpica/nsrepair.c
index 9e83335..18f02e4 100644
--- a/drivers/acpi/acpica/nsrepair.c
+++ b/drivers/acpi/acpica/nsrepair.c
@@ -46,6 +46,7 @@
 #include "acnamesp.h"
 #include "acinterp.h"
 #include "acpredef.h"
+#include "amlresrc.h"
 
 #define _COMPONENT          ACPI_NAMESPACE
 ACPI_MODULE_NAME("nsrepair")
@@ -71,6 +72,11 @@ ACPI_MODULE_NAME("nsrepair")
  * Buffer  -> String
  * Buffer  -> Package of Integers
  * Package -> Package of one Package
+ *
+ * Additional conversions that are available:
+ *  Convert a null return or zero return value to an end_tag descriptor
+ *  Convert an ASCII string to a Unicode buffer
+ *
  * An incorrect standalone object is wrapped with required outer package
  *
  * Additional possible repairs:
@@ -78,21 +84,51 @@ ACPI_MODULE_NAME("nsrepair")
  *
  ******************************************************************************/
 /* Local prototypes */
-static acpi_status
-acpi_ns_convert_to_integer(union acpi_operand_object *original_object,
-			   union acpi_operand_object **return_object);
-
-static acpi_status
-acpi_ns_convert_to_string(union acpi_operand_object *original_object,
-			  union acpi_operand_object **return_object);
+static const struct acpi_simple_repair_info *acpi_ns_match_simple_repair(struct
+									 acpi_namespace_node
+									 *node,
+									 u32
+									 return_btype,
+									 u32
+									 package_index);
 
-static acpi_status
-acpi_ns_convert_to_buffer(union acpi_operand_object *original_object,
-			  union acpi_operand_object **return_object);
+/*
+ * Special but simple repairs for some names.
+ *
+ * 2nd argument: Unexpected types that can be repaired
+ */
+static const struct acpi_simple_repair_info acpi_object_repair_info[] = {
+	/* Resource descriptor conversions */
+
+	{"_CRS",
+	 ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING | ACPI_RTYPE_BUFFER |
+	 ACPI_RTYPE_NONE,
+	 ACPI_NOT_PACKAGE_ELEMENT,
+	 acpi_ns_convert_to_resource},
+	{"_DMA",
+	 ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING | ACPI_RTYPE_BUFFER |
+	 ACPI_RTYPE_NONE,
+	 ACPI_NOT_PACKAGE_ELEMENT,
+	 acpi_ns_convert_to_resource},
+	{"_PRS",
+	 ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING | ACPI_RTYPE_BUFFER |
+	 ACPI_RTYPE_NONE,
+	 ACPI_NOT_PACKAGE_ELEMENT,
+	 acpi_ns_convert_to_resource},
+
+	/* Unicode conversions */
+
+	{"_MLS", ACPI_RTYPE_STRING, 1,
+	 acpi_ns_convert_to_unicode},
+	{"_STR", ACPI_RTYPE_STRING | ACPI_RTYPE_BUFFER,
+	 ACPI_NOT_PACKAGE_ELEMENT,
+	 acpi_ns_convert_to_unicode},
+	{{0, 0, 0, 0}, 0, 0, NULL}	/* Table terminator */
+};
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_ns_repair_object
+ * FUNCTION:    acpi_ns_simple_repair
  *
  * PARAMETERS:  data                - Pointer to validation data structure
  *              expected_btypes     - Object types expected
@@ -110,16 +146,54 @@ acpi_ns_convert_to_buffer(union acpi_operand_object *original_object,
  ******************************************************************************/
 
 acpi_status
-acpi_ns_repair_object(struct acpi_predefined_data *data,
+acpi_ns_simple_repair(struct acpi_predefined_data *data,
 		      u32 expected_btypes,
 		      u32 package_index,
 		      union acpi_operand_object **return_object_ptr)
 {
 	union acpi_operand_object *return_object = *return_object_ptr;
-	union acpi_operand_object *new_object;
+	union acpi_operand_object *new_object = NULL;
 	acpi_status status;
+	const struct acpi_simple_repair_info *predefined;
+
+	ACPI_FUNCTION_NAME(ns_simple_repair);
+
+	/*
+	 * Special repairs for certain names that are in the repair table.
+	 * Check if this name is in the list of repairable names.
+	 */
+	predefined = acpi_ns_match_simple_repair(data->node,
+						 data->return_btype,
+						 package_index);
+	if (predefined) {
+		if (!return_object) {
+			ACPI_WARN_PREDEFINED((AE_INFO, data->pathname,
+					      ACPI_WARN_ALWAYS,
+					      "Missing expected return value"));
+		}
+
+		status =
+		    predefined->object_converter(return_object, &new_object);
+		if (ACPI_FAILURE(status)) {
+
+			/* A fatal error occurred during a conversion */
+
+			ACPI_EXCEPTION((AE_INFO, status,
+					"During return object analysis"));
+			return (status);
+		}
+		if (new_object) {
+			goto object_repaired;
+		}
+	}
 
-	ACPI_FUNCTION_NAME(ns_repair_object);
+	/*
+	 * Do not perform simple object repair unless the return type is not
+	 * expected.
+	 */
+	if (data->return_btype & expected_btypes) {
+		return (AE_OK);
+	}
 
 	/*
 	 * At this point, we know that the type of the returned object was not
@@ -127,6 +201,24 @@ acpi_ns_repair_object(struct acpi_predefined_data *data,
 	 * repair the object by converting it to one of the expected object
 	 * types for this predefined name.
 	 */
+
+	/*
+	 * If there is no return value, check if we require a return value for
+	 * this predefined name. Either one return value is expected, or none,
+	 * for both methods and other objects.
+	 *
+	 * Exit now if there is no return object. Warning if one was expected.
+	 */
+	if (!return_object) {
+		if (expected_btypes && (!(expected_btypes & ACPI_RTYPE_NONE))) {
+			ACPI_WARN_PREDEFINED((AE_INFO, data->pathname,
+					      ACPI_WARN_ALWAYS,
+					      "Missing expected return value"));
+
+			return (AE_AML_NO_RETURN_VALUE);
+		}
+	}
+
 	if (expected_btypes & ACPI_RTYPE_INTEGER) {
 		status = acpi_ns_convert_to_integer(return_object, &new_object);
 		if (ACPI_SUCCESS(status)) {
@@ -216,254 +308,51 @@ acpi_ns_repair_object(struct acpi_predefined_data *data,
 	return (AE_OK);
 }
 
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ns_convert_to_integer
- *
- * PARAMETERS:  original_object     - Object to be converted
- *              return_object       - Where the new converted object is returned
- *
- * RETURN:      Status. AE_OK if conversion was successful.
- *
- * DESCRIPTION: Attempt to convert a String/Buffer object to an Integer.
- *
- ******************************************************************************/
-
-static acpi_status
-acpi_ns_convert_to_integer(union acpi_operand_object *original_object,
-			   union acpi_operand_object **return_object)
-{
-	union acpi_operand_object *new_object;
-	acpi_status status;
-	u64 value = 0;
-	u32 i;
-
-	switch (original_object->common.type) {
-	case ACPI_TYPE_STRING:
-
-		/* String-to-Integer conversion */
-
-		status = acpi_ut_strtoul64(original_object->string.pointer,
-					   ACPI_ANY_BASE, &value);
-		if (ACPI_FAILURE(status)) {
-			return (status);
-		}
-		break;
-
-	case ACPI_TYPE_BUFFER:
-
-		/* Buffer-to-Integer conversion. Max buffer size is 64 bits. */
-
-		if (original_object->buffer.length > 8) {
-			return (AE_AML_OPERAND_TYPE);
-		}
-
-		/* Extract each buffer byte to create the integer */
-
-		for (i = 0; i < original_object->buffer.length; i++) {
-			value |=
-			    ((u64) original_object->buffer.
-			     pointer[i] << (i * 8));
-		}
-		break;
-
-	default:
-		return (AE_AML_OPERAND_TYPE);
-	}
-
-	new_object = acpi_ut_create_integer_object(value);
-	if (!new_object) {
-		return (AE_NO_MEMORY);
-	}
-
-	*return_object = new_object;
-	return (AE_OK);
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ns_convert_to_string
- *
- * PARAMETERS:  original_object     - Object to be converted
- *              return_object       - Where the new converted object is returned
- *
- * RETURN:      Status. AE_OK if conversion was successful.
- *
- * DESCRIPTION: Attempt to convert a Integer/Buffer object to a String.
- *
- ******************************************************************************/
-
-static acpi_status
-acpi_ns_convert_to_string(union acpi_operand_object *original_object,
-			  union acpi_operand_object **return_object)
-{
-	union acpi_operand_object *new_object;
-	acpi_size length;
-	acpi_status status;
-
-	switch (original_object->common.type) {
-	case ACPI_TYPE_INTEGER:
-		/*
-		 * Integer-to-String conversion. Commonly, convert
-		 * an integer of value 0 to a NULL string. The last element of
-		 * _BIF and _BIX packages occasionally need this fix.
-		 */
-		if (original_object->integer.value == 0) {
-
-			/* Allocate a new NULL string object */
-
-			new_object = acpi_ut_create_string_object(0);
-			if (!new_object) {
-				return (AE_NO_MEMORY);
-			}
-		} else {
-			status =
-			    acpi_ex_convert_to_string(original_object,
-						      &new_object,
-						      ACPI_IMPLICIT_CONVERT_HEX);
-			if (ACPI_FAILURE(status)) {
-				return (status);
-			}
-		}
-		break;
-
-	case ACPI_TYPE_BUFFER:
-		/*
-		 * Buffer-to-String conversion. Use a to_string
-		 * conversion, no transform performed on the buffer data. The best
-		 * example of this is the _BIF method, where the string data from
-		 * the battery is often (incorrectly) returned as buffer object(s).
-		 */
-		length = 0;
-		while ((length < original_object->buffer.length) &&
-		       (original_object->buffer.pointer[length])) {
-			length++;
-		}
-
-		/* Allocate a new string object */
-
-		new_object = acpi_ut_create_string_object(length);
-		if (!new_object) {
-			return (AE_NO_MEMORY);
-		}
-
-		/*
-		 * Copy the raw buffer data with no transform. String is already NULL
-		 * terminated at Length+1.
-		 */
-		ACPI_MEMCPY(new_object->string.pointer,
-			    original_object->buffer.pointer, length);
-		break;
-
-	default:
-		return (AE_AML_OPERAND_TYPE);
-	}
-
-	*return_object = new_object;
-	return (AE_OK);
-}
-
-/*******************************************************************************
+/******************************************************************************
  *
- * FUNCTION:    acpi_ns_convert_to_buffer
+ * FUNCTION:    acpi_ns_match_simple_repair
  *
- * PARAMETERS:  original_object     - Object to be converted
- *              return_object       - Where the new converted object is returned
+ * PARAMETERS:  node                - Namespace node for the method/object
+ *              return_btype        - Object type that was returned
+ *              package_index       - Index of object within parent package (if
+ *                                    applicable - ACPI_NOT_PACKAGE_ELEMENT
+ *                                    otherwise)
  *
- * RETURN:      Status. AE_OK if conversion was successful.
+ * RETURN:      Pointer to entry in repair table. NULL indicates not found.
  *
- * DESCRIPTION: Attempt to convert a Integer/String/Package object to a Buffer.
+ * DESCRIPTION: Check an object name against the repairable object list.
  *
- ******************************************************************************/
+ *****************************************************************************/
 
-static acpi_status
-acpi_ns_convert_to_buffer(union acpi_operand_object *original_object,
-			  union acpi_operand_object **return_object)
+static const struct acpi_simple_repair_info *acpi_ns_match_simple_repair(struct
+									 acpi_namespace_node
+									 *node,
+									 u32
+									 return_btype,
+									 u32
+									 package_index)
 {
-	union acpi_operand_object *new_object;
-	acpi_status status;
-	union acpi_operand_object **elements;
-	u32 *dword_buffer;
-	u32 count;
-	u32 i;
+	const struct acpi_simple_repair_info *this_name;
 
-	switch (original_object->common.type) {
-	case ACPI_TYPE_INTEGER:
-		/*
-		 * Integer-to-Buffer conversion.
-		 * Convert the Integer to a packed-byte buffer. _MAT and other
-		 * objects need this sometimes, if a read has been performed on a
-		 * Field object that is less than or equal to the global integer
-		 * size (32 or 64 bits).
-		 */
-		status =
-		    acpi_ex_convert_to_buffer(original_object, &new_object);
-		if (ACPI_FAILURE(status)) {
-			return (status);
-		}
-		break;
+	/* Search info table for a repairable predefined method/object name */
 
-	case ACPI_TYPE_STRING:
+	this_name = acpi_object_repair_info;
+	while (this_name->object_converter) {
+		if (ACPI_COMPARE_NAME(node->name.ascii, this_name->name)) {
 
-		/* String-to-Buffer conversion. Simple data copy */
-
-		new_object =
-		    acpi_ut_create_buffer_object(original_object->string.
-						 length);
-		if (!new_object) {
-			return (AE_NO_MEMORY);
-		}
+			/* Check if we can actually repair this name/type combination */
 
-		ACPI_MEMCPY(new_object->buffer.pointer,
-			    original_object->string.pointer,
-			    original_object->string.length);
-		break;
-
-	case ACPI_TYPE_PACKAGE:
-		/*
-		 * This case is often seen for predefined names that must return a
-		 * Buffer object with multiple DWORD integers within. For example,
-		 * _FDE and _GTM. The Package can be converted to a Buffer.
-		 */
-
-		/* All elements of the Package must be integers */
-
-		elements = original_object->package.elements;
-		count = original_object->package.count;
-
-		for (i = 0; i < count; i++) {
-			if ((!*elements) ||
-			    ((*elements)->common.type != ACPI_TYPE_INTEGER)) {
-				return (AE_AML_OPERAND_TYPE);
+			if ((return_btype & this_name->unexpected_btypes) &&
+			    (package_index == this_name->package_index)) {
+				return (this_name);
 			}
-			elements++;
-		}
-
-		/* Create the new buffer object to replace the Package */
 
-		new_object = acpi_ut_create_buffer_object(ACPI_MUL_4(count));
-		if (!new_object) {
-			return (AE_NO_MEMORY);
+			return (NULL);
 		}
-
-		/* Copy the package elements (integers) to the buffer as DWORDs */
-
-		elements = original_object->package.elements;
-		dword_buffer = ACPI_CAST_PTR(u32, new_object->buffer.pointer);
-
-		for (i = 0; i < count; i++) {
-			*dword_buffer = (u32) (*elements)->integer.value;
-			dword_buffer++;
-			elements++;
-		}
-		break;
-
-	default:
-		return (AE_AML_OPERAND_TYPE);
+		this_name++;
 	}
 
-	*return_object = new_object;
-	return (AE_OK);
+	return (NULL);		/* Name was not found in the repair table */
 }
 
 /*******************************************************************************
diff --git a/drivers/acpi/acpica/nsrepair2.c b/drivers/acpi/acpica/nsrepair2.c
index ba4d982..149e9b9 100644
--- a/drivers/acpi/acpica/nsrepair2.c
+++ b/drivers/acpi/acpica/nsrepair2.c
@@ -66,9 +66,9 @@ typedef struct acpi_repair_info {
 
 /* Local prototypes */
 
-static const struct acpi_repair_info *acpi_ns_match_repairable_name(struct
-								    acpi_namespace_node
-								    *node);
+static const struct acpi_repair_info *acpi_ns_match_complex_repair(struct
+								   acpi_namespace_node
+								   *node);
 
 static acpi_status
 acpi_ns_repair_ALR(struct acpi_predefined_data *data,
@@ -175,7 +175,7 @@ acpi_ns_complex_repairs(struct acpi_predefined_data *data,
 
 	/* Check if this name is in the list of repairable names */
 
-	predefined = acpi_ns_match_repairable_name(node);
+	predefined = acpi_ns_match_complex_repair(node);
 	if (!predefined) {
 		return (validate_status);
 	}
@@ -186,7 +186,7 @@ acpi_ns_complex_repairs(struct acpi_predefined_data *data,
 
 /******************************************************************************
  *
- * FUNCTION:    acpi_ns_match_repairable_name
+ * FUNCTION:    acpi_ns_match_complex_repair
  *
  * PARAMETERS:  node                - Namespace node for the method/object
  *
@@ -196,9 +196,9 @@ acpi_ns_complex_repairs(struct acpi_predefined_data *data,
  *
  *****************************************************************************/
 
-static const struct acpi_repair_info *acpi_ns_match_repairable_name(struct
-								    acpi_namespace_node
-								    *node)
+static const struct acpi_repair_info *acpi_ns_match_complex_repair(struct
+								   acpi_namespace_node
+								   *node)
 {
 	const struct acpi_repair_info *this_name;
 
diff --git a/drivers/acpi/acpica/nsutils.c b/drivers/acpi/acpica/nsutils.c
index 686420d..2808586 100644
--- a/drivers/acpi/acpica/nsutils.c
+++ b/drivers/acpi/acpica/nsutils.c
@@ -112,10 +112,10 @@ acpi_object_type acpi_ns_get_type(struct acpi_namespace_node * node)
 
 	if (!node) {
 		ACPI_WARNING((AE_INFO, "Null Node parameter"));
-		return_VALUE(ACPI_TYPE_ANY);
+		return_UINT8(ACPI_TYPE_ANY);
 	}
 
-	return_VALUE(node->type);
+	return_UINT8(node->type);
 }
 
 /*******************************************************************************
@@ -140,10 +140,10 @@ u32 acpi_ns_local(acpi_object_type type)
 		/* Type code out of range  */
 
 		ACPI_WARNING((AE_INFO, "Invalid Object Type 0x%X", type));
-		return_VALUE(ACPI_NS_NORMAL);
+		return_UINT32(ACPI_NS_NORMAL);
 	}
 
-	return_VALUE(acpi_gbl_ns_properties[type] & ACPI_NS_LOCAL);
+	return_UINT32(acpi_gbl_ns_properties[type] & ACPI_NS_LOCAL);
 }
 
 /*******************************************************************************
diff --git a/drivers/acpi/acpica/psargs.c b/drivers/acpi/acpica/psargs.c
index f51308c..9f25a3d 100644
--- a/drivers/acpi/acpica/psargs.c
+++ b/drivers/acpi/acpica/psargs.c
@@ -108,7 +108,7 @@ acpi_ps_get_next_package_length(struct acpi_parse_state *parser_state)
 	/* Byte 0 is a special case, either bits [0:3] or [0:5] are used */
 
 	package_length |= (aml[0] & byte_zero_mask);
-	return_VALUE(package_length);
+	return_UINT32(package_length);
 }
 
 /*******************************************************************************
diff --git a/drivers/acpi/acpica/rscalc.c b/drivers/acpi/acpica/rscalc.c
index 7816d4ee..72077fa 100644
--- a/drivers/acpi/acpica/rscalc.c
+++ b/drivers/acpi/acpica/rscalc.c
@@ -202,6 +202,12 @@ acpi_rs_get_aml_length(struct acpi_resource * resource, acpi_size * size_needed)
 			return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE);
 		}
 
+		/* Sanity check the length. It must not be zero, or we loop forever */
+
+		if (!resource->length) {
+			return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH);
+		}
+
 		/* Get the base size of the (external stream) resource descriptor */
 
 		total_size = acpi_gbl_aml_resource_sizes[resource->type];
diff --git a/drivers/acpi/acpica/rsdump.c b/drivers/acpi/acpica/rsdump.c
index cab5144..b5fc0db 100644
--- a/drivers/acpi/acpica/rsdump.c
+++ b/drivers/acpi/acpica/rsdump.c
@@ -385,6 +385,14 @@ void acpi_rs_dump_resource_list(struct acpi_resource *resource_list)
 			return;
 		}
 
+		/* Sanity check the length. It must not be zero, or we loop forever */
+
+		if (!resource_list->length) {
+			acpi_os_printf
+			    ("Invalid zero length descriptor in resource list\n");
+			return;
+		}
+
 		/* Dump the resource descriptor */
 
 		if (type == ACPI_RESOURCE_TYPE_SERIAL_BUS) {
diff --git a/drivers/acpi/acpica/rslist.c b/drivers/acpi/acpica/rslist.c
index ee2e206..6053aa1 100644
--- a/drivers/acpi/acpica/rslist.c
+++ b/drivers/acpi/acpica/rslist.c
@@ -178,6 +178,14 @@ acpi_rs_convert_resources_to_aml(struct acpi_resource *resource,
 			return_ACPI_STATUS(AE_BAD_DATA);
 		}
 
+		/* Sanity check the length. It must not be zero, or we loop forever */
+
+		if (!resource->length) {
+			ACPI_ERROR((AE_INFO,
+				    "Invalid zero length descriptor in resource list\n"));
+			return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH);
+		}
+
 		/* Perform the conversion */
 
 		if (resource->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) {
diff --git a/drivers/acpi/acpica/rsxface.c b/drivers/acpi/acpica/rsxface.c
index 15d6eae..c0e5d2d 100644
--- a/drivers/acpi/acpica/rsxface.c
+++ b/drivers/acpi/acpica/rsxface.c
@@ -563,13 +563,19 @@ acpi_walk_resource_buffer(struct acpi_buffer * buffer,
 
 	while (resource < resource_end) {
 
-		/* Sanity check the resource */
+		/* Sanity check the resource type */
 
 		if (resource->type > ACPI_RESOURCE_TYPE_MAX) {
 			status = AE_AML_INVALID_RESOURCE_TYPE;
 			break;
 		}
 
+		/* Sanity check the length. It must not be zero, or we loop forever */
+
+		if (!resource->length) {
+			return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH);
+		}
+
 		/* Invoke the user function, abort on any error returned */
 
 		status = user_function(resource, context);
diff --git a/drivers/acpi/acpica/utaddress.c b/drivers/acpi/acpica/utaddress.c
index 698b9d3..e0a2e27 100644
--- a/drivers/acpi/acpica/utaddress.c
+++ b/drivers/acpi/acpica/utaddress.c
@@ -214,7 +214,7 @@ acpi_ut_check_address_range(acpi_adr_space_type space_id,
 
 	if ((space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) &&
 	    (space_id != ACPI_ADR_SPACE_SYSTEM_IO)) {
-		return_VALUE(0);
+		return_UINT32(0);
 	}
 
 	range_info = acpi_gbl_address_range_list[space_id];
@@ -256,7 +256,7 @@ acpi_ut_check_address_range(acpi_adr_space_type space_id,
 		range_info = range_info->next;
 	}
 
-	return_VALUE(overlap_count);
+	return_UINT32(overlap_count);
 }
 
 /*******************************************************************************
diff --git a/drivers/acpi/acpica/utcache.c b/drivers/acpi/acpica/utcache.c
index e0e8579..a877a96 100644
--- a/drivers/acpi/acpica/utcache.c
+++ b/drivers/acpi/acpica/utcache.c
@@ -85,7 +85,6 @@ acpi_os_create_cache(char *cache_name,
 	/* Populate the cache object and return it */
 
 	ACPI_MEMSET(cache, 0, sizeof(struct acpi_memory_list));
-	cache->link_offset = 8;
 	cache->list_name = cache_name;
 	cache->object_size = object_size;
 	cache->max_depth = max_depth;
@@ -108,7 +107,7 @@ acpi_os_create_cache(char *cache_name,
 
 acpi_status acpi_os_purge_cache(struct acpi_memory_list * cache)
 {
-	char *next;
+	void *next;
 	acpi_status status;
 
 	ACPI_FUNCTION_ENTRY();
@@ -128,10 +127,7 @@ acpi_status acpi_os_purge_cache(struct acpi_memory_list * cache)
 
 		/* Delete and unlink one cached state object */
 
-		next = *(ACPI_CAST_INDIRECT_PTR(char,
-						&(((char *)cache->
-						   list_head)[cache->
-							      link_offset])));
+		next = ACPI_GET_DESCRIPTOR_PTR(cache->list_head);
 		ACPI_FREE(cache->list_head);
 
 		cache->list_head = next;
@@ -221,10 +217,7 @@ acpi_os_release_object(struct acpi_memory_list * cache, void *object)
 
 		/* Put the object at the head of the cache list */
 
-		*(ACPI_CAST_INDIRECT_PTR(char,
-					 &(((char *)object)[cache->
-							    link_offset]))) =
-		    cache->list_head;
+		ACPI_SET_DESCRIPTOR_PTR(object, cache->list_head);
 		cache->list_head = object;
 		cache->current_depth++;
 
@@ -272,10 +265,7 @@ void *acpi_os_acquire_object(struct acpi_memory_list *cache)
 		/* There is an object available, use it */
 
 		object = cache->list_head;
-		cache->list_head = *(ACPI_CAST_INDIRECT_PTR(char,
-							    &(((char *)
-							       object)[cache->
-								       link_offset])));
+		cache->list_head = ACPI_GET_DESCRIPTOR_PTR(object);
 
 		cache->current_depth--;
 
diff --git a/drivers/acpi/acpica/utexcep.c b/drivers/acpi/acpica/utexcep.c
index a0ab7c0..b543a14 100644
--- a/drivers/acpi/acpica/utexcep.c
+++ b/drivers/acpi/acpica/utexcep.c
@@ -64,7 +64,7 @@ ACPI_MODULE_NAME("utexcep")
  ******************************************************************************/
 const char *acpi_format_exception(acpi_status status)
 {
-	const char *exception = NULL;
+	const struct acpi_exception_info *exception;
 
 	ACPI_FUNCTION_ENTRY();
 
@@ -76,10 +76,10 @@ const char *acpi_format_exception(acpi_status status)
 		ACPI_ERROR((AE_INFO,
 			    "Unknown exception code: 0x%8.8X", status));
 
-		exception = "UNKNOWN_STATUS_CODE";
+		return ("UNKNOWN_STATUS_CODE");
 	}
 
-	return (ACPI_CAST_PTR(const char, exception));
+	return (exception->name);
 }
 
 ACPI_EXPORT_SYMBOL(acpi_format_exception)
@@ -97,10 +97,10 @@ ACPI_EXPORT_SYMBOL(acpi_format_exception)
  *              an ASCII string.
  *
  ******************************************************************************/
-const char *acpi_ut_validate_exception(acpi_status status)
+const struct acpi_exception_info *acpi_ut_validate_exception(acpi_status status)
 {
 	u32 sub_status;
-	const char *exception = NULL;
+	const struct acpi_exception_info *exception = NULL;
 
 	ACPI_FUNCTION_ENTRY();
 
@@ -113,35 +113,35 @@ const char *acpi_ut_validate_exception(acpi_status status)
 	case AE_CODE_ENVIRONMENTAL:
 
 		if (sub_status <= AE_CODE_ENV_MAX) {
-			exception = acpi_gbl_exception_names_env[sub_status];
+			exception = &acpi_gbl_exception_names_env[sub_status];
 		}
 		break;
 
 	case AE_CODE_PROGRAMMER:
 
 		if (sub_status <= AE_CODE_PGM_MAX) {
-			exception = acpi_gbl_exception_names_pgm[sub_status];
+			exception = &acpi_gbl_exception_names_pgm[sub_status];
 		}
 		break;
 
 	case AE_CODE_ACPI_TABLES:
 
 		if (sub_status <= AE_CODE_TBL_MAX) {
-			exception = acpi_gbl_exception_names_tbl[sub_status];
+			exception = &acpi_gbl_exception_names_tbl[sub_status];
 		}
 		break;
 
 	case AE_CODE_AML:
 
 		if (sub_status <= AE_CODE_AML_MAX) {
-			exception = acpi_gbl_exception_names_aml[sub_status];
+			exception = &acpi_gbl_exception_names_aml[sub_status];
 		}
 		break;
 
 	case AE_CODE_CONTROL:
 
 		if (sub_status <= AE_CODE_CTRL_MAX) {
-			exception = acpi_gbl_exception_names_ctrl[sub_status];
+			exception = &acpi_gbl_exception_names_ctrl[sub_status];
 		}
 		break;
 
@@ -149,5 +149,9 @@ const char *acpi_ut_validate_exception(acpi_status status)
 		break;
 	}
 
-	return (ACPI_CAST_PTR(const char, exception));
+	if (!exception || !exception->name) {
+		return (NULL);
+	}
+
+	return (exception);
 }
diff --git a/drivers/acpi/acpica/utglobal.c b/drivers/acpi/acpica/utglobal.c
index ffecf4b..f736448 100644
--- a/drivers/acpi/acpica/utglobal.c
+++ b/drivers/acpi/acpica/utglobal.c
@@ -359,6 +359,8 @@ acpi_status acpi_ut_init_globals(void)
 
 #ifdef ACPI_DISASSEMBLER
 	acpi_gbl_external_list = NULL;
+	acpi_gbl_num_external_methods = 0;
+	acpi_gbl_resolved_external_methods = 0;
 #endif
 
 #ifdef ACPI_DEBUG_OUTPUT
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index c5cd5b5..e710045 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -146,7 +146,7 @@ struct acpi_battery {
 
 #define to_acpi_battery(x) container_of(x, struct acpi_battery, bat)
 
-inline int acpi_battery_present(struct acpi_battery *battery)
+static inline int acpi_battery_present(struct acpi_battery *battery)
 {
 	return battery->device->status.battery_present;
 }
@@ -929,7 +929,7 @@ static int acpi_battery_read_##_name(struct seq_file *seq, void *offset) \
 } \
 static int acpi_battery_##_name##_open_fs(struct inode *inode, struct file *file) \
 { \
-	return single_open(file, acpi_battery_read_##_name, PDE(inode)->data); \
+	return single_open(file, acpi_battery_read_##_name, PDE_DATA(inode)); \
 }
 
 DECLARE_FILE_FUNCTIONS(info);
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 01708a1..292de3c 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -288,13 +288,12 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context)
 	}
 out_success:
 	context->ret.length = out_obj->buffer.length;
-	context->ret.pointer = kmalloc(context->ret.length, GFP_KERNEL);
+	context->ret.pointer = kmemdup(out_obj->buffer.pointer,
+				       context->ret.length, GFP_KERNEL);
 	if (!context->ret.pointer) {
 		status =  AE_NO_MEMORY;
 		goto out_kfree;
 	}
-	memcpy(context->ret.pointer, out_obj->buffer.pointer,
-		context->ret.length);
 	status =  AE_OK;
 
 out_kfree:
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index 86c7d54..d2e617b 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -33,6 +33,7 @@
 #include <linux/slab.h>
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
+#include <acpi/button.h>
 
 #define PREFIX "ACPI: "
 
@@ -128,7 +129,7 @@ static int acpi_button_state_seq_show(struct seq_file *seq, void *offset)
 
 static int acpi_button_state_open_fs(struct inode *inode, struct file *file)
 {
-	return single_open(file, acpi_button_state_seq_show, PDE(inode)->data);
+	return single_open(file, acpi_button_state_seq_show, PDE_DATA(inode));
 }
 
 static const struct file_operations acpi_button_state_fops = {
diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c
index 5523ba7..e231516 100644
--- a/drivers/acpi/container.c
+++ b/drivers/acpi/container.c
@@ -1,12 +1,12 @@
 /*
- * acpi_container.c  - ACPI Generic Container Driver
- * ($Revision: )
+ * container.c  - ACPI Generic Container Driver
  *
  * Copyright (C) 2004 Anil S Keshavamurthy (anil.s.keshavamurthy@intel.com)
  * Copyright (C) 2004 Keiichiro Tokunaga (tokunaga.keiich@jp.fujitsu.com)
  * Copyright (C) 2004 Motoyuki Ito (motoyuki@soft.fujitsu.com)
- * Copyright (C) 2004 Intel Corp.
  * Copyright (C) 2004 FUJITSU LIMITED
+ * Copyright (C) 2004, 2013 Intel Corp.
+ * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
  *
  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  *
@@ -26,14 +26,11 @@
  *
  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  */
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/types.h>
 #include <linux/acpi.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
+
+#include "internal.h"
+
+#include "internal.h"
 
 #define PREFIX "ACPI: "
 
@@ -50,141 +47,20 @@ static const struct acpi_device_id container_device_ids[] = {
 static int container_device_attach(struct acpi_device *device,
 				   const struct acpi_device_id *not_used)
 {
-	/*
-	 * FIXME: This is necessary, so that acpi_eject_store() doesn't return
-	 * -ENODEV for containers.
-	 */
+	/* This is necessary for container hotplug to work. */
 	return 1;
 }
 
-static struct acpi_scan_handler container_device_handler = {
+static struct acpi_scan_handler container_handler = {
 	.ids = container_device_ids,
 	.attach = container_device_attach,
+	.hotplug = {
+		.enabled = true,
+		.mode = AHM_CONTAINER,
+	},
 };
 
-static int is_device_present(acpi_handle handle)
-{
-	acpi_handle temp;
-	acpi_status status;
-	unsigned long long sta;
-
-
-	status = acpi_get_handle(handle, "_STA", &temp);
-	if (ACPI_FAILURE(status))
-		return 1;	/* _STA not found, assume device present */
-
-	status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
-	if (ACPI_FAILURE(status))
-		return 0;	/* Firmware error */
-
-	return ((sta & ACPI_STA_DEVICE_PRESENT) == ACPI_STA_DEVICE_PRESENT);
-}
-
-static void container_notify_cb(acpi_handle handle, u32 type, void *context)
-{
-	struct acpi_device *device = NULL;
-	int result;
-	int present;
-	acpi_status status;
-	u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */
-
-	acpi_scan_lock_acquire();
-
-	switch (type) {
-	case ACPI_NOTIFY_BUS_CHECK:
-		/* Fall through */
-	case ACPI_NOTIFY_DEVICE_CHECK:
-		pr_debug("Container driver received %s event\n",
-		       (type == ACPI_NOTIFY_BUS_CHECK) ?
-		       "ACPI_NOTIFY_BUS_CHECK" : "ACPI_NOTIFY_DEVICE_CHECK");
-
-		present = is_device_present(handle);
-		status = acpi_bus_get_device(handle, &device);
-		if (!present) {
-			if (ACPI_SUCCESS(status)) {
-				/* device exist and this is a remove request */
-				device->flags.eject_pending = 1;
-				kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE);
-				goto out;
-			}
-			break;
-		}
-
-		if (!ACPI_FAILURE(status) || device)
-			break;
-
-		result = acpi_bus_scan(handle);
-		if (result) {
-			acpi_handle_warn(handle, "Failed to add container\n");
-			break;
-		}
-		result = acpi_bus_get_device(handle, &device);
-		if (result) {
-			acpi_handle_warn(handle, "Missing device object\n");
-			break;
-		}
-
-		kobject_uevent(&device->dev.kobj, KOBJ_ONLINE);
-		ost_code = ACPI_OST_SC_SUCCESS;
-		break;
-
-	case ACPI_NOTIFY_EJECT_REQUEST:
-		if (!acpi_bus_get_device(handle, &device) && device) {
-			device->flags.eject_pending = 1;
-			kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE);
-			goto out;
-		}
-		break;
-
-	default:
-		/* non-hotplug event; possibly handled by other handler */
-		goto out;
-	}
-
-	/* Inform firmware that the hotplug operation has completed */
-	(void) acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
-
- out:
-	acpi_scan_lock_release();
-}
-
-static bool is_container(acpi_handle handle)
-{
-	struct acpi_device_info *info;
-	bool ret = false;
-
-	if (ACPI_FAILURE(acpi_get_object_info(handle, &info)))
-		return false;
-
-	if (info->valid & ACPI_VALID_HID) {
-		const struct acpi_device_id *id;
-
-		for (id = container_device_ids; id->id[0]; id++) {
-			ret = !strcmp((char *)id->id, info->hardware_id.string);
-			if (ret)
-				break;
-		}
-	}
-	kfree(info);
-	return ret;
-}
-
-static acpi_status acpi_container_register_notify_handler(acpi_handle handle,
-							  u32 lvl, void *ctxt,
-							  void **retv)
-{
-	if (is_container(handle))
-		acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
-					    container_notify_cb, NULL);
-
-	return AE_OK;
-}
-
 void __init acpi_container_init(void)
 {
-	acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
-			    acpi_container_register_notify_handler, NULL,
-			    NULL, NULL);
-
-	acpi_scan_add_handler(&container_device_handler);
+	acpi_scan_add_handler_with_hotplug(&container_handler, "container");
 }
diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c
index dd314ef..96de787 100644
--- a/drivers/acpi/device_pm.c
+++ b/drivers/acpi/device_pm.c
@@ -145,27 +145,36 @@ int acpi_device_get_power(struct acpi_device *device, int *state)
 	}
 
 	/*
-	 * Get the device's power state either directly (via _PSC) or
-	 * indirectly (via power resources).
+	 * Get the device's power state from power resources settings and _PSC,
+	 * if available.
 	 */
+	if (device->power.flags.power_resources) {
+		int error = acpi_power_get_inferred_state(device, &result);
+		if (error)
+			return error;
+	}
 	if (device->power.flags.explicit_get) {
+		acpi_handle handle = device->handle;
 		unsigned long long psc;
-		acpi_status status = acpi_evaluate_integer(device->handle,
-							   "_PSC", NULL, &psc);
+		acpi_status status;
+
+		status = acpi_evaluate_integer(handle, "_PSC", NULL, &psc);
 		if (ACPI_FAILURE(status))
 			return -ENODEV;
 
-		result = psc;
-	}
-	/* The test below covers ACPI_STATE_UNKNOWN too. */
-	if (result <= ACPI_STATE_D2) {
-	  ; /* Do nothing. */
-	} else if (device->power.flags.power_resources) {
-		int error = acpi_power_get_inferred_state(device, &result);
-		if (error)
-			return error;
-	} else if (result == ACPI_STATE_D3_HOT) {
-		result = ACPI_STATE_D3;
+		/*
+		 * The power resources settings may indicate a power state
+		 * shallower than the actual power state of the device.
+		 *
+		 * Moreover, on systems predating ACPI 4.0, if the device
+		 * doesn't depend on any power resources and _PSC returns 3,
+		 * that means "power off".  We need to maintain compatibility
+		 * with those systems.
+		 */
+		if (psc > result && psc < ACPI_STATE_D3_COLD)
+			result = psc;
+		else if (result == ACPI_STATE_UNKNOWN)
+			result = psc > ACPI_STATE_D2 ? ACPI_STATE_D3_COLD : psc;
 	}
 
 	/*
diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c
index f815da8..8d1c010 100644
--- a/drivers/acpi/fan.c
+++ b/drivers/acpi/fan.c
@@ -174,9 +174,13 @@ static int acpi_fan_add(struct acpi_device *device)
 
 static int acpi_fan_remove(struct acpi_device *device)
 {
-	struct thermal_cooling_device *cdev = acpi_driver_data(device);
+	struct thermal_cooling_device *cdev;
+
+	if (!device)
+		return -EINVAL;
 
-	if (!device || !cdev)
+	cdev =  acpi_driver_data(device);
+	if (!cdev)
 		return -EINVAL;
 
 	sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
index 3c94a73..6f1afd9 100644
--- a/drivers/acpi/internal.h
+++ b/drivers/acpi/internal.h
@@ -41,6 +41,17 @@ void acpi_container_init(void);
 #else
 static inline void acpi_container_init(void) {}
 #endif
+#ifdef CONFIG_ACPI_HOTPLUG_MEMORY
+void acpi_memory_hotplug_init(void);
+#else
+static inline void acpi_memory_hotplug_init(void) {}
+#endif
+
+void acpi_sysfs_add_hotplug_profile(struct acpi_hotplug_profile *hotplug,
+				    const char *name);
+int acpi_scan_add_handler_with_hotplug(struct acpi_scan_handler *handler,
+				       const char *hotplug_profile_name);
+void acpi_scan_hotplug_enabled(struct acpi_hotplug_profile *hotplug, bool val);
 
 #ifdef CONFIG_DEBUG_FS
 extern struct dentry *acpi_debugfs_dir;
@@ -48,6 +59,11 @@ int acpi_debugfs_init(void);
 #else
 static inline void acpi_debugfs_init(void) { return; }
 #endif
+#ifdef CONFIG_X86_INTEL_LPSS
+void acpi_lpss_init(void);
+#else
+static inline void acpi_lpss_init(void) {}
+#endif
 
 /* --------------------------------------------------------------------------
                      Device Node Initialization / Removal
@@ -60,7 +76,7 @@ int acpi_device_add(struct acpi_device *device,
 void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
 			     int type, unsigned long long sta);
 void acpi_device_add_finalize(struct acpi_device *device);
-void acpi_free_ids(struct acpi_device *device);
+void acpi_free_pnp_ids(struct acpi_device_pnp *pnp);
 
 /* --------------------------------------------------------------------------
                                   Power Resource
@@ -131,4 +147,7 @@ static inline void suspend_nvs_restore(void) {}
   -------------------------------------------------------------------------- */
 struct platform_device;
 
+int acpi_create_platform_device(struct acpi_device *adev,
+				const struct acpi_device_id *id);
+
 #endif /* _ACPI_INTERNAL_H_ */
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 586e7e9..4d31748 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -1555,7 +1555,7 @@ int acpi_check_resource_conflict(const struct resource *res)
 	else
 		space_id = ACPI_ADR_SPACE_SYSTEM_MEMORY;
 
-	length = res->end - res->start + 1;
+	length = resource_size(res);
 	if (acpi_enforce_resources != ENFORCE_RESOURCES_NO)
 		warn = 1;
 	clash = acpi_check_address_range(space_id, res->start, length, warn);
diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c
index ab764ed..2652a61 100644
--- a/drivers/acpi/pci_link.c
+++ b/drivers/acpi/pci_link.c
@@ -354,6 +354,7 @@ static int acpi_pci_link_set(struct acpi_pci_link *link, int irq)
 
 	}
 	resource->end.type = ACPI_RESOURCE_TYPE_END_TAG;
+	resource->end.length = sizeof(struct acpi_resource);
 
 	/* Attempt to set the resource */
 	status = acpi_set_current_resources(link->device->handle, &buffer);
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 5ff1730..4241b8d 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -201,8 +201,8 @@ static acpi_status acpi_pci_query_osc(struct acpi_pci_root *root,
 		*control &= OSC_PCI_CONTROL_MASKS;
 		capbuf[OSC_CONTROL_TYPE] = *control | root->osc_control_set;
 	} else {
-		/* Run _OSC query for all possible controls. */
-		capbuf[OSC_CONTROL_TYPE] = OSC_PCI_CONTROL_MASKS;
+		/* Run _OSC query only with existing controls. */
+		capbuf[OSC_CONTROL_TYPE] = root->osc_control_set;
 	}
 
 	status = acpi_pci_run_osc(root->device->handle, capbuf, &result);
@@ -415,7 +415,6 @@ static int acpi_pci_root_add(struct acpi_device *device,
 	struct acpi_pci_root *root;
 	struct acpi_pci_driver *driver;
 	u32 flags, base_flags;
-	bool is_osc_granted = false;
 
 	root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL);
 	if (!root)
@@ -476,6 +475,30 @@ static int acpi_pci_root_add(struct acpi_device *device,
 	flags = base_flags = OSC_PCI_SEGMENT_GROUPS_SUPPORT;
 	acpi_pci_osc_support(root, flags);
 
+	/*
+	 * TBD: Need PCI interface for enumeration/configuration of roots.
+	 */
+
+	mutex_lock(&acpi_pci_root_lock);
+	list_add_tail(&root->node, &acpi_pci_roots);
+	mutex_unlock(&acpi_pci_root_lock);
+
+	/*
+	 * Scan the Root Bridge
+	 * --------------------
+	 * Must do this prior to any attempt to bind the root device, as the
+	 * PCI namespace does not get created until this call is made (and
+	 * thus the root bridge's pci_dev does not exist).
+	 */
+	root->bus = pci_acpi_scan_root(root);
+	if (!root->bus) {
+		printk(KERN_ERR PREFIX
+			    "Bus %04x:%02x not present in PCI namespace\n",
+			    root->segment, (unsigned int)root->secondary.start);
+		result = -ENODEV;
+		goto out_del_root;
+	}
+
 	/* Indicate support for various _OSC capabilities. */
 	if (pci_ext_cfg_avail())
 		flags |= OSC_EXT_PCI_CONFIG_SUPPORT;
@@ -494,6 +517,7 @@ static int acpi_pci_root_add(struct acpi_device *device,
 			flags = base_flags;
 		}
 	}
+
 	if (!pcie_ports_disabled
 	    && (flags & ACPI_PCIE_REQ_SUPPORT) == ACPI_PCIE_REQ_SUPPORT) {
 		flags = OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL
@@ -514,54 +538,28 @@ static int acpi_pci_root_add(struct acpi_device *device,
 		status = acpi_pci_osc_control_set(device->handle, &flags,
 				       OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
 		if (ACPI_SUCCESS(status)) {
-			is_osc_granted = true;
 			dev_info(&device->dev,
 				"ACPI _OSC control (0x%02x) granted\n", flags);
+			if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) {
+				/*
+				 * We have ASPM control, but the FADT indicates
+				 * that it's unsupported. Clear it.
+				 */
+				pcie_clear_aspm(root->bus);
+			}
 		} else {
-			is_osc_granted = false;
 			dev_info(&device->dev,
 				"ACPI _OSC request failed (%s), "
 				"returned control mask: 0x%02x\n",
 				acpi_format_exception(status), flags);
+			pr_info("ACPI _OSC control for PCIe not granted, "
+				"disabling ASPM\n");
+			pcie_no_aspm();
 		}
 	} else {
 		dev_info(&device->dev,
-			"Unable to request _OSC control "
-			"(_OSC support mask: 0x%02x)\n", flags);
-	}
-
-	/*
-	 * TBD: Need PCI interface for enumeration/configuration of roots.
-	 */
-
-	mutex_lock(&acpi_pci_root_lock);
-	list_add_tail(&root->node, &acpi_pci_roots);
-	mutex_unlock(&acpi_pci_root_lock);
-
-	/*
-	 * Scan the Root Bridge
-	 * --------------------
-	 * Must do this prior to any attempt to bind the root device, as the
-	 * PCI namespace does not get created until this call is made (and 
-	 * thus the root bridge's pci_dev does not exist).
-	 */
-	root->bus = pci_acpi_scan_root(root);
-	if (!root->bus) {
-		printk(KERN_ERR PREFIX
-			    "Bus %04x:%02x not present in PCI namespace\n",
-			    root->segment, (unsigned int)root->secondary.start);
-		result = -ENODEV;
-		goto out_del_root;
-	}
-
-	/* ASPM setting */
-	if (is_osc_granted) {
-		if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM)
-			pcie_clear_aspm(root->bus);
-	} else {
-		pr_info("ACPI _OSC control for PCIe not granted, "
-			"disabling ASPM\n");
-		pcie_no_aspm();
+			 "Unable to request _OSC control "
+			 "(_OSC support mask: 0x%02x)\n", flags);
 	}
 
 	pci_acpi_add_bus_pm_notifier(device, root->bus);
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index 34f5ef1..0481b1b 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -824,7 +824,7 @@ static void acpi_release_power_resource(struct device *dev)
 	list_del(&resource->list_node);
 	mutex_unlock(&power_resource_list_lock);
 
-	acpi_free_ids(device);
+	acpi_free_pnp_ids(&device->pnp);
 	kfree(resource);
 }
 
diff --git a/drivers/acpi/proc.c b/drivers/acpi/proc.c
index 52ce767..aa1227a 100644
--- a/drivers/acpi/proc.c
+++ b/drivers/acpi/proc.c
@@ -120,7 +120,7 @@ static int acpi_system_alarm_seq_show(struct seq_file *seq, void *offset)
 
 static int acpi_system_alarm_open_fs(struct inode *inode, struct file *file)
 {
-	return single_open(file, acpi_system_alarm_seq_show, PDE(inode)->data);
+	return single_open(file, acpi_system_alarm_seq_show, PDE_DATA(inode));
 }
 
 static int get_date_field(char **p, u32 * value)
@@ -397,7 +397,7 @@ static int
 acpi_system_wakeup_device_open_fs(struct inode *inode, struct file *file)
 {
 	return single_open(file, acpi_system_wakeup_device_seq_show,
-			   PDE(inode)->data);
+			   PDE_DATA(inode));
 }
 
 static const struct file_operations acpi_system_wakeup_device_fops = {
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index fc95308..ee255c6 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -66,7 +66,8 @@ module_param(latency_factor, uint, 0644);
 
 static DEFINE_PER_CPU(struct cpuidle_device *, acpi_cpuidle_device);
 
-static struct acpi_processor_cx *acpi_cstate[CPUIDLE_STATE_MAX];
+static DEFINE_PER_CPU(struct acpi_processor_cx * [CPUIDLE_STATE_MAX],
+								acpi_cstate);
 
 static int disabled_by_idle_boot_param(void)
 {
@@ -722,7 +723,7 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev,
 		struct cpuidle_driver *drv, int index)
 {
 	struct acpi_processor *pr;
-	struct acpi_processor_cx *cx = acpi_cstate[index];
+	struct acpi_processor_cx *cx = per_cpu(acpi_cstate[index], dev->cpu);
 
 	pr = __this_cpu_read(processors);
 
@@ -745,7 +746,7 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev,
  */
 static int acpi_idle_play_dead(struct cpuidle_device *dev, int index)
 {
-	struct acpi_processor_cx *cx = acpi_cstate[index];
+	struct acpi_processor_cx *cx = per_cpu(acpi_cstate[index], dev->cpu);
 
 	ACPI_FLUSH_CPU_CACHE();
 
@@ -775,7 +776,7 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
 		struct cpuidle_driver *drv, int index)
 {
 	struct acpi_processor *pr;
-	struct acpi_processor_cx *cx = acpi_cstate[index];
+	struct acpi_processor_cx *cx = per_cpu(acpi_cstate[index], dev->cpu);
 
 	pr = __this_cpu_read(processors);
 
@@ -833,7 +834,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
 		struct cpuidle_driver *drv, int index)
 {
 	struct acpi_processor *pr;
-	struct acpi_processor_cx *cx = acpi_cstate[index];
+	struct acpi_processor_cx *cx = per_cpu(acpi_cstate[index], dev->cpu);
 
 	pr = __this_cpu_read(processors);
 
@@ -960,7 +961,7 @@ static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr,
 		    !(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED))
 			continue;
 #endif
-		acpi_cstate[count] = cx;
+		per_cpu(acpi_cstate[count], dev->cpu) = cx;
 
 		count++;
 		if (count == CPUIDLE_STATE_MAX)
diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c
index 641b545..e8e6527 100644
--- a/drivers/acpi/processor_thermal.c
+++ b/drivers/acpi/processor_thermal.c
@@ -218,9 +218,13 @@ processor_get_max_state(struct thermal_cooling_device *cdev,
 			unsigned long *state)
 {
 	struct acpi_device *device = cdev->devdata;
-	struct acpi_processor *pr = acpi_driver_data(device);
+	struct acpi_processor *pr;
 
-	if (!device || !pr)
+	if (!device)
+		return -EINVAL;
+
+	pr = acpi_driver_data(device);
+	if (!pr)
 		return -EINVAL;
 
 	*state = acpi_processor_max_state(pr);
@@ -232,9 +236,13 @@ processor_get_cur_state(struct thermal_cooling_device *cdev,
 			unsigned long *cur_state)
 {
 	struct acpi_device *device = cdev->devdata;
-	struct acpi_processor *pr = acpi_driver_data(device);
+	struct acpi_processor *pr;
 
-	if (!device || !pr)
+	if (!device)
+		return -EINVAL;
+
+	pr = acpi_driver_data(device);
+	if (!pr)
 		return -EINVAL;
 
 	*cur_state = cpufreq_get_cur_state(pr->id);
@@ -248,11 +256,15 @@ processor_set_cur_state(struct thermal_cooling_device *cdev,
 			unsigned long state)
 {
 	struct acpi_device *device = cdev->devdata;
-	struct acpi_processor *pr = acpi_driver_data(device);
+	struct acpi_processor *pr;
 	int result = 0;
 	int max_pstate;
 
-	if (!device || !pr)
+	if (!device)
+		return -EINVAL;
+
+	pr = acpi_driver_data(device);
+	if (!pr)
 		return -EINVAL;
 
 	max_pstate = cpufreq_get_max_state(pr->id);
diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c
index 1d02b7b..e7dd2c1 100644
--- a/drivers/acpi/processor_throttling.c
+++ b/drivers/acpi/processor_throttling.c
@@ -211,9 +211,10 @@ err_ret:
  */
 void acpi_processor_throttling_init(void)
 {
-	if (acpi_processor_update_tsd_coord())
+	if (acpi_processor_update_tsd_coord()) {
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
 			"Assume no T-state coordination\n"));
+	}
 
 	return;
 }
diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c
index e523245..a296e08 100644
--- a/drivers/acpi/sbs.c
+++ b/drivers/acpi/sbs.c
@@ -584,7 +584,7 @@ static int acpi_battery_read_info(struct seq_file *seq, void *offset)
 
 static int acpi_battery_info_open_fs(struct inode *inode, struct file *file)
 {
-	return single_open(file, acpi_battery_read_info, PDE(inode)->data);
+	return single_open(file, acpi_battery_read_info, PDE_DATA(inode));
 }
 
 static int acpi_battery_read_state(struct seq_file *seq, void *offset)
@@ -623,7 +623,7 @@ static int acpi_battery_read_state(struct seq_file *seq, void *offset)
 
 static int acpi_battery_state_open_fs(struct inode *inode, struct file *file)
 {
-	return single_open(file, acpi_battery_read_state, PDE(inode)->data);
+	return single_open(file, acpi_battery_read_state, PDE_DATA(inode));
 }
 
 static int acpi_battery_read_alarm(struct seq_file *seq, void *offset)
@@ -688,7 +688,7 @@ acpi_battery_write_alarm(struct file *file, const char __user * buffer,
 
 static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file)
 {
-	return single_open(file, acpi_battery_read_alarm, PDE(inode)->data);
+	return single_open(file, acpi_battery_read_alarm, PDE_DATA(inode));
 }
 
 static const struct file_operations acpi_battery_info_fops = {
@@ -736,7 +736,7 @@ static int acpi_ac_read_state(struct seq_file *seq, void *offset)
 
 static int acpi_ac_state_open_fs(struct inode *inode, struct file *file)
 {
-	return single_open(file, acpi_ac_read_state, PDE(inode)->data);
+	return single_open(file, acpi_ac_read_state, PDE_DATA(inode));
 }
 
 static const struct file_operations acpi_ac_state_fops = {
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 5e7e991..d7f3c8b 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -63,6 +63,19 @@ int acpi_scan_add_handler(struct acpi_scan_handler *handler)
 	return 0;
 }
 
+int acpi_scan_add_handler_with_hotplug(struct acpi_scan_handler *handler,
+				       const char *hotplug_profile_name)
+{
+	int error;
+
+	error = acpi_scan_add_handler(handler);
+	if (error)
+		return error;
+
+	acpi_sysfs_add_hotplug_profile(&handler->hotplug, hotplug_profile_name);
+	return 0;
+}
+
 /*
  * Creates hid/cid(s) string needed for modalias and uevent
  * e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get:
@@ -107,32 +120,20 @@ acpi_device_modalias_show(struct device *dev, struct device_attribute *attr, cha
 }
 static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL);
 
-/**
- * acpi_bus_hot_remove_device: hot-remove a device and its children
- * @context: struct acpi_eject_event pointer (freed in this func)
- *
- * Hot-remove a device and its children. This function frees up the
- * memory space passed by arg context, so that the caller may call
- * this function asynchronously through acpi_os_hotplug_execute().
- */
-void acpi_bus_hot_remove_device(void *context)
+static int acpi_scan_hot_remove(struct acpi_device *device)
 {
-	struct acpi_eject_event *ej_event = context;
-	struct acpi_device *device = ej_event->device;
 	acpi_handle handle = device->handle;
-	acpi_handle temp;
+	acpi_handle not_used;
 	struct acpi_object_list arg_list;
 	union acpi_object arg;
-	acpi_status status = AE_OK;
-	u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */
-
-	mutex_lock(&acpi_scan_lock);
+	acpi_status status;
+	unsigned long long sta;
 
 	/* If there is no handle, the device node has been unregistered. */
-	if (!device->handle) {
+	if (!handle) {
 		dev_dbg(&device->dev, "ACPI handle missing\n");
 		put_device(&device->dev);
-		goto out;
+		return -EINVAL;
 	}
 
 	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
@@ -143,7 +144,7 @@ void acpi_bus_hot_remove_device(void *context)
 	put_device(&device->dev);
 	device = NULL;
 
-	if (ACPI_SUCCESS(acpi_get_handle(handle, "_LCK", &temp))) {
+	if (ACPI_SUCCESS(acpi_get_handle(handle, "_LCK", &not_used))) {
 		arg_list.count = 1;
 		arg_list.pointer = &arg;
 		arg.type = ACPI_TYPE_INTEGER;
@@ -161,18 +162,205 @@ void acpi_bus_hot_remove_device(void *context)
 	 */
 	status = acpi_evaluate_object(handle, "_EJ0", &arg_list, NULL);
 	if (ACPI_FAILURE(status)) {
-		if (status != AE_NOT_FOUND)
-			acpi_handle_warn(handle, "Eject failed\n");
+		if (status == AE_NOT_FOUND) {
+			return -ENODEV;
+		} else {
+			acpi_handle_warn(handle, "Eject failed (0x%x)\n",
+								status);
+			return -EIO;
+		}
+	}
 
-		/* Tell the firmware the hot-remove operation has failed. */
-		acpi_evaluate_hotplug_ost(handle, ej_event->event,
-					  ost_code, NULL);
+	/*
+	 * Verify if eject was indeed successful.  If not, log an error
+	 * message.  No need to call _OST since _EJ0 call was made OK.
+	 */
+	status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
+	if (ACPI_FAILURE(status)) {
+		acpi_handle_warn(handle,
+			"Status check after eject failed (0x%x)\n", status);
+	} else if (sta & ACPI_STA_DEVICE_ENABLED) {
+		acpi_handle_warn(handle,
+			"Eject incomplete - status 0x%llx\n", sta);
+	}
+
+	return 0;
+}
+
+static void acpi_bus_device_eject(void *context)
+{
+	acpi_handle handle = context;
+	struct acpi_device *device = NULL;
+	struct acpi_scan_handler *handler;
+	u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
+
+	mutex_lock(&acpi_scan_lock);
+
+	acpi_bus_get_device(handle, &device);
+	if (!device)
+		goto err_out;
+
+	handler = device->handler;
+	if (!handler || !handler->hotplug.enabled) {
+		ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED;
+		goto err_out;
+	}
+	acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST,
+				  ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
+	if (handler->hotplug.mode == AHM_CONTAINER) {
+		device->flags.eject_pending = true;
+		kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE);
+	} else {
+		int error;
+
+		get_device(&device->dev);
+		error = acpi_scan_hot_remove(device);
+		if (error)
+			goto err_out;
 	}
 
  out:
 	mutex_unlock(&acpi_scan_lock);
-	kfree(context);
 	return;
+
+ err_out:
+	acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST, ost_code,
+				  NULL);
+	goto out;
+}
+
+static void acpi_scan_bus_device_check(acpi_handle handle, u32 ost_source)
+{
+	struct acpi_device *device = NULL;
+	u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
+	int error;
+
+	mutex_lock(&acpi_scan_lock);
+
+	acpi_bus_get_device(handle, &device);
+	if (device) {
+		dev_warn(&device->dev, "Attempt to re-insert\n");
+		goto out;
+	}
+	acpi_evaluate_hotplug_ost(handle, ost_source,
+				  ACPI_OST_SC_INSERT_IN_PROGRESS, NULL);
+	error = acpi_bus_scan(handle);
+	if (error) {
+		acpi_handle_warn(handle, "Namespace scan failure\n");
+		goto out;
+	}
+	error = acpi_bus_get_device(handle, &device);
+	if (error) {
+		acpi_handle_warn(handle, "Missing device node object\n");
+		goto out;
+	}
+	ost_code = ACPI_OST_SC_SUCCESS;
+	if (device->handler && device->handler->hotplug.mode == AHM_CONTAINER)
+		kobject_uevent(&device->dev.kobj, KOBJ_ONLINE);
+
+ out:
+	acpi_evaluate_hotplug_ost(handle, ost_source, ost_code, NULL);
+	mutex_unlock(&acpi_scan_lock);
+}
+
+static void acpi_scan_bus_check(void *context)
+{
+	acpi_scan_bus_device_check((acpi_handle)context,
+				   ACPI_NOTIFY_BUS_CHECK);
+}
+
+static void acpi_scan_device_check(void *context)
+{
+	acpi_scan_bus_device_check((acpi_handle)context,
+				   ACPI_NOTIFY_DEVICE_CHECK);
+}
+
+static void acpi_hotplug_unsupported(acpi_handle handle, u32 type)
+{
+	u32 ost_status;
+
+	switch (type) {
+	case ACPI_NOTIFY_BUS_CHECK:
+		acpi_handle_debug(handle,
+			"ACPI_NOTIFY_BUS_CHECK event: unsupported\n");
+		ost_status = ACPI_OST_SC_INSERT_NOT_SUPPORTED;
+		break;
+	case ACPI_NOTIFY_DEVICE_CHECK:
+		acpi_handle_debug(handle,
+			"ACPI_NOTIFY_DEVICE_CHECK event: unsupported\n");
+		ost_status = ACPI_OST_SC_INSERT_NOT_SUPPORTED;
+		break;
+	case ACPI_NOTIFY_EJECT_REQUEST:
+		acpi_handle_debug(handle,
+			"ACPI_NOTIFY_EJECT_REQUEST event: unsupported\n");
+		ost_status = ACPI_OST_SC_EJECT_NOT_SUPPORTED;
+		break;
+	default:
+		/* non-hotplug event; possibly handled by other handler */
+		return;
+	}
+
+	acpi_evaluate_hotplug_ost(handle, type, ost_status, NULL);
+}
+
+static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data)
+{
+	acpi_osd_exec_callback callback;
+	struct acpi_scan_handler *handler = data;
+	acpi_status status;
+
+	if (!handler->hotplug.enabled)
+		return acpi_hotplug_unsupported(handle, type);
+
+	switch (type) {
+	case ACPI_NOTIFY_BUS_CHECK:
+		acpi_handle_debug(handle, "ACPI_NOTIFY_BUS_CHECK event\n");
+		callback = acpi_scan_bus_check;
+		break;
+	case ACPI_NOTIFY_DEVICE_CHECK:
+		acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_CHECK event\n");
+		callback = acpi_scan_device_check;
+		break;
+	case ACPI_NOTIFY_EJECT_REQUEST:
+		acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n");
+		callback = acpi_bus_device_eject;
+		break;
+	default:
+		/* non-hotplug event; possibly handled by other handler */
+		return;
+	}
+	status = acpi_os_hotplug_execute(callback, handle);
+	if (ACPI_FAILURE(status))
+		acpi_evaluate_hotplug_ost(handle, type,
+					  ACPI_OST_SC_NON_SPECIFIC_FAILURE,
+					  NULL);
+}
+
+/**
+ * acpi_bus_hot_remove_device: hot-remove a device and its children
+ * @context: struct acpi_eject_event pointer (freed in this func)
+ *
+ * Hot-remove a device and its children. This function frees up the
+ * memory space passed by arg context, so that the caller may call
+ * this function asynchronously through acpi_os_hotplug_execute().
+ */
+void acpi_bus_hot_remove_device(void *context)
+{
+	struct acpi_eject_event *ej_event = context;
+	struct acpi_device *device = ej_event->device;
+	acpi_handle handle = device->handle;
+	int error;
+
+	mutex_lock(&acpi_scan_lock);
+
+	error = acpi_scan_hot_remove(device);
+	if (error && handle)
+		acpi_evaluate_hotplug_ost(handle, ej_event->event,
+					  ACPI_OST_SC_NON_SPECIFIC_FAILURE,
+					  NULL);
+
+	mutex_unlock(&acpi_scan_lock);
+	kfree(context);
 }
 EXPORT_SYMBOL(acpi_bus_hot_remove_device);
 
@@ -206,51 +394,61 @@ static ssize_t
 acpi_eject_store(struct device *d, struct device_attribute *attr,
 		const char *buf, size_t count)
 {
-	int ret = count;
-	acpi_status status;
-	acpi_object_type type = 0;
 	struct acpi_device *acpi_device = to_acpi_device(d);
 	struct acpi_eject_event *ej_event;
+	acpi_object_type not_used;
+	acpi_status status;
+	u32 ost_source;
+	int ret;
 
-	if ((!count) || (buf[0] != '1')) {
+	if (!count || buf[0] != '1')
 		return -EINVAL;
-	}
-	if (!acpi_device->driver && !acpi_device->handler) {
-		ret = -ENODEV;
-		goto err;
-	}
-	status = acpi_get_type(acpi_device->handle, &type);
-	if (ACPI_FAILURE(status) || (!acpi_device->flags.ejectable)) {
-		ret = -ENODEV;
-		goto err;
-	}
 
-	ej_event = kmalloc(sizeof(*ej_event), GFP_KERNEL);
-	if (!ej_event) {
-		ret = -ENOMEM;
-		goto err;
-	}
+	if ((!acpi_device->handler || !acpi_device->handler->hotplug.enabled)
+	    && !acpi_device->driver)
+		return -ENODEV;
+
+	status = acpi_get_type(acpi_device->handle, &not_used);
+	if (ACPI_FAILURE(status) || !acpi_device->flags.ejectable)
+		return -ENODEV;
+
+	mutex_lock(&acpi_scan_lock);
 
-	get_device(&acpi_device->dev);
-	ej_event->device = acpi_device;
 	if (acpi_device->flags.eject_pending) {
-		/* event originated from ACPI eject notification */
-		ej_event->event = ACPI_NOTIFY_EJECT_REQUEST;
+		/* ACPI eject notification event. */
+		ost_source = ACPI_NOTIFY_EJECT_REQUEST;
 		acpi_device->flags.eject_pending = 0;
 	} else {
-		/* event originated from user */
-		ej_event->event = ACPI_OST_EC_OSPM_EJECT;
-		(void) acpi_evaluate_hotplug_ost(acpi_device->handle,
-			ej_event->event, ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
+		/* Eject initiated by user space. */
+		ost_source = ACPI_OST_EC_OSPM_EJECT;
 	}
-
+	ej_event = kmalloc(sizeof(*ej_event), GFP_KERNEL);
+	if (!ej_event) {
+		ret = -ENOMEM;
+		goto err_out;
+	}
+	acpi_evaluate_hotplug_ost(acpi_device->handle, ost_source,
+				  ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
+	ej_event->device = acpi_device;
+	ej_event->event = ost_source;
+	get_device(&acpi_device->dev);
 	status = acpi_os_hotplug_execute(acpi_bus_hot_remove_device, ej_event);
 	if (ACPI_FAILURE(status)) {
 		put_device(&acpi_device->dev);
 		kfree(ej_event);
+		ret = status == AE_NO_MEMORY ? -ENOMEM : -EAGAIN;
+		goto err_out;
 	}
-err:
+	ret = count;
+
+ out:
+	mutex_unlock(&acpi_scan_lock);
 	return ret;
+
+ err_out:
+	acpi_evaluate_hotplug_ost(acpi_device->handle, ost_source,
+				  ACPI_OST_SC_NON_SPECIFIC_FAILURE, NULL);
+	goto out;
 }
 
 static DEVICE_ATTR(eject, 0200, NULL, acpi_eject_store);
@@ -376,7 +574,7 @@ static int acpi_device_setup_files(struct acpi_device *dev)
 			goto end;
 	}
 
-	if (dev->flags.bus_address)
+	if (dev->pnp.type.bus_address)
 		result = device_create_file(&dev->dev, &dev_attr_adr);
 	if (dev->pnp.unique_id)
 		result = device_create_file(&dev->dev, &dev_attr_uid);
@@ -449,7 +647,7 @@ static void acpi_device_remove_files(struct acpi_device *dev)
 
 	if (dev->pnp.unique_id)
 		device_remove_file(&dev->dev, &dev_attr_uid);
-	if (dev->flags.bus_address)
+	if (dev->pnp.type.bus_address)
 		device_remove_file(&dev->dev, &dev_attr_adr);
 	device_remove_file(&dev->dev, &dev_attr_modalias);
 	device_remove_file(&dev->dev, &dev_attr_hid);
@@ -512,17 +710,6 @@ int acpi_match_device_ids(struct acpi_device *device,
 }
 EXPORT_SYMBOL(acpi_match_device_ids);
 
-void acpi_free_ids(struct acpi_device *device)
-{
-	struct acpi_hardware_id *id, *tmp;
-
-	list_for_each_entry_safe(id, tmp, &device->pnp.ids, list) {
-		kfree(id->id);
-		kfree(id);
-	}
-	kfree(device->pnp.unique_id);
-}
-
 static void acpi_free_power_resources_lists(struct acpi_device *device)
 {
 	int i;
@@ -543,7 +730,7 @@ static void acpi_device_release(struct device *dev)
 {
 	struct acpi_device *acpi_dev = to_acpi_device(dev);
 
-	acpi_free_ids(acpi_dev);
+	acpi_free_pnp_ids(&acpi_dev->pnp);
 	acpi_free_power_resources_lists(acpi_dev);
 	kfree(acpi_dev);
 }
@@ -1256,19 +1443,17 @@ static void acpi_device_get_busid(struct acpi_device *device)
 }
 
 /*
- * acpi_bay_match - see if a device is an ejectable driver bay
+ * acpi_bay_match - see if an acpi object is an ejectable driver bay
  *
  * If an acpi object is ejectable and has one of the ACPI ATA methods defined,
  * then we can safely call it an ejectable drive bay
  */
-static int acpi_bay_match(struct acpi_device *device){
+static int acpi_bay_match(acpi_handle handle)
+{
 	acpi_status status;
-	acpi_handle handle;
 	acpi_handle tmp;
 	acpi_handle phandle;
 
-	handle = device->handle;
-
 	status = acpi_get_handle(handle, "_EJ0", &tmp);
 	if (ACPI_FAILURE(status))
 		return -ENODEV;
@@ -1292,12 +1477,12 @@ static int acpi_bay_match(struct acpi_device *device){
 }
 
 /*
- * acpi_dock_match - see if a device has a _DCK method
+ * acpi_dock_match - see if an acpi object has a _DCK method
  */
-static int acpi_dock_match(struct acpi_device *device)
+static int acpi_dock_match(acpi_handle handle)
 {
 	acpi_handle tmp;
-	return acpi_get_handle(device->handle, "_DCK", &tmp);
+	return acpi_get_handle(handle, "_DCK", &tmp);
 }
 
 const char *acpi_device_hid(struct acpi_device *device)
@@ -1312,7 +1497,7 @@ const char *acpi_device_hid(struct acpi_device *device)
 }
 EXPORT_SYMBOL(acpi_device_hid);
 
-static void acpi_add_id(struct acpi_device *device, const char *dev_id)
+static void acpi_add_id(struct acpi_device_pnp *pnp, const char *dev_id)
 {
 	struct acpi_hardware_id *id;
 
@@ -1326,7 +1511,8 @@ static void acpi_add_id(struct acpi_device *device, const char *dev_id)
 		return;
 	}
 
-	list_add_tail(&id->list, &device->pnp.ids);
+	list_add_tail(&id->list, &pnp->ids);
+	pnp->type.hardware_id = 1;
 }
 
 /*
@@ -1334,7 +1520,7 @@ static void acpi_add_id(struct acpi_device *device, const char *dev_id)
  * lacks the SMBUS01 HID and the methods do not have the necessary "_"
  * prefix.  Work around this.
  */
-static int acpi_ibm_smbus_match(struct acpi_device *device)
+static int acpi_ibm_smbus_match(acpi_handle handle)
 {
 	acpi_handle h_dummy;
 	struct acpi_buffer path = {ACPI_ALLOCATE_BUFFER, NULL};
@@ -1344,7 +1530,7 @@ static int acpi_ibm_smbus_match(struct acpi_device *device)
 		return -ENODEV;
 
 	/* Look for SMBS object */
-	result = acpi_get_name(device->handle, ACPI_SINGLE_NAME, &path);
+	result = acpi_get_name(handle, ACPI_SINGLE_NAME, &path);
 	if (result)
 		return result;
 
@@ -1355,48 +1541,50 @@ static int acpi_ibm_smbus_match(struct acpi_device *device)
 
 	/* Does it have the necessary (but misnamed) methods? */
 	result = -ENODEV;
-	if (ACPI_SUCCESS(acpi_get_handle(device->handle, "SBI", &h_dummy)) &&
-	    ACPI_SUCCESS(acpi_get_handle(device->handle, "SBR", &h_dummy)) &&
-	    ACPI_SUCCESS(acpi_get_handle(device->handle, "SBW", &h_dummy)))
+	if (ACPI_SUCCESS(acpi_get_handle(handle, "SBI", &h_dummy)) &&
+	    ACPI_SUCCESS(acpi_get_handle(handle, "SBR", &h_dummy)) &&
+	    ACPI_SUCCESS(acpi_get_handle(handle, "SBW", &h_dummy)))
 		result = 0;
 out:
 	kfree(path.pointer);
 	return result;
 }
 
-static void acpi_device_set_id(struct acpi_device *device)
+static void acpi_set_pnp_ids(acpi_handle handle, struct acpi_device_pnp *pnp,
+				int device_type)
 {
 	acpi_status status;
 	struct acpi_device_info *info;
 	struct acpi_pnp_device_id_list *cid_list;
 	int i;
 
-	switch (device->device_type) {
+	switch (device_type) {
 	case ACPI_BUS_TYPE_DEVICE:
-		if (ACPI_IS_ROOT_DEVICE(device)) {
-			acpi_add_id(device, ACPI_SYSTEM_HID);
+		if (handle == ACPI_ROOT_OBJECT) {
+			acpi_add_id(pnp, ACPI_SYSTEM_HID);
 			break;
 		}
 
-		status = acpi_get_object_info(device->handle, &info);
+		status = acpi_get_object_info(handle, &info);
 		if (ACPI_FAILURE(status)) {
-			printk(KERN_ERR PREFIX "%s: Error reading device info\n", __func__);
+			pr_err(PREFIX "%s: Error reading device info\n",
+					__func__);
 			return;
 		}
 
 		if (info->valid & ACPI_VALID_HID)
-			acpi_add_id(device, info->hardware_id.string);
+			acpi_add_id(pnp, info->hardware_id.string);
 		if (info->valid & ACPI_VALID_CID) {
 			cid_list = &info->compatible_id_list;
 			for (i = 0; i < cid_list->count; i++)
-				acpi_add_id(device, cid_list->ids[i].string);
+				acpi_add_id(pnp, cid_list->ids[i].string);
 		}
 		if (info->valid & ACPI_VALID_ADR) {
-			device->pnp.bus_address = info->address;
-			device->flags.bus_address = 1;
+			pnp->bus_address = info->address;
+			pnp->type.bus_address = 1;
 		}
 		if (info->valid & ACPI_VALID_UID)
-			device->pnp.unique_id = kstrdup(info->unique_id.string,
+			pnp->unique_id = kstrdup(info->unique_id.string,
 							GFP_KERNEL);
 
 		kfree(info);
@@ -1405,40 +1593,50 @@ static void acpi_device_set_id(struct acpi_device *device)
 		 * Some devices don't reliably have _HIDs & _CIDs, so add
 		 * synthetic HIDs to make sure drivers can find them.
 		 */
-		if (acpi_is_video_device(device))
-			acpi_add_id(device, ACPI_VIDEO_HID);
-		else if (ACPI_SUCCESS(acpi_bay_match(device)))
-			acpi_add_id(device, ACPI_BAY_HID);
-		else if (ACPI_SUCCESS(acpi_dock_match(device)))
-			acpi_add_id(device, ACPI_DOCK_HID);
-		else if (!acpi_ibm_smbus_match(device))
-			acpi_add_id(device, ACPI_SMBUS_IBM_HID);
-		else if (list_empty(&device->pnp.ids) &&
-			 ACPI_IS_ROOT_DEVICE(device->parent)) {
-			acpi_add_id(device, ACPI_BUS_HID); /* \_SB, LNXSYBUS */
-			strcpy(device->pnp.device_name, ACPI_BUS_DEVICE_NAME);
-			strcpy(device->pnp.device_class, ACPI_BUS_CLASS);
+		if (acpi_is_video_device(handle))
+			acpi_add_id(pnp, ACPI_VIDEO_HID);
+		else if (ACPI_SUCCESS(acpi_bay_match(handle)))
+			acpi_add_id(pnp, ACPI_BAY_HID);
+		else if (ACPI_SUCCESS(acpi_dock_match(handle)))
+			acpi_add_id(pnp, ACPI_DOCK_HID);
+		else if (!acpi_ibm_smbus_match(handle))
+			acpi_add_id(pnp, ACPI_SMBUS_IBM_HID);
+		else if (list_empty(&pnp->ids) && handle == ACPI_ROOT_OBJECT) {
+			acpi_add_id(pnp, ACPI_BUS_HID); /* \_SB, LNXSYBUS */
+			strcpy(pnp->device_name, ACPI_BUS_DEVICE_NAME);
+			strcpy(pnp->device_class, ACPI_BUS_CLASS);
 		}
 
 		break;
 	case ACPI_BUS_TYPE_POWER:
-		acpi_add_id(device, ACPI_POWER_HID);
+		acpi_add_id(pnp, ACPI_POWER_HID);
 		break;
 	case ACPI_BUS_TYPE_PROCESSOR:
-		acpi_add_id(device, ACPI_PROCESSOR_OBJECT_HID);
+		acpi_add_id(pnp, ACPI_PROCESSOR_OBJECT_HID);
 		break;
 	case ACPI_BUS_TYPE_THERMAL:
-		acpi_add_id(device, ACPI_THERMAL_HID);
+		acpi_add_id(pnp, ACPI_THERMAL_HID);
 		break;
 	case ACPI_BUS_TYPE_POWER_BUTTON:
-		acpi_add_id(device, ACPI_BUTTON_HID_POWERF);
+		acpi_add_id(pnp, ACPI_BUTTON_HID_POWERF);
 		break;
 	case ACPI_BUS_TYPE_SLEEP_BUTTON:
-		acpi_add_id(device, ACPI_BUTTON_HID_SLEEPF);
+		acpi_add_id(pnp, ACPI_BUTTON_HID_SLEEPF);
 		break;
 	}
 }
 
+void acpi_free_pnp_ids(struct acpi_device_pnp *pnp)
+{
+	struct acpi_hardware_id *id, *tmp;
+
+	list_for_each_entry_safe(id, tmp, &pnp->ids, list) {
+		kfree(id->id);
+		kfree(id);
+	}
+	kfree(pnp->unique_id);
+}
+
 void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
 			     int type, unsigned long long sta)
 {
@@ -1448,7 +1646,7 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
 	device->parent = acpi_bus_get_parent(handle);
 	STRUCT_TO_INT(device->status) = sta;
 	acpi_device_get_busid(device);
-	acpi_device_set_id(device);
+	acpi_set_pnp_ids(handle, &device->pnp, type);
 	acpi_bus_get_flags(device);
 	device->flags.match_driver = false;
 	device_initialize(&device->dev);
@@ -1536,6 +1734,75 @@ static int acpi_bus_type_and_status(acpi_handle handle, int *type,
 	return 0;
 }
 
+static bool acpi_scan_handler_matching(struct acpi_scan_handler *handler,
+				       char *idstr,
+				       const struct acpi_device_id **matchid)
+{
+	const struct acpi_device_id *devid;
+
+	for (devid = handler->ids; devid->id[0]; devid++)
+		if (!strcmp((char *)devid->id, idstr)) {
+			if (matchid)
+				*matchid = devid;
+
+			return true;
+		}
+
+	return false;
+}
+
+static struct acpi_scan_handler *acpi_scan_match_handler(char *idstr,
+					const struct acpi_device_id **matchid)
+{
+	struct acpi_scan_handler *handler;
+
+	list_for_each_entry(handler, &acpi_scan_handlers_list, list_node)
+		if (acpi_scan_handler_matching(handler, idstr, matchid))
+			return handler;
+
+	return NULL;
+}
+
+void acpi_scan_hotplug_enabled(struct acpi_hotplug_profile *hotplug, bool val)
+{
+	if (!!hotplug->enabled == !!val)
+		return;
+
+	mutex_lock(&acpi_scan_lock);
+
+	hotplug->enabled = val;
+
+	mutex_unlock(&acpi_scan_lock);
+}
+
+static void acpi_scan_init_hotplug(acpi_handle handle, int type)
+{
+	struct acpi_device_pnp pnp = {};
+	struct acpi_hardware_id *hwid;
+	struct acpi_scan_handler *handler;
+
+	INIT_LIST_HEAD(&pnp.ids);
+	acpi_set_pnp_ids(handle, &pnp, type);
+
+	if (!pnp.type.hardware_id)
+		return;
+
+	/*
+	 * This relies on the fact that acpi_install_notify_handler() will not
+	 * install the same notify handler routine twice for the same handle.
+	 */
+	list_for_each_entry(hwid, &pnp.ids, list) {
+		handler = acpi_scan_match_handler(hwid->id, NULL);
+		if (handler) {
+			acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
+					acpi_hotplug_notify_cb, handler);
+			break;
+		}
+	}
+
+	acpi_free_pnp_ids(&pnp);
+}
+
 static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used,
 				      void *not_used, void **return_value)
 {
@@ -1558,6 +1825,8 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used,
 		return AE_OK;
 	}
 
+	acpi_scan_init_hotplug(handle, type);
+
 	if (!(sta & ACPI_STA_DEVICE_PRESENT) &&
 	    !(sta & ACPI_STA_DEVICE_FUNCTIONING)) {
 		struct acpi_device_wakeup wakeup;
@@ -1583,42 +1852,26 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used,
 	return AE_OK;
 }
 
-static int acpi_scan_do_attach_handler(struct acpi_device *device, char *id)
+static int acpi_scan_attach_handler(struct acpi_device *device)
 {
-	struct acpi_scan_handler *handler;
+	struct acpi_hardware_id *hwid;
+	int ret = 0;
 
-	list_for_each_entry(handler, &acpi_scan_handlers_list, list_node) {
+	list_for_each_entry(hwid, &device->pnp.ids, list) {
 		const struct acpi_device_id *devid;
+		struct acpi_scan_handler *handler;
 
-		for (devid = handler->ids; devid->id[0]; devid++) {
-			int ret;
-
-			if (strcmp((char *)devid->id, id))
-				continue;
-
+		handler = acpi_scan_match_handler(hwid->id, &devid);
+		if (handler) {
 			ret = handler->attach(device, devid);
 			if (ret > 0) {
 				device->handler = handler;
-				return ret;
+				break;
 			} else if (ret < 0) {
-				return ret;
+				break;
 			}
 		}
 	}
-	return 0;
-}
-
-static int acpi_scan_attach_handler(struct acpi_device *device)
-{
-	struct acpi_hardware_id *hwid;
-	int ret = 0;
-
-	list_for_each_entry(hwid, &device->pnp.ids, list) {
-		ret = acpi_scan_do_attach_handler(device, hwid->id);
-		if (ret)
-			break;
-
-	}
 	return ret;
 }
 
@@ -1788,9 +2041,11 @@ int __init acpi_scan_init(void)
 	acpi_pci_root_init();
 	acpi_pci_link_init();
 	acpi_platform_init();
+	acpi_lpss_init();
 	acpi_csrt_init();
 	acpi_container_init();
 	acpi_pci_slot_init();
+	acpi_memory_hotplug_init();
 
 	mutex_lock(&acpi_scan_lock);
 	/*
diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c
index 41c0504..fcae5fa 100644
--- a/drivers/acpi/sysfs.c
+++ b/drivers/acpi/sysfs.c
@@ -7,6 +7,8 @@
 #include <linux/moduleparam.h>
 #include <acpi/acpi_drivers.h>
 
+#include "internal.h"
+
 #define _COMPONENT		ACPI_SYSTEM_COMPONENT
 ACPI_MODULE_NAME("sysfs");
 
@@ -249,6 +251,7 @@ module_param_call(acpica_version, NULL, param_get_acpica_version, NULL, 0444);
 static LIST_HEAD(acpi_table_attr_list);
 static struct kobject *tables_kobj;
 static struct kobject *dynamic_tables_kobj;
+static struct kobject *hotplug_kobj;
 
 struct acpi_table_attr {
 	struct bin_attribute attr;
@@ -716,6 +719,67 @@ acpi_show_profile(struct device *dev, struct device_attribute *attr,
 static const struct device_attribute pm_profile_attr =
 	__ATTR(pm_profile, S_IRUGO, acpi_show_profile, NULL);
 
+static ssize_t hotplug_enabled_show(struct kobject *kobj,
+				    struct kobj_attribute *attr, char *buf)
+{
+	struct acpi_hotplug_profile *hotplug = to_acpi_hotplug_profile(kobj);
+
+	return sprintf(buf, "%d\n", hotplug->enabled);
+}
+
+static ssize_t hotplug_enabled_store(struct kobject *kobj,
+				     struct kobj_attribute *attr,
+				     const char *buf, size_t size)
+{
+	struct acpi_hotplug_profile *hotplug = to_acpi_hotplug_profile(kobj);
+	unsigned int val;
+
+	if (kstrtouint(buf, 10, &val) || val > 1)
+		return -EINVAL;
+
+	acpi_scan_hotplug_enabled(hotplug, val);
+	return size;
+}
+
+static struct kobj_attribute hotplug_enabled_attr =
+	__ATTR(enabled, S_IRUGO | S_IWUSR, hotplug_enabled_show,
+		hotplug_enabled_store);
+
+static struct attribute *hotplug_profile_attrs[] = {
+	&hotplug_enabled_attr.attr,
+	NULL
+};
+
+static struct kobj_type acpi_hotplug_profile_ktype = {
+	.sysfs_ops = &kobj_sysfs_ops,
+	.default_attrs = hotplug_profile_attrs,
+};
+
+void acpi_sysfs_add_hotplug_profile(struct acpi_hotplug_profile *hotplug,
+				    const char *name)
+{
+	int error;
+
+	if (!hotplug_kobj)
+		goto err_out;
+
+	kobject_init(&hotplug->kobj, &acpi_hotplug_profile_ktype);
+	error = kobject_set_name(&hotplug->kobj, "%s", name);
+	if (error)
+		goto err_out;
+
+	hotplug->kobj.parent = hotplug_kobj;
+	error = kobject_add(&hotplug->kobj, hotplug_kobj, NULL);
+	if (error)
+		goto err_out;
+
+	kobject_uevent(&hotplug->kobj, KOBJ_ADD);
+	return;
+
+ err_out:
+	pr_err(PREFIX "Unable to add hotplug profile '%s'\n", name);
+}
+
 int __init acpi_sysfs_init(void)
 {
 	int result;
@@ -723,6 +787,8 @@ int __init acpi_sysfs_init(void)
 	result = acpi_tables_sysfs_init();
 	if (result)
 		return result;
+
+	hotplug_kobj = kobject_create_and_add("hotplug", acpi_kobj);
 	result = sysfs_create_file(acpi_kobj, &pm_profile_attr.attr);
 	return result;
 }
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index 313f959..3cdd047 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -222,7 +222,7 @@ static int acpi_video_device_lcd_set_level(struct acpi_video_device *device,
 			int level);
 static int acpi_video_device_lcd_get_level_current(
 			struct acpi_video_device *device,
-			unsigned long long *level, int init);
+			unsigned long long *level, bool raw);
 static int acpi_video_get_next_level(struct acpi_video_device *device,
 				     u32 level_current, u32 event);
 static int acpi_video_switch_brightness(struct acpi_video_device *device,
@@ -236,7 +236,7 @@ static int acpi_video_get_brightness(struct backlight_device *bd)
 	struct acpi_video_device *vd =
 		(struct acpi_video_device *)bl_get_data(bd);
 
-	if (acpi_video_device_lcd_get_level_current(vd, &cur_level, 0))
+	if (acpi_video_device_lcd_get_level_current(vd, &cur_level, false))
 		return -EINVAL;
 	for (i = 2; i < vd->brightness->count; i++) {
 		if (vd->brightness->levels[i] == cur_level)
@@ -281,7 +281,7 @@ static int video_get_cur_state(struct thermal_cooling_device *cooling_dev, unsig
 	unsigned long long level;
 	int offset;
 
-	if (acpi_video_device_lcd_get_level_current(video, &level, 0))
+	if (acpi_video_device_lcd_get_level_current(video, &level, false))
 		return -EINVAL;
 	for (offset = 2; offset < video->brightness->count; offset++)
 		if (level == video->brightness->levels[offset]) {
@@ -447,12 +447,45 @@ static struct dmi_system_id video_dmi_table[] __initdata = {
 		DMI_MATCH(DMI_PRODUCT_NAME, "HP Folio 13 - 2000 Notebook PC"),
 		},
 	},
+	{
+	 .callback = video_ignore_initial_backlight,
+	 .ident = "HP Pavilion dm4",
+	 .matches = {
+		DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
+		DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dm4 Notebook PC"),
+		},
+	},
 	{}
 };
 
+static unsigned long long
+acpi_video_bqc_value_to_level(struct acpi_video_device *device,
+			      unsigned long long bqc_value)
+{
+	unsigned long long level;
+
+	if (device->brightness->flags._BQC_use_index) {
+		/*
+		 * _BQC returns an index that doesn't account for
+		 * the first 2 items with special meaning, so we need
+		 * to compensate for that by offsetting ourselves
+		 */
+		if (device->brightness->flags._BCL_reversed)
+			bqc_value = device->brightness->count - 3 - bqc_value;
+
+		level = device->brightness->levels[bqc_value + 2];
+	} else {
+		level = bqc_value;
+	}
+
+	level += bqc_offset_aml_bug_workaround;
+
+	return level;
+}
+
 static int
 acpi_video_device_lcd_get_level_current(struct acpi_video_device *device,
-					unsigned long long *level, int init)
+					unsigned long long *level, bool raw)
 {
 	acpi_status status = AE_OK;
 	int i;
@@ -463,29 +496,30 @@ acpi_video_device_lcd_get_level_current(struct acpi_video_device *device,
 		status = acpi_evaluate_integer(device->dev->handle, buf,
 						NULL, level);
 		if (ACPI_SUCCESS(status)) {
-			if (device->brightness->flags._BQC_use_index) {
-				if (device->brightness->flags._BCL_reversed)
-					*level = device->brightness->count
-								 - 3 - (*level);
-				*level = device->brightness->levels[*level + 2];
-
+			if (raw) {
+				/*
+				 * Caller has indicated he wants the raw
+				 * value returned by _BQC, so don't furtherly
+				 * mess with the value.
+				 */
+				return 0;
 			}
-			*level += bqc_offset_aml_bug_workaround;
+
+			*level = acpi_video_bqc_value_to_level(device, *level);
+
 			for (i = 2; i < device->brightness->count; i++)
 				if (device->brightness->levels[i] == *level) {
 					device->brightness->curr = *level;
 					return 0;
 			}
-			if (!init) {
-				/*
-				 * BQC returned an invalid level.
-				 * Stop using it.
-				 */
-				ACPI_WARNING((AE_INFO,
-					      "%s returned an invalid level",
-					      buf));
-				device->cap._BQC = device->cap._BCQ = 0;
-			}
+			/*
+			 * BQC returned an invalid level.
+			 * Stop using it.
+			 */
+			ACPI_WARNING((AE_INFO,
+				      "%s returned an invalid level",
+				      buf));
+			device->cap._BQC = device->cap._BCQ = 0;
 		} else {
 			/* Fixme:
 			 * should we return an error or ignore this failure?
@@ -703,7 +737,8 @@ acpi_video_init_brightness(struct acpi_video_device *device)
 	if (!device->cap._BQC)
 		goto set_level;
 
-	result = acpi_video_device_lcd_get_level_current(device, &level_old, 1);
+	result = acpi_video_device_lcd_get_level_current(device,
+							 &level_old, true);
 	if (result)
 		goto out_free_levels;
 
@@ -714,31 +749,27 @@ acpi_video_init_brightness(struct acpi_video_device *device)
 	if (result)
 		goto out_free_levels;
 
-	result = acpi_video_device_lcd_get_level_current(device, &level, 0);
+	result = acpi_video_device_lcd_get_level_current(device, &level, true);
 	if (result)
 		goto out_free_levels;
 
 	br->flags._BQC_use_index = (level == max_level ? 0 : 1);
 
-	if (!br->flags._BQC_use_index) {
+	if (use_bios_initial_backlight) {
+		level = acpi_video_bqc_value_to_level(device, level_old);
 		/*
-		 * Set the backlight to the initial state.
-		 * On some buggy laptops, _BQC returns an uninitialized value
-		 * when invoked for the first time, i.e. level_old is invalid.
-		 * set the backlight to max_level in this case
+		 * On some buggy laptops, _BQC returns an uninitialized
+		 * value when invoked for the first time, i.e.
+		 * level_old is invalid (no matter whether it's a level
+		 * or an index). Set the backlight to max_level in this case.
 		 */
-		if (use_bios_initial_backlight) {
-			for (i = 2; i < br->count; i++)
-				if (level_old == br->levels[i])
-					level = level_old;
-		}
-		goto set_level;
+		for (i = 2; i < br->count; i++)
+			if (level_old == br->levels[i])
+				break;
+		if (i == br->count)
+			level = max_level;
 	}
 
-	if (br->flags._BCL_reversed)
-		level_old = (br->count - 1) - level_old;
-	level = br->levels[level_old];
-
 set_level:
 	result = acpi_video_device_lcd_set_level(device, level);
 	if (result)
@@ -1268,7 +1299,8 @@ acpi_video_switch_brightness(struct acpi_video_device *device, int event)
 		goto out;
 
 	result = acpi_video_device_lcd_get_level_current(device,
-							 &level_current, 0);
+							 &level_current,
+							 false);
 	if (result)
 		goto out;
 
diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c
index 4ac2593..66f6762 100644
--- a/drivers/acpi/video_detect.c
+++ b/drivers/acpi/video_detect.c
@@ -67,40 +67,37 @@ acpi_backlight_cap_match(acpi_handle handle, u32 level, void *context,
 	return 0;
 }
 
-/* Returns true if the device is a video device which can be handled by
- * video.ko.
+/* Returns true if the ACPI object is a video device which can be
+ * handled by video.ko.
  * The device will get a Linux specific CID added in scan.c to
  * identify the device as an ACPI graphics device
  * Be aware that the graphics device may not be physically present
  * Use acpi_video_get_capabilities() to detect general ACPI video
  * capabilities of present cards
  */
-long acpi_is_video_device(struct acpi_device *device)
+long acpi_is_video_device(acpi_handle handle)
 {
 	acpi_handle h_dummy;
 	long video_caps = 0;
 
-	if (!device)
-		return 0;
-
 	/* Is this device able to support video switching ? */
-	if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOD", &h_dummy)) ||
-	    ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOS", &h_dummy)))
+	if (ACPI_SUCCESS(acpi_get_handle(handle, "_DOD", &h_dummy)) ||
+	    ACPI_SUCCESS(acpi_get_handle(handle, "_DOS", &h_dummy)))
 		video_caps |= ACPI_VIDEO_OUTPUT_SWITCHING;
 
 	/* Is this device able to retrieve a video ROM ? */
-	if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_ROM", &h_dummy)))
+	if (ACPI_SUCCESS(acpi_get_handle(handle, "_ROM", &h_dummy)))
 		video_caps |= ACPI_VIDEO_ROM_AVAILABLE;
 
 	/* Is this device able to configure which video head to be POSTed ? */
-	if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_VPO", &h_dummy)) &&
-	    ACPI_SUCCESS(acpi_get_handle(device->handle, "_GPD", &h_dummy)) &&
-	    ACPI_SUCCESS(acpi_get_handle(device->handle, "_SPD", &h_dummy)))
+	if (ACPI_SUCCESS(acpi_get_handle(handle, "_VPO", &h_dummy)) &&
+	    ACPI_SUCCESS(acpi_get_handle(handle, "_GPD", &h_dummy)) &&
+	    ACPI_SUCCESS(acpi_get_handle(handle, "_SPD", &h_dummy)))
 		video_caps |= ACPI_VIDEO_DEVICE_POSTING;
 
 	/* Only check for backlight functionality if one of the above hit. */
 	if (video_caps)
-		acpi_walk_namespace(ACPI_TYPE_DEVICE, device->handle,
+		acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
 				    ACPI_UINT32_MAX, acpi_backlight_cap_match, NULL,
 				    &video_caps, NULL);
 
@@ -127,7 +124,7 @@ find_video(acpi_handle handle, u32 lvl, void *context, void **rv)
 		if (!dev)
 			return AE_OK;
 		pci_dev_put(dev);
-		*cap |= acpi_is_video_device(acpi_dev);
+		*cap |= acpi_is_video_device(handle);
 	}
 	return AE_OK;
 }
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
index ffdd32d..2f48123 100644
--- a/drivers/ata/ata_piix.c
+++ b/drivers/ata/ata_piix.c
@@ -150,6 +150,7 @@ enum piix_controller_ids {
 	tolapai_sata,
 	piix_pata_vmw,			/* PIIX4 for VMware, spurious DMA_ERR */
 	ich8_sata_snb,
+	ich8_2port_sata_snb,
 };
 
 struct piix_map_db {
@@ -304,7 +305,7 @@ static const struct pci_device_id piix_pci_tbl[] = {
 	/* SATA Controller IDE (Lynx Point) */
 	{ 0x8086, 0x8c01, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },
 	/* SATA Controller IDE (Lynx Point) */
-	{ 0x8086, 0x8c08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
+	{ 0x8086, 0x8c08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata_snb },
 	/* SATA Controller IDE (Lynx Point) */
 	{ 0x8086, 0x8c09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
 	/* SATA Controller IDE (Lynx Point-LP) */
@@ -439,6 +440,7 @@ static const struct piix_map_db *piix_map_db_table[] = {
 	[ich8m_apple_sata]	= &ich8m_apple_map_db,
 	[tolapai_sata]		= &tolapai_map_db,
 	[ich8_sata_snb]		= &ich8_map_db,
+	[ich8_2port_sata_snb]	= &ich8_2port_map_db,
 };
 
 static struct pci_bits piix_enable_bits[] = {
@@ -1242,6 +1244,16 @@ static struct ata_port_info piix_port_info[] = {
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &piix_sata_ops,
 	},
+
+	[ich8_2port_sata_snb] =
+	{
+		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_SIDPR
+					| PIIX_FLAG_PIO16,
+		.pio_mask	= ATA_PIO4,
+		.mwdma_mask	= ATA_MWDMA2,
+		.udma_mask	= ATA_UDMA6,
+		.port_ops	= &piix_sata_ops,
+	},
 };
 
 #define AHCI_PCI_BAR 5
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
index 8a52dab..1c33f78 100644
--- a/drivers/ata/libata-acpi.c
+++ b/drivers/ata/libata-acpi.c
@@ -17,7 +17,6 @@
 #include <linux/pci.h>
 #include <linux/slab.h>
 #include <linux/pm_runtime.h>
-#include <linux/pm_qos.h>
 #include <scsi/scsi_device.h>
 #include "libata.h"
 
@@ -1020,38 +1019,6 @@ void ata_acpi_on_disable(struct ata_device *dev)
 	ata_acpi_clear_gtf(dev);
 }
 
-static void ata_acpi_register_power_resource(struct ata_device *dev)
-{
-	struct scsi_device *sdev = dev->sdev;
-	acpi_handle handle;
-
-	handle = ata_dev_acpi_handle(dev);
-	if (handle)
-		acpi_dev_pm_add_dependent(handle, &sdev->sdev_gendev);
-}
-
-static void ata_acpi_unregister_power_resource(struct ata_device *dev)
-{
-	struct scsi_device *sdev = dev->sdev;
-	acpi_handle handle;
-
-	handle = ata_dev_acpi_handle(dev);
-	if (handle)
-		acpi_dev_pm_remove_dependent(handle, &sdev->sdev_gendev);
-}
-
-void ata_acpi_bind(struct ata_device *dev)
-{
-	ata_acpi_register_power_resource(dev);
-	if (zpodd_dev_enabled(dev))
-		dev_pm_qos_expose_flags(&dev->sdev->sdev_gendev, 0);
-}
-
-void ata_acpi_unbind(struct ata_device *dev)
-{
-	ata_acpi_unregister_power_resource(dev);
-}
-
 static int compat_pci_ata(struct ata_port *ap)
 {
 	struct device *dev = ap->tdev.parent;
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 497adea..63c743b 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -2329,7 +2329,7 @@ int ata_dev_configure(struct ata_device *dev)
 		 * from SATA Settings page of Identify Device Data Log.
 		 */
 		if (ata_id_has_devslp(dev->id)) {
-			u8 sata_setting[ATA_SECT_SIZE];
+			u8 *sata_setting = ap->sector_buf;
 			int i, j;
 
 			dev->flags |= ATA_DFLAG_DEVSLP;
@@ -2439,6 +2439,9 @@ int ata_dev_configure(struct ata_device *dev)
 		dev->max_sectors = min_t(unsigned int, ATA_MAX_SECTORS_128,
 					 dev->max_sectors);
 
+	if (dev->horkage & ATA_HORKAGE_MAX_SEC_LBA48)
+		dev->max_sectors = ATA_MAX_SECTORS_LBA48;
+
 	if (ap->ops->dev_config)
 		ap->ops->dev_config(dev);
 
@@ -4100,6 +4103,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
 	/* Weird ATAPI devices */
 	{ "TORiSAN DVD-ROM DRD-N216", NULL,	ATA_HORKAGE_MAX_SEC_128 },
 	{ "QUANTUM DAT    DAT72-000", NULL,	ATA_HORKAGE_ATAPI_MOD16_DMA },
+	{ "Slimtype DVD A  DS8A8SH", NULL,	ATA_HORKAGE_MAX_SEC_LBA48 },
 
 	/* Devices we expect to fail diagnostics */
 
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 318b413..fe759ca 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -49,6 +49,7 @@
 #include <linux/hdreg.h>
 #include <linux/uaccess.h>
 #include <linux/suspend.h>
+#include <linux/pm_qos.h>
 #include <asm/unaligned.h>
 
 #include "libata.h"
@@ -532,8 +533,8 @@ int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg)
 			struct scsi_sense_hdr sshdr;
 			scsi_normalize_sense(sensebuf, SCSI_SENSE_BUFFERSIZE,
 					     &sshdr);
-			if (sshdr.sense_key == 0 &&
-			    sshdr.asc == 0 && sshdr.ascq == 0)
+			if (sshdr.sense_key == RECOVERED_ERROR &&
+			    sshdr.asc == 0 && sshdr.ascq == 0x1d)
 				cmd_result &= ~SAM_STAT_CHECK_CONDITION;
 		}
 
@@ -618,8 +619,8 @@ int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg)
 			struct scsi_sense_hdr sshdr;
 			scsi_normalize_sense(sensebuf, SCSI_SENSE_BUFFERSIZE,
 						&sshdr);
-			if (sshdr.sense_key == 0 &&
-				sshdr.asc == 0 && sshdr.ascq == 0)
+			if (sshdr.sense_key == RECOVERED_ERROR &&
+			    sshdr.asc == 0 && sshdr.ascq == 0x1d)
 				cmd_result &= ~SAM_STAT_CHECK_CONDITION;
 		}
 
@@ -3668,7 +3669,9 @@ void ata_scsi_scan_host(struct ata_port *ap, int sync)
 			if (!IS_ERR(sdev)) {
 				dev->sdev = sdev;
 				scsi_device_put(sdev);
-				ata_acpi_bind(dev);
+				if (zpodd_dev_enabled(dev))
+					dev_pm_qos_expose_flags(
+							&sdev->sdev_gendev, 0);
 			} else {
 				dev->sdev = NULL;
 			}
@@ -3767,7 +3770,6 @@ static void ata_scsi_remove_dev(struct ata_device *dev)
 
 	if (zpodd_dev_enabled(dev))
 		zpodd_exit(dev);
-	ata_acpi_unbind(dev);
 
 	/* clearing dev->sdev is protected by host lock */
 	sdev = dev->sdev;
diff --git a/drivers/ata/pata_at32.c b/drivers/ata/pata_at32.c
index 36f189c..8d493b4 100644
--- a/drivers/ata/pata_at32.c
+++ b/drivers/ata/pata_at32.c
@@ -393,18 +393,7 @@ static struct platform_driver pata_at32_driver = {
 	},
 };
 
-static int __init pata_at32_init(void)
-{
-	return platform_driver_probe(&pata_at32_driver, pata_at32_probe);
-}
-
-static void __exit pata_at32_exit(void)
-{
-	platform_driver_unregister(&pata_at32_driver);
-}
-
-module_init(pata_at32_init);
-module_exit(pata_at32_exit);
+module_platform_driver_probe(pata_at32_driver, pata_at32_probe);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("AVR32 SMC/CFC PATA Driver");
diff --git a/drivers/ata/pata_legacy.c b/drivers/ata/pata_legacy.c
index 4fe9d21..be81642 100644
--- a/drivers/ata/pata_legacy.c
+++ b/drivers/ata/pata_legacy.c
@@ -542,7 +542,7 @@ static void opti82c46x_set_piomode(struct ata_port *ap, struct ata_device *adev)
 	u8 sysclk;
 
 	/* Get the clock */
-	sysclk = opti_syscfg(0xAC) & 0xC0;	/* BIOS set */
+	sysclk = (opti_syscfg(0xAC) & 0xC0) >> 6;	/* BIOS set */
 
 	/* Enter configuration mode */
 	ioread16(ap->ioaddr.error_addr);
diff --git a/drivers/ata/pata_octeon_cf.c b/drivers/ata/pata_octeon_cf.c
index ff2e57f..e73bef3 100644
--- a/drivers/ata/pata_octeon_cf.c
+++ b/drivers/ata/pata_octeon_cf.c
@@ -926,7 +926,7 @@ static int octeon_cf_probe(struct platform_device *pdev)
 			goto free_cf_port;
 		}
 		cs1 = devm_ioremap_nocache(&pdev->dev, res_cs1->start,
-					   res_cs1->end - res_cs1->start + 1);
+					   resource_size(res_cs1));
 
 		if (!cs1)
 			goto free_cf_port;
diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c
index 958238d..40254f4 100644
--- a/drivers/ata/pata_pcmcia.c
+++ b/drivers/ata/pata_pcmcia.c
@@ -387,21 +387,9 @@ static struct pcmcia_driver pcmcia_driver = {
 	.probe		= pcmcia_init_one,
 	.remove		= pcmcia_remove_one,
 };
-
-static int __init pcmcia_init(void)
-{
-	return pcmcia_register_driver(&pcmcia_driver);
-}
-
-static void __exit pcmcia_exit(void)
-{
-	pcmcia_unregister_driver(&pcmcia_driver);
-}
+module_pcmcia_driver(pcmcia_driver);
 
 MODULE_AUTHOR("Alan Cox");
 MODULE_DESCRIPTION("low-level driver for PCMCIA ATA");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_VERSION);
-
-module_init(pcmcia_init);
-module_exit(pcmcia_exit);
diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c
index 608f82f..d40e403 100644
--- a/drivers/ata/sata_fsl.c
+++ b/drivers/ata/sata_fsl.c
@@ -285,6 +285,7 @@ struct sata_fsl_host_priv {
 	int irq;
 	int data_snoop;
 	struct device_attribute intr_coalescing;
+	struct device_attribute rx_watermark;
 };
 
 static void fsl_sata_set_irq_coalescing(struct ata_host *host,
@@ -311,7 +312,7 @@ static void fsl_sata_set_irq_coalescing(struct ata_host *host,
 	intr_coalescing_ticks = ticks;
 	spin_unlock(&host->lock);
 
-	DPRINTK("intrrupt coalescing, count = 0x%x, ticks = %x\n",
+	DPRINTK("interrupt coalescing, count = 0x%x, ticks = %x\n",
 			intr_coalescing_count, intr_coalescing_ticks);
 	DPRINTK("ICC register status: (hcr base: 0x%x) = 0x%x\n",
 			hcr_base, ioread32(hcr_base + ICC));
@@ -343,6 +344,48 @@ static ssize_t fsl_sata_intr_coalescing_store(struct device *dev,
 	return strlen(buf);
 }
 
+static ssize_t fsl_sata_rx_watermark_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	unsigned int rx_watermark;
+	unsigned long flags;
+	struct ata_host *host = dev_get_drvdata(dev);
+	struct sata_fsl_host_priv *host_priv = host->private_data;
+	void __iomem *csr_base = host_priv->csr_base;
+
+	spin_lock_irqsave(&host->lock, flags);
+	rx_watermark = ioread32(csr_base + TRANSCFG);
+	rx_watermark &= 0x1f;
+
+	spin_unlock_irqrestore(&host->lock, flags);
+	return sprintf(buf, "%d\n", rx_watermark);
+}
+
+static ssize_t fsl_sata_rx_watermark_store(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	unsigned int rx_watermark;
+	unsigned long flags;
+	struct ata_host *host = dev_get_drvdata(dev);
+	struct sata_fsl_host_priv *host_priv = host->private_data;
+	void __iomem *csr_base = host_priv->csr_base;
+	u32 temp;
+
+	if (sscanf(buf, "%d", &rx_watermark) != 1) {
+		printk(KERN_ERR "fsl-sata: wrong parameter format.\n");
+		return -EINVAL;
+	}
+
+	spin_lock_irqsave(&host->lock, flags);
+	temp = ioread32(csr_base + TRANSCFG);
+	temp &= 0xffffffe0;
+	iowrite32(temp | rx_watermark, csr_base + TRANSCFG);
+
+	spin_unlock_irqrestore(&host->lock, flags);
+	return strlen(buf);
+}
+
 static inline unsigned int sata_fsl_tag(unsigned int tag,
 					void __iomem *hcr_base)
 {
@@ -1500,6 +1543,17 @@ static int sata_fsl_probe(struct platform_device *ofdev)
 	if (retval)
 		goto error_exit_with_cleanup;
 
+	host_priv->rx_watermark.show = fsl_sata_rx_watermark_show;
+	host_priv->rx_watermark.store = fsl_sata_rx_watermark_store;
+	sysfs_attr_init(&host_priv->rx_watermark.attr);
+	host_priv->rx_watermark.attr.name = "rx_watermark";
+	host_priv->rx_watermark.attr.mode = S_IRUGO | S_IWUSR;
+	retval = device_create_file(host->dev, &host_priv->rx_watermark);
+	if (retval) {
+		device_remove_file(&ofdev->dev, &host_priv->intr_coalescing);
+		goto error_exit_with_cleanup;
+	}
+
 	return 0;
 
 error_exit_with_cleanup:
@@ -1522,6 +1576,7 @@ static int sata_fsl_remove(struct platform_device *ofdev)
 	struct sata_fsl_host_priv *host_priv = host->private_data;
 
 	device_remove_file(&ofdev->dev, &host_priv->intr_coalescing);
+	device_remove_file(&ofdev->dev, &host_priv->rx_watermark);
 
 	ata_host_detach(host);
 
diff --git a/drivers/ata/sata_highbank.c b/drivers/ata/sata_highbank.c
index 5dba77c..b1ab7d8 100644
--- a/drivers/ata/sata_highbank.c
+++ b/drivers/ata/sata_highbank.c
@@ -418,7 +418,7 @@ static int ahci_highbank_resume(struct device *dev)
 }
 #endif
 
-SIMPLE_DEV_PM_OPS(ahci_highbank_pm_ops,
+static SIMPLE_DEV_PM_OPS(ahci_highbank_pm_ops,
 		  ahci_highbank_suspend, ahci_highbank_resume);
 
 static struct platform_driver ahci_highbank_driver = {
diff --git a/drivers/ata/sata_svw.c b/drivers/ata/sata_svw.c
index 08608de..dc4f701 100644
--- a/drivers/ata/sata_svw.c
+++ b/drivers/ata/sata_svw.c
@@ -322,23 +322,11 @@ static u8 k2_stat_check_status(struct ata_port *ap)
 }
 
 #ifdef CONFIG_PPC_OF
-/*
- * k2_sata_proc_info
- * inout : decides on the direction of the dataflow and the meaning of the
- *	   variables
- * buffer: If inout==FALSE data is being written to it else read from it
- * *start: If inout==FALSE start of the valid data in the buffer
- * offset: If inout==FALSE offset from the beginning of the imaginary file
- *	   from which we start writing into the buffer
- * length: If inout==FALSE max number of bytes to be written into the buffer
- *	   else number of bytes in the buffer
- */
-static int k2_sata_proc_info(struct Scsi_Host *shost, char *page, char **start,
-			     off_t offset, int count, int inout)
+static int k2_sata_show_info(struct seq_file *m, struct Scsi_Host *shost)
 {
 	struct ata_port *ap;
 	struct device_node *np;
-	int len, index;
+	int index;
 
 	/* Find  the ata_port */
 	ap = ata_shost_to_port(shost);
@@ -356,15 +344,12 @@ static int k2_sata_proc_info(struct Scsi_Host *shost, char *page, char **start,
 		const u32 *reg = of_get_property(np, "reg", NULL);
 		if (!reg)
 			continue;
-		if (index == *reg)
+		if (index == *reg) {
+			seq_printf(m, "devspec: %s\n", np->full_name);
 			break;
+		}
 	}
-	if (np == NULL)
-		return 0;
-
-	len = sprintf(page, "devspec: %s\n", np->full_name);
-
-	return len;
+	return 0;
 }
 #endif /* CONFIG_PPC_OF */
 
@@ -372,7 +357,7 @@ static int k2_sata_proc_info(struct Scsi_Host *shost, char *page, char **start,
 static struct scsi_host_template k2_sata_sht = {
 	ATA_BMDMA_SHT(DRV_NAME),
 #ifdef CONFIG_PPC_OF
-	.proc_info		= k2_sata_proc_info,
+	.show_info		= k2_sata_show_info,
 #endif
 };
 
diff --git a/drivers/base/base.h b/drivers/base/base.h
index 6ee17bb..b8bdfe6 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -101,6 +101,8 @@ static inline int hypervisor_init(void) { return 0; }
 extern int platform_bus_init(void);
 extern void cpu_dev_init(void);
 
+struct kobject *virtual_device_parent(struct device *dev);
+
 extern int bus_add_device(struct device *dev);
 extern void bus_probe_device(struct device *dev);
 extern void bus_remove_device(struct device *dev);
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 519865b..1a68f94 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -898,18 +898,18 @@ static ssize_t bus_uevent_store(struct bus_type *bus,
 static BUS_ATTR(uevent, S_IWUSR, NULL, bus_uevent_store);
 
 /**
- * __bus_register - register a driver-core subsystem
+ * bus_register - register a driver-core subsystem
  * @bus: bus to register
- * @key: lockdep class key
  *
  * Once we have that, we register the bus with the kobject
  * infrastructure, then register the children subsystems it has:
  * the devices and drivers that belong to the subsystem.
  */
-int __bus_register(struct bus_type *bus, struct lock_class_key *key)
+int bus_register(struct bus_type *bus)
 {
 	int retval;
 	struct subsys_private *priv;
+	struct lock_class_key *key = &bus->lock_key;
 
 	priv = kzalloc(sizeof(struct subsys_private), GFP_KERNEL);
 	if (!priv)
@@ -981,7 +981,7 @@ out:
 	bus->p = NULL;
 	return retval;
 }
-EXPORT_SYMBOL_GPL(__bus_register);
+EXPORT_SYMBOL_GPL(bus_register);
 
 /**
  * bus_unregister - remove a bus from the system
@@ -1205,26 +1205,10 @@ static void system_root_device_release(struct device *dev)
 {
 	kfree(dev);
 }
-/**
- * subsys_system_register - register a subsystem at /sys/devices/system/
- * @subsys: system subsystem
- * @groups: default attributes for the root device
- *
- * All 'system' subsystems have a /sys/devices/system/<name> root device
- * with the name of the subsystem. The root device can carry subsystem-
- * wide attributes. All registered devices are below this single root
- * device and are named after the subsystem with a simple enumeration
- * number appended. The registered devices are not explicitely named;
- * only 'id' in the device needs to be set.
- *
- * Do not use this interface for anything new, it exists for compatibility
- * with bad ideas only. New subsystems should use plain subsystems; and
- * add the subsystem-wide attributes should be added to the subsystem
- * directory itself and not some create fake root-device placed in
- * /sys/devices/system/<name>.
- */
-int subsys_system_register(struct bus_type *subsys,
-			   const struct attribute_group **groups)
+
+static int subsys_register(struct bus_type *subsys,
+			   const struct attribute_group **groups,
+			   struct kobject *parent_of_root)
 {
 	struct device *dev;
 	int err;
@@ -1243,7 +1227,7 @@ int subsys_system_register(struct bus_type *subsys,
 	if (err < 0)
 		goto err_name;
 
-	dev->kobj.parent = &system_kset->kobj;
+	dev->kobj.parent = parent_of_root;
 	dev->groups = groups;
 	dev->release = system_root_device_release;
 
@@ -1263,8 +1247,55 @@ err_dev:
 	bus_unregister(subsys);
 	return err;
 }
+
+/**
+ * subsys_system_register - register a subsystem at /sys/devices/system/
+ * @subsys: system subsystem
+ * @groups: default attributes for the root device
+ *
+ * All 'system' subsystems have a /sys/devices/system/<name> root device
+ * with the name of the subsystem. The root device can carry subsystem-
+ * wide attributes. All registered devices are below this single root
+ * device and are named after the subsystem with a simple enumeration
+ * number appended. The registered devices are not explicitely named;
+ * only 'id' in the device needs to be set.
+ *
+ * Do not use this interface for anything new, it exists for compatibility
+ * with bad ideas only. New subsystems should use plain subsystems; and
+ * add the subsystem-wide attributes should be added to the subsystem
+ * directory itself and not some create fake root-device placed in
+ * /sys/devices/system/<name>.
+ */
+int subsys_system_register(struct bus_type *subsys,
+			   const struct attribute_group **groups)
+{
+	return subsys_register(subsys, groups, &system_kset->kobj);
+}
 EXPORT_SYMBOL_GPL(subsys_system_register);
 
+/**
+ * subsys_virtual_register - register a subsystem at /sys/devices/virtual/
+ * @subsys: virtual subsystem
+ * @groups: default attributes for the root device
+ *
+ * All 'virtual' subsystems have a /sys/devices/system/<name> root device
+ * with the name of the subystem.  The root device can carry subsystem-wide
+ * attributes.  All registered devices are below this single root device.
+ * There's no restriction on device naming.  This is for kernel software
+ * constructs which need sysfs interface.
+ */
+int subsys_virtual_register(struct bus_type *subsys,
+			    const struct attribute_group **groups)
+{
+	struct kobject *virtual_dir;
+
+	virtual_dir = virtual_device_parent(NULL);
+	if (!virtual_dir)
+		return -ENOMEM;
+
+	return subsys_register(subsys, groups, virtual_dir);
+}
+
 int __init buses_init(void)
 {
 	bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL);
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 56536f4b0..9742057 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -563,8 +563,15 @@ int device_create_file(struct device *dev,
 		       const struct device_attribute *attr)
 {
 	int error = 0;
-	if (dev)
+
+	if (dev) {
+		WARN(((attr->attr.mode & S_IWUGO) && !attr->store),
+				"Write permission without 'store'\n");
+		WARN(((attr->attr.mode & S_IRUGO) && !attr->show),
+				"Read permission without 'show'\n");
 		error = sysfs_create_file(&dev->kobj, &attr->attr);
+	}
+
 	return error;
 }
 
@@ -690,7 +697,7 @@ void device_initialize(struct device *dev)
 	set_dev_node(dev, -1);
 }
 
-static struct kobject *virtual_device_parent(struct device *dev)
+struct kobject *virtual_device_parent(struct device *dev)
 {
 	static struct kobject *virtual_dir = NULL;
 
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index fb10728..d8c7f3e 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -132,6 +132,17 @@ static ssize_t show_crash_notes(struct device *dev, struct device_attribute *att
 	return rc;
 }
 static DEVICE_ATTR(crash_notes, 0400, show_crash_notes, NULL);
+
+static ssize_t show_crash_notes_size(struct device *dev,
+				     struct device_attribute *attr,
+				     char *buf)
+{
+	ssize_t rc;
+
+	rc = sprintf(buf, "%zu\n", sizeof(note_buf_t));
+	return rc;
+}
+static DEVICE_ATTR(crash_notes_size, 0400, show_crash_notes_size, NULL);
 #endif
 
 /*
@@ -259,6 +270,9 @@ int __cpuinit register_cpu(struct cpu *cpu, int num)
 #ifdef CONFIG_KEXEC
 	if (!error)
 		error = device_create_file(&cpu->dev, &dev_attr_crash_notes);
+	if (!error)
+		error = device_create_file(&cpu->dev,
+					   &dev_attr_crash_notes_size);
 #endif
 	return error;
 }
diff --git a/drivers/base/devres.c b/drivers/base/devres.c
index 6683906..507379e 100644
--- a/drivers/base/devres.c
+++ b/drivers/base/devres.c
@@ -671,6 +671,80 @@ int devres_release_group(struct device *dev, void *id)
 EXPORT_SYMBOL_GPL(devres_release_group);
 
 /*
+ * Custom devres actions allow inserting a simple function call
+ * into the teadown sequence.
+ */
+
+struct action_devres {
+	void *data;
+	void (*action)(void *);
+};
+
+static int devm_action_match(struct device *dev, void *res, void *p)
+{
+	struct action_devres *devres = res;
+	struct action_devres *target = p;
+
+	return devres->action == target->action &&
+	       devres->data == target->data;
+}
+
+static void devm_action_release(struct device *dev, void *res)
+{
+	struct action_devres *devres = res;
+
+	devres->action(devres->data);
+}
+
+/**
+ * devm_add_action() - add a custom action to list of managed resources
+ * @dev: Device that owns the action
+ * @action: Function that should be called
+ * @data: Pointer to data passed to @action implementation
+ *
+ * This adds a custom action to the list of managed resources so that
+ * it gets executed as part of standard resource unwinding.
+ */
+int devm_add_action(struct device *dev, void (*action)(void *), void *data)
+{
+	struct action_devres *devres;
+
+	devres = devres_alloc(devm_action_release,
+			      sizeof(struct action_devres), GFP_KERNEL);
+	if (!devres)
+		return -ENOMEM;
+
+	devres->data = data;
+	devres->action = action;
+
+	devres_add(dev, devres);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(devm_add_action);
+
+/**
+ * devm_remove_action() - removes previously added custom action
+ * @dev: Device that owns the action
+ * @action: Function implementing the action
+ * @data: Pointer to data passed to @action implementation
+ *
+ * Removes instance of @action previously added by devm_add_action().
+ * Both action and data should match one of the existing entries.
+ */
+void devm_remove_action(struct device *dev, void (*action)(void *), void *data)
+{
+	struct action_devres devres = {
+		.data = data,
+		.action = action,
+	};
+
+	WARN_ON(devres_destroy(dev, devm_action_release, devm_action_match,
+			       &devres));
+
+}
+EXPORT_SYMBOL_GPL(devm_remove_action);
+
+/*
  * Managed kzalloc/kfree
  */
 static void devm_kzalloc_release(struct device *dev, void *res)
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index c0b8df3..9eda842 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -46,8 +46,8 @@ EXPORT_SYMBOL_GPL(platform_bus);
  * manipulate any relevant information in the pdev_archdata they can do:
  *
  *	platform_device_alloc()
- * 	... manipulate ...
- * 	platform_device_add()
+ *	... manipulate ...
+ *	platform_device_add()
  *
  * And if they don't care they can just call platform_device_register() and
  * everything will just work out.
@@ -326,9 +326,7 @@ int platform_device_add(struct platform_device *pdev)
 		}
 
 		if (p && insert_resource(p, r)) {
-			printk(KERN_ERR
-			       "%s: failed to claim resource %d\n",
-			       dev_name(&pdev->dev), i);
+			dev_err(&pdev->dev, "failed to claim resource %d\n", i);
 			ret = -EBUSY;
 			goto failed;
 		}
@@ -555,7 +553,8 @@ EXPORT_SYMBOL_GPL(platform_driver_unregister);
 /**
  * platform_driver_probe - register driver for non-hotpluggable device
  * @drv: platform driver structure
- * @probe: the driver probe routine, probably from an __init section
+ * @probe: the driver probe routine, probably from an __init section,
+ *         must not return -EPROBE_DEFER.
  *
  * Use this instead of platform_driver_register() when you know the device
  * is not hotpluggable and has already been registered, and you want to
@@ -566,6 +565,9 @@ EXPORT_SYMBOL_GPL(platform_driver_unregister);
  * into system-on-chip processors, where the controller devices have been
  * configured as part of board setup.
  *
+ * This is incompatible with deferred probing so probe() must not
+ * return -EPROBE_DEFER.
+ *
  * Returns zero if the driver registered and bound to a device, else returns
  * a negative error code and with the driver not registered.
  */
@@ -682,7 +684,7 @@ static int platform_uevent(struct device *dev, struct kobj_uevent_env *env)
 	int rc;
 
 	/* Some devices have extra OF data and an OF-style MODALIAS */
-	rc = of_device_uevent_modalias(dev,env);
+	rc = of_device_uevent_modalias(dev, env);
 	if (rc != -ENODEV)
 		return rc;
 
@@ -1126,8 +1128,8 @@ static int __init early_platform_driver_probe_id(char *class_str,
 
 		switch (match_id) {
 		case EARLY_PLATFORM_ID_ERROR:
-			pr_warning("%s: unable to parse %s parameter\n",
-				   class_str, epdrv->pdrv->driver.name);
+			pr_warn("%s: unable to parse %s parameter\n",
+				class_str, epdrv->pdrv->driver.name);
 			/* fall-through */
 		case EARLY_PLATFORM_ID_UNSET:
 			match = NULL;
@@ -1158,8 +1160,8 @@ static int __init early_platform_driver_probe_id(char *class_str,
 			}
 
 			if (epdrv->pdrv->probe(match))
-				pr_warning("%s: unable to probe %s early.\n",
-					   class_str, match->name);
+				pr_warn("%s: unable to probe %s early.\n",
+					class_str, match->name);
 			else
 				n++;
 		}
diff --git a/drivers/base/power/qos.c b/drivers/base/power/qos.c
index 5f74587e..71671c4 100644
--- a/drivers/base/power/qos.c
+++ b/drivers/base/power/qos.c
@@ -46,6 +46,7 @@
 #include "power.h"
 
 static DEFINE_MUTEX(dev_pm_qos_mtx);
+static DEFINE_MUTEX(dev_pm_qos_sysfs_mtx);
 
 static BLOCKING_NOTIFIER_HEAD(dev_pm_notifiers);
 
@@ -216,12 +217,17 @@ void dev_pm_qos_constraints_destroy(struct device *dev)
 	struct pm_qos_constraints *c;
 	struct pm_qos_flags *f;
 
-	mutex_lock(&dev_pm_qos_mtx);
+	mutex_lock(&dev_pm_qos_sysfs_mtx);
 
 	/*
 	 * If the device's PM QoS resume latency limit or PM QoS flags have been
 	 * exposed to user space, they have to be hidden at this point.
 	 */
+	pm_qos_sysfs_remove_latency(dev);
+	pm_qos_sysfs_remove_flags(dev);
+
+	mutex_lock(&dev_pm_qos_mtx);
+
 	__dev_pm_qos_hide_latency_limit(dev);
 	__dev_pm_qos_hide_flags(dev);
 
@@ -254,6 +260,8 @@ void dev_pm_qos_constraints_destroy(struct device *dev)
 
  out:
 	mutex_unlock(&dev_pm_qos_mtx);
+
+	mutex_unlock(&dev_pm_qos_sysfs_mtx);
 }
 
 /**
@@ -558,6 +566,14 @@ static void __dev_pm_qos_drop_user_request(struct device *dev,
 	kfree(req);
 }
 
+static void dev_pm_qos_drop_user_request(struct device *dev,
+					 enum dev_pm_qos_req_type type)
+{
+	mutex_lock(&dev_pm_qos_mtx);
+	__dev_pm_qos_drop_user_request(dev, type);
+	mutex_unlock(&dev_pm_qos_mtx);
+}
+
 /**
  * dev_pm_qos_expose_latency_limit - Expose PM QoS latency limit to user space.
  * @dev: Device whose PM QoS latency limit is to be exposed to user space.
@@ -581,6 +597,8 @@ int dev_pm_qos_expose_latency_limit(struct device *dev, s32 value)
 		return ret;
 	}
 
+	mutex_lock(&dev_pm_qos_sysfs_mtx);
+
 	mutex_lock(&dev_pm_qos_mtx);
 
 	if (IS_ERR_OR_NULL(dev->power.qos))
@@ -591,26 +609,27 @@ int dev_pm_qos_expose_latency_limit(struct device *dev, s32 value)
 	if (ret < 0) {
 		__dev_pm_qos_remove_request(req);
 		kfree(req);
+		mutex_unlock(&dev_pm_qos_mtx);
 		goto out;
 	}
-
 	dev->power.qos->latency_req = req;
+
+	mutex_unlock(&dev_pm_qos_mtx);
+
 	ret = pm_qos_sysfs_add_latency(dev);
 	if (ret)
-		__dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_LATENCY);
+		dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_LATENCY);
 
  out:
-	mutex_unlock(&dev_pm_qos_mtx);
+	mutex_unlock(&dev_pm_qos_sysfs_mtx);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(dev_pm_qos_expose_latency_limit);
 
 static void __dev_pm_qos_hide_latency_limit(struct device *dev)
 {
-	if (!IS_ERR_OR_NULL(dev->power.qos) && dev->power.qos->latency_req) {
-		pm_qos_sysfs_remove_latency(dev);
+	if (!IS_ERR_OR_NULL(dev->power.qos) && dev->power.qos->latency_req)
 		__dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_LATENCY);
-	}
 }
 
 /**
@@ -619,9 +638,15 @@ static void __dev_pm_qos_hide_latency_limit(struct device *dev)
  */
 void dev_pm_qos_hide_latency_limit(struct device *dev)
 {
+	mutex_lock(&dev_pm_qos_sysfs_mtx);
+
+	pm_qos_sysfs_remove_latency(dev);
+
 	mutex_lock(&dev_pm_qos_mtx);
 	__dev_pm_qos_hide_latency_limit(dev);
 	mutex_unlock(&dev_pm_qos_mtx);
+
+	mutex_unlock(&dev_pm_qos_sysfs_mtx);
 }
 EXPORT_SYMBOL_GPL(dev_pm_qos_hide_latency_limit);
 
@@ -649,6 +674,8 @@ int dev_pm_qos_expose_flags(struct device *dev, s32 val)
 	}
 
 	pm_runtime_get_sync(dev);
+	mutex_lock(&dev_pm_qos_sysfs_mtx);
+
 	mutex_lock(&dev_pm_qos_mtx);
 
 	if (IS_ERR_OR_NULL(dev->power.qos))
@@ -659,16 +686,19 @@ int dev_pm_qos_expose_flags(struct device *dev, s32 val)
 	if (ret < 0) {
 		__dev_pm_qos_remove_request(req);
 		kfree(req);
+		mutex_unlock(&dev_pm_qos_mtx);
 		goto out;
 	}
-
 	dev->power.qos->flags_req = req;
+
+	mutex_unlock(&dev_pm_qos_mtx);
+
 	ret = pm_qos_sysfs_add_flags(dev);
 	if (ret)
-		__dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_FLAGS);
+		dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_FLAGS);
 
  out:
-	mutex_unlock(&dev_pm_qos_mtx);
+	mutex_unlock(&dev_pm_qos_sysfs_mtx);
 	pm_runtime_put(dev);
 	return ret;
 }
@@ -676,10 +706,8 @@ EXPORT_SYMBOL_GPL(dev_pm_qos_expose_flags);
 
 static void __dev_pm_qos_hide_flags(struct device *dev)
 {
-	if (!IS_ERR_OR_NULL(dev->power.qos) && dev->power.qos->flags_req) {
-		pm_qos_sysfs_remove_flags(dev);
+	if (!IS_ERR_OR_NULL(dev->power.qos) && dev->power.qos->flags_req)
 		__dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_FLAGS);
-	}
 }
 
 /**
@@ -689,9 +717,15 @@ static void __dev_pm_qos_hide_flags(struct device *dev)
 void dev_pm_qos_hide_flags(struct device *dev)
 {
 	pm_runtime_get_sync(dev);
+	mutex_lock(&dev_pm_qos_sysfs_mtx);
+
+	pm_qos_sysfs_remove_flags(dev);
+
 	mutex_lock(&dev_pm_qos_mtx);
 	__dev_pm_qos_hide_flags(dev);
 	mutex_unlock(&dev_pm_qos_mtx);
+
+	mutex_unlock(&dev_pm_qos_sysfs_mtx);
 	pm_runtime_put(dev);
 }
 EXPORT_SYMBOL_GPL(dev_pm_qos_hide_flags);
diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h
index 5a22bd3..c130536 100644
--- a/drivers/base/regmap/internal.h
+++ b/drivers/base/regmap/internal.h
@@ -38,7 +38,8 @@ struct regmap_format {
 			     unsigned int reg, unsigned int val);
 	void (*format_reg)(void *buf, unsigned int reg, unsigned int shift);
 	void (*format_val)(void *buf, unsigned int val, unsigned int shift);
-	unsigned int (*parse_val)(void *buf);
+	unsigned int (*parse_val)(const void *buf);
+	void (*parse_inplace)(void *buf);
 };
 
 struct regmap_async {
@@ -76,6 +77,7 @@ struct regmap {
 	unsigned int debugfs_tot_len;
 
 	struct list_head debugfs_off_cache;
+	struct mutex cache_lock;
 #endif
 
 	unsigned int max_register;
@@ -125,6 +127,9 @@ struct regmap {
 	void *cache;
 	u32 cache_dirty;
 
+	unsigned long *cache_present;
+	unsigned int cache_present_nbits;
+
 	struct reg_default *patch;
 	int patch_regs;
 
@@ -187,12 +192,35 @@ int regcache_read(struct regmap *map,
 int regcache_write(struct regmap *map,
 			unsigned int reg, unsigned int value);
 int regcache_sync(struct regmap *map);
-
-unsigned int regcache_get_val(const void *base, unsigned int idx,
-			      unsigned int word_size);
-bool regcache_set_val(void *base, unsigned int idx,
-		      unsigned int val, unsigned int word_size);
+int regcache_sync_block(struct regmap *map, void *block,
+			unsigned int block_base, unsigned int start,
+			unsigned int end);
+
+static inline const void *regcache_get_val_addr(struct regmap *map,
+						const void *base,
+						unsigned int idx)
+{
+	return base + (map->cache_word_size * idx);
+}
+
+unsigned int regcache_get_val(struct regmap *map, const void *base,
+			      unsigned int idx);
+bool regcache_set_val(struct regmap *map, void *base, unsigned int idx,
+		      unsigned int val);
 int regcache_lookup_reg(struct regmap *map, unsigned int reg);
+int regcache_set_reg_present(struct regmap *map, unsigned int reg);
+
+static inline bool regcache_reg_present(struct regmap *map, unsigned int reg)
+{
+	if (!map->cache_present)
+		return true;
+	if (reg > map->cache_present_nbits)
+		return false;
+	return map->cache_present[BIT_WORD(reg)] & BIT_MASK(reg);
+}
+
+int _regmap_raw_write(struct regmap *map, unsigned int reg,
+		      const void *val, size_t val_len, bool async);
 
 void regmap_async_complete_cb(struct regmap_async *async, int ret);
 
diff --git a/drivers/base/regmap/regcache-lzo.c b/drivers/base/regmap/regcache-lzo.c
index afd6aa9..e210a6d 100644
--- a/drivers/base/regmap/regcache-lzo.c
+++ b/drivers/base/regmap/regcache-lzo.c
@@ -260,8 +260,7 @@ static int regcache_lzo_read(struct regmap *map,
 	ret = regcache_lzo_decompress_cache_block(map, lzo_block);
 	if (ret >= 0)
 		/* fetch the value from the cache */
-		*value = regcache_get_val(lzo_block->dst, blkpos,
-					  map->cache_word_size);
+		*value = regcache_get_val(map, lzo_block->dst, blkpos);
 
 	kfree(lzo_block->dst);
 	/* restore the pointer and length of the compressed block */
@@ -304,8 +303,7 @@ static int regcache_lzo_write(struct regmap *map,
 	}
 
 	/* write the new value to the cache */
-	if (regcache_set_val(lzo_block->dst, blkpos, value,
-			     map->cache_word_size)) {
+	if (regcache_set_val(map, lzo_block->dst, blkpos, value)) {
 		kfree(lzo_block->dst);
 		goto out;
 	}
diff --git a/drivers/base/regmap/regcache-rbtree.c b/drivers/base/regmap/regcache-rbtree.c
index e6732cf..aa0875f 100644
--- a/drivers/base/regmap/regcache-rbtree.c
+++ b/drivers/base/regmap/regcache-rbtree.c
@@ -47,22 +47,21 @@ static inline void regcache_rbtree_get_base_top_reg(
 	*top = rbnode->base_reg + ((rbnode->blklen - 1) * map->reg_stride);
 }
 
-static unsigned int regcache_rbtree_get_register(
-	struct regcache_rbtree_node *rbnode, unsigned int idx,
-	unsigned int word_size)
+static unsigned int regcache_rbtree_get_register(struct regmap *map,
+	struct regcache_rbtree_node *rbnode, unsigned int idx)
 {
-	return regcache_get_val(rbnode->block, idx, word_size);
+	return regcache_get_val(map, rbnode->block, idx);
 }
 
-static void regcache_rbtree_set_register(struct regcache_rbtree_node *rbnode,
-					 unsigned int idx, unsigned int val,
-					 unsigned int word_size)
+static void regcache_rbtree_set_register(struct regmap *map,
+					 struct regcache_rbtree_node *rbnode,
+					 unsigned int idx, unsigned int val)
 {
-	regcache_set_val(rbnode->block, idx, val, word_size);
+	regcache_set_val(map, rbnode->block, idx, val);
 }
 
 static struct regcache_rbtree_node *regcache_rbtree_lookup(struct regmap *map,
-	unsigned int reg)
+							   unsigned int reg)
 {
 	struct regcache_rbtree_ctx *rbtree_ctx = map->cache;
 	struct rb_node *node;
@@ -139,15 +138,21 @@ static int rbtree_show(struct seq_file *s, void *ignored)
 	struct regcache_rbtree_node *n;
 	struct rb_node *node;
 	unsigned int base, top;
+	size_t mem_size;
 	int nodes = 0;
 	int registers = 0;
 	int this_registers, average;
 
 	map->lock(map);
 
+	mem_size = sizeof(*rbtree_ctx);
+	mem_size += BITS_TO_LONGS(map->cache_present_nbits) * sizeof(long);
+
 	for (node = rb_first(&rbtree_ctx->root); node != NULL;
 	     node = rb_next(node)) {
 		n = container_of(node, struct regcache_rbtree_node, node);
+		mem_size += sizeof(*n);
+		mem_size += (n->blklen * map->cache_word_size);
 
 		regcache_rbtree_get_base_top_reg(map, n, &base, &top);
 		this_registers = ((top - base) / map->reg_stride) + 1;
@@ -162,8 +167,8 @@ static int rbtree_show(struct seq_file *s, void *ignored)
 	else
 		average = 0;
 
-	seq_printf(s, "%d nodes, %d registers, average %d registers\n",
-		   nodes, registers, average);
+	seq_printf(s, "%d nodes, %d registers, average %d registers, used %zu bytes\n",
+		   nodes, registers, average, mem_size);
 
 	map->unlock(map);
 
@@ -260,8 +265,9 @@ static int regcache_rbtree_read(struct regmap *map,
 	rbnode = regcache_rbtree_lookup(map, reg);
 	if (rbnode) {
 		reg_tmp = (reg - rbnode->base_reg) / map->reg_stride;
-		*value = regcache_rbtree_get_register(rbnode, reg_tmp,
-						      map->cache_word_size);
+		if (!regcache_reg_present(map, reg))
+			return -ENOENT;
+		*value = regcache_rbtree_get_register(map, rbnode, reg_tmp);
 	} else {
 		return -ENOENT;
 	}
@@ -270,21 +276,23 @@ static int regcache_rbtree_read(struct regmap *map,
 }
 
 
-static int regcache_rbtree_insert_to_block(struct regcache_rbtree_node *rbnode,
+static int regcache_rbtree_insert_to_block(struct regmap *map,
+					   struct regcache_rbtree_node *rbnode,
 					   unsigned int pos, unsigned int reg,
-					   unsigned int value, unsigned int word_size)
+					   unsigned int value)
 {
 	u8 *blk;
 
 	blk = krealloc(rbnode->block,
-		       (rbnode->blklen + 1) * word_size, GFP_KERNEL);
+		       (rbnode->blklen + 1) * map->cache_word_size,
+		       GFP_KERNEL);
 	if (!blk)
 		return -ENOMEM;
 
 	/* insert the register value in the correct place in the rbnode block */
-	memmove(blk + (pos + 1) * word_size,
-		blk + pos * word_size,
-		(rbnode->blklen - pos) * word_size);
+	memmove(blk + (pos + 1) * map->cache_word_size,
+		blk + pos * map->cache_word_size,
+		(rbnode->blklen - pos) * map->cache_word_size);
 
 	/* update the rbnode block, its size and the base register */
 	rbnode->block = blk;
@@ -292,7 +300,7 @@ static int regcache_rbtree_insert_to_block(struct regcache_rbtree_node *rbnode,
 	if (!pos)
 		rbnode->base_reg = reg;
 
-	regcache_rbtree_set_register(rbnode, pos, value, word_size);
+	regcache_rbtree_set_register(map, rbnode, pos, value);
 	return 0;
 }
 
@@ -302,25 +310,24 @@ static int regcache_rbtree_write(struct regmap *map, unsigned int reg,
 	struct regcache_rbtree_ctx *rbtree_ctx;
 	struct regcache_rbtree_node *rbnode, *rbnode_tmp;
 	struct rb_node *node;
-	unsigned int val;
 	unsigned int reg_tmp;
 	unsigned int pos;
 	int i;
 	int ret;
 
 	rbtree_ctx = map->cache;
+	/* update the reg_present bitmap, make space if necessary */
+	ret = regcache_set_reg_present(map, reg);
+	if (ret < 0)
+		return ret;
+
 	/* if we can't locate it in the cached rbnode we'll have
 	 * to traverse the rbtree looking for it.
 	 */
 	rbnode = regcache_rbtree_lookup(map, reg);
 	if (rbnode) {
 		reg_tmp = (reg - rbnode->base_reg) / map->reg_stride;
-		val = regcache_rbtree_get_register(rbnode, reg_tmp,
-						   map->cache_word_size);
-		if (val == value)
-			return 0;
-		regcache_rbtree_set_register(rbnode, reg_tmp, value,
-					     map->cache_word_size);
+		regcache_rbtree_set_register(map, rbnode, reg_tmp, value);
 	} else {
 		/* look for an adjacent register to the one we are about to add */
 		for (node = rb_first(&rbtree_ctx->root); node;
@@ -337,9 +344,10 @@ static int regcache_rbtree_write(struct regmap *map, unsigned int reg,
 					pos = i + 1;
 				else
 					pos = i;
-				ret = regcache_rbtree_insert_to_block(rbnode_tmp, pos,
-								      reg, value,
-								      map->cache_word_size);
+				ret = regcache_rbtree_insert_to_block(map,
+								      rbnode_tmp,
+								      pos, reg,
+								      value);
 				if (ret)
 					return ret;
 				rbtree_ctx->cached_rbnode = rbnode_tmp;
@@ -354,7 +362,7 @@ static int regcache_rbtree_write(struct regmap *map, unsigned int reg,
 		rbnode = kzalloc(sizeof *rbnode, GFP_KERNEL);
 		if (!rbnode)
 			return -ENOMEM;
-		rbnode->blklen = 1;
+		rbnode->blklen = sizeof(*rbnode);
 		rbnode->base_reg = reg;
 		rbnode->block = kmalloc(rbnode->blklen * map->cache_word_size,
 					GFP_KERNEL);
@@ -362,7 +370,7 @@ static int regcache_rbtree_write(struct regmap *map, unsigned int reg,
 			kfree(rbnode);
 			return -ENOMEM;
 		}
-		regcache_rbtree_set_register(rbnode, 0, value, map->cache_word_size);
+		regcache_rbtree_set_register(map, rbnode, 0, value);
 		regcache_rbtree_insert(map, &rbtree_ctx->root, rbnode);
 		rbtree_ctx->cached_rbnode = rbnode;
 	}
@@ -376,10 +384,8 @@ static int regcache_rbtree_sync(struct regmap *map, unsigned int min,
 	struct regcache_rbtree_ctx *rbtree_ctx;
 	struct rb_node *node;
 	struct regcache_rbtree_node *rbnode;
-	unsigned int regtmp;
-	unsigned int val;
 	int ret;
-	int i, base, end;
+	int base, end;
 
 	rbtree_ctx = map->cache;
 	for (node = rb_first(&rbtree_ctx->root); node; node = rb_next(node)) {
@@ -398,31 +404,17 @@ static int regcache_rbtree_sync(struct regmap *map, unsigned int min,
 			base = 0;
 
 		if (max < rbnode->base_reg + rbnode->blklen)
-			end = rbnode->base_reg + rbnode->blklen - max;
+			end = max - rbnode->base_reg + 1;
 		else
 			end = rbnode->blklen;
 
-		for (i = base; i < end; i++) {
-			regtmp = rbnode->base_reg + (i * map->reg_stride);
-			val = regcache_rbtree_get_register(rbnode, i,
-							   map->cache_word_size);
-
-			/* Is this the hardware default?  If so skip. */
-			ret = regcache_lookup_reg(map, regtmp);
-			if (ret >= 0 && val == map->reg_defaults[ret].def)
-				continue;
-
-			map->cache_bypass = 1;
-			ret = _regmap_write(map, regtmp, val);
-			map->cache_bypass = 0;
-			if (ret)
-				return ret;
-			dev_dbg(map->dev, "Synced register %#x, value %#x\n",
-				regtmp, val);
-		}
+		ret = regcache_sync_block(map, rbnode->block, rbnode->base_reg,
+					  base, end);
+		if (ret != 0)
+			return ret;
 	}
 
-	return 0;
+	return regmap_async_complete(map);
 }
 
 struct regcache_ops regcache_rbtree_ops = {
diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c
index e69ff3e..d81f605 100644
--- a/drivers/base/regmap/regcache.c
+++ b/drivers/base/regmap/regcache.c
@@ -45,8 +45,8 @@ static int regcache_hw_init(struct regmap *map)
 		tmp_buf = kmalloc(map->cache_size_raw, GFP_KERNEL);
 		if (!tmp_buf)
 			return -EINVAL;
-		ret = regmap_bulk_read(map, 0, tmp_buf,
-				       map->num_reg_defaults_raw);
+		ret = regmap_raw_read(map, 0, tmp_buf,
+				      map->num_reg_defaults_raw);
 		map->cache_bypass = cache_bypass;
 		if (ret < 0) {
 			kfree(tmp_buf);
@@ -58,8 +58,7 @@ static int regcache_hw_init(struct regmap *map)
 
 	/* calculate the size of reg_defaults */
 	for (count = 0, i = 0; i < map->num_reg_defaults_raw; i++) {
-		val = regcache_get_val(map->reg_defaults_raw,
-				       i, map->cache_word_size);
+		val = regcache_get_val(map, map->reg_defaults_raw, i);
 		if (regmap_volatile(map, i * map->reg_stride))
 			continue;
 		count++;
@@ -75,8 +74,7 @@ static int regcache_hw_init(struct regmap *map)
 	/* fill the reg_defaults */
 	map->num_reg_defaults = count;
 	for (i = 0, j = 0; i < map->num_reg_defaults_raw; i++) {
-		val = regcache_get_val(map->reg_defaults_raw,
-				       i, map->cache_word_size);
+		val = regcache_get_val(map, map->reg_defaults_raw, i);
 		if (regmap_volatile(map, i * map->reg_stride))
 			continue;
 		map->reg_defaults[j].reg = i * map->reg_stride;
@@ -123,6 +121,8 @@ int regcache_init(struct regmap *map, const struct regmap_config *config)
 	map->reg_defaults_raw = config->reg_defaults_raw;
 	map->cache_word_size = DIV_ROUND_UP(config->val_bits, 8);
 	map->cache_size_raw = map->cache_word_size * config->num_reg_defaults_raw;
+	map->cache_present = NULL;
+	map->cache_present_nbits = 0;
 
 	map->cache = NULL;
 	map->cache_ops = cache_types[i];
@@ -181,6 +181,7 @@ void regcache_exit(struct regmap *map)
 
 	BUG_ON(!map->cache_ops);
 
+	kfree(map->cache_present);
 	kfree(map->reg_defaults);
 	if (map->cache_free)
 		kfree(map->reg_defaults_raw);
@@ -417,28 +418,68 @@ void regcache_cache_bypass(struct regmap *map, bool enable)
 }
 EXPORT_SYMBOL_GPL(regcache_cache_bypass);
 
-bool regcache_set_val(void *base, unsigned int idx,
-		      unsigned int val, unsigned int word_size)
+int regcache_set_reg_present(struct regmap *map, unsigned int reg)
 {
-	switch (word_size) {
+	unsigned long *cache_present;
+	unsigned int cache_present_size;
+	unsigned int nregs;
+	int i;
+
+	nregs = reg + 1;
+	cache_present_size = BITS_TO_LONGS(nregs);
+	cache_present_size *= sizeof(long);
+
+	if (!map->cache_present) {
+		cache_present = kmalloc(cache_present_size, GFP_KERNEL);
+		if (!cache_present)
+			return -ENOMEM;
+		bitmap_zero(cache_present, nregs);
+		map->cache_present = cache_present;
+		map->cache_present_nbits = nregs;
+	}
+
+	if (nregs > map->cache_present_nbits) {
+		cache_present = krealloc(map->cache_present,
+					 cache_present_size, GFP_KERNEL);
+		if (!cache_present)
+			return -ENOMEM;
+		for (i = 0; i < nregs; i++)
+			if (i >= map->cache_present_nbits)
+				clear_bit(i, cache_present);
+		map->cache_present = cache_present;
+		map->cache_present_nbits = nregs;
+	}
+
+	set_bit(reg, map->cache_present);
+	return 0;
+}
+
+bool regcache_set_val(struct regmap *map, void *base, unsigned int idx,
+		      unsigned int val)
+{
+	if (regcache_get_val(map, base, idx) == val)
+		return true;
+
+	/* Use device native format if possible */
+	if (map->format.format_val) {
+		map->format.format_val(base + (map->cache_word_size * idx),
+				       val, 0);
+		return false;
+	}
+
+	switch (map->cache_word_size) {
 	case 1: {
 		u8 *cache = base;
-		if (cache[idx] == val)
-			return true;
 		cache[idx] = val;
 		break;
 	}
 	case 2: {
 		u16 *cache = base;
-		if (cache[idx] == val)
-			return true;
 		cache[idx] = val;
 		break;
 	}
 	case 4: {
 		u32 *cache = base;
-		if (cache[idx] == val)
-			return true;
 		cache[idx] = val;
 		break;
 	}
@@ -448,13 +489,18 @@ bool regcache_set_val(void *base, unsigned int idx,
 	return false;
 }
 
-unsigned int regcache_get_val(const void *base, unsigned int idx,
-			      unsigned int word_size)
+unsigned int regcache_get_val(struct regmap *map, const void *base,
+			      unsigned int idx)
 {
 	if (!base)
 		return -EINVAL;
 
-	switch (word_size) {
+	/* Use device native format if possible */
+	if (map->format.parse_val)
+		return map->format.parse_val(regcache_get_val_addr(map, base,
+								   idx));
+
+	switch (map->cache_word_size) {
 	case 1: {
 		const u8 *cache = base;
 		return cache[idx];
@@ -498,3 +544,117 @@ int regcache_lookup_reg(struct regmap *map, unsigned int reg)
 	else
 		return -ENOENT;
 }
+
+static int regcache_sync_block_single(struct regmap *map, void *block,
+				      unsigned int block_base,
+				      unsigned int start, unsigned int end)
+{
+	unsigned int i, regtmp, val;
+	int ret;
+
+	for (i = start; i < end; i++) {
+		regtmp = block_base + (i * map->reg_stride);
+
+		if (!regcache_reg_present(map, regtmp))
+			continue;
+
+		val = regcache_get_val(map, block, i);
+
+		/* Is this the hardware default?  If so skip. */
+		ret = regcache_lookup_reg(map, regtmp);
+		if (ret >= 0 && val == map->reg_defaults[ret].def)
+			continue;
+
+		map->cache_bypass = 1;
+
+		ret = _regmap_write(map, regtmp, val);
+
+		map->cache_bypass = 0;
+		if (ret != 0)
+			return ret;
+		dev_dbg(map->dev, "Synced register %#x, value %#x\n",
+			regtmp, val);
+	}
+
+	return 0;
+}
+
+static int regcache_sync_block_raw_flush(struct regmap *map, const void **data,
+					 unsigned int base, unsigned int cur)
+{
+	size_t val_bytes = map->format.val_bytes;
+	int ret, count;
+
+	if (*data == NULL)
+		return 0;
+
+	count = cur - base;
+
+	dev_dbg(map->dev, "Writing %d bytes for %d registers from 0x%x-0x%x\n",
+		count * val_bytes, count, base, cur - 1);
+
+	map->cache_bypass = 1;
+
+	ret = _regmap_raw_write(map, base, *data, count * val_bytes,
+				false);
+
+	map->cache_bypass = 0;
+
+	*data = NULL;
+
+	return ret;
+}
+
+int regcache_sync_block_raw(struct regmap *map, void *block,
+			    unsigned int block_base, unsigned int start,
+			    unsigned int end)
+{
+	unsigned int i, val;
+	unsigned int regtmp = 0;
+	unsigned int base = 0;
+	const void *data = NULL;
+	int ret;
+
+	for (i = start; i < end; i++) {
+		regtmp = block_base + (i * map->reg_stride);
+
+		if (!regcache_reg_present(map, regtmp)) {
+			ret = regcache_sync_block_raw_flush(map, &data,
+							    base, regtmp);
+			if (ret != 0)
+				return ret;
+			continue;
+		}
+
+		val = regcache_get_val(map, block, i);
+
+		/* Is this the hardware default?  If so skip. */
+		ret = regcache_lookup_reg(map, regtmp);
+		if (ret >= 0 && val == map->reg_defaults[ret].def) {
+			ret = regcache_sync_block_raw_flush(map, &data,
+							    base, regtmp);
+			if (ret != 0)
+				return ret;
+			continue;
+		}
+
+		if (!data) {
+			data = regcache_get_val_addr(map, block, i);
+			base = regtmp;
+		}
+	}
+
+	return regcache_sync_block_raw_flush(map, &data, base, regtmp);
+}
+
+int regcache_sync_block(struct regmap *map, void *block,
+			unsigned int block_base, unsigned int start,
+			unsigned int end)
+{
+	if (regmap_can_raw_write(map))
+		return regcache_sync_block_raw(map, block, block_base,
+					       start, end);
+	else
+		return regcache_sync_block_single(map, block, block_base,
+						  start, end);
+}
diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c
index 81d6f60..23b701f 100644
--- a/drivers/base/regmap/regmap-debugfs.c
+++ b/drivers/base/regmap/regmap-debugfs.c
@@ -88,16 +88,16 @@ static unsigned int regmap_debugfs_get_dump_start(struct regmap *map,
 	 * If we don't have a cache build one so we don't have to do a
 	 * linear scan each time.
 	 */
+	mutex_lock(&map->cache_lock);
+	i = base;
 	if (list_empty(&map->debugfs_off_cache)) {
-		for (i = base; i <= map->max_register; i += map->reg_stride) {
+		for (; i <= map->max_register; i += map->reg_stride) {
 			/* Skip unprinted registers, closing off cache entry */
 			if (!regmap_readable(map, i) ||
 			    regmap_precious(map, i)) {
 				if (c) {
 					c->max = p - 1;
-					fpos_offset = c->max - c->min;
-					reg_offset = fpos_offset / map->debugfs_tot_len;
-					c->max_reg = c->base_reg + reg_offset;
+					c->max_reg = i - map->reg_stride;
 					list_add_tail(&c->list,
 						      &map->debugfs_off_cache);
 					c = NULL;
@@ -111,6 +111,7 @@ static unsigned int regmap_debugfs_get_dump_start(struct regmap *map,
 				c = kzalloc(sizeof(*c), GFP_KERNEL);
 				if (!c) {
 					regmap_debugfs_free_dump_cache(map);
+					mutex_unlock(&map->cache_lock);
 					return base;
 				}
 				c->min = p;
@@ -124,9 +125,7 @@ static unsigned int regmap_debugfs_get_dump_start(struct regmap *map,
 	/* Close the last entry off if we didn't scan beyond it */
 	if (c) {
 		c->max = p - 1;
-		fpos_offset = c->max - c->min;
-		reg_offset = fpos_offset / map->debugfs_tot_len;
-		c->max_reg = c->base_reg + reg_offset;
+		c->max_reg = i - map->reg_stride;
 		list_add_tail(&c->list,
 			      &map->debugfs_off_cache);
 	}
@@ -145,12 +144,14 @@ static unsigned int regmap_debugfs_get_dump_start(struct regmap *map,
 			fpos_offset = from - c->min;
 			reg_offset = fpos_offset / map->debugfs_tot_len;
 			*pos = c->min + (reg_offset * map->debugfs_tot_len);
+			mutex_unlock(&map->cache_lock);
 			return c->base_reg + reg_offset;
 		}
 
 		*pos = c->max;
 		ret = c->max_reg;
 	}
+	mutex_unlock(&map->cache_lock);
 
 	return ret;
 }
@@ -311,6 +312,79 @@ static const struct file_operations regmap_range_fops = {
 	.llseek = default_llseek,
 };
 
+static ssize_t regmap_reg_ranges_read_file(struct file *file,
+					   char __user *user_buf, size_t count,
+					   loff_t *ppos)
+{
+	struct regmap *map = file->private_data;
+	struct regmap_debugfs_off_cache *c;
+	loff_t p = 0;
+	size_t buf_pos = 0;
+	char *buf;
+	char *entry;
+	int ret;
+
+	if (*ppos < 0 || !count)
+		return -EINVAL;
+
+	buf = kmalloc(count, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	entry = kmalloc(PAGE_SIZE, GFP_KERNEL);
+	if (!entry) {
+		kfree(buf);
+		return -ENOMEM;
+	}
+
+	/* While we are at it, build the register dump cache
+	 * now so the read() operation on the `registers' file
+	 * can benefit from using the cache.  We do not care
+	 * about the file position information that is contained
+	 * in the cache, just about the actual register blocks */
+	regmap_calc_tot_len(map, buf, count);
+	regmap_debugfs_get_dump_start(map, 0, *ppos, &p);
+
+	/* Reset file pointer as the fixed-format of the `registers'
+	 * file is not compatible with the `range' file */
+	p = 0;
+	mutex_lock(&map->cache_lock);
+	list_for_each_entry(c, &map->debugfs_off_cache, list) {
+		snprintf(entry, PAGE_SIZE, "%x-%x",
+			 c->base_reg, c->max_reg);
+		if (p >= *ppos) {
+			if (buf_pos + 1 + strlen(entry) > count)
+				break;
+			snprintf(buf + buf_pos, count - buf_pos,
+				 "%s", entry);
+			buf_pos += strlen(entry);
+			buf[buf_pos] = '\n';
+			buf_pos++;
+		}
+		p += strlen(entry) + 1;
+	}
+	mutex_unlock(&map->cache_lock);
+
+	kfree(entry);
+	ret = buf_pos;
+
+	if (copy_to_user(user_buf, buf, buf_pos)) {
+		ret = -EFAULT;
+		goto out_buf;
+	}
+
+	*ppos += buf_pos;
+out_buf:
+	kfree(buf);
+	return ret;
+}
+
+static const struct file_operations regmap_reg_ranges_fops = {
+	.open = simple_open,
+	.read = regmap_reg_ranges_read_file,
+	.llseek = default_llseek,
+};
+
 static ssize_t regmap_access_read_file(struct file *file,
 				       char __user *user_buf, size_t count,
 				       loff_t *ppos)
@@ -385,6 +459,7 @@ void regmap_debugfs_init(struct regmap *map, const char *name)
 	struct regmap_range_node *range_node;
 
 	INIT_LIST_HEAD(&map->debugfs_off_cache);
+	mutex_init(&map->cache_lock);
 
 	if (name) {
 		map->debugfs_name = kasprintf(GFP_KERNEL, "%s-%s",
@@ -403,6 +478,9 @@ void regmap_debugfs_init(struct regmap *map, const char *name)
 	debugfs_create_file("name", 0400, map->debugfs,
 			    map, &regmap_name_fops);
 
+	debugfs_create_file("range", 0400, map->debugfs,
+			    map, &regmap_reg_ranges_fops);
+
 	if (map->max_register) {
 		debugfs_create_file("registers", 0400, map->debugfs,
 				    map, &regmap_map_fops);
@@ -435,7 +513,9 @@ void regmap_debugfs_init(struct regmap *map, const char *name)
 void regmap_debugfs_exit(struct regmap *map)
 {
 	debugfs_remove_recursive(map->debugfs);
+	mutex_lock(&map->cache_lock);
 	regmap_debugfs_free_dump_cache(map);
+	mutex_unlock(&map->cache_lock);
 	kfree(map->debugfs_name);
 }
 
diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c
index 020ea2b..1643e88 100644
--- a/drivers/base/regmap/regmap-irq.c
+++ b/drivers/base/regmap/regmap-irq.c
@@ -460,7 +460,8 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
 	ret = request_threaded_irq(irq, NULL, regmap_irq_thread, irq_flags,
 				   chip->name, d);
 	if (ret != 0) {
-		dev_err(map->dev, "Failed to request IRQ %d: %d\n", irq, ret);
+		dev_err(map->dev, "Failed to request IRQ %d for %s: %d\n",
+			irq, chip->name, ret);
 		goto err_domain;
 	}
 
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index 3d23675..a941dcf 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -228,30 +228,39 @@ static void regmap_format_32_native(void *buf, unsigned int val,
 	*(u32 *)buf = val << shift;
 }
 
-static unsigned int regmap_parse_8(void *buf)
+static void regmap_parse_inplace_noop(void *buf)
 {
-	u8 *b = buf;
+}
+
+static unsigned int regmap_parse_8(const void *buf)
+{
+	const u8 *b = buf;
 
 	return b[0];
 }
 
-static unsigned int regmap_parse_16_be(void *buf)
+static unsigned int regmap_parse_16_be(const void *buf)
+{
+	const __be16 *b = buf;
+
+	return be16_to_cpu(b[0]);
+}
+
+static void regmap_parse_16_be_inplace(void *buf)
 {
 	__be16 *b = buf;
 
 	b[0] = be16_to_cpu(b[0]);
-
-	return b[0];
 }
 
-static unsigned int regmap_parse_16_native(void *buf)
+static unsigned int regmap_parse_16_native(const void *buf)
 {
 	return *(u16 *)buf;
 }
 
-static unsigned int regmap_parse_24(void *buf)
+static unsigned int regmap_parse_24(const void *buf)
 {
-	u8 *b = buf;
+	const u8 *b = buf;
 	unsigned int ret = b[2];
 	ret |= ((unsigned int)b[1]) << 8;
 	ret |= ((unsigned int)b[0]) << 16;
@@ -259,16 +268,21 @@ static unsigned int regmap_parse_24(void *buf)
 	return ret;
 }
 
-static unsigned int regmap_parse_32_be(void *buf)
+static unsigned int regmap_parse_32_be(const void *buf)
+{
+	const __be32 *b = buf;
+
+	return be32_to_cpu(b[0]);
+}
+
+static void regmap_parse_32_be_inplace(void *buf)
 {
 	__be32 *b = buf;
 
 	b[0] = be32_to_cpu(b[0]);
-
-	return b[0];
 }
 
-static unsigned int regmap_parse_32_native(void *buf)
+static unsigned int regmap_parse_32_native(const void *buf)
 {
 	return *(u32 *)buf;
 }
@@ -555,16 +569,21 @@ struct regmap *regmap_init(struct device *dev,
 		goto err_map;
 	}
 
+	if (val_endian == REGMAP_ENDIAN_NATIVE)
+		map->format.parse_inplace = regmap_parse_inplace_noop;
+
 	switch (config->val_bits) {
 	case 8:
 		map->format.format_val = regmap_format_8;
 		map->format.parse_val = regmap_parse_8;
+		map->format.parse_inplace = regmap_parse_inplace_noop;
 		break;
 	case 16:
 		switch (val_endian) {
 		case REGMAP_ENDIAN_BIG:
 			map->format.format_val = regmap_format_16_be;
 			map->format.parse_val = regmap_parse_16_be;
+			map->format.parse_inplace = regmap_parse_16_be_inplace;
 			break;
 		case REGMAP_ENDIAN_NATIVE:
 			map->format.format_val = regmap_format_16_native;
@@ -585,6 +604,7 @@ struct regmap *regmap_init(struct device *dev,
 		case REGMAP_ENDIAN_BIG:
 			map->format.format_val = regmap_format_32_be;
 			map->format.parse_val = regmap_parse_32_be;
+			map->format.parse_inplace = regmap_parse_32_be_inplace;
 			break;
 		case REGMAP_ENDIAN_NATIVE:
 			map->format.format_val = regmap_format_32_native;
@@ -710,12 +730,12 @@ skip_format_initialization:
 		}
 	}
 
+	regmap_debugfs_init(map, config->name);
+
 	ret = regcache_init(map, config);
 	if (ret != 0)
 		goto err_range;
 
-	regmap_debugfs_init(map, config->name);
-
 	/* Add a devres resource for dev_get_regmap() */
 	m = devres_alloc(dev_get_regmap_release, sizeof(*m), GFP_KERNEL);
 	if (!m) {
@@ -917,8 +937,8 @@ static int _regmap_select_page(struct regmap *map, unsigned int *reg,
 	return 0;
 }
 
-static int _regmap_raw_write(struct regmap *map, unsigned int reg,
-			     const void *val, size_t val_len, bool async)
+int _regmap_raw_write(struct regmap *map, unsigned int reg,
+		      const void *val, size_t val_len, bool async)
 {
 	struct regmap_range_node *range;
 	unsigned long flags;
@@ -930,7 +950,7 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg,
 	size_t len;
 	int i;
 
-	BUG_ON(!map->bus);
+	WARN_ON(!map->bus);
 
 	/* Check for unwritable registers before we start */
 	if (map->writeable_reg)
@@ -943,8 +963,7 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg,
 		unsigned int ival;
 		int val_bytes = map->format.val_bytes;
 		for (i = 0; i < val_len / val_bytes; i++) {
-			memcpy(map->work_buf, val + (i * val_bytes), val_bytes);
-			ival = map->format.parse_val(map->work_buf);
+			ival = map->format.parse_val(val + (i * val_bytes));
 			ret = regcache_write(map, reg + (i * map->reg_stride),
 					     ival);
 			if (ret) {
@@ -999,6 +1018,8 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg,
 		if (!async)
 			return -ENOMEM;
 
+		trace_regmap_async_write_start(map->dev, reg, val_len);
+
 		async->work_buf = kzalloc(map->format.buf_size,
 					  GFP_KERNEL | GFP_DMA);
 		if (!async->work_buf) {
@@ -1036,6 +1057,8 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg,
 			kfree(async->work_buf);
 			kfree(async);
 		}
+
+		return ret;
 	}
 
 	trace_regmap_hw_write_start(map->dev, reg,
@@ -1077,6 +1100,17 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg,
 	return ret;
 }
 
+/**
+ * regmap_can_raw_write - Test if regmap_raw_write() is supported
+ *
+ * @map: Map to check.
+ */
+bool regmap_can_raw_write(struct regmap *map)
+{
+	return map->bus && map->format.format_val && map->format.format_reg;
+}
+EXPORT_SYMBOL_GPL(regmap_can_raw_write);
+
 static int _regmap_bus_formatted_write(void *context, unsigned int reg,
 				       unsigned int val)
 {
@@ -1084,7 +1118,7 @@ static int _regmap_bus_formatted_write(void *context, unsigned int reg,
 	struct regmap_range_node *range;
 	struct regmap *map = context;
 
-	BUG_ON(!map->bus || !map->format.format_write);
+	WARN_ON(!map->bus || !map->format.format_write);
 
 	range = _regmap_range_lookup(map, reg);
 	if (range) {
@@ -1110,7 +1144,7 @@ static int _regmap_bus_raw_write(void *context, unsigned int reg,
 {
 	struct regmap *map = context;
 
-	BUG_ON(!map->bus || !map->format.format_val);
+	WARN_ON(!map->bus || !map->format.format_val);
 
 	map->format.format_val(map->work_buf + map->format.reg_bytes
 			       + map->format.pad_bytes, val, 0);
@@ -1200,12 +1234,10 @@ int regmap_raw_write(struct regmap *map, unsigned int reg,
 {
 	int ret;
 
-	if (!map->bus)
+	if (!regmap_can_raw_write(map))
 		return -EINVAL;
 	if (val_len % map->format.val_bytes)
 		return -EINVAL;
-	if (reg % map->reg_stride)
-		return -EINVAL;
 
 	map->lock(map->lock_arg);
 
@@ -1240,7 +1272,7 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,
 
 	if (!map->bus)
 		return -EINVAL;
-	if (!map->format.parse_val)
+	if (!map->format.parse_inplace)
 		return -EINVAL;
 	if (reg % map->reg_stride)
 		return -EINVAL;
@@ -1258,7 +1290,7 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,
 			goto out;
 		}
 		for (i = 0; i < val_count * val_bytes; i += val_bytes)
-			map->format.parse_val(wval + i);
+			map->format.parse_inplace(wval + i);
 	}
 	/*
 	 * Some devices does not support bulk write, for
@@ -1336,7 +1368,7 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
 	u8 *u8 = map->work_buf;
 	int ret;
 
-	BUG_ON(!map->bus);
+	WARN_ON(!map->bus);
 
 	range = _regmap_range_lookup(map, reg);
 	if (range) {
@@ -1391,7 +1423,7 @@ static int _regmap_read(struct regmap *map, unsigned int reg,
 	int ret;
 	void *context = _regmap_map_get_context(map);
 
-	BUG_ON(!map->reg_read);
+	WARN_ON(!map->reg_read);
 
 	if (!map->cache_bypass) {
 		ret = regcache_read(map, reg, val);
@@ -1519,7 +1551,7 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
 
 	if (!map->bus)
 		return -EINVAL;
-	if (!map->format.parse_val)
+	if (!map->format.parse_inplace)
 		return -EINVAL;
 	if (reg % map->reg_stride)
 		return -EINVAL;
@@ -1546,7 +1578,7 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
 		}
 
 		for (i = 0; i < val_count * val_bytes; i += val_bytes)
-			map->format.parse_val(val + i);
+			map->format.parse_inplace(val + i);
 	} else {
 		for (i = 0; i < val_count; i++) {
 			unsigned int ival;
@@ -1640,6 +1672,8 @@ void regmap_async_complete_cb(struct regmap_async *async, int ret)
 	struct regmap *map = async->map;
 	bool wake;
 
+	trace_regmap_async_io_complete(map->dev);
+
 	spin_lock(&map->async_lock);
 
 	list_del(&async->list);
@@ -1686,6 +1720,8 @@ int regmap_async_complete(struct regmap *map)
 	if (!map->bus->async_write)
 		return 0;
 
+	trace_regmap_async_complete_start(map->dev);
+
 	wait_event(map->async_waitq, regmap_async_is_done(map));
 
 	spin_lock_irqsave(&map->async_lock, flags);
@@ -1693,6 +1729,8 @@ int regmap_async_complete(struct regmap *map)
 	map->async_ret = 0;
 	spin_unlock_irqrestore(&map->async_lock, flags);
 
+	trace_regmap_async_complete_done(map->dev);
+
 	return ret;
 }
 EXPORT_SYMBOL_GPL(regmap_async_complete);
diff --git a/drivers/bcma/core.c b/drivers/bcma/core.c
index 03bbe10..17b26ce 100644
--- a/drivers/bcma/core.c
+++ b/drivers/bcma/core.c
@@ -104,7 +104,13 @@ void bcma_core_pll_ctl(struct bcma_device *core, u32 req, u32 status, bool on)
 		if (i)
 			bcma_err(core->bus, "PLL enable timeout\n");
 	} else {
-		bcma_warn(core->bus, "Disabling PLL not supported yet!\n");
+		/*
+		 * Mask the PLL but don't wait for it to be disabled. PLL may be
+		 * shared between cores and will be still up if there is another
+		 * core using it.
+		 */
+		bcma_mask32(core, BCMA_CLKCTLST, ~req);
+		bcma_read32(core, BCMA_CLKCTLST);
 	}
 }
 EXPORT_SYMBOL_GPL(bcma_core_pll_ctl);
diff --git a/drivers/bcma/driver_chipcommon.c b/drivers/bcma/driver_chipcommon.c
index 28fa50a..036c674 100644
--- a/drivers/bcma/driver_chipcommon.c
+++ b/drivers/bcma/driver_chipcommon.c
@@ -25,13 +25,14 @@ static inline u32 bcma_cc_write32_masked(struct bcma_drv_cc *cc, u16 offset,
 	return value;
 }
 
-static u32 bcma_chipco_get_alp_clock(struct bcma_drv_cc *cc)
+u32 bcma_chipco_get_alp_clock(struct bcma_drv_cc *cc)
 {
 	if (cc->capabilities & BCMA_CC_CAP_PMU)
 		return bcma_pmu_get_alp_clock(cc);
 
 	return 20000000;
 }
+EXPORT_SYMBOL_GPL(bcma_chipco_get_alp_clock);
 
 static u32 bcma_chipco_watchdog_get_max_timer(struct bcma_drv_cc *cc)
 {
@@ -213,6 +214,7 @@ u32 bcma_chipco_gpio_out(struct bcma_drv_cc *cc, u32 mask, u32 value)
 
 	return res;
 }
+EXPORT_SYMBOL_GPL(bcma_chipco_gpio_out);
 
 u32 bcma_chipco_gpio_outen(struct bcma_drv_cc *cc, u32 mask, u32 value)
 {
@@ -225,6 +227,7 @@ u32 bcma_chipco_gpio_outen(struct bcma_drv_cc *cc, u32 mask, u32 value)
 
 	return res;
 }
+EXPORT_SYMBOL_GPL(bcma_chipco_gpio_outen);
 
 /*
  * If the bit is set to 0, chipcommon controlls this GPIO,
diff --git a/drivers/bcma/driver_chipcommon_pmu.c b/drivers/bcma/driver_chipcommon_pmu.c
index 932b101..edca73a 100644
--- a/drivers/bcma/driver_chipcommon_pmu.c
+++ b/drivers/bcma/driver_chipcommon_pmu.c
@@ -174,19 +174,35 @@ u32 bcma_pmu_get_alp_clock(struct bcma_drv_cc *cc)
 	struct bcma_bus *bus = cc->core->bus;
 
 	switch (bus->chipinfo.id) {
+	case BCMA_CHIP_ID_BCM4313:
+	case BCMA_CHIP_ID_BCM43224:
+	case BCMA_CHIP_ID_BCM43225:
+	case BCMA_CHIP_ID_BCM43227:
+	case BCMA_CHIP_ID_BCM43228:
+	case BCMA_CHIP_ID_BCM4331:
+	case BCMA_CHIP_ID_BCM43421:
+	case BCMA_CHIP_ID_BCM43428:
+	case BCMA_CHIP_ID_BCM43431:
 	case BCMA_CHIP_ID_BCM4716:
-	case BCMA_CHIP_ID_BCM4748:
 	case BCMA_CHIP_ID_BCM47162:
-	case BCMA_CHIP_ID_BCM4313:
-	case BCMA_CHIP_ID_BCM5357:
+	case BCMA_CHIP_ID_BCM4748:
 	case BCMA_CHIP_ID_BCM4749:
+	case BCMA_CHIP_ID_BCM5357:
 	case BCMA_CHIP_ID_BCM53572:
+	case BCMA_CHIP_ID_BCM6362:
 		/* always 20Mhz */
 		return 20000 * 1000;
-	case BCMA_CHIP_ID_BCM5356:
 	case BCMA_CHIP_ID_BCM4706:
+	case BCMA_CHIP_ID_BCM5356:
 		/* always 25Mhz */
 		return 25000 * 1000;
+	case BCMA_CHIP_ID_BCM43460:
+	case BCMA_CHIP_ID_BCM4352:
+	case BCMA_CHIP_ID_BCM4360:
+		if (cc->status & BCMA_CC_CHIPST_4360_XTAL_40MZ)
+			return 40000 * 1000;
+		else
+			return 20000 * 1000;
 	default:
 		bcma_warn(bus, "No ALP clock specified for %04X device, pmu rev. %d, using default %d Hz\n",
 			  bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_ALP_CLOCK);
@@ -373,7 +389,7 @@ void bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc *cc, int spuravoid)
 		tmp |= (bcm5357_bcm43236_ndiv[spuravoid]) << BCMA_CC_PMU1_PLL0_PC2_NDIV_INT_SHIFT;
 		bcma_cc_write32(cc, BCMA_CC_PLLCTL_DATA, tmp);
 
-		tmp = 1 << 10;
+		tmp = BCMA_CC_PMU_CTL_PLL_UPD;
 		break;
 
 	case BCMA_CHIP_ID_BCM4331:
@@ -394,7 +410,7 @@ void bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc *cc, int spuravoid)
 			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2,
 						     0x03000a08);
 		}
-		tmp = 1 << 10;
+		tmp = BCMA_CC_PMU_CTL_PLL_UPD;
 		break;
 
 	case BCMA_CHIP_ID_BCM43224:
@@ -427,7 +443,7 @@ void bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc *cc, int spuravoid)
 			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5,
 						     0x88888815);
 		}
-		tmp = 1 << 10;
+		tmp = BCMA_CC_PMU_CTL_PLL_UPD;
 		break;
 
 	case BCMA_CHIP_ID_BCM4716:
@@ -461,7 +477,7 @@ void bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc *cc, int spuravoid)
 						     0x88888815);
 		}
 
-		tmp = 3 << 9;
+		tmp = BCMA_CC_PMU_CTL_PLL_UPD | BCMA_CC_PMU_CTL_NOILPONW;
 		break;
 
 	case BCMA_CHIP_ID_BCM43227:
@@ -497,7 +513,7 @@ void bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc *cc, int spuravoid)
 			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5,
 						     0x88888815);
 		}
-		tmp = 1 << 10;
+		tmp = BCMA_CC_PMU_CTL_PLL_UPD;
 		break;
 	default:
 		bcma_err(bus, "Unknown spuravoidance settings for chip 0x%04X, not changing PLL\n",
diff --git a/drivers/bcma/driver_mips.c b/drivers/bcma/driver_mips.c
index 9a7f0e3..11115bb 100644
--- a/drivers/bcma/driver_mips.c
+++ b/drivers/bcma/driver_mips.c
@@ -21,7 +21,7 @@
 #include <linux/serial_reg.h>
 #include <linux/time.h>
 
-static const char *part_probes[] = { "bcm47xxpart", NULL };
+static const char * const part_probes[] = { "bcm47xxpart", NULL };
 
 static struct physmap_flash_data bcma_pflash_data = {
 	.part_probe_types	= part_probes,
diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c
index 9a6188a..f72f52b 100644
--- a/drivers/bcma/main.c
+++ b/drivers/bcma/main.c
@@ -120,6 +120,11 @@ static int bcma_register_cores(struct bcma_bus *bus)
 			continue;
 		}
 
+		/* Only first GMAC core on BCM4706 is connected and working */
+		if (core->id.id == BCMA_CORE_4706_MAC_GBIT &&
+		    core->core_unit > 0)
+			continue;
+
 		core->dev.release = bcma_release_core_dev;
 		core->dev.bus = &bcma_bus_type;
 		dev_set_name(&core->dev, "bcma%d:%d", bus->num, dev_id);
diff --git a/drivers/bcma/scan.c b/drivers/bcma/scan.c
index 8d0b571..bca9c80 100644
--- a/drivers/bcma/scan.c
+++ b/drivers/bcma/scan.c
@@ -137,19 +137,19 @@ static void bcma_scan_switch_core(struct bcma_bus *bus, u32 addr)
 				       addr);
 }
 
-static u32 bcma_erom_get_ent(struct bcma_bus *bus, u32 **eromptr)
+static u32 bcma_erom_get_ent(struct bcma_bus *bus, u32 __iomem **eromptr)
 {
 	u32 ent = readl(*eromptr);
 	(*eromptr)++;
 	return ent;
 }
 
-static void bcma_erom_push_ent(u32 **eromptr)
+static void bcma_erom_push_ent(u32 __iomem **eromptr)
 {
 	(*eromptr)--;
 }
 
-static s32 bcma_erom_get_ci(struct bcma_bus *bus, u32 **eromptr)
+static s32 bcma_erom_get_ci(struct bcma_bus *bus, u32 __iomem **eromptr)
 {
 	u32 ent = bcma_erom_get_ent(bus, eromptr);
 	if (!(ent & SCAN_ER_VALID))
@@ -159,14 +159,14 @@ static s32 bcma_erom_get_ci(struct bcma_bus *bus, u32 **eromptr)
 	return ent;
 }
 
-static bool bcma_erom_is_end(struct bcma_bus *bus, u32 **eromptr)
+static bool bcma_erom_is_end(struct bcma_bus *bus, u32 __iomem **eromptr)
 {
 	u32 ent = bcma_erom_get_ent(bus, eromptr);
 	bcma_erom_push_ent(eromptr);
 	return (ent == (SCAN_ER_TAG_END | SCAN_ER_VALID));
 }
 
-static bool bcma_erom_is_bridge(struct bcma_bus *bus, u32 **eromptr)
+static bool bcma_erom_is_bridge(struct bcma_bus *bus, u32 __iomem **eromptr)
 {
 	u32 ent = bcma_erom_get_ent(bus, eromptr);
 	bcma_erom_push_ent(eromptr);
@@ -175,7 +175,7 @@ static bool bcma_erom_is_bridge(struct bcma_bus *bus, u32 **eromptr)
 		((ent & SCAN_ADDR_TYPE) == SCAN_ADDR_TYPE_BRIDGE));
 }
 
-static void bcma_erom_skip_component(struct bcma_bus *bus, u32 **eromptr)
+static void bcma_erom_skip_component(struct bcma_bus *bus, u32 __iomem **eromptr)
 {
 	u32 ent;
 	while (1) {
@@ -189,7 +189,7 @@ static void bcma_erom_skip_component(struct bcma_bus *bus, u32 **eromptr)
 	bcma_erom_push_ent(eromptr);
 }
 
-static s32 bcma_erom_get_mst_port(struct bcma_bus *bus, u32 **eromptr)
+static s32 bcma_erom_get_mst_port(struct bcma_bus *bus, u32 __iomem **eromptr)
 {
 	u32 ent = bcma_erom_get_ent(bus, eromptr);
 	if (!(ent & SCAN_ER_VALID))
@@ -199,7 +199,7 @@ static s32 bcma_erom_get_mst_port(struct bcma_bus *bus, u32 **eromptr)
 	return ent;
 }
 
-static s32 bcma_erom_get_addr_desc(struct bcma_bus *bus, u32 **eromptr,
+static s32 bcma_erom_get_addr_desc(struct bcma_bus *bus, u32 __iomem **eromptr,
 				  u32 type, u8 port)
 {
 	u32 addrl, addrh, sizel, sizeh = 0;
diff --git a/drivers/bcma/sprom.c b/drivers/bcma/sprom.c
index 4adf9ef9..8934298 100644
--- a/drivers/bcma/sprom.c
+++ b/drivers/bcma/sprom.c
@@ -217,6 +217,7 @@ static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom)
 	}
 
 	SPEX(board_rev, SSB_SPROM8_BOARDREV, ~0, 0);
+	SPEX(board_type, SSB_SPROM1_SPID, ~0, 0);
 
 	SPEX(txpid2g[0], SSB_SPROM4_TXPID2G01, SSB_SPROM4_TXPID2G0,
 	     SSB_SPROM4_TXPID2G0_SHIFT);
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c
index 5b5ee79..eb39501 100644
--- a/drivers/block/DAC960.c
+++ b/drivers/block/DAC960.c
@@ -6473,7 +6473,7 @@ static int dac960_initial_status_proc_show(struct seq_file *m, void *v)
 
 static int dac960_initial_status_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, dac960_initial_status_proc_show, PDE(inode)->data);
+	return single_open(file, dac960_initial_status_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations dac960_initial_status_proc_fops = {
@@ -6519,7 +6519,7 @@ static int dac960_current_status_proc_show(struct seq_file *m, void *v)
 
 static int dac960_current_status_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, dac960_current_status_proc_show, PDE(inode)->data);
+	return single_open(file, dac960_current_status_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations dac960_current_status_proc_fops = {
@@ -6540,14 +6540,14 @@ static int dac960_user_command_proc_show(struct seq_file *m, void *v)
 
 static int dac960_user_command_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, dac960_user_command_proc_show, PDE(inode)->data);
+	return single_open(file, dac960_user_command_proc_show, PDE_DATA(inode));
 }
 
 static ssize_t dac960_user_command_proc_write(struct file *file,
 				       const char __user *Buffer,
 				       size_t Count, loff_t *pos)
 {
-  DAC960_Controller_T *Controller = (DAC960_Controller_T *) PDE(file_inode(file))->data;
+  DAC960_Controller_T *Controller = PDE_DATA(file_inode(file));
   unsigned char CommandBuffer[80];
   int Length;
   if (Count > sizeof(CommandBuffer)-1) return -EINVAL;
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index b81ddfe..53e13ef 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -541,4 +541,10 @@ config BLK_DEV_RSXX
 	  To compile this driver as a module, choose M here: the
 	  module will be called rsxx.
 
+config BLOCKCONSOLE
+	bool "Block device console logging support"
+	help
+	  This enables logging to block devices.
+	  See <file:Documentation/block/blockconsole.txt> for details.
+
 endif # BLK_DEV
diff --git a/drivers/block/Makefile b/drivers/block/Makefile
index a3b4023..77d950a 100644
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -39,6 +39,7 @@ obj-$(CONFIG_XEN_BLKDEV_BACKEND)	+= xen-blkback/
 obj-$(CONFIG_BLK_DEV_DRBD)     += drbd/
 obj-$(CONFIG_BLK_DEV_RBD)     += rbd.o
 obj-$(CONFIG_BLK_DEV_PCIESSD_MTIP32XX)	+= mtip32xx/
+obj-$(CONFIG_BLOCKCONSOLE)	+= blockconsole.o
 
 obj-$(CONFIG_BLK_DEV_RSXX) += rsxx/
 
diff --git a/drivers/block/aoe/aoechr.c b/drivers/block/aoe/aoechr.c
index 42e67ad..ab41be6 100644
--- a/drivers/block/aoe/aoechr.c
+++ b/drivers/block/aoe/aoechr.c
@@ -139,13 +139,12 @@ bail:		spin_unlock_irqrestore(&emsgs_lock, flags);
 		return;
 	}
 
-	mp = kmalloc(n, GFP_ATOMIC);
+	mp = kmemdup(msg, n, GFP_ATOMIC);
 	if (mp == NULL) {
 		printk(KERN_ERR "aoe: allocation failure, len=%ld\n", n);
 		goto bail;
 	}
 
-	memcpy(mp, msg, n);
 	em->msg = mp;
 	em->flags |= EMFL_VALID;
 	em->len = n;
diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c
index 25ef5c0..fc803ec 100644
--- a/drivers/block/aoe/aoecmd.c
+++ b/drivers/block/aoe/aoecmd.c
@@ -51,8 +51,9 @@ new_skb(ulong len)
 {
 	struct sk_buff *skb;
 
-	skb = alloc_skb(len, GFP_ATOMIC);
+	skb = alloc_skb(len + MAX_HEADER, GFP_ATOMIC);
 	if (skb) {
+		skb_reserve(skb, MAX_HEADER);
 		skb_reset_mac_header(skb);
 		skb_reset_network_header(skb);
 		skb->protocol = __constant_htons(ETH_P_AOE);
@@ -919,16 +920,14 @@ bio_pagedec(struct bio *bio)
 static void
 bufinit(struct buf *buf, struct request *rq, struct bio *bio)
 {
-	struct bio_vec *bv;
-
 	memset(buf, 0, sizeof(*buf));
 	buf->rq = rq;
 	buf->bio = bio;
 	buf->resid = bio->bi_size;
 	buf->sector = bio->bi_sector;
 	bio_pageinc(bio);
-	buf->bv = bv = &bio->bi_io_vec[bio->bi_idx];
-	buf->bv_resid = bv->bv_len;
+	buf->bv = bio_iovec(bio);
+	buf->bv_resid = buf->bv->bv_len;
 	WARN_ON(buf->bv_resid == 0);
 }
 
diff --git a/drivers/block/blockconsole.c b/drivers/block/blockconsole.c
new file mode 100644
index 0000000..1600a19
--- /dev/null
+++ b/drivers/block/blockconsole.c
@@ -0,0 +1,619 @@
+/*
+ * Blockconsole - write kernel console to a block device
+ *
+ * Copyright (C) 2012  Joern Engel <joern@logfs.org>
+ */
+#include <linux/bio.h>
+#include <linux/blockconsole.h>
+#include <linux/console.h>
+#include <linux/fs.h>
+#include <linux/kref.h>
+#include <linux/kthread.h>
+#include <linux/mm.h>
+#include <linux/mount.h>
+#include <linux/random.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/workqueue.h>
+#include <linux/sched.h>
+#include <linux/sched/rt.h>
+#include <linux/ctype.h>
+
+#define BLOCKCONSOLE_MAGIC	"\nLinux blockconsole version 1.1\n"
+#define BCON_UUID_OFS		(32)
+#define BCON_ROUND_OFS		(41)
+#define BCON_TILE_OFS		(50)
+#define BCON_HEADERSIZE		(50)
+#define BCON_LONG_HEADERSIZE	(59) /* with tile index */
+
+#define PAGE_COUNT		(256)
+#define SECTOR_COUNT		(PAGE_COUNT * (PAGE_SIZE >> 9))
+#define CACHE_PAGE_MASK		(PAGE_COUNT - 1)
+#define CACHE_SECTOR_MASK	(SECTOR_COUNT - 1)
+#define CACHE_SIZE		(PAGE_COUNT << PAGE_SHIFT)
+#define CACHE_MASK		(CACHE_SIZE - 1)
+#define SECTOR_SHIFT		(9)
+#define SECTOR_SIZE		(1 << SECTOR_SHIFT)
+#define SECTOR_MASK		(~(SECTOR_SIZE-1))
+#define PG_SECTOR_MASK		((PAGE_SIZE >> 9) - 1)
+
+#undef pr_fmt
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+struct bcon_bio {
+	struct bio bio;
+	struct bio_vec bvec;
+	void *sector;
+	int in_flight;
+};
+
+struct blockconsole {
+	char devname[32];
+	spinlock_t end_io_lock;
+	struct timer_list pad_timer;
+	int error_count;
+	struct kref kref;
+	u64 console_bytes;
+	u64 write_bytes;
+	u64 max_bytes;
+	u32 round;
+	u32 uuid;
+	struct bcon_bio bio_array[SECTOR_COUNT];
+	struct page *pages;
+	struct bcon_bio zero_bios[PAGE_COUNT];
+	struct page *zero_page;
+	struct block_device *bdev;
+	struct console console;
+	struct work_struct unregister_work;
+	struct work_struct release_work;
+	struct task_struct *writeback_thread;
+	struct notifier_block panic_block;
+};
+
+static void bcon_get(struct blockconsole *bc)
+{
+	kref_get(&bc->kref);
+}
+
+static void __bcon_release(struct work_struct *work)
+{
+	struct blockconsole *bc = container_of(work, struct blockconsole,
+			release_work);
+
+	__free_pages(bc->zero_page, 0);
+	__free_pages(bc->pages, 8);
+	invalidate_mapping_pages(bc->bdev->bd_inode->i_mapping, 0, -1);
+	blkdev_put(bc->bdev, FMODE_READ|FMODE_WRITE);
+	kfree(bc);
+}
+
+static void bcon_release(struct kref *kref)
+{
+	struct blockconsole *bc = container_of(kref, struct blockconsole, kref);
+
+	/* bcon_release can be called from atomic context */
+	schedule_work(&bc->release_work);
+}
+
+static void bcon_put(struct blockconsole *bc)
+{
+	kref_put(&bc->kref, bcon_release);
+}
+
+static int __bcon_console_ofs(u64 console_bytes)
+{
+	return console_bytes & ~SECTOR_MASK;
+}
+
+static int bcon_console_ofs(struct blockconsole *bc)
+{
+	return __bcon_console_ofs(bc->console_bytes);
+}
+
+static int __bcon_console_sector(u64 console_bytes)
+{
+	return (console_bytes >> SECTOR_SHIFT) & CACHE_SECTOR_MASK;
+}
+
+static int bcon_console_sector(struct blockconsole *bc)
+{
+	return __bcon_console_sector(bc->console_bytes);
+}
+
+static int bcon_write_sector(struct blockconsole *bc)
+{
+	return (bc->write_bytes >> SECTOR_SHIFT) & CACHE_SECTOR_MASK;
+}
+
+static void clear_sector(void *sector)
+{
+	memset(sector, ' ', 511);
+	memset(sector + 511, 10, 1);
+}
+
+static void bcon_init_first_page(struct blockconsole *bc)
+{
+	char *buf = page_address(bc->pages);
+	size_t len = strlen(BLOCKCONSOLE_MAGIC);
+	u32 tile = bc->console_bytes >> 20; /* We overflow after 4TB - fine */
+
+	clear_sector(buf);
+	memcpy(buf, BLOCKCONSOLE_MAGIC, len);
+	sprintf(buf + BCON_UUID_OFS, "%08x", bc->uuid);
+	sprintf(buf + BCON_ROUND_OFS, "%08x", bc->round);
+	sprintf(buf + BCON_TILE_OFS, "%08x", tile);
+	/* replace NUL with newline */
+	buf[BCON_UUID_OFS + 8] = 10;
+	buf[BCON_ROUND_OFS + 8] = 10;
+	buf[BCON_TILE_OFS + 8] = 10;
+}
+
+static void bcon_advance_console_bytes(struct blockconsole *bc, int bytes)
+{
+	u64 old, new;
+
+	do {
+		old = bc->console_bytes;
+		new = old + bytes;
+		if (new >= bc->max_bytes)
+			new = 0;
+		if ((new & CACHE_MASK) == 0) {
+			bcon_init_first_page(bc);
+			new += BCON_LONG_HEADERSIZE;
+		}
+	} while (cmpxchg64(&bc->console_bytes, old, new) != old);
+}
+
+static void request_complete(struct bio *bio, int err,
+			     struct batch_complete *batch)
+{
+	complete((struct completion *)bio->bi_private);
+}
+
+static int sync_read(struct blockconsole *bc, u64 ofs)
+{
+	struct bio bio;
+	struct bio_vec bio_vec;
+	struct completion complete;
+
+	bio_init(&bio);
+	bio.bi_io_vec = &bio_vec;
+	bio_vec.bv_page = bc->pages;
+	bio_vec.bv_len = SECTOR_SIZE;
+	bio_vec.bv_offset = 0;
+	bio.bi_vcnt = 1;
+	bio.bi_idx = 0;
+	bio.bi_size = SECTOR_SIZE;
+	bio.bi_bdev = bc->bdev;
+	bio.bi_sector = ofs >> SECTOR_SHIFT;
+	init_completion(&complete);
+	bio.bi_private = &complete;
+	bio.bi_end_io = request_complete;
+
+	submit_bio(READ, &bio);
+	wait_for_completion(&complete);
+	return test_bit(BIO_UPTODATE, &bio.bi_flags) ? 0 : -EIO;
+}
+
+static void bcon_erase_segment(struct blockconsole *bc)
+{
+	int i;
+
+	for (i = 0; i < PAGE_COUNT; i++) {
+		struct bcon_bio *bcon_bio = bc->zero_bios + i;
+		struct bio *bio = &bcon_bio->bio;
+
+		/*
+		 * If the last erase hasn't finished yet, just skip it.  The log
+		 * will look messy, but that's all.
+		 */
+		rmb();
+		if (bcon_bio->in_flight)
+			continue;
+		bio_init(bio);
+		bio->bi_io_vec = &bcon_bio->bvec;
+		bio->bi_vcnt = 1;
+		bio->bi_size = PAGE_SIZE;
+		bio->bi_bdev = bc->bdev;
+		bio->bi_private = bc;
+		bio->bi_idx = 0;
+		bio->bi_sector = (bc->write_bytes + i * PAGE_SIZE) >> 9;
+		bcon_bio->in_flight = 1;
+		wmb();
+		/* We want the erase to go to the device first somehow */
+		submit_bio(WRITE | REQ_SOFTBARRIER, bio);
+	}
+}
+
+static void bcon_advance_write_bytes(struct blockconsole *bc, int bytes)
+{
+	bc->write_bytes += bytes;
+	if (bc->write_bytes >= bc->max_bytes) {
+		bc->write_bytes = 0;
+		bcon_init_first_page(bc);
+		bc->round++;
+	}
+}
+
+static int bcon_find_end_of_log(struct blockconsole *bc)
+{
+	u64 start = 0, end = bc->max_bytes, middle;
+	void *sec0 = bc->bio_array[0].sector;
+	void *sec1 = bc->bio_array[1].sector;
+	int err, version;
+
+	err = sync_read(bc, 0);
+	if (err)
+		return err;
+	/* Second sanity check, out of sheer paranoia */
+	version = bcon_magic_present(sec0);
+	if (!version)
+		return -EINVAL;
+
+	bc->uuid = simple_strtoull(sec0 + BCON_UUID_OFS, NULL, 16);
+	bc->round = simple_strtoull(sec0 + BCON_ROUND_OFS, NULL, 16);
+
+	memcpy(sec1, sec0, BCON_HEADERSIZE);
+	for (;;) {
+		middle = (start + end) / 2;
+		middle &= ~CACHE_MASK;
+		if (middle == start)
+			break;
+		err = sync_read(bc, middle);
+		if (err)
+			return err;
+		if (memcmp(sec1, sec0, BCON_HEADERSIZE)) {
+			/* If the two differ, we haven't written that far yet */
+			end = middle;
+		} else {
+			start = middle;
+		}
+	}
+	bc->console_bytes = bc->write_bytes = end;
+	bcon_advance_console_bytes(bc, 0); /* To skip the header */
+	bcon_advance_write_bytes(bc, 0); /* To wrap around, if necessary */
+	bcon_erase_segment(bc);
+	return 0;
+}
+
+static void bcon_unregister(struct work_struct *work)
+{
+	struct blockconsole *bc = container_of(work, struct blockconsole,
+			unregister_work);
+
+	atomic_notifier_chain_unregister(&panic_notifier_list, &bc->panic_block);
+	unregister_console(&bc->console);
+	del_timer_sync(&bc->pad_timer);
+	kthread_stop(bc->writeback_thread);
+	/* No new io will be scheduled anymore now */
+	bcon_put(bc);
+}
+
+#define BCON_MAX_ERRORS	10
+static void bcon_end_io(struct bio *bio, int err, struct batch_complete *batch)
+{
+	struct bcon_bio *bcon_bio = container_of(bio, struct bcon_bio, bio);
+	struct blockconsole *bc = bio->bi_private;
+	unsigned long flags;
+
+	/*
+	 * We want to assume the device broken and free this console if
+	 * we accumulate too many errors.  But if errors are transient,
+	 * we also want to forget about them once writes succeed again.
+	 * Oh, and we only want to reset the counter if it hasn't reached
+	 * the limit yet, so we don't bcon_put() twice from here.
+	 */
+	spin_lock_irqsave(&bc->end_io_lock, flags);
+	if (err) {
+		if (bc->error_count++ == BCON_MAX_ERRORS) {
+			pr_info("no longer logging to %s\n", bc->devname);
+			schedule_work(&bc->unregister_work);
+		}
+	} else {
+		if (bc->error_count && bc->error_count < BCON_MAX_ERRORS)
+			bc->error_count = 0;
+	}
+	/*
+	 * Add padding (a bunch of spaces and a newline) early so bcon_pad
+	 * only has to advance a pointer.
+	 */
+	clear_sector(bcon_bio->sector);
+	bcon_bio->in_flight = 0;
+	spin_unlock_irqrestore(&bc->end_io_lock, flags);
+	bcon_put(bc);
+}
+
+static void bcon_writesector(struct blockconsole *bc, int index)
+{
+	struct bcon_bio *bcon_bio = bc->bio_array + index;
+	struct bio *bio = &bcon_bio->bio;
+
+	rmb();
+	if (bcon_bio->in_flight)
+		return;
+	bcon_get(bc);
+
+	bio_init(bio);
+	bio->bi_io_vec = &bcon_bio->bvec;
+	bio->bi_vcnt = 1;
+	bio->bi_size = SECTOR_SIZE;
+	bio->bi_bdev = bc->bdev;
+	bio->bi_private = bc;
+	bio->bi_end_io = bcon_end_io;
+
+	bio->bi_idx = 0;
+	bio->bi_sector = bc->write_bytes >> 9;
+	bcon_bio->in_flight = 1;
+	wmb();
+	submit_bio(WRITE, bio);
+}
+
+static int bcon_writeback(void *_bc)
+{
+	struct blockconsole *bc = _bc;
+	struct sched_param(sp);
+
+	sp.sched_priority = MAX_RT_PRIO - 1; /* Highest realtime prio */
+	sched_setscheduler_nocheck(current, SCHED_FIFO, &sp);
+	for (;;) {
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule();
+		if (kthread_should_stop())
+			break;
+		while (bcon_write_sector(bc) != bcon_console_sector(bc)) {
+			bcon_writesector(bc, bcon_write_sector(bc));
+			bcon_advance_write_bytes(bc, SECTOR_SIZE);
+			if (bcon_write_sector(bc) == 0)
+				bcon_erase_segment(bc);
+		}
+	}
+	return 0;
+}
+
+static void bcon_pad(unsigned long data)
+{
+	struct blockconsole *bc = (void *)data;
+	unsigned int n;
+
+	/*
+	 * We deliberately race against bcon_write here.  If we lose the race,
+	 * our padding is no longer where we expected it to be, i.e. it is
+	 * no longer a bunch of spaces with a newline at the end.  There could
+	 * not be a newline at all or it could be somewhere in the middle.
+	 * Either way, the log corruption is fairly obvious to spot and ignore
+	 * for human readers.
+	 */
+	n = SECTOR_SIZE - bcon_console_ofs(bc);
+	if (n != SECTOR_SIZE) {
+		bcon_advance_console_bytes(bc, n);
+		wake_up_process(bc->writeback_thread);
+	}
+}
+
+static void bcon_write(struct console *console, const char *msg,
+		unsigned int len)
+{
+	struct blockconsole *bc = container_of(console, struct blockconsole,
+			console);
+	unsigned int n;
+	u64 console_bytes;
+	int i;
+
+	while (len) {
+		console_bytes = bc->console_bytes;
+		i = __bcon_console_sector(console_bytes);
+		rmb();
+		if (bc->bio_array[i].in_flight)
+			break;
+		n = min_t(int, len, SECTOR_SIZE -
+				__bcon_console_ofs(console_bytes));
+		memcpy(bc->bio_array[i].sector +
+				__bcon_console_ofs(console_bytes), msg, n);
+		len -= n;
+		msg += n;
+		bcon_advance_console_bytes(bc, n);
+	}
+	wake_up_process(bc->writeback_thread);
+	mod_timer(&bc->pad_timer, jiffies + HZ);
+}
+
+static void bcon_init_bios(struct blockconsole *bc)
+{
+	int i;
+
+	for (i = 0; i < SECTOR_COUNT; i++) {
+		int page_index = i >> (PAGE_SHIFT - SECTOR_SHIFT);
+		struct page *page = bc->pages + page_index;
+		struct bcon_bio *bcon_bio = bc->bio_array + i;
+		struct bio_vec *bvec = &bcon_bio->bvec;
+
+		bcon_bio->in_flight = 0;
+		bcon_bio->sector = page_address(bc->pages + page_index)
+			+ SECTOR_SIZE * (i & PG_SECTOR_MASK);
+		clear_sector(bcon_bio->sector);
+		bvec->bv_page = page;
+		bvec->bv_len = SECTOR_SIZE;
+		bvec->bv_offset = SECTOR_SIZE * (i & PG_SECTOR_MASK);
+	}
+}
+
+static void bcon_init_zero_bio(struct blockconsole *bc)
+{
+	int i;
+
+	memset(page_address(bc->zero_page), 0, PAGE_SIZE);
+	for (i = 0; i < PAGE_COUNT; i++) {
+		struct bcon_bio *bcon_bio = bc->zero_bios + i;
+		struct bio_vec *bvec = &bcon_bio->bvec;
+
+		bcon_bio->in_flight = 0;
+		bvec->bv_page = bc->zero_page;
+		bvec->bv_len = PAGE_SIZE;
+		bvec->bv_offset = 0;
+	}
+}
+
+static int blockconsole_panic(struct notifier_block *this, unsigned long event,
+		void *ptr)
+{
+	struct blockconsole *bc = container_of(this, struct blockconsole,
+			panic_block);
+	unsigned int n;
+
+	n = SECTOR_SIZE - bcon_console_ofs(bc);
+	if (n != SECTOR_SIZE)
+		bcon_advance_console_bytes(bc, n);
+	bcon_writeback(bc);
+	return NOTIFY_DONE;
+}
+
+static int bcon_create(const char *devname)
+{
+	const fmode_t mode = FMODE_READ | FMODE_WRITE;
+	struct blockconsole *bc;
+	int err;
+
+	bc = kzalloc(sizeof(*bc), GFP_KERNEL);
+	if (!bc)
+		return -ENOMEM;
+	memset(bc->devname, ' ', sizeof(bc->devname));
+	strlcpy(bc->devname, devname, sizeof(bc->devname));
+	spin_lock_init(&bc->end_io_lock);
+	strcpy(bc->console.name, "bcon");
+	bc->console.flags = CON_PRINTBUFFER | CON_ENABLED | CON_ALLDATA;
+	bc->console.write = bcon_write;
+	bc->bdev = blkdev_get_by_path(devname, mode, NULL);
+#ifndef MODULE
+	if (IS_ERR(bc->bdev)) {
+		dev_t devt = name_to_dev_t(devname);
+		if (devt)
+			bc->bdev = blkdev_get_by_dev(devt, mode, NULL);
+	}
+#endif
+	if (IS_ERR(bc->bdev))
+		goto out;
+	bc->pages = alloc_pages(GFP_KERNEL, 8);
+	if (!bc->pages)
+		goto out;
+	bc->zero_page = alloc_pages(GFP_KERNEL, 0);
+	if (!bc->zero_page)
+		goto out1;
+	bcon_init_bios(bc);
+	bcon_init_zero_bio(bc);
+	setup_timer(&bc->pad_timer, bcon_pad, (unsigned long)bc);
+	bc->max_bytes = bc->bdev->bd_inode->i_size & ~CACHE_MASK;
+	err = bcon_find_end_of_log(bc);
+	if (err)
+		goto out2;
+	kref_init(&bc->kref); /* This reference gets freed on errors */
+	bc->writeback_thread = kthread_run(bcon_writeback, bc, "bcon_%s",
+			devname);
+	if (IS_ERR(bc->writeback_thread))
+		goto out2;
+	INIT_WORK(&bc->unregister_work, bcon_unregister);
+	INIT_WORK(&bc->release_work, __bcon_release);
+	register_console(&bc->console);
+	bc->panic_block.notifier_call = blockconsole_panic;
+	bc->panic_block.priority = INT_MAX;
+	atomic_notifier_chain_register(&panic_notifier_list, &bc->panic_block);
+	pr_info("now logging to %s at %llx\n", devname, bc->console_bytes >> 20);
+
+	return 0;
+
+out2:
+	__free_pages(bc->zero_page, 0);
+out1:
+	__free_pages(bc->pages, 8);
+out:
+	kfree(bc);
+	/* Not strictly correct, be the caller doesn't care */
+	return -ENOMEM;
+}
+
+static void bcon_create_fuzzy(const char *name)
+{
+	char *longname;
+	int err;
+
+	err = bcon_create(name);
+	if (err) {
+		longname = kzalloc(strlen(name) + 6, GFP_KERNEL);
+		if (!longname)
+			return;
+		strcpy(longname, "/dev/");
+		strcat(longname, name);
+		bcon_create(longname);
+		kfree(longname);
+	}
+}
+
+static DEFINE_SPINLOCK(bcon_device_lock);
+static char scanned_devices[80];
+
+static void bcon_do_add(struct work_struct *work)
+{
+	char local_devices[80], *name, *remainder = local_devices;
+
+	spin_lock(&bcon_device_lock);
+	memcpy(local_devices, scanned_devices, sizeof(local_devices));
+	memset(scanned_devices, 0, sizeof(scanned_devices));
+	spin_unlock(&bcon_device_lock);
+
+	while (remainder && remainder[0]) {
+		name = strsep(&remainder, ",");
+		bcon_create_fuzzy(name);
+	}
+}
+
+static DECLARE_WORK(bcon_add_work, bcon_do_add);
+
+void bcon_add(const char *name)
+{
+	/*
+	 * We add each name to a small static buffer and ask for a workqueue
+	 * to go pick it up asap.  Once it is picked up, the buffer is empty
+	 * again, so hopefully it will suffice for all sane users.
+	 */
+	spin_lock(&bcon_device_lock);
+	if (scanned_devices[0])
+		strncat(scanned_devices, ",", sizeof(scanned_devices));
+	strncat(scanned_devices, name, sizeof(scanned_devices));
+	spin_unlock(&bcon_device_lock);
+	schedule_work(&bcon_add_work);
+}
+
+/*
+ * Check if we have an 8-digit hex number followed by newline
+ */
+static bool is_four_byte_hex(const void *data)
+{
+	const char *str = data;
+	int len = 0;
+
+	while (isxdigit(*str) && len++ < 9)
+		str++;
+
+	if (len != 8)
+		return false;
+
+	/* str should point to a \n now */
+	if (*str != 0xa)
+		return false;
+
+	return true;
+}
+
+int bcon_magic_present(const void *data)
+{
+	size_t len = strlen(BLOCKCONSOLE_MAGIC);
+
+	if (memcmp(data, BLOCKCONSOLE_MAGIC, len))
+		return 0;
+	if (!is_four_byte_hex(data + BCON_UUID_OFS))
+		return 0;
+	if (!is_four_byte_hex(data + BCON_ROUND_OFS))
+		return 0;
+	if (!is_four_byte_hex(data + BCON_TILE_OFS))
+		return 0;
+	return 11;
+}
diff --git a/drivers/block/brd.c b/drivers/block/brd.c
index 531ceb3..f1a29f8 100644
--- a/drivers/block/brd.c
+++ b/drivers/block/brd.c
@@ -334,8 +334,7 @@ static void brd_make_request(struct request_queue *q, struct bio *bio)
 	int err = -EIO;
 
 	sector = bio->bi_sector;
-	if (sector + (bio->bi_size >> SECTOR_SHIFT) >
-						get_capacity(bdev->bd_disk))
+	if (bio_end_sector(bio) > get_capacity(bdev->bd_disk))
 		goto out;
 
 	if (unlikely(bio->bi_rw & REQ_DISCARD)) {
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 1c1b8e5..e18c991 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -493,7 +493,7 @@ static int cciss_seq_open(struct inode *inode, struct file *file)
 	struct seq_file *seq = file->private_data;
 
 	if (!ret)
-		seq->private = PDE(inode)->data;
+		seq->private = PDE_DATA(inode);
 
 	return ret;
 }
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c
index da33111..ecd845c 100644
--- a/drivers/block/cciss_scsi.c
+++ b/drivers/block/cciss_scsi.c
@@ -54,13 +54,11 @@ static CommandList_struct *cmd_special_alloc(ctlr_info_t *h);
 static void cmd_free(ctlr_info_t *h, CommandList_struct *c);
 static void cmd_special_free(ctlr_info_t *h, CommandList_struct *c);
 
-static int cciss_scsi_proc_info(
-		struct Scsi_Host *sh,
+static int cciss_scsi_write_info(struct Scsi_Host *sh,
 		char *buffer, /* data buffer */
-		char **start, 	   /* where data in buffer starts */
-		off_t offset,	   /* offset from start of imaginary file */
-		int length, 	   /* length of data in buffer */
-		int func);	   /* 0 == read, 1 == write */
+		int length); 	   /* length of data in buffer */
+static int cciss_scsi_show_info(struct seq_file *m,
+				struct Scsi_Host *sh);
 
 static int cciss_scsi_queue_command (struct Scsi_Host *h,
 				     struct scsi_cmnd *cmd);
@@ -82,7 +80,8 @@ static struct scsi_host_template cciss_driver_template = {
 	.module			= THIS_MODULE,
 	.name			= "cciss",
 	.proc_name		= "cciss",
-	.proc_info		= cciss_scsi_proc_info,
+	.write_info		= cciss_scsi_write_info,
+	.show_info		= cciss_scsi_show_info,
 	.queuecommand		= cciss_scsi_queue_command,
 	.this_id		= 7,
 	.cmd_per_lun		= 1,
@@ -1302,59 +1301,54 @@ cciss_scsi_user_command(ctlr_info_t *h, int hostno, char *buffer, int length)
 	return length;
 }
 
-
 static int
-cciss_scsi_proc_info(struct Scsi_Host *sh,
+cciss_scsi_write_info(struct Scsi_Host *sh,
 		char *buffer, /* data buffer */
-		char **start, 	   /* where data in buffer starts */
-		off_t offset,	   /* offset from start of imaginary file */
-		int length, 	   /* length of data in buffer */
-		int func)	   /* 0 == read, 1 == write */
+		int length) 	   /* length of data in buffer */
 {
+	ctlr_info_t *h = (ctlr_info_t *) sh->hostdata[0];
+	if (h == NULL)  /* This really shouldn't ever happen. */
+		return -EINVAL;
 
-	int buflen, datalen;
-	ctlr_info_t *h;
+	return cciss_scsi_user_command(h, sh->host_no,
+			buffer, length);	
+} 
+
+static int
+cciss_scsi_show_info(struct seq_file *m, struct Scsi_Host *sh)
+{
+
+	ctlr_info_t *h = (ctlr_info_t *) sh->hostdata[0];
 	int i;
 
-	h = (ctlr_info_t *) sh->hostdata[0];
 	if (h == NULL)  /* This really shouldn't ever happen. */
 		return -EINVAL;
 
-	if (func == 0) {	/* User is reading from /proc/scsi/ciss*?/?*  */
-		buflen = sprintf(buffer, "cciss%d: SCSI host: %d\n",
-				h->ctlr, sh->host_no);
-
-		/* this information is needed by apps to know which cciss
-		   device corresponds to which scsi host number without
-		   having to open a scsi target device node.  The device
-		   information is not a duplicate of /proc/scsi/scsi because
-		   the two may be out of sync due to scsi hotplug, rather
-		   this info is for an app to be able to use to know how to
-		   get them back in sync. */
-
-		for (i = 0; i < ccissscsi[h->ctlr].ndevices; i++) {
-			struct cciss_scsi_dev_t *sd =
-				&ccissscsi[h->ctlr].dev[i];
-			buflen += sprintf(&buffer[buflen], "c%db%dt%dl%d %02d "
-				"0x%02x%02x%02x%02x%02x%02x%02x%02x\n",
-				sh->host_no, sd->bus, sd->target, sd->lun,
-				sd->devtype,
-				sd->scsi3addr[0], sd->scsi3addr[1],
-				sd->scsi3addr[2], sd->scsi3addr[3],
-				sd->scsi3addr[4], sd->scsi3addr[5],
-				sd->scsi3addr[6], sd->scsi3addr[7]);
-		}
-		datalen = buflen - offset;
-		if (datalen < 0) { 	/* they're reading past EOF. */
-			datalen = 0;
-			*start = buffer+buflen;	
-		} else
-			*start = buffer + offset;
-		return(datalen);
-	} else 	/* User is writing to /proc/scsi/cciss*?/?*  ... */
-		return cciss_scsi_user_command(h, sh->host_no,
-			buffer, length);	
-} 
+	seq_printf(m, "cciss%d: SCSI host: %d\n",
+			h->ctlr, sh->host_no);
+
+	/* this information is needed by apps to know which cciss
+	   device corresponds to which scsi host number without
+	   having to open a scsi target device node.  The device
+	   information is not a duplicate of /proc/scsi/scsi because
+	   the two may be out of sync due to scsi hotplug, rather
+	   this info is for an app to be able to use to know how to
+	   get them back in sync. */
+
+	for (i = 0; i < ccissscsi[h->ctlr].ndevices; i++) {
+		struct cciss_scsi_dev_t *sd =
+			&ccissscsi[h->ctlr].dev[i];
+		seq_printf(m, "c%db%dt%dl%d %02d "
+			"0x%02x%02x%02x%02x%02x%02x%02x%02x\n",
+			sh->host_no, sd->bus, sd->target, sd->lun,
+			sd->devtype,
+			sd->scsi3addr[0], sd->scsi3addr[1],
+			sd->scsi3addr[2], sd->scsi3addr[3],
+			sd->scsi3addr[4], sd->scsi3addr[5],
+			sd->scsi3addr[6], sd->scsi3addr[7]);
+	}
+	return 0;
+}
 
 /* cciss_scatter_gather takes a struct scsi_cmnd, (cmd), and does the pci 
    dma mapping  and fills in the scatter gather entries of the 
diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c
index 3f08713..3b9e8eb 100644
--- a/drivers/block/cpqarray.c
+++ b/drivers/block/cpqarray.c
@@ -296,7 +296,7 @@ static int ida_proc_show(struct seq_file *m, void *v)
 
 static int ida_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, ida_proc_show, PDE(inode)->data);
+	return single_open(file, ida_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations ida_proc_fops = {
diff --git a/drivers/block/drbd/drbd_actlog.c b/drivers/block/drbd/drbd_actlog.c
index 92510f8..6608076 100644
--- a/drivers/block/drbd/drbd_actlog.c
+++ b/drivers/block/drbd/drbd_actlog.c
@@ -104,7 +104,6 @@ struct update_al_work {
 	int err;
 };
 
-static int al_write_transaction(struct drbd_conf *mdev);
 
 void *drbd_md_get_buffer(struct drbd_conf *mdev)
 {
@@ -168,7 +167,11 @@ static int _drbd_md_sync_page_io(struct drbd_conf *mdev,
 	bio->bi_end_io = drbd_md_io_complete;
 	bio->bi_rw = rw;
 
-	if (!get_ldev_if_state(mdev, D_ATTACHING)) {  /* Corresponding put_ldev in drbd_md_io_complete() */
+	if (!(rw & WRITE) && mdev->state.disk == D_DISKLESS && mdev->ldev == NULL)
+		/* special case, drbd_md_read() during drbd_adm_attach(): no get_ldev */
+		;
+	else if (!get_ldev_if_state(mdev, D_ATTACHING)) {
+		/* Corresponding put_ldev in drbd_md_io_complete() */
 		dev_err(DEV, "ASSERT FAILED: get_ldev_if_state() == 1 in _drbd_md_sync_page_io()\n");
 		err = -ENODEV;
 		goto out;
@@ -199,9 +202,10 @@ int drbd_md_sync_page_io(struct drbd_conf *mdev, struct drbd_backing_dev *bdev,
 
 	BUG_ON(!bdev->md_bdev);
 
-	dev_dbg(DEV, "meta_data io: %s [%d]:%s(,%llus,%s)\n",
+	dev_dbg(DEV, "meta_data io: %s [%d]:%s(,%llus,%s) %pS\n",
 	     current->comm, current->pid, __func__,
-	     (unsigned long long)sector, (rw & WRITE) ? "WRITE" : "READ");
+	     (unsigned long long)sector, (rw & WRITE) ? "WRITE" : "READ",
+	     (void*)_RET_IP_ );
 
 	if (sector < drbd_md_first_sector(bdev) ||
 	    sector + 7 > drbd_md_last_sector(bdev))
@@ -209,7 +213,8 @@ int drbd_md_sync_page_io(struct drbd_conf *mdev, struct drbd_backing_dev *bdev,
 		     current->comm, current->pid, __func__,
 		     (unsigned long long)sector, (rw & WRITE) ? "WRITE" : "READ");
 
-	err = _drbd_md_sync_page_io(mdev, bdev, iop, sector, rw, MD_BLOCK_SIZE);
+	/* we do all our meta data IO in aligned 4k blocks. */
+	err = _drbd_md_sync_page_io(mdev, bdev, iop, sector, rw, 4096);
 	if (err) {
 		dev_err(DEV, "drbd_md_sync_page_io(,%llus,%s) failed with error %d\n",
 		    (unsigned long long)sector, (rw & WRITE) ? "WRITE" : "READ", err);
@@ -217,44 +222,99 @@ int drbd_md_sync_page_io(struct drbd_conf *mdev, struct drbd_backing_dev *bdev,
 	return err;
 }
 
-static struct lc_element *_al_get(struct drbd_conf *mdev, unsigned int enr)
+static struct bm_extent *find_active_resync_extent(struct drbd_conf *mdev, unsigned int enr)
 {
-	struct lc_element *al_ext;
 	struct lc_element *tmp;
-	int wake;
-
-	spin_lock_irq(&mdev->al_lock);
 	tmp = lc_find(mdev->resync, enr/AL_EXT_PER_BM_SECT);
 	if (unlikely(tmp != NULL)) {
 		struct bm_extent  *bm_ext = lc_entry(tmp, struct bm_extent, lce);
-		if (test_bit(BME_NO_WRITES, &bm_ext->flags)) {
-			wake = !test_and_set_bit(BME_PRIORITY, &bm_ext->flags);
-			spin_unlock_irq(&mdev->al_lock);
-			if (wake)
-				wake_up(&mdev->al_wait);
-			return NULL;
-		}
+		if (test_bit(BME_NO_WRITES, &bm_ext->flags))
+			return bm_ext;
+	}
+	return NULL;
+}
+
+static struct lc_element *_al_get(struct drbd_conf *mdev, unsigned int enr, bool nonblock)
+{
+	struct lc_element *al_ext;
+	struct bm_extent *bm_ext;
+	int wake;
+
+	spin_lock_irq(&mdev->al_lock);
+	bm_ext = find_active_resync_extent(mdev, enr);
+	if (bm_ext) {
+		wake = !test_and_set_bit(BME_PRIORITY, &bm_ext->flags);
+		spin_unlock_irq(&mdev->al_lock);
+		if (wake)
+			wake_up(&mdev->al_wait);
+		return NULL;
 	}
-	al_ext = lc_get(mdev->act_log, enr);
+	if (nonblock)
+		al_ext = lc_try_get(mdev->act_log, enr);
+	else
+		al_ext = lc_get(mdev->act_log, enr);
 	spin_unlock_irq(&mdev->al_lock);
 	return al_ext;
 }
 
-void drbd_al_begin_io(struct drbd_conf *mdev, struct drbd_interval *i)
+bool drbd_al_begin_io_fastpath(struct drbd_conf *mdev, struct drbd_interval *i)
 {
 	/* for bios crossing activity log extent boundaries,
 	 * we may need to activate two extents in one go */
 	unsigned first = i->sector >> (AL_EXTENT_SHIFT-9);
 	unsigned last = i->size == 0 ? first : (i->sector + (i->size >> 9) - 1) >> (AL_EXTENT_SHIFT-9);
-	unsigned enr;
-	bool locked = false;
 
+	D_ASSERT((unsigned)(last - first) <= 1);
+	D_ASSERT(atomic_read(&mdev->local_cnt) > 0);
+
+	/* FIXME figure out a fast path for bios crossing AL extent boundaries */
+	if (first != last)
+		return false;
+
+	return _al_get(mdev, first, true);
+}
+
+bool drbd_al_begin_io_prepare(struct drbd_conf *mdev, struct drbd_interval *i)
+{
+	/* for bios crossing activity log extent boundaries,
+	 * we may need to activate two extents in one go */
+	unsigned first = i->sector >> (AL_EXTENT_SHIFT-9);
+	unsigned last = i->size == 0 ? first : (i->sector + (i->size >> 9) - 1) >> (AL_EXTENT_SHIFT-9);
+	unsigned enr;
+	bool need_transaction = false;
 
 	D_ASSERT(first <= last);
 	D_ASSERT(atomic_read(&mdev->local_cnt) > 0);
 
-	for (enr = first; enr <= last; enr++)
-		wait_event(mdev->al_wait, _al_get(mdev, enr) != NULL);
+	for (enr = first; enr <= last; enr++) {
+		struct lc_element *al_ext;
+		wait_event(mdev->al_wait,
+				(al_ext = _al_get(mdev, enr, false)) != NULL);
+		if (al_ext->lc_number != enr)
+			need_transaction = true;
+	}
+	return need_transaction;
+}
+
+static int al_write_transaction(struct drbd_conf *mdev, bool delegate);
+
+/* When called through generic_make_request(), we must delegate
+ * activity log I/O to the worker thread: a further request
+ * submitted via generic_make_request() within the same task
+ * would be queued on current->bio_list, and would only start
+ * after this function returns (see generic_make_request()).
+ *
+ * However, if we *are* the worker, we must not delegate to ourselves.
+ */
+
+/*
+ * @delegate:   delegate activity log I/O to the worker thread
+ */
+void drbd_al_begin_io_commit(struct drbd_conf *mdev, bool delegate)
+{
+	bool locked = false;
+
+	BUG_ON(delegate && current == mdev->tconn->worker.task);
 
 	/* Serialize multiple transactions.
 	 * This uses test_and_set_bit, memory barrier is implicit.
@@ -264,13 +324,6 @@ void drbd_al_begin_io(struct drbd_conf *mdev, struct drbd_interval *i)
 			(locked = lc_try_lock_for_transaction(mdev->act_log)));
 
 	if (locked) {
-		/* drbd_al_write_transaction(mdev,al_ext,enr);
-		 * recurses into generic_make_request(), which
-		 * disallows recursion, bios being serialized on the
-		 * current->bio_tail list now.
-		 * we have to delegate updates to the activity log
-		 * to the worker thread. */
-
 		/* Double check: it may have been committed by someone else,
 		 * while we have been waiting for the lock. */
 		if (mdev->act_log->pending_changes) {
@@ -280,11 +333,8 @@ void drbd_al_begin_io(struct drbd_conf *mdev, struct drbd_interval *i)
 			write_al_updates = rcu_dereference(mdev->ldev->disk_conf)->al_updates;
 			rcu_read_unlock();
 
-			if (write_al_updates) {
-				al_write_transaction(mdev);
-				mdev->al_writ_cnt++;
-			}
-
+			if (write_al_updates)
+				al_write_transaction(mdev, delegate);
 			spin_lock_irq(&mdev->al_lock);
 			/* FIXME
 			if (err)
@@ -298,6 +348,66 @@ void drbd_al_begin_io(struct drbd_conf *mdev, struct drbd_interval *i)
 	}
 }
 
+/*
+ * @delegate:   delegate activity log I/O to the worker thread
+ */
+void drbd_al_begin_io(struct drbd_conf *mdev, struct drbd_interval *i, bool delegate)
+{
+	BUG_ON(delegate && current == mdev->tconn->worker.task);
+
+	if (drbd_al_begin_io_prepare(mdev, i))
+		drbd_al_begin_io_commit(mdev, delegate);
+}
+
+int drbd_al_begin_io_nonblock(struct drbd_conf *mdev, struct drbd_interval *i)
+{
+	struct lru_cache *al = mdev->act_log;
+	/* for bios crossing activity log extent boundaries,
+	 * we may need to activate two extents in one go */
+	unsigned first = i->sector >> (AL_EXTENT_SHIFT-9);
+	unsigned last = i->size == 0 ? first : (i->sector + (i->size >> 9) - 1) >> (AL_EXTENT_SHIFT-9);
+	unsigned nr_al_extents;
+	unsigned available_update_slots;
+	unsigned enr;
+
+	D_ASSERT(first <= last);
+
+	nr_al_extents = 1 + last - first; /* worst case: all touched extends are cold. */
+	available_update_slots = min(al->nr_elements - al->used,
+				al->max_pending_changes - al->pending_changes);
+
+	/* We want all necessary updates for a given request within the same transaction
+	 * We could first check how many updates are *actually* needed,
+	 * and use that instead of the worst-case nr_al_extents */
+	if (available_update_slots < nr_al_extents)
+		return -EWOULDBLOCK;
+
+	/* Is resync active in this area? */
+	for (enr = first; enr <= last; enr++) {
+		struct lc_element *tmp;
+		tmp = lc_find(mdev->resync, enr/AL_EXT_PER_BM_SECT);
+		if (unlikely(tmp != NULL)) {
+			struct bm_extent  *bm_ext = lc_entry(tmp, struct bm_extent, lce);
+			if (test_bit(BME_NO_WRITES, &bm_ext->flags)) {
+				if (!test_and_set_bit(BME_PRIORITY, &bm_ext->flags))
+					return -EBUSY;
+				return -EWOULDBLOCK;
+			}
+		}
+	}
+
+	/* Checkout the refcounts.
+	 * Given that we checked for available elements and update slots above,
+	 * this has to be successful. */
+	for (enr = first; enr <= last; enr++) {
+		struct lc_element *al_ext;
+		al_ext = lc_get_cumulative(mdev->act_log, enr);
+		if (!al_ext)
+			dev_info(DEV, "LOGIC BUG for enr=%u\n", enr);
+	}
+	return 0;
+}
+
 void drbd_al_complete_io(struct drbd_conf *mdev, struct drbd_interval *i)
 {
 	/* for bios crossing activity log extent boundaries,
@@ -350,6 +460,24 @@ static unsigned int rs_extent_to_bm_page(unsigned int rs_enr)
 		 (BM_EXT_SHIFT - BM_BLOCK_SHIFT));
 }
 
+static sector_t al_tr_number_to_on_disk_sector(struct drbd_conf *mdev)
+{
+	const unsigned int stripes = mdev->ldev->md.al_stripes;
+	const unsigned int stripe_size_4kB = mdev->ldev->md.al_stripe_size_4k;
+
+	/* transaction number, modulo on-disk ring buffer wrap around */
+	unsigned int t = mdev->al_tr_number % (mdev->ldev->md.al_size_4k);
+
+	/* ... to aligned 4k on disk block */
+	t = ((t % stripes) * stripe_size_4kB) + t/stripes;
+
+	/* ... to 512 byte sector in activity log */
+	t *= 8;
+
+	/* ... plus offset to the on disk position */
+	return mdev->ldev->md.md_offset + mdev->ldev->md.al_offset + t;
+}
+
 static int
 _al_write_transaction(struct drbd_conf *mdev)
 {
@@ -432,23 +560,27 @@ _al_write_transaction(struct drbd_conf *mdev)
 	if (mdev->al_tr_cycle >= mdev->act_log->nr_elements)
 		mdev->al_tr_cycle = 0;
 
-	sector =  mdev->ldev->md.md_offset
-		+ mdev->ldev->md.al_offset
-		+ mdev->al_tr_pos * (MD_BLOCK_SIZE>>9);
+	sector = al_tr_number_to_on_disk_sector(mdev);
 
 	crc = crc32c(0, buffer, 4096);
 	buffer->crc32c = cpu_to_be32(crc);
 
 	if (drbd_bm_write_hinted(mdev))
 		err = -EIO;
-		/* drbd_chk_io_error done already */
-	else if (drbd_md_sync_page_io(mdev, mdev->ldev, sector, WRITE)) {
-		err = -EIO;
-		drbd_chk_io_error(mdev, 1, DRBD_META_IO_ERROR);
-	} else {
-		/* advance ringbuffer position and transaction counter */
-		mdev->al_tr_pos = (mdev->al_tr_pos + 1) % (MD_AL_SECTORS*512/MD_BLOCK_SIZE);
-		mdev->al_tr_number++;
+	else {
+		bool write_al_updates;
+		rcu_read_lock();
+		write_al_updates = rcu_dereference(mdev->ldev->disk_conf)->al_updates;
+		rcu_read_unlock();
+		if (write_al_updates) {
+			if (drbd_md_sync_page_io(mdev, mdev->ldev, sector, WRITE)) {
+				err = -EIO;
+				drbd_chk_io_error(mdev, 1, DRBD_META_IO_ERROR);
+			} else {
+				mdev->al_tr_number++;
+				mdev->al_writ_cnt++;
+			}
+		}
 	}
 
 	drbd_md_put_buffer(mdev);
@@ -474,20 +606,18 @@ static int w_al_write_transaction(struct drbd_work *w, int unused)
 /* Calls from worker context (see w_restart_disk_io()) need to write the
    transaction directly. Others came through generic_make_request(),
    those need to delegate it to the worker. */
-static int al_write_transaction(struct drbd_conf *mdev)
+static int al_write_transaction(struct drbd_conf *mdev, bool delegate)
 {
-	struct update_al_work al_work;
-
-	if (current == mdev->tconn->worker.task)
+	if (delegate) {
+		struct update_al_work al_work;
+		init_completion(&al_work.event);
+		al_work.w.cb = w_al_write_transaction;
+		al_work.w.mdev = mdev;
+		drbd_queue_work_front(&mdev->tconn->sender_work, &al_work.w);
+		wait_for_completion(&al_work.event);
+		return al_work.err;
+	} else
 		return _al_write_transaction(mdev);
-
-	init_completion(&al_work.event);
-	al_work.w.cb = w_al_write_transaction;
-	al_work.w.mdev = mdev;
-	drbd_queue_work_front(&mdev->tconn->sender_work, &al_work.w);
-	wait_for_completion(&al_work.event);
-
-	return al_work.err;
 }
 
 static int _try_lc_del(struct drbd_conf *mdev, struct lc_element *al_ext)
diff --git a/drivers/block/drbd/drbd_bitmap.c b/drivers/block/drbd/drbd_bitmap.c
index 8dc2950..046aa17 100644
--- a/drivers/block/drbd/drbd_bitmap.c
+++ b/drivers/block/drbd/drbd_bitmap.c
@@ -612,6 +612,17 @@ static void bm_memset(struct drbd_bitmap *b, size_t offset, int c, size_t len)
 	}
 }
 
+/* For the layout, see comment above drbd_md_set_sector_offsets(). */
+static u64 drbd_md_on_disk_bits(struct drbd_backing_dev *ldev)
+{
+	u64 bitmap_sectors;
+	if (ldev->md.al_offset == 8)
+		bitmap_sectors = ldev->md.md_size_sect - ldev->md.bm_offset;
+	else
+		bitmap_sectors = ldev->md.al_offset - ldev->md.bm_offset;
+	return bitmap_sectors << (9 + 3);
+}
+
 /*
  * make sure the bitmap has enough room for the attached storage,
  * if necessary, resize.
@@ -668,7 +679,7 @@ int drbd_bm_resize(struct drbd_conf *mdev, sector_t capacity, int set_new_bits)
 	words = ALIGN(bits, 64) >> LN2_BPL;
 
 	if (get_ldev(mdev)) {
-		u64 bits_on_disk = ((u64)mdev->ldev->md.md_size_sect-MD_BM_OFFSET) << 12;
+		u64 bits_on_disk = drbd_md_on_disk_bits(mdev->ldev);
 		put_ldev(mdev);
 		if (bits > bits_on_disk) {
 			dev_info(DEV, "bits = %lu\n", bits);
@@ -937,7 +948,8 @@ static void bm_aio_ctx_destroy(struct kref *kref)
 }
 
 /* bv_page may be a copy, or may be the original */
-static void bm_async_io_complete(struct bio *bio, int error)
+static void bm_async_io_complete(struct bio *bio, int error,
+				 struct batch_complete *batch)
 {
 	struct bm_aio_ctx *ctx = bio->bi_private;
 	struct drbd_conf *mdev = ctx->mdev;
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h
index 6b51afa..f943aac 100644
--- a/drivers/block/drbd/drbd_int.h
+++ b/drivers/block/drbd/drbd_int.h
@@ -753,13 +753,16 @@ struct drbd_md {
 	u32 flags;
 	u32 md_size_sect;
 
-	s32 al_offset;	/* signed relative sector offset to al area */
+	s32 al_offset;	/* signed relative sector offset to activity log */
 	s32 bm_offset;	/* signed relative sector offset to bitmap */
 
-	/* u32 al_nr_extents;	   important for restoring the AL
-	 * is stored into  ldev->dc.al_extents, which in turn
-	 * gets applied to act_log->nr_elements
-	 */
+	/* cached value of bdev->disk_conf->meta_dev_idx (see below) */
+	s32 meta_dev_idx;
+
+	/* see al_tr_number_to_on_disk_sector() */
+	u32 al_stripes;
+	u32 al_stripe_size_4k;
+	u32 al_size_4k; /* cached product of the above */
 };
 
 struct drbd_backing_dev {
@@ -891,6 +894,14 @@ struct drbd_tconn {			/* is a resource from the config file */
 	} send;
 };
 
+struct submit_worker {
+	struct workqueue_struct *wq;
+	struct work_struct worker;
+
+	spinlock_t lock;
+	struct list_head writes;
+};
+
 struct drbd_conf {
 	struct drbd_tconn *tconn;
 	int vnr;			/* volume number within the connection */
@@ -1009,7 +1020,6 @@ struct drbd_conf {
 	struct lru_cache *act_log;	/* activity log */
 	unsigned int al_tr_number;
 	int al_tr_cycle;
-	int al_tr_pos;   /* position of the next transaction in the journal */
 	wait_queue_head_t seq_wait;
 	atomic_t packet_seq;
 	unsigned int peer_seq;
@@ -1032,6 +1042,10 @@ struct drbd_conf {
 	atomic_t ap_in_flight; /* App sectors in flight (waiting for ack) */
 	unsigned int peer_max_bio_size;
 	unsigned int local_max_bio_size;
+
+	/* any requests that would block in drbd_make_request()
+	 * are deferred to this single-threaded work queue */
+	struct submit_worker submit;
 };
 
 static inline struct drbd_conf *minor_to_mdev(unsigned int minor)
@@ -1148,25 +1162,44 @@ extern int drbd_bitmap_io_from_worker(struct drbd_conf *mdev,
 		char *why, enum bm_flag flags);
 extern int drbd_bmio_set_n_write(struct drbd_conf *mdev);
 extern int drbd_bmio_clear_n_write(struct drbd_conf *mdev);
-extern void drbd_go_diskless(struct drbd_conf *mdev);
 extern void drbd_ldev_destroy(struct drbd_conf *mdev);
 
 /* Meta data layout
-   We reserve a 128MB Block (4k aligned)
-   * either at the end of the backing device
-   * or on a separate meta data device. */
+ *
+ * We currently have two possible layouts.
+ * Offsets in (512 byte) sectors.
+ * external:
+ *   |----------- md_size_sect ------------------|
+ *   [ 4k superblock ][ activity log ][  Bitmap  ]
+ *   | al_offset == 8 |
+ *   | bm_offset = al_offset + X      |
+ *  ==> bitmap sectors = md_size_sect - bm_offset
+ *
+ *  Variants:
+ *     old, indexed fixed size meta data:
+ *
+ * internal:
+ *            |----------- md_size_sect ------------------|
+ * [data.....][  Bitmap  ][ activity log ][ 4k superblock ][padding*]
+ *                        | al_offset < 0 |
+ *            | bm_offset = al_offset - Y |
+ *  ==> bitmap sectors = Y = al_offset - bm_offset
+ *
+ *  [padding*] are zero or up to 7 unused 512 Byte sectors to the
+ *  end of the device, so that the [4k superblock] will be 4k aligned.
+ *
+ *  The activity log consists of 4k transaction blocks,
+ *  which are written in a ring-buffer, or striped ring-buffer like fashion,
+ *  which are writtensize used to be fixed 32kB,
+ *  but is about to become configurable.
+ */
 
-/* The following numbers are sectors */
-/* Allows up to about 3.8TB, so if you want more,
+/* Our old fixed size meta data layout
+ * allows up to about 3.8TB, so if you want more,
  * you need to use the "flexible" meta data format. */
-#define MD_RESERVED_SECT (128LU << 11)  /* 128 MB, unit sectors */
-#define MD_AL_OFFSET	8    /* 8 Sectors after start of meta area */
-#define MD_AL_SECTORS	64   /* = 32 kB on disk activity log ring buffer */
-#define MD_BM_OFFSET (MD_AL_OFFSET + MD_AL_SECTORS)
-
-/* we do all meta data IO in 4k blocks */
-#define MD_BLOCK_SHIFT	12
-#define MD_BLOCK_SIZE	(1<<MD_BLOCK_SHIFT)
+#define MD_128MB_SECT (128LLU << 11)  /* 128 MB, unit sectors */
+#define MD_4kB_SECT	 8
+#define MD_32kB_SECT	64
 
 /* One activity log extent represents 4M of storage */
 #define AL_EXTENT_SHIFT 22
@@ -1256,7 +1289,6 @@ struct bm_extent {
 
 /* in one sector of the bitmap, we have this many activity_log extents. */
 #define AL_EXT_PER_BM_SECT  (1 << (BM_EXT_SHIFT - AL_EXTENT_SHIFT))
-#define BM_WORDS_PER_AL_EXT (1 << (AL_EXTENT_SHIFT-BM_BLOCK_SHIFT-LN2_BPL))
 
 #define BM_BLOCKS_PER_BM_EXT_B (BM_EXT_SHIFT - BM_BLOCK_SHIFT)
 #define BM_BLOCKS_PER_BM_EXT_MASK  ((1<<BM_BLOCKS_PER_BM_EXT_B) - 1)
@@ -1276,16 +1308,18 @@ struct bm_extent {
  */
 
 #define DRBD_MAX_SECTORS_32 (0xffffffffLU)
-#define DRBD_MAX_SECTORS_BM \
-	  ((MD_RESERVED_SECT - MD_BM_OFFSET) * (1LL<<(BM_EXT_SHIFT-9)))
-#if DRBD_MAX_SECTORS_BM < DRBD_MAX_SECTORS_32
-#define DRBD_MAX_SECTORS      DRBD_MAX_SECTORS_BM
-#define DRBD_MAX_SECTORS_FLEX DRBD_MAX_SECTORS_BM
-#elif !defined(CONFIG_LBDAF) && BITS_PER_LONG == 32
+/* we have a certain meta data variant that has a fixed on-disk size of 128
+ * MiB, of which 4k are our "superblock", and 32k are the fixed size activity
+ * log, leaving this many sectors for the bitmap.
+ */
+
+#define DRBD_MAX_SECTORS_FIXED_BM \
+	  ((MD_128MB_SECT - MD_32kB_SECT - MD_4kB_SECT) * (1LL<<(BM_EXT_SHIFT-9)))
+#if !defined(CONFIG_LBDAF) && BITS_PER_LONG == 32
 #define DRBD_MAX_SECTORS      DRBD_MAX_SECTORS_32
 #define DRBD_MAX_SECTORS_FLEX DRBD_MAX_SECTORS_32
 #else
-#define DRBD_MAX_SECTORS      DRBD_MAX_SECTORS_BM
+#define DRBD_MAX_SECTORS      DRBD_MAX_SECTORS_FIXED_BM
 /* 16 TB in units of sectors */
 #if BITS_PER_LONG == 32
 /* adjust by one page worth of bitmap,
@@ -1418,6 +1452,7 @@ extern void conn_free_crypto(struct drbd_tconn *tconn);
 extern int proc_details;
 
 /* drbd_req */
+extern void do_submit(struct work_struct *ws);
 extern void __drbd_make_request(struct drbd_conf *, struct bio *, unsigned long);
 extern void drbd_make_request(struct request_queue *q, struct bio *bio);
 extern int drbd_read_remote(struct drbd_conf *mdev, struct drbd_request *req);
@@ -1576,7 +1611,10 @@ extern const char *drbd_conn_str(enum drbd_conns s);
 extern const char *drbd_role_str(enum drbd_role s);
 
 /* drbd_actlog.c */
-extern void drbd_al_begin_io(struct drbd_conf *mdev, struct drbd_interval *i);
+extern int drbd_al_begin_io_nonblock(struct drbd_conf *mdev, struct drbd_interval *i);
+extern void drbd_al_begin_io_commit(struct drbd_conf *mdev, bool delegate);
+extern bool drbd_al_begin_io_fastpath(struct drbd_conf *mdev, struct drbd_interval *i);
+extern void drbd_al_begin_io(struct drbd_conf *mdev, struct drbd_interval *i, bool delegate);
 extern void drbd_al_complete_io(struct drbd_conf *mdev, struct drbd_interval *i);
 extern void drbd_rs_complete_io(struct drbd_conf *mdev, sector_t sector);
 extern int drbd_rs_begin_io(struct drbd_conf *mdev, sector_t sector);
@@ -1755,9 +1793,9 @@ static inline void drbd_chk_io_error_(struct drbd_conf *mdev,
  * BTW, for internal meta data, this happens to be the maximum capacity
  * we could agree upon with our peer node.
  */
-static inline sector_t _drbd_md_first_sector(int meta_dev_idx, struct drbd_backing_dev *bdev)
+static inline sector_t drbd_md_first_sector(struct drbd_backing_dev *bdev)
 {
-	switch (meta_dev_idx) {
+	switch (bdev->md.meta_dev_idx) {
 	case DRBD_MD_INDEX_INTERNAL:
 	case DRBD_MD_INDEX_FLEX_INT:
 		return bdev->md.md_offset + bdev->md.bm_offset;
@@ -1767,36 +1805,19 @@ static inline sector_t _drbd_md_first_sector(int meta_dev_idx, struct drbd_backi
 	}
 }
 
-static inline sector_t drbd_md_first_sector(struct drbd_backing_dev *bdev)
-{
-	int meta_dev_idx;
-
-	rcu_read_lock();
-	meta_dev_idx = rcu_dereference(bdev->disk_conf)->meta_dev_idx;
-	rcu_read_unlock();
-
-	return _drbd_md_first_sector(meta_dev_idx, bdev);
-}
-
 /**
  * drbd_md_last_sector() - Return the last sector number of the meta data area
  * @bdev:	Meta data block device.
  */
 static inline sector_t drbd_md_last_sector(struct drbd_backing_dev *bdev)
 {
-	int meta_dev_idx;
-
-	rcu_read_lock();
-	meta_dev_idx = rcu_dereference(bdev->disk_conf)->meta_dev_idx;
-	rcu_read_unlock();
-
-	switch (meta_dev_idx) {
+	switch (bdev->md.meta_dev_idx) {
 	case DRBD_MD_INDEX_INTERNAL:
 	case DRBD_MD_INDEX_FLEX_INT:
-		return bdev->md.md_offset + MD_AL_OFFSET - 1;
+		return bdev->md.md_offset + MD_4kB_SECT -1;
 	case DRBD_MD_INDEX_FLEX_EXT:
 	default:
-		return bdev->md.md_offset + bdev->md.md_size_sect;
+		return bdev->md.md_offset + bdev->md.md_size_sect -1;
 	}
 }
 
@@ -1818,18 +1839,13 @@ static inline sector_t drbd_get_capacity(struct block_device *bdev)
 static inline sector_t drbd_get_max_capacity(struct drbd_backing_dev *bdev)
 {
 	sector_t s;
-	int meta_dev_idx;
 
-	rcu_read_lock();
-	meta_dev_idx = rcu_dereference(bdev->disk_conf)->meta_dev_idx;
-	rcu_read_unlock();
-
-	switch (meta_dev_idx) {
+	switch (bdev->md.meta_dev_idx) {
 	case DRBD_MD_INDEX_INTERNAL:
 	case DRBD_MD_INDEX_FLEX_INT:
 		s = drbd_get_capacity(bdev->backing_bdev)
 			? min_t(sector_t, DRBD_MAX_SECTORS_FLEX,
-				_drbd_md_first_sector(meta_dev_idx, bdev))
+				drbd_md_first_sector(bdev))
 			: 0;
 		break;
 	case DRBD_MD_INDEX_FLEX_EXT:
@@ -1848,39 +1864,24 @@ static inline sector_t drbd_get_max_capacity(struct drbd_backing_dev *bdev)
 }
 
 /**
- * drbd_md_ss__() - Return the sector number of our meta data super block
- * @mdev:	DRBD device.
+ * drbd_md_ss() - Return the sector number of our meta data super block
  * @bdev:	Meta data block device.
  */
-static inline sector_t drbd_md_ss__(struct drbd_conf *mdev,
-				    struct drbd_backing_dev *bdev)
+static inline sector_t drbd_md_ss(struct drbd_backing_dev *bdev)
 {
-	int meta_dev_idx;
+	const int meta_dev_idx = bdev->md.meta_dev_idx;
 
-	rcu_read_lock();
-	meta_dev_idx = rcu_dereference(bdev->disk_conf)->meta_dev_idx;
-	rcu_read_unlock();
-
-	switch (meta_dev_idx) {
-	default: /* external, some index */
-		return MD_RESERVED_SECT * meta_dev_idx;
-	case DRBD_MD_INDEX_INTERNAL:
-		/* with drbd08, internal meta data is always "flexible" */
-	case DRBD_MD_INDEX_FLEX_INT:
-		/* sizeof(struct md_on_disk_07) == 4k
-		 * position: last 4k aligned block of 4k size */
-		if (!bdev->backing_bdev) {
-			if (__ratelimit(&drbd_ratelimit_state)) {
-				dev_err(DEV, "bdev->backing_bdev==NULL\n");
-				dump_stack();
-			}
-			return 0;
-		}
-		return (drbd_get_capacity(bdev->backing_bdev) & ~7ULL)
-			- MD_AL_OFFSET;
-	case DRBD_MD_INDEX_FLEX_EXT:
+	if (meta_dev_idx == DRBD_MD_INDEX_FLEX_EXT)
 		return 0;
-	}
+
+	/* Since drbd08, internal meta data is always "flexible".
+	 * position: last 4k aligned block of 4k size */
+	if (meta_dev_idx == DRBD_MD_INDEX_INTERNAL ||
+	    meta_dev_idx == DRBD_MD_INDEX_FLEX_INT)
+		return (drbd_get_capacity(bdev->backing_bdev) & ~7ULL) - 8;
+
+	/* external, some index; this is the old fixed size layout */
+	return MD_128MB_SECT * bdev->md.meta_dev_idx;
 }
 
 static inline void
@@ -2053,9 +2054,11 @@ static inline void put_ldev(struct drbd_conf *mdev)
 		if (mdev->state.disk == D_DISKLESS)
 			/* even internal references gone, safe to destroy */
 			drbd_ldev_destroy(mdev);
-		if (mdev->state.disk == D_FAILED)
+		if (mdev->state.disk == D_FAILED) {
 			/* all application IO references gone. */
-			drbd_go_diskless(mdev);
+			if (!test_and_set_bit(GO_DISKLESS, &mdev->flags))
+				drbd_queue_work(&mdev->tconn->sender_work, &mdev->go_diskless);
+		}
 		wake_up(&mdev->misc_wait);
 	}
 }
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c
index e98da67..1b93a726 100644
--- a/drivers/block/drbd/drbd_main.c
+++ b/drivers/block/drbd/drbd_main.c
@@ -45,7 +45,7 @@
 #include <linux/reboot.h>
 #include <linux/notifier.h>
 #include <linux/kthread.h>
-
+#include <linux/workqueue.h>
 #define __KERNEL_SYSCALLS__
 #include <linux/unistd.h>
 #include <linux/vmalloc.h>
@@ -2300,6 +2300,7 @@ static void drbd_cleanup(void)
 	idr_for_each_entry(&minors, mdev, i) {
 		idr_remove(&minors, mdev_to_minor(mdev));
 		idr_remove(&mdev->tconn->volumes, mdev->vnr);
+		destroy_workqueue(mdev->submit.wq);
 		del_gendisk(mdev->vdisk);
 		/* synchronize_rcu(); No other threads running at this point */
 		kref_put(&mdev->kref, &drbd_minor_destroy);
@@ -2589,6 +2590,21 @@ void conn_destroy(struct kref *kref)
 	kfree(tconn);
 }
 
+int init_submitter(struct drbd_conf *mdev)
+{
+	/* opencoded create_singlethread_workqueue(),
+	 * to be able to say "drbd%d", ..., minor */
+	mdev->submit.wq = alloc_workqueue("drbd%u_submit",
+			WQ_UNBOUND | WQ_MEM_RECLAIM, 1, mdev->minor);
+	if (!mdev->submit.wq)
+		return -ENOMEM;
+
+	INIT_WORK(&mdev->submit.worker, do_submit);
+	spin_lock_init(&mdev->submit.lock);
+	INIT_LIST_HEAD(&mdev->submit.writes);
+	return 0;
+}
+
 enum drbd_ret_code conn_new_minor(struct drbd_tconn *tconn, unsigned int minor, int vnr)
 {
 	struct drbd_conf *mdev;
@@ -2678,6 +2694,12 @@ enum drbd_ret_code conn_new_minor(struct drbd_tconn *tconn, unsigned int minor,
 		goto out_idr_remove_minor;
 	}
 
+	if (init_submitter(mdev)) {
+		err = ERR_NOMEM;
+		drbd_msg_put_info("unable to create submit workqueue");
+		goto out_idr_remove_vol;
+	}
+
 	add_disk(disk);
 	kref_init(&mdev->kref); /* one ref for both idrs and the the add_disk */
 
@@ -2688,6 +2710,8 @@ enum drbd_ret_code conn_new_minor(struct drbd_tconn *tconn, unsigned int minor,
 
 	return NO_ERROR;
 
+out_idr_remove_vol:
+	idr_remove(&tconn->volumes, vnr_got);
 out_idr_remove_minor:
 	idr_remove(&minors, minor_got);
 	synchronize_rcu();
@@ -2795,6 +2819,7 @@ void drbd_free_bc(struct drbd_backing_dev *ldev)
 	blkdev_put(ldev->backing_bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL);
 	blkdev_put(ldev->md_bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL);
 
+	kfree(ldev->disk_conf);
 	kfree(ldev);
 }
 
@@ -2834,8 +2859,9 @@ void conn_md_sync(struct drbd_tconn *tconn)
 	rcu_read_unlock();
 }
 
+/* aligned 4kByte */
 struct meta_data_on_disk {
-	u64 la_size;           /* last agreed size. */
+	u64 la_size_sect;      /* last agreed size. */
 	u64 uuid[UI_SIZE];   /* UUIDs. */
 	u64 device_uuid;
 	u64 reserved_u64_1;
@@ -2843,13 +2869,17 @@ struct meta_data_on_disk {
 	u32 magic;
 	u32 md_size_sect;
 	u32 al_offset;         /* offset to this block */
-	u32 al_nr_extents;     /* important for restoring the AL */
+	u32 al_nr_extents;     /* important for restoring the AL (userspace) */
 	      /* `-- act_log->nr_elements <-- ldev->dc.al_extents */
 	u32 bm_offset;         /* offset to the bitmap, from here */
 	u32 bm_bytes_per_bit;  /* BM_BLOCK_SIZE */
 	u32 la_peer_max_bio_size;   /* last peer max_bio_size */
-	u32 reserved_u32[3];
 
+	/* see al_tr_number_to_on_disk_sector() */
+	u32 al_stripes;
+	u32 al_stripe_size_4k;
+
+	u8 reserved_u8[4096 - (7*8 + 10*4)];
 } __packed;
 
 /**
@@ -2862,6 +2892,10 @@ void drbd_md_sync(struct drbd_conf *mdev)
 	sector_t sector;
 	int i;
 
+	/* Don't accidentally change the DRBD meta data layout. */
+	BUILD_BUG_ON(UI_SIZE != 4);
+	BUILD_BUG_ON(sizeof(struct meta_data_on_disk) != 4096);
+
 	del_timer(&mdev->md_sync_timer);
 	/* timer may be rearmed by drbd_md_mark_dirty() now. */
 	if (!test_and_clear_bit(MD_DIRTY, &mdev->flags))
@@ -2876,9 +2910,9 @@ void drbd_md_sync(struct drbd_conf *mdev)
 	if (!buffer)
 		goto out;
 
-	memset(buffer, 0, 512);
+	memset(buffer, 0, sizeof(*buffer));
 
-	buffer->la_size = cpu_to_be64(drbd_get_capacity(mdev->this_bdev));
+	buffer->la_size_sect = cpu_to_be64(drbd_get_capacity(mdev->this_bdev));
 	for (i = UI_CURRENT; i < UI_SIZE; i++)
 		buffer->uuid[i] = cpu_to_be64(mdev->ldev->md.uuid[i]);
 	buffer->flags = cpu_to_be32(mdev->ldev->md.flags);
@@ -2893,7 +2927,10 @@ void drbd_md_sync(struct drbd_conf *mdev)
 	buffer->bm_offset = cpu_to_be32(mdev->ldev->md.bm_offset);
 	buffer->la_peer_max_bio_size = cpu_to_be32(mdev->peer_max_bio_size);
 
-	D_ASSERT(drbd_md_ss__(mdev, mdev->ldev) == mdev->ldev->md.md_offset);
+	buffer->al_stripes = cpu_to_be32(mdev->ldev->md.al_stripes);
+	buffer->al_stripe_size_4k = cpu_to_be32(mdev->ldev->md.al_stripe_size_4k);
+
+	D_ASSERT(drbd_md_ss(mdev->ldev) == mdev->ldev->md.md_offset);
 	sector = mdev->ldev->md.md_offset;
 
 	if (drbd_md_sync_page_io(mdev, mdev->ldev, sector, WRITE)) {
@@ -2911,13 +2948,141 @@ out:
 	put_ldev(mdev);
 }
 
+static int check_activity_log_stripe_size(struct drbd_conf *mdev,
+		struct meta_data_on_disk *on_disk,
+		struct drbd_md *in_core)
+{
+	u32 al_stripes = be32_to_cpu(on_disk->al_stripes);
+	u32 al_stripe_size_4k = be32_to_cpu(on_disk->al_stripe_size_4k);
+	u64 al_size_4k;
+
+	/* both not set: default to old fixed size activity log */
+	if (al_stripes == 0 && al_stripe_size_4k == 0) {
+		al_stripes = 1;
+		al_stripe_size_4k = MD_32kB_SECT/8;
+	}
+
+	/* some paranoia plausibility checks */
+
+	/* we need both values to be set */
+	if (al_stripes == 0 || al_stripe_size_4k == 0)
+		goto err;
+
+	al_size_4k = (u64)al_stripes * al_stripe_size_4k;
+
+	/* Upper limit of activity log area, to avoid potential overflow
+	 * problems in al_tr_number_to_on_disk_sector(). As right now, more
+	 * than 72 * 4k blocks total only increases the amount of history,
+	 * limiting this arbitrarily to 16 GB is not a real limitation ;-)  */
+	if (al_size_4k > (16 * 1024 * 1024/4))
+		goto err;
+
+	/* Lower limit: we need at least 8 transaction slots (32kB)
+	 * to not break existing setups */
+	if (al_size_4k < MD_32kB_SECT/8)
+		goto err;
+
+	in_core->al_stripe_size_4k = al_stripe_size_4k;
+	in_core->al_stripes = al_stripes;
+	in_core->al_size_4k = al_size_4k;
+
+	return 0;
+err:
+	dev_err(DEV, "invalid activity log striping: al_stripes=%u, al_stripe_size_4k=%u\n",
+			al_stripes, al_stripe_size_4k);
+	return -EINVAL;
+}
+
+static int check_offsets_and_sizes(struct drbd_conf *mdev, struct drbd_backing_dev *bdev)
+{
+	sector_t capacity = drbd_get_capacity(bdev->md_bdev);
+	struct drbd_md *in_core = &bdev->md;
+	s32 on_disk_al_sect;
+	s32 on_disk_bm_sect;
+
+	/* The on-disk size of the activity log, calculated from offsets, and
+	 * the size of the activity log calculated from the stripe settings,
+	 * should match.
+	 * Though we could relax this a bit: it is ok, if the striped activity log
+	 * fits in the available on-disk activity log size.
+	 * Right now, that would break how resize is implemented.
+	 * TODO: make drbd_determine_dev_size() (and the drbdmeta tool) aware
+	 * of possible unused padding space in the on disk layout. */
+	if (in_core->al_offset < 0) {
+		if (in_core->bm_offset > in_core->al_offset)
+			goto err;
+		on_disk_al_sect = -in_core->al_offset;
+		on_disk_bm_sect = in_core->al_offset - in_core->bm_offset;
+	} else {
+		if (in_core->al_offset != MD_4kB_SECT)
+			goto err;
+		if (in_core->bm_offset < in_core->al_offset + in_core->al_size_4k * MD_4kB_SECT)
+			goto err;
+
+		on_disk_al_sect = in_core->bm_offset - MD_4kB_SECT;
+		on_disk_bm_sect = in_core->md_size_sect - in_core->bm_offset;
+	}
+
+	/* old fixed size meta data is exactly that: fixed. */
+	if (in_core->meta_dev_idx >= 0) {
+		if (in_core->md_size_sect != MD_128MB_SECT
+		||  in_core->al_offset != MD_4kB_SECT
+		||  in_core->bm_offset != MD_4kB_SECT + MD_32kB_SECT
+		||  in_core->al_stripes != 1
+		||  in_core->al_stripe_size_4k != MD_32kB_SECT/8)
+			goto err;
+	}
+
+	if (capacity < in_core->md_size_sect)
+		goto err;
+	if (capacity - in_core->md_size_sect < drbd_md_first_sector(bdev))
+		goto err;
+
+	/* should be aligned, and at least 32k */
+	if ((on_disk_al_sect & 7) || (on_disk_al_sect < MD_32kB_SECT))
+		goto err;
+
+	/* should fit (for now: exactly) into the available on-disk space;
+	 * overflow prevention is in check_activity_log_stripe_size() above. */
+	if (on_disk_al_sect != in_core->al_size_4k * MD_4kB_SECT)
+		goto err;
+
+	/* again, should be aligned */
+	if (in_core->bm_offset & 7)
+		goto err;
+
+	/* FIXME check for device grow with flex external meta data? */
+
+	/* can the available bitmap space cover the last agreed device size? */
+	if (on_disk_bm_sect < (in_core->la_size_sect+7)/MD_4kB_SECT/8/512)
+		goto err;
+
+	return 0;
+
+err:
+	dev_err(DEV, "meta data offsets don't make sense: idx=%d "
+			"al_s=%u, al_sz4k=%u, al_offset=%d, bm_offset=%d, "
+			"md_size_sect=%u, la_size=%llu, md_capacity=%llu\n",
+			in_core->meta_dev_idx,
+			in_core->al_stripes, in_core->al_stripe_size_4k,
+			in_core->al_offset, in_core->bm_offset, in_core->md_size_sect,
+			(unsigned long long)in_core->la_size_sect,
+			(unsigned long long)capacity);
+
+	return -EINVAL;
+}
+
+
 /**
  * drbd_md_read() - Reads in the meta data super block
  * @mdev:	DRBD device.
  * @bdev:	Device from which the meta data should be read in.
  *
- * Return 0 (NO_ERROR) on success, and an enum drbd_ret_code in case
+ * Return NO_ERROR on success, and an enum drbd_ret_code in case
  * something goes wrong.
+ *
+ * Called exactly once during drbd_adm_attach(), while still being D_DISKLESS,
+ * even before @bdev is assigned to @mdev->ldev.
  */
 int drbd_md_read(struct drbd_conf *mdev, struct drbd_backing_dev *bdev)
 {
@@ -2925,12 +3090,17 @@ int drbd_md_read(struct drbd_conf *mdev, struct drbd_backing_dev *bdev)
 	u32 magic, flags;
 	int i, rv = NO_ERROR;
 
-	if (!get_ldev_if_state(mdev, D_ATTACHING))
-		return ERR_IO_MD_DISK;
+	if (mdev->state.disk != D_DISKLESS)
+		return ERR_DISK_CONFIGURED;
 
 	buffer = drbd_md_get_buffer(mdev);
 	if (!buffer)
-		goto out;
+		return ERR_NOMEM;
+
+	/* First, figure out where our meta data superblock is located,
+	 * and read it. */
+	bdev->md.meta_dev_idx = bdev->disk_conf->meta_dev_idx;
+	bdev->md.md_offset = drbd_md_ss(bdev);
 
 	if (drbd_md_sync_page_io(mdev, bdev, bdev->md.md_offset, READ)) {
 		/* NOTE: can't do normal error processing here as this is
@@ -2949,45 +3119,51 @@ int drbd_md_read(struct drbd_conf *mdev, struct drbd_backing_dev *bdev)
 		rv = ERR_MD_UNCLEAN;
 		goto err;
 	}
+
+	rv = ERR_MD_INVALID;
 	if (magic != DRBD_MD_MAGIC_08) {
 		if (magic == DRBD_MD_MAGIC_07)
 			dev_err(DEV, "Found old (0.7) meta data magic. Did you \"drbdadm create-md\"?\n");
 		else
 			dev_err(DEV, "Meta data magic not found. Did you \"drbdadm create-md\"?\n");
-		rv = ERR_MD_INVALID;
 		goto err;
 	}
-	if (be32_to_cpu(buffer->al_offset) != bdev->md.al_offset) {
-		dev_err(DEV, "unexpected al_offset: %d (expected %d)\n",
-		    be32_to_cpu(buffer->al_offset), bdev->md.al_offset);
-		rv = ERR_MD_INVALID;
+
+	if (be32_to_cpu(buffer->bm_bytes_per_bit) != BM_BLOCK_SIZE) {
+		dev_err(DEV, "unexpected bm_bytes_per_bit: %u (expected %u)\n",
+		    be32_to_cpu(buffer->bm_bytes_per_bit), BM_BLOCK_SIZE);
 		goto err;
 	}
+
+
+	/* convert to in_core endian */
+	bdev->md.la_size_sect = be64_to_cpu(buffer->la_size_sect);
+	for (i = UI_CURRENT; i < UI_SIZE; i++)
+		bdev->md.uuid[i] = be64_to_cpu(buffer->uuid[i]);
+	bdev->md.flags = be32_to_cpu(buffer->flags);
+	bdev->md.device_uuid = be64_to_cpu(buffer->device_uuid);
+
+	bdev->md.md_size_sect = be32_to_cpu(buffer->md_size_sect);
+	bdev->md.al_offset = be32_to_cpu(buffer->al_offset);
+	bdev->md.bm_offset = be32_to_cpu(buffer->bm_offset);
+
+	if (check_activity_log_stripe_size(mdev, buffer, &bdev->md))
+		goto err;
+	if (check_offsets_and_sizes(mdev, bdev))
+		goto err;
+
 	if (be32_to_cpu(buffer->bm_offset) != bdev->md.bm_offset) {
 		dev_err(DEV, "unexpected bm_offset: %d (expected %d)\n",
 		    be32_to_cpu(buffer->bm_offset), bdev->md.bm_offset);
-		rv = ERR_MD_INVALID;
 		goto err;
 	}
 	if (be32_to_cpu(buffer->md_size_sect) != bdev->md.md_size_sect) {
 		dev_err(DEV, "unexpected md_size: %u (expected %u)\n",
 		    be32_to_cpu(buffer->md_size_sect), bdev->md.md_size_sect);
-		rv = ERR_MD_INVALID;
 		goto err;
 	}
 
-	if (be32_to_cpu(buffer->bm_bytes_per_bit) != BM_BLOCK_SIZE) {
-		dev_err(DEV, "unexpected bm_bytes_per_bit: %u (expected %u)\n",
-		    be32_to_cpu(buffer->bm_bytes_per_bit), BM_BLOCK_SIZE);
-		rv = ERR_MD_INVALID;
-		goto err;
-	}
-
-	bdev->md.la_size_sect = be64_to_cpu(buffer->la_size);
-	for (i = UI_CURRENT; i < UI_SIZE; i++)
-		bdev->md.uuid[i] = be64_to_cpu(buffer->uuid[i]);
-	bdev->md.flags = be32_to_cpu(buffer->flags);
-	bdev->md.device_uuid = be64_to_cpu(buffer->device_uuid);
+	rv = NO_ERROR;
 
 	spin_lock_irq(&mdev->tconn->req_lock);
 	if (mdev->state.conn < C_CONNECTED) {
@@ -3000,8 +3176,6 @@ int drbd_md_read(struct drbd_conf *mdev, struct drbd_backing_dev *bdev)
 
  err:
 	drbd_md_put_buffer(mdev);
- out:
-	put_ldev(mdev);
 
 	return rv;
 }
@@ -3239,8 +3413,12 @@ static int w_go_diskless(struct drbd_work *w, int unused)
 	 * end up here after a failed attach, before ldev was even assigned.
 	 */
 	if (mdev->bitmap && mdev->ldev) {
+		/* An interrupted resync or similar is allowed to recounts bits
+		 * while we detach.
+		 * Any modifications would not be expected anymore, though.
+		 */
 		if (drbd_bitmap_io_from_worker(mdev, drbd_bm_write,
-					"detach", BM_LOCKED_MASK)) {
+					"detach", BM_LOCKED_TEST_ALLOWED)) {
 			if (test_bit(WAS_READ_ERROR, &mdev->flags)) {
 				drbd_md_set_flag(mdev, MDF_FULL_SYNC);
 				drbd_md_sync(mdev);
@@ -3252,13 +3430,6 @@ static int w_go_diskless(struct drbd_work *w, int unused)
 	return 0;
 }
 
-void drbd_go_diskless(struct drbd_conf *mdev)
-{
-	D_ASSERT(mdev->state.disk == D_FAILED);
-	if (!test_and_set_bit(GO_DISKLESS, &mdev->flags))
-		drbd_queue_work(&mdev->tconn->sender_work, &mdev->go_diskless);
-}
-
 /**
  * drbd_queue_bitmap_io() - Queues an IO operation on the whole bitmap
  * @mdev:	DRBD device.
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c
index 2af26fc..9e3f441 100644
--- a/drivers/block/drbd/drbd_nl.c
+++ b/drivers/block/drbd/drbd_nl.c
@@ -696,37 +696,52 @@ out:
 	return 0;
 }
 
-/* initializes the md.*_offset members, so we are able to find
- * the on disk meta data */
+/* Initializes the md.*_offset members, so we are able to find
+ * the on disk meta data.
+ *
+ * We currently have two possible layouts:
+ * external:
+ *   |----------- md_size_sect ------------------|
+ *   [ 4k superblock ][ activity log ][  Bitmap  ]
+ *   | al_offset == 8 |
+ *   | bm_offset = al_offset + X      |
+ *  ==> bitmap sectors = md_size_sect - bm_offset
+ *
+ * internal:
+ *            |----------- md_size_sect ------------------|
+ * [data.....][  Bitmap  ][ activity log ][ 4k superblock ]
+ *                        | al_offset < 0 |
+ *            | bm_offset = al_offset - Y |
+ *  ==> bitmap sectors = Y = al_offset - bm_offset
+ *
+ *  Activity log size used to be fixed 32kB,
+ *  but is about to become configurable.
+ */
 static void drbd_md_set_sector_offsets(struct drbd_conf *mdev,
 				       struct drbd_backing_dev *bdev)
 {
 	sector_t md_size_sect = 0;
-	int meta_dev_idx;
+	unsigned int al_size_sect = bdev->md.al_size_4k * 8;
 
-	rcu_read_lock();
-	meta_dev_idx = rcu_dereference(bdev->disk_conf)->meta_dev_idx;
+	bdev->md.md_offset = drbd_md_ss(bdev);
 
-	switch (meta_dev_idx) {
+	switch (bdev->md.meta_dev_idx) {
 	default:
 		/* v07 style fixed size indexed meta data */
-		bdev->md.md_size_sect = MD_RESERVED_SECT;
-		bdev->md.md_offset = drbd_md_ss__(mdev, bdev);
-		bdev->md.al_offset = MD_AL_OFFSET;
-		bdev->md.bm_offset = MD_BM_OFFSET;
+		bdev->md.md_size_sect = MD_128MB_SECT;
+		bdev->md.al_offset = MD_4kB_SECT;
+		bdev->md.bm_offset = MD_4kB_SECT + al_size_sect;
 		break;
 	case DRBD_MD_INDEX_FLEX_EXT:
 		/* just occupy the full device; unit: sectors */
 		bdev->md.md_size_sect = drbd_get_capacity(bdev->md_bdev);
-		bdev->md.md_offset = 0;
-		bdev->md.al_offset = MD_AL_OFFSET;
-		bdev->md.bm_offset = MD_BM_OFFSET;
+		bdev->md.al_offset = MD_4kB_SECT;
+		bdev->md.bm_offset = MD_4kB_SECT + al_size_sect;
 		break;
 	case DRBD_MD_INDEX_INTERNAL:
 	case DRBD_MD_INDEX_FLEX_INT:
-		bdev->md.md_offset = drbd_md_ss__(mdev, bdev);
 		/* al size is still fixed */
-		bdev->md.al_offset = -MD_AL_SECTORS;
+		bdev->md.al_offset = -al_size_sect;
 		/* we need (slightly less than) ~ this much bitmap sectors: */
 		md_size_sect = drbd_get_capacity(bdev->backing_bdev);
 		md_size_sect = ALIGN(md_size_sect, BM_SECT_PER_EXT);
@@ -735,14 +750,13 @@ static void drbd_md_set_sector_offsets(struct drbd_conf *mdev,
 
 		/* plus the "drbd meta data super block",
 		 * and the activity log; */
-		md_size_sect += MD_BM_OFFSET;
+		md_size_sect += MD_4kB_SECT + al_size_sect;
 
 		bdev->md.md_size_sect = md_size_sect;
 		/* bitmap offset is adjusted by 'super' block size */
-		bdev->md.bm_offset   = -md_size_sect + MD_AL_OFFSET;
+		bdev->md.bm_offset   = -md_size_sect + MD_4kB_SECT;
 		break;
 	}
-	rcu_read_unlock();
 }
 
 /* input size is expected to be in KB */
@@ -805,7 +819,7 @@ void drbd_resume_io(struct drbd_conf *mdev)
 enum determine_dev_size drbd_determine_dev_size(struct drbd_conf *mdev, enum dds_flags flags) __must_hold(local)
 {
 	sector_t prev_first_sect, prev_size; /* previous meta location */
-	sector_t la_size, u_size;
+	sector_t la_size_sect, u_size;
 	sector_t size;
 	char ppb[10];
 
@@ -828,7 +842,7 @@ enum determine_dev_size drbd_determine_dev_size(struct drbd_conf *mdev, enum dds
 
 	prev_first_sect = drbd_md_first_sector(mdev->ldev);
 	prev_size = mdev->ldev->md.md_size_sect;
-	la_size = mdev->ldev->md.la_size_sect;
+	la_size_sect = mdev->ldev->md.la_size_sect;
 
 	/* TODO: should only be some assert here, not (re)init... */
 	drbd_md_set_sector_offsets(mdev, mdev->ldev);
@@ -864,7 +878,7 @@ enum determine_dev_size drbd_determine_dev_size(struct drbd_conf *mdev, enum dds
 	if (rv == dev_size_error)
 		goto out;
 
-	la_size_changed = (la_size != mdev->ldev->md.la_size_sect);
+	la_size_changed = (la_size_sect != mdev->ldev->md.la_size_sect);
 
 	md_moved = prev_first_sect != drbd_md_first_sector(mdev->ldev)
 		|| prev_size	   != mdev->ldev->md.md_size_sect;
@@ -886,9 +900,9 @@ enum determine_dev_size drbd_determine_dev_size(struct drbd_conf *mdev, enum dds
 		drbd_md_mark_dirty(mdev);
 	}
 
-	if (size > la_size)
+	if (size > la_size_sect)
 		rv = grew;
-	if (size < la_size)
+	if (size < la_size_sect)
 		rv = shrunk;
 out:
 	lc_unlock(mdev->act_log);
@@ -903,7 +917,7 @@ drbd_new_dev_size(struct drbd_conf *mdev, struct drbd_backing_dev *bdev,
 		  sector_t u_size, int assume_peer_has_space)
 {
 	sector_t p_size = mdev->p_size;   /* partner's disk size. */
-	sector_t la_size = bdev->md.la_size_sect; /* last agreed size. */
+	sector_t la_size_sect = bdev->md.la_size_sect; /* last agreed size. */
 	sector_t m_size; /* my size */
 	sector_t size = 0;
 
@@ -917,8 +931,8 @@ drbd_new_dev_size(struct drbd_conf *mdev, struct drbd_backing_dev *bdev,
 	if (p_size && m_size) {
 		size = min_t(sector_t, p_size, m_size);
 	} else {
-		if (la_size) {
-			size = la_size;
+		if (la_size_sect) {
+			size = la_size_sect;
 			if (m_size && m_size < size)
 				size = m_size;
 			if (p_size && p_size < size)
@@ -1127,15 +1141,32 @@ static bool should_set_defaults(struct genl_info *info)
 	return 0 != (flags & DRBD_GENL_F_SET_DEFAULTS);
 }
 
-static void enforce_disk_conf_limits(struct disk_conf *dc)
+static unsigned int drbd_al_extents_max(struct drbd_backing_dev *bdev)
 {
-	if (dc->al_extents < DRBD_AL_EXTENTS_MIN)
-		dc->al_extents = DRBD_AL_EXTENTS_MIN;
-	if (dc->al_extents > DRBD_AL_EXTENTS_MAX)
-		dc->al_extents = DRBD_AL_EXTENTS_MAX;
+	/* This is limited by 16 bit "slot" numbers,
+	 * and by available on-disk context storage.
+	 *
+	 * Also (u16)~0 is special (denotes a "free" extent).
+	 *
+	 * One transaction occupies one 4kB on-disk block,
+	 * we have n such blocks in the on disk ring buffer,
+	 * the "current" transaction may fail (n-1),
+	 * and there is 919 slot numbers context information per transaction.
+	 *
+	 * 72 transaction blocks amounts to more than 2**16 context slots,
+	 * so cap there first.
+	 */
+	const unsigned int max_al_nr = DRBD_AL_EXTENTS_MAX;
+	const unsigned int sufficient_on_disk =
+		(max_al_nr + AL_CONTEXT_PER_TRANSACTION -1)
+		/AL_CONTEXT_PER_TRANSACTION;
+
+	unsigned int al_size_4k = bdev->md.al_size_4k;
+
+	if (al_size_4k > sufficient_on_disk)
+		return max_al_nr;
 
-	if (dc->c_plan_ahead > DRBD_C_PLAN_AHEAD_MAX)
-		dc->c_plan_ahead = DRBD_C_PLAN_AHEAD_MAX;
+	return (al_size_4k - 1) * AL_CONTEXT_PER_TRANSACTION;
 }
 
 int drbd_adm_disk_opts(struct sk_buff *skb, struct genl_info *info)
@@ -1182,7 +1213,13 @@ int drbd_adm_disk_opts(struct sk_buff *skb, struct genl_info *info)
 	if (!expect(new_disk_conf->resync_rate >= 1))
 		new_disk_conf->resync_rate = 1;
 
-	enforce_disk_conf_limits(new_disk_conf);
+	if (new_disk_conf->al_extents < DRBD_AL_EXTENTS_MIN)
+		new_disk_conf->al_extents = DRBD_AL_EXTENTS_MIN;
+	if (new_disk_conf->al_extents > drbd_al_extents_max(mdev->ldev))
+		new_disk_conf->al_extents = drbd_al_extents_max(mdev->ldev);
+
+	if (new_disk_conf->c_plan_ahead > DRBD_C_PLAN_AHEAD_MAX)
+		new_disk_conf->c_plan_ahead = DRBD_C_PLAN_AHEAD_MAX;
 
 	fifo_size = (new_disk_conf->c_plan_ahead * 10 * SLEEP_TIME) / HZ;
 	if (fifo_size != mdev->rs_plan_s->size) {
@@ -1330,7 +1367,8 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info)
 		goto fail;
 	}
 
-	enforce_disk_conf_limits(new_disk_conf);
+	if (new_disk_conf->c_plan_ahead > DRBD_C_PLAN_AHEAD_MAX)
+		new_disk_conf->c_plan_ahead = DRBD_C_PLAN_AHEAD_MAX;
 
 	new_plan = fifo_alloc((new_disk_conf->c_plan_ahead * 10 * SLEEP_TIME) / HZ);
 	if (!new_plan) {
@@ -1343,6 +1381,12 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info)
 		goto fail;
 	}
 
+	write_lock_irq(&global_state_lock);
+	retcode = drbd_resync_after_valid(mdev, new_disk_conf->resync_after);
+	write_unlock_irq(&global_state_lock);
+	if (retcode != NO_ERROR)
+		goto fail;
+
 	rcu_read_lock();
 	nc = rcu_dereference(mdev->tconn->net_conf);
 	if (nc) {
@@ -1399,8 +1443,16 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info)
 		goto fail;
 	}
 
-	/* RT - for drbd_get_max_capacity() DRBD_MD_INDEX_FLEX_INT */
-	drbd_md_set_sector_offsets(mdev, nbc);
+	/* Read our meta data super block early.
+	 * This also sets other on-disk offsets. */
+	retcode = drbd_md_read(mdev, nbc);
+	if (retcode != NO_ERROR)
+		goto fail;
+
+	if (new_disk_conf->al_extents < DRBD_AL_EXTENTS_MIN)
+		new_disk_conf->al_extents = DRBD_AL_EXTENTS_MIN;
+	if (new_disk_conf->al_extents > drbd_al_extents_max(nbc))
+		new_disk_conf->al_extents = drbd_al_extents_max(nbc);
 
 	if (drbd_get_max_capacity(nbc) < new_disk_conf->disk_size) {
 		dev_err(DEV, "max capacity %llu smaller than disk size %llu\n",
@@ -1416,7 +1468,7 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info)
 		min_md_device_sectors = (2<<10);
 	} else {
 		max_possible_sectors = DRBD_MAX_SECTORS;
-		min_md_device_sectors = MD_RESERVED_SECT * (new_disk_conf->meta_dev_idx + 1);
+		min_md_device_sectors = MD_128MB_SECT * (new_disk_conf->meta_dev_idx + 1);
 	}
 
 	if (drbd_get_capacity(nbc->md_bdev) < min_md_device_sectors) {
@@ -1467,8 +1519,6 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info)
 	if (!get_ldev_if_state(mdev, D_ATTACHING))
 		goto force_diskless;
 
-	drbd_md_set_sector_offsets(mdev, nbc);
-
 	if (!mdev->bitmap) {
 		if (drbd_bm_init(mdev)) {
 			retcode = ERR_NOMEM;
@@ -1476,10 +1526,6 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info)
 		}
 	}
 
-	retcode = drbd_md_read(mdev, nbc);
-	if (retcode != NO_ERROR)
-		goto force_diskless_dec;
-
 	if (mdev->state.conn < C_CONNECTED &&
 	    mdev->state.role == R_PRIMARY &&
 	    (mdev->ed_uuid & ~((u64)1)) != (nbc->md.uuid[UI_CURRENT] & ~((u64)1))) {
@@ -2158,8 +2204,11 @@ static enum drbd_state_rv conn_try_disconnect(struct drbd_tconn *tconn, bool for
 		return SS_SUCCESS;
 	case SS_PRIMARY_NOP:
 		/* Our state checking code wants to see the peer outdated. */
-		rv = conn_request_state(tconn, NS2(conn, C_DISCONNECTING,
-						pdsk, D_OUTDATED), CS_VERBOSE);
+		rv = conn_request_state(tconn, NS2(conn, C_DISCONNECTING, pdsk, D_OUTDATED), 0);
+
+		if (rv == SS_OUTDATE_WO_CONN) /* lost connection before graceful disconnect succeeded */
+			rv = conn_request_state(tconn, NS(conn, C_DISCONNECTING), CS_VERBOSE);
+
 		break;
 	case SS_CW_FAILED_BY_PEER:
 		/* The peer probably wants to see us outdated. */
@@ -2406,22 +2455,19 @@ int drbd_adm_invalidate(struct sk_buff *skb, struct genl_info *info)
 	wait_event(mdev->misc_wait, !test_bit(BITMAP_IO, &mdev->flags));
 	drbd_flush_workqueue(mdev);
 
-	retcode = _drbd_request_state(mdev, NS(conn, C_STARTING_SYNC_T), CS_ORDERED);
-
-	if (retcode < SS_SUCCESS && retcode != SS_NEED_CONNECTION)
-		retcode = drbd_request_state(mdev, NS(conn, C_STARTING_SYNC_T));
-
-	while (retcode == SS_NEED_CONNECTION) {
-		spin_lock_irq(&mdev->tconn->req_lock);
-		if (mdev->state.conn < C_CONNECTED)
-			retcode = _drbd_set_state(_NS(mdev, disk, D_INCONSISTENT), CS_VERBOSE, NULL);
-		spin_unlock_irq(&mdev->tconn->req_lock);
-
-		if (retcode != SS_NEED_CONNECTION)
-			break;
-
+	/* If we happen to be C_STANDALONE R_SECONDARY, just change to
+	 * D_INCONSISTENT, and set all bits in the bitmap.  Otherwise,
+	 * try to start a resync handshake as sync target for full sync.
+	 */
+	if (mdev->state.conn == C_STANDALONE && mdev->state.role == R_SECONDARY) {
+		retcode = drbd_request_state(mdev, NS(disk, D_INCONSISTENT));
+		if (retcode >= SS_SUCCESS) {
+			if (drbd_bitmap_io(mdev, &drbd_bmio_set_n_write,
+				"set_n_write from invalidate", BM_LOCKED_MASK))
+				retcode = ERR_IO_MD_DISK;
+		}
+	} else
 		retcode = drbd_request_state(mdev, NS(conn, C_STARTING_SYNC_T));
-	}
 	drbd_resume_io(mdev);
 
 out:
@@ -2475,21 +2521,22 @@ int drbd_adm_invalidate_peer(struct sk_buff *skb, struct genl_info *info)
 	wait_event(mdev->misc_wait, !test_bit(BITMAP_IO, &mdev->flags));
 	drbd_flush_workqueue(mdev);
 
-	retcode = _drbd_request_state(mdev, NS(conn, C_STARTING_SYNC_S), CS_ORDERED);
-	if (retcode < SS_SUCCESS) {
-		if (retcode == SS_NEED_CONNECTION && mdev->state.role == R_PRIMARY) {
-			/* The peer will get a resync upon connect anyways.
-			 * Just make that into a full resync. */
-			retcode = drbd_request_state(mdev, NS(pdsk, D_INCONSISTENT));
-			if (retcode >= SS_SUCCESS) {
-				if (drbd_bitmap_io(mdev, &drbd_bmio_set_susp_al,
-						   "set_n_write from invalidate_peer",
-						   BM_LOCKED_SET_ALLOWED))
-					retcode = ERR_IO_MD_DISK;
-			}
-		} else
-			retcode = drbd_request_state(mdev, NS(conn, C_STARTING_SYNC_S));
-	}
+	/* If we happen to be C_STANDALONE R_PRIMARY, just set all bits
+	 * in the bitmap.  Otherwise, try to start a resync handshake
+	 * as sync source for full sync.
+	 */
+	if (mdev->state.conn == C_STANDALONE && mdev->state.role == R_PRIMARY) {
+		/* The peer will get a resync upon connect anyways. Just make that
+		   into a full resync. */
+		retcode = drbd_request_state(mdev, NS(pdsk, D_INCONSISTENT));
+		if (retcode >= SS_SUCCESS) {
+			if (drbd_bitmap_io(mdev, &drbd_bmio_set_susp_al,
+				"set_n_write from invalidate_peer",
+				BM_LOCKED_SET_ALLOWED))
+				retcode = ERR_IO_MD_DISK;
+		}
+	} else
+		retcode = drbd_request_state(mdev, NS(conn, C_STARTING_SYNC_S));
 	drbd_resume_io(mdev);
 
 out:
@@ -3162,6 +3209,7 @@ static enum drbd_ret_code adm_delete_minor(struct drbd_conf *mdev)
 				    CS_VERBOSE + CS_WAIT_COMPLETE);
 		idr_remove(&mdev->tconn->volumes, mdev->vnr);
 		idr_remove(&minors, mdev_to_minor(mdev));
+		destroy_workqueue(mdev->submit.wq);
 		del_gendisk(mdev->vdisk);
 		synchronize_rcu();
 		kref_put(&mdev->kref, &drbd_minor_destroy);
diff --git a/drivers/block/drbd/drbd_proc.c b/drivers/block/drbd/drbd_proc.c
index 56672a6..bf31d41 100644
--- a/drivers/block/drbd/drbd_proc.c
+++ b/drivers/block/drbd/drbd_proc.c
@@ -313,8 +313,14 @@ static int drbd_seq_show(struct seq_file *seq, void *v)
 
 static int drbd_proc_open(struct inode *inode, struct file *file)
 {
-	if (try_module_get(THIS_MODULE))
-		return single_open(file, drbd_seq_show, PDE(inode)->data);
+	int err;
+
+	if (try_module_get(THIS_MODULE)) {
+		err = single_open(file, drbd_seq_show, PDE_DATA(inode));
+		if (err)
+			module_put(THIS_MODULE);
+		return err;
+	}
 	return -ENODEV;
 }
 
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c
index a9eccfc..4222aff 100644
--- a/drivers/block/drbd/drbd_receiver.c
+++ b/drivers/block/drbd/drbd_receiver.c
@@ -757,7 +757,8 @@ static struct socket *drbd_wait_for_connect(struct drbd_tconn *tconn, struct acc
 	rcu_read_unlock();
 
 	timeo = connect_int * HZ;
-	timeo += (random32() & 1) ? timeo / 7 : -timeo / 7; /* 28.5% random jitter */
+	/* 28.5% random jitter */
+	timeo += (prandom_u32() & 1) ? timeo / 7 : -timeo / 7;
 
 	err = wait_for_completion_interruptible_timeout(&ad->door_bell, timeo);
 	if (err <= 0)
@@ -849,6 +850,7 @@ int drbd_connected(struct drbd_conf *mdev)
 		err = drbd_send_current_state(mdev);
 	clear_bit(USE_DEGR_WFC_T, &mdev->flags);
 	clear_bit(RESIZE_PENDING, &mdev->flags);
+	atomic_set(&mdev->ap_in_flight, 0);
 	mod_timer(&mdev->request_timer, jiffies + HZ); /* just start it here. */
 	return err;
 }
@@ -953,7 +955,7 @@ retry:
 				conn_warn(tconn, "Error receiving initial packet\n");
 				sock_release(s);
 randomize:
-				if (random32() & 1)
+				if (prandom_u32() & 1)
 					goto retry;
 			}
 		}
@@ -2265,7 +2267,7 @@ static int receive_Data(struct drbd_tconn *tconn, struct packet_info *pi)
 		drbd_set_out_of_sync(mdev, peer_req->i.sector, peer_req->i.size);
 		peer_req->flags |= EE_CALL_AL_COMPLETE_IO;
 		peer_req->flags &= ~EE_MAY_SET_IN_SYNC;
-		drbd_al_begin_io(mdev, &peer_req->i);
+		drbd_al_begin_io(mdev, &peer_req->i, true);
 	}
 
 	err = drbd_submit_peer_request(mdev, peer_req, rw, DRBD_FAULT_DT_WR);
@@ -2661,7 +2663,6 @@ static int drbd_asb_recover_1p(struct drbd_conf *mdev) __must_hold(local)
 		if (hg == -1 && mdev->state.role == R_PRIMARY) {
 			enum drbd_state_rv rv2;
 
-			drbd_set_role(mdev, R_SECONDARY, 0);
 			 /* drbd_change_state() does not sleep while in SS_IN_TRANSIENT_STATE,
 			  * we might be here in C_WF_REPORT_PARAMS which is transient.
 			  * we do not need to wait for the after state change work either. */
@@ -3992,7 +3993,7 @@ static int receive_state(struct drbd_tconn *tconn, struct packet_info *pi)
 
 	clear_bit(DISCARD_MY_DATA, &mdev->flags);
 
-	drbd_md_sync(mdev); /* update connected indicator, la_size, ... */
+	drbd_md_sync(mdev); /* update connected indicator, la_size_sect, ... */
 
 	return 0;
 }
@@ -4659,8 +4660,8 @@ static int drbd_do_features(struct drbd_tconn *tconn)
 #if !defined(CONFIG_CRYPTO_HMAC) && !defined(CONFIG_CRYPTO_HMAC_MODULE)
 static int drbd_do_auth(struct drbd_tconn *tconn)
 {
-	dev_err(DEV, "This kernel was build without CONFIG_CRYPTO_HMAC.\n");
-	dev_err(DEV, "You need to disable 'cram-hmac-alg' in drbd.conf.\n");
+	conn_err(tconn, "This kernel was build without CONFIG_CRYPTO_HMAC.\n");
+	conn_err(tconn, "You need to disable 'cram-hmac-alg' in drbd.conf.\n");
 	return -1;
 }
 #else
@@ -5257,9 +5258,11 @@ int drbd_asender(struct drbd_thread *thi)
 	bool ping_timeout_active = false;
 	struct net_conf *nc;
 	int ping_timeo, tcp_cork, ping_int;
+	struct sched_param param = { .sched_priority = 2 };
 
-	current->policy = SCHED_RR;  /* Make this a realtime task! */
-	current->rt_priority = 2;    /* more important than all other tasks */
+	rv = sched_setscheduler(current, SCHED_RR, &param);
+	if (rv < 0)
+		conn_err(tconn, "drbd_asender: ERROR set priority, ret=%d\n", rv);
 
 	while (get_t_state(thi) == RUNNING) {
 		drbd_thread_current_set_cpu(thi);
diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c
index 2b8303a..c24379f 100644
--- a/drivers/block/drbd/drbd_req.c
+++ b/drivers/block/drbd/drbd_req.c
@@ -34,14 +34,14 @@
 static bool drbd_may_do_local_read(struct drbd_conf *mdev, sector_t sector, int size);
 
 /* Update disk stats at start of I/O request */
-static void _drbd_start_io_acct(struct drbd_conf *mdev, struct drbd_request *req, struct bio *bio)
+static void _drbd_start_io_acct(struct drbd_conf *mdev, struct drbd_request *req)
 {
-	const int rw = bio_data_dir(bio);
+	const int rw = bio_data_dir(req->master_bio);
 	int cpu;
 	cpu = part_stat_lock();
 	part_round_stats(cpu, &mdev->vdisk->part0);
 	part_stat_inc(cpu, &mdev->vdisk->part0, ios[rw]);
-	part_stat_add(cpu, &mdev->vdisk->part0, sectors[rw], bio_sectors(bio));
+	part_stat_add(cpu, &mdev->vdisk->part0, sectors[rw], req->i.size >> 9);
 	(void) cpu; /* The macro invocations above want the cpu argument, I do not like
 		       the compiler warning about cpu only assigned but never used... */
 	part_inc_in_flight(&mdev->vdisk->part0, rw);
@@ -263,8 +263,7 @@ void drbd_req_complete(struct drbd_request *req, struct bio_and_error *m)
 		else
 			root = &mdev->read_requests;
 		drbd_remove_request_interval(root, req);
-	} else if (!(s & RQ_POSTPONED))
-		D_ASSERT((s & (RQ_NET_MASK & ~RQ_NET_DONE)) == 0);
+	}
 
 	/* Before we can signal completion to the upper layers,
 	 * we may need to close the current transfer log epoch.
@@ -755,6 +754,11 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what,
 		D_ASSERT(req->rq_state & RQ_NET_PENDING);
 		mod_rq_state(req, m, RQ_NET_PENDING, RQ_NET_OK|RQ_NET_DONE);
 		break;
+
+	case QUEUE_AS_DRBD_BARRIER:
+		start_new_tl_epoch(mdev->tconn);
+		mod_rq_state(req, m, 0, RQ_NET_OK|RQ_NET_DONE);
+		break;
 	};
 
 	return rv;
@@ -861,8 +865,10 @@ static void maybe_pull_ahead(struct drbd_conf *mdev)
 	bool congested = false;
 	enum drbd_on_congestion on_congestion;
 
+	rcu_read_lock();
 	nc = rcu_dereference(tconn->net_conf);
 	on_congestion = nc ? nc->on_congestion : OC_BLOCK;
+	rcu_read_unlock();
 	if (on_congestion == OC_BLOCK ||
 	    tconn->agreed_pro_version < 96)
 		return;
@@ -956,14 +962,8 @@ static int drbd_process_write_request(struct drbd_request *req)
 	struct drbd_conf *mdev = req->w.mdev;
 	int remote, send_oos;
 
-	rcu_read_lock();
 	remote = drbd_should_do_remote(mdev->state);
-	if (remote) {
-		maybe_pull_ahead(mdev);
-		remote = drbd_should_do_remote(mdev->state);
-	}
 	send_oos = drbd_should_send_out_of_sync(mdev->state);
-	rcu_read_unlock();
 
 	/* Need to replicate writes.  Unless it is an empty flush,
 	 * which is better mapped to a DRBD P_BARRIER packet,
@@ -975,8 +975,8 @@ static int drbd_process_write_request(struct drbd_request *req)
 		/* The only size==0 bios we expect are empty flushes. */
 		D_ASSERT(req->master_bio->bi_rw & REQ_FLUSH);
 		if (remote)
-			start_new_tl_epoch(mdev->tconn);
-		return 0;
+			_req_mod(req, QUEUE_AS_DRBD_BARRIER);
+		return remote;
 	}
 
 	if (!remote && !send_oos)
@@ -1020,12 +1020,24 @@ drbd_submit_req_private_bio(struct drbd_request *req)
 		bio_endio(bio, -EIO);
 }
 
-void __drbd_make_request(struct drbd_conf *mdev, struct bio *bio, unsigned long start_time)
+static void drbd_queue_write(struct drbd_conf *mdev, struct drbd_request *req)
 {
-	const int rw = bio_rw(bio);
-	struct bio_and_error m = { NULL, };
+	spin_lock(&mdev->submit.lock);
+	list_add_tail(&req->tl_requests, &mdev->submit.writes);
+	spin_unlock(&mdev->submit.lock);
+	queue_work(mdev->submit.wq, &mdev->submit.worker);
+}
+
+/* returns the new drbd_request pointer, if the caller is expected to
+ * drbd_send_and_submit() it (to save latency), or NULL if we queued the
+ * request on the submitter thread.
+ * Returns ERR_PTR(-ENOMEM) if we cannot allocate a drbd_request.
+ */
+struct drbd_request *
+drbd_request_prepare(struct drbd_conf *mdev, struct bio *bio, unsigned long start_time)
+{
+	const int rw = bio_data_dir(bio);
 	struct drbd_request *req;
-	bool no_remote = false;
 
 	/* allocate outside of all locks; */
 	req = drbd_req_new(mdev, bio);
@@ -1035,7 +1047,7 @@ void __drbd_make_request(struct drbd_conf *mdev, struct bio *bio, unsigned long
 		 * if user cannot handle io errors, that's not our business. */
 		dev_err(DEV, "could not kmalloc() req\n");
 		bio_endio(bio, -ENOMEM);
-		return;
+		return ERR_PTR(-ENOMEM);
 	}
 	req->start_time = start_time;
 
@@ -1044,28 +1056,40 @@ void __drbd_make_request(struct drbd_conf *mdev, struct bio *bio, unsigned long
 		req->private_bio = NULL;
 	}
 
-	/* For WRITES going to the local disk, grab a reference on the target
-	 * extent.  This waits for any resync activity in the corresponding
-	 * resync extent to finish, and, if necessary, pulls in the target
-	 * extent into the activity log, which involves further disk io because
-	 * of transactional on-disk meta data updates.
-	 * Empty flushes don't need to go into the activity log, they can only
-	 * flush data for pending writes which are already in there. */
+	/* Update disk stats */
+	_drbd_start_io_acct(mdev, req);
+
 	if (rw == WRITE && req->private_bio && req->i.size
 	&& !test_bit(AL_SUSPENDED, &mdev->flags)) {
+		if (!drbd_al_begin_io_fastpath(mdev, &req->i)) {
+			drbd_queue_write(mdev, req);
+			return NULL;
+		}
 		req->rq_state |= RQ_IN_ACT_LOG;
-		drbd_al_begin_io(mdev, &req->i);
 	}
 
+	return req;
+}
+
+static void drbd_send_and_submit(struct drbd_conf *mdev, struct drbd_request *req)
+{
+	const int rw = bio_rw(req->master_bio);
+	struct bio_and_error m = { NULL, };
+	bool no_remote = false;
+
 	spin_lock_irq(&mdev->tconn->req_lock);
 	if (rw == WRITE) {
 		/* This may temporarily give up the req_lock,
 		 * but will re-aquire it before it returns here.
 		 * Needs to be before the check on drbd_suspended() */
 		complete_conflicting_writes(req);
+		/* no more giving up req_lock from now on! */
+
+		/* check for congestion, and potentially stop sending
+		 * full data updates, but start sending "dirty bits" only. */
+		maybe_pull_ahead(mdev);
 	}
 
-	/* no more giving up req_lock from now on! */
 
 	if (drbd_suspended(mdev)) {
 		/* push back and retry: */
@@ -1078,9 +1102,6 @@ void __drbd_make_request(struct drbd_conf *mdev, struct bio *bio, unsigned long
 		goto out;
 	}
 
-	/* Update disk stats */
-	_drbd_start_io_acct(mdev, req, bio);
-
 	/* We fail READ/READA early, if we can not serve it.
 	 * We must do this before req is registered on any lists.
 	 * Otherwise, drbd_req_complete() will queue failed READ for retry. */
@@ -1137,7 +1158,116 @@ out:
 
 	if (m.bio)
 		complete_master_bio(mdev, &m);
-	return;
+}
+
+void __drbd_make_request(struct drbd_conf *mdev, struct bio *bio, unsigned long start_time)
+{
+	struct drbd_request *req = drbd_request_prepare(mdev, bio, start_time);
+	if (IS_ERR_OR_NULL(req))
+		return;
+	drbd_send_and_submit(mdev, req);
+}
+
+static void submit_fast_path(struct drbd_conf *mdev, struct list_head *incoming)
+{
+	struct drbd_request *req, *tmp;
+	list_for_each_entry_safe(req, tmp, incoming, tl_requests) {
+		const int rw = bio_data_dir(req->master_bio);
+
+		if (rw == WRITE /* rw != WRITE should not even end up here! */
+		&& req->private_bio && req->i.size
+		&& !test_bit(AL_SUSPENDED, &mdev->flags)) {
+			if (!drbd_al_begin_io_fastpath(mdev, &req->i))
+				continue;
+
+			req->rq_state |= RQ_IN_ACT_LOG;
+		}
+
+		list_del_init(&req->tl_requests);
+		drbd_send_and_submit(mdev, req);
+	}
+}
+
+static bool prepare_al_transaction_nonblock(struct drbd_conf *mdev,
+					    struct list_head *incoming,
+					    struct list_head *pending)
+{
+	struct drbd_request *req, *tmp;
+	int wake = 0;
+	int err;
+
+	spin_lock_irq(&mdev->al_lock);
+	list_for_each_entry_safe(req, tmp, incoming, tl_requests) {
+		err = drbd_al_begin_io_nonblock(mdev, &req->i);
+		if (err == -EBUSY)
+			wake = 1;
+		if (err)
+			continue;
+		req->rq_state |= RQ_IN_ACT_LOG;
+		list_move_tail(&req->tl_requests, pending);
+	}
+	spin_unlock_irq(&mdev->al_lock);
+	if (wake)
+		wake_up(&mdev->al_wait);
+
+	return !list_empty(pending);
+}
+
+void do_submit(struct work_struct *ws)
+{
+	struct drbd_conf *mdev = container_of(ws, struct drbd_conf, submit.worker);
+	LIST_HEAD(incoming);
+	LIST_HEAD(pending);
+	struct drbd_request *req, *tmp;
+
+	for (;;) {
+		spin_lock(&mdev->submit.lock);
+		list_splice_tail_init(&mdev->submit.writes, &incoming);
+		spin_unlock(&mdev->submit.lock);
+
+		submit_fast_path(mdev, &incoming);
+		if (list_empty(&incoming))
+			break;
+
+		wait_event(mdev->al_wait, prepare_al_transaction_nonblock(mdev, &incoming, &pending));
+		/* Maybe more was queued, while we prepared the transaction?
+		 * Try to stuff them into this transaction as well.
+		 * Be strictly non-blocking here, no wait_event, we already
+		 * have something to commit.
+		 * Stop if we don't make any more progres.
+		 */
+		for (;;) {
+			LIST_HEAD(more_pending);
+			LIST_HEAD(more_incoming);
+			bool made_progress;
+
+			/* It is ok to look outside the lock,
+			 * it's only an optimization anyways */
+			if (list_empty(&mdev->submit.writes))
+				break;
+
+			spin_lock(&mdev->submit.lock);
+			list_splice_tail_init(&mdev->submit.writes, &more_incoming);
+			spin_unlock(&mdev->submit.lock);
+
+			if (list_empty(&more_incoming))
+				break;
+
+			made_progress = prepare_al_transaction_nonblock(mdev, &more_incoming, &more_pending);
+
+			list_splice_tail_init(&more_pending, &pending);
+			list_splice_tail_init(&more_incoming, &incoming);
+
+			if (!made_progress)
+				break;
+		}
+		drbd_al_begin_io_commit(mdev, false);
+
+		list_for_each_entry_safe(req, tmp, &pending, tl_requests) {
+			list_del_init(&req->tl_requests);
+			drbd_send_and_submit(mdev, req);
+		}
+	}
 }
 
 void drbd_make_request(struct request_queue *q, struct bio *bio)
diff --git a/drivers/block/drbd/drbd_req.h b/drivers/block/drbd/drbd_req.h
index c08d229..978cb1a 100644
--- a/drivers/block/drbd/drbd_req.h
+++ b/drivers/block/drbd/drbd_req.h
@@ -88,6 +88,14 @@ enum drbd_req_event {
 	QUEUE_FOR_NET_READ,
 	QUEUE_FOR_SEND_OOS,
 
+	/* An empty flush is queued as P_BARRIER,
+	 * which will cause it to complete "successfully",
+	 * even if the local disk flush failed.
+	 *
+	 * Just like "real" requests, empty flushes (blkdev_issue_flush()) will
+	 * only see an error if neither local nor remote data is reachable. */
+	QUEUE_AS_DRBD_BARRIER,
+
 	SEND_CANCELED,
 	SEND_FAILED,
 	HANDED_OVER_TO_NETWORK,
diff --git a/drivers/block/drbd/drbd_state.c b/drivers/block/drbd/drbd_state.c
index 0fe220c..90c5be2 100644
--- a/drivers/block/drbd/drbd_state.c
+++ b/drivers/block/drbd/drbd_state.c
@@ -570,6 +570,13 @@ is_valid_state(struct drbd_conf *mdev, union drbd_state ns)
 		  mdev->tconn->agreed_pro_version < 88)
 		rv = SS_NOT_SUPPORTED;
 
+	else if (ns.role == R_PRIMARY && ns.disk < D_UP_TO_DATE && ns.pdsk < D_UP_TO_DATE)
+		rv = SS_NO_UP_TO_DATE_DISK;
+
+	else if ((ns.conn == C_STARTING_SYNC_S || ns.conn == C_STARTING_SYNC_T) &&
+                 ns.pdsk == D_UNKNOWN)
+		rv = SS_NEED_CONNECTION;
+
 	else if (ns.conn >= C_CONNECTED && ns.pdsk == D_UNKNOWN)
 		rv = SS_CONNECTED_OUTDATES;
 
@@ -635,6 +642,10 @@ is_valid_soft_transition(union drbd_state os, union drbd_state ns, struct drbd_t
 	    && os.conn < C_WF_REPORT_PARAMS)
 		rv = SS_NEED_CONNECTION; /* No NetworkFailure -> SyncTarget etc... */
 
+	if (ns.conn == C_DISCONNECTING && ns.pdsk == D_OUTDATED &&
+	    os.conn < C_CONNECTED && os.pdsk > D_OUTDATED)
+		rv = SS_OUTDATE_WO_CONN;
+
 	return rv;
 }
 
@@ -1377,13 +1388,6 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os,
 			&drbd_bmio_set_n_write, &abw_start_sync,
 			"set_n_write from StartingSync", BM_LOCKED_TEST_ALLOWED);
 
-	/* We are invalidating our self... */
-	if (os.conn < C_CONNECTED && ns.conn < C_CONNECTED &&
-	    os.disk > D_INCONSISTENT && ns.disk == D_INCONSISTENT)
-		/* other bitmap operation expected during this phase */
-		drbd_queue_bitmap_io(mdev, &drbd_bmio_set_n_write, NULL,
-			"set_n_write from invalidate", BM_LOCKED_MASK);
-
 	/* first half of local IO error, failure to attach,
 	 * or administrative detach */
 	if (os.disk != D_FAILED && ns.disk == D_FAILED) {
@@ -1748,13 +1752,9 @@ _conn_rq_cond(struct drbd_tconn *tconn, union drbd_state mask, union drbd_state
 	if (test_and_clear_bit(CONN_WD_ST_CHG_FAIL, &tconn->flags))
 		return SS_CW_FAILED_BY_PEER;
 
-	rv = tconn->cstate != C_WF_REPORT_PARAMS ? SS_CW_NO_NEED : SS_UNKNOWN_ERROR;
-
-	if (rv == SS_UNKNOWN_ERROR)
-		rv = conn_is_valid_transition(tconn, mask, val, 0);
-
-	if (rv == SS_SUCCESS)
-		rv = SS_UNKNOWN_ERROR; /* cont waiting, otherwise fail. */
+	rv = conn_is_valid_transition(tconn, mask, val, 0);
+	if (rv == SS_SUCCESS && tconn->cstate == C_WF_REPORT_PARAMS)
+		rv = SS_UNKNOWN_ERROR; /* continue waiting */
 
 	return rv;
 }
diff --git a/drivers/block/drbd/drbd_strings.c b/drivers/block/drbd/drbd_strings.c
index 9a664bd..58e08ff 100644
--- a/drivers/block/drbd/drbd_strings.c
+++ b/drivers/block/drbd/drbd_strings.c
@@ -89,6 +89,7 @@ static const char *drbd_state_sw_errors[] = {
 	[-SS_LOWER_THAN_OUTDATED] = "Disk state is lower than outdated",
 	[-SS_IN_TRANSIENT_STATE] = "In transient state, retry after next state change",
 	[-SS_CONCURRENT_ST_CHG] = "Concurrent state changes detected and aborted",
+	[-SS_OUTDATE_WO_CONN] = "Need a connection for a graceful disconnect/outdate peer",
 	[-SS_O_VOL_PEER_PRI] = "Other vol primary on peer not allowed by config",
 };
 
diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c
index 424dc7b..04a80af 100644
--- a/drivers/block/drbd/drbd_worker.c
+++ b/drivers/block/drbd/drbd_worker.c
@@ -64,7 +64,8 @@ rwlock_t global_state_lock;
 /* used for synchronous meta data and bitmap IO
  * submitted by drbd_md_sync_page_io()
  */
-void drbd_md_io_complete(struct bio *bio, int error)
+void drbd_md_io_complete(struct bio *bio, int error,
+			 struct batch_complete *batch)
 {
 	struct drbd_md_io *md_io;
 	struct drbd_conf *mdev;
@@ -89,7 +90,8 @@ void drbd_md_io_complete(struct bio *bio, int error)
 	md_io->done = 1;
 	wake_up(&mdev->misc_wait);
 	bio_put(bio);
-	put_ldev(mdev);
+	if (mdev->ldev) /* special case: drbd_md_read() during drbd_adm_attach() */
+		put_ldev(mdev);
 }
 
 /* reads on behalf of the partner,
@@ -166,7 +168,8 @@ static void drbd_endio_write_sec_final(struct drbd_peer_request *peer_req) __rel
 /* writes on behalf of the partner, or resync writes,
  * "submitted" by the receiver.
  */
-void drbd_peer_request_endio(struct bio *bio, int error)
+void drbd_peer_request_endio(struct bio *bio, int error,
+			     struct batch_complete *batch)
 {
 	struct drbd_peer_request *peer_req = bio->bi_private;
 	struct drbd_conf *mdev = peer_req->w.mdev;
@@ -202,7 +205,8 @@ void drbd_peer_request_endio(struct bio *bio, int error)
 
 /* read, readA or write requests on R_PRIMARY coming from drbd_make_request
  */
-void drbd_request_endio(struct bio *bio, int error)
+void drbd_request_endio(struct bio *bio, int error,
+			struct batch_complete *batch)
 {
 	unsigned long flags;
 	struct drbd_request *req = bio->bi_private;
@@ -1410,7 +1414,7 @@ int w_restart_disk_io(struct drbd_work *w, int cancel)
 	struct drbd_conf *mdev = w->mdev;
 
 	if (bio_data_dir(req->master_bio) == WRITE && req->rq_state & RQ_IN_ACT_LOG)
-		drbd_al_begin_io(mdev, &req->i);
+		drbd_al_begin_io(mdev, &req->i, false);
 
 	drbd_req_make_private_bio(req, req->master_bio);
 	req->private_bio->bi_bdev = mdev->ldev->backing_bdev;
@@ -1425,7 +1429,7 @@ static int _drbd_may_sync_now(struct drbd_conf *mdev)
 	int resync_after;
 
 	while (1) {
-		if (!odev->ldev)
+		if (!odev->ldev || odev->state.disk == D_DISKLESS)
 			return 1;
 		rcu_read_lock();
 		resync_after = rcu_dereference(odev->ldev->disk_conf)->resync_after;
@@ -1433,7 +1437,7 @@ static int _drbd_may_sync_now(struct drbd_conf *mdev)
 		if (resync_after == -1)
 			return 1;
 		odev = minor_to_mdev(resync_after);
-		if (!expect(odev))
+		if (!odev)
 			return 1;
 		if ((odev->state.conn >= C_SYNC_SOURCE &&
 		     odev->state.conn <= C_PAUSED_SYNC_T) ||
@@ -1515,7 +1519,7 @@ enum drbd_ret_code drbd_resync_after_valid(struct drbd_conf *mdev, int o_minor)
 
 	if (o_minor == -1)
 		return NO_ERROR;
-	if (o_minor < -1 || minor_to_mdev(o_minor) == NULL)
+	if (o_minor < -1 || o_minor > MINORMASK)
 		return ERR_RESYNC_AFTER;
 
 	/* check for loops */
@@ -1524,6 +1528,15 @@ enum drbd_ret_code drbd_resync_after_valid(struct drbd_conf *mdev, int o_minor)
 		if (odev == mdev)
 			return ERR_RESYNC_AFTER_CYCLE;
 
+		/* You are free to depend on diskless, non-existing,
+		 * or not yet/no longer existing minors.
+		 * We only reject dependency loops.
+		 * We cannot follow the dependency chain beyond a detached or
+		 * missing minor.
+		 */
+		if (!odev || !odev->ldev || odev->state.disk == D_DISKLESS)
+			return NO_ERROR;
+
 		rcu_read_lock();
 		resync_after = rcu_dereference(odev->ldev->disk_conf)->resync_after;
 		rcu_read_unlock();
@@ -1652,7 +1665,9 @@ void drbd_start_resync(struct drbd_conf *mdev, enum drbd_conns side)
 	clear_bit(B_RS_H_DONE, &mdev->flags);
 
 	write_lock_irq(&global_state_lock);
-	if (!get_ldev_if_state(mdev, D_NEGOTIATING)) {
+	/* Did some connection breakage or IO error race with us? */
+	if (mdev->state.conn < C_CONNECTED
+	|| !get_ldev_if_state(mdev, D_NEGOTIATING)) {
 		write_unlock_irq(&global_state_lock);
 		mutex_unlock(mdev->state_mutex);
 		return;
diff --git a/drivers/block/drbd/drbd_wrappers.h b/drivers/block/drbd/drbd_wrappers.h
index 328f18e..d443dc0 100644
--- a/drivers/block/drbd/drbd_wrappers.h
+++ b/drivers/block/drbd/drbd_wrappers.h
@@ -20,9 +20,12 @@ static inline void drbd_set_my_capacity(struct drbd_conf *mdev,
 #define drbd_bio_uptodate(bio) bio_flagged(bio, BIO_UPTODATE)
 
 /* bi_end_io handlers */
-extern void drbd_md_io_complete(struct bio *bio, int error);
-extern void drbd_peer_request_endio(struct bio *bio, int error);
-extern void drbd_request_endio(struct bio *bio, int error);
+extern void drbd_md_io_complete(struct bio *bio, int error,
+				struct batch_complete *batch);
+extern void drbd_peer_request_endio(struct bio *bio, int error,
+				    struct batch_complete *batch);
+extern void drbd_request_endio(struct bio *bio, int error,
+			       struct batch_complete *batch);
 
 /*
  * used to submit our private bio
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index 2ddd64a..629b6d5 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -3748,7 +3748,8 @@ static unsigned int floppy_check_events(struct gendisk *disk,
  * a disk in the drive, and whether that disk is writable.
  */
 
-static void floppy_rb0_complete(struct bio *bio, int err)
+static void floppy_rb0_complete(struct bio *bio, int err,
+				struct batch_complete *batch)
 {
 	complete((struct completion *)bio->bi_private);
 }
@@ -3777,7 +3778,6 @@ static int __floppy_read_block_0(struct block_device *bdev)
 	bio_vec.bv_len = size;
 	bio_vec.bv_offset = 0;
 	bio.bi_vcnt = 1;
-	bio.bi_idx = 0;
 	bio.bi_size = size;
 	bio.bi_bdev = bdev;
 	bio.bi_sector = 0;
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index fe5f640..be9a101 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -230,9 +230,11 @@ static int __do_lo_send_write(struct file *file,
 	ssize_t bw;
 	mm_segment_t old_fs = get_fs();
 
+	file_start_write(file);
 	set_fs(get_ds());
 	bw = file->f_op->write(file, buf, len, &pos);
 	set_fs(old_fs);
+	file_end_write(file);
 	if (likely(bw == len))
 		return 0;
 	printk(KERN_ERR "loop: Write error at byte offset %llu, length %i.\n",
@@ -922,6 +924,11 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode,
 		lo->lo_flags |= LO_FLAGS_PARTSCAN;
 	if (lo->lo_flags & LO_FLAGS_PARTSCAN)
 		ioctl_by_bdev(bdev, BLKRRPART, 0);
+
+	/* Grab the block_device to prevent its destruction after we
+	 * put /dev/loopXX inode. Later in loop_clr_fd() we bdput(bdev).
+	 */
+	bdgrab(bdev);
 	return 0;
 
 out_clr:
@@ -1031,8 +1038,10 @@ static int loop_clr_fd(struct loop_device *lo)
 	memset(lo->lo_encrypt_key, 0, LO_KEY_SIZE);
 	memset(lo->lo_crypt_name, 0, LO_NAME_SIZE);
 	memset(lo->lo_file_name, 0, LO_NAME_SIZE);
-	if (bdev)
+	if (bdev) {
+		bdput(bdev);
 		invalidate_bdev(bdev);
+	}
 	set_capacity(lo->lo_disk, 0);
 	loop_sysfs_exit(lo);
 	if (bdev) {
diff --git a/drivers/block/mg_disk.c b/drivers/block/mg_disk.c
index 076ae7f..a56cfcd 100644
--- a/drivers/block/mg_disk.c
+++ b/drivers/block/mg_disk.c
@@ -780,6 +780,7 @@ static const struct block_device_operations mg_disk_ops = {
 	.getgeo = mg_getgeo
 };
 
+#ifdef CONFIG_PM_SLEEP
 static int mg_suspend(struct device *dev)
 {
 	struct mg_drv_data *prv_data = dev->platform_data;
@@ -824,6 +825,7 @@ static int mg_resume(struct device *dev)
 
 	return 0;
 }
+#endif
 
 static SIMPLE_DEV_PM_OPS(mg_pm, mg_suspend, mg_resume);
 
diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c
index 92250af..122c7b9 100644
--- a/drivers/block/mtip32xx/mtip32xx.c
+++ b/drivers/block/mtip32xx/mtip32xx.c
@@ -81,12 +81,17 @@
 /* Device instance number, incremented each time a device is probed. */
 static int instance;
 
+struct list_head online_list;
+struct list_head removing_list;
+spinlock_t dev_lock;
+
 /*
  * Global variable used to hold the major block device number
  * allocated in mtip_init().
  */
 static int mtip_major;
 static struct dentry *dfs_parent;
+static struct dentry *dfs_device_status;
 
 static u32 cpu_use[NR_CPUS];
 
@@ -146,6 +151,9 @@ static void mtip_command_cleanup(struct driver_data *dd)
 	struct mtip_cmd *command;
 	struct mtip_port *port = dd->port;
 	static int in_progress;
+	struct batch_complete batch;
+
+	batch_complete_init(&batch);
 
 	if (in_progress)
 		return;
@@ -161,11 +169,9 @@ static void mtip_command_cleanup(struct driver_data *dd)
 			command = &port->commands[commandindex];
 
 			if (atomic_read(&command->active)
-			    && (command->async_callback)) {
-				command->async_callback(command->async_data,
-					-ENODEV);
-				command->async_callback = NULL;
-				command->async_data = NULL;
+			    && (command->bio)) {
+				bio_endio_batch(command->bio, -ENODEV, &batch);
+				command->bio = NULL;
 			}
 
 			dma_unmap_sg(&port->dd->pdev->dev,
@@ -173,9 +179,10 @@ static void mtip_command_cleanup(struct driver_data *dd)
 				command->scatter_ents,
 				command->direction);
 		}
+		up(&port->cmd_slot);
 	}
 
-	up(&port->cmd_slot);
+	batch_complete(&batch);
 
 	set_bit(MTIP_DDF_CLEANUP_BIT, &dd->dd_flag);
 	in_progress = 0;
@@ -243,40 +250,31 @@ static inline void release_slot(struct mtip_port *port, int tag)
 /*
  * Reset the HBA (without sleeping)
  *
- * Just like hba_reset, except does not call sleep, so can be
- * run from interrupt/tasklet context.
- *
  * @dd Pointer to the driver data structure.
  *
  * return value
  *	0	The reset was successful.
  *	-1	The HBA Reset bit did not clear.
  */
-static int hba_reset_nosleep(struct driver_data *dd)
+static int mtip_hba_reset(struct driver_data *dd)
 {
 	unsigned long timeout;
 
-	/* Chip quirk: quiesce any chip function */
-	mdelay(10);
-
 	/* Set the reset bit */
 	writel(HOST_RESET, dd->mmio + HOST_CTL);
 
 	/* Flush */
 	readl(dd->mmio + HOST_CTL);
 
-	/*
-	 * Wait 10ms then spin for up to 1 second
-	 * waiting for reset acknowledgement
-	 */
-	timeout = jiffies + msecs_to_jiffies(1000);
-	mdelay(10);
-	while ((readl(dd->mmio + HOST_CTL) & HOST_RESET)
-		 && time_before(jiffies, timeout))
-		mdelay(1);
+	/* Spin for up to 2 seconds, waiting for reset acknowledgement */
+	timeout = jiffies + msecs_to_jiffies(2000);
+	do {
+		mdelay(10);
+		if (test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag))
+			return -1;
 
-	if (test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag))
-		return -1;
+	} while ((readl(dd->mmio + HOST_CTL) & HOST_RESET)
+		 && time_before(jiffies, timeout));
 
 	if (readl(dd->mmio + HOST_CTL) & HOST_RESET)
 		return -1;
@@ -481,7 +479,7 @@ static void mtip_restart_port(struct mtip_port *port)
 		dev_warn(&port->dd->pdev->dev,
 			"PxCMD.CR not clear, escalating reset\n");
 
-		if (hba_reset_nosleep(port->dd))
+		if (mtip_hba_reset(port->dd))
 			dev_err(&port->dd->pdev->dev,
 				"HBA reset escalation failed.\n");
 
@@ -527,6 +525,26 @@ static void mtip_restart_port(struct mtip_port *port)
 
 }
 
+static int mtip_device_reset(struct driver_data *dd)
+{
+	int rv = 0;
+
+	if (mtip_check_surprise_removal(dd->pdev))
+		return 0;
+
+	if (mtip_hba_reset(dd) < 0)
+		rv = -EFAULT;
+
+	mdelay(1);
+	mtip_init_port(dd->port);
+	mtip_start_port(dd->port);
+
+	/* Enable interrupts on the HBA. */
+	writel(readl(dd->mmio + HOST_CTL) | HOST_IRQ_EN,
+					dd->mmio + HOST_CTL);
+	return rv;
+}
+
 /*
  * Helper function for tag logging
  */
@@ -564,6 +582,9 @@ static void mtip_timeout_function(unsigned long int data)
 	unsigned int bit, group;
 	unsigned int num_command_slots;
 	unsigned long to, tagaccum[SLOTBITS_IN_LONGS];
+	struct batch_complete batch;
+
+	batch_complete_init(&batch);
 
 	if (unlikely(!port))
 		return;
@@ -606,11 +627,9 @@ static void mtip_timeout_function(unsigned long int data)
 			writel(1 << bit, port->completed[group]);
 
 			/* Call the async completion callback. */
-			if (likely(command->async_callback))
-				command->async_callback(command->async_data,
-							 -EIO);
-			command->async_callback = NULL;
-			command->comp_func = NULL;
+			if (likely(command->bio))
+				bio_endio_batch(command->bio, -EIO, &batch);
+			command->bio = NULL;
 
 			/* Unmap the DMA scatter list entries */
 			dma_unmap_sg(&port->dd->pdev->dev,
@@ -629,10 +648,12 @@ static void mtip_timeout_function(unsigned long int data)
 		}
 	}
 
+	batch_complete(&batch);
+
 	if (cmdto_cnt) {
 		print_tags(port->dd, "timed out", tagaccum, cmdto_cnt);
 		if (!test_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags)) {
-			mtip_restart_port(port);
+			mtip_device_reset(port->dd);
 			wake_up_interruptible(&port->svc_wait);
 		}
 		clear_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags);
@@ -679,7 +700,8 @@ static void mtip_timeout_function(unsigned long int data)
 static void mtip_async_complete(struct mtip_port *port,
 				int tag,
 				void *data,
-				int status)
+				int status,
+				struct batch_complete *batch)
 {
 	struct mtip_cmd *command;
 	struct driver_data *dd = data;
@@ -696,11 +718,10 @@ static void mtip_async_complete(struct mtip_port *port,
 	}
 
 	/* Upper layer callback */
-	if (likely(command->async_callback))
-		command->async_callback(command->async_data, cb_status);
+	if (likely(command->bio))
+		bio_endio_batch(command->bio, cb_status, batch);
 
-	command->async_callback = NULL;
-	command->comp_func = NULL;
+	command->bio = NULL;
 
 	/* Unmap the DMA scatter list entries */
 	dma_unmap_sg(&dd->pdev->dev,
@@ -733,24 +754,22 @@ static void mtip_async_complete(struct mtip_port *port,
 static void mtip_completion(struct mtip_port *port,
 			    int tag,
 			    void *data,
-			    int status)
+			    int status,
+			    struct batch_complete *batch)
 {
-	struct mtip_cmd *command = &port->commands[tag];
 	struct completion *waiting = data;
 	if (unlikely(status == PORT_IRQ_TF_ERR))
 		dev_warn(&port->dd->pdev->dev,
 			"Internal command %d completed with TFE\n", tag);
 
-	command->async_callback = NULL;
-	command->comp_func = NULL;
-
 	complete(waiting);
 }
 
 static void mtip_null_completion(struct mtip_port *port,
 			    int tag,
 			    void *data,
-			    int status)
+			    int status,
+			    struct batch_complete *batch)
 {
 	return;
 }
@@ -779,6 +798,7 @@ static void mtip_handle_tfe(struct driver_data *dd)
 	unsigned char *buf;
 	char *fail_reason = NULL;
 	int fail_all_ncq_write = 0, fail_all_ncq_cmds = 0;
+	struct batch_complete batch;
 
 	dev_warn(&dd->pdev->dev, "Taskfile error\n");
 
@@ -796,13 +816,14 @@ static void mtip_handle_tfe(struct driver_data *dd)
 		atomic_inc(&cmd->active); /* active > 1 indicates error */
 		if (cmd->comp_data && cmd->comp_func) {
 			cmd->comp_func(port, MTIP_TAG_INTERNAL,
-					cmd->comp_data, PORT_IRQ_TF_ERR);
+					cmd->comp_data, PORT_IRQ_TF_ERR, NULL);
 		}
 		goto handle_tfe_exit;
 	}
 
 	/* clear the tag accumulator */
 	memset(tagaccum, 0, SLOTBITS_IN_LONGS * sizeof(long));
+	batch_complete_init(&batch);
 
 	/* Loop through all the groups */
 	for (group = 0; group < dd->slot_groups; group++) {
@@ -829,7 +850,7 @@ static void mtip_handle_tfe(struct driver_data *dd)
 				cmd->comp_func(port,
 					 tag,
 					 cmd->comp_data,
-					 0);
+					 0, &batch);
 			} else {
 				dev_err(&port->dd->pdev->dev,
 					"Missing completion func for tag %d",
@@ -842,6 +863,7 @@ static void mtip_handle_tfe(struct driver_data *dd)
 			}
 		}
 	}
+	batch_complete(&batch);
 
 	print_tags(dd, "completed (TFE)", tagaccum, cmd_cnt);
 
@@ -883,6 +905,7 @@ static void mtip_handle_tfe(struct driver_data *dd)
 
 	/* clear the tag accumulator */
 	memset(tagaccum, 0, SLOTBITS_IN_LONGS * sizeof(long));
+	batch_complete_init(&batch);
 
 	/* Loop through all the groups */
 	for (group = 0; group < dd->slot_groups; group++) {
@@ -916,7 +939,7 @@ static void mtip_handle_tfe(struct driver_data *dd)
 					if (cmd->comp_func) {
 						cmd->comp_func(port, tag,
 							cmd->comp_data,
-							-ENODATA);
+							-ENODATA, &batch);
 					}
 					continue;
 				}
@@ -946,13 +969,15 @@ static void mtip_handle_tfe(struct driver_data *dd)
 					port,
 					tag,
 					cmd->comp_data,
-					PORT_IRQ_TF_ERR);
+					PORT_IRQ_TF_ERR, &batch);
 			else
 				dev_warn(&port->dd->pdev->dev,
 					"Bad completion for tag %d\n",
 					tag);
 		}
 	}
+
+	batch_complete(&batch);
 	print_tags(dd, "reissued (TFE)", tagaccum, cmd_cnt);
 
 handle_tfe_exit:
@@ -973,6 +998,9 @@ static inline void mtip_workq_sdbfx(struct mtip_port *port, int group,
 	struct driver_data *dd = port->dd;
 	int tag, bit;
 	struct mtip_cmd *command;
+	struct batch_complete batch;
+
+	batch_complete_init(&batch);
 
 	if (!completed) {
 		WARN_ON_ONCE(!completed);
@@ -997,7 +1025,8 @@ static inline void mtip_workq_sdbfx(struct mtip_port *port, int group,
 					port,
 					tag,
 					command->comp_data,
-					0);
+					0,
+					&batch);
 			} else {
 				dev_warn(&dd->pdev->dev,
 					"Null completion "
@@ -1007,13 +1036,16 @@ static inline void mtip_workq_sdbfx(struct mtip_port *port, int group,
 				if (mtip_check_surprise_removal(
 					dd->pdev)) {
 					mtip_command_cleanup(dd);
-					return;
+					goto out;
 				}
 			}
 		}
 		completed >>= 1;
 	}
 
+out:
+	batch_complete(&batch);
+
 	/* If last, re-enable interrupts */
 	if (atomic_dec_return(&dd->irq_workers_active) == 0)
 		writel(0xffffffff, dd->mmio + HOST_IRQ_STAT);
@@ -1034,7 +1066,7 @@ static inline void mtip_process_legacy(struct driver_data *dd, u32 port_stat)
 			cmd->comp_func(port,
 				MTIP_TAG_INTERNAL,
 				cmd->comp_data,
-				0);
+				0, NULL);
 			return;
 		}
 	}
@@ -1283,11 +1315,11 @@ static int mtip_exec_internal_command(struct mtip_port *port,
 	int rv = 0, ready2go = 1;
 	struct mtip_cmd *int_cmd = &port->commands[MTIP_TAG_INTERNAL];
 	unsigned long to;
+	struct driver_data *dd = port->dd;
 
 	/* Make sure the buffer is 8 byte aligned. This is asic specific. */
 	if (buffer & 0x00000007) {
-		dev_err(&port->dd->pdev->dev,
-			"SG buffer is not 8 byte aligned\n");
+		dev_err(&dd->pdev->dev, "SG buffer is not 8 byte aligned\n");
 		return -EFAULT;
 	}
 
@@ -1300,23 +1332,21 @@ static int mtip_exec_internal_command(struct mtip_port *port,
 		mdelay(100);
 	} while (time_before(jiffies, to));
 	if (!ready2go) {
-		dev_warn(&port->dd->pdev->dev,
+		dev_warn(&dd->pdev->dev,
 			"Internal cmd active. new cmd [%02X]\n", fis->command);
 		return -EBUSY;
 	}
 	set_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags);
 	port->ic_pause_timer = 0;
 
-	if (fis->command == ATA_CMD_SEC_ERASE_UNIT)
-		clear_bit(MTIP_PF_SE_ACTIVE_BIT, &port->flags);
-	else if (fis->command == ATA_CMD_DOWNLOAD_MICRO)
-		clear_bit(MTIP_PF_DM_ACTIVE_BIT, &port->flags);
+	clear_bit(MTIP_PF_SE_ACTIVE_BIT, &port->flags);
+	clear_bit(MTIP_PF_DM_ACTIVE_BIT, &port->flags);
 
 	if (atomic == GFP_KERNEL) {
 		if (fis->command != ATA_CMD_STANDBYNOW1) {
 			/* wait for io to complete if non atomic */
 			if (mtip_quiesce_io(port, 5000) < 0) {
-				dev_warn(&port->dd->pdev->dev,
+				dev_warn(&dd->pdev->dev,
 					"Failed to quiesce IO\n");
 				release_slot(port, MTIP_TAG_INTERNAL);
 				clear_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags);
@@ -1361,58 +1391,84 @@ static int mtip_exec_internal_command(struct mtip_port *port,
 	/* Issue the command to the hardware */
 	mtip_issue_non_ncq_command(port, MTIP_TAG_INTERNAL);
 
-	/* Poll if atomic, wait_for_completion otherwise */
 	if (atomic == GFP_KERNEL) {
 		/* Wait for the command to complete or timeout. */
-		if (wait_for_completion_timeout(
+		if (wait_for_completion_interruptible_timeout(
 				&wait,
-				msecs_to_jiffies(timeout)) == 0) {
-			dev_err(&port->dd->pdev->dev,
-				"Internal command did not complete [%d] "
-				"within timeout of  %lu ms\n",
-				atomic, timeout);
-			if (mtip_check_surprise_removal(port->dd->pdev) ||
+				msecs_to_jiffies(timeout)) <= 0) {
+			if (rv == -ERESTARTSYS) { /* interrupted */
+				dev_err(&dd->pdev->dev,
+					"Internal command [%02X] was interrupted after %lu ms\n",
+					fis->command, timeout);
+				rv = -EINTR;
+				goto exec_ic_exit;
+			} else if (rv == 0) /* timeout */
+				dev_err(&dd->pdev->dev,
+					"Internal command did not complete [%02X] within timeout of  %lu ms\n",
+					fis->command, timeout);
+			else
+				dev_err(&dd->pdev->dev,
+					"Internal command [%02X] wait returned code [%d] after %lu ms - unhandled\n",
+					fis->command, rv, timeout);
+
+			if (mtip_check_surprise_removal(dd->pdev) ||
 				test_bit(MTIP_DDF_REMOVE_PENDING_BIT,
-						&port->dd->dd_flag)) {
+						&dd->dd_flag)) {
+				dev_err(&dd->pdev->dev,
+					"Internal command [%02X] wait returned due to SR\n",
+					fis->command);
 				rv = -ENXIO;
 				goto exec_ic_exit;
 			}
+			mtip_device_reset(dd); /* recover from timeout issue */
 			rv = -EAGAIN;
+			goto exec_ic_exit;
 		}
 	} else {
+		u32 hba_stat, port_stat;
+
 		/* Spin for <timeout> checking if command still outstanding */
 		timeout = jiffies + msecs_to_jiffies(timeout);
 		while ((readl(port->cmd_issue[MTIP_TAG_INTERNAL])
 				& (1 << MTIP_TAG_INTERNAL))
 				&& time_before(jiffies, timeout)) {
-			if (mtip_check_surprise_removal(port->dd->pdev)) {
+			if (mtip_check_surprise_removal(dd->pdev)) {
 				rv = -ENXIO;
 				goto exec_ic_exit;
 			}
 			if ((fis->command != ATA_CMD_STANDBYNOW1) &&
 				test_bit(MTIP_DDF_REMOVE_PENDING_BIT,
-						&port->dd->dd_flag)) {
+						&dd->dd_flag)) {
 				rv = -ENXIO;
 				goto exec_ic_exit;
 			}
-			if (readl(port->mmio + PORT_IRQ_STAT) & PORT_IRQ_ERR) {
-				atomic_inc(&int_cmd->active); /* error */
-				break;
+			port_stat = readl(port->mmio + PORT_IRQ_STAT);
+			if (!port_stat)
+				continue;
+
+			if (port_stat & PORT_IRQ_ERR) {
+				dev_err(&dd->pdev->dev,
+					"Internal command [%02X] failed\n",
+					fis->command);
+				mtip_device_reset(dd);
+				rv = -EIO;
+				goto exec_ic_exit;
+			} else {
+				writel(port_stat, port->mmio + PORT_IRQ_STAT);
+				hba_stat = readl(dd->mmio + HOST_IRQ_STAT);
+				if (hba_stat)
+					writel(hba_stat,
+						dd->mmio + HOST_IRQ_STAT);
 			}
+			break;
 		}
 	}
 
-	if (atomic_read(&int_cmd->active) > 1) {
-		dev_err(&port->dd->pdev->dev,
-			"Internal command [%02X] failed\n", fis->command);
-		rv = -EIO;
-	}
 	if (readl(port->cmd_issue[MTIP_TAG_INTERNAL])
 			& (1 << MTIP_TAG_INTERNAL)) {
 		rv = -ENXIO;
-		if (!test_bit(MTIP_DDF_REMOVE_PENDING_BIT,
-					&port->dd->dd_flag)) {
-			mtip_restart_port(port);
+		if (!test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag)) {
+			mtip_device_reset(dd);
 			rv = -EAGAIN;
 		}
 	}
@@ -1724,7 +1780,8 @@ static int mtip_get_smart_attr(struct mtip_port *port, unsigned int id,
  *      -EINVAL		Invalid parameters passed in, trim not supported
  *      -EIO		Error submitting trim request to hw
  */
-static int mtip_send_trim(struct driver_data *dd, unsigned int lba, unsigned int len)
+static int mtip_send_trim(struct driver_data *dd, unsigned int lba,
+				unsigned int len)
 {
 	int i, rv = 0;
 	u64 tlba, tlen, sect_left;
@@ -1811,45 +1868,6 @@ static bool mtip_hw_get_capacity(struct driver_data *dd, sector_t *sectors)
 }
 
 /*
- * Reset the HBA.
- *
- * Resets the HBA by setting the HBA Reset bit in the Global
- * HBA Control register. After setting the HBA Reset bit the
- * function waits for 1 second before reading the HBA Reset
- * bit to make sure it has cleared. If HBA Reset is not clear
- * an error is returned. Cannot be used in non-blockable
- * context.
- *
- * @dd Pointer to the driver data structure.
- *
- * return value
- *	0  The reset was successful.
- *	-1 The HBA Reset bit did not clear.
- */
-static int mtip_hba_reset(struct driver_data *dd)
-{
-	mtip_deinit_port(dd->port);
-
-	/* Set the reset bit */
-	writel(HOST_RESET, dd->mmio + HOST_CTL);
-
-	/* Flush */
-	readl(dd->mmio + HOST_CTL);
-
-	/* Wait for reset to clear */
-	ssleep(1);
-
-	/* Check the bit has cleared */
-	if (readl(dd->mmio + HOST_CTL) & HOST_RESET) {
-		dev_err(&dd->pdev->dev,
-			"Reset bit did not clear.\n");
-		return -1;
-	}
-
-	return 0;
-}
-
-/*
  * Display the identify command data.
  *
  * @port Pointer to the port data structure.
@@ -2554,8 +2572,8 @@ static int mtip_hw_ioctl(struct driver_data *dd, unsigned int cmd,
  *	None
  */
 static void mtip_hw_submit_io(struct driver_data *dd, sector_t sector,
-			      int nsect, int nents, int tag, void *callback,
-			      void *data, int dir)
+			      int nsect, int nents, int tag,
+			      struct bio *bio, int dir)
 {
 	struct host_to_dev_fis	*fis;
 	struct mtip_port *port = dd->port;
@@ -2610,12 +2628,7 @@ static void mtip_hw_submit_io(struct driver_data *dd, sector_t sector,
 	command->comp_func = mtip_async_complete;
 	command->direction = dma_dir;
 
-	/*
-	 * Set the completion function and data for the command passed
-	 * from the upper layer.
-	 */
-	command->async_data = data;
-	command->async_callback = callback;
+	command->bio = bio;
 
 	/*
 	 * To prevent this command from being issued
@@ -2710,6 +2723,100 @@ static ssize_t mtip_hw_show_status(struct device *dev,
 
 static DEVICE_ATTR(status, S_IRUGO, mtip_hw_show_status, NULL);
 
+/* debugsfs entries */
+
+static ssize_t show_device_status(struct device_driver *drv, char *buf)
+{
+	int size = 0;
+	struct driver_data *dd, *tmp;
+	unsigned long flags;
+	char id_buf[42];
+	u16 status = 0;
+
+	spin_lock_irqsave(&dev_lock, flags);
+	size += sprintf(&buf[size], "Devices Present:\n");
+	list_for_each_entry_safe(dd, tmp, &online_list, online_list) {
+		if (dd->pdev) {
+			if (dd->port &&
+			    dd->port->identify &&
+			    dd->port->identify_valid) {
+				strlcpy(id_buf,
+					(char *) (dd->port->identify + 10), 21);
+				status = *(dd->port->identify + 141);
+			} else {
+				memset(id_buf, 0, 42);
+				status = 0;
+			}
+
+			if (dd->port &&
+			    test_bit(MTIP_PF_REBUILD_BIT, &dd->port->flags)) {
+				size += sprintf(&buf[size],
+					" device %s %s (ftl rebuild %d %%)\n",
+					dev_name(&dd->pdev->dev),
+					id_buf,
+					status);
+			} else {
+				size += sprintf(&buf[size],
+					" device %s %s\n",
+					dev_name(&dd->pdev->dev),
+					id_buf);
+			}
+		}
+	}
+
+	size += sprintf(&buf[size], "Devices Being Removed:\n");
+	list_for_each_entry_safe(dd, tmp, &removing_list, remove_list) {
+		if (dd->pdev) {
+			if (dd->port &&
+			    dd->port->identify &&
+			    dd->port->identify_valid) {
+				strlcpy(id_buf,
+					(char *) (dd->port->identify+10), 21);
+				status = *(dd->port->identify + 141);
+			} else {
+				memset(id_buf, 0, 42);
+				status = 0;
+			}
+
+			if (dd->port &&
+			    test_bit(MTIP_PF_REBUILD_BIT, &dd->port->flags)) {
+				size += sprintf(&buf[size],
+					" device %s %s (ftl rebuild %d %%)\n",
+					dev_name(&dd->pdev->dev),
+					id_buf,
+					status);
+			} else {
+				size += sprintf(&buf[size],
+					" device %s %s\n",
+					dev_name(&dd->pdev->dev),
+					id_buf);
+			}
+		}
+	}
+	spin_unlock_irqrestore(&dev_lock, flags);
+
+	return size;
+}
+
+static ssize_t mtip_hw_read_device_status(struct file *f, char __user *ubuf,
+						size_t len, loff_t *offset)
+{
+	int size = *offset;
+	char buf[MTIP_DFS_MAX_BUF_SIZE];
+
+	if (!len || *offset)
+		return 0;
+
+	size += show_device_status(NULL, buf);
+
+	*offset = size <= len ? size : len;
+	size = copy_to_user(ubuf, buf, *offset);
+	if (size)
+		return -EFAULT;
+
+	return *offset;
+}
+
 static ssize_t mtip_hw_read_registers(struct file *f, char __user *ubuf,
 				  size_t len, loff_t *offset)
 {
@@ -2804,6 +2911,13 @@ static ssize_t mtip_hw_read_flags(struct file *f, char __user *ubuf,
 	return *offset;
 }
 
+static const struct file_operations mtip_device_status_fops = {
+	.owner  = THIS_MODULE,
+	.open   = simple_open,
+	.read   = mtip_hw_read_device_status,
+	.llseek = no_llseek,
+};
+
 static const struct file_operations mtip_regs_fops = {
 	.owner  = THIS_MODULE,
 	.open   = simple_open,
@@ -3795,7 +3909,6 @@ static void mtip_make_request(struct request_queue *queue, struct bio *bio)
 				bio_sectors(bio),
 				nents,
 				tag,
-				bio_endio,
 				bio,
 				bio_data_dir(bio));
 	} else
@@ -4161,6 +4274,7 @@ static int mtip_pci_probe(struct pci_dev *pdev,
 	const struct cpumask *node_mask;
 	int cpu, i = 0, j = 0;
 	int my_node = NUMA_NO_NODE;
+	unsigned long flags;
 
 	/* Allocate memory for this devices private data. */
 	my_node = pcibus_to_node(pdev->bus);
@@ -4218,6 +4332,9 @@ static int mtip_pci_probe(struct pci_dev *pdev,
 	dd->pdev	= pdev;
 	dd->numa_node	= my_node;
 
+	INIT_LIST_HEAD(&dd->online_list);
+	INIT_LIST_HEAD(&dd->remove_list);
+
 	memset(dd->workq_name, 0, 32);
 	snprintf(dd->workq_name, 31, "mtipq%d", dd->instance);
 
@@ -4305,6 +4422,14 @@ static int mtip_pci_probe(struct pci_dev *pdev,
 	instance++;
 	if (rv != MTIP_FTL_REBUILD_MAGIC)
 		set_bit(MTIP_DDF_INIT_DONE_BIT, &dd->dd_flag);
+	else
+		rv = 0; /* device in rebuild state, return 0 from probe */
+
+	/* Add to online list even if in ftl rebuild */
+	spin_lock_irqsave(&dev_lock, flags);
+	list_add(&dd->online_list, &online_list);
+	spin_unlock_irqrestore(&dev_lock, flags);
+
 	goto done;
 
 block_initialize_err:
@@ -4338,9 +4463,15 @@ static void mtip_pci_remove(struct pci_dev *pdev)
 {
 	struct driver_data *dd = pci_get_drvdata(pdev);
 	int counter = 0;
+	unsigned long flags;
 
 	set_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag);
 
+	spin_lock_irqsave(&dev_lock, flags);
+	list_del_init(&dd->online_list);
+	list_add(&dd->remove_list, &removing_list);
+	spin_unlock_irqrestore(&dev_lock, flags);
+
 	if (mtip_check_surprise_removal(pdev)) {
 		while (!test_bit(MTIP_DDF_CLEANUP_BIT, &dd->dd_flag)) {
 			counter++;
@@ -4366,6 +4497,10 @@ static void mtip_pci_remove(struct pci_dev *pdev)
 
 	pci_disable_msi(pdev);
 
+	spin_lock_irqsave(&dev_lock, flags);
+	list_del_init(&dd->remove_list);
+	spin_unlock_irqrestore(&dev_lock, flags);
+
 	kfree(dd);
 	pcim_iounmap_regions(pdev, 1 << MTIP_ABAR);
 }
@@ -4513,6 +4648,11 @@ static int __init mtip_init(void)
 
 	pr_info(MTIP_DRV_NAME " Version " MTIP_DRV_VERSION "\n");
 
+	spin_lock_init(&dev_lock);
+
+	INIT_LIST_HEAD(&online_list);
+	INIT_LIST_HEAD(&removing_list);
+
 	/* Allocate a major block device number to use with this driver. */
 	error = register_blkdev(0, MTIP_DRV_NAME);
 	if (error <= 0) {
@@ -4522,11 +4662,18 @@ static int __init mtip_init(void)
 	}
 	mtip_major = error;
 
-	if (!dfs_parent) {
-		dfs_parent = debugfs_create_dir("rssd", NULL);
-		if (IS_ERR_OR_NULL(dfs_parent)) {
-			pr_warn("Error creating debugfs parent\n");
-			dfs_parent = NULL;
+	dfs_parent = debugfs_create_dir("rssd", NULL);
+	if (IS_ERR_OR_NULL(dfs_parent)) {
+		pr_warn("Error creating debugfs parent\n");
+		dfs_parent = NULL;
+	}
+	if (dfs_parent) {
+		dfs_device_status = debugfs_create_file("device_status",
+					S_IRUGO, dfs_parent, NULL,
+					&mtip_device_status_fops);
+		if (IS_ERR_OR_NULL(dfs_device_status)) {
+			pr_err("Error creating device_status node\n");
+			dfs_device_status = NULL;
 		}
 	}
 
diff --git a/drivers/block/mtip32xx/mtip32xx.h b/drivers/block/mtip32xx/mtip32xx.h
index 3bffff5..78456ec 100644
--- a/drivers/block/mtip32xx/mtip32xx.h
+++ b/drivers/block/mtip32xx/mtip32xx.h
@@ -129,9 +129,9 @@ enum {
 	MTIP_PF_EH_ACTIVE_BIT       = 1, /* error handling */
 	MTIP_PF_SE_ACTIVE_BIT       = 2, /* secure erase */
 	MTIP_PF_DM_ACTIVE_BIT       = 3, /* download microcde */
-	MTIP_PF_PAUSE_IO      =	((1 << MTIP_PF_IC_ACTIVE_BIT) | \
-				(1 << MTIP_PF_EH_ACTIVE_BIT) | \
-				(1 << MTIP_PF_SE_ACTIVE_BIT) | \
+	MTIP_PF_PAUSE_IO      =	((1 << MTIP_PF_IC_ACTIVE_BIT) |
+				(1 << MTIP_PF_EH_ACTIVE_BIT) |
+				(1 << MTIP_PF_SE_ACTIVE_BIT) |
 				(1 << MTIP_PF_DM_ACTIVE_BIT)),
 
 	MTIP_PF_SVC_THD_ACTIVE_BIT  = 4,
@@ -144,9 +144,9 @@ enum {
 	MTIP_DDF_REMOVE_PENDING_BIT = 1,
 	MTIP_DDF_OVER_TEMP_BIT      = 2,
 	MTIP_DDF_WRITE_PROTECT_BIT  = 3,
-	MTIP_DDF_STOP_IO      = ((1 << MTIP_DDF_REMOVE_PENDING_BIT) | \
-				(1 << MTIP_DDF_SEC_LOCK_BIT) | \
-				(1 << MTIP_DDF_OVER_TEMP_BIT) | \
+	MTIP_DDF_STOP_IO      = ((1 << MTIP_DDF_REMOVE_PENDING_BIT) |
+				(1 << MTIP_DDF_SEC_LOCK_BIT) |
+				(1 << MTIP_DDF_OVER_TEMP_BIT) |
 				(1 << MTIP_DDF_WRITE_PROTECT_BIT)),
 
 	MTIP_DDF_CLEANUP_BIT        = 5,
@@ -180,7 +180,7 @@ struct mtip_work {
 
 #define MTIP_TRIM_TIMEOUT_MS		240000
 #define MTIP_MAX_TRIM_ENTRIES		8
-#define MTIP_MAX_TRIM_ENTRY_LEN 	0xfff8
+#define MTIP_MAX_TRIM_ENTRY_LEN		0xfff8
 
 struct mtip_trim_entry {
 	u32 lba;   /* starting lba of region */
@@ -325,11 +325,9 @@ struct mtip_cmd {
 	void (*comp_func)(struct mtip_port *port,
 				int tag,
 				void *data,
-				int status);
-	/* Additional callback function that may be called by comp_func() */
-	void (*async_callback)(void *data, int status);
-
-	void *async_data; /* Addl. data passed to async_callback() */
+				int status,
+				struct batch_complete *batch);
+	struct bio *bio;
 
 	int scatter_ents; /* Number of scatter list entries used */
 
@@ -501,6 +499,10 @@ struct driver_data {
 	atomic_t irq_workers_active;
 
 	int isr_binding;
+
+	struct list_head online_list; /* linkage for online list */
+
+	struct list_head remove_list; /* linkage for removing list */
 };
 
 #endif
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index 2e7de7a..ce42c14 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -901,7 +901,7 @@ static void pkt_iosched_process_queue(struct pktcdvd_device *pd)
 			pd->iosched.successive_reads += bio->bi_size >> 10;
 		else {
 			pd->iosched.successive_reads = 0;
-			pd->iosched.last_write = bio->bi_sector + bio_sectors(bio);
+			pd->iosched.last_write = bio_end_sector(bio);
 		}
 		if (pd->iosched.successive_reads >= HI_SPEED_SWITCH) {
 			if (pd->read_speed == pd->write_speed) {
@@ -948,31 +948,6 @@ static int pkt_set_segment_merging(struct pktcdvd_device *pd, struct request_que
 }
 
 /*
- * Copy CD_FRAMESIZE bytes from src_bio into a destination page
- */
-static void pkt_copy_bio_data(struct bio *src_bio, int seg, int offs, struct page *dst_page, int dst_offs)
-{
-	unsigned int copy_size = CD_FRAMESIZE;
-
-	while (copy_size > 0) {
-		struct bio_vec *src_bvl = bio_iovec_idx(src_bio, seg);
-		void *vfrom = kmap_atomic(src_bvl->bv_page) +
-			src_bvl->bv_offset + offs;
-		void *vto = page_address(dst_page) + dst_offs;
-		int len = min_t(int, copy_size, src_bvl->bv_len - offs);
-
-		BUG_ON(len < 0);
-		memcpy(vto, vfrom, len);
-		kunmap_atomic(vfrom);
-
-		seg++;
-		offs = 0;
-		dst_offs += len;
-		copy_size -= len;
-	}
-}
-
-/*
  * Copy all data for this packet to pkt->pages[], so that
  * a) The number of required segments for the write bio is minimized, which
  *    is necessary for some scsi controllers.
@@ -1005,7 +980,8 @@ static void pkt_make_local_copy(struct packet_data *pkt, struct bio_vec *bvec)
 	}
 }
 
-static void pkt_end_io_read(struct bio *bio, int err)
+static void pkt_end_io_read(struct bio *bio, int err,
+			    struct batch_complete *batch)
 {
 	struct packet_data *pkt = bio->bi_private;
 	struct pktcdvd_device *pd = pkt->pd;
@@ -1023,7 +999,8 @@ static void pkt_end_io_read(struct bio *bio, int err)
 	pkt_bio_finished(pd);
 }
 
-static void pkt_end_io_packet_write(struct bio *bio, int err)
+static void pkt_end_io_packet_write(struct bio *bio, int err,
+				    struct batch_complete *batch)
 {
 	struct packet_data *pkt = bio->bi_private;
 	struct pktcdvd_device *pd = pkt->pd;
@@ -1181,16 +1158,15 @@ static int pkt_start_recovery(struct packet_data *pkt)
 	new_sector = new_block * (CD_FRAMESIZE >> 9);
 	pkt->sector = new_sector;
 
+	bio_reset(pkt->bio);
+	pkt->bio->bi_bdev = pd->bdev;
+	pkt->bio->bi_rw = REQ_WRITE;
 	pkt->bio->bi_sector = new_sector;
-	pkt->bio->bi_next = NULL;
-	pkt->bio->bi_flags = 1 << BIO_UPTODATE;
-	pkt->bio->bi_idx = 0;
+	pkt->bio->bi_size = pkt->frames * CD_FRAMESIZE;
+	pkt->bio->bi_vcnt = pkt->frames;
 
-	BUG_ON(pkt->bio->bi_rw != REQ_WRITE);
-	BUG_ON(pkt->bio->bi_vcnt != pkt->frames);
-	BUG_ON(pkt->bio->bi_size != pkt->frames * CD_FRAMESIZE);
-	BUG_ON(pkt->bio->bi_end_io != pkt_end_io_packet_write);
-	BUG_ON(pkt->bio->bi_private != pkt);
+	pkt->bio->bi_end_io = pkt_end_io_packet_write;
+	pkt->bio->bi_private = pkt;
 
 	drop_super(sb);
 	return 1;
@@ -1325,55 +1301,35 @@ try_next_bio:
  */
 static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt)
 {
-	struct bio *bio;
 	int f;
-	int frames_write;
 	struct bio_vec *bvec = pkt->w_bio->bi_io_vec;
 
+	bio_reset(pkt->w_bio);
+	pkt->w_bio->bi_sector = pkt->sector;
+	pkt->w_bio->bi_bdev = pd->bdev;
+	pkt->w_bio->bi_end_io = pkt_end_io_packet_write;
+	pkt->w_bio->bi_private = pkt;
+
+	/* XXX: locking? */
 	for (f = 0; f < pkt->frames; f++) {
 		bvec[f].bv_page = pkt->pages[(f * CD_FRAMESIZE) / PAGE_SIZE];
 		bvec[f].bv_offset = (f * CD_FRAMESIZE) % PAGE_SIZE;
+		if (!bio_add_page(pkt->w_bio, bvec[f].bv_page, CD_FRAMESIZE, bvec[f].bv_offset))
+			BUG();
 	}
+	VPRINTK(DRIVER_NAME": vcnt=%d\n", pkt->w_bio->bi_vcnt);
 
 	/*
 	 * Fill-in bvec with data from orig_bios.
 	 */
-	frames_write = 0;
 	spin_lock(&pkt->lock);
-	bio_list_for_each(bio, &pkt->orig_bios) {
-		int segment = bio->bi_idx;
-		int src_offs = 0;
-		int first_frame = (bio->bi_sector - pkt->sector) / (CD_FRAMESIZE >> 9);
-		int num_frames = bio->bi_size / CD_FRAMESIZE;
-		BUG_ON(first_frame < 0);
-		BUG_ON(first_frame + num_frames > pkt->frames);
-		for (f = first_frame; f < first_frame + num_frames; f++) {
-			struct bio_vec *src_bvl = bio_iovec_idx(bio, segment);
-
-			while (src_offs >= src_bvl->bv_len) {
-				src_offs -= src_bvl->bv_len;
-				segment++;
-				BUG_ON(segment >= bio->bi_vcnt);
-				src_bvl = bio_iovec_idx(bio, segment);
-			}
+	bio_copy_data(pkt->w_bio, pkt->orig_bios.head);
 
-			if (src_bvl->bv_len - src_offs >= CD_FRAMESIZE) {
-				bvec[f].bv_page = src_bvl->bv_page;
-				bvec[f].bv_offset = src_bvl->bv_offset + src_offs;
-			} else {
-				pkt_copy_bio_data(bio, segment, src_offs,
-						  bvec[f].bv_page, bvec[f].bv_offset);
-			}
-			src_offs += CD_FRAMESIZE;
-			frames_write++;
-		}
-	}
 	pkt_set_state(pkt, PACKET_WRITE_WAIT_STATE);
 	spin_unlock(&pkt->lock);
 
 	VPRINTK("pkt_start_write: Writing %d frames for zone %llx\n",
-		frames_write, (unsigned long long)pkt->sector);
-	BUG_ON(frames_write != pkt->write_size);
+		pkt->write_size, (unsigned long long)pkt->sector);
 
 	if (test_bit(PACKET_MERGE_SEGS, &pd->flags) || (pkt->write_size < pkt->frames)) {
 		pkt_make_local_copy(pkt, bvec);
@@ -1383,16 +1339,6 @@ static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt)
 	}
 
 	/* Start the write request */
-	bio_reset(pkt->w_bio);
-	pkt->w_bio->bi_sector = pkt->sector;
-	pkt->w_bio->bi_bdev = pd->bdev;
-	pkt->w_bio->bi_end_io = pkt_end_io_packet_write;
-	pkt->w_bio->bi_private = pkt;
-	for (f = 0; f < pkt->frames; f++)
-		if (!bio_add_page(pkt->w_bio, bvec[f].bv_page, CD_FRAMESIZE, bvec[f].bv_offset))
-			BUG();
-	VPRINTK(DRIVER_NAME": vcnt=%d\n", pkt->w_bio->bi_vcnt);
-
 	atomic_set(&pkt->io_wait, 1);
 	pkt->w_bio->bi_rw = WRITE;
 	pkt_queue_bio(pd, pkt->w_bio);
@@ -2395,7 +2341,8 @@ static int pkt_close(struct gendisk *disk, fmode_t mode)
 }
 
 
-static void pkt_end_io_read_cloned(struct bio *bio, int err)
+static void pkt_end_io_read_cloned(struct bio *bio, int err,
+				   struct batch_complete *batch)
 {
 	struct packet_stacked_data *psd = bio->bi_private;
 	struct pktcdvd_device *pd = psd->pd;
@@ -2433,7 +2380,7 @@ static void pkt_make_request(struct request_queue *q, struct bio *bio)
 		cloned_bio->bi_bdev = pd->bdev;
 		cloned_bio->bi_private = psd;
 		cloned_bio->bi_end_io = pkt_end_io_read_cloned;
-		pd->stats.secs_r += bio->bi_size >> 9;
+		pd->stats.secs_r += bio_sectors(bio);
 		pkt_queue_bio(pd, cloned_bio);
 		return;
 	}
@@ -2454,7 +2401,7 @@ static void pkt_make_request(struct request_queue *q, struct bio *bio)
 	zone = ZONE(bio->bi_sector, pd);
 	VPRINTK("pkt_make_request: start = %6llx stop = %6llx\n",
 		(unsigned long long)bio->bi_sector,
-		(unsigned long long)(bio->bi_sector + bio_sectors(bio)));
+		(unsigned long long)bio_end_sector(bio));
 
 	/* Check if we have to split the bio */
 	{
@@ -2462,7 +2409,7 @@ static void pkt_make_request(struct request_queue *q, struct bio *bio)
 		sector_t last_zone;
 		int first_sectors;
 
-		last_zone = ZONE(bio->bi_sector + bio_sectors(bio) - 1, pd);
+		last_zone = ZONE(bio_end_sector(bio) - 1, pd);
 		if (last_zone != zone) {
 			BUG_ON(last_zone != zone + pd->settings.size);
 			first_sectors = last_zone - bio->bi_sector;
@@ -2648,7 +2595,7 @@ static int pkt_seq_show(struct seq_file *m, void *p)
 
 static int pkt_seq_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, pkt_seq_show, PDE(inode)->data);
+	return single_open(file, pkt_seq_show, PDE_DATA(inode));
 }
 
 static const struct file_operations pkt_proc_fops = {
diff --git a/drivers/block/ps3vram.c b/drivers/block/ps3vram.c
index 75e112d..06a2e53 100644
--- a/drivers/block/ps3vram.c
+++ b/drivers/block/ps3vram.c
@@ -525,7 +525,7 @@ static int ps3vram_proc_show(struct seq_file *m, void *v)
 
 static int ps3vram_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, ps3vram_proc_show, PDE(inode)->data);
+	return single_open(file, ps3vram_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations ps3vram_proc_fops = {
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index f556f8a..6b2b039 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -952,7 +952,7 @@ static struct bio *bio_clone_range(struct bio *bio_src,
 	/* Find first affected segment... */
 
 	resid = offset;
-	__bio_for_each_segment(bv, bio_src, idx, 0) {
+	bio_for_each_segment(bv, bio_src, idx) {
 		if (resid < bv->bv_len)
 			break;
 		resid -= bv->bv_len;
diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c
index 758f2ac..deb722d 100644
--- a/drivers/block/swim3.c
+++ b/drivers/block/swim3.c
@@ -775,7 +775,7 @@ static irqreturn_t swim3_interrupt(int irq, void *dev_id)
 		if (intr & ERROR_INTR) {
 			n = fs->scount - 1 - resid / 512;
 			if (n > 0) {
-				blk_update_request(req, 0, n << 9);
+				blk_update_request(req, 0, n << 9, NULL);
 				fs->req_sector += n;
 			}
 			if (fs->retries < 5) {
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
index 8ad21a2..49d0ec2 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -100,96 +100,103 @@ static inline struct virtblk_req *virtblk_alloc_req(struct virtio_blk *vblk,
 	return vbr;
 }
 
-static void virtblk_add_buf_wait(struct virtio_blk *vblk,
-				 struct virtblk_req *vbr,
-				 unsigned long out,
-				 unsigned long in)
+static int __virtblk_add_req(struct virtqueue *vq,
+			     struct virtblk_req *vbr,
+			     struct scatterlist *data_sg,
+			     bool have_data)
 {
-	DEFINE_WAIT(wait);
+	struct scatterlist hdr, status, cmd, sense, inhdr, *sgs[6];
+	unsigned int num_out = 0, num_in = 0;
+	int type = vbr->out_hdr.type & ~VIRTIO_BLK_T_OUT;
 
-	for (;;) {
-		prepare_to_wait_exclusive(&vblk->queue_wait, &wait,
-					  TASK_UNINTERRUPTIBLE);
+	sg_init_one(&hdr, &vbr->out_hdr, sizeof(vbr->out_hdr));
+	sgs[num_out++] = &hdr;
 
-		spin_lock_irq(vblk->disk->queue->queue_lock);
-		if (virtqueue_add_buf(vblk->vq, vbr->sg, out, in, vbr,
-				      GFP_ATOMIC) < 0) {
-			spin_unlock_irq(vblk->disk->queue->queue_lock);
-			io_schedule();
-		} else {
-			virtqueue_kick(vblk->vq);
-			spin_unlock_irq(vblk->disk->queue->queue_lock);
-			break;
-		}
+	/*
+	 * If this is a packet command we need a couple of additional headers.
+	 * Behind the normal outhdr we put a segment with the scsi command
+	 * block, and before the normal inhdr we put the sense data and the
+	 * inhdr with additional status information.
+	 */
+	if (type == VIRTIO_BLK_T_SCSI_CMD) {
+		sg_init_one(&cmd, vbr->req->cmd, vbr->req->cmd_len);
+		sgs[num_out++] = &cmd;
+	}
 
+	if (have_data) {
+		if (vbr->out_hdr.type & VIRTIO_BLK_T_OUT)
+			sgs[num_out++] = data_sg;
+		else
+			sgs[num_out + num_in++] = data_sg;
 	}
 
-	finish_wait(&vblk->queue_wait, &wait);
+	if (type == VIRTIO_BLK_T_SCSI_CMD) {
+		sg_init_one(&sense, vbr->req->sense, SCSI_SENSE_BUFFERSIZE);
+		sgs[num_out + num_in++] = &sense;
+		sg_init_one(&inhdr, &vbr->in_hdr, sizeof(vbr->in_hdr));
+		sgs[num_out + num_in++] = &inhdr;
+	}
+
+	sg_init_one(&status, &vbr->status, sizeof(vbr->status));
+	sgs[num_out + num_in++] = &status;
+
+	return virtqueue_add_sgs(vq, sgs, num_out, num_in, vbr, GFP_ATOMIC);
 }
 
-static inline void virtblk_add_req(struct virtblk_req *vbr,
-				   unsigned int out, unsigned int in)
+static void virtblk_add_req(struct virtblk_req *vbr, bool have_data)
 {
 	struct virtio_blk *vblk = vbr->vblk;
+	DEFINE_WAIT(wait);
+	int ret;
 
 	spin_lock_irq(vblk->disk->queue->queue_lock);
-	if (unlikely(virtqueue_add_buf(vblk->vq, vbr->sg, out, in, vbr,
-					GFP_ATOMIC) < 0)) {
+	while (unlikely((ret = __virtblk_add_req(vblk->vq, vbr, vbr->sg,
+						 have_data)) < 0)) {
+		prepare_to_wait_exclusive(&vblk->queue_wait, &wait,
+					  TASK_UNINTERRUPTIBLE);
+
 		spin_unlock_irq(vblk->disk->queue->queue_lock);
-		virtblk_add_buf_wait(vblk, vbr, out, in);
-		return;
+		io_schedule();
+		spin_lock_irq(vblk->disk->queue->queue_lock);
+
+		finish_wait(&vblk->queue_wait, &wait);
 	}
+
 	virtqueue_kick(vblk->vq);
 	spin_unlock_irq(vblk->disk->queue->queue_lock);
 }
 
-static int virtblk_bio_send_flush(struct virtblk_req *vbr)
+static void virtblk_bio_send_flush(struct virtblk_req *vbr)
 {
-	unsigned int out = 0, in = 0;
-
 	vbr->flags |= VBLK_IS_FLUSH;
 	vbr->out_hdr.type = VIRTIO_BLK_T_FLUSH;
 	vbr->out_hdr.sector = 0;
 	vbr->out_hdr.ioprio = 0;
-	sg_set_buf(&vbr->sg[out++], &vbr->out_hdr, sizeof(vbr->out_hdr));
-	sg_set_buf(&vbr->sg[out + in++], &vbr->status, sizeof(vbr->status));
 
-	virtblk_add_req(vbr, out, in);
-
-	return 0;
+	virtblk_add_req(vbr, false);
 }
 
-static int virtblk_bio_send_data(struct virtblk_req *vbr)
+static void virtblk_bio_send_data(struct virtblk_req *vbr)
 {
 	struct virtio_blk *vblk = vbr->vblk;
-	unsigned int num, out = 0, in = 0;
 	struct bio *bio = vbr->bio;
+	bool have_data;
 
 	vbr->flags &= ~VBLK_IS_FLUSH;
 	vbr->out_hdr.type = 0;
 	vbr->out_hdr.sector = bio->bi_sector;
 	vbr->out_hdr.ioprio = bio_prio(bio);
 
-	sg_set_buf(&vbr->sg[out++], &vbr->out_hdr, sizeof(vbr->out_hdr));
-
-	num = blk_bio_map_sg(vblk->disk->queue, bio, vbr->sg + out);
-
-	sg_set_buf(&vbr->sg[num + out + in++], &vbr->status,
-		   sizeof(vbr->status));
-
-	if (num) {
-		if (bio->bi_rw & REQ_WRITE) {
+	if (blk_bio_map_sg(vblk->disk->queue, bio, vbr->sg)) {
+		have_data = true;
+		if (bio->bi_rw & REQ_WRITE)
 			vbr->out_hdr.type |= VIRTIO_BLK_T_OUT;
-			out += num;
-		} else {
+		else
 			vbr->out_hdr.type |= VIRTIO_BLK_T_IN;
-			in += num;
-		}
-	}
-
-	virtblk_add_req(vbr, out, in);
+	} else
+		have_data = false;
 
-	return 0;
+	virtblk_add_req(vbr, have_data);
 }
 
 static void virtblk_bio_send_data_work(struct work_struct *work)
@@ -210,7 +217,8 @@ static void virtblk_bio_send_flush_work(struct work_struct *work)
 	virtblk_bio_send_flush(vbr);
 }
 
-static inline void virtblk_request_done(struct virtblk_req *vbr)
+static inline void virtblk_request_done(struct virtblk_req *vbr,
+					struct batch_complete *batch)
 {
 	struct virtio_blk *vblk = vbr->vblk;
 	struct request *req = vbr->req;
@@ -224,11 +232,12 @@ static inline void virtblk_request_done(struct virtblk_req *vbr)
 		req->errors = (error != 0);
 	}
 
-	__blk_end_request_all(req, error);
+	blk_end_request_all_batch(req, error, batch);
 	mempool_free(vbr, vblk->pool);
 }
 
-static inline void virtblk_bio_flush_done(struct virtblk_req *vbr)
+static inline void virtblk_bio_flush_done(struct virtblk_req *vbr,
+					  struct batch_complete *batch)
 {
 	struct virtio_blk *vblk = vbr->vblk;
 
@@ -237,12 +246,13 @@ static inline void virtblk_bio_flush_done(struct virtblk_req *vbr)
 		INIT_WORK(&vbr->work, virtblk_bio_send_data_work);
 		queue_work(virtblk_wq, &vbr->work);
 	} else {
-		bio_endio(vbr->bio, virtblk_result(vbr));
+		bio_endio_batch(vbr->bio, virtblk_result(vbr), batch);
 		mempool_free(vbr, vblk->pool);
 	}
 }
 
-static inline void virtblk_bio_data_done(struct virtblk_req *vbr)
+static inline void virtblk_bio_data_done(struct virtblk_req *vbr,
+					 struct batch_complete *batch)
 {
 	struct virtio_blk *vblk = vbr->vblk;
 
@@ -252,17 +262,18 @@ static inline void virtblk_bio_data_done(struct virtblk_req *vbr)
 		INIT_WORK(&vbr->work, virtblk_bio_send_flush_work);
 		queue_work(virtblk_wq, &vbr->work);
 	} else {
-		bio_endio(vbr->bio, virtblk_result(vbr));
+		bio_endio_batch(vbr->bio, virtblk_result(vbr), batch);
 		mempool_free(vbr, vblk->pool);
 	}
 }
 
-static inline void virtblk_bio_done(struct virtblk_req *vbr)
+static inline void virtblk_bio_done(struct virtblk_req *vbr,
+				    struct batch_complete *batch)
 {
 	if (unlikely(vbr->flags & VBLK_IS_FLUSH))
-		virtblk_bio_flush_done(vbr);
+		virtblk_bio_flush_done(vbr, batch);
 	else
-		virtblk_bio_data_done(vbr);
+		virtblk_bio_data_done(vbr, batch);
 }
 
 static void virtblk_done(struct virtqueue *vq)
@@ -272,16 +283,19 @@ static void virtblk_done(struct virtqueue *vq)
 	struct virtblk_req *vbr;
 	unsigned long flags;
 	unsigned int len;
+	struct batch_complete batch;
+
+	batch_complete_init(&batch);
 
 	spin_lock_irqsave(vblk->disk->queue->queue_lock, flags);
 	do {
 		virtqueue_disable_cb(vq);
 		while ((vbr = virtqueue_get_buf(vblk->vq, &len)) != NULL) {
 			if (vbr->bio) {
-				virtblk_bio_done(vbr);
+				virtblk_bio_done(vbr, &batch);
 				bio_done = true;
 			} else {
-				virtblk_request_done(vbr);
+				virtblk_request_done(vbr, &batch);
 				req_done = true;
 			}
 		}
@@ -291,6 +305,8 @@ static void virtblk_done(struct virtqueue *vq)
 		blk_start_queue(vblk->disk->queue);
 	spin_unlock_irqrestore(vblk->disk->queue->queue_lock, flags);
 
+	batch_complete(&batch);
+
 	if (bio_done)
 		wake_up(&vblk->queue_wait);
 }
@@ -298,7 +314,7 @@ static void virtblk_done(struct virtqueue *vq)
 static bool do_req(struct request_queue *q, struct virtio_blk *vblk,
 		   struct request *req)
 {
-	unsigned long num, out = 0, in = 0;
+	unsigned int num;
 	struct virtblk_req *vbr;
 
 	vbr = virtblk_alloc_req(vblk, GFP_ATOMIC);
@@ -335,40 +351,15 @@ static bool do_req(struct request_queue *q, struct virtio_blk *vblk,
 		}
 	}
 
-	sg_set_buf(&vblk->sg[out++], &vbr->out_hdr, sizeof(vbr->out_hdr));
-
-	/*
-	 * If this is a packet command we need a couple of additional headers.
-	 * Behind the normal outhdr we put a segment with the scsi command
-	 * block, and before the normal inhdr we put the sense data and the
-	 * inhdr with additional status information before the normal inhdr.
-	 */
-	if (vbr->req->cmd_type == REQ_TYPE_BLOCK_PC)
-		sg_set_buf(&vblk->sg[out++], vbr->req->cmd, vbr->req->cmd_len);
-
-	num = blk_rq_map_sg(q, vbr->req, vblk->sg + out);
-
-	if (vbr->req->cmd_type == REQ_TYPE_BLOCK_PC) {
-		sg_set_buf(&vblk->sg[num + out + in++], vbr->req->sense, SCSI_SENSE_BUFFERSIZE);
-		sg_set_buf(&vblk->sg[num + out + in++], &vbr->in_hdr,
-			   sizeof(vbr->in_hdr));
-	}
-
-	sg_set_buf(&vblk->sg[num + out + in++], &vbr->status,
-		   sizeof(vbr->status));
-
+	num = blk_rq_map_sg(q, vbr->req, vblk->sg);
 	if (num) {
-		if (rq_data_dir(vbr->req) == WRITE) {
+		if (rq_data_dir(vbr->req) == WRITE)
 			vbr->out_hdr.type |= VIRTIO_BLK_T_OUT;
-			out += num;
-		} else {
+		else
 			vbr->out_hdr.type |= VIRTIO_BLK_T_IN;
-			in += num;
-		}
 	}
 
-	if (virtqueue_add_buf(vblk->vq, vblk->sg, out, in, vbr,
-			      GFP_ATOMIC) < 0) {
+	if (__virtblk_add_req(vblk->vq, vbr, vblk->sg, num) < 0) {
 		mempool_free(vbr, vblk->pool);
 		return false;
 	}
@@ -539,6 +530,7 @@ static void virtblk_config_changed_work(struct work_struct *work)
 	struct virtio_device *vdev = vblk->vdev;
 	struct request_queue *q = vblk->disk->queue;
 	char cap_str_2[10], cap_str_10[10];
+	char *envp[] = { "RESIZE=1", NULL };
 	u64 capacity, size;
 
 	mutex_lock(&vblk->config_lock);
@@ -568,6 +560,7 @@ static void virtblk_config_changed_work(struct work_struct *work)
 
 	set_capacity(vblk->disk, capacity);
 	revalidate_disk(vblk->disk);
+	kobject_uevent_env(&disk_to_dev(vblk->disk)->kobj, KOBJ_CHANGE, envp);
 done:
 	mutex_unlock(&vblk->config_lock);
 }
diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c
index dd5b2fe..990c1d8 100644
--- a/drivers/block/xen-blkback/blkback.c
+++ b/drivers/block/xen-blkback/blkback.c
@@ -741,7 +741,8 @@ static void __end_block_io_op(struct pending_req *pending_req, int error)
 /*
  * bio callback.
  */
-static void end_block_io_op(struct bio *bio, int error)
+static void end_block_io_op(struct bio *bio, int error,
+			    struct batch_complete *batch)
 {
 	__end_block_io_op(bio->bi_private, error);
 	bio_put(bio);
diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c
index 6aab00e..11f467c 100644
--- a/drivers/bluetooth/ath3k.c
+++ b/drivers/bluetooth/ath3k.c
@@ -90,6 +90,7 @@ static struct usb_device_id ath3k_table[] = {
 	{ USB_DEVICE(0x13d3, 0x3393) },
 	{ USB_DEVICE(0x0489, 0xe04e) },
 	{ USB_DEVICE(0x0489, 0xe056) },
+	{ USB_DEVICE(0x0489, 0xe04d) },
 
 	/* Atheros AR5BBU12 with sflash firmware */
 	{ USB_DEVICE(0x0489, 0xE02C) },
@@ -126,6 +127,7 @@ static struct usb_device_id ath3k_blist_tbl[] = {
 	{ USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x0489, 0xe04d), .driver_info = BTUSB_ATH3012 },
 
 	/* Atheros AR5BBU22 with sflash firmware */
 	{ USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 },
diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c
index 0d26851..6c3e3d4 100644
--- a/drivers/bluetooth/bluecard_cs.c
+++ b/drivers/bluetooth/bluecard_cs.c
@@ -934,17 +934,4 @@ static struct pcmcia_driver bluecard_driver = {
 	.remove		= bluecard_detach,
 	.id_table	= bluecard_ids,
 };
-
-static int __init init_bluecard_cs(void)
-{
-	return pcmcia_register_driver(&bluecard_driver);
-}
-
-
-static void __exit exit_bluecard_cs(void)
-{
-	pcmcia_unregister_driver(&bluecard_driver);
-}
-
-module_init(init_bluecard_cs);
-module_exit(exit_bluecard_cs);
+module_pcmcia_driver(bluecard_driver);
diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c
index 7ffd3f4..a1aaa3b 100644
--- a/drivers/bluetooth/bt3c_cs.c
+++ b/drivers/bluetooth/bt3c_cs.c
@@ -760,17 +760,4 @@ static struct pcmcia_driver bt3c_driver = {
 	.remove		= bt3c_detach,
 	.id_table	= bt3c_ids,
 };
-
-static int __init init_bt3c_cs(void)
-{
-	return pcmcia_register_driver(&bt3c_driver);
-}
-
-
-static void __exit exit_bt3c_cs(void)
-{
-	pcmcia_unregister_driver(&bt3c_driver);
-}
-
-module_init(init_bt3c_cs);
-module_exit(exit_bt3c_cs);
+module_pcmcia_driver(bt3c_driver);
diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c
index 9959d4c..1cb5183 100644
--- a/drivers/bluetooth/btmrvl_sdio.c
+++ b/drivers/bluetooth/btmrvl_sdio.c
@@ -83,8 +83,8 @@ static const struct btmrvl_sdio_card_reg btmrvl_reg_87xx = {
 };
 
 static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = {
-	.helper		= "sd8688_helper.bin",
-	.firmware	= "sd8688.bin",
+	.helper		= "mrvl/sd8688_helper.bin",
+	.firmware	= "mrvl/sd8688.bin",
 	.reg		= &btmrvl_reg_8688,
 	.sd_blksz_fw_dl	= 64,
 };
@@ -1185,7 +1185,7 @@ MODULE_AUTHOR("Marvell International Ltd.");
 MODULE_DESCRIPTION("Marvell BT-over-SDIO driver ver " VERSION);
 MODULE_VERSION(VERSION);
 MODULE_LICENSE("GPL v2");
-MODULE_FIRMWARE("sd8688_helper.bin");
-MODULE_FIRMWARE("sd8688.bin");
+MODULE_FIRMWARE("mrvl/sd8688_helper.bin");
+MODULE_FIRMWARE("mrvl/sd8688.bin");
 MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin");
 MODULE_FIRMWARE("mrvl/sd8797_uapsta.bin");
diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c
index 35a553a..beb262f 100644
--- a/drivers/bluetooth/btuart_cs.c
+++ b/drivers/bluetooth/btuart_cs.c
@@ -688,17 +688,4 @@ static struct pcmcia_driver btuart_driver = {
 	.remove		= btuart_detach,
 	.id_table	= btuart_ids,
 };
-
-static int __init init_btuart_cs(void)
-{
-	return pcmcia_register_driver(&btuart_driver);
-}
-
-
-static void __exit exit_btuart_cs(void)
-{
-	pcmcia_unregister_driver(&btuart_driver);
-}
-
-module_init(init_btuart_cs);
-module_exit(exit_btuart_cs);
+module_pcmcia_driver(btuart_driver);
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 2cc5f77..35c967f 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -148,6 +148,7 @@ static struct usb_device_id blacklist_table[] = {
 	{ USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x0489, 0xe04d), .driver_info = BTUSB_ATH3012 },
 
 	/* Atheros AR5BBU12 with sflash firmware */
 	{ USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE },
@@ -245,6 +246,7 @@ struct btusb_data {
 	struct usb_endpoint_descriptor *isoc_rx_ep;
 
 	__u8 cmdreq_type;
+	unsigned long driver_info;
 
 	unsigned int sco_num;
 	int isoc_altsetting;
@@ -698,6 +700,26 @@ static int btusb_flush(struct hci_dev *hdev)
 	return 0;
 }
 
+static int btusb_setup(struct hci_dev *hdev)
+{
+	struct btusb_data *data = hci_get_drvdata(hdev);
+
+	BT_DBG("%s", hdev->name);
+
+	if (data->driver_info & BTUSB_BCM92035) {
+		struct sk_buff *skb;
+		__u8 val = 0x00;
+
+		skb = __hci_cmd_sync(hdev, 0xfc3b, 1, &val, HCI_INIT_TIMEOUT);
+		if (IS_ERR(skb))
+			BT_ERR("BCM92035 command failed (%ld)", -PTR_ERR(skb));
+		else
+			kfree_skb(skb);
+	}
+
+	return 0;
+}
+
 static int btusb_send_frame(struct sk_buff *skb)
 {
 	struct hci_dev *hdev = (struct hci_dev *) skb->dev;
@@ -995,6 +1017,7 @@ static int btusb_probe(struct usb_interface *intf,
 		return -ENODEV;
 
 	data->cmdreq_type = USB_TYPE_CLASS;
+	data->driver_info = id->driver_info;
 
 	data->udev = interface_to_usbdev(intf);
 	data->intf = intf;
@@ -1025,6 +1048,7 @@ static int btusb_probe(struct usb_interface *intf,
 	hdev->open     = btusb_open;
 	hdev->close    = btusb_close;
 	hdev->flush    = btusb_flush;
+	hdev->setup    = btusb_setup;
 	hdev->send     = btusb_send_frame;
 	hdev->notify   = btusb_notify;
 
@@ -1065,17 +1089,6 @@ static int btusb_probe(struct usb_interface *intf,
 		data->isoc = NULL;
 	}
 
-	if (id->driver_info & BTUSB_BCM92035) {
-		unsigned char cmd[] = { 0x3b, 0xfc, 0x01, 0x00 };
-		struct sk_buff *skb;
-
-		skb = bt_skb_alloc(sizeof(cmd), GFP_KERNEL);
-		if (skb) {
-			memcpy(skb_put(skb, sizeof(cmd)), cmd, sizeof(cmd));
-			skb_queue_tail(&hdev->driver_init, skb);
-		}
-	}
-
 	if (data->isoc) {
 		err = usb_driver_claim_interface(&btusb_driver,
 							data->isoc, data);
diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c
index 036cb36..33f3a69 100644
--- a/drivers/bluetooth/dtl1_cs.c
+++ b/drivers/bluetooth/dtl1_cs.c
@@ -628,17 +628,4 @@ static struct pcmcia_driver dtl1_driver = {
 	.remove		= dtl1_detach,
 	.id_table	= dtl1_ids,
 };
-
-static int __init init_dtl1_cs(void)
-{
-	return pcmcia_register_driver(&dtl1_driver);
-}
-
-
-static void __exit exit_dtl1_cs(void)
-{
-	pcmcia_unregister_driver(&dtl1_driver);
-}
-
-module_init(init_dtl1_cs);
-module_exit(exit_dtl1_cs);
+module_pcmcia_driver(dtl1_driver);
diff --git a/drivers/bluetooth/hci_h4.c b/drivers/bluetooth/hci_h4.c
index c60623f..8ae9f1e 100644
--- a/drivers/bluetooth/hci_h4.c
+++ b/drivers/bluetooth/hci_h4.c
@@ -153,6 +153,9 @@ static int h4_recv(struct hci_uart *hu, void *data, int count)
 {
 	int ret;
 
+	if (!test_bit(HCI_UART_REGISTERED, &hu->flags))
+		return -EUNATCH;
+
 	ret = hci_recv_stream_fragment(hu->hdev, data, count);
 	if (ret < 0) {
 		BT_ERR("Frame Reassembly Failed");
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index ed0fade..bc68a44 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -260,12 +260,12 @@ static int hci_uart_send_frame(struct sk_buff *skb)
 
 /* ------ LDISC part ------ */
 /* hci_uart_tty_open
- * 
+ *
  *     Called when line discipline changed to HCI_UART.
  *
  * Arguments:
  *     tty    pointer to tty info structure
- * Return Value:    
+ * Return Value:
  *     0 if success, otherwise error code
  */
 static int hci_uart_tty_open(struct tty_struct *tty)
@@ -365,15 +365,15 @@ static void hci_uart_tty_wakeup(struct tty_struct *tty)
 }
 
 /* hci_uart_tty_receive()
- * 
+ *
  *     Called by tty low level driver when receive data is
  *     available.
- *     
+ *
  * Arguments:  tty          pointer to tty isntance data
  *             data         pointer to received data
  *             flags        pointer to flags for data
  *             count        count of received data in bytes
- *     
+ *
  * Return Value:    None
  */
 static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data, char *flags, int count)
@@ -388,7 +388,10 @@ static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data, char *f
 
 	spin_lock(&hu->rx_lock);
 	hu->proto->recv(hu, (void *) data, count);
-	hu->hdev->stat.byte_rx += count;
+
+	if (hu->hdev)
+		hu->hdev->stat.byte_rx += count;
+
 	spin_unlock(&hu->rx_lock);
 
 	tty_unthrottle(tty);
diff --git a/drivers/char/applicom.c b/drivers/char/applicom.c
index 25373df..974321a 100644
--- a/drivers/char/applicom.c
+++ b/drivers/char/applicom.c
@@ -804,8 +804,8 @@ static long ac_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 
 			printk(KERN_INFO "Prom version board %d ....... V%d.%d %s",
 			       i+1,
-			       (int)(readb(apbs[IndexCard].RamIO + VERS) >> 4),
-			       (int)(readb(apbs[IndexCard].RamIO + VERS) & 0xF),
+			       (int)(readb(apbs[i].RamIO + VERS) >> 4),
+			       (int)(readb(apbs[i].RamIO + VERS) & 0xF),
 			       boardname);
 
 
diff --git a/drivers/char/ds1620.c b/drivers/char/ds1620.c
index 24ffd8c..b599fae 100644
--- a/drivers/char/ds1620.c
+++ b/drivers/char/ds1620.c
@@ -397,10 +397,9 @@ static int __init ds1620_init(void)
 		return ret;
 
 #ifdef THERM_USE_PROC
-	proc_therm_ds1620 = create_proc_entry("therm", 0, NULL);
-	if (proc_therm_ds1620)
-		proc_therm_ds1620->read_proc = proc_therm_ds1620_read;
-	else
+	proc_therm_ds1620 = create_proc_read_entry("therm", 0, NULL,
+					proc_therm_ds1620_read, NULL);
+	if (!proc_therm_ds1620)
 		printk(KERN_ERR "therm: unable to register /proc/therm\n");
 #endif
 
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig
index c5a0262..2f9dbf7 100644
--- a/drivers/char/hw_random/Kconfig
+++ b/drivers/char/hw_random/Kconfig
@@ -86,6 +86,18 @@ config HW_RANDOM_BCM63XX
 
 	  If unusure, say Y.
 
+config HW_RANDOM_BCM2835
+	tristate "Broadcom BCM2835 Random Number Generator support"
+	depends on HW_RANDOM && ARCH_BCM2835
+	default HW_RANDOM
+	---help---
+	  This driver provides kernel-side support for the Random Number
+	  Generator hardware found on the Broadcom BCM2835 SoCs.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called bcm2835-rng
+
+	  If unsure, say Y.
 
 config HW_RANDOM_GEODE
 	tristate "AMD Geode HW Random Number Generator support"
diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile
index 1fd7eec..bed467c 100644
--- a/drivers/char/hw_random/Makefile
+++ b/drivers/char/hw_random/Makefile
@@ -26,3 +26,4 @@ obj-$(CONFIG_HW_RANDOM_PPC4XX) += ppc4xx-rng.o
 obj-$(CONFIG_HW_RANDOM_PSERIES) += pseries-rng.o
 obj-$(CONFIG_HW_RANDOM_EXYNOS)	+= exynos-rng.o
 obj-$(CONFIG_HW_RANDOM_TPM) += tpm-rng.o
+obj-$(CONFIG_HW_RANDOM_BCM2835) += bcm2835-rng.o
diff --git a/drivers/char/hw_random/bcm2835-rng.c b/drivers/char/hw_random/bcm2835-rng.c
new file mode 100644
index 0000000..eb7f147
--- /dev/null
+++ b/drivers/char/hw_random/bcm2835-rng.c
@@ -0,0 +1,113 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
+ * Copyright (c) 2013 Lubomir Rintel
+ *
+ * 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.
+ */
+
+#include <linux/hw_random.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/printk.h>
+
+#define RNG_CTRL	0x0
+#define RNG_STATUS	0x4
+#define RNG_DATA	0x8
+
+/* enable rng */
+#define RNG_RBGEN	0x1
+
+/* the initial numbers generated are "less random" so will be discarded */
+#define RNG_WARMUP_COUNT 0x40000
+
+static int bcm2835_rng_read(struct hwrng *rng, void *buf, size_t max,
+			       bool wait)
+{
+	void __iomem *rng_base = (void __iomem *)rng->priv;
+
+	while ((__raw_readl(rng_base + RNG_STATUS) >> 24) == 0) {
+		if (!wait)
+			return 0;
+		cpu_relax();
+	}
+
+	*(u32 *)buf = __raw_readl(rng_base + RNG_DATA);
+	return sizeof(u32);
+}
+
+static struct hwrng bcm2835_rng_ops = {
+	.name	= "bcm2835",
+	.read	= bcm2835_rng_read,
+};
+
+static int bcm2835_rng_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	void __iomem *rng_base;
+	int err;
+
+	/* map peripheral */
+	rng_base = of_iomap(np, 0);
+	if (!rng_base) {
+		dev_err(dev, "failed to remap rng regs");
+		return -ENODEV;
+	}
+	bcm2835_rng_ops.priv = (unsigned long)rng_base;
+
+	/* register driver */
+	err = hwrng_register(&bcm2835_rng_ops);
+	if (err) {
+		dev_err(dev, "hwrng registration failed\n");
+		iounmap(rng_base);
+	} else {
+		dev_info(dev, "hwrng registered\n");
+
+		/* set warm-up count & enable */
+		__raw_writel(RNG_WARMUP_COUNT, rng_base + RNG_STATUS);
+		__raw_writel(RNG_RBGEN, rng_base + RNG_CTRL);
+	}
+	return err;
+}
+
+static int bcm2835_rng_remove(struct platform_device *pdev)
+{
+	void __iomem *rng_base = (void __iomem *)bcm2835_rng_ops.priv;
+
+	/* disable rng hardware */
+	__raw_writel(0, rng_base + RNG_CTRL);
+
+	/* unregister driver */
+	hwrng_unregister(&bcm2835_rng_ops);
+	iounmap(rng_base);
+
+	return 0;
+}
+
+static const struct of_device_id bcm2835_rng_of_match[] = {
+	{ .compatible = "brcm,bcm2835-rng", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, bcm2835_rng_of_match);
+
+static struct platform_driver bcm2835_rng_driver = {
+	.driver = {
+		.name = "bcm2835-rng",
+		.owner = THIS_MODULE,
+		.of_match_table = bcm2835_rng_of_match,
+	},
+	.probe		= bcm2835_rng_probe,
+	.remove		= bcm2835_rng_remove,
+};
+module_platform_driver(bcm2835_rng_driver);
+
+MODULE_AUTHOR("Lubomir Rintel <lkundrak@v3.sk>");
+MODULE_DESCRIPTION("BCM2835 Random Number Generator (RNG) driver");
+MODULE_LICENSE("GPLv2");
diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c
index 69ae597..a0f7724 100644
--- a/drivers/char/hw_random/core.c
+++ b/drivers/char/hw_random/core.c
@@ -380,6 +380,15 @@ void hwrng_unregister(struct hwrng *rng)
 }
 EXPORT_SYMBOL_GPL(hwrng_unregister);
 
+static void __exit hwrng_exit(void)
+{
+	mutex_lock(&rng_mutex);
+	BUG_ON(current_rng);
+	kfree(rng_buffer);
+	mutex_unlock(&rng_mutex);
+}
+
+module_exit(hwrng_exit);
 
 MODULE_DESCRIPTION("H/W Random Number Generator (RNG) driver");
 MODULE_LICENSE("GPL");
diff --git a/drivers/char/hw_random/exynos-rng.c b/drivers/char/hw_random/exynos-rng.c
index ac47631..402ccfb 100644
--- a/drivers/char/hw_random/exynos-rng.c
+++ b/drivers/char/hw_random/exynos-rng.c
@@ -144,6 +144,7 @@ static int exynos_rng_remove(struct platform_device *pdev)
 	return 0;
 }
 
+#if defined(CONFIG_PM_SLEEP) || defined(CONFIG_PM_RUNTIME)
 static int exynos_rng_runtime_suspend(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
@@ -161,7 +162,7 @@ static int exynos_rng_runtime_resume(struct device *dev)
 
 	return clk_prepare_enable(exynos_rng->clk);
 }
-
+#endif
 
 static UNIVERSAL_DEV_PM_OPS(exynos_rng_pm_ops, exynos_rng_runtime_suspend,
 					exynos_rng_runtime_resume, NULL);
diff --git a/drivers/char/hw_random/mxc-rnga.c b/drivers/char/hw_random/mxc-rnga.c
index f05d857..4ca35e8 100644
--- a/drivers/char/hw_random/mxc-rnga.c
+++ b/drivers/char/hw_random/mxc-rnga.c
@@ -142,7 +142,7 @@ static void mxc_rnga_cleanup(struct hwrng *rng)
 static int __init mxc_rnga_probe(struct platform_device *pdev)
 {
 	int err = -ENODEV;
-	struct resource *res, *mem;
+	struct resource *res;
 	struct mxc_rng *mxc_rng;
 
 	mxc_rng = devm_kzalloc(&pdev->dev, sizeof(struct mxc_rng),
@@ -172,15 +172,9 @@ static int __init mxc_rnga_probe(struct platform_device *pdev)
 		goto err_region;
 	}
 
-	mem = request_mem_region(res->start, resource_size(res), pdev->name);
-	if (mem == NULL) {
-		err = -EBUSY;
-		goto err_region;
-	}
-
-	mxc_rng->mem = ioremap(res->start, resource_size(res));
-	if (!mxc_rng->mem) {
-		err = -ENOMEM;
+	mxc_rng->mem = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(mxc_rng->mem)) {
+		err = PTR_ERR(mxc_rng->mem);
 		goto err_ioremap;
 	}
 
@@ -195,8 +189,6 @@ static int __init mxc_rnga_probe(struct platform_device *pdev)
 	return 0;
 
 err_ioremap:
-	release_mem_region(res->start, resource_size(res));
-
 err_region:
 	clk_disable_unprepare(mxc_rng->clk);
 
@@ -206,15 +198,10 @@ out:
 
 static int __exit mxc_rnga_remove(struct platform_device *pdev)
 {
-	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	struct mxc_rng *mxc_rng = platform_get_drvdata(pdev);
 
 	hwrng_unregister(&mxc_rng->rng);
 
-	iounmap(mxc_rng->mem);
-
-	release_mem_region(res->start, resource_size(res));
-
 	clk_disable_unprepare(mxc_rng->clk);
 
 	return 0;
@@ -228,18 +215,7 @@ static struct platform_driver mxc_rnga_driver = {
 	.remove = __exit_p(mxc_rnga_remove),
 };
 
-static int __init mod_init(void)
-{
-	return platform_driver_probe(&mxc_rnga_driver, mxc_rnga_probe);
-}
-
-static void __exit mod_exit(void)
-{
-	platform_driver_unregister(&mxc_rnga_driver);
-}
-
-module_init(mod_init);
-module_exit(mod_exit);
+module_platform_driver_probe(mxc_rnga_driver, mxc_rnga_probe);
 
 MODULE_AUTHOR("Freescale Semiconductor, Inc.");
 MODULE_DESCRIPTION("H/W RNGA driver for i.MX");
diff --git a/drivers/char/hw_random/timeriomem-rng.c b/drivers/char/hw_random/timeriomem-rng.c
index 849db19..3e75737 100644
--- a/drivers/char/hw_random/timeriomem-rng.c
+++ b/drivers/char/hw_random/timeriomem-rng.c
@@ -23,127 +23,209 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
+#include <linux/of.h>
 #include <linux/hw_random.h>
 #include <linux/io.h>
+#include <linux/slab.h>
 #include <linux/timeriomem-rng.h>
 #include <linux/jiffies.h>
 #include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/completion.h>
 
-static struct timeriomem_rng_data *timeriomem_rng_data;
+struct timeriomem_rng_private_data {
+	void __iomem		*io_base;
+	unsigned int		expires;
+	unsigned int		period;
+	unsigned int		present:1;
 
-static void timeriomem_rng_trigger(unsigned long);
-static DEFINE_TIMER(timeriomem_rng_timer, timeriomem_rng_trigger, 0, 0);
+	struct timer_list	timer;
+	struct completion	completion;
+
+	struct hwrng		timeriomem_rng_ops;
+};
+
+#define to_rng_priv(rng) \
+		((struct timeriomem_rng_private_data *)rng->priv)
 
 /*
  * have data return 1, however return 0 if we have nothing
  */
 static int timeriomem_rng_data_present(struct hwrng *rng, int wait)
 {
-	if (rng->priv == 0)
-		return 1;
+	struct timeriomem_rng_private_data *priv = to_rng_priv(rng);
 
-	if (!wait || timeriomem_rng_data->present)
-		return timeriomem_rng_data->present;
+	if (!wait || priv->present)
+		return priv->present;
 
-	wait_for_completion(&timeriomem_rng_data->completion);
+	wait_for_completion(&priv->completion);
 
 	return 1;
 }
 
 static int timeriomem_rng_data_read(struct hwrng *rng, u32 *data)
 {
+	struct timeriomem_rng_private_data *priv = to_rng_priv(rng);
 	unsigned long cur;
 	s32 delay;
 
-	*data = readl(timeriomem_rng_data->address);
+	*data = readl(priv->io_base);
 
-	if (rng->priv != 0) {
-		cur = jiffies;
+	cur = jiffies;
 
-		delay = cur - timeriomem_rng_timer.expires;
-		delay = rng->priv - (delay % rng->priv);
+	delay = cur - priv->expires;
+	delay = priv->period - (delay % priv->period);
 
-		timeriomem_rng_timer.expires = cur + delay;
-		timeriomem_rng_data->present = 0;
+	priv->expires = cur + delay;
+	priv->present = 0;
 
-		init_completion(&timeriomem_rng_data->completion);
-		add_timer(&timeriomem_rng_timer);
-	}
+	INIT_COMPLETION(priv->completion);
+	mod_timer(&priv->timer, priv->expires);
 
 	return 4;
 }
 
-static void timeriomem_rng_trigger(unsigned long dummy)
+static void timeriomem_rng_trigger(unsigned long data)
 {
-	timeriomem_rng_data->present = 1;
-	complete(&timeriomem_rng_data->completion);
-}
+	struct timeriomem_rng_private_data *priv
+			= (struct timeriomem_rng_private_data *)data;
 
-static struct hwrng timeriomem_rng_ops = {
-	.name		= "timeriomem",
-	.data_present	= timeriomem_rng_data_present,
-	.data_read	= timeriomem_rng_data_read,
-	.priv		= 0,
-};
+	priv->present = 1;
+	complete(&priv->completion);
+}
 
 static int timeriomem_rng_probe(struct platform_device *pdev)
 {
+	struct timeriomem_rng_data *pdata = pdev->dev.platform_data;
+	struct timeriomem_rng_private_data *priv;
 	struct resource *res;
-	int ret;
+	int err = 0;
+	int period;
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!pdev->dev.of_node && !pdata) {
+		dev_err(&pdev->dev, "timeriomem_rng_data is missing\n");
+		return -EINVAL;
+	}
 
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res)
-		return -ENOENT;
+		return -ENXIO;
 
-	timeriomem_rng_data = pdev->dev.platform_data;
+	if (res->start % 4 != 0 || resource_size(res) != 4) {
+		dev_err(&pdev->dev,
+			"address must be four bytes wide and aligned\n");
+		return -EINVAL;
+	}
 
-	timeriomem_rng_data->address = ioremap(res->start, resource_size(res));
-	if (!timeriomem_rng_data->address)
-		return -EIO;
+	/* Allocate memory for the device structure (and zero it) */
+	priv = kzalloc(sizeof(struct timeriomem_rng_private_data), GFP_KERNEL);
+	if (!priv) {
+		dev_err(&pdev->dev, "failed to allocate device structure.\n");
+		return -ENOMEM;
+	}
+
+	platform_set_drvdata(pdev, priv);
+
+	if (pdev->dev.of_node) {
+		int i;
+
+		if (!of_property_read_u32(pdev->dev.of_node,
+						"period", &i))
+			period = i;
+		else {
+			dev_err(&pdev->dev, "missing period\n");
+			err = -EINVAL;
+			goto out_free;
+		}
+	} else
+		period = pdata->period;
+
+	priv->period = usecs_to_jiffies(period);
+	if (priv->period < 1) {
+		dev_err(&pdev->dev, "period is less than one jiffy\n");
+		err = -EINVAL;
+		goto out_free;
+	}
 
-	if (timeriomem_rng_data->period != 0
-		&& usecs_to_jiffies(timeriomem_rng_data->period) > 0) {
-		timeriomem_rng_timer.expires = jiffies;
+	priv->expires	= jiffies;
+	priv->present	= 1;
 
-		timeriomem_rng_ops.priv = usecs_to_jiffies(
-						timeriomem_rng_data->period);
+	init_completion(&priv->completion);
+	complete(&priv->completion);
+
+	setup_timer(&priv->timer, timeriomem_rng_trigger, (unsigned long)priv);
+
+	priv->timeriomem_rng_ops.name		= dev_name(&pdev->dev);
+	priv->timeriomem_rng_ops.data_present	= timeriomem_rng_data_present;
+	priv->timeriomem_rng_ops.data_read	= timeriomem_rng_data_read;
+	priv->timeriomem_rng_ops.priv		= (unsigned long)priv;
+
+	if (!request_mem_region(res->start, resource_size(res),
+				dev_name(&pdev->dev))) {
+		dev_err(&pdev->dev, "request_mem_region failed\n");
+		err = -EBUSY;
+		goto out_timer;
 	}
-	timeriomem_rng_data->present = 1;
 
-	ret = hwrng_register(&timeriomem_rng_ops);
-	if (ret)
-		goto failed;
+	priv->io_base = ioremap(res->start, resource_size(res));
+	if (priv->io_base == NULL) {
+		dev_err(&pdev->dev, "ioremap failed\n");
+		err = -EIO;
+		goto out_release_io;
+	}
+
+	err = hwrng_register(&priv->timeriomem_rng_ops);
+	if (err) {
+		dev_err(&pdev->dev, "problem registering\n");
+		goto out;
+	}
 
 	dev_info(&pdev->dev, "32bits from 0x%p @ %dus\n",
-			timeriomem_rng_data->address,
-			timeriomem_rng_data->period);
+			priv->io_base, period);
 
 	return 0;
 
-failed:
-	dev_err(&pdev->dev, "problem registering\n");
-	iounmap(timeriomem_rng_data->address);
-
-	return ret;
+out:
+	iounmap(priv->io_base);
+out_release_io:
+	release_mem_region(res->start, resource_size(res));
+out_timer:
+	del_timer_sync(&priv->timer);
+out_free:
+	platform_set_drvdata(pdev, NULL);
+	kfree(priv);
+	return err;
 }
 
 static int timeriomem_rng_remove(struct platform_device *pdev)
 {
-	del_timer_sync(&timeriomem_rng_timer);
-	hwrng_unregister(&timeriomem_rng_ops);
+	struct timeriomem_rng_private_data *priv = platform_get_drvdata(pdev);
+	struct resource *res;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
-	iounmap(timeriomem_rng_data->address);
+	hwrng_unregister(&priv->timeriomem_rng_ops);
+
+	del_timer_sync(&priv->timer);
+	iounmap(priv->io_base);
+	release_mem_region(res->start, resource_size(res));
+	platform_set_drvdata(pdev, NULL);
+	kfree(priv);
 
 	return 0;
 }
 
+static const struct of_device_id timeriomem_rng_match[] = {
+	{ .compatible = "timeriomem_rng" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, timeriomem_rng_match);
+
 static struct platform_driver timeriomem_rng_driver = {
 	.driver = {
 		.name		= "timeriomem_rng",
 		.owner		= THIS_MODULE,
+		.of_match_table	= timeriomem_rng_match,
 	},
 	.probe		= timeriomem_rng_probe,
 	.remove		= timeriomem_rng_remove,
diff --git a/drivers/char/hw_random/tx4939-rng.c b/drivers/char/hw_random/tx4939-rng.c
index 3099198..d34a24a 100644
--- a/drivers/char/hw_random/tx4939-rng.c
+++ b/drivers/char/hw_random/tx4939-rng.c
@@ -166,18 +166,7 @@ static struct platform_driver tx4939_rng_driver = {
 	.remove = tx4939_rng_remove,
 };
 
-static int __init tx4939rng_init(void)
-{
-	return platform_driver_probe(&tx4939_rng_driver, tx4939_rng_probe);
-}
-
-static void __exit tx4939rng_exit(void)
-{
-	platform_driver_unregister(&tx4939_rng_driver);
-}
-
-module_init(tx4939rng_init);
-module_exit(tx4939rng_exit);
+module_platform_driver_probe(tx4939_rng_driver, tx4939_rng_probe);
 
 MODULE_DESCRIPTION("H/W Random Number Generator (RNG) driver for TX4939");
 MODULE_LICENSE("GPL");
diff --git a/drivers/char/hw_random/virtio-rng.c b/drivers/char/hw_random/virtio-rng.c
index 6bf4d47..ef46a9c 100644
--- a/drivers/char/hw_random/virtio-rng.c
+++ b/drivers/char/hw_random/virtio-rng.c
@@ -47,7 +47,7 @@ static void register_buffer(u8 *buf, size_t size)
 	sg_init_one(&sg, buf, size);
 
 	/* There should always be room for one buffer. */
-	if (virtqueue_add_buf(vq, &sg, 0, 1, buf, GFP_KERNEL) < 0)
+	if (virtqueue_add_inbuf(vq, &sg, 1, buf, GFP_KERNEL) < 0)
 		BUG();
 
 	virtqueue_kick(vq);
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index 053201b..1420bbb 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -1917,7 +1917,7 @@ static int smi_ipmb_proc_show(struct seq_file *m, void *v)
 
 static int smi_ipmb_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, smi_ipmb_proc_show, PDE(inode)->data);
+	return single_open(file, smi_ipmb_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations smi_ipmb_proc_ops = {
@@ -1938,7 +1938,7 @@ static int smi_version_proc_show(struct seq_file *m, void *v)
 
 static int smi_version_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, smi_version_proc_show, PDE(inode)->data);
+	return single_open(file, smi_version_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations smi_version_proc_ops = {
@@ -2013,7 +2013,7 @@ static int smi_stats_proc_show(struct seq_file *m, void *v)
 
 static int smi_stats_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, smi_stats_proc_show, PDE(inode)->data);
+	return single_open(file, smi_stats_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations smi_stats_proc_ops = {
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index 0ac9b45..313538a 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -2839,7 +2839,7 @@ static int smi_type_proc_show(struct seq_file *m, void *v)
 
 static int smi_type_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, smi_type_proc_show, PDE(inode)->data);
+	return single_open(file, smi_type_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations smi_type_proc_ops = {
@@ -2882,7 +2882,7 @@ static int smi_si_stats_proc_show(struct seq_file *m, void *v)
 
 static int smi_si_stats_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, smi_si_stats_proc_show, PDE(inode)->data);
+	return single_open(file, smi_si_stats_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations smi_si_stats_proc_ops = {
@@ -2910,7 +2910,7 @@ static int smi_params_proc_show(struct seq_file *m, void *v)
 
 static int smi_params_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, smi_params_proc_show, PDE(inode)->data);
+	return single_open(file, smi_params_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations smi_params_proc_ops = {
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 2c644af..1ccbe94 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -28,6 +28,7 @@
 #include <linux/pfn.h>
 #include <linux/export.h>
 #include <linux/io.h>
+#include <linux/aio.h>
 
 #include <asm/uaccess.h>
 
@@ -627,6 +628,18 @@ static ssize_t write_null(struct file *file, const char __user *buf,
 	return count;
 }
 
+static ssize_t aio_read_null(struct kiocb *iocb, const struct iovec *iov,
+			     unsigned long nr_segs, loff_t pos)
+{
+	return 0;
+}
+
+static ssize_t aio_write_null(struct kiocb *iocb, const struct iovec *iov,
+			      unsigned long nr_segs, loff_t pos)
+{
+	return iov_length(iov, nr_segs);
+}
+
 static int pipe_to_null(struct pipe_inode_info *info, struct pipe_buffer *buf,
 			struct splice_desc *sd)
 {
@@ -670,6 +683,24 @@ static ssize_t read_zero(struct file *file, char __user *buf,
 	return written ? written : -EFAULT;
 }
 
+static ssize_t aio_read_zero(struct kiocb *iocb, const struct iovec *iov,
+			     unsigned long nr_segs, loff_t pos)
+{
+	size_t written = 0;
+	unsigned long i;
+	ssize_t ret;
+
+	for (i = 0; i < nr_segs; i++) {
+		ret = read_zero(iocb->ki_filp, iov[i].iov_base, iov[i].iov_len,
+				&pos);
+		if (ret < 0)
+			break;
+		written += ret;
+	}
+
+	return written ? written : -EFAULT;
+}
+
 static int mmap_zero(struct file *file, struct vm_area_struct *vma)
 {
 #ifndef CONFIG_MMU
@@ -738,6 +769,7 @@ static int open_port(struct inode *inode, struct file *filp)
 #define full_lseek      null_lseek
 #define write_zero	write_null
 #define read_full       read_zero
+#define aio_write_zero	aio_write_null
 #define open_mem	open_port
 #define open_kmem	open_mem
 #define open_oldmem	open_mem
@@ -766,6 +798,8 @@ static const struct file_operations null_fops = {
 	.llseek		= null_lseek,
 	.read		= read_null,
 	.write		= write_null,
+	.aio_read	= aio_read_null,
+	.aio_write	= aio_write_null,
 	.splice_write	= splice_write_null,
 };
 
@@ -782,6 +816,8 @@ static const struct file_operations zero_fops = {
 	.llseek		= zero_lseek,
 	.read		= read_zero,
 	.write		= write_zero,
+	.aio_read	= aio_read_zero,
+	.aio_write	= aio_write_zero,
 	.mmap		= mmap_zero,
 };
 
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 32a6c57..73e52b7 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -957,10 +957,23 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf,
 {
 	ssize_t ret = 0, i;
 	__u8 tmp[EXTRACT_SIZE];
+	unsigned long flags;
 
 	/* if last_data isn't primed, we need EXTRACT_SIZE extra bytes */
-	if (fips_enabled && !r->last_data_init)
-		nbytes += EXTRACT_SIZE;
+	if (fips_enabled) {
+		spin_lock_irqsave(&r->lock, flags);
+		if (!r->last_data_init) {
+			r->last_data_init = true;
+			spin_unlock_irqrestore(&r->lock, flags);
+			trace_extract_entropy(r->name, EXTRACT_SIZE,
+					      r->entropy_count, _RET_IP_);
+			xfer_secondary_pool(r, EXTRACT_SIZE);
+			extract_buf(r, tmp);
+			spin_lock_irqsave(&r->lock, flags);
+			memcpy(r->last_data, tmp, EXTRACT_SIZE);
+		}
+		spin_unlock_irqrestore(&r->lock, flags);
+	}
 
 	trace_extract_entropy(r->name, nbytes, r->entropy_count, _RET_IP_);
 	xfer_secondary_pool(r, nbytes);
@@ -970,19 +983,6 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf,
 		extract_buf(r, tmp);
 
 		if (fips_enabled) {
-			unsigned long flags;
-
-
-			/* prime last_data value if need be, per fips 140-2 */
-			if (!r->last_data_init) {
-				spin_lock_irqsave(&r->lock, flags);
-				memcpy(r->last_data, tmp, EXTRACT_SIZE);
-				r->last_data_init = true;
-				nbytes -= EXTRACT_SIZE;
-				spin_unlock_irqrestore(&r->lock, flags);
-				extract_buf(r, tmp);
-			}
-
 			spin_lock_irqsave(&r->lock, flags);
 			if (!memcmp(tmp, r->last_data, EXTRACT_SIZE))
 				panic("Hardware RNG duplicated output!\n");
@@ -1485,6 +1485,7 @@ unsigned int get_random_int(void)
 
 	return ret;
 }
+EXPORT_SYMBOL(get_random_int);
 
 /*
  * randomize_range() returns a start address such that
diff --git a/drivers/char/tile-srom.c b/drivers/char/tile-srom.c
index 3b22a60..2e2036e 100644
--- a/drivers/char/tile-srom.c
+++ b/drivers/char/tile-srom.c
@@ -371,7 +371,7 @@ static int srom_setup_minor(struct srom_dev *srom, int index)
 
 	dev = device_create(srom_class, &platform_bus,
 			    MKDEV(srom_major, index), srom, "%d", index);
-	return IS_ERR(dev) ? PTR_ERR(dev) : 0;
+	return PTR_RET(dev);
 }
 
 /** srom_init() - Initialize the driver's module. */
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index e905d5f..13ad9b1 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -149,7 +149,8 @@ struct ports_device {
 	spinlock_t ports_lock;
 
 	/* To protect the vq operations for the control channel */
-	spinlock_t cvq_lock;
+	spinlock_t c_ivq_lock;
+	spinlock_t c_ovq_lock;
 
 	/* The current config space is stored here */
 	struct virtio_console_config config;
@@ -502,7 +503,7 @@ static int add_inbuf(struct virtqueue *vq, struct port_buffer *buf)
 
 	sg_init_one(sg, buf->buf, buf->size);
 
-	ret = virtqueue_add_buf(vq, sg, 0, 1, buf, GFP_ATOMIC);
+	ret = virtqueue_add_inbuf(vq, sg, 1, buf, GFP_ATOMIC);
 	virtqueue_kick(vq);
 	if (!ret)
 		ret = vq->num_free;
@@ -569,11 +570,14 @@ static ssize_t __send_control_msg(struct ports_device *portdev, u32 port_id,
 	vq = portdev->c_ovq;
 
 	sg_init_one(sg, &cpkt, sizeof(cpkt));
-	if (virtqueue_add_buf(vq, sg, 1, 0, &cpkt, GFP_ATOMIC) == 0) {
+
+	spin_lock(&portdev->c_ovq_lock);
+	if (virtqueue_add_outbuf(vq, sg, 1, &cpkt, GFP_ATOMIC) == 0) {
 		virtqueue_kick(vq);
 		while (!virtqueue_get_buf(vq, &len))
 			cpu_relax();
 	}
+	spin_unlock(&portdev->c_ovq_lock);
 	return 0;
 }
 
@@ -618,7 +622,7 @@ static ssize_t __send_to_port(struct port *port, struct scatterlist *sg,
 
 	reclaim_consumed_buffers(port);
 
-	err = virtqueue_add_buf(out_vq, sg, nents, 0, data, GFP_ATOMIC);
+	err = virtqueue_add_outbuf(out_vq, sg, nents, data, GFP_ATOMIC);
 
 	/* Tell Host to go! */
 	virtqueue_kick(out_vq);
@@ -1436,7 +1440,7 @@ static int add_port(struct ports_device *portdev, u32 id)
 		 * rproc_serial does not want the console port, only
 		 * the generic port implementation.
 		 */
-		port->host_connected = port->guest_connected = true;
+		port->host_connected = true;
 	else if (!use_multiport(port->portdev)) {
 		/*
 		 * If we're not using multiport support,
@@ -1709,23 +1713,23 @@ static void control_work_handler(struct work_struct *work)
 	portdev = container_of(work, struct ports_device, control_work);
 	vq = portdev->c_ivq;
 
-	spin_lock(&portdev->cvq_lock);
+	spin_lock(&portdev->c_ivq_lock);
 	while ((buf = virtqueue_get_buf(vq, &len))) {
-		spin_unlock(&portdev->cvq_lock);
+		spin_unlock(&portdev->c_ivq_lock);
 
 		buf->len = len;
 		buf->offset = 0;
 
 		handle_control_message(portdev, buf);
 
-		spin_lock(&portdev->cvq_lock);
+		spin_lock(&portdev->c_ivq_lock);
 		if (add_inbuf(portdev->c_ivq, buf) < 0) {
 			dev_warn(&portdev->vdev->dev,
 				 "Error adding buffer to queue\n");
 			free_buf(buf, false);
 		}
 	}
-	spin_unlock(&portdev->cvq_lock);
+	spin_unlock(&portdev->c_ivq_lock);
 }
 
 static void out_intr(struct virtqueue *vq)
@@ -1752,13 +1756,23 @@ static void in_intr(struct virtqueue *vq)
 	port->inbuf = get_inbuf(port);
 
 	/*
-	 * Don't queue up data when port is closed.  This condition
+	 * Normally the port should not accept data when the port is
+	 * closed. For generic serial ports, the host won't (shouldn't)
+	 * send data till the guest is connected. But this condition
 	 * can be reached when a console port is not yet connected (no
-	 * tty is spawned) and the host sends out data to console
-	 * ports.  For generic serial ports, the host won't
-	 * (shouldn't) send data till the guest is connected.
+	 * tty is spawned) and the other side sends out data over the
+	 * vring, or when a remote devices start sending data before
+	 * the ports are opened.
+	 *
+	 * A generic serial port will discard data if not connected,
+	 * while console ports and rproc-serial ports accepts data at
+	 * any time. rproc-serial is initiated with guest_connected to
+	 * false because port_fops_open expects this. Console ports are
+	 * hooked up with an HVC console and is initialized with
+	 * guest_connected to true.
 	 */
-	if (!port->guest_connected)
+
+	if (!port->guest_connected && !is_rproc_serial(port->portdev->vdev))
 		discard_port_data(port);
 
 	spin_unlock_irqrestore(&port->inbuf_lock, flags);
@@ -1986,10 +2000,12 @@ static int virtcons_probe(struct virtio_device *vdev)
 	if (multiport) {
 		unsigned int nr_added_bufs;
 
-		spin_lock_init(&portdev->cvq_lock);
+		spin_lock_init(&portdev->c_ivq_lock);
+		spin_lock_init(&portdev->c_ovq_lock);
 		INIT_WORK(&portdev->control_work, &control_work_handler);
 
-		nr_added_bufs = fill_queue(portdev->c_ivq, &portdev->cvq_lock);
+		nr_added_bufs = fill_queue(portdev->c_ivq,
+					   &portdev->c_ivq_lock);
 		if (!nr_added_bufs) {
 			dev_err(&vdev->dev,
 				"Error allocating buffers for control queue\n");
@@ -2140,7 +2156,7 @@ static int virtcons_restore(struct virtio_device *vdev)
 		return ret;
 
 	if (use_multiport(portdev))
-		fill_queue(portdev->c_ivq, &portdev->cvq_lock);
+		fill_queue(portdev->c_ivq, &portdev->c_ivq_lock);
 
 	list_for_each_entry(port, &portdev->ports, list) {
 		port->in_vq = portdev->in_vqs[port->id];
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index a47e6ee..a64caef 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -63,6 +63,14 @@ config CLK_TWL6040
 	  McPDM. McPDM module is using the external bit clock on the McPDM bus
 	  as functional clock.
 
+config COMMON_CLK_AXI_CLKGEN
+	tristate "AXI clkgen driver"
+	depends on ARCH_ZYNQ || MICROBLAZE
+	help
+	---help---
+	  Support for the Analog Devices axi-clkgen pcore clock generator for Xilinx
+	  FPGAs. It is commonly used in Analog Devices' reference designs.
+
 endmenu
 
 source "drivers/clk/mvebu/Kconfig"
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 300d477..17e8dc4 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_COMMON_CLK)	+= clk-fixed-factor.o
 obj-$(CONFIG_COMMON_CLK)	+= clk-fixed-rate.o
 obj-$(CONFIG_COMMON_CLK)	+= clk-gate.o
 obj-$(CONFIG_COMMON_CLK)	+= clk-mux.o
+obj-$(CONFIG_COMMON_CLK)	+= clk-composite.o
 
 # SoCs specific
 obj-$(CONFIG_ARCH_BCM2835)	+= clk-bcm2835.o
@@ -23,14 +24,17 @@ ifeq ($(CONFIG_COMMON_CLK), y)
 obj-$(CONFIG_ARCH_MMP)		+= mmp/
 endif
 obj-$(CONFIG_MACH_LOONGSON1)	+= clk-ls1x.o
+obj-$(CONFIG_ARCH_SUNXI)	+= sunxi/
 obj-$(CONFIG_ARCH_U8500)	+= ux500/
 obj-$(CONFIG_ARCH_VT8500)	+= clk-vt8500.o
 obj-$(CONFIG_ARCH_ZYNQ)		+= clk-zynq.o
 obj-$(CONFIG_ARCH_TEGRA)	+= tegra/
+obj-$(CONFIG_PLAT_SAMSUNG)	+= samsung/
 
 obj-$(CONFIG_X86)		+= x86/
 
 # Chip specific
+obj-$(CONFIG_COMMON_CLK_AXI_CLKGEN) += clk-axi-clkgen.o
 obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o
 obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o
 obj-$(CONFIG_CLK_TWL6040)	+= clk-twl6040.o
diff --git a/drivers/clk/clk-axi-clkgen.c b/drivers/clk/clk-axi-clkgen.c
new file mode 100644
index 0000000..8137327
--- /dev/null
+++ b/drivers/clk/clk-axi-clkgen.c
@@ -0,0 +1,331 @@
+/*
+ * AXI clkgen driver
+ *
+ * Copyright 2012-2013 Analog Devices Inc.
+ *  Author: Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * Licensed under the GPL-2.
+ *
+ */
+
+#include <linux/platform_device.h>
+#include <linux/clk-provider.h>
+#include <linux/clk.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/module.h>
+#include <linux/err.h>
+
+#define AXI_CLKGEN_REG_UPDATE_ENABLE	0x04
+#define AXI_CLKGEN_REG_CLK_OUT1		0x08
+#define AXI_CLKGEN_REG_CLK_OUT2		0x0c
+#define AXI_CLKGEN_REG_CLK_DIV		0x10
+#define AXI_CLKGEN_REG_CLK_FB1		0x14
+#define AXI_CLKGEN_REG_CLK_FB2		0x18
+#define AXI_CLKGEN_REG_LOCK1		0x1c
+#define AXI_CLKGEN_REG_LOCK2		0x20
+#define AXI_CLKGEN_REG_LOCK3		0x24
+#define AXI_CLKGEN_REG_FILTER1		0x28
+#define AXI_CLKGEN_REG_FILTER2		0x2c
+
+struct axi_clkgen {
+	void __iomem *base;
+	struct clk_hw clk_hw;
+};
+
+static uint32_t axi_clkgen_lookup_filter(unsigned int m)
+{
+	switch (m) {
+	case 0:
+		return 0x01001990;
+	case 1:
+		return 0x01001190;
+	case 2:
+		return 0x01009890;
+	case 3:
+		return 0x01001890;
+	case 4:
+		return 0x01008890;
+	case 5 ... 8:
+		return 0x01009090;
+	case 9 ... 11:
+		return 0x01000890;
+	case 12:
+		return 0x08009090;
+	case 13 ... 22:
+		return 0x01001090;
+	case 23 ... 36:
+		return 0x01008090;
+	case 37 ... 46:
+		return 0x08001090;
+	default:
+		return 0x08008090;
+	}
+}
+
+static const uint32_t axi_clkgen_lock_table[] = {
+	0x060603e8, 0x060603e8, 0x080803e8, 0x0b0b03e8,
+	0x0e0e03e8, 0x111103e8, 0x131303e8, 0x161603e8,
+	0x191903e8, 0x1c1c03e8, 0x1f1f0384, 0x1f1f0339,
+	0x1f1f02ee, 0x1f1f02bc, 0x1f1f028a, 0x1f1f0271,
+	0x1f1f023f, 0x1f1f0226, 0x1f1f020d, 0x1f1f01f4,
+	0x1f1f01db, 0x1f1f01c2, 0x1f1f01a9, 0x1f1f0190,
+	0x1f1f0190, 0x1f1f0177, 0x1f1f015e, 0x1f1f015e,
+	0x1f1f0145, 0x1f1f0145, 0x1f1f012c, 0x1f1f012c,
+	0x1f1f012c, 0x1f1f0113, 0x1f1f0113, 0x1f1f0113,
+};
+
+static uint32_t axi_clkgen_lookup_lock(unsigned int m)
+{
+	if (m < ARRAY_SIZE(axi_clkgen_lock_table))
+		return axi_clkgen_lock_table[m];
+	return 0x1f1f00fa;
+}
+
+static const unsigned int fpfd_min = 10000;
+static const unsigned int fpfd_max = 300000;
+static const unsigned int fvco_min = 600000;
+static const unsigned int fvco_max = 1200000;
+
+static void axi_clkgen_calc_params(unsigned long fin, unsigned long fout,
+	unsigned int *best_d, unsigned int *best_m, unsigned int *best_dout)
+{
+	unsigned long d, d_min, d_max, _d_min, _d_max;
+	unsigned long m, m_min, m_max;
+	unsigned long f, dout, best_f, fvco;
+
+	fin /= 1000;
+	fout /= 1000;
+
+	best_f = ULONG_MAX;
+	*best_d = 0;
+	*best_m = 0;
+	*best_dout = 0;
+
+	d_min = max_t(unsigned long, DIV_ROUND_UP(fin, fpfd_max), 1);
+	d_max = min_t(unsigned long, fin / fpfd_min, 80);
+
+	m_min = max_t(unsigned long, DIV_ROUND_UP(fvco_min, fin) * d_min, 1);
+	m_max = min_t(unsigned long, fvco_max * d_max / fin, 64);
+
+	for (m = m_min; m <= m_max; m++) {
+		_d_min = max(d_min, DIV_ROUND_UP(fin * m, fvco_max));
+		_d_max = min(d_max, fin * m / fvco_min);
+
+		for (d = _d_min; d <= _d_max; d++) {
+			fvco = fin * m / d;
+
+			dout = DIV_ROUND_CLOSEST(fvco, fout);
+			dout = clamp_t(unsigned long, dout, 1, 128);
+			f = fvco / dout;
+			if (abs(f - fout) < abs(best_f - fout)) {
+				best_f = f;
+				*best_d = d;
+				*best_m = m;
+				*best_dout = dout;
+				if (best_f == fout)
+					return;
+			}
+		}
+	}
+}
+
+static void axi_clkgen_calc_clk_params(unsigned int divider, unsigned int *low,
+	unsigned int *high, unsigned int *edge, unsigned int *nocount)
+{
+	if (divider == 1)
+		*nocount = 1;
+	else
+		*nocount = 0;
+
+	*high = divider / 2;
+	*edge = divider % 2;
+	*low = divider - *high;
+}
+
+static void axi_clkgen_write(struct axi_clkgen *axi_clkgen,
+	unsigned int reg, unsigned int val)
+{
+	writel(val, axi_clkgen->base + reg);
+}
+
+static void axi_clkgen_read(struct axi_clkgen *axi_clkgen,
+	unsigned int reg, unsigned int *val)
+{
+	*val = readl(axi_clkgen->base + reg);
+}
+
+static struct axi_clkgen *clk_hw_to_axi_clkgen(struct clk_hw *clk_hw)
+{
+	return container_of(clk_hw, struct axi_clkgen, clk_hw);
+}
+
+static int axi_clkgen_set_rate(struct clk_hw *clk_hw,
+	unsigned long rate, unsigned long parent_rate)
+{
+	struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(clk_hw);
+	unsigned int d, m, dout;
+	unsigned int nocount;
+	unsigned int high;
+	unsigned int edge;
+	unsigned int low;
+	uint32_t filter;
+	uint32_t lock;
+
+	if (parent_rate == 0 || rate == 0)
+		return -EINVAL;
+
+	axi_clkgen_calc_params(parent_rate, rate, &d, &m, &dout);
+
+	if (d == 0 || dout == 0 || m == 0)
+		return -EINVAL;
+
+	filter = axi_clkgen_lookup_filter(m - 1);
+	lock = axi_clkgen_lookup_lock(m - 1);
+
+	axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_UPDATE_ENABLE, 0);
+
+	axi_clkgen_calc_clk_params(dout, &low, &high, &edge, &nocount);
+	axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_CLK_OUT1,
+		(high << 6) | low);
+	axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_CLK_OUT2,
+		(edge << 7) | (nocount << 6));
+
+	axi_clkgen_calc_clk_params(d, &low, &high, &edge, &nocount);
+	axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_CLK_DIV,
+		(edge << 13) | (nocount << 12) | (high << 6) | low);
+
+	axi_clkgen_calc_clk_params(m, &low, &high, &edge, &nocount);
+	axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_CLK_FB1,
+		(high << 6) | low);
+	axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_CLK_FB2,
+		(edge << 7) | (nocount << 6));
+
+	axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_LOCK1, lock & 0x3ff);
+	axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_LOCK2,
+		(((lock >> 16) & 0x1f) << 10) | 0x1);
+	axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_LOCK3,
+		(((lock >> 24) & 0x1f) << 10) | 0x3e9);
+	axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_FILTER1, filter >> 16);
+	axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_FILTER2, filter);
+
+	axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_UPDATE_ENABLE, 1);
+
+	return 0;
+}
+
+static long axi_clkgen_round_rate(struct clk_hw *hw, unsigned long rate,
+	unsigned long *parent_rate)
+{
+	unsigned int d, m, dout;
+
+	axi_clkgen_calc_params(*parent_rate, rate, &d, &m, &dout);
+
+	if (d == 0 || dout == 0 || m == 0)
+		return -EINVAL;
+
+	return *parent_rate / d * m / dout;
+}
+
+static unsigned long axi_clkgen_recalc_rate(struct clk_hw *clk_hw,
+	unsigned long parent_rate)
+{
+	struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(clk_hw);
+	unsigned int d, m, dout;
+	unsigned int reg;
+	unsigned long long tmp;
+
+	axi_clkgen_read(axi_clkgen, AXI_CLKGEN_REG_CLK_OUT1, &reg);
+	dout = (reg & 0x3f) + ((reg >> 6) & 0x3f);
+	axi_clkgen_read(axi_clkgen, AXI_CLKGEN_REG_CLK_DIV, &reg);
+	d = (reg & 0x3f) + ((reg >> 6) & 0x3f);
+	axi_clkgen_read(axi_clkgen, AXI_CLKGEN_REG_CLK_FB1, &reg);
+	m = (reg & 0x3f) + ((reg >> 6) & 0x3f);
+
+	if (d == 0 || dout == 0)
+		return 0;
+
+	tmp = (unsigned long long)(parent_rate / d) * m;
+	do_div(tmp, dout);
+
+	if (tmp > ULONG_MAX)
+		return ULONG_MAX;
+
+	return tmp;
+}
+
+static const struct clk_ops axi_clkgen_ops = {
+	.recalc_rate = axi_clkgen_recalc_rate,
+	.round_rate = axi_clkgen_round_rate,
+	.set_rate = axi_clkgen_set_rate,
+};
+
+static int axi_clkgen_probe(struct platform_device *pdev)
+{
+	struct axi_clkgen *axi_clkgen;
+	struct clk_init_data init;
+	const char *parent_name;
+	const char *clk_name;
+	struct resource *mem;
+	struct clk *clk;
+
+	axi_clkgen = devm_kzalloc(&pdev->dev, sizeof(*axi_clkgen), GFP_KERNEL);
+	if (!axi_clkgen)
+		return -ENOMEM;
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	axi_clkgen->base = devm_ioremap_resource(&pdev->dev, mem);
+	if (IS_ERR(axi_clkgen->base))
+		return PTR_ERR(axi_clkgen->base);
+
+	parent_name = of_clk_get_parent_name(pdev->dev.of_node, 0);
+	if (!parent_name)
+		return -EINVAL;
+
+	clk_name = pdev->dev.of_node->name;
+	of_property_read_string(pdev->dev.of_node, "clock-output-names",
+		&clk_name);
+
+	init.name = clk_name;
+	init.ops = &axi_clkgen_ops;
+	init.flags = 0;
+	init.parent_names = &parent_name;
+	init.num_parents = 1;
+
+	axi_clkgen->clk_hw.init = &init;
+	clk = devm_clk_register(&pdev->dev, &axi_clkgen->clk_hw);
+	if (IS_ERR(clk))
+		return PTR_ERR(clk);
+
+	return of_clk_add_provider(pdev->dev.of_node, of_clk_src_simple_get,
+				    clk);
+}
+
+static int axi_clkgen_remove(struct platform_device *pdev)
+{
+	of_clk_del_provider(pdev->dev.of_node);
+
+	return 0;
+}
+
+static const struct of_device_id axi_clkgen_ids[] = {
+	{ .compatible = "adi,axi-clkgen-1.00.a" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, axi_clkgen_ids);
+
+static struct platform_driver axi_clkgen_driver = {
+	.driver = {
+		.name = "adi-axi-clkgen",
+		.owner = THIS_MODULE,
+		.of_match_table = axi_clkgen_ids,
+	},
+	.probe = axi_clkgen_probe,
+	.remove = axi_clkgen_remove,
+};
+module_platform_driver(axi_clkgen_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_DESCRIPTION("Driver for the Analog Devices' AXI clkgen pcore clock generator");
diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c
new file mode 100644
index 0000000..097dee4
--- /dev/null
+++ b/drivers/clk/clk-composite.c
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2013 NVIDIA 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+
+#define to_clk_composite(_hw) container_of(_hw, struct clk_composite, hw)
+
+static u8 clk_composite_get_parent(struct clk_hw *hw)
+{
+	struct clk_composite *composite = to_clk_composite(hw);
+	const struct clk_ops *mux_ops = composite->mux_ops;
+	struct clk_hw *mux_hw = composite->mux_hw;
+
+	mux_hw->clk = hw->clk;
+
+	return mux_ops->get_parent(mux_hw);
+}
+
+static int clk_composite_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct clk_composite *composite = to_clk_composite(hw);
+	const struct clk_ops *mux_ops = composite->mux_ops;
+	struct clk_hw *mux_hw = composite->mux_hw;
+
+	mux_hw->clk = hw->clk;
+
+	return mux_ops->set_parent(mux_hw, index);
+}
+
+static unsigned long clk_composite_recalc_rate(struct clk_hw *hw,
+					    unsigned long parent_rate)
+{
+	struct clk_composite *composite = to_clk_composite(hw);
+	const struct clk_ops *div_ops = composite->div_ops;
+	struct clk_hw *div_hw = composite->div_hw;
+
+	div_hw->clk = hw->clk;
+
+	return div_ops->recalc_rate(div_hw, parent_rate);
+}
+
+static long clk_composite_round_rate(struct clk_hw *hw, unsigned long rate,
+				  unsigned long *prate)
+{
+	struct clk_composite *composite = to_clk_composite(hw);
+	const struct clk_ops *div_ops = composite->div_ops;
+	struct clk_hw *div_hw = composite->div_hw;
+
+	div_hw->clk = hw->clk;
+
+	return div_ops->round_rate(div_hw, rate, prate);
+}
+
+static int clk_composite_set_rate(struct clk_hw *hw, unsigned long rate,
+			       unsigned long parent_rate)
+{
+	struct clk_composite *composite = to_clk_composite(hw);
+	const struct clk_ops *div_ops = composite->div_ops;
+	struct clk_hw *div_hw = composite->div_hw;
+
+	div_hw->clk = hw->clk;
+
+	return div_ops->set_rate(div_hw, rate, parent_rate);
+}
+
+static int clk_composite_is_enabled(struct clk_hw *hw)
+{
+	struct clk_composite *composite = to_clk_composite(hw);
+	const struct clk_ops *gate_ops = composite->gate_ops;
+	struct clk_hw *gate_hw = composite->gate_hw;
+
+	gate_hw->clk = hw->clk;
+
+	return gate_ops->is_enabled(gate_hw);
+}
+
+static int clk_composite_enable(struct clk_hw *hw)
+{
+	struct clk_composite *composite = to_clk_composite(hw);
+	const struct clk_ops *gate_ops = composite->gate_ops;
+	struct clk_hw *gate_hw = composite->gate_hw;
+
+	gate_hw->clk = hw->clk;
+
+	return gate_ops->enable(gate_hw);
+}
+
+static void clk_composite_disable(struct clk_hw *hw)
+{
+	struct clk_composite *composite = to_clk_composite(hw);
+	const struct clk_ops *gate_ops = composite->gate_ops;
+	struct clk_hw *gate_hw = composite->gate_hw;
+
+	gate_hw->clk = hw->clk;
+
+	gate_ops->disable(gate_hw);
+}
+
+struct clk *clk_register_composite(struct device *dev, const char *name,
+			const char **parent_names, int num_parents,
+			struct clk_hw *mux_hw, const struct clk_ops *mux_ops,
+			struct clk_hw *div_hw, const struct clk_ops *div_ops,
+			struct clk_hw *gate_hw, const struct clk_ops *gate_ops,
+			unsigned long flags)
+{
+	struct clk *clk;
+	struct clk_init_data init;
+	struct clk_composite *composite;
+	struct clk_ops *clk_composite_ops;
+
+	composite = kzalloc(sizeof(*composite), GFP_KERNEL);
+	if (!composite) {
+		pr_err("%s: could not allocate composite clk\n", __func__);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	init.name = name;
+	init.flags = flags | CLK_IS_BASIC;
+	init.parent_names = parent_names;
+	init.num_parents = num_parents;
+
+	clk_composite_ops = &composite->ops;
+
+	if (mux_hw && mux_ops) {
+		if (!mux_ops->get_parent || !mux_ops->set_parent) {
+			clk = ERR_PTR(-EINVAL);
+			goto err;
+		}
+
+		composite->mux_hw = mux_hw;
+		composite->mux_ops = mux_ops;
+		clk_composite_ops->get_parent = clk_composite_get_parent;
+		clk_composite_ops->set_parent = clk_composite_set_parent;
+	}
+
+	if (div_hw && div_ops) {
+		if (!div_ops->recalc_rate || !div_ops->round_rate ||
+		    !div_ops->set_rate) {
+			clk = ERR_PTR(-EINVAL);
+			goto err;
+		}
+
+		composite->div_hw = div_hw;
+		composite->div_ops = div_ops;
+		clk_composite_ops->recalc_rate = clk_composite_recalc_rate;
+		clk_composite_ops->round_rate = clk_composite_round_rate;
+		clk_composite_ops->set_rate = clk_composite_set_rate;
+	}
+
+	if (gate_hw && gate_ops) {
+		if (!gate_ops->is_enabled || !gate_ops->enable ||
+		    !gate_ops->disable) {
+			clk = ERR_PTR(-EINVAL);
+			goto err;
+		}
+
+		composite->gate_hw = gate_hw;
+		composite->gate_ops = gate_ops;
+		clk_composite_ops->is_enabled = clk_composite_is_enabled;
+		clk_composite_ops->enable = clk_composite_enable;
+		clk_composite_ops->disable = clk_composite_disable;
+	}
+
+	init.ops = clk_composite_ops;
+	composite->hw.init = &init;
+
+	clk = clk_register(dev, &composite->hw);
+	if (IS_ERR(clk))
+		goto err;
+
+	if (composite->mux_hw)
+		composite->mux_hw->clk = clk;
+
+	if (composite->div_hw)
+		composite->div_hw->clk = clk;
+
+	if (composite->gate_hw)
+		composite->gate_hw->clk = clk;
+
+	return clk;
+
+err:
+	kfree(composite);
+	return clk;
+}
diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
index 68b4021..6d96741 100644
--- a/drivers/clk/clk-divider.c
+++ b/drivers/clk/clk-divider.c
@@ -109,8 +109,9 @@ static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
 
 	div = _get_div(divider, val);
 	if (!div) {
-		WARN(1, "%s: Invalid divisor for clock %s\n", __func__,
-						__clk_get_name(hw->clk));
+		WARN(!(divider->flags & CLK_DIVIDER_ALLOW_ZERO),
+			"%s: Zero divisor and CLK_DIVIDER_ALLOW_ZERO not set\n",
+			__clk_get_name(hw->clk));
 		return parent_rate;
 	}
 
diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
index 508c032..25b1734 100644
--- a/drivers/clk/clk-mux.c
+++ b/drivers/clk/clk-mux.c
@@ -32,6 +32,7 @@
 static u8 clk_mux_get_parent(struct clk_hw *hw)
 {
 	struct clk_mux *mux = to_clk_mux(hw);
+	int num_parents = __clk_get_num_parents(hw->clk);
 	u32 val;
 
 	/*
@@ -42,7 +43,16 @@ static u8 clk_mux_get_parent(struct clk_hw *hw)
 	 * val = 0x4 really means "bit 2, index starts at bit 0"
 	 */
 	val = readl(mux->reg) >> mux->shift;
-	val &= (1 << mux->width) - 1;
+	val &= mux->mask;
+
+	if (mux->table) {
+		int i;
+
+		for (i = 0; i < num_parents; i++)
+			if (mux->table[i] == val)
+				return i;
+		return -EINVAL;
+	}
 
 	if (val && (mux->flags & CLK_MUX_INDEX_BIT))
 		val = ffs(val) - 1;
@@ -50,7 +60,7 @@ static u8 clk_mux_get_parent(struct clk_hw *hw)
 	if (val && (mux->flags & CLK_MUX_INDEX_ONE))
 		val--;
 
-	if (val >= __clk_get_num_parents(hw->clk))
+	if (val >= num_parents)
 		return -EINVAL;
 
 	return val;
@@ -62,17 +72,22 @@ static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
 	u32 val;
 	unsigned long flags = 0;
 
-	if (mux->flags & CLK_MUX_INDEX_BIT)
-		index = (1 << ffs(index));
+	if (mux->table)
+		index = mux->table[index];
 
-	if (mux->flags & CLK_MUX_INDEX_ONE)
-		index++;
+	else {
+		if (mux->flags & CLK_MUX_INDEX_BIT)
+			index = (1 << ffs(index));
+
+		if (mux->flags & CLK_MUX_INDEX_ONE)
+			index++;
+	}
 
 	if (mux->lock)
 		spin_lock_irqsave(mux->lock, flags);
 
 	val = readl(mux->reg);
-	val &= ~(((1 << mux->width) - 1) << mux->shift);
+	val &= ~(mux->mask << mux->shift);
 	val |= index << mux->shift;
 	writel(val, mux->reg);
 
@@ -88,10 +103,10 @@ const struct clk_ops clk_mux_ops = {
 };
 EXPORT_SYMBOL_GPL(clk_mux_ops);
 
-struct clk *clk_register_mux(struct device *dev, const char *name,
+struct clk *clk_register_mux_table(struct device *dev, const char *name,
 		const char **parent_names, u8 num_parents, unsigned long flags,
-		void __iomem *reg, u8 shift, u8 width,
-		u8 clk_mux_flags, spinlock_t *lock)
+		void __iomem *reg, u8 shift, u32 mask,
+		u8 clk_mux_flags, u32 *table, spinlock_t *lock)
 {
 	struct clk_mux *mux;
 	struct clk *clk;
@@ -113,9 +128,10 @@ struct clk *clk_register_mux(struct device *dev, const char *name,
 	/* struct clk_mux assignments */
 	mux->reg = reg;
 	mux->shift = shift;
-	mux->width = width;
+	mux->mask = mask;
 	mux->flags = clk_mux_flags;
 	mux->lock = lock;
+	mux->table = table;
 	mux->hw.init = &init;
 
 	clk = clk_register(dev, &mux->hw);
@@ -125,3 +141,15 @@ struct clk *clk_register_mux(struct device *dev, const char *name,
 
 	return clk;
 }
+
+struct clk *clk_register_mux(struct device *dev, const char *name,
+		const char **parent_names, u8 num_parents, unsigned long flags,
+		void __iomem *reg, u8 shift, u8 width,
+		u8 clk_mux_flags, spinlock_t *lock)
+{
+	u32 mask = BIT(width) - 1;
+
+	return clk_register_mux_table(dev, name, parent_names, num_parents,
+				      flags, reg, shift, mask, clk_mux_flags,
+				      NULL, lock);
+}
diff --git a/drivers/clk/clk-prima2.c b/drivers/clk/clk-prima2.c
index f8e9d0c..643ca65 100644
--- a/drivers/clk/clk-prima2.c
+++ b/drivers/clk/clk-prima2.c
@@ -1113,7 +1113,7 @@ void __init sirfsoc_of_clk_init(void)
 
 	for (i = pll1; i < maxclk; i++) {
 		prima2_clks[i] = clk_register(NULL, prima2_clk_hw_array[i]);
-		BUG_ON(!prima2_clks[i]);
+		BUG_ON(IS_ERR(prima2_clks[i]));
 	}
 	clk_register_clkdev(prima2_clks[cpu], NULL, "cpu");
 	clk_register_clkdev(prima2_clks[io],  NULL, "io");
diff --git a/drivers/clk/clk-zynq.c b/drivers/clk/clk-zynq.c
index b14a25f..3206297 100644
--- a/drivers/clk/clk-zynq.c
+++ b/drivers/clk/clk-zynq.c
@@ -20,6 +20,7 @@
 #include <linux/slab.h>
 #include <linux/kernel.h>
 #include <linux/clk-provider.h>
+#include <linux/clk/zynq.h>
 
 static void __iomem *slcr_base;
 
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index ed87b24..0230c9d 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -19,14 +19,77 @@
 #include <linux/of.h>
 #include <linux/device.h>
 #include <linux/init.h>
+#include <linux/sched.h>
 
 static DEFINE_SPINLOCK(enable_lock);
 static DEFINE_MUTEX(prepare_lock);
 
+static struct task_struct *prepare_owner;
+static struct task_struct *enable_owner;
+
+static int prepare_refcnt;
+static int enable_refcnt;
+
 static HLIST_HEAD(clk_root_list);
 static HLIST_HEAD(clk_orphan_list);
 static LIST_HEAD(clk_notifier_list);
 
+/***           locking             ***/
+static void clk_prepare_lock(void)
+{
+	if (!mutex_trylock(&prepare_lock)) {
+		if (prepare_owner == current) {
+			prepare_refcnt++;
+			return;
+		}
+		mutex_lock(&prepare_lock);
+	}
+	WARN_ON_ONCE(prepare_owner != NULL);
+	WARN_ON_ONCE(prepare_refcnt != 0);
+	prepare_owner = current;
+	prepare_refcnt = 1;
+}
+
+static void clk_prepare_unlock(void)
+{
+	WARN_ON_ONCE(prepare_owner != current);
+	WARN_ON_ONCE(prepare_refcnt == 0);
+
+	if (--prepare_refcnt)
+		return;
+	prepare_owner = NULL;
+	mutex_unlock(&prepare_lock);
+}
+
+static unsigned long clk_enable_lock(void)
+{
+	unsigned long flags;
+
+	if (!spin_trylock_irqsave(&enable_lock, flags)) {
+		if (enable_owner == current) {
+			enable_refcnt++;
+			return flags;
+		}
+		spin_lock_irqsave(&enable_lock, flags);
+	}
+	WARN_ON_ONCE(enable_owner != NULL);
+	WARN_ON_ONCE(enable_refcnt != 0);
+	enable_owner = current;
+	enable_refcnt = 1;
+	return flags;
+}
+
+static void clk_enable_unlock(unsigned long flags)
+{
+	WARN_ON_ONCE(enable_owner != current);
+	WARN_ON_ONCE(enable_refcnt == 0);
+
+	if (--enable_refcnt)
+		return;
+	enable_owner = NULL;
+	spin_unlock_irqrestore(&enable_lock, flags);
+}
+
 /***        debugfs support        ***/
 
 #ifdef CONFIG_COMMON_CLK_DEBUG
@@ -69,7 +132,7 @@ static int clk_summary_show(struct seq_file *s, void *data)
 	seq_printf(s, "   clock                        enable_cnt  prepare_cnt  rate\n");
 	seq_printf(s, "---------------------------------------------------------------------\n");
 
-	mutex_lock(&prepare_lock);
+	clk_prepare_lock();
 
 	hlist_for_each_entry(c, &clk_root_list, child_node)
 		clk_summary_show_subtree(s, c, 0);
@@ -77,7 +140,7 @@ static int clk_summary_show(struct seq_file *s, void *data)
 	hlist_for_each_entry(c, &clk_orphan_list, child_node)
 		clk_summary_show_subtree(s, c, 0);
 
-	mutex_unlock(&prepare_lock);
+	clk_prepare_unlock();
 
 	return 0;
 }
@@ -130,7 +193,7 @@ static int clk_dump(struct seq_file *s, void *data)
 
 	seq_printf(s, "{");
 
-	mutex_lock(&prepare_lock);
+	clk_prepare_lock();
 
 	hlist_for_each_entry(c, &clk_root_list, child_node) {
 		if (!first_node)
@@ -144,7 +207,7 @@ static int clk_dump(struct seq_file *s, void *data)
 		clk_dump_subtree(s, c, 0);
 	}
 
-	mutex_unlock(&prepare_lock);
+	clk_prepare_unlock();
 
 	seq_printf(s, "}");
 	return 0;
@@ -316,7 +379,7 @@ static int __init clk_debug_init(void)
 	if (!orphandir)
 		return -ENOMEM;
 
-	mutex_lock(&prepare_lock);
+	clk_prepare_lock();
 
 	hlist_for_each_entry(clk, &clk_root_list, child_node)
 		clk_debug_create_subtree(clk, rootdir);
@@ -326,7 +389,7 @@ static int __init clk_debug_init(void)
 
 	inited = 1;
 
-	mutex_unlock(&prepare_lock);
+	clk_prepare_unlock();
 
 	return 0;
 }
@@ -336,6 +399,31 @@ static inline int clk_debug_register(struct clk *clk) { return 0; }
 #endif
 
 /* caller must hold prepare_lock */
+static void clk_unprepare_unused_subtree(struct clk *clk)
+{
+	struct clk *child;
+
+	if (!clk)
+		return;
+
+	hlist_for_each_entry(child, &clk->children, child_node)
+		clk_unprepare_unused_subtree(child);
+
+	if (clk->prepare_count)
+		return;
+
+	if (clk->flags & CLK_IGNORE_UNUSED)
+		return;
+
+	if (__clk_is_prepared(clk)) {
+		if (clk->ops->unprepare_unused)
+			clk->ops->unprepare_unused(clk->hw);
+		else if (clk->ops->unprepare)
+			clk->ops->unprepare(clk->hw);
+	}
+}
+
+/* caller must hold prepare_lock */
 static void clk_disable_unused_subtree(struct clk *clk)
 {
 	struct clk *child;
@@ -347,7 +435,7 @@ static void clk_disable_unused_subtree(struct clk *clk)
 	hlist_for_each_entry(child, &clk->children, child_node)
 		clk_disable_unused_subtree(child);
 
-	spin_lock_irqsave(&enable_lock, flags);
+	flags = clk_enable_lock();
 
 	if (clk->enable_count)
 		goto unlock_out;
@@ -368,7 +456,7 @@ static void clk_disable_unused_subtree(struct clk *clk)
 	}
 
 unlock_out:
-	spin_unlock_irqrestore(&enable_lock, flags);
+	clk_enable_unlock(flags);
 
 out:
 	return;
@@ -378,7 +466,7 @@ static int clk_disable_unused(void)
 {
 	struct clk *clk;
 
-	mutex_lock(&prepare_lock);
+	clk_prepare_lock();
 
 	hlist_for_each_entry(clk, &clk_root_list, child_node)
 		clk_disable_unused_subtree(clk);
@@ -386,7 +474,13 @@ static int clk_disable_unused(void)
 	hlist_for_each_entry(clk, &clk_orphan_list, child_node)
 		clk_disable_unused_subtree(clk);
 
-	mutex_unlock(&prepare_lock);
+	hlist_for_each_entry(clk, &clk_root_list, child_node)
+		clk_unprepare_unused_subtree(clk);
+
+	hlist_for_each_entry(clk, &clk_orphan_list, child_node)
+		clk_unprepare_unused_subtree(clk);
+
+	clk_prepare_unlock();
 
 	return 0;
 }
@@ -451,6 +545,27 @@ unsigned long __clk_get_flags(struct clk *clk)
 	return !clk ? 0 : clk->flags;
 }
 
+bool __clk_is_prepared(struct clk *clk)
+{
+	int ret;
+
+	if (!clk)
+		return false;
+
+	/*
+	 * .is_prepared is optional for clocks that can prepare
+	 * fall back to software usage counter if it is missing
+	 */
+	if (!clk->ops->is_prepared) {
+		ret = clk->prepare_count ? 1 : 0;
+		goto out;
+	}
+
+	ret = clk->ops->is_prepared(clk->hw);
+out:
+	return !!ret;
+}
+
 bool __clk_is_enabled(struct clk *clk)
 {
 	int ret;
@@ -548,9 +663,9 @@ void __clk_unprepare(struct clk *clk)
  */
 void clk_unprepare(struct clk *clk)
 {
-	mutex_lock(&prepare_lock);
+	clk_prepare_lock();
 	__clk_unprepare(clk);
-	mutex_unlock(&prepare_lock);
+	clk_prepare_unlock();
 }
 EXPORT_SYMBOL_GPL(clk_unprepare);
 
@@ -596,9 +711,9 @@ int clk_prepare(struct clk *clk)
 {
 	int ret;
 
-	mutex_lock(&prepare_lock);
+	clk_prepare_lock();
 	ret = __clk_prepare(clk);
-	mutex_unlock(&prepare_lock);
+	clk_prepare_unlock();
 
 	return ret;
 }
@@ -640,9 +755,9 @@ void clk_disable(struct clk *clk)
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&enable_lock, flags);
+	flags = clk_enable_lock();
 	__clk_disable(clk);
-	spin_unlock_irqrestore(&enable_lock, flags);
+	clk_enable_unlock(flags);
 }
 EXPORT_SYMBOL_GPL(clk_disable);
 
@@ -693,9 +808,9 @@ int clk_enable(struct clk *clk)
 	unsigned long flags;
 	int ret;
 
-	spin_lock_irqsave(&enable_lock, flags);
+	flags = clk_enable_lock();
 	ret = __clk_enable(clk);
-	spin_unlock_irqrestore(&enable_lock, flags);
+	clk_enable_unlock(flags);
 
 	return ret;
 }
@@ -740,9 +855,9 @@ long clk_round_rate(struct clk *clk, unsigned long rate)
 {
 	unsigned long ret;
 
-	mutex_lock(&prepare_lock);
+	clk_prepare_lock();
 	ret = __clk_round_rate(clk, rate);
-	mutex_unlock(&prepare_lock);
+	clk_prepare_unlock();
 
 	return ret;
 }
@@ -837,13 +952,13 @@ unsigned long clk_get_rate(struct clk *clk)
 {
 	unsigned long rate;
 
-	mutex_lock(&prepare_lock);
+	clk_prepare_lock();
 
 	if (clk && (clk->flags & CLK_GET_RATE_NOCACHE))
 		__clk_recalc_rates(clk, 0);
 
 	rate = __clk_get_rate(clk);
-	mutex_unlock(&prepare_lock);
+	clk_prepare_unlock();
 
 	return rate;
 }
@@ -974,7 +1089,7 @@ static struct clk *clk_propagate_rate_change(struct clk *clk, unsigned long even
 	int ret = NOTIFY_DONE;
 
 	if (clk->rate == clk->new_rate)
-		return 0;
+		return NULL;
 
 	if (clk->notifier_count) {
 		ret = __clk_notify(clk, event, clk->rate, clk->new_rate);
@@ -1048,7 +1163,7 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
 	int ret = 0;
 
 	/* prevent racing with updates to the clock topology */
-	mutex_lock(&prepare_lock);
+	clk_prepare_lock();
 
 	/* bail early if nothing to do */
 	if (rate == clk->rate)
@@ -1080,7 +1195,7 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
 	clk_change_rate(top);
 
 out:
-	mutex_unlock(&prepare_lock);
+	clk_prepare_unlock();
 
 	return ret;
 }
@@ -1096,9 +1211,9 @@ struct clk *clk_get_parent(struct clk *clk)
 {
 	struct clk *parent;
 
-	mutex_lock(&prepare_lock);
+	clk_prepare_lock();
 	parent = __clk_get_parent(clk);
-	mutex_unlock(&prepare_lock);
+	clk_prepare_unlock();
 
 	return parent;
 }
@@ -1242,19 +1357,19 @@ static int __clk_set_parent(struct clk *clk, struct clk *parent)
 		__clk_prepare(parent);
 
 	/* FIXME replace with clk_is_enabled(clk) someday */
-	spin_lock_irqsave(&enable_lock, flags);
+	flags = clk_enable_lock();
 	if (clk->enable_count)
 		__clk_enable(parent);
-	spin_unlock_irqrestore(&enable_lock, flags);
+	clk_enable_unlock(flags);
 
 	/* change clock input source */
 	ret = clk->ops->set_parent(clk->hw, i);
 
 	/* clean up old prepare and enable */
-	spin_lock_irqsave(&enable_lock, flags);
+	flags = clk_enable_lock();
 	if (clk->enable_count)
 		__clk_disable(old_parent);
-	spin_unlock_irqrestore(&enable_lock, flags);
+	clk_enable_unlock(flags);
 
 	if (clk->prepare_count)
 		__clk_unprepare(old_parent);
@@ -1286,7 +1401,7 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
 		return -ENOSYS;
 
 	/* prevent racing with updates to the clock topology */
-	mutex_lock(&prepare_lock);
+	clk_prepare_lock();
 
 	if (clk->parent == parent)
 		goto out;
@@ -1315,7 +1430,7 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
 	__clk_reparent(clk, parent);
 
 out:
-	mutex_unlock(&prepare_lock);
+	clk_prepare_unlock();
 
 	return ret;
 }
@@ -1338,7 +1453,7 @@ int __clk_init(struct device *dev, struct clk *clk)
 	if (!clk)
 		return -EINVAL;
 
-	mutex_lock(&prepare_lock);
+	clk_prepare_lock();
 
 	/* check to see if a clock with this name is already registered */
 	if (__clk_lookup(clk->name)) {
@@ -1462,7 +1577,7 @@ int __clk_init(struct device *dev, struct clk *clk)
 	clk_debug_register(clk);
 
 out:
-	mutex_unlock(&prepare_lock);
+	clk_prepare_unlock();
 
 	return ret;
 }
@@ -1696,7 +1811,7 @@ int clk_notifier_register(struct clk *clk, struct notifier_block *nb)
 	if (!clk || !nb)
 		return -EINVAL;
 
-	mutex_lock(&prepare_lock);
+	clk_prepare_lock();
 
 	/* search the list of notifiers for this clk */
 	list_for_each_entry(cn, &clk_notifier_list, node)
@@ -1720,7 +1835,7 @@ int clk_notifier_register(struct clk *clk, struct notifier_block *nb)
 	clk->notifier_count++;
 
 out:
-	mutex_unlock(&prepare_lock);
+	clk_prepare_unlock();
 
 	return ret;
 }
@@ -1745,7 +1860,7 @@ int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb)
 	if (!clk || !nb)
 		return -EINVAL;
 
-	mutex_lock(&prepare_lock);
+	clk_prepare_lock();
 
 	list_for_each_entry(cn, &clk_notifier_list, node)
 		if (cn->clk == clk)
@@ -1766,7 +1881,7 @@ int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb)
 		ret = -ENOENT;
 	}
 
-	mutex_unlock(&prepare_lock);
+	clk_prepare_unlock();
 
 	return ret;
 }
diff --git a/drivers/clk/mvebu/clk-core.c b/drivers/clk/mvebu/clk-core.c
index 69056a7..1b4e333 100644
--- a/drivers/clk/mvebu/clk-core.c
+++ b/drivers/clk/mvebu/clk-core.c
@@ -157,7 +157,7 @@ static u32 __init armada_370_get_cpu_freq(void __iomem *sar)
 	cpu_freq_select = ((readl(sar) >> SARL_A370_PCLK_FREQ_OPT) &
 			   SARL_A370_PCLK_FREQ_OPT_MASK);
 	if (cpu_freq_select > ARRAY_SIZE(armada_370_cpu_frequencies)) {
-		pr_err("CPU freq select unsuported %d\n", cpu_freq_select);
+		pr_err("CPU freq select unsupported %d\n", cpu_freq_select);
 		cpu_freq = 0;
 	} else
 		cpu_freq = armada_370_cpu_frequencies[cpu_freq_select];
@@ -279,7 +279,7 @@ static u32 __init armada_xp_get_cpu_freq(void __iomem *sar)
 			     SARH_AXP_PCLK_FREQ_OPT_MASK)
 			    << SARH_AXP_PCLK_FREQ_OPT_SHIFT);
 	if (cpu_freq_select > ARRAY_SIZE(armada_xp_cpu_frequencies)) {
-		pr_err("CPU freq select unsuported: %d\n", cpu_freq_select);
+		pr_err("CPU freq select unsupported: %d\n", cpu_freq_select);
 		cpu_freq = 0;
 	} else
 		cpu_freq = armada_xp_cpu_frequencies[cpu_freq_select];
diff --git a/drivers/clk/mvebu/clk-cpu.c b/drivers/clk/mvebu/clk-cpu.c
index 9dd2551..b0fbc07 100644
--- a/drivers/clk/mvebu/clk-cpu.c
+++ b/drivers/clk/mvebu/clk-cpu.c
@@ -16,7 +16,6 @@
 #include <linux/io.h>
 #include <linux/of.h>
 #include <linux/delay.h>
-#include "clk-cpu.h"
 
 #define SYS_CTRL_CLK_DIVIDER_CTRL_OFFSET    0x0
 #define SYS_CTRL_CLK_DIVIDER_VALUE_OFFSET   0xC
@@ -173,17 +172,5 @@ clks_out:
 	kfree(cpuclk);
 }
 
-static const __initconst struct of_device_id clk_cpu_match[] = {
-	{
-		.compatible = "marvell,armada-xp-cpu-clock",
-		.data = of_cpu_clk_setup,
-	},
-	{
-		/* sentinel */
-	},
-};
-
-void __init mvebu_cpu_clk_init(void)
-{
-	of_clk_init(clk_cpu_match);
-}
+CLK_OF_DECLARE(armada_xp_cpu_clock, "marvell,armada-xp-cpu-clock",
+					 of_cpu_clk_setup);
diff --git a/drivers/clk/mvebu/clk-cpu.h b/drivers/clk/mvebu/clk-cpu.h
deleted file mode 100644
index 08e2aff..0000000
--- a/drivers/clk/mvebu/clk-cpu.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Marvell MVEBU CPU clock handling.
- *
- * Copyright (C) 2012 Marvell
- *
- * Gregory CLEMENT <gregory.clement@free-electrons.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 __MVEBU_CLK_CPU_H
-#define __MVEBU_CLK_CPU_H
-
-#ifdef CONFIG_MVEBU_CLK_CPU
-void __init mvebu_cpu_clk_init(void);
-#else
-static inline void mvebu_cpu_clk_init(void) {}
-#endif
-
-#endif
diff --git a/drivers/clk/mvebu/clk.c b/drivers/clk/mvebu/clk.c
index 855681b..29f10fb 100644
--- a/drivers/clk/mvebu/clk.c
+++ b/drivers/clk/mvebu/clk.c
@@ -10,18 +10,14 @@
  * warranty of any kind, whether express or implied.
  */
 #include <linux/kernel.h>
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
-#include <linux/of_address.h>
-#include <linux/clk/mvebu.h>
 #include <linux/of.h>
 #include "clk-core.h"
-#include "clk-cpu.h"
 #include "clk-gating-ctrl.h"
 
 void __init mvebu_clocks_init(void)
 {
 	mvebu_core_clk_init();
 	mvebu_gating_clk_init();
-	mvebu_cpu_clk_init();
+	of_clk_init(NULL);
 }
diff --git a/drivers/clk/mxs/clk-imx23.c b/drivers/clk/mxs/clk-imx23.c
index b5c06f9..f6a7487 100644
--- a/drivers/clk/mxs/clk-imx23.c
+++ b/drivers/clk/mxs/clk-imx23.c
@@ -15,12 +15,15 @@
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/of.h>
-#include <mach/common.h>
-#include <mach/mx23.h>
+#include <linux/of_address.h>
 #include "clk.h"
 
-#define DIGCTRL			MX23_IO_ADDRESS(MX23_DIGCTL_BASE_ADDR)
-#define CLKCTRL			MX23_IO_ADDRESS(MX23_CLKCTRL_BASE_ADDR)
+static void __iomem *clkctrl;
+static void __iomem *digctrl;
+
+#define CLKCTRL clkctrl
+#define DIGCTRL digctrl
+
 #define PLLCTRL0		(CLKCTRL + 0x0000)
 #define CPU			(CLKCTRL + 0x0020)
 #define HBUS			(CLKCTRL + 0x0030)
@@ -48,10 +51,10 @@ static void __init clk_misc_init(void)
 	u32 val;
 
 	/* Gate off cpu clock in WFI for power saving */
-	__mxs_setl(1 << BP_CPU_INTERRUPT_WAIT, CPU);
+	writel_relaxed(1 << BP_CPU_INTERRUPT_WAIT, CPU + SET);
 
 	/* Clear BYPASS for SAIF */
-	__mxs_clrl(1 << BP_CLKSEQ_BYPASS_SAIF, CLKSEQ);
+	writel_relaxed(1 << BP_CLKSEQ_BYPASS_SAIF, CLKSEQ + CLR);
 
 	/* SAIF has to use frac div for functional operation */
 	val = readl_relaxed(SAIF);
@@ -62,14 +65,14 @@ static void __init clk_misc_init(void)
 	 * Source ssp clock from ref_io than ref_xtal,
 	 * as ref_xtal only provides 24 MHz as maximum.
 	 */
-	__mxs_clrl(1 << BP_CLKSEQ_BYPASS_SSP, CLKSEQ);
+	writel_relaxed(1 << BP_CLKSEQ_BYPASS_SSP, CLKSEQ + CLR);
 
 	/*
 	 * 480 MHz seems too high to be ssp clock source directly,
 	 * so set frac to get a 288 MHz ref_io.
 	 */
-	__mxs_clrl(0x3f << BP_FRAC_IOFRAC, FRAC);
-	__mxs_setl(30 << BP_FRAC_IOFRAC, FRAC);
+	writel_relaxed(0x3f << BP_FRAC_IOFRAC, FRAC + CLR);
+	writel_relaxed(30 << BP_FRAC_IOFRAC, FRAC + SET);
 }
 
 static const char *sel_pll[]  __initconst = { "pll", "ref_xtal", };
@@ -101,6 +104,14 @@ int __init mx23_clocks_init(void)
 	struct device_node *np;
 	u32 i;
 
+	np = of_find_compatible_node(NULL, NULL, "fsl,imx23-digctl");
+	digctrl = of_iomap(np, 0);
+	WARN_ON(!digctrl);
+
+	np = of_find_compatible_node(NULL, NULL, "fsl,imx23-clkctrl");
+	clkctrl = of_iomap(np, 0);
+	WARN_ON(!clkctrl);
+
 	clk_misc_init();
 
 	clks[ref_xtal] = mxs_clk_fixed("ref_xtal", 24000000);
@@ -153,19 +164,12 @@ int __init mx23_clocks_init(void)
 			return PTR_ERR(clks[i]);
 		}
 
-	np = of_find_compatible_node(NULL, NULL, "fsl,imx23-clkctrl");
-	if (np) {
-		clk_data.clks = clks;
-		clk_data.clk_num = ARRAY_SIZE(clks);
-		of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
-	}
-
-	clk_register_clkdev(clks[clk32k], NULL, "timrot");
+	clk_data.clks = clks;
+	clk_data.clk_num = ARRAY_SIZE(clks);
+	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
 
 	for (i = 0; i < ARRAY_SIZE(clks_init_on); i++)
 		clk_prepare_enable(clks[clks_init_on[i]]);
 
-	mxs_timer_init();
-
 	return 0;
 }
diff --git a/drivers/clk/mxs/clk-imx28.c b/drivers/clk/mxs/clk-imx28.c
index 76ce6c6..d0e5eed 100644
--- a/drivers/clk/mxs/clk-imx28.c
+++ b/drivers/clk/mxs/clk-imx28.c
@@ -15,11 +15,12 @@
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/of.h>
-#include <mach/common.h>
-#include <mach/mx28.h>
+#include <linux/of_address.h>
 #include "clk.h"
 
-#define CLKCTRL			MX28_IO_ADDRESS(MX28_CLKCTRL_BASE_ADDR)
+static void __iomem *clkctrl;
+#define CLKCTRL clkctrl
+
 #define PLL0CTRL0		(CLKCTRL + 0x0000)
 #define PLL1CTRL0		(CLKCTRL + 0x0020)
 #define PLL2CTRL0		(CLKCTRL + 0x0040)
@@ -53,7 +54,8 @@
 #define BP_FRAC0_IO1FRAC	16
 #define BP_FRAC0_IO0FRAC	24
 
-#define DIGCTRL			MX28_IO_ADDRESS(MX28_DIGCTL_BASE_ADDR)
+static void __iomem *digctrl;
+#define DIGCTRL digctrl
 #define BP_SAIF_CLKMUX		10
 
 /*
@@ -72,8 +74,8 @@ int mxs_saif_clkmux_select(unsigned int clkmux)
 	if (clkmux > 0x3)
 		return -EINVAL;
 
-	__mxs_clrl(0x3 << BP_SAIF_CLKMUX, DIGCTRL);
-	__mxs_setl(clkmux << BP_SAIF_CLKMUX, DIGCTRL);
+	writel_relaxed(0x3 << BP_SAIF_CLKMUX, DIGCTRL + CLR);
+	writel_relaxed(clkmux << BP_SAIF_CLKMUX, DIGCTRL + SET);
 
 	return 0;
 }
@@ -83,13 +85,13 @@ static void __init clk_misc_init(void)
 	u32 val;
 
 	/* Gate off cpu clock in WFI for power saving */
-	__mxs_setl(1 << BP_CPU_INTERRUPT_WAIT, CPU);
+	writel_relaxed(1 << BP_CPU_INTERRUPT_WAIT, CPU + SET);
 
 	/* 0 is a bad default value for a divider */
-	__mxs_setl(1 << BP_ENET_DIV_TIME, ENET);
+	writel_relaxed(1 << BP_ENET_DIV_TIME, ENET + SET);
 
 	/* Clear BYPASS for SAIF */
-	__mxs_clrl(0x3 << BP_CLKSEQ_BYPASS_SAIF0, CLKSEQ);
+	writel_relaxed(0x3 << BP_CLKSEQ_BYPASS_SAIF0, CLKSEQ + CLR);
 
 	/* SAIF has to use frac div for functional operation */
 	val = readl_relaxed(SAIF0);
@@ -109,7 +111,7 @@ static void __init clk_misc_init(void)
 	 * Source ssp clock from ref_io than ref_xtal,
 	 * as ref_xtal only provides 24 MHz as maximum.
 	 */
-	__mxs_clrl(0xf << BP_CLKSEQ_BYPASS_SSP0, CLKSEQ);
+	writel_relaxed(0xf << BP_CLKSEQ_BYPASS_SSP0, CLKSEQ + CLR);
 
 	/*
 	 * 480 MHz seems too high to be ssp clock source directly,
@@ -156,6 +158,14 @@ int __init mx28_clocks_init(void)
 	struct device_node *np;
 	u32 i;
 
+	np = of_find_compatible_node(NULL, NULL, "fsl,imx28-digctl");
+	digctrl = of_iomap(np, 0);
+	WARN_ON(!digctrl);
+
+	np = of_find_compatible_node(NULL, NULL, "fsl,imx28-clkctrl");
+	clkctrl = of_iomap(np, 0);
+	WARN_ON(!clkctrl);
+
 	clk_misc_init();
 
 	clks[ref_xtal] = mxs_clk_fixed("ref_xtal", 24000000);
@@ -231,20 +241,14 @@ int __init mx28_clocks_init(void)
 			return PTR_ERR(clks[i]);
 		}
 
-	np = of_find_compatible_node(NULL, NULL, "fsl,imx28-clkctrl");
-	if (np) {
-		clk_data.clks = clks;
-		clk_data.clk_num = ARRAY_SIZE(clks);
-		of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
-	}
+	clk_data.clks = clks;
+	clk_data.clk_num = ARRAY_SIZE(clks);
+	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
 
-	clk_register_clkdev(clks[xbus], NULL, "timrot");
 	clk_register_clkdev(clks[enet_out], NULL, "enet_out");
 
 	for (i = 0; i < ARRAY_SIZE(clks_init_on); i++)
 		clk_prepare_enable(clks[clks_init_on[i]]);
 
-	mxs_timer_init();
-
 	return 0;
 }
diff --git a/drivers/clk/mxs/clk.c b/drivers/clk/mxs/clk.c
index b24d560..5301bce 100644
--- a/drivers/clk/mxs/clk.c
+++ b/drivers/clk/mxs/clk.c
@@ -13,6 +13,7 @@
 #include <linux/io.h>
 #include <linux/jiffies.h>
 #include <linux/spinlock.h>
+#include "clk.h"
 
 DEFINE_SPINLOCK(mxs_lock);
 
diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile
new file mode 100644
index 0000000..b7c232e
--- /dev/null
+++ b/drivers/clk/samsung/Makefile
@@ -0,0 +1,8 @@
+#
+# Samsung Clock specific Makefile
+#
+
+obj-$(CONFIG_COMMON_CLK)	+= clk.o clk-pll.o
+obj-$(CONFIG_ARCH_EXYNOS4)	+= clk-exynos4.o
+obj-$(CONFIG_SOC_EXYNOS5250)	+= clk-exynos5250.o
+obj-$(CONFIG_SOC_EXYNOS5440)	+= clk-exynos5440.o
diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c
new file mode 100644
index 0000000..17674da
--- /dev/null
+++ b/drivers/clk/samsung/clk-exynos4.c
@@ -0,0 +1,1085 @@
+/*
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2013 Linaro Ltd.
+ * Author: Thomas Abraham <thomas.ab@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.
+ *
+ * Common Clock Framework support for all Exynos4 SoCs.
+*/
+
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include <plat/cpu.h>
+#include "clk.h"
+#include "clk-pll.h"
+
+/* Exynos4 clock controller register offsets */
+#define SRC_LEFTBUS		0x4200
+#define DIV_LEFTBUS		0x4500
+#define GATE_IP_LEFTBUS		0x4800
+#define E4X12_GATE_IP_IMAGE	0x4930
+#define SRC_RIGHTBUS		0x8200
+#define DIV_RIGHTBUS		0x8500
+#define GATE_IP_RIGHTBUS	0x8800
+#define E4X12_GATE_IP_PERIR	0x8960
+#define EPLL_LOCK		0xc010
+#define VPLL_LOCK		0xc020
+#define EPLL_CON0		0xc110
+#define EPLL_CON1		0xc114
+#define EPLL_CON2		0xc118
+#define VPLL_CON0		0xc120
+#define VPLL_CON1		0xc124
+#define VPLL_CON2		0xc128
+#define SRC_TOP0		0xc210
+#define SRC_TOP1		0xc214
+#define SRC_CAM			0xc220
+#define SRC_TV			0xc224
+#define SRC_MFC			0xcc28
+#define SRC_G3D			0xc22c
+#define E4210_SRC_IMAGE		0xc230
+#define SRC_LCD0		0xc234
+#define E4210_SRC_LCD1		0xc238
+#define E4X12_SRC_ISP		0xc238
+#define SRC_MAUDIO		0xc23c
+#define SRC_FSYS		0xc240
+#define SRC_PERIL0		0xc250
+#define SRC_PERIL1		0xc254
+#define E4X12_SRC_CAM1		0xc258
+#define SRC_MASK_TOP		0xc310
+#define SRC_MASK_CAM		0xc320
+#define SRC_MASK_TV		0xc324
+#define SRC_MASK_LCD0		0xc334
+#define E4210_SRC_MASK_LCD1	0xc338
+#define E4X12_SRC_MASK_ISP	0xc338
+#define SRC_MASK_MAUDIO		0xc33c
+#define SRC_MASK_FSYS		0xc340
+#define SRC_MASK_PERIL0		0xc350
+#define SRC_MASK_PERIL1		0xc354
+#define DIV_TOP			0xc510
+#define DIV_CAM			0xc520
+#define DIV_TV			0xc524
+#define DIV_MFC			0xc528
+#define DIV_G3D			0xc52c
+#define DIV_IMAGE		0xc530
+#define DIV_LCD0		0xc534
+#define E4210_DIV_LCD1		0xc538
+#define E4X12_DIV_ISP		0xc538
+#define DIV_MAUDIO		0xc53c
+#define DIV_FSYS0		0xc540
+#define DIV_FSYS1		0xc544
+#define DIV_FSYS2		0xc548
+#define DIV_FSYS3		0xc54c
+#define DIV_PERIL0		0xc550
+#define DIV_PERIL1		0xc554
+#define DIV_PERIL2		0xc558
+#define DIV_PERIL3		0xc55c
+#define DIV_PERIL4		0xc560
+#define DIV_PERIL5		0xc564
+#define E4X12_DIV_CAM1		0xc568
+#define GATE_SCLK_CAM		0xc820
+#define GATE_IP_CAM		0xc920
+#define GATE_IP_TV		0xc924
+#define GATE_IP_MFC		0xc928
+#define GATE_IP_G3D		0xc92c
+#define E4210_GATE_IP_IMAGE	0xc930
+#define GATE_IP_LCD0		0xc934
+#define E4210_GATE_IP_LCD1	0xc938
+#define E4X12_GATE_IP_ISP	0xc938
+#define E4X12_GATE_IP_MAUDIO	0xc93c
+#define GATE_IP_FSYS		0xc940
+#define GATE_IP_GPS		0xc94c
+#define GATE_IP_PERIL		0xc950
+#define E4210_GATE_IP_PERIR	0xc960
+#define GATE_BLOCK		0xc970
+#define E4X12_MPLL_CON0		0x10108
+#define SRC_DMC			0x10200
+#define SRC_MASK_DMC		0x10300
+#define DIV_DMC0		0x10500
+#define DIV_DMC1		0x10504
+#define GATE_IP_DMC		0x10900
+#define APLL_CON0		0x14100
+#define E4210_MPLL_CON0		0x14108
+#define SRC_CPU			0x14200
+#define DIV_CPU0		0x14500
+#define DIV_CPU1		0x14504
+#define GATE_SCLK_CPU		0x14800
+#define GATE_IP_CPU		0x14900
+#define E4X12_DIV_ISP0		0x18300
+#define E4X12_DIV_ISP1		0x18304
+#define E4X12_GATE_ISP0		0x18800
+#define E4X12_GATE_ISP1		0x18804
+
+/* the exynos4 soc type */
+enum exynos4_soc {
+	EXYNOS4210,
+	EXYNOS4X12,
+};
+
+/*
+ * Let each supported clock get a unique id. This id is used to lookup the clock
+ * for device tree based platforms. The clocks are categorized into three
+ * sections: core, sclk gate and bus interface gate clocks.
+ *
+ * When adding a new clock to this list, it is advised to choose a clock
+ * category and add it to the end of that category. That is because the the
+ * device tree source file is referring to these ids and any change in the
+ * sequence number of existing clocks will require corresponding change in the
+ * device tree files. This limitation would go away when pre-processor support
+ * for dtc would be available.
+ */
+enum exynos4_clks {
+	none,
+
+	/* core clocks */
+	xxti, xusbxti, fin_pll, fout_apll, fout_mpll, fout_epll, fout_vpll,
+	sclk_apll, sclk_mpll, sclk_epll, sclk_vpll, arm_clk, aclk200, aclk100,
+	aclk160, aclk133, mout_mpll_user_t, mout_mpll_user_c, mout_core,
+	mout_apll, /* 20 */
+
+	/* gate for special clocks (sclk) */
+	sclk_fimc0 = 128, sclk_fimc1, sclk_fimc2, sclk_fimc3, sclk_cam0,
+	sclk_cam1, sclk_csis0, sclk_csis1, sclk_hdmi, sclk_mixer, sclk_dac,
+	sclk_pixel, sclk_fimd0, sclk_mdnie0, sclk_mdnie_pwm0, sclk_mipi0,
+	sclk_audio0, sclk_mmc0, sclk_mmc1, sclk_mmc2, sclk_mmc3, sclk_mmc4,
+	sclk_sata, sclk_uart0, sclk_uart1, sclk_uart2, sclk_uart3, sclk_uart4,
+	sclk_audio1, sclk_audio2, sclk_spdif, sclk_spi0, sclk_spi1, sclk_spi2,
+	sclk_slimbus, sclk_fimd1, sclk_mipi1, sclk_pcm1, sclk_pcm2, sclk_i2s1,
+	sclk_i2s2, sclk_mipihsi, sclk_mfc, sclk_pcm0, sclk_g3d, sclk_pwm_isp,
+	sclk_spi0_isp, sclk_spi1_isp, sclk_uart_isp,
+
+	/* gate clocks */
+	fimc0 = 256, fimc1, fimc2, fimc3, csis0, csis1, jpeg, smmu_fimc0,
+	smmu_fimc1, smmu_fimc2, smmu_fimc3, smmu_jpeg, vp, mixer, tvenc, hdmi,
+	smmu_tv, mfc, smmu_mfcl, smmu_mfcr, g3d, g2d, rotator, mdma, smmu_g2d,
+	smmu_rotator, smmu_mdma, fimd0, mie0, mdnie0, dsim0, smmu_fimd0, fimd1,
+	mie1, dsim1, smmu_fimd1, pdma0, pdma1, pcie_phy, sata_phy, tsi, sdmmc0,
+	sdmmc1, sdmmc2, sdmmc3, sdmmc4, sata, sromc, usb_host, usb_device, pcie,
+	onenand, nfcon, smmu_pcie, gps, smmu_gps, uart0, uart1, uart2, uart3,
+	uart4, i2c0, i2c1, i2c2, i2c3, i2c4, i2c5, i2c6, i2c7, i2c_hdmi, tsadc,
+	spi0, spi1, spi2, i2s1, i2s2, pcm0, i2s0, pcm1, pcm2, pwm, slimbus,
+	spdif, ac97, modemif, chipid, sysreg, hdmi_cec, mct, wdt, rtc, keyif,
+	audss, mipi_hsi, mdma2, pixelasyncm0, pixelasyncm1, fimc_lite0,
+	fimc_lite1, ppmuispx, ppmuispmx, fimc_isp, fimc_drc, fimc_fd, mcuisp,
+	gicisp, smmu_isp, smmu_drc, smmu_fd, smmu_lite0, smmu_lite1, mcuctl_isp,
+	mpwm_isp, i2c0_isp, i2c1_isp, mtcadc_isp, pwm_isp, wdt_isp, uart_isp,
+	asyncaxim, smmu_ispcx, spi0_isp, spi1_isp, pwm_isp_sclk, spi0_isp_sclk,
+	spi1_isp_sclk, uart_isp_sclk,
+
+	/* mux clocks */
+	mout_fimc0 = 384, mout_fimc1, mout_fimc2, mout_fimc3, mout_cam0,
+	mout_cam1, mout_csis0, mout_csis1, mout_g3d0, mout_g3d1, mout_g3d,
+
+	nr_clks,
+};
+
+/*
+ * list of controller registers to be saved and restored during a
+ * suspend/resume cycle.
+ */
+static __initdata unsigned long exynos4210_clk_save[] = {
+	E4210_SRC_IMAGE,
+	E4210_SRC_LCD1,
+	E4210_SRC_MASK_LCD1,
+	E4210_DIV_LCD1,
+	E4210_GATE_IP_IMAGE,
+	E4210_GATE_IP_LCD1,
+	E4210_GATE_IP_PERIR,
+	E4210_MPLL_CON0,
+};
+
+static __initdata unsigned long exynos4x12_clk_save[] = {
+	E4X12_GATE_IP_IMAGE,
+	E4X12_GATE_IP_PERIR,
+	E4X12_SRC_CAM1,
+	E4X12_DIV_ISP,
+	E4X12_DIV_CAM1,
+	E4X12_MPLL_CON0,
+};
+
+static __initdata unsigned long exynos4_clk_regs[] = {
+	SRC_LEFTBUS,
+	DIV_LEFTBUS,
+	GATE_IP_LEFTBUS,
+	SRC_RIGHTBUS,
+	DIV_RIGHTBUS,
+	GATE_IP_RIGHTBUS,
+	EPLL_CON0,
+	EPLL_CON1,
+	EPLL_CON2,
+	VPLL_CON0,
+	VPLL_CON1,
+	VPLL_CON2,
+	SRC_TOP0,
+	SRC_TOP1,
+	SRC_CAM,
+	SRC_TV,
+	SRC_MFC,
+	SRC_G3D,
+	SRC_LCD0,
+	SRC_MAUDIO,
+	SRC_FSYS,
+	SRC_PERIL0,
+	SRC_PERIL1,
+	SRC_MASK_TOP,
+	SRC_MASK_CAM,
+	SRC_MASK_TV,
+	SRC_MASK_LCD0,
+	SRC_MASK_MAUDIO,
+	SRC_MASK_FSYS,
+	SRC_MASK_PERIL0,
+	SRC_MASK_PERIL1,
+	DIV_TOP,
+	DIV_CAM,
+	DIV_TV,
+	DIV_MFC,
+	DIV_G3D,
+	DIV_IMAGE,
+	DIV_LCD0,
+	DIV_MAUDIO,
+	DIV_FSYS0,
+	DIV_FSYS1,
+	DIV_FSYS2,
+	DIV_FSYS3,
+	DIV_PERIL0,
+	DIV_PERIL1,
+	DIV_PERIL2,
+	DIV_PERIL3,
+	DIV_PERIL4,
+	DIV_PERIL5,
+	GATE_SCLK_CAM,
+	GATE_IP_CAM,
+	GATE_IP_TV,
+	GATE_IP_MFC,
+	GATE_IP_G3D,
+	GATE_IP_LCD0,
+	GATE_IP_FSYS,
+	GATE_IP_GPS,
+	GATE_IP_PERIL,
+	GATE_BLOCK,
+	SRC_MASK_DMC,
+	SRC_DMC,
+	DIV_DMC0,
+	DIV_DMC1,
+	GATE_IP_DMC,
+	APLL_CON0,
+	SRC_CPU,
+	DIV_CPU0,
+	DIV_CPU1,
+	GATE_SCLK_CPU,
+	GATE_IP_CPU,
+};
+
+/* list of all parent clock list */
+PNAME(mout_apll_p)	= { "fin_pll", "fout_apll", };
+PNAME(mout_mpll_p)	= { "fin_pll", "fout_mpll", };
+PNAME(mout_epll_p)	= { "fin_pll", "fout_epll", };
+PNAME(mout_vpllsrc_p)	= { "fin_pll", "sclk_hdmi24m", };
+PNAME(mout_vpll_p)	= { "fin_pll", "fout_vpll", };
+PNAME(sclk_evpll_p)	= { "sclk_epll", "sclk_vpll", };
+PNAME(mout_mfc_p)	= { "mout_mfc0", "mout_mfc1", };
+PNAME(mout_g3d_p)	= { "mout_g3d0", "mout_g3d1", };
+PNAME(mout_g2d_p)	= { "mout_g2d0", "mout_g2d1", };
+PNAME(mout_hdmi_p)	= { "sclk_pixel", "sclk_hdmiphy", };
+PNAME(mout_jpeg_p)	= { "mout_jpeg0", "mout_jpeg1", };
+PNAME(mout_spdif_p)	= { "sclk_audio0", "sclk_audio1", "sclk_audio2",
+				"spdif_extclk", };
+PNAME(mout_onenand_p)  = {"aclk133", "aclk160", };
+PNAME(mout_onenand1_p) = {"mout_onenand", "sclk_vpll", };
+
+/* Exynos 4210-specific parent groups */
+PNAME(sclk_vpll_p4210)	= { "mout_vpllsrc", "fout_vpll", };
+PNAME(mout_core_p4210)	= { "mout_apll", "sclk_mpll", };
+PNAME(sclk_ampll_p4210)	= { "sclk_mpll", "sclk_apll", };
+PNAME(group1_p4210)	= { "xxti", "xusbxti", "sclk_hdmi24m",
+				"sclk_usbphy0", "none",	"sclk_hdmiphy",
+				"sclk_mpll", "sclk_epll", "sclk_vpll", };
+PNAME(mout_audio0_p4210) = { "cdclk0", "none", "sclk_hdmi24m",
+				"sclk_usbphy0", "xxti", "xusbxti", "sclk_mpll",
+				"sclk_epll", "sclk_vpll" };
+PNAME(mout_audio1_p4210) = { "cdclk1", "none", "sclk_hdmi24m",
+				"sclk_usbphy0", "xxti", "xusbxti", "sclk_mpll",
+				"sclk_epll", "sclk_vpll", };
+PNAME(mout_audio2_p4210) = { "cdclk2", "none", "sclk_hdmi24m",
+				"sclk_usbphy0", "xxti", "xusbxti", "sclk_mpll",
+				"sclk_epll", "sclk_vpll", };
+PNAME(mout_mixer_p4210)	= { "sclk_dac", "sclk_hdmi", };
+PNAME(mout_dac_p4210)	= { "sclk_vpll", "sclk_hdmiphy", };
+
+/* Exynos 4x12-specific parent groups */
+PNAME(mout_mpll_user_p4x12) = { "fin_pll", "sclk_mpll", };
+PNAME(mout_core_p4x12)	= { "mout_apll", "mout_mpll_user_c", };
+PNAME(sclk_ampll_p4x12)	= { "mout_mpll_user_t", "sclk_apll", };
+PNAME(group1_p4x12)	= { "xxti", "xusbxti", "sclk_hdmi24m", "sclk_usbphy0",
+				"none",	"sclk_hdmiphy", "mout_mpll_user_t",
+				"sclk_epll", "sclk_vpll", };
+PNAME(mout_audio0_p4x12) = { "cdclk0", "none", "sclk_hdmi24m",
+				"sclk_usbphy0", "xxti", "xusbxti",
+				"mout_mpll_user_t", "sclk_epll", "sclk_vpll" };
+PNAME(mout_audio1_p4x12) = { "cdclk1", "none", "sclk_hdmi24m",
+				"sclk_usbphy0", "xxti", "xusbxti",
+				"mout_mpll_user_t", "sclk_epll", "sclk_vpll", };
+PNAME(mout_audio2_p4x12) = { "cdclk2", "none", "sclk_hdmi24m",
+				"sclk_usbphy0", "xxti", "xusbxti",
+				"mout_mpll_user_t", "sclk_epll", "sclk_vpll", };
+PNAME(aclk_p4412)	= { "mout_mpll_user_t", "sclk_apll", };
+PNAME(mout_user_aclk400_mcuisp_p4x12) = {"fin_pll", "div_aclk400_mcuisp", };
+PNAME(mout_user_aclk200_p4x12) = {"fin_pll", "div_aclk200", };
+PNAME(mout_user_aclk266_gps_p4x12) = {"fin_pll", "div_aclk266_gps", };
+
+/* fixed rate clocks generated outside the soc */
+struct samsung_fixed_rate_clock exynos4_fixed_rate_ext_clks[] __initdata = {
+	FRATE(xxti, "xxti", NULL, CLK_IS_ROOT, 0),
+	FRATE(xusbxti, "xusbxti", NULL, CLK_IS_ROOT, 0),
+};
+
+/* fixed rate clocks generated inside the soc */
+struct samsung_fixed_rate_clock exynos4_fixed_rate_clks[] __initdata = {
+	FRATE(none, "sclk_hdmi24m", NULL, CLK_IS_ROOT, 24000000),
+	FRATE(none, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 27000000),
+	FRATE(none, "sclk_usbphy0", NULL, CLK_IS_ROOT, 48000000),
+};
+
+struct samsung_fixed_rate_clock exynos4210_fixed_rate_clks[] __initdata = {
+	FRATE(none, "sclk_usbphy1", NULL, CLK_IS_ROOT, 48000000),
+};
+
+/* list of mux clocks supported in all exynos4 soc's */
+struct samsung_mux_clock exynos4_mux_clks[] __initdata = {
+	MUX_F(mout_apll, "mout_apll", mout_apll_p, SRC_CPU, 0, 1,
+			CLK_SET_RATE_PARENT, 0),
+	MUX(none, "mout_hdmi", mout_hdmi_p, SRC_TV, 0, 1),
+	MUX(none, "mout_mfc1", sclk_evpll_p, SRC_MFC, 4, 1),
+	MUX(none, "mout_mfc", mout_mfc_p, SRC_MFC, 8, 1),
+	MUX_F(mout_g3d1, "mout_g3d1", sclk_evpll_p, SRC_G3D, 4, 1,
+			CLK_SET_RATE_PARENT, 0),
+	MUX_F(mout_g3d, "mout_g3d", mout_g3d_p, SRC_G3D, 8, 1,
+			CLK_SET_RATE_PARENT, 0),
+	MUX(none, "mout_spdif", mout_spdif_p, SRC_PERIL1, 8, 2),
+	MUX(none, "mout_onenand1", mout_onenand1_p, SRC_TOP0, 0, 1),
+	MUX_A(sclk_epll, "sclk_epll", mout_epll_p, SRC_TOP0, 4, 1, "sclk_epll"),
+	MUX(none, "mout_onenand", mout_onenand_p, SRC_TOP0, 28, 1),
+};
+
+/* list of mux clocks supported in exynos4210 soc */
+struct samsung_mux_clock exynos4210_mux_clks[] __initdata = {
+	MUX(none, "mout_aclk200", sclk_ampll_p4210, SRC_TOP0, 12, 1),
+	MUX(none, "mout_aclk100", sclk_ampll_p4210, SRC_TOP0, 16, 1),
+	MUX(none, "mout_aclk160", sclk_ampll_p4210, SRC_TOP0, 20, 1),
+	MUX(none, "mout_aclk133", sclk_ampll_p4210, SRC_TOP0, 24, 1),
+	MUX(none, "mout_vpllsrc", mout_vpllsrc_p, SRC_TOP1, 0, 1),
+	MUX(none, "mout_mixer", mout_mixer_p4210, SRC_TV, 4, 1),
+	MUX(none, "mout_dac", mout_dac_p4210, SRC_TV, 8, 1),
+	MUX(none, "mout_g2d0", sclk_ampll_p4210, E4210_SRC_IMAGE, 0, 1),
+	MUX(none, "mout_g2d1", sclk_evpll_p, E4210_SRC_IMAGE, 4, 1),
+	MUX(none, "mout_g2d", mout_g2d_p, E4210_SRC_IMAGE, 8, 1),
+	MUX(none, "mout_fimd1", group1_p4210, E4210_SRC_LCD1, 0, 4),
+	MUX(none, "mout_mipi1", group1_p4210, E4210_SRC_LCD1, 12, 4),
+	MUX_A(sclk_mpll, "sclk_mpll", mout_mpll_p, SRC_CPU, 8, 1, "sclk_mpll"),
+	MUX_A(mout_core, "mout_core", mout_core_p4210,
+			SRC_CPU, 16, 1, "mout_core"),
+	MUX_A(sclk_vpll, "sclk_vpll", sclk_vpll_p4210,
+			SRC_TOP0, 8, 1, "sclk_vpll"),
+	MUX(mout_fimc0, "mout_fimc0", group1_p4210, SRC_CAM, 0, 4),
+	MUX(mout_fimc1, "mout_fimc1", group1_p4210, SRC_CAM, 4, 4),
+	MUX(mout_fimc2, "mout_fimc2", group1_p4210, SRC_CAM, 8, 4),
+	MUX(mout_fimc3, "mout_fimc3", group1_p4210, SRC_CAM, 12, 4),
+	MUX(mout_cam0, "mout_cam0", group1_p4210, SRC_CAM, 16, 4),
+	MUX(mout_cam1, "mout_cam1", group1_p4210, SRC_CAM, 20, 4),
+	MUX(mout_csis0, "mout_csis0", group1_p4210, SRC_CAM, 24, 4),
+	MUX(mout_csis1, "mout_csis1", group1_p4210, SRC_CAM, 28, 4),
+	MUX(none, "mout_mfc0", sclk_ampll_p4210, SRC_MFC, 0, 1),
+	MUX_F(mout_g3d0, "mout_g3d0", sclk_ampll_p4210, SRC_G3D, 0, 1,
+			CLK_SET_RATE_PARENT, 0),
+	MUX(none, "mout_fimd0", group1_p4210, SRC_LCD0, 0, 4),
+	MUX(none, "mout_mipi0", group1_p4210, SRC_LCD0, 12, 4),
+	MUX(none, "mout_audio0", mout_audio0_p4210, SRC_MAUDIO, 0, 4),
+	MUX(none, "mout_mmc0", group1_p4210, SRC_FSYS, 0, 4),
+	MUX(none, "mout_mmc1", group1_p4210, SRC_FSYS, 4, 4),
+	MUX(none, "mout_mmc2", group1_p4210, SRC_FSYS, 8, 4),
+	MUX(none, "mout_mmc3", group1_p4210, SRC_FSYS, 12, 4),
+	MUX(none, "mout_mmc4", group1_p4210, SRC_FSYS, 16, 4),
+	MUX(none, "mout_sata", sclk_ampll_p4210, SRC_FSYS, 24, 1),
+	MUX(none, "mout_uart0", group1_p4210, SRC_PERIL0, 0, 4),
+	MUX(none, "mout_uart1", group1_p4210, SRC_PERIL0, 4, 4),
+	MUX(none, "mout_uart2", group1_p4210, SRC_PERIL0, 8, 4),
+	MUX(none, "mout_uart3", group1_p4210, SRC_PERIL0, 12, 4),
+	MUX(none, "mout_uart4", group1_p4210, SRC_PERIL0, 16, 4),
+	MUX(none, "mout_audio1", mout_audio1_p4210, SRC_PERIL1, 0, 4),
+	MUX(none, "mout_audio2", mout_audio2_p4210, SRC_PERIL1, 4, 4),
+	MUX(none, "mout_spi0", group1_p4210, SRC_PERIL1, 16, 4),
+	MUX(none, "mout_spi1", group1_p4210, SRC_PERIL1, 20, 4),
+	MUX(none, "mout_spi2", group1_p4210, SRC_PERIL1, 24, 4),
+};
+
+/* list of mux clocks supported in exynos4x12 soc */
+struct samsung_mux_clock exynos4x12_mux_clks[] __initdata = {
+	MUX(mout_mpll_user_c, "mout_mpll_user_c", mout_mpll_user_p4x12,
+			SRC_CPU, 24, 1),
+	MUX(none, "mout_aclk266_gps", aclk_p4412, SRC_TOP1, 4, 1),
+	MUX(none, "mout_aclk400_mcuisp", aclk_p4412, SRC_TOP1, 8, 1),
+	MUX(mout_mpll_user_t, "mout_mpll_user_t", mout_mpll_user_p4x12,
+			SRC_TOP1, 12, 1),
+	MUX(none, "mout_user_aclk266_gps", mout_user_aclk266_gps_p4x12,
+			SRC_TOP1, 16, 1),
+	MUX(aclk200, "aclk200", mout_user_aclk200_p4x12, SRC_TOP1, 20, 1),
+	MUX(none, "aclk400_mcuisp", mout_user_aclk400_mcuisp_p4x12,
+			SRC_TOP1, 24, 1),
+	MUX(none, "mout_aclk200", aclk_p4412, SRC_TOP0, 12, 1),
+	MUX(none, "mout_aclk100", aclk_p4412, SRC_TOP0, 16, 1),
+	MUX(none, "mout_aclk160", aclk_p4412, SRC_TOP0, 20, 1),
+	MUX(none, "mout_aclk133", aclk_p4412, SRC_TOP0, 24, 1),
+	MUX(none, "mout_mdnie0", group1_p4x12, SRC_LCD0, 4, 4),
+	MUX(none, "mout_mdnie_pwm0", group1_p4x12, SRC_LCD0, 8, 4),
+	MUX(none, "mout_sata", sclk_ampll_p4x12, SRC_FSYS, 24, 1),
+	MUX(none, "mout_jpeg0", sclk_ampll_p4x12, E4X12_SRC_CAM1, 0, 1),
+	MUX(none, "mout_jpeg1", sclk_evpll_p, E4X12_SRC_CAM1, 4, 1),
+	MUX(none, "mout_jpeg", mout_jpeg_p, E4X12_SRC_CAM1, 8, 1),
+	MUX_A(sclk_mpll, "sclk_mpll", mout_mpll_p,
+			SRC_DMC, 12, 1, "sclk_mpll"),
+	MUX_A(sclk_vpll, "sclk_vpll", mout_vpll_p,
+			SRC_TOP0, 8, 1, "sclk_vpll"),
+	MUX(mout_core, "mout_core", mout_core_p4x12, SRC_CPU, 16, 1),
+	MUX(mout_fimc0, "mout_fimc0", group1_p4x12, SRC_CAM, 0, 4),
+	MUX(mout_fimc1, "mout_fimc1", group1_p4x12, SRC_CAM, 4, 4),
+	MUX(mout_fimc2, "mout_fimc2", group1_p4x12, SRC_CAM, 8, 4),
+	MUX(mout_fimc3, "mout_fimc3", group1_p4x12, SRC_CAM, 12, 4),
+	MUX(mout_cam0, "mout_cam0", group1_p4x12, SRC_CAM, 16, 4),
+	MUX(mout_cam1, "mout_cam1", group1_p4x12, SRC_CAM, 20, 4),
+	MUX(mout_csis0, "mout_csis0", group1_p4x12, SRC_CAM, 24, 4),
+	MUX(mout_csis1, "mout_csis1", group1_p4x12, SRC_CAM, 28, 4),
+	MUX(none, "mout_mfc0", sclk_ampll_p4x12, SRC_MFC, 0, 1),
+	MUX_F(mout_g3d0, "mout_g3d0", sclk_ampll_p4x12, SRC_G3D, 0, 1,
+			CLK_SET_RATE_PARENT, 0),
+	MUX(none, "mout_fimd0", group1_p4x12, SRC_LCD0, 0, 4),
+	MUX(none, "mout_mipi0", group1_p4x12, SRC_LCD0, 12, 4),
+	MUX(none, "mout_audio0", mout_audio0_p4x12, SRC_MAUDIO, 0, 4),
+	MUX(none, "mout_mmc0", group1_p4x12, SRC_FSYS, 0, 4),
+	MUX(none, "mout_mmc1", group1_p4x12, SRC_FSYS, 4, 4),
+	MUX(none, "mout_mmc2", group1_p4x12, SRC_FSYS, 8, 4),
+	MUX(none, "mout_mmc3", group1_p4x12, SRC_FSYS, 12, 4),
+	MUX(none, "mout_mmc4", group1_p4x12, SRC_FSYS, 16, 4),
+	MUX(none, "mout_mipihsi", aclk_p4412, SRC_FSYS, 24, 1),
+	MUX(none, "mout_uart0", group1_p4x12, SRC_PERIL0, 0, 4),
+	MUX(none, "mout_uart1", group1_p4x12, SRC_PERIL0, 4, 4),
+	MUX(none, "mout_uart2", group1_p4x12, SRC_PERIL0, 8, 4),
+	MUX(none, "mout_uart3", group1_p4x12, SRC_PERIL0, 12, 4),
+	MUX(none, "mout_uart4", group1_p4x12, SRC_PERIL0, 16, 4),
+	MUX(none, "mout_audio1", mout_audio1_p4x12, SRC_PERIL1, 0, 4),
+	MUX(none, "mout_audio2", mout_audio2_p4x12, SRC_PERIL1, 4, 4),
+	MUX(none, "mout_spi0", group1_p4x12, SRC_PERIL1, 16, 4),
+	MUX(none, "mout_spi1", group1_p4x12, SRC_PERIL1, 20, 4),
+	MUX(none, "mout_spi2", group1_p4x12, SRC_PERIL1, 24, 4),
+	MUX(none, "mout_pwm_isp", group1_p4x12, E4X12_SRC_ISP, 0, 4),
+	MUX(none, "mout_spi0_isp", group1_p4x12, E4X12_SRC_ISP, 4, 4),
+	MUX(none, "mout_spi1_isp", group1_p4x12, E4X12_SRC_ISP, 8, 4),
+	MUX(none, "mout_uart_isp", group1_p4x12, E4X12_SRC_ISP, 12, 4),
+};
+
+/* list of divider clocks supported in all exynos4 soc's */
+struct samsung_div_clock exynos4_div_clks[] __initdata = {
+	DIV(none, "div_core", "mout_core", DIV_CPU0, 0, 3),
+	DIV(none, "div_core2", "div_core", DIV_CPU0, 28, 3),
+	DIV(none, "div_fimc0", "mout_fimc0", DIV_CAM, 0, 4),
+	DIV(none, "div_fimc1", "mout_fimc1", DIV_CAM, 4, 4),
+	DIV(none, "div_fimc2", "mout_fimc2", DIV_CAM, 8, 4),
+	DIV(none, "div_fimc3", "mout_fimc3", DIV_CAM, 12, 4),
+	DIV(none, "div_cam0", "mout_cam0", DIV_CAM, 16, 4),
+	DIV(none, "div_cam1", "mout_cam1", DIV_CAM, 20, 4),
+	DIV(none, "div_csis0", "mout_csis0", DIV_CAM, 24, 4),
+	DIV(none, "div_csis1", "mout_csis1", DIV_CAM, 28, 4),
+	DIV(sclk_mfc, "sclk_mfc", "mout_mfc", DIV_MFC, 0, 4),
+	DIV_F(none, "div_g3d", "mout_g3d", DIV_G3D, 0, 4,
+			CLK_SET_RATE_PARENT, 0),
+	DIV(none, "div_fimd0", "mout_fimd0", DIV_LCD0, 0, 4),
+	DIV(none, "div_mipi0", "mout_mipi0", DIV_LCD0, 16, 4),
+	DIV(none, "div_audio0", "mout_audio0", DIV_MAUDIO, 0, 4),
+	DIV(sclk_pcm0, "sclk_pcm0", "sclk_audio0", DIV_MAUDIO, 4, 8),
+	DIV(none, "div_mmc0", "mout_mmc0", DIV_FSYS1, 0, 4),
+	DIV(none, "div_mmc1", "mout_mmc1", DIV_FSYS1, 16, 4),
+	DIV(none, "div_mmc2", "mout_mmc2", DIV_FSYS2, 0, 4),
+	DIV(none, "div_mmc3", "mout_mmc3", DIV_FSYS2, 16, 4),
+	DIV(sclk_pixel, "sclk_pixel", "sclk_vpll", DIV_TV, 0, 4),
+	DIV(aclk100, "aclk100", "mout_aclk100", DIV_TOP, 4, 4),
+	DIV(aclk160, "aclk160", "mout_aclk160", DIV_TOP, 8, 3),
+	DIV(aclk133, "aclk133", "mout_aclk133", DIV_TOP, 12, 3),
+	DIV(none, "div_onenand", "mout_onenand1", DIV_TOP, 16, 3),
+	DIV(sclk_slimbus, "sclk_slimbus", "sclk_epll", DIV_PERIL3, 4, 4),
+	DIV(sclk_pcm1, "sclk_pcm1", "sclk_audio1", DIV_PERIL4, 4, 8),
+	DIV(sclk_pcm2, "sclk_pcm2", "sclk_audio2", DIV_PERIL4, 20, 8),
+	DIV(sclk_i2s1, "sclk_i2s1", "sclk_audio1", DIV_PERIL5, 0, 6),
+	DIV(sclk_i2s2, "sclk_i2s2", "sclk_audio2", DIV_PERIL5, 8, 6),
+	DIV(none, "div_mmc4", "mout_mmc4", DIV_FSYS3, 0, 4),
+	DIV(none, "div_mmc_pre4", "div_mmc4", DIV_FSYS3, 8, 8),
+	DIV(none, "div_uart0", "mout_uart0", DIV_PERIL0, 0, 4),
+	DIV(none, "div_uart1", "mout_uart1", DIV_PERIL0, 4, 4),
+	DIV(none, "div_uart2", "mout_uart2", DIV_PERIL0, 8, 4),
+	DIV(none, "div_uart3", "mout_uart3", DIV_PERIL0, 12, 4),
+	DIV(none, "div_uart4", "mout_uart4", DIV_PERIL0, 16, 4),
+	DIV(none, "div_spi0", "mout_spi0", DIV_PERIL1, 0, 4),
+	DIV(none, "div_spi_pre0", "div_spi0", DIV_PERIL1, 8, 8),
+	DIV(none, "div_spi1", "mout_spi1", DIV_PERIL1, 16, 4),
+	DIV(none, "div_spi_pre1", "div_spi1", DIV_PERIL1, 24, 8),
+	DIV(none, "div_spi2", "mout_spi2", DIV_PERIL2, 0, 4),
+	DIV(none, "div_spi_pre2", "div_spi2", DIV_PERIL2, 8, 8),
+	DIV(none, "div_audio1", "mout_audio1", DIV_PERIL4, 0, 4),
+	DIV(none, "div_audio2", "mout_audio2", DIV_PERIL4, 16, 4),
+	DIV_A(arm_clk, "arm_clk", "div_core2", DIV_CPU0, 28, 3, "arm_clk"),
+	DIV_A(sclk_apll, "sclk_apll", "mout_apll",
+			DIV_CPU0, 24, 3, "sclk_apll"),
+	DIV_F(none, "div_mipi_pre0", "div_mipi0", DIV_LCD0, 20, 4,
+			CLK_SET_RATE_PARENT, 0),
+	DIV_F(none, "div_mmc_pre0", "div_mmc0", DIV_FSYS1, 8, 8,
+			CLK_SET_RATE_PARENT, 0),
+	DIV_F(none, "div_mmc_pre1", "div_mmc1", DIV_FSYS1, 24, 8,
+			CLK_SET_RATE_PARENT, 0),
+	DIV_F(none, "div_mmc_pre2", "div_mmc2", DIV_FSYS2, 8, 8,
+			CLK_SET_RATE_PARENT, 0),
+	DIV_F(none, "div_mmc_pre3", "div_mmc3", DIV_FSYS2, 24, 8,
+			CLK_SET_RATE_PARENT, 0),
+};
+
+/* list of divider clocks supported in exynos4210 soc */
+struct samsung_div_clock exynos4210_div_clks[] __initdata = {
+	DIV(aclk200, "aclk200", "mout_aclk200", DIV_TOP, 0, 3),
+	DIV(none, "div_g2d", "mout_g2d", DIV_IMAGE, 0, 4),
+	DIV(none, "div_fimd1", "mout_fimd1", E4210_DIV_LCD1, 0, 4),
+	DIV(none, "div_mipi1", "mout_mipi1", E4210_DIV_LCD1, 16, 4),
+	DIV(none, "div_sata", "mout_sata", DIV_FSYS0, 20, 4),
+	DIV_F(none, "div_mipi_pre1", "div_mipi1", E4210_DIV_LCD1, 20, 4,
+			CLK_SET_RATE_PARENT, 0),
+};
+
+/* list of divider clocks supported in exynos4x12 soc */
+struct samsung_div_clock exynos4x12_div_clks[] __initdata = {
+	DIV(none, "div_mdnie0", "mout_mdnie0", DIV_LCD0, 4, 4),
+	DIV(none, "div_mdnie_pwm0", "mout_mdnie_pwm0", DIV_LCD0, 8, 4),
+	DIV(none, "div_mdnie_pwm_pre0", "div_mdnie_pwm0", DIV_LCD0, 12, 4),
+	DIV(none, "div_mipihsi", "mout_mipihsi", DIV_FSYS0, 20, 4),
+	DIV(none, "div_jpeg", "mout_jpeg", E4X12_DIV_CAM1, 0, 4),
+	DIV(none, "div_aclk200", "mout_aclk200", DIV_TOP, 0, 3),
+	DIV(none, "div_aclk266_gps", "mout_aclk266_gps", DIV_TOP, 20, 3),
+	DIV(none, "div_aclk400_mcuisp", "mout_aclk400_mcuisp", DIV_TOP, 24, 3),
+	DIV(none, "div_pwm_isp", "mout_pwm_isp", E4X12_DIV_ISP, 0, 4),
+	DIV(none, "div_spi0_isp", "mout_spi0_isp", E4X12_DIV_ISP, 4, 4),
+	DIV(none, "div_spi0_isp_pre", "div_spi0_isp", E4X12_DIV_ISP, 8, 8),
+	DIV(none, "div_spi1_isp", "mout_spi1_isp", E4X12_DIV_ISP, 16, 4),
+	DIV(none, "div_spi1_isp_pre", "div_spi1_isp", E4X12_DIV_ISP, 20, 8),
+	DIV(none, "div_uart_isp", "mout_uart_isp", E4X12_DIV_ISP, 28, 4),
+	DIV(none, "div_isp0", "aclk200", E4X12_DIV_ISP0, 0, 3),
+	DIV(none, "div_isp1", "aclk200", E4X12_DIV_ISP0, 4, 3),
+	DIV(none, "div_mpwm", "div_isp1", E4X12_DIV_ISP1, 0, 3),
+	DIV(none, "div_mcuisp0", "aclk400_mcuisp", E4X12_DIV_ISP1, 4, 3),
+	DIV(none, "div_mcuisp1", "div_mcuisp0", E4X12_DIV_ISP1, 8, 3),
+};
+
+/* list of gate clocks supported in all exynos4 soc's */
+struct samsung_gate_clock exynos4_gate_clks[] __initdata = {
+	/*
+	 * After all Exynos4 based platforms are migrated to use device tree,
+	 * the device name and clock alias names specified below for some
+	 * of the clocks can be removed.
+	 */
+	GATE(sclk_hdmi, "sclk_hdmi", "mout_hdmi", SRC_MASK_TV, 0, 0, 0),
+	GATE(sclk_spdif, "sclk_spdif", "mout_spdif", SRC_MASK_PERIL1, 8, 0, 0),
+	GATE(jpeg, "jpeg", "aclk160", GATE_IP_CAM, 6, 0, 0),
+	GATE(mie0, "mie0", "aclk160", GATE_IP_LCD0, 1, 0, 0),
+	GATE(dsim0, "dsim0", "aclk160", GATE_IP_LCD0, 3, 0, 0),
+	GATE(fimd1, "fimd1", "aclk160", E4210_GATE_IP_LCD1, 0, 0, 0),
+	GATE(mie1, "mie1", "aclk160", E4210_GATE_IP_LCD1, 1, 0, 0),
+	GATE(dsim1, "dsim1", "aclk160", E4210_GATE_IP_LCD1, 3, 0, 0),
+	GATE(smmu_fimd1, "smmu_fimd1", "aclk160", E4210_GATE_IP_LCD1, 4, 0, 0),
+	GATE(tsi, "tsi", "aclk133", GATE_IP_FSYS, 4, 0, 0),
+	GATE(sromc, "sromc", "aclk133", GATE_IP_FSYS, 11, 0, 0),
+	GATE(sclk_g3d, "sclk_g3d", "div_g3d", GATE_IP_G3D, 0,
+			CLK_SET_RATE_PARENT, 0),
+	GATE(usb_device, "usb_device", "aclk133", GATE_IP_FSYS, 13, 0, 0),
+	GATE(onenand, "onenand", "aclk133", GATE_IP_FSYS, 15, 0, 0),
+	GATE(nfcon, "nfcon", "aclk133", GATE_IP_FSYS, 16, 0, 0),
+	GATE(gps, "gps", "aclk133", GATE_IP_GPS, 0, 0, 0),
+	GATE(smmu_gps, "smmu_gps", "aclk133", GATE_IP_GPS, 1, 0, 0),
+	GATE(slimbus, "slimbus", "aclk100", GATE_IP_PERIL, 25, 0, 0),
+	GATE(sclk_cam0, "sclk_cam0", "div_cam0", GATE_SCLK_CAM, 4,
+			CLK_SET_RATE_PARENT, 0),
+	GATE(sclk_cam1, "sclk_cam1", "div_cam1", GATE_SCLK_CAM, 5,
+			CLK_SET_RATE_PARENT, 0),
+	GATE(sclk_mipi0, "sclk_mipi0", "div_mipi_pre0",
+			SRC_MASK_LCD0, 12, CLK_SET_RATE_PARENT, 0),
+	GATE(sclk_audio0, "sclk_audio0", "div_audio0", SRC_MASK_MAUDIO, 0,
+			CLK_SET_RATE_PARENT, 0),
+	GATE(sclk_audio1, "sclk_audio1", "div_audio1", SRC_MASK_PERIL1, 0,
+			CLK_SET_RATE_PARENT, 0),
+	GATE_D(vp, "s5p-mixer", "vp", "aclk160", GATE_IP_TV, 0, 0, 0),
+	GATE_D(mixer, "s5p-mixer", "mixer", "aclk160", GATE_IP_TV, 1, 0, 0),
+	GATE_D(hdmi, "exynos4-hdmi", "hdmi", "aclk160", GATE_IP_TV, 3, 0, 0),
+	GATE_A(pwm, "pwm", "aclk100", GATE_IP_PERIL, 24, 0, 0, "timers"),
+	GATE_A(sdmmc4, "sdmmc4", "aclk133", GATE_IP_FSYS, 9, 0, 0, "biu"),
+	GATE_A(usb_host, "usb_host", "aclk133",
+			GATE_IP_FSYS, 12, 0, 0, "usbhost"),
+	GATE_DA(sclk_fimc0, "exynos4-fimc.0", "sclk_fimc0", "div_fimc0",
+			SRC_MASK_CAM, 0, CLK_SET_RATE_PARENT, 0, "sclk_fimc"),
+	GATE_DA(sclk_fimc1, "exynos4-fimc.1", "sclk_fimc1", "div_fimc1",
+			SRC_MASK_CAM, 4, CLK_SET_RATE_PARENT, 0, "sclk_fimc"),
+	GATE_DA(sclk_fimc2, "exynos4-fimc.2", "sclk_fimc2", "div_fimc2",
+			SRC_MASK_CAM, 8, CLK_SET_RATE_PARENT, 0, "sclk_fimc"),
+	GATE_DA(sclk_fimc3, "exynos4-fimc.3", "sclk_fimc3", "div_fimc3",
+			SRC_MASK_CAM, 12, CLK_SET_RATE_PARENT, 0, "sclk_fimc"),
+	GATE_DA(sclk_csis0, "s5p-mipi-csis.0", "sclk_csis0", "div_csis0",
+			SRC_MASK_CAM, 24, CLK_SET_RATE_PARENT, 0, "sclk_csis"),
+	GATE_DA(sclk_csis1, "s5p-mipi-csis.1", "sclk_csis1", "div_csis1",
+			SRC_MASK_CAM, 28, CLK_SET_RATE_PARENT, 0, "sclk_csis"),
+	GATE_DA(sclk_fimd0, "exynos4-fb.0", "sclk_fimd0", "div_fimd0",
+			SRC_MASK_LCD0, 0, CLK_SET_RATE_PARENT, 0, "sclk_fimd"),
+	GATE_DA(sclk_mmc0, "exynos4-sdhci.0", "sclk_mmc0", "div_mmc_pre0",
+			SRC_MASK_FSYS, 0, CLK_SET_RATE_PARENT, 0,
+			"mmc_busclk.2"),
+	GATE_DA(sclk_mmc1, "exynos4-sdhci.1", "sclk_mmc1", "div_mmc_pre1",
+			SRC_MASK_FSYS, 4, CLK_SET_RATE_PARENT, 0,
+			"mmc_busclk.2"),
+	GATE_DA(sclk_mmc2, "exynos4-sdhci.2", "sclk_mmc2", "div_mmc_pre2",
+			SRC_MASK_FSYS, 8, CLK_SET_RATE_PARENT, 0,
+			"mmc_busclk.2"),
+	GATE_DA(sclk_mmc3, "exynos4-sdhci.3", "sclk_mmc3", "div_mmc_pre3",
+			SRC_MASK_FSYS, 12, CLK_SET_RATE_PARENT, 0,
+			"mmc_busclk.2"),
+	GATE_DA(sclk_mmc4, NULL, "sclk_mmc4", "div_mmc_pre4",
+			SRC_MASK_FSYS, 16, CLK_SET_RATE_PARENT, 0, "ciu"),
+	GATE_DA(sclk_uart0, "exynos4210-uart.0", "uclk0", "div_uart0",
+			SRC_MASK_PERIL0, 0, CLK_SET_RATE_PARENT,
+			0, "clk_uart_baud0"),
+	GATE_DA(sclk_uart1, "exynos4210-uart.1", "uclk1", "div_uart1",
+			SRC_MASK_PERIL0, 4, CLK_SET_RATE_PARENT,
+			0, "clk_uart_baud0"),
+	GATE_DA(sclk_uart2, "exynos4210-uart.2", "uclk2", "div_uart2",
+			SRC_MASK_PERIL0, 8, CLK_SET_RATE_PARENT,
+			0, "clk_uart_baud0"),
+	GATE_DA(sclk_uart3, "exynos4210-uart.3", "uclk3", "div_uart3",
+			SRC_MASK_PERIL0, 12, CLK_SET_RATE_PARENT,
+			0, "clk_uart_baud0"),
+	GATE_DA(sclk_uart4, "exynos4210-uart.4", "uclk4", "div_uart4",
+			SRC_MASK_PERIL0, 16, CLK_SET_RATE_PARENT,
+			0, "clk_uart_baud0"),
+	GATE(sclk_audio2, "sclk_audio2", "div_audio2", SRC_MASK_PERIL1, 4,
+			CLK_SET_RATE_PARENT, 0),
+	GATE_DA(sclk_spi0, "exynos4210-spi.0", "sclk_spi0", "div_spi_pre0",
+			SRC_MASK_PERIL1, 16, CLK_SET_RATE_PARENT,
+			0, "spi_busclk0"),
+	GATE_DA(sclk_spi1, "exynos4210-spi.1", "sclk_spi1", "div_spi_pre1",
+			SRC_MASK_PERIL1, 20, CLK_SET_RATE_PARENT,
+			0, "spi_busclk0"),
+	GATE_DA(sclk_spi2, "exynos4210-spi.2", "sclk_spi2", "div_spi_pre2",
+			SRC_MASK_PERIL1, 24, CLK_SET_RATE_PARENT,
+			0, "spi_busclk0"),
+	GATE_DA(fimc0, "exynos4-fimc.0", "fimc0", "aclk160",
+			GATE_IP_CAM, 0, 0, 0, "fimc"),
+	GATE_DA(fimc1, "exynos4-fimc.1", "fimc1", "aclk160",
+			GATE_IP_CAM, 1, 0, 0, "fimc"),
+	GATE_DA(fimc2, "exynos4-fimc.2", "fimc2", "aclk160",
+			GATE_IP_CAM, 2, 0, 0, "fimc"),
+	GATE_DA(fimc3, "exynos4-fimc.3", "fimc3", "aclk160",
+			GATE_IP_CAM, 3, 0, 0, "fimc"),
+	GATE_DA(csis0, "s5p-mipi-csis.0", "csis0", "aclk160",
+			GATE_IP_CAM, 4, 0, 0, "fimc"),
+	GATE_DA(csis1, "s5p-mipi-csis.1", "csis1", "aclk160",
+			GATE_IP_CAM, 5, 0, 0, "fimc"),
+	GATE_DA(smmu_fimc0, "exynos-sysmmu.5", "smmu_fimc0", "aclk160",
+			GATE_IP_CAM, 7, 0, 0, "sysmmu"),
+	GATE_DA(smmu_fimc1, "exynos-sysmmu.6", "smmu_fimc1", "aclk160",
+			GATE_IP_CAM, 8, 0, 0, "sysmmu"),
+	GATE_DA(smmu_fimc2, "exynos-sysmmu.7", "smmu_fimc2", "aclk160",
+			GATE_IP_CAM, 9, 0, 0, "sysmmu"),
+	GATE_DA(smmu_fimc3, "exynos-sysmmu.8", "smmu_fimc3", "aclk160",
+			GATE_IP_CAM, 10, 0, 0, "sysmmu"),
+	GATE_DA(smmu_jpeg, "exynos-sysmmu.3", "smmu_jpeg", "aclk160",
+			GATE_IP_CAM, 11, 0, 0, "sysmmu"),
+	GATE(pixelasyncm0, "pxl_async0", "aclk160", GATE_IP_CAM, 17, 0, 0),
+	GATE(pixelasyncm1, "pxl_async1", "aclk160", GATE_IP_CAM, 18, 0, 0),
+	GATE_DA(smmu_tv, "exynos-sysmmu.2", "smmu_tv", "aclk160",
+			GATE_IP_TV, 4, 0, 0, "sysmmu"),
+	GATE_DA(mfc, "s5p-mfc", "mfc", "aclk100", GATE_IP_MFC, 0, 0, 0, "mfc"),
+	GATE_DA(smmu_mfcl, "exynos-sysmmu.0", "smmu_mfcl", "aclk100",
+			GATE_IP_MFC, 1, 0, 0, "sysmmu"),
+	GATE_DA(smmu_mfcr, "exynos-sysmmu.1", "smmu_mfcr", "aclk100",
+			GATE_IP_MFC, 2, 0, 0, "sysmmu"),
+	GATE_DA(fimd0, "exynos4-fb.0", "fimd0", "aclk160",
+			GATE_IP_LCD0, 0, 0, 0, "fimd"),
+	GATE_DA(smmu_fimd0, "exynos-sysmmu.10", "smmu_fimd0", "aclk160",
+			GATE_IP_LCD0, 4, 0, 0, "sysmmu"),
+	GATE_DA(pdma0, "dma-pl330.0", "pdma0", "aclk133",
+			GATE_IP_FSYS, 0, 0, 0, "dma"),
+	GATE_DA(pdma1, "dma-pl330.1", "pdma1", "aclk133",
+			GATE_IP_FSYS, 1, 0, 0, "dma"),
+	GATE_DA(sdmmc0, "exynos4-sdhci.0", "sdmmc0", "aclk133",
+			GATE_IP_FSYS, 5, 0, 0, "hsmmc"),
+	GATE_DA(sdmmc1, "exynos4-sdhci.1", "sdmmc1", "aclk133",
+			GATE_IP_FSYS, 6, 0, 0, "hsmmc"),
+	GATE_DA(sdmmc2, "exynos4-sdhci.2", "sdmmc2", "aclk133",
+			GATE_IP_FSYS, 7, 0, 0, "hsmmc"),
+	GATE_DA(sdmmc3, "exynos4-sdhci.3", "sdmmc3", "aclk133",
+			GATE_IP_FSYS, 8, 0, 0, "hsmmc"),
+	GATE_DA(uart0, "exynos4210-uart.0", "uart0", "aclk100",
+			GATE_IP_PERIL, 0, 0, 0, "uart"),
+	GATE_DA(uart1, "exynos4210-uart.1", "uart1", "aclk100",
+			GATE_IP_PERIL, 1, 0, 0, "uart"),
+	GATE_DA(uart2, "exynos4210-uart.2", "uart2", "aclk100",
+			GATE_IP_PERIL, 2, 0, 0, "uart"),
+	GATE_DA(uart3, "exynos4210-uart.3", "uart3", "aclk100",
+			GATE_IP_PERIL, 3, 0, 0, "uart"),
+	GATE_DA(uart4, "exynos4210-uart.4", "uart4", "aclk100",
+			GATE_IP_PERIL, 4, 0, 0, "uart"),
+	GATE_DA(i2c0, "s3c2440-i2c.0", "i2c0", "aclk100",
+			GATE_IP_PERIL, 6, 0, 0, "i2c"),
+	GATE_DA(i2c1, "s3c2440-i2c.1", "i2c1", "aclk100",
+			GATE_IP_PERIL, 7, 0, 0, "i2c"),
+	GATE_DA(i2c2, "s3c2440-i2c.2", "i2c2", "aclk100",
+			GATE_IP_PERIL, 8, 0, 0, "i2c"),
+	GATE_DA(i2c3, "s3c2440-i2c.3", "i2c3", "aclk100",
+			GATE_IP_PERIL, 9, 0, 0, "i2c"),
+	GATE_DA(i2c4, "s3c2440-i2c.4", "i2c4", "aclk100",
+			GATE_IP_PERIL, 10, 0, 0, "i2c"),
+	GATE_DA(i2c5, "s3c2440-i2c.5", "i2c5", "aclk100",
+			GATE_IP_PERIL, 11, 0, 0, "i2c"),
+	GATE_DA(i2c6, "s3c2440-i2c.6", "i2c6", "aclk100",
+			GATE_IP_PERIL, 12, 0, 0, "i2c"),
+	GATE_DA(i2c7, "s3c2440-i2c.7", "i2c7", "aclk100",
+			GATE_IP_PERIL, 13, 0, 0, "i2c"),
+	GATE_DA(i2c_hdmi, "s3c2440-hdmiphy-i2c", "i2c-hdmi", "aclk100",
+			GATE_IP_PERIL, 14, 0, 0, "i2c"),
+	GATE_DA(spi0, "exynos4210-spi.0", "spi0", "aclk100",
+			GATE_IP_PERIL, 16, 0, 0, "spi"),
+	GATE_DA(spi1, "exynos4210-spi.1", "spi1", "aclk100",
+			GATE_IP_PERIL, 17, 0, 0, "spi"),
+	GATE_DA(spi2, "exynos4210-spi.2", "spi2", "aclk100",
+			GATE_IP_PERIL, 18, 0, 0, "spi"),
+	GATE_DA(i2s1, "samsung-i2s.1", "i2s1", "aclk100",
+			GATE_IP_PERIL, 20, 0, 0, "iis"),
+	GATE_DA(i2s2, "samsung-i2s.2", "i2s2", "aclk100",
+			GATE_IP_PERIL, 21, 0, 0, "iis"),
+	GATE_DA(pcm1, "samsung-pcm.1", "pcm1", "aclk100",
+			GATE_IP_PERIL, 22, 0, 0, "pcm"),
+	GATE_DA(pcm2, "samsung-pcm.2", "pcm2", "aclk100",
+			GATE_IP_PERIL, 23, 0, 0, "pcm"),
+	GATE_DA(spdif, "samsung-spdif", "spdif", "aclk100",
+			GATE_IP_PERIL, 26, 0, 0, "spdif"),
+	GATE_DA(ac97, "samsung-ac97", "ac97", "aclk100",
+			GATE_IP_PERIL, 27, 0, 0, "ac97"),
+};
+
+/* list of gate clocks supported in exynos4210 soc */
+struct samsung_gate_clock exynos4210_gate_clks[] __initdata = {
+	GATE(tvenc, "tvenc", "aclk160", GATE_IP_TV, 2, 0, 0),
+	GATE(g2d, "g2d", "aclk200", E4210_GATE_IP_IMAGE, 0, 0, 0),
+	GATE(rotator, "rotator", "aclk200", E4210_GATE_IP_IMAGE, 1, 0, 0),
+	GATE(mdma, "mdma", "aclk200", E4210_GATE_IP_IMAGE, 2, 0, 0),
+	GATE(smmu_g2d, "smmu_g2d", "aclk200", E4210_GATE_IP_IMAGE, 3, 0, 0),
+	GATE(smmu_mdma, "smmu_mdma", "aclk200", E4210_GATE_IP_IMAGE, 5, 0, 0),
+	GATE(pcie_phy, "pcie_phy", "aclk133", GATE_IP_FSYS, 2, 0, 0),
+	GATE(sata_phy, "sata_phy", "aclk133", GATE_IP_FSYS, 3, 0, 0),
+	GATE(sata, "sata", "aclk133", GATE_IP_FSYS, 10, 0, 0),
+	GATE(pcie, "pcie", "aclk133", GATE_IP_FSYS, 14, 0, 0),
+	GATE(smmu_pcie, "smmu_pcie", "aclk133", GATE_IP_FSYS, 18, 0, 0),
+	GATE(modemif, "modemif", "aclk100", GATE_IP_PERIL, 28, 0, 0),
+	GATE(chipid, "chipid", "aclk100", E4210_GATE_IP_PERIR, 0, 0, 0),
+	GATE(sysreg, "sysreg", "aclk100", E4210_GATE_IP_PERIR, 0, 0, 0),
+	GATE(hdmi_cec, "hdmi_cec", "aclk100", E4210_GATE_IP_PERIR, 11, 0, 0),
+	GATE(smmu_rotator, "smmu_rotator", "aclk200",
+			E4210_GATE_IP_IMAGE, 4, 0, 0),
+	GATE(sclk_mipi1, "sclk_mipi1", "div_mipi_pre1",
+			E4210_SRC_MASK_LCD1, 12, CLK_SET_RATE_PARENT, 0),
+	GATE(sclk_sata, "sclk_sata", "div_sata",
+			SRC_MASK_FSYS, 24, CLK_SET_RATE_PARENT, 0),
+	GATE(sclk_mixer, "sclk_mixer", "mout_mixer", SRC_MASK_TV, 4, 0, 0),
+	GATE(sclk_dac, "sclk_dac", "mout_dac", SRC_MASK_TV, 8, 0, 0),
+	GATE_A(tsadc, "tsadc", "aclk100", GATE_IP_PERIL, 15, 0, 0, "adc"),
+	GATE_A(mct, "mct", "aclk100", E4210_GATE_IP_PERIR, 13, 0, 0, "mct"),
+	GATE_A(wdt, "watchdog", "aclk100", E4210_GATE_IP_PERIR, 14, 0, 0, "watchdog"),
+	GATE_A(rtc, "rtc", "aclk100", E4210_GATE_IP_PERIR, 15, 0, 0, "rtc"),
+	GATE_A(keyif, "keyif", "aclk100", E4210_GATE_IP_PERIR, 16, 0, 0, "keypad"),
+	GATE_DA(sclk_fimd1, "exynos4-fb.1", "sclk_fimd1", "div_fimd1",
+			E4210_SRC_MASK_LCD1, 0, CLK_SET_RATE_PARENT, 0, "sclk_fimd"),
+};
+
+/* list of gate clocks supported in exynos4x12 soc */
+struct samsung_gate_clock exynos4x12_gate_clks[] __initdata = {
+	GATE(audss, "audss", "sclk_epll", E4X12_GATE_IP_MAUDIO, 0, 0, 0),
+	GATE(mdnie0, "mdnie0", "aclk160", GATE_IP_LCD0, 2, 0, 0),
+	GATE(rotator, "rotator", "aclk200", E4X12_GATE_IP_IMAGE, 1, 0, 0),
+	GATE(mdma2, "mdma2", "aclk200", E4X12_GATE_IP_IMAGE, 2, 0, 0),
+	GATE(smmu_mdma, "smmu_mdma", "aclk200", E4X12_GATE_IP_IMAGE, 5, 0, 0),
+	GATE(mipi_hsi, "mipi_hsi", "aclk133", GATE_IP_FSYS, 10, 0, 0),
+	GATE(chipid, "chipid", "aclk100", E4X12_GATE_IP_PERIR, 0, 0, 0),
+	GATE(sysreg, "sysreg", "aclk100", E4X12_GATE_IP_PERIR, 1, 0, 0),
+	GATE(hdmi_cec, "hdmi_cec", "aclk100", E4X12_GATE_IP_PERIR, 11, 0, 0),
+	GATE(sclk_mdnie0, "sclk_mdnie0", "div_mdnie0",
+			SRC_MASK_LCD0, 4, CLK_SET_RATE_PARENT, 0),
+	GATE(sclk_mdnie_pwm0, "sclk_mdnie_pwm0", "div_mdnie_pwm_pre0",
+			SRC_MASK_LCD0, 8, CLK_SET_RATE_PARENT, 0),
+	GATE(sclk_mipihsi, "sclk_mipihsi", "div_mipihsi",
+			SRC_MASK_FSYS, 24, CLK_SET_RATE_PARENT, 0),
+	GATE(smmu_rotator, "smmu_rotator", "aclk200",
+			E4X12_GATE_IP_IMAGE, 4, 0, 0),
+	GATE_A(mct, "mct", "aclk100", E4X12_GATE_IP_PERIR, 13, 0, 0, "mct"),
+	GATE_A(rtc, "rtc", "aclk100", E4X12_GATE_IP_PERIR, 15, 0, 0, "rtc"),
+	GATE_A(keyif, "keyif", "aclk100",
+			E4X12_GATE_IP_PERIR, 16, 0, 0, "keypad"),
+	GATE(sclk_pwm_isp, "sclk_pwm_isp", "div_pwm_isp",
+			E4X12_SRC_MASK_ISP, 0, CLK_SET_RATE_PARENT, 0),
+	GATE(sclk_spi0_isp, "sclk_spi0_isp", "div_spi0_isp_pre",
+			E4X12_SRC_MASK_ISP, 4, CLK_SET_RATE_PARENT, 0),
+	GATE(sclk_spi1_isp, "sclk_spi1_isp", "div_spi1_isp_pre",
+			E4X12_SRC_MASK_ISP, 8, CLK_SET_RATE_PARENT, 0),
+	GATE(sclk_uart_isp, "sclk_uart_isp", "div_uart_isp",
+			E4X12_SRC_MASK_ISP, 12, CLK_SET_RATE_PARENT, 0),
+	GATE(pwm_isp_sclk, "pwm_isp_sclk", "sclk_pwm_isp",
+			E4X12_GATE_IP_ISP, 0, 0, 0),
+	GATE(spi0_isp_sclk, "spi0_isp_sclk", "sclk_spi0_isp",
+			E4X12_GATE_IP_ISP, 1, 0, 0),
+	GATE(spi1_isp_sclk, "spi1_isp_sclk", "sclk_spi1_isp",
+			E4X12_GATE_IP_ISP, 2, 0, 0),
+	GATE(uart_isp_sclk, "uart_isp_sclk", "sclk_uart_isp",
+			E4X12_GATE_IP_ISP, 3, 0, 0),
+	GATE_A(wdt, "watchdog", "aclk100",
+			E4X12_GATE_IP_PERIR, 14, 0, 0, "watchdog"),
+	GATE_DA(pcm0, "samsung-pcm.0", "pcm0", "aclk100",
+			E4X12_GATE_IP_MAUDIO, 2, 0, 0, "pcm"),
+	GATE_DA(i2s0, "samsung-i2s.0", "i2s0", "aclk100",
+			E4X12_GATE_IP_MAUDIO, 3, 0, 0, "iis"),
+	GATE(fimc_isp, "isp", "aclk200", E4X12_GATE_ISP0, 0,
+			CLK_IGNORE_UNUSED, 0),
+	GATE(fimc_drc, "drc", "aclk200", E4X12_GATE_ISP0, 1,
+			CLK_IGNORE_UNUSED, 0),
+	GATE(fimc_fd, "fd", "aclk200", E4X12_GATE_ISP0, 2,
+			CLK_IGNORE_UNUSED, 0),
+	GATE(fimc_lite0, "lite0", "aclk200", E4X12_GATE_ISP0, 3,
+			CLK_IGNORE_UNUSED, 0),
+	GATE(fimc_lite1, "lite1", "aclk200", E4X12_GATE_ISP0, 4,
+			CLK_IGNORE_UNUSED, 0),
+	GATE(mcuisp, "mcuisp", "aclk200", E4X12_GATE_ISP0, 5,
+			CLK_IGNORE_UNUSED, 0),
+	GATE(gicisp, "gicisp", "aclk200", E4X12_GATE_ISP0, 7,
+			CLK_IGNORE_UNUSED, 0),
+	GATE(smmu_isp, "smmu_isp", "aclk200", E4X12_GATE_ISP0, 8,
+			CLK_IGNORE_UNUSED, 0),
+	GATE(smmu_drc, "smmu_drc", "aclk200", E4X12_GATE_ISP0, 9,
+			CLK_IGNORE_UNUSED, 0),
+	GATE(smmu_fd, "smmu_fd", "aclk200", E4X12_GATE_ISP0, 10,
+			CLK_IGNORE_UNUSED, 0),
+	GATE(smmu_lite0, "smmu_lite0", "aclk200", E4X12_GATE_ISP0, 11,
+			CLK_IGNORE_UNUSED, 0),
+	GATE(smmu_lite1, "smmu_lite1", "aclk200", E4X12_GATE_ISP0, 12,
+			CLK_IGNORE_UNUSED, 0),
+	GATE(ppmuispmx, "ppmuispmx", "aclk200", E4X12_GATE_ISP0, 20,
+			CLK_IGNORE_UNUSED, 0),
+	GATE(ppmuispx, "ppmuispx", "aclk200", E4X12_GATE_ISP0, 21,
+			CLK_IGNORE_UNUSED, 0),
+	GATE(mcuctl_isp, "mcuctl_isp", "aclk200", E4X12_GATE_ISP0, 23,
+			CLK_IGNORE_UNUSED, 0),
+	GATE(mpwm_isp, "mpwm_isp", "aclk200", E4X12_GATE_ISP0, 24,
+			CLK_IGNORE_UNUSED, 0),
+	GATE(i2c0_isp, "i2c0_isp", "aclk200", E4X12_GATE_ISP0, 25,
+			CLK_IGNORE_UNUSED, 0),
+	GATE(i2c1_isp, "i2c1_isp", "aclk200", E4X12_GATE_ISP0, 26,
+			CLK_IGNORE_UNUSED, 0),
+	GATE(mtcadc_isp, "mtcadc_isp", "aclk200", E4X12_GATE_ISP0, 27,
+			CLK_IGNORE_UNUSED, 0),
+	GATE(pwm_isp, "pwm_isp", "aclk200", E4X12_GATE_ISP0, 28,
+			CLK_IGNORE_UNUSED, 0),
+	GATE(wdt_isp, "wdt_isp", "aclk200", E4X12_GATE_ISP0, 30,
+			CLK_IGNORE_UNUSED, 0),
+	GATE(uart_isp, "uart_isp", "aclk200", E4X12_GATE_ISP0, 31,
+			CLK_IGNORE_UNUSED, 0),
+	GATE(asyncaxim, "asyncaxim", "aclk200", E4X12_GATE_ISP1, 0,
+			CLK_IGNORE_UNUSED, 0),
+	GATE(smmu_ispcx, "smmu_ispcx", "aclk200", E4X12_GATE_ISP1, 4,
+			CLK_IGNORE_UNUSED, 0),
+	GATE(spi0_isp, "spi0_isp", "aclk200", E4X12_GATE_ISP1, 12,
+			CLK_IGNORE_UNUSED, 0),
+	GATE(spi1_isp, "spi1_isp", "aclk200", E4X12_GATE_ISP1, 13,
+			CLK_IGNORE_UNUSED, 0),
+};
+
+#ifdef CONFIG_OF
+static struct of_device_id exynos4_clk_ids[] __initdata = {
+	{ .compatible = "samsung,exynos4210-clock",
+			.data = (void *)EXYNOS4210, },
+	{ .compatible = "samsung,exynos4412-clock",
+			.data = (void *)EXYNOS4X12, },
+	{ },
+};
+#endif
+
+/*
+ * The parent of the fin_pll clock is selected by the XOM[0] bit. This bit
+ * resides in chipid register space, outside of the clock controller memory
+ * mapped space. So to determine the parent of fin_pll clock, the chipid
+ * controller is first remapped and the value of XOM[0] bit is read to
+ * determine the parent clock.
+ */
+static void __init exynos4_clk_register_finpll(void)
+{
+	struct samsung_fixed_rate_clock fclk;
+	struct device_node *np;
+	struct clk *clk;
+	void __iomem *chipid_base = S5P_VA_CHIPID;
+	unsigned long xom, finpll_f = 24000000;
+	char *parent_name;
+
+	np = of_find_compatible_node(NULL, NULL, "samsung,exynos4210-chipid");
+	if (np)
+		chipid_base = of_iomap(np, 0);
+
+	if (chipid_base) {
+		xom = readl(chipid_base + 8);
+		parent_name = xom & 1 ? "xusbxti" : "xxti";
+		clk = clk_get(NULL, parent_name);
+		if (IS_ERR(clk)) {
+			pr_err("%s: failed to lookup parent clock %s, assuming "
+				"fin_pll clock frequency is 24MHz\n", __func__,
+				parent_name);
+		} else {
+			finpll_f = clk_get_rate(clk);
+		}
+	} else {
+		pr_err("%s: failed to map chipid registers, assuming "
+			"fin_pll clock frequency is 24MHz\n", __func__);
+	}
+
+	fclk.id = fin_pll;
+	fclk.name = "fin_pll";
+	fclk.parent_name = NULL;
+	fclk.flags = CLK_IS_ROOT;
+	fclk.fixed_rate = finpll_f;
+	samsung_clk_register_fixed_rate(&fclk, 1);
+
+	if (np)
+		iounmap(chipid_base);
+}
+
+/*
+ * This function allows non-dt platforms to specify the clock speed of the
+ * xxti and xusbxti clocks. These clocks are then registered with the specified
+ * clock speed.
+ */
+void __init exynos4_clk_register_fixed_ext(unsigned long xxti_f,
+						unsigned long xusbxti_f)
+{
+	exynos4_fixed_rate_ext_clks[0].fixed_rate = xxti_f;
+	exynos4_fixed_rate_ext_clks[1].fixed_rate = xusbxti_f;
+	samsung_clk_register_fixed_rate(exynos4_fixed_rate_ext_clks,
+			ARRAY_SIZE(exynos4_fixed_rate_ext_clks));
+}
+
+static __initdata struct of_device_id ext_clk_match[] = {
+	{ .compatible = "samsung,clock-xxti", .data = (void *)0, },
+	{ .compatible = "samsung,clock-xusbxti", .data = (void *)1, },
+	{},
+};
+
+/* register exynos4 clocks */
+void __init exynos4_clk_init(struct device_node *np)
+{
+	void __iomem *reg_base;
+	struct clk *apll, *mpll, *epll, *vpll;
+	u32 exynos4_soc;
+
+	if (np) {
+		const struct of_device_id *match;
+		match = of_match_node(exynos4_clk_ids, np);
+		exynos4_soc = (u32)match->data;
+
+		reg_base = of_iomap(np, 0);
+		if (!reg_base)
+			panic("%s: failed to map registers\n", __func__);
+	} else {
+		reg_base = S5P_VA_CMU;
+		if (soc_is_exynos4210())
+			exynos4_soc = EXYNOS4210;
+		else if (soc_is_exynos4212() || soc_is_exynos4412())
+			exynos4_soc = EXYNOS4X12;
+		else
+			panic("%s: unable to determine soc\n", __func__);
+	}
+
+	if (exynos4_soc == EXYNOS4210)
+		samsung_clk_init(np, reg_base, nr_clks,
+			exynos4_clk_regs, ARRAY_SIZE(exynos4_clk_regs),
+			exynos4210_clk_save, ARRAY_SIZE(exynos4210_clk_save));
+	else
+		samsung_clk_init(np, reg_base, nr_clks,
+			exynos4_clk_regs, ARRAY_SIZE(exynos4_clk_regs),
+			exynos4x12_clk_save, ARRAY_SIZE(exynos4x12_clk_save));
+
+	if (np)
+		samsung_clk_of_register_fixed_ext(exynos4_fixed_rate_ext_clks,
+			ARRAY_SIZE(exynos4_fixed_rate_ext_clks),
+			ext_clk_match);
+
+	exynos4_clk_register_finpll();
+
+	if (exynos4_soc == EXYNOS4210) {
+		apll = samsung_clk_register_pll45xx("fout_apll", "fin_pll",
+					reg_base + APLL_CON0, pll_4508);
+		mpll = samsung_clk_register_pll45xx("fout_mpll", "fin_pll",
+					reg_base + E4210_MPLL_CON0, pll_4508);
+		epll = samsung_clk_register_pll46xx("fout_epll", "fin_pll",
+					reg_base + EPLL_CON0, pll_4600);
+		vpll = samsung_clk_register_pll46xx("fout_vpll", "mout_vpllsrc",
+					reg_base + VPLL_CON0, pll_4650c);
+	} else {
+		apll = samsung_clk_register_pll35xx("fout_apll", "fin_pll",
+					reg_base + APLL_CON0);
+		mpll = samsung_clk_register_pll35xx("fout_mpll", "fin_pll",
+					reg_base + E4X12_MPLL_CON0);
+		epll = samsung_clk_register_pll36xx("fout_epll", "fin_pll",
+					reg_base + EPLL_CON0);
+		vpll = samsung_clk_register_pll36xx("fout_vpll", "fin_pll",
+					reg_base + VPLL_CON0);
+	}
+
+	samsung_clk_add_lookup(apll, fout_apll);
+	samsung_clk_add_lookup(mpll, fout_mpll);
+	samsung_clk_add_lookup(epll, fout_epll);
+	samsung_clk_add_lookup(vpll, fout_vpll);
+
+	samsung_clk_register_fixed_rate(exynos4_fixed_rate_clks,
+			ARRAY_SIZE(exynos4_fixed_rate_clks));
+	samsung_clk_register_mux(exynos4_mux_clks,
+			ARRAY_SIZE(exynos4_mux_clks));
+	samsung_clk_register_div(exynos4_div_clks,
+			ARRAY_SIZE(exynos4_div_clks));
+	samsung_clk_register_gate(exynos4_gate_clks,
+			ARRAY_SIZE(exynos4_gate_clks));
+
+	if (exynos4_soc == EXYNOS4210) {
+		samsung_clk_register_fixed_rate(exynos4210_fixed_rate_clks,
+			ARRAY_SIZE(exynos4210_fixed_rate_clks));
+		samsung_clk_register_mux(exynos4210_mux_clks,
+			ARRAY_SIZE(exynos4210_mux_clks));
+		samsung_clk_register_div(exynos4210_div_clks,
+			ARRAY_SIZE(exynos4210_div_clks));
+		samsung_clk_register_gate(exynos4210_gate_clks,
+			ARRAY_SIZE(exynos4210_gate_clks));
+	} else {
+		samsung_clk_register_mux(exynos4x12_mux_clks,
+			ARRAY_SIZE(exynos4x12_mux_clks));
+		samsung_clk_register_div(exynos4x12_div_clks,
+			ARRAY_SIZE(exynos4x12_div_clks));
+		samsung_clk_register_gate(exynos4x12_gate_clks,
+			ARRAY_SIZE(exynos4x12_gate_clks));
+	}
+
+	pr_info("%s clocks: sclk_apll = %ld, sclk_mpll = %ld\n"
+		"\tsclk_epll = %ld, sclk_vpll = %ld, arm_clk = %ld\n",
+		exynos4_soc == EXYNOS4210 ? "Exynos4210" : "Exynos4x12",
+		_get_rate("sclk_apll"),	_get_rate("sclk_mpll"),
+		_get_rate("sclk_epll"), _get_rate("sclk_vpll"),
+		_get_rate("arm_clk"));
+}
+CLK_OF_DECLARE(exynos4210_clk, "samsung,exynos4210-clock", exynos4_clk_init);
+CLK_OF_DECLARE(exynos4412_clk, "samsung,exynos4412-clock", exynos4_clk_init);
diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c
new file mode 100644
index 0000000..e5e733a
--- /dev/null
+++ b/drivers/clk/samsung/clk-exynos5250.c
@@ -0,0 +1,523 @@
+/*
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2013 Linaro Ltd.
+ * Author: Thomas Abraham <thomas.ab@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.
+ *
+ * Common Clock Framework support for Exynos5250 SoC.
+*/
+
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include <plat/cpu.h>
+#include "clk.h"
+#include "clk-pll.h"
+
+#define SRC_CPU			0x200
+#define DIV_CPU0		0x500
+#define SRC_CORE1		0x4204
+#define SRC_TOP0		0x10210
+#define SRC_TOP2		0x10218
+#define SRC_GSCL		0x10220
+#define SRC_DISP1_0		0x1022c
+#define SRC_MAU			0x10240
+#define SRC_FSYS		0x10244
+#define SRC_GEN			0x10248
+#define SRC_PERIC0		0x10250
+#define SRC_PERIC1		0x10254
+#define SRC_MASK_GSCL		0x10320
+#define SRC_MASK_DISP1_0	0x1032c
+#define SRC_MASK_MAU		0x10334
+#define SRC_MASK_FSYS		0x10340
+#define SRC_MASK_GEN		0x10344
+#define SRC_MASK_PERIC0		0x10350
+#define SRC_MASK_PERIC1		0x10354
+#define DIV_TOP0		0x10510
+#define DIV_TOP1		0x10514
+#define DIV_GSCL		0x10520
+#define DIV_DISP1_0		0x1052c
+#define DIV_GEN			0x1053c
+#define DIV_MAU			0x10544
+#define DIV_FSYS0		0x10548
+#define DIV_FSYS1		0x1054c
+#define DIV_FSYS2		0x10550
+#define DIV_PERIC0		0x10558
+#define DIV_PERIC1		0x1055c
+#define DIV_PERIC2		0x10560
+#define DIV_PERIC3		0x10564
+#define DIV_PERIC4		0x10568
+#define DIV_PERIC5		0x1056c
+#define GATE_IP_GSCL		0x10920
+#define GATE_IP_MFC		0x1092c
+#define GATE_IP_GEN		0x10934
+#define GATE_IP_FSYS		0x10944
+#define GATE_IP_PERIC		0x10950
+#define GATE_IP_PERIS		0x10960
+#define SRC_CDREX		0x20200
+#define PLL_DIV2_SEL		0x20a24
+#define GATE_IP_DISP1		0x10928
+
+/*
+ * Let each supported clock get a unique id. This id is used to lookup the clock
+ * for device tree based platforms. The clocks are categorized into three
+ * sections: core, sclk gate and bus interface gate clocks.
+ *
+ * When adding a new clock to this list, it is advised to choose a clock
+ * category and add it to the end of that category. That is because the the
+ * device tree source file is referring to these ids and any change in the
+ * sequence number of existing clocks will require corresponding change in the
+ * device tree files. This limitation would go away when pre-processor support
+ * for dtc would be available.
+ */
+enum exynos5250_clks {
+	none,
+
+	/* core clocks */
+	fin_pll,
+
+	/* gate for special clocks (sclk) */
+	sclk_cam_bayer = 128, sclk_cam0, sclk_cam1, sclk_gscl_wa, sclk_gscl_wb,
+	sclk_fimd1, sclk_mipi1, sclk_dp, sclk_hdmi, sclk_pixel, sclk_audio0,
+	sclk_mmc0, sclk_mmc1, sclk_mmc2, sclk_mmc3, sclk_sata, sclk_usb3,
+	sclk_jpeg, sclk_uart0, sclk_uart1, sclk_uart2, sclk_uart3, sclk_pwm,
+	sclk_audio1, sclk_audio2, sclk_spdif, sclk_spi0, sclk_spi1, sclk_spi2,
+
+	/* gate clocks */
+	gscl0 = 256, gscl1, gscl2, gscl3, gscl_wa, gscl_wb, smmu_gscl0,
+	smmu_gscl1, smmu_gscl2, smmu_gscl3, mfc, smmu_mfcl, smmu_mfcr, rotator,
+	jpeg, mdma1, smmu_rotator, smmu_jpeg, smmu_mdma1, pdma0, pdma1, sata,
+	usbotg, mipi_hsi, sdmmc0, sdmmc1, sdmmc2, sdmmc3, sromc, usb2, usb3,
+	sata_phyctrl, sata_phyi2c, uart0, uart1, uart2,	uart3, uart4, i2c0,
+	i2c1, i2c2, i2c3, i2c4, i2c5, i2c6, i2c7, i2c_hdmi, adc, spi0, spi1,
+	spi2, i2s1, i2s2, pcm1, pcm2, pwm, spdif, ac97, hsi2c0, hsi2c1, hsi2c2,
+	hsi2c3, chipid, sysreg, pmu, cmu_top, cmu_core, cmu_mem, tzpc0, tzpc1,
+	tzpc2, tzpc3, tzpc4, tzpc5, tzpc6, tzpc7, tzpc8, tzpc9, hdmi_cec, mct,
+	wdt, rtc, tmu, fimd1, mie1, dsim0, dp, mixer, hdmi,
+
+	nr_clks,
+};
+
+/*
+ * list of controller registers to be saved and restored during a
+ * suspend/resume cycle.
+ */
+static __initdata unsigned long exynos5250_clk_regs[] = {
+	SRC_CPU,
+	DIV_CPU0,
+	SRC_CORE1,
+	SRC_TOP0,
+	SRC_TOP2,
+	SRC_GSCL,
+	SRC_DISP1_0,
+	SRC_MAU,
+	SRC_FSYS,
+	SRC_GEN,
+	SRC_PERIC0,
+	SRC_PERIC1,
+	SRC_MASK_GSCL,
+	SRC_MASK_DISP1_0,
+	SRC_MASK_MAU,
+	SRC_MASK_FSYS,
+	SRC_MASK_GEN,
+	SRC_MASK_PERIC0,
+	SRC_MASK_PERIC1,
+	DIV_TOP0,
+	DIV_TOP1,
+	DIV_GSCL,
+	DIV_DISP1_0,
+	DIV_GEN,
+	DIV_MAU,
+	DIV_FSYS0,
+	DIV_FSYS1,
+	DIV_FSYS2,
+	DIV_PERIC0,
+	DIV_PERIC1,
+	DIV_PERIC2,
+	DIV_PERIC3,
+	DIV_PERIC4,
+	DIV_PERIC5,
+	GATE_IP_GSCL,
+	GATE_IP_MFC,
+	GATE_IP_GEN,
+	GATE_IP_FSYS,
+	GATE_IP_PERIC,
+	GATE_IP_PERIS,
+	SRC_CDREX,
+	PLL_DIV2_SEL,
+	GATE_IP_DISP1,
+};
+
+/* list of all parent clock list */
+PNAME(mout_apll_p)	= { "fin_pll", "fout_apll", };
+PNAME(mout_cpu_p)	= { "mout_apll", "mout_mpll", };
+PNAME(mout_mpll_fout_p)	= { "fout_mplldiv2", "fout_mpll" };
+PNAME(mout_mpll_p)	= { "fin_pll", "mout_mpll_fout" };
+PNAME(mout_bpll_fout_p)	= { "fout_bplldiv2", "fout_bpll" };
+PNAME(mout_bpll_p)	= { "fin_pll", "mout_bpll_fout" };
+PNAME(mout_vpllsrc_p)	= { "fin_pll", "sclk_hdmi27m" };
+PNAME(mout_vpll_p)	= { "mout_vpllsrc", "fout_vpll" };
+PNAME(mout_cpll_p)	= { "fin_pll", "fout_cpll" };
+PNAME(mout_epll_p)	= { "fin_pll", "fout_epll" };
+PNAME(mout_mpll_user_p)	= { "fin_pll", "sclk_mpll" };
+PNAME(mout_bpll_user_p)	= { "fin_pll", "sclk_bpll" };
+PNAME(mout_aclk166_p)	= { "sclk_cpll", "sclk_mpll_user" };
+PNAME(mout_aclk200_p)	= { "sclk_mpll_user", "sclk_bpll_user" };
+PNAME(mout_hdmi_p)	= { "div_hdmi_pixel", "sclk_hdmiphy" };
+PNAME(mout_usb3_p)	= { "sclk_mpll_user", "sclk_cpll" };
+PNAME(mout_group1_p)	= { "fin_pll", "fin_pll", "sclk_hdmi27m",
+				"sclk_dptxphy", "sclk_uhostphy", "sclk_hdmiphy",
+				"sclk_mpll_user", "sclk_epll", "sclk_vpll",
+				"sclk_cpll" };
+PNAME(mout_audio0_p)	= { "cdclk0", "fin_pll", "sclk_hdmi27m", "sclk_dptxphy",
+				"sclk_uhostphy", "sclk_hdmiphy",
+				"sclk_mpll_user", "sclk_epll", "sclk_vpll",
+				"sclk_cpll" };
+PNAME(mout_audio1_p)	= { "cdclk1", "fin_pll", "sclk_hdmi27m", "sclk_dptxphy",
+				"sclk_uhostphy", "sclk_hdmiphy",
+				"sclk_mpll_user", "sclk_epll", "sclk_vpll",
+				"sclk_cpll" };
+PNAME(mout_audio2_p)	= { "cdclk2", "fin_pll", "sclk_hdmi27m", "sclk_dptxphy",
+				"sclk_uhostphy", "sclk_hdmiphy",
+				"sclk_mpll_user", "sclk_epll", "sclk_vpll",
+				"sclk_cpll" };
+PNAME(mout_spdif_p)	= { "sclk_audio0", "sclk_audio1", "sclk_audio2",
+				"spdif_extclk" };
+
+/* fixed rate clocks generated outside the soc */
+struct samsung_fixed_rate_clock exynos5250_fixed_rate_ext_clks[] __initdata = {
+	FRATE(fin_pll, "fin_pll", NULL, CLK_IS_ROOT, 0),
+};
+
+/* fixed rate clocks generated inside the soc */
+struct samsung_fixed_rate_clock exynos5250_fixed_rate_clks[] __initdata = {
+	FRATE(none, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 24000000),
+	FRATE(none, "sclk_hdmi27m", NULL, CLK_IS_ROOT, 27000000),
+	FRATE(none, "sclk_dptxphy", NULL, CLK_IS_ROOT, 24000000),
+	FRATE(none, "sclk_uhostphy", NULL, CLK_IS_ROOT, 48000000),
+};
+
+struct samsung_fixed_factor_clock exynos5250_fixed_factor_clks[] __initdata = {
+	FFACTOR(none, "fout_mplldiv2", "fout_mpll", 1, 2, 0),
+	FFACTOR(none, "fout_bplldiv2", "fout_bpll", 1, 2, 0),
+};
+
+struct samsung_mux_clock exynos5250_mux_clks[] __initdata = {
+	MUX(none, "mout_apll", mout_apll_p, SRC_CPU, 0, 1),
+	MUX(none, "mout_cpu", mout_cpu_p, SRC_CPU, 16, 1),
+	MUX(none, "mout_mpll_fout", mout_mpll_fout_p, PLL_DIV2_SEL, 4, 1),
+	MUX(none, "sclk_mpll", mout_mpll_p, SRC_CORE1, 8, 1),
+	MUX(none, "mout_bpll_fout", mout_bpll_fout_p, PLL_DIV2_SEL, 0, 1),
+	MUX(none, "sclk_bpll", mout_bpll_p, SRC_CDREX, 0, 1),
+	MUX(none, "mout_vpllsrc", mout_vpllsrc_p, SRC_TOP2, 0, 1),
+	MUX(none, "sclk_vpll", mout_vpll_p, SRC_TOP2, 16, 1),
+	MUX(none, "sclk_epll", mout_epll_p, SRC_TOP2, 12, 1),
+	MUX(none, "sclk_cpll", mout_cpll_p, SRC_TOP2, 8, 1),
+	MUX(none, "sclk_mpll_user", mout_mpll_user_p, SRC_TOP2, 20, 1),
+	MUX(none, "sclk_bpll_user", mout_bpll_user_p, SRC_TOP2, 24, 1),
+	MUX(none, "mout_aclk166", mout_aclk166_p, SRC_TOP0, 8, 1),
+	MUX(none, "mout_aclk333", mout_aclk166_p, SRC_TOP0, 16, 1),
+	MUX(none, "mout_aclk200", mout_aclk200_p, SRC_TOP0, 12, 1),
+	MUX(none, "mout_cam_bayer", mout_group1_p, SRC_GSCL, 12, 4),
+	MUX(none, "mout_cam0", mout_group1_p, SRC_GSCL, 16, 4),
+	MUX(none, "mout_cam1", mout_group1_p, SRC_GSCL, 20, 4),
+	MUX(none, "mout_gscl_wa", mout_group1_p, SRC_GSCL, 24, 4),
+	MUX(none, "mout_gscl_wb", mout_group1_p, SRC_GSCL, 28, 4),
+	MUX(none, "mout_fimd1", mout_group1_p, SRC_DISP1_0, 0, 4),
+	MUX(none, "mout_mipi1", mout_group1_p, SRC_DISP1_0, 12, 4),
+	MUX(none, "mout_dp", mout_group1_p, SRC_DISP1_0, 16, 4),
+	MUX(none, "mout_hdmi", mout_hdmi_p, SRC_DISP1_0, 20, 1),
+	MUX(none, "mout_audio0", mout_audio0_p, SRC_MAU, 0, 4),
+	MUX(none, "mout_mmc0", mout_group1_p, SRC_FSYS, 0, 4),
+	MUX(none, "mout_mmc1", mout_group1_p, SRC_FSYS, 4, 4),
+	MUX(none, "mout_mmc2", mout_group1_p, SRC_FSYS, 8, 4),
+	MUX(none, "mout_mmc3", mout_group1_p, SRC_FSYS, 12, 4),
+	MUX(none, "mout_sata", mout_aclk200_p, SRC_FSYS, 24, 1),
+	MUX(none, "mout_usb3", mout_usb3_p, SRC_FSYS, 28, 1),
+	MUX(none, "mout_jpeg", mout_group1_p, SRC_GEN, 0, 4),
+	MUX(none, "mout_uart0", mout_group1_p, SRC_PERIC0, 0, 4),
+	MUX(none, "mout_uart1", mout_group1_p, SRC_PERIC0, 4, 4),
+	MUX(none, "mout_uart2", mout_group1_p, SRC_PERIC0, 8, 4),
+	MUX(none, "mout_uart3", mout_group1_p, SRC_PERIC0, 12, 4),
+	MUX(none, "mout_pwm", mout_group1_p, SRC_PERIC0, 24, 4),
+	MUX(none, "mout_audio1", mout_audio1_p, SRC_PERIC1, 0, 4),
+	MUX(none, "mout_audio2", mout_audio2_p, SRC_PERIC1, 4, 4),
+	MUX(none, "mout_spdif", mout_spdif_p, SRC_PERIC1, 8, 2),
+	MUX(none, "mout_spi0", mout_group1_p, SRC_PERIC1, 16, 4),
+	MUX(none, "mout_spi1", mout_group1_p, SRC_PERIC1, 20, 4),
+	MUX(none, "mout_spi2", mout_group1_p, SRC_PERIC1, 24, 4),
+};
+
+struct samsung_div_clock exynos5250_div_clks[] __initdata = {
+	DIV(none, "div_arm", "mout_cpu", DIV_CPU0, 0, 3),
+	DIV(none, "sclk_apll", "mout_apll", DIV_CPU0, 24, 3),
+	DIV(none, "aclk66_pre", "sclk_mpll_user", DIV_TOP1, 24, 3),
+	DIV(none, "aclk66", "aclk66_pre", DIV_TOP0, 0, 3),
+	DIV(none, "aclk266", "sclk_mpll_user", DIV_TOP0, 16, 3),
+	DIV(none, "aclk166", "mout_aclk166", DIV_TOP0, 8, 3),
+	DIV(none, "aclk333", "mout_aclk333", DIV_TOP0, 20, 3),
+	DIV(none, "aclk200", "mout_aclk200", DIV_TOP0, 12, 3),
+	DIV(none, "div_cam_bayer", "mout_cam_bayer", DIV_GSCL, 12, 4),
+	DIV(none, "div_cam0", "mout_cam0", DIV_GSCL, 16, 4),
+	DIV(none, "div_cam1", "mout_cam1", DIV_GSCL, 20, 4),
+	DIV(none, "div_gscl_wa", "mout_gscl_wa", DIV_GSCL, 24, 4),
+	DIV(none, "div_gscl_wb", "mout_gscl_wb", DIV_GSCL, 28, 4),
+	DIV(none, "div_fimd1", "mout_fimd1", DIV_DISP1_0, 0, 4),
+	DIV(none, "div_mipi1", "mout_mipi1", DIV_DISP1_0, 16, 4),
+	DIV(none, "div_dp", "mout_dp", DIV_DISP1_0, 24, 4),
+	DIV(none, "div_jpeg", "mout_jpeg", DIV_GEN, 4, 4),
+	DIV(none, "div_audio0", "mout_audio0", DIV_MAU, 0, 4),
+	DIV(none, "div_pcm0", "sclk_audio0", DIV_MAU, 4, 8),
+	DIV(none, "div_sata", "mout_sata", DIV_FSYS0, 20, 4),
+	DIV(none, "div_usb3", "mout_usb3", DIV_FSYS0, 24, 4),
+	DIV(none, "div_mmc0", "mout_mmc0", DIV_FSYS1, 0, 4),
+	DIV(none, "div_mmc1", "mout_mmc1", DIV_FSYS1, 16, 4),
+	DIV(none, "div_mmc2", "mout_mmc2", DIV_FSYS2, 0, 4),
+	DIV(none, "div_mmc3", "mout_mmc3", DIV_FSYS2, 16, 4),
+	DIV(none, "div_uart0", "mout_uart0", DIV_PERIC0, 0, 4),
+	DIV(none, "div_uart1", "mout_uart1", DIV_PERIC0, 4, 4),
+	DIV(none, "div_uart2", "mout_uart2", DIV_PERIC0, 8, 4),
+	DIV(none, "div_uart3", "mout_uart3", DIV_PERIC0, 12, 4),
+	DIV(none, "div_spi0", "mout_spi0", DIV_PERIC1, 0, 4),
+	DIV(none, "div_spi1", "mout_spi1", DIV_PERIC1, 16, 4),
+	DIV(none, "div_spi2", "mout_spi2", DIV_PERIC2, 0, 4),
+	DIV(none, "div_pwm", "mout_pwm", DIV_PERIC3, 0, 4),
+	DIV(none, "div_audio1", "mout_audio1", DIV_PERIC4, 0, 4),
+	DIV(none, "div_pcm1", "sclk_audio1", DIV_PERIC4, 4, 8),
+	DIV(none, "div_audio2", "mout_audio2", DIV_PERIC4, 16, 4),
+	DIV(none, "div_pcm2", "sclk_audio2", DIV_PERIC4, 20, 8),
+	DIV(none, "div_i2s1", "sclk_audio1", DIV_PERIC5, 0, 6),
+	DIV(none, "div_i2s2", "sclk_audio2", DIV_PERIC5, 8, 6),
+	DIV(sclk_pixel, "div_hdmi_pixel", "sclk_vpll", DIV_DISP1_0, 28, 4),
+	DIV_A(none, "armclk", "div_arm", DIV_CPU0, 28, 3, "armclk"),
+	DIV_F(none, "div_mipi1_pre", "div_mipi1",
+			DIV_DISP1_0, 20, 4, CLK_SET_RATE_PARENT, 0),
+	DIV_F(none, "div_mmc_pre0", "div_mmc0",
+			DIV_FSYS1, 8, 8, CLK_SET_RATE_PARENT, 0),
+	DIV_F(none, "div_mmc_pre1", "div_mmc1",
+			DIV_FSYS1, 24, 8, CLK_SET_RATE_PARENT, 0),
+	DIV_F(none, "div_mmc_pre2", "div_mmc2",
+			DIV_FSYS2, 8, 8, CLK_SET_RATE_PARENT, 0),
+	DIV_F(none, "div_mmc_pre3", "div_mmc3",
+			DIV_FSYS2, 24, 8, CLK_SET_RATE_PARENT, 0),
+	DIV_F(none, "div_spi_pre0", "div_spi0",
+			DIV_PERIC1, 8, 8, CLK_SET_RATE_PARENT, 0),
+	DIV_F(none, "div_spi_pre1", "div_spi1",
+			DIV_PERIC1, 24, 8, CLK_SET_RATE_PARENT, 0),
+	DIV_F(none, "div_spi_pre2", "div_spi2",
+			DIV_PERIC2, 8, 8, CLK_SET_RATE_PARENT, 0),
+};
+
+struct samsung_gate_clock exynos5250_gate_clks[] __initdata = {
+	GATE(gscl0, "gscl0", "none", GATE_IP_GSCL, 0, 0, 0),
+	GATE(gscl1, "gscl1", "none", GATE_IP_GSCL, 1, 0, 0),
+	GATE(gscl2, "gscl2", "aclk266", GATE_IP_GSCL, 2, 0, 0),
+	GATE(gscl3, "gscl3", "aclk266", GATE_IP_GSCL, 3, 0, 0),
+	GATE(gscl_wa, "gscl_wa", "div_gscl_wa", GATE_IP_GSCL, 5, 0, 0),
+	GATE(gscl_wb, "gscl_wb", "div_gscl_wb", GATE_IP_GSCL, 6, 0, 0),
+	GATE(smmu_gscl0, "smmu_gscl0", "aclk266", GATE_IP_GSCL, 7, 0, 0),
+	GATE(smmu_gscl1, "smmu_gscl1", "aclk266", GATE_IP_GSCL, 8, 0, 0),
+	GATE(smmu_gscl2, "smmu_gscl2", "aclk266", GATE_IP_GSCL, 9, 0, 0),
+	GATE(smmu_gscl3, "smmu_gscl3", "aclk266", GATE_IP_GSCL, 10, 0, 0),
+	GATE(mfc, "mfc", "aclk333", GATE_IP_MFC, 0, 0, 0),
+	GATE(smmu_mfcl, "smmu_mfcl", "aclk333", GATE_IP_MFC, 1, 0, 0),
+	GATE(smmu_mfcr, "smmu_mfcr", "aclk333", GATE_IP_MFC, 2, 0, 0),
+	GATE(rotator, "rotator", "aclk266", GATE_IP_GEN, 1, 0, 0),
+	GATE(jpeg, "jpeg", "aclk166", GATE_IP_GEN, 2, 0, 0),
+	GATE(mdma1, "mdma1", "aclk266", GATE_IP_GEN, 4, 0, 0),
+	GATE(smmu_rotator, "smmu_rotator", "aclk266", GATE_IP_GEN, 6, 0, 0),
+	GATE(smmu_jpeg, "smmu_jpeg", "aclk166", GATE_IP_GEN, 7, 0, 0),
+	GATE(smmu_mdma1, "smmu_mdma1", "aclk266", GATE_IP_GEN, 9, 0, 0),
+	GATE(pdma0, "pdma0", "aclk200", GATE_IP_FSYS, 1, 0, 0),
+	GATE(pdma1, "pdma1", "aclk200", GATE_IP_FSYS, 2, 0, 0),
+	GATE(sata, "sata", "aclk200", GATE_IP_FSYS, 6, 0, 0),
+	GATE(usbotg, "usbotg", "aclk200", GATE_IP_FSYS, 7, 0, 0),
+	GATE(mipi_hsi, "mipi_hsi", "aclk200", GATE_IP_FSYS, 8, 0, 0),
+	GATE(sdmmc0, "sdmmc0", "aclk200", GATE_IP_FSYS, 12, 0, 0),
+	GATE(sdmmc1, "sdmmc1", "aclk200", GATE_IP_FSYS, 13, 0, 0),
+	GATE(sdmmc2, "sdmmc2", "aclk200", GATE_IP_FSYS, 14, 0, 0),
+	GATE(sdmmc3, "sdmmc3", "aclk200", GATE_IP_FSYS, 15, 0, 0),
+	GATE(sromc, "sromc", "aclk200", GATE_IP_FSYS, 17, 0, 0),
+	GATE(usb2, "usb2", "aclk200", GATE_IP_FSYS, 18, 0, 0),
+	GATE(usb3, "usb3", "aclk200", GATE_IP_FSYS, 19, 0, 0),
+	GATE(sata_phyctrl, "sata_phyctrl", "aclk200", GATE_IP_FSYS, 24, 0, 0),
+	GATE(sata_phyi2c, "sata_phyi2c", "aclk200", GATE_IP_FSYS, 25, 0, 0),
+	GATE(uart0, "uart0", "aclk66", GATE_IP_PERIC, 0, 0, 0),
+	GATE(uart1, "uart1", "aclk66", GATE_IP_PERIC, 1, 0, 0),
+	GATE(uart2, "uart2", "aclk66", GATE_IP_PERIC, 2, 0, 0),
+	GATE(uart3, "uart3", "aclk66", GATE_IP_PERIC, 3, 0, 0),
+	GATE(uart4, "uart4", "aclk66", GATE_IP_PERIC, 4, 0, 0),
+	GATE(i2c0, "i2c0", "aclk66", GATE_IP_PERIC, 6, 0, 0),
+	GATE(i2c1, "i2c1", "aclk66", GATE_IP_PERIC, 7, 0, 0),
+	GATE(i2c2, "i2c2", "aclk66", GATE_IP_PERIC, 8, 0, 0),
+	GATE(i2c3, "i2c3", "aclk66", GATE_IP_PERIC, 9, 0, 0),
+	GATE(i2c4, "i2c4", "aclk66", GATE_IP_PERIC, 10, 0, 0),
+	GATE(i2c5, "i2c5", "aclk66", GATE_IP_PERIC, 11, 0, 0),
+	GATE(i2c6, "i2c6", "aclk66", GATE_IP_PERIC, 12, 0, 0),
+	GATE(i2c7, "i2c7", "aclk66", GATE_IP_PERIC, 13, 0, 0),
+	GATE(i2c_hdmi, "i2c_hdmi", "aclk66", GATE_IP_PERIC, 14, 0, 0),
+	GATE(adc, "adc", "aclk66", GATE_IP_PERIC, 15, 0, 0),
+	GATE(spi0, "spi0", "aclk66", GATE_IP_PERIC, 16, 0, 0),
+	GATE(spi1, "spi1", "aclk66", GATE_IP_PERIC, 17, 0, 0),
+	GATE(spi2, "spi2", "aclk66", GATE_IP_PERIC, 18, 0, 0),
+	GATE(i2s1, "i2s1", "aclk66", GATE_IP_PERIC, 20, 0, 0),
+	GATE(i2s2, "i2s2", "aclk66", GATE_IP_PERIC, 21, 0, 0),
+	GATE(pcm1, "pcm1", "aclk66", GATE_IP_PERIC, 22, 0, 0),
+	GATE(pcm2, "pcm2", "aclk66", GATE_IP_PERIC, 23, 0, 0),
+	GATE(pwm, "pwm", "aclk66", GATE_IP_PERIC, 24, 0, 0),
+	GATE(spdif, "spdif", "aclk66", GATE_IP_PERIC, 26, 0, 0),
+	GATE(ac97, "ac97", "aclk66", GATE_IP_PERIC, 27, 0, 0),
+	GATE(hsi2c0, "hsi2c0", "aclk66", GATE_IP_PERIC, 28, 0, 0),
+	GATE(hsi2c1, "hsi2c1", "aclk66", GATE_IP_PERIC, 29, 0, 0),
+	GATE(hsi2c2, "hsi2c2", "aclk66", GATE_IP_PERIC, 30, 0, 0),
+	GATE(hsi2c3, "hsi2c3", "aclk66", GATE_IP_PERIC, 31, 0, 0),
+	GATE(chipid, "chipid", "aclk66", GATE_IP_PERIS, 0, 0, 0),
+	GATE(sysreg, "sysreg", "aclk66", GATE_IP_PERIS, 1, 0, 0),
+	GATE(pmu, "pmu", "aclk66", GATE_IP_PERIS, 2, 0, 0),
+	GATE(tzpc0, "tzpc0", "aclk66", GATE_IP_PERIS, 6, 0, 0),
+	GATE(tzpc1, "tzpc1", "aclk66", GATE_IP_PERIS, 7, 0, 0),
+	GATE(tzpc2, "tzpc2", "aclk66", GATE_IP_PERIS, 8, 0, 0),
+	GATE(tzpc3, "tzpc3", "aclk66", GATE_IP_PERIS, 9, 0, 0),
+	GATE(tzpc4, "tzpc4", "aclk66", GATE_IP_PERIS, 10, 0, 0),
+	GATE(tzpc5, "tzpc5", "aclk66", GATE_IP_PERIS, 11, 0, 0),
+	GATE(tzpc6, "tzpc6", "aclk66", GATE_IP_PERIS, 12, 0, 0),
+	GATE(tzpc7, "tzpc7", "aclk66", GATE_IP_PERIS, 13, 0, 0),
+	GATE(tzpc8, "tzpc8", "aclk66", GATE_IP_PERIS, 14, 0, 0),
+	GATE(tzpc9, "tzpc9", "aclk66", GATE_IP_PERIS, 15, 0, 0),
+	GATE(hdmi_cec, "hdmi_cec", "aclk66", GATE_IP_PERIS, 16, 0, 0),
+	GATE(mct, "mct", "aclk66", GATE_IP_PERIS, 18, 0, 0),
+	GATE(wdt, "wdt", "aclk66", GATE_IP_PERIS, 19, 0, 0),
+	GATE(rtc, "rtc", "aclk66", GATE_IP_PERIS, 20, 0, 0),
+	GATE(tmu, "tmu", "aclk66", GATE_IP_PERIS, 21, 0, 0),
+	GATE(cmu_top, "cmu_top", "aclk66",
+			GATE_IP_PERIS, 3, CLK_IGNORE_UNUSED, 0),
+	GATE(cmu_core, "cmu_core", "aclk66",
+			GATE_IP_PERIS, 4, CLK_IGNORE_UNUSED, 0),
+	GATE(cmu_mem, "cmu_mem", "aclk66",
+			GATE_IP_PERIS, 5, CLK_IGNORE_UNUSED, 0),
+	GATE(sclk_cam_bayer, "sclk_cam_bayer", "div_cam_bayer",
+			SRC_MASK_GSCL, 12, CLK_SET_RATE_PARENT, 0),
+	GATE(sclk_cam0, "sclk_cam0", "div_cam0",
+			SRC_MASK_GSCL, 16, CLK_SET_RATE_PARENT, 0),
+	GATE(sclk_cam1, "sclk_cam1", "div_cam1",
+			SRC_MASK_GSCL, 20, CLK_SET_RATE_PARENT, 0),
+	GATE(sclk_gscl_wa, "sclk_gscl_wa", "div_gscl_wa",
+			SRC_MASK_GSCL, 24, CLK_SET_RATE_PARENT, 0),
+	GATE(sclk_gscl_wb, "sclk_gscl_wb", "div_gscl_wb",
+			SRC_MASK_GSCL, 28, CLK_SET_RATE_PARENT, 0),
+	GATE(sclk_fimd1, "sclk_fimd1", "div_fimd1",
+			SRC_MASK_DISP1_0, 0, CLK_SET_RATE_PARENT, 0),
+	GATE(sclk_mipi1, "sclk_mipi1", "div_mipi1",
+			SRC_MASK_DISP1_0, 12, CLK_SET_RATE_PARENT, 0),
+	GATE(sclk_dp, "sclk_dp", "div_dp",
+			SRC_MASK_DISP1_0, 16, CLK_SET_RATE_PARENT, 0),
+	GATE(sclk_hdmi, "sclk_hdmi", "mout_hdmi",
+			SRC_MASK_DISP1_0, 20, 0, 0),
+	GATE(sclk_audio0, "sclk_audio0", "div_audio0",
+			SRC_MASK_MAU, 0, CLK_SET_RATE_PARENT, 0),
+	GATE(sclk_mmc0, "sclk_mmc0", "div_mmc0",
+			SRC_MASK_FSYS, 0, CLK_SET_RATE_PARENT, 0),
+	GATE(sclk_mmc1, "sclk_mmc1", "div_mmc1",
+			SRC_MASK_FSYS, 4, CLK_SET_RATE_PARENT, 0),
+	GATE(sclk_mmc2, "sclk_mmc2", "div_mmc2",
+			SRC_MASK_FSYS, 8, CLK_SET_RATE_PARENT, 0),
+	GATE(sclk_mmc3, "sclk_mmc3", "div_mmc3",
+			SRC_MASK_FSYS, 12, CLK_SET_RATE_PARENT, 0),
+	GATE(sclk_sata, "sclk_sata", "div_sata",
+			SRC_MASK_FSYS, 24, CLK_SET_RATE_PARENT, 0),
+	GATE(sclk_usb3, "sclk_usb3", "div_usb3",
+			SRC_MASK_FSYS, 28, CLK_SET_RATE_PARENT, 0),
+	GATE(sclk_jpeg, "sclk_jpeg", "div_jpeg",
+			SRC_MASK_GEN, 0, CLK_SET_RATE_PARENT, 0),
+	GATE(sclk_uart0, "sclk_uart0", "div_uart0",
+			SRC_MASK_PERIC0, 0, CLK_SET_RATE_PARENT, 0),
+	GATE(sclk_uart1, "sclk_uart1", "div_uart1",
+			SRC_MASK_PERIC0, 4, CLK_SET_RATE_PARENT, 0),
+	GATE(sclk_uart2, "sclk_uart2", "div_uart2",
+			SRC_MASK_PERIC0, 8, CLK_SET_RATE_PARENT, 0),
+	GATE(sclk_uart3, "sclk_uart3", "div_uart3",
+			SRC_MASK_PERIC0, 12, CLK_SET_RATE_PARENT, 0),
+	GATE(sclk_pwm, "sclk_pwm", "div_pwm",
+			SRC_MASK_PERIC0, 24, CLK_SET_RATE_PARENT, 0),
+	GATE(sclk_audio1, "sclk_audio1", "div_audio1",
+			SRC_MASK_PERIC1, 0, CLK_SET_RATE_PARENT, 0),
+	GATE(sclk_audio2, "sclk_audio2", "div_audio2",
+			SRC_MASK_PERIC1, 4, CLK_SET_RATE_PARENT, 0),
+	GATE(sclk_spdif, "sclk_spdif", "mout_spdif",
+			SRC_MASK_PERIC1, 4, 0, 0),
+	GATE(sclk_spi0, "sclk_spi0", "div_spi_pre0",
+			SRC_MASK_PERIC1, 16, CLK_SET_RATE_PARENT, 0),
+	GATE(sclk_spi1, "sclk_spi1", "div_spi_pre1",
+			SRC_MASK_PERIC1, 20, CLK_SET_RATE_PARENT, 0),
+	GATE(sclk_spi2, "sclk_spi2", "div_spi_pre2",
+			SRC_MASK_PERIC1, 24, CLK_SET_RATE_PARENT, 0),
+	GATE(fimd1, "fimd1", "aclk200", GATE_IP_DISP1, 0, 0, 0),
+	GATE(mie1, "mie1", "aclk200", GATE_IP_DISP1, 1, 0, 0),
+	GATE(dsim0, "dsim0", "aclk200", GATE_IP_DISP1, 3, 0, 0),
+	GATE(dp, "dp", "aclk200", GATE_IP_DISP1, 4, 0, 0),
+	GATE(mixer, "mixer", "aclk200", GATE_IP_DISP1, 5, 0, 0),
+	GATE(hdmi, "hdmi", "aclk200", GATE_IP_DISP1, 6, 0, 0),
+};
+
+static __initdata struct of_device_id ext_clk_match[] = {
+	{ .compatible = "samsung,clock-xxti", .data = (void *)0, },
+	{ },
+};
+
+/* register exynox5250 clocks */
+void __init exynos5250_clk_init(struct device_node *np)
+{
+	void __iomem *reg_base;
+	struct clk *apll, *mpll, *epll, *vpll, *bpll, *gpll, *cpll;
+
+	if (np) {
+		reg_base = of_iomap(np, 0);
+		if (!reg_base)
+			panic("%s: failed to map registers\n", __func__);
+	} else {
+		panic("%s: unable to determine soc\n", __func__);
+	}
+
+	samsung_clk_init(np, reg_base, nr_clks,
+			exynos5250_clk_regs, ARRAY_SIZE(exynos5250_clk_regs),
+			NULL, 0);
+	samsung_clk_of_register_fixed_ext(exynos5250_fixed_rate_ext_clks,
+			ARRAY_SIZE(exynos5250_fixed_rate_ext_clks),
+			ext_clk_match);
+
+	apll = samsung_clk_register_pll35xx("fout_apll", "fin_pll",
+			reg_base + 0x100);
+	mpll = samsung_clk_register_pll35xx("fout_mpll", "fin_pll",
+			reg_base + 0x4100);
+	bpll = samsung_clk_register_pll35xx("fout_bpll", "fin_pll",
+			reg_base + 0x20110);
+	gpll = samsung_clk_register_pll35xx("fout_gpll", "fin_pll",
+			reg_base + 0x10150);
+	cpll = samsung_clk_register_pll35xx("fout_cpll", "fin_pll",
+			reg_base + 0x10120);
+	epll = samsung_clk_register_pll36xx("fout_epll", "fin_pll",
+			reg_base + 0x10130);
+	vpll = samsung_clk_register_pll36xx("fout_vpll", "mout_vpllsrc",
+			reg_base + 0x10140);
+
+	samsung_clk_register_fixed_rate(exynos5250_fixed_rate_clks,
+			ARRAY_SIZE(exynos5250_fixed_rate_clks));
+	samsung_clk_register_fixed_factor(exynos5250_fixed_factor_clks,
+			ARRAY_SIZE(exynos5250_fixed_factor_clks));
+	samsung_clk_register_mux(exynos5250_mux_clks,
+			ARRAY_SIZE(exynos5250_mux_clks));
+	samsung_clk_register_div(exynos5250_div_clks,
+			ARRAY_SIZE(exynos5250_div_clks));
+	samsung_clk_register_gate(exynos5250_gate_clks,
+			ARRAY_SIZE(exynos5250_gate_clks));
+
+	pr_info("Exynos5250: clock setup completed, armclk=%ld\n",
+			_get_rate("armclk"));
+}
+CLK_OF_DECLARE(exynos5250_clk, "samsung,exynos5250-clock", exynos5250_clk_init);
diff --git a/drivers/clk/samsung/clk-exynos5440.c b/drivers/clk/samsung/clk-exynos5440.c
new file mode 100644
index 0000000..a0a094c
--- /dev/null
+++ b/drivers/clk/samsung/clk-exynos5440.c
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ * Author: Thomas Abraham <thomas.ab@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.
+ *
+ * Common Clock Framework support for Exynos5440 SoC.
+*/
+
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include <plat/cpu.h>
+#include "clk.h"
+#include "clk-pll.h"
+
+#define CLKEN_OV_VAL		0xf8
+#define CPU_CLK_STATUS		0xfc
+#define MISC_DOUT1		0x558
+
+/*
+ * Let each supported clock get a unique id. This id is used to lookup the clock
+ * for device tree based platforms.
+ */
+enum exynos5440_clks {
+	none, xtal, arm_clk,
+
+	spi_baud = 16, pb0_250, pr0_250, pr1_250, b_250, b_125, b_200, sata,
+	usb, gmac0, cs250, pb0_250_o, pr0_250_o, pr1_250_o, b_250_o, b_125_o,
+	b_200_o, sata_o, usb_o, gmac0_o, cs250_o,
+
+	nr_clks,
+};
+
+/* parent clock name list */
+PNAME(mout_armclk_p)	= { "cplla", "cpllb" };
+PNAME(mout_spi_p)	= { "div125", "div200" };
+
+/* fixed rate clocks generated outside the soc */
+struct samsung_fixed_rate_clock exynos5440_fixed_rate_ext_clks[] __initdata = {
+	FRATE(none, "xtal", NULL, CLK_IS_ROOT, 0),
+};
+
+/* fixed rate clocks */
+struct samsung_fixed_rate_clock exynos5440_fixed_rate_clks[] __initdata = {
+	FRATE(none, "ppll", NULL, CLK_IS_ROOT, 1000000000),
+	FRATE(none, "usb_phy0", NULL, CLK_IS_ROOT, 60000000),
+	FRATE(none, "usb_phy1", NULL, CLK_IS_ROOT, 60000000),
+	FRATE(none, "usb_ohci12", NULL, CLK_IS_ROOT, 12000000),
+	FRATE(none, "usb_ohci48", NULL, CLK_IS_ROOT, 48000000),
+};
+
+/* fixed factor clocks */
+struct samsung_fixed_factor_clock exynos5440_fixed_factor_clks[] __initdata = {
+	FFACTOR(none, "div250", "ppll", 1, 4, 0),
+	FFACTOR(none, "div200", "ppll", 1, 5, 0),
+	FFACTOR(none, "div125", "div250", 1, 2, 0),
+};
+
+/* mux clocks */
+struct samsung_mux_clock exynos5440_mux_clks[] __initdata = {
+	MUX(none, "mout_spi", mout_spi_p, MISC_DOUT1, 5, 1),
+	MUX_A(arm_clk, "arm_clk", mout_armclk_p,
+			CPU_CLK_STATUS, 0, 1, "armclk"),
+};
+
+/* divider clocks */
+struct samsung_div_clock exynos5440_div_clks[] __initdata = {
+	DIV(spi_baud, "div_spi", "mout_spi", MISC_DOUT1, 3, 2),
+};
+
+/* gate clocks */
+struct samsung_gate_clock exynos5440_gate_clks[] __initdata = {
+	GATE(pb0_250, "pb0_250", "div250", CLKEN_OV_VAL, 3, 0, 0),
+	GATE(pr0_250, "pr0_250", "div250", CLKEN_OV_VAL, 4, 0, 0),
+	GATE(pr1_250, "pr1_250", "div250", CLKEN_OV_VAL, 5, 0, 0),
+	GATE(b_250, "b_250", "div250", CLKEN_OV_VAL, 9, 0, 0),
+	GATE(b_125, "b_125", "div125", CLKEN_OV_VAL, 10, 0, 0),
+	GATE(b_200, "b_200", "div200", CLKEN_OV_VAL, 11, 0, 0),
+	GATE(sata, "sata", "div200", CLKEN_OV_VAL, 12, 0, 0),
+	GATE(usb, "usb", "div200", CLKEN_OV_VAL, 13, 0, 0),
+	GATE(gmac0, "gmac0", "div200", CLKEN_OV_VAL, 14, 0, 0),
+	GATE(cs250, "cs250", "div250", CLKEN_OV_VAL, 19, 0, 0),
+	GATE(pb0_250_o, "pb0_250_o", "pb0_250", CLKEN_OV_VAL, 3, 0, 0),
+	GATE(pr0_250_o, "pr0_250_o", "pr0_250", CLKEN_OV_VAL, 4, 0, 0),
+	GATE(pr1_250_o, "pr1_250_o", "pr1_250", CLKEN_OV_VAL, 5, 0, 0),
+	GATE(b_250_o, "b_250_o", "b_250", CLKEN_OV_VAL, 9, 0, 0),
+	GATE(b_125_o, "b_125_o", "b_125", CLKEN_OV_VAL, 10, 0, 0),
+	GATE(b_200_o, "b_200_o", "b_200", CLKEN_OV_VAL, 11, 0, 0),
+	GATE(sata_o, "sata_o", "sata", CLKEN_OV_VAL, 12, 0, 0),
+	GATE(usb_o, "usb_o", "usb", CLKEN_OV_VAL, 13, 0, 0),
+	GATE(gmac0_o, "gmac0_o", "gmac", CLKEN_OV_VAL, 14, 0, 0),
+	GATE(cs250_o, "cs250_o", "cs250", CLKEN_OV_VAL, 19, 0, 0),
+};
+
+static __initdata struct of_device_id ext_clk_match[] = {
+	{ .compatible = "samsung,clock-xtal", .data = (void *)0, },
+	{},
+};
+
+/* register exynos5440 clocks */
+void __init exynos5440_clk_init(struct device_node *np)
+{
+	void __iomem *reg_base;
+
+	reg_base = of_iomap(np, 0);
+	if (!reg_base) {
+		pr_err("%s: failed to map clock controller registers,"
+			" aborting clock initialization\n", __func__);
+		return;
+	}
+
+	samsung_clk_init(np, reg_base, nr_clks, NULL, 0, NULL, 0);
+	samsung_clk_of_register_fixed_ext(exynos5440_fixed_rate_ext_clks,
+		ARRAY_SIZE(exynos5440_fixed_rate_ext_clks), ext_clk_match);
+
+	samsung_clk_register_pll2550x("cplla", "xtal", reg_base + 0x1c, 0x10);
+	samsung_clk_register_pll2550x("cpllb", "xtal", reg_base + 0x20, 0x10);
+
+	samsung_clk_register_fixed_rate(exynos5440_fixed_rate_clks,
+			ARRAY_SIZE(exynos5440_fixed_rate_clks));
+	samsung_clk_register_fixed_factor(exynos5440_fixed_factor_clks,
+			ARRAY_SIZE(exynos5440_fixed_factor_clks));
+	samsung_clk_register_mux(exynos5440_mux_clks,
+			ARRAY_SIZE(exynos5440_mux_clks));
+	samsung_clk_register_div(exynos5440_div_clks,
+			ARRAY_SIZE(exynos5440_div_clks));
+	samsung_clk_register_gate(exynos5440_gate_clks,
+			ARRAY_SIZE(exynos5440_gate_clks));
+
+	pr_info("Exynos5440: arm_clk = %ldHz\n", _get_rate("armclk"));
+	pr_info("exynos5440 clock initialization complete\n");
+}
+CLK_OF_DECLARE(exynos5440_clk, "samsung,exynos5440-clock", exynos5440_clk_init);
diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c
new file mode 100644
index 0000000..89135f6
--- /dev/null
+++ b/drivers/clk/samsung/clk-pll.c
@@ -0,0 +1,419 @@
+/*
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2013 Linaro 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.
+ *
+ * This file contains the utility functions to register the pll clocks.
+*/
+
+#include <linux/errno.h>
+#include "clk.h"
+#include "clk-pll.h"
+
+/*
+ * PLL35xx Clock Type
+ */
+
+#define PLL35XX_MDIV_MASK       (0x3FF)
+#define PLL35XX_PDIV_MASK       (0x3F)
+#define PLL35XX_SDIV_MASK       (0x7)
+#define PLL35XX_MDIV_SHIFT      (16)
+#define PLL35XX_PDIV_SHIFT      (8)
+#define PLL35XX_SDIV_SHIFT      (0)
+
+struct samsung_clk_pll35xx {
+	struct clk_hw		hw;
+	const void __iomem	*con_reg;
+};
+
+#define to_clk_pll35xx(_hw) container_of(_hw, struct samsung_clk_pll35xx, hw)
+
+static unsigned long samsung_pll35xx_recalc_rate(struct clk_hw *hw,
+				unsigned long parent_rate)
+{
+	struct samsung_clk_pll35xx *pll = to_clk_pll35xx(hw);
+	u32 mdiv, pdiv, sdiv, pll_con;
+	u64 fvco = parent_rate;
+
+	pll_con = __raw_readl(pll->con_reg);
+	mdiv = (pll_con >> PLL35XX_MDIV_SHIFT) & PLL35XX_MDIV_MASK;
+	pdiv = (pll_con >> PLL35XX_PDIV_SHIFT) & PLL35XX_PDIV_MASK;
+	sdiv = (pll_con >> PLL35XX_SDIV_SHIFT) & PLL35XX_SDIV_MASK;
+
+	fvco *= mdiv;
+	do_div(fvco, (pdiv << sdiv));
+
+	return (unsigned long)fvco;
+}
+
+static const struct clk_ops samsung_pll35xx_clk_ops = {
+	.recalc_rate = samsung_pll35xx_recalc_rate,
+};
+
+struct clk * __init samsung_clk_register_pll35xx(const char *name,
+			const char *pname, const void __iomem *con_reg)
+{
+	struct samsung_clk_pll35xx *pll;
+	struct clk *clk;
+	struct clk_init_data init;
+
+	pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+	if (!pll) {
+		pr_err("%s: could not allocate pll clk %s\n", __func__, name);
+		return NULL;
+	}
+
+	init.name = name;
+	init.ops = &samsung_pll35xx_clk_ops;
+	init.flags = CLK_GET_RATE_NOCACHE;
+	init.parent_names = &pname;
+	init.num_parents = 1;
+
+	pll->hw.init = &init;
+	pll->con_reg = con_reg;
+
+	clk = clk_register(NULL, &pll->hw);
+	if (IS_ERR(clk)) {
+		pr_err("%s: failed to register pll clock %s\n", __func__,
+				name);
+		kfree(pll);
+	}
+
+	if (clk_register_clkdev(clk, name, NULL))
+		pr_err("%s: failed to register lookup for %s", __func__, name);
+
+	return clk;
+}
+
+/*
+ * PLL36xx Clock Type
+ */
+
+#define PLL36XX_KDIV_MASK	(0xFFFF)
+#define PLL36XX_MDIV_MASK	(0x1FF)
+#define PLL36XX_PDIV_MASK	(0x3F)
+#define PLL36XX_SDIV_MASK	(0x7)
+#define PLL36XX_MDIV_SHIFT	(16)
+#define PLL36XX_PDIV_SHIFT	(8)
+#define PLL36XX_SDIV_SHIFT	(0)
+
+struct samsung_clk_pll36xx {
+	struct clk_hw		hw;
+	const void __iomem	*con_reg;
+};
+
+#define to_clk_pll36xx(_hw) container_of(_hw, struct samsung_clk_pll36xx, hw)
+
+static unsigned long samsung_pll36xx_recalc_rate(struct clk_hw *hw,
+				unsigned long parent_rate)
+{
+	struct samsung_clk_pll36xx *pll = to_clk_pll36xx(hw);
+	u32 mdiv, pdiv, sdiv, kdiv, pll_con0, pll_con1;
+	u64 fvco = parent_rate;
+
+	pll_con0 = __raw_readl(pll->con_reg);
+	pll_con1 = __raw_readl(pll->con_reg + 4);
+	mdiv = (pll_con0 >> PLL36XX_MDIV_SHIFT) & PLL36XX_MDIV_MASK;
+	pdiv = (pll_con0 >> PLL36XX_PDIV_SHIFT) & PLL36XX_PDIV_MASK;
+	sdiv = (pll_con0 >> PLL36XX_SDIV_SHIFT) & PLL36XX_SDIV_MASK;
+	kdiv = pll_con1 & PLL36XX_KDIV_MASK;
+
+	fvco *= (mdiv << 16) + kdiv;
+	do_div(fvco, (pdiv << sdiv));
+	fvco >>= 16;
+
+	return (unsigned long)fvco;
+}
+
+static const struct clk_ops samsung_pll36xx_clk_ops = {
+	.recalc_rate = samsung_pll36xx_recalc_rate,
+};
+
+struct clk * __init samsung_clk_register_pll36xx(const char *name,
+			const char *pname, const void __iomem *con_reg)
+{
+	struct samsung_clk_pll36xx *pll;
+	struct clk *clk;
+	struct clk_init_data init;
+
+	pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+	if (!pll) {
+		pr_err("%s: could not allocate pll clk %s\n", __func__, name);
+		return NULL;
+	}
+
+	init.name = name;
+	init.ops = &samsung_pll36xx_clk_ops;
+	init.flags = CLK_GET_RATE_NOCACHE;
+	init.parent_names = &pname;
+	init.num_parents = 1;
+
+	pll->hw.init = &init;
+	pll->con_reg = con_reg;
+
+	clk = clk_register(NULL, &pll->hw);
+	if (IS_ERR(clk)) {
+		pr_err("%s: failed to register pll clock %s\n", __func__,
+				name);
+		kfree(pll);
+	}
+
+	if (clk_register_clkdev(clk, name, NULL))
+		pr_err("%s: failed to register lookup for %s", __func__, name);
+
+	return clk;
+}
+
+/*
+ * PLL45xx Clock Type
+ */
+
+#define PLL45XX_MDIV_MASK	(0x3FF)
+#define PLL45XX_PDIV_MASK	(0x3F)
+#define PLL45XX_SDIV_MASK	(0x7)
+#define PLL45XX_MDIV_SHIFT	(16)
+#define PLL45XX_PDIV_SHIFT	(8)
+#define PLL45XX_SDIV_SHIFT	(0)
+
+struct samsung_clk_pll45xx {
+	struct clk_hw		hw;
+	enum pll45xx_type	type;
+	const void __iomem	*con_reg;
+};
+
+#define to_clk_pll45xx(_hw) container_of(_hw, struct samsung_clk_pll45xx, hw)
+
+static unsigned long samsung_pll45xx_recalc_rate(struct clk_hw *hw,
+				unsigned long parent_rate)
+{
+	struct samsung_clk_pll45xx *pll = to_clk_pll45xx(hw);
+	u32 mdiv, pdiv, sdiv, pll_con;
+	u64 fvco = parent_rate;
+
+	pll_con = __raw_readl(pll->con_reg);
+	mdiv = (pll_con >> PLL45XX_MDIV_SHIFT) & PLL45XX_MDIV_MASK;
+	pdiv = (pll_con >> PLL45XX_PDIV_SHIFT) & PLL45XX_PDIV_MASK;
+	sdiv = (pll_con >> PLL45XX_SDIV_SHIFT) & PLL45XX_SDIV_MASK;
+
+	if (pll->type == pll_4508)
+		sdiv = sdiv - 1;
+
+	fvco *= mdiv;
+	do_div(fvco, (pdiv << sdiv));
+
+	return (unsigned long)fvco;
+}
+
+static const struct clk_ops samsung_pll45xx_clk_ops = {
+	.recalc_rate = samsung_pll45xx_recalc_rate,
+};
+
+struct clk * __init samsung_clk_register_pll45xx(const char *name,
+			const char *pname, const void __iomem *con_reg,
+			enum pll45xx_type type)
+{
+	struct samsung_clk_pll45xx *pll;
+	struct clk *clk;
+	struct clk_init_data init;
+
+	pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+	if (!pll) {
+		pr_err("%s: could not allocate pll clk %s\n", __func__, name);
+		return NULL;
+	}
+
+	init.name = name;
+	init.ops = &samsung_pll45xx_clk_ops;
+	init.flags = CLK_GET_RATE_NOCACHE;
+	init.parent_names = &pname;
+	init.num_parents = 1;
+
+	pll->hw.init = &init;
+	pll->con_reg = con_reg;
+	pll->type = type;
+
+	clk = clk_register(NULL, &pll->hw);
+	if (IS_ERR(clk)) {
+		pr_err("%s: failed to register pll clock %s\n", __func__,
+				name);
+		kfree(pll);
+	}
+
+	if (clk_register_clkdev(clk, name, NULL))
+		pr_err("%s: failed to register lookup for %s", __func__, name);
+
+	return clk;
+}
+
+/*
+ * PLL46xx Clock Type
+ */
+
+#define PLL46XX_MDIV_MASK	(0x1FF)
+#define PLL46XX_PDIV_MASK	(0x3F)
+#define PLL46XX_SDIV_MASK	(0x7)
+#define PLL46XX_MDIV_SHIFT	(16)
+#define PLL46XX_PDIV_SHIFT	(8)
+#define PLL46XX_SDIV_SHIFT	(0)
+
+#define PLL46XX_KDIV_MASK	(0xFFFF)
+#define PLL4650C_KDIV_MASK	(0xFFF)
+#define PLL46XX_KDIV_SHIFT	(0)
+
+struct samsung_clk_pll46xx {
+	struct clk_hw		hw;
+	enum pll46xx_type	type;
+	const void __iomem	*con_reg;
+};
+
+#define to_clk_pll46xx(_hw) container_of(_hw, struct samsung_clk_pll46xx, hw)
+
+static unsigned long samsung_pll46xx_recalc_rate(struct clk_hw *hw,
+				unsigned long parent_rate)
+{
+	struct samsung_clk_pll46xx *pll = to_clk_pll46xx(hw);
+	u32 mdiv, pdiv, sdiv, kdiv, pll_con0, pll_con1, shift;
+	u64 fvco = parent_rate;
+
+	pll_con0 = __raw_readl(pll->con_reg);
+	pll_con1 = __raw_readl(pll->con_reg + 4);
+	mdiv = (pll_con0 >> PLL46XX_MDIV_SHIFT) & PLL46XX_MDIV_MASK;
+	pdiv = (pll_con0 >> PLL46XX_PDIV_SHIFT) & PLL46XX_PDIV_MASK;
+	sdiv = (pll_con0 >> PLL46XX_SDIV_SHIFT) & PLL46XX_SDIV_MASK;
+	kdiv = pll->type == pll_4650c ? pll_con1 & PLL4650C_KDIV_MASK :
+					pll_con1 & PLL46XX_KDIV_MASK;
+
+	shift = pll->type == pll_4600 ? 16 : 10;
+	fvco *= (mdiv << shift) + kdiv;
+	do_div(fvco, (pdiv << sdiv));
+	fvco >>= shift;
+
+	return (unsigned long)fvco;
+}
+
+static const struct clk_ops samsung_pll46xx_clk_ops = {
+	.recalc_rate = samsung_pll46xx_recalc_rate,
+};
+
+struct clk * __init samsung_clk_register_pll46xx(const char *name,
+			const char *pname, const void __iomem *con_reg,
+			enum pll46xx_type type)
+{
+	struct samsung_clk_pll46xx *pll;
+	struct clk *clk;
+	struct clk_init_data init;
+
+	pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+	if (!pll) {
+		pr_err("%s: could not allocate pll clk %s\n", __func__, name);
+		return NULL;
+	}
+
+	init.name = name;
+	init.ops = &samsung_pll46xx_clk_ops;
+	init.flags = CLK_GET_RATE_NOCACHE;
+	init.parent_names = &pname;
+	init.num_parents = 1;
+
+	pll->hw.init = &init;
+	pll->con_reg = con_reg;
+	pll->type = type;
+
+	clk = clk_register(NULL, &pll->hw);
+	if (IS_ERR(clk)) {
+		pr_err("%s: failed to register pll clock %s\n", __func__,
+				name);
+		kfree(pll);
+	}
+
+	if (clk_register_clkdev(clk, name, NULL))
+		pr_err("%s: failed to register lookup for %s", __func__, name);
+
+	return clk;
+}
+
+/*
+ * PLL2550x Clock Type
+ */
+
+#define PLL2550X_R_MASK       (0x1)
+#define PLL2550X_P_MASK       (0x3F)
+#define PLL2550X_M_MASK       (0x3FF)
+#define PLL2550X_S_MASK       (0x7)
+#define PLL2550X_R_SHIFT      (20)
+#define PLL2550X_P_SHIFT      (14)
+#define PLL2550X_M_SHIFT      (4)
+#define PLL2550X_S_SHIFT      (0)
+
+struct samsung_clk_pll2550x {
+	struct clk_hw		hw;
+	const void __iomem	*reg_base;
+	unsigned long		offset;
+};
+
+#define to_clk_pll2550x(_hw) container_of(_hw, struct samsung_clk_pll2550x, hw)
+
+static unsigned long samsung_pll2550x_recalc_rate(struct clk_hw *hw,
+				unsigned long parent_rate)
+{
+	struct samsung_clk_pll2550x *pll = to_clk_pll2550x(hw);
+	u32 r, p, m, s, pll_stat;
+	u64 fvco = parent_rate;
+
+	pll_stat = __raw_readl(pll->reg_base + pll->offset * 3);
+	r = (pll_stat >> PLL2550X_R_SHIFT) & PLL2550X_R_MASK;
+	if (!r)
+		return 0;
+	p = (pll_stat >> PLL2550X_P_SHIFT) & PLL2550X_P_MASK;
+	m = (pll_stat >> PLL2550X_M_SHIFT) & PLL2550X_M_MASK;
+	s = (pll_stat >> PLL2550X_S_SHIFT) & PLL2550X_S_MASK;
+
+	fvco *= m;
+	do_div(fvco, (p << s));
+
+	return (unsigned long)fvco;
+}
+
+static const struct clk_ops samsung_pll2550x_clk_ops = {
+	.recalc_rate = samsung_pll2550x_recalc_rate,
+};
+
+struct clk * __init samsung_clk_register_pll2550x(const char *name,
+			const char *pname, const void __iomem *reg_base,
+			const unsigned long offset)
+{
+	struct samsung_clk_pll2550x *pll;
+	struct clk *clk;
+	struct clk_init_data init;
+
+	pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+	if (!pll) {
+		pr_err("%s: could not allocate pll clk %s\n", __func__, name);
+		return NULL;
+	}
+
+	init.name = name;
+	init.ops = &samsung_pll2550x_clk_ops;
+	init.flags = CLK_GET_RATE_NOCACHE;
+	init.parent_names = &pname;
+	init.num_parents = 1;
+
+	pll->hw.init = &init;
+	pll->reg_base = reg_base;
+	pll->offset = offset;
+
+	clk = clk_register(NULL, &pll->hw);
+	if (IS_ERR(clk)) {
+		pr_err("%s: failed to register pll clock %s\n", __func__,
+				name);
+		kfree(pll);
+	}
+
+	if (clk_register_clkdev(clk, name, NULL))
+		pr_err("%s: failed to register lookup for %s", __func__, name);
+
+	return clk;
+}
diff --git a/drivers/clk/samsung/clk-pll.h b/drivers/clk/samsung/clk-pll.h
new file mode 100644
index 0000000..f33786e
--- /dev/null
+++ b/drivers/clk/samsung/clk-pll.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2013 Linaro 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.
+ *
+ * Common Clock Framework support for all PLL's in Samsung platforms
+*/
+
+#ifndef __SAMSUNG_CLK_PLL_H
+#define __SAMSUNG_CLK_PLL_H
+
+enum pll45xx_type {
+	pll_4500,
+	pll_4502,
+	pll_4508
+};
+
+enum pll46xx_type {
+	pll_4600,
+	pll_4650,
+	pll_4650c,
+};
+
+extern struct clk * __init samsung_clk_register_pll35xx(const char *name,
+			const char *pname, const void __iomem *con_reg);
+extern struct clk * __init samsung_clk_register_pll36xx(const char *name,
+			const char *pname, const void __iomem *con_reg);
+extern struct clk * __init samsung_clk_register_pll45xx(const char *name,
+			const char *pname, const void __iomem *con_reg,
+			enum pll45xx_type type);
+extern struct clk * __init samsung_clk_register_pll46xx(const char *name,
+			const char *pname, const void __iomem *con_reg,
+			enum pll46xx_type type);
+extern struct clk * __init samsung_clk_register_pll2550x(const char *name,
+			const char *pname, const void __iomem *reg_base,
+			const unsigned long offset);
+
+#endif /* __SAMSUNG_CLK_PLL_H */
diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c
new file mode 100644
index 0000000..3a50d4f
--- /dev/null
+++ b/drivers/clk/samsung/clk.c
@@ -0,0 +1,318 @@
+/*
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2013 Linaro Ltd.
+ * Author: Thomas Abraham <thomas.ab@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.
+ *
+ * This file includes utility functions to register clocks to common
+ * clock framework for Samsung platforms.
+*/
+
+#include <linux/syscore_ops.h>
+#include "clk.h"
+
+static DEFINE_SPINLOCK(lock);
+static struct clk **clk_table;
+static void __iomem *reg_base;
+#ifdef CONFIG_OF
+static struct clk_onecell_data clk_data;
+#endif
+
+#ifdef CONFIG_PM_SLEEP
+static struct samsung_clk_reg_dump *reg_dump;
+static unsigned long nr_reg_dump;
+
+static int samsung_clk_suspend(void)
+{
+	struct samsung_clk_reg_dump *rd = reg_dump;
+	unsigned long i;
+
+	for (i = 0; i < nr_reg_dump; i++, rd++)
+		rd->value = __raw_readl(reg_base + rd->offset);
+
+	return 0;
+}
+
+static void samsung_clk_resume(void)
+{
+	struct samsung_clk_reg_dump *rd = reg_dump;
+	unsigned long i;
+
+	for (i = 0; i < nr_reg_dump; i++, rd++)
+		__raw_writel(rd->value, reg_base + rd->offset);
+}
+
+static struct syscore_ops samsung_clk_syscore_ops = {
+	.suspend	= samsung_clk_suspend,
+	.resume		= samsung_clk_resume,
+};
+#endif /* CONFIG_PM_SLEEP */
+
+/* setup the essentials required to support clock lookup using ccf */
+void __init samsung_clk_init(struct device_node *np, void __iomem *base,
+		unsigned long nr_clks, unsigned long *rdump,
+		unsigned long nr_rdump, unsigned long *soc_rdump,
+		unsigned long nr_soc_rdump)
+{
+	reg_base = base;
+
+#ifdef CONFIG_PM_SLEEP
+	if (rdump && nr_rdump) {
+		unsigned int idx;
+		reg_dump = kzalloc(sizeof(struct samsung_clk_reg_dump)
+				* (nr_rdump + nr_soc_rdump), GFP_KERNEL);
+		if (!reg_dump) {
+			pr_err("%s: memory alloc for register dump failed\n",
+					__func__);
+			return;
+		}
+
+		for (idx = 0; idx < nr_rdump; idx++)
+			reg_dump[idx].offset = rdump[idx];
+		for (idx = 0; idx < nr_soc_rdump; idx++)
+			reg_dump[nr_rdump + idx].offset = soc_rdump[idx];
+		nr_reg_dump = nr_rdump + nr_soc_rdump;
+		register_syscore_ops(&samsung_clk_syscore_ops);
+	}
+#endif
+
+	clk_table = kzalloc(sizeof(struct clk *) * nr_clks, GFP_KERNEL);
+	if (!clk_table)
+		panic("could not allocate clock lookup table\n");
+
+	if (!np)
+		return;
+
+#ifdef CONFIG_OF
+	clk_data.clks = clk_table;
+	clk_data.clk_num = nr_clks;
+	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+#endif
+}
+
+/* add a clock instance to the clock lookup table used for dt based lookup */
+void samsung_clk_add_lookup(struct clk *clk, unsigned int id)
+{
+	if (clk_table && id)
+		clk_table[id] = clk;
+}
+
+/* register a list of aliases */
+void __init samsung_clk_register_alias(struct samsung_clock_alias *list,
+					unsigned int nr_clk)
+{
+	struct clk *clk;
+	unsigned int idx, ret;
+
+	if (!clk_table) {
+		pr_err("%s: clock table missing\n", __func__);
+		return;
+	}
+
+	for (idx = 0; idx < nr_clk; idx++, list++) {
+		if (!list->id) {
+			pr_err("%s: clock id missing for index %d\n", __func__,
+				idx);
+			continue;
+		}
+
+		clk = clk_table[list->id];
+		if (!clk) {
+			pr_err("%s: failed to find clock %d\n", __func__,
+				list->id);
+			continue;
+		}
+
+		ret = clk_register_clkdev(clk, list->alias, list->dev_name);
+		if (ret)
+			pr_err("%s: failed to register lookup %s\n",
+					__func__, list->alias);
+	}
+}
+
+/* register a list of fixed clocks */
+void __init samsung_clk_register_fixed_rate(
+		struct samsung_fixed_rate_clock *list, unsigned int nr_clk)
+{
+	struct clk *clk;
+	unsigned int idx, ret;
+
+	for (idx = 0; idx < nr_clk; idx++, list++) {
+		clk = clk_register_fixed_rate(NULL, list->name,
+			list->parent_name, list->flags, list->fixed_rate);
+		if (IS_ERR(clk)) {
+			pr_err("%s: failed to register clock %s\n", __func__,
+				list->name);
+			continue;
+		}
+
+		samsung_clk_add_lookup(clk, list->id);
+
+		/*
+		 * Unconditionally add a clock lookup for the fixed rate clocks.
+		 * There are not many of these on any of Samsung platforms.
+		 */
+		ret = clk_register_clkdev(clk, list->name, NULL);
+		if (ret)
+			pr_err("%s: failed to register clock lookup for %s",
+				__func__, list->name);
+	}
+}
+
+/* register a list of fixed factor clocks */
+void __init samsung_clk_register_fixed_factor(
+		struct samsung_fixed_factor_clock *list, unsigned int nr_clk)
+{
+	struct clk *clk;
+	unsigned int idx;
+
+	for (idx = 0; idx < nr_clk; idx++, list++) {
+		clk = clk_register_fixed_factor(NULL, list->name,
+			list->parent_name, list->flags, list->mult, list->div);
+		if (IS_ERR(clk)) {
+			pr_err("%s: failed to register clock %s\n", __func__,
+				list->name);
+			continue;
+		}
+
+		samsung_clk_add_lookup(clk, list->id);
+	}
+}
+
+/* register a list of mux clocks */
+void __init samsung_clk_register_mux(struct samsung_mux_clock *list,
+					unsigned int nr_clk)
+{
+	struct clk *clk;
+	unsigned int idx, ret;
+
+	for (idx = 0; idx < nr_clk; idx++, list++) {
+		clk = clk_register_mux(NULL, list->name, list->parent_names,
+			list->num_parents, list->flags, reg_base + list->offset,
+			list->shift, list->width, list->mux_flags, &lock);
+		if (IS_ERR(clk)) {
+			pr_err("%s: failed to register clock %s\n", __func__,
+				list->name);
+			continue;
+		}
+
+		samsung_clk_add_lookup(clk, list->id);
+
+		/* register a clock lookup only if a clock alias is specified */
+		if (list->alias) {
+			ret = clk_register_clkdev(clk, list->alias,
+						list->dev_name);
+			if (ret)
+				pr_err("%s: failed to register lookup %s\n",
+						__func__, list->alias);
+		}
+	}
+}
+
+/* register a list of div clocks */
+void __init samsung_clk_register_div(struct samsung_div_clock *list,
+					unsigned int nr_clk)
+{
+	struct clk *clk;
+	unsigned int idx, ret;
+
+	for (idx = 0; idx < nr_clk; idx++, list++) {
+		if (list->table)
+			clk = clk_register_divider_table(NULL, list->name,
+					list->parent_name, list->flags,
+					reg_base + list->offset, list->shift,
+					list->width, list->div_flags,
+					list->table, &lock);
+		else
+			clk = clk_register_divider(NULL, list->name,
+					list->parent_name, list->flags,
+					reg_base + list->offset, list->shift,
+					list->width, list->div_flags, &lock);
+		if (IS_ERR(clk)) {
+			pr_err("%s: failed to register clock %s\n", __func__,
+				list->name);
+			continue;
+		}
+
+		samsung_clk_add_lookup(clk, list->id);
+
+		/* register a clock lookup only if a clock alias is specified */
+		if (list->alias) {
+			ret = clk_register_clkdev(clk, list->alias,
+						list->dev_name);
+			if (ret)
+				pr_err("%s: failed to register lookup %s\n",
+						__func__, list->alias);
+		}
+	}
+}
+
+/* register a list of gate clocks */
+void __init samsung_clk_register_gate(struct samsung_gate_clock *list,
+						unsigned int nr_clk)
+{
+	struct clk *clk;
+	unsigned int idx, ret;
+
+	for (idx = 0; idx < nr_clk; idx++, list++) {
+		clk = clk_register_gate(NULL, list->name, list->parent_name,
+				list->flags, reg_base + list->offset,
+				list->bit_idx, list->gate_flags, &lock);
+		if (IS_ERR(clk)) {
+			pr_err("%s: failed to register clock %s\n", __func__,
+				list->name);
+			continue;
+		}
+
+		/* register a clock lookup only if a clock alias is specified */
+		if (list->alias) {
+			ret = clk_register_clkdev(clk, list->alias,
+							list->dev_name);
+			if (ret)
+				pr_err("%s: failed to register lookup %s\n",
+					__func__, list->alias);
+		}
+
+		samsung_clk_add_lookup(clk, list->id);
+	}
+}
+
+/*
+ * obtain the clock speed of all external fixed clock sources from device
+ * tree and register it
+ */
+void __init samsung_clk_of_register_fixed_ext(
+			struct samsung_fixed_rate_clock *fixed_rate_clk,
+			unsigned int nr_fixed_rate_clk,
+			struct of_device_id *clk_matches)
+{
+	const struct of_device_id *match;
+	struct device_node *np;
+	u32 freq;
+
+	for_each_matching_node_and_match(np, clk_matches, &match) {
+		if (of_property_read_u32(np, "clock-frequency", &freq))
+			continue;
+		fixed_rate_clk[(u32)match->data].fixed_rate = freq;
+	}
+	samsung_clk_register_fixed_rate(fixed_rate_clk, nr_fixed_rate_clk);
+}
+
+/* utility function to get the rate of a specified clock */
+unsigned long _get_rate(const char *clk_name)
+{
+	struct clk *clk;
+	unsigned long rate;
+
+	clk = clk_get(NULL, clk_name);
+	if (IS_ERR(clk)) {
+		pr_err("%s: could not find clock %s\n", __func__, clk_name);
+		return 0;
+	}
+	rate = clk_get_rate(clk);
+	clk_put(clk);
+	return rate;
+}
diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h
new file mode 100644
index 0000000..10b2111
--- /dev/null
+++ b/drivers/clk/samsung/clk.h
@@ -0,0 +1,289 @@
+/*
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2013 Linaro Ltd.
+ * Author: Thomas Abraham <thomas.ab@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.
+ *
+ * Common Clock Framework support for all Samsung platforms
+*/
+
+#ifndef __SAMSUNG_CLK_H
+#define __SAMSUNG_CLK_H
+
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/io.h>
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include <mach/map.h>
+
+/**
+ * struct samsung_clock_alias: information about mux clock
+ * @id: platform specific id of the clock.
+ * @dev_name: name of the device to which this clock belongs.
+ * @alias: optional clock alias name to be assigned to this clock.
+ */
+struct samsung_clock_alias {
+	unsigned int		id;
+	const char		*dev_name;
+	const char		*alias;
+};
+
+#define ALIAS(_id, dname, a)	\
+	{							\
+		.id		= _id,				\
+		.dev_name	= dname,			\
+		.alias		= a,				\
+	}
+
+/**
+ * struct samsung_fixed_rate_clock: information about fixed-rate clock
+ * @id: platform specific id of the clock.
+ * @name: name of this fixed-rate clock.
+ * @parent_name: optional parent clock name.
+ * @flags: optional fixed-rate clock flags.
+ * @fixed-rate: fixed clock rate of this clock.
+ */
+struct samsung_fixed_rate_clock {
+	unsigned int		id;
+	char			*name;
+	const char		*parent_name;
+	unsigned long		flags;
+	unsigned long		fixed_rate;
+};
+
+#define FRATE(_id, cname, pname, f, frate)		\
+	{						\
+		.id		= _id,			\
+		.name		= cname,		\
+		.parent_name	= pname,		\
+		.flags		= f,			\
+		.fixed_rate	= frate,		\
+	}
+
+/*
+ * struct samsung_fixed_factor_clock: information about fixed-factor clock
+ * @id: platform specific id of the clock.
+ * @name: name of this fixed-factor clock.
+ * @parent_name: parent clock name.
+ * @mult: fixed multiplication factor.
+ * @div: fixed division factor.
+ * @flags: optional fixed-factor clock flags.
+ */
+struct samsung_fixed_factor_clock {
+	unsigned int		id;
+	char			*name;
+	const char		*parent_name;
+	unsigned long		mult;
+	unsigned long		div;
+	unsigned long		flags;
+};
+
+#define FFACTOR(_id, cname, pname, m, d, f)		\
+	{						\
+		.id		= _id,			\
+		.name		= cname,		\
+		.parent_name	= pname,		\
+		.mult		= m,			\
+		.div		= d,			\
+		.flags		= f,			\
+	}
+
+/**
+ * struct samsung_mux_clock: information about mux clock
+ * @id: platform specific id of the clock.
+ * @dev_name: name of the device to which this clock belongs.
+ * @name: name of this mux clock.
+ * @parent_names: array of pointer to parent clock names.
+ * @num_parents: number of parents listed in @parent_names.
+ * @flags: optional flags for basic clock.
+ * @offset: offset of the register for configuring the mux.
+ * @shift: starting bit location of the mux control bit-field in @reg.
+ * @width: width of the mux control bit-field in @reg.
+ * @mux_flags: flags for mux-type clock.
+ * @alias: optional clock alias name to be assigned to this clock.
+ */
+struct samsung_mux_clock {
+	unsigned int		id;
+	const char		*dev_name;
+	const char		*name;
+	const char		**parent_names;
+	u8			num_parents;
+	unsigned long		flags;
+	unsigned long		offset;
+	u8			shift;
+	u8			width;
+	u8			mux_flags;
+	const char		*alias;
+};
+
+#define __MUX(_id, dname, cname, pnames, o, s, w, f, mf, a)	\
+	{							\
+		.id		= _id,				\
+		.dev_name	= dname,			\
+		.name		= cname,			\
+		.parent_names	= pnames,			\
+		.num_parents	= ARRAY_SIZE(pnames),		\
+		.flags		= f,				\
+		.offset		= o,				\
+		.shift		= s,				\
+		.width		= w,				\
+		.mux_flags	= mf,				\
+		.alias		= a,				\
+	}
+
+#define MUX(_id, cname, pnames, o, s, w)			\
+	__MUX(_id, NULL, cname, pnames, o, s, w, 0, 0, NULL)
+
+#define MUX_A(_id, cname, pnames, o, s, w, a)			\
+	__MUX(_id, NULL, cname, pnames, o, s, w, 0, 0, a)
+
+#define MUX_F(_id, cname, pnames, o, s, w, f, mf)		\
+	__MUX(_id, NULL, cname, pnames, o, s, w, f, mf, NULL)
+
+/**
+ * @id: platform specific id of the clock.
+ * struct samsung_div_clock: information about div clock
+ * @dev_name: name of the device to which this clock belongs.
+ * @name: name of this div clock.
+ * @parent_name: name of the parent clock.
+ * @flags: optional flags for basic clock.
+ * @offset: offset of the register for configuring the div.
+ * @shift: starting bit location of the div control bit-field in @reg.
+ * @div_flags: flags for div-type clock.
+ * @alias: optional clock alias name to be assigned to this clock.
+ */
+struct samsung_div_clock {
+	unsigned int		id;
+	const char		*dev_name;
+	const char		*name;
+	const char		*parent_name;
+	unsigned long		flags;
+	unsigned long		offset;
+	u8			shift;
+	u8			width;
+	u8			div_flags;
+	const char		*alias;
+	struct clk_div_table	*table;
+};
+
+#define __DIV(_id, dname, cname, pname, o, s, w, f, df, a, t)	\
+	{							\
+		.id		= _id,				\
+		.dev_name	= dname,			\
+		.name		= cname,			\
+		.parent_name	= pname,			\
+		.flags		= f,				\
+		.offset		= o,				\
+		.shift		= s,				\
+		.width		= w,				\
+		.div_flags	= df,				\
+		.alias		= a,				\
+		.table		= t,				\
+	}
+
+#define DIV(_id, cname, pname, o, s, w)				\
+	__DIV(_id, NULL, cname, pname, o, s, w, 0, 0, NULL, NULL)
+
+#define DIV_A(_id, cname, pname, o, s, w, a)			\
+	__DIV(_id, NULL, cname, pname, o, s, w, 0, 0, a, NULL)
+
+#define DIV_F(_id, cname, pname, o, s, w, f, df)		\
+	__DIV(_id, NULL, cname, pname, o, s, w, f, df, NULL, NULL)
+
+#define DIV_T(_id, cname, pname, o, s, w, t)			\
+	__DIV(_id, NULL, cname, pname, o, s, w, 0, 0, NULL, t)
+
+/**
+ * struct samsung_gate_clock: information about gate clock
+ * @id: platform specific id of the clock.
+ * @dev_name: name of the device to which this clock belongs.
+ * @name: name of this gate clock.
+ * @parent_name: name of the parent clock.
+ * @flags: optional flags for basic clock.
+ * @offset: offset of the register for configuring the gate.
+ * @bit_idx: bit index of the gate control bit-field in @reg.
+ * @gate_flags: flags for gate-type clock.
+ * @alias: optional clock alias name to be assigned to this clock.
+ */
+struct samsung_gate_clock {
+	unsigned int		id;
+	const char		*dev_name;
+	const char		*name;
+	const char		*parent_name;
+	unsigned long		flags;
+	unsigned long		offset;
+	u8			bit_idx;
+	u8			gate_flags;
+	const char		*alias;
+};
+
+#define __GATE(_id, dname, cname, pname, o, b, f, gf, a)	\
+	{							\
+		.id		= _id,				\
+		.dev_name	= dname,			\
+		.name		= cname,			\
+		.parent_name	= pname,			\
+		.flags		= f,				\
+		.offset		= o,				\
+		.bit_idx	= b,				\
+		.gate_flags	= gf,				\
+		.alias		= a,				\
+	}
+
+#define GATE(_id, cname, pname, o, b, f, gf)			\
+	__GATE(_id, NULL, cname, pname, o, b, f, gf, NULL)
+
+#define GATE_A(_id, cname, pname, o, b, f, gf, a)		\
+	__GATE(_id, NULL, cname, pname, o, b, f, gf, a)
+
+#define GATE_D(_id, dname, cname, pname, o, b, f, gf)		\
+	__GATE(_id, dname, cname, pname, o, b, f, gf, NULL)
+
+#define GATE_DA(_id, dname, cname, pname, o, b, f, gf, a)	\
+	__GATE(_id, dname, cname, pname, o, b, f, gf, a)
+
+#define PNAME(x) static const char *x[] __initdata
+
+/**
+ * struct samsung_clk_reg_dump: register dump of clock controller registers.
+ * @offset: clock register offset from the controller base address.
+ * @value: the value to be register at offset.
+ */
+struct samsung_clk_reg_dump {
+	u32	offset;
+	u32	value;
+};
+
+extern void __init samsung_clk_init(struct device_node *np, void __iomem *base,
+		unsigned long nr_clks, unsigned long *rdump,
+		unsigned long nr_rdump, unsigned long *soc_rdump,
+		unsigned long nr_soc_rdump);
+extern void __init samsung_clk_of_register_fixed_ext(
+		struct samsung_fixed_rate_clock *fixed_rate_clk,
+		unsigned int nr_fixed_rate_clk,
+		struct of_device_id *clk_matches);
+
+extern void samsung_clk_add_lookup(struct clk *clk, unsigned int id);
+
+extern void samsung_clk_register_alias(struct samsung_clock_alias *list,
+		unsigned int nr_clk);
+extern void __init samsung_clk_register_fixed_rate(
+		struct samsung_fixed_rate_clock *clk_list, unsigned int nr_clk);
+extern void __init samsung_clk_register_fixed_factor(
+		struct samsung_fixed_factor_clock *list, unsigned int nr_clk);
+extern void __init samsung_clk_register_mux(struct samsung_mux_clock *clk_list,
+		unsigned int nr_clk);
+extern void __init samsung_clk_register_div(struct samsung_div_clock *clk_list,
+		unsigned int nr_clk);
+extern void __init samsung_clk_register_gate(
+		struct samsung_gate_clock *clk_list, unsigned int nr_clk);
+
+extern unsigned long _get_rate(const char *clk_name);
+
+#endif /* __SAMSUNG_CLK_H */
diff --git a/drivers/clk/spear/spear1310_clock.c b/drivers/clk/spear/spear1310_clock.c
index ed9af42..aedbbe1 100644
--- a/drivers/clk/spear/spear1310_clock.c
+++ b/drivers/clk/spear/spear1310_clock.c
@@ -17,12 +17,10 @@
 #include <linux/io.h>
 #include <linux/of_platform.h>
 #include <linux/spinlock_types.h>
-#include <mach/spear.h>
 #include "clk.h"
 
-#define VA_SPEAR1310_RAS_BASE			IOMEM(UL(0xFA400000))
 /* PLL related registers and bit values */
-#define SPEAR1310_PLL_CFG			(VA_MISC_BASE + 0x210)
+#define SPEAR1310_PLL_CFG			(misc_base + 0x210)
 	/* PLL_CFG bit values */
 	#define SPEAR1310_CLCD_SYNT_CLK_MASK		1
 	#define SPEAR1310_CLCD_SYNT_CLK_SHIFT		31
@@ -35,15 +33,15 @@
 	#define SPEAR1310_PLL2_CLK_SHIFT		22
 	#define SPEAR1310_PLL1_CLK_SHIFT		20
 
-#define SPEAR1310_PLL1_CTR			(VA_MISC_BASE + 0x214)
-#define SPEAR1310_PLL1_FRQ			(VA_MISC_BASE + 0x218)
-#define SPEAR1310_PLL2_CTR			(VA_MISC_BASE + 0x220)
-#define SPEAR1310_PLL2_FRQ			(VA_MISC_BASE + 0x224)
-#define SPEAR1310_PLL3_CTR			(VA_MISC_BASE + 0x22C)
-#define SPEAR1310_PLL3_FRQ			(VA_MISC_BASE + 0x230)
-#define SPEAR1310_PLL4_CTR			(VA_MISC_BASE + 0x238)
-#define SPEAR1310_PLL4_FRQ			(VA_MISC_BASE + 0x23C)
-#define SPEAR1310_PERIP_CLK_CFG			(VA_MISC_BASE + 0x244)
+#define SPEAR1310_PLL1_CTR			(misc_base + 0x214)
+#define SPEAR1310_PLL1_FRQ			(misc_base + 0x218)
+#define SPEAR1310_PLL2_CTR			(misc_base + 0x220)
+#define SPEAR1310_PLL2_FRQ			(misc_base + 0x224)
+#define SPEAR1310_PLL3_CTR			(misc_base + 0x22C)
+#define SPEAR1310_PLL3_FRQ			(misc_base + 0x230)
+#define SPEAR1310_PLL4_CTR			(misc_base + 0x238)
+#define SPEAR1310_PLL4_FRQ			(misc_base + 0x23C)
+#define SPEAR1310_PERIP_CLK_CFG			(misc_base + 0x244)
 	/* PERIP_CLK_CFG bit values */
 	#define SPEAR1310_GPT_OSC24_VAL			0
 	#define SPEAR1310_GPT_APB_VAL			1
@@ -65,7 +63,7 @@
 	#define SPEAR1310_C3_CLK_MASK			1
 	#define SPEAR1310_C3_CLK_SHIFT			1
 
-#define SPEAR1310_GMAC_CLK_CFG			(VA_MISC_BASE + 0x248)
+#define SPEAR1310_GMAC_CLK_CFG			(misc_base + 0x248)
 	#define SPEAR1310_GMAC_PHY_IF_SEL_MASK		3
 	#define SPEAR1310_GMAC_PHY_IF_SEL_SHIFT		4
 	#define SPEAR1310_GMAC_PHY_CLK_MASK		1
@@ -73,7 +71,7 @@
 	#define SPEAR1310_GMAC_PHY_INPUT_CLK_MASK	2
 	#define SPEAR1310_GMAC_PHY_INPUT_CLK_SHIFT	1
 
-#define SPEAR1310_I2S_CLK_CFG			(VA_MISC_BASE + 0x24C)
+#define SPEAR1310_I2S_CLK_CFG			(misc_base + 0x24C)
 	/* I2S_CLK_CFG register mask */
 	#define SPEAR1310_I2S_SCLK_X_MASK		0x1F
 	#define SPEAR1310_I2S_SCLK_X_SHIFT		27
@@ -91,21 +89,21 @@
 	#define SPEAR1310_I2S_SRC_CLK_MASK		2
 	#define SPEAR1310_I2S_SRC_CLK_SHIFT		0
 
-#define SPEAR1310_C3_CLK_SYNT			(VA_MISC_BASE + 0x250)
-#define SPEAR1310_UART_CLK_SYNT			(VA_MISC_BASE + 0x254)
-#define SPEAR1310_GMAC_CLK_SYNT			(VA_MISC_BASE + 0x258)
-#define SPEAR1310_SDHCI_CLK_SYNT		(VA_MISC_BASE + 0x25C)
-#define SPEAR1310_CFXD_CLK_SYNT			(VA_MISC_BASE + 0x260)
-#define SPEAR1310_ADC_CLK_SYNT			(VA_MISC_BASE + 0x264)
-#define SPEAR1310_AMBA_CLK_SYNT			(VA_MISC_BASE + 0x268)
-#define SPEAR1310_CLCD_CLK_SYNT			(VA_MISC_BASE + 0x270)
-#define SPEAR1310_RAS_CLK_SYNT0			(VA_MISC_BASE + 0x280)
-#define SPEAR1310_RAS_CLK_SYNT1			(VA_MISC_BASE + 0x288)
-#define SPEAR1310_RAS_CLK_SYNT2			(VA_MISC_BASE + 0x290)
-#define SPEAR1310_RAS_CLK_SYNT3			(VA_MISC_BASE + 0x298)
+#define SPEAR1310_C3_CLK_SYNT			(misc_base + 0x250)
+#define SPEAR1310_UART_CLK_SYNT			(misc_base + 0x254)
+#define SPEAR1310_GMAC_CLK_SYNT			(misc_base + 0x258)
+#define SPEAR1310_SDHCI_CLK_SYNT		(misc_base + 0x25C)
+#define SPEAR1310_CFXD_CLK_SYNT			(misc_base + 0x260)
+#define SPEAR1310_ADC_CLK_SYNT			(misc_base + 0x264)
+#define SPEAR1310_AMBA_CLK_SYNT			(misc_base + 0x268)
+#define SPEAR1310_CLCD_CLK_SYNT			(misc_base + 0x270)
+#define SPEAR1310_RAS_CLK_SYNT0			(misc_base + 0x280)
+#define SPEAR1310_RAS_CLK_SYNT1			(misc_base + 0x288)
+#define SPEAR1310_RAS_CLK_SYNT2			(misc_base + 0x290)
+#define SPEAR1310_RAS_CLK_SYNT3			(misc_base + 0x298)
 	/* Check Fractional synthesizer reg masks */
 
-#define SPEAR1310_PERIP1_CLK_ENB		(VA_MISC_BASE + 0x300)
+#define SPEAR1310_PERIP1_CLK_ENB		(misc_base + 0x300)
 	/* PERIP1_CLK_ENB register masks */
 	#define SPEAR1310_RTC_CLK_ENB			31
 	#define SPEAR1310_ADC_CLK_ENB			30
@@ -138,7 +136,7 @@
 	#define SPEAR1310_SYSROM_CLK_ENB		1
 	#define SPEAR1310_BUS_CLK_ENB			0
 
-#define SPEAR1310_PERIP2_CLK_ENB		(VA_MISC_BASE + 0x304)
+#define SPEAR1310_PERIP2_CLK_ENB		(misc_base + 0x304)
 	/* PERIP2_CLK_ENB register masks */
 	#define SPEAR1310_THSENS_CLK_ENB		8
 	#define SPEAR1310_I2S_REF_PAD_CLK_ENB		7
@@ -150,7 +148,7 @@
 	#define SPEAR1310_DDR_CORE_CLK_ENB		1
 	#define SPEAR1310_DDR_CTRL_CLK_ENB		0
 
-#define SPEAR1310_RAS_CLK_ENB			(VA_MISC_BASE + 0x310)
+#define SPEAR1310_RAS_CLK_ENB			(misc_base + 0x310)
 	/* RAS_CLK_ENB register masks */
 	#define SPEAR1310_SYNT3_CLK_ENB			17
 	#define SPEAR1310_SYNT2_CLK_ENB			16
@@ -172,7 +170,7 @@
 	#define SPEAR1310_ACLK_CLK_ENB			0
 
 /* RAS Area Control Register */
-#define SPEAR1310_RAS_CTRL_REG0			(VA_SPEAR1310_RAS_BASE + 0x000)
+#define SPEAR1310_RAS_CTRL_REG0			(ras_base + 0x000)
 	#define SPEAR1310_SSP1_CLK_MASK			3
 	#define SPEAR1310_SSP1_CLK_SHIFT		26
 	#define SPEAR1310_TDM_CLK_MASK			1
@@ -197,12 +195,12 @@
 	#define SPEAR1310_PCI_CLK_MASK			1
 	#define SPEAR1310_PCI_CLK_SHIFT			0
 
-#define SPEAR1310_RAS_CTRL_REG1			(VA_SPEAR1310_RAS_BASE + 0x004)
+#define SPEAR1310_RAS_CTRL_REG1			(ras_base + 0x004)
 	#define SPEAR1310_PHY_CLK_MASK			0x3
 	#define SPEAR1310_RMII_PHY_CLK_SHIFT		0
 	#define SPEAR1310_SMII_RGMII_PHY_CLK_SHIFT	2
 
-#define SPEAR1310_RAS_SW_CLK_CTRL		(VA_SPEAR1310_RAS_BASE + 0x0148)
+#define SPEAR1310_RAS_SW_CLK_CTRL		(ras_base + 0x0148)
 	#define SPEAR1310_CAN1_CLK_ENB			25
 	#define SPEAR1310_CAN0_CLK_ENB			24
 	#define SPEAR1310_GPT64_CLK_ENB			23
@@ -385,7 +383,7 @@ static const char *ssp1_parents[] = { "ras_apb_clk", "gen_syn1_clk",
 static const char *pci_parents[] = { "ras_pll3_clk", "gen_syn2_clk", };
 static const char *tdm_parents[] = { "ras_pll3_clk", "gen_syn1_clk", };
 
-void __init spear1310_clk_init(void)
+void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base)
 {
 	struct clk *clk, *clk1;
 
diff --git a/drivers/clk/spear/spear1340_clock.c b/drivers/clk/spear/spear1340_clock.c
index 82abea3..9d0b394 100644
--- a/drivers/clk/spear/spear1340_clock.c
+++ b/drivers/clk/spear/spear1340_clock.c
@@ -17,18 +17,17 @@
 #include <linux/io.h>
 #include <linux/of_platform.h>
 #include <linux/spinlock_types.h>
-#include <mach/spear.h>
 #include "clk.h"
 
 /* Clock Configuration Registers */
-#define SPEAR1340_SYS_CLK_CTRL			(VA_MISC_BASE + 0x200)
+#define SPEAR1340_SYS_CLK_CTRL			(misc_base + 0x200)
 	#define SPEAR1340_HCLK_SRC_SEL_SHIFT	27
 	#define SPEAR1340_HCLK_SRC_SEL_MASK	1
 	#define SPEAR1340_SCLK_SRC_SEL_SHIFT	23
 	#define SPEAR1340_SCLK_SRC_SEL_MASK	3
 
 /* PLL related registers and bit values */
-#define SPEAR1340_PLL_CFG			(VA_MISC_BASE + 0x210)
+#define SPEAR1340_PLL_CFG			(misc_base + 0x210)
 	/* PLL_CFG bit values */
 	#define SPEAR1340_CLCD_SYNT_CLK_MASK		1
 	#define SPEAR1340_CLCD_SYNT_CLK_SHIFT		31
@@ -40,15 +39,15 @@
 	#define SPEAR1340_PLL2_CLK_SHIFT		22
 	#define SPEAR1340_PLL1_CLK_SHIFT		20
 
-#define SPEAR1340_PLL1_CTR			(VA_MISC_BASE + 0x214)
-#define SPEAR1340_PLL1_FRQ			(VA_MISC_BASE + 0x218)
-#define SPEAR1340_PLL2_CTR			(VA_MISC_BASE + 0x220)
-#define SPEAR1340_PLL2_FRQ			(VA_MISC_BASE + 0x224)
-#define SPEAR1340_PLL3_CTR			(VA_MISC_BASE + 0x22C)
-#define SPEAR1340_PLL3_FRQ			(VA_MISC_BASE + 0x230)
-#define SPEAR1340_PLL4_CTR			(VA_MISC_BASE + 0x238)
-#define SPEAR1340_PLL4_FRQ			(VA_MISC_BASE + 0x23C)
-#define SPEAR1340_PERIP_CLK_CFG			(VA_MISC_BASE + 0x244)
+#define SPEAR1340_PLL1_CTR			(misc_base + 0x214)
+#define SPEAR1340_PLL1_FRQ			(misc_base + 0x218)
+#define SPEAR1340_PLL2_CTR			(misc_base + 0x220)
+#define SPEAR1340_PLL2_FRQ			(misc_base + 0x224)
+#define SPEAR1340_PLL3_CTR			(misc_base + 0x22C)
+#define SPEAR1340_PLL3_FRQ			(misc_base + 0x230)
+#define SPEAR1340_PLL4_CTR			(misc_base + 0x238)
+#define SPEAR1340_PLL4_FRQ			(misc_base + 0x23C)
+#define SPEAR1340_PERIP_CLK_CFG			(misc_base + 0x244)
 	/* PERIP_CLK_CFG bit values */
 	#define SPEAR1340_SPDIF_CLK_MASK		1
 	#define SPEAR1340_SPDIF_OUT_CLK_SHIFT		15
@@ -66,13 +65,13 @@
 	#define SPEAR1340_C3_CLK_MASK			1
 	#define SPEAR1340_C3_CLK_SHIFT			1
 
-#define SPEAR1340_GMAC_CLK_CFG			(VA_MISC_BASE + 0x248)
+#define SPEAR1340_GMAC_CLK_CFG			(misc_base + 0x248)
 	#define SPEAR1340_GMAC_PHY_CLK_MASK		1
 	#define SPEAR1340_GMAC_PHY_CLK_SHIFT		2
 	#define SPEAR1340_GMAC_PHY_INPUT_CLK_MASK	2
 	#define SPEAR1340_GMAC_PHY_INPUT_CLK_SHIFT	0
 
-#define SPEAR1340_I2S_CLK_CFG			(VA_MISC_BASE + 0x24C)
+#define SPEAR1340_I2S_CLK_CFG			(misc_base + 0x24C)
 	/* I2S_CLK_CFG register mask */
 	#define SPEAR1340_I2S_SCLK_X_MASK		0x1F
 	#define SPEAR1340_I2S_SCLK_X_SHIFT		27
@@ -90,21 +89,21 @@
 	#define SPEAR1340_I2S_SRC_CLK_MASK		2
 	#define SPEAR1340_I2S_SRC_CLK_SHIFT		0
 
-#define SPEAR1340_C3_CLK_SYNT			(VA_MISC_BASE + 0x250)
-#define SPEAR1340_UART0_CLK_SYNT		(VA_MISC_BASE + 0x254)
-#define SPEAR1340_UART1_CLK_SYNT		(VA_MISC_BASE + 0x258)
-#define SPEAR1340_GMAC_CLK_SYNT			(VA_MISC_BASE + 0x25C)
-#define SPEAR1340_SDHCI_CLK_SYNT		(VA_MISC_BASE + 0x260)
-#define SPEAR1340_CFXD_CLK_SYNT			(VA_MISC_BASE + 0x264)
-#define SPEAR1340_ADC_CLK_SYNT			(VA_MISC_BASE + 0x270)
-#define SPEAR1340_AMBA_CLK_SYNT			(VA_MISC_BASE + 0x274)
-#define SPEAR1340_CLCD_CLK_SYNT			(VA_MISC_BASE + 0x27C)
-#define SPEAR1340_SYS_CLK_SYNT			(VA_MISC_BASE + 0x284)
-#define SPEAR1340_GEN_CLK_SYNT0			(VA_MISC_BASE + 0x28C)
-#define SPEAR1340_GEN_CLK_SYNT1			(VA_MISC_BASE + 0x294)
-#define SPEAR1340_GEN_CLK_SYNT2			(VA_MISC_BASE + 0x29C)
-#define SPEAR1340_GEN_CLK_SYNT3			(VA_MISC_BASE + 0x304)
-#define SPEAR1340_PERIP1_CLK_ENB		(VA_MISC_BASE + 0x30C)
+#define SPEAR1340_C3_CLK_SYNT			(misc_base + 0x250)
+#define SPEAR1340_UART0_CLK_SYNT		(misc_base + 0x254)
+#define SPEAR1340_UART1_CLK_SYNT		(misc_base + 0x258)
+#define SPEAR1340_GMAC_CLK_SYNT			(misc_base + 0x25C)
+#define SPEAR1340_SDHCI_CLK_SYNT		(misc_base + 0x260)
+#define SPEAR1340_CFXD_CLK_SYNT			(misc_base + 0x264)
+#define SPEAR1340_ADC_CLK_SYNT			(misc_base + 0x270)
+#define SPEAR1340_AMBA_CLK_SYNT			(misc_base + 0x274)
+#define SPEAR1340_CLCD_CLK_SYNT			(misc_base + 0x27C)
+#define SPEAR1340_SYS_CLK_SYNT			(misc_base + 0x284)
+#define SPEAR1340_GEN_CLK_SYNT0			(misc_base + 0x28C)
+#define SPEAR1340_GEN_CLK_SYNT1			(misc_base + 0x294)
+#define SPEAR1340_GEN_CLK_SYNT2			(misc_base + 0x29C)
+#define SPEAR1340_GEN_CLK_SYNT3			(misc_base + 0x304)
+#define SPEAR1340_PERIP1_CLK_ENB		(misc_base + 0x30C)
 	#define SPEAR1340_RTC_CLK_ENB			31
 	#define SPEAR1340_ADC_CLK_ENB			30
 	#define SPEAR1340_C3_CLK_ENB			29
@@ -133,7 +132,7 @@
 	#define SPEAR1340_SYSROM_CLK_ENB		1
 	#define SPEAR1340_BUS_CLK_ENB			0
 
-#define SPEAR1340_PERIP2_CLK_ENB		(VA_MISC_BASE + 0x310)
+#define SPEAR1340_PERIP2_CLK_ENB		(misc_base + 0x310)
 	#define SPEAR1340_THSENS_CLK_ENB		8
 	#define SPEAR1340_I2S_REF_PAD_CLK_ENB		7
 	#define SPEAR1340_ACP_CLK_ENB			6
@@ -144,7 +143,7 @@
 	#define SPEAR1340_DDR_CORE_CLK_ENB		1
 	#define SPEAR1340_DDR_CTRL_CLK_ENB		0
 
-#define SPEAR1340_PERIP3_CLK_ENB		(VA_MISC_BASE + 0x314)
+#define SPEAR1340_PERIP3_CLK_ENB		(misc_base + 0x314)
 	#define SPEAR1340_PLGPIO_CLK_ENB		18
 	#define SPEAR1340_VIDEO_DEC_CLK_ENB		16
 	#define SPEAR1340_VIDEO_ENC_CLK_ENB		15
@@ -441,7 +440,7 @@ static const char *gen_synth0_1_parents[] = { "vco1div4_clk", "vco3div2_clk",
 static const char *gen_synth2_3_parents[] = { "vco1div4_clk", "vco2div2_clk",
 	"pll2_clk", };
 
-void __init spear1340_clk_init(void)
+void __init spear1340_clk_init(void __iomem *misc_base)
 {
 	struct clk *clk, *clk1;
 
@@ -960,47 +959,47 @@ void __init spear1340_clk_init(void)
 			SPEAR1340_SPDIF_IN_CLK_ENB, 0, &_lock);
 	clk_register_clkdev(clk, NULL, "d0100000.spdif-in");
 
-	clk = clk_register_gate(NULL, "acp_clk", "acp_mclk", 0,
+	clk = clk_register_gate(NULL, "acp_clk", "ahb_clk", 0,
 			SPEAR1340_PERIP2_CLK_ENB, SPEAR1340_ACP_CLK_ENB, 0,
 			&_lock);
 	clk_register_clkdev(clk, NULL, "acp_clk");
 
-	clk = clk_register_gate(NULL, "plgpio_clk", "plgpio_mclk", 0,
+	clk = clk_register_gate(NULL, "plgpio_clk", "ahb_clk", 0,
 			SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_PLGPIO_CLK_ENB, 0,
 			&_lock);
 	clk_register_clkdev(clk, NULL, "e2800000.gpio");
 
-	clk = clk_register_gate(NULL, "video_dec_clk", "video_dec_mclk", 0,
+	clk = clk_register_gate(NULL, "video_dec_clk", "ahb_clk", 0,
 			SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_VIDEO_DEC_CLK_ENB,
 			0, &_lock);
 	clk_register_clkdev(clk, NULL, "video_dec");
 
-	clk = clk_register_gate(NULL, "video_enc_clk", "video_enc_mclk", 0,
+	clk = clk_register_gate(NULL, "video_enc_clk", "ahb_clk", 0,
 			SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_VIDEO_ENC_CLK_ENB,
 			0, &_lock);
 	clk_register_clkdev(clk, NULL, "video_enc");
 
-	clk = clk_register_gate(NULL, "video_in_clk", "video_in_mclk", 0,
+	clk = clk_register_gate(NULL, "video_in_clk", "ahb_clk", 0,
 			SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_VIDEO_IN_CLK_ENB, 0,
 			&_lock);
 	clk_register_clkdev(clk, NULL, "spear_vip");
 
-	clk = clk_register_gate(NULL, "cam0_clk", "cam0_mclk", 0,
+	clk = clk_register_gate(NULL, "cam0_clk", "ahb_clk", 0,
 			SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_CAM0_CLK_ENB, 0,
 			&_lock);
 	clk_register_clkdev(clk, NULL, "d0200000.cam0");
 
-	clk = clk_register_gate(NULL, "cam1_clk", "cam1_mclk", 0,
+	clk = clk_register_gate(NULL, "cam1_clk", "ahb_clk", 0,
 			SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_CAM1_CLK_ENB, 0,
 			&_lock);
 	clk_register_clkdev(clk, NULL, "d0300000.cam1");
 
-	clk = clk_register_gate(NULL, "cam2_clk", "cam2_mclk", 0,
+	clk = clk_register_gate(NULL, "cam2_clk", "ahb_clk", 0,
 			SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_CAM2_CLK_ENB, 0,
 			&_lock);
 	clk_register_clkdev(clk, NULL, "d0400000.cam2");
 
-	clk = clk_register_gate(NULL, "cam3_clk", "cam3_mclk", 0,
+	clk = clk_register_gate(NULL, "cam3_clk", "ahb_clk", 0,
 			SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_CAM3_CLK_ENB, 0,
 			&_lock);
 	clk_register_clkdev(clk, NULL, "d0500000.cam3");
diff --git a/drivers/clk/spear/spear3xx_clock.c b/drivers/clk/spear/spear3xx_clock.c
index 33d3ac5..f9ec43f 100644
--- a/drivers/clk/spear/spear3xx_clock.c
+++ b/drivers/clk/spear/spear3xx_clock.c
@@ -15,21 +15,20 @@
 #include <linux/io.h>
 #include <linux/of_platform.h>
 #include <linux/spinlock_types.h>
-#include <mach/misc_regs.h>
 #include "clk.h"
 
 static DEFINE_SPINLOCK(_lock);
 
-#define PLL1_CTR			(MISC_BASE + 0x008)
-#define PLL1_FRQ			(MISC_BASE + 0x00C)
-#define PLL2_CTR			(MISC_BASE + 0x014)
-#define PLL2_FRQ			(MISC_BASE + 0x018)
-#define PLL_CLK_CFG			(MISC_BASE + 0x020)
+#define PLL1_CTR			(misc_base + 0x008)
+#define PLL1_FRQ			(misc_base + 0x00C)
+#define PLL2_CTR			(misc_base + 0x014)
+#define PLL2_FRQ			(misc_base + 0x018)
+#define PLL_CLK_CFG			(misc_base + 0x020)
 	/* PLL_CLK_CFG register masks */
 	#define MCTR_CLK_SHIFT		28
 	#define MCTR_CLK_MASK		3
 
-#define CORE_CLK_CFG			(MISC_BASE + 0x024)
+#define CORE_CLK_CFG			(misc_base + 0x024)
 	/* CORE CLK CFG register masks */
 	#define GEN_SYNTH2_3_CLK_SHIFT	18
 	#define GEN_SYNTH2_3_CLK_MASK	1
@@ -39,7 +38,7 @@ static DEFINE_SPINLOCK(_lock);
 	#define PCLK_RATIO_SHIFT	8
 	#define PCLK_RATIO_MASK		2
 
-#define PERIP_CLK_CFG			(MISC_BASE + 0x028)
+#define PERIP_CLK_CFG			(misc_base + 0x028)
 	/* PERIP_CLK_CFG register masks */
 	#define UART_CLK_SHIFT		4
 	#define UART_CLK_MASK		1
@@ -50,7 +49,7 @@ static DEFINE_SPINLOCK(_lock);
 	#define GPT2_CLK_SHIFT		12
 	#define GPT_CLK_MASK		1
 
-#define PERIP1_CLK_ENB			(MISC_BASE + 0x02C)
+#define PERIP1_CLK_ENB			(misc_base + 0x02C)
 	/* PERIP1_CLK_ENB register masks */
 	#define UART_CLK_ENB		3
 	#define SSP_CLK_ENB		5
@@ -69,7 +68,7 @@ static DEFINE_SPINLOCK(_lock);
 	#define USBH_CLK_ENB		25
 	#define C3_CLK_ENB		31
 
-#define RAS_CLK_ENB			(MISC_BASE + 0x034)
+#define RAS_CLK_ENB			(misc_base + 0x034)
 	#define RAS_AHB_CLK_ENB		0
 	#define RAS_PLL1_CLK_ENB	1
 	#define RAS_APB_CLK_ENB		2
@@ -82,20 +81,20 @@ static DEFINE_SPINLOCK(_lock);
 	#define RAS_SYNT2_CLK_ENB	10
 	#define RAS_SYNT3_CLK_ENB	11
 
-#define PRSC0_CLK_CFG			(MISC_BASE + 0x044)
-#define PRSC1_CLK_CFG			(MISC_BASE + 0x048)
-#define PRSC2_CLK_CFG			(MISC_BASE + 0x04C)
-#define AMEM_CLK_CFG			(MISC_BASE + 0x050)
+#define PRSC0_CLK_CFG			(misc_base + 0x044)
+#define PRSC1_CLK_CFG			(misc_base + 0x048)
+#define PRSC2_CLK_CFG			(misc_base + 0x04C)
+#define AMEM_CLK_CFG			(misc_base + 0x050)
 	#define AMEM_CLK_ENB		0
 
-#define CLCD_CLK_SYNT			(MISC_BASE + 0x05C)
-#define FIRDA_CLK_SYNT			(MISC_BASE + 0x060)
-#define UART_CLK_SYNT			(MISC_BASE + 0x064)
-#define GMAC_CLK_SYNT			(MISC_BASE + 0x068)
-#define GEN0_CLK_SYNT			(MISC_BASE + 0x06C)
-#define GEN1_CLK_SYNT			(MISC_BASE + 0x070)
-#define GEN2_CLK_SYNT			(MISC_BASE + 0x074)
-#define GEN3_CLK_SYNT			(MISC_BASE + 0x078)
+#define CLCD_CLK_SYNT			(misc_base + 0x05C)
+#define FIRDA_CLK_SYNT			(misc_base + 0x060)
+#define UART_CLK_SYNT			(misc_base + 0x064)
+#define GMAC_CLK_SYNT			(misc_base + 0x068)
+#define GEN0_CLK_SYNT			(misc_base + 0x06C)
+#define GEN1_CLK_SYNT			(misc_base + 0x070)
+#define GEN2_CLK_SYNT			(misc_base + 0x074)
+#define GEN3_CLK_SYNT			(misc_base + 0x078)
 
 /* pll rate configuration table, in ascending order of rates */
 static struct pll_rate_tbl pll_rtbl[] = {
@@ -211,6 +210,17 @@ static inline void spear310_clk_init(void) { }
 
 /* array of all spear 320 clock lookups */
 #ifdef CONFIG_MACH_SPEAR320
+
+#define SPEAR320_CONTROL_REG		(soc_config_base + 0x0000)
+#define SPEAR320_EXT_CTRL_REG		(soc_config_base + 0x0018)
+
+	#define SPEAR320_UARTX_PCLK_MASK		0x1
+	#define SPEAR320_UART2_PCLK_SHIFT		8
+	#define SPEAR320_UART3_PCLK_SHIFT		9
+	#define SPEAR320_UART4_PCLK_SHIFT		10
+	#define SPEAR320_UART5_PCLK_SHIFT		11
+	#define SPEAR320_UART6_PCLK_SHIFT		12
+	#define SPEAR320_RS485_PCLK_SHIFT		13
 	#define SMII_PCLK_SHIFT				18
 	#define SMII_PCLK_MASK				2
 	#define SMII_PCLK_VAL_PAD			0x0
@@ -235,7 +245,7 @@ static const char *smii0_parents[] = { "smii_125m_pad", "ras_pll2_clk",
 	"ras_syn0_gclk", };
 static const char *uartx_parents[] = { "ras_syn1_gclk", "ras_apb_clk", };
 
-static void __init spear320_clk_init(void)
+static void __init spear320_clk_init(void __iomem *soc_config_base)
 {
 	struct clk *clk;
 
@@ -362,7 +372,7 @@ static void __init spear320_clk_init(void)
 static inline void spear320_clk_init(void) { }
 #endif
 
-void __init spear3xx_clk_init(void)
+void __init spear3xx_clk_init(void __iomem *misc_base, void __iomem *soc_config_base)
 {
 	struct clk *clk, *clk1;
 
@@ -634,5 +644,5 @@ void __init spear3xx_clk_init(void)
 	else if (of_machine_is_compatible("st,spear310"))
 		spear310_clk_init();
 	else if (of_machine_is_compatible("st,spear320"))
-		spear320_clk_init();
+		spear320_clk_init(soc_config_base);
 }
diff --git a/drivers/clk/spear/spear6xx_clock.c b/drivers/clk/spear/spear6xx_clock.c
index e862a33..9406f24 100644
--- a/drivers/clk/spear/spear6xx_clock.c
+++ b/drivers/clk/spear/spear6xx_clock.c
@@ -13,28 +13,27 @@
 #include <linux/clkdev.h>
 #include <linux/io.h>
 #include <linux/spinlock_types.h>
-#include <mach/misc_regs.h>
 #include "clk.h"
 
 static DEFINE_SPINLOCK(_lock);
 
-#define PLL1_CTR			(MISC_BASE + 0x008)
-#define PLL1_FRQ			(MISC_BASE + 0x00C)
-#define PLL2_CTR			(MISC_BASE + 0x014)
-#define PLL2_FRQ			(MISC_BASE + 0x018)
-#define PLL_CLK_CFG			(MISC_BASE + 0x020)
+#define PLL1_CTR			(misc_base + 0x008)
+#define PLL1_FRQ			(misc_base + 0x00C)
+#define PLL2_CTR			(misc_base + 0x014)
+#define PLL2_FRQ			(misc_base + 0x018)
+#define PLL_CLK_CFG			(misc_base + 0x020)
 	/* PLL_CLK_CFG register masks */
 	#define MCTR_CLK_SHIFT		28
 	#define MCTR_CLK_MASK		3
 
-#define CORE_CLK_CFG			(MISC_BASE + 0x024)
+#define CORE_CLK_CFG			(misc_base + 0x024)
 	/* CORE CLK CFG register masks */
 	#define HCLK_RATIO_SHIFT	10
 	#define HCLK_RATIO_MASK		2
 	#define PCLK_RATIO_SHIFT	8
 	#define PCLK_RATIO_MASK		2
 
-#define PERIP_CLK_CFG			(MISC_BASE + 0x028)
+#define PERIP_CLK_CFG			(misc_base + 0x028)
 	/* PERIP_CLK_CFG register masks */
 	#define CLCD_CLK_SHIFT		2
 	#define CLCD_CLK_MASK		2
@@ -48,7 +47,7 @@ static DEFINE_SPINLOCK(_lock);
 	#define GPT3_CLK_SHIFT		12
 	#define GPT_CLK_MASK		1
 
-#define PERIP1_CLK_ENB			(MISC_BASE + 0x02C)
+#define PERIP1_CLK_ENB			(misc_base + 0x02C)
 	/* PERIP1_CLK_ENB register masks */
 	#define UART0_CLK_ENB		3
 	#define UART1_CLK_ENB		4
@@ -74,13 +73,13 @@ static DEFINE_SPINLOCK(_lock);
 	#define USBH0_CLK_ENB		25
 	#define USBH1_CLK_ENB		26
 
-#define PRSC0_CLK_CFG			(MISC_BASE + 0x044)
-#define PRSC1_CLK_CFG			(MISC_BASE + 0x048)
-#define PRSC2_CLK_CFG			(MISC_BASE + 0x04C)
+#define PRSC0_CLK_CFG			(misc_base + 0x044)
+#define PRSC1_CLK_CFG			(misc_base + 0x048)
+#define PRSC2_CLK_CFG			(misc_base + 0x04C)
 
-#define CLCD_CLK_SYNT			(MISC_BASE + 0x05C)
-#define FIRDA_CLK_SYNT			(MISC_BASE + 0x060)
-#define UART_CLK_SYNT			(MISC_BASE + 0x064)
+#define CLCD_CLK_SYNT			(misc_base + 0x05C)
+#define FIRDA_CLK_SYNT			(misc_base + 0x060)
+#define UART_CLK_SYNT			(misc_base + 0x064)
 
 /* vco rate configuration table, in ascending order of rates */
 static struct pll_rate_tbl pll_rtbl[] = {
@@ -115,7 +114,7 @@ static struct gpt_rate_tbl gpt_rtbl[] = {
 	{.mscale = 1, .nscale = 0}, /* 83 MHz */
 };
 
-void __init spear6xx_clk_init(void)
+void __init spear6xx_clk_init(void __iomem *misc_base)
 {
 	struct clk *clk, *clk1;
 
diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile
new file mode 100644
index 0000000..b5bac91
--- /dev/null
+++ b/drivers/clk/sunxi/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for sunxi specific clk
+#
+
+obj-y += clk-sunxi.o clk-factors.o
diff --git a/drivers/clk/sunxi/clk-factors.c b/drivers/clk/sunxi/clk-factors.c
new file mode 100644
index 0000000..88523f9
--- /dev/null
+++ b/drivers/clk/sunxi/clk-factors.c
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2013 Emilio López <emilio@elopez.com.ar>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Adjustable factor-based clock implementation
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/string.h>
+
+#include <linux/delay.h>
+
+#include "clk-factors.h"
+
+/*
+ * DOC: basic adjustable factor-based clock that cannot gate
+ *
+ * Traits of this clock:
+ * prepare - clk_prepare only ensures that parents are prepared
+ * enable - clk_enable only ensures that parents are enabled
+ * rate - rate is adjustable.
+ *        clk->rate = (parent->rate * N * (K + 1) >> P) / (M + 1)
+ * parent - fixed parent.  No clk_set_parent support
+ */
+
+struct clk_factors {
+	struct clk_hw hw;
+	void __iomem *reg;
+	struct clk_factors_config *config;
+	void (*get_factors) (u32 *rate, u32 parent, u8 *n, u8 *k, u8 *m, u8 *p);
+	spinlock_t *lock;
+};
+
+#define to_clk_factors(_hw) container_of(_hw, struct clk_factors, hw)
+
+#define SETMASK(len, pos)		(((-1U) >> (31-len))  << (pos))
+#define CLRMASK(len, pos)		(~(SETMASK(len, pos)))
+#define FACTOR_GET(bit, len, reg)	(((reg) & SETMASK(len, bit)) >> (bit))
+
+#define FACTOR_SET(bit, len, reg, val) \
+	(((reg) & CLRMASK(len, bit)) | (val << (bit)))
+
+static unsigned long clk_factors_recalc_rate(struct clk_hw *hw,
+					     unsigned long parent_rate)
+{
+	u8 n = 1, k = 0, p = 0, m = 0;
+	u32 reg;
+	unsigned long rate;
+	struct clk_factors *factors = to_clk_factors(hw);
+	struct clk_factors_config *config = factors->config;
+
+	/* Fetch the register value */
+	reg = readl(factors->reg);
+
+	/* Get each individual factor if applicable */
+	if (config->nwidth != SUNXI_FACTORS_NOT_APPLICABLE)
+		n = FACTOR_GET(config->nshift, config->nwidth, reg);
+	if (config->kwidth != SUNXI_FACTORS_NOT_APPLICABLE)
+		k = FACTOR_GET(config->kshift, config->kwidth, reg);
+	if (config->mwidth != SUNXI_FACTORS_NOT_APPLICABLE)
+		m = FACTOR_GET(config->mshift, config->mwidth, reg);
+	if (config->pwidth != SUNXI_FACTORS_NOT_APPLICABLE)
+		p = FACTOR_GET(config->pshift, config->pwidth, reg);
+
+	/* Calculate the rate */
+	rate = (parent_rate * n * (k + 1) >> p) / (m + 1);
+
+	return rate;
+}
+
+static long clk_factors_round_rate(struct clk_hw *hw, unsigned long rate,
+				   unsigned long *parent_rate)
+{
+	struct clk_factors *factors = to_clk_factors(hw);
+	factors->get_factors((u32 *)&rate, (u32)*parent_rate,
+			     NULL, NULL, NULL, NULL);
+
+	return rate;
+}
+
+static int clk_factors_set_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long parent_rate)
+{
+	u8 n, k, m, p;
+	u32 reg;
+	struct clk_factors *factors = to_clk_factors(hw);
+	struct clk_factors_config *config = factors->config;
+	unsigned long flags = 0;
+
+	factors->get_factors((u32 *)&rate, (u32)parent_rate, &n, &k, &m, &p);
+
+	if (factors->lock)
+		spin_lock_irqsave(factors->lock, flags);
+
+	/* Fetch the register value */
+	reg = readl(factors->reg);
+
+	/* Set up the new factors - macros do not do anything if width is 0 */
+	reg = FACTOR_SET(config->nshift, config->nwidth, reg, n);
+	reg = FACTOR_SET(config->kshift, config->kwidth, reg, k);
+	reg = FACTOR_SET(config->mshift, config->mwidth, reg, m);
+	reg = FACTOR_SET(config->pshift, config->pwidth, reg, p);
+
+	/* Apply them now */
+	writel(reg, factors->reg);
+
+	/* delay 500us so pll stabilizes */
+	__delay((rate >> 20) * 500 / 2);
+
+	if (factors->lock)
+		spin_unlock_irqrestore(factors->lock, flags);
+
+	return 0;
+}
+
+static const struct clk_ops clk_factors_ops = {
+	.recalc_rate = clk_factors_recalc_rate,
+	.round_rate = clk_factors_round_rate,
+	.set_rate = clk_factors_set_rate,
+};
+
+/**
+ * clk_register_factors - register a factors clock with
+ * the clock framework
+ * @dev: device registering this clock
+ * @name: name of this clock
+ * @parent_name: name of clock's parent
+ * @flags: framework-specific flags
+ * @reg: register address to adjust factors
+ * @config: shift and width of factors n, k, m and p
+ * @get_factors: function to calculate the factors for a given frequency
+ * @lock: shared register lock for this clock
+ */
+struct clk *clk_register_factors(struct device *dev, const char *name,
+				 const char *parent_name,
+				 unsigned long flags, void __iomem *reg,
+				 struct clk_factors_config *config,
+				 void (*get_factors)(u32 *rate, u32 parent,
+						     u8 *n, u8 *k, u8 *m, u8 *p),
+				 spinlock_t *lock)
+{
+	struct clk_factors *factors;
+	struct clk *clk;
+	struct clk_init_data init;
+
+	/* allocate the factors */
+	factors = kzalloc(sizeof(struct clk_factors), GFP_KERNEL);
+	if (!factors) {
+		pr_err("%s: could not allocate factors clk\n", __func__);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	init.name = name;
+	init.ops = &clk_factors_ops;
+	init.flags = flags;
+	init.parent_names = (parent_name ? &parent_name : NULL);
+	init.num_parents = (parent_name ? 1 : 0);
+
+	/* struct clk_factors assignments */
+	factors->reg = reg;
+	factors->config = config;
+	factors->lock = lock;
+	factors->hw.init = &init;
+	factors->get_factors = get_factors;
+
+	/* register the clock */
+	clk = clk_register(dev, &factors->hw);
+
+	if (IS_ERR(clk))
+		kfree(factors);
+
+	return clk;
+}
diff --git a/drivers/clk/sunxi/clk-factors.h b/drivers/clk/sunxi/clk-factors.h
new file mode 100644
index 0000000..f49851c
--- /dev/null
+++ b/drivers/clk/sunxi/clk-factors.h
@@ -0,0 +1,27 @@
+#ifndef __MACH_SUNXI_CLK_FACTORS_H
+#define __MACH_SUNXI_CLK_FACTORS_H
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+
+#define SUNXI_FACTORS_NOT_APPLICABLE	(0)
+
+struct clk_factors_config {
+	u8 nshift;
+	u8 nwidth;
+	u8 kshift;
+	u8 kwidth;
+	u8 mshift;
+	u8 mwidth;
+	u8 pshift;
+	u8 pwidth;
+};
+
+struct clk *clk_register_factors(struct device *dev, const char *name,
+				 const char *parent_name,
+				 unsigned long flags, void __iomem *reg,
+				 struct clk_factors_config *config,
+				 void (*get_factors) (u32 *rate, u32 parent_rate,
+						      u8 *n, u8 *k, u8 *m, u8 *p),
+				 spinlock_t *lock);
+#endif
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
new file mode 100644
index 0000000..0bb0eb4
--- /dev/null
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -0,0 +1,450 @@
+/*
+ * Copyright 2013 Emilio López
+ *
+ * Emilio López <emilio@elopez.com.ar>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/clk/sunxi.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include "clk-factors.h"
+
+static DEFINE_SPINLOCK(clk_lock);
+
+/**
+ * sunxi_osc_clk_setup() - Setup function for gatable oscillator
+ */
+
+#define SUNXI_OSC24M_GATE	0
+
+static void __init sunxi_osc_clk_setup(struct device_node *node)
+{
+	struct clk *clk;
+	const char *clk_name = node->name;
+	const char *parent;
+	void *reg;
+
+	reg = of_iomap(node, 0);
+
+	parent = of_clk_get_parent_name(node, 0);
+
+	clk = clk_register_gate(NULL, clk_name, parent, 0, reg,
+				SUNXI_OSC24M_GATE, 0, &clk_lock);
+
+	if (clk) {
+		of_clk_add_provider(node, of_clk_src_simple_get, clk);
+		clk_register_clkdev(clk, clk_name, NULL);
+	}
+}
+
+
+
+/**
+ * sunxi_get_pll1_factors() - calculates n, k, m, p factors for PLL1
+ * PLL1 rate is calculated as follows
+ * rate = (parent_rate * n * (k + 1) >> p) / (m + 1);
+ * parent_rate is always 24Mhz
+ */
+
+static void sunxi_get_pll1_factors(u32 *freq, u32 parent_rate,
+				   u8 *n, u8 *k, u8 *m, u8 *p)
+{
+	u8 div;
+
+	/* Normalize value to a 6M multiple */
+	div = *freq / 6000000;
+	*freq = 6000000 * div;
+
+	/* we were called to round the frequency, we can now return */
+	if (n == NULL)
+		return;
+
+	/* m is always zero for pll1 */
+	*m = 0;
+
+	/* k is 1 only on these cases */
+	if (*freq >= 768000000 || *freq == 42000000 || *freq == 54000000)
+		*k = 1;
+	else
+		*k = 0;
+
+	/* p will be 3 for divs under 10 */
+	if (div < 10)
+		*p = 3;
+
+	/* p will be 2 for divs between 10 - 20 and odd divs under 32 */
+	else if (div < 20 || (div < 32 && (div & 1)))
+		*p = 2;
+
+	/* p will be 1 for even divs under 32, divs under 40 and odd pairs
+	 * of divs between 40-62 */
+	else if (div < 40 || (div < 64 && (div & 2)))
+		*p = 1;
+
+	/* any other entries have p = 0 */
+	else
+		*p = 0;
+
+	/* calculate a suitable n based on k and p */
+	div <<= *p;
+	div /= (*k + 1);
+	*n = div / 4;
+}
+
+
+
+/**
+ * sunxi_get_apb1_factors() - calculates m, p factors for APB1
+ * APB1 rate is calculated as follows
+ * rate = (parent_rate >> p) / (m + 1);
+ */
+
+static void sunxi_get_apb1_factors(u32 *freq, u32 parent_rate,
+				   u8 *n, u8 *k, u8 *m, u8 *p)
+{
+	u8 calcm, calcp;
+
+	if (parent_rate < *freq)
+		*freq = parent_rate;
+
+	parent_rate = (parent_rate + (*freq - 1)) / *freq;
+
+	/* Invalid rate! */
+	if (parent_rate > 32)
+		return;
+
+	if (parent_rate <= 4)
+		calcp = 0;
+	else if (parent_rate <= 8)
+		calcp = 1;
+	else if (parent_rate <= 16)
+		calcp = 2;
+	else
+		calcp = 3;
+
+	calcm = (parent_rate >> calcp) - 1;
+
+	*freq = (parent_rate >> calcp) / (calcm + 1);
+
+	/* we were called to round the frequency, we can now return */
+	if (n == NULL)
+		return;
+
+	*m = calcm;
+	*p = calcp;
+}
+
+
+
+/**
+ * sunxi_factors_clk_setup() - Setup function for factor clocks
+ */
+
+struct factors_data {
+	struct clk_factors_config *table;
+	void (*getter) (u32 *rate, u32 parent_rate, u8 *n, u8 *k, u8 *m, u8 *p);
+};
+
+static struct clk_factors_config pll1_config = {
+	.nshift = 8,
+	.nwidth = 5,
+	.kshift = 4,
+	.kwidth = 2,
+	.mshift = 0,
+	.mwidth = 2,
+	.pshift = 16,
+	.pwidth = 2,
+};
+
+static struct clk_factors_config apb1_config = {
+	.mshift = 0,
+	.mwidth = 5,
+	.pshift = 16,
+	.pwidth = 2,
+};
+
+static const __initconst struct factors_data pll1_data = {
+	.table = &pll1_config,
+	.getter = sunxi_get_pll1_factors,
+};
+
+static const __initconst struct factors_data apb1_data = {
+	.table = &apb1_config,
+	.getter = sunxi_get_apb1_factors,
+};
+
+static void __init sunxi_factors_clk_setup(struct device_node *node,
+					   struct factors_data *data)
+{
+	struct clk *clk;
+	const char *clk_name = node->name;
+	const char *parent;
+	void *reg;
+
+	reg = of_iomap(node, 0);
+
+	parent = of_clk_get_parent_name(node, 0);
+
+	clk = clk_register_factors(NULL, clk_name, parent, 0, reg,
+				   data->table, data->getter, &clk_lock);
+
+	if (clk) {
+		of_clk_add_provider(node, of_clk_src_simple_get, clk);
+		clk_register_clkdev(clk, clk_name, NULL);
+	}
+}
+
+
+
+/**
+ * sunxi_mux_clk_setup() - Setup function for muxes
+ */
+
+#define SUNXI_MUX_GATE_WIDTH	2
+
+struct mux_data {
+	u8 shift;
+};
+
+static const __initconst struct mux_data cpu_data = {
+	.shift = 16,
+};
+
+static const __initconst struct mux_data apb1_mux_data = {
+	.shift = 24,
+};
+
+static void __init sunxi_mux_clk_setup(struct device_node *node,
+				       struct mux_data *data)
+{
+	struct clk *clk;
+	const char *clk_name = node->name;
+	const char *parents[5];
+	void *reg;
+	int i = 0;
+
+	reg = of_iomap(node, 0);
+
+	while (i < 5 && (parents[i] = of_clk_get_parent_name(node, i)) != NULL)
+		i++;
+
+	clk = clk_register_mux(NULL, clk_name, parents, i, 0, reg,
+			       data->shift, SUNXI_MUX_GATE_WIDTH,
+			       0, &clk_lock);
+
+	if (clk) {
+		of_clk_add_provider(node, of_clk_src_simple_get, clk);
+		clk_register_clkdev(clk, clk_name, NULL);
+	}
+}
+
+
+
+/**
+ * sunxi_divider_clk_setup() - Setup function for simple divider clocks
+ */
+
+#define SUNXI_DIVISOR_WIDTH	2
+
+struct div_data {
+	u8 shift;
+	u8 pow;
+};
+
+static const __initconst struct div_data axi_data = {
+	.shift = 0,
+	.pow = 0,
+};
+
+static const __initconst struct div_data ahb_data = {
+	.shift = 4,
+	.pow = 1,
+};
+
+static const __initconst struct div_data apb0_data = {
+	.shift = 8,
+	.pow = 1,
+};
+
+static void __init sunxi_divider_clk_setup(struct device_node *node,
+					   struct div_data *data)
+{
+	struct clk *clk;
+	const char *clk_name = node->name;
+	const char *clk_parent;
+	void *reg;
+
+	reg = of_iomap(node, 0);
+
+	clk_parent = of_clk_get_parent_name(node, 0);
+
+	clk = clk_register_divider(NULL, clk_name, clk_parent, 0,
+				   reg, data->shift, SUNXI_DIVISOR_WIDTH,
+				   data->pow ? CLK_DIVIDER_POWER_OF_TWO : 0,
+				   &clk_lock);
+	if (clk) {
+		of_clk_add_provider(node, of_clk_src_simple_get, clk);
+		clk_register_clkdev(clk, clk_name, NULL);
+	}
+}
+
+
+
+/**
+ * sunxi_gates_clk_setup() - Setup function for leaf gates on clocks
+ */
+
+#define SUNXI_GATES_MAX_SIZE	64
+
+struct gates_data {
+	DECLARE_BITMAP(mask, SUNXI_GATES_MAX_SIZE);
+};
+
+static const __initconst struct gates_data axi_gates_data = {
+	.mask = {1},
+};
+
+static const __initconst struct gates_data ahb_gates_data = {
+	.mask = {0x7F77FFF, 0x14FB3F},
+};
+
+static const __initconst struct gates_data apb0_gates_data = {
+	.mask = {0x4EF},
+};
+
+static const __initconst struct gates_data apb1_gates_data = {
+	.mask = {0xFF00F7},
+};
+
+static void __init sunxi_gates_clk_setup(struct device_node *node,
+					 struct gates_data *data)
+{
+	struct clk_onecell_data *clk_data;
+	const char *clk_parent;
+	const char *clk_name;
+	void *reg;
+	int qty;
+	int i = 0;
+	int j = 0;
+	int ignore;
+
+	reg = of_iomap(node, 0);
+
+	clk_parent = of_clk_get_parent_name(node, 0);
+
+	/* Worst-case size approximation and memory allocation */
+	qty = find_last_bit(data->mask, SUNXI_GATES_MAX_SIZE);
+	clk_data = kmalloc(sizeof(struct clk_onecell_data), GFP_KERNEL);
+	if (!clk_data)
+		return;
+	clk_data->clks = kzalloc((qty+1) * sizeof(struct clk *), GFP_KERNEL);
+	if (!clk_data->clks) {
+		kfree(clk_data);
+		return;
+	}
+
+	for_each_set_bit(i, data->mask, SUNXI_GATES_MAX_SIZE) {
+		of_property_read_string_index(node, "clock-output-names",
+					      j, &clk_name);
+
+		/* No driver claims this clock, but it should remain gated */
+		ignore = !strcmp("ahb_sdram", clk_name) ? CLK_IGNORE_UNUSED : 0;
+
+		clk_data->clks[i] = clk_register_gate(NULL, clk_name,
+						      clk_parent, ignore,
+						      reg + 4 * (i/32), i % 32,
+						      0, &clk_lock);
+		WARN_ON(IS_ERR(clk_data->clks[i]));
+
+		j++;
+	}
+
+	/* Adjust to the real max */
+	clk_data->clk_num = i;
+
+	of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+}
+
+/* Matches for of_clk_init */
+static const __initconst struct of_device_id clk_match[] = {
+	{.compatible = "fixed-clock", .data = of_fixed_clk_setup,},
+	{.compatible = "allwinner,sun4i-osc-clk", .data = sunxi_osc_clk_setup,},
+	{}
+};
+
+/* Matches for factors clocks */
+static const __initconst struct of_device_id clk_factors_match[] = {
+	{.compatible = "allwinner,sun4i-pll1-clk", .data = &pll1_data,},
+	{.compatible = "allwinner,sun4i-apb1-clk", .data = &apb1_data,},
+	{}
+};
+
+/* Matches for divider clocks */
+static const __initconst struct of_device_id clk_div_match[] = {
+	{.compatible = "allwinner,sun4i-axi-clk", .data = &axi_data,},
+	{.compatible = "allwinner,sun4i-ahb-clk", .data = &ahb_data,},
+	{.compatible = "allwinner,sun4i-apb0-clk", .data = &apb0_data,},
+	{}
+};
+
+/* Matches for mux clocks */
+static const __initconst struct of_device_id clk_mux_match[] = {
+	{.compatible = "allwinner,sun4i-cpu-clk", .data = &cpu_data,},
+	{.compatible = "allwinner,sun4i-apb1-mux-clk", .data = &apb1_mux_data,},
+	{}
+};
+
+/* Matches for gate clocks */
+static const __initconst struct of_device_id clk_gates_match[] = {
+	{.compatible = "allwinner,sun4i-axi-gates-clk", .data = &axi_gates_data,},
+	{.compatible = "allwinner,sun4i-ahb-gates-clk", .data = &ahb_gates_data,},
+	{.compatible = "allwinner,sun4i-apb0-gates-clk", .data = &apb0_gates_data,},
+	{.compatible = "allwinner,sun4i-apb1-gates-clk", .data = &apb1_gates_data,},
+	{}
+};
+
+static void __init of_sunxi_table_clock_setup(const struct of_device_id *clk_match,
+					      void *function)
+{
+	struct device_node *np;
+	const struct div_data *data;
+	const struct of_device_id *match;
+	void (*setup_function)(struct device_node *, const void *) = function;
+
+	for_each_matching_node(np, clk_match) {
+		match = of_match_node(clk_match, np);
+		data = match->data;
+		setup_function(np, data);
+	}
+}
+
+void __init sunxi_init_clocks(void)
+{
+	/* Register all the simple sunxi clocks on DT */
+	of_clk_init(clk_match);
+
+	/* Register factor clocks */
+	of_sunxi_table_clock_setup(clk_factors_match, sunxi_factors_clk_setup);
+
+	/* Register divider clocks */
+	of_sunxi_table_clock_setup(clk_div_match, sunxi_divider_clk_setup);
+
+	/* Register mux clocks */
+	of_sunxi_table_clock_setup(clk_mux_match, sunxi_mux_clk_setup);
+
+	/* Register gate clocks */
+	of_sunxi_table_clock_setup(clk_gates_match, sunxi_gates_clk_setup);
+}
diff --git a/drivers/clk/tegra/clk-periph-gate.c b/drivers/clk/tegra/clk-periph-gate.c
index 6dd5332..d87e1ce 100644
--- a/drivers/clk/tegra/clk-periph-gate.c
+++ b/drivers/clk/tegra/clk-periph-gate.c
@@ -41,7 +41,7 @@ static DEFINE_SPINLOCK(periph_ref_lock);
 #define write_rst_clr(val, gate) \
 	writel_relaxed(val, gate->clk_base + (gate->regs->rst_clr_reg))
 
-#define periph_clk_to_bit(periph) (1 << (gate->clk_num % 32))
+#define periph_clk_to_bit(gate) (1 << (gate->clk_num % 32))
 
 /* Peripheral gate clock ops */
 static int clk_periph_is_enabled(struct clk_hw *hw)
diff --git a/drivers/clk/tegra/clk-periph.c b/drivers/clk/tegra/clk-periph.c
index 788486e..9dbd301 100644
--- a/drivers/clk/tegra/clk-periph.c
+++ b/drivers/clk/tegra/clk-periph.c
@@ -16,6 +16,7 @@
 
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/export.h>
 #include <linux/slab.h>
 #include <linux/err.h>
 
@@ -128,6 +129,7 @@ void tegra_periph_reset_deassert(struct clk *c)
 
 	tegra_periph_reset(gate, 0);
 }
+EXPORT_SYMBOL(tegra_periph_reset_deassert);
 
 void tegra_periph_reset_assert(struct clk *c)
 {
@@ -147,6 +149,7 @@ void tegra_periph_reset_assert(struct clk *c)
 
 	tegra_periph_reset(gate, 1);
 }
+EXPORT_SYMBOL(tegra_periph_reset_assert);
 
 const struct clk_ops tegra_clk_periph_ops = {
 	.get_parent = clk_periph_get_parent,
diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c
index 1e2de73..b020beb 100644
--- a/drivers/clk/tegra/clk-tegra20.c
+++ b/drivers/clk/tegra/clk-tegra20.c
@@ -703,7 +703,7 @@ static void tegra20_pll_init(void)
 	clks[pll_a_out0] = clk;
 
 	/* PLLE */
-	clk = tegra_clk_register_plle("pll_e", "pll_ref", clk_base, NULL,
+	clk = tegra_clk_register_plle("pll_e", "pll_ref", clk_base, pmc_base,
 			     0, 100000000, &pll_e_params,
 			     0, pll_e_freq_table, NULL);
 	clk_register_clkdev(clk, "pll_e", NULL);
@@ -711,8 +711,8 @@ static void tegra20_pll_init(void)
 }
 
 static const char *cclk_parents[] = { "clk_m", "pll_c", "clk_32k", "pll_m",
-				      "pll_p_cclk", "pll_p_out4_cclk",
-				      "pll_p_out3_cclk", "clk_d", "pll_x" };
+				      "pll_p", "pll_p_out4",
+				      "pll_p_out3", "clk_d", "pll_x" };
 static const char *sclk_parents[] = { "clk_m", "pll_c_out1", "pll_p_out4",
 				      "pll_p_out3", "pll_p_out2", "clk_d",
 				      "clk_32k", "pll_m_out1" };
@@ -721,38 +721,6 @@ static void tegra20_super_clk_init(void)
 {
 	struct clk *clk;
 
-	/*
-	 * DIV_U71 dividers for CCLK, these dividers are used only
-	 * if parent clock is fixed rate.
-	 */
-
-	/*
-	 * Clock input to cclk divided from pll_p using
-	 * U71 divider of cclk.
-	 */
-	clk = tegra_clk_register_divider("pll_p_cclk", "pll_p",
-				clk_base + SUPER_CCLK_DIVIDER, 0,
-				TEGRA_DIVIDER_INT, 16, 8, 1, NULL);
-	clk_register_clkdev(clk, "pll_p_cclk", NULL);
-
-	/*
-	 * Clock input to cclk divided from pll_p_out3 using
-	 * U71 divider of cclk.
-	 */
-	clk = tegra_clk_register_divider("pll_p_out3_cclk", "pll_p_out3",
-				clk_base + SUPER_CCLK_DIVIDER, 0,
-				TEGRA_DIVIDER_INT, 16, 8, 1, NULL);
-	clk_register_clkdev(clk, "pll_p_out3_cclk", NULL);
-
-	/*
-	 * Clock input to cclk divided from pll_p_out4 using
-	 * U71 divider of cclk.
-	 */
-	clk = tegra_clk_register_divider("pll_p_out4_cclk", "pll_p_out4",
-				clk_base + SUPER_CCLK_DIVIDER, 0,
-				TEGRA_DIVIDER_INT, 16, 8, 1, NULL);
-	clk_register_clkdev(clk, "pll_p_out4_cclk", NULL);
-
 	/* CCLK */
 	clk = tegra_clk_register_super_mux("cclk", cclk_parents,
 			      ARRAY_SIZE(cclk_parents), CLK_SET_RATE_PARENT,
@@ -1279,6 +1247,8 @@ static __initdata struct tegra_clk_init_table init_table[] = {
 	{host1x, pll_c, 150000000, 0},
 	{disp1, pll_p, 600000000, 0},
 	{disp2, pll_p, 600000000, 0},
+	{gr2d, pll_c, 300000000, 0},
+	{gr3d, pll_c, 300000000, 0},
 	{clk_max, clk_max, 0, 0}, /* This MUST be the last entry */
 };
 
diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c
index ba6f51b..a0c54ad 100644
--- a/drivers/clk/tegra/clk-tegra30.c
+++ b/drivers/clk/tegra/clk-tegra30.c
@@ -22,8 +22,7 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/clk/tegra.h>
-
-#include <mach/powergate.h>
+#include <linux/tegra-powergate.h>
 
 #include "clk.h"
 
@@ -1911,6 +1910,8 @@ static __initdata struct tegra_clk_init_table init_table[] = {
 	{disp1, pll_p, 600000000, 0},
 	{disp2, pll_p, 600000000, 0},
 	{twd, clk_max, 0, 1},
+	{gr2d, pll_c, 300000000, 0},
+	{gr3d, pll_c, 300000000, 0},
 	{clk_max, clk_max, 0, 0}, /* This MUST be the last entry. */
 };
 
diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h
index 0744731..a09d7dc 100644
--- a/drivers/clk/tegra/clk.h
+++ b/drivers/clk/tegra/clk.h
@@ -355,15 +355,16 @@ struct clk *tegra_clk_register_periph_nodiv(const char *name,
 		struct tegra_clk_periph *periph, void __iomem *clk_base,
 		u32 offset);
 
-#define TEGRA_CLK_PERIPH(_mux_shift, _mux_width, _mux_flags,		\
+#define TEGRA_CLK_PERIPH(_mux_shift, _mux_mask, _mux_flags,		\
 			 _div_shift, _div_width, _div_frac_width,	\
 			 _div_flags, _clk_num, _enb_refcnt, _regs,	\
-			 _gate_flags)					\
+			 _gate_flags, _table)				\
 	{								\
 		.mux = {						\
 			.flags = _mux_flags,				\
 			.shift = _mux_shift,				\
-			.width = _mux_width,				\
+			.mask = _mux_mask,				\
+			.table = _table,				\
 		},							\
 		.divider = {						\
 			.flags = _div_flags,				\
@@ -393,26 +394,36 @@ struct tegra_periph_init_data {
 	const char *dev_id;
 };
 
-#define TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parent_names, _offset, \
-			_mux_shift, _mux_width, _mux_flags, _div_shift,	\
+#define TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parent_names, _offset,\
+			_mux_shift, _mux_mask, _mux_flags, _div_shift,	\
 			_div_width, _div_frac_width, _div_flags, _regs,	\
-			_clk_num, _enb_refcnt, _gate_flags, _clk_id)	\
+			_clk_num, _enb_refcnt, _gate_flags, _clk_id, _table) \
 	{								\
 		.name = _name,						\
 		.clk_id = _clk_id,					\
 		.parent_names = _parent_names,				\
 		.num_parents = ARRAY_SIZE(_parent_names),		\
-		.periph = TEGRA_CLK_PERIPH(_mux_shift, _mux_width,	\
+		.periph = TEGRA_CLK_PERIPH(_mux_shift, _mux_mask,	\
 					   _mux_flags, _div_shift,	\
 					   _div_width, _div_frac_width,	\
 					   _div_flags, _clk_num,	\
 					   _enb_refcnt, _regs,		\
-					   _gate_flags),		\
+					   _gate_flags, _table),	\
 		.offset = _offset,					\
 		.con_id = _con_id,					\
 		.dev_id = _dev_id,					\
 	}
 
+#define TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parent_names, _offset,\
+			_mux_shift, _mux_width, _mux_flags, _div_shift,	\
+			_div_width, _div_frac_width, _div_flags, _regs,	\
+			_clk_num, _enb_refcnt, _gate_flags, _clk_id)	\
+	TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parent_names, _offset,\
+			_mux_shift, BIT(_mux_width) - 1, _mux_flags,	\
+			_div_shift, _div_width, _div_frac_width, _div_flags, \
+			_regs, _clk_num, _enb_refcnt, _gate_flags, _clk_id,\
+			NULL)
+
 /**
  * struct clk_super_mux - super clock
  *
diff --git a/drivers/clk/ux500/clk-prcmu.c b/drivers/clk/ux500/clk-prcmu.c
index 74faa7e..293a288 100644
--- a/drivers/clk/ux500/clk-prcmu.c
+++ b/drivers/clk/ux500/clk-prcmu.c
@@ -20,15 +20,23 @@
 struct clk_prcmu {
 	struct clk_hw hw;
 	u8 cg_sel;
+	int is_prepared;
 	int is_enabled;
+	int opp_requested;
 };
 
 /* PRCMU clock operations. */
 
 static int clk_prcmu_prepare(struct clk_hw *hw)
 {
+	int ret;
 	struct clk_prcmu *clk = to_clk_prcmu(hw);
-	return prcmu_request_clock(clk->cg_sel, true);
+
+	ret = prcmu_request_clock(clk->cg_sel, true);
+	if (!ret)
+		clk->is_prepared = 1;
+
+	return ret;;
 }
 
 static void clk_prcmu_unprepare(struct clk_hw *hw)
@@ -36,7 +44,15 @@ static void clk_prcmu_unprepare(struct clk_hw *hw)
 	struct clk_prcmu *clk = to_clk_prcmu(hw);
 	if (prcmu_request_clock(clk->cg_sel, false))
 		pr_err("clk_prcmu: %s failed to disable %s.\n", __func__,
-			hw->init->name);
+			__clk_get_name(hw->clk));
+	else
+		clk->is_prepared = 0;
+}
+
+static int clk_prcmu_is_prepared(struct clk_hw *hw)
+{
+	struct clk_prcmu *clk = to_clk_prcmu(hw);
+	return clk->is_prepared;
 }
 
 static int clk_prcmu_enable(struct clk_hw *hw)
@@ -79,58 +95,52 @@ static int clk_prcmu_set_rate(struct clk_hw *hw, unsigned long rate,
 	return prcmu_set_clock_rate(clk->cg_sel, rate);
 }
 
-static int request_ape_opp100(bool enable)
-{
-	static int reqs;
-	int err = 0;
-
-	if (enable) {
-		if (!reqs)
-			err = prcmu_qos_add_requirement(PRCMU_QOS_APE_OPP,
-							"clock", 100);
-		if (!err)
-			reqs++;
-	} else {
-		reqs--;
-		if (!reqs)
-			prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP,
-						"clock");
-	}
-	return err;
-}
-
 static int clk_prcmu_opp_prepare(struct clk_hw *hw)
 {
 	int err;
 	struct clk_prcmu *clk = to_clk_prcmu(hw);
 
-	err = request_ape_opp100(true);
-	if (err) {
-		pr_err("clk_prcmu: %s failed to request APE OPP100 for %s.\n",
-			__func__, hw->init->name);
-		return err;
+	if (!clk->opp_requested) {
+		err = prcmu_qos_add_requirement(PRCMU_QOS_APE_OPP,
+						(char *)__clk_get_name(hw->clk),
+						100);
+		if (err) {
+			pr_err("clk_prcmu: %s fail req APE OPP for %s.\n",
+				__func__, __clk_get_name(hw->clk));
+			return err;
+		}
+		clk->opp_requested = 1;
 	}
 
 	err = prcmu_request_clock(clk->cg_sel, true);
-	if (err)
-		request_ape_opp100(false);
+	if (err) {
+		prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP,
+					(char *)__clk_get_name(hw->clk));
+		clk->opp_requested = 0;
+		return err;
+	}
 
-	return err;
+	clk->is_prepared = 1;
+	return 0;
 }
 
 static void clk_prcmu_opp_unprepare(struct clk_hw *hw)
 {
 	struct clk_prcmu *clk = to_clk_prcmu(hw);
 
-	if (prcmu_request_clock(clk->cg_sel, false))
-		goto out_error;
-	if (request_ape_opp100(false))
-		goto out_error;
-	return;
-
-out_error:
-	pr_err("clk_prcmu: %s failed to disable %s.\n", __func__,
-		hw->init->name);
+	if (prcmu_request_clock(clk->cg_sel, false)) {
+		pr_err("clk_prcmu: %s failed to disable %s.\n", __func__,
+			__clk_get_name(hw->clk));
+		return;
+	}
+
+	if (clk->opp_requested) {
+		prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP,
+					(char *)__clk_get_name(hw->clk));
+		clk->opp_requested = 0;
+	}
+
+	clk->is_prepared = 0;
 }
 
 static int clk_prcmu_opp_volt_prepare(struct clk_hw *hw)
@@ -138,38 +148,49 @@ static int clk_prcmu_opp_volt_prepare(struct clk_hw *hw)
 	int err;
 	struct clk_prcmu *clk = to_clk_prcmu(hw);
 
-	err = prcmu_request_ape_opp_100_voltage(true);
-	if (err) {
-		pr_err("clk_prcmu: %s failed to request APE OPP VOLT for %s.\n",
-			__func__, hw->init->name);
-		return err;
+	if (!clk->opp_requested) {
+		err = prcmu_request_ape_opp_100_voltage(true);
+		if (err) {
+			pr_err("clk_prcmu: %s fail req APE OPP VOLT for %s.\n",
+				__func__, __clk_get_name(hw->clk));
+			return err;
+		}
+		clk->opp_requested = 1;
 	}
 
 	err = prcmu_request_clock(clk->cg_sel, true);
-	if (err)
+	if (err) {
 		prcmu_request_ape_opp_100_voltage(false);
+		clk->opp_requested = 0;
+		return err;
+	}
 
-	return err;
+	clk->is_prepared = 1;
+	return 0;
 }
 
 static void clk_prcmu_opp_volt_unprepare(struct clk_hw *hw)
 {
 	struct clk_prcmu *clk = to_clk_prcmu(hw);
 
-	if (prcmu_request_clock(clk->cg_sel, false))
-		goto out_error;
-	if (prcmu_request_ape_opp_100_voltage(false))
-		goto out_error;
-	return;
-
-out_error:
-	pr_err("clk_prcmu: %s failed to disable %s.\n", __func__,
-		hw->init->name);
+	if (prcmu_request_clock(clk->cg_sel, false)) {
+		pr_err("clk_prcmu: %s failed to disable %s.\n", __func__,
+			__clk_get_name(hw->clk));
+		return;
+	}
+
+	if (clk->opp_requested) {
+		prcmu_request_ape_opp_100_voltage(false);
+		clk->opp_requested = 0;
+	}
+
+	clk->is_prepared = 0;
 }
 
 static struct clk_ops clk_prcmu_scalable_ops = {
 	.prepare = clk_prcmu_prepare,
 	.unprepare = clk_prcmu_unprepare,
+	.is_prepared = clk_prcmu_is_prepared,
 	.enable = clk_prcmu_enable,
 	.disable = clk_prcmu_disable,
 	.is_enabled = clk_prcmu_is_enabled,
@@ -181,6 +202,7 @@ static struct clk_ops clk_prcmu_scalable_ops = {
 static struct clk_ops clk_prcmu_gate_ops = {
 	.prepare = clk_prcmu_prepare,
 	.unprepare = clk_prcmu_unprepare,
+	.is_prepared = clk_prcmu_is_prepared,
 	.enable = clk_prcmu_enable,
 	.disable = clk_prcmu_disable,
 	.is_enabled = clk_prcmu_is_enabled,
@@ -202,6 +224,7 @@ static struct clk_ops clk_prcmu_rate_ops = {
 static struct clk_ops clk_prcmu_opp_gate_ops = {
 	.prepare = clk_prcmu_opp_prepare,
 	.unprepare = clk_prcmu_opp_unprepare,
+	.is_prepared = clk_prcmu_is_prepared,
 	.enable = clk_prcmu_enable,
 	.disable = clk_prcmu_disable,
 	.is_enabled = clk_prcmu_is_enabled,
@@ -211,6 +234,7 @@ static struct clk_ops clk_prcmu_opp_gate_ops = {
 static struct clk_ops clk_prcmu_opp_volt_scalable_ops = {
 	.prepare = clk_prcmu_opp_volt_prepare,
 	.unprepare = clk_prcmu_opp_volt_unprepare,
+	.is_prepared = clk_prcmu_is_prepared,
 	.enable = clk_prcmu_enable,
 	.disable = clk_prcmu_disable,
 	.is_enabled = clk_prcmu_is_enabled,
@@ -242,7 +266,9 @@ static struct clk *clk_reg_prcmu(const char *name,
 	}
 
 	clk->cg_sel = cg_sel;
+	clk->is_prepared = 1;
 	clk->is_enabled = 1;
+	clk->opp_requested = 0;
 	/* "rate" can be used for changing the initial frequency */
 	if (rate)
 		prcmu_set_clock_rate(cg_sel, rate);
diff --git a/drivers/clk/ux500/u8500_clk.c b/drivers/clk/ux500/u8500_clk.c
index 6b889a0..9d9add1 100644
--- a/drivers/clk/ux500/u8500_clk.c
+++ b/drivers/clk/ux500/u8500_clk.c
@@ -324,7 +324,8 @@ void u8500_clk_init(void)
 
 	clk = clk_reg_prcc_pclk("p3_pclk0", "per3clk", U8500_CLKRST3_BASE,
 				BIT(0), 0);
-	clk_register_clkdev(clk, NULL, "fsmc");
+	clk_register_clkdev(clk, "fsmc", NULL);
+	clk_register_clkdev(clk, NULL, "smsc911x");
 
 	clk = clk_reg_prcc_pclk("p3_pclk1", "per3clk", U8500_CLKRST3_BASE,
 				BIT(1), 0);
diff --git a/drivers/clk/x86/Makefile b/drivers/clk/x86/Makefile
index f9ba4fa..0478138 100644
--- a/drivers/clk/x86/Makefile
+++ b/drivers/clk/x86/Makefile
@@ -1,2 +1,2 @@
-clk-x86-lpss-objs		:= clk-lpss.o clk-lpt.o
+clk-x86-lpss-objs		:= clk-lpt.o
 obj-$(CONFIG_X86_INTEL_LPSS)	+= clk-x86-lpss.o
diff --git a/drivers/clk/x86/clk-lpss.c b/drivers/clk/x86/clk-lpss.c
deleted file mode 100644
index b5e229f..0000000
--- a/drivers/clk/x86/clk-lpss.c
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Intel Low Power Subsystem clocks.
- *
- * Copyright (C) 2013, Intel Corporation
- * Authors: Mika Westerberg <mika.westerberg@linux.intel.com>
- *	    Heikki Krogerus <heikki.krogerus@linux.intel.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/acpi.h>
-#include <linux/clk.h>
-#include <linux/clk-provider.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/module.h>
-
-static int clk_lpss_is_mmio_resource(struct acpi_resource *res, void *data)
-{
-	struct resource r;
-	return !acpi_dev_resource_memory(res, &r);
-}
-
-static acpi_status clk_lpss_find_mmio(acpi_handle handle, u32 level,
-				      void *data, void **retval)
-{
-	struct resource_list_entry *rentry;
-	struct list_head resource_list;
-	struct acpi_device *adev;
-	const char *uid = data;
-	int ret;
-
-	if (acpi_bus_get_device(handle, &adev))
-		return AE_OK;
-
-	if (uid) {
-		if (!adev->pnp.unique_id)
-			return AE_OK;
-		if (strcmp(uid, adev->pnp.unique_id))
-			return AE_OK;
-	}
-
-	INIT_LIST_HEAD(&resource_list);
-	ret = acpi_dev_get_resources(adev, &resource_list,
-				     clk_lpss_is_mmio_resource, NULL);
-	if (ret < 0)
-		return AE_NO_MEMORY;
-
-	list_for_each_entry(rentry, &resource_list, node)
-		if (resource_type(&rentry->res) == IORESOURCE_MEM) {
-			*(struct resource *)retval = rentry->res;
-			break;
-		}
-
-	acpi_dev_free_resource_list(&resource_list);
-	return AE_OK;
-}
-
-/**
- * clk_register_lpss_gate - register LPSS clock gate
- * @name: name of this clock gate
- * @parent_name: parent clock name
- * @hid: ACPI _HID of the device
- * @uid: ACPI _UID of the device (optional)
- * @offset: LPSS PRV_CLOCK_PARAMS offset
- *
- * Creates and registers LPSS clock gate.
- */
-struct clk *clk_register_lpss_gate(const char *name, const char *parent_name,
-				   const char *hid, const char *uid,
-				   unsigned offset)
-{
-	struct resource res = { };
-	void __iomem *mmio_base;
-	acpi_status status;
-	struct clk *clk;
-
-	/*
-	 * First try to look the device and its mmio resource from the
-	 * ACPI namespace.
-	 */
-	status = acpi_get_devices(hid, clk_lpss_find_mmio, (void *)uid,
-				  (void **)&res);
-	if (ACPI_FAILURE(status) || !res.start)
-		return ERR_PTR(-ENODEV);
-
-	mmio_base = ioremap(res.start, resource_size(&res));
-	if (!mmio_base)
-		return ERR_PTR(-ENOMEM);
-
-	clk = clk_register_gate(NULL, name, parent_name, 0, mmio_base + offset,
-				0, 0, NULL);
-	if (IS_ERR(clk))
-		iounmap(mmio_base);
-
-	return clk;
-}
diff --git a/drivers/clk/x86/clk-lpss.h b/drivers/clk/x86/clk-lpss.h
deleted file mode 100644
index e9460f4..0000000
--- a/drivers/clk/x86/clk-lpss.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Intel Low Power Subsystem clock.
- *
- * Copyright (C) 2013, Intel Corporation
- * Authors: Mika Westerberg <mika.westerberg@linux.intel.com>
- *	    Heikki Krogerus <heikki.krogerus@linux.intel.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 __CLK_LPSS_H
-#define __CLK_LPSS_H
-
-#include <linux/err.h>
-#include <linux/errno.h>
-#include <linux/clk.h>
-
-#ifdef CONFIG_ACPI
-extern struct clk *clk_register_lpss_gate(const char *name,
-					  const char *parent_name,
-					  const char *hid, const char *uid,
-					  unsigned offset);
-#else
-static inline struct clk *clk_register_lpss_gate(const char *name,
-						 const char *parent_name,
-						 const char *hid,
-						 const char *uid,
-						 unsigned offset)
-{
-	return ERR_PTR(-ENODEV);
-}
-#endif
-
-#endif /* __CLK_LPSS_H */
diff --git a/drivers/clk/x86/clk-lpt.c b/drivers/clk/x86/clk-lpt.c
index 81298ae..5cf4f46 100644
--- a/drivers/clk/x86/clk-lpt.c
+++ b/drivers/clk/x86/clk-lpt.c
@@ -10,7 +10,6 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/acpi.h>
 #include <linux/clk.h>
 #include <linux/clkdev.h>
 #include <linux/clk-provider.h>
@@ -18,8 +17,6 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 
-#include "clk-lpss.h"
-
 #define PRV_CLOCK_PARAMS 0x800
 
 static int lpt_clk_probe(struct platform_device *pdev)
@@ -34,40 +31,6 @@ static int lpt_clk_probe(struct platform_device *pdev)
 
 	/* Shared DMA clock */
 	clk_register_clkdev(clk, "hclk", "INTL9C60.0.auto");
-
-	/* SPI clocks */
-	clk = clk_register_lpss_gate("spi0_clk", "lpss_clk", "INT33C0", NULL,
-				     PRV_CLOCK_PARAMS);
-	if (!IS_ERR(clk))
-		clk_register_clkdev(clk, NULL, "INT33C0:00");
-
-	clk = clk_register_lpss_gate("spi1_clk", "lpss_clk", "INT33C1", NULL,
-				     PRV_CLOCK_PARAMS);
-	if (!IS_ERR(clk))
-		clk_register_clkdev(clk, NULL, "INT33C1:00");
-
-	/* I2C clocks */
-	clk = clk_register_lpss_gate("i2c0_clk", "lpss_clk", "INT33C2", NULL,
-				     PRV_CLOCK_PARAMS);
-	if (!IS_ERR(clk))
-		clk_register_clkdev(clk, NULL, "INT33C2:00");
-
-	clk = clk_register_lpss_gate("i2c1_clk", "lpss_clk", "INT33C3", NULL,
-				     PRV_CLOCK_PARAMS);
-	if (!IS_ERR(clk))
-		clk_register_clkdev(clk, NULL, "INT33C3:00");
-
-	/* UART clocks */
-	clk = clk_register_lpss_gate("uart0_clk", "lpss_clk", "INT33C4", NULL,
-				     PRV_CLOCK_PARAMS);
-	if (!IS_ERR(clk))
-		clk_register_clkdev(clk, NULL, "INT33C4:00");
-
-	clk = clk_register_lpss_gate("uart1_clk", "lpss_clk", "INT33C5", NULL,
-				     PRV_CLOCK_PARAMS);
-	if (!IS_ERR(clk))
-		clk_register_clkdev(clk, NULL, "INT33C5:00");
-
 	return 0;
 }
 
@@ -79,8 +42,7 @@ static struct platform_driver lpt_clk_driver = {
 	.probe = lpt_clk_probe,
 };
 
-static int __init lpt_clk_init(void)
+int __init lpt_clk_init(void)
 {
 	return platform_driver_register(&lpt_clk_driver);
 }
-arch_initcall(lpt_clk_init);
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index e507ab7..73fcddb 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -31,6 +31,9 @@ config SUNXI_TIMER
 config VT8500_TIMER
 	bool
 
+config CADENCE_TTC_TIMER
+	bool
+
 config CLKSRC_NOMADIK_MTU
 	bool
 	depends on (ARCH_NOMADIK || ARCH_U8500)
@@ -67,3 +70,8 @@ config CLKSRC_METAG_GENERIC
 	def_bool y if METAG
 	help
 	  This option enables support for the Meta per-thread timers.
+
+config CLKSRC_EXYNOS_MCT
+	def_bool y if ARCH_EXYNOS
+	help
+	  Support for Multi Core Timer controller on Exynos SoCs.
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 4d8283a..88541ce 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -16,9 +16,14 @@ obj-$(CONFIG_CLKSRC_NOMADIK_MTU)	+= nomadik-mtu.o
 obj-$(CONFIG_CLKSRC_DBX500_PRCMU)	+= clksrc-dbx500-prcmu.o
 obj-$(CONFIG_ARMADA_370_XP_TIMER)	+= time-armada-370-xp.o
 obj-$(CONFIG_ARCH_BCM2835)	+= bcm2835_timer.o
+obj-$(CONFIG_ARCH_MARCO)	+= timer-marco.o
+obj-$(CONFIG_ARCH_PRIMA2)	+= timer-prima2.o
+obj-$(CONFIG_ARCH_MXS)		+= mxs_timer.o
 obj-$(CONFIG_SUNXI_TIMER)	+= sunxi_timer.o
 obj-$(CONFIG_ARCH_TEGRA)	+= tegra20_timer.o
 obj-$(CONFIG_VT8500_TIMER)	+= vt8500_timer.o
+obj-$(CONFIG_CADENCE_TTC_TIMER)		+= cadence_ttc_timer.o
+obj-$(CONFIG_CLKSRC_EXYNOS_MCT)	+= exynos_mct.o
 
 obj-$(CONFIG_ARM_ARCH_TIMER)		+= arm_arch_timer.o
 obj-$(CONFIG_CLKSRC_METAG_GENERIC)	+= metag_generic.o
diff --git a/drivers/clocksource/bcm2835_timer.c b/drivers/clocksource/bcm2835_timer.c
index 50c68fe..766611d 100644
--- a/drivers/clocksource/bcm2835_timer.c
+++ b/drivers/clocksource/bcm2835_timer.c
@@ -95,23 +95,13 @@ static irqreturn_t bcm2835_time_interrupt(int irq, void *dev_id)
 	}
 }
 
-static struct of_device_id bcm2835_time_match[] __initconst = {
-	{ .compatible = "brcm,bcm2835-system-timer" },
-	{}
-};
-
-static void __init bcm2835_timer_init(void)
+static void __init bcm2835_timer_init(struct device_node *node)
 {
-	struct device_node *node;
 	void __iomem *base;
 	u32 freq;
 	int irq;
 	struct bcm2835_timer *timer;
 
-	node = of_find_matching_node(NULL, bcm2835_time_match);
-	if (!node)
-		panic("No bcm2835 timer node");
-
 	base = of_iomap(node, 0);
 	if (!base)
 		panic("Can't remap registers");
diff --git a/drivers/clocksource/cadence_ttc_timer.c b/drivers/clocksource/cadence_ttc_timer.c
new file mode 100644
index 0000000..685bc60
--- /dev/null
+++ b/drivers/clocksource/cadence_ttc_timer.c
@@ -0,0 +1,436 @@
+/*
+ * This file contains driver for the Cadence Triple Timer Counter Rev 06
+ *
+ *  Copyright (C) 2011-2013 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/clk.h>
+#include <linux/interrupt.h>
+#include <linux/clockchips.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/slab.h>
+#include <linux/clk-provider.h>
+
+/*
+ * 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 is configurable and
+ * obtained from device tree. The pre-scaler of 32 is used.
+ */
+
+/*
+ * Timer Register Offset Definitions of Timer 1, Increment base address by 4
+ * and use same offsets for Timer 2
+ */
+#define TTC_CLK_CNTRL_OFFSET		0x00 /* Clock Control Reg, RW */
+#define TTC_CNT_CNTRL_OFFSET		0x0C /* Counter Control Reg, RW */
+#define TTC_COUNT_VAL_OFFSET		0x18 /* Counter Value Reg, RO */
+#define TTC_INTR_VAL_OFFSET		0x24 /* Interval Count Reg, RW */
+#define TTC_ISR_OFFSET		0x54 /* Interrupt Status Reg, RO */
+#define TTC_IER_OFFSET		0x60 /* Interrupt Enable Reg, RW */
+
+#define TTC_CNT_CNTRL_DISABLE_MASK	0x1
+
+/*
+ * Setup the timers to use pre-scaling, using a fixed value for now that will
+ * work across most input frequency, but it may need to be more dynamic
+ */
+#define PRESCALE_EXPONENT	11	/* 2 ^ PRESCALE_EXPONENT = PRESCALE */
+#define PRESCALE		2048	/* The exponent must match this */
+#define CLK_CNTRL_PRESCALE	((PRESCALE_EXPONENT - 1) << 1)
+#define CLK_CNTRL_PRESCALE_EN	1
+#define CNT_CNTRL_RESET		(1 << 4)
+
+/**
+ * struct ttc_timer - This definition defines local timer structure
+ *
+ * @base_addr:	Base address of timer
+ * @clk:	Associated clock source
+ * @clk_rate_change_nb	Notifier block for clock rate changes
+ */
+struct ttc_timer {
+	void __iomem *base_addr;
+	struct clk *clk;
+	struct notifier_block clk_rate_change_nb;
+};
+
+#define to_ttc_timer(x) \
+		container_of(x, struct ttc_timer, clk_rate_change_nb)
+
+struct ttc_timer_clocksource {
+	struct ttc_timer	ttc;
+	struct clocksource	cs;
+};
+
+#define to_ttc_timer_clksrc(x) \
+		container_of(x, struct ttc_timer_clocksource, cs)
+
+struct ttc_timer_clockevent {
+	struct ttc_timer		ttc;
+	struct clock_event_device	ce;
+};
+
+#define to_ttc_timer_clkevent(x) \
+		container_of(x, struct ttc_timer_clockevent, ce)
+
+/**
+ * ttc_set_interval - Set the timer interval value
+ *
+ * @timer:	Pointer to the timer instance
+ * @cycles:	Timer interval ticks
+ **/
+static void ttc_set_interval(struct ttc_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 + TTC_CNT_CNTRL_OFFSET);
+	ctrl_reg |= TTC_CNT_CNTRL_DISABLE_MASK;
+	__raw_writel(ctrl_reg, timer->base_addr + TTC_CNT_CNTRL_OFFSET);
+
+	__raw_writel(cycles, timer->base_addr + TTC_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 |= CNT_CNTRL_RESET;
+	ctrl_reg &= ~TTC_CNT_CNTRL_DISABLE_MASK;
+	__raw_writel(ctrl_reg, timer->base_addr + TTC_CNT_CNTRL_OFFSET);
+}
+
+/**
+ * ttc_clock_event_interrupt - Clock event timer interrupt handler
+ *
+ * @irq:	IRQ number of the Timer
+ * @dev_id:	void pointer to the ttc_timer instance
+ *
+ * returns: Always IRQ_HANDLED - success
+ **/
+static irqreturn_t ttc_clock_event_interrupt(int irq, void *dev_id)
+{
+	struct ttc_timer_clockevent *ttce = dev_id;
+	struct ttc_timer *timer = &ttce->ttc;
+
+	/* Acknowledge the interrupt and call event handler */
+	__raw_readl(timer->base_addr + TTC_ISR_OFFSET);
+
+	ttce->ce.event_handler(&ttce->ce);
+
+	return IRQ_HANDLED;
+}
+
+/**
+ * __ttc_clocksource_read - Reads the timer counter register
+ *
+ * returns: Current timer counter register value
+ **/
+static cycle_t __ttc_clocksource_read(struct clocksource *cs)
+{
+	struct ttc_timer *timer = &to_ttc_timer_clksrc(cs)->ttc;
+
+	return (cycle_t)__raw_readl(timer->base_addr +
+				TTC_COUNT_VAL_OFFSET);
+}
+
+/**
+ * ttc_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 ttc_set_next_event(unsigned long cycles,
+					struct clock_event_device *evt)
+{
+	struct ttc_timer_clockevent *ttce = to_ttc_timer_clkevent(evt);
+	struct ttc_timer *timer = &ttce->ttc;
+
+	ttc_set_interval(timer, cycles);
+	return 0;
+}
+
+/**
+ * ttc_set_mode - Sets the mode of timer
+ *
+ * @mode:	Mode to be set
+ * @evt:	Address of clock event instance
+ **/
+static void ttc_set_mode(enum clock_event_mode mode,
+					struct clock_event_device *evt)
+{
+	struct ttc_timer_clockevent *ttce = to_ttc_timer_clkevent(evt);
+	struct ttc_timer *timer = &ttce->ttc;
+	u32 ctrl_reg;
+
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		ttc_set_interval(timer,
+				DIV_ROUND_CLOSEST(clk_get_rate(ttce->ttc.clk),
+					PRESCALE * HZ));
+		break;
+	case CLOCK_EVT_MODE_ONESHOT:
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_SHUTDOWN:
+		ctrl_reg = __raw_readl(timer->base_addr +
+					TTC_CNT_CNTRL_OFFSET);
+		ctrl_reg |= TTC_CNT_CNTRL_DISABLE_MASK;
+		__raw_writel(ctrl_reg,
+				timer->base_addr + TTC_CNT_CNTRL_OFFSET);
+		break;
+	case CLOCK_EVT_MODE_RESUME:
+		ctrl_reg = __raw_readl(timer->base_addr +
+					TTC_CNT_CNTRL_OFFSET);
+		ctrl_reg &= ~TTC_CNT_CNTRL_DISABLE_MASK;
+		__raw_writel(ctrl_reg,
+				timer->base_addr + TTC_CNT_CNTRL_OFFSET);
+		break;
+	}
+}
+
+static int ttc_rate_change_clocksource_cb(struct notifier_block *nb,
+		unsigned long event, void *data)
+{
+	struct clk_notifier_data *ndata = data;
+	struct ttc_timer *ttc = to_ttc_timer(nb);
+	struct ttc_timer_clocksource *ttccs = container_of(ttc,
+			struct ttc_timer_clocksource, ttc);
+
+	switch (event) {
+	case POST_RATE_CHANGE:
+		/*
+		 * Do whatever is necessary to maintain a proper time base
+		 *
+		 * I cannot find a way to adjust the currently used clocksource
+		 * to the new frequency. __clocksource_updatefreq_hz() sounds
+		 * good, but does not work. Not sure what's that missing.
+		 *
+		 * This approach works, but triggers two clocksource switches.
+		 * The first after unregister to clocksource jiffies. And
+		 * another one after the register to the newly registered timer.
+		 *
+		 * Alternatively we could 'waste' another HW timer to ping pong
+		 * between clock sources. That would also use one register and
+		 * one unregister call, but only trigger one clocksource switch
+		 * for the cost of another HW timer used by the OS.
+		 */
+		clocksource_unregister(&ttccs->cs);
+		clocksource_register_hz(&ttccs->cs,
+				ndata->new_rate / PRESCALE);
+		/* fall through */
+	case PRE_RATE_CHANGE:
+	case ABORT_RATE_CHANGE:
+	default:
+		return NOTIFY_DONE;
+	}
+}
+
+static void __init ttc_setup_clocksource(struct clk *clk, void __iomem *base)
+{
+	struct ttc_timer_clocksource *ttccs;
+	int err;
+
+	ttccs = kzalloc(sizeof(*ttccs), GFP_KERNEL);
+	if (WARN_ON(!ttccs))
+		return;
+
+	ttccs->ttc.clk = clk;
+
+	err = clk_prepare_enable(ttccs->ttc.clk);
+	if (WARN_ON(err)) {
+		kfree(ttccs);
+		return;
+	}
+
+	ttccs->ttc.clk_rate_change_nb.notifier_call =
+		ttc_rate_change_clocksource_cb;
+	ttccs->ttc.clk_rate_change_nb.next = NULL;
+	if (clk_notifier_register(ttccs->ttc.clk,
+				&ttccs->ttc.clk_rate_change_nb))
+		pr_warn("Unable to register clock notifier.\n");
+
+	ttccs->ttc.base_addr = base;
+	ttccs->cs.name = "ttc_clocksource";
+	ttccs->cs.rating = 200;
+	ttccs->cs.read = __ttc_clocksource_read;
+	ttccs->cs.mask = CLOCKSOURCE_MASK(16);
+	ttccs->cs.flags = CLOCK_SOURCE_IS_CONTINUOUS;
+
+	/*
+	 * 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.
+	 */
+	__raw_writel(0x0,  ttccs->ttc.base_addr + TTC_IER_OFFSET);
+	__raw_writel(CLK_CNTRL_PRESCALE | CLK_CNTRL_PRESCALE_EN,
+		     ttccs->ttc.base_addr + TTC_CLK_CNTRL_OFFSET);
+	__raw_writel(CNT_CNTRL_RESET,
+		     ttccs->ttc.base_addr + TTC_CNT_CNTRL_OFFSET);
+
+	err = clocksource_register_hz(&ttccs->cs,
+			clk_get_rate(ttccs->ttc.clk) / PRESCALE);
+	if (WARN_ON(err)) {
+		kfree(ttccs);
+		return;
+	}
+}
+
+static int ttc_rate_change_clockevent_cb(struct notifier_block *nb,
+		unsigned long event, void *data)
+{
+	struct clk_notifier_data *ndata = data;
+	struct ttc_timer *ttc = to_ttc_timer(nb);
+	struct ttc_timer_clockevent *ttcce = container_of(ttc,
+			struct ttc_timer_clockevent, ttc);
+
+	switch (event) {
+	case POST_RATE_CHANGE:
+	{
+		unsigned long flags;
+
+		/*
+		 * clockevents_update_freq should be called with IRQ disabled on
+		 * the CPU the timer provides events for. The timer we use is
+		 * common to both CPUs, not sure if we need to run on both
+		 * cores.
+		 */
+		local_irq_save(flags);
+		clockevents_update_freq(&ttcce->ce,
+				ndata->new_rate / PRESCALE);
+		local_irq_restore(flags);
+
+		/* fall through */
+	}
+	case PRE_RATE_CHANGE:
+	case ABORT_RATE_CHANGE:
+	default:
+		return NOTIFY_DONE;
+	}
+}
+
+static void __init ttc_setup_clockevent(struct clk *clk,
+						void __iomem *base, u32 irq)
+{
+	struct ttc_timer_clockevent *ttcce;
+	int err;
+
+	ttcce = kzalloc(sizeof(*ttcce), GFP_KERNEL);
+	if (WARN_ON(!ttcce))
+		return;
+
+	ttcce->ttc.clk = clk;
+
+	err = clk_prepare_enable(ttcce->ttc.clk);
+	if (WARN_ON(err)) {
+		kfree(ttcce);
+		return;
+	}
+
+	ttcce->ttc.clk_rate_change_nb.notifier_call =
+		ttc_rate_change_clockevent_cb;
+	ttcce->ttc.clk_rate_change_nb.next = NULL;
+	if (clk_notifier_register(ttcce->ttc.clk,
+				&ttcce->ttc.clk_rate_change_nb))
+		pr_warn("Unable to register clock notifier.\n");
+
+	ttcce->ttc.base_addr = base;
+	ttcce->ce.name = "ttc_clockevent";
+	ttcce->ce.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
+	ttcce->ce.set_next_event = ttc_set_next_event;
+	ttcce->ce.set_mode = ttc_set_mode;
+	ttcce->ce.rating = 200;
+	ttcce->ce.irq = irq;
+	ttcce->ce.cpumask = cpu_possible_mask;
+
+	/*
+	 * Setup the clock event timer to be an interval timer which
+	 * is prescaled by 32 using the interval interrupt. Leave it
+	 * disabled for now.
+	 */
+	__raw_writel(0x23, ttcce->ttc.base_addr + TTC_CNT_CNTRL_OFFSET);
+	__raw_writel(CLK_CNTRL_PRESCALE | CLK_CNTRL_PRESCALE_EN,
+		     ttcce->ttc.base_addr + TTC_CLK_CNTRL_OFFSET);
+	__raw_writel(0x1,  ttcce->ttc.base_addr + TTC_IER_OFFSET);
+
+	err = request_irq(irq, ttc_clock_event_interrupt,
+			  IRQF_DISABLED | IRQF_TIMER,
+			  ttcce->ce.name, ttcce);
+	if (WARN_ON(err)) {
+		kfree(ttcce);
+		return;
+	}
+
+	clockevents_config_and_register(&ttcce->ce,
+			clk_get_rate(ttcce->ttc.clk) / PRESCALE, 1, 0xfffe);
+}
+
+/**
+ * ttc_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 ttc_timer_init(struct device_node *timer)
+{
+	unsigned int irq;
+	void __iomem *timer_baseaddr;
+	struct clk *clk;
+	static int initialized;
+
+	if (initialized)
+		return;
+
+	initialized = 1;
+
+	/*
+	 * Get the 1st Triple Timer Counter (TTC) block from the device tree
+	 * and use it. Note that the event timer uses the interrupt and it's the
+	 * 2nd TTC hence the irq_of_parse_and_map(,1)
+	 */
+	timer_baseaddr = of_iomap(timer, 0);
+	if (!timer_baseaddr) {
+		pr_err("ERROR: invalid timer base address\n");
+		BUG();
+	}
+
+	irq = irq_of_parse_and_map(timer, 1);
+	if (irq <= 0) {
+		pr_err("ERROR: invalid interrupt number\n");
+		BUG();
+	}
+
+	clk = of_clk_get_by_name(timer, "cpu_1x");
+	if (IS_ERR(clk)) {
+		pr_err("ERROR: timer input clock not found\n");
+		BUG();
+	}
+
+	ttc_setup_clocksource(clk, timer_baseaddr);
+	ttc_setup_clockevent(clk, timer_baseaddr + 4, irq);
+
+	pr_info("%s #0 at %p, irq=%d\n", timer->name, timer_baseaddr, irq);
+}
+
+CLOCKSOURCE_OF_DECLARE(ttc, "cdns,ttc", ttc_timer_init);
diff --git a/drivers/clocksource/clksrc-of.c b/drivers/clocksource/clksrc-of.c
index bdabdaa..37f5325 100644
--- a/drivers/clocksource/clksrc-of.c
+++ b/drivers/clocksource/clksrc-of.c
@@ -16,6 +16,7 @@
 
 #include <linux/init.h>
 #include <linux/of.h>
+#include <linux/clocksource.h>
 
 extern struct of_device_id __clksrc_of_table[];
 
@@ -26,10 +27,10 @@ void __init clocksource_of_init(void)
 {
 	struct device_node *np;
 	const struct of_device_id *match;
-	void (*init_func)(void);
+	clocksource_of_init_fn init_func;
 
 	for_each_matching_node_and_match(np, __clksrc_of_table, &match) {
 		init_func = match->data;
-		init_func();
+		init_func(np);
 	}
 }
diff --git a/drivers/clocksource/em_sti.c b/drivers/clocksource/em_sti.c
index e6a553c..4329a29 100644
--- a/drivers/clocksource/em_sti.c
+++ b/drivers/clocksource/em_sti.c
@@ -399,7 +399,18 @@ static struct platform_driver em_sti_device_driver = {
 	}
 };
 
-module_platform_driver(em_sti_device_driver);
+static int __init em_sti_init(void)
+{
+	return platform_driver_register(&em_sti_device_driver);
+}
+
+static void __exit em_sti_exit(void)
+{
+	platform_driver_unregister(&em_sti_device_driver);
+}
+
+subsys_initcall(em_sti_init);
+module_exit(em_sti_exit);
 
 MODULE_AUTHOR("Magnus Damm");
 MODULE_DESCRIPTION("Renesas Emma Mobile STI Timer Driver");
diff --git a/drivers/clocksource/exynos_mct.c b/drivers/clocksource/exynos_mct.c
new file mode 100644
index 0000000..fd69d5e
--- /dev/null
+++ b/drivers/clocksource/exynos_mct.c
@@ -0,0 +1,559 @@
+/* linux/arch/arm/mach-exynos4/mct.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 MCT(Multi-Core Timer) 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/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 <linux/delay.h>
+#include <linux/percpu.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+#include <linux/clocksource.h>
+
+#include <asm/arch_timer.h>
+#include <asm/localtimer.h>
+
+#include <plat/cpu.h>
+
+#include <mach/map.h>
+#include <mach/irqs.h>
+#include <asm/mach/time.h>
+
+#define EXYNOS4_MCTREG(x)		(x)
+#define EXYNOS4_MCT_G_CNT_L		EXYNOS4_MCTREG(0x100)
+#define EXYNOS4_MCT_G_CNT_U		EXYNOS4_MCTREG(0x104)
+#define EXYNOS4_MCT_G_CNT_WSTAT		EXYNOS4_MCTREG(0x110)
+#define EXYNOS4_MCT_G_COMP0_L		EXYNOS4_MCTREG(0x200)
+#define EXYNOS4_MCT_G_COMP0_U		EXYNOS4_MCTREG(0x204)
+#define EXYNOS4_MCT_G_COMP0_ADD_INCR	EXYNOS4_MCTREG(0x208)
+#define EXYNOS4_MCT_G_TCON		EXYNOS4_MCTREG(0x240)
+#define EXYNOS4_MCT_G_INT_CSTAT		EXYNOS4_MCTREG(0x244)
+#define EXYNOS4_MCT_G_INT_ENB		EXYNOS4_MCTREG(0x248)
+#define EXYNOS4_MCT_G_WSTAT		EXYNOS4_MCTREG(0x24C)
+#define _EXYNOS4_MCT_L_BASE		EXYNOS4_MCTREG(0x300)
+#define EXYNOS4_MCT_L_BASE(x)		(_EXYNOS4_MCT_L_BASE + (0x100 * x))
+#define EXYNOS4_MCT_L_MASK		(0xffffff00)
+
+#define MCT_L_TCNTB_OFFSET		(0x00)
+#define MCT_L_ICNTB_OFFSET		(0x08)
+#define MCT_L_TCON_OFFSET		(0x20)
+#define MCT_L_INT_CSTAT_OFFSET		(0x30)
+#define MCT_L_INT_ENB_OFFSET		(0x34)
+#define MCT_L_WSTAT_OFFSET		(0x40)
+#define MCT_G_TCON_START		(1 << 8)
+#define MCT_G_TCON_COMP0_AUTO_INC	(1 << 1)
+#define MCT_G_TCON_COMP0_ENABLE		(1 << 0)
+#define MCT_L_TCON_INTERVAL_MODE	(1 << 2)
+#define MCT_L_TCON_INT_START		(1 << 1)
+#define MCT_L_TCON_TIMER_START		(1 << 0)
+
+#define TICK_BASE_CNT	1
+
+enum {
+	MCT_INT_SPI,
+	MCT_INT_PPI
+};
+
+enum {
+	MCT_G0_IRQ,
+	MCT_G1_IRQ,
+	MCT_G2_IRQ,
+	MCT_G3_IRQ,
+	MCT_L0_IRQ,
+	MCT_L1_IRQ,
+	MCT_L2_IRQ,
+	MCT_L3_IRQ,
+	MCT_NR_IRQS,
+};
+
+static void __iomem *reg_base;
+static unsigned long clk_rate;
+static unsigned int mct_int_type;
+static int mct_irqs[MCT_NR_IRQS];
+
+struct mct_clock_event_device {
+	struct clock_event_device *evt;
+	unsigned long base;
+	char name[10];
+};
+
+static void exynos4_mct_write(unsigned int value, unsigned long offset)
+{
+	unsigned long stat_addr;
+	u32 mask;
+	u32 i;
+
+	__raw_writel(value, reg_base + offset);
+
+	if (likely(offset >= EXYNOS4_MCT_L_BASE(0))) {
+		stat_addr = (offset & ~EXYNOS4_MCT_L_MASK) + MCT_L_WSTAT_OFFSET;
+		switch (offset & EXYNOS4_MCT_L_MASK) {
+		case MCT_L_TCON_OFFSET:
+			mask = 1 << 3;		/* L_TCON write status */
+			break;
+		case MCT_L_ICNTB_OFFSET:
+			mask = 1 << 1;		/* L_ICNTB write status */
+			break;
+		case MCT_L_TCNTB_OFFSET:
+			mask = 1 << 0;		/* L_TCNTB write status */
+			break;
+		default:
+			return;
+		}
+	} else {
+		switch (offset) {
+		case EXYNOS4_MCT_G_TCON:
+			stat_addr = EXYNOS4_MCT_G_WSTAT;
+			mask = 1 << 16;		/* G_TCON write status */
+			break;
+		case EXYNOS4_MCT_G_COMP0_L:
+			stat_addr = EXYNOS4_MCT_G_WSTAT;
+			mask = 1 << 0;		/* G_COMP0_L write status */
+			break;
+		case EXYNOS4_MCT_G_COMP0_U:
+			stat_addr = EXYNOS4_MCT_G_WSTAT;
+			mask = 1 << 1;		/* G_COMP0_U write status */
+			break;
+		case EXYNOS4_MCT_G_COMP0_ADD_INCR:
+			stat_addr = EXYNOS4_MCT_G_WSTAT;
+			mask = 1 << 2;		/* G_COMP0_ADD_INCR w status */
+			break;
+		case EXYNOS4_MCT_G_CNT_L:
+			stat_addr = EXYNOS4_MCT_G_CNT_WSTAT;
+			mask = 1 << 0;		/* G_CNT_L write status */
+			break;
+		case EXYNOS4_MCT_G_CNT_U:
+			stat_addr = EXYNOS4_MCT_G_CNT_WSTAT;
+			mask = 1 << 1;		/* G_CNT_U write status */
+			break;
+		default:
+			return;
+		}
+	}
+
+	/* Wait maximum 1 ms until written values are applied */
+	for (i = 0; i < loops_per_jiffy / 1000 * HZ; i++)
+		if (__raw_readl(reg_base + stat_addr) & mask) {
+			__raw_writel(mask, reg_base + stat_addr);
+			return;
+		}
+
+	panic("MCT hangs after writing %d (offset:0x%lx)\n", value, offset);
+}
+
+/* Clocksource handling */
+static void exynos4_mct_frc_start(u32 hi, u32 lo)
+{
+	u32 reg;
+
+	exynos4_mct_write(lo, EXYNOS4_MCT_G_CNT_L);
+	exynos4_mct_write(hi, EXYNOS4_MCT_G_CNT_U);
+
+	reg = __raw_readl(reg_base + EXYNOS4_MCT_G_TCON);
+	reg |= MCT_G_TCON_START;
+	exynos4_mct_write(reg, EXYNOS4_MCT_G_TCON);
+}
+
+static cycle_t exynos4_frc_read(struct clocksource *cs)
+{
+	unsigned int lo, hi;
+	u32 hi2 = __raw_readl(reg_base + EXYNOS4_MCT_G_CNT_U);
+
+	do {
+		hi = hi2;
+		lo = __raw_readl(reg_base + EXYNOS4_MCT_G_CNT_L);
+		hi2 = __raw_readl(reg_base + EXYNOS4_MCT_G_CNT_U);
+	} while (hi != hi2);
+
+	return ((cycle_t)hi << 32) | lo;
+}
+
+static void exynos4_frc_resume(struct clocksource *cs)
+{
+	exynos4_mct_frc_start(0, 0);
+}
+
+struct clocksource mct_frc = {
+	.name		= "mct-frc",
+	.rating		= 400,
+	.read		= exynos4_frc_read,
+	.mask		= CLOCKSOURCE_MASK(64),
+	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
+	.resume		= exynos4_frc_resume,
+};
+
+static void __init exynos4_clocksource_init(void)
+{
+	exynos4_mct_frc_start(0, 0);
+
+	if (clocksource_register_hz(&mct_frc, clk_rate))
+		panic("%s: can't register clocksource\n", mct_frc.name);
+}
+
+static void exynos4_mct_comp0_stop(void)
+{
+	unsigned int tcon;
+
+	tcon = __raw_readl(reg_base + EXYNOS4_MCT_G_TCON);
+	tcon &= ~(MCT_G_TCON_COMP0_ENABLE | MCT_G_TCON_COMP0_AUTO_INC);
+
+	exynos4_mct_write(tcon, EXYNOS4_MCT_G_TCON);
+	exynos4_mct_write(0, EXYNOS4_MCT_G_INT_ENB);
+}
+
+static void exynos4_mct_comp0_start(enum clock_event_mode mode,
+				    unsigned long cycles)
+{
+	unsigned int tcon;
+	cycle_t comp_cycle;
+
+	tcon = __raw_readl(reg_base + EXYNOS4_MCT_G_TCON);
+
+	if (mode == CLOCK_EVT_MODE_PERIODIC) {
+		tcon |= MCT_G_TCON_COMP0_AUTO_INC;
+		exynos4_mct_write(cycles, EXYNOS4_MCT_G_COMP0_ADD_INCR);
+	}
+
+	comp_cycle = exynos4_frc_read(&mct_frc) + cycles;
+	exynos4_mct_write((u32)comp_cycle, EXYNOS4_MCT_G_COMP0_L);
+	exynos4_mct_write((u32)(comp_cycle >> 32), EXYNOS4_MCT_G_COMP0_U);
+
+	exynos4_mct_write(0x1, EXYNOS4_MCT_G_INT_ENB);
+
+	tcon |= MCT_G_TCON_COMP0_ENABLE;
+	exynos4_mct_write(tcon , EXYNOS4_MCT_G_TCON);
+}
+
+static int exynos4_comp_set_next_event(unsigned long cycles,
+				       struct clock_event_device *evt)
+{
+	exynos4_mct_comp0_start(evt->mode, cycles);
+
+	return 0;
+}
+
+static void exynos4_comp_set_mode(enum clock_event_mode mode,
+				  struct clock_event_device *evt)
+{
+	unsigned long cycles_per_jiffy;
+	exynos4_mct_comp0_stop();
+
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		cycles_per_jiffy =
+			(((unsigned long long) NSEC_PER_SEC / HZ * evt->mult) >> evt->shift);
+		exynos4_mct_comp0_start(mode, cycles_per_jiffy);
+		break;
+
+	case CLOCK_EVT_MODE_ONESHOT:
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_SHUTDOWN:
+	case CLOCK_EVT_MODE_RESUME:
+		break;
+	}
+}
+
+static struct clock_event_device mct_comp_device = {
+	.name		= "mct-comp",
+	.features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+	.rating		= 250,
+	.set_next_event	= exynos4_comp_set_next_event,
+	.set_mode	= exynos4_comp_set_mode,
+};
+
+static irqreturn_t exynos4_mct_comp_isr(int irq, void *dev_id)
+{
+	struct clock_event_device *evt = dev_id;
+
+	exynos4_mct_write(0x1, EXYNOS4_MCT_G_INT_CSTAT);
+
+	evt->event_handler(evt);
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction mct_comp_event_irq = {
+	.name		= "mct_comp_irq",
+	.flags		= IRQF_TIMER | IRQF_IRQPOLL,
+	.handler	= exynos4_mct_comp_isr,
+	.dev_id		= &mct_comp_device,
+};
+
+static void exynos4_clockevent_init(void)
+{
+	mct_comp_device.cpumask = cpumask_of(0);
+	clockevents_config_and_register(&mct_comp_device, clk_rate,
+					0xf, 0xffffffff);
+	setup_irq(mct_irqs[MCT_G0_IRQ], &mct_comp_event_irq);
+}
+
+#ifdef CONFIG_LOCAL_TIMERS
+
+static DEFINE_PER_CPU(struct mct_clock_event_device, percpu_mct_tick);
+
+/* Clock event handling */
+static void exynos4_mct_tick_stop(struct mct_clock_event_device *mevt)
+{
+	unsigned long tmp;
+	unsigned long mask = MCT_L_TCON_INT_START | MCT_L_TCON_TIMER_START;
+	unsigned long offset = mevt->base + MCT_L_TCON_OFFSET;
+
+	tmp = __raw_readl(reg_base + offset);
+	if (tmp & mask) {
+		tmp &= ~mask;
+		exynos4_mct_write(tmp, offset);
+	}
+}
+
+static void exynos4_mct_tick_start(unsigned long cycles,
+				   struct mct_clock_event_device *mevt)
+{
+	unsigned long tmp;
+
+	exynos4_mct_tick_stop(mevt);
+
+	tmp = (1 << 31) | cycles;	/* MCT_L_UPDATE_ICNTB */
+
+	/* update interrupt count buffer */
+	exynos4_mct_write(tmp, mevt->base + MCT_L_ICNTB_OFFSET);
+
+	/* enable MCT tick interrupt */
+	exynos4_mct_write(0x1, mevt->base + MCT_L_INT_ENB_OFFSET);
+
+	tmp = __raw_readl(reg_base + mevt->base + MCT_L_TCON_OFFSET);
+	tmp |= MCT_L_TCON_INT_START | MCT_L_TCON_TIMER_START |
+	       MCT_L_TCON_INTERVAL_MODE;
+	exynos4_mct_write(tmp, mevt->base + MCT_L_TCON_OFFSET);
+}
+
+static int exynos4_tick_set_next_event(unsigned long cycles,
+				       struct clock_event_device *evt)
+{
+	struct mct_clock_event_device *mevt = this_cpu_ptr(&percpu_mct_tick);
+
+	exynos4_mct_tick_start(cycles, mevt);
+
+	return 0;
+}
+
+static inline void exynos4_tick_set_mode(enum clock_event_mode mode,
+					 struct clock_event_device *evt)
+{
+	struct mct_clock_event_device *mevt = this_cpu_ptr(&percpu_mct_tick);
+	unsigned long cycles_per_jiffy;
+
+	exynos4_mct_tick_stop(mevt);
+
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		cycles_per_jiffy =
+			(((unsigned long long) NSEC_PER_SEC / HZ * evt->mult) >> evt->shift);
+		exynos4_mct_tick_start(cycles_per_jiffy, mevt);
+		break;
+
+	case CLOCK_EVT_MODE_ONESHOT:
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_SHUTDOWN:
+	case CLOCK_EVT_MODE_RESUME:
+		break;
+	}
+}
+
+static int exynos4_mct_tick_clear(struct mct_clock_event_device *mevt)
+{
+	struct clock_event_device *evt = mevt->evt;
+
+	/*
+	 * This is for supporting oneshot mode.
+	 * Mct would generate interrupt periodically
+	 * without explicit stopping.
+	 */
+	if (evt->mode != CLOCK_EVT_MODE_PERIODIC)
+		exynos4_mct_tick_stop(mevt);
+
+	/* Clear the MCT tick interrupt */
+	if (__raw_readl(reg_base + mevt->base + MCT_L_INT_CSTAT_OFFSET) & 1) {
+		exynos4_mct_write(0x1, mevt->base + MCT_L_INT_CSTAT_OFFSET);
+		return 1;
+	} else {
+		return 0;
+	}
+}
+
+static irqreturn_t exynos4_mct_tick_isr(int irq, void *dev_id)
+{
+	struct mct_clock_event_device *mevt = dev_id;
+	struct clock_event_device *evt = mevt->evt;
+
+	exynos4_mct_tick_clear(mevt);
+
+	evt->event_handler(evt);
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction mct_tick0_event_irq = {
+	.name		= "mct_tick0_irq",
+	.flags		= IRQF_TIMER | IRQF_NOBALANCING,
+	.handler	= exynos4_mct_tick_isr,
+};
+
+static struct irqaction mct_tick1_event_irq = {
+	.name		= "mct_tick1_irq",
+	.flags		= IRQF_TIMER | IRQF_NOBALANCING,
+	.handler	= exynos4_mct_tick_isr,
+};
+
+static int __cpuinit exynos4_local_timer_setup(struct clock_event_device *evt)
+{
+	struct mct_clock_event_device *mevt;
+	unsigned int cpu = smp_processor_id();
+
+	mevt = this_cpu_ptr(&percpu_mct_tick);
+	mevt->evt = evt;
+
+	mevt->base = EXYNOS4_MCT_L_BASE(cpu);
+	sprintf(mevt->name, "mct_tick%d", cpu);
+
+	evt->name = mevt->name;
+	evt->cpumask = cpumask_of(cpu);
+	evt->set_next_event = exynos4_tick_set_next_event;
+	evt->set_mode = exynos4_tick_set_mode;
+	evt->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
+	evt->rating = 450;
+	clockevents_config_and_register(evt, clk_rate / (TICK_BASE_CNT + 1),
+					0xf, 0x7fffffff);
+
+	exynos4_mct_write(TICK_BASE_CNT, mevt->base + MCT_L_TCNTB_OFFSET);
+
+	if (mct_int_type == MCT_INT_SPI) {
+		if (cpu == 0) {
+			mct_tick0_event_irq.dev_id = mevt;
+			evt->irq = mct_irqs[MCT_L0_IRQ];
+			setup_irq(evt->irq, &mct_tick0_event_irq);
+		} else {
+			mct_tick1_event_irq.dev_id = mevt;
+			evt->irq = mct_irqs[MCT_L1_IRQ];
+			setup_irq(evt->irq, &mct_tick1_event_irq);
+			irq_set_affinity(evt->irq, cpumask_of(1));
+		}
+	} else {
+		enable_percpu_irq(mct_irqs[MCT_L0_IRQ], 0);
+	}
+
+	return 0;
+}
+
+static void exynos4_local_timer_stop(struct clock_event_device *evt)
+{
+	unsigned int cpu = smp_processor_id();
+	evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt);
+	if (mct_int_type == MCT_INT_SPI)
+		if (cpu == 0)
+			remove_irq(evt->irq, &mct_tick0_event_irq);
+		else
+			remove_irq(evt->irq, &mct_tick1_event_irq);
+	else
+		disable_percpu_irq(mct_irqs[MCT_L0_IRQ]);
+}
+
+static struct local_timer_ops exynos4_mct_tick_ops __cpuinitdata = {
+	.setup	= exynos4_local_timer_setup,
+	.stop	= exynos4_local_timer_stop,
+};
+#endif /* CONFIG_LOCAL_TIMERS */
+
+static void __init exynos4_timer_resources(struct device_node *np)
+{
+	struct clk *mct_clk, *tick_clk;
+
+	tick_clk = np ? of_clk_get_by_name(np, "fin_pll") :
+				clk_get(NULL, "fin_pll");
+	if (IS_ERR(tick_clk))
+		panic("%s: unable to determine tick clock rate\n", __func__);
+	clk_rate = clk_get_rate(tick_clk);
+
+	mct_clk = np ? of_clk_get_by_name(np, "mct") : clk_get(NULL, "mct");
+	if (IS_ERR(mct_clk))
+		panic("%s: unable to retrieve mct clock instance\n", __func__);
+	clk_prepare_enable(mct_clk);
+
+	reg_base = np ? of_iomap(np, 0) : S5P_VA_SYSTIMER;
+	if (!reg_base)
+		panic("%s: unable to ioremap mct address space\n", __func__);
+
+#ifdef CONFIG_LOCAL_TIMERS
+	if (mct_int_type == MCT_INT_PPI) {
+		int err;
+
+		err = request_percpu_irq(mct_irqs[MCT_L0_IRQ],
+					 exynos4_mct_tick_isr, "MCT",
+					 &percpu_mct_tick);
+		WARN(err, "MCT: can't request IRQ %d (%d)\n",
+		     mct_irqs[MCT_L0_IRQ], err);
+	}
+
+	local_timer_register(&exynos4_mct_tick_ops);
+#endif /* CONFIG_LOCAL_TIMERS */
+}
+
+static const struct of_device_id exynos_mct_ids[] = {
+	{ .compatible = "samsung,exynos4210-mct", .data = (void *)MCT_INT_SPI },
+	{ .compatible = "samsung,exynos4412-mct", .data = (void *)MCT_INT_PPI },
+	{ }
+};
+
+void __init mct_init(void)
+{
+	struct device_node *np = NULL;
+	const struct of_device_id *match;
+	u32 nr_irqs, i;
+
+#ifdef CONFIG_OF
+	np = of_find_matching_node_and_match(NULL, exynos_mct_ids, &match);
+#endif
+	if (np) {
+		mct_int_type = (u32)(match->data);
+
+		/* This driver uses only one global timer interrupt */
+		mct_irqs[MCT_G0_IRQ] = irq_of_parse_and_map(np, MCT_G0_IRQ);
+
+		/*
+		 * Find out the number of local irqs specified. The local
+		 * timer irqs are specified after the four global timer
+		 * irqs are specified.
+		 */
+#ifdef CONFIG_OF
+		nr_irqs = of_irq_count(np);
+#endif
+		for (i = MCT_L0_IRQ; i < nr_irqs; i++)
+			mct_irqs[i] = irq_of_parse_and_map(np, i);
+	} else if (soc_is_exynos4210()) {
+		mct_irqs[MCT_G0_IRQ] = EXYNOS4_IRQ_MCT_G0;
+		mct_irqs[MCT_L0_IRQ] = EXYNOS4_IRQ_MCT_L0;
+		mct_irqs[MCT_L1_IRQ] = EXYNOS4_IRQ_MCT_L1;
+		mct_int_type = MCT_INT_SPI;
+	} else {
+		panic("unable to determine mct controller type\n");
+	}
+
+	exynos4_timer_resources(np);
+	exynos4_clocksource_init();
+	exynos4_clockevent_init();
+}
+CLOCKSOURCE_OF_DECLARE(exynos4210, "samsung,exynos4210-mct", mct_init);
+CLOCKSOURCE_OF_DECLARE(exynos4412, "samsung,exynos4412-mct", mct_init);
diff --git a/drivers/clocksource/mxs_timer.c b/drivers/clocksource/mxs_timer.c
new file mode 100644
index 0000000..02af420
--- /dev/null
+++ b/drivers/clocksource/mxs_timer.c
@@ -0,0 +1,304 @@
+/*
+ *  Copyright (C) 2000-2001 Deep Blue Solutions
+ *  Copyright (C) 2002 Shane Nay (shane@minirl.com)
+ *  Copyright (C) 2006-2007 Pavel Pisa (ppisa@pikron.com)
+ *  Copyright (C) 2008 Juergen Beisert (kernel@pengutronix.de)
+ *  Copyright (C) 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/err.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/clockchips.h>
+#include <linux/clk.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/stmp_device.h>
+
+#include <asm/mach/time.h>
+#include <asm/sched_clock.h>
+
+/*
+ * There are 2 versions of the timrot on Freescale MXS-based SoCs.
+ * The v1 on MX23 only gets 16 bits counter, while v2 on MX28
+ * extends the counter to 32 bits.
+ *
+ * The implementation uses two timers, one for clock_event and
+ * another for clocksource. MX28 uses timrot 0 and 1, while MX23
+ * uses 0 and 2.
+ */
+
+#define MX23_TIMROT_VERSION_OFFSET	0x0a0
+#define MX28_TIMROT_VERSION_OFFSET	0x120
+#define BP_TIMROT_MAJOR_VERSION		24
+#define BV_TIMROT_VERSION_1		0x01
+#define BV_TIMROT_VERSION_2		0x02
+#define timrot_is_v1()	(timrot_major_version == BV_TIMROT_VERSION_1)
+
+/*
+ * There are 4 registers for each timrotv2 instance, and 2 registers
+ * for each timrotv1. So address step 0x40 in macros below strides
+ * one instance of timrotv2 while two instances of timrotv1.
+ *
+ * As the result, HW_TIMROT_XXXn(1) defines the address of timrot1
+ * on MX28 while timrot2 on MX23.
+ */
+/* common between v1 and v2 */
+#define HW_TIMROT_ROTCTRL		0x00
+#define HW_TIMROT_TIMCTRLn(n)		(0x20 + (n) * 0x40)
+/* v1 only */
+#define HW_TIMROT_TIMCOUNTn(n)		(0x30 + (n) * 0x40)
+/* v2 only */
+#define HW_TIMROT_RUNNING_COUNTn(n)	(0x30 + (n) * 0x40)
+#define HW_TIMROT_FIXED_COUNTn(n)	(0x40 + (n) * 0x40)
+
+#define BM_TIMROT_TIMCTRLn_RELOAD	(1 << 6)
+#define BM_TIMROT_TIMCTRLn_UPDATE	(1 << 7)
+#define BM_TIMROT_TIMCTRLn_IRQ_EN	(1 << 14)
+#define BM_TIMROT_TIMCTRLn_IRQ		(1 << 15)
+#define BP_TIMROT_TIMCTRLn_SELECT	0
+#define BV_TIMROTv1_TIMCTRLn_SELECT__32KHZ_XTAL		0x8
+#define BV_TIMROTv2_TIMCTRLn_SELECT__32KHZ_XTAL		0xb
+#define BV_TIMROTv2_TIMCTRLn_SELECT__TICK_ALWAYS	0xf
+
+static struct clock_event_device mxs_clockevent_device;
+static enum clock_event_mode mxs_clockevent_mode = CLOCK_EVT_MODE_UNUSED;
+
+static void __iomem *mxs_timrot_base;
+static u32 timrot_major_version;
+
+static inline void timrot_irq_disable(void)
+{
+	__raw_writel(BM_TIMROT_TIMCTRLn_IRQ_EN, mxs_timrot_base +
+		     HW_TIMROT_TIMCTRLn(0) + STMP_OFFSET_REG_CLR);
+}
+
+static inline void timrot_irq_enable(void)
+{
+	__raw_writel(BM_TIMROT_TIMCTRLn_IRQ_EN, mxs_timrot_base +
+		     HW_TIMROT_TIMCTRLn(0) + STMP_OFFSET_REG_SET);
+}
+
+static void timrot_irq_acknowledge(void)
+{
+	__raw_writel(BM_TIMROT_TIMCTRLn_IRQ, mxs_timrot_base +
+		     HW_TIMROT_TIMCTRLn(0) + STMP_OFFSET_REG_CLR);
+}
+
+static cycle_t timrotv1_get_cycles(struct clocksource *cs)
+{
+	return ~((__raw_readl(mxs_timrot_base + HW_TIMROT_TIMCOUNTn(1))
+			& 0xffff0000) >> 16);
+}
+
+static int timrotv1_set_next_event(unsigned long evt,
+					struct clock_event_device *dev)
+{
+	/* timrot decrements the count */
+	__raw_writel(evt, mxs_timrot_base + HW_TIMROT_TIMCOUNTn(0));
+
+	return 0;
+}
+
+static int timrotv2_set_next_event(unsigned long evt,
+					struct clock_event_device *dev)
+{
+	/* timrot decrements the count */
+	__raw_writel(evt, mxs_timrot_base + HW_TIMROT_FIXED_COUNTn(0));
+
+	return 0;
+}
+
+static irqreturn_t mxs_timer_interrupt(int irq, void *dev_id)
+{
+	struct clock_event_device *evt = dev_id;
+
+	timrot_irq_acknowledge();
+	evt->event_handler(evt);
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction mxs_timer_irq = {
+	.name		= "MXS Timer Tick",
+	.dev_id		= &mxs_clockevent_device,
+	.flags		= IRQF_TIMER | IRQF_IRQPOLL,
+	.handler	= mxs_timer_interrupt,
+};
+
+#ifdef DEBUG
+static const char *clock_event_mode_label[] const = {
+	[CLOCK_EVT_MODE_PERIODIC] = "CLOCK_EVT_MODE_PERIODIC",
+	[CLOCK_EVT_MODE_ONESHOT]  = "CLOCK_EVT_MODE_ONESHOT",
+	[CLOCK_EVT_MODE_SHUTDOWN] = "CLOCK_EVT_MODE_SHUTDOWN",
+	[CLOCK_EVT_MODE_UNUSED]   = "CLOCK_EVT_MODE_UNUSED"
+};
+#endif /* DEBUG */
+
+static void mxs_set_mode(enum clock_event_mode mode,
+				struct clock_event_device *evt)
+{
+	/* Disable interrupt in timer module */
+	timrot_irq_disable();
+
+	if (mode != mxs_clockevent_mode) {
+		/* Set event time into the furthest future */
+		if (timrot_is_v1())
+			__raw_writel(0xffff,
+				mxs_timrot_base + HW_TIMROT_TIMCOUNTn(1));
+		else
+			__raw_writel(0xffffffff,
+				mxs_timrot_base + HW_TIMROT_FIXED_COUNTn(1));
+
+		/* Clear pending interrupt */
+		timrot_irq_acknowledge();
+	}
+
+#ifdef DEBUG
+	pr_info("%s: changing mode from %s to %s\n", __func__,
+		clock_event_mode_label[mxs_clockevent_mode],
+		clock_event_mode_label[mode]);
+#endif /* DEBUG */
+
+	/* Remember timer mode */
+	mxs_clockevent_mode = mode;
+
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		pr_err("%s: Periodic mode is not implemented\n", __func__);
+		break;
+	case CLOCK_EVT_MODE_ONESHOT:
+		timrot_irq_enable();
+		break;
+	case CLOCK_EVT_MODE_SHUTDOWN:
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_RESUME:
+		/* Left event sources disabled, no more interrupts appear */
+		break;
+	}
+}
+
+static struct clock_event_device mxs_clockevent_device = {
+	.name		= "mxs_timrot",
+	.features	= CLOCK_EVT_FEAT_ONESHOT,
+	.set_mode	= mxs_set_mode,
+	.set_next_event	= timrotv2_set_next_event,
+	.rating		= 200,
+};
+
+static int __init mxs_clockevent_init(struct clk *timer_clk)
+{
+	if (timrot_is_v1())
+		mxs_clockevent_device.set_next_event = timrotv1_set_next_event;
+	mxs_clockevent_device.cpumask = cpumask_of(0);
+	clockevents_config_and_register(&mxs_clockevent_device,
+					clk_get_rate(timer_clk),
+					timrot_is_v1() ? 0xf : 0x2,
+					timrot_is_v1() ? 0xfffe : 0xfffffffe);
+
+	return 0;
+}
+
+static struct clocksource clocksource_mxs = {
+	.name		= "mxs_timer",
+	.rating		= 200,
+	.read		= timrotv1_get_cycles,
+	.mask		= CLOCKSOURCE_MASK(16),
+	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static u32 notrace mxs_read_sched_clock_v2(void)
+{
+	return ~readl_relaxed(mxs_timrot_base + HW_TIMROT_RUNNING_COUNTn(1));
+}
+
+static int __init mxs_clocksource_init(struct clk *timer_clk)
+{
+	unsigned int c = clk_get_rate(timer_clk);
+
+	if (timrot_is_v1())
+		clocksource_register_hz(&clocksource_mxs, c);
+	else {
+		clocksource_mmio_init(mxs_timrot_base + HW_TIMROT_RUNNING_COUNTn(1),
+			"mxs_timer", c, 200, 32, clocksource_mmio_readl_down);
+		setup_sched_clock(mxs_read_sched_clock_v2, 32, c);
+	}
+
+	return 0;
+}
+
+static void __init mxs_timer_init(struct device_node *np)
+{
+	struct clk *timer_clk;
+	int irq;
+
+	mxs_timrot_base = of_iomap(np, 0);
+	WARN_ON(!mxs_timrot_base);
+
+	timer_clk = of_clk_get(np, 0);
+	if (IS_ERR(timer_clk)) {
+		pr_err("%s: failed to get clk\n", __func__);
+		return;
+	}
+
+	clk_prepare_enable(timer_clk);
+
+	/*
+	 * Initialize timers to a known state
+	 */
+	stmp_reset_block(mxs_timrot_base + HW_TIMROT_ROTCTRL);
+
+	/* get timrot version */
+	timrot_major_version = __raw_readl(mxs_timrot_base +
+			(of_device_is_compatible(np, "fsl,imx23-timrot") ?
+						MX23_TIMROT_VERSION_OFFSET :
+						MX28_TIMROT_VERSION_OFFSET));
+	timrot_major_version >>= BP_TIMROT_MAJOR_VERSION;
+
+	/* one for clock_event */
+	__raw_writel((timrot_is_v1() ?
+			BV_TIMROTv1_TIMCTRLn_SELECT__32KHZ_XTAL :
+			BV_TIMROTv2_TIMCTRLn_SELECT__TICK_ALWAYS) |
+			BM_TIMROT_TIMCTRLn_UPDATE |
+			BM_TIMROT_TIMCTRLn_IRQ_EN,
+			mxs_timrot_base + HW_TIMROT_TIMCTRLn(0));
+
+	/* another for clocksource */
+	__raw_writel((timrot_is_v1() ?
+			BV_TIMROTv1_TIMCTRLn_SELECT__32KHZ_XTAL :
+			BV_TIMROTv2_TIMCTRLn_SELECT__TICK_ALWAYS) |
+			BM_TIMROT_TIMCTRLn_RELOAD,
+			mxs_timrot_base + HW_TIMROT_TIMCTRLn(1));
+
+	/* set clocksource timer fixed count to the maximum */
+	if (timrot_is_v1())
+		__raw_writel(0xffff,
+			mxs_timrot_base + HW_TIMROT_TIMCOUNTn(1));
+	else
+		__raw_writel(0xffffffff,
+			mxs_timrot_base + HW_TIMROT_FIXED_COUNTn(1));
+
+	/* init and register the timer to the framework */
+	mxs_clocksource_init(timer_clk);
+	mxs_clockevent_init(timer_clk);
+
+	/* Make irqs happen */
+	irq = irq_of_parse_and_map(np, 0);
+	setup_irq(irq, &mxs_timer_irq);
+}
+CLOCKSOURCE_OF_DECLARE(mxs, "fsl,timrot", mxs_timer_init);
diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
index 488c14c..08d0c41 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -54,62 +54,100 @@ struct sh_cmt_priv {
 	struct clocksource cs;
 	unsigned long total_cycles;
 	bool cs_enabled;
+
+	/* callbacks for CMSTR and CMCSR access */
+	unsigned long (*read_control)(void __iomem *base, unsigned long offs);
+	void (*write_control)(void __iomem *base, unsigned long offs,
+			      unsigned long value);
+
+	/* callbacks for CMCNT and CMCOR access */
+	unsigned long (*read_count)(void __iomem *base, unsigned long offs);
+	void (*write_count)(void __iomem *base, unsigned long offs,
+			    unsigned long value);
 };
 
-static DEFINE_RAW_SPINLOCK(sh_cmt_lock);
+/* Examples of supported CMT timer register layouts and I/O access widths:
+ *
+ * "16-bit counter and 16-bit control" as found on sh7263:
+ * CMSTR 0xfffec000 16-bit
+ * CMCSR 0xfffec002 16-bit
+ * CMCNT 0xfffec004 16-bit
+ * CMCOR 0xfffec006 16-bit
+ *
+ * "32-bit counter and 16-bit control" as found on sh7372, sh73a0, r8a7740:
+ * CMSTR 0xffca0000 16-bit
+ * CMCSR 0xffca0060 16-bit
+ * CMCNT 0xffca0064 32-bit
+ * CMCOR 0xffca0068 32-bit
+ */
+
+static unsigned long sh_cmt_read16(void __iomem *base, unsigned long offs)
+{
+	return ioread16(base + (offs << 1));
+}
+
+static unsigned long sh_cmt_read32(void __iomem *base, unsigned long offs)
+{
+	return ioread32(base + (offs << 2));
+}
+
+static void sh_cmt_write16(void __iomem *base, unsigned long offs,
+			   unsigned long value)
+{
+	iowrite16(value, base + (offs << 1));
+}
+
+static void sh_cmt_write32(void __iomem *base, unsigned long offs,
+			   unsigned long value)
+{
+	iowrite32(value, base + (offs << 2));
+}
 
-#define CMSTR -1 /* shared register */
 #define CMCSR 0 /* channel register */
 #define CMCNT 1 /* channel register */
 #define CMCOR 2 /* channel register */
 
-static inline unsigned long sh_cmt_read(struct sh_cmt_priv *p, int reg_nr)
+static inline unsigned long sh_cmt_read_cmstr(struct sh_cmt_priv *p)
 {
 	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
-	void __iomem *base = p->mapbase;
-	unsigned long offs;
-
-	if (reg_nr == CMSTR) {
-		offs = 0;
-		base -= cfg->channel_offset;
-	} else
-		offs = reg_nr;
-
-	if (p->width == 16)
-		offs <<= 1;
-	else {
-		offs <<= 2;
-		if ((reg_nr == CMCNT) || (reg_nr == CMCOR))
-			return ioread32(base + offs);
-	}
 
-	return ioread16(base + offs);
+	return p->read_control(p->mapbase - cfg->channel_offset, 0);
 }
 
-static inline void sh_cmt_write(struct sh_cmt_priv *p, int reg_nr,
-				unsigned long value)
+static inline unsigned long sh_cmt_read_cmcsr(struct sh_cmt_priv *p)
+{
+	return p->read_control(p->mapbase, CMCSR);
+}
+
+static inline unsigned long sh_cmt_read_cmcnt(struct sh_cmt_priv *p)
+{
+	return p->read_count(p->mapbase, CMCNT);
+}
+
+static inline void sh_cmt_write_cmstr(struct sh_cmt_priv *p,
+				      unsigned long value)
 {
 	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
-	void __iomem *base = p->mapbase;
-	unsigned long offs;
-
-	if (reg_nr == CMSTR) {
-		offs = 0;
-		base -= cfg->channel_offset;
-	} else
-		offs = reg_nr;
-
-	if (p->width == 16)
-		offs <<= 1;
-	else {
-		offs <<= 2;
-		if ((reg_nr == CMCNT) || (reg_nr == CMCOR)) {
-			iowrite32(value, base + offs);
-			return;
-		}
-	}
 
-	iowrite16(value, base + offs);
+	p->write_control(p->mapbase - cfg->channel_offset, 0, value);
+}
+
+static inline void sh_cmt_write_cmcsr(struct sh_cmt_priv *p,
+				      unsigned long value)
+{
+	p->write_control(p->mapbase, CMCSR, value);
+}
+
+static inline void sh_cmt_write_cmcnt(struct sh_cmt_priv *p,
+				      unsigned long value)
+{
+	p->write_count(p->mapbase, CMCNT, value);
+}
+
+static inline void sh_cmt_write_cmcor(struct sh_cmt_priv *p,
+				      unsigned long value)
+{
+	p->write_count(p->mapbase, CMCOR, value);
 }
 
 static unsigned long sh_cmt_get_counter(struct sh_cmt_priv *p,
@@ -118,15 +156,15 @@ static unsigned long sh_cmt_get_counter(struct sh_cmt_priv *p,
 	unsigned long v1, v2, v3;
 	int o1, o2;
 
-	o1 = sh_cmt_read(p, CMCSR) & p->overflow_bit;
+	o1 = sh_cmt_read_cmcsr(p) & p->overflow_bit;
 
 	/* Make sure the timer value is stable. Stolen from acpi_pm.c */
 	do {
 		o2 = o1;
-		v1 = sh_cmt_read(p, CMCNT);
-		v2 = sh_cmt_read(p, CMCNT);
-		v3 = sh_cmt_read(p, CMCNT);
-		o1 = sh_cmt_read(p, CMCSR) & p->overflow_bit;
+		v1 = sh_cmt_read_cmcnt(p);
+		v2 = sh_cmt_read_cmcnt(p);
+		v3 = sh_cmt_read_cmcnt(p);
+		o1 = sh_cmt_read_cmcsr(p) & p->overflow_bit;
 	} while (unlikely((o1 != o2) || (v1 > v2 && v1 < v3)
 			  || (v2 > v3 && v2 < v1) || (v3 > v1 && v3 < v2)));
 
@@ -134,6 +172,7 @@ static unsigned long sh_cmt_get_counter(struct sh_cmt_priv *p,
 	return v2;
 }
 
+static DEFINE_RAW_SPINLOCK(sh_cmt_lock);
 
 static void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start)
 {
@@ -142,14 +181,14 @@ static void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start)
 
 	/* start stop register shared by multiple timer channels */
 	raw_spin_lock_irqsave(&sh_cmt_lock, flags);
-	value = sh_cmt_read(p, CMSTR);
+	value = sh_cmt_read_cmstr(p);
 
 	if (start)
 		value |= 1 << cfg->timer_bit;
 	else
 		value &= ~(1 << cfg->timer_bit);
 
-	sh_cmt_write(p, CMSTR, value);
+	sh_cmt_write_cmstr(p, value);
 	raw_spin_unlock_irqrestore(&sh_cmt_lock, flags);
 }
 
@@ -173,14 +212,14 @@ static int sh_cmt_enable(struct sh_cmt_priv *p, unsigned long *rate)
 	/* configure channel, periodic mode and maximum timeout */
 	if (p->width == 16) {
 		*rate = clk_get_rate(p->clk) / 512;
-		sh_cmt_write(p, CMCSR, 0x43);
+		sh_cmt_write_cmcsr(p, 0x43);
 	} else {
 		*rate = clk_get_rate(p->clk) / 8;
-		sh_cmt_write(p, CMCSR, 0x01a4);
+		sh_cmt_write_cmcsr(p, 0x01a4);
 	}
 
-	sh_cmt_write(p, CMCOR, 0xffffffff);
-	sh_cmt_write(p, CMCNT, 0);
+	sh_cmt_write_cmcor(p, 0xffffffff);
+	sh_cmt_write_cmcnt(p, 0);
 
 	/*
 	 * According to the sh73a0 user's manual, as CMCNT can be operated
@@ -194,12 +233,12 @@ static int sh_cmt_enable(struct sh_cmt_priv *p, unsigned long *rate)
 	 * take RCLKx2 at maximum.
 	 */
 	for (k = 0; k < 100; k++) {
-		if (!sh_cmt_read(p, CMCNT))
+		if (!sh_cmt_read_cmcnt(p))
 			break;
 		udelay(1);
 	}
 
-	if (sh_cmt_read(p, CMCNT)) {
+	if (sh_cmt_read_cmcnt(p)) {
 		dev_err(&p->pdev->dev, "cannot clear CMCNT\n");
 		ret = -ETIMEDOUT;
 		goto err1;
@@ -222,7 +261,7 @@ static void sh_cmt_disable(struct sh_cmt_priv *p)
 	sh_cmt_start_stop_ch(p, 0);
 
 	/* disable interrupts in CMT block */
-	sh_cmt_write(p, CMCSR, 0);
+	sh_cmt_write_cmcsr(p, 0);
 
 	/* stop clock */
 	clk_disable(p->clk);
@@ -270,7 +309,7 @@ static void sh_cmt_clock_event_program_verify(struct sh_cmt_priv *p,
 		if (new_match > p->max_match_value)
 			new_match = p->max_match_value;
 
-		sh_cmt_write(p, CMCOR, new_match);
+		sh_cmt_write_cmcor(p, new_match);
 
 		now = sh_cmt_get_counter(p, &has_wrapped);
 		if (has_wrapped && (new_match > p->match_value)) {
@@ -346,7 +385,7 @@ static irqreturn_t sh_cmt_interrupt(int irq, void *dev_id)
 	struct sh_cmt_priv *p = dev_id;
 
 	/* clear flags */
-	sh_cmt_write(p, CMCSR, sh_cmt_read(p, CMCSR) & p->clear_bits);
+	sh_cmt_write_cmcsr(p, sh_cmt_read_cmcsr(p) & p->clear_bits);
 
 	/* update clock source counter to begin with if enabled
 	 * the wrap flag should be cleared by the timer specific
@@ -625,14 +664,6 @@ static int sh_cmt_register(struct sh_cmt_priv *p, char *name,
 			   unsigned long clockevent_rating,
 			   unsigned long clocksource_rating)
 {
-	if (p->width == (sizeof(p->max_match_value) * 8))
-		p->max_match_value = ~0;
-	else
-		p->max_match_value = (1 << p->width) - 1;
-
-	p->match_value = p->max_match_value;
-	raw_spin_lock_init(&p->lock);
-
 	if (clockevent_rating)
 		sh_cmt_register_clockevent(p, name, clockevent_rating);
 
@@ -657,8 +688,6 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
 		goto err0;
 	}
 
-	platform_set_drvdata(pdev, p);
-
 	res = platform_get_resource(p->pdev, IORESOURCE_MEM, 0);
 	if (!res) {
 		dev_err(&p->pdev->dev, "failed to get I/O memory\n");
@@ -693,32 +722,51 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
 		goto err1;
 	}
 
+	p->read_control = sh_cmt_read16;
+	p->write_control = sh_cmt_write16;
+
 	if (resource_size(res) == 6) {
 		p->width = 16;
+		p->read_count = sh_cmt_read16;
+		p->write_count = sh_cmt_write16;
 		p->overflow_bit = 0x80;
 		p->clear_bits = ~0x80;
 	} else {
 		p->width = 32;
+		p->read_count = sh_cmt_read32;
+		p->write_count = sh_cmt_write32;
 		p->overflow_bit = 0x8000;
 		p->clear_bits = ~0xc000;
 	}
 
+	if (p->width == (sizeof(p->max_match_value) * 8))
+		p->max_match_value = ~0;
+	else
+		p->max_match_value = (1 << p->width) - 1;
+
+	p->match_value = p->max_match_value;
+	raw_spin_lock_init(&p->lock);
+
 	ret = sh_cmt_register(p, (char *)dev_name(&p->pdev->dev),
 			      cfg->clockevent_rating,
 			      cfg->clocksource_rating);
 	if (ret) {
 		dev_err(&p->pdev->dev, "registration failed\n");
-		goto err1;
+		goto err2;
 	}
 	p->cs_enabled = false;
 
 	ret = setup_irq(irq, &p->irqaction);
 	if (ret) {
 		dev_err(&p->pdev->dev, "failed to request irq %d\n", irq);
-		goto err1;
+		goto err2;
 	}
 
+	platform_set_drvdata(pdev, p);
+
 	return 0;
+err2:
+	clk_put(p->clk);
 
 err1:
 	iounmap(p->mapbase);
@@ -751,7 +799,6 @@ static int sh_cmt_probe(struct platform_device *pdev)
 	ret = sh_cmt_setup(p, pdev);
 	if (ret) {
 		kfree(p);
-		platform_set_drvdata(pdev, NULL);
 		pm_runtime_idle(&pdev->dev);
 		return ret;
 	}
@@ -791,7 +838,7 @@ static void __exit sh_cmt_exit(void)
 }
 
 early_platform_init("earlytimer", &sh_cmt_device_driver);
-module_init(sh_cmt_init);
+subsys_initcall(sh_cmt_init);
 module_exit(sh_cmt_exit);
 
 MODULE_AUTHOR("Magnus Damm");
diff --git a/drivers/clocksource/sh_mtu2.c b/drivers/clocksource/sh_mtu2.c
index 83943e2..4aac9ee 100644
--- a/drivers/clocksource/sh_mtu2.c
+++ b/drivers/clocksource/sh_mtu2.c
@@ -386,7 +386,7 @@ static void __exit sh_mtu2_exit(void)
 }
 
 early_platform_init("earlytimer", &sh_mtu2_device_driver);
-module_init(sh_mtu2_init);
+subsys_initcall(sh_mtu2_init);
 module_exit(sh_mtu2_exit);
 
 MODULE_AUTHOR("Magnus Damm");
diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c
index b4502edc..78b8dae 100644
--- a/drivers/clocksource/sh_tmu.c
+++ b/drivers/clocksource/sh_tmu.c
@@ -549,7 +549,7 @@ static void __exit sh_tmu_exit(void)
 }
 
 early_platform_init("earlytimer", &sh_tmu_device_driver);
-module_init(sh_tmu_init);
+subsys_initcall(sh_tmu_init);
 module_exit(sh_tmu_exit);
 
 MODULE_AUTHOR("Magnus Damm");
diff --git a/drivers/clocksource/sunxi_timer.c b/drivers/clocksource/sunxi_timer.c
index 4086b91..0ce85e2 100644
--- a/drivers/clocksource/sunxi_timer.c
+++ b/drivers/clocksource/sunxi_timer.c
@@ -23,7 +23,7 @@
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <linux/sunxi_timer.h>
-#include <linux/clk-provider.h>
+#include <linux/clk/sunxi.h>
 
 #define TIMER_CTL_REG		0x00
 #define TIMER_CTL_ENABLE		(1 << 0)
@@ -123,7 +123,7 @@ void __init sunxi_timer_init(void)
 	if (irq <= 0)
 		panic("Can't parse IRQ");
 
-	of_clk_init(NULL);
+	sunxi_init_clocks();
 
 	clk = of_clk_get(node, 0);
 	if (IS_ERR(clk))
diff --git a/drivers/clocksource/tegra20_timer.c b/drivers/clocksource/tegra20_timer.c
index 0bde03f..ae877b0 100644
--- a/drivers/clocksource/tegra20_timer.c
+++ b/drivers/clocksource/tegra20_timer.c
@@ -154,29 +154,12 @@ static struct irqaction tegra_timer_irq = {
 	.dev_id		= &tegra_clockevent,
 };
 
-static const struct of_device_id timer_match[] __initconst = {
-	{ .compatible = "nvidia,tegra20-timer" },
-	{}
-};
-
-static const struct of_device_id rtc_match[] __initconst = {
-	{ .compatible = "nvidia,tegra20-rtc" },
-	{}
-};
-
-static void __init tegra20_init_timer(void)
+static void __init tegra20_init_timer(struct device_node *np)
 {
-	struct device_node *np;
 	struct clk *clk;
 	unsigned long rate;
 	int ret;
 
-	np = of_find_matching_node(NULL, timer_match);
-	if (!np) {
-		pr_err("Failed to find timer DT node\n");
-		BUG();
-	}
-
 	timer_reg_base = of_iomap(np, 0);
 	if (!timer_reg_base) {
 		pr_err("Can't map timer registers\n");
@@ -189,7 +172,7 @@ static void __init tegra20_init_timer(void)
 		BUG();
 	}
 
-	clk = clk_get_sys("timer", NULL);
+	clk = of_clk_get(np, 0);
 	if (IS_ERR(clk)) {
 		pr_warn("Unable to get timer clock. Assuming 12Mhz input clock.\n");
 		rate = 12000000;
@@ -200,30 +183,6 @@ static void __init tegra20_init_timer(void)
 
 	of_node_put(np);
 
-	np = of_find_matching_node(NULL, rtc_match);
-	if (!np) {
-		pr_err("Failed to find RTC DT node\n");
-		BUG();
-	}
-
-	rtc_base = of_iomap(np, 0);
-	if (!rtc_base) {
-		pr_err("Can't map RTC registers");
-		BUG();
-	}
-
-	/*
-	 * rtc registers are used by read_persistent_clock, keep the rtc clock
-	 * enabled
-	 */
-	clk = clk_get_sys("rtc-tegra", NULL);
-	if (IS_ERR(clk))
-		pr_warn("Unable to get rtc-tegra clock\n");
-	else
-		clk_prepare_enable(clk);
-
-	of_node_put(np);
-
 	switch (rate) {
 	case 12000000:
 		timer_writel(0x000b, TIMERUS_USEC_CFG);
@@ -259,12 +218,34 @@ static void __init tegra20_init_timer(void)
 	tegra_clockevent.irq = tegra_timer_irq.irq;
 	clockevents_config_and_register(&tegra_clockevent, 1000000,
 					0x1, 0x1fffffff);
-#ifdef CONFIG_HAVE_ARM_TWD
-	twd_local_timer_of_register();
-#endif
+}
+CLOCKSOURCE_OF_DECLARE(tegra20_timer, "nvidia,tegra20-timer", tegra20_init_timer);
+
+static void __init tegra20_init_rtc(struct device_node *np)
+{
+	struct clk *clk;
+
+	rtc_base = of_iomap(np, 0);
+	if (!rtc_base) {
+		pr_err("Can't map RTC registers");
+		BUG();
+	}
+
+	/*
+	 * rtc registers are used by read_persistent_clock, keep the rtc clock
+	 * enabled
+	 */
+	clk = of_clk_get(np, 0);
+	if (IS_ERR(clk))
+		pr_warn("Unable to get rtc-tegra clock\n");
+	else
+		clk_prepare_enable(clk);
+
+	of_node_put(np);
+
 	register_persistent_clock(NULL, tegra_read_persistent_clock);
 }
-CLOCKSOURCE_OF_DECLARE(tegra20, "nvidia,tegra20-timer", tegra20_init_timer);
+CLOCKSOURCE_OF_DECLARE(tegra20_rtc, "nvidia,tegra20-rtc", tegra20_init_rtc);
 
 #ifdef CONFIG_PM
 static u32 usec_config;
diff --git a/drivers/clocksource/timer-marco.c b/drivers/clocksource/timer-marco.c
new file mode 100644
index 0000000..97738db
--- /dev/null
+++ b/drivers/clocksource/timer-marco.c
@@ -0,0 +1,299 @@
+/*
+ * 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/slab.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+#include <asm/sched_clock.h>
+#include <asm/localtimer.h>
+#include <asm/mach/time.h>
+
+#define SIRFSOC_TIMER_32COUNTER_0_CTRL			0x0000
+#define SIRFSOC_TIMER_32COUNTER_1_CTRL			0x0004
+#define SIRFSOC_TIMER_MATCH_0				0x0018
+#define SIRFSOC_TIMER_MATCH_1				0x001c
+#define SIRFSOC_TIMER_COUNTER_0				0x0048
+#define SIRFSOC_TIMER_COUNTER_1				0x004c
+#define SIRFSOC_TIMER_INTR_STATUS			0x0060
+#define SIRFSOC_TIMER_WATCHDOG_EN			0x0064
+#define SIRFSOC_TIMER_64COUNTER_CTRL			0x0068
+#define SIRFSOC_TIMER_64COUNTER_LO			0x006c
+#define SIRFSOC_TIMER_64COUNTER_HI			0x0070
+#define SIRFSOC_TIMER_64COUNTER_LOAD_LO			0x0074
+#define SIRFSOC_TIMER_64COUNTER_LOAD_HI			0x0078
+#define SIRFSOC_TIMER_64COUNTER_RLATCHED_LO		0x007c
+#define SIRFSOC_TIMER_64COUNTER_RLATCHED_HI		0x0080
+
+#define SIRFSOC_TIMER_REG_CNT 6
+
+static const u32 sirfsoc_timer_reg_list[SIRFSOC_TIMER_REG_CNT] = {
+	SIRFSOC_TIMER_WATCHDOG_EN,
+	SIRFSOC_TIMER_32COUNTER_0_CTRL,
+	SIRFSOC_TIMER_32COUNTER_1_CTRL,
+	SIRFSOC_TIMER_64COUNTER_CTRL,
+	SIRFSOC_TIMER_64COUNTER_RLATCHED_LO,
+	SIRFSOC_TIMER_64COUNTER_RLATCHED_HI,
+};
+
+static u32 sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT];
+
+static void __iomem *sirfsoc_timer_base;
+
+/* disable count and interrupt */
+static inline void sirfsoc_timer_count_disable(int idx)
+{
+	writel_relaxed(readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL + 4 * idx) & ~0x7,
+		sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL + 4 * idx);
+}
+
+/* enable count and interrupt */
+static inline void sirfsoc_timer_count_enable(int idx)
+{
+	writel_relaxed(readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL + 4 * idx) | 0x7,
+		sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL + 4 * idx);
+}
+
+/* timer interrupt handler */
+static irqreturn_t sirfsoc_timer_interrupt(int irq, void *dev_id)
+{
+	struct clock_event_device *ce = dev_id;
+	int cpu = smp_processor_id();
+
+	/* clear timer interrupt */
+	writel_relaxed(BIT(cpu), sirfsoc_timer_base + SIRFSOC_TIMER_INTR_STATUS);
+
+	if (ce->mode == CLOCK_EVT_MODE_ONESHOT)
+		sirfsoc_timer_count_disable(cpu);
+
+	ce->event_handler(ce);
+
+	return IRQ_HANDLED;
+}
+
+/* read 64-bit timer counter */
+static cycle_t sirfsoc_timer_read(struct clocksource *cs)
+{
+	u64 cycles;
+
+	writel_relaxed((readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL) |
+			BIT(0)) & ~BIT(1), sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL);
+
+	cycles = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_RLATCHED_HI);
+	cycles = (cycles << 32) | readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_RLATCHED_LO);
+
+	return cycles;
+}
+
+static int sirfsoc_timer_set_next_event(unsigned long delta,
+	struct clock_event_device *ce)
+{
+	int cpu = smp_processor_id();
+
+	writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_0 +
+		4 * cpu);
+	writel_relaxed(delta, sirfsoc_timer_base + SIRFSOC_TIMER_MATCH_0 +
+		4 * cpu);
+
+	/* enable the tick */
+	sirfsoc_timer_count_enable(cpu);
+
+	return 0;
+}
+
+static void sirfsoc_timer_set_mode(enum clock_event_mode mode,
+	struct clock_event_device *ce)
+{
+	switch (mode) {
+	case CLOCK_EVT_MODE_ONESHOT:
+		/* enable in set_next_event */
+		break;
+	default:
+		break;
+	}
+
+	sirfsoc_timer_count_disable(smp_processor_id());
+}
+
+static void sirfsoc_clocksource_suspend(struct clocksource *cs)
+{
+	int i;
+
+	for (i = 0; i < SIRFSOC_TIMER_REG_CNT; i++)
+		sirfsoc_timer_reg_val[i] = readl_relaxed(sirfsoc_timer_base + sirfsoc_timer_reg_list[i]);
+}
+
+static void sirfsoc_clocksource_resume(struct clocksource *cs)
+{
+	int i;
+
+	for (i = 0; i < SIRFSOC_TIMER_REG_CNT - 2; i++)
+		writel_relaxed(sirfsoc_timer_reg_val[i], sirfsoc_timer_base + sirfsoc_timer_reg_list[i]);
+
+	writel_relaxed(sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT - 2],
+		sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_LOAD_LO);
+	writel_relaxed(sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT - 1],
+		sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_LOAD_HI);
+
+	writel_relaxed(readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL) |
+		BIT(1) | BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL);
+}
+
+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,
+	.suspend = sirfsoc_clocksource_suspend,
+	.resume = sirfsoc_clocksource_resume,
+};
+
+static struct irqaction sirfsoc_timer_irq = {
+	.name = "sirfsoc_timer0",
+	.flags = IRQF_TIMER | IRQF_NOBALANCING,
+	.handler = sirfsoc_timer_interrupt,
+	.dev_id = &sirfsoc_clockevent,
+};
+
+#ifdef CONFIG_LOCAL_TIMERS
+
+static struct irqaction sirfsoc_timer1_irq = {
+	.name = "sirfsoc_timer1",
+	.flags = IRQF_TIMER | IRQF_NOBALANCING,
+	.handler = sirfsoc_timer_interrupt,
+};
+
+static int __cpuinit sirfsoc_local_timer_setup(struct clock_event_device *ce)
+{
+	/* Use existing clock_event for cpu 0 */
+	if (!smp_processor_id())
+		return 0;
+
+	ce->irq = sirfsoc_timer1_irq.irq;
+	ce->name = "local_timer";
+	ce->features = sirfsoc_clockevent.features;
+	ce->rating = sirfsoc_clockevent.rating;
+	ce->set_mode = sirfsoc_timer_set_mode;
+	ce->set_next_event = sirfsoc_timer_set_next_event;
+	ce->shift = sirfsoc_clockevent.shift;
+	ce->mult = sirfsoc_clockevent.mult;
+	ce->max_delta_ns = sirfsoc_clockevent.max_delta_ns;
+	ce->min_delta_ns = sirfsoc_clockevent.min_delta_ns;
+
+	sirfsoc_timer1_irq.dev_id = ce;
+	BUG_ON(setup_irq(ce->irq, &sirfsoc_timer1_irq));
+	irq_set_affinity(sirfsoc_timer1_irq.irq, cpumask_of(1));
+
+	clockevents_register_device(ce);
+	return 0;
+}
+
+static void sirfsoc_local_timer_stop(struct clock_event_device *ce)
+{
+	sirfsoc_timer_count_disable(1);
+
+	remove_irq(sirfsoc_timer1_irq.irq, &sirfsoc_timer1_irq);
+}
+
+static struct local_timer_ops sirfsoc_local_timer_ops __cpuinitdata = {
+	.setup	= sirfsoc_local_timer_setup,
+	.stop	= sirfsoc_local_timer_stop,
+};
+#endif /* CONFIG_LOCAL_TIMERS */
+
+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);
+#ifdef CONFIG_LOCAL_TIMERS
+	local_timer_register(&sirfsoc_local_timer_ops);
+#endif
+}
+
+/* initialize the kernel jiffy timer source */
+static void __init sirfsoc_marco_timer_init(void)
+{
+	unsigned long rate;
+	u32 timer_div;
+	struct clk *clk;
+
+	/* timer's input clock is io clock */
+	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);
+
+	/* Initialize the timer dividers */
+	timer_div = rate / CLOCK_TICK_RATE - 1;
+	writel_relaxed(timer_div << 16, sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL);
+	writel_relaxed(timer_div << 16, sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL);
+	writel_relaxed(timer_div << 16, sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_1_CTRL);
+
+	/* Initialize timer counters to 0 */
+	writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_LOAD_LO);
+	writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_LOAD_HI);
+	writel_relaxed(readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL) |
+		BIT(1) | BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL);
+	writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_0);
+	writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_1);
+
+	/* Clear all interrupts */
+	writel_relaxed(0xFFFF, sirfsoc_timer_base + SIRFSOC_TIMER_INTR_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 void __init sirfsoc_of_timer_init(struct device_node *np)
+{
+	sirfsoc_timer_base = of_iomap(np, 0);
+	if (!sirfsoc_timer_base)
+		panic("unable to map timer cpu registers\n");
+
+	sirfsoc_timer_irq.irq = irq_of_parse_and_map(np, 0);
+	if (!sirfsoc_timer_irq.irq)
+		panic("No irq passed for timer0 via DT\n");
+
+#ifdef CONFIG_LOCAL_TIMERS
+	sirfsoc_timer1_irq.irq = irq_of_parse_and_map(np, 1);
+	if (!sirfsoc_timer1_irq.irq)
+		panic("No irq passed for timer1 via DT\n");
+#endif
+
+	sirfsoc_marco_timer_init();
+}
+CLOCKSOURCE_OF_DECLARE(sirfsoc_marco_timer, "sirf,marco-tick", sirfsoc_of_timer_init );
diff --git a/drivers/clocksource/timer-prima2.c b/drivers/clocksource/timer-prima2.c
new file mode 100644
index 0000000..7608826
--- /dev/null
+++ b/drivers/clocksource/timer-prima2.c
@@ -0,0 +1,215 @@
+/*
+ * 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_irq.h>
+#include <linux/of_address.h>
+#include <asm/sched_clock.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)
+
+#define SIRFSOC_TIMER_REG_CNT 11
+
+static const u32 sirfsoc_timer_reg_list[SIRFSOC_TIMER_REG_CNT] = {
+	SIRFSOC_TIMER_MATCH_0, SIRFSOC_TIMER_MATCH_1, SIRFSOC_TIMER_MATCH_2,
+	SIRFSOC_TIMER_MATCH_3, SIRFSOC_TIMER_MATCH_4, SIRFSOC_TIMER_MATCH_5,
+	SIRFSOC_TIMER_INT_EN, SIRFSOC_TIMER_WATCHDOG_EN, SIRFSOC_TIMER_DIV,
+	SIRFSOC_TIMER_LATCHED_LO, SIRFSOC_TIMER_LATCHED_HI,
+};
+
+static u32 sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT];
+
+static void __iomem *sirfsoc_timer_base;
+
+/* 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 void sirfsoc_clocksource_suspend(struct clocksource *cs)
+{
+	int i;
+
+	writel_relaxed(SIRFSOC_TIMER_LATCH_BIT, sirfsoc_timer_base + SIRFSOC_TIMER_LATCH);
+
+	for (i = 0; i < SIRFSOC_TIMER_REG_CNT; i++)
+		sirfsoc_timer_reg_val[i] = readl_relaxed(sirfsoc_timer_base + sirfsoc_timer_reg_list[i]);
+}
+
+static void sirfsoc_clocksource_resume(struct clocksource *cs)
+{
+	int i;
+
+	for (i = 0; i < SIRFSOC_TIMER_REG_CNT - 2; i++)
+		writel_relaxed(sirfsoc_timer_reg_val[i], sirfsoc_timer_base + sirfsoc_timer_reg_list[i]);
+
+	writel_relaxed(sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT - 2], sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_LO);
+	writel_relaxed(sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT - 1], sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_HI);
+}
+
+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,
+	.suspend = sirfsoc_clocksource_suspend,
+	.resume = sirfsoc_clocksource_resume,
+};
+
+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 */
+static u32 notrace sirfsoc_read_sched_clock(void)
+{
+	return (u32)(sirfsoc_timer_read(NULL) & 0xffffffff);
+}
+
+static void __init sirfsoc_clockevent_init(void)
+{
+	sirfsoc_clockevent.cpumask = cpumask_of(0);
+	clockevents_config_and_register(&sirfsoc_clockevent, CLOCK_TICK_RATE,
+					2, -2);
+}
+
+/* initialize the kernel jiffy timer source */
+static void __init sirfsoc_prima2_timer_init(struct device_node *np)
+{
+	unsigned long rate;
+	struct clk *clk;
+
+	/* timer's input clock is io clock */
+	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);
+
+	sirfsoc_timer_base = of_iomap(np, 0);
+	if (!sirfsoc_timer_base)
+		panic("unable to map timer cpu registers\n");
+
+	sirfsoc_timer_irq.irq = irq_of_parse_and_map(np, 0);
+
+	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));
+
+	setup_sched_clock(sirfsoc_read_sched_clock, 32, CLOCK_TICK_RATE);
+
+	BUG_ON(setup_irq(sirfsoc_timer_irq.irq, &sirfsoc_timer_irq));
+
+	sirfsoc_clockevent_init();
+}
+CLOCKSOURCE_OF_DECLARE(sirfsoc_prima2_timer, "sirf,prima2-tick", sirfsoc_prima2_timer_init);
diff --git a/drivers/clocksource/vt8500_timer.c b/drivers/clocksource/vt8500_timer.c
index 8efc86b..64f553f 100644
--- a/drivers/clocksource/vt8500_timer.c
+++ b/drivers/clocksource/vt8500_timer.c
@@ -129,22 +129,10 @@ static struct irqaction irq = {
 	.dev_id  = &clockevent,
 };
 
-static struct of_device_id vt8500_timer_ids[] = {
-	{ .compatible = "via,vt8500-timer" },
-	{ }
-};
-
-static void __init vt8500_timer_init(void)
+static void __init vt8500_timer_init(struct device_node *np)
 {
-	struct device_node *np;
 	int timer_irq;
 
-	np = of_find_matching_node(NULL, vt8500_timer_ids);
-	if (!np) {
-		pr_err("%s: Timer description missing from Device Tree\n",
-								__func__);
-		return;
-	}
 	regbase = of_iomap(np, 0);
 	if (!regbase) {
 		pr_err("%s: Missing iobase description in Device Tree\n",
@@ -177,4 +165,4 @@ static void __init vt8500_timer_init(void)
 					4, 0xf0000000);
 }
 
-CLOCKSOURCE_OF_DECLARE(vt8500, "via,vt8500-timer", vt8500_timer_init)
+CLOCKSOURCE_OF_DECLARE(vt8500, "via,vt8500-timer", vt8500_timer_init);
diff --git a/drivers/connector/cn_proc.c b/drivers/connector/cn_proc.c
index 1110478..08ae128 100644
--- a/drivers/connector/cn_proc.c
+++ b/drivers/connector/cn_proc.c
@@ -232,6 +232,31 @@ void proc_comm_connector(struct task_struct *task)
 	cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL);
 }
 
+void proc_coredump_connector(struct task_struct *task)
+{
+	struct cn_msg *msg;
+	struct proc_event *ev;
+	__u8 buffer[CN_PROC_MSG_SIZE];
+	struct timespec ts;
+
+	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_COREDUMP;
+	ev->event_data.coredump.process_pid = task->pid;
+	ev->event_data.coredump.process_tgid = task->tgid;
+
+	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/connector/connector.c b/drivers/connector/connector.c
index f1b7e24..6ecfa75 100644
--- a/drivers/connector/connector.c
+++ b/drivers/connector/connector.c
@@ -23,7 +23,7 @@
 #include <linux/module.h>
 #include <linux/list.h>
 #include <linux/skbuff.h>
-#include <linux/netlink.h>
+#include <net/netlink.h>
 #include <linux/moduleparam.h>
 #include <linux/connector.h>
 #include <linux/slab.h>
@@ -95,13 +95,13 @@ int cn_netlink_send(struct cn_msg *msg, u32 __group, gfp_t gfp_mask)
 	if (!netlink_has_listeners(dev->nls, group))
 		return -ESRCH;
 
-	size = NLMSG_SPACE(sizeof(*msg) + msg->len);
+	size = sizeof(*msg) + msg->len;
 
-	skb = alloc_skb(size, gfp_mask);
+	skb = nlmsg_new(size, gfp_mask);
 	if (!skb)
 		return -ENOMEM;
 
-	nlh = nlmsg_put(skb, 0, msg->seq, NLMSG_DONE, size - sizeof(*nlh), 0);
+	nlh = nlmsg_put(skb, 0, msg->seq, NLMSG_DONE, size, 0);
 	if (!nlh) {
 		kfree_skb(skb);
 		return -EMSGSIZE;
@@ -124,7 +124,7 @@ static int cn_call_callback(struct sk_buff *skb)
 {
 	struct cn_callback_entry *i, *cbq = NULL;
 	struct cn_dev *dev = &cdev;
-	struct cn_msg *msg = NLMSG_DATA(nlmsg_hdr(skb));
+	struct cn_msg *msg = nlmsg_data(nlmsg_hdr(skb));
 	struct netlink_skb_parms *nsp = &NETLINK_CB(skb);
 	int err = -ENODEV;
 
@@ -162,7 +162,7 @@ static void cn_rx_skb(struct sk_buff *__skb)
 
 	skb = skb_get(__skb);
 
-	if (skb->len >= NLMSG_SPACE(0)) {
+	if (skb->len >= NLMSG_HDRLEN) {
 		nlh = nlmsg_hdr(skb);
 
 		if (nlh->nlmsg_len < sizeof(struct cn_msg) ||
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index 030ddf6..87b7e48 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -2,6 +2,18 @@
 # ARM CPU Frequency scaling drivers
 #
 
+config ARM_BIG_LITTLE_CPUFREQ
+	tristate
+	depends on ARM_CPU_TOPOLOGY
+
+config ARM_DT_BL_CPUFREQ
+	tristate "Generic ARM big LITTLE CPUfreq driver probed via DT"
+	select ARM_BIG_LITTLE_CPUFREQ
+	depends on OF && HAVE_CLK
+	help
+	  This enables the Generic CPUfreq driver for ARM big.LITTLE platform.
+	  This gets frequency tables from DT.
+
 config ARM_OMAP2PLUS_CPUFREQ
 	bool "TI OMAP2+"
 	depends on ARCH_OMAP2PLUS
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index 863fd18..ba9a3e1 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -44,6 +44,11 @@ obj-$(CONFIG_X86_INTEL_PSTATE)		+= intel_pstate.o
 
 ##################################################################################
 # ARM SoC drivers
+obj-$(CONFIG_ARM_BIG_LITTLE_CPUFREQ)	+= arm_big_little.o
+# big LITTLE per platform glues. Keep DT_BL_CPUFREQ as the last entry in all big
+# LITTLE drivers, so that it is probed last.
+obj-$(CONFIG_ARM_DT_BL_CPUFREQ)		+= arm_big_little_dt.o
+
 obj-$(CONFIG_UX500_SOC_DB8500)		+= dbx500-cpufreq.o
 obj-$(CONFIG_ARM_S3C2416_CPUFREQ)	+= s3c2416-cpufreq.o
 obj-$(CONFIG_ARM_S3C64XX_CPUFREQ)	+= s3c64xx-cpufreq.o
diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c
index 57a8774..11b8b4b 100644
--- a/drivers/cpufreq/acpi-cpufreq.c
+++ b/drivers/cpufreq/acpi-cpufreq.c
@@ -423,7 +423,6 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy,
 	struct drv_cmd cmd;
 	unsigned int next_state = 0; /* Index into freq_table */
 	unsigned int next_perf_state = 0; /* Index into perf table */
-	unsigned int i;
 	int result = 0;
 
 	pr_debug("acpi_cpufreq_target %d (%d)\n", target_freq, policy->cpu);
@@ -486,10 +485,7 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy,
 
 	freqs.old = perf->states[perf->state].core_frequency * 1000;
 	freqs.new = data->freq_table[next_state].frequency;
-	for_each_cpu(i, policy->cpus) {
-		freqs.cpu = i;
-		cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
-	}
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
 
 	drv_write(&cmd);
 
@@ -502,10 +498,7 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy,
 		}
 	}
 
-	for_each_cpu(i, policy->cpus) {
-		freqs.cpu = i;
-		cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
-	}
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
 	perf->state = next_perf_state;
 
 out:
diff --git a/drivers/cpufreq/arm_big_little.c b/drivers/cpufreq/arm_big_little.c
new file mode 100644
index 0000000..1d29d1a
--- /dev/null
+++ b/drivers/cpufreq/arm_big_little.c
@@ -0,0 +1,282 @@
+/*
+ * ARM big.LITTLE Platforms CPUFreq support
+ *
+ * Copyright (C) 2013 ARM Ltd.
+ * Sudeep KarkadaNagesha <sudeep.karkadanagesha@arm.com>
+ *
+ * Copyright (C) 2013 Linaro.
+ * Viresh Kumar <viresh.kumar@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/clk.h>
+#include <linux/cpu.h>
+#include <linux/cpufreq.h>
+#include <linux/cpumask.h>
+#include <linux/export.h>
+#include <linux/of_platform.h>
+#include <linux/opp.h>
+#include <linux/slab.h>
+#include <linux/topology.h>
+#include <linux/types.h>
+
+#include "arm_big_little.h"
+
+/* Currently we support only two clusters */
+#define MAX_CLUSTERS	2
+
+static struct cpufreq_arm_bL_ops *arm_bL_ops;
+static struct clk *clk[MAX_CLUSTERS];
+static struct cpufreq_frequency_table *freq_table[MAX_CLUSTERS];
+static atomic_t cluster_usage[MAX_CLUSTERS] = {ATOMIC_INIT(0), ATOMIC_INIT(0)};
+
+static int cpu_to_cluster(int cpu)
+{
+	return topology_physical_package_id(cpu);
+}
+
+static unsigned int bL_cpufreq_get(unsigned int cpu)
+{
+	u32 cur_cluster = cpu_to_cluster(cpu);
+
+	return clk_get_rate(clk[cur_cluster]) / 1000;
+}
+
+/* Validate policy frequency range */
+static int bL_cpufreq_verify_policy(struct cpufreq_policy *policy)
+{
+	u32 cur_cluster = cpu_to_cluster(policy->cpu);
+
+	return cpufreq_frequency_table_verify(policy, freq_table[cur_cluster]);
+}
+
+/* Set clock frequency */
+static int bL_cpufreq_set_target(struct cpufreq_policy *policy,
+		unsigned int target_freq, unsigned int relation)
+{
+	struct cpufreq_freqs freqs;
+	u32 cpu = policy->cpu, freq_tab_idx, cur_cluster;
+	int ret = 0;
+
+	cur_cluster = cpu_to_cluster(policy->cpu);
+
+	freqs.old = bL_cpufreq_get(policy->cpu);
+
+	/* Determine valid target frequency using freq_table */
+	cpufreq_frequency_table_target(policy, freq_table[cur_cluster],
+			target_freq, relation, &freq_tab_idx);
+	freqs.new = freq_table[cur_cluster][freq_tab_idx].frequency;
+
+	freqs.cpu = policy->cpu;
+
+	pr_debug("%s: cpu: %d, cluster: %d, oldfreq: %d, target freq: %d, new freq: %d\n",
+			__func__, cpu, cur_cluster, freqs.old, target_freq,
+			freqs.new);
+
+	if (freqs.old == freqs.new)
+		return 0;
+
+	for_each_cpu(freqs.cpu, policy->cpus)
+		cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+
+	ret = clk_set_rate(clk[cur_cluster], freqs.new * 1000);
+	if (ret) {
+		pr_err("clk_set_rate failed: %d\n", ret);
+		return ret;
+	}
+
+	policy->cur = freqs.new;
+
+	for_each_cpu(freqs.cpu, policy->cpus)
+		cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
+	return ret;
+}
+
+static void put_cluster_clk_and_freq_table(struct device *cpu_dev)
+{
+	u32 cluster = cpu_to_cluster(cpu_dev->id);
+
+	if (!atomic_dec_return(&cluster_usage[cluster])) {
+		clk_put(clk[cluster]);
+		opp_free_cpufreq_table(cpu_dev, &freq_table[cluster]);
+		dev_dbg(cpu_dev, "%s: cluster: %d\n", __func__, cluster);
+	}
+}
+
+static int get_cluster_clk_and_freq_table(struct device *cpu_dev)
+{
+	u32 cluster = cpu_to_cluster(cpu_dev->id);
+	char name[14] = "cpu-cluster.";
+	int ret;
+
+	if (atomic_inc_return(&cluster_usage[cluster]) != 1)
+		return 0;
+
+	ret = arm_bL_ops->init_opp_table(cpu_dev);
+	if (ret) {
+		dev_err(cpu_dev, "%s: init_opp_table failed, cpu: %d, err: %d\n",
+				__func__, cpu_dev->id, ret);
+		goto atomic_dec;
+	}
+
+	ret = opp_init_cpufreq_table(cpu_dev, &freq_table[cluster]);
+	if (ret) {
+		dev_err(cpu_dev, "%s: failed to init cpufreq table, cpu: %d, err: %d\n",
+				__func__, cpu_dev->id, ret);
+		goto atomic_dec;
+	}
+
+	name[12] = cluster + '0';
+	clk[cluster] = clk_get_sys(name, NULL);
+	if (!IS_ERR(clk[cluster])) {
+		dev_dbg(cpu_dev, "%s: clk: %p & freq table: %p, cluster: %d\n",
+				__func__, clk[cluster], freq_table[cluster],
+				cluster);
+		return 0;
+	}
+
+	dev_err(cpu_dev, "%s: Failed to get clk for cpu: %d, cluster: %d\n",
+			__func__, cpu_dev->id, cluster);
+	ret = PTR_ERR(clk[cluster]);
+	opp_free_cpufreq_table(cpu_dev, &freq_table[cluster]);
+
+atomic_dec:
+	atomic_dec(&cluster_usage[cluster]);
+	dev_err(cpu_dev, "%s: Failed to get data for cluster: %d\n", __func__,
+			cluster);
+	return ret;
+}
+
+/* Per-CPU initialization */
+static int bL_cpufreq_init(struct cpufreq_policy *policy)
+{
+	u32 cur_cluster = cpu_to_cluster(policy->cpu);
+	struct device *cpu_dev;
+	int ret;
+
+	cpu_dev = get_cpu_device(policy->cpu);
+	if (!cpu_dev) {
+		pr_err("%s: failed to get cpu%d device\n", __func__,
+				policy->cpu);
+		return -ENODEV;
+	}
+
+	ret = get_cluster_clk_and_freq_table(cpu_dev);
+	if (ret)
+		return ret;
+
+	ret = cpufreq_frequency_table_cpuinfo(policy, freq_table[cur_cluster]);
+	if (ret) {
+		dev_err(cpu_dev, "CPU %d, cluster: %d invalid freq table\n",
+				policy->cpu, cur_cluster);
+		put_cluster_clk_and_freq_table(cpu_dev);
+		return ret;
+	}
+
+	cpufreq_frequency_table_get_attr(freq_table[cur_cluster], policy->cpu);
+
+	if (arm_bL_ops->get_transition_latency)
+		policy->cpuinfo.transition_latency =
+			arm_bL_ops->get_transition_latency(cpu_dev);
+	else
+		policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
+
+	policy->cur = bL_cpufreq_get(policy->cpu);
+
+	cpumask_copy(policy->cpus, topology_core_cpumask(policy->cpu));
+
+	dev_info(cpu_dev, "CPU %d initialized\n", policy->cpu);
+	return 0;
+}
+
+static int bL_cpufreq_exit(struct cpufreq_policy *policy)
+{
+	struct device *cpu_dev;
+
+	cpu_dev = get_cpu_device(policy->cpu);
+	if (!cpu_dev) {
+		pr_err("%s: failed to get cpu%d device\n", __func__,
+				policy->cpu);
+		return -ENODEV;
+	}
+
+	put_cluster_clk_and_freq_table(cpu_dev);
+	dev_dbg(cpu_dev, "%s: Exited, cpu: %d\n", __func__, policy->cpu);
+
+	return 0;
+}
+
+/* Export freq_table to sysfs */
+static struct freq_attr *bL_cpufreq_attr[] = {
+	&cpufreq_freq_attr_scaling_available_freqs,
+	NULL,
+};
+
+static struct cpufreq_driver bL_cpufreq_driver = {
+	.name			= "arm-big-little",
+	.flags			= CPUFREQ_STICKY,
+	.verify			= bL_cpufreq_verify_policy,
+	.target			= bL_cpufreq_set_target,
+	.get			= bL_cpufreq_get,
+	.init			= bL_cpufreq_init,
+	.exit			= bL_cpufreq_exit,
+	.have_multiple_policies	= true,
+	.attr			= bL_cpufreq_attr,
+};
+
+int bL_cpufreq_register(struct cpufreq_arm_bL_ops *ops)
+{
+	int ret;
+
+	if (arm_bL_ops) {
+		pr_debug("%s: Already registered: %s, exiting\n", __func__,
+				arm_bL_ops->name);
+		return -EBUSY;
+	}
+
+	if (!ops || !strlen(ops->name) || !ops->init_opp_table) {
+		pr_err("%s: Invalid arm_bL_ops, exiting\n", __func__);
+		return -ENODEV;
+	}
+
+	arm_bL_ops = ops;
+
+	ret = cpufreq_register_driver(&bL_cpufreq_driver);
+	if (ret) {
+		pr_info("%s: Failed registering platform driver: %s, err: %d\n",
+				__func__, ops->name, ret);
+		arm_bL_ops = NULL;
+	} else {
+		pr_info("%s: Registered platform driver: %s\n", __func__,
+				ops->name);
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(bL_cpufreq_register);
+
+void bL_cpufreq_unregister(struct cpufreq_arm_bL_ops *ops)
+{
+	if (arm_bL_ops != ops) {
+		pr_err("%s: Registered with: %s, can't unregister, exiting\n",
+				__func__, arm_bL_ops->name);
+		return;
+	}
+
+	cpufreq_unregister_driver(&bL_cpufreq_driver);
+	pr_info("%s: Un-registered platform driver: %s\n", __func__,
+			arm_bL_ops->name);
+	arm_bL_ops = NULL;
+}
+EXPORT_SYMBOL_GPL(bL_cpufreq_unregister);
diff --git a/drivers/cpufreq/arm_big_little.h b/drivers/cpufreq/arm_big_little.h
new file mode 100644
index 0000000..70f18fc
--- /dev/null
+++ b/drivers/cpufreq/arm_big_little.h
@@ -0,0 +1,40 @@
+/*
+ * ARM big.LITTLE platform's CPUFreq header file
+ *
+ * Copyright (C) 2013 ARM Ltd.
+ * Sudeep KarkadaNagesha <sudeep.karkadanagesha@arm.com>
+ *
+ * Copyright (C) 2013 Linaro.
+ * Viresh Kumar <viresh.kumar@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#ifndef CPUFREQ_ARM_BIG_LITTLE_H
+#define CPUFREQ_ARM_BIG_LITTLE_H
+
+#include <linux/cpufreq.h>
+#include <linux/device.h>
+#include <linux/types.h>
+
+struct cpufreq_arm_bL_ops {
+	char name[CPUFREQ_NAME_LEN];
+	int (*get_transition_latency)(struct device *cpu_dev);
+
+	/*
+	 * This must set opp table for cpu_dev in a similar way as done by
+	 * of_init_opp_table().
+	 */
+	int (*init_opp_table)(struct device *cpu_dev);
+};
+
+int bL_cpufreq_register(struct cpufreq_arm_bL_ops *ops);
+void bL_cpufreq_unregister(struct cpufreq_arm_bL_ops *ops);
+
+#endif /* CPUFREQ_ARM_BIG_LITTLE_H */
diff --git a/drivers/cpufreq/arm_big_little_dt.c b/drivers/cpufreq/arm_big_little_dt.c
new file mode 100644
index 0000000..452ff46
--- /dev/null
+++ b/drivers/cpufreq/arm_big_little_dt.c
@@ -0,0 +1,92 @@
+/*
+ * Generic big.LITTLE CPUFreq Interface driver
+ *
+ * It provides necessary ops to arm_big_little cpufreq driver and gets
+ * Frequency information from Device Tree. Freq table in DT must be in KHz.
+ *
+ * Copyright (C) 2013 Linaro.
+ * Viresh Kumar <viresh.kumar@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/cpufreq.h>
+#include <linux/device.h>
+#include <linux/export.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/opp.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include "arm_big_little.h"
+
+static int dt_init_opp_table(struct device *cpu_dev)
+{
+	struct device_node *np = NULL;
+	int count = 0, ret;
+
+	for_each_child_of_node(of_find_node_by_path("/cpus"), np) {
+		if (count++ != cpu_dev->id)
+			continue;
+		if (!of_get_property(np, "operating-points", NULL))
+			return -ENODATA;
+
+		cpu_dev->of_node = np;
+
+		ret = of_init_opp_table(cpu_dev);
+		if (ret)
+			return ret;
+
+		return 0;
+	}
+
+	return -ENODEV;
+}
+
+static int dt_get_transition_latency(struct device *cpu_dev)
+{
+	struct device_node *np = NULL;
+	u32 transition_latency = CPUFREQ_ETERNAL;
+	int count = 0;
+
+	for_each_child_of_node(of_find_node_by_path("/cpus"), np) {
+		if (count++ != cpu_dev->id)
+			continue;
+
+		of_property_read_u32(np, "clock-latency", &transition_latency);
+		return 0;
+	}
+
+	return -ENODEV;
+}
+
+static struct cpufreq_arm_bL_ops dt_bL_ops = {
+	.name	= "dt-bl",
+	.get_transition_latency = dt_get_transition_latency,
+	.init_opp_table = dt_init_opp_table,
+};
+
+static int generic_bL_init(void)
+{
+	return bL_cpufreq_register(&dt_bL_ops);
+}
+module_init(generic_bL_init);
+
+static void generic_bL_exit(void)
+{
+	return bL_cpufreq_unregister(&dt_bL_ops);
+}
+module_exit(generic_bL_exit);
+
+MODULE_AUTHOR("Viresh Kumar <viresh.kumar@linaro.org>");
+MODULE_DESCRIPTION("Generic ARM big LITTLE cpufreq driver via DT");
+MODULE_LICENSE("GPL");
diff --git a/drivers/cpufreq/cpufreq-cpu0.c b/drivers/cpufreq/cpufreq-cpu0.c
index 4e5b7fb..31282fc 100644
--- a/drivers/cpufreq/cpufreq-cpu0.c
+++ b/drivers/cpufreq/cpufreq-cpu0.c
@@ -44,8 +44,9 @@ static int cpu0_set_target(struct cpufreq_policy *policy,
 {
 	struct cpufreq_freqs freqs;
 	struct opp *opp;
-	unsigned long freq_Hz, volt = 0, volt_old = 0, tol = 0;
-	unsigned int index, cpu;
+	unsigned long volt = 0, volt_old = 0, tol = 0;
+	long freq_Hz;
+	unsigned int index;
 	int ret;
 
 	ret = cpufreq_frequency_table_target(policy, freq_table, target_freq,
@@ -65,10 +66,7 @@ static int cpu0_set_target(struct cpufreq_policy *policy,
 	if (freqs.old == freqs.new)
 		return 0;
 
-	for_each_online_cpu(cpu) {
-		freqs.cpu = cpu;
-		cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
-	}
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
 
 	if (cpu_reg) {
 		rcu_read_lock();
@@ -76,7 +74,9 @@ static int cpu0_set_target(struct cpufreq_policy *policy,
 		if (IS_ERR(opp)) {
 			rcu_read_unlock();
 			pr_err("failed to find OPP for %ld\n", freq_Hz);
-			return PTR_ERR(opp);
+			freqs.new = freqs.old;
+			ret = PTR_ERR(opp);
+			goto post_notify;
 		}
 		volt = opp_get_voltage(opp);
 		rcu_read_unlock();
@@ -94,7 +94,7 @@ static int cpu0_set_target(struct cpufreq_policy *policy,
 		if (ret) {
 			pr_err("failed to scale voltage up: %d\n", ret);
 			freqs.new = freqs.old;
-			return ret;
+			goto post_notify;
 		}
 	}
 
@@ -103,7 +103,8 @@ static int cpu0_set_target(struct cpufreq_policy *policy,
 		pr_err("failed to set clock rate: %d\n", ret);
 		if (cpu_reg)
 			regulator_set_voltage_tol(cpu_reg, volt_old, tol);
-		return ret;
+		freqs.new = freqs.old;
+		goto post_notify;
 	}
 
 	/* scaling down?  scale voltage after frequency */
@@ -113,25 +114,19 @@ static int cpu0_set_target(struct cpufreq_policy *policy,
 			pr_err("failed to scale voltage down: %d\n", ret);
 			clk_set_rate(cpu_clk, freqs.old * 1000);
 			freqs.new = freqs.old;
-			return ret;
 		}
 	}
 
-	for_each_online_cpu(cpu) {
-		freqs.cpu = cpu;
-		cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
-	}
+post_notify:
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
 
-	return 0;
+	return ret;
 }
 
 static int cpu0_cpufreq_init(struct cpufreq_policy *policy)
 {
 	int ret;
 
-	if (policy->cpu != 0)
-		return -EINVAL;
-
 	ret = cpufreq_frequency_table_cpuinfo(policy, freq_table);
 	if (ret) {
 		pr_err("invalid frequency table: %d\n", ret);
@@ -178,10 +173,16 @@ static struct cpufreq_driver cpu0_cpufreq_driver = {
 
 static int cpu0_cpufreq_probe(struct platform_device *pdev)
 {
-	struct device_node *np;
+	struct device_node *np, *parent;
 	int ret;
 
-	for_each_child_of_node(of_find_node_by_path("/cpus"), np) {
+	parent = of_find_node_by_path("/cpus");
+	if (!parent) {
+		pr_err("failed to find OF /cpus\n");
+		return -ENOENT;
+	}
+
+	for_each_child_of_node(parent, np) {
 		if (of_get_property(np, "operating-points", NULL))
 			break;
 	}
diff --git a/drivers/cpufreq/cpufreq-nforce2.c b/drivers/cpufreq/cpufreq-nforce2.c
index 13d311e..af1542d 100644
--- a/drivers/cpufreq/cpufreq-nforce2.c
+++ b/drivers/cpufreq/cpufreq-nforce2.c
@@ -263,7 +263,6 @@ static int nforce2_target(struct cpufreq_policy *policy,
 
 	freqs.old = nforce2_get(policy->cpu);
 	freqs.new = target_fsb * fid * 100;
-	freqs.cpu = 0;		/* Only one CPU on nForce2 platforms */
 
 	if (freqs.old == freqs.new)
 		return 0;
@@ -271,7 +270,7 @@ static int nforce2_target(struct cpufreq_policy *policy,
 	pr_debug("Old CPU frequency %d kHz, new %d kHz\n",
 	       freqs.old, freqs.new);
 
-	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
 
 	/* Disable IRQs */
 	/* local_irq_save(flags); */
@@ -286,7 +285,7 @@ static int nforce2_target(struct cpufreq_policy *policy,
 	/* Enable IRQs */
 	/* local_irq_restore(flags); */
 
-	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
 
 	return 0;
 }
@@ -360,12 +359,10 @@ static int nforce2_cpu_init(struct cpufreq_policy *policy)
 		min_fsb = NFORCE2_MIN_FSB;
 
 	/* cpuinfo and default policy values */
-	policy->cpuinfo.min_freq = min_fsb * fid * 100;
-	policy->cpuinfo.max_freq = max_fsb * fid * 100;
+	policy->min = policy->cpuinfo.min_freq = min_fsb * fid * 100;
+	policy->max = policy->cpuinfo.max_freq = max_fsb * fid * 100;
 	policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
 	policy->cur = nforce2_get(policy->cpu);
-	policy->min = policy->cpuinfo.min_freq;
-	policy->max = policy->cpuinfo.max_freq;
 
 	return 0;
 }
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index b02824d..0198cd0 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -45,7 +45,7 @@ static DEFINE_PER_CPU(struct cpufreq_policy *, cpufreq_cpu_data);
 /* This one keeps track of the previously set governor of a removed CPU */
 static DEFINE_PER_CPU(char[CPUFREQ_NAME_LEN], cpufreq_cpu_governor);
 #endif
-static DEFINE_SPINLOCK(cpufreq_driver_lock);
+static DEFINE_RWLOCK(cpufreq_driver_lock);
 
 /*
  * cpu_policy_rwsem is a per CPU reader-writer semaphore designed to cure
@@ -128,6 +128,11 @@ void disable_cpufreq(void)
 static LIST_HEAD(cpufreq_governor_list);
 static DEFINE_MUTEX(cpufreq_governor_mutex);
 
+bool have_governor_per_policy(void)
+{
+	return cpufreq_driver->have_governor_per_policy;
+}
+
 static struct cpufreq_policy *__cpufreq_cpu_get(unsigned int cpu, bool sysfs)
 {
 	struct cpufreq_policy *data;
@@ -137,7 +142,7 @@ static struct cpufreq_policy *__cpufreq_cpu_get(unsigned int cpu, bool sysfs)
 		goto err_out;
 
 	/* get the cpufreq driver */
-	spin_lock_irqsave(&cpufreq_driver_lock, flags);
+	read_lock_irqsave(&cpufreq_driver_lock, flags);
 
 	if (!cpufreq_driver)
 		goto err_out_unlock;
@@ -155,13 +160,13 @@ static struct cpufreq_policy *__cpufreq_cpu_get(unsigned int cpu, bool sysfs)
 	if (!sysfs && !kobject_get(&data->kobj))
 		goto err_out_put_module;
 
-	spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
+	read_unlock_irqrestore(&cpufreq_driver_lock, flags);
 	return data;
 
 err_out_put_module:
 	module_put(cpufreq_driver->owner);
 err_out_unlock:
-	spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
+	read_unlock_irqrestore(&cpufreq_driver_lock, flags);
 err_out:
 	return NULL;
 }
@@ -244,19 +249,9 @@ static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci)
 #endif
 
 
-/**
- * cpufreq_notify_transition - call notifier chain and adjust_jiffies
- * on frequency transition.
- *
- * This function calls the transition notifiers and the "adjust_jiffies"
- * function. It is called twice on all CPU frequency changes that have
- * external effects.
- */
-void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state)
+void __cpufreq_notify_transition(struct cpufreq_policy *policy,
+		struct cpufreq_freqs *freqs, unsigned int state)
 {
-	struct cpufreq_policy *policy;
-	unsigned long flags;
-
 	BUG_ON(irqs_disabled());
 
 	if (cpufreq_disabled())
@@ -266,10 +261,6 @@ void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state)
 	pr_debug("notification %u of frequency transition to %u kHz\n",
 		state, freqs->new);
 
-	spin_lock_irqsave(&cpufreq_driver_lock, flags);
-	policy = per_cpu(cpufreq_cpu_data, freqs->cpu);
-	spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
-
 	switch (state) {
 
 	case CPUFREQ_PRECHANGE:
@@ -303,6 +294,20 @@ void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state)
 		break;
 	}
 }
+/**
+ * cpufreq_notify_transition - call notifier chain and adjust_jiffies
+ * on frequency transition.
+ *
+ * This function calls the transition notifiers and the "adjust_jiffies"
+ * function. It is called twice on all CPU frequency changes that have
+ * external effects.
+ */
+void cpufreq_notify_transition(struct cpufreq_policy *policy,
+		struct cpufreq_freqs *freqs, unsigned int state)
+{
+	for_each_cpu(freqs->cpu, policy->cpus)
+		__cpufreq_notify_transition(policy, freqs, state);
+}
 EXPORT_SYMBOL_GPL(cpufreq_notify_transition);
 
 
@@ -765,12 +770,12 @@ static int cpufreq_add_dev_interface(unsigned int cpu,
 			goto err_out_kobj_put;
 	}
 
-	spin_lock_irqsave(&cpufreq_driver_lock, flags);
+	write_lock_irqsave(&cpufreq_driver_lock, flags);
 	for_each_cpu(j, policy->cpus) {
 		per_cpu(cpufreq_cpu_data, j) = policy;
 		per_cpu(cpufreq_policy_cpu, j) = policy->cpu;
 	}
-	spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
+	write_unlock_irqrestore(&cpufreq_driver_lock, flags);
 
 	ret = cpufreq_add_dev_symlink(cpu, policy);
 	if (ret)
@@ -813,12 +818,12 @@ static int cpufreq_add_policy_cpu(unsigned int cpu, unsigned int sibling,
 
 	lock_policy_rwsem_write(sibling);
 
-	spin_lock_irqsave(&cpufreq_driver_lock, flags);
+	write_lock_irqsave(&cpufreq_driver_lock, flags);
 
 	cpumask_set_cpu(cpu, policy->cpus);
 	per_cpu(cpufreq_policy_cpu, cpu) = policy->cpu;
 	per_cpu(cpufreq_cpu_data, cpu) = policy;
-	spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
+	write_unlock_irqrestore(&cpufreq_driver_lock, flags);
 
 	unlock_policy_rwsem_write(sibling);
 
@@ -871,15 +876,15 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
 
 #ifdef CONFIG_HOTPLUG_CPU
 	/* Check if this cpu was hot-unplugged earlier and has siblings */
-	spin_lock_irqsave(&cpufreq_driver_lock, flags);
+	read_lock_irqsave(&cpufreq_driver_lock, flags);
 	for_each_online_cpu(sibling) {
 		struct cpufreq_policy *cp = per_cpu(cpufreq_cpu_data, sibling);
 		if (cp && cpumask_test_cpu(cpu, cp->related_cpus)) {
-			spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
+			read_unlock_irqrestore(&cpufreq_driver_lock, flags);
 			return cpufreq_add_policy_cpu(cpu, sibling, dev);
 		}
 	}
-	spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
+	read_unlock_irqrestore(&cpufreq_driver_lock, flags);
 #endif
 #endif
 
@@ -952,10 +957,10 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
 	return 0;
 
 err_out_unregister:
-	spin_lock_irqsave(&cpufreq_driver_lock, flags);
+	write_lock_irqsave(&cpufreq_driver_lock, flags);
 	for_each_cpu(j, policy->cpus)
 		per_cpu(cpufreq_cpu_data, j) = NULL;
-	spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
+	write_unlock_irqrestore(&cpufreq_driver_lock, flags);
 
 	kobject_put(&policy->kobj);
 	wait_for_completion(&policy->kobj_unregister);
@@ -1008,12 +1013,12 @@ static int __cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif
 
 	pr_debug("%s: unregistering CPU %u\n", __func__, cpu);
 
-	spin_lock_irqsave(&cpufreq_driver_lock, flags);
+	write_lock_irqsave(&cpufreq_driver_lock, flags);
 
 	data = per_cpu(cpufreq_cpu_data, cpu);
 	per_cpu(cpufreq_cpu_data, cpu) = NULL;
 
-	spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
+	write_unlock_irqrestore(&cpufreq_driver_lock, flags);
 
 	if (!data) {
 		pr_debug("%s: No cpu_data found\n", __func__);
@@ -1047,9 +1052,9 @@ static int __cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif
 			WARN_ON(lock_policy_rwsem_write(cpu));
 			cpumask_set_cpu(cpu, data->cpus);
 
-			spin_lock_irqsave(&cpufreq_driver_lock, flags);
+			write_lock_irqsave(&cpufreq_driver_lock, flags);
 			per_cpu(cpufreq_cpu_data, cpu) = data;
-			spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
+			write_unlock_irqrestore(&cpufreq_driver_lock, flags);
 
 			unlock_policy_rwsem_write(cpu);
 
@@ -1070,6 +1075,8 @@ static int __cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif
 
 	/* If cpu is last user of policy, free policy */
 	if (cpus == 1) {
+		__cpufreq_governor(data, CPUFREQ_GOV_POLICY_EXIT);
+
 		lock_policy_rwsem_read(cpu);
 		kobj = &data->kobj;
 		cmp = &data->kobj_unregister;
@@ -1134,16 +1141,23 @@ static void handle_update(struct work_struct *work)
 static void cpufreq_out_of_sync(unsigned int cpu, unsigned int old_freq,
 				unsigned int new_freq)
 {
+	struct cpufreq_policy *policy;
 	struct cpufreq_freqs freqs;
+	unsigned long flags;
+
 
 	pr_debug("Warning: CPU frequency out of sync: cpufreq and timing "
 	       "core thinks of %u, is %u kHz.\n", old_freq, new_freq);
 
-	freqs.cpu = cpu;
 	freqs.old = old_freq;
 	freqs.new = new_freq;
-	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
-	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
+	read_lock_irqsave(&cpufreq_driver_lock, flags);
+	policy = per_cpu(cpufreq_cpu_data, cpu);
+	read_unlock_irqrestore(&cpufreq_driver_lock, flags);
+
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
 }
 
 
@@ -1544,10 +1558,12 @@ static int __cpufreq_governor(struct cpufreq_policy *policy,
 						policy->cpu, event);
 	ret = policy->governor->governor(policy, event);
 
-	if (event == CPUFREQ_GOV_START)
-		policy->governor->initialized++;
-	else if (event == CPUFREQ_GOV_STOP)
-		policy->governor->initialized--;
+	if (!ret) {
+		if (event == CPUFREQ_GOV_POLICY_INIT)
+			policy->governor->initialized++;
+		else if (event == CPUFREQ_GOV_POLICY_EXIT)
+			policy->governor->initialized--;
+	}
 
 	/* we keep one module reference alive for
 			each CPU governed by this CPU */
@@ -1651,7 +1667,7 @@ EXPORT_SYMBOL(cpufreq_get_policy);
 static int __cpufreq_set_policy(struct cpufreq_policy *data,
 				struct cpufreq_policy *policy)
 {
-	int ret = 0;
+	int ret = 0, failed = 1;
 
 	pr_debug("setting new policy for CPU %u: %u - %u kHz\n", policy->cpu,
 		policy->min, policy->max);
@@ -1705,18 +1721,31 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data,
 			pr_debug("governor switch\n");
 
 			/* end old governor */
-			if (data->governor)
+			if (data->governor) {
 				__cpufreq_governor(data, CPUFREQ_GOV_STOP);
+				__cpufreq_governor(data,
+						CPUFREQ_GOV_POLICY_EXIT);
+			}
 
 			/* start new governor */
 			data->governor = policy->governor;
-			if (__cpufreq_governor(data, CPUFREQ_GOV_START)) {
+			if (!__cpufreq_governor(data, CPUFREQ_GOV_POLICY_INIT)) {
+				if (!__cpufreq_governor(data, CPUFREQ_GOV_START))
+					failed = 0;
+				else
+					__cpufreq_governor(data,
+							CPUFREQ_GOV_POLICY_EXIT);
+			}
+
+			if (failed) {
 				/* new governor failed, so re-start old one */
 				pr_debug("starting governor %s failed\n",
 							data->governor->name);
 				if (old_gov) {
 					data->governor = old_gov;
 					__cpufreq_governor(data,
+							CPUFREQ_GOV_POLICY_INIT);
+					__cpufreq_governor(data,
 							   CPUFREQ_GOV_START);
 				}
 				ret = -EINVAL;
@@ -1848,13 +1877,13 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
 	if (driver_data->setpolicy)
 		driver_data->flags |= CPUFREQ_CONST_LOOPS;
 
-	spin_lock_irqsave(&cpufreq_driver_lock, flags);
+	write_lock_irqsave(&cpufreq_driver_lock, flags);
 	if (cpufreq_driver) {
-		spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
+		write_unlock_irqrestore(&cpufreq_driver_lock, flags);
 		return -EBUSY;
 	}
 	cpufreq_driver = driver_data;
-	spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
+	write_unlock_irqrestore(&cpufreq_driver_lock, flags);
 
 	ret = subsys_interface_register(&cpufreq_interface);
 	if (ret)
@@ -1886,9 +1915,9 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
 err_if_unreg:
 	subsys_interface_unregister(&cpufreq_interface);
 err_null_driver:
-	spin_lock_irqsave(&cpufreq_driver_lock, flags);
+	write_lock_irqsave(&cpufreq_driver_lock, flags);
 	cpufreq_driver = NULL;
-	spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
+	write_unlock_irqrestore(&cpufreq_driver_lock, flags);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(cpufreq_register_driver);
@@ -1914,9 +1943,9 @@ int cpufreq_unregister_driver(struct cpufreq_driver *driver)
 	subsys_interface_unregister(&cpufreq_interface);
 	unregister_hotcpu_notifier(&cpufreq_cpu_notifier);
 
-	spin_lock_irqsave(&cpufreq_driver_lock, flags);
+	write_lock_irqsave(&cpufreq_driver_lock, flags);
 	cpufreq_driver = NULL;
-	spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
+	write_unlock_irqrestore(&cpufreq_driver_lock, flags);
 
 	return 0;
 }
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c
index 4fd0006..0ceb2ef 100644
--- a/drivers/cpufreq/cpufreq_conservative.c
+++ b/drivers/cpufreq/cpufreq_conservative.c
@@ -20,6 +20,7 @@
 #include <linux/mutex.h>
 #include <linux/notifier.h>
 #include <linux/percpu-defs.h>
+#include <linux/slab.h>
 #include <linux/sysfs.h>
 #include <linux/types.h>
 
@@ -28,25 +29,29 @@
 /* Conservative governor macros */
 #define DEF_FREQUENCY_UP_THRESHOLD		(80)
 #define DEF_FREQUENCY_DOWN_THRESHOLD		(20)
+#define DEF_FREQUENCY_STEP			(5)
 #define DEF_SAMPLING_DOWN_FACTOR		(1)
 #define MAX_SAMPLING_DOWN_FACTOR		(10)
 
-static struct dbs_data cs_dbs_data;
 static DEFINE_PER_CPU(struct cs_cpu_dbs_info_s, cs_cpu_dbs_info);
 
-static struct cs_dbs_tuners cs_tuners = {
-	.up_threshold = DEF_FREQUENCY_UP_THRESHOLD,
-	.down_threshold = DEF_FREQUENCY_DOWN_THRESHOLD,
-	.sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR,
-	.ignore_nice = 0,
-	.freq_step = 5,
-};
+static inline unsigned int get_freq_target(struct cs_dbs_tuners *cs_tuners,
+					   struct cpufreq_policy *policy)
+{
+	unsigned int freq_target = (cs_tuners->freq_step * policy->max) / 100;
+
+	/* max freq cannot be less than 100. But who knows... */
+	if (unlikely(freq_target == 0))
+		freq_target = DEF_FREQUENCY_STEP;
+
+	return freq_target;
+}
 
 /*
  * Every sampling_rate, we check, if current idle time is less than 20%
- * (default), then we try to increase frequency Every sampling_rate *
- * sampling_down_factor, we check, if current idle time is more than 80%, then
- * we try to decrease frequency
+ * (default), then we try to increase frequency. Every sampling_rate *
+ * sampling_down_factor, we check, if current idle time is more than 80%
+ * (default), then we try to decrease frequency
  *
  * Any frequency increase takes it to the maximum frequency. Frequency reduction
  * happens at minimum steps of 5% (default) of maximum frequency
@@ -55,30 +60,25 @@ static void cs_check_cpu(int cpu, unsigned int load)
 {
 	struct cs_cpu_dbs_info_s *dbs_info = &per_cpu(cs_cpu_dbs_info, cpu);
 	struct cpufreq_policy *policy = dbs_info->cdbs.cur_policy;
-	unsigned int freq_target;
+	struct dbs_data *dbs_data = policy->governor_data;
+	struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
 
 	/*
 	 * break out if we 'cannot' reduce the speed as the user might
 	 * want freq_step to be zero
 	 */
-	if (cs_tuners.freq_step == 0)
+	if (cs_tuners->freq_step == 0)
 		return;
 
 	/* Check for frequency increase */
-	if (load > cs_tuners.up_threshold) {
+	if (load > cs_tuners->up_threshold) {
 		dbs_info->down_skip = 0;
 
 		/* if we are already at full speed then break out early */
 		if (dbs_info->requested_freq == policy->max)
 			return;
 
-		freq_target = (cs_tuners.freq_step * policy->max) / 100;
-
-		/* max freq cannot be less than 100. But who knows.... */
-		if (unlikely(freq_target == 0))
-			freq_target = 5;
-
-		dbs_info->requested_freq += freq_target;
+		dbs_info->requested_freq += get_freq_target(cs_tuners, policy);
 		if (dbs_info->requested_freq > policy->max)
 			dbs_info->requested_freq = policy->max;
 
@@ -87,45 +87,48 @@ static void cs_check_cpu(int cpu, unsigned int load)
 		return;
 	}
 
-	/*
-	 * The optimal frequency is the frequency that is the lowest that can
-	 * support the current CPU usage without triggering the up policy. To be
-	 * safe, we focus 10 points under the threshold.
-	 */
-	if (load < (cs_tuners.down_threshold - 10)) {
-		freq_target = (cs_tuners.freq_step * policy->max) / 100;
-
-		dbs_info->requested_freq -= freq_target;
-		if (dbs_info->requested_freq < policy->min)
-			dbs_info->requested_freq = policy->min;
+	/* if sampling_down_factor is active break out early */
+	if (++dbs_info->down_skip < cs_tuners->sampling_down_factor)
+		return;
+	dbs_info->down_skip = 0;
 
+	/* Check for frequency decrease */
+	if (load < cs_tuners->down_threshold) {
 		/*
 		 * if we cannot reduce the frequency anymore, break out early
 		 */
 		if (policy->cur == policy->min)
 			return;
 
+		dbs_info->requested_freq -= get_freq_target(cs_tuners, policy);
+		if (dbs_info->requested_freq < policy->min)
+			dbs_info->requested_freq = policy->min;
+
 		__cpufreq_driver_target(policy, dbs_info->requested_freq,
-				CPUFREQ_RELATION_H);
+				CPUFREQ_RELATION_L);
 		return;
 	}
 }
 
 static void cs_dbs_timer(struct work_struct *work)
 {
-	struct delayed_work *dw = to_delayed_work(work);
 	struct cs_cpu_dbs_info_s *dbs_info = container_of(work,
 			struct cs_cpu_dbs_info_s, cdbs.work.work);
 	unsigned int cpu = dbs_info->cdbs.cur_policy->cpu;
 	struct cs_cpu_dbs_info_s *core_dbs_info = &per_cpu(cs_cpu_dbs_info,
 			cpu);
-	int delay = delay_for_sampling_rate(cs_tuners.sampling_rate);
+	struct dbs_data *dbs_data = dbs_info->cdbs.cur_policy->governor_data;
+	struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
+	int delay = delay_for_sampling_rate(cs_tuners->sampling_rate);
+	bool modify_all = true;
 
 	mutex_lock(&core_dbs_info->cdbs.timer_mutex);
-	if (need_load_eval(&core_dbs_info->cdbs, cs_tuners.sampling_rate))
-		dbs_check_cpu(&cs_dbs_data, cpu);
+	if (!need_load_eval(&core_dbs_info->cdbs, cs_tuners->sampling_rate))
+		modify_all = false;
+	else
+		dbs_check_cpu(dbs_data, cpu);
 
-	schedule_delayed_work_on(smp_processor_id(), dw, delay);
+	gov_queue_work(dbs_data, dbs_info->cdbs.cur_policy, delay, modify_all);
 	mutex_unlock(&core_dbs_info->cdbs.timer_mutex);
 }
 
@@ -154,16 +157,12 @@ static int dbs_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
 }
 
 /************************** sysfs interface ************************/
-static ssize_t show_sampling_rate_min(struct kobject *kobj,
-				      struct attribute *attr, char *buf)
-{
-	return sprintf(buf, "%u\n", cs_dbs_data.min_sampling_rate);
-}
+static struct common_dbs_data cs_dbs_cdata;
 
-static ssize_t store_sampling_down_factor(struct kobject *a,
-					  struct attribute *b,
-					  const char *buf, size_t count)
+static ssize_t store_sampling_down_factor(struct dbs_data *dbs_data,
+		const char *buf, size_t count)
 {
+	struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
 	unsigned int input;
 	int ret;
 	ret = sscanf(buf, "%u", &input);
@@ -171,13 +170,14 @@ static ssize_t store_sampling_down_factor(struct kobject *a,
 	if (ret != 1 || input > MAX_SAMPLING_DOWN_FACTOR || input < 1)
 		return -EINVAL;
 
-	cs_tuners.sampling_down_factor = input;
+	cs_tuners->sampling_down_factor = input;
 	return count;
 }
 
-static ssize_t store_sampling_rate(struct kobject *a, struct attribute *b,
-				   const char *buf, size_t count)
+static ssize_t store_sampling_rate(struct dbs_data *dbs_data, const char *buf,
+		size_t count)
 {
+	struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
 	unsigned int input;
 	int ret;
 	ret = sscanf(buf, "%u", &input);
@@ -185,43 +185,46 @@ static ssize_t store_sampling_rate(struct kobject *a, struct attribute *b,
 	if (ret != 1)
 		return -EINVAL;
 
-	cs_tuners.sampling_rate = max(input, cs_dbs_data.min_sampling_rate);
+	cs_tuners->sampling_rate = max(input, dbs_data->min_sampling_rate);
 	return count;
 }
 
-static ssize_t store_up_threshold(struct kobject *a, struct attribute *b,
-				  const char *buf, size_t count)
+static ssize_t store_up_threshold(struct dbs_data *dbs_data, const char *buf,
+		size_t count)
 {
+	struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
 	unsigned int input;
 	int ret;
 	ret = sscanf(buf, "%u", &input);
 
-	if (ret != 1 || input > 100 || input <= cs_tuners.down_threshold)
+	if (ret != 1 || input > 100 || input <= cs_tuners->down_threshold)
 		return -EINVAL;
 
-	cs_tuners.up_threshold = input;
+	cs_tuners->up_threshold = input;
 	return count;
 }
 
-static ssize_t store_down_threshold(struct kobject *a, struct attribute *b,
-				    const char *buf, size_t count)
+static ssize_t store_down_threshold(struct dbs_data *dbs_data, const char *buf,
+		size_t count)
 {
+	struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
 	unsigned int input;
 	int ret;
 	ret = sscanf(buf, "%u", &input);
 
 	/* cannot be lower than 11 otherwise freq will not fall */
 	if (ret != 1 || input < 11 || input > 100 ||
-			input >= cs_tuners.up_threshold)
+			input >= cs_tuners->up_threshold)
 		return -EINVAL;
 
-	cs_tuners.down_threshold = input;
+	cs_tuners->down_threshold = input;
 	return count;
 }
 
-static ssize_t store_ignore_nice_load(struct kobject *a, struct attribute *b,
-				      const char *buf, size_t count)
+static ssize_t store_ignore_nice(struct dbs_data *dbs_data, const char *buf,
+		size_t count)
 {
+	struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
 	unsigned int input, j;
 	int ret;
 
@@ -232,27 +235,28 @@ static ssize_t store_ignore_nice_load(struct kobject *a, struct attribute *b,
 	if (input > 1)
 		input = 1;
 
-	if (input == cs_tuners.ignore_nice) /* nothing to do */
+	if (input == cs_tuners->ignore_nice) /* nothing to do */
 		return count;
 
-	cs_tuners.ignore_nice = input;
+	cs_tuners->ignore_nice = input;
 
 	/* we need to re-evaluate prev_cpu_idle */
 	for_each_online_cpu(j) {
 		struct cs_cpu_dbs_info_s *dbs_info;
 		dbs_info = &per_cpu(cs_cpu_dbs_info, j);
 		dbs_info->cdbs.prev_cpu_idle = get_cpu_idle_time(j,
-						&dbs_info->cdbs.prev_cpu_wall);
-		if (cs_tuners.ignore_nice)
+					&dbs_info->cdbs.prev_cpu_wall, 0);
+		if (cs_tuners->ignore_nice)
 			dbs_info->cdbs.prev_cpu_nice =
 				kcpustat_cpu(j).cpustat[CPUTIME_NICE];
 	}
 	return count;
 }
 
-static ssize_t store_freq_step(struct kobject *a, struct attribute *b,
-			       const char *buf, size_t count)
+static ssize_t store_freq_step(struct dbs_data *dbs_data, const char *buf,
+		size_t count)
 {
+	struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
 	unsigned int input;
 	int ret;
 	ret = sscanf(buf, "%u", &input);
@@ -267,43 +271,88 @@ static ssize_t store_freq_step(struct kobject *a, struct attribute *b,
 	 * no need to test here if freq_step is zero as the user might actually
 	 * want this, they would be crazy though :)
 	 */
-	cs_tuners.freq_step = input;
+	cs_tuners->freq_step = input;
 	return count;
 }
 
-show_one(cs, sampling_rate, sampling_rate);
-show_one(cs, sampling_down_factor, sampling_down_factor);
-show_one(cs, up_threshold, up_threshold);
-show_one(cs, down_threshold, down_threshold);
-show_one(cs, ignore_nice_load, ignore_nice);
-show_one(cs, freq_step, freq_step);
-
-define_one_global_rw(sampling_rate);
-define_one_global_rw(sampling_down_factor);
-define_one_global_rw(up_threshold);
-define_one_global_rw(down_threshold);
-define_one_global_rw(ignore_nice_load);
-define_one_global_rw(freq_step);
-define_one_global_ro(sampling_rate_min);
-
-static struct attribute *dbs_attributes[] = {
-	&sampling_rate_min.attr,
-	&sampling_rate.attr,
-	&sampling_down_factor.attr,
-	&up_threshold.attr,
-	&down_threshold.attr,
-	&ignore_nice_load.attr,
-	&freq_step.attr,
+show_store_one(cs, sampling_rate);
+show_store_one(cs, sampling_down_factor);
+show_store_one(cs, up_threshold);
+show_store_one(cs, down_threshold);
+show_store_one(cs, ignore_nice);
+show_store_one(cs, freq_step);
+declare_show_sampling_rate_min(cs);
+
+gov_sys_pol_attr_rw(sampling_rate);
+gov_sys_pol_attr_rw(sampling_down_factor);
+gov_sys_pol_attr_rw(up_threshold);
+gov_sys_pol_attr_rw(down_threshold);
+gov_sys_pol_attr_rw(ignore_nice);
+gov_sys_pol_attr_rw(freq_step);
+gov_sys_pol_attr_ro(sampling_rate_min);
+
+static struct attribute *dbs_attributes_gov_sys[] = {
+	&sampling_rate_min_gov_sys.attr,
+	&sampling_rate_gov_sys.attr,
+	&sampling_down_factor_gov_sys.attr,
+	&up_threshold_gov_sys.attr,
+	&down_threshold_gov_sys.attr,
+	&ignore_nice_gov_sys.attr,
+	&freq_step_gov_sys.attr,
 	NULL
 };
 
-static struct attribute_group cs_attr_group = {
-	.attrs = dbs_attributes,
+static struct attribute_group cs_attr_group_gov_sys = {
+	.attrs = dbs_attributes_gov_sys,
+	.name = "conservative",
+};
+
+static struct attribute *dbs_attributes_gov_pol[] = {
+	&sampling_rate_min_gov_pol.attr,
+	&sampling_rate_gov_pol.attr,
+	&sampling_down_factor_gov_pol.attr,
+	&up_threshold_gov_pol.attr,
+	&down_threshold_gov_pol.attr,
+	&ignore_nice_gov_pol.attr,
+	&freq_step_gov_pol.attr,
+	NULL
+};
+
+static struct attribute_group cs_attr_group_gov_pol = {
+	.attrs = dbs_attributes_gov_pol,
 	.name = "conservative",
 };
 
 /************************** sysfs end ************************/
 
+static int cs_init(struct dbs_data *dbs_data)
+{
+	struct cs_dbs_tuners *tuners;
+
+	tuners = kzalloc(sizeof(struct cs_dbs_tuners), GFP_KERNEL);
+	if (!tuners) {
+		pr_err("%s: kzalloc failed\n", __func__);
+		return -ENOMEM;
+	}
+
+	tuners->up_threshold = DEF_FREQUENCY_UP_THRESHOLD;
+	tuners->down_threshold = DEF_FREQUENCY_DOWN_THRESHOLD;
+	tuners->sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR;
+	tuners->ignore_nice = 0;
+	tuners->freq_step = DEF_FREQUENCY_STEP;
+
+	dbs_data->tuners = tuners;
+	dbs_data->min_sampling_rate = MIN_SAMPLING_RATE_RATIO *
+		jiffies_to_usecs(10);
+	mutex_init(&dbs_data->mutex);
+	return 0;
+}
+
+static void cs_exit(struct dbs_data *dbs_data)
+{
+	kfree(dbs_data->tuners);
+}
+
 define_get_cpu_dbs_routines(cs_cpu_dbs_info);
 
 static struct notifier_block cs_cpufreq_notifier_block = {
@@ -314,21 +363,23 @@ static struct cs_ops cs_ops = {
 	.notifier_block = &cs_cpufreq_notifier_block,
 };
 
-static struct dbs_data cs_dbs_data = {
+static struct common_dbs_data cs_dbs_cdata = {
 	.governor = GOV_CONSERVATIVE,
-	.attr_group = &cs_attr_group,
-	.tuners = &cs_tuners,
+	.attr_group_gov_sys = &cs_attr_group_gov_sys,
+	.attr_group_gov_pol = &cs_attr_group_gov_pol,
 	.get_cpu_cdbs = get_cpu_cdbs,
 	.get_cpu_dbs_info_s = get_cpu_dbs_info_s,
 	.gov_dbs_timer = cs_dbs_timer,
 	.gov_check_cpu = cs_check_cpu,
 	.gov_ops = &cs_ops,
+	.init = cs_init,
+	.exit = cs_exit,
 };
 
 static int cs_cpufreq_governor_dbs(struct cpufreq_policy *policy,
 				   unsigned int event)
 {
-	return cpufreq_governor_dbs(&cs_dbs_data, policy, event);
+	return cpufreq_governor_dbs(policy, &cs_dbs_cdata, event);
 }
 
 #ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE
@@ -343,7 +394,6 @@ struct cpufreq_governor cpufreq_gov_conservative = {
 
 static int __init cpufreq_gov_dbs_init(void)
 {
-	mutex_init(&cs_dbs_data.mutex);
 	return cpufreq_register_governor(&cpufreq_gov_conservative);
 }
 
diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c
index 5a76086..443442d 100644
--- a/drivers/cpufreq/cpufreq_governor.c
+++ b/drivers/cpufreq/cpufreq_governor.c
@@ -22,12 +22,29 @@
 #include <linux/export.h>
 #include <linux/kernel_stat.h>
 #include <linux/mutex.h>
+#include <linux/slab.h>
 #include <linux/tick.h>
 #include <linux/types.h>
 #include <linux/workqueue.h>
 
 #include "cpufreq_governor.h"
 
+static struct kobject *get_governor_parent_kobj(struct cpufreq_policy *policy)
+{
+	if (have_governor_per_policy())
+		return &policy->kobj;
+	else
+		return cpufreq_global_kobject;
+}
+
+static struct attribute_group *get_sysfs_attr(struct dbs_data *dbs_data)
+{
+	if (have_governor_per_policy())
+		return dbs_data->cdata->attr_group_gov_pol;
+	else
+		return dbs_data->cdata->attr_group_gov_sys;
+}
+
 static inline u64 get_cpu_idle_time_jiffy(unsigned int cpu, u64 *wall)
 {
 	u64 idle_time;
@@ -50,13 +67,13 @@ static inline u64 get_cpu_idle_time_jiffy(unsigned int cpu, u64 *wall)
 	return cputime_to_usecs(idle_time);
 }
 
-u64 get_cpu_idle_time(unsigned int cpu, u64 *wall)
+u64 get_cpu_idle_time(unsigned int cpu, u64 *wall, int io_busy)
 {
-	u64 idle_time = get_cpu_idle_time_us(cpu, NULL);
+	u64 idle_time = get_cpu_idle_time_us(cpu, io_busy ? wall : NULL);
 
 	if (idle_time == -1ULL)
 		return get_cpu_idle_time_jiffy(cpu, wall);
-	else
+	else if (!io_busy)
 		idle_time += get_cpu_iowait_time_us(cpu, wall);
 
 	return idle_time;
@@ -65,7 +82,7 @@ EXPORT_SYMBOL_GPL(get_cpu_idle_time);
 
 void dbs_check_cpu(struct dbs_data *dbs_data, int cpu)
 {
-	struct cpu_dbs_common_info *cdbs = dbs_data->get_cpu_cdbs(cpu);
+	struct cpu_dbs_common_info *cdbs = dbs_data->cdata->get_cpu_cdbs(cpu);
 	struct od_dbs_tuners *od_tuners = dbs_data->tuners;
 	struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
 	struct cpufreq_policy *policy;
@@ -73,7 +90,7 @@ void dbs_check_cpu(struct dbs_data *dbs_data, int cpu)
 	unsigned int ignore_nice;
 	unsigned int j;
 
-	if (dbs_data->governor == GOV_ONDEMAND)
+	if (dbs_data->cdata->governor == GOV_ONDEMAND)
 		ignore_nice = od_tuners->ignore_nice;
 	else
 		ignore_nice = cs_tuners->ignore_nice;
@@ -83,13 +100,22 @@ void dbs_check_cpu(struct dbs_data *dbs_data, int cpu)
 	/* Get Absolute Load (in terms of freq for ondemand gov) */
 	for_each_cpu(j, policy->cpus) {
 		struct cpu_dbs_common_info *j_cdbs;
-		u64 cur_wall_time, cur_idle_time, cur_iowait_time;
-		unsigned int idle_time, wall_time, iowait_time;
+		u64 cur_wall_time, cur_idle_time;
+		unsigned int idle_time, wall_time;
 		unsigned int load;
+		int io_busy = 0;
 
-		j_cdbs = dbs_data->get_cpu_cdbs(j);
+		j_cdbs = dbs_data->cdata->get_cpu_cdbs(j);
 
-		cur_idle_time = get_cpu_idle_time(j, &cur_wall_time);
+		/*
+		 * For the purpose of ondemand, waiting for disk IO is
+		 * an indication that you're performance critical, and
+		 * not that the system is actually idle. So do not add
+		 * the iowait time to the cpu idle time.
+		 */
+		if (dbs_data->cdata->governor == GOV_ONDEMAND)
+			io_busy = od_tuners->io_is_busy;
+		cur_idle_time = get_cpu_idle_time(j, &cur_wall_time, io_busy);
 
 		wall_time = (unsigned int)
 			(cur_wall_time - j_cdbs->prev_cpu_wall);
@@ -117,35 +143,12 @@ void dbs_check_cpu(struct dbs_data *dbs_data, int cpu)
 			idle_time += jiffies_to_usecs(cur_nice_jiffies);
 		}
 
-		if (dbs_data->governor == GOV_ONDEMAND) {
-			struct od_cpu_dbs_info_s *od_j_dbs_info =
-				dbs_data->get_cpu_dbs_info_s(cpu);
-
-			cur_iowait_time = get_cpu_iowait_time_us(j,
-					&cur_wall_time);
-			if (cur_iowait_time == -1ULL)
-				cur_iowait_time = 0;
-
-			iowait_time = (unsigned int) (cur_iowait_time -
-					od_j_dbs_info->prev_cpu_iowait);
-			od_j_dbs_info->prev_cpu_iowait = cur_iowait_time;
-
-			/*
-			 * For the purpose of ondemand, waiting for disk IO is
-			 * an indication that you're performance critical, and
-			 * not that the system is actually idle. So subtract the
-			 * iowait time from the cpu idle time.
-			 */
-			if (od_tuners->io_is_busy && idle_time >= iowait_time)
-				idle_time -= iowait_time;
-		}
-
 		if (unlikely(!wall_time || wall_time < idle_time))
 			continue;
 
 		load = 100 * (wall_time - idle_time) / wall_time;
 
-		if (dbs_data->governor == GOV_ONDEMAND) {
+		if (dbs_data->cdata->governor == GOV_ONDEMAND) {
 			int freq_avg = __cpufreq_driver_getavg(policy, j);
 			if (freq_avg <= 0)
 				freq_avg = policy->cur;
@@ -157,24 +160,42 @@ void dbs_check_cpu(struct dbs_data *dbs_data, int cpu)
 			max_load = load;
 	}
 
-	dbs_data->gov_check_cpu(cpu, max_load);
+	dbs_data->cdata->gov_check_cpu(cpu, max_load);
 }
 EXPORT_SYMBOL_GPL(dbs_check_cpu);
 
-static inline void dbs_timer_init(struct dbs_data *dbs_data, int cpu,
-				  unsigned int sampling_rate)
+static inline void __gov_queue_work(int cpu, struct dbs_data *dbs_data,
+		unsigned int delay)
 {
-	int delay = delay_for_sampling_rate(sampling_rate);
-	struct cpu_dbs_common_info *cdbs = dbs_data->get_cpu_cdbs(cpu);
+	struct cpu_dbs_common_info *cdbs = dbs_data->cdata->get_cpu_cdbs(cpu);
 
-	schedule_delayed_work_on(cpu, &cdbs->work, delay);
+	mod_delayed_work_on(cpu, system_wq, &cdbs->work, delay);
 }
 
-static inline void dbs_timer_exit(struct dbs_data *dbs_data, int cpu)
+void gov_queue_work(struct dbs_data *dbs_data, struct cpufreq_policy *policy,
+		unsigned int delay, bool all_cpus)
 {
-	struct cpu_dbs_common_info *cdbs = dbs_data->get_cpu_cdbs(cpu);
+	int i;
 
-	cancel_delayed_work_sync(&cdbs->work);
+	if (!all_cpus) {
+		__gov_queue_work(smp_processor_id(), dbs_data, delay);
+	} else {
+		for_each_cpu(i, policy->cpus)
+			__gov_queue_work(i, dbs_data, delay);
+	}
+}
+EXPORT_SYMBOL_GPL(gov_queue_work);
+
+static inline void gov_cancel_work(struct dbs_data *dbs_data,
+		struct cpufreq_policy *policy)
+{
+	struct cpu_dbs_common_info *cdbs;
+	int i;
+
+	for_each_cpu(i, policy->cpus) {
+		cdbs = dbs_data->cdata->get_cpu_cdbs(i);
+		cancel_delayed_work_sync(&cdbs->work);
+	}
 }
 
 /* Will return if we need to evaluate cpu load again or not */
@@ -196,31 +217,130 @@ bool need_load_eval(struct cpu_dbs_common_info *cdbs,
 }
 EXPORT_SYMBOL_GPL(need_load_eval);
 
-int cpufreq_governor_dbs(struct dbs_data *dbs_data,
-		struct cpufreq_policy *policy, unsigned int event)
+static void set_sampling_rate(struct dbs_data *dbs_data,
+		unsigned int sampling_rate)
 {
+	if (dbs_data->cdata->governor == GOV_CONSERVATIVE) {
+		struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
+		cs_tuners->sampling_rate = sampling_rate;
+	} else {
+		struct od_dbs_tuners *od_tuners = dbs_data->tuners;
+		od_tuners->sampling_rate = sampling_rate;
+	}
+}
+
+int cpufreq_governor_dbs(struct cpufreq_policy *policy,
+		struct common_dbs_data *cdata, unsigned int event)
+{
+	struct dbs_data *dbs_data;
 	struct od_cpu_dbs_info_s *od_dbs_info = NULL;
 	struct cs_cpu_dbs_info_s *cs_dbs_info = NULL;
-	struct cs_ops *cs_ops = NULL;
 	struct od_ops *od_ops = NULL;
-	struct od_dbs_tuners *od_tuners = dbs_data->tuners;
-	struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
+	struct od_dbs_tuners *od_tuners = NULL;
+	struct cs_dbs_tuners *cs_tuners = NULL;
 	struct cpu_dbs_common_info *cpu_cdbs;
-	unsigned int *sampling_rate, latency, ignore_nice, j, cpu = policy->cpu;
+	unsigned int sampling_rate, latency, ignore_nice, j, cpu = policy->cpu;
+	int io_busy = 0;
 	int rc;
 
-	cpu_cdbs = dbs_data->get_cpu_cdbs(cpu);
+	if (have_governor_per_policy())
+		dbs_data = policy->governor_data;
+	else
+		dbs_data = cdata->gdbs_data;
+
+	WARN_ON(!dbs_data && (event != CPUFREQ_GOV_POLICY_INIT));
+
+	switch (event) {
+	case CPUFREQ_GOV_POLICY_INIT:
+		if (have_governor_per_policy()) {
+			WARN_ON(dbs_data);
+		} else if (dbs_data) {
+			policy->governor_data = dbs_data;
+			return 0;
+		}
+
+		dbs_data = kzalloc(sizeof(*dbs_data), GFP_KERNEL);
+		if (!dbs_data) {
+			pr_err("%s: POLICY_INIT: kzalloc failed\n", __func__);
+			return -ENOMEM;
+		}
+
+		dbs_data->cdata = cdata;
+		rc = cdata->init(dbs_data);
+		if (rc) {
+			pr_err("%s: POLICY_INIT: init() failed\n", __func__);
+			kfree(dbs_data);
+			return rc;
+		}
+
+		rc = sysfs_create_group(get_governor_parent_kobj(policy),
+				get_sysfs_attr(dbs_data));
+		if (rc) {
+			cdata->exit(dbs_data);
+			kfree(dbs_data);
+			return rc;
+		}
+
+		policy->governor_data = dbs_data;
 
-	if (dbs_data->governor == GOV_CONSERVATIVE) {
-		cs_dbs_info = dbs_data->get_cpu_dbs_info_s(cpu);
-		sampling_rate = &cs_tuners->sampling_rate;
+		/* policy latency is in nS. Convert it to uS first */
+		latency = policy->cpuinfo.transition_latency / 1000;
+		if (latency == 0)
+			latency = 1;
+
+		/* Bring kernel and HW constraints together */
+		dbs_data->min_sampling_rate = max(dbs_data->min_sampling_rate,
+				MIN_LATENCY_MULTIPLIER * latency);
+		set_sampling_rate(dbs_data, max(dbs_data->min_sampling_rate,
+					latency * LATENCY_MULTIPLIER));
+
+		if (dbs_data->cdata->governor == GOV_CONSERVATIVE) {
+			struct cs_ops *cs_ops = dbs_data->cdata->gov_ops;
+
+			cpufreq_register_notifier(cs_ops->notifier_block,
+					CPUFREQ_TRANSITION_NOTIFIER);
+		}
+
+		if (!have_governor_per_policy())
+			cdata->gdbs_data = dbs_data;
+
+		return 0;
+	case CPUFREQ_GOV_POLICY_EXIT:
+		if ((policy->governor->initialized == 1) ||
+				have_governor_per_policy()) {
+			sysfs_remove_group(get_governor_parent_kobj(policy),
+					get_sysfs_attr(dbs_data));
+
+			if (dbs_data->cdata->governor == GOV_CONSERVATIVE) {
+				struct cs_ops *cs_ops = dbs_data->cdata->gov_ops;
+
+				cpufreq_unregister_notifier(cs_ops->notifier_block,
+						CPUFREQ_TRANSITION_NOTIFIER);
+			}
+
+			cdata->exit(dbs_data);
+			kfree(dbs_data);
+			cdata->gdbs_data = NULL;
+		}
+
+		policy->governor_data = NULL;
+		return 0;
+	}
+
+	cpu_cdbs = dbs_data->cdata->get_cpu_cdbs(cpu);
+
+	if (dbs_data->cdata->governor == GOV_CONSERVATIVE) {
+		cs_tuners = dbs_data->tuners;
+		cs_dbs_info = dbs_data->cdata->get_cpu_dbs_info_s(cpu);
+		sampling_rate = cs_tuners->sampling_rate;
 		ignore_nice = cs_tuners->ignore_nice;
-		cs_ops = dbs_data->gov_ops;
 	} else {
-		od_dbs_info = dbs_data->get_cpu_dbs_info_s(cpu);
-		sampling_rate = &od_tuners->sampling_rate;
+		od_tuners = dbs_data->tuners;
+		od_dbs_info = dbs_data->cdata->get_cpu_dbs_info_s(cpu);
+		sampling_rate = od_tuners->sampling_rate;
 		ignore_nice = od_tuners->ignore_nice;
-		od_ops = dbs_data->gov_ops;
+		od_ops = dbs_data->cdata->gov_ops;
+		io_busy = od_tuners->io_is_busy;
 	}
 
 	switch (event) {
@@ -232,96 +352,53 @@ int cpufreq_governor_dbs(struct dbs_data *dbs_data,
 
 		for_each_cpu(j, policy->cpus) {
 			struct cpu_dbs_common_info *j_cdbs =
-				dbs_data->get_cpu_cdbs(j);
+				dbs_data->cdata->get_cpu_cdbs(j);
 
 			j_cdbs->cpu = j;
 			j_cdbs->cur_policy = policy;
 			j_cdbs->prev_cpu_idle = get_cpu_idle_time(j,
-					&j_cdbs->prev_cpu_wall);
+					       &j_cdbs->prev_cpu_wall, io_busy);
 			if (ignore_nice)
 				j_cdbs->prev_cpu_nice =
 					kcpustat_cpu(j).cpustat[CPUTIME_NICE];
 
 			mutex_init(&j_cdbs->timer_mutex);
 			INIT_DEFERRABLE_WORK(&j_cdbs->work,
-					     dbs_data->gov_dbs_timer);
-		}
-
-		if (!policy->governor->initialized) {
-			rc = sysfs_create_group(cpufreq_global_kobject,
-					dbs_data->attr_group);
-			if (rc) {
-				mutex_unlock(&dbs_data->mutex);
-				return rc;
-			}
+					     dbs_data->cdata->gov_dbs_timer);
 		}
 
 		/*
 		 * conservative does not implement micro like ondemand
 		 * governor, thus we are bound to jiffes/HZ
 		 */
-		if (dbs_data->governor == GOV_CONSERVATIVE) {
+		if (dbs_data->cdata->governor == GOV_CONSERVATIVE) {
 			cs_dbs_info->down_skip = 0;
 			cs_dbs_info->enable = 1;
 			cs_dbs_info->requested_freq = policy->cur;
-
-			if (!policy->governor->initialized) {
-				cpufreq_register_notifier(cs_ops->notifier_block,
-						CPUFREQ_TRANSITION_NOTIFIER);
-
-				dbs_data->min_sampling_rate =
-					MIN_SAMPLING_RATE_RATIO *
-					jiffies_to_usecs(10);
-			}
 		} else {
 			od_dbs_info->rate_mult = 1;
 			od_dbs_info->sample_type = OD_NORMAL_SAMPLE;
 			od_ops->powersave_bias_init_cpu(cpu);
-
-			if (!policy->governor->initialized)
-				od_tuners->io_is_busy = od_ops->io_busy();
 		}
 
-		if (policy->governor->initialized)
-			goto unlock;
-
-		/* policy latency is in nS. Convert it to uS first */
-		latency = policy->cpuinfo.transition_latency / 1000;
-		if (latency == 0)
-			latency = 1;
-
-		/* Bring kernel and HW constraints together */
-		dbs_data->min_sampling_rate = max(dbs_data->min_sampling_rate,
-				MIN_LATENCY_MULTIPLIER * latency);
-		*sampling_rate = max(dbs_data->min_sampling_rate, latency *
-				LATENCY_MULTIPLIER);
-unlock:
 		mutex_unlock(&dbs_data->mutex);
 
 		/* Initiate timer time stamp */
 		cpu_cdbs->time_stamp = ktime_get();
 
-		for_each_cpu(j, policy->cpus)
-			dbs_timer_init(dbs_data, j, *sampling_rate);
+		gov_queue_work(dbs_data, policy,
+				delay_for_sampling_rate(sampling_rate), true);
 		break;
 
 	case CPUFREQ_GOV_STOP:
-		if (dbs_data->governor == GOV_CONSERVATIVE)
+		if (dbs_data->cdata->governor == GOV_CONSERVATIVE)
 			cs_dbs_info->enable = 0;
 
-		for_each_cpu(j, policy->cpus)
-			dbs_timer_exit(dbs_data, j);
+		gov_cancel_work(dbs_data, policy);
 
 		mutex_lock(&dbs_data->mutex);
 		mutex_destroy(&cpu_cdbs->timer_mutex);
 
-		if (policy->governor->initialized == 1) {
-			sysfs_remove_group(cpufreq_global_kobject,
-					dbs_data->attr_group);
-			if (dbs_data->governor == GOV_CONSERVATIVE)
-				cpufreq_unregister_notifier(cs_ops->notifier_block,
-						CPUFREQ_TRANSITION_NOTIFIER);
-		}
 		mutex_unlock(&dbs_data->mutex);
 
 		break;
diff --git a/drivers/cpufreq/cpufreq_governor.h b/drivers/cpufreq/cpufreq_governor.h
index 46bde01..6593769 100644
--- a/drivers/cpufreq/cpufreq_governor.h
+++ b/drivers/cpufreq/cpufreq_governor.h
@@ -14,8 +14,8 @@
  * published by the Free Software Foundation.
  */
 
-#ifndef _CPUFREQ_GOVERNER_H
-#define _CPUFREQ_GOVERNER_H
+#ifndef _CPUFREQ_GOVERNOR_H
+#define _CPUFREQ_GOVERNOR_H
 
 #include <linux/cpufreq.h>
 #include <linux/kobject.h>
@@ -34,20 +34,81 @@
  */
 #define MIN_SAMPLING_RATE_RATIO			(2)
 #define LATENCY_MULTIPLIER			(1000)
-#define MIN_LATENCY_MULTIPLIER			(100)
+#define MIN_LATENCY_MULTIPLIER			(20)
 #define TRANSITION_LATENCY_LIMIT		(10 * 1000 * 1000)
 
 /* Ondemand Sampling types */
 enum {OD_NORMAL_SAMPLE, OD_SUB_SAMPLE};
 
-/* Macro creating sysfs show routines */
-#define show_one(_gov, file_name, object)				\
-static ssize_t show_##file_name						\
+/*
+ * Macro for creating governors sysfs routines
+ *
+ * - gov_sys: One governor instance per whole system
+ * - gov_pol: One governor instance per policy
+ */
+
+/* Create attributes */
+#define gov_sys_attr_ro(_name)						\
+static struct global_attr _name##_gov_sys =				\
+__ATTR(_name, 0444, show_##_name##_gov_sys, NULL)
+
+#define gov_sys_attr_rw(_name)						\
+static struct global_attr _name##_gov_sys =				\
+__ATTR(_name, 0644, show_##_name##_gov_sys, store_##_name##_gov_sys)
+
+#define gov_pol_attr_ro(_name)						\
+static struct freq_attr _name##_gov_pol =				\
+__ATTR(_name, 0444, show_##_name##_gov_pol, NULL)
+
+#define gov_pol_attr_rw(_name)						\
+static struct freq_attr _name##_gov_pol =				\
+__ATTR(_name, 0644, show_##_name##_gov_pol, store_##_name##_gov_pol)
+
+#define gov_sys_pol_attr_rw(_name)					\
+	gov_sys_attr_rw(_name);						\
+	gov_pol_attr_rw(_name)
+
+#define gov_sys_pol_attr_ro(_name)					\
+	gov_sys_attr_ro(_name);						\
+	gov_pol_attr_ro(_name)
+
+/* Create show/store routines */
+#define show_one(_gov, file_name)					\
+static ssize_t show_##file_name##_gov_sys				\
 (struct kobject *kobj, struct attribute *attr, char *buf)		\
 {									\
-	return sprintf(buf, "%u\n", _gov##_tuners.object);		\
+	struct _gov##_dbs_tuners *tuners = _gov##_dbs_cdata.gdbs_data->tuners; \
+	return sprintf(buf, "%u\n", tuners->file_name);			\
+}									\
+									\
+static ssize_t show_##file_name##_gov_pol					\
+(struct cpufreq_policy *policy, char *buf)				\
+{									\
+	struct dbs_data *dbs_data = policy->governor_data;		\
+	struct _gov##_dbs_tuners *tuners = dbs_data->tuners;		\
+	return sprintf(buf, "%u\n", tuners->file_name);			\
+}
+
+#define store_one(_gov, file_name)					\
+static ssize_t store_##file_name##_gov_sys				\
+(struct kobject *kobj, struct attribute *attr, const char *buf, size_t count)	\
+{									\
+	struct dbs_data *dbs_data = _gov##_dbs_cdata.gdbs_data;		\
+	return store_##file_name(dbs_data, buf, count);			\
+}									\
+									\
+static ssize_t store_##file_name##_gov_pol				\
+(struct cpufreq_policy *policy, const char *buf, size_t count)		\
+{									\
+	struct dbs_data *dbs_data = policy->governor_data;		\
+	return store_##file_name(dbs_data, buf, count);			\
 }
 
+#define show_store_one(_gov, file_name)					\
+show_one(_gov, file_name);						\
+store_one(_gov, file_name)
+
+/* create helper routines */
 #define define_get_cpu_dbs_routines(_dbs_info)				\
 static struct cpu_dbs_common_info *get_cpu_cdbs(int cpu)		\
 {									\
@@ -87,7 +148,6 @@ struct cpu_dbs_common_info {
 
 struct od_cpu_dbs_info_s {
 	struct cpu_dbs_common_info cdbs;
-	u64 prev_cpu_iowait;
 	struct cpufreq_frequency_table *freq_table;
 	unsigned int freq_lo;
 	unsigned int freq_lo_jiffies;
@@ -103,7 +163,7 @@ struct cs_cpu_dbs_info_s {
 	unsigned int enable:1;
 };
 
-/* Governers sysfs tunables */
+/* Per policy Governers sysfs tunables */
 struct od_dbs_tuners {
 	unsigned int ignore_nice;
 	unsigned int sampling_rate;
@@ -123,31 +183,42 @@ struct cs_dbs_tuners {
 	unsigned int freq_step;
 };
 
-/* Per Governer data */
-struct dbs_data {
+/* Common Governer data across policies */
+struct dbs_data;
+struct common_dbs_data {
 	/* Common across governors */
 	#define GOV_ONDEMAND		0
 	#define GOV_CONSERVATIVE	1
 	int governor;
-	unsigned int min_sampling_rate;
-	struct attribute_group *attr_group;
-	void *tuners;
+	struct attribute_group *attr_group_gov_sys; /* one governor - system */
+	struct attribute_group *attr_group_gov_pol; /* one governor - policy */
 
-	/* dbs_mutex protects dbs_enable in governor start/stop */
-	struct mutex mutex;
+	/* Common data for platforms that don't set have_governor_per_policy */
+	struct dbs_data *gdbs_data;
 
 	struct cpu_dbs_common_info *(*get_cpu_cdbs)(int cpu);
 	void *(*get_cpu_dbs_info_s)(int cpu);
 	void (*gov_dbs_timer)(struct work_struct *work);
 	void (*gov_check_cpu)(int cpu, unsigned int load);
+	int (*init)(struct dbs_data *dbs_data);
+	void (*exit)(struct dbs_data *dbs_data);
 
 	/* Governor specific ops, see below */
 	void *gov_ops;
 };
 
+/* Governer Per policy data */
+struct dbs_data {
+	struct common_dbs_data *cdata;
+	unsigned int min_sampling_rate;
+	void *tuners;
+
+	/* dbs_mutex protects dbs_enable in governor start/stop */
+	struct mutex mutex;
+};
+
 /* Governor specific ops, will be passed to dbs_data->gov_ops */
 struct od_ops {
-	int (*io_busy)(void);
 	void (*powersave_bias_init_cpu)(int cpu);
 	unsigned int (*powersave_bias_target)(struct cpufreq_policy *policy,
 			unsigned int freq_next, unsigned int relation);
@@ -169,10 +240,27 @@ static inline int delay_for_sampling_rate(unsigned int sampling_rate)
 	return delay;
 }
 
-u64 get_cpu_idle_time(unsigned int cpu, u64 *wall);
+#define declare_show_sampling_rate_min(_gov)				\
+static ssize_t show_sampling_rate_min_gov_sys				\
+(struct kobject *kobj, struct attribute *attr, char *buf)		\
+{									\
+	struct dbs_data *dbs_data = _gov##_dbs_cdata.gdbs_data;		\
+	return sprintf(buf, "%u\n", dbs_data->min_sampling_rate);	\
+}									\
+									\
+static ssize_t show_sampling_rate_min_gov_pol				\
+(struct cpufreq_policy *policy, char *buf)				\
+{									\
+	struct dbs_data *dbs_data = policy->governor_data;		\
+	return sprintf(buf, "%u\n", dbs_data->min_sampling_rate);	\
+}
+
+u64 get_cpu_idle_time(unsigned int cpu, u64 *wall, int io_busy);
 void dbs_check_cpu(struct dbs_data *dbs_data, int cpu);
 bool need_load_eval(struct cpu_dbs_common_info *cdbs,
 		unsigned int sampling_rate);
-int cpufreq_governor_dbs(struct dbs_data *dbs_data,
-		struct cpufreq_policy *policy, unsigned int event);
-#endif /* _CPUFREQ_GOVERNER_H */
+int cpufreq_governor_dbs(struct cpufreq_policy *policy,
+		struct common_dbs_data *cdata, unsigned int event);
+void gov_queue_work(struct dbs_data *dbs_data, struct cpufreq_policy *policy,
+		unsigned int delay, bool all_cpus);
+#endif /* _CPUFREQ_GOVERNOR_H */
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index f3eb26c..1471478 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -20,6 +20,7 @@
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/percpu-defs.h>
+#include <linux/slab.h>
 #include <linux/sysfs.h>
 #include <linux/tick.h>
 #include <linux/types.h>
@@ -37,22 +38,12 @@
 #define MIN_FREQUENCY_UP_THRESHOLD		(11)
 #define MAX_FREQUENCY_UP_THRESHOLD		(100)
 
-static struct dbs_data od_dbs_data;
 static DEFINE_PER_CPU(struct od_cpu_dbs_info_s, od_cpu_dbs_info);
 
 #ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND
 static struct cpufreq_governor cpufreq_gov_ondemand;
 #endif
 
-static struct od_dbs_tuners od_tuners = {
-	.up_threshold = DEF_FREQUENCY_UP_THRESHOLD,
-	.sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR,
-	.adj_up_threshold = DEF_FREQUENCY_UP_THRESHOLD -
-			    DEF_FREQUENCY_DOWN_DIFFERENTIAL,
-	.ignore_nice = 0,
-	.powersave_bias = 0,
-};
-
 static void ondemand_powersave_bias_init_cpu(int cpu)
 {
 	struct od_cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info, cpu);
@@ -98,6 +89,8 @@ static unsigned int powersave_bias_target(struct cpufreq_policy *policy,
 	unsigned int jiffies_total, jiffies_hi, jiffies_lo;
 	struct od_cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info,
 						   policy->cpu);
+	struct dbs_data *dbs_data = policy->governor_data;
+	struct od_dbs_tuners *od_tuners = dbs_data->tuners;
 
 	if (!dbs_info->freq_table) {
 		dbs_info->freq_lo = 0;
@@ -108,7 +101,7 @@ static unsigned int powersave_bias_target(struct cpufreq_policy *policy,
 	cpufreq_frequency_table_target(policy, dbs_info->freq_table, freq_next,
 			relation, &index);
 	freq_req = dbs_info->freq_table[index].frequency;
-	freq_reduc = freq_req * od_tuners.powersave_bias / 1000;
+	freq_reduc = freq_req * od_tuners->powersave_bias / 1000;
 	freq_avg = freq_req - freq_reduc;
 
 	/* Find freq bounds for freq_avg in freq_table */
@@ -127,7 +120,7 @@ static unsigned int powersave_bias_target(struct cpufreq_policy *policy,
 		dbs_info->freq_lo_jiffies = 0;
 		return freq_lo;
 	}
-	jiffies_total = usecs_to_jiffies(od_tuners.sampling_rate);
+	jiffies_total = usecs_to_jiffies(od_tuners->sampling_rate);
 	jiffies_hi = (freq_avg - freq_lo) * jiffies_total;
 	jiffies_hi += ((freq_hi - freq_lo) / 2);
 	jiffies_hi /= (freq_hi - freq_lo);
@@ -148,12 +141,15 @@ static void ondemand_powersave_bias_init(void)
 
 static void dbs_freq_increase(struct cpufreq_policy *p, unsigned int freq)
 {
-	if (od_tuners.powersave_bias)
+	struct dbs_data *dbs_data = p->governor_data;
+	struct od_dbs_tuners *od_tuners = dbs_data->tuners;
+
+	if (od_tuners->powersave_bias)
 		freq = powersave_bias_target(p, freq, CPUFREQ_RELATION_H);
 	else if (p->cur == p->max)
 		return;
 
-	__cpufreq_driver_target(p, freq, od_tuners.powersave_bias ?
+	__cpufreq_driver_target(p, freq, od_tuners->powersave_bias ?
 			CPUFREQ_RELATION_L : CPUFREQ_RELATION_H);
 }
 
@@ -170,15 +166,17 @@ static void od_check_cpu(int cpu, unsigned int load_freq)
 {
 	struct od_cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info, cpu);
 	struct cpufreq_policy *policy = dbs_info->cdbs.cur_policy;
+	struct dbs_data *dbs_data = policy->governor_data;
+	struct od_dbs_tuners *od_tuners = dbs_data->tuners;
 
 	dbs_info->freq_lo = 0;
 
 	/* Check for frequency increase */
-	if (load_freq > od_tuners.up_threshold * policy->cur) {
+	if (load_freq > od_tuners->up_threshold * policy->cur) {
 		/* If switching to max speed, apply sampling_down_factor */
 		if (policy->cur < policy->max)
 			dbs_info->rate_mult =
-				od_tuners.sampling_down_factor;
+				od_tuners->sampling_down_factor;
 		dbs_freq_increase(policy, policy->max);
 		return;
 	}
@@ -193,9 +191,10 @@ static void od_check_cpu(int cpu, unsigned int load_freq)
 	 * support the current CPU usage without triggering the up policy. To be
 	 * safe, we focus 10 points under the threshold.
 	 */
-	if (load_freq < od_tuners.adj_up_threshold * policy->cur) {
+	if (load_freq < od_tuners->adj_up_threshold
+			* policy->cur) {
 		unsigned int freq_next;
-		freq_next = load_freq / od_tuners.adj_up_threshold;
+		freq_next = load_freq / od_tuners->adj_up_threshold;
 
 		/* No longer fully busy, reset rate_mult */
 		dbs_info->rate_mult = 1;
@@ -203,7 +202,7 @@ static void od_check_cpu(int cpu, unsigned int load_freq)
 		if (freq_next < policy->min)
 			freq_next = policy->min;
 
-		if (!od_tuners.powersave_bias) {
+		if (!od_tuners->powersave_bias) {
 			__cpufreq_driver_target(policy, freq_next,
 					CPUFREQ_RELATION_L);
 		} else {
@@ -217,51 +216,48 @@ static void od_check_cpu(int cpu, unsigned int load_freq)
 
 static void od_dbs_timer(struct work_struct *work)
 {
-	struct delayed_work *dw = to_delayed_work(work);
 	struct od_cpu_dbs_info_s *dbs_info =
 		container_of(work, struct od_cpu_dbs_info_s, cdbs.work.work);
 	unsigned int cpu = dbs_info->cdbs.cur_policy->cpu;
 	struct od_cpu_dbs_info_s *core_dbs_info = &per_cpu(od_cpu_dbs_info,
 			cpu);
-	int delay, sample_type = core_dbs_info->sample_type;
-	bool eval_load;
+	struct dbs_data *dbs_data = dbs_info->cdbs.cur_policy->governor_data;
+	struct od_dbs_tuners *od_tuners = dbs_data->tuners;
+	int delay = 0, sample_type = core_dbs_info->sample_type;
+	bool modify_all = true;
 
 	mutex_lock(&core_dbs_info->cdbs.timer_mutex);
-	eval_load = need_load_eval(&core_dbs_info->cdbs,
-			od_tuners.sampling_rate);
+	if (!need_load_eval(&core_dbs_info->cdbs, od_tuners->sampling_rate)) {
+		modify_all = false;
+		goto max_delay;
+	}
 
 	/* Common NORMAL_SAMPLE setup */
 	core_dbs_info->sample_type = OD_NORMAL_SAMPLE;
 	if (sample_type == OD_SUB_SAMPLE) {
 		delay = core_dbs_info->freq_lo_jiffies;
-		if (eval_load)
-			__cpufreq_driver_target(core_dbs_info->cdbs.cur_policy,
-						core_dbs_info->freq_lo,
-						CPUFREQ_RELATION_H);
+		__cpufreq_driver_target(core_dbs_info->cdbs.cur_policy,
+				core_dbs_info->freq_lo, CPUFREQ_RELATION_H);
 	} else {
-		if (eval_load)
-			dbs_check_cpu(&od_dbs_data, cpu);
+		dbs_check_cpu(dbs_data, cpu);
 		if (core_dbs_info->freq_lo) {
 			/* Setup timer for SUB_SAMPLE */
 			core_dbs_info->sample_type = OD_SUB_SAMPLE;
 			delay = core_dbs_info->freq_hi_jiffies;
-		} else {
-			delay = delay_for_sampling_rate(od_tuners.sampling_rate
-						* core_dbs_info->rate_mult);
 		}
 	}
 
-	schedule_delayed_work_on(smp_processor_id(), dw, delay);
+max_delay:
+	if (!delay)
+		delay = delay_for_sampling_rate(od_tuners->sampling_rate
+				* core_dbs_info->rate_mult);
+
+	gov_queue_work(dbs_data, dbs_info->cdbs.cur_policy, delay, modify_all);
 	mutex_unlock(&core_dbs_info->cdbs.timer_mutex);
 }
 
 /************************** sysfs interface ************************/
-
-static ssize_t show_sampling_rate_min(struct kobject *kobj,
-				      struct attribute *attr, char *buf)
-{
-	return sprintf(buf, "%u\n", od_dbs_data.min_sampling_rate);
-}
+static struct common_dbs_data od_dbs_cdata;
 
 /**
  * update_sampling_rate - update sampling rate effective immediately if needed.
@@ -276,12 +272,14 @@ static ssize_t show_sampling_rate_min(struct kobject *kobj,
  * reducing the sampling rate, we need to make the new value effective
  * immediately.
  */
-static void update_sampling_rate(unsigned int new_rate)
+static void update_sampling_rate(struct dbs_data *dbs_data,
+		unsigned int new_rate)
 {
+	struct od_dbs_tuners *od_tuners = dbs_data->tuners;
 	int cpu;
 
-	od_tuners.sampling_rate = new_rate = max(new_rate,
-			od_dbs_data.min_sampling_rate);
+	od_tuners->sampling_rate = new_rate = max(new_rate,
+			dbs_data->min_sampling_rate);
 
 	for_each_online_cpu(cpu) {
 		struct cpufreq_policy *policy;
@@ -314,42 +312,54 @@ static void update_sampling_rate(unsigned int new_rate)
 			cancel_delayed_work_sync(&dbs_info->cdbs.work);
 			mutex_lock(&dbs_info->cdbs.timer_mutex);
 
-			schedule_delayed_work_on(cpu, &dbs_info->cdbs.work,
-					usecs_to_jiffies(new_rate));
+			gov_queue_work(dbs_data, dbs_info->cdbs.cur_policy,
+					usecs_to_jiffies(new_rate), true);
 
 		}
 		mutex_unlock(&dbs_info->cdbs.timer_mutex);
 	}
 }
 
-static ssize_t store_sampling_rate(struct kobject *a, struct attribute *b,
-				   const char *buf, size_t count)
+static ssize_t store_sampling_rate(struct dbs_data *dbs_data, const char *buf,
+		size_t count)
 {
 	unsigned int input;
 	int ret;
 	ret = sscanf(buf, "%u", &input);
 	if (ret != 1)
 		return -EINVAL;
-	update_sampling_rate(input);
+
+	update_sampling_rate(dbs_data, input);
 	return count;
 }
 
-static ssize_t store_io_is_busy(struct kobject *a, struct attribute *b,
-				   const char *buf, size_t count)
+static ssize_t store_io_is_busy(struct dbs_data *dbs_data, const char *buf,
+		size_t count)
 {
+	struct od_dbs_tuners *od_tuners = dbs_data->tuners;
 	unsigned int input;
 	int ret;
+	unsigned int j;
 
 	ret = sscanf(buf, "%u", &input);
 	if (ret != 1)
 		return -EINVAL;
-	od_tuners.io_is_busy = !!input;
+	od_tuners->io_is_busy = !!input;
+
+	/* we need to re-evaluate prev_cpu_idle */
+	for_each_online_cpu(j) {
+		struct od_cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info,
+									j);
+		dbs_info->cdbs.prev_cpu_idle = get_cpu_idle_time(j,
+			&dbs_info->cdbs.prev_cpu_wall, od_tuners->io_is_busy);
+	}
 	return count;
 }
 
-static ssize_t store_up_threshold(struct kobject *a, struct attribute *b,
-				  const char *buf, size_t count)
+static ssize_t store_up_threshold(struct dbs_data *dbs_data, const char *buf,
+		size_t count)
 {
+	struct od_dbs_tuners *od_tuners = dbs_data->tuners;
 	unsigned int input;
 	int ret;
 	ret = sscanf(buf, "%u", &input);
@@ -359,23 +369,24 @@ static ssize_t store_up_threshold(struct kobject *a, struct attribute *b,
 		return -EINVAL;
 	}
 	/* Calculate the new adj_up_threshold */
-	od_tuners.adj_up_threshold += input;
-	od_tuners.adj_up_threshold -= od_tuners.up_threshold;
+	od_tuners->adj_up_threshold += input;
+	od_tuners->adj_up_threshold -= od_tuners->up_threshold;
 
-	od_tuners.up_threshold = input;
+	od_tuners->up_threshold = input;
 	return count;
 }
 
-static ssize_t store_sampling_down_factor(struct kobject *a,
-			struct attribute *b, const char *buf, size_t count)
+static ssize_t store_sampling_down_factor(struct dbs_data *dbs_data,
+		const char *buf, size_t count)
 {
+	struct od_dbs_tuners *od_tuners = dbs_data->tuners;
 	unsigned int input, j;
 	int ret;
 	ret = sscanf(buf, "%u", &input);
 
 	if (ret != 1 || input > MAX_SAMPLING_DOWN_FACTOR || input < 1)
 		return -EINVAL;
-	od_tuners.sampling_down_factor = input;
+	od_tuners->sampling_down_factor = input;
 
 	/* Reset down sampling multiplier in case it was active */
 	for_each_online_cpu(j) {
@@ -386,9 +397,10 @@ static ssize_t store_sampling_down_factor(struct kobject *a,
 	return count;
 }
 
-static ssize_t store_ignore_nice_load(struct kobject *a, struct attribute *b,
-				      const char *buf, size_t count)
+static ssize_t store_ignore_nice(struct dbs_data *dbs_data, const char *buf,
+		size_t count)
 {
+	struct od_dbs_tuners *od_tuners = dbs_data->tuners;
 	unsigned int input;
 	int ret;
 
@@ -401,18 +413,18 @@ static ssize_t store_ignore_nice_load(struct kobject *a, struct attribute *b,
 	if (input > 1)
 		input = 1;
 
-	if (input == od_tuners.ignore_nice) { /* nothing to do */
+	if (input == od_tuners->ignore_nice) { /* nothing to do */
 		return count;
 	}
-	od_tuners.ignore_nice = input;
+	od_tuners->ignore_nice = input;
 
 	/* we need to re-evaluate prev_cpu_idle */
 	for_each_online_cpu(j) {
 		struct od_cpu_dbs_info_s *dbs_info;
 		dbs_info = &per_cpu(od_cpu_dbs_info, j);
 		dbs_info->cdbs.prev_cpu_idle = get_cpu_idle_time(j,
-						&dbs_info->cdbs.prev_cpu_wall);
-		if (od_tuners.ignore_nice)
+			&dbs_info->cdbs.prev_cpu_wall, od_tuners->io_is_busy);
+		if (od_tuners->ignore_nice)
 			dbs_info->cdbs.prev_cpu_nice =
 				kcpustat_cpu(j).cpustat[CPUTIME_NICE];
 
@@ -420,9 +432,10 @@ static ssize_t store_ignore_nice_load(struct kobject *a, struct attribute *b,
 	return count;
 }
 
-static ssize_t store_powersave_bias(struct kobject *a, struct attribute *b,
-				    const char *buf, size_t count)
+static ssize_t store_powersave_bias(struct dbs_data *dbs_data, const char *buf,
+		size_t count)
 {
+	struct od_dbs_tuners *od_tuners = dbs_data->tuners;
 	unsigned int input;
 	int ret;
 	ret = sscanf(buf, "%u", &input);
@@ -433,68 +446,138 @@ static ssize_t store_powersave_bias(struct kobject *a, struct attribute *b,
 	if (input > 1000)
 		input = 1000;
 
-	od_tuners.powersave_bias = input;
+	od_tuners->powersave_bias = input;
 	ondemand_powersave_bias_init();
 	return count;
 }
 
-show_one(od, sampling_rate, sampling_rate);
-show_one(od, io_is_busy, io_is_busy);
-show_one(od, up_threshold, up_threshold);
-show_one(od, sampling_down_factor, sampling_down_factor);
-show_one(od, ignore_nice_load, ignore_nice);
-show_one(od, powersave_bias, powersave_bias);
-
-define_one_global_rw(sampling_rate);
-define_one_global_rw(io_is_busy);
-define_one_global_rw(up_threshold);
-define_one_global_rw(sampling_down_factor);
-define_one_global_rw(ignore_nice_load);
-define_one_global_rw(powersave_bias);
-define_one_global_ro(sampling_rate_min);
-
-static struct attribute *dbs_attributes[] = {
-	&sampling_rate_min.attr,
-	&sampling_rate.attr,
-	&up_threshold.attr,
-	&sampling_down_factor.attr,
-	&ignore_nice_load.attr,
-	&powersave_bias.attr,
-	&io_is_busy.attr,
+show_store_one(od, sampling_rate);
+show_store_one(od, io_is_busy);
+show_store_one(od, up_threshold);
+show_store_one(od, sampling_down_factor);
+show_store_one(od, ignore_nice);
+show_store_one(od, powersave_bias);
+declare_show_sampling_rate_min(od);
+
+gov_sys_pol_attr_rw(sampling_rate);
+gov_sys_pol_attr_rw(io_is_busy);
+gov_sys_pol_attr_rw(up_threshold);
+gov_sys_pol_attr_rw(sampling_down_factor);
+gov_sys_pol_attr_rw(ignore_nice);
+gov_sys_pol_attr_rw(powersave_bias);
+gov_sys_pol_attr_ro(sampling_rate_min);
+
+static struct attribute *dbs_attributes_gov_sys[] = {
+	&sampling_rate_min_gov_sys.attr,
+	&sampling_rate_gov_sys.attr,
+	&up_threshold_gov_sys.attr,
+	&sampling_down_factor_gov_sys.attr,
+	&ignore_nice_gov_sys.attr,
+	&powersave_bias_gov_sys.attr,
+	&io_is_busy_gov_sys.attr,
 	NULL
 };
 
-static struct attribute_group od_attr_group = {
-	.attrs = dbs_attributes,
+static struct attribute_group od_attr_group_gov_sys = {
+	.attrs = dbs_attributes_gov_sys,
+	.name = "ondemand",
+};
+
+static struct attribute *dbs_attributes_gov_pol[] = {
+	&sampling_rate_min_gov_pol.attr,
+	&sampling_rate_gov_pol.attr,
+	&up_threshold_gov_pol.attr,
+	&sampling_down_factor_gov_pol.attr,
+	&ignore_nice_gov_pol.attr,
+	&powersave_bias_gov_pol.attr,
+	&io_is_busy_gov_pol.attr,
+	NULL
+};
+
+static struct attribute_group od_attr_group_gov_pol = {
+	.attrs = dbs_attributes_gov_pol,
 	.name = "ondemand",
 };
 
 /************************** sysfs end ************************/
 
+static int od_init(struct dbs_data *dbs_data)
+{
+	struct od_dbs_tuners *tuners;
+	u64 idle_time;
+	int cpu;
+
+	tuners = kzalloc(sizeof(struct od_dbs_tuners), GFP_KERNEL);
+	if (!tuners) {
+		pr_err("%s: kzalloc failed\n", __func__);
+		return -ENOMEM;
+	}
+
+	cpu = get_cpu();
+	idle_time = get_cpu_idle_time_us(cpu, NULL);
+	put_cpu();
+	if (idle_time != -1ULL) {
+		/* Idle micro accounting is supported. Use finer thresholds */
+		tuners->up_threshold = MICRO_FREQUENCY_UP_THRESHOLD;
+		tuners->adj_up_threshold = MICRO_FREQUENCY_UP_THRESHOLD -
+			MICRO_FREQUENCY_DOWN_DIFFERENTIAL;
+		/*
+		 * In nohz/micro accounting case we set the minimum frequency
+		 * not depending on HZ, but fixed (very low). The deferred
+		 * timer might skip some samples if idle/sleeping as needed.
+		*/
+		dbs_data->min_sampling_rate = MICRO_FREQUENCY_MIN_SAMPLE_RATE;
+	} else {
+		tuners->up_threshold = DEF_FREQUENCY_UP_THRESHOLD;
+		tuners->adj_up_threshold = DEF_FREQUENCY_UP_THRESHOLD -
+			DEF_FREQUENCY_DOWN_DIFFERENTIAL;
+
+		/* For correct statistics, we need 10 ticks for each measure */
+		dbs_data->min_sampling_rate = MIN_SAMPLING_RATE_RATIO *
+			jiffies_to_usecs(10);
+	}
+
+	tuners->sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR;
+	tuners->ignore_nice = 0;
+	tuners->powersave_bias = 0;
+	tuners->io_is_busy = should_io_be_busy();
+
+	dbs_data->tuners = tuners;
+	pr_info("%s: tuners %p\n", __func__, tuners);
+	mutex_init(&dbs_data->mutex);
+	return 0;
+}
+
+static void od_exit(struct dbs_data *dbs_data)
+{
+	kfree(dbs_data->tuners);
+}
+
 define_get_cpu_dbs_routines(od_cpu_dbs_info);
 
 static struct od_ops od_ops = {
-	.io_busy = should_io_be_busy,
 	.powersave_bias_init_cpu = ondemand_powersave_bias_init_cpu,
 	.powersave_bias_target = powersave_bias_target,
 	.freq_increase = dbs_freq_increase,
 };
 
-static struct dbs_data od_dbs_data = {
+static struct common_dbs_data od_dbs_cdata = {
 	.governor = GOV_ONDEMAND,
-	.attr_group = &od_attr_group,
-	.tuners = &od_tuners,
+	.attr_group_gov_sys = &od_attr_group_gov_sys,
+	.attr_group_gov_pol = &od_attr_group_gov_pol,
 	.get_cpu_cdbs = get_cpu_cdbs,
 	.get_cpu_dbs_info_s = get_cpu_dbs_info_s,
 	.gov_dbs_timer = od_dbs_timer,
 	.gov_check_cpu = od_check_cpu,
 	.gov_ops = &od_ops,
+	.init = od_init,
+	.exit = od_exit,
 };
 
 static int od_cpufreq_governor_dbs(struct cpufreq_policy *policy,
 		unsigned int event)
 {
-	return cpufreq_governor_dbs(&od_dbs_data, policy, event);
+	return cpufreq_governor_dbs(policy, &od_dbs_cdata, event);
 }
 
 #ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND
@@ -509,29 +592,6 @@ struct cpufreq_governor cpufreq_gov_ondemand = {
 
 static int __init cpufreq_gov_dbs_init(void)
 {
-	u64 idle_time;
-	int cpu = get_cpu();
-
-	mutex_init(&od_dbs_data.mutex);
-	idle_time = get_cpu_idle_time_us(cpu, NULL);
-	put_cpu();
-	if (idle_time != -1ULL) {
-		/* Idle micro accounting is supported. Use finer thresholds */
-		od_tuners.up_threshold = MICRO_FREQUENCY_UP_THRESHOLD;
-		od_tuners.adj_up_threshold = MICRO_FREQUENCY_UP_THRESHOLD -
-					     MICRO_FREQUENCY_DOWN_DIFFERENTIAL;
-		/*
-		 * In nohz/micro accounting case we set the minimum frequency
-		 * not depending on HZ, but fixed (very low). The deferred
-		 * timer might skip some samples if idle/sleeping as needed.
-		*/
-		od_dbs_data.min_sampling_rate = MICRO_FREQUENCY_MIN_SAMPLE_RATE;
-	} else {
-		/* For correct statistics, we need 10 ticks for each measure */
-		od_dbs_data.min_sampling_rate = MIN_SAMPLING_RATE_RATIO *
-			jiffies_to_usecs(10);
-	}
-
 	return cpufreq_register_governor(&cpufreq_gov_ondemand);
 }
 
diff --git a/drivers/cpufreq/dbx500-cpufreq.c b/drivers/cpufreq/dbx500-cpufreq.c
index 72f0c3e..15ed367 100644
--- a/drivers/cpufreq/dbx500-cpufreq.c
+++ b/drivers/cpufreq/dbx500-cpufreq.c
@@ -37,12 +37,6 @@ static int dbx500_cpufreq_target(struct cpufreq_policy *policy,
 	unsigned int idx;
 	int ret;
 
-	/* scale the target frequency to one of the extremes supported */
-	if (target_freq < policy->cpuinfo.min_freq)
-		target_freq = policy->cpuinfo.min_freq;
-	if (target_freq > policy->cpuinfo.max_freq)
-		target_freq = policy->cpuinfo.max_freq;
-
 	/* Lookup the next frequency */
 	if (cpufreq_frequency_table_target(policy, freq_table, target_freq,
 					relation, &idx))
@@ -55,8 +49,7 @@ static int dbx500_cpufreq_target(struct cpufreq_policy *policy,
 		return 0;
 
 	/* pre-change notification */
-	for_each_cpu(freqs.cpu, policy->cpus)
-		cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
 
 	/* update armss clk frequency */
 	ret = clk_set_rate(armss_clk, freqs.new * 1000);
@@ -68,8 +61,7 @@ static int dbx500_cpufreq_target(struct cpufreq_policy *policy,
 	}
 
 	/* post change notification */
-	for_each_cpu(freqs.cpu, policy->cpus)
-		cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
 
 	return 0;
 }
diff --git a/drivers/cpufreq/e_powersaver.c b/drivers/cpufreq/e_powersaver.c
index 3fffbe6..37380fb 100644
--- a/drivers/cpufreq/e_powersaver.c
+++ b/drivers/cpufreq/e_powersaver.c
@@ -104,7 +104,7 @@ static unsigned int eps_get(unsigned int cpu)
 }
 
 static int eps_set_state(struct eps_cpu_data *centaur,
-			 unsigned int cpu,
+			 struct cpufreq_policy *policy,
 			 u32 dest_state)
 {
 	struct cpufreq_freqs freqs;
@@ -112,10 +112,9 @@ static int eps_set_state(struct eps_cpu_data *centaur,
 	int err = 0;
 	int i;
 
-	freqs.old = eps_get(cpu);
+	freqs.old = eps_get(policy->cpu);
 	freqs.new = centaur->fsb * ((dest_state >> 8) & 0xff);
-	freqs.cpu = cpu;
-	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
 
 	/* Wait while CPU is busy */
 	rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
@@ -162,7 +161,7 @@ postchange:
 		current_multiplier);
 	}
 #endif
-	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
 	return err;
 }
 
@@ -190,7 +189,7 @@ static int eps_target(struct cpufreq_policy *policy,
 
 	/* Make frequency transition */
 	dest_state = centaur->freq_table[newstate].index & 0xffff;
-	ret = eps_set_state(centaur, cpu, dest_state);
+	ret = eps_set_state(centaur, policy, dest_state);
 	if (ret)
 		printk(KERN_ERR "eps: Timeout!\n");
 	return ret;
diff --git a/drivers/cpufreq/elanfreq.c b/drivers/cpufreq/elanfreq.c
index 960671f..658d860 100644
--- a/drivers/cpufreq/elanfreq.c
+++ b/drivers/cpufreq/elanfreq.c
@@ -117,15 +117,15 @@ static unsigned int elanfreq_get_cpu_frequency(unsigned int cpu)
  *	There is no return value.
  */
 
-static void elanfreq_set_cpu_state(unsigned int state)
+static void elanfreq_set_cpu_state(struct cpufreq_policy *policy,
+		unsigned int state)
 {
 	struct cpufreq_freqs    freqs;
 
 	freqs.old = elanfreq_get_cpu_frequency(0);
 	freqs.new = elan_multiplier[state].clock;
-	freqs.cpu = 0; /* elanfreq.c is UP only driver */
 
-	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
 
 	printk(KERN_INFO "elanfreq: attempting to set frequency to %i kHz\n",
 			elan_multiplier[state].clock);
@@ -161,7 +161,7 @@ static void elanfreq_set_cpu_state(unsigned int state)
 	udelay(10000);
 	local_irq_enable();
 
-	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
 };
 
 
@@ -188,7 +188,7 @@ static int elanfreq_target(struct cpufreq_policy *policy,
 				target_freq, relation, &newstate))
 		return -EINVAL;
 
-	elanfreq_set_cpu_state(newstate);
+	elanfreq_set_cpu_state(policy, newstate);
 
 	return 0;
 }
diff --git a/drivers/cpufreq/exynos-cpufreq.c b/drivers/cpufreq/exynos-cpufreq.c
index 78057a3..c0c4ce5 100644
--- a/drivers/cpufreq/exynos-cpufreq.c
+++ b/drivers/cpufreq/exynos-cpufreq.c
@@ -70,7 +70,6 @@ static int exynos_cpufreq_scale(unsigned int target_freq)
 
 	freqs.old = policy->cur;
 	freqs.new = target_freq;
-	freqs.cpu = policy->cpu;
 
 	if (freqs.new == freqs.old)
 		goto out;
@@ -105,8 +104,7 @@ static int exynos_cpufreq_scale(unsigned int target_freq)
 	}
 	arm_volt = volt_table[index];
 
-	for_each_cpu(freqs.cpu, policy->cpus)
-		cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
 
 	/* When the new frequency is higher than current frequency */
 	if ((freqs.new > freqs.old) && !safe_arm_volt) {
@@ -131,8 +129,7 @@ static int exynos_cpufreq_scale(unsigned int target_freq)
 
 	exynos_info->set_freq(old_index, index);
 
-	for_each_cpu(freqs.cpu, policy->cpus)
-		cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
 
 	/* When the new frequency is lower than current frequency */
 	if ((freqs.new < freqs.old) ||
diff --git a/drivers/cpufreq/gx-suspmod.c b/drivers/cpufreq/gx-suspmod.c
index 456bee0..3dfc99b 100644
--- a/drivers/cpufreq/gx-suspmod.c
+++ b/drivers/cpufreq/gx-suspmod.c
@@ -251,14 +251,13 @@ static unsigned int gx_validate_speed(unsigned int khz, u8 *on_duration,
  * set cpu speed in khz.
  **/
 
-static void gx_set_cpuspeed(unsigned int khz)
+static void gx_set_cpuspeed(struct cpufreq_policy *policy, unsigned int khz)
 {
 	u8 suscfg, pmer1;
 	unsigned int new_khz;
 	unsigned long flags;
 	struct cpufreq_freqs freqs;
 
-	freqs.cpu = 0;
 	freqs.old = gx_get_cpuspeed(0);
 
 	new_khz = gx_validate_speed(khz, &gx_params->on_duration,
@@ -266,11 +265,9 @@ static void gx_set_cpuspeed(unsigned int khz)
 
 	freqs.new = new_khz;
 
-	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
 	local_irq_save(flags);
 
-
-
 	if (new_khz != stock_freq) {
 		/* if new khz == 100% of CPU speed, it is special case */
 		switch (gx_params->cs55x0->device) {
@@ -317,7 +314,7 @@ static void gx_set_cpuspeed(unsigned int khz)
 
 	gx_params->pci_suscfg = suscfg;
 
-	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
 
 	pr_debug("suspend modulation w/ duration of ON:%d us, OFF:%d us\n",
 		gx_params->on_duration * 32, gx_params->off_duration * 32);
@@ -397,7 +394,7 @@ static int cpufreq_gx_target(struct cpufreq_policy *policy,
 		tmp_freq = gx_validate_speed(tmp_freq, &tmp1, &tmp2);
 	}
 
-	gx_set_cpuspeed(tmp_freq);
+	gx_set_cpuspeed(policy, tmp_freq);
 
 	return 0;
 }
diff --git a/drivers/cpufreq/highbank-cpufreq.c b/drivers/cpufreq/highbank-cpufreq.c
index b61b5a3..3118b87 100644
--- a/drivers/cpufreq/highbank-cpufreq.c
+++ b/drivers/cpufreq/highbank-cpufreq.c
@@ -19,7 +19,7 @@
 #include <linux/cpu.h>
 #include <linux/err.h>
 #include <linux/of.h>
-#include <linux/mailbox.h>
+#include <linux/pl320-ipc.h>
 #include <linux/platform_device.h>
 
 #define HB_CPUFREQ_CHANGE_NOTE	0x80000001
diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c
index 54e336d..b78bc35 100644
--- a/drivers/cpufreq/imx6q-cpufreq.c
+++ b/drivers/cpufreq/imx6q-cpufreq.c
@@ -50,7 +50,7 @@ static int imx6q_set_target(struct cpufreq_policy *policy,
 	struct cpufreq_freqs freqs;
 	struct opp *opp;
 	unsigned long freq_hz, volt, volt_old;
-	unsigned int index, cpu;
+	unsigned int index;
 	int ret;
 
 	ret = cpufreq_frequency_table_target(policy, freq_table, target_freq,
@@ -68,10 +68,7 @@ static int imx6q_set_target(struct cpufreq_policy *policy,
 	if (freqs.old == freqs.new)
 		return 0;
 
-	for_each_online_cpu(cpu) {
-		freqs.cpu = cpu;
-		cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
-	}
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
 
 	rcu_read_lock();
 	opp = opp_find_freq_ceil(cpu_dev, &freq_hz);
@@ -166,10 +163,7 @@ static int imx6q_set_target(struct cpufreq_policy *policy,
 		}
 	}
 
-	for_each_online_cpu(cpu) {
-		freqs.cpu = cpu;
-		cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
-	}
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
 
 	return 0;
 }
diff --git a/drivers/cpufreq/kirkwood-cpufreq.c b/drivers/cpufreq/kirkwood-cpufreq.c
index 0e83e3c..d36ea8d 100644
--- a/drivers/cpufreq/kirkwood-cpufreq.c
+++ b/drivers/cpufreq/kirkwood-cpufreq.c
@@ -55,7 +55,8 @@ static unsigned int kirkwood_cpufreq_get_cpu_frequency(unsigned int cpu)
 	return kirkwood_freq_table[0].frequency;
 }
 
-static void kirkwood_cpufreq_set_cpu_state(unsigned int index)
+static void kirkwood_cpufreq_set_cpu_state(struct cpufreq_policy *policy,
+		unsigned int index)
 {
 	struct cpufreq_freqs freqs;
 	unsigned int state = kirkwood_freq_table[index].index;
@@ -63,9 +64,8 @@ static void kirkwood_cpufreq_set_cpu_state(unsigned int index)
 
 	freqs.old = kirkwood_cpufreq_get_cpu_frequency(0);
 	freqs.new = kirkwood_freq_table[index].frequency;
-	freqs.cpu = 0; /* Kirkwood is UP */
 
-	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
 
 	dev_dbg(priv.dev, "Attempting to set frequency to %i KHz\n",
 		kirkwood_freq_table[index].frequency);
@@ -99,7 +99,7 @@ static void kirkwood_cpufreq_set_cpu_state(unsigned int index)
 
 		local_irq_enable();
 	}
-	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
 };
 
 static int kirkwood_cpufreq_verify(struct cpufreq_policy *policy)
@@ -117,7 +117,7 @@ static int kirkwood_cpufreq_target(struct cpufreq_policy *policy,
 				target_freq, relation, &index))
 		return -EINVAL;
 
-	kirkwood_cpufreq_set_cpu_state(index);
+	kirkwood_cpufreq_set_cpu_state(policy, index);
 
 	return 0;
 }
@@ -175,11 +175,9 @@ static int kirkwood_cpufreq_probe(struct platform_device *pdev)
 		dev_err(&pdev->dev, "Cannot get memory resource\n");
 		return -ENODEV;
 	}
-	priv.base = devm_request_and_ioremap(&pdev->dev, res);
-	if (!priv.base) {
-		dev_err(&pdev->dev, "Cannot ioremap\n");
-		return -EADDRNOTAVAIL;
-	}
+	priv.base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(priv.base))
+		return PTR_ERR(priv.base);
 
 	np = of_find_node_by_path("/cpus/cpu@0");
 	if (!np)
diff --git a/drivers/cpufreq/longhaul.c b/drivers/cpufreq/longhaul.c
index 1180d53..b448638 100644
--- a/drivers/cpufreq/longhaul.c
+++ b/drivers/cpufreq/longhaul.c
@@ -242,7 +242,8 @@ static void do_powersaver(int cx_address, unsigned int mults_index,
  * Sets a new clock ratio.
  */
 
-static void longhaul_setstate(unsigned int table_index)
+static void longhaul_setstate(struct cpufreq_policy *policy,
+		unsigned int table_index)
 {
 	unsigned int mults_index;
 	int speed, mult;
@@ -267,9 +268,8 @@ static void longhaul_setstate(unsigned int table_index)
 
 	freqs.old = calc_speed(longhaul_get_cpu_mult());
 	freqs.new = speed;
-	freqs.cpu = 0; /* longhaul.c is UP only driver */
 
-	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
 
 	pr_debug("Setting to FSB:%dMHz Mult:%d.%dx (%s)\n",
 			fsb, mult/10, mult%10, print_speed(speed/1000));
@@ -386,7 +386,7 @@ retry_loop:
 		}
 	}
 	/* Report true CPU frequency */
-	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
 
 	if (!bm_timeout)
 		printk(KERN_INFO PFX "Warning: Timeout while waiting for "
@@ -648,7 +648,7 @@ static int longhaul_target(struct cpufreq_policy *policy,
 		return 0;
 
 	if (!can_scale_voltage)
-		longhaul_setstate(table_index);
+		longhaul_setstate(policy, table_index);
 	else {
 		/* On test system voltage transitions exceeding single
 		 * step up or down were turning motherboard off. Both
@@ -663,7 +663,7 @@ static int longhaul_target(struct cpufreq_policy *policy,
 		while (i != table_index) {
 			vid = (longhaul_table[i].index >> 8) & 0x1f;
 			if (vid != current_vid) {
-				longhaul_setstate(i);
+				longhaul_setstate(policy, i);
 				current_vid = vid;
 				msleep(200);
 			}
@@ -672,7 +672,7 @@ static int longhaul_target(struct cpufreq_policy *policy,
 			else
 				i--;
 		}
-		longhaul_setstate(table_index);
+		longhaul_setstate(policy, table_index);
 	}
 	longhaul_index = table_index;
 	return 0;
@@ -998,15 +998,17 @@ static int __init longhaul_init(void)
 
 static void __exit longhaul_exit(void)
 {
+	struct cpufreq_policy *policy = cpufreq_cpu_get(0);
 	int i;
 
 	for (i = 0; i < numscales; i++) {
 		if (mults[i] == maxmult) {
-			longhaul_setstate(i);
+			longhaul_setstate(policy, i);
 			break;
 		}
 	}
 
+	cpufreq_cpu_put(policy);
 	cpufreq_unregister_driver(&longhaul_driver);
 	kfree(longhaul_table);
 }
diff --git a/drivers/cpufreq/maple-cpufreq.c b/drivers/cpufreq/maple-cpufreq.c
index d4c4989..cdd6291 100644
--- a/drivers/cpufreq/maple-cpufreq.c
+++ b/drivers/cpufreq/maple-cpufreq.c
@@ -158,11 +158,10 @@ static int maple_cpufreq_target(struct cpufreq_policy *policy,
 
 	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);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
 	rc = maple_scom_switch_freq(newstate);
-	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
 
 	mutex_unlock(&maple_switch_mutex);
 
diff --git a/drivers/cpufreq/omap-cpufreq.c b/drivers/cpufreq/omap-cpufreq.c
index 9128c07..ad7549c 100644
--- a/drivers/cpufreq/omap-cpufreq.c
+++ b/drivers/cpufreq/omap-cpufreq.c
@@ -88,16 +88,12 @@ static int omap_target(struct cpufreq_policy *policy,
 	}
 
 	freqs.old = omap_getspeed(policy->cpu);
-	freqs.cpu = policy->cpu;
 
 	if (freqs.old == freqs.new && policy->cur == freqs.new)
 		return ret;
 
 	/* notifiers */
-	for_each_cpu(i, policy->cpus) {
-		freqs.cpu = i;
-		cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
-	}
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
 
 	freq = freqs.new * 1000;
 	ret = clk_round_rate(mpu_clk, freq);
@@ -157,10 +153,7 @@ static int omap_target(struct cpufreq_policy *policy,
 
 done:
 	/* notifiers */
-	for_each_cpu(i, policy->cpus) {
-		freqs.cpu = i;
-		cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
-	}
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
 
 	return ret;
 }
@@ -184,7 +177,7 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
 		goto fail_ck;
 	}
 
-	policy->cur = policy->min = policy->max = omap_getspeed(policy->cpu);
+	policy->cur = omap_getspeed(policy->cpu);
 
 	if (!freq_table)
 		result = opp_init_cpufreq_table(mpu_dev, &freq_table);
@@ -203,8 +196,6 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
 
 	cpufreq_frequency_table_get_attr(freq_table, policy->cpu);
 
-	policy->min = policy->cpuinfo.min_freq;
-	policy->max = policy->cpuinfo.max_freq;
 	policy->cur = omap_getspeed(policy->cpu);
 
 	/*
diff --git a/drivers/cpufreq/p4-clockmod.c b/drivers/cpufreq/p4-clockmod.c
index 827629c9..421ef37 100644
--- a/drivers/cpufreq/p4-clockmod.c
+++ b/drivers/cpufreq/p4-clockmod.c
@@ -58,8 +58,7 @@ static int cpufreq_p4_setdc(unsigned int cpu, unsigned int newstate)
 {
 	u32 l, h;
 
-	if (!cpu_online(cpu) ||
-	    (newstate > DC_DISABLE) || (newstate == DC_RESV))
+	if ((newstate > DC_DISABLE) || (newstate == DC_RESV))
 		return -EINVAL;
 
 	rdmsr_on_cpu(cpu, MSR_IA32_THERM_STATUS, &l, &h);
@@ -125,10 +124,7 @@ static int cpufreq_p4_target(struct cpufreq_policy *policy,
 		return 0;
 
 	/* notifiers */
-	for_each_cpu(i, policy->cpus) {
-		freqs.cpu = i;
-		cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
-	}
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
 
 	/* run on each logical CPU,
 	 * see section 13.15.3 of IA32 Intel Architecture Software
@@ -138,10 +134,7 @@ static int cpufreq_p4_target(struct cpufreq_policy *policy,
 		cpufreq_p4_setdc(i, p4clockmod_table[newstate].index);
 
 	/* notifiers */
-	for_each_cpu(i, policy->cpus) {
-		freqs.cpu = i;
-		cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
-	}
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
 
 	return 0;
 }
diff --git a/drivers/cpufreq/pcc-cpufreq.c b/drivers/cpufreq/pcc-cpufreq.c
index 503996a..0de0008 100644
--- a/drivers/cpufreq/pcc-cpufreq.c
+++ b/drivers/cpufreq/pcc-cpufreq.c
@@ -215,8 +215,7 @@ static int pcc_cpufreq_target(struct cpufreq_policy *policy,
 		(pcch_virt_addr + pcc_cpu_data->input_offset));
 
 	freqs.new = target_freq;
-	freqs.cpu = cpu;
-	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
 
 	input_buffer = 0x1 | (((target_freq * 100)
 			       / (ioread32(&pcch_hdr->nominal) * 1000)) << 8);
@@ -237,7 +236,7 @@ static int pcc_cpufreq_target(struct cpufreq_policy *policy,
 	}
 	iowrite16(0, &pcch_hdr->status);
 
-	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
 	pr_debug("target: was SUCCESSFUL for cpu %d\n", cpu);
 	spin_unlock(&pcc_lock);
 
diff --git a/drivers/cpufreq/powernow-k6.c b/drivers/cpufreq/powernow-k6.c
index af23e0b..ea0222a 100644
--- a/drivers/cpufreq/powernow-k6.c
+++ b/drivers/cpufreq/powernow-k6.c
@@ -68,7 +68,8 @@ static int powernow_k6_get_cpu_multiplier(void)
  *
  *   Tries to change the PowerNow! multiplier
  */
-static void powernow_k6_set_state(unsigned int best_i)
+static void powernow_k6_set_state(struct cpufreq_policy *policy,
+		unsigned int best_i)
 {
 	unsigned long outvalue = 0, invalue = 0;
 	unsigned long msrval;
@@ -81,9 +82,8 @@ static void powernow_k6_set_state(unsigned int best_i)
 
 	freqs.old = busfreq * powernow_k6_get_cpu_multiplier();
 	freqs.new = busfreq * clock_ratio[best_i].index;
-	freqs.cpu = 0; /* powernow-k6.c is UP only driver */
 
-	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
 
 	/* we now need to transform best_i to the BVC format, see AMD#23446 */
 
@@ -98,7 +98,7 @@ static void powernow_k6_set_state(unsigned int best_i)
 	msrval = POWERNOW_IOPORT + 0x0;
 	wrmsr(MSR_K6_EPMR, msrval, 0); /* disable it again */
 
-	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
 
 	return;
 }
@@ -136,7 +136,7 @@ static int powernow_k6_target(struct cpufreq_policy *policy,
 				target_freq, relation, &newstate))
 		return -EINVAL;
 
-	powernow_k6_set_state(newstate);
+	powernow_k6_set_state(policy, newstate);
 
 	return 0;
 }
@@ -182,7 +182,7 @@ static int powernow_k6_cpu_exit(struct cpufreq_policy *policy)
 	unsigned int i;
 	for (i = 0; i < 8; i++) {
 		if (i == max_multiplier)
-			powernow_k6_set_state(i);
+			powernow_k6_set_state(policy, i);
 	}
 	cpufreq_frequency_table_put_attr(policy->cpu);
 	return 0;
diff --git a/drivers/cpufreq/powernow-k7.c b/drivers/cpufreq/powernow-k7.c
index 334cc2f..53888da 100644
--- a/drivers/cpufreq/powernow-k7.c
+++ b/drivers/cpufreq/powernow-k7.c
@@ -248,7 +248,7 @@ static void change_VID(int vid)
 }
 
 
-static void change_speed(unsigned int index)
+static void change_speed(struct cpufreq_policy *policy, unsigned int index)
 {
 	u8 fid, vid;
 	struct cpufreq_freqs freqs;
@@ -263,15 +263,13 @@ static void change_speed(unsigned int index)
 	fid = powernow_table[index].index & 0xFF;
 	vid = (powernow_table[index].index & 0xFF00) >> 8;
 
-	freqs.cpu = 0;
-
 	rdmsrl(MSR_K7_FID_VID_STATUS, fidvidstatus.val);
 	cfid = fidvidstatus.bits.CFID;
 	freqs.old = fsb * fid_codes[cfid] / 10;
 
 	freqs.new = powernow_table[index].frequency;
 
-	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
 
 	/* Now do the magic poking into the MSRs.  */
 
@@ -292,7 +290,7 @@ static void change_speed(unsigned int index)
 	if (have_a0 == 1)
 		local_irq_enable();
 
-	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
 }
 
 
@@ -546,7 +544,7 @@ static int powernow_target(struct cpufreq_policy *policy,
 				relation, &newstate))
 		return -EINVAL;
 
-	change_speed(newstate);
+	change_speed(policy, newstate);
 
 	return 0;
 }
diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c
index d13a136..b828efe 100644
--- a/drivers/cpufreq/powernow-k8.c
+++ b/drivers/cpufreq/powernow-k8.c
@@ -928,9 +928,10 @@ static int get_transition_latency(struct powernow_k8_data *data)
 static int transition_frequency_fidvid(struct powernow_k8_data *data,
 		unsigned int index)
 {
+	struct cpufreq_policy *policy;
 	u32 fid = 0;
 	u32 vid = 0;
-	int res, i;
+	int res;
 	struct cpufreq_freqs freqs;
 
 	pr_debug("cpu %d transition to index %u\n", smp_processor_id(), index);
@@ -959,10 +960,10 @@ static int transition_frequency_fidvid(struct powernow_k8_data *data,
 	freqs.old = find_khz_freq_from_fid(data->currfid);
 	freqs.new = find_khz_freq_from_fid(fid);
 
-	for_each_cpu(i, data->available_cores) {
-		freqs.cpu = i;
-		cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
-	}
+	policy = cpufreq_cpu_get(smp_processor_id());
+	cpufreq_cpu_put(policy);
+
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
 
 	res = transition_fid_vid(data, fid, vid);
 	if (res)
@@ -970,10 +971,7 @@ static int transition_frequency_fidvid(struct powernow_k8_data *data,
 
 	freqs.new = find_khz_freq_from_fid(data->currfid);
 
-	for_each_cpu(i, data->available_cores) {
-		freqs.cpu = i;
-		cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
-	}
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
 	return res;
 }
 
@@ -1104,9 +1102,6 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
 	struct init_on_cpu init_on_cpu;
 	int rc;
 
-	if (!cpu_online(pol->cpu))
-		return -ENODEV;
-
 	smp_call_function_single(pol->cpu, check_supported_cpu, &rc, 1);
 	if (rc)
 		return -ENODEV;
diff --git a/drivers/cpufreq/s3c2416-cpufreq.c b/drivers/cpufreq/s3c2416-cpufreq.c
index bcc053b..4f1881e 100644
--- a/drivers/cpufreq/s3c2416-cpufreq.c
+++ b/drivers/cpufreq/s3c2416-cpufreq.c
@@ -256,7 +256,6 @@ static int s3c2416_cpufreq_set_target(struct cpufreq_policy *policy,
 		goto out;
 	}
 
-	freqs.cpu = 0;
 	freqs.flags = 0;
 	freqs.old = s3c_freq->is_dvs ? FREQ_DVS
 				     : clk_get_rate(s3c_freq->armclk) / 1000;
@@ -274,7 +273,7 @@ static int s3c2416_cpufreq_set_target(struct cpufreq_policy *policy,
 	if (!to_dvs && freqs.old == freqs.new)
 		goto out;
 
-	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
 
 	if (to_dvs) {
 		pr_debug("cpufreq: enter dvs\n");
@@ -287,7 +286,7 @@ static int s3c2416_cpufreq_set_target(struct cpufreq_policy *policy,
 		ret = s3c2416_cpufreq_set_armdiv(s3c_freq, freqs.new);
 	}
 
-	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
 
 out:
 	mutex_unlock(&cpufreq_lock);
diff --git a/drivers/cpufreq/s3c64xx-cpufreq.c b/drivers/cpufreq/s3c64xx-cpufreq.c
index 6f9490b..27cacb5 100644
--- a/drivers/cpufreq/s3c64xx-cpufreq.c
+++ b/drivers/cpufreq/s3c64xx-cpufreq.c
@@ -84,7 +84,6 @@ static int s3c64xx_cpufreq_set_target(struct cpufreq_policy *policy,
 	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;
@@ -95,7 +94,7 @@ static int s3c64xx_cpufreq_set_target(struct cpufreq_policy *policy,
 
 	pr_debug("Transition %d-%dkHz\n", freqs.old, freqs.new);
 
-	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
 
 #ifdef CONFIG_REGULATOR
 	if (vddarm && freqs.new > freqs.old) {
@@ -117,7 +116,7 @@ static int s3c64xx_cpufreq_set_target(struct cpufreq_policy *policy,
 		goto err;
 	}
 
-	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
 
 #ifdef CONFIG_REGULATOR
 	if (vddarm && freqs.new < freqs.old) {
@@ -141,7 +140,7 @@ 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);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
 
 	return ret;
 }
diff --git a/drivers/cpufreq/s5pv210-cpufreq.c b/drivers/cpufreq/s5pv210-cpufreq.c
index a484aae..5c77570 100644
--- a/drivers/cpufreq/s5pv210-cpufreq.c
+++ b/drivers/cpufreq/s5pv210-cpufreq.c
@@ -229,7 +229,6 @@ static int s5pv210_target(struct cpufreq_policy *policy,
 	}
 
 	freqs.new = s5pv210_freq_table[index].frequency;
-	freqs.cpu = 0;
 
 	if (freqs.new == freqs.old)
 		goto exit;
@@ -256,7 +255,7 @@ static int s5pv210_target(struct cpufreq_policy *policy,
 			goto exit;
 	}
 
-	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
 
 	/* Check if there need to change PLL */
 	if ((index == L0) || (priv_index == L0))
@@ -468,7 +467,7 @@ static int s5pv210_target(struct cpufreq_policy *policy,
 		}
 	}
 
-	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
 
 	if (freqs.new < freqs.old) {
 		regulator_set_voltage(int_regulator,
diff --git a/drivers/cpufreq/sc520_freq.c b/drivers/cpufreq/sc520_freq.c
index e42e073..f740b13 100644
--- a/drivers/cpufreq/sc520_freq.c
+++ b/drivers/cpufreq/sc520_freq.c
@@ -53,7 +53,8 @@ static unsigned int sc520_freq_get_cpu_frequency(unsigned int cpu)
 	}
 }
 
-static void sc520_freq_set_cpu_state(unsigned int state)
+static void sc520_freq_set_cpu_state(struct cpufreq_policy *policy,
+		unsigned int state)
 {
 
 	struct cpufreq_freqs	freqs;
@@ -61,9 +62,8 @@ static void sc520_freq_set_cpu_state(unsigned int state)
 
 	freqs.old = sc520_freq_get_cpu_frequency(0);
 	freqs.new = sc520_freq_table[state].frequency;
-	freqs.cpu = 0; /* AMD Elan is UP */
 
-	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
 
 	pr_debug("attempting to set frequency to %i kHz\n",
 			sc520_freq_table[state].frequency);
@@ -75,7 +75,7 @@ static void sc520_freq_set_cpu_state(unsigned int state)
 
 	local_irq_enable();
 
-	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
 };
 
 static int sc520_freq_verify(struct cpufreq_policy *policy)
@@ -93,7 +93,7 @@ static int sc520_freq_target(struct cpufreq_policy *policy,
 				target_freq, relation, &newstate))
 		return -EINVAL;
 
-	sc520_freq_set_cpu_state(newstate);
+	sc520_freq_set_cpu_state(policy, newstate);
 
 	return 0;
 }
diff --git a/drivers/cpufreq/spear-cpufreq.c b/drivers/cpufreq/spear-cpufreq.c
index 7e4d773..156829f 100644
--- a/drivers/cpufreq/spear-cpufreq.c
+++ b/drivers/cpufreq/spear-cpufreq.c
@@ -121,7 +121,6 @@ static int spear_cpufreq_target(struct cpufreq_policy *policy,
 				target_freq, relation, &index))
 		return -EINVAL;
 
-	freqs.cpu = policy->cpu;
 	freqs.old = spear_cpufreq_get(0);
 
 	newfreq = spear_cpufreq.freq_tbl[index].frequency * 1000;
@@ -158,8 +157,7 @@ static int spear_cpufreq_target(struct cpufreq_policy *policy,
 	freqs.new = newfreq / 1000;
 	freqs.new /= mult;
 
-	for_each_cpu(freqs.cpu, policy->cpus)
-		cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
 
 	if (mult == 2)
 		ret = spear1340_set_cpu_rate(srcclk, newfreq);
@@ -172,8 +170,7 @@ static int spear_cpufreq_target(struct cpufreq_policy *policy,
 		freqs.new = clk_get_rate(spear_cpufreq.clk) / 1000;
 	}
 
-	for_each_cpu(freqs.cpu, policy->cpus)
-		cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
 	return ret;
 }
 
diff --git a/drivers/cpufreq/speedstep-centrino.c b/drivers/cpufreq/speedstep-centrino.c
index 3a953d5..618e6f4 100644
--- a/drivers/cpufreq/speedstep-centrino.c
+++ b/drivers/cpufreq/speedstep-centrino.c
@@ -457,7 +457,7 @@ static int centrino_target (struct cpufreq_policy *policy,
 	unsigned int	msr, oldmsr = 0, h = 0, cpu = policy->cpu;
 	struct cpufreq_freqs	freqs;
 	int			retval = 0;
-	unsigned int		j, k, first_cpu, tmp;
+	unsigned int		j, first_cpu, tmp;
 	cpumask_var_t covered_cpus;
 
 	if (unlikely(!zalloc_cpumask_var(&covered_cpus, GFP_KERNEL)))
@@ -481,10 +481,6 @@ static int centrino_target (struct cpufreq_policy *policy,
 	for_each_cpu(j, policy->cpus) {
 		int good_cpu;
 
-		/* cpufreq holds the hotplug lock, so we are safe here */
-		if (!cpu_online(j))
-			continue;
-
 		/*
 		 * Support for SMP systems.
 		 * Make sure we are running on CPU that wants to change freq
@@ -522,13 +518,8 @@ static int centrino_target (struct cpufreq_policy *policy,
 			pr_debug("target=%dkHz old=%d new=%d msr=%04x\n",
 				target_freq, freqs.old, freqs.new, msr);
 
-			for_each_cpu(k, policy->cpus) {
-				if (!cpu_online(k))
-					continue;
-				freqs.cpu = k;
-				cpufreq_notify_transition(&freqs,
+			cpufreq_notify_transition(policy, &freqs,
 					CPUFREQ_PRECHANGE);
-			}
 
 			first_cpu = 0;
 			/* all but 16 LSB are reserved, treat them with care */
@@ -544,12 +535,7 @@ static int centrino_target (struct cpufreq_policy *policy,
 		cpumask_set_cpu(j, covered_cpus);
 	}
 
-	for_each_cpu(k, policy->cpus) {
-		if (!cpu_online(k))
-			continue;
-		freqs.cpu = k;
-		cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
-	}
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
 
 	if (unlikely(retval)) {
 		/*
@@ -565,12 +551,8 @@ static int centrino_target (struct cpufreq_policy *policy,
 		tmp = freqs.new;
 		freqs.new = freqs.old;
 		freqs.old = tmp;
-		for_each_cpu(j, policy->cpus) {
-			if (!cpu_online(j))
-				continue;
-			cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
-			cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
-		}
+		cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
+		cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
 	}
 	retval = 0;
 
diff --git a/drivers/cpufreq/speedstep-ich.c b/drivers/cpufreq/speedstep-ich.c
index e29b59a..e2e5aa9 100644
--- a/drivers/cpufreq/speedstep-ich.c
+++ b/drivers/cpufreq/speedstep-ich.c
@@ -263,7 +263,6 @@ static int speedstep_target(struct cpufreq_policy *policy,
 {
 	unsigned int newstate = 0, policy_cpu;
 	struct cpufreq_freqs freqs;
-	int i;
 
 	if (cpufreq_frequency_table_target(policy, &speedstep_freqs[0],
 				target_freq, relation, &newstate))
@@ -272,7 +271,6 @@ static int speedstep_target(struct cpufreq_policy *policy,
 	policy_cpu = cpumask_any_and(policy->cpus, cpu_online_mask);
 	freqs.old = speedstep_get(policy_cpu);
 	freqs.new = speedstep_freqs[newstate].frequency;
-	freqs.cpu = policy->cpu;
 
 	pr_debug("transiting from %u to %u kHz\n", freqs.old, freqs.new);
 
@@ -280,18 +278,12 @@ static int speedstep_target(struct cpufreq_policy *policy,
 	if (freqs.old == freqs.new)
 		return 0;
 
-	for_each_cpu(i, policy->cpus) {
-		freqs.cpu = i;
-		cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
-	}
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
 
 	smp_call_function_single(policy_cpu, _speedstep_set_state, &newstate,
 				 true);
 
-	for_each_cpu(i, policy->cpus) {
-		freqs.cpu = i;
-		cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
-	}
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
 
 	return 0;
 }
diff --git a/drivers/cpufreq/speedstep-smi.c b/drivers/cpufreq/speedstep-smi.c
index 6a457fc..f5a6b70 100644
--- a/drivers/cpufreq/speedstep-smi.c
+++ b/drivers/cpufreq/speedstep-smi.c
@@ -252,14 +252,13 @@ static int speedstep_target(struct cpufreq_policy *policy,
 
 	freqs.old = speedstep_freqs[speedstep_get_state()].frequency;
 	freqs.new = speedstep_freqs[newstate].frequency;
-	freqs.cpu = 0; /* speedstep.c is UP only driver */
 
 	if (freqs.old == freqs.new)
 		return 0;
 
-	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
 	speedstep_set_state(newstate);
-	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
 
 	return 0;
 }
diff --git a/drivers/cpuidle/Kconfig b/drivers/cpuidle/Kconfig
index 071e2c3..c4cc27e 100644
--- a/drivers/cpuidle/Kconfig
+++ b/drivers/cpuidle/Kconfig
@@ -39,10 +39,4 @@ config CPU_IDLE_CALXEDA
 	help
 	  Select this to enable cpuidle on Calxeda processors.
 
-config CPU_IDLE_KIRKWOOD
-	bool "CPU Idle Driver for Kirkwood processors"
-	depends on ARCH_KIRKWOOD
-	help
-	  Select this to enable cpuidle on Kirkwood processors.
-
 endif
diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile
index 24c6e7d..0d8bd55 100644
--- a/drivers/cpuidle/Makefile
+++ b/drivers/cpuidle/Makefile
@@ -6,4 +6,4 @@ obj-y += cpuidle.o driver.o governor.o sysfs.o governors/
 obj-$(CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED) += coupled.o
 
 obj-$(CONFIG_CPU_IDLE_CALXEDA) += cpuidle-calxeda.o
-obj-$(CONFIG_CPU_IDLE_KIRKWOOD) += cpuidle-kirkwood.o
+obj-$(CONFIG_ARCH_KIRKWOOD) += cpuidle-kirkwood.o
diff --git a/drivers/cpuidle/cpuidle-kirkwood.c b/drivers/cpuidle/cpuidle-kirkwood.c
index 670aa1e..53aad73 100644
--- a/drivers/cpuidle/cpuidle-kirkwood.c
+++ b/drivers/cpuidle/cpuidle-kirkwood.c
@@ -66,9 +66,9 @@ static int kirkwood_cpuidle_probe(struct platform_device *pdev)
 	if (res == NULL)
 		return -EINVAL;
 
-	ddr_operation_base = devm_request_and_ioremap(&pdev->dev, res);
-	if (!ddr_operation_base)
-		return -EADDRNOTAVAIL;
+	ddr_operation_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(ddr_operation_base))
+		return PTR_ERR(ddr_operation_base);
 
 	device = &per_cpu(kirkwood_cpuidle_device, smp_processor_id());
 	device->state_count = KIRKWOOD_MAX_STATES;
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
index eba6929..c500370 100644
--- a/drivers/cpuidle/cpuidle.c
+++ b/drivers/cpuidle/cpuidle.c
@@ -8,6 +8,7 @@
  * This code is licenced under the GPL.
  */
 
+#include <linux/clockchips.h>
 #include <linux/kernel.h>
 #include <linux/mutex.h>
 #include <linux/sched.h>
@@ -146,12 +147,20 @@ int cpuidle_idle_call(void)
 
 	trace_cpu_idle_rcuidle(next_state, dev->cpu);
 
+	if (drv->states[next_state].flags & CPUIDLE_FLAG_TIMER_STOP)
+		clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER,
+				   &dev->cpu);
+
 	if (cpuidle_state_is_coupled(dev, drv, next_state))
 		entered_state = cpuidle_enter_state_coupled(dev, drv,
 							    next_state);
 	else
 		entered_state = cpuidle_enter_state(dev, drv, next_state);
 
+	if (drv->states[next_state].flags & CPUIDLE_FLAG_TIMER_STOP)
+		clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT,
+				   &dev->cpu);
+
 	trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, dev->cpu);
 
 	/* give the governor an opportunity to reflect on the outcome */
diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c
index 422c7b6..8dfaaae 100644
--- a/drivers/cpuidle/driver.c
+++ b/drivers/cpuidle/driver.c
@@ -11,6 +11,8 @@
 #include <linux/mutex.h>
 #include <linux/module.h>
 #include <linux/cpuidle.h>
+#include <linux/cpumask.h>
+#include <linux/clockchips.h>
 
 #include "cpuidle.h"
 
@@ -19,9 +21,28 @@ DEFINE_SPINLOCK(cpuidle_driver_lock);
 static void __cpuidle_set_cpu_driver(struct cpuidle_driver *drv, int cpu);
 static struct cpuidle_driver * __cpuidle_get_cpu_driver(int cpu);
 
-static void __cpuidle_driver_init(struct cpuidle_driver *drv)
+static void cpuidle_setup_broadcast_timer(void *arg)
 {
+	int cpu = smp_processor_id();
+	clockevents_notify((long)(arg), &cpu);
+}
+
+static void __cpuidle_driver_init(struct cpuidle_driver *drv, int cpu)
+{
+	int i;
+
 	drv->refcnt = 0;
+
+	for (i = drv->state_count - 1; i >= 0 ; i--) {
+
+		if (!(drv->states[i].flags & CPUIDLE_FLAG_TIMER_STOP))
+			continue;
+
+		drv->bctimer = 1;
+		on_each_cpu_mask(get_cpu_mask(cpu), cpuidle_setup_broadcast_timer,
+				 (void *)CLOCK_EVT_NOTIFY_BROADCAST_ON, 1);
+		break;
+	}
 }
 
 static int __cpuidle_register_driver(struct cpuidle_driver *drv, int cpu)
@@ -35,7 +56,7 @@ static int __cpuidle_register_driver(struct cpuidle_driver *drv, int cpu)
 	if (__cpuidle_get_cpu_driver(cpu))
 		return -EBUSY;
 
-	__cpuidle_driver_init(drv);
+	__cpuidle_driver_init(drv, cpu);
 
 	__cpuidle_set_cpu_driver(drv, cpu);
 
@@ -49,6 +70,12 @@ static void __cpuidle_unregister_driver(struct cpuidle_driver *drv, int cpu)
 
 	if (!WARN_ON(drv->refcnt > 0))
 		__cpuidle_set_cpu_driver(NULL, cpu);
+
+	if (drv->bctimer) {
+		drv->bctimer = 0;
+		on_each_cpu_mask(get_cpu_mask(cpu), cpuidle_setup_broadcast_timer,
+				 (void *)CLOCK_EVT_NOTIFY_BROADCAST_OFF, 1);
+	}
 }
 
 #ifdef CONFIG_CPU_IDLE_MULTIPLE_DRIVERS
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index 87ec4d0..dffb855 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -276,6 +276,16 @@ config CRYPTO_DEV_PICOXCELL
 
 	  Saying m here will build a module named pipcoxcell_crypto.
 
+config CRYPTO_DEV_SAHARA
+	tristate "Support for SAHARA crypto accelerator"
+	depends on ARCH_MXC && EXPERIMENTAL && OF
+	select CRYPTO_BLKCIPHER
+	select CRYPTO_AES
+	select CRYPTO_ECB
+	help
+	  This option enables support for the SAHARA HW crypto accelerator
+	  found in some Freescale i.MX chips.
+
 config CRYPTO_DEV_S5P
 	tristate "Support for Samsung S5PV210 crypto accelerator"
 	depends on ARCH_S5PV210
@@ -361,15 +371,17 @@ config CRYPTO_DEV_ATMEL_TDES
 	  will be called atmel-tdes.
 
 config CRYPTO_DEV_ATMEL_SHA
-	tristate "Support for Atmel SHA1/SHA256 hw accelerator"
+	tristate "Support for Atmel SHA hw accelerator"
 	depends on ARCH_AT91
 	select CRYPTO_SHA1
 	select CRYPTO_SHA256
+	select CRYPTO_SHA512
 	select CRYPTO_ALGAPI
 	help
-	  Some Atmel processors have SHA1/SHA256 hw accelerator.
+	  Some Atmel processors have SHA1/SHA224/SHA256/SHA384/SHA512
+	  hw accelerator.
 	  Select this if you want to use the Atmel module for
-	  SHA1/SHA256 algorithms.
+	  SHA1/SHA224/SHA256/SHA384/SHA512 algorithms.
 
 	  To compile this driver as a module, choose M here: the module
 	  will be called atmel-sha.
diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile
index 880a47b..38ce13d 100644
--- a/drivers/crypto/Makefile
+++ b/drivers/crypto/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_CRYPTO_DEV_PPC4XX) += amcc/
 obj-$(CONFIG_CRYPTO_DEV_OMAP_SHAM) += omap-sham.o
 obj-$(CONFIG_CRYPTO_DEV_OMAP_AES) += omap-aes.o
 obj-$(CONFIG_CRYPTO_DEV_PICOXCELL) += picoxcell_crypto.o
+obj-$(CONFIG_CRYPTO_DEV_SAHARA) += sahara.o
 obj-$(CONFIG_CRYPTO_DEV_S5P) += s5p-sss.o
 obj-$(CONFIG_CRYPTO_DEV_TEGRA_AES) += tegra-aes.o
 obj-$(CONFIG_CRYPTO_DEV_UX500) += ux500/
diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c
index 6f22ba5..c1efd91 100644
--- a/drivers/crypto/atmel-aes.c
+++ b/drivers/crypto/atmel-aes.c
@@ -38,7 +38,7 @@
 #include <crypto/aes.h>
 #include <crypto/hash.h>
 #include <crypto/internal/hash.h>
-#include <linux/platform_data/atmel-aes.h>
+#include <linux/platform_data/crypto-atmel.h>
 #include "atmel-aes-regs.h"
 
 #define CFB8_BLOCK_SIZE		1
@@ -47,7 +47,7 @@
 #define CFB64_BLOCK_SIZE	8
 
 /* AES flags */
-#define AES_FLAGS_MODE_MASK	0x01ff
+#define AES_FLAGS_MODE_MASK	0x03ff
 #define AES_FLAGS_ENCRYPT	BIT(0)
 #define AES_FLAGS_CBC		BIT(1)
 #define AES_FLAGS_CFB		BIT(2)
@@ -55,21 +55,26 @@
 #define AES_FLAGS_CFB16		BIT(4)
 #define AES_FLAGS_CFB32		BIT(5)
 #define AES_FLAGS_CFB64		BIT(6)
-#define AES_FLAGS_OFB		BIT(7)
-#define AES_FLAGS_CTR		BIT(8)
+#define AES_FLAGS_CFB128	BIT(7)
+#define AES_FLAGS_OFB		BIT(8)
+#define AES_FLAGS_CTR		BIT(9)
 
 #define AES_FLAGS_INIT		BIT(16)
 #define AES_FLAGS_DMA		BIT(17)
 #define AES_FLAGS_BUSY		BIT(18)
+#define AES_FLAGS_FAST		BIT(19)
 
-#define AES_FLAGS_DUALBUFF	BIT(24)
-
-#define ATMEL_AES_QUEUE_LENGTH	1
-#define ATMEL_AES_CACHE_SIZE	0
+#define ATMEL_AES_QUEUE_LENGTH	50
 
 #define ATMEL_AES_DMA_THRESHOLD		16
 
 
+struct atmel_aes_caps {
+	bool	has_dualbuff;
+	bool	has_cfb64;
+	u32		max_burst_size;
+};
+
 struct atmel_aes_dev;
 
 struct atmel_aes_ctx {
@@ -77,6 +82,8 @@ struct atmel_aes_ctx {
 
 	int		keylen;
 	u32		key[AES_KEYSIZE_256 / sizeof(u32)];
+
+	u16		block_size;
 };
 
 struct atmel_aes_reqctx {
@@ -112,20 +119,27 @@ struct atmel_aes_dev {
 
 	struct scatterlist	*in_sg;
 	unsigned int		nb_in_sg;
-
+	size_t				in_offset;
 	struct scatterlist	*out_sg;
 	unsigned int		nb_out_sg;
+	size_t				out_offset;
 
 	size_t	bufcnt;
+	size_t	buflen;
+	size_t	dma_size;
 
-	u8	buf_in[ATMEL_AES_DMA_THRESHOLD] __aligned(sizeof(u32));
-	int	dma_in;
+	void	*buf_in;
+	int		dma_in;
+	dma_addr_t	dma_addr_in;
 	struct atmel_aes_dma	dma_lch_in;
 
-	u8	buf_out[ATMEL_AES_DMA_THRESHOLD] __aligned(sizeof(u32));
-	int	dma_out;
+	void	*buf_out;
+	int		dma_out;
+	dma_addr_t	dma_addr_out;
 	struct atmel_aes_dma	dma_lch_out;
 
+	struct atmel_aes_caps	caps;
+
 	u32	hw_version;
 };
 
@@ -165,6 +179,37 @@ static int atmel_aes_sg_length(struct ablkcipher_request *req,
 	return sg_nb;
 }
 
+static int atmel_aes_sg_copy(struct scatterlist **sg, size_t *offset,
+			void *buf, size_t buflen, size_t total, int out)
+{
+	unsigned int count, off = 0;
+
+	while (buflen && total) {
+		count = min((*sg)->length - *offset, total);
+		count = min(count, buflen);
+
+		if (!count)
+			return off;
+
+		scatterwalk_map_and_copy(buf + off, *sg, *offset, count, out);
+
+		off += count;
+		buflen -= count;
+		*offset += count;
+		total -= count;
+
+		if (*offset == (*sg)->length) {
+			*sg = sg_next(*sg);
+			if (*sg)
+				*offset = 0;
+			else
+				total = 0;
+		}
+	}
+
+	return off;
+}
+
 static inline u32 atmel_aes_read(struct atmel_aes_dev *dd, u32 offset)
 {
 	return readl_relaxed(dd->io_base + offset);
@@ -190,14 +235,6 @@ static void atmel_aes_write_n(struct atmel_aes_dev *dd, u32 offset,
 		atmel_aes_write(dd, offset, *value);
 }
 
-static void atmel_aes_dualbuff_test(struct atmel_aes_dev *dd)
-{
-	atmel_aes_write(dd, AES_MR, AES_MR_DUALBUFF);
-
-	if (atmel_aes_read(dd, AES_MR) & AES_MR_DUALBUFF)
-		dd->flags |= AES_FLAGS_DUALBUFF;
-}
-
 static struct atmel_aes_dev *atmel_aes_find_dev(struct atmel_aes_ctx *ctx)
 {
 	struct atmel_aes_dev *aes_dd = NULL;
@@ -225,7 +262,7 @@ static int atmel_aes_hw_init(struct atmel_aes_dev *dd)
 
 	if (!(dd->flags & AES_FLAGS_INIT)) {
 		atmel_aes_write(dd, AES_CR, AES_CR_SWRST);
-		atmel_aes_dualbuff_test(dd);
+		atmel_aes_write(dd, AES_MR, 0xE << AES_MR_CKEY_OFFSET);
 		dd->flags |= AES_FLAGS_INIT;
 		dd->err = 0;
 	}
@@ -233,11 +270,19 @@ static int atmel_aes_hw_init(struct atmel_aes_dev *dd)
 	return 0;
 }
 
+static inline unsigned int atmel_aes_get_version(struct atmel_aes_dev *dd)
+{
+	return atmel_aes_read(dd, AES_HW_VERSION) & 0x00000fff;
+}
+
 static void atmel_aes_hw_version_init(struct atmel_aes_dev *dd)
 {
 	atmel_aes_hw_init(dd);
 
-	dd->hw_version = atmel_aes_read(dd, AES_HW_VERSION);
+	dd->hw_version = atmel_aes_get_version(dd);
+
+	dev_info(dd->dev,
+			"version: 0x%x\n", dd->hw_version);
 
 	clk_disable_unprepare(dd->iclk);
 }
@@ -260,50 +305,77 @@ static void atmel_aes_dma_callback(void *data)
 	tasklet_schedule(&dd->done_task);
 }
 
-static int atmel_aes_crypt_dma(struct atmel_aes_dev *dd)
+static int atmel_aes_crypt_dma(struct atmel_aes_dev *dd,
+		dma_addr_t dma_addr_in, dma_addr_t dma_addr_out, int length)
 {
+	struct scatterlist sg[2];
 	struct dma_async_tx_descriptor	*in_desc, *out_desc;
-	int nb_dma_sg_in, nb_dma_sg_out;
 
-	dd->nb_in_sg = atmel_aes_sg_length(dd->req, dd->in_sg);
-	if (!dd->nb_in_sg)
-		goto exit_err;
+	dd->dma_size = length;
 
-	nb_dma_sg_in = dma_map_sg(dd->dev, dd->in_sg, dd->nb_in_sg,
-			DMA_TO_DEVICE);
-	if (!nb_dma_sg_in)
-		goto exit_err;
+	if (!(dd->flags & AES_FLAGS_FAST)) {
+		dma_sync_single_for_device(dd->dev, dma_addr_in, length,
+					   DMA_TO_DEVICE);
+	}
 
-	in_desc = dmaengine_prep_slave_sg(dd->dma_lch_in.chan, dd->in_sg,
-				nb_dma_sg_in, DMA_MEM_TO_DEV,
-				DMA_PREP_INTERRUPT  |  DMA_CTRL_ACK);
+	if (dd->flags & AES_FLAGS_CFB8) {
+		dd->dma_lch_in.dma_conf.dst_addr_width =
+			DMA_SLAVE_BUSWIDTH_1_BYTE;
+		dd->dma_lch_out.dma_conf.src_addr_width =
+			DMA_SLAVE_BUSWIDTH_1_BYTE;
+	} else if (dd->flags & AES_FLAGS_CFB16) {
+		dd->dma_lch_in.dma_conf.dst_addr_width =
+			DMA_SLAVE_BUSWIDTH_2_BYTES;
+		dd->dma_lch_out.dma_conf.src_addr_width =
+			DMA_SLAVE_BUSWIDTH_2_BYTES;
+	} else {
+		dd->dma_lch_in.dma_conf.dst_addr_width =
+			DMA_SLAVE_BUSWIDTH_4_BYTES;
+		dd->dma_lch_out.dma_conf.src_addr_width =
+			DMA_SLAVE_BUSWIDTH_4_BYTES;
+	}
 
-	if (!in_desc)
-		goto unmap_in;
+	if (dd->flags & (AES_FLAGS_CFB8 | AES_FLAGS_CFB16 |
+			AES_FLAGS_CFB32 | AES_FLAGS_CFB64)) {
+		dd->dma_lch_in.dma_conf.src_maxburst = 1;
+		dd->dma_lch_in.dma_conf.dst_maxburst = 1;
+		dd->dma_lch_out.dma_conf.src_maxburst = 1;
+		dd->dma_lch_out.dma_conf.dst_maxburst = 1;
+	} else {
+		dd->dma_lch_in.dma_conf.src_maxburst = dd->caps.max_burst_size;
+		dd->dma_lch_in.dma_conf.dst_maxburst = dd->caps.max_burst_size;
+		dd->dma_lch_out.dma_conf.src_maxburst = dd->caps.max_burst_size;
+		dd->dma_lch_out.dma_conf.dst_maxburst = dd->caps.max_burst_size;
+	}
 
-	/* callback not needed */
+	dmaengine_slave_config(dd->dma_lch_in.chan, &dd->dma_lch_in.dma_conf);
+	dmaengine_slave_config(dd->dma_lch_out.chan, &dd->dma_lch_out.dma_conf);
 
-	dd->nb_out_sg = atmel_aes_sg_length(dd->req, dd->out_sg);
-	if (!dd->nb_out_sg)
-		goto unmap_in;
+	dd->flags |= AES_FLAGS_DMA;
 
-	nb_dma_sg_out = dma_map_sg(dd->dev, dd->out_sg, dd->nb_out_sg,
-			DMA_FROM_DEVICE);
-	if (!nb_dma_sg_out)
-		goto unmap_out;
+	sg_init_table(&sg[0], 1);
+	sg_dma_address(&sg[0]) = dma_addr_in;
+	sg_dma_len(&sg[0]) = length;
 
-	out_desc = dmaengine_prep_slave_sg(dd->dma_lch_out.chan, dd->out_sg,
-				nb_dma_sg_out, DMA_DEV_TO_MEM,
-				DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	sg_init_table(&sg[1], 1);
+	sg_dma_address(&sg[1]) = dma_addr_out;
+	sg_dma_len(&sg[1]) = length;
+
+	in_desc = dmaengine_prep_slave_sg(dd->dma_lch_in.chan, &sg[0],
+				1, DMA_MEM_TO_DEV,
+				DMA_PREP_INTERRUPT  |  DMA_CTRL_ACK);
+	if (!in_desc)
+		return -EINVAL;
 
+	out_desc = dmaengine_prep_slave_sg(dd->dma_lch_out.chan, &sg[1],
+				1, DMA_DEV_TO_MEM,
+				DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
 	if (!out_desc)
-		goto unmap_out;
+		return -EINVAL;
 
 	out_desc->callback = atmel_aes_dma_callback;
 	out_desc->callback_param = dd;
 
-	dd->total -= dd->req->nbytes;
-
 	dmaengine_submit(out_desc);
 	dma_async_issue_pending(dd->dma_lch_out.chan);
 
@@ -311,15 +383,6 @@ static int atmel_aes_crypt_dma(struct atmel_aes_dev *dd)
 	dma_async_issue_pending(dd->dma_lch_in.chan);
 
 	return 0;
-
-unmap_out:
-	dma_unmap_sg(dd->dev, dd->out_sg, dd->nb_out_sg,
-		DMA_FROM_DEVICE);
-unmap_in:
-	dma_unmap_sg(dd->dev, dd->in_sg, dd->nb_in_sg,
-		DMA_TO_DEVICE);
-exit_err:
-	return -EINVAL;
 }
 
 static int atmel_aes_crypt_cpu_start(struct atmel_aes_dev *dd)
@@ -352,30 +415,66 @@ static int atmel_aes_crypt_cpu_start(struct atmel_aes_dev *dd)
 
 static int atmel_aes_crypt_dma_start(struct atmel_aes_dev *dd)
 {
-	int err;
+	int err, fast = 0, in, out;
+	size_t count;
+	dma_addr_t addr_in, addr_out;
+
+	if ((!dd->in_offset) && (!dd->out_offset)) {
+		/* check for alignment */
+		in = IS_ALIGNED((u32)dd->in_sg->offset, sizeof(u32)) &&
+			IS_ALIGNED(dd->in_sg->length, dd->ctx->block_size);
+		out = IS_ALIGNED((u32)dd->out_sg->offset, sizeof(u32)) &&
+			IS_ALIGNED(dd->out_sg->length, dd->ctx->block_size);
+		fast = in && out;
+
+		if (sg_dma_len(dd->in_sg) != sg_dma_len(dd->out_sg))
+			fast = 0;
+	}
+
+
+	if (fast)  {
+		count = min(dd->total, sg_dma_len(dd->in_sg));
+		count = min(count, sg_dma_len(dd->out_sg));
+
+		err = dma_map_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE);
+		if (!err) {
+			dev_err(dd->dev, "dma_map_sg() error\n");
+			return -EINVAL;
+		}
+
+		err = dma_map_sg(dd->dev, dd->out_sg, 1,
+				DMA_FROM_DEVICE);
+		if (!err) {
+			dev_err(dd->dev, "dma_map_sg() error\n");
+			dma_unmap_sg(dd->dev, dd->in_sg, 1,
+				DMA_TO_DEVICE);
+			return -EINVAL;
+		}
+
+		addr_in = sg_dma_address(dd->in_sg);
+		addr_out = sg_dma_address(dd->out_sg);
+
+		dd->flags |= AES_FLAGS_FAST;
 
-	if (dd->flags & AES_FLAGS_CFB8) {
-		dd->dma_lch_in.dma_conf.dst_addr_width =
-			DMA_SLAVE_BUSWIDTH_1_BYTE;
-		dd->dma_lch_out.dma_conf.src_addr_width =
-			DMA_SLAVE_BUSWIDTH_1_BYTE;
-	} else if (dd->flags & AES_FLAGS_CFB16) {
-		dd->dma_lch_in.dma_conf.dst_addr_width =
-			DMA_SLAVE_BUSWIDTH_2_BYTES;
-		dd->dma_lch_out.dma_conf.src_addr_width =
-			DMA_SLAVE_BUSWIDTH_2_BYTES;
 	} else {
-		dd->dma_lch_in.dma_conf.dst_addr_width =
-			DMA_SLAVE_BUSWIDTH_4_BYTES;
-		dd->dma_lch_out.dma_conf.src_addr_width =
-			DMA_SLAVE_BUSWIDTH_4_BYTES;
+		/* use cache buffers */
+		count = atmel_aes_sg_copy(&dd->in_sg, &dd->in_offset,
+				dd->buf_in, dd->buflen, dd->total, 0);
+
+		addr_in = dd->dma_addr_in;
+		addr_out = dd->dma_addr_out;
+
+		dd->flags &= ~AES_FLAGS_FAST;
 	}
 
-	dmaengine_slave_config(dd->dma_lch_in.chan, &dd->dma_lch_in.dma_conf);
-	dmaengine_slave_config(dd->dma_lch_out.chan, &dd->dma_lch_out.dma_conf);
+	dd->total -= count;
 
-	dd->flags |= AES_FLAGS_DMA;
-	err = atmel_aes_crypt_dma(dd);
+	err = atmel_aes_crypt_dma(dd, addr_in, addr_out, count);
+
+	if (err && (dd->flags & AES_FLAGS_FAST)) {
+		dma_unmap_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE);
+		dma_unmap_sg(dd->dev, dd->out_sg, 1, DMA_TO_DEVICE);
+	}
 
 	return err;
 }
@@ -410,6 +509,8 @@ static int atmel_aes_write_ctrl(struct atmel_aes_dev *dd)
 			valmr |= AES_MR_CFBS_32b;
 		else if (dd->flags & AES_FLAGS_CFB64)
 			valmr |= AES_MR_CFBS_64b;
+		else if (dd->flags & AES_FLAGS_CFB128)
+			valmr |= AES_MR_CFBS_128b;
 	} else if (dd->flags & AES_FLAGS_OFB) {
 		valmr |= AES_MR_OPMOD_OFB;
 	} else if (dd->flags & AES_FLAGS_CTR) {
@@ -423,7 +524,7 @@ static int atmel_aes_write_ctrl(struct atmel_aes_dev *dd)
 
 	if (dd->total > ATMEL_AES_DMA_THRESHOLD) {
 		valmr |= AES_MR_SMOD_IDATAR0;
-		if (dd->flags & AES_FLAGS_DUALBUFF)
+		if (dd->caps.has_dualbuff)
 			valmr |= AES_MR_DUALBUFF;
 	} else {
 		valmr |= AES_MR_SMOD_AUTO;
@@ -477,7 +578,9 @@ static int atmel_aes_handle_queue(struct atmel_aes_dev *dd,
 	/* assign new request to device */
 	dd->req = req;
 	dd->total = req->nbytes;
+	dd->in_offset = 0;
 	dd->in_sg = req->src;
+	dd->out_offset = 0;
 	dd->out_sg = req->dst;
 
 	rctx = ablkcipher_request_ctx(req);
@@ -506,18 +609,86 @@ static int atmel_aes_handle_queue(struct atmel_aes_dev *dd,
 static int atmel_aes_crypt_dma_stop(struct atmel_aes_dev *dd)
 {
 	int err = -EINVAL;
+	size_t count;
 
 	if (dd->flags & AES_FLAGS_DMA) {
-		dma_unmap_sg(dd->dev, dd->out_sg,
-			dd->nb_out_sg, DMA_FROM_DEVICE);
-		dma_unmap_sg(dd->dev, dd->in_sg,
-			dd->nb_in_sg, DMA_TO_DEVICE);
 		err = 0;
+		if  (dd->flags & AES_FLAGS_FAST) {
+			dma_unmap_sg(dd->dev, dd->out_sg, 1, DMA_FROM_DEVICE);
+			dma_unmap_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE);
+		} else {
+			dma_sync_single_for_device(dd->dev, dd->dma_addr_out,
+				dd->dma_size, DMA_FROM_DEVICE);
+
+			/* copy data */
+			count = atmel_aes_sg_copy(&dd->out_sg, &dd->out_offset,
+				dd->buf_out, dd->buflen, dd->dma_size, 1);
+			if (count != dd->dma_size) {
+				err = -EINVAL;
+				pr_err("not all data converted: %u\n", count);
+			}
+		}
 	}
 
 	return err;
 }
 
+
+static int atmel_aes_buff_init(struct atmel_aes_dev *dd)
+{
+	int err = -ENOMEM;
+
+	dd->buf_in = (void *)__get_free_pages(GFP_KERNEL, 0);
+	dd->buf_out = (void *)__get_free_pages(GFP_KERNEL, 0);
+	dd->buflen = PAGE_SIZE;
+	dd->buflen &= ~(AES_BLOCK_SIZE - 1);
+
+	if (!dd->buf_in || !dd->buf_out) {
+		dev_err(dd->dev, "unable to alloc pages.\n");
+		goto err_alloc;
+	}
+
+	/* MAP here */
+	dd->dma_addr_in = dma_map_single(dd->dev, dd->buf_in,
+					dd->buflen, DMA_TO_DEVICE);
+	if (dma_mapping_error(dd->dev, dd->dma_addr_in)) {
+		dev_err(dd->dev, "dma %d bytes error\n", dd->buflen);
+		err = -EINVAL;
+		goto err_map_in;
+	}
+
+	dd->dma_addr_out = dma_map_single(dd->dev, dd->buf_out,
+					dd->buflen, DMA_FROM_DEVICE);
+	if (dma_mapping_error(dd->dev, dd->dma_addr_out)) {
+		dev_err(dd->dev, "dma %d bytes error\n", dd->buflen);
+		err = -EINVAL;
+		goto err_map_out;
+	}
+
+	return 0;
+
+err_map_out:
+	dma_unmap_single(dd->dev, dd->dma_addr_in, dd->buflen,
+		DMA_TO_DEVICE);
+err_map_in:
+	free_page((unsigned long)dd->buf_out);
+	free_page((unsigned long)dd->buf_in);
+err_alloc:
+	if (err)
+		pr_err("error: %d\n", err);
+	return err;
+}
+
+static void atmel_aes_buff_cleanup(struct atmel_aes_dev *dd)
+{
+	dma_unmap_single(dd->dev, dd->dma_addr_out, dd->buflen,
+			 DMA_FROM_DEVICE);
+	dma_unmap_single(dd->dev, dd->dma_addr_in, dd->buflen,
+		DMA_TO_DEVICE);
+	free_page((unsigned long)dd->buf_out);
+	free_page((unsigned long)dd->buf_in);
+}
+
 static int atmel_aes_crypt(struct ablkcipher_request *req, unsigned long mode)
 {
 	struct atmel_aes_ctx *ctx = crypto_ablkcipher_ctx(
@@ -525,9 +696,30 @@ static int atmel_aes_crypt(struct ablkcipher_request *req, unsigned long mode)
 	struct atmel_aes_reqctx *rctx = ablkcipher_request_ctx(req);
 	struct atmel_aes_dev *dd;
 
-	if (!IS_ALIGNED(req->nbytes, AES_BLOCK_SIZE)) {
-		pr_err("request size is not exact amount of AES blocks\n");
-		return -EINVAL;
+	if (mode & AES_FLAGS_CFB8) {
+		if (!IS_ALIGNED(req->nbytes, CFB8_BLOCK_SIZE)) {
+			pr_err("request size is not exact amount of CFB8 blocks\n");
+			return -EINVAL;
+		}
+		ctx->block_size = CFB8_BLOCK_SIZE;
+	} else if (mode & AES_FLAGS_CFB16) {
+		if (!IS_ALIGNED(req->nbytes, CFB16_BLOCK_SIZE)) {
+			pr_err("request size is not exact amount of CFB16 blocks\n");
+			return -EINVAL;
+		}
+		ctx->block_size = CFB16_BLOCK_SIZE;
+	} else if (mode & AES_FLAGS_CFB32) {
+		if (!IS_ALIGNED(req->nbytes, CFB32_BLOCK_SIZE)) {
+			pr_err("request size is not exact amount of CFB32 blocks\n");
+			return -EINVAL;
+		}
+		ctx->block_size = CFB32_BLOCK_SIZE;
+	} else {
+		if (!IS_ALIGNED(req->nbytes, AES_BLOCK_SIZE)) {
+			pr_err("request size is not exact amount of AES blocks\n");
+			return -EINVAL;
+		}
+		ctx->block_size = AES_BLOCK_SIZE;
 	}
 
 	dd = atmel_aes_find_dev(ctx);
@@ -551,14 +743,12 @@ static bool atmel_aes_filter(struct dma_chan *chan, void *slave)
 	}
 }
 
-static int atmel_aes_dma_init(struct atmel_aes_dev *dd)
+static int atmel_aes_dma_init(struct atmel_aes_dev *dd,
+	struct crypto_platform_data *pdata)
 {
 	int err = -ENOMEM;
-	struct aes_platform_data	*pdata;
 	dma_cap_mask_t mask_in, mask_out;
 
-	pdata = dd->dev->platform_data;
-
 	if (pdata && pdata->dma_slave->txdata.dma_dev &&
 		pdata->dma_slave->rxdata.dma_dev) {
 
@@ -568,28 +758,38 @@ static int atmel_aes_dma_init(struct atmel_aes_dev *dd)
 
 		dd->dma_lch_in.chan = dma_request_channel(mask_in,
 				atmel_aes_filter, &pdata->dma_slave->rxdata);
+
 		if (!dd->dma_lch_in.chan)
 			goto err_dma_in;
 
 		dd->dma_lch_in.dma_conf.direction = DMA_MEM_TO_DEV;
 		dd->dma_lch_in.dma_conf.dst_addr = dd->phys_base +
 			AES_IDATAR(0);
-		dd->dma_lch_in.dma_conf.src_maxburst = 1;
-		dd->dma_lch_in.dma_conf.dst_maxburst = 1;
+		dd->dma_lch_in.dma_conf.src_maxburst = dd->caps.max_burst_size;
+		dd->dma_lch_in.dma_conf.src_addr_width =
+			DMA_SLAVE_BUSWIDTH_4_BYTES;
+		dd->dma_lch_in.dma_conf.dst_maxburst = dd->caps.max_burst_size;
+		dd->dma_lch_in.dma_conf.dst_addr_width =
+			DMA_SLAVE_BUSWIDTH_4_BYTES;
 		dd->dma_lch_in.dma_conf.device_fc = false;
 
 		dma_cap_zero(mask_out);
 		dma_cap_set(DMA_SLAVE, mask_out);
 		dd->dma_lch_out.chan = dma_request_channel(mask_out,
 				atmel_aes_filter, &pdata->dma_slave->txdata);
+
 		if (!dd->dma_lch_out.chan)
 			goto err_dma_out;
 
 		dd->dma_lch_out.dma_conf.direction = DMA_DEV_TO_MEM;
 		dd->dma_lch_out.dma_conf.src_addr = dd->phys_base +
 			AES_ODATAR(0);
-		dd->dma_lch_out.dma_conf.src_maxburst = 1;
-		dd->dma_lch_out.dma_conf.dst_maxburst = 1;
+		dd->dma_lch_out.dma_conf.src_maxburst = dd->caps.max_burst_size;
+		dd->dma_lch_out.dma_conf.src_addr_width =
+			DMA_SLAVE_BUSWIDTH_4_BYTES;
+		dd->dma_lch_out.dma_conf.dst_maxburst = dd->caps.max_burst_size;
+		dd->dma_lch_out.dma_conf.dst_addr_width =
+			DMA_SLAVE_BUSWIDTH_4_BYTES;
 		dd->dma_lch_out.dma_conf.device_fc = false;
 
 		return 0;
@@ -665,13 +865,13 @@ static int atmel_aes_ofb_decrypt(struct ablkcipher_request *req)
 static int atmel_aes_cfb_encrypt(struct ablkcipher_request *req)
 {
 	return atmel_aes_crypt(req,
-		AES_FLAGS_ENCRYPT | AES_FLAGS_CFB);
+		AES_FLAGS_ENCRYPT | AES_FLAGS_CFB | AES_FLAGS_CFB128);
 }
 
 static int atmel_aes_cfb_decrypt(struct ablkcipher_request *req)
 {
 	return atmel_aes_crypt(req,
-		AES_FLAGS_CFB);
+		AES_FLAGS_CFB | AES_FLAGS_CFB128);
 }
 
 static int atmel_aes_cfb64_encrypt(struct ablkcipher_request *req)
@@ -753,7 +953,7 @@ static struct crypto_alg aes_algs[] = {
 	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
 	.cra_blocksize		= AES_BLOCK_SIZE,
 	.cra_ctxsize		= sizeof(struct atmel_aes_ctx),
-	.cra_alignmask		= 0x0,
+	.cra_alignmask		= 0xf,
 	.cra_type		= &crypto_ablkcipher_type,
 	.cra_module		= THIS_MODULE,
 	.cra_init		= atmel_aes_cra_init,
@@ -773,7 +973,7 @@ static struct crypto_alg aes_algs[] = {
 	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
 	.cra_blocksize		= AES_BLOCK_SIZE,
 	.cra_ctxsize		= sizeof(struct atmel_aes_ctx),
-	.cra_alignmask		= 0x0,
+	.cra_alignmask		= 0xf,
 	.cra_type		= &crypto_ablkcipher_type,
 	.cra_module		= THIS_MODULE,
 	.cra_init		= atmel_aes_cra_init,
@@ -794,7 +994,7 @@ static struct crypto_alg aes_algs[] = {
 	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
 	.cra_blocksize		= AES_BLOCK_SIZE,
 	.cra_ctxsize		= sizeof(struct atmel_aes_ctx),
-	.cra_alignmask		= 0x0,
+	.cra_alignmask		= 0xf,
 	.cra_type		= &crypto_ablkcipher_type,
 	.cra_module		= THIS_MODULE,
 	.cra_init		= atmel_aes_cra_init,
@@ -815,7 +1015,7 @@ static struct crypto_alg aes_algs[] = {
 	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
 	.cra_blocksize		= AES_BLOCK_SIZE,
 	.cra_ctxsize		= sizeof(struct atmel_aes_ctx),
-	.cra_alignmask		= 0x0,
+	.cra_alignmask		= 0xf,
 	.cra_type		= &crypto_ablkcipher_type,
 	.cra_module		= THIS_MODULE,
 	.cra_init		= atmel_aes_cra_init,
@@ -836,7 +1036,7 @@ static struct crypto_alg aes_algs[] = {
 	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
 	.cra_blocksize		= CFB32_BLOCK_SIZE,
 	.cra_ctxsize		= sizeof(struct atmel_aes_ctx),
-	.cra_alignmask		= 0x0,
+	.cra_alignmask		= 0x3,
 	.cra_type		= &crypto_ablkcipher_type,
 	.cra_module		= THIS_MODULE,
 	.cra_init		= atmel_aes_cra_init,
@@ -857,7 +1057,7 @@ static struct crypto_alg aes_algs[] = {
 	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
 	.cra_blocksize		= CFB16_BLOCK_SIZE,
 	.cra_ctxsize		= sizeof(struct atmel_aes_ctx),
-	.cra_alignmask		= 0x0,
+	.cra_alignmask		= 0x1,
 	.cra_type		= &crypto_ablkcipher_type,
 	.cra_module		= THIS_MODULE,
 	.cra_init		= atmel_aes_cra_init,
@@ -899,7 +1099,7 @@ static struct crypto_alg aes_algs[] = {
 	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
 	.cra_blocksize		= AES_BLOCK_SIZE,
 	.cra_ctxsize		= sizeof(struct atmel_aes_ctx),
-	.cra_alignmask		= 0x0,
+	.cra_alignmask		= 0xf,
 	.cra_type		= &crypto_ablkcipher_type,
 	.cra_module		= THIS_MODULE,
 	.cra_init		= atmel_aes_cra_init,
@@ -915,15 +1115,14 @@ static struct crypto_alg aes_algs[] = {
 },
 };
 
-static struct crypto_alg aes_cfb64_alg[] = {
-{
+static struct crypto_alg aes_cfb64_alg = {
 	.cra_name		= "cfb64(aes)",
 	.cra_driver_name	= "atmel-cfb64-aes",
 	.cra_priority		= 100,
 	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
 	.cra_blocksize		= CFB64_BLOCK_SIZE,
 	.cra_ctxsize		= sizeof(struct atmel_aes_ctx),
-	.cra_alignmask		= 0x0,
+	.cra_alignmask		= 0x7,
 	.cra_type		= &crypto_ablkcipher_type,
 	.cra_module		= THIS_MODULE,
 	.cra_init		= atmel_aes_cra_init,
@@ -936,7 +1135,6 @@ static struct crypto_alg aes_cfb64_alg[] = {
 		.encrypt	= atmel_aes_cfb64_encrypt,
 		.decrypt	= atmel_aes_cfb64_decrypt,
 	}
-},
 };
 
 static void atmel_aes_queue_task(unsigned long data)
@@ -969,7 +1167,14 @@ static void atmel_aes_done_task(unsigned long data)
 	err = dd->err ? : err;
 
 	if (dd->total && !err) {
-		err = atmel_aes_crypt_dma_start(dd);
+		if (dd->flags & AES_FLAGS_FAST) {
+			dd->in_sg = sg_next(dd->in_sg);
+			dd->out_sg = sg_next(dd->out_sg);
+			if (!dd->in_sg || !dd->out_sg)
+				err = -EINVAL;
+		}
+		if (!err)
+			err = atmel_aes_crypt_dma_start(dd);
 		if (!err)
 			return; /* DMA started. Not fininishing. */
 	}
@@ -1003,8 +1208,8 @@ static void atmel_aes_unregister_algs(struct atmel_aes_dev *dd)
 
 	for (i = 0; i < ARRAY_SIZE(aes_algs); i++)
 		crypto_unregister_alg(&aes_algs[i]);
-	if (dd->hw_version >= 0x130)
-		crypto_unregister_alg(&aes_cfb64_alg[0]);
+	if (dd->caps.has_cfb64)
+		crypto_unregister_alg(&aes_cfb64_alg);
 }
 
 static int atmel_aes_register_algs(struct atmel_aes_dev *dd)
@@ -1017,10 +1222,8 @@ static int atmel_aes_register_algs(struct atmel_aes_dev *dd)
 			goto err_aes_algs;
 	}
 
-	atmel_aes_hw_version_init(dd);
-
-	if (dd->hw_version >= 0x130) {
-		err = crypto_register_alg(&aes_cfb64_alg[0]);
+	if (dd->caps.has_cfb64) {
+		err = crypto_register_alg(&aes_cfb64_alg);
 		if (err)
 			goto err_aes_cfb64_alg;
 	}
@@ -1036,10 +1239,32 @@ err_aes_algs:
 	return err;
 }
 
+static void atmel_aes_get_cap(struct atmel_aes_dev *dd)
+{
+	dd->caps.has_dualbuff = 0;
+	dd->caps.has_cfb64 = 0;
+	dd->caps.max_burst_size = 1;
+
+	/* keep only major version number */
+	switch (dd->hw_version & 0xff0) {
+	case 0x130:
+		dd->caps.has_dualbuff = 1;
+		dd->caps.has_cfb64 = 1;
+		dd->caps.max_burst_size = 4;
+		break;
+	case 0x120:
+		break;
+	default:
+		dev_warn(dd->dev,
+				"Unmanaged aes version, set minimum capabilities\n");
+		break;
+	}
+}
+
 static int atmel_aes_probe(struct platform_device *pdev)
 {
 	struct atmel_aes_dev *aes_dd;
-	struct aes_platform_data	*pdata;
+	struct crypto_platform_data *pdata;
 	struct device *dev = &pdev->dev;
 	struct resource *aes_res;
 	unsigned long aes_phys_size;
@@ -1099,7 +1324,7 @@ static int atmel_aes_probe(struct platform_device *pdev)
 	}
 
 	/* Initializing the clock */
-	aes_dd->iclk = clk_get(&pdev->dev, NULL);
+	aes_dd->iclk = clk_get(&pdev->dev, "aes_clk");
 	if (IS_ERR(aes_dd->iclk)) {
 		dev_err(dev, "clock intialization failed.\n");
 		err = PTR_ERR(aes_dd->iclk);
@@ -1113,7 +1338,15 @@ static int atmel_aes_probe(struct platform_device *pdev)
 		goto aes_io_err;
 	}
 
-	err = atmel_aes_dma_init(aes_dd);
+	atmel_aes_hw_version_init(aes_dd);
+
+	atmel_aes_get_cap(aes_dd);
+
+	err = atmel_aes_buff_init(aes_dd);
+	if (err)
+		goto err_aes_buff;
+
+	err = atmel_aes_dma_init(aes_dd, pdata);
 	if (err)
 		goto err_aes_dma;
 
@@ -1135,6 +1368,8 @@ err_algs:
 	spin_unlock(&atmel_aes.lock);
 	atmel_aes_dma_cleanup(aes_dd);
 err_aes_dma:
+	atmel_aes_buff_cleanup(aes_dd);
+err_aes_buff:
 	iounmap(aes_dd->io_base);
 aes_io_err:
 	clk_put(aes_dd->iclk);
diff --git a/drivers/crypto/atmel-sha-regs.h b/drivers/crypto/atmel-sha-regs.h
index dc53a20..83b2d74 100644
--- a/drivers/crypto/atmel-sha-regs.h
+++ b/drivers/crypto/atmel-sha-regs.h
@@ -14,10 +14,13 @@
 #define SHA_MR_MODE_MANUAL		0x0
 #define SHA_MR_MODE_AUTO		0x1
 #define SHA_MR_MODE_PDC			0x2
-#define	SHA_MR_DUALBUFF			(1 << 3)
 #define SHA_MR_PROCDLY			(1 << 4)
 #define SHA_MR_ALGO_SHA1		(0 << 8)
 #define SHA_MR_ALGO_SHA256		(1 << 8)
+#define SHA_MR_ALGO_SHA384		(2 << 8)
+#define SHA_MR_ALGO_SHA512		(3 << 8)
+#define SHA_MR_ALGO_SHA224		(4 << 8)
+#define	SHA_MR_DUALBUFF			(1 << 16)
 
 #define SHA_IER				0x10
 #define SHA_IDR				0x14
@@ -33,6 +36,8 @@
 #define SHA_ISR_URAT_MR			(0x2 << 12)
 #define SHA_ISR_URAT_WO			(0x5 << 12)
 
+#define	SHA_HW_VERSION		0xFC
+
 #define SHA_TPR				0x108
 #define SHA_TCR				0x10C
 #define SHA_TNPR			0x118
diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c
index 4918e94..eaed8bf 100644
--- a/drivers/crypto/atmel-sha.c
+++ b/drivers/crypto/atmel-sha.c
@@ -38,6 +38,7 @@
 #include <crypto/sha.h>
 #include <crypto/hash.h>
 #include <crypto/internal/hash.h>
+#include <linux/platform_data/crypto-atmel.h>
 #include "atmel-sha-regs.h"
 
 /* SHA flags */
@@ -52,11 +53,12 @@
 #define SHA_FLAGS_FINUP		BIT(16)
 #define SHA_FLAGS_SG		BIT(17)
 #define SHA_FLAGS_SHA1		BIT(18)
-#define SHA_FLAGS_SHA256	BIT(19)
-#define SHA_FLAGS_ERROR		BIT(20)
-#define SHA_FLAGS_PAD		BIT(21)
-
-#define SHA_FLAGS_DUALBUFF	BIT(24)
+#define SHA_FLAGS_SHA224	BIT(19)
+#define SHA_FLAGS_SHA256	BIT(20)
+#define SHA_FLAGS_SHA384	BIT(21)
+#define SHA_FLAGS_SHA512	BIT(22)
+#define SHA_FLAGS_ERROR		BIT(23)
+#define SHA_FLAGS_PAD		BIT(24)
 
 #define SHA_OP_UPDATE	1
 #define SHA_OP_FINAL	2
@@ -65,6 +67,12 @@
 
 #define ATMEL_SHA_DMA_THRESHOLD		56
 
+struct atmel_sha_caps {
+	bool	has_dma;
+	bool	has_dualbuff;
+	bool	has_sha224;
+	bool	has_sha_384_512;
+};
 
 struct atmel_sha_dev;
 
@@ -73,8 +81,8 @@ struct atmel_sha_reqctx {
 	unsigned long	flags;
 	unsigned long	op;
 
-	u8	digest[SHA256_DIGEST_SIZE] __aligned(sizeof(u32));
-	size_t	digcnt;
+	u8	digest[SHA512_DIGEST_SIZE] __aligned(sizeof(u32));
+	u64	digcnt[2];
 	size_t	bufcnt;
 	size_t	buflen;
 	dma_addr_t	dma_addr;
@@ -84,6 +92,8 @@ struct atmel_sha_reqctx {
 	unsigned int	offset;	/* offset in current sg */
 	unsigned int	total;	/* total request */
 
+	size_t block_size;
+
 	u8	buffer[0] __aligned(sizeof(u32));
 };
 
@@ -97,7 +107,12 @@ struct atmel_sha_ctx {
 
 };
 
-#define ATMEL_SHA_QUEUE_LENGTH	1
+#define ATMEL_SHA_QUEUE_LENGTH	50
+
+struct atmel_sha_dma {
+	struct dma_chan			*chan;
+	struct dma_slave_config dma_conf;
+};
 
 struct atmel_sha_dev {
 	struct list_head	list;
@@ -114,6 +129,12 @@ struct atmel_sha_dev {
 	unsigned long		flags;
 	struct crypto_queue	queue;
 	struct ahash_request	*req;
+
+	struct atmel_sha_dma	dma_lch_in;
+
+	struct atmel_sha_caps	caps;
+
+	u32	hw_version;
 };
 
 struct atmel_sha_drv {
@@ -137,14 +158,6 @@ static inline void atmel_sha_write(struct atmel_sha_dev *dd,
 	writel_relaxed(value, dd->io_base + offset);
 }
 
-static void atmel_sha_dualbuff_test(struct atmel_sha_dev *dd)
-{
-	atmel_sha_write(dd, SHA_MR, SHA_MR_DUALBUFF);
-
-	if (atmel_sha_read(dd, SHA_MR) & SHA_MR_DUALBUFF)
-		dd->flags |= SHA_FLAGS_DUALBUFF;
-}
-
 static size_t atmel_sha_append_sg(struct atmel_sha_reqctx *ctx)
 {
 	size_t count;
@@ -176,31 +189,58 @@ static size_t atmel_sha_append_sg(struct atmel_sha_reqctx *ctx)
 }
 
 /*
- * The purpose of this padding is to ensure that the padded message
- * is a multiple of 512 bits. The bit "1" is appended at the end of
- * the message followed by "padlen-1" zero bits. Then a 64 bits block
- * equals to the message length in bits is appended.
+ * The purpose of this padding is to ensure that the padded message is a
+ * multiple of 512 bits (SHA1/SHA224/SHA256) or 1024 bits (SHA384/SHA512).
+ * The bit "1" is appended at the end of the message followed by
+ * "padlen-1" zero bits. Then a 64 bits block (SHA1/SHA224/SHA256) or
+ * 128 bits block (SHA384/SHA512) equals to the message length in bits
+ * is appended.
  *
- * padlen is calculated as followed:
+ * For SHA1/SHA224/SHA256, padlen is calculated as followed:
  *  - if message length < 56 bytes then padlen = 56 - message length
  *  - else padlen = 64 + 56 - message length
+ *
+ * For SHA384/SHA512, padlen is calculated as followed:
+ *  - if message length < 112 bytes then padlen = 112 - message length
+ *  - else padlen = 128 + 112 - message length
  */
 static void atmel_sha_fill_padding(struct atmel_sha_reqctx *ctx, int length)
 {
 	unsigned int index, padlen;
-	u64 bits;
-	u64 size;
-
-	bits = (ctx->bufcnt + ctx->digcnt + length) << 3;
-	size = cpu_to_be64(bits);
-
-	index = ctx->bufcnt & 0x3f;
-	padlen = (index < 56) ? (56 - index) : ((64+56) - index);
-	*(ctx->buffer + ctx->bufcnt) = 0x80;
-	memset(ctx->buffer + ctx->bufcnt + 1, 0, padlen-1);
-	memcpy(ctx->buffer + ctx->bufcnt + padlen, &size, 8);
-	ctx->bufcnt += padlen + 8;
-	ctx->flags |= SHA_FLAGS_PAD;
+	u64 bits[2];
+	u64 size[2];
+
+	size[0] = ctx->digcnt[0];
+	size[1] = ctx->digcnt[1];
+
+	size[0] += ctx->bufcnt;
+	if (size[0] < ctx->bufcnt)
+		size[1]++;
+
+	size[0] += length;
+	if (size[0]  < length)
+		size[1]++;
+
+	bits[1] = cpu_to_be64(size[0] << 3);
+	bits[0] = cpu_to_be64(size[1] << 3 | size[0] >> 61);
+
+	if (ctx->flags & (SHA_FLAGS_SHA384 | SHA_FLAGS_SHA512)) {
+		index = ctx->bufcnt & 0x7f;
+		padlen = (index < 112) ? (112 - index) : ((128+112) - index);
+		*(ctx->buffer + ctx->bufcnt) = 0x80;
+		memset(ctx->buffer + ctx->bufcnt + 1, 0, padlen-1);
+		memcpy(ctx->buffer + ctx->bufcnt + padlen, bits, 16);
+		ctx->bufcnt += padlen + 16;
+		ctx->flags |= SHA_FLAGS_PAD;
+	} else {
+		index = ctx->bufcnt & 0x3f;
+		padlen = (index < 56) ? (56 - index) : ((64+56) - index);
+		*(ctx->buffer + ctx->bufcnt) = 0x80;
+		memset(ctx->buffer + ctx->bufcnt + 1, 0, padlen-1);
+		memcpy(ctx->buffer + ctx->bufcnt + padlen, &bits[1], 8);
+		ctx->bufcnt += padlen + 8;
+		ctx->flags |= SHA_FLAGS_PAD;
+	}
 }
 
 static int atmel_sha_init(struct ahash_request *req)
@@ -231,13 +271,35 @@ static int atmel_sha_init(struct ahash_request *req)
 	dev_dbg(dd->dev, "init: digest size: %d\n",
 		crypto_ahash_digestsize(tfm));
 
-	if (crypto_ahash_digestsize(tfm) == SHA1_DIGEST_SIZE)
+	switch (crypto_ahash_digestsize(tfm)) {
+	case SHA1_DIGEST_SIZE:
 		ctx->flags |= SHA_FLAGS_SHA1;
-	else if (crypto_ahash_digestsize(tfm) == SHA256_DIGEST_SIZE)
+		ctx->block_size = SHA1_BLOCK_SIZE;
+		break;
+	case SHA224_DIGEST_SIZE:
+		ctx->flags |= SHA_FLAGS_SHA224;
+		ctx->block_size = SHA224_BLOCK_SIZE;
+		break;
+	case SHA256_DIGEST_SIZE:
 		ctx->flags |= SHA_FLAGS_SHA256;
+		ctx->block_size = SHA256_BLOCK_SIZE;
+		break;
+	case SHA384_DIGEST_SIZE:
+		ctx->flags |= SHA_FLAGS_SHA384;
+		ctx->block_size = SHA384_BLOCK_SIZE;
+		break;
+	case SHA512_DIGEST_SIZE:
+		ctx->flags |= SHA_FLAGS_SHA512;
+		ctx->block_size = SHA512_BLOCK_SIZE;
+		break;
+	default:
+		return -EINVAL;
+		break;
+	}
 
 	ctx->bufcnt = 0;
-	ctx->digcnt = 0;
+	ctx->digcnt[0] = 0;
+	ctx->digcnt[1] = 0;
 	ctx->buflen = SHA_BUFFER_LEN;
 
 	return 0;
@@ -249,19 +311,28 @@ static void atmel_sha_write_ctrl(struct atmel_sha_dev *dd, int dma)
 	u32 valcr = 0, valmr = SHA_MR_MODE_AUTO;
 
 	if (likely(dma)) {
-		atmel_sha_write(dd, SHA_IER, SHA_INT_TXBUFE);
+		if (!dd->caps.has_dma)
+			atmel_sha_write(dd, SHA_IER, SHA_INT_TXBUFE);
 		valmr = SHA_MR_MODE_PDC;
-		if (dd->flags & SHA_FLAGS_DUALBUFF)
-			valmr = SHA_MR_DUALBUFF;
+		if (dd->caps.has_dualbuff)
+			valmr |= SHA_MR_DUALBUFF;
 	} else {
 		atmel_sha_write(dd, SHA_IER, SHA_INT_DATARDY);
 	}
 
-	if (ctx->flags & SHA_FLAGS_SHA256)
+	if (ctx->flags & SHA_FLAGS_SHA1)
+		valmr |= SHA_MR_ALGO_SHA1;
+	else if (ctx->flags & SHA_FLAGS_SHA224)
+		valmr |= SHA_MR_ALGO_SHA224;
+	else if (ctx->flags & SHA_FLAGS_SHA256)
 		valmr |= SHA_MR_ALGO_SHA256;
+	else if (ctx->flags & SHA_FLAGS_SHA384)
+		valmr |= SHA_MR_ALGO_SHA384;
+	else if (ctx->flags & SHA_FLAGS_SHA512)
+		valmr |= SHA_MR_ALGO_SHA512;
 
 	/* Setting CR_FIRST only for the first iteration */
-	if (!ctx->digcnt)
+	if (!(ctx->digcnt[0] || ctx->digcnt[1]))
 		valcr = SHA_CR_FIRST;
 
 	atmel_sha_write(dd, SHA_CR, valcr);
@@ -275,13 +346,15 @@ static int atmel_sha_xmit_cpu(struct atmel_sha_dev *dd, const u8 *buf,
 	int count, len32;
 	const u32 *buffer = (const u32 *)buf;
 
-	dev_dbg(dd->dev, "xmit_cpu: digcnt: %d, length: %d, final: %d\n",
-						ctx->digcnt, length, final);
+	dev_dbg(dd->dev, "xmit_cpu: digcnt: 0x%llx 0x%llx, length: %d, final: %d\n",
+		ctx->digcnt[1], ctx->digcnt[0], length, final);
 
 	atmel_sha_write_ctrl(dd, 0);
 
 	/* should be non-zero before next lines to disable clocks later */
-	ctx->digcnt += length;
+	ctx->digcnt[0] += length;
+	if (ctx->digcnt[0] < length)
+		ctx->digcnt[1]++;
 
 	if (final)
 		dd->flags |= SHA_FLAGS_FINAL; /* catch last interrupt */
@@ -302,8 +375,8 @@ static int atmel_sha_xmit_pdc(struct atmel_sha_dev *dd, dma_addr_t dma_addr1,
 	struct atmel_sha_reqctx *ctx = ahash_request_ctx(dd->req);
 	int len32;
 
-	dev_dbg(dd->dev, "xmit_pdc: digcnt: %d, length: %d, final: %d\n",
-						ctx->digcnt, length1, final);
+	dev_dbg(dd->dev, "xmit_pdc: digcnt: 0x%llx 0x%llx, length: %d, final: %d\n",
+		ctx->digcnt[1], ctx->digcnt[0], length1, final);
 
 	len32 = DIV_ROUND_UP(length1, sizeof(u32));
 	atmel_sha_write(dd, SHA_PTCR, SHA_PTCR_TXTDIS);
@@ -317,7 +390,9 @@ static int atmel_sha_xmit_pdc(struct atmel_sha_dev *dd, dma_addr_t dma_addr1,
 	atmel_sha_write_ctrl(dd, 1);
 
 	/* should be non-zero before next lines to disable clocks later */
-	ctx->digcnt += length1;
+	ctx->digcnt[0] += length1;
+	if (ctx->digcnt[0] < length1)
+		ctx->digcnt[1]++;
 
 	if (final)
 		dd->flags |= SHA_FLAGS_FINAL; /* catch last interrupt */
@@ -330,6 +405,86 @@ static int atmel_sha_xmit_pdc(struct atmel_sha_dev *dd, dma_addr_t dma_addr1,
 	return -EINPROGRESS;
 }
 
+static void atmel_sha_dma_callback(void *data)
+{
+	struct atmel_sha_dev *dd = data;
+
+	/* dma_lch_in - completed - wait DATRDY */
+	atmel_sha_write(dd, SHA_IER, SHA_INT_DATARDY);
+}
+
+static int atmel_sha_xmit_dma(struct atmel_sha_dev *dd, dma_addr_t dma_addr1,
+		size_t length1, dma_addr_t dma_addr2, size_t length2, int final)
+{
+	struct atmel_sha_reqctx *ctx = ahash_request_ctx(dd->req);
+	struct dma_async_tx_descriptor	*in_desc;
+	struct scatterlist sg[2];
+
+	dev_dbg(dd->dev, "xmit_dma: digcnt: 0x%llx 0x%llx, length: %d, final: %d\n",
+		ctx->digcnt[1], ctx->digcnt[0], length1, final);
+
+	if (ctx->flags & (SHA_FLAGS_SHA1 | SHA_FLAGS_SHA224 |
+			SHA_FLAGS_SHA256)) {
+		dd->dma_lch_in.dma_conf.src_maxburst = 16;
+		dd->dma_lch_in.dma_conf.dst_maxburst = 16;
+	} else {
+		dd->dma_lch_in.dma_conf.src_maxburst = 32;
+		dd->dma_lch_in.dma_conf.dst_maxburst = 32;
+	}
+
+	dmaengine_slave_config(dd->dma_lch_in.chan, &dd->dma_lch_in.dma_conf);
+
+	if (length2) {
+		sg_init_table(sg, 2);
+		sg_dma_address(&sg[0]) = dma_addr1;
+		sg_dma_len(&sg[0]) = length1;
+		sg_dma_address(&sg[1]) = dma_addr2;
+		sg_dma_len(&sg[1]) = length2;
+		in_desc = dmaengine_prep_slave_sg(dd->dma_lch_in.chan, sg, 2,
+			DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	} else {
+		sg_init_table(sg, 1);
+		sg_dma_address(&sg[0]) = dma_addr1;
+		sg_dma_len(&sg[0]) = length1;
+		in_desc = dmaengine_prep_slave_sg(dd->dma_lch_in.chan, sg, 1,
+			DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	}
+	if (!in_desc)
+		return -EINVAL;
+
+	in_desc->callback = atmel_sha_dma_callback;
+	in_desc->callback_param = dd;
+
+	atmel_sha_write_ctrl(dd, 1);
+
+	/* should be non-zero before next lines to disable clocks later */
+	ctx->digcnt[0] += length1;
+	if (ctx->digcnt[0] < length1)
+		ctx->digcnt[1]++;
+
+	if (final)
+		dd->flags |= SHA_FLAGS_FINAL; /* catch last interrupt */
+
+	dd->flags |=  SHA_FLAGS_DMA_ACTIVE;
+
+	/* Start DMA transfer */
+	dmaengine_submit(in_desc);
+	dma_async_issue_pending(dd->dma_lch_in.chan);
+
+	return -EINPROGRESS;
+}
+
+static int atmel_sha_xmit_start(struct atmel_sha_dev *dd, dma_addr_t dma_addr1,
+		size_t length1, dma_addr_t dma_addr2, size_t length2, int final)
+{
+	if (dd->caps.has_dma)
+		return atmel_sha_xmit_dma(dd, dma_addr1, length1,
+				dma_addr2, length2, final);
+	else
+		return atmel_sha_xmit_pdc(dd, dma_addr1, length1,
+				dma_addr2, length2, final);
+}
+
 static int atmel_sha_update_cpu(struct atmel_sha_dev *dd)
 {
 	struct atmel_sha_reqctx *ctx = ahash_request_ctx(dd->req);
@@ -337,7 +492,6 @@ static int atmel_sha_update_cpu(struct atmel_sha_dev *dd)
 
 	atmel_sha_append_sg(ctx);
 	atmel_sha_fill_padding(ctx, 0);
-
 	bufcnt = ctx->bufcnt;
 	ctx->bufcnt = 0;
 
@@ -349,17 +503,17 @@ static int atmel_sha_xmit_dma_map(struct atmel_sha_dev *dd,
 					size_t length, int final)
 {
 	ctx->dma_addr = dma_map_single(dd->dev, ctx->buffer,
-				ctx->buflen + SHA1_BLOCK_SIZE, DMA_TO_DEVICE);
+				ctx->buflen + ctx->block_size, DMA_TO_DEVICE);
 	if (dma_mapping_error(dd->dev, ctx->dma_addr)) {
 		dev_err(dd->dev, "dma %u bytes error\n", ctx->buflen +
-				SHA1_BLOCK_SIZE);
+				ctx->block_size);
 		return -EINVAL;
 	}
 
 	ctx->flags &= ~SHA_FLAGS_SG;
 
 	/* next call does not fail... so no unmap in the case of error */
-	return atmel_sha_xmit_pdc(dd, ctx->dma_addr, length, 0, 0, final);
+	return atmel_sha_xmit_start(dd, ctx->dma_addr, length, 0, 0, final);
 }
 
 static int atmel_sha_update_dma_slow(struct atmel_sha_dev *dd)
@@ -372,8 +526,8 @@ static int atmel_sha_update_dma_slow(struct atmel_sha_dev *dd)
 
 	final = (ctx->flags & SHA_FLAGS_FINUP) && !ctx->total;
 
-	dev_dbg(dd->dev, "slow: bufcnt: %u, digcnt: %d, final: %d\n",
-					 ctx->bufcnt, ctx->digcnt, final);
+	dev_dbg(dd->dev, "slow: bufcnt: %u, digcnt: 0x%llx 0x%llx, final: %d\n",
+		 ctx->bufcnt, ctx->digcnt[1], ctx->digcnt[0], final);
 
 	if (final)
 		atmel_sha_fill_padding(ctx, 0);
@@ -400,30 +554,25 @@ static int atmel_sha_update_dma_start(struct atmel_sha_dev *dd)
 	if (ctx->bufcnt || ctx->offset)
 		return atmel_sha_update_dma_slow(dd);
 
-	dev_dbg(dd->dev, "fast: digcnt: %d, bufcnt: %u, total: %u\n",
-			ctx->digcnt, ctx->bufcnt, ctx->total);
+	dev_dbg(dd->dev, "fast: digcnt: 0x%llx 0x%llx, bufcnt: %u, total: %u\n",
+		ctx->digcnt[1], ctx->digcnt[0], ctx->bufcnt, ctx->total);
 
 	sg = ctx->sg;
 
 	if (!IS_ALIGNED(sg->offset, sizeof(u32)))
 		return atmel_sha_update_dma_slow(dd);
 
-	if (!sg_is_last(sg) && !IS_ALIGNED(sg->length, SHA1_BLOCK_SIZE))
-		/* size is not SHA1_BLOCK_SIZE aligned */
+	if (!sg_is_last(sg) && !IS_ALIGNED(sg->length, ctx->block_size))
+		/* size is not ctx->block_size aligned */
 		return atmel_sha_update_dma_slow(dd);
 
 	length = min(ctx->total, sg->length);
 
 	if (sg_is_last(sg)) {
 		if (!(ctx->flags & SHA_FLAGS_FINUP)) {
-			/* not last sg must be SHA1_BLOCK_SIZE aligned */
-			tail = length & (SHA1_BLOCK_SIZE - 1);
+			/* not last sg must be ctx->block_size aligned */
+			tail = length & (ctx->block_size - 1);
 			length -= tail;
-			if (length == 0) {
-				/* offset where to start slow */
-				ctx->offset = length;
-				return atmel_sha_update_dma_slow(dd);
-			}
 		}
 	}
 
@@ -434,7 +583,7 @@ static int atmel_sha_update_dma_start(struct atmel_sha_dev *dd)
 
 	/* Add padding */
 	if (final) {
-		tail = length & (SHA1_BLOCK_SIZE - 1);
+		tail = length & (ctx->block_size - 1);
 		length -= tail;
 		ctx->total += tail;
 		ctx->offset = length; /* offset where to start slow */
@@ -445,10 +594,10 @@ static int atmel_sha_update_dma_start(struct atmel_sha_dev *dd)
 		atmel_sha_fill_padding(ctx, length);
 
 		ctx->dma_addr = dma_map_single(dd->dev, ctx->buffer,
-			ctx->buflen + SHA1_BLOCK_SIZE, DMA_TO_DEVICE);
+			ctx->buflen + ctx->block_size, DMA_TO_DEVICE);
 		if (dma_mapping_error(dd->dev, ctx->dma_addr)) {
 			dev_err(dd->dev, "dma %u bytes error\n",
-				ctx->buflen + SHA1_BLOCK_SIZE);
+				ctx->buflen + ctx->block_size);
 			return -EINVAL;
 		}
 
@@ -456,7 +605,7 @@ static int atmel_sha_update_dma_start(struct atmel_sha_dev *dd)
 			ctx->flags &= ~SHA_FLAGS_SG;
 			count = ctx->bufcnt;
 			ctx->bufcnt = 0;
-			return atmel_sha_xmit_pdc(dd, ctx->dma_addr, count, 0,
+			return atmel_sha_xmit_start(dd, ctx->dma_addr, count, 0,
 					0, final);
 		} else {
 			ctx->sg = sg;
@@ -470,7 +619,7 @@ static int atmel_sha_update_dma_start(struct atmel_sha_dev *dd)
 
 			count = ctx->bufcnt;
 			ctx->bufcnt = 0;
-			return atmel_sha_xmit_pdc(dd, sg_dma_address(ctx->sg),
+			return atmel_sha_xmit_start(dd, sg_dma_address(ctx->sg),
 					length, ctx->dma_addr, count, final);
 		}
 	}
@@ -483,7 +632,7 @@ static int atmel_sha_update_dma_start(struct atmel_sha_dev *dd)
 	ctx->flags |= SHA_FLAGS_SG;
 
 	/* next call does not fail... so no unmap in the case of error */
-	return atmel_sha_xmit_pdc(dd, sg_dma_address(ctx->sg), length, 0,
+	return atmel_sha_xmit_start(dd, sg_dma_address(ctx->sg), length, 0,
 								0, final);
 }
 
@@ -498,12 +647,13 @@ static int atmel_sha_update_dma_stop(struct atmel_sha_dev *dd)
 			if (ctx->sg)
 				ctx->offset = 0;
 		}
-		if (ctx->flags & SHA_FLAGS_PAD)
+		if (ctx->flags & SHA_FLAGS_PAD) {
 			dma_unmap_single(dd->dev, ctx->dma_addr,
-				ctx->buflen + SHA1_BLOCK_SIZE, DMA_TO_DEVICE);
+				ctx->buflen + ctx->block_size, DMA_TO_DEVICE);
+		}
 	} else {
 		dma_unmap_single(dd->dev, ctx->dma_addr, ctx->buflen +
-						SHA1_BLOCK_SIZE, DMA_TO_DEVICE);
+						ctx->block_size, DMA_TO_DEVICE);
 	}
 
 	return 0;
@@ -515,8 +665,8 @@ static int atmel_sha_update_req(struct atmel_sha_dev *dd)
 	struct atmel_sha_reqctx *ctx = ahash_request_ctx(req);
 	int err;
 
-	dev_dbg(dd->dev, "update_req: total: %u, digcnt: %d, finup: %d\n",
-		 ctx->total, ctx->digcnt, (ctx->flags & SHA_FLAGS_FINUP) != 0);
+	dev_dbg(dd->dev, "update_req: total: %u, digcnt: 0x%llx 0x%llx\n",
+		ctx->total, ctx->digcnt[1], ctx->digcnt[0]);
 
 	if (ctx->flags & SHA_FLAGS_CPU)
 		err = atmel_sha_update_cpu(dd);
@@ -524,8 +674,8 @@ static int atmel_sha_update_req(struct atmel_sha_dev *dd)
 		err = atmel_sha_update_dma_start(dd);
 
 	/* wait for dma completion before can take more data */
-	dev_dbg(dd->dev, "update: err: %d, digcnt: %d\n",
-			err, ctx->digcnt);
+	dev_dbg(dd->dev, "update: err: %d, digcnt: 0x%llx 0%llx\n",
+			err, ctx->digcnt[1], ctx->digcnt[0]);
 
 	return err;
 }
@@ -562,12 +712,21 @@ static void atmel_sha_copy_hash(struct ahash_request *req)
 	u32 *hash = (u32 *)ctx->digest;
 	int i;
 
-	if (likely(ctx->flags & SHA_FLAGS_SHA1))
+	if (ctx->flags & SHA_FLAGS_SHA1)
 		for (i = 0; i < SHA1_DIGEST_SIZE / sizeof(u32); i++)
 			hash[i] = atmel_sha_read(ctx->dd, SHA_REG_DIGEST(i));
-	else
+	else if (ctx->flags & SHA_FLAGS_SHA224)
+		for (i = 0; i < SHA224_DIGEST_SIZE / sizeof(u32); i++)
+			hash[i] = atmel_sha_read(ctx->dd, SHA_REG_DIGEST(i));
+	else if (ctx->flags & SHA_FLAGS_SHA256)
 		for (i = 0; i < SHA256_DIGEST_SIZE / sizeof(u32); i++)
 			hash[i] = atmel_sha_read(ctx->dd, SHA_REG_DIGEST(i));
+	else if (ctx->flags & SHA_FLAGS_SHA384)
+		for (i = 0; i < SHA384_DIGEST_SIZE / sizeof(u32); i++)
+			hash[i] = atmel_sha_read(ctx->dd, SHA_REG_DIGEST(i));
+	else
+		for (i = 0; i < SHA512_DIGEST_SIZE / sizeof(u32); i++)
+			hash[i] = atmel_sha_read(ctx->dd, SHA_REG_DIGEST(i));
 }
 
 static void atmel_sha_copy_ready_hash(struct ahash_request *req)
@@ -577,10 +736,16 @@ static void atmel_sha_copy_ready_hash(struct ahash_request *req)
 	if (!req->result)
 		return;
 
-	if (likely(ctx->flags & SHA_FLAGS_SHA1))
+	if (ctx->flags & SHA_FLAGS_SHA1)
 		memcpy(req->result, ctx->digest, SHA1_DIGEST_SIZE);
-	else
+	else if (ctx->flags & SHA_FLAGS_SHA224)
+		memcpy(req->result, ctx->digest, SHA224_DIGEST_SIZE);
+	else if (ctx->flags & SHA_FLAGS_SHA256)
 		memcpy(req->result, ctx->digest, SHA256_DIGEST_SIZE);
+	else if (ctx->flags & SHA_FLAGS_SHA384)
+		memcpy(req->result, ctx->digest, SHA384_DIGEST_SIZE);
+	else
+		memcpy(req->result, ctx->digest, SHA512_DIGEST_SIZE);
 }
 
 static int atmel_sha_finish(struct ahash_request *req)
@@ -589,11 +754,11 @@ static int atmel_sha_finish(struct ahash_request *req)
 	struct atmel_sha_dev *dd = ctx->dd;
 	int err = 0;
 
-	if (ctx->digcnt)
+	if (ctx->digcnt[0] || ctx->digcnt[1])
 		atmel_sha_copy_ready_hash(req);
 
-	dev_dbg(dd->dev, "digcnt: %d, bufcnt: %d\n", ctx->digcnt,
-		ctx->bufcnt);
+	dev_dbg(dd->dev, "digcnt: 0x%llx 0x%llx, bufcnt: %d\n", ctx->digcnt[1],
+		ctx->digcnt[0], ctx->bufcnt);
 
 	return err;
 }
@@ -628,9 +793,8 @@ static int atmel_sha_hw_init(struct atmel_sha_dev *dd)
 {
 	clk_prepare_enable(dd->iclk);
 
-	if (SHA_FLAGS_INIT & dd->flags) {
+	if (!(SHA_FLAGS_INIT & dd->flags)) {
 		atmel_sha_write(dd, SHA_CR, SHA_CR_SWRST);
-		atmel_sha_dualbuff_test(dd);
 		dd->flags |= SHA_FLAGS_INIT;
 		dd->err = 0;
 	}
@@ -638,6 +802,23 @@ static int atmel_sha_hw_init(struct atmel_sha_dev *dd)
 	return 0;
 }
 
+static inline unsigned int atmel_sha_get_version(struct atmel_sha_dev *dd)
+{
+	return atmel_sha_read(dd, SHA_HW_VERSION) & 0x00000fff;
+}
+
+static void atmel_sha_hw_version_init(struct atmel_sha_dev *dd)
+{
+	atmel_sha_hw_init(dd);
+
+	dd->hw_version = atmel_sha_get_version(dd);
+
+	dev_info(dd->dev,
+			"version: 0x%x\n", dd->hw_version);
+
+	clk_disable_unprepare(dd->iclk);
+}
+
 static int atmel_sha_handle_queue(struct atmel_sha_dev *dd,
 				  struct ahash_request *req)
 {
@@ -682,10 +863,9 @@ static int atmel_sha_handle_queue(struct atmel_sha_dev *dd,
 
 	if (ctx->op == SHA_OP_UPDATE) {
 		err = atmel_sha_update_req(dd);
-		if (err != -EINPROGRESS && (ctx->flags & SHA_FLAGS_FINUP)) {
+		if (err != -EINPROGRESS && (ctx->flags & SHA_FLAGS_FINUP))
 			/* no final() after finup() */
 			err = atmel_sha_final_req(dd);
-		}
 	} else if (ctx->op == SHA_OP_FINAL) {
 		err = atmel_sha_final_req(dd);
 	}
@@ -808,7 +988,7 @@ static int atmel_sha_cra_init_alg(struct crypto_tfm *tfm, const char *alg_base)
 	}
 	crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
 				 sizeof(struct atmel_sha_reqctx) +
-				 SHA_BUFFER_LEN + SHA256_BLOCK_SIZE);
+				 SHA_BUFFER_LEN + SHA512_BLOCK_SIZE);
 
 	return 0;
 }
@@ -826,7 +1006,7 @@ static void atmel_sha_cra_exit(struct crypto_tfm *tfm)
 	tctx->fallback = NULL;
 }
 
-static struct ahash_alg sha_algs[] = {
+static struct ahash_alg sha_1_256_algs[] = {
 {
 	.init		= atmel_sha_init,
 	.update		= atmel_sha_update,
@@ -875,6 +1055,79 @@ static struct ahash_alg sha_algs[] = {
 },
 };
 
+static struct ahash_alg sha_224_alg = {
+	.init		= atmel_sha_init,
+	.update		= atmel_sha_update,
+	.final		= atmel_sha_final,
+	.finup		= atmel_sha_finup,
+	.digest		= atmel_sha_digest,
+	.halg = {
+		.digestsize	= SHA224_DIGEST_SIZE,
+		.base	= {
+			.cra_name		= "sha224",
+			.cra_driver_name	= "atmel-sha224",
+			.cra_priority		= 100,
+			.cra_flags		= CRYPTO_ALG_ASYNC |
+						CRYPTO_ALG_NEED_FALLBACK,
+			.cra_blocksize		= SHA224_BLOCK_SIZE,
+			.cra_ctxsize		= sizeof(struct atmel_sha_ctx),
+			.cra_alignmask		= 0,
+			.cra_module		= THIS_MODULE,
+			.cra_init		= atmel_sha_cra_init,
+			.cra_exit		= atmel_sha_cra_exit,
+		}
+	}
+};
+
+static struct ahash_alg sha_384_512_algs[] = {
+{
+	.init		= atmel_sha_init,
+	.update		= atmel_sha_update,
+	.final		= atmel_sha_final,
+	.finup		= atmel_sha_finup,
+	.digest		= atmel_sha_digest,
+	.halg = {
+		.digestsize	= SHA384_DIGEST_SIZE,
+		.base	= {
+			.cra_name		= "sha384",
+			.cra_driver_name	= "atmel-sha384",
+			.cra_priority		= 100,
+			.cra_flags		= CRYPTO_ALG_ASYNC |
+						CRYPTO_ALG_NEED_FALLBACK,
+			.cra_blocksize		= SHA384_BLOCK_SIZE,
+			.cra_ctxsize		= sizeof(struct atmel_sha_ctx),
+			.cra_alignmask		= 0x3,
+			.cra_module		= THIS_MODULE,
+			.cra_init		= atmel_sha_cra_init,
+			.cra_exit		= atmel_sha_cra_exit,
+		}
+	}
+},
+{
+	.init		= atmel_sha_init,
+	.update		= atmel_sha_update,
+	.final		= atmel_sha_final,
+	.finup		= atmel_sha_finup,
+	.digest		= atmel_sha_digest,
+	.halg = {
+		.digestsize	= SHA512_DIGEST_SIZE,
+		.base	= {
+			.cra_name		= "sha512",
+			.cra_driver_name	= "atmel-sha512",
+			.cra_priority		= 100,
+			.cra_flags		= CRYPTO_ALG_ASYNC |
+						CRYPTO_ALG_NEED_FALLBACK,
+			.cra_blocksize		= SHA512_BLOCK_SIZE,
+			.cra_ctxsize		= sizeof(struct atmel_sha_ctx),
+			.cra_alignmask		= 0x3,
+			.cra_module		= THIS_MODULE,
+			.cra_init		= atmel_sha_cra_init,
+			.cra_exit		= atmel_sha_cra_exit,
+		}
+	}
+},
+};
+
 static void atmel_sha_done_task(unsigned long data)
 {
 	struct atmel_sha_dev *dd = (struct atmel_sha_dev *)data;
@@ -941,32 +1194,142 @@ static void atmel_sha_unregister_algs(struct atmel_sha_dev *dd)
 {
 	int i;
 
-	for (i = 0; i < ARRAY_SIZE(sha_algs); i++)
-		crypto_unregister_ahash(&sha_algs[i]);
+	for (i = 0; i < ARRAY_SIZE(sha_1_256_algs); i++)
+		crypto_unregister_ahash(&sha_1_256_algs[i]);
+
+	if (dd->caps.has_sha224)
+		crypto_unregister_ahash(&sha_224_alg);
+
+	if (dd->caps.has_sha_384_512) {
+		for (i = 0; i < ARRAY_SIZE(sha_384_512_algs); i++)
+			crypto_unregister_ahash(&sha_384_512_algs[i]);
+	}
 }
 
 static int atmel_sha_register_algs(struct atmel_sha_dev *dd)
 {
 	int err, i, j;
 
-	for (i = 0; i < ARRAY_SIZE(sha_algs); i++) {
-		err = crypto_register_ahash(&sha_algs[i]);
+	for (i = 0; i < ARRAY_SIZE(sha_1_256_algs); i++) {
+		err = crypto_register_ahash(&sha_1_256_algs[i]);
 		if (err)
-			goto err_sha_algs;
+			goto err_sha_1_256_algs;
+	}
+
+	if (dd->caps.has_sha224) {
+		err = crypto_register_ahash(&sha_224_alg);
+		if (err)
+			goto err_sha_224_algs;
+	}
+
+	if (dd->caps.has_sha_384_512) {
+		for (i = 0; i < ARRAY_SIZE(sha_384_512_algs); i++) {
+			err = crypto_register_ahash(&sha_384_512_algs[i]);
+			if (err)
+				goto err_sha_384_512_algs;
+		}
 	}
 
 	return 0;
 
-err_sha_algs:
+err_sha_384_512_algs:
+	for (j = 0; j < i; j++)
+		crypto_unregister_ahash(&sha_384_512_algs[j]);
+	crypto_unregister_ahash(&sha_224_alg);
+err_sha_224_algs:
+	i = ARRAY_SIZE(sha_1_256_algs);
+err_sha_1_256_algs:
 	for (j = 0; j < i; j++)
-		crypto_unregister_ahash(&sha_algs[j]);
+		crypto_unregister_ahash(&sha_1_256_algs[j]);
 
 	return err;
 }
 
+static bool atmel_sha_filter(struct dma_chan *chan, void *slave)
+{
+	struct at_dma_slave	*sl = slave;
+
+	if (sl && sl->dma_dev == chan->device->dev) {
+		chan->private = sl;
+		return true;
+	} else {
+		return false;
+	}
+}
+
+static int atmel_sha_dma_init(struct atmel_sha_dev *dd,
+				struct crypto_platform_data *pdata)
+{
+	int err = -ENOMEM;
+	dma_cap_mask_t mask_in;
+
+	if (pdata && pdata->dma_slave->rxdata.dma_dev) {
+		/* Try to grab DMA channel */
+		dma_cap_zero(mask_in);
+		dma_cap_set(DMA_SLAVE, mask_in);
+
+		dd->dma_lch_in.chan = dma_request_channel(mask_in,
+				atmel_sha_filter, &pdata->dma_slave->rxdata);
+
+		if (!dd->dma_lch_in.chan)
+			return err;
+
+		dd->dma_lch_in.dma_conf.direction = DMA_MEM_TO_DEV;
+		dd->dma_lch_in.dma_conf.dst_addr = dd->phys_base +
+			SHA_REG_DIN(0);
+		dd->dma_lch_in.dma_conf.src_maxburst = 1;
+		dd->dma_lch_in.dma_conf.src_addr_width =
+			DMA_SLAVE_BUSWIDTH_4_BYTES;
+		dd->dma_lch_in.dma_conf.dst_maxburst = 1;
+		dd->dma_lch_in.dma_conf.dst_addr_width =
+			DMA_SLAVE_BUSWIDTH_4_BYTES;
+		dd->dma_lch_in.dma_conf.device_fc = false;
+
+		return 0;
+	}
+
+	return -ENODEV;
+}
+
+static void atmel_sha_dma_cleanup(struct atmel_sha_dev *dd)
+{
+	dma_release_channel(dd->dma_lch_in.chan);
+}
+
+static void atmel_sha_get_cap(struct atmel_sha_dev *dd)
+{
+
+	dd->caps.has_dma = 0;
+	dd->caps.has_dualbuff = 0;
+	dd->caps.has_sha224 = 0;
+	dd->caps.has_sha_384_512 = 0;
+
+	/* keep only major version number */
+	switch (dd->hw_version & 0xff0) {
+	case 0x410:
+		dd->caps.has_dma = 1;
+		dd->caps.has_dualbuff = 1;
+		dd->caps.has_sha224 = 1;
+		dd->caps.has_sha_384_512 = 1;
+		break;
+	case 0x400:
+		dd->caps.has_dma = 1;
+		dd->caps.has_dualbuff = 1;
+		dd->caps.has_sha224 = 1;
+		break;
+	case 0x320:
+		break;
+	default:
+		dev_warn(dd->dev,
+				"Unmanaged sha version, set minimum capabilities\n");
+		break;
+	}
+}
+
 static int atmel_sha_probe(struct platform_device *pdev)
 {
 	struct atmel_sha_dev *sha_dd;
+	struct crypto_platform_data	*pdata;
 	struct device *dev = &pdev->dev;
 	struct resource *sha_res;
 	unsigned long sha_phys_size;
@@ -1018,7 +1381,7 @@ static int atmel_sha_probe(struct platform_device *pdev)
 	}
 
 	/* Initializing the clock */
-	sha_dd->iclk = clk_get(&pdev->dev, NULL);
+	sha_dd->iclk = clk_get(&pdev->dev, "sha_clk");
 	if (IS_ERR(sha_dd->iclk)) {
 		dev_err(dev, "clock intialization failed.\n");
 		err = PTR_ERR(sha_dd->iclk);
@@ -1032,6 +1395,22 @@ static int atmel_sha_probe(struct platform_device *pdev)
 		goto sha_io_err;
 	}
 
+	atmel_sha_hw_version_init(sha_dd);
+
+	atmel_sha_get_cap(sha_dd);
+
+	if (sha_dd->caps.has_dma) {
+		pdata = pdev->dev.platform_data;
+		if (!pdata) {
+			dev_err(&pdev->dev, "platform data not available\n");
+			err = -ENXIO;
+			goto err_pdata;
+		}
+		err = atmel_sha_dma_init(sha_dd, pdata);
+		if (err)
+			goto err_sha_dma;
+	}
+
 	spin_lock(&atmel_sha.lock);
 	list_add_tail(&sha_dd->list, &atmel_sha.dev_list);
 	spin_unlock(&atmel_sha.lock);
@@ -1048,6 +1427,10 @@ err_algs:
 	spin_lock(&atmel_sha.lock);
 	list_del(&sha_dd->list);
 	spin_unlock(&atmel_sha.lock);
+	if (sha_dd->caps.has_dma)
+		atmel_sha_dma_cleanup(sha_dd);
+err_sha_dma:
+err_pdata:
 	iounmap(sha_dd->io_base);
 sha_io_err:
 	clk_put(sha_dd->iclk);
@@ -1078,6 +1461,9 @@ static int atmel_sha_remove(struct platform_device *pdev)
 
 	tasklet_kill(&sha_dd->done_task);
 
+	if (sha_dd->caps.has_dma)
+		atmel_sha_dma_cleanup(sha_dd);
+
 	iounmap(sha_dd->io_base);
 
 	clk_put(sha_dd->iclk);
@@ -1102,6 +1488,6 @@ static struct platform_driver atmel_sha_driver = {
 
 module_platform_driver(atmel_sha_driver);
 
-MODULE_DESCRIPTION("Atmel SHA1/SHA256 hw acceleration support.");
+MODULE_DESCRIPTION("Atmel SHA (1/256/224/384/512) hw acceleration support.");
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Nicolas Royer - Eukréa Electromatique");
diff --git a/drivers/crypto/atmel-tdes-regs.h b/drivers/crypto/atmel-tdes-regs.h
index 5ac2a90..f86734d 100644
--- a/drivers/crypto/atmel-tdes-regs.h
+++ b/drivers/crypto/atmel-tdes-regs.h
@@ -69,6 +69,8 @@
 #define	TDES_XTEARNDR_XTEA_RNDS_MASK	(0x3F << 0)
 #define	TDES_XTEARNDR_XTEA_RNDS_OFFSET	0
 
+#define	TDES_HW_VERSION	0xFC
+
 #define TDES_RPR		0x100
 #define TDES_RCR		0x104
 #define TDES_TPR		0x108
diff --git a/drivers/crypto/atmel-tdes.c b/drivers/crypto/atmel-tdes.c
index 7c73fbb..4a99564 100644
--- a/drivers/crypto/atmel-tdes.c
+++ b/drivers/crypto/atmel-tdes.c
@@ -38,29 +38,35 @@
 #include <crypto/des.h>
 #include <crypto/hash.h>
 #include <crypto/internal/hash.h>
+#include <linux/platform_data/crypto-atmel.h>
 #include "atmel-tdes-regs.h"
 
 /* TDES flags  */
-#define TDES_FLAGS_MODE_MASK		0x007f
+#define TDES_FLAGS_MODE_MASK		0x00ff
 #define TDES_FLAGS_ENCRYPT	BIT(0)
 #define TDES_FLAGS_CBC		BIT(1)
 #define TDES_FLAGS_CFB		BIT(2)
 #define TDES_FLAGS_CFB8		BIT(3)
 #define TDES_FLAGS_CFB16	BIT(4)
 #define TDES_FLAGS_CFB32	BIT(5)
-#define TDES_FLAGS_OFB		BIT(6)
+#define TDES_FLAGS_CFB64	BIT(6)
+#define TDES_FLAGS_OFB		BIT(7)
 
 #define TDES_FLAGS_INIT		BIT(16)
 #define TDES_FLAGS_FAST		BIT(17)
 #define TDES_FLAGS_BUSY		BIT(18)
+#define TDES_FLAGS_DMA		BIT(19)
 
-#define ATMEL_TDES_QUEUE_LENGTH	1
+#define ATMEL_TDES_QUEUE_LENGTH	50
 
 #define CFB8_BLOCK_SIZE		1
 #define CFB16_BLOCK_SIZE	2
 #define CFB32_BLOCK_SIZE	4
-#define CFB64_BLOCK_SIZE	8
 
+struct atmel_tdes_caps {
+	bool	has_dma;
+	u32		has_cfb_3keys;
+};
 
 struct atmel_tdes_dev;
 
@@ -70,12 +76,19 @@ struct atmel_tdes_ctx {
 	int		keylen;
 	u32		key[3*DES_KEY_SIZE / sizeof(u32)];
 	unsigned long	flags;
+
+	u16		block_size;
 };
 
 struct atmel_tdes_reqctx {
 	unsigned long mode;
 };
 
+struct atmel_tdes_dma {
+	struct dma_chan			*chan;
+	struct dma_slave_config dma_conf;
+};
+
 struct atmel_tdes_dev {
 	struct list_head	list;
 	unsigned long		phys_base;
@@ -99,8 +112,10 @@ struct atmel_tdes_dev {
 	size_t				total;
 
 	struct scatterlist	*in_sg;
+	unsigned int		nb_in_sg;
 	size_t				in_offset;
 	struct scatterlist	*out_sg;
+	unsigned int		nb_out_sg;
 	size_t				out_offset;
 
 	size_t	buflen;
@@ -109,10 +124,16 @@ struct atmel_tdes_dev {
 	void	*buf_in;
 	int		dma_in;
 	dma_addr_t	dma_addr_in;
+	struct atmel_tdes_dma	dma_lch_in;
 
 	void	*buf_out;
 	int		dma_out;
 	dma_addr_t	dma_addr_out;
+	struct atmel_tdes_dma	dma_lch_out;
+
+	struct atmel_tdes_caps	caps;
+
+	u32	hw_version;
 };
 
 struct atmel_tdes_drv {
@@ -207,6 +228,31 @@ static int atmel_tdes_hw_init(struct atmel_tdes_dev *dd)
 	return 0;
 }
 
+static inline unsigned int atmel_tdes_get_version(struct atmel_tdes_dev *dd)
+{
+	return atmel_tdes_read(dd, TDES_HW_VERSION) & 0x00000fff;
+}
+
+static void atmel_tdes_hw_version_init(struct atmel_tdes_dev *dd)
+{
+	atmel_tdes_hw_init(dd);
+
+	dd->hw_version = atmel_tdes_get_version(dd);
+
+	dev_info(dd->dev,
+			"version: 0x%x\n", dd->hw_version);
+
+	clk_disable_unprepare(dd->iclk);
+}
+
+static void atmel_tdes_dma_callback(void *data)
+{
+	struct atmel_tdes_dev *dd = data;
+
+	/* dma_lch_out - completed */
+	tasklet_schedule(&dd->done_task);
+}
+
 static int atmel_tdes_write_ctrl(struct atmel_tdes_dev *dd)
 {
 	int err;
@@ -217,7 +263,9 @@ static int atmel_tdes_write_ctrl(struct atmel_tdes_dev *dd)
 	if (err)
 		return err;
 
-	atmel_tdes_write(dd, TDES_PTCR, TDES_PTCR_TXTDIS|TDES_PTCR_RXTDIS);
+	if (!dd->caps.has_dma)
+		atmel_tdes_write(dd, TDES_PTCR,
+			TDES_PTCR_TXTDIS | TDES_PTCR_RXTDIS);
 
 	/* MR register must be set before IV registers */
 	if (dd->ctx->keylen > (DES_KEY_SIZE << 1)) {
@@ -241,6 +289,8 @@ static int atmel_tdes_write_ctrl(struct atmel_tdes_dev *dd)
 			valmr |= TDES_MR_CFBS_16b;
 		else if (dd->flags & TDES_FLAGS_CFB32)
 			valmr |= TDES_MR_CFBS_32b;
+		else if (dd->flags & TDES_FLAGS_CFB64)
+			valmr |= TDES_MR_CFBS_64b;
 	} else if (dd->flags & TDES_FLAGS_OFB) {
 		valmr |= TDES_MR_OPMOD_OFB;
 	}
@@ -262,7 +312,7 @@ static int atmel_tdes_write_ctrl(struct atmel_tdes_dev *dd)
 	return 0;
 }
 
-static int atmel_tdes_crypt_dma_stop(struct atmel_tdes_dev *dd)
+static int atmel_tdes_crypt_pdc_stop(struct atmel_tdes_dev *dd)
 {
 	int err = 0;
 	size_t count;
@@ -288,7 +338,7 @@ static int atmel_tdes_crypt_dma_stop(struct atmel_tdes_dev *dd)
 	return err;
 }
 
-static int atmel_tdes_dma_init(struct atmel_tdes_dev *dd)
+static int atmel_tdes_buff_init(struct atmel_tdes_dev *dd)
 {
 	int err = -ENOMEM;
 
@@ -333,7 +383,7 @@ err_alloc:
 	return err;
 }
 
-static void atmel_tdes_dma_cleanup(struct atmel_tdes_dev *dd)
+static void atmel_tdes_buff_cleanup(struct atmel_tdes_dev *dd)
 {
 	dma_unmap_single(dd->dev, dd->dma_addr_out, dd->buflen,
 			 DMA_FROM_DEVICE);
@@ -343,7 +393,7 @@ static void atmel_tdes_dma_cleanup(struct atmel_tdes_dev *dd)
 	free_page((unsigned long)dd->buf_in);
 }
 
-static int atmel_tdes_crypt_dma(struct crypto_tfm *tfm, dma_addr_t dma_addr_in,
+static int atmel_tdes_crypt_pdc(struct crypto_tfm *tfm, dma_addr_t dma_addr_in,
 			       dma_addr_t dma_addr_out, int length)
 {
 	struct atmel_tdes_ctx *ctx = crypto_tfm_ctx(tfm);
@@ -379,7 +429,76 @@ static int atmel_tdes_crypt_dma(struct crypto_tfm *tfm, dma_addr_t dma_addr_in,
 	return 0;
 }
 
-static int atmel_tdes_crypt_dma_start(struct atmel_tdes_dev *dd)
+static int atmel_tdes_crypt_dma(struct crypto_tfm *tfm, dma_addr_t dma_addr_in,
+			       dma_addr_t dma_addr_out, int length)
+{
+	struct atmel_tdes_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct atmel_tdes_dev *dd = ctx->dd;
+	struct scatterlist sg[2];
+	struct dma_async_tx_descriptor	*in_desc, *out_desc;
+
+	dd->dma_size = length;
+
+	if (!(dd->flags & TDES_FLAGS_FAST)) {
+		dma_sync_single_for_device(dd->dev, dma_addr_in, length,
+					   DMA_TO_DEVICE);
+	}
+
+	if (dd->flags & TDES_FLAGS_CFB8) {
+		dd->dma_lch_in.dma_conf.dst_addr_width =
+			DMA_SLAVE_BUSWIDTH_1_BYTE;
+		dd->dma_lch_out.dma_conf.src_addr_width =
+			DMA_SLAVE_BUSWIDTH_1_BYTE;
+	} else if (dd->flags & TDES_FLAGS_CFB16) {
+		dd->dma_lch_in.dma_conf.dst_addr_width =
+			DMA_SLAVE_BUSWIDTH_2_BYTES;
+		dd->dma_lch_out.dma_conf.src_addr_width =
+			DMA_SLAVE_BUSWIDTH_2_BYTES;
+	} else {
+		dd->dma_lch_in.dma_conf.dst_addr_width =
+			DMA_SLAVE_BUSWIDTH_4_BYTES;
+		dd->dma_lch_out.dma_conf.src_addr_width =
+			DMA_SLAVE_BUSWIDTH_4_BYTES;
+	}
+
+	dmaengine_slave_config(dd->dma_lch_in.chan, &dd->dma_lch_in.dma_conf);
+	dmaengine_slave_config(dd->dma_lch_out.chan, &dd->dma_lch_out.dma_conf);
+
+	dd->flags |= TDES_FLAGS_DMA;
+
+	sg_init_table(&sg[0], 1);
+	sg_dma_address(&sg[0]) = dma_addr_in;
+	sg_dma_len(&sg[0]) = length;
+
+	sg_init_table(&sg[1], 1);
+	sg_dma_address(&sg[1]) = dma_addr_out;
+	sg_dma_len(&sg[1]) = length;
+
+	in_desc = dmaengine_prep_slave_sg(dd->dma_lch_in.chan, &sg[0],
+				1, DMA_MEM_TO_DEV,
+				DMA_PREP_INTERRUPT  |  DMA_CTRL_ACK);
+	if (!in_desc)
+		return -EINVAL;
+
+	out_desc = dmaengine_prep_slave_sg(dd->dma_lch_out.chan, &sg[1],
+				1, DMA_DEV_TO_MEM,
+				DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	if (!out_desc)
+		return -EINVAL;
+
+	out_desc->callback = atmel_tdes_dma_callback;
+	out_desc->callback_param = dd;
+
+	dmaengine_submit(out_desc);
+	dma_async_issue_pending(dd->dma_lch_out.chan);
+
+	dmaengine_submit(in_desc);
+	dma_async_issue_pending(dd->dma_lch_in.chan);
+
+	return 0;
+}
+
+static int atmel_tdes_crypt_start(struct atmel_tdes_dev *dd)
 {
 	struct crypto_tfm *tfm = crypto_ablkcipher_tfm(
 					crypto_ablkcipher_reqtfm(dd->req));
@@ -387,23 +506,23 @@ static int atmel_tdes_crypt_dma_start(struct atmel_tdes_dev *dd)
 	size_t count;
 	dma_addr_t addr_in, addr_out;
 
-	if (sg_is_last(dd->in_sg) && sg_is_last(dd->out_sg)) {
+	if ((!dd->in_offset) && (!dd->out_offset)) {
 		/* check for alignment */
-		in = IS_ALIGNED((u32)dd->in_sg->offset, sizeof(u32));
-		out = IS_ALIGNED((u32)dd->out_sg->offset, sizeof(u32));
-
+		in = IS_ALIGNED((u32)dd->in_sg->offset, sizeof(u32)) &&
+			IS_ALIGNED(dd->in_sg->length, dd->ctx->block_size);
+		out = IS_ALIGNED((u32)dd->out_sg->offset, sizeof(u32)) &&
+			IS_ALIGNED(dd->out_sg->length, dd->ctx->block_size);
 		fast = in && out;
+
+		if (sg_dma_len(dd->in_sg) != sg_dma_len(dd->out_sg))
+			fast = 0;
 	}
 
+
 	if (fast)  {
 		count = min(dd->total, sg_dma_len(dd->in_sg));
 		count = min(count, sg_dma_len(dd->out_sg));
 
-		if (count != dd->total) {
-			pr_err("request length != buffer length\n");
-			return -EINVAL;
-		}
-
 		err = dma_map_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE);
 		if (!err) {
 			dev_err(dd->dev, "dma_map_sg() error\n");
@@ -433,13 +552,16 @@ static int atmel_tdes_crypt_dma_start(struct atmel_tdes_dev *dd)
 		addr_out = dd->dma_addr_out;
 
 		dd->flags &= ~TDES_FLAGS_FAST;
-
 	}
 
 	dd->total -= count;
 
-	err = atmel_tdes_crypt_dma(tfm, addr_in, addr_out, count);
-	if (err) {
+	if (dd->caps.has_dma)
+		err = atmel_tdes_crypt_dma(tfm, addr_in, addr_out, count);
+	else
+		err = atmel_tdes_crypt_pdc(tfm, addr_in, addr_out, count);
+
+	if (err && (dd->flags & TDES_FLAGS_FAST)) {
 		dma_unmap_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE);
 		dma_unmap_sg(dd->dev, dd->out_sg, 1, DMA_TO_DEVICE);
 	}
@@ -447,7 +569,6 @@ static int atmel_tdes_crypt_dma_start(struct atmel_tdes_dev *dd)
 	return err;
 }
 
-
 static void atmel_tdes_finish_req(struct atmel_tdes_dev *dd, int err)
 {
 	struct ablkcipher_request *req = dd->req;
@@ -506,7 +627,7 @@ static int atmel_tdes_handle_queue(struct atmel_tdes_dev *dd,
 
 	err = atmel_tdes_write_ctrl(dd);
 	if (!err)
-		err = atmel_tdes_crypt_dma_start(dd);
+		err = atmel_tdes_crypt_start(dd);
 	if (err) {
 		/* des_task will not finish it, so do it here */
 		atmel_tdes_finish_req(dd, err);
@@ -516,41 +637,145 @@ static int atmel_tdes_handle_queue(struct atmel_tdes_dev *dd,
 	return ret;
 }
 
+static int atmel_tdes_crypt_dma_stop(struct atmel_tdes_dev *dd)
+{
+	int err = -EINVAL;
+	size_t count;
+
+	if (dd->flags & TDES_FLAGS_DMA) {
+		err = 0;
+		if  (dd->flags & TDES_FLAGS_FAST) {
+			dma_unmap_sg(dd->dev, dd->out_sg, 1, DMA_FROM_DEVICE);
+			dma_unmap_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE);
+		} else {
+			dma_sync_single_for_device(dd->dev, dd->dma_addr_out,
+				dd->dma_size, DMA_FROM_DEVICE);
+
+			/* copy data */
+			count = atmel_tdes_sg_copy(&dd->out_sg, &dd->out_offset,
+				dd->buf_out, dd->buflen, dd->dma_size, 1);
+			if (count != dd->dma_size) {
+				err = -EINVAL;
+				pr_err("not all data converted: %u\n", count);
+			}
+		}
+	}
+	return err;
+}
 
 static int atmel_tdes_crypt(struct ablkcipher_request *req, unsigned long mode)
 {
 	struct atmel_tdes_ctx *ctx = crypto_ablkcipher_ctx(
 			crypto_ablkcipher_reqtfm(req));
 	struct atmel_tdes_reqctx *rctx = ablkcipher_request_ctx(req);
-	struct atmel_tdes_dev *dd;
 
 	if (mode & TDES_FLAGS_CFB8) {
 		if (!IS_ALIGNED(req->nbytes, CFB8_BLOCK_SIZE)) {
 			pr_err("request size is not exact amount of CFB8 blocks\n");
 			return -EINVAL;
 		}
+		ctx->block_size = CFB8_BLOCK_SIZE;
 	} else if (mode & TDES_FLAGS_CFB16) {
 		if (!IS_ALIGNED(req->nbytes, CFB16_BLOCK_SIZE)) {
 			pr_err("request size is not exact amount of CFB16 blocks\n");
 			return -EINVAL;
 		}
+		ctx->block_size = CFB16_BLOCK_SIZE;
 	} else if (mode & TDES_FLAGS_CFB32) {
 		if (!IS_ALIGNED(req->nbytes, CFB32_BLOCK_SIZE)) {
 			pr_err("request size is not exact amount of CFB32 blocks\n");
 			return -EINVAL;
 		}
-	} else if (!IS_ALIGNED(req->nbytes, DES_BLOCK_SIZE)) {
-		pr_err("request size is not exact amount of DES blocks\n");
-		return -EINVAL;
+		ctx->block_size = CFB32_BLOCK_SIZE;
+	} else {
+		if (!IS_ALIGNED(req->nbytes, DES_BLOCK_SIZE)) {
+			pr_err("request size is not exact amount of DES blocks\n");
+			return -EINVAL;
+		}
+		ctx->block_size = DES_BLOCK_SIZE;
 	}
 
-	dd = atmel_tdes_find_dev(ctx);
-	if (!dd)
+	rctx->mode = mode;
+
+	return atmel_tdes_handle_queue(ctx->dd, req);
+}
+
+static bool atmel_tdes_filter(struct dma_chan *chan, void *slave)
+{
+	struct at_dma_slave	*sl = slave;
+
+	if (sl && sl->dma_dev == chan->device->dev) {
+		chan->private = sl;
+		return true;
+	} else {
+		return false;
+	}
+}
+
+static int atmel_tdes_dma_init(struct atmel_tdes_dev *dd,
+			struct crypto_platform_data *pdata)
+{
+	int err = -ENOMEM;
+	dma_cap_mask_t mask_in, mask_out;
+
+	if (pdata && pdata->dma_slave->txdata.dma_dev &&
+		pdata->dma_slave->rxdata.dma_dev) {
+
+		/* Try to grab 2 DMA channels */
+		dma_cap_zero(mask_in);
+		dma_cap_set(DMA_SLAVE, mask_in);
+
+		dd->dma_lch_in.chan = dma_request_channel(mask_in,
+				atmel_tdes_filter, &pdata->dma_slave->rxdata);
+
+		if (!dd->dma_lch_in.chan)
+			goto err_dma_in;
+
+		dd->dma_lch_in.dma_conf.direction = DMA_MEM_TO_DEV;
+		dd->dma_lch_in.dma_conf.dst_addr = dd->phys_base +
+			TDES_IDATA1R;
+		dd->dma_lch_in.dma_conf.src_maxburst = 1;
+		dd->dma_lch_in.dma_conf.src_addr_width =
+			DMA_SLAVE_BUSWIDTH_4_BYTES;
+		dd->dma_lch_in.dma_conf.dst_maxburst = 1;
+		dd->dma_lch_in.dma_conf.dst_addr_width =
+			DMA_SLAVE_BUSWIDTH_4_BYTES;
+		dd->dma_lch_in.dma_conf.device_fc = false;
+
+		dma_cap_zero(mask_out);
+		dma_cap_set(DMA_SLAVE, mask_out);
+		dd->dma_lch_out.chan = dma_request_channel(mask_out,
+				atmel_tdes_filter, &pdata->dma_slave->txdata);
+
+		if (!dd->dma_lch_out.chan)
+			goto err_dma_out;
+
+		dd->dma_lch_out.dma_conf.direction = DMA_DEV_TO_MEM;
+		dd->dma_lch_out.dma_conf.src_addr = dd->phys_base +
+			TDES_ODATA1R;
+		dd->dma_lch_out.dma_conf.src_maxburst = 1;
+		dd->dma_lch_out.dma_conf.src_addr_width =
+			DMA_SLAVE_BUSWIDTH_4_BYTES;
+		dd->dma_lch_out.dma_conf.dst_maxburst = 1;
+		dd->dma_lch_out.dma_conf.dst_addr_width =
+			DMA_SLAVE_BUSWIDTH_4_BYTES;
+		dd->dma_lch_out.dma_conf.device_fc = false;
+
+		return 0;
+	} else {
 		return -ENODEV;
+	}
 
-	rctx->mode = mode;
+err_dma_out:
+	dma_release_channel(dd->dma_lch_in.chan);
+err_dma_in:
+	return err;
+}
 
-	return atmel_tdes_handle_queue(dd, req);
+static void atmel_tdes_dma_cleanup(struct atmel_tdes_dev *dd)
+{
+	dma_release_channel(dd->dma_lch_in.chan);
+	dma_release_channel(dd->dma_lch_out.chan);
 }
 
 static int atmel_des_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
@@ -590,7 +815,8 @@ static int atmel_tdes_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
 	/*
 	 * HW bug in cfb 3-keys mode.
 	 */
-	if (strstr(alg_name, "cfb") && (keylen != 2*DES_KEY_SIZE)) {
+	if (!ctx->dd->caps.has_cfb_3keys && strstr(alg_name, "cfb")
+			&& (keylen != 2*DES_KEY_SIZE)) {
 		crypto_ablkcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
 		return -EINVAL;
 	} else if ((keylen != 2*DES_KEY_SIZE) && (keylen != 3*DES_KEY_SIZE)) {
@@ -678,8 +904,15 @@ static int atmel_tdes_ofb_decrypt(struct ablkcipher_request *req)
 
 static int atmel_tdes_cra_init(struct crypto_tfm *tfm)
 {
+	struct atmel_tdes_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct atmel_tdes_dev *dd;
+
 	tfm->crt_ablkcipher.reqsize = sizeof(struct atmel_tdes_reqctx);
 
+	dd = atmel_tdes_find_dev(ctx);
+	if (!dd)
+		return -ENODEV;
+
 	return 0;
 }
 
@@ -695,7 +928,7 @@ static struct crypto_alg tdes_algs[] = {
 	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
 	.cra_blocksize		= DES_BLOCK_SIZE,
 	.cra_ctxsize		= sizeof(struct atmel_tdes_ctx),
-	.cra_alignmask		= 0,
+	.cra_alignmask		= 0x7,
 	.cra_type		= &crypto_ablkcipher_type,
 	.cra_module		= THIS_MODULE,
 	.cra_init		= atmel_tdes_cra_init,
@@ -715,7 +948,7 @@ static struct crypto_alg tdes_algs[] = {
 	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
 	.cra_blocksize		= DES_BLOCK_SIZE,
 	.cra_ctxsize		= sizeof(struct atmel_tdes_ctx),
-	.cra_alignmask		= 0,
+	.cra_alignmask		= 0x7,
 	.cra_type		= &crypto_ablkcipher_type,
 	.cra_module		= THIS_MODULE,
 	.cra_init		= atmel_tdes_cra_init,
@@ -736,7 +969,7 @@ static struct crypto_alg tdes_algs[] = {
 	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
 	.cra_blocksize		= DES_BLOCK_SIZE,
 	.cra_ctxsize		= sizeof(struct atmel_tdes_ctx),
-	.cra_alignmask		= 0,
+	.cra_alignmask		= 0x7,
 	.cra_type		= &crypto_ablkcipher_type,
 	.cra_module		= THIS_MODULE,
 	.cra_init		= atmel_tdes_cra_init,
@@ -778,7 +1011,7 @@ static struct crypto_alg tdes_algs[] = {
 	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
 	.cra_blocksize		= CFB16_BLOCK_SIZE,
 	.cra_ctxsize		= sizeof(struct atmel_tdes_ctx),
-	.cra_alignmask		= 0,
+	.cra_alignmask		= 0x1,
 	.cra_type		= &crypto_ablkcipher_type,
 	.cra_module		= THIS_MODULE,
 	.cra_init		= atmel_tdes_cra_init,
@@ -799,7 +1032,7 @@ static struct crypto_alg tdes_algs[] = {
 	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
 	.cra_blocksize		= CFB32_BLOCK_SIZE,
 	.cra_ctxsize		= sizeof(struct atmel_tdes_ctx),
-	.cra_alignmask		= 0,
+	.cra_alignmask		= 0x3,
 	.cra_type		= &crypto_ablkcipher_type,
 	.cra_module		= THIS_MODULE,
 	.cra_init		= atmel_tdes_cra_init,
@@ -820,7 +1053,7 @@ static struct crypto_alg tdes_algs[] = {
 	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
 	.cra_blocksize		= DES_BLOCK_SIZE,
 	.cra_ctxsize		= sizeof(struct atmel_tdes_ctx),
-	.cra_alignmask		= 0,
+	.cra_alignmask		= 0x7,
 	.cra_type		= &crypto_ablkcipher_type,
 	.cra_module		= THIS_MODULE,
 	.cra_init		= atmel_tdes_cra_init,
@@ -841,7 +1074,7 @@ static struct crypto_alg tdes_algs[] = {
 	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
 	.cra_blocksize		= DES_BLOCK_SIZE,
 	.cra_ctxsize		= sizeof(struct atmel_tdes_ctx),
-	.cra_alignmask		= 0,
+	.cra_alignmask		= 0x7,
 	.cra_type		= &crypto_ablkcipher_type,
 	.cra_module		= THIS_MODULE,
 	.cra_init		= atmel_tdes_cra_init,
@@ -861,7 +1094,7 @@ static struct crypto_alg tdes_algs[] = {
 	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
 	.cra_blocksize		= DES_BLOCK_SIZE,
 	.cra_ctxsize		= sizeof(struct atmel_tdes_ctx),
-	.cra_alignmask		= 0,
+	.cra_alignmask		= 0x7,
 	.cra_type		= &crypto_ablkcipher_type,
 	.cra_module		= THIS_MODULE,
 	.cra_init		= atmel_tdes_cra_init,
@@ -882,7 +1115,7 @@ static struct crypto_alg tdes_algs[] = {
 	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
 	.cra_blocksize		= DES_BLOCK_SIZE,
 	.cra_ctxsize		= sizeof(struct atmel_tdes_ctx),
-	.cra_alignmask		= 0,
+	.cra_alignmask		= 0x7,
 	.cra_type		= &crypto_ablkcipher_type,
 	.cra_module		= THIS_MODULE,
 	.cra_init		= atmel_tdes_cra_init,
@@ -924,7 +1157,7 @@ static struct crypto_alg tdes_algs[] = {
 	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
 	.cra_blocksize		= CFB16_BLOCK_SIZE,
 	.cra_ctxsize		= sizeof(struct atmel_tdes_ctx),
-	.cra_alignmask		= 0,
+	.cra_alignmask		= 0x1,
 	.cra_type		= &crypto_ablkcipher_type,
 	.cra_module		= THIS_MODULE,
 	.cra_init		= atmel_tdes_cra_init,
@@ -945,7 +1178,7 @@ static struct crypto_alg tdes_algs[] = {
 	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
 	.cra_blocksize		= CFB32_BLOCK_SIZE,
 	.cra_ctxsize		= sizeof(struct atmel_tdes_ctx),
-	.cra_alignmask		= 0,
+	.cra_alignmask		= 0x3,
 	.cra_type		= &crypto_ablkcipher_type,
 	.cra_module		= THIS_MODULE,
 	.cra_init		= atmel_tdes_cra_init,
@@ -966,7 +1199,7 @@ static struct crypto_alg tdes_algs[] = {
 	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
 	.cra_blocksize		= DES_BLOCK_SIZE,
 	.cra_ctxsize		= sizeof(struct atmel_tdes_ctx),
-	.cra_alignmask		= 0,
+	.cra_alignmask		= 0x7,
 	.cra_type		= &crypto_ablkcipher_type,
 	.cra_module		= THIS_MODULE,
 	.cra_init		= atmel_tdes_cra_init,
@@ -994,14 +1227,24 @@ static void atmel_tdes_done_task(unsigned long data)
 	struct atmel_tdes_dev *dd = (struct atmel_tdes_dev *) data;
 	int err;
 
-	err = atmel_tdes_crypt_dma_stop(dd);
+	if (!(dd->flags & TDES_FLAGS_DMA))
+		err = atmel_tdes_crypt_pdc_stop(dd);
+	else
+		err = atmel_tdes_crypt_dma_stop(dd);
 
 	err = dd->err ? : err;
 
 	if (dd->total && !err) {
-		err = atmel_tdes_crypt_dma_start(dd);
+		if (dd->flags & TDES_FLAGS_FAST) {
+			dd->in_sg = sg_next(dd->in_sg);
+			dd->out_sg = sg_next(dd->out_sg);
+			if (!dd->in_sg || !dd->out_sg)
+				err = -EINVAL;
+		}
 		if (!err)
-			return;
+			err = atmel_tdes_crypt_start(dd);
+		if (!err)
+			return; /* DMA started. Not fininishing. */
 	}
 
 	atmel_tdes_finish_req(dd, err);
@@ -1053,9 +1296,31 @@ err_tdes_algs:
 	return err;
 }
 
+static void atmel_tdes_get_cap(struct atmel_tdes_dev *dd)
+{
+
+	dd->caps.has_dma = 0;
+	dd->caps.has_cfb_3keys = 0;
+
+	/* keep only major version number */
+	switch (dd->hw_version & 0xf00) {
+	case 0x700:
+		dd->caps.has_dma = 1;
+		dd->caps.has_cfb_3keys = 1;
+		break;
+	case 0x600:
+		break;
+	default:
+		dev_warn(dd->dev,
+				"Unmanaged tdes version, set minimum capabilities\n");
+		break;
+	}
+}
+
 static int atmel_tdes_probe(struct platform_device *pdev)
 {
 	struct atmel_tdes_dev *tdes_dd;
+	struct crypto_platform_data	*pdata;
 	struct device *dev = &pdev->dev;
 	struct resource *tdes_res;
 	unsigned long tdes_phys_size;
@@ -1109,7 +1374,7 @@ static int atmel_tdes_probe(struct platform_device *pdev)
 	}
 
 	/* Initializing the clock */
-	tdes_dd->iclk = clk_get(&pdev->dev, NULL);
+	tdes_dd->iclk = clk_get(&pdev->dev, "tdes_clk");
 	if (IS_ERR(tdes_dd->iclk)) {
 		dev_err(dev, "clock intialization failed.\n");
 		err = PTR_ERR(tdes_dd->iclk);
@@ -1123,9 +1388,25 @@ static int atmel_tdes_probe(struct platform_device *pdev)
 		goto tdes_io_err;
 	}
 
-	err = atmel_tdes_dma_init(tdes_dd);
+	atmel_tdes_hw_version_init(tdes_dd);
+
+	atmel_tdes_get_cap(tdes_dd);
+
+	err = atmel_tdes_buff_init(tdes_dd);
 	if (err)
-		goto err_tdes_dma;
+		goto err_tdes_buff;
+
+	if (tdes_dd->caps.has_dma) {
+		pdata = pdev->dev.platform_data;
+		if (!pdata) {
+			dev_err(&pdev->dev, "platform data not available\n");
+			err = -ENXIO;
+			goto err_pdata;
+		}
+		err = atmel_tdes_dma_init(tdes_dd, pdata);
+		if (err)
+			goto err_tdes_dma;
+	}
 
 	spin_lock(&atmel_tdes.lock);
 	list_add_tail(&tdes_dd->list, &atmel_tdes.dev_list);
@@ -1143,8 +1424,12 @@ err_algs:
 	spin_lock(&atmel_tdes.lock);
 	list_del(&tdes_dd->list);
 	spin_unlock(&atmel_tdes.lock);
-	atmel_tdes_dma_cleanup(tdes_dd);
+	if (tdes_dd->caps.has_dma)
+		atmel_tdes_dma_cleanup(tdes_dd);
 err_tdes_dma:
+err_pdata:
+	atmel_tdes_buff_cleanup(tdes_dd);
+err_tdes_buff:
 	iounmap(tdes_dd->io_base);
 tdes_io_err:
 	clk_put(tdes_dd->iclk);
@@ -1178,7 +1463,10 @@ static int atmel_tdes_remove(struct platform_device *pdev)
 	tasklet_kill(&tdes_dd->done_task);
 	tasklet_kill(&tdes_dd->queue_task);
 
-	atmel_tdes_dma_cleanup(tdes_dd);
+	if (tdes_dd->caps.has_dma)
+		atmel_tdes_dma_cleanup(tdes_dd);
+
+	atmel_tdes_buff_cleanup(tdes_dd);
 
 	iounmap(tdes_dd->io_base);
 
diff --git a/drivers/crypto/bfin_crc.c b/drivers/crypto/bfin_crc.c
index 827913d..d797f31 100644
--- a/drivers/crypto/bfin_crc.c
+++ b/drivers/crypto/bfin_crc.c
@@ -151,7 +151,7 @@ static int bfin_crypto_crc_init(struct ahash_request *req)
 	struct bfin_crypto_crc_reqctx *ctx = ahash_request_ctx(req);
 	struct bfin_crypto_crc *crc;
 
-	dev_dbg(crc->dev, "crc_init\n");
+	dev_dbg(ctx->crc->dev, "crc_init\n");
 	spin_lock_bh(&crc_list.lock);
 	list_for_each_entry(crc, &crc_list.dev_list, list) {
 		crc_ctx->crc = crc;
@@ -160,7 +160,7 @@ static int bfin_crypto_crc_init(struct ahash_request *req)
 	spin_unlock_bh(&crc_list.lock);
 
 	if (sg_count(req->src) > CRC_MAX_DMA_DESC) {
-		dev_dbg(crc->dev, "init: requested sg list is too big > %d\n",
+		dev_dbg(ctx->crc->dev, "init: requested sg list is too big > %d\n",
 			CRC_MAX_DMA_DESC);
 		return -EINVAL;
 	}
@@ -175,7 +175,7 @@ static int bfin_crypto_crc_init(struct ahash_request *req)
 	/* init crc results */
 	put_unaligned_le32(crc_ctx->key, req->result);
 
-	dev_dbg(crc->dev, "init: digest size: %d\n",
+	dev_dbg(ctx->crc->dev, "init: digest size: %d\n",
 		crypto_ahash_digestsize(tfm));
 
 	return bfin_crypto_crc_init_hw(crc, crc_ctx->key);
diff --git a/drivers/crypto/caam/Kconfig b/drivers/crypto/caam/Kconfig
index 65c7668..b44091c 100644
--- a/drivers/crypto/caam/Kconfig
+++ b/drivers/crypto/caam/Kconfig
@@ -78,7 +78,7 @@ config CRYPTO_DEV_FSL_CAAM_AHASH_API
 	tristate "Register hash algorithm implementations with Crypto API"
 	depends on CRYPTO_DEV_FSL_CAAM
 	default y
-	select CRYPTO_AHASH
+	select CRYPTO_HASH
 	help
 	  Selecting this will offload ahash for users of the
 	  scatterlist crypto API to the SEC4 via job ring.
diff --git a/drivers/crypto/caam/caamalg.c b/drivers/crypto/caam/caamalg.c
index cf268b1..765fdf5 100644
--- a/drivers/crypto/caam/caamalg.c
+++ b/drivers/crypto/caam/caamalg.c
@@ -1693,6 +1693,7 @@ static struct caam_alg_template driver_algs[] = {
 		.name = "authenc(hmac(sha224),cbc(aes))",
 		.driver_name = "authenc-hmac-sha224-cbc-aes-caam",
 		.blocksize = AES_BLOCK_SIZE,
+		.type = CRYPTO_ALG_TYPE_AEAD,
 		.template_aead = {
 			.setkey = aead_setkey,
 			.setauthsize = aead_setauthsize,
@@ -1732,6 +1733,7 @@ static struct caam_alg_template driver_algs[] = {
 		.name = "authenc(hmac(sha384),cbc(aes))",
 		.driver_name = "authenc-hmac-sha384-cbc-aes-caam",
 		.blocksize = AES_BLOCK_SIZE,
+		.type = CRYPTO_ALG_TYPE_AEAD,
 		.template_aead = {
 			.setkey = aead_setkey,
 			.setauthsize = aead_setauthsize,
@@ -1810,6 +1812,7 @@ static struct caam_alg_template driver_algs[] = {
 		.name = "authenc(hmac(sha224),cbc(des3_ede))",
 		.driver_name = "authenc-hmac-sha224-cbc-des3_ede-caam",
 		.blocksize = DES3_EDE_BLOCK_SIZE,
+		.type = CRYPTO_ALG_TYPE_AEAD,
 		.template_aead = {
 			.setkey = aead_setkey,
 			.setauthsize = aead_setauthsize,
@@ -1849,6 +1852,7 @@ static struct caam_alg_template driver_algs[] = {
 		.name = "authenc(hmac(sha384),cbc(des3_ede))",
 		.driver_name = "authenc-hmac-sha384-cbc-des3_ede-caam",
 		.blocksize = DES3_EDE_BLOCK_SIZE,
+		.type = CRYPTO_ALG_TYPE_AEAD,
 		.template_aead = {
 			.setkey = aead_setkey,
 			.setauthsize = aead_setauthsize,
@@ -1926,6 +1930,7 @@ static struct caam_alg_template driver_algs[] = {
 		.name = "authenc(hmac(sha224),cbc(des))",
 		.driver_name = "authenc-hmac-sha224-cbc-des-caam",
 		.blocksize = DES_BLOCK_SIZE,
+		.type = CRYPTO_ALG_TYPE_AEAD,
 		.template_aead = {
 			.setkey = aead_setkey,
 			.setauthsize = aead_setauthsize,
@@ -1965,6 +1970,7 @@ static struct caam_alg_template driver_algs[] = {
 		.name = "authenc(hmac(sha384),cbc(des))",
 		.driver_name = "authenc-hmac-sha384-cbc-des-caam",
 		.blocksize = DES_BLOCK_SIZE,
+		.type = CRYPTO_ALG_TYPE_AEAD,
 		.template_aead = {
 			.setkey = aead_setkey,
 			.setauthsize = aead_setauthsize,
diff --git a/drivers/crypto/caam/caamhash.c b/drivers/crypto/caam/caamhash.c
index 32aba7a..5996521 100644
--- a/drivers/crypto/caam/caamhash.c
+++ b/drivers/crypto/caam/caamhash.c
@@ -411,7 +411,7 @@ static int ahash_set_sh_desc(struct crypto_ahash *ahash)
 	return 0;
 }
 
-static u32 gen_split_hash_key(struct caam_hash_ctx *ctx, const u8 *key_in,
+static int gen_split_hash_key(struct caam_hash_ctx *ctx, const u8 *key_in,
 			      u32 keylen)
 {
 	return gen_split_key(ctx->jrdev, ctx->key, ctx->split_key_len,
@@ -420,7 +420,7 @@ static u32 gen_split_hash_key(struct caam_hash_ctx *ctx, const u8 *key_in,
 }
 
 /* Digest hash size if it is too large */
-static u32 hash_digest_key(struct caam_hash_ctx *ctx, const u8 *key_in,
+static int hash_digest_key(struct caam_hash_ctx *ctx, const u8 *key_in,
 			   u32 *keylen, u8 *key_out, u32 digestsize)
 {
 	struct device *jrdev = ctx->jrdev;
diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c
index 1c56f63..6e94bcd 100644
--- a/drivers/crypto/caam/ctrl.c
+++ b/drivers/crypto/caam/ctrl.c
@@ -66,7 +66,7 @@ static void build_instantiation_desc(u32 *desc)
 
 	/*
 	 * load 1 to clear written reg:
-	 * resets the done interrrupt and returns the RNG to idle.
+	 * resets the done interrupt and returns the RNG to idle.
 	 */
 	append_load_imm_u32(desc, 1, LDST_SRCDST_WORD_CLRW);
 
@@ -304,6 +304,9 @@ static int caam_probe(struct platform_device *pdev)
 			caam_remove(pdev);
 			return ret;
 		}
+
+		/* Enable RDB bit so that RNG works faster */
+		setbits32(&topregs->ctrl.scfgr, SCFGR_RDBENABLE);
 	}
 
 	/* NOTE: RTIC detection ought to go here, around Si time */
diff --git a/drivers/crypto/caam/error.c b/drivers/crypto/caam/error.c
index 30b8f74..9f25f52 100644
--- a/drivers/crypto/caam/error.c
+++ b/drivers/crypto/caam/error.c
@@ -36,7 +36,7 @@ static void report_jump_idx(u32 status, char *outstr)
 
 static void report_ccb_status(u32 status, char *outstr)
 {
-	char *cha_id_list[] = {
+	static const char * const cha_id_list[] = {
 		"",
 		"AES",
 		"DES",
@@ -51,7 +51,7 @@ static void report_ccb_status(u32 status, char *outstr)
 		"ZUCE",
 		"ZUCA",
 	};
-	char *err_id_list[] = {
+	static const char * const err_id_list[] = {
 		"No error.",
 		"Mode error.",
 		"Data size error.",
@@ -69,7 +69,7 @@ static void report_ccb_status(u32 status, char *outstr)
 		"Invalid CHA combination was selected",
 		"Invalid CHA selected.",
 	};
-	char *rng_err_id_list[] = {
+	static const char * const rng_err_id_list[] = {
 		"",
 		"",
 		"",
@@ -117,7 +117,7 @@ static void report_jump_status(u32 status, char *outstr)
 
 static void report_deco_status(u32 status, char *outstr)
 {
-	const struct {
+	static const struct {
 		u8 value;
 		char *error_text;
 	} desc_error_list[] = {
@@ -245,7 +245,7 @@ static void report_cond_code_status(u32 status, char *outstr)
 
 char *caam_jr_strstatus(char *outstr, u32 status)
 {
-	struct stat_src {
+	static const struct stat_src {
 		void (*report_ssed)(u32 status, char *outstr);
 		char *error;
 	} status_src[] = {
diff --git a/drivers/crypto/caam/key_gen.c b/drivers/crypto/caam/key_gen.c
index f6dba10..87138d2 100644
--- a/drivers/crypto/caam/key_gen.c
+++ b/drivers/crypto/caam/key_gen.c
@@ -44,7 +44,7 @@ Split key generation-----------------------------------------------
 [06] 0x64260028    fifostr: class2 mdsplit-jdk len=40
 			@0xffe04000
 */
-u32 gen_split_key(struct device *jrdev, u8 *key_out, int split_key_len,
+int gen_split_key(struct device *jrdev, u8 *key_out, int split_key_len,
 		  int split_key_pad_len, const u8 *key_in, u32 keylen,
 		  u32 alg_op)
 {
diff --git a/drivers/crypto/caam/key_gen.h b/drivers/crypto/caam/key_gen.h
index d95d290..c5588f6 100644
--- a/drivers/crypto/caam/key_gen.h
+++ b/drivers/crypto/caam/key_gen.h
@@ -12,6 +12,6 @@ struct split_key_result {
 
 void split_key_done(struct device *dev, u32 *desc, u32 err, void *context);
 
-u32 gen_split_key(struct device *jrdev, u8 *key_out, int split_key_len,
+int gen_split_key(struct device *jrdev, u8 *key_out, int split_key_len,
 		    int split_key_pad_len, const u8 *key_in, u32 keylen,
 		    u32 alg_op);
diff --git a/drivers/crypto/caam/regs.h b/drivers/crypto/caam/regs.h
index 3223fc6..cd6feda 100644
--- a/drivers/crypto/caam/regs.h
+++ b/drivers/crypto/caam/regs.h
@@ -252,7 +252,8 @@ struct caam_ctrl {
 	/* Read/Writable					        */
 	u32 rsvd1;
 	u32 mcr;		/* MCFG      Master Config Register  */
-	u32 rsvd2[2];
+	u32 rsvd2;
+	u32 scfgr;		/* SCFGR, Security Config Register */
 
 	/* Bus Access Configuration Section			010-11f */
 	/* Read/Writable                                                */
@@ -299,6 +300,7 @@ struct caam_ctrl {
 #define MCFGR_WDFAIL		0x20000000 /* DECO watchdog force-fail */
 #define MCFGR_DMA_RESET		0x10000000
 #define MCFGR_LONG_PTR		0x00010000 /* Use >32-bit desc addressing */
+#define SCFGR_RDBENABLE		0x00000400
 
 /* AXI read cache control */
 #define MCFGR_ARCACHE_SHIFT	12
diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c
index 6aa425f..ee15b0f 100644
--- a/drivers/crypto/omap-aes.c
+++ b/drivers/crypto/omap-aes.c
@@ -636,7 +636,7 @@ static void omap_aes_finish_req(struct omap_aes_dev *dd, int err)
 
 	pr_debug("err: %d\n", err);
 
-	pm_runtime_put_sync(dd->dev);
+	pm_runtime_put(dd->dev);
 	dd->flags &= ~FLAGS_BUSY;
 
 	req->base.complete(&req->base, err);
@@ -1248,18 +1248,7 @@ static struct platform_driver omap_aes_driver = {
 	},
 };
 
-static int __init omap_aes_mod_init(void)
-{
-	return  platform_driver_register(&omap_aes_driver);
-}
-
-static void __exit omap_aes_mod_exit(void)
-{
-	platform_driver_unregister(&omap_aes_driver);
-}
-
-module_init(omap_aes_mod_init);
-module_exit(omap_aes_mod_exit);
+module_platform_driver(omap_aes_driver);
 
 MODULE_DESCRIPTION("OMAP AES hw acceleration support.");
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c
index 3d1611f..a1e1b47 100644
--- a/drivers/crypto/omap-sham.c
+++ b/drivers/crypto/omap-sham.c
@@ -923,7 +923,7 @@ static void omap_sham_finish_req(struct ahash_request *req, int err)
 	dd->flags &= ~(BIT(FLAGS_BUSY) | BIT(FLAGS_FINAL) | BIT(FLAGS_CPU) |
 			BIT(FLAGS_DMA_READY) | BIT(FLAGS_OUTPUT_READY));
 
-	pm_runtime_put_sync(dd->dev);
+	pm_runtime_put(dd->dev);
 
 	if (req->base.complete)
 		req->base.complete(&req->base, err);
@@ -1813,18 +1813,7 @@ static struct platform_driver omap_sham_driver = {
 	},
 };
 
-static int __init omap_sham_mod_init(void)
-{
-	return platform_driver_register(&omap_sham_driver);
-}
-
-static void __exit omap_sham_mod_exit(void)
-{
-	platform_driver_unregister(&omap_sham_driver);
-}
-
-module_init(omap_sham_mod_init);
-module_exit(omap_sham_mod_exit);
+module_platform_driver(omap_sham_driver);
 
 MODULE_DESCRIPTION("OMAP SHA1/MD5 hw acceleration support.");
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/crypto/picoxcell_crypto.c b/drivers/crypto/picoxcell_crypto.c
index 2096d46..ac30724 100644
--- a/drivers/crypto/picoxcell_crypto.c
+++ b/drivers/crypto/picoxcell_crypto.c
@@ -1688,8 +1688,6 @@ static const struct of_device_id spacc_of_id_table[] = {
 	{ .compatible = "picochip,spacc-l2" },
 	{}
 };
-#else /* CONFIG_OF */
-#define spacc_of_id_table NULL
 #endif /* CONFIG_OF */
 
 static bool spacc_is_compatible(struct platform_device *pdev,
@@ -1874,7 +1872,7 @@ static struct platform_driver spacc_driver = {
 #ifdef CONFIG_PM
 		.pm	= &spacc_pm_ops,
 #endif /* CONFIG_PM */
-		.of_match_table	= spacc_of_id_table,
+		.of_match_table	= of_match_ptr(spacc_of_id_table),
 	},
 	.id_table	= spacc_id_table,
 };
diff --git a/drivers/crypto/sahara.c b/drivers/crypto/sahara.c
new file mode 100644
index 0000000..a97bb6c
--- /dev/null
+++ b/drivers/crypto/sahara.c
@@ -0,0 +1,1070 @@
+/*
+ * Cryptographic API.
+ *
+ * Support for SAHARA cryptographic accelerator.
+ *
+ * Copyright (c) 2013 Vista Silicon S.L.
+ * Author: Javier Martin <javier.martin@vista-silicon.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.
+ *
+ * Based on omap-aes.c and tegra-aes.c
+ */
+
+#include <crypto/algapi.h>
+#include <crypto/aes.h>
+
+#include <linux/clk.h>
+#include <linux/crypto.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#define SAHARA_NAME "sahara"
+#define SAHARA_VERSION_3	3
+#define SAHARA_TIMEOUT_MS	1000
+#define SAHARA_MAX_HW_DESC	2
+#define SAHARA_MAX_HW_LINK	20
+
+#define FLAGS_MODE_MASK		0x000f
+#define FLAGS_ENCRYPT		BIT(0)
+#define FLAGS_CBC		BIT(1)
+#define FLAGS_NEW_KEY		BIT(3)
+#define FLAGS_BUSY		4
+
+#define SAHARA_HDR_BASE			0x00800000
+#define SAHARA_HDR_SKHA_ALG_AES	0
+#define SAHARA_HDR_SKHA_OP_ENC		(1 << 2)
+#define SAHARA_HDR_SKHA_MODE_ECB	(0 << 3)
+#define SAHARA_HDR_SKHA_MODE_CBC	(1 << 3)
+#define SAHARA_HDR_FORM_DATA		(5 << 16)
+#define SAHARA_HDR_FORM_KEY		(8 << 16)
+#define SAHARA_HDR_LLO			(1 << 24)
+#define SAHARA_HDR_CHA_SKHA		(1 << 28)
+#define SAHARA_HDR_CHA_MDHA		(2 << 28)
+#define SAHARA_HDR_PARITY_BIT		(1 << 31)
+
+/* SAHARA can only process one request at a time */
+#define SAHARA_QUEUE_LENGTH	1
+
+#define SAHARA_REG_VERSION	0x00
+#define SAHARA_REG_DAR		0x04
+#define SAHARA_REG_CONTROL	0x08
+#define		SAHARA_CONTROL_SET_THROTTLE(x)	(((x) & 0xff) << 24)
+#define		SAHARA_CONTROL_SET_MAXBURST(x)	(((x) & 0xff) << 16)
+#define		SAHARA_CONTROL_RNG_AUTORSD	(1 << 7)
+#define		SAHARA_CONTROL_ENABLE_INT	(1 << 4)
+#define SAHARA_REG_CMD		0x0C
+#define		SAHARA_CMD_RESET		(1 << 0)
+#define		SAHARA_CMD_CLEAR_INT		(1 << 8)
+#define		SAHARA_CMD_CLEAR_ERR		(1 << 9)
+#define		SAHARA_CMD_SINGLE_STEP		(1 << 10)
+#define		SAHARA_CMD_MODE_BATCH		(1 << 16)
+#define		SAHARA_CMD_MODE_DEBUG		(1 << 18)
+#define	SAHARA_REG_STATUS	0x10
+#define		SAHARA_STATUS_GET_STATE(x)	((x) & 0x7)
+#define			SAHARA_STATE_IDLE	0
+#define			SAHARA_STATE_BUSY	1
+#define			SAHARA_STATE_ERR	2
+#define			SAHARA_STATE_FAULT	3
+#define			SAHARA_STATE_COMPLETE	4
+#define			SAHARA_STATE_COMP_FLAG	(1 << 2)
+#define		SAHARA_STATUS_DAR_FULL		(1 << 3)
+#define		SAHARA_STATUS_ERROR		(1 << 4)
+#define		SAHARA_STATUS_SECURE		(1 << 5)
+#define		SAHARA_STATUS_FAIL		(1 << 6)
+#define		SAHARA_STATUS_INIT		(1 << 7)
+#define		SAHARA_STATUS_RNG_RESEED	(1 << 8)
+#define		SAHARA_STATUS_ACTIVE_RNG	(1 << 9)
+#define		SAHARA_STATUS_ACTIVE_MDHA	(1 << 10)
+#define		SAHARA_STATUS_ACTIVE_SKHA	(1 << 11)
+#define		SAHARA_STATUS_MODE_BATCH	(1 << 16)
+#define		SAHARA_STATUS_MODE_DEDICATED	(1 << 17)
+#define		SAHARA_STATUS_MODE_DEBUG	(1 << 18)
+#define		SAHARA_STATUS_GET_ISTATE(x)	(((x) >> 24) & 0xff)
+#define SAHARA_REG_ERRSTATUS	0x14
+#define		SAHARA_ERRSTATUS_GET_SOURCE(x)	((x) & 0xf)
+#define			SAHARA_ERRSOURCE_CHA	14
+#define			SAHARA_ERRSOURCE_DMA	15
+#define		SAHARA_ERRSTATUS_DMA_DIR	(1 << 8)
+#define		SAHARA_ERRSTATUS_GET_DMASZ(x)(((x) >> 9) & 0x3)
+#define		SAHARA_ERRSTATUS_GET_DMASRC(x) (((x) >> 13) & 0x7)
+#define		SAHARA_ERRSTATUS_GET_CHASRC(x)	(((x) >> 16) & 0xfff)
+#define		SAHARA_ERRSTATUS_GET_CHAERR(x)	(((x) >> 28) & 0x3)
+#define SAHARA_REG_FADDR	0x18
+#define SAHARA_REG_CDAR		0x1C
+#define SAHARA_REG_IDAR		0x20
+
+struct sahara_hw_desc {
+	u32		hdr;
+	u32		len1;
+	dma_addr_t	p1;
+	u32		len2;
+	dma_addr_t	p2;
+	dma_addr_t	next;
+};
+
+struct sahara_hw_link {
+	u32		len;
+	dma_addr_t	p;
+	dma_addr_t	next;
+};
+
+struct sahara_ctx {
+	struct sahara_dev *dev;
+	unsigned long flags;
+	int keylen;
+	u8 key[AES_KEYSIZE_128];
+	struct crypto_ablkcipher *fallback;
+};
+
+struct sahara_aes_reqctx {
+	unsigned long mode;
+};
+
+struct sahara_dev {
+	struct device		*device;
+	void __iomem		*regs_base;
+	struct clk		*clk_ipg;
+	struct clk		*clk_ahb;
+
+	struct sahara_ctx	*ctx;
+	spinlock_t		lock;
+	struct crypto_queue	queue;
+	unsigned long		flags;
+
+	struct tasklet_struct	done_task;
+	struct tasklet_struct	queue_task;
+
+	struct sahara_hw_desc	*hw_desc[SAHARA_MAX_HW_DESC];
+	dma_addr_t		hw_phys_desc[SAHARA_MAX_HW_DESC];
+
+	u8			*key_base;
+	dma_addr_t		key_phys_base;
+
+	u8			*iv_base;
+	dma_addr_t		iv_phys_base;
+
+	struct sahara_hw_link	*hw_link[SAHARA_MAX_HW_LINK];
+	dma_addr_t		hw_phys_link[SAHARA_MAX_HW_LINK];
+
+	struct ablkcipher_request *req;
+	size_t			total;
+	struct scatterlist	*in_sg;
+	unsigned int		nb_in_sg;
+	struct scatterlist	*out_sg;
+	unsigned int		nb_out_sg;
+
+	u32			error;
+	struct timer_list	watchdog;
+};
+
+static struct sahara_dev *dev_ptr;
+
+static inline void sahara_write(struct sahara_dev *dev, u32 data, u32 reg)
+{
+	writel(data, dev->regs_base + reg);
+}
+
+static inline unsigned int sahara_read(struct sahara_dev *dev, u32 reg)
+{
+	return readl(dev->regs_base + reg);
+}
+
+static u32 sahara_aes_key_hdr(struct sahara_dev *dev)
+{
+	u32 hdr = SAHARA_HDR_BASE | SAHARA_HDR_SKHA_ALG_AES |
+			SAHARA_HDR_FORM_KEY | SAHARA_HDR_LLO |
+			SAHARA_HDR_CHA_SKHA | SAHARA_HDR_PARITY_BIT;
+
+	if (dev->flags & FLAGS_CBC) {
+		hdr |= SAHARA_HDR_SKHA_MODE_CBC;
+		hdr ^= SAHARA_HDR_PARITY_BIT;
+	}
+
+	if (dev->flags & FLAGS_ENCRYPT) {
+		hdr |= SAHARA_HDR_SKHA_OP_ENC;
+		hdr ^= SAHARA_HDR_PARITY_BIT;
+	}
+
+	return hdr;
+}
+
+static u32 sahara_aes_data_link_hdr(struct sahara_dev *dev)
+{
+	return SAHARA_HDR_BASE | SAHARA_HDR_FORM_DATA |
+			SAHARA_HDR_CHA_SKHA | SAHARA_HDR_PARITY_BIT;
+}
+
+static int sahara_sg_length(struct scatterlist *sg,
+			    unsigned int total)
+{
+	int sg_nb;
+	unsigned int len;
+	struct scatterlist *sg_list;
+
+	sg_nb = 0;
+	sg_list = sg;
+
+	while (total) {
+		len = min(sg_list->length, total);
+
+		sg_nb++;
+		total -= len;
+
+		sg_list = sg_next(sg_list);
+		if (!sg_list)
+			total = 0;
+	}
+
+	return sg_nb;
+}
+
+static char *sahara_err_src[16] = {
+	"No error",
+	"Header error",
+	"Descriptor length error",
+	"Descriptor length or pointer error",
+	"Link length error",
+	"Link pointer error",
+	"Input buffer error",
+	"Output buffer error",
+	"Output buffer starvation",
+	"Internal state fault",
+	"General descriptor problem",
+	"Reserved",
+	"Descriptor address error",
+	"Link address error",
+	"CHA error",
+	"DMA error"
+};
+
+static char *sahara_err_dmasize[4] = {
+	"Byte transfer",
+	"Half-word transfer",
+	"Word transfer",
+	"Reserved"
+};
+
+static char *sahara_err_dmasrc[8] = {
+	"No error",
+	"AHB bus error",
+	"Internal IP bus error",
+	"Parity error",
+	"DMA crosses 256 byte boundary",
+	"DMA is busy",
+	"Reserved",
+	"DMA HW error"
+};
+
+static char *sahara_cha_errsrc[12] = {
+	"Input buffer non-empty",
+	"Illegal address",
+	"Illegal mode",
+	"Illegal data size",
+	"Illegal key size",
+	"Write during processing",
+	"CTX read during processing",
+	"HW error",
+	"Input buffer disabled/underflow",
+	"Output buffer disabled/overflow",
+	"DES key parity error",
+	"Reserved"
+};
+
+static char *sahara_cha_err[4] = { "No error", "SKHA", "MDHA", "RNG" };
+
+static void sahara_decode_error(struct sahara_dev *dev, unsigned int error)
+{
+	u8 source = SAHARA_ERRSTATUS_GET_SOURCE(error);
+	u16 chasrc = ffs(SAHARA_ERRSTATUS_GET_CHASRC(error));
+
+	dev_err(dev->device, "%s: Error Register = 0x%08x\n", __func__, error);
+
+	dev_err(dev->device, "	- %s.\n", sahara_err_src[source]);
+
+	if (source == SAHARA_ERRSOURCE_DMA) {
+		if (error & SAHARA_ERRSTATUS_DMA_DIR)
+			dev_err(dev->device, "		* DMA read.\n");
+		else
+			dev_err(dev->device, "		* DMA write.\n");
+
+		dev_err(dev->device, "		* %s.\n",
+		       sahara_err_dmasize[SAHARA_ERRSTATUS_GET_DMASZ(error)]);
+		dev_err(dev->device, "		* %s.\n",
+		       sahara_err_dmasrc[SAHARA_ERRSTATUS_GET_DMASRC(error)]);
+	} else if (source == SAHARA_ERRSOURCE_CHA) {
+		dev_err(dev->device, "		* %s.\n",
+			sahara_cha_errsrc[chasrc]);
+		dev_err(dev->device, "		* %s.\n",
+		       sahara_cha_err[SAHARA_ERRSTATUS_GET_CHAERR(error)]);
+	}
+	dev_err(dev->device, "\n");
+}
+
+static char *sahara_state[4] = { "Idle", "Busy", "Error", "HW Fault" };
+
+static void sahara_decode_status(struct sahara_dev *dev, unsigned int status)
+{
+	u8 state;
+
+	if (!IS_ENABLED(DEBUG))
+		return;
+
+	state = SAHARA_STATUS_GET_STATE(status);
+
+	dev_dbg(dev->device, "%s: Status Register = 0x%08x\n",
+		__func__, status);
+
+	dev_dbg(dev->device, "	- State = %d:\n", state);
+	if (state & SAHARA_STATE_COMP_FLAG)
+		dev_dbg(dev->device, "		* Descriptor completed. IRQ pending.\n");
+
+	dev_dbg(dev->device, "		* %s.\n",
+	       sahara_state[state & ~SAHARA_STATE_COMP_FLAG]);
+
+	if (status & SAHARA_STATUS_DAR_FULL)
+		dev_dbg(dev->device, "	- DAR Full.\n");
+	if (status & SAHARA_STATUS_ERROR)
+		dev_dbg(dev->device, "	- Error.\n");
+	if (status & SAHARA_STATUS_SECURE)
+		dev_dbg(dev->device, "	- Secure.\n");
+	if (status & SAHARA_STATUS_FAIL)
+		dev_dbg(dev->device, "	- Fail.\n");
+	if (status & SAHARA_STATUS_RNG_RESEED)
+		dev_dbg(dev->device, "	- RNG Reseed Request.\n");
+	if (status & SAHARA_STATUS_ACTIVE_RNG)
+		dev_dbg(dev->device, "	- RNG Active.\n");
+	if (status & SAHARA_STATUS_ACTIVE_MDHA)
+		dev_dbg(dev->device, "	- MDHA Active.\n");
+	if (status & SAHARA_STATUS_ACTIVE_SKHA)
+		dev_dbg(dev->device, "	- SKHA Active.\n");
+
+	if (status & SAHARA_STATUS_MODE_BATCH)
+		dev_dbg(dev->device, "	- Batch Mode.\n");
+	else if (status & SAHARA_STATUS_MODE_DEDICATED)
+		dev_dbg(dev->device, "	- Decidated Mode.\n");
+	else if (status & SAHARA_STATUS_MODE_DEBUG)
+		dev_dbg(dev->device, "	- Debug Mode.\n");
+
+	dev_dbg(dev->device, "	- Internal state = 0x%02x\n",
+	       SAHARA_STATUS_GET_ISTATE(status));
+
+	dev_dbg(dev->device, "Current DAR: 0x%08x\n",
+		sahara_read(dev, SAHARA_REG_CDAR));
+	dev_dbg(dev->device, "Initial DAR: 0x%08x\n\n",
+		sahara_read(dev, SAHARA_REG_IDAR));
+}
+
+static void sahara_dump_descriptors(struct sahara_dev *dev)
+{
+	int i;
+
+	if (!IS_ENABLED(DEBUG))
+		return;
+
+	for (i = 0; i < SAHARA_MAX_HW_DESC; i++) {
+		dev_dbg(dev->device, "Descriptor (%d) (0x%08x):\n",
+			i, dev->hw_phys_desc[i]);
+		dev_dbg(dev->device, "\thdr = 0x%08x\n", dev->hw_desc[i]->hdr);
+		dev_dbg(dev->device, "\tlen1 = %u\n", dev->hw_desc[i]->len1);
+		dev_dbg(dev->device, "\tp1 = 0x%08x\n", dev->hw_desc[i]->p1);
+		dev_dbg(dev->device, "\tlen2 = %u\n", dev->hw_desc[i]->len2);
+		dev_dbg(dev->device, "\tp2 = 0x%08x\n", dev->hw_desc[i]->p2);
+		dev_dbg(dev->device, "\tnext = 0x%08x\n",
+			dev->hw_desc[i]->next);
+	}
+	dev_dbg(dev->device, "\n");
+}
+
+static void sahara_dump_links(struct sahara_dev *dev)
+{
+	int i;
+
+	if (!IS_ENABLED(DEBUG))
+		return;
+
+	for (i = 0; i < SAHARA_MAX_HW_LINK; i++) {
+		dev_dbg(dev->device, "Link (%d) (0x%08x):\n",
+			i, dev->hw_phys_link[i]);
+		dev_dbg(dev->device, "\tlen = %u\n", dev->hw_link[i]->len);
+		dev_dbg(dev->device, "\tp = 0x%08x\n", dev->hw_link[i]->p);
+		dev_dbg(dev->device, "\tnext = 0x%08x\n",
+			dev->hw_link[i]->next);
+	}
+	dev_dbg(dev->device, "\n");
+}
+
+static void sahara_aes_done_task(unsigned long data)
+{
+	struct sahara_dev *dev = (struct sahara_dev *)data;
+
+	dma_unmap_sg(dev->device, dev->out_sg, dev->nb_out_sg,
+		DMA_TO_DEVICE);
+	dma_unmap_sg(dev->device, dev->in_sg, dev->nb_in_sg,
+		DMA_FROM_DEVICE);
+
+	spin_lock(&dev->lock);
+	clear_bit(FLAGS_BUSY, &dev->flags);
+	spin_unlock(&dev->lock);
+
+	dev->req->base.complete(&dev->req->base, dev->error);
+}
+
+void sahara_watchdog(unsigned long data)
+{
+	struct sahara_dev *dev = (struct sahara_dev *)data;
+	unsigned int err = sahara_read(dev, SAHARA_REG_ERRSTATUS);
+	unsigned int stat = sahara_read(dev, SAHARA_REG_STATUS);
+
+	sahara_decode_status(dev, stat);
+	sahara_decode_error(dev, err);
+	dev->error = -ETIMEDOUT;
+	sahara_aes_done_task(data);
+}
+
+static int sahara_hw_descriptor_create(struct sahara_dev *dev)
+{
+	struct sahara_ctx *ctx = dev->ctx;
+	struct scatterlist *sg;
+	int ret;
+	int i, j;
+
+	/* Copy new key if necessary */
+	if (ctx->flags & FLAGS_NEW_KEY) {
+		memcpy(dev->key_base, ctx->key, ctx->keylen);
+		ctx->flags &= ~FLAGS_NEW_KEY;
+
+		if (dev->flags & FLAGS_CBC) {
+			dev->hw_desc[0]->len1 = AES_BLOCK_SIZE;
+			dev->hw_desc[0]->p1 = dev->iv_phys_base;
+		} else {
+			dev->hw_desc[0]->len1 = 0;
+			dev->hw_desc[0]->p1 = 0;
+		}
+		dev->hw_desc[0]->len2 = ctx->keylen;
+		dev->hw_desc[0]->p2 = dev->key_phys_base;
+		dev->hw_desc[0]->next = dev->hw_phys_desc[1];
+	}
+	dev->hw_desc[0]->hdr = sahara_aes_key_hdr(dev);
+
+	dev->nb_in_sg = sahara_sg_length(dev->in_sg, dev->total);
+	dev->nb_out_sg = sahara_sg_length(dev->out_sg, dev->total);
+	if ((dev->nb_in_sg + dev->nb_out_sg) > SAHARA_MAX_HW_LINK) {
+		dev_err(dev->device, "not enough hw links (%d)\n",
+			dev->nb_in_sg + dev->nb_out_sg);
+		return -EINVAL;
+	}
+
+	ret = dma_map_sg(dev->device, dev->in_sg, dev->nb_in_sg,
+			 DMA_TO_DEVICE);
+	if (ret != dev->nb_in_sg) {
+		dev_err(dev->device, "couldn't map in sg\n");
+		goto unmap_in;
+	}
+	ret = dma_map_sg(dev->device, dev->out_sg, dev->nb_out_sg,
+			 DMA_FROM_DEVICE);
+	if (ret != dev->nb_out_sg) {
+		dev_err(dev->device, "couldn't map out sg\n");
+		goto unmap_out;
+	}
+
+	/* Create input links */
+	dev->hw_desc[1]->p1 = dev->hw_phys_link[0];
+	sg = dev->in_sg;
+	for (i = 0; i < dev->nb_in_sg; i++) {
+		dev->hw_link[i]->len = sg->length;
+		dev->hw_link[i]->p = sg->dma_address;
+		if (i == (dev->nb_in_sg - 1)) {
+			dev->hw_link[i]->next = 0;
+		} else {
+			dev->hw_link[i]->next = dev->hw_phys_link[i + 1];
+			sg = sg_next(sg);
+		}
+	}
+
+	/* Create output links */
+	dev->hw_desc[1]->p2 = dev->hw_phys_link[i];
+	sg = dev->out_sg;
+	for (j = i; j < dev->nb_out_sg + i; j++) {
+		dev->hw_link[j]->len = sg->length;
+		dev->hw_link[j]->p = sg->dma_address;
+		if (j == (dev->nb_out_sg + i - 1)) {
+			dev->hw_link[j]->next = 0;
+		} else {
+			dev->hw_link[j]->next = dev->hw_phys_link[j + 1];
+			sg = sg_next(sg);
+		}
+	}
+
+	/* Fill remaining fields of hw_desc[1] */
+	dev->hw_desc[1]->hdr = sahara_aes_data_link_hdr(dev);
+	dev->hw_desc[1]->len1 = dev->total;
+	dev->hw_desc[1]->len2 = dev->total;
+	dev->hw_desc[1]->next = 0;
+
+	sahara_dump_descriptors(dev);
+	sahara_dump_links(dev);
+
+	/* Start processing descriptor chain. */
+	mod_timer(&dev->watchdog,
+		  jiffies + msecs_to_jiffies(SAHARA_TIMEOUT_MS));
+	sahara_write(dev, dev->hw_phys_desc[0], SAHARA_REG_DAR);
+
+	return 0;
+
+unmap_out:
+	dma_unmap_sg(dev->device, dev->out_sg, dev->nb_out_sg,
+		DMA_TO_DEVICE);
+unmap_in:
+	dma_unmap_sg(dev->device, dev->in_sg, dev->nb_in_sg,
+		DMA_FROM_DEVICE);
+
+	return -EINVAL;
+}
+
+static void sahara_aes_queue_task(unsigned long data)
+{
+	struct sahara_dev *dev = (struct sahara_dev *)data;
+	struct crypto_async_request *async_req, *backlog;
+	struct sahara_ctx *ctx;
+	struct sahara_aes_reqctx *rctx;
+	struct ablkcipher_request *req;
+	int ret;
+
+	spin_lock(&dev->lock);
+	backlog = crypto_get_backlog(&dev->queue);
+	async_req = crypto_dequeue_request(&dev->queue);
+	if (!async_req)
+		clear_bit(FLAGS_BUSY, &dev->flags);
+	spin_unlock(&dev->lock);
+
+	if (!async_req)
+		return;
+
+	if (backlog)
+		backlog->complete(backlog, -EINPROGRESS);
+
+	req = ablkcipher_request_cast(async_req);
+
+	/* Request is ready to be dispatched by the device */
+	dev_dbg(dev->device,
+		"dispatch request (nbytes=%d, src=%p, dst=%p)\n",
+		req->nbytes, req->src, req->dst);
+
+	/* assign new request to device */
+	dev->req = req;
+	dev->total = req->nbytes;
+	dev->in_sg = req->src;
+	dev->out_sg = req->dst;
+
+	rctx = ablkcipher_request_ctx(req);
+	ctx = crypto_ablkcipher_ctx(crypto_ablkcipher_reqtfm(req));
+	rctx->mode &= FLAGS_MODE_MASK;
+	dev->flags = (dev->flags & ~FLAGS_MODE_MASK) | rctx->mode;
+
+	if ((dev->flags & FLAGS_CBC) && req->info)
+		memcpy(dev->iv_base, req->info, AES_KEYSIZE_128);
+
+	/* assign new context to device */
+	ctx->dev = dev;
+	dev->ctx = ctx;
+
+	ret = sahara_hw_descriptor_create(dev);
+	if (ret < 0) {
+		spin_lock(&dev->lock);
+		clear_bit(FLAGS_BUSY, &dev->flags);
+		spin_unlock(&dev->lock);
+		dev->req->base.complete(&dev->req->base, ret);
+	}
+}
+
+static int sahara_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
+			     unsigned int keylen)
+{
+	struct sahara_ctx *ctx = crypto_ablkcipher_ctx(tfm);
+	int ret;
+
+	ctx->keylen = keylen;
+
+	/* SAHARA only supports 128bit keys */
+	if (keylen == AES_KEYSIZE_128) {
+		memcpy(ctx->key, key, keylen);
+		ctx->flags |= FLAGS_NEW_KEY;
+		return 0;
+	}
+
+	if (keylen != AES_KEYSIZE_128 &&
+	    keylen != AES_KEYSIZE_192 && keylen != AES_KEYSIZE_256)
+		return -EINVAL;
+
+	/*
+	 * The requested key size is not supported by HW, do a fallback.
+	 */
+	ctx->fallback->base.crt_flags &= ~CRYPTO_TFM_REQ_MASK;
+	ctx->fallback->base.crt_flags |=
+		(tfm->base.crt_flags & CRYPTO_TFM_REQ_MASK);
+
+	ret = crypto_ablkcipher_setkey(ctx->fallback, key, keylen);
+	if (ret) {
+		struct crypto_tfm *tfm_aux = crypto_ablkcipher_tfm(tfm);
+
+		tfm_aux->crt_flags &= ~CRYPTO_TFM_RES_MASK;
+		tfm_aux->crt_flags |=
+			(ctx->fallback->base.crt_flags & CRYPTO_TFM_RES_MASK);
+	}
+	return ret;
+}
+
+static int sahara_aes_crypt(struct ablkcipher_request *req, unsigned long mode)
+{
+	struct sahara_ctx *ctx = crypto_ablkcipher_ctx(
+		crypto_ablkcipher_reqtfm(req));
+	struct sahara_aes_reqctx *rctx = ablkcipher_request_ctx(req);
+	struct sahara_dev *dev = dev_ptr;
+	int err = 0;
+	int busy;
+
+	dev_dbg(dev->device, "nbytes: %d, enc: %d, cbc: %d\n",
+		req->nbytes, !!(mode & FLAGS_ENCRYPT), !!(mode & FLAGS_CBC));
+
+	if (!IS_ALIGNED(req->nbytes, AES_BLOCK_SIZE)) {
+		dev_err(dev->device,
+			"request size is not exact amount of AES blocks\n");
+		return -EINVAL;
+	}
+
+	ctx->dev = dev;
+
+	rctx->mode = mode;
+	spin_lock_bh(&dev->lock);
+	err = ablkcipher_enqueue_request(&dev->queue, req);
+	busy = test_and_set_bit(FLAGS_BUSY, &dev->flags);
+	spin_unlock_bh(&dev->lock);
+
+	if (!busy)
+		tasklet_schedule(&dev->queue_task);
+
+	return err;
+}
+
+static int sahara_aes_ecb_encrypt(struct ablkcipher_request *req)
+{
+	struct crypto_tfm *tfm =
+		crypto_ablkcipher_tfm(crypto_ablkcipher_reqtfm(req));
+	struct sahara_ctx *ctx = crypto_ablkcipher_ctx(
+		crypto_ablkcipher_reqtfm(req));
+	int err;
+
+	if (unlikely(ctx->keylen != AES_KEYSIZE_128)) {
+		ablkcipher_request_set_tfm(req, ctx->fallback);
+		err = crypto_ablkcipher_encrypt(req);
+		ablkcipher_request_set_tfm(req, __crypto_ablkcipher_cast(tfm));
+		return err;
+	}
+
+	return sahara_aes_crypt(req, FLAGS_ENCRYPT);
+}
+
+static int sahara_aes_ecb_decrypt(struct ablkcipher_request *req)
+{
+	struct crypto_tfm *tfm =
+		crypto_ablkcipher_tfm(crypto_ablkcipher_reqtfm(req));
+	struct sahara_ctx *ctx = crypto_ablkcipher_ctx(
+		crypto_ablkcipher_reqtfm(req));
+	int err;
+
+	if (unlikely(ctx->keylen != AES_KEYSIZE_128)) {
+		ablkcipher_request_set_tfm(req, ctx->fallback);
+		err = crypto_ablkcipher_decrypt(req);
+		ablkcipher_request_set_tfm(req, __crypto_ablkcipher_cast(tfm));
+		return err;
+	}
+
+	return sahara_aes_crypt(req, 0);
+}
+
+static int sahara_aes_cbc_encrypt(struct ablkcipher_request *req)
+{
+	struct crypto_tfm *tfm =
+		crypto_ablkcipher_tfm(crypto_ablkcipher_reqtfm(req));
+	struct sahara_ctx *ctx = crypto_ablkcipher_ctx(
+		crypto_ablkcipher_reqtfm(req));
+	int err;
+
+	if (unlikely(ctx->keylen != AES_KEYSIZE_128)) {
+		ablkcipher_request_set_tfm(req, ctx->fallback);
+		err = crypto_ablkcipher_encrypt(req);
+		ablkcipher_request_set_tfm(req, __crypto_ablkcipher_cast(tfm));
+		return err;
+	}
+
+	return sahara_aes_crypt(req, FLAGS_ENCRYPT | FLAGS_CBC);
+}
+
+static int sahara_aes_cbc_decrypt(struct ablkcipher_request *req)
+{
+	struct crypto_tfm *tfm =
+		crypto_ablkcipher_tfm(crypto_ablkcipher_reqtfm(req));
+	struct sahara_ctx *ctx = crypto_ablkcipher_ctx(
+		crypto_ablkcipher_reqtfm(req));
+	int err;
+
+	if (unlikely(ctx->keylen != AES_KEYSIZE_128)) {
+		ablkcipher_request_set_tfm(req, ctx->fallback);
+		err = crypto_ablkcipher_decrypt(req);
+		ablkcipher_request_set_tfm(req, __crypto_ablkcipher_cast(tfm));
+		return err;
+	}
+
+	return sahara_aes_crypt(req, FLAGS_CBC);
+}
+
+static int sahara_aes_cra_init(struct crypto_tfm *tfm)
+{
+	const char *name = tfm->__crt_alg->cra_name;
+	struct sahara_ctx *ctx = crypto_tfm_ctx(tfm);
+
+	ctx->fallback = crypto_alloc_ablkcipher(name, 0,
+				CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK);
+	if (IS_ERR(ctx->fallback)) {
+		pr_err("Error allocating fallback algo %s\n", name);
+		return PTR_ERR(ctx->fallback);
+	}
+
+	tfm->crt_ablkcipher.reqsize = sizeof(struct sahara_aes_reqctx);
+
+	return 0;
+}
+
+static void sahara_aes_cra_exit(struct crypto_tfm *tfm)
+{
+	struct sahara_ctx *ctx = crypto_tfm_ctx(tfm);
+
+	if (ctx->fallback)
+		crypto_free_ablkcipher(ctx->fallback);
+	ctx->fallback = NULL;
+}
+
+static struct crypto_alg aes_algs[] = {
+{
+	.cra_name		= "ecb(aes)",
+	.cra_driver_name	= "sahara-ecb-aes",
+	.cra_priority		= 300,
+	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER |
+			CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK,
+	.cra_blocksize		= AES_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct sahara_ctx),
+	.cra_alignmask		= 0x0,
+	.cra_type		= &crypto_ablkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_init		= sahara_aes_cra_init,
+	.cra_exit		= sahara_aes_cra_exit,
+	.cra_u.ablkcipher = {
+		.min_keysize	= AES_MIN_KEY_SIZE ,
+		.max_keysize	= AES_MAX_KEY_SIZE,
+		.setkey		= sahara_aes_setkey,
+		.encrypt	= sahara_aes_ecb_encrypt,
+		.decrypt	= sahara_aes_ecb_decrypt,
+	}
+}, {
+	.cra_name		= "cbc(aes)",
+	.cra_driver_name	= "sahara-cbc-aes",
+	.cra_priority		= 300,
+	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER |
+			CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK,
+	.cra_blocksize		= AES_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct sahara_ctx),
+	.cra_alignmask		= 0x0,
+	.cra_type		= &crypto_ablkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_init		= sahara_aes_cra_init,
+	.cra_exit		= sahara_aes_cra_exit,
+	.cra_u.ablkcipher = {
+		.min_keysize	= AES_MIN_KEY_SIZE ,
+		.max_keysize	= AES_MAX_KEY_SIZE,
+		.ivsize		= AES_BLOCK_SIZE,
+		.setkey		= sahara_aes_setkey,
+		.encrypt	= sahara_aes_cbc_encrypt,
+		.decrypt	= sahara_aes_cbc_decrypt,
+	}
+}
+};
+
+static irqreturn_t sahara_irq_handler(int irq, void *data)
+{
+	struct sahara_dev *dev = (struct sahara_dev *)data;
+	unsigned int stat = sahara_read(dev, SAHARA_REG_STATUS);
+	unsigned int err = sahara_read(dev, SAHARA_REG_ERRSTATUS);
+
+	del_timer(&dev->watchdog);
+
+	sahara_write(dev, SAHARA_CMD_CLEAR_INT | SAHARA_CMD_CLEAR_ERR,
+		     SAHARA_REG_CMD);
+
+	sahara_decode_status(dev, stat);
+
+	if (SAHARA_STATUS_GET_STATE(stat) == SAHARA_STATE_BUSY) {
+		return IRQ_NONE;
+	} else if (SAHARA_STATUS_GET_STATE(stat) == SAHARA_STATE_COMPLETE) {
+		dev->error = 0;
+	} else {
+		sahara_decode_error(dev, err);
+		dev->error = -EINVAL;
+	}
+
+	tasklet_schedule(&dev->done_task);
+
+	return IRQ_HANDLED;
+}
+
+
+static int sahara_register_algs(struct sahara_dev *dev)
+{
+	int err, i, j;
+
+	for (i = 0; i < ARRAY_SIZE(aes_algs); i++) {
+		INIT_LIST_HEAD(&aes_algs[i].cra_list);
+		err = crypto_register_alg(&aes_algs[i]);
+		if (err)
+			goto err_aes_algs;
+	}
+
+	return 0;
+
+err_aes_algs:
+	for (j = 0; j < i; j++)
+		crypto_unregister_alg(&aes_algs[j]);
+
+	return err;
+}
+
+static void sahara_unregister_algs(struct sahara_dev *dev)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(aes_algs); i++)
+		crypto_unregister_alg(&aes_algs[i]);
+}
+
+static struct platform_device_id sahara_platform_ids[] = {
+	{ .name = "sahara-imx27" },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(platform, sahara_platform_ids);
+
+static struct of_device_id sahara_dt_ids[] = {
+	{ .compatible = "fsl,imx27-sahara" },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(platform, sahara_dt_ids);
+
+static int sahara_probe(struct platform_device *pdev)
+{
+	struct sahara_dev *dev;
+	struct resource *res;
+	u32 version;
+	int irq;
+	int err;
+	int i;
+
+	dev = devm_kzalloc(&pdev->dev, sizeof(struct sahara_dev), GFP_KERNEL);
+	if (dev == NULL) {
+		dev_err(&pdev->dev, "unable to alloc data struct.\n");
+		return -ENOMEM;
+	}
+
+	dev->device = &pdev->dev;
+	platform_set_drvdata(pdev, dev);
+
+	/* Get the base address */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "failed to get memory region resource\n");
+		return -ENODEV;
+	}
+
+	if (devm_request_mem_region(&pdev->dev, res->start,
+			resource_size(res), SAHARA_NAME) == NULL) {
+		dev_err(&pdev->dev, "failed to request memory region\n");
+		return -ENOENT;
+	}
+	dev->regs_base = devm_ioremap(&pdev->dev, res->start,
+				      resource_size(res));
+	if (!dev->regs_base) {
+		dev_err(&pdev->dev, "failed to ioremap address region\n");
+		return -ENOENT;
+	}
+
+	/* Get the IRQ */
+	irq = platform_get_irq(pdev,  0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "failed to get irq resource\n");
+		return irq;
+	}
+
+	if (devm_request_irq(&pdev->dev, irq, sahara_irq_handler,
+		0, SAHARA_NAME, dev) < 0) {
+		dev_err(&pdev->dev, "failed to request irq\n");
+		return -ENOENT;
+	}
+
+	/* clocks */
+	dev->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
+	if (IS_ERR(dev->clk_ipg)) {
+		dev_err(&pdev->dev, "Could not get ipg clock\n");
+		return PTR_ERR(dev->clk_ipg);
+	}
+
+	dev->clk_ahb = devm_clk_get(&pdev->dev, "ahb");
+	if (IS_ERR(dev->clk_ahb)) {
+		dev_err(&pdev->dev, "Could not get ahb clock\n");
+		return PTR_ERR(dev->clk_ahb);
+	}
+
+	/* Allocate HW descriptors */
+	dev->hw_desc[0] = dma_alloc_coherent(&pdev->dev,
+			SAHARA_MAX_HW_DESC * sizeof(struct sahara_hw_desc),
+			&dev->hw_phys_desc[0], GFP_KERNEL);
+	if (!dev->hw_desc[0]) {
+		dev_err(&pdev->dev, "Could not allocate hw descriptors\n");
+		return -ENOMEM;
+	}
+	dev->hw_desc[1] = dev->hw_desc[0] + 1;
+	dev->hw_phys_desc[1] = dev->hw_phys_desc[0] +
+				sizeof(struct sahara_hw_desc);
+
+	/* Allocate space for iv and key */
+	dev->key_base = dma_alloc_coherent(&pdev->dev, 2 * AES_KEYSIZE_128,
+				&dev->key_phys_base, GFP_KERNEL);
+	if (!dev->key_base) {
+		dev_err(&pdev->dev, "Could not allocate memory for key\n");
+		err = -ENOMEM;
+		goto err_key;
+	}
+	dev->iv_base = dev->key_base + AES_KEYSIZE_128;
+	dev->iv_phys_base = dev->key_phys_base + AES_KEYSIZE_128;
+
+	/* Allocate space for HW links */
+	dev->hw_link[0] = dma_alloc_coherent(&pdev->dev,
+			SAHARA_MAX_HW_LINK * sizeof(struct sahara_hw_link),
+			&dev->hw_phys_link[0], GFP_KERNEL);
+	if (!dev->hw_link) {
+		dev_err(&pdev->dev, "Could not allocate hw links\n");
+		err = -ENOMEM;
+		goto err_link;
+	}
+	for (i = 1; i < SAHARA_MAX_HW_LINK; i++) {
+		dev->hw_phys_link[i] = dev->hw_phys_link[i - 1] +
+					sizeof(struct sahara_hw_link);
+		dev->hw_link[i] = dev->hw_link[i - 1] + 1;
+	}
+
+	crypto_init_queue(&dev->queue, SAHARA_QUEUE_LENGTH);
+
+	dev_ptr = dev;
+
+	tasklet_init(&dev->queue_task, sahara_aes_queue_task,
+		     (unsigned long)dev);
+	tasklet_init(&dev->done_task, sahara_aes_done_task,
+		     (unsigned long)dev);
+
+	init_timer(&dev->watchdog);
+	dev->watchdog.function = &sahara_watchdog;
+	dev->watchdog.data = (unsigned long)dev;
+
+	clk_prepare_enable(dev->clk_ipg);
+	clk_prepare_enable(dev->clk_ahb);
+
+	version = sahara_read(dev, SAHARA_REG_VERSION);
+	if (version != SAHARA_VERSION_3) {
+		dev_err(&pdev->dev, "SAHARA version %d not supported\n",
+			version);
+		err = -ENODEV;
+		goto err_algs;
+	}
+
+	sahara_write(dev, SAHARA_CMD_RESET | SAHARA_CMD_MODE_BATCH,
+		     SAHARA_REG_CMD);
+	sahara_write(dev, SAHARA_CONTROL_SET_THROTTLE(0) |
+			SAHARA_CONTROL_SET_MAXBURST(8) |
+			SAHARA_CONTROL_RNG_AUTORSD |
+			SAHARA_CONTROL_ENABLE_INT,
+			SAHARA_REG_CONTROL);
+
+	err = sahara_register_algs(dev);
+	if (err)
+		goto err_algs;
+
+	dev_info(&pdev->dev, "SAHARA version %d initialized\n", version);
+
+	return 0;
+
+err_algs:
+	dma_free_coherent(&pdev->dev,
+			  SAHARA_MAX_HW_LINK * sizeof(struct sahara_hw_link),
+			  dev->hw_link[0], dev->hw_phys_link[0]);
+	clk_disable_unprepare(dev->clk_ipg);
+	clk_disable_unprepare(dev->clk_ahb);
+	dev_ptr = NULL;
+err_link:
+	dma_free_coherent(&pdev->dev,
+			  2 * AES_KEYSIZE_128,
+			  dev->key_base, dev->key_phys_base);
+err_key:
+	dma_free_coherent(&pdev->dev,
+			  SAHARA_MAX_HW_DESC * sizeof(struct sahara_hw_desc),
+			  dev->hw_desc[0], dev->hw_phys_desc[0]);
+
+	return err;
+}
+
+static int sahara_remove(struct platform_device *pdev)
+{
+	struct sahara_dev *dev = platform_get_drvdata(pdev);
+
+	dma_free_coherent(&pdev->dev,
+			  SAHARA_MAX_HW_LINK * sizeof(struct sahara_hw_link),
+			  dev->hw_link[0], dev->hw_phys_link[0]);
+	dma_free_coherent(&pdev->dev,
+			  2 * AES_KEYSIZE_128,
+			  dev->key_base, dev->key_phys_base);
+	dma_free_coherent(&pdev->dev,
+			  SAHARA_MAX_HW_DESC * sizeof(struct sahara_hw_desc),
+			  dev->hw_desc[0], dev->hw_phys_desc[0]);
+
+	tasklet_kill(&dev->done_task);
+	tasklet_kill(&dev->queue_task);
+
+	sahara_unregister_algs(dev);
+
+	clk_disable_unprepare(dev->clk_ipg);
+	clk_disable_unprepare(dev->clk_ahb);
+
+	dev_ptr = NULL;
+
+	return 0;
+}
+
+static struct platform_driver sahara_driver = {
+	.probe		= sahara_probe,
+	.remove		= sahara_remove,
+	.driver		= {
+		.name	= SAHARA_NAME,
+		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(sahara_dt_ids),
+	},
+	.id_table = sahara_platform_ids,
+};
+
+module_platform_driver(sahara_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Javier Martin <javier.martin@vista-silicon.com>");
+MODULE_DESCRIPTION("SAHARA2 HW crypto accelerator");
diff --git a/drivers/crypto/ux500/hash/hash_core.c b/drivers/crypto/ux500/hash/hash_core.c
index 632c333..d99b671 100644
--- a/drivers/crypto/ux500/hash/hash_core.c
+++ b/drivers/crypto/ux500/hash/hash_core.c
@@ -939,6 +939,7 @@ static int hash_dma_final(struct ahash_request *req)
 	if (!ctx->device->dma.nents) {
 		dev_err(device_data->dev, "[%s] "
 				"ctx->device->dma.nents = 0", __func__);
+		ret = ctx->device->dma.nents;
 		goto out;
 	}
 
@@ -946,6 +947,7 @@ static int hash_dma_final(struct ahash_request *req)
 	if (bytes_written != req->nbytes) {
 		dev_err(device_data->dev, "[%s] "
 				"hash_dma_write() failed!", __func__);
+		ret = bytes_written;
 		goto out;
 	}
 
@@ -1368,14 +1370,12 @@ static int hash_setkey(struct crypto_ahash *tfm,
 	/**
 	 * Freed in final.
 	 */
-	ctx->key = kmalloc(keylen, GFP_KERNEL);
+	ctx->key = kmemdup(key, keylen, GFP_KERNEL);
 	if (!ctx->key) {
 		pr_err(DEV_DBG_NAME " [%s] Failed to allocate ctx->key "
 		       "for %d\n", __func__, alg);
 		return -ENOMEM;
 	}
-
-	memcpy(ctx->key, key, keylen);
 	ctx->keylen = keylen;
 
 	return ret;
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 80b6997..aeaea32 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -83,6 +83,7 @@ config INTEL_IOP_ADMA
 
 config DW_DMAC
 	tristate "Synopsys DesignWare AHB DMA support"
+	depends on GENERIC_HARDIRQS
 	select DMA_ENGINE
 	default y if CPU_AT32AP7000
 	help
diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c
index 6e13f26..8415467 100644
--- a/drivers/dma/at_hdmac.c
+++ b/drivers/dma/at_hdmac.c
@@ -1407,7 +1407,7 @@ err_kfree:
 	return err;
 }
 
-static int __exit at_dma_remove(struct platform_device *pdev)
+static int at_dma_remove(struct platform_device *pdev)
 {
 	struct at_dma		*atdma = platform_get_drvdata(pdev);
 	struct dma_chan		*chan, *_chan;
@@ -1565,7 +1565,7 @@ static const struct dev_pm_ops at_dma_dev_pm_ops = {
 };
 
 static struct platform_driver at_dma_driver = {
-	.remove		= __exit_p(at_dma_remove),
+	.remove		= at_dma_remove,
 	.shutdown	= at_dma_shutdown,
 	.id_table	= atdma_devtypes,
 	.driver = {
diff --git a/drivers/dma/coh901318.c b/drivers/dma/coh901318.c
index 797940e..3b23061 100644
--- a/drivers/dma/coh901318.c
+++ b/drivers/dma/coh901318.c
@@ -2748,7 +2748,7 @@ static int __init coh901318_probe(struct platform_device *pdev)
 	return err;
 }
 
-static int __exit coh901318_remove(struct platform_device *pdev)
+static int coh901318_remove(struct platform_device *pdev)
 {
 	struct coh901318_base *base = platform_get_drvdata(pdev);
 
@@ -2760,7 +2760,7 @@ static int __exit coh901318_remove(struct platform_device *pdev)
 
 
 static struct platform_driver coh901318_driver = {
-	.remove = __exit_p(coh901318_remove),
+	.remove = coh901318_remove,
 	.driver = {
 		.name	= "coh901318",
 	},
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
index b2728d6..c121b03 100644
--- a/drivers/dma/dmaengine.c
+++ b/drivers/dma/dmaengine.c
@@ -174,7 +174,8 @@ static struct class dma_devclass = {
 #define dma_device_satisfies_mask(device, mask) \
 	__dma_device_satisfies_mask((device), &(mask))
 static int
-__dma_device_satisfies_mask(struct dma_device *device, dma_cap_mask_t *want)
+__dma_device_satisfies_mask(struct dma_device *device,
+			    const dma_cap_mask_t *want)
 {
 	dma_cap_mask_t has;
 
@@ -463,7 +464,8 @@ static void dma_channel_rebalance(void)
 		}
 }
 
-static struct dma_chan *private_candidate(dma_cap_mask_t *mask, struct dma_device *dev,
+static struct dma_chan *private_candidate(const dma_cap_mask_t *mask,
+					  struct dma_device *dev,
 					  dma_filter_fn fn, void *fn_param)
 {
 	struct dma_chan *chan;
@@ -505,7 +507,8 @@ static struct dma_chan *private_candidate(dma_cap_mask_t *mask, struct dma_devic
  * @fn: optional callback to disposition available channels
  * @fn_param: opaque parameter to pass to dma_filter_fn
  */
-struct dma_chan *__dma_request_channel(dma_cap_mask_t *mask, dma_filter_fn fn, void *fn_param)
+struct dma_chan *__dma_request_channel(const dma_cap_mask_t *mask,
+				       dma_filter_fn fn, void *fn_param)
 {
 	struct dma_device *device, *_d;
 	struct dma_chan *chan = NULL;
@@ -555,7 +558,7 @@ EXPORT_SYMBOL_GPL(__dma_request_channel);
  * @dev:	pointer to client device structure
  * @name:	slave channel name
  */
-struct dma_chan *dma_request_slave_channel(struct device *dev, char *name)
+struct dma_chan *dma_request_slave_channel(struct device *dev, const char *name)
 {
 	/* If device-tree is present get slave info from here */
 	if (dev->of_node)
diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c
index a2c8904..d8ce4ec 100644
--- a/drivers/dma/dmatest.c
+++ b/drivers/dma/dmatest.c
@@ -2,6 +2,7 @@
  * DMA Engine test module
  *
  * Copyright (C) 2007 Atmel Corporation
+ * Copyright (C) 2013 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
@@ -18,6 +19,10 @@
 #include <linux/random.h>
 #include <linux/slab.h>
 #include <linux/wait.h>
+#include <linux/ctype.h>
+#include <linux/debugfs.h>
+#include <linux/uaccess.h>
+#include <linux/seq_file.h>
 
 static unsigned int test_buf_size = 16384;
 module_param(test_buf_size, uint, S_IRUGO);
@@ -61,6 +66,9 @@ module_param(timeout, uint, S_IRUGO);
 MODULE_PARM_DESC(timeout, "Transfer Timeout in msec (default: 3000), "
 		 "Pass -1 for infinite timeout");
 
+/* Maximum amount of mismatched bytes in buffer to print */
+#define MAX_ERROR_COUNT		32
+
 /*
  * Initialization patterns. All bytes in the source buffer has bit 7
  * set, all bytes in the destination buffer has bit 7 cleared.
@@ -78,13 +86,65 @@ MODULE_PARM_DESC(timeout, "Transfer Timeout in msec (default: 3000), "
 #define PATTERN_OVERWRITE	0x20
 #define PATTERN_COUNT_MASK	0x1f
 
+enum dmatest_error_type {
+	DMATEST_ET_OK,
+	DMATEST_ET_MAP_SRC,
+	DMATEST_ET_MAP_DST,
+	DMATEST_ET_PREP,
+	DMATEST_ET_SUBMIT,
+	DMATEST_ET_TIMEOUT,
+	DMATEST_ET_DMA_ERROR,
+	DMATEST_ET_DMA_IN_PROGRESS,
+	DMATEST_ET_VERIFY,
+	DMATEST_ET_VERIFY_BUF,
+};
+
+struct dmatest_verify_buffer {
+	unsigned int	index;
+	u8		expected;
+	u8		actual;
+};
+
+struct dmatest_verify_result {
+	unsigned int			error_count;
+	struct dmatest_verify_buffer	data[MAX_ERROR_COUNT];
+	u8				pattern;
+	bool				is_srcbuf;
+};
+
+struct dmatest_thread_result {
+	struct list_head	node;
+	unsigned int		n;
+	unsigned int		src_off;
+	unsigned int		dst_off;
+	unsigned int		len;
+	enum dmatest_error_type	type;
+	union {
+		unsigned long			data;
+		dma_cookie_t			cookie;
+		enum dma_status			status;
+		int				error;
+		struct dmatest_verify_result	*vr;
+	};
+};
+
+struct dmatest_result {
+	struct list_head	node;
+	char			*name;
+	struct list_head	results;
+};
+
+struct dmatest_info;
+
 struct dmatest_thread {
 	struct list_head	node;
+	struct dmatest_info	*info;
 	struct task_struct	*task;
 	struct dma_chan		*chan;
 	u8			**srcs;
 	u8			**dsts;
 	enum dma_transaction_type type;
+	bool			done;
 };
 
 struct dmatest_chan {
@@ -93,25 +153,69 @@ struct dmatest_chan {
 	struct list_head	threads;
 };
 
-/*
- * These are protected by dma_list_mutex since they're only used by
- * the DMA filter function callback
+/**
+ * struct dmatest_params - test parameters.
+ * @buf_size:		size of the memcpy test buffer
+ * @channel:		bus ID of the channel to test
+ * @device:		bus ID of the DMA Engine to test
+ * @threads_per_chan:	number of threads to start per channel
+ * @max_channels:	maximum number of channels to use
+ * @iterations:		iterations before stopping test
+ * @xor_sources:	number of xor source buffers
+ * @pq_sources:		number of p+q source buffers
+ * @timeout:		transfer timeout in msec, -1 for infinite timeout
  */
-static LIST_HEAD(dmatest_channels);
-static unsigned int nr_channels;
+struct dmatest_params {
+	unsigned int	buf_size;
+	char		channel[20];
+	char		device[20];
+	unsigned int	threads_per_chan;
+	unsigned int	max_channels;
+	unsigned int	iterations;
+	unsigned int	xor_sources;
+	unsigned int	pq_sources;
+	int		timeout;
+};
 
-static bool dmatest_match_channel(struct dma_chan *chan)
+/**
+ * struct dmatest_info - test information.
+ * @params:		test parameters
+ * @lock:		access protection to the fields of this structure
+ */
+struct dmatest_info {
+	/* Test parameters */
+	struct dmatest_params	params;
+
+	/* Internal state */
+	struct list_head	channels;
+	unsigned int		nr_channels;
+	struct mutex		lock;
+
+	/* debugfs related stuff */
+	struct dentry		*root;
+	struct dmatest_params	dbgfs_params;
+
+	/* Test results */
+	struct list_head	results;
+	struct mutex		results_lock;
+};
+
+static struct dmatest_info test_info;
+
+static bool dmatest_match_channel(struct dmatest_params *params,
+		struct dma_chan *chan)
 {
-	if (test_channel[0] == '\0')
+	if (params->channel[0] == '\0')
 		return true;
-	return strcmp(dma_chan_name(chan), test_channel) == 0;
+	return strcmp(dma_chan_name(chan), params->channel) == 0;
 }
 
-static bool dmatest_match_device(struct dma_device *device)
+static bool dmatest_match_device(struct dmatest_params *params,
+		struct dma_device *device)
 {
-	if (test_device[0] == '\0')
+	if (params->device[0] == '\0')
 		return true;
-	return strcmp(dev_name(device->dev), test_device) == 0;
+	return strcmp(dev_name(device->dev), params->device) == 0;
 }
 
 static unsigned long dmatest_random(void)
@@ -122,7 +226,8 @@ static unsigned long dmatest_random(void)
 	return buf;
 }
 
-static void dmatest_init_srcs(u8 **bufs, unsigned int start, unsigned int len)
+static void dmatest_init_srcs(u8 **bufs, unsigned int start, unsigned int len,
+		unsigned int buf_size)
 {
 	unsigned int i;
 	u8 *buf;
@@ -133,13 +238,14 @@ static void dmatest_init_srcs(u8 **bufs, unsigned int start, unsigned int len)
 		for ( ; i < start + len; i++)
 			buf[i] = PATTERN_SRC | PATTERN_COPY
 				| (~i & PATTERN_COUNT_MASK);
-		for ( ; i < test_buf_size; i++)
+		for ( ; i < buf_size; i++)
 			buf[i] = PATTERN_SRC | (~i & PATTERN_COUNT_MASK);
 		buf++;
 	}
 }
 
-static void dmatest_init_dsts(u8 **bufs, unsigned int start, unsigned int len)
+static void dmatest_init_dsts(u8 **bufs, unsigned int start, unsigned int len,
+		unsigned int buf_size)
 {
 	unsigned int i;
 	u8 *buf;
@@ -150,40 +256,14 @@ static void dmatest_init_dsts(u8 **bufs, unsigned int start, unsigned int len)
 		for ( ; i < start + len; i++)
 			buf[i] = PATTERN_DST | PATTERN_OVERWRITE
 				| (~i & PATTERN_COUNT_MASK);
-		for ( ; i < test_buf_size; i++)
+		for ( ; i < buf_size; i++)
 			buf[i] = PATTERN_DST | (~i & PATTERN_COUNT_MASK);
 	}
 }
 
-static void dmatest_mismatch(u8 actual, u8 pattern, unsigned int index,
-		unsigned int counter, bool is_srcbuf)
-{
-	u8		diff = actual ^ pattern;
-	u8		expected = pattern | (~counter & PATTERN_COUNT_MASK);
-	const char	*thread_name = current->comm;
-
-	if (is_srcbuf)
-		pr_warning("%s: srcbuf[0x%x] overwritten!"
-				" Expected %02x, got %02x\n",
-				thread_name, index, expected, actual);
-	else if ((pattern & PATTERN_COPY)
-			&& (diff & (PATTERN_COPY | PATTERN_OVERWRITE)))
-		pr_warning("%s: dstbuf[0x%x] not copied!"
-				" Expected %02x, got %02x\n",
-				thread_name, index, expected, actual);
-	else if (diff & PATTERN_SRC)
-		pr_warning("%s: dstbuf[0x%x] was copied!"
-				" Expected %02x, got %02x\n",
-				thread_name, index, expected, actual);
-	else
-		pr_warning("%s: dstbuf[0x%x] mismatch!"
-				" Expected %02x, got %02x\n",
-				thread_name, index, expected, actual);
-}
-
-static unsigned int dmatest_verify(u8 **bufs, unsigned int start,
-		unsigned int end, unsigned int counter, u8 pattern,
-		bool is_srcbuf)
+static unsigned int dmatest_verify(struct dmatest_verify_result *vr, u8 **bufs,
+		unsigned int start, unsigned int end, unsigned int counter,
+		u8 pattern, bool is_srcbuf)
 {
 	unsigned int i;
 	unsigned int error_count = 0;
@@ -191,6 +271,7 @@ static unsigned int dmatest_verify(u8 **bufs, unsigned int start,
 	u8 expected;
 	u8 *buf;
 	unsigned int counter_orig = counter;
+	struct dmatest_verify_buffer *vb;
 
 	for (; (buf = *bufs); bufs++) {
 		counter = counter_orig;
@@ -198,18 +279,21 @@ static unsigned int dmatest_verify(u8 **bufs, unsigned int start,
 			actual = buf[i];
 			expected = pattern | (~counter & PATTERN_COUNT_MASK);
 			if (actual != expected) {
-				if (error_count < 32)
-					dmatest_mismatch(actual, pattern, i,
-							 counter, is_srcbuf);
+				if (error_count < MAX_ERROR_COUNT && vr) {
+					vb = &vr->data[error_count];
+					vb->index = i;
+					vb->expected = expected;
+					vb->actual = actual;
+				}
 				error_count++;
 			}
 			counter++;
 		}
 	}
 
-	if (error_count > 32)
+	if (error_count > MAX_ERROR_COUNT)
 		pr_warning("%s: %u errors suppressed\n",
-			current->comm, error_count - 32);
+			current->comm, error_count - MAX_ERROR_COUNT);
 
 	return error_count;
 }
@@ -249,6 +333,170 @@ static unsigned int min_odd(unsigned int x, unsigned int y)
 	return val % 2 ? val : val - 1;
 }
 
+static char *verify_result_get_one(struct dmatest_verify_result *vr,
+		unsigned int i)
+{
+	struct dmatest_verify_buffer *vb = &vr->data[i];
+	u8 diff = vb->actual ^ vr->pattern;
+	static char buf[512];
+	char *msg;
+
+	if (vr->is_srcbuf)
+		msg = "srcbuf overwritten!";
+	else if ((vr->pattern & PATTERN_COPY)
+			&& (diff & (PATTERN_COPY | PATTERN_OVERWRITE)))
+		msg = "dstbuf not copied!";
+	else if (diff & PATTERN_SRC)
+		msg = "dstbuf was copied!";
+	else
+		msg = "dstbuf mismatch!";
+
+	snprintf(buf, sizeof(buf) - 1, "%s [0x%x] Expected %02x, got %02x", msg,
+		 vb->index, vb->expected, vb->actual);
+
+	return buf;
+}
+
+static char *thread_result_get(const char *name,
+		struct dmatest_thread_result *tr)
+{
+	static const char * const messages[] = {
+		[DMATEST_ET_OK]			= "No errors",
+		[DMATEST_ET_MAP_SRC]		= "src mapping error",
+		[DMATEST_ET_MAP_DST]		= "dst mapping error",
+		[DMATEST_ET_PREP]		= "prep error",
+		[DMATEST_ET_SUBMIT]		= "submit error",
+		[DMATEST_ET_TIMEOUT]		= "test timed out",
+		[DMATEST_ET_DMA_ERROR]		=
+			"got completion callback (DMA_ERROR)",
+		[DMATEST_ET_DMA_IN_PROGRESS]	=
+			"got completion callback (DMA_IN_PROGRESS)",
+		[DMATEST_ET_VERIFY]		= "errors",
+		[DMATEST_ET_VERIFY_BUF]		= "verify errors",
+	};
+	static char buf[512];
+
+	snprintf(buf, sizeof(buf) - 1,
+		 "%s: #%u: %s with src_off=0x%x ""dst_off=0x%x len=0x%x (%lu)",
+		 name, tr->n, messages[tr->type], tr->src_off, tr->dst_off,
+		 tr->len, tr->data);
+
+	return buf;
+}
+
+static int thread_result_add(struct dmatest_info *info,
+		struct dmatest_result *r, enum dmatest_error_type type,
+		unsigned int n, unsigned int src_off, unsigned int dst_off,
+		unsigned int len, unsigned long data)
+{
+	struct dmatest_thread_result *tr;
+
+	tr = kzalloc(sizeof(*tr), GFP_KERNEL);
+	if (!tr)
+		return -ENOMEM;
+
+	tr->type = type;
+	tr->n = n;
+	tr->src_off = src_off;
+	tr->dst_off = dst_off;
+	tr->len = len;
+	tr->data = data;
+
+	mutex_lock(&info->results_lock);
+	list_add_tail(&tr->node, &r->results);
+	mutex_unlock(&info->results_lock);
+
+	pr_warn("%s\n", thread_result_get(r->name, tr));
+	return 0;
+}
+
+static unsigned int verify_result_add(struct dmatest_info *info,
+		struct dmatest_result *r, unsigned int n,
+		unsigned int src_off, unsigned int dst_off, unsigned int len,
+		u8 **bufs, int whence, unsigned int counter, u8 pattern,
+		bool is_srcbuf)
+{
+	struct dmatest_verify_result *vr;
+	unsigned int error_count;
+	unsigned int buf_off = is_srcbuf ? src_off : dst_off;
+	unsigned int start, end;
+
+	if (whence < 0) {
+		start = 0;
+		end = buf_off;
+	} else if (whence > 0) {
+		start = buf_off + len;
+		end = info->params.buf_size;
+	} else {
+		start = buf_off;
+		end = buf_off + len;
+	}
+
+	vr = kmalloc(sizeof(*vr), GFP_KERNEL);
+	if (!vr) {
+		pr_warn("dmatest: No memory to store verify result\n");
+		return dmatest_verify(NULL, bufs, start, end, counter, pattern,
+				      is_srcbuf);
+	}
+
+	vr->pattern = pattern;
+	vr->is_srcbuf = is_srcbuf;
+
+	error_count = dmatest_verify(vr, bufs, start, end, counter, pattern,
+				     is_srcbuf);
+	if (error_count) {
+		vr->error_count = error_count;
+		thread_result_add(info, r, DMATEST_ET_VERIFY_BUF, n, src_off,
+				  dst_off, len, (unsigned long)vr);
+		return error_count;
+	}
+
+	kfree(vr);
+	return 0;
+}
+
+static void result_free(struct dmatest_info *info, const char *name)
+{
+	struct dmatest_result *r, *_r;
+
+	mutex_lock(&info->results_lock);
+	list_for_each_entry_safe(r, _r, &info->results, node) {
+		struct dmatest_thread_result *tr, *_tr;
+
+		if (name && strcmp(r->name, name))
+			continue;
+
+		list_for_each_entry_safe(tr, _tr, &r->results, node) {
+			if (tr->type == DMATEST_ET_VERIFY_BUF)
+				kfree(tr->vr);
+			list_del(&tr->node);
+			kfree(tr);
+		}
+
+		kfree(r->name);
+		list_del(&r->node);
+		kfree(r);
+	}
+
+	mutex_unlock(&info->results_lock);
+}
+
+static struct dmatest_result *result_init(struct dmatest_info *info,
+		const char *name)
+{
+	struct dmatest_result *r;
+
+	r = kzalloc(sizeof(*r), GFP_KERNEL);
+	if (r) {
+		r->name = kstrdup(name, GFP_KERNEL);
+		INIT_LIST_HEAD(&r->results);
+		mutex_lock(&info->results_lock);
+		list_add_tail(&r->node, &info->results);
+		mutex_unlock(&info->results_lock);
+	}
+	return r;
+}
+
 /*
  * This function repeatedly tests DMA transfers of various lengths and
  * offsets for a given operation type until it is told to exit by
@@ -268,6 +516,8 @@ static int dmatest_func(void *data)
 	DECLARE_WAIT_QUEUE_HEAD_ONSTACK(done_wait);
 	struct dmatest_thread	*thread = data;
 	struct dmatest_done	done = { .wait = &done_wait };
+	struct dmatest_info	*info;
+	struct dmatest_params	*params;
 	struct dma_chan		*chan;
 	struct dma_device	*dev;
 	const char		*thread_name;
@@ -278,11 +528,12 @@ static int dmatest_func(void *data)
 	dma_cookie_t		cookie;
 	enum dma_status		status;
 	enum dma_ctrl_flags 	flags;
-	u8			pq_coefs[pq_sources + 1];
+	u8			*pq_coefs = NULL;
 	int			ret;
 	int			src_cnt;
 	int			dst_cnt;
 	int			i;
+	struct dmatest_result	*result;
 
 	thread_name = current->comm;
 	set_freezable();
@@ -290,28 +541,39 @@ static int dmatest_func(void *data)
 	ret = -ENOMEM;
 
 	smp_rmb();
+	info = thread->info;
+	params = &info->params;
 	chan = thread->chan;
 	dev = chan->device;
 	if (thread->type == DMA_MEMCPY)
 		src_cnt = dst_cnt = 1;
 	else if (thread->type == DMA_XOR) {
 		/* force odd to ensure dst = src */
-		src_cnt = min_odd(xor_sources | 1, dev->max_xor);
+		src_cnt = min_odd(params->xor_sources | 1, dev->max_xor);
 		dst_cnt = 1;
 	} else if (thread->type == DMA_PQ) {
 		/* force odd to ensure dst = src */
-		src_cnt = min_odd(pq_sources | 1, dma_maxpq(dev, 0));
+		src_cnt = min_odd(params->pq_sources | 1, dma_maxpq(dev, 0));
 		dst_cnt = 2;
+
+		pq_coefs = kmalloc(params->pq_sources+1, GFP_KERNEL);
+		if (!pq_coefs)
+			goto err_thread_type;
+
 		for (i = 0; i < src_cnt; i++)
 			pq_coefs[i] = 1;
 	} else
+		goto err_thread_type;
+
+	result = result_init(info, thread_name);
+	if (!result)
 		goto err_srcs;
 
 	thread->srcs = kcalloc(src_cnt+1, sizeof(u8 *), GFP_KERNEL);
 	if (!thread->srcs)
 		goto err_srcs;
 	for (i = 0; i < src_cnt; i++) {
-		thread->srcs[i] = kmalloc(test_buf_size, GFP_KERNEL);
+		thread->srcs[i] = kmalloc(params->buf_size, GFP_KERNEL);
 		if (!thread->srcs[i])
 			goto err_srcbuf;
 	}
@@ -321,7 +583,7 @@ static int dmatest_func(void *data)
 	if (!thread->dsts)
 		goto err_dsts;
 	for (i = 0; i < dst_cnt; i++) {
-		thread->dsts[i] = kmalloc(test_buf_size, GFP_KERNEL);
+		thread->dsts[i] = kmalloc(params->buf_size, GFP_KERNEL);
 		if (!thread->dsts[i])
 			goto err_dstbuf;
 	}
@@ -337,7 +599,7 @@ static int dmatest_func(void *data)
 	      | DMA_COMPL_SKIP_DEST_UNMAP | DMA_COMPL_SRC_UNMAP_SINGLE;
 
 	while (!kthread_should_stop()
-	       && !(iterations && total_tests >= iterations)) {
+	       && !(params->iterations && total_tests >= params->iterations)) {
 		struct dma_async_tx_descriptor *tx = NULL;
 		dma_addr_t dma_srcs[src_cnt];
 		dma_addr_t dma_dsts[dst_cnt];
@@ -353,24 +615,24 @@ static int dmatest_func(void *data)
 		else if (thread->type == DMA_PQ)
 			align = dev->pq_align;
 
-		if (1 << align > test_buf_size) {
+		if (1 << align > params->buf_size) {
 			pr_err("%u-byte buffer too small for %d-byte alignment\n",
-			       test_buf_size, 1 << align);
+			       params->buf_size, 1 << align);
 			break;
 		}
 
-		len = dmatest_random() % test_buf_size + 1;
+		len = dmatest_random() % params->buf_size + 1;
 		len = (len >> align) << align;
 		if (!len)
 			len = 1 << align;
-		src_off = dmatest_random() % (test_buf_size - len + 1);
-		dst_off = dmatest_random() % (test_buf_size - len + 1);
+		src_off = dmatest_random() % (params->buf_size - len + 1);
+		dst_off = dmatest_random() % (params->buf_size - len + 1);
 
 		src_off = (src_off >> align) << align;
 		dst_off = (dst_off >> align) << align;
 
-		dmatest_init_srcs(thread->srcs, src_off, len);
-		dmatest_init_dsts(thread->dsts, dst_off, len);
+		dmatest_init_srcs(thread->srcs, src_off, len, params->buf_size);
+		dmatest_init_dsts(thread->dsts, dst_off, len, params->buf_size);
 
 		for (i = 0; i < src_cnt; i++) {
 			u8 *buf = thread->srcs[i] + src_off;
@@ -380,10 +642,10 @@ static int dmatest_func(void *data)
 			ret = dma_mapping_error(dev->dev, dma_srcs[i]);
 			if (ret) {
 				unmap_src(dev->dev, dma_srcs, len, i);
-				pr_warn("%s: #%u: mapping error %d with "
-					"src_off=0x%x len=0x%x\n",
-					thread_name, total_tests - 1, ret,
-					src_off, len);
+				thread_result_add(info, result,
+						  DMATEST_ET_MAP_SRC,
+						  total_tests, src_off, dst_off,
+						  len, ret);
 				failed_tests++;
 				continue;
 			}
@@ -391,16 +653,17 @@ static int dmatest_func(void *data)
 		/* map with DMA_BIDIRECTIONAL to force writeback/invalidate */
 		for (i = 0; i < dst_cnt; i++) {
 			dma_dsts[i] = dma_map_single(dev->dev, thread->dsts[i],
-						     test_buf_size,
+						     params->buf_size,
 						     DMA_BIDIRECTIONAL);
 			ret = dma_mapping_error(dev->dev, dma_dsts[i]);
 			if (ret) {
 				unmap_src(dev->dev, dma_srcs, len, src_cnt);
-				unmap_dst(dev->dev, dma_dsts, test_buf_size, i);
-				pr_warn("%s: #%u: mapping error %d with "
-					"dst_off=0x%x len=0x%x\n",
-					thread_name, total_tests - 1, ret,
-					dst_off, test_buf_size);
+				unmap_dst(dev->dev, dma_dsts, params->buf_size,
+					  i);
+				thread_result_add(info, result,
+						  DMATEST_ET_MAP_DST,
+						  total_tests, src_off, dst_off,
+						  len, ret);
 				failed_tests++;
 				continue;
 			}
@@ -428,11 +691,11 @@ static int dmatest_func(void *data)
 
 		if (!tx) {
 			unmap_src(dev->dev, dma_srcs, len, src_cnt);
-			unmap_dst(dev->dev, dma_dsts, test_buf_size, dst_cnt);
-			pr_warning("%s: #%u: prep error with src_off=0x%x "
-					"dst_off=0x%x len=0x%x\n",
-					thread_name, total_tests - 1,
-					src_off, dst_off, len);
+			unmap_dst(dev->dev, dma_dsts, params->buf_size,
+				  dst_cnt);
+			thread_result_add(info, result, DMATEST_ET_PREP,
+					  total_tests, src_off, dst_off,
+					  len, 0);
 			msleep(100);
 			failed_tests++;
 			continue;
@@ -444,18 +707,18 @@ static int dmatest_func(void *data)
 		cookie = tx->tx_submit(tx);
 
 		if (dma_submit_error(cookie)) {
-			pr_warning("%s: #%u: submit error %d with src_off=0x%x "
-					"dst_off=0x%x len=0x%x\n",
-					thread_name, total_tests - 1, cookie,
-					src_off, dst_off, len);
+			thread_result_add(info, result, DMATEST_ET_SUBMIT,
+					  total_tests, src_off, dst_off,
+					  len, cookie);
 			msleep(100);
 			failed_tests++;
 			continue;
 		}
 		dma_async_issue_pending(chan);
 
-		wait_event_freezable_timeout(done_wait, done.done,
-					     msecs_to_jiffies(timeout));
+		wait_event_freezable_timeout(done_wait,
+					     done.done || kthread_should_stop(),
+					     msecs_to_jiffies(params->timeout));
 
 		status = dma_async_is_tx_complete(chan, cookie, NULL, NULL);
 
@@ -468,56 +731,57 @@ static int dmatest_func(void *data)
 			 * free it this time?" dancing.  For now, just
 			 * leave it dangling.
 			 */
-			pr_warning("%s: #%u: test timed out\n",
-				   thread_name, total_tests - 1);
+			thread_result_add(info, result, DMATEST_ET_TIMEOUT,
+					  total_tests, src_off, dst_off,
+					  len, 0);
 			failed_tests++;
 			continue;
 		} else if (status != DMA_SUCCESS) {
-			pr_warning("%s: #%u: got completion callback,"
-				   " but status is \'%s\'\n",
-				   thread_name, total_tests - 1,
-				   status == DMA_ERROR ? "error" : "in progress");
+			enum dmatest_error_type type = (status == DMA_ERROR) ?
+				DMATEST_ET_DMA_ERROR : DMATEST_ET_DMA_IN_PROGRESS;
+			thread_result_add(info, result, type,
+					  total_tests, src_off, dst_off,
+					  len, status);
 			failed_tests++;
 			continue;
 		}
 
 		/* Unmap by myself (see DMA_COMPL_SKIP_DEST_UNMAP above) */
-		unmap_dst(dev->dev, dma_dsts, test_buf_size, dst_cnt);
+		unmap_dst(dev->dev, dma_dsts, params->buf_size, dst_cnt);
 
 		error_count = 0;
 
 		pr_debug("%s: verifying source buffer...\n", thread_name);
-		error_count += dmatest_verify(thread->srcs, 0, src_off,
+		error_count += verify_result_add(info, result, total_tests,
+				src_off, dst_off, len, thread->srcs, -1,
 				0, PATTERN_SRC, true);
-		error_count += dmatest_verify(thread->srcs, src_off,
-				src_off + len, src_off,
-				PATTERN_SRC | PATTERN_COPY, true);
-		error_count += dmatest_verify(thread->srcs, src_off + len,
-				test_buf_size, src_off + len,
-				PATTERN_SRC, true);
-
-		pr_debug("%s: verifying dest buffer...\n",
-				thread->task->comm);
-		error_count += dmatest_verify(thread->dsts, 0, dst_off,
+		error_count += verify_result_add(info, result, total_tests,
+				src_off, dst_off, len, thread->srcs, 0,
+				src_off, PATTERN_SRC | PATTERN_COPY, true);
+		error_count += verify_result_add(info, result, total_tests,
+				src_off, dst_off, len, thread->srcs, 1,
+				src_off + len, PATTERN_SRC, true);
+
+		pr_debug("%s: verifying dest buffer...\n", thread_name);
+		error_count += verify_result_add(info, result, total_tests,
+				src_off, dst_off, len, thread->dsts, -1,
 				0, PATTERN_DST, false);
-		error_count += dmatest_verify(thread->dsts, dst_off,
-				dst_off + len, src_off,
-				PATTERN_SRC | PATTERN_COPY, false);
-		error_count += dmatest_verify(thread->dsts, dst_off + len,
-				test_buf_size, dst_off + len,
-				PATTERN_DST, false);
+		error_count += verify_result_add(info, result, total_tests,
+				src_off, dst_off, len, thread->dsts, 0,
+				src_off, PATTERN_SRC | PATTERN_COPY, false);
+		error_count += verify_result_add(info, result, total_tests,
+				src_off, dst_off, len, thread->dsts, 1,
+				dst_off + len, PATTERN_DST, false);
 
 		if (error_count) {
-			pr_warning("%s: #%u: %u errors with "
-				"src_off=0x%x dst_off=0x%x len=0x%x\n",
-				thread_name, total_tests - 1, error_count,
-				src_off, dst_off, len);
+			thread_result_add(info, result, DMATEST_ET_VERIFY,
+					  total_tests, src_off, dst_off,
+					  len, error_count);
 			failed_tests++;
 		} else {
-			pr_debug("%s: #%u: No errors with "
-				"src_off=0x%x dst_off=0x%x len=0x%x\n",
-				thread_name, total_tests - 1,
-				src_off, dst_off, len);
+			thread_result_add(info, result, DMATEST_ET_OK,
+					  total_tests, src_off, dst_off,
+					  len, 0);
 		}
 	}
 
@@ -532,6 +796,8 @@ err_dsts:
 err_srcbuf:
 	kfree(thread->srcs);
 err_srcs:
+	kfree(pq_coefs);
+err_thread_type:
 	pr_notice("%s: terminating after %u tests, %u failures (status %d)\n",
 			thread_name, total_tests, failed_tests, ret);
 
@@ -539,7 +805,9 @@ err_srcs:
 	if (ret)
 		dmaengine_terminate_all(chan);
 
-	if (iterations > 0)
+	thread->done = true;
+
+	if (params->iterations > 0)
 		while (!kthread_should_stop()) {
 			DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wait_dmatest_exit);
 			interruptible_sleep_on(&wait_dmatest_exit);
@@ -568,8 +836,10 @@ static void dmatest_cleanup_channel(struct dmatest_chan *dtc)
 	kfree(dtc);
 }
 
-static int dmatest_add_threads(struct dmatest_chan *dtc, enum dma_transaction_type type)
+static int dmatest_add_threads(struct dmatest_info *info,
+		struct dmatest_chan *dtc, enum dma_transaction_type type)
 {
+	struct dmatest_params *params = &info->params;
 	struct dmatest_thread *thread;
 	struct dma_chan *chan = dtc->chan;
 	char *op;
@@ -584,7 +854,7 @@ static int dmatest_add_threads(struct dmatest_chan *dtc, enum dma_transaction_ty
 	else
 		return -EINVAL;
 
-	for (i = 0; i < threads_per_chan; i++) {
+	for (i = 0; i < params->threads_per_chan; i++) {
 		thread = kzalloc(sizeof(struct dmatest_thread), GFP_KERNEL);
 		if (!thread) {
 			pr_warning("dmatest: No memory for %s-%s%u\n",
@@ -592,6 +862,7 @@ static int dmatest_add_threads(struct dmatest_chan *dtc, enum dma_transaction_ty
 
 			break;
 		}
+		thread->info = info;
 		thread->chan = dtc->chan;
 		thread->type = type;
 		smp_wmb();
@@ -612,7 +883,8 @@ static int dmatest_add_threads(struct dmatest_chan *dtc, enum dma_transaction_ty
 	return i;
 }
 
-static int dmatest_add_channel(struct dma_chan *chan)
+static int dmatest_add_channel(struct dmatest_info *info,
+		struct dma_chan *chan)
 {
 	struct dmatest_chan	*dtc;
 	struct dma_device	*dma_dev = chan->device;
@@ -629,75 +901,418 @@ static int dmatest_add_channel(struct dma_chan *chan)
 	INIT_LIST_HEAD(&dtc->threads);
 
 	if (dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask)) {
-		cnt = dmatest_add_threads(dtc, DMA_MEMCPY);
+		cnt = dmatest_add_threads(info, dtc, DMA_MEMCPY);
 		thread_count += cnt > 0 ? cnt : 0;
 	}
 	if (dma_has_cap(DMA_XOR, dma_dev->cap_mask)) {
-		cnt = dmatest_add_threads(dtc, DMA_XOR);
+		cnt = dmatest_add_threads(info, dtc, DMA_XOR);
 		thread_count += cnt > 0 ? cnt : 0;
 	}
 	if (dma_has_cap(DMA_PQ, dma_dev->cap_mask)) {
-		cnt = dmatest_add_threads(dtc, DMA_PQ);
+		cnt = dmatest_add_threads(info, dtc, DMA_PQ);
 		thread_count += cnt > 0 ? cnt : 0;
 	}
 
 	pr_info("dmatest: Started %u threads using %s\n",
 		thread_count, dma_chan_name(chan));
 
-	list_add_tail(&dtc->node, &dmatest_channels);
-	nr_channels++;
+	list_add_tail(&dtc->node, &info->channels);
+	info->nr_channels++;
 
 	return 0;
 }
 
 static bool filter(struct dma_chan *chan, void *param)
 {
-	if (!dmatest_match_channel(chan) || !dmatest_match_device(chan->device))
+	struct dmatest_params *params = param;
+
+	if (!dmatest_match_channel(params, chan) ||
+	    !dmatest_match_device(params, chan->device))
 		return false;
 	else
 		return true;
 }
 
-static int __init dmatest_init(void)
+static int __run_threaded_test(struct dmatest_info *info)
 {
 	dma_cap_mask_t mask;
 	struct dma_chan *chan;
+	struct dmatest_params *params = &info->params;
 	int err = 0;
 
 	dma_cap_zero(mask);
 	dma_cap_set(DMA_MEMCPY, mask);
 	for (;;) {
-		chan = dma_request_channel(mask, filter, NULL);
+		chan = dma_request_channel(mask, filter, params);
 		if (chan) {
-			err = dmatest_add_channel(chan);
+			err = dmatest_add_channel(info, chan);
 			if (err) {
 				dma_release_channel(chan);
 				break; /* add_channel failed, punt */
 			}
 		} else
 			break; /* no more channels available */
-		if (max_channels && nr_channels >= max_channels)
+		if (params->max_channels &&
+		    info->nr_channels >= params->max_channels)
 			break; /* we have all we need */
 	}
-
 	return err;
 }
-/* when compiled-in wait for drivers to load first */
-late_initcall(dmatest_init);
 
-static void __exit dmatest_exit(void)
+#ifndef MODULE
+static int run_threaded_test(struct dmatest_info *info)
+{
+	int ret;
+
+	mutex_lock(&info->lock);
+	ret = __run_threaded_test(info);
+	mutex_unlock(&info->lock);
+	return ret;
+}
+#endif
+
+static void __stop_threaded_test(struct dmatest_info *info)
 {
 	struct dmatest_chan *dtc, *_dtc;
 	struct dma_chan *chan;
 
-	list_for_each_entry_safe(dtc, _dtc, &dmatest_channels, node) {
+	list_for_each_entry_safe(dtc, _dtc, &info->channels, node) {
 		list_del(&dtc->node);
 		chan = dtc->chan;
 		dmatest_cleanup_channel(dtc);
-		pr_debug("dmatest: dropped channel %s\n",
-			 dma_chan_name(chan));
+		pr_debug("dmatest: dropped channel %s\n", dma_chan_name(chan));
 		dma_release_channel(chan);
 	}
+
+	info->nr_channels = 0;
+}
+
+static void stop_threaded_test(struct dmatest_info *info)
+{
+	mutex_lock(&info->lock);
+	__stop_threaded_test(info);
+	mutex_unlock(&info->lock);
+}
+
+static int __restart_threaded_test(struct dmatest_info *info, bool run)
+{
+	struct dmatest_params *params = &info->params;
+	int ret;
+
+	/* Stop any running test first */
+	__stop_threaded_test(info);
+
+	if (run == false)
+		return 0;
+
+	/* Clear results from previous run */
+	result_free(info, NULL);
+
+	/* Copy test parameters */
+	memcpy(params, &info->dbgfs_params, sizeof(*params));
+
+	/* Run test with new parameters */
+	ret = __run_threaded_test(info);
+	if (ret) {
+		__stop_threaded_test(info);
+		pr_err("dmatest: Can't run test\n");
+	}
+
+	return ret;
+}
+
+static ssize_t dtf_write_string(void *to, size_t available, loff_t *ppos,
+		const void __user *from, size_t count)
+{
+	char tmp[20];
+	ssize_t len;
+
+	len = simple_write_to_buffer(tmp, sizeof(tmp) - 1, ppos, from, count);
+	if (len >= 0) {
+		tmp[len] = '\0';
+		strlcpy(to, strim(tmp), available);
+	}
+
+	return len;
+}
+
+static ssize_t dtf_read_channel(struct file *file, char __user *buf,
+		size_t count, loff_t *ppos)
+{
+	struct dmatest_info *info = file->private_data;
+	return simple_read_from_buffer(buf, count, ppos,
+			info->dbgfs_params.channel,
+			strlen(info->dbgfs_params.channel));
+}
+
+static ssize_t dtf_write_channel(struct file *file, const char __user *buf,
+		size_t size, loff_t *ppos)
+{
+	struct dmatest_info *info = file->private_data;
+	return dtf_write_string(info->dbgfs_params.channel,
+				sizeof(info->dbgfs_params.channel),
+				ppos, buf, size);
+}
+
+static const struct file_operations dtf_channel_fops = {
+	.read	= dtf_read_channel,
+	.write	= dtf_write_channel,
+	.open	= simple_open,
+	.llseek	= default_llseek,
+};
+
+static ssize_t dtf_read_device(struct file *file, char __user *buf,
+		size_t count, loff_t *ppos)
+{
+	struct dmatest_info *info = file->private_data;
+	return simple_read_from_buffer(buf, count, ppos,
+			info->dbgfs_params.device,
+			strlen(info->dbgfs_params.device));
+}
+
+static ssize_t dtf_write_device(struct file *file, const char __user *buf,
+		size_t size, loff_t *ppos)
+{
+	struct dmatest_info *info = file->private_data;
+	return dtf_write_string(info->dbgfs_params.device,
+				sizeof(info->dbgfs_params.device),
+				ppos, buf, size);
+}
+
+static const struct file_operations dtf_device_fops = {
+	.read	= dtf_read_device,
+	.write	= dtf_write_device,
+	.open	= simple_open,
+	.llseek	= default_llseek,
+};
+
+static ssize_t dtf_read_run(struct file *file, char __user *user_buf,
+		size_t count, loff_t *ppos)
+{
+	struct dmatest_info *info = file->private_data;
+	char buf[3];
+	struct dmatest_chan *dtc;
+	bool alive = false;
+
+	mutex_lock(&info->lock);
+	list_for_each_entry(dtc, &info->channels, node) {
+		struct dmatest_thread *thread;
+
+		list_for_each_entry(thread, &dtc->threads, node) {
+			if (!thread->done) {
+				alive = true;
+				break;
+			}
+		}
+	}
+
+	if (alive) {
+		buf[0] = 'Y';
+	} else {
+		__stop_threaded_test(info);
+		buf[0] = 'N';
+	}
+
+	mutex_unlock(&info->lock);
+	buf[1] = '\n';
+	buf[2] = 0x00;
+	return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
+}
+
+static ssize_t dtf_write_run(struct file *file, const char __user *user_buf,
+		size_t count, loff_t *ppos)
+{
+	struct dmatest_info *info = file->private_data;
+	char buf[16];
+	bool bv;
+	int ret = 0;
+
+	if (copy_from_user(buf, user_buf, min(count, (sizeof(buf) - 1))))
+		return -EFAULT;
+
+	if (strtobool(buf, &bv) == 0) {
+		mutex_lock(&info->lock);
+		ret = __restart_threaded_test(info, bv);
+		mutex_unlock(&info->lock);
+	}
+
+	return ret ? ret : count;
+}
+
+static const struct file_operations dtf_run_fops = {
+	.read	= dtf_read_run,
+	.write	= dtf_write_run,
+	.open	= simple_open,
+	.llseek	= default_llseek,
+};
+
+static int dtf_results_show(struct seq_file *sf, void *data)
+{
+	struct dmatest_info *info = sf->private;
+	struct dmatest_result *result;
+	struct dmatest_thread_result *tr;
+	unsigned int i;
+
+	mutex_lock(&info->results_lock);
+	list_for_each_entry(result, &info->results, node) {
+		list_for_each_entry(tr, &result->results, node) {
+			seq_printf(sf, "%s\n",
+				thread_result_get(result->name, tr));
+			if (tr->type == DMATEST_ET_VERIFY_BUF) {
+				for (i = 0; i < tr->vr->error_count; i++) {
+					seq_printf(sf, "\t%s\n",
+						verify_result_get_one(tr->vr, i));
+				}
+			}
+		}
+	}
+
+	mutex_unlock(&info->results_lock);
+	return 0;
+}
+
+static int dtf_results_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, dtf_results_show, inode->i_private);
+}
+
+static const struct file_operations dtf_results_fops = {
+	.open		= dtf_results_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static int dmatest_register_dbgfs(struct dmatest_info *info)
+{
+	struct dentry *d;
+	struct dmatest_params *params = &info->dbgfs_params;
+	int ret = -ENOMEM;
+
+	d = debugfs_create_dir("dmatest", NULL);
+	if (IS_ERR(d))
+		return PTR_ERR(d);
+	if (!d)
+		goto err_root;
+
+	info->root = d;
+
+	/* Copy initial values */
+	memcpy(params, &info->params, sizeof(*params));
+
+	/* Test parameters */
+
+	d = debugfs_create_u32("test_buf_size", S_IWUSR | S_IRUGO, info->root,
+			       (u32 *)&params->buf_size);
+	if (IS_ERR_OR_NULL(d))
+		goto err_node;
+
+	d = debugfs_create_file("channel", S_IRUGO | S_IWUSR, info->root,
+				info, &dtf_channel_fops);
+	if (IS_ERR_OR_NULL(d))
+		goto err_node;
+
+	d = debugfs_create_file("device", S_IRUGO | S_IWUSR, info->root,
+				info, &dtf_device_fops);
+	if (IS_ERR_OR_NULL(d))
+		goto err_node;
+
+	d = debugfs_create_u32("threads_per_chan", S_IWUSR | S_IRUGO, info->root,
+			       (u32 *)&params->threads_per_chan);
+	if (IS_ERR_OR_NULL(d))
+		goto err_node;
+
+	d = debugfs_create_u32("max_channels", S_IWUSR | S_IRUGO, info->root,
+			       (u32 *)&params->max_channels);
+	if (IS_ERR_OR_NULL(d))
+		goto err_node;
+
+	d = debugfs_create_u32("iterations", S_IWUSR | S_IRUGO, info->root,
+			       (u32 *)&params->iterations);
+	if (IS_ERR_OR_NULL(d))
+		goto err_node;
+
+	d = debugfs_create_u32("xor_sources", S_IWUSR | S_IRUGO, info->root,
+			       (u32 *)&params->xor_sources);
+	if (IS_ERR_OR_NULL(d))
+		goto err_node;
+
+	d = debugfs_create_u32("pq_sources", S_IWUSR | S_IRUGO, info->root,
+			       (u32 *)&params->pq_sources);
+	if (IS_ERR_OR_NULL(d))
+		goto err_node;
+
+	d = debugfs_create_u32("timeout", S_IWUSR | S_IRUGO, info->root,
+			       (u32 *)&params->timeout);
+	if (IS_ERR_OR_NULL(d))
+		goto err_node;
+
+	/* Run or stop threaded test */
+	d = debugfs_create_file("run", S_IWUSR | S_IRUGO, info->root,
+				info, &dtf_run_fops);
+	if (IS_ERR_OR_NULL(d))
+		goto err_node;
+
+	/* Results of test in progress */
+	d = debugfs_create_file("results", S_IRUGO, info->root, info,
+				&dtf_results_fops);
+	if (IS_ERR_OR_NULL(d))
+		goto err_node;
+
+	return 0;
+
+err_node:
+	debugfs_remove_recursive(info->root);
+err_root:
+	pr_err("dmatest: Failed to initialize debugfs\n");
+	return ret;
+}
+
+static int __init dmatest_init(void)
+{
+	struct dmatest_info *info = &test_info;
+	struct dmatest_params *params = &info->params;
+	int ret;
+
+	memset(info, 0, sizeof(*info));
+
+	mutex_init(&info->lock);
+	INIT_LIST_HEAD(&info->channels);
+
+	mutex_init(&info->results_lock);
+	INIT_LIST_HEAD(&info->results);
+
+	/* Set default parameters */
+	params->buf_size = test_buf_size;
+	strlcpy(params->channel, test_channel, sizeof(params->channel));
+	strlcpy(params->device, test_device, sizeof(params->device));
+	params->threads_per_chan = threads_per_chan;
+	params->max_channels = max_channels;
+	params->iterations = iterations;
+	params->xor_sources = xor_sources;
+	params->pq_sources = pq_sources;
+	params->timeout = timeout;
+
+	ret = dmatest_register_dbgfs(info);
+	if (ret)
+		return ret;
+
+#ifdef MODULE
+	return 0;
+#else
+	return run_threaded_test(info);
+#endif
+}
+/* when compiled-in wait for drivers to load first */
+late_initcall(dmatest_init);
+
+static void __exit dmatest_exit(void)
+{
+	struct dmatest_info *info = &test_info;
+
+	debugfs_remove_recursive(info->root);
+	stop_threaded_test(info);
+	result_free(info, NULL);
 }
 module_exit(dmatest_exit);
 
diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c
index 43a5329..e33dc3b 100644
--- a/drivers/dma/dw_dmac.c
+++ b/drivers/dma/dw_dmac.c
@@ -49,29 +49,22 @@ static inline unsigned int dwc_get_sms(struct dw_dma_slave *slave)
 	return slave ? slave->src_master : 1;
 }
 
-#define SRC_MASTER	0
-#define DST_MASTER	1
-
-static inline unsigned int dwc_get_master(struct dma_chan *chan, int master)
+static inline void dwc_set_masters(struct dw_dma_chan *dwc)
 {
-	struct dw_dma *dw = to_dw_dma(chan->device);
-	struct dw_dma_slave *dws = chan->private;
-	unsigned int m;
-
-	if (master == SRC_MASTER)
-		m = dwc_get_sms(dws);
-	else
-		m = dwc_get_dms(dws);
+	struct dw_dma *dw = to_dw_dma(dwc->chan.device);
+	struct dw_dma_slave *dws = dwc->chan.private;
+	unsigned char mmax = dw->nr_masters - 1;
 
-	return min_t(unsigned int, dw->nr_masters - 1, m);
+	if (dwc->request_line == ~0) {
+		dwc->src_master = min_t(unsigned char, mmax, dwc_get_sms(dws));
+		dwc->dst_master = min_t(unsigned char, mmax, dwc_get_dms(dws));
+	}
 }
 
 #define DWC_DEFAULT_CTLLO(_chan) ({				\
 		struct dw_dma_chan *_dwc = to_dw_dma_chan(_chan);	\
 		struct dma_slave_config	*_sconfig = &_dwc->dma_sconfig;	\
 		bool _is_slave = is_slave_direction(_dwc->direction);	\
-		int _dms = dwc_get_master(_chan, DST_MASTER);		\
-		int _sms = dwc_get_master(_chan, SRC_MASTER);		\
 		u8 _smsize = _is_slave ? _sconfig->src_maxburst :	\
 			DW_DMA_MSIZE_16;			\
 		u8 _dmsize = _is_slave ? _sconfig->dst_maxburst :	\
@@ -81,8 +74,8 @@ static inline unsigned int dwc_get_master(struct dma_chan *chan, int master)
 		 | DWC_CTLL_SRC_MSIZE(_smsize)			\
 		 | DWC_CTLL_LLP_D_EN				\
 		 | DWC_CTLL_LLP_S_EN				\
-		 | DWC_CTLL_DMS(_dms)				\
-		 | DWC_CTLL_SMS(_sms));				\
+		 | DWC_CTLL_DMS(_dwc->dst_master)		\
+		 | DWC_CTLL_SMS(_dwc->src_master));		\
 	})
 
 /*
@@ -92,13 +85,6 @@ static inline unsigned int dwc_get_master(struct dma_chan *chan, int master)
  */
 #define NR_DESCS_PER_CHANNEL	64
 
-static inline unsigned int dwc_get_data_width(struct dma_chan *chan, int master)
-{
-	struct dw_dma *dw = to_dw_dma(chan->device);
-
-	return dw->data_width[dwc_get_master(chan, master)];
-}
-
 /*----------------------------------------------------------------------*/
 
 static struct device *chan2dev(struct dma_chan *chan)
@@ -172,13 +158,7 @@ static void dwc_initialize(struct dw_dma_chan *dwc)
 	if (dwc->initialized == true)
 		return;
 
-	if (dws && dws->cfg_hi == ~0 && dws->cfg_lo == ~0) {
-		/* autoconfigure based on request line from DT */
-		if (dwc->direction == DMA_MEM_TO_DEV)
-			cfghi = DWC_CFGH_DST_PER(dwc->request_line);
-		else if (dwc->direction == DMA_DEV_TO_MEM)
-			cfghi = DWC_CFGH_SRC_PER(dwc->request_line);
-	} else if (dws) {
+	if (dws) {
 		/*
 		 * We need controller-specific data to set up slave
 		 * transfers.
@@ -189,9 +169,9 @@ static void dwc_initialize(struct dw_dma_chan *dwc)
 		cfglo |= dws->cfg_lo & ~DWC_CFGL_CH_PRIOR_MASK;
 	} else {
 		if (dwc->direction == DMA_MEM_TO_DEV)
-			cfghi = DWC_CFGH_DST_PER(dwc->dma_sconfig.slave_id);
+			cfghi = DWC_CFGH_DST_PER(dwc->request_line);
 		else if (dwc->direction == DMA_DEV_TO_MEM)
-			cfghi = DWC_CFGH_SRC_PER(dwc->dma_sconfig.slave_id);
+			cfghi = DWC_CFGH_SRC_PER(dwc->request_line);
 	}
 
 	channel_writel(dwc, CFG_LO, cfglo);
@@ -473,16 +453,16 @@ static void dwc_scan_descriptors(struct dw_dma *dw, struct dw_dma_chan *dwc)
 			(unsigned long long)llp);
 
 	list_for_each_entry_safe(desc, _desc, &dwc->active_list, desc_node) {
-		/* initial residue value */
+		/* Initial residue value */
 		dwc->residue = desc->total_len;
 
-		/* check first descriptors addr */
+		/* Check first descriptors addr */
 		if (desc->txd.phys == llp) {
 			spin_unlock_irqrestore(&dwc->lock, flags);
 			return;
 		}
 
-		/* check first descriptors llp */
+		/* Check first descriptors llp */
 		if (desc->lli.llp == llp) {
 			/* This one is currently in progress */
 			dwc->residue -= dwc_get_sent(dwc);
@@ -588,7 +568,7 @@ inline dma_addr_t dw_dma_get_dst_addr(struct dma_chan *chan)
 }
 EXPORT_SYMBOL(dw_dma_get_dst_addr);
 
-/* called with dwc->lock held and all DMAC interrupts disabled */
+/* Called with dwc->lock held and all DMAC interrupts disabled */
 static void dwc_handle_cyclic(struct dw_dma *dw, struct dw_dma_chan *dwc,
 		u32 status_err, u32 status_xfer)
 {
@@ -626,7 +606,7 @@ static void dwc_handle_cyclic(struct dw_dma *dw, struct dw_dma_chan *dwc,
 
 		dwc_chan_disable(dw, dwc);
 
-		/* make sure DMA does not restart by loading a new list */
+		/* Make sure DMA does not restart by loading a new list */
 		channel_writel(dwc, LLP, 0);
 		channel_writel(dwc, CTL_LO, 0);
 		channel_writel(dwc, CTL_HI, 0);
@@ -745,6 +725,7 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
 		size_t len, unsigned long flags)
 {
 	struct dw_dma_chan	*dwc = to_dw_dma_chan(chan);
+	struct dw_dma		*dw = to_dw_dma(chan->device);
 	struct dw_desc		*desc;
 	struct dw_desc		*first;
 	struct dw_desc		*prev;
@@ -767,8 +748,8 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
 
 	dwc->direction = DMA_MEM_TO_MEM;
 
-	data_width = min_t(unsigned int, dwc_get_data_width(chan, SRC_MASTER),
-			   dwc_get_data_width(chan, DST_MASTER));
+	data_width = min_t(unsigned int, dw->data_width[dwc->src_master],
+			   dw->data_width[dwc->dst_master]);
 
 	src_width = dst_width = min_t(unsigned int, data_width,
 				      dwc_fast_fls(src | dest | len));
@@ -826,6 +807,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
 		unsigned long flags, void *context)
 {
 	struct dw_dma_chan	*dwc = to_dw_dma_chan(chan);
+	struct dw_dma		*dw = to_dw_dma(chan->device);
 	struct dma_slave_config	*sconfig = &dwc->dma_sconfig;
 	struct dw_desc		*prev;
 	struct dw_desc		*first;
@@ -859,7 +841,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
 		ctllo |= sconfig->device_fc ? DWC_CTLL_FC(DW_DMA_FC_P_M2P) :
 			DWC_CTLL_FC(DW_DMA_FC_D_M2P);
 
-		data_width = dwc_get_data_width(chan, SRC_MASTER);
+		data_width = dw->data_width[dwc->src_master];
 
 		for_each_sg(sgl, sg, sg_len, i) {
 			struct dw_desc	*desc;
@@ -919,7 +901,7 @@ slave_sg_todev_fill_desc:
 		ctllo |= sconfig->device_fc ? DWC_CTLL_FC(DW_DMA_FC_P_P2M) :
 			DWC_CTLL_FC(DW_DMA_FC_D_P2M);
 
-		data_width = dwc_get_data_width(chan, DST_MASTER);
+		data_width = dw->data_width[dwc->dst_master];
 
 		for_each_sg(sgl, sg, sg_len, i) {
 			struct dw_desc	*desc;
@@ -1020,6 +1002,10 @@ set_runtime_config(struct dma_chan *chan, struct dma_slave_config *sconfig)
 	memcpy(&dwc->dma_sconfig, sconfig, sizeof(*sconfig));
 	dwc->direction = sconfig->direction;
 
+	/* Take the request line from slave_id member */
+	if (dwc->request_line == ~0)
+		dwc->request_line = sconfig->slave_id;
+
 	convert_burst(&dwc->dma_sconfig.src_maxburst);
 	convert_burst(&dwc->dma_sconfig.dst_maxburst);
 	convert_slave_id(dwc);
@@ -1030,10 +1016,11 @@ set_runtime_config(struct dma_chan *chan, struct dma_slave_config *sconfig)
 static inline void dwc_chan_pause(struct dw_dma_chan *dwc)
 {
 	u32 cfglo = channel_readl(dwc, CFG_LO);
+	unsigned int count = 20;	/* timeout iterations */
 
 	channel_writel(dwc, CFG_LO, cfglo | DWC_CFGL_CH_SUSP);
-	while (!(channel_readl(dwc, CFG_LO) & DWC_CFGL_FIFO_EMPTY))
-		cpu_relax();
+	while (!(channel_readl(dwc, CFG_LO) & DWC_CFGL_FIFO_EMPTY) && count--)
+		udelay(2);
 
 	dwc->paused = true;
 }
@@ -1169,6 +1156,8 @@ static int dwc_alloc_chan_resources(struct dma_chan *chan)
 	 * doesn't mean what you think it means), and status writeback.
 	 */
 
+	dwc_set_masters(dwc);
+
 	spin_lock_irqsave(&dwc->lock, flags);
 	i = dwc->descs_allocated;
 	while (dwc->descs_allocated < NR_DESCS_PER_CHANNEL) {
@@ -1226,6 +1215,7 @@ static void dwc_free_chan_resources(struct dma_chan *chan)
 	list_splice_init(&dwc->free_list, &list);
 	dwc->descs_allocated = 0;
 	dwc->initialized = false;
+	dwc->request_line = ~0;
 
 	/* Disable interrupts */
 	channel_clear_bit(dw, MASK.XFER, dwc->mask);
@@ -1241,42 +1231,36 @@ static void dwc_free_chan_resources(struct dma_chan *chan)
 	dev_vdbg(chan2dev(chan), "%s: done\n", __func__);
 }
 
-struct dw_dma_filter_args {
+/*----------------------------------------------------------------------*/
+
+struct dw_dma_of_filter_args {
 	struct dw_dma *dw;
 	unsigned int req;
 	unsigned int src;
 	unsigned int dst;
 };
 
-static bool dw_dma_generic_filter(struct dma_chan *chan, void *param)
+static bool dw_dma_of_filter(struct dma_chan *chan, void *param)
 {
 	struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
-	struct dw_dma *dw = to_dw_dma(chan->device);
-	struct dw_dma_filter_args *fargs = param;
-	struct dw_dma_slave *dws = &dwc->slave;
+	struct dw_dma_of_filter_args *fargs = param;
 
-	/* ensure the device matches our channel */
+	/* Ensure the device matches our channel */
         if (chan->device != &fargs->dw->dma)
                 return false;
 
-	dws->dma_dev	= dw->dma.dev;
-	dws->cfg_hi	= ~0;
-	dws->cfg_lo	= ~0;
-	dws->src_master	= fargs->src;
-	dws->dst_master	= fargs->dst;
-
 	dwc->request_line = fargs->req;
-
-	chan->private = dws;
+	dwc->src_master	= fargs->src;
+	dwc->dst_master	= fargs->dst;
 
 	return true;
 }
 
-static struct dma_chan *dw_dma_xlate(struct of_phandle_args *dma_spec,
-					 struct of_dma *ofdma)
+static struct dma_chan *dw_dma_of_xlate(struct of_phandle_args *dma_spec,
+					struct of_dma *ofdma)
 {
 	struct dw_dma *dw = ofdma->of_dma_data;
-	struct dw_dma_filter_args fargs = {
+	struct dw_dma_of_filter_args fargs = {
 		.dw = dw,
 	};
 	dma_cap_mask_t cap;
@@ -1297,7 +1281,7 @@ static struct dma_chan *dw_dma_xlate(struct of_phandle_args *dma_spec,
 	dma_cap_set(DMA_SLAVE, cap);
 
 	/* TODO: there should be a simpler way to do this */
-	return dma_request_channel(cap, dw_dma_generic_filter, &fargs);
+	return dma_request_channel(cap, dw_dma_of_filter, &fargs);
 }
 
 /* --------------------- Cyclic DMA API extensions -------------------- */
@@ -1322,7 +1306,7 @@ int dw_dma_cyclic_start(struct dma_chan *chan)
 
 	spin_lock_irqsave(&dwc->lock, flags);
 
-	/* assert channel is idle */
+	/* Assert channel is idle */
 	if (dma_readl(dw, CH_EN) & dwc->mask) {
 		dev_err(chan2dev(&dwc->chan),
 			"BUG: Attempted to start non-idle channel\n");
@@ -1334,7 +1318,7 @@ int dw_dma_cyclic_start(struct dma_chan *chan)
 	dma_writel(dw, CLEAR.ERROR, dwc->mask);
 	dma_writel(dw, CLEAR.XFER, dwc->mask);
 
-	/* setup DMAC channel registers */
+	/* Setup DMAC channel registers */
 	channel_writel(dwc, LLP, dwc->cdesc->desc[0]->txd.phys);
 	channel_writel(dwc, CTL_LO, DWC_CTLL_LLP_D_EN | DWC_CTLL_LLP_S_EN);
 	channel_writel(dwc, CTL_HI, 0);
@@ -1501,7 +1485,7 @@ struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan,
 		last = desc;
 	}
 
-	/* lets make a cyclic list */
+	/* Let's make a cyclic list */
 	last->lli.llp = cdesc->desc[0]->txd.phys;
 
 	dev_dbg(chan2dev(&dwc->chan), "cyclic prepared buf 0x%llx len %zu "
@@ -1706,7 +1690,7 @@ static int dw_probe(struct platform_device *pdev)
 
 	dw->regs = regs;
 
-	/* get hardware configuration parameters */
+	/* Get hardware configuration parameters */
 	if (autocfg) {
 		max_blk_size = dma_readl(dw, MAX_BLK_SIZE);
 
@@ -1728,10 +1712,10 @@ static int dw_probe(struct platform_device *pdev)
 	/* Calculate all channel mask before DMA setup */
 	dw->all_chan_mask = (1 << nr_channels) - 1;
 
-	/* force dma off, just in case */
+	/* Force dma off, just in case */
 	dw_dma_off(dw);
 
-	/* disable BLOCK interrupts as well */
+	/* Disable BLOCK interrupts as well */
 	channel_clear_bit(dw, MASK.BLOCK, dw->all_chan_mask);
 
 	err = devm_request_irq(&pdev->dev, irq, dw_dma_interrupt, 0,
@@ -1741,7 +1725,7 @@ static int dw_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, dw);
 
-	/* create a pool of consistent memory blocks for hardware descriptors */
+	/* Create a pool of consistent memory blocks for hardware descriptors */
 	dw->desc_pool = dmam_pool_create("dw_dmac_desc_pool", &pdev->dev,
 					 sizeof(struct dw_desc), 4, 0);
 	if (!dw->desc_pool) {
@@ -1781,8 +1765,9 @@ static int dw_probe(struct platform_device *pdev)
 		channel_clear_bit(dw, CH_EN, dwc->mask);
 
 		dwc->direction = DMA_TRANS_NONE;
+		dwc->request_line = ~0;
 
-		/* hardware configuration */
+		/* Hardware configuration */
 		if (autocfg) {
 			unsigned int dwc_params;
 
@@ -1842,8 +1827,8 @@ static int dw_probe(struct platform_device *pdev)
 
 	if (pdev->dev.of_node) {
 		err = of_dma_controller_register(pdev->dev.of_node,
-						 dw_dma_xlate, dw);
-		if (err && err != -ENODEV)
+						 dw_dma_of_xlate, dw);
+		if (err)
 			dev_err(&pdev->dev,
 				"could not register of_dma_controller\n");
 	}
@@ -1912,11 +1897,11 @@ static const struct dev_pm_ops dw_dev_pm_ops = {
 };
 
 #ifdef CONFIG_OF
-static const struct of_device_id dw_dma_id_table[] = {
+static const struct of_device_id dw_dma_of_id_table[] = {
 	{ .compatible = "snps,dma-spear1340" },
 	{}
 };
-MODULE_DEVICE_TABLE(of, dw_dma_id_table);
+MODULE_DEVICE_TABLE(of, dw_dma_of_id_table);
 #endif
 
 static const struct platform_device_id dw_dma_ids[] = {
@@ -1932,7 +1917,7 @@ static struct platform_driver dw_driver = {
 	.driver = {
 		.name	= "dw_dmac",
 		.pm	= &dw_dev_pm_ops,
-		.of_match_table = of_match_ptr(dw_dma_id_table),
+		.of_match_table = of_match_ptr(dw_dma_of_id_table),
 	},
 	.id_table	= dw_dma_ids,
 };
diff --git a/drivers/dma/dw_dmac_regs.h b/drivers/dma/dw_dmac_regs.h
index 4d02c36..9b0e12e 100644
--- a/drivers/dma/dw_dmac_regs.h
+++ b/drivers/dma/dw_dmac_regs.h
@@ -212,8 +212,11 @@ struct dw_dma_chan {
 	/* hardware configuration */
 	unsigned int		block_size;
 	bool			nollp;
+
+	/* custom slave configuration */
 	unsigned int		request_line;
-	struct dw_dma_slave	slave;
+	unsigned char		src_master;
+	unsigned char		dst_master;
 
 	/* configuration passed via DMA_SLAVE_CONFIG */
 	struct dma_slave_config dma_sconfig;
diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c
index 70b8975..f285833 100644
--- a/drivers/dma/imx-dma.c
+++ b/drivers/dma/imx-dma.c
@@ -859,8 +859,7 @@ static struct dma_async_tx_descriptor *imxdma_prep_dma_cyclic(
 
 	desc = list_first_entry(&imxdmac->ld_free, struct imxdma_desc, node);
 
-	if (imxdmac->sg_list)
-		kfree(imxdmac->sg_list);
+	kfree(imxdmac->sg_list);
 
 	imxdmac->sg_list = kcalloc(periods + 1,
 			sizeof(struct scatterlist), GFP_KERNEL);
@@ -1145,7 +1144,7 @@ err:
 	return ret;
 }
 
-static int __exit imxdma_remove(struct platform_device *pdev)
+static int imxdma_remove(struct platform_device *pdev)
 {
 	struct imxdma_engine *imxdma = platform_get_drvdata(pdev);
 
@@ -1162,7 +1161,7 @@ static struct platform_driver imxdma_driver = {
 		.name	= "imx-dma",
 	},
 	.id_table	= imx_dma_devtype,
-	.remove		= __exit_p(imxdma_remove),
+	.remove		= imxdma_remove,
 };
 
 static int __init imxdma_module_init(void)
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index f082aa3..092867b 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -1462,7 +1462,7 @@ err_irq:
 	return ret;
 }
 
-static int __exit sdma_remove(struct platform_device *pdev)
+static int sdma_remove(struct platform_device *pdev)
 {
 	return -EBUSY;
 }
@@ -1473,7 +1473,7 @@ static struct platform_driver sdma_driver = {
 		.of_match_table = sdma_dt_ids,
 	},
 	.id_table	= sdma_devtypes,
-	.remove		= __exit_p(sdma_remove),
+	.remove		= sdma_remove,
 };
 
 static int __init sdma_module_init(void)
diff --git a/drivers/dma/ioat/dca.c b/drivers/dma/ioat/dca.c
index 9b04185..9e84d5b 100644
--- a/drivers/dma/ioat/dca.c
+++ b/drivers/dma/ioat/dca.c
@@ -470,8 +470,10 @@ struct dca_provider *ioat2_dca_init(struct pci_dev *pdev, void __iomem *iobase)
 	}
 
 	if (!dca2_tag_map_valid(ioatdca->tag_map)) {
-		dev_err(&pdev->dev, "APICID_TAG_MAP set incorrectly by BIOS, "
-			"disabling DCA\n");
+		WARN_TAINT_ONCE(1, TAINT_FIRMWARE_WORKAROUND,
+				"%s %s: APICID_TAG_MAP set incorrectly by BIOS, disabling DCA\n",
+				dev_driver_string(&pdev->dev),
+				dev_name(&pdev->dev));
 		free_dca_provider(dca);
 		return NULL;
 	}
@@ -689,7 +691,10 @@ struct dca_provider *ioat3_dca_init(struct pci_dev *pdev, void __iomem *iobase)
 	}
 
 	if (dca3_tag_map_invalid(ioatdca->tag_map)) {
-		dev_err(&pdev->dev, "APICID_TAG_MAP set incorrectly by BIOS, disabling DCA\n");
+		WARN_TAINT_ONCE(1, TAINT_FIRMWARE_WORKAROUND,
+				"%s %s: APICID_TAG_MAP set incorrectly by BIOS, disabling DCA\n",
+				dev_driver_string(&pdev->dev),
+				dev_name(&pdev->dev));
 		free_dca_provider(dca);
 		return NULL;
 	}
diff --git a/drivers/dma/ioat/dma.h b/drivers/dma/ioat/dma.h
index 53a4cbb..95ae7b3 100644
--- a/drivers/dma/ioat/dma.h
+++ b/drivers/dma/ioat/dma.h
@@ -179,7 +179,7 @@ __dump_desc_dbg(struct ioat_chan_common *chan, struct ioat_dma_descriptor *hw,
 	struct device *dev = to_dev(chan);
 
 	dev_dbg(dev, "desc[%d]: (%#llx->%#llx) cookie: %d flags: %#x"
-		" ctl: %#x (op: %d int_en: %d compl: %d)\n", id,
+		" ctl: %#10.8x (op: %#x int_en: %d compl: %d)\n", id,
 		(unsigned long long) tx->phys,
 		(unsigned long long) hw->next, tx->cookie, tx->flags,
 		hw->ctl, hw->ctl_f.op, hw->ctl_f.int_en, hw->ctl_f.compl_write);
diff --git a/drivers/dma/ioat/dma_v3.c b/drivers/dma/ioat/dma_v3.c
index e8336cce..a1dcfb2 100644
--- a/drivers/dma/ioat/dma_v3.c
+++ b/drivers/dma/ioat/dma_v3.c
@@ -605,7 +605,7 @@ dump_pq_desc_dbg(struct ioat2_dma_chan *ioat, struct ioat_ring_ent *desc, struct
 	int i;
 
 	dev_dbg(dev, "desc[%d]: (%#llx->%#llx) flags: %#x"
-		" sz: %#x ctl: %#x (op: %d int: %d compl: %d pq: '%s%s' src_cnt: %d)\n",
+		" sz: %#10.8x ctl: %#x (op: %#x int: %d compl: %d pq: '%s%s' src_cnt: %d)\n",
 		desc_id(desc), (unsigned long long) desc->txd.phys,
 		(unsigned long long) (pq_ex ? pq_ex->next : pq->next),
 		desc->txd.flags, pq->size, pq->ctl, pq->ctl_f.op, pq->ctl_f.int_en,
@@ -617,6 +617,7 @@ dump_pq_desc_dbg(struct ioat2_dma_chan *ioat, struct ioat_ring_ent *desc, struct
 			(unsigned long long) pq_get_src(descs, i), pq->coef[i]);
 	dev_dbg(dev, "\tP: %#llx\n", pq->p_addr);
 	dev_dbg(dev, "\tQ: %#llx\n", pq->q_addr);
+	dev_dbg(dev, "\tNEXT: %#llx\n", pq->next);
 }
 
 static struct dma_async_tx_descriptor *
@@ -1330,15 +1331,9 @@ int ioat3_dma_probe(struct ioatdma_device *device, int dca)
 	}
 
 
-	if (is_raid_device) {
-		dma->device_tx_status = ioat3_tx_status;
-		device->cleanup_fn = ioat3_cleanup_event;
-		device->timer_fn = ioat3_timer_event;
-	} else {
-		dma->device_tx_status = ioat_dma_tx_status;
-		device->cleanup_fn = ioat2_cleanup_event;
-		device->timer_fn = ioat2_timer_event;
-	}
+	dma->device_tx_status = ioat3_tx_status;
+	device->cleanup_fn = ioat3_cleanup_event;
+	device->timer_fn = ioat3_timer_event;
 
 	#ifdef CONFIG_ASYNC_TX_DISABLE_PQ_VAL_DMA
 	dma_cap_clear(DMA_PQ_VAL, dma->cap_mask);
diff --git a/drivers/dma/ipu/ipu_idmac.c b/drivers/dma/ipu/ipu_idmac.c
index 8c61d17..d39c2cd 100644
--- a/drivers/dma/ipu/ipu_idmac.c
+++ b/drivers/dma/ipu/ipu_idmac.c
@@ -1642,7 +1642,7 @@ static int __init ipu_idmac_init(struct ipu *ipu)
 	return dma_async_device_register(&idmac->dma);
 }
 
-static void __exit ipu_idmac_exit(struct ipu *ipu)
+static void ipu_idmac_exit(struct ipu *ipu)
 {
 	int i;
 	struct idmac *idmac = &ipu->idmac;
@@ -1756,7 +1756,7 @@ err_noirq:
 	return ret;
 }
 
-static int __exit ipu_remove(struct platform_device *pdev)
+static int ipu_remove(struct platform_device *pdev)
 {
 	struct ipu *ipu = platform_get_drvdata(pdev);
 
@@ -1781,7 +1781,7 @@ static struct platform_driver ipu_platform_driver = {
 		.name	= "ipu-core",
 		.owner	= THIS_MODULE,
 	},
-	.remove		= __exit_p(ipu_remove),
+	.remove		= ipu_remove,
 };
 
 static int __init ipu_init(void)
diff --git a/drivers/dma/mxs-dma.c b/drivers/dma/mxs-dma.c
index 8f6d30d..b48a79c 100644
--- a/drivers/dma/mxs-dma.c
+++ b/drivers/dma/mxs-dma.c
@@ -27,6 +27,7 @@
 #include <linux/stmp_device.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/of_dma.h>
 
 #include <asm/irq.h>
 
@@ -139,6 +140,8 @@ struct mxs_dma_engine {
 	struct dma_device		dma_device;
 	struct device_dma_parameters	dma_parms;
 	struct mxs_dma_chan		mxs_chans[MXS_DMA_CHANNELS];
+	struct platform_device		*pdev;
+	unsigned int			nr_channels;
 };
 
 struct mxs_dma_type {
@@ -350,10 +353,8 @@ static int mxs_dma_alloc_chan_resources(struct dma_chan *chan)
 	struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
 	int ret;
 
-	if (!data)
-		return -EINVAL;
-
-	mxs_chan->chan_irq = data->chan_irq;
+	if (data)
+		mxs_chan->chan_irq = data->chan_irq;
 
 	mxs_chan->ccw = dma_alloc_coherent(mxs_dma->dma_device.dev,
 				CCW_BLOCK_SIZE, &mxs_chan->ccw_phys,
@@ -665,8 +666,55 @@ err_out:
 	return ret;
 }
 
+struct mxs_dma_filter_param {
+	struct device_node *of_node;
+	unsigned int chan_id;
+};
+
+static bool mxs_dma_filter_fn(struct dma_chan *chan, void *fn_param)
+{
+	struct mxs_dma_filter_param *param = fn_param;
+	struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan);
+	struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
+	int chan_irq;
+
+	if (mxs_dma->dma_device.dev->of_node != param->of_node)
+		return false;
+
+	if (chan->chan_id != param->chan_id)
+		return false;
+
+	chan_irq = platform_get_irq(mxs_dma->pdev, param->chan_id);
+	if (chan_irq < 0)
+		return false;
+
+	mxs_chan->chan_irq = chan_irq;
+
+	return true;
+}
+
+struct dma_chan *mxs_dma_xlate(struct of_phandle_args *dma_spec,
+			       struct of_dma *ofdma)
+{
+	struct mxs_dma_engine *mxs_dma = ofdma->of_dma_data;
+	dma_cap_mask_t mask = mxs_dma->dma_device.cap_mask;
+	struct mxs_dma_filter_param param;
+
+	if (dma_spec->args_count != 1)
+		return NULL;
+
+	param.of_node = ofdma->of_node;
+	param.chan_id = dma_spec->args[0];
+
+	if (param.chan_id >= mxs_dma->nr_channels)
+		return NULL;
+
+	return dma_request_channel(mask, mxs_dma_filter_fn, &param);
+}
+
 static int __init mxs_dma_probe(struct platform_device *pdev)
 {
+	struct device_node *np = pdev->dev.of_node;
 	const struct platform_device_id *id_entry;
 	const struct of_device_id *of_id;
 	const struct mxs_dma_type *dma_type;
@@ -674,10 +722,16 @@ static int __init mxs_dma_probe(struct platform_device *pdev)
 	struct resource *iores;
 	int ret, i;
 
-	mxs_dma = kzalloc(sizeof(*mxs_dma), GFP_KERNEL);
+	mxs_dma = devm_kzalloc(&pdev->dev, sizeof(*mxs_dma), GFP_KERNEL);
 	if (!mxs_dma)
 		return -ENOMEM;
 
+	ret = of_property_read_u32(np, "dma-channels", &mxs_dma->nr_channels);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to read dma-channels\n");
+		return ret;
+	}
+
 	of_id = of_match_device(mxs_dma_dt_ids, &pdev->dev);
 	if (of_id)
 		id_entry = of_id->data;
@@ -689,24 +743,13 @@ static int __init mxs_dma_probe(struct platform_device *pdev)
 	mxs_dma->dev_id = dma_type->id;
 
 	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	mxs_dma->base = devm_ioremap_resource(&pdev->dev, iores);
+	if (IS_ERR(mxs_dma->base))
+		return PTR_ERR(mxs_dma->base);
 
-	if (!request_mem_region(iores->start, resource_size(iores),
-				pdev->name)) {
-		ret = -EBUSY;
-		goto err_request_region;
-	}
-
-	mxs_dma->base = ioremap(iores->start, resource_size(iores));
-	if (!mxs_dma->base) {
-		ret = -ENOMEM;
-		goto err_ioremap;
-	}
-
-	mxs_dma->clk = clk_get(&pdev->dev, NULL);
-	if (IS_ERR(mxs_dma->clk)) {
-		ret = PTR_ERR(mxs_dma->clk);
-		goto err_clk;
-	}
+	mxs_dma->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(mxs_dma->clk))
+		return PTR_ERR(mxs_dma->clk);
 
 	dma_cap_set(DMA_SLAVE, mxs_dma->dma_device.cap_mask);
 	dma_cap_set(DMA_CYCLIC, mxs_dma->dma_device.cap_mask);
@@ -732,8 +775,9 @@ static int __init mxs_dma_probe(struct platform_device *pdev)
 
 	ret = mxs_dma_init(mxs_dma);
 	if (ret)
-		goto err_init;
+		return ret;
 
+	mxs_dma->pdev = pdev;
 	mxs_dma->dma_device.dev = &pdev->dev;
 
 	/* mxs_dma gets 65535 bytes maximum sg size */
@@ -751,22 +795,19 @@ static int __init mxs_dma_probe(struct platform_device *pdev)
 	ret = dma_async_device_register(&mxs_dma->dma_device);
 	if (ret) {
 		dev_err(mxs_dma->dma_device.dev, "unable to register\n");
-		goto err_init;
+		return ret;
+	}
+
+	ret = of_dma_controller_register(np, mxs_dma_xlate, mxs_dma);
+	if (ret) {
+		dev_err(mxs_dma->dma_device.dev,
+			"failed to register controller\n");
+		dma_async_device_unregister(&mxs_dma->dma_device);
 	}
 
 	dev_info(mxs_dma->dma_device.dev, "initialized\n");
 
 	return 0;
-
-err_init:
-	clk_put(mxs_dma->clk);
-err_clk:
-	iounmap(mxs_dma->base);
-err_ioremap:
-	release_mem_region(iores->start, resource_size(iores));
-err_request_region:
-	kfree(mxs_dma);
-	return ret;
 }
 
 static struct platform_driver mxs_dma_driver = {
diff --git a/drivers/dma/of-dma.c b/drivers/dma/of-dma.c
index 69d04d2..8266893 100644
--- a/drivers/dma/of-dma.c
+++ b/drivers/dma/of-dma.c
@@ -36,11 +36,6 @@ static struct of_dma *of_dma_get_controller(struct of_phandle_args *dma_spec)
 
 	spin_lock(&of_dma_lock);
 
-	if (list_empty(&of_dma_list)) {
-		spin_unlock(&of_dma_lock);
-		return NULL;
-	}
-
 	list_for_each_entry(ofdma, &of_dma_list, of_dma_controllers)
 		if ((ofdma->of_node == dma_spec->np) &&
 		    (ofdma->of_dma_nbcells == dma_spec->args_count)) {
@@ -93,6 +88,7 @@ int of_dma_controller_register(struct device_node *np,
 {
 	struct of_dma	*ofdma;
 	int		nbcells;
+	const __be32	*prop;
 
 	if (!np || !of_dma_xlate) {
 		pr_err("%s: not enough information provided\n", __func__);
@@ -103,8 +99,11 @@ int of_dma_controller_register(struct device_node *np,
 	if (!ofdma)
 		return -ENOMEM;
 
-	nbcells = be32_to_cpup(of_get_property(np, "#dma-cells", NULL));
-	if (!nbcells) {
+	prop = of_get_property(np, "#dma-cells", NULL);
+	if (prop)
+		nbcells = be32_to_cpup(prop);
+
+	if (!prop || !nbcells) {
 		pr_err("%s: #dma-cells property is missing or invalid\n",
 		       __func__);
 		kfree(ofdma);
@@ -172,8 +171,8 @@ EXPORT_SYMBOL_GPL(of_dma_controller_free);
  * specifiers, matches the name provided. Returns 0 if the name matches and
  * a valid pointer to the DMA specifier is found. Otherwise returns -ENODEV.
  */
-static int of_dma_match_channel(struct device_node *np, char *name, int index,
-				struct of_phandle_args *dma_spec)
+static int of_dma_match_channel(struct device_node *np, const char *name,
+				int index, struct of_phandle_args *dma_spec)
 {
 	const char *s;
 
@@ -198,7 +197,7 @@ static int of_dma_match_channel(struct device_node *np, char *name, int index,
  * Returns pointer to appropriate dma channel on success or NULL on error.
  */
 struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
-					      char *name)
+					      const char *name)
 {
 	struct of_phandle_args	dma_spec;
 	struct of_dma		*ofdma;
diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c
index c4b4fd2..2ea3d7e 100644
--- a/drivers/dma/omap-dma.c
+++ b/drivers/dma/omap-dma.c
@@ -16,6 +16,8 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
+#include <linux/of_dma.h>
+#include <linux/of_device.h>
 
 #include "virt-dma.h"
 
@@ -67,6 +69,10 @@ static const unsigned es_bytes[] = {
 	[OMAP_DMA_DATA_TYPE_S32] = 4,
 };
 
+static struct of_dma_filter_info omap_dma_info = {
+	.filter_fn = omap_dma_filter_fn,
+};
+
 static inline struct omap_dmadev *to_omap_dma_dev(struct dma_device *d)
 {
 	return container_of(d, struct omap_dmadev, ddev);
@@ -621,8 +627,22 @@ static int omap_dma_probe(struct platform_device *pdev)
 		pr_warn("OMAP-DMA: failed to register slave DMA engine device: %d\n",
 			rc);
 		omap_dma_free(od);
-	} else {
-		platform_set_drvdata(pdev, od);
+		return rc;
+	}
+
+	platform_set_drvdata(pdev, od);
+
+	if (pdev->dev.of_node) {
+		omap_dma_info.dma_cap = od->ddev.cap_mask;
+
+		/* Device-tree DMA controller registration */
+		rc = of_dma_controller_register(pdev->dev.of_node,
+				of_dma_simple_xlate, &omap_dma_info);
+		if (rc) {
+			pr_warn("OMAP-DMA: failed to register DMA controller\n");
+			dma_async_device_unregister(&od->ddev);
+			omap_dma_free(od);
+		}
 	}
 
 	dev_info(&pdev->dev, "OMAP DMA engine driver\n");
@@ -634,18 +654,32 @@ static int omap_dma_remove(struct platform_device *pdev)
 {
 	struct omap_dmadev *od = platform_get_drvdata(pdev);
 
+	if (pdev->dev.of_node)
+		of_dma_controller_free(pdev->dev.of_node);
+
 	dma_async_device_unregister(&od->ddev);
 	omap_dma_free(od);
 
 	return 0;
 }
 
+static const struct of_device_id omap_dma_match[] = {
+	{ .compatible = "ti,omap2420-sdma", },
+	{ .compatible = "ti,omap2430-sdma", },
+	{ .compatible = "ti,omap3430-sdma", },
+	{ .compatible = "ti,omap3630-sdma", },
+	{ .compatible = "ti,omap4430-sdma", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, omap_dma_match);
+
 static struct platform_driver omap_dma_driver = {
 	.probe	= omap_dma_probe,
 	.remove	= omap_dma_remove,
 	.driver = {
 		.name = "omap-dma-engine",
 		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(omap_dma_match),
 	},
 };
 
diff --git a/drivers/dma/pch_dma.c b/drivers/dma/pch_dma.c
index d01faeb..ce3dc3e 100644
--- a/drivers/dma/pch_dma.c
+++ b/drivers/dma/pch_dma.c
@@ -476,7 +476,7 @@ static struct pch_dma_desc *pdc_desc_get(struct pch_dma_chan *pd_chan)
 	dev_dbg(chan2dev(&pd_chan->chan), "scanned %d descriptors\n", i);
 
 	if (!ret) {
-		ret = pdc_alloc_desc(&pd_chan->chan, GFP_NOIO);
+		ret = pdc_alloc_desc(&pd_chan->chan, GFP_ATOMIC);
 		if (ret) {
 			spin_lock(&pd_chan->lock);
 			pd_chan->descs_allocated++;
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index 7181531..a17553f 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -26,6 +26,7 @@
 #include <linux/scatterlist.h>
 #include <linux/of.h>
 #include <linux/of_dma.h>
+#include <linux/err.h>
 
 #include "dmaengine.h"
 #define PL330_MAX_CHAN		8
@@ -2288,13 +2289,12 @@ static inline void fill_queue(struct dma_pl330_chan *pch)
 
 		/* If already submitted */
 		if (desc->status == BUSY)
-			break;
+			continue;
 
 		ret = pl330_submit_req(pch->pl330_chid,
 						&desc->req);
 		if (!ret) {
 			desc->status = BUSY;
-			break;
 		} else if (ret == -EAGAIN) {
 			/* QFull or DMAC Dying */
 			break;
@@ -2882,7 +2882,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
 {
 	struct dma_pl330_platdata *pdat;
 	struct dma_pl330_dmac *pdmac;
-	struct dma_pl330_chan *pch;
+	struct dma_pl330_chan *pch, *_p;
 	struct pl330_info *pi;
 	struct dma_device *pd;
 	struct resource *res;
@@ -2904,9 +2904,9 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
 	pi->mcbufsz = pdat ? pdat->mcbuf_sz : 0;
 
 	res = &adev->res;
-	pi->base = devm_request_and_ioremap(&adev->dev, res);
-	if (!pi->base)
-		return -ENXIO;
+	pi->base = devm_ioremap_resource(&adev->dev, res);
+	if (IS_ERR(pi->base))
+		return PTR_ERR(pi->base);
 
 	amba_set_drvdata(adev, pdmac);
 
@@ -2984,7 +2984,16 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
 	ret = dma_async_device_register(pd);
 	if (ret) {
 		dev_err(&adev->dev, "unable to register DMAC\n");
-		goto probe_err2;
+		goto probe_err3;
+	}
+
+	if (adev->dev.of_node) {
+		ret = of_dma_controller_register(adev->dev.of_node,
+					 of_dma_pl330_xlate, pdmac);
+		if (ret) {
+			dev_err(&adev->dev,
+			"unable to register DMA to the generic DT DMA helpers\n");
+		}
 	}
 
 	dev_info(&adev->dev,
@@ -2995,16 +3004,21 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
 		pi->pcfg.data_bus_width / 8, pi->pcfg.num_chan,
 		pi->pcfg.num_peri, pi->pcfg.num_events);
 
-	ret = of_dma_controller_register(adev->dev.of_node,
-					 of_dma_pl330_xlate, pdmac);
-	if (ret) {
-		dev_err(&adev->dev,
-		"unable to register DMA to the generic DT DMA helpers\n");
-		goto probe_err2;
-	}
-
 	return 0;
+probe_err3:
+	amba_set_drvdata(adev, NULL);
 
+	/* Idle the DMAC */
+	list_for_each_entry_safe(pch, _p, &pdmac->ddma.channels,
+			chan.device_node) {
+
+		/* Remove the channel */
+		list_del(&pch->chan.device_node);
+
+		/* Flush the channel */
+		pl330_control(&pch->chan, DMA_TERMINATE_ALL, 0);
+		pl330_free_chan_resources(&pch->chan);
+	}
 probe_err2:
 	pl330_del(pi);
 probe_err1:
@@ -3023,8 +3037,10 @@ static int pl330_remove(struct amba_device *adev)
 	if (!pdmac)
 		return 0;
 
-	of_dma_controller_free(adev->dev.of_node);
+	if (adev->dev.of_node)
+		of_dma_controller_free(adev->dev.of_node);
 
+	dma_async_device_unregister(&pdmac->ddma);
 	amba_set_drvdata(adev, NULL);
 
 	/* Idle the DMAC */
diff --git a/drivers/dma/sirf-dma.c b/drivers/dma/sirf-dma.c
index 1d627e2..c439529 100644
--- a/drivers/dma/sirf-dma.c
+++ b/drivers/dma/sirf-dma.c
@@ -16,6 +16,7 @@
 #include <linux/of_address.h>
 #include <linux/of_device.h>
 #include <linux/of_platform.h>
+#include <linux/clk.h>
 #include <linux/sirfsoc_dma.h>
 
 #include "dmaengine.h"
@@ -78,6 +79,7 @@ struct sirfsoc_dma {
 	struct sirfsoc_dma_chan		channels[SIRFSOC_DMA_CHANNELS];
 	void __iomem			*base;
 	int				irq;
+	struct clk			*clk;
 	bool				is_marco;
 };
 
@@ -639,6 +641,12 @@ static int sirfsoc_dma_probe(struct platform_device *op)
 		return -EINVAL;
 	}
 
+	sdma->clk = devm_clk_get(dev, NULL);
+	if (IS_ERR(sdma->clk)) {
+		dev_err(dev, "failed to get a clock.\n");
+		return PTR_ERR(sdma->clk);
+	}
+
 	ret = of_address_to_resource(dn, 0, &res);
 	if (ret) {
 		dev_err(dev, "Error parsing memory region!\n");
@@ -698,6 +706,8 @@ static int sirfsoc_dma_probe(struct platform_device *op)
 
 	tasklet_init(&sdma->tasklet, sirfsoc_dma_tasklet, (unsigned long)sdma);
 
+	clk_prepare_enable(sdma->clk);
+
 	/* Register DMA engine */
 	dev_set_drvdata(dev, sdma);
 	ret = dma_async_device_register(dma);
@@ -720,6 +730,7 @@ static int sirfsoc_dma_remove(struct platform_device *op)
 	struct device *dev = &op->dev;
 	struct sirfsoc_dma *sdma = dev_get_drvdata(dev);
 
+	clk_disable_unprepare(sdma->clk);
 	dma_async_device_unregister(&sdma->dma);
 	free_irq(sdma->irq, sdma);
 	irq_dispose_mapping(sdma->irq);
diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c
index fcee27e..5a0b66c 100644
--- a/drivers/dma/tegra20-apb-dma.c
+++ b/drivers/dma/tegra20-apb-dma.c
@@ -1213,7 +1213,6 @@ static const struct tegra_dma_chip_data tegra20_dma_chip_data = {
 	.support_channel_pause	= false,
 };
 
-#if defined(CONFIG_OF)
 /* Tegra30 specific DMA controller information */
 static const struct tegra_dma_chip_data tegra30_dma_chip_data = {
 	.nr_channels		= 32,
@@ -1243,7 +1242,6 @@ static const struct of_device_id tegra_dma_of_match[] = {
 	},
 };
 MODULE_DEVICE_TABLE(of, tegra_dma_of_match);
-#endif
 
 static int tegra_dma_probe(struct platform_device *pdev)
 {
@@ -1252,20 +1250,14 @@ static int tegra_dma_probe(struct platform_device *pdev)
 	int ret;
 	int i;
 	const struct tegra_dma_chip_data *cdata = NULL;
+	const struct of_device_id *match;
 
-	if (pdev->dev.of_node) {
-		const struct of_device_id *match;
-		match = of_match_device(of_match_ptr(tegra_dma_of_match),
-					&pdev->dev);
-		if (!match) {
-			dev_err(&pdev->dev, "Error: No device match found\n");
-			return -ENODEV;
-		}
-		cdata = match->data;
-	} else {
-		/* If no device tree then fallback to tegra20 */
-		cdata = &tegra20_dma_chip_data;
+	match = of_match_device(tegra_dma_of_match, &pdev->dev);
+	if (!match) {
+		dev_err(&pdev->dev, "Error: No device match found\n");
+		return -ENODEV;
 	}
+	cdata = match->data;
 
 	tdma = devm_kzalloc(&pdev->dev, sizeof(*tdma) + cdata->nr_channels *
 			sizeof(struct tegra_dma_channel), GFP_KERNEL);
@@ -1460,7 +1452,7 @@ static struct platform_driver tegra_dmac_driver = {
 		.name	= "tegra-apbdma",
 		.owner = THIS_MODULE,
 		.pm	= &tegra_dma_dev_pm_ops,
-		.of_match_table = of_match_ptr(tegra_dma_of_match),
+		.of_match_table = tegra_dma_of_match,
 	},
 	.probe		= tegra_dma_probe,
 	.remove		= tegra_dma_remove,
diff --git a/drivers/dma/timb_dma.c b/drivers/dma/timb_dma.c
index 952f823..26107ba 100644
--- a/drivers/dma/timb_dma.c
+++ b/drivers/dma/timb_dma.c
@@ -823,7 +823,7 @@ static struct platform_driver td_driver = {
 		.owner  = THIS_MODULE,
 	},
 	.probe	= td_probe,
-	.remove	= __exit_p(td_remove),
+	.remove	= td_remove,
 };
 
 module_platform_driver(td_driver);
diff --git a/drivers/dma/txx9dmac.c b/drivers/dma/txx9dmac.c
index 913f55c..a59fb48 100644
--- a/drivers/dma/txx9dmac.c
+++ b/drivers/dma/txx9dmac.c
@@ -1190,7 +1190,7 @@ static int __init txx9dmac_chan_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __exit txx9dmac_chan_remove(struct platform_device *pdev)
+static int txx9dmac_chan_remove(struct platform_device *pdev)
 {
 	struct txx9dmac_chan *dc = platform_get_drvdata(pdev);
 
@@ -1252,7 +1252,7 @@ static int __init txx9dmac_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __exit txx9dmac_remove(struct platform_device *pdev)
+static int txx9dmac_remove(struct platform_device *pdev)
 {
 	struct txx9dmac_dev *ddev = platform_get_drvdata(pdev);
 
@@ -1299,14 +1299,14 @@ static const struct dev_pm_ops txx9dmac_dev_pm_ops = {
 };
 
 static struct platform_driver txx9dmac_chan_driver = {
-	.remove		= __exit_p(txx9dmac_chan_remove),
+	.remove		= txx9dmac_chan_remove,
 	.driver = {
 		.name	= "txx9dmac-chan",
 	},
 };
 
 static struct platform_driver txx9dmac_driver = {
-	.remove		= __exit_p(txx9dmac_remove),
+	.remove		= txx9dmac_remove,
 	.shutdown	= txx9dmac_shutdown,
 	.driver = {
 		.name	= "txx9dmac",
diff --git a/drivers/eisa/pci_eisa.c b/drivers/eisa/pci_eisa.c
index cdae207..6c3fca9 100644
--- a/drivers/eisa/pci_eisa.c
+++ b/drivers/eisa/pci_eisa.c
@@ -19,10 +19,10 @@
 /* There is only *one* pci_eisa device per machine, right ? */
 static struct eisa_root_device pci_eisa_root;
 
-static int __init pci_eisa_init(struct pci_dev *pdev,
-				const struct pci_device_id *ent)
+static int __init pci_eisa_init(struct pci_dev *pdev)
 {
-	int rc;
+	int rc, i;
+	struct resource *res, *bus_res = NULL;
 
 	if ((rc = pci_enable_device (pdev))) {
 		printk (KERN_ERR "pci_eisa : Could not enable device %s\n",
@@ -30,9 +30,30 @@ static int __init pci_eisa_init(struct pci_dev *pdev,
 		return rc;
 	}
 
+	/*
+	 * The Intel 82375 PCI-EISA bridge is a subtractive-decode PCI
+	 * device, so the resources available on EISA are the same as those
+	 * available on the 82375 bus.  This works the same as a PCI-PCI
+	 * bridge in subtractive-decode mode (see pci_read_bridge_bases()).
+	 * We assume other PCI-EISA bridges are similar.
+	 *
+	 * eisa_root_register() can only deal with a single io port resource,
+	*  so we use the first valid io port resource.
+	 */
+	pci_bus_for_each_resource(pdev->bus, res, i)
+		if (res && (res->flags & IORESOURCE_IO)) {
+			bus_res = res;
+			break;
+		}
+
+	if (!bus_res) {
+		dev_err(&pdev->dev, "No resources available\n");
+		return -1;
+	}
+
 	pci_eisa_root.dev              = &pdev->dev;
-	pci_eisa_root.res	       = pdev->bus->resource[0];
-	pci_eisa_root.bus_base_addr    = pdev->bus->resource[0]->start;
+	pci_eisa_root.res	       = bus_res;
+	pci_eisa_root.bus_base_addr    = bus_res->start;
 	pci_eisa_root.slots	       = EISA_MAX_SLOTS;
 	pci_eisa_root.dma_mask         = pdev->dma_mask;
 	dev_set_drvdata(pci_eisa_root.dev, &pci_eisa_root);
@@ -45,22 +66,26 @@ static int __init pci_eisa_init(struct pci_dev *pdev,
 	return 0;
 }
 
-static struct pci_device_id pci_eisa_pci_tbl[] = {
-	{ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
-	  PCI_CLASS_BRIDGE_EISA << 8, 0xffff00, 0 },
-	{ 0, }
-};
+/*
+ * We have to call pci_eisa_init_early() before pnpacpi_init()/isapnp_init().
+ *   Otherwise pnp resource will get enabled early and could prevent eisa
+ *   to be initialized.
+ * Also need to make sure pci_eisa_init_early() is called after
+ * x86/pci_subsys_init().
+ * So need to use subsys_initcall_sync with it.
+ */
+static int __init pci_eisa_init_early(void)
+{
+	struct pci_dev *dev = NULL;
+	int ret;
 
-static struct pci_driver __refdata pci_eisa_driver = {
-	.name		= "pci_eisa",
-	.id_table	= pci_eisa_pci_tbl,
-	.probe		= pci_eisa_init,
-};
+	for_each_pci_dev(dev)
+		if ((dev->class >> 8) == PCI_CLASS_BRIDGE_EISA) {
+			ret = pci_eisa_init(dev);
+			if (ret)
+				return ret;
+		}
 
-static int __init pci_eisa_init_module (void)
-{
-	return pci_register_driver (&pci_eisa_driver);
+	return 0;
 }
-
-device_initcall(pci_eisa_init_module);
-MODULE_DEVICE_TABLE(pci, pci_eisa_pci_tbl);
+subsys_initcall_sync(pci_eisa_init_early);
diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c
index dc357a4..7a1b4a7 100644
--- a/drivers/extcon/extcon-arizona.c
+++ b/drivers/extcon/extcon-arizona.c
@@ -33,12 +33,17 @@
 #include <linux/mfd/arizona/pdata.h>
 #include <linux/mfd/arizona/registers.h>
 
-#define ARIZONA_NUM_BUTTONS 6
+#define ARIZONA_MAX_MICD_RANGE 8
 
 #define ARIZONA_ACCDET_MODE_MIC 0
 #define ARIZONA_ACCDET_MODE_HPL 1
 #define ARIZONA_ACCDET_MODE_HPR 2
 
+#define ARIZONA_HPDET_MAX 10000
+
+#define HPDET_DEBOUNCE 500
+#define DEFAULT_MICD_TIMEOUT 2000
+
 struct arizona_extcon_info {
 	struct device *dev;
 	struct arizona *arizona;
@@ -46,17 +51,27 @@ struct arizona_extcon_info {
 	struct regulator *micvdd;
 	struct input_dev *input;
 
+	u16 last_jackdet;
+
 	int micd_mode;
 	const struct arizona_micd_config *micd_modes;
 	int micd_num_modes;
 
+	const struct arizona_micd_range *micd_ranges;
+	int num_micd_ranges;
+
+	int micd_timeout;
+
 	bool micd_reva;
 	bool micd_clamp;
 
 	struct delayed_work hpdet_work;
+	struct delayed_work micd_detect_work;
+	struct delayed_work micd_timeout_work;
 
 	bool hpdet_active;
 	bool hpdet_done;
+	bool hpdet_retried;
 
 	int num_hpdet_res;
 	unsigned int hpdet_res[3];
@@ -71,20 +86,25 @@ struct arizona_extcon_info {
 };
 
 static const struct arizona_micd_config micd_default_modes[] = {
-	{ 0,                  2 << ARIZONA_MICD_BIAS_SRC_SHIFT, 1 },
 	{ ARIZONA_ACCDET_SRC, 1 << ARIZONA_MICD_BIAS_SRC_SHIFT, 0 },
+	{ 0,                  2 << ARIZONA_MICD_BIAS_SRC_SHIFT, 1 },
 };
 
-static struct {
-	u16 status;
-	int report;
-} arizona_lvl_to_key[ARIZONA_NUM_BUTTONS] = {
-	{  0x1, BTN_0 },
-	{  0x2, BTN_1 },
-	{  0x4, BTN_2 },
-	{  0x8, BTN_3 },
-	{ 0x10, BTN_4 },
-	{ 0x20, BTN_5 },
+static const struct arizona_micd_range micd_default_ranges[] = {
+	{ .max =  11, .key = BTN_0 },
+	{ .max =  28, .key = BTN_1 },
+	{ .max =  54, .key = BTN_2 },
+	{ .max = 100, .key = BTN_3 },
+	{ .max = 186, .key = BTN_4 },
+	{ .max = 430, .key = BTN_5 },
+};
+
+static const int arizona_micd_levels[] = {
+	3, 6, 8, 11, 13, 16, 18, 21, 23, 26, 28, 31, 34, 36, 39, 41, 44, 46,
+	49, 52, 54, 57, 60, 62, 65, 67, 70, 73, 75, 78, 81, 83, 89, 94, 100,
+	105, 111, 116, 122, 127, 139, 150, 161, 173, 186, 196, 209, 220, 245,
+	270, 295, 321, 348, 375, 402, 430, 489, 550, 614, 681, 752, 903, 1071,
+	1257,
 };
 
 #define ARIZONA_CABLE_MECHANICAL 0
@@ -100,10 +120,63 @@ static const char *arizona_cable[] = {
 	NULL,
 };
 
+static void arizona_start_hpdet_acc_id(struct arizona_extcon_info *info);
+
+static void arizona_extcon_do_magic(struct arizona_extcon_info *info,
+				    unsigned int magic)
+{
+	struct arizona *arizona = info->arizona;
+	int ret;
+
+	mutex_lock(&arizona->dapm->card->dapm_mutex);
+
+	arizona->hpdet_magic = magic;
+
+	/* Keep the HP output stages disabled while doing the magic */
+	if (magic) {
+		ret = regmap_update_bits(arizona->regmap,
+					 ARIZONA_OUTPUT_ENABLES_1,
+					 ARIZONA_OUT1L_ENA |
+					 ARIZONA_OUT1R_ENA, 0);
+		if (ret != 0)
+			dev_warn(arizona->dev,
+				"Failed to disable headphone outputs: %d\n",
+				 ret);
+	}
+
+	ret = regmap_update_bits(arizona->regmap, 0x225, 0x4000,
+				 magic);
+	if (ret != 0)
+		dev_warn(arizona->dev, "Failed to do magic: %d\n",
+				 ret);
+
+	ret = regmap_update_bits(arizona->regmap, 0x226, 0x4000,
+				 magic);
+	if (ret != 0)
+		dev_warn(arizona->dev, "Failed to do magic: %d\n",
+			 ret);
+
+	/* Restore the desired state while not doing the magic */
+	if (!magic) {
+		ret = regmap_update_bits(arizona->regmap,
+					 ARIZONA_OUTPUT_ENABLES_1,
+					 ARIZONA_OUT1L_ENA |
+					 ARIZONA_OUT1R_ENA, arizona->hp_ena);
+		if (ret != 0)
+			dev_warn(arizona->dev,
+				 "Failed to restore headphone outputs: %d\n",
+				 ret);
+	}
+
+	mutex_unlock(&arizona->dapm->card->dapm_mutex);
+}
+
 static void arizona_extcon_set_mode(struct arizona_extcon_info *info, int mode)
 {
 	struct arizona *arizona = info->arizona;
 
+	mode %= info->micd_num_modes;
+
 	if (arizona->pdata.micd_pol_gpio > 0)
 		gpio_set_value_cansleep(arizona->pdata.micd_pol_gpio,
 					info->micd_modes[mode].gpio);
@@ -330,7 +403,7 @@ static int arizona_hpdet_read(struct arizona_extcon_info *info)
 		/* If we go out of range report top of range */
 		if (val < 100 || val > 0x3fb) {
 			dev_dbg(arizona->dev, "Measurement out of range\n");
-			return 10000;
+			return ARIZONA_HPDET_MAX;
 		}
 
 		dev_dbg(arizona->dev, "HPDET read %d in range %d\n",
@@ -391,7 +464,8 @@ static int arizona_hpdet_read(struct arizona_extcon_info *info)
 	return val;
 }
 
-static int arizona_hpdet_do_id(struct arizona_extcon_info *info, int *reading)
+static int arizona_hpdet_do_id(struct arizona_extcon_info *info, int *reading,
+			       bool *mic)
 {
 	struct arizona *arizona = info->arizona;
 	int id_gpio = arizona->pdata.hpdet_id_gpio;
@@ -403,32 +477,8 @@ static int arizona_hpdet_do_id(struct arizona_extcon_info *info, int *reading)
 	if (arizona->pdata.hpdet_acc_id) {
 		info->hpdet_res[info->num_hpdet_res++] = *reading;
 
-		/*
-		 * If the impedence is too high don't measure the
-		 * second ground.
-		 */
-		if (info->num_hpdet_res == 1 && *reading >= 45) {
-			dev_dbg(arizona->dev, "Skipping ground flip\n");
-			info->hpdet_res[info->num_hpdet_res++] = *reading;
-		}
-
-		if (info->num_hpdet_res == 1) {
-			dev_dbg(arizona->dev, "Flipping ground\n");
-
-			regmap_update_bits(arizona->regmap,
-					   ARIZONA_ACCESSORY_DETECT_MODE_1,
-					   ARIZONA_ACCDET_SRC,
-					   ~info->micd_modes[0].src);
-
-			regmap_update_bits(arizona->regmap,
-					   ARIZONA_HEADPHONE_DETECT_1,
-					   ARIZONA_HP_POLL, ARIZONA_HP_POLL);
-			return -EAGAIN;
-		}
-
 		/* Only check the mic directly if we didn't already ID it */
-		if (id_gpio && info->num_hpdet_res == 2 &&
-		    !((info->hpdet_res[0] > info->hpdet_res[1] * 2))) {
+		if (id_gpio && info->num_hpdet_res == 1) {
 			dev_dbg(arizona->dev, "Measuring mic\n");
 
 			regmap_update_bits(arizona->regmap,
@@ -447,22 +497,28 @@ static int arizona_hpdet_do_id(struct arizona_extcon_info *info, int *reading)
 		}
 
 		/* OK, got both.  Now, compare... */
-		dev_dbg(arizona->dev, "HPDET measured %d %d %d\n",
-			info->hpdet_res[0], info->hpdet_res[1],
-			info->hpdet_res[2]);
-
+		dev_dbg(arizona->dev, "HPDET measured %d %d\n",
+			info->hpdet_res[0], info->hpdet_res[1]);
 
 		/* Take the headphone impedance for the main report */
 		*reading = info->hpdet_res[0];
 
+		/* Sometimes we get false readings due to slow insert */
+		if (*reading >= ARIZONA_HPDET_MAX && !info->hpdet_retried) {
+			dev_dbg(arizona->dev, "Retrying high impedance\n");
+			info->num_hpdet_res = 0;
+			info->hpdet_retried = true;
+			arizona_start_hpdet_acc_id(info);
+			pm_runtime_put(info->dev);
+			return -EAGAIN;
+		}
+
 		/*
-		 * Either the two grounds measure differently or we
-		 * measure the mic as high impedance.
+		 * If we measure the mic as 
 		 */
-		if ((info->hpdet_res[0] > info->hpdet_res[1] * 2) ||
-		    (id_gpio && info->hpdet_res[2] > 10)) {
+		if (!id_gpio || info->hpdet_res[1] > 50) {
 			dev_dbg(arizona->dev, "Detected mic\n");
-			info->mic = true;
+			*mic = true;
 			info->detecting = true;
 		} else {
 			dev_dbg(arizona->dev, "Detected headphone\n");
@@ -484,8 +540,8 @@ static irqreturn_t arizona_hpdet_irq(int irq, void *data)
 	struct arizona *arizona = info->arizona;
 	int id_gpio = arizona->pdata.hpdet_id_gpio;
 	int report = ARIZONA_CABLE_HEADPHONE;
-	unsigned int val;
 	int ret, reading;
+	bool mic = false;
 
 	mutex_lock(&info->lock);
 
@@ -521,7 +577,7 @@ static irqreturn_t arizona_hpdet_irq(int irq, void *data)
 			   ARIZONA_HP_IMPEDANCE_RANGE_MASK | ARIZONA_HP_POLL,
 			   0);
 
-	ret = arizona_hpdet_do_id(info, &reading);
+	ret = arizona_hpdet_do_id(info, &reading, &mic);
 	if (ret == -EAGAIN) {
 		goto out;
 	} else if (ret < 0) {
@@ -539,28 +595,7 @@ static irqreturn_t arizona_hpdet_irq(int irq, void *data)
 		dev_err(arizona->dev, "Failed to report HP/line: %d\n",
 			ret);
 
-	mutex_lock(&arizona->dapm->card->dapm_mutex);
-
-	ret = regmap_read(arizona->regmap, ARIZONA_OUTPUT_ENABLES_1, &val);
-	if (ret != 0) {
-		dev_err(arizona->dev, "Failed to read output enables: %d\n",
-			ret);
-		val = 0;
-	}
-
-	if (!(val & (ARIZONA_OUT1L_ENA | ARIZONA_OUT1R_ENA))) {
-		ret = regmap_update_bits(arizona->regmap, 0x225, 0x4000, 0);
-		if (ret != 0)
-			dev_warn(arizona->dev, "Failed to undo magic: %d\n",
-				 ret);
-
-		ret = regmap_update_bits(arizona->regmap, 0x226, 0x4000, 0);
-		if (ret != 0)
-			dev_warn(arizona->dev, "Failed to undo magic: %d\n",
-				 ret);
-	}
-
-	mutex_unlock(&arizona->dapm->card->dapm_mutex);
+	arizona_extcon_do_magic(info, 0);
 
 done:
 	if (id_gpio)
@@ -572,7 +607,7 @@ done:
 			   ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC);
 
 	/* If we have a mic then reenable MICDET */
-	if (info->mic)
+	if (mic || info->mic)
 		arizona_start_mic(info);
 
 	if (info->hpdet_active) {
@@ -606,13 +641,7 @@ static void arizona_identify_headphone(struct arizona_extcon_info *info)
 	if (info->mic)
 		arizona_stop_mic(info);
 
-	ret = regmap_update_bits(arizona->regmap, 0x225, 0x4000, 0x4000);
-	if (ret != 0)
-		dev_warn(arizona->dev, "Failed to do magic: %d\n", ret);
-
-	ret = regmap_update_bits(arizona->regmap, 0x226, 0x4000, 0x4000);
-	if (ret != 0)
-		dev_warn(arizona->dev, "Failed to do magic: %d\n", ret);
+	arizona_extcon_do_magic(info, 0x4000);
 
 	ret = regmap_update_bits(arizona->regmap,
 				 ARIZONA_ACCESSORY_DETECT_MODE_1,
@@ -653,7 +682,8 @@ err:
 static void arizona_start_hpdet_acc_id(struct arizona_extcon_info *info)
 {
 	struct arizona *arizona = info->arizona;
-	unsigned int val;
+	int hp_reading = 32;
+	bool mic;
 	int ret;
 
 	dev_dbg(arizona->dev, "Starting identification via HPDET\n");
@@ -663,32 +693,7 @@ static void arizona_start_hpdet_acc_id(struct arizona_extcon_info *info)
 
 	info->hpdet_active = true;
 
-	arizona_extcon_pulse_micbias(info);
-
-	mutex_lock(&arizona->dapm->card->dapm_mutex);
-
-	ret = regmap_read(arizona->regmap, ARIZONA_OUTPUT_ENABLES_1, &val);
-	if (ret != 0) {
-		dev_err(arizona->dev, "Failed to read output enables: %d\n",
-			ret);
-		val = 0;
-	}
-
-	if (!(val & (ARIZONA_OUT1L_ENA | ARIZONA_OUT1R_ENA))) {
-		ret = regmap_update_bits(arizona->regmap, 0x225, 0x4000,
-					 0x4000);
-		if (ret != 0)
-			dev_warn(arizona->dev, "Failed to do magic: %d\n",
-				 ret);
-
-		ret = regmap_update_bits(arizona->regmap, 0x226, 0x4000,
-					 0x4000);
-		if (ret != 0)
-			dev_warn(arizona->dev, "Failed to do magic: %d\n",
-				 ret);
-	}
-
-	mutex_unlock(&arizona->dapm->card->dapm_mutex);
+	arizona_extcon_do_magic(info, 0x4000);
 
 	ret = regmap_update_bits(arizona->regmap,
 				 ARIZONA_ACCESSORY_DETECT_MODE_1,
@@ -700,12 +705,18 @@ static void arizona_start_hpdet_acc_id(struct arizona_extcon_info *info)
 		goto err;
 	}
 
-	ret = regmap_update_bits(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1,
-				 ARIZONA_HP_POLL, ARIZONA_HP_POLL);
-	if (ret != 0) {
-		dev_err(arizona->dev, "Can't start HPDETL measurement: %d\n",
-			ret);
-		goto err;
+	if (arizona->pdata.hpdet_acc_id_line) {
+		ret = regmap_update_bits(arizona->regmap,
+					 ARIZONA_HEADPHONE_DETECT_1,
+					 ARIZONA_HP_POLL, ARIZONA_HP_POLL);
+		if (ret != 0) {
+			dev_err(arizona->dev,
+				"Can't start HPDETL measurement: %d\n",
+				ret);
+			goto err;
+		}
+	} else {
+		arizona_hpdet_do_id(info, &hp_reading, &mic);
 	}
 
 	return;
@@ -724,28 +735,58 @@ err:
 	info->hpdet_active = false;
 }
 
-static irqreturn_t arizona_micdet(int irq, void *data)
+static void arizona_micd_timeout_work(struct work_struct *work)
 {
-	struct arizona_extcon_info *info = data;
+	struct arizona_extcon_info *info = container_of(work,
+							struct arizona_extcon_info,
+							micd_timeout_work.work);
+
+	mutex_lock(&info->lock);
+
+	dev_dbg(info->arizona->dev, "MICD timed out, reporting HP\n");
+	arizona_identify_headphone(info);
+
+	info->detecting = false;
+
+	arizona_stop_mic(info);
+
+	mutex_unlock(&info->lock);
+}
+
+static void arizona_micd_detect(struct work_struct *work)
+{
+	struct arizona_extcon_info *info = container_of(work,
+							struct arizona_extcon_info,
+							micd_detect_work.work);
 	struct arizona *arizona = info->arizona;
-	unsigned int val, lvl;
-	int ret, i;
+	unsigned int val = 0, lvl;
+	int ret, i, key;
+
+	cancel_delayed_work_sync(&info->micd_timeout_work);
 
 	mutex_lock(&info->lock);
 
-	ret = regmap_read(arizona->regmap, ARIZONA_MIC_DETECT_3, &val);
-	if (ret != 0) {
-		dev_err(arizona->dev, "Failed to read MICDET: %d\n", ret);
-		mutex_unlock(&info->lock);
-		return IRQ_NONE;
-	}
+	for (i = 0; i < 10 && !(val & 0x7fc); i++) {
+		ret = regmap_read(arizona->regmap, ARIZONA_MIC_DETECT_3, &val);
+		if (ret != 0) {
+			dev_err(arizona->dev, "Failed to read MICDET: %d\n", ret);
+			mutex_unlock(&info->lock);
+			return;
+		}
 
-	dev_dbg(arizona->dev, "MICDET: %x\n", val);
+		dev_dbg(arizona->dev, "MICDET: %x\n", val);
+
+		if (!(val & ARIZONA_MICD_VALID)) {
+			dev_warn(arizona->dev, "Microphone detection state invalid\n");
+			mutex_unlock(&info->lock);
+			return;
+		}
+	}
 
-	if (!(val & ARIZONA_MICD_VALID)) {
-		dev_warn(arizona->dev, "Microphone detection state invalid\n");
+	if (i == 10 && !(val & 0x7fc)) {
+		dev_err(arizona->dev, "Failed to get valid MICDET value\n");
 		mutex_unlock(&info->lock);
-		return IRQ_NONE;
+		return;
 	}
 
 	/* Due to jack detect this should never happen */
@@ -786,7 +827,7 @@ static irqreturn_t arizona_micdet(int irq, void *data)
 	 * impedence then give up and report headphones.
 	 */
 	if (info->detecting && (val & 0x3f8)) {
-		if (info->jack_flips >= info->micd_num_modes) {
+		if (info->jack_flips >= info->micd_num_modes * 10) {
 			dev_dbg(arizona->dev, "Detected HP/line\n");
 			arizona_identify_headphone(info);
 
@@ -816,12 +857,17 @@ static irqreturn_t arizona_micdet(int irq, void *data)
 			lvl = val & ARIZONA_MICD_LVL_MASK;
 			lvl >>= ARIZONA_MICD_LVL_SHIFT;
 
-			for (i = 0; i < ARIZONA_NUM_BUTTONS; i++)
-				if (lvl & arizona_lvl_to_key[i].status)
-					input_report_key(info->input,
-							 arizona_lvl_to_key[i].report,
-							 1);
-			input_sync(info->input);
+			for (i = 0; i < info->num_micd_ranges; i++)
+				input_report_key(info->input,
+						 info->micd_ranges[i].key, 0);
+
+			WARN_ON(!lvl);
+			WARN_ON(ffs(lvl) - 1 >= info->num_micd_ranges);
+			if (lvl && ffs(lvl) - 1 < info->num_micd_ranges) {
+				key = info->micd_ranges[ffs(lvl) - 1].key;
+				input_report_key(info->input, key, 1);
+				input_sync(info->input);
+			}
 
 		} else if (info->detecting) {
 			dev_dbg(arizona->dev, "Headphone detected\n");
@@ -835,16 +881,41 @@ static irqreturn_t arizona_micdet(int irq, void *data)
 		}
 	} else {
 		dev_dbg(arizona->dev, "Mic button released\n");
-		for (i = 0; i < ARIZONA_NUM_BUTTONS; i++)
+		for (i = 0; i < info->num_micd_ranges; i++)
 			input_report_key(info->input,
-					 arizona_lvl_to_key[i].report, 0);
+					 info->micd_ranges[i].key, 0);
 		input_sync(info->input);
 		arizona_extcon_pulse_micbias(info);
 	}
 
 handled:
+	if (info->detecting)
+		schedule_delayed_work(&info->micd_timeout_work,
+				      msecs_to_jiffies(info->micd_timeout));
+
 	pm_runtime_mark_last_busy(info->dev);
 	mutex_unlock(&info->lock);
+}
+
+static irqreturn_t arizona_micdet(int irq, void *data)
+{
+	struct arizona_extcon_info *info = data;
+	struct arizona *arizona = info->arizona;
+	int debounce = arizona->pdata.micd_detect_debounce;
+
+	cancel_delayed_work_sync(&info->micd_detect_work);
+	cancel_delayed_work_sync(&info->micd_timeout_work);
+
+	mutex_lock(&info->lock);
+	if (!info->detecting)
+		debounce = 0;
+	mutex_unlock(&info->lock);
+
+	if (debounce)
+		schedule_delayed_work(&info->micd_detect_work,
+				      msecs_to_jiffies(debounce));
+	else
+		arizona_micd_detect(&info->micd_detect_work.work);
 
 	return IRQ_HANDLED;
 }
@@ -865,11 +936,13 @@ static irqreturn_t arizona_jackdet(int irq, void *data)
 	struct arizona_extcon_info *info = data;
 	struct arizona *arizona = info->arizona;
 	unsigned int val, present, mask;
+	bool cancelled_hp, cancelled_mic;
 	int ret, i;
 
-	pm_runtime_get_sync(info->dev);
+	cancelled_hp = cancel_delayed_work_sync(&info->hpdet_work);
+	cancelled_mic = cancel_delayed_work_sync(&info->micd_timeout_work);
 
-	cancel_delayed_work_sync(&info->hpdet_work);
+	pm_runtime_get_sync(info->dev);
 
 	mutex_lock(&info->lock);
 
@@ -890,7 +963,22 @@ static irqreturn_t arizona_jackdet(int irq, void *data)
 		return IRQ_NONE;
 	}
 
-	if ((val & mask) == present) {
+	val &= mask;
+	if (val == info->last_jackdet) {
+		dev_dbg(arizona->dev, "Suppressing duplicate JACKDET\n");
+		if (cancelled_hp)
+			schedule_delayed_work(&info->hpdet_work,
+					      msecs_to_jiffies(HPDET_DEBOUNCE));
+
+		if (cancelled_mic)
+			schedule_delayed_work(&info->micd_timeout_work,
+					      msecs_to_jiffies(info->micd_timeout));
+
+		goto out;
+	}
+	info->last_jackdet = val;
+
+	if (info->last_jackdet == present) {
 		dev_dbg(arizona->dev, "Detected jack\n");
 		ret = extcon_set_cable_state_(&info->edev,
 					      ARIZONA_CABLE_MECHANICAL, true);
@@ -907,7 +995,7 @@ static irqreturn_t arizona_jackdet(int irq, void *data)
 			arizona_start_mic(info);
 		} else {
 			schedule_delayed_work(&info->hpdet_work,
-					      msecs_to_jiffies(250));
+					      msecs_to_jiffies(HPDET_DEBOUNCE));
 		}
 
 		regmap_update_bits(arizona->regmap,
@@ -923,10 +1011,11 @@ static irqreturn_t arizona_jackdet(int irq, void *data)
 			info->hpdet_res[i] = 0;
 		info->mic = false;
 		info->hpdet_done = false;
+		info->hpdet_retried = false;
 
-		for (i = 0; i < ARIZONA_NUM_BUTTONS; i++)
+		for (i = 0; i < info->num_micd_ranges; i++)
 			input_report_key(info->input,
-					 arizona_lvl_to_key[i].report, 0);
+					 info->micd_ranges[i].key, 0);
 		input_sync(info->input);
 
 		ret = extcon_update_state(&info->edev, 0xffffffff, 0);
@@ -940,6 +1029,11 @@ static irqreturn_t arizona_jackdet(int irq, void *data)
 				   ARIZONA_MICD_CLAMP_DB | ARIZONA_JD1_DB);
 	}
 
+	if (arizona->pdata.micd_timeout)
+		info->micd_timeout = arizona->pdata.micd_timeout;
+	else
+		info->micd_timeout = DEFAULT_MICD_TIMEOUT;
+
 	/* Clear trig_sts to make sure DCVDD is not forced up */
 	regmap_write(arizona->regmap, ARIZONA_AOD_WKUP_AND_TRIG,
 		     ARIZONA_MICD_CLAMP_FALL_TRIG_STS |
@@ -947,6 +1041,7 @@ static irqreturn_t arizona_jackdet(int irq, void *data)
 		     ARIZONA_JD1_FALL_TRIG_STS |
 		     ARIZONA_JD1_RISE_TRIG_STS);
 
+out:
 	mutex_unlock(&info->lock);
 
 	pm_runtime_mark_last_busy(info->dev);
@@ -955,13 +1050,34 @@ static irqreturn_t arizona_jackdet(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
+/* Map a level onto a slot in the register bank */
+static void arizona_micd_set_level(struct arizona *arizona, int index,
+				   unsigned int level)
+{
+	int reg;
+	unsigned int mask;
+
+	reg = ARIZONA_MIC_DETECT_LEVEL_4 - (index / 2);
+
+	if (!(index % 2)) {
+		mask = 0x3f00;
+		level <<= 8;
+	} else {
+		mask = 0x3f;
+	}
+
+	/* Program the level itself */
+	regmap_update_bits(arizona->regmap, reg, mask, level);
+}
+
 static int arizona_extcon_probe(struct platform_device *pdev)
 {
 	struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
 	struct arizona_pdata *pdata;
 	struct arizona_extcon_info *info;
+	unsigned int val;
 	int jack_irq_fall, jack_irq_rise;
-	int ret, mode, i;
+	int ret, mode, i, j;
 
 	if (!arizona->dapm || !arizona->dapm->card)
 		return -EPROBE_DEFER;
@@ -985,7 +1101,10 @@ static int arizona_extcon_probe(struct platform_device *pdev)
 	mutex_init(&info->lock);
 	info->arizona = arizona;
 	info->dev = &pdev->dev;
+	info->last_jackdet = ~(ARIZONA_MICD_CLAMP_STS | ARIZONA_JD1_STS);
 	INIT_DELAYED_WORK(&info->hpdet_work, arizona_hpdet_work);
+	INIT_DELAYED_WORK(&info->micd_detect_work, arizona_micd_detect);
+	INIT_DELAYED_WORK(&info->micd_timeout_work, arizona_micd_timeout_work);
 	platform_set_drvdata(pdev, info);
 
 	switch (arizona->type) {
@@ -1014,6 +1133,17 @@ static int arizona_extcon_probe(struct platform_device *pdev)
 		goto err;
 	}
 
+	info->input = devm_input_allocate_device(&pdev->dev);
+	if (!info->input) {
+		dev_err(arizona->dev, "Can't allocate input dev\n");
+		ret = -ENOMEM;
+		goto err_register;
+	}
+
+	info->input->name = "Headset";
+	info->input->phys = "arizona/extcon";
+	info->input->dev.parent = &pdev->dev;
+
 	if (pdata->num_micd_configs) {
 		info->micd_modes = pdata->micd_configs;
 		info->micd_num_modes = pdata->num_micd_configs;
@@ -1069,15 +1199,79 @@ static int arizona_extcon_probe(struct platform_device *pdev)
 				   arizona->pdata.micd_dbtime
 				   << ARIZONA_MICD_DBTIME_SHIFT);
 
+	BUILD_BUG_ON(ARRAY_SIZE(arizona_micd_levels) != 0x40);
+
+	if (arizona->pdata.num_micd_ranges) {
+		info->micd_ranges = pdata->micd_ranges;
+		info->num_micd_ranges = pdata->num_micd_ranges;
+	} else {
+		info->micd_ranges = micd_default_ranges;
+		info->num_micd_ranges = ARRAY_SIZE(micd_default_ranges);
+	}
+
+	if (arizona->pdata.num_micd_ranges > ARIZONA_MAX_MICD_RANGE) {
+		dev_err(arizona->dev, "Too many MICD ranges: %d\n",
+			arizona->pdata.num_micd_ranges);
+	}
+
+	if (info->num_micd_ranges > 1) {
+		for (i = 1; i < info->num_micd_ranges; i++) {
+			if (info->micd_ranges[i - 1].max >
+			    info->micd_ranges[i].max) {
+				dev_err(arizona->dev,
+					"MICD ranges must be sorted\n");
+				ret = -EINVAL;
+				goto err_input;
+			}
+		}
+	}
+
+	/* Disable all buttons by default */
+	regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_2,
+			   ARIZONA_MICD_LVL_SEL_MASK, 0x81);
+
+	/* Set up all the buttons the user specified */
+	for (i = 0; i < info->num_micd_ranges; i++) {
+		for (j = 0; j < ARRAY_SIZE(arizona_micd_levels); j++)
+			if (arizona_micd_levels[j] >= info->micd_ranges[i].max)
+				break;
+
+		if (j == ARRAY_SIZE(arizona_micd_levels)) {
+			dev_err(arizona->dev, "Unsupported MICD level %d\n",
+				info->micd_ranges[i].max);
+			ret = -EINVAL;
+			goto err_input;
+		}
+
+		dev_dbg(arizona->dev, "%d ohms for MICD threshold %d\n",
+			arizona_micd_levels[j], i);
+
+		arizona_micd_set_level(arizona, i, j);
+		input_set_capability(info->input, EV_KEY,
+				     info->micd_ranges[i].key);
+
+		/* Enable reporting of that range */
+		regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_2,
+				   1 << i, 1 << i);
+	}
+
+	/* Set all the remaining keys to a maximum */
+	for (; i < ARIZONA_MAX_MICD_RANGE; i++)
+		arizona_micd_set_level(arizona, i, 0x3f);
+
 	/*
 	 * If we have a clamp use it, activating in conjunction with
 	 * GPIO5 if that is connected for jack detect operation.
 	 */
 	if (info->micd_clamp) {
 		if (arizona->pdata.jd_gpio5) {
-			/* Put the GPIO into input mode */
+			/* Put the GPIO into input mode with optional pull */
+			val = 0xc101;
+			if (arizona->pdata.jd_gpio5_nopull)
+				val &= ~ARIZONA_GPN_PU;
+
 			regmap_write(arizona->regmap, ARIZONA_GPIO5_CTRL,
-				     0xc101);
+				     val);
 
 			regmap_update_bits(arizona->regmap,
 					   ARIZONA_MICD_CLAMP_CONTROL,
@@ -1096,20 +1290,6 @@ static int arizona_extcon_probe(struct platform_device *pdev)
 
 	arizona_extcon_set_mode(info, 0);
 
-	info->input = devm_input_allocate_device(&pdev->dev);
-	if (!info->input) {
-		dev_err(arizona->dev, "Can't allocate input dev\n");
-		ret = -ENOMEM;
-		goto err_register;
-	}
-
-	for (i = 0; i < ARIZONA_NUM_BUTTONS; i++)
-		input_set_capability(info->input, EV_KEY,
-				     arizona_lvl_to_key[i].report);
-	info->input->name = "Headset";
-	info->input->phys = "arizona/extcon";
-	info->input->dev.parent = &pdev->dev;
-
 	pm_runtime_enable(&pdev->dev);
 	pm_runtime_idle(&pdev->dev);
 	pm_runtime_get_sync(&pdev->dev);
diff --git a/drivers/firewire/Kconfig b/drivers/firewire/Kconfig
index 7224533..7a701a5 100644
--- a/drivers/firewire/Kconfig
+++ b/drivers/firewire/Kconfig
@@ -47,9 +47,9 @@ config FIREWIRE_NET
 	tristate "IP networking over 1394"
 	depends on FIREWIRE && INET
 	help
-	  This enables IPv4 over IEEE 1394, providing IP connectivity with
-	  other implementations of RFC 2734 as found on several operating
-	  systems.  Multicast support is currently limited.
+	  This enables IPv4/IPv6 over IEEE 1394, providing IP connectivity
+	  with other implementations of RFC 2734/3146 as found on several
+	  operating systems.  Multicast support is currently limited.
 
 	  To compile this driver as a module, say M here:  The module will be
 	  called firewire-net.
diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c
index 2b27bff..4d56536 100644
--- a/drivers/firewire/net.c
+++ b/drivers/firewire/net.c
@@ -1,5 +1,6 @@
 /*
  * IPv4 over IEEE 1394, per RFC 2734
+ * IPv6 over IEEE 1394, per RFC 3146
  *
  * Copyright (C) 2009 Jay Fenlason <fenlason@redhat.com>
  *
@@ -28,6 +29,7 @@
 
 #include <asm/unaligned.h>
 #include <net/arp.h>
+#include <net/firewire.h>
 
 /* rx limits */
 #define FWNET_MAX_FRAGMENTS		30 /* arbitrary, > TX queue depth */
@@ -45,6 +47,7 @@
 
 #define IANA_SPECIFIER_ID		0x00005eU
 #define RFC2734_SW_VERSION		0x000001U
+#define RFC3146_SW_VERSION		0x000002U
 
 #define IEEE1394_GASP_HDR_SIZE	8
 
@@ -57,32 +60,10 @@
 #define RFC2374_HDR_LASTFRAG	2	/* last fragment	*/
 #define RFC2374_HDR_INTFRAG	3	/* interior fragment	*/
 
-#define RFC2734_HW_ADDR_LEN	16
-
-struct rfc2734_arp {
-	__be16 hw_type;		/* 0x0018	*/
-	__be16 proto_type;	/* 0x0806       */
-	u8 hw_addr_len;		/* 16		*/
-	u8 ip_addr_len;		/* 4		*/
-	__be16 opcode;		/* ARP Opcode	*/
-	/* Above is exactly the same format as struct arphdr */
-
-	__be64 s_uniq_id;	/* Sender's 64bit EUI			*/
-	u8 max_rec;		/* Sender's max packet size		*/
-	u8 sspd;		/* Sender's max speed			*/
-	__be16 fifo_hi;		/* hi 16bits of sender's FIFO addr	*/
-	__be32 fifo_lo;		/* lo 32bits of sender's FIFO addr	*/
-	__be32 sip;		/* Sender's IP Address			*/
-	__be32 tip;		/* IP Address of requested hw addr	*/
-} __packed;
-
-/* This header format is specific to this driver implementation. */
-#define FWNET_ALEN	8
-#define FWNET_HLEN	10
-struct fwnet_header {
-	u8 h_dest[FWNET_ALEN];	/* destination address */
-	__be16 h_proto;		/* packet type ID field */
-} __packed;
+static bool fwnet_hwaddr_is_multicast(u8 *ha)
+{
+	return !!(*ha & 1);
+}
 
 /* IPv4 and IPv6 encapsulation header */
 struct rfc2734_header {
@@ -191,8 +172,6 @@ struct fwnet_peer {
 	struct list_head peer_link;
 	struct fwnet_device *dev;
 	u64 guid;
-	u64 fifo;
-	__be32 ip;
 
 	/* guarded by dev->lock */
 	struct list_head pd_list; /* received partial datagrams */
@@ -222,6 +201,15 @@ struct fwnet_packet_task {
 };
 
 /*
+ * Get fifo address embedded in hwaddr
+ */
+static __u64 fwnet_hwaddr_fifo(union fwnet_hwaddr *ha)
+{
+	return (u64)get_unaligned_be16(&ha->uc.fifo_hi) << 32
+	       | get_unaligned_be32(&ha->uc.fifo_lo);
+}
+
+/*
  * saddr == NULL means use device source address.
  * daddr == NULL means leave destination address (eg unresolved arp).
  */
@@ -513,10 +501,20 @@ static int fwnet_finish_incoming_packet(struct net_device *net,
 					bool is_broadcast, u16 ether_type)
 {
 	struct fwnet_device *dev;
-	static const __be64 broadcast_hw = cpu_to_be64(~0ULL);
 	int status;
 	__be64 guid;
 
+	switch (ether_type) {
+	case ETH_P_ARP:
+	case ETH_P_IP:
+#if IS_ENABLED(CONFIG_IPV6)
+	case ETH_P_IPV6:
+#endif
+		break;
+	default:
+		goto err;
+	}
+
 	dev = netdev_priv(net);
 	/* Write metadata, and then pass to the receive level */
 	skb->dev = net;
@@ -524,92 +522,11 @@ static int fwnet_finish_incoming_packet(struct net_device *net,
 
 	/*
 	 * Parse the encapsulation header. This actually does the job of
-	 * converting to an ethernet frame header, as well as arp
-	 * conversion if needed. ARP conversion is easier in this
-	 * direction, since we are using ethernet as our backend.
+	 * converting to an ethernet-like pseudo frame header.
 	 */
-	/*
-	 * If this is an ARP packet, convert it. First, we want to make
-	 * use of some of the fields, since they tell us a little bit
-	 * about the sending machine.
-	 */
-	if (ether_type == ETH_P_ARP) {
-		struct rfc2734_arp *arp1394;
-		struct arphdr *arp;
-		unsigned char *arp_ptr;
-		u64 fifo_addr;
-		u64 peer_guid;
-		unsigned sspd;
-		u16 max_payload;
-		struct fwnet_peer *peer;
-		unsigned long flags;
-
-		arp1394   = (struct rfc2734_arp *)skb->data;
-		arp       = (struct arphdr *)skb->data;
-		arp_ptr   = (unsigned char *)(arp + 1);
-		peer_guid = get_unaligned_be64(&arp1394->s_uniq_id);
-		fifo_addr = (u64)get_unaligned_be16(&arp1394->fifo_hi) << 32
-				| get_unaligned_be32(&arp1394->fifo_lo);
-
-		sspd = arp1394->sspd;
-		/* Sanity check.  OS X 10.3 PPC reportedly sends 131. */
-		if (sspd > SCODE_3200) {
-			dev_notice(&net->dev, "sspd %x out of range\n", sspd);
-			sspd = SCODE_3200;
-		}
-		max_payload = fwnet_max_payload(arp1394->max_rec, sspd);
-
-		spin_lock_irqsave(&dev->lock, flags);
-		peer = fwnet_peer_find_by_guid(dev, peer_guid);
-		if (peer) {
-			peer->fifo = fifo_addr;
-
-			if (peer->speed > sspd)
-				peer->speed = sspd;
-			if (peer->max_payload > max_payload)
-				peer->max_payload = max_payload;
-
-			peer->ip = arp1394->sip;
-		}
-		spin_unlock_irqrestore(&dev->lock, flags);
-
-		if (!peer) {
-			dev_notice(&net->dev,
-				   "no peer for ARP packet from %016llx\n",
-				   (unsigned long long)peer_guid);
-			goto no_peer;
-		}
-
-		/*
-		 * Now that we're done with the 1394 specific stuff, we'll
-		 * need to alter some of the data.  Believe it or not, all
-		 * that needs to be done is sender_IP_address needs to be
-		 * moved, the destination hardware address get stuffed
-		 * in and the hardware address length set to 8.
-		 *
-		 * IMPORTANT: The code below overwrites 1394 specific data
-		 * needed above so keep the munging of the data for the
-		 * higher level IP stack last.
-		 */
-
-		arp->ar_hln = 8;
-		/* skip over sender unique id */
-		arp_ptr += arp->ar_hln;
-		/* move sender IP addr */
-		put_unaligned(arp1394->sip, (u32 *)arp_ptr);
-		/* skip over sender IP addr */
-		arp_ptr += arp->ar_pln;
-
-		if (arp->ar_op == htons(ARPOP_REQUEST))
-			memset(arp_ptr, 0, sizeof(u64));
-		else
-			memcpy(arp_ptr, net->dev_addr, sizeof(u64));
-	}
-
-	/* Now add the ethernet header. */
 	guid = cpu_to_be64(dev->card->guid);
 	if (dev_hard_header(skb, net, ether_type,
-			   is_broadcast ? &broadcast_hw : &guid,
+			   is_broadcast ? net->broadcast : net->dev_addr,
 			   NULL, skb->len) >= 0) {
 		struct fwnet_header *eth;
 		u16 *rawp;
@@ -618,7 +535,7 @@ static int fwnet_finish_incoming_packet(struct net_device *net,
 		skb_reset_mac_header(skb);
 		skb_pull(skb, sizeof(*eth));
 		eth = (struct fwnet_header *)skb_mac_header(skb);
-		if (*eth->h_dest & 1) {
+		if (fwnet_hwaddr_is_multicast(eth->h_dest)) {
 			if (memcmp(eth->h_dest, net->broadcast,
 				   net->addr_len) == 0)
 				skb->pkt_type = PACKET_BROADCAST;
@@ -630,7 +547,7 @@ static int fwnet_finish_incoming_packet(struct net_device *net,
 			if (memcmp(eth->h_dest, net->dev_addr, net->addr_len))
 				skb->pkt_type = PACKET_OTHERHOST;
 		}
-		if (ntohs(eth->h_proto) >= 1536) {
+		if (ntohs(eth->h_proto) >= ETH_P_802_3_MIN) {
 			protocol = eth->h_proto;
 		} else {
 			rawp = (u16 *)skb->data;
@@ -652,7 +569,7 @@ static int fwnet_finish_incoming_packet(struct net_device *net,
 
 	return 0;
 
- no_peer:
+ err:
 	net->stats.rx_errors++;
 	net->stats.rx_dropped++;
 
@@ -856,7 +773,12 @@ static void fwnet_receive_broadcast(struct fw_iso_context *context,
 	ver = be32_to_cpu(buf_ptr[1]) & 0xffffff;
 	source_node_id = be32_to_cpu(buf_ptr[0]) >> 16;
 
-	if (specifier_id == IANA_SPECIFIER_ID && ver == RFC2734_SW_VERSION) {
+	if (specifier_id == IANA_SPECIFIER_ID &&
+	    (ver == RFC2734_SW_VERSION
+#if IS_ENABLED(CONFIG_IPV6)
+	     || ver == RFC3146_SW_VERSION
+#endif
+	    )) {
 		buf_ptr += 2;
 		length -= IEEE1394_GASP_HDR_SIZE;
 		fwnet_incoming_packet(dev, buf_ptr, length, source_node_id,
@@ -1059,16 +981,27 @@ static int fwnet_send_packet(struct fwnet_packet_task *ptask)
 		u8 *p;
 		int generation;
 		int node_id;
+		unsigned int sw_version;
 
 		/* ptask->generation may not have been set yet */
 		generation = dev->card->generation;
 		smp_rmb();
 		node_id = dev->card->node_id;
 
+		switch (ptask->skb->protocol) {
+		default:
+			sw_version = RFC2734_SW_VERSION;
+			break;
+#if IS_ENABLED(CONFIG_IPV6)
+		case htons(ETH_P_IPV6):
+			sw_version = RFC3146_SW_VERSION;
+#endif
+		}
+
 		p = skb_push(ptask->skb, IEEE1394_GASP_HDR_SIZE);
 		put_unaligned_be32(node_id << 16 | IANA_SPECIFIER_ID >> 8, p);
 		put_unaligned_be32((IANA_SPECIFIER_ID & 0xff) << 24
-						| RFC2734_SW_VERSION, &p[4]);
+						| sw_version, &p[4]);
 
 		/* We should not transmit if broadcast_channel.valid == 0. */
 		fw_send_request(dev->card, &ptask->transaction,
@@ -1116,6 +1049,62 @@ static int fwnet_send_packet(struct fwnet_packet_task *ptask)
 	return 0;
 }
 
+static void fwnet_fifo_stop(struct fwnet_device *dev)
+{
+	if (dev->local_fifo == FWNET_NO_FIFO_ADDR)
+		return;
+
+	fw_core_remove_address_handler(&dev->handler);
+	dev->local_fifo = FWNET_NO_FIFO_ADDR;
+}
+
+static int fwnet_fifo_start(struct fwnet_device *dev)
+{
+	int retval;
+
+	if (dev->local_fifo != FWNET_NO_FIFO_ADDR)
+		return 0;
+
+	dev->handler.length = 4096;
+	dev->handler.address_callback = fwnet_receive_packet;
+	dev->handler.callback_data = dev;
+
+	retval = fw_core_add_address_handler(&dev->handler,
+					     &fw_high_memory_region);
+	if (retval < 0)
+		return retval;
+
+	dev->local_fifo = dev->handler.offset;
+
+	return 0;
+}
+
+static void __fwnet_broadcast_stop(struct fwnet_device *dev)
+{
+	unsigned u;
+
+	if (dev->broadcast_state != FWNET_BROADCAST_ERROR) {
+		for (u = 0; u < FWNET_ISO_PAGE_COUNT; u++)
+			kunmap(dev->broadcast_rcv_buffer.pages[u]);
+		fw_iso_buffer_destroy(&dev->broadcast_rcv_buffer, dev->card);
+	}
+	if (dev->broadcast_rcv_context) {
+		fw_iso_context_destroy(dev->broadcast_rcv_context);
+		dev->broadcast_rcv_context = NULL;
+	}
+	kfree(dev->broadcast_rcv_buffer_ptrs);
+	dev->broadcast_rcv_buffer_ptrs = NULL;
+	dev->broadcast_state = FWNET_BROADCAST_ERROR;
+}
+
+static void fwnet_broadcast_stop(struct fwnet_device *dev)
+{
+	if (dev->broadcast_state == FWNET_BROADCAST_ERROR)
+		return;
+	fw_iso_context_stop(dev->broadcast_rcv_context);
+	__fwnet_broadcast_stop(dev);
+}
+
 static int fwnet_broadcast_start(struct fwnet_device *dev)
 {
 	struct fw_iso_context *context;
@@ -1124,60 +1113,47 @@ static int fwnet_broadcast_start(struct fwnet_device *dev)
 	unsigned max_receive;
 	struct fw_iso_packet packet;
 	unsigned long offset;
+	void **ptrptr;
 	unsigned u;
 
-	if (dev->local_fifo == FWNET_NO_FIFO_ADDR) {
-		dev->handler.length = 4096;
-		dev->handler.address_callback = fwnet_receive_packet;
-		dev->handler.callback_data = dev;
-
-		retval = fw_core_add_address_handler(&dev->handler,
-					&fw_high_memory_region);
-		if (retval < 0)
-			goto failed_initial;
-
-		dev->local_fifo = dev->handler.offset;
-	}
+	if (dev->broadcast_state != FWNET_BROADCAST_ERROR)
+		return 0;
 
 	max_receive = 1U << (dev->card->max_receive + 1);
 	num_packets = (FWNET_ISO_PAGE_COUNT * PAGE_SIZE) / max_receive;
 
-	if (!dev->broadcast_rcv_context) {
-		void **ptrptr;
-
-		context = fw_iso_context_create(dev->card,
-		    FW_ISO_CONTEXT_RECEIVE, IEEE1394_BROADCAST_CHANNEL,
-		    dev->card->link_speed, 8, fwnet_receive_broadcast, dev);
-		if (IS_ERR(context)) {
-			retval = PTR_ERR(context);
-			goto failed_context_create;
-		}
+	ptrptr = kmalloc(sizeof(void *) * num_packets, GFP_KERNEL);
+	if (!ptrptr) {
+		retval = -ENOMEM;
+		goto failed;
+	}
+	dev->broadcast_rcv_buffer_ptrs = ptrptr;
+
+	context = fw_iso_context_create(dev->card, FW_ISO_CONTEXT_RECEIVE,
+					IEEE1394_BROADCAST_CHANNEL,
+					dev->card->link_speed, 8,
+					fwnet_receive_broadcast, dev);
+	if (IS_ERR(context)) {
+		retval = PTR_ERR(context);
+		goto failed;
+	}
 
-		retval = fw_iso_buffer_init(&dev->broadcast_rcv_buffer,
-		    dev->card, FWNET_ISO_PAGE_COUNT, DMA_FROM_DEVICE);
-		if (retval < 0)
-			goto failed_buffer_init;
+	retval = fw_iso_buffer_init(&dev->broadcast_rcv_buffer, dev->card,
+				    FWNET_ISO_PAGE_COUNT, DMA_FROM_DEVICE);
+	if (retval < 0)
+		goto failed;
 
-		ptrptr = kmalloc(sizeof(void *) * num_packets, GFP_KERNEL);
-		if (!ptrptr) {
-			retval = -ENOMEM;
-			goto failed_ptrs_alloc;
-		}
+	dev->broadcast_state = FWNET_BROADCAST_STOPPED;
 
-		dev->broadcast_rcv_buffer_ptrs = ptrptr;
-		for (u = 0; u < FWNET_ISO_PAGE_COUNT; u++) {
-			void *ptr;
-			unsigned v;
+	for (u = 0; u < FWNET_ISO_PAGE_COUNT; u++) {
+		void *ptr;
+		unsigned v;
 
-			ptr = kmap(dev->broadcast_rcv_buffer.pages[u]);
-			for (v = 0; v < num_packets / FWNET_ISO_PAGE_COUNT; v++)
-				*ptrptr++ = (void *)
-						((char *)ptr + v * max_receive);
-		}
-		dev->broadcast_rcv_context = context;
-	} else {
-		context = dev->broadcast_rcv_context;
+		ptr = kmap(dev->broadcast_rcv_buffer.pages[u]);
+		for (v = 0; v < num_packets / FWNET_ISO_PAGE_COUNT; v++)
+			*ptrptr++ = (void *) ((char *)ptr + v * max_receive);
 	}
+	dev->broadcast_rcv_context = context;
 
 	packet.payload_length = max_receive;
 	packet.interrupt = 1;
@@ -1191,7 +1167,7 @@ static int fwnet_broadcast_start(struct fwnet_device *dev)
 		retval = fw_iso_context_queue(context, &packet,
 				&dev->broadcast_rcv_buffer, offset);
 		if (retval < 0)
-			goto failed_rcv_queue;
+			goto failed;
 
 		offset += max_receive;
 	}
@@ -1201,7 +1177,7 @@ static int fwnet_broadcast_start(struct fwnet_device *dev)
 	retval = fw_iso_context_start(context, -1, 0,
 			FW_ISO_CONTEXT_MATCH_ALL_TAGS); /* ??? sync */
 	if (retval < 0)
-		goto failed_rcv_queue;
+		goto failed;
 
 	/* FIXME: adjust it according to the min. speed of all known peers? */
 	dev->broadcast_xmt_max_payload = IEEE1394_MAX_PAYLOAD_S100
@@ -1210,19 +1186,8 @@ static int fwnet_broadcast_start(struct fwnet_device *dev)
 
 	return 0;
 
- failed_rcv_queue:
-	kfree(dev->broadcast_rcv_buffer_ptrs);
-	dev->broadcast_rcv_buffer_ptrs = NULL;
- failed_ptrs_alloc:
-	fw_iso_buffer_destroy(&dev->broadcast_rcv_buffer, dev->card);
- failed_buffer_init:
-	fw_iso_context_destroy(context);
-	dev->broadcast_rcv_context = NULL;
- failed_context_create:
-	fw_core_remove_address_handler(&dev->handler);
- failed_initial:
-	dev->local_fifo = FWNET_NO_FIFO_ADDR;
-
+ failed:
+	__fwnet_broadcast_stop(dev);
 	return retval;
 }
 
@@ -1240,11 +1205,10 @@ static int fwnet_open(struct net_device *net)
 	struct fwnet_device *dev = netdev_priv(net);
 	int ret;
 
-	if (dev->broadcast_state == FWNET_BROADCAST_ERROR) {
-		ret = fwnet_broadcast_start(dev);
-		if (ret)
-			return ret;
-	}
+	ret = fwnet_broadcast_start(dev);
+	if (ret)
+		return ret;
+
 	netif_start_queue(net);
 
 	spin_lock_irq(&dev->lock);
@@ -1257,9 +1221,10 @@ static int fwnet_open(struct net_device *net)
 /* ifdown */
 static int fwnet_stop(struct net_device *net)
 {
-	netif_stop_queue(net);
+	struct fwnet_device *dev = netdev_priv(net);
 
-	/* Deallocate iso context for use by other applications? */
+	netif_stop_queue(net);
+	fwnet_broadcast_stop(dev);
 
 	return 0;
 }
@@ -1299,19 +1264,27 @@ static netdev_tx_t fwnet_tx(struct sk_buff *skb, struct net_device *net)
 	 * We might need to rebuild the header on tx failure.
 	 */
 	memcpy(&hdr_buf, skb->data, sizeof(hdr_buf));
-	skb_pull(skb, sizeof(hdr_buf));
-
 	proto = hdr_buf.h_proto;
+
+	switch (proto) {
+	case htons(ETH_P_ARP):
+	case htons(ETH_P_IP):
+#if IS_ENABLED(CONFIG_IPV6)
+	case htons(ETH_P_IPV6):
+#endif
+		break;
+	default:
+		goto fail;
+	}
+
+	skb_pull(skb, sizeof(hdr_buf));
 	dg_size = skb->len;
 
 	/*
 	 * Set the transmission type for the packet.  ARP packets and IP
 	 * broadcast packets are sent via GASP.
 	 */
-	if (memcmp(hdr_buf.h_dest, net->broadcast, FWNET_ALEN) == 0
-	    || proto == htons(ETH_P_ARP)
-	    || (proto == htons(ETH_P_IP)
-		&& IN_MULTICAST(ntohl(ip_hdr(skb)->daddr)))) {
+	if (fwnet_hwaddr_is_multicast(hdr_buf.h_dest)) {
 		max_payload        = dev->broadcast_xmt_max_payload;
 		datagram_label_ptr = &dev->broadcast_xmt_datagramlabel;
 
@@ -1320,11 +1293,12 @@ static netdev_tx_t fwnet_tx(struct sk_buff *skb, struct net_device *net)
 		ptask->dest_node   = IEEE1394_ALL_NODES;
 		ptask->speed       = SCODE_100;
 	} else {
-		__be64 guid = get_unaligned((__be64 *)hdr_buf.h_dest);
+		union fwnet_hwaddr *ha = (union fwnet_hwaddr *)hdr_buf.h_dest;
+		__be64 guid = get_unaligned(&ha->uc.uniq_id);
 		u8 generation;
 
 		peer = fwnet_peer_find_by_guid(dev, be64_to_cpu(guid));
-		if (!peer || peer->fifo == FWNET_NO_FIFO_ADDR)
+		if (!peer)
 			goto fail;
 
 		generation         = peer->generation;
@@ -1332,32 +1306,12 @@ static netdev_tx_t fwnet_tx(struct sk_buff *skb, struct net_device *net)
 		max_payload        = peer->max_payload;
 		datagram_label_ptr = &peer->datagram_label;
 
-		ptask->fifo_addr   = peer->fifo;
+		ptask->fifo_addr   = fwnet_hwaddr_fifo(ha);
 		ptask->generation  = generation;
 		ptask->dest_node   = dest_node;
 		ptask->speed       = peer->speed;
 	}
 
-	/* If this is an ARP packet, convert it */
-	if (proto == htons(ETH_P_ARP)) {
-		struct arphdr *arp = (struct arphdr *)skb->data;
-		unsigned char *arp_ptr = (unsigned char *)(arp + 1);
-		struct rfc2734_arp *arp1394 = (struct rfc2734_arp *)skb->data;
-		__be32 ipaddr;
-
-		ipaddr = get_unaligned((__be32 *)(arp_ptr + FWNET_ALEN));
-
-		arp1394->hw_addr_len    = RFC2734_HW_ADDR_LEN;
-		arp1394->max_rec        = dev->card->max_receive;
-		arp1394->sspd		= dev->card->link_speed;
-
-		put_unaligned_be16(dev->local_fifo >> 32,
-				   &arp1394->fifo_hi);
-		put_unaligned_be32(dev->local_fifo & 0xffffffff,
-				   &arp1394->fifo_lo);
-		put_unaligned(ipaddr, &arp1394->sip);
-	}
-
 	ptask->hdr.w0 = 0;
 	ptask->hdr.w1 = 0;
 	ptask->skb = skb;
@@ -1472,8 +1426,6 @@ static int fwnet_add_peer(struct fwnet_device *dev,
 
 	peer->dev = dev;
 	peer->guid = (u64)device->config_rom[3] << 32 | device->config_rom[4];
-	peer->fifo = FWNET_NO_FIFO_ADDR;
-	peer->ip = 0;
 	INIT_LIST_HEAD(&peer->pd_list);
 	peer->pdg_size = 0;
 	peer->datagram_label = 0;
@@ -1503,6 +1455,7 @@ static int fwnet_probe(struct device *_dev)
 	struct fwnet_device *dev;
 	unsigned max_mtu;
 	int ret;
+	union fwnet_hwaddr *ha;
 
 	mutex_lock(&fwnet_device_mutex);
 
@@ -1533,6 +1486,11 @@ static int fwnet_probe(struct device *_dev)
 	dev->card = card;
 	dev->netdev = net;
 
+	ret = fwnet_fifo_start(dev);
+	if (ret < 0)
+		goto out;
+	dev->local_fifo = dev->handler.offset;
+
 	/*
 	 * Use the RFC 2734 default 1500 octets or the maximum payload
 	 * as initial MTU
@@ -1542,24 +1500,31 @@ static int fwnet_probe(struct device *_dev)
 	net->mtu = min(1500U, max_mtu);
 
 	/* Set our hardware address while we're at it */
-	put_unaligned_be64(card->guid, net->dev_addr);
-	put_unaligned_be64(~0ULL, net->broadcast);
+	ha = (union fwnet_hwaddr *)net->dev_addr;
+	put_unaligned_be64(card->guid, &ha->uc.uniq_id);
+	ha->uc.max_rec = dev->card->max_receive;
+	ha->uc.sspd = dev->card->link_speed;
+	put_unaligned_be16(dev->local_fifo >> 32, &ha->uc.fifo_hi);
+	put_unaligned_be32(dev->local_fifo & 0xffffffff, &ha->uc.fifo_lo);
+
+	memset(net->broadcast, -1, net->addr_len);
+
 	ret = register_netdev(net);
 	if (ret)
 		goto out;
 
 	list_add_tail(&dev->dev_link, &fwnet_device_list);
-	dev_notice(&net->dev, "IPv4 over IEEE 1394 on card %s\n",
+	dev_notice(&net->dev, "IP over IEEE 1394 on card %s\n",
 		   dev_name(card->device));
  have_dev:
 	ret = fwnet_add_peer(dev, unit, device);
 	if (ret && allocated_netdev) {
 		unregister_netdev(net);
 		list_del(&dev->dev_link);
-	}
  out:
-	if (ret && allocated_netdev)
+		fwnet_fifo_stop(dev);
 		free_netdev(net);
+	}
 
 	mutex_unlock(&fwnet_device_mutex);
 
@@ -1592,22 +1557,14 @@ static int fwnet_remove(struct device *_dev)
 	mutex_lock(&fwnet_device_mutex);
 
 	net = dev->netdev;
-	if (net && peer->ip)
-		arp_invalidate(net, peer->ip);
 
 	fwnet_remove_peer(peer, dev);
 
 	if (list_empty(&dev->peer_list)) {
 		unregister_netdev(net);
 
-		if (dev->local_fifo != FWNET_NO_FIFO_ADDR)
-			fw_core_remove_address_handler(&dev->handler);
-		if (dev->broadcast_rcv_context) {
-			fw_iso_context_stop(dev->broadcast_rcv_context);
-			fw_iso_buffer_destroy(&dev->broadcast_rcv_buffer,
-					      dev->card);
-			fw_iso_context_destroy(dev->broadcast_rcv_context);
-		}
+		fwnet_fifo_stop(dev);
+
 		for (i = 0; dev->queued_datagrams && i < 5; i++)
 			ssleep(1);
 		WARN_ON(dev->queued_datagrams);
@@ -1646,6 +1603,14 @@ static const struct ieee1394_device_id fwnet_id_table[] = {
 		.specifier_id = IANA_SPECIFIER_ID,
 		.version      = RFC2734_SW_VERSION,
 	},
+#if IS_ENABLED(CONFIG_IPV6)
+	{
+		.match_flags  = IEEE1394_MATCH_SPECIFIER_ID |
+				IEEE1394_MATCH_VERSION,
+		.specifier_id = IANA_SPECIFIER_ID,
+		.version      = RFC3146_SW_VERSION,
+	},
+#endif
 	{ }
 };
 
@@ -1683,6 +1648,30 @@ static struct fw_descriptor rfc2374_unit_directory = {
 	.data   = rfc2374_unit_directory_data
 };
 
+#if IS_ENABLED(CONFIG_IPV6)
+static const u32 rfc3146_unit_directory_data[] = {
+	0x00040000,	/* directory_length		*/
+	0x1200005e,	/* unit_specifier_id: IANA	*/
+	0x81000003,	/* textual descriptor offset	*/
+	0x13000002,	/* unit_sw_version: RFC 3146	*/
+	0x81000005,	/* textual descriptor offset	*/
+	0x00030000,	/* descriptor_length		*/
+	0x00000000,	/* text				*/
+	0x00000000,	/* minimal ASCII, en		*/
+	0x49414e41,	/* I A N A			*/
+	0x00030000,	/* descriptor_length		*/
+	0x00000000,	/* text				*/
+	0x00000000,	/* minimal ASCII, en		*/
+	0x49507636,	/* I P v 6			*/
+};
+
+static struct fw_descriptor rfc3146_unit_directory = {
+	.length = ARRAY_SIZE(rfc3146_unit_directory_data),
+	.key    = (CSR_DIRECTORY | CSR_UNIT) << 24,
+	.data   = rfc3146_unit_directory_data
+};
+#endif
+
 static int __init fwnet_init(void)
 {
 	int err;
@@ -1691,11 +1680,17 @@ static int __init fwnet_init(void)
 	if (err)
 		return err;
 
+#if IS_ENABLED(CONFIG_IPV6)
+	err = fw_core_add_descriptor(&rfc3146_unit_directory);
+	if (err)
+		goto out;
+#endif
+
 	fwnet_packet_task_cache = kmem_cache_create("packet_task",
 			sizeof(struct fwnet_packet_task), 0, 0, NULL);
 	if (!fwnet_packet_task_cache) {
 		err = -ENOMEM;
-		goto out;
+		goto out2;
 	}
 
 	err = driver_register(&fwnet_driver.driver);
@@ -1703,7 +1698,11 @@ static int __init fwnet_init(void)
 		return 0;
 
 	kmem_cache_destroy(fwnet_packet_task_cache);
+out2:
+#if IS_ENABLED(CONFIG_IPV6)
+	fw_core_remove_descriptor(&rfc3146_unit_directory);
 out:
+#endif
 	fw_core_remove_descriptor(&rfc2374_unit_directory);
 
 	return err;
@@ -1714,11 +1713,14 @@ static void __exit fwnet_cleanup(void)
 {
 	driver_unregister(&fwnet_driver.driver);
 	kmem_cache_destroy(fwnet_packet_task_cache);
+#if IS_ENABLED(CONFIG_IPV6)
+	fw_core_remove_descriptor(&rfc3146_unit_directory);
+#endif
 	fw_core_remove_descriptor(&rfc2374_unit_directory);
 }
 module_exit(fwnet_cleanup);
 
 MODULE_AUTHOR("Jay Fenlason <fenlason@redhat.com>");
-MODULE_DESCRIPTION("IPv4 over IEEE1394 as per RFC 2734");
+MODULE_DESCRIPTION("IP over IEEE1394 as per RFC 2734/3146");
 MODULE_LICENSE("GPL");
 MODULE_DEVICE_TABLE(ieee1394, fwnet_id_table);
diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c
index 4cd392d..40e940d 100644
--- a/drivers/firmware/dmi_scan.c
+++ b/drivers/firmware/dmi_scan.c
@@ -410,22 +410,45 @@ static void __init dmi_dump_ids(void)
 	printk(KERN_CONT "\n");
 }
 
-static int __init dmi_present(const char __iomem *p)
+static int __init dmi_present(const u8 *buf)
 {
-	u8 buf[15];
+	int smbios_ver;
 
-	memcpy_fromio(buf, p, 15);
-	if (dmi_checksum(buf, 15)) {
+	if (memcmp(buf, "_SM_", 4) == 0 &&
+	    buf[5] < 32 && dmi_checksum(buf, buf[5])) {
+		smbios_ver = (buf[6] << 8) + buf[7];
+
+		/* Some BIOS report weird SMBIOS version, fix that up */
+		switch (smbios_ver) {
+		case 0x021F:
+		case 0x0221:
+			pr_debug("SMBIOS version fixup(2.%d->2.%d)\n",
+				 smbios_ver & 0xFF, 3);
+			smbios_ver = 0x0203;
+			break;
+		case 0x0233:
+			pr_debug("SMBIOS version fixup(2.%d->2.%d)\n", 51, 6);
+			smbios_ver = 0x0206;
+			break;
+		}
+	} else {
+		smbios_ver = 0;
+	}
+
+	buf += 16;
+
+	if (memcmp(buf, "_DMI_", 5) == 0 && dmi_checksum(buf, 15)) {
 		dmi_num = (buf[13] << 8) | buf[12];
 		dmi_len = (buf[7] << 8) | buf[6];
 		dmi_base = (buf[11] << 24) | (buf[10] << 16) |
 			(buf[9] << 8) | buf[8];
 
 		if (dmi_walk_early(dmi_decode) == 0) {
-			if (dmi_ver)
+			if (smbios_ver) {
+				dmi_ver = smbios_ver;
 				pr_info("SMBIOS %d.%d present.\n",
 				       dmi_ver >> 8, dmi_ver & 0xFF);
-			else {
+			} else {
 				dmi_ver = (buf[14] & 0xF0) << 4 |
 					   (buf[14] & 0x0F);
 				pr_info("Legacy DMI %d.%d present.\n",
@@ -435,40 +458,14 @@ static int __init dmi_present(const char __iomem *p)
 			return 0;
 		}
 	}
-	dmi_ver = 0;
-	return 1;
-}
 
-static int __init smbios_present(const char __iomem *p)
-{
-	u8 buf[32];
-
-	memcpy_fromio(buf, p, 32);
-	if ((buf[5] < 32) && dmi_checksum(buf, buf[5])) {
-		dmi_ver = (buf[6] << 8) + buf[7];
-
-		/* Some BIOS report weird SMBIOS version, fix that up */
-		switch (dmi_ver) {
-		case 0x021F:
-		case 0x0221:
-			pr_debug("SMBIOS version fixup(2.%d->2.%d)\n",
-			       dmi_ver & 0xFF, 3);
-			dmi_ver = 0x0203;
-			break;
-		case 0x0233:
-			pr_debug("SMBIOS version fixup(2.%d->2.%d)\n", 51, 6);
-			dmi_ver = 0x0206;
-			break;
-		}
-		return memcmp(p + 16, "_DMI_", 5) || dmi_present(p + 16);
-	}
 	return 1;
 }
 
 void __init dmi_scan_machine(void)
 {
 	char __iomem *p, *q;
-	int rc;
+	char buf[32];
 
 	if (efi_enabled(EFI_CONFIG_TABLES)) {
 		if (efi.smbios == EFI_INVALID_TABLE_ADDR)
@@ -481,10 +478,10 @@ void __init dmi_scan_machine(void)
 		p = dmi_ioremap(efi.smbios, 32);
 		if (p == NULL)
 			goto error;
-
-		rc = smbios_present(p);
+		memcpy_fromio(buf, p, 32);
 		dmi_iounmap(p, 32);
-		if (!rc) {
+
+		if (!dmi_present(buf)) {
 			dmi_available = 1;
 			goto out;
 		}
@@ -499,18 +496,15 @@ void __init dmi_scan_machine(void)
 		if (p == NULL)
 			goto error;
 
+		memset(buf, 0, 16);
 		for (q = p; q < p + 0x10000; q += 16) {
-			if (memcmp(q, "_SM_", 4) == 0 && q - p <= 0xFFE0)
-				rc = smbios_present(q);
-			else if (memcmp(q, "_DMI_", 5) == 0)
-				rc = dmi_present(q);
-			else
-				continue;
-			if (!rc) {
+			memcpy_fromio(buf + 16, q, 16);
+			if (!dmi_present(buf)) {
 				dmi_available = 1;
 				dmi_iounmap(p, 0x10000);
 				goto out;
 			}
+			memcpy(buf, buf + 16, 16);
 		}
 		dmi_iounmap(p, 0x10000);
 	}
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 93aaadf..afbe0d1 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -204,6 +204,12 @@ config GPIO_PXA
 	help
 	  Say yes here to support the PXA GPIO device
 
+config GPIO_RCAR
+	tristate "Renesas R-Car GPIO"
+	depends on ARM
+	help
+	  Say yes here to support GPIO on Renesas R-Car SoCs.
+
 config GPIO_SPEAR_SPICS
 	bool "ST SPEAr13xx SPI Chip Select as GPIO support"
 	depends on PLAT_SPEAR
@@ -303,7 +309,7 @@ config GPIO_GE_FPGA
 
 config GPIO_LYNXPOINT
 	bool "Intel Lynxpoint GPIO support"
-	depends on ACPI
+	depends on ACPI && X86
 	select IRQ_DOMAIN
 	help
 	  driver for GPIO functionality on Intel Lynxpoint PCH chipset
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 22e07bc..b41c74d 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -57,6 +57,7 @@ obj-$(CONFIG_GPIO_PL061)	+= gpio-pl061.o
 obj-$(CONFIG_GPIO_PXA)		+= gpio-pxa.o
 obj-$(CONFIG_GPIO_RC5T583)	+= gpio-rc5t583.o
 obj-$(CONFIG_GPIO_RDC321X)	+= gpio-rdc321x.o
+obj-$(CONFIG_GPIO_RCAR)		+= gpio-rcar.o
 obj-$(CONFIG_PLAT_SAMSUNG)	+= gpio-samsung.o
 obj-$(CONFIG_ARCH_SA1100)	+= gpio-sa1100.o
 obj-$(CONFIG_GPIO_SCH)		+= gpio-sch.o
diff --git a/drivers/gpio/gpio-74x164.c b/drivers/gpio/gpio-74x164.c
index 464be96..7216079 100644
--- a/drivers/gpio/gpio-74x164.c
+++ b/drivers/gpio/gpio-74x164.c
@@ -137,7 +137,7 @@ static int gen_74x164_probe(struct spi_device *spi)
 
 	mutex_init(&chip->lock);
 
-	dev_set_drvdata(&spi->dev, chip);
+	spi_set_drvdata(spi, chip);
 
 	chip->spi = spi;
 
@@ -176,7 +176,7 @@ static int gen_74x164_probe(struct spi_device *spi)
 	return ret;
 
 exit_destroy:
-	dev_set_drvdata(&spi->dev, NULL);
+	spi_set_drvdata(spi, NULL);
 	mutex_destroy(&chip->lock);
 	return ret;
 }
@@ -186,11 +186,11 @@ static int gen_74x164_remove(struct spi_device *spi)
 	struct gen_74x164_chip *chip;
 	int ret;
 
-	chip = dev_get_drvdata(&spi->dev);
+	chip = spi_get_drvdata(spi);
 	if (chip == NULL)
 		return -ENODEV;
 
-	dev_set_drvdata(&spi->dev, NULL);
+	spi_set_drvdata(spi, NULL);
 
 	ret = gpiochip_remove(&chip->gpio_chip);
 	if (!ret)
diff --git a/drivers/gpio/gpio-adp5520.c b/drivers/gpio/gpio-adp5520.c
index 8afa95f..f33f78d 100644
--- a/drivers/gpio/gpio-adp5520.c
+++ b/drivers/gpio/gpio-adp5520.c
@@ -105,7 +105,7 @@ static int adp5520_gpio_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
-	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
 	if (dev == NULL) {
 		dev_err(&pdev->dev, "failed to alloc memory\n");
 		return -ENOMEM;
@@ -163,7 +163,6 @@ static int adp5520_gpio_probe(struct platform_device *pdev)
 	return 0;
 
 err:
-	kfree(dev);
 	return ret;
 }
 
@@ -180,7 +179,6 @@ static int adp5520_gpio_remove(struct platform_device *pdev)
 		return ret;
 	}
 
-	kfree(dev);
 	return 0;
 }
 
diff --git a/drivers/gpio/gpio-em.c b/drivers/gpio/gpio-em.c
index deca78f..5cba855 100644
--- a/drivers/gpio/gpio-em.c
+++ b/drivers/gpio/gpio-em.c
@@ -231,10 +231,12 @@ static int em_gio_irq_domain_map(struct irq_domain *h, unsigned int virq,
 
 static struct irq_domain_ops em_gio_irq_domain_ops = {
 	.map	= em_gio_irq_domain_map,
+	.xlate	= irq_domain_xlate_twocell,
 };
 
 static int em_gio_probe(struct platform_device *pdev)
 {
+	struct gpio_em_config pdata_dt;
 	struct gpio_em_config *pdata = pdev->dev.platform_data;
 	struct em_gio_priv *p;
 	struct resource *io[2], *irq[2];
@@ -243,7 +245,7 @@ static int em_gio_probe(struct platform_device *pdev)
 	const char *name = dev_name(&pdev->dev);
 	int ret;
 
-	p = kzalloc(sizeof(*p), GFP_KERNEL);
+	p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL);
 	if (!p) {
 		dev_err(&pdev->dev, "failed to allocate driver data\n");
 		ret = -ENOMEM;
@@ -259,24 +261,45 @@ static int em_gio_probe(struct platform_device *pdev)
 	irq[0] = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 	irq[1] = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
 
-	if (!io[0] || !io[1] || !irq[0] || !irq[1] || !pdata) {
-		dev_err(&pdev->dev, "missing IRQ, IOMEM or configuration\n");
+	if (!io[0] || !io[1] || !irq[0] || !irq[1]) {
+		dev_err(&pdev->dev, "missing IRQ or IOMEM\n");
 		ret = -EINVAL;
-		goto err1;
+		goto err0;
 	}
 
-	p->base0 = ioremap_nocache(io[0]->start, resource_size(io[0]));
+	p->base0 = devm_ioremap_nocache(&pdev->dev, io[0]->start,
+					resource_size(io[0]));
 	if (!p->base0) {
 		dev_err(&pdev->dev, "failed to remap low I/O memory\n");
 		ret = -ENXIO;
-		goto err1;
+		goto err0;
 	}
 
-	p->base1 = ioremap_nocache(io[1]->start, resource_size(io[1]));
+	p->base1 = devm_ioremap_nocache(&pdev->dev, io[1]->start,
+				   resource_size(io[1]));
 	if (!p->base1) {
 		dev_err(&pdev->dev, "failed to remap high I/O memory\n");
 		ret = -ENXIO;
-		goto err2;
+		goto err0;
+	}
+
+	if (!pdata) {
+		memset(&pdata_dt, 0, sizeof(pdata_dt));
+		pdata = &pdata_dt;
+
+		if (of_property_read_u32(pdev->dev.of_node, "ngpios",
+					 &pdata->number_of_pins)) {
+			dev_err(&pdev->dev, "Missing ngpios OF property\n");
+			ret = -EINVAL;
+			goto err0;
+		}
+
+		ret = of_alias_get_id(pdev->dev.of_node, "gpio");
+		if (ret < 0) {
+			dev_err(&pdev->dev, "Couldn't get OF id\n");
+			goto err0;
+		}
+		pdata->gpio_base = ret * 32; /* 32 GPIOs per instance */
 	}
 
 	gpio_chip = &p->gpio_chip;
@@ -306,40 +329,32 @@ static int em_gio_probe(struct platform_device *pdev)
 	if (!p->irq_domain) {
 		ret = -ENXIO;
 		dev_err(&pdev->dev, "cannot initialize irq domain\n");
-		goto err3;
+		goto err0;
 	}
 
-	if (request_irq(irq[0]->start, em_gio_irq_handler, 0, name, p)) {
+	if (devm_request_irq(&pdev->dev, irq[0]->start,
+			     em_gio_irq_handler, 0, name, p)) {
 		dev_err(&pdev->dev, "failed to request low IRQ\n");
 		ret = -ENOENT;
-		goto err4;
+		goto err1;
 	}
 
-	if (request_irq(irq[1]->start, em_gio_irq_handler, 0, name, p)) {
+	if (devm_request_irq(&pdev->dev, irq[1]->start,
+			     em_gio_irq_handler, 0, name, p)) {
 		dev_err(&pdev->dev, "failed to request high IRQ\n");
 		ret = -ENOENT;
-		goto err5;
+		goto err1;
 	}
 
 	ret = gpiochip_add(gpio_chip);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to add GPIO controller\n");
-		goto err6;
+		goto err1;
 	}
 	return 0;
 
-err6:
-	free_irq(irq[1]->start, pdev);
-err5:
-	free_irq(irq[0]->start, pdev);
-err4:
-	irq_domain_remove(p->irq_domain);
-err3:
-	iounmap(p->base1);
-err2:
-	iounmap(p->base0);
 err1:
-	kfree(p);
+	irq_domain_remove(p->irq_domain);
 err0:
 	return ret;
 }
@@ -347,34 +362,43 @@ err0:
 static int em_gio_remove(struct platform_device *pdev)
 {
 	struct em_gio_priv *p = platform_get_drvdata(pdev);
-	struct resource *irq[2];
 	int ret;
 
 	ret = gpiochip_remove(&p->gpio_chip);
 	if (ret)
 		return ret;
 
-	irq[0] = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	irq[1] = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
-
-	free_irq(irq[1]->start, pdev);
-	free_irq(irq[0]->start, pdev);
 	irq_domain_remove(p->irq_domain);
-	iounmap(p->base1);
-	iounmap(p->base0);
-	kfree(p);
 	return 0;
 }
 
+static const struct of_device_id em_gio_dt_ids[] = {
+	{ .compatible = "renesas,em-gio", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, em_gio_dt_ids);
+
 static struct platform_driver em_gio_device_driver = {
 	.probe		= em_gio_probe,
 	.remove		= em_gio_remove,
 	.driver		= {
 		.name	= "em_gio",
+		.of_match_table = em_gio_dt_ids,
+		.owner		= THIS_MODULE,
 	}
 };
 
-module_platform_driver(em_gio_device_driver);
+static int __init em_gio_init(void)
+{
+	return platform_driver_register(&em_gio_device_driver);
+}
+postcore_initcall(em_gio_init);
+
+static void __exit em_gio_exit(void)
+{
+	platform_driver_unregister(&em_gio_device_driver);
+}
+module_exit(em_gio_exit);
 
 MODULE_AUTHOR("Magnus Damm");
 MODULE_DESCRIPTION("Renesas Emma Mobile GIO Driver");
diff --git a/drivers/gpio/gpio-ich.c b/drivers/gpio/gpio-ich.c
index f9dbd50..e16d932 100644
--- a/drivers/gpio/gpio-ich.c
+++ b/drivers/gpio/gpio-ich.c
@@ -130,14 +130,11 @@ static int ichx_read_bit(int reg, unsigned nr)
 
 static bool ichx_gpio_check_available(struct gpio_chip *gpio, unsigned nr)
 {
-	return ichx_priv.use_gpio & (1 << (nr / 32));
+	return !!(ichx_priv.use_gpio & (1 << (nr / 32)));
 }
 
 static int ichx_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
 {
-	if (!ichx_gpio_check_available(gpio, nr))
-		return -ENXIO;
-
 	/*
 	 * Try setting pin as an input and verify it worked since many pins
 	 * are output-only.
@@ -151,9 +148,6 @@ static int ichx_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
 static int ichx_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,
 					int val)
 {
-	if (!ichx_gpio_check_available(gpio, nr))
-		return -ENXIO;
-
 	/* Set GPIO output value. */
 	ichx_write_bit(GPIO_LVL, nr, val, 0);
 
@@ -169,9 +163,6 @@ static int ichx_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,
 
 static int ichx_gpio_get(struct gpio_chip *chip, unsigned nr)
 {
-	if (!ichx_gpio_check_available(chip, nr))
-		return -ENXIO;
-
 	return ichx_read_bit(GPIO_LVL, nr);
 }
 
@@ -180,9 +171,6 @@ static int ich6_gpio_get(struct gpio_chip *chip, unsigned nr)
 	unsigned long flags;
 	u32 data;
 
-	if (!ichx_gpio_check_available(chip, nr))
-		return -ENXIO;
-
 	/*
 	 * GPI 0 - 15 need to be read from the power management registers on
 	 * a ICH6/3100 bridge.
@@ -207,6 +195,9 @@ static int ich6_gpio_get(struct gpio_chip *chip, unsigned nr)
 
 static int ichx_gpio_request(struct gpio_chip *chip, unsigned nr)
 {
+	if (!ichx_gpio_check_available(chip, nr))
+		return -ENXIO;
+
 	/*
 	 * Note we assume the BIOS properly set a bridge's USE value.  Some
 	 * chips (eg Intel 3100) have bogus USE values though, so first see if
@@ -214,7 +205,7 @@ static int ichx_gpio_request(struct gpio_chip *chip, unsigned nr)
 	 * If it can't be trusted, assume that the pin can be used as a GPIO.
 	 */
 	if (ichx_priv.desc->use_sel_ignore[nr / 32] & (1 << (nr & 0x1f)))
-		return 1;
+		return 0;
 
 	return ichx_read_bit(GPIO_USE_SEL, nr) ? 0 : -ENODEV;
 }
diff --git a/drivers/gpio/gpio-lynxpoint.c b/drivers/gpio/gpio-lynxpoint.c
index 3472b05..86c17de 100644
--- a/drivers/gpio/gpio-lynxpoint.c
+++ b/drivers/gpio/gpio-lynxpoint.c
@@ -32,6 +32,7 @@
 #include <linux/acpi.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
+#include <linux/io.h>
 
 /* LynxPoint chipset has support for 94 gpio pins */
 
diff --git a/drivers/gpio/gpio-max7300.c b/drivers/gpio/gpio-max7300.c
index 4b6b9a0..40ab6df 100644
--- a/drivers/gpio/gpio-max7300.c
+++ b/drivers/gpio/gpio-max7300.c
@@ -41,7 +41,7 @@ static int max7300_probe(struct i2c_client *client,
 			I2C_FUNC_SMBUS_BYTE_DATA))
 		return -EIO;
 
-	ts = kzalloc(sizeof(struct max7301), GFP_KERNEL);
+	ts = devm_kzalloc(&client->dev, sizeof(struct max7301), GFP_KERNEL);
 	if (!ts)
 		return -ENOMEM;
 
@@ -50,8 +50,6 @@ static int max7300_probe(struct i2c_client *client,
 	ts->dev = &client->dev;
 
 	ret = __max730x_probe(ts);
-	if (ret)
-		kfree(ts);
 	return ret;
 }
 
diff --git a/drivers/gpio/gpio-max7301.c b/drivers/gpio/gpio-max7301.c
index c6c535c..3b16ab7 100644
--- a/drivers/gpio/gpio-max7301.c
+++ b/drivers/gpio/gpio-max7301.c
@@ -56,12 +56,13 @@ static int max7301_probe(struct spi_device *spi)
 	int ret;
 
 	/* bits_per_word cannot be configured in platform data */
-	spi->bits_per_word = 16;
+	if (spi->dev.platform_data)
+		spi->bits_per_word = 16;
 	ret = spi_setup(spi);
 	if (ret < 0)
 		return ret;
 
-	ts = kzalloc(sizeof(struct max7301), GFP_KERNEL);
+	ts = devm_kzalloc(&spi->dev, sizeof(struct max7301), GFP_KERNEL);
 	if (!ts)
 		return -ENOMEM;
 
@@ -70,8 +71,6 @@ static int max7301_probe(struct spi_device *spi)
 	ts->dev = &spi->dev;
 
 	ret = __max730x_probe(ts);
-	if (ret)
-		kfree(ts);
 	return ret;
 }
 
diff --git a/drivers/gpio/gpio-max732x.c b/drivers/gpio/gpio-max732x.c
index 1e0467c..d4b51b1 100644
--- a/drivers/gpio/gpio-max732x.c
+++ b/drivers/gpio/gpio-max732x.c
@@ -589,7 +589,8 @@ static int max732x_probe(struct i2c_client *client,
 		return -EINVAL;
 	}
 
-	chip = kzalloc(sizeof(struct max732x_chip), GFP_KERNEL);
+	chip = devm_kzalloc(&client->dev, sizeof(struct max732x_chip),
+			GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 	chip->client = client;
@@ -647,7 +648,6 @@ static int max732x_probe(struct i2c_client *client,
 
 out_failed:
 	max732x_irq_teardown(chip);
-	kfree(chip);
 	return ret;
 }
 
@@ -680,7 +680,6 @@ static int max732x_remove(struct i2c_client *client)
 	if (chip->client_dummy)
 		i2c_unregister_device(chip->client_dummy);
 
-	kfree(chip);
 	return 0;
 }
 
diff --git a/drivers/gpio/gpio-mc33880.c b/drivers/gpio/gpio-mc33880.c
index 6a8fdc2..63a7a1b 100644
--- a/drivers/gpio/gpio-mc33880.c
+++ b/drivers/gpio/gpio-mc33880.c
@@ -101,13 +101,13 @@ static int mc33880_probe(struct spi_device *spi)
 	if (ret < 0)
 		return ret;
 
-	mc = kzalloc(sizeof(struct mc33880), GFP_KERNEL);
+	mc = devm_kzalloc(&spi->dev, sizeof(struct mc33880), GFP_KERNEL);
 	if (!mc)
 		return -ENOMEM;
 
 	mutex_init(&mc->lock);
 
-	dev_set_drvdata(&spi->dev, mc);
+	spi_set_drvdata(spi, mc);
 
 	mc->spi = spi;
 
@@ -130,7 +130,8 @@ static int mc33880_probe(struct spi_device *spi)
 		ret = mc33880_write_config(mc);
 
 	if (ret) {
-		printk(KERN_ERR "Failed writing to " DRIVER_NAME ": %d\n", ret);
+		dev_err(&spi->dev, "Failed writing to " DRIVER_NAME ": %d\n",
+			ret);
 		goto exit_destroy;
 	}
 
@@ -141,9 +142,8 @@ static int mc33880_probe(struct spi_device *spi)
 	return ret;
 
 exit_destroy:
-	dev_set_drvdata(&spi->dev, NULL);
+	spi_set_drvdata(spi, NULL);
 	mutex_destroy(&mc->lock);
-	kfree(mc);
 	return ret;
 }
 
@@ -152,17 +152,16 @@ static int mc33880_remove(struct spi_device *spi)
 	struct mc33880 *mc;
 	int ret;
 
-	mc = dev_get_drvdata(&spi->dev);
+	mc = spi_get_drvdata(spi);
 	if (mc == NULL)
 		return -ENODEV;
 
-	dev_set_drvdata(&spi->dev, NULL);
+	spi_set_drvdata(spi, NULL);
 
 	ret = gpiochip_remove(&mc->chip);
-	if (!ret) {
+	if (!ret)
 		mutex_destroy(&mc->lock);
-		kfree(mc);
-	} else
+	else
 		dev_err(&spi->dev, "Failed to remove the GPIO controller: %d\n",
 			ret);
 
diff --git a/drivers/gpio/gpio-msm-v1.c b/drivers/gpio/gpio-msm-v1.c
index 52a4d42..c798585 100644
--- a/drivers/gpio/gpio-msm-v1.c
+++ b/drivers/gpio/gpio-msm-v1.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2012, The Linux Foundation. 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
@@ -19,9 +19,10 @@
 #include <linux/io.h>
 #include <linux/irq.h>
 #include <linux/module.h>
-#include <mach/cpu.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+
 #include <mach/msm_gpiomux.h>
-#include <mach/msm_iomap.h>
 
 /* see 80-VA736-2 Rev C pp 695-751
 **
@@ -34,10 +35,10 @@
 ** macros.
 */
 
-#define MSM_GPIO1_REG(off) (MSM_GPIO1_BASE + (off))
-#define MSM_GPIO2_REG(off) (MSM_GPIO2_BASE + 0x400 + (off))
-#define MSM_GPIO1_SHADOW_REG(off) (MSM_GPIO1_BASE + 0x800 + (off))
-#define MSM_GPIO2_SHADOW_REG(off) (MSM_GPIO2_BASE + 0xC00 + (off))
+#define MSM_GPIO1_REG(off) (off)
+#define MSM_GPIO2_REG(off) (off)
+#define MSM_GPIO1_SHADOW_REG(off) (off)
+#define MSM_GPIO2_SHADOW_REG(off) (off)
 
 /*
  * MSM7X00 registers
@@ -276,16 +277,14 @@
 
 #define MSM_GPIO_BANK(soc, bank, first, last)				\
 	{								\
-		.regs = {						\
-			.out =         soc##_GPIO_OUT_##bank,		\
-			.in =          soc##_GPIO_IN_##bank,		\
-			.int_status =  soc##_GPIO_INT_STATUS_##bank,	\
-			.int_clear =   soc##_GPIO_INT_CLEAR_##bank,	\
-			.int_en =      soc##_GPIO_INT_EN_##bank,	\
-			.int_edge =    soc##_GPIO_INT_EDGE_##bank,	\
-			.int_pos =     soc##_GPIO_INT_POS_##bank,	\
-			.oe =          soc##_GPIO_OE_##bank,		\
-		},							\
+		.regs[MSM_GPIO_OUT] =         soc##_GPIO_OUT_##bank,	\
+		.regs[MSM_GPIO_IN] =          soc##_GPIO_IN_##bank,	\
+		.regs[MSM_GPIO_INT_STATUS] =  soc##_GPIO_INT_STATUS_##bank, \
+		.regs[MSM_GPIO_INT_CLEAR] =   soc##_GPIO_INT_CLEAR_##bank, \
+		.regs[MSM_GPIO_INT_EN] =      soc##_GPIO_INT_EN_##bank,	\
+		.regs[MSM_GPIO_INT_EDGE] =    soc##_GPIO_INT_EDGE_##bank, \
+		.regs[MSM_GPIO_INT_POS] =     soc##_GPIO_INT_POS_##bank, \
+		.regs[MSM_GPIO_OE] =          soc##_GPIO_OE_##bank,	\
 		.chip = {						\
 			.base = (first),				\
 			.ngpio = (last) - (first) + 1,			\
@@ -301,39 +300,57 @@
 
 #define MSM_GPIO_BROKEN_INT_CLEAR 1
 
-struct msm_gpio_regs {
-	void __iomem *out;
-	void __iomem *in;
-	void __iomem *int_status;
-	void __iomem *int_clear;
-	void __iomem *int_en;
-	void __iomem *int_edge;
-	void __iomem *int_pos;
-	void __iomem *oe;
+enum msm_gpio_reg {
+	MSM_GPIO_IN,
+	MSM_GPIO_OUT,
+	MSM_GPIO_INT_STATUS,
+	MSM_GPIO_INT_CLEAR,
+	MSM_GPIO_INT_EN,
+	MSM_GPIO_INT_EDGE,
+	MSM_GPIO_INT_POS,
+	MSM_GPIO_OE,
+	MSM_GPIO_REG_NR
 };
 
 struct msm_gpio_chip {
 	spinlock_t		lock;
 	struct gpio_chip	chip;
-	struct msm_gpio_regs	regs;
+	unsigned long		regs[MSM_GPIO_REG_NR];
 #if MSM_GPIO_BROKEN_INT_CLEAR
 	unsigned                int_status_copy;
 #endif
 	unsigned int            both_edge_detect;
 	unsigned int            int_enable[2]; /* 0: awake, 1: sleep */
+	void __iomem		*base;
+};
+
+struct msm_gpio_initdata {
+	struct msm_gpio_chip *chips;
+	int count;
 };
 
+static void msm_gpio_writel(struct msm_gpio_chip *chip, u32 val,
+			    enum msm_gpio_reg reg)
+{
+	writel(val, chip->base + chip->regs[reg]);
+}
+
+static u32 msm_gpio_readl(struct msm_gpio_chip *chip, enum msm_gpio_reg reg)
+{
+	return readl(chip->base + chip->regs[reg]);
+}
+
 static int msm_gpio_write(struct msm_gpio_chip *msm_chip,
 			  unsigned offset, unsigned on)
 {
 	unsigned mask = BIT(offset);
 	unsigned val;
 
-	val = readl(msm_chip->regs.out);
+	val = msm_gpio_readl(msm_chip, MSM_GPIO_OUT);
 	if (on)
-		writel(val | mask, msm_chip->regs.out);
+		msm_gpio_writel(msm_chip, val | mask, MSM_GPIO_OUT);
 	else
-		writel(val & ~mask, msm_chip->regs.out);
+		msm_gpio_writel(msm_chip, val & ~mask, MSM_GPIO_OUT);
 	return 0;
 }
 
@@ -342,13 +359,13 @@ static void msm_gpio_update_both_edge_detect(struct msm_gpio_chip *msm_chip)
 	int loop_limit = 100;
 	unsigned pol, val, val2, intstat;
 	do {
-		val = readl(msm_chip->regs.in);
-		pol = readl(msm_chip->regs.int_pos);
+		val = msm_gpio_readl(msm_chip, MSM_GPIO_IN);
+		pol = msm_gpio_readl(msm_chip, MSM_GPIO_INT_POS);
 		pol = (pol & ~msm_chip->both_edge_detect) |
 		      (~val & msm_chip->both_edge_detect);
-		writel(pol, msm_chip->regs.int_pos);
-		intstat = readl(msm_chip->regs.int_status);
-		val2 = readl(msm_chip->regs.in);
+		msm_gpio_writel(msm_chip, pol, MSM_GPIO_INT_POS);
+		intstat = msm_gpio_readl(msm_chip, MSM_GPIO_INT_STATUS);
+		val2 = msm_gpio_readl(msm_chip, MSM_GPIO_IN);
 		if (((val ^ val2) & msm_chip->both_edge_detect & ~intstat) == 0)
 			return;
 	} while (loop_limit-- > 0);
@@ -365,10 +382,11 @@ static int msm_gpio_clear_detect_status(struct msm_gpio_chip *msm_chip,
 	/* Save interrupts that already triggered before we loose them. */
 	/* Any interrupt that triggers between the read of int_status */
 	/* and the write to int_clear will still be lost though. */
-	msm_chip->int_status_copy |= readl(msm_chip->regs.int_status);
+	msm_chip->int_status_copy |=
+		msm_gpio_readl(msm_chip, MSM_GPIO_INT_STATUS);
 	msm_chip->int_status_copy &= ~bit;
 #endif
-	writel(bit, msm_chip->regs.int_clear);
+	msm_gpio_writel(msm_chip, bit, MSM_GPIO_INT_CLEAR);
 	msm_gpio_update_both_edge_detect(msm_chip);
 	return 0;
 }
@@ -377,10 +395,12 @@ static int msm_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
 {
 	struct msm_gpio_chip *msm_chip;
 	unsigned long irq_flags;
+	u32 val;
 
 	msm_chip = container_of(chip, struct msm_gpio_chip, chip);
 	spin_lock_irqsave(&msm_chip->lock, irq_flags);
-	writel(readl(msm_chip->regs.oe) & ~BIT(offset), msm_chip->regs.oe);
+	val = msm_gpio_readl(msm_chip, MSM_GPIO_OE) & ~BIT(offset);
+	msm_gpio_writel(msm_chip, val, MSM_GPIO_OE);
 	spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
 	return 0;
 }
@@ -390,11 +410,13 @@ msm_gpio_direction_output(struct gpio_chip *chip, unsigned offset, int value)
 {
 	struct msm_gpio_chip *msm_chip;
 	unsigned long irq_flags;
+	u32 val;
 
 	msm_chip = container_of(chip, struct msm_gpio_chip, chip);
 	spin_lock_irqsave(&msm_chip->lock, irq_flags);
 	msm_gpio_write(msm_chip, offset, value);
-	writel(readl(msm_chip->regs.oe) | BIT(offset), msm_chip->regs.oe);
+	val = msm_gpio_readl(msm_chip, MSM_GPIO_OE) | BIT(offset);
+	msm_gpio_writel(msm_chip, val, MSM_GPIO_OE);
 	spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
 	return 0;
 }
@@ -404,7 +426,7 @@ static int msm_gpio_get(struct gpio_chip *chip, unsigned offset)
 	struct msm_gpio_chip *msm_chip;
 
 	msm_chip = container_of(chip, struct msm_gpio_chip, chip);
-	return (readl(msm_chip->regs.in) & (1U << offset)) ? 1 : 0;
+	return (msm_gpio_readl(msm_chip, MSM_GPIO_IN) & (1U << offset)) ? 1 : 0;
 }
 
 static void msm_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
@@ -450,6 +472,11 @@ static struct msm_gpio_chip msm_gpio_chips_msm7x01[] = {
 	MSM_GPIO_BANK(MSM7X00, 5, 107, 121),
 };
 
+static struct msm_gpio_initdata msm_gpio_7x01_init = {
+	.chips = msm_gpio_chips_msm7x01,
+	.count = ARRAY_SIZE(msm_gpio_chips_msm7x01),
+};
+
 static struct msm_gpio_chip msm_gpio_chips_msm7x30[] = {
 	MSM_GPIO_BANK(MSM7X30, 0,   0,  15),
 	MSM_GPIO_BANK(MSM7X30, 1,  16,  43),
@@ -461,6 +488,11 @@ static struct msm_gpio_chip msm_gpio_chips_msm7x30[] = {
 	MSM_GPIO_BANK(MSM7X30, 7, 151, 181),
 };
 
+static struct msm_gpio_initdata msm_gpio_7x30_init = {
+	.chips = msm_gpio_chips_msm7x30,
+	.count = ARRAY_SIZE(msm_gpio_chips_msm7x30),
+};
+
 static struct msm_gpio_chip msm_gpio_chips_qsd8x50[] = {
 	MSM_GPIO_BANK(QSD8X50, 0,   0,  15),
 	MSM_GPIO_BANK(QSD8X50, 1,  16,  42),
@@ -472,6 +504,11 @@ static struct msm_gpio_chip msm_gpio_chips_qsd8x50[] = {
 	MSM_GPIO_BANK(QSD8X50, 7, 153, 164),
 };
 
+static struct msm_gpio_initdata msm_gpio_8x50_init = {
+	.chips = msm_gpio_chips_qsd8x50,
+	.count = ARRAY_SIZE(msm_gpio_chips_qsd8x50),
+};
+
 static void msm_gpio_irq_ack(struct irq_data *d)
 {
 	unsigned long irq_flags;
@@ -490,10 +527,10 @@ static void msm_gpio_irq_mask(struct irq_data *d)
 
 	spin_lock_irqsave(&msm_chip->lock, irq_flags);
 	/* level triggered interrupts are also latched */
-	if (!(readl(msm_chip->regs.int_edge) & BIT(offset)))
+	if (!(msm_gpio_readl(msm_chip, MSM_GPIO_INT_EDGE) & BIT(offset)))
 		msm_gpio_clear_detect_status(msm_chip, offset);
 	msm_chip->int_enable[0] &= ~BIT(offset);
-	writel(msm_chip->int_enable[0], msm_chip->regs.int_en);
+	msm_gpio_writel(msm_chip, msm_chip->int_enable[0], MSM_GPIO_INT_EN);
 	spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
 }
 
@@ -505,10 +542,10 @@ static void msm_gpio_irq_unmask(struct irq_data *d)
 
 	spin_lock_irqsave(&msm_chip->lock, irq_flags);
 	/* level triggered interrupts are also latched */
-	if (!(readl(msm_chip->regs.int_edge) & BIT(offset)))
+	if (!(msm_gpio_readl(msm_chip, MSM_GPIO_INT_EDGE) & BIT(offset)))
 		msm_gpio_clear_detect_status(msm_chip, offset);
 	msm_chip->int_enable[0] |= BIT(offset);
-	writel(msm_chip->int_enable[0], msm_chip->regs.int_en);
+	msm_gpio_writel(msm_chip, msm_chip->int_enable[0], MSM_GPIO_INT_EN);
 	spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
 }
 
@@ -537,12 +574,12 @@ static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int flow_type)
 	unsigned val, mask = BIT(offset);
 
 	spin_lock_irqsave(&msm_chip->lock, irq_flags);
-	val = readl(msm_chip->regs.int_edge);
+	val = msm_gpio_readl(msm_chip, MSM_GPIO_INT_EDGE);
 	if (flow_type & IRQ_TYPE_EDGE_BOTH) {
-		writel(val | mask, msm_chip->regs.int_edge);
+		msm_gpio_writel(msm_chip, val | mask, MSM_GPIO_INT_EDGE);
 		__irq_set_handler_locked(d->irq, handle_edge_irq);
 	} else {
-		writel(val & ~mask, msm_chip->regs.int_edge);
+		msm_gpio_writel(msm_chip, val & ~mask, MSM_GPIO_INT_EDGE);
 		__irq_set_handler_locked(d->irq, handle_level_irq);
 	}
 	if ((flow_type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) {
@@ -550,11 +587,12 @@ static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int flow_type)
 		msm_gpio_update_both_edge_detect(msm_chip);
 	} else {
 		msm_chip->both_edge_detect &= ~mask;
-		val = readl(msm_chip->regs.int_pos);
+		val = msm_gpio_readl(msm_chip, MSM_GPIO_INT_POS);
 		if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_HIGH))
-			writel(val | mask, msm_chip->regs.int_pos);
+			val |= mask;
 		else
-			writel(val & ~mask, msm_chip->regs.int_pos);
+			val &= ~mask;
+		msm_gpio_writel(msm_chip, val, MSM_GPIO_INT_POS);
 	}
 	spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
 	return 0;
@@ -567,7 +605,7 @@ static void msm_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 
 	for (i = 0; i < msm_gpio_count; i++) {
 		struct msm_gpio_chip *msm_chip = &msm_gpio_chips[i];
-		val = readl(msm_chip->regs.int_status);
+		val = msm_gpio_readl(msm_chip, MSM_GPIO_INT_STATUS);
 		val &= msm_chip->int_enable[0];
 		while (val) {
 			mask = val & -val;
@@ -592,22 +630,36 @@ static struct irq_chip msm_gpio_irq_chip = {
 	.irq_set_type  = msm_gpio_irq_set_type,
 };
 
-static int __init msm_init_gpio(void)
+static int __devinit gpio_msm_v1_probe(struct platform_device *pdev)
 {
 	int i, j = 0;
-
-	if (cpu_is_msm7x01()) {
-		msm_gpio_chips = msm_gpio_chips_msm7x01;
-		msm_gpio_count = ARRAY_SIZE(msm_gpio_chips_msm7x01);
-	} else if (cpu_is_msm7x30()) {
-		msm_gpio_chips = msm_gpio_chips_msm7x30;
-		msm_gpio_count = ARRAY_SIZE(msm_gpio_chips_msm7x30);
-	} else if (cpu_is_qsd8x50()) {
-		msm_gpio_chips = msm_gpio_chips_qsd8x50;
-		msm_gpio_count = ARRAY_SIZE(msm_gpio_chips_qsd8x50);
-	} else {
-		return 0;
-	}
+	const struct platform_device_id *dev_id = platform_get_device_id(pdev);
+	struct msm_gpio_initdata *data;
+	int irq1, irq2;
+	struct resource *res;
+	void __iomem *base1, __iomem *base2;
+
+	data = (struct msm_gpio_initdata *)dev_id->driver_data;
+	msm_gpio_chips = data->chips;
+	msm_gpio_count = data->count;
+
+	irq1 = platform_get_irq(pdev, 0);
+	if (irq1 < 0)
+		return irq1;
+
+	irq2 = platform_get_irq(pdev, 1);
+	if (irq2 < 0)
+		return irq2;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	base1 = devm_request_and_ioremap(&pdev->dev, res);
+	if (!base1)
+		return -EADDRNOTAVAIL;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	base2 = devm_request_and_ioremap(&pdev->dev, res);
+	if (!base2)
+		return -EADDRNOTAVAIL;
 
 	for (i = FIRST_GPIO_IRQ; i < FIRST_GPIO_IRQ + NR_GPIO_IRQS; i++) {
 		if (i - FIRST_GPIO_IRQ >=
@@ -621,16 +673,42 @@ static int __init msm_init_gpio(void)
 	}
 
 	for (i = 0; i < msm_gpio_count; i++) {
+		if (i == 1)
+			msm_gpio_chips[i].base = base2;
+		else
+			msm_gpio_chips[i].base = base1;
 		spin_lock_init(&msm_gpio_chips[i].lock);
-		writel(0, msm_gpio_chips[i].regs.int_en);
+		msm_gpio_writel(&msm_gpio_chips[i], 0, MSM_GPIO_INT_EN);
 		gpiochip_add(&msm_gpio_chips[i].chip);
 	}
 
-	irq_set_chained_handler(INT_GPIO_GROUP1, msm_gpio_irq_handler);
-	irq_set_chained_handler(INT_GPIO_GROUP2, msm_gpio_irq_handler);
-	irq_set_irq_wake(INT_GPIO_GROUP1, 1);
-	irq_set_irq_wake(INT_GPIO_GROUP2, 2);
+	irq_set_chained_handler(irq1, msm_gpio_irq_handler);
+	irq_set_chained_handler(irq2, msm_gpio_irq_handler);
+	irq_set_irq_wake(irq1, 1);
+	irq_set_irq_wake(irq2, 2);
 	return 0;
 }
 
-postcore_initcall(msm_init_gpio);
+static struct platform_device_id gpio_msm_v1_device_ids[] = {
+	{ "gpio-msm-7201", (unsigned long)&msm_gpio_7x01_init },
+	{ "gpio-msm-7x30", (unsigned long)&msm_gpio_7x30_init },
+	{ "gpio-msm-8x50", (unsigned long)&msm_gpio_8x50_init },
+	{ }
+};
+MODULE_DEVICE_TABLE(platform, gpio_msm_v1_device_ids);
+
+static struct platform_driver gpio_msm_v1_driver = {
+	.driver = {
+		.name = "gpio-msm-v1",
+		.owner = THIS_MODULE,
+	},
+	.probe = gpio_msm_v1_probe,
+	.id_table = gpio_msm_v1_device_ids,
+};
+
+static int __init gpio_msm_v1_init(void)
+{
+	return platform_driver_register(&gpio_msm_v1_driver);
+}
+postcore_initcall(gpio_msm_v1_init);
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpio/gpio-msm-v2.c b/drivers/gpio/gpio-msm-v2.c
index 55a7e77..dd2edde 100644
--- a/drivers/gpio/gpio-msm-v2.c
+++ b/drivers/gpio/gpio-msm-v2.c
@@ -23,13 +23,12 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
+#include <linux/irqchip/chained_irq.h>
 #include <linux/irq.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/spinlock.h>
 
-#include <asm/mach/irq.h>
-
 #include <mach/msm_gpiomux.h>
 #include <mach/msm_iomap.h>
 
diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c
index 61a6fde..bf69a7e 100644
--- a/drivers/gpio/gpio-mvebu.c
+++ b/drivers/gpio/gpio-mvebu.c
@@ -117,7 +117,7 @@ static inline void __iomem *mvebu_gpioreg_edge_cause(struct mvebu_gpio_chip *mvc
 {
 	int cpu;
 
-	switch(mvchip->soc_variant) {
+	switch (mvchip->soc_variant) {
 	case MVEBU_GPIO_SOC_VARIANT_ORION:
 	case MVEBU_GPIO_SOC_VARIANT_MV78200:
 		return mvchip->membase + GPIO_EDGE_CAUSE_OFF;
@@ -133,7 +133,7 @@ static inline void __iomem *mvebu_gpioreg_edge_mask(struct mvebu_gpio_chip *mvch
 {
 	int cpu;
 
-	switch(mvchip->soc_variant) {
+	switch (mvchip->soc_variant) {
 	case MVEBU_GPIO_SOC_VARIANT_ORION:
 		return mvchip->membase + GPIO_EDGE_MASK_OFF;
 	case MVEBU_GPIO_SOC_VARIANT_MV78200:
@@ -151,7 +151,7 @@ static void __iomem *mvebu_gpioreg_level_mask(struct mvebu_gpio_chip *mvchip)
 {
 	int cpu;
 
-	switch(mvchip->soc_variant) {
+	switch (mvchip->soc_variant) {
 	case MVEBU_GPIO_SOC_VARIANT_ORION:
 		return mvchip->membase + GPIO_LEVEL_MASK_OFF;
 	case MVEBU_GPIO_SOC_VARIANT_MV78200:
@@ -401,7 +401,7 @@ static int mvebu_gpio_irq_set_type(struct irq_data *d, unsigned int type)
 	/*
 	 * Configure interrupt polarity.
 	 */
-	switch(type) {
+	switch (type) {
 	case IRQ_TYPE_EDGE_RISING:
 	case IRQ_TYPE_LEVEL_HIGH:
 		u = readl_relaxed(mvebu_gpioreg_in_pol(mvchip));
@@ -470,18 +470,76 @@ static void mvebu_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 	}
 }
 
+#ifdef CONFIG_DEBUG_FS
+#include <linux/seq_file.h>
+
+static void mvebu_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
+{
+	struct mvebu_gpio_chip *mvchip =
+		container_of(chip, struct mvebu_gpio_chip, chip);
+	u32 out, io_conf, blink, in_pol, data_in, cause, edg_msk, lvl_msk;
+	int i;
+
+	out	= readl_relaxed(mvebu_gpioreg_out(mvchip));
+	io_conf	= readl_relaxed(mvebu_gpioreg_io_conf(mvchip));
+	blink	= readl_relaxed(mvebu_gpioreg_blink(mvchip));
+	in_pol	= readl_relaxed(mvebu_gpioreg_in_pol(mvchip));
+	data_in	= readl_relaxed(mvebu_gpioreg_data_in(mvchip));
+	cause	= readl_relaxed(mvebu_gpioreg_edge_cause(mvchip));
+	edg_msk	= readl_relaxed(mvebu_gpioreg_edge_mask(mvchip));
+	lvl_msk	= readl_relaxed(mvebu_gpioreg_level_mask(mvchip));
+
+	for (i = 0; i < chip->ngpio; i++) {
+		const char *label;
+		u32 msk;
+		bool is_out;
+
+		label = gpiochip_is_requested(chip, i);
+		if (!label)
+			continue;
+
+		msk = 1 << i;
+		is_out = !(io_conf & msk);
+
+		seq_printf(s, " gpio-%-3d (%-20.20s)", chip->base + i, label);
+
+		if (is_out) {
+			seq_printf(s, " out %s %s\n",
+				   out & msk ? "hi" : "lo",
+				   blink & msk ? "(blink )" : "");
+			continue;
+		}
+
+		seq_printf(s, " in  %s (act %s) - IRQ",
+			   (data_in ^ in_pol) & msk  ? "hi" : "lo",
+			   in_pol & msk ? "lo" : "hi");
+		if (!((edg_msk | lvl_msk) & msk)) {
+			seq_printf(s, " disabled\n");
+			continue;
+		}
+		if (edg_msk & msk)
+			seq_printf(s, " edge ");
+		if (lvl_msk & msk)
+			seq_printf(s, " level");
+		seq_printf(s, " (%s)\n", cause & msk ? "pending" : "clear  ");
+	}
+}
+#else
+#define mvebu_gpio_dbg_show NULL
+#endif
+
 static struct of_device_id mvebu_gpio_of_match[] = {
 	{
 		.compatible = "marvell,orion-gpio",
-		.data       = (void*) MVEBU_GPIO_SOC_VARIANT_ORION,
+		.data       = (void *) MVEBU_GPIO_SOC_VARIANT_ORION,
 	},
 	{
 		.compatible = "marvell,mv78200-gpio",
-		.data       = (void*) MVEBU_GPIO_SOC_VARIANT_MV78200,
+		.data       = (void *) MVEBU_GPIO_SOC_VARIANT_MV78200,
 	},
 	{
 		.compatible = "marvell,armadaxp-gpio",
-		.data       = (void*) MVEBU_GPIO_SOC_VARIANT_ARMADAXP,
+		.data       = (void *) MVEBU_GPIO_SOC_VARIANT_ARMADAXP,
 	},
 	{
 		/* sentinel */
@@ -509,13 +567,13 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
 		soc_variant = MVEBU_GPIO_SOC_VARIANT_ORION;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (! res) {
+	if (!res) {
 		dev_err(&pdev->dev, "Cannot get memory resource\n");
 		return -ENODEV;
 	}
 
 	mvchip = devm_kzalloc(&pdev->dev, sizeof(struct mvebu_gpio_chip), GFP_KERNEL);
-	if (! mvchip){
+	if (!mvchip) {
 		dev_err(&pdev->dev, "Cannot allocate memory\n");
 		return -ENOMEM;
 	}
@@ -550,6 +608,7 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
 	mvchip->chip.ngpio = ngpios;
 	mvchip->chip.can_sleep = 0;
 	mvchip->chip.of_node = np;
+	mvchip->chip.dbg_show = mvebu_gpio_dbg_show;
 
 	spin_lock_init(&mvchip->lock);
 	mvchip->membase = devm_ioremap_resource(&pdev->dev, res);
@@ -560,21 +619,21 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
 	 * per-CPU registers */
 	if (soc_variant == MVEBU_GPIO_SOC_VARIANT_ARMADAXP) {
 		res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-		if (! res) {
+		if (!res) {
 			dev_err(&pdev->dev, "Cannot get memory resource\n");
 			return -ENODEV;
 		}
 
 		mvchip->percpu_membase = devm_ioremap_resource(&pdev->dev,
 							       res);
-		if (IS_ERR(mvchip->percpu_membase)) 
+		if (IS_ERR(mvchip->percpu_membase))
 			return PTR_ERR(mvchip->percpu_membase);
 	}
 
 	/*
 	 * Mask and clear GPIO interrupts.
 	 */
-	switch(soc_variant) {
+	switch (soc_variant) {
 	case MVEBU_GPIO_SOC_VARIANT_ORION:
 		writel_relaxed(0, mvchip->membase + GPIO_EDGE_CAUSE_OFF);
 		writel_relaxed(0, mvchip->membase + GPIO_EDGE_MASK_OFF);
@@ -632,7 +691,7 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
 
 	gc = irq_alloc_generic_chip("mvebu_gpio_irq", 2, mvchip->irqbase,
 				    mvchip->membase, handle_level_irq);
-	if (! gc) {
+	if (!gc) {
 		dev_err(&pdev->dev, "Cannot allocate generic irq_chip\n");
 		return -ENOMEM;
 	}
diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
index 7877335..7176743 100644
--- a/drivers/gpio/gpio-mxc.c
+++ b/drivers/gpio/gpio-mxc.c
@@ -24,6 +24,7 @@
 #include <linux/io.h>
 #include <linux/irq.h>
 #include <linux/irqdomain.h>
+#include <linux/irqchip/chained_irq.h>
 #include <linux/gpio.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
@@ -32,7 +33,6 @@
 #include <linux/of_device.h>
 #include <linux/module.h>
 #include <asm-generic/bug.h>
-#include <asm/mach/irq.h>
 
 enum mxc_gpio_hwtype {
 	IMX1_GPIO,	/* runs on i.mx1 */
diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c
index 159f5c5..c1db1db 100644
--- a/drivers/gpio/gpio-omap.c
+++ b/drivers/gpio/gpio-omap.c
@@ -25,11 +25,10 @@
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/irqdomain.h>
+#include <linux/irqchip/chained_irq.h>
 #include <linux/gpio.h>
 #include <linux/platform_data/gpio-omap.h>
 
-#include <asm/mach/irq.h>
-
 #define OFF_MODE	1
 
 static LIST_HEAD(omap_gpio_list);
@@ -53,7 +52,6 @@ struct gpio_bank {
 	struct list_head node;
 	void __iomem *base;
 	u16 irq;
-	int irq_base;
 	struct irq_domain *domain;
 	u32 non_wakeup_gpios;
 	u32 enabled_non_wakeup_gpios;
@@ -89,7 +87,14 @@ struct gpio_bank {
 
 static int irq_to_gpio(struct gpio_bank *bank, unsigned int gpio_irq)
 {
-	return gpio_irq - bank->irq_base + bank->chip.base;
+	return bank->chip.base + gpio_irq;
+}
+
+static int omap_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	struct gpio_bank *bank = container_of(chip, struct gpio_bank, chip);
+
+	return irq_find_mapping(bank->domain, offset);
 }
 
 static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input)
@@ -421,13 +426,16 @@ static int gpio_irq_type(struct irq_data *d, unsigned type)
 	int retval;
 	unsigned long flags;
 
+	if (WARN_ON(!bank->mod_usage))
+		return -EINVAL;
+
 #ifdef CONFIG_ARCH_OMAP1
 	if (d->irq > IH_MPUIO_BASE)
 		gpio = OMAP_MPUIO(d->irq - IH_MPUIO_BASE);
 #endif
 
 	if (!gpio)
-		gpio = irq_to_gpio(bank, d->irq);
+		gpio = irq_to_gpio(bank, d->hwirq);
 
 	if (type & ~IRQ_TYPE_SENSE_MASK)
 		return -EINVAL;
@@ -580,7 +588,7 @@ static void _reset_gpio(struct gpio_bank *bank, int gpio)
 static int gpio_wake_enable(struct irq_data *d, unsigned int enable)
 {
 	struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
-	unsigned int gpio = irq_to_gpio(bank, d->irq);
+	unsigned int gpio = irq_to_gpio(bank, d->hwirq);
 
 	return _set_gpio_wakeup(bank, gpio, enable);
 }
@@ -680,7 +688,7 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 {
 	void __iomem *isr_reg = NULL;
 	u32 isr;
-	unsigned int gpio_irq, gpio_index;
+	unsigned int i;
 	struct gpio_bank *bank;
 	int unmasked = 0;
 	struct irq_chip *chip = irq_desc_get_chip(desc);
@@ -694,7 +702,7 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 	if (WARN_ON(!isr_reg))
 		goto exit;
 
-	while(1) {
+	while (1) {
 		u32 isr_saved, level_mask = 0;
 		u32 enabled;
 
@@ -721,15 +729,10 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 		if (!isr)
 			break;
 
-		gpio_irq = bank->irq_base;
-		for (; isr != 0; isr >>= 1, gpio_irq++) {
-			int gpio = irq_to_gpio(bank, gpio_irq);
-
+		for (i = 0; isr != 0; isr >>= 1, i++) {
 			if (!(isr & 1))
 				continue;
 
-			gpio_index = GPIO_INDEX(bank, gpio);
-
 			/*
 			 * Some chips can't respond to both rising and falling
 			 * at the same time.  If this irq was requested with
@@ -737,10 +740,10 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 			 * to respond to the IRQ for the opposite direction.
 			 * This will be indicated in the bank toggle_mask.
 			 */
-			if (bank->toggle_mask & (1 << gpio_index))
-				_toggle_gpio_edge_triggering(bank, gpio_index);
+			if (bank->toggle_mask & (1 << i))
+				_toggle_gpio_edge_triggering(bank, i);
 
-			generic_handle_irq(gpio_irq);
+			generic_handle_irq(irq_find_mapping(bank->domain, i));
 		}
 	}
 	/* if bank has any level sensitive GPIO pin interrupt
@@ -756,7 +759,7 @@ exit:
 static void gpio_irq_shutdown(struct irq_data *d)
 {
 	struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
-	unsigned int gpio = irq_to_gpio(bank, d->irq);
+	unsigned int gpio = irq_to_gpio(bank, d->hwirq);
 	unsigned long flags;
 
 	spin_lock_irqsave(&bank->lock, flags);
@@ -767,7 +770,7 @@ static void gpio_irq_shutdown(struct irq_data *d)
 static void gpio_ack_irq(struct irq_data *d)
 {
 	struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
-	unsigned int gpio = irq_to_gpio(bank, d->irq);
+	unsigned int gpio = irq_to_gpio(bank, d->hwirq);
 
 	_clear_gpio_irqstatus(bank, gpio);
 }
@@ -775,7 +778,7 @@ static void gpio_ack_irq(struct irq_data *d)
 static void gpio_mask_irq(struct irq_data *d)
 {
 	struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
-	unsigned int gpio = irq_to_gpio(bank, d->irq);
+	unsigned int gpio = irq_to_gpio(bank, d->hwirq);
 	unsigned long flags;
 
 	spin_lock_irqsave(&bank->lock, flags);
@@ -787,7 +790,7 @@ static void gpio_mask_irq(struct irq_data *d)
 static void gpio_unmask_irq(struct irq_data *d)
 {
 	struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
-	unsigned int gpio = irq_to_gpio(bank, d->irq);
+	unsigned int gpio = irq_to_gpio(bank, d->hwirq);
 	unsigned int irq_mask = GPIO_BIT(bank, gpio);
 	u32 trigger = irqd_get_trigger_type(d);
 	unsigned long flags;
@@ -953,14 +956,6 @@ static void gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 	spin_unlock_irqrestore(&bank->lock, flags);
 }
 
-static int gpio_2irq(struct gpio_chip *chip, unsigned offset)
-{
-	struct gpio_bank *bank;
-
-	bank = container_of(chip, struct gpio_bank, chip);
-	return bank->irq_base + offset;
-}
-
 /*---------------------------------------------------------------------*/
 
 static void __init omap_gpio_show_rev(struct gpio_bank *bank)
@@ -1057,7 +1052,7 @@ static void omap_gpio_chip_init(struct gpio_bank *bank)
 	bank->chip.direction_output = gpio_output;
 	bank->chip.set_debounce = gpio_debounce;
 	bank->chip.set = gpio_set;
-	bank->chip.to_irq = gpio_2irq;
+	bank->chip.to_irq = omap_gpio_to_irq;
 	if (bank->is_mpuio) {
 		bank->chip.label = "mpuio";
 		if (bank->regs->wkup_en)
@@ -1072,15 +1067,16 @@ static void omap_gpio_chip_init(struct gpio_bank *bank)
 
 	gpiochip_add(&bank->chip);
 
-	for (j = bank->irq_base; j < bank->irq_base + bank->width; j++) {
-		irq_set_lockdep_class(j, &gpio_lock_class);
-		irq_set_chip_data(j, bank);
+	for (j = 0; j < bank->width; j++) {
+		int irq = irq_create_mapping(bank->domain, j);
+		irq_set_lockdep_class(irq, &gpio_lock_class);
+		irq_set_chip_data(irq, bank);
 		if (bank->is_mpuio) {
-			omap_mpuio_alloc_gc(bank, j, bank->width);
+			omap_mpuio_alloc_gc(bank, irq, 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_chip_and_handler(irq, &gpio_irq_chip,
+						 handle_simple_irq);
+			set_irq_flags(irq, IRQF_VALID);
 		}
 	}
 	irq_set_chained_handler(bank->irq, gpio_irq_handler);
@@ -1130,14 +1126,10 @@ static int omap_gpio_probe(struct platform_device *pdev)
 	bank->chip.of_node = of_node_get(node);
 #endif
 
-	bank->irq_base = irq_alloc_descs(-1, 0, bank->width, 0);
-	if (bank->irq_base < 0) {
-		dev_err(dev, "Couldn't allocate IRQ numbers\n");
+	bank->domain = irq_domain_add_linear(node, bank->width,
+					     &irq_domain_simple_ops, NULL);
+	if (!bank->domain)
 		return -ENODEV;
-	}
-
-	bank->domain = irq_domain_add_legacy(node, bank->width, bank->irq_base,
-					     0, &irq_domain_simple_ops, NULL);
 
 	if (bank->regs->set_dataout && bank->regs->clr_dataout)
 		bank->set_dataout = _set_gpio_dataout_reg;
diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c
index 2405946..15dbc36 100644
--- a/drivers/gpio/gpio-pca953x.c
+++ b/drivers/gpio/gpio-pca953x.c
@@ -146,8 +146,7 @@ static int pca953x_write_regs(struct pca953x_chip *chip, int reg, u8 *val)
 		ret = i2c_smbus_write_i2c_block_data(chip->client,
 					(reg << bank_shift) | REG_ADDR_AI,
 					NBANK(chip), val);
-	}
-	else {
+	} else {
 		switch (chip->chip_type) {
 		case PCA953X_TYPE:
 			ret = i2c_smbus_write_word_data(chip->client,
diff --git a/drivers/gpio/gpio-pcf857x.c b/drivers/gpio/gpio-pcf857x.c
index a19b745..e8faf53 100644
--- a/drivers/gpio/gpio-pcf857x.c
+++ b/drivers/gpio/gpio-pcf857x.c
@@ -45,6 +45,7 @@ static const struct i2c_device_id pcf857x_id[] = {
 	{ "pca9675", 16 },
 	{ "max7328", 8 },
 	{ "max7329", 8 },
+	{ "tca9554", 8 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, pcf857x_id);
@@ -267,7 +268,7 @@ static int pcf857x_probe(struct i2c_client *client,
 	}
 
 	/* Allocate, initialize, and register this gpio_chip. */
-	gpio = kzalloc(sizeof *gpio, GFP_KERNEL);
+	gpio = devm_kzalloc(&client->dev, sizeof(*gpio), GFP_KERNEL);
 	if (!gpio)
 		return -ENOMEM;
 
@@ -390,7 +391,6 @@ fail:
 	if (pdata && client->irq)
 		pcf857x_irq_domain_cleanup(gpio);
 
-	kfree(gpio);
 	return status;
 }
 
@@ -415,9 +415,7 @@ static int pcf857x_remove(struct i2c_client *client)
 		pcf857x_irq_domain_cleanup(gpio);
 
 	status = gpiochip_remove(&gpio->chip);
-	if (status == 0)
-		kfree(gpio);
-	else
+	if (status)
 		dev_err(&client->dev, "%s --> %d\n", "remove", status);
 	return status;
 }
diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c
index b820869..c1ff7f6 100644
--- a/drivers/gpio/gpio-pl061.c
+++ b/drivers/gpio/gpio-pl061.c
@@ -15,6 +15,8 @@
 #include <linux/io.h>
 #include <linux/ioport.h>
 #include <linux/irq.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/irqdomain.h>
 #include <linux/bitops.h>
 #include <linux/workqueue.h>
 #include <linux/gpio.h>
@@ -22,8 +24,8 @@
 #include <linux/amba/bus.h>
 #include <linux/amba/pl061.h>
 #include <linux/slab.h>
+#include <linux/pinctrl/consumer.h>
 #include <linux/pm.h>
-#include <asm/mach/irq.h>
 
 #define GPIODIR 0x400
 #define GPIOIS  0x404
@@ -51,8 +53,7 @@ struct pl061_gpio {
 	spinlock_t		lock;
 
 	void __iomem		*base;
-	int			irq_base;
-	struct irq_chip_generic	*irq_gc;
+	struct irq_domain	*domain;
 	struct gpio_chip	gc;
 
 #ifdef CONFIG_PM
@@ -60,6 +61,24 @@ struct pl061_gpio {
 #endif
 };
 
+static int pl061_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+	/*
+	 * Map back to global GPIO space and request muxing, the direction
+	 * parameter does not matter for this controller.
+	 */
+	int gpio = chip->base + offset;
+
+	return pinctrl_request_gpio(gpio);
+}
+
+static void pl061_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+	int gpio = chip->base + offset;
+
+	pinctrl_free_gpio(gpio);
+}
+
 static int pl061_direction_input(struct gpio_chip *gc, unsigned offset)
 {
 	struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
@@ -122,24 +141,20 @@ 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 <= 0)
-		return -EINVAL;
-
-	return chip->irq_base + offset;
+	return irq_create_mapping(chip->domain, offset);
 }
 
 static int pl061_irq_type(struct irq_data *d, unsigned trigger)
 {
-	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
-	struct pl061_gpio *chip = gc->private;
-	int offset = d->irq - chip->irq_base;
+	struct pl061_gpio *chip = irq_data_get_irq_chip_data(d);
+	int offset = irqd_to_hwirq(d);
 	unsigned long flags;
 	u8 gpiois, gpioibe, gpioiev;
 
 	if (offset < 0 || offset >= PL061_GPIO_NR)
 		return -EINVAL;
 
-	raw_spin_lock_irqsave(&gc->lock, flags);
+	spin_lock_irqsave(&chip->lock, flags);
 
 	gpioiev = readb(chip->base + GPIOIEV);
 
@@ -168,7 +183,7 @@ static int pl061_irq_type(struct irq_data *d, unsigned trigger)
 
 	writeb(gpioiev, chip->base + GPIOIEV);
 
-	raw_spin_unlock_irqrestore(&gc->lock, flags);
+	spin_unlock_irqrestore(&chip->lock, flags);
 
 	return 0;
 }
@@ -192,31 +207,61 @@ static void pl061_irq_handler(unsigned irq, struct irq_desc *desc)
 	chained_irq_exit(irqchip, desc);
 }
 
-static void __init pl061_init_gc(struct pl061_gpio *chip, int irq_base)
+static void pl061_irq_mask(struct irq_data *d)
+{
+	struct pl061_gpio *chip = irq_data_get_irq_chip_data(d);
+	u8 mask = 1 << (irqd_to_hwirq(d) % PL061_GPIO_NR);
+	u8 gpioie;
+
+	spin_lock(&chip->lock);
+	gpioie = readb(chip->base + GPIOIE) & ~mask;
+	writeb(gpioie, chip->base + GPIOIE);
+	spin_unlock(&chip->lock);
+}
+
+static void pl061_irq_unmask(struct irq_data *d)
 {
-	struct irq_chip_type *ct;
+	struct pl061_gpio *chip = irq_data_get_irq_chip_data(d);
+	u8 mask = 1 << (irqd_to_hwirq(d) % PL061_GPIO_NR);
+	u8 gpioie;
+
+	spin_lock(&chip->lock);
+	gpioie = readb(chip->base + GPIOIE) | mask;
+	writeb(gpioie, chip->base + GPIOIE);
+	spin_unlock(&chip->lock);
+}
+
+static struct irq_chip pl061_irqchip = {
+	.name		= "pl061 gpio",
+	.irq_mask	= pl061_irq_mask,
+	.irq_unmask	= pl061_irq_unmask,
+	.irq_set_type	= pl061_irq_type,
+};
 
-	chip->irq_gc = irq_alloc_generic_chip("gpio-pl061", 1, irq_base,
-					      chip->base, handle_simple_irq);
-	chip->irq_gc->private = chip;
+static int pl061_irq_map(struct irq_domain *d, unsigned int virq,
+			 irq_hw_number_t hw)
+{
+	struct pl061_gpio *chip = d->host_data;
 
-	ct = chip->irq_gc->chip_types;
-	ct->chip.irq_mask = irq_gc_mask_clr_bit;
-	ct->chip.irq_unmask = irq_gc_mask_set_bit;
-	ct->chip.irq_set_type = pl061_irq_type;
-	ct->chip.irq_set_wake = irq_gc_set_wake;
-	ct->regs.mask = GPIOIE;
+	irq_set_chip_and_handler_name(virq, &pl061_irqchip, handle_simple_irq,
+				      "pl061");
+	irq_set_chip_data(virq, chip);
+	irq_set_irq_type(virq, IRQ_TYPE_NONE);
 
-	irq_setup_generic_chip(chip->irq_gc, IRQ_MSK(PL061_GPIO_NR),
-			       IRQ_GC_INIT_NESTED_LOCK, IRQ_NOREQUEST, 0);
+	return 0;
 }
 
+static const struct irq_domain_ops pl061_domain_ops = {
+	.map	= pl061_irq_map,
+	.xlate	= irq_domain_xlate_twocell,
+};
+
 static int pl061_probe(struct amba_device *adev, const struct amba_id *id)
 {
 	struct device *dev = &adev->dev;
 	struct pl061_platform_data *pdata = dev->platform_data;
 	struct pl061_gpio *chip;
-	int ret, irq, i;
+	int ret, irq, i, irq_base;
 
 	chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
@@ -224,24 +269,32 @@ static int pl061_probe(struct amba_device *adev, const struct amba_id *id)
 
 	if (pdata) {
 		chip->gc.base = pdata->gpio_base;
-		chip->irq_base = pdata->irq_base;
-	} else if (adev->dev.of_node) {
+		irq_base = pdata->irq_base;
+		if (irq_base <= 0)
+			return -ENODEV;
+	} else {
 		chip->gc.base = -1;
-		chip->irq_base = 0;
-	} else
-		return -ENODEV;
+		irq_base = 0;
+	}
 
 	if (!devm_request_mem_region(dev, adev->res.start,
-				resource_size(&adev->res), "pl061"))
+				     resource_size(&adev->res), "pl061"))
 		return -EBUSY;
 
 	chip->base = devm_ioremap(dev, adev->res.start,
-				resource_size(&adev->res));
-	if (chip->base == NULL)
+				  resource_size(&adev->res));
+	if (!chip->base)
 		return -ENOMEM;
 
+	chip->domain = irq_domain_add_simple(adev->dev.of_node, PL061_GPIO_NR,
+					     irq_base, &pl061_domain_ops, chip);
+	if (!chip->domain)
+		return -ENODEV;
+
 	spin_lock_init(&chip->lock);
 
+	chip->gc.request = pl061_gpio_request;
+	chip->gc.free = pl061_gpio_free;
 	chip->gc.direction_input = pl061_direction_input;
 	chip->gc.direction_output = pl061_direction_output;
 	chip->gc.get = pl061_get_value;
@@ -259,12 +312,6 @@ static int pl061_probe(struct amba_device *adev, const struct amba_id *id)
 	/*
 	 * irq_chip support
 	 */
-
-	if (chip->irq_base <= 0)
-		return 0;
-
-	pl061_init_gc(chip, chip->irq_base);
-
 	writeb(0, chip->base + GPIOIE); /* disable irqs */
 	irq = adev->irq[0];
 	if (irq < 0)
diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c
index 9cc108d..9ee9f86 100644
--- a/drivers/gpio/gpio-pxa.c
+++ b/drivers/gpio/gpio-pxa.c
@@ -19,6 +19,7 @@
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/irqdomain.h>
+#include <linux/irqchip/chained_irq.h>
 #include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
@@ -26,8 +27,6 @@
 #include <linux/syscore_ops.h>
 #include <linux/slab.h>
 
-#include <asm/mach/irq.h>
-
 #include <mach/irqs.h>
 
 /*
@@ -602,7 +601,7 @@ static int pxa_gpio_probe(struct platform_device *pdev)
 	for_each_gpio_chip(gpio, c) {
 		writel_relaxed(0, c->regbase + GFER_OFFSET);
 		writel_relaxed(0, c->regbase + GRER_OFFSET);
-		writel_relaxed(~0,c->regbase + GEDR_OFFSET);
+		writel_relaxed(~0, c->regbase + GEDR_OFFSET);
 		/* unmask GPIO edge detect for AP side */
 		if (gpio_is_mmp_type(gpio_type))
 			writel_relaxed(~0, c->regbase + ED_MASK_OFFSET);
@@ -669,7 +668,7 @@ static void pxa_gpio_resume(void)
 
 	for_each_gpio_chip(gpio, c) {
 		/* restore level with set/clear */
-		writel_relaxed( c->saved_gplr, c->regbase + GPSR_OFFSET);
+		writel_relaxed(c->saved_gplr, c->regbase + GPSR_OFFSET);
 		writel_relaxed(~c->saved_gplr, c->regbase + GPCR_OFFSET);
 
 		writel_relaxed(c->saved_grer, c->regbase + GRER_OFFSET);
diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c
new file mode 100644
index 0000000..b4ca450
--- /dev/null
+++ b/drivers/gpio/gpio-rcar.c
@@ -0,0 +1,396 @@
+/*
+ * Renesas R-Car GPIO Support
+ *
+ *  Copyright (C) 2013 Magnus Damm
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either 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/err.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/irqdomain.h>
+#include <linux/module.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/platform_data/gpio-rcar.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+
+struct gpio_rcar_priv {
+	void __iomem *base;
+	spinlock_t lock;
+	struct gpio_rcar_config config;
+	struct platform_device *pdev;
+	struct gpio_chip gpio_chip;
+	struct irq_chip irq_chip;
+	struct irq_domain *irq_domain;
+};
+
+#define IOINTSEL 0x00
+#define INOUTSEL 0x04
+#define OUTDT 0x08
+#define INDT 0x0c
+#define INTDT 0x10
+#define INTCLR 0x14
+#define INTMSK 0x18
+#define MSKCLR 0x1c
+#define POSNEG 0x20
+#define EDGLEVEL 0x24
+#define FILONOFF 0x28
+
+static inline u32 gpio_rcar_read(struct gpio_rcar_priv *p, int offs)
+{
+	return ioread32(p->base + offs);
+}
+
+static inline void gpio_rcar_write(struct gpio_rcar_priv *p, int offs,
+				   u32 value)
+{
+	iowrite32(value, p->base + offs);
+}
+
+static void gpio_rcar_modify_bit(struct gpio_rcar_priv *p, int offs,
+				 int bit, bool value)
+{
+	u32 tmp = gpio_rcar_read(p, offs);
+
+	if (value)
+		tmp |= BIT(bit);
+	else
+		tmp &= ~BIT(bit);
+
+	gpio_rcar_write(p, offs, tmp);
+}
+
+static void gpio_rcar_irq_disable(struct irq_data *d)
+{
+	struct gpio_rcar_priv *p = irq_data_get_irq_chip_data(d);
+
+	gpio_rcar_write(p, INTMSK, ~BIT(irqd_to_hwirq(d)));
+}
+
+static void gpio_rcar_irq_enable(struct irq_data *d)
+{
+	struct gpio_rcar_priv *p = irq_data_get_irq_chip_data(d);
+
+	gpio_rcar_write(p, MSKCLR, BIT(irqd_to_hwirq(d)));
+}
+
+static void gpio_rcar_config_interrupt_input_mode(struct gpio_rcar_priv *p,
+						  unsigned int hwirq,
+						  bool active_high_rising_edge,
+						  bool level_trigger)
+{
+	unsigned long flags;
+
+	/* follow steps in the GPIO documentation for
+	 * "Setting Edge-Sensitive Interrupt Input Mode" and
+	 * "Setting Level-Sensitive Interrupt Input Mode"
+	 */
+
+	spin_lock_irqsave(&p->lock, flags);
+
+	/* Configure postive or negative logic in POSNEG */
+	gpio_rcar_modify_bit(p, POSNEG, hwirq, !active_high_rising_edge);
+
+	/* Configure edge or level trigger in EDGLEVEL */
+	gpio_rcar_modify_bit(p, EDGLEVEL, hwirq, !level_trigger);
+
+	/* Select "Interrupt Input Mode" in IOINTSEL */
+	gpio_rcar_modify_bit(p, IOINTSEL, hwirq, true);
+
+	/* Write INTCLR in case of edge trigger */
+	if (!level_trigger)
+		gpio_rcar_write(p, INTCLR, BIT(hwirq));
+
+	spin_unlock_irqrestore(&p->lock, flags);
+}
+
+static int gpio_rcar_irq_set_type(struct irq_data *d, unsigned int type)
+{
+	struct gpio_rcar_priv *p = irq_data_get_irq_chip_data(d);
+	unsigned int hwirq = irqd_to_hwirq(d);
+
+	dev_dbg(&p->pdev->dev, "sense irq = %d, type = %d\n", hwirq, type);
+
+	switch (type & IRQ_TYPE_SENSE_MASK) {
+	case IRQ_TYPE_LEVEL_HIGH:
+		gpio_rcar_config_interrupt_input_mode(p, hwirq, true, true);
+		break;
+	case IRQ_TYPE_LEVEL_LOW:
+		gpio_rcar_config_interrupt_input_mode(p, hwirq, false, true);
+		break;
+	case IRQ_TYPE_EDGE_RISING:
+		gpio_rcar_config_interrupt_input_mode(p, hwirq, true, false);
+		break;
+	case IRQ_TYPE_EDGE_FALLING:
+		gpio_rcar_config_interrupt_input_mode(p, hwirq, false, false);
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static irqreturn_t gpio_rcar_irq_handler(int irq, void *dev_id)
+{
+	struct gpio_rcar_priv *p = dev_id;
+	u32 pending;
+	unsigned int offset, irqs_handled = 0;
+
+	while ((pending = gpio_rcar_read(p, INTDT))) {
+		offset = __ffs(pending);
+		gpio_rcar_write(p, INTCLR, BIT(offset));
+		generic_handle_irq(irq_find_mapping(p->irq_domain, offset));
+		irqs_handled++;
+	}
+
+	return irqs_handled ? IRQ_HANDLED : IRQ_NONE;
+}
+
+static inline struct gpio_rcar_priv *gpio_to_priv(struct gpio_chip *chip)
+{
+	return container_of(chip, struct gpio_rcar_priv, gpio_chip);
+}
+
+static void gpio_rcar_config_general_input_output_mode(struct gpio_chip *chip,
+						       unsigned int gpio,
+						       bool output)
+{
+	struct gpio_rcar_priv *p = gpio_to_priv(chip);
+	unsigned long flags;
+
+	/* follow steps in the GPIO documentation for
+	 * "Setting General Output Mode" and
+	 * "Setting General Input Mode"
+	 */
+
+	spin_lock_irqsave(&p->lock, flags);
+
+	/* Configure postive logic in POSNEG */
+	gpio_rcar_modify_bit(p, POSNEG, gpio, false);
+
+	/* Select "General Input/Output Mode" in IOINTSEL */
+	gpio_rcar_modify_bit(p, IOINTSEL, gpio, false);
+
+	/* Select Input Mode or Output Mode in INOUTSEL */
+	gpio_rcar_modify_bit(p, INOUTSEL, gpio, output);
+
+	spin_unlock_irqrestore(&p->lock, flags);
+}
+
+static int gpio_rcar_request(struct gpio_chip *chip, unsigned offset)
+{
+	return pinctrl_request_gpio(chip->base + offset);
+}
+
+static void gpio_rcar_free(struct gpio_chip *chip, unsigned offset)
+{
+	pinctrl_free_gpio(chip->base + offset);
+
+	/* Set the GPIO as an input to ensure that the next GPIO request won't
+	 * drive the GPIO pin as an output.
+	 */
+	gpio_rcar_config_general_input_output_mode(chip, offset, false);
+}
+
+static int gpio_rcar_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	gpio_rcar_config_general_input_output_mode(chip, offset, false);
+	return 0;
+}
+
+static int gpio_rcar_get(struct gpio_chip *chip, unsigned offset)
+{
+	return (int)(gpio_rcar_read(gpio_to_priv(chip), INDT) & BIT(offset));
+}
+
+static void gpio_rcar_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+	struct gpio_rcar_priv *p = gpio_to_priv(chip);
+	unsigned long flags;
+
+	spin_lock_irqsave(&p->lock, flags);
+	gpio_rcar_modify_bit(p, OUTDT, offset, value);
+	spin_unlock_irqrestore(&p->lock, flags);
+}
+
+static int gpio_rcar_direction_output(struct gpio_chip *chip, unsigned offset,
+				      int value)
+{
+	/* write GPIO value to output before selecting output mode of pin */
+	gpio_rcar_set(chip, offset, value);
+	gpio_rcar_config_general_input_output_mode(chip, offset, true);
+	return 0;
+}
+
+static int gpio_rcar_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	return irq_create_mapping(gpio_to_priv(chip)->irq_domain, offset);
+}
+
+static int gpio_rcar_irq_domain_map(struct irq_domain *h, unsigned int virq,
+				 irq_hw_number_t hw)
+{
+	struct gpio_rcar_priv *p = h->host_data;
+
+	dev_dbg(&p->pdev->dev, "map hw irq = %d, virq = %d\n", (int)hw, virq);
+
+	irq_set_chip_data(virq, h->host_data);
+	irq_set_chip_and_handler(virq, &p->irq_chip, handle_level_irq);
+	set_irq_flags(virq, IRQF_VALID); /* kill me now */
+	return 0;
+}
+
+static struct irq_domain_ops gpio_rcar_irq_domain_ops = {
+	.map	= gpio_rcar_irq_domain_map,
+};
+
+static int gpio_rcar_probe(struct platform_device *pdev)
+{
+	struct gpio_rcar_config *pdata = pdev->dev.platform_data;
+	struct gpio_rcar_priv *p;
+	struct resource *io, *irq;
+	struct gpio_chip *gpio_chip;
+	struct irq_chip *irq_chip;
+	const char *name = dev_name(&pdev->dev);
+	int ret;
+
+	p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL);
+	if (!p) {
+		dev_err(&pdev->dev, "failed to allocate driver data\n");
+		ret = -ENOMEM;
+		goto err0;
+	}
+
+	/* deal with driver instance configuration */
+	if (pdata)
+		p->config = *pdata;
+
+	p->pdev = pdev;
+	platform_set_drvdata(pdev, p);
+	spin_lock_init(&p->lock);
+
+	io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+
+	if (!io || !irq) {
+		dev_err(&pdev->dev, "missing IRQ or IOMEM\n");
+		ret = -EINVAL;
+		goto err0;
+	}
+
+	p->base = devm_ioremap_nocache(&pdev->dev, io->start,
+				       resource_size(io));
+	if (!p->base) {
+		dev_err(&pdev->dev, "failed to remap I/O memory\n");
+		ret = -ENXIO;
+		goto err0;
+	}
+
+	gpio_chip = &p->gpio_chip;
+	gpio_chip->request = gpio_rcar_request;
+	gpio_chip->free = gpio_rcar_free;
+	gpio_chip->direction_input = gpio_rcar_direction_input;
+	gpio_chip->get = gpio_rcar_get;
+	gpio_chip->direction_output = gpio_rcar_direction_output;
+	gpio_chip->set = gpio_rcar_set;
+	gpio_chip->to_irq = gpio_rcar_to_irq;
+	gpio_chip->label = name;
+	gpio_chip->owner = THIS_MODULE;
+	gpio_chip->base = p->config.gpio_base;
+	gpio_chip->ngpio = p->config.number_of_pins;
+
+	irq_chip = &p->irq_chip;
+	irq_chip->name = name;
+	irq_chip->irq_mask = gpio_rcar_irq_disable;
+	irq_chip->irq_unmask = gpio_rcar_irq_enable;
+	irq_chip->irq_enable = gpio_rcar_irq_enable;
+	irq_chip->irq_disable = gpio_rcar_irq_disable;
+	irq_chip->irq_set_type = gpio_rcar_irq_set_type;
+	irq_chip->flags	= IRQCHIP_SKIP_SET_WAKE | IRQCHIP_SET_TYPE_MASKED;
+
+	p->irq_domain = irq_domain_add_simple(pdev->dev.of_node,
+					      p->config.number_of_pins,
+					      p->config.irq_base,
+					      &gpio_rcar_irq_domain_ops, p);
+	if (!p->irq_domain) {
+		ret = -ENXIO;
+		dev_err(&pdev->dev, "cannot initialize irq domain\n");
+		goto err1;
+	}
+
+	if (devm_request_irq(&pdev->dev, irq->start,
+			     gpio_rcar_irq_handler, 0, name, p)) {
+		dev_err(&pdev->dev, "failed to request IRQ\n");
+		ret = -ENOENT;
+		goto err1;
+	}
+
+	ret = gpiochip_add(gpio_chip);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to add GPIO controller\n");
+		goto err1;
+	}
+
+	dev_info(&pdev->dev, "driving %d GPIOs\n", p->config.number_of_pins);
+
+	/* warn in case of mismatch if irq base is specified */
+	if (p->config.irq_base) {
+		ret = irq_find_mapping(p->irq_domain, 0);
+		if (p->config.irq_base != ret)
+			dev_warn(&pdev->dev, "irq base mismatch (%u/%u)\n",
+				 p->config.irq_base, ret);
+	}
+
+	ret = gpiochip_add_pin_range(gpio_chip, p->config.pctl_name, 0,
+				     gpio_chip->base, gpio_chip->ngpio);
+	if (ret < 0)
+		dev_warn(&pdev->dev, "failed to add pin range\n");
+
+	return 0;
+
+err1:
+	irq_domain_remove(p->irq_domain);
+err0:
+	return ret;
+}
+
+static int gpio_rcar_remove(struct platform_device *pdev)
+{
+	struct gpio_rcar_priv *p = platform_get_drvdata(pdev);
+	int ret;
+
+	ret = gpiochip_remove(&p->gpio_chip);
+	if (ret)
+		return ret;
+
+	irq_domain_remove(p->irq_domain);
+	return 0;
+}
+
+static struct platform_driver gpio_rcar_device_driver = {
+	.probe		= gpio_rcar_probe,
+	.remove		= gpio_rcar_remove,
+	.driver		= {
+		.name	= "gpio_rcar",
+	}
+};
+
+module_platform_driver(gpio_rcar_device_driver);
+
+MODULE_AUTHOR("Magnus Damm");
+MODULE_DESCRIPTION("Renesas R-Car GPIO Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c
index b3643ff..b22ca79 100644
--- a/drivers/gpio/gpio-samsung.c
+++ b/drivers/gpio/gpio-samsung.c
@@ -1122,8 +1122,12 @@ int samsung_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset)
 #ifdef CONFIG_PLAT_S3C24XX
 static int s3c24xx_gpiolib_fbank_to_irq(struct gpio_chip *chip, unsigned offset)
 {
-	if (offset < 4)
-		return IRQ_EINT0 + offset;
+	if (offset < 4) {
+		if (soc_is_s3c2412())
+			return IRQ_EINT0_2412 + offset;
+		else
+			return IRQ_EINT0 + offset;
+	}
 
 	if (offset < 8)
 		return IRQ_EINT4 + offset - 4;
@@ -3024,7 +3028,9 @@ static __init int samsung_gpiolib_init(void)
 	static const struct of_device_id exynos_pinctrl_ids[] = {
 		{ .compatible = "samsung,exynos4210-pinctrl", },
 		{ .compatible = "samsung,exynos4x12-pinctrl", },
+		{ .compatible = "samsung,exynos5250-pinctrl", },
 		{ .compatible = "samsung,exynos5440-pinctrl", },
+		{ }
 	};
 	for_each_matching_node(pctrl_np, exynos_pinctrl_ids)
 		if (pctrl_np && of_device_is_available(pctrl_np))
diff --git a/drivers/gpio/gpio-sch.c b/drivers/gpio/gpio-sch.c
index edae963..1e4de16 100644
--- a/drivers/gpio/gpio-sch.c
+++ b/drivers/gpio/gpio-sch.c
@@ -125,13 +125,17 @@ static int sch_gpio_resume_direction_in(struct gpio_chip *gc,
 					unsigned gpio_num)
 {
 	u8 curr_dirs;
+	unsigned short offset, bit;
 
 	spin_lock(&gpio_lock);
 
-	curr_dirs = inb(gpio_ba + RGIO);
+	offset = RGIO + gpio_num / 8;
+	bit = gpio_num % 8;
+
+	curr_dirs = inb(gpio_ba + offset);
 
-	if (!(curr_dirs & (1 << gpio_num)))
-		outb(curr_dirs | (1 << gpio_num) , gpio_ba + RGIO);
+	if (!(curr_dirs & (1 << bit)))
+		outb(curr_dirs | (1 << bit), gpio_ba + offset);
 
 	spin_unlock(&gpio_lock);
 	return 0;
@@ -139,22 +143,31 @@ static int sch_gpio_resume_direction_in(struct gpio_chip *gc,
 
 static int sch_gpio_resume_get(struct gpio_chip *gc, unsigned gpio_num)
 {
-	return !!(inb(gpio_ba + RGLV) & (1 << gpio_num));
+	unsigned short offset, bit;
+
+	offset = RGLV + gpio_num / 8;
+	bit = gpio_num % 8;
+
+	return !!(inb(gpio_ba + offset) & (1 << bit));
 }
 
 static void sch_gpio_resume_set(struct gpio_chip *gc,
 				unsigned gpio_num, int val)
 {
 	u8 curr_vals;
+	unsigned short offset, bit;
 
 	spin_lock(&gpio_lock);
 
-	curr_vals = inb(gpio_ba + RGLV);
+	offset = RGLV + gpio_num / 8;
+	bit = gpio_num % 8;
+
+	curr_vals = inb(gpio_ba + offset);
 
 	if (val)
-		outb(curr_vals | (1 << gpio_num), gpio_ba + RGLV);
+		outb(curr_vals | (1 << bit), gpio_ba + offset);
 	else
-		outb((curr_vals & ~(1 << gpio_num)), gpio_ba + RGLV);
+		outb((curr_vals & ~(1 << bit)), gpio_ba + offset);
 
 	spin_unlock(&gpio_lock);
 }
@@ -163,14 +176,18 @@ static int sch_gpio_resume_direction_out(struct gpio_chip *gc,
 					unsigned gpio_num, int val)
 {
 	u8 curr_dirs;
+	unsigned short offset, bit;
 
 	sch_gpio_resume_set(gc, gpio_num, val);
 
+	offset = RGIO + gpio_num / 8;
+	bit = gpio_num % 8;
+
 	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);
+	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;
@@ -204,45 +221,41 @@ static int sch_gpio_probe(struct platform_device *pdev)
 	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;
-
-		case PCI_DEVICE_ID_INTEL_CENTERTON_ILB:
-			sch_gpio_core.base = 0;
-			sch_gpio_core.ngpio = 21;
-
-			sch_gpio_resume.base = 21;
-			sch_gpio_resume.ngpio = 9;
-			break;
-
-		default:
-			err = -ENODEV;
-			goto err_sch_gpio_core;
+	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;
+
+	case PCI_DEVICE_ID_INTEL_CENTERTON_ILB:
+		sch_gpio_core.base = 0;
+		sch_gpio_core.ngpio = 21;
+		sch_gpio_resume.base = 21;
+		sch_gpio_resume.ngpio = 9;
+		break;
+
+	default:
+		err = -ENODEV;
+		goto err_sch_gpio_core;
 	}
 
 	sch_gpio_core.dev = &pdev->dev;
diff --git a/drivers/gpio/gpio-stmpe.c b/drivers/gpio/gpio-stmpe.c
index 770476a..3ce5bc3 100644
--- a/drivers/gpio/gpio-stmpe.c
+++ b/drivers/gpio/gpio-stmpe.c
@@ -307,11 +307,15 @@ static const struct irq_domain_ops stmpe_gpio_irq_simple_ops = {
 	.xlate = irq_domain_xlate_twocell,
 };
 
-static int stmpe_gpio_irq_init(struct stmpe_gpio *stmpe_gpio)
+static int stmpe_gpio_irq_init(struct stmpe_gpio *stmpe_gpio,
+		struct device_node *np)
 {
-	int base = stmpe_gpio->irq_base;
+	int base = 0;
 
-	stmpe_gpio->domain = irq_domain_add_simple(NULL,
+	if (!np)
+		base = stmpe_gpio->irq_base;
+
+	stmpe_gpio->domain = irq_domain_add_simple(np,
 				stmpe_gpio->chip.ngpio, base,
 				&stmpe_gpio_irq_simple_ops, stmpe_gpio);
 	if (!stmpe_gpio->domain) {
@@ -346,6 +350,9 @@ static int stmpe_gpio_probe(struct platform_device *pdev)
 	stmpe_gpio->chip = template_chip;
 	stmpe_gpio->chip.ngpio = stmpe->num_gpios;
 	stmpe_gpio->chip.dev = &pdev->dev;
+#ifdef CONFIG_OF
+	stmpe_gpio->chip.of_node = np;
+#endif
 	stmpe_gpio->chip.base = pdata ? pdata->gpio_base : -1;
 
 	if (pdata)
@@ -366,7 +373,7 @@ static int stmpe_gpio_probe(struct platform_device *pdev)
 		goto out_free;
 
 	if (irq >= 0) {
-		ret = stmpe_gpio_irq_init(stmpe_gpio);
+		ret = stmpe_gpio_irq_init(stmpe_gpio, np);
 		if (ret)
 			goto out_disable;
 
diff --git a/drivers/gpio/gpio-stp-xway.c b/drivers/gpio/gpio-stp-xway.c
index c20e051..04882a9 100644
--- a/drivers/gpio/gpio-stp-xway.c
+++ b/drivers/gpio/gpio-stp-xway.c
@@ -217,7 +217,7 @@ static int xway_stp_probe(struct platform_device *pdev)
 	chip->virt = devm_ioremap_resource(&pdev->dev, res);
 	if (IS_ERR(chip->virt))
 		return PTR_ERR(chip->virt);
-	
+
 	chip->gc.dev = &pdev->dev;
 	chip->gc.label = "stp-xway";
 	chip->gc.direction_output = xway_stp_dir_out;
diff --git a/drivers/gpio/gpio-tc3589x.c b/drivers/gpio/gpio-tc3589x.c
index c0595bb..d34d80d 100644
--- a/drivers/gpio/gpio-tc3589x.c
+++ b/drivers/gpio/gpio-tc3589x.c
@@ -282,9 +282,9 @@ static void tc3589x_gpio_irq_unmap(struct irq_domain *d, unsigned int virq)
 }
 
 static struct irq_domain_ops tc3589x_irq_ops = {
-        .map    = tc3589x_gpio_irq_map,
-        .unmap  = tc3589x_gpio_irq_unmap,
-        .xlate  = irq_domain_xlate_twocell,
+	.map    = tc3589x_gpio_irq_map,
+	.unmap  = tc3589x_gpio_irq_unmap,
+	.xlate  = irq_domain_xlate_twocell,
 };
 
 static int tc3589x_gpio_irq_init(struct tc3589x_gpio *tc3589x_gpio,
@@ -344,7 +344,7 @@ static int tc3589x_gpio_probe(struct platform_device *pdev)
 	tc3589x_gpio->chip.base = (pdata) ? pdata->gpio_base : -1;
 
 #ifdef CONFIG_OF_GPIO
-        tc3589x_gpio->chip.of_node = np;
+	tc3589x_gpio->chip.of_node = np;
 #endif
 
 	tc3589x_gpio->irq_base = tc3589x->irq_base ?
diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c
index 414ad91..da4cb5b 100644
--- a/drivers/gpio/gpio-tegra.c
+++ b/drivers/gpio/gpio-tegra.c
@@ -27,11 +27,10 @@
 #include <linux/platform_device.h>
 #include <linux/module.h>
 #include <linux/irqdomain.h>
+#include <linux/irqchip/chained_irq.h>
 #include <linux/pinctrl/consumer.h>
 #include <linux/pm.h>
 
-#include <asm/mach/irq.h>
-
 #define GPIO_BANK(x)		((x) >> 5)
 #define GPIO_PORT(x)		(((x) >> 3) & 0x3)
 #define GPIO_BIT(x)		((x) & 0x7)
@@ -72,6 +71,7 @@ struct tegra_gpio_bank {
 	u32 oe[4];
 	u32 int_enb[4];
 	u32 int_lvl[4];
+	u32 wake_enb[4];
 #endif
 };
 
@@ -333,15 +333,31 @@ static int tegra_gpio_suspend(struct device *dev)
 			bank->oe[p] = tegra_gpio_readl(GPIO_OE(gpio));
 			bank->int_enb[p] = tegra_gpio_readl(GPIO_INT_ENB(gpio));
 			bank->int_lvl[p] = tegra_gpio_readl(GPIO_INT_LVL(gpio));
+
+			/* Enable gpio irq for wake up source */
+			tegra_gpio_writel(bank->wake_enb[p],
+					  GPIO_INT_ENB(gpio));
 		}
 	}
 	local_irq_restore(flags);
 	return 0;
 }
 
-static int tegra_gpio_wake_enable(struct irq_data *d, unsigned int enable)
+static int tegra_gpio_irq_set_wake(struct irq_data *d, unsigned int enable)
 {
 	struct tegra_gpio_bank *bank = irq_data_get_irq_chip_data(d);
+	int gpio = d->hwirq;
+	u32 port, bit, mask;
+
+	port = GPIO_PORT(gpio);
+	bit = GPIO_BIT(gpio);
+	mask = BIT(bit);
+
+	if (enable)
+		bank->wake_enb[port] |= mask;
+	else
+		bank->wake_enb[port] &= ~mask;
+
 	return irq_set_irq_wake(bank->irq, enable);
 }
 #endif
@@ -353,7 +369,7 @@ static struct irq_chip tegra_gpio_irq_chip = {
 	.irq_unmask	= tegra_gpio_irq_unmask,
 	.irq_set_type	= tegra_gpio_irq_set_type,
 #ifdef CONFIG_PM_SLEEP
-	.irq_set_wake	= tegra_gpio_wake_enable,
+	.irq_set_wake	= tegra_gpio_irq_set_wake,
 #endif
 };
 
@@ -398,10 +414,11 @@ static int tegra_gpio_probe(struct platform_device *pdev)
 	int j;
 
 	match = of_match_device(tegra_gpio_of_match, &pdev->dev);
-	if (match)
-		config = (struct tegra_gpio_soc_config *)match->data;
-	else
-		config = &tegra20_gpio_config;
+	if (!match) {
+		dev_err(&pdev->dev, "Error: No device match found\n");
+		return -ENODEV;
+	}
+	config = (struct tegra_gpio_soc_config *)match->data;
 
 	tegra_gpio_bank_stride = config->bank_stride;
 	tegra_gpio_upper_offset = config->upper_offset;
@@ -462,9 +479,7 @@ static int tegra_gpio_probe(struct platform_device *pdev)
 		}
 	}
 
-#ifdef CONFIG_OF_GPIO
 	tegra_gpio_chip.of_node = pdev->dev.of_node;
-#endif
 
 	gpiochip_add(&tegra_gpio_chip);
 
diff --git a/drivers/gpio/gpio-timberdale.c b/drivers/gpio/gpio-timberdale.c
index 702cca9..4377405 100644
--- a/drivers/gpio/gpio-timberdale.c
+++ b/drivers/gpio/gpio-timberdale.c
@@ -167,8 +167,7 @@ static int timbgpio_irq_type(struct irq_data *d, unsigned trigger)
 		if (ver < 3) {
 			ret = -EINVAL;
 			goto out;
-		}
-		else {
+		} else {
 			flr |= 1 << offset;
 			bflr |= 1 << offset;
 		}
diff --git a/drivers/gpio/gpio-tps65910.c b/drivers/gpio/gpio-tps65910.c
index 5083825..0614621 100644
--- a/drivers/gpio/gpio-tps65910.c
+++ b/drivers/gpio/gpio-tps65910.c
@@ -133,7 +133,7 @@ static int tps65910_gpio_probe(struct platform_device *pdev)
 	tps65910_gpio->gpio_chip.owner = THIS_MODULE;
 	tps65910_gpio->gpio_chip.label = tps65910->i2c_client->name;
 
-	switch(tps65910_chip_id(tps65910)) {
+	switch (tps65910_chip_id(tps65910)) {
 	case TPS65910:
 		tps65910_gpio->gpio_chip.ngpio = TPS65910_NUM_GPIO;
 		break;
diff --git a/drivers/gpio/gpio-viperboard.c b/drivers/gpio/gpio-viperboard.c
index 59d7239..095ab14 100644
--- a/drivers/gpio/gpio-viperboard.c
+++ b/drivers/gpio/gpio-viperboard.c
@@ -380,10 +380,6 @@ static int vprbrd_gpiob_direction_output(struct gpio_chip *chip,
 	struct vprbrd *vb = gpio->vb;
 
 	gpio->gpiob_out |= (1 << offset);
-	if (value)
-		gpio->gpiob_val |= (1 << offset);
-	else
-		gpio->gpiob_val &= ~(1 << offset);
 
 	mutex_lock(&vb->lock);
 
diff --git a/drivers/gpio/gpio-vt8500.c b/drivers/gpio/gpio-vt8500.c
index 81683ca..b2d8d6f 100644
--- a/drivers/gpio/gpio-vt8500.c
+++ b/drivers/gpio/gpio-vt8500.c
@@ -309,11 +309,9 @@ static int vt8500_gpio_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
-	gpio_base = devm_request_and_ioremap(&pdev->dev, res);
-	if (!gpio_base) {
-		dev_err(&pdev->dev, "Unable to map GPIO registers\n");
-		return -ENOMEM;
-	}
+	gpio_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(gpio_base))
+		return PTR_ERR(gpio_base);
 
 	ret = vt8500_add_chips(pdev, gpio_base, of_id->data);
 
diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c
index 5150df6..665f953 100644
--- a/drivers/gpio/gpiolib-of.c
+++ b/drivers/gpio/gpiolib-of.c
@@ -61,7 +61,7 @@ static int of_gpiochip_find_and_xlate(struct gpio_chip *gc, void *data)
  * in flags for the GPIO.
  */
 int of_get_named_gpio_flags(struct device_node *np, const char *propname,
-                           int index, enum of_gpio_flags *flags)
+			   int index, enum of_gpio_flags *flags)
 {
 	/* Return -EPROBE_DEFER to support probe() functions to be called
 	 * later when the GPIO actually becomes available
@@ -203,22 +203,11 @@ static void of_gpiochip_add_pin_range(struct gpio_chip *chip)
 		if (!pctldev)
 			break;
 
-		/*
-		 * This assumes that the n GPIO pins are consecutive in the
-		 * GPIO number space, and that the pins are also consecutive
-		 * in their local number space. Currently it is not possible
-		 * to add different ranges for one and the same GPIO chip,
-		 * as the code assumes that we have one consecutive range
-		 * on both, mapping 1-to-1.
-		 *
-		 * TODO: make the OF bindings handle multiple sparse ranges
-		 * on the same GPIO chip.
-		 */
 		ret = gpiochip_add_pin_range(chip,
 					     pinctrl_dev_get_devname(pctldev),
-					     0, /* offset in gpiochip */
 					     pinspec.args[0],
-					     pinspec.args[1]);
+					     pinspec.args[1],
+					     pinspec.args[2]);
 
 		if (ret)
 			break;
diff --git a/drivers/gpu/drm/drm_cache.c b/drivers/gpu/drm/drm_cache.c
index a575cb2..bb8f580 100644
--- a/drivers/gpu/drm/drm_cache.c
+++ b/drivers/gpu/drm/drm_cache.c
@@ -105,12 +105,11 @@ drm_clflush_sg(struct sg_table *st)
 {
 #if defined(CONFIG_X86)
 	if (cpu_has_clflush) {
-		struct scatterlist *sg;
-		int i;
+		struct sg_page_iter sg_iter;
 
 		mb();
-		for_each_sg(st->sgl, sg, st->nents, i)
-			drm_clflush_page(sg_page(sg));
+		for_each_sg_page(st->sgl, &sg_iter, st->nents, 0)
+			drm_clflush_page(sg_page_iter_page(&sg_iter));
 		mb();
 
 		return;
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 792c3e3..dd64a06 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -2326,7 +2326,6 @@ int drm_mode_addfb(struct drm_device *dev,
 	fb = dev->mode_config.funcs->fb_create(dev, file_priv, &r);
 	if (IS_ERR(fb)) {
 		DRM_DEBUG_KMS("could not create framebuffer\n");
-		drm_modeset_unlock_all(dev);
 		return PTR_ERR(fb);
 	}
 
@@ -2506,7 +2505,6 @@ int drm_mode_addfb2(struct drm_device *dev,
 	fb = dev->mode_config.funcs->fb_create(dev, file_priv, r);
 	if (IS_ERR(fb)) {
 		DRM_DEBUG_KMS("could not create framebuffer\n");
-		drm_modeset_unlock_all(dev);
 		return PTR_ERR(fb);
 	}
 
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 59d6b9b..5cd0193 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -399,6 +399,14 @@ static void drm_fb_helper_dpms(struct fb_info *info, int dpms_mode)
 		return;
 
 	/*
+	 * fbdev->blank can be called from irq context in case of a panic.
+	 * Since we already have our own special panic handler which will
+	 * restore the fbdev console mode completely, just bail out early.
+	 */
+	if (oops_in_progress)
+		return;
+
+	/*
 	 * For each CRTC in this fb, turn the connectors on/off.
 	 */
 	drm_modeset_lock_all(dev);
@@ -1398,7 +1406,7 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper)
 	struct drm_mode_set *modeset;
 	bool *enabled;
 	int width, height;
-	int i, ret;
+	int i;
 
 	DRM_DEBUG_KMS("\n");
 
@@ -1419,16 +1427,23 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper)
 
 	drm_enable_connectors(fb_helper, enabled);
 
-	ret = drm_target_cloned(fb_helper, modes, enabled, width, height);
-	if (!ret) {
-		ret = drm_target_preferred(fb_helper, modes, enabled, width, height);
-		if (!ret)
+	if (!(fb_helper->funcs->initial_config &&
+	      fb_helper->funcs->initial_config(fb_helper, crtcs, modes,
+					       enabled, width, height))) {
+		memset(modes, 0, dev->mode_config.num_connector*sizeof(modes[0]));
+		memset(crtcs, 0, dev->mode_config.num_connector*sizeof(crtcs[0]));
+
+		if (!drm_target_cloned(fb_helper,
+				       modes, enabled, width, height) &&
+		    !drm_target_preferred(fb_helper,
+					  modes, enabled, width, height))
 			DRM_ERROR("Unable to find initial modes\n");
-	}
 
-	DRM_DEBUG_KMS("picking CRTCs for %dx%d config\n", width, height);
+		DRM_DEBUG_KMS("picking CRTCs for %dx%d config\n",
+			      width, height);
 
-	drm_pick_crtcs(fb_helper, crtcs, modes, 0, width, height);
+		drm_pick_crtcs(fb_helper, crtcs, modes, 0, width, height);
+	}
 
 	/* need to set the modesets up here for use later */
 	/* fill out the connector<->crtc mappings into the modesets */
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
index 13fdcd1..429e07d 100644
--- a/drivers/gpu/drm/drm_fops.c
+++ b/drivers/gpu/drm/drm_fops.c
@@ -123,6 +123,7 @@ int drm_open(struct inode *inode, struct file *filp)
 	int retcode = 0;
 	int need_setup = 0;
 	struct address_space *old_mapping;
+	struct address_space *old_imapping;
 
 	minor = idr_find(&drm_minors_idr, minor_id);
 	if (!minor)
@@ -137,6 +138,7 @@ int drm_open(struct inode *inode, struct file *filp)
 	if (!dev->open_count++)
 		need_setup = 1;
 	mutex_lock(&dev->struct_mutex);
+	old_imapping = inode->i_mapping;
 	old_mapping = dev->dev_mapping;
 	if (old_mapping == NULL)
 		dev->dev_mapping = &inode->i_data;
@@ -159,8 +161,8 @@ int drm_open(struct inode *inode, struct file *filp)
 
 err_undo:
 	mutex_lock(&dev->struct_mutex);
-	filp->f_mapping = old_mapping;
-	inode->i_mapping = old_mapping;
+	filp->f_mapping = old_imapping;
+	inode->i_mapping = old_imapping;
 	iput(container_of(dev->dev_mapping, struct inode, i_data));
 	dev->dev_mapping = old_mapping;
 	mutex_unlock(&dev->struct_mutex);
diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c
index 366910d..25d0218 100644
--- a/drivers/gpu/drm/drm_prime.c
+++ b/drivers/gpu/drm/drm_prime.c
@@ -401,21 +401,17 @@ int drm_prime_fd_to_handle_ioctl(struct drm_device *dev, void *data,
 struct sg_table *drm_prime_pages_to_sg(struct page **pages, int nr_pages)
 {
 	struct sg_table *sg = NULL;
-	struct scatterlist *iter;
-	int i;
 	int ret;
 
 	sg = kmalloc(sizeof(struct sg_table), GFP_KERNEL);
 	if (!sg)
 		goto out;
 
-	ret = sg_alloc_table(sg, nr_pages, GFP_KERNEL);
+	ret = sg_alloc_table_from_pages(sg, pages, nr_pages, 0,
+				nr_pages << PAGE_SHIFT, GFP_KERNEL);
 	if (ret)
 		goto out;
 
-	for_each_sg(sg->sgl, iter, nr_pages, i)
-		sg_set_page(iter, pages[i], PAGE_SIZE, 0);
-
 	return sg;
 out:
 	kfree(sg);
diff --git a/drivers/gpu/drm/drm_proc.c b/drivers/gpu/drm/drm_proc.c
index ff5456b..e064318 100644
--- a/drivers/gpu/drm/drm_proc.c
+++ b/drivers/gpu/drm/drm_proc.c
@@ -63,7 +63,7 @@ static struct drm_info_list drm_proc_list[] = {
 
 static int drm_proc_open(struct inode *inode, struct file *file)
 {
-	struct drm_info_node* node = PDE(inode)->data;
+	struct drm_info_node* node = PDE_DATA(inode);
 
 	return single_open(file, node->info_ent->show, node);
 }
diff --git a/drivers/gpu/drm/gma500/oaktrail_hdmi_i2c.c b/drivers/gpu/drm/gma500/oaktrail_hdmi_i2c.c
index 88627e3..1eb86c7 100644
--- a/drivers/gpu/drm/gma500/oaktrail_hdmi_i2c.c
+++ b/drivers/gpu/drm/gma500/oaktrail_hdmi_i2c.c
@@ -319,8 +319,7 @@ void oaktrail_hdmi_i2c_exit(struct pci_dev *dev)
 	struct hdmi_i2c_dev *i2c_dev;
 
 	hdmi_dev = pci_get_drvdata(dev);
-	if (i2c_del_adapter(&oaktrail_hdmi_i2c_adapter))
-		DRM_DEBUG_DRIVER("Failed to delete hdmi-i2c adapter\n");
+	i2c_del_adapter(&oaktrail_hdmi_i2c_adapter);
 
 	i2c_dev = hdmi_dev->i2c_dev;
 	kfree(i2c_dev);
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 7299ea4..be88532 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -772,6 +772,23 @@ static int i915_error_state(struct seq_file *m, void *unused)
 				}
 			}
 		}
+
+		obj = error->ring[i].ctx;
+		if (obj) {
+			seq_printf(m, "%s --- HW Context = 0x%08x\n",
+				   dev_priv->ring[i].name,
+				   obj->gtt_offset);
+			offset = 0;
+			for (elt = 0; elt < PAGE_SIZE/16; elt += 4) {
+				seq_printf(m, "[%04x] %08x %08x %08x %08x\n",
+					   offset,
+					   obj->pages[0][elt],
+					   obj->pages[0][elt+1],
+					   obj->pages[0][elt+2],
+					   obj->pages[0][elt+3]);
+					offset += 16;
+			}
+		}
 	}
 
 	if (error->overlay)
@@ -849,76 +866,42 @@ static const struct file_operations i915_error_state_fops = {
 	.release = i915_error_state_release,
 };
 
-static ssize_t
-i915_next_seqno_read(struct file *filp,
-		 char __user *ubuf,
-		 size_t max,
-		 loff_t *ppos)
+static int
+i915_next_seqno_get(void *data, u64 *val)
 {
-	struct drm_device *dev = filp->private_data;
+	struct drm_device *dev = data;
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	char buf[80];
-	int len;
 	int ret;
 
 	ret = mutex_lock_interruptible(&dev->struct_mutex);
 	if (ret)
 		return ret;
 
-	len = snprintf(buf, sizeof(buf),
-		       "next_seqno :  0x%x\n",
-		       dev_priv->next_seqno);
-
+	*val = dev_priv->next_seqno;
 	mutex_unlock(&dev->struct_mutex);
 
-	if (len > sizeof(buf))
-		len = sizeof(buf);
-
-	return simple_read_from_buffer(ubuf, max, ppos, buf, len);
+	return 0;
 }
 
-static ssize_t
-i915_next_seqno_write(struct file *filp,
-		      const char __user *ubuf,
-		      size_t cnt,
-		      loff_t *ppos)
-{
-	struct drm_device *dev = filp->private_data;
-	char buf[20];
-	u32 val = 1;
+static int
+i915_next_seqno_set(void *data, u64 val)
+{
+	struct drm_device *dev = data;
 	int ret;
 
-	if (cnt > 0) {
-		if (cnt > sizeof(buf) - 1)
-			return -EINVAL;
-
-		if (copy_from_user(buf, ubuf, cnt))
-			return -EFAULT;
-		buf[cnt] = 0;
-
-		ret = kstrtouint(buf, 0, &val);
-		if (ret < 0)
-			return ret;
-	}
-
 	ret = mutex_lock_interruptible(&dev->struct_mutex);
 	if (ret)
 		return ret;
 
 	ret = i915_gem_set_seqno(dev, val);
-
 	mutex_unlock(&dev->struct_mutex);
 
-	return ret ?: cnt;
+	return ret;
 }
 
-static const struct file_operations i915_next_seqno_fops = {
-	.owner = THIS_MODULE,
-	.open = simple_open,
-	.read = i915_next_seqno_read,
-	.write = i915_next_seqno_write,
-	.llseek = default_llseek,
-};
+DEFINE_SIMPLE_ATTRIBUTE(i915_next_seqno_fops,
+			i915_next_seqno_get, i915_next_seqno_set,
+			"next_seqno :  0x%llx\n");
 
 static int i915_rstdby_delays(struct seq_file *m, void *unused)
 {
@@ -1680,105 +1663,51 @@ static int i915_dpio_info(struct seq_file *m, void *data)
 	return 0;
 }
 
-static ssize_t
-i915_wedged_read(struct file *filp,
-		 char __user *ubuf,
-		 size_t max,
-		 loff_t *ppos)
+static int
+i915_wedged_get(void *data, u64 *val)
 {
-	struct drm_device *dev = filp->private_data;
+	struct drm_device *dev = data;
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	char buf[80];
-	int len;
-
-	len = snprintf(buf, sizeof(buf),
-		       "wedged :  %d\n",
-		       atomic_read(&dev_priv->gpu_error.reset_counter));
 
-	if (len > sizeof(buf))
-		len = sizeof(buf);
+	*val = atomic_read(&dev_priv->gpu_error.reset_counter);
 
-	return simple_read_from_buffer(ubuf, max, ppos, buf, len);
+	return 0;
 }
 
-static ssize_t
-i915_wedged_write(struct file *filp,
-		  const char __user *ubuf,
-		  size_t cnt,
-		  loff_t *ppos)
+static int
+i915_wedged_set(void *data, u64 val)
 {
-	struct drm_device *dev = filp->private_data;
-	char buf[20];
-	int val = 1;
-
-	if (cnt > 0) {
-		if (cnt > sizeof(buf) - 1)
-			return -EINVAL;
-
-		if (copy_from_user(buf, ubuf, cnt))
-			return -EFAULT;
-		buf[cnt] = 0;
+	struct drm_device *dev = data;
 
-		val = simple_strtoul(buf, NULL, 0);
-	}
-
-	DRM_INFO("Manually setting wedged to %d\n", val);
+	DRM_INFO("Manually setting wedged to %llu\n", val);
 	i915_handle_error(dev, val);
 
-	return cnt;
+	return 0;
 }
 
-static const struct file_operations i915_wedged_fops = {
-	.owner = THIS_MODULE,
-	.open = simple_open,
-	.read = i915_wedged_read,
-	.write = i915_wedged_write,
-	.llseek = default_llseek,
-};
+DEFINE_SIMPLE_ATTRIBUTE(i915_wedged_fops,
+			i915_wedged_get, i915_wedged_set,
+			"wedged :  %llu\n");
 
-static ssize_t
-i915_ring_stop_read(struct file *filp,
-		    char __user *ubuf,
-		    size_t max,
-		    loff_t *ppos)
+static int
+i915_ring_stop_get(void *data, u64 *val)
 {
-	struct drm_device *dev = filp->private_data;
+	struct drm_device *dev = data;
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	char buf[20];
-	int len;
-
-	len = snprintf(buf, sizeof(buf),
-		       "0x%08x\n", dev_priv->gpu_error.stop_rings);
 
-	if (len > sizeof(buf))
-		len = sizeof(buf);
+	*val = dev_priv->gpu_error.stop_rings;
 
-	return simple_read_from_buffer(ubuf, max, ppos, buf, len);
+	return 0;
 }
 
-static ssize_t
-i915_ring_stop_write(struct file *filp,
-		     const char __user *ubuf,
-		     size_t cnt,
-		     loff_t *ppos)
+static int
+i915_ring_stop_set(void *data, u64 val)
 {
-	struct drm_device *dev = filp->private_data;
+	struct drm_device *dev = data;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	char buf[20];
-	int val = 0, ret;
-
-	if (cnt > 0) {
-		if (cnt > sizeof(buf) - 1)
-			return -EINVAL;
-
-		if (copy_from_user(buf, ubuf, cnt))
-			return -EFAULT;
-		buf[cnt] = 0;
-
-		val = simple_strtoul(buf, NULL, 0);
-	}
+	int ret;
 
-	DRM_DEBUG_DRIVER("Stopping rings 0x%08x\n", val);
+	DRM_DEBUG_DRIVER("Stopping rings 0x%08llx\n", val);
 
 	ret = mutex_lock_interruptible(&dev->struct_mutex);
 	if (ret)
@@ -1787,16 +1716,12 @@ i915_ring_stop_write(struct file *filp,
 	dev_priv->gpu_error.stop_rings = val;
 	mutex_unlock(&dev->struct_mutex);
 
-	return cnt;
+	return 0;
 }
 
-static const struct file_operations i915_ring_stop_fops = {
-	.owner = THIS_MODULE,
-	.open = simple_open,
-	.read = i915_ring_stop_read,
-	.write = i915_ring_stop_write,
-	.llseek = default_llseek,
-};
+DEFINE_SIMPLE_ATTRIBUTE(i915_ring_stop_fops,
+			i915_ring_stop_get, i915_ring_stop_set,
+			"0x%08llx\n");
 
 #define DROP_UNBOUND 0x1
 #define DROP_BOUND 0x2
@@ -1806,46 +1731,23 @@ static const struct file_operations i915_ring_stop_fops = {
 		  DROP_BOUND | \
 		  DROP_RETIRE | \
 		  DROP_ACTIVE)
-static ssize_t
-i915_drop_caches_read(struct file *filp,
-		      char __user *ubuf,
-		      size_t max,
-		      loff_t *ppos)
+static int
+i915_drop_caches_get(void *data, u64 *val)
 {
-	char buf[20];
-	int len;
-
-	len = snprintf(buf, sizeof(buf), "0x%08x\n", DROP_ALL);
-	if (len > sizeof(buf))
-		len = sizeof(buf);
+	*val = DROP_ALL;
 
-	return simple_read_from_buffer(ubuf, max, ppos, buf, len);
+	return 0;
 }
 
-static ssize_t
-i915_drop_caches_write(struct file *filp,
-		       const char __user *ubuf,
-		       size_t cnt,
-		       loff_t *ppos)
+static int
+i915_drop_caches_set(void *data, u64 val)
 {
-	struct drm_device *dev = filp->private_data;
+	struct drm_device *dev = data;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_i915_gem_object *obj, *next;
-	char buf[20];
-	int val = 0, ret;
-
-	if (cnt > 0) {
-		if (cnt > sizeof(buf) - 1)
-			return -EINVAL;
-
-		if (copy_from_user(buf, ubuf, cnt))
-			return -EFAULT;
-		buf[cnt] = 0;
-
-		val = simple_strtoul(buf, NULL, 0);
-	}
+	int ret;
 
-	DRM_DEBUG_DRIVER("Dropping caches: 0x%08x\n", val);
+	DRM_DEBUG_DRIVER("Dropping caches: 0x%08llx\n", val);
 
 	/* No need to check and wait for gpu resets, only libdrm auto-restarts
 	 * on ioctls on -EAGAIN. */
@@ -1883,27 +1785,19 @@ i915_drop_caches_write(struct file *filp,
 unlock:
 	mutex_unlock(&dev->struct_mutex);
 
-	return ret ?: cnt;
+	return ret;
 }
 
-static const struct file_operations i915_drop_caches_fops = {
-	.owner = THIS_MODULE,
-	.open = simple_open,
-	.read = i915_drop_caches_read,
-	.write = i915_drop_caches_write,
-	.llseek = default_llseek,
-};
+DEFINE_SIMPLE_ATTRIBUTE(i915_drop_caches_fops,
+			i915_drop_caches_get, i915_drop_caches_set,
+			"0x%08llx\n");
 
-static ssize_t
-i915_max_freq_read(struct file *filp,
-		   char __user *ubuf,
-		   size_t max,
-		   loff_t *ppos)
+static int
+i915_max_freq_get(void *data, u64 *val)
 {
-	struct drm_device *dev = filp->private_data;
+	struct drm_device *dev = data;
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	char buf[80];
-	int len, ret;
+	int ret;
 
 	if (!(IS_GEN6(dev) || IS_GEN7(dev)))
 		return -ENODEV;
@@ -1912,42 +1806,23 @@ i915_max_freq_read(struct file *filp,
 	if (ret)
 		return ret;
 
-	len = snprintf(buf, sizeof(buf),
-		       "max freq: %d\n", dev_priv->rps.max_delay * GT_FREQUENCY_MULTIPLIER);
+	*val = dev_priv->rps.max_delay * GT_FREQUENCY_MULTIPLIER;
 	mutex_unlock(&dev_priv->rps.hw_lock);
 
-	if (len > sizeof(buf))
-		len = sizeof(buf);
-
-	return simple_read_from_buffer(ubuf, max, ppos, buf, len);
+	return 0;
 }
 
-static ssize_t
-i915_max_freq_write(struct file *filp,
-		  const char __user *ubuf,
-		  size_t cnt,
-		  loff_t *ppos)
+static int
+i915_max_freq_set(void *data, u64 val)
 {
-	struct drm_device *dev = filp->private_data;
+	struct drm_device *dev = data;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	char buf[20];
-	int val = 1, ret;
+	int ret;
 
 	if (!(IS_GEN6(dev) || IS_GEN7(dev)))
 		return -ENODEV;
 
-	if (cnt > 0) {
-		if (cnt > sizeof(buf) - 1)
-			return -EINVAL;
-
-		if (copy_from_user(buf, ubuf, cnt))
-			return -EFAULT;
-		buf[cnt] = 0;
-
-		val = simple_strtoul(buf, NULL, 0);
-	}
-
-	DRM_DEBUG_DRIVER("Manually setting max freq to %d\n", val);
+	DRM_DEBUG_DRIVER("Manually setting max freq to %llu\n", val);
 
 	ret = mutex_lock_interruptible(&dev_priv->rps.hw_lock);
 	if (ret)
@@ -1956,30 +1831,24 @@ i915_max_freq_write(struct file *filp,
 	/*
 	 * Turbo will still be enabled, but won't go above the set value.
 	 */
-	dev_priv->rps.max_delay = val / GT_FREQUENCY_MULTIPLIER;
-
-	gen6_set_rps(dev, val / GT_FREQUENCY_MULTIPLIER);
+	do_div(val, GT_FREQUENCY_MULTIPLIER);
+	dev_priv->rps.max_delay = val;
+	gen6_set_rps(dev, val);
 	mutex_unlock(&dev_priv->rps.hw_lock);
 
-	return cnt;
+	return 0;
 }
 
-static const struct file_operations i915_max_freq_fops = {
-	.owner = THIS_MODULE,
-	.open = simple_open,
-	.read = i915_max_freq_read,
-	.write = i915_max_freq_write,
-	.llseek = default_llseek,
-};
+DEFINE_SIMPLE_ATTRIBUTE(i915_max_freq_fops,
+			i915_max_freq_get, i915_max_freq_set,
+			"max freq: %llu\n");
 
-static ssize_t
-i915_min_freq_read(struct file *filp, char __user *ubuf, size_t max,
-		   loff_t *ppos)
+static int
+i915_min_freq_get(void *data, u64 *val)
 {
-	struct drm_device *dev = filp->private_data;
+	struct drm_device *dev = data;
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	char buf[80];
-	int len, ret;
+	int ret;
 
 	if (!(IS_GEN6(dev) || IS_GEN7(dev)))
 		return -ENODEV;
@@ -1988,40 +1857,23 @@ i915_min_freq_read(struct file *filp, char __user *ubuf, size_t max,
 	if (ret)
 		return ret;
 
-	len = snprintf(buf, sizeof(buf),
-		       "min freq: %d\n", dev_priv->rps.min_delay * GT_FREQUENCY_MULTIPLIER);
+	*val = dev_priv->rps.min_delay * GT_FREQUENCY_MULTIPLIER;
 	mutex_unlock(&dev_priv->rps.hw_lock);
 
-	if (len > sizeof(buf))
-		len = sizeof(buf);
-
-	return simple_read_from_buffer(ubuf, max, ppos, buf, len);
+	return 0;
 }
 
-static ssize_t
-i915_min_freq_write(struct file *filp, const char __user *ubuf, size_t cnt,
-		    loff_t *ppos)
+static int
+i915_min_freq_set(void *data, u64 val)
 {
-	struct drm_device *dev = filp->private_data;
+	struct drm_device *dev = data;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	char buf[20];
-	int val = 1, ret;
+	int ret;
 
 	if (!(IS_GEN6(dev) || IS_GEN7(dev)))
 		return -ENODEV;
 
-	if (cnt > 0) {
-		if (cnt > sizeof(buf) - 1)
-			return -EINVAL;
-
-		if (copy_from_user(buf, ubuf, cnt))
-			return -EFAULT;
-		buf[cnt] = 0;
-
-		val = simple_strtoul(buf, NULL, 0);
-	}
-
-	DRM_DEBUG_DRIVER("Manually setting min freq to %d\n", val);
+	DRM_DEBUG_DRIVER("Manually setting min freq to %llu\n", val);
 
 	ret = mutex_lock_interruptible(&dev_priv->rps.hw_lock);
 	if (ret)
@@ -2030,33 +1882,25 @@ i915_min_freq_write(struct file *filp, const char __user *ubuf, size_t cnt,
 	/*
 	 * Turbo will still be enabled, but won't go below the set value.
 	 */
-	dev_priv->rps.min_delay = val / GT_FREQUENCY_MULTIPLIER;
-
-	gen6_set_rps(dev, val / GT_FREQUENCY_MULTIPLIER);
+	do_div(val, GT_FREQUENCY_MULTIPLIER);
+	dev_priv->rps.min_delay = val;
+	gen6_set_rps(dev, val);
 	mutex_unlock(&dev_priv->rps.hw_lock);
 
-	return cnt;
+	return 0;
 }
 
-static const struct file_operations i915_min_freq_fops = {
-	.owner = THIS_MODULE,
-	.open = simple_open,
-	.read = i915_min_freq_read,
-	.write = i915_min_freq_write,
-	.llseek = default_llseek,
-};
+DEFINE_SIMPLE_ATTRIBUTE(i915_min_freq_fops,
+			i915_min_freq_get, i915_min_freq_set,
+			"min freq: %llu\n");
 
-static ssize_t
-i915_cache_sharing_read(struct file *filp,
-		   char __user *ubuf,
-		   size_t max,
-		   loff_t *ppos)
+static int
+i915_cache_sharing_get(void *data, u64 *val)
 {
-	struct drm_device *dev = filp->private_data;
+	struct drm_device *dev = data;
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	char buf[80];
 	u32 snpcr;
-	int len, ret;
+	int ret;
 
 	if (!(IS_GEN6(dev) || IS_GEN7(dev)))
 		return -ENODEV;
@@ -2068,46 +1912,25 @@ i915_cache_sharing_read(struct file *filp,
 	snpcr = I915_READ(GEN6_MBCUNIT_SNPCR);
 	mutex_unlock(&dev_priv->dev->struct_mutex);
 
-	len = snprintf(buf, sizeof(buf),
-		       "%d\n", (snpcr & GEN6_MBC_SNPCR_MASK) >>
-		       GEN6_MBC_SNPCR_SHIFT);
+	*val = (snpcr & GEN6_MBC_SNPCR_MASK) >> GEN6_MBC_SNPCR_SHIFT;
 
-	if (len > sizeof(buf))
-		len = sizeof(buf);
-
-	return simple_read_from_buffer(ubuf, max, ppos, buf, len);
+	return 0;
 }
 
-static ssize_t
-i915_cache_sharing_write(struct file *filp,
-		  const char __user *ubuf,
-		  size_t cnt,
-		  loff_t *ppos)
+static int
+i915_cache_sharing_set(void *data, u64 val)
 {
-	struct drm_device *dev = filp->private_data;
+	struct drm_device *dev = data;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	char buf[20];
 	u32 snpcr;
-	int val = 1;
 
 	if (!(IS_GEN6(dev) || IS_GEN7(dev)))
 		return -ENODEV;
 
-	if (cnt > 0) {
-		if (cnt > sizeof(buf) - 1)
-			return -EINVAL;
-
-		if (copy_from_user(buf, ubuf, cnt))
-			return -EFAULT;
-		buf[cnt] = 0;
-
-		val = simple_strtoul(buf, NULL, 0);
-	}
-
-	if (val < 0 || val > 3)
+	if (val > 3)
 		return -EINVAL;
 
-	DRM_DEBUG_DRIVER("Manually setting uncore sharing to %d\n", val);
+	DRM_DEBUG_DRIVER("Manually setting uncore sharing to %llu\n", val);
 
 	/* Update the cache sharing policy here as well */
 	snpcr = I915_READ(GEN6_MBCUNIT_SNPCR);
@@ -2115,16 +1938,12 @@ i915_cache_sharing_write(struct file *filp,
 	snpcr |= (val << GEN6_MBC_SNPCR_SHIFT);
 	I915_WRITE(GEN6_MBCUNIT_SNPCR, snpcr);
 
-	return cnt;
+	return 0;
 }
 
-static const struct file_operations i915_cache_sharing_fops = {
-	.owner = THIS_MODULE,
-	.open = simple_open,
-	.read = i915_cache_sharing_read,
-	.write = i915_cache_sharing_write,
-	.llseek = default_llseek,
-};
+DEFINE_SIMPLE_ATTRIBUTE(i915_cache_sharing_fops,
+			i915_cache_sharing_get, i915_cache_sharing_set,
+			"%llu\n");
 
 /* As the drm_debugfs_init() routines are called before dev->dev_private is
  * allocated we need to hook into the minor for release. */
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 4fa6beb..4be58e3 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1453,6 +1453,22 @@ static void i915_dump_device_info(struct drm_i915_private *dev_priv)
 }
 
 /**
+ * intel_early_sanitize_regs - clean up BIOS state
+ * @dev: DRM device
+ *
+ * This function must be called before we do any I915_READ or I915_WRITE. Its
+ * purpose is to clean up any state left by the BIOS that may affect us when
+ * reading and/or writing registers.
+ */
+static void intel_early_sanitize_regs(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	if (IS_HASWELL(dev))
+		I915_WRITE_NOTRACE(FPGA_DBG, FPGA_DBG_RM_NOCLAIM);
+}
+
+/**
  * i915_driver_load - setup chip and create an initial config
  * @dev: DRM device
  * @flags: startup flags
@@ -1542,6 +1558,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 		goto put_gmch;
 	}
 
+	intel_early_sanitize_regs(dev);
+
 	aperture_size = dev_priv->gtt.mappable_end;
 
 	dev_priv->gtt.mappable =
@@ -1612,14 +1630,11 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 	mutex_init(&dev_priv->rps.hw_lock);
 	mutex_init(&dev_priv->modeset_restore_lock);
 
-	if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev))
-		dev_priv->num_pipe = 3;
-	else if (IS_MOBILE(dev) || !IS_GEN2(dev))
-		dev_priv->num_pipe = 2;
-	else
-		dev_priv->num_pipe = 1;
+	dev_priv->num_plane = 1;
+	if (IS_VALLEYVIEW(dev))
+		dev_priv->num_plane = 2;
 
-	ret = drm_vblank_init(dev, dev_priv->num_pipe);
+	ret = drm_vblank_init(dev, INTEL_INFO(dev)->num_pipes);
 	if (ret)
 		goto out_gem_unload;
 
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index e9b5789..a5b8aa9 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -121,9 +121,7 @@ MODULE_PARM_DESC(i915_enable_ppgtt,
 unsigned int i915_preliminary_hw_support __read_mostly = 0;
 module_param_named(preliminary_hw_support, i915_preliminary_hw_support, int, 0600);
 MODULE_PARM_DESC(preliminary_hw_support,
-		"Enable preliminary hardware support. "
-		"Enable Haswell and ValleyView Support. "
-		"(default: false)");
+		"Enable preliminary hardware support. (default: false)");
 
 int i915_disable_power_well __read_mostly = 0;
 module_param_named(disable_power_well, i915_disable_power_well, int, 0600);
@@ -143,74 +141,74 @@ extern int intel_agp_enabled;
 	.driver_data = (unsigned long) info }
 
 static const struct intel_device_info intel_i830_info = {
-	.gen = 2, .is_mobile = 1, .cursor_needs_physical = 1,
+	.gen = 2, .is_mobile = 1, .cursor_needs_physical = 1, .num_pipes = 2,
 	.has_overlay = 1, .overlay_needs_physical = 1,
 };
 
 static const struct intel_device_info intel_845g_info = {
-	.gen = 2,
+	.gen = 2, .num_pipes = 1,
 	.has_overlay = 1, .overlay_needs_physical = 1,
 };
 
 static const struct intel_device_info intel_i85x_info = {
-	.gen = 2, .is_i85x = 1, .is_mobile = 1,
+	.gen = 2, .is_i85x = 1, .is_mobile = 1, .num_pipes = 2,
 	.cursor_needs_physical = 1,
 	.has_overlay = 1, .overlay_needs_physical = 1,
 };
 
 static const struct intel_device_info intel_i865g_info = {
-	.gen = 2,
+	.gen = 2, .num_pipes = 1,
 	.has_overlay = 1, .overlay_needs_physical = 1,
 };
 
 static const struct intel_device_info intel_i915g_info = {
-	.gen = 3, .is_i915g = 1, .cursor_needs_physical = 1,
+	.gen = 3, .is_i915g = 1, .cursor_needs_physical = 1, .num_pipes = 2,
 	.has_overlay = 1, .overlay_needs_physical = 1,
 };
 static const struct intel_device_info intel_i915gm_info = {
-	.gen = 3, .is_mobile = 1,
+	.gen = 3, .is_mobile = 1, .num_pipes = 2,
 	.cursor_needs_physical = 1,
 	.has_overlay = 1, .overlay_needs_physical = 1,
 	.supports_tv = 1,
 };
 static const struct intel_device_info intel_i945g_info = {
-	.gen = 3, .has_hotplug = 1, .cursor_needs_physical = 1,
+	.gen = 3, .has_hotplug = 1, .cursor_needs_physical = 1, .num_pipes = 2,
 	.has_overlay = 1, .overlay_needs_physical = 1,
 };
 static const struct intel_device_info intel_i945gm_info = {
-	.gen = 3, .is_i945gm = 1, .is_mobile = 1,
+	.gen = 3, .is_i945gm = 1, .is_mobile = 1, .num_pipes = 2,
 	.has_hotplug = 1, .cursor_needs_physical = 1,
 	.has_overlay = 1, .overlay_needs_physical = 1,
 	.supports_tv = 1,
 };
 
 static const struct intel_device_info intel_i965g_info = {
-	.gen = 4, .is_broadwater = 1,
+	.gen = 4, .is_broadwater = 1, .num_pipes = 2,
 	.has_hotplug = 1,
 	.has_overlay = 1,
 };
 
 static const struct intel_device_info intel_i965gm_info = {
-	.gen = 4, .is_crestline = 1,
+	.gen = 4, .is_crestline = 1, .num_pipes = 2,
 	.is_mobile = 1, .has_fbc = 1, .has_hotplug = 1,
 	.has_overlay = 1,
 	.supports_tv = 1,
 };
 
 static const struct intel_device_info intel_g33_info = {
-	.gen = 3, .is_g33 = 1,
+	.gen = 3, .is_g33 = 1, .num_pipes = 2,
 	.need_gfx_hws = 1, .has_hotplug = 1,
 	.has_overlay = 1,
 };
 
 static const struct intel_device_info intel_g45_info = {
-	.gen = 4, .is_g4x = 1, .need_gfx_hws = 1,
+	.gen = 4, .is_g4x = 1, .need_gfx_hws = 1, .num_pipes = 2,
 	.has_pipe_cxsr = 1, .has_hotplug = 1,
 	.has_bsd_ring = 1,
 };
 
 static const struct intel_device_info intel_gm45_info = {
-	.gen = 4, .is_g4x = 1,
+	.gen = 4, .is_g4x = 1, .num_pipes = 2,
 	.is_mobile = 1, .need_gfx_hws = 1, .has_fbc = 1,
 	.has_pipe_cxsr = 1, .has_hotplug = 1,
 	.supports_tv = 1,
@@ -218,26 +216,26 @@ static const struct intel_device_info intel_gm45_info = {
 };
 
 static const struct intel_device_info intel_pineview_info = {
-	.gen = 3, .is_g33 = 1, .is_pineview = 1, .is_mobile = 1,
+	.gen = 3, .is_g33 = 1, .is_pineview = 1, .is_mobile = 1, .num_pipes = 2,
 	.need_gfx_hws = 1, .has_hotplug = 1,
 	.has_overlay = 1,
 };
 
 static const struct intel_device_info intel_ironlake_d_info = {
-	.gen = 5,
+	.gen = 5, .num_pipes = 2,
 	.need_gfx_hws = 1, .has_hotplug = 1,
 	.has_bsd_ring = 1,
 };
 
 static const struct intel_device_info intel_ironlake_m_info = {
-	.gen = 5, .is_mobile = 1,
+	.gen = 5, .is_mobile = 1, .num_pipes = 2,
 	.need_gfx_hws = 1, .has_hotplug = 1,
 	.has_fbc = 1,
 	.has_bsd_ring = 1,
 };
 
 static const struct intel_device_info intel_sandybridge_d_info = {
-	.gen = 6,
+	.gen = 6, .num_pipes = 2,
 	.need_gfx_hws = 1, .has_hotplug = 1,
 	.has_bsd_ring = 1,
 	.has_blt_ring = 1,
@@ -246,7 +244,7 @@ static const struct intel_device_info intel_sandybridge_d_info = {
 };
 
 static const struct intel_device_info intel_sandybridge_m_info = {
-	.gen = 6, .is_mobile = 1,
+	.gen = 6, .is_mobile = 1, .num_pipes = 2,
 	.need_gfx_hws = 1, .has_hotplug = 1,
 	.has_fbc = 1,
 	.has_bsd_ring = 1,
@@ -255,61 +253,49 @@ static const struct intel_device_info intel_sandybridge_m_info = {
 	.has_force_wake = 1,
 };
 
+#define GEN7_FEATURES  \
+	.gen = 7, .num_pipes = 3, \
+	.need_gfx_hws = 1, .has_hotplug = 1, \
+	.has_bsd_ring = 1, \
+	.has_blt_ring = 1, \
+	.has_llc = 1, \
+	.has_force_wake = 1
+
 static const struct intel_device_info intel_ivybridge_d_info = {
-	.is_ivybridge = 1, .gen = 7,
-	.need_gfx_hws = 1, .has_hotplug = 1,
-	.has_bsd_ring = 1,
-	.has_blt_ring = 1,
-	.has_llc = 1,
-	.has_force_wake = 1,
+	GEN7_FEATURES,
+	.is_ivybridge = 1,
 };
 
 static const struct intel_device_info intel_ivybridge_m_info = {
-	.is_ivybridge = 1, .gen = 7, .is_mobile = 1,
-	.need_gfx_hws = 1, .has_hotplug = 1,
-	.has_fbc = 0,	/* FBC is not enabled on Ivybridge mobile yet */
-	.has_bsd_ring = 1,
-	.has_blt_ring = 1,
-	.has_llc = 1,
-	.has_force_wake = 1,
+	GEN7_FEATURES,
+	.is_ivybridge = 1,
+	.is_mobile = 1,
 };
 
 static const struct intel_device_info intel_valleyview_m_info = {
-	.gen = 7, .is_mobile = 1,
-	.need_gfx_hws = 1, .has_hotplug = 1,
-	.has_fbc = 0,
-	.has_bsd_ring = 1,
-	.has_blt_ring = 1,
+	GEN7_FEATURES,
+	.is_mobile = 1,
+	.num_pipes = 2,
 	.is_valleyview = 1,
 	.display_mmio_offset = VLV_DISPLAY_BASE,
 };
 
 static const struct intel_device_info intel_valleyview_d_info = {
-	.gen = 7,
-	.need_gfx_hws = 1, .has_hotplug = 1,
-	.has_fbc = 0,
-	.has_bsd_ring = 1,
-	.has_blt_ring = 1,
+	GEN7_FEATURES,
+	.num_pipes = 2,
 	.is_valleyview = 1,
 	.display_mmio_offset = VLV_DISPLAY_BASE,
 };
 
 static const struct intel_device_info intel_haswell_d_info = {
-	.is_haswell = 1, .gen = 7,
-	.need_gfx_hws = 1, .has_hotplug = 1,
-	.has_bsd_ring = 1,
-	.has_blt_ring = 1,
-	.has_llc = 1,
-	.has_force_wake = 1,
+	GEN7_FEATURES,
+	.is_haswell = 1,
 };
 
 static const struct intel_device_info intel_haswell_m_info = {
-	.is_haswell = 1, .gen = 7, .is_mobile = 1,
-	.need_gfx_hws = 1, .has_hotplug = 1,
-	.has_bsd_ring = 1,
-	.has_blt_ring = 1,
-	.has_llc = 1,
-	.has_force_wake = 1,
+	GEN7_FEATURES,
+	.is_haswell = 1,
+	.is_mobile = 1,
 };
 
 static const struct pci_device_id pciidlist[] = {		/* aka */
@@ -394,6 +380,9 @@ static const struct pci_device_id pciidlist[] = {		/* aka */
 	INTEL_VGA_DEVICE(0x0D16, &intel_haswell_m_info), /* CRW GT2 mobile */
 	INTEL_VGA_DEVICE(0x0D26, &intel_haswell_m_info), /* CRW GT2 mobile */
 	INTEL_VGA_DEVICE(0x0f30, &intel_valleyview_m_info),
+	INTEL_VGA_DEVICE(0x0f31, &intel_valleyview_m_info),
+	INTEL_VGA_DEVICE(0x0f32, &intel_valleyview_m_info),
+	INTEL_VGA_DEVICE(0x0f33, &intel_valleyview_m_info),
 	INTEL_VGA_DEVICE(0x0157, &intel_valleyview_m_info),
 	INTEL_VGA_DEVICE(0x0155, &intel_valleyview_d_info),
 	{0, 0, 0}
@@ -474,6 +463,7 @@ bool i915_semaphore_is_enabled(struct drm_device *dev)
 static int i915_drm_freeze(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_crtc *crtc;
 
 	/* ignore lid events during suspend */
 	mutex_lock(&dev_priv->modeset_restore_lock);
@@ -497,10 +487,14 @@ static int i915_drm_freeze(struct drm_device *dev)
 
 		cancel_delayed_work_sync(&dev_priv->rps.delayed_resume_work);
 
-		intel_modeset_disable(dev);
-
 		drm_irq_uninstall(dev);
 		dev_priv->enable_hotplug_processing = false;
+		/*
+		 * Disable CRTCs directly since we want to preserve sw state
+		 * for _thaw.
+		 */
+		list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
+			dev_priv->display.crtc_disable(crtc);
 	}
 
 	i915_save_state(dev);
@@ -556,6 +550,24 @@ void intel_console_resume(struct work_struct *work)
 	console_unlock();
 }
 
+static void intel_resume_hotplug(struct drm_device *dev)
+{
+	struct drm_mode_config *mode_config = &dev->mode_config;
+	struct intel_encoder *encoder;
+
+	mutex_lock(&mode_config->mutex);
+	DRM_DEBUG_KMS("running encoder hotplug functions\n");
+
+	list_for_each_entry(encoder, &mode_config->encoder_list, base.head)
+		if (encoder->hot_plug)
+			encoder->hot_plug(encoder);
+
+	mutex_unlock(&mode_config->mutex);
+
+	/* Just fire off a uevent and let userspace tell us what to do */
+	drm_helper_hpd_irq_event(dev);
+}
+
 static int __i915_drm_thaw(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -578,7 +590,10 @@ static int __i915_drm_thaw(struct drm_device *dev)
 		drm_irq_install(dev);
 
 		intel_modeset_init_hw(dev);
-		intel_modeset_setup_hw_state(dev, false);
+
+		drm_modeset_lock_all(dev);
+		intel_modeset_setup_hw_state(dev, true);
+		drm_modeset_unlock_all(dev);
 
 		/*
 		 * ... but also need to make sure that hotplug processing
@@ -588,6 +603,8 @@ static int __i915_drm_thaw(struct drm_device *dev)
 		 * */
 		intel_hpd_init(dev);
 		dev_priv->enable_hotplug_processing = true;
+		/* Config may have changed between suspend and resume */
+		intel_resume_hotplug(dev);
 	}
 
 	intel_opregion_init(dev);
@@ -732,6 +749,7 @@ static int ironlake_do_reset(struct drm_device *dev)
 	int ret;
 
 	gdrst = I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR);
+	gdrst &= ~GRDOM_MASK;
 	I915_WRITE(MCHBAR_MIRROR_BASE + ILK_GDSR,
 		   gdrst | GRDOM_RENDER | GRDOM_RESET_ENABLE);
 	ret = wait_for(I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR) & 0x1, 500);
@@ -740,6 +758,7 @@ static int ironlake_do_reset(struct drm_device *dev)
 
 	/* We can't reset render&media without also resetting display ... */
 	gdrst = I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR);
+	gdrst &= ~GRDOM_MASK;
 	I915_WRITE(MCHBAR_MIRROR_BASE + ILK_GDSR,
 		   gdrst | GRDOM_MEDIA | GRDOM_RESET_ENABLE);
 	return wait_for(I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR) & 0x1, 500);
@@ -1147,6 +1166,27 @@ ilk_dummy_write(struct drm_i915_private *dev_priv)
 	I915_WRITE_NOTRACE(MI_MODE, 0);
 }
 
+static void
+hsw_unclaimed_reg_clear(struct drm_i915_private *dev_priv, u32 reg)
+{
+	if (IS_HASWELL(dev_priv->dev) &&
+	    (I915_READ_NOTRACE(FPGA_DBG) & FPGA_DBG_RM_NOCLAIM)) {
+		DRM_ERROR("Unknown unclaimed register before writing to %x\n",
+			  reg);
+		I915_WRITE_NOTRACE(FPGA_DBG, FPGA_DBG_RM_NOCLAIM);
+	}
+}
+
+static void
+hsw_unclaimed_reg_check(struct drm_i915_private *dev_priv, u32 reg)
+{
+	if (IS_HASWELL(dev_priv->dev) &&
+	    (I915_READ_NOTRACE(FPGA_DBG) & FPGA_DBG_RM_NOCLAIM)) {
+		DRM_ERROR("Unclaimed write to %x\n", reg);
+		I915_WRITE_NOTRACE(FPGA_DBG, FPGA_DBG_RM_NOCLAIM);
+	}
+}
+
 #define __i915_read(x, y) \
 u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \
 	u##x val = 0; \
@@ -1183,18 +1223,12 @@ void i915_write##x(struct drm_i915_private *dev_priv, u32 reg, u##x val) { \
 	} \
 	if (IS_GEN5(dev_priv->dev)) \
 		ilk_dummy_write(dev_priv); \
-	if (IS_HASWELL(dev_priv->dev) && (I915_READ_NOTRACE(GEN7_ERR_INT) & ERR_INT_MMIO_UNCLAIMED)) { \
-		DRM_ERROR("Unknown unclaimed register before writing to %x\n", reg); \
-		I915_WRITE_NOTRACE(GEN7_ERR_INT, ERR_INT_MMIO_UNCLAIMED); \
-	} \
+	hsw_unclaimed_reg_clear(dev_priv, reg); \
 	write##y(val, dev_priv->regs + reg); \
 	if (unlikely(__fifo_ret)) { \
 		gen6_gt_check_fifodbg(dev_priv); \
 	} \
-	if (IS_HASWELL(dev_priv->dev) && (I915_READ_NOTRACE(GEN7_ERR_INT) & ERR_INT_MMIO_UNCLAIMED)) { \
-		DRM_ERROR("Unclaimed write to %x\n", reg); \
-		writel(ERR_INT_MMIO_UNCLAIMED, dev_priv->regs + GEN7_ERR_INT);	\
-	} \
+	hsw_unclaimed_reg_check(dev_priv, reg); \
 }
 __i915_write(8, b)
 __i915_write(16, w)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 01769e2..44fca0b 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -86,6 +86,19 @@ enum port {
 };
 #define port_name(p) ((p) + 'A')
 
+enum hpd_pin {
+	HPD_NONE = 0,
+	HPD_PORT_A = HPD_NONE, /* PORT_A is internal */
+	HPD_TV = HPD_NONE,     /* TV is known to be unreliable */
+	HPD_CRT,
+	HPD_SDVO_B,
+	HPD_SDVO_C,
+	HPD_PORT_B,
+	HPD_PORT_C,
+	HPD_PORT_D,
+	HPD_NUM_PINS
+};
+
 #define I915_GEM_GPU_DOMAINS \
 	(I915_GEM_DOMAIN_RENDER | \
 	 I915_GEM_DOMAIN_SAMPLER | \
@@ -93,7 +106,7 @@ enum port {
 	 I915_GEM_DOMAIN_INSTRUCTION | \
 	 I915_GEM_DOMAIN_VERTEX)
 
-#define for_each_pipe(p) for ((p) = 0; (p) < dev_priv->num_pipe; (p)++)
+#define for_each_pipe(p) for ((p) = 0; (p) < INTEL_INFO(dev)->num_pipes; (p)++)
 
 #define for_each_encoder_on_crtc(dev, __crtc, intel_encoder) \
 	list_for_each_entry((intel_encoder), &(dev)->mode_config.encoder_list, base.head) \
@@ -243,7 +256,7 @@ struct drm_i915_error_state {
 			int page_count;
 			u32 gtt_offset;
 			u32 *pages[0];
-		} *ringbuffer, *batchbuffer;
+		} *ringbuffer, *batchbuffer, *ctx;
 		struct drm_i915_error_request {
 			long jiffies;
 			u32 seqno;
@@ -271,6 +284,9 @@ struct drm_i915_error_state {
 	struct intel_display_error_state *display;
 };
 
+struct intel_crtc_config;
+struct intel_crtc;
+
 struct drm_i915_display_funcs {
 	bool (*fbc_enabled)(struct drm_device *dev);
 	void (*enable_fbc)(struct drm_crtc *crtc, unsigned long interval);
@@ -283,9 +299,11 @@ struct drm_i915_display_funcs {
 	void (*update_linetime_wm)(struct drm_device *dev, int pipe,
 				 struct drm_display_mode *mode);
 	void (*modeset_global_resources)(struct drm_device *dev);
+	/* Returns the active state of the crtc, and if the crtc is active,
+	 * fills out the pipe-config with the hw state. */
+	bool (*get_pipe_config)(struct intel_crtc *,
+				struct intel_crtc_config *);
 	int (*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);
 	void (*crtc_enable)(struct drm_crtc *crtc);
@@ -341,6 +359,7 @@ struct drm_i915_gt_funcs {
 
 struct intel_device_info {
 	u32 display_mmio_offset;
+	u8 num_pipes:3;
 	u8 gen;
 	u8 is_mobile:1;
 	u8 is_i85x:1;
@@ -905,16 +924,14 @@ typedef struct drm_i915_private {
 	struct mutex dpio_lock;
 
 	/** Cached value of IMR to avoid reads in updating the bitfield */
-	u32 pipestat[2];
 	u32 irq_mask;
 	u32 gt_irq_mask;
 
-	u32 hotplug_supported_mask;
 	struct work_struct hotplug_work;
 	bool enable_hotplug_processing;
 
-	int num_pipe;
 	int num_pch_pll;
+	int num_plane;
 
 	unsigned long cfb_size;
 	unsigned int cfb_fb;
@@ -928,9 +945,14 @@ typedef struct drm_i915_private {
 	struct intel_overlay *overlay;
 	unsigned int sprite_scaling_enabled;
 
+	/* backlight */
+	struct {
+		int level;
+		bool enabled;
+		struct backlight_device *device;
+	} backlight;
+
 	/* LVDS info */
-	int backlight_level;  /* restore backlight to this value */
-	bool backlight_enabled;
 	struct drm_display_mode *lfp_lvds_vbt_mode; /* if any */
 	struct drm_display_mode *sdvo_lvds_vbt_mode; /* if any */
 
@@ -1032,8 +1054,6 @@ typedef struct drm_i915_private {
 	 */
 	struct work_struct console_resume_work;
 
-	struct backlight_device *backlight;
-
 	struct drm_property *broadcast_rgb_property;
 	struct drm_property *force_audio_property;
 
@@ -1340,6 +1360,7 @@ struct drm_i915_file_private {
 #define HAS_PIPE_CONTROL(dev) (INTEL_INFO(dev)->gen >= 5)
 
 #define HAS_DDI(dev)		(IS_HASWELL(dev))
+#define HAS_POWER_WELL(dev)	(IS_HASWELL(dev))
 
 #define INTEL_PCH_DEVICE_ID_MASK		0xff00
 #define INTEL_PCH_IBX_DEVICE_ID_TYPE		0x3b00
@@ -1529,17 +1550,12 @@ void i915_gem_lastclose(struct drm_device *dev);
 int __must_check i915_gem_object_get_pages(struct drm_i915_gem_object *obj);
 static inline struct page *i915_gem_object_get_page(struct drm_i915_gem_object *obj, int n)
 {
-	struct scatterlist *sg = obj->pages->sgl;
-	int nents = obj->pages->nents;
-	while (nents > SG_MAX_SINGLE_ALLOC) {
-		if (n < SG_MAX_SINGLE_ALLOC - 1)
-			break;
-
-		sg = sg_chain_ptr(sg + SG_MAX_SINGLE_ALLOC - 1);
-		n -= SG_MAX_SINGLE_ALLOC - 1;
-		nents -= SG_MAX_SINGLE_ALLOC - 1;
-	}
-	return sg_page(sg+n);
+	struct sg_page_iter sg_iter;
+
+	for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents, n)
+		return sg_page_iter_page(&sg_iter);
+
+	return NULL;
 }
 static inline void i915_gem_object_pin_pages(struct drm_i915_gem_object *obj)
 {
@@ -1718,6 +1734,11 @@ void i915_gem_stolen_cleanup_compression(struct drm_device *dev);
 void i915_gem_cleanup_stolen(struct drm_device *dev);
 struct drm_i915_gem_object *
 i915_gem_object_create_stolen(struct drm_device *dev, u32 size);
+struct drm_i915_gem_object *
+i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev,
+					       u32 stolen_offset,
+					       u32 gtt_offset,
+					       u32 size);
 void i915_gem_object_release_stolen(struct drm_i915_gem_object *obj);
 
 /* i915_gem_tiling.c */
@@ -1848,6 +1869,8 @@ int __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv);
 
 int sandybridge_pcode_read(struct drm_i915_private *dev_priv, u8 mbox, u32 *val);
 int sandybridge_pcode_write(struct drm_i915_private *dev_priv, u8 mbox, u32 val);
+int valleyview_punit_read(struct drm_i915_private *dev_priv, u8 addr, u32 *val);
+int valleyview_punit_write(struct drm_i915_private *dev_priv, u8 addr, u32 val);
 
 #define __i915_read(x, y) \
 	u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg);
@@ -1901,4 +1924,9 @@ static inline uint32_t i915_vgacntrl_reg(struct drm_device *dev)
 		return VGACNTRL;
 }
 
+static inline void __user *to_user_ptr(u64 address)
+{
+	return (void __user *)(uintptr_t)address;
+}
+
 #endif
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 0e207e6..911bd40 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -411,10 +411,9 @@ i915_gem_shmem_pread(struct drm_device *dev,
 	int obj_do_bit17_swizzling, page_do_bit17_swizzling;
 	int prefaulted = 0;
 	int needs_clflush = 0;
-	struct scatterlist *sg;
-	int i;
+	struct sg_page_iter sg_iter;
 
-	user_data = (char __user *) (uintptr_t) args->data_ptr;
+	user_data = to_user_ptr(args->data_ptr);
 	remain = args->size;
 
 	obj_do_bit17_swizzling = i915_gem_object_needs_bit17_swizzle(obj);
@@ -441,11 +440,9 @@ i915_gem_shmem_pread(struct drm_device *dev,
 
 	offset = args->offset;
 
-	for_each_sg(obj->pages->sgl, sg, obj->pages->nents, i) {
-		struct page *page;
-
-		if (i < offset >> PAGE_SHIFT)
-			continue;
+	for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents,
+			 offset >> PAGE_SHIFT) {
+		struct page *page = sg_page_iter_page(&sg_iter);
 
 		if (remain <= 0)
 			break;
@@ -460,7 +457,6 @@ i915_gem_shmem_pread(struct drm_device *dev,
 		if ((shmem_page_offset + page_length) > PAGE_SIZE)
 			page_length = PAGE_SIZE - shmem_page_offset;
 
-		page = sg_page(sg);
 		page_do_bit17_swizzling = obj_do_bit17_swizzling &&
 			(page_to_phys(page) & (1 << 17)) != 0;
 
@@ -522,7 +518,7 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data,
 		return 0;
 
 	if (!access_ok(VERIFY_WRITE,
-		       (char __user *)(uintptr_t)args->data_ptr,
+		       to_user_ptr(args->data_ptr),
 		       args->size))
 		return -EFAULT;
 
@@ -613,7 +609,7 @@ i915_gem_gtt_pwrite_fast(struct drm_device *dev,
 	if (ret)
 		goto out_unpin;
 
-	user_data = (char __user *) (uintptr_t) args->data_ptr;
+	user_data = to_user_ptr(args->data_ptr);
 	remain = args->size;
 
 	offset = obj->gtt_offset + args->offset;
@@ -732,10 +728,9 @@ i915_gem_shmem_pwrite(struct drm_device *dev,
 	int hit_slowpath = 0;
 	int needs_clflush_after = 0;
 	int needs_clflush_before = 0;
-	int i;
-	struct scatterlist *sg;
+	struct sg_page_iter sg_iter;
 
-	user_data = (char __user *) (uintptr_t) args->data_ptr;
+	user_data = to_user_ptr(args->data_ptr);
 	remain = args->size;
 
 	obj_do_bit17_swizzling = i915_gem_object_needs_bit17_swizzle(obj);
@@ -768,13 +763,11 @@ i915_gem_shmem_pwrite(struct drm_device *dev,
 	offset = args->offset;
 	obj->dirty = 1;
 
-	for_each_sg(obj->pages->sgl, sg, obj->pages->nents, i) {
-		struct page *page;
+	for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents,
+			 offset >> PAGE_SHIFT) {
+		struct page *page = sg_page_iter_page(&sg_iter);
 		int partial_cacheline_write;
 
-		if (i < offset >> PAGE_SHIFT)
-			continue;
-
 		if (remain <= 0)
 			break;
 
@@ -796,7 +789,6 @@ i915_gem_shmem_pwrite(struct drm_device *dev,
 			((shmem_page_offset | page_length)
 				& (boot_cpu_data.x86_clflush_size - 1));
 
-		page = sg_page(sg);
 		page_do_bit17_swizzling = obj_do_bit17_swizzling &&
 			(page_to_phys(page) & (1 << 17)) != 0;
 
@@ -867,11 +859,11 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
 		return 0;
 
 	if (!access_ok(VERIFY_READ,
-		       (char __user *)(uintptr_t)args->data_ptr,
+		       to_user_ptr(args->data_ptr),
 		       args->size))
 		return -EFAULT;
 
-	ret = fault_in_multipages_readable((char __user *)(uintptr_t)args->data_ptr,
+	ret = fault_in_multipages_readable(to_user_ptr(args->data_ptr),
 					   args->size);
 	if (ret)
 		return -EFAULT;
@@ -1633,9 +1625,8 @@ i915_gem_object_is_purgeable(struct drm_i915_gem_object *obj)
 static void
 i915_gem_object_put_pages_gtt(struct drm_i915_gem_object *obj)
 {
-	int page_count = obj->base.size / PAGE_SIZE;
-	struct scatterlist *sg;
-	int ret, i;
+	struct sg_page_iter sg_iter;
+	int ret;
 
 	BUG_ON(obj->madv == __I915_MADV_PURGED);
 
@@ -1655,8 +1646,8 @@ i915_gem_object_put_pages_gtt(struct drm_i915_gem_object *obj)
 	if (obj->madv == I915_MADV_DONTNEED)
 		obj->dirty = 0;
 
-	for_each_sg(obj->pages->sgl, sg, page_count, i) {
-		struct page *page = sg_page(sg);
+	for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents, 0) {
+		struct page *page = sg_page_iter_page(&sg_iter);
 
 		if (obj->dirty)
 			set_page_dirty(page);
@@ -1757,7 +1748,9 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
 	struct address_space *mapping;
 	struct sg_table *st;
 	struct scatterlist *sg;
+	struct sg_page_iter sg_iter;
 	struct page *page;
+	unsigned long last_pfn = 0;	/* suppress gcc warning */
 	gfp_t gfp;
 
 	/* Assert that the object is not currently in any GPU domain. As it
@@ -1787,7 +1780,9 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
 	gfp = mapping_gfp_mask(mapping);
 	gfp |= __GFP_NORETRY | __GFP_NOWARN | __GFP_NO_KSWAPD;
 	gfp &= ~(__GFP_IO | __GFP_WAIT);
-	for_each_sg(st->sgl, sg, page_count, i) {
+	sg = st->sgl;
+	st->nents = 0;
+	for (i = 0; i < page_count; i++) {
 		page = shmem_read_mapping_page_gfp(mapping, i, gfp);
 		if (IS_ERR(page)) {
 			i915_gem_purge(dev_priv, page_count);
@@ -1810,9 +1805,18 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
 			gfp &= ~(__GFP_IO | __GFP_WAIT);
 		}
 
-		sg_set_page(sg, page, PAGE_SIZE, 0);
+		if (!i || page_to_pfn(page) != last_pfn + 1) {
+			if (i)
+				sg = sg_next(sg);
+			st->nents++;
+			sg_set_page(sg, page, PAGE_SIZE, 0);
+		} else {
+			sg->length += PAGE_SIZE;
+		}
+		last_pfn = page_to_pfn(page);
 	}
 
+	sg_mark_end(sg);
 	obj->pages = st;
 
 	if (i915_gem_object_needs_bit17_swizzle(obj))
@@ -1821,8 +1825,9 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
 	return 0;
 
 err_pages:
-	for_each_sg(st->sgl, sg, i, page_count)
-		page_cache_release(sg_page(sg));
+	sg_mark_end(sg);
+	for_each_sg_page(st->sgl, &sg_iter, st->nents, 0)
+		page_cache_release(sg_page_iter_page(&sg_iter));
 	sg_free_table(st);
 	kfree(st);
 	return PTR_ERR(page);
@@ -2123,11 +2128,11 @@ static void i915_gem_reset_fences(struct drm_device *dev)
 	for (i = 0; i < dev_priv->num_fence_regs; i++) {
 		struct drm_i915_fence_reg *reg = &dev_priv->fence_regs[i];
 
-		i915_gem_write_fence(dev, i, NULL);
-
 		if (reg->obj)
 			i915_gem_object_fence_lost(reg->obj);
 
+		i915_gem_write_fence(dev, i, NULL);
+
 		reg->pin_count = 0;
 		reg->obj = NULL;
 		INIT_LIST_HEAD(&reg->lru_list);
@@ -2717,6 +2722,7 @@ int
 i915_gem_object_put_fence(struct drm_i915_gem_object *obj)
 {
 	struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
+	struct drm_i915_fence_reg *fence;
 	int ret;
 
 	ret = i915_gem_object_wait_fence(obj);
@@ -2726,10 +2732,10 @@ i915_gem_object_put_fence(struct drm_i915_gem_object *obj)
 	if (obj->fence_reg == I915_FENCE_REG_NONE)
 		return 0;
 
-	i915_gem_object_update_fence(obj,
-				     &dev_priv->fence_regs[obj->fence_reg],
-				     false);
+	fence = &dev_priv->fence_regs[obj->fence_reg];
+
 	i915_gem_object_fence_lost(obj);
+	i915_gem_object_update_fence(obj, fence, false);
 
 	return 0;
 }
@@ -4010,7 +4016,16 @@ int i915_gem_init(struct drm_device *dev)
 	int ret;
 
 	mutex_lock(&dev->struct_mutex);
+
+	if (IS_VALLEYVIEW(dev)) {
+		/* VLVA0 (potential hack), BIOS isn't actually waking us */
+		I915_WRITE(VLV_GTLC_WAKE_CTRL, 1);
+		if (wait_for((I915_READ(VLV_GTLC_PW_STATUS) & 1) == 1, 10))
+			DRM_DEBUG_DRIVER("allow wake ack timed out\n");
+	}
+
 	i915_gem_init_global_gtt(dev);
+
 	ret = i915_gem_init_hw(dev);
 	mutex_unlock(&dev->struct_mutex);
 	if (ret) {
@@ -4327,7 +4342,7 @@ i915_gem_phys_pwrite(struct drm_device *dev,
 		     struct drm_file *file_priv)
 {
 	void *vaddr = obj->phys_obj->handle->vaddr + args->offset;
-	char __user *user_data = (char __user *) (uintptr_t) args->data_ptr;
+	char __user *user_data = to_user_ptr(args->data_ptr);
 
 	if (__copy_from_user_inatomic_nocache(vaddr, user_data, args->size)) {
 		unsigned long unwritten;
diff --git a/drivers/gpu/drm/i915/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/i915_gem_dmabuf.c
index 6a5af68..c6dfc14 100644
--- a/drivers/gpu/drm/i915/i915_gem_dmabuf.c
+++ b/drivers/gpu/drm/i915/i915_gem_dmabuf.c
@@ -62,7 +62,7 @@ static struct sg_table *i915_gem_map_dma_buf(struct dma_buf_attachment *attachme
 	src = obj->pages->sgl;
 	dst = st->sgl;
 	for (i = 0; i < obj->pages->nents; i++) {
-		sg_set_page(dst, sg_page(src), PAGE_SIZE, 0);
+		sg_set_page(dst, sg_page(src), src->length, 0);
 		dst = sg_next(dst);
 		src = sg_next(src);
 	}
@@ -105,7 +105,7 @@ static void *i915_gem_dmabuf_vmap(struct dma_buf *dma_buf)
 {
 	struct drm_i915_gem_object *obj = dma_buf->priv;
 	struct drm_device *dev = obj->base.dev;
-	struct scatterlist *sg;
+	struct sg_page_iter sg_iter;
 	struct page **pages;
 	int ret, i;
 
@@ -124,14 +124,15 @@ static void *i915_gem_dmabuf_vmap(struct dma_buf *dma_buf)
 
 	ret = -ENOMEM;
 
-	pages = drm_malloc_ab(obj->pages->nents, sizeof(struct page *));
+	pages = drm_malloc_ab(obj->base.size >> PAGE_SHIFT, sizeof(*pages));
 	if (pages == NULL)
 		goto error;
 
-	for_each_sg(obj->pages->sgl, sg, obj->pages->nents, i)
-		pages[i] = sg_page(sg);
+	i = 0;
+	for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents, 0);
+		pages[i++] = sg_page_iter_page(&sg_iter);
 
-	obj->dma_buf_vmapping = vmap(pages, obj->pages->nents, 0, PAGE_KERNEL);
+	obj->dma_buf_vmapping = vmap(pages, i, 0, PAGE_KERNEL);
 	drm_free_large(pages);
 
 	if (!obj->dma_buf_vmapping)
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index 3b11ab0..117ce38 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -57,7 +57,7 @@ eb_create(struct drm_i915_gem_execbuffer2 *args)
 	if (eb == NULL) {
 		int size = args->buffer_count;
 		int count = PAGE_SIZE / sizeof(struct hlist_head) / 2;
-		BUILD_BUG_ON(!is_power_of_2(PAGE_SIZE / sizeof(struct hlist_head)));
+		BUILD_BUG_ON_NOT_POWER_OF_2(PAGE_SIZE / sizeof(struct hlist_head));
 		while (count > 2*size)
 			count >>= 1;
 		eb = kzalloc(count*sizeof(struct hlist_head) +
@@ -305,7 +305,7 @@ i915_gem_execbuffer_relocate_object(struct drm_i915_gem_object *obj,
 	struct drm_i915_gem_exec_object2 *entry = obj->exec_entry;
 	int remain, ret;
 
-	user_relocs = (void __user *)(uintptr_t)entry->relocs_ptr;
+	user_relocs = to_user_ptr(entry->relocs_ptr);
 
 	remain = entry->relocation_count;
 	while (remain) {
@@ -359,8 +359,7 @@ i915_gem_execbuffer_relocate_object_slow(struct drm_i915_gem_object *obj,
 }
 
 static int
-i915_gem_execbuffer_relocate(struct drm_device *dev,
-			     struct eb_objects *eb)
+i915_gem_execbuffer_relocate(struct eb_objects *eb)
 {
 	struct drm_i915_gem_object *obj;
 	int ret = 0;
@@ -475,7 +474,6 @@ i915_gem_execbuffer_unreserve_object(struct drm_i915_gem_object *obj)
 
 static int
 i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring,
-			    struct drm_file *file,
 			    struct list_head *objects,
 			    bool *need_relocs)
 {
@@ -618,7 +616,7 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev,
 		u64 invalid_offset = (u64)-1;
 		int j;
 
-		user_relocs = (void __user *)(uintptr_t)exec[i].relocs_ptr;
+		user_relocs = to_user_ptr(exec[i].relocs_ptr);
 
 		if (copy_from_user(reloc+total, user_relocs,
 				   exec[i].relocation_count * sizeof(*reloc))) {
@@ -663,7 +661,7 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev,
 		goto err;
 
 	need_relocs = (args->flags & I915_EXEC_NO_RELOC) == 0;
-	ret = i915_gem_execbuffer_reserve(ring, file, &eb->objects, &need_relocs);
+	ret = i915_gem_execbuffer_reserve(ring, &eb->objects, &need_relocs);
 	if (ret)
 		goto err;
 
@@ -736,7 +734,7 @@ validate_exec_list(struct drm_i915_gem_exec_object2 *exec,
 	int relocs_max = INT_MAX / sizeof(struct drm_i915_gem_relocation_entry);
 
 	for (i = 0; i < count; i++) {
-		char __user *ptr = (char __user *)(uintptr_t)exec[i].relocs_ptr;
+		char __user *ptr = to_user_ptr(exec[i].relocs_ptr);
 		int length; /* limited by fault_in_pages_readable() */
 
 		if (exec[i].flags & __EXEC_OBJECT_UNKNOWN_FLAGS)
@@ -752,7 +750,11 @@ validate_exec_list(struct drm_i915_gem_exec_object2 *exec,
 
 		length = exec[i].relocation_count *
 			sizeof(struct drm_i915_gem_relocation_entry);
-		/* we may also need to update the presumed offsets */
+		/*
+		 * We must check that the entire relocation array is safe
+		 * to read, but since we may need to update the presumed
+		 * offsets during execution, check for full write access.
+		 */
 		if (!access_ok(VERIFY_WRITE, ptr, length))
 			return -EFAULT;
 
@@ -949,9 +951,8 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 		}
 
 		if (copy_from_user(cliprects,
-				     (struct drm_clip_rect __user *)(uintptr_t)
-				     args->cliprects_ptr,
-				     sizeof(*cliprects)*args->num_cliprects)) {
+				   to_user_ptr(args->cliprects_ptr),
+				   sizeof(*cliprects)*args->num_cliprects)) {
 			ret = -EFAULT;
 			goto pre_mutex_err;
 		}
@@ -986,13 +987,13 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 
 	/* Move the objects en-masse into the GTT, evicting if necessary. */
 	need_relocs = (args->flags & I915_EXEC_NO_RELOC) == 0;
-	ret = i915_gem_execbuffer_reserve(ring, file, &eb->objects, &need_relocs);
+	ret = i915_gem_execbuffer_reserve(ring, &eb->objects, &need_relocs);
 	if (ret)
 		goto err;
 
 	/* The objects are in their final locations, apply the relocations. */
 	if (need_relocs)
-		ret = i915_gem_execbuffer_relocate(dev, eb);
+		ret = i915_gem_execbuffer_relocate(eb);
 	if (ret) {
 		if (ret == -EFAULT) {
 			ret = i915_gem_execbuffer_relocate_slow(dev, args, file, ring,
@@ -1115,7 +1116,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
 		return -ENOMEM;
 	}
 	ret = copy_from_user(exec_list,
-			     (void __user *)(uintptr_t)args->buffers_ptr,
+			     to_user_ptr(args->buffers_ptr),
 			     sizeof(*exec_list) * args->buffer_count);
 	if (ret != 0) {
 		DRM_DEBUG("copy %d exec entries failed %d\n",
@@ -1154,7 +1155,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
 		for (i = 0; i < args->buffer_count; i++)
 			exec_list[i].offset = exec2_list[i].offset;
 		/* ... and back out to userspace */
-		ret = copy_to_user((void __user *)(uintptr_t)args->buffers_ptr,
+		ret = copy_to_user(to_user_ptr(args->buffers_ptr),
 				   exec_list,
 				   sizeof(*exec_list) * args->buffer_count);
 		if (ret) {
@@ -1195,8 +1196,7 @@ i915_gem_execbuffer2(struct drm_device *dev, void *data,
 		return -ENOMEM;
 	}
 	ret = copy_from_user(exec2_list,
-			     (struct drm_i915_relocation_entry __user *)
-			     (uintptr_t) args->buffers_ptr,
+			     to_user_ptr(args->buffers_ptr),
 			     sizeof(*exec2_list) * args->buffer_count);
 	if (ret != 0) {
 		DRM_DEBUG("copy %d exec entries failed %d\n",
@@ -1208,7 +1208,7 @@ i915_gem_execbuffer2(struct drm_device *dev, void *data,
 	ret = i915_gem_do_execbuffer(dev, data, file, args, exec2_list);
 	if (!ret) {
 		/* Copy the new buffer offsets back to the user's exec list. */
-		ret = copy_to_user((void __user *)(uintptr_t)args->buffers_ptr,
+		ret = copy_to_user(to_user_ptr(args->buffers_ptr),
 				   exec2_list,
 				   sizeof(*exec2_list) * args->buffer_count);
 		if (ret) {
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index 926a1e2..24a23b3 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -83,7 +83,7 @@ static void gen6_ppgtt_clear_range(struct i915_hw_ppgtt *ppgtt,
 {
 	gtt_pte_t *pt_vaddr;
 	gtt_pte_t scratch_pte;
-	unsigned act_pd = first_entry / I915_PPGTT_PT_ENTRIES;
+	unsigned act_pt = first_entry / I915_PPGTT_PT_ENTRIES;
 	unsigned first_pte = first_entry % I915_PPGTT_PT_ENTRIES;
 	unsigned last_pte, i;
 
@@ -96,7 +96,7 @@ static void gen6_ppgtt_clear_range(struct i915_hw_ppgtt *ppgtt,
 		if (last_pte > I915_PPGTT_PT_ENTRIES)
 			last_pte = I915_PPGTT_PT_ENTRIES;
 
-		pt_vaddr = kmap_atomic(ppgtt->pt_pages[act_pd]);
+		pt_vaddr = kmap_atomic(ppgtt->pt_pages[act_pt]);
 
 		for (i = first_pte; i < last_pte; i++)
 			pt_vaddr[i] = scratch_pte;
@@ -105,7 +105,7 @@ static void gen6_ppgtt_clear_range(struct i915_hw_ppgtt *ppgtt,
 
 		num_entries -= last_pte - first_pte;
 		first_pte = 0;
-		act_pd++;
+		act_pt++;
 	}
 }
 
@@ -115,42 +115,26 @@ static void gen6_ppgtt_insert_entries(struct i915_hw_ppgtt *ppgtt,
 				      enum i915_cache_level cache_level)
 {
 	gtt_pte_t *pt_vaddr;
-	unsigned act_pd = first_entry / I915_PPGTT_PT_ENTRIES;
-	unsigned first_pte = first_entry % I915_PPGTT_PT_ENTRIES;
-	unsigned i, j, m, segment_len;
-	dma_addr_t page_addr;
-	struct scatterlist *sg;
-
-	/* init sg walking */
-	sg = pages->sgl;
-	i = 0;
-	segment_len = sg_dma_len(sg) >> PAGE_SHIFT;
-	m = 0;
-
-	while (i < pages->nents) {
-		pt_vaddr = kmap_atomic(ppgtt->pt_pages[act_pd]);
-
-		for (j = first_pte; j < I915_PPGTT_PT_ENTRIES; j++) {
-			page_addr = sg_dma_address(sg) + (m << PAGE_SHIFT);
-			pt_vaddr[j] = gen6_pte_encode(ppgtt->dev, page_addr,
-						      cache_level);
-
-			/* grab the next page */
-			if (++m == segment_len) {
-				if (++i == pages->nents)
-					break;
-
-				sg = sg_next(sg);
-				segment_len = sg_dma_len(sg) >> PAGE_SHIFT;
-				m = 0;
-			}
-		}
-
-		kunmap_atomic(pt_vaddr);
+	unsigned act_pt = first_entry / I915_PPGTT_PT_ENTRIES;
+	unsigned act_pte = first_entry % I915_PPGTT_PT_ENTRIES;
+	struct sg_page_iter sg_iter;
+
+	pt_vaddr = kmap_atomic(ppgtt->pt_pages[act_pt]);
+	for_each_sg_page(pages->sgl, &sg_iter, pages->nents, 0) {
+		dma_addr_t page_addr;
+
+		page_addr = sg_page_iter_dma_address(&sg_iter);
+		pt_vaddr[act_pte] = gen6_pte_encode(ppgtt->dev, page_addr,
+						    cache_level);
+		if (++act_pte == I915_PPGTT_PT_ENTRIES) {
+			kunmap_atomic(pt_vaddr);
+			act_pt++;
+			pt_vaddr = kmap_atomic(ppgtt->pt_pages[act_pt]);
+			act_pte = 0;
 
-		first_pte = 0;
-		act_pd++;
+		}
 	}
+	kunmap_atomic(pt_vaddr);
 }
 
 static void gen6_ppgtt_cleanup(struct i915_hw_ppgtt *ppgtt)
@@ -432,21 +416,16 @@ static void gen6_ggtt_insert_entries(struct drm_device *dev,
 				     enum i915_cache_level level)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct scatterlist *sg = st->sgl;
 	gtt_pte_t __iomem *gtt_entries =
 		(gtt_pte_t __iomem *)dev_priv->gtt.gsm + first_entry;
-	int unused, i = 0;
-	unsigned int len, m = 0;
+	int i = 0;
+	struct sg_page_iter sg_iter;
 	dma_addr_t addr;
 
-	for_each_sg(st->sgl, sg, st->nents, unused) {
-		len = sg_dma_len(sg) >> PAGE_SHIFT;
-		for (m = 0; m < len; m++) {
-			addr = sg_dma_address(sg) + (m << PAGE_SHIFT);
-			iowrite32(gen6_pte_encode(dev, addr, level),
-				  &gtt_entries[i]);
-			i++;
-		}
+	for_each_sg_page(st->sgl, &sg_iter, st->nents, 0) {
+		addr = sg_page_iter_dma_address(&sg_iter);
+		iowrite32(gen6_pte_encode(dev, addr, level), &gtt_entries[i]);
+		i++;
 	}
 
 	/* XXX: This serves as a posting read to make sure that the PTE has
@@ -752,7 +731,7 @@ static int gen6_gmch_probe(struct drm_device *dev,
 	pci_read_config_word(dev->pdev, SNB_GMCH_CTRL, &snb_gmch_ctl);
 	gtt_size = gen6_get_total_gtt_size(snb_gmch_ctl);
 
-	if (IS_GEN7(dev))
+	if (IS_GEN7(dev) && !IS_VALLEYVIEW(dev))
 		*stolen = gen7_get_stolen_size(snb_gmch_ctl);
 	else
 		*stolen = gen6_get_stolen_size(snb_gmch_ctl);
diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c
index 69d97cb..130d1db 100644
--- a/drivers/gpu/drm/i915/i915_gem_stolen.c
+++ b/drivers/gpu/drm/i915/i915_gem_stolen.c
@@ -312,6 +312,71 @@ i915_gem_object_create_stolen(struct drm_device *dev, u32 size)
 	return NULL;
 }
 
+struct drm_i915_gem_object *
+i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev,
+					       u32 stolen_offset,
+					       u32 gtt_offset,
+					       u32 size)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_gem_object *obj;
+	struct drm_mm_node *stolen;
+
+	if (dev_priv->mm.stolen_base == 0)
+		return NULL;
+
+	DRM_DEBUG_KMS("creating preallocated stolen object: stolen_offset=%x, gtt_offset=%x, size=%x\n",
+			stolen_offset, gtt_offset, size);
+
+	/* KISS and expect everything to be page-aligned */
+	BUG_ON(stolen_offset & 4095);
+	BUG_ON(gtt_offset & 4095);
+	BUG_ON(size & 4095);
+
+	if (WARN_ON(size == 0))
+		return NULL;
+
+	stolen = drm_mm_create_block(&dev_priv->mm.stolen,
+				     stolen_offset, size,
+				     false);
+	if (stolen == NULL) {
+		DRM_DEBUG_KMS("failed to allocate stolen space\n");
+		return NULL;
+	}
+
+	obj = _i915_gem_object_create_stolen(dev, stolen);
+	if (obj == NULL) {
+		DRM_DEBUG_KMS("failed to allocate stolen object\n");
+		drm_mm_put_block(stolen);
+		return NULL;
+	}
+
+	/* To simplify the initialisation sequence between KMS and GTT,
+	 * we allow construction of the stolen object prior to
+	 * setting up the GTT space. The actual reservation will occur
+	 * later.
+	 */
+	if (drm_mm_initialized(&dev_priv->mm.gtt_space)) {
+		obj->gtt_space = drm_mm_create_block(&dev_priv->mm.gtt_space,
+						     gtt_offset, size,
+						     false);
+		if (obj->gtt_space == NULL) {
+			DRM_DEBUG_KMS("failed to allocate stolen GTT space\n");
+			drm_gem_object_unreference(&obj->base);
+			return NULL;
+		}
+	} else
+		obj->gtt_space = I915_GTT_RESERVED;
+
+	obj->gtt_offset = gtt_offset;
+	obj->has_global_gtt_mapping = 1;
+
+	list_add_tail(&obj->gtt_list, &dev_priv->mm.bound_list);
+	list_add_tail(&obj->mm_list, &dev_priv->mm.inactive_list);
+
+	return obj;
+}
+
 void
 i915_gem_object_release_stolen(struct drm_i915_gem_object *obj)
 {
diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c
index abcba2f..c807eb9 100644
--- a/drivers/gpu/drm/i915/i915_gem_tiling.c
+++ b/drivers/gpu/drm/i915/i915_gem_tiling.c
@@ -473,28 +473,29 @@ i915_gem_swizzle_page(struct page *page)
 void
 i915_gem_object_do_bit_17_swizzle(struct drm_i915_gem_object *obj)
 {
-	struct scatterlist *sg;
-	int page_count = obj->base.size >> PAGE_SHIFT;
+	struct sg_page_iter sg_iter;
 	int i;
 
 	if (obj->bit_17 == NULL)
 		return;
 
-	for_each_sg(obj->pages->sgl, sg, page_count, i) {
-		struct page *page = sg_page(sg);
+	i = 0;
+	for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents, 0) {
+		struct page *page = sg_page_iter_page(&sg_iter);
 		char new_bit_17 = page_to_phys(page) >> 17;
 		if ((new_bit_17 & 0x1) !=
 		    (test_bit(i, obj->bit_17) != 0)) {
 			i915_gem_swizzle_page(page);
 			set_page_dirty(page);
 		}
+		i++;
 	}
 }
 
 void
 i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj)
 {
-	struct scatterlist *sg;
+	struct sg_page_iter sg_iter;
 	int page_count = obj->base.size >> PAGE_SHIFT;
 	int i;
 
@@ -508,11 +509,12 @@ i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj)
 		}
 	}
 
-	for_each_sg(obj->pages->sgl, sg, page_count, i) {
-		struct page *page = sg_page(sg);
-		if (page_to_phys(page) & (1 << 17))
+	i = 0;
+	for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents, 0) {
+		if (page_to_phys(sg_page_iter_page(&sg_iter)) & (1 << 17))
 			__set_bit(i, obj->bit_17);
 		else
 			__clear_bit(i, obj->bit_17);
+		i++;
 	}
 }
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 3c7bb04..4c5bdd0 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -36,6 +36,60 @@
 #include "i915_trace.h"
 #include "intel_drv.h"
 
+static const u32 hpd_ibx[] = {
+	[HPD_CRT] = SDE_CRT_HOTPLUG,
+	[HPD_SDVO_B] = SDE_SDVOB_HOTPLUG,
+	[HPD_PORT_B] = SDE_PORTB_HOTPLUG,
+	[HPD_PORT_C] = SDE_PORTC_HOTPLUG,
+	[HPD_PORT_D] = SDE_PORTD_HOTPLUG
+};
+
+static const u32 hpd_cpt[] = {
+	[HPD_CRT] = SDE_CRT_HOTPLUG_CPT,
+	[HPD_SDVO_B] = SDE_SDVOB_HOTPLUG_CPT,
+	[HPD_PORT_B] = SDE_PORTB_HOTPLUG_CPT,
+	[HPD_PORT_C] = SDE_PORTC_HOTPLUG_CPT,
+	[HPD_PORT_D] = SDE_PORTD_HOTPLUG_CPT
+};
+
+static const u32 hpd_mask_i915[] = {
+	[HPD_CRT] = CRT_HOTPLUG_INT_EN,
+	[HPD_SDVO_B] = SDVOB_HOTPLUG_INT_EN,
+	[HPD_SDVO_C] = SDVOC_HOTPLUG_INT_EN,
+	[HPD_PORT_B] = PORTB_HOTPLUG_INT_EN,
+	[HPD_PORT_C] = PORTC_HOTPLUG_INT_EN,
+	[HPD_PORT_D] = PORTD_HOTPLUG_INT_EN
+};
+
+static const u32 hpd_status_gen4[] = {
+	[HPD_CRT] = CRT_HOTPLUG_INT_STATUS,
+	[HPD_SDVO_B] = SDVOB_HOTPLUG_INT_STATUS_G4X,
+	[HPD_SDVO_C] = SDVOC_HOTPLUG_INT_STATUS_G4X,
+	[HPD_PORT_B] = PORTB_HOTPLUG_INT_STATUS,
+	[HPD_PORT_C] = PORTC_HOTPLUG_INT_STATUS,
+	[HPD_PORT_D] = PORTD_HOTPLUG_INT_STATUS
+};
+
+static const u32 hpd_status_i965[] = {
+	 [HPD_CRT] = CRT_HOTPLUG_INT_STATUS,
+	 [HPD_SDVO_B] = SDVOB_HOTPLUG_INT_STATUS_I965,
+	 [HPD_SDVO_C] = SDVOC_HOTPLUG_INT_STATUS_I965,
+	 [HPD_PORT_B] = PORTB_HOTPLUG_INT_STATUS,
+	 [HPD_PORT_C] = PORTC_HOTPLUG_INT_STATUS,
+	 [HPD_PORT_D] = PORTD_HOTPLUG_INT_STATUS
+};
+
+static const u32 hpd_status_i915[] = { /* i915 and valleyview are the same */
+	[HPD_CRT] = CRT_HOTPLUG_INT_STATUS,
+	[HPD_SDVO_B] = SDVOB_HOTPLUG_INT_STATUS_I915,
+	[HPD_SDVO_C] = SDVOC_HOTPLUG_INT_STATUS_I915,
+	[HPD_PORT_B] = PORTB_HOTPLUG_INT_STATUS,
+	[HPD_PORT_C] = PORTC_HOTPLUG_INT_STATUS,
+	[HPD_PORT_D] = PORTD_HOTPLUG_INT_STATUS
+};
+
+
+
 /* For display hotplug interrupt */
 static void
 ironlake_enable_display_irq(drm_i915_private_t *dev_priv, u32 mask)
@@ -47,7 +101,7 @@ ironlake_enable_display_irq(drm_i915_private_t *dev_priv, u32 mask)
 	}
 }
 
-static inline void
+static void
 ironlake_disable_display_irq(drm_i915_private_t *dev_priv, u32 mask)
 {
 	if ((dev_priv->irq_mask & mask) != mask) {
@@ -60,26 +114,30 @@ ironlake_disable_display_irq(drm_i915_private_t *dev_priv, u32 mask)
 void
 i915_enable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask)
 {
-	if ((dev_priv->pipestat[pipe] & mask) != mask) {
-		u32 reg = PIPESTAT(pipe);
+	u32 reg = PIPESTAT(pipe);
+	u32 pipestat = I915_READ(reg) & 0x7fff0000;
 
-		dev_priv->pipestat[pipe] |= mask;
-		/* Enable the interrupt, clear any pending status */
-		I915_WRITE(reg, dev_priv->pipestat[pipe] | (mask >> 16));
-		POSTING_READ(reg);
-	}
+	if ((pipestat & mask) == mask)
+		return;
+
+	/* Enable the interrupt, clear any pending status */
+	pipestat |= mask | (mask >> 16);
+	I915_WRITE(reg, pipestat);
+	POSTING_READ(reg);
 }
 
 void
 i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask)
 {
-	if ((dev_priv->pipestat[pipe] & mask) != 0) {
-		u32 reg = PIPESTAT(pipe);
+	u32 reg = PIPESTAT(pipe);
+	u32 pipestat = I915_READ(reg) & 0x7fff0000;
 
-		dev_priv->pipestat[pipe] &= ~mask;
-		I915_WRITE(reg, dev_priv->pipestat[pipe]);
-		POSTING_READ(reg);
-	}
+	if ((pipestat & mask) == 0)
+		return;
+
+	pipestat &= ~mask;
+	I915_WRITE(reg, pipestat);
+	POSTING_READ(reg);
 }
 
 /**
@@ -250,10 +308,9 @@ static int i915_get_vblank_timestamp(struct drm_device *dev, int pipe,
 			      struct timeval *vblank_time,
 			      unsigned flags)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_crtc *crtc;
 
-	if (pipe < 0 || pipe >= dev_priv->num_pipe) {
+	if (pipe < 0 || pipe >= INTEL_INFO(dev)->num_pipes) {
 		DRM_ERROR("Invalid crtc %d\n", pipe);
 		return -EINVAL;
 	}
@@ -596,7 +653,7 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg)
 
 			DRM_DEBUG_DRIVER("hotplug event received, stat 0x%08x\n",
 					 hotplug_status);
-			if (hotplug_status & dev_priv->hotplug_supported_mask)
+			if (hotplug_status & HOTPLUG_INT_STATUS_I915)
 				queue_work(dev_priv->wq,
 					   &dev_priv->hotplug_work);
 
@@ -937,6 +994,8 @@ static void i915_error_work_func(struct work_struct *work)
 		for_each_ring(ring, dev_priv, i)
 			wake_up_all(&ring->irq_queue);
 
+		intel_display_handle_reset(dev);
+
 		wake_up_all(&dev_priv->gpu_error.reset_queue);
 	}
 }
@@ -972,24 +1031,23 @@ static void i915_get_extra_instdone(struct drm_device *dev,
 
 #ifdef CONFIG_DEBUG_FS
 static struct drm_i915_error_object *
-i915_error_object_create(struct drm_i915_private *dev_priv,
-			 struct drm_i915_gem_object *src)
+i915_error_object_create_sized(struct drm_i915_private *dev_priv,
+			       struct drm_i915_gem_object *src,
+			       const int num_pages)
 {
 	struct drm_i915_error_object *dst;
-	int i, count;
+	int i;
 	u32 reloc_offset;
 
 	if (src == NULL || src->pages == NULL)
 		return NULL;
 
-	count = src->base.size / PAGE_SIZE;
-
-	dst = kmalloc(sizeof(*dst) + count * sizeof(u32 *), GFP_ATOMIC);
+	dst = kmalloc(sizeof(*dst) + num_pages * sizeof(u32 *), GFP_ATOMIC);
 	if (dst == NULL)
 		return NULL;
 
 	reloc_offset = src->gtt_offset;
-	for (i = 0; i < count; i++) {
+	for (i = 0; i < num_pages; i++) {
 		unsigned long flags;
 		void *d;
 
@@ -1039,7 +1097,7 @@ i915_error_object_create(struct drm_i915_private *dev_priv,
 
 		reloc_offset += PAGE_SIZE;
 	}
-	dst->page_count = count;
+	dst->page_count = num_pages;
 	dst->gtt_offset = src->gtt_offset;
 
 	return dst;
@@ -1050,6 +1108,9 @@ unwind:
 	kfree(dst);
 	return NULL;
 }
+#define i915_error_object_create(dev_priv, src) \
+	i915_error_object_create_sized((dev_priv), (src), \
+				       (src)->base.size>>PAGE_SHIFT)
 
 static void
 i915_error_object_free(struct drm_i915_error_object *obj)
@@ -1256,6 +1317,26 @@ static void i915_record_ring_state(struct drm_device *dev,
 	error->cpu_ring_tail[ring->id] = ring->tail;
 }
 
+
+static void i915_gem_record_active_context(struct intel_ring_buffer *ring,
+					   struct drm_i915_error_state *error,
+					   struct drm_i915_error_ring *ering)
+{
+	struct drm_i915_private *dev_priv = ring->dev->dev_private;
+	struct drm_i915_gem_object *obj;
+
+	/* Currently render ring is the only HW context user */
+	if (ring->id != RCS || !error->ccid)
+		return;
+
+	list_for_each_entry(obj, &dev_priv->mm.bound_list, gtt_list) {
+		if ((error->ccid & PAGE_MASK) == obj->gtt_offset) {
+			ering->ctx = i915_error_object_create_sized(dev_priv,
+								    obj, 1);
+		}
+	}
+}
+
 static void i915_gem_record_rings(struct drm_device *dev,
 				  struct drm_i915_error_state *error)
 {
@@ -1273,6 +1354,9 @@ static void i915_gem_record_rings(struct drm_device *dev,
 		error->ring[i].ringbuffer =
 			i915_error_object_create(dev_priv, ring->obj);
 
+
+		i915_gem_record_active_context(ring, error, &error->ring[i]);
+
 		count = 0;
 		list_for_each_entry(request, &ring->request_list, list)
 			count++;
@@ -1328,14 +1412,15 @@ static void i915_capture_error_state(struct drm_device *dev)
 		return;
 	}
 
-	DRM_INFO("capturing error event; look for more information in"
+	DRM_INFO("capturing error event; look for more information in "
 		 "/sys/kernel/debug/dri/%d/i915_error_state\n",
 		 dev->primary->index);
 
 	kref_init(&error->ref);
 	error->eir = I915_READ(EIR);
 	error->pgtbl_er = I915_READ(PGTBL_ER);
-	error->ccid = I915_READ(CCID);
+	if (HAS_HW_CONTEXTS(dev))
+		error->ccid = I915_READ(CCID);
 
 	if (HAS_PCH_SPLIT(dev))
 		error->ier = I915_READ(DEIER) | I915_READ(GTIER);
@@ -1356,8 +1441,9 @@ static void i915_capture_error_state(struct drm_device *dev)
 	else if (INTEL_INFO(dev)->gen == 6)
 		error->forcewake = I915_READ(FORCEWAKE);
 
-	for_each_pipe(pipe)
-		error->pipestat[pipe] = I915_READ(PIPESTAT(pipe));
+	if (!HAS_PCH_SPLIT(dev))
+		for_each_pipe(pipe)
+			error->pipestat[pipe] = I915_READ(PIPESTAT(pipe));
 
 	if (INTEL_INFO(dev)->gen >= 6) {
 		error->error = I915_READ(ERROR_GEN6);
@@ -1567,7 +1653,7 @@ void i915_handle_error(struct drm_device *dev, bool wedged)
 	queue_work(dev_priv->wq, &dev_priv->gpu_error.work);
 }
 
-static void i915_pageflip_stall_check(struct drm_device *dev, int pipe)
+static void __always_unused i915_pageflip_stall_check(struct drm_device *dev, int pipe)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
@@ -1777,6 +1863,37 @@ static bool i915_hangcheck_ring_idle(struct intel_ring_buffer *ring, bool *err)
 	return false;
 }
 
+static bool semaphore_passed(struct intel_ring_buffer *ring)
+{
+	struct drm_i915_private *dev_priv = ring->dev->dev_private;
+	u32 acthd = intel_ring_get_active_head(ring) & HEAD_ADDR;
+	struct intel_ring_buffer *signaller;
+	u32 cmd, ipehr, acthd_min;
+
+	ipehr = I915_READ(RING_IPEHR(ring->mmio_base));
+	if ((ipehr & ~(0x3 << 16)) !=
+	    (MI_SEMAPHORE_MBOX | MI_SEMAPHORE_COMPARE | MI_SEMAPHORE_REGISTER))
+		return false;
+
+	/* ACTHD is likely pointing to the dword after the actual command,
+	 * so scan backwards until we find the MBOX.
+	 */
+	acthd_min = max((int)acthd - 3 * 4, 0);
+	do {
+		cmd = ioread32(ring->virtual_start + acthd);
+		if (cmd == ipehr)
+			break;
+
+		acthd -= 4;
+		if (acthd < acthd_min)
+			return false;
+	} while (1);
+
+	signaller = &dev_priv->ring[(ring->id + (((ipehr >> 17) & 1) + 1)) % 3];
+	return i915_seqno_passed(signaller->get_seqno(signaller, false),
+				 ioread32(ring->virtual_start+acthd+4)+1);
+}
+
 static bool kick_ring(struct intel_ring_buffer *ring)
 {
 	struct drm_device *dev = ring->dev;
@@ -1788,6 +1905,15 @@ static bool kick_ring(struct intel_ring_buffer *ring)
 		I915_WRITE_CTL(ring, tmp);
 		return true;
 	}
+
+	if (INTEL_INFO(dev)->gen >= 6 &&
+	    tmp & RING_WAIT_SEMAPHORE &&
+	    semaphore_passed(ring)) {
+		DRM_ERROR("Kicking stuck semaphore on %s\n",
+			  ring->name);
+		I915_WRITE_CTL(ring, tmp);
+		return true;
+	}
 	return false;
 }
 
@@ -1903,7 +2029,13 @@ static void ironlake_irq_preinstall(struct drm_device *dev)
 
 	/* south display irq */
 	I915_WRITE(SDEIMR, 0xffffffff);
-	I915_WRITE(SDEIER, 0x0);
+	/*
+	 * SDEIER is also touched by the interrupt handler to work around missed
+	 * PCH interrupts. Hence we can't update it after the interrupt handler
+	 * is enabled - instead we unconditionally enable all PCH interrupt
+	 * sources here, but then only unmask them as needed with SDEIMR.
+	 */
+	I915_WRITE(SDEIER, 0xffffffff);
 	POSTING_READ(SDEIER);
 }
 
@@ -1939,18 +2071,30 @@ static void valleyview_irq_preinstall(struct drm_device *dev)
 	POSTING_READ(VLV_IER);
 }
 
-/*
- * Enable digital hotplug on the PCH, and configure the DP short pulse
- * duration to 2ms (which is the minimum in the Display Port spec)
- *
- * This register is the same on all known PCH chips.
- */
-
-static void ibx_enable_hotplug(struct drm_device *dev)
+static void ibx_hpd_irq_setup(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-	u32	hotplug;
+	struct drm_mode_config *mode_config = &dev->mode_config;
+	struct intel_encoder *intel_encoder;
+	u32 mask = ~I915_READ(SDEIMR);
+	u32 hotplug;
+
+	if (HAS_PCH_IBX(dev)) {
+		list_for_each_entry(intel_encoder, &mode_config->encoder_list, base.head)
+			mask |= hpd_ibx[intel_encoder->hpd_pin];
+	} else {
+		list_for_each_entry(intel_encoder, &mode_config->encoder_list, base.head)
+			mask |= hpd_cpt[intel_encoder->hpd_pin];
+	}
+
+	I915_WRITE(SDEIMR, ~mask);
 
+	/*
+	 * Enable digital hotplug on the PCH, and configure the DP short pulse
+	 * duration to 2ms (which is the minimum in the Display Port spec)
+	 *
+	 * This register is the same on all known PCH chips.
+	 */
 	hotplug = I915_READ(PCH_PORT_HOTPLUG);
 	hotplug &= ~(PORTD_PULSE_DURATION_MASK|PORTC_PULSE_DURATION_MASK|PORTB_PULSE_DURATION_MASK);
 	hotplug |= PORTD_HOTPLUG_ENABLE | PORTD_PULSE_DURATION_2ms;
@@ -1965,20 +2109,11 @@ static void ibx_irq_postinstall(struct drm_device *dev)
 	u32 mask;
 
 	if (HAS_PCH_IBX(dev))
-		mask = SDE_HOTPLUG_MASK |
-		       SDE_GMBUS |
-		       SDE_AUX_MASK;
+		mask = SDE_GMBUS | SDE_AUX_MASK;
 	else
-		mask = SDE_HOTPLUG_MASK_CPT |
-		       SDE_GMBUS_CPT |
-		       SDE_AUX_MASK_CPT;
-
+		mask = SDE_GMBUS_CPT | SDE_AUX_MASK_CPT;
 	I915_WRITE(SDEIIR, I915_READ(SDEIIR));
 	I915_WRITE(SDEIMR, ~mask);
-	I915_WRITE(SDEIER, mask);
-	POSTING_READ(SDEIER);
-
-	ibx_enable_hotplug(dev);
 }
 
 static int ironlake_irq_postinstall(struct drm_device *dev)
@@ -2089,9 +2224,6 @@ static int valleyview_irq_postinstall(struct drm_device *dev)
 		I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT |
 		I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
 
-	dev_priv->pipestat[0] = 0;
-	dev_priv->pipestat[1] = 0;
-
 	/* Hack for broken MSIs on VLV */
 	pci_write_config_dword(dev_priv->dev->pdev, 0x94, 0xfee00000);
 	pci_read_config_word(dev->pdev, 0x98, &msid);
@@ -2135,30 +2267,6 @@ static int valleyview_irq_postinstall(struct drm_device *dev)
 	return 0;
 }
 
-static void valleyview_hpd_irq_setup(struct drm_device *dev)
-{
-	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-	u32 hotplug_en = I915_READ(PORT_HOTPLUG_EN);
-
-	/* Note HDMI and DP share bits */
-	if (dev_priv->hotplug_supported_mask & PORTB_HOTPLUG_INT_STATUS)
-		hotplug_en |= PORTB_HOTPLUG_INT_EN;
-	if (dev_priv->hotplug_supported_mask & PORTC_HOTPLUG_INT_STATUS)
-		hotplug_en |= PORTC_HOTPLUG_INT_EN;
-	if (dev_priv->hotplug_supported_mask & PORTD_HOTPLUG_INT_STATUS)
-		hotplug_en |= PORTD_HOTPLUG_INT_EN;
-	if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS_I915)
-		hotplug_en |= SDVOC_HOTPLUG_INT_EN;
-	if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS_I915)
-		hotplug_en |= SDVOB_HOTPLUG_INT_EN;
-	if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS) {
-		hotplug_en |= CRT_HOTPLUG_INT_EN;
-		hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50;
-	}
-
-	I915_WRITE(PORT_HOTPLUG_EN, hotplug_en);
-}
-
 static void valleyview_irq_uninstall(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
@@ -2221,9 +2329,6 @@ static int i8xx_irq_postinstall(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 
-	dev_priv->pipestat[0] = 0;
-	dev_priv->pipestat[1] = 0;
-
 	I915_WRITE16(EMR,
 		     ~(I915_ERROR_PAGE_TABLE | I915_ERROR_MEMORY_REFRESH));
 
@@ -2246,6 +2351,37 @@ static int i8xx_irq_postinstall(struct drm_device *dev)
 	return 0;
 }
 
+/*
+ * Returns true when a page flip has completed.
+ */
+static bool i8xx_handle_vblank(struct drm_device *dev,
+			       int pipe, u16 iir)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	u16 flip_pending = DISPLAY_PLANE_FLIP_PENDING(pipe);
+
+	if (!drm_handle_vblank(dev, pipe))
+		return false;
+
+	if ((iir & flip_pending) == 0)
+		return false;
+
+	intel_prepare_page_flip(dev, pipe);
+
+	/* We detect FlipDone by looking for the change in PendingFlip from '1'
+	 * to '0' on the following vblank, i.e. IIR has the Pendingflip
+	 * asserted following the MI_DISPLAY_FLIP, but ISR is deasserted, hence
+	 * the flip is completed (no longer pending). Since this doesn't raise
+	 * an interrupt per se, we watch for the change at vblank.
+	 */
+	if (I915_READ16(ISR) & flip_pending)
+		return false;
+
+	intel_finish_page_flip(dev, pipe);
+
+	return true;
+}
+
 static irqreturn_t i8xx_irq_handler(int irq, void *arg)
 {
 	struct drm_device *dev = (struct drm_device *) arg;
@@ -2301,22 +2437,12 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg)
 			notify_ring(dev, &dev_priv->ring[RCS]);
 
 		if (pipe_stats[0] & PIPE_VBLANK_INTERRUPT_STATUS &&
-		    drm_handle_vblank(dev, 0)) {
-			if (iir & I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT) {
-				intel_prepare_page_flip(dev, 0);
-				intel_finish_page_flip(dev, 0);
-				flip_mask &= ~I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT;
-			}
-		}
+		    i8xx_handle_vblank(dev, 0, iir))
+			flip_mask &= ~DISPLAY_PLANE_FLIP_PENDING(0);
 
 		if (pipe_stats[1] & PIPE_VBLANK_INTERRUPT_STATUS &&
-		    drm_handle_vblank(dev, 1)) {
-			if (iir & I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT) {
-				intel_prepare_page_flip(dev, 1);
-				intel_finish_page_flip(dev, 1);
-				flip_mask &= ~I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT;
-			}
-		}
+		    i8xx_handle_vblank(dev, 1, iir))
+			flip_mask &= ~DISPLAY_PLANE_FLIP_PENDING(1);
 
 		iir = new_iir;
 	}
@@ -2364,9 +2490,6 @@ static int i915_irq_postinstall(struct drm_device *dev)
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 	u32 enable_mask;
 
-	dev_priv->pipestat[0] = 0;
-	dev_priv->pipestat[1] = 0;
-
 	I915_WRITE(EMR, ~(I915_ERROR_PAGE_TABLE | I915_ERROR_MEMORY_REFRESH));
 
 	/* Unmask the interrupts that we always want on. */
@@ -2404,33 +2527,35 @@ static int i915_irq_postinstall(struct drm_device *dev)
 	return 0;
 }
 
-static void i915_hpd_irq_setup(struct drm_device *dev)
+/*
+ * Returns true when a page flip has completed.
+ */
+static bool i915_handle_vblank(struct drm_device *dev,
+			       int plane, int pipe, u32 iir)
 {
-	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-	u32 hotplug_en;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	u32 flip_pending = DISPLAY_PLANE_FLIP_PENDING(plane);
 
-	if (I915_HAS_HOTPLUG(dev)) {
-		hotplug_en = I915_READ(PORT_HOTPLUG_EN);
+	if (!drm_handle_vblank(dev, pipe))
+		return false;
 
-		if (dev_priv->hotplug_supported_mask & PORTB_HOTPLUG_INT_STATUS)
-			hotplug_en |= PORTB_HOTPLUG_INT_EN;
-		if (dev_priv->hotplug_supported_mask & PORTC_HOTPLUG_INT_STATUS)
-			hotplug_en |= PORTC_HOTPLUG_INT_EN;
-		if (dev_priv->hotplug_supported_mask & PORTD_HOTPLUG_INT_STATUS)
-			hotplug_en |= PORTD_HOTPLUG_INT_EN;
-		if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS_I915)
-			hotplug_en |= SDVOC_HOTPLUG_INT_EN;
-		if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS_I915)
-			hotplug_en |= SDVOB_HOTPLUG_INT_EN;
-		if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS) {
-			hotplug_en |= CRT_HOTPLUG_INT_EN;
-			hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50;
-		}
+	if ((iir & flip_pending) == 0)
+		return false;
 
-		/* Ignore TV since it's buggy */
+	intel_prepare_page_flip(dev, plane);
 
-		I915_WRITE(PORT_HOTPLUG_EN, hotplug_en);
-	}
+	/* We detect FlipDone by looking for the change in PendingFlip from '1'
+	 * to '0' on the following vblank, i.e. IIR has the Pendingflip
+	 * asserted following the MI_DISPLAY_FLIP, but ISR is deasserted, hence
+	 * the flip is completed (no longer pending). Since this doesn't raise
+	 * an interrupt per se, we watch for the change at vblank.
+	 */
+	if (I915_READ(ISR) & flip_pending)
+		return false;
+
+	intel_finish_page_flip(dev, pipe);
+
+	return true;
 }
 
 static irqreturn_t i915_irq_handler(int irq, void *arg)
@@ -2442,10 +2567,6 @@ static irqreturn_t i915_irq_handler(int irq, void *arg)
 	u32 flip_mask =
 		I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT |
 		I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT;
-	u32 flip[2] = {
-		I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT,
-		I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT
-	};
 	int pipe, ret = IRQ_NONE;
 
 	atomic_inc(&dev_priv->irq_received);
@@ -2489,7 +2610,7 @@ static irqreturn_t i915_irq_handler(int irq, void *arg)
 
 			DRM_DEBUG_DRIVER("hotplug event received, stat 0x%08x\n",
 				  hotplug_status);
-			if (hotplug_status & dev_priv->hotplug_supported_mask)
+			if (hotplug_status & HOTPLUG_INT_STATUS_I915)
 				queue_work(dev_priv->wq,
 					   &dev_priv->hotplug_work);
 
@@ -2507,14 +2628,10 @@ static irqreturn_t i915_irq_handler(int irq, void *arg)
 			int plane = pipe;
 			if (IS_MOBILE(dev))
 				plane = !plane;
+
 			if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS &&
-			    drm_handle_vblank(dev, pipe)) {
-				if (iir & flip[plane]) {
-					intel_prepare_page_flip(dev, plane);
-					intel_finish_page_flip(dev, pipe);
-					flip_mask &= ~flip[plane];
-				}
-			}
+			    i915_handle_vblank(dev, plane, pipe, iir))
+				flip_mask &= ~DISPLAY_PLANE_FLIP_PENDING(plane);
 
 			if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS)
 				blc_event = true;
@@ -2603,13 +2720,13 @@ static int i965_irq_postinstall(struct drm_device *dev)
 			       I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT);
 
 	enable_mask = ~dev_priv->irq_mask;
+	enable_mask &= ~(I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT |
+			 I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT);
 	enable_mask |= I915_USER_INTERRUPT;
 
 	if (IS_G4X(dev))
 		enable_mask |= I915_BSD_USER_INTERRUPT;
 
-	dev_priv->pipestat[0] = 0;
-	dev_priv->pipestat[1] = 0;
 	i915_enable_pipestat(dev_priv, 0, PIPE_GMBUS_EVENT_ENABLE);
 
 	/*
@@ -2639,45 +2756,32 @@ static int i965_irq_postinstall(struct drm_device *dev)
 	return 0;
 }
 
-static void i965_hpd_irq_setup(struct drm_device *dev)
+static void i915_hpd_irq_setup(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+	struct drm_mode_config *mode_config = &dev->mode_config;
+	struct intel_encoder *encoder;
 	u32 hotplug_en;
 
-	/* Note HDMI and DP share hotplug bits */
-	hotplug_en = 0;
-	if (dev_priv->hotplug_supported_mask & PORTB_HOTPLUG_INT_STATUS)
-		hotplug_en |= PORTB_HOTPLUG_INT_EN;
-	if (dev_priv->hotplug_supported_mask & PORTC_HOTPLUG_INT_STATUS)
-		hotplug_en |= PORTC_HOTPLUG_INT_EN;
-	if (dev_priv->hotplug_supported_mask & PORTD_HOTPLUG_INT_STATUS)
-		hotplug_en |= PORTD_HOTPLUG_INT_EN;
-	if (IS_G4X(dev)) {
-		if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS_G4X)
-			hotplug_en |= SDVOC_HOTPLUG_INT_EN;
-		if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS_G4X)
-			hotplug_en |= SDVOB_HOTPLUG_INT_EN;
-	} else {
-		if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS_I965)
-			hotplug_en |= SDVOC_HOTPLUG_INT_EN;
-		if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS_I965)
-			hotplug_en |= SDVOB_HOTPLUG_INT_EN;
-	}
-	if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS) {
-		hotplug_en |= CRT_HOTPLUG_INT_EN;
-
+	if (I915_HAS_HOTPLUG(dev)) {
+		hotplug_en = I915_READ(PORT_HOTPLUG_EN);
+		hotplug_en &= ~HOTPLUG_INT_EN_MASK;
+		/* Note HDMI and DP share hotplug bits */
+		/* enable bits are the same for all generations */
+		list_for_each_entry(encoder, &mode_config->encoder_list, base.head)
+			hotplug_en |= hpd_mask_i915[encoder->hpd_pin];
 		/* Programming the CRT detection parameters tends
 		   to generate a spurious hotplug event about three
 		   seconds later.  So just do it once.
-		   */
+		*/
 		if (IS_G4X(dev))
 			hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64;
+		hotplug_en &= ~CRT_HOTPLUG_VOLTAGE_COMPARE_MASK;
 		hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50;
-	}
-
-	/* Ignore TV since it's buggy */
 
-	I915_WRITE(PORT_HOTPLUG_EN, hotplug_en);
+		/* Ignore TV since it's buggy */
+		I915_WRITE(PORT_HOTPLUG_EN, hotplug_en);
+	}
 }
 
 static irqreturn_t i965_irq_handler(int irq, void *arg)
@@ -2689,6 +2793,9 @@ static irqreturn_t i965_irq_handler(int irq, void *arg)
 	unsigned long irqflags;
 	int irq_received;
 	int ret = IRQ_NONE, pipe;
+	u32 flip_mask =
+		I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT |
+		I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT;
 
 	atomic_inc(&dev_priv->irq_received);
 
@@ -2697,7 +2804,7 @@ static irqreturn_t i965_irq_handler(int irq, void *arg)
 	for (;;) {
 		bool blc_event = false;
 
-		irq_received = iir != 0;
+		irq_received = (iir & ~flip_mask) != 0;
 
 		/* Can't rely on pipestat interrupt bit in iir as it might
 		 * have been cleared after the pipestat interrupt was received.
@@ -2736,7 +2843,9 @@ static irqreturn_t i965_irq_handler(int irq, void *arg)
 
 			DRM_DEBUG_DRIVER("hotplug event received, stat 0x%08x\n",
 				  hotplug_status);
-			if (hotplug_status & dev_priv->hotplug_supported_mask)
+			if (hotplug_status & (IS_G4X(dev) ?
+					      HOTPLUG_INT_STATUS_G4X :
+					      HOTPLUG_INT_STATUS_I965))
 				queue_work(dev_priv->wq,
 					   &dev_priv->hotplug_work);
 
@@ -2744,7 +2853,7 @@ static irqreturn_t i965_irq_handler(int irq, void *arg)
 			I915_READ(PORT_HOTPLUG_STAT);
 		}
 
-		I915_WRITE(IIR, iir);
+		I915_WRITE(IIR, iir & ~flip_mask);
 		new_iir = I915_READ(IIR); /* Flush posted writes */
 
 		if (iir & I915_USER_INTERRUPT)
@@ -2752,18 +2861,10 @@ static irqreturn_t i965_irq_handler(int irq, void *arg)
 		if (iir & I915_BSD_USER_INTERRUPT)
 			notify_ring(dev, &dev_priv->ring[VCS]);
 
-		if (iir & I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT)
-			intel_prepare_page_flip(dev, 0);
-
-		if (iir & I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT)
-			intel_prepare_page_flip(dev, 1);
-
 		for_each_pipe(pipe) {
 			if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS &&
-			    drm_handle_vblank(dev, pipe)) {
-				i915_pageflip_stall_check(dev, pipe);
-				intel_finish_page_flip(dev, pipe);
-			}
+			    i915_handle_vblank(dev, pipe, pipe, iir))
+				flip_mask &= ~DISPLAY_PLANE_FLIP_PENDING(pipe);
 
 			if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS)
 				blc_event = true;
@@ -2857,7 +2958,7 @@ void intel_irq_init(struct drm_device *dev)
 		dev->driver->irq_uninstall = valleyview_irq_uninstall;
 		dev->driver->enable_vblank = valleyview_enable_vblank;
 		dev->driver->disable_vblank = valleyview_disable_vblank;
-		dev_priv->display.hpd_irq_setup = valleyview_hpd_irq_setup;
+		dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup;
 	} else if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) {
 		/* Share pre & uninstall handlers with ILK/SNB */
 		dev->driver->irq_handler = ivybridge_irq_handler;
@@ -2866,6 +2967,7 @@ void intel_irq_init(struct drm_device *dev)
 		dev->driver->irq_uninstall = ironlake_irq_uninstall;
 		dev->driver->enable_vblank = ivybridge_enable_vblank;
 		dev->driver->disable_vblank = ivybridge_disable_vblank;
+		dev_priv->display.hpd_irq_setup = ibx_hpd_irq_setup;
 	} else if (HAS_PCH_SPLIT(dev)) {
 		dev->driver->irq_handler = ironlake_irq_handler;
 		dev->driver->irq_preinstall = ironlake_irq_preinstall;
@@ -2873,6 +2975,7 @@ void intel_irq_init(struct drm_device *dev)
 		dev->driver->irq_uninstall = ironlake_irq_uninstall;
 		dev->driver->enable_vblank = ironlake_enable_vblank;
 		dev->driver->disable_vblank = ironlake_disable_vblank;
+		dev_priv->display.hpd_irq_setup = ibx_hpd_irq_setup;
 	} else {
 		if (INTEL_INFO(dev)->gen == 2) {
 			dev->driver->irq_preinstall = i8xx_irq_preinstall;
@@ -2890,7 +2993,7 @@ void intel_irq_init(struct drm_device *dev)
 			dev->driver->irq_postinstall = i965_irq_postinstall;
 			dev->driver->irq_uninstall = i965_irq_uninstall;
 			dev->driver->irq_handler = i965_irq_handler;
-			dev_priv->display.hpd_irq_setup = i965_hpd_irq_setup;
+			dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup;
 		}
 		dev->driver->enable_vblank = i915_enable_vblank;
 		dev->driver->disable_vblank = i915_disable_vblank;
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 848992f..058686c 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -91,6 +91,7 @@
 #define  GRDOM_FULL	(0<<2)
 #define  GRDOM_RENDER	(1<<2)
 #define  GRDOM_MEDIA	(3<<2)
+#define  GRDOM_MASK	(3<<2)
 #define  GRDOM_RESET_ENABLE (1<<0)
 
 #define GEN6_MBCUNIT_SNPCR	0x900c /* for LLC config */
@@ -121,6 +122,7 @@
 
 #define GAM_ECOCHK			0x4090
 #define   ECOCHK_SNB_BIT		(1<<10)
+#define   HSW_ECOCHK_ARB_PRIO_SOL	(1<<6)
 #define   ECOCHK_PPGTT_CACHE64B		(0x3<<3)
 #define   ECOCHK_PPGTT_CACHE4B		(0x0<<3)
 
@@ -522,6 +524,9 @@
 #define GEN7_ERR_INT	0x44040
 #define   ERR_INT_MMIO_UNCLAIMED (1<<13)
 
+#define FPGA_DBG		0x42300
+#define   FPGA_DBG_RM_NOCLAIM	(1<<31)
+
 #define DERRMR		0x44050
 
 /* GM45+ chicken bits -- debug workaround bits that may be required
@@ -591,6 +596,7 @@
 #define   I915_USER_INTERRUPT				(1<<1)
 #define   I915_ASLE_INTERRUPT				(1<<0)
 #define   I915_BSD_USER_INTERRUPT                      (1<<25)
+#define   DISPLAY_PLANE_FLIP_PENDING(plane) (1<<(11-(plane))) /* A and B only */
 #define EIR		0x020b0
 #define EMR		0x020b4
 #define ESR		0x020b8
@@ -1637,6 +1643,12 @@
 #define   SDVOC_HOTPLUG_INT_EN			(1 << 25)
 #define   TV_HOTPLUG_INT_EN			(1 << 18)
 #define   CRT_HOTPLUG_INT_EN			(1 << 9)
+#define HOTPLUG_INT_EN_MASK			(PORTB_HOTPLUG_INT_EN | \
+						 PORTC_HOTPLUG_INT_EN | \
+						 PORTD_HOTPLUG_INT_EN | \
+						 SDVOC_HOTPLUG_INT_EN | \
+						 SDVOB_HOTPLUG_INT_EN | \
+						 CRT_HOTPLUG_INT_EN)
 #define   CRT_HOTPLUG_FORCE_DETECT		(1 << 3)
 #define CRT_HOTPLUG_ACTIVATION_PERIOD_32	(0 << 8)
 /* must use period 64 on GM45 according to docs */
@@ -1675,43 +1687,84 @@
 #define   SDVOB_HOTPLUG_INT_STATUS_I965		(3 << 2)
 #define   SDVOC_HOTPLUG_INT_STATUS_I915		(1 << 7)
 #define   SDVOB_HOTPLUG_INT_STATUS_I915		(1 << 6)
-
-/* SDVO port control */
-#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   HOTPLUG_INT_STATUS_G4X		(CRT_HOTPLUG_INT_STATUS | \
+						 SDVOB_HOTPLUG_INT_STATUS_G4X | \
+						 SDVOC_HOTPLUG_INT_STATUS_G4X | \
+						 PORTB_HOTPLUG_INT_STATUS | \
+						 PORTC_HOTPLUG_INT_STATUS | \
+						 PORTD_HOTPLUG_INT_STATUS)
+
+#define HOTPLUG_INT_STATUS_I965			(CRT_HOTPLUG_INT_STATUS | \
+						 SDVOB_HOTPLUG_INT_STATUS_I965 | \
+						 SDVOC_HOTPLUG_INT_STATUS_I965 | \
+						 PORTB_HOTPLUG_INT_STATUS | \
+						 PORTC_HOTPLUG_INT_STATUS | \
+						 PORTD_HOTPLUG_INT_STATUS)
+
+#define HOTPLUG_INT_STATUS_I915			(CRT_HOTPLUG_INT_STATUS | \
+						 SDVOB_HOTPLUG_INT_STATUS_I915 | \
+						 SDVOC_HOTPLUG_INT_STATUS_I915 | \
+						 PORTB_HOTPLUG_INT_STATUS | \
+						 PORTC_HOTPLUG_INT_STATUS | \
+						 PORTD_HOTPLUG_INT_STATUS)
+
+/* SDVO and HDMI port control.
+ * The same register may be used for SDVO or HDMI */
+#define GEN3_SDVOB	0x61140
+#define GEN3_SDVOC	0x61160
+#define GEN4_HDMIB	GEN3_SDVOB
+#define GEN4_HDMIC	GEN3_SDVOC
+#define PCH_SDVOB	0xe1140
+#define PCH_HDMIB	PCH_SDVOB
+#define PCH_HDMIC	0xe1150
+#define PCH_HDMID	0xe1160
+
+/* Gen 3 SDVO bits: */
+#define   SDVO_ENABLE				(1 << 31)
+#define   SDVO_PIPE_SEL(pipe)			((pipe) << 30)
+#define   SDVO_PIPE_SEL_MASK			(1 << 30)
+#define   SDVO_PIPE_B_SELECT			(1 << 30)
+#define   SDVO_STALL_SELECT			(1 << 29)
+#define   SDVO_INTERRUPT_ENABLE			(1 << 26)
 /**
  * 915G/GM SDVO pixel multiplier.
- *
  * Programmed value is multiplier - 1, up to 5x.
- *
  * \sa DPLL_MD_UDI_MULTIPLIER_MASK
  */
-#define   SDVO_PORT_MULTIPLY_MASK	(7 << 23)
+#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_ENCODING_SDVO		(0x0 << 10)
-#define   SDVO_ENCODING_HDMI		(0x2 << 10)
-/** Requird for HDMI operation */
-#define   SDVO_NULL_PACKETS_DURING_VSYNC (1 << 9)
-#define   SDVO_COLOR_RANGE_16_235	(1 << 8)
-#define   SDVO_BORDER_ENABLE		(1 << 7)
-#define   SDVO_AUDIO_ENABLE		(1 << 6)
-/** New with 965, default is to be set */
-#define   SDVO_VSYNC_ACTIVE_HIGH	(1 << 4)
-/** New with 965, default is to be set */
-#define   SDVO_HSYNC_ACTIVE_HIGH	(1 << 3)
-#define   SDVOB_PCIE_CONCURRENCY	(1 << 3)
-#define   SDVO_DETECTED			(1 << 2)
+#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) /* Port C only */
+#define   SDVO_BORDER_ENABLE			(1 << 7) /* SDVO only */
+#define   SDVOB_PCIE_CONCURRENCY		(1 << 3) /* Port B only */
+#define   SDVO_DETECTED				(1 << 2)
 /* Bits to be preserved when writing */
-#define   SDVOB_PRESERVE_MASK ((1 << 17) | (1 << 16) | (1 << 14) | (1 << 26))
-#define   SDVOC_PRESERVE_MASK ((1 << 17) | (1 << 26))
+#define   SDVOB_PRESERVE_MASK ((1 << 17) | (1 << 16) | (1 << 14) | \
+			       SDVO_INTERRUPT_ENABLE)
+#define   SDVOC_PRESERVE_MASK ((1 << 17) | SDVO_INTERRUPT_ENABLE)
+
+/* Gen 4 SDVO/HDMI bits: */
+#define   SDVO_COLOR_FORMAT_8bpc		(0 << 26)
+#define   SDVO_ENCODING_SDVO			(0 << 10)
+#define   SDVO_ENCODING_HDMI			(2 << 10)
+#define   HDMI_MODE_SELECT_HDMI			(1 << 9) /* HDMI only */
+#define   HDMI_MODE_SELECT_DVI			(0 << 9) /* HDMI only */
+#define   HDMI_COLOR_RANGE_16_235		(1 << 8) /* HDMI only */
+#define   SDVO_AUDIO_ENABLE			(1 << 6)
+/* VSYNC/HSYNC bits new with 965, default is to be set */
+#define   SDVO_VSYNC_ACTIVE_HIGH		(1 << 4)
+#define   SDVO_HSYNC_ACTIVE_HIGH		(1 << 3)
+
+/* Gen 5 (IBX) SDVO/HDMI bits: */
+#define   HDMI_COLOR_FORMAT_12bpc		(3 << 26) /* HDMI only */
+#define   SDVOB_HOTPLUG_ENABLE			(1 << 23) /* SDVO only */
+
+/* Gen 6 (CPT) SDVO/HDMI bits: */
+#define   SDVO_PIPE_SEL_CPT(pipe)		((pipe) << 29)
+#define   SDVO_PIPE_SEL_MASK_CPT		(3 << 29)
+
 
 /* DVO port control */
 #define DVOA			0x61120
@@ -1898,7 +1951,7 @@
 #define PFIT_AUTO_RATIOS (dev_priv->info->display_mmio_offset + 0x61238)
 
 /* Backlight control */
-#define BLC_PWM_CTL2		0x61250 /* 965+ only */
+#define BLC_PWM_CTL2	(dev_priv->info->display_mmio_offset + 0x61250) /* 965+ only */
 #define   BLM_PWM_ENABLE		(1 << 31)
 #define   BLM_COMBINATION_MODE		(1 << 30) /* gen4 only */
 #define   BLM_PIPE_SELECT		(1 << 29)
@@ -1917,7 +1970,7 @@
 #define   BLM_PHASE_IN_COUNT_MASK	(0xff << 8)
 #define   BLM_PHASE_IN_INCR_SHIFT	(0)
 #define   BLM_PHASE_IN_INCR_MASK	(0xff << 0)
-#define BLC_PWM_CTL		0x61254
+#define BLC_PWM_CTL	(dev_priv->info->display_mmio_offset + 0x61254)
 /*
  * This is the most significant 15 bits of the number of backlight cycles in a
  * complete cycle of the modulated backlight control.
@@ -1939,7 +1992,7 @@
 #define   BACKLIGHT_DUTY_CYCLE_MASK_PNV		(0xfffe)
 #define   BLM_POLARITY_PNV			(1 << 0) /* pnv only */
 
-#define BLC_HIST_CTL		0x61260
+#define BLC_HIST_CTL	(dev_priv->info->display_mmio_offset + 0x61260)
 
 /* New registers for PCH-split platforms. Safe where new bits show up, the
  * register layout machtes with gen4 BLC_PWM_CTL[12]. */
@@ -2776,6 +2829,8 @@
 #define   DSPFW_HPLL_CURSOR_SHIFT	16
 #define   DSPFW_HPLL_CURSOR_MASK	(0x3f<<16)
 #define   DSPFW_HPLL_SR_MASK		(0x1ff)
+#define DSPFW4			(dev_priv->info->display_mmio_offset + 0x70070)
+#define DSPFW7			(dev_priv->info->display_mmio_offset + 0x7007c)
 
 /* drain latency register values*/
 #define DRAIN_LATENCY_PRECISION_32	32
@@ -3233,6 +3288,63 @@
 #define SPRGAMC(pipe) _PIPE(pipe, _SPRA_GAMC, _SPRB_GAMC)
 #define SPRSURFLIVE(pipe) _PIPE(pipe, _SPRA_SURFLIVE, _SPRB_SURFLIVE)
 
+#define _SPACNTR		0x72180
+#define   SP_ENABLE			(1<<31)
+#define   SP_GEAMMA_ENABLE		(1<<30)
+#define   SP_PIXFORMAT_MASK		(0xf<<26)
+#define   SP_FORMAT_YUV422		(0<<26)
+#define   SP_FORMAT_BGR565		(5<<26)
+#define   SP_FORMAT_BGRX8888		(6<<26)
+#define   SP_FORMAT_BGRA8888		(7<<26)
+#define   SP_FORMAT_RGBX1010102		(8<<26)
+#define   SP_FORMAT_RGBA1010102		(9<<26)
+#define   SP_FORMAT_RGBX8888		(0xe<<26)
+#define   SP_FORMAT_RGBA8888		(0xf<<26)
+#define   SP_SOURCE_KEY			(1<<22)
+#define   SP_YUV_BYTE_ORDER_MASK	(3<<16)
+#define   SP_YUV_ORDER_YUYV		(0<<16)
+#define   SP_YUV_ORDER_UYVY		(1<<16)
+#define   SP_YUV_ORDER_YVYU		(2<<16)
+#define   SP_YUV_ORDER_VYUY		(3<<16)
+#define   SP_TILED			(1<<10)
+#define _SPALINOFF		0x72184
+#define _SPASTRIDE		0x72188
+#define _SPAPOS			0x7218c
+#define _SPASIZE		0x72190
+#define _SPAKEYMINVAL		0x72194
+#define _SPAKEYMSK		0x72198
+#define _SPASURF		0x7219c
+#define _SPAKEYMAXVAL		0x721a0
+#define _SPATILEOFF		0x721a4
+#define _SPACONSTALPHA		0x721a8
+#define _SPAGAMC		0x721f4
+
+#define _SPBCNTR		0x72280
+#define _SPBLINOFF		0x72284
+#define _SPBSTRIDE		0x72288
+#define _SPBPOS			0x7228c
+#define _SPBSIZE		0x72290
+#define _SPBKEYMINVAL		0x72294
+#define _SPBKEYMSK		0x72298
+#define _SPBSURF		0x7229c
+#define _SPBKEYMAXVAL		0x722a0
+#define _SPBTILEOFF		0x722a4
+#define _SPBCONSTALPHA		0x722a8
+#define _SPBGAMC		0x722f4
+
+#define SPCNTR(pipe, plane) _PIPE(pipe * 2 + plane, _SPACNTR, _SPBCNTR)
+#define SPLINOFF(pipe, plane) _PIPE(pipe * 2 + plane, _SPALINOFF, _SPBLINOFF)
+#define SPSTRIDE(pipe, plane) _PIPE(pipe * 2 + plane, _SPASTRIDE, _SPBSTRIDE)
+#define SPPOS(pipe, plane) _PIPE(pipe * 2 + plane, _SPAPOS, _SPBPOS)
+#define SPSIZE(pipe, plane) _PIPE(pipe * 2 + plane, _SPASIZE, _SPBSIZE)
+#define SPKEYMINVAL(pipe, plane) _PIPE(pipe * 2 + plane, _SPAKEYMINVAL, _SPBKEYMINVAL)
+#define SPKEYMSK(pipe, plane) _PIPE(pipe * 2 + plane, _SPAKEYMSK, _SPBKEYMSK)
+#define SPSURF(pipe, plane) _PIPE(pipe * 2 + plane, _SPASURF, _SPBSURF)
+#define SPKEYMAXVAL(pipe, plane) _PIPE(pipe * 2 + plane, _SPAKEYMAXVAL, _SPBKEYMAXVAL)
+#define SPTILEOFF(pipe, plane) _PIPE(pipe * 2 + plane, _SPATILEOFF, _SPBTILEOFF)
+#define SPCONSTALPHA(pipe, plane) _PIPE(pipe * 2 + plane, _SPACONSTALPHA, _SPBCONSTALPHA)
+#define SPGAMC(pipe, plane) _PIPE(pipe * 2 + plane, _SPAGAMC, _SPBGAMC)
+
 /* VBIOS regs */
 #define VGACNTRL		0x71400
 # define VGA_DISP_DISABLE			(1 << 31)
@@ -3508,7 +3620,11 @@
 #define SDE_PORTC_HOTPLUG       (1 << 9)
 #define SDE_PORTB_HOTPLUG       (1 << 8)
 #define SDE_SDVOB_HOTPLUG       (1 << 6)
-#define SDE_HOTPLUG_MASK	(0xf << 8)
+#define SDE_HOTPLUG_MASK        (SDE_CRT_HOTPLUG | \
+				 SDE_SDVOB_HOTPLUG |	\
+				 SDE_PORTB_HOTPLUG |	\
+				 SDE_PORTC_HOTPLUG |	\
+				 SDE_PORTD_HOTPLUG)
 #define SDE_TRANSB_CRC_DONE	(1 << 5)
 #define SDE_TRANSB_CRC_ERR	(1 << 4)
 #define SDE_TRANSB_FIFO_UNDER	(1 << 3)
@@ -3531,7 +3647,9 @@
 #define SDE_PORTC_HOTPLUG_CPT	(1 << 22)
 #define SDE_PORTB_HOTPLUG_CPT	(1 << 21)
 #define SDE_CRT_HOTPLUG_CPT	(1 << 19)
+#define SDE_SDVOB_HOTPLUG_CPT	(1 << 18)
 #define SDE_HOTPLUG_MASK_CPT	(SDE_CRT_HOTPLUG_CPT |		\
+				 SDE_SDVOB_HOTPLUG_CPT |	\
 				 SDE_PORTD_HOTPLUG_CPT |	\
 				 SDE_PORTC_HOTPLUG_CPT |	\
 				 SDE_PORTB_HOTPLUG_CPT)
@@ -3754,14 +3872,16 @@
 #define HSW_VIDEO_DIP_VSC_ECC_B		0x61344
 #define HSW_VIDEO_DIP_GCP_B		0x61210
 
-#define HSW_TVIDEO_DIP_CTL(pipe) \
-	 _PIPE(pipe, HSW_VIDEO_DIP_CTL_A, HSW_VIDEO_DIP_CTL_B)
-#define HSW_TVIDEO_DIP_AVI_DATA(pipe) \
-	 _PIPE(pipe, HSW_VIDEO_DIP_AVI_DATA_A, HSW_VIDEO_DIP_AVI_DATA_B)
-#define HSW_TVIDEO_DIP_SPD_DATA(pipe) \
-	 _PIPE(pipe, HSW_VIDEO_DIP_SPD_DATA_A, HSW_VIDEO_DIP_SPD_DATA_B)
-#define HSW_TVIDEO_DIP_GCP(pipe) \
-	_PIPE(pipe, HSW_VIDEO_DIP_GCP_A, HSW_VIDEO_DIP_GCP_B)
+#define HSW_TVIDEO_DIP_CTL(trans) \
+	 _TRANSCODER(trans, HSW_VIDEO_DIP_CTL_A, HSW_VIDEO_DIP_CTL_B)
+#define HSW_TVIDEO_DIP_AVI_DATA(trans) \
+	 _TRANSCODER(trans, HSW_VIDEO_DIP_AVI_DATA_A, HSW_VIDEO_DIP_AVI_DATA_B)
+#define HSW_TVIDEO_DIP_SPD_DATA(trans) \
+	 _TRANSCODER(trans, HSW_VIDEO_DIP_SPD_DATA_A, HSW_VIDEO_DIP_SPD_DATA_B)
+#define HSW_TVIDEO_DIP_GCP(trans) \
+	_TRANSCODER(trans, HSW_VIDEO_DIP_GCP_A, HSW_VIDEO_DIP_GCP_B)
+#define HSW_TVIDEO_DIP_VSC_DATA(trans) \
+	 _TRANSCODER(trans, HSW_VIDEO_DIP_VSC_DATA_A, HSW_VIDEO_DIP_VSC_DATA_B)
 
 #define _TRANS_HTOTAL_B          0xe1000
 #define _TRANS_HBLANK_B          0xe1004
@@ -3976,34 +4096,6 @@
 #define FDI_PLL_CTL_1           0xfe000
 #define FDI_PLL_CTL_2           0xfe004
 
-/* or SDVOB */
-#define HDMIB   0xe1140
-#define  PORT_ENABLE    (1 << 31)
-#define  TRANSCODER(pipe)       ((pipe) << 30)
-#define  TRANSCODER_CPT(pipe)   ((pipe) << 29)
-#define  TRANSCODER_MASK        (1 << 30)
-#define  TRANSCODER_MASK_CPT    (3 << 29)
-#define  COLOR_FORMAT_8bpc      (0)
-#define  COLOR_FORMAT_12bpc     (3 << 26)
-#define  SDVOB_HOTPLUG_ENABLE   (1 << 23)
-#define  SDVO_ENCODING          (0)
-#define  TMDS_ENCODING          (2 << 10)
-#define  NULL_PACKET_VSYNC_ENABLE       (1 << 9)
-/* CPT */
-#define  HDMI_MODE_SELECT	(1 << 9)
-#define  DVI_MODE_SELECT	(0)
-#define  SDVOB_BORDER_ENABLE    (1 << 7)
-#define  AUDIO_ENABLE           (1 << 6)
-#define  VSYNC_ACTIVE_HIGH      (1 << 4)
-#define  HSYNC_ACTIVE_HIGH      (1 << 3)
-#define  PORT_DETECTED          (1 << 2)
-
-/* PCH SDVOB multiplex with HDMIB */
-#define PCH_SDVOB	HDMIB
-
-#define HDMIC   0xe1150
-#define HDMID   0xe1160
-
 #define PCH_LVDS	0xe1180
 #define  LVDS_DETECTED	(1 << 1)
 
@@ -4020,6 +4112,15 @@
 #define PIPEB_PP_OFF_DELAYS     (VLV_DISPLAY_BASE + 0x6130c)
 #define PIPEB_PP_DIVISOR        (VLV_DISPLAY_BASE + 0x61310)
 
+#define VLV_PIPE_PP_STATUS(pipe) _PIPE(pipe, PIPEA_PP_STATUS, PIPEB_PP_STATUS)
+#define VLV_PIPE_PP_CONTROL(pipe) _PIPE(pipe, PIPEA_PP_CONTROL, PIPEB_PP_CONTROL)
+#define VLV_PIPE_PP_ON_DELAYS(pipe) \
+		_PIPE(pipe, PIPEA_PP_ON_DELAYS, PIPEB_PP_ON_DELAYS)
+#define VLV_PIPE_PP_OFF_DELAYS(pipe) \
+		_PIPE(pipe, PIPEA_PP_OFF_DELAYS, PIPEB_PP_OFF_DELAYS)
+#define VLV_PIPE_PP_DIVISOR(pipe) \
+		_PIPE(pipe, PIPEA_PP_DIVISOR, PIPEB_PP_DIVISOR)
+
 #define PCH_PP_STATUS		0xc7200
 #define PCH_PP_CONTROL		0xc7204
 #define  PANEL_UNLOCK_REGS	(0xabcd << 16)
@@ -4149,8 +4250,12 @@
 #define  FORCEWAKE				0xA18C
 #define  FORCEWAKE_VLV				0x1300b0
 #define  FORCEWAKE_ACK_VLV			0x1300b4
+#define  FORCEWAKE_MEDIA_VLV			0x1300b8
+#define  FORCEWAKE_ACK_MEDIA_VLV		0x1300bc
 #define  FORCEWAKE_ACK_HSW			0x130044
 #define  FORCEWAKE_ACK				0x130090
+#define  VLV_GTLC_WAKE_CTRL			0x130090
+#define  VLV_GTLC_PW_STATUS			0x130094
 #define  FORCEWAKE_MT				0xa188 /* multi-threaded */
 #define   FORCEWAKE_KERNEL			0x1
 #define   FORCEWAKE_USER			0x2
@@ -4184,6 +4289,7 @@
 #define GEN6_RPNSWREQ				0xA008
 #define   GEN6_TURBO_DISABLE			(1<<31)
 #define   GEN6_FREQUENCY(x)			((x)<<25)
+#define   HSW_FREQUENCY(x)			((x)<<24)
 #define   GEN6_OFFSET(x)			((x)<<19)
 #define   GEN6_AGGRESSIVE_TURBO			(0<<15)
 #define GEN6_RC_VIDEO_FREQ			0xA00C
@@ -4275,6 +4381,20 @@
 #define GEN6_PCODE_DATA				0x138128
 #define   GEN6_PCODE_FREQ_IA_RATIO_SHIFT	8
 
+#define VLV_IOSF_DOORBELL_REQ			0x182100
+#define   IOSF_DEVFN_SHIFT			24
+#define   IOSF_OPCODE_SHIFT			16
+#define   IOSF_PORT_SHIFT			8
+#define   IOSF_BYTE_ENABLES_SHIFT		4
+#define   IOSF_BAR_SHIFT			1
+#define   IOSF_SB_BUSY				(1<<0)
+#define   IOSF_PORT_PUNIT			0x4
+#define VLV_IOSF_DATA				0x182104
+#define VLV_IOSF_ADDR				0x182108
+
+#define PUNIT_OPCODE_REG_READ			6
+#define PUNIT_OPCODE_REG_WRITE			7
+
 #define GEN6_GT_CORE_STATUS		0x138060
 #define   GEN6_CORE_CPD_STATE_MASK	(7<<4)
 #define   GEN6_RCn_MASK			7
diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c
index 2135f21..41f0fde 100644
--- a/drivers/gpu/drm/i915/i915_suspend.c
+++ b/drivers/gpu/drm/i915/i915_suspend.c
@@ -209,7 +209,8 @@ static void i915_save_display(struct drm_device *dev)
 		dev_priv->regfile.saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_PCH_CTL2);
 		dev_priv->regfile.saveBLC_CPU_PWM_CTL = I915_READ(BLC_PWM_CPU_CTL);
 		dev_priv->regfile.saveBLC_CPU_PWM_CTL2 = I915_READ(BLC_PWM_CPU_CTL2);
-		dev_priv->regfile.saveLVDS = I915_READ(PCH_LVDS);
+		if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
+			dev_priv->regfile.saveLVDS = I915_READ(PCH_LVDS);
 	} else {
 		dev_priv->regfile.savePP_CONTROL = I915_READ(PP_CONTROL);
 		dev_priv->regfile.savePFIT_PGM_RATIOS = I915_READ(PFIT_PGM_RATIOS);
@@ -255,6 +256,7 @@ static void i915_save_display(struct drm_device *dev)
 static void i915_restore_display(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 mask = 0xffffffff;
 
 	/* Display arbitration */
 	if (INTEL_INFO(dev)->gen <= 4)
@@ -267,10 +269,13 @@ static void i915_restore_display(struct drm_device *dev)
 	if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev))
 		I915_WRITE(BLC_PWM_CTL2, dev_priv->regfile.saveBLC_PWM_CTL2);
 
-	if (HAS_PCH_SPLIT(dev)) {
-		I915_WRITE(PCH_LVDS, dev_priv->regfile.saveLVDS);
-	} else if (IS_MOBILE(dev) && !IS_I830(dev))
-		I915_WRITE(LVDS, dev_priv->regfile.saveLVDS);
+	if (drm_core_check_feature(dev, DRIVER_MODESET))
+		mask = ~LVDS_PORT_EN;
+
+	if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
+		I915_WRITE(PCH_LVDS, dev_priv->regfile.saveLVDS & mask);
+	else if (INTEL_INFO(dev)->gen <= 4 && IS_MOBILE(dev) && !IS_I830(dev))
+		I915_WRITE(LVDS, dev_priv->regfile.saveLVDS & mask);
 
 	if (!IS_I830(dev) && !IS_845G(dev) && !HAS_PCH_SPLIT(dev))
 		I915_WRITE(PFIT_CONTROL, dev_priv->regfile.savePFIT_CONTROL);
diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
index 9462081..a3a3e22 100644
--- a/drivers/gpu/drm/i915/i915_sysfs.c
+++ b/drivers/gpu/drm/i915/i915_sysfs.c
@@ -49,7 +49,7 @@ static ssize_t
 show_rc6_mask(struct device *kdev, struct device_attribute *attr, char *buf)
 {
 	struct drm_minor *dminor = container_of(kdev, struct drm_minor, kdev);
-	return snprintf(buf, PAGE_SIZE, "%x", intel_enable_rc6(dminor->dev));
+	return snprintf(buf, PAGE_SIZE, "%x\n", intel_enable_rc6(dminor->dev));
 }
 
 static ssize_t
@@ -57,7 +57,7 @@ show_rc6_ms(struct device *kdev, struct device_attribute *attr, char *buf)
 {
 	struct drm_minor *dminor = container_of(kdev, struct drm_minor, kdev);
 	u32 rc6_residency = calc_residency(dminor->dev, GEN6_GT_GFX_RC6);
-	return snprintf(buf, PAGE_SIZE, "%u", rc6_residency);
+	return snprintf(buf, PAGE_SIZE, "%u\n", rc6_residency);
 }
 
 static ssize_t
@@ -65,7 +65,7 @@ show_rc6p_ms(struct device *kdev, struct device_attribute *attr, char *buf)
 {
 	struct drm_minor *dminor = container_of(kdev, struct drm_minor, kdev);
 	u32 rc6p_residency = calc_residency(dminor->dev, GEN6_GT_GFX_RC6p);
-	return snprintf(buf, PAGE_SIZE, "%u", rc6p_residency);
+	return snprintf(buf, PAGE_SIZE, "%u\n", rc6p_residency);
 }
 
 static ssize_t
@@ -73,7 +73,7 @@ show_rc6pp_ms(struct device *kdev, struct device_attribute *attr, char *buf)
 {
 	struct drm_minor *dminor = container_of(kdev, struct drm_minor, kdev);
 	u32 rc6pp_residency = calc_residency(dminor->dev, GEN6_GT_GFX_RC6pp);
-	return snprintf(buf, PAGE_SIZE, "%u", rc6pp_residency);
+	return snprintf(buf, PAGE_SIZE, "%u\n", rc6pp_residency);
 }
 
 static DEVICE_ATTR(rc6_enable, S_IRUGO, show_rc6_mask, NULL);
@@ -215,7 +215,7 @@ static ssize_t gt_cur_freq_mhz_show(struct device *kdev,
 	ret = dev_priv->rps.cur_delay * GT_FREQUENCY_MULTIPLIER;
 	mutex_unlock(&dev_priv->rps.hw_lock);
 
-	return snprintf(buf, PAGE_SIZE, "%d", ret);
+	return snprintf(buf, PAGE_SIZE, "%d\n", ret);
 }
 
 static ssize_t gt_max_freq_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf)
@@ -229,7 +229,7 @@ static ssize_t gt_max_freq_mhz_show(struct device *kdev, struct device_attribute
 	ret = dev_priv->rps.max_delay * GT_FREQUENCY_MULTIPLIER;
 	mutex_unlock(&dev_priv->rps.hw_lock);
 
-	return snprintf(buf, PAGE_SIZE, "%d", ret);
+	return snprintf(buf, PAGE_SIZE, "%d\n", ret);
 }
 
 static ssize_t gt_max_freq_mhz_store(struct device *kdev,
@@ -280,7 +280,7 @@ static ssize_t gt_min_freq_mhz_show(struct device *kdev, struct device_attribute
 	ret = dev_priv->rps.min_delay * GT_FREQUENCY_MULTIPLIER;
 	mutex_unlock(&dev_priv->rps.hw_lock);
 
-	return snprintf(buf, PAGE_SIZE, "%d", ret);
+	return snprintf(buf, PAGE_SIZE, "%d\n", ret);
 }
 
 static ssize_t gt_min_freq_mhz_store(struct device *kdev,
@@ -355,7 +355,7 @@ static ssize_t gt_rp_mhz_show(struct device *kdev, struct device_attribute *attr
 	} else {
 		BUG();
 	}
-	return snprintf(buf, PAGE_SIZE, "%d", val);
+	return snprintf(buf, PAGE_SIZE, "%d\n", val);
 }
 
 static const struct attribute *gen6_attrs[] = {
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index 32a3693..1d8d63a 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -45,6 +45,9 @@
 
 struct intel_crt {
 	struct intel_encoder base;
+	/* DPMS state is stored in the connector, which we need in the
+	 * encoder's enable/disable callbacks */
+	struct intel_connector *connector;
 	bool force_hotplug_required;
 	u32 adpa_reg;
 };
@@ -81,29 +84,6 @@ static bool intel_crt_get_hw_state(struct intel_encoder *encoder,
 	return true;
 }
 
-static void intel_disable_crt(struct intel_encoder *encoder)
-{
-	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
-	struct intel_crt *crt = intel_encoder_to_crt(encoder);
-	u32 temp;
-
-	temp = I915_READ(crt->adpa_reg);
-	temp |= ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE;
-	temp &= ~ADPA_DAC_ENABLE;
-	I915_WRITE(crt->adpa_reg, temp);
-}
-
-static void intel_enable_crt(struct intel_encoder *encoder)
-{
-	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
-	struct intel_crt *crt = intel_encoder_to_crt(encoder);
-	u32 temp;
-
-	temp = I915_READ(crt->adpa_reg);
-	temp |= ADPA_DAC_ENABLE;
-	I915_WRITE(crt->adpa_reg, temp);
-}
-
 /* Note: The caller is required to filter out dpms modes not supported by the
  * platform. */
 static void intel_crt_set_dpms(struct intel_encoder *encoder, int mode)
@@ -135,6 +115,19 @@ static void intel_crt_set_dpms(struct intel_encoder *encoder, int mode)
 	I915_WRITE(crt->adpa_reg, temp);
 }
 
+static void intel_disable_crt(struct intel_encoder *encoder)
+{
+	intel_crt_set_dpms(encoder, DRM_MODE_DPMS_OFF);
+}
+
+static void intel_enable_crt(struct intel_encoder *encoder)
+{
+	struct intel_crt *crt = intel_encoder_to_crt(encoder);
+
+	intel_crt_set_dpms(encoder, crt->connector->base.dpms);
+}
+
+
 static void intel_crt_dpms(struct drm_connector *connector, int mode)
 {
 	struct drm_device *dev = connector->dev;
@@ -206,10 +199,14 @@ static int intel_crt_mode_valid(struct drm_connector *connector,
 	return MODE_OK;
 }
 
-static bool intel_crt_mode_fixup(struct drm_encoder *encoder,
-				 const struct drm_display_mode *mode,
-				 struct drm_display_mode *adjusted_mode)
+static bool intel_crt_compute_config(struct intel_encoder *encoder,
+				     struct intel_crtc_config *pipe_config)
 {
+	struct drm_device *dev = encoder->base.dev;
+
+	if (HAS_PCH_SPLIT(dev))
+		pipe_config->has_pch_encoder = true;
+
 	return true;
 }
 
@@ -683,7 +680,6 @@ static void intel_crt_reset(struct drm_connector *connector)
  */
 
 static const struct drm_encoder_helper_funcs crt_encoder_funcs = {
-	.mode_fixup = intel_crt_mode_fixup,
 	.mode_set = intel_crt_mode_set,
 };
 
@@ -746,6 +742,7 @@ void intel_crt_init(struct drm_device *dev)
 	}
 
 	connector = &intel_connector->base;
+	crt->connector = intel_connector;
 	drm_connector_init(dev, &intel_connector->base,
 			   &intel_crt_connector_funcs, DRM_MODE_CONNECTOR_VGA);
 
@@ -774,8 +771,11 @@ void intel_crt_init(struct drm_device *dev)
 	else
 		crt->adpa_reg = ADPA;
 
+	crt->base.compute_config = intel_crt_compute_config;
 	crt->base.disable = intel_disable_crt;
 	crt->base.enable = intel_enable_crt;
+	if (I915_HAS_HOTPLUG(dev))
+		crt->base.hpd_pin = HPD_CRT;
 	if (HAS_DDI(dev))
 		crt->base.get_hw_state = intel_ddi_get_hw_state;
 	else
@@ -797,8 +797,6 @@ void intel_crt_init(struct drm_device *dev)
 	 */
 	crt->force_hotplug_required = 0;
 
-	dev_priv->hotplug_supported_mask |= CRT_HOTPLUG_INT_STATUS;
-
 	/*
 	 * TODO: find a proper way to discover whether we need to set the the
 	 * polarity and link reversal bits or not, instead of relying on the
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 8d0bac3..22524cb 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -898,6 +898,9 @@ bool intel_ddi_pll_mode_set(struct drm_crtc *crtc, int clock)
 			plls->spll_refcount++;
 			reg = SPLL_CTL;
 			intel_crtc->ddi_pll_sel = PORT_CLK_SEL_SPLL;
+		} else {
+			DRM_ERROR("SPLL already in use\n");
+			return false;
 		}
 
 		WARN(I915_READ(reg) & SPLL_PLL_ENABLE,
@@ -928,7 +931,7 @@ void intel_ddi_set_pipe_settings(struct drm_crtc *crtc)
 	if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) {
 
 		temp = TRANS_MSA_SYNC_CLK;
-		switch (intel_crtc->bpp) {
+		switch (intel_crtc->config.pipe_bpp) {
 		case 18:
 			temp |= TRANS_MSA_6_BPC;
 			break;
@@ -942,15 +945,13 @@ void intel_ddi_set_pipe_settings(struct drm_crtc *crtc)
 			temp |= TRANS_MSA_12_BPC;
 			break;
 		default:
-			temp |= TRANS_MSA_8_BPC;
-			WARN(1, "%d bpp unsupported by DDI function\n",
-			     intel_crtc->bpp);
+			BUG();
 		}
 		I915_WRITE(TRANS_MSA_MISC(cpu_transcoder), temp);
 	}
 }
 
-void intel_ddi_enable_pipe_func(struct drm_crtc *crtc)
+void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc)
 {
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc);
@@ -966,7 +967,7 @@ void intel_ddi_enable_pipe_func(struct drm_crtc *crtc)
 	temp = TRANS_DDI_FUNC_ENABLE;
 	temp |= TRANS_DDI_SELECT_PORT(port);
 
-	switch (intel_crtc->bpp) {
+	switch (intel_crtc->config.pipe_bpp) {
 	case 18:
 		temp |= TRANS_DDI_BPC_6;
 		break;
@@ -980,8 +981,7 @@ void intel_ddi_enable_pipe_func(struct drm_crtc *crtc)
 		temp |= TRANS_DDI_BPC_12;
 		break;
 	default:
-		WARN(1, "%d bpp unsupported by transcoder DDI function\n",
-		     intel_crtc->bpp);
+		BUG();
 	}
 
 	if (crtc->mode.flags & DRM_MODE_FLAG_PVSYNC)
@@ -1150,14 +1150,14 @@ bool intel_ddi_get_hw_state(struct intel_encoder *encoder,
 
 	DRM_DEBUG_KMS("No pipe for ddi port %i found\n", port);
 
-	return true;
+	return false;
 }
 
 static uint32_t intel_ddi_get_crtc_pll(struct drm_i915_private *dev_priv,
 				       enum pipe pipe)
 {
 	uint32_t temp, ret;
-	enum port port;
+	enum port port = I915_MAX_PORTS;
 	enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv,
 								      pipe);
 	int i;
@@ -1173,10 +1173,16 @@ static uint32_t intel_ddi_get_crtc_pll(struct drm_i915_private *dev_priv,
 				port = i;
 	}
 
-	ret = I915_READ(PORT_CLK_SEL(port));
-
-	DRM_DEBUG_KMS("Pipe %c connected to port %c using clock 0x%08x\n",
-		      pipe_name(pipe), port_name(port), ret);
+	if (port == I915_MAX_PORTS) {
+		WARN(1, "Pipe %c enabled on an unknown port\n",
+		     pipe_name(pipe));
+		ret = PORT_CLK_SEL_NONE;
+	} else {
+		ret = I915_READ(PORT_CLK_SEL(port));
+		DRM_DEBUG_KMS("Pipe %c connected to port %c using clock "
+			      "0x%08x\n", pipe_name(pipe), port_name(port),
+			      ret);
+	}
 
 	return ret;
 }
@@ -1341,15 +1347,15 @@ static void intel_disable_ddi(struct intel_encoder *intel_encoder)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	uint32_t tmp;
 
+	tmp = I915_READ(HSW_AUD_PIN_ELD_CP_VLD);
+	tmp &= ~((AUDIO_OUTPUT_ENABLE_A | AUDIO_ELD_VALID_A) << (pipe * 4));
+	I915_WRITE(HSW_AUD_PIN_ELD_CP_VLD, tmp);
+
 	if (type == INTEL_OUTPUT_EDP) {
 		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
 
 		ironlake_edp_backlight_off(intel_dp);
 	}
-
-	tmp = I915_READ(HSW_AUD_PIN_ELD_CP_VLD);
-	tmp &= ~((AUDIO_OUTPUT_ENABLE_A | AUDIO_ELD_VALID_A) << (pipe * 4));
-	I915_WRITE(HSW_AUD_PIN_ELD_CP_VLD, tmp);
 }
 
 int intel_ddi_get_cdclk_freq(struct drm_i915_private *dev_priv)
@@ -1467,19 +1473,17 @@ static void intel_ddi_destroy(struct drm_encoder *encoder)
 	intel_dp_encoder_destroy(encoder);
 }
 
-static bool intel_ddi_mode_fixup(struct drm_encoder *encoder,
-				 const struct drm_display_mode *mode,
-				 struct drm_display_mode *adjusted_mode)
+static bool intel_ddi_compute_config(struct intel_encoder *encoder,
+				     struct intel_crtc_config *pipe_config)
 {
-	struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
-	int type = intel_encoder->type;
+	int type = encoder->type;
 
-	WARN(type == INTEL_OUTPUT_UNKNOWN, "mode_fixup() on unknown output!\n");
+	WARN(type == INTEL_OUTPUT_UNKNOWN, "compute_config() on unknown output!\n");
 
 	if (type == INTEL_OUTPUT_HDMI)
-		return intel_hdmi_mode_fixup(encoder, mode, adjusted_mode);
+		return intel_hdmi_compute_config(encoder, pipe_config);
 	else
-		return intel_dp_mode_fixup(encoder, mode, adjusted_mode);
+		return intel_dp_compute_config(encoder, pipe_config);
 }
 
 static const struct drm_encoder_funcs intel_ddi_funcs = {
@@ -1487,7 +1491,6 @@ static const struct drm_encoder_funcs intel_ddi_funcs = {
 };
 
 static const struct drm_encoder_helper_funcs intel_ddi_helper_funcs = {
-	.mode_fixup = intel_ddi_mode_fixup,
 	.mode_set = intel_ddi_mode_set,
 };
 
@@ -1527,6 +1530,7 @@ void intel_ddi_init(struct drm_device *dev, enum port port)
 			 DRM_MODE_ENCODER_TMDS);
 	drm_encoder_helper_add(encoder, &intel_ddi_helper_funcs);
 
+	intel_encoder->compute_config = intel_ddi_compute_config;
 	intel_encoder->enable = intel_enable_ddi;
 	intel_encoder->pre_enable = intel_ddi_pre_enable;
 	intel_encoder->disable = intel_disable_ddi;
@@ -1537,9 +1541,7 @@ void intel_ddi_init(struct drm_device *dev, enum port port)
 	intel_dig_port->port_reversal = I915_READ(DDI_BUF_CTL(port)) &
 					DDI_BUF_PORT_REVERSAL;
 	if (hdmi_connector)
-		intel_dig_port->hdmi.sdvox_reg = DDI_BUF_CTL(port);
-	else
-		intel_dig_port->hdmi.sdvox_reg = 0;
+		intel_dig_port->hdmi.hdmi_reg = DDI_BUF_CTL(port);
 	intel_dig_port->dp.output_reg = DDI_BUF_CTL(port);
 
 	intel_encoder->type = INTEL_OUTPUT_UNKNOWN;
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index b20d501..1b2c744 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -71,8 +71,24 @@ typedef struct intel_limit intel_limit_t;
 struct intel_limit {
 	intel_range_t   dot, vco, n, m, m1, m2, p, p1;
 	intel_p2_t	    p2;
-	bool (* find_pll)(const intel_limit_t *, struct drm_crtc *,
-			int, int, intel_clock_t *, intel_clock_t *);
+	/**
+	 * find_pll() - Find the best values for the PLL
+	 * @limit: limits for the PLL
+	 * @crtc: current CRTC
+	 * @target: target frequency in kHz
+	 * @refclk: reference clock frequency in kHz
+	 * @match_clock: if provided, @best_clock P divider must
+	 *               match the P divider from @match_clock
+	 *               used for LVDS downclocking
+	 * @best_clock: best PLL values found
+	 *
+	 * Returns true on success, false on failure.
+	 */
+	bool (*find_pll)(const intel_limit_t *limit,
+			 struct drm_crtc *crtc,
+			 int target, int refclk,
+			 intel_clock_t *match_clock,
+			 intel_clock_t *best_clock);
 };
 
 /* FDI */
@@ -98,15 +114,6 @@ intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
 			intel_clock_t *best_clock);
 
 static bool
-intel_find_pll_g4x_dp(const intel_limit_t *, struct drm_crtc *crtc,
-		      int target, int refclk, intel_clock_t *match_clock,
-		      intel_clock_t *best_clock);
-static bool
-intel_find_pll_ironlake_dp(const intel_limit_t *, struct drm_crtc *crtc,
-			   int target, int refclk, intel_clock_t *match_clock,
-			   intel_clock_t *best_clock);
-
-static bool
 intel_vlv_find_best_pll(const intel_limit_t *limit, struct drm_crtc *crtc,
 			int target, int refclk, intel_clock_t *match_clock,
 			intel_clock_t *best_clock);
@@ -238,20 +245,6 @@ static const intel_limit_t intel_limits_g4x_dual_channel_lvds = {
 	.find_pll = intel_g4x_find_best_PLL,
 };
 
-static const intel_limit_t intel_limits_g4x_display_port = {
-	.dot = { .min = 161670, .max = 227000 },
-	.vco = { .min = 1750000, .max = 3500000},
-	.n = { .min = 1, .max = 2 },
-	.m = { .min = 97, .max = 108 },
-	.m1 = { .min = 0x10, .max = 0x12 },
-	.m2 = { .min = 0x05, .max = 0x06 },
-	.p = { .min = 10, .max = 20 },
-	.p1 = { .min = 1, .max = 2},
-	.p2 = { .dot_limit = 0,
-		.p2_slow = 10, .p2_fast = 10 },
-	.find_pll = intel_find_pll_g4x_dp,
-};
-
 static const intel_limit_t intel_limits_pineview_sdvo = {
 	.dot = { .min = 20000, .max = 400000},
 	.vco = { .min = 1700000, .max = 3500000 },
@@ -358,20 +351,6 @@ static const intel_limit_t intel_limits_ironlake_dual_lvds_100m = {
 	.find_pll = intel_g4x_find_best_PLL,
 };
 
-static const intel_limit_t intel_limits_ironlake_display_port = {
-	.dot = { .min = 25000, .max = 350000 },
-	.vco = { .min = 1760000, .max = 3510000},
-	.n = { .min = 1, .max = 2 },
-	.m = { .min = 81, .max = 90 },
-	.m1 = { .min = 12, .max = 22 },
-	.m2 = { .min = 5, .max = 9 },
-	.p = { .min = 10, .max = 20 },
-	.p1 = { .min = 1, .max = 2},
-	.p2 = { .dot_limit = 0,
-		.p2_slow = 10, .p2_fast = 10 },
-	.find_pll = intel_find_pll_ironlake_dp,
-};
-
 static const intel_limit_t intel_limits_vlv_dac = {
 	.dot = { .min = 25000, .max = 270000 },
 	.vco = { .min = 4000000, .max = 6000000 },
@@ -471,7 +450,6 @@ static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc,
 
 	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
 		if (intel_is_dual_link_lvds(dev)) {
-			/* LVDS dual channel */
 			if (refclk == 100000)
 				limit = &intel_limits_ironlake_dual_lvds_100m;
 			else
@@ -482,10 +460,7 @@ static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc,
 			else
 				limit = &intel_limits_ironlake_single_lvds;
 		}
-	} else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT) ||
-		   intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP))
-		limit = &intel_limits_ironlake_display_port;
-	else
+	} else
 		limit = &intel_limits_ironlake_dac;
 
 	return limit;
@@ -498,18 +473,14 @@ static const intel_limit_t *intel_g4x_limit(struct drm_crtc *crtc)
 
 	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
 		if (intel_is_dual_link_lvds(dev))
-			/* LVDS with dual channel */
 			limit = &intel_limits_g4x_dual_channel_lvds;
 		else
-			/* LVDS with dual channel */
 			limit = &intel_limits_g4x_single_channel_lvds;
 	} else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI) ||
 		   intel_pipe_has_type(crtc, INTEL_OUTPUT_ANALOG)) {
 		limit = &intel_limits_g4x_hdmi;
 	} else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_SDVO)) {
 		limit = &intel_limits_g4x_sdvo;
-	} else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) {
-		limit = &intel_limits_g4x_display_port;
 	} else /* The option is for other outputs */
 		limit = &intel_limits_i9xx_sdvo;
 
@@ -752,59 +723,6 @@ intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
 }
 
 static bool
-intel_find_pll_ironlake_dp(const intel_limit_t *limit, struct drm_crtc *crtc,
-			   int target, int refclk, intel_clock_t *match_clock,
-			   intel_clock_t *best_clock)
-{
-	struct drm_device *dev = crtc->dev;
-	intel_clock_t clock;
-
-	if (target < 200000) {
-		clock.n = 1;
-		clock.p1 = 2;
-		clock.p2 = 10;
-		clock.m1 = 12;
-		clock.m2 = 9;
-	} else {
-		clock.n = 2;
-		clock.p1 = 1;
-		clock.p2 = 10;
-		clock.m1 = 14;
-		clock.m2 = 8;
-	}
-	intel_clock(dev, refclk, &clock);
-	memcpy(best_clock, &clock, sizeof(intel_clock_t));
-	return true;
-}
-
-/* DisplayPort has only two frequencies, 162MHz and 270MHz */
-static bool
-intel_find_pll_g4x_dp(const intel_limit_t *limit, struct drm_crtc *crtc,
-		      int target, int refclk, intel_clock_t *match_clock,
-		      intel_clock_t *best_clock)
-{
-	intel_clock_t clock;
-	if (target < 200000) {
-		clock.p1 = 2;
-		clock.p2 = 10;
-		clock.n = 2;
-		clock.m1 = 23;
-		clock.m2 = 8;
-	} else {
-		clock.p1 = 1;
-		clock.p2 = 10;
-		clock.n = 1;
-		clock.m1 = 14;
-		clock.m2 = 2;
-	}
-	clock.m = 5 * (clock.m1 + 2) + (clock.m2 + 2);
-	clock.p = (clock.p1 * clock.p2);
-	clock.dot = 96000 * clock.m / (clock.n + 2) / clock.p;
-	clock.vco = 0;
-	memcpy(best_clock, &clock, sizeof(intel_clock_t));
-	return true;
-}
-static bool
 intel_vlv_find_best_pll(const intel_limit_t *limit, struct drm_crtc *crtc,
 			int target, int refclk, intel_clock_t *match_clock,
 			intel_clock_t *best_clock)
@@ -1254,7 +1172,7 @@ static void assert_planes_disabled(struct drm_i915_private *dev_priv,
 	int cur_pipe;
 
 	/* Planes are fixed to pipes on ILK+ */
-	if (HAS_PCH_SPLIT(dev_priv->dev)) {
+	if (HAS_PCH_SPLIT(dev_priv->dev) || IS_VALLEYVIEW(dev_priv->dev)) {
 		reg = DSPCNTR(pipe);
 		val = I915_READ(reg);
 		WARN((val & DISPLAY_PLANE_ENABLE),
@@ -1275,6 +1193,25 @@ static void assert_planes_disabled(struct drm_i915_private *dev_priv,
 	}
 }
 
+static void assert_sprites_disabled(struct drm_i915_private *dev_priv,
+				    enum pipe pipe)
+{
+	int reg, i;
+	u32 val;
+
+	if (!IS_VALLEYVIEW(dev_priv->dev))
+		return;
+
+	/* Need to check both planes against the pipe */
+	for (i = 0; i < dev_priv->num_plane; i++) {
+		reg = SPCNTR(pipe, i);
+		val = I915_READ(reg);
+		WARN((val & SP_ENABLE),
+		     "sprite %d assertion failure, should be off on pipe %c but is still active\n",
+		     pipe * 2 + i, pipe_name(pipe));
+	}
+}
+
 static void assert_pch_refclk_enabled(struct drm_i915_private *dev_priv)
 {
 	u32 val;
@@ -1327,14 +1264,14 @@ static bool dp_pipe_enabled(struct drm_i915_private *dev_priv,
 static bool hdmi_pipe_enabled(struct drm_i915_private *dev_priv,
 			      enum pipe pipe, u32 val)
 {
-	if ((val & PORT_ENABLE) == 0)
+	if ((val & SDVO_ENABLE) == 0)
 		return false;
 
 	if (HAS_PCH_CPT(dev_priv->dev)) {
-		if ((val & PORT_TRANS_SEL_MASK) != PORT_TRANS_SEL_CPT(pipe))
+		if ((val & SDVO_PIPE_SEL_MASK_CPT) != SDVO_PIPE_SEL_CPT(pipe))
 			return false;
 	} else {
-		if ((val & TRANSCODER_MASK) != TRANSCODER(pipe))
+		if ((val & SDVO_PIPE_SEL_MASK) != SDVO_PIPE_SEL(pipe))
 			return false;
 	}
 	return true;
@@ -1392,7 +1329,7 @@ static void assert_pch_hdmi_disabled(struct drm_i915_private *dev_priv,
 	     "PCH HDMI (0x%08x) enabled on transcoder %c, should be disabled\n",
 	     reg, pipe_name(pipe));
 
-	WARN(HAS_PCH_IBX(dev_priv->dev) && (val & PORT_ENABLE) == 0
+	WARN(HAS_PCH_IBX(dev_priv->dev) && (val & SDVO_ENABLE) == 0
 	     && (val & SDVO_PIPE_B_SELECT),
 	     "IBX PCH hdmi port still using transcoder B\n");
 }
@@ -1419,9 +1356,9 @@ static void assert_pch_ports_disabled(struct drm_i915_private *dev_priv,
 	     "PCH LVDS enabled on transcoder %c, should be disabled\n",
 	     pipe_name(pipe));
 
-	assert_pch_hdmi_disabled(dev_priv, pipe, HDMIB);
-	assert_pch_hdmi_disabled(dev_priv, pipe, HDMIC);
-	assert_pch_hdmi_disabled(dev_priv, pipe, HDMID);
+	assert_pch_hdmi_disabled(dev_priv, pipe, PCH_HDMIB);
+	assert_pch_hdmi_disabled(dev_priv, pipe, PCH_HDMIC);
+	assert_pch_hdmi_disabled(dev_priv, pipe, PCH_HDMID);
 }
 
 /**
@@ -1859,6 +1796,7 @@ static void intel_disable_pipe(struct drm_i915_private *dev_priv,
 	 * or we might hang the display.
 	 */
 	assert_planes_disabled(dev_priv, pipe);
+	assert_sprites_disabled(dev_priv, pipe);
 
 	/* Don't disable pipe A or pipe A PLLs if needed */
 	if (pipe == PIPE_A && (dev_priv->quirks & QUIRK_PIPEA_FORCE))
@@ -1937,6 +1875,15 @@ static void intel_disable_plane(struct drm_i915_private *dev_priv,
 	intel_wait_for_vblank(dev_priv->dev, pipe);
 }
 
+static bool need_vtd_wa(struct drm_device *dev)
+{
+#ifdef CONFIG_INTEL_IOMMU
+	if (INTEL_INFO(dev)->gen >= 6 && intel_iommu_gfx_mapped)
+		return true;
+#endif
+	return false;
+}
+
 int
 intel_pin_and_fence_fb_obj(struct drm_device *dev,
 			   struct drm_i915_gem_object *obj,
@@ -1967,6 +1914,14 @@ intel_pin_and_fence_fb_obj(struct drm_device *dev,
 		BUG();
 	}
 
+	/* Note that the w/a also requires 64 PTE of padding following the
+	 * bo. We currently fill all unused PTE with the shadow page and so
+	 * we should always have valid PTE following the scanout preventing
+	 * the VT-d warning.
+	 */
+	if (need_vtd_wa(dev) && alignment < 256 * 1024)
+		alignment = 256 * 1024;
+
 	dev_priv->mm.interruptible = false;
 	ret = i915_gem_object_pin_to_display_plane(obj, alignment, pipelined);
 	if (ret)
@@ -2083,8 +2038,7 @@ static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb,
 		dspcntr |= DISPPLANE_RGBX101010;
 		break;
 	default:
-		DRM_ERROR("Unknown pixel format 0x%08x\n", fb->pixel_format);
-		return -EINVAL;
+		BUG();
 	}
 
 	if (INTEL_INFO(dev)->gen >= 4) {
@@ -2177,8 +2131,7 @@ static int ironlake_update_plane(struct drm_crtc *crtc,
 		dspcntr |= DISPPLANE_RGBX101010;
 		break;
 	default:
-		DRM_ERROR("Unknown pixel format 0x%08x\n", fb->pixel_format);
-		return -EINVAL;
+		BUG();
 	}
 
 	if (obj->tiling_mode != I915_TILING_NONE)
@@ -2229,6 +2182,44 @@ intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb,
 	return dev_priv->display.update_plane(crtc, fb, x, y);
 }
 
+void intel_display_handle_reset(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_crtc *crtc;
+
+	/*
+	 * Flips in the rings have been nuked by the reset,
+	 * so complete all pending flips so that user space
+	 * will get its events and not get stuck.
+	 *
+	 * Also update the base address of all primary
+	 * planes to the the last fb to make sure we're
+	 * showing the correct fb after a reset.
+	 *
+	 * Need to make two loops over the crtcs so that we
+	 * don't try to grab a crtc mutex before the
+	 * pending_flip_queue really got woken up.
+	 */
+
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+		enum plane plane = intel_crtc->plane;
+
+		intel_prepare_page_flip(dev, plane);
+		intel_finish_page_flip_plane(dev, plane);
+	}
+
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+
+		mutex_lock(&crtc->mutex);
+		if (intel_crtc->active)
+			dev_priv->display.update_plane(crtc, crtc->fb,
+						       crtc->x, crtc->y);
+		mutex_unlock(&crtc->mutex);
+	}
+}
+
 static int
 intel_finish_fb(struct drm_framebuffer *old_fb)
 {
@@ -2295,10 +2286,10 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
 		return 0;
 	}
 
-	if(intel_crtc->plane > dev_priv->num_pipe) {
+	if (intel_crtc->plane > INTEL_INFO(dev)->num_pipes) {
 		DRM_ERROR("no plane for crtc: plane %d, num_pipes %d\n",
 				intel_crtc->plane,
-				dev_priv->num_pipe);
+				INTEL_INFO(dev)->num_pipes);
 		return -EINVAL;
 	}
 
@@ -2312,9 +2303,6 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
 		return ret;
 	}
 
-	if (crtc->fb)
-		intel_finish_fb(crtc->fb);
-
 	ret = dev_priv->display.update_plane(crtc, fb, x, y);
 	if (ret) {
 		intel_unpin_fb_obj(to_intel_framebuffer(fb)->obj);
@@ -2912,32 +2900,6 @@ static void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc)
 	mutex_unlock(&dev->struct_mutex);
 }
 
-static bool ironlake_crtc_driving_pch(struct drm_crtc *crtc)
-{
-	struct drm_device *dev = crtc->dev;
-	struct intel_encoder *intel_encoder;
-
-	/*
-	 * If there's a non-PCH eDP on this crtc, it must be DP_A, and that
-	 * must be driven by its own crtc; no sharing is possible.
-	 */
-	for_each_encoder_on_crtc(dev, crtc, intel_encoder) {
-		switch (intel_encoder->type) {
-		case INTEL_OUTPUT_EDP:
-			if (!intel_encoder_is_pch_edp(&intel_encoder->base))
-				return false;
-			continue;
-		}
-	}
-
-	return true;
-}
-
-static bool haswell_crtc_driving_pch(struct drm_crtc *crtc)
-{
-	return intel_pipe_has_type(crtc, INTEL_OUTPUT_ANALOG);
-}
-
 /* Program iCLKIP clock to the desired frequency */
 static void lpt_program_iclkip(struct drm_crtc *crtc)
 {
@@ -3273,7 +3235,6 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 	int pipe = intel_crtc->pipe;
 	int plane = intel_crtc->plane;
 	u32 temp;
-	bool is_pch_port;
 
 	WARN_ON(!crtc->enabled);
 
@@ -3289,9 +3250,8 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 			I915_WRITE(PCH_LVDS, temp | LVDS_PORT_EN);
 	}
 
-	is_pch_port = ironlake_crtc_driving_pch(crtc);
 
-	if (is_pch_port) {
+	if (intel_crtc->config.has_pch_encoder) {
 		/* Note: FDI PLL enabling _must_ be done before we enable the
 		 * cpu pipes, hence this is separate from all the other fdi/pch
 		 * enabling. */
@@ -3328,10 +3288,11 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 	 */
 	intel_crtc_load_lut(crtc);
 
-	intel_enable_pipe(dev_priv, pipe, is_pch_port);
+	intel_enable_pipe(dev_priv, pipe,
+			  intel_crtc->config.has_pch_encoder);
 	intel_enable_plane(dev_priv, plane, pipe);
 
-	if (is_pch_port)
+	if (intel_crtc->config.has_pch_encoder)
 		ironlake_pch_enable(crtc);
 
 	mutex_lock(&dev->struct_mutex);
@@ -3365,7 +3326,6 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
 	struct intel_encoder *encoder;
 	int pipe = intel_crtc->pipe;
 	int plane = intel_crtc->plane;
-	bool is_pch_port;
 
 	WARN_ON(!crtc->enabled);
 
@@ -3375,9 +3335,7 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
 	intel_crtc->active = true;
 	intel_update_watermarks(dev);
 
-	is_pch_port = haswell_crtc_driving_pch(crtc);
-
-	if (is_pch_port)
+	if (intel_crtc->config.has_pch_encoder)
 		dev_priv->display.fdi_link_train(crtc);
 
 	for_each_encoder_on_crtc(dev, crtc, encoder)
@@ -3406,12 +3364,13 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
 	intel_crtc_load_lut(crtc);
 
 	intel_ddi_set_pipe_settings(crtc);
-	intel_ddi_enable_pipe_func(crtc);
+	intel_ddi_enable_transcoder_func(crtc);
 
-	intel_enable_pipe(dev_priv, pipe, is_pch_port);
+	intel_enable_pipe(dev_priv, pipe,
+			  intel_crtc->config.has_pch_encoder);
 	intel_enable_plane(dev_priv, plane, pipe);
 
-	if (is_pch_port)
+	if (intel_crtc->config.has_pch_encoder)
 		lpt_pch_enable(crtc);
 
 	mutex_lock(&dev->struct_mutex);
@@ -3523,13 +3482,10 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
 	int pipe = intel_crtc->pipe;
 	int plane = intel_crtc->plane;
 	enum transcoder cpu_transcoder = intel_crtc->cpu_transcoder;
-	bool is_pch_port;
 
 	if (!intel_crtc->active)
 		return;
 
-	is_pch_port = haswell_crtc_driving_pch(crtc);
-
 	for_each_encoder_on_crtc(dev, crtc, encoder)
 		encoder->disable(encoder);
 
@@ -3556,7 +3512,7 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
 		if (encoder->post_disable)
 			encoder->post_disable(encoder);
 
-	if (is_pch_port) {
+	if (intel_crtc->config.has_pch_encoder) {
 		lpt_disable_pch_transcoder(dev_priv);
 		intel_ddi_fdi_disable(crtc);
 	}
@@ -3906,22 +3862,23 @@ bool intel_connector_get_hw_state(struct intel_connector *connector)
 	return encoder->get_hw_state(encoder, &pipe);
 }
 
-static bool intel_crtc_mode_fixup(struct drm_crtc *crtc,
-				  const struct drm_display_mode *mode,
-				  struct drm_display_mode *adjusted_mode)
+static bool intel_crtc_compute_config(struct drm_crtc *crtc,
+				      struct intel_crtc_config *pipe_config)
 {
 	struct drm_device *dev = crtc->dev;
+	struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
 
 	if (HAS_PCH_SPLIT(dev)) {
 		/* FDI link clock is fixed at 2.7G */
-		if (mode->clock * 3 > IRONLAKE_FDI_FREQ * 4)
+		if (pipe_config->requested_mode.clock * 3
+		    > IRONLAKE_FDI_FREQ * 4)
 			return false;
 	}
 
 	/* All interlaced capable intel hw wants timings in frames. Note though
 	 * that intel_lvds_mode_fixup does some funny tricks with the crtc
 	 * timings, so we need to be careful not to clobber these.*/
-	if (!(adjusted_mode->private_flags & INTEL_MODE_CRTC_TIMINGS_SET))
+	if (!pipe_config->timings_set)
 		drm_mode_set_crtcinfo(adjusted_mode, 0);
 
 	/* WaPruneModeWithIncorrectHsyncOffset: Cantiga+ cannot handle modes
@@ -3931,6 +3888,14 @@ static bool intel_crtc_mode_fixup(struct drm_crtc *crtc,
 		adjusted_mode->hsync_start == adjusted_mode->hdisplay)
 		return false;
 
+	if ((IS_G4X(dev) || IS_VALLEYVIEW(dev)) && pipe_config->pipe_bpp > 10) {
+		pipe_config->pipe_bpp = 10*3; /* 12bpc is gen5+ */
+	} else if (INTEL_INFO(dev)->gen <= 4 && pipe_config->pipe_bpp > 8) {
+		/* only a 8bpc pipe, with 6bpc dither through the panel fitter
+		 * for lvds. */
+		pipe_config->pipe_bpp = 8*3;
+	}
+
 	return true;
 }
 
@@ -4034,142 +3999,6 @@ 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
- * @mode: requested mode
- *
- * 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.
- *    DP may want to dither down to 6bpc to fit larger modes
- *
- * 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,
-					 struct drm_framebuffer *fb,
-					 unsigned int *pipe_bpp,
-					 struct drm_display_mode *mode)
-{
-	struct drm_device *dev = crtc->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct drm_connector *connector;
-	struct intel_encoder *intel_encoder;
-	unsigned int display_bpc = UINT_MAX, bpc;
-
-	/* Walk the encoders & connectors on this crtc, get min bpc */
-	for_each_encoder_on_crtc(dev, crtc, intel_encoder) {
-
-		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_KMS("clamping display bpc (was %d) to LVDS (%d)\n", display_bpc, lvds_bpc);
-				display_bpc = lvds_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 != &intel_encoder->base)
-				continue;
-
-			/* Don't use an invalid EDID bpc value */
-			if (connector->display_info.bpc &&
-			    connector->display_info.bpc < display_bpc) {
-				DRM_DEBUG_KMS("clamping display bpc (was %d) to EDID reported max of %d\n", display_bpc, connector->display_info.bpc);
-				display_bpc = connector->display_info.bpc;
-			}
-		}
-
-		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 && edp_bpc < display_bpc) {
-				DRM_DEBUG_KMS("clamping display bpc (was %d) to eDP (%d)\n", display_bpc, edp_bpc);
-				display_bpc = edp_bpc;
-			}
-			continue;
-		}
-
-		/*
-		 * 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_KMS("forcing bpc to 12 for HDMI\n");
-				display_bpc = 12;
-			} else {
-				DRM_DEBUG_KMS("forcing bpc to 8 for HDMI\n");
-				display_bpc = 8;
-			}
-		}
-	}
-
-	if (mode->private_flags & INTEL_MODE_DP_FORCE_6BPC) {
-		DRM_DEBUG_KMS("Dithering DP to 6bpc\n");
-		display_bpc = 6;
-	}
-
-	/*
-	 * 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 (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 = 8;
-		break;
-	case 30:
-		bpc = 10;
-		break;
-	case 48:
-		bpc = 12;
-		break;
-	default:
-		DRM_DEBUG("unsupported depth, assuming 24 bits\n");
-		bpc = min((unsigned int)8, display_bpc);
-		break;
-	}
-
-	display_bpc = min(display_bpc, bpc);
-
-	DRM_DEBUG_KMS("setting pipe bpc to %d (max display bpc %d)\n",
-		      bpc, display_bpc);
-
-	*pipe_bpp = display_bpc * 3;
-
-	return display_bpc != bpc;
-}
-
 static int vlv_get_refclk(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
@@ -4214,37 +4043,38 @@ static int i9xx_get_refclk(struct drm_crtc *crtc, int num_connectors)
 	return refclk;
 }
 
-static void i9xx_adjust_sdvo_tv_clock(struct drm_display_mode *adjusted_mode,
-				      intel_clock_t *clock)
+static void i9xx_adjust_sdvo_tv_clock(struct intel_crtc *crtc)
 {
+	unsigned dotclock = crtc->config.adjusted_mode.clock;
+	struct dpll *clock = &crtc->config.dpll;
+
 	/* SDVO TV has fixed PLL values depend on its clock range,
 	   this mirrors vbios setting. */
-	if (adjusted_mode->clock >= 100000
-	    && adjusted_mode->clock < 140500) {
+	if (dotclock >= 100000 && dotclock < 140500) {
 		clock->p1 = 2;
 		clock->p2 = 10;
 		clock->n = 3;
 		clock->m1 = 16;
 		clock->m2 = 8;
-	} else if (adjusted_mode->clock >= 140500
-		   && adjusted_mode->clock <= 200000) {
+	} else if (dotclock >= 140500 && dotclock <= 200000) {
 		clock->p1 = 1;
 		clock->p2 = 10;
 		clock->n = 6;
 		clock->m1 = 12;
 		clock->m2 = 8;
 	}
+
+	crtc->config.clock_set = true;
 }
 
-static void i9xx_update_pll_dividers(struct drm_crtc *crtc,
-				     intel_clock_t *clock,
+static void i9xx_update_pll_dividers(struct intel_crtc *crtc,
 				     intel_clock_t *reduced_clock)
 {
-	struct drm_device *dev = crtc->dev;
+	struct drm_device *dev = crtc->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	int pipe = intel_crtc->pipe;
+	int pipe = crtc->pipe;
 	u32 fp, fp2 = 0;
+	struct dpll *clock = &crtc->config.dpll;
 
 	if (IS_PINEVIEW(dev)) {
 		fp = (1 << clock->n) << 16 | clock->m1 << 8 | clock->m2;
@@ -4260,26 +4090,29 @@ static void i9xx_update_pll_dividers(struct drm_crtc *crtc,
 
 	I915_WRITE(FP0(pipe), fp);
 
-	intel_crtc->lowfreq_avail = false;
-	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) &&
+	crtc->lowfreq_avail = false;
+	if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_LVDS) &&
 	    reduced_clock && i915_powersave) {
 		I915_WRITE(FP1(pipe), fp2);
-		intel_crtc->lowfreq_avail = true;
+		crtc->lowfreq_avail = true;
 	} else {
 		I915_WRITE(FP1(pipe), fp);
 	}
 }
 
-static void vlv_update_pll(struct drm_crtc *crtc,
-			   struct drm_display_mode *mode,
-			   struct drm_display_mode *adjusted_mode,
-			   intel_clock_t *clock, intel_clock_t *reduced_clock,
-			   int num_connectors)
+static void intel_dp_set_m_n(struct intel_crtc *crtc)
 {
-	struct drm_device *dev = crtc->dev;
+	if (crtc->config.has_pch_encoder)
+		intel_pch_transcoder_set_m_n(crtc, &crtc->config.dp_m_n);
+	else
+		intel_cpu_transcoder_set_m_n(crtc, &crtc->config.dp_m_n);
+}
+
+static void vlv_update_pll(struct intel_crtc *crtc)
+{
+	struct drm_device *dev = crtc->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	int pipe = intel_crtc->pipe;
+	int pipe = crtc->pipe;
 	u32 dpll, mdiv, pdiv;
 	u32 bestn, bestm1, bestm2, bestp1, bestp2;
 	bool is_sdvo;
@@ -4287,8 +4120,8 @@ static void vlv_update_pll(struct drm_crtc *crtc,
 
 	mutex_lock(&dev_priv->dpio_lock);
 
-	is_sdvo = intel_pipe_has_type(crtc, INTEL_OUTPUT_SDVO) ||
-		intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI);
+	is_sdvo = intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_SDVO) ||
+		intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_HDMI);
 
 	dpll = DPLL_VGA_MODE_DIS;
 	dpll |= DPLL_EXT_BUFFER_ENABLE_VLV;
@@ -4298,11 +4131,11 @@ static void vlv_update_pll(struct drm_crtc *crtc,
 	I915_WRITE(DPLL(pipe), dpll);
 	POSTING_READ(DPLL(pipe));
 
-	bestn = clock->n;
-	bestm1 = clock->m1;
-	bestm2 = clock->m2;
-	bestp1 = clock->p1;
-	bestp2 = clock->p2;
+	bestn = crtc->config.dpll.n;
+	bestm1 = crtc->config.dpll.m1;
+	bestm2 = crtc->config.dpll.m2;
+	bestp1 = crtc->config.dpll.p1;
+	bestp2 = crtc->config.dpll.p2;
 
 	/*
 	 * In Valleyview PLL and program lane counter registers are exposed
@@ -4334,8 +4167,8 @@ static void vlv_update_pll(struct drm_crtc *crtc,
 
 	intel_dpio_write(dev_priv, DPIO_FASTCLK_DISABLE, 0x620);
 
-	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT))
-		intel_dp_set_m_n(crtc, mode, adjusted_mode);
+	if (crtc->config.has_dp_encoder)
+		intel_dp_set_m_n(crtc);
 
 	I915_WRITE(DPLL(pipe), dpll);
 
@@ -4345,26 +4178,25 @@ static void vlv_update_pll(struct drm_crtc *crtc,
 
 	temp = 0;
 	if (is_sdvo) {
-		temp = intel_mode_get_pixel_multiplier(adjusted_mode);
-		if (temp > 1)
-			temp = (temp - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT;
-		else
-			temp = 0;
+		temp = 0;
+		if (crtc->config.pixel_multiplier > 1) {
+			temp = (crtc->config.pixel_multiplier - 1)
+				<< DPLL_MD_UDI_MULTIPLIER_SHIFT;
+		}
 	}
 	I915_WRITE(DPLL_MD(pipe), temp);
 	POSTING_READ(DPLL_MD(pipe));
 
 	/* Now program lane control registers */
-	if(intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)
-			|| intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI))
-	{
+	if(intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DISPLAYPORT)
+	   || intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_HDMI)) {
 		temp = 0x1000C4;
 		if(pipe == 1)
 			temp |= (1 << 21);
 		intel_dpio_write(dev_priv, DPIO_DATA_CHANNEL1, temp);
 	}
-	if(intel_pipe_has_type(crtc,INTEL_OUTPUT_EDP))
-	{
+
+	if(intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_EDP)) {
 		temp = 0x1000C4;
 		if(pipe == 1)
 			temp |= (1 << 21);
@@ -4374,40 +4206,39 @@ static void vlv_update_pll(struct drm_crtc *crtc,
 	mutex_unlock(&dev_priv->dpio_lock);
 }
 
-static void i9xx_update_pll(struct drm_crtc *crtc,
-			    struct drm_display_mode *mode,
-			    struct drm_display_mode *adjusted_mode,
-			    intel_clock_t *clock, intel_clock_t *reduced_clock,
+static void i9xx_update_pll(struct intel_crtc *crtc,
+			    intel_clock_t *reduced_clock,
 			    int num_connectors)
 {
-	struct drm_device *dev = crtc->dev;
+	struct drm_device *dev = crtc->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	struct intel_encoder *encoder;
-	int pipe = intel_crtc->pipe;
+	int pipe = crtc->pipe;
 	u32 dpll;
 	bool is_sdvo;
+	struct dpll *clock = &crtc->config.dpll;
 
-	i9xx_update_pll_dividers(crtc, clock, reduced_clock);
+	i9xx_update_pll_dividers(crtc, reduced_clock);
 
-	is_sdvo = intel_pipe_has_type(crtc, INTEL_OUTPUT_SDVO) ||
-		intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI);
+	is_sdvo = intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_SDVO) ||
+		intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_HDMI);
 
 	dpll = DPLL_VGA_MODE_DIS;
 
-	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS))
+	if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_LVDS))
 		dpll |= DPLLB_MODE_LVDS;
 	else
 		dpll |= DPLLB_MODE_DAC_SERIAL;
+
 	if (is_sdvo) {
-		int pixel_multiplier = intel_mode_get_pixel_multiplier(adjusted_mode);
-		if (pixel_multiplier > 1) {
-			if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))
-				dpll |= (pixel_multiplier - 1) << SDVO_MULTIPLIER_SHIFT_HIRES;
+		if ((crtc->config.pixel_multiplier > 1) &&
+		    (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))) {
+			dpll |= (crtc->config.pixel_multiplier - 1)
+				<< SDVO_MULTIPLIER_SHIFT_HIRES;
 		}
 		dpll |= DPLL_DVO_HIGH_SPEED;
 	}
-	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT))
+	if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DISPLAYPORT))
 		dpll |= DPLL_DVO_HIGH_SPEED;
 
 	/* compute bitmask from p1 value */
@@ -4435,13 +4266,13 @@ static void i9xx_update_pll(struct drm_crtc *crtc,
 	if (INTEL_INFO(dev)->gen >= 4)
 		dpll |= (6 << PLL_LOAD_PULSE_PHASE_SHIFT);
 
-	if (is_sdvo && intel_pipe_has_type(crtc, INTEL_OUTPUT_TVOUT))
+	if (is_sdvo && intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_TVOUT))
 		dpll |= PLL_REF_INPUT_TVCLKINBC;
-	else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_TVOUT))
+	else if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_TVOUT))
 		/* XXX: just matching BIOS for now */
 		/*	dpll |= PLL_REF_INPUT_TVCLKINBC; */
 		dpll |= 3;
-	else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) &&
+	else if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_LVDS) &&
 		 intel_panel_use_ssc(dev_priv) && num_connectors < 2)
 		dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN;
 	else
@@ -4452,12 +4283,12 @@ static void i9xx_update_pll(struct drm_crtc *crtc,
 	POSTING_READ(DPLL(pipe));
 	udelay(150);
 
-	for_each_encoder_on_crtc(dev, crtc, encoder)
+	for_each_encoder_on_crtc(dev, &crtc->base, encoder)
 		if (encoder->pre_pll_enable)
 			encoder->pre_pll_enable(encoder);
 
-	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT))
-		intel_dp_set_m_n(crtc, mode, adjusted_mode);
+	if (crtc->config.has_dp_encoder)
+		intel_dp_set_m_n(crtc);
 
 	I915_WRITE(DPLL(pipe), dpll);
 
@@ -4468,11 +4299,11 @@ static void i9xx_update_pll(struct drm_crtc *crtc,
 	if (INTEL_INFO(dev)->gen >= 4) {
 		u32 temp = 0;
 		if (is_sdvo) {
-			temp = intel_mode_get_pixel_multiplier(adjusted_mode);
-			if (temp > 1)
-				temp = (temp - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT;
-			else
-				temp = 0;
+			temp = 0;
+			if (crtc->config.pixel_multiplier > 1) {
+				temp = (crtc->config.pixel_multiplier - 1)
+					<< DPLL_MD_UDI_MULTIPLIER_SHIFT;
+			}
 		}
 		I915_WRITE(DPLL_MD(pipe), temp);
 	} else {
@@ -4485,23 +4316,23 @@ static void i9xx_update_pll(struct drm_crtc *crtc,
 	}
 }
 
-static void i8xx_update_pll(struct drm_crtc *crtc,
+static void i8xx_update_pll(struct intel_crtc *crtc,
 			    struct drm_display_mode *adjusted_mode,
-			    intel_clock_t *clock, intel_clock_t *reduced_clock,
+			    intel_clock_t *reduced_clock,
 			    int num_connectors)
 {
-	struct drm_device *dev = crtc->dev;
+	struct drm_device *dev = crtc->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	struct intel_encoder *encoder;
-	int pipe = intel_crtc->pipe;
+	int pipe = crtc->pipe;
 	u32 dpll;
+	struct dpll *clock = &crtc->config.dpll;
 
-	i9xx_update_pll_dividers(crtc, clock, reduced_clock);
+	i9xx_update_pll_dividers(crtc, reduced_clock);
 
 	dpll = DPLL_VGA_MODE_DIS;
 
-	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
+	if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_LVDS)) {
 		dpll |= (1 << (clock->p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT;
 	} else {
 		if (clock->p1 == 2)
@@ -4512,11 +4343,7 @@ static void i8xx_update_pll(struct drm_crtc *crtc,
 			dpll |= PLL_P2_DIVIDE_BY_4;
 	}
 
-	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_TVOUT))
-		/* XXX: just matching BIOS for now */
-		/*	dpll |= PLL_REF_INPUT_TVCLKINBC; */
-		dpll |= 3;
-	else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) &&
+	if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_LVDS) &&
 		 intel_panel_use_ssc(dev_priv) && num_connectors < 2)
 		dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN;
 	else
@@ -4527,7 +4354,7 @@ static void i8xx_update_pll(struct drm_crtc *crtc,
 	POSTING_READ(DPLL(pipe));
 	udelay(150);
 
-	for_each_encoder_on_crtc(dev, crtc, encoder)
+	for_each_encoder_on_crtc(dev, &crtc->base, encoder)
 		if (encoder->pre_pll_enable)
 			encoder->pre_pll_enable(encoder);
 
@@ -4603,22 +4430,92 @@ static void intel_set_pipe_timings(struct intel_crtc *intel_crtc,
 		   ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1));
 }
 
+static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc)
+{
+	struct drm_device *dev = intel_crtc->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	uint32_t pipeconf;
+
+	pipeconf = I915_READ(PIPECONF(intel_crtc->pipe));
+
+	if (intel_crtc->pipe == 0 && INTEL_INFO(dev)->gen < 4) {
+		/* Enable pixel doubling when the dot clock is > 90% of the (display)
+		 * core speed.
+		 *
+		 * XXX: No double-wide on 915GM pipe B. Is that the only reason for the
+		 * pipe == 0 check?
+		 */
+		if (intel_crtc->config.requested_mode.clock >
+		    dev_priv->display.get_display_clock_speed(dev) * 9 / 10)
+			pipeconf |= PIPECONF_DOUBLE_WIDE;
+		else
+			pipeconf &= ~PIPECONF_DOUBLE_WIDE;
+	}
+
+	/* default to 8bpc */
+	pipeconf &= ~(PIPECONF_BPC_MASK | PIPECONF_DITHER_EN);
+	if (intel_crtc->config.has_dp_encoder) {
+		if (intel_crtc->config.dither) {
+			pipeconf |= PIPECONF_6BPC |
+				    PIPECONF_DITHER_EN |
+				    PIPECONF_DITHER_TYPE_SP;
+		}
+	}
+
+	if (IS_VALLEYVIEW(dev) && intel_pipe_has_type(&intel_crtc->base,
+						      INTEL_OUTPUT_EDP)) {
+		if (intel_crtc->config.dither) {
+			pipeconf |= PIPECONF_6BPC |
+					PIPECONF_ENABLE |
+					I965_PIPECONF_ACTIVE;
+		}
+	}
+
+	if (HAS_PIPE_CXSR(dev)) {
+		if (intel_crtc->lowfreq_avail) {
+			DRM_DEBUG_KMS("enabling CxSR downclocking\n");
+			pipeconf |= PIPECONF_CXSR_DOWNCLOCK;
+		} else {
+			DRM_DEBUG_KMS("disabling CxSR downclocking\n");
+			pipeconf &= ~PIPECONF_CXSR_DOWNCLOCK;
+		}
+	}
+
+	pipeconf &= ~PIPECONF_INTERLACE_MASK;
+	if (!IS_GEN2(dev) &&
+	    intel_crtc->config.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE)
+		pipeconf |= PIPECONF_INTERLACE_W_FIELD_INDICATION;
+	else
+		pipeconf |= PIPECONF_PROGRESSIVE;
+
+	if (IS_VALLEYVIEW(dev)) {
+		if (intel_crtc->config.limited_color_range)
+			pipeconf |= PIPECONF_COLOR_RANGE_SELECT;
+		else
+			pipeconf &= ~PIPECONF_COLOR_RANGE_SELECT;
+	}
+
+	I915_WRITE(PIPECONF(intel_crtc->pipe), pipeconf);
+	POSTING_READ(PIPECONF(intel_crtc->pipe));
+}
+
 static int i9xx_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 *fb)
 {
 	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 drm_display_mode *adjusted_mode =
+		&intel_crtc->config.adjusted_mode;
+	struct drm_display_mode *mode = &intel_crtc->config.requested_mode;
 	int pipe = intel_crtc->pipe;
 	int plane = intel_crtc->plane;
 	int refclk, num_connectors = 0;
 	intel_clock_t clock, reduced_clock;
-	u32 dspcntr, pipeconf;
+	u32 dspcntr;
 	bool ok, has_reduced_clock = false, is_sdvo = false;
-	bool is_lvds = false, is_tv = false, is_dp = false;
+	bool is_lvds = false, is_tv = false;
 	struct intel_encoder *encoder;
 	const intel_limit_t *limit;
 	int ret;
@@ -4637,9 +4534,6 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
 		case INTEL_OUTPUT_TVOUT:
 			is_tv = true;
 			break;
-		case INTEL_OUTPUT_DISPLAYPORT:
-			is_dp = true;
-			break;
 		}
 
 		num_connectors++;
@@ -4676,86 +4570,42 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
 						    &clock,
 						    &reduced_clock);
 	}
+	/* Compat-code for transition, will disappear. */
+	if (!intel_crtc->config.clock_set) {
+		intel_crtc->config.dpll.n = clock.n;
+		intel_crtc->config.dpll.m1 = clock.m1;
+		intel_crtc->config.dpll.m2 = clock.m2;
+		intel_crtc->config.dpll.p1 = clock.p1;
+		intel_crtc->config.dpll.p2 = clock.p2;
+	}
 
 	if (is_sdvo && is_tv)
-		i9xx_adjust_sdvo_tv_clock(adjusted_mode, &clock);
+		i9xx_adjust_sdvo_tv_clock(intel_crtc);
 
 	if (IS_GEN2(dev))
-		i8xx_update_pll(crtc, adjusted_mode, &clock,
+		i8xx_update_pll(intel_crtc, adjusted_mode,
 				has_reduced_clock ? &reduced_clock : NULL,
 				num_connectors);
 	else if (IS_VALLEYVIEW(dev))
-		vlv_update_pll(crtc, mode, adjusted_mode, &clock,
-				has_reduced_clock ? &reduced_clock : NULL,
-				num_connectors);
+		vlv_update_pll(intel_crtc);
 	else
-		i9xx_update_pll(crtc, mode, adjusted_mode, &clock,
+		i9xx_update_pll(intel_crtc,
 				has_reduced_clock ? &reduced_clock : NULL,
 				num_connectors);
 
-	/* setup pipeconf */
-	pipeconf = I915_READ(PIPECONF(pipe));
-
 	/* Set up the display plane register */
 	dspcntr = DISPPLANE_GAMMA_ENABLE;
 
-	if (pipe == 0)
-		dspcntr &= ~DISPPLANE_SEL_PIPE_MASK;
-	else
-		dspcntr |= DISPPLANE_SEL_PIPE_B;
-
-	if (pipe == 0 && INTEL_INFO(dev)->gen < 4) {
-		/* Enable pixel doubling when the dot clock is > 90% of the (display)
-		 * core speed.
-		 *
-		 * XXX: No double-wide on 915GM pipe B. Is that the only reason for the
-		 * pipe == 0 check?
-		 */
-		if (mode->clock >
-		    dev_priv->display.get_display_clock_speed(dev) * 9 / 10)
-			pipeconf |= PIPECONF_DOUBLE_WIDE;
+	if (!IS_VALLEYVIEW(dev)) {
+		if (pipe == 0)
+			dspcntr &= ~DISPPLANE_SEL_PIPE_MASK;
 		else
-			pipeconf &= ~PIPECONF_DOUBLE_WIDE;
-	}
-
-	/* default to 8bpc */
-	pipeconf &= ~(PIPECONF_BPC_MASK | PIPECONF_DITHER_EN);
-	if (is_dp) {
-		if (adjusted_mode->private_flags & INTEL_MODE_DP_FORCE_6BPC) {
-			pipeconf |= PIPECONF_6BPC |
-				    PIPECONF_DITHER_EN |
-				    PIPECONF_DITHER_TYPE_SP;
-		}
-	}
-
-	if (IS_VALLEYVIEW(dev) && intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP)) {
-		if (adjusted_mode->private_flags & INTEL_MODE_DP_FORCE_6BPC) {
-			pipeconf |= PIPECONF_6BPC |
-					PIPECONF_ENABLE |
-					I965_PIPECONF_ACTIVE;
-		}
+			dspcntr |= DISPPLANE_SEL_PIPE_B;
 	}
 
 	DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');
 	drm_mode_debug_printmodeline(mode);
 
-	if (HAS_PIPE_CXSR(dev)) {
-		if (intel_crtc->lowfreq_avail) {
-			DRM_DEBUG_KMS("enabling CxSR downclocking\n");
-			pipeconf |= PIPECONF_CXSR_DOWNCLOCK;
-		} else {
-			DRM_DEBUG_KMS("disabling CxSR downclocking\n");
-			pipeconf &= ~PIPECONF_CXSR_DOWNCLOCK;
-		}
-	}
-
-	pipeconf &= ~PIPECONF_INTERLACE_MASK;
-	if (!IS_GEN2(dev) &&
-	    adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
-		pipeconf |= PIPECONF_INTERLACE_W_FIELD_INDICATION;
-	else
-		pipeconf |= PIPECONF_PROGRESSIVE;
-
 	intel_set_pipe_timings(intel_crtc, mode, adjusted_mode);
 
 	/* pipesrc and dspsize control the size that is scaled from,
@@ -4766,8 +4616,8 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
 		   (mode->hdisplay - 1));
 	I915_WRITE(DSPPOS(plane), 0);
 
-	I915_WRITE(PIPECONF(pipe), pipeconf);
-	POSTING_READ(PIPECONF(pipe));
+	i9xx_set_pipeconf(intel_crtc);
+
 	intel_enable_pipe(dev_priv, pipe, false);
 
 	intel_wait_for_vblank(dev, pipe);
@@ -4782,12 +4632,26 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
 	return ret;
 }
 
+static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
+				 struct intel_crtc_config *pipe_config)
+{
+	struct drm_device *dev = crtc->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	uint32_t tmp;
+
+	tmp = I915_READ(PIPECONF(crtc->pipe));
+	if (!(tmp & PIPECONF_ENABLE))
+		return false;
+
+	return true;
+}
+
 static void ironlake_init_pch_refclk(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_mode_config *mode_config = &dev->mode_config;
 	struct intel_encoder *encoder;
-	u32 temp;
+	u32 val, final;
 	bool has_lvds = false;
 	bool has_cpu_edp = false;
 	bool has_pch_edp = false;
@@ -4830,70 +4694,109 @@ static void ironlake_init_pch_refclk(struct drm_device *dev)
 	 * PCH B stepping, previous chipset stepping should be
 	 * ignoring this setting.
 	 */
-	temp = I915_READ(PCH_DREF_CONTROL);
+	val = I915_READ(PCH_DREF_CONTROL);
+
+	/* As we must carefully and slowly disable/enable each source in turn,
+	 * compute the final state we want first and check if we need to
+	 * make any changes at all.
+	 */
+	final = val;
+	final &= ~DREF_NONSPREAD_SOURCE_MASK;
+	if (has_ck505)
+		final |= DREF_NONSPREAD_CK505_ENABLE;
+	else
+		final |= DREF_NONSPREAD_SOURCE_ENABLE;
+
+	final &= ~DREF_SSC_SOURCE_MASK;
+	final &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
+	final &= ~DREF_SSC1_ENABLE;
+
+	if (has_panel) {
+		final |= DREF_SSC_SOURCE_ENABLE;
+
+		if (intel_panel_use_ssc(dev_priv) && can_ssc)
+			final |= DREF_SSC1_ENABLE;
+
+		if (has_cpu_edp) {
+			if (intel_panel_use_ssc(dev_priv) && can_ssc)
+				final |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD;
+			else
+				final |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD;
+		} else
+			final |= DREF_CPU_SOURCE_OUTPUT_DISABLE;
+	} else {
+		final |= DREF_SSC_SOURCE_DISABLE;
+		final |= DREF_CPU_SOURCE_OUTPUT_DISABLE;
+	}
+
+	if (final == val)
+		return;
+
 	/* Always enable nonspread source */
-	temp &= ~DREF_NONSPREAD_SOURCE_MASK;
+	val &= ~DREF_NONSPREAD_SOURCE_MASK;
 
 	if (has_ck505)
-		temp |= DREF_NONSPREAD_CK505_ENABLE;
+		val |= DREF_NONSPREAD_CK505_ENABLE;
 	else
-		temp |= DREF_NONSPREAD_SOURCE_ENABLE;
+		val |= DREF_NONSPREAD_SOURCE_ENABLE;
 
 	if (has_panel) {
-		temp &= ~DREF_SSC_SOURCE_MASK;
-		temp |= DREF_SSC_SOURCE_ENABLE;
+		val &= ~DREF_SSC_SOURCE_MASK;
+		val |= DREF_SSC_SOURCE_ENABLE;
 
 		/* SSC must be turned on before enabling the CPU output  */
 		if (intel_panel_use_ssc(dev_priv) && can_ssc) {
 			DRM_DEBUG_KMS("Using SSC on panel\n");
-			temp |= DREF_SSC1_ENABLE;
+			val |= DREF_SSC1_ENABLE;
 		} else
-			temp &= ~DREF_SSC1_ENABLE;
+			val &= ~DREF_SSC1_ENABLE;
 
 		/* Get SSC going before enabling the outputs */
-		I915_WRITE(PCH_DREF_CONTROL, temp);
+		I915_WRITE(PCH_DREF_CONTROL, val);
 		POSTING_READ(PCH_DREF_CONTROL);
 		udelay(200);
 
-		temp &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
+		val &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
 
 		/* Enable CPU source on CPU attached eDP */
 		if (has_cpu_edp) {
 			if (intel_panel_use_ssc(dev_priv) && can_ssc) {
 				DRM_DEBUG_KMS("Using SSC on eDP\n");
-				temp |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD;
+				val |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD;
 			}
 			else
-				temp |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD;
+				val |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD;
 		} else
-			temp |= DREF_CPU_SOURCE_OUTPUT_DISABLE;
+			val |= DREF_CPU_SOURCE_OUTPUT_DISABLE;
 
-		I915_WRITE(PCH_DREF_CONTROL, temp);
+		I915_WRITE(PCH_DREF_CONTROL, val);
 		POSTING_READ(PCH_DREF_CONTROL);
 		udelay(200);
 	} else {
 		DRM_DEBUG_KMS("Disabling SSC entirely\n");
 
-		temp &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
+		val &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
 
 		/* Turn off CPU output */
-		temp |= DREF_CPU_SOURCE_OUTPUT_DISABLE;
+		val |= DREF_CPU_SOURCE_OUTPUT_DISABLE;
 
-		I915_WRITE(PCH_DREF_CONTROL, temp);
+		I915_WRITE(PCH_DREF_CONTROL, val);
 		POSTING_READ(PCH_DREF_CONTROL);
 		udelay(200);
 
 		/* Turn off the SSC source */
-		temp &= ~DREF_SSC_SOURCE_MASK;
-		temp |= DREF_SSC_SOURCE_DISABLE;
+		val &= ~DREF_SSC_SOURCE_MASK;
+		val |= DREF_SSC_SOURCE_DISABLE;
 
 		/* Turn off SSC1 */
-		temp &= ~ DREF_SSC1_ENABLE;
+		val &= ~DREF_SSC1_ENABLE;
 
-		I915_WRITE(PCH_DREF_CONTROL, temp);
+		I915_WRITE(PCH_DREF_CONTROL, val);
 		POSTING_READ(PCH_DREF_CONTROL);
 		udelay(200);
 	}
+
+	BUG_ON(val != final);
 }
 
 /* Sequence to enable CLKOUT_DP for FDI usage and configure PCH FDI I/O. */
@@ -5118,7 +5021,7 @@ static void ironlake_set_pipeconf(struct drm_crtc *crtc,
 	val = I915_READ(PIPECONF(pipe));
 
 	val &= ~PIPECONF_BPC_MASK;
-	switch (intel_crtc->bpp) {
+	switch (intel_crtc->config.pipe_bpp) {
 	case 18:
 		val |= PIPECONF_6BPC;
 		break;
@@ -5146,7 +5049,7 @@ static void ironlake_set_pipeconf(struct drm_crtc *crtc,
 	else
 		val |= PIPECONF_PROGRESSIVE;
 
-	if (adjusted_mode->private_flags & INTEL_MODE_LIMITED_COLOR_RANGE)
+	if (intel_crtc->config.limited_color_range)
 		val |= PIPECONF_COLOR_RANGE_SELECT;
 	else
 		val &= ~PIPECONF_COLOR_RANGE_SELECT;
@@ -5162,8 +5065,7 @@ static void ironlake_set_pipeconf(struct drm_crtc *crtc,
  * is supported, but eventually this should handle various
  * RGB<->YCbCr scenarios as well.
  */
-static void intel_set_pipe_csc(struct drm_crtc *crtc,
-			       const struct drm_display_mode *adjusted_mode)
+static void intel_set_pipe_csc(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -5178,7 +5080,7 @@ static void intel_set_pipe_csc(struct drm_crtc *crtc,
 	 * consideration.
 	 */
 
-	if (adjusted_mode->private_flags & INTEL_MODE_LIMITED_COLOR_RANGE)
+	if (intel_crtc->config.limited_color_range)
 		coeff = ((235 - 16) * (1 << 12) / 255) & 0xff8; /* 0.xxx... */
 
 	/*
@@ -5202,7 +5104,7 @@ static void intel_set_pipe_csc(struct drm_crtc *crtc,
 	if (INTEL_INFO(dev)->gen > 6) {
 		uint16_t postoff = 0;
 
-		if (adjusted_mode->private_flags & INTEL_MODE_LIMITED_COLOR_RANGE)
+		if (intel_crtc->config.limited_color_range)
 			postoff = (16 * (1 << 13) / 255) & 0x1fff;
 
 		I915_WRITE(PIPE_CSC_POSTOFF_HI(pipe), postoff);
@@ -5213,7 +5115,7 @@ static void intel_set_pipe_csc(struct drm_crtc *crtc,
 	} else {
 		uint32_t mode = CSC_MODE_YUV_TO_RGB;
 
-		if (adjusted_mode->private_flags & INTEL_MODE_LIMITED_COLOR_RANGE)
+		if (intel_crtc->config.limited_color_range)
 			mode |= CSC_BLACK_SCREEN_OFFSET;
 
 		I915_WRITE(PIPE_CSC_MODE(pipe), mode);
@@ -5303,7 +5205,7 @@ static bool ironlake_compute_clocks(struct drm_crtc *crtc,
 	}
 
 	if (is_sdvo && is_tv)
-		i9xx_adjust_sdvo_tv_clock(adjusted_mode, clock);
+		i9xx_adjust_sdvo_tv_clock(to_intel_crtc(crtc));
 
 	return true;
 }
@@ -5344,7 +5246,7 @@ static bool ironlake_check_fdi_lanes(struct intel_crtc *intel_crtc)
 		return false;
 	}
 
-	if (dev_priv->num_pipe == 2)
+	if (INTEL_INFO(dev)->num_pipes == 2)
 		return true;
 
 	switch (intel_crtc->pipe) {
@@ -5401,77 +5303,77 @@ int ironlake_get_lanes_required(int target_clock, int link_bw, int bpp)
 	return bps / (link_bw * 8) + 1;
 }
 
-static void ironlake_set_m_n(struct drm_crtc *crtc,
-			     struct drm_display_mode *mode,
-			     struct drm_display_mode *adjusted_mode)
+void intel_pch_transcoder_set_m_n(struct intel_crtc *crtc,
+				  struct intel_link_m_n *m_n)
 {
-	struct drm_device *dev = crtc->dev;
+	struct drm_device *dev = crtc->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	enum transcoder cpu_transcoder = intel_crtc->cpu_transcoder;
-	struct intel_encoder *intel_encoder, *edp_encoder = NULL;
-	struct intel_link_m_n m_n = {0};
-	int target_clock, pixel_multiplier, lane, link_bw;
-	bool is_dp = false, is_cpu_edp = false;
+	int pipe = crtc->pipe;
 
-	for_each_encoder_on_crtc(dev, crtc, intel_encoder) {
-		switch (intel_encoder->type) {
-		case INTEL_OUTPUT_DISPLAYPORT:
-			is_dp = true;
-			break;
-		case INTEL_OUTPUT_EDP:
-			is_dp = true;
-			if (!intel_encoder_is_pch_edp(&intel_encoder->base))
-				is_cpu_edp = true;
-			edp_encoder = intel_encoder;
-			break;
-		}
-	}
+	I915_WRITE(TRANSDATA_M1(pipe), TU_SIZE(m_n->tu) | m_n->gmch_m);
+	I915_WRITE(TRANSDATA_N1(pipe), m_n->gmch_n);
+	I915_WRITE(TRANSDPLINK_M1(pipe), m_n->link_m);
+	I915_WRITE(TRANSDPLINK_N1(pipe), m_n->link_n);
+}
+
+void intel_cpu_transcoder_set_m_n(struct intel_crtc *crtc,
+				  struct intel_link_m_n *m_n)
+{
+	struct drm_device *dev = crtc->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	int pipe = crtc->pipe;
+	enum transcoder transcoder = crtc->cpu_transcoder;
 
-	/* FDI link */
-	pixel_multiplier = intel_mode_get_pixel_multiplier(adjusted_mode);
-	lane = 0;
-	/* CPU eDP doesn't require FDI link, so just set DP M/N
-	   according to current link config */
-	if (is_cpu_edp) {
-		intel_edp_link_config(edp_encoder, &lane, &link_bw);
+	if (INTEL_INFO(dev)->gen >= 5) {
+		I915_WRITE(PIPE_DATA_M1(transcoder), TU_SIZE(m_n->tu) | m_n->gmch_m);
+		I915_WRITE(PIPE_DATA_N1(transcoder), m_n->gmch_n);
+		I915_WRITE(PIPE_LINK_M1(transcoder), m_n->link_m);
+		I915_WRITE(PIPE_LINK_N1(transcoder), m_n->link_n);
 	} else {
-		/* FDI is a binary signal running at ~2.7GHz, encoding
-		 * each output octet as 10 bits. The actual frequency
-		 * is stored as a divider into a 100MHz clock, and the
-		 * mode pixel clock is stored in units of 1KHz.
-		 * Hence the bw of each lane in terms of the mode signal
-		 * is:
-		 */
-		link_bw = intel_fdi_link_freq(dev) * MHz(100)/KHz(1)/10;
+		I915_WRITE(PIPE_GMCH_DATA_M(pipe), TU_SIZE(m_n->tu) | m_n->gmch_m);
+		I915_WRITE(PIPE_GMCH_DATA_N(pipe), m_n->gmch_n);
+		I915_WRITE(PIPE_DP_LINK_M(pipe), m_n->link_m);
+		I915_WRITE(PIPE_DP_LINK_N(pipe), m_n->link_n);
 	}
+}
+
+static void ironlake_fdi_set_m_n(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct drm_display_mode *adjusted_mode =
+		&intel_crtc->config.adjusted_mode;
+	struct intel_link_m_n m_n = {0};
+	int target_clock, lane, link_bw;
+
+	/* FDI is a binary signal running at ~2.7GHz, encoding
+	 * each output octet as 10 bits. The actual frequency
+	 * is stored as a divider into a 100MHz clock, and the
+	 * mode pixel clock is stored in units of 1KHz.
+	 * Hence the bw of each lane in terms of the mode signal
+	 * is:
+	 */
+	link_bw = intel_fdi_link_freq(dev) * MHz(100)/KHz(1)/10;
 
-	/* [e]DP over FDI requires target mode clock instead of link clock. */
-	if (edp_encoder)
-		target_clock = intel_edp_target_clock(edp_encoder, mode);
-	else if (is_dp)
-		target_clock = mode->clock;
+	if (intel_crtc->config.pixel_target_clock)
+		target_clock = intel_crtc->config.pixel_target_clock;
 	else
 		target_clock = adjusted_mode->clock;
 
-	if (!lane)
-		lane = ironlake_get_lanes_required(target_clock, link_bw,
-						   intel_crtc->bpp);
+	lane = ironlake_get_lanes_required(target_clock, link_bw,
+					   intel_crtc->config.pipe_bpp);
 
 	intel_crtc->fdi_lanes = lane;
 
-	if (pixel_multiplier > 1)
-		link_bw *= pixel_multiplier;
-	intel_link_compute_m_n(intel_crtc->bpp, lane, target_clock, link_bw, &m_n);
+	if (intel_crtc->config.pixel_multiplier > 1)
+		link_bw *= intel_crtc->config.pixel_multiplier;
+	intel_link_compute_m_n(intel_crtc->config.pipe_bpp, lane, target_clock,
+			       link_bw, &m_n);
 
-	I915_WRITE(PIPE_DATA_M1(cpu_transcoder), TU_SIZE(m_n.tu) | m_n.gmch_m);
-	I915_WRITE(PIPE_DATA_N1(cpu_transcoder), m_n.gmch_n);
-	I915_WRITE(PIPE_LINK_M1(cpu_transcoder), m_n.link_m);
-	I915_WRITE(PIPE_LINK_N1(cpu_transcoder), m_n.link_n);
+	intel_cpu_transcoder_set_m_n(intel_crtc, &m_n);
 }
 
 static uint32_t ironlake_compute_dpll(struct intel_crtc *intel_crtc,
-				      struct drm_display_mode *adjusted_mode,
 				      intel_clock_t *clock, u32 fp)
 {
 	struct drm_crtc *crtc = &intel_crtc->base;
@@ -5479,9 +5381,8 @@ static uint32_t ironlake_compute_dpll(struct intel_crtc *intel_crtc,
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_encoder *intel_encoder;
 	uint32_t dpll;
-	int factor, pixel_multiplier, num_connectors = 0;
+	int factor, num_connectors = 0;
 	bool is_lvds = false, is_sdvo = false, is_tv = false;
-	bool is_dp = false, is_cpu_edp = false;
 
 	for_each_encoder_on_crtc(dev, crtc, intel_encoder) {
 		switch (intel_encoder->type) {
@@ -5497,14 +5398,6 @@ static uint32_t ironlake_compute_dpll(struct intel_crtc *intel_crtc,
 		case INTEL_OUTPUT_TVOUT:
 			is_tv = true;
 			break;
-		case INTEL_OUTPUT_DISPLAYPORT:
-			is_dp = true;
-			break;
-		case INTEL_OUTPUT_EDP:
-			is_dp = true;
-			if (!intel_encoder_is_pch_edp(&intel_encoder->base))
-				is_cpu_edp = true;
-			break;
 		}
 
 		num_connectors++;
@@ -5530,13 +5423,14 @@ static uint32_t ironlake_compute_dpll(struct intel_crtc *intel_crtc,
 	else
 		dpll |= DPLLB_MODE_DAC_SERIAL;
 	if (is_sdvo) {
-		pixel_multiplier = intel_mode_get_pixel_multiplier(adjusted_mode);
-		if (pixel_multiplier > 1) {
-			dpll |= (pixel_multiplier - 1) << PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT;
+		if (intel_crtc->config.pixel_multiplier > 1) {
+			dpll |= (intel_crtc->config.pixel_multiplier - 1)
+				<< PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT;
 		}
 		dpll |= DPLL_DVO_HIGH_SPEED;
 	}
-	if (is_dp && !is_cpu_edp)
+	if (intel_crtc->config.has_dp_encoder &&
+	    intel_crtc->config.has_pch_encoder)
 		dpll |= DPLL_DVO_HIGH_SPEED;
 
 	/* compute bitmask from p1 value */
@@ -5574,21 +5468,22 @@ static uint32_t ironlake_compute_dpll(struct intel_crtc *intel_crtc,
 }
 
 static int ironlake_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 *fb)
 {
 	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 drm_display_mode *adjusted_mode =
+		&intel_crtc->config.adjusted_mode;
+	struct drm_display_mode *mode = &intel_crtc->config.requested_mode;
 	int pipe = intel_crtc->pipe;
 	int plane = intel_crtc->plane;
 	int num_connectors = 0;
 	intel_clock_t clock, reduced_clock;
 	u32 dpll, fp = 0, fp2 = 0;
 	bool ok, has_reduced_clock = false;
-	bool is_lvds = false, is_dp = false, is_cpu_edp = false;
+	bool is_lvds = false;
 	struct intel_encoder *encoder;
 	int ret;
 	bool dither, fdi_config_ok;
@@ -5598,14 +5493,6 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 		case INTEL_OUTPUT_LVDS:
 			is_lvds = true;
 			break;
-		case INTEL_OUTPUT_DISPLAYPORT:
-			is_dp = true;
-			break;
-		case INTEL_OUTPUT_EDP:
-			is_dp = true;
-			if (!intel_encoder_is_pch_edp(&encoder->base))
-				is_cpu_edp = true;
-			break;
 		}
 
 		num_connectors++;
@@ -5614,19 +5501,28 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 	WARN(!(HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)),
 	     "Unexpected PCH type %d\n", INTEL_PCH_TYPE(dev));
 
+	intel_crtc->cpu_transcoder = pipe;
+
 	ok = ironlake_compute_clocks(crtc, adjusted_mode, &clock,
 				     &has_reduced_clock, &reduced_clock);
 	if (!ok) {
 		DRM_ERROR("Couldn't find PLL settings for mode!\n");
 		return -EINVAL;
 	}
+	/* Compat-code for transition, will disappear. */
+	if (!intel_crtc->config.clock_set) {
+		intel_crtc->config.dpll.n = clock.n;
+		intel_crtc->config.dpll.m1 = clock.m1;
+		intel_crtc->config.dpll.m2 = clock.m2;
+		intel_crtc->config.dpll.p1 = clock.p1;
+		intel_crtc->config.dpll.p2 = clock.p2;
+	}
 
 	/* Ensure that the cursor is valid for the new mode before changing... */
 	intel_crtc_update_cursor(crtc, true);
 
 	/* determine panel color depth */
-	dither = intel_choose_pipe_bpp_dither(crtc, fb, &intel_crtc->bpp,
-					      adjusted_mode);
+	dither = intel_crtc->config.dither;
 	if (is_lvds && dev_priv->lvds_dither)
 		dither = true;
 
@@ -5635,13 +5531,13 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 		fp2 = reduced_clock.n << 16 | reduced_clock.m1 << 8 |
 			reduced_clock.m2;
 
-	dpll = ironlake_compute_dpll(intel_crtc, adjusted_mode, &clock, fp);
+	dpll = ironlake_compute_dpll(intel_crtc, &clock, fp);
 
 	DRM_DEBUG_KMS("Mode for pipe %d:\n", pipe);
 	drm_mode_debug_printmodeline(mode);
 
 	/* CPU eDP is the only output that doesn't need a PCH PLL of its own. */
-	if (!is_cpu_edp) {
+	if (intel_crtc->config.has_pch_encoder) {
 		struct intel_pch_pll *pll;
 
 		pll = intel_get_pch_pll(intel_crtc, dpll, fp);
@@ -5653,8 +5549,8 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 	} else
 		intel_put_pch_pll(intel_crtc);
 
-	if (is_dp && !is_cpu_edp)
-		intel_dp_set_m_n(crtc, mode, adjusted_mode);
+	if (intel_crtc->config.has_dp_encoder)
+		intel_dp_set_m_n(intel_crtc);
 
 	for_each_encoder_on_crtc(dev, crtc, encoder)
 		if (encoder->pre_pll_enable)
@@ -5689,7 +5585,9 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 
 	/* Note, this also computes intel_crtc->fdi_lanes which is used below in
 	 * ironlake_check_fdi_lanes. */
-	ironlake_set_m_n(crtc, mode, adjusted_mode);
+	intel_crtc->fdi_lanes = 0;
+	if (intel_crtc->config.has_pch_encoder)
+		ironlake_fdi_set_m_n(crtc);
 
 	fdi_config_ok = ironlake_check_fdi_lanes(intel_crtc);
 
@@ -5710,6 +5608,23 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 	return fdi_config_ok ? ret : -EINVAL;
 }
 
+static bool ironlake_get_pipe_config(struct intel_crtc *crtc,
+				     struct intel_crtc_config *pipe_config)
+{
+	struct drm_device *dev = crtc->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	uint32_t tmp;
+
+	tmp = I915_READ(PIPECONF(crtc->pipe));
+	if (!(tmp & PIPECONF_ENABLE))
+		return false;
+
+	if (I915_READ(TRANSCONF(crtc->pipe)) & TRANS_ENABLE)
+		pipe_config->has_pch_encoder = true;
+
+	return true;
+}
+
 static void haswell_modeset_global_resources(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -5740,29 +5655,26 @@ static void haswell_modeset_global_resources(struct drm_device *dev)
 }
 
 static int haswell_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 *fb)
 {
 	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 drm_display_mode *adjusted_mode =
+		&intel_crtc->config.adjusted_mode;
+	struct drm_display_mode *mode = &intel_crtc->config.requested_mode;
 	int pipe = intel_crtc->pipe;
 	int plane = intel_crtc->plane;
 	int num_connectors = 0;
-	bool is_dp = false, is_cpu_edp = false;
+	bool is_cpu_edp = false;
 	struct intel_encoder *encoder;
 	int ret;
 	bool dither;
 
 	for_each_encoder_on_crtc(dev, crtc, encoder) {
 		switch (encoder->type) {
-		case INTEL_OUTPUT_DISPLAYPORT:
-			is_dp = true;
-			break;
 		case INTEL_OUTPUT_EDP:
-			is_dp = true;
 			if (!intel_encoder_is_pch_edp(&encoder->base))
 				is_cpu_edp = true;
 			break;
@@ -5795,25 +5707,24 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,
 	intel_crtc_update_cursor(crtc, true);
 
 	/* determine panel color depth */
-	dither = intel_choose_pipe_bpp_dither(crtc, fb, &intel_crtc->bpp,
-					      adjusted_mode);
+	dither = intel_crtc->config.dither;
 
 	DRM_DEBUG_KMS("Mode for pipe %d:\n", pipe);
 	drm_mode_debug_printmodeline(mode);
 
-	if (is_dp && !is_cpu_edp)
-		intel_dp_set_m_n(crtc, mode, adjusted_mode);
+	if (intel_crtc->config.has_dp_encoder)
+		intel_dp_set_m_n(intel_crtc);
 
 	intel_crtc->lowfreq_avail = false;
 
 	intel_set_pipe_timings(intel_crtc, mode, adjusted_mode);
 
-	if (!is_dp || is_cpu_edp)
-		ironlake_set_m_n(crtc, mode, adjusted_mode);
+	if (intel_crtc->config.has_pch_encoder)
+		ironlake_fdi_set_m_n(crtc);
 
 	haswell_set_pipeconf(crtc, adjusted_mode, dither);
 
-	intel_set_pipe_csc(crtc, adjusted_mode);
+	intel_set_pipe_csc(crtc);
 
 	/* Set up the display plane register */
 	I915_WRITE(DSPCNTR(plane), DISPPLANE_GAMMA_ENABLE | DISPPLANE_PIPE_CSC_ENABLE);
@@ -5828,9 +5739,32 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,
 	return ret;
 }
 
+static bool haswell_get_pipe_config(struct intel_crtc *crtc,
+				    struct intel_crtc_config *pipe_config)
+{
+	struct drm_device *dev = crtc->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	uint32_t tmp;
+
+	tmp = I915_READ(PIPECONF(crtc->cpu_transcoder));
+	if (!(tmp & PIPECONF_ENABLE))
+		return false;
+
+	/*
+	 * aswell has only FDI/PCH transcoder A. It is which is connected to
+	 * DDI E. So just check whether this pipe is wired to DDI E and whether
+	 * the PCH transcoder is on.
+	 */
+	tmp = I915_READ(TRANS_DDI_FUNC_CTL(crtc->pipe));
+	if ((tmp & TRANS_DDI_PORT_MASK) == TRANS_DDI_SELECT_PORT(PORT_E) &&
+	    I915_READ(TRANSCONF(PIPE_A)) & TRANS_ENABLE)
+		pipe_config->has_pch_encoder = true;
+
+
+	return true;
+}
+
 static int 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 *fb)
 {
@@ -5839,13 +5773,16 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
 	struct drm_encoder_helper_funcs *encoder_funcs;
 	struct intel_encoder *encoder;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct drm_display_mode *adjusted_mode =
+		&intel_crtc->config.adjusted_mode;
+	struct drm_display_mode *mode = &intel_crtc->config.requested_mode;
 	int pipe = intel_crtc->pipe;
 	int ret;
 
 	drm_vblank_pre_modeset(dev, pipe);
 
-	ret = dev_priv->display.crtc_mode_set(crtc, mode, adjusted_mode,
-					      x, y, fb);
+	ret = dev_priv->display.crtc_mode_set(crtc, x, y, fb);
+
 	drm_vblank_post_modeset(dev, pipe);
 
 	if (ret != 0)
@@ -5856,8 +5793,12 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
 			encoder->base.base.id,
 			drm_get_encoder_name(&encoder->base),
 			mode->base.id, mode->name);
-		encoder_funcs = encoder->base.helper_private;
-		encoder_funcs->mode_set(&encoder->base, mode, adjusted_mode);
+		if (encoder->mode_set) {
+			encoder->mode_set(encoder);
+		} else {
+			encoder_funcs = encoder->base.helper_private;
+			encoder_funcs->mode_set(&encoder->base, mode, adjusted_mode);
+		}
 	}
 
 	return 0;
@@ -6325,13 +6266,24 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
 	/* we only need to pin inside GTT if cursor is non-phy */
 	mutex_lock(&dev->struct_mutex);
 	if (!dev_priv->info->cursor_needs_physical) {
+		unsigned alignment;
+
 		if (obj->tiling_mode) {
 			DRM_ERROR("cursor cannot be tiled\n");
 			ret = -EINVAL;
 			goto fail_locked;
 		}
 
-		ret = i915_gem_object_pin_to_display_plane(obj, 0, NULL);
+		/* Note that the w/a also requires 2 PTE of padding following
+		 * the bo. We currently fill all unused PTE with the shadow
+		 * page and so we should always have valid PTE following the
+		 * cursor preventing the VT-d warning.
+		 */
+		alignment = 0;
+		if (need_vtd_wa(dev))
+			alignment = 64*1024;
+
+		ret = i915_gem_object_pin_to_display_plane(obj, alignment, NULL);
 		if (ret) {
 			DRM_ERROR("failed to move cursor bo into the GTT\n");
 			goto fail_locked;
@@ -6436,20 +6388,6 @@ static void intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
 	intel_crtc_load_lut(crtc);
 }
 
-/**
- * Get a pipe with a simple mode set on it for doing load-based monitor
- * detection.
- *
- * It will be up to the load-detect code to adjust the pipe as appropriate for
- * its requirements.  The pipe will be connected to no other encoders.
- *
- * Currently this code will only succeed if there is a pipe with no encoders
- * configured for it.  In the future, it could choose to temporarily disable
- * some outputs to free up a pipe for its use.
- *
- * \return crtc, or NULL if no pipes are available.
- */
-
 /* VESA 640x480x72Hz mode to set on the pipe */
 static struct drm_display_mode load_detect_mode = {
 	DRM_MODE("640x480", DRM_MODE_TYPE_DEFAULT, 31500, 640, 664,
@@ -6954,7 +6892,6 @@ static void do_intel_finish_page_flip(struct drm_device *dev,
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	struct intel_unpin_work *work;
-	struct drm_i915_gem_object *obj;
 	unsigned long flags;
 
 	/* Ignore early vblank irqs */
@@ -6984,8 +6921,6 @@ static void do_intel_finish_page_flip(struct drm_device *dev,
 
 	spin_unlock_irqrestore(&dev->event_lock, flags);
 
-	obj = work->old_fb_obj;
-
 	wake_up_all(&dev_priv->pending_flip_queue);
 
 	queue_work(dev_priv->wq, &work->work);
@@ -7473,19 +7408,93 @@ static void intel_modeset_commit_output_state(struct drm_device *dev)
 	}
 }
 
-static struct drm_display_mode *
-intel_modeset_adjusted_mode(struct drm_crtc *crtc,
-			    struct drm_display_mode *mode)
+static int
+pipe_config_set_bpp(struct drm_crtc *crtc,
+		    struct drm_framebuffer *fb,
+		    struct intel_crtc_config *pipe_config)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_connector *connector;
+	int bpp;
+
+	switch (fb->pixel_format) {
+	case DRM_FORMAT_C8:
+		bpp = 8*3; /* since we go through a colormap */
+		break;
+	case DRM_FORMAT_XRGB1555:
+	case DRM_FORMAT_ARGB1555:
+		/* checked in intel_framebuffer_init already */
+		if (WARN_ON(INTEL_INFO(dev)->gen > 3))
+			return -EINVAL;
+	case DRM_FORMAT_RGB565:
+		bpp = 6*3; /* min is 18bpp */
+		break;
+	case DRM_FORMAT_XBGR8888:
+	case DRM_FORMAT_ABGR8888:
+		/* checked in intel_framebuffer_init already */
+		if (WARN_ON(INTEL_INFO(dev)->gen < 4))
+			return -EINVAL;
+	case DRM_FORMAT_XRGB8888:
+	case DRM_FORMAT_ARGB8888:
+		bpp = 8*3;
+		break;
+	case DRM_FORMAT_XRGB2101010:
+	case DRM_FORMAT_ARGB2101010:
+	case DRM_FORMAT_XBGR2101010:
+	case DRM_FORMAT_ABGR2101010:
+		/* checked in intel_framebuffer_init already */
+		if (WARN_ON(INTEL_INFO(dev)->gen < 4))
+			return -EINVAL;
+		bpp = 10*3;
+		break;
+	/* TODO: gen4+ supports 16 bpc floating point, too. */
+	default:
+		DRM_DEBUG_KMS("unsupported depth\n");
+		return -EINVAL;
+	}
+
+	pipe_config->pipe_bpp = bpp;
+
+	/* Clamp display bpp to EDID value */
+	list_for_each_entry(connector, &dev->mode_config.connector_list,
+			    head) {
+		if (connector->encoder && connector->encoder->crtc != crtc)
+			continue;
+
+		/* Don't use an invalid EDID bpc value */
+		if (connector->display_info.bpc &&
+		    connector->display_info.bpc * 3 < bpp) {
+			DRM_DEBUG_KMS("clamping display bpp (was %d) to EDID reported max of %d\n",
+				      bpp, connector->display_info.bpc*3);
+			pipe_config->pipe_bpp = connector->display_info.bpc*3;
+		}
+	}
+
+	return bpp;
+}
+
+static struct intel_crtc_config *
+intel_modeset_pipe_config(struct drm_crtc *crtc,
+			  struct drm_framebuffer *fb,
+			  struct drm_display_mode *mode)
 {
 	struct drm_device *dev = crtc->dev;
-	struct drm_display_mode *adjusted_mode;
 	struct drm_encoder_helper_funcs *encoder_funcs;
 	struct intel_encoder *encoder;
+	struct intel_crtc_config *pipe_config;
+	int plane_bpp;
 
-	adjusted_mode = drm_mode_duplicate(dev, mode);
-	if (!adjusted_mode)
+	pipe_config = kzalloc(sizeof(*pipe_config), GFP_KERNEL);
+	if (!pipe_config)
 		return ERR_PTR(-ENOMEM);
 
+	drm_mode_copy(&pipe_config->adjusted_mode, mode);
+	drm_mode_copy(&pipe_config->requested_mode, mode);
+
+	plane_bpp = pipe_config_set_bpp(crtc, fb, pipe_config);
+	if (plane_bpp < 0)
+		goto fail;
+
 	/* Pass our mode to the connectors and the CRTC to give them a chance to
 	 * adjust it according to limitations or connector properties, and also
 	 * a chance to reject the mode entirely.
@@ -7495,23 +7504,38 @@ intel_modeset_adjusted_mode(struct drm_crtc *crtc,
 
 		if (&encoder->new_crtc->base != crtc)
 			continue;
+
+		if (encoder->compute_config) {
+			if (!(encoder->compute_config(encoder, pipe_config))) {
+				DRM_DEBUG_KMS("Encoder config failure\n");
+				goto fail;
+			}
+
+			continue;
+		}
+
 		encoder_funcs = encoder->base.helper_private;
-		if (!(encoder_funcs->mode_fixup(&encoder->base, mode,
-						adjusted_mode))) {
+		if (!(encoder_funcs->mode_fixup(&encoder->base,
+						&pipe_config->requested_mode,
+						&pipe_config->adjusted_mode))) {
 			DRM_DEBUG_KMS("Encoder fixup failed\n");
 			goto fail;
 		}
 	}
 
-	if (!(intel_crtc_mode_fixup(crtc, mode, adjusted_mode))) {
+	if (!(intel_crtc_compute_config(crtc, pipe_config))) {
 		DRM_DEBUG_KMS("CRTC fixup failed\n");
 		goto fail;
 	}
 	DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
 
-	return adjusted_mode;
+	pipe_config->dither = pipe_config->pipe_bpp != plane_bpp;
+	DRM_DEBUG_KMS("plane bpp: %i, pipe bpp: %i, dithering: %i\n",
+		      plane_bpp, pipe_config->pipe_bpp, pipe_config->dither);
+
+	return pipe_config;
 fail:
-	drm_mode_destroy(dev, adjusted_mode);
+	kfree(pipe_config);
 	return ERR_PTR(-EINVAL);
 }
 
@@ -7673,12 +7697,29 @@ intel_modeset_update_state(struct drm_device *dev, unsigned prepare_pipes)
 			    base.head) \
 		if (mask & (1 <<(intel_crtc)->pipe)) \
 
+static bool
+intel_pipe_config_compare(struct intel_crtc_config *current_config,
+			  struct intel_crtc_config *pipe_config)
+{
+	if (current_config->has_pch_encoder != pipe_config->has_pch_encoder) {
+		DRM_ERROR("mismatch in has_pch_encoder "
+			  "(expected %i, found %i)\n",
+			  current_config->has_pch_encoder,
+			  pipe_config->has_pch_encoder);
+		return false;
+	}
+
+	return true;
+}
+
 void
 intel_modeset_check_state(struct drm_device *dev)
 {
+	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct intel_crtc *crtc;
 	struct intel_encoder *encoder;
 	struct intel_connector *connector;
+	struct intel_crtc_config pipe_config;
 
 	list_for_each_entry(connector, &dev->mode_config.connector_list,
 			    base.head) {
@@ -7767,7 +7808,16 @@ intel_modeset_check_state(struct drm_device *dev)
 		     "crtc's computed enabled state doesn't match tracked enabled state "
 		     "(expected %i, found %i)\n", enabled, crtc->base.enabled);
 
-		assert_pipe(dev->dev_private, crtc->pipe, crtc->active);
+		memset(&pipe_config, 0, sizeof(pipe_config));
+		active = dev_priv->display.get_pipe_config(crtc,
+							   &pipe_config);
+		WARN(crtc->active != active,
+		     "crtc active state doesn't match with hw state "
+		     "(expected %i, found %i)\n", crtc->active, active);
+
+		WARN(active &&
+		     !intel_pipe_config_compare(&crtc->config, &pipe_config),
+		     "pipe state doesn't match!\n");
 	}
 }
 
@@ -7777,7 +7827,8 @@ int intel_set_mode(struct drm_crtc *crtc,
 {
 	struct drm_device *dev = crtc->dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	struct drm_display_mode *adjusted_mode, *saved_mode, *saved_hwmode;
+	struct drm_display_mode *saved_mode, *saved_hwmode;
+	struct intel_crtc_config *pipe_config = NULL;
 	struct intel_crtc *intel_crtc;
 	unsigned disable_pipes, prepare_pipes, modeset_pipes;
 	int ret = 0;
@@ -7790,12 +7841,6 @@ int intel_set_mode(struct drm_crtc *crtc,
 	intel_modeset_affected_pipes(crtc, &modeset_pipes,
 				     &prepare_pipes, &disable_pipes);
 
-	DRM_DEBUG_KMS("set mode pipe masks: modeset: %x, prepare: %x, disable: %x\n",
-		      modeset_pipes, prepare_pipes, disable_pipes);
-
-	for_each_intel_crtc_masked(dev, disable_pipes, intel_crtc)
-		intel_crtc_disable(&intel_crtc->base);
-
 	*saved_hwmode = crtc->hwmode;
 	*saved_mode = crtc->mode;
 
@@ -7804,15 +7849,22 @@ int intel_set_mode(struct drm_crtc *crtc,
 	 * Hence simply check whether any bit is set in modeset_pipes in all the
 	 * pieces of code that are not yet converted to deal with mutliple crtcs
 	 * changing their mode at the same time. */
-	adjusted_mode = NULL;
 	if (modeset_pipes) {
-		adjusted_mode = intel_modeset_adjusted_mode(crtc, mode);
-		if (IS_ERR(adjusted_mode)) {
-			ret = PTR_ERR(adjusted_mode);
+		pipe_config = intel_modeset_pipe_config(crtc, fb, mode);
+		if (IS_ERR(pipe_config)) {
+			ret = PTR_ERR(pipe_config);
+			pipe_config = NULL;
+
 			goto out;
 		}
 	}
 
+	DRM_DEBUG_KMS("set mode pipe masks: modeset: %x, prepare: %x, disable: %x\n",
+		      modeset_pipes, prepare_pipes, disable_pipes);
+
+	for_each_intel_crtc_masked(dev, disable_pipes, intel_crtc)
+		intel_crtc_disable(&intel_crtc->base);
+
 	for_each_intel_crtc_masked(dev, prepare_pipes, intel_crtc) {
 		if (intel_crtc->base.enabled)
 			dev_priv->display.crtc_disable(&intel_crtc->base);
@@ -7821,8 +7873,12 @@ int intel_set_mode(struct drm_crtc *crtc,
 	/* crtc->mode is already used by the ->mode_set callbacks, hence we need
 	 * to set it here already despite that we pass it down the callchain.
 	 */
-	if (modeset_pipes)
+	if (modeset_pipes) {
 		crtc->mode = *mode;
+		/* mode_set/enable/disable functions rely on a correct pipe
+		 * config. */
+		to_intel_crtc(crtc)->config = *pipe_config;
+	}
 
 	/* Only after disabling all output pipelines that will be changed can we
 	 * update the the output configuration. */
@@ -7836,7 +7892,6 @@ int intel_set_mode(struct drm_crtc *crtc,
 	 */
 	for_each_intel_crtc_masked(dev, modeset_pipes, intel_crtc) {
 		ret = intel_crtc_mode_set(&intel_crtc->base,
-					  mode, adjusted_mode,
 					  x, y, fb);
 		if (ret)
 			goto done;
@@ -7848,7 +7903,7 @@ int intel_set_mode(struct drm_crtc *crtc,
 
 	if (modeset_pipes) {
 		/* Store real post-adjustment hardware mode. */
-		crtc->hwmode = *adjusted_mode;
+		crtc->hwmode = pipe_config->adjusted_mode;
 
 		/* Calculate and store various constants which
 		 * are later needed by vblank and swap-completion
@@ -7859,7 +7914,6 @@ int intel_set_mode(struct drm_crtc *crtc,
 
 	/* FIXME: add subpixel order */
 done:
-	drm_mode_destroy(dev, adjusted_mode);
 	if (ret && crtc->enabled) {
 		crtc->hwmode = *saved_hwmode;
 		crtc->mode = *saved_mode;
@@ -7868,6 +7922,7 @@ done:
 	}
 
 out:
+	kfree(pipe_config);
 	kfree(saved_mode);
 	return ret;
 }
@@ -7959,10 +8014,8 @@ intel_set_config_compute_mode_changes(struct drm_mode_set *set,
 			config->mode_changed = true;
 		} else if (set->fb == NULL) {
 			config->mode_changed = true;
-		} else if (set->fb->depth != set->crtc->fb->depth) {
-			config->mode_changed = true;
-		} else if (set->fb->bits_per_pixel !=
-			   set->crtc->fb->bits_per_pixel) {
+		} else if (set->fb->pixel_format !=
+			   set->crtc->fb->pixel_format) {
 			config->mode_changed = true;
 		} else
 			config->fb_changed = true;
@@ -8145,6 +8198,8 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
 			goto fail;
 		}
 	} else if (config->fb_changed) {
+		intel_crtc_wait_for_pending_flips(set->crtc);
+
 		ret = intel_pipe_set_base(set->crtc,
 					  set->x, set->y, set->fb);
 	}
@@ -8232,8 +8287,6 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
 	dev_priv->plane_to_crtc_mapping[intel_crtc->plane] = &intel_crtc->base;
 	dev_priv->pipe_to_crtc_mapping[intel_crtc->pipe] = &intel_crtc->base;
 
-	intel_crtc->bpp = 24; /* default for pre-Ironlake */
-
 	drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs);
 }
 
@@ -8343,20 +8396,20 @@ static void intel_setup_outputs(struct drm_device *dev)
 		if (has_edp_a(dev))
 			intel_dp_init(dev, DP_A, PORT_A);
 
-		if (I915_READ(HDMIB) & PORT_DETECTED) {
+		if (I915_READ(PCH_HDMIB) & SDVO_DETECTED) {
 			/* PCH SDVOB multiplex with HDMIB */
 			found = intel_sdvo_init(dev, PCH_SDVOB, true);
 			if (!found)
-				intel_hdmi_init(dev, HDMIB, PORT_B);
+				intel_hdmi_init(dev, PCH_HDMIB, PORT_B);
 			if (!found && (I915_READ(PCH_DP_B) & DP_DETECTED))
 				intel_dp_init(dev, PCH_DP_B, PORT_B);
 		}
 
-		if (I915_READ(HDMIC) & PORT_DETECTED)
-			intel_hdmi_init(dev, HDMIC, PORT_C);
+		if (I915_READ(PCH_HDMIC) & SDVO_DETECTED)
+			intel_hdmi_init(dev, PCH_HDMIC, PORT_C);
 
-		if (!dpd_is_edp && I915_READ(HDMID) & PORT_DETECTED)
-			intel_hdmi_init(dev, HDMID, PORT_D);
+		if (!dpd_is_edp && I915_READ(PCH_HDMID) & SDVO_DETECTED)
+			intel_hdmi_init(dev, PCH_HDMID, PORT_D);
 
 		if (I915_READ(PCH_DP_C) & DP_DETECTED)
 			intel_dp_init(dev, PCH_DP_C, PORT_C);
@@ -8368,24 +8421,21 @@ static void intel_setup_outputs(struct drm_device *dev)
 		if (I915_READ(VLV_DISPLAY_BASE + DP_C) & DP_DETECTED)
 			intel_dp_init(dev, VLV_DISPLAY_BASE + DP_C, PORT_C);
 
-		if (I915_READ(VLV_DISPLAY_BASE + SDVOB) & PORT_DETECTED) {
-			intel_hdmi_init(dev, VLV_DISPLAY_BASE + SDVOB, PORT_B);
+		if (I915_READ(VLV_DISPLAY_BASE + GEN4_HDMIB) & SDVO_DETECTED) {
+			intel_hdmi_init(dev, VLV_DISPLAY_BASE + GEN4_HDMIB,
+					PORT_B);
 			if (I915_READ(VLV_DISPLAY_BASE + DP_B) & DP_DETECTED)
 				intel_dp_init(dev, VLV_DISPLAY_BASE + DP_B, PORT_B);
 		}
-
-		if (I915_READ(VLV_DISPLAY_BASE + SDVOC) & PORT_DETECTED)
-			intel_hdmi_init(dev, VLV_DISPLAY_BASE + SDVOC, PORT_C);
-
 	} else if (SUPPORTS_DIGITAL_OUTPUTS(dev)) {
 		bool found = false;
 
-		if (I915_READ(SDVOB) & SDVO_DETECTED) {
+		if (I915_READ(GEN3_SDVOB) & SDVO_DETECTED) {
 			DRM_DEBUG_KMS("probing SDVOB\n");
-			found = intel_sdvo_init(dev, SDVOB, true);
+			found = intel_sdvo_init(dev, GEN3_SDVOB, true);
 			if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) {
 				DRM_DEBUG_KMS("probing HDMI on SDVOB\n");
-				intel_hdmi_init(dev, SDVOB, PORT_B);
+				intel_hdmi_init(dev, GEN4_HDMIB, PORT_B);
 			}
 
 			if (!found && SUPPORTS_INTEGRATED_DP(dev)) {
@@ -8396,16 +8446,16 @@ static void intel_setup_outputs(struct drm_device *dev)
 
 		/* Before G4X SDVOC doesn't have its own detect register */
 
-		if (I915_READ(SDVOB) & SDVO_DETECTED) {
+		if (I915_READ(GEN3_SDVOB) & SDVO_DETECTED) {
 			DRM_DEBUG_KMS("probing SDVOC\n");
-			found = intel_sdvo_init(dev, SDVOC, false);
+			found = intel_sdvo_init(dev, GEN3_SDVOC, false);
 		}
 
-		if (!found && (I915_READ(SDVOC) & SDVO_DETECTED)) {
+		if (!found && (I915_READ(GEN3_SDVOC) & SDVO_DETECTED)) {
 
 			if (SUPPORTS_INTEGRATED_HDMI(dev)) {
 				DRM_DEBUG_KMS("probing HDMI on SDVOC\n");
-				intel_hdmi_init(dev, SDVOC, PORT_C);
+				intel_hdmi_init(dev, GEN4_HDMIC, PORT_C);
 			}
 			if (SUPPORTS_INTEGRATED_DP(dev)) {
 				DRM_DEBUG_KMS("probing DP_C\n");
@@ -8572,20 +8622,22 @@ static void intel_init_display(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	/* We always want a DPMS function */
 	if (HAS_DDI(dev)) {
+		dev_priv->display.get_pipe_config = haswell_get_pipe_config;
 		dev_priv->display.crtc_mode_set = haswell_crtc_mode_set;
 		dev_priv->display.crtc_enable = haswell_crtc_enable;
 		dev_priv->display.crtc_disable = haswell_crtc_disable;
 		dev_priv->display.off = haswell_crtc_off;
 		dev_priv->display.update_plane = ironlake_update_plane;
 	} else if (HAS_PCH_SPLIT(dev)) {
+		dev_priv->display.get_pipe_config = ironlake_get_pipe_config;
 		dev_priv->display.crtc_mode_set = ironlake_crtc_mode_set;
 		dev_priv->display.crtc_enable = ironlake_crtc_enable;
 		dev_priv->display.crtc_disable = ironlake_crtc_disable;
 		dev_priv->display.off = ironlake_crtc_off;
 		dev_priv->display.update_plane = ironlake_update_plane;
 	} else {
+		dev_priv->display.get_pipe_config = i9xx_get_pipe_config;
 		dev_priv->display.crtc_mode_set = i9xx_crtc_mode_set;
 		dev_priv->display.crtc_enable = i9xx_crtc_enable;
 		dev_priv->display.crtc_disable = i9xx_crtc_disable;
@@ -8828,7 +8880,7 @@ void intel_modeset_init_hw(struct drm_device *dev)
 void intel_modeset_init(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	int i, ret;
+	int i, j, ret;
 
 	drm_mode_config_init(dev);
 
@@ -8859,13 +8911,17 @@ void intel_modeset_init(struct drm_device *dev)
 	dev->mode_config.fb_base = dev_priv->gtt.mappable_base;
 
 	DRM_DEBUG_KMS("%d display pipe%s available.\n",
-		      dev_priv->num_pipe, dev_priv->num_pipe > 1 ? "s" : "");
+		      INTEL_INFO(dev)->num_pipes,
+		      INTEL_INFO(dev)->num_pipes > 1 ? "s" : "");
 
-	for (i = 0; i < dev_priv->num_pipe; i++) {
+	for (i = 0; i < INTEL_INFO(dev)->num_pipes; i++) {
 		intel_crtc_init(dev, i);
-		ret = intel_plane_init(dev, i);
-		if (ret)
-			DRM_DEBUG_KMS("plane %d init failed: %d\n", i, ret);
+		for (j = 0; j < dev_priv->num_plane; j++) {
+			ret = intel_plane_init(dev, i, j);
+			if (ret)
+				DRM_DEBUG_KMS("pipe %d plane %d init failed: %d\n",
+					      i, j, ret);
+		}
 	}
 
 	intel_cpu_pll_init(dev);
@@ -8918,10 +8974,11 @@ static void intel_enable_pipe_a(struct drm_device *dev)
 static bool
 intel_check_plane_mapping(struct intel_crtc *crtc)
 {
-	struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
+	struct drm_device *dev = crtc->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 reg, val;
 
-	if (dev_priv->num_pipe == 1)
+	if (INTEL_INFO(dev)->num_pipes == 1)
 		return true;
 
 	reg = DSPCNTR(!crtc->plane);
@@ -9077,6 +9134,7 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	enum pipe pipe;
 	u32 tmp;
+	struct drm_plane *plane;
 	struct intel_crtc *crtc;
 	struct intel_encoder *encoder;
 	struct intel_connector *connector;
@@ -9096,6 +9154,13 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
 			case TRANS_DDI_EDP_INPUT_C_ONOFF:
 				pipe = PIPE_C;
 				break;
+			default:
+				/* A bogus value has been programmed, disable
+				 * the transcoder */
+				WARN(1, "Bogus eDP source %08x\n", tmp);
+				intel_ddi_disable_transcoder_func(dev_priv,
+						TRANSCODER_EDP);
+				goto setup_pipes;
 			}
 
 			crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
@@ -9106,14 +9171,12 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
 		}
 	}
 
-	for_each_pipe(pipe) {
-		crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
-
-		tmp = I915_READ(PIPECONF(crtc->cpu_transcoder));
-		if (tmp & PIPECONF_ENABLE)
-			crtc->active = true;
-		else
-			crtc->active = false;
+setup_pipes:
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list,
+			    base.head) {
+		memset(&crtc->config, 0, sizeof(crtc->config));
+		crtc->active = dev_priv->display.get_pipe_config(crtc,
+								 &crtc->config);
 
 		crtc->base.enabled = crtc->active;
 
@@ -9173,8 +9236,12 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
 
 	if (force_restore) {
 		for_each_pipe(pipe) {
-			intel_crtc_restore_mode(dev_priv->pipe_to_crtc_mapping[pipe]);
+			struct drm_crtc *crtc =
+				dev_priv->pipe_to_crtc_mapping[pipe];
+			intel_crtc_restore_mode(crtc);
 		}
+		list_for_each_entry(plane, &dev->mode_config.plane_list, head)
+			intel_plane_restore(plane);
 
 		i915_redisable_vga(dev);
 	} else {
@@ -9323,15 +9390,24 @@ intel_display_capture_error_state(struct drm_device *dev)
 	for_each_pipe(i) {
 		cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv, i);
 
-		error->cursor[i].control = I915_READ(CURCNTR(i));
-		error->cursor[i].position = I915_READ(CURPOS(i));
-		error->cursor[i].base = I915_READ(CURBASE(i));
+		if (INTEL_INFO(dev)->gen <= 6 || IS_VALLEYVIEW(dev)) {
+			error->cursor[i].control = I915_READ(CURCNTR(i));
+			error->cursor[i].position = I915_READ(CURPOS(i));
+			error->cursor[i].base = I915_READ(CURBASE(i));
+		} else {
+			error->cursor[i].control = I915_READ(CURCNTR_IVB(i));
+			error->cursor[i].position = I915_READ(CURPOS_IVB(i));
+			error->cursor[i].base = I915_READ(CURBASE_IVB(i));
+		}
 
 		error->plane[i].control = I915_READ(DSPCNTR(i));
 		error->plane[i].stride = I915_READ(DSPSTRIDE(i));
-		error->plane[i].size = I915_READ(DSPSIZE(i));
-		error->plane[i].pos = I915_READ(DSPPOS(i));
-		error->plane[i].addr = I915_READ(DSPADDR(i));
+		if (INTEL_INFO(dev)->gen <= 3) {
+			error->plane[i].size = I915_READ(DSPSIZE(i));
+			error->plane[i].pos = I915_READ(DSPPOS(i));
+		}
+		if (INTEL_INFO(dev)->gen <= 7 && !IS_HASWELL(dev))
+			error->plane[i].addr = I915_READ(DSPADDR(i));
 		if (INTEL_INFO(dev)->gen >= 4) {
 			error->plane[i].surface = I915_READ(DSPSURF(i));
 			error->plane[i].tile_offset = I915_READ(DSPTILEOFF(i));
@@ -9355,10 +9431,9 @@ intel_display_print_error_state(struct seq_file *m,
 				struct drm_device *dev,
 				struct intel_display_error_state *error)
 {
-	drm_i915_private_t *dev_priv = dev->dev_private;
 	int i;
 
-	seq_printf(m, "Num Pipes: %d\n", dev_priv->num_pipe);
+	seq_printf(m, "Num Pipes: %d\n", INTEL_INFO(dev)->num_pipes);
 	for_each_pipe(i) {
 		seq_printf(m, "Pipe [%d]:\n", i);
 		seq_printf(m, "  CONF: %08x\n", error->pipe[i].conf);
@@ -9373,9 +9448,12 @@ intel_display_print_error_state(struct seq_file *m,
 		seq_printf(m, "Plane [%d]:\n", i);
 		seq_printf(m, "  CNTR: %08x\n", error->plane[i].control);
 		seq_printf(m, "  STRIDE: %08x\n", error->plane[i].stride);
-		seq_printf(m, "  SIZE: %08x\n", error->plane[i].size);
-		seq_printf(m, "  POS: %08x\n", error->plane[i].pos);
-		seq_printf(m, "  ADDR: %08x\n", error->plane[i].addr);
+		if (INTEL_INFO(dev)->gen <= 3) {
+			seq_printf(m, "  SIZE: %08x\n", error->plane[i].size);
+			seq_printf(m, "  POS: %08x\n", error->plane[i].pos);
+		}
+		if (INTEL_INFO(dev)->gen <= 7 && !IS_HASWELL(dev))
+			seq_printf(m, "  ADDR: %08x\n", error->plane[i].addr);
 		if (INTEL_INFO(dev)->gen >= 4) {
 			seq_printf(m, "  SURF: %08x\n", error->plane[i].surface);
 			seq_printf(m, "  TILEOFF: %08x\n", error->plane[i].tile_offset);
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index d7d4afe..37483d9 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -109,29 +109,6 @@ bool intel_encoder_is_pch_edp(struct drm_encoder *encoder)
 
 static void intel_dp_link_down(struct intel_dp *intel_dp);
 
-void
-intel_edp_link_config(struct intel_encoder *intel_encoder,
-		       int *lane_num, int *link_bw)
-{
-	struct intel_dp *intel_dp = enc_to_intel_dp(&intel_encoder->base);
-
-	*lane_num = intel_dp->lane_count;
-	*link_bw = drm_dp_bw_code_to_link_rate(intel_dp->link_bw);
-}
-
-int
-intel_edp_target_clock(struct intel_encoder *intel_encoder,
-		       struct drm_display_mode *mode)
-{
-	struct intel_dp *intel_dp = enc_to_intel_dp(&intel_encoder->base);
-	struct intel_connector *intel_connector = intel_dp->attached_connector;
-
-	if (intel_connector->panel.fixed_mode)
-		return intel_connector->panel.fixed_mode->clock;
-	else
-		return mode->clock;
-}
-
 static int
 intel_dp_max_link_bw(struct intel_dp *intel_dp)
 {
@@ -177,34 +154,6 @@ intel_dp_max_data_rate(int max_link_clock, int max_lanes)
 	return (max_link_clock * max_lanes * 8) / 10;
 }
 
-static bool
-intel_dp_adjust_dithering(struct intel_dp *intel_dp,
-			  struct drm_display_mode *mode,
-			  bool adjust_mode)
-{
-	int max_link_clock =
-		drm_dp_bw_code_to_link_rate(intel_dp_max_link_bw(intel_dp));
-	int max_lanes = drm_dp_max_lane_count(intel_dp->dpcd);
-	int max_rate, mode_rate;
-
-	mode_rate = intel_dp_link_required(mode->clock, 24);
-	max_rate = intel_dp_max_data_rate(max_link_clock, max_lanes);
-
-	if (mode_rate > max_rate) {
-		mode_rate = intel_dp_link_required(mode->clock, 18);
-		if (mode_rate > max_rate)
-			return false;
-
-		if (adjust_mode)
-			mode->private_flags
-				|= INTEL_MODE_DP_FORCE_6BPC;
-
-		return true;
-	}
-
-	return true;
-}
-
 static int
 intel_dp_mode_valid(struct drm_connector *connector,
 		    struct drm_display_mode *mode)
@@ -212,6 +161,8 @@ intel_dp_mode_valid(struct drm_connector *connector,
 	struct intel_dp *intel_dp = intel_attached_dp(connector);
 	struct intel_connector *intel_connector = to_intel_connector(connector);
 	struct drm_display_mode *fixed_mode = intel_connector->panel.fixed_mode;
+	int target_clock = mode->clock;
+	int max_rate, mode_rate, max_lanes, max_link_clock;
 
 	if (is_edp(intel_dp) && fixed_mode) {
 		if (mode->hdisplay > fixed_mode->hdisplay)
@@ -219,9 +170,17 @@ intel_dp_mode_valid(struct drm_connector *connector,
 
 		if (mode->vdisplay > fixed_mode->vdisplay)
 			return MODE_PANEL;
+
+		target_clock = fixed_mode->clock;
 	}
 
-	if (!intel_dp_adjust_dithering(intel_dp, mode, false))
+	max_link_clock = drm_dp_bw_code_to_link_rate(intel_dp_max_link_bw(intel_dp));
+	max_lanes = drm_dp_max_lane_count(intel_dp->dpcd);
+
+	max_rate = intel_dp_max_data_rate(max_link_clock, max_lanes);
+	mode_rate = intel_dp_link_required(target_clock, 18);
+
+	if (mode_rate > max_rate)
 		return MODE_CLOCK_HIGH;
 
 	if (mode->clock < 10000)
@@ -294,16 +253,20 @@ static bool ironlake_edp_have_panel_power(struct intel_dp *intel_dp)
 {
 	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 pp_stat_reg;
 
-	return (I915_READ(PCH_PP_STATUS) & PP_ON) != 0;
+	pp_stat_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_STATUS : PCH_PP_STATUS;
+	return (I915_READ(pp_stat_reg) & PP_ON) != 0;
 }
 
 static bool ironlake_edp_have_panel_vdd(struct intel_dp *intel_dp)
 {
 	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 pp_ctrl_reg;
 
-	return (I915_READ(PCH_PP_CONTROL) & EDP_FORCE_VDD) != 0;
+	pp_ctrl_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_CONTROL : PCH_PP_CONTROL;
+	return (I915_READ(pp_ctrl_reg) & EDP_FORCE_VDD) != 0;
 }
 
 static void
@@ -311,14 +274,19 @@ intel_dp_check_edp(struct intel_dp *intel_dp)
 {
 	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 pp_stat_reg, pp_ctrl_reg;
 
 	if (!is_edp(intel_dp))
 		return;
+
+	pp_stat_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_STATUS : PCH_PP_STATUS;
+	pp_ctrl_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_CONTROL : PCH_PP_CONTROL;
+
 	if (!ironlake_edp_have_panel_power(intel_dp) && !ironlake_edp_have_panel_vdd(intel_dp)) {
 		WARN(1, "eDP powered off while attempting aux channel communication.\n");
 		DRM_DEBUG_KMS("Status 0x%08x Control 0x%08x\n",
-			      I915_READ(PCH_PP_STATUS),
-			      I915_READ(PCH_PP_CONTROL));
+				I915_READ(pp_stat_reg),
+				I915_READ(pp_ctrl_reg));
 	}
 }
 
@@ -328,29 +296,10 @@ intel_dp_aux_wait_done(struct intel_dp *intel_dp, bool has_aux_irq)
 	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
 	struct drm_device *dev = intel_dig_port->base.base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	uint32_t ch_ctl = intel_dp->output_reg + 0x10;
+	uint32_t ch_ctl = intel_dp->aux_ch_ctl_reg;
 	uint32_t status;
 	bool done;
 
-	if (IS_HASWELL(dev)) {
-		switch (intel_dig_port->port) {
-		case PORT_A:
-			ch_ctl = DPA_AUX_CH_CTL;
-			break;
-		case PORT_B:
-			ch_ctl = PCH_DPB_AUX_CH_CTL;
-			break;
-		case PORT_C:
-			ch_ctl = PCH_DPC_AUX_CH_CTL;
-			break;
-		case PORT_D:
-			ch_ctl = PCH_DPD_AUX_CH_CTL;
-			break;
-		default:
-			BUG();
-		}
-	}
-
 #define C (((status = I915_READ_NOTRACE(ch_ctl)) & DP_AUX_CH_CTL_SEND_BUSY) == 0)
 	if (has_aux_irq)
 		done = wait_event_timeout(dev_priv->gmbus_wait_queue, C,
@@ -370,11 +319,10 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
 		uint8_t *send, int send_bytes,
 		uint8_t *recv, int recv_size)
 {
-	uint32_t output_reg = intel_dp->output_reg;
 	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
 	struct drm_device *dev = intel_dig_port->base.base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	uint32_t ch_ctl = output_reg + 0x10;
+	uint32_t ch_ctl = intel_dp->aux_ch_ctl_reg;
 	uint32_t ch_data = ch_ctl + 4;
 	int i, ret, recv_bytes;
 	uint32_t status;
@@ -388,29 +336,6 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
 	 */
 	pm_qos_update_request(&dev_priv->pm_qos, 0);
 
-	if (IS_HASWELL(dev)) {
-		switch (intel_dig_port->port) {
-		case PORT_A:
-			ch_ctl = DPA_AUX_CH_CTL;
-			ch_data = DPA_AUX_CH_DATA1;
-			break;
-		case PORT_B:
-			ch_ctl = PCH_DPB_AUX_CH_CTL;
-			ch_data = PCH_DPB_AUX_CH_DATA1;
-			break;
-		case PORT_C:
-			ch_ctl = PCH_DPC_AUX_CH_CTL;
-			ch_data = PCH_DPC_AUX_CH_DATA1;
-			break;
-		case PORT_D:
-			ch_ctl = PCH_DPD_AUX_CH_CTL;
-			ch_data = PCH_DPD_AUX_CH_DATA1;
-			break;
-		default:
-			BUG();
-		}
-	}
-
 	intel_dp_check_edp(intel_dp);
 	/* The clock divider is based off the hrawclk,
 	 * and would like to run at 2MHz. So, take the
@@ -731,19 +656,70 @@ intel_dp_i2c_init(struct intel_dp *intel_dp,
 	return ret;
 }
 
+static void
+intel_dp_set_clock(struct intel_encoder *encoder,
+		   struct intel_crtc_config *pipe_config, int link_bw)
+{
+	struct drm_device *dev = encoder->base.dev;
+
+	if (IS_G4X(dev)) {
+		if (link_bw == DP_LINK_BW_1_62) {
+			pipe_config->dpll.p1 = 2;
+			pipe_config->dpll.p2 = 10;
+			pipe_config->dpll.n = 2;
+			pipe_config->dpll.m1 = 23;
+			pipe_config->dpll.m2 = 8;
+		} else {
+			pipe_config->dpll.p1 = 1;
+			pipe_config->dpll.p2 = 10;
+			pipe_config->dpll.n = 1;
+			pipe_config->dpll.m1 = 14;
+			pipe_config->dpll.m2 = 2;
+		}
+		pipe_config->clock_set = true;
+	} else if (IS_HASWELL(dev)) {
+		/* Haswell has special-purpose DP DDI clocks. */
+	} else if (HAS_PCH_SPLIT(dev)) {
+		if (link_bw == DP_LINK_BW_1_62) {
+			pipe_config->dpll.n = 1;
+			pipe_config->dpll.p1 = 2;
+			pipe_config->dpll.p2 = 10;
+			pipe_config->dpll.m1 = 12;
+			pipe_config->dpll.m2 = 9;
+		} else {
+			pipe_config->dpll.n = 2;
+			pipe_config->dpll.p1 = 1;
+			pipe_config->dpll.p2 = 10;
+			pipe_config->dpll.m1 = 14;
+			pipe_config->dpll.m2 = 8;
+		}
+		pipe_config->clock_set = true;
+	} else if (IS_VALLEYVIEW(dev)) {
+		/* FIXME: Need to figure out optimized DP clocks for vlv. */
+	}
+}
+
 bool
-intel_dp_mode_fixup(struct drm_encoder *encoder,
-		    const struct drm_display_mode *mode,
-		    struct drm_display_mode *adjusted_mode)
+intel_dp_compute_config(struct intel_encoder *encoder,
+			struct intel_crtc_config *pipe_config)
 {
-	struct drm_device *dev = encoder->dev;
-	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+	struct drm_device *dev = encoder->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
+	struct drm_display_mode *mode = &pipe_config->requested_mode;
+	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
 	struct intel_connector *intel_connector = intel_dp->attached_connector;
 	int lane_count, clock;
 	int max_lane_count = drm_dp_max_lane_count(intel_dp->dpcd);
 	int max_clock = intel_dp_max_link_bw(intel_dp) == DP_LINK_BW_2_7 ? 1 : 0;
 	int bpp, mode_rate;
 	static int bws[2] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7 };
+	int target_clock, link_avail, link_clock;
+
+	if (HAS_PCH_SPLIT(dev) && !HAS_DDI(dev) && !is_cpu_edp(intel_dp))
+		pipe_config->has_pch_encoder = true;
+
+	pipe_config->has_dp_encoder = true;
 
 	if (is_edp(intel_dp) && intel_connector->panel.fixed_mode) {
 		intel_fixed_panel_mode(intel_connector->panel.fixed_mode,
@@ -752,6 +728,8 @@ intel_dp_mode_fixup(struct drm_encoder *encoder,
 					intel_connector->panel.fitting_mode,
 					mode, adjusted_mode);
 	}
+	/* We need to take the panel's fixed mode into account. */
+	target_clock = adjusted_mode->clock;
 
 	if (adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK)
 		return false;
@@ -760,11 +738,28 @@ intel_dp_mode_fixup(struct drm_encoder *encoder,
 		      "max bw %02x pixel clock %iKHz\n",
 		      max_lane_count, bws[max_clock], adjusted_mode->clock);
 
-	if (!intel_dp_adjust_dithering(intel_dp, adjusted_mode, true))
-		return false;
+	/* Walk through all bpp values. Luckily they're all nicely spaced with 2
+	 * bpc in between. */
+	bpp = min_t(int, 8*3, pipe_config->pipe_bpp);
+	for (; bpp >= 6*3; bpp -= 2*3) {
+		mode_rate = intel_dp_link_required(target_clock, bpp);
+
+		for (clock = 0; clock <= max_clock; clock++) {
+			for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) {
+				link_clock = drm_dp_bw_code_to_link_rate(bws[clock]);
+				link_avail = intel_dp_max_data_rate(link_clock,
+								    lane_count);
+
+				if (mode_rate <= link_avail) {
+					goto found;
+				}
+			}
+		}
+	}
 
-	bpp = adjusted_mode->private_flags & INTEL_MODE_DP_FORCE_6BPC ? 18 : 24;
+	return false;
 
+found:
 	if (intel_dp->color_range_auto) {
 		/*
 		 * See:
@@ -778,104 +773,40 @@ intel_dp_mode_fixup(struct drm_encoder *encoder,
 	}
 
 	if (intel_dp->color_range)
-		adjusted_mode->private_flags |= INTEL_MODE_LIMITED_COLOR_RANGE;
-
-	mode_rate = intel_dp_link_required(adjusted_mode->clock, bpp);
-
-	for (clock = 0; clock <= max_clock; clock++) {
-		for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) {
-			int link_bw_clock =
-				drm_dp_bw_code_to_link_rate(bws[clock]);
-			int link_avail = intel_dp_max_data_rate(link_bw_clock,
-								lane_count);
-
-			if (mode_rate <= link_avail) {
-				intel_dp->link_bw = bws[clock];
-				intel_dp->lane_count = lane_count;
-				adjusted_mode->clock = link_bw_clock;
-				DRM_DEBUG_KMS("DP link bw %02x lane "
-						"count %d clock %d bpp %d\n",
-				       intel_dp->link_bw, intel_dp->lane_count,
-				       adjusted_mode->clock, bpp);
-				DRM_DEBUG_KMS("DP link bw required %i available %i\n",
-					      mode_rate, link_avail);
-				return true;
-			}
-		}
-	}
+		pipe_config->limited_color_range = true;
 
-	return false;
-}
+	intel_dp->link_bw = bws[clock];
+	intel_dp->lane_count = lane_count;
+	adjusted_mode->clock = drm_dp_bw_code_to_link_rate(intel_dp->link_bw);
+	pipe_config->pixel_target_clock = target_clock;
 
-void
-intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
-		 struct drm_display_mode *adjusted_mode)
-{
-	struct drm_device *dev = crtc->dev;
-	struct intel_encoder *intel_encoder;
-	struct intel_dp *intel_dp;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	int lane_count = 4;
-	struct intel_link_m_n m_n;
-	int pipe = intel_crtc->pipe;
-	enum transcoder cpu_transcoder = intel_crtc->cpu_transcoder;
-	int target_clock;
+	DRM_DEBUG_KMS("DP link bw %02x lane count %d clock %d bpp %d\n",
+		      intel_dp->link_bw, intel_dp->lane_count,
+		      adjusted_mode->clock, bpp);
+	DRM_DEBUG_KMS("DP link bw required %i available %i\n",
+		      mode_rate, link_avail);
 
-	/*
-	 * Find the lane count in the intel_encoder private
-	 */
-	for_each_encoder_on_crtc(dev, crtc, intel_encoder) {
-		intel_dp = enc_to_intel_dp(&intel_encoder->base);
+	intel_link_compute_m_n(bpp, lane_count,
+			       target_clock, adjusted_mode->clock,
+			       &pipe_config->dp_m_n);
 
-		if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT ||
-		    intel_encoder->type == INTEL_OUTPUT_EDP)
-		{
-			lane_count = intel_dp->lane_count;
-			break;
-		}
-	}
-
-	target_clock = mode->clock;
-	for_each_encoder_on_crtc(dev, crtc, intel_encoder) {
-		if (intel_encoder->type == INTEL_OUTPUT_EDP) {
-			target_clock = intel_edp_target_clock(intel_encoder,
-							      mode);
-			break;
-		}
-	}
+	intel_dp_set_clock(encoder, pipe_config, intel_dp->link_bw);
 
 	/*
-	 * Compute the GMCH and Link ratios. The '3' here is
-	 * the number of bytes_per_pixel post-LUT, which we always
-	 * set up for 8-bits of R/G/B, or 3 bytes total.
+	 * XXX: We have a strange regression where using the vbt edp bpp value
+	 * for the link bw computation results in black screens, the panel only
+	 * works when we do the computation at the usual 24bpp (but still
+	 * requires us to use 18bpp). Until that's fully debugged, stay
+	 * bug-for-bug compatible with the old code.
 	 */
-	intel_link_compute_m_n(intel_crtc->bpp, lane_count,
-			       target_clock, adjusted_mode->clock, &m_n);
-
-	if (IS_HASWELL(dev)) {
-		I915_WRITE(PIPE_DATA_M1(cpu_transcoder),
-			   TU_SIZE(m_n.tu) | m_n.gmch_m);
-		I915_WRITE(PIPE_DATA_N1(cpu_transcoder), m_n.gmch_n);
-		I915_WRITE(PIPE_LINK_M1(cpu_transcoder), m_n.link_m);
-		I915_WRITE(PIPE_LINK_N1(cpu_transcoder), m_n.link_n);
-	} else if (HAS_PCH_SPLIT(dev)) {
-		I915_WRITE(TRANSDATA_M1(pipe), TU_SIZE(m_n.tu) | m_n.gmch_m);
-		I915_WRITE(TRANSDATA_N1(pipe), m_n.gmch_n);
-		I915_WRITE(TRANSDPLINK_M1(pipe), m_n.link_m);
-		I915_WRITE(TRANSDPLINK_N1(pipe), m_n.link_n);
-	} else if (IS_VALLEYVIEW(dev)) {
-		I915_WRITE(PIPE_DATA_M1(pipe), TU_SIZE(m_n.tu) | m_n.gmch_m);
-		I915_WRITE(PIPE_DATA_N1(pipe), m_n.gmch_n);
-		I915_WRITE(PIPE_LINK_M1(pipe), m_n.link_m);
-		I915_WRITE(PIPE_LINK_N1(pipe), m_n.link_n);
-	} else {
-		I915_WRITE(PIPE_GMCH_DATA_M(pipe),
-			   TU_SIZE(m_n.tu) | m_n.gmch_m);
-		I915_WRITE(PIPE_GMCH_DATA_N(pipe), m_n.gmch_n);
-		I915_WRITE(PIPE_DP_LINK_M(pipe), m_n.link_m);
-		I915_WRITE(PIPE_DP_LINK_N(pipe), m_n.link_n);
+	if (is_edp(intel_dp) && dev_priv->edp.bpp) {
+		DRM_DEBUG_KMS("clamping display bpc (was %d) to eDP (%d)\n",
+			      bpp, dev_priv->edp.bpp);
+		bpp = min_t(int, bpp, dev_priv->edp.bpp);
 	}
+	pipe_config->pipe_bpp = bpp;
+
+	return true;
 }
 
 void intel_dp_init_link_config(struct intel_dp *intel_dp)
@@ -994,7 +925,7 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
 		else
 			intel_dp->DP |= DP_PLL_FREQ_270MHZ;
 	} else if (!HAS_PCH_CPT(dev) || is_cpu_edp(intel_dp)) {
-		if (!HAS_PCH_SPLIT(dev))
+		if (!HAS_PCH_SPLIT(dev) && !IS_VALLEYVIEW(dev))
 			intel_dp->DP |= intel_dp->color_range;
 
 		if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
@@ -1009,7 +940,7 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
 		if (intel_crtc->pipe == 1)
 			intel_dp->DP |= DP_PIPEB_SELECT;
 
-		if (is_cpu_edp(intel_dp)) {
+		if (is_cpu_edp(intel_dp) && !IS_VALLEYVIEW(dev)) {
 			/* don't miss out required setting for eDP */
 			if (adjusted_mode->clock < 200000)
 				intel_dp->DP |= DP_PLL_FREQ_160MHZ;
@@ -1020,7 +951,7 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
 		intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT;
 	}
 
-	if (is_cpu_edp(intel_dp))
+	if (is_cpu_edp(intel_dp) && !IS_VALLEYVIEW(dev))
 		ironlake_set_pll_edp(crtc, adjusted_mode->clock);
 }
 
@@ -1039,16 +970,20 @@ static void ironlake_wait_panel_status(struct intel_dp *intel_dp,
 {
 	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 pp_stat_reg, pp_ctrl_reg;
+
+	pp_stat_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_STATUS : PCH_PP_STATUS;
+	pp_ctrl_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_CONTROL : PCH_PP_CONTROL;
 
 	DRM_DEBUG_KMS("mask %08x value %08x status %08x control %08x\n",
-		      mask, value,
-		      I915_READ(PCH_PP_STATUS),
-		      I915_READ(PCH_PP_CONTROL));
+			mask, value,
+			I915_READ(pp_stat_reg),
+			I915_READ(pp_ctrl_reg));
 
-	if (_wait_for((I915_READ(PCH_PP_STATUS) & mask) == value, 5000, 10)) {
+	if (_wait_for((I915_READ(pp_stat_reg) & mask) == value, 5000, 10)) {
 		DRM_ERROR("Panel status timeout: status %08x control %08x\n",
-			  I915_READ(PCH_PP_STATUS),
-			  I915_READ(PCH_PP_CONTROL));
+				I915_READ(pp_stat_reg),
+				I915_READ(pp_ctrl_reg));
 	}
 }
 
@@ -1075,9 +1010,15 @@ static void ironlake_wait_panel_power_cycle(struct intel_dp *intel_dp)
  * is locked
  */
 
-static  u32 ironlake_get_pp_control(struct drm_i915_private *dev_priv)
+static  u32 ironlake_get_pp_control(struct intel_dp *intel_dp)
 {
-	u32	control = I915_READ(PCH_PP_CONTROL);
+	struct drm_device *dev = intel_dp_to_dev(intel_dp);
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 control;
+	u32 pp_ctrl_reg;
+
+	pp_ctrl_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_CONTROL : PCH_PP_CONTROL;
+	control = I915_READ(pp_ctrl_reg);
 
 	control &= ~PANEL_UNLOCK_MASK;
 	control |= PANEL_UNLOCK_REGS;
@@ -1089,6 +1030,7 @@ void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp)
 	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 pp;
+	u32 pp_stat_reg, pp_ctrl_reg;
 
 	if (!is_edp(intel_dp))
 		return;
@@ -1107,13 +1049,16 @@ void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp)
 	if (!ironlake_edp_have_panel_power(intel_dp))
 		ironlake_wait_panel_power_cycle(intel_dp);
 
-	pp = ironlake_get_pp_control(dev_priv);
+	pp = ironlake_get_pp_control(intel_dp);
 	pp |= EDP_FORCE_VDD;
-	I915_WRITE(PCH_PP_CONTROL, pp);
-	POSTING_READ(PCH_PP_CONTROL);
-	DRM_DEBUG_KMS("PCH_PP_STATUS: 0x%08x PCH_PP_CONTROL: 0x%08x\n",
-		      I915_READ(PCH_PP_STATUS), I915_READ(PCH_PP_CONTROL));
 
+	pp_stat_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_STATUS : PCH_PP_STATUS;
+	pp_ctrl_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_CONTROL : PCH_PP_CONTROL;
+
+	I915_WRITE(pp_ctrl_reg, pp);
+	POSTING_READ(pp_ctrl_reg);
+	DRM_DEBUG_KMS("PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n",
+			I915_READ(pp_stat_reg), I915_READ(pp_ctrl_reg));
 	/*
 	 * If the panel wasn't on, delay before accessing aux channel
 	 */
@@ -1128,19 +1073,23 @@ static void ironlake_panel_vdd_off_sync(struct intel_dp *intel_dp)
 	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 pp;
+	u32 pp_stat_reg, pp_ctrl_reg;
 
 	WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
 
 	if (!intel_dp->want_panel_vdd && ironlake_edp_have_panel_vdd(intel_dp)) {
-		pp = ironlake_get_pp_control(dev_priv);
+		pp = ironlake_get_pp_control(intel_dp);
 		pp &= ~EDP_FORCE_VDD;
-		I915_WRITE(PCH_PP_CONTROL, pp);
-		POSTING_READ(PCH_PP_CONTROL);
 
-		/* Make sure sequencer is idle before allowing subsequent activity */
-		DRM_DEBUG_KMS("PCH_PP_STATUS: 0x%08x PCH_PP_CONTROL: 0x%08x\n",
-			      I915_READ(PCH_PP_STATUS), I915_READ(PCH_PP_CONTROL));
+		pp_stat_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_STATUS : PCH_PP_STATUS;
+		pp_ctrl_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_CONTROL : PCH_PP_CONTROL;
 
+		I915_WRITE(pp_ctrl_reg, pp);
+		POSTING_READ(pp_ctrl_reg);
+
+		/* Make sure sequencer is idle before allowing subsequent activity */
+		DRM_DEBUG_KMS("PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n",
+		I915_READ(pp_stat_reg), I915_READ(pp_ctrl_reg));
 		msleep(intel_dp->panel_power_down_delay);
 	}
 }
@@ -1184,6 +1133,7 @@ void ironlake_edp_panel_on(struct intel_dp *intel_dp)
 	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 pp;
+	u32 pp_ctrl_reg;
 
 	if (!is_edp(intel_dp))
 		return;
@@ -1197,7 +1147,7 @@ void ironlake_edp_panel_on(struct intel_dp *intel_dp)
 
 	ironlake_wait_panel_power_cycle(intel_dp);
 
-	pp = ironlake_get_pp_control(dev_priv);
+	pp = ironlake_get_pp_control(intel_dp);
 	if (IS_GEN5(dev)) {
 		/* ILK workaround: disable reset around power sequence */
 		pp &= ~PANEL_POWER_RESET;
@@ -1209,8 +1159,10 @@ void ironlake_edp_panel_on(struct intel_dp *intel_dp)
 	if (!IS_GEN5(dev))
 		pp |= PANEL_POWER_RESET;
 
-	I915_WRITE(PCH_PP_CONTROL, pp);
-	POSTING_READ(PCH_PP_CONTROL);
+	pp_ctrl_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_CONTROL : PCH_PP_CONTROL;
+
+	I915_WRITE(pp_ctrl_reg, pp);
+	POSTING_READ(pp_ctrl_reg);
 
 	ironlake_wait_panel_on(intel_dp);
 
@@ -1226,6 +1178,7 @@ void ironlake_edp_panel_off(struct intel_dp *intel_dp)
 	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 pp;
+	u32 pp_ctrl_reg;
 
 	if (!is_edp(intel_dp))
 		return;
@@ -1234,12 +1187,15 @@ void ironlake_edp_panel_off(struct intel_dp *intel_dp)
 
 	WARN(!intel_dp->want_panel_vdd, "Need VDD to turn off panel\n");
 
-	pp = ironlake_get_pp_control(dev_priv);
+	pp = ironlake_get_pp_control(intel_dp);
 	/* We need to switch off panel power _and_ force vdd, for otherwise some
 	 * panels get very unhappy and cease to work. */
 	pp &= ~(POWER_TARGET_ON | EDP_FORCE_VDD | PANEL_POWER_RESET | EDP_BLC_ENABLE);
-	I915_WRITE(PCH_PP_CONTROL, pp);
-	POSTING_READ(PCH_PP_CONTROL);
+
+	pp_ctrl_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_CONTROL : PCH_PP_CONTROL;
+
+	I915_WRITE(pp_ctrl_reg, pp);
+	POSTING_READ(pp_ctrl_reg);
 
 	intel_dp->want_panel_vdd = false;
 
@@ -1253,6 +1209,7 @@ void ironlake_edp_backlight_on(struct intel_dp *intel_dp)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int pipe = to_intel_crtc(intel_dig_port->base.base.crtc)->pipe;
 	u32 pp;
+	u32 pp_ctrl_reg;
 
 	if (!is_edp(intel_dp))
 		return;
@@ -1265,10 +1222,13 @@ void ironlake_edp_backlight_on(struct intel_dp *intel_dp)
 	 * allowing it to appear.
 	 */
 	msleep(intel_dp->backlight_on_delay);
-	pp = ironlake_get_pp_control(dev_priv);
+	pp = ironlake_get_pp_control(intel_dp);
 	pp |= EDP_BLC_ENABLE;
-	I915_WRITE(PCH_PP_CONTROL, pp);
-	POSTING_READ(PCH_PP_CONTROL);
+
+	pp_ctrl_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_CONTROL : PCH_PP_CONTROL;
+
+	I915_WRITE(pp_ctrl_reg, pp);
+	POSTING_READ(pp_ctrl_reg);
 
 	intel_panel_enable_backlight(dev, pipe);
 }
@@ -1278,6 +1238,7 @@ void ironlake_edp_backlight_off(struct intel_dp *intel_dp)
 	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 pp;
+	u32 pp_ctrl_reg;
 
 	if (!is_edp(intel_dp))
 		return;
@@ -1285,10 +1246,13 @@ void ironlake_edp_backlight_off(struct intel_dp *intel_dp)
 	intel_panel_disable_backlight(dev);
 
 	DRM_DEBUG_KMS("\n");
-	pp = ironlake_get_pp_control(dev_priv);
+	pp = ironlake_get_pp_control(intel_dp);
 	pp &= ~EDP_BLC_ENABLE;
-	I915_WRITE(PCH_PP_CONTROL, pp);
-	POSTING_READ(PCH_PP_CONTROL);
+
+	pp_ctrl_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_CONTROL : PCH_PP_CONTROL;
+
+	I915_WRITE(pp_ctrl_reg, pp);
+	POSTING_READ(pp_ctrl_reg);
 	msleep(intel_dp->backlight_off_delay);
 }
 
@@ -1384,7 +1348,7 @@ static bool intel_dp_get_hw_state(struct intel_encoder *encoder,
 	if (!(tmp & DP_PORT_EN))
 		return false;
 
-	if (is_cpu_edp(intel_dp) && IS_GEN7(dev)) {
+	if (is_cpu_edp(intel_dp) && IS_GEN7(dev) && !IS_VALLEYVIEW(dev)) {
 		*pipe = PORT_TO_PIPE_CPT(tmp);
 	} else if (!HAS_PCH_CPT(dev) || is_cpu_edp(intel_dp)) {
 		*pipe = PORT_TO_PIPE(tmp);
@@ -1441,10 +1405,12 @@ static void intel_disable_dp(struct intel_encoder *encoder)
 static void intel_post_disable_dp(struct intel_encoder *encoder)
 {
 	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
+	struct drm_device *dev = encoder->base.dev;
 
 	if (is_cpu_edp(intel_dp)) {
 		intel_dp_link_down(intel_dp);
-		ironlake_edp_pll_off(intel_dp);
+		if (!IS_VALLEYVIEW(dev))
+			ironlake_edp_pll_off(intel_dp);
 	}
 }
 
@@ -1470,8 +1436,9 @@ static void intel_enable_dp(struct intel_encoder *encoder)
 static void intel_pre_enable_dp(struct intel_encoder *encoder)
 {
 	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
+	struct drm_device *dev = encoder->base.dev;
 
-	if (is_cpu_edp(intel_dp))
+	if (is_cpu_edp(intel_dp) && !IS_VALLEYVIEW(dev))
 		ironlake_edp_pll_on(intel_dp);
 }
 
@@ -1548,7 +1515,7 @@ intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, uint8_t voltage_swing)
 {
 	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 
-	if (IS_HASWELL(dev)) {
+	if (HAS_DDI(dev)) {
 		switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) {
 		case DP_TRAIN_VOLTAGE_SWING_400:
 			return DP_TRAIN_PRE_EMPHASIS_9_5;
@@ -1756,7 +1723,7 @@ intel_dp_set_signal_levels(struct intel_dp *intel_dp, uint32_t *DP)
 	uint32_t signal_levels, mask;
 	uint8_t train_set = intel_dp->train_set[0];
 
-	if (IS_HASWELL(dev)) {
+	if (HAS_DDI(dev)) {
 		signal_levels = intel_hsw_signal_levels(train_set);
 		mask = DDI_BUF_EMP_MASK;
 	} else if (IS_GEN7(dev) && is_cpu_edp(intel_dp) && !IS_VALLEYVIEW(dev)) {
@@ -1787,7 +1754,7 @@ intel_dp_set_link_train(struct intel_dp *intel_dp,
 	int ret;
 	uint32_t temp;
 
-	if (IS_HASWELL(dev)) {
+	if (HAS_DDI(dev)) {
 		temp = I915_READ(DP_TP_CTL(port));
 
 		if (dp_train_pat & DP_LINK_SCRAMBLING_DISABLE)
@@ -2028,7 +1995,7 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)
 	}
 
 	if (channel_eq)
-		DRM_DEBUG_KMS("Channel EQ done. DP Training successfull\n");
+		DRM_DEBUG_KMS("Channel EQ done. DP Training successful\n");
 
 	intel_dp_set_link_train(intel_dp, DP, DP_TRAINING_PATTERN_DISABLE);
 }
@@ -2311,6 +2278,16 @@ g4x_dp_detect(struct intel_dp *intel_dp)
 	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
 	uint32_t bit;
 
+	/* Can't disconnect eDP, but you can close the lid... */
+	if (is_edp(intel_dp)) {
+		enum drm_connector_status status;
+
+		status = intel_panel_detect(dev);
+		if (status == connector_status_unknown)
+			status = connector_status_connected;
+		return status;
+	}
+
 	switch (intel_dig_port->port) {
 	case PORT_B:
 		bit = PORTB_HOTPLUG_LIVE_STATUS;
@@ -2559,18 +2536,20 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder)
 {
 	struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
 	struct intel_dp *intel_dp = &intel_dig_port->dp;
+	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 
 	i2c_del_adapter(&intel_dp->adapter);
 	drm_encoder_cleanup(encoder);
 	if (is_edp(intel_dp)) {
 		cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
+		mutex_lock(&dev->mode_config.mutex);
 		ironlake_panel_vdd_off_sync(intel_dp);
+		mutex_unlock(&dev->mode_config.mutex);
 	}
 	kfree(intel_dig_port);
 }
 
 static const struct drm_encoder_helper_funcs intel_dp_helper_funcs = {
-	.mode_fixup = intel_dp_mode_fixup,
 	.mode_set = intel_dp_mode_set,
 };
 
@@ -2666,15 +2645,28 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev,
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct edp_power_seq cur, vbt, spec, final;
 	u32 pp_on, pp_off, pp_div, pp;
+	int pp_control_reg, pp_on_reg, pp_off_reg, pp_div_reg;
+
+	if (HAS_PCH_SPLIT(dev)) {
+		pp_control_reg = PCH_PP_CONTROL;
+		pp_on_reg = PCH_PP_ON_DELAYS;
+		pp_off_reg = PCH_PP_OFF_DELAYS;
+		pp_div_reg = PCH_PP_DIVISOR;
+	} else {
+		pp_control_reg = PIPEA_PP_CONTROL;
+		pp_on_reg = PIPEA_PP_ON_DELAYS;
+		pp_off_reg = PIPEA_PP_OFF_DELAYS;
+		pp_div_reg = PIPEA_PP_DIVISOR;
+	}
 
 	/* Workaround: Need to write PP_CONTROL with the unlock key as
 	 * the very first thing. */
-	pp = ironlake_get_pp_control(dev_priv);
-	I915_WRITE(PCH_PP_CONTROL, pp);
+	pp = ironlake_get_pp_control(intel_dp);
+	I915_WRITE(pp_control_reg, pp);
 
-	pp_on = I915_READ(PCH_PP_ON_DELAYS);
-	pp_off = I915_READ(PCH_PP_OFF_DELAYS);
-	pp_div = I915_READ(PCH_PP_DIVISOR);
+	pp_on = I915_READ(pp_on_reg);
+	pp_off = I915_READ(pp_off_reg);
+	pp_div = I915_READ(pp_div_reg);
 
 	/* Pull timing values out of registers */
 	cur.t1_t3 = (pp_on & PANEL_POWER_UP_DELAY_MASK) >>
@@ -2749,7 +2741,22 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
 					      struct edp_power_seq *seq)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	u32 pp_on, pp_off, pp_div;
+	u32 pp_on, pp_off, pp_div, port_sel = 0;
+	int div = HAS_PCH_SPLIT(dev) ? intel_pch_rawclk(dev) : intel_hrawclk(dev);
+	int pp_on_reg, pp_off_reg, pp_div_reg;
+
+	if (HAS_PCH_SPLIT(dev)) {
+		pp_on_reg = PCH_PP_ON_DELAYS;
+		pp_off_reg = PCH_PP_OFF_DELAYS;
+		pp_div_reg = PCH_PP_DIVISOR;
+	} else {
+		pp_on_reg = PIPEA_PP_ON_DELAYS;
+		pp_off_reg = PIPEA_PP_OFF_DELAYS;
+		pp_div_reg = PIPEA_PP_DIVISOR;
+	}
+
+	if (IS_VALLEYVIEW(dev))
+		port_sel = I915_READ(pp_on_reg) & 0xc0000000;
 
 	/* And finally store the new values in the power sequencer. */
 	pp_on = (seq->t1_t3 << PANEL_POWER_UP_DELAY_SHIFT) |
@@ -2758,8 +2765,7 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
 		 (seq->t10 << PANEL_POWER_DOWN_DELAY_SHIFT);
 	/* Compute the divisor for the pp clock, simply match the Bspec
 	 * formula. */
-	pp_div = ((100 * intel_pch_rawclk(dev))/2 - 1)
-			<< PP_REFERENCE_DIVIDER_SHIFT;
+	pp_div = ((100 * div)/2 - 1) << PP_REFERENCE_DIVIDER_SHIFT;
 	pp_div |= (DIV_ROUND_UP(seq->t11_t12, 1000)
 			<< PANEL_POWER_CYCLE_DELAY_SHIFT);
 
@@ -2767,19 +2773,21 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
 	 * power sequencer any more. */
 	if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) {
 		if (is_cpu_edp(intel_dp))
-			pp_on |= PANEL_POWER_PORT_DP_A;
+			port_sel = PANEL_POWER_PORT_DP_A;
 		else
-			pp_on |= PANEL_POWER_PORT_DP_D;
+			port_sel = PANEL_POWER_PORT_DP_D;
 	}
 
-	I915_WRITE(PCH_PP_ON_DELAYS, pp_on);
-	I915_WRITE(PCH_PP_OFF_DELAYS, pp_off);
-	I915_WRITE(PCH_PP_DIVISOR, pp_div);
+	pp_on |= port_sel;
+
+	I915_WRITE(pp_on_reg, pp_on);
+	I915_WRITE(pp_off_reg, pp_off);
+	I915_WRITE(pp_div_reg, pp_div);
 
 	DRM_DEBUG_KMS("panel power sequencer register settings: PP_ON %#x, PP_OFF %#x, PP_DIV %#x\n",
-		      I915_READ(PCH_PP_ON_DELAYS),
-		      I915_READ(PCH_PP_OFF_DELAYS),
-		      I915_READ(PCH_PP_DIVISOR));
+		      I915_READ(pp_on_reg),
+		      I915_READ(pp_off_reg),
+		      I915_READ(pp_div_reg));
 }
 
 void
@@ -2841,27 +2849,46 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 	else
 		intel_connector->get_hw_state = intel_connector_get_hw_state;
 
+	intel_dp->aux_ch_ctl_reg = intel_dp->output_reg + 0x10;
+	if (HAS_DDI(dev)) {
+		switch (intel_dig_port->port) {
+		case PORT_A:
+			intel_dp->aux_ch_ctl_reg = DPA_AUX_CH_CTL;
+			break;
+		case PORT_B:
+			intel_dp->aux_ch_ctl_reg = PCH_DPB_AUX_CH_CTL;
+			break;
+		case PORT_C:
+			intel_dp->aux_ch_ctl_reg = PCH_DPC_AUX_CH_CTL;
+			break;
+		case PORT_D:
+			intel_dp->aux_ch_ctl_reg = PCH_DPD_AUX_CH_CTL;
+			break;
+		default:
+			BUG();
+		}
+	}
 
 	/* Set up the DDC bus. */
 	switch (port) {
 	case PORT_A:
+		intel_encoder->hpd_pin = HPD_PORT_A;
 		name = "DPDDC-A";
 		break;
 	case PORT_B:
-		dev_priv->hotplug_supported_mask |= PORTB_HOTPLUG_INT_STATUS;
+		intel_encoder->hpd_pin = HPD_PORT_B;
 		name = "DPDDC-B";
 		break;
 	case PORT_C:
-		dev_priv->hotplug_supported_mask |= PORTC_HOTPLUG_INT_STATUS;
+		intel_encoder->hpd_pin = HPD_PORT_C;
 		name = "DPDDC-C";
 		break;
 	case PORT_D:
-		dev_priv->hotplug_supported_mask |= PORTD_HOTPLUG_INT_STATUS;
+		intel_encoder->hpd_pin = HPD_PORT_D;
 		name = "DPDDC-D";
 		break;
 	default:
-		WARN(1, "Invalid port %c\n", port_name(port));
-		break;
+		BUG();
 	}
 
 	if (is_edp(intel_dp))
@@ -2971,6 +2998,7 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
 			 DRM_MODE_ENCODER_TMDS);
 	drm_encoder_helper_add(&intel_encoder->base, &intel_dp_helper_funcs);
 
+	intel_encoder->compute_config = intel_dp_compute_config;
 	intel_encoder->enable = intel_enable_dp;
 	intel_encoder->pre_enable = intel_pre_enable_dp;
 	intel_encoder->disable = intel_disable_dp;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 07ebac6..d7bd031 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -33,12 +33,21 @@
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_dp_helper.h>
 
+/**
+ * _wait_for - magic (register) wait macro
+ *
+ * Does the right thing for modeset paths when run under kdgb or similar atomic
+ * contexts. Note that it's important that we check the condition again after
+ * having timed out, since the timeout could be due to preemption or similar and
+ * we've never had a chance to check the condition before the timeout.
+ */
 #define _wait_for(COND, MS, W) ({ \
-	unsigned long timeout__ = jiffies + msecs_to_jiffies(MS);	\
+	unsigned long timeout__ = jiffies + msecs_to_jiffies(MS) + 1;	\
 	int ret__ = 0;							\
 	while (!(COND)) {						\
 		if (time_after(jiffies, timeout__)) {			\
-			ret__ = -ETIMEDOUT;				\
+			if (!(COND))					\
+				ret__ = -ETIMEDOUT;			\
 			break;						\
 		}							\
 		if (W && drm_can_sleep())  {				\
@@ -50,21 +59,10 @@
 	ret__;								\
 })
 
-#define wait_for_atomic_us(COND, US) ({ \
-	unsigned long timeout__ = jiffies + usecs_to_jiffies(US);	\
-	int ret__ = 0;							\
-	while (!(COND)) {						\
-		if (time_after(jiffies, timeout__)) {			\
-			ret__ = -ETIMEDOUT;				\
-			break;						\
-		}							\
-		cpu_relax();						\
-	}								\
-	ret__;								\
-})
-
 #define wait_for(COND, MS) _wait_for(COND, MS, 1)
 #define wait_for_atomic(COND, MS) _wait_for(COND, MS, 0)
+#define wait_for_atomic_us(COND, US) _wait_for((COND), \
+					       DIV_ROUND_UP((US), 1000), 0)
 
 #define KHz(x) (1000*x)
 #define MHz(x) KHz(1000*x)
@@ -101,34 +99,6 @@
 #define INTEL_DVO_CHIP_TMDS 2
 #define INTEL_DVO_CHIP_TVOUT 4
 
-/* drm_display_mode->private_flags */
-#define INTEL_MODE_PIXEL_MULTIPLIER_SHIFT (0x0)
-#define INTEL_MODE_PIXEL_MULTIPLIER_MASK (0xf << INTEL_MODE_PIXEL_MULTIPLIER_SHIFT)
-#define INTEL_MODE_DP_FORCE_6BPC (0x10)
-/* This flag must be set by the encoder's mode_fixup if it changes the crtc
- * timings in the mode to prevent the crtc fixup from overwriting them.
- * Currently only lvds needs that. */
-#define INTEL_MODE_CRTC_TIMINGS_SET (0x20)
-/*
- * Set when limited 16-235 (as opposed to full 0-255) RGB color range is
- * to be used.
- */
-#define INTEL_MODE_LIMITED_COLOR_RANGE (0x40)
-
-static inline void
-intel_mode_set_pixel_multiplier(struct drm_display_mode *mode,
-				int multiplier)
-{
-	mode->clock *= multiplier;
-	mode->private_flags |= multiplier;
-}
-
-static inline int
-intel_mode_get_pixel_multiplier(const struct drm_display_mode *mode)
-{
-	return (mode->private_flags & INTEL_MODE_PIXEL_MULTIPLIER_MASK) >> INTEL_MODE_PIXEL_MULTIPLIER_SHIFT;
-}
-
 struct intel_framebuffer {
 	struct drm_framebuffer base;
 	struct drm_i915_gem_object *obj;
@@ -158,9 +128,12 @@ struct intel_encoder {
 	bool cloneable;
 	bool connectors_active;
 	void (*hot_plug)(struct intel_encoder *);
+	bool (*compute_config)(struct intel_encoder *,
+			       struct intel_crtc_config *);
 	void (*pre_pll_enable)(struct intel_encoder *);
 	void (*pre_enable)(struct intel_encoder *);
 	void (*enable)(struct intel_encoder *);
+	void (*mode_set)(struct intel_encoder *intel_encoder);
 	void (*disable)(struct intel_encoder *);
 	void (*post_disable)(struct intel_encoder *);
 	/* Read out the current hw state of this connector, returning true if
@@ -168,6 +141,7 @@ struct intel_encoder {
 	 * it is connected to in the pipe parameter. */
 	bool (*get_hw_state)(struct intel_encoder *, enum pipe *pipe);
 	int crtc_mask;
+	enum hpd_pin hpd_pin;
 };
 
 struct intel_panel {
@@ -199,6 +173,51 @@ struct intel_connector {
 	struct edid *edid;
 };
 
+struct intel_crtc_config {
+	struct drm_display_mode requested_mode;
+	struct drm_display_mode adjusted_mode;
+	/* This flag must be set by the encoder's compute_config callback if it
+	 * changes the crtc timings in the mode to prevent the crtc fixup from
+	 * overwriting them.  Currently only lvds needs that. */
+	bool timings_set;
+	/* Whether to set up the PCH/FDI. Note that we never allow sharing
+	 * between pch encoders and cpu encoders. */
+	bool has_pch_encoder;
+
+	/*
+	 * Use reduced/limited/broadcast rbg range, compressing from the full
+	 * range fed into the crtcs.
+	 */
+	bool limited_color_range;
+
+	/* DP has a bunch of special case unfortunately, so mark the pipe
+	 * accordingly. */
+	bool has_dp_encoder;
+	bool dither;
+
+	/* Controls for the clock computation, to override various stages. */
+	bool clock_set;
+
+	/* Settings for the intel dpll used on pretty much everything but
+	 * haswell. */
+	struct dpll {
+		unsigned n;
+		unsigned m1, m2;
+		unsigned p1, p2;
+	} dpll;
+
+	int pipe_bpp;
+	struct intel_link_m_n dp_m_n;
+	/**
+	 * This is currently used by DP and HDMI encoders since those can have a
+	 * target pixel clock != the port link clock (which is currently stored
+	 * in adjusted_mode->clock).
+	 */
+	int pixel_target_clock;
+	/* Used by SDVO (and if we ever fix it, HDMI). */
+	unsigned pixel_multiplier;
+};
+
 struct intel_crtc {
 	struct drm_crtc base;
 	enum pipe pipe;
@@ -230,7 +249,8 @@ struct intel_crtc {
 	int16_t cursor_x, cursor_y;
 	int16_t cursor_width, cursor_height;
 	bool cursor_visible;
-	unsigned int bpp;
+
+	struct intel_crtc_config config;
 
 	/* We can share PLLs across outputs if the timings match */
 	struct intel_pch_pll *pch_pll;
@@ -242,11 +262,16 @@ struct intel_crtc {
 
 struct intel_plane {
 	struct drm_plane base;
+	int plane;
 	enum pipe pipe;
 	struct drm_i915_gem_object *obj;
 	bool can_scale;
 	int max_downscale;
 	u32 lut_r[1024], lut_g[1024], lut_b[1024];
+	int crtc_x, crtc_y;
+	unsigned int crtc_w, crtc_h;
+	uint32_t src_x, src_y;
+	uint32_t src_w, src_h;
 	void (*update_plane)(struct drm_plane *plane,
 			     struct drm_framebuffer *fb,
 			     struct drm_i915_gem_object *obj,
@@ -347,7 +372,7 @@ struct dip_infoframe {
 } __attribute__((packed));
 
 struct intel_hdmi {
-	u32 sdvox_reg;
+	u32 hdmi_reg;
 	int ddc_bus;
 	uint32_t color_range;
 	bool color_range_auto;
@@ -366,6 +391,7 @@ struct intel_hdmi {
 
 struct intel_dp {
 	uint32_t output_reg;
+	uint32_t aux_ch_ctl_reg;
 	uint32_t DP;
 	uint8_t  link_configuration[DP_LINK_CONFIGURATION_SIZE];
 	bool has_audio;
@@ -443,13 +469,12 @@ extern void intel_attach_broadcast_rgb_property(struct drm_connector *connector)
 
 extern void intel_crt_init(struct drm_device *dev);
 extern void intel_hdmi_init(struct drm_device *dev,
-			    int sdvox_reg, enum port port);
+			    int hdmi_reg, enum port port);
 extern void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
 				      struct intel_connector *intel_connector);
 extern struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder);
-extern bool intel_hdmi_mode_fixup(struct drm_encoder *encoder,
-				  const struct drm_display_mode *mode,
-				  struct drm_display_mode *adjusted_mode);
+extern bool intel_hdmi_compute_config(struct intel_encoder *encoder,
+				      struct intel_crtc_config *pipe_config);
 extern void intel_dip_infoframe_csum(struct dip_infoframe *avi_if);
 extern bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg,
 			    bool is_sdvob);
@@ -464,18 +489,14 @@ extern void intel_dp_init(struct drm_device *dev, int output_reg,
 			  enum port port);
 extern void intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 				    struct intel_connector *intel_connector);
-void
-intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
-		 struct drm_display_mode *adjusted_mode);
 extern void intel_dp_init_link_config(struct intel_dp *intel_dp);
 extern void intel_dp_start_link_train(struct intel_dp *intel_dp);
 extern void intel_dp_complete_link_train(struct intel_dp *intel_dp);
 extern void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode);
 extern void intel_dp_encoder_destroy(struct drm_encoder *encoder);
 extern void intel_dp_check_link_status(struct intel_dp *intel_dp);
-extern bool intel_dp_mode_fixup(struct drm_encoder *encoder,
-				const struct drm_display_mode *mode,
-				struct drm_display_mode *adjusted_mode);
+extern bool intel_dp_compute_config(struct intel_encoder *encoder,
+				    struct intel_crtc_config *pipe_config);
 extern bool intel_dpd_is_edp(struct drm_device *dev);
 extern void ironlake_edp_backlight_on(struct intel_dp *intel_dp);
 extern void ironlake_edp_backlight_off(struct intel_dp *intel_dp);
@@ -483,11 +504,8 @@ extern void ironlake_edp_panel_on(struct intel_dp *intel_dp);
 extern void ironlake_edp_panel_off(struct intel_dp *intel_dp);
 extern void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp);
 extern void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync);
-extern void intel_edp_link_config(struct intel_encoder *, int *, int *);
-extern int intel_edp_target_clock(struct intel_encoder *,
-				  struct drm_display_mode *mode);
 extern bool intel_encoder_is_pch_edp(struct drm_encoder *encoder);
-extern int intel_plane_init(struct drm_device *dev, enum pipe pipe);
+extern int intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane);
 extern void intel_flush_display_plane(struct drm_i915_private *dev_priv,
 				      enum plane plane);
 
@@ -531,6 +549,7 @@ extern bool intel_encoder_check_is_cloned(struct intel_encoder *encoder);
 extern void intel_connector_dpms(struct drm_connector *, int mode);
 extern bool intel_connector_get_hw_state(struct intel_connector *connector);
 extern void intel_modeset_check_state(struct drm_device *dev);
+extern void intel_plane_restore(struct drm_plane *plane);
 
 
 static inline struct intel_encoder *intel_attached_encoder(struct drm_connector *connector)
@@ -636,6 +655,10 @@ extern void intel_init_clock_gating(struct drm_device *dev);
 extern void intel_write_eld(struct drm_encoder *encoder,
 			    struct drm_display_mode *mode);
 extern void intel_cpt_verify_modeset(struct drm_device *dev, int pipe);
+extern void intel_cpu_transcoder_set_m_n(struct intel_crtc *crtc,
+					 struct intel_link_m_n *m_n);
+extern void intel_pch_transcoder_set_m_n(struct intel_crtc *crtc,
+					 struct intel_link_m_n *m_n);
 extern void intel_prepare_ddi(struct drm_device *dev);
 extern void hsw_fdi_link_train(struct drm_crtc *crtc);
 extern void intel_ddi_init(struct drm_device *dev, enum port port);
@@ -681,7 +704,7 @@ extern bool intel_ddi_get_hw_state(struct intel_encoder *encoder,
 				   enum pipe *pipe);
 extern int intel_ddi_get_cdclk_freq(struct drm_i915_private *dev_priv);
 extern void intel_ddi_pll_init(struct drm_device *dev);
-extern void intel_ddi_enable_pipe_func(struct drm_crtc *crtc);
+extern void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc);
 extern void intel_ddi_disable_transcoder_func(struct drm_i915_private *dev_priv,
 					      enum transcoder cpu_transcoder);
 extern void intel_ddi_enable_pipe_clock(struct intel_crtc *intel_crtc);
@@ -695,4 +718,6 @@ extern bool
 intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector);
 extern void intel_ddi_fdi_disable(struct drm_crtc *crtc);
 
+extern void intel_display_handle_reset(struct drm_device *dev);
+
 #endif /* __INTEL_DRV_H__ */
diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c
index 981bdce..8d81c929 100644
--- a/drivers/gpu/drm/i915/intel_fb.c
+++ b/drivers/gpu/drm/i915/intel_fb.c
@@ -150,7 +150,8 @@ static int intelfb_create(struct drm_fb_helper *helper,
 	}
 	info->screen_size = size;
 
-//	memset(info->screen_base, 0, size);
+	/* This driver doesn't need a VT switch to restore the mode on resume */
+	info->skip_vt_switch = true;
 
 	drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth);
 	drm_fb_helper_fill_var(info, &ifbdev->helper, sizes->fb_width, sizes->fb_height);
@@ -227,7 +228,7 @@ int intel_fbdev_init(struct drm_device *dev)
 	ifbdev->helper.funcs = &intel_fb_helper_funcs;
 
 	ret = drm_fb_helper_init(dev, &ifbdev->helper,
-				 dev_priv->num_pipe,
+				 INTEL_INFO(dev)->num_pipes,
 				 INTELFB_CONN_LIMIT);
 	if (ret) {
 		kfree(ifbdev);
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index fa8ec4a..ee4a8da 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -50,7 +50,7 @@ assert_hdmi_port_disabled(struct intel_hdmi *intel_hdmi)
 
 	enabled_bits = HAS_DDI(dev) ? DDI_BUF_CTL_ENABLE : SDVO_ENABLE;
 
-	WARN(I915_READ(intel_hdmi->sdvox_reg) & enabled_bits,
+	WARN(I915_READ(intel_hdmi->hdmi_reg) & enabled_bits,
 	     "HDMI port enabled, expecting disabled\n");
 }
 
@@ -120,13 +120,14 @@ static u32 hsw_infoframe_enable(struct dip_infoframe *frame)
 	}
 }
 
-static u32 hsw_infoframe_data_reg(struct dip_infoframe *frame, enum pipe pipe)
+static u32 hsw_infoframe_data_reg(struct dip_infoframe *frame,
+				  enum transcoder cpu_transcoder)
 {
 	switch (frame->type) {
 	case DIP_TYPE_AVI:
-		return HSW_TVIDEO_DIP_AVI_DATA(pipe);
+		return HSW_TVIDEO_DIP_AVI_DATA(cpu_transcoder);
 	case DIP_TYPE_SPD:
-		return HSW_TVIDEO_DIP_SPD_DATA(pipe);
+		return HSW_TVIDEO_DIP_SPD_DATA(cpu_transcoder);
 	default:
 		DRM_DEBUG_DRIVER("unknown info frame type %d\n", frame->type);
 		return 0;
@@ -293,8 +294,8 @@ static void hsw_write_infoframe(struct drm_encoder *encoder,
 	struct drm_device *dev = encoder->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
-	u32 ctl_reg = HSW_TVIDEO_DIP_CTL(intel_crtc->pipe);
-	u32 data_reg = hsw_infoframe_data_reg(frame, intel_crtc->pipe);
+	u32 ctl_reg = HSW_TVIDEO_DIP_CTL(intel_crtc->cpu_transcoder);
+	u32 data_reg = hsw_infoframe_data_reg(frame, intel_crtc->cpu_transcoder);
 	unsigned int i, len = DIP_HEADER_SIZE + frame->len;
 	u32 val = I915_READ(ctl_reg);
 
@@ -332,6 +333,7 @@ static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder,
 					 struct drm_display_mode *adjusted_mode)
 {
 	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
+	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
 	struct dip_infoframe avi_if = {
 		.type = DIP_TYPE_AVI,
 		.ver = DIP_VERSION_AVI,
@@ -342,7 +344,7 @@ static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder,
 		avi_if.body.avi.YQ_CN_PR |= DIP_AVI_PR_2;
 
 	if (intel_hdmi->rgb_quant_range_selectable) {
-		if (adjusted_mode->private_flags & INTEL_MODE_LIMITED_COLOR_RANGE)
+		if (intel_crtc->config.limited_color_range)
 			avi_if.body.avi.ITC_EC_Q_SC |= DIP_AVI_RGB_QUANT_RANGE_LIMITED;
 		else
 			avi_if.body.avi.ITC_EC_Q_SC |= DIP_AVI_RGB_QUANT_RANGE_FULL;
@@ -568,7 +570,7 @@ static void hsw_set_infoframes(struct drm_encoder *encoder,
 	struct drm_i915_private *dev_priv = encoder->dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
 	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
-	u32 reg = HSW_TVIDEO_DIP_CTL(intel_crtc->pipe);
+	u32 reg = HSW_TVIDEO_DIP_CTL(intel_crtc->cpu_transcoder);
 	u32 val = I915_READ(reg);
 
 	assert_hdmi_port_disabled(intel_hdmi);
@@ -597,40 +599,40 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder,
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
 	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
-	u32 sdvox;
+	u32 hdmi_val;
 
-	sdvox = SDVO_ENCODING_HDMI;
-	if (!HAS_PCH_SPLIT(dev))
-		sdvox |= intel_hdmi->color_range;
+	hdmi_val = SDVO_ENCODING_HDMI;
+	if (!HAS_PCH_SPLIT(dev) && !IS_VALLEYVIEW(dev))
+		hdmi_val |= intel_hdmi->color_range;
 	if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
-		sdvox |= SDVO_VSYNC_ACTIVE_HIGH;
+		hdmi_val |= SDVO_VSYNC_ACTIVE_HIGH;
 	if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
-		sdvox |= SDVO_HSYNC_ACTIVE_HIGH;
+		hdmi_val |= SDVO_HSYNC_ACTIVE_HIGH;
 
-	if (intel_crtc->bpp > 24)
-		sdvox |= COLOR_FORMAT_12bpc;
+	if (intel_crtc->config.pipe_bpp > 24)
+		hdmi_val |= HDMI_COLOR_FORMAT_12bpc;
 	else
-		sdvox |= COLOR_FORMAT_8bpc;
+		hdmi_val |= SDVO_COLOR_FORMAT_8bpc;
 
 	/* Required on CPT */
 	if (intel_hdmi->has_hdmi_sink && HAS_PCH_CPT(dev))
-		sdvox |= HDMI_MODE_SELECT;
+		hdmi_val |= HDMI_MODE_SELECT_HDMI;
 
 	if (intel_hdmi->has_audio) {
 		DRM_DEBUG_DRIVER("Enabling HDMI audio on pipe %c\n",
 				 pipe_name(intel_crtc->pipe));
-		sdvox |= SDVO_AUDIO_ENABLE;
-		sdvox |= SDVO_NULL_PACKETS_DURING_VSYNC;
+		hdmi_val |= SDVO_AUDIO_ENABLE;
+		hdmi_val |= HDMI_MODE_SELECT_HDMI;
 		intel_write_eld(encoder, adjusted_mode);
 	}
 
 	if (HAS_PCH_CPT(dev))
-		sdvox |= PORT_TRANS_SEL_CPT(intel_crtc->pipe);
-	else if (intel_crtc->pipe == PIPE_B)
-		sdvox |= SDVO_PIPE_B_SELECT;
+		hdmi_val |= SDVO_PIPE_SEL_CPT(intel_crtc->pipe);
+	else
+		hdmi_val |= SDVO_PIPE_SEL(intel_crtc->pipe);
 
-	I915_WRITE(intel_hdmi->sdvox_reg, sdvox);
-	POSTING_READ(intel_hdmi->sdvox_reg);
+	I915_WRITE(intel_hdmi->hdmi_reg, hdmi_val);
+	POSTING_READ(intel_hdmi->hdmi_reg);
 
 	intel_hdmi->set_infoframes(encoder, adjusted_mode);
 }
@@ -643,7 +645,7 @@ static bool intel_hdmi_get_hw_state(struct intel_encoder *encoder,
 	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
 	u32 tmp;
 
-	tmp = I915_READ(intel_hdmi->sdvox_reg);
+	tmp = I915_READ(intel_hdmi->hdmi_reg);
 
 	if (!(tmp & SDVO_ENABLE))
 		return false;
@@ -660,6 +662,7 @@ static void intel_enable_hdmi(struct intel_encoder *encoder)
 {
 	struct drm_device *dev = encoder->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
 	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
 	u32 temp;
 	u32 enable_bits = SDVO_ENABLE;
@@ -667,38 +670,32 @@ static void intel_enable_hdmi(struct intel_encoder *encoder)
 	if (intel_hdmi->has_audio)
 		enable_bits |= SDVO_AUDIO_ENABLE;
 
-	temp = I915_READ(intel_hdmi->sdvox_reg);
+	temp = I915_READ(intel_hdmi->hdmi_reg);
 
 	/* HW workaround for IBX, we need to move the port to transcoder A
-	 * before disabling it. */
-	if (HAS_PCH_IBX(dev)) {
-		struct drm_crtc *crtc = encoder->base.crtc;
-		int pipe = crtc ? to_intel_crtc(crtc)->pipe : -1;
-
-		/* Restore the transcoder select bit. */
-		if (pipe == PIPE_B)
-			enable_bits |= SDVO_PIPE_B_SELECT;
-	}
+	 * before disabling it, so restore the transcoder select bit here. */
+	if (HAS_PCH_IBX(dev))
+		enable_bits |= SDVO_PIPE_SEL(intel_crtc->pipe);
 
 	/* HW workaround, need to toggle enable bit off and on for 12bpc, but
 	 * we do this anyway which shows more stable in testing.
 	 */
 	if (HAS_PCH_SPLIT(dev)) {
-		I915_WRITE(intel_hdmi->sdvox_reg, temp & ~SDVO_ENABLE);
-		POSTING_READ(intel_hdmi->sdvox_reg);
+		I915_WRITE(intel_hdmi->hdmi_reg, temp & ~SDVO_ENABLE);
+		POSTING_READ(intel_hdmi->hdmi_reg);
 	}
 
 	temp |= enable_bits;
 
-	I915_WRITE(intel_hdmi->sdvox_reg, temp);
-	POSTING_READ(intel_hdmi->sdvox_reg);
+	I915_WRITE(intel_hdmi->hdmi_reg, temp);
+	POSTING_READ(intel_hdmi->hdmi_reg);
 
 	/* HW workaround, need to write this twice for issue that may result
 	 * in first write getting masked.
 	 */
 	if (HAS_PCH_SPLIT(dev)) {
-		I915_WRITE(intel_hdmi->sdvox_reg, temp);
-		POSTING_READ(intel_hdmi->sdvox_reg);
+		I915_WRITE(intel_hdmi->hdmi_reg, temp);
+		POSTING_READ(intel_hdmi->hdmi_reg);
 	}
 }
 
@@ -710,7 +707,7 @@ static void intel_disable_hdmi(struct intel_encoder *encoder)
 	u32 temp;
 	u32 enable_bits = SDVO_ENABLE | SDVO_AUDIO_ENABLE;
 
-	temp = I915_READ(intel_hdmi->sdvox_reg);
+	temp = I915_READ(intel_hdmi->hdmi_reg);
 
 	/* HW workaround for IBX, we need to move the port to transcoder A
 	 * before disabling it. */
@@ -720,12 +717,12 @@ static void intel_disable_hdmi(struct intel_encoder *encoder)
 
 		if (temp & SDVO_PIPE_B_SELECT) {
 			temp &= ~SDVO_PIPE_B_SELECT;
-			I915_WRITE(intel_hdmi->sdvox_reg, temp);
-			POSTING_READ(intel_hdmi->sdvox_reg);
+			I915_WRITE(intel_hdmi->hdmi_reg, temp);
+			POSTING_READ(intel_hdmi->hdmi_reg);
 
 			/* Again we need to write this twice. */
-			I915_WRITE(intel_hdmi->sdvox_reg, temp);
-			POSTING_READ(intel_hdmi->sdvox_reg);
+			I915_WRITE(intel_hdmi->hdmi_reg, temp);
+			POSTING_READ(intel_hdmi->hdmi_reg);
 
 			/* Transcoder selection bits only update
 			 * effectively on vblank. */
@@ -740,21 +737,21 @@ static void intel_disable_hdmi(struct intel_encoder *encoder)
 	 * we do this anyway which shows more stable in testing.
 	 */
 	if (HAS_PCH_SPLIT(dev)) {
-		I915_WRITE(intel_hdmi->sdvox_reg, temp & ~SDVO_ENABLE);
-		POSTING_READ(intel_hdmi->sdvox_reg);
+		I915_WRITE(intel_hdmi->hdmi_reg, temp & ~SDVO_ENABLE);
+		POSTING_READ(intel_hdmi->hdmi_reg);
 	}
 
 	temp &= ~enable_bits;
 
-	I915_WRITE(intel_hdmi->sdvox_reg, temp);
-	POSTING_READ(intel_hdmi->sdvox_reg);
+	I915_WRITE(intel_hdmi->hdmi_reg, temp);
+	POSTING_READ(intel_hdmi->hdmi_reg);
 
 	/* HW workaround, need to write this twice for issue that may result
 	 * in first write getting masked.
 	 */
 	if (HAS_PCH_SPLIT(dev)) {
-		I915_WRITE(intel_hdmi->sdvox_reg, temp);
-		POSTING_READ(intel_hdmi->sdvox_reg);
+		I915_WRITE(intel_hdmi->hdmi_reg, temp);
+		POSTING_READ(intel_hdmi->hdmi_reg);
 	}
 }
 
@@ -772,23 +769,40 @@ static int intel_hdmi_mode_valid(struct drm_connector *connector,
 	return MODE_OK;
 }
 
-bool intel_hdmi_mode_fixup(struct drm_encoder *encoder,
-			   const struct drm_display_mode *mode,
-			   struct drm_display_mode *adjusted_mode)
+bool intel_hdmi_compute_config(struct intel_encoder *encoder,
+			       struct intel_crtc_config *pipe_config)
 {
-	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
+	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
+	struct drm_device *dev = encoder->base.dev;
+	struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
 
 	if (intel_hdmi->color_range_auto) {
 		/* See CEA-861-E - 5.1 Default Encoding Parameters */
 		if (intel_hdmi->has_hdmi_sink &&
 		    drm_match_cea_mode(adjusted_mode) > 1)
-			intel_hdmi->color_range = SDVO_COLOR_RANGE_16_235;
+			intel_hdmi->color_range = HDMI_COLOR_RANGE_16_235;
 		else
 			intel_hdmi->color_range = 0;
 	}
 
 	if (intel_hdmi->color_range)
-		adjusted_mode->private_flags |= INTEL_MODE_LIMITED_COLOR_RANGE;
+		pipe_config->limited_color_range = true;
+
+	if (HAS_PCH_SPLIT(dev) && !HAS_DDI(dev))
+		pipe_config->has_pch_encoder = true;
+
+	/*
+	 * HDMI is either 12 or 8, so if the display lets 10bpc sneak
+	 * through, clamp it down. Note that g4x/vlv don't support 12bpc hdmi
+	 * outputs.
+	 */
+	if (pipe_config->pipe_bpp > 8*3 && HAS_PCH_SPLIT(dev)) {
+		DRM_DEBUG_KMS("forcing bpc to 12 for HDMI\n");
+		pipe_config->pipe_bpp = 12*3;
+	} else {
+		DRM_DEBUG_KMS("forcing bpc to 8 for HDMI\n");
+		pipe_config->pipe_bpp = 8*3;
+	}
 
 	return true;
 }
@@ -916,7 +930,7 @@ intel_hdmi_set_property(struct drm_connector *connector,
 			break;
 		case INTEL_BROADCAST_RGB_LIMITED:
 			intel_hdmi->color_range_auto = false;
-			intel_hdmi->color_range = SDVO_COLOR_RANGE_16_235;
+			intel_hdmi->color_range = HDMI_COLOR_RANGE_16_235;
 			break;
 		default:
 			return -EINVAL;
@@ -941,7 +955,6 @@ static void intel_hdmi_destroy(struct drm_connector *connector)
 }
 
 static const struct drm_encoder_helper_funcs intel_hdmi_helper_funcs = {
-	.mode_fixup = intel_hdmi_mode_fixup,
 	.mode_set = intel_hdmi_mode_set,
 };
 
@@ -992,29 +1005,30 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
 	switch (port) {
 	case PORT_B:
 		intel_hdmi->ddc_bus = GMBUS_PORT_DPB;
-		dev_priv->hotplug_supported_mask |= PORTB_HOTPLUG_INT_STATUS;
+		intel_encoder->hpd_pin = HPD_PORT_B;
 		break;
 	case PORT_C:
 		intel_hdmi->ddc_bus = GMBUS_PORT_DPC;
-		dev_priv->hotplug_supported_mask |= PORTC_HOTPLUG_INT_STATUS;
+		intel_encoder->hpd_pin = HPD_PORT_C;
 		break;
 	case PORT_D:
 		intel_hdmi->ddc_bus = GMBUS_PORT_DPD;
-		dev_priv->hotplug_supported_mask |= PORTD_HOTPLUG_INT_STATUS;
+		intel_encoder->hpd_pin = HPD_PORT_D;
 		break;
 	case PORT_A:
+		intel_encoder->hpd_pin = HPD_PORT_A;
 		/* Internal port only for eDP. */
 	default:
 		BUG();
 	}
 
-	if (!HAS_PCH_SPLIT(dev)) {
-		intel_hdmi->write_infoframe = g4x_write_infoframe;
-		intel_hdmi->set_infoframes = g4x_set_infoframes;
-	} else if (IS_VALLEYVIEW(dev)) {
+	if (IS_VALLEYVIEW(dev)) {
 		intel_hdmi->write_infoframe = vlv_write_infoframe;
 		intel_hdmi->set_infoframes = vlv_set_infoframes;
-	} else if (IS_HASWELL(dev)) {
+	} else if (!HAS_PCH_SPLIT(dev)) {
+		intel_hdmi->write_infoframe = g4x_write_infoframe;
+		intel_hdmi->set_infoframes = g4x_set_infoframes;
+	} else if (HAS_DDI(dev)) {
 		intel_hdmi->write_infoframe = hsw_write_infoframe;
 		intel_hdmi->set_infoframes = hsw_set_infoframes;
 	} else if (HAS_PCH_IBX(dev)) {
@@ -1045,7 +1059,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
 	}
 }
 
-void intel_hdmi_init(struct drm_device *dev, int sdvox_reg, enum port port)
+void intel_hdmi_init(struct drm_device *dev, int hdmi_reg, enum port port)
 {
 	struct intel_digital_port *intel_dig_port;
 	struct intel_encoder *intel_encoder;
@@ -1069,6 +1083,7 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg, enum port port)
 			 DRM_MODE_ENCODER_TMDS);
 	drm_encoder_helper_add(&intel_encoder->base, &intel_hdmi_helper_funcs);
 
+	intel_encoder->compute_config = intel_hdmi_compute_config;
 	intel_encoder->enable = intel_enable_hdmi;
 	intel_encoder->disable = intel_disable_hdmi;
 	intel_encoder->get_hw_state = intel_hdmi_get_hw_state;
@@ -1078,7 +1093,7 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg, enum port port)
 	intel_encoder->cloneable = false;
 
 	intel_dig_port->port = port;
-	intel_dig_port->hdmi.sdvox_reg = sdvox_reg;
+	intel_dig_port->hdmi.hdmi_reg = hdmi_reg;
 	intel_dig_port->dp.output_reg = 0;
 
 	intel_hdmi_init_connector(intel_dig_port, intel_connector);
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index 3d1d974..ca2d903 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -261,8 +261,6 @@ centre_horizontally(struct drm_display_mode *mode,
 
 	mode->crtc_hsync_start = mode->crtc_hblank_start + sync_pos;
 	mode->crtc_hsync_end = mode->crtc_hsync_start + sync_width;
-
-	mode->private_flags |= INTEL_MODE_CRTC_TIMINGS_SET;
 }
 
 static void
@@ -284,8 +282,6 @@ centre_vertically(struct drm_display_mode *mode,
 
 	mode->crtc_vsync_start = mode->crtc_vblank_start + sync_pos;
 	mode->crtc_vsync_end = mode->crtc_vsync_start + sync_width;
-
-	mode->private_flags |= INTEL_MODE_CRTC_TIMINGS_SET;
 }
 
 static inline u32 panel_fitter_scaling(u32 source, u32 target)
@@ -301,17 +297,20 @@ static inline u32 panel_fitter_scaling(u32 source, u32 target)
 	return (FACTOR * ratio + FACTOR/2) / FACTOR;
 }
 
-static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
-				  const struct drm_display_mode *mode,
-				  struct drm_display_mode *adjusted_mode)
+static bool intel_lvds_compute_config(struct intel_encoder *intel_encoder,
+				      struct intel_crtc_config *pipe_config)
 {
-	struct drm_device *dev = encoder->dev;
+	struct drm_device *dev = intel_encoder->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(encoder);
+	struct intel_lvds_encoder *lvds_encoder =
+		to_lvds_encoder(&intel_encoder->base);
 	struct intel_connector *intel_connector =
 		&lvds_encoder->attached_connector->base;
+	struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
+	struct drm_display_mode *mode = &pipe_config->requested_mode;
 	struct intel_crtc *intel_crtc = lvds_encoder->base.new_crtc;
 	u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0;
+	unsigned int lvds_bpp;
 	int pipe;
 
 	/* Should never happen!! */
@@ -323,6 +322,17 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
 	if (intel_encoder_check_is_cloned(&lvds_encoder->base))
 		return false;
 
+	if ((I915_READ(lvds_encoder->reg) & LVDS_A3_POWER_MASK) ==
+	    LVDS_A3_POWER_UP)
+		lvds_bpp = 8*3;
+	else
+		lvds_bpp = 6*3;
+
+	if (lvds_bpp != pipe_config->pipe_bpp) {
+		DRM_DEBUG_KMS("forcing display bpp (was %d) to LVDS (%d)\n",
+			      pipe_config->pipe_bpp, lvds_bpp);
+		pipe_config->pipe_bpp = lvds_bpp;
+	}
 	/*
 	 * 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,
@@ -333,6 +343,8 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
 			       adjusted_mode);
 
 	if (HAS_PCH_SPLIT(dev)) {
+		pipe_config->has_pch_encoder = true;
+
 		intel_pch_panel_fitting(dev,
 					intel_connector->panel.fitting_mode,
 					mode, adjusted_mode);
@@ -359,6 +371,7 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
 		I915_WRITE(BCLRPAT(pipe), 0);
 
 	drm_mode_set_crtcinfo(adjusted_mode, 0);
+	pipe_config->timings_set = true;
 
 	switch (intel_connector->panel.fitting_mode) {
 	case DRM_MODE_SCALE_CENTER:
@@ -661,7 +674,6 @@ static int intel_lvds_set_property(struct drm_connector *connector,
 }
 
 static const struct drm_encoder_helper_funcs intel_lvds_helper_funcs = {
-	.mode_fixup = intel_lvds_mode_fixup,
 	.mode_set = intel_lvds_mode_set,
 };
 
@@ -850,6 +862,14 @@ static const struct dmi_system_id intel_no_lvds[] = {
 			DMI_MATCH(DMI_PRODUCT_NAME, "X7SPA-H"),
 		},
 	},
+	{
+		.callback = intel_no_lvds_dmi_callback,
+		.ident = "Fujitsu Esprimo Q900",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO Q900"),
+		},
+	},
 
 	{ }	/* terminating entry */
 };
@@ -1019,12 +1039,15 @@ static bool intel_lvds_supported(struct drm_device *dev)
 {
 	/* With the introduction of the PCH we gained a dedicated
 	 * LVDS presence pin, use it. */
-	if (HAS_PCH_SPLIT(dev))
+	if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
 		return true;
 
 	/* Otherwise LVDS was only attached to mobile products,
 	 * except for the inglorious 830gm */
-	return IS_MOBILE(dev) && !IS_I830(dev);
+	if (INTEL_INFO(dev)->gen <= 4 && IS_MOBILE(dev) && !IS_I830(dev))
+		return true;
+
+	return false;
 }
 
 /**
@@ -1102,6 +1125,7 @@ bool intel_lvds_init(struct drm_device *dev)
 	intel_encoder->enable = intel_enable_lvds;
 	intel_encoder->pre_enable = intel_pre_enable_lvds;
 	intel_encoder->pre_pll_enable = intel_pre_pll_enable_lvds;
+	intel_encoder->compute_config = intel_lvds_compute_config;
 	intel_encoder->disable = intel_disable_lvds;
 	intel_encoder->get_hw_state = intel_lvds_get_hw_state;
 	intel_connector->get_hw_state = intel_connector_get_hw_state;
diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c
index 4d33874..a8117e6 100644
--- a/drivers/gpu/drm/i915/intel_opregion.c
+++ b/drivers/gpu/drm/i915/intel_opregion.c
@@ -350,11 +350,11 @@ static void intel_didl_outputs(struct drm_device *dev)
 	if (!handle || acpi_bus_get_device(handle, &acpi_dev))
 		return;
 
-	if (acpi_is_video_device(acpi_dev))
+	if (acpi_is_video_device(handle))
 		acpi_video_bus = acpi_dev;
 	else {
 		list_for_each_entry(acpi_cdev, &acpi_dev->children, node) {
-			if (acpi_is_video_device(acpi_cdev)) {
+			if (acpi_is_video_device(acpi_cdev->handle)) {
 				acpi_video_bus = acpi_cdev;
 				break;
 			}
diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
index bee8cb6..7874cec 100644
--- a/drivers/gpu/drm/i915/intel_panel.c
+++ b/drivers/gpu/drm/i915/intel_panel.c
@@ -286,8 +286,11 @@ void intel_panel_set_backlight(struct drm_device *dev, u32 level)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	dev_priv->backlight_level = level;
-	if (dev_priv->backlight_enabled)
+	dev_priv->backlight.level = level;
+	if (dev_priv->backlight.device)
+		dev_priv->backlight.device->props.brightness = level;
+
+	if (dev_priv->backlight.enabled)
 		intel_panel_actually_set_backlight(dev, level);
 }
 
@@ -295,7 +298,7 @@ void intel_panel_disable_backlight(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	dev_priv->backlight_enabled = false;
+	dev_priv->backlight.enabled = false;
 	intel_panel_actually_set_backlight(dev, 0);
 
 	if (INTEL_INFO(dev)->gen >= 4) {
@@ -318,8 +321,12 @@ void intel_panel_enable_backlight(struct drm_device *dev,
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	if (dev_priv->backlight_level == 0)
-		dev_priv->backlight_level = intel_panel_get_max_backlight(dev);
+	if (dev_priv->backlight.level == 0) {
+		dev_priv->backlight.level = intel_panel_get_max_backlight(dev);
+		if (dev_priv->backlight.device)
+			dev_priv->backlight.device->props.brightness =
+				dev_priv->backlight.level;
+	}
 
 	if (INTEL_INFO(dev)->gen >= 4) {
 		uint32_t reg, tmp;
@@ -335,7 +342,7 @@ void intel_panel_enable_backlight(struct drm_device *dev,
 		if (tmp & BLM_PWM_ENABLE)
 			goto set_level;
 
-		if (dev_priv->num_pipe == 3)
+		if (INTEL_INFO(dev)->num_pipes == 3)
 			tmp &= ~BLM_PIPE_SELECT_IVB;
 		else
 			tmp &= ~BLM_PIPE_SELECT;
@@ -360,16 +367,16 @@ set_level:
 	 * BLC_PWM_CPU_CTL may be cleared to zero automatically when these
 	 * registers are set.
 	 */
-	dev_priv->backlight_enabled = true;
-	intel_panel_actually_set_backlight(dev, dev_priv->backlight_level);
+	dev_priv->backlight.enabled = true;
+	intel_panel_actually_set_backlight(dev, dev_priv->backlight.level);
 }
 
 static void intel_panel_init_backlight(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	dev_priv->backlight_level = intel_panel_get_backlight(dev);
-	dev_priv->backlight_enabled = dev_priv->backlight_level != 0;
+	dev_priv->backlight.level = intel_panel_get_backlight(dev);
+	dev_priv->backlight.enabled = dev_priv->backlight.level != 0;
 }
 
 enum drm_connector_status
@@ -405,8 +412,7 @@ static int intel_panel_update_status(struct backlight_device *bd)
 static int intel_panel_get_brightness(struct backlight_device *bd)
 {
 	struct drm_device *dev = bl_get_data(bd);
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	return dev_priv->backlight_level;
+	return intel_panel_get_backlight(dev);
 }
 
 static const struct backlight_ops intel_panel_bl_ops = {
@@ -424,31 +430,31 @@ int intel_panel_setup_backlight(struct drm_connector *connector)
 
 	memset(&props, 0, sizeof(props));
 	props.type = BACKLIGHT_RAW;
+	props.brightness = dev_priv->backlight.level;
 	props.max_brightness = _intel_panel_get_max_backlight(dev);
 	if (props.max_brightness == 0) {
 		DRM_DEBUG_DRIVER("Failed to get maximum backlight value\n");
 		return -ENODEV;
 	}
-	dev_priv->backlight =
+	dev_priv->backlight.device =
 		backlight_device_register("intel_backlight",
 					  &connector->kdev, dev,
 					  &intel_panel_bl_ops, &props);
 
-	if (IS_ERR(dev_priv->backlight)) {
+	if (IS_ERR(dev_priv->backlight.device)) {
 		DRM_ERROR("Failed to register backlight: %ld\n",
-			  PTR_ERR(dev_priv->backlight));
-		dev_priv->backlight = NULL;
+			  PTR_ERR(dev_priv->backlight.device));
+		dev_priv->backlight.device = NULL;
 		return -ENODEV;
 	}
-	dev_priv->backlight->props.brightness = intel_panel_get_backlight(dev);
 	return 0;
 }
 
 void intel_panel_destroy_backlight(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	if (dev_priv->backlight)
-		backlight_device_unregister(dev_priv->backlight);
+	if (dev_priv->backlight.device)
+		backlight_device_unregister(dev_priv->backlight.device);
 }
 #else
 int intel_panel_setup_backlight(struct drm_connector *connector)
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index adca007..13a0666 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2460,10 +2460,14 @@ void gen6_set_rps(struct drm_device *dev, u8 val)
 	if (val == dev_priv->rps.cur_delay)
 		return;
 
-	I915_WRITE(GEN6_RPNSWREQ,
-		   GEN6_FREQUENCY(val) |
-		   GEN6_OFFSET(0) |
-		   GEN6_AGGRESSIVE_TURBO);
+	if (IS_HASWELL(dev))
+		I915_WRITE(GEN6_RPNSWREQ,
+			   HSW_FREQUENCY(val));
+	else
+		I915_WRITE(GEN6_RPNSWREQ,
+			   GEN6_FREQUENCY(val) |
+			   GEN6_OFFSET(0) |
+			   GEN6_AGGRESSIVE_TURBO);
 
 	/* Make sure we continue to get interrupts
 	 * until we hit the minimum or maximum frequencies.
@@ -2601,12 +2605,19 @@ static void gen6_enable_rps(struct drm_device *dev)
 		   GEN6_RC_CTL_EI_MODE(1) |
 		   GEN6_RC_CTL_HW_ENABLE);
 
-	I915_WRITE(GEN6_RPNSWREQ,
-		   GEN6_FREQUENCY(10) |
-		   GEN6_OFFSET(0) |
-		   GEN6_AGGRESSIVE_TURBO);
-	I915_WRITE(GEN6_RC_VIDEO_FREQ,
-		   GEN6_FREQUENCY(12));
+	if (IS_HASWELL(dev)) {
+		I915_WRITE(GEN6_RPNSWREQ,
+			   HSW_FREQUENCY(10));
+		I915_WRITE(GEN6_RC_VIDEO_FREQ,
+			   HSW_FREQUENCY(12));
+	} else {
+		I915_WRITE(GEN6_RPNSWREQ,
+			   GEN6_FREQUENCY(10) |
+			   GEN6_OFFSET(0) |
+			   GEN6_AGGRESSIVE_TURBO);
+		I915_WRITE(GEN6_RC_VIDEO_FREQ,
+			   GEN6_FREQUENCY(12));
+	}
 
 	I915_WRITE(GEN6_RP_DOWN_TIMEOUT, 1000000);
 	I915_WRITE(GEN6_RP_INTERRUPT_LIMITS,
@@ -2628,12 +2639,14 @@ static void gen6_enable_rps(struct drm_device *dev)
 		   (IS_HASWELL(dev) ? GEN7_RP_DOWN_IDLE_AVG : GEN6_RP_DOWN_IDLE_CONT));
 
 	ret = sandybridge_pcode_write(dev_priv, GEN6_PCODE_WRITE_MIN_FREQ_TABLE, 0);
-	if (!ret) {
+	if (!ret && (IS_GEN6(dev) || IS_IVYBRIDGE(dev))) {
 		pcu_mbox = 0;
 		ret = sandybridge_pcode_read(dev_priv, GEN6_READ_OC_PARAMS, &pcu_mbox);
-		if (ret && pcu_mbox & (1<<31)) { /* OC supported */
+		if (!ret && (pcu_mbox & (1<<31))) { /* OC supported */
+			DRM_DEBUG_DRIVER("overclocking supported, adjusting frequency max from %dMHz to %dMHz\n",
+					 (dev_priv->rps.max_delay & 0xff) * 50,
+					 (pcu_mbox & 0xff) * 50);
 			dev_priv->rps.max_delay = pcu_mbox & 0xff;
-			DRM_DEBUG_DRIVER("overclocking supported, adjusting frequency max to %dMHz\n", pcu_mbox * 50);
 		}
 	} else {
 		DRM_DEBUG_DRIVER("Failed to set the min frequency\n");
@@ -2821,7 +2834,7 @@ static void ironlake_enable_rc6(struct drm_device *dev)
 	ret = intel_ring_idle(ring);
 	dev_priv->mm.interruptible = was_interruptible;
 	if (ret) {
-		DRM_ERROR("failed to enable ironlake power power savings\n");
+		DRM_ERROR("failed to enable ironlake power savings\n");
 		ironlake_teardown_rc6(dev);
 		return;
 	}
@@ -3768,6 +3781,9 @@ static void haswell_init_clock_gating(struct drm_device *dev)
 	I915_WRITE(GEN6_MBCTL, I915_READ(GEN6_MBCTL) |
 		   GEN6_MBCTL_ENABLE_BOOT_FETCH);
 
+	/* WaSwitchSolVfFArbitrationPriority */
+	I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | HSW_ECOCHK_ARB_PRIO_SOL);
+
 	/* XXX: This is a workaround for early silicon revisions and should be
 	 * removed later.
 	 */
@@ -3899,8 +3915,10 @@ static void valleyview_init_clock_gating(struct drm_device *dev)
 		   CHICKEN3_DGMG_REQ_OUT_FIX_DISABLE |
 		   CHICKEN3_DGMG_DONE_FIX_DISABLE);
 
+	/* WaDisablePSDDualDispatchEnable */
 	I915_WRITE(GEN7_HALF_SLICE_CHICKEN1,
-		   _MASKED_BIT_ENABLE(GEN7_PSD_SINGLE_PORT_DISPATCH_ENABLE));
+		   _MASKED_BIT_ENABLE(GEN7_MAX_PS_THREAD_DEP |
+				      GEN7_PSD_SINGLE_PORT_DISPATCH_ENABLE));
 
 	/* Apply the WaDisableRHWOOptimizationForRenderHang workaround. */
 	I915_WRITE(GEN7_COMMON_SLICE_CHICKEN1,
@@ -3968,24 +3986,20 @@ static void valleyview_init_clock_gating(struct drm_device *dev)
 		   _MASKED_BIT_ENABLE(PIXEL_SUBSPAN_COLLECT_OPT_DISABLE));
 
 	/*
-	 * On ValleyView, the GUnit needs to signal the GT
-	 * when flip and other events complete.  So enable
-	 * all the GUnit->GT interrupts here
-	 */
-	I915_WRITE(VLV_DPFLIPSTAT, PIPEB_LINE_COMPARE_INT_EN |
-		   PIPEB_HLINE_INT_EN | PIPEB_VBLANK_INT_EN |
-		   SPRITED_FLIPDONE_INT_EN | SPRITEC_FLIPDONE_INT_EN |
-		   PLANEB_FLIPDONE_INT_EN | PIPEA_LINE_COMPARE_INT_EN |
-		   PIPEA_HLINE_INT_EN | PIPEA_VBLANK_INT_EN |
-		   SPRITEB_FLIPDONE_INT_EN | SPRITEA_FLIPDONE_INT_EN |
-		   PLANEA_FLIPDONE_INT_EN);
-
-	/*
 	 * WaDisableVLVClockGating_VBIIssue
 	 * Disable clock gating on th GCFG unit to prevent a delay
 	 * in the reporting of vblank events.
 	 */
-	I915_WRITE(VLV_GUNIT_CLOCK_GATE, GCFG_DIS);
+	I915_WRITE(VLV_GUNIT_CLOCK_GATE, 0xffffffff);
+
+	/* Conservative clock gating settings for now */
+	I915_WRITE(0x9400, 0xffffffff);
+	I915_WRITE(0x9404, 0xffffffff);
+	I915_WRITE(0x9408, 0xffffffff);
+	I915_WRITE(0x940c, 0xffffffff);
+	I915_WRITE(0x9410, 0xffffffff);
+	I915_WRITE(0x9414, 0xffffffff);
+	I915_WRITE(0x9418, 0xffffffff);
 }
 
 static void g4x_init_clock_gating(struct drm_device *dev)
@@ -4076,7 +4090,7 @@ void intel_set_power_well(struct drm_device *dev, bool enable)
 	bool is_enabled, enable_requested;
 	uint32_t tmp;
 
-	if (!IS_HASWELL(dev))
+	if (!HAS_POWER_WELL(dev))
 		return;
 
 	if (!i915_disable_power_well && !enable)
@@ -4114,7 +4128,7 @@ void intel_init_power_well(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	if (!IS_HASWELL(dev))
+	if (!HAS_POWER_WELL(dev))
 		return;
 
 	/* For now, we need the power well to be always enabled. */
@@ -4274,21 +4288,14 @@ static void __gen6_gt_force_wake_reset(struct drm_i915_private *dev_priv)
 
 static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
 {
-	u32 forcewake_ack;
-
-	if (IS_HASWELL(dev_priv->dev))
-		forcewake_ack = FORCEWAKE_ACK_HSW;
-	else
-		forcewake_ack = FORCEWAKE_ACK;
-
-	if (wait_for_atomic((I915_READ_NOTRACE(forcewake_ack) & 1) == 0,
+	if (wait_for_atomic((I915_READ_NOTRACE(FORCEWAKE_ACK) & 1) == 0,
 			    FORCEWAKE_ACK_TIMEOUT_MS))
 		DRM_ERROR("Timed out waiting for forcewake old ack to clear.\n");
 
-	I915_WRITE_NOTRACE(FORCEWAKE, FORCEWAKE_KERNEL);
+	I915_WRITE_NOTRACE(FORCEWAKE, 1);
 	POSTING_READ(ECOBUS); /* something from same cacheline, but !FORCEWAKE */
 
-	if (wait_for_atomic((I915_READ_NOTRACE(forcewake_ack) & 1),
+	if (wait_for_atomic((I915_READ_NOTRACE(FORCEWAKE_ACK) & 1),
 			    FORCEWAKE_ACK_TIMEOUT_MS))
 		DRM_ERROR("Timed out waiting for forcewake to ack request.\n");
 
@@ -4311,7 +4318,7 @@ static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv)
 	else
 		forcewake_ack = FORCEWAKE_MT_ACK;
 
-	if (wait_for_atomic((I915_READ_NOTRACE(forcewake_ack) & 1) == 0,
+	if (wait_for_atomic((I915_READ_NOTRACE(forcewake_ack) & FORCEWAKE_KERNEL) == 0,
 			    FORCEWAKE_ACK_TIMEOUT_MS))
 		DRM_ERROR("Timed out waiting for forcewake old ack to clear.\n");
 
@@ -4319,7 +4326,7 @@ static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv)
 	/* something from same cacheline, but !FORCEWAKE_MT */
 	POSTING_READ(ECOBUS);
 
-	if (wait_for_atomic((I915_READ_NOTRACE(forcewake_ack) & 1),
+	if (wait_for_atomic((I915_READ_NOTRACE(forcewake_ack) & FORCEWAKE_KERNEL),
 			    FORCEWAKE_ACK_TIMEOUT_MS))
 		DRM_ERROR("Timed out waiting for forcewake to ack request.\n");
 
@@ -4409,15 +4416,22 @@ static void vlv_force_wake_reset(struct drm_i915_private *dev_priv)
 
 static void vlv_force_wake_get(struct drm_i915_private *dev_priv)
 {
-	if (wait_for_atomic((I915_READ_NOTRACE(FORCEWAKE_ACK_VLV) & 1) == 0,
+	if (wait_for_atomic((I915_READ_NOTRACE(FORCEWAKE_ACK_VLV) & FORCEWAKE_KERNEL) == 0,
 			    FORCEWAKE_ACK_TIMEOUT_MS))
 		DRM_ERROR("Timed out waiting for forcewake old ack to clear.\n");
 
 	I915_WRITE_NOTRACE(FORCEWAKE_VLV, _MASKED_BIT_ENABLE(FORCEWAKE_KERNEL));
+	I915_WRITE_NOTRACE(FORCEWAKE_MEDIA_VLV,
+			   _MASKED_BIT_ENABLE(FORCEWAKE_KERNEL));
 
-	if (wait_for_atomic((I915_READ_NOTRACE(FORCEWAKE_ACK_VLV) & 1),
+	if (wait_for_atomic((I915_READ_NOTRACE(FORCEWAKE_ACK_VLV) & FORCEWAKE_KERNEL),
 			    FORCEWAKE_ACK_TIMEOUT_MS))
-		DRM_ERROR("Timed out waiting for forcewake to ack request.\n");
+		DRM_ERROR("Timed out waiting for GT to ack forcewake request.\n");
+
+	if (wait_for_atomic((I915_READ_NOTRACE(FORCEWAKE_ACK_MEDIA_VLV) &
+			     FORCEWAKE_KERNEL),
+			    FORCEWAKE_ACK_TIMEOUT_MS))
+		DRM_ERROR("Timed out waiting for media to ack forcewake request.\n");
 
 	__gen6_gt_wait_for_thread_c0(dev_priv);
 }
@@ -4425,8 +4439,9 @@ static void vlv_force_wake_get(struct drm_i915_private *dev_priv)
 static void vlv_force_wake_put(struct drm_i915_private *dev_priv)
 {
 	I915_WRITE_NOTRACE(FORCEWAKE_VLV, _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL));
-	/* something from same cacheline, but !FORCEWAKE_VLV */
-	POSTING_READ(FORCEWAKE_ACK_VLV);
+	I915_WRITE_NOTRACE(FORCEWAKE_MEDIA_VLV,
+			   _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL));
+	/* The below doubles as a POSTING_READ */
 	gen6_gt_check_fifodbg(dev_priv);
 }
 
@@ -4511,3 +4526,56 @@ int sandybridge_pcode_write(struct drm_i915_private *dev_priv, u8 mbox, u32 val)
 
 	return 0;
 }
+
+static int vlv_punit_rw(struct drm_i915_private *dev_priv, u8 opcode,
+			u8 addr, u32 *val)
+{
+	u32 cmd, devfn, port, be, bar;
+
+	bar = 0;
+	be = 0xf;
+	port = IOSF_PORT_PUNIT;
+	devfn = PCI_DEVFN(2, 0);
+
+	cmd = (devfn << IOSF_DEVFN_SHIFT) | (opcode << IOSF_OPCODE_SHIFT) |
+		(port << IOSF_PORT_SHIFT) | (be << IOSF_BYTE_ENABLES_SHIFT) |
+		(bar << IOSF_BAR_SHIFT);
+
+	WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
+
+	if (I915_READ(VLV_IOSF_DOORBELL_REQ) & IOSF_SB_BUSY) {
+		DRM_DEBUG_DRIVER("warning: pcode (%s) mailbox access failed\n",
+				 opcode == PUNIT_OPCODE_REG_READ ?
+				 "read" : "write");
+		return -EAGAIN;
+	}
+
+	I915_WRITE(VLV_IOSF_ADDR, addr);
+	if (opcode == PUNIT_OPCODE_REG_WRITE)
+		I915_WRITE(VLV_IOSF_DATA, *val);
+	I915_WRITE(VLV_IOSF_DOORBELL_REQ, cmd);
+
+	if (wait_for((I915_READ(VLV_IOSF_DOORBELL_REQ) & IOSF_SB_BUSY) == 0,
+		     500)) {
+		DRM_ERROR("timeout waiting for pcode %s (%d) to finish\n",
+			  opcode == PUNIT_OPCODE_REG_READ ? "read" : "write",
+			  addr);
+		return -ETIMEDOUT;
+	}
+
+	if (opcode == PUNIT_OPCODE_REG_READ)
+		*val = I915_READ(VLV_IOSF_DATA);
+	I915_WRITE(VLV_IOSF_DATA, 0);
+
+	return 0;
+}
+
+int valleyview_punit_read(struct drm_i915_private *dev_priv, u8 addr, u32 *val)
+{
+	return vlv_punit_rw(dev_priv, PUNIT_OPCODE_REG_READ, addr, val);
+}
+
+int valleyview_punit_write(struct drm_i915_private *dev_priv, u8 addr, u32 val)
+{
+	return vlv_punit_rw(dev_priv, PUNIT_OPCODE_REG_WRITE, addr, &val);
+}
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index d07a8cd..298dc85 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -246,11 +246,11 @@ static void intel_sdvo_write_sdvox(struct intel_sdvo *intel_sdvo, u32 val)
 		return;
 	}
 
-	if (intel_sdvo->sdvo_reg == SDVOB) {
-		cval = I915_READ(SDVOC);
-	} else {
-		bval = I915_READ(SDVOB);
-	}
+	if (intel_sdvo->sdvo_reg == GEN3_SDVOB)
+		cval = I915_READ(GEN3_SDVOC);
+	else
+		bval = I915_READ(GEN3_SDVOB);
+
 	/*
 	 * Write the registers twice for luck. Sometimes,
 	 * writing them only once doesn't appear to 'stick'.
@@ -258,10 +258,10 @@ static void intel_sdvo_write_sdvox(struct intel_sdvo *intel_sdvo, u32 val)
 	 */
 	for (i = 0; i < 2; i++)
 	{
-		I915_WRITE(SDVOB, bval);
-		I915_READ(SDVOB);
-		I915_WRITE(SDVOC, cval);
-		I915_READ(SDVOC);
+		I915_WRITE(GEN3_SDVOB, bval);
+		I915_READ(GEN3_SDVOB);
+		I915_WRITE(GEN3_SDVOC, cval);
+		I915_READ(GEN3_SDVOC);
 	}
 }
 
@@ -451,7 +451,7 @@ static bool intel_sdvo_write_cmd(struct intel_sdvo *intel_sdvo, u8 cmd,
 	int i, ret = true;
 
         /* Would be simpler to allocate both in one go ? */        
-	buf = (u8 *)kzalloc(args_len * 2 + 2, GFP_KERNEL);
+	buf = kzalloc(args_len * 2 + 2, GFP_KERNEL);
 	if (!buf)
 		return false;
 
@@ -788,7 +788,6 @@ static void intel_sdvo_get_dtd_from_mode(struct intel_sdvo_dtd *dtd,
 	v_sync_offset = mode->vsync_start - mode->vdisplay;
 
 	mode_clock = mode->clock;
-	mode_clock /= intel_mode_get_pixel_multiplier(mode) ?: 1;
 	mode_clock /= 10;
 	dtd->part1.clock = mode_clock;
 
@@ -957,14 +956,17 @@ static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo,
 		.len = DIP_LEN_AVI,
 	};
 	uint8_t sdvo_data[4 + sizeof(avi_if.body.avi)];
+	struct intel_crtc *intel_crtc = to_intel_crtc(intel_sdvo->base.base.crtc);
 
 	if (intel_sdvo->rgb_quant_range_selectable) {
-		if (adjusted_mode->private_flags & INTEL_MODE_LIMITED_COLOR_RANGE)
+		if (intel_crtc->config.limited_color_range)
 			avi_if.body.avi.ITC_EC_Q_SC |= DIP_AVI_RGB_QUANT_RANGE_LIMITED;
 		else
 			avi_if.body.avi.ITC_EC_Q_SC |= DIP_AVI_RGB_QUANT_RANGE_FULL;
 	}
 
+	avi_if.body.avi.VIC = drm_match_cea_mode(adjusted_mode);
+
 	intel_dip_infoframe_csum(&avi_if);
 
 	/* sdvo spec says that the ecc is handled by the hw, and it looks like
@@ -1039,12 +1041,18 @@ intel_sdvo_get_preferred_input_mode(struct intel_sdvo *intel_sdvo,
 	return true;
 }
 
-static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder,
-				  const struct drm_display_mode *mode,
-				  struct drm_display_mode *adjusted_mode)
+static bool intel_sdvo_compute_config(struct intel_encoder *encoder,
+				      struct intel_crtc_config *pipe_config)
 {
-	struct intel_sdvo *intel_sdvo = to_intel_sdvo(encoder);
-	int multiplier;
+	struct intel_sdvo *intel_sdvo = to_intel_sdvo(&encoder->base);
+	struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
+	struct drm_display_mode *mode = &pipe_config->requested_mode;
+
+	DRM_DEBUG_KMS("forcing bpc to 8 for SDVO\n");
+	pipe_config->pipe_bpp = 8*3;
+
+	if (HAS_PCH_SPLIT(encoder->base.dev))
+		pipe_config->has_pch_encoder = true;
 
 	/* We need to construct preferred input timings based on our
 	 * output timings.  To do that, we have to set the output
@@ -1071,37 +1079,40 @@ static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder,
 	/* Make the CRTC code factor in the SDVO pixel multiplier.  The
 	 * SDVO device will factor out the multiplier during mode_set.
 	 */
-	multiplier = intel_sdvo_get_pixel_multiplier(adjusted_mode);
-	intel_mode_set_pixel_multiplier(adjusted_mode, multiplier);
+	pipe_config->pixel_multiplier =
+		intel_sdvo_get_pixel_multiplier(adjusted_mode);
+	adjusted_mode->clock *= pipe_config->pixel_multiplier;
 
 	if (intel_sdvo->color_range_auto) {
 		/* See CEA-861-E - 5.1 Default Encoding Parameters */
+		/* FIXME: This bit is only valid when using TMDS encoding and 8
+		 * bit per color mode. */
 		if (intel_sdvo->has_hdmi_monitor &&
 		    drm_match_cea_mode(adjusted_mode) > 1)
-			intel_sdvo->color_range = SDVO_COLOR_RANGE_16_235;
+			intel_sdvo->color_range = HDMI_COLOR_RANGE_16_235;
 		else
 			intel_sdvo->color_range = 0;
 	}
 
 	if (intel_sdvo->color_range)
-		adjusted_mode->private_flags |= INTEL_MODE_LIMITED_COLOR_RANGE;
+		pipe_config->limited_color_range = true;
 
 	return true;
 }
 
-static void intel_sdvo_mode_set(struct drm_encoder *encoder,
-				struct drm_display_mode *mode,
-				struct drm_display_mode *adjusted_mode)
+static void intel_sdvo_mode_set(struct intel_encoder *intel_encoder)
 {
-	struct drm_device *dev = encoder->dev;
+	struct drm_device *dev = intel_encoder->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct drm_crtc *crtc = encoder->crtc;
+	struct drm_crtc *crtc = intel_encoder->base.crtc;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	struct intel_sdvo *intel_sdvo = to_intel_sdvo(encoder);
+	struct drm_display_mode *adjusted_mode =
+		&intel_crtc->config.adjusted_mode;
+	struct drm_display_mode *mode = &intel_crtc->config.requested_mode;
+	struct intel_sdvo *intel_sdvo = to_intel_sdvo(&intel_encoder->base);
 	u32 sdvox;
 	struct intel_sdvo_in_out_map in_out;
 	struct intel_sdvo_dtd input_dtd, output_dtd;
-	int pixel_multiplier = intel_mode_get_pixel_multiplier(adjusted_mode);
 	int rate;
 
 	if (!mode)
@@ -1161,7 +1172,7 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
 		DRM_INFO("Setting input timings on %s failed\n",
 			 SDVO_NAME(intel_sdvo));
 
-	switch (pixel_multiplier) {
+	switch (intel_crtc->config.pixel_multiplier) {
 	default:
 	case 1: rate = SDVO_CLOCK_RATE_MULT_1X; break;
 	case 2: rate = SDVO_CLOCK_RATE_MULT_2X; break;
@@ -1182,10 +1193,10 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
 	} else {
 		sdvox = I915_READ(intel_sdvo->sdvo_reg);
 		switch (intel_sdvo->sdvo_reg) {
-		case SDVOB:
+		case GEN3_SDVOB:
 			sdvox &= SDVOB_PRESERVE_MASK;
 			break;
-		case SDVOC:
+		case GEN3_SDVOC:
 			sdvox &= SDVOC_PRESERVE_MASK;
 			break;
 		}
@@ -1193,9 +1204,9 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
 	}
 
 	if (INTEL_PCH_TYPE(dev) >= PCH_CPT)
-		sdvox |= TRANSCODER_CPT(intel_crtc->pipe);
+		sdvox |= SDVO_PIPE_SEL_CPT(intel_crtc->pipe);
 	else
-		sdvox |= TRANSCODER(intel_crtc->pipe);
+		sdvox |= SDVO_PIPE_SEL(intel_crtc->pipe);
 
 	if (intel_sdvo->has_hdmi_audio)
 		sdvox |= SDVO_AUDIO_ENABLE;
@@ -1205,7 +1216,8 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
 	} else if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) {
 		/* done in crtc_mode_set as it lives inside the dpll register */
 	} else {
-		sdvox |= (pixel_multiplier - 1) << SDVO_PORT_MULTIPLY_SHIFT;
+		sdvox |= (intel_crtc->config.pixel_multiplier - 1)
+			<< SDVO_PORT_MULTIPLY_SHIFT;
 	}
 
 	if (input_dtd.part2.sdvo_flags & SDVO_NEED_TO_STALL &&
@@ -1219,8 +1231,12 @@ static bool intel_sdvo_connector_get_hw_state(struct intel_connector *connector)
 	struct intel_sdvo_connector *intel_sdvo_connector =
 		to_intel_sdvo_connector(&connector->base);
 	struct intel_sdvo *intel_sdvo = intel_attached_sdvo(&connector->base);
+	struct drm_i915_private *dev_priv = intel_sdvo->base.base.dev->dev_private;
 	u16 active_outputs;
 
+	if (!(I915_READ(intel_sdvo->sdvo_reg) & SDVO_ENABLE))
+		return false;
+
 	intel_sdvo_get_active_outputs(intel_sdvo, &active_outputs);
 
 	if (active_outputs & intel_sdvo_connector->output_flag)
@@ -1305,15 +1321,9 @@ static void intel_enable_sdvo(struct intel_encoder *encoder)
 	temp = I915_READ(intel_sdvo->sdvo_reg);
 	if ((temp & SDVO_ENABLE) == 0) {
 		/* HW workaround for IBX, we need to move the port
-		 * to transcoder A before disabling it. */
-		if (HAS_PCH_IBX(dev)) {
-			struct drm_crtc *crtc = encoder->base.crtc;
-			int pipe = crtc ? to_intel_crtc(crtc)->pipe : -1;
-
-			/* Restore the transcoder select bit. */
-			if (pipe == PIPE_B)
-				temp |= SDVO_PIPE_B_SELECT;
-		}
+		 * to transcoder A before disabling it, so restore it here. */
+		if (HAS_PCH_IBX(dev))
+			temp |= SDVO_PIPE_SEL(intel_crtc->pipe);
 
 		intel_sdvo_write_sdvox(intel_sdvo, temp | SDVO_ENABLE);
 	}
@@ -1932,7 +1942,9 @@ intel_sdvo_set_property(struct drm_connector *connector,
 			break;
 		case INTEL_BROADCAST_RGB_LIMITED:
 			intel_sdvo->color_range_auto = false;
-			intel_sdvo->color_range = SDVO_COLOR_RANGE_16_235;
+			/* FIXME: this bit is only valid when using TMDS
+			 * encoding and 8 bit per color mode. */
+			intel_sdvo->color_range = HDMI_COLOR_RANGE_16_235;
 			break;
 		default:
 			return -EINVAL;
@@ -2040,11 +2052,6 @@ done:
 #undef CHECK_PROPERTY
 }
 
-static const struct drm_encoder_helper_funcs intel_sdvo_helper_funcs = {
-	.mode_fixup = intel_sdvo_mode_fixup,
-	.mode_set = intel_sdvo_mode_set,
-};
-
 static const struct drm_connector_funcs intel_sdvo_connector_funcs = {
 	.dpms = intel_sdvo_dpms,
 	.detect = intel_sdvo_detect,
@@ -2779,9 +2786,15 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)
 			SDVOB_HOTPLUG_INT_STATUS_I915 : SDVOC_HOTPLUG_INT_STATUS_I915;
 	}
 
-	drm_encoder_helper_add(&intel_encoder->base, &intel_sdvo_helper_funcs);
+	/* Only enable the hotplug irq if we need it, to work around noisy
+	 * hotplug lines.
+	 */
+	if (intel_sdvo->hotplug_active)
+		intel_encoder->hpd_pin = HPD_SDVO_B ? HPD_SDVO_B : HPD_SDVO_C;
 
+	intel_encoder->compute_config = intel_sdvo_compute_config;
 	intel_encoder->disable = intel_disable_sdvo;
+	intel_encoder->mode_set = intel_sdvo_mode_set;
 	intel_encoder->enable = intel_enable_sdvo;
 	intel_encoder->get_hw_state = intel_sdvo_get_hw_state;
 
@@ -2807,12 +2820,6 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)
 	 */
 	intel_sdvo->base.cloneable = false;
 
-	/* Only enable the hotplug irq if we need it, to work around noisy
-	 * hotplug lines.
-	 */
-	if (intel_sdvo->hotplug_active)
-		dev_priv->hotplug_supported_mask |= hotplug_mask;
-
 	intel_sdvo_select_ddc_bus(dev_priv, intel_sdvo, sdvo_reg);
 
 	/* Set the input timing to the screen. Assume always input 0. */
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 1b6eb76..c7d25c5 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -37,6 +37,174 @@
 #include "i915_drv.h"
 
 static void
+vlv_update_plane(struct drm_plane *dplane, struct drm_framebuffer *fb,
+		 struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
+		 unsigned int crtc_w, unsigned int crtc_h,
+		 uint32_t x, uint32_t y,
+		 uint32_t src_w, uint32_t src_h)
+{
+	struct drm_device *dev = dplane->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_plane *intel_plane = to_intel_plane(dplane);
+	int pipe = intel_plane->pipe;
+	int plane = intel_plane->plane;
+	u32 sprctl;
+	unsigned long sprsurf_offset, linear_offset;
+	int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
+
+	sprctl = I915_READ(SPCNTR(pipe, plane));
+
+	/* Mask out pixel format bits in case we change it */
+	sprctl &= ~SP_PIXFORMAT_MASK;
+	sprctl &= ~SP_YUV_BYTE_ORDER_MASK;
+	sprctl &= ~SP_TILED;
+
+	switch (fb->pixel_format) {
+	case DRM_FORMAT_YUYV:
+		sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YUYV;
+		break;
+	case DRM_FORMAT_YVYU:
+		sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YVYU;
+		break;
+	case DRM_FORMAT_UYVY:
+		sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_UYVY;
+		break;
+	case DRM_FORMAT_VYUY:
+		sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_VYUY;
+		break;
+	case DRM_FORMAT_RGB565:
+		sprctl |= SP_FORMAT_BGR565;
+		break;
+	case DRM_FORMAT_XRGB8888:
+		sprctl |= SP_FORMAT_BGRX8888;
+		break;
+	case DRM_FORMAT_ARGB8888:
+		sprctl |= SP_FORMAT_BGRA8888;
+		break;
+	case DRM_FORMAT_XBGR2101010:
+		sprctl |= SP_FORMAT_RGBX1010102;
+		break;
+	case DRM_FORMAT_ABGR2101010:
+		sprctl |= SP_FORMAT_RGBA1010102;
+		break;
+	case DRM_FORMAT_XBGR8888:
+		sprctl |= SP_FORMAT_RGBX8888;
+		break;
+	case DRM_FORMAT_ABGR8888:
+		sprctl |= SP_FORMAT_RGBA8888;
+		break;
+	default:
+		/*
+		 * If we get here one of the upper layers failed to filter
+		 * out the unsupported plane formats
+		 */
+		BUG();
+		break;
+	}
+
+	if (obj->tiling_mode != I915_TILING_NONE)
+		sprctl |= SP_TILED;
+
+	sprctl |= SP_ENABLE;
+
+	/* Sizes are 0 based */
+	src_w--;
+	src_h--;
+	crtc_w--;
+	crtc_h--;
+
+	intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size);
+
+	I915_WRITE(SPSTRIDE(pipe, plane), fb->pitches[0]);
+	I915_WRITE(SPPOS(pipe, plane), (crtc_y << 16) | crtc_x);
+
+	linear_offset = y * fb->pitches[0] + x * pixel_size;
+	sprsurf_offset = intel_gen4_compute_page_offset(&x, &y,
+							obj->tiling_mode,
+							pixel_size,
+							fb->pitches[0]);
+	linear_offset -= sprsurf_offset;
+
+	if (obj->tiling_mode != I915_TILING_NONE)
+		I915_WRITE(SPTILEOFF(pipe, plane), (y << 16) | x);
+	else
+		I915_WRITE(SPLINOFF(pipe, plane), linear_offset);
+
+	I915_WRITE(SPSIZE(pipe, plane), (crtc_h << 16) | crtc_w);
+	I915_WRITE(SPCNTR(pipe, plane), sprctl);
+	I915_MODIFY_DISPBASE(SPSURF(pipe, plane), obj->gtt_offset +
+			     sprsurf_offset);
+	POSTING_READ(SPSURF(pipe, plane));
+}
+
+static void
+vlv_disable_plane(struct drm_plane *dplane)
+{
+	struct drm_device *dev = dplane->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_plane *intel_plane = to_intel_plane(dplane);
+	int pipe = intel_plane->pipe;
+	int plane = intel_plane->plane;
+
+	I915_WRITE(SPCNTR(pipe, plane), I915_READ(SPCNTR(pipe, plane)) &
+		   ~SP_ENABLE);
+	/* Activate double buffered register update */
+	I915_MODIFY_DISPBASE(SPSURF(pipe, plane), 0);
+	POSTING_READ(SPSURF(pipe, plane));
+}
+
+static int
+vlv_update_colorkey(struct drm_plane *dplane,
+		    struct drm_intel_sprite_colorkey *key)
+{
+	struct drm_device *dev = dplane->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_plane *intel_plane = to_intel_plane(dplane);
+	int pipe = intel_plane->pipe;
+	int plane = intel_plane->plane;
+	u32 sprctl;
+
+	if (key->flags & I915_SET_COLORKEY_DESTINATION)
+		return -EINVAL;
+
+	I915_WRITE(SPKEYMINVAL(pipe, plane), key->min_value);
+	I915_WRITE(SPKEYMAXVAL(pipe, plane), key->max_value);
+	I915_WRITE(SPKEYMSK(pipe, plane), key->channel_mask);
+
+	sprctl = I915_READ(SPCNTR(pipe, plane));
+	sprctl &= ~SP_SOURCE_KEY;
+	if (key->flags & I915_SET_COLORKEY_SOURCE)
+		sprctl |= SP_SOURCE_KEY;
+	I915_WRITE(SPCNTR(pipe, plane), sprctl);
+
+	POSTING_READ(SPKEYMSK(pipe, plane));
+
+	return 0;
+}
+
+static void
+vlv_get_colorkey(struct drm_plane *dplane,
+		 struct drm_intel_sprite_colorkey *key)
+{
+	struct drm_device *dev = dplane->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_plane *intel_plane = to_intel_plane(dplane);
+	int pipe = intel_plane->pipe;
+	int plane = intel_plane->plane;
+	u32 sprctl;
+
+	key->min_value = I915_READ(SPKEYMINVAL(pipe, plane));
+	key->max_value = I915_READ(SPKEYMAXVAL(pipe, plane));
+	key->channel_mask = I915_READ(SPKEYMSK(pipe, plane));
+
+	sprctl = I915_READ(SPCNTR(pipe, plane));
+	if (sprctl & SP_SOURCE_KEY)
+		key->flags = I915_SET_COLORKEY_SOURCE;
+	else
+		key->flags = I915_SET_COLORKEY_NONE;
+}
+
+static void
 ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
 		 struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
 		 unsigned int crtc_w, unsigned int crtc_h,
@@ -441,6 +609,15 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 
 	old_obj = intel_plane->obj;
 
+	intel_plane->crtc_x = crtc_x;
+	intel_plane->crtc_y = crtc_y;
+	intel_plane->crtc_w = crtc_w;
+	intel_plane->crtc_h = crtc_h;
+	intel_plane->src_x = src_x;
+	intel_plane->src_y = src_y;
+	intel_plane->src_w = src_w;
+	intel_plane->src_h = src_h;
+
 	src_w = src_w >> 16;
 	src_h = src_h >> 16;
 
@@ -513,6 +690,11 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 
 	mutex_lock(&dev->struct_mutex);
 
+	/* Note that this will apply the VT-d workaround for scanouts,
+	 * which is more restrictive than required for sprites. (The
+	 * primary plane requires 256KiB alignment with 64 PTE padding,
+	 * the sprite planes only require 128KiB alignment and 32 PTE padding.
+	 */
 	ret = intel_pin_and_fence_fb_obj(dev, obj, NULL);
 	if (ret)
 		goto out_unlock;
@@ -568,6 +750,8 @@ intel_disable_plane(struct drm_plane *plane)
 	if (!intel_plane->obj)
 		goto out;
 
+	intel_wait_for_vblank(dev, intel_plane->pipe);
+
 	mutex_lock(&dev->struct_mutex);
 	intel_unpin_fb_obj(intel_plane->obj);
 	intel_plane->obj = NULL;
@@ -647,6 +831,20 @@ out_unlock:
 	return ret;
 }
 
+void intel_plane_restore(struct drm_plane *plane)
+{
+	struct intel_plane *intel_plane = to_intel_plane(plane);
+
+	if (!plane->crtc || !plane->fb)
+		return;
+
+	intel_update_plane(plane, plane->crtc, plane->fb,
+			   intel_plane->crtc_x, intel_plane->crtc_y,
+			   intel_plane->crtc_w, intel_plane->crtc_h,
+			   intel_plane->src_x, intel_plane->src_y,
+			   intel_plane->src_w, intel_plane->src_h);
+}
+
 static const struct drm_plane_funcs intel_plane_funcs = {
 	.update_plane = intel_update_plane,
 	.disable_plane = intel_disable_plane,
@@ -670,8 +868,22 @@ static uint32_t snb_plane_formats[] = {
 	DRM_FORMAT_VYUY,
 };
 
+static uint32_t vlv_plane_formats[] = {
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_ABGR8888,
+	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_XBGR8888,
+	DRM_FORMAT_XRGB8888,
+	DRM_FORMAT_XBGR2101010,
+	DRM_FORMAT_ABGR2101010,
+	DRM_FORMAT_YUYV,
+	DRM_FORMAT_YVYU,
+	DRM_FORMAT_UYVY,
+	DRM_FORMAT_VYUY,
+};
+
 int
-intel_plane_init(struct drm_device *dev, enum pipe pipe)
+intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane)
 {
 	struct intel_plane *intel_plane;
 	unsigned long possible_crtcs;
@@ -710,14 +922,26 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe)
 			intel_plane->can_scale = false;
 		else
 			intel_plane->can_scale = true;
-		intel_plane->max_downscale = 2;
-		intel_plane->update_plane = ivb_update_plane;
-		intel_plane->disable_plane = ivb_disable_plane;
-		intel_plane->update_colorkey = ivb_update_colorkey;
-		intel_plane->get_colorkey = ivb_get_colorkey;
-
-		plane_formats = snb_plane_formats;
-		num_plane_formats = ARRAY_SIZE(snb_plane_formats);
+
+		if (IS_VALLEYVIEW(dev)) {
+			intel_plane->max_downscale = 1;
+			intel_plane->update_plane = vlv_update_plane;
+			intel_plane->disable_plane = vlv_disable_plane;
+			intel_plane->update_colorkey = vlv_update_colorkey;
+			intel_plane->get_colorkey = vlv_get_colorkey;
+
+			plane_formats = vlv_plane_formats;
+			num_plane_formats = ARRAY_SIZE(vlv_plane_formats);
+		} else {
+			intel_plane->max_downscale = 2;
+			intel_plane->update_plane = ivb_update_plane;
+			intel_plane->disable_plane = ivb_disable_plane;
+			intel_plane->update_colorkey = ivb_update_colorkey;
+			intel_plane->get_colorkey = ivb_get_colorkey;
+
+			plane_formats = snb_plane_formats;
+			num_plane_formats = ARRAY_SIZE(snb_plane_formats);
+		}
 		break;
 
 	default:
@@ -726,6 +950,7 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe)
 	}
 
 	intel_plane->pipe = pipe;
+	intel_plane->plane = plane;
 	possible_crtcs = (1 << pipe);
 	ret = drm_plane_init(dev, &intel_plane->base, possible_crtcs,
 			     &intel_plane_funcs,
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
index d808421..6673726 100644
--- a/drivers/gpu/drm/i915/intel_tv.c
+++ b/drivers/gpu/drm/i915/intel_tv.c
@@ -905,11 +905,10 @@ intel_tv_mode_valid(struct drm_connector *connector,
 
 
 static bool
-intel_tv_mode_fixup(struct drm_encoder *encoder,
-		    const struct drm_display_mode *mode,
-		    struct drm_display_mode *adjusted_mode)
+intel_tv_compute_config(struct intel_encoder *encoder,
+			struct intel_crtc_config *pipe_config)
 {
-	struct intel_tv *intel_tv = enc_to_intel_tv(encoder);
+	struct intel_tv *intel_tv = enc_to_intel_tv(&encoder->base);
 	const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv);
 
 	if (!tv_mode)
@@ -918,7 +917,10 @@ intel_tv_mode_fixup(struct drm_encoder *encoder,
 	if (intel_encoder_check_is_cloned(&intel_tv->base))
 		return false;
 
-	adjusted_mode->clock = tv_mode->clock;
+	pipe_config->adjusted_mode.clock = tv_mode->clock;
+	DRM_DEBUG_KMS("forcing bpc to 8 for TV\n");
+	pipe_config->pipe_bpp = 8*3;
+
 	return true;
 }
 
@@ -1485,7 +1487,6 @@ out:
 }
 
 static const struct drm_encoder_helper_funcs intel_tv_helper_funcs = {
-	.mode_fixup = intel_tv_mode_fixup,
 	.mode_set = intel_tv_mode_set,
 };
 
@@ -1620,6 +1621,7 @@ intel_tv_init(struct drm_device *dev)
 	drm_encoder_init(dev, &intel_encoder->base, &intel_tv_enc_funcs,
 			 DRM_MODE_ENCODER_TVDAC);
 
+	intel_encoder->compute_config = intel_tv_compute_config;
 	intel_encoder->enable = intel_enable_tv;
 	intel_encoder->disable = intel_disable_tv;
 	intel_encoder->get_hw_state = intel_tv_get_hw_state;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/base.c b/drivers/gpu/drm/nouveau/core/subdev/bios/base.c
index e816f06..0e2c1a4 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/bios/base.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/bios/base.c
@@ -248,6 +248,22 @@ nouveau_bios_shadow_pci(struct nouveau_bios *bios)
 	}
 }
 
+static void
+nouveau_bios_shadow_platform(struct nouveau_bios *bios)
+{
+	struct pci_dev *pdev = nv_device(bios)->pdev;
+	size_t size;
+
+	void __iomem *rom = pci_platform_rom(pdev, &size);
+	if (rom && size) {
+		bios->data = kmalloc(size, GFP_KERNEL);
+		if (bios->data) {
+			memcpy_fromio(bios->data, rom, size);
+			bios->size = size;
+		}
+	}
+}
+
 static int
 nouveau_bios_score(struct nouveau_bios *bios, const bool writeable)
 {
@@ -288,6 +304,7 @@ nouveau_bios_shadow(struct nouveau_bios *bios)
 		{ "PROM", nouveau_bios_shadow_prom, false, 0, 0, NULL },
 		{ "ACPI", nouveau_bios_shadow_acpi, true, 0, 0, NULL },
 		{ "PCIROM", nouveau_bios_shadow_pci, true, 0, 0, NULL },
+		{ "PLATFORM", nouveau_bios_shadow_platform, true, 0, 0, NULL },
 		{}
 	};
 	struct methods *mthd, *best;
diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.c b/drivers/gpu/drm/nouveau/nouveau_abi16.c
index 3b6dc88..5eb3e0d 100644
--- a/drivers/gpu/drm/nouveau/nouveau_abi16.c
+++ b/drivers/gpu/drm/nouveau/nouveau_abi16.c
@@ -391,7 +391,7 @@ nouveau_abi16_ioctl_notifierobj_alloc(ABI16_IOCTL_ARGS)
 	struct nouveau_drm *drm = nouveau_drm(dev);
 	struct nouveau_device *device = nv_device(drm->device);
 	struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv, dev);
-	struct nouveau_abi16_chan *chan, *temp;
+	struct nouveau_abi16_chan *chan = NULL, *temp;
 	struct nouveau_abi16_ntfy *ntfy;
 	struct nouveau_object *object;
 	struct nv_dma_class args = {};
@@ -404,10 +404,11 @@ nouveau_abi16_ioctl_notifierobj_alloc(ABI16_IOCTL_ARGS)
 	if (unlikely(nv_device(abi16->device)->card_type >= NV_C0))
 		return nouveau_abi16_put(abi16, -EINVAL);
 
-	list_for_each_entry_safe(chan, temp, &abi16->channels, head) {
-		if (chan->chan->handle == (NVDRM_CHAN | info->channel))
+	list_for_each_entry(temp, &abi16->channels, head) {
+		if (temp->chan->handle == (NVDRM_CHAN | info->channel)) {
+			chan = temp;
 			break;
-		chan = NULL;
+		}
 	}
 
 	if (!chan)
@@ -459,17 +460,18 @@ nouveau_abi16_ioctl_gpuobj_free(ABI16_IOCTL_ARGS)
 {
 	struct drm_nouveau_gpuobj_free *fini = data;
 	struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv, dev);
-	struct nouveau_abi16_chan *chan, *temp;
+	struct nouveau_abi16_chan *chan = NULL, *temp;
 	struct nouveau_abi16_ntfy *ntfy;
 	int ret;
 
 	if (unlikely(!abi16))
 		return -ENOMEM;
 
-	list_for_each_entry_safe(chan, temp, &abi16->channels, head) {
-		if (chan->chan->handle == (NVDRM_CHAN | fini->channel))
+	list_for_each_entry(temp, &abi16->channels, head) {
+		if (temp->chan->handle == (NVDRM_CHAN | fini->channel)) {
+			chan = temp;
 			break;
-		chan = NULL;
+		}
 	}
 
 	if (!chan)
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
index d109936..c95decf 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
@@ -72,11 +72,25 @@ module_param_named(modeset, nouveau_modeset, int, 0400);
 static struct drm_driver driver;
 
 static int
+nouveau_drm_vblank_handler(struct nouveau_eventh *event, int head)
+{
+	struct nouveau_drm *drm =
+		container_of(event, struct nouveau_drm, vblank[head]);
+	drm_handle_vblank(drm->dev, head);
+	return NVKM_EVENT_KEEP;
+}
+
+static int
 nouveau_drm_vblank_enable(struct drm_device *dev, int head)
 {
 	struct nouveau_drm *drm = nouveau_drm(dev);
 	struct nouveau_disp *pdisp = nouveau_disp(drm->device);
-	nouveau_event_get(pdisp->vblank, head, &drm->vblank);
+
+	if (WARN_ON_ONCE(head > ARRAY_SIZE(drm->vblank)))
+		return -EIO;
+	WARN_ON_ONCE(drm->vblank[head].func);
+	drm->vblank[head].func = nouveau_drm_vblank_handler;
+	nouveau_event_get(pdisp->vblank, head, &drm->vblank[head]);
 	return 0;
 }
 
@@ -85,16 +99,11 @@ nouveau_drm_vblank_disable(struct drm_device *dev, int head)
 {
 	struct nouveau_drm *drm = nouveau_drm(dev);
 	struct nouveau_disp *pdisp = nouveau_disp(drm->device);
-	nouveau_event_put(pdisp->vblank, head, &drm->vblank);
-}
-
-static int
-nouveau_drm_vblank_handler(struct nouveau_eventh *event, int head)
-{
-	struct nouveau_drm *drm =
-		container_of(event, struct nouveau_drm, vblank);
-	drm_handle_vblank(drm->dev, head);
-	return NVKM_EVENT_KEEP;
+	if (drm->vblank[head].func)
+		nouveau_event_put(pdisp->vblank, head, &drm->vblank[head]);
+	else
+		WARN_ON_ONCE(1);
+	drm->vblank[head].func = NULL;
 }
 
 static u64
@@ -292,7 +301,6 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags)
 
 	dev->dev_private = drm;
 	drm->dev = dev;
-	drm->vblank.func = nouveau_drm_vblank_handler;
 
 	INIT_LIST_HEAD(&drm->clients);
 	spin_lock_init(&drm->tile.lock);
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.h b/drivers/gpu/drm/nouveau/nouveau_drm.h
index b25df37..9c39baf 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.h
@@ -113,7 +113,7 @@ struct nouveau_drm {
 	struct nvbios vbios;
 	struct nouveau_display *display;
 	struct backlight_device *backlight;
-	struct nouveau_eventh vblank;
+	struct nouveau_eventh vblank[4];
 
 	/* power management */
 	struct nouveau_pm *pm;
diff --git a/drivers/gpu/drm/radeon/radeon_bios.c b/drivers/gpu/drm/radeon/radeon_bios.c
index b801591..fa3c56f 100644
--- a/drivers/gpu/drm/radeon/radeon_bios.c
+++ b/drivers/gpu/drm/radeon/radeon_bios.c
@@ -99,6 +99,29 @@ static bool radeon_read_bios(struct radeon_device *rdev)
 	return true;
 }
 
+static bool radeon_read_platform_bios(struct radeon_device *rdev)
+{
+	uint8_t __iomem *bios;
+	size_t size;
+
+	rdev->bios = NULL;
+
+	bios = pci_platform_rom(rdev->pdev, &size);
+	if (!bios) {
+		return false;
+	}
+
+	if (size == 0 || bios[0] != 0x55 || bios[1] != 0xaa) {
+		return false;
+	}
+	rdev->bios = kmemdup(bios, size, GFP_KERNEL);
+	if (rdev->bios == NULL) {
+		return false;
+	}
+
+	return true;
+}
+
 #ifdef CONFIG_ACPI
 /* ATRM is used to get the BIOS on the discrete cards in
  * dual-gpu systems.
@@ -620,6 +643,9 @@ bool radeon_get_bios(struct radeon_device *rdev)
 	if (r == false) {
 		r = radeon_read_disabled_bios(rdev);
 	}
+	if (r == false) {
+		r = radeon_read_platform_bios(rdev);
+	}
 	if (r == false || rdev->bios == NULL) {
 		DRM_ERROR("Unable to locate a BIOS ROM\n");
 		rdev->bios = NULL;
diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c
index 48f80cd..5a99d43 100644
--- a/drivers/gpu/drm/radeon/radeon_irq_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c
@@ -270,7 +270,7 @@ int radeon_irq_kms_init(struct radeon_device *rdev)
 }
 
 /**
- * radeon_irq_kms_fini - tear down driver interrrupt info
+ * radeon_irq_kms_fini - tear down driver interrupt info
  *
  * @rdev: radeon device pointer
  *
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 5f07d85..613083a 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -92,14 +92,14 @@ menu "Special HID drivers"
 
 config HID_A4TECH
 	tristate "A4 tech mice" if EXPERT
-	depends on USB_HID
+	depends on HID
 	default !EXPERT
 	---help---
 	Support for A4 tech X5 and WOP-35 / Trust 450L mice.
 
 config HID_ACRUX
 	tristate "ACRUX game controller support"
-	depends on USB_HID
+	depends on HID
 	---help---
 	Say Y here if you want to enable support for ACRUX game controllers.
 
@@ -113,7 +113,7 @@ config HID_ACRUX_FF
 
 config HID_APPLE
 	tristate "Apple {i,Power,Mac}Books" if EXPERT
-	depends on (USB_HID || BT_HIDP)
+	depends on HID
 	default !EXPERT
 	---help---
 	Support for some Apple devices which less or more break
@@ -124,34 +124,34 @@ config HID_APPLE
 
 config HID_AUREAL
 	tristate "Aureal"
-	depends on USB_HID
+	depends on HID
 	---help---
 	Support for Aureal Cy se W-01RN Remote Controller and other Aureal derived remotes.
 
 config HID_BELKIN
 	tristate "Belkin Flip KVM and Wireless keyboard" if EXPERT
-	depends on USB_HID
+	depends on HID
 	default !EXPERT
 	---help---
 	Support for Belkin Flip KVM and Wireless keyboard.
 
 config HID_CHERRY
 	tristate "Cherry Cymotion keyboard" if EXPERT
-	depends on USB_HID
+	depends on HID
 	default !EXPERT
 	---help---
 	Support for Cherry Cymotion keyboard.
 
 config HID_CHICONY
 	tristate "Chicony Tactical pad" if EXPERT
-	depends on USB_HID
+	depends on HID
 	default !EXPERT
 	---help---
 	Support for Chicony Tactical pad.
 
 config HID_PRODIKEYS
 	tristate "Prodikeys PC-MIDI Keyboard support"
-	depends on USB_HID && SND
+	depends on HID && SND
 	select SND_RAWMIDI
 	---help---
 	Support for Prodikeys PC-MIDI Keyboard device support.
@@ -166,14 +166,14 @@ config HID_PRODIKEYS
 
 config HID_CYPRESS
 	tristate "Cypress mouse and barcode readers" if EXPERT
-	depends on USB_HID
+	depends on HID
 	default !EXPERT
 	---help---
 	Support for cypress mouse and barcode readers.
 
 config HID_DRAGONRISE
 	tristate "DragonRise Inc. game controller"
-	depends on USB_HID
+	depends on HID
 	---help---
 	Say Y here if you have DragonRise Inc. game controllers.
 	These might be branded as:
@@ -192,7 +192,7 @@ config DRAGONRISE_FF
 
 config HID_EMS_FF
 	tristate "EMS Production Inc. force feedback support"
-	depends on USB_HID
+	depends on HID
 	select INPUT_FF_MEMLESS
 	---help---
 	Say Y here if you want to enable force feedback support for devices by
@@ -202,13 +202,13 @@ config HID_EMS_FF
 
 config HID_ELECOM
 	tristate "ELECOM BM084 bluetooth mouse"
-	depends on BT_HIDP
+	depends on HID
 	---help---
 	Support for the ELECOM BM084 (bluetooth mouse).
 
 config HID_EZKEY
 	tristate "Ezkey BTC 8193 keyboard" if EXPERT
-	depends on USB_HID
+	depends on HID
 	default !EXPERT
 	---help---
 	Support for Ezkey BTC 8193 keyboard.
@@ -231,7 +231,7 @@ config HOLTEK_FF
 
 config HID_KEYTOUCH
 	tristate "Keytouch HID devices"
-	depends on USB_HID
+	depends on HID
 	---help---
 	Support for Keytouch HID devices not fully compliant with
 	the specification. Currently supported:
@@ -239,7 +239,7 @@ config HID_KEYTOUCH
 
 config HID_KYE
 	tristate "KYE/Genius devices"
-	depends on USB_HID
+	depends on HID
 	---help---
 	Support for KYE/Genius devices not fully compliant with HID standard:
 	- Ergo Mouse
@@ -249,25 +249,25 @@ config HID_KYE
 
 config HID_UCLOGIC
 	tristate "UC-Logic"
-	depends on USB_HID
+	depends on HID
 	---help---
 	Support for UC-Logic tablets.
 
 config HID_WALTOP
 	tristate "Waltop"
-	depends on USB_HID
+	depends on HID
 	---help---
 	Support for Waltop tablets.
 
 config HID_GYRATION
 	tristate "Gyration remote control"
-	depends on USB_HID
+	depends on HID
 	---help---
 	Support for Gyration remote control.
 
 config HID_ICADE
 	tristate "ION iCade arcade controller"
-	depends on BT_HIDP
+	depends on HID
 	---help---
 	Support for the ION iCade arcade controller to work as a joystick.
 
@@ -276,20 +276,20 @@ config HID_ICADE
 
 config HID_TWINHAN
 	tristate "Twinhan IR remote control"
-	depends on USB_HID
+	depends on HID
 	---help---
 	Support for Twinhan IR remote control.
 
 config HID_KENSINGTON
 	tristate "Kensington Slimblade Trackball" if EXPERT
-	depends on USB_HID
+	depends on HID
 	default !EXPERT
 	---help---
 	Support for Kensington Slimblade Trackball.
 
 config HID_LCPOWER
 	tristate "LC-Power"
-	depends on USB_HID
+	depends on HID
 	---help---
 	Support for LC-Power RC1000MCE RF remote control.
 
@@ -308,7 +308,7 @@ config HID_LENOVO_TPKBD
 
 config HID_LOGITECH
 	tristate "Logitech devices" if EXPERT
-	depends on USB_HID
+	depends on HID
 	default !EXPERT
 	---help---
 	Support for Logitech devices that are not fully compliant with HID standard.
@@ -374,7 +374,7 @@ config LOGIWHEELS_FF
 
 config HID_MAGICMOUSE
 	tristate "Apple MagicMouse multi-touch support"
-	depends on BT_HIDP
+	depends on HID
 	---help---
 	Support for the Apple Magic Mouse multi-touch.
 
@@ -383,21 +383,21 @@ config HID_MAGICMOUSE
 
 config HID_MICROSOFT
 	tristate "Microsoft non-fully HID-compliant devices" if EXPERT
-	depends on USB_HID
+	depends on HID
 	default !EXPERT
 	---help---
 	Support for Microsoft devices that are not fully compliant with HID standard.
 
 config HID_MONTEREY
 	tristate "Monterey Genius KB29E keyboard" if EXPERT
-	depends on USB_HID
+	depends on HID
 	default !EXPERT
 	---help---
 	Support for Monterey Genius KB29E.
 
 config HID_MULTITOUCH
 	tristate "HID Multitouch panels"
-	depends on USB_HID
+	depends on HID
 	---help---
 	  Generic support for HID multitouch panels.
 
@@ -445,7 +445,7 @@ config HID_NTRIG
 
 config HID_ORTEK
 	tristate "Ortek PKB-1700/WKB-2000/Skycable wireless keyboard and mouse trackpad"
-	depends on USB_HID
+	depends on HID
 	---help---
 	There are certain devices which have LogicalMaximum wrong in the keyboard
 	usage page of their report descriptor. The most prevailing ones so far
@@ -458,7 +458,7 @@ config HID_ORTEK
 
 config HID_PANTHERLORD
 	tristate "Pantherlord/GreenAsia game controller"
-	depends on USB_HID
+	depends on HID
 	---help---
 	  Say Y here if you have a PantherLord/GreenAsia based game controller
 	  or adapter.
@@ -473,13 +473,13 @@ config PANTHERLORD_FF
 
 config HID_PETALYNX
 	tristate "Petalynx Maxter remote control"
-	depends on USB_HID
+	depends on HID
 	---help---
 	Support for Petalynx Maxter remote control.
 
 config HID_PICOLCD
 	tristate "PicoLCD (graphic version)"
-	depends on USB_HID
+	depends on HID
 	---help---
 	  This provides support for Minibox PicoLCD devices, currently
 	  only the graphical ones are supported.
@@ -545,14 +545,14 @@ config HID_PICOLCD_CIR
 
 config HID_PRIMAX
 	tristate "Primax non-fully HID-compliant devices"
-	depends on USB_HID
+	depends on HID
 	---help---
 	Support for Primax devices that are not fully compliant with the
 	HID standard.
 
 config HID_PS3REMOTE
 	tristate "Sony PS3 BD Remote Control"
-	depends on BT_HIDP
+	depends on HID
 	---help---
 	Support for the Sony PS3 Blue-ray Disk Remote Control and Logitech
 	Harmony Adapter for PS3, which connect over Bluetooth.
@@ -569,7 +569,7 @@ config HID_ROCCAT
 
 config HID_SAITEK
 	tristate "Saitek non-fully HID-compliant devices"
-	depends on USB_HID
+	depends on HID
 	---help---
 	Support for Saitek devices that are not fully compliant with the
 	HID standard.
@@ -578,7 +578,7 @@ config HID_SAITEK
 
 config HID_SAMSUNG
 	tristate "Samsung InfraRed remote control or keyboards"
-	depends on USB_HID
+	depends on HID
 	---help---
 	Support for Samsung InfraRed remote control or keyboards.
 
@@ -592,25 +592,25 @@ config HID_SONY
 
 config HID_SPEEDLINK
 	tristate "Speedlink VAD Cezanne mouse support"
-	depends on USB_HID
+	depends on HID
 	---help---
 	Support for Speedlink Vicious and Divine Cezanne mouse.
 
 config HID_STEELSERIES
 	tristate "Steelseries SRW-S1 steering wheel support"
-	depends on USB_HID
+	depends on HID
 	---help---
 	Support for Steelseries SRW-S1 steering wheel
 
 config HID_SUNPLUS
 	tristate "Sunplus wireless desktop"
-	depends on USB_HID
+	depends on HID
 	---help---
 	Support for Sunplus wireless desktop.
 
 config HID_GREENASIA
 	tristate "GreenAsia (Product ID 0x12) game controller support"
-	depends on USB_HID
+	depends on HID
 	---help---
 	  Say Y here if you have a GreenAsia (Product ID 0x12) based game
 	  controller or adapter.
@@ -632,7 +632,7 @@ config HID_HYPERV_MOUSE
 
 config HID_SMARTJOYPLUS
 	tristate "SmartJoy PLUS PS2/USB adapter support"
-	depends on USB_HID
+	depends on HID
 	---help---
 	Support for SmartJoy PLUS PS2/USB adapter, Super Dual Box,
 	Super Joy Box 3 Pro, Super Dual Box Pro, and Super Joy Box 5 Pro.
@@ -650,20 +650,20 @@ config SMARTJOYPLUS_FF
 
 config HID_TIVO
 	tristate "TiVo Slide Bluetooth remote control support"
-	depends on (USB_HID || BT_HIDP)
+	depends on HID
 	---help---
 	Say Y if you have a TiVo Slide Bluetooth remote control.
 
 config HID_TOPSEED
 	tristate "TopSeed Cyberlink, BTC Emprex, Conceptronic remote control support"
-	depends on USB_HID
+	depends on HID
 	---help---
 	Say Y if you have a TopSeed Cyberlink or BTC Emprex or Conceptronic
 	CLLRCMCE remote control.
 
 config HID_THINGM
 	tristate "ThingM blink(1) USB RGB LED"
-	depends on USB_HID
+	depends on HID
 	depends on LEDS_CLASS
 	---help---
 	Support for the ThingM blink(1) USB RGB LED. This driver registers a
@@ -673,7 +673,7 @@ config HID_THINGM
 
 config HID_THRUSTMASTER
 	tristate "ThrustMaster devices support"
-	depends on USB_HID
+	depends on HID
 	---help---
 	  Say Y here if you have a THRUSTMASTER FireStore Dual Power 2 or
 	  a THRUSTMASTER Ferrari GT Rumble Wheel.
@@ -689,7 +689,7 @@ config THRUSTMASTER_FF
 
 config HID_WACOM
 	tristate "Wacom Bluetooth devices support"
-	depends on BT_HIDP
+	depends on HID
 	depends on LEDS_CLASS
 	select POWER_SUPPLY
 	---help---
@@ -697,7 +697,7 @@ config HID_WACOM
 
 config HID_WIIMOTE
 	tristate "Nintendo Wii Remote support"
-	depends on BT_HIDP
+	depends on HID
 	depends on LEDS_CLASS
 	select POWER_SUPPLY
 	select INPUT_FF_MEMLESS
@@ -715,7 +715,7 @@ config HID_WIIMOTE_EXT
 
 config HID_ZEROPLUS
 	tristate "Zeroplus based game controller support"
-	depends on USB_HID
+	depends on HID
 	---help---
 	  Say Y here if you have a Zeroplus based game controller.
 
@@ -729,16 +729,16 @@ config ZEROPLUS_FF
 
 config HID_ZYDACRON
 	tristate "Zydacron remote control support"
-	depends on USB_HID
+	depends on HID
 	---help---
 	Support for Zydacron remote control.
 
 config HID_SENSOR_HUB
 	tristate "HID Sensors framework support"
-	depends on USB_HID && GENERIC_HARDIRQS
+	depends on HID && GENERIC_HARDIRQS
 	select MFD_CORE
 	default n
-	-- help---
+	---help---
 	  Support for HID Sensor framework. This creates a MFD instance
 	  for a sensor hub and identifies all the sensors connected to it.
 	  Each sensor is registered as a MFD cell, so that sensor specific
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index 72d1b0b..2735151 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -94,8 +94,8 @@ obj-$(CONFIG_HID_PRIMAX)	+= hid-primax.o
 obj-$(CONFIG_HID_PS3REMOTE)	+= hid-ps3remote.o
 obj-$(CONFIG_HID_ROCCAT)	+= hid-roccat.o hid-roccat-common.o \
 	hid-roccat-arvo.o hid-roccat-isku.o hid-roccat-kone.o \
-	hid-roccat-koneplus.o hid-roccat-kovaplus.o hid-roccat-lua.o \
-	hid-roccat-pyra.o hid-roccat-savu.o
+	hid-roccat-koneplus.o hid-roccat-konepure.o hid-roccat-kovaplus.o \
+	hid-roccat-lua.o hid-roccat-pyra.o hid-roccat-savu.o
 obj-$(CONFIG_HID_SAITEK)	+= hid-saitek.o
 obj-$(CONFIG_HID_SAMSUNG)	+= hid-samsung.o
 obj-$(CONFIG_HID_SMARTJOYPLUS)	+= hid-sjoy.o
diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c
index 320a958..9e0c4fbb 100644
--- a/drivers/hid/hid-apple.c
+++ b/drivers/hid/hid-apple.c
@@ -21,7 +21,6 @@
 #include <linux/hid.h>
 #include <linux/module.h>
 #include <linux/slab.h>
-#include <linux/usb.h>
 
 #include "hid-ids.h"
 
diff --git a/drivers/hid/hid-axff.c b/drivers/hid/hid-axff.c
index 62f0cee..64ab94a 100644
--- a/drivers/hid/hid-axff.c
+++ b/drivers/hid/hid-axff.c
@@ -29,14 +29,12 @@
 
 #include <linux/input.h>
 #include <linux/slab.h>
-#include <linux/usb.h>
 #include <linux/hid.h>
 #include <linux/module.h>
 
 #include "hid-ids.h"
 
 #ifdef CONFIG_HID_ACRUX_FF
-#include "usbhid/usbhid.h"
 
 struct axff_device {
 	struct hid_report *report;
@@ -68,7 +66,7 @@ static int axff_play(struct input_dev *dev, void *data, struct ff_effect *effect
 	}
 
 	dbg_hid("running with 0x%02x 0x%02x", left, right);
-	usbhid_submit_report(hid, axff->report, USB_DIR_OUT);
+	hid_hw_request(hid, axff->report, HID_REQ_SET_REPORT);
 
 	return 0;
 }
@@ -114,7 +112,7 @@ static int axff_init(struct hid_device *hid)
 		goto err_free_mem;
 
 	axff->report = report;
-	usbhid_submit_report(hid, axff->report, USB_DIR_OUT);
+	hid_hw_request(hid, axff->report, HID_REQ_SET_REPORT);
 
 	hid_info(hid, "Force Feedback for ACRUX game controllers by Sergei Kolzun <x0r@dv-life.ru>\n");
 
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 512b01c..3d5bbb0 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -728,8 +728,7 @@ static int hid_scan_report(struct hid_device *hid)
 		} else if (page == HID_UP_SENSOR &&
 			item.type == HID_ITEM_TYPE_MAIN &&
 			item.tag == HID_MAIN_ITEM_TAG_BEGIN_COLLECTION &&
-			(item_udata(&item) & 0xff) == HID_COLLECTION_PHYSICAL &&
-			(hid->bus == BUS_USB || hid->bus == BUS_I2C))
+			(item_udata(&item) & 0xff) == HID_COLLECTION_PHYSICAL)
 			hid->group = HID_GROUP_SENSOR_HUB;
 	}
 
@@ -1267,7 +1266,7 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i
 	if (!hid)
 		return -ENODEV;
 
-	if (down_trylock(&hid->driver_lock))
+	if (down_trylock(&hid->driver_input_lock))
 		return -EBUSY;
 
 	if (!hid->driver) {
@@ -1324,7 +1323,7 @@ nomem:
 	ret = hid_report_raw_event(hid, type, data, size, interrupt);
 
 unlock:
-	up(&hid->driver_lock);
+	up(&hid->driver_input_lock);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(hid_input_report);
@@ -1687,6 +1686,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ARVO) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ISKU) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPLUS) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPURE) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KOVAPLUS) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_LUA) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRED) },
@@ -1747,6 +1747,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
 
 	{ 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) },
+	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO, USB_DEVICE_ID_NINTENDO_WIIMOTE2) },
 	{ }
 };
 
@@ -1845,6 +1846,11 @@ static int hid_device_probe(struct device *dev)
 
 	if (down_interruptible(&hdev->driver_lock))
 		return -EINTR;
+	if (down_interruptible(&hdev->driver_input_lock)) {
+		ret = -EINTR;
+		goto unlock_driver_lock;
+	}
+	hdev->io_started = false;
 
 	if (!hdev->driver) {
 		id = hid_match_device(hdev, hdrv);
@@ -1867,6 +1873,9 @@ static int hid_device_probe(struct device *dev)
 		}
 	}
 unlock:
+	if (!hdev->io_started)
+		up(&hdev->driver_input_lock);
+unlock_driver_lock:
 	up(&hdev->driver_lock);
 	return ret;
 }
@@ -1875,9 +1884,15 @@ static int hid_device_remove(struct device *dev)
 {
 	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
 	struct hid_driver *hdrv;
+	int ret = 0;
 
 	if (down_interruptible(&hdev->driver_lock))
 		return -EINTR;
+	if (down_interruptible(&hdev->driver_input_lock)) {
+		ret = -EINTR;
+		goto unlock_driver_lock;
+	}
+	hdev->io_started = false;
 
 	hdrv = hdev->driver;
 	if (hdrv) {
@@ -1889,8 +1904,11 @@ static int hid_device_remove(struct device *dev)
 		hdev->driver = NULL;
 	}
 
+	if (!hdev->io_started)
+		up(&hdev->driver_input_lock);
+unlock_driver_lock:
 	up(&hdev->driver_lock);
-	return 0;
+	return ret;
 }
 
 static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
@@ -2077,7 +2095,6 @@ static const struct hid_device_id hid_ignore_list[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_HYBRID) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_HEATCONTROL) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_BEATPAD) },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_MASTERKIT, USB_DEVICE_ID_MASTERKIT_MA901RADIO) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1024LS) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1208LS) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICKIT1) },
@@ -2244,6 +2261,18 @@ bool hid_ignore(struct hid_device *hdev)
 		     hdev->product <= USB_DEVICE_ID_VELLEMAN_K8061_LAST))
 			return true;
 		break;
+	case USB_VENDOR_ID_ATMEL_V_USB:
+		/* Masterkit MA901 usb radio based on Atmel tiny85 chip and
+		 * it has the same USB ID as many Atmel V-USB devices. This
+		 * usb radio is handled by radio-ma901.c driver so we want
+		 * ignore the hid. Check the name, bus, product and ignore
+		 * if we have MA901 usb radio.
+		 */
+		if (hdev->product == USB_DEVICE_ID_ATMEL_V_USB &&
+			hdev->bus == BUS_USB &&
+			strncmp(hdev->name, "www.masterkit.ru MA901", 22) == 0)
+			return true;
+		break;
 	}
 
 	if (hdev->type == HID_TYPE_USBMOUSE &&
@@ -2330,6 +2359,7 @@ struct hid_device *hid_allocate_device(void)
 	init_waitqueue_head(&hdev->debug_wait);
 	INIT_LIST_HEAD(&hdev->debug_list);
 	sema_init(&hdev->driver_lock, 1);
+	sema_init(&hdev->driver_input_lock, 1);
 
 	return hdev;
 }
diff --git a/drivers/hid/hid-dr.c b/drivers/hid/hid-dr.c
index 0fe8f65..ce06444 100644
--- a/drivers/hid/hid-dr.c
+++ b/drivers/hid/hid-dr.c
@@ -29,14 +29,12 @@
 
 #include <linux/input.h>
 #include <linux/slab.h>
-#include <linux/usb.h>
 #include <linux/hid.h>
 #include <linux/module.h>
 
 #include "hid-ids.h"
 
 #ifdef CONFIG_DRAGONRISE_FF
-#include "usbhid/usbhid.h"
 
 struct drff_device {
 	struct hid_report *report;
@@ -68,7 +66,7 @@ static int drff_play(struct input_dev *dev, void *data,
 		drff->report->field[0]->value[1] = 0x00;
 		drff->report->field[0]->value[2] = weak;
 		drff->report->field[0]->value[4] = strong;
-		usbhid_submit_report(hid, drff->report, USB_DIR_OUT);
+		hid_hw_request(hid, drff->report, HID_REQ_SET_REPORT);
 
 		drff->report->field[0]->value[0] = 0xfa;
 		drff->report->field[0]->value[1] = 0xfe;
@@ -80,7 +78,7 @@ static int drff_play(struct input_dev *dev, void *data,
 	drff->report->field[0]->value[2] = 0x00;
 	drff->report->field[0]->value[4] = 0x00;
 	dbg_hid("running with 0x%02x 0x%02x", strong, weak);
-	usbhid_submit_report(hid, drff->report, USB_DIR_OUT);
+	hid_hw_request(hid, drff->report, HID_REQ_SET_REPORT);
 
 	return 0;
 }
@@ -132,7 +130,7 @@ static int drff_init(struct hid_device *hid)
 	drff->report->field[0]->value[4] = 0x00;
 	drff->report->field[0]->value[5] = 0x00;
 	drff->report->field[0]->value[6] = 0x00;
-	usbhid_submit_report(hid, drff->report, USB_DIR_OUT);
+	hid_hw_request(hid, drff->report, HID_REQ_SET_REPORT);
 
 	hid_info(hid, "Force Feedback for DragonRise Inc. "
 		 "game controllers by Richard Walmsley <richwalm@gmail.com>\n");
diff --git a/drivers/hid/hid-emsff.c b/drivers/hid/hid-emsff.c
index 2e093ab..d82d75b 100644
--- a/drivers/hid/hid-emsff.c
+++ b/drivers/hid/hid-emsff.c
@@ -23,11 +23,9 @@
 
 #include <linux/hid.h>
 #include <linux/input.h>
-#include <linux/usb.h>
 #include <linux/module.h>
 
 #include "hid-ids.h"
-#include "usbhid/usbhid.h"
 
 struct emsff_device {
 	struct hid_report *report;
@@ -52,7 +50,7 @@ static int emsff_play(struct input_dev *dev, void *data,
 	emsff->report->field[0]->value[2] = strong;
 
 	dbg_hid("running with 0x%02x 0x%02x\n", strong, weak);
-	usbhid_submit_report(hid, emsff->report, USB_DIR_OUT);
+	hid_hw_request(hid, emsff->report, HID_REQ_SET_REPORT);
 
 	return 0;
 }
@@ -104,7 +102,7 @@ static int emsff_init(struct hid_device *hid)
 	emsff->report->field[0]->value[4] = 0x00;
 	emsff->report->field[0]->value[5] = 0x00;
 	emsff->report->field[0]->value[6] = 0x00;
-	usbhid_submit_report(hid, emsff->report, USB_DIR_OUT);
+	hid_hw_request(hid, emsff->report, HID_REQ_SET_REPORT);
 
 	hid_info(hid, "force feedback for EMS based devices by Ignaz Forster <ignaz.forster@gmx.de>\n");
 
diff --git a/drivers/hid/hid-gaff.c b/drivers/hid/hid-gaff.c
index 04d2e6a..2d8cead 100644
--- a/drivers/hid/hid-gaff.c
+++ b/drivers/hid/hid-gaff.c
@@ -29,13 +29,11 @@
 
 #include <linux/input.h>
 #include <linux/slab.h>
-#include <linux/usb.h>
 #include <linux/hid.h>
 #include <linux/module.h>
 #include "hid-ids.h"
 
 #ifdef CONFIG_GREENASIA_FF
-#include "usbhid/usbhid.h"
 
 struct gaff_device {
 	struct hid_report *report;
@@ -63,14 +61,14 @@ static int hid_gaff_play(struct input_dev *dev, void *data,
 	gaff->report->field[0]->value[4] = left;
 	gaff->report->field[0]->value[5] = 0;
 	dbg_hid("running with 0x%02x 0x%02x", left, right);
-	usbhid_submit_report(hid, gaff->report, USB_DIR_OUT);
+	hid_hw_request(hid, gaff->report, HID_REQ_SET_REPORT);
 
 	gaff->report->field[0]->value[0] = 0xfa;
 	gaff->report->field[0]->value[1] = 0xfe;
 	gaff->report->field[0]->value[2] = 0x0;
 	gaff->report->field[0]->value[4] = 0x0;
 
-	usbhid_submit_report(hid, gaff->report, USB_DIR_OUT);
+	hid_hw_request(hid, gaff->report, HID_REQ_SET_REPORT);
 
 	return 0;
 }
@@ -122,12 +120,12 @@ static int gaff_init(struct hid_device *hid)
 	gaff->report->field[0]->value[1] = 0x00;
 	gaff->report->field[0]->value[2] = 0x00;
 	gaff->report->field[0]->value[3] = 0x00;
-	usbhid_submit_report(hid, gaff->report, USB_DIR_OUT);
+	hid_hw_request(hid, gaff->report, HID_REQ_SET_REPORT);
 
 	gaff->report->field[0]->value[0] = 0xfa;
 	gaff->report->field[0]->value[1] = 0xfe;
 
-	usbhid_submit_report(hid, gaff->report, USB_DIR_OUT);
+	hid_hw_request(hid, gaff->report, HID_REQ_SET_REPORT);
 
 	hid_info(hid, "Force Feedback for GreenAsia 0x12 devices by Lukasz Lubojanski <lukasz@lubojanski.info>\n");
 
diff --git a/drivers/hid/hid-holtekff.c b/drivers/hid/hid-holtekff.c
index f34d118..9a8f051 100644
--- a/drivers/hid/hid-holtekff.c
+++ b/drivers/hid/hid-holtekff.c
@@ -27,12 +27,10 @@
 #include <linux/input.h>
 #include <linux/module.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>");
@@ -102,7 +100,7 @@ static void holtekff_send(struct holtekff_device *holtekff,
 
 	dbg_hid("sending %*ph\n", 7, data);
 
-	usbhid_submit_report(hid, holtekff->field->report, USB_DIR_OUT);
+	hid_hw_request(hid, holtekff->field->report, HID_REQ_SET_REPORT);
 }
 
 static int holtekff_play(struct input_dev *dev, void *data,
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index c438877..eae685d 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -158,6 +158,8 @@
 #define USB_VENDOR_ID_ATMEL		0x03eb
 #define USB_DEVICE_ID_ATMEL_MULTITOUCH	0x211c
 #define USB_DEVICE_ID_ATMEL_MXT_DIGITIZER	0x2118
+#define USB_VENDOR_ID_ATMEL_V_USB	0x16c0
+#define USB_DEVICE_ID_ATMEL_V_USB	0x05df
 
 #define USB_VENDOR_ID_AUREAL		0x0755
 #define USB_DEVICE_ID_AUREAL_W01RN	0x2626
@@ -557,9 +559,6 @@
 #define USB_VENDOR_ID_MADCATZ		0x0738
 #define USB_DEVICE_ID_MADCATZ_BEATPAD	0x4540
 
-#define USB_VENDOR_ID_MASTERKIT			0x16c0
-#define USB_DEVICE_ID_MASTERKIT_MA901RADIO	0x05df
-
 #define USB_VENDOR_ID_MCC		0x09db
 #define USB_DEVICE_ID_MCC_PMD1024LS	0x0076
 #define USB_DEVICE_ID_MCC_PMD1208LS	0x007a
@@ -614,6 +613,7 @@
 
 #define USB_VENDOR_ID_NINTENDO		0x057e
 #define USB_DEVICE_ID_NINTENDO_WIIMOTE	0x0306
+#define USB_DEVICE_ID_NINTENDO_WIIMOTE2	0x0330
 
 #define USB_VENDOR_ID_NOVATEK		0x0603
 #define USB_DEVICE_ID_NOVATEK_PCT	0x0600
@@ -693,8 +693,10 @@
 #define USB_VENDOR_ID_ROCCAT		0x1e7d
 #define USB_DEVICE_ID_ROCCAT_ARVO	0x30d4
 #define USB_DEVICE_ID_ROCCAT_ISKU	0x319c
+#define USB_DEVICE_ID_ROCCAT_ISKUFX	0x3264
 #define USB_DEVICE_ID_ROCCAT_KONE	0x2ced
 #define USB_DEVICE_ID_ROCCAT_KONEPLUS	0x2d51
+#define USB_DEVICE_ID_ROCCAT_KONEPURE	0x2dbe
 #define USB_DEVICE_ID_ROCCAT_KONEXTD	0x2e22
 #define USB_DEVICE_ID_ROCCAT_KOVAPLUS	0x2d50
 #define USB_DEVICE_ID_ROCCAT_LUA	0x2c2e
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 21b196c..945b815 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -1198,6 +1198,67 @@ static struct hid_input *hidinput_allocate(struct hid_device *hid)
 	return hidinput;
 }
 
+static bool hidinput_has_been_populated(struct hid_input *hidinput)
+{
+	int i;
+	unsigned long r = 0;
+
+	for (i = 0; i < BITS_TO_LONGS(EV_CNT); i++)
+		r |= hidinput->input->evbit[i];
+
+	for (i = 0; i < BITS_TO_LONGS(KEY_CNT); i++)
+		r |= hidinput->input->keybit[i];
+
+	for (i = 0; i < BITS_TO_LONGS(REL_CNT); i++)
+		r |= hidinput->input->relbit[i];
+
+	for (i = 0; i < BITS_TO_LONGS(ABS_CNT); i++)
+		r |= hidinput->input->absbit[i];
+
+	for (i = 0; i < BITS_TO_LONGS(MSC_CNT); i++)
+		r |= hidinput->input->mscbit[i];
+
+	for (i = 0; i < BITS_TO_LONGS(LED_CNT); i++)
+		r |= hidinput->input->ledbit[i];
+
+	for (i = 0; i < BITS_TO_LONGS(SND_CNT); i++)
+		r |= hidinput->input->sndbit[i];
+
+	for (i = 0; i < BITS_TO_LONGS(FF_CNT); i++)
+		r |= hidinput->input->ffbit[i];
+
+	for (i = 0; i < BITS_TO_LONGS(SW_CNT); i++)
+		r |= hidinput->input->swbit[i];
+
+	return !!r;
+}
+
+static void hidinput_cleanup_hidinput(struct hid_device *hid,
+		struct hid_input *hidinput)
+{
+	struct hid_report *report;
+	int i, k;
+
+	list_del(&hidinput->list);
+	input_free_device(hidinput->input);
+
+	for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) {
+		if (k == HID_OUTPUT_REPORT &&
+			hid->quirks & HID_QUIRK_SKIP_OUTPUT_REPORTS)
+			continue;
+
+		list_for_each_entry(report, &hid->report_enum[k].report_list,
+				    list) {
+
+			for (i = 0; i < report->maxfield; i++)
+				if (report->field[i]->hidinput == hidinput)
+					report->field[i]->hidinput = NULL;
+		}
+	}
+
+	kfree(hidinput);
+}
+
 /*
  * Register the input device; print a message.
  * Configure the input layer interface
@@ -1249,6 +1310,10 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
 					hidinput_configure_usage(hidinput, report->field[i],
 								 report->field[i]->usage + j);
 
+			if ((hid->quirks & HID_QUIRK_NO_EMPTY_INPUT) &&
+			    !hidinput_has_been_populated(hidinput))
+				continue;
+
 			if (hid->quirks & HID_QUIRK_MULTI_INPUT) {
 				/* This will leave hidinput NULL, so that it
 				 * allocates another one if we have more inputs on
@@ -1265,6 +1330,18 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
 		}
 	}
 
+	if (hidinput && (hid->quirks & HID_QUIRK_NO_EMPTY_INPUT) &&
+	    !hidinput_has_been_populated(hidinput)) {
+		/* no need to register an input device not populated */
+		hidinput_cleanup_hidinput(hid, hidinput);
+		hidinput = NULL;
+	}
+
+	if (list_empty(&hid->inputs)) {
+		hid_err(hid, "No inputs registered, leaving\n");
+		goto out_unwind;
+	}
+
 	if (hidinput) {
 		if (drv->input_configured)
 			drv->input_configured(hid, hidinput);
diff --git a/drivers/hid/hid-kye.c b/drivers/hid/hid-kye.c
index ef72dae..6af90db 100644
--- a/drivers/hid/hid-kye.c
+++ b/drivers/hid/hid-kye.c
@@ -16,8 +16,6 @@
 #include <linux/device.h>
 #include <linux/hid.h>
 #include <linux/module.h>
-#include <linux/usb.h>
-#include "usbhid/usbhid.h"
 
 #include "hid-ids.h"
 
@@ -361,7 +359,7 @@ static int kye_tablet_enable(struct hid_device *hdev)
 	value[4] = 0x00;
 	value[5] = 0x00;
 	value[6] = 0x00;
-	usbhid_submit_report(hdev, report, USB_DIR_OUT);
+	hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
 
 	return 0;
 }
diff --git a/drivers/hid/hid-lenovo-tpkbd.c b/drivers/hid/hid-lenovo-tpkbd.c
index 956c3b1..07837f5 100644
--- a/drivers/hid/hid-lenovo-tpkbd.c
+++ b/drivers/hid/hid-lenovo-tpkbd.c
@@ -68,7 +68,7 @@ static int tpkbd_features_set(struct hid_device *hdev)
 	report->field[2]->value[0] = data_pointer->sensitivity;
 	report->field[3]->value[0] = data_pointer->press_speed;
 
-	usbhid_submit_report(hdev, report, USB_DIR_OUT);
+	hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
 	return 0;
 }
 
@@ -228,8 +228,6 @@ static ssize_t pointer_press_speed_show(struct device *dev,
 	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
 	struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
 
-	data_pointer = hid_get_drvdata(hdev);
-
 	return snprintf(buf, PAGE_SIZE, "%u\n",
 		data_pointer->press_speed);
 }
@@ -332,7 +330,7 @@ static void tpkbd_led_brightness_set(struct led_classdev *led_cdev,
 	report = hdev->report_enum[HID_OUTPUT_REPORT].report_id_hash[3];
 	report->field[0]->value[0] = (data_pointer->led_state >> 0) & 1;
 	report->field[0]->value[1] = (data_pointer->led_state >> 1) & 1;
-	usbhid_submit_report(hdev, report, USB_DIR_OUT);
+	hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
 }
 
 static int tpkbd_probe_tp(struct hid_device *hdev)
diff --git a/drivers/hid/hid-lg2ff.c b/drivers/hid/hid-lg2ff.c
index 3c31bc6..b3cd150 100644
--- a/drivers/hid/hid-lg2ff.c
+++ b/drivers/hid/hid-lg2ff.c
@@ -23,10 +23,8 @@
 
 #include <linux/input.h>
 #include <linux/slab.h>
-#include <linux/usb.h>
 #include <linux/hid.h>
 
-#include "usbhid/usbhid.h"
 #include "hid-lg.h"
 
 struct lg2ff_device {
@@ -56,7 +54,7 @@ static int play_effect(struct input_dev *dev, void *data,
 		lg2ff->report->field[0]->value[4] = 0x00;
 	}
 
-	usbhid_submit_report(hid, lg2ff->report, USB_DIR_OUT);
+	hid_hw_request(hid, lg2ff->report, HID_REQ_SET_REPORT);
 	return 0;
 }
 
@@ -108,7 +106,7 @@ int lg2ff_init(struct hid_device *hid)
 	report->field[0]->value[5] = 0x00;
 	report->field[0]->value[6] = 0x00;
 
-	usbhid_submit_report(hid, report, USB_DIR_OUT);
+	hid_hw_request(hid, report, HID_REQ_SET_REPORT);
 
 	hid_info(hid, "Force feedback for Logitech RumblePad/Rumblepad 2 by Anssi Hannula <anssi.hannula@gmail.com>\n");
 
diff --git a/drivers/hid/hid-lg3ff.c b/drivers/hid/hid-lg3ff.c
index f98644c..e52f181 100644
--- a/drivers/hid/hid-lg3ff.c
+++ b/drivers/hid/hid-lg3ff.c
@@ -22,10 +22,8 @@
 
 
 #include <linux/input.h>
-#include <linux/usb.h>
 #include <linux/hid.h>
 
-#include "usbhid/usbhid.h"
 #include "hid-lg.h"
 
 /*
@@ -92,7 +90,7 @@ static int hid_lg3ff_play(struct input_dev *dev, void *data,
 		report->field[0]->value[1] = (unsigned char)(-x);
 		report->field[0]->value[31] = (unsigned char)(-y);
 
-		usbhid_submit_report(hid, report, USB_DIR_OUT);
+		hid_hw_request(hid, report, HID_REQ_SET_REPORT);
 		break;
 	}
 	return 0;
@@ -118,7 +116,7 @@ static void hid_lg3ff_set_autocenter(struct input_dev *dev, u16 magnitude)
 	report->field[0]->value[33] = 0x7F;
 	report->field[0]->value[34] = 0x7F;
 
-	usbhid_submit_report(hid, report, USB_DIR_OUT);
+	hid_hw_request(hid, report, HID_REQ_SET_REPORT);
 }
 
 
diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c
index 65a6ec8..7da40a1 100644
--- a/drivers/hid/hid-lg4ff.c
+++ b/drivers/hid/hid-lg4ff.c
@@ -202,7 +202,7 @@ static int hid_lg4ff_play(struct input_dev *dev, void *data, struct ff_effect *e
 		value[5] = 0x00;
 		value[6] = 0x00;
 
-		usbhid_submit_report(hid, report, USB_DIR_OUT);
+		hid_hw_request(hid, report, HID_REQ_SET_REPORT);
 		break;
 	}
 	return 0;
@@ -225,7 +225,7 @@ static void hid_lg4ff_set_autocenter_default(struct input_dev *dev, u16 magnitud
 	value[5] = 0x00;
 	value[6] = 0x00;
 
-	usbhid_submit_report(hid, report, USB_DIR_OUT);
+	hid_hw_request(hid, report, HID_REQ_SET_REPORT);
 }
 
 /* Sends autocentering command compatible with Formula Force EX */
@@ -245,7 +245,7 @@ static void hid_lg4ff_set_autocenter_ffex(struct input_dev *dev, u16 magnitude)
 	value[5] = 0x00;
 	value[6] = 0x00;
 
-	usbhid_submit_report(hid, report, USB_DIR_OUT);
+	hid_hw_request(hid, report, HID_REQ_SET_REPORT);
 }
 
 /* Sends command to set range compatible with G25/G27/Driving Force GT */
@@ -265,7 +265,7 @@ static void hid_lg4ff_set_range_g25(struct hid_device *hid, u16 range)
 	value[5] = 0x00;
 	value[6] = 0x00;
 
-	usbhid_submit_report(hid, report, USB_DIR_OUT);
+	hid_hw_request(hid, report, HID_REQ_SET_REPORT);
 }
 
 /* Sends commands to set range compatible with Driving Force Pro wheel */
@@ -294,7 +294,7 @@ static void hid_lg4ff_set_range_dfp(struct hid_device *hid, __u16 range)
 		report->field[0]->value[1] = 0x02;
 		full_range = 200;
 	}
-	usbhid_submit_report(hid, report, USB_DIR_OUT);
+	hid_hw_request(hid, report, HID_REQ_SET_REPORT);
 
 	/* Prepare "fine" limit command */
 	value[0] = 0x81;
@@ -306,7 +306,7 @@ static void hid_lg4ff_set_range_dfp(struct hid_device *hid, __u16 range)
 	value[6] = 0x00;
 
 	if (range == 200 || range == 900) {	/* Do not apply any fine limit */
-		usbhid_submit_report(hid, report, USB_DIR_OUT);
+		hid_hw_request(hid, report, HID_REQ_SET_REPORT);
 		return;
 	}
 
@@ -320,7 +320,7 @@ static void hid_lg4ff_set_range_dfp(struct hid_device *hid, __u16 range)
 	value[5] = (start_right & 0xe) << 4 | (start_left & 0xe);
 	value[6] = 0xff;
 
-	usbhid_submit_report(hid, report, USB_DIR_OUT);
+	hid_hw_request(hid, report, HID_REQ_SET_REPORT);
 }
 
 static void hid_lg4ff_switch_native(struct hid_device *hid, const struct lg4ff_native_cmd *cmd)
@@ -334,7 +334,7 @@ static void hid_lg4ff_switch_native(struct hid_device *hid, const struct lg4ff_n
 		for (i = 0; i < 7; i++)
 			report->field[0]->value[i] = cmd->cmd[j++];
 
-		usbhid_submit_report(hid, report, USB_DIR_OUT);
+		hid_hw_request(hid, report, HID_REQ_SET_REPORT);
 	}
 }
 
@@ -410,7 +410,7 @@ static void lg4ff_set_leds(struct hid_device *hid, __u8 leds)
 	value[4] = 0x00;
 	value[5] = 0x00;
 	value[6] = 0x00;
-	usbhid_submit_report(hid, report, USB_DIR_OUT);
+	hid_hw_request(hid, report, HID_REQ_SET_REPORT);
 }
 
 static void lg4ff_led_set_brightness(struct led_classdev *led_cdev,
diff --git a/drivers/hid/hid-lgff.c b/drivers/hid/hid-lgff.c
index 27bc54f..d7ea8c8 100644
--- a/drivers/hid/hid-lgff.c
+++ b/drivers/hid/hid-lgff.c
@@ -30,10 +30,8 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/input.h>
-#include <linux/usb.h>
 #include <linux/hid.h>
 
-#include "usbhid/usbhid.h"
 #include "hid-lg.h"
 
 struct dev_type {
@@ -89,7 +87,7 @@ static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *ef
 		report->field[0]->value[2] = x;
 		report->field[0]->value[3] = y;
 		dbg_hid("(x, y)=(%04x, %04x)\n", x, y);
-		usbhid_submit_report(hid, report, USB_DIR_OUT);
+		hid_hw_request(hid, report, HID_REQ_SET_REPORT);
 		break;
 
 	case FF_RUMBLE:
@@ -104,7 +102,7 @@ static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *ef
 		report->field[0]->value[2] = left;
 		report->field[0]->value[3] = right;
 		dbg_hid("(left, right)=(%04x, %04x)\n", left, right);
-		usbhid_submit_report(hid, report, USB_DIR_OUT);
+		hid_hw_request(hid, report, HID_REQ_SET_REPORT);
 		break;
 	}
 	return 0;
@@ -124,7 +122,7 @@ static void hid_lgff_set_autocenter(struct input_dev *dev, u16 magnitude)
 	*value++ = 0x80;
 	*value++ = 0x00;
 	*value = 0x00;
-	usbhid_submit_report(hid, report, USB_DIR_OUT);
+	hid_hw_request(hid, report, HID_REQ_SET_REPORT);
 }
 
 int lgff_init(struct hid_device* hid)
diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c
index 8758f38c..5207591a 100644
--- a/drivers/hid/hid-logitech-dj.c
+++ b/drivers/hid/hid-logitech-dj.c
@@ -27,7 +27,6 @@
 #include <linux/module.h>
 #include <linux/usb.h>
 #include <asm/unaligned.h>
-#include "usbhid/usbhid.h"
 #include "hid-ids.h"
 #include "hid-logitech-dj.h"
 
@@ -193,7 +192,6 @@ static struct hid_ll_driver logi_dj_ll_driver;
 static int logi_dj_output_hidraw_report(struct hid_device *hid, u8 * buf,
 					size_t count,
 					unsigned char report_type);
-static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev);
 
 static void logi_dj_recv_destroy_djhid_device(struct dj_receiver_dev *djrcv_dev,
 						struct dj_report *dj_report)
@@ -234,7 +232,6 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev,
 	if (dj_report->report_params[DEVICE_PAIRED_PARAM_SPFUNCTION] &
 	    SPFUNCTION_DEVICE_LIST_EMPTY) {
 		dbg_hid("%s: device list is empty\n", __func__);
-		djrcv_dev->querying_devices = false;
 		return;
 	}
 
@@ -245,12 +242,6 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev,
 		return;
 	}
 
-	if (djrcv_dev->paired_dj_devices[dj_report->device_index]) {
-		/* The device is already known. No need to reallocate it. */
-		dbg_hid("%s: device is already known\n", __func__);
-		return;
-	}
-
 	dj_hiddev = hid_allocate_device();
 	if (IS_ERR(dj_hiddev)) {
 		dev_err(&djrcv_hdev->dev, "%s: hid_allocate_device failed\n",
@@ -314,7 +305,6 @@ static void delayedwork_callback(struct work_struct *work)
 	struct dj_report dj_report;
 	unsigned long flags;
 	int count;
-	int retval;
 
 	dbg_hid("%s\n", __func__);
 
@@ -347,25 +337,6 @@ static void delayedwork_callback(struct work_struct *work)
 		logi_dj_recv_destroy_djhid_device(djrcv_dev, &dj_report);
 		break;
 	default:
-	/* A normal report (i. e. not belonging to a pair/unpair notification)
-	 * arriving here, means that the report arrived but we did not have a
-	 * paired dj_device associated to the report's device_index, this
-	 * means that the original "device paired" notification corresponding
-	 * to this dj_device never arrived to this driver. The reason is that
-	 * hid-core discards all packets coming from a device while probe() is
-	 * executing. */
-	if (!djrcv_dev->paired_dj_devices[dj_report.device_index]) {
-		/* ok, we don't know the device, just re-ask the
-		 * receiver for the list of connected devices. */
-		retval = logi_dj_recv_query_paired_devices(djrcv_dev);
-		if (!retval) {
-			/* everything went fine, so just leave */
-			break;
-		}
-		dev_err(&djrcv_dev->hdev->dev,
-			"%s:logi_dj_recv_query_paired_devices "
-			"error:%d\n", __func__, retval);
-		}
 		dbg_hid("%s: unexpected report type\n", __func__);
 	}
 }
@@ -396,12 +367,6 @@ static void logi_dj_recv_forward_null_report(struct dj_receiver_dev *djrcv_dev,
 	if (!djdev) {
 		dbg_hid("djrcv_dev->paired_dj_devices[dj_report->device_index]"
 			" is NULL, index %d\n", dj_report->device_index);
-		kfifo_in(&djrcv_dev->notif_fifo, dj_report, sizeof(struct dj_report));
-
-		if (schedule_work(&djrcv_dev->work) == 0) {
-			dbg_hid("%s: did not schedule the work item, was already "
-			"queued\n", __func__);
-		}
 		return;
 	}
 
@@ -432,12 +397,6 @@ static void logi_dj_recv_forward_report(struct dj_receiver_dev *djrcv_dev,
 	if (dj_device == NULL) {
 		dbg_hid("djrcv_dev->paired_dj_devices[dj_report->device_index]"
 			" is NULL, index %d\n", dj_report->device_index);
-		kfifo_in(&djrcv_dev->notif_fifo, dj_report, sizeof(struct dj_report));
-
-		if (schedule_work(&djrcv_dev->work) == 0) {
-			dbg_hid("%s: did not schedule the work item, was already "
-			"queued\n", __func__);
-		}
 		return;
 	}
 
@@ -475,7 +434,7 @@ static int logi_dj_recv_send_report(struct dj_receiver_dev *djrcv_dev,
 	for (i = 0; i < report->field[0]->report_count; i++)
 		report->field[0]->value[i] = data[i];
 
-	usbhid_submit_report(hdev, report, USB_DIR_OUT);
+	hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
 
 	return 0;
 }
@@ -485,10 +444,6 @@ static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev)
 	struct dj_report *dj_report;
 	int retval;
 
-	/* no need to protect djrcv_dev->querying_devices */
-	if (djrcv_dev->querying_devices)
-		return 0;
-
 	dj_report = kzalloc(sizeof(struct dj_report), GFP_KERNEL);
 	if (!dj_report)
 		return -ENOMEM;
@@ -500,7 +455,6 @@ static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev)
 	return retval;
 }
 
-
 static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev,
 					  unsigned timeout)
 {
@@ -644,7 +598,7 @@ static int logi_dj_ll_input_event(struct input_dev *dev, unsigned int type,
 	hid_set_field(report->field[0], 1, REPORT_TYPE_LEDS);
 	hid_set_field(report->field[0], 2, data[1]);
 
-	usbhid_submit_report(dj_rcv_hiddev, report, USB_DIR_OUT);
+	hid_hw_request(dj_rcv_hiddev, report, HID_REQ_SET_REPORT);
 
 	return 0;
 
@@ -809,6 +763,9 @@ static int logi_dj_probe(struct hid_device *hdev,
 		goto llopen_failed;
 	}
 
+	/* Allow incoming packets to arrive: */
+	hid_device_io_start(hdev);
+
 	retval = logi_dj_recv_query_paired_devices(djrcv_dev);
 	if (retval < 0) {
 		dev_err(&hdev->dev, "%s:logi_dj_recv_query_paired_devices "
diff --git a/drivers/hid/hid-logitech-dj.h b/drivers/hid/hid-logitech-dj.h
index 4a40003..fd28a5e 100644
--- a/drivers/hid/hid-logitech-dj.h
+++ b/drivers/hid/hid-logitech-dj.h
@@ -101,7 +101,6 @@ struct dj_receiver_dev {
 	struct work_struct work;
 	struct kfifo notif_fifo;
 	spinlock_t lock;
-	bool querying_devices;
 };
 
 struct dj_device {
diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c
index f7f113b..5bc3734 100644
--- a/drivers/hid/hid-magicmouse.c
+++ b/drivers/hid/hid-magicmouse.c
@@ -19,7 +19,6 @@
 #include <linux/input/mt.h>
 #include <linux/module.h>
 #include <linux/slab.h>
-#include <linux/usb.h>
 
 #include "hid-ids.h"
 
@@ -462,6 +461,21 @@ static int magicmouse_input_mapping(struct hid_device *hdev,
 	return 0;
 }
 
+static void magicmouse_input_configured(struct hid_device *hdev,
+		struct hid_input *hi)
+
+{
+	struct magicmouse_sc *msc = hid_get_drvdata(hdev);
+
+	int ret = magicmouse_setup_input(msc->input, hdev);
+	if (ret) {
+		hid_err(hdev, "magicmouse setup input failed (%d)\n", ret);
+		/* clean msc->input to notify probe() of the failure */
+		msc->input = NULL;
+	}
+}
+
+
 static int magicmouse_probe(struct hid_device *hdev,
 	const struct hid_device_id *id)
 {
@@ -493,15 +507,10 @@ static int magicmouse_probe(struct hid_device *hdev,
 		goto err_free;
 	}
 
-	/* We do this after hid-input is done parsing reports so that
-	 * hid-input uses the most natural button and axis IDs.
-	 */
-	if (msc->input) {
-		ret = magicmouse_setup_input(msc->input, hdev);
-		if (ret) {
-			hid_err(hdev, "magicmouse setup input failed (%d)\n", ret);
-			goto err_stop_hw;
-		}
+	if (!msc->input) {
+		hid_err(hdev, "magicmouse input not registered\n");
+		ret = -ENOMEM;
+		goto err_stop_hw;
 	}
 
 	if (id->product == USB_DEVICE_ID_APPLE_MAGICMOUSE)
@@ -568,6 +577,7 @@ static struct hid_driver magicmouse_driver = {
 	.remove = magicmouse_remove,
 	.raw_event = magicmouse_raw_event,
 	.input_mapping = magicmouse_input_mapping,
+	.input_configured = magicmouse_input_configured,
 };
 module_hid_driver(magicmouse_driver);
 
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 82e9211..dc3ae5c 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -2,8 +2,9 @@
  *  HID driver for multitouch panels
  *
  *  Copyright (c) 2010-2012 Stephane Chatty <chatty@enac.fr>
- *  Copyright (c) 2010-2012 Benjamin Tissoires <benjamin.tissoires@gmail.com>
+ *  Copyright (c) 2010-2013 Benjamin Tissoires <benjamin.tissoires@gmail.com>
  *  Copyright (c) 2010-2012 Ecole Nationale de l'Aviation Civile, France
+ *  Copyright (c) 2012-2013 Red Hat, Inc
  *
  *  This code is partly based on hid-egalax.c:
  *
@@ -26,13 +27,24 @@
  * any later version.
  */
 
+/*
+ * This driver is regularly tested thanks to the tool hid-test[1].
+ * This tool relies on hid-replay[2] and a database of hid devices[3].
+ * Please run these regression tests before patching this module so that
+ * your patch won't break existing known devices.
+ *
+ * [1] https://github.com/bentiss/hid-test
+ * [2] https://github.com/bentiss/hid-replay
+ * [3] https://github.com/bentiss/hid-devices
+ */
+
 #include <linux/device.h>
 #include <linux/hid.h>
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/usb.h>
 #include <linux/input/mt.h>
-#include "usbhid/usbhid.h"
+#include <linux/string.h>
 
 
 MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>");
@@ -86,9 +98,9 @@ struct mt_device {
 					   multitouch fields */
 	int cc_index;	/* contact count field index in the report */
 	int cc_value_index;	/* contact count value index in the field */
-	unsigned last_field_index;	/* last field index of the report */
 	unsigned last_slot_field;	/* the last field of a slot */
 	unsigned mt_report_id;	/* the report ID of the multitouch device */
+	unsigned pen_report_id;	/* the report ID of the pen device */
 	__s8 inputmode;		/* InputMode HID feature, -1 if non-existent */
 	__s8 inputmode_index;	/* InputMode HID feature index in the report */
 	__s8 maxcontact_report_id;	/* Maximum Contact Number HID feature,
@@ -104,6 +116,9 @@ struct mt_device {
 	unsigned mt_flags;	/* flags to pass to input-mt */
 };
 
+static void mt_post_parse_default_settings(struct mt_device *td);
+static void mt_post_parse(struct mt_device *td);
+
 /* classes of device behavior */
 #define MT_CLS_DEFAULT				0x0001
 
@@ -246,6 +261,14 @@ static struct mt_class mt_classes[] = {
 	{ }
 };
 
+static void mt_free_input_name(struct hid_input *hi)
+{
+	struct hid_device *hdev = hi->report->device;
+
+	if (hi->input->name != hdev->name)
+		kfree(hi->input->name);
+}
+
 static ssize_t mt_show_quirks(struct device *dev,
 			   struct device_attribute *attr,
 			   char *buf)
@@ -354,7 +377,53 @@ static void mt_store_field(struct hid_usage *usage, struct mt_device *td,
 	f->usages[f->length++] = usage->hid;
 }
 
-static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+static int mt_pen_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+		struct hid_field *field, struct hid_usage *usage,
+		unsigned long **bit, int *max)
+{
+	struct mt_device *td = hid_get_drvdata(hdev);
+
+	td->pen_report_id = field->report->id;
+
+	return 0;
+}
+
+static int mt_pen_input_mapped(struct hid_device *hdev, struct hid_input *hi,
+		struct hid_field *field, struct hid_usage *usage,
+		unsigned long **bit, int *max)
+{
+	return 0;
+}
+
+static int mt_pen_event(struct hid_device *hid, struct hid_field *field,
+				struct hid_usage *usage, __s32 value)
+{
+	/* let hid-input handle it */
+	return 0;
+}
+
+static void mt_pen_report(struct hid_device *hid, struct hid_report *report)
+{
+	struct hid_field *field = report->field[0];
+
+	input_sync(field->hidinput->input);
+}
+
+static void mt_pen_input_configured(struct hid_device *hdev,
+					struct hid_input *hi)
+{
+	char *name = kzalloc(strlen(hi->input->name) + 5, GFP_KERNEL);
+	if (name) {
+		sprintf(name, "%s Pen", hi->input->name);
+		mt_free_input_name(hi);
+		hi->input->name = name;
+	}
+
+	/* force BTN_STYLUS to allow tablet matching in udev */
+	__set_bit(BTN_STYLUS, hi->input->keybit);
+}
+
+static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
 		struct hid_field *field, struct hid_usage *usage,
 		unsigned long **bit, int *max)
 {
@@ -363,13 +432,8 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
 	int code;
 	struct hid_usage *prev_usage = NULL;
 
-	/* Only map fields from TouchScreen or TouchPad collections.
-	* We need to ignore fields that belong to other collections
-	* such as Mouse that might have the same GenericDesktop usages. */
 	if (field->application == HID_DG_TOUCHSCREEN)
 		td->mt_flags |= INPUT_MT_DIRECT;
-	else if (field->application != HID_DG_TOUCHPAD)
-		return 0;
 
 	/*
 	 * Model touchscreens providing buttons as touchpads.
@@ -378,12 +442,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
 	    (usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON)
 		td->mt_flags |= INPUT_MT_POINTER;
 
-	/* eGalax devices provide a Digitizer.Stylus input which overrides
-	 * the correct Digitizers.Finger X/Y ranges.
-	 * Let's just ignore this input. */
-	if (field->physical == HID_DG_STYLUS)
-		return -1;
-
 	if (usage->usage_index)
 		prev_usage = &field->usage[usage->usage_index - 1];
 
@@ -405,7 +463,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
 			}
 
 			mt_store_field(usage, td, hi);
-			td->last_field_index = field->index;
 			return 1;
 		case HID_GD_Y:
 			if (prev_usage && (prev_usage->hid == usage->hid)) {
@@ -421,7 +478,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
 			}
 
 			mt_store_field(usage, td, hi);
-			td->last_field_index = field->index;
 			return 1;
 		}
 		return 0;
@@ -436,21 +492,17 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
 					ABS_MT_DISTANCE, 0, 1, 0, 0);
 			}
 			mt_store_field(usage, td, hi);
-			td->last_field_index = field->index;
 			return 1;
 		case HID_DG_CONFIDENCE:
 			mt_store_field(usage, td, hi);
-			td->last_field_index = field->index;
 			return 1;
 		case HID_DG_TIPSWITCH:
 			hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
 			input_set_capability(hi->input, EV_KEY, BTN_TOUCH);
 			mt_store_field(usage, td, hi);
-			td->last_field_index = field->index;
 			return 1;
 		case HID_DG_CONTACTID:
 			mt_store_field(usage, td, hi);
-			td->last_field_index = field->index;
 			td->touches_by_report++;
 			td->mt_report_id = field->report->id;
 			return 1;
@@ -461,7 +513,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
 				set_abs(hi->input, ABS_MT_TOUCH_MAJOR, field,
 					cls->sn_width);
 			mt_store_field(usage, td, hi);
-			td->last_field_index = field->index;
 			return 1;
 		case HID_DG_HEIGHT:
 			hid_map_usage(hi, usage, bit, max,
@@ -473,7 +524,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
 					ABS_MT_ORIENTATION, 0, 1, 0, 0);
 			}
 			mt_store_field(usage, td, hi);
-			td->last_field_index = field->index;
 			return 1;
 		case HID_DG_TIPPRESSURE:
 			hid_map_usage(hi, usage, bit, max,
@@ -481,17 +531,14 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
 			set_abs(hi->input, ABS_MT_PRESSURE, field,
 				cls->sn_pressure);
 			mt_store_field(usage, td, hi);
-			td->last_field_index = field->index;
 			return 1;
 		case HID_DG_CONTACTCOUNT:
 			td->cc_index = field->index;
 			td->cc_value_index = usage->usage_index;
-			td->last_field_index = field->index;
 			return 1;
 		case HID_DG_CONTACTMAX:
 			/* we don't set td->last_slot_field as contactcount and
 			 * contact max are global to the report */
-			td->last_field_index = field->index;
 			return -1;
 		case HID_DG_TOUCH:
 			/* Legacy devices use TIPSWITCH and not TOUCH.
@@ -515,7 +562,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
 	return 0;
 }
 
-static int mt_input_mapped(struct hid_device *hdev, struct hid_input *hi,
+static int mt_touch_input_mapped(struct hid_device *hdev, struct hid_input *hi,
 		struct hid_field *field, struct hid_usage *usage,
 		unsigned long **bit, int *max)
 {
@@ -606,7 +653,7 @@ static void mt_sync_frame(struct mt_device *td, struct input_dev *input)
 	td->num_received = 0;
 }
 
-static int mt_event(struct hid_device *hid, struct hid_field *field,
+static int mt_touch_event(struct hid_device *hid, struct hid_field *field,
 				struct hid_usage *usage, __s32 value)
 {
 	/* we will handle the hidinput part later, now remains hiddev */
@@ -680,29 +727,19 @@ static void mt_process_mt_event(struct hid_device *hid, struct hid_field *field,
 		if (usage->usage_index + 1 == field->report_count) {
 			/* we only take into account the last report. */
 			if (usage->hid == td->last_slot_field)
-				mt_complete_slot(td, input);
-
-			if (field->index == td->last_field_index
-				&& td->num_received >= td->num_expected)
-				mt_sync_frame(td, field->hidinput->input);
+				mt_complete_slot(td, field->hidinput->input);
 		}
 
 	}
 }
 
-static void mt_report(struct hid_device *hid, struct hid_report *report)
+static void mt_touch_report(struct hid_device *hid, struct hid_report *report)
 {
 	struct mt_device *td = hid_get_drvdata(hid);
 	struct hid_field *field;
 	unsigned count;
 	int r, n;
 
-	if (report->id != td->mt_report_id)
-		return;
-
-	if (!(hid->claimed & HID_CLAIMED_INPUT))
-		return;
-
 	/*
 	 * Includes multi-packet support where subsequent
 	 * packets are sent with zero contactcount.
@@ -725,6 +762,91 @@ static void mt_report(struct hid_device *hid, struct hid_report *report)
 			mt_process_mt_event(hid, field, &field->usage[n],
 					field->value[n]);
 	}
+
+	if (td->num_received >= td->num_expected)
+		mt_sync_frame(td, report->field[0]->hidinput->input);
+}
+
+static void mt_touch_input_configured(struct hid_device *hdev,
+					struct hid_input *hi)
+{
+	struct mt_device *td = hid_get_drvdata(hdev);
+	struct mt_class *cls = &td->mtclass;
+	struct input_dev *input = hi->input;
+
+	if (!td->maxcontacts)
+		td->maxcontacts = MT_DEFAULT_MAXCONTACT;
+
+	mt_post_parse(td);
+	if (td->serial_maybe)
+		mt_post_parse_default_settings(td);
+
+	if (cls->is_indirect)
+		td->mt_flags |= INPUT_MT_POINTER;
+
+	if (cls->quirks & MT_QUIRK_NOT_SEEN_MEANS_UP)
+		td->mt_flags |= INPUT_MT_DROP_UNUSED;
+
+	input_mt_init_slots(input, td->maxcontacts, td->mt_flags);
+
+	td->mt_flags = 0;
+}
+
+static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+		struct hid_field *field, struct hid_usage *usage,
+		unsigned long **bit, int *max)
+{
+	/* Only map fields from TouchScreen or TouchPad collections.
+	* We need to ignore fields that belong to other collections
+	* such as Mouse that might have the same GenericDesktop usages. */
+	if (field->application != HID_DG_TOUCHSCREEN &&
+	    field->application != HID_DG_PEN &&
+	    field->application != HID_DG_TOUCHPAD)
+		return -1;
+
+	if (field->physical == HID_DG_STYLUS)
+		return mt_pen_input_mapping(hdev, hi, field, usage, bit, max);
+
+	return mt_touch_input_mapping(hdev, hi, field, usage, bit, max);
+}
+
+static int mt_input_mapped(struct hid_device *hdev, struct hid_input *hi,
+		struct hid_field *field, struct hid_usage *usage,
+		unsigned long **bit, int *max)
+{
+	if (field->physical == HID_DG_STYLUS)
+		return mt_pen_input_mapped(hdev, hi, field, usage, bit, max);
+
+	return mt_touch_input_mapped(hdev, hi, field, usage, bit, max);
+}
+
+static int mt_event(struct hid_device *hid, struct hid_field *field,
+				struct hid_usage *usage, __s32 value)
+{
+	struct mt_device *td = hid_get_drvdata(hid);
+
+	if (field->report->id == td->mt_report_id)
+		return mt_touch_event(hid, field, usage, value);
+
+	if (field->report->id == td->pen_report_id)
+		return mt_pen_event(hid, field, usage, value);
+
+	/* ignore other reports */
+	return 1;
+}
+
+static void mt_report(struct hid_device *hid, struct hid_report *report)
+{
+	struct mt_device *td = hid_get_drvdata(hid);
+
+	if (!(hid->claimed & HID_CLAIMED_INPUT))
+		return;
+
+	if (report->id == td->mt_report_id)
+		mt_touch_report(hid, report);
+
+	if (report->id == td->pen_report_id)
+		mt_pen_report(hid, report);
 }
 
 static void mt_set_input_mode(struct hid_device *hdev)
@@ -740,7 +862,7 @@ static void mt_set_input_mode(struct hid_device *hdev)
 	r = re->report_id_hash[td->inputmode];
 	if (r) {
 		r->field[0]->value[td->inputmode_index] = 0x02;
-		usbhid_submit_report(hdev, r, USB_DIR_OUT);
+		hid_hw_request(hdev, r, HID_REQ_SET_REPORT);
 	}
 }
 
@@ -765,7 +887,7 @@ static void mt_set_maxcontacts(struct hid_device *hdev)
 		max = min(fieldmax, max);
 		if (r->field[0]->value[0] != max) {
 			r->field[0]->value[0] = max;
-			usbhid_submit_report(hdev, r, USB_DIR_OUT);
+			hid_hw_request(hdev, r, HID_REQ_SET_REPORT);
 		}
 	}
 }
@@ -801,32 +923,18 @@ static void mt_post_parse(struct mt_device *td)
 }
 
 static void mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
-
 {
 	struct mt_device *td = hid_get_drvdata(hdev);
-	struct mt_class *cls = &td->mtclass;
-	struct input_dev *input = hi->input;
+	char *name = kstrdup(hdev->name, GFP_KERNEL);
 
-	/* Only initialize slots for MT input devices */
-	if (!test_bit(ABS_MT_POSITION_X, input->absbit))
-		return;
+	if (name)
+		hi->input->name = name;
 
-	if (!td->maxcontacts)
-		td->maxcontacts = MT_DEFAULT_MAXCONTACT;
+	if (hi->report->id == td->mt_report_id)
+		mt_touch_input_configured(hdev, hi);
 
-	mt_post_parse(td);
-	if (td->serial_maybe)
-		mt_post_parse_default_settings(td);
-
-	if (cls->is_indirect)
-		td->mt_flags |= INPUT_MT_POINTER;
-
-	if (cls->quirks & MT_QUIRK_NOT_SEEN_MEANS_UP)
-		td->mt_flags |= INPUT_MT_DROP_UNUSED;
-
-	input_mt_init_slots(input, td->maxcontacts, td->mt_flags);
-
-	td->mt_flags = 0;
+	if (hi->report->id == td->pen_report_id)
+		mt_pen_input_configured(hdev, hi);
 }
 
 static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
@@ -834,6 +942,7 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
 	int ret, i;
 	struct mt_device *td;
 	struct mt_class *mtclass = mt_classes; /* MT_CLS_DEFAULT */
+	struct hid_input *hi;
 
 	for (i = 0; mt_classes[i].name ; i++) {
 		if (id->driver_data == mt_classes[i].name) {
@@ -847,6 +956,14 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
 	 */
 	hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC;
 
+	/*
+	 * This allows the driver to handle different input sensors
+	 * that emits events through different reports on the same HID
+	 * device.
+	 */
+	hdev->quirks |= HID_QUIRK_MULTI_INPUT;
+	hdev->quirks |= HID_QUIRK_NO_EMPTY_INPUT;
+
 	td = kzalloc(sizeof(struct mt_device), GFP_KERNEL);
 	if (!td) {
 		dev_err(&hdev->dev, "cannot allocate multitouch data\n");
@@ -856,6 +973,8 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
 	td->inputmode = -1;
 	td->maxcontact_report_id = -1;
 	td->cc_index = -1;
+	td->mt_report_id = -1;
+	td->pen_report_id = -1;
 	hid_set_drvdata(hdev, td);
 
 	td->fields = kzalloc(sizeof(struct mt_fields), GFP_KERNEL);
@@ -874,7 +993,7 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
 
 	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
 	if (ret)
-		goto fail;
+		goto hid_fail;
 
 	ret = sysfs_create_group(&hdev->dev.kobj, &mt_attribute_group);
 
@@ -886,6 +1005,9 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
 
 	return 0;
 
+hid_fail:
+	list_for_each_entry(hi, &hdev->inputs, list)
+		mt_free_input_name(hi);
 fail:
 	kfree(td->fields);
 	kfree(td);
@@ -902,26 +1024,11 @@ static int mt_reset_resume(struct hid_device *hdev)
 
 static int mt_resume(struct hid_device *hdev)
 {
-	struct usb_interface *intf;
-	struct usb_host_interface *interface;
-	struct usb_device *dev;
-
-	if (hdev->bus != BUS_USB)
-		return 0;
-
-	intf = to_usb_interface(hdev->dev.parent);
-	interface = intf->cur_altsetting;
-	dev = hid_to_usb_dev(hdev);
-
 	/* Some Elan legacy devices require SET_IDLE to be set on resume.
 	 * It should be safe to send it to other devices too.
 	 * Tested on 3M, Stantum, Cypress, Zytronic, eGalax, and Elan panels. */
 
-	usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-			HID_REQ_SET_IDLE,
-			USB_TYPE_CLASS | USB_RECIP_INTERFACE,
-			0, interface->desc.bInterfaceNumber,
-			NULL, 0, USB_CTRL_SET_TIMEOUT);
+	hid_hw_idle(hdev, 0, 0, HID_REQ_SET_IDLE);
 
 	return 0;
 }
@@ -930,8 +1037,14 @@ static int mt_resume(struct hid_device *hdev)
 static void mt_remove(struct hid_device *hdev)
 {
 	struct mt_device *td = hid_get_drvdata(hdev);
+	struct hid_input *hi;
+
 	sysfs_remove_group(&hdev->dev.kobj, &mt_attribute_group);
 	hid_hw_stop(hdev);
+
+	list_for_each_entry(hi, &hdev->inputs, list)
+		mt_free_input_name(hi);
+
 	kfree(td);
 	hid_set_drvdata(hdev, NULL);
 }
diff --git a/drivers/hid/hid-ntrig.c b/drivers/hid/hid-ntrig.c
index 7757e82..ef95102 100644
--- a/drivers/hid/hid-ntrig.c
+++ b/drivers/hid/hid-ntrig.c
@@ -118,8 +118,8 @@ static inline int ntrig_get_mode(struct hid_device *hdev)
 	if (!report)
 		return -EINVAL;
 
-	usbhid_submit_report(hdev, report, USB_DIR_IN);
-	usbhid_wait_io(hdev);
+	hid_hw_request(hdev, report, HID_REQ_GET_REPORT);
+	hid_hw_wait(hdev);
 	return (int)report->field[0]->value[0];
 }
 
@@ -137,7 +137,7 @@ static inline void ntrig_set_mode(struct hid_device *hdev, const int mode)
 	if (!report)
 		return;
 
-	usbhid_submit_report(hdev, report, USB_DIR_IN);
+	hid_hw_request(hdev, report, HID_REQ_GET_REPORT);
 }
 
 static void ntrig_report_version(struct hid_device *hdev)
@@ -937,8 +937,8 @@ static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id)
 	if (report) {
 		/* Let the device settle to ensure the wakeup message gets
 		 * through */
-		usbhid_wait_io(hdev);
-		usbhid_submit_report(hdev, report, USB_DIR_IN);
+		hid_hw_wait(hdev);
+		hid_hw_request(hdev, report, HID_REQ_GET_REPORT);
 
 		/*
 		 * Sanity check: if the current mode is invalid reset it to
diff --git a/drivers/hid/hid-picolcd.h b/drivers/hid/hid-picolcd.h
index 020cef6..e56d847 100644
--- a/drivers/hid/hid-picolcd.h
+++ b/drivers/hid/hid-picolcd.h
@@ -142,10 +142,10 @@ struct hid_report *picolcd_report(int id, struct hid_device *hdev, int dir);
 #ifdef CONFIG_DEBUG_FS
 void picolcd_debug_out_report(struct picolcd_data *data,
 		struct hid_device *hdev, struct hid_report *report);
-#define usbhid_submit_report(a, b, c) \
+#define hid_hw_request(a, b, c) \
 	do { \
 		picolcd_debug_out_report(hid_get_drvdata(a), a, b); \
-		usbhid_submit_report(a, b, c); \
+		hid_hw_request(a, b, c); \
 	} while (0)
 
 void picolcd_debug_raw_event(struct picolcd_data *data,
@@ -302,7 +302,7 @@ static inline int picolcd_init_cir(struct picolcd_data *data, struct hid_report
 static inline void picolcd_exit_cir(struct picolcd_data *data)
 {
 }
-#endif /* CONFIG_HID_PICOLCD_LIRC */
+#endif /* CONFIG_HID_PICOLCD_CIR */
 
 int picolcd_reset(struct hid_device *hdev);
 struct picolcd_pending *picolcd_send_and_wait(struct hid_device *hdev,
diff --git a/drivers/hid/hid-picolcd_backlight.c b/drivers/hid/hid-picolcd_backlight.c
index b91f309..a32c5f8 100644
--- a/drivers/hid/hid-picolcd_backlight.c
+++ b/drivers/hid/hid-picolcd_backlight.c
@@ -18,8 +18,6 @@
  ***************************************************************************/
 
 #include <linux/hid.h>
-#include "usbhid/usbhid.h"
-#include <linux/usb.h>
 
 #include <linux/fb.h>
 #include <linux/backlight.h>
@@ -46,7 +44,7 @@ static int picolcd_set_brightness(struct backlight_device *bdev)
 	spin_lock_irqsave(&data->lock, flags);
 	hid_set_field(report->field[0], 0, data->lcd_power == FB_BLANK_UNBLANK ? data->lcd_brightness : 0);
 	if (!(data->status & PICOLCD_FAILED))
-		usbhid_submit_report(data->hdev, report, USB_DIR_OUT);
+		hid_hw_request(data->hdev, report, HID_REQ_SET_REPORT);
 	spin_unlock_irqrestore(&data->lock, flags);
 	return 0;
 }
diff --git a/drivers/hid/hid-picolcd_cir.c b/drivers/hid/hid-picolcd_cir.c
index a79e95b..e346038 100644
--- a/drivers/hid/hid-picolcd_cir.c
+++ b/drivers/hid/hid-picolcd_cir.c
@@ -21,8 +21,6 @@
 #include <linux/hid-debug.h>
 #include <linux/input.h>
 #include "hid-ids.h"
-#include "usbhid/usbhid.h"
-#include <linux/usb.h>
 
 #include <linux/fb.h>
 #include <linux/vmalloc.h>
diff --git a/drivers/hid/hid-picolcd_core.c b/drivers/hid/hid-picolcd_core.c
index 31cd93f..b48092d 100644
--- a/drivers/hid/hid-picolcd_core.c
+++ b/drivers/hid/hid-picolcd_core.c
@@ -21,8 +21,6 @@
 #include <linux/hid-debug.h>
 #include <linux/input.h>
 #include "hid-ids.h"
-#include "usbhid/usbhid.h"
-#include <linux/usb.h>
 
 #include <linux/fb.h>
 #include <linux/vmalloc.h>
@@ -110,7 +108,7 @@ struct picolcd_pending *picolcd_send_and_wait(struct hid_device *hdev,
 		work = NULL;
 	} else {
 		data->pending = work;
-		usbhid_submit_report(data->hdev, report, USB_DIR_OUT);
+		hid_hw_request(data->hdev, report, HID_REQ_SET_REPORT);
 		spin_unlock_irqrestore(&data->lock, flags);
 		wait_for_completion_interruptible_timeout(&work->ready, HZ*2);
 		spin_lock_irqsave(&data->lock, flags);
@@ -244,7 +242,7 @@ int picolcd_reset(struct hid_device *hdev)
 		spin_unlock_irqrestore(&data->lock, flags);
 		return -ENODEV;
 	}
-	usbhid_submit_report(hdev, report, USB_DIR_OUT);
+	hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
 	spin_unlock_irqrestore(&data->lock, flags);
 
 	error = picolcd_check_version(hdev);
@@ -303,7 +301,7 @@ static ssize_t picolcd_operation_mode_store(struct device *dev,
 	spin_lock_irqsave(&data->lock, flags);
 	hid_set_field(report->field[0], 0, timeout & 0xff);
 	hid_set_field(report->field[0], 1, (timeout >> 8) & 0xff);
-	usbhid_submit_report(data->hdev, report, USB_DIR_OUT);
+	hid_hw_request(data->hdev, report, HID_REQ_SET_REPORT);
 	spin_unlock_irqrestore(&data->lock, flags);
 	return count;
 }
diff --git a/drivers/hid/hid-picolcd_debugfs.c b/drivers/hid/hid-picolcd_debugfs.c
index 4809aa1..59ab8e1 100644
--- a/drivers/hid/hid-picolcd_debugfs.c
+++ b/drivers/hid/hid-picolcd_debugfs.c
@@ -19,8 +19,6 @@
 
 #include <linux/hid.h>
 #include <linux/hid-debug.h>
-#include "usbhid/usbhid.h"
-#include <linux/usb.h>
 
 #include <linux/fb.h>
 #include <linux/seq_file.h>
diff --git a/drivers/hid/hid-picolcd_fb.c b/drivers/hid/hid-picolcd_fb.c
index eb00357..591f6b2 100644
--- a/drivers/hid/hid-picolcd_fb.c
+++ b/drivers/hid/hid-picolcd_fb.c
@@ -19,8 +19,6 @@
 
 #include <linux/hid.h>
 #include <linux/vmalloc.h>
-#include "usbhid/usbhid.h"
-#include <linux/usb.h>
 
 #include <linux/fb.h>
 #include <linux/module.h>
@@ -143,8 +141,8 @@ static int picolcd_fb_send_tile(struct picolcd_data *data, u8 *vbitmap,
 		else
 			hid_set_field(report2->field[0], 4 + i - 32, tdata[i]);
 
-	usbhid_submit_report(data->hdev, report1, USB_DIR_OUT);
-	usbhid_submit_report(data->hdev, report2, USB_DIR_OUT);
+	hid_hw_request(data->hdev, report1, HID_REQ_SET_REPORT);
+	hid_hw_request(data->hdev, report2, HID_REQ_SET_REPORT);
 	spin_unlock_irqrestore(&data->lock, flags);
 	return 0;
 }
@@ -214,7 +212,7 @@ int picolcd_fb_reset(struct picolcd_data *data, int clear)
 				hid_set_field(report->field[0], j, mapcmd[j]);
 			else
 				hid_set_field(report->field[0], j, 0);
-		usbhid_submit_report(data->hdev, report, USB_DIR_OUT);
+		hid_hw_request(data->hdev, report, HID_REQ_SET_REPORT);
 	}
 	spin_unlock_irqrestore(&data->lock, flags);
 
@@ -270,7 +268,7 @@ static void picolcd_fb_update(struct fb_info *info)
 				mutex_unlock(&info->lock);
 				if (!data)
 					return;
-				usbhid_wait_io(data->hdev);
+				hid_hw_wait(data->hdev);
 				mutex_lock(&info->lock);
 				n = 0;
 			}
@@ -288,7 +286,7 @@ static void picolcd_fb_update(struct fb_info *info)
 		spin_unlock_irqrestore(&fbdata->lock, flags);
 		mutex_unlock(&info->lock);
 		if (data)
-			usbhid_wait_io(data->hdev);
+			hid_hw_wait(data->hdev);
 		return;
 	}
 out:
diff --git a/drivers/hid/hid-picolcd_lcd.c b/drivers/hid/hid-picolcd_lcd.c
index 2d0ddc5..89821c2 100644
--- a/drivers/hid/hid-picolcd_lcd.c
+++ b/drivers/hid/hid-picolcd_lcd.c
@@ -18,8 +18,6 @@
  ***************************************************************************/
 
 #include <linux/hid.h>
-#include "usbhid/usbhid.h"
-#include <linux/usb.h>
 
 #include <linux/fb.h>
 #include <linux/lcd.h>
@@ -48,7 +46,7 @@ static int picolcd_set_contrast(struct lcd_device *ldev, int contrast)
 	spin_lock_irqsave(&data->lock, flags);
 	hid_set_field(report->field[0], 0, data->lcd_contrast);
 	if (!(data->status & PICOLCD_FAILED))
-		usbhid_submit_report(data->hdev, report, USB_DIR_OUT);
+		hid_hw_request(data->hdev, report, HID_REQ_SET_REPORT);
 	spin_unlock_irqrestore(&data->lock, flags);
 	return 0;
 }
diff --git a/drivers/hid/hid-picolcd_leds.c b/drivers/hid/hid-picolcd_leds.c
index 28cb6a4..e994f9c 100644
--- a/drivers/hid/hid-picolcd_leds.c
+++ b/drivers/hid/hid-picolcd_leds.c
@@ -21,8 +21,6 @@
 #include <linux/hid-debug.h>
 #include <linux/input.h>
 #include "hid-ids.h"
-#include "usbhid/usbhid.h"
-#include <linux/usb.h>
 
 #include <linux/fb.h>
 #include <linux/vmalloc.h>
@@ -55,7 +53,7 @@ void picolcd_leds_set(struct picolcd_data *data)
 	spin_lock_irqsave(&data->lock, flags);
 	hid_set_field(report->field[0], 0, data->led_state);
 	if (!(data->status & PICOLCD_FAILED))
-		usbhid_submit_report(data->hdev, report, USB_DIR_OUT);
+		hid_hw_request(data->hdev, report, HID_REQ_SET_REPORT);
 	spin_unlock_irqrestore(&data->lock, flags);
 }
 
diff --git a/drivers/hid/hid-pl.c b/drivers/hid/hid-pl.c
index b0199d2..d29112f 100644
--- a/drivers/hid/hid-pl.c
+++ b/drivers/hid/hid-pl.c
@@ -43,13 +43,11 @@
 #include <linux/input.h>
 #include <linux/slab.h>
 #include <linux/module.h>
-#include <linux/usb.h>
 #include <linux/hid.h>
 
 #include "hid-ids.h"
 
 #ifdef CONFIG_PANTHERLORD_FF
-#include "usbhid/usbhid.h"
 
 struct plff_device {
 	struct hid_report *report;
@@ -75,7 +73,7 @@ static int hid_plff_play(struct input_dev *dev, void *data,
 	*plff->strong = left;
 	*plff->weak = right;
 	debug("running with 0x%02x 0x%02x", left, right);
-	usbhid_submit_report(hid, plff->report, USB_DIR_OUT);
+	hid_hw_request(hid, plff->report, HID_REQ_SET_REPORT);
 
 	return 0;
 }
@@ -169,7 +167,7 @@ static int plff_init(struct hid_device *hid)
 
 		*strong = 0x00;
 		*weak = 0x00;
-		usbhid_submit_report(hid, plff->report, USB_DIR_OUT);
+		hid_hw_request(hid, plff->report, HID_REQ_SET_REPORT);
 	}
 
 	hid_info(hid, "Force feedback for PantherLord/GreenAsia devices by Anssi Hannula <anssi.hannula@gmail.com>\n");
diff --git a/drivers/hid/hid-prodikeys.c b/drivers/hid/hid-prodikeys.c
index 4e1c4bc..7ed8280 100644
--- a/drivers/hid/hid-prodikeys.c
+++ b/drivers/hid/hid-prodikeys.c
@@ -26,7 +26,6 @@
 #include <sound/core.h>
 #include <sound/initval.h>
 #include <sound/rawmidi.h>
-#include "usbhid/usbhid.h"
 #include "hid-ids.h"
 
 
@@ -306,7 +305,7 @@ static void pcmidi_submit_output_report(struct pcmidi_snd *pm, int state)
 	report->field[0]->value[0] = 0x01;
 	report->field[0]->value[1] = state;
 
-	usbhid_submit_report(hdev, report, USB_DIR_OUT);
+	hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
 }
 
 static int pcmidi_handle_report1(struct pcmidi_snd *pm, u8 *data)
diff --git a/drivers/hid/hid-roccat-isku.c b/drivers/hid/hid-roccat-isku.c
index 1219998..8023751 100644
--- a/drivers/hid/hid-roccat-isku.c
+++ b/drivers/hid/hid-roccat-isku.c
@@ -130,14 +130,14 @@ static ssize_t isku_sysfs_read(struct file *fp, struct kobject *kobj,
 	if (off >= real_size)
 		return 0;
 
-	if (off != 0 || count != real_size)
+	if (off != 0 || count > real_size)
 		return -EINVAL;
 
 	mutex_lock(&isku->isku_lock);
-	retval = isku_receive(usb_dev, command, buf, real_size);
+	retval = isku_receive(usb_dev, command, buf, count);
 	mutex_unlock(&isku->isku_lock);
 
-	return retval ? retval : real_size;
+	return retval ? retval : count;
 }
 
 static ssize_t isku_sysfs_write(struct file *fp, struct kobject *kobj,
@@ -150,15 +150,15 @@ static ssize_t isku_sysfs_write(struct file *fp, struct kobject *kobj,
 	struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
 	int retval;
 
-	if (off != 0 || count != real_size)
+	if (off != 0 || count > real_size)
 		return -EINVAL;
 
 	mutex_lock(&isku->isku_lock);
 	retval = roccat_common2_send_with_status(usb_dev, command,
-			(void *)buf, real_size);
+			(void *)buf, count);
 	mutex_unlock(&isku->isku_lock);
 
-	return retval ? retval : real_size;
+	return retval ? retval : count;
 }
 
 #define ISKU_SYSFS_W(thingy, THINGY) \
@@ -216,6 +216,7 @@ ISKU_SYSFS_RW(light, LIGHT)
 ISKU_SYSFS_RW(key_mask, KEY_MASK)
 ISKU_SYSFS_RW(last_set, LAST_SET)
 ISKU_SYSFS_W(talk, TALK)
+ISKU_SYSFS_W(talkfx, TALKFX)
 ISKU_SYSFS_R(info, INFO)
 ISKU_SYSFS_W(control, CONTROL)
 ISKU_SYSFS_W(reset, RESET)
@@ -232,6 +233,7 @@ static struct bin_attribute isku_bin_attributes[] = {
 	ISKU_BIN_ATTR_RW(key_mask, KEY_MASK),
 	ISKU_BIN_ATTR_RW(last_set, LAST_SET),
 	ISKU_BIN_ATTR_W(talk, TALK),
+	ISKU_BIN_ATTR_W(talkfx, TALKFX),
 	ISKU_BIN_ATTR_R(info, INFO),
 	ISKU_BIN_ATTR_W(control, CONTROL),
 	ISKU_BIN_ATTR_W(reset, RESET),
@@ -405,6 +407,7 @@ static int isku_raw_event(struct hid_device *hdev,
 
 static const struct hid_device_id isku_devices[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ISKU) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ISKUFX) },
 	{ }
 };
 
@@ -443,5 +446,5 @@ module_init(isku_init);
 module_exit(isku_exit);
 
 MODULE_AUTHOR("Stefan Achatz");
-MODULE_DESCRIPTION("USB Roccat Isku driver");
+MODULE_DESCRIPTION("USB Roccat Isku/FX driver");
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/hid/hid-roccat-isku.h b/drivers/hid/hid-roccat-isku.h
index cf6896c..5305686 100644
--- a/drivers/hid/hid-roccat-isku.h
+++ b/drivers/hid/hid-roccat-isku.h
@@ -25,10 +25,11 @@ enum {
 	ISKU_SIZE_KEYS_MACRO = 0x23,
 	ISKU_SIZE_KEYS_CAPSLOCK = 0x06,
 	ISKU_SIZE_LAST_SET = 0x14,
-	ISKU_SIZE_LIGHT = 0x0a,
+	ISKU_SIZE_LIGHT = 0x10,
 	ISKU_SIZE_MACRO = 0x823,
 	ISKU_SIZE_RESET = 0x03,
 	ISKU_SIZE_TALK = 0x10,
+	ISKU_SIZE_TALKFX = 0x10,
 };
 
 enum {
@@ -59,6 +60,7 @@ enum isku_commands {
 	ISKU_COMMAND_LAST_SET = 0x14,
 	ISKU_COMMAND_15 = 0x15,
 	ISKU_COMMAND_TALK = 0x16,
+	ISKU_COMMAND_TALKFX = 0x17,
 	ISKU_COMMAND_FIRMWARE_WRITE = 0x1b,
 	ISKU_COMMAND_FIRMWARE_WRITE_CONTROL = 0x1c,
 };
diff --git a/drivers/hid/hid-roccat-konepure.c b/drivers/hid/hid-roccat-konepure.c
new file mode 100644
index 0000000..c79d0b0
--- /dev/null
+++ b/drivers/hid/hid-roccat-konepure.c
@@ -0,0 +1,304 @@
+/*
+ * Roccat KonePure driver for Linux
+ *
+ * Copyright (c) 2012 Stefan Achatz <erazor_de@users.sourceforge.net>
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+/*
+ * Roccat KonePure is a smaller version of KoneXTD with less buttons and lights.
+ */
+
+#include <linux/device.h>
+#include <linux/input.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/hid-roccat.h>
+#include "hid-ids.h"
+#include "hid-roccat-common.h"
+#include "hid-roccat-konepure.h"
+
+static struct class *konepure_class;
+
+static ssize_t konepure_sysfs_read(struct file *fp, struct kobject *kobj,
+		char *buf, loff_t off, size_t count,
+		size_t real_size, uint command)
+{
+	struct device *dev =
+			container_of(kobj, struct device, kobj)->parent->parent;
+	struct konepure_device *konepure = hid_get_drvdata(dev_get_drvdata(dev));
+	struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
+	int retval;
+
+	if (off >= real_size)
+		return 0;
+
+	if (off != 0 || count != real_size)
+		return -EINVAL;
+
+	mutex_lock(&konepure->konepure_lock);
+	retval = roccat_common2_receive(usb_dev, command, buf, real_size);
+	mutex_unlock(&konepure->konepure_lock);
+
+	return retval ? retval : real_size;
+}
+
+static ssize_t konepure_sysfs_write(struct file *fp, struct kobject *kobj,
+		void const *buf, loff_t off, size_t count,
+		size_t real_size, uint command)
+{
+	struct device *dev =
+			container_of(kobj, struct device, kobj)->parent->parent;
+	struct konepure_device *konepure = hid_get_drvdata(dev_get_drvdata(dev));
+	struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
+	int retval;
+
+	if (off != 0 || count != real_size)
+		return -EINVAL;
+
+	mutex_lock(&konepure->konepure_lock);
+	retval = roccat_common2_send_with_status(usb_dev, command,
+			(void *)buf, real_size);
+	mutex_unlock(&konepure->konepure_lock);
+
+	return retval ? retval : real_size;
+}
+
+#define KONEPURE_SYSFS_W(thingy, THINGY) \
+static ssize_t konepure_sysfs_write_ ## thingy(struct file *fp, \
+		struct kobject *kobj, struct bin_attribute *attr, char *buf, \
+		loff_t off, size_t count) \
+{ \
+	return konepure_sysfs_write(fp, kobj, buf, off, count, \
+			KONEPURE_SIZE_ ## THINGY, KONEPURE_COMMAND_ ## THINGY); \
+}
+
+#define KONEPURE_SYSFS_R(thingy, THINGY) \
+static ssize_t konepure_sysfs_read_ ## thingy(struct file *fp, \
+		struct kobject *kobj, struct bin_attribute *attr, char *buf, \
+		loff_t off, size_t count) \
+{ \
+	return konepure_sysfs_read(fp, kobj, buf, off, count, \
+			KONEPURE_SIZE_ ## THINGY, KONEPURE_COMMAND_ ## THINGY); \
+}
+
+#define KONEPURE_SYSFS_RW(thingy, THINGY) \
+KONEPURE_SYSFS_W(thingy, THINGY) \
+KONEPURE_SYSFS_R(thingy, THINGY)
+
+#define KONEPURE_BIN_ATTRIBUTE_RW(thingy, THINGY) \
+{ \
+	.attr = { .name = #thingy, .mode = 0660 }, \
+	.size = KONEPURE_SIZE_ ## THINGY, \
+	.read = konepure_sysfs_read_ ## thingy, \
+	.write = konepure_sysfs_write_ ## thingy \
+}
+
+#define KONEPURE_BIN_ATTRIBUTE_R(thingy, THINGY) \
+{ \
+	.attr = { .name = #thingy, .mode = 0440 }, \
+	.size = KONEPURE_SIZE_ ## THINGY, \
+	.read = konepure_sysfs_read_ ## thingy, \
+}
+
+#define KONEPURE_BIN_ATTRIBUTE_W(thingy, THINGY) \
+{ \
+	.attr = { .name = #thingy, .mode = 0220 }, \
+	.size = KONEPURE_SIZE_ ## THINGY, \
+	.write = konepure_sysfs_write_ ## thingy \
+}
+
+KONEPURE_SYSFS_RW(actual_profile, ACTUAL_PROFILE)
+KONEPURE_SYSFS_W(control, CONTROL)
+KONEPURE_SYSFS_RW(info, INFO)
+KONEPURE_SYSFS_W(talk, TALK)
+KONEPURE_SYSFS_W(macro, MACRO)
+KONEPURE_SYSFS_RW(sensor, SENSOR)
+KONEPURE_SYSFS_RW(tcu, TCU)
+KONEPURE_SYSFS_R(tcu_image, TCU_IMAGE)
+KONEPURE_SYSFS_RW(profile_settings, PROFILE_SETTINGS)
+KONEPURE_SYSFS_RW(profile_buttons, PROFILE_BUTTONS)
+
+static struct bin_attribute konepure_bin_attributes[] = {
+	KONEPURE_BIN_ATTRIBUTE_RW(actual_profile, ACTUAL_PROFILE),
+	KONEPURE_BIN_ATTRIBUTE_W(control, CONTROL),
+	KONEPURE_BIN_ATTRIBUTE_RW(info, INFO),
+	KONEPURE_BIN_ATTRIBUTE_W(talk, TALK),
+	KONEPURE_BIN_ATTRIBUTE_W(macro, MACRO),
+	KONEPURE_BIN_ATTRIBUTE_RW(sensor, SENSOR),
+	KONEPURE_BIN_ATTRIBUTE_RW(tcu, TCU),
+	KONEPURE_BIN_ATTRIBUTE_R(tcu_image, TCU_IMAGE),
+	KONEPURE_BIN_ATTRIBUTE_RW(profile_settings, PROFILE_SETTINGS),
+	KONEPURE_BIN_ATTRIBUTE_RW(profile_buttons, PROFILE_BUTTONS),
+	__ATTR_NULL
+};
+
+static int konepure_init_konepure_device_struct(struct usb_device *usb_dev,
+		struct konepure_device *konepure)
+{
+	mutex_init(&konepure->konepure_lock);
+
+	return 0;
+}
+
+static int konepure_init_specials(struct hid_device *hdev)
+{
+	struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
+	struct usb_device *usb_dev = interface_to_usbdev(intf);
+	struct konepure_device *konepure;
+	int retval;
+
+	if (intf->cur_altsetting->desc.bInterfaceProtocol
+			!= USB_INTERFACE_PROTOCOL_MOUSE) {
+		hid_set_drvdata(hdev, NULL);
+		return 0;
+	}
+
+	konepure = kzalloc(sizeof(*konepure), GFP_KERNEL);
+	if (!konepure) {
+		hid_err(hdev, "can't alloc device descriptor\n");
+		return -ENOMEM;
+	}
+	hid_set_drvdata(hdev, konepure);
+
+	retval = konepure_init_konepure_device_struct(usb_dev, konepure);
+	if (retval) {
+		hid_err(hdev, "couldn't init struct konepure_device\n");
+		goto exit_free;
+	}
+
+	retval = roccat_connect(konepure_class, hdev,
+			sizeof(struct konepure_mouse_report_button));
+	if (retval < 0) {
+		hid_err(hdev, "couldn't init char dev\n");
+	} else {
+		konepure->chrdev_minor = retval;
+		konepure->roccat_claimed = 1;
+	}
+
+	return 0;
+exit_free:
+	kfree(konepure);
+	return retval;
+}
+
+static void konepure_remove_specials(struct hid_device *hdev)
+{
+	struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
+	struct konepure_device *konepure;
+
+	if (intf->cur_altsetting->desc.bInterfaceProtocol
+			!= USB_INTERFACE_PROTOCOL_MOUSE)
+		return;
+
+	konepure = hid_get_drvdata(hdev);
+	if (konepure->roccat_claimed)
+		roccat_disconnect(konepure->chrdev_minor);
+	kfree(konepure);
+}
+
+static int konepure_probe(struct hid_device *hdev,
+		const struct hid_device_id *id)
+{
+	int retval;
+
+	retval = hid_parse(hdev);
+	if (retval) {
+		hid_err(hdev, "parse failed\n");
+		goto exit;
+	}
+
+	retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+	if (retval) {
+		hid_err(hdev, "hw start failed\n");
+		goto exit;
+	}
+
+	retval = konepure_init_specials(hdev);
+	if (retval) {
+		hid_err(hdev, "couldn't install mouse\n");
+		goto exit_stop;
+	}
+
+	return 0;
+
+exit_stop:
+	hid_hw_stop(hdev);
+exit:
+	return retval;
+}
+
+static void konepure_remove(struct hid_device *hdev)
+{
+	konepure_remove_specials(hdev);
+	hid_hw_stop(hdev);
+}
+
+static int konepure_raw_event(struct hid_device *hdev,
+		struct hid_report *report, u8 *data, int size)
+{
+	struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
+	struct konepure_device *konepure = hid_get_drvdata(hdev);
+
+	if (intf->cur_altsetting->desc.bInterfaceProtocol
+			!= USB_INTERFACE_PROTOCOL_MOUSE)
+		return 0;
+
+	if (data[0] != KONEPURE_MOUSE_REPORT_NUMBER_BUTTON)
+		return 0;
+
+	if (konepure != NULL && konepure->roccat_claimed)
+		roccat_report_event(konepure->chrdev_minor, data);
+
+	return 0;
+}
+
+static const struct hid_device_id konepure_devices[] = {
+	{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPURE) },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(hid, konepure_devices);
+
+static struct hid_driver konepure_driver = {
+		.name = "konepure",
+		.id_table = konepure_devices,
+		.probe = konepure_probe,
+		.remove = konepure_remove,
+		.raw_event = konepure_raw_event
+};
+
+static int __init konepure_init(void)
+{
+	int retval;
+
+	konepure_class = class_create(THIS_MODULE, "konepure");
+	if (IS_ERR(konepure_class))
+		return PTR_ERR(konepure_class);
+	konepure_class->dev_bin_attrs = konepure_bin_attributes;
+
+	retval = hid_register_driver(&konepure_driver);
+	if (retval)
+		class_destroy(konepure_class);
+	return retval;
+}
+
+static void __exit konepure_exit(void)
+{
+	hid_unregister_driver(&konepure_driver);
+	class_destroy(konepure_class);
+}
+
+module_init(konepure_init);
+module_exit(konepure_exit);
+
+MODULE_AUTHOR("Stefan Achatz");
+MODULE_DESCRIPTION("USB Roccat KonePure driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/hid/hid-roccat-konepure.h b/drivers/hid/hid-roccat-konepure.h
new file mode 100644
index 0000000..2cd24e9
--- /dev/null
+++ b/drivers/hid/hid-roccat-konepure.h
@@ -0,0 +1,72 @@
+#ifndef __HID_ROCCAT_KONEPURE_H
+#define __HID_ROCCAT_KONEPURE_H
+
+/*
+ * Copyright (c) 2012 Stefan Achatz <erazor_de@users.sourceforge.net>
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+#include <linux/types.h>
+
+enum {
+	KONEPURE_SIZE_ACTUAL_PROFILE = 0x03,
+	KONEPURE_SIZE_CONTROL = 0x03,
+	KONEPURE_SIZE_FIRMWARE_WRITE = 0x0402,
+	KONEPURE_SIZE_INFO = 0x06,
+	KONEPURE_SIZE_MACRO = 0x0822,
+	KONEPURE_SIZE_PROFILE_SETTINGS = 0x1f,
+	KONEPURE_SIZE_PROFILE_BUTTONS = 0x3b,
+	KONEPURE_SIZE_SENSOR = 0x06,
+	KONEPURE_SIZE_TALK = 0x10,
+	KONEPURE_SIZE_TCU = 0x04,
+	KONEPURE_SIZE_TCU_IMAGE = 0x0404,
+};
+
+enum konepure_control_requests {
+	KONEPURE_CONTROL_REQUEST_GENERAL = 0x80,
+	KONEPURE_CONTROL_REQUEST_BUTTONS = 0x90,
+};
+
+enum konepure_commands {
+	KONEPURE_COMMAND_CONTROL = 0x04,
+	KONEPURE_COMMAND_ACTUAL_PROFILE = 0x05,
+	KONEPURE_COMMAND_PROFILE_SETTINGS = 0x06,
+	KONEPURE_COMMAND_PROFILE_BUTTONS = 0x07,
+	KONEPURE_COMMAND_MACRO = 0x08,
+	KONEPURE_COMMAND_INFO = 0x09,
+	KONEPURE_COMMAND_TCU = 0x0c,
+	KONEPURE_COMMAND_TCU_IMAGE = 0x0c,
+	KONEPURE_COMMAND_E = 0x0e,
+	KONEPURE_COMMAND_SENSOR = 0x0f,
+	KONEPURE_COMMAND_TALK = 0x10,
+	KONEPURE_COMMAND_FIRMWARE_WRITE = 0x1b,
+	KONEPURE_COMMAND_FIRMWARE_WRITE_CONTROL = 0x1c,
+};
+
+enum {
+	KONEPURE_MOUSE_REPORT_NUMBER_BUTTON = 3,
+};
+
+struct konepure_mouse_report_button {
+	uint8_t report_number; /* always KONEPURE_MOUSE_REPORT_NUMBER_BUTTON */
+	uint8_t zero;
+	uint8_t type;
+	uint8_t data1;
+	uint8_t data2;
+	uint8_t zero2;
+	uint8_t unknown[2];
+} __packed;
+
+struct konepure_device {
+	int roccat_claimed;
+	int chrdev_minor;
+	struct mutex konepure_lock;
+};
+
+#endif
diff --git a/drivers/hid/hid-roccat.c b/drivers/hid/hid-roccat.c
index d7437ef..b59b3df 100644
--- a/drivers/hid/hid-roccat.c
+++ b/drivers/hid/hid-roccat.c
@@ -242,7 +242,6 @@ static int roccat_release(struct inode *inode, struct file *file)
  * roccat_report_event() - output data to readers
  * @minor: minor device number returned by roccat_connect()
  * @data: pointer to data
- * @len: size of data
  *
  * Return value is zero on success, a negative error code on failure.
  *
@@ -290,6 +289,7 @@ EXPORT_SYMBOL_GPL(roccat_report_event);
  * @class: the class thats used to create the device. Meant to hold device
  * specific sysfs attributes.
  * @hid: the hid device the char device should be connected to.
+ * @report_size: size of reports
  *
  * Return value is minor device number in Range [0, ROCCAT_MAX_DEVICES] on
  * success, a negative error code on failure.
diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c
index 6679788..ca749810 100644
--- a/drivers/hid/hid-sensor-hub.c
+++ b/drivers/hid/hid-sensor-hub.c
@@ -18,8 +18,6 @@
  */
 #include <linux/device.h>
 #include <linux/hid.h>
-#include <linux/usb.h>
-#include "usbhid/usbhid.h"
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/mfd/core.h>
@@ -204,8 +202,8 @@ int sensor_hub_set_feature(struct hid_sensor_hub_device *hsdev, u32 report_id,
 		goto done_proc;
 	}
 	hid_set_field(report->field[field_index], 0, value);
-	usbhid_submit_report(hsdev->hdev, report, USB_DIR_OUT);
-	usbhid_wait_io(hsdev->hdev);
+	hid_hw_request(hsdev->hdev, report, HID_REQ_SET_REPORT);
+	hid_hw_wait(hsdev->hdev);
 
 done_proc:
 	mutex_unlock(&data->mutex);
@@ -227,8 +225,8 @@ int sensor_hub_get_feature(struct hid_sensor_hub_device *hsdev, u32 report_id,
 		ret = -EINVAL;
 		goto done_proc;
 	}
-	usbhid_submit_report(hsdev->hdev, report, USB_DIR_IN);
-	usbhid_wait_io(hsdev->hdev);
+	hid_hw_request(hsdev->hdev, report, HID_REQ_GET_REPORT);
+	hid_hw_wait(hsdev->hdev);
 	*value = report->field[field_index]->value[0];
 
 done_proc:
@@ -262,7 +260,7 @@ int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev,
 		spin_unlock_irqrestore(&data->lock, flags);
 		goto err_free;
 	}
-	usbhid_submit_report(hsdev->hdev, report, USB_DIR_IN);
+	hid_hw_request(hsdev->hdev, report, HID_REQ_GET_REPORT);
 	spin_unlock_irqrestore(&data->lock, flags);
 	wait_for_completion_interruptible_timeout(&data->pending.ready, HZ*5);
 	switch (data->pending.raw_size) {
diff --git a/drivers/hid/hid-sjoy.c b/drivers/hid/hid-sjoy.c
index 28f7740..37845ec 100644
--- a/drivers/hid/hid-sjoy.c
+++ b/drivers/hid/hid-sjoy.c
@@ -28,13 +28,11 @@
 
 #include <linux/input.h>
 #include <linux/slab.h>
-#include <linux/usb.h>
 #include <linux/hid.h>
 #include <linux/module.h>
 #include "hid-ids.h"
 
 #ifdef CONFIG_SMARTJOYPLUS_FF
-#include "usbhid/usbhid.h"
 
 struct sjoyff_device {
 	struct hid_report *report;
@@ -57,7 +55,7 @@ static int hid_sjoyff_play(struct input_dev *dev, void *data,
 	sjoyff->report->field[0]->value[1] = right;
 	sjoyff->report->field[0]->value[2] = left;
 	dev_dbg(&dev->dev, "running with 0x%02x 0x%02x\n", left, right);
-	usbhid_submit_report(hid, sjoyff->report, USB_DIR_OUT);
+	hid_hw_request(hid, sjoyff->report, HID_REQ_SET_REPORT);
 
 	return 0;
 }
@@ -115,7 +113,7 @@ static int sjoyff_init(struct hid_device *hid)
 		sjoyff->report->field[0]->value[0] = 0x01;
 		sjoyff->report->field[0]->value[1] = 0x00;
 		sjoyff->report->field[0]->value[2] = 0x00;
-		usbhid_submit_report(hid, sjoyff->report, USB_DIR_OUT);
+		hid_hw_request(hid, sjoyff->report, HID_REQ_SET_REPORT);
 	}
 
 	hid_info(hid, "Force feedback for SmartJoy PLUS PS2/USB adapter\n");
diff --git a/drivers/hid/hid-speedlink.c b/drivers/hid/hid-speedlink.c
index e94371a..a2f587d 100644
--- a/drivers/hid/hid-speedlink.c
+++ b/drivers/hid/hid-speedlink.c
@@ -16,10 +16,8 @@
 #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)},
diff --git a/drivers/hid/hid-steelseries.c b/drivers/hid/hid-steelseries.c
index 2ed995c..9b0efb0 100644
--- a/drivers/hid/hid-steelseries.c
+++ b/drivers/hid/hid-steelseries.c
@@ -16,7 +16,6 @@
 #include <linux/hid.h>
 #include <linux/module.h>
 
-#include "usbhid/usbhid.h"
 #include "hid-ids.h"
 
 #if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE)
@@ -132,7 +131,7 @@ static void steelseries_srws1_set_leds(struct hid_device *hdev, __u16 leds)
 	value[14] = 0x00;
 	value[15] = 0x00;
 
-	usbhid_submit_report(hdev, report, USB_DIR_OUT);
+	hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
 
 	/* Note: LED change does not show on device until the device is read/polled */
 }
@@ -378,16 +377,5 @@ static struct hid_driver steelseries_srws1_driver = {
 	.report_fixup = steelseries_srws1_report_fixup
 };
 
-static int __init steelseries_srws1_init(void)
-{
-	return hid_register_driver(&steelseries_srws1_driver);
-}
-
-static void __exit steelseries_srws1_exit(void)
-{
-	hid_unregister_driver(&steelseries_srws1_driver);
-}
-
-module_init(steelseries_srws1_init);
-module_exit(steelseries_srws1_exit);
+module_hid_driver(steelseries_srws1_driver);
 MODULE_LICENSE("GPL");
diff --git a/drivers/hid/hid-thingm.c b/drivers/hid/hid-thingm.c
index 2055a52..99342cf 100644
--- a/drivers/hid/hid-thingm.c
+++ b/drivers/hid/hid-thingm.c
@@ -12,7 +12,6 @@
 #include <linux/hid.h>
 #include <linux/leds.h>
 #include <linux/module.h>
-#include <linux/usb.h>
 
 #include "hid-ids.h"
 
diff --git a/drivers/hid/hid-tmff.c b/drivers/hid/hid-tmff.c
index e4fcf3f..b833760 100644
--- a/drivers/hid/hid-tmff.c
+++ b/drivers/hid/hid-tmff.c
@@ -30,7 +30,6 @@
 #include <linux/hid.h>
 #include <linux/input.h>
 #include <linux/slab.h>
-#include <linux/usb.h>
 #include <linux/module.h>
 
 #include "hid-ids.h"
@@ -46,7 +45,6 @@ static const signed short ff_joystick[] = {
 };
 
 #ifdef CONFIG_THRUSTMASTER_FF
-#include "usbhid/usbhid.h"
 
 /* Usages for thrustmaster devices I know about */
 #define THRUSTMASTER_USAGE_FF	(HID_UP_GENDESK | 0xbb)
@@ -103,7 +101,7 @@ static int tmff_play(struct input_dev *dev, void *data,
 		dbg_hid("(x, y)=(%04x, %04x)\n", x, y);
 		ff_field->value[0] = x;
 		ff_field->value[1] = y;
-		usbhid_submit_report(hid, tmff->report, USB_DIR_OUT);
+		hid_hw_request(hid, tmff->report, HID_REQ_SET_REPORT);
 		break;
 
 	case FF_RUMBLE:
@@ -117,7 +115,7 @@ static int tmff_play(struct input_dev *dev, void *data,
 		dbg_hid("(left,right)=(%08x, %08x)\n", left, right);
 		ff_field->value[0] = left;
 		ff_field->value[1] = right;
-		usbhid_submit_report(hid, tmff->report, USB_DIR_OUT);
+		hid_hw_request(hid, tmff->report, HID_REQ_SET_REPORT);
 		break;
 	}
 	return 0;
diff --git a/drivers/hid/hid-wiimote-core.c b/drivers/hid/hid-wiimote-core.c
index 0fb8ab9..e5ee1f2 100644
--- a/drivers/hid/hid-wiimote-core.c
+++ b/drivers/hid/hid-wiimote-core.c
@@ -789,12 +789,20 @@ static void __ir_to_input(struct wiimote_data *wdata, const __u8 *ir,
 	input_report_abs(wdata->ir, yid, y);
 }
 
-static void handler_status(struct wiimote_data *wdata, const __u8 *payload)
+/* reduced status report with "BB BB" key data only */
+static void handler_status_K(struct wiimote_data *wdata,
+			     const __u8 *payload)
 {
 	handler_keys(wdata, payload);
 
 	/* on status reports the drm is reset so we need to resend the drm */
 	wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
+}
+
+/* extended status report with "BB BB LF 00 00 VV" data */
+static void handler_status(struct wiimote_data *wdata, const __u8 *payload)
+{
+	handler_status_K(wdata, payload);
 
 	wiiext_event(wdata, payload[2] & 0x02);
 
@@ -804,6 +812,12 @@ static void handler_status(struct wiimote_data *wdata, const __u8 *payload)
 	}
 }
 
+/* reduced generic report with "BB BB" key data only */
+static void handler_generic_K(struct wiimote_data *wdata, const __u8 *payload)
+{
+	handler_keys(wdata, payload);
+}
+
 static void handler_data(struct wiimote_data *wdata, const __u8 *payload)
 {
 	__u16 offset = payload[3] << 8 | payload[4];
@@ -947,16 +961,26 @@ struct wiiproto_handler {
 
 static struct wiiproto_handler handlers[] = {
 	{ .id = WIIPROTO_REQ_STATUS, .size = 6, .func = handler_status },
+	{ .id = WIIPROTO_REQ_STATUS, .size = 2, .func = handler_status_K },
 	{ .id = WIIPROTO_REQ_DATA, .size = 21, .func = handler_data },
+	{ .id = WIIPROTO_REQ_DATA, .size = 2, .func = handler_generic_K },
 	{ .id = WIIPROTO_REQ_RETURN, .size = 4, .func = handler_return },
+	{ .id = WIIPROTO_REQ_RETURN, .size = 2, .func = handler_generic_K },
 	{ .id = WIIPROTO_REQ_DRM_K, .size = 2, .func = handler_keys },
 	{ .id = WIIPROTO_REQ_DRM_KA, .size = 5, .func = handler_drm_KA },
+	{ .id = WIIPROTO_REQ_DRM_KA, .size = 2, .func = handler_generic_K },
 	{ .id = WIIPROTO_REQ_DRM_KE, .size = 10, .func = handler_drm_KE },
+	{ .id = WIIPROTO_REQ_DRM_KE, .size = 2, .func = handler_generic_K },
 	{ .id = WIIPROTO_REQ_DRM_KAI, .size = 17, .func = handler_drm_KAI },
+	{ .id = WIIPROTO_REQ_DRM_KAI, .size = 2, .func = handler_generic_K },
 	{ .id = WIIPROTO_REQ_DRM_KEE, .size = 21, .func = handler_drm_KEE },
+	{ .id = WIIPROTO_REQ_DRM_KEE, .size = 2, .func = handler_generic_K },
 	{ .id = WIIPROTO_REQ_DRM_KAE, .size = 21, .func = handler_drm_KAE },
+	{ .id = WIIPROTO_REQ_DRM_KAE, .size = 2, .func = handler_generic_K },
 	{ .id = WIIPROTO_REQ_DRM_KIE, .size = 21, .func = handler_drm_KIE },
+	{ .id = WIIPROTO_REQ_DRM_KIE, .size = 2, .func = handler_generic_K },
 	{ .id = WIIPROTO_REQ_DRM_KAIE, .size = 21, .func = handler_drm_KAIE },
+	{ .id = WIIPROTO_REQ_DRM_KAIE, .size = 2, .func = handler_generic_K },
 	{ .id = WIIPROTO_REQ_DRM_E, .size = 21, .func = handler_drm_E },
 	{ .id = WIIPROTO_REQ_DRM_SKAI1, .size = 21, .func = handler_drm_SKAI1 },
 	{ .id = WIIPROTO_REQ_DRM_SKAI2, .size = 21, .func = handler_drm_SKAI2 },
@@ -970,7 +994,6 @@ static int wiimote_hid_event(struct hid_device *hdev, struct hid_report *report,
 	struct wiiproto_handler *h;
 	int i;
 	unsigned long flags;
-	bool handled = false;
 
 	if (size < 1)
 		return -EINVAL;
@@ -981,11 +1004,11 @@ static int wiimote_hid_event(struct hid_device *hdev, struct hid_report *report,
 		h = &handlers[i];
 		if (h->id == raw_data[0] && h->size < size) {
 			h->func(wdata, &raw_data[1]);
-			handled = true;
+			break;
 		}
 	}
 
-	if (!handled)
+	if (!handlers[i].id)
 		hid_warn(hdev, "Unhandled report %hhu size %d\n", raw_data[0],
 									size);
 
@@ -1160,6 +1183,7 @@ static void wiimote_destroy(struct wiimote_data *wdata)
 	wiimote_leds_destroy(wdata);
 
 	power_supply_unregister(&wdata->battery);
+	kfree(wdata->battery.name);
 	input_unregister_device(wdata->accel);
 	input_unregister_device(wdata->ir);
 	input_unregister_device(wdata->input);
@@ -1216,9 +1240,14 @@ static int wiimote_hid_probe(struct hid_device *hdev,
 	wdata->battery.properties = wiimote_battery_props;
 	wdata->battery.num_properties = ARRAY_SIZE(wiimote_battery_props);
 	wdata->battery.get_property = wiimote_battery_get_property;
-	wdata->battery.name = "wiimote_battery";
 	wdata->battery.type = POWER_SUPPLY_TYPE_BATTERY;
 	wdata->battery.use_for_apm = 0;
+	wdata->battery.name = kasprintf(GFP_KERNEL, "wiimote_battery_%s",
+					wdata->hdev->uniq);
+	if (!wdata->battery.name) {
+		ret = -ENOMEM;
+		goto err_battery_name;
+	}
 
 	ret = power_supply_register(&wdata->hdev->dev, &wdata->battery);
 	if (ret) {
@@ -1254,6 +1283,8 @@ err_free:
 	return ret;
 
 err_battery:
+	kfree(wdata->battery.name);
+err_battery_name:
 	input_unregister_device(wdata->input);
 	wdata->input = NULL;
 err_input:
@@ -1283,6 +1314,8 @@ static void wiimote_hid_remove(struct hid_device *hdev)
 static const struct hid_device_id wiimote_hid_devices[] = {
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO,
 				USB_DEVICE_ID_NINTENDO_WIIMOTE) },
+	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO,
+				USB_DEVICE_ID_NINTENDO_WIIMOTE2) },
 	{ }
 };
 MODULE_DEVICE_TABLE(hid, wiimote_hid_devices);
diff --git a/drivers/hid/hid-zpff.c b/drivers/hid/hid-zpff.c
index af66452..6ec28a3 100644
--- a/drivers/hid/hid-zpff.c
+++ b/drivers/hid/hid-zpff.c
@@ -24,13 +24,11 @@
 #include <linux/hid.h>
 #include <linux/input.h>
 #include <linux/slab.h>
-#include <linux/usb.h>
 #include <linux/module.h>
 
 #include "hid-ids.h"
 
 #ifdef CONFIG_ZEROPLUS_FF
-#include "usbhid/usbhid.h"
 
 struct zpff_device {
 	struct hid_report *report;
@@ -59,7 +57,7 @@ static int zpff_play(struct input_dev *dev, void *data,
 	zpff->report->field[2]->value[0] = left;
 	zpff->report->field[3]->value[0] = right;
 	dbg_hid("running with 0x%02x 0x%02x\n", left, right);
-	usbhid_submit_report(hid, zpff->report, USB_DIR_OUT);
+	hid_hw_request(hid, zpff->report, HID_REQ_SET_REPORT);
 
 	return 0;
 }
@@ -104,7 +102,7 @@ static int zpff_init(struct hid_device *hid)
 	zpff->report->field[1]->value[0] = 0x02;
 	zpff->report->field[2]->value[0] = 0x00;
 	zpff->report->field[3]->value[0] = 0x00;
-	usbhid_submit_report(hid, zpff->report, USB_DIR_OUT);
+	hid_hw_request(hid, zpff->report, HID_REQ_SET_REPORT);
 
 	hid_info(hid, "force feedback for Zeroplus based devices by Anssi Hannula <anssi.hannula@gmail.com>\n");
 
diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c
index ec79302..2b1799a 100644
--- a/drivers/hid/i2c-hid/i2c-hid.c
+++ b/drivers/hid/i2c-hid/i2c-hid.c
@@ -563,6 +563,36 @@ static int i2c_hid_output_raw_report(struct hid_device *hid, __u8 *buf,
 	return ret;
 }
 
+static void i2c_hid_request(struct hid_device *hid, struct hid_report *rep,
+		int reqtype)
+{
+	struct i2c_client *client = hid->driver_data;
+	char *buf;
+	int ret;
+	int len = i2c_hid_get_report_length(rep) - 2;
+
+	buf = kzalloc(len, GFP_KERNEL);
+	if (!buf)
+		return;
+
+	switch (reqtype) {
+	case HID_REQ_GET_REPORT:
+		ret = i2c_hid_get_raw_report(hid, rep->id, buf, len, rep->type);
+		if (ret < 0)
+			dev_err(&client->dev, "%s: unable to get report: %d\n",
+				__func__, ret);
+		else
+			hid_input_report(hid, rep->type, buf, ret, 0);
+		break;
+	case HID_REQ_SET_REPORT:
+		hid_output_report(rep, buf);
+		i2c_hid_output_raw_report(hid, buf, len, rep->type);
+		break;
+	}
+
+	kfree(buf);
+}
+
 static int i2c_hid_parse(struct hid_device *hid)
 {
 	struct i2c_client *client = hid->driver_data;
@@ -742,6 +772,7 @@ static struct hid_ll_driver i2c_hid_ll_driver = {
 	.open = i2c_hid_open,
 	.close = i2c_hid_close,
 	.power = i2c_hid_power,
+	.request = i2c_hid_request,
 	.hidinput_input_event = i2c_hid_hidinput_input_event,
 };
 
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index 8e0c4bf94..9941828 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -639,7 +639,7 @@ static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *re
 	}
 }
 
-void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir)
+static void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir)
 {
 	struct usbhid_device *usbhid = hid->driver_data;
 	unsigned long flags;
@@ -648,7 +648,6 @@ void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, uns
 	__usbhid_submit_report(hid, report, dir);
 	spin_unlock_irqrestore(&usbhid->lock, flags);
 }
-EXPORT_SYMBOL_GPL(usbhid_submit_report);
 
 /* Workqueue routine to send requests to change LEDs */
 static void hid_led(struct work_struct *work)
@@ -706,7 +705,7 @@ static int usb_hidinput_input_event(struct input_dev *dev, unsigned int type, un
 	return 0;
 }
 
-int usbhid_wait_io(struct hid_device *hid)
+static int usbhid_wait_io(struct hid_device *hid)
 {
 	struct usbhid_device *usbhid = hid->driver_data;
 
@@ -720,7 +719,6 @@ int usbhid_wait_io(struct hid_device *hid)
 
 	return 0;
 }
-EXPORT_SYMBOL_GPL(usbhid_wait_io);
 
 static int hid_set_idle(struct usb_device *dev, int ifnum, int report, int idle)
 {
@@ -1243,6 +1241,32 @@ static int usbhid_power(struct hid_device *hid, int lvl)
 	return r;
 }
 
+static void usbhid_request(struct hid_device *hid, struct hid_report *rep, int reqtype)
+{
+	switch (reqtype) {
+	case HID_REQ_GET_REPORT:
+		usbhid_submit_report(hid, rep, USB_DIR_IN);
+		break;
+	case HID_REQ_SET_REPORT:
+		usbhid_submit_report(hid, rep, USB_DIR_OUT);
+		break;
+	}
+}
+
+static int usbhid_idle(struct hid_device *hid, int report, int idle,
+		int reqtype)
+{
+	struct usb_device *dev = hid_to_usb_dev(hid);
+	struct usb_interface *intf = to_usb_interface(hid->dev.parent);
+	struct usb_host_interface *interface = intf->cur_altsetting;
+	int ifnum = interface->desc.bInterfaceNumber;
+
+	if (reqtype != HID_REQ_SET_IDLE)
+		return -EINVAL;
+
+	return hid_set_idle(dev, ifnum, report, idle);
+}
+
 static struct hid_ll_driver usb_hid_driver = {
 	.parse = usbhid_parse,
 	.start = usbhid_start,
@@ -1251,6 +1275,9 @@ static struct hid_ll_driver usb_hid_driver = {
 	.close = usbhid_close,
 	.power = usbhid_power,
 	.hidinput_input_event = usb_hidinput_input_event,
+	.request = usbhid_request,
+	.wait = usbhid_wait_io,
+	.idle = usbhid_idle,
 };
 
 static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id *id)
@@ -1493,7 +1520,7 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message)
 {
 	struct hid_device *hid = usb_get_intfdata(intf);
 	struct usbhid_device *usbhid = hid->driver_data;
-	int status;
+	int status = 0;
 	bool driver_suspended = false;
 
 	if (PMSG_IS_AUTO(message)) {
@@ -1520,19 +1547,15 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message)
 		}
 
 	} else {
-		if (hid->driver && hid->driver->suspend) {
+		/* TODO: resume() might need to handle suspend failure */
+		if (hid->driver && hid->driver->suspend)
 			status = hid->driver->suspend(hid, message);
-			if (status < 0)
-				return status;
-		}
 		driver_suspended = true;
 		spin_lock_irq(&usbhid->lock);
 		set_bit(HID_SUSPENDED, &usbhid->iofl);
 		spin_unlock_irq(&usbhid->lock);
-		if (usbhid_wait_io(hid) < 0) {
+		if (usbhid_wait_io(hid) < 0)
 			status = -EIO;
-			goto failed;
-		}
 	}
 
 	hid_cancel_delayed_stuff(usbhid);
@@ -1544,7 +1567,7 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message)
 		goto failed;
 	}
 	dev_dbg(&intf->dev, "suspend\n");
-	return 0;
+	return status;
 
  failed:
 	hid_resume_common(hid, driver_suspended);
diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
index f91c136..10b6167 100644
--- a/drivers/hid/usbhid/hid-pidff.c
+++ b/drivers/hid/usbhid/hid-pidff.c
@@ -263,8 +263,8 @@ static void pidff_set_envelope_report(struct pidff_device *pidff,
 		envelope->attack_level,
 		pidff->set_envelope[PID_ATTACK_LEVEL].value[0]);
 
-	usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_ENVELOPE],
-			  USB_DIR_OUT);
+	hid_hw_request(pidff->hid, pidff->reports[PID_SET_ENVELOPE],
+			HID_REQ_SET_REPORT);
 }
 
 /*
@@ -290,8 +290,8 @@ static void pidff_set_constant_force_report(struct pidff_device *pidff,
 	pidff_set_signed(&pidff->set_constant[PID_MAGNITUDE],
 			 effect->u.constant.level);
 
-	usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_CONSTANT],
-			  USB_DIR_OUT);
+	hid_hw_request(pidff->hid, pidff->reports[PID_SET_CONSTANT],
+			HID_REQ_SET_REPORT);
 }
 
 /*
@@ -325,8 +325,8 @@ static void pidff_set_effect_report(struct pidff_device *pidff,
 				pidff->effect_direction);
 	pidff->set_effect[PID_START_DELAY].value[0] = effect->replay.delay;
 
-	usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_EFFECT],
-			  USB_DIR_OUT);
+	hid_hw_request(pidff->hid, pidff->reports[PID_SET_EFFECT],
+			HID_REQ_SET_REPORT);
 }
 
 /*
@@ -357,8 +357,8 @@ static void pidff_set_periodic_report(struct pidff_device *pidff,
 	pidff_set(&pidff->set_periodic[PID_PHASE], effect->u.periodic.phase);
 	pidff->set_periodic[PID_PERIOD].value[0] = effect->u.periodic.period;
 
-	usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_PERIODIC],
-			  USB_DIR_OUT);
+	hid_hw_request(pidff->hid, pidff->reports[PID_SET_PERIODIC],
+			HID_REQ_SET_REPORT);
 
 }
 
@@ -399,8 +399,8 @@ static void pidff_set_condition_report(struct pidff_device *pidff,
 			  effect->u.condition[i].left_saturation);
 		pidff_set(&pidff->set_condition[PID_DEAD_BAND],
 			  effect->u.condition[i].deadband);
-		usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_CONDITION],
-				  USB_DIR_OUT);
+		hid_hw_request(pidff->hid, pidff->reports[PID_SET_CONDITION],
+				HID_REQ_SET_REPORT);
 	}
 }
 
@@ -440,8 +440,8 @@ static void pidff_set_ramp_force_report(struct pidff_device *pidff,
 			 effect->u.ramp.start_level);
 	pidff_set_signed(&pidff->set_ramp[PID_RAMP_END],
 			 effect->u.ramp.end_level);
-	usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_RAMP],
-			  USB_DIR_OUT);
+	hid_hw_request(pidff->hid, pidff->reports[PID_SET_RAMP],
+			HID_REQ_SET_REPORT);
 }
 
 /*
@@ -465,19 +465,19 @@ static int pidff_request_effect_upload(struct pidff_device *pidff, int efnum)
 	int j;
 
 	pidff->create_new_effect_type->value[0] = efnum;
-	usbhid_submit_report(pidff->hid, pidff->reports[PID_CREATE_NEW_EFFECT],
-			  USB_DIR_OUT);
+	hid_hw_request(pidff->hid, pidff->reports[PID_CREATE_NEW_EFFECT],
+			HID_REQ_SET_REPORT);
 	hid_dbg(pidff->hid, "create_new_effect sent, type: %d\n", efnum);
 
 	pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0] = 0;
 	pidff->block_load_status->value[0] = 0;
-	usbhid_wait_io(pidff->hid);
+	hid_hw_wait(pidff->hid);
 
 	for (j = 0; j < 60; j++) {
 		hid_dbg(pidff->hid, "pid_block_load requested\n");
-		usbhid_submit_report(pidff->hid, pidff->reports[PID_BLOCK_LOAD],
-				  USB_DIR_IN);
-		usbhid_wait_io(pidff->hid);
+		hid_hw_request(pidff->hid, pidff->reports[PID_BLOCK_LOAD],
+				HID_REQ_GET_REPORT);
+		hid_hw_wait(pidff->hid);
 		if (pidff->block_load_status->value[0] ==
 		    pidff->status_id[PID_BLOCK_LOAD_SUCCESS]) {
 			hid_dbg(pidff->hid, "device reported free memory: %d bytes\n",
@@ -513,8 +513,8 @@ static void pidff_playback_pid(struct pidff_device *pidff, int pid_id, int n)
 		pidff->effect_operation[PID_LOOP_COUNT].value[0] = n;
 	}
 
-	usbhid_submit_report(pidff->hid, pidff->reports[PID_EFFECT_OPERATION],
-			  USB_DIR_OUT);
+	hid_hw_request(pidff->hid, pidff->reports[PID_EFFECT_OPERATION],
+			HID_REQ_SET_REPORT);
 }
 
 /**
@@ -535,8 +535,8 @@ static int pidff_playback(struct input_dev *dev, int effect_id, int value)
 static void pidff_erase_pid(struct pidff_device *pidff, int pid_id)
 {
 	pidff->block_free[PID_EFFECT_BLOCK_INDEX].value[0] = pid_id;
-	usbhid_submit_report(pidff->hid, pidff->reports[PID_BLOCK_FREE],
-			  USB_DIR_OUT);
+	hid_hw_request(pidff->hid, pidff->reports[PID_BLOCK_FREE],
+			HID_REQ_SET_REPORT);
 }
 
 /*
@@ -551,7 +551,7 @@ static int pidff_erase_effect(struct input_dev *dev, int effect_id)
 		effect_id, pidff->pid_id[effect_id]);
 	/* Wait for the queue to clear. We do not want a full fifo to
 	   prevent the effect removal. */
-	usbhid_wait_io(pidff->hid);
+	hid_hw_wait(pidff->hid);
 	pidff_playback_pid(pidff, pid_id, 0);
 	pidff_erase_pid(pidff, pid_id);
 
@@ -718,8 +718,8 @@ static void pidff_set_gain(struct input_dev *dev, u16 gain)
 	struct pidff_device *pidff = dev->ff->private;
 
 	pidff_set(&pidff->device_gain[PID_DEVICE_GAIN_FIELD], gain);
-	usbhid_submit_report(pidff->hid, pidff->reports[PID_DEVICE_GAIN],
-			  USB_DIR_OUT);
+	hid_hw_request(pidff->hid, pidff->reports[PID_DEVICE_GAIN],
+			HID_REQ_SET_REPORT);
 }
 
 static void pidff_autocenter(struct pidff_device *pidff, u16 magnitude)
@@ -744,8 +744,8 @@ static void pidff_autocenter(struct pidff_device *pidff, u16 magnitude)
 	pidff->set_effect[PID_DIRECTION_ENABLE].value[0] = 1;
 	pidff->set_effect[PID_START_DELAY].value[0] = 0;
 
-	usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_EFFECT],
-			  USB_DIR_OUT);
+	hid_hw_request(pidff->hid, pidff->reports[PID_SET_EFFECT],
+			HID_REQ_SET_REPORT);
 }
 
 /*
@@ -1158,19 +1158,19 @@ static void pidff_reset(struct pidff_device *pidff)
 
 	pidff->device_control->value[0] = pidff->control_id[PID_RESET];
 	/* We reset twice as sometimes hid_wait_io isn't waiting long enough */
-	usbhid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT);
-	usbhid_wait_io(hid);
-	usbhid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT);
-	usbhid_wait_io(hid);
+	hid_hw_request(hid, pidff->reports[PID_DEVICE_CONTROL], HID_REQ_SET_REPORT);
+	hid_hw_wait(hid);
+	hid_hw_request(hid, pidff->reports[PID_DEVICE_CONTROL], HID_REQ_SET_REPORT);
+	hid_hw_wait(hid);
 
 	pidff->device_control->value[0] =
 		pidff->control_id[PID_ENABLE_ACTUATORS];
-	usbhid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT);
-	usbhid_wait_io(hid);
+	hid_hw_request(hid, pidff->reports[PID_DEVICE_CONTROL], HID_REQ_SET_REPORT);
+	hid_hw_wait(hid);
 
 	/* pool report is sometimes messed up, refetch it */
-	usbhid_submit_report(hid, pidff->reports[PID_POOL], USB_DIR_IN);
-	usbhid_wait_io(hid);
+	hid_hw_request(hid, pidff->reports[PID_POOL], HID_REQ_GET_REPORT);
+	hid_hw_wait(hid);
 
 	if (pidff->pool[PID_SIMULTANEOUS_MAX].value) {
 		while (pidff->pool[PID_SIMULTANEOUS_MAX].value[0] < 2) {
@@ -1181,9 +1181,9 @@ static void pidff_reset(struct pidff_device *pidff)
 				break;
 			}
 			hid_dbg(pidff->hid, "pid_pool requested again\n");
-			usbhid_submit_report(hid, pidff->reports[PID_POOL],
-					  USB_DIR_IN);
-			usbhid_wait_io(hid);
+			hid_hw_request(hid, pidff->reports[PID_POOL],
+					  HID_REQ_GET_REPORT);
+			hid_hw_wait(hid);
 		}
 	}
 }
@@ -1269,8 +1269,8 @@ int hid_pidff_init(struct hid_device *hid)
 
 	if (test_bit(FF_GAIN, dev->ffbit)) {
 		pidff_set(&pidff->device_gain[PID_DEVICE_GAIN_FIELD], 0xffff);
-		usbhid_submit_report(hid, pidff->reports[PID_DEVICE_GAIN],
-				     USB_DIR_OUT);
+		hid_hw_request(hid, pidff->reports[PID_DEVICE_GAIN],
+				     HID_REQ_SET_REPORT);
 	}
 
 	error = pidff_check_autocenter(pidff, dev);
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c
index 87bd649..2f1ddca 100644
--- a/drivers/hid/usbhid/hiddev.c
+++ b/drivers/hid/usbhid/hiddev.c
@@ -705,8 +705,8 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 		if (report == NULL)
 			break;
 
-		usbhid_submit_report(hid, report, USB_DIR_IN);
-		usbhid_wait_io(hid);
+		hid_hw_request(hid, report, HID_REQ_GET_REPORT);
+		hid_hw_wait(hid);
 
 		r = 0;
 		break;
@@ -724,8 +724,8 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 		if (report == NULL)
 			break;
 
-		usbhid_submit_report(hid, report, USB_DIR_OUT);
-		usbhid_wait_io(hid);
+		hid_hw_request(hid, report, HID_REQ_SET_REPORT);
+		hid_hw_wait(hid);
 
 		r = 0;
 		break;
diff --git a/drivers/hid/usbhid/usbhid.h b/drivers/hid/usbhid/usbhid.h
index bd87a61..dbb6af6 100644
--- a/drivers/hid/usbhid/usbhid.h
+++ b/drivers/hid/usbhid/usbhid.h
@@ -34,12 +34,9 @@
 #include <linux/input.h>
 
 /*  API provided by hid-core.c for USB HID drivers */
-int usbhid_wait_io(struct hid_device* hid);
 void usbhid_close(struct hid_device *hid);
 int usbhid_open(struct hid_device *hid);
 void usbhid_init_reports(struct hid_device *hid);
-void usbhid_submit_report
-(struct hid_device *hid, struct hid_report *report, unsigned char dir);
 int usbhid_get_power(struct hid_device *hid);
 void usbhid_put_power(struct hid_device *hid);
 struct usb_interface *usbhid_find_interface(int minor);
diff --git a/drivers/hv/Kconfig b/drivers/hv/Kconfig
index 64630f1..0403b51 100644
--- a/drivers/hv/Kconfig
+++ b/drivers/hv/Kconfig
@@ -2,7 +2,7 @@ menu "Microsoft Hyper-V guest support"
 
 config HYPERV
 	tristate "Microsoft Hyper-V client drivers"
-	depends on X86 && ACPI && PCI && X86_LOCAL_APIC
+	depends on X86 && ACPI && PCI && X86_LOCAL_APIC && HYPERVISOR_GUEST
 	help
 	  Select this option to run Linux as a Hyper-V client operating
 	  system.
diff --git a/drivers/hv/Makefile b/drivers/hv/Makefile
index e6abfa0..0a74b56 100644
--- a/drivers/hv/Makefile
+++ b/drivers/hv/Makefile
@@ -5,4 +5,4 @@ obj-$(CONFIG_HYPERV_BALLOON)	+= hv_balloon.o
 hv_vmbus-y := vmbus_drv.o \
 		 hv.o connection.o channel.o \
 		 channel_mgmt.o ring_buffer.o
-hv_utils-y := hv_util.o hv_kvp.o
+hv_utils-y := hv_util.o hv_kvp.o hv_snapshot.o
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
index ff1be16..bad8128 100644
--- a/drivers/hv/channel_mgmt.c
+++ b/drivers/hv/channel_mgmt.c
@@ -165,8 +165,19 @@ static void vmbus_process_rescind_offer(struct work_struct *work)
 	struct vmbus_channel *channel = container_of(work,
 						     struct vmbus_channel,
 						     work);
+	unsigned long flags;
+	struct vmbus_channel_relid_released msg;
 
 	vmbus_device_unregister(channel->device_obj);
+	memset(&msg, 0, sizeof(struct vmbus_channel_relid_released));
+	msg.child_relid = channel->offermsg.child_relid;
+	msg.header.msgtype = CHANNELMSG_RELID_RELEASED;
+	vmbus_post_msg(&msg, sizeof(struct vmbus_channel_relid_released));
+
+	spin_lock_irqsave(&vmbus_connection.channel_lock, flags);
+	list_del(&channel->listentry);
+	spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags);
+	free_channel(channel);
 }
 
 void vmbus_free_channels(void)
diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c
index 7311589..ae49237 100644
--- a/drivers/hv/hv.c
+++ b/drivers/hv/hv.c
@@ -289,9 +289,8 @@ void hv_synic_init(void *arg)
 	/* Check the version */
 	rdmsrl(HV_X64_MSR_SVERSION, version);
 
-	hv_context.event_dpc[cpu] = (struct tasklet_struct *)
-					kmalloc(sizeof(struct tasklet_struct),
-						GFP_ATOMIC);
+	hv_context.event_dpc[cpu] = kmalloc(sizeof(struct tasklet_struct),
+					    GFP_ATOMIC);
 	if (hv_context.event_dpc[cpu] == NULL) {
 		pr_err("Unable to allocate event dpc\n");
 		goto cleanup;
diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c
index 3787321..4c605c7 100644
--- a/drivers/hv/hv_balloon.c
+++ b/drivers/hv/hv_balloon.c
@@ -117,7 +117,14 @@ union dm_caps {
 	struct {
 		__u64 balloon:1;
 		__u64 hot_add:1;
-		__u64 reservedz:62;
+		/*
+		 * To support guests that may have alignment
+		 * limitations on hot-add, the guest can specify
+		 * its alignment requirements; a value of n
+		 * represents an alignment of 2^n in mega bytes.
+		 */
+		__u64 hot_add_alignment:4;
+		__u64 reservedz:58;
 	} cap_bits;
 	__u64 caps;
 } __packed;
@@ -412,13 +419,45 @@ struct dm_info_msg {
  * End protocol definitions.
  */
 
-static bool hot_add;
+/*
+ * State to manage hot adding memory into the guest.
+ * The range start_pfn : end_pfn specifies the range
+ * that the host has asked us to hot add. The range
+ * start_pfn : ha_end_pfn specifies the range that we have
+ * currently hot added. We hot add in multiples of 128M
+ * chunks; it is possible that we may not be able to bring
+ * online all the pages in the region. The range
+ * covered_start_pfn : covered_end_pfn defines the pages that can
+ * be brough online.
+ */
+
+struct hv_hotadd_state {
+	struct list_head list;
+	unsigned long start_pfn;
+	unsigned long covered_start_pfn;
+	unsigned long covered_end_pfn;
+	unsigned long ha_end_pfn;
+	unsigned long end_pfn;
+};
+
+struct balloon_state {
+	__u32 num_pages;
+	struct work_struct wrk;
+};
+
+struct hot_add_wrk {
+	union dm_mem_page_range ha_page_range;
+	union dm_mem_page_range ha_region_range;
+	struct work_struct wrk;
+};
+
+static bool hot_add = true;
 static bool do_hot_add;
 /*
  * Delay reporting memory pressure by
  * the specified number of seconds.
  */
-static uint pressure_report_delay = 30;
+static uint pressure_report_delay = 45;
 
 module_param(hot_add, bool, (S_IRUGO | S_IWUSR));
 MODULE_PARM_DESC(hot_add, "If set attempt memory hot_add");
@@ -446,6 +485,7 @@ enum hv_dm_state {
 static __u8 recv_buffer[PAGE_SIZE];
 static __u8 *send_buffer;
 #define PAGES_IN_2M	512
+#define HA_CHUNK (32 * 1024)
 
 struct hv_dynmem_device {
 	struct hv_device *dev;
@@ -459,7 +499,28 @@ struct hv_dynmem_device {
 	unsigned int num_pages_ballooned;
 
 	/*
-	 * This thread handles both balloon/hot-add
+	 * State to manage the ballooning (up) operation.
+	 */
+	struct balloon_state balloon_wrk;
+
+	/*
+	 * State to execute the "hot-add" operation.
+	 */
+	struct hot_add_wrk ha_wrk;
+
+	/*
+	 * This state tracks if the host has specified a hot-add
+	 * region.
+	 */
+	bool host_specified_ha_region;
+
+	/*
+	 * State to synchronize hot-add.
+	 */
+	struct completion  ol_waitevent;
+	bool ha_waiting;
+	/*
+	 * This thread handles hot-add
 	 * requests from the host as well as notifying
 	 * the host with regards to memory pressure in
 	 * the guest.
@@ -467,6 +528,11 @@ struct hv_dynmem_device {
 	struct task_struct *thread;
 
 	/*
+	 * A list of hot-add regions.
+	 */
+	struct list_head ha_region_list;
+
+	/*
 	 * We start with the highest version we can support
 	 * and downgrade based on the host; we save here the
 	 * next version to try.
@@ -476,35 +542,358 @@ struct hv_dynmem_device {
 
 static struct hv_dynmem_device dm_device;
 
-static void hot_add_req(struct hv_dynmem_device *dm, struct dm_hot_add *msg)
+#ifdef CONFIG_MEMORY_HOTPLUG
+
+static void hv_bring_pgs_online(unsigned long start_pfn, unsigned long size)
 {
+	int i;
 
-	struct dm_hot_add_response resp;
+	for (i = 0; i < size; i++) {
+		struct page *pg;
+		pg = pfn_to_page(start_pfn + i);
+		__online_page_set_limits(pg);
+		__online_page_increment_counters(pg);
+		__online_page_free(pg);
+	}
+}
 
-	if (do_hot_add) {
+static void hv_mem_hot_add(unsigned long start, unsigned long size,
+				unsigned long pfn_count,
+				struct hv_hotadd_state *has)
+{
+	int ret = 0;
+	int i, nid, t;
+	unsigned long start_pfn;
+	unsigned long processed_pfn;
+	unsigned long total_pfn = pfn_count;
+
+	for (i = 0; i < (size/HA_CHUNK); i++) {
+		start_pfn = start + (i * HA_CHUNK);
+		has->ha_end_pfn +=  HA_CHUNK;
+
+		if (total_pfn > HA_CHUNK) {
+			processed_pfn = HA_CHUNK;
+			total_pfn -= HA_CHUNK;
+		} else {
+			processed_pfn = total_pfn;
+			total_pfn = 0;
+		}
+
+		has->covered_end_pfn +=  processed_pfn;
+
+		init_completion(&dm_device.ol_waitevent);
+		dm_device.ha_waiting = true;
+
+		nid = memory_add_physaddr_to_nid(PFN_PHYS(start_pfn));
+		ret = add_memory(nid, PFN_PHYS((start_pfn)),
+				(HA_CHUNK << PAGE_SHIFT));
 
-		pr_info("Memory hot add not supported\n");
+		if (ret) {
+			pr_info("hot_add memory failed error is %d\n", ret);
+			if (ret == -EEXIST) {
+				/*
+				 * This error indicates that the error
+				 * is not a transient failure. This is the
+				 * case where the guest's physical address map
+				 * precludes hot adding memory. Stop all further
+				 * memory hot-add.
+				 */
+				do_hot_add = false;
+			}
+			has->ha_end_pfn -= HA_CHUNK;
+			has->covered_end_pfn -=  processed_pfn;
+			break;
+		}
 
 		/*
-		 * Currently we do not support hot add.
-		 * Just fail the request.
+		 * Wait for the memory block to be onlined.
 		 */
+		t = wait_for_completion_timeout(&dm_device.ol_waitevent, 5*HZ);
+		if (t == 0) {
+			pr_info("hot_add memory timedout\n");
+			has->ha_end_pfn -= HA_CHUNK;
+			has->covered_end_pfn -=  processed_pfn;
+			break;
+		}
+
+	}
+
+	return;
+}
+
+static void hv_online_page(struct page *pg)
+{
+	struct list_head *cur;
+	struct hv_hotadd_state *has;
+	unsigned long cur_start_pgp;
+	unsigned long cur_end_pgp;
+
+	if (dm_device.ha_waiting) {
+		dm_device.ha_waiting = false;
+		complete(&dm_device.ol_waitevent);
+	}
+
+	list_for_each(cur, &dm_device.ha_region_list) {
+		has = list_entry(cur, struct hv_hotadd_state, list);
+		cur_start_pgp = (unsigned long)
+				pfn_to_page(has->covered_start_pfn);
+		cur_end_pgp = (unsigned long)pfn_to_page(has->covered_end_pfn);
+
+		if (((unsigned long)pg >= cur_start_pgp) &&
+			((unsigned long)pg < cur_end_pgp)) {
+			/*
+			 * This frame is currently backed; online the
+			 * page.
+			 */
+			__online_page_set_limits(pg);
+			__online_page_increment_counters(pg);
+			__online_page_free(pg);
+			has->covered_start_pfn++;
+		}
+	}
+}
+
+static bool pfn_covered(unsigned long start_pfn, unsigned long pfn_cnt)
+{
+	struct list_head *cur;
+	struct hv_hotadd_state *has;
+	unsigned long residual, new_inc;
+
+	if (list_empty(&dm_device.ha_region_list))
+		return false;
+
+	list_for_each(cur, &dm_device.ha_region_list) {
+		has = list_entry(cur, struct hv_hotadd_state, list);
+
+		/*
+		 * If the pfn range we are dealing with is not in the current
+		 * "hot add block", move on.
+		 */
+		if ((start_pfn >= has->end_pfn))
+			continue;
+		/*
+		 * If the current hot add-request extends beyond
+		 * our current limit; extend it.
+		 */
+		if ((start_pfn + pfn_cnt) > has->end_pfn) {
+			residual = (start_pfn + pfn_cnt - has->end_pfn);
+			/*
+			 * Extend the region by multiples of HA_CHUNK.
+			 */
+			new_inc = (residual / HA_CHUNK) * HA_CHUNK;
+			if (residual % HA_CHUNK)
+				new_inc += HA_CHUNK;
+
+			has->end_pfn += new_inc;
+		}
+
+		/*
+		 * If the current start pfn is not where the covered_end
+		 * is, update it.
+		 */
+
+		if (has->covered_end_pfn != start_pfn) {
+			has->covered_end_pfn = start_pfn;
+			has->covered_start_pfn = start_pfn;
+		}
+		return true;
+
 	}
 
+	return false;
+}
+
+static unsigned long handle_pg_range(unsigned long pg_start,
+					unsigned long pg_count)
+{
+	unsigned long start_pfn = pg_start;
+	unsigned long pfn_cnt = pg_count;
+	unsigned long size;
+	struct list_head *cur;
+	struct hv_hotadd_state *has;
+	unsigned long pgs_ol = 0;
+	unsigned long old_covered_state;
+
+	if (list_empty(&dm_device.ha_region_list))
+		return 0;
+
+	list_for_each(cur, &dm_device.ha_region_list) {
+		has = list_entry(cur, struct hv_hotadd_state, list);
+
+		/*
+		 * If the pfn range we are dealing with is not in the current
+		 * "hot add block", move on.
+		 */
+		if ((start_pfn >= has->end_pfn))
+			continue;
+
+		old_covered_state = has->covered_end_pfn;
+
+		if (start_pfn < has->ha_end_pfn) {
+			/*
+			 * This is the case where we are backing pages
+			 * in an already hot added region. Bring
+			 * these pages online first.
+			 */
+			pgs_ol = has->ha_end_pfn - start_pfn;
+			if (pgs_ol > pfn_cnt)
+				pgs_ol = pfn_cnt;
+			hv_bring_pgs_online(start_pfn, pgs_ol);
+			has->covered_end_pfn +=  pgs_ol;
+			has->covered_start_pfn +=  pgs_ol;
+			pfn_cnt -= pgs_ol;
+		}
+
+		if ((has->ha_end_pfn < has->end_pfn) && (pfn_cnt > 0)) {
+			/*
+			 * We have some residual hot add range
+			 * that needs to be hot added; hot add
+			 * it now. Hot add a multiple of
+			 * of HA_CHUNK that fully covers the pages
+			 * we have.
+			 */
+			size = (has->end_pfn - has->ha_end_pfn);
+			if (pfn_cnt <= size) {
+				size = ((pfn_cnt / HA_CHUNK) * HA_CHUNK);
+				if (pfn_cnt % HA_CHUNK)
+					size += HA_CHUNK;
+			} else {
+				pfn_cnt = size;
+			}
+			hv_mem_hot_add(has->ha_end_pfn, size, pfn_cnt, has);
+		}
+		/*
+		 * If we managed to online any pages that were given to us,
+		 * we declare success.
+		 */
+		return has->covered_end_pfn - old_covered_state;
+
+	}
+
+	return 0;
+}
+
+static unsigned long process_hot_add(unsigned long pg_start,
+					unsigned long pfn_cnt,
+					unsigned long rg_start,
+					unsigned long rg_size)
+{
+	struct hv_hotadd_state *ha_region = NULL;
+
+	if (pfn_cnt == 0)
+		return 0;
+
+	if (!dm_device.host_specified_ha_region)
+		if (pfn_covered(pg_start, pfn_cnt))
+			goto do_pg_range;
+
+	/*
+	 * If the host has specified a hot-add range; deal with it first.
+	 */
+
+	if (rg_size != 0) {
+		ha_region = kzalloc(sizeof(struct hv_hotadd_state), GFP_KERNEL);
+		if (!ha_region)
+			return 0;
+
+		INIT_LIST_HEAD(&ha_region->list);
+
+		list_add_tail(&ha_region->list, &dm_device.ha_region_list);
+		ha_region->start_pfn = rg_start;
+		ha_region->ha_end_pfn = rg_start;
+		ha_region->covered_start_pfn = pg_start;
+		ha_region->covered_end_pfn = pg_start;
+		ha_region->end_pfn = rg_start + rg_size;
+	}
+
+do_pg_range:
+	/*
+	 * Process the page range specified; bringing them
+	 * online if possible.
+	 */
+	return handle_pg_range(pg_start, pfn_cnt);
+}
+
+#endif
+
+static void hot_add_req(struct work_struct *dummy)
+{
+	struct dm_hot_add_response resp;
+#ifdef CONFIG_MEMORY_HOTPLUG
+	unsigned long pg_start, pfn_cnt;
+	unsigned long rg_start, rg_sz;
+#endif
+	struct hv_dynmem_device *dm = &dm_device;
+
 	memset(&resp, 0, sizeof(struct dm_hot_add_response));
 	resp.hdr.type = DM_MEM_HOT_ADD_RESPONSE;
 	resp.hdr.size = sizeof(struct dm_hot_add_response);
 	resp.hdr.trans_id = atomic_inc_return(&trans_id);
 
-	resp.page_count = 0;
-	resp.result = 0;
+#ifdef CONFIG_MEMORY_HOTPLUG
+	pg_start = dm->ha_wrk.ha_page_range.finfo.start_page;
+	pfn_cnt = dm->ha_wrk.ha_page_range.finfo.page_cnt;
+
+	rg_start = dm->ha_wrk.ha_region_range.finfo.start_page;
+	rg_sz = dm->ha_wrk.ha_region_range.finfo.page_cnt;
+
+	if ((rg_start == 0) && (!dm->host_specified_ha_region)) {
+		unsigned long region_size;
+		unsigned long region_start;
+
+		/*
+		 * The host has not specified the hot-add region.
+		 * Based on the hot-add page range being specified,
+		 * compute a hot-add region that can cover the pages
+		 * that need to be hot-added while ensuring the alignment
+		 * and size requirements of Linux as it relates to hot-add.
+		 */
+		region_start = pg_start;
+		region_size = (pfn_cnt / HA_CHUNK) * HA_CHUNK;
+		if (pfn_cnt % HA_CHUNK)
+			region_size += HA_CHUNK;
+
+		region_start = (pg_start / HA_CHUNK) * HA_CHUNK;
+
+		rg_start = region_start;
+		rg_sz = region_size;
+	}
+
+	if (do_hot_add)
+		resp.page_count = process_hot_add(pg_start, pfn_cnt,
+						rg_start, rg_sz);
+#endif
+	/*
+	 * The result field of the response structure has the
+	 * following semantics:
+	 *
+	 * 1. If all or some pages hot-added: Guest should return success.
+	 *
+	 * 2. If no pages could be hot-added:
+	 *
+	 * If the guest returns success, then the host
+	 * will not attempt any further hot-add operations. This
+	 * signifies a permanent failure.
+	 *
+	 * If the guest returns failure, then this failure will be
+	 * treated as a transient failure and the host may retry the
+	 * hot-add operation after some delay.
+	 */
+	if (resp.page_count > 0)
+		resp.result = 1;
+	else if (!do_hot_add)
+		resp.result = 1;
+	else
+		resp.result = 0;
+
+	if (!do_hot_add || (resp.page_count == 0))
+		pr_info("Memory hot add failed\n");
 
 	dm->state = DM_INITIALIZED;
 	vmbus_sendpacket(dm->dev->channel, &resp,
 			sizeof(struct dm_hot_add_response),
 			(unsigned long)NULL,
 			VM_PKT_DATA_INBAND, 0);
-
 }
 
 static void process_info(struct hv_dynmem_device *dm, struct dm_info_msg *msg)
@@ -523,7 +912,7 @@ static void process_info(struct hv_dynmem_device *dm, struct dm_info_msg *msg)
 	}
 }
 
-unsigned long compute_balloon_floor(void)
+static unsigned long compute_balloon_floor(void)
 {
 	unsigned long min_pages;
 #define MB2PAGES(mb) ((mb) << (20 - PAGE_SHIFT))
@@ -644,6 +1033,14 @@ static int  alloc_balloon_pages(struct hv_dynmem_device *dm, int num_pages,
 
 		dm->num_pages_ballooned += alloc_unit;
 
+		/*
+		 * If we allocatted 2M pages; split them so we
+		 * can free them in any order we get.
+		 */
+
+		if (alloc_unit != 1)
+			split_page(pg, get_order(alloc_unit << PAGE_SHIFT));
+
 		bl_resp->range_count++;
 		bl_resp->range_array[i].finfo.start_page =
 			page_to_pfn(pg);
@@ -657,9 +1054,9 @@ static int  alloc_balloon_pages(struct hv_dynmem_device *dm, int num_pages,
 
 
 
-static void balloon_up(struct hv_dynmem_device *dm, struct dm_balloon *req)
+static void balloon_up(struct work_struct *dummy)
 {
-	int num_pages = req->num_pages;
+	int num_pages = dm_device.balloon_wrk.num_pages;
 	int num_ballooned = 0;
 	struct dm_balloon_response *bl_resp;
 	int alloc_unit;
@@ -670,9 +1067,10 @@ static void balloon_up(struct hv_dynmem_device *dm, struct dm_balloon *req)
 
 
 	/*
-	 * Currently, we only support 4k allocations.
+	 * We will attempt 2M allocations. However, if we fail to
+	 * allocate 2M chunks, we will go back to 4k allocations.
 	 */
-	alloc_unit = 1;
+	alloc_unit = 512;
 
 	while (!done) {
 		bl_resp = (struct dm_balloon_response *)send_buffer;
@@ -684,14 +1082,19 @@ static void balloon_up(struct hv_dynmem_device *dm, struct dm_balloon *req)
 
 
 		num_pages -= num_ballooned;
-		num_ballooned = alloc_balloon_pages(dm, num_pages,
+		num_ballooned = alloc_balloon_pages(&dm_device, num_pages,
 						bl_resp, alloc_unit,
 						 &alloc_error);
 
+		if ((alloc_error) && (alloc_unit != 1)) {
+			alloc_unit = 1;
+			continue;
+		}
+
 		if ((alloc_error) || (num_ballooned == num_pages)) {
 			bl_resp->more_pages = 0;
 			done = true;
-			dm->state = DM_INITIALIZED;
+			dm_device.state = DM_INITIALIZED;
 		}
 
 		/*
@@ -719,7 +1122,7 @@ static void balloon_up(struct hv_dynmem_device *dm, struct dm_balloon *req)
 			pr_info("Balloon response failed\n");
 
 			for (i = 0; i < bl_resp->range_count; i++)
-				free_balloon_pages(dm,
+				free_balloon_pages(&dm_device,
 						 &bl_resp->range_array[i]);
 
 			done = true;
@@ -761,7 +1164,6 @@ static int dm_thread_func(void *dm_dev)
 {
 	struct hv_dynmem_device *dm = dm_dev;
 	int t;
-	unsigned long  scan_start;
 
 	while (!kthread_should_stop()) {
 		t = wait_for_completion_timeout(&dm_device.config_event, 1*HZ);
@@ -773,22 +1175,6 @@ static int dm_thread_func(void *dm_dev)
 		if (t == 0)
 			post_status(dm);
 
-		scan_start = jiffies;
-		switch (dm->state) {
-		case DM_BALLOON_UP:
-			balloon_up(dm, (struct dm_balloon *)recv_buffer);
-			break;
-
-		case DM_HOT_ADD:
-			hot_add_req(dm, (struct dm_hot_add *)recv_buffer);
-			break;
-		default:
-			break;
-		}
-
-		if (!time_in_range(jiffies, scan_start, scan_start + HZ))
-			post_status(dm);
-
 	}
 
 	return 0;
@@ -861,6 +1247,10 @@ static void balloon_onchannelcallback(void *context)
 	struct dm_message *dm_msg;
 	struct dm_header *dm_hdr;
 	struct hv_dynmem_device *dm = hv_get_drvdata(dev);
+	struct dm_balloon *bal_msg;
+	struct dm_hot_add *ha_msg;
+	union dm_mem_page_range *ha_pg_range;
+	union dm_mem_page_range *ha_region;
 
 	memset(recv_buffer, 0, sizeof(recv_buffer));
 	vmbus_recvpacket(dev->channel, recv_buffer,
@@ -882,8 +1272,12 @@ static void balloon_onchannelcallback(void *context)
 			break;
 
 		case DM_BALLOON_REQUEST:
+			if (dm->state == DM_BALLOON_UP)
+				pr_warn("Currently ballooning\n");
+			bal_msg = (struct dm_balloon *)recv_buffer;
 			dm->state = DM_BALLOON_UP;
-			complete(&dm->config_event);
+			dm_device.balloon_wrk.num_pages = bal_msg->num_pages;
+			schedule_work(&dm_device.balloon_wrk.wrk);
 			break;
 
 		case DM_UNBALLOON_REQUEST:
@@ -893,8 +1287,31 @@ static void balloon_onchannelcallback(void *context)
 			break;
 
 		case DM_MEM_HOT_ADD_REQUEST:
+			if (dm->state == DM_HOT_ADD)
+				pr_warn("Currently hot-adding\n");
 			dm->state = DM_HOT_ADD;
-			complete(&dm->config_event);
+			ha_msg = (struct dm_hot_add *)recv_buffer;
+			if (ha_msg->hdr.size == sizeof(struct dm_hot_add)) {
+				/*
+				 * This is a normal hot-add request specifying
+				 * hot-add memory.
+				 */
+				ha_pg_range = &ha_msg->range;
+				dm->ha_wrk.ha_page_range = *ha_pg_range;
+				dm->ha_wrk.ha_region_range.page_range = 0;
+			} else {
+				/*
+				 * Host is specifying that we first hot-add
+				 * a region and then partially populate this
+				 * region.
+				 */
+				dm->host_specified_ha_region = true;
+				ha_pg_range = &ha_msg->range;
+				ha_region = &ha_pg_range[1];
+				dm->ha_wrk.ha_page_range = *ha_pg_range;
+				dm->ha_wrk.ha_region_range = *ha_region;
+			}
+			schedule_work(&dm_device.ha_wrk.wrk);
 			break;
 
 		case DM_INFO_MESSAGE:
@@ -937,6 +1354,10 @@ static int balloon_probe(struct hv_device *dev,
 	dm_device.next_version = DYNMEM_PROTOCOL_VERSION_WIN7;
 	init_completion(&dm_device.host_event);
 	init_completion(&dm_device.config_event);
+	INIT_LIST_HEAD(&dm_device.ha_region_list);
+	INIT_WORK(&dm_device.balloon_wrk.wrk, balloon_up);
+	INIT_WORK(&dm_device.ha_wrk.wrk, hot_add_req);
+	dm_device.host_specified_ha_region = false;
 
 	dm_device.thread =
 		 kthread_run(dm_thread_func, &dm_device, "hv_balloon");
@@ -945,6 +1366,10 @@ static int balloon_probe(struct hv_device *dev,
 		goto probe_error1;
 	}
 
+#ifdef CONFIG_MEMORY_HOTPLUG
+	set_online_page_callback(&hv_online_page);
+#endif
+
 	hv_set_drvdata(dev, &dm_device);
 	/*
 	 * Initiate the hand shake with the host and negotiate
@@ -962,8 +1387,7 @@ static int balloon_probe(struct hv_device *dev,
 	ret = vmbus_sendpacket(dev->channel, &version_req,
 				sizeof(struct dm_version_request),
 				(unsigned long)NULL,
-				VM_PKT_DATA_INBAND,
-				VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+				VM_PKT_DATA_INBAND, 0);
 	if (ret)
 		goto probe_error2;
 
@@ -990,13 +1414,13 @@ static int balloon_probe(struct hv_device *dev,
 	cap_msg.hdr.trans_id = atomic_inc_return(&trans_id);
 
 	cap_msg.caps.cap_bits.balloon = 1;
+	cap_msg.caps.cap_bits.hot_add = 1;
+
 	/*
-	 * While we currently don't support hot-add,
-	 * we still advertise this capability since the
-	 * host requires that guests partcipating in the
-	 * dynamic memory protocol support hot add.
+	 * Specify our alignment requirements as it relates
+	 * memory hot-add. Specify 128MB alignment.
 	 */
-	cap_msg.caps.cap_bits.hot_add = 1;
+	cap_msg.caps.cap_bits.hot_add_alignment = 7;
 
 	/*
 	 * Currently the host does not use these
@@ -1009,8 +1433,7 @@ static int balloon_probe(struct hv_device *dev,
 	ret = vmbus_sendpacket(dev->channel, &cap_msg,
 				sizeof(struct dm_capabilities),
 				(unsigned long)NULL,
-				VM_PKT_DATA_INBAND,
-				VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+				VM_PKT_DATA_INBAND, 0);
 	if (ret)
 		goto probe_error2;
 
@@ -1034,6 +1457,9 @@ static int balloon_probe(struct hv_device *dev,
 	return 0;
 
 probe_error2:
+#ifdef CONFIG_MEMORY_HOTPLUG
+	restore_online_page_callback(&hv_online_page);
+#endif
 	kthread_stop(dm_device.thread);
 
 probe_error1:
@@ -1046,13 +1472,26 @@ probe_error0:
 static int balloon_remove(struct hv_device *dev)
 {
 	struct hv_dynmem_device *dm = hv_get_drvdata(dev);
+	struct list_head *cur, *tmp;
+	struct hv_hotadd_state *has;
 
 	if (dm->num_pages_ballooned != 0)
 		pr_warn("Ballooned pages: %d\n", dm->num_pages_ballooned);
 
+	cancel_work_sync(&dm->balloon_wrk.wrk);
+	cancel_work_sync(&dm->ha_wrk.wrk);
+
 	vmbus_close(dev->channel);
 	kthread_stop(dm->thread);
 	kfree(send_buffer);
+#ifdef CONFIG_MEMORY_HOTPLUG
+	restore_online_page_callback(&hv_online_page);
+#endif
+	list_for_each_safe(cur, tmp, &dm->ha_region_list) {
+		has = list_entry(cur, struct hv_hotadd_state, list);
+		list_del(&has->list);
+		kfree(has);
+	}
 
 	return 0;
 }
@@ -1079,14 +1518,7 @@ static int __init init_balloon_drv(void)
 	return vmbus_driver_register(&balloon_drv);
 }
 
-static void exit_balloon_drv(void)
-{
-
-	vmbus_driver_unregister(&balloon_drv);
-}
-
 module_init(init_balloon_drv);
-module_exit(exit_balloon_drv);
 
 MODULE_DESCRIPTION("Hyper-V Balloon");
 MODULE_VERSION(HV_DRV_VERSION);
diff --git a/drivers/hv/hv_snapshot.c b/drivers/hv/hv_snapshot.c
new file mode 100644
index 0000000..8ad5653
--- /dev/null
+++ b/drivers/hv/hv_snapshot.c
@@ -0,0 +1,287 @@
+/*
+ * An implementation of host initiated guest snapshot.
+ *
+ *
+ * Copyright (C) 2013, Microsoft, Inc.
+ * Author : K. Y. Srinivasan <kys@microsoft.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, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/net.h>
+#include <linux/nls.h>
+#include <linux/connector.h>
+#include <linux/workqueue.h>
+#include <linux/hyperv.h>
+
+
+
+/*
+ * Global state maintained for transaction that is being processed.
+ * Note that only one transaction can be active at any point in time.
+ *
+ * This state is set when we receive a request from the host; we
+ * cleanup this state when the transaction is completed - when we respond
+ * to the host with the key value.
+ */
+
+static struct {
+	bool active; /* transaction status - active or not */
+	int recv_len; /* number of bytes received. */
+	struct vmbus_channel *recv_channel; /* chn we got the request */
+	u64 recv_req_id; /* request ID. */
+	struct hv_vss_msg  *msg; /* current message */
+} vss_transaction;
+
+
+static void vss_respond_to_host(int error);
+
+static struct cb_id vss_id = { CN_VSS_IDX, CN_VSS_VAL };
+static const char vss_name[] = "vss_kernel_module";
+static __u8 *recv_buffer;
+
+static void vss_send_op(struct work_struct *dummy);
+static DECLARE_WORK(vss_send_op_work, vss_send_op);
+
+/*
+ * Callback when data is received from user mode.
+ */
+
+static void
+vss_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
+{
+	struct hv_vss_msg *vss_msg;
+
+	vss_msg = (struct hv_vss_msg *)msg->data;
+
+	if (vss_msg->vss_hdr.operation == VSS_OP_REGISTER) {
+		pr_info("VSS daemon registered\n");
+		vss_transaction.active = false;
+		if (vss_transaction.recv_channel != NULL)
+			hv_vss_onchannelcallback(vss_transaction.recv_channel);
+		return;
+
+	}
+	vss_respond_to_host(vss_msg->error);
+}
+
+
+static void vss_send_op(struct work_struct *dummy)
+{
+	int op = vss_transaction.msg->vss_hdr.operation;
+	struct cn_msg *msg;
+	struct hv_vss_msg *vss_msg;
+
+	msg = kzalloc(sizeof(*msg) + sizeof(*vss_msg), GFP_ATOMIC);
+	if (!msg)
+		return;
+
+	vss_msg = (struct hv_vss_msg *)msg->data;
+
+	msg->id.idx =  CN_VSS_IDX;
+	msg->id.val = CN_VSS_VAL;
+
+	vss_msg->vss_hdr.operation = op;
+	msg->len = sizeof(struct hv_vss_msg);
+
+	cn_netlink_send(msg, 0, GFP_ATOMIC);
+	kfree(msg);
+
+	return;
+}
+
+/*
+ * Send a response back to the host.
+ */
+
+static void
+vss_respond_to_host(int error)
+{
+	struct icmsg_hdr *icmsghdrp;
+	u32	buf_len;
+	struct vmbus_channel *channel;
+	u64	req_id;
+
+	/*
+	 * If a transaction is not active; log and return.
+	 */
+
+	if (!vss_transaction.active) {
+		/*
+		 * This is a spurious call!
+		 */
+		pr_warn("VSS: Transaction not active\n");
+		return;
+	}
+	/*
+	 * Copy the global state for completing the transaction. Note that
+	 * only one transaction can be active at a time.
+	 */
+
+	buf_len = vss_transaction.recv_len;
+	channel = vss_transaction.recv_channel;
+	req_id = vss_transaction.recv_req_id;
+	vss_transaction.active = false;
+
+	icmsghdrp = (struct icmsg_hdr *)
+			&recv_buffer[sizeof(struct vmbuspipe_hdr)];
+
+	if (channel->onchannel_callback == NULL)
+		/*
+		 * We have raced with util driver being unloaded;
+		 * silently return.
+		 */
+		return;
+
+	icmsghdrp->status = error;
+
+	icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION | ICMSGHDRFLAG_RESPONSE;
+
+	vmbus_sendpacket(channel, recv_buffer, buf_len, req_id,
+				VM_PKT_DATA_INBAND, 0);
+
+}
+
+/*
+ * This callback is invoked when we get a VSS message from the host.
+ * The host ensures that only one VSS transaction can be active at a time.
+ */
+
+void hv_vss_onchannelcallback(void *context)
+{
+	struct vmbus_channel *channel = context;
+	u32 recvlen;
+	u64 requestid;
+	struct hv_vss_msg *vss_msg;
+
+
+	struct icmsg_hdr *icmsghdrp;
+	struct icmsg_negotiate *negop = NULL;
+
+	if (vss_transaction.active) {
+		/*
+		 * We will defer processing this callback once
+		 * the current transaction is complete.
+		 */
+		vss_transaction.recv_channel = channel;
+		return;
+	}
+
+	vmbus_recvpacket(channel, recv_buffer, PAGE_SIZE * 2, &recvlen,
+			 &requestid);
+
+	if (recvlen > 0) {
+		icmsghdrp = (struct icmsg_hdr *)&recv_buffer[
+			sizeof(struct vmbuspipe_hdr)];
+
+		if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
+			vmbus_prep_negotiate_resp(icmsghdrp, negop,
+				 recv_buffer, MAX_SRV_VER, MAX_SRV_VER);
+			/*
+			 * We currently negotiate the highest number the
+			 * host has presented. If this version is not
+			 * atleast 5.0, reject.
+			 */
+			negop = (struct icmsg_negotiate *)&recv_buffer[
+				sizeof(struct vmbuspipe_hdr) +
+				sizeof(struct icmsg_hdr)];
+
+			if (negop->icversion_data[1].major < 5)
+				negop->icframe_vercnt = 0;
+		} else {
+			vss_msg = (struct hv_vss_msg *)&recv_buffer[
+				sizeof(struct vmbuspipe_hdr) +
+				sizeof(struct icmsg_hdr)];
+
+			/*
+			 * Stash away this global state for completing the
+			 * transaction; note transactions are serialized.
+			 */
+
+			vss_transaction.recv_len = recvlen;
+			vss_transaction.recv_channel = channel;
+			vss_transaction.recv_req_id = requestid;
+			vss_transaction.active = true;
+			vss_transaction.msg = (struct hv_vss_msg *)vss_msg;
+
+			switch (vss_msg->vss_hdr.operation) {
+				/*
+				 * Initiate a "freeze/thaw"
+				 * operation in the guest.
+				 * We respond to the host once
+				 * the operation is complete.
+				 *
+				 * We send the message to the
+				 * user space daemon and the
+				 * operation is performed in
+				 * the daemon.
+				 */
+			case VSS_OP_FREEZE:
+			case VSS_OP_THAW:
+				schedule_work(&vss_send_op_work);
+				return;
+
+			case VSS_OP_HOT_BACKUP:
+				vss_msg->vss_cf.flags =
+					 VSS_HBU_NO_AUTO_RECOVERY;
+				vss_respond_to_host(0);
+				return;
+
+			case VSS_OP_GET_DM_INFO:
+				vss_msg->dm_info.flags = 0;
+				vss_respond_to_host(0);
+				return;
+
+			default:
+				vss_respond_to_host(0);
+				return;
+
+			}
+
+		}
+
+		icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
+			| ICMSGHDRFLAG_RESPONSE;
+
+		vmbus_sendpacket(channel, recv_buffer,
+				       recvlen, requestid,
+				       VM_PKT_DATA_INBAND, 0);
+	}
+
+}
+
+int
+hv_vss_init(struct hv_util_service *srv)
+{
+	int err;
+
+	err = cn_add_callback(&vss_id, vss_name, vss_cn_callback);
+	if (err)
+		return err;
+	recv_buffer = srv->recv_buffer;
+
+	/*
+	 * When this driver loads, the user level daemon that
+	 * processes the host requests may not yet be running.
+	 * Defer processing channel callbacks until the daemon
+	 * has registered.
+	 */
+	vss_transaction.active = true;
+	return 0;
+}
+
+void hv_vss_deinit(void)
+{
+	cn_del_callback(&vss_id);
+	cancel_work_sync(&vss_send_op_work);
+}
diff --git a/drivers/hv/hv_util.c b/drivers/hv/hv_util.c
index 1d4cbd8..2f561c5 100644
--- a/drivers/hv/hv_util.c
+++ b/drivers/hv/hv_util.c
@@ -49,6 +49,12 @@ static struct hv_util_service util_kvp = {
 	.util_deinit = hv_kvp_deinit,
 };
 
+static struct hv_util_service util_vss = {
+	.util_cb = hv_vss_onchannelcallback,
+	.util_init = hv_vss_init,
+	.util_deinit = hv_vss_deinit,
+};
+
 static void perform_shutdown(struct work_struct *dummy)
 {
 	orderly_poweroff(true);
@@ -339,6 +345,10 @@ static const struct hv_vmbus_device_id id_table[] = {
 	{ HV_KVP_GUID,
 	  .driver_data = (unsigned long)&util_kvp
 	},
+	/* VSS GUID */
+	{ HV_VSS_GUID,
+	  .driver_data = (unsigned long)&util_vss
+	},
 	{ },
 };
 
diff --git a/drivers/hv/ring_buffer.c b/drivers/hv/ring_buffer.c
index cafa72f..d6fbb577 100644
--- a/drivers/hv/ring_buffer.c
+++ b/drivers/hv/ring_buffer.c
@@ -71,6 +71,7 @@ u32 hv_end_read(struct hv_ring_buffer_info *rbi)
 
 static bool hv_need_to_signal(u32 old_write, struct hv_ring_buffer_info *rbi)
 {
+	smp_mb();
 	if (rbi->ring_buffer->interrupt_mask)
 		return false;
 
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 89ac1cb..da93094 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -179,9 +179,29 @@ config SENSORS_ADM9240
 	  This driver can also be built as a module.  If so, the module
 	  will be called adm9240.
 
+config SENSORS_ADT7X10
+	tristate
+	help
+	  This module contains common code shared by the ADT7310/ADT7320 and
+	  ADT7410/ADT7420 temperature monitoring chip drivers.
+
+	  If build as a module, the module will be called adt7x10.
+
+config SENSORS_ADT7310
+	tristate "Analog Devices ADT7310/ADT7320"
+	depends on SPI_MASTER
+	select SENSORS_ADT7X10
+	help
+	  If you say yes here you get support for the Analog Devices
+	  ADT7310 and ADT7320 temperature monitoring chips.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called adt7310.
+
 config SENSORS_ADT7410
 	tristate "Analog Devices ADT7410/ADT7420"
 	depends on I2C
+	select SENSORS_ADT7X10
 	help
 	  If you say yes here you get support for the Analog Devices
 	  ADT7410 and ADT7420 temperature monitoring chips.
@@ -499,6 +519,15 @@ config SENSORS_IBMPEX
 	  This driver can also be built as a module.  If so, the module
 	  will be called ibmpex.
 
+config SENSORS_IIO_HWMON
+	tristate "Hwmon driver that uses channels specified via iio maps"
+	depends on IIO
+	help
+	  This is a platform driver that in combination with a suitable
+	  map allows IIO devices to provide basic hwmon functionality
+	  for those channels specified in the map.  This map can be provided
+	  either via platform data or the device tree bindings.
+
 config SENSORS_IT87
 	tristate "ITE IT87xx and compatibles"
 	depends on !PPC
@@ -588,7 +617,7 @@ config SENSORS_LM75
 	  temperature sensor chip, with models including:
 
 		- Analog Devices ADT75
-		- Dallas Semiconductor DS75 and DS1775
+		- Dallas Semiconductor DS75, DS1775 and DS7505
 		- Maxim MAX6625 and MAX6626
 		- Microchip MCP980x
 		- National Semiconductor LM75, LM75A
@@ -751,6 +780,16 @@ config SENSORS_LTC4261
 	  This driver can also be built as a module. If so, the module will
 	  be called ltc4261.
 
+config SENSORS_LM95234
+	tristate "National Semiconductor LM95234"
+	depends on I2C
+	help
+	  If you say yes here you get support for the LM95234 temperature
+	  sensor.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called lm95234.
+
 config SENSORS_LM95241
 	tristate "National Semiconductor LM95241 and compatibles"
 	depends on I2C
@@ -877,8 +916,22 @@ config SENSORS_MCP3021
 	  This driver can also be built as a module.  If so, the module
 	  will be called mcp3021.
 
+config SENSORS_NCT6775
+	tristate "Nuvoton NCT6775F and compatibles"
+	depends on !PPC
+	select HWMON_VID
+	help
+	  If you say yes here you get support for the hardware monitoring
+	  functionality of the Nuvoton NCT6775F, NCT6776F, NCT6779D
+	  and compatible Super-I/O chips. This driver replaces the
+	  w83627ehf driver for NCT6775F and NCT6776F.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called nct6775.
+
 config SENSORS_NTC_THERMISTOR
 	tristate "NTC thermistor support"
+	depends on (!OF && !IIO) || (OF && IIO)
 	help
 	  This driver supports NTC thermistors sensor reading and its
 	  interpretation. The driver can also monitor the temperature and
@@ -1204,8 +1257,8 @@ config SENSORS_TMP401
 	tristate "Texas Instruments TMP401 and compatibles"
 	depends on I2C
 	help
-	  If you say yes here you get support for Texas Instruments TMP401 and
-	  TMP411 temperature sensor chips.
+	  If you say yes here you get support for Texas Instruments TMP401,
+	  TMP411, and TMP431 temperature sensor chips.
 
 	  This driver can also be built as a module.  If so, the module
 	  will be called tmp401.
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 8d6d97e..c51b0dc 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -34,6 +34,8 @@ obj-$(CONFIG_SENSORS_ADM9240)	+= adm9240.o
 obj-$(CONFIG_SENSORS_ADS1015)	+= ads1015.o
 obj-$(CONFIG_SENSORS_ADS7828)	+= ads7828.o
 obj-$(CONFIG_SENSORS_ADS7871)	+= ads7871.o
+obj-$(CONFIG_SENSORS_ADT7X10)	+= adt7x10.o
+obj-$(CONFIG_SENSORS_ADT7310)	+= adt7310.o
 obj-$(CONFIG_SENSORS_ADT7410)	+= adt7410.o
 obj-$(CONFIG_SENSORS_ADT7411)	+= adt7411.o
 obj-$(CONFIG_SENSORS_ADT7462)	+= adt7462.o
@@ -65,6 +67,7 @@ obj-$(CONFIG_SENSORS_ULTRA45)	+= ultra45_env.o
 obj-$(CONFIG_SENSORS_I5K_AMB)	+= i5k_amb.o
 obj-$(CONFIG_SENSORS_IBMAEM)	+= ibmaem.o
 obj-$(CONFIG_SENSORS_IBMPEX)	+= ibmpex.o
+obj-$(CONFIG_SENSORS_IIO_HWMON) += iio_hwmon.o
 obj-$(CONFIG_SENSORS_INA209)	+= ina209.o
 obj-$(CONFIG_SENSORS_INA2XX)	+= ina2xx.o
 obj-$(CONFIG_SENSORS_IT87)	+= it87.o
@@ -86,6 +89,7 @@ obj-$(CONFIG_SENSORS_LM87)	+= lm87.o
 obj-$(CONFIG_SENSORS_LM90)	+= lm90.o
 obj-$(CONFIG_SENSORS_LM92)	+= lm92.o
 obj-$(CONFIG_SENSORS_LM93)	+= lm93.o
+obj-$(CONFIG_SENSORS_LM95234)	+= lm95234.o
 obj-$(CONFIG_SENSORS_LM95241)	+= lm95241.o
 obj-$(CONFIG_SENSORS_LM95245)	+= lm95245.o
 obj-$(CONFIG_SENSORS_LTC4151)	+= ltc4151.o
@@ -103,6 +107,7 @@ obj-$(CONFIG_SENSORS_MAX6650)	+= max6650.o
 obj-$(CONFIG_SENSORS_MAX6697)	+= max6697.o
 obj-$(CONFIG_SENSORS_MC13783_ADC)+= mc13783-adc.o
 obj-$(CONFIG_SENSORS_MCP3021)	+= mcp3021.o
+obj-$(CONFIG_SENSORS_NCT6775)	+= nct6775.o
 obj-$(CONFIG_SENSORS_NTC_THERMISTOR)	+= ntc_thermistor.o
 obj-$(CONFIG_SENSORS_PC87360)	+= pc87360.o
 obj-$(CONFIG_SENSORS_PC87427)	+= pc87427.o
diff --git a/drivers/hwmon/abituguru.c b/drivers/hwmon/abituguru.c
index 6119ff8..df0b699 100644
--- a/drivers/hwmon/abituguru.c
+++ b/drivers/hwmon/abituguru.c
@@ -96,9 +96,12 @@
 #define ABIT_UGURU_MAX_TIMEOUTS			2
 /* utility macros */
 #define ABIT_UGURU_NAME				"abituguru"
-#define ABIT_UGURU_DEBUG(level, format, arg...)				\
-	if (level <= verbose)						\
-		printk(KERN_DEBUG ABIT_UGURU_NAME ": "	format , ## arg)
+#define ABIT_UGURU_DEBUG(level, format, arg...)		\
+	do {						\
+		if (level <= verbose)			\
+			pr_debug(format , ## arg);	\
+	} while (0)
+
 /* Macros to help calculate the sysfs_names array length */
 /*
  * sum of strlen of: in??_input\0, in??_{min,max}\0, in??_{min,max}_alarm\0,
@@ -1533,7 +1536,7 @@ static int abituguru_resume(struct device *dev)
 }
 
 static SIMPLE_DEV_PM_OPS(abituguru_pm, abituguru_suspend, abituguru_resume);
-#define ABIT_UGURU_PM	&abituguru_pm
+#define ABIT_UGURU_PM	(&abituguru_pm)
 #else
 #define ABIT_UGURU_PM	NULL
 #endif /* CONFIG_PM */
diff --git a/drivers/hwmon/abituguru3.c b/drivers/hwmon/abituguru3.c
index 205327d..1d2da31 100644
--- a/drivers/hwmon/abituguru3.c
+++ b/drivers/hwmon/abituguru3.c
@@ -76,9 +76,11 @@
 #define ABIT_UGURU3_SYNCHRONIZE_TIMEOUT		5
 /* utility macros */
 #define ABIT_UGURU3_NAME			"abituguru3"
-#define ABIT_UGURU3_DEBUG(format, arg...)	\
-	if (verbose)				\
-		printk(KERN_DEBUG ABIT_UGURU3_NAME ": "	format , ## arg)
+#define ABIT_UGURU3_DEBUG(format, arg...)		\
+	do {						\
+		if (verbose)				\
+			pr_debug(format , ## arg);	\
+	} while (0)
 
 /* Macros to help calculate the sysfs_names array length */
 #define ABIT_UGURU3_MAX_NO_SENSORS 26
@@ -1159,7 +1161,7 @@ static int abituguru3_resume(struct device *dev)
 }
 
 static SIMPLE_DEV_PM_OPS(abituguru3_pm, abituguru3_suspend, abituguru3_resume);
-#define ABIT_UGURU3_PM	&abituguru3_pm
+#define ABIT_UGURU3_PM	(&abituguru3_pm)
 #else
 #define ABIT_UGURU3_PM	NULL
 #endif /* CONFIG_PM */
diff --git a/drivers/hwmon/ad7314.c b/drivers/hwmon/ad7314.c
index a57584d..f3c6001 100644
--- a/drivers/hwmon/ad7314.c
+++ b/drivers/hwmon/ad7314.c
@@ -166,6 +166,5 @@ static struct spi_driver ad7314_driver = {
 module_spi_driver(ad7314_driver);
 
 MODULE_AUTHOR("Sonic Zhang <sonic.zhang@analog.com>");
-MODULE_DESCRIPTION("Analog Devices AD7314, ADT7301 and ADT7302 digital"
-			" temperature sensor driver");
+MODULE_DESCRIPTION("Analog Devices AD7314, ADT7301 and ADT7302 digital temperature sensor driver");
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/hwmon/adm1021.c b/drivers/hwmon/adm1021.c
index 71bcba8a..7e76922 100644
--- a/drivers/hwmon/adm1021.c
+++ b/drivers/hwmon/adm1021.c
@@ -312,8 +312,7 @@ static int adm1021_detect(struct i2c_client *client,
 	int conv_rate, status, config, man_id, dev_id;
 
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
-		pr_debug("adm1021: detect failed, "
-			 "smbus byte data not supported!\n");
+		pr_debug("detect failed, smbus byte data not supported!\n");
 		return -ENODEV;
 	}
 
@@ -324,7 +323,7 @@ static int adm1021_detect(struct i2c_client *client,
 
 	/* Check unused bits */
 	if ((status & 0x03) || (config & 0x3F) || (conv_rate & 0xF8)) {
-		pr_debug("adm1021: detect failed, chip not detected!\n");
+		pr_debug("detect failed, chip not detected!\n");
 		return -ENODEV;
 	}
 
@@ -353,7 +352,7 @@ static int adm1021_detect(struct i2c_client *client,
 	else
 		type_name = "max1617";
 
-	pr_debug("adm1021: Detected chip %s at adapter %d, address 0x%02x.\n",
+	pr_debug("Detected chip %s at adapter %d, address 0x%02x.\n",
 		 type_name, i2c_adapter_id(adapter), client->addr);
 	strlcpy(info->type, type_name, I2C_NAME_SIZE);
 
@@ -368,10 +367,8 @@ static int adm1021_probe(struct i2c_client *client,
 
 	data = devm_kzalloc(&client->dev, sizeof(struct adm1021_data),
 			    GFP_KERNEL);
-	if (!data) {
-		pr_debug("adm1021: detect failed, devm_kzalloc failed!\n");
+	if (!data)
 		return -ENOMEM;
-	}
 
 	i2c_set_clientdata(client, data);
 	data->type = id->driver_data;
diff --git a/drivers/hwmon/adm1026.c b/drivers/hwmon/adm1026.c
index ea09046..3a6d9ef 100644
--- a/drivers/hwmon/adm1026.c
+++ b/drivers/hwmon/adm1026.c
@@ -49,14 +49,14 @@ static int gpio_fan[8] = { -1, -1, -1, -1, -1, -1, -1, -1 };
 module_param_array(gpio_input, int, NULL, 0);
 MODULE_PARM_DESC(gpio_input, "List of GPIO pins (0-16) to program as inputs");
 module_param_array(gpio_output, int, NULL, 0);
-MODULE_PARM_DESC(gpio_output, "List of GPIO pins (0-16) to program as "
-	"outputs");
+MODULE_PARM_DESC(gpio_output,
+		 "List of GPIO pins (0-16) to program as outputs");
 module_param_array(gpio_inverted, int, NULL, 0);
-MODULE_PARM_DESC(gpio_inverted, "List of GPIO pins (0-16) to program as "
-	"inverted");
+MODULE_PARM_DESC(gpio_inverted,
+		 "List of GPIO pins (0-16) to program as inverted");
 module_param_array(gpio_normal, int, NULL, 0);
-MODULE_PARM_DESC(gpio_normal, "List of GPIO pins (0-16) to program as "
-	"normal/non-inverted");
+MODULE_PARM_DESC(gpio_normal,
+		 "List of GPIO pins (0-16) to program as normal/non-inverted");
 module_param_array(gpio_fan, int, NULL, 0);
 MODULE_PARM_DESC(gpio_fan, "List of GPIO pins (0-7) to program as fan tachs");
 
@@ -372,31 +372,31 @@ static void adm1026_init_client(struct i2c_client *client)
 	dev_dbg(&client->dev, "ADM1026_REG_CONFIG1 is: 0x%02x\n",
 		data->config1);
 	if ((data->config1 & CFG1_MONITOR) == 0) {
-		dev_dbg(&client->dev, "Monitoring not currently "
-			"enabled.\n");
+		dev_dbg(&client->dev,
+			"Monitoring not currently enabled.\n");
 	}
 	if (data->config1 & CFG1_INT_ENABLE) {
-		dev_dbg(&client->dev, "SMBALERT interrupts are "
-			"enabled.\n");
+		dev_dbg(&client->dev,
+			"SMBALERT interrupts are enabled.\n");
 	}
 	if (data->config1 & CFG1_AIN8_9) {
-		dev_dbg(&client->dev, "in8 and in9 enabled. "
-			"temp3 disabled.\n");
+		dev_dbg(&client->dev,
+			"in8 and in9 enabled. temp3 disabled.\n");
 	} else {
-		dev_dbg(&client->dev, "temp3 enabled.  in8 and "
-			"in9 disabled.\n");
+		dev_dbg(&client->dev,
+			"temp3 enabled.  in8 and in9 disabled.\n");
 	}
 	if (data->config1 & CFG1_THERM_HOT) {
-		dev_dbg(&client->dev, "Automatic THERM, PWM, "
-			"and temp limits enabled.\n");
+		dev_dbg(&client->dev,
+			"Automatic THERM, PWM, and temp limits enabled.\n");
 	}
 
 	if (data->config3 & CFG3_GPIO16_ENABLE) {
-		dev_dbg(&client->dev, "GPIO16 enabled.  THERM "
-			"pin disabled.\n");
+		dev_dbg(&client->dev,
+			"GPIO16 enabled.  THERM pin disabled.\n");
 	} else {
-		dev_dbg(&client->dev, "THERM pin enabled.  "
-			"GPIO16 disabled.\n");
+		dev_dbg(&client->dev,
+			"THERM pin enabled.  GPIO16 disabled.\n");
 	}
 	if (data->config3 & CFG3_VREF_250)
 		dev_dbg(&client->dev, "Vref is 2.50 Volts.\n");
@@ -1798,8 +1798,8 @@ static int adm1026_detect(struct i2c_client *client,
 	company = adm1026_read_value(client, ADM1026_REG_COMPANY);
 	verstep = adm1026_read_value(client, ADM1026_REG_VERSTEP);
 
-	dev_dbg(&adapter->dev, "Detecting device at %d,0x%02x with"
-		" COMPANY: 0x%02x and VERSTEP: 0x%02x\n",
+	dev_dbg(&adapter->dev,
+		"Detecting device at %d,0x%02x with COMPANY: 0x%02x and VERSTEP: 0x%02x\n",
 		i2c_adapter_id(client->adapter), client->addr,
 		company, verstep);
 
@@ -1811,11 +1811,12 @@ static int adm1026_detect(struct i2c_client *client,
 		/* Analog Devices ADM1026 */
 	} else if (company == ADM1026_COMPANY_ANALOG_DEV
 		&& (verstep & 0xf0) == ADM1026_VERSTEP_GENERIC) {
-		dev_err(&adapter->dev, "Unrecognized stepping "
-			"0x%02x. Defaulting to ADM1026.\n", verstep);
+		dev_err(&adapter->dev,
+			"Unrecognized stepping 0x%02x. Defaulting to ADM1026.\n",
+			verstep);
 	} else if ((verstep & 0xf0) == ADM1026_VERSTEP_GENERIC) {
-		dev_err(&adapter->dev, "Found version/stepping "
-			"0x%02x. Assuming generic ADM1026.\n",
+		dev_err(&adapter->dev,
+			"Found version/stepping 0x%02x. Assuming generic ADM1026.\n",
 			verstep);
 	} else {
 		dev_dbg(&adapter->dev, "Autodetection failed\n");
diff --git a/drivers/hwmon/adm1029.c b/drivers/hwmon/adm1029.c
index 97f4718..9ee5e06 100644
--- a/drivers/hwmon/adm1029.c
+++ b/drivers/hwmon/adm1029.c
@@ -224,8 +224,9 @@ static ssize_t set_fan_div(struct device *dev,
 		break;
 	default:
 		mutex_unlock(&data->update_lock);
-		dev_err(&client->dev, "fan_div value %ld not "
-			"supported. Choose one of 1, 2 or 4!\n", val);
+		dev_err(&client->dev,
+			"fan_div value %ld not supported. Choose one of 1, 2 or 4!\n",
+			val);
 		return -EINVAL;
 	}
 	/* Update the value */
@@ -326,8 +327,8 @@ static int adm1029_detect(struct i2c_client *client,
 		 * There are no "official" CHIP ID, so actually
 		 * we use Major/Minor revision for that
 		 */
-		pr_info("adm1029: Unknown major revision %x, "
-			"please let us know\n", chip_id);
+		pr_info("Unknown major revision %x, please let us know\n",
+			chip_id);
 		return -ENODEV;
 	}
 
diff --git a/drivers/hwmon/adm9240.c b/drivers/hwmon/adm9240.c
index 2416628..086d02a 100644
--- a/drivers/hwmon/adm9240.c
+++ b/drivers/hwmon/adm9240.c
@@ -351,8 +351,9 @@ static void adm9240_write_fan_div(struct i2c_client *client, int nr,
 	reg &= ~(3 << shift);
 	reg |= (fan_div << shift);
 	i2c_smbus_write_byte_data(client, ADM9240_REG_VID_FAN_DIV, reg);
-	dev_dbg(&client->dev, "fan%d clock divider changed from %u "
-			"to %u\n", nr + 1, 1 << old, 1 << fan_div);
+	dev_dbg(&client->dev,
+		"fan%d clock divider changed from %u to %u\n",
+		nr + 1, 1 << old, 1 << fan_div);
 }
 
 /*
@@ -699,8 +700,8 @@ static void adm9240_init_client(struct i2c_client *client)
 		/* start measurement cycle */
 		i2c_smbus_write_byte_data(client, ADM9240_REG_CONFIG, 1);
 
-		dev_info(&client->dev, "cold start: config was 0x%02x "
-				"mode %u\n", conf, mode);
+		dev_info(&client->dev,
+			 "cold start: config was 0x%02x mode %u\n", conf, mode);
 	}
 }
 
diff --git a/drivers/hwmon/ads7871.c b/drivers/hwmon/ads7871.c
index a798759..3eff73b 100644
--- a/drivers/hwmon/ads7871.c
+++ b/drivers/hwmon/ads7871.c
@@ -40,25 +40,25 @@
  * the instruction byte
  */
 /*Instruction Bit masks*/
-#define INST_MODE_bm	(1<<7)
-#define INST_READ_bm	(1<<6)
-#define INST_16BIT_bm	(1<<5)
+#define INST_MODE_BM	(1 << 7)
+#define INST_READ_BM	(1 << 6)
+#define INST_16BIT_BM	(1 << 5)
 
 /*From figure 18 in the datasheet*/
 /*bit masks for Rev/Oscillator Control Register*/
-#define MUX_CNV_bv	7
-#define MUX_CNV_bm	(1<<MUX_CNV_bv)
-#define MUX_M3_bm	(1<<3) /*M3 selects single ended*/
-#define MUX_G_bv	4 /*allows for reg = (gain << MUX_G_bv) | ...*/
+#define MUX_CNV_BV	7
+#define MUX_CNV_BM	(1 << MUX_CNV_BV)
+#define MUX_M3_BM	(1 << 3) /*M3 selects single ended*/
+#define MUX_G_BV	4 /*allows for reg = (gain << MUX_G_BV) | ...*/
 
 /*From figure 18 in the datasheet*/
 /*bit masks for Rev/Oscillator Control Register*/
-#define OSC_OSCR_bm	(1<<5)
-#define OSC_OSCE_bm	(1<<4)
-#define OSC_REFE_bm	(1<<3)
-#define OSC_BUFE_bm	(1<<2)
-#define OSC_R2V_bm	(1<<1)
-#define OSC_RBG_bm	(1<<0)
+#define OSC_OSCR_BM	(1 << 5)
+#define OSC_OSCE_BM	(1 << 4)
+#define OSC_REFE_BM	(1 << 3)
+#define OSC_BUFE_BM	(1 << 2)
+#define OSC_R2V_BM	(1 << 1)
+#define OSC_RBG_BM	(1 << 0)
 
 #include <linux/module.h>
 #include <linux/init.h>
@@ -79,7 +79,7 @@ struct ads7871_data {
 static int ads7871_read_reg8(struct spi_device *spi, int reg)
 {
 	int ret;
-	reg = reg | INST_READ_bm;
+	reg = reg | INST_READ_BM;
 	ret = spi_w8r8(spi, reg);
 	return ret;
 }
@@ -87,7 +87,7 @@ static int ads7871_read_reg8(struct spi_device *spi, int reg)
 static int ads7871_read_reg16(struct spi_device *spi, int reg)
 {
 	int ret;
-	reg = reg | INST_READ_bm | INST_16BIT_bm;
+	reg = reg | INST_READ_BM | INST_16BIT_BM;
 	ret = spi_w8r16(spi, reg);
 	return ret;
 }
@@ -111,13 +111,13 @@ static ssize_t show_voltage(struct device *dev,
 	 * TODO: add support for conversions
 	 * other than single ended with a gain of 1
 	 */
-	/*MUX_M3_bm forces single ended*/
+	/*MUX_M3_BM forces single ended*/
 	/*This is also where the gain of the PGA would be set*/
 	ads7871_write_reg8(spi, REG_GAIN_MUX,
-		(MUX_CNV_bm | MUX_M3_bm | channel));
+		(MUX_CNV_BM | MUX_M3_BM | channel));
 
 	ret = ads7871_read_reg8(spi, REG_GAIN_MUX);
-	mux_cnv = ((ret & MUX_CNV_bm)>>MUX_CNV_bv);
+	mux_cnv = ((ret & MUX_CNV_BM) >> MUX_CNV_BV);
 	/*
 	 * on 400MHz arm9 platform the conversion
 	 * is already done when we do this test
@@ -125,14 +125,14 @@ static ssize_t show_voltage(struct device *dev,
 	while ((i < 2) && mux_cnv) {
 		i++;
 		ret = ads7871_read_reg8(spi, REG_GAIN_MUX);
-		mux_cnv = ((ret & MUX_CNV_bm)>>MUX_CNV_bv);
+		mux_cnv = ((ret & MUX_CNV_BM) >> MUX_CNV_BV);
 		msleep_interruptible(1);
 	}
 
 	if (mux_cnv == 0) {
 		val = ads7871_read_reg16(spi, REG_LS_BYTE);
 		/*result in volts*10000 = (val/8192)*2.5*10000*/
-		val = ((val>>2) * 25000) / 8192;
+		val = ((val >> 2) * 25000) / 8192;
 		return sprintf(buf, "%d\n", val);
 	} else {
 		return -1;
@@ -189,7 +189,7 @@ static int ads7871_probe(struct spi_device *spi)
 	ads7871_write_reg8(spi, REG_SER_CONTROL, 0);
 	ads7871_write_reg8(spi, REG_AD_CONTROL, 0);
 
-	val = (OSC_OSCR_bm | OSC_OSCE_bm | OSC_REFE_bm | OSC_BUFE_bm);
+	val = (OSC_OSCR_BM | OSC_OSCE_BM | OSC_REFE_BM | OSC_BUFE_BM);
 	ads7871_write_reg8(spi, REG_OSC_CONTROL, val);
 	ret = ads7871_read_reg8(spi, REG_OSC_CONTROL);
 
diff --git a/drivers/hwmon/adt7310.c b/drivers/hwmon/adt7310.c
new file mode 100644
index 0000000..da5f078
--- /dev/null
+++ b/drivers/hwmon/adt7310.c
@@ -0,0 +1,123 @@
+/*
+ * ADT7310/ADT7310 digital temperature sensor driver
+ *
+ * Copyright 2012-2013 Analog Devices Inc.
+ *   Author: Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/spi/spi.h>
+#include <asm/unaligned.h>
+
+#include "adt7x10.h"
+
+#define ADT7310_STATUS			0
+#define ADT7310_CONFIG			1
+#define ADT7310_TEMPERATURE		2
+#define ADT7310_ID			3
+#define ADT7310_T_CRIT			4
+#define ADT7310_T_HYST			5
+#define ADT7310_T_ALARM_HIGH		6
+#define ADT7310_T_ALARM_LOW		7
+
+static const u8 adt7310_reg_table[] = {
+	[ADT7X10_TEMPERATURE]   = ADT7310_TEMPERATURE,
+	[ADT7X10_STATUS]	= ADT7310_STATUS,
+	[ADT7X10_CONFIG]	= ADT7310_CONFIG,
+	[ADT7X10_T_ALARM_HIGH]	= ADT7310_T_ALARM_HIGH,
+	[ADT7X10_T_ALARM_LOW]	= ADT7310_T_ALARM_LOW,
+	[ADT7X10_T_CRIT]	= ADT7310_T_CRIT,
+	[ADT7X10_T_HYST]	= ADT7310_T_HYST,
+	[ADT7X10_ID]		= ADT7310_ID,
+};
+
+#define ADT7310_CMD_REG_OFFSET	3
+#define ADT7310_CMD_READ	0x40
+
+#define AD7310_COMMAND(reg) (adt7310_reg_table[(reg)] << ADT7310_CMD_REG_OFFSET)
+
+static int adt7310_spi_read_word(struct device *dev, u8 reg)
+{
+	struct spi_device *spi = to_spi_device(dev);
+	int ret;
+
+	ret = spi_w8r16(spi, AD7310_COMMAND(reg) | ADT7310_CMD_READ);
+	if (ret < 0)
+		return ret;
+
+	return be16_to_cpu((__force __be16)ret);
+}
+
+static int adt7310_spi_write_word(struct device *dev, u8 reg, u16 data)
+{
+	struct spi_device *spi = to_spi_device(dev);
+	u8 buf[3];
+
+	buf[0] = AD7310_COMMAND(reg);
+	put_unaligned_be16(data, &buf[1]);
+
+	return spi_write(spi, buf, sizeof(buf));
+}
+
+static int adt7310_spi_read_byte(struct device *dev, u8 reg)
+{
+	struct spi_device *spi = to_spi_device(dev);
+
+	return spi_w8r8(spi, AD7310_COMMAND(reg) | ADT7310_CMD_READ);
+}
+
+static int adt7310_spi_write_byte(struct device *dev, u8 reg,
+	u8 data)
+{
+	struct spi_device *spi = to_spi_device(dev);
+	u8 buf[2];
+
+	buf[0] = AD7310_COMMAND(reg);
+	buf[1] = data;
+
+	return spi_write(spi, buf, sizeof(buf));
+}
+
+static const struct adt7x10_ops adt7310_spi_ops = {
+	.read_word = adt7310_spi_read_word,
+	.write_word = adt7310_spi_write_word,
+	.read_byte = adt7310_spi_read_byte,
+	.write_byte = adt7310_spi_write_byte,
+};
+
+static int adt7310_spi_probe(struct spi_device *spi)
+{
+	return adt7x10_probe(&spi->dev, spi_get_device_id(spi)->name, spi->irq,
+			&adt7310_spi_ops);
+}
+
+static int adt7310_spi_remove(struct spi_device *spi)
+{
+	return adt7x10_remove(&spi->dev, spi->irq);
+}
+
+static const struct spi_device_id adt7310_id[] = {
+	{ "adt7310", 0 },
+	{ "adt7320", 0 },
+	{}
+};
+MODULE_DEVICE_TABLE(spi, adt7310_id);
+
+static struct spi_driver adt7310_driver = {
+	.driver = {
+		.name	= "adt7310",
+		.owner	= THIS_MODULE,
+		.pm	= ADT7X10_DEV_PM_OPS,
+	},
+	.probe		= adt7310_spi_probe,
+	.remove		= adt7310_spi_remove,
+	.id_table	= adt7310_id,
+};
+module_spi_driver(adt7310_driver);
+
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_DESCRIPTION("ADT7310/ADT7320 driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/adt7410.c b/drivers/hwmon/adt7410.c
index 99a7290..0dc066a 100644
--- a/drivers/hwmon/adt7410.c
+++ b/drivers/hwmon/adt7410.c
@@ -1,460 +1,80 @@
 /*
- * adt7410.c - Part of lm_sensors, Linux kernel modules for hardware
- *	 monitoring
- * This driver handles the ADT7410 and compatible digital temperature sensors.
- * Hartmut Knaack <knaack.h@gmx.de> 2012-07-22
- * based on lm75.c by Frodo Looijaard <frodol@dds.nl>
- * and adt7410.c from iio-staging by Sonic Zhang <sonic.zhang@analog.com>
+ * ADT7410/ADT7420 digital temperature sensor 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.
+ * Copyright 2012-2013 Analog Devices Inc.
+ *   Author: Lars-Peter Clausen <lars@metafoo.de>
  *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You 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.
+ * Licensed under the GPL-2 or later.
  */
 
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/hwmon.h>
-#include <linux/hwmon-sysfs.h>
-#include <linux/err.h>
-#include <linux/mutex.h>
-#include <linux/delay.h>
-
-/*
- * ADT7410 registers definition
- */
-
-#define ADT7410_TEMPERATURE		0
-#define ADT7410_STATUS			2
-#define ADT7410_CONFIG			3
-#define ADT7410_T_ALARM_HIGH		4
-#define ADT7410_T_ALARM_LOW		6
-#define ADT7410_T_CRIT			8
-#define ADT7410_T_HYST			0xA
-
-/*
- * ADT7410 status
- */
-#define ADT7410_STAT_T_LOW		(1 << 4)
-#define ADT7410_STAT_T_HIGH		(1 << 5)
-#define ADT7410_STAT_T_CRIT		(1 << 6)
-#define ADT7410_STAT_NOT_RDY		(1 << 7)
-
-/*
- * ADT7410 config
- */
-#define ADT7410_FAULT_QUEUE_MASK	(1 << 0 | 1 << 1)
-#define ADT7410_CT_POLARITY		(1 << 2)
-#define ADT7410_INT_POLARITY		(1 << 3)
-#define ADT7410_EVENT_MODE		(1 << 4)
-#define ADT7410_MODE_MASK		(1 << 5 | 1 << 6)
-#define ADT7410_FULL			(0 << 5 | 0 << 6)
-#define ADT7410_PD			(1 << 5 | 1 << 6)
-#define ADT7410_RESOLUTION		(1 << 7)
-
-/*
- * ADT7410 masks
- */
-#define ADT7410_T13_VALUE_MASK			0xFFF8
-#define ADT7410_T_HYST_MASK			0xF
-
-/* straight from the datasheet */
-#define ADT7410_TEMP_MIN (-55000)
-#define ADT7410_TEMP_MAX 150000
-
-enum adt7410_type {		/* keep sorted in alphabetical order */
-	adt7410,
-};
-
-static const u8 ADT7410_REG_TEMP[4] = {
-	ADT7410_TEMPERATURE,		/* input */
-	ADT7410_T_ALARM_HIGH,		/* high */
-	ADT7410_T_ALARM_LOW,		/* low */
-	ADT7410_T_CRIT,			/* critical */
-};
-
-/* Each client has this additional data */
-struct adt7410_data {
-	struct device		*hwmon_dev;
-	struct mutex		update_lock;
-	u8			config;
-	u8			oldconfig;
-	bool			valid;		/* true if registers valid */
-	unsigned long		last_updated;	/* In jiffies */
-	s16			temp[4];	/* Register values,
-						   0 = input
-						   1 = high
-						   2 = low
-						   3 = critical */
-	u8			hyst;		/* hysteresis offset */
-};
-
-/*
- * adt7410 register access by I2C
- */
-static int adt7410_temp_ready(struct i2c_client *client)
-{
-	int i, status;
-
-	for (i = 0; i < 6; i++) {
-		status = i2c_smbus_read_byte_data(client, ADT7410_STATUS);
-		if (status < 0)
-			return status;
-		if (!(status & ADT7410_STAT_NOT_RDY))
-			return 0;
-		msleep(60);
-	}
-	return -ETIMEDOUT;
-}
-
-static struct adt7410_data *adt7410_update_device(struct device *dev)
-{
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adt7410_data *data = i2c_get_clientdata(client);
-	struct adt7410_data *ret = data;
-	mutex_lock(&data->update_lock);
-
-	if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
-	    || !data->valid) {
-		int i, status;
 
-		dev_dbg(&client->dev, "Starting update\n");
+#include "adt7x10.h"
 
-		status = adt7410_temp_ready(client); /* check for new value */
-		if (unlikely(status)) {
-			ret = ERR_PTR(status);
-			goto abort;
-		}
-		for (i = 0; i < ARRAY_SIZE(data->temp); i++) {
-			status = i2c_smbus_read_word_swapped(client,
-							ADT7410_REG_TEMP[i]);
-			if (unlikely(status < 0)) {
-				dev_dbg(dev,
-					"Failed to read value: reg %d, error %d\n",
-					ADT7410_REG_TEMP[i], status);
-				ret = ERR_PTR(status);
-				goto abort;
-			}
-			data->temp[i] = status;
-		}
-		status = i2c_smbus_read_byte_data(client, ADT7410_T_HYST);
-		if (unlikely(status < 0)) {
-			dev_dbg(dev,
-				"Failed to read value: reg %d, error %d\n",
-				ADT7410_T_HYST, status);
-			ret = ERR_PTR(status);
-			goto abort;
-		}
-		data->hyst = status;
-		data->last_updated = jiffies;
-		data->valid = true;
-	}
-
-abort:
-	mutex_unlock(&data->update_lock);
-	return ret;
-}
-
-static s16 ADT7410_TEMP_TO_REG(long temp)
+static int adt7410_i2c_read_word(struct device *dev, u8 reg)
 {
-	return DIV_ROUND_CLOSEST(clamp_val(temp, ADT7410_TEMP_MIN,
-					   ADT7410_TEMP_MAX) * 128, 1000);
+	return i2c_smbus_read_word_swapped(to_i2c_client(dev), reg);
 }
 
-static int ADT7410_REG_TO_TEMP(struct adt7410_data *data, s16 reg)
+static int adt7410_i2c_write_word(struct device *dev, u8 reg, u16 data)
 {
-	/* in 13 bit mode, bits 0-2 are status flags - mask them out */
-	if (!(data->config & ADT7410_RESOLUTION))
-		reg &= ADT7410_T13_VALUE_MASK;
-	/*
-	 * temperature is stored in twos complement format, in steps of
-	 * 1/128°C
-	 */
-	return DIV_ROUND_CLOSEST(reg * 1000, 128);
+	return i2c_smbus_write_word_swapped(to_i2c_client(dev), reg, data);
 }
 
-/*-----------------------------------------------------------------------*/
-
-/* sysfs attributes for hwmon */
-
-static ssize_t adt7410_show_temp(struct device *dev,
-				 struct device_attribute *da, char *buf)
+static int adt7410_i2c_read_byte(struct device *dev, u8 reg)
 {
-	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
-	struct adt7410_data *data = adt7410_update_device(dev);
-
-	if (IS_ERR(data))
-		return PTR_ERR(data);
-
-	return sprintf(buf, "%d\n", ADT7410_REG_TO_TEMP(data,
-		       data->temp[attr->index]));
+	return i2c_smbus_read_byte_data(to_i2c_client(dev), reg);
 }
 
-static ssize_t adt7410_set_temp(struct device *dev,
-				struct device_attribute *da,
-				const char *buf, size_t count)
+static int adt7410_i2c_write_byte(struct device *dev, u8 reg, u8 data)
 {
-	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adt7410_data *data = i2c_get_clientdata(client);
-	int nr = attr->index;
-	long temp;
-	int ret;
-
-	ret = kstrtol(buf, 10, &temp);
-	if (ret)
-		return ret;
-
-	mutex_lock(&data->update_lock);
-	data->temp[nr] = ADT7410_TEMP_TO_REG(temp);
-	ret = i2c_smbus_write_word_swapped(client, ADT7410_REG_TEMP[nr],
-					   data->temp[nr]);
-	if (ret)
-		count = ret;
-	mutex_unlock(&data->update_lock);
-	return count;
+	return i2c_smbus_write_byte_data(to_i2c_client(dev), reg, data);
 }
 
-static ssize_t adt7410_show_t_hyst(struct device *dev,
-				   struct device_attribute *da,
-				   char *buf)
-{
-	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
-	struct adt7410_data *data;
-	int nr = attr->index;
-	int hyst;
-
-	data = adt7410_update_device(dev);
-	if (IS_ERR(data))
-		return PTR_ERR(data);
-	hyst = (data->hyst & ADT7410_T_HYST_MASK) * 1000;
-
-	/*
-	 * hysteresis is stored as a 4 bit offset in the device, convert it
-	 * to an absolute value
-	 */
-	if (nr == 2)	/* min has positive offset, others have negative */
-		hyst = -hyst;
-	return sprintf(buf, "%d\n",
-		       ADT7410_REG_TO_TEMP(data, data->temp[nr]) - hyst);
-}
-
-static ssize_t adt7410_set_t_hyst(struct device *dev,
-				  struct device_attribute *da,
-				  const char *buf, size_t count)
-{
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adt7410_data *data = i2c_get_clientdata(client);
-	int limit, ret;
-	long hyst;
-
-	ret = kstrtol(buf, 10, &hyst);
-	if (ret)
-		return ret;
-	/* convert absolute hysteresis value to a 4 bit delta value */
-	limit = ADT7410_REG_TO_TEMP(data, data->temp[1]);
-	hyst = clamp_val(hyst, ADT7410_TEMP_MIN, ADT7410_TEMP_MAX);
-	data->hyst = clamp_val(DIV_ROUND_CLOSEST(limit - hyst, 1000), 0,
-			       ADT7410_T_HYST_MASK);
-	ret = i2c_smbus_write_byte_data(client, ADT7410_T_HYST, data->hyst);
-	if (ret)
-		return ret;
-
-	return count;
-}
-
-static ssize_t adt7410_show_alarm(struct device *dev,
-				  struct device_attribute *da,
-				  char *buf)
-{
-	struct i2c_client *client = to_i2c_client(dev);
-	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
-	int ret;
-
-	ret = i2c_smbus_read_byte_data(client, ADT7410_STATUS);
-	if (ret < 0)
-		return ret;
-
-	return sprintf(buf, "%d\n", !!(ret & attr->index));
-}
-
-static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, adt7410_show_temp, NULL, 0);
-static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO,
-			  adt7410_show_temp, adt7410_set_temp, 1);
-static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO,
-			  adt7410_show_temp, adt7410_set_temp, 2);
-static SENSOR_DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO,
-			  adt7410_show_temp, adt7410_set_temp, 3);
-static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO,
-			  adt7410_show_t_hyst, adt7410_set_t_hyst, 1);
-static SENSOR_DEVICE_ATTR(temp1_min_hyst, S_IRUGO,
-			  adt7410_show_t_hyst, NULL, 2);
-static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO,
-			  adt7410_show_t_hyst, NULL, 3);
-static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, adt7410_show_alarm,
-			  NULL, ADT7410_STAT_T_LOW);
-static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, adt7410_show_alarm,
-			  NULL, ADT7410_STAT_T_HIGH);
-static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, adt7410_show_alarm,
-			  NULL, ADT7410_STAT_T_CRIT);
-
-static struct attribute *adt7410_attributes[] = {
-	&sensor_dev_attr_temp1_input.dev_attr.attr,
-	&sensor_dev_attr_temp1_max.dev_attr.attr,
-	&sensor_dev_attr_temp1_min.dev_attr.attr,
-	&sensor_dev_attr_temp1_crit.dev_attr.attr,
-	&sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
-	&sensor_dev_attr_temp1_min_hyst.dev_attr.attr,
-	&sensor_dev_attr_temp1_crit_hyst.dev_attr.attr,
-	&sensor_dev_attr_temp1_min_alarm.dev_attr.attr,
-	&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
-	&sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
-	NULL
+static const struct adt7x10_ops adt7410_i2c_ops = {
+	.read_word = adt7410_i2c_read_word,
+	.write_word = adt7410_i2c_write_word,
+	.read_byte = adt7410_i2c_read_byte,
+	.write_byte = adt7410_i2c_write_byte,
 };
 
-static const struct attribute_group adt7410_group = {
-	.attrs = adt7410_attributes,
-};
-
-/*-----------------------------------------------------------------------*/
-
-/* device probe and removal */
-
-static int adt7410_probe(struct i2c_client *client,
-			 const struct i2c_device_id *id)
+static int adt7410_i2c_probe(struct i2c_client *client,
+	const struct i2c_device_id *id)
 {
-	struct adt7410_data *data;
-	int ret;
-
 	if (!i2c_check_functionality(client->adapter,
 			I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA))
 		return -ENODEV;
 
-	data = devm_kzalloc(&client->dev, sizeof(struct adt7410_data),
-			    GFP_KERNEL);
-	if (!data)
-		return -ENOMEM;
-
-	i2c_set_clientdata(client, data);
-	mutex_init(&data->update_lock);
-
-	/* configure as specified */
-	ret = i2c_smbus_read_byte_data(client, ADT7410_CONFIG);
-	if (ret < 0) {
-		dev_dbg(&client->dev, "Can't read config? %d\n", ret);
-		return ret;
-	}
-	data->oldconfig = ret;
-	/*
-	 * Set to 16 bit resolution, continous conversion and comparator mode.
-	 */
-	ret &= ~ADT7410_MODE_MASK;
-	data->config = ret | ADT7410_FULL | ADT7410_RESOLUTION |
-			ADT7410_EVENT_MODE;
-	if (data->config != data->oldconfig) {
-		ret = i2c_smbus_write_byte_data(client, ADT7410_CONFIG,
-						data->config);
-		if (ret)
-			return ret;
-	}
-	dev_dbg(&client->dev, "Config %02x\n", data->config);
-
-	/* Register sysfs hooks */
-	ret = sysfs_create_group(&client->dev.kobj, &adt7410_group);
-	if (ret)
-		goto exit_restore;
-
-	data->hwmon_dev = hwmon_device_register(&client->dev);
-	if (IS_ERR(data->hwmon_dev)) {
-		ret = PTR_ERR(data->hwmon_dev);
-		goto exit_remove;
-	}
-
-	dev_info(&client->dev, "sensor '%s'\n", client->name);
-
-	return 0;
-
-exit_remove:
-	sysfs_remove_group(&client->dev.kobj, &adt7410_group);
-exit_restore:
-	i2c_smbus_write_byte_data(client, ADT7410_CONFIG, data->oldconfig);
-	return ret;
+	return adt7x10_probe(&client->dev, NULL, client->irq, &adt7410_i2c_ops);
 }
 
-static int adt7410_remove(struct i2c_client *client)
+static int adt7410_i2c_remove(struct i2c_client *client)
 {
-	struct adt7410_data *data = i2c_get_clientdata(client);
-
-	hwmon_device_unregister(data->hwmon_dev);
-	sysfs_remove_group(&client->dev.kobj, &adt7410_group);
-	if (data->oldconfig != data->config)
-		i2c_smbus_write_byte_data(client, ADT7410_CONFIG,
-					  data->oldconfig);
-	return 0;
+	return adt7x10_remove(&client->dev, client->irq);
 }
 
 static const struct i2c_device_id adt7410_ids[] = {
-	{ "adt7410", adt7410, },
-	{ "adt7420", adt7410, },
-	{ /* LIST END */ }
+	{ "adt7410", 0 },
+	{ "adt7420", 0 },
+	{}
 };
 MODULE_DEVICE_TABLE(i2c, adt7410_ids);
 
-#ifdef CONFIG_PM_SLEEP
-static int adt7410_suspend(struct device *dev)
-{
-	int ret;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adt7410_data *data = i2c_get_clientdata(client);
-
-	ret = i2c_smbus_write_byte_data(client, ADT7410_CONFIG,
-					data->config | ADT7410_PD);
-	return ret;
-}
-
-static int adt7410_resume(struct device *dev)
-{
-	int ret;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adt7410_data *data = i2c_get_clientdata(client);
-
-	ret = i2c_smbus_write_byte_data(client, ADT7410_CONFIG, data->config);
-	return ret;
-}
-
-static SIMPLE_DEV_PM_OPS(adt7410_dev_pm_ops, adt7410_suspend, adt7410_resume);
-
-#define ADT7410_DEV_PM_OPS (&adt7410_dev_pm_ops)
-#else
-#define ADT7410_DEV_PM_OPS NULL
-#endif /* CONFIG_PM */
-
 static struct i2c_driver adt7410_driver = {
 	.class		= I2C_CLASS_HWMON,
 	.driver = {
 		.name	= "adt7410",
-		.pm	= ADT7410_DEV_PM_OPS,
+		.pm	= ADT7X10_DEV_PM_OPS,
 	},
-	.probe		= adt7410_probe,
-	.remove		= adt7410_remove,
+	.probe		= adt7410_i2c_probe,
+	.remove		= adt7410_i2c_remove,
 	.id_table	= adt7410_ids,
 	.address_list	= I2C_ADDRS(0x48, 0x49, 0x4a, 0x4b),
 };
-
 module_i2c_driver(adt7410_driver);
 
-MODULE_AUTHOR("Hartmut Knaack");
-MODULE_DESCRIPTION("ADT7410/ADT7420 driver");
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_DESCRIPTION("ADT7410/AD7420 driver");
 MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/adt7411.c b/drivers/hwmon/adt7411.c
index 34ff03a..d9299de 100644
--- a/drivers/hwmon/adt7411.c
+++ b/drivers/hwmon/adt7411.c
@@ -259,15 +259,17 @@ static int adt7411_detect(struct i2c_client *client,
 
 	val = i2c_smbus_read_byte_data(client, ADT7411_REG_MANUFACTURER_ID);
 	if (val < 0 || val != ADT7411_MANUFACTURER_ID) {
-		dev_dbg(&client->dev, "Wrong manufacturer ID. Got %d, "
-			"expected %d\n", val, ADT7411_MANUFACTURER_ID);
+		dev_dbg(&client->dev,
+			"Wrong manufacturer ID. Got %d, expected %d\n",
+			val, ADT7411_MANUFACTURER_ID);
 		return -ENODEV;
 	}
 
 	val = i2c_smbus_read_byte_data(client, ADT7411_REG_DEVICE_ID);
 	if (val < 0 || val != ADT7411_DEVICE_ID) {
-		dev_dbg(&client->dev, "Wrong device ID. Got %d, "
-			"expected %d\n", val, ADT7411_DEVICE_ID);
+		dev_dbg(&client->dev,
+			"Wrong device ID. Got %d, expected %d\n",
+			val, ADT7411_DEVICE_ID);
 		return -ENODEV;
 	}
 
diff --git a/drivers/hwmon/adt7x10.c b/drivers/hwmon/adt7x10.c
new file mode 100644
index 0000000..98141f4
--- /dev/null
+++ b/drivers/hwmon/adt7x10.c
@@ -0,0 +1,511 @@
+/*
+ * adt7x10.c - Part of lm_sensors, Linux kernel modules for hardware
+ *	 monitoring
+ * This driver handles the ADT7410 and compatible digital temperature sensors.
+ * Hartmut Knaack <knaack.h@gmx.de> 2012-07-22
+ * based on lm75.c by Frodo Looijaard <frodol@dds.nl>
+ * and adt7410.c from iio-staging by Sonic Zhang <sonic.zhang@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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+
+#include "adt7x10.h"
+
+/*
+ * ADT7X10 status
+ */
+#define ADT7X10_STAT_T_LOW		(1 << 4)
+#define ADT7X10_STAT_T_HIGH		(1 << 5)
+#define ADT7X10_STAT_T_CRIT		(1 << 6)
+#define ADT7X10_STAT_NOT_RDY		(1 << 7)
+
+/*
+ * ADT7X10 config
+ */
+#define ADT7X10_FAULT_QUEUE_MASK	(1 << 0 | 1 << 1)
+#define ADT7X10_CT_POLARITY		(1 << 2)
+#define ADT7X10_INT_POLARITY		(1 << 3)
+#define ADT7X10_EVENT_MODE		(1 << 4)
+#define ADT7X10_MODE_MASK		(1 << 5 | 1 << 6)
+#define ADT7X10_FULL			(0 << 5 | 0 << 6)
+#define ADT7X10_PD			(1 << 5 | 1 << 6)
+#define ADT7X10_RESOLUTION		(1 << 7)
+
+/*
+ * ADT7X10 masks
+ */
+#define ADT7X10_T13_VALUE_MASK		0xFFF8
+#define ADT7X10_T_HYST_MASK		0xF
+
+/* straight from the datasheet */
+#define ADT7X10_TEMP_MIN (-55000)
+#define ADT7X10_TEMP_MAX 150000
+
+/* Each client has this additional data */
+struct adt7x10_data {
+	const struct adt7x10_ops *ops;
+	const char		*name;
+	struct device		*hwmon_dev;
+	struct mutex		update_lock;
+	u8			config;
+	u8			oldconfig;
+	bool			valid;		/* true if registers valid */
+	unsigned long		last_updated;	/* In jiffies */
+	s16			temp[4];	/* Register values,
+						   0 = input
+						   1 = high
+						   2 = low
+						   3 = critical */
+	u8			hyst;		/* hysteresis offset */
+};
+
+static int adt7x10_read_byte(struct device *dev, u8 reg)
+{
+	struct adt7x10_data *d = dev_get_drvdata(dev);
+	return d->ops->read_byte(dev, reg);
+}
+
+static int adt7x10_write_byte(struct device *dev, u8 reg, u8 data)
+{
+	struct adt7x10_data *d = dev_get_drvdata(dev);
+	return d->ops->write_byte(dev, reg, data);
+}
+
+static int adt7x10_read_word(struct device *dev, u8 reg)
+{
+	struct adt7x10_data *d = dev_get_drvdata(dev);
+	return d->ops->read_word(dev, reg);
+}
+
+static int adt7x10_write_word(struct device *dev, u8 reg, u16 data)
+{
+	struct adt7x10_data *d = dev_get_drvdata(dev);
+	return d->ops->write_word(dev, reg, data);
+}
+
+static const u8 ADT7X10_REG_TEMP[4] = {
+	ADT7X10_TEMPERATURE,		/* input */
+	ADT7X10_T_ALARM_HIGH,		/* high */
+	ADT7X10_T_ALARM_LOW,		/* low */
+	ADT7X10_T_CRIT,			/* critical */
+};
+
+static irqreturn_t adt7x10_irq_handler(int irq, void *private)
+{
+	struct device *dev = private;
+	int status;
+
+	status = adt7x10_read_byte(dev, ADT7X10_STATUS);
+	if (status < 0)
+		return IRQ_HANDLED;
+
+	if (status & ADT7X10_STAT_T_HIGH)
+		sysfs_notify(&dev->kobj, NULL, "temp1_max_alarm");
+	if (status & ADT7X10_STAT_T_LOW)
+		sysfs_notify(&dev->kobj, NULL, "temp1_min_alarm");
+	if (status & ADT7X10_STAT_T_CRIT)
+		sysfs_notify(&dev->kobj, NULL, "temp1_crit_alarm");
+
+	return IRQ_HANDLED;
+}
+
+static int adt7x10_temp_ready(struct device *dev)
+{
+	int i, status;
+
+	for (i = 0; i < 6; i++) {
+		status = adt7x10_read_byte(dev, ADT7X10_STATUS);
+		if (status < 0)
+			return status;
+		if (!(status & ADT7X10_STAT_NOT_RDY))
+			return 0;
+		msleep(60);
+	}
+	return -ETIMEDOUT;
+}
+
+static int adt7x10_update_temp(struct device *dev)
+{
+	struct adt7x10_data *data = dev_get_drvdata(dev);
+	int ret = 0;
+
+	mutex_lock(&data->update_lock);
+
+	if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
+	    || !data->valid) {
+		int temp;
+
+		dev_dbg(dev, "Starting update\n");
+
+		ret = adt7x10_temp_ready(dev); /* check for new value */
+		if (ret)
+			goto abort;
+
+		temp = adt7x10_read_word(dev, ADT7X10_REG_TEMP[0]);
+		if (temp < 0) {
+			ret = temp;
+			dev_dbg(dev, "Failed to read value: reg %d, error %d\n",
+				ADT7X10_REG_TEMP[0], ret);
+			goto abort;
+		}
+		data->temp[0] = temp;
+		data->last_updated = jiffies;
+		data->valid = true;
+	}
+
+abort:
+	mutex_unlock(&data->update_lock);
+	return ret;
+}
+
+static int adt7x10_fill_cache(struct device *dev)
+{
+	struct adt7x10_data *data = dev_get_drvdata(dev);
+	int ret;
+	int i;
+
+	for (i = 1; i < ARRAY_SIZE(data->temp); i++) {
+		ret = adt7x10_read_word(dev, ADT7X10_REG_TEMP[i]);
+		if (ret < 0) {
+			dev_dbg(dev, "Failed to read value: reg %d, error %d\n",
+				ADT7X10_REG_TEMP[i], ret);
+			return ret;
+		}
+		data->temp[i] = ret;
+	}
+
+	ret = adt7x10_read_byte(dev, ADT7X10_T_HYST);
+	if (ret < 0) {
+		dev_dbg(dev, "Failed to read value: reg %d, error %d\n",
+				ADT7X10_T_HYST, ret);
+		return ret;
+	}
+	data->hyst = ret;
+
+	return 0;
+}
+
+static s16 ADT7X10_TEMP_TO_REG(long temp)
+{
+	return DIV_ROUND_CLOSEST(clamp_val(temp, ADT7X10_TEMP_MIN,
+					       ADT7X10_TEMP_MAX) * 128, 1000);
+}
+
+static int ADT7X10_REG_TO_TEMP(struct adt7x10_data *data, s16 reg)
+{
+	/* in 13 bit mode, bits 0-2 are status flags - mask them out */
+	if (!(data->config & ADT7X10_RESOLUTION))
+		reg &= ADT7X10_T13_VALUE_MASK;
+	/*
+	 * temperature is stored in twos complement format, in steps of
+	 * 1/128°C
+	 */
+	return DIV_ROUND_CLOSEST(reg * 1000, 128);
+}
+
+/*-----------------------------------------------------------------------*/
+
+/* sysfs attributes for hwmon */
+
+static ssize_t adt7x10_show_temp(struct device *dev,
+				 struct device_attribute *da,
+				 char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	struct adt7x10_data *data = dev_get_drvdata(dev);
+
+
+	if (attr->index == 0) {
+		int ret;
+
+		ret = adt7x10_update_temp(dev);
+		if (ret)
+			return ret;
+	}
+
+	return sprintf(buf, "%d\n", ADT7X10_REG_TO_TEMP(data,
+		       data->temp[attr->index]));
+}
+
+static ssize_t adt7x10_set_temp(struct device *dev,
+				struct device_attribute *da,
+				const char *buf, size_t count)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	struct adt7x10_data *data = dev_get_drvdata(dev);
+	int nr = attr->index;
+	long temp;
+	int ret;
+
+	ret = kstrtol(buf, 10, &temp);
+	if (ret)
+		return ret;
+
+	mutex_lock(&data->update_lock);
+	data->temp[nr] = ADT7X10_TEMP_TO_REG(temp);
+	ret = adt7x10_write_word(dev, ADT7X10_REG_TEMP[nr], data->temp[nr]);
+	if (ret)
+		count = ret;
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static ssize_t adt7x10_show_t_hyst(struct device *dev,
+				   struct device_attribute *da,
+				   char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	struct adt7x10_data *data = dev_get_drvdata(dev);
+	int nr = attr->index;
+	int hyst;
+
+	hyst = (data->hyst & ADT7X10_T_HYST_MASK) * 1000;
+
+	/*
+	 * hysteresis is stored as a 4 bit offset in the device, convert it
+	 * to an absolute value
+	 */
+	if (nr == 2)	/* min has positive offset, others have negative */
+		hyst = -hyst;
+	return sprintf(buf, "%d\n",
+		       ADT7X10_REG_TO_TEMP(data, data->temp[nr]) - hyst);
+}
+
+static ssize_t adt7x10_set_t_hyst(struct device *dev,
+				  struct device_attribute *da,
+				  const char *buf, size_t count)
+{
+	struct adt7x10_data *data = dev_get_drvdata(dev);
+	int limit, ret;
+	long hyst;
+
+	ret = kstrtol(buf, 10, &hyst);
+	if (ret)
+		return ret;
+	/* convert absolute hysteresis value to a 4 bit delta value */
+	limit = ADT7X10_REG_TO_TEMP(data, data->temp[1]);
+	hyst = clamp_val(hyst, ADT7X10_TEMP_MIN, ADT7X10_TEMP_MAX);
+	data->hyst = clamp_val(DIV_ROUND_CLOSEST(limit - hyst, 1000),
+				   0, ADT7X10_T_HYST_MASK);
+	ret = adt7x10_write_byte(dev, ADT7X10_T_HYST, data->hyst);
+	if (ret)
+		return ret;
+
+	return count;
+}
+
+static ssize_t adt7x10_show_alarm(struct device *dev,
+				  struct device_attribute *da,
+				  char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	int ret;
+
+	ret = adt7x10_read_byte(dev, ADT7X10_STATUS);
+	if (ret < 0)
+		return ret;
+
+	return sprintf(buf, "%d\n", !!(ret & attr->index));
+}
+
+static ssize_t adt7x10_show_name(struct device *dev,
+				 struct device_attribute *da,
+				 char *buf)
+{
+	struct adt7x10_data *data = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%s\n", data->name);
+}
+
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, adt7x10_show_temp, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO,
+			  adt7x10_show_temp, adt7x10_set_temp, 1);
+static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO,
+			  adt7x10_show_temp, adt7x10_set_temp, 2);
+static SENSOR_DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO,
+			  adt7x10_show_temp, adt7x10_set_temp, 3);
+static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO,
+			  adt7x10_show_t_hyst, adt7x10_set_t_hyst, 1);
+static SENSOR_DEVICE_ATTR(temp1_min_hyst, S_IRUGO,
+			  adt7x10_show_t_hyst, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO,
+			  adt7x10_show_t_hyst, NULL, 3);
+static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, adt7x10_show_alarm,
+			  NULL, ADT7X10_STAT_T_LOW);
+static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, adt7x10_show_alarm,
+			  NULL, ADT7X10_STAT_T_HIGH);
+static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, adt7x10_show_alarm,
+			  NULL, ADT7X10_STAT_T_CRIT);
+static DEVICE_ATTR(name, S_IRUGO, adt7x10_show_name, NULL);
+
+static struct attribute *adt7x10_attributes[] = {
+	&sensor_dev_attr_temp1_input.dev_attr.attr,
+	&sensor_dev_attr_temp1_max.dev_attr.attr,
+	&sensor_dev_attr_temp1_min.dev_attr.attr,
+	&sensor_dev_attr_temp1_crit.dev_attr.attr,
+	&sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
+	&sensor_dev_attr_temp1_min_hyst.dev_attr.attr,
+	&sensor_dev_attr_temp1_crit_hyst.dev_attr.attr,
+	&sensor_dev_attr_temp1_min_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
+	NULL
+};
+
+static const struct attribute_group adt7x10_group = {
+	.attrs = adt7x10_attributes,
+};
+
+int adt7x10_probe(struct device *dev, const char *name, int irq,
+		  const struct adt7x10_ops *ops)
+{
+	struct adt7x10_data *data;
+	int ret;
+
+	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->ops = ops;
+	data->name = name;
+
+	dev_set_drvdata(dev, data);
+	mutex_init(&data->update_lock);
+
+	/* configure as specified */
+	ret = adt7x10_read_byte(dev, ADT7X10_CONFIG);
+	if (ret < 0) {
+		dev_dbg(dev, "Can't read config? %d\n", ret);
+		return ret;
+	}
+	data->oldconfig = ret;
+
+	/*
+	 * Set to 16 bit resolution, continous conversion and comparator mode.
+	 */
+	data->config = data->oldconfig;
+	data->config &= ~(ADT7X10_MODE_MASK | ADT7X10_CT_POLARITY |
+			ADT7X10_INT_POLARITY);
+	data->config |= ADT7X10_FULL | ADT7X10_RESOLUTION | ADT7X10_EVENT_MODE;
+
+	if (data->config != data->oldconfig) {
+		ret = adt7x10_write_byte(dev, ADT7X10_CONFIG, data->config);
+		if (ret)
+			return ret;
+	}
+	dev_dbg(dev, "Config %02x\n", data->config);
+
+	ret = adt7x10_fill_cache(dev);
+	if (ret)
+		goto exit_restore;
+
+	/* Register sysfs hooks */
+	ret = sysfs_create_group(&dev->kobj, &adt7x10_group);
+	if (ret)
+		goto exit_restore;
+
+	/*
+	 * The I2C device will already have it's own 'name' attribute, but for
+	 * the SPI device we need to register it. name will only be non NULL if
+	 * the device doesn't register the 'name' attribute on its own.
+	 */
+	if (name) {
+		ret = device_create_file(dev, &dev_attr_name);
+		if (ret)
+			goto exit_remove;
+	}
+
+	data->hwmon_dev = hwmon_device_register(dev);
+	if (IS_ERR(data->hwmon_dev)) {
+		ret = PTR_ERR(data->hwmon_dev);
+		goto exit_remove_name;
+	}
+
+	if (irq > 0) {
+		ret = request_threaded_irq(irq, NULL, adt7x10_irq_handler,
+				IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+				dev_name(dev), dev);
+		if (ret)
+			goto exit_hwmon_device_unregister;
+	}
+
+	return 0;
+
+exit_hwmon_device_unregister:
+	hwmon_device_unregister(data->hwmon_dev);
+exit_remove_name:
+	if (name)
+		device_remove_file(dev, &dev_attr_name);
+exit_remove:
+	sysfs_remove_group(&dev->kobj, &adt7x10_group);
+exit_restore:
+	adt7x10_write_byte(dev, ADT7X10_CONFIG, data->oldconfig);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(adt7x10_probe);
+
+int adt7x10_remove(struct device *dev, int irq)
+{
+	struct adt7x10_data *data = dev_get_drvdata(dev);
+
+	if (irq > 0)
+		free_irq(irq, dev);
+
+	hwmon_device_unregister(data->hwmon_dev);
+	if (data->name)
+		device_remove_file(dev, &dev_attr_name);
+	sysfs_remove_group(&dev->kobj, &adt7x10_group);
+	if (data->oldconfig != data->config)
+		adt7x10_write_byte(dev, ADT7X10_CONFIG, data->oldconfig);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(adt7x10_remove);
+
+#ifdef CONFIG_PM_SLEEP
+
+static int adt7x10_suspend(struct device *dev)
+{
+	struct adt7x10_data *data = dev_get_drvdata(dev);
+
+	return adt7x10_write_byte(dev, ADT7X10_CONFIG,
+		data->config | ADT7X10_PD);
+}
+
+static int adt7x10_resume(struct device *dev)
+{
+	struct adt7x10_data *data = dev_get_drvdata(dev);
+
+	return adt7x10_write_byte(dev, ADT7X10_CONFIG, data->config);
+}
+
+SIMPLE_DEV_PM_OPS(adt7x10_dev_pm_ops, adt7x10_suspend, adt7x10_resume);
+EXPORT_SYMBOL_GPL(adt7x10_dev_pm_ops);
+
+#endif /* CONFIG_PM_SLEEP */
+
+MODULE_AUTHOR("Hartmut Knaack");
+MODULE_DESCRIPTION("ADT7410/ADT7420, ADT7310/ADT7320 common code");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/adt7x10.h b/drivers/hwmon/adt7x10.h
new file mode 100644
index 0000000..d491c69
--- /dev/null
+++ b/drivers/hwmon/adt7x10.h
@@ -0,0 +1,37 @@
+#ifndef __HWMON_ADT7X10_H__
+#define __HWMON_ADT7X10_H__
+
+#include <linux/types.h>
+#include <linux/pm.h>
+
+/* ADT7410 registers definition */
+#define ADT7X10_TEMPERATURE		0
+#define ADT7X10_STATUS			2
+#define ADT7X10_CONFIG			3
+#define ADT7X10_T_ALARM_HIGH		4
+#define ADT7X10_T_ALARM_LOW		6
+#define ADT7X10_T_CRIT			8
+#define ADT7X10_T_HYST			0xA
+#define ADT7X10_ID			0xB
+
+struct device;
+
+struct adt7x10_ops {
+	int (*read_byte)(struct device *, u8 reg);
+	int (*write_byte)(struct device *, u8 reg, u8 data);
+	int (*read_word)(struct device *, u8 reg);
+	int (*write_word)(struct device *, u8 reg, u16 data);
+};
+
+int adt7x10_probe(struct device *dev, const char *name, int irq,
+	const struct adt7x10_ops *ops);
+int adt7x10_remove(struct device *dev, int irq);
+
+#ifdef CONFIG_PM_SLEEP
+extern const struct dev_pm_ops adt7x10_dev_pm_ops;
+#define ADT7X10_DEV_PM_OPS (&adt7x10_dev_pm_ops)
+#else
+#define ADT7X10_DEV_PM_OPS NULL
+#endif
+
+#endif
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c
index b41baff..62c2e32 100644
--- a/drivers/hwmon/applesmc.c
+++ b/drivers/hwmon/applesmc.c
@@ -922,7 +922,7 @@ static void applesmc_brightness_set(struct led_classdev *led_cdev,
 	ret = queue_work(applesmc_led_wq, &backlight_work);
 
 	if (debug && (!ret))
-		printk(KERN_DEBUG "applesmc: work was already on the queue.\n");
+		dev_dbg(led_cdev->dev, "work was already on the queue.\n");
 }
 
 static ssize_t applesmc_key_count_show(struct device *dev,
diff --git a/drivers/hwmon/asb100.c b/drivers/hwmon/asb100.c
index 6ac612c..f960636 100644
--- a/drivers/hwmon/asb100.c
+++ b/drivers/hwmon/asb100.c
@@ -55,8 +55,8 @@ static const unsigned short normal_i2c[] = { 0x2d, I2C_CLIENT_END };
 
 static unsigned short force_subclients[4];
 module_param_array(force_subclients, short, NULL, 0);
-MODULE_PARM_DESC(force_subclients, "List of subclient addresses: "
-	"{bus, clientaddr, subclientaddr1, subclientaddr2}");
+MODULE_PARM_DESC(force_subclients,
+	"List of subclient addresses: {bus, clientaddr, subclientaddr1, subclientaddr2}");
 
 /* Voltage IN registers 0-6 */
 #define ASB100_REG_IN(nr)	(0x20 + (nr))
@@ -689,8 +689,8 @@ static int asb100_detect_subclients(struct i2c_client *client)
 		for (i = 2; i <= 3; i++) {
 			if (force_subclients[i] < 0x48 ||
 			    force_subclients[i] > 0x4f) {
-				dev_err(&client->dev, "invalid subclient "
-					"address %d; must be 0x48-0x4f\n",
+				dev_err(&client->dev,
+					"invalid subclient address %d; must be 0x48-0x4f\n",
 					force_subclients[i]);
 				err = -ENODEV;
 				goto ERROR_SC_2;
@@ -708,24 +708,27 @@ static int asb100_detect_subclients(struct i2c_client *client)
 	}
 
 	if (sc_addr[0] == sc_addr[1]) {
-		dev_err(&client->dev, "duplicate addresses 0x%x "
-				"for subclients\n", sc_addr[0]);
+		dev_err(&client->dev,
+			"duplicate addresses 0x%x for subclients\n",
+			sc_addr[0]);
 		err = -ENODEV;
 		goto ERROR_SC_2;
 	}
 
 	data->lm75[0] = i2c_new_dummy(adapter, sc_addr[0]);
 	if (!data->lm75[0]) {
-		dev_err(&client->dev, "subclient %d registration "
-			"at address 0x%x failed.\n", 1, sc_addr[0]);
+		dev_err(&client->dev,
+			"subclient %d registration at address 0x%x failed.\n",
+			1, sc_addr[0]);
 		err = -ENOMEM;
 		goto ERROR_SC_2;
 	}
 
 	data->lm75[1] = i2c_new_dummy(adapter, sc_addr[1]);
 	if (!data->lm75[1]) {
-		dev_err(&client->dev, "subclient %d registration "
-			"at address 0x%x failed.\n", 2, sc_addr[1]);
+		dev_err(&client->dev,
+			"subclient %d registration at address 0x%x failed.\n",
+			2, sc_addr[1]);
 		err = -ENOMEM;
 		goto ERROR_SC_3;
 	}
diff --git a/drivers/hwmon/asc7621.c b/drivers/hwmon/asc7621.c
index da7f5b5..3ad9d84 100644
--- a/drivers/hwmon/asc7621.c
+++ b/drivers/hwmon/asc7621.c
@@ -159,12 +159,12 @@ static inline int write_byte(struct i2c_client *client, u8 reg, u8 data)
  * and retrieval of like parameters.
  */
 
-#define SETUP_SHOW_data_param(d, a) \
+#define SETUP_SHOW_DATA_PARAM(d, a) \
 	struct sensor_device_attribute *sda = to_sensor_dev_attr(a); \
 	struct asc7621_data *data = asc7621_update_device(d); \
 	struct asc7621_param *param = to_asc7621_param(sda)
 
-#define SETUP_STORE_data_param(d, a) \
+#define SETUP_STORE_DATA_PARAM(d, a) \
 	struct sensor_device_attribute *sda = to_sensor_dev_attr(a); \
 	struct i2c_client *client = to_i2c_client(d); \
 	struct asc7621_data *data = i2c_get_clientdata(client); \
@@ -177,7 +177,7 @@ static inline int write_byte(struct i2c_client *client, u8 reg, u8 data)
 static ssize_t show_u8(struct device *dev, struct device_attribute *attr,
 		       char *buf)
 {
-	SETUP_SHOW_data_param(dev, attr);
+	SETUP_SHOW_DATA_PARAM(dev, attr);
 
 	return sprintf(buf, "%u\n", data->reg[param->msb[0]]);
 }
@@ -185,7 +185,7 @@ static ssize_t show_u8(struct device *dev, struct device_attribute *attr,
 static ssize_t store_u8(struct device *dev, struct device_attribute *attr,
 			const char *buf, size_t count)
 {
-	SETUP_STORE_data_param(dev, attr);
+	SETUP_STORE_DATA_PARAM(dev, attr);
 	long reqval;
 
 	if (kstrtol(buf, 10, &reqval))
@@ -206,7 +206,7 @@ static ssize_t store_u8(struct device *dev, struct device_attribute *attr,
 static ssize_t show_bitmask(struct device *dev,
 			    struct device_attribute *attr, char *buf)
 {
-	SETUP_SHOW_data_param(dev, attr);
+	SETUP_SHOW_DATA_PARAM(dev, attr);
 
 	return sprintf(buf, "%u\n",
 		       (data->reg[param->msb[0]] >> param->
@@ -217,7 +217,7 @@ static ssize_t store_bitmask(struct device *dev,
 			     struct device_attribute *attr,
 			     const char *buf, size_t count)
 {
-	SETUP_STORE_data_param(dev, attr);
+	SETUP_STORE_DATA_PARAM(dev, attr);
 	long reqval;
 	u8 currval;
 
@@ -246,7 +246,7 @@ static ssize_t store_bitmask(struct device *dev,
 static ssize_t show_fan16(struct device *dev,
 			  struct device_attribute *attr, char *buf)
 {
-	SETUP_SHOW_data_param(dev, attr);
+	SETUP_SHOW_DATA_PARAM(dev, attr);
 	u16 regval;
 
 	mutex_lock(&data->update_lock);
@@ -262,7 +262,7 @@ static ssize_t store_fan16(struct device *dev,
 			   struct device_attribute *attr, const char *buf,
 			   size_t count)
 {
-	SETUP_STORE_data_param(dev, attr);
+	SETUP_STORE_DATA_PARAM(dev, attr);
 	long reqval;
 
 	if (kstrtol(buf, 10, &reqval))
@@ -307,7 +307,7 @@ static int asc7621_in_scaling[] = {
 static ssize_t show_in10(struct device *dev, struct device_attribute *attr,
 			 char *buf)
 {
-	SETUP_SHOW_data_param(dev, attr);
+	SETUP_SHOW_DATA_PARAM(dev, attr);
 	u16 regval;
 	u8 nr = sda->index;
 
@@ -325,7 +325,7 @@ static ssize_t show_in10(struct device *dev, struct device_attribute *attr,
 static ssize_t show_in8(struct device *dev, struct device_attribute *attr,
 			char *buf)
 {
-	SETUP_SHOW_data_param(dev, attr);
+	SETUP_SHOW_DATA_PARAM(dev, attr);
 	u8 nr = sda->index;
 
 	return sprintf(buf, "%u\n",
@@ -336,7 +336,7 @@ static ssize_t show_in8(struct device *dev, struct device_attribute *attr,
 static ssize_t store_in8(struct device *dev, struct device_attribute *attr,
 			 const char *buf, size_t count)
 {
-	SETUP_STORE_data_param(dev, attr);
+	SETUP_STORE_DATA_PARAM(dev, attr);
 	long reqval;
 	u8 nr = sda->index;
 
@@ -360,7 +360,7 @@ static ssize_t store_in8(struct device *dev, struct device_attribute *attr,
 static ssize_t show_temp8(struct device *dev,
 			  struct device_attribute *attr, char *buf)
 {
-	SETUP_SHOW_data_param(dev, attr);
+	SETUP_SHOW_DATA_PARAM(dev, attr);
 
 	return sprintf(buf, "%d\n", ((s8) data->reg[param->msb[0]]) * 1000);
 }
@@ -369,7 +369,7 @@ static ssize_t store_temp8(struct device *dev,
 			   struct device_attribute *attr, const char *buf,
 			   size_t count)
 {
-	SETUP_STORE_data_param(dev, attr);
+	SETUP_STORE_DATA_PARAM(dev, attr);
 	long reqval;
 	s8 temp;
 
@@ -397,7 +397,7 @@ static ssize_t store_temp8(struct device *dev,
 static ssize_t show_temp10(struct device *dev,
 			   struct device_attribute *attr, char *buf)
 {
-	SETUP_SHOW_data_param(dev, attr);
+	SETUP_SHOW_DATA_PARAM(dev, attr);
 	u8 msb, lsb;
 	int temp;
 
@@ -414,7 +414,7 @@ static ssize_t show_temp10(struct device *dev,
 static ssize_t show_temp62(struct device *dev,
 			   struct device_attribute *attr, char *buf)
 {
-	SETUP_SHOW_data_param(dev, attr);
+	SETUP_SHOW_DATA_PARAM(dev, attr);
 	u8 regval = data->reg[param->msb[0]];
 	int temp = ((s8) (regval & 0xfc) * 1000) + ((regval & 0x03) * 250);
 
@@ -425,7 +425,7 @@ static ssize_t store_temp62(struct device *dev,
 			    struct device_attribute *attr, const char *buf,
 			    size_t count)
 {
-	SETUP_STORE_data_param(dev, attr);
+	SETUP_STORE_DATA_PARAM(dev, attr);
 	long reqval, i, f;
 	s8 temp;
 
@@ -459,7 +459,7 @@ static u32 asc7621_range_map[] = {
 static ssize_t show_ap2_temp(struct device *dev,
 			     struct device_attribute *attr, char *buf)
 {
-	SETUP_SHOW_data_param(dev, attr);
+	SETUP_SHOW_DATA_PARAM(dev, attr);
 	long auto_point1;
 	u8 regval;
 	int temp;
@@ -479,7 +479,7 @@ static ssize_t store_ap2_temp(struct device *dev,
 			      struct device_attribute *attr,
 			      const char *buf, size_t count)
 {
-	SETUP_STORE_data_param(dev, attr);
+	SETUP_STORE_DATA_PARAM(dev, attr);
 	long reqval, auto_point1;
 	int i;
 	u8 currval, newval = 0;
@@ -510,7 +510,7 @@ static ssize_t store_ap2_temp(struct device *dev,
 static ssize_t show_pwm_ac(struct device *dev,
 			   struct device_attribute *attr, char *buf)
 {
-	SETUP_SHOW_data_param(dev, attr);
+	SETUP_SHOW_DATA_PARAM(dev, attr);
 	u8 config, altbit, regval;
 	u8 map[] = {
 		0x01, 0x02, 0x04, 0x1f, 0x00, 0x06, 0x07, 0x10,
@@ -530,7 +530,7 @@ static ssize_t store_pwm_ac(struct device *dev,
 			    struct device_attribute *attr,
 			    const char *buf, size_t count)
 {
-	SETUP_STORE_data_param(dev, attr);
+	SETUP_STORE_DATA_PARAM(dev, attr);
 	unsigned long reqval;
 	u8 currval, config, altbit, newval;
 	u16 map[] = {
@@ -569,7 +569,7 @@ static ssize_t store_pwm_ac(struct device *dev,
 static ssize_t show_pwm_enable(struct device *dev,
 			       struct device_attribute *attr, char *buf)
 {
-	SETUP_SHOW_data_param(dev, attr);
+	SETUP_SHOW_DATA_PARAM(dev, attr);
 	u8 config, altbit, minoff, val, newval;
 
 	mutex_lock(&data->update_lock);
@@ -599,7 +599,7 @@ static ssize_t store_pwm_enable(struct device *dev,
 				struct device_attribute *attr,
 				const char *buf, size_t count)
 {
-	SETUP_STORE_data_param(dev, attr);
+	SETUP_STORE_DATA_PARAM(dev, attr);
 	long reqval;
 	u8 currval, config, altbit, newval, minoff = 255;
 
@@ -659,7 +659,7 @@ static u32 asc7621_pwm_freq_map[] = {
 static ssize_t show_pwm_freq(struct device *dev,
 			     struct device_attribute *attr, char *buf)
 {
-	SETUP_SHOW_data_param(dev, attr);
+	SETUP_SHOW_DATA_PARAM(dev, attr);
 	u8 regval =
 	    (data->reg[param->msb[0]] >> param->shift[0]) & param->mask[0];
 
@@ -672,7 +672,7 @@ static ssize_t store_pwm_freq(struct device *dev,
 			      struct device_attribute *attr,
 			      const char *buf, size_t count)
 {
-	SETUP_STORE_data_param(dev, attr);
+	SETUP_STORE_DATA_PARAM(dev, attr);
 	unsigned long reqval;
 	u8 currval, newval = 255;
 	int i;
@@ -707,7 +707,7 @@ static u32 asc7621_pwm_auto_spinup_map[] =  {
 static ssize_t show_pwm_ast(struct device *dev,
 			    struct device_attribute *attr, char *buf)
 {
-	SETUP_SHOW_data_param(dev, attr);
+	SETUP_SHOW_DATA_PARAM(dev, attr);
 	u8 regval =
 	    (data->reg[param->msb[0]] >> param->shift[0]) & param->mask[0];
 
@@ -721,7 +721,7 @@ static ssize_t store_pwm_ast(struct device *dev,
 			     struct device_attribute *attr,
 			     const char *buf, size_t count)
 {
-	SETUP_STORE_data_param(dev, attr);
+	SETUP_STORE_DATA_PARAM(dev, attr);
 	long reqval;
 	u8 currval, newval = 255;
 	u32 i;
@@ -756,7 +756,7 @@ static u32 asc7621_temp_smoothing_time_map[] = {
 static ssize_t show_temp_st(struct device *dev,
 			    struct device_attribute *attr, char *buf)
 {
-	SETUP_SHOW_data_param(dev, attr);
+	SETUP_SHOW_DATA_PARAM(dev, attr);
 	u8 regval =
 	    (data->reg[param->msb[0]] >> param->shift[0]) & param->mask[0];
 	regval = clamp_val(regval, 0, 7);
@@ -768,7 +768,7 @@ static ssize_t store_temp_st(struct device *dev,
 			     struct device_attribute *attr,
 			     const char *buf, size_t count)
 {
-	SETUP_STORE_data_param(dev, attr);
+	SETUP_STORE_DATA_PARAM(dev, attr);
 	long reqval;
 	u8 currval, newval = 255;
 	u32 i;
diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c
index 3f1e297..658ce3a 100644
--- a/drivers/hwmon/coretemp.c
+++ b/drivers/hwmon/coretemp.c
@@ -411,8 +411,7 @@ static int __cpuinit chk_ucode_version(unsigned int cpu)
 	 * fixed for stepping D0 (6EC).
 	 */
 	if (c->x86_model == 0xe && c->x86_mask < 0xc && c->microcode < 0x39) {
-		pr_err("Errata AE18 not fixed, update BIOS or "
-		       "microcode of the CPU!\n");
+		pr_err("Errata AE18 not fixed, update BIOS or microcode of the CPU!\n");
 		return -ENODEV;
 	}
 	return 0;
diff --git a/drivers/hwmon/da9052-hwmon.c b/drivers/hwmon/da9052-hwmon.c
index ab4452c..960fac3 100644
--- a/drivers/hwmon/da9052-hwmon.c
+++ b/drivers/hwmon/da9052-hwmon.c
@@ -43,19 +43,19 @@ static const char * const input_names[] = {
 };
 
 /* Conversion function for VDDOUT and VBAT */
-static inline int volt_reg_to_mV(int value)
+static inline int volt_reg_to_mv(int value)
 {
 	return DIV_ROUND_CLOSEST(value * 1000, 512) + 2500;
 }
 
 /* Conversion function for ADC channels 4, 5 and 6 */
-static inline int input_reg_to_mV(int value)
+static inline int input_reg_to_mv(int value)
 {
 	return DIV_ROUND_CLOSEST(value * 2500, 1023);
 }
 
 /* Conversion function for VBBAT */
-static inline int vbbat_reg_to_mV(int value)
+static inline int vbbat_reg_to_mv(int value)
 {
 	return DIV_ROUND_CLOSEST(value * 2500, 512);
 }
@@ -96,7 +96,7 @@ static ssize_t da9052_read_vddout(struct device *dev,
 		goto hwmon_err;
 
 	mutex_unlock(&hwmon->hwmon_lock);
-	return sprintf(buf, "%d\n", volt_reg_to_mV(vdd));
+	return sprintf(buf, "%d\n", volt_reg_to_mv(vdd));
 
 hwmon_err_release:
 	da9052_disable_vddout_channel(hwmon->da9052);
@@ -137,7 +137,7 @@ static ssize_t da9052_read_vbat(struct device *dev,
 	if (ret < 0)
 		return ret;
 
-	return sprintf(buf, "%d\n", volt_reg_to_mV(ret));
+	return sprintf(buf, "%d\n", volt_reg_to_mv(ret));
 }
 
 static ssize_t da9052_read_misc_channel(struct device *dev,
@@ -152,7 +152,7 @@ static ssize_t da9052_read_misc_channel(struct device *dev,
 	if (ret < 0)
 		return ret;
 
-	return sprintf(buf, "%d\n", input_reg_to_mV(ret));
+	return sprintf(buf, "%d\n", input_reg_to_mv(ret));
 }
 
 static ssize_t da9052_read_tjunc(struct device *dev,
@@ -187,7 +187,7 @@ static ssize_t da9052_read_vbbat(struct device *dev,
 	if (ret < 0)
 		return ret;
 
-	return sprintf(buf, "%d\n", vbbat_reg_to_mV(ret));
+	return sprintf(buf, "%d\n", vbbat_reg_to_mv(ret));
 }
 
 static ssize_t da9052_hwmon_show_name(struct device *dev,
diff --git a/drivers/hwmon/da9055-hwmon.c b/drivers/hwmon/da9055-hwmon.c
index 9465c05..029ecab 100644
--- a/drivers/hwmon/da9055-hwmon.c
+++ b/drivers/hwmon/da9055-hwmon.c
@@ -119,7 +119,7 @@ static irqreturn_t da9055_auxadc_irq(int irq, void *irq_data)
 }
 
 /* Conversion function for VSYS and ADCINx */
-static inline int volt_reg_to_mV(int value, int channel)
+static inline int volt_reg_to_mv(int value, int channel)
 {
 	if (channel == DA9055_ADC_VSYS)
 		return DIV_ROUND_CLOSEST(value * 1000, DA9055_VSYS_DIV) + 2500;
@@ -168,7 +168,7 @@ static ssize_t da9055_read_auto_ch(struct device *dev,
 
 	mutex_unlock(&hwmon->hwmon_lock);
 
-	return sprintf(buf, "%d\n", volt_reg_to_mV(adc, channel));
+	return sprintf(buf, "%d\n", volt_reg_to_mv(adc, channel));
 
 hwmon_err_release:
 	da9055_disable_auto_mode(hwmon->da9055, channel);
diff --git a/drivers/hwmon/dme1737.c b/drivers/hwmon/dme1737.c
index c347c94..4ae3fff 100644
--- a/drivers/hwmon/dme1737.c
+++ b/drivers/hwmon/dme1737.c
@@ -55,14 +55,16 @@ MODULE_PARM_DESC(force_id, "Override the detected device ID");
 
 static bool probe_all_addr;
 module_param(probe_all_addr, bool, 0);
-MODULE_PARM_DESC(probe_all_addr, "Include probing of non-standard LPC "
-		 "addresses");
+MODULE_PARM_DESC(probe_all_addr,
+		 "Include probing of non-standard LPC addresses");
 
 /* Addresses to scan */
 static const unsigned short normal_i2c[] = {0x2c, 0x2d, 0x2e, I2C_CLIENT_END};
 
 enum chips { dme1737, sch5027, sch311x, sch5127 };
 
+#define	DO_REPORT "Please report to the driver maintainer."
+
 /* ---------------------------------------------------------------------
  * Registers
  *
@@ -566,9 +568,9 @@ static u8 dme1737_read(const struct dme1737_data *data, u8 reg)
 		val = i2c_smbus_read_byte_data(client, reg);
 
 		if (val < 0) {
-			dev_warn(&client->dev, "Read from register "
-				 "0x%02x failed! Please report to the driver "
-				 "maintainer.\n", reg);
+			dev_warn(&client->dev,
+				 "Read from register 0x%02x failed! %s\n",
+				 reg, DO_REPORT);
 		}
 	} else { /* ISA device */
 		outb(reg, data->addr);
@@ -587,9 +589,9 @@ static s32 dme1737_write(const struct dme1737_data *data, u8 reg, u8 val)
 		res = i2c_smbus_write_byte_data(client, reg, val);
 
 		if (res < 0) {
-			dev_warn(&client->dev, "Write to register "
-				 "0x%02x failed! Please report to the driver "
-				 "maintainer.\n", reg);
+			dev_warn(&client->dev,
+				 "Write to register 0x%02x failed! %s\n",
+				 reg, DO_REPORT);
 		}
 	} else { /* ISA device */
 		outb(reg, data->addr);
@@ -1167,8 +1169,8 @@ static ssize_t set_fan(struct device *dev, struct device_attribute *attr,
 		/* Only valid for fan[1-4] */
 		if (!(val == 1 || val == 2 || val == 4)) {
 			count = -EINVAL;
-			dev_warn(dev, "Fan type value %ld not "
-				 "supported. Choose one of 1, 2, or 4.\n",
+			dev_warn(dev,
+				 "Fan type value %ld not supported. Choose one of 1, 2, or 4.\n",
 				 val);
 			goto exit;
 		}
@@ -1294,8 +1296,8 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
 		/* Only valid for pwm[1-3] */
 		if (val < 0 || val > 2) {
 			count = -EINVAL;
-			dev_warn(dev, "PWM enable %ld not "
-				 "supported. Choose one of 0, 1, or 2.\n",
+			dev_warn(dev,
+				 "PWM enable %ld not supported. Choose one of 0, 1, or 2.\n",
 				 val);
 			goto exit;
 		}
@@ -1399,8 +1401,8 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
 		if (!(val == 1 || val == 2 || val == 4 ||
 		      val == 6 || val == 7)) {
 			count = -EINVAL;
-			dev_warn(dev, "PWM auto channels zone %ld "
-				 "not supported. Choose one of 1, 2, 4, 6, "
+			dev_warn(dev,
+				 "PWM auto channels zone %ld not supported. Choose one of 1, 2, 4, 6, "
 				 "or 7.\n", val);
 			goto exit;
 		}
@@ -2178,8 +2180,8 @@ static int dme1737_create_files(struct device *dev)
 	 * selected attributes from read-only to read-writeable.
 	 */
 	if (data->config & 0x02) {
-		dev_info(dev, "Device is locked. Some attributes "
-			 "will be read-only.\n");
+		dev_info(dev,
+			 "Device is locked. Some attributes will be read-only.\n");
 	} else {
 		/* Change permissions of zone sysfs attributes */
 		dme1737_chmod_group(dev, &dme1737_zone_chmod_group,
@@ -2247,9 +2249,8 @@ static int dme1737_init_device(struct device *dev)
 	/* Inform if part is not monitoring/started */
 	if (!(data->config & 0x01)) {
 		if (!force_start) {
-			dev_err(dev, "Device is not monitoring. "
-				"Use the force_start load parameter to "
-				"override.\n");
+			dev_err(dev,
+				"Device is not monitoring. Use the force_start load parameter to override.\n");
 			return -EFAULT;
 		}
 
@@ -2289,8 +2290,8 @@ static int dme1737_init_device(struct device *dev)
 		 */
 		if (dme1737_i2c_get_features(0x2e, data) &&
 		    dme1737_i2c_get_features(0x4e, data)) {
-			dev_warn(dev, "Failed to query Super-IO for optional "
-				 "features.\n");
+			dev_warn(dev,
+				 "Failed to query Super-IO for optional features.\n");
 		}
 	}
 
@@ -2317,8 +2318,8 @@ static int dme1737_init_device(struct device *dev)
 		break;
 	}
 
-	dev_info(dev, "Optional features: pwm3=%s, pwm5=%s, pwm6=%s, "
-		 "fan3=%s, fan4=%s, fan5=%s, fan6=%s.\n",
+	dev_info(dev,
+		 "Optional features: pwm3=%s, pwm5=%s, pwm6=%s, fan3=%s, fan4=%s, fan5=%s, fan6=%s.\n",
 		 (data->has_features & HAS_PWM(2)) ? "yes" : "no",
 		 (data->has_features & HAS_PWM(4)) ? "yes" : "no",
 		 (data->has_features & HAS_PWM(5)) ? "yes" : "no",
@@ -2330,18 +2331,16 @@ static int dme1737_init_device(struct device *dev)
 	reg = dme1737_read(data, DME1737_REG_TACH_PWM);
 	/* Inform if fan-to-pwm mapping differs from the default */
 	if (client && reg != 0xa4) {   /* I2C chip */
-		dev_warn(dev, "Non-standard fan to pwm mapping: "
-			 "fan1->pwm%d, fan2->pwm%d, fan3->pwm%d, "
-			 "fan4->pwm%d. Please report to the driver "
-			 "maintainer.\n",
+		dev_warn(dev,
+			 "Non-standard fan to pwm mapping: fan1->pwm%d, fan2->pwm%d, fan3->pwm%d, fan4->pwm%d. %s\n",
 			 (reg & 0x03) + 1, ((reg >> 2) & 0x03) + 1,
-			 ((reg >> 4) & 0x03) + 1, ((reg >> 6) & 0x03) + 1);
+			 ((reg >> 4) & 0x03) + 1, ((reg >> 6) & 0x03) + 1,
+			 DO_REPORT);
 	} else if (!client && reg != 0x24) {   /* ISA chip */
-		dev_warn(dev, "Non-standard fan to pwm mapping: "
-			 "fan1->pwm%d, fan2->pwm%d, fan3->pwm%d. "
-			 "Please report to the driver maintainer.\n",
+		dev_warn(dev,
+			 "Non-standard fan to pwm mapping: fan1->pwm%d, fan2->pwm%d, fan3->pwm%d. %s\n",
 			 (reg & 0x03) + 1, ((reg >> 2) & 0x03) + 1,
-			 ((reg >> 4) & 0x03) + 1);
+			 ((reg >> 4) & 0x03) + 1, DO_REPORT);
 	}
 
 	/*
@@ -2355,8 +2354,9 @@ static int dme1737_init_device(struct device *dev)
 						DME1737_REG_PWM_CONFIG(ix));
 			if ((data->has_features & HAS_PWM(ix)) &&
 			    (PWM_EN_FROM_REG(data->pwm_config[ix]) == -1)) {
-				dev_info(dev, "Switching pwm%d to "
-					 "manual mode.\n", ix + 1);
+				dev_info(dev,
+					 "Switching pwm%d to manual mode.\n",
+					 ix + 1);
 				data->pwm_config[ix] = PWM_EN_TO_REG(1,
 							data->pwm_config[ix]);
 				dme1737_write(data, DME1737_REG_PWM(ix), 0);
diff --git a/drivers/hwmon/f71805f.c b/drivers/hwmon/f71805f.c
index a981697..0c9f3da 100644
--- a/drivers/hwmon/f71805f.c
+++ b/drivers/hwmon/f71805f.c
@@ -1350,8 +1350,7 @@ static void f71805f_init_device(struct f71805f_data *data)
 
 	reg = f71805f_read8(data, F71805F_REG_START);
 	if ((reg & 0x41) != 0x01) {
-		printk(KERN_DEBUG DRVNAME ": Starting monitoring "
-		       "operations\n");
+		pr_debug("Starting monitoring operations\n");
 		f71805f_write8(data, F71805F_REG_START, (reg | 0x01) & ~0x40);
 	}
 
diff --git a/drivers/hwmon/fam15h_power.c b/drivers/hwmon/fam15h_power.c
index b757088..dff8410 100644
--- a/drivers/hwmon/fam15h_power.c
+++ b/drivers/hwmon/fam15h_power.c
@@ -189,8 +189,8 @@ static void fam15h_power_init_data(struct pci_dev *f4,
 
 	/* result not allowed to be >= 256W */
 	if ((tmp >> 16) >= 256)
-		dev_warn(&f4->dev, "Bogus value for ProcessorPwrWatts "
-			 "(processor_pwr_watts>=%u)\n",
+		dev_warn(&f4->dev,
+			 "Bogus value for ProcessorPwrWatts (processor_pwr_watts>=%u)\n",
 			 (unsigned int) (tmp >> 16));
 
 	/* convert to microWatt */
diff --git a/drivers/hwmon/fschmd.c b/drivers/hwmon/fschmd.c
index 8af2755..d58abdc 100644
--- a/drivers/hwmon/fschmd.c
+++ b/drivers/hwmon/fschmd.c
@@ -463,8 +463,9 @@ static ssize_t store_fan_div(struct device *dev, struct device_attribute
 		v = 3;
 		break;
 	default:
-		dev_err(dev, "fan_div value %lu not supported. "
-			"Choose one of 2, 4 or 8!\n", v);
+		dev_err(dev,
+			"fan_div value %lu not supported. Choose one of 2, 4 or 8!\n",
+			v);
 		return -EINVAL;
 	}
 
@@ -1249,8 +1250,8 @@ static int fschmd_probe(struct i2c_client *client,
 	}
 	if (i == ARRAY_SIZE(watchdog_minors)) {
 		data->watchdog_miscdev.minor = 0;
-		dev_warn(&client->dev, "Couldn't register watchdog chardev "
-			"(due to no free minor)\n");
+		dev_warn(&client->dev,
+			 "Couldn't register watchdog chardev (due to no free minor)\n");
 	}
 	mutex_unlock(&watchdog_data_mutex);
 
diff --git a/drivers/hwmon/gl518sm.c b/drivers/hwmon/gl518sm.c
index e2e5909..95257a5 100644
--- a/drivers/hwmon/gl518sm.c
+++ b/drivers/hwmon/gl518sm.c
@@ -344,8 +344,9 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
 		val = 3;
 		break;
 	default:
-		dev_err(dev, "Invalid fan clock divider %lu, choose one "
-			"of 1, 2, 4 or 8\n", val);
+		dev_err(dev,
+			"Invalid fan clock divider %lu, choose one of 1, 2, 4 or 8\n",
+			val);
 		return -EINVAL;
 	}
 
diff --git a/drivers/hwmon/gpio-fan.c b/drivers/hwmon/gpio-fan.c
index 3978194..3104149 100644
--- a/drivers/hwmon/gpio-fan.c
+++ b/drivers/hwmon/gpio-fan.c
@@ -105,10 +105,6 @@ static int fan_alarm_init(struct gpio_fan_data *fan_data,
 	if (err)
 		return err;
 
-	err = device_create_file(&pdev->dev, &dev_attr_fan1_alarm);
-	if (err)
-		return err;
-
 	/*
 	 * If the alarm GPIO don't support interrupts, just leave
 	 * without initializing the fail notification support.
@@ -121,23 +117,9 @@ static int fan_alarm_init(struct gpio_fan_data *fan_data,
 	irq_set_irq_type(alarm_irq, IRQ_TYPE_EDGE_BOTH);
 	err = devm_request_irq(&pdev->dev, alarm_irq, fan_alarm_irq_handler,
 			       IRQF_SHARED, "GPIO fan alarm", fan_data);
-	if (err)
-		goto err_free_sysfs;
-
-	return 0;
-
-err_free_sysfs:
-	device_remove_file(&pdev->dev, &dev_attr_fan1_alarm);
 	return err;
 }
 
-static void fan_alarm_free(struct gpio_fan_data *fan_data)
-{
-	struct platform_device *pdev = fan_data->pdev;
-
-	device_remove_file(&pdev->dev, &dev_attr_fan1_alarm);
-}
-
 /*
  * Control GPIOs.
  */
@@ -327,6 +309,12 @@ exit_unlock:
 	return ret;
 }
 
+static ssize_t show_name(struct device *dev,
+			 struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "gpio-fan\n");
+}
+
 static DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm, set_pwm);
 static DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR,
 		   show_pwm_enable, set_pwm_enable);
@@ -336,8 +324,26 @@ static DEVICE_ATTR(fan1_max, S_IRUGO, show_rpm_max, NULL);
 static DEVICE_ATTR(fan1_input, S_IRUGO, show_rpm, NULL);
 static DEVICE_ATTR(fan1_target, S_IRUGO | S_IWUSR, show_rpm, set_rpm);
 
-static struct attribute *gpio_fan_ctrl_attributes[] = {
-	&dev_attr_pwm1.attr,
+static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
+
+static umode_t gpio_fan_is_visible(struct kobject *kobj,
+				   struct attribute *attr, int index)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct gpio_fan_data *data = dev_get_drvdata(dev);
+
+	if (index == 1 && !data->alarm)
+		return 0;
+	if (index > 1 && !data->ctrl)
+		return 0;
+
+	return attr->mode;
+}
+
+static struct attribute *gpio_fan_attributes[] = {
+	&dev_attr_name.attr,
+	&dev_attr_fan1_alarm.attr,		/* 1 */
+	&dev_attr_pwm1.attr,			/* 2 */
 	&dev_attr_pwm1_enable.attr,
 	&dev_attr_pwm1_mode.attr,
 	&dev_attr_fan1_input.attr,
@@ -347,8 +353,9 @@ static struct attribute *gpio_fan_ctrl_attributes[] = {
 	NULL
 };
 
-static const struct attribute_group gpio_fan_ctrl_group = {
-	.attrs = gpio_fan_ctrl_attributes,
+static const struct attribute_group gpio_fan_group = {
+	.attrs = gpio_fan_attributes,
+	.is_visible = gpio_fan_is_visible,
 };
 
 static int fan_ctrl_init(struct gpio_fan_data *fan_data,
@@ -379,30 +386,9 @@ static int fan_ctrl_init(struct gpio_fan_data *fan_data,
 	if (fan_data->speed_index < 0)
 		return -ENODEV;
 
-	err = sysfs_create_group(&pdev->dev.kobj, &gpio_fan_ctrl_group);
-	return err;
-}
-
-static void fan_ctrl_free(struct gpio_fan_data *fan_data)
-{
-	struct platform_device *pdev = fan_data->pdev;
-
-	sysfs_remove_group(&pdev->dev.kobj, &gpio_fan_ctrl_group);
-}
-
-/*
- * Platform driver.
- */
-
-static ssize_t show_name(struct device *dev,
-			 struct device_attribute *attr, char *buf)
-{
-	return sprintf(buf, "gpio-fan\n");
+	return 0;
 }
 
-static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
-
-
 #ifdef CONFIG_OF_GPIO
 /*
  * Translate OpenFirmware node properties into platform_data
@@ -546,38 +532,30 @@ static int gpio_fan_probe(struct platform_device *pdev)
 
 	/* Configure control GPIOs if available. */
 	if (pdata->ctrl && pdata->num_ctrl > 0) {
-		if (!pdata->speed || pdata->num_speed <= 1) {
-			err = -EINVAL;
-			goto err_free_alarm;
-		}
+		if (!pdata->speed || pdata->num_speed <= 1)
+			return -EINVAL;
 		err = fan_ctrl_init(fan_data, pdata);
 		if (err)
-			goto err_free_alarm;
+			return err;
 	}
 
-	err = device_create_file(&pdev->dev, &dev_attr_name);
+	err = sysfs_create_group(&pdev->dev.kobj, &gpio_fan_group);
 	if (err)
-		goto err_free_ctrl;
+		return err;
 
 	/* Make this driver part of hwmon class. */
 	fan_data->hwmon_dev = hwmon_device_register(&pdev->dev);
 	if (IS_ERR(fan_data->hwmon_dev)) {
 		err = PTR_ERR(fan_data->hwmon_dev);
-		goto err_remove_name;
+		goto err_remove;
 	}
 
 	dev_info(&pdev->dev, "GPIO fan initialized\n");
 
 	return 0;
 
-err_remove_name:
-	device_remove_file(&pdev->dev, &dev_attr_name);
-err_free_ctrl:
-	if (fan_data->ctrl)
-		fan_ctrl_free(fan_data);
-err_free_alarm:
-	if (fan_data->alarm)
-		fan_alarm_free(fan_data);
+err_remove:
+	sysfs_remove_group(&pdev->dev.kobj, &gpio_fan_group);
 	return err;
 }
 
@@ -586,11 +564,7 @@ static int gpio_fan_remove(struct platform_device *pdev)
 	struct gpio_fan_data *fan_data = platform_get_drvdata(pdev);
 
 	hwmon_device_unregister(fan_data->hwmon_dev);
-	device_remove_file(&pdev->dev, &dev_attr_name);
-	if (fan_data->alarm)
-		fan_alarm_free(fan_data);
-	if (fan_data->ctrl)
-		fan_ctrl_free(fan_data);
+	sysfs_remove_group(&pdev->dev.kobj, &gpio_fan_group);
 
 	return 0;
 }
@@ -619,7 +593,7 @@ static int gpio_fan_resume(struct device *dev)
 }
 
 static SIMPLE_DEV_PM_OPS(gpio_fan_pm, gpio_fan_suspend, gpio_fan_resume);
-#define GPIO_FAN_PM	&gpio_fan_pm
+#define GPIO_FAN_PM	(&gpio_fan_pm)
 #else
 #define GPIO_FAN_PM	NULL
 #endif
diff --git a/drivers/hwmon/ibmaem.c b/drivers/hwmon/ibmaem.c
index a14f634..1429f6e 100644
--- a/drivers/hwmon/ibmaem.c
+++ b/drivers/hwmon/ibmaem.c
@@ -289,8 +289,9 @@ static int aem_init_ipmi_data(struct aem_ipmi_data *data, int iface,
 	err = ipmi_create_user(data->interface, &driver_data.ipmi_hndlrs,
 			       data, &data->user);
 	if (err < 0) {
-		dev_err(bmc, "Unable to register user with IPMI "
-			"interface %d\n", data->interface);
+		dev_err(bmc,
+			"Unable to register user with IPMI interface %d\n",
+			data->interface);
 		return -EACCES;
 	}
 
@@ -328,8 +329,8 @@ static void aem_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data)
 	struct aem_ipmi_data *data = user_msg_data;
 
 	if (msg->msgid != data->tx_msgid) {
-		dev_err(data->bmc_device, "Mismatch between received msgid "
-			"(%02x) and transmitted msgid (%02x)!\n",
+		dev_err(data->bmc_device,
+			"Mismatch between received msgid (%02x) and transmitted msgid (%02x)!\n",
 			(int)msg->msgid,
 			(int)data->tx_msgid);
 		ipmi_free_recv_msg(msg);
@@ -575,8 +576,8 @@ static int aem_init_aem1_inst(struct aem_ipmi_data *probe, u8 module_handle)
 	/* Register with hwmon */
 	data->hwmon_dev = hwmon_device_register(&data->pdev->dev);
 	if (IS_ERR(data->hwmon_dev)) {
-		dev_err(&data->pdev->dev, "Unable to register hwmon "
-			"device for IPMI interface %d\n",
+		dev_err(&data->pdev->dev,
+			"Unable to register hwmon device for IPMI interface %d\n",
 			probe->interface);
 		res = PTR_ERR(data->hwmon_dev);
 		goto hwmon_reg_err;
@@ -715,8 +716,8 @@ static int aem_init_aem2_inst(struct aem_ipmi_data *probe,
 	/* Register with hwmon */
 	data->hwmon_dev = hwmon_device_register(&data->pdev->dev);
 	if (IS_ERR(data->hwmon_dev)) {
-		dev_err(&data->pdev->dev, "Unable to register hwmon "
-			"device for IPMI interface %d\n",
+		dev_err(&data->pdev->dev,
+			"Unable to register hwmon device for IPMI interface %d\n",
 			probe->interface);
 		res = PTR_ERR(data->hwmon_dev);
 		goto hwmon_reg_err;
@@ -768,8 +769,8 @@ static void aem_init_aem2(struct aem_ipmi_data *probe)
 
 	while (!aem_find_aem2(probe, &fi_resp, i)) {
 		if (fi_resp.major != 2) {
-			dev_err(probe->bmc_device, "Unknown AEM v%d; please "
-				"report this to the maintainer.\n",
+			dev_err(probe->bmc_device,
+				"Unknown AEM v%d; please report this to the maintainer.\n",
 				fi_resp.major);
 			i++;
 			continue;
diff --git a/drivers/hwmon/ibmpex.c b/drivers/hwmon/ibmpex.c
index b622a93..74b365e 100644
--- a/drivers/hwmon/ibmpex.c
+++ b/drivers/hwmon/ibmpex.c
@@ -163,8 +163,8 @@ static int ibmpex_ver_check(struct ibmpex_bmc_data *data)
 	data->sensor_major = data->rx_msg_data[0];
 	data->sensor_minor = data->rx_msg_data[1];
 
-	dev_info(data->bmc_device, "Found BMC with sensor interface "
-		 "v%d.%d %d-%02d-%02d on interface %d\n",
+	dev_info(data->bmc_device,
+		 "Found BMC with sensor interface v%d.%d %d-%02d-%02d on interface %d\n",
 		 data->sensor_major,
 		 data->sensor_minor,
 		 extract_value(data->rx_msg_data, 2),
@@ -478,8 +478,9 @@ static void ibmpex_register_bmc(int iface, struct device *dev)
 	err = ipmi_create_user(data->interface, &driver_data.ipmi_hndlrs,
 			       data, &data->user);
 	if (err < 0) {
-		dev_err(dev, "Unable to register user with IPMI "
-			"interface %d\n", data->interface);
+		dev_err(dev,
+			"Unable to register user with IPMI interface %d\n",
+			data->interface);
 		goto out;
 	}
 
@@ -501,8 +502,8 @@ static void ibmpex_register_bmc(int iface, struct device *dev)
 	data->hwmon_dev = hwmon_device_register(data->bmc_device);
 
 	if (IS_ERR(data->hwmon_dev)) {
-		dev_err(data->bmc_device, "Unable to register hwmon "
-			"device for IPMI interface %d\n",
+		dev_err(data->bmc_device,
+			"Unable to register hwmon device for IPMI interface %d\n",
 			data->interface);
 		goto out_user;
 	}
@@ -567,8 +568,8 @@ static void ibmpex_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data)
 	struct ibmpex_bmc_data *data = (struct ibmpex_bmc_data *)user_msg_data;
 
 	if (msg->msgid != data->tx_msgid) {
-		dev_err(data->bmc_device, "Mismatch between received msgid "
-			"(%02x) and transmitted msgid (%02x)!\n",
+		dev_err(data->bmc_device,
+			"Mismatch between received msgid (%02x) and transmitted msgid (%02x)!\n",
 			(int)msg->msgid,
 			(int)data->tx_msgid);
 		ipmi_free_recv_msg(msg);
diff --git a/drivers/hwmon/iio_hwmon.c b/drivers/hwmon/iio_hwmon.c
new file mode 100644
index 0000000..aafa453
--- /dev/null
+++ b/drivers/hwmon/iio_hwmon.c
@@ -0,0 +1,196 @@
+/* Hwmon client for industrial I/O devices
+ *
+ * Copyright (c) 2011 Jonathan Cameron
+ *
+ * This program is free software; you can 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/slab.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/hwmon.h>
+#include <linux/of.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/iio/consumer.h>
+#include <linux/iio/types.h>
+
+/**
+ * struct iio_hwmon_state - device instance state
+ * @channels:		filled with array of channels from iio
+ * @num_channels:	number of channels in channels (saves counting twice)
+ * @hwmon_dev:		associated hwmon device
+ * @attr_group:	the group of attributes
+ * @attrs:		null terminated array of attribute pointers.
+ */
+struct iio_hwmon_state {
+	struct iio_channel *channels;
+	int num_channels;
+	struct device *hwmon_dev;
+	struct attribute_group attr_group;
+	struct attribute **attrs;
+};
+
+/*
+ * Assumes that IIO and hwmon operate in the same base units.
+ * This is supposed to be true, but needs verification for
+ * new channel types.
+ */
+static ssize_t iio_hwmon_read_val(struct device *dev,
+				  struct device_attribute *attr,
+				  char *buf)
+{
+	int result;
+	int ret;
+	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
+	struct iio_hwmon_state *state = dev_get_drvdata(dev);
+
+	ret = iio_read_channel_processed(&state->channels[sattr->index],
+					&result);
+	if (ret < 0)
+		return ret;
+
+	return sprintf(buf, "%d\n", result);
+}
+
+static ssize_t show_name(struct device *dev, struct device_attribute *attr,
+			 char *buf)
+{
+	const char *name = "iio_hwmon";
+
+	if (dev->of_node && dev->of_node->name)
+		name = dev->of_node->name;
+
+	return sprintf(buf, "%s\n", name);
+}
+
+static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
+
+static int iio_hwmon_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct iio_hwmon_state *st;
+	struct sensor_device_attribute *a;
+	int ret, i;
+	int in_i = 1, temp_i = 1, curr_i = 1;
+	enum iio_chan_type type;
+	struct iio_channel *channels;
+
+	channels = iio_channel_get_all(dev);
+	if (IS_ERR(channels))
+		return PTR_ERR(channels);
+
+	st = devm_kzalloc(dev, sizeof(*st), GFP_KERNEL);
+	if (st == NULL)
+		return -ENOMEM;
+
+	st->channels = channels;
+
+	/* count how many attributes we have */
+	while (st->channels[st->num_channels].indio_dev)
+		st->num_channels++;
+
+	st->attrs = devm_kzalloc(dev,
+				 sizeof(*st->attrs) * (st->num_channels + 2),
+				 GFP_KERNEL);
+	if (st->attrs == NULL) {
+		ret = -ENOMEM;
+		goto error_release_channels;
+	}
+
+	for (i = 0; i < st->num_channels; i++) {
+		a = devm_kzalloc(dev, sizeof(*a), GFP_KERNEL);
+		if (a == NULL) {
+			ret = -ENOMEM;
+			goto error_release_channels;
+		}
+
+		sysfs_attr_init(&a->dev_attr.attr);
+		ret = iio_get_channel_type(&st->channels[i], &type);
+		if (ret < 0)
+			goto error_release_channels;
+
+		switch (type) {
+		case IIO_VOLTAGE:
+			a->dev_attr.attr.name = kasprintf(GFP_KERNEL,
+							  "in%d_input",
+							  in_i++);
+			break;
+		case IIO_TEMP:
+			a->dev_attr.attr.name = kasprintf(GFP_KERNEL,
+							  "temp%d_input",
+							  temp_i++);
+			break;
+		case IIO_CURRENT:
+			a->dev_attr.attr.name = kasprintf(GFP_KERNEL,
+							  "curr%d_input",
+							  curr_i++);
+			break;
+		default:
+			ret = -EINVAL;
+			goto error_release_channels;
+		}
+		if (a->dev_attr.attr.name == NULL) {
+			ret = -ENOMEM;
+			goto error_release_channels;
+		}
+		a->dev_attr.show = iio_hwmon_read_val;
+		a->dev_attr.attr.mode = S_IRUGO;
+		a->index = i;
+		st->attrs[i] = &a->dev_attr.attr;
+	}
+	st->attrs[st->num_channels] = &dev_attr_name.attr;
+	st->attr_group.attrs = st->attrs;
+	platform_set_drvdata(pdev, st);
+	ret = sysfs_create_group(&dev->kobj, &st->attr_group);
+	if (ret < 0)
+		goto error_release_channels;
+
+	st->hwmon_dev = hwmon_device_register(dev);
+	if (IS_ERR(st->hwmon_dev)) {
+		ret = PTR_ERR(st->hwmon_dev);
+		goto error_remove_group;
+	}
+	return 0;
+
+error_remove_group:
+	sysfs_remove_group(&dev->kobj, &st->attr_group);
+error_release_channels:
+	iio_channel_release_all(st->channels);
+	return ret;
+}
+
+static int iio_hwmon_remove(struct platform_device *pdev)
+{
+	struct iio_hwmon_state *st = platform_get_drvdata(pdev);
+
+	hwmon_device_unregister(st->hwmon_dev);
+	sysfs_remove_group(&pdev->dev.kobj, &st->attr_group);
+	iio_channel_release_all(st->channels);
+
+	return 0;
+}
+
+static struct of_device_id iio_hwmon_of_match[] = {
+	{ .compatible = "iio-hwmon", },
+	{ }
+};
+
+static struct platform_driver __refdata iio_hwmon_driver = {
+	.driver = {
+		.name = "iio_hwmon",
+		.owner = THIS_MODULE,
+		.of_match_table = iio_hwmon_of_match,
+	},
+	.probe = iio_hwmon_probe,
+	.remove = iio_hwmon_remove,
+};
+
+module_platform_driver(iio_hwmon_driver);
+
+MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>");
+MODULE_DESCRIPTION("IIO to hwmon driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/hwmon/ina2xx.c b/drivers/hwmon/ina2xx.c
index 8e7158c..4958b2f 100644
--- a/drivers/hwmon/ina2xx.c
+++ b/drivers/hwmon/ina2xx.c
@@ -186,20 +186,20 @@ static ssize_t ina2xx_show_value(struct device *dev,
 }
 
 /* shunt voltage */
-static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, \
-	ina2xx_show_value, NULL, INA2XX_SHUNT_VOLTAGE);
+static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, ina2xx_show_value, NULL,
+			  INA2XX_SHUNT_VOLTAGE);
 
 /* bus voltage */
-static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, \
-	ina2xx_show_value, NULL, INA2XX_BUS_VOLTAGE);
+static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, ina2xx_show_value, NULL,
+			  INA2XX_BUS_VOLTAGE);
 
 /* calculated current */
-static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, \
-	ina2xx_show_value, NULL, INA2XX_CURRENT);
+static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, ina2xx_show_value, NULL,
+			  INA2XX_CURRENT);
 
 /* calculated power */
-static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, \
-	ina2xx_show_value, NULL, INA2XX_POWER);
+static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, ina2xx_show_value, NULL,
+			  INA2XX_POWER);
 
 /* pointers to created device attributes */
 static struct attribute *ina2xx_attributes[] = {
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c
index 37fc980..72b21d5 100644
--- a/drivers/hwmon/it87.c
+++ b/drivers/hwmon/it87.c
@@ -1778,7 +1778,7 @@ static int __init it87_find(unsigned short *address,
 		superio_select(5);
 		sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f;
 	} else if (sio_data->type == it8783) {
-		int reg25, reg27, reg2A, reg2C, regEF;
+		int reg25, reg27, reg2a, reg2c, regef;
 
 		sio_data->skip_vid = 1;	/* No VID */
 
@@ -1786,15 +1786,15 @@ static int __init it87_find(unsigned short *address,
 
 		reg25 = superio_inb(IT87_SIO_GPIO1_REG);
 		reg27 = superio_inb(IT87_SIO_GPIO3_REG);
-		reg2A = superio_inb(IT87_SIO_PINX1_REG);
-		reg2C = superio_inb(IT87_SIO_PINX2_REG);
-		regEF = superio_inb(IT87_SIO_SPI_REG);
+		reg2a = superio_inb(IT87_SIO_PINX1_REG);
+		reg2c = superio_inb(IT87_SIO_PINX2_REG);
+		regef = superio_inb(IT87_SIO_SPI_REG);
 
 		/* Check if fan3 is there or not */
-		if ((reg27 & (1 << 0)) || !(reg2C & (1 << 2)))
+		if ((reg27 & (1 << 0)) || !(reg2c & (1 << 2)))
 			sio_data->skip_fan |= (1 << 2);
 		if ((reg25 & (1 << 4))
-		    || (!(reg2A & (1 << 1)) && (regEF & (1 << 0))))
+		    || (!(reg2a & (1 << 1)) && (regef & (1 << 0))))
 			sio_data->skip_pwm |= (1 << 2);
 
 		/* Check if fan2 is there or not */
@@ -1804,7 +1804,7 @@ static int __init it87_find(unsigned short *address,
 			sio_data->skip_pwm |= (1 << 1);
 
 		/* VIN5 */
-		if ((reg27 & (1 << 0)) || (reg2C & (1 << 2)))
+		if ((reg27 & (1 << 0)) || (reg2c & (1 << 2)))
 			sio_data->skip_in |= (1 << 5); /* No VIN5 */
 
 		/* VIN6 */
@@ -1829,18 +1829,18 @@ static int __init it87_find(unsigned short *address,
 			 * not the case, and ask the user to report if the
 			 * resulting voltage is sane.
 			 */
-			if (!(reg2C & (1 << 1))) {
-				reg2C |= (1 << 1);
-				superio_outb(IT87_SIO_PINX2_REG, reg2C);
+			if (!(reg2c & (1 << 1))) {
+				reg2c |= (1 << 1);
+				superio_outb(IT87_SIO_PINX2_REG, reg2c);
 				pr_notice("Routing internal VCCH5V to in7.\n");
 			}
 			pr_notice("in7 routed to internal voltage divider, with external pin disabled.\n");
 			pr_notice("Please report if it displays a reasonable voltage.\n");
 		}
 
-		if (reg2C & (1 << 0))
+		if (reg2c & (1 << 0))
 			sio_data->internal |= (1 << 0);
-		if (reg2C & (1 << 1))
+		if (reg2c & (1 << 1))
 			sio_data->internal |= (1 << 1);
 
 		sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f;
diff --git a/drivers/hwmon/k8temp.c b/drivers/hwmon/k8temp.c
index 9f3c0ae..5b50e9e 100644
--- a/drivers/hwmon/k8temp.c
+++ b/drivers/hwmon/k8temp.c
@@ -200,8 +200,8 @@ static int k8temp_probe(struct pci_dev *pdev,
 	 */
 	if (model >= 0x40) {
 		data->swap_core_select = 1;
-		dev_warn(&pdev->dev, "Temperature readouts might be wrong - "
-			 "check erratum #141\n");
+		dev_warn(&pdev->dev,
+			 "Temperature readouts might be wrong - check erratum #141\n");
 	}
 
 	/*
diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c
index 291edff..c03b490 100644
--- a/drivers/hwmon/lm75.c
+++ b/drivers/hwmon/lm75.c
@@ -38,6 +38,7 @@ enum lm75_type {		/* keep sorted in alphabetical order */
 	adt75,
 	ds1775,
 	ds75,
+	ds7505,
 	lm75,
 	lm75a,
 	max6625,
@@ -71,9 +72,12 @@ struct lm75_data {
 	struct device		*hwmon_dev;
 	struct mutex		update_lock;
 	u8			orig_conf;
+	u8			resolution;	/* In bits, between 9 and 12 */
+	u8			resolution_limits;
 	char			valid;		/* !=0 if registers are valid */
 	unsigned long		last_updated;	/* In jiffies */
-	u16			temp[3];	/* Register values,
+	unsigned long		sample_time;	/* In jiffies */
+	s16			temp[3];	/* Register values,
 						   0 = input
 						   1 = max
 						   2 = hyst */
@@ -93,12 +97,15 @@ static ssize_t show_temp(struct device *dev, struct device_attribute *da,
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
 	struct lm75_data *data = lm75_update_device(dev);
+	long temp;
 
 	if (IS_ERR(data))
 		return PTR_ERR(data);
 
-	return sprintf(buf, "%d\n",
-		       LM75_TEMP_FROM_REG(data->temp[attr->index]));
+	temp = ((data->temp[attr->index] >> (16 - data->resolution)) * 1000)
+	       >> (data->resolution - 8);
+
+	return sprintf(buf, "%ld\n", temp);
 }
 
 static ssize_t set_temp(struct device *dev, struct device_attribute *da,
@@ -110,13 +117,25 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *da,
 	int nr = attr->index;
 	long temp;
 	int error;
+	u8 resolution;
 
 	error = kstrtol(buf, 10, &temp);
 	if (error)
 		return error;
 
+	/*
+	 * Resolution of limit registers is assumed to be the same as the
+	 * temperature input register resolution unless given explicitly.
+	 */
+	if (attr->index && data->resolution_limits)
+		resolution = data->resolution_limits;
+	else
+		resolution = data->resolution;
+
 	mutex_lock(&data->update_lock);
-	data->temp[nr] = LM75_TEMP_TO_REG(temp);
+	temp = clamp_val(temp, LM75_TEMP_MIN, LM75_TEMP_MAX);
+	data->temp[nr] = DIV_ROUND_CLOSEST(temp  << (resolution - 8),
+					   1000) << (16 - resolution);
 	lm75_write_value(client, LM75_REG_TEMP[nr], data->temp[nr]);
 	mutex_unlock(&data->update_lock);
 	return count;
@@ -151,6 +170,7 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	int status;
 	u8 set_mask, clr_mask;
 	int new;
+	enum lm75_type kind = id->driver_data;
 
 	if (!i2c_check_functionality(client->adapter,
 			I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA))
@@ -167,8 +187,65 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	 * Then tweak to be more precise when appropriate.
 	 */
 	set_mask = 0;
-	clr_mask = (1 << 0)			/* continuous conversions */
-		| (1 << 6) | (1 << 5);		/* 9-bit mode */
+	clr_mask = LM75_SHUTDOWN;		/* continuous conversions */
+
+	switch (kind) {
+	case adt75:
+		clr_mask |= 1 << 5;		/* not one-shot mode */
+		data->resolution = 12;
+		data->sample_time = HZ / 8;
+		break;
+	case ds1775:
+	case ds75:
+	case stds75:
+		clr_mask |= 3 << 5;
+		set_mask |= 2 << 5;		/* 11-bit mode */
+		data->resolution = 11;
+		data->sample_time = HZ;
+		break;
+	case ds7505:
+		set_mask |= 3 << 5;		/* 12-bit mode */
+		data->resolution = 12;
+		data->sample_time = HZ / 4;
+		break;
+	case lm75:
+	case lm75a:
+		data->resolution = 9;
+		data->sample_time = HZ / 2;
+		break;
+	case max6625:
+		data->resolution = 9;
+		data->sample_time = HZ / 4;
+		break;
+	case max6626:
+		data->resolution = 12;
+		data->resolution_limits = 9;
+		data->sample_time = HZ / 4;
+		break;
+	case tcn75:
+		data->resolution = 9;
+		data->sample_time = HZ / 8;
+		break;
+	case mcp980x:
+		data->resolution_limits = 9;
+		/* fall through */
+	case tmp100:
+	case tmp101:
+		set_mask |= 3 << 5;		/* 12-bit mode */
+		data->resolution = 12;
+		data->sample_time = HZ;
+		clr_mask |= 1 << 7;		/* not one-shot mode */
+		break;
+	case tmp105:
+	case tmp175:
+	case tmp275:
+	case tmp75:
+		set_mask |= 3 << 5;		/* 12-bit mode */
+		clr_mask |= 1 << 7;		/* not one-shot mode */
+		data->resolution = 12;
+		data->sample_time = HZ / 2;
+		break;
+	}
 
 	/* configure as specified */
 	status = lm75_read_value(client, LM75_REG_CONF);
@@ -218,6 +295,7 @@ static const struct i2c_device_id lm75_ids[] = {
 	{ "adt75", adt75, },
 	{ "ds1775", ds1775, },
 	{ "ds75", ds75, },
+	{ "ds7505", ds7505, },
 	{ "lm75", lm75, },
 	{ "lm75a", lm75a, },
 	{ "max6625", max6625, },
@@ -407,7 +485,7 @@ static struct lm75_data *lm75_update_device(struct device *dev)
 
 	mutex_lock(&data->update_lock);
 
-	if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
+	if (time_after(jiffies, data->last_updated + data->sample_time)
 	    || !data->valid) {
 		int i;
 		dev_dbg(&client->dev, "Starting lm75 update\n");
diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c
index 483538f..6cf6bff 100644
--- a/drivers/hwmon/lm78.c
+++ b/drivers/hwmon/lm78.c
@@ -386,8 +386,9 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *da,
 		data->fan_div[nr] = 3;
 		break;
 	default:
-		dev_err(dev, "fan_div value %ld not "
-			"supported. Choose one of 1, 2, 4 or 8!\n", val);
+		dev_err(dev,
+			"fan_div value %ld not supported. Choose one of 1, 2, 4 or 8!\n",
+			val);
 		mutex_unlock(&data->update_lock);
 		return -EINVAL;
 	}
@@ -636,8 +637,9 @@ static int lm78_i2c_detect(struct i2c_client *client,
 		goto err_nodev;
 
 	if (lm78_alias_detect(client, i)) {
-		dev_dbg(&adapter->dev, "Device at 0x%02x appears to "
-			"be the same as ISA device\n", address);
+		dev_dbg(&adapter->dev,
+			"Device at 0x%02x appears to be the same as ISA device\n",
+			address);
 		goto err_nodev;
 	}
 
diff --git a/drivers/hwmon/lm80.c b/drivers/hwmon/lm80.c
index 357fbb9..eba89aa 100644
--- a/drivers/hwmon/lm80.c
+++ b/drivers/hwmon/lm80.c
@@ -286,8 +286,9 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
 		data->fan_div[nr] = 3;
 		break;
 	default:
-		dev_err(&client->dev, "fan_div value %ld not "
-			"supported. Choose one of 1, 2, 4 or 8!\n", val);
+		dev_err(&client->dev,
+			"fan_div value %ld not supported. Choose one of 1, 2, 4 or 8!\n",
+			val);
 		mutex_unlock(&data->update_lock);
 		return -EINVAL;
 	}
diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c
index 47ade8b..3894c40 100644
--- a/drivers/hwmon/lm85.c
+++ b/drivers/hwmon/lm85.c
@@ -1293,8 +1293,8 @@ static int lm85_detect(struct i2c_client *client, struct i2c_board_info *info)
 	company = lm85_read_value(client, LM85_REG_COMPANY);
 	verstep = lm85_read_value(client, LM85_REG_VERSTEP);
 
-	dev_dbg(&adapter->dev, "Detecting device at 0x%02x with "
-		"COMPANY: 0x%02x and VERSTEP: 0x%02x\n",
+	dev_dbg(&adapter->dev,
+		"Detecting device at 0x%02x with COMPANY: 0x%02x and VERSTEP: 0x%02x\n",
 		address, company, verstep);
 
 	/* All supported chips have the version in common */
diff --git a/drivers/hwmon/lm93.c b/drivers/hwmon/lm93.c
index b40f34c..a6f4605 100644
--- a/drivers/hwmon/lm93.c
+++ b/drivers/hwmon/lm93.c
@@ -354,12 +354,12 @@ static const unsigned long lm93_vin_val_max[16] = {
 
 static unsigned LM93_IN_FROM_REG(int nr, u8 reg)
 {
-	const long uV_max = lm93_vin_val_max[nr] * 1000;
-	const long uV_min = lm93_vin_val_min[nr] * 1000;
+	const long uv_max = lm93_vin_val_max[nr] * 1000;
+	const long uv_min = lm93_vin_val_min[nr] * 1000;
 
-	const long slope = (uV_max - uV_min) /
+	const long slope = (uv_max - uv_min) /
 		(lm93_vin_reg_max[nr] - lm93_vin_reg_min[nr]);
-	const long intercept = uV_min - slope * lm93_vin_reg_min[nr];
+	const long intercept = uv_min - slope * lm93_vin_reg_min[nr];
 
 	return (slope * reg + intercept + 500) / 1000;
 }
@@ -371,20 +371,20 @@ static unsigned LM93_IN_FROM_REG(int nr, u8 reg)
 static u8 LM93_IN_TO_REG(int nr, unsigned val)
 {
 	/* range limit */
-	const long mV = clamp_val(val,
+	const long mv = clamp_val(val,
 				  lm93_vin_val_min[nr], lm93_vin_val_max[nr]);
 
 	/* try not to lose too much precision here */
-	const long uV = mV * 1000;
-	const long uV_max = lm93_vin_val_max[nr] * 1000;
-	const long uV_min = lm93_vin_val_min[nr] * 1000;
+	const long uv = mv * 1000;
+	const long uv_max = lm93_vin_val_max[nr] * 1000;
+	const long uv_min = lm93_vin_val_min[nr] * 1000;
 
 	/* convert */
-	const long slope = (uV_max - uV_min) /
+	const long slope = (uv_max - uv_min) /
 		(lm93_vin_reg_max[nr] - lm93_vin_reg_min[nr]);
-	const long intercept = uV_min - slope * lm93_vin_reg_min[nr];
+	const long intercept = uv_min - slope * lm93_vin_reg_min[nr];
 
-	u8 result = ((uV - intercept + (slope/2)) / slope);
+	u8 result = ((uv - intercept + (slope/2)) / slope);
 	result = clamp_val(result,
 			   lm93_vin_reg_min[nr], lm93_vin_reg_max[nr]);
 	return result;
@@ -393,10 +393,10 @@ static u8 LM93_IN_TO_REG(int nr, unsigned val)
 /* vid in mV, upper == 0 indicates low limit, otherwise upper limit */
 static unsigned LM93_IN_REL_FROM_REG(u8 reg, int upper, int vid)
 {
-	const long uV_offset = upper ? (((reg >> 4 & 0x0f) + 1) * 12500) :
+	const long uv_offset = upper ? (((reg >> 4 & 0x0f) + 1) * 12500) :
 				(((reg >> 0 & 0x0f) + 1) * -25000);
-	const long uV_vid = vid * 1000;
-	return (uV_vid + uV_offset + 5000) / 10000;
+	const long uv_vid = vid * 1000;
+	return (uv_vid + uv_offset + 5000) / 10000;
 }
 
 #define LM93_IN_MIN_FROM_REG(reg, vid)	LM93_IN_REL_FROM_REG((reg), 0, (vid))
@@ -409,13 +409,13 @@ static unsigned LM93_IN_REL_FROM_REG(u8 reg, int upper, int vid)
  */
 static u8 LM93_IN_REL_TO_REG(unsigned val, int upper, int vid)
 {
-	long uV_offset = vid * 1000 - val * 10000;
+	long uv_offset = vid * 1000 - val * 10000;
 	if (upper) {
-		uV_offset = clamp_val(uV_offset, 12500, 200000);
-		return (u8)((uV_offset /  12500 - 1) << 4);
+		uv_offset = clamp_val(uv_offset, 12500, 200000);
+		return (u8)((uv_offset /  12500 - 1) << 4);
 	} else {
-		uV_offset = clamp_val(uV_offset, -400000, -25000);
-		return (u8)((uV_offset / -25000 - 1) << 0);
+		uv_offset = clamp_val(uv_offset, -400000, -25000);
+		return (u8)((uv_offset / -25000 - 1) << 0);
 	}
 }
 
@@ -818,8 +818,9 @@ static u8 lm93_read_byte(struct i2c_client *client, u8 reg)
 		if (value >= 0) {
 			return value;
 		} else {
-			dev_warn(&client->dev, "lm93: read byte data failed, "
-				"address 0x%02x.\n", reg);
+			dev_warn(&client->dev,
+				 "lm93: read byte data failed, address 0x%02x.\n",
+				 reg);
 			mdelay(i + 3);
 		}
 
@@ -838,8 +839,9 @@ static int lm93_write_byte(struct i2c_client *client, u8 reg, u8 value)
 	result = i2c_smbus_write_byte_data(client, reg, value);
 
 	if (result < 0)
-		dev_warn(&client->dev, "lm93: write byte data failed, "
-			 "0x%02x at address 0x%02x.\n", value, reg);
+		dev_warn(&client->dev,
+			 "lm93: write byte data failed, 0x%02x at address 0x%02x.\n",
+			 value, reg);
 
 	return result;
 }
@@ -854,8 +856,9 @@ static u16 lm93_read_word(struct i2c_client *client, u8 reg)
 		if (value >= 0) {
 			return value;
 		} else {
-			dev_warn(&client->dev, "lm93: read word data failed, "
-				 "address 0x%02x.\n", reg);
+			dev_warn(&client->dev,
+				 "lm93: read word data failed, address 0x%02x.\n",
+				 reg);
 			mdelay(i + 3);
 		}
 
@@ -874,8 +877,9 @@ static int lm93_write_word(struct i2c_client *client, u8 reg, u16 value)
 	result = i2c_smbus_write_word_data(client, reg, value);
 
 	if (result < 0)
-		dev_warn(&client->dev, "lm93: write word data failed, "
-			 "0x%04x at address 0x%02x.\n", value, reg);
+		dev_warn(&client->dev,
+			 "lm93: write word data failed, 0x%04x at address 0x%02x.\n",
+			 value, reg);
 
 	return result;
 }
@@ -898,8 +902,8 @@ static void lm93_read_block(struct i2c_client *client, u8 fbn, u8 *values)
 		if (result == lm93_block_read_cmds[fbn].len) {
 			break;
 		} else {
-			dev_warn(&client->dev, "lm93: block read data failed, "
-				 "command 0x%02x.\n",
+			dev_warn(&client->dev,
+				 "lm93: block read data failed, command 0x%02x.\n",
 				 lm93_block_read_cmds[fbn].cmd);
 			mdelay(i + 3);
 		}
@@ -2672,8 +2676,8 @@ static void lm93_init_client(struct i2c_client *client)
 			return;
 	}
 
-	dev_warn(&client->dev, "timed out waiting for sensor "
-		 "chip to signal ready!\n");
+	dev_warn(&client->dev,
+		 "timed out waiting for sensor chip to signal ready!\n");
 }
 
 /* Return 0 if detection is successful, -ENODEV otherwise */
@@ -2733,12 +2737,12 @@ static int lm93_probe(struct i2c_client *client,
 		dev_dbg(&client->dev, "using SMBus block data transactions\n");
 		update = lm93_update_client_full;
 	} else if ((LM93_SMBUS_FUNC_MIN & func) == LM93_SMBUS_FUNC_MIN) {
-		dev_dbg(&client->dev, "disabled SMBus block data "
-			"transactions\n");
+		dev_dbg(&client->dev,
+			"disabled SMBus block data transactions\n");
 		update = lm93_update_client_min;
 	} else {
-		dev_dbg(&client->dev, "detect failed, "
-			"smbus byte and/or word data not supported!\n");
+		dev_dbg(&client->dev,
+			"detect failed, smbus byte and/or word data not supported!\n");
 		return -ENODEV;
 	}
 
diff --git a/drivers/hwmon/lm95234.c b/drivers/hwmon/lm95234.c
new file mode 100644
index 0000000..307c9ea
--- /dev/null
+++ b/drivers/hwmon/lm95234.c
@@ -0,0 +1,769 @@
+/*
+ * Driver for Texas Instruments / National Semiconductor LM95234
+ *
+ * Copyright (c) 2013 Guenter Roeck <linux@roeck-us.net>
+ *
+ * Derived from lm95241.c
+ * Copyright (C) 2008, 2010 Davide Rizzo <elpa.rizzo@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.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/sysfs.h>
+
+#define DRVNAME "lm95234"
+
+static const unsigned short normal_i2c[] = { 0x18, 0x4d, 0x4e, I2C_CLIENT_END };
+
+/* LM95234 registers */
+#define LM95234_REG_MAN_ID		0xFE
+#define LM95234_REG_CHIP_ID		0xFF
+#define LM95234_REG_STATUS		0x02
+#define LM95234_REG_CONFIG		0x03
+#define LM95234_REG_CONVRATE		0x04
+#define LM95234_REG_STS_FAULT		0x07
+#define LM95234_REG_STS_TCRIT1		0x08
+#define LM95234_REG_STS_TCRIT2		0x09
+#define LM95234_REG_TEMPH(x)		((x) + 0x10)
+#define LM95234_REG_TEMPL(x)		((x) + 0x20)
+#define LM95234_REG_UTEMPH(x)		((x) + 0x19)	/* Remote only */
+#define LM95234_REG_UTEMPL(x)		((x) + 0x29)
+#define LM95234_REG_REM_MODEL		0x30
+#define LM95234_REG_REM_MODEL_STS	0x38
+#define LM95234_REG_OFFSET(x)		((x) + 0x31)	/* Remote only */
+#define LM95234_REG_TCRIT1(x)		((x) + 0x40)
+#define LM95234_REG_TCRIT2(x)		((x) + 0x49)	/* Remote channel 1,2 */
+#define LM95234_REG_TCRIT_HYST		0x5a
+
+#define NATSEMI_MAN_ID			0x01
+#define LM95234_CHIP_ID			0x79
+
+/* Client data (each client gets its own) */
+struct lm95234_data {
+	struct device *hwmon_dev;
+	struct mutex update_lock;
+	unsigned long last_updated, interval;	/* in jiffies */
+	bool valid;		/* false until following fields are valid */
+	/* registers values */
+	int temp[5];		/* temperature (signed) */
+	u32 status;		/* fault/alarm status */
+	u8 tcrit1[5];		/* critical temperature limit */
+	u8 tcrit2[2];		/* high temperature limit */
+	s8 toffset[4];		/* remote temperature offset */
+	u8 thyst;		/* common hysteresis */
+
+	u8 sensor_type;		/* temperature sensor type */
+};
+
+static int lm95234_read_temp(struct i2c_client *client, int index, int *t)
+{
+	int val;
+	u16 temp = 0;
+
+	if (index) {
+		val = i2c_smbus_read_byte_data(client,
+					       LM95234_REG_UTEMPH(index - 1));
+		if (val < 0)
+			return val;
+		temp = val << 8;
+		val = i2c_smbus_read_byte_data(client,
+					       LM95234_REG_UTEMPL(index - 1));
+		if (val < 0)
+			return val;
+		temp |= val;
+		*t = temp;
+	}
+	/*
+	 * Read signed temperature if unsigned temperature is 0,
+	 * or if this is the local sensor.
+	 */
+	if (!temp) {
+		val = i2c_smbus_read_byte_data(client,
+					       LM95234_REG_TEMPH(index));
+		if (val < 0)
+			return val;
+		temp = val << 8;
+		val = i2c_smbus_read_byte_data(client,
+					       LM95234_REG_TEMPL(index));
+		if (val < 0)
+			return val;
+		temp |= val;
+		*t = (s16)temp;
+	}
+	return 0;
+}
+
+static u16 update_intervals[] = { 143, 364, 1000, 2500 };
+
+/* Fill value cache. Must be called with update lock held. */
+
+static int lm95234_fill_cache(struct i2c_client *client)
+{
+	struct lm95234_data *data = i2c_get_clientdata(client);
+	int i, ret;
+
+	ret = i2c_smbus_read_byte_data(client, LM95234_REG_CONVRATE);
+	if (ret < 0)
+		return ret;
+
+	data->interval = msecs_to_jiffies(update_intervals[ret & 0x03]);
+
+	for (i = 0; i < ARRAY_SIZE(data->tcrit1); i++) {
+		ret = i2c_smbus_read_byte_data(client, LM95234_REG_TCRIT1(i));
+		if (ret < 0)
+			return ret;
+		data->tcrit1[i] = ret;
+	}
+	for (i = 0; i < ARRAY_SIZE(data->tcrit2); i++) {
+		ret = i2c_smbus_read_byte_data(client, LM95234_REG_TCRIT2(i));
+		if (ret < 0)
+			return ret;
+		data->tcrit2[i] = ret;
+	}
+	for (i = 0; i < ARRAY_SIZE(data->toffset); i++) {
+		ret = i2c_smbus_read_byte_data(client, LM95234_REG_OFFSET(i));
+		if (ret < 0)
+			return ret;
+		data->toffset[i] = ret;
+	}
+
+	ret = i2c_smbus_read_byte_data(client, LM95234_REG_TCRIT_HYST);
+	if (ret < 0)
+		return ret;
+	data->thyst = ret;
+
+	ret = i2c_smbus_read_byte_data(client, LM95234_REG_REM_MODEL);
+	if (ret < 0)
+		return ret;
+	data->sensor_type = ret;
+
+	return 0;
+}
+
+static int lm95234_update_device(struct i2c_client *client,
+				 struct lm95234_data *data)
+{
+	int ret;
+
+	mutex_lock(&data->update_lock);
+
+	if (time_after(jiffies, data->last_updated + data->interval) ||
+	    !data->valid) {
+		int i;
+
+		if (!data->valid) {
+			ret = lm95234_fill_cache(client);
+			if (ret < 0)
+				goto abort;
+		}
+
+		data->valid = false;
+		for (i = 0; i < ARRAY_SIZE(data->temp); i++) {
+			ret = lm95234_read_temp(client, i, &data->temp[i]);
+			if (ret < 0)
+				goto abort;
+		}
+
+		ret = i2c_smbus_read_byte_data(client, LM95234_REG_STS_FAULT);
+		if (ret < 0)
+			goto abort;
+		data->status = ret;
+
+		ret = i2c_smbus_read_byte_data(client, LM95234_REG_STS_TCRIT1);
+		if (ret < 0)
+			goto abort;
+		data->status |= ret << 8;
+
+		ret = i2c_smbus_read_byte_data(client, LM95234_REG_STS_TCRIT2);
+		if (ret < 0)
+			goto abort;
+		data->status |= ret << 16;
+
+		data->last_updated = jiffies;
+		data->valid = true;
+	}
+	ret = 0;
+abort:
+	mutex_unlock(&data->update_lock);
+
+	return ret;
+}
+
+static ssize_t show_temp(struct device *dev, struct device_attribute *attr,
+			 char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm95234_data *data = i2c_get_clientdata(client);
+	int index = to_sensor_dev_attr(attr)->index;
+	int ret = lm95234_update_device(client, data);
+
+	if (ret)
+		return ret;
+
+	return sprintf(buf, "%d\n",
+		       DIV_ROUND_CLOSEST(data->temp[index] * 125, 32));
+}
+
+static ssize_t show_alarm(struct device *dev,
+			  struct device_attribute *attr, char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm95234_data *data = i2c_get_clientdata(client);
+	u32 mask = to_sensor_dev_attr(attr)->index;
+	int ret = lm95234_update_device(client, data);
+
+	if (ret)
+		return ret;
+
+	return sprintf(buf, "%u", !!(data->status & mask));
+}
+
+static ssize_t show_type(struct device *dev, struct device_attribute *attr,
+			 char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm95234_data *data = i2c_get_clientdata(client);
+	u8 mask = to_sensor_dev_attr(attr)->index;
+	int ret = lm95234_update_device(client, data);
+
+	if (ret)
+		return ret;
+
+	return sprintf(buf, data->sensor_type & mask ? "1\n" : "2\n");
+}
+
+static ssize_t set_type(struct device *dev, struct device_attribute *attr,
+			const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm95234_data *data = i2c_get_clientdata(client);
+	unsigned long val;
+	u8 mask = to_sensor_dev_attr(attr)->index;
+	int ret = lm95234_update_device(client, data);
+
+	if (ret)
+		return ret;
+
+	ret = kstrtoul(buf, 10, &val);
+	if (ret < 0)
+		return ret;
+
+	if (val != 1 && val != 2)
+		return -EINVAL;
+
+	mutex_lock(&data->update_lock);
+	if (val == 1)
+		data->sensor_type |= mask;
+	else
+		data->sensor_type &= ~mask;
+	data->valid = false;
+	i2c_smbus_write_byte_data(client, LM95234_REG_REM_MODEL,
+				  data->sensor_type);
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+static ssize_t show_tcrit2(struct device *dev, struct device_attribute *attr,
+			   char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm95234_data *data = i2c_get_clientdata(client);
+	int index = to_sensor_dev_attr(attr)->index;
+	int ret = lm95234_update_device(client, data);
+
+	if (ret)
+		return ret;
+
+	return sprintf(buf, "%u", data->tcrit2[index] * 1000);
+}
+
+static ssize_t set_tcrit2(struct device *dev, struct device_attribute *attr,
+			  const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm95234_data *data = i2c_get_clientdata(client);
+	int index = to_sensor_dev_attr(attr)->index;
+	long val;
+	int ret = lm95234_update_device(client, data);
+
+	if (ret)
+		return ret;
+
+	ret = kstrtol(buf, 10, &val);
+	if (ret < 0)
+		return ret;
+
+	val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, index ? 255 : 127);
+
+	mutex_lock(&data->update_lock);
+	data->tcrit2[index] = val;
+	i2c_smbus_write_byte_data(client, LM95234_REG_TCRIT2(index), val);
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+static ssize_t show_tcrit2_hyst(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm95234_data *data = i2c_get_clientdata(client);
+	int index = to_sensor_dev_attr(attr)->index;
+	int ret = lm95234_update_device(client, data);
+
+	if (ret)
+		return ret;
+
+	/* Result can be negative, so be careful with unsigned operands */
+	return sprintf(buf, "%d",
+		       ((int)data->tcrit2[index] - (int)data->thyst) * 1000);
+}
+
+static ssize_t show_tcrit1(struct device *dev, struct device_attribute *attr,
+			   char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm95234_data *data = i2c_get_clientdata(client);
+	int index = to_sensor_dev_attr(attr)->index;
+
+	return sprintf(buf, "%u", data->tcrit1[index] * 1000);
+}
+
+static ssize_t set_tcrit1(struct device *dev, struct device_attribute *attr,
+			  const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm95234_data *data = i2c_get_clientdata(client);
+	int index = to_sensor_dev_attr(attr)->index;
+	long val;
+	int ret = lm95234_update_device(client, data);
+
+	if (ret)
+		return ret;
+
+	ret = kstrtol(buf, 10, &val);
+	if (ret < 0)
+		return ret;
+
+	val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, 255);
+
+	mutex_lock(&data->update_lock);
+	data->tcrit1[index] = val;
+	i2c_smbus_write_byte_data(client, LM95234_REG_TCRIT1(index), val);
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+static ssize_t show_tcrit1_hyst(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm95234_data *data = i2c_get_clientdata(client);
+	int index = to_sensor_dev_attr(attr)->index;
+	int ret = lm95234_update_device(client, data);
+
+	if (ret)
+		return ret;
+
+	/* Result can be negative, so be careful with unsigned operands */
+	return sprintf(buf, "%d",
+		       ((int)data->tcrit1[index] - (int)data->thyst) * 1000);
+}
+
+static ssize_t set_tcrit1_hyst(struct device *dev,
+			       struct device_attribute *attr,
+			       const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm95234_data *data = i2c_get_clientdata(client);
+	int index = to_sensor_dev_attr(attr)->index;
+	long val;
+	int ret = lm95234_update_device(client, data);
+
+	if (ret)
+		return ret;
+
+	ret = kstrtol(buf, 10, &val);
+	if (ret < 0)
+		return ret;
+
+	val = DIV_ROUND_CLOSEST(val, 1000);
+	val = clamp_val((int)data->tcrit1[index] - val, 0, 31);
+
+	mutex_lock(&data->update_lock);
+	data->thyst = val;
+	i2c_smbus_write_byte_data(client, LM95234_REG_TCRIT_HYST, val);
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+static ssize_t show_offset(struct device *dev, struct device_attribute *attr,
+			   char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm95234_data *data = i2c_get_clientdata(client);
+	int index = to_sensor_dev_attr(attr)->index;
+	int ret = lm95234_update_device(client, data);
+
+	if (ret)
+		return ret;
+
+	return sprintf(buf, "%d", data->toffset[index] * 500);
+}
+
+static ssize_t set_offset(struct device *dev, struct device_attribute *attr,
+			  const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm95234_data *data = i2c_get_clientdata(client);
+	int index = to_sensor_dev_attr(attr)->index;
+	long val;
+	int ret = lm95234_update_device(client, data);
+
+	if (ret)
+		return ret;
+
+	ret = kstrtol(buf, 10, &val);
+	if (ret < 0)
+		return ret;
+
+	/* Accuracy is 1/2 degrees C */
+	val = clamp_val(DIV_ROUND_CLOSEST(val, 500), -128, 127);
+
+	mutex_lock(&data->update_lock);
+	data->toffset[index] = val;
+	i2c_smbus_write_byte_data(client, LM95234_REG_OFFSET(index), val);
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+static ssize_t show_interval(struct device *dev, struct device_attribute *attr,
+			     char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm95234_data *data = i2c_get_clientdata(client);
+	int ret = lm95234_update_device(client, data);
+
+	if (ret)
+		return ret;
+
+	return sprintf(buf, "%lu\n",
+		       DIV_ROUND_CLOSEST(data->interval * 1000, HZ));
+}
+
+static ssize_t set_interval(struct device *dev, struct device_attribute *attr,
+			    const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm95234_data *data = i2c_get_clientdata(client);
+	unsigned long val;
+	u8 regval;
+	int ret = lm95234_update_device(client, data);
+
+	if (ret)
+		return ret;
+
+	ret = kstrtoul(buf, 10, &val);
+	if (ret < 0)
+		return ret;
+
+	for (regval = 0; regval < 3; regval++) {
+		if (val <= update_intervals[regval])
+			break;
+	}
+
+	mutex_lock(&data->update_lock);
+	data->interval = msecs_to_jiffies(update_intervals[regval]);
+	i2c_smbus_write_byte_data(client, LM95234_REG_CONVRATE, regval);
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp, NULL, 3);
+static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_temp, NULL, 4);
+
+static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL,
+			  BIT(0) | BIT(1));
+static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL,
+			  BIT(2) | BIT(3));
+static SENSOR_DEVICE_ATTR(temp4_fault, S_IRUGO, show_alarm, NULL,
+			  BIT(4) | BIT(5));
+static SENSOR_DEVICE_ATTR(temp5_fault, S_IRUGO, show_alarm, NULL,
+			  BIT(6) | BIT(7));
+
+static SENSOR_DEVICE_ATTR(temp2_type, S_IWUSR | S_IRUGO, show_type, set_type,
+			  BIT(1));
+static SENSOR_DEVICE_ATTR(temp3_type, S_IWUSR | S_IRUGO, show_type, set_type,
+			  BIT(2));
+static SENSOR_DEVICE_ATTR(temp4_type, S_IWUSR | S_IRUGO, show_type, set_type,
+			  BIT(3));
+static SENSOR_DEVICE_ATTR(temp5_type, S_IWUSR | S_IRUGO, show_type, set_type,
+			  BIT(4));
+
+static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_tcrit1,
+			  set_tcrit1, 0);
+static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_tcrit2,
+			  set_tcrit2, 0);
+static SENSOR_DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO, show_tcrit2,
+			  set_tcrit2, 1);
+static SENSOR_DEVICE_ATTR(temp4_max, S_IWUSR | S_IRUGO, show_tcrit1,
+			  set_tcrit1, 3);
+static SENSOR_DEVICE_ATTR(temp5_max, S_IWUSR | S_IRUGO, show_tcrit1,
+			  set_tcrit1, 4);
+
+static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, show_tcrit1_hyst,
+			  set_tcrit1_hyst, 0);
+static SENSOR_DEVICE_ATTR(temp2_max_hyst, S_IRUGO, show_tcrit2_hyst, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp3_max_hyst, S_IRUGO, show_tcrit2_hyst, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp4_max_hyst, S_IRUGO, show_tcrit1_hyst, NULL, 3);
+static SENSOR_DEVICE_ATTR(temp5_max_hyst, S_IRUGO, show_tcrit1_hyst, NULL, 4);
+
+static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL,
+			  BIT(0 + 8));
+static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL,
+			  BIT(1 + 16));
+static SENSOR_DEVICE_ATTR(temp3_max_alarm, S_IRUGO, show_alarm, NULL,
+			  BIT(2 + 16));
+static SENSOR_DEVICE_ATTR(temp4_max_alarm, S_IRUGO, show_alarm, NULL,
+			  BIT(3 + 8));
+static SENSOR_DEVICE_ATTR(temp5_max_alarm, S_IRUGO, show_alarm, NULL,
+			  BIT(4 + 8));
+
+static SENSOR_DEVICE_ATTR(temp2_crit, S_IWUSR | S_IRUGO, show_tcrit1,
+			  set_tcrit1, 1);
+static SENSOR_DEVICE_ATTR(temp3_crit, S_IWUSR | S_IRUGO, show_tcrit1,
+			  set_tcrit1, 2);
+
+static SENSOR_DEVICE_ATTR(temp2_crit_hyst, S_IRUGO, show_tcrit1_hyst, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp3_crit_hyst, S_IRUGO, show_tcrit1_hyst, NULL, 2);
+
+static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL,
+			  BIT(1 + 8));
+static SENSOR_DEVICE_ATTR(temp3_crit_alarm, S_IRUGO, show_alarm, NULL,
+			  BIT(2 + 8));
+
+static SENSOR_DEVICE_ATTR(temp2_offset, S_IWUSR | S_IRUGO, show_offset,
+			  set_offset, 0);
+static SENSOR_DEVICE_ATTR(temp3_offset, S_IWUSR | S_IRUGO, show_offset,
+			  set_offset, 1);
+static SENSOR_DEVICE_ATTR(temp4_offset, S_IWUSR | S_IRUGO, show_offset,
+			  set_offset, 2);
+static SENSOR_DEVICE_ATTR(temp5_offset, S_IWUSR | S_IRUGO, show_offset,
+			  set_offset, 3);
+
+static DEVICE_ATTR(update_interval, S_IWUSR | S_IRUGO, show_interval,
+		   set_interval);
+
+static struct attribute *lm95234_attributes[] = {
+	&sensor_dev_attr_temp1_input.dev_attr.attr,
+	&sensor_dev_attr_temp2_input.dev_attr.attr,
+	&sensor_dev_attr_temp3_input.dev_attr.attr,
+	&sensor_dev_attr_temp4_input.dev_attr.attr,
+	&sensor_dev_attr_temp5_input.dev_attr.attr,
+	&sensor_dev_attr_temp2_fault.dev_attr.attr,
+	&sensor_dev_attr_temp3_fault.dev_attr.attr,
+	&sensor_dev_attr_temp4_fault.dev_attr.attr,
+	&sensor_dev_attr_temp5_fault.dev_attr.attr,
+	&sensor_dev_attr_temp2_type.dev_attr.attr,
+	&sensor_dev_attr_temp3_type.dev_attr.attr,
+	&sensor_dev_attr_temp4_type.dev_attr.attr,
+	&sensor_dev_attr_temp5_type.dev_attr.attr,
+	&sensor_dev_attr_temp1_max.dev_attr.attr,
+	&sensor_dev_attr_temp2_max.dev_attr.attr,
+	&sensor_dev_attr_temp3_max.dev_attr.attr,
+	&sensor_dev_attr_temp4_max.dev_attr.attr,
+	&sensor_dev_attr_temp5_max.dev_attr.attr,
+	&sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
+	&sensor_dev_attr_temp2_max_hyst.dev_attr.attr,
+	&sensor_dev_attr_temp3_max_hyst.dev_attr.attr,
+	&sensor_dev_attr_temp4_max_hyst.dev_attr.attr,
+	&sensor_dev_attr_temp5_max_hyst.dev_attr.attr,
+	&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp3_max_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp4_max_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp5_max_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp2_crit.dev_attr.attr,
+	&sensor_dev_attr_temp3_crit.dev_attr.attr,
+	&sensor_dev_attr_temp2_crit_hyst.dev_attr.attr,
+	&sensor_dev_attr_temp3_crit_hyst.dev_attr.attr,
+	&sensor_dev_attr_temp2_crit_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp3_crit_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp2_offset.dev_attr.attr,
+	&sensor_dev_attr_temp3_offset.dev_attr.attr,
+	&sensor_dev_attr_temp4_offset.dev_attr.attr,
+	&sensor_dev_attr_temp5_offset.dev_attr.attr,
+	&dev_attr_update_interval.attr,
+	NULL
+};
+
+static const struct attribute_group lm95234_group = {
+	.attrs = lm95234_attributes,
+};
+
+static int lm95234_detect(struct i2c_client *client,
+			  struct i2c_board_info *info)
+{
+	struct i2c_adapter *adapter = client->adapter;
+	int mfg_id, chip_id, val;
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		return -ENODEV;
+
+	mfg_id = i2c_smbus_read_byte_data(client, LM95234_REG_MAN_ID);
+	if (mfg_id != NATSEMI_MAN_ID)
+		return -ENODEV;
+
+	chip_id = i2c_smbus_read_byte_data(client, LM95234_REG_CHIP_ID);
+	if (chip_id != LM95234_CHIP_ID)
+		return -ENODEV;
+
+	val = i2c_smbus_read_byte_data(client, LM95234_REG_STATUS);
+	if (val & 0x30)
+		return -ENODEV;
+
+	val = i2c_smbus_read_byte_data(client, LM95234_REG_CONFIG);
+	if (val & 0xbc)
+		return -ENODEV;
+
+	val = i2c_smbus_read_byte_data(client, LM95234_REG_CONVRATE);
+	if (val & 0xfc)
+		return -ENODEV;
+
+	val = i2c_smbus_read_byte_data(client, LM95234_REG_REM_MODEL);
+	if (val & 0xe1)
+		return -ENODEV;
+
+	val = i2c_smbus_read_byte_data(client, LM95234_REG_REM_MODEL_STS);
+	if (val & 0xe1)
+		return -ENODEV;
+
+	strlcpy(info->type, "lm95234", I2C_NAME_SIZE);
+	return 0;
+}
+
+static int lm95234_init_client(struct i2c_client *client)
+{
+	int val, model;
+
+	/* start conversion if necessary */
+	val = i2c_smbus_read_byte_data(client, LM95234_REG_CONFIG);
+	if (val < 0)
+		return val;
+	if (val & 0x40)
+		i2c_smbus_write_byte_data(client, LM95234_REG_CONFIG,
+					  val & ~0x40);
+
+	/* If diode type status reports an error, try to fix it */
+	val = i2c_smbus_read_byte_data(client, LM95234_REG_REM_MODEL_STS);
+	if (val < 0)
+		return val;
+	model = i2c_smbus_read_byte_data(client, LM95234_REG_REM_MODEL);
+	if (model < 0)
+		return model;
+	if (model & val) {
+		dev_notice(&client->dev,
+			   "Fixing remote diode type misconfiguration (0x%x)\n",
+			   val);
+		i2c_smbus_write_byte_data(client, LM95234_REG_REM_MODEL,
+					  model & ~val);
+	}
+	return 0;
+}
+
+static int lm95234_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
+{
+	struct device *dev = &client->dev;
+	struct lm95234_data *data;
+	int err;
+
+	data = devm_kzalloc(dev, sizeof(struct lm95234_data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	i2c_set_clientdata(client, data);
+	mutex_init(&data->update_lock);
+
+	/* Initialize the LM95234 chip */
+	err = lm95234_init_client(client);
+	if (err < 0)
+		return err;
+
+	/* Register sysfs hooks */
+	err = sysfs_create_group(&dev->kobj, &lm95234_group);
+	if (err)
+		return err;
+
+	data->hwmon_dev = hwmon_device_register(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(&dev->kobj, &lm95234_group);
+	return err;
+}
+
+static int lm95234_remove(struct i2c_client *client)
+{
+	struct lm95234_data *data = i2c_get_clientdata(client);
+
+	hwmon_device_unregister(data->hwmon_dev);
+	sysfs_remove_group(&client->dev.kobj, &lm95234_group);
+
+	return 0;
+}
+
+/* Driver data (common to all clients) */
+static const struct i2c_device_id lm95234_id[] = {
+	{ "lm95234", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, lm95234_id);
+
+static struct i2c_driver lm95234_driver = {
+	.class		= I2C_CLASS_HWMON,
+	.driver = {
+		.name	= DRVNAME,
+	},
+	.probe		= lm95234_probe,
+	.remove		= lm95234_remove,
+	.id_table	= lm95234_id,
+	.detect		= lm95234_detect,
+	.address_list	= normal_i2c,
+};
+
+module_i2c_driver(lm95234_driver);
+
+MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>");
+MODULE_DESCRIPTION("LM95234 sensor driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/ltc4151.c b/drivers/hwmon/ltc4151.c
index 4319a94..af81be1 100644
--- a/drivers/hwmon/ltc4151.c
+++ b/drivers/hwmon/ltc4151.c
@@ -146,14 +146,14 @@ static ssize_t ltc4151_show_value(struct device *dev,
 /*
  * Input voltages.
  */
-static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, \
-	ltc4151_show_value, NULL, LTC4151_VIN_H);
-static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, \
-	ltc4151_show_value, NULL, LTC4151_ADIN_H);
+static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, ltc4151_show_value, NULL,
+			  LTC4151_VIN_H);
+static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, ltc4151_show_value, NULL,
+			  LTC4151_ADIN_H);
 
 /* Currents (via sense resistor) */
-static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, \
-	ltc4151_show_value, NULL, LTC4151_SENSE_H);
+static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, ltc4151_show_value, NULL,
+			  LTC4151_SENSE_H);
 
 /*
  * Finally, construct an array of pointers to members of the above objects,
diff --git a/drivers/hwmon/ltc4215.c b/drivers/hwmon/ltc4215.c
index e887610..8a14296 100644
--- a/drivers/hwmon/ltc4215.c
+++ b/drivers/hwmon/ltc4215.c
@@ -172,12 +172,12 @@ static ssize_t ltc4215_show_alarm(struct device *dev,
 					  struct device_attribute *da,
 					  char *buf)
 {
-	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(da);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
 	struct ltc4215_data *data = ltc4215_update_device(dev);
-	const u8 reg = data->regs[attr->index];
-	const u32 mask = attr->nr;
+	const u8 reg = data->regs[LTC4215_STATUS];
+	const u32 mask = attr->index;
 
-	return snprintf(buf, PAGE_SIZE, "%u\n", (reg & mask) ? 1 : 0);
+	return snprintf(buf, PAGE_SIZE, "%u\n", !!(reg & mask));
 }
 
 /*
@@ -186,39 +186,29 @@ static ssize_t ltc4215_show_alarm(struct device *dev,
  * for each register.
  */
 
-#define LTC4215_VOLTAGE(name, ltc4215_cmd_idx) \
-	static SENSOR_DEVICE_ATTR(name, S_IRUGO, \
-	ltc4215_show_voltage, NULL, ltc4215_cmd_idx)
-
-#define LTC4215_CURRENT(name) \
-	static SENSOR_DEVICE_ATTR(name, S_IRUGO, \
-	ltc4215_show_current, NULL, 0);
-
-#define LTC4215_POWER(name) \
-	static SENSOR_DEVICE_ATTR(name, S_IRUGO, \
-	ltc4215_show_power, NULL, 0);
-
-#define LTC4215_ALARM(name, mask, reg) \
-	static SENSOR_DEVICE_ATTR_2(name, S_IRUGO, \
-	ltc4215_show_alarm, NULL, (mask), reg)
-
 /* Construct a sensor_device_attribute structure for each register */
 
 /* Current */
-LTC4215_CURRENT(curr1_input);
-LTC4215_ALARM(curr1_max_alarm,	(1 << 2),	LTC4215_STATUS);
+static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, ltc4215_show_current, NULL, 0);
+static SENSOR_DEVICE_ATTR(curr1_max_alarm, S_IRUGO, ltc4215_show_alarm, NULL,
+			  1 << 2);
 
 /* Power (virtual) */
-LTC4215_POWER(power1_input);
+static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, ltc4215_show_power, NULL, 0);
 
 /* Input Voltage */
-LTC4215_VOLTAGE(in1_input,			LTC4215_ADIN);
-LTC4215_ALARM(in1_max_alarm,	(1 << 0),	LTC4215_STATUS);
-LTC4215_ALARM(in1_min_alarm,	(1 << 1),	LTC4215_STATUS);
+static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, ltc4215_show_voltage, NULL,
+			  LTC4215_ADIN);
+static SENSOR_DEVICE_ATTR(in1_max_alarm, S_IRUGO, ltc4215_show_alarm, NULL,
+			  1 << 0);
+static SENSOR_DEVICE_ATTR(in1_min_alarm, S_IRUGO, ltc4215_show_alarm, NULL,
+			  1 << 1);
 
 /* Output Voltage */
-LTC4215_VOLTAGE(in2_input,			LTC4215_SOURCE);
-LTC4215_ALARM(in2_min_alarm,	(1 << 3),	LTC4215_STATUS);
+static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, ltc4215_show_voltage, NULL,
+			  LTC4215_SOURCE);
+static SENSOR_DEVICE_ATTR(in2_min_alarm, S_IRUGO, ltc4215_show_alarm, NULL,
+			  1 << 3);
 
 /*
  * Finally, construct an array of pointers to members of the above objects,
diff --git a/drivers/hwmon/ltc4245.c b/drivers/hwmon/ltc4245.c
index 3653f79..cdc1ecc 100644
--- a/drivers/hwmon/ltc4245.c
+++ b/drivers/hwmon/ltc4245.c
@@ -319,80 +319,82 @@ static ssize_t ltc4245_show_gpio(struct device *dev,
 	return snprintf(buf, PAGE_SIZE, "%u\n", val * 10);
 }
 
-/*
- * These macros are used below in constructing device attribute objects
- * for use with sysfs_create_group() to make a sysfs device file
- * for each register.
- */
-
-#define LTC4245_VOLTAGE(name, ltc4245_cmd_idx) \
-	static SENSOR_DEVICE_ATTR(name, S_IRUGO, \
-	ltc4245_show_voltage, NULL, ltc4245_cmd_idx)
-
-#define LTC4245_CURRENT(name, ltc4245_cmd_idx) \
-	static SENSOR_DEVICE_ATTR(name, S_IRUGO, \
-	ltc4245_show_current, NULL, ltc4245_cmd_idx)
-
-#define LTC4245_POWER(name, ltc4245_cmd_idx) \
-	static SENSOR_DEVICE_ATTR(name, S_IRUGO, \
-	ltc4245_show_power, NULL, ltc4245_cmd_idx)
-
-#define LTC4245_ALARM(name, mask, reg) \
-	static SENSOR_DEVICE_ATTR_2(name, S_IRUGO, \
-	ltc4245_show_alarm, NULL, (mask), reg)
-
-#define LTC4245_GPIO_VOLTAGE(name, gpio_num) \
-	static SENSOR_DEVICE_ATTR(name, S_IRUGO, \
-	ltc4245_show_gpio, NULL, gpio_num)
-
 /* Construct a sensor_device_attribute structure for each register */
 
 /* Input voltages */
-LTC4245_VOLTAGE(in1_input,			LTC4245_12VIN);
-LTC4245_VOLTAGE(in2_input,			LTC4245_5VIN);
-LTC4245_VOLTAGE(in3_input,			LTC4245_3VIN);
-LTC4245_VOLTAGE(in4_input,			LTC4245_VEEIN);
+static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, ltc4245_show_voltage, NULL,
+			  LTC4245_12VIN);
+static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, ltc4245_show_voltage, NULL,
+			  LTC4245_5VIN);
+static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, ltc4245_show_voltage, NULL,
+			  LTC4245_3VIN);
+static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, ltc4245_show_voltage, NULL,
+			  LTC4245_VEEIN);
 
 /* Input undervoltage alarms */
-LTC4245_ALARM(in1_min_alarm,	(1 << 0),	LTC4245_FAULT1);
-LTC4245_ALARM(in2_min_alarm,	(1 << 1),	LTC4245_FAULT1);
-LTC4245_ALARM(in3_min_alarm,	(1 << 2),	LTC4245_FAULT1);
-LTC4245_ALARM(in4_min_alarm,	(1 << 3),	LTC4245_FAULT1);
+static SENSOR_DEVICE_ATTR_2(in1_min_alarm, S_IRUGO, ltc4245_show_alarm, NULL,
+			    1 << 0, LTC4245_FAULT1);
+static SENSOR_DEVICE_ATTR_2(in2_min_alarm, S_IRUGO, ltc4245_show_alarm, NULL,
+			    1 << 1, LTC4245_FAULT1);
+static SENSOR_DEVICE_ATTR_2(in3_min_alarm, S_IRUGO, ltc4245_show_alarm, NULL,
+			    1 << 2, LTC4245_FAULT1);
+static SENSOR_DEVICE_ATTR_2(in4_min_alarm, S_IRUGO, ltc4245_show_alarm, NULL,
+			    1 << 3, LTC4245_FAULT1);
 
 /* Currents (via sense resistor) */
-LTC4245_CURRENT(curr1_input,			LTC4245_12VSENSE);
-LTC4245_CURRENT(curr2_input,			LTC4245_5VSENSE);
-LTC4245_CURRENT(curr3_input,			LTC4245_3VSENSE);
-LTC4245_CURRENT(curr4_input,			LTC4245_VEESENSE);
+static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, ltc4245_show_current, NULL,
+			  LTC4245_12VSENSE);
+static SENSOR_DEVICE_ATTR(curr2_input, S_IRUGO, ltc4245_show_current, NULL,
+			  LTC4245_5VSENSE);
+static SENSOR_DEVICE_ATTR(curr3_input, S_IRUGO, ltc4245_show_current, NULL,
+			  LTC4245_3VSENSE);
+static SENSOR_DEVICE_ATTR(curr4_input, S_IRUGO, ltc4245_show_current, NULL,
+			  LTC4245_VEESENSE);
 
 /* Overcurrent alarms */
-LTC4245_ALARM(curr1_max_alarm,	(1 << 4),	LTC4245_FAULT1);
-LTC4245_ALARM(curr2_max_alarm,	(1 << 5),	LTC4245_FAULT1);
-LTC4245_ALARM(curr3_max_alarm,	(1 << 6),	LTC4245_FAULT1);
-LTC4245_ALARM(curr4_max_alarm,	(1 << 7),	LTC4245_FAULT1);
+static SENSOR_DEVICE_ATTR_2(curr1_max_alarm, S_IRUGO, ltc4245_show_alarm, NULL,
+			    1 << 4, LTC4245_FAULT1);
+static SENSOR_DEVICE_ATTR_2(curr2_max_alarm, S_IRUGO, ltc4245_show_alarm, NULL,
+			    1 << 5, LTC4245_FAULT1);
+static SENSOR_DEVICE_ATTR_2(curr3_max_alarm, S_IRUGO, ltc4245_show_alarm, NULL,
+			    1 << 6, LTC4245_FAULT1);
+static SENSOR_DEVICE_ATTR_2(curr4_max_alarm, S_IRUGO, ltc4245_show_alarm, NULL,
+			    1 << 7, LTC4245_FAULT1);
 
 /* Output voltages */
-LTC4245_VOLTAGE(in5_input,			LTC4245_12VOUT);
-LTC4245_VOLTAGE(in6_input,			LTC4245_5VOUT);
-LTC4245_VOLTAGE(in7_input,			LTC4245_3VOUT);
-LTC4245_VOLTAGE(in8_input,			LTC4245_VEEOUT);
+static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, ltc4245_show_voltage, NULL,
+			  LTC4245_12VOUT);
+static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, ltc4245_show_voltage, NULL,
+			  LTC4245_5VOUT);
+static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, ltc4245_show_voltage, NULL,
+			  LTC4245_3VOUT);
+static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, ltc4245_show_voltage, NULL,
+			  LTC4245_VEEOUT);
 
 /* Power Bad alarms */
-LTC4245_ALARM(in5_min_alarm,	(1 << 0),	LTC4245_FAULT2);
-LTC4245_ALARM(in6_min_alarm,	(1 << 1),	LTC4245_FAULT2);
-LTC4245_ALARM(in7_min_alarm,	(1 << 2),	LTC4245_FAULT2);
-LTC4245_ALARM(in8_min_alarm,	(1 << 3),	LTC4245_FAULT2);
+static SENSOR_DEVICE_ATTR_2(in5_min_alarm, S_IRUGO, ltc4245_show_alarm, NULL,
+			    1 << 0, LTC4245_FAULT2);
+static SENSOR_DEVICE_ATTR_2(in6_min_alarm, S_IRUGO, ltc4245_show_alarm, NULL,
+			    1 << 1, LTC4245_FAULT2);
+static SENSOR_DEVICE_ATTR_2(in7_min_alarm, S_IRUGO, ltc4245_show_alarm, NULL,
+			    1 << 2, LTC4245_FAULT2);
+static SENSOR_DEVICE_ATTR_2(in8_min_alarm, S_IRUGO, ltc4245_show_alarm, NULL,
+			    1 << 3, LTC4245_FAULT2);
 
 /* GPIO voltages */
-LTC4245_GPIO_VOLTAGE(in9_input,			0);
-LTC4245_GPIO_VOLTAGE(in10_input,		1);
-LTC4245_GPIO_VOLTAGE(in11_input,		2);
+static SENSOR_DEVICE_ATTR(in9_input, S_IRUGO, ltc4245_show_gpio, NULL, 0);
+static SENSOR_DEVICE_ATTR(in10_input, S_IRUGO, ltc4245_show_gpio, NULL, 1);
+static SENSOR_DEVICE_ATTR(in11_input, S_IRUGO, ltc4245_show_gpio, NULL, 2);
 
 /* Power Consumption (virtual) */
-LTC4245_POWER(power1_input,			LTC4245_12VSENSE);
-LTC4245_POWER(power2_input,			LTC4245_5VSENSE);
-LTC4245_POWER(power3_input,			LTC4245_3VSENSE);
-LTC4245_POWER(power4_input,			LTC4245_VEESENSE);
+static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, ltc4245_show_power, NULL,
+			  LTC4245_12VSENSE);
+static SENSOR_DEVICE_ATTR(power2_input, S_IRUGO, ltc4245_show_power, NULL,
+			  LTC4245_5VSENSE);
+static SENSOR_DEVICE_ATTR(power3_input, S_IRUGO, ltc4245_show_power, NULL,
+			  LTC4245_3VSENSE);
+static SENSOR_DEVICE_ATTR(power4_input, S_IRUGO, ltc4245_show_power, NULL,
+			  LTC4245_VEESENSE);
 
 /*
  * Finally, construct an array of pointers to members of the above objects,
diff --git a/drivers/hwmon/ltc4261.c b/drivers/hwmon/ltc4261.c
index 84a2d28..487da58 100644
--- a/drivers/hwmon/ltc4261.c
+++ b/drivers/hwmon/ltc4261.c
@@ -165,24 +165,12 @@ static ssize_t ltc4261_show_bool(struct device *dev,
 }
 
 /*
- * These macros are used below in constructing device attribute objects
- * for use with sysfs_create_group() to make a sysfs device file
- * for each register.
- */
-
-#define LTC4261_VALUE(name, ltc4261_cmd_idx) \
-	static SENSOR_DEVICE_ATTR(name, S_IRUGO, \
-	ltc4261_show_value, NULL, ltc4261_cmd_idx)
-
-#define LTC4261_BOOL(name, mask) \
-	static SENSOR_DEVICE_ATTR(name, S_IRUGO, \
-	ltc4261_show_bool, NULL, (mask))
-
-/*
  * Input voltages.
  */
-LTC4261_VALUE(in1_input, LTC4261_ADIN_H);
-LTC4261_VALUE(in2_input, LTC4261_ADIN2_H);
+static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, ltc4261_show_value, NULL,
+			  LTC4261_ADIN_H);
+static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, ltc4261_show_value, NULL,
+			  LTC4261_ADIN2_H);
 
 /*
  * Voltage alarms. The chip has only one set of voltage alarm status bits,
@@ -192,16 +180,22 @@ LTC4261_VALUE(in2_input, LTC4261_ADIN2_H);
  * To ensure that the alarm condition is reported to the user, report it
  * with both voltage sensors.
  */
-LTC4261_BOOL(in1_min_alarm, FAULT_UV);
-LTC4261_BOOL(in1_max_alarm, FAULT_OV);
-LTC4261_BOOL(in2_min_alarm, FAULT_UV);
-LTC4261_BOOL(in2_max_alarm, FAULT_OV);
+static SENSOR_DEVICE_ATTR(in1_min_alarm, S_IRUGO, ltc4261_show_bool, NULL,
+			  FAULT_UV);
+static SENSOR_DEVICE_ATTR(in1_max_alarm, S_IRUGO, ltc4261_show_bool, NULL,
+			  FAULT_OV);
+static SENSOR_DEVICE_ATTR(in2_min_alarm, S_IRUGO, ltc4261_show_bool, NULL,
+			  FAULT_UV);
+static SENSOR_DEVICE_ATTR(in2_max_alarm, S_IRUGO, ltc4261_show_bool, NULL,
+			  FAULT_OV);
 
 /* Currents (via sense resistor) */
-LTC4261_VALUE(curr1_input, LTC4261_SENSE_H);
+static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, ltc4261_show_value, NULL,
+			  LTC4261_SENSE_H);
 
 /* Overcurrent alarm */
-LTC4261_BOOL(curr1_max_alarm, FAULT_OC);
+static SENSOR_DEVICE_ATTR(curr1_max_alarm, S_IRUGO, ltc4261_show_bool, NULL,
+			  FAULT_OC);
 
 static struct attribute *ltc4261_attributes[] = {
 	&sensor_dev_attr_in1_input.dev_attr.attr,
diff --git a/drivers/hwmon/max6697.c b/drivers/hwmon/max6697.c
index bf4aa37..328fb03 100644
--- a/drivers/hwmon/max6697.c
+++ b/drivers/hwmon/max6697.c
@@ -399,82 +399,95 @@ static SENSOR_DEVICE_ATTR(temp6_fault, S_IRUGO, show_alarm, NULL, 5);
 static SENSOR_DEVICE_ATTR(temp7_fault, S_IRUGO, show_alarm, NULL, 6);
 static SENSOR_DEVICE_ATTR(temp8_fault, S_IRUGO, show_alarm, NULL, 7);
 
-static struct attribute *max6697_attributes[8][7] = {
-	{
-		&sensor_dev_attr_temp1_input.dev_attr.attr,
-		&sensor_dev_attr_temp1_max.dev_attr.attr,
-		&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
-		&sensor_dev_attr_temp1_crit.dev_attr.attr,
-		&sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
-		NULL
-	}, {
-		&sensor_dev_attr_temp2_input.dev_attr.attr,
-		&sensor_dev_attr_temp2_max.dev_attr.attr,
-		&sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
-		&sensor_dev_attr_temp2_crit.dev_attr.attr,
-		&sensor_dev_attr_temp2_crit_alarm.dev_attr.attr,
-		&sensor_dev_attr_temp2_fault.dev_attr.attr,
-		NULL
-	}, {
-		&sensor_dev_attr_temp3_input.dev_attr.attr,
-		&sensor_dev_attr_temp3_max.dev_attr.attr,
-		&sensor_dev_attr_temp3_max_alarm.dev_attr.attr,
-		&sensor_dev_attr_temp3_crit.dev_attr.attr,
-		&sensor_dev_attr_temp3_crit_alarm.dev_attr.attr,
-		&sensor_dev_attr_temp3_fault.dev_attr.attr,
-		NULL
-	}, {
-		&sensor_dev_attr_temp4_input.dev_attr.attr,
-		&sensor_dev_attr_temp4_max.dev_attr.attr,
-		&sensor_dev_attr_temp4_max_alarm.dev_attr.attr,
-		&sensor_dev_attr_temp4_crit.dev_attr.attr,
-		&sensor_dev_attr_temp4_crit_alarm.dev_attr.attr,
-		&sensor_dev_attr_temp4_fault.dev_attr.attr,
-		NULL
-	}, {
-		&sensor_dev_attr_temp5_input.dev_attr.attr,
-		&sensor_dev_attr_temp5_max.dev_attr.attr,
-		&sensor_dev_attr_temp5_max_alarm.dev_attr.attr,
-		&sensor_dev_attr_temp5_crit.dev_attr.attr,
-		&sensor_dev_attr_temp5_crit_alarm.dev_attr.attr,
-		&sensor_dev_attr_temp5_fault.dev_attr.attr,
-		NULL
-	}, {
-		&sensor_dev_attr_temp6_input.dev_attr.attr,
-		&sensor_dev_attr_temp6_max.dev_attr.attr,
-		&sensor_dev_attr_temp6_max_alarm.dev_attr.attr,
-		&sensor_dev_attr_temp6_crit.dev_attr.attr,
-		&sensor_dev_attr_temp6_crit_alarm.dev_attr.attr,
-		&sensor_dev_attr_temp6_fault.dev_attr.attr,
-		NULL
-	}, {
-		&sensor_dev_attr_temp7_input.dev_attr.attr,
-		&sensor_dev_attr_temp7_max.dev_attr.attr,
-		&sensor_dev_attr_temp7_max_alarm.dev_attr.attr,
-		&sensor_dev_attr_temp7_crit.dev_attr.attr,
-		&sensor_dev_attr_temp7_crit_alarm.dev_attr.attr,
-		&sensor_dev_attr_temp7_fault.dev_attr.attr,
-		NULL
-	}, {
-		&sensor_dev_attr_temp8_input.dev_attr.attr,
-		&sensor_dev_attr_temp8_max.dev_attr.attr,
-		&sensor_dev_attr_temp8_max_alarm.dev_attr.attr,
-		&sensor_dev_attr_temp8_crit.dev_attr.attr,
-		&sensor_dev_attr_temp8_crit_alarm.dev_attr.attr,
-		&sensor_dev_attr_temp8_fault.dev_attr.attr,
-		NULL
-	}
+static DEVICE_ATTR(dummy, 0, NULL, NULL);
+
+static umode_t max6697_is_visible(struct kobject *kobj, struct attribute *attr,
+				  int index)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct i2c_client *client = to_i2c_client(dev);
+	struct max6697_data *data = i2c_get_clientdata(client);
+	const struct max6697_chip_data *chip = data->chip;
+	int channel = index / 6;	/* channel number */
+	int nr = index % 6;		/* attribute index within channel */
+
+	if (channel >= chip->channels)
+		return 0;
+
+	if ((nr == 3 || nr == 4) && !(chip->have_crit & (1 << channel)))
+		return 0;
+	if (nr == 5 && !(chip->have_fault & (1 << channel)))
+		return 0;
+
+	return attr->mode;
+}
+
+/*
+ * max6697_is_visible uses the index into the following array to determine
+ * if attributes should be created or not. Any change in order or content
+ * must be matched in max6697_is_visible.
+ */
+static struct attribute *max6697_attributes[] = {
+	&sensor_dev_attr_temp1_input.dev_attr.attr,
+	&sensor_dev_attr_temp1_max.dev_attr.attr,
+	&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp1_crit.dev_attr.attr,
+	&sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
+	&dev_attr_dummy.attr,
+
+	&sensor_dev_attr_temp2_input.dev_attr.attr,
+	&sensor_dev_attr_temp2_max.dev_attr.attr,
+	&sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp2_crit.dev_attr.attr,
+	&sensor_dev_attr_temp2_crit_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp2_fault.dev_attr.attr,
+
+	&sensor_dev_attr_temp3_input.dev_attr.attr,
+	&sensor_dev_attr_temp3_max.dev_attr.attr,
+	&sensor_dev_attr_temp3_max_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp3_crit.dev_attr.attr,
+	&sensor_dev_attr_temp3_crit_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp3_fault.dev_attr.attr,
+
+	&sensor_dev_attr_temp4_input.dev_attr.attr,
+	&sensor_dev_attr_temp4_max.dev_attr.attr,
+	&sensor_dev_attr_temp4_max_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp4_crit.dev_attr.attr,
+	&sensor_dev_attr_temp4_crit_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp4_fault.dev_attr.attr,
+
+	&sensor_dev_attr_temp5_input.dev_attr.attr,
+	&sensor_dev_attr_temp5_max.dev_attr.attr,
+	&sensor_dev_attr_temp5_max_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp5_crit.dev_attr.attr,
+	&sensor_dev_attr_temp5_crit_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp5_fault.dev_attr.attr,
+
+	&sensor_dev_attr_temp6_input.dev_attr.attr,
+	&sensor_dev_attr_temp6_max.dev_attr.attr,
+	&sensor_dev_attr_temp6_max_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp6_crit.dev_attr.attr,
+	&sensor_dev_attr_temp6_crit_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp6_fault.dev_attr.attr,
+
+	&sensor_dev_attr_temp7_input.dev_attr.attr,
+	&sensor_dev_attr_temp7_max.dev_attr.attr,
+	&sensor_dev_attr_temp7_max_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp7_crit.dev_attr.attr,
+	&sensor_dev_attr_temp7_crit_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp7_fault.dev_attr.attr,
+
+	&sensor_dev_attr_temp8_input.dev_attr.attr,
+	&sensor_dev_attr_temp8_max.dev_attr.attr,
+	&sensor_dev_attr_temp8_max_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp8_crit.dev_attr.attr,
+	&sensor_dev_attr_temp8_crit_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp8_fault.dev_attr.attr,
+	NULL
 };
 
-static const struct attribute_group max6697_group[8] = {
-	{ .attrs = max6697_attributes[0] },
-	{ .attrs = max6697_attributes[1] },
-	{ .attrs = max6697_attributes[2] },
-	{ .attrs = max6697_attributes[3] },
-	{ .attrs = max6697_attributes[4] },
-	{ .attrs = max6697_attributes[5] },
-	{ .attrs = max6697_attributes[6] },
-	{ .attrs = max6697_attributes[7] },
+static const struct attribute_group max6697_group = {
+	.attrs = max6697_attributes, .is_visible = max6697_is_visible,
 };
 
 static void max6697_get_config_of(struct device_node *node,
@@ -606,21 +619,13 @@ done:
 	return 0;
 }
 
-static void max6697_remove_files(struct i2c_client *client)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(max6697_group); i++)
-		sysfs_remove_group(&client->dev.kobj, &max6697_group[i]);
-}
-
 static int max6697_probe(struct i2c_client *client,
 			 const struct i2c_device_id *id)
 {
 	struct i2c_adapter *adapter = client->adapter;
 	struct device *dev = &client->dev;
 	struct max6697_data *data;
-	int i, err;
+	int err;
 
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 		return -ENODEV;
@@ -639,37 +644,9 @@ static int max6697_probe(struct i2c_client *client,
 	if (err)
 		return err;
 
-	for (i = 0; i < data->chip->channels; i++) {
-		err = sysfs_create_file(&dev->kobj,
-					max6697_attributes[i][0]);
-		if (err)
-			goto error;
-		err = sysfs_create_file(&dev->kobj,
-					max6697_attributes[i][1]);
-		if (err)
-			goto error;
-		err = sysfs_create_file(&dev->kobj,
-					max6697_attributes[i][2]);
-		if (err)
-			goto error;
-
-		if (data->chip->have_crit & (1 << i)) {
-			err = sysfs_create_file(&dev->kobj,
-						max6697_attributes[i][3]);
-			if (err)
-				goto error;
-			err = sysfs_create_file(&dev->kobj,
-						max6697_attributes[i][4]);
-			if (err)
-				goto error;
-		}
-		if (data->chip->have_fault & (1 << i)) {
-			err = sysfs_create_file(&dev->kobj,
-						max6697_attributes[i][5]);
-			if (err)
-				goto error;
-		}
-	}
+	err = sysfs_create_group(&client->dev.kobj, &max6697_group);
+	if (err)
+		return err;
 
 	data->hwmon_dev = hwmon_device_register(dev);
 	if (IS_ERR(data->hwmon_dev)) {
@@ -680,7 +657,7 @@ static int max6697_probe(struct i2c_client *client,
 	return 0;
 
 error:
-	max6697_remove_files(client);
+	sysfs_remove_group(&client->dev.kobj, &max6697_group);
 	return err;
 }
 
@@ -689,7 +666,7 @@ static int max6697_remove(struct i2c_client *client)
 	struct max6697_data *data = i2c_get_clientdata(client);
 
 	hwmon_device_unregister(data->hwmon_dev);
-	max6697_remove_files(client);
+	sysfs_remove_group(&client->dev.kobj, &max6697_group);
 
 	return 0;
 }
diff --git a/drivers/hwmon/mc13783-adc.c b/drivers/hwmon/mc13783-adc.c
index 2a7f331..982d862 100644
--- a/drivers/hwmon/mc13783-adc.c
+++ b/drivers/hwmon/mc13783-adc.c
@@ -273,18 +273,7 @@ static struct platform_driver mc13783_adc_driver = {
 	.id_table	= mc13783_adc_idtable,
 };
 
-static int __init mc13783_adc_init(void)
-{
-	return platform_driver_probe(&mc13783_adc_driver, mc13783_adc_probe);
-}
-
-static void __exit mc13783_adc_exit(void)
-{
-	platform_driver_unregister(&mc13783_adc_driver);
-}
-
-module_init(mc13783_adc_init);
-module_exit(mc13783_adc_exit);
+module_platform_driver_probe(mc13783_adc_driver, mc13783_adc_probe);
 
 MODULE_DESCRIPTION("MC13783 ADC driver");
 MODULE_AUTHOR("Luotao Fu <l.fu@pengutronix.de>");
diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c
new file mode 100644
index 0000000..d05a700
--- /dev/null
+++ b/drivers/hwmon/nct6775.c
@@ -0,0 +1,4228 @@
+/*
+ * nct6775 - Driver for the hardware monitoring functionality of
+ *	       Nuvoton NCT677x Super-I/O chips
+ *
+ * Copyright (C) 2012  Guenter Roeck <linux@roeck-us.net>
+ *
+ * Derived from w83627ehf driver
+ * Copyright (C) 2005-2012  Jean Delvare <khali@linux-fr.org>
+ * Copyright (C) 2006  Yuan Mu (Winbond),
+ *		       Rudolf Marek <r.marek@assembler.cz>
+ *		       David Hubbard <david.c.hubbard@gmail.com>
+ *		       Daniel J Blueman <daniel.blueman@gmail.com>
+ * Copyright (C) 2010  Sheng-Yuan Huang (Nuvoton) (PS00)
+ *
+ * Shamelessly ripped from the w83627hf driver
+ * Copyright (C) 2003  Mark Studebaker
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You 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 the following chips:
+ *
+ * Chip        #vin    #fan    #pwm    #temp  chip IDs       man ID
+ * nct6775f     9      4       3       6+3    0xb470 0xc1    0x5ca3
+ * nct6776f     9      5       3       6+3    0xc330 0xc1    0x5ca3
+ * nct6779d    15      5       5       2+6    0xc560 0xc1    0x5ca3
+ *
+ * #temp lists the number of monitored temperature sources (first value) plus
+ * the number of directly connectable temperature sensors (second value).
+ */
+
+#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/hwmon-vid.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/acpi.h>
+#include <linux/io.h>
+#include "lm75.h"
+
+#define USE_ALTERNATE
+
+enum kinds { nct6775, nct6776, nct6779 };
+
+/* used to set data->name = nct6775_device_names[data->sio_kind] */
+static const char * const nct6775_device_names[] = {
+	"nct6775",
+	"nct6776",
+	"nct6779",
+};
+
+static unsigned short force_id;
+module_param(force_id, ushort, 0);
+MODULE_PARM_DESC(force_id, "Override the detected device ID");
+
+static unsigned short fan_debounce;
+module_param(fan_debounce, ushort, 0);
+MODULE_PARM_DESC(fan_debounce, "Enable debouncing for fan RPM signal");
+
+#define DRVNAME "nct6775"
+
+/*
+ * Super-I/O constants and functions
+ */
+
+#define NCT6775_LD_ACPI		0x0a
+#define NCT6775_LD_HWM		0x0b
+#define NCT6775_LD_VID		0x0d
+
+#define SIO_REG_LDSEL		0x07	/* Logical device select */
+#define SIO_REG_DEVID		0x20	/* Device ID (2 bytes) */
+#define SIO_REG_ENABLE		0x30	/* Logical device enable */
+#define SIO_REG_ADDR		0x60	/* Logical device address (2 bytes) */
+
+#define SIO_NCT6775_ID		0xb470
+#define SIO_NCT6776_ID		0xc330
+#define SIO_NCT6779_ID		0xc560
+#define SIO_ID_MASK		0xFFF0
+
+enum pwm_enable { off, manual, thermal_cruise, speed_cruise, sf3, sf4 };
+
+static inline void
+superio_outb(int ioreg, int reg, int val)
+{
+	outb(reg, ioreg);
+	outb(val, ioreg + 1);
+}
+
+static inline int
+superio_inb(int ioreg, int reg)
+{
+	outb(reg, ioreg);
+	return inb(ioreg + 1);
+}
+
+static inline void
+superio_select(int ioreg, int ld)
+{
+	outb(SIO_REG_LDSEL, ioreg);
+	outb(ld, ioreg + 1);
+}
+
+static inline int
+superio_enter(int ioreg)
+{
+	/*
+	 * Try to reserve <ioreg> and <ioreg + 1> for exclusive access.
+	 */
+	if (!request_muxed_region(ioreg, 2, DRVNAME))
+		return -EBUSY;
+
+	outb(0x87, ioreg);
+	outb(0x87, ioreg);
+
+	return 0;
+}
+
+static inline void
+superio_exit(int ioreg)
+{
+	outb(0xaa, ioreg);
+	outb(0x02, ioreg);
+	outb(0x02, ioreg + 1);
+	release_region(ioreg, 2);
+}
+
+/*
+ * ISA constants
+ */
+
+#define IOREGION_ALIGNMENT	(~7)
+#define IOREGION_OFFSET		5
+#define IOREGION_LENGTH		2
+#define ADDR_REG_OFFSET		0
+#define DATA_REG_OFFSET		1
+
+#define NCT6775_REG_BANK	0x4E
+#define NCT6775_REG_CONFIG	0x40
+
+/*
+ * Not currently used:
+ * REG_MAN_ID has the value 0x5ca3 for all supported chips.
+ * REG_CHIP_ID == 0x88/0xa1/0xc1 depending on chip model.
+ * REG_MAN_ID is at port 0x4f
+ * REG_CHIP_ID is at port 0x58
+ */
+
+#define NUM_TEMP	10	/* Max number of temp attribute sets w/ limits*/
+#define NUM_TEMP_FIXED	6	/* Max number of fixed temp attribute sets */
+
+#define NUM_REG_ALARM	4	/* Max number of alarm registers */
+
+/* Common and NCT6775 specific data */
+
+/* Voltage min/max registers for nr=7..14 are in bank 5 */
+
+static const u16 NCT6775_REG_IN_MAX[] = {
+	0x2b, 0x2d, 0x2f, 0x31, 0x33, 0x35, 0x37, 0x554, 0x556, 0x558, 0x55a,
+	0x55c, 0x55e, 0x560, 0x562 };
+static const u16 NCT6775_REG_IN_MIN[] = {
+	0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x555, 0x557, 0x559, 0x55b,
+	0x55d, 0x55f, 0x561, 0x563 };
+static const u16 NCT6775_REG_IN[] = {
+	0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x550, 0x551, 0x552
+};
+
+#define NCT6775_REG_VBAT		0x5D
+#define NCT6775_REG_DIODE		0x5E
+
+#define NCT6775_REG_FANDIV1		0x506
+#define NCT6775_REG_FANDIV2		0x507
+
+#define NCT6775_REG_CR_FAN_DEBOUNCE	0xf0
+
+static const u16 NCT6775_REG_ALARM[NUM_REG_ALARM] = { 0x459, 0x45A, 0x45B };
+
+/* 0..15 voltages, 16..23 fans, 24..31 temperatures */
+
+static const s8 NCT6775_ALARM_BITS[] = {
+	0, 1, 2, 3, 8, 21, 20, 16,	/* in0.. in7 */
+	17, -1, -1, -1, -1, -1, -1,	/* in8..in14 */
+	-1,				/* unused */
+	6, 7, 11, 10, 23,		/* fan1..fan5 */
+	-1, -1, -1,			/* unused */
+	4, 5, 13, -1, -1, -1,		/* temp1..temp6 */
+	12, -1 };			/* intrusion0, intrusion1 */
+
+#define FAN_ALARM_BASE		16
+#define TEMP_ALARM_BASE		24
+#define INTRUSION_ALARM_BASE	30
+
+static const u8 NCT6775_REG_CR_CASEOPEN_CLR[] = { 0xe6, 0xee };
+static const u8 NCT6775_CR_CASEOPEN_CLR_MASK[] = { 0x20, 0x01 };
+
+/* DC or PWM output fan configuration */
+static const u8 NCT6775_REG_PWM_MODE[] = { 0x04, 0x04, 0x12 };
+static const u8 NCT6775_PWM_MODE_MASK[] = { 0x01, 0x02, 0x01 };
+
+/* Advanced Fan control, some values are common for all fans */
+
+static const u16 NCT6775_REG_TARGET[] = { 0x101, 0x201, 0x301, 0x801, 0x901 };
+static const u16 NCT6775_REG_FAN_MODE[] = { 0x102, 0x202, 0x302, 0x802, 0x902 };
+static const u16 NCT6775_REG_FAN_STEP_DOWN_TIME[] = {
+	0x103, 0x203, 0x303, 0x803, 0x903 };
+static const u16 NCT6775_REG_FAN_STEP_UP_TIME[] = {
+	0x104, 0x204, 0x304, 0x804, 0x904 };
+static const u16 NCT6775_REG_FAN_STOP_OUTPUT[] = {
+	0x105, 0x205, 0x305, 0x805, 0x905 };
+static const u16 NCT6775_REG_FAN_START_OUTPUT[]
+	= { 0x106, 0x206, 0x306, 0x806, 0x906 };
+static const u16 NCT6775_REG_FAN_MAX_OUTPUT[] = { 0x10a, 0x20a, 0x30a };
+static const u16 NCT6775_REG_FAN_STEP_OUTPUT[] = { 0x10b, 0x20b, 0x30b };
+
+static const u16 NCT6775_REG_FAN_STOP_TIME[] = {
+	0x107, 0x207, 0x307, 0x807, 0x907 };
+static const u16 NCT6775_REG_PWM[] = { 0x109, 0x209, 0x309, 0x809, 0x909 };
+static const u16 NCT6775_REG_PWM_READ[] = { 0x01, 0x03, 0x11, 0x13, 0x15 };
+
+static const u16 NCT6775_REG_FAN[] = { 0x630, 0x632, 0x634, 0x636, 0x638 };
+static const u16 NCT6775_REG_FAN_MIN[] = { 0x3b, 0x3c, 0x3d };
+static const u16 NCT6775_REG_FAN_PULSES[] = { 0x641, 0x642, 0x643, 0x644, 0 };
+
+static const u16 NCT6775_REG_TEMP[] = {
+	0x27, 0x150, 0x250, 0x62b, 0x62c, 0x62d };
+
+static const u16 NCT6775_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
+	0, 0x152, 0x252, 0x628, 0x629, 0x62A };
+static const u16 NCT6775_REG_TEMP_HYST[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
+	0x3a, 0x153, 0x253, 0x673, 0x678, 0x67D };
+static const u16 NCT6775_REG_TEMP_OVER[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
+	0x39, 0x155, 0x255, 0x672, 0x677, 0x67C };
+
+static const u16 NCT6775_REG_TEMP_SOURCE[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
+	0x621, 0x622, 0x623, 0x624, 0x625, 0x626 };
+
+static const u16 NCT6775_REG_TEMP_SEL[] = {
+	0x100, 0x200, 0x300, 0x800, 0x900 };
+
+static const u16 NCT6775_REG_WEIGHT_TEMP_SEL[] = {
+	0x139, 0x239, 0x339, 0x839, 0x939 };
+static const u16 NCT6775_REG_WEIGHT_TEMP_STEP[] = {
+	0x13a, 0x23a, 0x33a, 0x83a, 0x93a };
+static const u16 NCT6775_REG_WEIGHT_TEMP_STEP_TOL[] = {
+	0x13b, 0x23b, 0x33b, 0x83b, 0x93b };
+static const u16 NCT6775_REG_WEIGHT_DUTY_STEP[] = {
+	0x13c, 0x23c, 0x33c, 0x83c, 0x93c };
+static const u16 NCT6775_REG_WEIGHT_TEMP_BASE[] = {
+	0x13d, 0x23d, 0x33d, 0x83d, 0x93d };
+
+static const u16 NCT6775_REG_TEMP_OFFSET[] = { 0x454, 0x455, 0x456 };
+
+static const u16 NCT6775_REG_AUTO_TEMP[] = {
+	0x121, 0x221, 0x321, 0x821, 0x921 };
+static const u16 NCT6775_REG_AUTO_PWM[] = {
+	0x127, 0x227, 0x327, 0x827, 0x927 };
+
+#define NCT6775_AUTO_TEMP(data, nr, p)	((data)->REG_AUTO_TEMP[nr] + (p))
+#define NCT6775_AUTO_PWM(data, nr, p)	((data)->REG_AUTO_PWM[nr] + (p))
+
+static const u16 NCT6775_REG_CRITICAL_ENAB[] = { 0x134, 0x234, 0x334 };
+
+static const u16 NCT6775_REG_CRITICAL_TEMP[] = {
+	0x135, 0x235, 0x335, 0x835, 0x935 };
+static const u16 NCT6775_REG_CRITICAL_TEMP_TOLERANCE[] = {
+	0x138, 0x238, 0x338, 0x838, 0x938 };
+
+static const char *const nct6775_temp_label[] = {
+	"",
+	"SYSTIN",
+	"CPUTIN",
+	"AUXTIN",
+	"AMD SB-TSI",
+	"PECI Agent 0",
+	"PECI Agent 1",
+	"PECI Agent 2",
+	"PECI Agent 3",
+	"PECI Agent 4",
+	"PECI Agent 5",
+	"PECI Agent 6",
+	"PECI Agent 7",
+	"PCH_CHIP_CPU_MAX_TEMP",
+	"PCH_CHIP_TEMP",
+	"PCH_CPU_TEMP",
+	"PCH_MCH_TEMP",
+	"PCH_DIM0_TEMP",
+	"PCH_DIM1_TEMP",
+	"PCH_DIM2_TEMP",
+	"PCH_DIM3_TEMP"
+};
+
+static const u16 NCT6775_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6775_temp_label) - 1]
+	= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x661, 0x662, 0x664 };
+
+static const u16 NCT6775_REG_TEMP_CRIT[ARRAY_SIZE(nct6775_temp_label) - 1]
+	= { 0, 0, 0, 0, 0xa00, 0xa01, 0xa02, 0xa03, 0xa04, 0xa05, 0xa06,
+	    0xa07 };
+
+/* NCT6776 specific data */
+
+static const s8 NCT6776_ALARM_BITS[] = {
+	0, 1, 2, 3, 8, 21, 20, 16,	/* in0.. in7 */
+	17, -1, -1, -1, -1, -1, -1,	/* in8..in14 */
+	-1,				/* unused */
+	6, 7, 11, 10, 23,		/* fan1..fan5 */
+	-1, -1, -1,			/* unused */
+	4, 5, 13, -1, -1, -1,		/* temp1..temp6 */
+	12, 9 };			/* intrusion0, intrusion1 */
+
+static const u16 NCT6776_REG_TOLERANCE_H[] = {
+	0x10c, 0x20c, 0x30c, 0x80c, 0x90c };
+
+static const u8 NCT6776_REG_PWM_MODE[] = { 0x04, 0, 0 };
+static const u8 NCT6776_PWM_MODE_MASK[] = { 0x01, 0, 0 };
+
+static const u16 NCT6776_REG_FAN_MIN[] = { 0x63a, 0x63c, 0x63e, 0x640, 0x642 };
+static const u16 NCT6776_REG_FAN_PULSES[] = { 0x644, 0x645, 0x646, 0, 0 };
+
+static const u16 NCT6776_REG_WEIGHT_DUTY_BASE[] = {
+	0x13e, 0x23e, 0x33e, 0x83e, 0x93e };
+
+static const u16 NCT6776_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
+	0x18, 0x152, 0x252, 0x628, 0x629, 0x62A };
+
+static const char *const nct6776_temp_label[] = {
+	"",
+	"SYSTIN",
+	"CPUTIN",
+	"AUXTIN",
+	"SMBUSMASTER 0",
+	"SMBUSMASTER 1",
+	"SMBUSMASTER 2",
+	"SMBUSMASTER 3",
+	"SMBUSMASTER 4",
+	"SMBUSMASTER 5",
+	"SMBUSMASTER 6",
+	"SMBUSMASTER 7",
+	"PECI Agent 0",
+	"PECI Agent 1",
+	"PCH_CHIP_CPU_MAX_TEMP",
+	"PCH_CHIP_TEMP",
+	"PCH_CPU_TEMP",
+	"PCH_MCH_TEMP",
+	"PCH_DIM0_TEMP",
+	"PCH_DIM1_TEMP",
+	"PCH_DIM2_TEMP",
+	"PCH_DIM3_TEMP",
+	"BYTE_TEMP"
+};
+
+static const u16 NCT6776_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6776_temp_label) - 1]
+	= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x401, 0x402, 0x404 };
+
+static const u16 NCT6776_REG_TEMP_CRIT[ARRAY_SIZE(nct6776_temp_label) - 1]
+	= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x709, 0x70a };
+
+/* NCT6779 specific data */
+
+static const u16 NCT6779_REG_IN[] = {
+	0x480, 0x481, 0x482, 0x483, 0x484, 0x485, 0x486, 0x487,
+	0x488, 0x489, 0x48a, 0x48b, 0x48c, 0x48d, 0x48e };
+
+static const u16 NCT6779_REG_ALARM[NUM_REG_ALARM] = {
+	0x459, 0x45A, 0x45B, 0x568 };
+
+static const s8 NCT6779_ALARM_BITS[] = {
+	0, 1, 2, 3, 8, 21, 20, 16,	/* in0.. in7 */
+	17, 24, 25, 26, 27, 28, 29,	/* in8..in14 */
+	-1,				/* unused */
+	6, 7, 11, 10, 23,		/* fan1..fan5 */
+	-1, -1, -1,			/* unused */
+	4, 5, 13, -1, -1, -1,		/* temp1..temp6 */
+	12, 9 };			/* intrusion0, intrusion1 */
+
+static const u16 NCT6779_REG_FAN[] = { 0x4b0, 0x4b2, 0x4b4, 0x4b6, 0x4b8 };
+static const u16 NCT6779_REG_FAN_PULSES[] = {
+	0x644, 0x645, 0x646, 0x647, 0x648 };
+
+static const u16 NCT6779_REG_CRITICAL_PWM_ENABLE[] = {
+	0x136, 0x236, 0x336, 0x836, 0x936 };
+static const u16 NCT6779_REG_CRITICAL_PWM[] = {
+	0x137, 0x237, 0x337, 0x837, 0x937 };
+
+static const u16 NCT6779_REG_TEMP[] = { 0x27, 0x150 };
+static const u16 NCT6779_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6779_REG_TEMP)] = {
+	0x18, 0x152 };
+static const u16 NCT6779_REG_TEMP_HYST[ARRAY_SIZE(NCT6779_REG_TEMP)] = {
+	0x3a, 0x153 };
+static const u16 NCT6779_REG_TEMP_OVER[ARRAY_SIZE(NCT6779_REG_TEMP)] = {
+	0x39, 0x155 };
+
+static const u16 NCT6779_REG_TEMP_OFFSET[] = {
+	0x454, 0x455, 0x456, 0x44a, 0x44b, 0x44c };
+
+static const char *const nct6779_temp_label[] = {
+	"",
+	"SYSTIN",
+	"CPUTIN",
+	"AUXTIN0",
+	"AUXTIN1",
+	"AUXTIN2",
+	"AUXTIN3",
+	"",
+	"SMBUSMASTER 0",
+	"SMBUSMASTER 1",
+	"SMBUSMASTER 2",
+	"SMBUSMASTER 3",
+	"SMBUSMASTER 4",
+	"SMBUSMASTER 5",
+	"SMBUSMASTER 6",
+	"SMBUSMASTER 7",
+	"PECI Agent 0",
+	"PECI Agent 1",
+	"PCH_CHIP_CPU_MAX_TEMP",
+	"PCH_CHIP_TEMP",
+	"PCH_CPU_TEMP",
+	"PCH_MCH_TEMP",
+	"PCH_DIM0_TEMP",
+	"PCH_DIM1_TEMP",
+	"PCH_DIM2_TEMP",
+	"PCH_DIM3_TEMP",
+	"BYTE_TEMP"
+};
+
+static const u16 NCT6779_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6779_temp_label) - 1]
+	= { 0x490, 0x491, 0x492, 0x493, 0x494, 0x495, 0, 0,
+	    0, 0, 0, 0, 0, 0, 0, 0,
+	    0, 0x400, 0x401, 0x402, 0x404, 0x405, 0x406, 0x407,
+	    0x408, 0 };
+
+static const u16 NCT6779_REG_TEMP_CRIT[ARRAY_SIZE(nct6779_temp_label) - 1]
+	= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x709, 0x70a };
+
+static enum pwm_enable reg_to_pwm_enable(int pwm, int mode)
+{
+	if (mode == 0 && pwm == 255)
+		return off;
+	return mode + 1;
+}
+
+static int pwm_enable_to_reg(enum pwm_enable mode)
+{
+	if (mode == off)
+		return 0;
+	return mode - 1;
+}
+
+/*
+ * Conversions
+ */
+
+/* 1 is DC mode, output in ms */
+static unsigned int step_time_from_reg(u8 reg, u8 mode)
+{
+	return mode ? 400 * reg : 100 * reg;
+}
+
+static u8 step_time_to_reg(unsigned int msec, u8 mode)
+{
+	return clamp_val((mode ? (msec + 200) / 400 :
+					(msec + 50) / 100), 1, 255);
+}
+
+static unsigned int fan_from_reg8(u16 reg, unsigned int divreg)
+{
+	if (reg == 0 || reg == 255)
+		return 0;
+	return 1350000U / (reg << divreg);
+}
+
+static unsigned int fan_from_reg13(u16 reg, unsigned int divreg)
+{
+	if ((reg & 0xff1f) == 0xff1f)
+		return 0;
+
+	reg = (reg & 0x1f) | ((reg & 0xff00) >> 3);
+
+	if (reg == 0)
+		return 0;
+
+	return 1350000U / reg;
+}
+
+static unsigned int fan_from_reg16(u16 reg, unsigned int divreg)
+{
+	if (reg == 0 || reg == 0xffff)
+		return 0;
+
+	/*
+	 * Even though the registers are 16 bit wide, the fan divisor
+	 * still applies.
+	 */
+	return 1350000U / (reg << divreg);
+}
+
+static u16 fan_to_reg(u32 fan, unsigned int divreg)
+{
+	if (!fan)
+		return 0;
+
+	return (1350000U / fan) >> divreg;
+}
+
+static inline unsigned int
+div_from_reg(u8 reg)
+{
+	return 1 << reg;
+}
+
+/*
+ * Some of the voltage inputs have internal scaling, the tables below
+ * contain 8 (the ADC LSB in mV) * scaling factor * 100
+ */
+static const u16 scale_in[15] = {
+	800, 800, 1600, 1600, 800, 800, 800, 1600, 1600, 800, 800, 800, 800,
+	800, 800
+};
+
+static inline long in_from_reg(u8 reg, u8 nr)
+{
+	return DIV_ROUND_CLOSEST(reg * scale_in[nr], 100);
+}
+
+static inline u8 in_to_reg(u32 val, u8 nr)
+{
+	return clamp_val(DIV_ROUND_CLOSEST(val * 100, scale_in[nr]), 0, 255);
+}
+
+/*
+ * Data structures and manipulation thereof
+ */
+
+struct nct6775_data {
+	int addr;	/* IO base of hw monitor block */
+	enum kinds kind;
+	const char *name;
+
+	struct device *hwmon_dev;
+
+	u16 reg_temp[4][NUM_TEMP]; /* 0=temp, 1=temp_over, 2=temp_hyst,
+				    * 3=temp_crit
+				    */
+	u8 temp_src[NUM_TEMP];
+	u16 reg_temp_config[NUM_TEMP];
+	const char * const *temp_label;
+	int temp_label_num;
+
+	u16 REG_CONFIG;
+	u16 REG_VBAT;
+	u16 REG_DIODE;
+
+	const s8 *ALARM_BITS;
+
+	const u16 *REG_VIN;
+	const u16 *REG_IN_MINMAX[2];
+
+	const u16 *REG_TARGET;
+	const u16 *REG_FAN;
+	const u16 *REG_FAN_MODE;
+	const u16 *REG_FAN_MIN;
+	const u16 *REG_FAN_PULSES;
+	const u16 *REG_FAN_TIME[3];
+
+	const u16 *REG_TOLERANCE_H;
+
+	const u8 *REG_PWM_MODE;
+	const u8 *PWM_MODE_MASK;
+
+	const u16 *REG_PWM[7];	/* [0]=pwm, [1]=pwm_start, [2]=pwm_floor,
+				 * [3]=pwm_max, [4]=pwm_step,
+				 * [5]=weight_duty_step, [6]=weight_duty_base
+				 */
+	const u16 *REG_PWM_READ;
+
+	const u16 *REG_AUTO_TEMP;
+	const u16 *REG_AUTO_PWM;
+
+	const u16 *REG_CRITICAL_TEMP;
+	const u16 *REG_CRITICAL_TEMP_TOLERANCE;
+
+	const u16 *REG_TEMP_SOURCE;	/* temp register sources */
+	const u16 *REG_TEMP_SEL;
+	const u16 *REG_WEIGHT_TEMP_SEL;
+	const u16 *REG_WEIGHT_TEMP[3];	/* 0=base, 1=tolerance, 2=step */
+
+	const u16 *REG_TEMP_OFFSET;
+
+	const u16 *REG_ALARM;
+
+	unsigned int (*fan_from_reg)(u16 reg, unsigned int divreg);
+	unsigned int (*fan_from_reg_min)(u16 reg, unsigned int divreg);
+
+	struct mutex update_lock;
+	bool valid;		/* true if following fields are valid */
+	unsigned long last_updated;	/* In jiffies */
+
+	/* Register values */
+	u8 bank;		/* current register bank */
+	u8 in_num;		/* number of in inputs we have */
+	u8 in[15][3];		/* [0]=in, [1]=in_max, [2]=in_min */
+	unsigned int rpm[5];
+	u16 fan_min[5];
+	u8 fan_pulses[5];
+	u8 fan_div[5];
+	u8 has_pwm;
+	u8 has_fan;		/* some fan inputs can be disabled */
+	u8 has_fan_min;		/* some fans don't have min register */
+	bool has_fan_div;
+
+	u8 temp_fixed_num;	/* 3 or 6 */
+	u8 temp_type[NUM_TEMP_FIXED];
+	s8 temp_offset[NUM_TEMP_FIXED];
+	s16 temp[4][NUM_TEMP]; /* 0=temp, 1=temp_over, 2=temp_hyst,
+				* 3=temp_crit */
+	u64 alarms;
+
+	u8 pwm_num;	/* number of pwm */
+	u8 pwm_mode[5]; /* 1->DC variable voltage, 0->PWM variable duty cycle */
+	enum pwm_enable pwm_enable[5];
+			/* 0->off
+			 * 1->manual
+			 * 2->thermal cruise mode (also called SmartFan I)
+			 * 3->fan speed cruise mode
+			 * 4->SmartFan III
+			 * 5->enhanced variable thermal cruise (SmartFan IV)
+			 */
+	u8 pwm[7][5];	/* [0]=pwm, [1]=pwm_start, [2]=pwm_floor,
+			 * [3]=pwm_max, [4]=pwm_step,
+			 * [5]=weight_duty_step, [6]=weight_duty_base
+			 */
+
+	u8 target_temp[5];
+	u8 target_temp_mask;
+	u32 target_speed[5];
+	u32 target_speed_tolerance[5];
+	u8 speed_tolerance_limit;
+
+	u8 temp_tolerance[2][5];
+	u8 tolerance_mask;
+
+	u8 fan_time[3][5]; /* 0 = stop_time, 1 = step_up, 2 = step_down */
+
+	/* Automatic fan speed control registers */
+	int auto_pwm_num;
+	u8 auto_pwm[5][7];
+	u8 auto_temp[5][7];
+	u8 pwm_temp_sel[5];
+	u8 pwm_weight_temp_sel[5];
+	u8 weight_temp[3][5];	/* 0->temp_step, 1->temp_step_tol,
+				 * 2->temp_base
+				 */
+
+	u8 vid;
+	u8 vrm;
+
+	u16 have_temp;
+	u16 have_temp_fixed;
+	u16 have_in;
+#ifdef CONFIG_PM
+	/* Remember extra register values over suspend/resume */
+	u8 vbat;
+	u8 fandiv1;
+	u8 fandiv2;
+#endif
+};
+
+struct nct6775_sio_data {
+	int sioreg;
+	enum kinds kind;
+};
+
+static bool is_word_sized(struct nct6775_data *data, u16 reg)
+{
+	switch (data->kind) {
+	case nct6775:
+		return (((reg & 0xff00) == 0x100 ||
+		    (reg & 0xff00) == 0x200) &&
+		   ((reg & 0x00ff) == 0x50 ||
+		    (reg & 0x00ff) == 0x53 ||
+		    (reg & 0x00ff) == 0x55)) ||
+		  (reg & 0xfff0) == 0x630 ||
+		  reg == 0x640 || reg == 0x642 ||
+		  reg == 0x662 ||
+		  ((reg & 0xfff0) == 0x650 && (reg & 0x000f) >= 0x06) ||
+		  reg == 0x73 || reg == 0x75 || reg == 0x77;
+	case nct6776:
+		return (((reg & 0xff00) == 0x100 ||
+		    (reg & 0xff00) == 0x200) &&
+		   ((reg & 0x00ff) == 0x50 ||
+		    (reg & 0x00ff) == 0x53 ||
+		    (reg & 0x00ff) == 0x55)) ||
+		  (reg & 0xfff0) == 0x630 ||
+		  reg == 0x402 ||
+		  reg == 0x640 || reg == 0x642 ||
+		  ((reg & 0xfff0) == 0x650 && (reg & 0x000f) >= 0x06) ||
+		  reg == 0x73 || reg == 0x75 || reg == 0x77;
+	case nct6779:
+		return reg == 0x150 || reg == 0x153 || reg == 0x155 ||
+		  ((reg & 0xfff0) == 0x4b0 && (reg & 0x000f) < 0x09) ||
+		  reg == 0x402 ||
+		  reg == 0x63a || reg == 0x63c || reg == 0x63e ||
+		  reg == 0x640 || reg == 0x642 ||
+		  reg == 0x73 || reg == 0x75 || reg == 0x77 || reg == 0x79 ||
+		  reg == 0x7b;
+	}
+	return false;
+}
+
+/*
+ * On older chips, only registers 0x50-0x5f are banked.
+ * On more recent chips, all registers are banked.
+ * Assume that is the case and set the bank number for each access.
+ * Cache the bank number so it only needs to be set if it changes.
+ */
+static inline void nct6775_set_bank(struct nct6775_data *data, u16 reg)
+{
+	u8 bank = reg >> 8;
+	if (data->bank != bank) {
+		outb_p(NCT6775_REG_BANK, data->addr + ADDR_REG_OFFSET);
+		outb_p(bank, data->addr + DATA_REG_OFFSET);
+		data->bank = bank;
+	}
+}
+
+static u16 nct6775_read_value(struct nct6775_data *data, u16 reg)
+{
+	int res, word_sized = is_word_sized(data, reg);
+
+	nct6775_set_bank(data, reg);
+	outb_p(reg & 0xff, data->addr + ADDR_REG_OFFSET);
+	res = inb_p(data->addr + DATA_REG_OFFSET);
+	if (word_sized) {
+		outb_p((reg & 0xff) + 1,
+		       data->addr + ADDR_REG_OFFSET);
+		res = (res << 8) + inb_p(data->addr + DATA_REG_OFFSET);
+	}
+	return res;
+}
+
+static int nct6775_write_value(struct nct6775_data *data, u16 reg, u16 value)
+{
+	int word_sized = is_word_sized(data, reg);
+
+	nct6775_set_bank(data, reg);
+	outb_p(reg & 0xff, data->addr + ADDR_REG_OFFSET);
+	if (word_sized) {
+		outb_p(value >> 8, data->addr + DATA_REG_OFFSET);
+		outb_p((reg & 0xff) + 1,
+		       data->addr + ADDR_REG_OFFSET);
+	}
+	outb_p(value & 0xff, data->addr + DATA_REG_OFFSET);
+	return 0;
+}
+
+/* We left-align 8-bit temperature values to make the code simpler */
+static u16 nct6775_read_temp(struct nct6775_data *data, u16 reg)
+{
+	u16 res;
+
+	res = nct6775_read_value(data, reg);
+	if (!is_word_sized(data, reg))
+		res <<= 8;
+
+	return res;
+}
+
+static int nct6775_write_temp(struct nct6775_data *data, u16 reg, u16 value)
+{
+	if (!is_word_sized(data, reg))
+		value >>= 8;
+	return nct6775_write_value(data, reg, value);
+}
+
+/* This function assumes that the caller holds data->update_lock */
+static void nct6775_write_fan_div(struct nct6775_data *data, int nr)
+{
+	u8 reg;
+
+	switch (nr) {
+	case 0:
+		reg = (nct6775_read_value(data, NCT6775_REG_FANDIV1) & 0x70)
+		    | (data->fan_div[0] & 0x7);
+		nct6775_write_value(data, NCT6775_REG_FANDIV1, reg);
+		break;
+	case 1:
+		reg = (nct6775_read_value(data, NCT6775_REG_FANDIV1) & 0x7)
+		    | ((data->fan_div[1] << 4) & 0x70);
+		nct6775_write_value(data, NCT6775_REG_FANDIV1, reg);
+		break;
+	case 2:
+		reg = (nct6775_read_value(data, NCT6775_REG_FANDIV2) & 0x70)
+		    | (data->fan_div[2] & 0x7);
+		nct6775_write_value(data, NCT6775_REG_FANDIV2, reg);
+		break;
+	case 3:
+		reg = (nct6775_read_value(data, NCT6775_REG_FANDIV2) & 0x7)
+		    | ((data->fan_div[3] << 4) & 0x70);
+		nct6775_write_value(data, NCT6775_REG_FANDIV2, reg);
+		break;
+	}
+}
+
+static void nct6775_write_fan_div_common(struct nct6775_data *data, int nr)
+{
+	if (data->kind == nct6775)
+		nct6775_write_fan_div(data, nr);
+}
+
+static void nct6775_update_fan_div(struct nct6775_data *data)
+{
+	u8 i;
+
+	i = nct6775_read_value(data, NCT6775_REG_FANDIV1);
+	data->fan_div[0] = i & 0x7;
+	data->fan_div[1] = (i & 0x70) >> 4;
+	i = nct6775_read_value(data, NCT6775_REG_FANDIV2);
+	data->fan_div[2] = i & 0x7;
+	if (data->has_fan & (1<<3))
+		data->fan_div[3] = (i & 0x70) >> 4;
+}
+
+static void nct6775_update_fan_div_common(struct nct6775_data *data)
+{
+	if (data->kind == nct6775)
+		nct6775_update_fan_div(data);
+}
+
+static void nct6775_init_fan_div(struct nct6775_data *data)
+{
+	int i;
+
+	nct6775_update_fan_div_common(data);
+	/*
+	 * For all fans, start with highest divider value if the divider
+	 * register is not initialized. This ensures that we get a
+	 * reading from the fan count register, even if it is not optimal.
+	 * We'll compute a better divider later on.
+	 */
+	for (i = 0; i < 3; i++) {
+		if (!(data->has_fan & (1 << i)))
+			continue;
+		if (data->fan_div[i] == 0) {
+			data->fan_div[i] = 7;
+			nct6775_write_fan_div_common(data, i);
+		}
+	}
+}
+
+static void nct6775_init_fan_common(struct device *dev,
+				    struct nct6775_data *data)
+{
+	int i;
+	u8 reg;
+
+	if (data->has_fan_div)
+		nct6775_init_fan_div(data);
+
+	/*
+	 * If fan_min is not set (0), set it to 0xff to disable it. This
+	 * prevents the unnecessary warning when fanX_min is reported as 0.
+	 */
+	for (i = 0; i < 5; i++) {
+		if (data->has_fan_min & (1 << i)) {
+			reg = nct6775_read_value(data, data->REG_FAN_MIN[i]);
+			if (!reg)
+				nct6775_write_value(data, data->REG_FAN_MIN[i],
+						    data->has_fan_div ? 0xff
+								      : 0xff1f);
+		}
+	}
+}
+
+static void nct6775_select_fan_div(struct device *dev,
+				   struct nct6775_data *data, int nr, u16 reg)
+{
+	u8 fan_div = data->fan_div[nr];
+	u16 fan_min;
+
+	if (!data->has_fan_div)
+		return;
+
+	/*
+	 * If we failed to measure the fan speed, or the reported value is not
+	 * in the optimal range, and the clock divider can be modified,
+	 * let's try that for next time.
+	 */
+	if (reg == 0x00 && fan_div < 0x07)
+		fan_div++;
+	else if (reg != 0x00 && reg < 0x30 && fan_div > 0)
+		fan_div--;
+
+	if (fan_div != data->fan_div[nr]) {
+		dev_dbg(dev, "Modifying fan%d clock divider from %u to %u\n",
+			nr + 1, div_from_reg(data->fan_div[nr]),
+			div_from_reg(fan_div));
+
+		/* Preserve min limit if possible */
+		if (data->has_fan_min & (1 << nr)) {
+			fan_min = data->fan_min[nr];
+			if (fan_div > data->fan_div[nr]) {
+				if (fan_min != 255 && fan_min > 1)
+					fan_min >>= 1;
+			} else {
+				if (fan_min != 255) {
+					fan_min <<= 1;
+					if (fan_min > 254)
+						fan_min = 254;
+				}
+			}
+			if (fan_min != data->fan_min[nr]) {
+				data->fan_min[nr] = fan_min;
+				nct6775_write_value(data, data->REG_FAN_MIN[nr],
+						    fan_min);
+			}
+		}
+		data->fan_div[nr] = fan_div;
+		nct6775_write_fan_div_common(data, nr);
+	}
+}
+
+static void nct6775_update_pwm(struct device *dev)
+{
+	struct nct6775_data *data = dev_get_drvdata(dev);
+	int i, j;
+	int fanmodecfg, reg;
+	bool duty_is_dc;
+
+	for (i = 0; i < data->pwm_num; i++) {
+		if (!(data->has_pwm & (1 << i)))
+			continue;
+
+		duty_is_dc = data->REG_PWM_MODE[i] &&
+		  (nct6775_read_value(data, data->REG_PWM_MODE[i])
+		   & data->PWM_MODE_MASK[i]);
+		data->pwm_mode[i] = duty_is_dc;
+
+		fanmodecfg = nct6775_read_value(data, data->REG_FAN_MODE[i]);
+		for (j = 0; j < ARRAY_SIZE(data->REG_PWM); j++) {
+			if (data->REG_PWM[j] && data->REG_PWM[j][i]) {
+				data->pwm[j][i]
+				  = nct6775_read_value(data,
+						       data->REG_PWM[j][i]);
+			}
+		}
+
+		data->pwm_enable[i] = reg_to_pwm_enable(data->pwm[0][i],
+							(fanmodecfg >> 4) & 7);
+
+		if (!data->temp_tolerance[0][i] ||
+		    data->pwm_enable[i] != speed_cruise)
+			data->temp_tolerance[0][i] = fanmodecfg & 0x0f;
+		if (!data->target_speed_tolerance[i] ||
+		    data->pwm_enable[i] == speed_cruise) {
+			u8 t = fanmodecfg & 0x0f;
+			if (data->REG_TOLERANCE_H) {
+				t |= (nct6775_read_value(data,
+				      data->REG_TOLERANCE_H[i]) & 0x70) >> 1;
+			}
+			data->target_speed_tolerance[i] = t;
+		}
+
+		data->temp_tolerance[1][i] =
+			nct6775_read_value(data,
+					data->REG_CRITICAL_TEMP_TOLERANCE[i]);
+
+		reg = nct6775_read_value(data, data->REG_TEMP_SEL[i]);
+		data->pwm_temp_sel[i] = reg & 0x1f;
+		/* If fan can stop, report floor as 0 */
+		if (reg & 0x80)
+			data->pwm[2][i] = 0;
+
+		reg = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[i]);
+		data->pwm_weight_temp_sel[i] = reg & 0x1f;
+		/* If weight is disabled, report weight source as 0 */
+		if (j == 1 && !(reg & 0x80))
+			data->pwm_weight_temp_sel[i] = 0;
+
+		/* Weight temp data */
+		for (j = 0; j < 3; j++) {
+			data->weight_temp[j][i]
+			  = nct6775_read_value(data,
+					       data->REG_WEIGHT_TEMP[j][i]);
+		}
+	}
+}
+
+static void nct6775_update_pwm_limits(struct device *dev)
+{
+	struct nct6775_data *data = dev_get_drvdata(dev);
+	int i, j;
+	u8 reg;
+	u16 reg_t;
+
+	for (i = 0; i < data->pwm_num; i++) {
+		if (!(data->has_pwm & (1 << i)))
+			continue;
+
+		for (j = 0; j < 3; j++) {
+			data->fan_time[j][i] =
+			  nct6775_read_value(data, data->REG_FAN_TIME[j][i]);
+		}
+
+		reg_t = nct6775_read_value(data, data->REG_TARGET[i]);
+		/* Update only in matching mode or if never updated */
+		if (!data->target_temp[i] ||
+		    data->pwm_enable[i] == thermal_cruise)
+			data->target_temp[i] = reg_t & data->target_temp_mask;
+		if (!data->target_speed[i] ||
+		    data->pwm_enable[i] == speed_cruise) {
+			if (data->REG_TOLERANCE_H) {
+				reg_t |= (nct6775_read_value(data,
+					data->REG_TOLERANCE_H[i]) & 0x0f) << 8;
+			}
+			data->target_speed[i] = reg_t;
+		}
+
+		for (j = 0; j < data->auto_pwm_num; j++) {
+			data->auto_pwm[i][j] =
+			  nct6775_read_value(data,
+					     NCT6775_AUTO_PWM(data, i, j));
+			data->auto_temp[i][j] =
+			  nct6775_read_value(data,
+					     NCT6775_AUTO_TEMP(data, i, j));
+		}
+
+		/* critical auto_pwm temperature data */
+		data->auto_temp[i][data->auto_pwm_num] =
+			nct6775_read_value(data, data->REG_CRITICAL_TEMP[i]);
+
+		switch (data->kind) {
+		case nct6775:
+			reg = nct6775_read_value(data,
+						 NCT6775_REG_CRITICAL_ENAB[i]);
+			data->auto_pwm[i][data->auto_pwm_num] =
+						(reg & 0x02) ? 0xff : 0x00;
+			break;
+		case nct6776:
+			data->auto_pwm[i][data->auto_pwm_num] = 0xff;
+			break;
+		case nct6779:
+			reg = nct6775_read_value(data,
+					NCT6779_REG_CRITICAL_PWM_ENABLE[i]);
+			if (reg & 1)
+				data->auto_pwm[i][data->auto_pwm_num] =
+				  nct6775_read_value(data,
+					NCT6779_REG_CRITICAL_PWM[i]);
+			else
+				data->auto_pwm[i][data->auto_pwm_num] = 0xff;
+			break;
+		}
+	}
+}
+
+static struct nct6775_data *nct6775_update_device(struct device *dev)
+{
+	struct nct6775_data *data = dev_get_drvdata(dev);
+	int i, j;
+
+	mutex_lock(&data->update_lock);
+
+	if (time_after(jiffies, data->last_updated + HZ + HZ/2)
+	    || !data->valid) {
+		/* Fan clock dividers */
+		nct6775_update_fan_div_common(data);
+
+		/* Measured voltages and limits */
+		for (i = 0; i < data->in_num; i++) {
+			if (!(data->have_in & (1 << i)))
+				continue;
+
+			data->in[i][0] = nct6775_read_value(data,
+							    data->REG_VIN[i]);
+			data->in[i][1] = nct6775_read_value(data,
+					  data->REG_IN_MINMAX[0][i]);
+			data->in[i][2] = nct6775_read_value(data,
+					  data->REG_IN_MINMAX[1][i]);
+		}
+
+		/* Measured fan speeds and limits */
+		for (i = 0; i < 5; i++) {
+			u16 reg;
+
+			if (!(data->has_fan & (1 << i)))
+				continue;
+
+			reg = nct6775_read_value(data, data->REG_FAN[i]);
+			data->rpm[i] = data->fan_from_reg(reg,
+							  data->fan_div[i]);
+
+			if (data->has_fan_min & (1 << i))
+				data->fan_min[i] = nct6775_read_value(data,
+					   data->REG_FAN_MIN[i]);
+			data->fan_pulses[i] =
+			  nct6775_read_value(data, data->REG_FAN_PULSES[i]);
+
+			nct6775_select_fan_div(dev, data, i, reg);
+		}
+
+		nct6775_update_pwm(dev);
+		nct6775_update_pwm_limits(dev);
+
+		/* Measured temperatures and limits */
+		for (i = 0; i < NUM_TEMP; i++) {
+			if (!(data->have_temp & (1 << i)))
+				continue;
+			for (j = 0; j < 4; j++) {
+				if (data->reg_temp[j][i])
+					data->temp[j][i]
+					  = nct6775_read_temp(data,
+						data->reg_temp[j][i]);
+			}
+			if (!(data->have_temp_fixed & (1 << i)))
+				continue;
+			data->temp_offset[i]
+			  = nct6775_read_value(data, data->REG_TEMP_OFFSET[i]);
+		}
+
+		data->alarms = 0;
+		for (i = 0; i < NUM_REG_ALARM; i++) {
+			u8 alarm;
+			if (!data->REG_ALARM[i])
+				continue;
+			alarm = nct6775_read_value(data, data->REG_ALARM[i]);
+			data->alarms |= ((u64)alarm) << (i << 3);
+		}
+
+		data->last_updated = jiffies;
+		data->valid = true;
+	}
+
+	mutex_unlock(&data->update_lock);
+	return data;
+}
+
+/*
+ * Sysfs callback functions
+ */
+static ssize_t
+show_in_reg(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct nct6775_data *data = nct6775_update_device(dev);
+	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+	int nr = sattr->nr;
+	int index = sattr->index;
+	return sprintf(buf, "%ld\n", in_from_reg(data->in[nr][index], nr));
+}
+
+static ssize_t
+store_in_reg(struct device *dev, struct device_attribute *attr, const char *buf,
+	     size_t count)
+{
+	struct nct6775_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+	int nr = sattr->nr;
+	int index = sattr->index;
+	unsigned long val;
+	int err = kstrtoul(buf, 10, &val);
+	if (err < 0)
+		return err;
+	mutex_lock(&data->update_lock);
+	data->in[nr][index] = in_to_reg(val, nr);
+	nct6775_write_value(data, data->REG_IN_MINMAX[index-1][nr],
+			    data->in[nr][index]);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static ssize_t
+show_alarm(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct nct6775_data *data = nct6775_update_device(dev);
+	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
+	int nr = data->ALARM_BITS[sattr->index];
+	return sprintf(buf, "%u\n",
+		       (unsigned int)((data->alarms >> nr) & 0x01));
+}
+
+static SENSOR_DEVICE_ATTR_2(in0_input, S_IRUGO, show_in_reg, NULL, 0, 0);
+static SENSOR_DEVICE_ATTR_2(in1_input, S_IRUGO, show_in_reg, NULL, 1, 0);
+static SENSOR_DEVICE_ATTR_2(in2_input, S_IRUGO, show_in_reg, NULL, 2, 0);
+static SENSOR_DEVICE_ATTR_2(in3_input, S_IRUGO, show_in_reg, NULL, 3, 0);
+static SENSOR_DEVICE_ATTR_2(in4_input, S_IRUGO, show_in_reg, NULL, 4, 0);
+static SENSOR_DEVICE_ATTR_2(in5_input, S_IRUGO, show_in_reg, NULL, 5, 0);
+static SENSOR_DEVICE_ATTR_2(in6_input, S_IRUGO, show_in_reg, NULL, 6, 0);
+static SENSOR_DEVICE_ATTR_2(in7_input, S_IRUGO, show_in_reg, NULL, 7, 0);
+static SENSOR_DEVICE_ATTR_2(in8_input, S_IRUGO, show_in_reg, NULL, 8, 0);
+static SENSOR_DEVICE_ATTR_2(in9_input, S_IRUGO, show_in_reg, NULL, 9, 0);
+static SENSOR_DEVICE_ATTR_2(in10_input, S_IRUGO, show_in_reg, NULL, 10, 0);
+static SENSOR_DEVICE_ATTR_2(in11_input, S_IRUGO, show_in_reg, NULL, 11, 0);
+static SENSOR_DEVICE_ATTR_2(in12_input, S_IRUGO, show_in_reg, NULL, 12, 0);
+static SENSOR_DEVICE_ATTR_2(in13_input, S_IRUGO, show_in_reg, NULL, 13, 0);
+static SENSOR_DEVICE_ATTR_2(in14_input, S_IRUGO, show_in_reg, NULL, 14, 0);
+
+static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0);
+static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1);
+static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2);
+static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3);
+static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 4);
+static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 5);
+static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 6);
+static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 7);
+static SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 8);
+static SENSOR_DEVICE_ATTR(in9_alarm, S_IRUGO, show_alarm, NULL, 9);
+static SENSOR_DEVICE_ATTR(in10_alarm, S_IRUGO, show_alarm, NULL, 10);
+static SENSOR_DEVICE_ATTR(in11_alarm, S_IRUGO, show_alarm, NULL, 11);
+static SENSOR_DEVICE_ATTR(in12_alarm, S_IRUGO, show_alarm, NULL, 12);
+static SENSOR_DEVICE_ATTR(in13_alarm, S_IRUGO, show_alarm, NULL, 13);
+static SENSOR_DEVICE_ATTR(in14_alarm, S_IRUGO, show_alarm, NULL, 14);
+
+static SENSOR_DEVICE_ATTR_2(in0_min, S_IWUSR | S_IRUGO, show_in_reg,
+			    store_in_reg, 0, 1);
+static SENSOR_DEVICE_ATTR_2(in1_min, S_IWUSR | S_IRUGO, show_in_reg,
+			    store_in_reg, 1, 1);
+static SENSOR_DEVICE_ATTR_2(in2_min, S_IWUSR | S_IRUGO, show_in_reg,
+			    store_in_reg, 2, 1);
+static SENSOR_DEVICE_ATTR_2(in3_min, S_IWUSR | S_IRUGO, show_in_reg,
+			    store_in_reg, 3, 1);
+static SENSOR_DEVICE_ATTR_2(in4_min, S_IWUSR | S_IRUGO, show_in_reg,
+			    store_in_reg, 4, 1);
+static SENSOR_DEVICE_ATTR_2(in5_min, S_IWUSR | S_IRUGO, show_in_reg,
+			    store_in_reg, 5, 1);
+static SENSOR_DEVICE_ATTR_2(in6_min, S_IWUSR | S_IRUGO, show_in_reg,
+			    store_in_reg, 6, 1);
+static SENSOR_DEVICE_ATTR_2(in7_min, S_IWUSR | S_IRUGO, show_in_reg,
+			    store_in_reg, 7, 1);
+static SENSOR_DEVICE_ATTR_2(in8_min, S_IWUSR | S_IRUGO, show_in_reg,
+			    store_in_reg, 8, 1);
+static SENSOR_DEVICE_ATTR_2(in9_min, S_IWUSR | S_IRUGO, show_in_reg,
+			    store_in_reg, 9, 1);
+static SENSOR_DEVICE_ATTR_2(in10_min, S_IWUSR | S_IRUGO, show_in_reg,
+			    store_in_reg, 10, 1);
+static SENSOR_DEVICE_ATTR_2(in11_min, S_IWUSR | S_IRUGO, show_in_reg,
+			    store_in_reg, 11, 1);
+static SENSOR_DEVICE_ATTR_2(in12_min, S_IWUSR | S_IRUGO, show_in_reg,
+			    store_in_reg, 12, 1);
+static SENSOR_DEVICE_ATTR_2(in13_min, S_IWUSR | S_IRUGO, show_in_reg,
+			    store_in_reg, 13, 1);
+static SENSOR_DEVICE_ATTR_2(in14_min, S_IWUSR | S_IRUGO, show_in_reg,
+			    store_in_reg, 14, 1);
+
+static SENSOR_DEVICE_ATTR_2(in0_max, S_IWUSR | S_IRUGO, show_in_reg,
+			    store_in_reg, 0, 2);
+static SENSOR_DEVICE_ATTR_2(in1_max, S_IWUSR | S_IRUGO, show_in_reg,
+			    store_in_reg, 1, 2);
+static SENSOR_DEVICE_ATTR_2(in2_max, S_IWUSR | S_IRUGO, show_in_reg,
+			    store_in_reg, 2, 2);
+static SENSOR_DEVICE_ATTR_2(in3_max, S_IWUSR | S_IRUGO, show_in_reg,
+			    store_in_reg, 3, 2);
+static SENSOR_DEVICE_ATTR_2(in4_max, S_IWUSR | S_IRUGO, show_in_reg,
+			    store_in_reg, 4, 2);
+static SENSOR_DEVICE_ATTR_2(in5_max, S_IWUSR | S_IRUGO, show_in_reg,
+			    store_in_reg, 5, 2);
+static SENSOR_DEVICE_ATTR_2(in6_max, S_IWUSR | S_IRUGO, show_in_reg,
+			    store_in_reg, 6, 2);
+static SENSOR_DEVICE_ATTR_2(in7_max, S_IWUSR | S_IRUGO, show_in_reg,
+			    store_in_reg, 7, 2);
+static SENSOR_DEVICE_ATTR_2(in8_max, S_IWUSR | S_IRUGO, show_in_reg,
+			    store_in_reg, 8, 2);
+static SENSOR_DEVICE_ATTR_2(in9_max, S_IWUSR | S_IRUGO, show_in_reg,
+			    store_in_reg, 9, 2);
+static SENSOR_DEVICE_ATTR_2(in10_max, S_IWUSR | S_IRUGO, show_in_reg,
+			    store_in_reg, 10, 2);
+static SENSOR_DEVICE_ATTR_2(in11_max, S_IWUSR | S_IRUGO, show_in_reg,
+			    store_in_reg, 11, 2);
+static SENSOR_DEVICE_ATTR_2(in12_max, S_IWUSR | S_IRUGO, show_in_reg,
+			    store_in_reg, 12, 2);
+static SENSOR_DEVICE_ATTR_2(in13_max, S_IWUSR | S_IRUGO, show_in_reg,
+			    store_in_reg, 13, 2);
+static SENSOR_DEVICE_ATTR_2(in14_max, S_IWUSR | S_IRUGO, show_in_reg,
+			    store_in_reg, 14, 2);
+
+static struct attribute *nct6775_attributes_in[15][5] = {
+	{
+		&sensor_dev_attr_in0_input.dev_attr.attr,
+		&sensor_dev_attr_in0_min.dev_attr.attr,
+		&sensor_dev_attr_in0_max.dev_attr.attr,
+		&sensor_dev_attr_in0_alarm.dev_attr.attr,
+		NULL
+	},
+	{
+		&sensor_dev_attr_in1_input.dev_attr.attr,
+		&sensor_dev_attr_in1_min.dev_attr.attr,
+		&sensor_dev_attr_in1_max.dev_attr.attr,
+		&sensor_dev_attr_in1_alarm.dev_attr.attr,
+		NULL
+	},
+	{
+		&sensor_dev_attr_in2_input.dev_attr.attr,
+		&sensor_dev_attr_in2_min.dev_attr.attr,
+		&sensor_dev_attr_in2_max.dev_attr.attr,
+		&sensor_dev_attr_in2_alarm.dev_attr.attr,
+		NULL
+	},
+	{
+		&sensor_dev_attr_in3_input.dev_attr.attr,
+		&sensor_dev_attr_in3_min.dev_attr.attr,
+		&sensor_dev_attr_in3_max.dev_attr.attr,
+		&sensor_dev_attr_in3_alarm.dev_attr.attr,
+		NULL
+	},
+	{
+		&sensor_dev_attr_in4_input.dev_attr.attr,
+		&sensor_dev_attr_in4_min.dev_attr.attr,
+		&sensor_dev_attr_in4_max.dev_attr.attr,
+		&sensor_dev_attr_in4_alarm.dev_attr.attr,
+		NULL
+	},
+	{
+		&sensor_dev_attr_in5_input.dev_attr.attr,
+		&sensor_dev_attr_in5_min.dev_attr.attr,
+		&sensor_dev_attr_in5_max.dev_attr.attr,
+		&sensor_dev_attr_in5_alarm.dev_attr.attr,
+		NULL
+	},
+	{
+		&sensor_dev_attr_in6_input.dev_attr.attr,
+		&sensor_dev_attr_in6_min.dev_attr.attr,
+		&sensor_dev_attr_in6_max.dev_attr.attr,
+		&sensor_dev_attr_in6_alarm.dev_attr.attr,
+		NULL
+	},
+	{
+		&sensor_dev_attr_in7_input.dev_attr.attr,
+		&sensor_dev_attr_in7_min.dev_attr.attr,
+		&sensor_dev_attr_in7_max.dev_attr.attr,
+		&sensor_dev_attr_in7_alarm.dev_attr.attr,
+		NULL
+	},
+	{
+		&sensor_dev_attr_in8_input.dev_attr.attr,
+		&sensor_dev_attr_in8_min.dev_attr.attr,
+		&sensor_dev_attr_in8_max.dev_attr.attr,
+		&sensor_dev_attr_in8_alarm.dev_attr.attr,
+		NULL
+	},
+	{
+		&sensor_dev_attr_in9_input.dev_attr.attr,
+		&sensor_dev_attr_in9_min.dev_attr.attr,
+		&sensor_dev_attr_in9_max.dev_attr.attr,
+		&sensor_dev_attr_in9_alarm.dev_attr.attr,
+		NULL
+	},
+	{
+		&sensor_dev_attr_in10_input.dev_attr.attr,
+		&sensor_dev_attr_in10_min.dev_attr.attr,
+		&sensor_dev_attr_in10_max.dev_attr.attr,
+		&sensor_dev_attr_in10_alarm.dev_attr.attr,
+		NULL
+	},
+	{
+		&sensor_dev_attr_in11_input.dev_attr.attr,
+		&sensor_dev_attr_in11_min.dev_attr.attr,
+		&sensor_dev_attr_in11_max.dev_attr.attr,
+		&sensor_dev_attr_in11_alarm.dev_attr.attr,
+		NULL
+	},
+	{
+		&sensor_dev_attr_in12_input.dev_attr.attr,
+		&sensor_dev_attr_in12_min.dev_attr.attr,
+		&sensor_dev_attr_in12_max.dev_attr.attr,
+		&sensor_dev_attr_in12_alarm.dev_attr.attr,
+		NULL
+	},
+	{
+		&sensor_dev_attr_in13_input.dev_attr.attr,
+		&sensor_dev_attr_in13_min.dev_attr.attr,
+		&sensor_dev_attr_in13_max.dev_attr.attr,
+		&sensor_dev_attr_in13_alarm.dev_attr.attr,
+		NULL
+	},
+	{
+		&sensor_dev_attr_in14_input.dev_attr.attr,
+		&sensor_dev_attr_in14_min.dev_attr.attr,
+		&sensor_dev_attr_in14_max.dev_attr.attr,
+		&sensor_dev_attr_in14_alarm.dev_attr.attr,
+		NULL
+	},
+};
+
+static const struct attribute_group nct6775_group_in[15] = {
+	{ .attrs = nct6775_attributes_in[0] },
+	{ .attrs = nct6775_attributes_in[1] },
+	{ .attrs = nct6775_attributes_in[2] },
+	{ .attrs = nct6775_attributes_in[3] },
+	{ .attrs = nct6775_attributes_in[4] },
+	{ .attrs = nct6775_attributes_in[5] },
+	{ .attrs = nct6775_attributes_in[6] },
+	{ .attrs = nct6775_attributes_in[7] },
+	{ .attrs = nct6775_attributes_in[8] },
+	{ .attrs = nct6775_attributes_in[9] },
+	{ .attrs = nct6775_attributes_in[10] },
+	{ .attrs = nct6775_attributes_in[11] },
+	{ .attrs = nct6775_attributes_in[12] },
+	{ .attrs = nct6775_attributes_in[13] },
+	{ .attrs = nct6775_attributes_in[14] },
+};
+
+static ssize_t
+show_fan(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct nct6775_data *data = nct6775_update_device(dev);
+	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
+	int nr = sattr->index;
+	return sprintf(buf, "%d\n", data->rpm[nr]);
+}
+
+static ssize_t
+show_fan_min(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct nct6775_data *data = nct6775_update_device(dev);
+	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
+	int nr = sattr->index;
+	return sprintf(buf, "%d\n",
+		       data->fan_from_reg_min(data->fan_min[nr],
+					      data->fan_div[nr]));
+}
+
+static ssize_t
+show_fan_div(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct nct6775_data *data = nct6775_update_device(dev);
+	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
+	int nr = sattr->index;
+	return sprintf(buf, "%u\n", div_from_reg(data->fan_div[nr]));
+}
+
+static ssize_t
+store_fan_min(struct device *dev, struct device_attribute *attr,
+	      const char *buf, size_t count)
+{
+	struct nct6775_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
+	int nr = sattr->index;
+	unsigned long val;
+	int err;
+	unsigned int reg;
+	u8 new_div;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err < 0)
+		return err;
+
+	mutex_lock(&data->update_lock);
+	if (!data->has_fan_div) {
+		/* NCT6776F or NCT6779D; we know this is a 13 bit register */
+		if (!val) {
+			val = 0xff1f;
+		} else {
+			if (val > 1350000U)
+				val = 135000U;
+			val = 1350000U / val;
+			val = (val & 0x1f) | ((val << 3) & 0xff00);
+		}
+		data->fan_min[nr] = val;
+		goto write_min;	/* Leave fan divider alone */
+	}
+	if (!val) {
+		/* No min limit, alarm disabled */
+		data->fan_min[nr] = 255;
+		new_div = data->fan_div[nr]; /* No change */
+		dev_info(dev, "fan%u low limit and alarm disabled\n", nr + 1);
+		goto write_div;
+	}
+	reg = 1350000U / val;
+	if (reg >= 128 * 255) {
+		/*
+		 * Speed below this value cannot possibly be represented,
+		 * even with the highest divider (128)
+		 */
+		data->fan_min[nr] = 254;
+		new_div = 7; /* 128 == (1 << 7) */
+		dev_warn(dev,
+			 "fan%u low limit %lu below minimum %u, set to minimum\n",
+			 nr + 1, val, data->fan_from_reg_min(254, 7));
+	} else if (!reg) {
+		/*
+		 * Speed above this value cannot possibly be represented,
+		 * even with the lowest divider (1)
+		 */
+		data->fan_min[nr] = 1;
+		new_div = 0; /* 1 == (1 << 0) */
+		dev_warn(dev,
+			 "fan%u low limit %lu above maximum %u, set to maximum\n",
+			 nr + 1, val, data->fan_from_reg_min(1, 0));
+	} else {
+		/*
+		 * Automatically pick the best divider, i.e. the one such
+		 * that the min limit will correspond to a register value
+		 * in the 96..192 range
+		 */
+		new_div = 0;
+		while (reg > 192 && new_div < 7) {
+			reg >>= 1;
+			new_div++;
+		}
+		data->fan_min[nr] = reg;
+	}
+
+write_div:
+	/*
+	 * Write both the fan clock divider (if it changed) and the new
+	 * fan min (unconditionally)
+	 */
+	if (new_div != data->fan_div[nr]) {
+		dev_dbg(dev, "fan%u clock divider changed from %u to %u\n",
+			nr + 1, div_from_reg(data->fan_div[nr]),
+			div_from_reg(new_div));
+		data->fan_div[nr] = new_div;
+		nct6775_write_fan_div_common(data, nr);
+		/* Give the chip time to sample a new speed value */
+		data->last_updated = jiffies;
+	}
+
+write_min:
+	nct6775_write_value(data, data->REG_FAN_MIN[nr], data->fan_min[nr]);
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+static ssize_t
+show_fan_pulses(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct nct6775_data *data = nct6775_update_device(dev);
+	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
+	int p = data->fan_pulses[sattr->index];
+
+	return sprintf(buf, "%d\n", p ? : 4);
+}
+
+static ssize_t
+store_fan_pulses(struct device *dev, struct device_attribute *attr,
+		 const char *buf, size_t count)
+{
+	struct nct6775_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
+	int nr = sattr->index;
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err < 0)
+		return err;
+
+	if (val > 4)
+		return -EINVAL;
+
+	mutex_lock(&data->update_lock);
+	data->fan_pulses[nr] = val & 3;
+	nct6775_write_value(data, data->REG_FAN_PULSES[nr], val & 3);
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+static struct sensor_device_attribute sda_fan_input[] = {
+	SENSOR_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0),
+	SENSOR_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1),
+	SENSOR_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2),
+	SENSOR_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3),
+	SENSOR_ATTR(fan5_input, S_IRUGO, show_fan, NULL, 4),
+};
+
+static struct sensor_device_attribute sda_fan_alarm[] = {
+	SENSOR_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, FAN_ALARM_BASE),
+	SENSOR_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, FAN_ALARM_BASE + 1),
+	SENSOR_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, FAN_ALARM_BASE + 2),
+	SENSOR_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL, FAN_ALARM_BASE + 3),
+	SENSOR_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL, FAN_ALARM_BASE + 4),
+};
+
+static struct sensor_device_attribute sda_fan_min[] = {
+	SENSOR_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min,
+		    store_fan_min, 0),
+	SENSOR_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min,
+		    store_fan_min, 1),
+	SENSOR_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min,
+		    store_fan_min, 2),
+	SENSOR_ATTR(fan4_min, S_IWUSR | S_IRUGO, show_fan_min,
+		    store_fan_min, 3),
+	SENSOR_ATTR(fan5_min, S_IWUSR | S_IRUGO, show_fan_min,
+		    store_fan_min, 4),
+};
+
+static struct sensor_device_attribute sda_fan_pulses[] = {
+	SENSOR_ATTR(fan1_pulses, S_IWUSR | S_IRUGO, show_fan_pulses,
+		    store_fan_pulses, 0),
+	SENSOR_ATTR(fan2_pulses, S_IWUSR | S_IRUGO, show_fan_pulses,
+		    store_fan_pulses, 1),
+	SENSOR_ATTR(fan3_pulses, S_IWUSR | S_IRUGO, show_fan_pulses,
+		    store_fan_pulses, 2),
+	SENSOR_ATTR(fan4_pulses, S_IWUSR | S_IRUGO, show_fan_pulses,
+		    store_fan_pulses, 3),
+	SENSOR_ATTR(fan5_pulses, S_IWUSR | S_IRUGO, show_fan_pulses,
+		    store_fan_pulses, 4),
+};
+
+static struct sensor_device_attribute sda_fan_div[] = {
+	SENSOR_ATTR(fan1_div, S_IRUGO, show_fan_div, NULL, 0),
+	SENSOR_ATTR(fan2_div, S_IRUGO, show_fan_div, NULL, 1),
+	SENSOR_ATTR(fan3_div, S_IRUGO, show_fan_div, NULL, 2),
+	SENSOR_ATTR(fan4_div, S_IRUGO, show_fan_div, NULL, 3),
+	SENSOR_ATTR(fan5_div, S_IRUGO, show_fan_div, NULL, 4),
+};
+
+static ssize_t
+show_temp_label(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct nct6775_data *data = nct6775_update_device(dev);
+	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
+	int nr = sattr->index;
+	return sprintf(buf, "%s\n", data->temp_label[data->temp_src[nr]]);
+}
+
+static ssize_t
+show_temp(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct nct6775_data *data = nct6775_update_device(dev);
+	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+	int nr = sattr->nr;
+	int index = sattr->index;
+
+	return sprintf(buf, "%d\n", LM75_TEMP_FROM_REG(data->temp[index][nr]));
+}
+
+static ssize_t
+store_temp(struct device *dev, struct device_attribute *attr, const char *buf,
+	   size_t count)
+{
+	struct nct6775_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+	int nr = sattr->nr;
+	int index = sattr->index;
+	int err;
+	long val;
+
+	err = kstrtol(buf, 10, &val);
+	if (err < 0)
+		return err;
+
+	mutex_lock(&data->update_lock);
+	data->temp[index][nr] = LM75_TEMP_TO_REG(val);
+	nct6775_write_temp(data, data->reg_temp[index][nr],
+			   data->temp[index][nr]);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static ssize_t
+show_temp_offset(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct nct6775_data *data = nct6775_update_device(dev);
+	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
+
+	return sprintf(buf, "%d\n", data->temp_offset[sattr->index] * 1000);
+}
+
+static ssize_t
+store_temp_offset(struct device *dev, struct device_attribute *attr,
+		  const char *buf, size_t count)
+{
+	struct nct6775_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
+	int nr = sattr->index;
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err < 0)
+		return err;
+
+	val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), -128, 127);
+
+	mutex_lock(&data->update_lock);
+	data->temp_offset[nr] = val;
+	nct6775_write_value(data, data->REG_TEMP_OFFSET[nr], val);
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+static ssize_t
+show_temp_type(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct nct6775_data *data = nct6775_update_device(dev);
+	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
+	int nr = sattr->index;
+	return sprintf(buf, "%d\n", (int)data->temp_type[nr]);
+}
+
+static ssize_t
+store_temp_type(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct nct6775_data *data = nct6775_update_device(dev);
+	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
+	int nr = sattr->index;
+	unsigned long val;
+	int err;
+	u8 vbat, diode, bit;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err < 0)
+		return err;
+
+	if (val != 1 && val != 3 && val != 4)
+		return -EINVAL;
+
+	mutex_lock(&data->update_lock);
+
+	data->temp_type[nr] = val;
+	vbat = nct6775_read_value(data, data->REG_VBAT) & ~(0x02 << nr);
+	diode = nct6775_read_value(data, data->REG_DIODE) & ~(0x02 << nr);
+	bit = 0x02 << nr;
+	switch (val) {
+	case 1:	/* CPU diode (diode, current mode) */
+		vbat |= bit;
+		diode |= bit;
+		break;
+	case 3: /* diode, voltage mode */
+		vbat |= bit;
+		break;
+	case 4:	/* thermistor */
+		break;
+	}
+	nct6775_write_value(data, data->REG_VBAT, vbat);
+	nct6775_write_value(data, data->REG_DIODE, diode);
+
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static struct sensor_device_attribute_2 sda_temp_input[] = {
+	SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 0),
+	SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 1, 0),
+	SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 2, 0),
+	SENSOR_ATTR_2(temp4_input, S_IRUGO, show_temp, NULL, 3, 0),
+	SENSOR_ATTR_2(temp5_input, S_IRUGO, show_temp, NULL, 4, 0),
+	SENSOR_ATTR_2(temp6_input, S_IRUGO, show_temp, NULL, 5, 0),
+	SENSOR_ATTR_2(temp7_input, S_IRUGO, show_temp, NULL, 6, 0),
+	SENSOR_ATTR_2(temp8_input, S_IRUGO, show_temp, NULL, 7, 0),
+	SENSOR_ATTR_2(temp9_input, S_IRUGO, show_temp, NULL, 8, 0),
+	SENSOR_ATTR_2(temp10_input, S_IRUGO, show_temp, NULL, 9, 0),
+};
+
+static struct sensor_device_attribute sda_temp_label[] = {
+	SENSOR_ATTR(temp1_label, S_IRUGO, show_temp_label, NULL, 0),
+	SENSOR_ATTR(temp2_label, S_IRUGO, show_temp_label, NULL, 1),
+	SENSOR_ATTR(temp3_label, S_IRUGO, show_temp_label, NULL, 2),
+	SENSOR_ATTR(temp4_label, S_IRUGO, show_temp_label, NULL, 3),
+	SENSOR_ATTR(temp5_label, S_IRUGO, show_temp_label, NULL, 4),
+	SENSOR_ATTR(temp6_label, S_IRUGO, show_temp_label, NULL, 5),
+	SENSOR_ATTR(temp7_label, S_IRUGO, show_temp_label, NULL, 6),
+	SENSOR_ATTR(temp8_label, S_IRUGO, show_temp_label, NULL, 7),
+	SENSOR_ATTR(temp9_label, S_IRUGO, show_temp_label, NULL, 8),
+	SENSOR_ATTR(temp10_label, S_IRUGO, show_temp_label, NULL, 9),
+};
+
+static struct sensor_device_attribute_2 sda_temp_max[] = {
+	SENSOR_ATTR_2(temp1_max, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      0, 1),
+	SENSOR_ATTR_2(temp2_max, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      1, 1),
+	SENSOR_ATTR_2(temp3_max, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      2, 1),
+	SENSOR_ATTR_2(temp4_max, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      3, 1),
+	SENSOR_ATTR_2(temp5_max, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      4, 1),
+	SENSOR_ATTR_2(temp6_max, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      5, 1),
+	SENSOR_ATTR_2(temp7_max, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      6, 1),
+	SENSOR_ATTR_2(temp8_max, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      7, 1),
+	SENSOR_ATTR_2(temp9_max, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      8, 1),
+	SENSOR_ATTR_2(temp10_max, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      9, 1),
+};
+
+static struct sensor_device_attribute_2 sda_temp_max_hyst[] = {
+	SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      0, 2),
+	SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      1, 2),
+	SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      2, 2),
+	SENSOR_ATTR_2(temp4_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      3, 2),
+	SENSOR_ATTR_2(temp5_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      4, 2),
+	SENSOR_ATTR_2(temp6_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      5, 2),
+	SENSOR_ATTR_2(temp7_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      6, 2),
+	SENSOR_ATTR_2(temp8_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      7, 2),
+	SENSOR_ATTR_2(temp9_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      8, 2),
+	SENSOR_ATTR_2(temp10_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      9, 2),
+};
+
+static struct sensor_device_attribute_2 sda_temp_crit[] = {
+	SENSOR_ATTR_2(temp1_crit, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      0, 3),
+	SENSOR_ATTR_2(temp2_crit, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      1, 3),
+	SENSOR_ATTR_2(temp3_crit, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      2, 3),
+	SENSOR_ATTR_2(temp4_crit, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      3, 3),
+	SENSOR_ATTR_2(temp5_crit, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      4, 3),
+	SENSOR_ATTR_2(temp6_crit, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      5, 3),
+	SENSOR_ATTR_2(temp7_crit, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      6, 3),
+	SENSOR_ATTR_2(temp8_crit, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      7, 3),
+	SENSOR_ATTR_2(temp9_crit, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      8, 3),
+	SENSOR_ATTR_2(temp10_crit, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      9, 3),
+};
+
+static struct sensor_device_attribute sda_temp_offset[] = {
+	SENSOR_ATTR(temp1_offset, S_IRUGO | S_IWUSR, show_temp_offset,
+		    store_temp_offset, 0),
+	SENSOR_ATTR(temp2_offset, S_IRUGO | S_IWUSR, show_temp_offset,
+		    store_temp_offset, 1),
+	SENSOR_ATTR(temp3_offset, S_IRUGO | S_IWUSR, show_temp_offset,
+		    store_temp_offset, 2),
+	SENSOR_ATTR(temp4_offset, S_IRUGO | S_IWUSR, show_temp_offset,
+		    store_temp_offset, 3),
+	SENSOR_ATTR(temp5_offset, S_IRUGO | S_IWUSR, show_temp_offset,
+		    store_temp_offset, 4),
+	SENSOR_ATTR(temp6_offset, S_IRUGO | S_IWUSR, show_temp_offset,
+		    store_temp_offset, 5),
+};
+
+static struct sensor_device_attribute sda_temp_type[] = {
+	SENSOR_ATTR(temp1_type, S_IRUGO | S_IWUSR, show_temp_type,
+		    store_temp_type, 0),
+	SENSOR_ATTR(temp2_type, S_IRUGO | S_IWUSR, show_temp_type,
+		    store_temp_type, 1),
+	SENSOR_ATTR(temp3_type, S_IRUGO | S_IWUSR, show_temp_type,
+		    store_temp_type, 2),
+	SENSOR_ATTR(temp4_type, S_IRUGO | S_IWUSR, show_temp_type,
+		    store_temp_type, 3),
+	SENSOR_ATTR(temp5_type, S_IRUGO | S_IWUSR, show_temp_type,
+		    store_temp_type, 4),
+	SENSOR_ATTR(temp6_type, S_IRUGO | S_IWUSR, show_temp_type,
+		    store_temp_type, 5),
+};
+
+static struct sensor_device_attribute sda_temp_alarm[] = {
+	SENSOR_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL,
+		    TEMP_ALARM_BASE),
+	SENSOR_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL,
+		    TEMP_ALARM_BASE + 1),
+	SENSOR_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL,
+		    TEMP_ALARM_BASE + 2),
+	SENSOR_ATTR(temp4_alarm, S_IRUGO, show_alarm, NULL,
+		    TEMP_ALARM_BASE + 3),
+	SENSOR_ATTR(temp5_alarm, S_IRUGO, show_alarm, NULL,
+		    TEMP_ALARM_BASE + 4),
+	SENSOR_ATTR(temp6_alarm, S_IRUGO, show_alarm, NULL,
+		    TEMP_ALARM_BASE + 5),
+};
+
+#define NUM_TEMP_ALARM	ARRAY_SIZE(sda_temp_alarm)
+
+static ssize_t
+show_pwm_mode(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct nct6775_data *data = nct6775_update_device(dev);
+	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
+
+	return sprintf(buf, "%d\n", !data->pwm_mode[sattr->index]);
+}
+
+static ssize_t
+store_pwm_mode(struct device *dev, struct device_attribute *attr,
+	       const char *buf, size_t count)
+{
+	struct nct6775_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
+	int nr = sattr->index;
+	unsigned long val;
+	int err;
+	u8 reg;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err < 0)
+		return err;
+
+	if (val > 1)
+		return -EINVAL;
+
+	/* Setting DC mode is not supported for all chips/channels */
+	if (data->REG_PWM_MODE[nr] == 0) {
+		if (val)
+			return -EINVAL;
+		return count;
+	}
+
+	mutex_lock(&data->update_lock);
+	data->pwm_mode[nr] = val;
+	reg = nct6775_read_value(data, data->REG_PWM_MODE[nr]);
+	reg &= ~data->PWM_MODE_MASK[nr];
+	if (val)
+		reg |= data->PWM_MODE_MASK[nr];
+	nct6775_write_value(data, data->REG_PWM_MODE[nr], reg);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static ssize_t
+show_pwm(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct nct6775_data *data = nct6775_update_device(dev);
+	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+	int nr = sattr->nr;
+	int index = sattr->index;
+	int pwm;
+
+	/*
+	 * For automatic fan control modes, show current pwm readings.
+	 * Otherwise, show the configured value.
+	 */
+	if (index == 0 && data->pwm_enable[nr] > manual)
+		pwm = nct6775_read_value(data, data->REG_PWM_READ[nr]);
+	else
+		pwm = data->pwm[index][nr];
+
+	return sprintf(buf, "%d\n", pwm);
+}
+
+static ssize_t
+store_pwm(struct device *dev, struct device_attribute *attr, const char *buf,
+	  size_t count)
+{
+	struct nct6775_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+	int nr = sattr->nr;
+	int index = sattr->index;
+	unsigned long val;
+	int minval[7] = { 0, 1, 1, data->pwm[2][nr], 0, 0, 0 };
+	int maxval[7]
+	  = { 255, 255, data->pwm[3][nr] ? : 255, 255, 255, 255, 255 };
+	int err;
+	u8 reg;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err < 0)
+		return err;
+	val = clamp_val(val, minval[index], maxval[index]);
+
+	mutex_lock(&data->update_lock);
+	data->pwm[index][nr] = val;
+	nct6775_write_value(data, data->REG_PWM[index][nr], val);
+	if (index == 2)	{ /* floor: disable if val == 0 */
+		reg = nct6775_read_value(data, data->REG_TEMP_SEL[nr]);
+		reg &= 0x7f;
+		if (val)
+			reg |= 0x80;
+		nct6775_write_value(data, data->REG_TEMP_SEL[nr], reg);
+	}
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+/* Returns 0 if OK, -EINVAL otherwise */
+static int check_trip_points(struct nct6775_data *data, int nr)
+{
+	int i;
+
+	for (i = 0; i < data->auto_pwm_num - 1; i++) {
+		if (data->auto_temp[nr][i] > data->auto_temp[nr][i + 1])
+			return -EINVAL;
+	}
+	for (i = 0; i < data->auto_pwm_num - 1; i++) {
+		if (data->auto_pwm[nr][i] > data->auto_pwm[nr][i + 1])
+			return -EINVAL;
+	}
+	/* validate critical temperature and pwm if enabled (pwm > 0) */
+	if (data->auto_pwm[nr][data->auto_pwm_num]) {
+		if (data->auto_temp[nr][data->auto_pwm_num - 1] >
+				data->auto_temp[nr][data->auto_pwm_num] ||
+		    data->auto_pwm[nr][data->auto_pwm_num - 1] >
+				data->auto_pwm[nr][data->auto_pwm_num])
+			return -EINVAL;
+	}
+	return 0;
+}
+
+static void pwm_update_registers(struct nct6775_data *data, int nr)
+{
+	u8 reg;
+
+	switch (data->pwm_enable[nr]) {
+	case off:
+	case manual:
+		break;
+	case speed_cruise:
+		reg = nct6775_read_value(data, data->REG_FAN_MODE[nr]);
+		reg = (reg & ~data->tolerance_mask) |
+		  (data->target_speed_tolerance[nr] & data->tolerance_mask);
+		nct6775_write_value(data, data->REG_FAN_MODE[nr], reg);
+		nct6775_write_value(data, data->REG_TARGET[nr],
+				    data->target_speed[nr] & 0xff);
+		if (data->REG_TOLERANCE_H) {
+			reg = (data->target_speed[nr] >> 8) & 0x0f;
+			reg |= (data->target_speed_tolerance[nr] & 0x38) << 1;
+			nct6775_write_value(data,
+					    data->REG_TOLERANCE_H[nr],
+					    reg);
+		}
+		break;
+	case thermal_cruise:
+		nct6775_write_value(data, data->REG_TARGET[nr],
+				    data->target_temp[nr]);
+		/* intentional */
+	default:
+		reg = nct6775_read_value(data, data->REG_FAN_MODE[nr]);
+		reg = (reg & ~data->tolerance_mask) |
+		  data->temp_tolerance[0][nr];
+		nct6775_write_value(data, data->REG_FAN_MODE[nr], reg);
+		break;
+	}
+}
+
+static ssize_t
+show_pwm_enable(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct nct6775_data *data = nct6775_update_device(dev);
+	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
+
+	return sprintf(buf, "%d\n", data->pwm_enable[sattr->index]);
+}
+
+static ssize_t
+store_pwm_enable(struct device *dev, struct device_attribute *attr,
+		 const char *buf, size_t count)
+{
+	struct nct6775_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
+	int nr = sattr->index;
+	unsigned long val;
+	int err;
+	u16 reg;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err < 0)
+		return err;
+
+	if (val > sf4)
+		return -EINVAL;
+
+	if (val == sf3 && data->kind != nct6775)
+		return -EINVAL;
+
+	if (val == sf4 && check_trip_points(data, nr)) {
+		dev_err(dev, "Inconsistent trip points, not switching to SmartFan IV mode\n");
+		dev_err(dev, "Adjust trip points and try again\n");
+		return -EINVAL;
+	}
+
+	mutex_lock(&data->update_lock);
+	data->pwm_enable[nr] = val;
+	if (val == off) {
+		/*
+		 * turn off pwm control: select manual mode, set pwm to maximum
+		 */
+		data->pwm[0][nr] = 255;
+		nct6775_write_value(data, data->REG_PWM[0][nr], 255);
+	}
+	pwm_update_registers(data, nr);
+	reg = nct6775_read_value(data, data->REG_FAN_MODE[nr]);
+	reg &= 0x0f;
+	reg |= pwm_enable_to_reg(val) << 4;
+	nct6775_write_value(data, data->REG_FAN_MODE[nr], reg);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static ssize_t
+show_pwm_temp_sel_common(struct nct6775_data *data, char *buf, int src)
+{
+	int i, sel = 0;
+
+	for (i = 0; i < NUM_TEMP; i++) {
+		if (!(data->have_temp & (1 << i)))
+			continue;
+		if (src == data->temp_src[i]) {
+			sel = i + 1;
+			break;
+		}
+	}
+
+	return sprintf(buf, "%d\n", sel);
+}
+
+static ssize_t
+show_pwm_temp_sel(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct nct6775_data *data = nct6775_update_device(dev);
+	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
+	int index = sattr->index;
+
+	return show_pwm_temp_sel_common(data, buf, data->pwm_temp_sel[index]);
+}
+
+static ssize_t
+store_pwm_temp_sel(struct device *dev, struct device_attribute *attr,
+		   const char *buf, size_t count)
+{
+	struct nct6775_data *data = nct6775_update_device(dev);
+	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
+	int nr = sattr->index;
+	unsigned long val;
+	int err, reg, src;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err < 0)
+		return err;
+	if (val == 0 || val > NUM_TEMP)
+		return -EINVAL;
+	if (!(data->have_temp & (1 << (val - 1))) || !data->temp_src[val - 1])
+		return -EINVAL;
+
+	mutex_lock(&data->update_lock);
+	src = data->temp_src[val - 1];
+	data->pwm_temp_sel[nr] = src;
+	reg = nct6775_read_value(data, data->REG_TEMP_SEL[nr]);
+	reg &= 0xe0;
+	reg |= src;
+	nct6775_write_value(data, data->REG_TEMP_SEL[nr], reg);
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+static ssize_t
+show_pwm_weight_temp_sel(struct device *dev, struct device_attribute *attr,
+			 char *buf)
+{
+	struct nct6775_data *data = nct6775_update_device(dev);
+	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
+	int index = sattr->index;
+
+	return show_pwm_temp_sel_common(data, buf,
+					data->pwm_weight_temp_sel[index]);
+}
+
+static ssize_t
+store_pwm_weight_temp_sel(struct device *dev, struct device_attribute *attr,
+			  const char *buf, size_t count)
+{
+	struct nct6775_data *data = nct6775_update_device(dev);
+	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
+	int nr = sattr->index;
+	unsigned long val;
+	int err, reg, src;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err < 0)
+		return err;
+	if (val > NUM_TEMP)
+		return -EINVAL;
+	if (val && (!(data->have_temp & (1 << (val - 1))) ||
+		    !data->temp_src[val - 1]))
+		return -EINVAL;
+
+	mutex_lock(&data->update_lock);
+	if (val) {
+		src = data->temp_src[val - 1];
+		data->pwm_weight_temp_sel[nr] = src;
+		reg = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[nr]);
+		reg &= 0xe0;
+		reg |= (src | 0x80);
+		nct6775_write_value(data, data->REG_WEIGHT_TEMP_SEL[nr], reg);
+	} else {
+		data->pwm_weight_temp_sel[nr] = 0;
+		reg = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[nr]);
+		reg &= 0x7f;
+		nct6775_write_value(data, data->REG_WEIGHT_TEMP_SEL[nr], reg);
+	}
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+static ssize_t
+show_target_temp(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct nct6775_data *data = nct6775_update_device(dev);
+	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
+
+	return sprintf(buf, "%d\n", data->target_temp[sattr->index] * 1000);
+}
+
+static ssize_t
+store_target_temp(struct device *dev, struct device_attribute *attr,
+		  const char *buf, size_t count)
+{
+	struct nct6775_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
+	int nr = sattr->index;
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err < 0)
+		return err;
+
+	val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0,
+			data->target_temp_mask);
+
+	mutex_lock(&data->update_lock);
+	data->target_temp[nr] = val;
+	pwm_update_registers(data, nr);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static ssize_t
+show_target_speed(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct nct6775_data *data = nct6775_update_device(dev);
+	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
+	int nr = sattr->index;
+
+	return sprintf(buf, "%d\n",
+		       fan_from_reg16(data->target_speed[nr],
+				      data->fan_div[nr]));
+}
+
+static ssize_t
+store_target_speed(struct device *dev, struct device_attribute *attr,
+		   const char *buf, size_t count)
+{
+	struct nct6775_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
+	int nr = sattr->index;
+	unsigned long val;
+	int err;
+	u16 speed;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err < 0)
+		return err;
+
+	val = clamp_val(val, 0, 1350000U);
+	speed = fan_to_reg(val, data->fan_div[nr]);
+
+	mutex_lock(&data->update_lock);
+	data->target_speed[nr] = speed;
+	pwm_update_registers(data, nr);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static ssize_t
+show_temp_tolerance(struct device *dev, struct device_attribute *attr,
+		    char *buf)
+{
+	struct nct6775_data *data = nct6775_update_device(dev);
+	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+	int nr = sattr->nr;
+	int index = sattr->index;
+
+	return sprintf(buf, "%d\n", data->temp_tolerance[index][nr] * 1000);
+}
+
+static ssize_t
+store_temp_tolerance(struct device *dev, struct device_attribute *attr,
+		     const char *buf, size_t count)
+{
+	struct nct6775_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+	int nr = sattr->nr;
+	int index = sattr->index;
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err < 0)
+		return err;
+
+	/* Limit tolerance as needed */
+	val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, data->tolerance_mask);
+
+	mutex_lock(&data->update_lock);
+	data->temp_tolerance[index][nr] = val;
+	if (index)
+		pwm_update_registers(data, nr);
+	else
+		nct6775_write_value(data,
+				    data->REG_CRITICAL_TEMP_TOLERANCE[nr],
+				    val);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+/*
+ * Fan speed tolerance is a tricky beast, since the associated register is
+ * a tick counter, but the value is reported and configured as rpm.
+ * Compute resulting low and high rpm values and report the difference.
+ */
+static ssize_t
+show_speed_tolerance(struct device *dev, struct device_attribute *attr,
+		     char *buf)
+{
+	struct nct6775_data *data = nct6775_update_device(dev);
+	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
+	int nr = sattr->index;
+	int low = data->target_speed[nr] - data->target_speed_tolerance[nr];
+	int high = data->target_speed[nr] + data->target_speed_tolerance[nr];
+	int tolerance;
+
+	if (low <= 0)
+		low = 1;
+	if (high > 0xffff)
+		high = 0xffff;
+	if (high < low)
+		high = low;
+
+	tolerance = (fan_from_reg16(low, data->fan_div[nr])
+		     - fan_from_reg16(high, data->fan_div[nr])) / 2;
+
+	return sprintf(buf, "%d\n", tolerance);
+}
+
+static ssize_t
+store_speed_tolerance(struct device *dev, struct device_attribute *attr,
+		      const char *buf, size_t count)
+{
+	struct nct6775_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
+	int nr = sattr->index;
+	unsigned long val;
+	int err;
+	int low, high;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err < 0)
+		return err;
+
+	high = fan_from_reg16(data->target_speed[nr],
+			      data->fan_div[nr]) + val;
+	low = fan_from_reg16(data->target_speed[nr],
+			     data->fan_div[nr]) - val;
+	if (low <= 0)
+		low = 1;
+	if (high < low)
+		high = low;
+
+	val = (fan_to_reg(low, data->fan_div[nr]) -
+	       fan_to_reg(high, data->fan_div[nr])) / 2;
+
+	/* Limit tolerance as needed */
+	val = clamp_val(val, 0, data->speed_tolerance_limit);
+
+	mutex_lock(&data->update_lock);
+	data->target_speed_tolerance[nr] = val;
+	pwm_update_registers(data, nr);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static SENSOR_DEVICE_ATTR_2(pwm1, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0, 0);
+static SENSOR_DEVICE_ATTR_2(pwm2, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 1, 0);
+static SENSOR_DEVICE_ATTR_2(pwm3, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 2, 0);
+static SENSOR_DEVICE_ATTR_2(pwm4, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 3, 0);
+static SENSOR_DEVICE_ATTR_2(pwm5, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 4, 0);
+
+static SENSOR_DEVICE_ATTR(pwm1_mode, S_IWUSR | S_IRUGO, show_pwm_mode,
+			  store_pwm_mode, 0);
+static SENSOR_DEVICE_ATTR(pwm2_mode, S_IWUSR | S_IRUGO, show_pwm_mode,
+			  store_pwm_mode, 1);
+static SENSOR_DEVICE_ATTR(pwm3_mode, S_IWUSR | S_IRUGO, show_pwm_mode,
+			  store_pwm_mode, 2);
+static SENSOR_DEVICE_ATTR(pwm4_mode, S_IWUSR | S_IRUGO, show_pwm_mode,
+			  store_pwm_mode, 3);
+static SENSOR_DEVICE_ATTR(pwm5_mode, S_IWUSR | S_IRUGO, show_pwm_mode,
+			  store_pwm_mode, 4);
+
+static SENSOR_DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, show_pwm_enable,
+			  store_pwm_enable, 0);
+static SENSOR_DEVICE_ATTR(pwm2_enable, S_IWUSR | S_IRUGO, show_pwm_enable,
+			  store_pwm_enable, 1);
+static SENSOR_DEVICE_ATTR(pwm3_enable, S_IWUSR | S_IRUGO, show_pwm_enable,
+			  store_pwm_enable, 2);
+static SENSOR_DEVICE_ATTR(pwm4_enable, S_IWUSR | S_IRUGO, show_pwm_enable,
+			  store_pwm_enable, 3);
+static SENSOR_DEVICE_ATTR(pwm5_enable, S_IWUSR | S_IRUGO, show_pwm_enable,
+			  store_pwm_enable, 4);
+
+static SENSOR_DEVICE_ATTR(pwm1_temp_sel, S_IWUSR | S_IRUGO,
+			    show_pwm_temp_sel, store_pwm_temp_sel, 0);
+static SENSOR_DEVICE_ATTR(pwm2_temp_sel, S_IWUSR | S_IRUGO,
+			    show_pwm_temp_sel, store_pwm_temp_sel, 1);
+static SENSOR_DEVICE_ATTR(pwm3_temp_sel, S_IWUSR | S_IRUGO,
+			    show_pwm_temp_sel, store_pwm_temp_sel, 2);
+static SENSOR_DEVICE_ATTR(pwm4_temp_sel, S_IWUSR | S_IRUGO,
+			    show_pwm_temp_sel, store_pwm_temp_sel, 3);
+static SENSOR_DEVICE_ATTR(pwm5_temp_sel, S_IWUSR | S_IRUGO,
+			    show_pwm_temp_sel, store_pwm_temp_sel, 4);
+
+static SENSOR_DEVICE_ATTR(pwm1_target_temp, S_IWUSR | S_IRUGO, show_target_temp,
+			  store_target_temp, 0);
+static SENSOR_DEVICE_ATTR(pwm2_target_temp, S_IWUSR | S_IRUGO, show_target_temp,
+			  store_target_temp, 1);
+static SENSOR_DEVICE_ATTR(pwm3_target_temp, S_IWUSR | S_IRUGO, show_target_temp,
+			  store_target_temp, 2);
+static SENSOR_DEVICE_ATTR(pwm4_target_temp, S_IWUSR | S_IRUGO, show_target_temp,
+			  store_target_temp, 3);
+static SENSOR_DEVICE_ATTR(pwm5_target_temp, S_IWUSR | S_IRUGO, show_target_temp,
+			  store_target_temp, 4);
+
+static SENSOR_DEVICE_ATTR(fan1_target, S_IWUSR | S_IRUGO, show_target_speed,
+			  store_target_speed, 0);
+static SENSOR_DEVICE_ATTR(fan2_target, S_IWUSR | S_IRUGO, show_target_speed,
+			  store_target_speed, 1);
+static SENSOR_DEVICE_ATTR(fan3_target, S_IWUSR | S_IRUGO, show_target_speed,
+			  store_target_speed, 2);
+static SENSOR_DEVICE_ATTR(fan4_target, S_IWUSR | S_IRUGO, show_target_speed,
+			  store_target_speed, 3);
+static SENSOR_DEVICE_ATTR(fan5_target, S_IWUSR | S_IRUGO, show_target_speed,
+			  store_target_speed, 4);
+
+static SENSOR_DEVICE_ATTR(fan1_tolerance, S_IWUSR | S_IRUGO,
+			    show_speed_tolerance, store_speed_tolerance, 0);
+static SENSOR_DEVICE_ATTR(fan2_tolerance, S_IWUSR | S_IRUGO,
+			    show_speed_tolerance, store_speed_tolerance, 1);
+static SENSOR_DEVICE_ATTR(fan3_tolerance, S_IWUSR | S_IRUGO,
+			    show_speed_tolerance, store_speed_tolerance, 2);
+static SENSOR_DEVICE_ATTR(fan4_tolerance, S_IWUSR | S_IRUGO,
+			    show_speed_tolerance, store_speed_tolerance, 3);
+static SENSOR_DEVICE_ATTR(fan5_tolerance, S_IWUSR | S_IRUGO,
+			    show_speed_tolerance, store_speed_tolerance, 4);
+
+/* Smart Fan registers */
+
+static ssize_t
+show_weight_temp(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct nct6775_data *data = nct6775_update_device(dev);
+	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+	int nr = sattr->nr;
+	int index = sattr->index;
+
+	return sprintf(buf, "%d\n", data->weight_temp[index][nr] * 1000);
+}
+
+static ssize_t
+store_weight_temp(struct device *dev, struct device_attribute *attr,
+		  const char *buf, size_t count)
+{
+	struct nct6775_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+	int nr = sattr->nr;
+	int index = sattr->index;
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err < 0)
+		return err;
+
+	val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, 255);
+
+	mutex_lock(&data->update_lock);
+	data->weight_temp[index][nr] = val;
+	nct6775_write_value(data, data->REG_WEIGHT_TEMP[index][nr], val);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static SENSOR_DEVICE_ATTR(pwm1_weight_temp_sel, S_IWUSR | S_IRUGO,
+			    show_pwm_weight_temp_sel, store_pwm_weight_temp_sel,
+			    0);
+static SENSOR_DEVICE_ATTR(pwm2_weight_temp_sel, S_IWUSR | S_IRUGO,
+			    show_pwm_weight_temp_sel, store_pwm_weight_temp_sel,
+			    1);
+static SENSOR_DEVICE_ATTR(pwm3_weight_temp_sel, S_IWUSR | S_IRUGO,
+			    show_pwm_weight_temp_sel, store_pwm_weight_temp_sel,
+			    2);
+static SENSOR_DEVICE_ATTR(pwm4_weight_temp_sel, S_IWUSR | S_IRUGO,
+			    show_pwm_weight_temp_sel, store_pwm_weight_temp_sel,
+			    3);
+static SENSOR_DEVICE_ATTR(pwm5_weight_temp_sel, S_IWUSR | S_IRUGO,
+			    show_pwm_weight_temp_sel, store_pwm_weight_temp_sel,
+			    4);
+
+static SENSOR_DEVICE_ATTR_2(pwm1_weight_temp_step, S_IWUSR | S_IRUGO,
+			    show_weight_temp, store_weight_temp, 0, 0);
+static SENSOR_DEVICE_ATTR_2(pwm2_weight_temp_step, S_IWUSR | S_IRUGO,
+			    show_weight_temp, store_weight_temp, 1, 0);
+static SENSOR_DEVICE_ATTR_2(pwm3_weight_temp_step, S_IWUSR | S_IRUGO,
+			    show_weight_temp, store_weight_temp, 2, 0);
+static SENSOR_DEVICE_ATTR_2(pwm4_weight_temp_step, S_IWUSR | S_IRUGO,
+			    show_weight_temp, store_weight_temp, 3, 0);
+static SENSOR_DEVICE_ATTR_2(pwm5_weight_temp_step, S_IWUSR | S_IRUGO,
+			    show_weight_temp, store_weight_temp, 4, 0);
+
+static SENSOR_DEVICE_ATTR_2(pwm1_weight_temp_step_tol, S_IWUSR | S_IRUGO,
+			    show_weight_temp, store_weight_temp, 0, 1);
+static SENSOR_DEVICE_ATTR_2(pwm2_weight_temp_step_tol, S_IWUSR | S_IRUGO,
+			    show_weight_temp, store_weight_temp, 1, 1);
+static SENSOR_DEVICE_ATTR_2(pwm3_weight_temp_step_tol, S_IWUSR | S_IRUGO,
+			    show_weight_temp, store_weight_temp, 2, 1);
+static SENSOR_DEVICE_ATTR_2(pwm4_weight_temp_step_tol, S_IWUSR | S_IRUGO,
+			    show_weight_temp, store_weight_temp, 3, 1);
+static SENSOR_DEVICE_ATTR_2(pwm5_weight_temp_step_tol, S_IWUSR | S_IRUGO,
+			    show_weight_temp, store_weight_temp, 4, 1);
+
+static SENSOR_DEVICE_ATTR_2(pwm1_weight_temp_step_base, S_IWUSR | S_IRUGO,
+			    show_weight_temp, store_weight_temp, 0, 2);
+static SENSOR_DEVICE_ATTR_2(pwm2_weight_temp_step_base, S_IWUSR | S_IRUGO,
+			    show_weight_temp, store_weight_temp, 1, 2);
+static SENSOR_DEVICE_ATTR_2(pwm3_weight_temp_step_base, S_IWUSR | S_IRUGO,
+			    show_weight_temp, store_weight_temp, 2, 2);
+static SENSOR_DEVICE_ATTR_2(pwm4_weight_temp_step_base, S_IWUSR | S_IRUGO,
+			    show_weight_temp, store_weight_temp, 3, 2);
+static SENSOR_DEVICE_ATTR_2(pwm5_weight_temp_step_base, S_IWUSR | S_IRUGO,
+			    show_weight_temp, store_weight_temp, 4, 2);
+
+static SENSOR_DEVICE_ATTR_2(pwm1_weight_duty_step, S_IWUSR | S_IRUGO,
+			    show_pwm, store_pwm, 0, 5);
+static SENSOR_DEVICE_ATTR_2(pwm2_weight_duty_step, S_IWUSR | S_IRUGO,
+			    show_pwm, store_pwm, 1, 5);
+static SENSOR_DEVICE_ATTR_2(pwm3_weight_duty_step, S_IWUSR | S_IRUGO,
+			    show_pwm, store_pwm, 2, 5);
+static SENSOR_DEVICE_ATTR_2(pwm4_weight_duty_step, S_IWUSR | S_IRUGO,
+			    show_pwm, store_pwm, 3, 5);
+static SENSOR_DEVICE_ATTR_2(pwm5_weight_duty_step, S_IWUSR | S_IRUGO,
+			    show_pwm, store_pwm, 4, 5);
+
+/* duty_base is not supported on all chips */
+static struct sensor_device_attribute_2 sda_weight_duty_base[] = {
+	SENSOR_ATTR_2(pwm1_weight_duty_base, S_IWUSR | S_IRUGO,
+		      show_pwm, store_pwm, 0, 6),
+	SENSOR_ATTR_2(pwm2_weight_duty_base, S_IWUSR | S_IRUGO,
+		      show_pwm, store_pwm, 1, 6),
+	SENSOR_ATTR_2(pwm3_weight_duty_base, S_IWUSR | S_IRUGO,
+		      show_pwm, store_pwm, 2, 6),
+	SENSOR_ATTR_2(pwm4_weight_duty_base, S_IWUSR | S_IRUGO,
+		      show_pwm, store_pwm, 3, 6),
+	SENSOR_ATTR_2(pwm5_weight_duty_base, S_IWUSR | S_IRUGO,
+		      show_pwm, store_pwm, 4, 6),
+};
+
+static ssize_t
+show_fan_time(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct nct6775_data *data = nct6775_update_device(dev);
+	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+	int nr = sattr->nr;
+	int index = sattr->index;
+
+	return sprintf(buf, "%d\n",
+		       step_time_from_reg(data->fan_time[index][nr],
+					  data->pwm_mode[nr]));
+}
+
+static ssize_t
+store_fan_time(struct device *dev, struct device_attribute *attr,
+	       const char *buf, size_t count)
+{
+	struct nct6775_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+	int nr = sattr->nr;
+	int index = sattr->index;
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err < 0)
+		return err;
+
+	val = step_time_to_reg(val, data->pwm_mode[nr]);
+	mutex_lock(&data->update_lock);
+	data->fan_time[index][nr] = val;
+	nct6775_write_value(data, data->REG_FAN_TIME[index][nr], val);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static ssize_t
+show_name(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct nct6775_data *data = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%s\n", data->name);
+}
+
+static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
+
+static SENSOR_DEVICE_ATTR_2(pwm1_stop_time, S_IWUSR | S_IRUGO, show_fan_time,
+			    store_fan_time, 0, 0);
+static SENSOR_DEVICE_ATTR_2(pwm2_stop_time, S_IWUSR | S_IRUGO, show_fan_time,
+			    store_fan_time, 1, 0);
+static SENSOR_DEVICE_ATTR_2(pwm3_stop_time, S_IWUSR | S_IRUGO, show_fan_time,
+			    store_fan_time, 2, 0);
+static SENSOR_DEVICE_ATTR_2(pwm4_stop_time, S_IWUSR | S_IRUGO, show_fan_time,
+			    store_fan_time, 3, 0);
+static SENSOR_DEVICE_ATTR_2(pwm5_stop_time, S_IWUSR | S_IRUGO, show_fan_time,
+			    store_fan_time, 4, 0);
+
+static SENSOR_DEVICE_ATTR_2(pwm1_step_up_time, S_IWUSR | S_IRUGO, show_fan_time,
+			    store_fan_time, 0, 1);
+static SENSOR_DEVICE_ATTR_2(pwm2_step_up_time, S_IWUSR | S_IRUGO, show_fan_time,
+			    store_fan_time, 1, 1);
+static SENSOR_DEVICE_ATTR_2(pwm3_step_up_time, S_IWUSR | S_IRUGO, show_fan_time,
+			    store_fan_time, 2, 1);
+static SENSOR_DEVICE_ATTR_2(pwm4_step_up_time, S_IWUSR | S_IRUGO, show_fan_time,
+			    store_fan_time, 3, 1);
+static SENSOR_DEVICE_ATTR_2(pwm5_step_up_time, S_IWUSR | S_IRUGO, show_fan_time,
+			    store_fan_time, 4, 1);
+
+static SENSOR_DEVICE_ATTR_2(pwm1_step_down_time, S_IWUSR | S_IRUGO,
+			    show_fan_time, store_fan_time, 0, 2);
+static SENSOR_DEVICE_ATTR_2(pwm2_step_down_time, S_IWUSR | S_IRUGO,
+			    show_fan_time, store_fan_time, 1, 2);
+static SENSOR_DEVICE_ATTR_2(pwm3_step_down_time, S_IWUSR | S_IRUGO,
+			    show_fan_time, store_fan_time, 2, 2);
+static SENSOR_DEVICE_ATTR_2(pwm4_step_down_time, S_IWUSR | S_IRUGO,
+			    show_fan_time, store_fan_time, 3, 2);
+static SENSOR_DEVICE_ATTR_2(pwm5_step_down_time, S_IWUSR | S_IRUGO,
+			    show_fan_time, store_fan_time, 4, 2);
+
+static SENSOR_DEVICE_ATTR_2(pwm1_start, S_IWUSR | S_IRUGO, show_pwm,
+			    store_pwm, 0, 1);
+static SENSOR_DEVICE_ATTR_2(pwm2_start, S_IWUSR | S_IRUGO, show_pwm,
+			    store_pwm, 1, 1);
+static SENSOR_DEVICE_ATTR_2(pwm3_start, S_IWUSR | S_IRUGO, show_pwm,
+			    store_pwm, 2, 1);
+static SENSOR_DEVICE_ATTR_2(pwm4_start, S_IWUSR | S_IRUGO, show_pwm,
+			    store_pwm, 3, 1);
+static SENSOR_DEVICE_ATTR_2(pwm5_start, S_IWUSR | S_IRUGO, show_pwm,
+			    store_pwm, 4, 1);
+
+static SENSOR_DEVICE_ATTR_2(pwm1_floor, S_IWUSR | S_IRUGO, show_pwm,
+			    store_pwm, 0, 2);
+static SENSOR_DEVICE_ATTR_2(pwm2_floor, S_IWUSR | S_IRUGO, show_pwm,
+			    store_pwm, 1, 2);
+static SENSOR_DEVICE_ATTR_2(pwm3_floor, S_IWUSR | S_IRUGO, show_pwm,
+			    store_pwm, 2, 2);
+static SENSOR_DEVICE_ATTR_2(pwm4_floor, S_IWUSR | S_IRUGO, show_pwm,
+			    store_pwm, 3, 2);
+static SENSOR_DEVICE_ATTR_2(pwm5_floor, S_IWUSR | S_IRUGO, show_pwm,
+			    store_pwm, 4, 2);
+
+static SENSOR_DEVICE_ATTR_2(pwm1_temp_tolerance, S_IWUSR | S_IRUGO,
+			    show_temp_tolerance, store_temp_tolerance, 0, 0);
+static SENSOR_DEVICE_ATTR_2(pwm2_temp_tolerance, S_IWUSR | S_IRUGO,
+			    show_temp_tolerance, store_temp_tolerance, 1, 0);
+static SENSOR_DEVICE_ATTR_2(pwm3_temp_tolerance, S_IWUSR | S_IRUGO,
+			    show_temp_tolerance, store_temp_tolerance, 2, 0);
+static SENSOR_DEVICE_ATTR_2(pwm4_temp_tolerance, S_IWUSR | S_IRUGO,
+			    show_temp_tolerance, store_temp_tolerance, 3, 0);
+static SENSOR_DEVICE_ATTR_2(pwm5_temp_tolerance, S_IWUSR | S_IRUGO,
+			    show_temp_tolerance, store_temp_tolerance, 4, 0);
+
+static SENSOR_DEVICE_ATTR_2(pwm1_crit_temp_tolerance, S_IWUSR | S_IRUGO,
+			    show_temp_tolerance, store_temp_tolerance, 0, 1);
+static SENSOR_DEVICE_ATTR_2(pwm2_crit_temp_tolerance, S_IWUSR | S_IRUGO,
+			    show_temp_tolerance, store_temp_tolerance, 1, 1);
+static SENSOR_DEVICE_ATTR_2(pwm3_crit_temp_tolerance, S_IWUSR | S_IRUGO,
+			    show_temp_tolerance, store_temp_tolerance, 2, 1);
+static SENSOR_DEVICE_ATTR_2(pwm4_crit_temp_tolerance, S_IWUSR | S_IRUGO,
+			    show_temp_tolerance, store_temp_tolerance, 3, 1);
+static SENSOR_DEVICE_ATTR_2(pwm5_crit_temp_tolerance, S_IWUSR | S_IRUGO,
+			    show_temp_tolerance, store_temp_tolerance, 4, 1);
+
+/* pwm_max is not supported on all chips */
+static struct sensor_device_attribute_2 sda_pwm_max[] = {
+	SENSOR_ATTR_2(pwm1_max, S_IWUSR | S_IRUGO, show_pwm, store_pwm,
+		      0, 3),
+	SENSOR_ATTR_2(pwm2_max, S_IWUSR | S_IRUGO, show_pwm, store_pwm,
+		      1, 3),
+	SENSOR_ATTR_2(pwm3_max, S_IWUSR | S_IRUGO, show_pwm, store_pwm,
+		      2, 3),
+	SENSOR_ATTR_2(pwm4_max, S_IWUSR | S_IRUGO, show_pwm, store_pwm,
+		      3, 3),
+	SENSOR_ATTR_2(pwm5_max, S_IWUSR | S_IRUGO, show_pwm, store_pwm,
+		      4, 3),
+};
+
+/* pwm_step is not supported on all chips */
+static struct sensor_device_attribute_2 sda_pwm_step[] = {
+	SENSOR_ATTR_2(pwm1_step, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0, 4),
+	SENSOR_ATTR_2(pwm2_step, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 1, 4),
+	SENSOR_ATTR_2(pwm3_step, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 2, 4),
+	SENSOR_ATTR_2(pwm4_step, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 3, 4),
+	SENSOR_ATTR_2(pwm5_step, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 4, 4),
+};
+
+static struct attribute *nct6775_attributes_pwm[5][20] = {
+	{
+		&sensor_dev_attr_pwm1.dev_attr.attr,
+		&sensor_dev_attr_pwm1_mode.dev_attr.attr,
+		&sensor_dev_attr_pwm1_enable.dev_attr.attr,
+		&sensor_dev_attr_pwm1_temp_sel.dev_attr.attr,
+		&sensor_dev_attr_pwm1_temp_tolerance.dev_attr.attr,
+		&sensor_dev_attr_pwm1_crit_temp_tolerance.dev_attr.attr,
+		&sensor_dev_attr_pwm1_target_temp.dev_attr.attr,
+		&sensor_dev_attr_fan1_target.dev_attr.attr,
+		&sensor_dev_attr_fan1_tolerance.dev_attr.attr,
+		&sensor_dev_attr_pwm1_stop_time.dev_attr.attr,
+		&sensor_dev_attr_pwm1_step_up_time.dev_attr.attr,
+		&sensor_dev_attr_pwm1_step_down_time.dev_attr.attr,
+		&sensor_dev_attr_pwm1_start.dev_attr.attr,
+		&sensor_dev_attr_pwm1_floor.dev_attr.attr,
+		&sensor_dev_attr_pwm1_weight_temp_sel.dev_attr.attr,
+		&sensor_dev_attr_pwm1_weight_temp_step.dev_attr.attr,
+		&sensor_dev_attr_pwm1_weight_temp_step_tol.dev_attr.attr,
+		&sensor_dev_attr_pwm1_weight_temp_step_base.dev_attr.attr,
+		&sensor_dev_attr_pwm1_weight_duty_step.dev_attr.attr,
+		NULL
+	},
+	{
+		&sensor_dev_attr_pwm2.dev_attr.attr,
+		&sensor_dev_attr_pwm2_mode.dev_attr.attr,
+		&sensor_dev_attr_pwm2_enable.dev_attr.attr,
+		&sensor_dev_attr_pwm2_temp_sel.dev_attr.attr,
+		&sensor_dev_attr_pwm2_temp_tolerance.dev_attr.attr,
+		&sensor_dev_attr_pwm2_crit_temp_tolerance.dev_attr.attr,
+		&sensor_dev_attr_pwm2_target_temp.dev_attr.attr,
+		&sensor_dev_attr_fan2_target.dev_attr.attr,
+		&sensor_dev_attr_fan2_tolerance.dev_attr.attr,
+		&sensor_dev_attr_pwm2_stop_time.dev_attr.attr,
+		&sensor_dev_attr_pwm2_step_up_time.dev_attr.attr,
+		&sensor_dev_attr_pwm2_step_down_time.dev_attr.attr,
+		&sensor_dev_attr_pwm2_start.dev_attr.attr,
+		&sensor_dev_attr_pwm2_floor.dev_attr.attr,
+		&sensor_dev_attr_pwm2_weight_temp_sel.dev_attr.attr,
+		&sensor_dev_attr_pwm2_weight_temp_step.dev_attr.attr,
+		&sensor_dev_attr_pwm2_weight_temp_step_tol.dev_attr.attr,
+		&sensor_dev_attr_pwm2_weight_temp_step_base.dev_attr.attr,
+		&sensor_dev_attr_pwm2_weight_duty_step.dev_attr.attr,
+		NULL
+	},
+	{
+		&sensor_dev_attr_pwm3.dev_attr.attr,
+		&sensor_dev_attr_pwm3_mode.dev_attr.attr,
+		&sensor_dev_attr_pwm3_enable.dev_attr.attr,
+		&sensor_dev_attr_pwm3_temp_sel.dev_attr.attr,
+		&sensor_dev_attr_pwm3_temp_tolerance.dev_attr.attr,
+		&sensor_dev_attr_pwm3_crit_temp_tolerance.dev_attr.attr,
+		&sensor_dev_attr_pwm3_target_temp.dev_attr.attr,
+		&sensor_dev_attr_fan3_target.dev_attr.attr,
+		&sensor_dev_attr_fan3_tolerance.dev_attr.attr,
+		&sensor_dev_attr_pwm3_stop_time.dev_attr.attr,
+		&sensor_dev_attr_pwm3_step_up_time.dev_attr.attr,
+		&sensor_dev_attr_pwm3_step_down_time.dev_attr.attr,
+		&sensor_dev_attr_pwm3_start.dev_attr.attr,
+		&sensor_dev_attr_pwm3_floor.dev_attr.attr,
+		&sensor_dev_attr_pwm3_weight_temp_sel.dev_attr.attr,
+		&sensor_dev_attr_pwm3_weight_temp_step.dev_attr.attr,
+		&sensor_dev_attr_pwm3_weight_temp_step_tol.dev_attr.attr,
+		&sensor_dev_attr_pwm3_weight_temp_step_base.dev_attr.attr,
+		&sensor_dev_attr_pwm3_weight_duty_step.dev_attr.attr,
+		NULL
+	},
+	{
+		&sensor_dev_attr_pwm4.dev_attr.attr,
+		&sensor_dev_attr_pwm4_mode.dev_attr.attr,
+		&sensor_dev_attr_pwm4_enable.dev_attr.attr,
+		&sensor_dev_attr_pwm4_temp_sel.dev_attr.attr,
+		&sensor_dev_attr_pwm4_temp_tolerance.dev_attr.attr,
+		&sensor_dev_attr_pwm4_crit_temp_tolerance.dev_attr.attr,
+		&sensor_dev_attr_pwm4_target_temp.dev_attr.attr,
+		&sensor_dev_attr_fan4_target.dev_attr.attr,
+		&sensor_dev_attr_fan4_tolerance.dev_attr.attr,
+		&sensor_dev_attr_pwm4_stop_time.dev_attr.attr,
+		&sensor_dev_attr_pwm4_step_up_time.dev_attr.attr,
+		&sensor_dev_attr_pwm4_step_down_time.dev_attr.attr,
+		&sensor_dev_attr_pwm4_start.dev_attr.attr,
+		&sensor_dev_attr_pwm4_floor.dev_attr.attr,
+		&sensor_dev_attr_pwm4_weight_temp_sel.dev_attr.attr,
+		&sensor_dev_attr_pwm4_weight_temp_step.dev_attr.attr,
+		&sensor_dev_attr_pwm4_weight_temp_step_tol.dev_attr.attr,
+		&sensor_dev_attr_pwm4_weight_temp_step_base.dev_attr.attr,
+		&sensor_dev_attr_pwm4_weight_duty_step.dev_attr.attr,
+		NULL
+	},
+	{
+		&sensor_dev_attr_pwm5.dev_attr.attr,
+		&sensor_dev_attr_pwm5_mode.dev_attr.attr,
+		&sensor_dev_attr_pwm5_enable.dev_attr.attr,
+		&sensor_dev_attr_pwm5_temp_sel.dev_attr.attr,
+		&sensor_dev_attr_pwm5_temp_tolerance.dev_attr.attr,
+		&sensor_dev_attr_pwm5_crit_temp_tolerance.dev_attr.attr,
+		&sensor_dev_attr_pwm5_target_temp.dev_attr.attr,
+		&sensor_dev_attr_fan5_target.dev_attr.attr,
+		&sensor_dev_attr_fan5_tolerance.dev_attr.attr,
+		&sensor_dev_attr_pwm5_stop_time.dev_attr.attr,
+		&sensor_dev_attr_pwm5_step_up_time.dev_attr.attr,
+		&sensor_dev_attr_pwm5_step_down_time.dev_attr.attr,
+		&sensor_dev_attr_pwm5_start.dev_attr.attr,
+		&sensor_dev_attr_pwm5_floor.dev_attr.attr,
+		&sensor_dev_attr_pwm5_weight_temp_sel.dev_attr.attr,
+		&sensor_dev_attr_pwm5_weight_temp_step.dev_attr.attr,
+		&sensor_dev_attr_pwm5_weight_temp_step_tol.dev_attr.attr,
+		&sensor_dev_attr_pwm5_weight_temp_step_base.dev_attr.attr,
+		&sensor_dev_attr_pwm5_weight_duty_step.dev_attr.attr,
+		NULL
+	},
+};
+
+static const struct attribute_group nct6775_group_pwm[5] = {
+	{ .attrs = nct6775_attributes_pwm[0] },
+	{ .attrs = nct6775_attributes_pwm[1] },
+	{ .attrs = nct6775_attributes_pwm[2] },
+	{ .attrs = nct6775_attributes_pwm[3] },
+	{ .attrs = nct6775_attributes_pwm[4] },
+};
+
+static ssize_t
+show_auto_pwm(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct nct6775_data *data = nct6775_update_device(dev);
+	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+
+	return sprintf(buf, "%d\n", data->auto_pwm[sattr->nr][sattr->index]);
+}
+
+static ssize_t
+store_auto_pwm(struct device *dev, struct device_attribute *attr,
+	       const char *buf, size_t count)
+{
+	struct nct6775_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+	int nr = sattr->nr;
+	int point = sattr->index;
+	unsigned long val;
+	int err;
+	u8 reg;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err < 0)
+		return err;
+	if (val > 255)
+		return -EINVAL;
+
+	if (point == data->auto_pwm_num) {
+		if (data->kind != nct6775 && !val)
+			return -EINVAL;
+		if (data->kind != nct6779 && val)
+			val = 0xff;
+	}
+
+	mutex_lock(&data->update_lock);
+	data->auto_pwm[nr][point] = val;
+	if (point < data->auto_pwm_num) {
+		nct6775_write_value(data,
+				    NCT6775_AUTO_PWM(data, nr, point),
+				    data->auto_pwm[nr][point]);
+	} else {
+		switch (data->kind) {
+		case nct6775:
+			/* disable if needed (pwm == 0) */
+			reg = nct6775_read_value(data,
+						 NCT6775_REG_CRITICAL_ENAB[nr]);
+			if (val)
+				reg |= 0x02;
+			else
+				reg &= ~0x02;
+			nct6775_write_value(data, NCT6775_REG_CRITICAL_ENAB[nr],
+					    reg);
+			break;
+		case nct6776:
+			break; /* always enabled, nothing to do */
+		case nct6779:
+			nct6775_write_value(data, NCT6779_REG_CRITICAL_PWM[nr],
+					    val);
+			reg = nct6775_read_value(data,
+					NCT6779_REG_CRITICAL_PWM_ENABLE[nr]);
+			if (val == 255)
+				reg &= ~0x01;
+			else
+				reg |= 0x01;
+			nct6775_write_value(data,
+					    NCT6779_REG_CRITICAL_PWM_ENABLE[nr],
+					    reg);
+			break;
+		}
+	}
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static ssize_t
+show_auto_temp(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct nct6775_data *data = nct6775_update_device(dev);
+	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+	int nr = sattr->nr;
+	int point = sattr->index;
+
+	/*
+	 * We don't know for sure if the temperature is signed or unsigned.
+	 * Assume it is unsigned.
+	 */
+	return sprintf(buf, "%d\n", data->auto_temp[nr][point] * 1000);
+}
+
+static ssize_t
+store_auto_temp(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct nct6775_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+	int nr = sattr->nr;
+	int point = sattr->index;
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
+	if (val > 255000)
+		return -EINVAL;
+
+	mutex_lock(&data->update_lock);
+	data->auto_temp[nr][point] = DIV_ROUND_CLOSEST(val, 1000);
+	if (point < data->auto_pwm_num) {
+		nct6775_write_value(data,
+				    NCT6775_AUTO_TEMP(data, nr, point),
+				    data->auto_temp[nr][point]);
+	} else {
+		nct6775_write_value(data, data->REG_CRITICAL_TEMP[nr],
+				    data->auto_temp[nr][point]);
+	}
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+/*
+ * The number of auto-point trip points is chip dependent.
+ * Need to check support while generating/removing attribute files.
+ */
+static struct sensor_device_attribute_2 sda_auto_pwm_arrays[] = {
+	SENSOR_ATTR_2(pwm1_auto_point1_pwm, S_IWUSR | S_IRUGO,
+		      show_auto_pwm, store_auto_pwm, 0, 0),
+	SENSOR_ATTR_2(pwm1_auto_point1_temp, S_IWUSR | S_IRUGO,
+		      show_auto_temp, store_auto_temp, 0, 0),
+	SENSOR_ATTR_2(pwm1_auto_point2_pwm, S_IWUSR | S_IRUGO,
+		      show_auto_pwm, store_auto_pwm, 0, 1),
+	SENSOR_ATTR_2(pwm1_auto_point2_temp, S_IWUSR | S_IRUGO,
+		      show_auto_temp, store_auto_temp, 0, 1),
+	SENSOR_ATTR_2(pwm1_auto_point3_pwm, S_IWUSR | S_IRUGO,
+		      show_auto_pwm, store_auto_pwm, 0, 2),
+	SENSOR_ATTR_2(pwm1_auto_point3_temp, S_IWUSR | S_IRUGO,
+		      show_auto_temp, store_auto_temp, 0, 2),
+	SENSOR_ATTR_2(pwm1_auto_point4_pwm, S_IWUSR | S_IRUGO,
+		      show_auto_pwm, store_auto_pwm, 0, 3),
+	SENSOR_ATTR_2(pwm1_auto_point4_temp, S_IWUSR | S_IRUGO,
+		      show_auto_temp, store_auto_temp, 0, 3),
+	SENSOR_ATTR_2(pwm1_auto_point5_pwm, S_IWUSR | S_IRUGO,
+		      show_auto_pwm, store_auto_pwm, 0, 4),
+	SENSOR_ATTR_2(pwm1_auto_point5_temp, S_IWUSR | S_IRUGO,
+		      show_auto_temp, store_auto_temp, 0, 4),
+	SENSOR_ATTR_2(pwm1_auto_point6_pwm, S_IWUSR | S_IRUGO,
+		      show_auto_pwm, store_auto_pwm, 0, 5),
+	SENSOR_ATTR_2(pwm1_auto_point6_temp, S_IWUSR | S_IRUGO,
+		      show_auto_temp, store_auto_temp, 0, 5),
+	SENSOR_ATTR_2(pwm1_auto_point7_pwm, S_IWUSR | S_IRUGO,
+		      show_auto_pwm, store_auto_pwm, 0, 6),
+	SENSOR_ATTR_2(pwm1_auto_point7_temp, S_IWUSR | S_IRUGO,
+		      show_auto_temp, store_auto_temp, 0, 6),
+
+	SENSOR_ATTR_2(pwm2_auto_point1_pwm, S_IWUSR | S_IRUGO,
+		      show_auto_pwm, store_auto_pwm, 1, 0),
+	SENSOR_ATTR_2(pwm2_auto_point1_temp, S_IWUSR | S_IRUGO,
+		      show_auto_temp, store_auto_temp, 1, 0),
+	SENSOR_ATTR_2(pwm2_auto_point2_pwm, S_IWUSR | S_IRUGO,
+		      show_auto_pwm, store_auto_pwm, 1, 1),
+	SENSOR_ATTR_2(pwm2_auto_point2_temp, S_IWUSR | S_IRUGO,
+		      show_auto_temp, store_auto_temp, 1, 1),
+	SENSOR_ATTR_2(pwm2_auto_point3_pwm, S_IWUSR | S_IRUGO,
+		      show_auto_pwm, store_auto_pwm, 1, 2),
+	SENSOR_ATTR_2(pwm2_auto_point3_temp, S_IWUSR | S_IRUGO,
+		      show_auto_temp, store_auto_temp, 1, 2),
+	SENSOR_ATTR_2(pwm2_auto_point4_pwm, S_IWUSR | S_IRUGO,
+		      show_auto_pwm, store_auto_pwm, 1, 3),
+	SENSOR_ATTR_2(pwm2_auto_point4_temp, S_IWUSR | S_IRUGO,
+		      show_auto_temp, store_auto_temp, 1, 3),
+	SENSOR_ATTR_2(pwm2_auto_point5_pwm, S_IWUSR | S_IRUGO,
+		      show_auto_pwm, store_auto_pwm, 1, 4),
+	SENSOR_ATTR_2(pwm2_auto_point5_temp, S_IWUSR | S_IRUGO,
+		      show_auto_temp, store_auto_temp, 1, 4),
+	SENSOR_ATTR_2(pwm2_auto_point6_pwm, S_IWUSR | S_IRUGO,
+		      show_auto_pwm, store_auto_pwm, 1, 5),
+	SENSOR_ATTR_2(pwm2_auto_point6_temp, S_IWUSR | S_IRUGO,
+		      show_auto_temp, store_auto_temp, 1, 5),
+	SENSOR_ATTR_2(pwm2_auto_point7_pwm, S_IWUSR | S_IRUGO,
+		      show_auto_pwm, store_auto_pwm, 1, 6),
+	SENSOR_ATTR_2(pwm2_auto_point7_temp, S_IWUSR | S_IRUGO,
+		      show_auto_temp, store_auto_temp, 1, 6),
+
+	SENSOR_ATTR_2(pwm3_auto_point1_pwm, S_IWUSR | S_IRUGO,
+		      show_auto_pwm, store_auto_pwm, 2, 0),
+	SENSOR_ATTR_2(pwm3_auto_point1_temp, S_IWUSR | S_IRUGO,
+		      show_auto_temp, store_auto_temp, 2, 0),
+	SENSOR_ATTR_2(pwm3_auto_point2_pwm, S_IWUSR | S_IRUGO,
+		      show_auto_pwm, store_auto_pwm, 2, 1),
+	SENSOR_ATTR_2(pwm3_auto_point2_temp, S_IWUSR | S_IRUGO,
+		      show_auto_temp, store_auto_temp, 2, 1),
+	SENSOR_ATTR_2(pwm3_auto_point3_pwm, S_IWUSR | S_IRUGO,
+		      show_auto_pwm, store_auto_pwm, 2, 2),
+	SENSOR_ATTR_2(pwm3_auto_point3_temp, S_IWUSR | S_IRUGO,
+		      show_auto_temp, store_auto_temp, 2, 2),
+	SENSOR_ATTR_2(pwm3_auto_point4_pwm, S_IWUSR | S_IRUGO,
+		      show_auto_pwm, store_auto_pwm, 2, 3),
+	SENSOR_ATTR_2(pwm3_auto_point4_temp, S_IWUSR | S_IRUGO,
+		      show_auto_temp, store_auto_temp, 2, 3),
+	SENSOR_ATTR_2(pwm3_auto_point5_pwm, S_IWUSR | S_IRUGO,
+		      show_auto_pwm, store_auto_pwm, 2, 4),
+	SENSOR_ATTR_2(pwm3_auto_point5_temp, S_IWUSR | S_IRUGO,
+		      show_auto_temp, store_auto_temp, 2, 4),
+	SENSOR_ATTR_2(pwm3_auto_point6_pwm, S_IWUSR | S_IRUGO,
+		      show_auto_pwm, store_auto_pwm, 2, 5),
+	SENSOR_ATTR_2(pwm3_auto_point6_temp, S_IWUSR | S_IRUGO,
+		      show_auto_temp, store_auto_temp, 2, 5),
+	SENSOR_ATTR_2(pwm3_auto_point7_pwm, S_IWUSR | S_IRUGO,
+		      show_auto_pwm, store_auto_pwm, 2, 6),
+	SENSOR_ATTR_2(pwm3_auto_point7_temp, S_IWUSR | S_IRUGO,
+		      show_auto_temp, store_auto_temp, 2, 6),
+
+	SENSOR_ATTR_2(pwm4_auto_point1_pwm, S_IWUSR | S_IRUGO,
+		      show_auto_pwm, store_auto_pwm, 3, 0),
+	SENSOR_ATTR_2(pwm4_auto_point1_temp, S_IWUSR | S_IRUGO,
+		      show_auto_temp, store_auto_temp, 3, 0),
+	SENSOR_ATTR_2(pwm4_auto_point2_pwm, S_IWUSR | S_IRUGO,
+		      show_auto_pwm, store_auto_pwm, 3, 1),
+	SENSOR_ATTR_2(pwm4_auto_point2_temp, S_IWUSR | S_IRUGO,
+		      show_auto_temp, store_auto_temp, 3, 1),
+	SENSOR_ATTR_2(pwm4_auto_point3_pwm, S_IWUSR | S_IRUGO,
+		      show_auto_pwm, store_auto_pwm, 3, 2),
+	SENSOR_ATTR_2(pwm4_auto_point3_temp, S_IWUSR | S_IRUGO,
+		      show_auto_temp, store_auto_temp, 3, 2),
+	SENSOR_ATTR_2(pwm4_auto_point4_pwm, S_IWUSR | S_IRUGO,
+		      show_auto_pwm, store_auto_pwm, 3, 3),
+	SENSOR_ATTR_2(pwm4_auto_point4_temp, S_IWUSR | S_IRUGO,
+		      show_auto_temp, store_auto_temp, 3, 3),
+	SENSOR_ATTR_2(pwm4_auto_point5_pwm, S_IWUSR | S_IRUGO,
+		      show_auto_pwm, store_auto_pwm, 3, 4),
+	SENSOR_ATTR_2(pwm4_auto_point5_temp, S_IWUSR | S_IRUGO,
+		      show_auto_temp, store_auto_temp, 3, 4),
+	SENSOR_ATTR_2(pwm4_auto_point6_pwm, S_IWUSR | S_IRUGO,
+		      show_auto_pwm, store_auto_pwm, 3, 5),
+	SENSOR_ATTR_2(pwm4_auto_point6_temp, S_IWUSR | S_IRUGO,
+		      show_auto_temp, store_auto_temp, 3, 5),
+	SENSOR_ATTR_2(pwm4_auto_point7_pwm, S_IWUSR | S_IRUGO,
+		      show_auto_pwm, store_auto_pwm, 3, 6),
+	SENSOR_ATTR_2(pwm4_auto_point7_temp, S_IWUSR | S_IRUGO,
+		      show_auto_temp, store_auto_temp, 3, 6),
+
+	SENSOR_ATTR_2(pwm5_auto_point1_pwm, S_IWUSR | S_IRUGO,
+		      show_auto_pwm, store_auto_pwm, 4, 0),
+	SENSOR_ATTR_2(pwm5_auto_point1_temp, S_IWUSR | S_IRUGO,
+		      show_auto_temp, store_auto_temp, 4, 0),
+	SENSOR_ATTR_2(pwm5_auto_point2_pwm, S_IWUSR | S_IRUGO,
+		      show_auto_pwm, store_auto_pwm, 4, 1),
+	SENSOR_ATTR_2(pwm5_auto_point2_temp, S_IWUSR | S_IRUGO,
+		      show_auto_temp, store_auto_temp, 4, 1),
+	SENSOR_ATTR_2(pwm5_auto_point3_pwm, S_IWUSR | S_IRUGO,
+		      show_auto_pwm, store_auto_pwm, 4, 2),
+	SENSOR_ATTR_2(pwm5_auto_point3_temp, S_IWUSR | S_IRUGO,
+		      show_auto_temp, store_auto_temp, 4, 2),
+	SENSOR_ATTR_2(pwm5_auto_point4_pwm, S_IWUSR | S_IRUGO,
+		      show_auto_pwm, store_auto_pwm, 4, 3),
+	SENSOR_ATTR_2(pwm5_auto_point4_temp, S_IWUSR | S_IRUGO,
+		      show_auto_temp, store_auto_temp, 4, 3),
+	SENSOR_ATTR_2(pwm5_auto_point5_pwm, S_IWUSR | S_IRUGO,
+		      show_auto_pwm, store_auto_pwm, 4, 4),
+	SENSOR_ATTR_2(pwm5_auto_point5_temp, S_IWUSR | S_IRUGO,
+		      show_auto_temp, store_auto_temp, 4, 4),
+	SENSOR_ATTR_2(pwm5_auto_point6_pwm, S_IWUSR | S_IRUGO,
+		      show_auto_pwm, store_auto_pwm, 4, 5),
+	SENSOR_ATTR_2(pwm5_auto_point6_temp, S_IWUSR | S_IRUGO,
+		      show_auto_temp, store_auto_temp, 4, 5),
+	SENSOR_ATTR_2(pwm5_auto_point7_pwm, S_IWUSR | S_IRUGO,
+		      show_auto_pwm, store_auto_pwm, 4, 6),
+	SENSOR_ATTR_2(pwm5_auto_point7_temp, S_IWUSR | S_IRUGO,
+		      show_auto_temp, store_auto_temp, 4, 6),
+};
+
+static ssize_t
+show_vid(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct nct6775_data *data = dev_get_drvdata(dev);
+	return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm));
+}
+
+static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
+
+/* Case open detection */
+
+static ssize_t
+clear_caseopen(struct device *dev, struct device_attribute *attr,
+	       const char *buf, size_t count)
+{
+	struct nct6775_data *data = dev_get_drvdata(dev);
+	struct nct6775_sio_data *sio_data = dev->platform_data;
+	int nr = to_sensor_dev_attr(attr)->index - INTRUSION_ALARM_BASE;
+	unsigned long val;
+	u8 reg;
+	int ret;
+
+	if (kstrtoul(buf, 10, &val) || val != 0)
+		return -EINVAL;
+
+	mutex_lock(&data->update_lock);
+
+	/*
+	 * Use CR registers to clear caseopen status.
+	 * The CR registers are the same for all chips, and not all chips
+	 * support clearing the caseopen status through "regular" registers.
+	 */
+	ret = superio_enter(sio_data->sioreg);
+	if (ret) {
+		count = ret;
+		goto error;
+	}
+
+	superio_select(sio_data->sioreg, NCT6775_LD_ACPI);
+	reg = superio_inb(sio_data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr]);
+	reg |= NCT6775_CR_CASEOPEN_CLR_MASK[nr];
+	superio_outb(sio_data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr], reg);
+	reg &= ~NCT6775_CR_CASEOPEN_CLR_MASK[nr];
+	superio_outb(sio_data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr], reg);
+	superio_exit(sio_data->sioreg);
+
+	data->valid = false;	/* Force cache refresh */
+error:
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static struct sensor_device_attribute sda_caseopen[] = {
+	SENSOR_ATTR(intrusion0_alarm, S_IWUSR | S_IRUGO, show_alarm,
+		    clear_caseopen, INTRUSION_ALARM_BASE),
+	SENSOR_ATTR(intrusion1_alarm, S_IWUSR | S_IRUGO, show_alarm,
+		    clear_caseopen, INTRUSION_ALARM_BASE + 1),
+};
+
+/*
+ * Driver and device management
+ */
+
+static void nct6775_device_remove_files(struct device *dev)
+{
+	/*
+	 * some entries in the following arrays may not have been used in
+	 * device_create_file(), but device_remove_file() will ignore them
+	 */
+	int i;
+	struct nct6775_data *data = dev_get_drvdata(dev);
+
+	for (i = 0; i < data->pwm_num; i++)
+		sysfs_remove_group(&dev->kobj, &nct6775_group_pwm[i]);
+
+	for (i = 0; i < ARRAY_SIZE(sda_pwm_max); i++)
+		device_remove_file(dev, &sda_pwm_max[i].dev_attr);
+
+	for (i = 0; i < ARRAY_SIZE(sda_pwm_step); i++)
+		device_remove_file(dev, &sda_pwm_step[i].dev_attr);
+
+	for (i = 0; i < ARRAY_SIZE(sda_weight_duty_base); i++)
+		device_remove_file(dev, &sda_weight_duty_base[i].dev_attr);
+
+	for (i = 0; i < ARRAY_SIZE(sda_auto_pwm_arrays); i++)
+		device_remove_file(dev, &sda_auto_pwm_arrays[i].dev_attr);
+
+	for (i = 0; i < data->in_num; i++)
+		sysfs_remove_group(&dev->kobj, &nct6775_group_in[i]);
+
+	for (i = 0; i < 5; i++) {
+		device_remove_file(dev, &sda_fan_input[i].dev_attr);
+		device_remove_file(dev, &sda_fan_alarm[i].dev_attr);
+		device_remove_file(dev, &sda_fan_div[i].dev_attr);
+		device_remove_file(dev, &sda_fan_min[i].dev_attr);
+		device_remove_file(dev, &sda_fan_pulses[i].dev_attr);
+	}
+	for (i = 0; i < NUM_TEMP; i++) {
+		if (!(data->have_temp & (1 << i)))
+			continue;
+		device_remove_file(dev, &sda_temp_input[i].dev_attr);
+		device_remove_file(dev, &sda_temp_label[i].dev_attr);
+		device_remove_file(dev, &sda_temp_max[i].dev_attr);
+		device_remove_file(dev, &sda_temp_max_hyst[i].dev_attr);
+		device_remove_file(dev, &sda_temp_crit[i].dev_attr);
+		if (!(data->have_temp_fixed & (1 << i)))
+			continue;
+		device_remove_file(dev, &sda_temp_type[i].dev_attr);
+		device_remove_file(dev, &sda_temp_offset[i].dev_attr);
+		if (i >= NUM_TEMP_ALARM)
+			continue;
+		device_remove_file(dev, &sda_temp_alarm[i].dev_attr);
+	}
+
+	device_remove_file(dev, &sda_caseopen[0].dev_attr);
+	device_remove_file(dev, &sda_caseopen[1].dev_attr);
+
+	device_remove_file(dev, &dev_attr_name);
+	device_remove_file(dev, &dev_attr_cpu0_vid);
+}
+
+/* Get the monitoring functions started */
+static inline void nct6775_init_device(struct nct6775_data *data)
+{
+	int i;
+	u8 tmp, diode;
+
+	/* Start monitoring if needed */
+	if (data->REG_CONFIG) {
+		tmp = nct6775_read_value(data, data->REG_CONFIG);
+		if (!(tmp & 0x01))
+			nct6775_write_value(data, data->REG_CONFIG, tmp | 0x01);
+	}
+
+	/* Enable temperature sensors if needed */
+	for (i = 0; i < NUM_TEMP; i++) {
+		if (!(data->have_temp & (1 << i)))
+			continue;
+		if (!data->reg_temp_config[i])
+			continue;
+		tmp = nct6775_read_value(data, data->reg_temp_config[i]);
+		if (tmp & 0x01)
+			nct6775_write_value(data, data->reg_temp_config[i],
+					    tmp & 0xfe);
+	}
+
+	/* Enable VBAT monitoring if needed */
+	tmp = nct6775_read_value(data, data->REG_VBAT);
+	if (!(tmp & 0x01))
+		nct6775_write_value(data, data->REG_VBAT, tmp | 0x01);
+
+	diode = nct6775_read_value(data, data->REG_DIODE);
+
+	for (i = 0; i < data->temp_fixed_num; i++) {
+		if (!(data->have_temp_fixed & (1 << i)))
+			continue;
+		if ((tmp & (0x02 << i)))	/* diode */
+			data->temp_type[i] = 3 - ((diode >> i) & 0x02);
+		else				/* thermistor */
+			data->temp_type[i] = 4;
+	}
+}
+
+static int
+nct6775_check_fan_inputs(const struct nct6775_sio_data *sio_data,
+			 struct nct6775_data *data)
+{
+	int regval;
+	bool fan3pin, fan3min, fan4pin, fan4min, fan5pin;
+	bool pwm3pin, pwm4pin, pwm5pin;
+	int ret;
+
+	ret = superio_enter(sio_data->sioreg);
+	if (ret)
+		return ret;
+
+	/* fan4 and fan5 share some pins with the GPIO and serial flash */
+	if (data->kind == nct6775) {
+		regval = superio_inb(sio_data->sioreg, 0x2c);
+
+		fan3pin = regval & (1 << 6);
+		fan3min = fan3pin;
+		pwm3pin = regval & (1 << 7);
+
+		/* On NCT6775, fan4 shares pins with the fdc interface */
+		fan4pin = !(superio_inb(sio_data->sioreg, 0x2A) & 0x80);
+		fan4min = 0;
+		fan5pin = 0;
+		pwm4pin = 0;
+		pwm5pin = 0;
+	} else if (data->kind == nct6776) {
+		bool gpok = superio_inb(sio_data->sioreg, 0x27) & 0x80;
+
+		superio_select(sio_data->sioreg, NCT6775_LD_HWM);
+		regval = superio_inb(sio_data->sioreg, SIO_REG_ENABLE);
+
+		if (regval & 0x80)
+			fan3pin = gpok;
+		else
+			fan3pin = !(superio_inb(sio_data->sioreg, 0x24) & 0x40);
+
+		if (regval & 0x40)
+			fan4pin = gpok;
+		else
+			fan4pin = superio_inb(sio_data->sioreg, 0x1C) & 0x01;
+
+		if (regval & 0x20)
+			fan5pin = gpok;
+		else
+			fan5pin = superio_inb(sio_data->sioreg, 0x1C) & 0x02;
+
+		fan4min = fan4pin;
+		fan3min = fan3pin;
+		pwm3pin = fan3pin;
+		pwm4pin = 0;
+		pwm5pin = 0;
+	} else {	/* NCT6779D */
+		regval = superio_inb(sio_data->sioreg, 0x1c);
+
+		fan3pin = !(regval & (1 << 5));
+		fan4pin = !(regval & (1 << 6));
+		fan5pin = !(regval & (1 << 7));
+
+		pwm3pin = !(regval & (1 << 0));
+		pwm4pin = !(regval & (1 << 1));
+		pwm5pin = !(regval & (1 << 2));
+
+		fan3min = fan3pin;
+		fan4min = fan4pin;
+	}
+
+	superio_exit(sio_data->sioreg);
+
+	data->has_fan = data->has_fan_min = 0x03; /* fan1 and fan2 */
+	data->has_fan |= fan3pin << 2;
+	data->has_fan_min |= fan3min << 2;
+
+	data->has_fan |= (fan4pin << 3) | (fan5pin << 4);
+	data->has_fan_min |= (fan4min << 3) | (fan5pin << 4);
+
+	data->has_pwm = 0x03 | (pwm3pin << 2) | (pwm4pin << 3) | (pwm5pin << 4);
+
+	return 0;
+}
+
+static void add_temp_sensors(struct nct6775_data *data, const u16 *regp,
+			     int *available, int *mask)
+{
+	int i;
+	u8 src;
+
+	for (i = 0; i < data->pwm_num && *available; i++) {
+		int index;
+
+		if (!regp[i])
+			continue;
+		src = nct6775_read_value(data, regp[i]);
+		src &= 0x1f;
+		if (!src || (*mask & (1 << src)))
+			continue;
+		if (src >= data->temp_label_num ||
+		    !strlen(data->temp_label[src]))
+			continue;
+
+		index = __ffs(*available);
+		nct6775_write_value(data, data->REG_TEMP_SOURCE[index], src);
+		*available &= ~(1 << index);
+		*mask |= 1 << src;
+	}
+}
+
+static int nct6775_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct nct6775_sio_data *sio_data = dev->platform_data;
+	struct nct6775_data *data;
+	struct resource *res;
+	int i, s, err = 0;
+	int src, mask, available;
+	const u16 *reg_temp, *reg_temp_over, *reg_temp_hyst, *reg_temp_config;
+	const u16 *reg_temp_alternate, *reg_temp_crit;
+	int num_reg_temp;
+	bool have_vid = false;
+	u8 cr2a;
+
+	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+	if (!devm_request_region(&pdev->dev, res->start, IOREGION_LENGTH,
+				 DRVNAME))
+		return -EBUSY;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(struct nct6775_data),
+			    GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->kind = sio_data->kind;
+	data->addr = res->start;
+	mutex_init(&data->update_lock);
+	data->name = nct6775_device_names[data->kind];
+	data->bank = 0xff;		/* Force initial bank selection */
+	platform_set_drvdata(pdev, data);
+
+	switch (data->kind) {
+	case nct6775:
+		data->in_num = 9;
+		data->pwm_num = 3;
+		data->auto_pwm_num = 6;
+		data->has_fan_div = true;
+		data->temp_fixed_num = 3;
+
+		data->ALARM_BITS = NCT6775_ALARM_BITS;
+
+		data->fan_from_reg = fan_from_reg16;
+		data->fan_from_reg_min = fan_from_reg8;
+		data->target_temp_mask = 0x7f;
+		data->tolerance_mask = 0x0f;
+		data->speed_tolerance_limit = 15;
+
+		data->temp_label = nct6775_temp_label;
+		data->temp_label_num = ARRAY_SIZE(nct6775_temp_label);
+
+		data->REG_CONFIG = NCT6775_REG_CONFIG;
+		data->REG_VBAT = NCT6775_REG_VBAT;
+		data->REG_DIODE = NCT6775_REG_DIODE;
+		data->REG_VIN = NCT6775_REG_IN;
+		data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
+		data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
+		data->REG_TARGET = NCT6775_REG_TARGET;
+		data->REG_FAN = NCT6775_REG_FAN;
+		data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
+		data->REG_FAN_MIN = NCT6775_REG_FAN_MIN;
+		data->REG_FAN_PULSES = NCT6775_REG_FAN_PULSES;
+		data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
+		data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME;
+		data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME;
+		data->REG_PWM[0] = NCT6775_REG_PWM;
+		data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
+		data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
+		data->REG_PWM[3] = NCT6775_REG_FAN_MAX_OUTPUT;
+		data->REG_PWM[4] = NCT6775_REG_FAN_STEP_OUTPUT;
+		data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP;
+		data->REG_PWM_READ = NCT6775_REG_PWM_READ;
+		data->REG_PWM_MODE = NCT6775_REG_PWM_MODE;
+		data->PWM_MODE_MASK = NCT6775_PWM_MODE_MASK;
+		data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
+		data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
+		data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
+		data->REG_CRITICAL_TEMP_TOLERANCE
+		  = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
+		data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET;
+		data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
+		data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
+		data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL;
+		data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP;
+		data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL;
+		data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE;
+		data->REG_ALARM = NCT6775_REG_ALARM;
+
+		reg_temp = NCT6775_REG_TEMP;
+		num_reg_temp = ARRAY_SIZE(NCT6775_REG_TEMP);
+		reg_temp_over = NCT6775_REG_TEMP_OVER;
+		reg_temp_hyst = NCT6775_REG_TEMP_HYST;
+		reg_temp_config = NCT6775_REG_TEMP_CONFIG;
+		reg_temp_alternate = NCT6775_REG_TEMP_ALTERNATE;
+		reg_temp_crit = NCT6775_REG_TEMP_CRIT;
+
+		break;
+	case nct6776:
+		data->in_num = 9;
+		data->pwm_num = 3;
+		data->auto_pwm_num = 4;
+		data->has_fan_div = false;
+		data->temp_fixed_num = 3;
+
+		data->ALARM_BITS = NCT6776_ALARM_BITS;
+
+		data->fan_from_reg = fan_from_reg13;
+		data->fan_from_reg_min = fan_from_reg13;
+		data->target_temp_mask = 0xff;
+		data->tolerance_mask = 0x07;
+		data->speed_tolerance_limit = 63;
+
+		data->temp_label = nct6776_temp_label;
+		data->temp_label_num = ARRAY_SIZE(nct6776_temp_label);
+
+		data->REG_CONFIG = NCT6775_REG_CONFIG;
+		data->REG_VBAT = NCT6775_REG_VBAT;
+		data->REG_DIODE = NCT6775_REG_DIODE;
+		data->REG_VIN = NCT6775_REG_IN;
+		data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
+		data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
+		data->REG_TARGET = NCT6775_REG_TARGET;
+		data->REG_FAN = NCT6775_REG_FAN;
+		data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
+		data->REG_FAN_MIN = NCT6776_REG_FAN_MIN;
+		data->REG_FAN_PULSES = NCT6776_REG_FAN_PULSES;
+		data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
+		data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME;
+		data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME;
+		data->REG_TOLERANCE_H = NCT6776_REG_TOLERANCE_H;
+		data->REG_PWM[0] = NCT6775_REG_PWM;
+		data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
+		data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
+		data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP;
+		data->REG_PWM[6] = NCT6776_REG_WEIGHT_DUTY_BASE;
+		data->REG_PWM_READ = NCT6775_REG_PWM_READ;
+		data->REG_PWM_MODE = NCT6776_REG_PWM_MODE;
+		data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK;
+		data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
+		data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
+		data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
+		data->REG_CRITICAL_TEMP_TOLERANCE
+		  = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
+		data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET;
+		data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
+		data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
+		data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL;
+		data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP;
+		data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL;
+		data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE;
+		data->REG_ALARM = NCT6775_REG_ALARM;
+
+		reg_temp = NCT6775_REG_TEMP;
+		num_reg_temp = ARRAY_SIZE(NCT6775_REG_TEMP);
+		reg_temp_over = NCT6775_REG_TEMP_OVER;
+		reg_temp_hyst = NCT6775_REG_TEMP_HYST;
+		reg_temp_config = NCT6776_REG_TEMP_CONFIG;
+		reg_temp_alternate = NCT6776_REG_TEMP_ALTERNATE;
+		reg_temp_crit = NCT6776_REG_TEMP_CRIT;
+
+		break;
+	case nct6779:
+		data->in_num = 15;
+		data->pwm_num = 5;
+		data->auto_pwm_num = 4;
+		data->has_fan_div = false;
+		data->temp_fixed_num = 6;
+
+		data->ALARM_BITS = NCT6779_ALARM_BITS;
+
+		data->fan_from_reg = fan_from_reg13;
+		data->fan_from_reg_min = fan_from_reg13;
+		data->target_temp_mask = 0xff;
+		data->tolerance_mask = 0x07;
+		data->speed_tolerance_limit = 63;
+
+		data->temp_label = nct6779_temp_label;
+		data->temp_label_num = ARRAY_SIZE(nct6779_temp_label);
+
+		data->REG_CONFIG = NCT6775_REG_CONFIG;
+		data->REG_VBAT = NCT6775_REG_VBAT;
+		data->REG_DIODE = NCT6775_REG_DIODE;
+		data->REG_VIN = NCT6779_REG_IN;
+		data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
+		data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
+		data->REG_TARGET = NCT6775_REG_TARGET;
+		data->REG_FAN = NCT6779_REG_FAN;
+		data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
+		data->REG_FAN_MIN = NCT6776_REG_FAN_MIN;
+		data->REG_FAN_PULSES = NCT6779_REG_FAN_PULSES;
+		data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
+		data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME;
+		data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME;
+		data->REG_TOLERANCE_H = NCT6776_REG_TOLERANCE_H;
+		data->REG_PWM[0] = NCT6775_REG_PWM;
+		data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
+		data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
+		data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP;
+		data->REG_PWM[6] = NCT6776_REG_WEIGHT_DUTY_BASE;
+		data->REG_PWM_READ = NCT6775_REG_PWM_READ;
+		data->REG_PWM_MODE = NCT6776_REG_PWM_MODE;
+		data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK;
+		data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
+		data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
+		data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
+		data->REG_CRITICAL_TEMP_TOLERANCE
+		  = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
+		data->REG_TEMP_OFFSET = NCT6779_REG_TEMP_OFFSET;
+		data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
+		data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
+		data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL;
+		data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP;
+		data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL;
+		data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE;
+		data->REG_ALARM = NCT6779_REG_ALARM;
+
+		reg_temp = NCT6779_REG_TEMP;
+		num_reg_temp = ARRAY_SIZE(NCT6779_REG_TEMP);
+		reg_temp_over = NCT6779_REG_TEMP_OVER;
+		reg_temp_hyst = NCT6779_REG_TEMP_HYST;
+		reg_temp_config = NCT6779_REG_TEMP_CONFIG;
+		reg_temp_alternate = NCT6779_REG_TEMP_ALTERNATE;
+		reg_temp_crit = NCT6779_REG_TEMP_CRIT;
+
+		break;
+	default:
+		return -ENODEV;
+	}
+	data->have_in = (1 << data->in_num) - 1;
+	data->have_temp = 0;
+
+	/*
+	 * On some boards, not all available temperature sources are monitored,
+	 * even though some of the monitoring registers are unused.
+	 * Get list of unused monitoring registers, then detect if any fan
+	 * controls are configured to use unmonitored temperature sources.
+	 * If so, assign the unmonitored temperature sources to available
+	 * monitoring registers.
+	 */
+	mask = 0;
+	available = 0;
+	for (i = 0; i < num_reg_temp; i++) {
+		if (reg_temp[i] == 0)
+			continue;
+
+		src = nct6775_read_value(data, data->REG_TEMP_SOURCE[i]) & 0x1f;
+		if (!src || (mask & (1 << src)))
+			available |= 1 << i;
+
+		mask |= 1 << src;
+	}
+
+	/*
+	 * Now find unmonitored temperature registers and enable monitoring
+	 * if additional monitoring registers are available.
+	 */
+	add_temp_sensors(data, data->REG_TEMP_SEL, &available, &mask);
+	add_temp_sensors(data, data->REG_WEIGHT_TEMP_SEL, &available, &mask);
+
+	mask = 0;
+	s = NUM_TEMP_FIXED;	/* First dynamic temperature attribute */
+	for (i = 0; i < num_reg_temp; i++) {
+		if (reg_temp[i] == 0)
+			continue;
+
+		src = nct6775_read_value(data, data->REG_TEMP_SOURCE[i]) & 0x1f;
+		if (!src || (mask & (1 << src)))
+			continue;
+
+		if (src >= data->temp_label_num ||
+		    !strlen(data->temp_label[src])) {
+			dev_info(dev,
+				 "Invalid temperature source %d at index %d, source register 0x%x, temp register 0x%x\n",
+				 src, i, data->REG_TEMP_SOURCE[i], reg_temp[i]);
+			continue;
+		}
+
+		mask |= 1 << src;
+
+		/* Use fixed index for SYSTIN(1), CPUTIN(2), AUXTIN(3) */
+		if (src <= data->temp_fixed_num) {
+			data->have_temp |= 1 << (src - 1);
+			data->have_temp_fixed |= 1 << (src - 1);
+			data->reg_temp[0][src - 1] = reg_temp[i];
+			data->reg_temp[1][src - 1] = reg_temp_over[i];
+			data->reg_temp[2][src - 1] = reg_temp_hyst[i];
+			data->reg_temp_config[src - 1] = reg_temp_config[i];
+			data->temp_src[src - 1] = src;
+			continue;
+		}
+
+		if (s >= NUM_TEMP)
+			continue;
+
+		/* Use dynamic index for other sources */
+		data->have_temp |= 1 << s;
+		data->reg_temp[0][s] = reg_temp[i];
+		data->reg_temp[1][s] = reg_temp_over[i];
+		data->reg_temp[2][s] = reg_temp_hyst[i];
+		data->reg_temp_config[s] = reg_temp_config[i];
+		if (reg_temp_crit[src - 1])
+			data->reg_temp[3][s] = reg_temp_crit[src - 1];
+
+		data->temp_src[s] = src;
+		s++;
+	}
+
+#ifdef USE_ALTERNATE
+	/*
+	 * Go through the list of alternate temp registers and enable
+	 * if possible.
+	 * The temperature is already monitored if the respective bit in <mask>
+	 * is set.
+	 */
+	for (i = 0; i < data->temp_label_num - 1; i++) {
+		if (!reg_temp_alternate[i])
+			continue;
+		if (mask & (1 << (i + 1)))
+			continue;
+		if (i < data->temp_fixed_num) {
+			if (data->have_temp & (1 << i))
+				continue;
+			data->have_temp |= 1 << i;
+			data->have_temp_fixed |= 1 << i;
+			data->reg_temp[0][i] = reg_temp_alternate[i];
+			data->reg_temp[1][i] = reg_temp_over[i];
+			data->reg_temp[2][i] = reg_temp_hyst[i];
+			data->temp_src[i] = i + 1;
+			continue;
+		}
+
+		if (s >= NUM_TEMP)	/* Abort if no more space */
+			break;
+
+		data->have_temp |= 1 << s;
+		data->reg_temp[0][s] = reg_temp_alternate[i];
+		data->temp_src[s] = i + 1;
+		s++;
+	}
+#endif /* USE_ALTERNATE */
+
+	switch (data->kind) {
+	case nct6775:
+		break;
+	case nct6776:
+		/*
+		 * On NCT6776, AUXTIN and VIN3 pins are shared.
+		 * Only way to detect it is to check if AUXTIN is used
+		 * as a temperature source, and if that source is
+		 * enabled.
+		 *
+		 * If that is the case, disable in6, which reports VIN3.
+		 * Otherwise disable temp3.
+		 */
+		if (data->have_temp & (1 << 2)) {
+			u8 reg = nct6775_read_value(data,
+						    data->reg_temp_config[2]);
+			if (reg & 0x01)
+				data->have_temp &= ~(1 << 2);
+			else
+				data->have_in &= ~(1 << 6);
+		}
+		break;
+	case nct6779:
+		/*
+		 * Shared pins:
+		 *	VIN4 / AUXTIN0
+		 *	VIN5 / AUXTIN1
+		 *	VIN6 / AUXTIN2
+		 *	VIN7 / AUXTIN3
+		 *
+		 * There does not seem to be a clean way to detect if VINx or
+		 * AUXTINx is active, so for keep both sensor types enabled
+		 * for now.
+		 */
+		break;
+	}
+
+	/* Initialize the chip */
+	nct6775_init_device(data);
+
+	err = superio_enter(sio_data->sioreg);
+	if (err)
+		return err;
+
+	cr2a = superio_inb(sio_data->sioreg, 0x2a);
+	switch (data->kind) {
+	case nct6775:
+		have_vid = (cr2a & 0x40);
+		break;
+	case nct6776:
+		have_vid = (cr2a & 0x60) == 0x40;
+		break;
+	case nct6779:
+		break;
+	}
+
+	/*
+	 * Read VID value
+	 * We can get the VID input values directly at logical device D 0xe3.
+	 */
+	if (have_vid) {
+		superio_select(sio_data->sioreg, NCT6775_LD_VID);
+		data->vid = superio_inb(sio_data->sioreg, 0xe3);
+		data->vrm = vid_which_vrm();
+	}
+
+	if (fan_debounce) {
+		u8 tmp;
+
+		superio_select(sio_data->sioreg, NCT6775_LD_HWM);
+		tmp = superio_inb(sio_data->sioreg,
+				  NCT6775_REG_CR_FAN_DEBOUNCE);
+		switch (data->kind) {
+		case nct6775:
+			tmp |= 0x1e;
+			break;
+		case nct6776:
+		case nct6779:
+			tmp |= 0x3e;
+			break;
+		}
+		superio_outb(sio_data->sioreg, NCT6775_REG_CR_FAN_DEBOUNCE,
+			     tmp);
+		dev_info(&pdev->dev, "Enabled fan debounce for chip %s\n",
+			 data->name);
+	}
+
+	superio_exit(sio_data->sioreg);
+
+	if (have_vid) {
+		err = device_create_file(dev, &dev_attr_cpu0_vid);
+		if (err)
+			return err;
+	}
+
+	err = nct6775_check_fan_inputs(sio_data, data);
+	if (err)
+		goto exit_remove;
+
+	/* Read fan clock dividers immediately */
+	nct6775_init_fan_common(dev, data);
+
+	/* Register sysfs hooks */
+	for (i = 0; i < data->pwm_num; i++) {
+		if (!(data->has_pwm & (1 << i)))
+			continue;
+
+		err = sysfs_create_group(&dev->kobj, &nct6775_group_pwm[i]);
+		if (err)
+			goto exit_remove;
+
+		if (data->REG_PWM[3]) {
+			err = device_create_file(dev,
+					&sda_pwm_max[i].dev_attr);
+			if (err)
+				goto exit_remove;
+		}
+		if (data->REG_PWM[4]) {
+			err = device_create_file(dev,
+					&sda_pwm_step[i].dev_attr);
+			if (err)
+				goto exit_remove;
+		}
+		if (data->REG_PWM[6]) {
+			err = device_create_file(dev,
+					&sda_weight_duty_base[i].dev_attr);
+			if (err)
+				goto exit_remove;
+		}
+	}
+	for (i = 0; i < ARRAY_SIZE(sda_auto_pwm_arrays); i++) {
+		struct sensor_device_attribute_2 *attr =
+			&sda_auto_pwm_arrays[i];
+
+		if (!(data->has_pwm & (1 << attr->nr)))
+			continue;
+		if (attr->index > data->auto_pwm_num)
+			continue;
+		err = device_create_file(dev, &attr->dev_attr);
+		if (err)
+			goto exit_remove;
+	}
+
+	for (i = 0; i < data->in_num; i++) {
+		if (!(data->have_in & (1 << i)))
+			continue;
+		err = sysfs_create_group(&dev->kobj, &nct6775_group_in[i]);
+		if (err)
+			goto exit_remove;
+	}
+
+	for (i = 0; i < 5; i++) {
+		if (data->has_fan & (1 << i)) {
+			err = device_create_file(dev,
+						 &sda_fan_input[i].dev_attr);
+			if (err)
+				goto exit_remove;
+			err = device_create_file(dev,
+						 &sda_fan_alarm[i].dev_attr);
+			if (err)
+				goto exit_remove;
+			if (data->kind != nct6776 &&
+			    data->kind != nct6779) {
+				err = device_create_file(dev,
+						&sda_fan_div[i].dev_attr);
+				if (err)
+					goto exit_remove;
+			}
+			if (data->has_fan_min & (1 << i)) {
+				err = device_create_file(dev,
+						&sda_fan_min[i].dev_attr);
+				if (err)
+					goto exit_remove;
+			}
+			err = device_create_file(dev,
+						&sda_fan_pulses[i].dev_attr);
+			if (err)
+				goto exit_remove;
+		}
+	}
+
+	for (i = 0; i < NUM_TEMP; i++) {
+		if (!(data->have_temp & (1 << i)))
+			continue;
+		err = device_create_file(dev, &sda_temp_input[i].dev_attr);
+		if (err)
+			goto exit_remove;
+		if (data->temp_label) {
+			err = device_create_file(dev,
+						 &sda_temp_label[i].dev_attr);
+			if (err)
+				goto exit_remove;
+		}
+		if (data->reg_temp[1][i]) {
+			err = device_create_file(dev,
+						 &sda_temp_max[i].dev_attr);
+			if (err)
+				goto exit_remove;
+		}
+		if (data->reg_temp[2][i]) {
+			err = device_create_file(dev,
+					&sda_temp_max_hyst[i].dev_attr);
+			if (err)
+				goto exit_remove;
+		}
+		if (data->reg_temp[3][i]) {
+			err = device_create_file(dev,
+						 &sda_temp_crit[i].dev_attr);
+			if (err)
+				goto exit_remove;
+		}
+		if (!(data->have_temp_fixed & (1 << i)))
+			continue;
+		err = device_create_file(dev, &sda_temp_type[i].dev_attr);
+		if (err)
+			goto exit_remove;
+		err = device_create_file(dev, &sda_temp_offset[i].dev_attr);
+		if (err)
+			goto exit_remove;
+		if (i >= NUM_TEMP_ALARM ||
+		    data->ALARM_BITS[TEMP_ALARM_BASE + i] < 0)
+			continue;
+		err = device_create_file(dev, &sda_temp_alarm[i].dev_attr);
+		if (err)
+			goto exit_remove;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(sda_caseopen); i++) {
+		if (data->ALARM_BITS[INTRUSION_ALARM_BASE + i] < 0)
+			continue;
+		err = device_create_file(dev, &sda_caseopen[i].dev_attr);
+		if (err)
+			goto exit_remove;
+	}
+
+	err = device_create_file(dev, &dev_attr_name);
+	if (err)
+		goto exit_remove;
+
+	data->hwmon_dev = hwmon_device_register(dev);
+	if (IS_ERR(data->hwmon_dev)) {
+		err = PTR_ERR(data->hwmon_dev);
+		goto exit_remove;
+	}
+
+	return 0;
+
+exit_remove:
+	nct6775_device_remove_files(dev);
+	return err;
+}
+
+static int nct6775_remove(struct platform_device *pdev)
+{
+	struct nct6775_data *data = platform_get_drvdata(pdev);
+
+	hwmon_device_unregister(data->hwmon_dev);
+	nct6775_device_remove_files(&pdev->dev);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int nct6775_suspend(struct device *dev)
+{
+	struct nct6775_data *data = nct6775_update_device(dev);
+	struct nct6775_sio_data *sio_data = dev->platform_data;
+
+	mutex_lock(&data->update_lock);
+	data->vbat = nct6775_read_value(data, data->REG_VBAT);
+	if (sio_data->kind == nct6775) {
+		data->fandiv1 = nct6775_read_value(data, NCT6775_REG_FANDIV1);
+		data->fandiv2 = nct6775_read_value(data, NCT6775_REG_FANDIV2);
+	}
+	mutex_unlock(&data->update_lock);
+
+	return 0;
+}
+
+static int nct6775_resume(struct device *dev)
+{
+	struct nct6775_data *data = dev_get_drvdata(dev);
+	struct nct6775_sio_data *sio_data = dev->platform_data;
+	int i, j;
+
+	mutex_lock(&data->update_lock);
+	data->bank = 0xff;		/* Force initial bank selection */
+
+	/* Restore limits */
+	for (i = 0; i < data->in_num; i++) {
+		if (!(data->have_in & (1 << i)))
+			continue;
+
+		nct6775_write_value(data, data->REG_IN_MINMAX[0][i],
+				    data->in[i][1]);
+		nct6775_write_value(data, data->REG_IN_MINMAX[1][i],
+				    data->in[i][2]);
+	}
+
+	for (i = 0; i < 5; i++) {
+		if (!(data->has_fan_min & (1 << i)))
+			continue;
+
+		nct6775_write_value(data, data->REG_FAN_MIN[i],
+				    data->fan_min[i]);
+	}
+
+	for (i = 0; i < NUM_TEMP; i++) {
+		if (!(data->have_temp & (1 << i)))
+			continue;
+
+		for (j = 1; j < 4; j++)
+			if (data->reg_temp[j][i])
+				nct6775_write_temp(data, data->reg_temp[j][i],
+						   data->temp[j][i]);
+	}
+
+	/* Restore other settings */
+	nct6775_write_value(data, data->REG_VBAT, data->vbat);
+	if (sio_data->kind == nct6775) {
+		nct6775_write_value(data, NCT6775_REG_FANDIV1, data->fandiv1);
+		nct6775_write_value(data, NCT6775_REG_FANDIV2, data->fandiv2);
+	}
+
+	/* Force re-reading all values */
+	data->valid = false;
+	mutex_unlock(&data->update_lock);
+
+	return 0;
+}
+
+static const struct dev_pm_ops nct6775_dev_pm_ops = {
+	.suspend = nct6775_suspend,
+	.resume = nct6775_resume,
+};
+
+#define NCT6775_DEV_PM_OPS	(&nct6775_dev_pm_ops)
+#else
+#define NCT6775_DEV_PM_OPS	NULL
+#endif /* CONFIG_PM */
+
+static struct platform_driver nct6775_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= DRVNAME,
+		.pm	= NCT6775_DEV_PM_OPS,
+	},
+	.probe		= nct6775_probe,
+	.remove		= nct6775_remove,
+};
+
+static const char *nct6775_sio_names[] __initconst = {
+	"NCT6775F",
+	"NCT6776D/F",
+	"NCT6779D",
+};
+
+/* nct6775_find() looks for a '627 in the Super-I/O config space */
+static int __init nct6775_find(int sioaddr, unsigned short *addr,
+			       struct nct6775_sio_data *sio_data)
+{
+	u16 val;
+	int err;
+
+	err = superio_enter(sioaddr);
+	if (err)
+		return err;
+
+	if (force_id)
+		val = force_id;
+	else
+		val = (superio_inb(sioaddr, SIO_REG_DEVID) << 8)
+		    | superio_inb(sioaddr, SIO_REG_DEVID + 1);
+	switch (val & SIO_ID_MASK) {
+	case SIO_NCT6775_ID:
+		sio_data->kind = nct6775;
+		break;
+	case SIO_NCT6776_ID:
+		sio_data->kind = nct6776;
+		break;
+	case SIO_NCT6779_ID:
+		sio_data->kind = nct6779;
+		break;
+	default:
+		if (val != 0xffff)
+			pr_debug("unsupported chip ID: 0x%04x\n", val);
+		superio_exit(sioaddr);
+		return -ENODEV;
+	}
+
+	/* We have a known chip, find the HWM I/O address */
+	superio_select(sioaddr, NCT6775_LD_HWM);
+	val = (superio_inb(sioaddr, SIO_REG_ADDR) << 8)
+	    | superio_inb(sioaddr, SIO_REG_ADDR + 1);
+	*addr = val & IOREGION_ALIGNMENT;
+	if (*addr == 0) {
+		pr_err("Refusing to enable a Super-I/O device with a base I/O port 0\n");
+		superio_exit(sioaddr);
+		return -ENODEV;
+	}
+
+	/* Activate logical device if needed */
+	val = superio_inb(sioaddr, SIO_REG_ENABLE);
+	if (!(val & 0x01)) {
+		pr_warn("Forcibly enabling Super-I/O. Sensor is probably unusable.\n");
+		superio_outb(sioaddr, SIO_REG_ENABLE, val | 0x01);
+	}
+
+	superio_exit(sioaddr);
+	pr_info("Found %s or compatible chip at %#x\n",
+		nct6775_sio_names[sio_data->kind], *addr);
+	sio_data->sioreg = sioaddr;
+
+	return 0;
+}
+
+/*
+ * when Super-I/O functions move to a separate file, the Super-I/O
+ * bus will manage the lifetime of the device and this module will only keep
+ * track of the nct6775 driver. But since we platform_device_alloc(), we
+ * must keep track of the device
+ */
+static struct platform_device *pdev;
+
+static int __init sensors_nct6775_init(void)
+{
+	int err;
+	unsigned short address;
+	struct resource res;
+	struct nct6775_sio_data sio_data;
+
+	/*
+	 * initialize sio_data->kind and sio_data->sioreg.
+	 *
+	 * when Super-I/O functions move to a separate file, the Super-I/O
+	 * driver will probe 0x2e and 0x4e and auto-detect the presence of a
+	 * nct6775 hardware monitor, and call probe()
+	 */
+	if (nct6775_find(0x2e, &address, &sio_data) &&
+	    nct6775_find(0x4e, &address, &sio_data))
+		return -ENODEV;
+
+	err = platform_driver_register(&nct6775_driver);
+	if (err)
+		goto exit;
+
+	pdev = platform_device_alloc(DRVNAME, address);
+	if (!pdev) {
+		err = -ENOMEM;
+		pr_err("Device allocation failed\n");
+		goto exit_unregister;
+	}
+
+	err = platform_device_add_data(pdev, &sio_data,
+				       sizeof(struct nct6775_sio_data));
+	if (err) {
+		pr_err("Platform data allocation failed\n");
+		goto exit_device_put;
+	}
+
+	memset(&res, 0, sizeof(res));
+	res.name = DRVNAME;
+	res.start = address + IOREGION_OFFSET;
+	res.end = address + IOREGION_OFFSET + IOREGION_LENGTH - 1;
+	res.flags = IORESOURCE_IO;
+
+	err = acpi_check_resource_conflict(&res);
+	if (err)
+		goto exit_device_put;
+
+	err = platform_device_add_resources(pdev, &res, 1);
+	if (err) {
+		pr_err("Device resource addition failed (%d)\n", err);
+		goto exit_device_put;
+	}
+
+	/* platform_device_add calls probe() */
+	err = platform_device_add(pdev);
+	if (err) {
+		pr_err("Device addition failed (%d)\n", err);
+		goto exit_device_put;
+	}
+
+	return 0;
+
+exit_device_put:
+	platform_device_put(pdev);
+exit_unregister:
+	platform_driver_unregister(&nct6775_driver);
+exit:
+	return err;
+}
+
+static void __exit sensors_nct6775_exit(void)
+{
+	platform_device_unregister(pdev);
+	platform_driver_unregister(&nct6775_driver);
+}
+
+MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>");
+MODULE_DESCRIPTION("NCT6775F/NCT6776F/NCT6779D driver");
+MODULE_LICENSE("GPL");
+
+module_init(sensors_nct6775_init);
+module_exit(sensors_nct6775_exit);
diff --git a/drivers/hwmon/ntc_thermistor.c b/drivers/hwmon/ntc_thermistor.c
index b5f63f9..d6d640a 100644
--- a/drivers/hwmon/ntc_thermistor.c
+++ b/drivers/hwmon/ntc_thermistor.c
@@ -26,17 +26,33 @@
 #include <linux/math64.h>
 #include <linux/platform_device.h>
 #include <linux/err.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 
 #include <linux/platform_data/ntc_thermistor.h>
 
+#include <linux/iio/iio.h>
+#include <linux/iio/machine.h>
+#include <linux/iio/driver.h>
+#include <linux/iio/consumer.h>
+
 #include <linux/hwmon.h>
 #include <linux/hwmon-sysfs.h>
 
 struct ntc_compensation {
-	int		temp_C;
+	int		temp_c;
 	unsigned int	ohm;
 };
 
+static const struct platform_device_id ntc_thermistor_id[] = {
+	{ "ncp15wb473", TYPE_NCPXXWB473 },
+	{ "ncp18wb473", TYPE_NCPXXWB473 },
+	{ "ncp21wb473", TYPE_NCPXXWB473 },
+	{ "ncp03wb473", TYPE_NCPXXWB473 },
+	{ "ncp15wl333", TYPE_NCPXXWL333 },
+	{ },
+};
+
 /*
  * A compensation table should be sorted by the values of .ohm
  * in descending order.
@@ -44,76 +60,76 @@ struct ntc_compensation {
  * Thermistors Datasheet
  */
 static const struct ntc_compensation ncpXXwb473[] = {
-	{ .temp_C	= -40, .ohm	= 1747920 },
-	{ .temp_C	= -35, .ohm	= 1245428 },
-	{ .temp_C	= -30, .ohm	= 898485 },
-	{ .temp_C	= -25, .ohm	= 655802 },
-	{ .temp_C	= -20, .ohm	= 483954 },
-	{ .temp_C	= -15, .ohm	= 360850 },
-	{ .temp_C	= -10, .ohm	= 271697 },
-	{ .temp_C	= -5, .ohm	= 206463 },
-	{ .temp_C	= 0, .ohm	= 158214 },
-	{ .temp_C	= 5, .ohm	= 122259 },
-	{ .temp_C	= 10, .ohm	= 95227 },
-	{ .temp_C	= 15, .ohm	= 74730 },
-	{ .temp_C	= 20, .ohm	= 59065 },
-	{ .temp_C	= 25, .ohm	= 47000 },
-	{ .temp_C	= 30, .ohm	= 37643 },
-	{ .temp_C	= 35, .ohm	= 30334 },
-	{ .temp_C	= 40, .ohm	= 24591 },
-	{ .temp_C	= 45, .ohm	= 20048 },
-	{ .temp_C	= 50, .ohm	= 16433 },
-	{ .temp_C	= 55, .ohm	= 13539 },
-	{ .temp_C	= 60, .ohm	= 11209 },
-	{ .temp_C	= 65, .ohm	= 9328 },
-	{ .temp_C	= 70, .ohm	= 7798 },
-	{ .temp_C	= 75, .ohm	= 6544 },
-	{ .temp_C	= 80, .ohm	= 5518 },
-	{ .temp_C	= 85, .ohm	= 4674 },
-	{ .temp_C	= 90, .ohm	= 3972 },
-	{ .temp_C	= 95, .ohm	= 3388 },
-	{ .temp_C	= 100, .ohm	= 2902 },
-	{ .temp_C	= 105, .ohm	= 2494 },
-	{ .temp_C	= 110, .ohm	= 2150 },
-	{ .temp_C	= 115, .ohm	= 1860 },
-	{ .temp_C	= 120, .ohm	= 1615 },
-	{ .temp_C	= 125, .ohm	= 1406 },
+	{ .temp_c	= -40, .ohm	= 1747920 },
+	{ .temp_c	= -35, .ohm	= 1245428 },
+	{ .temp_c	= -30, .ohm	= 898485 },
+	{ .temp_c	= -25, .ohm	= 655802 },
+	{ .temp_c	= -20, .ohm	= 483954 },
+	{ .temp_c	= -15, .ohm	= 360850 },
+	{ .temp_c	= -10, .ohm	= 271697 },
+	{ .temp_c	= -5, .ohm	= 206463 },
+	{ .temp_c	= 0, .ohm	= 158214 },
+	{ .temp_c	= 5, .ohm	= 122259 },
+	{ .temp_c	= 10, .ohm	= 95227 },
+	{ .temp_c	= 15, .ohm	= 74730 },
+	{ .temp_c	= 20, .ohm	= 59065 },
+	{ .temp_c	= 25, .ohm	= 47000 },
+	{ .temp_c	= 30, .ohm	= 37643 },
+	{ .temp_c	= 35, .ohm	= 30334 },
+	{ .temp_c	= 40, .ohm	= 24591 },
+	{ .temp_c	= 45, .ohm	= 20048 },
+	{ .temp_c	= 50, .ohm	= 16433 },
+	{ .temp_c	= 55, .ohm	= 13539 },
+	{ .temp_c	= 60, .ohm	= 11209 },
+	{ .temp_c	= 65, .ohm	= 9328 },
+	{ .temp_c	= 70, .ohm	= 7798 },
+	{ .temp_c	= 75, .ohm	= 6544 },
+	{ .temp_c	= 80, .ohm	= 5518 },
+	{ .temp_c	= 85, .ohm	= 4674 },
+	{ .temp_c	= 90, .ohm	= 3972 },
+	{ .temp_c	= 95, .ohm	= 3388 },
+	{ .temp_c	= 100, .ohm	= 2902 },
+	{ .temp_c	= 105, .ohm	= 2494 },
+	{ .temp_c	= 110, .ohm	= 2150 },
+	{ .temp_c	= 115, .ohm	= 1860 },
+	{ .temp_c	= 120, .ohm	= 1615 },
+	{ .temp_c	= 125, .ohm	= 1406 },
 };
 static const struct ntc_compensation ncpXXwl333[] = {
-	{ .temp_C	= -40, .ohm	= 1610154 },
-	{ .temp_C	= -35, .ohm	= 1130850 },
-	{ .temp_C	= -30, .ohm	= 802609 },
-	{ .temp_C	= -25, .ohm	= 575385 },
-	{ .temp_C	= -20, .ohm	= 416464 },
-	{ .temp_C	= -15, .ohm	= 304219 },
-	{ .temp_C	= -10, .ohm	= 224193 },
-	{ .temp_C	= -5, .ohm	= 166623 },
-	{ .temp_C	= 0, .ohm	= 124850 },
-	{ .temp_C	= 5, .ohm	= 94287 },
-	{ .temp_C	= 10, .ohm	= 71747 },
-	{ .temp_C	= 15, .ohm	= 54996 },
-	{ .temp_C	= 20, .ohm	= 42455 },
-	{ .temp_C	= 25, .ohm	= 33000 },
-	{ .temp_C	= 30, .ohm	= 25822 },
-	{ .temp_C	= 35, .ohm	= 20335 },
-	{ .temp_C	= 40, .ohm	= 16115 },
-	{ .temp_C	= 45, .ohm	= 12849 },
-	{ .temp_C	= 50, .ohm	= 10306 },
-	{ .temp_C	= 55, .ohm	= 8314 },
-	{ .temp_C	= 60, .ohm	= 6746 },
-	{ .temp_C	= 65, .ohm	= 5503 },
-	{ .temp_C	= 70, .ohm	= 4513 },
-	{ .temp_C	= 75, .ohm	= 3721 },
-	{ .temp_C	= 80, .ohm	= 3084 },
-	{ .temp_C	= 85, .ohm	= 2569 },
-	{ .temp_C	= 90, .ohm	= 2151 },
-	{ .temp_C	= 95, .ohm	= 1809 },
-	{ .temp_C	= 100, .ohm	= 1529 },
-	{ .temp_C	= 105, .ohm	= 1299 },
-	{ .temp_C	= 110, .ohm	= 1108 },
-	{ .temp_C	= 115, .ohm	= 949 },
-	{ .temp_C	= 120, .ohm	= 817 },
-	{ .temp_C	= 125, .ohm	= 707 },
+	{ .temp_c	= -40, .ohm	= 1610154 },
+	{ .temp_c	= -35, .ohm	= 1130850 },
+	{ .temp_c	= -30, .ohm	= 802609 },
+	{ .temp_c	= -25, .ohm	= 575385 },
+	{ .temp_c	= -20, .ohm	= 416464 },
+	{ .temp_c	= -15, .ohm	= 304219 },
+	{ .temp_c	= -10, .ohm	= 224193 },
+	{ .temp_c	= -5, .ohm	= 166623 },
+	{ .temp_c	= 0, .ohm	= 124850 },
+	{ .temp_c	= 5, .ohm	= 94287 },
+	{ .temp_c	= 10, .ohm	= 71747 },
+	{ .temp_c	= 15, .ohm	= 54996 },
+	{ .temp_c	= 20, .ohm	= 42455 },
+	{ .temp_c	= 25, .ohm	= 33000 },
+	{ .temp_c	= 30, .ohm	= 25822 },
+	{ .temp_c	= 35, .ohm	= 20335 },
+	{ .temp_c	= 40, .ohm	= 16115 },
+	{ .temp_c	= 45, .ohm	= 12849 },
+	{ .temp_c	= 50, .ohm	= 10306 },
+	{ .temp_c	= 55, .ohm	= 8314 },
+	{ .temp_c	= 60, .ohm	= 6746 },
+	{ .temp_c	= 65, .ohm	= 5503 },
+	{ .temp_c	= 70, .ohm	= 4513 },
+	{ .temp_c	= 75, .ohm	= 3721 },
+	{ .temp_c	= 80, .ohm	= 3084 },
+	{ .temp_c	= 85, .ohm	= 2569 },
+	{ .temp_c	= 90, .ohm	= 2151 },
+	{ .temp_c	= 95, .ohm	= 1809 },
+	{ .temp_c	= 100, .ohm	= 1529 },
+	{ .temp_c	= 105, .ohm	= 1299 },
+	{ .temp_c	= 110, .ohm	= 1108 },
+	{ .temp_c	= 115, .ohm	= 949 },
+	{ .temp_c	= 120, .ohm	= 817 },
+	{ .temp_c	= 125, .ohm	= 707 },
 };
 
 struct ntc_data {
@@ -125,6 +141,92 @@ struct ntc_data {
 	char name[PLATFORM_NAME_SIZE];
 };
 
+#ifdef CONFIG_OF
+static int ntc_adc_iio_read(struct ntc_thermistor_platform_data *pdata)
+{
+	struct iio_channel *channel = pdata->chan;
+	unsigned int result;
+	int val, ret;
+
+	ret = iio_read_channel_raw(channel, &val);
+	if (ret < 0) {
+		pr_err("read channel() error: %d\n", ret);
+		return ret;
+	}
+
+	/* unit: mV */
+	result = pdata->pullup_uv * val;
+	result >>= 12;
+
+	return result;
+}
+
+static const struct of_device_id ntc_match[] = {
+	{ .compatible = "ntc,ncp15wb473",
+		.data = &ntc_thermistor_id[TYPE_NCPXXWB473] },
+	{ .compatible = "ntc,ncp18wb473",
+		.data = &ntc_thermistor_id[TYPE_NCPXXWB473] },
+	{ .compatible = "ntc,ncp21wb473",
+		.data = &ntc_thermistor_id[TYPE_NCPXXWB473] },
+	{ .compatible = "ntc,ncp03wb473",
+		.data = &ntc_thermistor_id[TYPE_NCPXXWB473] },
+	{ .compatible = "ntc,ncp15wl333",
+		.data = &ntc_thermistor_id[TYPE_NCPXXWL333] },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, ntc_match);
+
+static struct ntc_thermistor_platform_data *
+ntc_thermistor_parse_dt(struct platform_device *pdev)
+{
+	struct iio_channel *chan;
+	struct device_node *np = pdev->dev.of_node;
+	struct ntc_thermistor_platform_data *pdata;
+
+	if (!np)
+		return NULL;
+
+	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata)
+		return ERR_PTR(-ENOMEM);
+
+	chan = iio_channel_get(&pdev->dev, NULL);
+	if (IS_ERR(chan))
+		return ERR_CAST(chan);
+
+	if (of_property_read_u32(np, "pullup-uv", &pdata->pullup_uv))
+		return ERR_PTR(-ENODEV);
+	if (of_property_read_u32(np, "pullup-ohm", &pdata->pullup_ohm))
+		return ERR_PTR(-ENODEV);
+	if (of_property_read_u32(np, "pulldown-ohm", &pdata->pulldown_ohm))
+		return ERR_PTR(-ENODEV);
+
+	if (of_find_property(np, "connected-positive", NULL))
+		pdata->connect = NTC_CONNECTED_POSITIVE;
+	else /* status change should be possible if not always on. */
+		pdata->connect = NTC_CONNECTED_GROUND;
+
+	pdata->chan = chan;
+	pdata->read_uv = ntc_adc_iio_read;
+
+	return pdata;
+}
+static void ntc_iio_channel_release(struct ntc_thermistor_platform_data *pdata)
+{
+	if (pdata->chan)
+		iio_channel_release(pdata->chan);
+}
+#else
+static struct ntc_thermistor_platform_data *
+ntc_thermistor_parse_dt(struct platform_device *pdev)
+{
+	return NULL;
+}
+
+static void ntc_iio_channel_release(struct ntc_thermistor_platform_data *pdata)
+{ }
+#endif
+
 static inline u64 div64_u64_safe(u64 dividend, u64 divisor)
 {
 	if (divisor == 0 && dividend == 0)
@@ -134,37 +236,37 @@ static inline u64 div64_u64_safe(u64 dividend, u64 divisor)
 	return div64_u64(dividend, divisor);
 }
 
-static int get_ohm_of_thermistor(struct ntc_data *data, unsigned int uV)
+static int get_ohm_of_thermistor(struct ntc_data *data, unsigned int uv)
 {
 	struct ntc_thermistor_platform_data *pdata = data->pdata;
-	u64 mV = uV / 1000;
-	u64 pmV = pdata->pullup_uV / 1000;
-	u64 N, puO, pdO;
-	puO = pdata->pullup_ohm;
-	pdO = pdata->pulldown_ohm;
+	u64 mv = uv / 1000;
+	u64 pmv = pdata->pullup_uv / 1000;
+	u64 n, puo, pdo;
+	puo = pdata->pullup_ohm;
+	pdo = pdata->pulldown_ohm;
 
-	if (mV == 0) {
+	if (mv == 0) {
 		if (pdata->connect == NTC_CONNECTED_POSITIVE)
 			return INT_MAX;
 		return 0;
 	}
-	if (mV >= pmV)
+	if (mv >= pmv)
 		return (pdata->connect == NTC_CONNECTED_POSITIVE) ?
 			0 : INT_MAX;
 
-	if (pdata->connect == NTC_CONNECTED_POSITIVE && puO == 0)
-		N = div64_u64_safe(pdO * (pmV - mV), mV);
-	else if (pdata->connect == NTC_CONNECTED_GROUND && pdO == 0)
-		N = div64_u64_safe(puO * mV, pmV - mV);
+	if (pdata->connect == NTC_CONNECTED_POSITIVE && puo == 0)
+		n = div64_u64_safe(pdo * (pmv - mv), mv);
+	else if (pdata->connect == NTC_CONNECTED_GROUND && pdo == 0)
+		n = div64_u64_safe(puo * mv, pmv - mv);
 	else if (pdata->connect == NTC_CONNECTED_POSITIVE)
-		N = div64_u64_safe(pdO * puO * (pmV - mV),
-				puO * mV - pdO * (pmV - mV));
+		n = div64_u64_safe(pdo * puo * (pmv - mv),
+				puo * mv - pdo * (pmv - mv));
 	else
-		N = div64_u64_safe(pdO * puO * mV, pdO * (pmV - mV) - puO * mV);
+		n = div64_u64_safe(pdo * puo * mv, pdo * (pmv - mv) - puo * mv);
 
-	if (N > INT_MAX)
-		N = INT_MAX;
-	return N;
+	if (n > INT_MAX)
+		n = INT_MAX;
+	return n;
 }
 
 static void lookup_comp(struct ntc_data *data, unsigned int ohm,
@@ -233,7 +335,7 @@ static void lookup_comp(struct ntc_data *data, unsigned int ohm,
 		*i_high = end - 1;
 }
 
-static int get_temp_mC(struct ntc_data *data, unsigned int ohm)
+static int get_temp_mc(struct ntc_data *data, unsigned int ohm)
 {
 	int low, high;
 	int temp;
@@ -241,10 +343,10 @@ static int get_temp_mC(struct ntc_data *data, unsigned int ohm)
 	lookup_comp(data, ohm, &low, &high);
 	if (low == high) {
 		/* Unable to use linear approximation */
-		temp = data->comp[low].temp_C * 1000;
+		temp = data->comp[low].temp_c * 1000;
 	} else {
-		temp = data->comp[low].temp_C * 1000 +
-			((data->comp[high].temp_C - data->comp[low].temp_C) *
+		temp = data->comp[low].temp_c * 1000 +
+			((data->comp[high].temp_c - data->comp[low].temp_c) *
 			 1000 * ((int)ohm - (int)data->comp[low].ohm)) /
 			((int)data->comp[high].ohm - (int)data->comp[low].ohm);
 	}
@@ -253,16 +355,16 @@ static int get_temp_mC(struct ntc_data *data, unsigned int ohm)
 
 static int ntc_thermistor_get_ohm(struct ntc_data *data)
 {
-	int read_uV;
+	int read_uv;
 
 	if (data->pdata->read_ohm)
 		return data->pdata->read_ohm();
 
-	if (data->pdata->read_uV) {
-		read_uV = data->pdata->read_uV();
-		if (read_uV < 0)
-			return read_uV;
-		return get_ohm_of_thermistor(data, read_uV);
+	if (data->pdata->read_uv) {
+		read_uv = data->pdata->read_uv(data->pdata);
+		if (read_uv < 0)
+			return read_uv;
+		return get_ohm_of_thermistor(data, read_uv);
 	}
 	return -EINVAL;
 }
@@ -291,7 +393,7 @@ static ssize_t ntc_show_temp(struct device *dev,
 	if (ohm < 0)
 		return ohm;
 
-	return sprintf(buf, "%d\n", get_temp_mC(data, ohm));
+	return sprintf(buf, "%d\n", get_temp_mc(data, ohm));
 }
 
 static SENSOR_DEVICE_ATTR(temp1_type, S_IRUGO, ntc_show_type, NULL, 0);
@@ -311,9 +413,18 @@ static const struct attribute_group ntc_attr_group = {
 
 static int ntc_thermistor_probe(struct platform_device *pdev)
 {
+	const struct of_device_id *of_id =
+			of_match_device(of_match_ptr(ntc_match), &pdev->dev);
+	const struct platform_device_id *pdev_id;
+	struct ntc_thermistor_platform_data *pdata;
 	struct ntc_data *data;
-	struct ntc_thermistor_platform_data *pdata = pdev->dev.platform_data;
-	int ret = 0;
+	int ret;
+
+	pdata = ntc_thermistor_parse_dt(pdev);
+	if (IS_ERR(pdata))
+		return PTR_ERR(pdata);
+	else if (pdata == NULL)
+		pdata = pdev->dev.platform_data;
 
 	if (!pdata) {
 		dev_err(&pdev->dev, "No platform init data supplied.\n");
@@ -321,19 +432,19 @@ static int ntc_thermistor_probe(struct platform_device *pdev)
 	}
 
 	/* Either one of the two is required. */
-	if (!pdata->read_uV && !pdata->read_ohm) {
+	if (!pdata->read_uv && !pdata->read_ohm) {
 		dev_err(&pdev->dev,
-			"Both read_uV and read_ohm missing. Need either one of the two.\n");
+			"Both read_uv and read_ohm missing. Need either one of the two.\n");
 		return -EINVAL;
 	}
 
-	if (pdata->read_uV && pdata->read_ohm) {
+	if (pdata->read_uv && pdata->read_ohm) {
 		dev_warn(&pdev->dev,
-			 "Only one of read_uV and read_ohm is needed; ignoring read_uV.\n");
-		pdata->read_uV = NULL;
+			 "Only one of read_uv and read_ohm is needed; ignoring read_uv.\n");
+		pdata->read_uv = NULL;
 	}
 
-	if (pdata->read_uV && (pdata->pullup_uV == 0 ||
+	if (pdata->read_uv && (pdata->pullup_uv == 0 ||
 				(pdata->pullup_ohm == 0 && pdata->connect ==
 				 NTC_CONNECTED_GROUND) ||
 				(pdata->pulldown_ohm == 0 && pdata->connect ==
@@ -341,7 +452,7 @@ static int ntc_thermistor_probe(struct platform_device *pdev)
 				(pdata->connect != NTC_CONNECTED_POSITIVE &&
 				 pdata->connect != NTC_CONNECTED_GROUND))) {
 		dev_err(&pdev->dev,
-			"Required data to use read_uV not supplied.\n");
+			"Required data to use read_uv not supplied.\n");
 		return -EINVAL;
 	}
 
@@ -349,11 +460,13 @@ static int ntc_thermistor_probe(struct platform_device *pdev)
 	if (!data)
 		return -ENOMEM;
 
+	pdev_id = of_id ? of_id->data : platform_get_device_id(pdev);
+
 	data->dev = &pdev->dev;
 	data->pdata = pdata;
-	strlcpy(data->name, pdev->id_entry->name, sizeof(data->name));
+	strlcpy(data->name, pdev_id->name, sizeof(data->name));
 
-	switch (pdev->id_entry->driver_data) {
+	switch (pdev_id->driver_data) {
 	case TYPE_NCPXXWB473:
 		data->comp = ncpXXwb473;
 		data->n_comp = ARRAY_SIZE(ncpXXwb473);
@@ -364,8 +477,7 @@ static int ntc_thermistor_probe(struct platform_device *pdev)
 		break;
 	default:
 		dev_err(&pdev->dev, "Unknown device type: %lu(%s)\n",
-				pdev->id_entry->driver_data,
-				pdev->id_entry->name);
+				pdev_id->driver_data, pdev_id->name);
 		return -EINVAL;
 	}
 
@@ -384,39 +496,34 @@ static int ntc_thermistor_probe(struct platform_device *pdev)
 		goto err_after_sysfs;
 	}
 
-	dev_info(&pdev->dev, "Thermistor %s:%d (type: %s/%lu) successfully probed.\n",
-			pdev->name, pdev->id, pdev->id_entry->name,
-			pdev->id_entry->driver_data);
+	dev_info(&pdev->dev, "Thermistor type: %s successfully probed.\n",
+								pdev->name);
+
 	return 0;
 err_after_sysfs:
 	sysfs_remove_group(&data->dev->kobj, &ntc_attr_group);
+	ntc_iio_channel_release(pdata);
 	return ret;
 }
 
 static int ntc_thermistor_remove(struct platform_device *pdev)
 {
 	struct ntc_data *data = platform_get_drvdata(pdev);
+	struct ntc_thermistor_platform_data *pdata = data->pdata;
 
 	hwmon_device_unregister(data->hwmon_dev);
 	sysfs_remove_group(&data->dev->kobj, &ntc_attr_group);
+	ntc_iio_channel_release(pdata);
 	platform_set_drvdata(pdev, NULL);
 
 	return 0;
 }
 
-static const struct platform_device_id ntc_thermistor_id[] = {
-	{ "ncp15wb473", TYPE_NCPXXWB473 },
-	{ "ncp18wb473", TYPE_NCPXXWB473 },
-	{ "ncp21wb473", TYPE_NCPXXWB473 },
-	{ "ncp03wb473", TYPE_NCPXXWB473 },
-	{ "ncp15wl333", TYPE_NCPXXWL333 },
-	{ },
-};
-
 static struct platform_driver ntc_thermistor_driver = {
 	.driver = {
 		.name = "ntc-thermistor",
 		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(ntc_match),
 	},
 	.probe = ntc_thermistor_probe,
 	.remove = ntc_thermistor_remove,
diff --git a/drivers/hwmon/pc87360.c b/drivers/hwmon/pc87360.c
index e35856b..aa615ba 100644
--- a/drivers/hwmon/pc87360.c
+++ b/drivers/hwmon/pc87360.c
@@ -1190,8 +1190,7 @@ static int __init pc87360_find(int sioaddr, u8 *devid,
 				confreg[3] = superio_inb(sioaddr, 0x25);
 
 				if (confreg[2] & 0x40) {
-					pr_info("Using thermistors for "
-						"temperature monitoring\n");
+					pr_info("Using thermistors for temperature monitoring\n");
 				}
 				if (confreg[3] & 0xE0) {
 					pr_info("VID inputs routed (mode %u)\n",
@@ -1271,9 +1270,9 @@ static int pc87360_probe(struct platform_device *pdev)
 		if (data->address[i]
 		 && !devm_request_region(dev, extra_isa[i], PC87360_EXTENT,
 					 pc87360_driver.driver.name)) {
-			dev_err(dev, "Region 0x%x-0x%x already "
-				"in use!\n", extra_isa[i],
-				extra_isa[i]+PC87360_EXTENT-1);
+			dev_err(dev,
+				"Region 0x%x-0x%x already in use!\n",
+				extra_isa[i], extra_isa[i]+PC87360_EXTENT-1);
 			return -EBUSY;
 		}
 	}
@@ -1435,8 +1434,8 @@ static void pc87360_init_device(struct platform_device *pdev,
 	if (init >= 2 && data->innr) {
 		reg = pc87360_read_value(data, LD_IN, NO_BANK,
 					 PC87365_REG_IN_CONVRATE);
-		dev_info(&pdev->dev, "VLM conversion set to "
-			 "1s period, 160us delay\n");
+		dev_info(&pdev->dev,
+			 "VLM conversion set to 1s period, 160us delay\n");
 		pc87360_write_value(data, LD_IN, NO_BANK,
 				    PC87365_REG_IN_CONVRATE,
 				    (reg & 0xC0) | 0x11);
@@ -1450,8 +1449,8 @@ static void pc87360_init_device(struct platform_device *pdev,
 		if (init >= init_in[i]) {
 			/* Forcibly enable voltage channel */
 			if (!(reg & CHAN_ENA)) {
-				dev_dbg(&pdev->dev, "Forcibly "
-					"enabling in%d\n", i);
+				dev_dbg(&pdev->dev, "Forcibly enabling in%d\n",
+					i);
 				pc87360_write_value(data, LD_IN, i,
 						    PC87365_REG_IN_STATUS,
 						    (reg & 0x68) | 0x87);
@@ -1575,8 +1574,8 @@ static void pc87360_autodiv(struct device *dev, int nr)
 			data->fan_status[nr] += 0x20;
 			data->fan_min[nr] >>= 1;
 			data->fan[nr] >>= 1;
-			dev_dbg(dev, "Increasing "
-				"clock divider to %d for fan %d\n",
+			dev_dbg(dev,
+				"Increasing clock divider to %d for fan %d\n",
 				FAN_DIV_FROM_REG(data->fan_status[nr]), nr + 1);
 		}
 	} else {
@@ -1587,8 +1586,8 @@ static void pc87360_autodiv(struct device *dev, int nr)
 			data->fan_status[nr] -= 0x20;
 			data->fan_min[nr] <<= 1;
 			data->fan[nr] <<= 1;
-			dev_dbg(dev, "Decreasing "
-				"clock divider to %d for fan %d\n",
+			dev_dbg(dev,
+				"Decreasing clock divider to %d for fan %d\n",
 				FAN_DIV_FROM_REG(data->fan_status[nr]),
 				nr + 1);
 		}
diff --git a/drivers/hwmon/pc87427.c b/drivers/hwmon/pc87427.c
index 6086ad0..ea60686 100644
--- a/drivers/hwmon/pc87427.c
+++ b/drivers/hwmon/pc87427.c
@@ -627,8 +627,9 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute
 	pc87427_readall_pwm(data, nr);
 	mode = data->pwm_enable[nr] & PWM_ENABLE_MODE_MASK;
 	if (mode != PWM_MODE_MANUAL && mode != PWM_MODE_OFF) {
-		dev_notice(dev, "Can't set PWM%d duty cycle while not in "
-			   "manual mode\n", nr + 1);
+		dev_notice(dev,
+			   "Can't set PWM%d duty cycle while not in manual mode\n",
+			   nr + 1);
 		mutex_unlock(&data->lock);
 		return -EPERM;
 	}
@@ -1245,16 +1246,16 @@ static int __init pc87427_find(int sioaddr, struct pc87427_sio_data *sio_data)
 
 		val = superio_inb(sioaddr, SIOREG_MAP);
 		if (val & 0x01) {
-			pr_warn("Logical device 0x%02x is memory-mapped, "
-				"can't use\n", logdev[i]);
+			pr_warn("Logical device 0x%02x is memory-mapped, can't use\n",
+				logdev[i]);
 			continue;
 		}
 
 		val = (superio_inb(sioaddr, SIOREG_IOBASE) << 8)
 		    | superio_inb(sioaddr, SIOREG_IOBASE + 1);
 		if (!val) {
-			pr_info("I/O base address not set for logical device "
-				"0x%02x\n", logdev[i]);
+			pr_info("I/O base address not set for logical device 0x%02x\n",
+				logdev[i]);
 			continue;
 		}
 		sio_data->address[i] = val;
diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig
index 4f9eb0a..39cc63e 100644
--- a/drivers/hwmon/pmbus/Kconfig
+++ b/drivers/hwmon/pmbus/Kconfig
@@ -42,17 +42,17 @@ config SENSORS_LM25066
 	default n
 	help
 	  If you say yes here you get hardware monitoring support for National
-	  Semiconductor LM25066, LM5064, and LM5066.
+	  Semiconductor LM25056, LM25066, LM5064, and LM5066.
 
 	  This driver can also be built as a module. If so, the module will
 	  be called lm25066.
 
 config SENSORS_LTC2978
-	tristate "Linear Technologies LTC2978 and LTC3880"
+	tristate "Linear Technologies LTC2974, LTC2978, LTC3880, and LTC3883"
 	default n
 	help
 	  If you say yes here you get hardware monitoring support for Linear
-	  Technology LTC2978 and LTC3880.
+	  Technology LTC2974, LTC2978, LTC3880, and LTC3883.
 
 	  This driver can also be built as a module. If so, the module will
 	  be called ltc2978.
diff --git a/drivers/hwmon/pmbus/lm25066.c b/drivers/hwmon/pmbus/lm25066.c
index c299392..6a9d6ed 100644
--- a/drivers/hwmon/pmbus/lm25066.c
+++ b/drivers/hwmon/pmbus/lm25066.c
@@ -1,7 +1,8 @@
 /*
- * Hardware monitoring driver for LM25066 / LM5064 / LM5066
+ * Hardware monitoring driver for LM25056 / LM25066 / LM5064 / LM5066
  *
  * Copyright (c) 2011 Ericsson AB.
+ * Copyright (c) 2013 Guenter Roeck
  *
  * This 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,7 +27,7 @@
 #include <linux/i2c.h>
 #include "pmbus.h"
 
-enum chips { lm25066, lm5064, lm5066 };
+enum chips { lm25056, lm25066, lm5064, lm5066 };
 
 #define LM25066_READ_VAUX		0xd0
 #define LM25066_MFR_READ_IIN		0xd1
@@ -43,6 +44,138 @@ enum chips { lm25066, lm5064, lm5066 };
 
 #define LM25066_DEV_SETUP_CL		(1 << 4)	/* Current limit */
 
+/* LM25056 only */
+
+#define LM25056_VAUX_OV_WARN_LIMIT	0xe3
+#define LM25056_VAUX_UV_WARN_LIMIT	0xe4
+
+#define LM25056_MFR_STS_VAUX_OV_WARN	(1 << 1)
+#define LM25056_MFR_STS_VAUX_UV_WARN	(1 << 0)
+
+struct __coeff {
+	short m, b, R;
+};
+
+#define PSC_CURRENT_IN_L	(PSC_NUM_CLASSES)
+#define PSC_POWER_L		(PSC_NUM_CLASSES + 1)
+
+static struct __coeff lm25066_coeff[4][PSC_NUM_CLASSES + 2] = {
+	[lm25056] = {
+		[PSC_VOLTAGE_IN] = {
+			.m = 16296,
+			.R = -2,
+		},
+		[PSC_CURRENT_IN] = {
+			.m = 13797,
+			.R = -2,
+		},
+		[PSC_CURRENT_IN_L] = {
+			.m = 6726,
+			.R = -2,
+		},
+		[PSC_POWER] = {
+			.m = 5501,
+			.R = -3,
+		},
+		[PSC_POWER_L] = {
+			.m = 26882,
+			.R = -4,
+		},
+		[PSC_TEMPERATURE] = {
+			.m = 1580,
+			.b = -14500,
+			.R = -2,
+		},
+	},
+	[lm25066] = {
+		[PSC_VOLTAGE_IN] = {
+			.m = 22070,
+			.R = -2,
+		},
+		[PSC_VOLTAGE_OUT] = {
+			.m = 22070,
+			.R = -2,
+		},
+		[PSC_CURRENT_IN] = {
+			.m = 13661,
+			.R = -2,
+		},
+		[PSC_CURRENT_IN_L] = {
+			.m = 6852,
+			.R = -2,
+		},
+		[PSC_POWER] = {
+			.m = 736,
+			.R = -2,
+		},
+		[PSC_POWER_L] = {
+			.m = 369,
+			.R = -2,
+		},
+		[PSC_TEMPERATURE] = {
+			.m = 16,
+		},
+	},
+	[lm5064] = {
+		[PSC_VOLTAGE_IN] = {
+			.m = 4611,
+			.R = -2,
+		},
+		[PSC_VOLTAGE_OUT] = {
+			.m = 4621,
+			.R = -2,
+		},
+		[PSC_CURRENT_IN] = {
+			.m = 10742,
+			.R = -2,
+		},
+		[PSC_CURRENT_IN_L] = {
+			.m = 5456,
+			.R = -2,
+		},
+		[PSC_POWER] = {
+			.m = 1204,
+			.R = -3,
+		},
+		[PSC_POWER_L] = {
+			.m = 612,
+			.R = -3,
+		},
+		[PSC_TEMPERATURE] = {
+			.m = 16,
+		},
+	},
+	[lm5066] = {
+		[PSC_VOLTAGE_IN] = {
+			.m = 4587,
+			.R = -2,
+		},
+		[PSC_VOLTAGE_OUT] = {
+			.m = 4587,
+			.R = -2,
+		},
+		[PSC_CURRENT_IN] = {
+			.m = 10753,
+			.R = -2,
+		},
+		[PSC_CURRENT_IN_L] = {
+			.m = 5405,
+			.R = -2,
+		},
+		[PSC_POWER] = {
+			.m = 1204,
+			.R = -3,
+		},
+		[PSC_POWER_L] = {
+			.m = 605,
+			.R = -3,
+		},
+		[PSC_TEMPERATURE] = {
+			.m = 16,
+		},
+	},
+};
+
 struct lm25066_data {
 	int id;
 	struct pmbus_driver_info info;
@@ -56,42 +189,31 @@ static int lm25066_read_word_data(struct i2c_client *client, int page, int reg)
 	const struct lm25066_data *data = to_lm25066_data(info);
 	int ret;
 
-	if (page > 1)
-		return -ENXIO;
-
-	/* Map READ_VAUX into READ_VOUT register on page 1 */
-	if (page == 1) {
-		switch (reg) {
-		case PMBUS_READ_VOUT:
-			ret = pmbus_read_word_data(client, 0,
-						   LM25066_READ_VAUX);
-			if (ret < 0)
-				break;
-			/* Adjust returned value to match VOUT coefficients */
-			switch (data->id) {
-			case lm25066:
-				/* VOUT: 4.54 mV VAUX: 283.2 uV LSB */
-				ret = DIV_ROUND_CLOSEST(ret * 2832, 45400);
-				break;
-			case lm5064:
-				/* VOUT: 4.53 mV VAUX: 700 uV LSB */
-				ret = DIV_ROUND_CLOSEST(ret * 70, 453);
-				break;
-			case lm5066:
-				/* VOUT: 2.18 mV VAUX: 725 uV LSB */
-				ret = DIV_ROUND_CLOSEST(ret * 725, 2180);
-				break;
-			}
+	switch (reg) {
+	case PMBUS_VIRT_READ_VMON:
+		ret = pmbus_read_word_data(client, 0, LM25066_READ_VAUX);
+		if (ret < 0)
+			break;
+		/* Adjust returned value to match VIN coefficients */
+		switch (data->id) {
+		case lm25056:
+			/* VIN: 6.14 mV VAUX: 293 uV LSB */
+			ret = DIV_ROUND_CLOSEST(ret * 293, 6140);
 			break;
-		default:
-			/* No other valid registers on page 1 */
-			ret = -ENXIO;
+		case lm25066:
+			/* VIN: 4.54 mV VAUX: 283.2 uV LSB */
+			ret = DIV_ROUND_CLOSEST(ret * 2832, 45400);
+			break;
+		case lm5064:
+			/* VIN: 4.53 mV VAUX: 700 uV LSB */
+			ret = DIV_ROUND_CLOSEST(ret * 70, 453);
+			break;
+		case lm5066:
+			/* VIN: 2.18 mV VAUX: 725 uV LSB */
+			ret = DIV_ROUND_CLOSEST(ret * 725, 2180);
 			break;
 		}
-		goto done;
-	}
-
-	switch (reg) {
+		break;
 	case PMBUS_READ_IIN:
 		ret = pmbus_read_word_data(client, 0, LM25066_MFR_READ_IIN);
 		break;
@@ -128,7 +250,58 @@ static int lm25066_read_word_data(struct i2c_client *client, int page, int reg)
 		ret = -ENODATA;
 		break;
 	}
-done:
+	return ret;
+}
+
+static int lm25056_read_word_data(struct i2c_client *client, int page, int reg)
+{
+	int ret;
+
+	switch (reg) {
+	case PMBUS_VIRT_VMON_UV_WARN_LIMIT:
+		ret = pmbus_read_word_data(client, 0,
+					   LM25056_VAUX_UV_WARN_LIMIT);
+		if (ret < 0)
+			break;
+		/* Adjust returned value to match VIN coefficients */
+		ret = DIV_ROUND_CLOSEST(ret * 293, 6140);
+		break;
+	case PMBUS_VIRT_VMON_OV_WARN_LIMIT:
+		ret = pmbus_read_word_data(client, 0,
+					   LM25056_VAUX_OV_WARN_LIMIT);
+		if (ret < 0)
+			break;
+		/* Adjust returned value to match VIN coefficients */
+		ret = DIV_ROUND_CLOSEST(ret * 293, 6140);
+		break;
+	default:
+		ret = lm25066_read_word_data(client, page, reg);
+		break;
+	}
+	return ret;
+}
+
+static int lm25056_read_byte_data(struct i2c_client *client, int page, int reg)
+{
+	int ret, s;
+
+	switch (reg) {
+	case PMBUS_VIRT_STATUS_VMON:
+		ret = pmbus_read_byte_data(client, 0,
+					   PMBUS_STATUS_MFR_SPECIFIC);
+		if (ret < 0)
+			break;
+		s = 0;
+		if (ret & LM25056_MFR_STS_VAUX_UV_WARN)
+			s |= PB_VOLTAGE_UV_WARNING;
+		if (ret & LM25056_MFR_STS_VAUX_OV_WARN)
+			s |= PB_VOLTAGE_OV_WARNING;
+		ret = s;
+		break;
+	default:
+		ret = -ENODATA;
+		break;
+	}
 	return ret;
 }
 
@@ -137,19 +310,45 @@ static int lm25066_write_word_data(struct i2c_client *client, int page, int reg,
 {
 	int ret;
 
-	if (page > 1)
-		return -ENXIO;
-
 	switch (reg) {
+	case PMBUS_VOUT_UV_WARN_LIMIT:
+	case PMBUS_OT_FAULT_LIMIT:
+	case PMBUS_OT_WARN_LIMIT:
+	case PMBUS_VIN_UV_WARN_LIMIT:
+	case PMBUS_VIN_OV_WARN_LIMIT:
+		word = ((s16)word < 0) ? 0 : clamp_val(word, 0, 0x0fff);
+		ret = pmbus_write_word_data(client, 0, reg, word);
+		pmbus_clear_cache(client);
+		break;
 	case PMBUS_IIN_OC_WARN_LIMIT:
+		word = ((s16)word < 0) ? 0 : clamp_val(word, 0, 0x0fff);
 		ret = pmbus_write_word_data(client, 0,
 					    LM25066_MFR_IIN_OC_WARN_LIMIT,
 					    word);
+		pmbus_clear_cache(client);
 		break;
 	case PMBUS_PIN_OP_WARN_LIMIT:
+		word = ((s16)word < 0) ? 0 : clamp_val(word, 0, 0x0fff);
 		ret = pmbus_write_word_data(client, 0,
 					    LM25066_MFR_PIN_OP_WARN_LIMIT,
 					    word);
+		pmbus_clear_cache(client);
+		break;
+	case PMBUS_VIRT_VMON_UV_WARN_LIMIT:
+		/* Adjust from VIN coefficients (for LM25056) */
+		word = DIV_ROUND_CLOSEST((int)word * 6140, 293);
+		word = ((s16)word < 0) ? 0 : clamp_val(word, 0, 0x0fff);
+		ret = pmbus_write_word_data(client, 0,
+					    LM25056_VAUX_UV_WARN_LIMIT, word);
+		pmbus_clear_cache(client);
+		break;
+	case PMBUS_VIRT_VMON_OV_WARN_LIMIT:
+		/* Adjust from VIN coefficients (for LM25056) */
+		word = DIV_ROUND_CLOSEST((int)word * 6140, 293);
+		word = ((s16)word < 0) ? 0 : clamp_val(word, 0, 0x0fff);
+		ret = pmbus_write_word_data(client, 0,
+					    LM25056_VAUX_OV_WARN_LIMIT, word);
+		pmbus_clear_cache(client);
 		break;
 	case PMBUS_VIRT_RESET_PIN_HISTORY:
 		ret = pmbus_write_byte(client, 0, LM25066_CLEAR_PIN_PEAK);
@@ -161,23 +360,13 @@ static int lm25066_write_word_data(struct i2c_client *client, int page, int reg,
 	return ret;
 }
 
-static int lm25066_write_byte(struct i2c_client *client, int page, u8 value)
-{
-	if (page > 1)
-		return -ENXIO;
-
-	if (page <= 0)
-		return pmbus_write_byte(client, page, value);
-
-	return 0;
-}
-
 static int lm25066_probe(struct i2c_client *client,
 			  const struct i2c_device_id *id)
 {
 	int config;
 	struct lm25066_data *data;
 	struct pmbus_driver_info *info;
+	struct __coeff *coeff;
 
 	if (!i2c_check_functionality(client->adapter,
 				     I2C_FUNC_SMBUS_READ_BYTE_DATA))
@@ -195,107 +384,54 @@ static int lm25066_probe(struct i2c_client *client,
 	data->id = id->driver_data;
 	info = &data->info;
 
-	info->pages = 2;
+	info->pages = 1;
 	info->format[PSC_VOLTAGE_IN] = direct;
 	info->format[PSC_VOLTAGE_OUT] = direct;
 	info->format[PSC_CURRENT_IN] = direct;
 	info->format[PSC_TEMPERATURE] = direct;
 	info->format[PSC_POWER] = direct;
 
-	info->m[PSC_TEMPERATURE] = 16;
-	info->b[PSC_TEMPERATURE] = 0;
-	info->R[PSC_TEMPERATURE] = 0;
-
-	info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT
-	  | PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_PIN | PMBUS_HAVE_IIN
-	  | PMBUS_HAVE_STATUS_INPUT | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;
-	info->func[1] = PMBUS_HAVE_VOUT;
-
-	info->read_word_data = lm25066_read_word_data;
+	info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VMON
+	  | PMBUS_HAVE_PIN | PMBUS_HAVE_IIN | PMBUS_HAVE_STATUS_INPUT
+	  | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;
+
+	if (data->id == lm25056) {
+		info->func[0] |= PMBUS_HAVE_STATUS_VMON;
+		info->read_word_data = lm25056_read_word_data;
+		info->read_byte_data = lm25056_read_byte_data;
+	} else {
+		info->func[0] |= PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT;
+		info->read_word_data = lm25066_read_word_data;
+	}
 	info->write_word_data = lm25066_write_word_data;
-	info->write_byte = lm25066_write_byte;
-
-	switch (id->driver_data) {
-	case lm25066:
-		info->m[PSC_VOLTAGE_IN] = 22070;
-		info->b[PSC_VOLTAGE_IN] = 0;
-		info->R[PSC_VOLTAGE_IN] = -2;
-		info->m[PSC_VOLTAGE_OUT] = 22070;
-		info->b[PSC_VOLTAGE_OUT] = 0;
-		info->R[PSC_VOLTAGE_OUT] = -2;
-
-		if (config & LM25066_DEV_SETUP_CL) {
-			info->m[PSC_CURRENT_IN] = 6852;
-			info->b[PSC_CURRENT_IN] = 0;
-			info->R[PSC_CURRENT_IN] = -2;
-			info->m[PSC_POWER] = 369;
-			info->b[PSC_POWER] = 0;
-			info->R[PSC_POWER] = -2;
-		} else {
-			info->m[PSC_CURRENT_IN] = 13661;
-			info->b[PSC_CURRENT_IN] = 0;
-			info->R[PSC_CURRENT_IN] = -2;
-			info->m[PSC_POWER] = 736;
-			info->b[PSC_POWER] = 0;
-			info->R[PSC_POWER] = -2;
-		}
-		break;
-	case lm5064:
-		info->m[PSC_VOLTAGE_IN] = 22075;
-		info->b[PSC_VOLTAGE_IN] = 0;
-		info->R[PSC_VOLTAGE_IN] = -2;
-		info->m[PSC_VOLTAGE_OUT] = 22075;
-		info->b[PSC_VOLTAGE_OUT] = 0;
-		info->R[PSC_VOLTAGE_OUT] = -2;
-
-		if (config & LM25066_DEV_SETUP_CL) {
-			info->m[PSC_CURRENT_IN] = 6713;
-			info->b[PSC_CURRENT_IN] = 0;
-			info->R[PSC_CURRENT_IN] = -2;
-			info->m[PSC_POWER] = 3619;
-			info->b[PSC_POWER] = 0;
-			info->R[PSC_POWER] = -3;
-		} else {
-			info->m[PSC_CURRENT_IN] = 13426;
-			info->b[PSC_CURRENT_IN] = 0;
-			info->R[PSC_CURRENT_IN] = -2;
-			info->m[PSC_POWER] = 7238;
-			info->b[PSC_POWER] = 0;
-			info->R[PSC_POWER] = -3;
-		}
-		break;
-	case lm5066:
-		info->m[PSC_VOLTAGE_IN] = 4587;
-		info->b[PSC_VOLTAGE_IN] = 0;
-		info->R[PSC_VOLTAGE_IN] = -2;
-		info->m[PSC_VOLTAGE_OUT] = 4587;
-		info->b[PSC_VOLTAGE_OUT] = 0;
-		info->R[PSC_VOLTAGE_OUT] = -2;
-
-		if (config & LM25066_DEV_SETUP_CL) {
-			info->m[PSC_CURRENT_IN] = 10753;
-			info->b[PSC_CURRENT_IN] = 0;
-			info->R[PSC_CURRENT_IN] = -2;
-			info->m[PSC_POWER] = 1204;
-			info->b[PSC_POWER] = 0;
-			info->R[PSC_POWER] = -3;
-		} else {
-			info->m[PSC_CURRENT_IN] = 5405;
-			info->b[PSC_CURRENT_IN] = 0;
-			info->R[PSC_CURRENT_IN] = -2;
-			info->m[PSC_POWER] = 605;
-			info->b[PSC_POWER] = 0;
-			info->R[PSC_POWER] = -3;
-		}
-		break;
-	default:
-		return -ENODEV;
+
+	coeff = &lm25066_coeff[data->id][0];
+	info->m[PSC_TEMPERATURE] = coeff[PSC_TEMPERATURE].m;
+	info->b[PSC_TEMPERATURE] = coeff[PSC_TEMPERATURE].b;
+	info->R[PSC_TEMPERATURE] = coeff[PSC_TEMPERATURE].R;
+	info->m[PSC_VOLTAGE_IN] = coeff[PSC_VOLTAGE_IN].m;
+	info->b[PSC_VOLTAGE_IN] = coeff[PSC_VOLTAGE_IN].b;
+	info->R[PSC_VOLTAGE_IN] = coeff[PSC_VOLTAGE_IN].R;
+	info->m[PSC_VOLTAGE_OUT] = coeff[PSC_VOLTAGE_OUT].m;
+	info->b[PSC_VOLTAGE_OUT] = coeff[PSC_VOLTAGE_OUT].b;
+	info->R[PSC_VOLTAGE_OUT] = coeff[PSC_VOLTAGE_OUT].R;
+	info->b[PSC_CURRENT_IN] = coeff[PSC_CURRENT_IN].b;
+	info->R[PSC_CURRENT_IN] = coeff[PSC_CURRENT_IN].R;
+	info->b[PSC_POWER] = coeff[PSC_POWER].b;
+	info->R[PSC_POWER] = coeff[PSC_POWER].R;
+	if (config & LM25066_DEV_SETUP_CL) {
+		info->m[PSC_CURRENT_IN] = coeff[PSC_CURRENT_IN_L].m;
+		info->m[PSC_POWER] = coeff[PSC_POWER_L].m;
+	} else {
+		info->m[PSC_CURRENT_IN] = coeff[PSC_CURRENT_IN].m;
+		info->m[PSC_POWER] = coeff[PSC_POWER].m;
 	}
 
 	return pmbus_do_probe(client, id, info);
 }
 
 static const struct i2c_device_id lm25066_id[] = {
+	{"lm25056", lm25056},
 	{"lm25066", lm25066},
 	{"lm5064", lm5064},
 	{"lm5066", lm5066},
@@ -317,5 +453,5 @@ static struct i2c_driver lm25066_driver = {
 module_i2c_driver(lm25066_driver);
 
 MODULE_AUTHOR("Guenter Roeck");
-MODULE_DESCRIPTION("PMBus driver for LM25066/LM5064/LM5066");
+MODULE_DESCRIPTION("PMBus driver for LM25056/LM25066/LM5064/LM5066");
 MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/pmbus/ltc2978.c b/drivers/hwmon/pmbus/ltc2978.c
index 6d61307..586a89e 100644
--- a/drivers/hwmon/pmbus/ltc2978.c
+++ b/drivers/hwmon/pmbus/ltc2978.c
@@ -1,7 +1,8 @@
 /*
- * Hardware monitoring driver for LTC2978 and LTC3880
+ * Hardware monitoring driver for LTC2974, LTC2978, LTC3880, and LTC3883
  *
  * Copyright (c) 2011 Ericsson AB.
+ * Copyright (c) 2013 Guenter Roeck
  *
  * This 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,28 +27,43 @@
 #include <linux/i2c.h>
 #include "pmbus.h"
 
-enum chips { ltc2978, ltc3880 };
+enum chips { ltc2974, ltc2978, ltc3880, ltc3883 };
 
-/* LTC2978 and LTC3880 */
+/* Common for all chips */
 #define LTC2978_MFR_VOUT_PEAK		0xdd
 #define LTC2978_MFR_VIN_PEAK		0xde
 #define LTC2978_MFR_TEMPERATURE_PEAK	0xdf
 #define LTC2978_MFR_SPECIAL_ID		0xe7
 
-/* LTC2978 only */
+/* LTC2974 and LTC2978 */
 #define LTC2978_MFR_VOUT_MIN		0xfb
 #define LTC2978_MFR_VIN_MIN		0xfc
 #define LTC2978_MFR_TEMPERATURE_MIN	0xfd
 
-/* LTC3880 only */
+/* LTC2974 only */
+#define LTC2974_MFR_IOUT_PEAK		0xd7
+#define LTC2974_MFR_IOUT_MIN		0xd8
+
+/* LTC3880 and LTC3883 */
 #define LTC3880_MFR_IOUT_PEAK		0xd7
 #define LTC3880_MFR_CLEAR_PEAKS		0xe3
 #define LTC3880_MFR_TEMPERATURE2_PEAK	0xf4
 
+/* LTC3883 only */
+#define LTC3883_MFR_IIN_PEAK		0xe1
+
+#define LTC2974_ID			0x0212
 #define LTC2978_ID_REV1			0x0121
 #define LTC2978_ID_REV2			0x0122
 #define LTC3880_ID			0x4000
 #define LTC3880_ID_MASK			0xff00
+#define LTC3883_ID			0x4300
+#define LTC3883_ID_MASK			0xff00
+
+#define LTC2974_NUM_PAGES		4
+#define LTC2978_NUM_PAGES		8
+#define LTC3880_NUM_PAGES		2
+#define LTC3883_NUM_PAGES		1
 
 /*
  * LTC2978 clears peak data whenever the CLEAR_FAULTS command is executed, which
@@ -56,13 +72,15 @@ enum chips { ltc2978, ltc3880 };
  * internal cache of measured peak data, which is only cleared if an explicit
  * "clear peak" command is executed for the sensor in question.
  */
+
 struct ltc2978_data {
 	enum chips id;
-	int vin_min, vin_max;
-	int temp_min, temp_max[2];
-	int vout_min[8], vout_max[8];
-	int iout_max[2];
-	int temp2_max;
+	u16 vin_min, vin_max;
+	u16 temp_min[LTC2974_NUM_PAGES], temp_max[LTC2974_NUM_PAGES];
+	u16 vout_min[LTC2978_NUM_PAGES], vout_max[LTC2978_NUM_PAGES];
+	u16 iout_min[LTC2974_NUM_PAGES], iout_max[LTC2974_NUM_PAGES];
+	u16 iin_max;
+	u16 temp2_max;
 	struct pmbus_driver_info info;
 };
 
@@ -167,9 +185,9 @@ static int ltc2978_read_word_data(struct i2c_client *client, int page, int reg)
 					   LTC2978_MFR_TEMPERATURE_MIN);
 		if (ret >= 0) {
 			if (lin11_to_val(ret)
-			    < lin11_to_val(data->temp_min))
-				data->temp_min = ret;
-			ret = data->temp_min;
+			    < lin11_to_val(data->temp_min[page]))
+				data->temp_min[page] = ret;
+			ret = data->temp_min[page];
 		}
 		break;
 	case PMBUS_VIRT_READ_IOUT_MAX:
@@ -185,6 +203,41 @@ static int ltc2978_read_word_data(struct i2c_client *client, int page, int reg)
 	return ret;
 }
 
+static int ltc2974_read_word_data(struct i2c_client *client, int page, int reg)
+{
+	const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+	struct ltc2978_data *data = to_ltc2978_data(info);
+	int ret;
+
+	switch (reg) {
+	case PMBUS_VIRT_READ_IOUT_MAX:
+		ret = pmbus_read_word_data(client, page, LTC2974_MFR_IOUT_PEAK);
+		if (ret >= 0) {
+			if (lin11_to_val(ret)
+			    > lin11_to_val(data->iout_max[page]))
+				data->iout_max[page] = ret;
+			ret = data->iout_max[page];
+		}
+		break;
+	case PMBUS_VIRT_READ_IOUT_MIN:
+		ret = pmbus_read_word_data(client, page, LTC2974_MFR_IOUT_MIN);
+		if (ret >= 0) {
+			if (lin11_to_val(ret)
+			    < lin11_to_val(data->iout_min[page]))
+				data->iout_min[page] = ret;
+			ret = data->iout_min[page];
+		}
+		break;
+	case PMBUS_VIRT_RESET_IOUT_HISTORY:
+		ret = 0;
+		break;
+	default:
+		ret = ltc2978_read_word_data(client, page, reg);
+		break;
+	}
+	return ret;
+}
+
 static int ltc3880_read_word_data(struct i2c_client *client, int page, int reg)
 {
 	const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
@@ -226,15 +279,41 @@ static int ltc3880_read_word_data(struct i2c_client *client, int page, int reg)
 	return ret;
 }
 
+static int ltc3883_read_word_data(struct i2c_client *client, int page, int reg)
+{
+	const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+	struct ltc2978_data *data = to_ltc2978_data(info);
+	int ret;
+
+	switch (reg) {
+	case PMBUS_VIRT_READ_IIN_MAX:
+		ret = pmbus_read_word_data(client, page, LTC3883_MFR_IIN_PEAK);
+		if (ret >= 0) {
+			if (lin11_to_val(ret)
+			    > lin11_to_val(data->iin_max))
+				data->iin_max = ret;
+			ret = data->iin_max;
+		}
+		break;
+	case PMBUS_VIRT_RESET_IIN_HISTORY:
+		ret = 0;
+		break;
+	default:
+		ret = ltc3880_read_word_data(client, page, reg);
+		break;
+	}
+	return ret;
+}
+
 static int ltc2978_clear_peaks(struct i2c_client *client, int page,
 			       enum chips id)
 {
 	int ret;
 
-	if (id == ltc2978)
-		ret = pmbus_write_byte(client, page, PMBUS_CLEAR_FAULTS);
-	else
+	if (id == ltc3880 || id == ltc3883)
 		ret = pmbus_write_byte(client, 0, LTC3880_MFR_CLEAR_PEAKS);
+	else
+		ret = pmbus_write_byte(client, page, PMBUS_CLEAR_FAULTS);
 
 	return ret;
 }
@@ -247,8 +326,13 @@ static int ltc2978_write_word_data(struct i2c_client *client, int page,
 	int ret;
 
 	switch (reg) {
+	case PMBUS_VIRT_RESET_IIN_HISTORY:
+		data->iin_max = 0x7c00;
+		ret = ltc2978_clear_peaks(client, page, data->id);
+		break;
 	case PMBUS_VIRT_RESET_IOUT_HISTORY:
 		data->iout_max[page] = 0x7c00;
+		data->iout_min[page] = 0xfbff;
 		ret = ltc2978_clear_peaks(client, page, data->id);
 		break;
 	case PMBUS_VIRT_RESET_TEMP2_HISTORY:
@@ -266,7 +350,7 @@ static int ltc2978_write_word_data(struct i2c_client *client, int page,
 		ret = ltc2978_clear_peaks(client, page, data->id);
 		break;
 	case PMBUS_VIRT_RESET_TEMP_HISTORY:
-		data->temp_min = 0x7bff;
+		data->temp_min[page] = 0x7bff;
 		data->temp_max[page] = 0x7c00;
 		ret = ltc2978_clear_peaks(client, page, data->id);
 		break;
@@ -278,8 +362,10 @@ static int ltc2978_write_word_data(struct i2c_client *client, int page,
 }
 
 static const struct i2c_device_id ltc2978_id[] = {
+	{"ltc2974", ltc2974},
 	{"ltc2978", ltc2978},
 	{"ltc3880", ltc3880},
+	{"ltc3883", ltc3883},
 	{}
 };
 MODULE_DEVICE_TABLE(i2c, ltc2978_id);
@@ -304,10 +390,14 @@ static int ltc2978_probe(struct i2c_client *client,
 	if (chip_id < 0)
 		return chip_id;
 
-	if (chip_id == LTC2978_ID_REV1 || chip_id == LTC2978_ID_REV2) {
+	if (chip_id == LTC2974_ID) {
+		data->id = ltc2974;
+	} else if (chip_id == LTC2978_ID_REV1 || chip_id == LTC2978_ID_REV2) {
 		data->id = ltc2978;
 	} else if ((chip_id & LTC3880_ID_MASK) == LTC3880_ID) {
 		data->id = ltc3880;
+	} else if ((chip_id & LTC3883_ID_MASK) == LTC3883_ID) {
+		data->id = ltc3883;
 	} else {
 		dev_err(&client->dev, "Unsupported chip ID 0x%x\n", chip_id);
 		return -ENODEV;
@@ -323,26 +413,45 @@ static int ltc2978_probe(struct i2c_client *client,
 
 	data->vin_min = 0x7bff;
 	data->vin_max = 0x7c00;
-	data->temp_min = 0x7bff;
+	for (i = 0; i < ARRAY_SIZE(data->vout_min); i++)
+		data->vout_min[i] = 0xffff;
+	for (i = 0; i < ARRAY_SIZE(data->iout_min); i++)
+		data->iout_min[i] = 0xfbff;
+	for (i = 0; i < ARRAY_SIZE(data->iout_max); i++)
+		data->iout_max[i] = 0x7c00;
+	for (i = 0; i < ARRAY_SIZE(data->temp_min); i++)
+		data->temp_min[i] = 0x7bff;
 	for (i = 0; i < ARRAY_SIZE(data->temp_max); i++)
 		data->temp_max[i] = 0x7c00;
 	data->temp2_max = 0x7c00;
 
 	switch (data->id) {
+	case ltc2974:
+		info->read_word_data = ltc2974_read_word_data;
+		info->pages = LTC2974_NUM_PAGES;
+		info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT
+		  | PMBUS_HAVE_TEMP2;
+		for (i = 0; i < info->pages; i++) {
+			info->func[i] |= PMBUS_HAVE_VOUT
+			  | PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_POUT
+			  | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP
+			  | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT;
+		}
+		break;
 	case ltc2978:
 		info->read_word_data = ltc2978_read_word_data;
-		info->pages = 8;
+		info->pages = LTC2978_NUM_PAGES;
 		info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT
 		  | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
 		  | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;
-		for (i = 1; i < 8; i++) {
+		for (i = 1; i < LTC2978_NUM_PAGES; i++) {
 			info->func[i] = PMBUS_HAVE_VOUT
 			  | PMBUS_HAVE_STATUS_VOUT;
 		}
 		break;
 	case ltc3880:
 		info->read_word_data = ltc3880_read_word_data;
-		info->pages = 2;
+		info->pages = LTC3880_NUM_PAGES;
 		info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_IIN
 		  | PMBUS_HAVE_STATUS_INPUT
 		  | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
@@ -353,15 +462,20 @@ static int ltc2978_probe(struct i2c_client *client,
 		  | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT
 		  | PMBUS_HAVE_POUT
 		  | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;
-		data->iout_max[0] = 0x7c00;
-		data->iout_max[1] = 0x7c00;
+		break;
+	case ltc3883:
+		info->read_word_data = ltc3883_read_word_data;
+		info->pages = LTC3883_NUM_PAGES;
+		info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_IIN
+		  | PMBUS_HAVE_STATUS_INPUT
+		  | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
+		  | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT
+		  | PMBUS_HAVE_PIN | PMBUS_HAVE_POUT | PMBUS_HAVE_TEMP
+		  | PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP;
 		break;
 	default:
 		return -ENODEV;
 	}
-	for (i = 0; i < info->pages; i++)
-		data->vout_min[i] = 0xffff;
-
 	return pmbus_do_probe(client, id, info);
 }
 
@@ -378,5 +492,5 @@ static struct i2c_driver ltc2978_driver = {
 module_i2c_driver(ltc2978_driver);
 
 MODULE_AUTHOR("Guenter Roeck");
-MODULE_DESCRIPTION("PMBus driver for LTC2978 and LTC3880");
+MODULE_DESCRIPTION("PMBus driver for LTC2974, LTC2978, LTC3880, and LTC3883");
 MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/s3c-hwmon.c b/drivers/hwmon/s3c-hwmon.c
index ff2ae02..a9f7e80 100644
--- a/drivers/hwmon/s3c-hwmon.c
+++ b/drivers/hwmon/s3c-hwmon.c
@@ -107,17 +107,14 @@ static ssize_t s3c_hwmon_show_raw(struct device *dev,
 	return  (ret < 0) ? ret : snprintf(buf, PAGE_SIZE, "%d\n", ret);
 }
 
-#define DEF_ADC_ATTR(x)	\
-	static SENSOR_DEVICE_ATTR(adc##x##_raw, S_IRUGO, s3c_hwmon_show_raw, NULL, x)
-
-DEF_ADC_ATTR(0);
-DEF_ADC_ATTR(1);
-DEF_ADC_ATTR(2);
-DEF_ADC_ATTR(3);
-DEF_ADC_ATTR(4);
-DEF_ADC_ATTR(5);
-DEF_ADC_ATTR(6);
-DEF_ADC_ATTR(7);
+static SENSOR_DEVICE_ATTR(adc0_raw, S_IRUGO, s3c_hwmon_show_raw, NULL, 0);
+static SENSOR_DEVICE_ATTR(adc1_raw, S_IRUGO, s3c_hwmon_show_raw, NULL, 1);
+static SENSOR_DEVICE_ATTR(adc2_raw, S_IRUGO, s3c_hwmon_show_raw, NULL, 2);
+static SENSOR_DEVICE_ATTR(adc3_raw, S_IRUGO, s3c_hwmon_show_raw, NULL, 3);
+static SENSOR_DEVICE_ATTR(adc4_raw, S_IRUGO, s3c_hwmon_show_raw, NULL, 4);
+static SENSOR_DEVICE_ATTR(adc5_raw, S_IRUGO, s3c_hwmon_show_raw, NULL, 5);
+static SENSOR_DEVICE_ATTR(adc6_raw, S_IRUGO, s3c_hwmon_show_raw, NULL, 6);
+static SENSOR_DEVICE_ATTR(adc7_raw, S_IRUGO, s3c_hwmon_show_raw, NULL, 7);
 
 static struct attribute *s3c_hwmon_attrs[9] = {
 	&sensor_dev_attr_adc0_raw.dev_attr.attr,
diff --git a/drivers/hwmon/sch56xx-common.c b/drivers/hwmon/sch56xx-common.c
index d00b30a..7386819 100644
--- a/drivers/hwmon/sch56xx-common.c
+++ b/drivers/hwmon/sch56xx-common.c
@@ -161,8 +161,8 @@ static int sch56xx_send_cmd(u16 addr, u8 cmd, u16 reg, u8 v)
 			break;
 	}
 	if (i == max_busy_polls + max_lazy_polls) {
-		pr_err("Max retries exceeded reading virtual "
-		       "register 0x%04hx (%d)\n", reg, 1);
+		pr_err("Max retries exceeded reading virtual register 0x%04hx (%d)\n",
+		       reg, 1);
 		return -EIO;
 	}
 
@@ -178,12 +178,12 @@ static int sch56xx_send_cmd(u16 addr, u8 cmd, u16 reg, u8 v)
 			break;
 
 		if (i == 0)
-			pr_warn("EC reports: 0x%02x reading virtual register "
-				"0x%04hx\n", (unsigned int)val, reg);
+			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);
+		pr_err("Max retries exceeded reading virtual register 0x%04hx (%d)\n",
+		       reg, 2);
 		return -EIO;
 	}
 
diff --git a/drivers/hwmon/sis5595.c b/drivers/hwmon/sis5595.c
index c35847a..1404e63 100644
--- a/drivers/hwmon/sis5595.c
+++ b/drivers/hwmon/sis5595.c
@@ -456,8 +456,9 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *da,
 		data->fan_div[nr] = 3;
 		break;
 	default:
-		dev_err(dev, "fan_div value %ld not "
-			"supported. Choose one of 1, 2, 4 or 8!\n", val);
+		dev_err(dev,
+			"fan_div value %ld not supported. Choose one of 1, 2, 4 or 8!\n",
+			val);
 		mutex_unlock(&data->update_lock);
 		return -EINVAL;
 	}
diff --git a/drivers/hwmon/thmc50.c b/drivers/hwmon/thmc50.c
index 4b59eb5..db288db 100644
--- a/drivers/hwmon/thmc50.c
+++ b/drivers/hwmon/thmc50.c
@@ -41,8 +41,8 @@ enum chips { thmc50, adm1022 };
 static unsigned short adm1022_temp3[16];
 static unsigned int adm1022_temp3_num;
 module_param_array(adm1022_temp3, ushort, &adm1022_temp3_num, 0);
-MODULE_PARM_DESC(adm1022_temp3, "List of adapter,address pairs "
-			"to enable 3rd temperature (ADM1022 only)");
+MODULE_PARM_DESC(adm1022_temp3,
+		 "List of adapter,address pairs to enable 3rd temperature (ADM1022 only)");
 
 /* Many THMC50 constants specified below */
 
@@ -312,8 +312,7 @@ static int thmc50_detect(struct i2c_client *client,
 	const char *type_name;
 
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
-		pr_debug("thmc50: detect failed, "
-			 "smbus byte data not supported!\n");
+		pr_debug("thmc50: detect failed, smbus byte data not supported!\n");
 		return -ENODEV;
 	}
 
diff --git a/drivers/hwmon/tmp102.c b/drivers/hwmon/tmp102.c
index 523dd89..d7b47ab 100644
--- a/drivers/hwmon/tmp102.c
+++ b/drivers/hwmon/tmp102.c
@@ -155,8 +155,8 @@ static int tmp102_probe(struct i2c_client *client,
 
 	if (!i2c_check_functionality(client->adapter,
 				     I2C_FUNC_SMBUS_WORD_DATA)) {
-		dev_err(&client->dev, "adapter doesn't support SMBus word "
-			"transactions\n");
+		dev_err(&client->dev,
+			"adapter doesn't support SMBus word transactions\n");
 		return -ENODEV;
 	}
 
diff --git a/drivers/hwmon/tmp401.c b/drivers/hwmon/tmp401.c
index c85f696..be71a3e 100644
--- a/drivers/hwmon/tmp401.c
+++ b/drivers/hwmon/tmp401.c
@@ -40,9 +40,9 @@
 #include <linux/sysfs.h>
 
 /* Addresses to scan */
-static const unsigned short normal_i2c[] = { 0x4c, I2C_CLIENT_END };
+static const unsigned short normal_i2c[] = { 0x4c, 0x4d, 0x4e, I2C_CLIENT_END };
 
-enum chips { tmp401, tmp411 };
+enum chips { tmp401, tmp411, tmp431 };
 
 /*
  * The TMP401 registers, note some registers have different addresses for
@@ -89,7 +89,10 @@ static const u8 TMP411_TEMP_HIGHEST_LSB[2]		= { 0x33, 0x37 };
 /* Manufacturer / Device ID's */
 #define TMP401_MANUFACTURER_ID			0x55
 #define TMP401_DEVICE_ID			0x11
-#define TMP411_DEVICE_ID			0x12
+#define TMP411A_DEVICE_ID			0x12
+#define TMP411B_DEVICE_ID			0x13
+#define TMP411C_DEVICE_ID			0x10
+#define TMP431_DEVICE_ID			0x31
 
 /*
  * Driver data (common to all clients)
@@ -98,6 +101,7 @@ static const u8 TMP411_TEMP_HIGHEST_LSB[2]		= { 0x33, 0x37 };
 static const struct i2c_device_id tmp401_id[] = {
 	{ "tmp401", tmp401 },
 	{ "tmp411", tmp411 },
+	{ "tmp431", tmp431 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, tmp401_id);
@@ -451,8 +455,9 @@ static ssize_t reset_temp_history(struct device *dev,
 		return -EINVAL;
 
 	if (val != 1) {
-		dev_err(dev, "temp_reset_history value %ld not"
-			" supported. Use 1 to reset the history!\n", val);
+		dev_err(dev,
+			"temp_reset_history value %ld not supported. Use 1 to reset the history!\n",
+			val);
 		return -EINVAL;
 	}
 	i2c_smbus_write_byte_data(to_i2c_client(dev),
@@ -554,11 +559,30 @@ static int tmp401_detect(struct i2c_client *client,
 
 	switch (reg) {
 	case TMP401_DEVICE_ID:
+		if (client->addr != 0x4c)
+			return -ENODEV;
 		kind = tmp401;
 		break;
-	case TMP411_DEVICE_ID:
+	case TMP411A_DEVICE_ID:
+		if (client->addr != 0x4c)
+			return -ENODEV;
 		kind = tmp411;
 		break;
+	case TMP411B_DEVICE_ID:
+		if (client->addr != 0x4d)
+			return -ENODEV;
+		kind = tmp411;
+		break;
+	case TMP411C_DEVICE_ID:
+		if (client->addr != 0x4e)
+			return -ENODEV;
+		kind = tmp411;
+		break;
+	case TMP431_DEVICE_ID:
+		if (client->addr == 0x4e)
+			return -ENODEV;
+		kind = tmp431;
+		break;
 	default:
 		return -ENODEV;
 	}
@@ -602,7 +626,7 @@ static int tmp401_probe(struct i2c_client *client,
 {
 	int i, err = 0;
 	struct tmp401_data *data;
-	const char *names[] = { "TMP401", "TMP411" };
+	const char *names[] = { "TMP401", "TMP411", "TMP431" };
 
 	data = devm_kzalloc(&client->dev, sizeof(struct tmp401_data),
 			    GFP_KERNEL);
diff --git a/drivers/hwmon/tmp421.c b/drivers/hwmon/tmp421.c
index 6a8ded2..964c1d6 100644
--- a/drivers/hwmon/tmp421.c
+++ b/drivers/hwmon/tmp421.c
@@ -208,8 +208,8 @@ static int tmp421_init_client(struct i2c_client *client)
 	/* Start conversions (disable shutdown if necessary) */
 	config = i2c_smbus_read_byte_data(client, TMP421_CONFIG_REG_1);
 	if (config < 0) {
-		dev_err(&client->dev, "Could not read configuration"
-			 " register (%d)\n", config);
+		dev_err(&client->dev,
+			"Could not read configuration register (%d)\n", config);
 		return -ENODEV;
 	}
 
@@ -322,6 +322,5 @@ static struct i2c_driver tmp421_driver = {
 module_i2c_driver(tmp421_driver);
 
 MODULE_AUTHOR("Andre Prendel <andre.prendel@gmx.de>");
-MODULE_DESCRIPTION("Texas Instruments TMP421/422/423 temperature sensor"
-		   " driver");
+MODULE_DESCRIPTION("Texas Instruments TMP421/422/423 temperature sensor driver");
 MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/via686a.c b/drivers/hwmon/via686a.c
index 3123b30..c9dcce8 100644
--- a/drivers/hwmon/via686a.c
+++ b/drivers/hwmon/via686a.c
@@ -125,7 +125,7 @@ static const u8 VIA686A_REG_TEMP_HYST[]	= { 0x3a, 0x3e, 0x1e };
  * (These conversions were contributed by Jonathan Teh Soon Yew
  * <j.teh@iname.com>)
  */
-static inline u8 IN_TO_REG(long val, int inNum)
+static inline u8 IN_TO_REG(long val, int in_num)
 {
 	/*
 	 * To avoid floating point, we multiply constants by 10 (100 for +12V).
@@ -134,29 +134,29 @@ static inline u8 IN_TO_REG(long val, int inNum)
 	 * by an additional 10000 (100000 for +12V): 1000 for val and 10 (100)
 	 * for the constants.
 	 */
-	if (inNum <= 1)
+	if (in_num <= 1)
 		return (u8) clamp_val((val * 21024 - 1205000) / 250000, 0, 255);
-	else if (inNum == 2)
+	else if (in_num == 2)
 		return (u8) clamp_val((val * 15737 - 1205000) / 250000, 0, 255);
-	else if (inNum == 3)
+	else if (in_num == 3)
 		return (u8) clamp_val((val * 10108 - 1205000) / 250000, 0, 255);
 	else
 		return (u8) clamp_val((val * 41714 - 12050000) / 2500000, 0,
 				      255);
 }
 
-static inline long IN_FROM_REG(u8 val, int inNum)
+static inline long IN_FROM_REG(u8 val, int in_num)
 {
 	/*
 	 * To avoid floating point, we multiply constants by 10 (100 for +12V).
 	 * We also multiply them by 1000 because we want 0.001V/bit for the
 	 * output value. Rounding is done.
 	 */
-	if (inNum <= 1)
+	if (in_num <= 1)
 		return (long) ((250000 * val + 1330000 + 21024 / 2) / 21024);
-	else if (inNum == 2)
+	else if (in_num == 2)
 		return (long) ((250000 * val + 1330000 + 15737 / 2) / 15737);
-	else if (inNum == 3)
+	else if (in_num == 3)
 		return (long) ((250000 * val + 1330000 + 10108 / 2) / 10108);
 	else
 		return (long) ((2500000 * val + 13300000 + 41714 / 2) / 41714);
@@ -210,10 +210,10 @@ static inline u8 FAN_TO_REG(long rpm, int div)
  * VIA register values 0-255.  I *10 before rounding, so we get tenth-degree
  * precision.  (I could have done all 1024 values for our 10-bit readings,
  * but the function is very linear in the useful range (0-80 deg C), so
- * we'll just use linear interpolation for 10-bit readings.)  So, tempLUT
+ * we'll just use linear interpolation for 10-bit readings.)  So, temp_lut
  * is the temp at via register values 0-255:
  */
-static const s16 tempLUT[] = {
+static const s16 temp_lut[] = {
 	-709, -688, -667, -646, -627, -607, -589, -570, -553, -536, -519,
 	-503, -487, -471, -456, -442, -428, -414, -400, -387, -375,
 	-362, -350, -339, -327, -316, -305, -295, -285, -275, -265,
@@ -261,7 +261,7 @@ static const s16 tempLUT[] = {
  * - 2.525453e-04*val^3 + 1.424593e-02*val^2 + 2.148941e+00*val +7.275808e+01)
  * Note that n=161:
  */
-static const u8 viaLUT[] = {
+static const u8 via_lut[] = {
 	12, 12, 13, 14, 14, 15, 16, 16, 17, 18, 18, 19, 20, 20, 21, 22, 23,
 	23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 39, 40,
 	41, 43, 45, 46, 48, 49, 51, 53, 55, 57, 59, 60, 62, 64, 66,
@@ -284,26 +284,26 @@ static const u8 viaLUT[] = {
  */
 static inline u8 TEMP_TO_REG(long val)
 {
-	return viaLUT[val <= -50000 ? 0 : val >= 110000 ? 160 :
+	return via_lut[val <= -50000 ? 0 : val >= 110000 ? 160 :
 		      (val < 0 ? val - 500 : val + 500) / 1000 + 50];
 }
 
 /* for 8-bit temperature hyst and over registers */
-#define TEMP_FROM_REG(val)	((long)tempLUT[val] * 100)
+#define TEMP_FROM_REG(val)	((long)temp_lut[val] * 100)
 
 /* for 10-bit temperature readings */
 static inline long TEMP_FROM_REG10(u16 val)
 {
-	u16 eightBits = val >> 2;
-	u16 twoBits = val & 3;
+	u16 eight_bits = val >> 2;
+	u16 two_bits = val & 3;
 
 	/* no interpolation for these */
-	if (twoBits == 0 || eightBits == 255)
-		return TEMP_FROM_REG(eightBits);
+	if (two_bits == 0 || eight_bits == 255)
+		return TEMP_FROM_REG(eight_bits);
 
 	/* do some linear interpolation */
-	return (tempLUT[eightBits] * (4 - twoBits) +
-		tempLUT[eightBits + 1] * twoBits) * 25;
+	return (temp_lut[eight_bits] * (4 - two_bits) +
+		temp_lut[eight_bits + 1] * two_bits) * 25;
 }
 
 #define DIV_FROM_REG(val) (1 << (val))
@@ -889,8 +889,8 @@ static int via686a_pci_probe(struct pci_dev *dev,
 
 	address = val & ~(VIA686A_EXTENT - 1);
 	if (address == 0) {
-		dev_err(&dev->dev, "base address not set - upgrade BIOS "
-			"or use force_addr=0xaddr\n");
+		dev_err(&dev->dev,
+			"base address not set - upgrade BIOS or use force_addr=0xaddr\n");
 		return -ENODEV;
 	}
 
@@ -899,8 +899,9 @@ static int via686a_pci_probe(struct pci_dev *dev,
 		return -ENODEV;
 	if (!(val & 0x0001)) {
 		if (!force_addr) {
-			dev_warn(&dev->dev, "Sensors disabled, enable "
-				 "with force_addr=0x%x\n", address);
+			dev_warn(&dev->dev,
+				 "Sensors disabled, enable with force_addr=0x%x\n",
+				 address);
 			return -ENODEV;
 		}
 
diff --git a/drivers/hwmon/vt1211.c b/drivers/hwmon/vt1211.c
index dcc62f8..6b2f1a4 100644
--- a/drivers/hwmon/vt1211.c
+++ b/drivers/hwmon/vt1211.c
@@ -571,8 +571,9 @@ static ssize_t set_fan(struct device *dev, struct device_attribute *attr,
 			break;
 		default:
 			count = -EINVAL;
-			dev_warn(dev, "fan div value %ld not supported. "
-				 "Choose one of 1, 2, 4, or 8.\n", val);
+			dev_warn(dev,
+				 "fan div value %ld not supported. Choose one of 1, 2, 4, or 8.\n",
+				 val);
 			goto EXIT;
 		}
 		vt1211_write8(data, VT1211_REG_FAN_DIV,
@@ -674,8 +675,9 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
 			break;
 		default:
 			count = -EINVAL;
-			dev_warn(dev, "pwm mode %ld not supported. "
-				 "Choose one of 0 or 2.\n", val);
+			dev_warn(dev,
+				 "pwm mode %ld not supported. Choose one of 0 or 2.\n",
+				 val);
 			goto EXIT;
 		}
 		vt1211_write8(data, VT1211_REG_PWM_CTL,
@@ -700,8 +702,9 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
 	case SHOW_SET_PWM_AUTO_CHANNELS_TEMP:
 		if (val < 1 || val > 7) {
 			count = -EINVAL;
-			dev_warn(dev, "temp channel %ld not supported. "
-				 "Choose a value between 1 and 7.\n", val);
+			dev_warn(dev,
+				 "temp channel %ld not supported. Choose a value between 1 and 7.\n",
+				 val);
 			goto EXIT;
 		}
 		if (!ISTEMP(val - 1, data->uch_config)) {
@@ -1325,15 +1328,15 @@ static int __init vt1211_init(void)
 
 	if ((uch_config < -1) || (uch_config > 31)) {
 		err = -EINVAL;
-		pr_warn("Invalid UCH configuration %d. "
-			"Choose a value between 0 and 31.\n", uch_config);
+		pr_warn("Invalid UCH configuration %d. Choose a value between 0 and 31.\n",
+			uch_config);
 		goto EXIT;
 	}
 
 	if ((int_mode < -1) || (int_mode > 0)) {
 		err = -EINVAL;
-		pr_warn("Invalid interrupt mode %d. "
-			"Only mode 0 is supported.\n", int_mode);
+		pr_warn("Invalid interrupt mode %d. Only mode 0 is supported.\n",
+			int_mode);
 		goto EXIT;
 	}
 
diff --git a/drivers/hwmon/vt8231.c b/drivers/hwmon/vt8231.c
index 988a2a7..0e70178 100644
--- a/drivers/hwmon/vt8231.c
+++ b/drivers/hwmon/vt8231.c
@@ -573,8 +573,9 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
 		data->fan_div[nr] = 3;
 		break;
 	default:
-		dev_err(dev, "fan_div value %ld not supported. "
-			"Choose one of 1, 2, 4 or 8!\n", val);
+		dev_err(dev,
+			"fan_div value %ld not supported. Choose one of 1, 2, 4 or 8!\n",
+			val);
 		mutex_unlock(&data->update_lock);
 		return -EINVAL;
 	}
diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c
index 0a89211..0160272 100644
--- a/drivers/hwmon/w83627ehf.c
+++ b/drivers/hwmon/w83627ehf.c
@@ -840,8 +840,8 @@ static struct w83627ehf_data *w83627ehf_update_device(struct device *dev)
 			    && (reg >= 0xff || (sio_data->kind == nct6775
 						&& reg == 0x00))
 			    && data->fan_div[i] < 0x07) {
-				dev_dbg(dev, "Increasing fan%d "
-					"clock divider from %u to %u\n",
+				dev_dbg(dev,
+					"Increasing fan%d clock divider from %u to %u\n",
 					i + 1, div_from_reg(data->fan_div[i]),
 					div_from_reg(data->fan_div[i] + 1));
 				data->fan_div[i]++;
@@ -1110,9 +1110,9 @@ store_fan_min(struct device *dev, struct device_attribute *attr,
 		 */
 		data->fan_min[nr] = 254;
 		new_div = 7; /* 128 == (1 << 7) */
-		dev_warn(dev, "fan%u low limit %lu below minimum %u, set to "
-			 "minimum\n", nr + 1, val,
-			 data->fan_from_reg_min(254, 7));
+		dev_warn(dev,
+			 "fan%u low limit %lu below minimum %u, set to minimum\n",
+			 nr + 1, val, data->fan_from_reg_min(254, 7));
 	} else if (!reg) {
 		/*
 		 * Speed above this value cannot possibly be represented,
@@ -1120,9 +1120,9 @@ store_fan_min(struct device *dev, struct device_attribute *attr,
 		 */
 		data->fan_min[nr] = 1;
 		new_div = 0; /* 1 == (1 << 0) */
-		dev_warn(dev, "fan%u low limit %lu above maximum %u, set to "
-			 "maximum\n", nr + 1, val,
-			 data->fan_from_reg_min(1, 0));
+		dev_warn(dev,
+			 "fan%u low limit %lu above maximum %u, set to maximum\n",
+			 nr + 1, val, data->fan_from_reg_min(1, 0));
 	} else {
 		/*
 		 * Automatically pick the best divider, i.e. the one such
@@ -2396,15 +2396,15 @@ static int w83627ehf_probe(struct platform_device *pdev)
 				en_vrm10 = superio_inb(sio_data->sioreg,
 						       SIO_REG_EN_VRM10);
 				if ((en_vrm10 & 0x08) && data->vrm == 90) {
-					dev_warn(dev, "Setting VID input "
-						 "voltage to TTL\n");
+					dev_warn(dev,
+						 "Setting VID input voltage to TTL\n");
 					superio_outb(sio_data->sioreg,
 						     SIO_REG_EN_VRM10,
 						     en_vrm10 & ~0x08);
 				} else if (!(en_vrm10 & 0x08)
 					   && data->vrm == 100) {
-					dev_warn(dev, "Setting VID input "
-						 "voltage to VRM10\n");
+					dev_warn(dev,
+						 "Setting VID input voltage to VRM10\n");
 					superio_outb(sio_data->sioreg,
 						     SIO_REG_EN_VRM10,
 						     en_vrm10 | 0x08);
@@ -2420,8 +2420,8 @@ static int w83627ehf_probe(struct platform_device *pdev)
 			if (err)
 				goto exit_release;
 		} else {
-			dev_info(dev, "VID pins in output mode, CPU VID not "
-				 "available\n");
+			dev_info(dev,
+				 "VID pins in output mode, CPU VID not available\n");
 		}
 	}
 
@@ -2795,8 +2795,7 @@ static int __init w83627ehf_find(int sioaddr, unsigned short *addr,
 	/* Activate logical device if needed */
 	val = superio_inb(sioaddr, SIO_REG_ENABLE);
 	if (!(val & 0x01)) {
-		pr_warn("Forcibly enabling Super-I/O. "
-			"Sensor is probably unusable.\n");
+		pr_warn("Forcibly enabling Super-I/O. Sensor is probably unusable.\n");
 		superio_outb(sioaddr, SIO_REG_ENABLE, val | 0x01);
 	}
 
diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c
index aeec5b1..f9d5139 100644
--- a/drivers/hwmon/w83781d.c
+++ b/drivers/hwmon/w83781d.c
@@ -64,8 +64,8 @@ enum chips { w83781d, w83782d, w83783s, as99127f };
 /* Insmod parameters */
 static unsigned short force_subclients[4];
 module_param_array(force_subclients, short, NULL, 0);
-MODULE_PARM_DESC(force_subclients, "List of subclient addresses: "
-		    "{bus, clientaddr, subclientaddr1, subclientaddr2}");
+MODULE_PARM_DESC(force_subclients,
+		 "List of subclient addresses: {bus, clientaddr, subclientaddr1, subclientaddr2}");
 
 static bool reset;
 module_param(reset, bool, 0);
@@ -826,8 +826,9 @@ store_sensor(struct device *dev, struct device_attribute *da,
 		data->sens[nr] = val;
 		break;
 	case W83781D_DEFAULT_BETA:
-		dev_warn(dev, "Sensor type %d is deprecated, please use 4 "
-			 "instead\n", W83781D_DEFAULT_BETA);
+		dev_warn(dev,
+			 "Sensor type %d is deprecated, please use 4 instead\n",
+			 W83781D_DEFAULT_BETA);
 		/* fall through */
 	case 4:		/* thermistor */
 		tmp = w83781d_read_value(data, W83781D_REG_SCFG1);
@@ -874,8 +875,8 @@ w83781d_detect_subclients(struct i2c_client *new_client)
 		for (i = 2; i <= 3; i++) {
 			if (force_subclients[i] < 0x48 ||
 			    force_subclients[i] > 0x4f) {
-				dev_err(&new_client->dev, "Invalid subclient "
-					"address %d; must be 0x48-0x4f\n",
+				dev_err(&new_client->dev,
+					"Invalid subclient address %d; must be 0x48-0x4f\n",
 					force_subclients[i]);
 				err = -EINVAL;
 				goto ERROR_SC_1;
@@ -910,9 +911,9 @@ w83781d_detect_subclients(struct i2c_client *new_client)
 	for (i = 0; i < num_sc; i++) {
 		data->lm75[i] = i2c_new_dummy(adapter, sc_addr[i]);
 		if (!data->lm75[i]) {
-			dev_err(&new_client->dev, "Subclient %d "
-				"registration at address 0x%x "
-				"failed.\n", i, sc_addr[i]);
+			dev_err(&new_client->dev,
+				"Subclient %d registration at address 0x%x failed.\n",
+				i, sc_addr[i]);
 			err = -ENOMEM;
 			if (i == 1)
 				goto ERROR_SC_3;
@@ -1176,8 +1177,9 @@ w83781d_detect(struct i2c_client *client, struct i2c_board_info *info)
 		goto err_nodev;
 
 	if (val1 <= 0x30 && w83781d_alias_detect(client, val1)) {
-		dev_dbg(&adapter->dev, "Device at 0x%02x appears to "
-			"be the same as ISA device\n", address);
+		dev_dbg(&adapter->dev,
+			"Device at 0x%02x appears to be the same as ISA device\n",
+			address);
 		goto err_nodev;
 	}
 
@@ -1367,8 +1369,8 @@ w83781d_init_device(struct device *dev)
 		 * as I see very little reason why this would be needed at
 		 * all.
 		 */
-		dev_info(dev, "If reset=1 solved a problem you were "
-			 "having, please report!\n");
+		dev_info(dev,
+			 "If reset=1 solved a problem you were having, please report!\n");
 
 		/* save these registers */
 		i = w83781d_read_value(data, W83781D_REG_BEEP_CONFIG);
@@ -1425,8 +1427,8 @@ w83781d_init_device(struct device *dev)
 		/* Enable temp2 */
 		tmp = w83781d_read_value(data, W83781D_REG_TEMP2_CONFIG);
 		if (tmp & 0x01) {
-			dev_warn(dev, "Enabling temp2, readings "
-				 "might not make sense\n");
+			dev_warn(dev,
+				 "Enabling temp2, readings might not make sense\n");
 			w83781d_write_value(data, W83781D_REG_TEMP2_CONFIG,
 				tmp & 0xfe);
 		}
@@ -1436,8 +1438,8 @@ w83781d_init_device(struct device *dev)
 			tmp = w83781d_read_value(data,
 				W83781D_REG_TEMP3_CONFIG);
 			if (tmp & 0x01) {
-				dev_warn(dev, "Enabling temp3, "
-					 "readings might not make sense\n");
+				dev_warn(dev,
+					 "Enabling temp3, readings might not make sense\n");
 				w83781d_write_value(data,
 					W83781D_REG_TEMP3_CONFIG, tmp & 0xfe);
 			}
diff --git a/drivers/hwmon/w83791d.c b/drivers/hwmon/w83791d.c
index 38ddddd..a3feee3 100644
--- a/drivers/hwmon/w83791d.c
+++ b/drivers/hwmon/w83791d.c
@@ -56,8 +56,8 @@ static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f,
 
 static unsigned short force_subclients[4];
 module_param_array(force_subclients, short, NULL, 0);
-MODULE_PARM_DESC(force_subclients, "List of subclient addresses: "
-			"{bus, clientaddr, subclientaddr1, subclientaddr2}");
+MODULE_PARM_DESC(force_subclients,
+		 "List of subclient addresses: {bus, clientaddr, subclientaddr1, subclientaddr2}");
 
 static bool reset;
 module_param(reset, bool, 0);
diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c
index 5cb83dd..0b80489 100644
--- a/drivers/hwmon/w83792d.c
+++ b/drivers/hwmon/w83792d.c
@@ -54,8 +54,8 @@ static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f,
 
 static unsigned short force_subclients[4];
 module_param_array(force_subclients, short, NULL, 0);
-MODULE_PARM_DESC(force_subclients, "List of subclient addresses: "
-			"{bus, clientaddr, subclientaddr1, subclientaddr2}");
+MODULE_PARM_DESC(force_subclients,
+		 "List of subclient addresses: {bus, clientaddr, subclientaddr1, subclientaddr2}");
 
 static bool init;
 module_param(init, bool, 0);
@@ -951,8 +951,8 @@ w83792d_detect_subclients(struct i2c_client *new_client)
 		for (i = 2; i <= 3; i++) {
 			if (force_subclients[i] < 0x48 ||
 			    force_subclients[i] > 0x4f) {
-				dev_err(&new_client->dev, "invalid subclient "
-					"address %d; must be 0x48-0x4f\n",
+				dev_err(&new_client->dev,
+					"invalid subclient address %d; must be 0x48-0x4f\n",
 					force_subclients[i]);
 				err = -ENODEV;
 				goto ERROR_SC_0;
@@ -969,8 +969,9 @@ w83792d_detect_subclients(struct i2c_client *new_client)
 	if (!(val & 0x80)) {
 		if ((data->lm75[0] != NULL) &&
 			((val & 0x7) == ((val >> 4) & 0x7))) {
-			dev_err(&new_client->dev, "duplicate addresses 0x%x, "
-				"use force_subclient\n", data->lm75[0]->addr);
+			dev_err(&new_client->dev,
+				"duplicate addresses 0x%x, use force_subclient\n",
+				data->lm75[0]->addr);
 			err = -ENODEV;
 			goto ERROR_SC_1;
 		}
diff --git a/drivers/hwmon/w83793.c b/drivers/hwmon/w83793.c
index 6604275..b0c30a5 100644
--- a/drivers/hwmon/w83793.c
+++ b/drivers/hwmon/w83793.c
@@ -59,8 +59,8 @@ static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f,
 
 static unsigned short force_subclients[4];
 module_param_array(force_subclients, short, NULL, 0);
-MODULE_PARM_DESC(force_subclients, "List of subclient addresses: "
-		       "{bus, clientaddr, subclientaddr1, subclientaddr2}");
+MODULE_PARM_DESC(force_subclients,
+		 "List of subclient addresses: {bus, clientaddr, subclientaddr1, subclientaddr2}");
 
 static bool reset;
 module_param(reset, bool, 0);
@@ -1921,8 +1921,8 @@ static int w83793_probe(struct i2c_client *client,
 	}
 	if (i == ARRAY_SIZE(watchdog_minors)) {
 		data->watchdog_miscdev.minor = 0;
-		dev_warn(&client->dev, "Couldn't register watchdog chardev "
-			"(due to no free minor)\n");
+		dev_warn(&client->dev,
+			 "Couldn't register watchdog chardev (due to no free minor)\n");
 	}
 
 	mutex_unlock(&watchdog_data_mutex);
diff --git a/drivers/hwmon/w83795.c b/drivers/hwmon/w83795.c
index e226096..908209d 100644
--- a/drivers/hwmon/w83795.c
+++ b/drivers/hwmon/w83795.c
@@ -2120,11 +2120,12 @@ static void w83795_check_dynamic_in_limits(struct i2c_client *client)
 					   &w83795_in[i][3].dev_attr.attr,
 					   S_IRUGO);
 		if (err_max || err_min)
-			dev_warn(&client->dev, "Failed to set in%d limits "
-				 "read-only (%d, %d)\n", i, err_max, err_min);
+			dev_warn(&client->dev,
+				 "Failed to set in%d limits read-only (%d, %d)\n",
+				 i, err_max, err_min);
 		else
-			dev_info(&client->dev, "in%d limits set dynamically "
-				 "from VID\n", i);
+			dev_info(&client->dev,
+				 "in%d limits set dynamically from VID\n", i);
 	}
 }
 
diff --git a/drivers/i2c/busses/i2c-amd756-s4882.c b/drivers/i2c/busses/i2c-amd756-s4882.c
index 378fcb5..07f01ac 100644
--- a/drivers/i2c/busses/i2c-amd756-s4882.c
+++ b/drivers/i2c/busses/i2c-amd756-s4882.c
@@ -169,11 +169,7 @@ static int __init amd756_s4882_init(void)
 	}
 
 	/* Unregister physical bus */
-	error = i2c_del_adapter(&amd756_smbus);
-	if (error) {
-		dev_err(&amd756_smbus.dev, "Physical bus removal failed\n");
-		goto ERROR0;
-	}
+	i2c_del_adapter(&amd756_smbus);
 
 	printk(KERN_INFO "Enabling SMBus multiplexing for Tyan S4882\n");
 	/* Define the 5 virtual adapters and algorithms structures */
diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c
index 75195e3..2fcd275 100644
--- a/drivers/i2c/busses/i2c-at91.c
+++ b/drivers/i2c/busses/i2c-at91.c
@@ -603,8 +603,6 @@ static const struct of_device_id atmel_twi_dt_ids[] = {
 	}
 };
 MODULE_DEVICE_TABLE(of, atmel_twi_dt_ids);
-#else
-#define atmel_twi_dt_ids NULL
 #endif
 
 static bool filter(struct dma_chan *chan, void *slave)
@@ -785,12 +783,11 @@ static int at91_twi_probe(struct platform_device *pdev)
 static int at91_twi_remove(struct platform_device *pdev)
 {
 	struct at91_twi_dev *dev = platform_get_drvdata(pdev);
-	int rc;
 
-	rc = i2c_del_adapter(&dev->adapter);
+	i2c_del_adapter(&dev->adapter);
 	clk_disable_unprepare(dev->clk);
 
-	return rc;
+	return 0;
 }
 
 #ifdef CONFIG_PM
@@ -828,7 +825,7 @@ static struct platform_driver at91_twi_driver = {
 	.driver		= {
 		.name	= "at91_i2c",
 		.owner	= THIS_MODULE,
-		.of_match_table = atmel_twi_dt_ids,
+		.of_match_table = of_match_ptr(atmel_twi_dt_ids),
 		.pm	= at91_twi_pm_ops,
 	},
 };
diff --git a/drivers/i2c/busses/i2c-cbus-gpio.c b/drivers/i2c/busses/i2c-cbus-gpio.c
index 98386d6..1be13ac 100644
--- a/drivers/i2c/busses/i2c-cbus-gpio.c
+++ b/drivers/i2c/busses/i2c-cbus-gpio.c
@@ -206,7 +206,9 @@ static int cbus_i2c_remove(struct platform_device *pdev)
 {
 	struct i2c_adapter *adapter = platform_get_drvdata(pdev);
 
-	return i2c_del_adapter(adapter);
+	i2c_del_adapter(adapter);
+
+	return 0;
 }
 
 static int cbus_i2c_probe(struct platform_device *pdev)
diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c
index 7d1e590..c01edac 100644
--- a/drivers/i2c/busses/i2c-davinci.c
+++ b/drivers/i2c/busses/i2c-davinci.c
@@ -137,7 +137,7 @@ static inline u16 davinci_i2c_read_reg(struct davinci_i2c_dev *i2c_dev, int reg)
 }
 
 /* Generate a pulse on the i2c clock pin. */
-static void generic_i2c_clock_pulse(unsigned int scl_pin)
+static void davinci_i2c_clock_pulse(unsigned int scl_pin)
 {
 	u16 i;
 
@@ -155,7 +155,7 @@ static void generic_i2c_clock_pulse(unsigned int scl_pin)
 /* This routine does i2c bus recovery as specified in the
  * i2c protocol Rev. 03 section 3.16 titled "Bus clear"
  */
-static void i2c_recover_bus(struct davinci_i2c_dev *dev)
+static void davinci_i2c_recover_bus(struct davinci_i2c_dev *dev)
 {
 	u32 flag = 0;
 	struct davinci_i2c_platform_data *pdata = dev->pdata;
@@ -166,7 +166,7 @@ static void i2c_recover_bus(struct davinci_i2c_dev *dev)
 	flag |=  DAVINCI_I2C_MDR_NACK;
 	/* write the data into mode register */
 	davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag);
-	generic_i2c_clock_pulse(pdata->scl_pin);
+	davinci_i2c_clock_pulse(pdata->scl_pin);
 	/* Send STOP */
 	flag = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG);
 	flag |= DAVINCI_I2C_MDR_STP;
@@ -289,7 +289,7 @@ static int i2c_davinci_wait_bus_not_busy(struct davinci_i2c_dev *dev,
 				return -ETIMEDOUT;
 			} else {
 				to_cnt = 0;
-				i2c_recover_bus(dev);
+				davinci_i2c_recover_bus(dev);
 				i2c_davinci_init(dev);
 			}
 		}
@@ -379,7 +379,7 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
 						      dev->adapter.timeout);
 	if (r == 0) {
 		dev_err(dev->dev, "controller timed out\n");
-		i2c_recover_bus(dev);
+		davinci_i2c_recover_bus(dev);
 		i2c_davinci_init(dev);
 		dev->buf_len = 0;
 		return -ETIMEDOUT;
@@ -643,7 +643,7 @@ static int davinci_i2c_probe(struct platform_device *pdev)
 {
 	struct davinci_i2c_dev *dev;
 	struct i2c_adapter *adap;
-	struct resource *mem, *irq, *ioarea;
+	struct resource *mem, *irq;
 	int r;
 
 	/* NOTE: driver uses the static register mapping */
@@ -659,17 +659,11 @@ static int davinci_i2c_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
-	ioarea = request_mem_region(mem->start, resource_size(mem),
-				    pdev->name);
-	if (!ioarea) {
-		dev_err(&pdev->dev, "I2C region already claimed\n");
-		return -EBUSY;
-	}
-
-	dev = kzalloc(sizeof(struct davinci_i2c_dev), GFP_KERNEL);
+	dev = devm_kzalloc(&pdev->dev, sizeof(struct davinci_i2c_dev),
+			GFP_KERNEL);
 	if (!dev) {
-		r = -ENOMEM;
-		goto err_release_region;
+		dev_err(&pdev->dev, "Memory allocation failed\n");
+		return -ENOMEM;
 	}
 
 	init_completion(&dev->cmd_complete);
@@ -699,22 +693,23 @@ static int davinci_i2c_probe(struct platform_device *pdev)
 		dev->pdata = &davinci_i2c_platform_data_default;
 	}
 
-	dev->clk = clk_get(&pdev->dev, NULL);
+	dev->clk = devm_clk_get(&pdev->dev, NULL);
 	if (IS_ERR(dev->clk)) {
 		r = -ENODEV;
 		goto err_free_mem;
 	}
 	clk_prepare_enable(dev->clk);
 
-	dev->base = ioremap(mem->start, resource_size(mem));
-	if (!dev->base) {
-		r = -EBUSY;
-		goto err_mem_ioremap;
+	dev->base = devm_ioremap_resource(&pdev->dev, mem);
+	if (IS_ERR(dev->base)) {
+		r = PTR_ERR(dev->base);
+		goto err_unuse_clocks;
 	}
 
 	i2c_davinci_init(dev);
 
-	r = request_irq(dev->irq, i2c_davinci_isr, 0, pdev->name, dev);
+	r = devm_request_irq(&pdev->dev, dev->irq, i2c_davinci_isr, 0,
+			pdev->name, dev);
 	if (r) {
 		dev_err(&pdev->dev, "failure requesting irq %i\n", dev->irq);
 		goto err_unuse_clocks;
@@ -723,7 +718,7 @@ static int davinci_i2c_probe(struct platform_device *pdev)
 	r = i2c_davinci_cpufreq_register(dev);
 	if (r) {
 		dev_err(&pdev->dev, "failed to register cpufreq\n");
-		goto err_free_irq;
+		goto err_unuse_clocks;
 	}
 
 	adap = &dev->adapter;
@@ -740,25 +735,17 @@ static int davinci_i2c_probe(struct platform_device *pdev)
 	r = i2c_add_numbered_adapter(adap);
 	if (r) {
 		dev_err(&pdev->dev, "failure adding adapter\n");
-		goto err_free_irq;
+		goto err_unuse_clocks;
 	}
 	of_i2c_register_devices(adap);
 
 	return 0;
 
-err_free_irq:
-	free_irq(dev->irq, dev);
 err_unuse_clocks:
-	iounmap(dev->base);
-err_mem_ioremap:
 	clk_disable_unprepare(dev->clk);
-	clk_put(dev->clk);
 	dev->clk = NULL;
 err_free_mem:
 	put_device(&pdev->dev);
-	kfree(dev);
-err_release_region:
-	release_mem_region(mem->start, resource_size(mem));
 
 	return r;
 }
@@ -766,7 +753,6 @@ err_release_region:
 static int davinci_i2c_remove(struct platform_device *pdev)
 {
 	struct davinci_i2c_dev *dev = platform_get_drvdata(pdev);
-	struct resource *mem;
 
 	i2c_davinci_cpufreq_deregister(dev);
 
@@ -774,16 +760,10 @@ static int davinci_i2c_remove(struct platform_device *pdev)
 	put_device(&pdev->dev);
 
 	clk_disable_unprepare(dev->clk);
-	clk_put(dev->clk);
 	dev->clk = NULL;
 
 	davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, 0);
-	free_irq(dev->irq, dev);
-	iounmap(dev->base);
-	kfree(dev);
 
-	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	release_mem_region(mem->start, resource_size(mem));
 	return 0;
 }
 
diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c
index 0ceb6e1..e3085c4 100644
--- a/drivers/i2c/busses/i2c-designware-platdrv.c
+++ b/drivers/i2c/busses/i2c-designware-platdrv.c
@@ -182,7 +182,6 @@ static int dw_i2c_probe(struct platform_device *pdev)
 	adap->algo = &i2c_dw_algo;
 	adap->dev.parent = &pdev->dev;
 	adap->dev.of_node = pdev->dev.of_node;
-	ACPI_HANDLE_SET(&adap->dev, ACPI_HANDLE(&pdev->dev));
 
 	r = i2c_add_numbered_adapter(adap);
 	if (r) {
diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c
index f3fa433..bc6e139 100644
--- a/drivers/i2c/busses/i2c-gpio.c
+++ b/drivers/i2c/busses/i2c-gpio.c
@@ -85,23 +85,29 @@ static int i2c_gpio_getscl(void *data)
 	return gpio_get_value(pdata->scl_pin);
 }
 
-static int of_i2c_gpio_probe(struct device_node *np,
-			     struct i2c_gpio_platform_data *pdata)
+static int of_i2c_gpio_get_pins(struct device_node *np,
+				unsigned int *sda_pin, unsigned int *scl_pin)
 {
-	u32 reg;
-
 	if (of_gpio_count(np) < 2)
 		return -ENODEV;
 
-	pdata->sda_pin = of_get_gpio(np, 0);
-	pdata->scl_pin = of_get_gpio(np, 1);
+	*sda_pin = of_get_gpio(np, 0);
+	*scl_pin = of_get_gpio(np, 1);
 
-	if (!gpio_is_valid(pdata->sda_pin) || !gpio_is_valid(pdata->scl_pin)) {
+	if (!gpio_is_valid(*sda_pin) || !gpio_is_valid(*scl_pin)) {
 		pr_err("%s: invalid GPIO pins, sda=%d/scl=%d\n",
-		       np->full_name, pdata->sda_pin, pdata->scl_pin);
+		       np->full_name, *sda_pin, *scl_pin);
 		return -ENODEV;
 	}
 
+	return 0;
+}
+
+static void of_i2c_gpio_get_props(struct device_node *np,
+				  struct i2c_gpio_platform_data *pdata)
+{
+	u32 reg;
+
 	of_property_read_u32(np, "i2c-gpio,delay-us", &pdata->udelay);
 
 	if (!of_property_read_u32(np, "i2c-gpio,timeout-ms", &reg))
@@ -113,8 +119,6 @@ static int of_i2c_gpio_probe(struct device_node *np,
 		of_property_read_bool(np, "i2c-gpio,scl-open-drain");
 	pdata->scl_is_output_only =
 		of_property_read_bool(np, "i2c-gpio,scl-output-only");
-
-	return 0;
 }
 
 static int i2c_gpio_probe(struct platform_device *pdev)
@@ -123,31 +127,52 @@ static int i2c_gpio_probe(struct platform_device *pdev)
 	struct i2c_gpio_platform_data *pdata;
 	struct i2c_algo_bit_data *bit_data;
 	struct i2c_adapter *adap;
+	unsigned int sda_pin, scl_pin;
 	int ret;
 
-	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
-	if (!priv)
-		return -ENOMEM;
-	adap = &priv->adap;
-	bit_data = &priv->bit_data;
-	pdata = &priv->pdata;
-
+	/* First get the GPIO pins; if it fails, we'll defer the probe. */
 	if (pdev->dev.of_node) {
-		ret = of_i2c_gpio_probe(pdev->dev.of_node, pdata);
+		ret = of_i2c_gpio_get_pins(pdev->dev.of_node,
+					   &sda_pin, &scl_pin);
 		if (ret)
 			return ret;
 	} else {
 		if (!pdev->dev.platform_data)
 			return -ENXIO;
-		memcpy(pdata, pdev->dev.platform_data, sizeof(*pdata));
+		pdata = pdev->dev.platform_data;
+		sda_pin = pdata->sda_pin;
+		scl_pin = pdata->scl_pin;
 	}
 
-	ret = gpio_request(pdata->sda_pin, "sda");
-	if (ret)
+	ret = gpio_request(sda_pin, "sda");
+	if (ret) {
+		if (ret == -EINVAL)
+			ret = -EPROBE_DEFER;	/* Try again later */
 		goto err_request_sda;
-	ret = gpio_request(pdata->scl_pin, "scl");
-	if (ret)
+	}
+	ret = gpio_request(scl_pin, "scl");
+	if (ret) {
+		if (ret == -EINVAL)
+			ret = -EPROBE_DEFER;	/* Try again later */
 		goto err_request_scl;
+	}
+
+	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		ret = -ENOMEM;
+		goto err_add_bus;
+	}
+	adap = &priv->adap;
+	bit_data = &priv->bit_data;
+	pdata = &priv->pdata;
+
+	if (pdev->dev.of_node) {
+		pdata->sda_pin = sda_pin;
+		pdata->scl_pin = scl_pin;
+		of_i2c_gpio_get_props(pdev->dev.of_node, pdata);
+	} else {
+		memcpy(pdata, pdev->dev.platform_data, sizeof(*pdata));
+	}
 
 	if (pdata->sda_is_open_drain) {
 		gpio_direction_output(pdata->sda_pin, 1);
@@ -211,9 +236,9 @@ static int i2c_gpio_probe(struct platform_device *pdev)
 	return 0;
 
 err_add_bus:
-	gpio_free(pdata->scl_pin);
+	gpio_free(scl_pin);
 err_request_scl:
-	gpio_free(pdata->sda_pin);
+	gpio_free(sda_pin);
 err_request_sda:
 	return ret;
 }
diff --git a/drivers/i2c/busses/i2c-intel-mid.c b/drivers/i2c/busses/i2c-intel-mid.c
index 323fa01..0fb6597 100644
--- a/drivers/i2c/busses/i2c-intel-mid.c
+++ b/drivers/i2c/busses/i2c-intel-mid.c
@@ -1082,8 +1082,7 @@ static void intel_mid_i2c_remove(struct pci_dev *dev)
 {
 	struct intel_mid_i2c_private *mrst = pci_get_drvdata(dev);
 	intel_mid_i2c_disable(&mrst->adap);
-	if (i2c_del_adapter(&mrst->adap))
-		dev_err(&dev->dev, "Failed to delete i2c adapter");
+	i2c_del_adapter(&mrst->adap);
 
 	free_irq(dev->irq, mrst);
 	iounmap(mrst->base);
diff --git a/drivers/i2c/busses/i2c-ismt.c b/drivers/i2c/busses/i2c-ismt.c
index 130f02c..cd82eb4 100644
--- a/drivers/i2c/busses/i2c-ismt.c
+++ b/drivers/i2c/busses/i2c-ismt.c
@@ -183,7 +183,7 @@ struct ismt_priv {
 /**
  * ismt_ids - PCI device IDs supported by this driver
  */
-static const DEFINE_PCI_DEVICE_TABLE(ismt_ids) = {
+static DEFINE_PCI_DEVICE_TABLE(ismt_ids) = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_S1200_SMT0) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_S1200_SMT1) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_AVOTON_SMT) },
diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c
index 8b20ef8..3bbd65d 100644
--- a/drivers/i2c/busses/i2c-mv64xxx.c
+++ b/drivers/i2c/busses/i2c-mv64xxx.c
@@ -701,9 +701,8 @@ static int
 mv64xxx_i2c_remove(struct platform_device *dev)
 {
 	struct mv64xxx_i2c_data		*drv_data = platform_get_drvdata(dev);
-	int	rc;
 
-	rc = i2c_del_adapter(&drv_data->adapter);
+	i2c_del_adapter(&drv_data->adapter);
 	free_irq(drv_data->irq, drv_data);
 	mv64xxx_i2c_unmap_regs(drv_data);
 #if defined(CONFIG_HAVE_CLK)
@@ -715,7 +714,7 @@ mv64xxx_i2c_remove(struct platform_device *dev)
 #endif
 	kfree(drv_data);
 
-	return rc;
+	return 0;
 }
 
 static const struct of_device_id mv64xxx_i2c_of_match_table[] = {
diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c
index 120f246..26d9b82 100644
--- a/drivers/i2c/busses/i2c-mxs.c
+++ b/drivers/i2c/busses/i2c-mxs.c
@@ -31,7 +31,6 @@
 #include <linux/of_i2c.h>
 #include <linux/dma-mapping.h>
 #include <linux/dmaengine.h>
-#include <linux/fsl/mxs-dma.h>
 
 #define DRIVER_NAME "mxs-i2c"
 
@@ -113,9 +112,7 @@ struct mxs_i2c_dev {
 	uint32_t timing1;
 
 	/* DMA support components */
-	int				dma_channel;
 	struct dma_chan         	*dmach;
-	struct mxs_dma_data		dma_data;
 	uint32_t			pio_data[2];
 	uint32_t			addr_data;
 	struct scatterlist		sg_io[2];
@@ -518,21 +515,6 @@ static const struct i2c_algorithm mxs_i2c_algo = {
 	.functionality = mxs_i2c_func,
 };
 
-static bool mxs_i2c_dma_filter(struct dma_chan *chan, void *param)
-{
-	struct mxs_i2c_dev *i2c = param;
-
-	if (!mxs_dma_is_apbx(chan))
-		return false;
-
-	if (chan->chan_id != i2c->dma_channel)
-		return false;
-
-	chan->private = &i2c->dma_data;
-
-	return true;
-}
-
 static void mxs_i2c_derive_timing(struct mxs_i2c_dev *i2c, int speed)
 {
 	/* The I2C block clock run at 24MHz */
@@ -577,17 +559,6 @@ static int mxs_i2c_get_ofdata(struct mxs_i2c_dev *i2c)
 	struct device_node *node = dev->of_node;
 	int ret;
 
-	/*
-	 * TODO: This is a temporary solution and should be changed
-	 * to use generic DMA binding later when the helpers get in.
-	 */
-	ret = of_property_read_u32(node, "fsl,i2c-dma-channel",
-				   &i2c->dma_channel);
-	if (ret) {
-		dev_err(dev, "Failed to get DMA channel!\n");
-		return -ENODEV;
-	}
-
 	ret = of_property_read_u32(node, "clock-frequency", &speed);
 	if (ret) {
 		dev_warn(dev, "No I2C speed selected, using 100kHz\n");
@@ -607,8 +578,7 @@ static int mxs_i2c_probe(struct platform_device *pdev)
 	struct pinctrl *pinctrl;
 	struct resource *res;
 	resource_size_t res_size;
-	int err, irq, dmairq;
-	dma_cap_mask_t mask;
+	int err, irq;
 
 	pinctrl = devm_pinctrl_get_select_default(dev);
 	if (IS_ERR(pinctrl))
@@ -620,9 +590,8 @@ static int mxs_i2c_probe(struct platform_device *pdev)
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	irq = platform_get_irq(pdev, 0);
-	dmairq = platform_get_irq(pdev, 1);
 
-	if (!res || irq < 0 || dmairq < 0)
+	if (!res || irq < 0)
 		return -ENOENT;
 
 	res_size = resource_size(res);
@@ -648,10 +617,7 @@ static int mxs_i2c_probe(struct platform_device *pdev)
 	}
 
 	/* Setup the DMA */
-	dma_cap_zero(mask);
-	dma_cap_set(DMA_SLAVE, mask);
-	i2c->dma_data.chan_irq = dmairq;
-	i2c->dmach = dma_request_channel(mask, mxs_i2c_dma_filter, i2c);
+	i2c->dmach = dma_request_slave_channel(dev, "rx-tx");
 	if (!i2c->dmach) {
 		dev_err(dev, "Failed to request dma\n");
 		return -ENODEV;
@@ -686,11 +652,8 @@ static int mxs_i2c_probe(struct platform_device *pdev)
 static int mxs_i2c_remove(struct platform_device *pdev)
 {
 	struct mxs_i2c_dev *i2c = platform_get_drvdata(pdev);
-	int ret;
 
-	ret = i2c_del_adapter(&i2c->adapter);
-	if (ret)
-		return -EBUSY;
+	i2c_del_adapter(&i2c->adapter);
 
 	if (i2c->dmach)
 		dma_release_channel(i2c->dmach);
diff --git a/drivers/i2c/busses/i2c-nforce2-s4985.c b/drivers/i2c/busses/i2c-nforce2-s4985.c
index 29015eb..2ca268d 100644
--- a/drivers/i2c/busses/i2c-nforce2-s4985.c
+++ b/drivers/i2c/busses/i2c-nforce2-s4985.c
@@ -164,11 +164,7 @@ static int __init nforce2_s4985_init(void)
 	}
 
 	/* Unregister physical bus */
-	error = i2c_del_adapter(nforce2_smbus);
-	if (error) {
-		dev_err(&nforce2_smbus->dev, "Physical bus removal failed\n");
-		goto ERROR0;
-	}
+	i2c_del_adapter(nforce2_smbus);
 
 	printk(KERN_INFO "Enabling SMBus multiplexing for Tyan S4985\n");
 	/* Define the 5 virtual adapters and algorithms structures */
diff --git a/drivers/i2c/busses/i2c-powermac.c b/drivers/i2c/busses/i2c-powermac.c
index da54e67..8dc90da 100644
--- a/drivers/i2c/busses/i2c-powermac.c
+++ b/drivers/i2c/busses/i2c-powermac.c
@@ -213,14 +213,8 @@ static const struct i2c_algorithm i2c_powermac_algorithm = {
 static int i2c_powermac_remove(struct platform_device *dev)
 {
 	struct i2c_adapter	*adapter = platform_get_drvdata(dev);
-	int			rc;
-
-	rc = i2c_del_adapter(adapter);
-	/* We aren't that prepared to deal with this... */
-	if (rc)
-		printk(KERN_WARNING
-		       "i2c-powermac.c: Failed to remove bus %s !\n",
-		       adapter->name);
+
+	i2c_del_adapter(adapter);
 	memset(adapter, 0, sizeof(*adapter));
 
 	return 0;
diff --git a/drivers/i2c/busses/i2c-puv3.c b/drivers/i2c/busses/i2c-puv3.c
index 261d7db..37a84c8 100644
--- a/drivers/i2c/busses/i2c-puv3.c
+++ b/drivers/i2c/busses/i2c-puv3.c
@@ -199,7 +199,7 @@ static int puv3_i2c_probe(struct platform_device *pdev)
 
 	adapter = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL);
 	if (adapter == NULL) {
-		dev_err(&pdev->dev, "can't allocate inteface!\n");
+		dev_err(&pdev->dev, "can't allocate interface!\n");
 		rc = -ENOMEM;
 		goto fail_nomem;
 	}
@@ -234,21 +234,15 @@ static int puv3_i2c_remove(struct platform_device *pdev)
 {
 	struct i2c_adapter *adapter = platform_get_drvdata(pdev);
 	struct resource *mem;
-	int rc;
 
-	rc = i2c_del_adapter(adapter);
-	if (rc) {
-		dev_err(&pdev->dev, "Adapter '%s' delete fail\n",
-				adapter->name);
-		return rc;
-	}
+	i2c_del_adapter(adapter);
 
 	put_device(&pdev->dev);
 
 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	release_mem_region(mem->start, resource_size(mem));
 
-	return rc;
+	return 0;
 }
 
 #ifdef CONFIG_PM
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
index 1e88e8d..ea6d45d 100644
--- a/drivers/i2c/busses/i2c-pxa.c
+++ b/drivers/i2c/busses/i2c-pxa.c
@@ -1053,16 +1053,13 @@ static int i2c_pxa_probe_dt(struct platform_device *pdev, struct pxa_i2c *i2c,
 	struct device_node *np = pdev->dev.of_node;
 	const struct of_device_id *of_id =
 			of_match_device(i2c_pxa_dt_ids, &pdev->dev);
-	int ret;
 
 	if (!of_id)
 		return 1;
-	ret = of_alias_get_id(np, "i2c");
-	if (ret < 0) {
-		dev_err(&pdev->dev, "failed to get alias id, errno %d\n", ret);
-		return ret;
-	}
-	pdev->id = ret;
+
+	/* For device tree we always use the dynamic or alias-assigned ID */
+	i2c->adap.nr = -1;
+
 	if (of_get_property(np, "mrvl,i2c-polling", NULL))
 		i2c->use_pio = 1;
 	if (of_get_property(np, "mrvl,i2c-fast-mode", NULL))
@@ -1100,6 +1097,9 @@ static int i2c_pxa_probe(struct platform_device *dev)
 		goto emalloc;
 	}
 
+	/* Default adapter num to device id; i2c_pxa_probe_dt can override. */
+	i2c->adap.nr = dev->id;
+
 	ret = i2c_pxa_probe_dt(dev, i2c, &i2c_type);
 	if (ret > 0)
 		ret = i2c_pxa_probe_pdata(dev, i2c, &i2c_type);
@@ -1124,9 +1124,7 @@ static int i2c_pxa_probe(struct platform_device *dev)
 	spin_lock_init(&i2c->lock);
 	init_waitqueue_head(&i2c->wait);
 
-	i2c->adap.nr = dev->id;
-	snprintf(i2c->adap.name, sizeof(i2c->adap.name), "pxa_i2c-i2c.%u",
-		 i2c->adap.nr);
+	strlcpy(i2c->adap.name, "pxa_i2c-i2c", sizeof(i2c->adap.name));
 
 	i2c->clk = clk_get(&dev->dev, NULL);
 	if (IS_ERR(i2c->clk)) {
@@ -1169,7 +1167,7 @@ static int i2c_pxa_probe(struct platform_device *dev)
 	} else {
 		i2c->adap.algo = &i2c_pxa_algorithm;
 		ret = request_irq(irq, i2c_pxa_handler, IRQF_SHARED,
-				  i2c->adap.name, i2c);
+				  dev_name(&dev->dev), i2c);
 		if (ret)
 			goto ereqirq;
 	}
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index f6b880b..0a81f1f 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -42,9 +42,46 @@
 
 #include <asm/irq.h>
 
-#include <plat/regs-iic.h>
 #include <linux/platform_data/i2c-s3c2410.h>
 
+/* see s3c2410x user guide, v1.1, section 9 (p447) for more info */
+
+#define S3C2410_IICCON			0x00
+#define S3C2410_IICSTAT			0x04
+#define S3C2410_IICADD			0x08
+#define S3C2410_IICDS			0x0C
+#define S3C2440_IICLC			0x10
+
+#define S3C2410_IICCON_ACKEN		(1 << 7)
+#define S3C2410_IICCON_TXDIV_16		(0 << 6)
+#define S3C2410_IICCON_TXDIV_512	(1 << 6)
+#define S3C2410_IICCON_IRQEN		(1 << 5)
+#define S3C2410_IICCON_IRQPEND		(1 << 4)
+#define S3C2410_IICCON_SCALE(x)		((x) & 0xf)
+#define S3C2410_IICCON_SCALEMASK	(0xf)
+
+#define S3C2410_IICSTAT_MASTER_RX	(2 << 6)
+#define S3C2410_IICSTAT_MASTER_TX	(3 << 6)
+#define S3C2410_IICSTAT_SLAVE_RX	(0 << 6)
+#define S3C2410_IICSTAT_SLAVE_TX	(1 << 6)
+#define S3C2410_IICSTAT_MODEMASK	(3 << 6)
+
+#define S3C2410_IICSTAT_START		(1 << 5)
+#define S3C2410_IICSTAT_BUSBUSY		(1 << 5)
+#define S3C2410_IICSTAT_TXRXEN		(1 << 4)
+#define S3C2410_IICSTAT_ARBITR		(1 << 3)
+#define S3C2410_IICSTAT_ASSLAVE		(1 << 2)
+#define S3C2410_IICSTAT_ADDR0		(1 << 1)
+#define S3C2410_IICSTAT_LASTBIT		(1 << 0)
+
+#define S3C2410_IICLC_SDA_DELAY0	(0 << 0)
+#define S3C2410_IICLC_SDA_DELAY5	(1 << 0)
+#define S3C2410_IICLC_SDA_DELAY10	(2 << 0)
+#define S3C2410_IICLC_SDA_DELAY15	(3 << 0)
+#define S3C2410_IICLC_SDA_DELAY_MASK	(3 << 0)
+
+#define S3C2410_IICLC_FILTER_ON		(1 << 2)
+
 /* Treat S3C2410 as baseline hardware, anything else is supported via quirks */
 #define QUIRK_S3C2440		(1 << 0)
 #define QUIRK_HDMIPHY		(1 << 1)
diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index b714776..b60ff90 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -25,7 +25,6 @@
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
-#include <linux/i2c-tegra.h>
 #include <linux/of_i2c.h>
 #include <linux/of_device.h>
 #include <linux/module.h>
@@ -172,7 +171,7 @@ struct tegra_i2c_dev {
 	u8 *msg_buf;
 	size_t msg_buf_remaining;
 	int msg_read;
-	unsigned long bus_clk_rate;
+	u32 bus_clk_rate;
 	bool is_suspended;
 };
 
@@ -694,7 +693,6 @@ static const struct tegra_i2c_hw_feature tegra114_i2c_hw = {
 	.clk_divisor_std_fast_mode = 0x19,
 };
 
-#if defined(CONFIG_OF)
 /* Match table for of_platform binding */
 static const struct of_device_id tegra_i2c_of_match[] = {
 	{ .compatible = "nvidia,tegra114-i2c", .data = &tegra114_i2c_hw, },
@@ -704,16 +702,13 @@ static const struct of_device_id tegra_i2c_of_match[] = {
 	{},
 };
 MODULE_DEVICE_TABLE(of, tegra_i2c_of_match);
-#endif
 
 static int tegra_i2c_probe(struct platform_device *pdev)
 {
 	struct tegra_i2c_dev *i2c_dev;
-	struct tegra_i2c_platform_data *pdata = pdev->dev.platform_data;
 	struct resource *res;
 	struct clk *div_clk;
 	struct clk *fast_clk;
-	const unsigned int *prop;
 	void __iomem *base;
 	int irq;
 	int ret = 0;
@@ -754,23 +749,16 @@ static int tegra_i2c_probe(struct platform_device *pdev)
 	i2c_dev->cont_id = pdev->id;
 	i2c_dev->dev = &pdev->dev;
 
-	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);
-	}
+	ret = of_property_read_u32(i2c_dev->dev->of_node, "clock-frequency",
+					&i2c_dev->bus_clk_rate);
+	if (ret)
+		i2c_dev->bus_clk_rate = 100000; /* default clock rate */
 
 	i2c_dev->hw = &tegra20_i2c_hw;
 
 	if (pdev->dev.of_node) {
 		const struct of_device_id *match;
-		match = of_match_device(of_match_ptr(tegra_i2c_of_match),
-						&pdev->dev);
+		match = of_match_device(tegra_i2c_of_match, &pdev->dev);
 		i2c_dev->hw = match->data;
 		i2c_dev->is_dvc = of_device_is_compatible(pdev->dev.of_node,
 						"nvidia,tegra20-i2c-dvc");
@@ -876,7 +864,7 @@ static struct platform_driver tegra_i2c_driver = {
 	.driver  = {
 		.name  = "tegra-i2c",
 		.owner = THIS_MODULE,
-		.of_match_table = of_match_ptr(tegra_i2c_of_match),
+		.of_match_table = tegra_i2c_of_match,
 		.pm    = TEGRA_I2C_PM,
 	},
 };
diff --git a/drivers/i2c/busses/i2c-viperboard.c b/drivers/i2c/busses/i2c-viperboard.c
index f45c32c..c68450c 100644
--- a/drivers/i2c/busses/i2c-viperboard.c
+++ b/drivers/i2c/busses/i2c-viperboard.c
@@ -421,11 +421,10 @@ error:
 static int vprbrd_i2c_remove(struct platform_device *pdev)
 {
 	struct vprbrd_i2c *vb_i2c = platform_get_drvdata(pdev);
-	int ret;
 
-	ret = i2c_del_adapter(&vb_i2c->i2c);
+	i2c_del_adapter(&vb_i2c->i2c);
 
-	return ret;
+	return 0;
 }
 
 static struct platform_driver vprbrd_i2c_driver = {
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 991d38d..e9ac0d8 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -27,7 +27,9 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
+#include <linux/delay.h>
 #include <linux/errno.h>
+#include <linux/gpio.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
 #include <linux/init.h>
@@ -47,7 +49,7 @@
 
 /* core_lock protects i2c_adapter_idr, and guarantees
    that device detection, deletion of detected devices, and attach_adapter
-   and detach_adapter calls are serialized */
+   calls are serialized */
 static DEFINE_MUTEX(core_lock);
 static DEFINE_IDR(i2c_adapter_idr);
 
@@ -109,6 +111,130 @@ static int i2c_device_uevent(struct device *dev, struct kobj_uevent_env *env)
 #define i2c_device_uevent	NULL
 #endif	/* CONFIG_HOTPLUG */
 
+/* i2c bus recovery routines */
+static int get_scl_gpio_value(struct i2c_adapter *adap)
+{
+	return gpio_get_value(adap->bus_recovery_info->scl_gpio);
+}
+
+static void set_scl_gpio_value(struct i2c_adapter *adap, int val)
+{
+	gpio_set_value(adap->bus_recovery_info->scl_gpio, val);
+}
+
+static int get_sda_gpio_value(struct i2c_adapter *adap)
+{
+	return gpio_get_value(adap->bus_recovery_info->sda_gpio);
+}
+
+static int i2c_get_gpios_for_recovery(struct i2c_adapter *adap)
+{
+	struct i2c_bus_recovery_info *bri = adap->bus_recovery_info;
+	struct device *dev = &adap->dev;
+	int ret = 0;
+
+	ret = gpio_request_one(bri->scl_gpio, GPIOF_OPEN_DRAIN |
+			GPIOF_OUT_INIT_HIGH, "i2c-scl");
+	if (ret) {
+		dev_warn(dev, "Can't get SCL gpio: %d\n", bri->scl_gpio);
+		return ret;
+	}
+
+	if (bri->get_sda) {
+		if (gpio_request_one(bri->sda_gpio, GPIOF_IN, "i2c-sda")) {
+			/* work without SDA polling */
+			dev_warn(dev, "Can't get SDA gpio: %d. Not using SDA polling\n",
+					bri->sda_gpio);
+			bri->get_sda = NULL;
+		}
+	}
+
+	return ret;
+}
+
+static void i2c_put_gpios_for_recovery(struct i2c_adapter *adap)
+{
+	struct i2c_bus_recovery_info *bri = adap->bus_recovery_info;
+
+	if (bri->get_sda)
+		gpio_free(bri->sda_gpio);
+
+	gpio_free(bri->scl_gpio);
+}
+
+/*
+ * We are generating clock pulses. ndelay() determines durating of clk pulses.
+ * We will generate clock with rate 100 KHz and so duration of both clock levels
+ * is: delay in ns = (10^6 / 100) / 2
+ */
+#define RECOVERY_NDELAY		5000
+#define RECOVERY_CLK_CNT	9
+
+static int i2c_generic_recovery(struct i2c_adapter *adap)
+{
+	struct i2c_bus_recovery_info *bri = adap->bus_recovery_info;
+	int i = 0, val = 1, ret = 0;
+
+	if (bri->prepare_recovery)
+		bri->prepare_recovery(bri);
+
+	/*
+	 * By this time SCL is high, as we need to give 9 falling-rising edges
+	 */
+	while (i++ < RECOVERY_CLK_CNT * 2) {
+		if (val) {
+			/* Break if SDA is high */
+			if (bri->get_sda && bri->get_sda(adap))
+					break;
+			/* SCL shouldn't be low here */
+			if (!bri->get_scl(adap)) {
+				dev_err(&adap->dev,
+					"SCL is stuck low, exit recovery\n");
+				ret = -EBUSY;
+				break;
+			}
+		}
+
+		val = !val;
+		bri->set_scl(adap, val);
+		ndelay(RECOVERY_NDELAY);
+	}
+
+	if (bri->unprepare_recovery)
+		bri->unprepare_recovery(bri);
+
+	return ret;
+}
+
+int i2c_generic_scl_recovery(struct i2c_adapter *adap)
+{
+	adap->bus_recovery_info->set_scl(adap, 1);
+	return i2c_generic_recovery(adap);
+}
+
+int i2c_generic_gpio_recovery(struct i2c_adapter *adap)
+{
+	int ret;
+
+	ret = i2c_get_gpios_for_recovery(adap);
+	if (ret)
+		return ret;
+
+	ret = i2c_generic_recovery(adap);
+	i2c_put_gpios_for_recovery(adap);
+
+	return ret;
+}
+
+int i2c_recover_bus(struct i2c_adapter *adap)
+{
+	if (!adap->bus_recovery_info)
+		return -EOPNOTSUPP;
+
+	dev_dbg(&adap->dev, "Trying i2c bus recovery\n");
+	return adap->bus_recovery_info->recover_bus(adap);
+}
+
 static int i2c_device_probe(struct device *dev)
 {
 	struct i2c_client	*client = i2c_verify_client(dev);
@@ -902,6 +1028,39 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
 			 "Failed to create compatibility class link\n");
 #endif
 
+	/* bus recovery specific initialization */
+	if (adap->bus_recovery_info) {
+		struct i2c_bus_recovery_info *bri = adap->bus_recovery_info;
+
+		if (!bri->recover_bus) {
+			dev_err(&adap->dev, "No recover_bus() found, not using recovery\n");
+			adap->bus_recovery_info = NULL;
+			goto exit_recovery;
+		}
+
+		/* Generic GPIO recovery */
+		if (bri->recover_bus == i2c_generic_gpio_recovery) {
+			if (!gpio_is_valid(bri->scl_gpio)) {
+				dev_err(&adap->dev, "Invalid SCL gpio, not using recovery\n");
+				adap->bus_recovery_info = NULL;
+				goto exit_recovery;
+			}
+
+			if (gpio_is_valid(bri->sda_gpio))
+				bri->get_sda = get_sda_gpio_value;
+			else
+				bri->get_sda = NULL;
+
+			bri->get_scl = get_scl_gpio_value;
+			bri->set_scl = set_scl_gpio_value;
+		} else if (!bri->set_scl || !bri->get_scl) {
+			/* Generic SCL recovery */
+			dev_err(&adap->dev, "No {get|set}_gpio() found, not using recovery\n");
+			adap->bus_recovery_info = NULL;
+		}
+	}
+
+exit_recovery:
 	/* create pre-declared device nodes */
 	if (adap->nr < __i2c_first_dynamic_bus_num)
 		i2c_scan_static_board_info(adap);
@@ -921,13 +1080,35 @@ out_list:
 }
 
 /**
+ * __i2c_add_numbered_adapter - i2c_add_numbered_adapter where nr is never -1
+ * @adap: the adapter to register (with adap->nr initialized)
+ * Context: can sleep
+ *
+ * See i2c_add_numbered_adapter() for details.
+ */
+static int __i2c_add_numbered_adapter(struct i2c_adapter *adap)
+{
+	int	id;
+
+	mutex_lock(&core_lock);
+	id = idr_alloc(&i2c_adapter_idr, adap, adap->nr, adap->nr + 1,
+		       GFP_KERNEL);
+	mutex_unlock(&core_lock);
+	if (id < 0)
+		return id == -ENOSPC ? -EBUSY : id;
+
+	return i2c_register_adapter(adap);
+}
+
+/**
  * i2c_add_adapter - declare i2c adapter, use dynamic bus number
  * @adapter: the adapter to add
  * Context: can sleep
  *
  * This routine is used to declare an I2C adapter when its bus number
- * doesn't matter.  Examples: for I2C adapters dynamically added by
- * USB links or PCI plugin cards.
+ * doesn't matter or when its bus number is specified by an dt alias.
+ * Examples of bases when the bus number doesn't matter: I2C adapters
+ * dynamically added by USB links or PCI plugin cards.
  *
  * When this returns zero, a new bus number was allocated and stored
  * in adap->nr, and the specified adapter became available for clients.
@@ -935,8 +1116,17 @@ out_list:
  */
 int i2c_add_adapter(struct i2c_adapter *adapter)
 {
+	struct device *dev = &adapter->dev;
 	int id;
 
+	if (dev->of_node) {
+		id = of_alias_get_id(dev->of_node, "i2c");
+		if (id >= 0) {
+			adapter->nr = id;
+			return __i2c_add_numbered_adapter(adapter);
+		}
+	}
+
 	mutex_lock(&core_lock);
 	id = idr_alloc(&i2c_adapter_idr, adapter,
 		       __i2c_first_dynamic_bus_num, 0, GFP_KERNEL);
@@ -975,26 +1165,17 @@ EXPORT_SYMBOL(i2c_add_adapter);
  */
 int i2c_add_numbered_adapter(struct i2c_adapter *adap)
 {
-	int	id;
-
 	if (adap->nr == -1) /* -1 means dynamically assign bus id */
 		return i2c_add_adapter(adap);
 
-	mutex_lock(&core_lock);
-	id = idr_alloc(&i2c_adapter_idr, adap, adap->nr, adap->nr + 1,
-		       GFP_KERNEL);
-	mutex_unlock(&core_lock);
-	if (id < 0)
-		return id == -ENOSPC ? -EBUSY : id;
-	return i2c_register_adapter(adap);
+	return __i2c_add_numbered_adapter(adap);
 }
 EXPORT_SYMBOL_GPL(i2c_add_numbered_adapter);
 
-static int i2c_do_del_adapter(struct i2c_driver *driver,
+static void i2c_do_del_adapter(struct i2c_driver *driver,
 			      struct i2c_adapter *adapter)
 {
 	struct i2c_client *client, *_n;
-	int res;
 
 	/* Remove the devices we created ourselves as the result of hardware
 	 * probing (using a driver's detect method) */
@@ -1006,16 +1187,6 @@ static int i2c_do_del_adapter(struct i2c_driver *driver,
 			i2c_unregister_device(client);
 		}
 	}
-
-	if (!driver->detach_adapter)
-		return 0;
-	dev_warn(&adapter->dev, "%s: detach_adapter method is deprecated\n",
-		 driver->driver.name);
-	res = driver->detach_adapter(adapter);
-	if (res)
-		dev_err(&adapter->dev, "detach_adapter failed (%d) "
-			"for driver [%s]\n", res, driver->driver.name);
-	return res;
 }
 
 static int __unregister_client(struct device *dev, void *dummy)
@@ -1036,7 +1207,8 @@ static int __unregister_dummy(struct device *dev, void *dummy)
 
 static int __process_removed_adapter(struct device_driver *d, void *data)
 {
-	return i2c_do_del_adapter(to_i2c_driver(d), data);
+	i2c_do_del_adapter(to_i2c_driver(d), data);
+	return 0;
 }
 
 /**
@@ -1047,9 +1219,8 @@ static int __process_removed_adapter(struct device_driver *d, void *data)
  * This unregisters an I2C adapter which was previously registered
  * by @i2c_add_adapter or @i2c_add_numbered_adapter.
  */
-int i2c_del_adapter(struct i2c_adapter *adap)
+void i2c_del_adapter(struct i2c_adapter *adap)
 {
-	int res = 0;
 	struct i2c_adapter *found;
 	struct i2c_client *client, *next;
 
@@ -1060,16 +1231,14 @@ int i2c_del_adapter(struct i2c_adapter *adap)
 	if (found != adap) {
 		pr_debug("i2c-core: attempting to delete unregistered "
 			 "adapter [%s]\n", adap->name);
-		return -EINVAL;
+		return;
 	}
 
 	/* Tell drivers about this removal */
 	mutex_lock(&core_lock);
-	res = bus_for_each_drv(&i2c_bus_type, NULL, adap,
+	bus_for_each_drv(&i2c_bus_type, NULL, adap,
 			       __process_removed_adapter);
 	mutex_unlock(&core_lock);
-	if (res)
-		return res;
 
 	/* Remove devices instantiated from sysfs */
 	mutex_lock_nested(&adap->userspace_clients_lock,
@@ -1088,8 +1257,8 @@ int i2c_del_adapter(struct i2c_adapter *adap)
 	 * we can't remove the dummy devices during the first pass: they
 	 * could have been instantiated by real devices wishing to clean
 	 * them up properly, so we give them a chance to do that first. */
-	res = device_for_each_child(&adap->dev, NULL, __unregister_client);
-	res = device_for_each_child(&adap->dev, NULL, __unregister_dummy);
+	device_for_each_child(&adap->dev, NULL, __unregister_client);
+	device_for_each_child(&adap->dev, NULL, __unregister_dummy);
 
 #ifdef CONFIG_I2C_COMPAT
 	class_compat_remove_link(i2c_adapter_compat_class, &adap->dev,
@@ -1114,8 +1283,6 @@ int i2c_del_adapter(struct i2c_adapter *adap)
 	/* Clear the device structure in case this adapter is ever going to be
 	   added again */
 	memset(&adap->dev, 0, sizeof(adap->dev));
-
-	return 0;
 }
 EXPORT_SYMBOL(i2c_del_adapter);
 
@@ -1185,9 +1352,9 @@ EXPORT_SYMBOL(i2c_register_driver);
 
 static int __process_removed_driver(struct device *dev, void *data)
 {
-	if (dev->type != &i2c_adapter_type)
-		return 0;
-	return i2c_do_del_adapter(data, to_i2c_adapter(dev));
+	if (dev->type == &i2c_adapter_type)
+		i2c_do_del_adapter(data, to_i2c_adapter(dev));
+	return 0;
 }
 
 /**
diff --git a/drivers/i2c/i2c-mux.c b/drivers/i2c/i2c-mux.c
index d94e0ce..7409ebb 100644
--- a/drivers/i2c/i2c-mux.c
+++ b/drivers/i2c/i2c-mux.c
@@ -191,17 +191,12 @@ struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent,
 }
 EXPORT_SYMBOL_GPL(i2c_add_mux_adapter);
 
-int i2c_del_mux_adapter(struct i2c_adapter *adap)
+void i2c_del_mux_adapter(struct i2c_adapter *adap)
 {
 	struct i2c_mux_priv *priv = adap->algo_data;
-	int ret;
 
-	ret = i2c_del_adapter(adap);
-	if (ret < 0)
-		return ret;
+	i2c_del_adapter(adap);
 	kfree(priv);
-
-	return 0;
 }
 EXPORT_SYMBOL_GPL(i2c_del_mux_adapter);
 
diff --git a/drivers/i2c/muxes/i2c-mux-gpio.c b/drivers/i2c/muxes/i2c-mux-gpio.c
index abc2e55a..5a0ce00 100644
--- a/drivers/i2c/muxes/i2c-mux-gpio.c
+++ b/drivers/i2c/muxes/i2c-mux-gpio.c
@@ -201,10 +201,21 @@ static int i2c_mux_gpio_probe(struct platform_device *pdev)
 
 	for (i = 0; i < mux->data.n_gpios; i++) {
 		ret = gpio_request(gpio_base + mux->data.gpios[i], "i2c-mux-gpio");
-		if (ret)
+		if (ret) {
+			dev_err(&pdev->dev, "Failed to request GPIO %d\n",
+				mux->data.gpios[i]);
 			goto err_request_gpio;
-		gpio_direction_output(gpio_base + mux->data.gpios[i],
-				      initial_state & (1 << i));
+		}
+
+		ret = gpio_direction_output(gpio_base + mux->data.gpios[i],
+					    initial_state & (1 << i));
+		if (ret) {
+			dev_err(&pdev->dev,
+				"Failed to set direction of GPIO %d to output\n",
+				mux->data.gpios[i]);
+			i++;	/* gpio_request above succeeded, so must free */
+			goto err_request_gpio;
+		}
 	}
 
 	for (i = 0; i < mux->data.n_values; i++) {
diff --git a/drivers/i2c/muxes/i2c-mux-pca954x.c b/drivers/i2c/muxes/i2c-mux-pca954x.c
index 8e43872..a531d80 100644
--- a/drivers/i2c/muxes/i2c-mux-pca954x.c
+++ b/drivers/i2c/muxes/i2c-mux-pca954x.c
@@ -262,13 +262,11 @@ static int pca954x_remove(struct i2c_client *client)
 {
 	struct pca954x *data = i2c_get_clientdata(client);
 	const struct chip_desc *chip = &chips[data->type];
-	int i, err;
+	int i;
 
 	for (i = 0; i < chip->nchans; ++i)
 		if (data->virt_adaps[i]) {
-			err = i2c_del_mux_adapter(data->virt_adaps[i]);
-			if (err)
-				return err;
+			i2c_del_mux_adapter(data->virt_adaps[i]);
 			data->virt_adaps[i] = NULL;
 		}
 
diff --git a/drivers/ide/gayle.c b/drivers/ide/gayle.c
index 51beb85..0a8440a 100644
--- a/drivers/ide/gayle.c
+++ b/drivers/ide/gayle.c
@@ -183,20 +183,7 @@ static struct platform_driver amiga_gayle_ide_driver = {
 	},
 };
 
-static int __init amiga_gayle_ide_init(void)
-{
-	return platform_driver_probe(&amiga_gayle_ide_driver,
-				     amiga_gayle_ide_probe);
-}
-
-module_init(amiga_gayle_ide_init);
-
-static void __exit amiga_gayle_ide_exit(void)
-{
-	platform_driver_unregister(&amiga_gayle_ide_driver);
-}
-
-module_exit(amiga_gayle_ide_exit);
+module_platform_driver_probe(amiga_gayle_ide_driver, amiga_gayle_ide_probe);
 
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:amiga-gayle-ide");
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 8126824..b231139 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -1408,7 +1408,7 @@ static int idecd_capacity_proc_show(struct seq_file *m, void *v)
 
 static int idecd_capacity_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, idecd_capacity_proc_show, PDE(inode)->data);
+	return single_open(file, idecd_capacity_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations idecd_capacity_proc_fops = {
diff --git a/drivers/ide/ide-disk_proc.c b/drivers/ide/ide-disk_proc.c
index 8b570a1..0d1fae6 100644
--- a/drivers/ide/ide-disk_proc.c
+++ b/drivers/ide/ide-disk_proc.c
@@ -53,7 +53,7 @@ static int idedisk_cache_proc_show(struct seq_file *m, void *v)
 
 static int idedisk_cache_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, idedisk_cache_proc_show, PDE(inode)->data);
+	return single_open(file, idedisk_cache_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations idedisk_cache_proc_fops = {
@@ -74,7 +74,7 @@ static int idedisk_capacity_proc_show(struct seq_file *m, void *v)
 
 static int idedisk_capacity_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, idedisk_capacity_proc_show, PDE(inode)->data);
+	return single_open(file, idedisk_capacity_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations idedisk_capacity_proc_fops = {
@@ -115,7 +115,7 @@ static int idedisk_sv_proc_show(struct seq_file *m, void *v)
 
 static int idedisk_sv_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, idedisk_sv_proc_show, PDE(inode)->data);
+	return single_open(file, idedisk_sv_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations idedisk_sv_proc_fops = {
@@ -133,7 +133,7 @@ static int idedisk_st_proc_show(struct seq_file *m, void *v)
 
 static int idedisk_st_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, idedisk_st_proc_show, PDE(inode)->data);
+	return single_open(file, idedisk_st_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations idedisk_st_proc_fops = {
diff --git a/drivers/ide/ide-floppy_proc.c b/drivers/ide/ide-floppy_proc.c
index 1600720..e7a25ea 100644
--- a/drivers/ide/ide-floppy_proc.c
+++ b/drivers/ide/ide-floppy_proc.c
@@ -15,7 +15,7 @@ static int idefloppy_capacity_proc_show(struct seq_file *m, void *v)
 
 static int idefloppy_capacity_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, idefloppy_capacity_proc_show, PDE(inode)->data);
+	return single_open(file, idefloppy_capacity_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations idefloppy_capacity_proc_fops = {
diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c
index 2abcc47..97c0700 100644
--- a/drivers/ide/ide-proc.c
+++ b/drivers/ide/ide-proc.c
@@ -58,7 +58,7 @@ static int ide_imodel_proc_show(struct seq_file *m, void *v)
 
 static int ide_imodel_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, ide_imodel_proc_show, PDE(inode)->data);
+	return single_open(file, ide_imodel_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations ide_imodel_proc_fops = {
@@ -82,7 +82,7 @@ static int ide_mate_proc_show(struct seq_file *m, void *v)
 
 static int ide_mate_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, ide_mate_proc_show, PDE(inode)->data);
+	return single_open(file, ide_mate_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations ide_mate_proc_fops = {
@@ -103,7 +103,7 @@ static int ide_channel_proc_show(struct seq_file *m, void *v)
 
 static int ide_channel_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, ide_channel_proc_show, PDE(inode)->data);
+	return single_open(file, ide_channel_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations ide_channel_proc_fops = {
@@ -143,7 +143,7 @@ static int ide_identify_proc_show(struct seq_file *m, void *v)
 
 static int ide_identify_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, ide_identify_proc_show, PDE(inode)->data);
+	return single_open(file, ide_identify_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations ide_identify_proc_fops = {
@@ -325,7 +325,7 @@ static int ide_settings_proc_show(struct seq_file *m, void *v)
 
 static int ide_settings_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, ide_settings_proc_show, PDE(inode)->data);
+	return single_open(file, ide_settings_proc_show, PDE_DATA(inode));
 }
 
 #define MAX_LEN	30
@@ -333,7 +333,7 @@ static int ide_settings_proc_open(struct inode *inode, struct file *file)
 static ssize_t ide_settings_proc_write(struct file *file, const char __user *buffer,
 				       size_t count, loff_t *pos)
 {
-	ide_drive_t	*drive = (ide_drive_t *) PDE(file_inode(file))->data;
+	ide_drive_t	*drive = PDE_DATA(file_inode(file));
 	char		name[MAX_LEN + 1];
 	int		for_real = 0, mul_factor, div_factor;
 	unsigned long	n;
@@ -474,7 +474,7 @@ static int ide_geometry_proc_show(struct seq_file *m, void *v)
 
 static int ide_geometry_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, ide_geometry_proc_show, PDE(inode)->data);
+	return single_open(file, ide_geometry_proc_show, PDE_DATA(inode));
 }
 
 const struct file_operations ide_geometry_proc_fops = {
@@ -497,7 +497,7 @@ static int ide_dmodel_proc_show(struct seq_file *seq, void *v)
 
 static int ide_dmodel_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, ide_dmodel_proc_show, PDE(inode)->data);
+	return single_open(file, ide_dmodel_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations ide_dmodel_proc_fops = {
@@ -525,7 +525,7 @@ static int ide_driver_proc_show(struct seq_file *m, void *v)
 
 static int ide_driver_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, ide_driver_proc_show, PDE(inode)->data);
+	return single_open(file, ide_driver_proc_show, PDE_DATA(inode));
 }
 
 static int ide_replace_subdriver(ide_drive_t *drive, const char *driver)
@@ -558,7 +558,7 @@ static int ide_replace_subdriver(ide_drive_t *drive, const char *driver)
 static ssize_t ide_driver_proc_write(struct file *file, const char __user *buffer,
 				     size_t count, loff_t *pos)
 {
-	ide_drive_t	*drive = (ide_drive_t *) PDE(file_inode(file))->data;
+	ide_drive_t	*drive = PDE_DATA(file_inode(file));
 	char name[32];
 
 	if (!capable(CAP_SYS_ADMIN))
@@ -601,7 +601,7 @@ static int ide_media_proc_show(struct seq_file *m, void *v)
 
 static int ide_media_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, ide_media_proc_show, PDE(inode)->data);
+	return single_open(file, ide_media_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations ide_media_proc_fops = {
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index ce8237d..89f8595 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -1847,7 +1847,7 @@ static int idetape_name_proc_show(struct seq_file *m, void *v)
 
 static int idetape_name_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, idetape_name_proc_show, PDE(inode)->data);
+	return single_open(file, idetape_name_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations idetape_name_proc_fops = {
diff --git a/drivers/ide/tx4938ide.c b/drivers/ide/tx4938ide.c
index 91d49dd..ede8575 100644
--- a/drivers/ide/tx4938ide.c
+++ b/drivers/ide/tx4938ide.c
@@ -203,18 +203,7 @@ static struct platform_driver tx4938ide_driver = {
 	.remove = __exit_p(tx4938ide_remove),
 };
 
-static int __init tx4938ide_init(void)
-{
-	return platform_driver_probe(&tx4938ide_driver, tx4938ide_probe);
-}
-
-static void __exit tx4938ide_exit(void)
-{
-	platform_driver_unregister(&tx4938ide_driver);
-}
-
-module_init(tx4938ide_init);
-module_exit(tx4938ide_exit);
+module_platform_driver_probe(tx4938ide_driver, tx4938ide_probe);
 
 MODULE_DESCRIPTION("TX4938 internal IDE driver");
 MODULE_LICENSE("GPL");
diff --git a/drivers/ide/tx4939ide.c b/drivers/ide/tx4939ide.c
index c0ab800..4ecdee5 100644
--- a/drivers/ide/tx4939ide.c
+++ b/drivers/ide/tx4939ide.c
@@ -624,18 +624,7 @@ static struct platform_driver tx4939ide_driver = {
 	.resume = tx4939ide_resume,
 };
 
-static int __init tx4939ide_init(void)
-{
-	return platform_driver_probe(&tx4939ide_driver, tx4939ide_probe);
-}
-
-static void __exit tx4939ide_exit(void)
-{
-	platform_driver_unregister(&tx4939ide_driver);
-}
-
-module_init(tx4939ide_init);
-module_exit(tx4939ide_exit);
+module_platform_driver_probe(tx4939ide_driver, tx4939ide_probe);
 
 MODULE_DESCRIPTION("TX4939 internal IDE driver");
 MODULE_LICENSE("GPL");
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index 5d66750..1a38dd7 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -465,6 +465,7 @@ static const struct x86_cpu_id intel_idle_ids[] = {
 	ICPU(0x3c, idle_cpu_hsw),
 	ICPU(0x3f, idle_cpu_hsw),
 	ICPU(0x45, idle_cpu_hsw),
+	ICPU(0x46, idle_cpu_hsw),
 	{}
 };
 MODULE_DEVICE_TABLE(x86cpu, intel_idle_ids);
diff --git a/drivers/iio/accel/hid-sensor-accel-3d.c b/drivers/iio/accel/hid-sensor-accel-3d.c
index dd8ea42..bbcbd71 100644
--- a/drivers/iio/accel/hid-sensor-accel-3d.c
+++ b/drivers/iio/accel/hid-sensor-accel-3d.c
@@ -60,28 +60,28 @@ static const struct iio_chan_spec accel_3d_channels[] = {
 		.type = IIO_ACCEL,
 		.modified = 1,
 		.channel2 = IIO_MOD_X,
-		.info_mask = IIO_CHAN_INFO_OFFSET_SHARED_BIT |
-		IIO_CHAN_INFO_SCALE_SHARED_BIT |
-		IIO_CHAN_INFO_SAMP_FREQ_SHARED_BIT |
-		IIO_CHAN_INFO_HYSTERESIS_SHARED_BIT,
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
+		BIT(IIO_CHAN_INFO_SCALE) |
+		BIT(IIO_CHAN_INFO_SAMP_FREQ) |
+		BIT(IIO_CHAN_INFO_HYSTERESIS),
 		.scan_index = CHANNEL_SCAN_INDEX_X,
 	}, {
 		.type = IIO_ACCEL,
 		.modified = 1,
 		.channel2 = IIO_MOD_Y,
-		.info_mask = IIO_CHAN_INFO_OFFSET_SHARED_BIT |
-		IIO_CHAN_INFO_SCALE_SHARED_BIT |
-		IIO_CHAN_INFO_SAMP_FREQ_SHARED_BIT |
-		IIO_CHAN_INFO_HYSTERESIS_SHARED_BIT,
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
+		BIT(IIO_CHAN_INFO_SCALE) |
+		BIT(IIO_CHAN_INFO_SAMP_FREQ) |
+		BIT(IIO_CHAN_INFO_HYSTERESIS),
 		.scan_index = CHANNEL_SCAN_INDEX_Y,
 	}, {
 		.type = IIO_ACCEL,
 		.modified = 1,
 		.channel2 = IIO_MOD_Z,
-		.info_mask = IIO_CHAN_INFO_OFFSET_SHARED_BIT |
-		IIO_CHAN_INFO_SCALE_SHARED_BIT |
-		IIO_CHAN_INFO_SAMP_FREQ_SHARED_BIT |
-		IIO_CHAN_INFO_HYSTERESIS_SHARED_BIT,
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
+		BIT(IIO_CHAN_INFO_SCALE) |
+		BIT(IIO_CHAN_INFO_SAMP_FREQ) |
+		BIT(IIO_CHAN_INFO_HYSTERESIS),
 		.scan_index = CHANNEL_SCAN_INDEX_Z,
 	}
 };
diff --git a/drivers/iio/accel/kxsd9.c b/drivers/iio/accel/kxsd9.c
index c2229a5..7229645 100644
--- a/drivers/iio/accel/kxsd9.c
+++ b/drivers/iio/accel/kxsd9.c
@@ -177,8 +177,8 @@ error_ret:
 		.type = IIO_ACCEL,					\
 		.modified = 1,						\
 		.channel2 = IIO_MOD_##axis,				\
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |		\
-			IIO_CHAN_INFO_SCALE_SHARED_BIT,			\
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),	\
 		.address = KXSD9_REG_##axis,				\
 	}
 
@@ -186,7 +186,7 @@ static const struct iio_chan_spec kxsd9_channels[] = {
 	KXSD9_ACCEL_CHAN(X), KXSD9_ACCEL_CHAN(Y), KXSD9_ACCEL_CHAN(Z),
 	{
 		.type = IIO_VOLTAGE,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
 		.indexed = 1,
 		.address = KXSD9_REG_AUX,
 	}
diff --git a/drivers/iio/accel/st_accel_buffer.c b/drivers/iio/accel/st_accel_buffer.c
index 6bd82c7..d9b3507 100644
--- a/drivers/iio/accel/st_accel_buffer.c
+++ b/drivers/iio/accel/st_accel_buffer.c
@@ -25,7 +25,7 @@
 
 int st_accel_trig_set_state(struct iio_trigger *trig, bool state)
 {
-	struct iio_dev *indio_dev = trig->private_data;
+	struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
 
 	return st_sensors_set_dataready_irq(indio_dev, state);
 }
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index e372257..ab0767e6 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -30,6 +30,18 @@ config AD7298
 	  To compile this driver as a module, choose M here: the
 	  module will be called ad7298.
 
+config AD7923
+	tristate "Analog Devices AD7923 and similar ADCs driver"
+	depends on SPI
+	select IIO_BUFFER
+	select IIO_TRIGGERED_BUFFER
+	help
+	  Say yes here to build support for Analog Devices
+	  AD7904, AD7914, AD7923, AD7924 4 Channel ADCs.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ad7923.
+
 config AD7791
 	tristate "Analog Devices AD7791 ADC driver"
 	depends on SPI
@@ -91,6 +103,14 @@ config AT91_ADC
 	help
 	  Say yes here to build support for Atmel AT91 ADC.
 
+config EXYNOS_ADC
+	bool "Exynos ADC driver support"
+	depends on OF
+	help
+	  Core support for the ADC block found in the Samsung EXYNOS series
+	  of SoCs for drivers such as the touchscreen and hwmon to use to share
+	  this resource.
+
 config LP8788_ADC
 	bool "LP8788 ADC driver"
 	depends on MFD_LP8788
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index 2d5f100..0a825be 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -5,11 +5,13 @@
 obj-$(CONFIG_AD_SIGMA_DELTA) += ad_sigma_delta.o
 obj-$(CONFIG_AD7266) += ad7266.o
 obj-$(CONFIG_AD7298) += ad7298.o
+obj-$(CONFIG_AD7923) += ad7923.o
 obj-$(CONFIG_AD7476) += ad7476.o
 obj-$(CONFIG_AD7791) += ad7791.o
 obj-$(CONFIG_AD7793) += ad7793.o
 obj-$(CONFIG_AD7887) += ad7887.o
 obj-$(CONFIG_AT91_ADC) += at91_adc.o
+obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o
 obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
 obj-$(CONFIG_MAX1363) += max1363.o
 obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o
diff --git a/drivers/iio/adc/ad7266.c b/drivers/iio/adc/ad7266.c
index bbad9b9..c2744a7 100644
--- a/drivers/iio/adc/ad7266.c
+++ b/drivers/iio/adc/ad7266.c
@@ -201,9 +201,9 @@ static int ad7266_read_raw(struct iio_dev *indio_dev,
 	.indexed = 1,					\
 	.channel = (_chan),				\
 	.address = (_chan),				\
-	.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT	\
-		| IIO_CHAN_INFO_SCALE_SHARED_BIT	\
-		| IIO_CHAN_INFO_OFFSET_SHARED_BIT,	\
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),	\
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) \
+		| BIT(IIO_CHAN_INFO_OFFSET),			\
 	.scan_index = (_chan),				\
 	.scan_type = {					\
 		.sign = (_sign),			\
@@ -249,9 +249,9 @@ static AD7266_DECLARE_SINGLE_ENDED_CHANNELS_FIXED(s, 's');
 	.channel = (_chan) * 2,				\
 	.channel2 = (_chan) * 2 + 1,			\
 	.address = (_chan),				\
-	.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT	\
-		| IIO_CHAN_INFO_SCALE_SHARED_BIT	\
-		| IIO_CHAN_INFO_OFFSET_SHARED_BIT,	\
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),	\
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE)	\
+		| BIT(IIO_CHAN_INFO_OFFSET),			\
 	.scan_index = (_chan),				\
 	.scan_type = {					\
 		.sign = _sign,			\
diff --git a/drivers/iio/adc/ad7298.c b/drivers/iio/adc/ad7298.c
index b34d754..03b7718 100644
--- a/drivers/iio/adc/ad7298.c
+++ b/drivers/iio/adc/ad7298.c
@@ -63,8 +63,8 @@ struct ad7298_state {
 		.type = IIO_VOLTAGE,					\
 		.indexed = 1,						\
 		.channel = index,					\
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |		\
-		IIO_CHAN_INFO_SCALE_SHARED_BIT,				\
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),	\
 		.address = index,					\
 		.scan_index = index,					\
 		.scan_type = {						\
@@ -80,9 +80,9 @@ static const struct iio_chan_spec ad7298_channels[] = {
 		.type = IIO_TEMP,
 		.indexed = 1,
 		.channel = 0,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-			IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
-			IIO_CHAN_INFO_OFFSET_SEPARATE_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+			BIT(IIO_CHAN_INFO_SCALE) |
+			BIT(IIO_CHAN_INFO_OFFSET),
 		.address = AD7298_CH_TEMP,
 		.scan_index = -1,
 		.scan_type = {
diff --git a/drivers/iio/adc/ad7476.c b/drivers/iio/adc/ad7476.c
index 1491fa6..2e98bef4 100644
--- a/drivers/iio/adc/ad7476.c
+++ b/drivers/iio/adc/ad7476.c
@@ -140,12 +140,12 @@ static int ad7476_read_raw(struct iio_dev *indio_dev,
 	return -EINVAL;
 }
 
-#define _AD7476_CHAN(bits, _shift, _info_mask)			\
+#define _AD7476_CHAN(bits, _shift, _info_mask_sep)		\
 	{							\
 	.type = IIO_VOLTAGE,					\
 	.indexed = 1,						\
-	.info_mask = _info_mask |				\
-	IIO_CHAN_INFO_SCALE_SHARED_BIT,				\
+	.info_mask_separate = _info_mask_sep,			\
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),	\
 	.scan_type = {						\
 		.sign = 'u',					\
 		.realbits = (bits),				\
@@ -156,9 +156,9 @@ static int ad7476_read_raw(struct iio_dev *indio_dev,
 }
 
 #define AD7476_CHAN(bits) _AD7476_CHAN((bits), 13 - (bits), \
-		IIO_CHAN_INFO_RAW_SEPARATE_BIT)
+		BIT(IIO_CHAN_INFO_RAW))
 #define AD7940_CHAN(bits) _AD7476_CHAN((bits), 15 - (bits), \
-		IIO_CHAN_INFO_RAW_SEPARATE_BIT)
+		BIT(IIO_CHAN_INFO_RAW))
 #define AD7091R_CHAN(bits) _AD7476_CHAN((bits), 16 - (bits), 0)
 
 static const struct ad7476_chip_info ad7476_chip_info_tbl[] = {
diff --git a/drivers/iio/adc/ad7887.c b/drivers/iio/adc/ad7887.c
index a33d5cd..dd15a5b 100644
--- a/drivers/iio/adc/ad7887.c
+++ b/drivers/iio/adc/ad7887.c
@@ -207,8 +207,8 @@ static const struct ad7887_chip_info ad7887_chip_info_tbl[] = {
 			.type = IIO_VOLTAGE,
 			.indexed = 1,
 			.channel = 1,
-			.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-			IIO_CHAN_INFO_SCALE_SHARED_BIT,
+			.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+			.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
 			.address = 1,
 			.scan_index = 1,
 			.scan_type = IIO_ST('u', 12, 16, 0),
@@ -217,8 +217,8 @@ static const struct ad7887_chip_info ad7887_chip_info_tbl[] = {
 			.type = IIO_VOLTAGE,
 			.indexed = 1,
 			.channel = 0,
-			.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-			IIO_CHAN_INFO_SCALE_SHARED_BIT,
+			.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+			.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
 			.address = 0,
 			.scan_index = 0,
 			.scan_type = IIO_ST('u', 12, 16, 0),
diff --git a/drivers/iio/adc/ad7923.c b/drivers/iio/adc/ad7923.c
new file mode 100644
index 0000000..97fa0d3
--- /dev/null
+++ b/drivers/iio/adc/ad7923.c
@@ -0,0 +1,383 @@
+/*
+ * AD7904/AD7914/AD7923/AD7924 SPI ADC driver
+ *
+ * Copyright 2011 Analog Devices Inc (from AD7923 Driver)
+ * Copyright 2012 CS Systemes d'Information
+ *
+ * Licensed under the GPL-2.
+ */
+
+#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/delay.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+
+#define AD7923_WRITE_CR		(1 << 11)	/* write control register */
+#define AD7923_RANGE		(1 << 1)	/* range to REFin */
+#define AD7923_CODING		(1 << 0)	/* coding is straight binary */
+#define AD7923_PM_MODE_AS	(1)		/* auto shutdown */
+#define AD7923_PM_MODE_FS	(2)		/* full shutdown */
+#define AD7923_PM_MODE_OPS	(3)		/* normal operation */
+#define AD7923_CHANNEL_0	(0)		/* analog input 0 */
+#define AD7923_CHANNEL_1	(1)		/* analog input 1 */
+#define AD7923_CHANNEL_2	(2)		/* analog input 2 */
+#define AD7923_CHANNEL_3	(3)		/* analog input 3 */
+#define AD7923_SEQUENCE_OFF	(0)		/* no sequence fonction */
+#define AD7923_SEQUENCE_PROTECT	(2)		/* no interrupt write cycle */
+#define AD7923_SEQUENCE_ON	(3)		/* continuous sequence */
+
+#define AD7923_MAX_CHAN		4
+
+#define AD7923_PM_MODE_WRITE(mode)	(mode << 4)	/* write mode */
+#define AD7923_CHANNEL_WRITE(channel)	(channel << 6)	/* write channel */
+#define AD7923_SEQUENCE_WRITE(sequence)	(((sequence & 1) << 3) \
+					+ ((sequence & 2) << 9))
+						/* write sequence fonction */
+/* left shift for CR : bit 11 transmit in first */
+#define AD7923_SHIFT_REGISTER	4
+
+/* val = value, dec = left shift, bits = number of bits of the mask */
+#define EXTRACT(val, dec, bits)		((val >> dec) & ((1 << bits) - 1))
+
+struct ad7923_state {
+	struct spi_device		*spi;
+	struct spi_transfer		ring_xfer[5];
+	struct spi_transfer		scan_single_xfer[2];
+	struct spi_message		ring_msg;
+	struct spi_message		scan_single_msg;
+
+	struct regulator		*reg;
+
+	unsigned int			settings;
+
+	/*
+	 * DMA (thus cache coherency maintenance) requires the
+	 * transfer buffers to live in their own cache lines.
+	 */
+	__be16				rx_buf[4] ____cacheline_aligned;
+	__be16				tx_buf[4];
+};
+
+struct ad7923_chip_info {
+	const struct iio_chan_spec *channels;
+	unsigned int num_channels;
+};
+
+enum ad7923_id {
+	AD7904,
+	AD7914,
+	AD7924,
+};
+
+#define AD7923_V_CHAN(index, bits)					\
+	{								\
+		.type = IIO_VOLTAGE,					\
+		.indexed = 1,						\
+		.channel = index,					\
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),	\
+		.address = index,					\
+		.scan_index = index,					\
+		.scan_type = {						\
+			.sign = 'u',					\
+			.realbits = (bits),				\
+			.storagebits = 16,				\
+			.endianness = IIO_BE,				\
+		},							\
+	}
+
+#define DECLARE_AD7923_CHANNELS(name, bits) \
+const struct iio_chan_spec name ## _channels[] = { \
+	AD7923_V_CHAN(0, bits), \
+	AD7923_V_CHAN(1, bits), \
+	AD7923_V_CHAN(2, bits), \
+	AD7923_V_CHAN(3, bits), \
+	IIO_CHAN_SOFT_TIMESTAMP(4), \
+}
+
+static DECLARE_AD7923_CHANNELS(ad7904, 8);
+static DECLARE_AD7923_CHANNELS(ad7914, 10);
+static DECLARE_AD7923_CHANNELS(ad7924, 12);
+
+static const struct ad7923_chip_info ad7923_chip_info[] = {
+	[AD7904] = {
+		.channels = ad7904_channels,
+		.num_channels = ARRAY_SIZE(ad7904_channels),
+	},
+	[AD7914] = {
+		.channels = ad7914_channels,
+		.num_channels = ARRAY_SIZE(ad7914_channels),
+	},
+	[AD7924] = {
+		.channels = ad7924_channels,
+		.num_channels = ARRAY_SIZE(ad7924_channels),
+	},
+};
+
+/**
+ * ad7923_update_scan_mode() setup the spi transfer buffer for the new scan mask
+ **/
+static int ad7923_update_scan_mode(struct iio_dev *indio_dev,
+	const unsigned long *active_scan_mask)
+{
+	struct ad7923_state *st = iio_priv(indio_dev);
+	int i, cmd, len;
+
+	len = 0;
+	for_each_set_bit(i, active_scan_mask, AD7923_MAX_CHAN) {
+		cmd = AD7923_WRITE_CR | AD7923_CHANNEL_WRITE(i) |
+			AD7923_SEQUENCE_WRITE(AD7923_SEQUENCE_OFF) |
+			st->settings;
+		cmd <<= AD7923_SHIFT_REGISTER;
+		st->tx_buf[len++] = cpu_to_be16(cmd);
+	}
+	/* build spi ring message */
+	st->ring_xfer[0].tx_buf = &st->tx_buf[0];
+	st->ring_xfer[0].len = len;
+	st->ring_xfer[0].cs_change = 1;
+
+	spi_message_init(&st->ring_msg);
+	spi_message_add_tail(&st->ring_xfer[0], &st->ring_msg);
+
+	for (i = 0; i < len; i++) {
+		st->ring_xfer[i + 1].rx_buf = &st->rx_buf[i];
+		st->ring_xfer[i + 1].len = 2;
+		st->ring_xfer[i + 1].cs_change = 1;
+		spi_message_add_tail(&st->ring_xfer[i + 1], &st->ring_msg);
+	}
+	/* make sure last transfer cs_change is not set */
+	st->ring_xfer[i + 1].cs_change = 0;
+
+	return 0;
+}
+
+/**
+ * ad7923_trigger_handler() bh of trigger launched polling to ring buffer
+ *
+ * Currently there is no option in this driver to disable the saving of
+ * timestamps within the ring.
+ **/
+static irqreturn_t ad7923_trigger_handler(int irq, void *p)
+{
+	struct iio_poll_func *pf = p;
+	struct iio_dev *indio_dev = pf->indio_dev;
+	struct ad7923_state *st = iio_priv(indio_dev);
+	s64 time_ns = 0;
+	int b_sent;
+
+	b_sent = spi_sync(st->spi, &st->ring_msg);
+	if (b_sent)
+		goto done;
+
+	if (indio_dev->scan_timestamp) {
+		time_ns = iio_get_time_ns();
+		memcpy((u8 *)st->rx_buf + indio_dev->scan_bytes - sizeof(s64),
+			&time_ns, sizeof(time_ns));
+	}
+
+	iio_push_to_buffers(indio_dev, (u8 *)st->rx_buf);
+
+done:
+	iio_trigger_notify_done(indio_dev->trig);
+
+	return IRQ_HANDLED;
+}
+
+static int ad7923_scan_direct(struct ad7923_state *st, unsigned ch)
+{
+	int ret, cmd;
+
+	cmd = AD7923_WRITE_CR | AD7923_CHANNEL_WRITE(ch) |
+		AD7923_SEQUENCE_WRITE(AD7923_SEQUENCE_OFF) |
+		st->settings;
+	cmd <<= AD7923_SHIFT_REGISTER;
+	st->tx_buf[0] = cpu_to_be16(cmd);
+
+	ret = spi_sync(st->spi, &st->scan_single_msg);
+	if (ret)
+		return ret;
+
+	return be16_to_cpu(st->rx_buf[0]);
+}
+
+static int ad7923_get_range(struct ad7923_state *st)
+{
+	int vref;
+
+	vref = regulator_get_voltage(st->reg);
+	if (vref < 0)
+		return vref;
+
+	vref /= 1000;
+
+	if (!(st->settings & AD7923_RANGE))
+		vref *= 2;
+
+	return vref;
+}
+
+static int ad7923_read_raw(struct iio_dev *indio_dev,
+			   struct iio_chan_spec const *chan,
+			   int *val,
+			   int *val2,
+			   long m)
+{
+	int ret;
+	struct ad7923_state *st = iio_priv(indio_dev);
+
+	switch (m) {
+	case IIO_CHAN_INFO_RAW:
+		mutex_lock(&indio_dev->mlock);
+		if (iio_buffer_enabled(indio_dev))
+			ret = -EBUSY;
+		else
+			ret = ad7923_scan_direct(st, chan->address);
+		mutex_unlock(&indio_dev->mlock);
+
+		if (ret < 0)
+			return ret;
+
+		if (chan->address == EXTRACT(ret, 12, 4))
+			*val = EXTRACT(ret, 0, 12);
+		else
+			return -EIO;
+
+		return IIO_VAL_INT;
+	case IIO_CHAN_INFO_SCALE:
+		ret = ad7923_get_range(st);
+		if (ret < 0)
+			return ret;
+		*val = ret;
+		*val2 = chan->scan_type.realbits;
+		return IIO_VAL_FRACTIONAL_LOG2;
+	}
+	return -EINVAL;
+}
+
+static const struct iio_info ad7923_info = {
+	.read_raw = &ad7923_read_raw,
+	.update_scan_mode = ad7923_update_scan_mode,
+	.driver_module = THIS_MODULE,
+};
+
+static int ad7923_probe(struct spi_device *spi)
+{
+	struct ad7923_state *st;
+	struct iio_dev *indio_dev = iio_device_alloc(sizeof(*st));
+	const struct ad7923_chip_info *info;
+	int ret;
+
+	if (indio_dev == NULL)
+		return -ENOMEM;
+
+	st = iio_priv(indio_dev);
+
+	spi_set_drvdata(spi, indio_dev);
+
+	st->spi = spi;
+	st->settings = AD7923_CODING | AD7923_RANGE |
+			AD7923_PM_MODE_WRITE(AD7923_PM_MODE_OPS);
+
+	info = &ad7923_chip_info[spi_get_device_id(spi)->driver_data];
+
+	indio_dev->name = spi_get_device_id(spi)->name;
+	indio_dev->dev.parent = &spi->dev;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->channels = info->channels;
+	indio_dev->num_channels = info->num_channels;
+	indio_dev->info = &ad7923_info;
+
+	/* Setup default message */
+
+	st->scan_single_xfer[0].tx_buf = &st->tx_buf[0];
+	st->scan_single_xfer[0].len = 2;
+	st->scan_single_xfer[0].cs_change = 1;
+	st->scan_single_xfer[1].rx_buf = &st->rx_buf[0];
+	st->scan_single_xfer[1].len = 2;
+
+	spi_message_init(&st->scan_single_msg);
+	spi_message_add_tail(&st->scan_single_xfer[0], &st->scan_single_msg);
+	spi_message_add_tail(&st->scan_single_xfer[1], &st->scan_single_msg);
+
+	st->reg = regulator_get(&spi->dev, "refin");
+	if (IS_ERR(st->reg)) {
+		ret = PTR_ERR(st->reg);
+		goto error_free;
+	}
+	ret = regulator_enable(st->reg);
+	if (ret)
+		goto error_put_reg;
+
+	ret = iio_triggered_buffer_setup(indio_dev, NULL,
+			&ad7923_trigger_handler, NULL);
+	if (ret)
+		goto error_disable_reg;
+
+	ret = iio_device_register(indio_dev);
+	if (ret)
+		goto error_cleanup_ring;
+
+	return 0;
+
+error_cleanup_ring:
+	iio_triggered_buffer_cleanup(indio_dev);
+error_disable_reg:
+	regulator_disable(st->reg);
+error_put_reg:
+	regulator_put(st->reg);
+error_free:
+	iio_device_free(indio_dev);
+
+	return ret;
+}
+
+static int ad7923_remove(struct spi_device *spi)
+{
+	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+	struct ad7923_state *st = iio_priv(indio_dev);
+
+	iio_device_unregister(indio_dev);
+	iio_triggered_buffer_cleanup(indio_dev);
+	regulator_disable(st->reg);
+	regulator_put(st->reg);
+	iio_device_free(indio_dev);
+
+	return 0;
+}
+
+static const struct spi_device_id ad7923_id[] = {
+	{"ad7904", AD7904},
+	{"ad7914", AD7914},
+	{"ad7923", AD7924},
+	{"ad7924", AD7924},
+	{}
+};
+MODULE_DEVICE_TABLE(spi, ad7923_id);
+
+static struct spi_driver ad7923_driver = {
+	.driver = {
+		.name	= "ad7923",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= ad7923_probe,
+	.remove		= ad7923_remove,
+	.id_table	= ad7923_id,
+};
+module_spi_driver(ad7923_driver);
+
+MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
+MODULE_AUTHOR("Patrick Vasseur <patrick.vasseur@c-s.fr>");
+MODULE_DESCRIPTION("Analog Devices AD7904/AD7914/AD7923/AD7924 ADC");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/adc/ad_sigma_delta.c b/drivers/iio/adc/ad_sigma_delta.c
index afe6d78..f0d6335 100644
--- a/drivers/iio/adc/ad_sigma_delta.c
+++ b/drivers/iio/adc/ad_sigma_delta.c
@@ -470,7 +470,7 @@ static int ad_sd_probe_trigger(struct iio_dev *indio_dev)
 		disable_irq_nosync(sigma_delta->spi->irq);
 	}
 	sigma_delta->trig->dev.parent = &sigma_delta->spi->dev;
-	sigma_delta->trig->private_data = sigma_delta;
+	iio_trigger_set_drvdata(sigma_delta->trig, sigma_delta);
 
 	ret = iio_trigger_register(sigma_delta->trig);
 	if (ret)
diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c
index 83c836b..e5b88d5 100644
--- a/drivers/iio/adc/at91_adc.c
+++ b/drivers/iio/adc/at91_adc.c
@@ -52,11 +52,15 @@ struct at91_adc_state {
 	void __iomem		*reg_base;
 	struct at91_adc_reg_desc *registers;
 	u8			startup_time;
+	u8			sample_hold_time;
+	bool			sleep_mode;
 	struct iio_trigger	**trig;
 	struct at91_adc_trigger	*trigger_list;
 	u32			trigger_number;
 	bool			use_external;
 	u32			vref_mv;
+	u32			res;		/* resolution used for convertions */
+	bool			low_res;	/* the resolution corresponds to the lowest one */
 	wait_queue_head_t	wq_data_avail;
 };
 
@@ -138,10 +142,10 @@ static int at91_adc_channel_init(struct iio_dev *idev)
 		chan->channel = bit;
 		chan->scan_index = idx;
 		chan->scan_type.sign = 'u';
-		chan->scan_type.realbits = 10;
+		chan->scan_type.realbits = st->res;
 		chan->scan_type.storagebits = 16;
-		chan->info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT |
-			IIO_CHAN_INFO_RAW_SEPARATE_BIT;
+		chan->info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE);
+		chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
 		idx++;
 	}
 	timestamp = chan_array + idx;
@@ -188,7 +192,7 @@ static u8 at91_adc_get_trigger_value_by_name(struct iio_dev *idev,
 
 static int at91_adc_configure_trigger(struct iio_trigger *trig, bool state)
 {
-	struct iio_dev *idev = trig->private_data;
+	struct iio_dev *idev = iio_trigger_get_drvdata(trig);
 	struct at91_adc_state *st = iio_priv(idev);
 	struct iio_buffer *buffer = idev->buffer;
 	struct at91_adc_reg_desc *reg = st->registers;
@@ -254,7 +258,7 @@ static struct iio_trigger *at91_adc_allocate_trigger(struct iio_dev *idev,
 		return NULL;
 
 	trig->dev.parent = idev->dev.parent;
-	trig->private_data = idev;
+	iio_trigger_set_drvdata(trig, idev);
 	trig->ops = &at91_adc_trigger_ops;
 
 	ret = iio_trigger_register(trig);
@@ -372,6 +376,59 @@ static int at91_adc_read_raw(struct iio_dev *idev,
 	return -EINVAL;
 }
 
+static int at91_adc_of_get_resolution(struct at91_adc_state *st,
+				      struct platform_device *pdev)
+{
+	struct iio_dev *idev = iio_priv_to_dev(st);
+	struct device_node *np = pdev->dev.of_node;
+	int count, i, ret = 0;
+	char *res_name, *s;
+	u32 *resolutions;
+
+	count = of_property_count_strings(np, "atmel,adc-res-names");
+	if (count < 2) {
+		dev_err(&idev->dev, "You must specified at least two resolution names for "
+				    "adc-res-names property in the DT\n");
+		return count;
+	}
+
+	resolutions = kmalloc(count * sizeof(*resolutions), GFP_KERNEL);
+	if (!resolutions)
+		return -ENOMEM;
+
+	if (of_property_read_u32_array(np, "atmel,adc-res", resolutions, count)) {
+		dev_err(&idev->dev, "Missing adc-res property in the DT.\n");
+		ret = -ENODEV;
+		goto ret;
+	}
+
+	if (of_property_read_string(np, "atmel,adc-use-res", (const char **)&res_name))
+		res_name = "highres";
+
+	for (i = 0; i < count; i++) {
+		if (of_property_read_string_index(np, "atmel,adc-res-names", i, (const char **)&s))
+			continue;
+
+		if (strcmp(res_name, s))
+			continue;
+
+		st->res = resolutions[i];
+		if (!strcmp(res_name, "lowres"))
+			st->low_res = true;
+		else
+			st->low_res = false;
+
+		dev_info(&idev->dev, "Resolution used: %u bits\n", st->res);
+		goto ret;
+	}
+
+	dev_err(&idev->dev, "There is no resolution for %s\n", res_name);
+
+ret:
+	kfree(resolutions);
+	return ret;
+}
+
 static int at91_adc_probe_dt(struct at91_adc_state *st,
 			     struct platform_device *pdev)
 {
@@ -400,6 +457,8 @@ static int at91_adc_probe_dt(struct at91_adc_state *st,
 	}
 	st->num_channels = prop;
 
+	st->sleep_mode = of_property_read_bool(node, "atmel,adc-sleep-mode");
+
 	if (of_property_read_u32(node, "atmel,adc-startup-time", &prop)) {
 		dev_err(&idev->dev, "Missing adc-startup-time property in the DT.\n");
 		ret = -EINVAL;
@@ -407,6 +466,9 @@ static int at91_adc_probe_dt(struct at91_adc_state *st,
 	}
 	st->startup_time = prop;
 
+	prop = 0;
+	of_property_read_u32(node, "atmel,adc-sample-hold-time", &prop);
+	st->sample_hold_time = prop;
 
 	if (of_property_read_u32(node, "atmel,adc-vref", &prop)) {
 		dev_err(&idev->dev, "Missing adc-vref property in the DT.\n");
@@ -415,6 +477,10 @@ static int at91_adc_probe_dt(struct at91_adc_state *st,
 	}
 	st->vref_mv = prop;
 
+	ret = at91_adc_of_get_resolution(st, pdev);
+	if (ret)
+		goto error_ret;
+
 	st->registers = devm_kzalloc(&idev->dev,
 				     sizeof(struct at91_adc_reg_desc),
 				     GFP_KERNEL);
@@ -516,11 +582,12 @@ static const struct iio_info at91_adc_info = {
 
 static int at91_adc_probe(struct platform_device *pdev)
 {
-	unsigned int prsc, mstrclk, ticks, adc_clk;
+	unsigned int prsc, mstrclk, ticks, adc_clk, shtim;
 	int ret;
 	struct iio_dev *idev;
 	struct at91_adc_state *st;
 	struct resource *res;
+	u32 reg;
 
 	idev = iio_device_alloc(sizeof(struct at91_adc_state));
 	if (idev == NULL) {
@@ -628,9 +695,22 @@ static int at91_adc_probe(struct platform_device *pdev)
 	 */
 	ticks = round_up((st->startup_time * adc_clk /
 			  1000000) - 1, 8) / 8;
-	at91_adc_writel(st, AT91_ADC_MR,
-			(AT91_ADC_PRESCAL_(prsc) & AT91_ADC_PRESCAL) |
-			(AT91_ADC_STARTUP_(ticks) & AT91_ADC_STARTUP));
+	/*
+	 * a minimal Sample and Hold Time is necessary for the ADC to guarantee
+	 * the best converted final value between two channels selection
+	 * The formula thus is : Sample and Hold Time = (shtim + 1) / ADCClock
+	 */
+	shtim = round_up((st->sample_hold_time * adc_clk /
+			  1000000) - 1, 1);
+
+	reg = AT91_ADC_PRESCAL_(prsc) & AT91_ADC_PRESCAL;
+	reg |= AT91_ADC_STARTUP_(ticks) & AT91_ADC_STARTUP;
+	if (st->low_res)
+		reg |= AT91_ADC_LOWRES;
+	if (st->sleep_mode)
+		reg |= AT91_ADC_SLEEP;
+	reg |= AT91_ADC_SHTIM_(shtim) & AT91_ADC_SHTIM;
+	at91_adc_writel(st, AT91_ADC_MR, reg);
 
 	/* Setup the ADC channels available on the board */
 	ret = at91_adc_channel_init(idev);
diff --git a/drivers/iio/adc/exynos_adc.c b/drivers/iio/adc/exynos_adc.c
new file mode 100644
index 0000000..9f3a8ef
--- /dev/null
+++ b/drivers/iio/adc/exynos_adc.c
@@ -0,0 +1,452 @@
+/*
+ *  exynos_adc.c - Support for ADC in EXYNOS SoCs
+ *
+ *  8 ~ 10 channel, 10/12-bit ADC
+ *
+ *  Copyright (C) 2013 Naveen Krishna Chatradhi <ch.naveen@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/module.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/completion.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/regulator/consumer.h>
+#include <linux/of_platform.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/machine.h>
+#include <linux/iio/driver.h>
+
+enum adc_version {
+	ADC_V1,
+	ADC_V2
+};
+
+/* EXYNOS4412/5250 ADC_V1 registers definitions */
+#define ADC_V1_CON(x)		((x) + 0x00)
+#define ADC_V1_DLY(x)		((x) + 0x08)
+#define ADC_V1_DATX(x)		((x) + 0x0C)
+#define ADC_V1_INTCLR(x)	((x) + 0x18)
+#define ADC_V1_MUX(x)		((x) + 0x1c)
+
+/* Future ADC_V2 registers definitions */
+#define ADC_V2_CON1(x)		((x) + 0x00)
+#define ADC_V2_CON2(x)		((x) + 0x04)
+#define ADC_V2_STAT(x)		((x) + 0x08)
+#define ADC_V2_INT_EN(x)	((x) + 0x10)
+#define ADC_V2_INT_ST(x)	((x) + 0x14)
+#define ADC_V2_VER(x)		((x) + 0x20)
+
+/* Bit definitions for ADC_V1 */
+#define ADC_V1_CON_RES		(1u << 16)
+#define ADC_V1_CON_PRSCEN	(1u << 14)
+#define ADC_V1_CON_PRSCLV(x)	(((x) & 0xFF) << 6)
+#define ADC_V1_CON_STANDBY	(1u << 2)
+
+/* Bit definitions for ADC_V2 */
+#define ADC_V2_CON1_SOFT_RESET	(1u << 2)
+
+#define ADC_V2_CON2_OSEL	(1u << 10)
+#define ADC_V2_CON2_ESEL	(1u << 9)
+#define ADC_V2_CON2_HIGHF	(1u << 8)
+#define ADC_V2_CON2_C_TIME(x)	(((x) & 7) << 4)
+#define ADC_V2_CON2_ACH_SEL(x)	(((x) & 0xF) << 0)
+#define ADC_V2_CON2_ACH_MASK	0xF
+
+#define MAX_ADC_V2_CHANNELS	10
+#define MAX_ADC_V1_CHANNELS	8
+
+/* Bit definitions common for ADC_V1 and ADC_V2 */
+#define ADC_CON_EN_START	(1u << 0)
+#define ADC_DATX_MASK		0xFFF
+
+#define EXYNOS_ADC_TIMEOUT	(msecs_to_jiffies(1000))
+
+struct exynos_adc {
+	void __iomem		*regs;
+	void __iomem		*enable_reg;
+	struct clk		*clk;
+	unsigned int		irq;
+	struct regulator	*vdd;
+
+	struct completion	completion;
+
+	u32			value;
+	unsigned int            version;
+};
+
+static const struct of_device_id exynos_adc_match[] = {
+	{ .compatible = "samsung,exynos-adc-v1", .data = (void *)ADC_V1 },
+	{ .compatible = "samsung,exynos-adc-v2", .data = (void *)ADC_V2 },
+	{},
+};
+MODULE_DEVICE_TABLE(of, exynos_adc_match);
+
+static inline unsigned int exynos_adc_get_version(struct platform_device *pdev)
+{
+	const struct of_device_id *match;
+
+	match = of_match_node(exynos_adc_match, pdev->dev.of_node);
+	return (unsigned int)match->data;
+}
+
+static int exynos_read_raw(struct iio_dev *indio_dev,
+				struct iio_chan_spec const *chan,
+				int *val,
+				int *val2,
+				long mask)
+{
+	struct exynos_adc *info = iio_priv(indio_dev);
+	unsigned long timeout;
+	u32 con1, con2;
+
+	if (mask != IIO_CHAN_INFO_RAW)
+		return -EINVAL;
+
+	mutex_lock(&indio_dev->mlock);
+
+	/* Select the channel to be used and Trigger conversion */
+	if (info->version == ADC_V2) {
+		con2 = readl(ADC_V2_CON2(info->regs));
+		con2 &= ~ADC_V2_CON2_ACH_MASK;
+		con2 |= ADC_V2_CON2_ACH_SEL(chan->address);
+		writel(con2, ADC_V2_CON2(info->regs));
+
+		con1 = readl(ADC_V2_CON1(info->regs));
+		writel(con1 | ADC_CON_EN_START,
+				ADC_V2_CON1(info->regs));
+	} else {
+		writel(chan->address, ADC_V1_MUX(info->regs));
+
+		con1 = readl(ADC_V1_CON(info->regs));
+		writel(con1 | ADC_CON_EN_START,
+				ADC_V1_CON(info->regs));
+	}
+
+	timeout = wait_for_completion_interruptible_timeout
+			(&info->completion, EXYNOS_ADC_TIMEOUT);
+	*val = info->value;
+
+	mutex_unlock(&indio_dev->mlock);
+
+	if (timeout == 0)
+		return -ETIMEDOUT;
+
+	return IIO_VAL_INT;
+}
+
+static irqreturn_t exynos_adc_isr(int irq, void *dev_id)
+{
+	struct exynos_adc *info = (struct exynos_adc *)dev_id;
+
+	/* Read value */
+	info->value = readl(ADC_V1_DATX(info->regs)) &
+						ADC_DATX_MASK;
+	/* clear irq */
+	if (info->version == ADC_V2)
+		writel(1, ADC_V2_INT_ST(info->regs));
+	else
+		writel(1, ADC_V1_INTCLR(info->regs));
+
+	complete(&info->completion);
+
+	return IRQ_HANDLED;
+}
+
+static int exynos_adc_reg_access(struct iio_dev *indio_dev,
+			      unsigned reg, unsigned writeval,
+			      unsigned *readval)
+{
+	struct exynos_adc *info = iio_priv(indio_dev);
+
+	if (readval == NULL)
+		return -EINVAL;
+
+	*readval = readl(info->regs + reg);
+
+	return 0;
+}
+
+static const struct iio_info exynos_adc_iio_info = {
+	.read_raw = &exynos_read_raw,
+	.debugfs_reg_access = &exynos_adc_reg_access,
+	.driver_module = THIS_MODULE,
+};
+
+#define ADC_CHANNEL(_index, _id) {			\
+	.type = IIO_VOLTAGE,				\
+	.indexed = 1,					\
+	.channel = _index,				\
+	.address = _index,				\
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),	\
+	.datasheet_name = _id,				\
+}
+
+static const struct iio_chan_spec exynos_adc_iio_channels[] = {
+	ADC_CHANNEL(0, "adc0"),
+	ADC_CHANNEL(1, "adc1"),
+	ADC_CHANNEL(2, "adc2"),
+	ADC_CHANNEL(3, "adc3"),
+	ADC_CHANNEL(4, "adc4"),
+	ADC_CHANNEL(5, "adc5"),
+	ADC_CHANNEL(6, "adc6"),
+	ADC_CHANNEL(7, "adc7"),
+	ADC_CHANNEL(8, "adc8"),
+	ADC_CHANNEL(9, "adc9"),
+};
+
+static int exynos_adc_remove_devices(struct device *dev, void *c)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+
+	platform_device_unregister(pdev);
+
+	return 0;
+}
+
+static void exynos_adc_hw_init(struct exynos_adc *info)
+{
+	u32 con1, con2;
+
+	if (info->version == ADC_V2) {
+		con1 = ADC_V2_CON1_SOFT_RESET;
+		writel(con1, ADC_V2_CON1(info->regs));
+
+		con2 = ADC_V2_CON2_OSEL | ADC_V2_CON2_ESEL |
+			ADC_V2_CON2_HIGHF | ADC_V2_CON2_C_TIME(0);
+		writel(con2, ADC_V2_CON2(info->regs));
+
+		/* Enable interrupts */
+		writel(1, ADC_V2_INT_EN(info->regs));
+	} else {
+		/* set default prescaler values and Enable prescaler */
+		con1 =  ADC_V1_CON_PRSCLV(49) | ADC_V1_CON_PRSCEN;
+
+		/* Enable 12-bit ADC resolution */
+		con1 |= ADC_V1_CON_RES;
+		writel(con1, ADC_V1_CON(info->regs));
+	}
+}
+
+static int exynos_adc_probe(struct platform_device *pdev)
+{
+	struct exynos_adc *info = NULL;
+	struct device_node *np = pdev->dev.of_node;
+	struct iio_dev *indio_dev = NULL;
+	struct resource	*mem;
+	int ret = -ENODEV;
+	int irq;
+
+	if (!np)
+		return ret;
+
+	indio_dev = iio_device_alloc(sizeof(struct exynos_adc));
+	if (!indio_dev) {
+		dev_err(&pdev->dev, "failed allocating iio device\n");
+		return -ENOMEM;
+	}
+
+	info = iio_priv(indio_dev);
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	info->regs = devm_request_and_ioremap(&pdev->dev, mem);
+	if (!info->regs) {
+		ret = -ENOMEM;
+		goto err_iio;
+	}
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	info->enable_reg = devm_request_and_ioremap(&pdev->dev, mem);
+	if (!info->enable_reg) {
+		ret = -ENOMEM;
+		goto err_iio;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "no irq resource?\n");
+		ret = irq;
+		goto err_iio;
+	}
+
+	info->irq = irq;
+
+	init_completion(&info->completion);
+
+	ret = request_irq(info->irq, exynos_adc_isr,
+					0, dev_name(&pdev->dev), info);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed requesting irq, irq = %d\n",
+							info->irq);
+		goto err_iio;
+	}
+
+	writel(1, info->enable_reg);
+
+	info->clk = devm_clk_get(&pdev->dev, "adc");
+	if (IS_ERR(info->clk)) {
+		dev_err(&pdev->dev, "failed getting clock, err = %ld\n",
+							PTR_ERR(info->clk));
+		ret = PTR_ERR(info->clk);
+		goto err_irq;
+	}
+
+	info->vdd = devm_regulator_get(&pdev->dev, "vdd");
+	if (IS_ERR(info->vdd)) {
+		dev_err(&pdev->dev, "failed getting regulator, err = %ld\n",
+							PTR_ERR(info->vdd));
+		ret = PTR_ERR(info->vdd);
+		goto err_irq;
+	}
+
+	info->version = exynos_adc_get_version(pdev);
+
+	platform_set_drvdata(pdev, indio_dev);
+
+	indio_dev->name = dev_name(&pdev->dev);
+	indio_dev->dev.parent = &pdev->dev;
+	indio_dev->dev.of_node = pdev->dev.of_node;
+	indio_dev->info = &exynos_adc_iio_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->channels = exynos_adc_iio_channels;
+
+	if (info->version == ADC_V1)
+		indio_dev->num_channels = MAX_ADC_V1_CHANNELS;
+	else
+		indio_dev->num_channels = MAX_ADC_V2_CHANNELS;
+
+	ret = iio_device_register(indio_dev);
+	if (ret)
+		goto err_irq;
+
+	ret = regulator_enable(info->vdd);
+	if (ret)
+		goto err_iio_dev;
+
+	clk_prepare_enable(info->clk);
+
+	exynos_adc_hw_init(info);
+
+	ret = of_platform_populate(np, exynos_adc_match, NULL, &pdev->dev);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed adding child nodes\n");
+		goto err_of_populate;
+	}
+
+	return 0;
+
+err_of_populate:
+	device_for_each_child(&pdev->dev, NULL,
+				exynos_adc_remove_devices);
+	regulator_disable(info->vdd);
+	clk_disable_unprepare(info->clk);
+err_iio_dev:
+	iio_device_unregister(indio_dev);
+err_irq:
+	free_irq(info->irq, info);
+err_iio:
+	iio_device_free(indio_dev);
+	return ret;
+}
+
+static int exynos_adc_remove(struct platform_device *pdev)
+{
+	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+	struct exynos_adc *info = iio_priv(indio_dev);
+
+	device_for_each_child(&pdev->dev, NULL,
+				exynos_adc_remove_devices);
+	regulator_disable(info->vdd);
+	clk_disable_unprepare(info->clk);
+	writel(0, info->enable_reg);
+	iio_device_unregister(indio_dev);
+	free_irq(info->irq, info);
+	iio_device_free(indio_dev);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int exynos_adc_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct exynos_adc *info = platform_get_drvdata(pdev);
+	u32 con;
+
+	if (info->version == ADC_V2) {
+		con = readl(ADC_V2_CON1(info->regs));
+		con &= ~ADC_CON_EN_START;
+		writel(con, ADC_V2_CON1(info->regs));
+	} else {
+		con = readl(ADC_V1_CON(info->regs));
+		con |= ADC_V1_CON_STANDBY;
+		writel(con, ADC_V1_CON(info->regs));
+	}
+
+	clk_disable_unprepare(info->clk);
+	writel(0, info->enable_reg);
+	regulator_disable(info->vdd);
+
+	return 0;
+}
+
+static int exynos_adc_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct exynos_adc *info = platform_get_drvdata(pdev);
+	int ret;
+
+	ret = regulator_enable(info->vdd);
+	if (ret)
+		return ret;
+
+	writel(1, info->enable_reg);
+	clk_prepare_enable(info->clk);
+
+	exynos_adc_hw_init(info);
+
+	return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(exynos_adc_pm_ops,
+			exynos_adc_suspend,
+			exynos_adc_resume);
+
+static struct platform_driver exynos_adc_driver = {
+	.probe		= exynos_adc_probe,
+	.remove		= exynos_adc_remove,
+	.driver		= {
+		.name	= "exynos-adc",
+		.owner	= THIS_MODULE,
+		.of_match_table = exynos_adc_match,
+		.pm	= &exynos_adc_pm_ops,
+	},
+};
+
+module_platform_driver(exynos_adc_driver);
+
+MODULE_AUTHOR("Naveen Krishna Chatradhi <ch.naveen@samsung.com>");
+MODULE_DESCRIPTION("Samsung EXYNOS5 ADC driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/adc/lp8788_adc.c b/drivers/iio/adc/lp8788_adc.c
index 763f575..62bc39e 100644
--- a/drivers/iio/adc/lp8788_adc.c
+++ b/drivers/iio/adc/lp8788_adc.c
@@ -132,8 +132,8 @@ static const struct iio_info lp8788_adc_info = {
 		.type = _type,					\
 		.indexed = 1,					\
 		.channel = LPADC_##_id,				\
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |	\
-			IIO_CHAN_INFO_SCALE_SEPARATE_BIT,	\
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |	\
+			BIT(IIO_CHAN_INFO_SCALE),		\
 		.datasheet_name = #_id,				\
 }
 
diff --git a/drivers/iio/adc/max1363.c b/drivers/iio/adc/max1363.c
index 6c1cfb7..9e6da72 100644
--- a/drivers/iio/adc/max1363.c
+++ b/drivers/iio/adc/max1363.c
@@ -427,15 +427,15 @@ static const enum max1363_modes max1363_mode_list[] = {
 #define MAX1363_EV_M						\
 	(IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING)	\
 	 | IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING))
-#define MAX1363_INFO_MASK (IIO_CHAN_INFO_RAW_SEPARATE_BIT |	\
-			   IIO_CHAN_INFO_SCALE_SHARED_BIT)
+
 #define MAX1363_CHAN_U(num, addr, si, bits, evmask)			\
 	{								\
 		.type = IIO_VOLTAGE,					\
 		.indexed = 1,						\
 		.channel = num,						\
 		.address = addr,					\
-		.info_mask = MAX1363_INFO_MASK,				\
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),	\
 		.datasheet_name = "AIN"#num,				\
 		.scan_type = {						\
 			.sign = 'u',					\
@@ -456,7 +456,8 @@ static const enum max1363_modes max1363_mode_list[] = {
 		.channel = num,						\
 		.channel2 = num2,					\
 		.address = addr,					\
-		.info_mask = MAX1363_INFO_MASK,				\
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),	\
 		.datasheet_name = "AIN"#num"-AIN"#num2,			\
 		.scan_type = {						\
 			.sign = 's',					\
diff --git a/drivers/iio/adc/ti-adc081c.c b/drivers/iio/adc/ti-adc081c.c
index f4a46dd..2826faa 100644
--- a/drivers/iio/adc/ti-adc081c.c
+++ b/drivers/iio/adc/ti-adc081c.c
@@ -55,8 +55,8 @@ static int adc081c_read_raw(struct iio_dev *iio,
 
 static const struct iio_chan_spec adc081c_channel = {
 	.type = IIO_VOLTAGE,
-	.info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT |
-		     IIO_CHAN_INFO_RAW_SEPARATE_BIT,
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
 };
 
 static const struct iio_info adc081c_info = {
diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
index cd030e1..5f9a7e7 100644
--- a/drivers/iio/adc/ti_am335x_adc.c
+++ b/drivers/iio/adc/ti_am335x_adc.c
@@ -89,7 +89,7 @@ static int tiadc_channel_init(struct iio_dev *indio_dev, int channels)
 		chan->type = IIO_VOLTAGE;
 		chan->indexed = 1;
 		chan->channel = i;
-		chan->info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT;
+		chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
 	}
 
 	indio_dev->channels = chan_array;
diff --git a/drivers/iio/adc/viperboard_adc.c b/drivers/iio/adc/viperboard_adc.c
index ad02615..56ac481 100644
--- a/drivers/iio/adc/viperboard_adc.c
+++ b/drivers/iio/adc/viperboard_adc.c
@@ -41,7 +41,7 @@ struct vprbrd_adc {
 	.type = IIO_VOLTAGE,				\
 	.indexed = 1,					\
 	.channel = _index,				\
-	.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,	\
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),	\
 	.scan_index = _index,				\
 	.scan_type = {					\
 		.sign = 'u',				\
diff --git a/drivers/iio/amplifiers/ad8366.c b/drivers/iio/amplifiers/ad8366.c
index d6c0af2..d354554 100644
--- a/drivers/iio/amplifiers/ad8366.c
+++ b/drivers/iio/amplifiers/ad8366.c
@@ -125,7 +125,7 @@ static const struct iio_info ad8366_info = {
 	.output = 1,					\
 	.indexed = 1,					\
 	.channel = _channel,				\
-	.info_mask = IIO_CHAN_INFO_HARDWAREGAIN_SEPARATE_BIT,\
+	.info_mask_separate = BIT(IIO_CHAN_INFO_HARDWAREGAIN),\
 }
 
 static const struct iio_chan_spec ad8366_channels[] = {
diff --git a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
index 7a525a9..87419c4 100644
--- a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
+++ b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
@@ -31,7 +31,7 @@
 static int hid_sensor_data_rdy_trigger_set_state(struct iio_trigger *trig,
 						bool state)
 {
-	struct hid_sensor_common *st = trig->private_data;
+	struct hid_sensor_common *st = iio_trigger_get_drvdata(trig);
 	int state_val;
 
 	state_val = state ? 1 : 0;
@@ -76,7 +76,7 @@ int hid_sensor_setup_trigger(struct iio_dev *indio_dev, const char *name,
 	}
 
 	trig->dev.parent = indio_dev->dev.parent;
-	trig->private_data = attrb;
+	iio_trigger_set_drvdata(trig, attrb);
 	trig->ops = &hid_sensor_trigger_ops;
 	ret = iio_trigger_register(trig);
 
diff --git a/drivers/iio/common/st_sensors/st_sensors_spi.c b/drivers/iio/common/st_sensors/st_sensors_spi.c
index f0aa2f1..251baf6 100644
--- a/drivers/iio/common/st_sensors/st_sensors_spi.c
+++ b/drivers/iio/common/st_sensors/st_sensors_spi.c
@@ -29,7 +29,6 @@ static unsigned int st_sensors_spi_get_irq(struct iio_dev *indio_dev)
 static int st_sensors_spi_read(struct st_sensor_transfer_buffer *tb,
 	struct device *dev, u8 reg_addr, int len, u8 *data, bool multiread_bit)
 {
-	struct spi_message msg;
 	int err;
 
 	struct spi_transfer xfers[] = {
@@ -51,10 +50,7 @@ static int st_sensors_spi_read(struct st_sensor_transfer_buffer *tb,
 	else
 		tb->tx_buf[0] = reg_addr | ST_SENSORS_SPI_READ;
 
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfers[0], &msg);
-	spi_message_add_tail(&xfers[1], &msg);
-	err = spi_sync(to_spi_device(dev), &msg);
+	err = spi_sync_transfer(to_spi_device(dev), xfers, ARRAY_SIZE(xfers));
 	if (err)
 		goto acc_spi_read_error;
 
@@ -83,7 +79,6 @@ static int st_sensors_spi_read_multiple_byte(
 static int st_sensors_spi_write_byte(struct st_sensor_transfer_buffer *tb,
 				struct device *dev, u8 reg_addr, u8 data)
 {
-	struct spi_message msg;
 	int err;
 
 	struct spi_transfer xfers = {
@@ -96,9 +91,7 @@ static int st_sensors_spi_write_byte(struct st_sensor_transfer_buffer *tb,
 	tb->tx_buf[0] = reg_addr;
 	tb->tx_buf[1] = data;
 
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfers, &msg);
-	err = spi_sync(to_spi_device(dev), &msg);
+	err = spi_sync_transfer(to_spi_device(dev), &xfers, 1);
 	mutex_unlock(&tb->buf_lock);
 
 	return err;
diff --git a/drivers/iio/common/st_sensors/st_sensors_trigger.c b/drivers/iio/common/st_sensors/st_sensors_trigger.c
index 139ed03..8fc3a97 100644
--- a/drivers/iio/common/st_sensors/st_sensors_trigger.c
+++ b/drivers/iio/common/st_sensors/st_sensors_trigger.c
@@ -40,7 +40,7 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev,
 	if (err)
 		goto request_irq_error;
 
-	sdata->trig->private_data = indio_dev;
+	iio_trigger_set_drvdata(sdata->trig, indio_dev);
 	sdata->trig->ops = trigger_ops;
 	sdata->trig->dev.parent = sdata->dev;
 
diff --git a/drivers/iio/dac/ad5064.c b/drivers/iio/dac/ad5064.c
index 74f2d52..aa26d50 100644
--- a/drivers/iio/dac/ad5064.c
+++ b/drivers/iio/dac/ad5064.c
@@ -296,8 +296,8 @@ static const struct iio_chan_spec_ext_info ad5064_ext_info[] = {
 	.indexed = 1,						\
 	.output = 1,						\
 	.channel = (chan),					\
-	.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |		\
-	IIO_CHAN_INFO_SCALE_SEPARATE_BIT,			\
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |		\
+	BIT(IIO_CHAN_INFO_SCALE),					\
 	.address = addr,					\
 	.scan_type = IIO_ST('u', (bits), 16, 20 - (bits)),	\
 	.ext_info = ad5064_ext_info,				\
diff --git a/drivers/iio/dac/ad5360.c b/drivers/iio/dac/ad5360.c
index 9277121..80923af 100644
--- a/drivers/iio/dac/ad5360.c
+++ b/drivers/iio/dac/ad5360.c
@@ -102,11 +102,11 @@ enum ad5360_type {
 	.type = IIO_VOLTAGE,					\
 	.indexed = 1,						\
 	.output = 1,						\
-	.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |		\
-		IIO_CHAN_INFO_SCALE_SEPARATE_BIT |		\
-		IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |		\
-		IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT |	\
-		IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT,	\
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |		\
+		BIT(IIO_CHAN_INFO_SCALE) |				\
+		BIT(IIO_CHAN_INFO_OFFSET) |				\
+		BIT(IIO_CHAN_INFO_CALIBSCALE) |			\
+		BIT(IIO_CHAN_INFO_CALIBBIAS),			\
 	.scan_type = IIO_ST('u', (bits), 16, 16 - (bits))	\
 }
 
diff --git a/drivers/iio/dac/ad5380.c b/drivers/iio/dac/ad5380.c
index 483fc37..bf2db02 100644
--- a/drivers/iio/dac/ad5380.c
+++ b/drivers/iio/dac/ad5380.c
@@ -257,10 +257,10 @@ static struct iio_chan_spec_ext_info ad5380_ext_info[] = {
 	.type = IIO_VOLTAGE,					\
 	.indexed = 1,						\
 	.output = 1,						\
-	.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |		\
-		IIO_CHAN_INFO_SCALE_SHARED_BIT |		\
-		IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT |		\
-		IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT,		\
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |		\
+		BIT(IIO_CHAN_INFO_CALIBSCALE) |			\
+		BIT(IIO_CHAN_INFO_CALIBBIAS),			\
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),	\
 	.scan_type = IIO_ST('u', (_bits), 16, 14 - (_bits)),	\
 	.ext_info = ad5380_ext_info,				\
 }
diff --git a/drivers/iio/dac/ad5421.c b/drivers/iio/dac/ad5421.c
index 6b86a63..98f2440 100644
--- a/drivers/iio/dac/ad5421.c
+++ b/drivers/iio/dac/ad5421.c
@@ -86,11 +86,11 @@ static const struct iio_chan_spec ad5421_channels[] = {
 		.indexed = 1,
 		.output = 1,
 		.channel = 0,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-			IIO_CHAN_INFO_SCALE_SHARED_BIT |
-			IIO_CHAN_INFO_OFFSET_SHARED_BIT |
-			IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT |
-			IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+			BIT(IIO_CHAN_INFO_CALIBSCALE) |
+			BIT(IIO_CHAN_INFO_CALIBBIAS),
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |
+			BIT(IIO_CHAN_INFO_OFFSET),
 		.scan_type = IIO_ST('u', 16, 16, 0),
 		.event_mask = IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING) |
 			IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING),
diff --git a/drivers/iio/dac/ad5446.c b/drivers/iio/dac/ad5446.c
index f5583ae..cae8f60 100644
--- a/drivers/iio/dac/ad5446.c
+++ b/drivers/iio/dac/ad5446.c
@@ -143,8 +143,8 @@ static const struct iio_chan_spec_ext_info ad5446_ext_info_powerdown[] = {
 	.indexed = 1, \
 	.output = 1, \
 	.channel = 0, \
-	.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
-	IIO_CHAN_INFO_SCALE_SHARED_BIT,	\
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
 	.scan_type = IIO_ST('u', (bits), (storage), (shift)), \
 	.ext_info = (ext), \
 }
diff --git a/drivers/iio/dac/ad5449.c b/drivers/iio/dac/ad5449.c
index c4731b7..ba1c914 100644
--- a/drivers/iio/dac/ad5449.c
+++ b/drivers/iio/dac/ad5449.c
@@ -206,8 +206,8 @@ static const struct iio_info ad5449_info = {
 	.indexed = 1,						\
 	.output = 1,						\
 	.channel = (chan),					\
-	.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |		\
-		IIO_CHAN_INFO_SCALE_SEPARATE_BIT,		\
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |		\
+		BIT(IIO_CHAN_INFO_SCALE),			\
 	.address = (chan),					\
 	.scan_type = IIO_ST('u', (bits), 16, 12 - (bits)),	\
 }
diff --git a/drivers/iio/dac/ad5504.c b/drivers/iio/dac/ad5504.c
index e5e5974..139206e 100644
--- a/drivers/iio/dac/ad5504.c
+++ b/drivers/iio/dac/ad5504.c
@@ -259,8 +259,8 @@ static const struct iio_chan_spec_ext_info ad5504_ext_info[] = {
 	.indexed = 1, \
 	.output = 1, \
 	.channel = (_chan), \
-	.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
-		     IIO_CHAN_INFO_SCALE_SHARED_BIT, \
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
 	.address = AD5504_ADDR_DAC(_chan), \
 	.scan_type = IIO_ST('u', 12, 16, 0), \
 	.ext_info = ad5504_ext_info, \
diff --git a/drivers/iio/dac/ad5624r_spi.c b/drivers/iio/dac/ad5624r_spi.c
index f6e1166..bb298aa 100644
--- a/drivers/iio/dac/ad5624r_spi.c
+++ b/drivers/iio/dac/ad5624r_spi.c
@@ -174,8 +174,8 @@ static const struct iio_chan_spec_ext_info ad5624r_ext_info[] = {
 	.indexed = 1, \
 	.output = 1, \
 	.channel = (_chan), \
-	.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
-		     IIO_CHAN_INFO_SCALE_SHARED_BIT, \
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
 	.address = (_chan), \
 	.scan_type = IIO_ST('u', (_bits), 16, 16 - (_bits)), \
 	.ext_info = ad5624r_ext_info, \
diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c
index 5e554af..06439b1 100644
--- a/drivers/iio/dac/ad5686.c
+++ b/drivers/iio/dac/ad5686.c
@@ -276,9 +276,9 @@ static const struct iio_chan_spec_ext_info ad5686_ext_info[] = {
 		.indexed = 1,					\
 		.output = 1,					\
 		.channel = chan,				\
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |	\
-		IIO_CHAN_INFO_SCALE_SHARED_BIT,			\
-		.address = AD5686_ADDR_DAC(chan),			\
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),	\
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),\
+		.address = AD5686_ADDR_DAC(chan),		\
 		.scan_type = IIO_ST('u', bits, 16, shift),	\
 		.ext_info = ad5686_ext_info,			\
 }
diff --git a/drivers/iio/dac/ad5755.c b/drivers/iio/dac/ad5755.c
index 71faabc..12bb315 100644
--- a/drivers/iio/dac/ad5755.c
+++ b/drivers/iio/dac/ad5755.c
@@ -393,11 +393,11 @@ static const struct iio_chan_spec_ext_info ad5755_ext_info[] = {
 #define AD5755_CHANNEL(_bits) {					\
 	.indexed = 1,						\
 	.output = 1,						\
-	.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |		\
-		IIO_CHAN_INFO_SCALE_SEPARATE_BIT |		\
-		IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |		\
-		IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT |		\
-		IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT,		\
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |		\
+		BIT(IIO_CHAN_INFO_SCALE) |			\
+		BIT(IIO_CHAN_INFO_OFFSET) |			\
+		BIT(IIO_CHAN_INFO_CALIBSCALE) |			\
+		BIT(IIO_CHAN_INFO_CALIBBIAS),			\
 	.scan_type = IIO_ST('u', (_bits), 16, 16 - (_bits)),	\
 	.ext_info = ad5755_ext_info,				\
 }
diff --git a/drivers/iio/dac/ad5764.c b/drivers/iio/dac/ad5764.c
index 5b7acd3..7a53f7d 100644
--- a/drivers/iio/dac/ad5764.c
+++ b/drivers/iio/dac/ad5764.c
@@ -78,11 +78,11 @@ enum ad5764_type {
 	.output = 1,						\
 	.channel = (_chan),					\
 	.address = (_chan),					\
-	.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |		\
-		IIO_CHAN_INFO_OFFSET_SHARED_BIT |		\
-		IIO_CHAN_INFO_SCALE_SEPARATE_BIT |		\
-		IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT |		\
-		IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT,		\
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |		\
+		BIT(IIO_CHAN_INFO_SCALE) |			\
+		BIT(IIO_CHAN_INFO_CALIBSCALE) |			\
+		BIT(IIO_CHAN_INFO_CALIBBIAS),			\
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET),	\
 	.scan_type = IIO_ST('u', (_bits), 16, 16 - (_bits))	\
 }
 
diff --git a/drivers/iio/dac/ad5791.c b/drivers/iio/dac/ad5791.c
index 8dfd3da..97c1e5d 100644
--- a/drivers/iio/dac/ad5791.c
+++ b/drivers/iio/dac/ad5791.c
@@ -302,9 +302,9 @@ static const struct iio_chan_spec_ext_info ad5791_ext_info[] = {
 	.indexed = 1,					\
 	.address = AD5791_ADDR_DAC0,			\
 	.channel = 0,					\
-	.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |	\
-		IIO_CHAN_INFO_SCALE_SHARED_BIT |	\
-		IIO_CHAN_INFO_OFFSET_SHARED_BIT,	\
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),	\
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |	\
+		BIT(IIO_CHAN_INFO_OFFSET),		\
 	.scan_type = IIO_ST('u', bits, 24, shift),	\
 	.ext_info = ad5791_ext_info,			\
 }
diff --git a/drivers/iio/dac/max517.c b/drivers/iio/dac/max517.c
index 352abe2..ebfaa41 100644
--- a/drivers/iio/dac/max517.c
+++ b/drivers/iio/dac/max517.c
@@ -146,8 +146,8 @@ static const struct iio_info max517_info = {
 	.indexed = 1,					\
 	.output = 1,					\
 	.channel = (chan),				\
-	.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |	\
-	IIO_CHAN_INFO_SCALE_SEPARATE_BIT,		\
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |	\
+	BIT(IIO_CHAN_INFO_SCALE),			\
 	.scan_type = IIO_ST('u', 8, 8, 0),		\
 }
 
diff --git a/drivers/iio/dac/mcp4725.c b/drivers/iio/dac/mcp4725.c
index 8f88cc4..a612ec7 100644
--- a/drivers/iio/dac/mcp4725.c
+++ b/drivers/iio/dac/mcp4725.c
@@ -69,8 +69,8 @@ static const struct iio_chan_spec mcp4725_channel = {
 	.indexed	= 1,
 	.output		= 1,
 	.channel	= 0,
-	.info_mask	= IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-			  IIO_CHAN_INFO_SCALE_SHARED_BIT,
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
 	.scan_type	= IIO_ST('u', 12, 16, 0),
 };
 
diff --git a/drivers/iio/frequency/ad9523.c b/drivers/iio/frequency/ad9523.c
index 1ea132e..92276de 100644
--- a/drivers/iio/frequency/ad9523.c
+++ b/drivers/iio/frequency/ad9523.c
@@ -920,10 +920,10 @@ static int ad9523_setup(struct iio_dev *indio_dev)
 			st->ad9523_channels[i].channel = chan->channel_num;
 			st->ad9523_channels[i].extend_name =
 				chan->extended_name;
-			st->ad9523_channels[i].info_mask =
-				IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-				IIO_CHAN_INFO_PHASE_SEPARATE_BIT |
-				IIO_CHAN_INFO_FREQUENCY_SEPARATE_BIT;
+			st->ad9523_channels[i].info_mask_separate =
+				BIT(IIO_CHAN_INFO_RAW) |
+				BIT(IIO_CHAN_INFO_PHASE) |
+				BIT(IIO_CHAN_INFO_FREQUENCY);
 		}
 	}
 
diff --git a/drivers/iio/gyro/adis16080.c b/drivers/iio/gyro/adis16080.c
index 1861287..e1bb5f9 100644
--- a/drivers/iio/gyro/adis16080.c
+++ b/drivers/iio/gyro/adis16080.c
@@ -136,32 +136,32 @@ static const struct iio_chan_spec adis16080_channels[] = {
 		.type = IIO_ANGL_VEL,
 		.modified = 1,
 		.channel2 = IIO_MOD_Z,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-			IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+			BIT(IIO_CHAN_INFO_SCALE),
 		.address = ADIS16080_DIN_GYRO,
 	}, {
 		.type = IIO_VOLTAGE,
 		.indexed = 1,
 		.channel = 0,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-			IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
-			IIO_CHAN_INFO_OFFSET_SEPARATE_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+			BIT(IIO_CHAN_INFO_SCALE) |
+			BIT(IIO_CHAN_INFO_OFFSET),
 		.address = ADIS16080_DIN_AIN1,
 	}, {
 		.type = IIO_VOLTAGE,
 		.indexed = 1,
 		.channel = 1,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-			IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
-			IIO_CHAN_INFO_OFFSET_SEPARATE_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+			BIT(IIO_CHAN_INFO_SCALE) |
+			BIT(IIO_CHAN_INFO_OFFSET),
 		.address = ADIS16080_DIN_AIN2,
 	}, {
 		.type = IIO_TEMP,
 		.indexed = 1,
 		.channel = 0,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-			IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
-			IIO_CHAN_INFO_OFFSET_SEPARATE_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+			BIT(IIO_CHAN_INFO_SCALE) |
+			BIT(IIO_CHAN_INFO_OFFSET),
 		.address = ADIS16080_DIN_TEMP,
 	}
 };
diff --git a/drivers/iio/gyro/adis16136.c b/drivers/iio/gyro/adis16136.c
index 8cb0bcb..058e6d5 100644
--- a/drivers/iio/gyro/adis16136.c
+++ b/drivers/iio/gyro/adis16136.c
@@ -357,10 +357,11 @@ static const struct iio_chan_spec adis16136_channels[] = {
 		.type = IIO_ANGL_VEL,
 		.modified = 1,
 		.channel2 = IIO_MOD_X,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-			IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
-			IIO_CHAN_INFO_SCALE_SHARED_BIT |
-			IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SEPARATE_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+			BIT(IIO_CHAN_INFO_CALIBBIAS) |
+			BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY),
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
+
 		.address = ADIS16136_REG_GYRO_OUT2,
 		.scan_index = ADIS16136_SCAN_GYRO,
 		.scan_type = {
@@ -373,8 +374,8 @@ static const struct iio_chan_spec adis16136_channels[] = {
 		.type = IIO_TEMP,
 		.indexed = 1,
 		.channel = 0,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-			IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+			BIT(IIO_CHAN_INFO_SCALE),
 		.address = ADIS16136_REG_TEMP_OUT,
 		.scan_index = ADIS16136_SCAN_TEMP,
 		.scan_type = {
diff --git a/drivers/iio/gyro/adxrs450.c b/drivers/iio/gyro/adxrs450.c
index 5b79953..8bd72b4 100644
--- a/drivers/iio/gyro/adxrs450.c
+++ b/drivers/iio/gyro/adxrs450.c
@@ -383,16 +383,16 @@ static const struct iio_chan_spec adxrs450_channels[2][2] = {
 			.type = IIO_ANGL_VEL,
 			.modified = 1,
 			.channel2 = IIO_MOD_Z,
-			.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-			IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
-			IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SEPARATE_BIT |
-			IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+			.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+			BIT(IIO_CHAN_INFO_CALIBBIAS) |
+			BIT(IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW) |
+			BIT(IIO_CHAN_INFO_SCALE),
 		}, {
 			.type = IIO_TEMP,
 			.indexed = 1,
 			.channel = 0,
-			.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-			IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+			.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+			BIT(IIO_CHAN_INFO_SCALE),
 		}
 	},
 	[ID_ADXRS453] = {
@@ -400,15 +400,15 @@ static const struct iio_chan_spec adxrs450_channels[2][2] = {
 			.type = IIO_ANGL_VEL,
 			.modified = 1,
 			.channel2 = IIO_MOD_Z,
-			.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-			IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
-			IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SEPARATE_BIT,
+			.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+			BIT(IIO_CHAN_INFO_SCALE) |
+			BIT(IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW),
 		}, {
 			.type = IIO_TEMP,
 			.indexed = 1,
 			.channel = 0,
-			.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-			IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+			.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+			BIT(IIO_CHAN_INFO_SCALE),
 		}
 	},
 };
diff --git a/drivers/iio/gyro/hid-sensor-gyro-3d.c b/drivers/iio/gyro/hid-sensor-gyro-3d.c
index fcfc83a..bc943dd 100644
--- a/drivers/iio/gyro/hid-sensor-gyro-3d.c
+++ b/drivers/iio/gyro/hid-sensor-gyro-3d.c
@@ -60,28 +60,28 @@ static const struct iio_chan_spec gyro_3d_channels[] = {
 		.type = IIO_ANGL_VEL,
 		.modified = 1,
 		.channel2 = IIO_MOD_X,
-		.info_mask = IIO_CHAN_INFO_OFFSET_SHARED_BIT |
-		IIO_CHAN_INFO_SCALE_SHARED_BIT |
-		IIO_CHAN_INFO_SAMP_FREQ_SHARED_BIT |
-		IIO_CHAN_INFO_HYSTERESIS_SHARED_BIT,
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
+		BIT(IIO_CHAN_INFO_SCALE) |
+		BIT(IIO_CHAN_INFO_SAMP_FREQ) |
+		BIT(IIO_CHAN_INFO_HYSTERESIS),
 		.scan_index = CHANNEL_SCAN_INDEX_X,
 	}, {
 		.type = IIO_ANGL_VEL,
 		.modified = 1,
 		.channel2 = IIO_MOD_Y,
-		.info_mask = IIO_CHAN_INFO_OFFSET_SHARED_BIT |
-		IIO_CHAN_INFO_SCALE_SHARED_BIT |
-		IIO_CHAN_INFO_SAMP_FREQ_SHARED_BIT |
-		IIO_CHAN_INFO_HYSTERESIS_SHARED_BIT,
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
+		BIT(IIO_CHAN_INFO_SCALE) |
+		BIT(IIO_CHAN_INFO_SAMP_FREQ) |
+		BIT(IIO_CHAN_INFO_HYSTERESIS),
 		.scan_index = CHANNEL_SCAN_INDEX_Y,
 	}, {
 		.type = IIO_ANGL_VEL,
 		.modified = 1,
 		.channel2 = IIO_MOD_Z,
-		.info_mask = IIO_CHAN_INFO_OFFSET_SHARED_BIT |
-		IIO_CHAN_INFO_SCALE_SHARED_BIT |
-		IIO_CHAN_INFO_SAMP_FREQ_SHARED_BIT |
-		IIO_CHAN_INFO_HYSTERESIS_SHARED_BIT,
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
+		BIT(IIO_CHAN_INFO_SCALE) |
+		BIT(IIO_CHAN_INFO_SAMP_FREQ) |
+		BIT(IIO_CHAN_INFO_HYSTERESIS),
 		.scan_index = CHANNEL_SCAN_INDEX_Z,
 	}
 };
diff --git a/drivers/iio/gyro/itg3200_buffer.c b/drivers/iio/gyro/itg3200_buffer.c
index f667d2c..6c43af9 100644
--- a/drivers/iio/gyro/itg3200_buffer.c
+++ b/drivers/iio/gyro/itg3200_buffer.c
@@ -81,7 +81,7 @@ void itg3200_buffer_unconfigure(struct iio_dev *indio_dev)
 static int itg3200_data_rdy_trigger_set_state(struct iio_trigger *trig,
 		bool state)
 {
-	struct iio_dev *indio_dev = trig->private_data;
+	struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
 	int ret;
 	u8 msc;
 
@@ -129,7 +129,7 @@ int itg3200_probe_trigger(struct iio_dev *indio_dev)
 
 	st->trig->dev.parent = &st->i2c->dev;
 	st->trig->ops = &itg3200_trigger_ops;
-	st->trig->private_data = indio_dev;
+	iio_trigger_set_drvdata(st->trig, indio_dev);
 	ret = iio_trigger_register(st->trig);
 	if (ret)
 		goto error_free_irq;
diff --git a/drivers/iio/gyro/itg3200_core.c b/drivers/iio/gyro/itg3200_core.c
index df2e6aa..d66605d2 100644
--- a/drivers/iio/gyro/itg3200_core.c
+++ b/drivers/iio/gyro/itg3200_core.c
@@ -248,12 +248,6 @@ err_ret:
 	return ret;
 }
 
-#define ITG3200_TEMP_INFO_MASK	(IIO_CHAN_INFO_OFFSET_SHARED_BIT | \
-				 IIO_CHAN_INFO_SCALE_SHARED_BIT | \
-				 IIO_CHAN_INFO_RAW_SEPARATE_BIT)
-#define ITG3200_GYRO_INFO_MASK	(IIO_CHAN_INFO_SCALE_SHARED_BIT | \
-				 IIO_CHAN_INFO_RAW_SEPARATE_BIT)
-
 #define ITG3200_ST						\
 	{ .sign = 's', .realbits = 16, .storagebits = 16, .endianness = IIO_BE }
 
@@ -261,7 +255,8 @@ err_ret:
 	.type = IIO_ANGL_VEL, \
 	.modified = 1, \
 	.channel2 = IIO_MOD_ ## _mod, \
-	.info_mask = ITG3200_GYRO_INFO_MASK, \
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
 	.address = ITG3200_REG_GYRO_ ## _mod ## OUT_H, \
 	.scan_index = ITG3200_SCAN_GYRO_ ## _mod, \
 	.scan_type = ITG3200_ST, \
@@ -271,7 +266,9 @@ static const struct iio_chan_spec itg3200_channels[] = {
 	{
 		.type = IIO_TEMP,
 		.channel2 = IIO_NO_MOD,
-		.info_mask = ITG3200_TEMP_INFO_MASK,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
+		BIT(IIO_CHAN_INFO_SCALE),
 		.address = ITG3200_REG_TEMP_OUT_H,
 		.scan_index = ITG3200_SCAN_TEMP,
 		.scan_type = ITG3200_ST,
diff --git a/drivers/iio/gyro/st_gyro_buffer.c b/drivers/iio/gyro/st_gyro_buffer.c
index da4d122..69017c7 100644
--- a/drivers/iio/gyro/st_gyro_buffer.c
+++ b/drivers/iio/gyro/st_gyro_buffer.c
@@ -25,7 +25,7 @@
 
 int st_gyro_trig_set_state(struct iio_trigger *trig, bool state)
 {
-	struct iio_dev *indio_dev = trig->private_data;
+	struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
 
 	return st_sensors_set_dataready_irq(indio_dev, state);
 }
diff --git a/drivers/iio/iio_core.h b/drivers/iio/iio_core.h
index f652e6a..05c1b74 100644
--- a/drivers/iio/iio_core.h
+++ b/drivers/iio/iio_core.h
@@ -18,6 +18,7 @@
 struct iio_chan_spec;
 struct iio_dev;
 
+extern struct device_type iio_device_type;
 
 int __iio_add_chan_devattr(const char *postfix,
 			   struct iio_chan_spec const *chan,
diff --git a/drivers/iio/imu/adis16400_core.c b/drivers/iio/imu/adis16400_core.c
index b7f215e..f60591f 100644
--- a/drivers/iio/imu/adis16400_core.c
+++ b/drivers/iio/imu/adis16400_core.c
@@ -484,8 +484,8 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
 	.indexed = 1, \
 	.channel = 0, \
 	.extend_name = name, \
-	.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
-		IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+		BIT(IIO_CHAN_INFO_SCALE), \
 	.address = (addr), \
 	.scan_index = (si), \
 	.scan_type = { \
@@ -507,10 +507,10 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
 	.type = IIO_ANGL_VEL, \
 	.modified = 1, \
 	.channel2 = IIO_MOD_ ## mod, \
-	.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
-		IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | \
-		IIO_CHAN_INFO_SCALE_SHARED_BIT | \
-		IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, \
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+		BIT(IIO_CHAN_INFO_CALIBBIAS),		  \
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
+		BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \
 	.address = addr, \
 	.scan_index = ADIS16400_SCAN_GYRO_ ## mod, \
 	.scan_type = { \
@@ -526,10 +526,10 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
 	.type = IIO_ACCEL, \
 	.modified = 1, \
 	.channel2 = IIO_MOD_ ## mod, \
-	.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
-		IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | \
-		IIO_CHAN_INFO_SCALE_SHARED_BIT | \
-		IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, \
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+		BIT(IIO_CHAN_INFO_CALIBBIAS), \
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
+		BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \
 	.address = (addr), \
 	.scan_index = ADIS16400_SCAN_ACC_ ## mod, \
 	.scan_type = { \
@@ -545,9 +545,9 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
 	.type = IIO_MAGN, \
 	.modified = 1, \
 	.channel2 = IIO_MOD_ ## mod, \
-	.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
-		IIO_CHAN_INFO_SCALE_SHARED_BIT | \
-		IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, \
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
+		BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \
 	.address = (addr), \
 	.scan_index = ADIS16400_SCAN_MAGN_ ## mod, \
 	.scan_type = { \
@@ -568,10 +568,11 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
 	.indexed = 1, \
 	.channel = 0, \
 	.extend_name = ADIS16400_MOD_TEMP_NAME_ ## mod, \
-	.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
-		IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | \
-		IIO_CHAN_INFO_SCALE_SEPARATE_BIT | \
-		IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, \
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+		BIT(IIO_CHAN_INFO_OFFSET) | \
+		BIT(IIO_CHAN_INFO_SCALE), \
+	.info_mask_shared_by_type = \
+		BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \
 	.address = (addr), \
 	.scan_index = ADIS16350_SCAN_TEMP_ ## mod, \
 	.scan_type = { \
@@ -587,9 +588,9 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
 	.type = IIO_TEMP, \
 	.indexed = 1, \
 	.channel = 0, \
-	.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
-		IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | \
-		IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+		BIT(IIO_CHAN_INFO_OFFSET) | \
+		BIT(IIO_CHAN_INFO_SCALE), \
 	.address = (addr), \
 	.scan_index = ADIS16350_SCAN_TEMP_X, \
 	.scan_type = { \
@@ -605,8 +606,8 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
 	.type = IIO_INCLI, \
 	.modified = 1, \
 	.channel2 = IIO_MOD_ ## mod, \
-	.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
-		IIO_CHAN_INFO_SCALE_SHARED_BIT, \
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
 	.address = (addr), \
 	.scan_index = ADIS16300_SCAN_INCLI_ ## mod, \
 	.scan_type = { \
@@ -646,8 +647,8 @@ static const struct iio_chan_spec adis16448_channels[] = {
 	ADIS16400_MAGN_CHAN(Z, ADIS16400_ZMAGN_OUT, 16),
 	{
 		.type = IIO_PRESSURE,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-		IIO_CHAN_INFO_SCALE_SHARED_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
 		.address = ADIS16448_BARO_OUT,
 		.scan_index = ADIS16400_SCAN_BARO,
 		.scan_type = IIO_ST('s', 16, 16, 0),
diff --git a/drivers/iio/imu/adis16480.c b/drivers/iio/imu/adis16480.c
index 8c26a5f..b7db383 100644
--- a/drivers/iio/imu/adis16480.c
+++ b/drivers/iio/imu/adis16480.c
@@ -591,15 +591,15 @@ static int adis16480_write_raw(struct iio_dev *indio_dev,
 	}
 }
 
-#define ADIS16480_MOD_CHANNEL(_type, _mod, _address, _si, _info, _bits) \
+#define ADIS16480_MOD_CHANNEL(_type, _mod, _address, _si, _info_sep, _bits) \
 	{ \
 		.type = (_type), \
 		.modified = 1, \
 		.channel2 = (_mod), \
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
-			IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | \
-			IIO_CHAN_INFO_SCALE_SHARED_BIT | \
-			_info, \
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+			BIT(IIO_CHAN_INFO_CALIBBIAS) | \
+			_info_sep, \
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
 		.address = (_address), \
 		.scan_index = (_si), \
 		.scan_type = { \
@@ -613,21 +613,21 @@ static int adis16480_write_raw(struct iio_dev *indio_dev,
 #define ADIS16480_GYRO_CHANNEL(_mod) \
 	ADIS16480_MOD_CHANNEL(IIO_ANGL_VEL, IIO_MOD_ ## _mod, \
 	ADIS16480_REG_ ## _mod ## _GYRO_OUT, ADIS16480_SCAN_GYRO_ ## _mod, \
-	IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SEPARATE_BIT | \
-	IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT, \
+	BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY) | \
+	BIT(IIO_CHAN_INFO_CALIBSCALE), \
 	32)
 
 #define ADIS16480_ACCEL_CHANNEL(_mod) \
 	ADIS16480_MOD_CHANNEL(IIO_ACCEL, IIO_MOD_ ## _mod, \
 	ADIS16480_REG_ ## _mod ## _ACCEL_OUT, ADIS16480_SCAN_ACCEL_ ## _mod, \
-	IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SEPARATE_BIT | \
-	IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT, \
+	BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY) | \
+	BIT(IIO_CHAN_INFO_CALIBSCALE), \
 	32)
 
 #define ADIS16480_MAGN_CHANNEL(_mod) \
 	ADIS16480_MOD_CHANNEL(IIO_MAGN, IIO_MOD_ ## _mod, \
 	ADIS16480_REG_ ## _mod ## _MAGN_OUT, ADIS16480_SCAN_MAGN_ ## _mod, \
-	IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SEPARATE_BIT, \
+	BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \
 	16)
 
 #define ADIS16480_PRESSURE_CHANNEL() \
@@ -635,9 +635,9 @@ static int adis16480_write_raw(struct iio_dev *indio_dev,
 		.type = IIO_PRESSURE, \
 		.indexed = 1, \
 		.channel = 0, \
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
-			IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | \
-			IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+			BIT(IIO_CHAN_INFO_CALIBBIAS) | \
+			BIT(IIO_CHAN_INFO_SCALE), \
 		.address = ADIS16480_REG_BAROM_OUT, \
 		.scan_index = ADIS16480_SCAN_BARO, \
 		.scan_type = { \
@@ -652,9 +652,9 @@ static int adis16480_write_raw(struct iio_dev *indio_dev,
 		.type = IIO_TEMP, \
 		.indexed = 1, \
 		.channel = 0, \
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
-			IIO_CHAN_INFO_SCALE_SEPARATE_BIT | \
-			IIO_CHAN_INFO_OFFSET_SEPARATE_BIT, \
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+			BIT(IIO_CHAN_INFO_SCALE) | \
+			BIT(IIO_CHAN_INFO_OFFSET), \
 		.address = ADIS16480_REG_TEMP_OUT, \
 		.scan_index = ADIS16480_SCAN_TEMP, \
 		.scan_type = { \
diff --git a/drivers/iio/imu/adis_trigger.c b/drivers/iio/imu/adis_trigger.c
index 5a24c9c..e0017c2 100644
--- a/drivers/iio/imu/adis_trigger.c
+++ b/drivers/iio/imu/adis_trigger.c
@@ -19,7 +19,7 @@
 static int adis_data_rdy_trigger_set_state(struct iio_trigger *trig,
 						bool state)
 {
-	struct adis *adis = trig->private_data;
+	struct adis *adis = iio_trigger_get_drvdata(trig);
 
 	return adis_enable_irq(adis, state);
 }
@@ -57,7 +57,7 @@ int adis_probe_trigger(struct adis *adis, struct iio_dev *indio_dev)
 
 	adis->trig->dev.parent = &adis->spi->dev;
 	adis->trig->ops = &adis_trigger_ops;
-	adis->trig->private_data = adis;
+	iio_trigger_set_drvdata(adis->trig, adis);
 	ret = iio_trigger_register(adis->trig);
 
 	indio_dev->trig = adis->trig;
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
index 37ca05b..fe4c61e 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
@@ -544,8 +544,8 @@ static int inv_mpu6050_validate_trigger(struct iio_dev *indio_dev,
 		.type = _type,                                        \
 		.modified = 1,                                        \
 		.channel2 = _channel2,                                \
-		.info_mask =  IIO_CHAN_INFO_SCALE_SHARED_BIT          \
-				| IIO_CHAN_INFO_RAW_SEPARATE_BIT,     \
+		.info_mask_shared_by_type =  BIT(IIO_CHAN_INFO_SCALE), \
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),         \
 		.scan_index = _index,                                 \
 		.scan_type = {                                        \
 				.sign = 's',                          \
@@ -564,9 +564,9 @@ static const struct iio_chan_spec inv_mpu_channels[] = {
 	 */
 	{
 		.type = IIO_TEMP,
-		.info_mask =  IIO_CHAN_INFO_RAW_SEPARATE_BIT
-				| IIO_CHAN_INFO_OFFSET_SEPARATE_BIT
-				| IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+		.info_mask_separate =  BIT(IIO_CHAN_INFO_RAW)
+				| BIT(IIO_CHAN_INFO_OFFSET)
+				| BIT(IIO_CHAN_INFO_SCALE),
 		.scan_index = -1,
 	},
 	INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_X, INV_MPU6050_SCAN_GYRO_X),
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c
index 331781f..7da0832 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c
@@ -105,9 +105,8 @@ irqreturn_t inv_mpu6050_irq_handler(int irq, void *p)
 	s64 timestamp;
 
 	timestamp = iio_get_time_ns();
-	spin_lock(&st->time_stamp_lock);
-	kfifo_in(&st->timestamps, &timestamp, 1);
-	spin_unlock(&st->time_stamp_lock);
+	kfifo_in_spinlocked(&st->timestamps, &timestamp, 1,
+				&st->time_stamp_lock);
 
 	return IRQ_WAKE_THREAD;
 }
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
index e1d0869..03b9372 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
@@ -103,7 +103,7 @@ static int inv_mpu6050_set_enable(struct iio_dev *indio_dev, bool enable)
 static int inv_mpu_data_rdy_trigger_set_state(struct iio_trigger *trig,
 						bool state)
 {
-	return inv_mpu6050_set_enable(trig->private_data, state);
+	return inv_mpu6050_set_enable(iio_trigger_get_drvdata(trig), state);
 }
 
 static const struct iio_trigger_ops inv_mpu_trigger_ops = {
@@ -130,8 +130,8 @@ int inv_mpu6050_probe_trigger(struct iio_dev *indio_dev)
 	if (ret)
 		goto error_free_trig;
 	st->trig->dev.parent = &st->client->dev;
-	st->trig->private_data = indio_dev;
 	st->trig->ops = &inv_mpu_trigger_ops;
+	iio_trigger_set_drvdata(st->trig, indio_dev);
 	ret = iio_trigger_register(st->trig);
 	if (ret)
 		goto error_free_irq;
diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
index 8848f16..e145931 100644
--- a/drivers/iio/industrialio-core.c
+++ b/drivers/iio/industrialio-core.c
@@ -691,21 +691,34 @@ static int iio_device_add_channel_sysfs(struct iio_dev *indio_dev,
 
 	if (chan->channel < 0)
 		return 0;
-	for_each_set_bit(i, &chan->info_mask, sizeof(long)*8) {
-		ret = __iio_add_chan_devattr(iio_chan_info_postfix[i/2],
+	for_each_set_bit(i, &chan->info_mask_separate, sizeof(long)*8) {
+		ret = __iio_add_chan_devattr(iio_chan_info_postfix[i],
 					     chan,
 					     &iio_read_channel_info,
 					     &iio_write_channel_info,
-					     i/2,
-					     !(i%2),
+					     i,
+					     0,
 					     &indio_dev->dev,
 					     &indio_dev->channel_attr_list);
-		if (ret == -EBUSY && (i%2 == 0)) {
+		if (ret < 0)
+			goto error_ret;
+		attrcount++;
+	}
+	for_each_set_bit(i, &chan->info_mask_shared_by_type, sizeof(long)*8) {
+		ret = __iio_add_chan_devattr(iio_chan_info_postfix[i],
+					     chan,
+					     &iio_read_channel_info,
+					     &iio_write_channel_info,
+					     i,
+					     1,
+					     &indio_dev->dev,
+					     &indio_dev->channel_attr_list);
+		if (ret == -EBUSY) {
 			ret = 0;
 			continue;
-		}
-		if (ret < 0)
+		} else if (ret < 0) {
 			goto error_ret;
+		}
 		attrcount++;
 	}
 
@@ -847,7 +860,7 @@ static void iio_dev_release(struct device *device)
 	kfree(indio_dev);
 }
 
-static struct device_type iio_dev_type = {
+struct device_type iio_device_type = {
 	.name = "iio_device",
 	.release = iio_dev_release,
 };
@@ -869,7 +882,7 @@ struct iio_dev *iio_device_alloc(int sizeof_priv)
 
 	if (dev) {
 		dev->dev.groups = dev->groups;
-		dev->dev.type = &iio_dev_type;
+		dev->dev.type = &iio_device_type;
 		dev->dev.bus = &iio_bus_type;
 		device_initialize(&dev->dev);
 		dev_set_drvdata(&dev->dev, (void *)dev);
@@ -960,6 +973,10 @@ int iio_device_register(struct iio_dev *indio_dev)
 {
 	int ret;
 
+	/* If the calling driver did not initialize of_node, do it here */
+	if (!indio_dev->dev.of_node && indio_dev->dev.parent)
+		indio_dev->dev.of_node = indio_dev->dev.parent->of_node;
+
 	/* configure elements for the chrdev */
 	indio_dev->dev.devt = MKDEV(MAJOR(iio_devt), indio_dev->id);
 
diff --git a/drivers/iio/industrialio-event.c b/drivers/iio/industrialio-event.c
index 261cae0..10aa9ef 100644
--- a/drivers/iio/industrialio-event.c
+++ b/drivers/iio/industrialio-event.c
@@ -46,10 +46,11 @@ int iio_push_event(struct iio_dev *indio_dev, u64 ev_code, s64 timestamp)
 {
 	struct iio_event_interface *ev_int = indio_dev->event_interface;
 	struct iio_event_data ev;
+	unsigned long flags;
 	int copied;
 
 	/* Does anyone care? */
-	spin_lock(&ev_int->wait.lock);
+	spin_lock_irqsave(&ev_int->wait.lock, flags);
 	if (test_bit(IIO_BUSY_BIT_POS, &ev_int->flags)) {
 
 		ev.id = ev_code;
@@ -59,7 +60,7 @@ int iio_push_event(struct iio_dev *indio_dev, u64 ev_code, s64 timestamp)
 		if (copied != 0)
 			wake_up_locked_poll(&ev_int->wait, POLLIN);
 	}
-	spin_unlock(&ev_int->wait.lock);
+	spin_unlock_irqrestore(&ev_int->wait.lock, flags);
 
 	return 0;
 }
@@ -76,10 +77,10 @@ static unsigned int iio_event_poll(struct file *filep,
 
 	poll_wait(filep, &ev_int->wait, wait);
 
-	spin_lock(&ev_int->wait.lock);
+	spin_lock_irq(&ev_int->wait.lock);
 	if (!kfifo_is_empty(&ev_int->det_events))
 		events = POLLIN | POLLRDNORM;
-	spin_unlock(&ev_int->wait.lock);
+	spin_unlock_irq(&ev_int->wait.lock);
 
 	return events;
 }
@@ -96,14 +97,14 @@ static ssize_t iio_event_chrdev_read(struct file *filep,
 	if (count < sizeof(struct iio_event_data))
 		return -EINVAL;
 
-	spin_lock(&ev_int->wait.lock);
+	spin_lock_irq(&ev_int->wait.lock);
 	if (kfifo_is_empty(&ev_int->det_events)) {
 		if (filep->f_flags & O_NONBLOCK) {
 			ret = -EAGAIN;
 			goto error_unlock;
 		}
 		/* Blocking on device; waiting for something to be there */
-		ret = wait_event_interruptible_locked(ev_int->wait,
+		ret = wait_event_interruptible_locked_irq(ev_int->wait,
 					!kfifo_is_empty(&ev_int->det_events));
 		if (ret)
 			goto error_unlock;
@@ -113,7 +114,7 @@ static ssize_t iio_event_chrdev_read(struct file *filep,
 	ret = kfifo_to_user(&ev_int->det_events, buf, count, &copied);
 
 error_unlock:
-	spin_unlock(&ev_int->wait.lock);
+	spin_unlock_irq(&ev_int->wait.lock);
 
 	return ret ? ret : copied;
 }
@@ -122,7 +123,7 @@ static int iio_event_chrdev_release(struct inode *inode, struct file *filep)
 {
 	struct iio_event_interface *ev_int = filep->private_data;
 
-	spin_lock(&ev_int->wait.lock);
+	spin_lock_irq(&ev_int->wait.lock);
 	__clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags);
 	/*
 	 * In order to maintain a clean state for reopening,
@@ -130,7 +131,7 @@ static int iio_event_chrdev_release(struct inode *inode, struct file *filep)
 	 * any new __iio_push_event calls running.
 	 */
 	kfifo_reset_out(&ev_int->det_events);
-	spin_unlock(&ev_int->wait.lock);
+	spin_unlock_irq(&ev_int->wait.lock);
 
 	return 0;
 }
@@ -151,18 +152,18 @@ int iio_event_getfd(struct iio_dev *indio_dev)
 	if (ev_int == NULL)
 		return -ENODEV;
 
-	spin_lock(&ev_int->wait.lock);
+	spin_lock_irq(&ev_int->wait.lock);
 	if (__test_and_set_bit(IIO_BUSY_BIT_POS, &ev_int->flags)) {
-		spin_unlock(&ev_int->wait.lock);
+		spin_unlock_irq(&ev_int->wait.lock);
 		return -EBUSY;
 	}
-	spin_unlock(&ev_int->wait.lock);
+	spin_unlock_irq(&ev_int->wait.lock);
 	fd = anon_inode_getfd("iio:event",
 				&iio_event_chrdev_fileops, ev_int, O_RDONLY);
 	if (fd < 0) {
-		spin_lock(&ev_int->wait.lock);
+		spin_lock_irq(&ev_int->wait.lock);
 		__clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags);
-		spin_unlock(&ev_int->wait.lock);
+		spin_unlock_irq(&ev_int->wait.lock);
 	}
 	return fd;
 }
diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c
index b289915..795d100 100644
--- a/drivers/iio/inkern.c
+++ b/drivers/iio/inkern.c
@@ -10,6 +10,7 @@
 #include <linux/export.h>
 #include <linux/slab.h>
 #include <linux/mutex.h>
+#include <linux/of.h>
 
 #include <linux/iio/iio.h>
 #include "iio_core.h"
@@ -92,6 +93,164 @@ static const struct iio_chan_spec
 	return chan;
 }
 
+#ifdef CONFIG_OF
+
+static int iio_dev_node_match(struct device *dev, void *data)
+{
+	return dev->of_node == data && dev->type == &iio_device_type;
+}
+
+static int __of_iio_channel_get(struct iio_channel *channel,
+				struct device_node *np, int index)
+{
+	struct device *idev;
+	struct iio_dev *indio_dev;
+	int err;
+	struct of_phandle_args iiospec;
+
+	err = of_parse_phandle_with_args(np, "io-channels",
+					 "#io-channel-cells",
+					 index, &iiospec);
+	if (err)
+		return err;
+
+	idev = bus_find_device(&iio_bus_type, NULL, iiospec.np,
+			       iio_dev_node_match);
+	of_node_put(iiospec.np);
+	if (idev == NULL)
+		return -EPROBE_DEFER;
+
+	indio_dev = dev_to_iio_dev(idev);
+	channel->indio_dev = indio_dev;
+	index = iiospec.args_count ? iiospec.args[0] : 0;
+	if (index >= indio_dev->num_channels) {
+		return -EINVAL;
+		goto err_put;
+	}
+	channel->channel = &indio_dev->channels[index];
+
+	return 0;
+
+err_put:
+	iio_device_put(indio_dev);
+	return err;
+}
+
+static struct iio_channel *of_iio_channel_get(struct device_node *np, int index)
+{
+	struct iio_channel *channel;
+	int err;
+
+	if (index < 0)
+		return ERR_PTR(-EINVAL);
+
+	channel = kzalloc(sizeof(*channel), GFP_KERNEL);
+	if (channel == NULL)
+		return ERR_PTR(-ENOMEM);
+
+	err = __of_iio_channel_get(channel, np, index);
+	if (err)
+		goto err_free_channel;
+
+	return channel;
+
+err_free_channel:
+	kfree(channel);
+	return ERR_PTR(err);
+}
+
+static struct iio_channel *of_iio_channel_get_by_name(struct device_node *np,
+						      const char *name)
+{
+	struct iio_channel *chan = NULL;
+
+	/* Walk up the tree of devices looking for a matching iio channel */
+	while (np) {
+		int index = 0;
+
+		/*
+		 * For named iio channels, first look up the name in the
+		 * "io-channel-names" property.  If it cannot be found, the
+		 * index will be an error code, and of_iio_channel_get()
+		 * will fail.
+		 */
+		if (name)
+			index = of_property_match_string(np, "io-channel-names",
+							 name);
+		chan = of_iio_channel_get(np, index);
+		if (!IS_ERR(chan))
+			break;
+		else if (name && index >= 0) {
+			pr_err("ERROR: could not get IIO channel %s:%s(%i)\n",
+				np->full_name, name ? name : "", index);
+			return chan;
+		}
+
+		/*
+		 * No matching IIO channel found on this node.
+		 * If the parent node has a "io-channel-ranges" property,
+		 * then we can try one of its channels.
+		 */
+		np = np->parent;
+		if (np && !of_get_property(np, "io-channel-ranges", NULL))
+			break;
+	}
+	return chan;
+}
+
+static struct iio_channel *of_iio_channel_get_all(struct device *dev)
+{
+	struct iio_channel *chans;
+	int i, mapind, nummaps = 0;
+	int ret;
+
+	do {
+		ret = of_parse_phandle_with_args(dev->of_node,
+						 "io-channels",
+						 "#io-channel-cells",
+						 nummaps, NULL);
+		if (ret < 0)
+			break;
+	} while (++nummaps);
+
+	if (nummaps == 0)	/* no error, return NULL to search map table */
+		return NULL;
+
+	/* NULL terminated array to save passing size */
+	chans = kcalloc(nummaps + 1, sizeof(*chans), GFP_KERNEL);
+	if (chans == NULL)
+		return ERR_PTR(-ENOMEM);
+
+	/* Search for OF matches */
+	for (mapind = 0; mapind < nummaps; mapind++) {
+		ret = __of_iio_channel_get(&chans[mapind], dev->of_node,
+					   mapind);
+		if (ret)
+			goto error_free_chans;
+	}
+	return chans;
+
+error_free_chans:
+	for (i = 0; i < mapind; i++)
+		iio_device_put(chans[i].indio_dev);
+	kfree(chans);
+	return ERR_PTR(ret);
+}
+
+#else /* CONFIG_OF */
+
+static inline struct iio_channel *
+of_iio_channel_get_by_name(struct device_node *np, const char *name)
+{
+	return NULL;
+}
+
+static inline struct iio_channel *of_iio_channel_get_all(struct device *dev)
+{
+	return NULL;
+}
+
+#endif /* CONFIG_OF */
 
 static struct iio_channel *iio_channel_get_sys(const char *name,
 					       const char *channel_name)
@@ -150,7 +309,14 @@ struct iio_channel *iio_channel_get(struct device *dev,
 				    const char *channel_name)
 {
 	const char *name = dev ? dev_name(dev) : NULL;
+	struct iio_channel *channel;
 
+	if (dev) {
+		channel = of_iio_channel_get_by_name(dev->of_node,
+						     channel_name);
+		if (channel != NULL)
+			return channel;
+	}
 	return iio_channel_get_sys(name, channel_name);
 }
 EXPORT_SYMBOL_GPL(iio_channel_get);
@@ -173,6 +339,11 @@ struct iio_channel *iio_channel_get_all(struct device *dev)
 
 	if (dev == NULL)
 		return ERR_PTR(-EINVAL);
+
+	chans = of_iio_channel_get_all(dev);
+	if (chans)
+		return chans;
+
 	name = dev_name(dev);
 
 	mutex_lock(&iio_map_list_lock);
diff --git a/drivers/iio/light/adjd_s311.c b/drivers/iio/light/adjd_s311.c
index d5b9d39..5f4749e 100644
--- a/drivers/iio/light/adjd_s311.c
+++ b/drivers/iio/light/adjd_s311.c
@@ -207,8 +207,8 @@ static const struct iio_chan_spec_ext_info adjd_s311_ext_info[] = {
 	.type = IIO_INTENSITY, \
 	.modified = 1, \
 	.address = (IDX_##_color), \
-	.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
-		IIO_CHAN_INFO_HARDWAREGAIN_SEPARATE_BIT, \
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+		BIT(IIO_CHAN_INFO_HARDWAREGAIN), \
 	.channel2 = (IIO_MOD_LIGHT_##_color), \
 	.scan_index = (_scan_idx), \
 	.scan_type = IIO_ST('u', 10, 16, 0), \
diff --git a/drivers/iio/light/hid-sensor-als.c b/drivers/iio/light/hid-sensor-als.c
index 3d7e8c9..80d68ff 100644
--- a/drivers/iio/light/hid-sensor-als.c
+++ b/drivers/iio/light/hid-sensor-als.c
@@ -49,10 +49,10 @@ static const struct iio_chan_spec als_channels[] = {
 		.type = IIO_INTENSITY,
 		.modified = 1,
 		.channel2 = IIO_MOD_LIGHT_BOTH,
-		.info_mask = IIO_CHAN_INFO_OFFSET_SHARED_BIT |
-		IIO_CHAN_INFO_SCALE_SHARED_BIT |
-		IIO_CHAN_INFO_SAMP_FREQ_SHARED_BIT |
-		IIO_CHAN_INFO_HYSTERESIS_SHARED_BIT,
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
+		BIT(IIO_CHAN_INFO_SCALE) |
+		BIT(IIO_CHAN_INFO_SAMP_FREQ) |
+		BIT(IIO_CHAN_INFO_HYSTERESIS),
 		.scan_index = CHANNEL_SCAN_INDEX_ILLUM,
 	}
 };
diff --git a/drivers/iio/light/lm3533-als.c b/drivers/iio/light/lm3533-als.c
index 7503012..5fa31a4 100644
--- a/drivers/iio/light/lm3533-als.c
+++ b/drivers/iio/light/lm3533-als.c
@@ -231,7 +231,7 @@ static int lm3533_als_read_raw(struct iio_dev *indio_dev,
 		.channel	= _channel,				\
 		.indexed	= true,					\
 		.output		= true,					\
-		.info_mask	= IIO_CHAN_INFO_RAW_SEPARATE_BIT,	\
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\
 	}
 
 static const struct iio_chan_spec lm3533_als_channels[] = {
@@ -239,8 +239,8 @@ static const struct iio_chan_spec lm3533_als_channels[] = {
 		.type		= IIO_LIGHT,
 		.channel	= 0,
 		.indexed	= true,
-		.info_mask	= (IIO_CHAN_INFO_AVERAGE_RAW_SEPARATE_BIT |
-				   IIO_CHAN_INFO_RAW_SEPARATE_BIT),
+		.info_mask_separate = BIT(IIO_CHAN_INFO_AVERAGE_RAW) |
+				   BIT(IIO_CHAN_INFO_RAW),
 	},
 	CHANNEL_CURRENT(0),
 	CHANNEL_CURRENT(1),
diff --git a/drivers/iio/light/tsl2563.c b/drivers/iio/light/tsl2563.c
index fd8be69..1f529f3 100644
--- a/drivers/iio/light/tsl2563.c
+++ b/drivers/iio/light/tsl2563.c
@@ -530,14 +530,14 @@ static const struct iio_chan_spec tsl2563_channels[] = {
 	{
 		.type = IIO_LIGHT,
 		.indexed = 1,
-		.info_mask = IIO_CHAN_INFO_PROCESSED_SEPARATE_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
 		.channel = 0,
 	}, {
 		.type = IIO_INTENSITY,
 		.modified = 1,
 		.channel2 = IIO_MOD_LIGHT_BOTH,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-		IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+		BIT(IIO_CHAN_INFO_CALIBSCALE),
 		.event_mask = (IIO_EV_BIT(IIO_EV_TYPE_THRESH,
 					  IIO_EV_DIR_RISING) |
 			       IIO_EV_BIT(IIO_EV_TYPE_THRESH,
@@ -546,8 +546,8 @@ static const struct iio_chan_spec tsl2563_channels[] = {
 		.type = IIO_INTENSITY,
 		.modified = 1,
 		.channel2 = IIO_MOD_LIGHT_IR,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-		IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+		BIT(IIO_CHAN_INFO_CALIBSCALE),
 	}
 };
 
diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c
index 2aa748f..1014943 100644
--- a/drivers/iio/light/vcnl4000.c
+++ b/drivers/iio/light/vcnl4000.c
@@ -93,11 +93,11 @@ static int vcnl4000_measure(struct vcnl4000_data *data, u8 req_mask,
 static const struct iio_chan_spec vcnl4000_channels[] = {
 	{
 		.type = IIO_LIGHT,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-			IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+			BIT(IIO_CHAN_INFO_SCALE),
 	}, {
 		.type = IIO_PROXIMITY,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
 	}
 };
 
diff --git a/drivers/iio/magnetometer/Kconfig b/drivers/iio/magnetometer/Kconfig
index cd29be5..bd1cfb6 100644
--- a/drivers/iio/magnetometer/Kconfig
+++ b/drivers/iio/magnetometer/Kconfig
@@ -3,6 +3,17 @@
 #
 menu "Magnetometer sensors"
 
+config AK8975
+	tristate "Asahi Kasei AK8975 3-Axis Magnetometer"
+	depends on I2C
+	depends on GPIOLIB
+	help
+	  Say yes here to build support for Asahi Kasei AK8975 3-Axis
+	  Magnetometer.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called ak8975.
+
 config HID_SENSOR_MAGNETOMETER_3D
 	depends on HID_SENSOR_HUB
 	select IIO_BUFFER
diff --git a/drivers/iio/magnetometer/Makefile b/drivers/iio/magnetometer/Makefile
index e786728..7f328e3 100644
--- a/drivers/iio/magnetometer/Makefile
+++ b/drivers/iio/magnetometer/Makefile
@@ -2,6 +2,7 @@
 # Makefile for industrial I/O Magnetometer sensor drivers
 #
 
+obj-$(CONFIG_AK8975)	+= ak8975.o
 obj-$(CONFIG_HID_SENSOR_MAGNETOMETER_3D) += hid-sensor-magn-3d.o
 
 obj-$(CONFIG_IIO_ST_MAGN_3AXIS) += st_magn.o
diff --git a/drivers/iio/magnetometer/ak8975.c b/drivers/iio/magnetometer/ak8975.c
new file mode 100644
index 0000000..af6c320
--- /dev/null
+++ b/drivers/iio/magnetometer/ak8975.c
@@ -0,0 +1,485 @@
+/*
+ * A sensor driver for the magnetometer AK8975.
+ *
+ * Magnetic compass sensor driver for monitoring magnetic flux information.
+ *
+ * Copyright (c) 2010, NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA	02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+
+#include <linux/gpio.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+/*
+ * Register definitions, as well as various shifts and masks to get at the
+ * individual fields of the registers.
+ */
+#define AK8975_REG_WIA			0x00
+#define AK8975_DEVICE_ID		0x48
+
+#define AK8975_REG_INFO			0x01
+
+#define AK8975_REG_ST1			0x02
+#define AK8975_REG_ST1_DRDY_SHIFT	0
+#define AK8975_REG_ST1_DRDY_MASK	(1 << AK8975_REG_ST1_DRDY_SHIFT)
+
+#define AK8975_REG_HXL			0x03
+#define AK8975_REG_HXH			0x04
+#define AK8975_REG_HYL			0x05
+#define AK8975_REG_HYH			0x06
+#define AK8975_REG_HZL			0x07
+#define AK8975_REG_HZH			0x08
+#define AK8975_REG_ST2			0x09
+#define AK8975_REG_ST2_DERR_SHIFT	2
+#define AK8975_REG_ST2_DERR_MASK	(1 << AK8975_REG_ST2_DERR_SHIFT)
+
+#define AK8975_REG_ST2_HOFL_SHIFT	3
+#define AK8975_REG_ST2_HOFL_MASK	(1 << AK8975_REG_ST2_HOFL_SHIFT)
+
+#define AK8975_REG_CNTL			0x0A
+#define AK8975_REG_CNTL_MODE_SHIFT	0
+#define AK8975_REG_CNTL_MODE_MASK	(0xF << AK8975_REG_CNTL_MODE_SHIFT)
+#define AK8975_REG_CNTL_MODE_POWER_DOWN	0
+#define AK8975_REG_CNTL_MODE_ONCE	1
+#define AK8975_REG_CNTL_MODE_SELF_TEST	8
+#define AK8975_REG_CNTL_MODE_FUSE_ROM	0xF
+
+#define AK8975_REG_RSVC			0x0B
+#define AK8975_REG_ASTC			0x0C
+#define AK8975_REG_TS1			0x0D
+#define AK8975_REG_TS2			0x0E
+#define AK8975_REG_I2CDIS		0x0F
+#define AK8975_REG_ASAX			0x10
+#define AK8975_REG_ASAY			0x11
+#define AK8975_REG_ASAZ			0x12
+
+#define AK8975_MAX_REGS			AK8975_REG_ASAZ
+
+/*
+ * Miscellaneous values.
+ */
+#define AK8975_MAX_CONVERSION_TIMEOUT	500
+#define AK8975_CONVERSION_DONE_POLL_TIME 10
+
+/*
+ * Per-instance context data for the device.
+ */
+struct ak8975_data {
+	struct i2c_client	*client;
+	struct attribute_group	attrs;
+	struct mutex		lock;
+	u8			asa[3];
+	long			raw_to_gauss[3];
+	u8			reg_cache[AK8975_MAX_REGS];
+	int			eoc_gpio;
+};
+
+static const int ak8975_index_to_reg[] = {
+	AK8975_REG_HXL, AK8975_REG_HYL, AK8975_REG_HZL,
+};
+
+/*
+ * Helper function to write to the I2C device's registers.
+ */
+static int ak8975_write_data(struct i2c_client *client,
+			     u8 reg, u8 val, u8 mask, u8 shift)
+{
+	struct iio_dev *indio_dev = i2c_get_clientdata(client);
+	struct ak8975_data *data = iio_priv(indio_dev);
+	u8 regval;
+	int ret;
+
+	regval = (data->reg_cache[reg] & ~mask) | (val << shift);
+	ret = i2c_smbus_write_byte_data(client, reg, regval);
+	if (ret < 0) {
+		dev_err(&client->dev, "Write to device fails status %x\n", ret);
+		return ret;
+	}
+	data->reg_cache[reg] = regval;
+
+	return 0;
+}
+
+/*
+ * Perform some start-of-day setup, including reading the asa calibration
+ * values and caching them.
+ */
+static int ak8975_setup(struct i2c_client *client)
+{
+	struct iio_dev *indio_dev = i2c_get_clientdata(client);
+	struct ak8975_data *data = iio_priv(indio_dev);
+	u8 device_id;
+	int ret;
+
+	/* Confirm that the device we're talking to is really an AK8975. */
+	ret = i2c_smbus_read_byte_data(client, AK8975_REG_WIA);
+	if (ret < 0) {
+		dev_err(&client->dev, "Error reading WIA\n");
+		return ret;
+	}
+	device_id = ret;
+	if (device_id != AK8975_DEVICE_ID) {
+		dev_err(&client->dev, "Device ak8975 not found\n");
+		return -ENODEV;
+	}
+
+	/* Write the fused rom access mode. */
+	ret = ak8975_write_data(client,
+				AK8975_REG_CNTL,
+				AK8975_REG_CNTL_MODE_FUSE_ROM,
+				AK8975_REG_CNTL_MODE_MASK,
+				AK8975_REG_CNTL_MODE_SHIFT);
+	if (ret < 0) {
+		dev_err(&client->dev, "Error in setting fuse access mode\n");
+		return ret;
+	}
+
+	/* Get asa data and store in the device data. */
+	ret = i2c_smbus_read_i2c_block_data(client, AK8975_REG_ASAX,
+					    3, data->asa);
+	if (ret < 0) {
+		dev_err(&client->dev, "Not able to read asa data\n");
+		return ret;
+	}
+
+	/* After reading fuse ROM data set power-down mode */
+	ret = ak8975_write_data(client,
+				AK8975_REG_CNTL,
+				AK8975_REG_CNTL_MODE_POWER_DOWN,
+				AK8975_REG_CNTL_MODE_MASK,
+				AK8975_REG_CNTL_MODE_SHIFT);
+	if (ret < 0) {
+		dev_err(&client->dev, "Error in setting power-down mode\n");
+		return ret;
+	}
+
+/*
+ * Precalculate scale factor (in Gauss units) for each axis and
+ * store in the device data.
+ *
+ * This scale factor is axis-dependent, and is derived from 3 calibration
+ * factors ASA(x), ASA(y), and ASA(z).
+ *
+ * These ASA values are read from the sensor device at start of day, and
+ * cached in the device context struct.
+ *
+ * Adjusting the flux value with the sensitivity adjustment value should be
+ * done via the following formula:
+ *
+ * Hadj = H * ( ( ( (ASA-128)*0.5 ) / 128 ) + 1 )
+ *
+ * where H is the raw value, ASA is the sensitivity adjustment, and Hadj
+ * is the resultant adjusted value.
+ *
+ * We reduce the formula to:
+ *
+ * Hadj = H * (ASA + 128) / 256
+ *
+ * H is in the range of -4096 to 4095.  The magnetometer has a range of
+ * +-1229uT.  To go from the raw value to uT is:
+ *
+ * HuT = H * 1229/4096, or roughly, 3/10.
+ *
+ * Since 1uT = 100 gauss, our final scale factor becomes:
+ *
+ * Hadj = H * ((ASA + 128) / 256) * 3/10 * 100
+ * Hadj = H * ((ASA + 128) * 30 / 256
+ *
+ * Since ASA doesn't change, we cache the resultant scale factor into the
+ * device context in ak8975_setup().
+ */
+	data->raw_to_gauss[0] = ((data->asa[0] + 128) * 30) >> 8;
+	data->raw_to_gauss[1] = ((data->asa[1] + 128) * 30) >> 8;
+	data->raw_to_gauss[2] = ((data->asa[2] + 128) * 30) >> 8;
+
+	return 0;
+}
+
+static int wait_conversion_complete_gpio(struct ak8975_data *data)
+{
+	struct i2c_client *client = data->client;
+	u32 timeout_ms = AK8975_MAX_CONVERSION_TIMEOUT;
+	int ret;
+
+	/* Wait for the conversion to complete. */
+	while (timeout_ms) {
+		msleep(AK8975_CONVERSION_DONE_POLL_TIME);
+		if (gpio_get_value(data->eoc_gpio))
+			break;
+		timeout_ms -= AK8975_CONVERSION_DONE_POLL_TIME;
+	}
+	if (!timeout_ms) {
+		dev_err(&client->dev, "Conversion timeout happened\n");
+		return -EINVAL;
+	}
+
+	ret = i2c_smbus_read_byte_data(client, AK8975_REG_ST1);
+	if (ret < 0)
+		dev_err(&client->dev, "Error in reading ST1\n");
+
+	return ret;
+}
+
+static int wait_conversion_complete_polled(struct ak8975_data *data)
+{
+	struct i2c_client *client = data->client;
+	u8 read_status;
+	u32 timeout_ms = AK8975_MAX_CONVERSION_TIMEOUT;
+	int ret;
+
+	/* Wait for the conversion to complete. */
+	while (timeout_ms) {
+		msleep(AK8975_CONVERSION_DONE_POLL_TIME);
+		ret = i2c_smbus_read_byte_data(client, AK8975_REG_ST1);
+		if (ret < 0) {
+			dev_err(&client->dev, "Error in reading ST1\n");
+			return ret;
+		}
+		read_status = ret;
+		if (read_status)
+			break;
+		timeout_ms -= AK8975_CONVERSION_DONE_POLL_TIME;
+	}
+	if (!timeout_ms) {
+		dev_err(&client->dev, "Conversion timeout happened\n");
+		return -EINVAL;
+	}
+	return read_status;
+}
+
+/*
+ * Emits the raw flux value for the x, y, or z axis.
+ */
+static int ak8975_read_axis(struct iio_dev *indio_dev, int index, int *val)
+{
+	struct ak8975_data *data = iio_priv(indio_dev);
+	struct i2c_client *client = data->client;
+	u16 meas_reg;
+	s16 raw;
+	int ret;
+
+	mutex_lock(&data->lock);
+
+	/* Set up the device for taking a sample. */
+	ret = ak8975_write_data(client,
+				AK8975_REG_CNTL,
+				AK8975_REG_CNTL_MODE_ONCE,
+				AK8975_REG_CNTL_MODE_MASK,
+				AK8975_REG_CNTL_MODE_SHIFT);
+	if (ret < 0) {
+		dev_err(&client->dev, "Error in setting operating mode\n");
+		goto exit;
+	}
+
+	/* Wait for the conversion to complete. */
+	if (gpio_is_valid(data->eoc_gpio))
+		ret = wait_conversion_complete_gpio(data);
+	else
+		ret = wait_conversion_complete_polled(data);
+	if (ret < 0)
+		goto exit;
+
+	if (ret & AK8975_REG_ST1_DRDY_MASK) {
+		ret = i2c_smbus_read_byte_data(client, AK8975_REG_ST2);
+		if (ret < 0) {
+			dev_err(&client->dev, "Error in reading ST2\n");
+			goto exit;
+		}
+		if (ret & (AK8975_REG_ST2_DERR_MASK |
+			   AK8975_REG_ST2_HOFL_MASK)) {
+			dev_err(&client->dev, "ST2 status error 0x%x\n", ret);
+			ret = -EINVAL;
+			goto exit;
+		}
+	}
+
+	/* Read the flux value from the appropriate register
+	   (the register is specified in the iio device attributes). */
+	ret = i2c_smbus_read_word_data(client, ak8975_index_to_reg[index]);
+	if (ret < 0) {
+		dev_err(&client->dev, "Read axis data fails\n");
+		goto exit;
+	}
+	meas_reg = ret;
+
+	mutex_unlock(&data->lock);
+
+	/* Endian conversion of the measured values. */
+	raw = (s16) (le16_to_cpu(meas_reg));
+
+	/* Clamp to valid range. */
+	raw = clamp_t(s16, raw, -4096, 4095);
+	*val = raw;
+	return IIO_VAL_INT;
+
+exit:
+	mutex_unlock(&data->lock);
+	return ret;
+}
+
+static int ak8975_read_raw(struct iio_dev *indio_dev,
+			   struct iio_chan_spec const *chan,
+			   int *val, int *val2,
+			   long mask)
+{
+	struct ak8975_data *data = iio_priv(indio_dev);
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		return ak8975_read_axis(indio_dev, chan->address, val);
+	case IIO_CHAN_INFO_SCALE:
+		*val = data->raw_to_gauss[chan->address];
+		return IIO_VAL_INT;
+	}
+	return -EINVAL;
+}
+
+#define AK8975_CHANNEL(axis, index)					\
+	{								\
+		.type = IIO_MAGN,					\
+		.modified = 1,						\
+		.channel2 = IIO_MOD_##axis,				\
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |		\
+			     BIT(IIO_CHAN_INFO_SCALE),			\
+		.address = index,					\
+	}
+
+static const struct iio_chan_spec ak8975_channels[] = {
+	AK8975_CHANNEL(X, 0), AK8975_CHANNEL(Y, 1), AK8975_CHANNEL(Z, 2),
+};
+
+static const struct iio_info ak8975_info = {
+	.read_raw = &ak8975_read_raw,
+	.driver_module = THIS_MODULE,
+};
+
+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;
+
+	/* Grab and set up the supplied GPIO. */
+	if (client->dev.platform_data == NULL)
+		eoc_gpio = -1;
+	else
+		eoc_gpio = *(int *)(client->dev.platform_data);
+
+	/* We may not have a GPIO based IRQ to scan, that is fine, we will
+	   poll if so */
+	if (gpio_is_valid(eoc_gpio)) {
+		err = gpio_request_one(eoc_gpio, GPIOF_IN, "ak_8975");
+		if (err < 0) {
+			dev_err(&client->dev,
+				"failed to request GPIO %d, error %d\n",
+							eoc_gpio, err);
+			goto exit;
+		}
+	}
+
+	/* Register with IIO */
+	indio_dev = iio_device_alloc(sizeof(*data));
+	if (indio_dev == NULL) {
+		err = -ENOMEM;
+		goto exit_gpio;
+	}
+	data = iio_priv(indio_dev);
+	i2c_set_clientdata(client, indio_dev);
+	/* Perform some basic start-of-day setup of the device. */
+	err = ak8975_setup(client);
+	if (err < 0) {
+		dev_err(&client->dev, "AK8975 initialization fails\n");
+		goto exit_free_iio;
+	}
+
+	data->client = client;
+	mutex_init(&data->lock);
+	data->eoc_gpio = eoc_gpio;
+	indio_dev->dev.parent = &client->dev;
+	indio_dev->channels = ak8975_channels;
+	indio_dev->num_channels = ARRAY_SIZE(ak8975_channels);
+	indio_dev->info = &ak8975_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+
+	err = iio_device_register(indio_dev);
+	if (err < 0)
+		goto exit_free_iio;
+
+	return 0;
+
+exit_free_iio:
+	iio_device_free(indio_dev);
+exit_gpio:
+	if (gpio_is_valid(eoc_gpio))
+		gpio_free(eoc_gpio);
+exit:
+	return err;
+}
+
+static int ak8975_remove(struct i2c_client *client)
+{
+	struct iio_dev *indio_dev = i2c_get_clientdata(client);
+	struct ak8975_data *data = iio_priv(indio_dev);
+
+	iio_device_unregister(indio_dev);
+
+	if (gpio_is_valid(data->eoc_gpio))
+		gpio_free(data->eoc_gpio);
+
+	iio_device_free(indio_dev);
+
+	return 0;
+}
+
+static const struct i2c_device_id ak8975_id[] = {
+	{"ak8975", 0},
+	{}
+};
+
+MODULE_DEVICE_TABLE(i2c, ak8975_id);
+
+static const struct of_device_id ak8975_of_match[] = {
+	{ .compatible = "asahi-kasei,ak8975", },
+	{ .compatible = "ak8975", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, ak8975_of_match);
+
+static struct i2c_driver ak8975_driver = {
+	.driver = {
+		.name	= "ak8975",
+		.of_match_table = ak8975_of_match,
+	},
+	.probe		= ak8975_probe,
+	.remove		= ak8975_remove,
+	.id_table	= ak8975_id,
+};
+module_i2c_driver(ak8975_driver);
+
+MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
+MODULE_DESCRIPTION("AK8975 magnetometer driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/magnetometer/hid-sensor-magn-3d.c b/drivers/iio/magnetometer/hid-sensor-magn-3d.c
index d8d0126..99f4e49 100644
--- a/drivers/iio/magnetometer/hid-sensor-magn-3d.c
+++ b/drivers/iio/magnetometer/hid-sensor-magn-3d.c
@@ -60,28 +60,28 @@ static const struct iio_chan_spec magn_3d_channels[] = {
 		.type = IIO_MAGN,
 		.modified = 1,
 		.channel2 = IIO_MOD_X,
-		.info_mask = IIO_CHAN_INFO_OFFSET_SHARED_BIT |
-		IIO_CHAN_INFO_SCALE_SHARED_BIT |
-		IIO_CHAN_INFO_SAMP_FREQ_SHARED_BIT |
-		IIO_CHAN_INFO_HYSTERESIS_SHARED_BIT,
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
+		BIT(IIO_CHAN_INFO_SCALE) |
+		BIT(IIO_CHAN_INFO_SAMP_FREQ) |
+		BIT(IIO_CHAN_INFO_HYSTERESIS),
 		.scan_index = CHANNEL_SCAN_INDEX_X,
 	}, {
 		.type = IIO_MAGN,
 		.modified = 1,
 		.channel2 = IIO_MOD_Y,
-		.info_mask = IIO_CHAN_INFO_OFFSET_SHARED_BIT |
-		IIO_CHAN_INFO_SCALE_SHARED_BIT |
-		IIO_CHAN_INFO_SAMP_FREQ_SHARED_BIT |
-		IIO_CHAN_INFO_HYSTERESIS_SHARED_BIT,
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
+		BIT(IIO_CHAN_INFO_SCALE) |
+		BIT(IIO_CHAN_INFO_SAMP_FREQ) |
+		BIT(IIO_CHAN_INFO_HYSTERESIS),
 		.scan_index = CHANNEL_SCAN_INDEX_Y,
 	}, {
 		.type = IIO_MAGN,
 		.modified = 1,
 		.channel2 = IIO_MOD_Z,
-		.info_mask = IIO_CHAN_INFO_OFFSET_SHARED_BIT |
-		IIO_CHAN_INFO_SCALE_SHARED_BIT |
-		IIO_CHAN_INFO_SAMP_FREQ_SHARED_BIT |
-		IIO_CHAN_INFO_HYSTERESIS_SHARED_BIT,
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
+		BIT(IIO_CHAN_INFO_SCALE) |
+		BIT(IIO_CHAN_INFO_SAMP_FREQ) |
+		BIT(IIO_CHAN_INFO_HYSTERESIS),
 		.scan_index = CHANNEL_SCAN_INDEX_Z,
 	}
 };
diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c
index a841123..5dee86d 100644
--- a/drivers/infiniband/core/umem.c
+++ b/drivers/infiniband/core/umem.c
@@ -89,6 +89,7 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
 	int ret;
 	int off;
 	int i;
+	bool gift, writable;
 	DEFINE_DMA_ATTRS(attrs);
 
 	if (dmasync)
@@ -96,6 +97,15 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
 
 	if (!can_do_mlock())
 		return ERR_PTR(-EPERM);
+	/*
+	 * We ask for writable memory if any access flags other than
+	 * "remote read" or "gift" are set.  "Local write" and "remote write"
+	 * obviously require write access.  "Remote atomic" can do
+	 * things like fetch and add, which will modify memory, and
+	 * "MW bind" can change permissions by binding a window.
+	 */
+	gift  = access & IB_ACCESS_GIFT;
+	writable = access & ~(IB_ACCESS_REMOTE_READ | IB_ACCESS_GIFT);
 
 	umem = kmalloc(sizeof *umem, GFP_KERNEL);
 	if (!umem)
@@ -105,14 +115,7 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
 	umem->length    = size;
 	umem->offset    = addr & ~PAGE_MASK;
 	umem->page_size = PAGE_SIZE;
-	/*
-	 * We ask for writable memory if any access flags other than
-	 * "remote read" are set.  "Local write" and "remote write"
-	 * obviously require write access.  "Remote atomic" can do
-	 * things like fetch and add, which will modify memory, and
-	 * "MW bind" can change permissions by binding a window.
-	 */
-	umem->writable  = !!(access & ~IB_ACCESS_REMOTE_READ);
+	umem->writable  = writable;
 
 	/* We assume the memory is from hugetlb until proved otherwise */
 	umem->hugetlb   = 1;
@@ -152,7 +155,7 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
 		ret = get_user_pages(current, current->mm, cur_base,
 				     min_t(unsigned long, npages,
 					   PAGE_SIZE / sizeof (struct page *)),
-				     1, !umem->writable, page_list, vma_list);
+				     !gift, !umem->writable, page_list, vma_list);
 
 		if (ret < 0)
 			goto out;
diff --git a/drivers/infiniband/hw/cxgb3/cxio_resource.c b/drivers/infiniband/hw/cxgb3/cxio_resource.c
index 31f9201..c40088e 100644
--- a/drivers/infiniband/hw/cxgb3/cxio_resource.c
+++ b/drivers/infiniband/hw/cxgb3/cxio_resource.c
@@ -62,13 +62,13 @@ static int __cxio_init_resource_fifo(struct kfifo *fifo,
 		kfifo_in(fifo, (unsigned char *) &entry, sizeof(u32));
 	if (random) {
 		j = 0;
-		random_bytes = random32();
+		random_bytes = prandom_u32();
 		for (i = 0; i < RANDOM_SIZE; i++)
 			rarray[i] = i + skip_low;
 		for (i = skip_low + RANDOM_SIZE; i < nr - skip_high; i++) {
 			if (j >= RANDOM_SIZE) {
 				j = 0;
-				random_bytes = random32();
+				random_bytes = prandom_u32();
 			}
 			idx = (random_bytes >> (j * 2)) & 0xF;
 			kfifo_in(fifo,
diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c
index a3fde52..65c30ea 100644
--- a/drivers/infiniband/hw/cxgb4/cm.c
+++ b/drivers/infiniband/hw/cxgb4/cm.c
@@ -511,12 +511,16 @@ static unsigned int select_ntuple(struct c4iw_dev *dev, struct dst_entry *dst,
 static int send_connect(struct c4iw_ep *ep)
 {
 	struct cpl_act_open_req *req;
+	struct cpl_t5_act_open_req *t5_req;
 	struct sk_buff *skb;
 	u64 opt0;
 	u32 opt2;
 	unsigned int mtu_idx;
 	int wscale;
-	int wrlen = roundup(sizeof *req, 16);
+	int size = is_t4(ep->com.dev->rdev.lldi.adapter_type) ?
+		sizeof(struct cpl_act_open_req) :
+		sizeof(struct cpl_t5_act_open_req);
+	int wrlen = roundup(size, 16);
 
 	PDBG("%s ep %p atid %u\n", __func__, ep, ep->atid);
 
@@ -552,17 +556,36 @@ static int send_connect(struct c4iw_ep *ep)
 		opt2 |= WND_SCALE_EN(1);
 	t4_set_arp_err_handler(skb, NULL, act_open_req_arp_failure);
 
-	req = (struct cpl_act_open_req *) skb_put(skb, wrlen);
-	INIT_TP_WR(req, 0);
-	OPCODE_TID(req) = cpu_to_be32(
-		MK_OPCODE_TID(CPL_ACT_OPEN_REQ, ((ep->rss_qid<<14)|ep->atid)));
-	req->local_port = ep->com.local_addr.sin_port;
-	req->peer_port = ep->com.remote_addr.sin_port;
-	req->local_ip = ep->com.local_addr.sin_addr.s_addr;
-	req->peer_ip = ep->com.remote_addr.sin_addr.s_addr;
-	req->opt0 = cpu_to_be64(opt0);
-	req->params = cpu_to_be32(select_ntuple(ep->com.dev, ep->dst, ep->l2t));
-	req->opt2 = cpu_to_be32(opt2);
+	if (is_t4(ep->com.dev->rdev.lldi.adapter_type)) {
+		req = (struct cpl_act_open_req *) skb_put(skb, wrlen);
+		INIT_TP_WR(req, 0);
+		OPCODE_TID(req) = cpu_to_be32(
+				MK_OPCODE_TID(CPL_ACT_OPEN_REQ,
+				((ep->rss_qid << 14) | ep->atid)));
+		req->local_port = ep->com.local_addr.sin_port;
+		req->peer_port = ep->com.remote_addr.sin_port;
+		req->local_ip = ep->com.local_addr.sin_addr.s_addr;
+		req->peer_ip = ep->com.remote_addr.sin_addr.s_addr;
+		req->opt0 = cpu_to_be64(opt0);
+		req->params = cpu_to_be32(select_ntuple(ep->com.dev,
+					ep->dst, ep->l2t));
+		req->opt2 = cpu_to_be32(opt2);
+	} else {
+		t5_req = (struct cpl_t5_act_open_req *) skb_put(skb, wrlen);
+		INIT_TP_WR(t5_req, 0);
+		OPCODE_TID(t5_req) = cpu_to_be32(
+					MK_OPCODE_TID(CPL_ACT_OPEN_REQ,
+					((ep->rss_qid << 14) | ep->atid)));
+		t5_req->local_port = ep->com.local_addr.sin_port;
+		t5_req->peer_port = ep->com.remote_addr.sin_port;
+		t5_req->local_ip = ep->com.local_addr.sin_addr.s_addr;
+		t5_req->peer_ip = ep->com.remote_addr.sin_addr.s_addr;
+		t5_req->opt0 = cpu_to_be64(opt0);
+		t5_req->params = cpu_to_be64(V_FILTER_TUPLE(
+				select_ntuple(ep->com.dev, ep->dst, ep->l2t)));
+		t5_req->opt2 = cpu_to_be32(opt2);
+	}
+
 	set_bit(ACT_OPEN_REQ, &ep->com.history);
 	return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t);
 }
@@ -1676,9 +1699,9 @@ static int act_open_rpl(struct c4iw_dev *dev, struct sk_buff *skb)
 	case CPL_ERR_CONN_TIMEDOUT:
 		break;
 	case CPL_ERR_TCAM_FULL:
+		dev->rdev.stats.tcam_full++;
 		if (dev->rdev.lldi.enable_fw_ofld_conn) {
 			mutex_lock(&dev->rdev.stats.lock);
-			dev->rdev.stats.tcam_full++;
 			mutex_unlock(&dev->rdev.stats.lock);
 			send_fw_act_open_req(ep,
 					     GET_TID_TID(GET_AOPEN_ATID(
@@ -2875,12 +2898,14 @@ static int deferred_fw6_msg(struct c4iw_dev *dev, struct sk_buff *skb)
 static void build_cpl_pass_accept_req(struct sk_buff *skb, int stid , u8 tos)
 {
 	u32 l2info;
-	u16 vlantag, len, hdr_len;
+	u16 vlantag, len, hdr_len, eth_hdr_len;
 	u8 intf;
 	struct cpl_rx_pkt *cpl = cplhdr(skb);
 	struct cpl_pass_accept_req *req;
 	struct tcp_options_received tmp_opt;
+	struct c4iw_dev *dev;
 
+	dev = *((struct c4iw_dev **) (skb->cb + sizeof(void *)));
 	/* Store values from cpl_rx_pkt in temporary location. */
 	vlantag = (__force u16) cpl->vlan;
 	len = (__force u16) cpl->len;
@@ -2896,7 +2921,7 @@ static void build_cpl_pass_accept_req(struct sk_buff *skb, int stid , u8 tos)
 	 */
 	memset(&tmp_opt, 0, sizeof(tmp_opt));
 	tcp_clear_options(&tmp_opt);
-	tcp_parse_options(skb, &tmp_opt, NULL, 0, NULL);
+	tcp_parse_options(skb, &tmp_opt, 0, NULL);
 
 	req = (struct cpl_pass_accept_req *)__skb_push(skb, sizeof(*req));
 	memset(req, 0, sizeof(*req));
@@ -2904,14 +2929,16 @@ static void build_cpl_pass_accept_req(struct sk_buff *skb, int stid , u8 tos)
 			 V_SYN_MAC_IDX(G_RX_MACIDX(
 			 (__force int) htonl(l2info))) |
 			 F_SYN_XACT_MATCH);
+	eth_hdr_len = is_t4(dev->rdev.lldi.adapter_type) ?
+			    G_RX_ETHHDR_LEN((__force int) htonl(l2info)) :
+			    G_RX_T5_ETHHDR_LEN((__force int) htonl(l2info));
 	req->hdr_len = cpu_to_be32(V_SYN_RX_CHAN(G_RX_CHAN(
 					(__force int) htonl(l2info))) |
 				   V_TCP_HDR_LEN(G_RX_TCPHDR_LEN(
 					(__force int) htons(hdr_len))) |
 				   V_IP_HDR_LEN(G_RX_IPHDR_LEN(
 					(__force int) htons(hdr_len))) |
-				   V_ETH_HDR_LEN(G_RX_ETHHDR_LEN(
-					(__force int) htonl(l2info))));
+				   V_ETH_HDR_LEN(G_RX_ETHHDR_LEN(eth_hdr_len)));
 	req->vlan = (__force __be16) vlantag;
 	req->len = (__force __be16) len;
 	req->tos_stid = cpu_to_be32(PASS_OPEN_TID(stid) |
@@ -2999,7 +3026,7 @@ static int rx_pkt(struct c4iw_dev *dev, struct sk_buff *skb)
 	u16 window;
 	struct port_info *pi;
 	struct net_device *pdev;
-	u16 rss_qid;
+	u16 rss_qid, eth_hdr_len;
 	int step;
 	u32 tx_chan;
 	struct neighbour *neigh;
@@ -3028,7 +3055,10 @@ static int rx_pkt(struct c4iw_dev *dev, struct sk_buff *skb)
 		goto reject;
 	}
 
-	if (G_RX_ETHHDR_LEN(ntohl(cpl->l2info)) == ETH_HLEN) {
+	eth_hdr_len = is_t4(dev->rdev.lldi.adapter_type) ?
+			    G_RX_ETHHDR_LEN(htonl(cpl->l2info)) :
+			    G_RX_T5_ETHHDR_LEN(htonl(cpl->l2info));
+	if (eth_hdr_len == ETH_HLEN) {
 		eh = (struct ethhdr *)(req + 1);
 		iph = (struct iphdr *)(eh + 1);
 	} else {
diff --git a/drivers/infiniband/hw/cxgb4/device.c b/drivers/infiniband/hw/cxgb4/device.c
index 80069ad..ae65601 100644
--- a/drivers/infiniband/hw/cxgb4/device.c
+++ b/drivers/infiniband/hw/cxgb4/device.c
@@ -41,10 +41,20 @@
 #define DRV_VERSION "0.1"
 
 MODULE_AUTHOR("Steve Wise");
-MODULE_DESCRIPTION("Chelsio T4 RDMA Driver");
+MODULE_DESCRIPTION("Chelsio T4/T5 RDMA Driver");
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_VERSION(DRV_VERSION);
 
+static int allow_db_fc_on_t5;
+module_param(allow_db_fc_on_t5, int, 0644);
+MODULE_PARM_DESC(allow_db_fc_on_t5,
+		 "Allow DB Flow Control on T5 (default = 0)");
+
+static int allow_db_coalescing_on_t5;
+module_param(allow_db_coalescing_on_t5, int, 0644);
+MODULE_PARM_DESC(allow_db_coalescing_on_t5,
+		 "Allow DB Coalescing on T5 (default = 0)");
+
 struct uld_ctx {
 	struct list_head entry;
 	struct cxgb4_lld_info lldi;
@@ -614,7 +624,7 @@ static int rdma_supported(const struct cxgb4_lld_info *infop)
 {
 	return infop->vr->stag.size > 0 && infop->vr->pbl.size > 0 &&
 	       infop->vr->rq.size > 0 && infop->vr->qp.size > 0 &&
-	       infop->vr->cq.size > 0 && infop->vr->ocq.size > 0;
+	       infop->vr->cq.size > 0;
 }
 
 static struct c4iw_dev *c4iw_alloc(const struct cxgb4_lld_info *infop)
@@ -627,6 +637,22 @@ static struct c4iw_dev *c4iw_alloc(const struct cxgb4_lld_info *infop)
 		       pci_name(infop->pdev));
 		return ERR_PTR(-ENOSYS);
 	}
+	if (!ocqp_supported(infop))
+		pr_info("%s: On-Chip Queues not supported on this device.\n",
+			pci_name(infop->pdev));
+
+	if (!is_t4(infop->adapter_type)) {
+		if (!allow_db_fc_on_t5) {
+			db_fc_threshold = 100000;
+			pr_info("DB Flow Control Disabled.\n");
+		}
+
+		if (!allow_db_coalescing_on_t5) {
+			db_coalescing_threshold = -1;
+			pr_info("DB Coalescing Disabled.\n");
+		}
+	}
+
 	devp = (struct c4iw_dev *)ib_alloc_device(sizeof(*devp));
 	if (!devp) {
 		printk(KERN_ERR MOD "Cannot allocate ib device\n");
@@ -678,8 +704,8 @@ static void *c4iw_uld_add(const struct cxgb4_lld_info *infop)
 	int i;
 
 	if (!vers_printed++)
-		printk(KERN_INFO MOD "Chelsio T4 RDMA Driver - version %s\n",
-		       DRV_VERSION);
+		pr_info("Chelsio T4/T5 RDMA Driver - version %s\n",
+			DRV_VERSION);
 
 	ctx = kzalloc(sizeof *ctx, GFP_KERNEL);
 	if (!ctx) {
diff --git a/drivers/infiniband/hw/cxgb4/id_table.c b/drivers/infiniband/hw/cxgb4/id_table.c
index f95e5df..0161ae6 100644
--- a/drivers/infiniband/hw/cxgb4/id_table.c
+++ b/drivers/infiniband/hw/cxgb4/id_table.c
@@ -54,7 +54,7 @@ u32 c4iw_id_alloc(struct c4iw_id_table *alloc)
 
 	if (obj < alloc->max) {
 		if (alloc->flags & C4IW_ID_TABLE_F_RANDOM)
-			alloc->last += random32() % RANDOM_SKIP;
+			alloc->last += prandom_u32() % RANDOM_SKIP;
 		else
 			alloc->last = obj + 1;
 		if (alloc->last >= alloc->max)
@@ -88,7 +88,7 @@ int c4iw_id_table_alloc(struct c4iw_id_table *alloc, u32 start, u32 num,
 	alloc->start = start;
 	alloc->flags = flags;
 	if (flags & C4IW_ID_TABLE_F_RANDOM)
-		alloc->last = random32() % RANDOM_SKIP;
+		alloc->last = prandom_u32() % RANDOM_SKIP;
 	else
 		alloc->last = 0;
 	alloc->max  = num;
diff --git a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
index 7eec5e1..485183a 100644
--- a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
+++ b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
@@ -162,7 +162,7 @@ static inline int c4iw_num_stags(struct c4iw_rdev *rdev)
 	return min((int)T4_MAX_NUM_STAG, (int)(rdev->lldi.vr->stag.size >> 5));
 }
 
-#define C4IW_WR_TO (10*HZ)
+#define C4IW_WR_TO (30*HZ)
 
 struct c4iw_wr_wait {
 	struct completion completion;
@@ -369,7 +369,6 @@ struct c4iw_fr_page_list {
 	DEFINE_DMA_UNMAP_ADDR(mapping);
 	dma_addr_t dma_addr;
 	struct c4iw_dev *dev;
-	int size;
 };
 
 static inline struct c4iw_fr_page_list *to_c4iw_fr_page_list(
@@ -817,6 +816,15 @@ static inline int compute_wscale(int win)
 	return wscale;
 }
 
+static inline int ocqp_supported(const struct cxgb4_lld_info *infop)
+{
+#if defined(__i386__) || defined(__x86_64__) || defined(CONFIG_PPC64)
+	return infop->vr->ocq.size > 0;
+#else
+	return 0;
+#endif
+}
+
 u32 c4iw_id_alloc(struct c4iw_id_table *alloc);
 void c4iw_id_free(struct c4iw_id_table *alloc, u32 obj);
 int c4iw_id_table_alloc(struct c4iw_id_table *alloc, u32 start, u32 num,
@@ -930,6 +938,8 @@ extern struct cxgb4_client t4c_client;
 extern c4iw_handler_func c4iw_handlers[NUM_CPL_CMDS];
 extern int c4iw_max_read_depth;
 extern int db_fc_threshold;
+extern int db_coalescing_threshold;
+extern int use_dsgl;
 
 
 #endif
diff --git a/drivers/infiniband/hw/cxgb4/mem.c b/drivers/infiniband/hw/cxgb4/mem.c
index 903a92d..4cb8eb2 100644
--- a/drivers/infiniband/hw/cxgb4/mem.c
+++ b/drivers/infiniband/hw/cxgb4/mem.c
@@ -30,16 +30,76 @@
  * SOFTWARE.
  */
 
+#include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <rdma/ib_umem.h>
 #include <linux/atomic.h>
 
 #include "iw_cxgb4.h"
 
+int use_dsgl = 1;
+module_param(use_dsgl, int, 0644);
+MODULE_PARM_DESC(use_dsgl, "Use DSGL for PBL/FastReg (default=1)");
+
 #define T4_ULPTX_MIN_IO 32
 #define C4IW_MAX_INLINE_SIZE 96
+#define T4_ULPTX_MAX_DMA 1024
+#define C4IW_INLINE_THRESHOLD 128
 
-static int write_adapter_mem(struct c4iw_rdev *rdev, u32 addr, u32 len,
-			     void *data)
+static int inline_threshold = C4IW_INLINE_THRESHOLD;
+module_param(inline_threshold, int, 0644);
+MODULE_PARM_DESC(inline_threshold, "inline vs dsgl threshold (default=128)");
+
+static int _c4iw_write_mem_dma_aligned(struct c4iw_rdev *rdev, u32 addr,
+				       u32 len, dma_addr_t data, int wait)
+{
+	struct sk_buff *skb;
+	struct ulp_mem_io *req;
+	struct ulptx_sgl *sgl;
+	u8 wr_len;
+	int ret = 0;
+	struct c4iw_wr_wait wr_wait;
+
+	addr &= 0x7FFFFFF;
+
+	if (wait)
+		c4iw_init_wr_wait(&wr_wait);
+	wr_len = roundup(sizeof(*req) + sizeof(*sgl), 16);
+
+	skb = alloc_skb(wr_len, GFP_KERNEL | __GFP_NOFAIL);
+	if (!skb)
+		return -ENOMEM;
+	set_wr_txq(skb, CPL_PRIORITY_CONTROL, 0);
+
+	req = (struct ulp_mem_io *)__skb_put(skb, wr_len);
+	memset(req, 0, wr_len);
+	INIT_ULPTX_WR(req, wr_len, 0, 0);
+	req->wr.wr_hi = cpu_to_be32(FW_WR_OP(FW_ULPTX_WR) |
+			(wait ? FW_WR_COMPL(1) : 0));
+	req->wr.wr_lo = wait ? (__force __be64)&wr_wait : 0;
+	req->wr.wr_mid = cpu_to_be32(FW_WR_LEN16(DIV_ROUND_UP(wr_len, 16)));
+	req->cmd = cpu_to_be32(ULPTX_CMD(ULP_TX_MEM_WRITE));
+	req->cmd |= cpu_to_be32(V_T5_ULP_MEMIO_ORDER(1));
+	req->dlen = cpu_to_be32(ULP_MEMIO_DATA_LEN(len>>5));
+	req->len16 = cpu_to_be32(DIV_ROUND_UP(wr_len-sizeof(req->wr), 16));
+	req->lock_addr = cpu_to_be32(ULP_MEMIO_ADDR(addr));
+
+	sgl = (struct ulptx_sgl *)(req + 1);
+	sgl->cmd_nsge = cpu_to_be32(ULPTX_CMD(ULP_TX_SC_DSGL) |
+				    ULPTX_NSGE(1));
+	sgl->len0 = cpu_to_be32(len);
+	sgl->addr0 = cpu_to_be64(data);
+
+	ret = c4iw_ofld_send(rdev, skb);
+	if (ret)
+		return ret;
+	if (wait)
+		ret = c4iw_wait_for_reply(rdev, &wr_wait, 0, 0, __func__);
+	return ret;
+}
+
+static int _c4iw_write_mem_inline(struct c4iw_rdev *rdev, u32 addr, u32 len,
+				  void *data)
 {
 	struct sk_buff *skb;
 	struct ulp_mem_io *req;
@@ -47,6 +107,12 @@ static int write_adapter_mem(struct c4iw_rdev *rdev, u32 addr, u32 len,
 	u8 wr_len, *to_dp, *from_dp;
 	int copy_len, num_wqe, i, ret = 0;
 	struct c4iw_wr_wait wr_wait;
+	__be32 cmd = cpu_to_be32(ULPTX_CMD(ULP_TX_MEM_WRITE));
+
+	if (is_t4(rdev->lldi.adapter_type))
+		cmd |= cpu_to_be32(ULP_MEMIO_ORDER(1));
+	else
+		cmd |= cpu_to_be32(V_T5_ULP_MEMIO_IMM(1));
 
 	addr &= 0x7FFFFFF;
 	PDBG("%s addr 0x%x len %u\n", __func__, addr, len);
@@ -77,7 +143,7 @@ static int write_adapter_mem(struct c4iw_rdev *rdev, u32 addr, u32 len,
 		req->wr.wr_mid = cpu_to_be32(
 				       FW_WR_LEN16(DIV_ROUND_UP(wr_len, 16)));
 
-		req->cmd = cpu_to_be32(ULPTX_CMD(ULP_TX_MEM_WRITE) | (1<<23));
+		req->cmd = cmd;
 		req->dlen = cpu_to_be32(ULP_MEMIO_DATA_LEN(
 				DIV_ROUND_UP(copy_len, T4_ULPTX_MIN_IO)));
 		req->len16 = cpu_to_be32(DIV_ROUND_UP(wr_len-sizeof(req->wr),
@@ -107,6 +173,67 @@ static int write_adapter_mem(struct c4iw_rdev *rdev, u32 addr, u32 len,
 	return ret;
 }
 
+int _c4iw_write_mem_dma(struct c4iw_rdev *rdev, u32 addr, u32 len, void *data)
+{
+	u32 remain = len;
+	u32 dmalen;
+	int ret = 0;
+	dma_addr_t daddr;
+	dma_addr_t save;
+
+	daddr = dma_map_single(&rdev->lldi.pdev->dev, data, len, DMA_TO_DEVICE);
+	if (dma_mapping_error(&rdev->lldi.pdev->dev, daddr))
+		return -1;
+	save = daddr;
+
+	while (remain > inline_threshold) {
+		if (remain < T4_ULPTX_MAX_DMA) {
+			if (remain & ~T4_ULPTX_MIN_IO)
+				dmalen = remain & ~(T4_ULPTX_MIN_IO-1);
+			else
+				dmalen = remain;
+		} else
+			dmalen = T4_ULPTX_MAX_DMA;
+		remain -= dmalen;
+		ret = _c4iw_write_mem_dma_aligned(rdev, addr, dmalen, daddr,
+						 !remain);
+		if (ret)
+			goto out;
+		addr += dmalen >> 5;
+		data += dmalen;
+		daddr += dmalen;
+	}
+	if (remain)
+		ret = _c4iw_write_mem_inline(rdev, addr, remain, data);
+out:
+	dma_unmap_single(&rdev->lldi.pdev->dev, save, len, DMA_TO_DEVICE);
+	return ret;
+}
+
+/*
+ * write len bytes of data into addr (32B aligned address)
+ * If data is NULL, clear len byte of memory to zero.
+ */
+static int write_adapter_mem(struct c4iw_rdev *rdev, u32 addr, u32 len,
+			     void *data)
+{
+	if (is_t5(rdev->lldi.adapter_type) && use_dsgl) {
+		if (len > inline_threshold) {
+			if (_c4iw_write_mem_dma(rdev, addr, len, data)) {
+				printk_ratelimited(KERN_WARNING
+						   "%s: dma map"
+						   " failure (non fatal)\n",
+						   pci_name(rdev->lldi.pdev));
+				return _c4iw_write_mem_inline(rdev, addr, len,
+							      data);
+			} else
+				return 0;
+		} else
+			return _c4iw_write_mem_inline(rdev, addr, len, data);
+	} else
+		return _c4iw_write_mem_inline(rdev, addr, len, data);
+}
+
 /*
  * Build and write a TPT entry.
  * IN: stag key, pdid, perm, bind_enabled, zbva, to, len, page_size,
@@ -760,19 +887,23 @@ struct ib_fast_reg_page_list *c4iw_alloc_fastreg_pbl(struct ib_device *device,
 	struct c4iw_fr_page_list *c4pl;
 	struct c4iw_dev *dev = to_c4iw_dev(device);
 	dma_addr_t dma_addr;
-	int size = sizeof *c4pl + page_list_len * sizeof(u64);
+	int pll_len = roundup(page_list_len * sizeof(u64), 32);
 
-	c4pl = dma_alloc_coherent(&dev->rdev.lldi.pdev->dev, size,
-				  &dma_addr, GFP_KERNEL);
+	c4pl = kmalloc(sizeof(*c4pl), GFP_KERNEL);
 	if (!c4pl)
 		return ERR_PTR(-ENOMEM);
 
+	c4pl->ibpl.page_list = dma_alloc_coherent(&dev->rdev.lldi.pdev->dev,
+						  pll_len, &dma_addr,
+						  GFP_KERNEL);
+	if (!c4pl->ibpl.page_list) {
+		kfree(c4pl);
+		return ERR_PTR(-ENOMEM);
+	}
 	dma_unmap_addr_set(c4pl, mapping, dma_addr);
 	c4pl->dma_addr = dma_addr;
 	c4pl->dev = dev;
-	c4pl->size = size;
-	c4pl->ibpl.page_list = (u64 *)(c4pl + 1);
-	c4pl->ibpl.max_page_list_len = page_list_len;
+	c4pl->ibpl.max_page_list_len = pll_len;
 
 	return &c4pl->ibpl;
 }
@@ -781,8 +912,10 @@ void c4iw_free_fastreg_pbl(struct ib_fast_reg_page_list *ibpl)
 {
 	struct c4iw_fr_page_list *c4pl = to_c4iw_fr_page_list(ibpl);
 
-	dma_free_coherent(&c4pl->dev->rdev.lldi.pdev->dev, c4pl->size,
-			  c4pl, dma_unmap_addr(c4pl, mapping));
+	dma_free_coherent(&c4pl->dev->rdev.lldi.pdev->dev,
+			  c4pl->ibpl.max_page_list_len,
+			  c4pl->ibpl.page_list, dma_unmap_addr(c4pl, mapping));
+	kfree(c4pl);
 }
 
 int c4iw_dereg_mr(struct ib_mr *ib_mr)
diff --git a/drivers/infiniband/hw/cxgb4/provider.c b/drivers/infiniband/hw/cxgb4/provider.c
index e084fdc..7e94c9a 100644
--- a/drivers/infiniband/hw/cxgb4/provider.c
+++ b/drivers/infiniband/hw/cxgb4/provider.c
@@ -162,8 +162,14 @@ static int c4iw_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
 		 */
 		if (addr >= rdev->oc_mw_pa)
 			vma->vm_page_prot = t4_pgprot_wc(vma->vm_page_prot);
-		else
-			vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+		else {
+			if (is_t5(rdev->lldi.adapter_type))
+				vma->vm_page_prot =
+					t4_pgprot_wc(vma->vm_page_prot);
+			else
+				vma->vm_page_prot =
+					pgprot_noncached(vma->vm_page_prot);
+		}
 		ret = io_remap_pfn_range(vma, vma->vm_start,
 					 addr >> PAGE_SHIFT,
 					 len, vma->vm_page_prot);
@@ -263,7 +269,7 @@ static int c4iw_query_device(struct ib_device *ibdev,
 	dev = to_c4iw_dev(ibdev);
 	memset(props, 0, sizeof *props);
 	memcpy(&props->sys_image_guid, dev->rdev.lldi.ports[0]->dev_addr, 6);
-	props->hw_ver = dev->rdev.lldi.adapter_type;
+	props->hw_ver = CHELSIO_CHIP_RELEASE(dev->rdev.lldi.adapter_type);
 	props->fw_ver = dev->rdev.lldi.fw_vers;
 	props->device_cap_flags = dev->device_cap_flags;
 	props->page_size_cap = T4_PAGESIZE_MASK;
@@ -346,7 +352,8 @@ static ssize_t show_rev(struct device *dev, struct device_attribute *attr,
 	struct c4iw_dev *c4iw_dev = container_of(dev, struct c4iw_dev,
 						 ibdev.dev);
 	PDBG("%s dev 0x%p\n", __func__, dev);
-	return sprintf(buf, "%d\n", c4iw_dev->rdev.lldi.adapter_type);
+	return sprintf(buf, "%d\n",
+		       CHELSIO_CHIP_RELEASE(c4iw_dev->rdev.lldi.adapter_type));
 }
 
 static ssize_t show_fw_ver(struct device *dev, struct device_attribute *attr,
diff --git a/drivers/infiniband/hw/cxgb4/qp.c b/drivers/infiniband/hw/cxgb4/qp.c
index 70b1808..5b059e2 100644
--- a/drivers/infiniband/hw/cxgb4/qp.c
+++ b/drivers/infiniband/hw/cxgb4/qp.c
@@ -42,10 +42,21 @@ static int ocqp_support = 1;
 module_param(ocqp_support, int, 0644);
 MODULE_PARM_DESC(ocqp_support, "Support on-chip SQs (default=1)");
 
-int db_fc_threshold = 2000;
+int db_fc_threshold = 1000;
 module_param(db_fc_threshold, int, 0644);
-MODULE_PARM_DESC(db_fc_threshold, "QP count/threshold that triggers automatic "
-		 "db flow control mode (default = 2000)");
+MODULE_PARM_DESC(db_fc_threshold,
+		 "QP count/threshold that triggers"
+		 " automatic db flow control mode (default = 1000)");
+
+int db_coalescing_threshold;
+module_param(db_coalescing_threshold, int, 0644);
+MODULE_PARM_DESC(db_coalescing_threshold,
+		 "QP count/threshold that triggers"
+		 " disabling db coalescing (default = 0)");
+
+static int max_fr_immd = T4_MAX_FR_IMMD;
+module_param(max_fr_immd, int, 0644);
+MODULE_PARM_DESC(max_fr_immd, "fastreg threshold for using DSGL instead of immedate");
 
 static void set_state(struct c4iw_qp *qhp, enum c4iw_qp_state state)
 {
@@ -76,7 +87,7 @@ static void dealloc_sq(struct c4iw_rdev *rdev, struct t4_sq *sq)
 
 static int alloc_oc_sq(struct c4iw_rdev *rdev, struct t4_sq *sq)
 {
-	if (!ocqp_support || !t4_ocqp_supported())
+	if (!ocqp_support || !ocqp_supported(&rdev->lldi))
 		return -ENOSYS;
 	sq->dma_addr = c4iw_ocqp_pool_alloc(rdev, sq->memsize);
 	if (!sq->dma_addr)
@@ -129,7 +140,7 @@ static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq,
 	int wr_len;
 	struct c4iw_wr_wait wr_wait;
 	struct sk_buff *skb;
-	int ret;
+	int ret = 0;
 	int eqsize;
 
 	wq->sq.qid = c4iw_get_qpid(rdev, uctx);
@@ -169,17 +180,14 @@ static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq,
 	}
 
 	if (user) {
-		ret = alloc_oc_sq(rdev, &wq->sq);
-		if (ret)
+		if (alloc_oc_sq(rdev, &wq->sq) && alloc_host_sq(rdev, &wq->sq))
 			goto free_hwaddr;
-
-		ret = alloc_host_sq(rdev, &wq->sq);
-		if (ret)
-			goto free_sq;
-	} else
+	} else {
 		ret = alloc_host_sq(rdev, &wq->sq);
 		if (ret)
 			goto free_hwaddr;
+	}
+
 	memset(wq->sq.queue, 0, wq->sq.memsize);
 	dma_unmap_addr_set(&wq->sq, mapping, wq->sq.dma_addr);
 
@@ -534,7 +542,7 @@ static int build_rdma_recv(struct c4iw_qp *qhp, union t4_recv_wr *wqe,
 }
 
 static int build_fastreg(struct t4_sq *sq, union t4_wr *wqe,
-			 struct ib_send_wr *wr, u8 *len16)
+			 struct ib_send_wr *wr, u8 *len16, u8 t5dev)
 {
 
 	struct fw_ri_immd *imdp;
@@ -556,28 +564,51 @@ static int build_fastreg(struct t4_sq *sq, union t4_wr *wqe,
 	wqe->fr.va_hi = cpu_to_be32(wr->wr.fast_reg.iova_start >> 32);
 	wqe->fr.va_lo_fbo = cpu_to_be32(wr->wr.fast_reg.iova_start &
 					0xffffffff);
-	WARN_ON(pbllen > T4_MAX_FR_IMMD);
-	imdp = (struct fw_ri_immd *)(&wqe->fr + 1);
-	imdp->op = FW_RI_DATA_IMMD;
-	imdp->r1 = 0;
-	imdp->r2 = 0;
-	imdp->immdlen = cpu_to_be32(pbllen);
-	p = (__be64 *)(imdp + 1);
-	rem = pbllen;
-	for (i = 0; i < wr->wr.fast_reg.page_list_len; i++) {
-		*p = cpu_to_be64((u64)wr->wr.fast_reg.page_list->page_list[i]);
-		rem -= sizeof *p;
-		if (++p == (__be64 *)&sq->queue[sq->size])
-			p = (__be64 *)sq->queue;
-	}
-	BUG_ON(rem < 0);
-	while (rem) {
-		*p = 0;
-		rem -= sizeof *p;
-		if (++p == (__be64 *)&sq->queue[sq->size])
-			p = (__be64 *)sq->queue;
+
+	if (t5dev && use_dsgl && (pbllen > max_fr_immd)) {
+		struct c4iw_fr_page_list *c4pl =
+			to_c4iw_fr_page_list(wr->wr.fast_reg.page_list);
+		struct fw_ri_dsgl *sglp;
+
+		for (i = 0; i < wr->wr.fast_reg.page_list_len; i++) {
+			wr->wr.fast_reg.page_list->page_list[i] = (__force u64)
+				cpu_to_be64((u64)
+				wr->wr.fast_reg.page_list->page_list[i]);
+		}
+
+		sglp = (struct fw_ri_dsgl *)(&wqe->fr + 1);
+		sglp->op = FW_RI_DATA_DSGL;
+		sglp->r1 = 0;
+		sglp->nsge = cpu_to_be16(1);
+		sglp->addr0 = cpu_to_be64(c4pl->dma_addr);
+		sglp->len0 = cpu_to_be32(pbllen);
+
+		*len16 = DIV_ROUND_UP(sizeof(wqe->fr) + sizeof(*sglp), 16);
+	} else {
+		imdp = (struct fw_ri_immd *)(&wqe->fr + 1);
+		imdp->op = FW_RI_DATA_IMMD;
+		imdp->r1 = 0;
+		imdp->r2 = 0;
+		imdp->immdlen = cpu_to_be32(pbllen);
+		p = (__be64 *)(imdp + 1);
+		rem = pbllen;
+		for (i = 0; i < wr->wr.fast_reg.page_list_len; i++) {
+			*p = cpu_to_be64(
+				(u64)wr->wr.fast_reg.page_list->page_list[i]);
+			rem -= sizeof(*p);
+			if (++p == (__be64 *)&sq->queue[sq->size])
+				p = (__be64 *)sq->queue;
+		}
+		BUG_ON(rem < 0);
+		while (rem) {
+			*p = 0;
+			rem -= sizeof(*p);
+			if (++p == (__be64 *)&sq->queue[sq->size])
+				p = (__be64 *)sq->queue;
+		}
+		*len16 = DIV_ROUND_UP(sizeof(wqe->fr) + sizeof(*imdp)
+				      + pbllen, 16);
 	}
-	*len16 = DIV_ROUND_UP(sizeof wqe->fr + sizeof *imdp + pbllen, 16);
 	return 0;
 }
 
@@ -678,7 +709,10 @@ int c4iw_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
 		case IB_WR_FAST_REG_MR:
 			fw_opcode = FW_RI_FR_NSMR_WR;
 			swsqe->opcode = FW_RI_FAST_REGISTER;
-			err = build_fastreg(&qhp->wq.sq, wqe, wr, &len16);
+			err = build_fastreg(&qhp->wq.sq, wqe, wr, &len16,
+					    is_t5(
+					    qhp->rhp->rdev.lldi.adapter_type) ?
+					    1 : 0);
 			break;
 		case IB_WR_LOCAL_INV:
 			if (wr->send_flags & IB_SEND_FENCE)
@@ -1450,6 +1484,9 @@ int c4iw_destroy_qp(struct ib_qp *ib_qp)
 		rhp->db_state = NORMAL;
 		idr_for_each(&rhp->qpidr, enable_qp_db, NULL);
 	}
+	if (db_coalescing_threshold >= 0)
+		if (rhp->qpcnt <= db_coalescing_threshold)
+			cxgb4_enable_db_coalescing(rhp->rdev.lldi.ports[0]);
 	spin_unlock_irq(&rhp->lock);
 	atomic_dec(&qhp->refcnt);
 	wait_event(qhp->wait, !atomic_read(&qhp->refcnt));
@@ -1561,11 +1598,15 @@ struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs,
 	spin_lock_irq(&rhp->lock);
 	if (rhp->db_state != NORMAL)
 		t4_disable_wq_db(&qhp->wq);
-	if (++rhp->qpcnt > db_fc_threshold && rhp->db_state == NORMAL) {
+	rhp->qpcnt++;
+	if (rhp->qpcnt > db_fc_threshold && rhp->db_state == NORMAL) {
 		rhp->rdev.stats.db_state_transitions++;
 		rhp->db_state = FLOW_CONTROL;
 		idr_for_each(&rhp->qpidr, disable_qp_db, NULL);
 	}
+	if (db_coalescing_threshold >= 0)
+		if (rhp->qpcnt > db_coalescing_threshold)
+			cxgb4_disable_db_coalescing(rhp->rdev.lldi.ports[0]);
 	ret = insert_handle_nolock(rhp, &rhp->qpidr, qhp, qhp->wq.sq.qid);
 	spin_unlock_irq(&rhp->lock);
 	if (ret)
diff --git a/drivers/infiniband/hw/cxgb4/t4.h b/drivers/infiniband/hw/cxgb4/t4.h
index 16f26ab..ebcb03b 100644
--- a/drivers/infiniband/hw/cxgb4/t4.h
+++ b/drivers/infiniband/hw/cxgb4/t4.h
@@ -84,7 +84,7 @@ struct t4_status_page {
 			sizeof(struct fw_ri_isgl)) / sizeof(struct fw_ri_sge))
 #define T4_MAX_FR_IMMD ((T4_SQ_NUM_BYTES - sizeof(struct fw_ri_fr_nsmr_wr) - \
 			sizeof(struct fw_ri_immd)) & ~31UL)
-#define T4_MAX_FR_DEPTH (T4_MAX_FR_IMMD / sizeof(u64))
+#define T4_MAX_FR_DEPTH (1024 / sizeof(u64))
 
 #define T4_RQ_NUM_SLOTS 2
 #define T4_RQ_NUM_BYTES (T4_EQ_ENTRY_SIZE * T4_RQ_NUM_SLOTS)
@@ -280,15 +280,6 @@ static inline pgprot_t t4_pgprot_wc(pgprot_t prot)
 #endif
 }
 
-static inline int t4_ocqp_supported(void)
-{
-#if defined(__i386__) || defined(__x86_64__) || defined(CONFIG_PPC64)
-	return 1;
-#else
-	return 0;
-#endif
-}
-
 enum {
 	T4_SQ_ONCHIP = (1<<0),
 };
diff --git a/drivers/infiniband/hw/ipath/ipath_file_ops.c b/drivers/infiniband/hw/ipath/ipath_file_ops.c
index aed8afe..6d7f453 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/slab.h>
 #include <linux/highmem.h>
 #include <linux/io.h>
+#include <linux/aio.h>
 #include <linux/jiffies.h>
 #include <linux/cpu.h>
 #include <asm/pgtable.h>
diff --git a/drivers/infiniband/hw/mlx4/mad.c b/drivers/infiniband/hw/mlx4/mad.c
index 934792c..4d599ce 100644
--- a/drivers/infiniband/hw/mlx4/mad.c
+++ b/drivers/infiniband/hw/mlx4/mad.c
@@ -93,7 +93,7 @@ static void __propagate_pkey_ev(struct mlx4_ib_dev *dev, int port_num,
 __be64 mlx4_ib_gen_node_guid(void)
 {
 #define NODE_GUID_HI	((u64) (((u64)IB_OPENIB_OUI) << 40))
-	return cpu_to_be64(NODE_GUID_HI | random32());
+	return cpu_to_be64(NODE_GUID_HI | prandom_u32());
 }
 
 __be64 mlx4_ib_get_new_demux_tid(struct mlx4_ib_demux_ctx *ctx)
diff --git a/drivers/infiniband/hw/qib/qib_file_ops.c b/drivers/infiniband/hw/qib/qib_file_ops.c
index 4f7aa30..b56c942 100644
--- a/drivers/infiniband/hw/qib/qib_file_ops.c
+++ b/drivers/infiniband/hw/qib/qib_file_ops.c
@@ -39,7 +39,7 @@
 #include <linux/vmalloc.h>
 #include <linux/highmem.h>
 #include <linux/io.h>
-#include <linux/uio.h>
+#include <linux/aio.h>
 #include <linux/jiffies.h>
 #include <asm/pgtable.h>
 #include <linux/delay.h>
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
index 1ef880d..3eceb61 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
@@ -460,7 +460,7 @@ static int ipoib_cm_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *even
 		goto err_qp;
 	}
 
-	psn = random32() & 0xffffff;
+	psn = prandom_u32() & 0xffffff;
 	ret = ipoib_cm_modify_rx_qp(dev, cm_id, p->qp, psn);
 	if (ret)
 		goto err_modify;
diff --git a/drivers/input/input-mt.c b/drivers/input/input-mt.c
index 71db193..c0ce893 100644
--- a/drivers/input/input-mt.c
+++ b/drivers/input/input-mt.c
@@ -79,6 +79,8 @@ int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots,
 	}
 	if (flags & INPUT_MT_DIRECT)
 		__set_bit(INPUT_PROP_DIRECT, dev->propbit);
+	if (flags & INPUT_MT_SEMI_MT)
+		__set_bit(INPUT_PROP_SEMI_MT, dev->propbit);
 	if (flags & INPUT_MT_TRACK) {
 		unsigned int n2 = num_slots * num_slots;
 		mt->red = kcalloc(n2, sizeof(*mt->red), GFP_KERNEL);
@@ -246,6 +248,7 @@ void input_mt_sync_frame(struct input_dev *dev)
 {
 	struct input_mt *mt = dev->mt;
 	struct input_mt_slot *s;
+	bool use_count = false;
 
 	if (!mt)
 		return;
@@ -259,7 +262,10 @@ void input_mt_sync_frame(struct input_dev *dev)
 		}
 	}
 
-	input_mt_report_pointer_emulation(dev, (mt->flags & INPUT_MT_POINTER));
+	if ((mt->flags & INPUT_MT_POINTER) & !(mt->flags & INPUT_MT_SEMI_MT))
+		use_count = true;
+
+	input_mt_report_pointer_emulation(dev, use_count);
 
 	mt->frame++;
 }
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index ac05006..6a195d5 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -628,4 +628,16 @@ config KEYBOARD_W90P910
 	  To compile this driver as a module, choose M here: the
 	  module will be called w90p910_keypad.
 
+config KEYBOARD_CROS_EC
+	tristate "ChromeOS EC keyboard"
+	select INPUT_MATRIXKMAP
+	depends on MFD_CROS_EC
+	help
+	  Say Y here to enable the matrix keyboard used by ChromeOS devices
+	  and implemented on the ChromeOS EC. You must enable one bus option
+	  (MFD_CROS_EC_I2C or MFD_CROS_EC_SPI) to use this.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called cros_ec_keyb.
+
 endif
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index 49b1645..0c43e8c 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_KEYBOARD_AMIGA)		+= amikbd.o
 obj-$(CONFIG_KEYBOARD_ATARI)		+= atakbd.o
 obj-$(CONFIG_KEYBOARD_ATKBD)		+= atkbd.o
 obj-$(CONFIG_KEYBOARD_BFIN)		+= bf54x-keys.o
+obj-$(CONFIG_KEYBOARD_CROS_EC)		+= cros_ec_keyb.o
 obj-$(CONFIG_KEYBOARD_DAVINCI)		+= davinci_keyscan.o
 obj-$(CONFIG_KEYBOARD_EP93XX)		+= ep93xx_keypad.o
 obj-$(CONFIG_KEYBOARD_GOLDFISH_EVENTS)	+= goldfish_events.o
diff --git a/drivers/input/keyboard/amikbd.c b/drivers/input/keyboard/amikbd.c
index 79172af..ba0b36f 100644
--- a/drivers/input/keyboard/amikbd.c
+++ b/drivers/input/keyboard/amikbd.c
@@ -260,18 +260,6 @@ static struct platform_driver amikbd_driver = {
 	},
 };
 
-static int __init amikbd_init(void)
-{
-	return platform_driver_probe(&amikbd_driver, amikbd_probe);
-}
-
-module_init(amikbd_init);
-
-static void __exit amikbd_exit(void)
-{
-	platform_driver_unregister(&amikbd_driver);
-}
-
-module_exit(amikbd_exit);
+module_platform_driver_probe(amikbd_driver, amikbd_probe);
 
 MODULE_ALIAS("platform:amiga-keyboard");
diff --git a/drivers/input/keyboard/cros_ec_keyb.c b/drivers/input/keyboard/cros_ec_keyb.c
new file mode 100644
index 0000000..49557f2
--- /dev/null
+++ b/drivers/input/keyboard/cros_ec_keyb.c
@@ -0,0 +1,334 @@
+/*
+ * ChromeOS EC keyboard driver
+ *
+ * Copyright (C) 2012 Google, 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.
+ *
+ * This driver uses the Chrome OS EC byte-level message-based protocol for
+ * communicating the keyboard state (which keys are pressed) from a keyboard EC
+ * to the AP over some bus (such as i2c, lpc, spi).  The EC does debouncing,
+ * but everything else (including deghosting) is done here.  The main
+ * motivation for this is to keep the EC firmware as simple as possible, since
+ * it cannot be easily upgraded and EC flash/IRAM space is relatively
+ * expensive.
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/kernel.h>
+#include <linux/notifier.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/input/matrix_keypad.h>
+#include <linux/mfd/cros_ec.h>
+#include <linux/mfd/cros_ec_commands.h>
+
+/*
+ * @rows: Number of rows in the keypad
+ * @cols: Number of columns in the keypad
+ * @row_shift: log2 or number of rows, rounded up
+ * @keymap_data: Matrix keymap data used to convert to keyscan values
+ * @ghost_filter: true to enable the matrix key-ghosting filter
+ * @dev: Device pointer
+ * @idev: Input device
+ * @ec: Top level ChromeOS device to use to talk to EC
+ * @event_notifier: interrupt event notifier for transport devices
+ */
+struct cros_ec_keyb {
+	unsigned int rows;
+	unsigned int cols;
+	int row_shift;
+	const struct matrix_keymap_data *keymap_data;
+	bool ghost_filter;
+
+	struct device *dev;
+	struct input_dev *idev;
+	struct cros_ec_device *ec;
+	struct notifier_block notifier;
+};
+
+
+static bool cros_ec_keyb_row_has_ghosting(struct cros_ec_keyb *ckdev,
+					  uint8_t *buf, int row)
+{
+	int pressed_in_row = 0;
+	int row_has_teeth = 0;
+	int col, mask;
+
+	mask = 1 << row;
+	for (col = 0; col < ckdev->cols; col++) {
+		if (buf[col] & mask) {
+			pressed_in_row++;
+			row_has_teeth |= buf[col] & ~mask;
+			if (pressed_in_row > 1 && row_has_teeth) {
+				/* ghosting */
+				dev_dbg(ckdev->dev,
+					"ghost found at: r%d c%d, pressed %d, teeth 0x%x\n",
+					row, col, pressed_in_row,
+					row_has_teeth);
+				return true;
+			}
+		}
+	}
+
+	return false;
+}
+
+/*
+ * Returns true when there is at least one combination of pressed keys that
+ * results in ghosting.
+ */
+static bool cros_ec_keyb_has_ghosting(struct cros_ec_keyb *ckdev, uint8_t *buf)
+{
+	int row;
+
+	/*
+	 * Ghosting happens if for any pressed key X there are other keys
+	 * pressed both in the same row and column of X as, for instance,
+	 * in the following diagram:
+	 *
+	 * . . Y . g .
+	 * . . . . . .
+	 * . . . . . .
+	 * . . X . Z .
+	 *
+	 * In this case only X, Y, and Z are pressed, but g appears to be
+	 * pressed too (see Wikipedia).
+	 *
+	 * We can detect ghosting in a single pass (*) over the keyboard state
+	 * by maintaining two arrays.  pressed_in_row counts how many pressed
+	 * keys we have found in a row.  row_has_teeth is true if any of the
+	 * pressed keys for this row has other pressed keys in its column.  If
+	 * at any point of the scan we find that a row has multiple pressed
+	 * keys, and at least one of them is at the intersection with a column
+	 * with multiple pressed keys, we're sure there is ghosting.
+	 * Conversely, if there is ghosting, we will detect such situation for
+	 * at least one key during the pass.
+	 *
+	 * (*) This looks linear in the number of keys, but it's not.  We can
+	 * cheat because the number of rows is small.
+	 */
+	for (row = 0; row < ckdev->rows; row++)
+		if (cros_ec_keyb_row_has_ghosting(ckdev, buf, row))
+			return true;
+
+	return false;
+}
+
+/*
+ * Compares the new keyboard state to the old one and produces key
+ * press/release events accordingly.  The keyboard state is 13 bytes (one byte
+ * per column)
+ */
+static void cros_ec_keyb_process(struct cros_ec_keyb *ckdev,
+			 uint8_t *kb_state, int len)
+{
+	struct input_dev *idev = ckdev->idev;
+	int col, row;
+	int new_state;
+	int num_cols;
+
+	num_cols = len;
+
+	if (ckdev->ghost_filter && cros_ec_keyb_has_ghosting(ckdev, kb_state)) {
+		/*
+		 * Simple-minded solution: ignore this state. The obvious
+		 * improvement is to only ignore changes to keys involved in
+		 * the ghosting, but process the other changes.
+		 */
+		dev_dbg(ckdev->dev, "ghosting found\n");
+		return;
+	}
+
+	for (col = 0; col < ckdev->cols; col++) {
+		for (row = 0; row < ckdev->rows; row++) {
+			int pos = MATRIX_SCAN_CODE(row, col, ckdev->row_shift);
+			const unsigned short *keycodes = idev->keycode;
+			int code;
+
+			code = keycodes[pos];
+			new_state = kb_state[col] & (1 << row);
+			if (!!new_state != test_bit(code, idev->key)) {
+				dev_dbg(ckdev->dev,
+					"changed: [r%d c%d]: byte %02x\n",
+					row, col, new_state);
+
+				input_report_key(idev, code, new_state);
+			}
+		}
+	}
+	input_sync(ckdev->idev);
+}
+
+static int cros_ec_keyb_open(struct input_dev *dev)
+{
+	struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
+
+	return blocking_notifier_chain_register(&ckdev->ec->event_notifier,
+						&ckdev->notifier);
+}
+
+static void cros_ec_keyb_close(struct input_dev *dev)
+{
+	struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
+
+	blocking_notifier_chain_unregister(&ckdev->ec->event_notifier,
+					   &ckdev->notifier);
+}
+
+static int cros_ec_keyb_get_state(struct cros_ec_keyb *ckdev, uint8_t *kb_state)
+{
+	return ckdev->ec->command_recv(ckdev->ec, EC_CMD_MKBP_STATE,
+					  kb_state, ckdev->cols);
+}
+
+static int cros_ec_keyb_work(struct notifier_block *nb,
+		     unsigned long state, void *_notify)
+{
+	int ret;
+	struct cros_ec_keyb *ckdev = container_of(nb, struct cros_ec_keyb,
+						    notifier);
+	uint8_t kb_state[ckdev->cols];
+
+	ret = cros_ec_keyb_get_state(ckdev, kb_state);
+	if (ret >= 0)
+		cros_ec_keyb_process(ckdev, kb_state, ret);
+
+	return NOTIFY_DONE;
+}
+
+/* Clear any keys in the buffer */
+static void cros_ec_keyb_clear_keyboard(struct cros_ec_keyb *ckdev)
+{
+	uint8_t old_state[ckdev->cols];
+	uint8_t new_state[ckdev->cols];
+	unsigned long duration;
+	int i, ret;
+
+	/*
+	 * Keep reading until we see that the scan state does not change.
+	 * That indicates that we are done.
+	 *
+	 * Assume that the EC keyscan buffer is at most 32 deep.
+	 */
+	duration = jiffies;
+	ret = cros_ec_keyb_get_state(ckdev, new_state);
+	for (i = 1; !ret && i < 32; i++) {
+		memcpy(old_state, new_state, sizeof(old_state));
+		ret = cros_ec_keyb_get_state(ckdev, new_state);
+		if (0 == memcmp(old_state, new_state, sizeof(old_state)))
+			break;
+	}
+	duration = jiffies - duration;
+	dev_info(ckdev->dev, "Discarded %d keyscan(s) in %dus\n", i,
+		jiffies_to_usecs(duration));
+}
+
+static int cros_ec_keyb_probe(struct platform_device *pdev)
+{
+	struct cros_ec_device *ec = dev_get_drvdata(pdev->dev.parent);
+	struct device *dev = ec->dev;
+	struct cros_ec_keyb *ckdev;
+	struct input_dev *idev;
+	struct device_node *np;
+	int err;
+
+	np = pdev->dev.of_node;
+	if (!np)
+		return -ENODEV;
+
+	ckdev = devm_kzalloc(&pdev->dev, sizeof(*ckdev), GFP_KERNEL);
+	if (!ckdev)
+		return -ENOMEM;
+	err = matrix_keypad_parse_of_params(&pdev->dev, &ckdev->rows,
+					    &ckdev->cols);
+	if (err)
+		return err;
+
+	idev = devm_input_allocate_device(&pdev->dev);
+	if (!idev)
+		return -ENOMEM;
+
+	ckdev->ec = ec;
+	ckdev->notifier.notifier_call = cros_ec_keyb_work;
+	ckdev->dev = dev;
+	dev_set_drvdata(&pdev->dev, ckdev);
+
+	idev->name = ec->ec_name;
+	idev->phys = ec->phys_name;
+	__set_bit(EV_REP, idev->evbit);
+
+	idev->id.bustype = BUS_VIRTUAL;
+	idev->id.version = 1;
+	idev->id.product = 0;
+	idev->dev.parent = &pdev->dev;
+	idev->open = cros_ec_keyb_open;
+	idev->close = cros_ec_keyb_close;
+
+	ckdev->ghost_filter = of_property_read_bool(np,
+					"google,needs-ghost-filter");
+
+	err = matrix_keypad_build_keymap(NULL, NULL, ckdev->rows, ckdev->cols,
+					 NULL, idev);
+	if (err) {
+		dev_err(dev, "cannot build key matrix\n");
+		return err;
+	}
+
+	ckdev->row_shift = get_count_order(ckdev->cols);
+
+	input_set_capability(idev, EV_MSC, MSC_SCAN);
+	input_set_drvdata(idev, ckdev);
+	ckdev->idev = idev;
+	err = input_register_device(ckdev->idev);
+	if (err) {
+		dev_err(dev, "cannot register input device\n");
+		return err;
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int cros_ec_keyb_resume(struct device *dev)
+{
+	struct cros_ec_keyb *ckdev = dev_get_drvdata(dev);
+
+	/*
+	 * When the EC is not a wake source, then it could not have caused the
+	 * resume, so we clear the EC's key scan buffer. If the EC was a
+	 * wake source (e.g. the lid is open and the user might press a key to
+	 * wake) then the key scan buffer should be preserved.
+	 */
+	if (ckdev->ec->was_wake_device)
+		cros_ec_keyb_clear_keyboard(ckdev);
+
+	return 0;
+}
+
+#endif
+
+static SIMPLE_DEV_PM_OPS(cros_ec_keyb_pm_ops, NULL, cros_ec_keyb_resume);
+
+static struct platform_driver cros_ec_keyb_driver = {
+	.probe = cros_ec_keyb_probe,
+	.driver = {
+		.name = "cros-ec-keyb",
+		.pm	= &cros_ec_keyb_pm_ops,
+	},
+};
+
+module_platform_driver(cros_ec_keyb_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("ChromeOS EC keyboard driver");
+MODULE_ALIAS("platform:cros-ec-keyb");
diff --git a/drivers/input/keyboard/davinci_keyscan.c b/drivers/input/keyboard/davinci_keyscan.c
index 4e4e453..8297537 100644
--- a/drivers/input/keyboard/davinci_keyscan.c
+++ b/drivers/input/keyboard/davinci_keyscan.c
@@ -329,17 +329,7 @@ static struct platform_driver davinci_ks_driver = {
 	.remove	= davinci_ks_remove,
 };
 
-static int __init davinci_ks_init(void)
-{
-	return platform_driver_probe(&davinci_ks_driver, davinci_ks_probe);
-}
-module_init(davinci_ks_init);
-
-static void __exit davinci_ks_exit(void)
-{
-	platform_driver_unregister(&davinci_ks_driver);
-}
-module_exit(davinci_ks_exit);
+module_platform_driver_probe(davinci_ks_driver, davinci_ks_probe);
 
 MODULE_AUTHOR("Miguel Aguilar");
 MODULE_DESCRIPTION("Texas Instruments DaVinci Key Scan Driver");
diff --git a/drivers/input/keyboard/imx_keypad.c b/drivers/input/keyboard/imx_keypad.c
index 98f9113..03c8cc5 100644
--- a/drivers/input/keyboard/imx_keypad.c
+++ b/drivers/input/keyboard/imx_keypad.c
@@ -448,24 +448,17 @@ static int imx_keypad_probe(struct platform_device *pdev)
 		return -EINVAL;
 	}
 
-	res = request_mem_region(res->start, resource_size(res), pdev->name);
-	if (res == NULL) {
-		dev_err(&pdev->dev, "failed to request I/O memory\n");
-		return -EBUSY;
-	}
-
-	input_dev = input_allocate_device();
+	input_dev = devm_input_allocate_device(&pdev->dev);
 	if (!input_dev) {
 		dev_err(&pdev->dev, "failed to allocate the input device\n");
-		error = -ENOMEM;
-		goto failed_rel_mem;
+		return -ENOMEM;
 	}
 
-	keypad = kzalloc(sizeof(struct imx_keypad), GFP_KERNEL);
+	keypad = devm_kzalloc(&pdev->dev, sizeof(struct imx_keypad),
+			     GFP_KERNEL);
 	if (!keypad) {
 		dev_err(&pdev->dev, "not enough memory for driver data\n");
-		error = -ENOMEM;
-		goto failed_free_input;
+		return -ENOMEM;
 	}
 
 	keypad->input_dev = input_dev;
@@ -475,18 +468,14 @@ static int imx_keypad_probe(struct platform_device *pdev)
 	setup_timer(&keypad->check_matrix_timer,
 		    imx_keypad_check_for_events, (unsigned long) keypad);
 
-	keypad->mmio_base = ioremap(res->start, resource_size(res));
-	if (keypad->mmio_base == NULL) {
-		dev_err(&pdev->dev, "failed to remap I/O memory\n");
-		error = -ENOMEM;
-		goto failed_free_priv;
-	}
+	keypad->mmio_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(keypad->mmio_base))
+		return PTR_ERR(keypad->mmio_base);
 
-	keypad->clk = clk_get(&pdev->dev, NULL);
+	keypad->clk = devm_clk_get(&pdev->dev, NULL);
 	if (IS_ERR(keypad->clk)) {
 		dev_err(&pdev->dev, "failed to get keypad clock\n");
-		error = PTR_ERR(keypad->clk);
-		goto failed_unmap;
+		return PTR_ERR(keypad->clk);
 	}
 
 	/* Init the Input device */
@@ -502,7 +491,7 @@ static int imx_keypad_probe(struct platform_device *pdev)
 					   keypad->keycodes, input_dev);
 	if (error) {
 		dev_err(&pdev->dev, "failed to build keymap\n");
-		goto failed_clock_put;
+		return error;
 	}
 
 	/* Search for rows and cols enabled */
@@ -527,61 +516,24 @@ static int imx_keypad_probe(struct platform_device *pdev)
 	imx_keypad_inhibit(keypad);
 	clk_disable_unprepare(keypad->clk);
 
-	error = request_irq(irq, imx_keypad_irq_handler, 0,
+	error = devm_request_irq(&pdev->dev, irq, imx_keypad_irq_handler, 0,
 			    pdev->name, keypad);
 	if (error) {
 		dev_err(&pdev->dev, "failed to request IRQ\n");
-		goto failed_clock_put;
+		return error;
 	}
 
 	/* Register the input device */
 	error = input_register_device(input_dev);
 	if (error) {
 		dev_err(&pdev->dev, "failed to register input device\n");
-		goto failed_free_irq;
+		return error;
 	}
 
 	platform_set_drvdata(pdev, keypad);
 	device_init_wakeup(&pdev->dev, 1);
 
 	return 0;
-
-failed_free_irq:
-	free_irq(irq, pdev);
-failed_clock_put:
-	clk_put(keypad->clk);
-failed_unmap:
-	iounmap(keypad->mmio_base);
-failed_free_priv:
-	kfree(keypad);
-failed_free_input:
-	input_free_device(input_dev);
-failed_rel_mem:
-	release_mem_region(res->start, resource_size(res));
-	return error;
-}
-
-static int imx_keypad_remove(struct platform_device *pdev)
-{
-	struct imx_keypad *keypad = platform_get_drvdata(pdev);
-	struct resource *res;
-
-	dev_dbg(&pdev->dev, ">%s\n", __func__);
-
-	platform_set_drvdata(pdev, NULL);
-
-	input_unregister_device(keypad->input_dev);
-
-	free_irq(keypad->irq, keypad);
-	clk_put(keypad->clk);
-
-	iounmap(keypad->mmio_base);
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	release_mem_region(res->start, resource_size(res));
-
-	kfree(keypad);
-
-	return 0;
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -640,7 +592,6 @@ static struct platform_driver imx_keypad_driver = {
 		.of_match_table = of_match_ptr(imx_keypad_of_match),
 	},
 	.probe		= imx_keypad_probe,
-	.remove		= imx_keypad_remove,
 };
 module_platform_driver(imx_keypad_driver);
 
diff --git a/drivers/input/keyboard/lpc32xx-keys.c b/drivers/input/keyboard/lpc32xx-keys.c
index 1b8add6..4218143 100644
--- a/drivers/input/keyboard/lpc32xx-keys.c
+++ b/drivers/input/keyboard/lpc32xx-keys.c
@@ -144,12 +144,13 @@ static int lpc32xx_parse_dt(struct device *dev,
 {
 	struct device_node *np = dev->of_node;
 	u32 rows = 0, columns = 0;
+	int err;
 
-	of_property_read_u32(np, "keypad,num-rows", &rows);
-	of_property_read_u32(np, "keypad,num-columns", &columns);
-	if (!rows || rows != columns) {
-		dev_err(dev,
-			"rows and columns must be specified and be equal!\n");
+	err = matrix_keypad_parse_of_params(dev, &rows, &columns);
+	if (err)
+		return err;
+	if (rows != columns) {
+		dev_err(dev, "rows and columns must be equal!\n");
 		return -EINVAL;
 	}
 
diff --git a/drivers/input/keyboard/nomadik-ske-keypad.c b/drivers/input/keyboard/nomadik-ske-keypad.c
index 0e6a815..c7d505c 100644
--- a/drivers/input/keyboard/nomadik-ske-keypad.c
+++ b/drivers/input/keyboard/nomadik-ske-keypad.c
@@ -430,17 +430,7 @@ static struct platform_driver ske_keypad_driver = {
 	.remove = ske_keypad_remove,
 };
 
-static int __init ske_keypad_init(void)
-{
-	return platform_driver_probe(&ske_keypad_driver, ske_keypad_probe);
-}
-module_init(ske_keypad_init);
-
-static void __exit ske_keypad_exit(void)
-{
-	platform_driver_unregister(&ske_keypad_driver);
-}
-module_exit(ske_keypad_exit);
+module_platform_driver_probe(ske_keypad_driver, ske_keypad_probe);
 
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Naveen Kumar <naveen.gaddipati@stericsson.com> / Sundar Iyer <sundar.iyer@stericsson.com>");
diff --git a/drivers/input/keyboard/omap4-keypad.c b/drivers/input/keyboard/omap4-keypad.c
index e25b022..1b28909 100644
--- a/drivers/input/keyboard/omap4-keypad.c
+++ b/drivers/input/keyboard/omap4-keypad.c
@@ -215,18 +215,12 @@ static int omap4_keypad_parse_dt(struct device *dev,
 				 struct omap4_keypad *keypad_data)
 {
 	struct device_node *np = dev->of_node;
+	int err;
 
-	if (!np) {
-		dev_err(dev, "missing DT data");
-		return -EINVAL;
-	}
-
-	of_property_read_u32(np, "keypad,num-rows", &keypad_data->rows);
-	of_property_read_u32(np, "keypad,num-columns", &keypad_data->cols);
-	if (!keypad_data->rows || !keypad_data->cols) {
-		dev_err(dev, "number of keypad rows/columns not specified\n");
-		return -EINVAL;
-	}
+	err = matrix_keypad_parse_of_params(dev, &keypad_data->rows,
+					    &keypad_data->cols);
+	if (err)
+		return err;
 
 	if (of_get_property(np, "linux,input-no-autorepeat", NULL))
 		keypad_data->no_autorepeat = true;
diff --git a/drivers/input/keyboard/tca8418_keypad.c b/drivers/input/keyboard/tca8418_keypad.c
index a34cc67..55c1530 100644
--- a/drivers/input/keyboard/tca8418_keypad.c
+++ b/drivers/input/keyboard/tca8418_keypad.c
@@ -288,8 +288,11 @@ static int tca8418_keypad_probe(struct i2c_client *client,
 		irq_is_gpio = pdata->irq_is_gpio;
 	} else {
 		struct device_node *np = dev->of_node;
-		of_property_read_u32(np, "keypad,num-rows", &rows);
-		of_property_read_u32(np, "keypad,num-columns", &cols);
+		int err;
+
+		err = matrix_keypad_parse_of_params(dev, &rows, &cols);
+		if (err)
+			return err;
 		rep = of_property_read_bool(np, "keypad,autorepeat");
 	}
 
diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c
index 0e138eb..b46142f 100644
--- a/drivers/input/keyboard/tegra-kbc.c
+++ b/drivers/input/keyboard/tegra-kbc.c
@@ -27,17 +27,19 @@
 #include <linux/io.h>
 #include <linux/interrupt.h>
 #include <linux/of.h>
+#include <linux/of_device.h>
 #include <linux/clk.h>
 #include <linux/slab.h>
 #include <linux/input/matrix_keypad.h>
 #include <linux/clk/tegra.h>
+#include <linux/err.h>
 
-#define KBC_MAX_GPIO	24
 #define KBC_MAX_KPENT	8
 
-#define KBC_MAX_ROW	16
-#define KBC_MAX_COL	8
-#define KBC_MAX_KEY	(KBC_MAX_ROW * KBC_MAX_COL)
+/* Maximum row/column supported by Tegra KBC yet  is 16x8 */
+#define KBC_MAX_GPIO	24
+/* Maximum keys supported by Tegra KBC yet is 16 x 8*/
+#define KBC_MAX_KEY	(16 * 8)
 
 #define KBC_MAX_DEBOUNCE_CNT	0x3ffu
 
@@ -80,6 +82,12 @@ enum tegra_pin_type {
 	PIN_CFG_ROW,
 };
 
+/* Tegra KBC hw support */
+struct tegra_kbc_hw_support {
+	int max_rows;
+	int max_columns;
+};
+
 struct tegra_kbc_pin_cfg {
 	enum tegra_pin_type type;
 	unsigned char num;
@@ -108,6 +116,9 @@ struct tegra_kbc {
 	u32 wakeup_key;
 	struct timer_list timer;
 	struct clk *clk;
+	const struct tegra_kbc_hw_support *hw_support;
+	int max_keys;
+	int num_rows_and_columns;
 };
 
 static void tegra_kbc_report_released_keys(struct input_dev *input,
@@ -204,11 +215,11 @@ static void tegra_kbc_report_keys(struct tegra_kbc *kbc)
 
 	/*
 	 * If the platform uses Fn keymaps, translate keys on a Fn keypress.
-	 * Function keycodes are KBC_MAX_KEY apart from the plain keycodes.
+	 * Function keycodes are max_keys apart from the plain keycodes.
 	 */
 	if (fn_keypress) {
 		for (i = 0; i < num_down; i++) {
-			scancodes[i] += KBC_MAX_KEY;
+			scancodes[i] += kbc->max_keys;
 			keycodes[i] = kbc->keycode[scancodes[i]];
 		}
 	}
@@ -315,7 +326,7 @@ static void tegra_kbc_setup_wakekeys(struct tegra_kbc *kbc, bool filter)
 	/* Either mask all keys or none. */
 	rst_val = (filter && !kbc->wakeup) ? ~0 : 0;
 
-	for (i = 0; i < KBC_MAX_ROW; i++)
+	for (i = 0; i < kbc->hw_support->max_rows; i++)
 		writel(rst_val, kbc->mmio + KBC_ROW0_MASK_0 + i * 4);
 }
 
@@ -452,7 +463,7 @@ static bool tegra_kbc_check_pin_cfg(const struct tegra_kbc *kbc,
 
 		switch (pin_cfg->type) {
 		case PIN_CFG_ROW:
-			if (pin_cfg->num >= KBC_MAX_ROW) {
+			if (pin_cfg->num >= kbc->hw_support->max_rows) {
 				dev_err(kbc->dev,
 					"pin_cfg[%d]: invalid row number %d\n",
 					i, pin_cfg->num);
@@ -462,7 +473,7 @@ static bool tegra_kbc_check_pin_cfg(const struct tegra_kbc *kbc,
 			break;
 
 		case PIN_CFG_COL:
-			if (pin_cfg->num >= KBC_MAX_COL) {
+			if (pin_cfg->num >= kbc->hw_support->max_columns) {
 				dev_err(kbc->dev,
 					"pin_cfg[%d]: invalid column number %d\n",
 					i, pin_cfg->num);
@@ -520,6 +531,18 @@ static int tegra_kbc_parse_dt(struct tegra_kbc *kbc)
 	}
 	num_cols = proplen / sizeof(u32);
 
+	if (num_rows > kbc->hw_support->max_rows) {
+		dev_err(kbc->dev,
+			"Number of rows is more than supported by hardware\n");
+		return -EINVAL;
+	}
+
+	if (num_cols > kbc->hw_support->max_columns) {
+		dev_err(kbc->dev,
+			"Number of cols is more than supported by hardware\n");
+		return -EINVAL;
+	}
+
 	if (!of_get_property(np, "linux,keymap", &proplen)) {
 		dev_err(kbc->dev, "property linux,keymap not found\n");
 		return -ENOENT;
@@ -532,7 +555,7 @@ static int tegra_kbc_parse_dt(struct tegra_kbc *kbc)
 	}
 
 	/* Set all pins as non-configured */
-	for (i = 0; i < KBC_MAX_GPIO; i++)
+	for (i = 0; i < kbc->num_rows_and_columns; i++)
 		kbc->pin_cfg[i].type = PIN_CFG_IGNORE;
 
 	ret = of_property_read_u32_array(np, "nvidia,kbc-row-pins",
@@ -562,6 +585,24 @@ static int tegra_kbc_parse_dt(struct tegra_kbc *kbc)
 	return 0;
 }
 
+static const struct tegra_kbc_hw_support tegra20_kbc_hw_support = {
+	.max_rows	= 16,
+	.max_columns	= 8,
+};
+
+static const struct tegra_kbc_hw_support tegra11_kbc_hw_support = {
+	.max_rows	= 11,
+	.max_columns	= 8,
+};
+
+static const struct of_device_id tegra_kbc_of_match[] = {
+	{ .compatible = "nvidia,tegra114-kbc", .data = &tegra11_kbc_hw_support},
+	{ .compatible = "nvidia,tegra30-kbc", .data = &tegra20_kbc_hw_support},
+	{ .compatible = "nvidia,tegra20-kbc", .data = &tegra20_kbc_hw_support},
+	{ },
+};
+MODULE_DEVICE_TABLE(of, tegra_kbc_of_match);
+
 static int tegra_kbc_probe(struct platform_device *pdev)
 {
 	struct tegra_kbc *kbc;
@@ -570,7 +611,10 @@ static int tegra_kbc_probe(struct platform_device *pdev)
 	int num_rows = 0;
 	unsigned int debounce_cnt;
 	unsigned int scan_time_rows;
-	unsigned int keymap_rows = KBC_MAX_KEY;
+	unsigned int keymap_rows;
+	const struct of_device_id *match;
+
+	match = of_match_device(of_match_ptr(tegra_kbc_of_match), &pdev->dev);
 
 	kbc = devm_kzalloc(&pdev->dev, sizeof(*kbc), GFP_KERNEL);
 	if (!kbc) {
@@ -579,6 +623,12 @@ static int tegra_kbc_probe(struct platform_device *pdev)
 	}
 
 	kbc->dev = &pdev->dev;
+	kbc->hw_support = match->data;
+	kbc->max_keys = kbc->hw_support->max_rows *
+				kbc->hw_support->max_columns;
+	kbc->num_rows_and_columns = kbc->hw_support->max_rows +
+					kbc->hw_support->max_columns;
+	keymap_rows = kbc->max_keys;
 	spin_lock_init(&kbc->lock);
 
 	err = tegra_kbc_parse_dt(kbc);
@@ -608,11 +658,9 @@ static int tegra_kbc_probe(struct platform_device *pdev)
 
 	setup_timer(&kbc->timer, tegra_kbc_keypress_timer, (unsigned long)kbc);
 
-	kbc->mmio = devm_request_and_ioremap(&pdev->dev, res);
-	if (!kbc->mmio) {
-		dev_err(&pdev->dev, "Cannot request memregion/iomap address\n");
-		return -EBUSY;
-	}
+	kbc->mmio = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(kbc->mmio))
+		return PTR_ERR(kbc->mmio);
 
 	kbc->clk = devm_clk_get(&pdev->dev, NULL);
 	if (IS_ERR(kbc->clk)) {
@@ -641,7 +689,8 @@ static int tegra_kbc_probe(struct platform_device *pdev)
 		keymap_rows *= 2;
 
 	err = matrix_keypad_build_keymap(kbc->keymap_data, NULL,
-					 keymap_rows, KBC_MAX_COL,
+					 keymap_rows,
+					 kbc->hw_support->max_columns,
 					 kbc->keycode, kbc->idev);
 	if (err) {
 		dev_err(&pdev->dev, "failed to setup keymap\n");
@@ -767,12 +816,6 @@ static int tegra_kbc_resume(struct device *dev)
 
 static SIMPLE_DEV_PM_OPS(tegra_kbc_pm_ops, tegra_kbc_suspend, tegra_kbc_resume);
 
-static const struct of_device_id tegra_kbc_of_match[] = {
-	{ .compatible = "nvidia,tegra20-kbc", },
-	{ },
-};
-MODULE_DEVICE_TABLE(of, tegra_kbc_of_match);
-
 static struct platform_driver tegra_kbc_driver = {
 	.probe		= tegra_kbc_probe,
 	.driver	= {
diff --git a/drivers/input/matrix-keymap.c b/drivers/input/matrix-keymap.c
index 3ae496e..619b382 100644
--- a/drivers/input/matrix-keymap.c
+++ b/drivers/input/matrix-keymap.c
@@ -50,6 +50,25 @@ static bool matrix_keypad_map_key(struct input_dev *input_dev,
 }
 
 #ifdef CONFIG_OF
+int matrix_keypad_parse_of_params(struct device *dev,
+				  unsigned int *rows, unsigned int *cols)
+{
+	struct device_node *np = dev->of_node;
+
+	if (!np) {
+		dev_err(dev, "missing DT data");
+		return -EINVAL;
+	}
+	of_property_read_u32(np, "keypad,num-rows", rows);
+	of_property_read_u32(np, "keypad,num-columns", cols);
+	if (!*rows || !*cols) {
+		dev_err(dev, "number of keypad rows/columns not specified\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 static int matrix_keypad_parse_of_keymap(const char *propname,
 					 unsigned int rows, unsigned int cols,
 					 struct input_dev *input_dev)
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 259ef31..af80928 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -590,6 +590,16 @@ config INPUT_ADXL34X_SPI
 	  To compile this driver as a module, choose M here: the
 	  module will be called adxl34x-spi.
 
+config INPUT_IMS_PCU
+	tristate "IMS Passenger Control Unit driver"
+	depends on USB
+	depends on LEDS_CLASS
+	help
+	  Say Y here if you have system with IMS Rave Passenger Control Unit.
+
+	  To compile this driver as a module, choose M here: the module will be
+	  called ims_pcu.
+
 config INPUT_CMA3000
 	tristate "VTI CMA3000 Tri-axis accelerometer"
 	help
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index 1f1e1b1..d7fc17f 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -29,6 +29,7 @@ obj-$(CONFIG_INPUT_DM355EVM)		+= dm355evm_keys.o
 obj-$(CONFIG_INPUT_GP2A)		+= gp2ap002a00f.o
 obj-$(CONFIG_INPUT_GPIO_TILT_POLLED)	+= gpio_tilt_polled.o
 obj-$(CONFIG_HP_SDC_RTC)		+= hp_sdc_rtc.o
+obj-$(CONFIG_INPUT_IMS_PCU)		+= ims-pcu.o
 obj-$(CONFIG_INPUT_IXP4XX_BEEPER)	+= ixp4xx-beeper.o
 obj-$(CONFIG_INPUT_KEYSPAN_REMOTE)	+= keyspan_remote.o
 obj-$(CONFIG_INPUT_KXTJ9)		+= kxtj9.o
diff --git a/drivers/input/misc/ad714x-i2c.c b/drivers/input/misc/ad714x-i2c.c
index 29d2064..e0f5225 100644
--- a/drivers/input/misc/ad714x-i2c.c
+++ b/drivers/input/misc/ad714x-i2c.c
@@ -13,7 +13,7 @@
 #include <linux/pm.h>
 #include "ad714x.h"
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int ad714x_i2c_suspend(struct device *dev)
 {
 	return ad714x_disable(i2c_get_clientdata(to_i2c_client(dev)));
diff --git a/drivers/input/misc/ad714x-spi.c b/drivers/input/misc/ad714x-spi.c
index bdccca4..6189148 100644
--- a/drivers/input/misc/ad714x-spi.c
+++ b/drivers/input/misc/ad714x-spi.c
@@ -16,7 +16,7 @@
 #define AD714x_SPI_CMD_PREFIX      0xE000   /* bits 15:11 */
 #define AD714x_SPI_READ            BIT(10)
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int ad714x_spi_suspend(struct device *dev)
 {
 	return ad714x_disable(spi_get_drvdata(to_spi_device(dev)));
diff --git a/drivers/input/misc/adxl34x-i2c.c b/drivers/input/misc/adxl34x-i2c.c
index 535dda4..416f47d 100644
--- a/drivers/input/misc/adxl34x-i2c.c
+++ b/drivers/input/misc/adxl34x-i2c.c
@@ -105,7 +105,7 @@ static int adxl34x_i2c_remove(struct i2c_client *client)
 	return adxl34x_remove(ac);
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int adxl34x_i2c_suspend(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
diff --git a/drivers/input/misc/adxl34x-spi.c b/drivers/input/misc/adxl34x-spi.c
index ad5f40d..990b49e 100644
--- a/drivers/input/misc/adxl34x-spi.c
+++ b/drivers/input/misc/adxl34x-spi.c
@@ -94,7 +94,7 @@ static int adxl34x_spi_remove(struct spi_device *spi)
 	return adxl34x_remove(ac);
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int adxl34x_spi_suspend(struct device *dev)
 {
 	struct spi_device *spi = to_spi_device(dev);
diff --git a/drivers/input/misc/ims-pcu.c b/drivers/input/misc/ims-pcu.c
new file mode 100644
index 0000000..e204f26
--- /dev/null
+++ b/drivers/input/misc/ims-pcu.c
@@ -0,0 +1,1901 @@
+/*
+ * Driver for IMS Passenger Control Unit Devices
+ *
+ * Copyright (C) 2013 The IMS Company
+ *
+ * This program is free software; you can 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/completion.h>
+#include <linux/device.h>
+#include <linux/firmware.h>
+#include <linux/ihex.h>
+#include <linux/input.h>
+#include <linux/kernel.h>
+#include <linux/leds.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/usb/input.h>
+#include <linux/usb/cdc.h>
+#include <asm/unaligned.h>
+
+#define IMS_PCU_KEYMAP_LEN		32
+
+struct ims_pcu_buttons {
+	struct input_dev *input;
+	char name[32];
+	char phys[32];
+	unsigned short keymap[IMS_PCU_KEYMAP_LEN];
+};
+
+struct ims_pcu_gamepad {
+	struct input_dev *input;
+	char name[32];
+	char phys[32];
+};
+
+struct ims_pcu_backlight {
+	struct led_classdev cdev;
+	struct work_struct work;
+	enum led_brightness desired_brightness;
+	char name[32];
+};
+
+#define IMS_PCU_PART_NUMBER_LEN		15
+#define IMS_PCU_SERIAL_NUMBER_LEN	8
+#define IMS_PCU_DOM_LEN			8
+#define IMS_PCU_FW_VERSION_LEN		(9 + 1)
+#define IMS_PCU_BL_VERSION_LEN		(9 + 1)
+#define IMS_PCU_BL_RESET_REASON_LEN	(2 + 1)
+
+#define IMS_PCU_BUF_SIZE		128
+
+struct ims_pcu {
+	struct usb_device *udev;
+	struct device *dev; /* control interface's device, used for logging */
+
+	unsigned int device_no;
+
+	bool bootloader_mode;
+
+	char part_number[IMS_PCU_PART_NUMBER_LEN];
+	char serial_number[IMS_PCU_SERIAL_NUMBER_LEN];
+	char date_of_manufacturing[IMS_PCU_DOM_LEN];
+	char fw_version[IMS_PCU_FW_VERSION_LEN];
+	char bl_version[IMS_PCU_BL_VERSION_LEN];
+	char reset_reason[IMS_PCU_BL_RESET_REASON_LEN];
+	int update_firmware_status;
+
+	struct usb_interface *ctrl_intf;
+
+	struct usb_endpoint_descriptor *ep_ctrl;
+	struct urb *urb_ctrl;
+	u8 *urb_ctrl_buf;
+	dma_addr_t ctrl_dma;
+	size_t max_ctrl_size;
+
+	struct usb_interface *data_intf;
+
+	struct usb_endpoint_descriptor *ep_in;
+	struct urb *urb_in;
+	u8 *urb_in_buf;
+	dma_addr_t read_dma;
+	size_t max_in_size;
+
+	struct usb_endpoint_descriptor *ep_out;
+	u8 *urb_out_buf;
+	size_t max_out_size;
+
+	u8 read_buf[IMS_PCU_BUF_SIZE];
+	u8 read_pos;
+	u8 check_sum;
+	bool have_stx;
+	bool have_dle;
+
+	u8 cmd_buf[IMS_PCU_BUF_SIZE];
+	u8 ack_id;
+	u8 expected_response;
+	u8 cmd_buf_len;
+	struct completion cmd_done;
+	struct mutex cmd_mutex;
+
+	u32 fw_start_addr;
+	u32 fw_end_addr;
+	struct completion async_firmware_done;
+
+	struct ims_pcu_buttons buttons;
+	struct ims_pcu_gamepad *gamepad;
+	struct ims_pcu_backlight backlight;
+
+	bool setup_complete; /* Input and LED devices have been created */
+};
+
+
+/*********************************************************************
+ *             Buttons Input device support                          *
+ *********************************************************************/
+
+static const unsigned short ims_pcu_keymap_1[] = {
+	[1] = KEY_ATTENDANT_OFF,
+	[2] = KEY_ATTENDANT_ON,
+	[3] = KEY_LIGHTS_TOGGLE,
+	[4] = KEY_VOLUMEUP,
+	[5] = KEY_VOLUMEDOWN,
+	[6] = KEY_INFO,
+};
+
+static const unsigned short ims_pcu_keymap_2[] = {
+	[4] = KEY_VOLUMEUP,
+	[5] = KEY_VOLUMEDOWN,
+	[6] = KEY_INFO,
+};
+
+static const unsigned short ims_pcu_keymap_3[] = {
+	[1] = KEY_HOMEPAGE,
+	[2] = KEY_ATTENDANT_TOGGLE,
+	[3] = KEY_LIGHTS_TOGGLE,
+	[4] = KEY_VOLUMEUP,
+	[5] = KEY_VOLUMEDOWN,
+	[6] = KEY_DISPLAYTOGGLE,
+	[18] = KEY_PLAYPAUSE,
+};
+
+static const unsigned short ims_pcu_keymap_4[] = {
+	[1] = KEY_ATTENDANT_OFF,
+	[2] = KEY_ATTENDANT_ON,
+	[3] = KEY_LIGHTS_TOGGLE,
+	[4] = KEY_VOLUMEUP,
+	[5] = KEY_VOLUMEDOWN,
+	[6] = KEY_INFO,
+	[18] = KEY_PLAYPAUSE,
+};
+
+static const unsigned short ims_pcu_keymap_5[] = {
+	[1] = KEY_ATTENDANT_OFF,
+	[2] = KEY_ATTENDANT_ON,
+	[3] = KEY_LIGHTS_TOGGLE,
+};
+
+struct ims_pcu_device_info {
+	const unsigned short *keymap;
+	size_t keymap_len;
+	bool has_gamepad;
+};
+
+#define IMS_PCU_DEVINFO(_n, _gamepad)				\
+	[_n] = {						\
+		.keymap = ims_pcu_keymap_##_n,			\
+		.keymap_len = ARRAY_SIZE(ims_pcu_keymap_##_n),	\
+		.has_gamepad = _gamepad,			\
+	}
+
+static const struct ims_pcu_device_info ims_pcu_device_info[] = {
+	IMS_PCU_DEVINFO(1, true),
+	IMS_PCU_DEVINFO(2, true),
+	IMS_PCU_DEVINFO(3, true),
+	IMS_PCU_DEVINFO(4, true),
+	IMS_PCU_DEVINFO(5, false),
+};
+
+static void ims_pcu_buttons_report(struct ims_pcu *pcu, u32 data)
+{
+	struct ims_pcu_buttons *buttons = &pcu->buttons;
+	struct input_dev *input = buttons->input;
+	int i;
+
+	for (i = 0; i < 32; i++) {
+		unsigned short keycode = buttons->keymap[i];
+
+		if (keycode != KEY_RESERVED)
+			input_report_key(input, keycode, data & (1UL << i));
+	}
+
+	input_sync(input);
+}
+
+static int ims_pcu_setup_buttons(struct ims_pcu *pcu,
+				 const unsigned short *keymap,
+				 size_t keymap_len)
+{
+	struct ims_pcu_buttons *buttons = &pcu->buttons;
+	struct input_dev *input;
+	int i;
+	int error;
+
+	input = input_allocate_device();
+	if (!input) {
+		dev_err(pcu->dev,
+			"Not enough memory for input input device\n");
+		return -ENOMEM;
+	}
+
+	snprintf(buttons->name, sizeof(buttons->name),
+		 "IMS PCU#%d Button Interface", pcu->device_no);
+
+	usb_make_path(pcu->udev, buttons->phys, sizeof(buttons->phys));
+	strlcat(buttons->phys, "/input0", sizeof(buttons->phys));
+
+	memcpy(buttons->keymap, keymap, sizeof(*keymap) * keymap_len);
+
+	input->name = buttons->name;
+	input->phys = buttons->phys;
+	usb_to_input_id(pcu->udev, &input->id);
+	input->dev.parent = &pcu->ctrl_intf->dev;
+
+	input->keycode = buttons->keymap;
+	input->keycodemax = ARRAY_SIZE(buttons->keymap);
+	input->keycodesize = sizeof(buttons->keymap[0]);
+
+	__set_bit(EV_KEY, input->evbit);
+	for (i = 0; i < IMS_PCU_KEYMAP_LEN; i++)
+		__set_bit(buttons->keymap[i], input->keybit);
+	__clear_bit(KEY_RESERVED, input->keybit);
+
+	error = input_register_device(input);
+	if (error) {
+		dev_err(pcu->dev,
+			"Failed to register buttons input device: %d\n",
+			error);
+		input_free_device(input);
+		return error;
+	}
+
+	buttons->input = input;
+	return 0;
+}
+
+static void ims_pcu_destroy_buttons(struct ims_pcu *pcu)
+{
+	struct ims_pcu_buttons *buttons = &pcu->buttons;
+
+	input_unregister_device(buttons->input);
+}
+
+
+/*********************************************************************
+ *             Gamepad Input device support                          *
+ *********************************************************************/
+
+static void ims_pcu_gamepad_report(struct ims_pcu *pcu, u32 data)
+{
+	struct ims_pcu_gamepad *gamepad = pcu->gamepad;
+	struct input_dev *input = gamepad->input;
+	int x, y;
+
+	x = !!(data & (1 << 14)) - !!(data & (1 << 13));
+	y = !!(data & (1 << 12)) - !!(data & (1 << 11));
+
+	input_report_abs(input, ABS_X, x);
+	input_report_abs(input, ABS_Y, y);
+
+	input_report_key(input, BTN_A, data & (1 << 7));
+	input_report_key(input, BTN_B, data & (1 << 8));
+	input_report_key(input, BTN_X, data & (1 << 9));
+	input_report_key(input, BTN_Y, data & (1 << 10));
+	input_report_key(input, BTN_START, data & (1 << 15));
+	input_report_key(input, BTN_SELECT, data & (1 << 16));
+
+	input_sync(input);
+}
+
+static int ims_pcu_setup_gamepad(struct ims_pcu *pcu)
+{
+	struct ims_pcu_gamepad *gamepad;
+	struct input_dev *input;
+	int error;
+
+	gamepad = kzalloc(sizeof(struct ims_pcu_gamepad), GFP_KERNEL);
+	input = input_allocate_device();
+	if (!gamepad || !input) {
+		dev_err(pcu->dev,
+			"Not enough memory for gamepad device\n");
+		error = -ENOMEM;
+		goto err_free_mem;
+	}
+
+	gamepad->input = input;
+
+	snprintf(gamepad->name, sizeof(gamepad->name),
+		 "IMS PCU#%d Gamepad Interface", pcu->device_no);
+
+	usb_make_path(pcu->udev, gamepad->phys, sizeof(gamepad->phys));
+	strlcat(gamepad->phys, "/input1", sizeof(gamepad->phys));
+
+	input->name = gamepad->name;
+	input->phys = gamepad->phys;
+	usb_to_input_id(pcu->udev, &input->id);
+	input->dev.parent = &pcu->ctrl_intf->dev;
+
+	__set_bit(EV_KEY, input->evbit);
+	__set_bit(BTN_A, input->keybit);
+	__set_bit(BTN_B, input->keybit);
+	__set_bit(BTN_X, input->keybit);
+	__set_bit(BTN_Y, input->keybit);
+	__set_bit(BTN_START, input->keybit);
+	__set_bit(BTN_SELECT, input->keybit);
+
+	__set_bit(EV_ABS, input->evbit);
+	input_set_abs_params(input, ABS_X, -1, 1, 0, 0);
+	input_set_abs_params(input, ABS_Y, -1, 1, 0, 0);
+
+	error = input_register_device(input);
+	if (error) {
+		dev_err(pcu->dev,
+			"Failed to register gamepad input device: %d\n",
+			error);
+		goto err_free_mem;
+	}
+
+	pcu->gamepad = gamepad;
+	return 0;
+
+err_free_mem:
+	input_free_device(input);
+	kfree(gamepad);
+	return -ENOMEM;
+}
+
+static void ims_pcu_destroy_gamepad(struct ims_pcu *pcu)
+{
+	struct ims_pcu_gamepad *gamepad = pcu->gamepad;
+
+	input_unregister_device(gamepad->input);
+	kfree(gamepad);
+}
+
+
+/*********************************************************************
+ *             PCU Communication protocol handling                   *
+ *********************************************************************/
+
+#define IMS_PCU_PROTOCOL_STX		0x02
+#define IMS_PCU_PROTOCOL_ETX		0x03
+#define IMS_PCU_PROTOCOL_DLE		0x10
+
+/* PCU commands */
+#define IMS_PCU_CMD_STATUS		0xa0
+#define IMS_PCU_CMD_PCU_RESET		0xa1
+#define IMS_PCU_CMD_RESET_REASON	0xa2
+#define IMS_PCU_CMD_SEND_BUTTONS	0xa3
+#define IMS_PCU_CMD_JUMP_TO_BTLDR	0xa4
+#define IMS_PCU_CMD_GET_INFO		0xa5
+#define IMS_PCU_CMD_SET_BRIGHTNESS	0xa6
+#define IMS_PCU_CMD_EEPROM		0xa7
+#define IMS_PCU_CMD_GET_FW_VERSION	0xa8
+#define IMS_PCU_CMD_GET_BL_VERSION	0xa9
+#define IMS_PCU_CMD_SET_INFO		0xab
+#define IMS_PCU_CMD_GET_BRIGHTNESS	0xac
+#define IMS_PCU_CMD_GET_DEVICE_ID	0xae
+#define IMS_PCU_CMD_SPECIAL_INFO	0xb0
+#define IMS_PCU_CMD_BOOTLOADER		0xb1	/* Pass data to bootloader */
+
+/* PCU responses */
+#define IMS_PCU_RSP_STATUS		0xc0
+#define IMS_PCU_RSP_PCU_RESET		0	/* Originally 0xc1 */
+#define IMS_PCU_RSP_RESET_REASON	0xc2
+#define IMS_PCU_RSP_SEND_BUTTONS	0xc3
+#define IMS_PCU_RSP_JUMP_TO_BTLDR	0	/* Originally 0xc4 */
+#define IMS_PCU_RSP_GET_INFO		0xc5
+#define IMS_PCU_RSP_SET_BRIGHTNESS	0xc6
+#define IMS_PCU_RSP_EEPROM		0xc7
+#define IMS_PCU_RSP_GET_FW_VERSION	0xc8
+#define IMS_PCU_RSP_GET_BL_VERSION	0xc9
+#define IMS_PCU_RSP_SET_INFO		0xcb
+#define IMS_PCU_RSP_GET_BRIGHTNESS	0xcc
+#define IMS_PCU_RSP_CMD_INVALID		0xcd
+#define IMS_PCU_RSP_GET_DEVICE_ID	0xce
+#define IMS_PCU_RSP_SPECIAL_INFO	0xd0
+#define IMS_PCU_RSP_BOOTLOADER		0xd1	/* Bootloader response */
+
+#define IMS_PCU_RSP_EVNT_BUTTONS	0xe0	/* Unsolicited, button state */
+#define IMS_PCU_GAMEPAD_MASK		0x0001ff80UL	/* Bits 7 through 16 */
+
+
+#define IMS_PCU_MIN_PACKET_LEN		3
+#define IMS_PCU_DATA_OFFSET		2
+
+#define IMS_PCU_CMD_WRITE_TIMEOUT	100 /* msec */
+#define IMS_PCU_CMD_RESPONSE_TIMEOUT	500 /* msec */
+
+static void ims_pcu_report_events(struct ims_pcu *pcu)
+{
+	u32 data = get_unaligned_be32(&pcu->read_buf[3]);
+
+	ims_pcu_buttons_report(pcu, data & ~IMS_PCU_GAMEPAD_MASK);
+	if (pcu->gamepad)
+		ims_pcu_gamepad_report(pcu, data);
+}
+
+static void ims_pcu_handle_response(struct ims_pcu *pcu)
+{
+	switch (pcu->read_buf[0]) {
+	case IMS_PCU_RSP_EVNT_BUTTONS:
+		if (likely(pcu->setup_complete))
+			ims_pcu_report_events(pcu);
+		break;
+
+	default:
+		/*
+		 * See if we got command completion.
+		 * If both the sequence and response code match save
+		 * the data and signal completion.
+		 */
+		if (pcu->read_buf[0] == pcu->expected_response &&
+		    pcu->read_buf[1] == pcu->ack_id - 1) {
+
+			memcpy(pcu->cmd_buf, pcu->read_buf, pcu->read_pos);
+			pcu->cmd_buf_len = pcu->read_pos;
+			complete(&pcu->cmd_done);
+		}
+		break;
+	}
+}
+
+static void ims_pcu_process_data(struct ims_pcu *pcu, struct urb *urb)
+{
+	int i;
+
+	for (i = 0; i < urb->actual_length; i++) {
+		u8 data = pcu->urb_in_buf[i];
+
+		/* Skip everything until we get Start Xmit */
+		if (!pcu->have_stx && data != IMS_PCU_PROTOCOL_STX)
+			continue;
+
+		if (pcu->have_dle) {
+			pcu->have_dle = false;
+			pcu->read_buf[pcu->read_pos++] = data;
+			pcu->check_sum += data;
+			continue;
+		}
+
+		switch (data) {
+		case IMS_PCU_PROTOCOL_STX:
+			if (pcu->have_stx)
+				dev_warn(pcu->dev,
+					 "Unexpected STX at byte %d, discarding old data\n",
+					 pcu->read_pos);
+			pcu->have_stx = true;
+			pcu->have_dle = false;
+			pcu->read_pos = 0;
+			pcu->check_sum = 0;
+			break;
+
+		case IMS_PCU_PROTOCOL_DLE:
+			pcu->have_dle = true;
+			break;
+
+		case IMS_PCU_PROTOCOL_ETX:
+			if (pcu->read_pos < IMS_PCU_MIN_PACKET_LEN) {
+				dev_warn(pcu->dev,
+					 "Short packet received (%d bytes), ignoring\n",
+					 pcu->read_pos);
+			} else if (pcu->check_sum != 0) {
+				dev_warn(pcu->dev,
+					 "Invalid checksum in packet (%d bytes), ignoring\n",
+					 pcu->read_pos);
+			} else {
+				ims_pcu_handle_response(pcu);
+			}
+
+			pcu->have_stx = false;
+			pcu->have_dle = false;
+			pcu->read_pos = 0;
+			break;
+
+		default:
+			pcu->read_buf[pcu->read_pos++] = data;
+			pcu->check_sum += data;
+			break;
+		}
+	}
+}
+
+static bool ims_pcu_byte_needs_escape(u8 byte)
+{
+	return byte == IMS_PCU_PROTOCOL_STX ||
+	       byte == IMS_PCU_PROTOCOL_ETX ||
+	       byte == IMS_PCU_PROTOCOL_DLE;
+}
+
+static int ims_pcu_send_cmd_chunk(struct ims_pcu *pcu,
+				  u8 command, int chunk, int len)
+{
+	int error;
+
+	error = usb_bulk_msg(pcu->udev,
+			     usb_sndbulkpipe(pcu->udev,
+					     pcu->ep_out->bEndpointAddress),
+			     pcu->urb_out_buf, len,
+			     NULL, IMS_PCU_CMD_WRITE_TIMEOUT);
+	if (error < 0) {
+		dev_dbg(pcu->dev,
+			"Sending 0x%02x command failed at chunk %d: %d\n",
+			command, chunk, error);
+		return error;
+	}
+
+	return 0;
+}
+
+static int ims_pcu_send_command(struct ims_pcu *pcu,
+				u8 command, const u8 *data, int len)
+{
+	int count = 0;
+	int chunk = 0;
+	int delta;
+	int i;
+	int error;
+	u8 csum = 0;
+	u8 ack_id;
+
+	pcu->urb_out_buf[count++] = IMS_PCU_PROTOCOL_STX;
+
+	/* We know the command need not be escaped */
+	pcu->urb_out_buf[count++] = command;
+	csum += command;
+
+	ack_id = pcu->ack_id++;
+	if (ack_id == 0xff)
+		ack_id = pcu->ack_id++;
+
+	if (ims_pcu_byte_needs_escape(ack_id))
+		pcu->urb_out_buf[count++] = IMS_PCU_PROTOCOL_DLE;
+
+	pcu->urb_out_buf[count++] = ack_id;
+	csum += ack_id;
+
+	for (i = 0; i < len; i++) {
+
+		delta = ims_pcu_byte_needs_escape(data[i]) ? 2 : 1;
+		if (count + delta >= pcu->max_out_size) {
+			error = ims_pcu_send_cmd_chunk(pcu, command,
+						       ++chunk, count);
+			if (error)
+				return error;
+
+			count = 0;
+		}
+
+		if (delta == 2)
+			pcu->urb_out_buf[count++] = IMS_PCU_PROTOCOL_DLE;
+
+		pcu->urb_out_buf[count++] = data[i];
+		csum += data[i];
+	}
+
+	csum = 1 + ~csum;
+
+	delta = ims_pcu_byte_needs_escape(csum) ? 3 : 2;
+	if (count + delta >= pcu->max_out_size) {
+		error = ims_pcu_send_cmd_chunk(pcu, command, ++chunk, count);
+		if (error)
+			return error;
+
+		count = 0;
+	}
+
+	if (delta == 3)
+		pcu->urb_out_buf[count++] = IMS_PCU_PROTOCOL_DLE;
+
+	pcu->urb_out_buf[count++] = csum;
+	pcu->urb_out_buf[count++] = IMS_PCU_PROTOCOL_ETX;
+
+	return ims_pcu_send_cmd_chunk(pcu, command, ++chunk, count);
+}
+
+static int __ims_pcu_execute_command(struct ims_pcu *pcu,
+				     u8 command, const void *data, size_t len,
+				     u8 expected_response, int response_time)
+{
+	int error;
+
+	pcu->expected_response = expected_response;
+	init_completion(&pcu->cmd_done);
+
+	error = ims_pcu_send_command(pcu, command, data, len);
+	if (error)
+		return error;
+
+	if (expected_response &&
+	    !wait_for_completion_timeout(&pcu->cmd_done,
+					 msecs_to_jiffies(response_time))) {
+		dev_dbg(pcu->dev, "Command 0x%02x timed out\n", command);
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
+#define ims_pcu_execute_command(pcu, code, data, len)			\
+	__ims_pcu_execute_command(pcu,					\
+				  IMS_PCU_CMD_##code, data, len,	\
+				  IMS_PCU_RSP_##code,			\
+				  IMS_PCU_CMD_RESPONSE_TIMEOUT)
+
+#define ims_pcu_execute_query(pcu, code)				\
+	ims_pcu_execute_command(pcu, code, NULL, 0)
+
+/* Bootloader commands */
+#define IMS_PCU_BL_CMD_QUERY_DEVICE	0xa1
+#define IMS_PCU_BL_CMD_UNLOCK_CONFIG	0xa2
+#define IMS_PCU_BL_CMD_ERASE_APP	0xa3
+#define IMS_PCU_BL_CMD_PROGRAM_DEVICE	0xa4
+#define IMS_PCU_BL_CMD_PROGRAM_COMPLETE	0xa5
+#define IMS_PCU_BL_CMD_READ_APP		0xa6
+#define IMS_PCU_BL_CMD_RESET_DEVICE	0xa7
+#define IMS_PCU_BL_CMD_LAUNCH_APP	0xa8
+
+/* Bootloader commands */
+#define IMS_PCU_BL_RSP_QUERY_DEVICE	0xc1
+#define IMS_PCU_BL_RSP_UNLOCK_CONFIG	0xc2
+#define IMS_PCU_BL_RSP_ERASE_APP	0xc3
+#define IMS_PCU_BL_RSP_PROGRAM_DEVICE	0xc4
+#define IMS_PCU_BL_RSP_PROGRAM_COMPLETE	0xc5
+#define IMS_PCU_BL_RSP_READ_APP		0xc6
+#define IMS_PCU_BL_RSP_RESET_DEVICE	0	/* originally 0xa7 */
+#define IMS_PCU_BL_RSP_LAUNCH_APP	0	/* originally 0xa8 */
+
+#define IMS_PCU_BL_DATA_OFFSET		3
+
+static int __ims_pcu_execute_bl_command(struct ims_pcu *pcu,
+				        u8 command, const void *data, size_t len,
+				        u8 expected_response, int response_time)
+{
+	int error;
+
+	pcu->cmd_buf[0] = command;
+	if (data)
+		memcpy(&pcu->cmd_buf[1], data, len);
+
+	error = __ims_pcu_execute_command(pcu,
+				IMS_PCU_CMD_BOOTLOADER, pcu->cmd_buf, len + 1,
+				expected_response ? IMS_PCU_RSP_BOOTLOADER : 0,
+				response_time);
+	if (error) {
+		dev_err(pcu->dev,
+			"Failure when sending 0x%02x command to bootloader, error: %d\n",
+			pcu->cmd_buf[0], error);
+		return error;
+	}
+
+	if (expected_response && pcu->cmd_buf[2] != expected_response) {
+		dev_err(pcu->dev,
+			"Unexpected response from bootloader: 0x%02x, wanted 0x%02x\n",
+			pcu->cmd_buf[2], expected_response);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+#define ims_pcu_execute_bl_command(pcu, code, data, len, timeout)	\
+	__ims_pcu_execute_bl_command(pcu,				\
+				     IMS_PCU_BL_CMD_##code, data, len,	\
+				     IMS_PCU_BL_RSP_##code, timeout)	\
+
+#define IMS_PCU_INFO_PART_OFFSET	2
+#define IMS_PCU_INFO_DOM_OFFSET		17
+#define IMS_PCU_INFO_SERIAL_OFFSET	25
+
+#define IMS_PCU_SET_INFO_SIZE		31
+
+static int ims_pcu_get_info(struct ims_pcu *pcu)
+{
+	int error;
+
+	error = ims_pcu_execute_query(pcu, GET_INFO);
+	if (error) {
+		dev_err(pcu->dev,
+			"GET_INFO command failed, error: %d\n", error);
+		return error;
+	}
+
+	memcpy(pcu->part_number,
+	       &pcu->cmd_buf[IMS_PCU_INFO_PART_OFFSET],
+	       sizeof(pcu->part_number));
+	memcpy(pcu->date_of_manufacturing,
+	       &pcu->cmd_buf[IMS_PCU_INFO_DOM_OFFSET],
+	       sizeof(pcu->date_of_manufacturing));
+	memcpy(pcu->serial_number,
+	       &pcu->cmd_buf[IMS_PCU_INFO_SERIAL_OFFSET],
+	       sizeof(pcu->serial_number));
+
+	return 0;
+}
+
+static int ims_pcu_set_info(struct ims_pcu *pcu)
+{
+	int error;
+
+	memcpy(&pcu->cmd_buf[IMS_PCU_INFO_PART_OFFSET],
+	       pcu->part_number, sizeof(pcu->part_number));
+	memcpy(&pcu->cmd_buf[IMS_PCU_INFO_DOM_OFFSET],
+	       pcu->date_of_manufacturing, sizeof(pcu->date_of_manufacturing));
+	memcpy(&pcu->cmd_buf[IMS_PCU_INFO_SERIAL_OFFSET],
+	       pcu->serial_number, sizeof(pcu->serial_number));
+
+	error = ims_pcu_execute_command(pcu, SET_INFO,
+					&pcu->cmd_buf[IMS_PCU_DATA_OFFSET],
+					IMS_PCU_SET_INFO_SIZE);
+	if (error) {
+		dev_err(pcu->dev,
+			"Failed to update device information, error: %d\n",
+			error);
+		return error;
+	}
+
+	return 0;
+}
+
+static int ims_pcu_switch_to_bootloader(struct ims_pcu *pcu)
+{
+	int error;
+
+	/* Execute jump to the bootoloader */
+	error = ims_pcu_execute_command(pcu, JUMP_TO_BTLDR, NULL, 0);
+	if (error) {
+		dev_err(pcu->dev,
+			"Failure when sending JUMP TO BOOLTLOADER command, error: %d\n",
+			error);
+		return error;
+	}
+
+	return 0;
+}
+
+/*********************************************************************
+ *             Firmware Update handling                              *
+ *********************************************************************/
+
+#define IMS_PCU_FIRMWARE_NAME	"imspcu.fw"
+
+struct ims_pcu_flash_fmt {
+	__le32 addr;
+	u8 len;
+	u8 data[];
+};
+
+static unsigned int ims_pcu_count_fw_records(const struct firmware *fw)
+{
+	const struct ihex_binrec *rec = (const struct ihex_binrec *)fw->data;
+	unsigned int count = 0;
+
+	while (rec) {
+		count++;
+		rec = ihex_next_binrec(rec);
+	}
+
+	return count;
+}
+
+static int ims_pcu_verify_block(struct ims_pcu *pcu,
+				u32 addr, u8 len, const u8 *data)
+{
+	struct ims_pcu_flash_fmt *fragment;
+	int error;
+
+	fragment = (void *)&pcu->cmd_buf[1];
+	put_unaligned_le32(addr, &fragment->addr);
+	fragment->len = len;
+
+	error = ims_pcu_execute_bl_command(pcu, READ_APP, NULL, 5,
+					IMS_PCU_CMD_RESPONSE_TIMEOUT);
+	if (error) {
+		dev_err(pcu->dev,
+			"Failed to retrieve block at 0x%08x, len %d, error: %d\n",
+			addr, len, error);
+		return error;
+	}
+
+	fragment = (void *)&pcu->cmd_buf[IMS_PCU_BL_DATA_OFFSET];
+	if (get_unaligned_le32(&fragment->addr) != addr ||
+	    fragment->len != len) {
+		dev_err(pcu->dev,
+			"Wrong block when retrieving 0x%08x (0x%08x), len %d (%d)\n",
+			addr, get_unaligned_le32(&fragment->addr),
+			len, fragment->len);
+		return -EINVAL;
+	}
+
+	if (memcmp(fragment->data, data, len)) {
+		dev_err(pcu->dev,
+			"Mismatch in block at 0x%08x, len %d\n",
+			addr, len);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int ims_pcu_flash_firmware(struct ims_pcu *pcu,
+				  const struct firmware *fw,
+				  unsigned int n_fw_records)
+{
+	const struct ihex_binrec *rec = (const struct ihex_binrec *)fw->data;
+	struct ims_pcu_flash_fmt *fragment;
+	unsigned int count = 0;
+	u32 addr;
+	u8 len;
+	int error;
+
+	error = ims_pcu_execute_bl_command(pcu, ERASE_APP, NULL, 0, 2000);
+	if (error) {
+		dev_err(pcu->dev,
+			"Failed to erase application image, error: %d\n",
+			error);
+		return error;
+	}
+
+	while (rec) {
+		/*
+		 * The firmware format is messed up for some reason.
+		 * The address twice that of what is needed for some
+		 * reason and we end up overwriting half of the data
+		 * with the next record.
+		 */
+		addr = be32_to_cpu(rec->addr) / 2;
+		len = be16_to_cpu(rec->len);
+
+		fragment = (void *)&pcu->cmd_buf[1];
+		put_unaligned_le32(addr, &fragment->addr);
+		fragment->len = len;
+		memcpy(fragment->data, rec->data, len);
+
+		error = ims_pcu_execute_bl_command(pcu, PROGRAM_DEVICE,
+						NULL, len + 5,
+						IMS_PCU_CMD_RESPONSE_TIMEOUT);
+		if (error) {
+			dev_err(pcu->dev,
+				"Failed to write block at 0x%08x, len %d, error: %d\n",
+				addr, len, error);
+			return error;
+		}
+
+		if (addr >= pcu->fw_start_addr && addr < pcu->fw_end_addr) {
+			error = ims_pcu_verify_block(pcu, addr, len, rec->data);
+			if (error)
+				return error;
+		}
+
+		count++;
+		pcu->update_firmware_status = (count * 100) / n_fw_records;
+
+		rec = ihex_next_binrec(rec);
+	}
+
+	error = ims_pcu_execute_bl_command(pcu, PROGRAM_COMPLETE,
+					    NULL, 0, 2000);
+	if (error)
+		dev_err(pcu->dev,
+			"Failed to send PROGRAM_COMPLETE, error: %d\n",
+			error);
+
+	return 0;
+}
+
+static int ims_pcu_handle_firmware_update(struct ims_pcu *pcu,
+					  const struct firmware *fw)
+{
+	unsigned int n_fw_records;
+	int retval;
+
+	dev_info(pcu->dev, "Updating firmware %s, size: %zu\n",
+		 IMS_PCU_FIRMWARE_NAME, fw->size);
+
+	n_fw_records = ims_pcu_count_fw_records(fw);
+
+	retval = ims_pcu_flash_firmware(pcu, fw, n_fw_records);
+	if (retval)
+		goto out;
+
+	retval = ims_pcu_execute_bl_command(pcu, LAUNCH_APP, NULL, 0, 0);
+	if (retval)
+		dev_err(pcu->dev,
+			"Failed to start application image, error: %d\n",
+			retval);
+
+out:
+	pcu->update_firmware_status = retval;
+	sysfs_notify(&pcu->dev->kobj, NULL, "update_firmware_status");
+	return retval;
+}
+
+static void ims_pcu_process_async_firmware(const struct firmware *fw,
+					   void *context)
+{
+	struct ims_pcu *pcu = context;
+	int error;
+
+	if (!fw) {
+		dev_err(pcu->dev, "Failed to get firmware %s\n",
+			IMS_PCU_FIRMWARE_NAME);
+		goto out;
+	}
+
+	error = ihex_validate_fw(fw);
+	if (error) {
+		dev_err(pcu->dev, "Firmware %s is invalid\n",
+			IMS_PCU_FIRMWARE_NAME);
+		goto out;
+	}
+
+	mutex_lock(&pcu->cmd_mutex);
+	ims_pcu_handle_firmware_update(pcu, fw);
+	mutex_unlock(&pcu->cmd_mutex);
+
+	release_firmware(fw);
+
+out:
+	complete(&pcu->async_firmware_done);
+}
+
+/*********************************************************************
+ *             Backlight LED device support                          *
+ *********************************************************************/
+
+#define IMS_PCU_MAX_BRIGHTNESS		31998
+
+static void ims_pcu_backlight_work(struct work_struct *work)
+{
+	struct ims_pcu_backlight *backlight =
+			container_of(work, struct ims_pcu_backlight, work);
+	struct ims_pcu *pcu =
+			container_of(backlight, struct ims_pcu, backlight);
+	int desired_brightness = backlight->desired_brightness;
+	__le16 br_val = cpu_to_le16(desired_brightness);
+	int error;
+
+	mutex_lock(&pcu->cmd_mutex);
+
+	error = ims_pcu_execute_command(pcu, SET_BRIGHTNESS,
+					&br_val, sizeof(br_val));
+	if (error && error != -ENODEV)
+		dev_warn(pcu->dev,
+			 "Failed to set desired brightness %u, error: %d\n",
+			 desired_brightness, error);
+
+	mutex_unlock(&pcu->cmd_mutex);
+}
+
+static void ims_pcu_backlight_set_brightness(struct led_classdev *cdev,
+					     enum led_brightness value)
+{
+	struct ims_pcu_backlight *backlight =
+			container_of(cdev, struct ims_pcu_backlight, cdev);
+
+	backlight->desired_brightness = value;
+	schedule_work(&backlight->work);
+}
+
+static enum led_brightness
+ims_pcu_backlight_get_brightness(struct led_classdev *cdev)
+{
+	struct ims_pcu_backlight *backlight =
+			container_of(cdev, struct ims_pcu_backlight, cdev);
+	struct ims_pcu *pcu =
+			container_of(backlight, struct ims_pcu, backlight);
+	int brightness;
+	int error;
+
+	mutex_lock(&pcu->cmd_mutex);
+
+	error = ims_pcu_execute_query(pcu, GET_BRIGHTNESS);
+	if (error) {
+		dev_warn(pcu->dev,
+			 "Failed to get current brightness, error: %d\n",
+			 error);
+		/* Assume the LED is OFF */
+		brightness = LED_OFF;
+	} else {
+		brightness =
+			get_unaligned_le16(&pcu->cmd_buf[IMS_PCU_DATA_OFFSET]);
+	}
+
+	mutex_unlock(&pcu->cmd_mutex);
+
+	return brightness;
+}
+
+static int ims_pcu_setup_backlight(struct ims_pcu *pcu)
+{
+	struct ims_pcu_backlight *backlight = &pcu->backlight;
+	int error;
+
+	INIT_WORK(&backlight->work, ims_pcu_backlight_work);
+	snprintf(backlight->name, sizeof(backlight->name),
+		 "pcu%d::kbd_backlight", pcu->device_no);
+
+	backlight->cdev.name = backlight->name;
+	backlight->cdev.max_brightness = IMS_PCU_MAX_BRIGHTNESS;
+	backlight->cdev.brightness_get = ims_pcu_backlight_get_brightness;
+	backlight->cdev.brightness_set = ims_pcu_backlight_set_brightness;
+
+	error = led_classdev_register(pcu->dev, &backlight->cdev);
+	if (error) {
+		dev_err(pcu->dev,
+			"Failed to register backlight LED device, error: %d\n",
+			error);
+		return error;
+	}
+
+	return 0;
+}
+
+static void ims_pcu_destroy_backlight(struct ims_pcu *pcu)
+{
+	struct ims_pcu_backlight *backlight = &pcu->backlight;
+
+	led_classdev_unregister(&backlight->cdev);
+	cancel_work_sync(&backlight->work);
+}
+
+
+/*********************************************************************
+ *             Sysfs attributes handling                             *
+ *********************************************************************/
+
+struct ims_pcu_attribute {
+	struct device_attribute dattr;
+	size_t field_offset;
+	int field_length;
+};
+
+static ssize_t ims_pcu_attribute_show(struct device *dev,
+				      struct device_attribute *dattr,
+				      char *buf)
+{
+	struct usb_interface *intf = to_usb_interface(dev);
+	struct ims_pcu *pcu = usb_get_intfdata(intf);
+	struct ims_pcu_attribute *attr =
+			container_of(dattr, struct ims_pcu_attribute, dattr);
+	char *field = (char *)pcu + attr->field_offset;
+
+	return scnprintf(buf, PAGE_SIZE, "%.*s\n", attr->field_length, field);
+}
+
+static ssize_t ims_pcu_attribute_store(struct device *dev,
+				       struct device_attribute *dattr,
+				       const char *buf, size_t count)
+{
+
+	struct usb_interface *intf = to_usb_interface(dev);
+	struct ims_pcu *pcu = usb_get_intfdata(intf);
+	struct ims_pcu_attribute *attr =
+			container_of(dattr, struct ims_pcu_attribute, dattr);
+	char *field = (char *)pcu + attr->field_offset;
+	size_t data_len;
+	int error;
+
+	if (count > attr->field_length)
+		return -EINVAL;
+
+	data_len = strnlen(buf, attr->field_length);
+	if (data_len > attr->field_length)
+		return -EINVAL;
+
+	error = mutex_lock_interruptible(&pcu->cmd_mutex);
+	if (error)
+		return error;
+
+	memset(field, 0, attr->field_length);
+	memcpy(field, buf, data_len);
+
+	error = ims_pcu_set_info(pcu);
+
+	/*
+	 * Even if update failed, let's fetch the info again as we just
+	 * clobbered one of the fields.
+	 */
+	ims_pcu_get_info(pcu);
+
+	mutex_unlock(&pcu->cmd_mutex);
+
+	return error < 0 ? error : count;
+}
+
+#define IMS_PCU_ATTR(_field, _mode)					\
+struct ims_pcu_attribute ims_pcu_attr_##_field = {			\
+	.dattr = __ATTR(_field, _mode,					\
+			ims_pcu_attribute_show,				\
+			ims_pcu_attribute_store),			\
+	.field_offset = offsetof(struct ims_pcu, _field),		\
+	.field_length = sizeof(((struct ims_pcu *)NULL)->_field),	\
+}
+
+#define IMS_PCU_RO_ATTR(_field)						\
+		IMS_PCU_ATTR(_field, S_IRUGO)
+#define IMS_PCU_RW_ATTR(_field)						\
+		IMS_PCU_ATTR(_field, S_IRUGO | S_IWUSR)
+
+static IMS_PCU_RW_ATTR(part_number);
+static IMS_PCU_RW_ATTR(serial_number);
+static IMS_PCU_RW_ATTR(date_of_manufacturing);
+
+static IMS_PCU_RO_ATTR(fw_version);
+static IMS_PCU_RO_ATTR(bl_version);
+static IMS_PCU_RO_ATTR(reset_reason);
+
+static ssize_t ims_pcu_reset_device(struct device *dev,
+				    struct device_attribute *dattr,
+				    const char *buf, size_t count)
+{
+	static const u8 reset_byte = 1;
+	struct usb_interface *intf = to_usb_interface(dev);
+	struct ims_pcu *pcu = usb_get_intfdata(intf);
+	int value;
+	int error;
+
+	error = kstrtoint(buf, 0, &value);
+	if (error)
+		return error;
+
+	if (value != 1)
+		return -EINVAL;
+
+	dev_info(pcu->dev, "Attempting to reset device\n");
+
+	error = ims_pcu_execute_command(pcu, PCU_RESET, &reset_byte, 1);
+	if (error) {
+		dev_info(pcu->dev,
+			 "Failed to reset device, error: %d\n",
+			 error);
+		return error;
+	}
+
+	return count;
+}
+
+static DEVICE_ATTR(reset_device, S_IWUSR, NULL, ims_pcu_reset_device);
+
+static ssize_t ims_pcu_update_firmware_store(struct device *dev,
+					     struct device_attribute *dattr,
+					     const char *buf, size_t count)
+{
+	struct usb_interface *intf = to_usb_interface(dev);
+	struct ims_pcu *pcu = usb_get_intfdata(intf);
+	const struct firmware *fw = NULL;
+	int value;
+	int error;
+
+	error = kstrtoint(buf, 0, &value);
+	if (error)
+		return error;
+
+	if (value != 1)
+		return -EINVAL;
+
+	error = mutex_lock_interruptible(&pcu->cmd_mutex);
+	if (error)
+		return error;
+
+	error = request_ihex_firmware(&fw, IMS_PCU_FIRMWARE_NAME, pcu->dev);
+	if (error) {
+		dev_err(pcu->dev, "Failed to request firmware %s, error: %d\n",
+			IMS_PCU_FIRMWARE_NAME, error);
+		goto out;
+	}
+
+	/*
+	 * If we are already in bootloader mode we can proceed with
+	 * flashing the firmware.
+	 *
+	 * If we are in application mode, then we need to switch into
+	 * bootloader mode, which will cause the device to disconnect
+	 * and reconnect as different device.
+	 */
+	if (pcu->bootloader_mode)
+		error = ims_pcu_handle_firmware_update(pcu, fw);
+	else
+		error = ims_pcu_switch_to_bootloader(pcu);
+
+	release_firmware(fw);
+
+out:
+	mutex_unlock(&pcu->cmd_mutex);
+	return error ?: count;
+}
+
+static DEVICE_ATTR(update_firmware, S_IWUSR,
+		   NULL, ims_pcu_update_firmware_store);
+
+static ssize_t
+ims_pcu_update_firmware_status_show(struct device *dev,
+				    struct device_attribute *dattr,
+				    char *buf)
+{
+	struct usb_interface *intf = to_usb_interface(dev);
+	struct ims_pcu *pcu = usb_get_intfdata(intf);
+
+	return scnprintf(buf, PAGE_SIZE, "%d\n", pcu->update_firmware_status);
+}
+
+static DEVICE_ATTR(update_firmware_status, S_IRUGO,
+		   ims_pcu_update_firmware_status_show, NULL);
+
+static struct attribute *ims_pcu_attrs[] = {
+	&ims_pcu_attr_part_number.dattr.attr,
+	&ims_pcu_attr_serial_number.dattr.attr,
+	&ims_pcu_attr_date_of_manufacturing.dattr.attr,
+	&ims_pcu_attr_fw_version.dattr.attr,
+	&ims_pcu_attr_bl_version.dattr.attr,
+	&ims_pcu_attr_reset_reason.dattr.attr,
+	&dev_attr_reset_device.attr,
+	&dev_attr_update_firmware.attr,
+	&dev_attr_update_firmware_status.attr,
+	NULL
+};
+
+static umode_t ims_pcu_is_attr_visible(struct kobject *kobj,
+				       struct attribute *attr, int n)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct usb_interface *intf = to_usb_interface(dev);
+	struct ims_pcu *pcu = usb_get_intfdata(intf);
+	umode_t mode = attr->mode;
+
+	if (pcu->bootloader_mode) {
+		if (attr != &dev_attr_update_firmware_status.attr &&
+		    attr != &dev_attr_update_firmware.attr &&
+		    attr != &dev_attr_reset_device.attr) {
+			mode = 0;
+		}
+	} else {
+		if (attr == &dev_attr_update_firmware_status.attr)
+			mode = 0;
+	}
+
+	return mode;
+}
+
+static struct attribute_group ims_pcu_attr_group = {
+	.is_visible	= ims_pcu_is_attr_visible,
+	.attrs		= ims_pcu_attrs,
+};
+
+static void ims_pcu_irq(struct urb *urb)
+{
+	struct ims_pcu *pcu = urb->context;
+	int retval, status;
+
+	status = urb->status;
+
+	switch (status) {
+	case 0:
+		/* success */
+		break;
+	case -ECONNRESET:
+	case -ENOENT:
+	case -ESHUTDOWN:
+		/* this urb is terminated, clean up */
+		dev_dbg(pcu->dev, "%s - urb shutting down with status: %d\n",
+			__func__, status);
+		return;
+	default:
+		dev_dbg(pcu->dev, "%s - nonzero urb status received: %d\n",
+			__func__, status);
+		goto exit;
+	}
+
+	dev_dbg(pcu->dev, "%s: received %d: %*ph\n", __func__,
+		urb->actual_length, urb->actual_length, pcu->urb_in_buf);
+
+	if (urb == pcu->urb_in)
+		ims_pcu_process_data(pcu, urb);
+
+exit:
+	retval = usb_submit_urb(urb, GFP_ATOMIC);
+	if (retval && retval != -ENODEV)
+		dev_err(pcu->dev, "%s - usb_submit_urb failed with result %d\n",
+			__func__, retval);
+}
+
+static int ims_pcu_buffers_alloc(struct ims_pcu *pcu)
+{
+	int error;
+
+	pcu->urb_in_buf = usb_alloc_coherent(pcu->udev, pcu->max_in_size,
+					     GFP_KERNEL, &pcu->read_dma);
+	if (!pcu->urb_in_buf) {
+		dev_err(pcu->dev,
+			"Failed to allocate memory for read buffer\n");
+		return -ENOMEM;
+	}
+
+	pcu->urb_in = usb_alloc_urb(0, GFP_KERNEL);
+	if (!pcu->urb_in) {
+		dev_err(pcu->dev, "Failed to allocate input URB\n");
+		error = -ENOMEM;
+		goto err_free_urb_in_buf;
+	}
+
+	pcu->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+	pcu->urb_in->transfer_dma = pcu->read_dma;
+
+	usb_fill_bulk_urb(pcu->urb_in, pcu->udev,
+			  usb_rcvbulkpipe(pcu->udev,
+					  pcu->ep_in->bEndpointAddress),
+			  pcu->urb_in_buf, pcu->max_in_size,
+			  ims_pcu_irq, pcu);
+
+	/*
+	 * We are using usb_bulk_msg() for sending so there is no point
+	 * in allocating memory with usb_alloc_coherent().
+	 */
+	pcu->urb_out_buf = kmalloc(pcu->max_out_size, GFP_KERNEL);
+	if (!pcu->urb_out_buf) {
+		dev_err(pcu->dev, "Failed to allocate memory for write buffer\n");
+		error = -ENOMEM;
+		goto err_free_in_urb;
+	}
+
+	pcu->urb_ctrl_buf = usb_alloc_coherent(pcu->udev, pcu->max_ctrl_size,
+					       GFP_KERNEL, &pcu->ctrl_dma);
+	if (!pcu->urb_ctrl_buf) {
+		dev_err(pcu->dev,
+			"Failed to allocate memory for read buffer\n");
+		goto err_free_urb_out_buf;
+	}
+
+	pcu->urb_ctrl = usb_alloc_urb(0, GFP_KERNEL);
+	if (!pcu->urb_ctrl) {
+		dev_err(pcu->dev, "Failed to allocate input URB\n");
+		error = -ENOMEM;
+		goto err_free_urb_ctrl_buf;
+	}
+
+	pcu->urb_ctrl->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+	pcu->urb_ctrl->transfer_dma = pcu->ctrl_dma;
+
+	usb_fill_int_urb(pcu->urb_ctrl, pcu->udev,
+			  usb_rcvintpipe(pcu->udev,
+					 pcu->ep_ctrl->bEndpointAddress),
+			  pcu->urb_ctrl_buf, pcu->max_ctrl_size,
+			  ims_pcu_irq, pcu, pcu->ep_ctrl->bInterval);
+
+	return 0;
+
+err_free_urb_ctrl_buf:
+	usb_free_coherent(pcu->udev, pcu->max_ctrl_size,
+			  pcu->urb_ctrl_buf, pcu->ctrl_dma);
+err_free_urb_out_buf:
+	kfree(pcu->urb_out_buf);
+err_free_in_urb:
+	usb_free_urb(pcu->urb_in);
+err_free_urb_in_buf:
+	usb_free_coherent(pcu->udev, pcu->max_in_size,
+			  pcu->urb_in_buf, pcu->read_dma);
+	return error;
+}
+
+static void ims_pcu_buffers_free(struct ims_pcu *pcu)
+{
+	usb_kill_urb(pcu->urb_in);
+	usb_free_urb(pcu->urb_in);
+
+	usb_free_coherent(pcu->udev, pcu->max_out_size,
+			  pcu->urb_in_buf, pcu->read_dma);
+
+	kfree(pcu->urb_out_buf);
+
+	usb_kill_urb(pcu->urb_ctrl);
+	usb_free_urb(pcu->urb_ctrl);
+
+	usb_free_coherent(pcu->udev, pcu->max_ctrl_size,
+			  pcu->urb_ctrl_buf, pcu->ctrl_dma);
+}
+
+static const struct usb_cdc_union_desc *
+ims_pcu_get_cdc_union_desc(struct usb_interface *intf)
+{
+	const void *buf = intf->altsetting->extra;
+	size_t buflen = intf->altsetting->extralen;
+	struct usb_cdc_union_desc *union_desc;
+
+	if (!buf) {
+		dev_err(&intf->dev, "Missing descriptor data\n");
+		return NULL;
+	}
+
+	if (!buflen) {
+		dev_err(&intf->dev, "Zero length descriptor\n");
+		return NULL;
+	}
+
+	while (buflen > 0) {
+		union_desc = (struct usb_cdc_union_desc *)buf;
+
+		if (union_desc->bDescriptorType == USB_DT_CS_INTERFACE &&
+		    union_desc->bDescriptorSubType == USB_CDC_UNION_TYPE) {
+			dev_dbg(&intf->dev, "Found union header\n");
+			return union_desc;
+		}
+
+		buflen -= union_desc->bLength;
+		buf += union_desc->bLength;
+	}
+
+	dev_err(&intf->dev, "Missing CDC union descriptor\n");
+	return NULL;
+}
+
+static int ims_pcu_parse_cdc_data(struct usb_interface *intf, struct ims_pcu *pcu)
+{
+	const struct usb_cdc_union_desc *union_desc;
+	struct usb_host_interface *alt;
+
+	union_desc = ims_pcu_get_cdc_union_desc(intf);
+	if (!union_desc)
+		return -EINVAL;
+
+	pcu->ctrl_intf = usb_ifnum_to_if(pcu->udev,
+					 union_desc->bMasterInterface0);
+
+	alt = pcu->ctrl_intf->cur_altsetting;
+	pcu->ep_ctrl = &alt->endpoint[0].desc;
+	pcu->max_ctrl_size = usb_endpoint_maxp(pcu->ep_ctrl);
+
+	pcu->data_intf = usb_ifnum_to_if(pcu->udev,
+					 union_desc->bSlaveInterface0);
+
+	alt = pcu->data_intf->cur_altsetting;
+	if (alt->desc.bNumEndpoints != 2) {
+		dev_err(pcu->dev,
+			"Incorrect number of endpoints on data interface (%d)\n",
+			alt->desc.bNumEndpoints);
+		return -EINVAL;
+	}
+
+	pcu->ep_out = &alt->endpoint[0].desc;
+	if (!usb_endpoint_is_bulk_out(pcu->ep_out)) {
+		dev_err(pcu->dev,
+			"First endpoint on data interface is not BULK OUT\n");
+		return -EINVAL;
+	}
+
+	pcu->max_out_size = usb_endpoint_maxp(pcu->ep_out);
+	if (pcu->max_out_size < 8) {
+		dev_err(pcu->dev,
+			"Max OUT packet size is too small (%zd)\n",
+			pcu->max_out_size);
+		return -EINVAL;
+	}
+
+	pcu->ep_in = &alt->endpoint[1].desc;
+	if (!usb_endpoint_is_bulk_in(pcu->ep_in)) {
+		dev_err(pcu->dev,
+			"Second endpoint on data interface is not BULK IN\n");
+		return -EINVAL;
+	}
+
+	pcu->max_in_size = usb_endpoint_maxp(pcu->ep_in);
+	if (pcu->max_in_size < 8) {
+		dev_err(pcu->dev,
+			"Max IN packet size is too small (%zd)\n",
+			pcu->max_in_size);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int ims_pcu_start_io(struct ims_pcu *pcu)
+{
+	int error;
+
+	error = usb_submit_urb(pcu->urb_ctrl, GFP_KERNEL);
+	if (error) {
+		dev_err(pcu->dev,
+			"Failed to start control IO - usb_submit_urb failed with result: %d\n",
+			error);
+		return -EIO;
+	}
+
+	error = usb_submit_urb(pcu->urb_in, GFP_KERNEL);
+	if (error) {
+		dev_err(pcu->dev,
+			"Failed to start IO - usb_submit_urb failed with result: %d\n",
+			error);
+		usb_kill_urb(pcu->urb_ctrl);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static void ims_pcu_stop_io(struct ims_pcu *pcu)
+{
+	usb_kill_urb(pcu->urb_in);
+	usb_kill_urb(pcu->urb_ctrl);
+}
+
+static int ims_pcu_line_setup(struct ims_pcu *pcu)
+{
+	struct usb_host_interface *interface = pcu->ctrl_intf->cur_altsetting;
+	struct usb_cdc_line_coding *line = (void *)pcu->cmd_buf;
+	int error;
+
+	memset(line, 0, sizeof(*line));
+	line->dwDTERate = cpu_to_le32(57600);
+	line->bDataBits = 8;
+
+	error = usb_control_msg(pcu->udev, usb_sndctrlpipe(pcu->udev, 0),
+				USB_CDC_REQ_SET_LINE_CODING,
+				USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+				0, interface->desc.bInterfaceNumber,
+				line, sizeof(struct usb_cdc_line_coding),
+				5000);
+	if (error < 0) {
+		dev_err(pcu->dev, "Failed to set line coding, error: %d\n",
+			error);
+		return error;
+	}
+
+	error = usb_control_msg(pcu->udev, usb_sndctrlpipe(pcu->udev, 0),
+				USB_CDC_REQ_SET_CONTROL_LINE_STATE,
+				USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+				0x03, interface->desc.bInterfaceNumber,
+				NULL, 0, 5000);
+	if (error < 0) {
+		dev_err(pcu->dev, "Failed to set line state, error: %d\n",
+			error);
+		return error;
+	}
+
+	return 0;
+}
+
+static int ims_pcu_get_device_info(struct ims_pcu *pcu)
+{
+	int error;
+
+	error = ims_pcu_get_info(pcu);
+	if (error)
+		return error;
+
+	error = ims_pcu_execute_query(pcu, GET_FW_VERSION);
+	if (error) {
+		dev_err(pcu->dev,
+			"GET_FW_VERSION command failed, error: %d\n", error);
+		return error;
+	}
+
+	snprintf(pcu->fw_version, sizeof(pcu->fw_version),
+		 "%02d%02d%02d%02d.%c%c",
+		 pcu->cmd_buf[2], pcu->cmd_buf[3], pcu->cmd_buf[4], pcu->cmd_buf[5],
+		 pcu->cmd_buf[6], pcu->cmd_buf[7]);
+
+	error = ims_pcu_execute_query(pcu, GET_BL_VERSION);
+	if (error) {
+		dev_err(pcu->dev,
+			"GET_BL_VERSION command failed, error: %d\n", error);
+		return error;
+	}
+
+	snprintf(pcu->bl_version, sizeof(pcu->bl_version),
+		 "%02d%02d%02d%02d.%c%c",
+		 pcu->cmd_buf[2], pcu->cmd_buf[3], pcu->cmd_buf[4], pcu->cmd_buf[5],
+		 pcu->cmd_buf[6], pcu->cmd_buf[7]);
+
+	error = ims_pcu_execute_query(pcu, RESET_REASON);
+	if (error) {
+		dev_err(pcu->dev,
+			"RESET_REASON command failed, error: %d\n", error);
+		return error;
+	}
+
+	snprintf(pcu->reset_reason, sizeof(pcu->reset_reason),
+		 "%02x", pcu->cmd_buf[IMS_PCU_DATA_OFFSET]);
+
+	dev_dbg(pcu->dev,
+		"P/N: %s, MD: %s, S/N: %s, FW: %s, BL: %s, RR: %s\n",
+		pcu->part_number,
+		pcu->date_of_manufacturing,
+		pcu->serial_number,
+		pcu->fw_version,
+		pcu->bl_version,
+		pcu->reset_reason);
+
+	return 0;
+}
+
+static int ims_pcu_identify_type(struct ims_pcu *pcu, u8 *device_id)
+{
+	int error;
+
+	error = ims_pcu_execute_query(pcu, GET_DEVICE_ID);
+	if (error) {
+		dev_err(pcu->dev,
+			"GET_DEVICE_ID command failed, error: %d\n", error);
+		return error;
+	}
+
+	*device_id = pcu->cmd_buf[IMS_PCU_DATA_OFFSET];
+	dev_dbg(pcu->dev, "Detected device ID: %d\n", *device_id);
+
+	return 0;
+}
+
+static int ims_pcu_init_application_mode(struct ims_pcu *pcu)
+{
+	static atomic_t device_no = ATOMIC_INIT(0);
+
+	const struct ims_pcu_device_info *info;
+	u8 device_id;
+	int error;
+
+	error = ims_pcu_get_device_info(pcu);
+	if (error) {
+		/* Device does not respond to basic queries, hopeless */
+		return error;
+	}
+
+	error = ims_pcu_identify_type(pcu, &device_id);
+	if (error) {
+		dev_err(pcu->dev,
+			"Failed to identify device, error: %d\n", error);
+		/*
+		 * Do not signal error, but do not create input nor
+		 * backlight devices either, let userspace figure this
+		 * out (flash a new firmware?).
+		 */
+		return 0;
+	}
+
+	if (device_id >= ARRAY_SIZE(ims_pcu_device_info) ||
+	    !ims_pcu_device_info[device_id].keymap) {
+		dev_err(pcu->dev, "Device ID %d is not valid\n", device_id);
+		/* Same as above, punt to userspace */
+		return 0;
+	}
+
+	/* Device appears to be operable, complete initialization */
+	pcu->device_no = atomic_inc_return(&device_no) - 1;
+
+	error = ims_pcu_setup_backlight(pcu);
+	if (error)
+		return error;
+
+	info = &ims_pcu_device_info[device_id];
+	error = ims_pcu_setup_buttons(pcu, info->keymap, info->keymap_len);
+	if (error)
+		goto err_destroy_backlight;
+
+	if (info->has_gamepad) {
+		error = ims_pcu_setup_gamepad(pcu);
+		if (error)
+			goto err_destroy_buttons;
+	}
+
+	pcu->setup_complete = true;
+
+	return 0;
+
+err_destroy_backlight:
+	ims_pcu_destroy_backlight(pcu);
+err_destroy_buttons:
+	ims_pcu_destroy_buttons(pcu);
+	return error;
+}
+
+static void ims_pcu_destroy_application_mode(struct ims_pcu *pcu)
+{
+	if (pcu->setup_complete) {
+		pcu->setup_complete = false;
+		mb(); /* make sure flag setting is not reordered */
+
+		if (pcu->gamepad)
+			ims_pcu_destroy_gamepad(pcu);
+		ims_pcu_destroy_buttons(pcu);
+		ims_pcu_destroy_backlight(pcu);
+	}
+}
+
+static int ims_pcu_init_bootloader_mode(struct ims_pcu *pcu)
+{
+	int error;
+
+	error = ims_pcu_execute_bl_command(pcu, QUERY_DEVICE, NULL, 0,
+					   IMS_PCU_CMD_RESPONSE_TIMEOUT);
+	if (error) {
+		dev_err(pcu->dev, "Bootloader does not respond, aborting\n");
+		return error;
+	}
+
+	pcu->fw_start_addr =
+		get_unaligned_le32(&pcu->cmd_buf[IMS_PCU_DATA_OFFSET + 11]);
+	pcu->fw_end_addr =
+		get_unaligned_le32(&pcu->cmd_buf[IMS_PCU_DATA_OFFSET + 15]);
+
+	dev_info(pcu->dev,
+		 "Device is in bootloader mode (addr 0x%08x-0x%08x), requesting firmware\n",
+		 pcu->fw_start_addr, pcu->fw_end_addr);
+
+	error = request_firmware_nowait(THIS_MODULE, true,
+					IMS_PCU_FIRMWARE_NAME,
+					pcu->dev, GFP_KERNEL, pcu,
+					ims_pcu_process_async_firmware);
+	if (error) {
+		/* This error is not fatal, let userspace have another chance */
+		complete(&pcu->async_firmware_done);
+	}
+
+	return 0;
+}
+
+static void ims_pcu_destroy_bootloader_mode(struct ims_pcu *pcu)
+{
+	/* Make sure our initial firmware request has completed */
+	wait_for_completion(&pcu->async_firmware_done);
+}
+
+#define IMS_PCU_APPLICATION_MODE	0
+#define IMS_PCU_BOOTLOADER_MODE		1
+
+static struct usb_driver ims_pcu_driver;
+
+static int ims_pcu_probe(struct usb_interface *intf,
+			 const struct usb_device_id *id)
+{
+	struct usb_device *udev = interface_to_usbdev(intf);
+	struct ims_pcu *pcu;
+	int error;
+
+	pcu = kzalloc(sizeof(struct ims_pcu), GFP_KERNEL);
+	if (!pcu)
+		return -ENOMEM;
+
+	pcu->dev = &intf->dev;
+	pcu->udev = udev;
+	pcu->bootloader_mode = id->driver_info == IMS_PCU_BOOTLOADER_MODE;
+	mutex_init(&pcu->cmd_mutex);
+	init_completion(&pcu->cmd_done);
+	init_completion(&pcu->async_firmware_done);
+
+	error = ims_pcu_parse_cdc_data(intf, pcu);
+	if (error)
+		goto err_free_mem;
+
+	error = usb_driver_claim_interface(&ims_pcu_driver,
+					   pcu->data_intf, pcu);
+	if (error) {
+		dev_err(&intf->dev,
+			"Unable to claim corresponding data interface: %d\n",
+			error);
+		goto err_free_mem;
+	}
+
+	usb_set_intfdata(pcu->ctrl_intf, pcu);
+	usb_set_intfdata(pcu->data_intf, pcu);
+
+	error = ims_pcu_buffers_alloc(pcu);
+	if (error)
+		goto err_unclaim_intf;
+
+	error = ims_pcu_start_io(pcu);
+	if (error)
+		goto err_free_buffers;
+
+	error = ims_pcu_line_setup(pcu);
+	if (error)
+		goto err_stop_io;
+
+	error = sysfs_create_group(&intf->dev.kobj, &ims_pcu_attr_group);
+	if (error)
+		goto err_stop_io;
+
+	error = pcu->bootloader_mode ?
+			ims_pcu_init_bootloader_mode(pcu) :
+			ims_pcu_init_application_mode(pcu);
+	if (error)
+		goto err_remove_sysfs;
+
+	return 0;
+
+err_remove_sysfs:
+	sysfs_remove_group(&intf->dev.kobj, &ims_pcu_attr_group);
+err_stop_io:
+	ims_pcu_stop_io(pcu);
+err_free_buffers:
+	ims_pcu_buffers_free(pcu);
+err_unclaim_intf:
+	usb_driver_release_interface(&ims_pcu_driver, pcu->data_intf);
+err_free_mem:
+	kfree(pcu);
+	return error;
+}
+
+static void ims_pcu_disconnect(struct usb_interface *intf)
+{
+	struct ims_pcu *pcu = usb_get_intfdata(intf);
+	struct usb_host_interface *alt = intf->cur_altsetting;
+
+	usb_set_intfdata(intf, NULL);
+
+	/*
+	 * See if we are dealing with control or data interface. The cleanup
+	 * happens when we unbind primary (control) interface.
+	 */
+	if (alt->desc.bInterfaceClass != USB_CLASS_COMM)
+		return;
+
+	sysfs_remove_group(&intf->dev.kobj, &ims_pcu_attr_group);
+
+	ims_pcu_stop_io(pcu);
+
+	if (pcu->bootloader_mode)
+		ims_pcu_destroy_bootloader_mode(pcu);
+	else
+		ims_pcu_destroy_application_mode(pcu);
+
+	ims_pcu_buffers_free(pcu);
+	kfree(pcu);
+}
+
+#ifdef CONFIG_PM
+static int ims_pcu_suspend(struct usb_interface *intf,
+			   pm_message_t message)
+{
+	struct ims_pcu *pcu = usb_get_intfdata(intf);
+	struct usb_host_interface *alt = intf->cur_altsetting;
+
+	if (alt->desc.bInterfaceClass == USB_CLASS_COMM)
+		ims_pcu_stop_io(pcu);
+
+	return 0;
+}
+
+static int ims_pcu_resume(struct usb_interface *intf)
+{
+	struct ims_pcu *pcu = usb_get_intfdata(intf);
+	struct usb_host_interface *alt = intf->cur_altsetting;
+	int retval = 0;
+
+	if (alt->desc.bInterfaceClass == USB_CLASS_COMM) {
+		retval = ims_pcu_start_io(pcu);
+		if (retval == 0)
+			retval = ims_pcu_line_setup(pcu);
+	}
+
+	return retval;
+}
+#endif
+
+static const struct usb_device_id ims_pcu_id_table[] = {
+	{
+		USB_DEVICE_AND_INTERFACE_INFO(0x04d8, 0x0082,
+					USB_CLASS_COMM,
+					USB_CDC_SUBCLASS_ACM,
+					USB_CDC_ACM_PROTO_AT_V25TER),
+		.driver_info = IMS_PCU_APPLICATION_MODE,
+	},
+	{
+		USB_DEVICE_AND_INTERFACE_INFO(0x04d8, 0x0083,
+					USB_CLASS_COMM,
+					USB_CDC_SUBCLASS_ACM,
+					USB_CDC_ACM_PROTO_AT_V25TER),
+		.driver_info = IMS_PCU_BOOTLOADER_MODE,
+	},
+	{ }
+};
+
+static struct usb_driver ims_pcu_driver = {
+	.name			= "ims_pcu",
+	.id_table		= ims_pcu_id_table,
+	.probe			= ims_pcu_probe,
+	.disconnect		= ims_pcu_disconnect,
+#ifdef CONFIG_PM
+	.suspend		= ims_pcu_suspend,
+	.resume			= ims_pcu_resume,
+	.reset_resume		= ims_pcu_resume,
+#endif
+};
+
+module_usb_driver(ims_pcu_driver);
+
+MODULE_DESCRIPTION("IMS Passenger Control Unit driver");
+MODULE_AUTHOR("Dmitry Torokhov <dmitry.torokhov@gmail.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/misc/mma8450.c b/drivers/input/misc/mma8450.c
index 480557f..f330969 100644
--- a/drivers/input/misc/mma8450.c
+++ b/drivers/input/misc/mma8450.c
@@ -123,9 +123,9 @@ static void mma8450_poll(struct input_polled_dev *dev)
 	if (ret < 0)
 		return;
 
-	x = ((buf[1] << 4) & 0xff0) | (buf[0] & 0xf);
-	y = ((buf[3] << 4) & 0xff0) | (buf[2] & 0xf);
-	z = ((buf[5] << 4) & 0xff0) | (buf[4] & 0xf);
+	x = ((int)(s8)buf[1] << 4) | (buf[0] & 0xf);
+	y = ((int)(s8)buf[3] << 4) | (buf[2] & 0xf);
+	z = ((int)(s8)buf[5] << 4) | (buf[4] & 0xf);
 
 	input_report_abs(dev->input, ABS_X, x);
 	input_report_abs(dev->input, ABS_Y, y);
diff --git a/drivers/input/misc/twl4030-pwrbutton.c b/drivers/input/misc/twl4030-pwrbutton.c
index 27c2bc8..b9a05fd 100644
--- a/drivers/input/misc/twl4030-pwrbutton.c
+++ b/drivers/input/misc/twl4030-pwrbutton.c
@@ -114,18 +114,8 @@ static struct platform_driver twl4030_pwrbutton_driver = {
 	},
 };
 
-static int __init twl4030_pwrbutton_init(void)
-{
-	return platform_driver_probe(&twl4030_pwrbutton_driver,
+module_platform_driver_probe(twl4030_pwrbutton_driver,
 			twl4030_pwrbutton_probe);
-}
-module_init(twl4030_pwrbutton_init);
-
-static void __exit twl4030_pwrbutton_exit(void)
-{
-	platform_driver_unregister(&twl4030_pwrbutton_driver);
-}
-module_exit(twl4030_pwrbutton_exit);
 
 MODULE_ALIAS("platform:twl4030_pwrbutton");
 MODULE_DESCRIPTION("Triton2 Power Button");
diff --git a/drivers/input/mouse/amimouse.c b/drivers/input/mouse/amimouse.c
index 5fa9934..b55d5af 100644
--- a/drivers/input/mouse/amimouse.c
+++ b/drivers/input/mouse/amimouse.c
@@ -146,18 +146,6 @@ static struct platform_driver amimouse_driver = {
 	},
 };
 
-static int __init amimouse_init(void)
-{
-	return platform_driver_probe(&amimouse_driver, amimouse_probe);
-}
-
-module_init(amimouse_init);
-
-static void __exit amimouse_exit(void)
-{
-	platform_driver_unregister(&amimouse_driver);
-}
-
-module_exit(amimouse_exit);
+module_platform_driver_probe(amimouse_driver, amimouse_probe);
 
 MODULE_ALIAS("platform:amiga-mouse");
diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig
index 3ec5ef2..aebfe3e 100644
--- a/drivers/input/serio/Kconfig
+++ b/drivers/input/serio/Kconfig
@@ -245,4 +245,14 @@ config SERIO_ARC_PS2
 	  To compile this driver as a module, choose M here; the module
 	  will be called arc_ps2.
 
+config SERIO_APBPS2
+	tristate "GRLIB APBPS2 PS/2 keyboard/mouse controller"
+	depends on OF
+	help
+	  Say Y here if you want support for GRLIB APBPS2 peripherals used
+	  to connect to PS/2 keyboard and/or mouse.
+
+	  To compile this driver as a module, choose M here: the module will
+	  be called apbps2.
+
 endif
diff --git a/drivers/input/serio/Makefile b/drivers/input/serio/Makefile
index 4b0c8f8..8edb36c 100644
--- a/drivers/input/serio/Makefile
+++ b/drivers/input/serio/Makefile
@@ -26,3 +26,4 @@ obj-$(CONFIG_SERIO_AMS_DELTA)	+= ams_delta_serio.o
 obj-$(CONFIG_SERIO_XILINX_XPS_PS2)	+= xilinx_ps2.o
 obj-$(CONFIG_SERIO_ALTERA_PS2)	+= altera_ps2.o
 obj-$(CONFIG_SERIO_ARC_PS2)	+= arc_ps2.o
+obj-$(CONFIG_SERIO_APBPS2)	+= apbps2.o
diff --git a/drivers/input/serio/apbps2.c b/drivers/input/serio/apbps2.c
new file mode 100644
index 0000000..2c14e6f
--- /dev/null
+++ b/drivers/input/serio/apbps2.c
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2013 Aeroflex Gaisler
+ *
+ * This driver supports the APBPS2 PS/2 core available in the GRLIB
+ * VHDL IP core library.
+ *
+ * Full documentation of the APBPS2 core can be found here:
+ * http://www.gaisler.com/products/grlib/grip.pdf
+ *
+ * See "Documentation/devicetree/bindings/input/ps2keyb-mouse-apbps2.txt" for
+ * information on open firmware properties.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Contributors: Daniel Hellstrom <daniel@gaisler.com>
+ */
+#include <linux/platform_device.h>
+#include <linux/of_device.h>
+#include <linux/module.h>
+#include <linux/serio.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/of_irq.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+
+struct apbps2_regs {
+	u32 __iomem data;	/* 0x00 */
+	u32 __iomem status;	/* 0x04 */
+	u32 __iomem ctrl;	/* 0x08 */
+	u32 __iomem reload;	/* 0x0c */
+};
+
+#define APBPS2_STATUS_DR	(1<<0)
+#define APBPS2_STATUS_PE	(1<<1)
+#define APBPS2_STATUS_FE	(1<<2)
+#define APBPS2_STATUS_KI	(1<<3)
+#define APBPS2_STATUS_RF	(1<<4)
+#define APBPS2_STATUS_TF	(1<<5)
+#define APBPS2_STATUS_TCNT	(0x1f<<22)
+#define APBPS2_STATUS_RCNT	(0x1f<<27)
+
+#define APBPS2_CTRL_RE		(1<<0)
+#define APBPS2_CTRL_TE		(1<<1)
+#define APBPS2_CTRL_RI		(1<<2)
+#define APBPS2_CTRL_TI		(1<<3)
+
+struct apbps2_priv {
+	struct serio		*io;
+	struct apbps2_regs	*regs;
+};
+
+static int apbps2_idx;
+
+static irqreturn_t apbps2_isr(int irq, void *dev_id)
+{
+	struct apbps2_priv *priv = dev_id;
+	unsigned long status, data, rxflags;
+	irqreturn_t ret = IRQ_NONE;
+
+	while ((status = ioread32be(&priv->regs->status)) & APBPS2_STATUS_DR) {
+		data = ioread32be(&priv->regs->data);
+		rxflags = (status & APBPS2_STATUS_PE) ? SERIO_PARITY : 0;
+		rxflags |= (status & APBPS2_STATUS_FE) ? SERIO_FRAME : 0;
+
+		/* clear error bits? */
+		if (rxflags)
+			iowrite32be(0, &priv->regs->status);
+
+		serio_interrupt(priv->io, data, rxflags);
+
+		ret = IRQ_HANDLED;
+	}
+
+	return ret;
+}
+
+static int apbps2_write(struct serio *io, unsigned char val)
+{
+	struct apbps2_priv *priv = io->port_data;
+	unsigned int tleft = 10000; /* timeout in 100ms */
+
+	/* delay until PS/2 controller has room for more chars */
+	while ((ioread32be(&priv->regs->status) & APBPS2_STATUS_TF) && tleft--)
+		udelay(10);
+
+	if ((ioread32be(&priv->regs->status) & APBPS2_STATUS_TF) == 0) {
+		iowrite32be(val, &priv->regs->data);
+
+		iowrite32be(APBPS2_CTRL_RE | APBPS2_CTRL_RI | APBPS2_CTRL_TE,
+				&priv->regs->ctrl);
+		return 0;
+	}
+
+	return -ETIMEDOUT;
+}
+
+static int apbps2_open(struct serio *io)
+{
+	struct apbps2_priv *priv = io->port_data;
+	int limit;
+	unsigned long tmp;
+
+	/* clear error flags */
+	iowrite32be(0, &priv->regs->status);
+
+	/* Clear old data if available (unlikely) */
+	limit = 1024;
+	while ((ioread32be(&priv->regs->status) & APBPS2_STATUS_DR) && --limit)
+		tmp = ioread32be(&priv->regs->data);
+
+	/* Enable reciever and it's interrupt */
+	iowrite32be(APBPS2_CTRL_RE | APBPS2_CTRL_RI, &priv->regs->ctrl);
+
+	return 0;
+}
+
+static void apbps2_close(struct serio *io)
+{
+	struct apbps2_priv *priv = io->port_data;
+
+	/* stop interrupts at PS/2 HW level */
+	iowrite32be(0, &priv->regs->ctrl);
+}
+
+/* Initialize one APBPS2 PS/2 core */
+static int apbps2_of_probe(struct platform_device *ofdev)
+{
+	struct apbps2_priv *priv;
+	int irq, err;
+	u32 freq_hz;
+	struct resource *res;
+
+	priv = devm_kzalloc(&ofdev->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		dev_err(&ofdev->dev, "memory allocation failed\n");
+		return -ENOMEM;
+	}
+
+	/* Find Device Address */
+	res = platform_get_resource(ofdev, IORESOURCE_MEM, 0);
+	priv->regs = devm_request_and_ioremap(&ofdev->dev, res);
+	if (!priv->regs) {
+		dev_err(&ofdev->dev, "io-regs mapping failed\n");
+		return -EBUSY;
+	}
+
+	/* Reset hardware, disable interrupt */
+	iowrite32be(0, &priv->regs->ctrl);
+
+	/* IRQ */
+	irq = irq_of_parse_and_map(ofdev->dev.of_node, 0);
+	err = devm_request_irq(&ofdev->dev, irq, apbps2_isr,
+				IRQF_SHARED, "apbps2", priv);
+	if (err) {
+		dev_err(&ofdev->dev, "request IRQ%d failed\n", irq);
+		return err;
+	}
+
+	/* Get core frequency */
+	if (of_property_read_u32(ofdev->dev.of_node, "freq", &freq_hz)) {
+		dev_err(&ofdev->dev, "unable to get core frequency\n");
+		return -EINVAL;
+	}
+
+	/* Set reload register to core freq in kHz/10 */
+	iowrite32be(freq_hz / 10000, &priv->regs->reload);
+
+	priv->io = kzalloc(sizeof(struct serio), GFP_KERNEL);
+	if (!priv->io)
+		return -ENOMEM;
+
+	priv->io->id.type = SERIO_8042;
+	priv->io->open = apbps2_open;
+	priv->io->close = apbps2_close;
+	priv->io->write = apbps2_write;
+	priv->io->port_data = priv;
+	strlcpy(priv->io->name, "APBPS2 PS/2", sizeof(priv->io->name));
+	snprintf(priv->io->phys, sizeof(priv->io->phys),
+		 "apbps2_%d", apbps2_idx++);
+
+	dev_info(&ofdev->dev, "irq = %d, base = 0x%p\n", irq, priv->regs);
+
+	serio_register_port(priv->io);
+
+	platform_set_drvdata(ofdev, priv);
+
+	return 0;
+}
+
+static int apbps2_of_remove(struct platform_device *of_dev)
+{
+	struct apbps2_priv *priv = platform_get_drvdata(of_dev);
+
+	serio_unregister_port(priv->io);
+
+	return 0;
+}
+
+static struct of_device_id apbps2_of_match[] = {
+	{ .name = "GAISLER_APBPS2", },
+	{ .name = "01_060", },
+	{}
+};
+
+MODULE_DEVICE_TABLE(of, apbps2_of_match);
+
+static struct platform_driver apbps2_of_driver = {
+	.driver = {
+		.name = "grlib-apbps2",
+		.owner = THIS_MODULE,
+		.of_match_table = apbps2_of_match,
+	},
+	.probe = apbps2_of_probe,
+	.remove = apbps2_of_remove,
+};
+
+module_platform_driver(apbps2_of_driver);
+
+MODULE_AUTHOR("Aeroflex Gaisler AB.");
+MODULE_DESCRIPTION("GRLIB APBPS2 PS/2 serial I/O");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/serio/arc_ps2.c b/drivers/input/serio/arc_ps2.c
index c52e3e5..3fb7727 100644
--- a/drivers/input/serio/arc_ps2.c
+++ b/drivers/input/serio/arc_ps2.c
@@ -14,6 +14,7 @@
 #include <linux/input.h>
 #include <linux/serio.h>
 #include <linux/platform_device.h>
+#include <linux/of.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
@@ -259,10 +260,19 @@ static int arc_ps2_remove(struct platform_device *pdev)
 	return 0;
 }
 
+#ifdef CONFIG_OF
+static const struct of_device_id arc_ps2_match[] = {
+	{ .compatible = "snps,arc_ps2" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, arc_ps2_match);
+#endif
+
 static struct platform_driver arc_ps2_driver = {
 	.driver	= {
-		.name	= "arc_ps2",
-		.owner	= THIS_MODULE,
+		.name		= "arc_ps2",
+		.owner		= THIS_MODULE,
+		.of_match_table	= of_match_ptr(arc_ps2_match),
 	},
 	.probe	= arc_ps2_probe,
 	.remove	= arc_ps2_remove,
diff --git a/drivers/input/serio/at32psif.c b/drivers/input/serio/at32psif.c
index 36e799c..190ce35 100644
--- a/drivers/input/serio/at32psif.c
+++ b/drivers/input/serio/at32psif.c
@@ -359,18 +359,7 @@ static struct platform_driver psif_driver = {
 	},
 };
 
-static int __init psif_init(void)
-{
-	return platform_driver_probe(&psif_driver, psif_probe);
-}
-
-static void __exit psif_exit(void)
-{
-	platform_driver_unregister(&psif_driver);
-}
-
-module_init(psif_init);
-module_exit(psif_exit);
+module_platform_driver_probe(psif_driver, psif_probe);
 
 MODULE_AUTHOR("Hans-Christian Egtvedt <egtvedt@samfundet.no>");
 MODULE_DESCRIPTION("Atmel AVR32 PSIF PS/2 driver");
diff --git a/drivers/input/serio/q40kbd.c b/drivers/input/serio/q40kbd.c
index 70fe542..436a343 100644
--- a/drivers/input/serio/q40kbd.c
+++ b/drivers/input/serio/q40kbd.c
@@ -193,15 +193,4 @@ static struct platform_driver q40kbd_driver = {
 	.remove		= q40kbd_remove,
 };
 
-static int __init q40kbd_init(void)
-{
-	return platform_driver_probe(&q40kbd_driver, q40kbd_probe);
-}
-
-static void __exit q40kbd_exit(void)
-{
-	platform_driver_unregister(&q40kbd_driver);
-}
-
-module_init(q40kbd_init);
-module_exit(q40kbd_exit);
+module_platform_driver_probe(q40kbd_driver, q40kbd_probe);
diff --git a/drivers/input/touchscreen/atmel-wm97xx.c b/drivers/input/touchscreen/atmel-wm97xx.c
index c5c2dbb..2c1e46b 100644
--- a/drivers/input/touchscreen/atmel-wm97xx.c
+++ b/drivers/input/touchscreen/atmel-wm97xx.c
@@ -432,17 +432,7 @@ static struct platform_driver atmel_wm97xx_driver = {
 	},
 };
 
-static int __init atmel_wm97xx_init(void)
-{
-	return platform_driver_probe(&atmel_wm97xx_driver, atmel_wm97xx_probe);
-}
-module_init(atmel_wm97xx_init);
-
-static void __exit atmel_wm97xx_exit(void)
-{
-	platform_driver_unregister(&atmel_wm97xx_driver);
-}
-module_exit(atmel_wm97xx_exit);
+module_platform_driver_probe(atmel_wm97xx_driver, atmel_wm97xx_probe);
 
 MODULE_AUTHOR("Hans-Christian Egtvedt <egtvedt@samfundet.no>");
 MODULE_DESCRIPTION("wm97xx continuous touch driver for Atmel AT91 and AVR32");
diff --git a/drivers/input/touchscreen/auo-pixcir-ts.c b/drivers/input/touchscreen/auo-pixcir-ts.c
index c6e19a9..d3f9f6b 100644
--- a/drivers/input/touchscreen/auo-pixcir-ts.c
+++ b/drivers/input/touchscreen/auo-pixcir-ts.c
@@ -31,6 +31,8 @@
 #include <linux/delay.h>
 #include <linux/gpio.h>
 #include <linux/input/auo-pixcir-ts.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
 
 /*
  * Coordinate calculation:
@@ -111,6 +113,7 @@
 struct auo_pixcir_ts {
 	struct i2c_client	*client;
 	struct input_dev	*input;
+	const struct auo_pixcir_ts_platdata *pdata;
 	char			phys[32];
 
 	/* special handling for touch_indicate interupt mode */
@@ -132,7 +135,7 @@ static int auo_pixcir_collect_data(struct auo_pixcir_ts *ts,
 				   struct auo_point_t *point)
 {
 	struct i2c_client *client = ts->client;
-	const struct auo_pixcir_ts_platdata *pdata = client->dev.platform_data;
+	const struct auo_pixcir_ts_platdata *pdata = ts->pdata;
 	uint8_t raw_coord[8];
 	uint8_t raw_area[4];
 	int i, ret;
@@ -178,8 +181,7 @@ static int auo_pixcir_collect_data(struct auo_pixcir_ts *ts,
 static irqreturn_t auo_pixcir_interrupt(int irq, void *dev_id)
 {
 	struct auo_pixcir_ts *ts = dev_id;
-	struct i2c_client *client = ts->client;
-	const struct auo_pixcir_ts_platdata *pdata = client->dev.platform_data;
+	const struct auo_pixcir_ts_platdata *pdata = ts->pdata;
 	struct auo_point_t point[AUO_PIXCIR_REPORT_POINTS];
 	int i;
 	int ret;
@@ -290,7 +292,7 @@ static int auo_pixcir_int_config(struct auo_pixcir_ts *ts,
 					   int int_setting)
 {
 	struct i2c_client *client = ts->client;
-	struct auo_pixcir_ts_platdata *pdata = client->dev.platform_data;
+	const struct auo_pixcir_ts_platdata *pdata = ts->pdata;
 	int ret;
 
 	ret = i2c_smbus_read_byte_data(client, AUO_PIXCIR_REG_INT_SETTING);
@@ -479,53 +481,105 @@ unlock:
 }
 #endif
 
-static SIMPLE_DEV_PM_OPS(auo_pixcir_pm_ops, auo_pixcir_suspend,
-			 auo_pixcir_resume);
+static SIMPLE_DEV_PM_OPS(auo_pixcir_pm_ops,
+			 auo_pixcir_suspend, auo_pixcir_resume);
+
+#ifdef CONFIG_OF
+static struct auo_pixcir_ts_platdata *auo_pixcir_parse_dt(struct device *dev)
+{
+	struct auo_pixcir_ts_platdata *pdata;
+	struct device_node *np = dev->of_node;
+
+	if (!np)
+		return ERR_PTR(-ENOENT);
+
+	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata) {
+		dev_err(dev, "failed to allocate platform data\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	pdata->gpio_int = of_get_gpio(np, 0);
+	if (!gpio_is_valid(pdata->gpio_int)) {
+		dev_err(dev, "failed to get interrupt gpio\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	pdata->gpio_rst = of_get_gpio(np, 1);
+	if (!gpio_is_valid(pdata->gpio_rst)) {
+		dev_err(dev, "failed to get reset gpio\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (of_property_read_u32(np, "x-size", &pdata->x_max)) {
+		dev_err(dev, "failed to get x-size property\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (of_property_read_u32(np, "y-size", &pdata->y_max)) {
+		dev_err(dev, "failed to get y-size property\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	/* default to asserting the interrupt when the screen is touched */
+	pdata->int_setting = AUO_PIXCIR_INT_TOUCH_IND;
+
+	return pdata;
+}
+#else
+static struct auo_pixcir_ts_platdata *auo_pixcir_parse_dt(struct device *dev)
+{
+	return ERR_PTR(-EINVAL);
+}
+#endif
+
+static void auo_pixcir_reset(void *data)
+{
+	struct auo_pixcir_ts *ts = data;
+
+	gpio_set_value(ts->pdata->gpio_rst, 0);
+}
 
 static int auo_pixcir_probe(struct i2c_client *client,
-				      const struct i2c_device_id *id)
+			    const struct i2c_device_id *id)
 {
-	const struct auo_pixcir_ts_platdata *pdata = client->dev.platform_data;
+	const struct auo_pixcir_ts_platdata *pdata;
 	struct auo_pixcir_ts *ts;
 	struct input_dev *input_dev;
-	int ret;
-
-	if (!pdata)
-		return -EINVAL;
+	int version;
+	int error;
+
+	pdata = dev_get_platdata(&client->dev);
+	if (!pdata) {
+		pdata = auo_pixcir_parse_dt(&client->dev);
+		if (IS_ERR(pdata))
+			return PTR_ERR(pdata);
+	}
 
-	ts = kzalloc(sizeof(struct auo_pixcir_ts), GFP_KERNEL);
+	ts = devm_kzalloc(&client->dev,
+			  sizeof(struct auo_pixcir_ts), GFP_KERNEL);
 	if (!ts)
 		return -ENOMEM;
 
-	ret = gpio_request(pdata->gpio_int, "auo_pixcir_ts_int");
-	if (ret) {
-		dev_err(&client->dev, "request of gpio %d failed, %d\n",
-			pdata->gpio_int, ret);
-		goto err_gpio_int;
+	input_dev = devm_input_allocate_device(&client->dev);
+	if (!input_dev) {
+		dev_err(&client->dev, "could not allocate input device\n");
+		return -ENOMEM;
 	}
 
-	if (pdata->init_hw)
-		pdata->init_hw(client);
-
+	ts->pdata = pdata;
 	ts->client = client;
+	ts->input = input_dev;
 	ts->touch_ind_mode = 0;
+	ts->stopped = true;
 	init_waitqueue_head(&ts->wait);
 
 	snprintf(ts->phys, sizeof(ts->phys),
 		 "%s/input0", dev_name(&client->dev));
 
-	input_dev = input_allocate_device();
-	if (!input_dev) {
-		dev_err(&client->dev, "could not allocate input device\n");
-		goto err_input_alloc;
-	}
-
-	ts->input = input_dev;
-
 	input_dev->name = "AUO-Pixcir touchscreen";
 	input_dev->phys = ts->phys;
 	input_dev->id.bustype = BUS_I2C;
-	input_dev->dev.parent = &client->dev;
 
 	input_dev->open = auo_pixcir_input_open;
 	input_dev->close = auo_pixcir_input_close;
@@ -550,70 +604,70 @@ static int auo_pixcir_probe(struct i2c_client *client,
 			     AUO_PIXCIR_MAX_AREA, 0, 0);
 	input_set_abs_params(input_dev, ABS_MT_ORIENTATION, 0, 1, 0, 0);
 
-	ret = i2c_smbus_read_byte_data(client, AUO_PIXCIR_REG_VERSION);
-	if (ret < 0)
-		goto err_fw_vers;
-	dev_info(&client->dev, "firmware version 0x%X\n", ret);
-
-	ret = auo_pixcir_int_config(ts, pdata->int_setting);
-	if (ret)
-		goto err_fw_vers;
-
 	input_set_drvdata(ts->input, ts);
-	ts->stopped = true;
 
-	ret = request_threaded_irq(client->irq, NULL, auo_pixcir_interrupt,
-				   IRQF_TRIGGER_RISING | IRQF_ONESHOT,
-				   input_dev->name, ts);
-	if (ret) {
-		dev_err(&client->dev, "irq %d requested failed\n", client->irq);
-		goto err_fw_vers;
+	error = devm_gpio_request_one(&client->dev, pdata->gpio_int,
+				      GPIOF_DIR_IN, "auo_pixcir_ts_int");
+	if (error) {
+		dev_err(&client->dev, "request of gpio %d failed, %d\n",
+			pdata->gpio_int, error);
+		return error;
 	}
 
-	/* stop device and put it into deep sleep until it is opened */
-	ret = auo_pixcir_stop(ts);
-	if (ret < 0)
-		goto err_input_register;
-
-	ret = input_register_device(input_dev);
-	if (ret) {
-		dev_err(&client->dev, "could not register input device\n");
-		goto err_input_register;
+	error = devm_gpio_request_one(&client->dev, pdata->gpio_rst,
+				      GPIOF_DIR_OUT | GPIOF_INIT_HIGH,
+				      "auo_pixcir_ts_rst");
+	if (error) {
+		dev_err(&client->dev, "request of gpio %d failed, %d\n",
+			pdata->gpio_rst, error);
+		return error;
 	}
 
-	i2c_set_clientdata(client, ts);
-
-	return 0;
+	error = devm_add_action(&client->dev, auo_pixcir_reset, ts);
+	if (error) {
+		auo_pixcir_reset(ts);
+		dev_err(&client->dev, "failed to register reset action, %d\n",
+			error);
+		return error;
+	}
 
-err_input_register:
-	free_irq(client->irq, ts);
-err_fw_vers:
-	input_free_device(input_dev);
-err_input_alloc:
-	if (pdata->exit_hw)
-		pdata->exit_hw(client);
-	gpio_free(pdata->gpio_int);
-err_gpio_int:
-	kfree(ts);
+	msleep(200);
 
-	return ret;
-}
-
-static int auo_pixcir_remove(struct i2c_client *client)
-{
-	struct auo_pixcir_ts *ts = i2c_get_clientdata(client);
-	const struct auo_pixcir_ts_platdata *pdata = client->dev.platform_data;
+	version = i2c_smbus_read_byte_data(client, AUO_PIXCIR_REG_VERSION);
+	if (version < 0) {
+		error = version;
+		return error;
+	}
 
-	free_irq(client->irq, ts);
+	dev_info(&client->dev, "firmware version 0x%X\n", version);
 
-	input_unregister_device(ts->input);
+	error = auo_pixcir_int_config(ts, pdata->int_setting);
+	if (error)
+		return error;
 
-	if (pdata->exit_hw)
-		pdata->exit_hw(client);
+	error = devm_request_threaded_irq(&client->dev, client->irq,
+					  NULL, auo_pixcir_interrupt,
+					  IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+					  input_dev->name, ts);
+	if (error) {
+		dev_err(&client->dev, "irq %d requested failed, %d\n",
+			client->irq, error);
+		return error;
+	}
 
-	gpio_free(pdata->gpio_int);
+	/* stop device and put it into deep sleep until it is opened */
+	error = auo_pixcir_stop(ts);
+	if (error)
+		return error;
+
+	error = input_register_device(input_dev);
+	if (error) {
+		dev_err(&client->dev, "could not register input device, %d\n",
+			error);
+		return error;
+	}
 
-	kfree(ts);
+	i2c_set_clientdata(client, ts);
 
 	return 0;
 }
@@ -624,14 +678,22 @@ static const struct i2c_device_id auo_pixcir_idtable[] = {
 };
 MODULE_DEVICE_TABLE(i2c, auo_pixcir_idtable);
 
+#ifdef CONFIG_OF
+static struct of_device_id auo_pixcir_ts_dt_idtable[] = {
+	{ .compatible = "auo,auo_pixcir_ts" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, auo_pixcir_ts_dt_idtable);
+#endif
+
 static struct i2c_driver auo_pixcir_driver = {
 	.driver = {
 		.owner	= THIS_MODULE,
 		.name	= "auo_pixcir_ts",
 		.pm	= &auo_pixcir_pm_ops,
+		.of_match_table	= of_match_ptr(auo_pixcir_ts_dt_idtable),
 	},
 	.probe		= auo_pixcir_probe,
-	.remove		= auo_pixcir_remove,
 	.id_table	= auo_pixcir_idtable,
 };
 
diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c
index a917015..83fa1b1 100644
--- a/drivers/input/touchscreen/edt-ft5x06.c
+++ b/drivers/input/touchscreen/edt-ft5x06.c
@@ -440,8 +440,7 @@ static int edt_ft5x06_work_mode(struct edt_ft5x06_ts_data *tsdata)
 		return -EIO;
 	}
 
-	if (tsdata->raw_buffer)
-		kfree(tsdata->raw_buffer);
+	kfree(tsdata->raw_buffer);
 	tsdata->raw_buffer = NULL;
 
 	/* restore parameters */
diff --git a/drivers/input/touchscreen/eeti_ts.c b/drivers/input/touchscreen/eeti_ts.c
index 55255a9..8fe5086 100644
--- a/drivers/input/touchscreen/eeti_ts.c
+++ b/drivers/input/touchscreen/eeti_ts.c
@@ -206,8 +206,7 @@ static int eeti_ts_probe(struct i2c_client *client,
 	if (err < 0)
 		goto err1;
 
-	if (pdata)
-		priv->irq_active_high = pdata->irq_active_high;
+	priv->irq_active_high = pdata->irq_active_high;
 
 	irq_flags = priv->irq_active_high ?
 		IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING;
diff --git a/drivers/input/touchscreen/mc13783_ts.c b/drivers/input/touchscreen/mc13783_ts.c
index 02103b6..89308fe 100644
--- a/drivers/input/touchscreen/mc13783_ts.c
+++ b/drivers/input/touchscreen/mc13783_ts.c
@@ -250,17 +250,7 @@ static struct platform_driver mc13783_ts_driver = {
 	},
 };
 
-static int __init mc13783_ts_init(void)
-{
-	return platform_driver_probe(&mc13783_ts_driver, &mc13783_ts_probe);
-}
-module_init(mc13783_ts_init);
-
-static void __exit mc13783_ts_exit(void)
-{
-	platform_driver_unregister(&mc13783_ts_driver);
-}
-module_exit(mc13783_ts_exit);
+module_platform_driver_probe(mc13783_ts_driver, mc13783_ts_probe);
 
 MODULE_DESCRIPTION("MC13783 input touchscreen driver");
 MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
diff --git a/drivers/input/touchscreen/wm9712.c b/drivers/input/touchscreen/wm9712.c
index 6e743e3..16b5211 100644
--- a/drivers/input/touchscreen/wm9712.c
+++ b/drivers/input/touchscreen/wm9712.c
@@ -162,14 +162,14 @@ static void wm9712_phy_init(struct wm97xx *wm)
 	if (rpu) {
 		dig2 &= 0xffc0;
 		dig2 |= WM9712_RPU(rpu);
-		dev_dbg(wm->dev, "setting pen detect pull-up to %d Ohms",
+		dev_dbg(wm->dev, "setting pen detect pull-up to %d Ohms\n",
 			64000 / rpu);
 	}
 
 	/* WM9712 five wire */
 	if (five_wire) {
 		dig2 |= WM9712_45W;
-		dev_dbg(wm->dev, "setting 5-wire touchscreen mode.");
+		dev_dbg(wm->dev, "setting 5-wire touchscreen mode.\n");
 
 		if (pil) {
 			dev_warn(wm->dev, "pressure measurement is not "
@@ -182,21 +182,21 @@ static void wm9712_phy_init(struct wm97xx *wm)
 	if (pil == 2) {
 		dig2 |= WM9712_PIL;
 		dev_dbg(wm->dev,
-			"setting pressure measurement current to 400uA.");
+			"setting pressure measurement current to 400uA.\n");
 	} else if (pil)
 		dev_dbg(wm->dev,
-			"setting pressure measurement current to 200uA.");
+			"setting pressure measurement current to 200uA.\n");
 	if (!pil)
 		pressure = 0;
 
 	/* polling mode sample settling delay */
 	if (delay < 0 || delay > 15) {
-		dev_dbg(wm->dev, "supplied delay out of range.");
+		dev_dbg(wm->dev, "supplied delay out of range.\n");
 		delay = 4;
 	}
 	dig1 &= 0xff0f;
 	dig1 |= WM97XX_DELAY(delay);
-	dev_dbg(wm->dev, "setting adc sample delay to %d u Secs.",
+	dev_dbg(wm->dev, "setting adc sample delay to %d u Secs.\n",
 		delay_table[delay]);
 
 	/* mask */
@@ -285,7 +285,7 @@ static int wm9712_poll_sample(struct wm97xx *wm, int adcsel, int *sample)
 		if (is_pden(wm))
 			wm->pen_probably_down = 0;
 		else
-			dev_dbg(wm->dev, "adc sample timeout");
+			dev_dbg(wm->dev, "adc sample timeout\n");
 		return RC_PENUP;
 	}
 
@@ -295,15 +295,19 @@ static int wm9712_poll_sample(struct wm97xx *wm, int adcsel, int *sample)
 
 	/* check we have correct sample */
 	if ((*sample ^ adcsel) & WM97XX_ADCSEL_MASK) {
-		dev_dbg(wm->dev, "adc wrong sample, wanted %x got %x",
+		dev_dbg(wm->dev, "adc wrong sample, wanted %x got %x\n",
 			adcsel & WM97XX_ADCSEL_MASK,
 			*sample & WM97XX_ADCSEL_MASK);
-		return RC_PENUP;
+		return RC_AGAIN;
 	}
 
 	if (wants_pen && !(*sample & WM97XX_PEN_DOWN)) {
-		wm->pen_probably_down = 0;
-		return RC_PENUP;
+		/* Sometimes it reads a wrong value the first time. */
+		*sample = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
+		if (!(*sample & WM97XX_PEN_DOWN)) {
+			wm->pen_probably_down = 0;
+			return RC_PENUP;
+		}
 	}
 
 	return RC_VALID;
@@ -345,7 +349,7 @@ static int wm9712_poll_coord(struct wm97xx *wm, struct wm97xx_data *data)
 		if (is_pden(wm))
 			wm->pen_probably_down = 0;
 		else
-			dev_dbg(wm->dev, "adc sample timeout");
+			dev_dbg(wm->dev, "adc sample timeout\n");
 		return RC_PENUP;
 	}
 
diff --git a/drivers/input/touchscreen/wm97xx-core.c b/drivers/input/touchscreen/wm97xx-core.c
index 5dbe73a..7e45c9f 100644
--- a/drivers/input/touchscreen/wm97xx-core.c
+++ b/drivers/input/touchscreen/wm97xx-core.c
@@ -442,6 +442,16 @@ static int wm97xx_read_samples(struct wm97xx *wm)
 			"pen down: x=%x:%d, y=%x:%d, pressure=%x:%d\n",
 			data.x >> 12, data.x & 0xfff, data.y >> 12,
 			data.y & 0xfff, data.p >> 12, data.p & 0xfff);
+
+		if (abs_x[0] > (data.x & 0xfff) ||
+		    abs_x[1] < (data.x & 0xfff) ||
+		    abs_y[0] > (data.y & 0xfff) ||
+		    abs_y[1] < (data.y & 0xfff)) {
+			dev_dbg(wm->dev, "Measurement out of range, dropping it\n");
+			rc = RC_AGAIN;
+			goto out;
+		}
+
 		input_report_abs(wm->input_dev, ABS_X, data.x & 0xfff);
 		input_report_abs(wm->input_dev, ABS_Y, data.y & 0xfff);
 		input_report_abs(wm->input_dev, ABS_PRESSURE, data.p & 0xfff);
@@ -455,6 +465,7 @@ static int wm97xx_read_samples(struct wm97xx *wm)
 		wm->ts_reader_interval = wm->ts_reader_min_interval;
 	}
 
+out:
 	mutex_unlock(&wm->codec_mutex);
 	return rc;
 }
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index b287ca3..8301837 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -173,7 +173,7 @@ 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);
+	return PCI_DEVID(pdev->bus->number, pdev->devfn);
 }
 
 static struct iommu_dev_data *get_dev_data(struct device *dev)
@@ -649,26 +649,26 @@ retry:
 	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),
+		       PCI_BUS_NUM(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),
+		       PCI_BUS_NUM(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),
+		       PCI_BUS_NUM(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),
+		       PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid),
 		       domid, address, flags);
 		break;
 	case EVENT_TYPE_ILL_CMD:
@@ -682,13 +682,13 @@ retry:
 	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),
+		       PCI_BUS_NUM(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),
+		       PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid),
 		       address, flags);
 		break;
 	default:
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c
index e3c2d74..2f46881 100644
--- a/drivers/iommu/amd_iommu_init.c
+++ b/drivers/iommu/amd_iommu_init.c
@@ -406,7 +406,7 @@ 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)));
+	update_last_devid(PCI_DEVID(MMIO_GET_BUS(cap), MMIO_GET_LD(cap)));
 
 	return 0;
 }
@@ -423,7 +423,7 @@ static int __init find_last_devid_from_ivhd(struct ivhd_header *h)
 	p += sizeof(*h);
 	end += h->length;
 
-	find_last_devid_on_pci(PCI_BUS(h->devid),
+	find_last_devid_on_pci(PCI_BUS_NUM(h->devid),
 			PCI_SLOT(h->devid),
 			PCI_FUNC(h->devid),
 			h->cap_ptr);
@@ -784,10 +784,10 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu,
 
 			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_BUS_NUM(iommu->first_device),
 				    PCI_SLOT(iommu->first_device),
 				    PCI_FUNC(iommu->first_device),
-				    PCI_BUS(iommu->last_device),
+				    PCI_BUS_NUM(iommu->last_device),
 				    PCI_SLOT(iommu->last_device),
 				    PCI_FUNC(iommu->last_device),
 				    e->flags);
@@ -801,7 +801,7 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu,
 
 			DUMP_printk("  DEV_SELECT\t\t\t devid: %02x:%02x.%x "
 				    "flags: %02x\n",
-				    PCI_BUS(e->devid),
+				    PCI_BUS_NUM(e->devid),
 				    PCI_SLOT(e->devid),
 				    PCI_FUNC(e->devid),
 				    e->flags);
@@ -813,7 +813,7 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu,
 
 			DUMP_printk("  DEV_SELECT_RANGE_START\t "
 				    "devid: %02x:%02x.%x flags: %02x\n",
-				    PCI_BUS(e->devid),
+				    PCI_BUS_NUM(e->devid),
 				    PCI_SLOT(e->devid),
 				    PCI_FUNC(e->devid),
 				    e->flags);
@@ -827,11 +827,11 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu,
 
 			DUMP_printk("  DEV_ALIAS\t\t\t devid: %02x:%02x.%x "
 				    "flags: %02x devid_to: %02x:%02x.%x\n",
-				    PCI_BUS(e->devid),
+				    PCI_BUS_NUM(e->devid),
 				    PCI_SLOT(e->devid),
 				    PCI_FUNC(e->devid),
 				    e->flags,
-				    PCI_BUS(e->ext >> 8),
+				    PCI_BUS_NUM(e->ext >> 8),
 				    PCI_SLOT(e->ext >> 8),
 				    PCI_FUNC(e->ext >> 8));
 
@@ -846,11 +846,11 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu,
 			DUMP_printk("  DEV_ALIAS_RANGE\t\t "
 				    "devid: %02x:%02x.%x flags: %02x "
 				    "devid_to: %02x:%02x.%x\n",
-				    PCI_BUS(e->devid),
+				    PCI_BUS_NUM(e->devid),
 				    PCI_SLOT(e->devid),
 				    PCI_FUNC(e->devid),
 				    e->flags,
-				    PCI_BUS(e->ext >> 8),
+				    PCI_BUS_NUM(e->ext >> 8),
 				    PCI_SLOT(e->ext >> 8),
 				    PCI_FUNC(e->ext >> 8));
 
@@ -864,7 +864,7 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu,
 
 			DUMP_printk("  DEV_EXT_SELECT\t\t devid: %02x:%02x.%x "
 				    "flags: %02x ext: %08x\n",
-				    PCI_BUS(e->devid),
+				    PCI_BUS_NUM(e->devid),
 				    PCI_SLOT(e->devid),
 				    PCI_FUNC(e->devid),
 				    e->flags, e->ext);
@@ -877,7 +877,7 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu,
 
 			DUMP_printk("  DEV_EXT_SELECT_RANGE\t devid: "
 				    "%02x:%02x.%x flags: %02x ext: %08x\n",
-				    PCI_BUS(e->devid),
+				    PCI_BUS_NUM(e->devid),
 				    PCI_SLOT(e->devid),
 				    PCI_FUNC(e->devid),
 				    e->flags, e->ext);
@@ -890,7 +890,7 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu,
 		case IVHD_DEV_RANGE_END:
 
 			DUMP_printk("  DEV_RANGE_END\t\t devid: %02x:%02x.%x\n",
-				    PCI_BUS(e->devid),
+				    PCI_BUS_NUM(e->devid),
 				    PCI_SLOT(e->devid),
 				    PCI_FUNC(e->devid));
 
@@ -924,7 +924,7 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu,
 
 			DUMP_printk("  DEV_SPECIAL(%s[%d])\t\tdevid: %02x:%02x.%x\n",
 				    var, (int)handle,
-				    PCI_BUS(devid),
+				    PCI_BUS_NUM(devid),
 				    PCI_SLOT(devid),
 				    PCI_FUNC(devid));
 
@@ -1086,7 +1086,7 @@ static int __init init_iommu_all(struct acpi_table_header *table)
 
 			DUMP_printk("device: %02x:%02x.%01x cap: %04x "
 				    "seg: %d flags: %01x info %04x\n",
-				    PCI_BUS(h->devid), PCI_SLOT(h->devid),
+				    PCI_BUS_NUM(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",
@@ -1116,7 +1116,7 @@ static int iommu_init_pci(struct amd_iommu *iommu)
 	int cap_ptr = iommu->cap_ptr;
 	u32 range, misc, low, high;
 
-	iommu->dev = pci_get_bus_and_slot(PCI_BUS(iommu->devid),
+	iommu->dev = pci_get_bus_and_slot(PCI_BUS_NUM(iommu->devid),
 					  iommu->devid & 0xff);
 	if (!iommu->dev)
 		return -ENODEV;
@@ -1128,9 +1128,9 @@ static int iommu_init_pci(struct amd_iommu *iommu)
 	pci_read_config_dword(iommu->dev, cap_ptr + MMIO_MISC_OFFSET,
 			      &misc);
 
-	iommu->first_device = calc_devid(MMIO_GET_BUS(range),
+	iommu->first_device = PCI_DEVID(MMIO_GET_BUS(range),
 					 MMIO_GET_FD(range));
-	iommu->last_device = calc_devid(MMIO_GET_BUS(range),
+	iommu->last_device = PCI_DEVID(MMIO_GET_BUS(range),
 					MMIO_GET_LD(range));
 
 	if (!(iommu->cap & (1 << IOMMU_CAP_IOTLB)))
@@ -1388,8 +1388,8 @@ static int __init init_unity_map_range(struct ivmd_header *m)
 
 	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_BUS_NUM(e->devid_start), PCI_SLOT(e->devid_start),
+		    PCI_FUNC(e->devid_start), PCI_BUS_NUM(e->devid_end),
 		    PCI_SLOT(e->devid_end), PCI_FUNC(e->devid_end),
 		    e->address_start, e->address_end, m->flags);
 
diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h
index e38ab43..ec36cf6 100644
--- a/drivers/iommu/amd_iommu_types.h
+++ b/drivers/iommu/amd_iommu_types.h
@@ -24,6 +24,7 @@
 #include <linux/mutex.h>
 #include <linux/list.h>
 #include <linux/spinlock.h>
+#include <linux/pci.h>
 
 /*
  * Maximum number of IOMMUs supported
@@ -315,9 +316,6 @@
 
 #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
@@ -703,13 +701,6 @@ extern int amd_iommu_max_glx_val;
  */
 extern void iommu_flush_all_caches(struct amd_iommu *iommu);
 
-/* 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;
-}
-
 static inline int get_ioapic_devid(int id)
 {
 	struct devid_map *entry;
diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c
index e5cdaf8..9f8aa07 100644
--- a/drivers/iommu/dmar.c
+++ b/drivers/iommu/dmar.c
@@ -1204,7 +1204,7 @@ irqreturn_t dmar_fault(int irq, void *dev_id)
 
 	/* TBD: ignore advanced fault log currently */
 	if (!(fault_status & DMA_FSTS_PPF))
-		goto clear_rest;
+		goto unlock_exit;
 
 	fault_index = dma_fsts_fault_record_index(fault_status);
 	reg = cap_fault_reg_offset(iommu->cap);
@@ -1245,11 +1245,10 @@ irqreturn_t dmar_fault(int irq, void *dev_id)
 			fault_index = 0;
 		raw_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);
 
+	writel(DMA_FSTS_PFO | DMA_FSTS_PPF, iommu->reg + DMAR_FSTS_REG);
+
+unlock_exit:
 	raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
 	return IRQ_HANDLED;
 }
@@ -1297,6 +1296,7 @@ int __init enable_drhd_fault_handling(void)
 	for_each_drhd_unit(drhd) {
 		int ret;
 		struct intel_iommu *iommu = drhd->iommu;
+		u32 fault_status;
 		ret = dmar_set_interrupt(iommu);
 
 		if (ret) {
@@ -1309,6 +1309,8 @@ int __init enable_drhd_fault_handling(void)
 		 * Clear any previous faults.
 		 */
 		dmar_fault(iommu->irq, iommu);
+		fault_status = readl(iommu->reg + DMAR_FSTS_REG);
+		writel(fault_status, iommu->reg + DMAR_FSTS_REG);
 	}
 
 	return 0;
diff --git a/drivers/ipack/carriers/tpci200.c b/drivers/ipack/carriers/tpci200.c
index 0246b1f..c276fde 100644
--- a/drivers/ipack/carriers/tpci200.c
+++ b/drivers/ipack/carriers/tpci200.c
@@ -480,6 +480,7 @@ static void tpci200_release_device(struct ipack_device *dev)
 
 static int tpci200_create_device(struct tpci200_board *tpci200, int i)
 {
+	int ret;
 	enum ipack_space space;
 	struct ipack_device *dev =
 		kzalloc(sizeof(struct ipack_device), GFP_KERNEL);
@@ -495,7 +496,18 @@ static int tpci200_create_device(struct tpci200_board *tpci200, int i)
 			+ tpci200_space_interval[space] * i;
 		dev->region[space].size = tpci200_space_size[space];
 	}
-	return ipack_device_register(dev);
+
+	ret = ipack_device_init(dev);
+	if (ret < 0) {
+		ipack_put_device(dev);
+		return ret;
+	}
+
+	ret = ipack_device_add(dev);
+	if (ret < 0)
+		ipack_put_device(dev);
+
+	return ret;
 }
 
 static int tpci200_pci_probe(struct pci_dev *pdev,
diff --git a/drivers/ipack/ipack.c b/drivers/ipack/ipack.c
index 7ec6b20..6e066c5 100644
--- a/drivers/ipack/ipack.c
+++ b/drivers/ipack/ipack.c
@@ -227,7 +227,7 @@ static int ipack_unregister_bus_member(struct device *dev, void *data)
 	struct ipack_bus_device *bus = data;
 
 	if (idev->bus == bus)
-		ipack_device_unregister(idev);
+		ipack_device_del(idev);
 
 	return 1;
 }
@@ -419,7 +419,7 @@ out:
 	return ret;
 }
 
-int ipack_device_register(struct ipack_device *dev)
+int ipack_device_init(struct ipack_device *dev)
 {
 	int ret;
 
@@ -428,6 +428,7 @@ int ipack_device_register(struct ipack_device *dev)
 	dev->dev.parent = dev->bus->parent;
 	dev_set_name(&dev->dev,
 		     "ipack-dev.%u.%u", dev->bus->bus_nr, dev->slot);
+	device_initialize(&dev->dev);
 
 	if (dev->bus->ops->set_clockrate(dev, 8))
 		dev_warn(&dev->dev, "failed to switch to 8 MHz operation for reading of device ID.\n");
@@ -447,19 +448,34 @@ int ipack_device_register(struct ipack_device *dev)
 			dev_err(&dev->dev, "failed to switch to 32 MHz operation.\n");
 	}
 
-	ret = device_register(&dev->dev);
-	if (ret < 0)
-		kfree(dev->id);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ipack_device_init);
 
-	return ret;
+int ipack_device_add(struct ipack_device *dev)
+{
+	return device_add(&dev->dev);
+}
+EXPORT_SYMBOL_GPL(ipack_device_add);
+
+void ipack_device_del(struct ipack_device *dev)
+{
+	device_del(&dev->dev);
+	ipack_put_device(dev);
+}
+EXPORT_SYMBOL_GPL(ipack_device_del);
+
+void ipack_get_device(struct ipack_device *dev)
+{
+	get_device(&dev->dev);
 }
-EXPORT_SYMBOL_GPL(ipack_device_register);
+EXPORT_SYMBOL_GPL(ipack_get_device);
 
-void ipack_device_unregister(struct ipack_device *dev)
+void ipack_put_device(struct ipack_device *dev)
 {
-	device_unregister(&dev->dev);
+	put_device(&dev->dev);
 }
-EXPORT_SYMBOL_GPL(ipack_device_unregister);
+EXPORT_SYMBOL_GPL(ipack_put_device);
 
 static int __init ipack_init(void)
 {
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index a350969..4a33351 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -25,6 +25,14 @@ config ARM_VIC_NR
 	  The maximum number of VICs available in the system, for
 	  power management.
 
+config RENESAS_INTC_IRQPIN
+	bool
+	select IRQ_DOMAIN
+
+config RENESAS_IRQC
+	bool
+	select IRQ_DOMAIN
+
 config VERSATILE_FPGA_IRQ
 	bool
 	select IRQ_DOMAIN
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 98e3b87..7bdcdfe 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -2,10 +2,15 @@ obj-$(CONFIG_IRQCHIP)			+= irqchip.o
 
 obj-$(CONFIG_ARCH_BCM2835)		+= irq-bcm2835.o
 obj-$(CONFIG_ARCH_EXYNOS)		+= exynos-combiner.o
+obj-$(CONFIG_ARCH_MXS)			+= irq-mxs.o
+obj-$(CONFIG_ARCH_S3C24XX)		+= irq-s3c24xx.o
 obj-$(CONFIG_METAG)			+= irq-metag-ext.o
 obj-$(CONFIG_METAG_PERFCOUNTER_IRQS)	+= irq-metag.o
 obj-$(CONFIG_ARCH_SUNXI)		+= irq-sunxi.o
 obj-$(CONFIG_ARCH_SPEAR3XX)		+= spear-shirq.o
 obj-$(CONFIG_ARM_GIC)			+= irq-gic.o
 obj-$(CONFIG_ARM_VIC)			+= irq-vic.o
+obj-$(CONFIG_RENESAS_INTC_IRQPIN)	+= irq-renesas-intc-irqpin.o
+obj-$(CONFIG_RENESAS_IRQC)		+= irq-renesas-irqc.o
+obj-$(CONFIG_SIRF_IRQ)			+= irq-sirfsoc.o
 obj-$(CONFIG_VERSATILE_FPGA_IRQ)	+= irq-versatile-fpga.o
diff --git a/drivers/irqchip/exynos-combiner.c b/drivers/irqchip/exynos-combiner.c
index 04d86a9..02492ab 100644
--- a/drivers/irqchip/exynos-combiner.c
+++ b/drivers/irqchip/exynos-combiner.c
@@ -13,6 +13,7 @@
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/irqdomain.h>
+#include <linux/irqchip/chained_irq.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <asm/mach/irq.h>
@@ -31,6 +32,7 @@ struct combiner_chip_data {
 	unsigned int irq_offset;
 	unsigned int irq_mask;
 	void __iomem *base;
+	unsigned int parent_irq;
 };
 
 static struct irq_domain *combiner_irq_domain;
@@ -87,22 +89,46 @@ static void combiner_handle_cascade_irq(unsigned int irq, struct irq_desc *desc)
 	chained_irq_exit(chip, desc);
 }
 
+#ifdef CONFIG_SMP
+static int combiner_set_affinity(struct irq_data *d,
+				 const struct cpumask *mask_val, bool force)
+{
+	struct combiner_chip_data *chip_data = irq_data_get_irq_chip_data(d);
+	struct irq_chip *chip = irq_get_chip(chip_data->parent_irq);
+	struct irq_data *data = irq_get_irq_data(chip_data->parent_irq);
+
+	if (chip && chip->irq_set_affinity)
+		return chip->irq_set_affinity(data, mask_val, force);
+	else
+		return -EINVAL;
+}
+#endif
+
 static struct irq_chip combiner_chip = {
-	.name		= "COMBINER",
-	.irq_mask	= combiner_mask_irq,
-	.irq_unmask	= combiner_unmask_irq,
+	.name			= "COMBINER",
+	.irq_mask		= combiner_mask_irq,
+	.irq_unmask		= combiner_unmask_irq,
+#ifdef CONFIG_SMP
+	.irq_set_affinity	= combiner_set_affinity,
+#endif
 };
 
-static void __init combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq)
+static unsigned int max_combiner_nr(void)
 {
-	unsigned int max_nr;
-
 	if (soc_is_exynos5250())
-		max_nr = EXYNOS5_MAX_COMBINER_NR;
+		return EXYNOS5_MAX_COMBINER_NR;
+	else if (soc_is_exynos4412())
+		return EXYNOS4412_MAX_COMBINER_NR;
+	else if (soc_is_exynos4212())
+		return EXYNOS4212_MAX_COMBINER_NR;
 	else
-		max_nr = EXYNOS4_MAX_COMBINER_NR;
+		return EXYNOS4210_MAX_COMBINER_NR;
+}
 
-	if (combiner_nr >= max_nr)
+static void __init combiner_cascade_irq(unsigned int combiner_nr,
+					unsigned int irq)
+{
+	if (combiner_nr >= max_combiner_nr())
 		BUG();
 	if (irq_set_handler_data(irq, &combiner_data[combiner_nr]) != 0)
 		BUG();
@@ -110,12 +136,13 @@ static void __init combiner_cascade_irq(unsigned int combiner_nr, unsigned int i
 }
 
 static void __init combiner_init_one(unsigned int combiner_nr,
-				     void __iomem *base)
+				     void __iomem *base, unsigned int irq)
 {
 	combiner_data[combiner_nr].base = base;
 	combiner_data[combiner_nr].irq_offset = irq_find_mapping(
 		combiner_irq_domain, combiner_nr * MAX_IRQ_IN_COMBINER);
 	combiner_data[combiner_nr].irq_mask = 0xff << ((combiner_nr % 4) << 3);
+	combiner_data[combiner_nr].parent_irq = irq;
 
 	/* Disable all interrupts */
 	__raw_writel(combiner_data[combiner_nr].irq_mask,
@@ -166,23 +193,38 @@ static struct irq_domain_ops combiner_irq_domain_ops = {
 	.map	= combiner_irq_domain_map,
 };
 
+static unsigned int exynos4x12_combiner_extra_irq(int group)
+{
+	switch (group) {
+	case 16:
+		return IRQ_SPI(107);
+	case 17:
+		return IRQ_SPI(108);
+	case 18:
+		return IRQ_SPI(48);
+	case 19:
+		return IRQ_SPI(42);
+	default:
+		return 0;
+	}
+}
+
 void __init combiner_init(void __iomem *combiner_base,
 			  struct device_node *np)
 {
 	int i, irq, irq_base;
 	unsigned int max_nr, nr_irq;
 
+	max_nr = max_combiner_nr();
+
 	if (np) {
 		if (of_property_read_u32(np, "samsung,combiner-nr", &max_nr)) {
-			pr_warning("%s: number of combiners not specified, "
+			pr_info("%s: number of combiners not specified, "
 				"setting default as %d.\n",
-				__func__, EXYNOS4_MAX_COMBINER_NR);
-			max_nr = EXYNOS4_MAX_COMBINER_NR;
+				__func__, max_nr);
 		}
-	} else {
-		max_nr = soc_is_exynos5250() ? EXYNOS5_MAX_COMBINER_NR :
-						EXYNOS4_MAX_COMBINER_NR;
 	}
+
 	nr_irq = max_nr * MAX_IRQ_IN_COMBINER;
 
 	irq_base = irq_alloc_descs(COMBINER_IRQ(0, 0), 1, nr_irq, 0);
@@ -199,12 +241,15 @@ void __init combiner_init(void __iomem *combiner_base,
 	}
 
 	for (i = 0; i < max_nr; i++) {
-		combiner_init_one(i, combiner_base + (i >> 2) * 0x10);
-		irq = IRQ_SPI(i);
+		if (i < EXYNOS4210_MAX_COMBINER_NR || soc_is_exynos5250())
+			irq = IRQ_SPI(i);
+		else
+			irq = exynos4x12_combiner_extra_irq(i);
 #ifdef CONFIG_OF
 		if (np)
 			irq = irq_of_parse_and_map(np, i);
 #endif
+		combiner_init_one(i, combiner_base + (i >> 2) * 0x10, irq);
 		combiner_cascade_irq(i, irq);
 	}
 }
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index a32e0d5..47aea33 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -28,6 +28,7 @@
 #include <linux/module.h>
 #include <linux/list.h>
 #include <linux/smp.h>
+#include <linux/cpu.h>
 #include <linux/cpu_pm.h>
 #include <linux/cpumask.h>
 #include <linux/io.h>
@@ -38,12 +39,12 @@
 #include <linux/interrupt.h>
 #include <linux/percpu.h>
 #include <linux/slab.h>
+#include <linux/irqchip/chained_irq.h>
 #include <linux/irqchip/arm-gic.h>
 
 #include <asm/irq.h>
 #include <asm/exception.h>
 #include <asm/smp_plat.h>
-#include <asm/mach/irq.h>
 
 #include "irqchip.h"
 
@@ -127,7 +128,7 @@ static inline void gic_set_base_accessor(struct gic_chip_data *data,
 #else
 #define gic_data_dist_base(d)	((d)->dist_base.common_base)
 #define gic_data_cpu_base(d)	((d)->cpu_base.common_base)
-#define gic_set_base_accessor(d,f)
+#define gic_set_base_accessor(d, f)
 #endif
 
 static inline void __iomem *gic_dist_base(struct irq_data *d)
@@ -323,7 +324,7 @@ static void gic_handle_cascade_irq(unsigned int irq, struct irq_desc *desc)
 
 	cascade_irq = irq_find_mapping(chip_data->domain, gic_irq);
 	if (unlikely(gic_irq < 32 || gic_irq > 1020))
-		do_bad_IRQ(cascade_irq, desc);
+		handle_bad_irq(cascade_irq, desc);
 	else
 		generic_handle_irq(cascade_irq);
 
@@ -699,6 +700,25 @@ static int gic_irq_domain_xlate(struct irq_domain *d,
 	return 0;
 }
 
+#ifdef CONFIG_SMP
+static int __cpuinit gic_secondary_init(struct notifier_block *nfb,
+					unsigned long action, void *hcpu)
+{
+	if (action == CPU_STARTING)
+		gic_cpu_init(&gic_data[0]);
+	return NOTIFY_OK;
+}
+
+/*
+ * Notifier for enabling the GIC CPU interface. Set an arbitrarily high
+ * priority because the GIC needs to be up before the ARM generic timers.
+ */
+static struct notifier_block __cpuinitdata gic_cpu_notifier = {
+	.notifier_call = gic_secondary_init,
+	.priority = 100,
+};
+#endif
+
 const struct irq_domain_ops gic_irq_domain_ops = {
 	.map = gic_irq_domain_map,
 	.xlate = gic_irq_domain_xlate,
@@ -789,6 +809,7 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start,
 
 #ifdef CONFIG_SMP
 	set_smp_cross_call(gic_raise_softirq);
+	register_cpu_notifier(&gic_cpu_notifier);
 #endif
 
 	set_handle_irq(gic_handle_irq);
@@ -799,15 +820,8 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start,
 	gic_pm_init(gic);
 }
 
-void __cpuinit gic_secondary_init(unsigned int gic_nr)
-{
-	BUG_ON(gic_nr >= MAX_GIC_NR);
-
-	gic_cpu_init(&gic_data[gic_nr]);
-}
-
 #ifdef CONFIG_OF
-static int gic_cnt __initdata = 0;
+static int gic_cnt __initdata;
 
 int __init gic_of_init(struct device_node *node, struct device_node *parent)
 {
diff --git a/drivers/irqchip/irq-mxs.c b/drivers/irqchip/irq-mxs.c
new file mode 100644
index 0000000..29889bb
--- /dev/null
+++ b/drivers/irqchip/irq-mxs.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2009-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/kernel.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/stmp_device.h>
+#include <asm/exception.h>
+
+#include "irqchip.h"
+
+#define HW_ICOLL_VECTOR				0x0000
+#define HW_ICOLL_LEVELACK			0x0010
+#define HW_ICOLL_CTRL				0x0020
+#define HW_ICOLL_STAT_OFFSET			0x0070
+#define HW_ICOLL_INTERRUPTn_SET(n)		(0x0124 + (n) * 0x10)
+#define HW_ICOLL_INTERRUPTn_CLR(n)		(0x0128 + (n) * 0x10)
+#define BM_ICOLL_INTERRUPTn_ENABLE		0x00000004
+#define BV_ICOLL_LEVELACK_IRQLEVELACK__LEVEL0	0x1
+
+#define ICOLL_NUM_IRQS		128
+
+static void __iomem *icoll_base;
+static struct irq_domain *icoll_domain;
+
+static void icoll_ack_irq(struct irq_data *d)
+{
+	/*
+	 * The Interrupt Collector is able to prioritize irqs.
+	 * Currently only level 0 is used. So acking can use
+	 * BV_ICOLL_LEVELACK_IRQLEVELACK__LEVEL0 unconditionally.
+	 */
+	__raw_writel(BV_ICOLL_LEVELACK_IRQLEVELACK__LEVEL0,
+			icoll_base + HW_ICOLL_LEVELACK);
+}
+
+static void icoll_mask_irq(struct irq_data *d)
+{
+	__raw_writel(BM_ICOLL_INTERRUPTn_ENABLE,
+			icoll_base + HW_ICOLL_INTERRUPTn_CLR(d->hwirq));
+}
+
+static void icoll_unmask_irq(struct irq_data *d)
+{
+	__raw_writel(BM_ICOLL_INTERRUPTn_ENABLE,
+			icoll_base + HW_ICOLL_INTERRUPTn_SET(d->hwirq));
+}
+
+static struct irq_chip mxs_icoll_chip = {
+	.irq_ack = icoll_ack_irq,
+	.irq_mask = icoll_mask_irq,
+	.irq_unmask = icoll_unmask_irq,
+};
+
+asmlinkage void __exception_irq_entry icoll_handle_irq(struct pt_regs *regs)
+{
+	u32 irqnr;
+
+	do {
+		irqnr = __raw_readl(icoll_base + HW_ICOLL_STAT_OFFSET);
+		if (irqnr != 0x7f) {
+			__raw_writel(irqnr, icoll_base + HW_ICOLL_VECTOR);
+			irqnr = irq_find_mapping(icoll_domain, irqnr);
+			handle_IRQ(irqnr, regs);
+			continue;
+		}
+		break;
+	} while (1);
+}
+
+static int icoll_irq_domain_map(struct irq_domain *d, unsigned int virq,
+				irq_hw_number_t hw)
+{
+	irq_set_chip_and_handler(virq, &mxs_icoll_chip, handle_level_irq);
+	set_irq_flags(virq, IRQF_VALID);
+
+	return 0;
+}
+
+static struct irq_domain_ops icoll_irq_domain_ops = {
+	.map = icoll_irq_domain_map,
+	.xlate = irq_domain_xlate_onecell,
+};
+
+static void __init icoll_of_init(struct device_node *np,
+			  struct device_node *interrupt_parent)
+{
+	icoll_base = of_iomap(np, 0);
+	WARN_ON(!icoll_base);
+
+	/*
+	 * Interrupt Collector reset, which initializes the priority
+	 * for each irq to level 0.
+	 */
+	stmp_reset_block(icoll_base + HW_ICOLL_CTRL);
+
+	icoll_domain = irq_domain_add_linear(np, ICOLL_NUM_IRQS,
+					     &icoll_irq_domain_ops, NULL);
+	WARN_ON(!icoll_domain);
+}
+IRQCHIP_DECLARE(mxs, "fsl,icoll", icoll_of_init);
diff --git a/drivers/irqchip/irq-renesas-intc-irqpin.c b/drivers/irqchip/irq-renesas-intc-irqpin.c
new file mode 100644
index 0000000..5a68e5a
--- /dev/null
+++ b/drivers/irqchip/irq-renesas-intc-irqpin.c
@@ -0,0 +1,547 @@
+/*
+ * Renesas INTC External IRQ Pin Driver
+ *
+ *  Copyright (C) 2013 Magnus Damm
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either 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/init.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/platform_data/irq-renesas-intc-irqpin.h>
+
+#define INTC_IRQPIN_MAX 8 /* maximum 8 interrupts per driver instance */
+
+#define INTC_IRQPIN_REG_SENSE 0 /* ICRn */
+#define INTC_IRQPIN_REG_PRIO 1 /* INTPRInn */
+#define INTC_IRQPIN_REG_SOURCE 2 /* INTREQnn */
+#define INTC_IRQPIN_REG_MASK 3 /* INTMSKnn */
+#define INTC_IRQPIN_REG_CLEAR 4 /* INTMSKCLRnn */
+#define INTC_IRQPIN_REG_NR 5
+
+/* INTC external IRQ PIN hardware register access:
+ *
+ * SENSE is read-write 32-bit with 2-bits or 4-bits per IRQ (*)
+ * PRIO is read-write 32-bit with 4-bits per IRQ (**)
+ * SOURCE is read-only 32-bit or 8-bit with 1-bit per IRQ (***)
+ * MASK is write-only 32-bit or 8-bit with 1-bit per IRQ (***)
+ * CLEAR is write-only 32-bit or 8-bit with 1-bit per IRQ (***)
+ *
+ * (*) May be accessed by more than one driver instance - lock needed
+ * (**) Read-modify-write access by one driver instance - lock needed
+ * (***) Accessed by one driver instance only - no locking needed
+ */
+
+struct intc_irqpin_iomem {
+	void __iomem *iomem;
+	unsigned long (*read)(void __iomem *iomem);
+	void (*write)(void __iomem *iomem, unsigned long data);
+	int width;
+};
+
+struct intc_irqpin_irq {
+	int hw_irq;
+	int requested_irq;
+	int domain_irq;
+	struct intc_irqpin_priv *p;
+};
+
+struct intc_irqpin_priv {
+	struct intc_irqpin_iomem iomem[INTC_IRQPIN_REG_NR];
+	struct intc_irqpin_irq irq[INTC_IRQPIN_MAX];
+	struct renesas_intc_irqpin_config config;
+	unsigned int number_of_irqs;
+	struct platform_device *pdev;
+	struct irq_chip irq_chip;
+	struct irq_domain *irq_domain;
+	bool shared_irqs;
+	u8 shared_irq_mask;
+};
+
+static unsigned long intc_irqpin_read32(void __iomem *iomem)
+{
+	return ioread32(iomem);
+}
+
+static unsigned long intc_irqpin_read8(void __iomem *iomem)
+{
+	return ioread8(iomem);
+}
+
+static void intc_irqpin_write32(void __iomem *iomem, unsigned long data)
+{
+	iowrite32(data, iomem);
+}
+
+static void intc_irqpin_write8(void __iomem *iomem, unsigned long data)
+{
+	iowrite8(data, iomem);
+}
+
+static inline unsigned long intc_irqpin_read(struct intc_irqpin_priv *p,
+					     int reg)
+{
+	struct intc_irqpin_iomem *i = &p->iomem[reg];
+
+	return i->read(i->iomem);
+}
+
+static inline void intc_irqpin_write(struct intc_irqpin_priv *p,
+				     int reg, unsigned long data)
+{
+	struct intc_irqpin_iomem *i = &p->iomem[reg];
+
+	i->write(i->iomem, data);
+}
+
+static inline unsigned long intc_irqpin_hwirq_mask(struct intc_irqpin_priv *p,
+						   int reg, int hw_irq)
+{
+	return BIT((p->iomem[reg].width - 1) - hw_irq);
+}
+
+static inline void intc_irqpin_irq_write_hwirq(struct intc_irqpin_priv *p,
+					       int reg, int hw_irq)
+{
+	intc_irqpin_write(p, reg, intc_irqpin_hwirq_mask(p, reg, hw_irq));
+}
+
+static DEFINE_RAW_SPINLOCK(intc_irqpin_lock); /* only used by slow path */
+
+static void intc_irqpin_read_modify_write(struct intc_irqpin_priv *p,
+					  int reg, int shift,
+					  int width, int value)
+{
+	unsigned long flags;
+	unsigned long tmp;
+
+	raw_spin_lock_irqsave(&intc_irqpin_lock, flags);
+
+	tmp = intc_irqpin_read(p, reg);
+	tmp &= ~(((1 << width) - 1) << shift);
+	tmp |= value << shift;
+	intc_irqpin_write(p, reg, tmp);
+
+	raw_spin_unlock_irqrestore(&intc_irqpin_lock, flags);
+}
+
+static void intc_irqpin_mask_unmask_prio(struct intc_irqpin_priv *p,
+					 int irq, int do_mask)
+{
+	int bitfield_width = 4; /* PRIO assumed to have fixed bitfield width */
+	int shift = (7 - irq) * bitfield_width; /* PRIO assumed to be 32-bit */
+
+	intc_irqpin_read_modify_write(p, INTC_IRQPIN_REG_PRIO,
+				      shift, bitfield_width,
+				      do_mask ? 0 : (1 << bitfield_width) - 1);
+}
+
+static int intc_irqpin_set_sense(struct intc_irqpin_priv *p, int irq, int value)
+{
+	int bitfield_width = p->config.sense_bitfield_width;
+	int shift = (7 - irq) * bitfield_width; /* SENSE assumed to be 32-bit */
+
+	dev_dbg(&p->pdev->dev, "sense irq = %d, mode = %d\n", irq, value);
+
+	if (value >= (1 << bitfield_width))
+		return -EINVAL;
+
+	intc_irqpin_read_modify_write(p, INTC_IRQPIN_REG_SENSE, shift,
+				      bitfield_width, value);
+	return 0;
+}
+
+static void intc_irqpin_dbg(struct intc_irqpin_irq *i, char *str)
+{
+	dev_dbg(&i->p->pdev->dev, "%s (%d:%d:%d)\n",
+		str, i->requested_irq, i->hw_irq, i->domain_irq);
+}
+
+static void intc_irqpin_irq_enable(struct irq_data *d)
+{
+	struct intc_irqpin_priv *p = irq_data_get_irq_chip_data(d);
+	int hw_irq = irqd_to_hwirq(d);
+
+	intc_irqpin_dbg(&p->irq[hw_irq], "enable");
+	intc_irqpin_irq_write_hwirq(p, INTC_IRQPIN_REG_CLEAR, hw_irq);
+}
+
+static void intc_irqpin_irq_disable(struct irq_data *d)
+{
+	struct intc_irqpin_priv *p = irq_data_get_irq_chip_data(d);
+	int hw_irq = irqd_to_hwirq(d);
+
+	intc_irqpin_dbg(&p->irq[hw_irq], "disable");
+	intc_irqpin_irq_write_hwirq(p, INTC_IRQPIN_REG_MASK, hw_irq);
+}
+
+static void intc_irqpin_shared_irq_enable(struct irq_data *d)
+{
+	struct intc_irqpin_priv *p = irq_data_get_irq_chip_data(d);
+	int hw_irq = irqd_to_hwirq(d);
+
+	intc_irqpin_dbg(&p->irq[hw_irq], "shared enable");
+	intc_irqpin_irq_write_hwirq(p, INTC_IRQPIN_REG_CLEAR, hw_irq);
+
+	p->shared_irq_mask &= ~BIT(hw_irq);
+}
+
+static void intc_irqpin_shared_irq_disable(struct irq_data *d)
+{
+	struct intc_irqpin_priv *p = irq_data_get_irq_chip_data(d);
+	int hw_irq = irqd_to_hwirq(d);
+
+	intc_irqpin_dbg(&p->irq[hw_irq], "shared disable");
+	intc_irqpin_irq_write_hwirq(p, INTC_IRQPIN_REG_MASK, hw_irq);
+
+	p->shared_irq_mask |= BIT(hw_irq);
+}
+
+static void intc_irqpin_irq_enable_force(struct irq_data *d)
+{
+	struct intc_irqpin_priv *p = irq_data_get_irq_chip_data(d);
+	int irq = p->irq[irqd_to_hwirq(d)].requested_irq;
+
+	intc_irqpin_irq_enable(d);
+
+	/* enable interrupt through parent interrupt controller,
+	 * assumes non-shared interrupt with 1:1 mapping
+	 * needed for busted IRQs on some SoCs like sh73a0
+	 */
+	irq_get_chip(irq)->irq_unmask(irq_get_irq_data(irq));
+}
+
+static void intc_irqpin_irq_disable_force(struct irq_data *d)
+{
+	struct intc_irqpin_priv *p = irq_data_get_irq_chip_data(d);
+	int irq = p->irq[irqd_to_hwirq(d)].requested_irq;
+
+	/* disable interrupt through parent interrupt controller,
+	 * assumes non-shared interrupt with 1:1 mapping
+	 * needed for busted IRQs on some SoCs like sh73a0
+	 */
+	irq_get_chip(irq)->irq_mask(irq_get_irq_data(irq));
+	intc_irqpin_irq_disable(d);
+}
+
+#define INTC_IRQ_SENSE_VALID 0x10
+#define INTC_IRQ_SENSE(x) (x + INTC_IRQ_SENSE_VALID)
+
+static unsigned char intc_irqpin_sense[IRQ_TYPE_SENSE_MASK + 1] = {
+	[IRQ_TYPE_EDGE_FALLING] = INTC_IRQ_SENSE(0x00),
+	[IRQ_TYPE_EDGE_RISING] = INTC_IRQ_SENSE(0x01),
+	[IRQ_TYPE_LEVEL_LOW] = INTC_IRQ_SENSE(0x02),
+	[IRQ_TYPE_LEVEL_HIGH] = INTC_IRQ_SENSE(0x03),
+	[IRQ_TYPE_EDGE_BOTH] = INTC_IRQ_SENSE(0x04),
+};
+
+static int intc_irqpin_irq_set_type(struct irq_data *d, unsigned int type)
+{
+	unsigned char value = intc_irqpin_sense[type & IRQ_TYPE_SENSE_MASK];
+	struct intc_irqpin_priv *p = irq_data_get_irq_chip_data(d);
+
+	if (!(value & INTC_IRQ_SENSE_VALID))
+		return -EINVAL;
+
+	return intc_irqpin_set_sense(p, irqd_to_hwirq(d),
+				     value ^ INTC_IRQ_SENSE_VALID);
+}
+
+static irqreturn_t intc_irqpin_irq_handler(int irq, void *dev_id)
+{
+	struct intc_irqpin_irq *i = dev_id;
+	struct intc_irqpin_priv *p = i->p;
+	unsigned long bit;
+
+	intc_irqpin_dbg(i, "demux1");
+	bit = intc_irqpin_hwirq_mask(p, INTC_IRQPIN_REG_SOURCE, i->hw_irq);
+
+	if (intc_irqpin_read(p, INTC_IRQPIN_REG_SOURCE) & bit) {
+		intc_irqpin_write(p, INTC_IRQPIN_REG_SOURCE, ~bit);
+		intc_irqpin_dbg(i, "demux2");
+		generic_handle_irq(i->domain_irq);
+		return IRQ_HANDLED;
+	}
+	return IRQ_NONE;
+}
+
+static irqreturn_t intc_irqpin_shared_irq_handler(int irq, void *dev_id)
+{
+	struct intc_irqpin_priv *p = dev_id;
+	unsigned int reg_source = intc_irqpin_read(p, INTC_IRQPIN_REG_SOURCE);
+	irqreturn_t status = IRQ_NONE;
+	int k;
+
+	for (k = 0; k < 8; k++) {
+		if (reg_source & BIT(7 - k)) {
+			if (BIT(k) & p->shared_irq_mask)
+				continue;
+
+			status |= intc_irqpin_irq_handler(irq, &p->irq[k]);
+		}
+	}
+
+	return status;
+}
+
+static int intc_irqpin_irq_domain_map(struct irq_domain *h, unsigned int virq,
+				      irq_hw_number_t hw)
+{
+	struct intc_irqpin_priv *p = h->host_data;
+
+	p->irq[hw].domain_irq = virq;
+	p->irq[hw].hw_irq = hw;
+
+	intc_irqpin_dbg(&p->irq[hw], "map");
+	irq_set_chip_data(virq, h->host_data);
+	irq_set_chip_and_handler(virq, &p->irq_chip, handle_level_irq);
+	set_irq_flags(virq, IRQF_VALID); /* kill me now */
+	return 0;
+}
+
+static struct irq_domain_ops intc_irqpin_irq_domain_ops = {
+	.map	= intc_irqpin_irq_domain_map,
+	.xlate  = irq_domain_xlate_twocell,
+};
+
+static int intc_irqpin_probe(struct platform_device *pdev)
+{
+	struct renesas_intc_irqpin_config *pdata = pdev->dev.platform_data;
+	struct intc_irqpin_priv *p;
+	struct intc_irqpin_iomem *i;
+	struct resource *io[INTC_IRQPIN_REG_NR];
+	struct resource *irq;
+	struct irq_chip *irq_chip;
+	void (*enable_fn)(struct irq_data *d);
+	void (*disable_fn)(struct irq_data *d);
+	const char *name = dev_name(&pdev->dev);
+	int ref_irq;
+	int ret;
+	int k;
+
+	p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL);
+	if (!p) {
+		dev_err(&pdev->dev, "failed to allocate driver data\n");
+		ret = -ENOMEM;
+		goto err0;
+	}
+
+	/* deal with driver instance configuration */
+	if (pdata)
+		memcpy(&p->config, pdata, sizeof(*pdata));
+	if (!p->config.sense_bitfield_width)
+		p->config.sense_bitfield_width = 4; /* default to 4 bits */
+
+	p->pdev = pdev;
+	platform_set_drvdata(pdev, p);
+
+	/* get hold of manadatory IOMEM */
+	for (k = 0; k < INTC_IRQPIN_REG_NR; k++) {
+		io[k] = platform_get_resource(pdev, IORESOURCE_MEM, k);
+		if (!io[k]) {
+			dev_err(&pdev->dev, "not enough IOMEM resources\n");
+			ret = -EINVAL;
+			goto err0;
+		}
+	}
+
+	/* allow any number of IRQs between 1 and INTC_IRQPIN_MAX */
+	for (k = 0; k < INTC_IRQPIN_MAX; k++) {
+		irq = platform_get_resource(pdev, IORESOURCE_IRQ, k);
+		if (!irq)
+			break;
+
+		p->irq[k].p = p;
+		p->irq[k].requested_irq = irq->start;
+	}
+
+	p->number_of_irqs = k;
+	if (p->number_of_irqs < 1) {
+		dev_err(&pdev->dev, "not enough IRQ resources\n");
+		ret = -EINVAL;
+		goto err0;
+	}
+
+	/* ioremap IOMEM and setup read/write callbacks */
+	for (k = 0; k < INTC_IRQPIN_REG_NR; k++) {
+		i = &p->iomem[k];
+
+		switch (resource_size(io[k])) {
+		case 1:
+			i->width = 8;
+			i->read = intc_irqpin_read8;
+			i->write = intc_irqpin_write8;
+			break;
+		case 4:
+			i->width = 32;
+			i->read = intc_irqpin_read32;
+			i->write = intc_irqpin_write32;
+			break;
+		default:
+			dev_err(&pdev->dev, "IOMEM size mismatch\n");
+			ret = -EINVAL;
+			goto err0;
+		}
+
+		i->iomem = devm_ioremap_nocache(&pdev->dev, io[k]->start,
+						resource_size(io[k]));
+		if (!i->iomem) {
+			dev_err(&pdev->dev, "failed to remap IOMEM\n");
+			ret = -ENXIO;
+			goto err0;
+		}
+	}
+
+	/* mask all interrupts using priority */
+	for (k = 0; k < p->number_of_irqs; k++)
+		intc_irqpin_mask_unmask_prio(p, k, 1);
+
+	/* clear all pending interrupts */
+	intc_irqpin_write(p, INTC_IRQPIN_REG_SOURCE, 0x0);
+
+	/* scan for shared interrupt lines */
+	ref_irq = p->irq[0].requested_irq;
+	p->shared_irqs = true;
+	for (k = 1; k < p->number_of_irqs; k++) {
+		if (ref_irq != p->irq[k].requested_irq) {
+			p->shared_irqs = false;
+			break;
+		}
+	}
+
+	/* use more severe masking method if requested */
+	if (p->config.control_parent) {
+		enable_fn = intc_irqpin_irq_enable_force;
+		disable_fn = intc_irqpin_irq_disable_force;
+	} else if (!p->shared_irqs) {
+		enable_fn = intc_irqpin_irq_enable;
+		disable_fn = intc_irqpin_irq_disable;
+	} else {
+		enable_fn = intc_irqpin_shared_irq_enable;
+		disable_fn = intc_irqpin_shared_irq_disable;
+	}
+
+	irq_chip = &p->irq_chip;
+	irq_chip->name = name;
+	irq_chip->irq_mask = disable_fn;
+	irq_chip->irq_unmask = enable_fn;
+	irq_chip->irq_enable = enable_fn;
+	irq_chip->irq_disable = disable_fn;
+	irq_chip->irq_set_type = intc_irqpin_irq_set_type;
+	irq_chip->flags	= IRQCHIP_SKIP_SET_WAKE;
+
+	p->irq_domain = irq_domain_add_simple(pdev->dev.of_node,
+					      p->number_of_irqs,
+					      p->config.irq_base,
+					      &intc_irqpin_irq_domain_ops, p);
+	if (!p->irq_domain) {
+		ret = -ENXIO;
+		dev_err(&pdev->dev, "cannot initialize irq domain\n");
+		goto err0;
+	}
+
+	if (p->shared_irqs) {
+		/* request one shared interrupt */
+		if (devm_request_irq(&pdev->dev, p->irq[0].requested_irq,
+				intc_irqpin_shared_irq_handler,
+				IRQF_SHARED, name, p)) {
+			dev_err(&pdev->dev, "failed to request low IRQ\n");
+			ret = -ENOENT;
+			goto err1;
+		}
+	} else {
+		/* request interrupts one by one */
+		for (k = 0; k < p->number_of_irqs; k++) {
+			if (devm_request_irq(&pdev->dev,
+					p->irq[k].requested_irq,
+					intc_irqpin_irq_handler,
+					0, name, &p->irq[k])) {
+				dev_err(&pdev->dev,
+					"failed to request low IRQ\n");
+				ret = -ENOENT;
+				goto err1;
+			}
+		}
+	}
+
+	/* unmask all interrupts on prio level */
+	for (k = 0; k < p->number_of_irqs; k++)
+		intc_irqpin_mask_unmask_prio(p, k, 0);
+
+	dev_info(&pdev->dev, "driving %d irqs\n", p->number_of_irqs);
+
+	/* warn in case of mismatch if irq base is specified */
+	if (p->config.irq_base) {
+		if (p->config.irq_base != p->irq[0].domain_irq)
+			dev_warn(&pdev->dev, "irq base mismatch (%d/%d)\n",
+				 p->config.irq_base, p->irq[0].domain_irq);
+	}
+
+	return 0;
+
+err1:
+	irq_domain_remove(p->irq_domain);
+err0:
+	return ret;
+}
+
+static int intc_irqpin_remove(struct platform_device *pdev)
+{
+	struct intc_irqpin_priv *p = platform_get_drvdata(pdev);
+
+	irq_domain_remove(p->irq_domain);
+
+	return 0;
+}
+
+static const struct of_device_id intc_irqpin_dt_ids[] = {
+	{ .compatible = "renesas,intc-irqpin", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, intc_irqpin_dt_ids);
+
+static struct platform_driver intc_irqpin_device_driver = {
+	.probe		= intc_irqpin_probe,
+	.remove		= intc_irqpin_remove,
+	.driver		= {
+		.name	= "renesas_intc_irqpin",
+		.of_match_table = intc_irqpin_dt_ids,
+		.owner  = THIS_MODULE,
+	}
+};
+
+static int __init intc_irqpin_init(void)
+{
+	return platform_driver_register(&intc_irqpin_device_driver);
+}
+postcore_initcall(intc_irqpin_init);
+
+static void __exit intc_irqpin_exit(void)
+{
+	platform_driver_unregister(&intc_irqpin_device_driver);
+}
+module_exit(intc_irqpin_exit);
+
+MODULE_AUTHOR("Magnus Damm");
+MODULE_DESCRIPTION("Renesas INTC External IRQ Pin Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/irqchip/irq-renesas-irqc.c b/drivers/irqchip/irq-renesas-irqc.c
new file mode 100644
index 0000000..927bff3
--- /dev/null
+++ b/drivers/irqchip/irq-renesas-irqc.c
@@ -0,0 +1,307 @@
+/*
+ * Renesas IRQC Driver
+ *
+ *  Copyright (C) 2013 Magnus Damm
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either 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/init.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/platform_data/irq-renesas-irqc.h>
+
+#define IRQC_IRQ_MAX 32 /* maximum 32 interrupts per driver instance */
+
+#define IRQC_REQ_STS 0x00
+#define IRQC_EN_STS 0x04
+#define IRQC_EN_SET 0x08
+#define IRQC_INT_CPU_BASE(n) (0x000 + ((n) * 0x10))
+#define DETECT_STATUS 0x100
+#define IRQC_CONFIG(n) (0x180 + ((n) * 0x04))
+
+struct irqc_irq {
+	int hw_irq;
+	int requested_irq;
+	int domain_irq;
+	struct irqc_priv *p;
+};
+
+struct irqc_priv {
+	void __iomem *iomem;
+	void __iomem *cpu_int_base;
+	struct irqc_irq irq[IRQC_IRQ_MAX];
+	struct renesas_irqc_config config;
+	unsigned int number_of_irqs;
+	struct platform_device *pdev;
+	struct irq_chip irq_chip;
+	struct irq_domain *irq_domain;
+};
+
+static void irqc_dbg(struct irqc_irq *i, char *str)
+{
+	dev_dbg(&i->p->pdev->dev, "%s (%d:%d:%d)\n",
+		str, i->requested_irq, i->hw_irq, i->domain_irq);
+}
+
+static void irqc_irq_enable(struct irq_data *d)
+{
+	struct irqc_priv *p = irq_data_get_irq_chip_data(d);
+	int hw_irq = irqd_to_hwirq(d);
+
+	irqc_dbg(&p->irq[hw_irq], "enable");
+	iowrite32(BIT(hw_irq), p->cpu_int_base + IRQC_EN_SET);
+}
+
+static void irqc_irq_disable(struct irq_data *d)
+{
+	struct irqc_priv *p = irq_data_get_irq_chip_data(d);
+	int hw_irq = irqd_to_hwirq(d);
+
+	irqc_dbg(&p->irq[hw_irq], "disable");
+	iowrite32(BIT(hw_irq), p->cpu_int_base + IRQC_EN_STS);
+}
+
+#define INTC_IRQ_SENSE_VALID 0x10
+#define INTC_IRQ_SENSE(x) (x + INTC_IRQ_SENSE_VALID)
+
+static unsigned char irqc_sense[IRQ_TYPE_SENSE_MASK + 1] = {
+	[IRQ_TYPE_LEVEL_LOW] = INTC_IRQ_SENSE(0x01),
+	[IRQ_TYPE_LEVEL_HIGH] = INTC_IRQ_SENSE(0x02),
+	[IRQ_TYPE_EDGE_FALLING] = INTC_IRQ_SENSE(0x04), /* Synchronous */
+	[IRQ_TYPE_EDGE_RISING] = INTC_IRQ_SENSE(0x08), /* Synchronous */
+	[IRQ_TYPE_EDGE_BOTH] = INTC_IRQ_SENSE(0x0c),  /* Synchronous */
+};
+
+static int irqc_irq_set_type(struct irq_data *d, unsigned int type)
+{
+	struct irqc_priv *p = irq_data_get_irq_chip_data(d);
+	int hw_irq = irqd_to_hwirq(d);
+	unsigned char value = irqc_sense[type & IRQ_TYPE_SENSE_MASK];
+	unsigned long tmp;
+
+	irqc_dbg(&p->irq[hw_irq], "sense");
+
+	if (!(value & INTC_IRQ_SENSE_VALID))
+		return -EINVAL;
+
+	tmp = ioread32(p->iomem + IRQC_CONFIG(hw_irq));
+	tmp &= ~0x3f;
+	tmp |= value ^ INTC_IRQ_SENSE_VALID;
+	iowrite32(tmp, p->iomem + IRQC_CONFIG(hw_irq));
+	return 0;
+}
+
+static irqreturn_t irqc_irq_handler(int irq, void *dev_id)
+{
+	struct irqc_irq *i = dev_id;
+	struct irqc_priv *p = i->p;
+	unsigned long bit = BIT(i->hw_irq);
+
+	irqc_dbg(i, "demux1");
+
+	if (ioread32(p->iomem + DETECT_STATUS) & bit) {
+		iowrite32(bit, p->iomem + DETECT_STATUS);
+		irqc_dbg(i, "demux2");
+		generic_handle_irq(i->domain_irq);
+		return IRQ_HANDLED;
+	}
+	return IRQ_NONE;
+}
+
+static int irqc_irq_domain_map(struct irq_domain *h, unsigned int virq,
+			       irq_hw_number_t hw)
+{
+	struct irqc_priv *p = h->host_data;
+
+	p->irq[hw].domain_irq = virq;
+	p->irq[hw].hw_irq = hw;
+
+	irqc_dbg(&p->irq[hw], "map");
+	irq_set_chip_data(virq, h->host_data);
+	irq_set_chip_and_handler(virq, &p->irq_chip, handle_level_irq);
+	set_irq_flags(virq, IRQF_VALID); /* kill me now */
+	return 0;
+}
+
+static struct irq_domain_ops irqc_irq_domain_ops = {
+	.map	= irqc_irq_domain_map,
+	.xlate  = irq_domain_xlate_twocell,
+};
+
+static int irqc_probe(struct platform_device *pdev)
+{
+	struct renesas_irqc_config *pdata = pdev->dev.platform_data;
+	struct irqc_priv *p;
+	struct resource *io;
+	struct resource *irq;
+	struct irq_chip *irq_chip;
+	const char *name = dev_name(&pdev->dev);
+	int ret;
+	int k;
+
+	p = kzalloc(sizeof(*p), GFP_KERNEL);
+	if (!p) {
+		dev_err(&pdev->dev, "failed to allocate driver data\n");
+		ret = -ENOMEM;
+		goto err0;
+	}
+
+	/* deal with driver instance configuration */
+	if (pdata)
+		memcpy(&p->config, pdata, sizeof(*pdata));
+
+	p->pdev = pdev;
+	platform_set_drvdata(pdev, p);
+
+	/* get hold of manadatory IOMEM */
+	io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!io) {
+		dev_err(&pdev->dev, "not enough IOMEM resources\n");
+		ret = -EINVAL;
+		goto err1;
+	}
+
+	/* allow any number of IRQs between 1 and IRQC_IRQ_MAX */
+	for (k = 0; k < IRQC_IRQ_MAX; k++) {
+		irq = platform_get_resource(pdev, IORESOURCE_IRQ, k);
+		if (!irq)
+			break;
+
+		p->irq[k].p = p;
+		p->irq[k].requested_irq = irq->start;
+	}
+
+	p->number_of_irqs = k;
+	if (p->number_of_irqs < 1) {
+		dev_err(&pdev->dev, "not enough IRQ resources\n");
+		ret = -EINVAL;
+		goto err1;
+	}
+
+	/* ioremap IOMEM and setup read/write callbacks */
+	p->iomem = ioremap_nocache(io->start, resource_size(io));
+	if (!p->iomem) {
+		dev_err(&pdev->dev, "failed to remap IOMEM\n");
+		ret = -ENXIO;
+		goto err2;
+	}
+
+	p->cpu_int_base = p->iomem + IRQC_INT_CPU_BASE(0); /* SYS-SPI */
+
+	irq_chip = &p->irq_chip;
+	irq_chip->name = name;
+	irq_chip->irq_mask = irqc_irq_disable;
+	irq_chip->irq_unmask = irqc_irq_enable;
+	irq_chip->irq_enable = irqc_irq_enable;
+	irq_chip->irq_disable = irqc_irq_disable;
+	irq_chip->irq_set_type = irqc_irq_set_type;
+	irq_chip->flags	= IRQCHIP_SKIP_SET_WAKE;
+
+	p->irq_domain = irq_domain_add_simple(pdev->dev.of_node,
+					      p->number_of_irqs,
+					      p->config.irq_base,
+					      &irqc_irq_domain_ops, p);
+	if (!p->irq_domain) {
+		ret = -ENXIO;
+		dev_err(&pdev->dev, "cannot initialize irq domain\n");
+		goto err2;
+	}
+
+	/* request interrupts one by one */
+	for (k = 0; k < p->number_of_irqs; k++) {
+		if (request_irq(p->irq[k].requested_irq, irqc_irq_handler,
+				0, name, &p->irq[k])) {
+			dev_err(&pdev->dev, "failed to request IRQ\n");
+			ret = -ENOENT;
+			goto err3;
+		}
+	}
+
+	dev_info(&pdev->dev, "driving %d irqs\n", p->number_of_irqs);
+
+	/* warn in case of mismatch if irq base is specified */
+	if (p->config.irq_base) {
+		if (p->config.irq_base != p->irq[0].domain_irq)
+			dev_warn(&pdev->dev, "irq base mismatch (%d/%d)\n",
+				 p->config.irq_base, p->irq[0].domain_irq);
+	}
+
+	return 0;
+err3:
+	for (; k >= 0; k--)
+		free_irq(p->irq[k - 1].requested_irq, &p->irq[k - 1]);
+
+	irq_domain_remove(p->irq_domain);
+err2:
+	iounmap(p->iomem);
+err1:
+	kfree(p);
+err0:
+	return ret;
+}
+
+static int irqc_remove(struct platform_device *pdev)
+{
+	struct irqc_priv *p = platform_get_drvdata(pdev);
+	int k;
+
+	for (k = 0; k < p->number_of_irqs; k++)
+		free_irq(p->irq[k].requested_irq, &p->irq[k]);
+
+	irq_domain_remove(p->irq_domain);
+	iounmap(p->iomem);
+	kfree(p);
+	return 0;
+}
+
+static const struct of_device_id irqc_dt_ids[] = {
+	{ .compatible = "renesas,irqc", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, irqc_dt_ids);
+
+static struct platform_driver irqc_device_driver = {
+	.probe		= irqc_probe,
+	.remove		= irqc_remove,
+	.driver		= {
+		.name	= "renesas_irqc",
+		.of_match_table	= irqc_dt_ids,
+		.owner	= THIS_MODULE,
+	}
+};
+
+static int __init irqc_init(void)
+{
+	return platform_driver_register(&irqc_device_driver);
+}
+postcore_initcall(irqc_init);
+
+static void __exit irqc_exit(void)
+{
+	platform_driver_unregister(&irqc_device_driver);
+}
+module_exit(irqc_exit);
+
+MODULE_AUTHOR("Magnus Damm");
+MODULE_DESCRIPTION("Renesas IRQC Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/irqchip/irq-s3c24xx.c b/drivers/irqchip/irq-s3c24xx.c
new file mode 100644
index 0000000..4c06494
--- /dev/null
+++ b/drivers/irqchip/irq-s3c24xx.c
@@ -0,0 +1,1356 @@
+/*
+ * S3C24XX IRQ handling
+ *
+ * Copyright (c) 2003-2004 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ * Copyright (c) 2012 Heiko Stuebner <heiko@sntech.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.
+*/
+
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/irqdomain.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+
+#include <asm/exception.h>
+#include <asm/mach/irq.h>
+
+#include <mach/regs-irq.h>
+#include <mach/regs-gpio.h>
+
+#include <plat/cpu.h>
+#include <plat/regs-irqtype.h>
+#include <plat/pm.h>
+
+#include "irqchip.h"
+
+#define S3C_IRQTYPE_NONE	0
+#define S3C_IRQTYPE_EINT	1
+#define S3C_IRQTYPE_EDGE	2
+#define S3C_IRQTYPE_LEVEL	3
+
+struct s3c_irq_data {
+	unsigned int type;
+	unsigned long offset;
+	unsigned long parent_irq;
+
+	/* data gets filled during init */
+	struct s3c_irq_intc *intc;
+	unsigned long sub_bits;
+	struct s3c_irq_intc *sub_intc;
+};
+
+/*
+ * Sructure holding the controller data
+ * @reg_pending		register holding pending irqs
+ * @reg_intpnd		special register intpnd in main intc
+ * @reg_mask		mask register
+ * @domain		irq_domain of the controller
+ * @parent		parent controller for ext and sub irqs
+ * @irqs		irq-data, always s3c_irq_data[32]
+ */
+struct s3c_irq_intc {
+	void __iomem		*reg_pending;
+	void __iomem		*reg_intpnd;
+	void __iomem		*reg_mask;
+	struct irq_domain	*domain;
+	struct s3c_irq_intc	*parent;
+	struct s3c_irq_data	*irqs;
+};
+
+/*
+ * Array holding pointers to the global controller structs
+ * [0] ... main_intc
+ * [1] ... sub_intc
+ * [2] ... main_intc2 on s3c2416
+ */
+static struct s3c_irq_intc *s3c_intc[3];
+
+static void s3c_irq_mask(struct irq_data *data)
+{
+	struct s3c_irq_data *irq_data = irq_data_get_irq_chip_data(data);
+	struct s3c_irq_intc *intc = irq_data->intc;
+	struct s3c_irq_intc *parent_intc = intc->parent;
+	struct s3c_irq_data *parent_data;
+	unsigned long mask;
+	unsigned int irqno;
+
+	mask = __raw_readl(intc->reg_mask);
+	mask |= (1UL << irq_data->offset);
+	__raw_writel(mask, intc->reg_mask);
+
+	if (parent_intc) {
+		parent_data = &parent_intc->irqs[irq_data->parent_irq];
+
+		/* check to see if we need to mask the parent IRQ
+		 * The parent_irq is always in main_intc, so the hwirq
+		 * for find_mapping does not need an offset in any case.
+		 */
+		if ((mask & parent_data->sub_bits) == parent_data->sub_bits) {
+			irqno = irq_find_mapping(parent_intc->domain,
+					 irq_data->parent_irq);
+			s3c_irq_mask(irq_get_irq_data(irqno));
+		}
+	}
+}
+
+static void s3c_irq_unmask(struct irq_data *data)
+{
+	struct s3c_irq_data *irq_data = irq_data_get_irq_chip_data(data);
+	struct s3c_irq_intc *intc = irq_data->intc;
+	struct s3c_irq_intc *parent_intc = intc->parent;
+	unsigned long mask;
+	unsigned int irqno;
+
+	mask = __raw_readl(intc->reg_mask);
+	mask &= ~(1UL << irq_data->offset);
+	__raw_writel(mask, intc->reg_mask);
+
+	if (parent_intc) {
+		irqno = irq_find_mapping(parent_intc->domain,
+					 irq_data->parent_irq);
+		s3c_irq_unmask(irq_get_irq_data(irqno));
+	}
+}
+
+static inline void s3c_irq_ack(struct irq_data *data)
+{
+	struct s3c_irq_data *irq_data = irq_data_get_irq_chip_data(data);
+	struct s3c_irq_intc *intc = irq_data->intc;
+	unsigned long bitval = 1UL << irq_data->offset;
+
+	__raw_writel(bitval, intc->reg_pending);
+	if (intc->reg_intpnd)
+		__raw_writel(bitval, intc->reg_intpnd);
+}
+
+static int s3c_irq_type(struct irq_data *data, unsigned int type)
+{
+	switch (type) {
+	case IRQ_TYPE_NONE:
+		break;
+	case IRQ_TYPE_EDGE_RISING:
+	case IRQ_TYPE_EDGE_FALLING:
+	case IRQ_TYPE_EDGE_BOTH:
+		irq_set_handler(data->irq, handle_edge_irq);
+		break;
+	case IRQ_TYPE_LEVEL_LOW:
+	case IRQ_TYPE_LEVEL_HIGH:
+		irq_set_handler(data->irq, handle_level_irq);
+		break;
+	default:
+		pr_err("No such irq type %d", type);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int s3c_irqext_type_set(void __iomem *gpcon_reg,
+			       void __iomem *extint_reg,
+			       unsigned long gpcon_offset,
+			       unsigned long extint_offset,
+			       unsigned int type)
+{
+	unsigned long newvalue = 0, value;
+
+	/* Set the GPIO to external interrupt mode */
+	value = __raw_readl(gpcon_reg);
+	value = (value & ~(3 << gpcon_offset)) | (0x02 << gpcon_offset);
+	__raw_writel(value, gpcon_reg);
+
+	/* Set the external interrupt to pointed trigger type */
+	switch (type)
+	{
+		case IRQ_TYPE_NONE:
+			pr_warn("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:
+			pr_err("No such irq type %d", type);
+			return -EINVAL;
+	}
+
+	value = __raw_readl(extint_reg);
+	value = (value & ~(7 << extint_offset)) | (newvalue << extint_offset);
+	__raw_writel(value, extint_reg);
+
+	return 0;
+}
+
+static int s3c_irqext_type(struct irq_data *data, unsigned int type)
+{
+	void __iomem *extint_reg;
+	void __iomem *gpcon_reg;
+	unsigned long gpcon_offset, extint_offset;
+
+	if ((data->hwirq >= 4) && (data->hwirq <= 7)) {
+		gpcon_reg = S3C2410_GPFCON;
+		extint_reg = S3C24XX_EXTINT0;
+		gpcon_offset = (data->hwirq) * 2;
+		extint_offset = (data->hwirq) * 4;
+	} else if ((data->hwirq >= 8) && (data->hwirq <= 15)) {
+		gpcon_reg = S3C2410_GPGCON;
+		extint_reg = S3C24XX_EXTINT1;
+		gpcon_offset = (data->hwirq - 8) * 2;
+		extint_offset = (data->hwirq - 8) * 4;
+	} else if ((data->hwirq >= 16) && (data->hwirq <= 23)) {
+		gpcon_reg = S3C2410_GPGCON;
+		extint_reg = S3C24XX_EXTINT2;
+		gpcon_offset = (data->hwirq - 8) * 2;
+		extint_offset = (data->hwirq - 16) * 4;
+	} else {
+		return -EINVAL;
+	}
+
+	return s3c_irqext_type_set(gpcon_reg, extint_reg, gpcon_offset,
+				   extint_offset, type);
+}
+
+static int s3c_irqext0_type(struct irq_data *data, unsigned int type)
+{
+	void __iomem *extint_reg;
+	void __iomem *gpcon_reg;
+	unsigned long gpcon_offset, extint_offset;
+
+	if ((data->hwirq >= 0) && (data->hwirq <= 3)) {
+		gpcon_reg = S3C2410_GPFCON;
+		extint_reg = S3C24XX_EXTINT0;
+		gpcon_offset = (data->hwirq) * 2;
+		extint_offset = (data->hwirq) * 4;
+	} else {
+		return -EINVAL;
+	}
+
+	return s3c_irqext_type_set(gpcon_reg, extint_reg, gpcon_offset,
+				   extint_offset, type);
+}
+
+static struct irq_chip s3c_irq_chip = {
+	.name		= "s3c",
+	.irq_ack	= s3c_irq_ack,
+	.irq_mask	= s3c_irq_mask,
+	.irq_unmask	= s3c_irq_unmask,
+	.irq_set_type	= s3c_irq_type,
+	.irq_set_wake	= s3c_irq_wake
+};
+
+static struct irq_chip s3c_irq_level_chip = {
+	.name		= "s3c-level",
+	.irq_mask	= s3c_irq_mask,
+	.irq_unmask	= s3c_irq_unmask,
+	.irq_ack	= s3c_irq_ack,
+	.irq_set_type	= s3c_irq_type,
+};
+
+static struct irq_chip s3c_irqext_chip = {
+	.name		= "s3c-ext",
+	.irq_mask	= s3c_irq_mask,
+	.irq_unmask	= s3c_irq_unmask,
+	.irq_ack	= s3c_irq_ack,
+	.irq_set_type	= s3c_irqext_type,
+	.irq_set_wake	= s3c_irqext_wake
+};
+
+static struct irq_chip s3c_irq_eint0t4 = {
+	.name		= "s3c-ext0",
+	.irq_ack	= s3c_irq_ack,
+	.irq_mask	= s3c_irq_mask,
+	.irq_unmask	= s3c_irq_unmask,
+	.irq_set_wake	= s3c_irq_wake,
+	.irq_set_type	= s3c_irqext0_type,
+};
+
+static void s3c_irq_demux(unsigned int irq, struct irq_desc *desc)
+{
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	struct s3c_irq_data *irq_data = irq_desc_get_chip_data(desc);
+	struct s3c_irq_intc *intc = irq_data->intc;
+	struct s3c_irq_intc *sub_intc = irq_data->sub_intc;
+	unsigned long src;
+	unsigned long msk;
+	unsigned int n;
+	unsigned int offset;
+
+	/* we're using individual domains for the non-dt case
+	 * and one big domain for the dt case where the subintc
+	 * starts at hwirq number 32.
+	 */
+	offset = (intc->domain->of_node) ? 32 : 0;
+
+	chained_irq_enter(chip, desc);
+
+	src = __raw_readl(sub_intc->reg_pending);
+	msk = __raw_readl(sub_intc->reg_mask);
+
+	src &= ~msk;
+	src &= irq_data->sub_bits;
+
+	while (src) {
+		n = __ffs(src);
+		src &= ~(1 << n);
+		irq = irq_find_mapping(sub_intc->domain, offset + n);
+		generic_handle_irq(irq);
+	}
+
+	chained_irq_exit(chip, desc);
+}
+
+static inline int s3c24xx_handle_intc(struct s3c_irq_intc *intc,
+				      struct pt_regs *regs, int intc_offset)
+{
+	int pnd;
+	int offset;
+	int irq;
+
+	pnd = __raw_readl(intc->reg_intpnd);
+	if (!pnd)
+		return false;
+
+	/* non-dt machines use individual domains */
+	if (!intc->domain->of_node)
+		intc_offset = 0;
+
+	/* We have a problem that the INTOFFSET register does not always
+	 * show one interrupt. Occasionally we get two interrupts through
+	 * the prioritiser, and this causes the INTOFFSET register to show
+	 * what looks like the logical-or of the two interrupt numbers.
+	 *
+	 * Thanks to Klaus, Shannon, et al for helping to debug this problem
+	 */
+	offset = __raw_readl(intc->reg_intpnd + 4);
+
+	/* Find the bit manually, when the offset is wrong.
+	 * The pending register only ever contains the one bit of the next
+	 * interrupt to handle.
+	 */
+	if (!(pnd & (1 << offset)))
+		offset =  __ffs(pnd);
+
+	irq = irq_find_mapping(intc->domain, intc_offset + offset);
+	handle_IRQ(irq, regs);
+	return true;
+}
+
+asmlinkage void __exception_irq_entry s3c24xx_handle_irq(struct pt_regs *regs)
+{
+	do {
+		if (likely(s3c_intc[0]))
+			if (s3c24xx_handle_intc(s3c_intc[0], regs, 0))
+				continue;
+
+		if (s3c_intc[2])
+			if (s3c24xx_handle_intc(s3c_intc[2], regs, 64))
+				continue;
+
+		break;
+	} while (1);
+}
+
+#ifdef CONFIG_FIQ
+/**
+ * s3c24xx_set_fiq - set the FIQ routing
+ * @irq: IRQ number to route to FIQ on processor.
+ * @on: Whether to route @irq to the FIQ, or to remove the FIQ routing.
+ *
+ * Change the state of the IRQ to FIQ routing depending on @irq and @on. If
+ * @on is true, the @irq is checked to see if it can be routed and the
+ * interrupt controller updated to route the IRQ. If @on is false, the FIQ
+ * routing is cleared, regardless of which @irq is specified.
+ */
+int s3c24xx_set_fiq(unsigned int irq, bool on)
+{
+	u32 intmod;
+	unsigned offs;
+
+	if (on) {
+		offs = irq - FIQ_START;
+		if (offs > 31)
+			return -EINVAL;
+
+		intmod = 1 << offs;
+	} else {
+		intmod = 0;
+	}
+
+	__raw_writel(intmod, S3C2410_INTMOD);
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(s3c24xx_set_fiq);
+#endif
+
+static int s3c24xx_irq_map(struct irq_domain *h, unsigned int virq,
+							irq_hw_number_t hw)
+{
+	struct s3c_irq_intc *intc = h->host_data;
+	struct s3c_irq_data *irq_data = &intc->irqs[hw];
+	struct s3c_irq_intc *parent_intc;
+	struct s3c_irq_data *parent_irq_data;
+	unsigned int irqno;
+
+	/* attach controller pointer to irq_data */
+	irq_data->intc = intc;
+	irq_data->offset = hw;
+
+	parent_intc = intc->parent;
+
+	/* set handler and flags */
+	switch (irq_data->type) {
+	case S3C_IRQTYPE_NONE:
+		return 0;
+	case S3C_IRQTYPE_EINT:
+		/* On the S3C2412, the EINT0to3 have a parent irq
+		 * but need the s3c_irq_eint0t4 chip
+		 */
+		if (parent_intc && (!soc_is_s3c2412() || hw >= 4))
+			irq_set_chip_and_handler(virq, &s3c_irqext_chip,
+						 handle_edge_irq);
+		else
+			irq_set_chip_and_handler(virq, &s3c_irq_eint0t4,
+						 handle_edge_irq);
+		break;
+	case S3C_IRQTYPE_EDGE:
+		if (parent_intc || intc->reg_pending == S3C2416_SRCPND2)
+			irq_set_chip_and_handler(virq, &s3c_irq_level_chip,
+						 handle_edge_irq);
+		else
+			irq_set_chip_and_handler(virq, &s3c_irq_chip,
+						 handle_edge_irq);
+		break;
+	case S3C_IRQTYPE_LEVEL:
+		if (parent_intc)
+			irq_set_chip_and_handler(virq, &s3c_irq_level_chip,
+						 handle_level_irq);
+		else
+			irq_set_chip_and_handler(virq, &s3c_irq_chip,
+						 handle_level_irq);
+		break;
+	default:
+		pr_err("irq-s3c24xx: unsupported irqtype %d\n", irq_data->type);
+		return -EINVAL;
+	}
+
+	irq_set_chip_data(virq, irq_data);
+
+	set_irq_flags(virq, IRQF_VALID);
+
+	if (parent_intc && irq_data->type != S3C_IRQTYPE_NONE) {
+		if (irq_data->parent_irq > 31) {
+			pr_err("irq-s3c24xx: parent irq %lu is out of range\n",
+			       irq_data->parent_irq);
+			goto err;
+		}
+
+		parent_irq_data = &parent_intc->irqs[irq_data->parent_irq];
+		parent_irq_data->sub_intc = intc;
+		parent_irq_data->sub_bits |= (1UL << hw);
+
+		/* attach the demuxer to the parent irq */
+		irqno = irq_find_mapping(parent_intc->domain,
+					 irq_data->parent_irq);
+		if (!irqno) {
+			pr_err("irq-s3c24xx: could not find mapping for parent irq %lu\n",
+			       irq_data->parent_irq);
+			goto err;
+		}
+		irq_set_chained_handler(irqno, s3c_irq_demux);
+	}
+
+	return 0;
+
+err:
+	set_irq_flags(virq, 0);
+
+	/* the only error can result from bad mapping data*/
+	return -EINVAL;
+}
+
+static struct irq_domain_ops s3c24xx_irq_ops = {
+	.map = s3c24xx_irq_map,
+	.xlate = irq_domain_xlate_twocell,
+};
+
+static void s3c24xx_clear_intc(struct s3c_irq_intc *intc)
+{
+	void __iomem *reg_source;
+	unsigned long pend;
+	unsigned long last;
+	int i;
+
+	/* if intpnd is set, read the next pending irq from there */
+	reg_source = intc->reg_intpnd ? intc->reg_intpnd : intc->reg_pending;
+
+	last = 0;
+	for (i = 0; i < 4; i++) {
+		pend = __raw_readl(reg_source);
+
+		if (pend == 0 || pend == last)
+			break;
+
+		__raw_writel(pend, intc->reg_pending);
+		if (intc->reg_intpnd)
+			__raw_writel(pend, intc->reg_intpnd);
+
+		pr_info("irq: clearing pending status %08x\n", (int)pend);
+		last = pend;
+	}
+}
+
+static struct s3c_irq_intc *s3c24xx_init_intc(struct device_node *np,
+				       struct s3c_irq_data *irq_data,
+				       struct s3c_irq_intc *parent,
+				       unsigned long address)
+{
+	struct s3c_irq_intc *intc;
+	void __iomem *base = (void *)0xf6000000; /* static mapping */
+	int irq_num;
+	int irq_start;
+	int ret;
+
+	intc = kzalloc(sizeof(struct s3c_irq_intc), GFP_KERNEL);
+	if (!intc)
+		return ERR_PTR(-ENOMEM);
+
+	intc->irqs = irq_data;
+
+	if (parent)
+		intc->parent = parent;
+
+	/* select the correct data for the controller.
+	 * Need to hard code the irq num start and offset
+	 * to preserve the static mapping for now
+	 */
+	switch (address) {
+	case 0x4a000000:
+		pr_debug("irq: found main intc\n");
+		intc->reg_pending = base;
+		intc->reg_mask = base + 0x08;
+		intc->reg_intpnd = base + 0x10;
+		irq_num = 32;
+		irq_start = S3C2410_IRQ(0);
+		break;
+	case 0x4a000018:
+		pr_debug("irq: found subintc\n");
+		intc->reg_pending = base + 0x18;
+		intc->reg_mask = base + 0x1c;
+		irq_num = 29;
+		irq_start = S3C2410_IRQSUB(0);
+		break;
+	case 0x4a000040:
+		pr_debug("irq: found intc2\n");
+		intc->reg_pending = base + 0x40;
+		intc->reg_mask = base + 0x48;
+		intc->reg_intpnd = base + 0x50;
+		irq_num = 8;
+		irq_start = S3C2416_IRQ(0);
+		break;
+	case 0x560000a4:
+		pr_debug("irq: found eintc\n");
+		base = (void *)0xfd000000;
+
+		intc->reg_mask = base + 0xa4;
+		intc->reg_pending = base + 0x08;
+		irq_num = 24;
+		irq_start = S3C2410_IRQ(32);
+		break;
+	default:
+		pr_err("irq: unsupported controller address\n");
+		ret = -EINVAL;
+		goto err;
+	}
+
+	/* now that all the data is complete, init the irq-domain */
+	s3c24xx_clear_intc(intc);
+	intc->domain = irq_domain_add_legacy(np, irq_num, irq_start,
+					     0, &s3c24xx_irq_ops,
+					     intc);
+	if (!intc->domain) {
+		pr_err("irq: could not create irq-domain\n");
+		ret = -EINVAL;
+		goto err;
+	}
+
+	set_handle_irq(s3c24xx_handle_irq);
+
+	return intc;
+
+err:
+	kfree(intc);
+	return ERR_PTR(ret);
+}
+
+static struct s3c_irq_data init_eint[32] = {
+	{ .type = S3C_IRQTYPE_NONE, }, /* reserved */
+	{ .type = S3C_IRQTYPE_NONE, }, /* reserved */
+	{ .type = S3C_IRQTYPE_NONE, }, /* reserved */
+	{ .type = S3C_IRQTYPE_NONE, }, /* reserved */
+	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT4 */
+	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT5 */
+	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT6 */
+	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT7 */
+	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT8 */
+	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT9 */
+	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT10 */
+	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT11 */
+	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT12 */
+	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT13 */
+	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT14 */
+	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT15 */
+	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT16 */
+	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT17 */
+	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT18 */
+	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT19 */
+	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT20 */
+	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT21 */
+	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT22 */
+	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT23 */
+};
+
+#ifdef CONFIG_CPU_S3C2410
+static struct s3c_irq_data init_s3c2410base[32] = {
+	{ .type = S3C_IRQTYPE_EINT, }, /* EINT0 */
+	{ .type = S3C_IRQTYPE_EINT, }, /* EINT1 */
+	{ .type = S3C_IRQTYPE_EINT, }, /* EINT2 */
+	{ .type = S3C_IRQTYPE_EINT, }, /* EINT3 */
+	{ .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */
+	{ .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */
+	{ .type = S3C_IRQTYPE_NONE, }, /* reserved */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* TICK */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* WDT */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */
+	{ .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* LCD */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* DMA0 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* DMA1 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* DMA2 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* DMA3 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* SDI */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */
+	{ .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */
+	{ .type = S3C_IRQTYPE_NONE, }, /* reserved */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* USBD */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* USBH */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* IIC */
+	{ .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* SPI1 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* RTC */
+	{ .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */
+};
+
+static struct s3c_irq_data init_s3c2410subint[32] = {
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */
+	{ .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */
+	{ .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */
+};
+
+void __init s3c2410_init_irq(void)
+{
+#ifdef CONFIG_FIQ
+	init_FIQ(FIQ_START);
+#endif
+
+	s3c_intc[0] = s3c24xx_init_intc(NULL, &init_s3c2410base[0], NULL,
+					0x4a000000);
+	if (IS_ERR(s3c_intc[0])) {
+		pr_err("irq: could not create main interrupt controller\n");
+		return;
+	}
+
+	s3c_intc[1] = s3c24xx_init_intc(NULL, &init_s3c2410subint[0],
+					s3c_intc[0], 0x4a000018);
+	s3c24xx_init_intc(NULL, &init_eint[0], s3c_intc[0], 0x560000a4);
+}
+#endif
+
+#ifdef CONFIG_CPU_S3C2412
+static struct s3c_irq_data init_s3c2412base[32] = {
+	{ .type = S3C_IRQTYPE_LEVEL, }, /* EINT0 */
+	{ .type = S3C_IRQTYPE_LEVEL, }, /* EINT1 */
+	{ .type = S3C_IRQTYPE_LEVEL, }, /* EINT2 */
+	{ .type = S3C_IRQTYPE_LEVEL, }, /* EINT3 */
+	{ .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */
+	{ .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */
+	{ .type = S3C_IRQTYPE_NONE, }, /* reserved */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* TICK */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* WDT */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */
+	{ .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* LCD */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* DMA0 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* DMA1 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* DMA2 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* DMA3 */
+	{ .type = S3C_IRQTYPE_LEVEL, }, /* SDI/CF */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */
+	{ .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */
+	{ .type = S3C_IRQTYPE_NONE, }, /* reserved */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* USBD */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* USBH */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* IIC */
+	{ .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* SPI1 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* RTC */
+	{ .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */
+};
+
+static struct s3c_irq_data init_s3c2412eint[32] = {
+	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 0 }, /* EINT0 */
+	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 1 }, /* EINT1 */
+	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 2 }, /* EINT2 */
+	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 3 }, /* EINT3 */
+	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT4 */
+	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT5 */
+	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT6 */
+	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT7 */
+	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT8 */
+	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT9 */
+	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT10 */
+	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT11 */
+	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT12 */
+	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT13 */
+	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT14 */
+	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT15 */
+	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT16 */
+	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT17 */
+	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT18 */
+	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT19 */
+	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT20 */
+	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT21 */
+	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT22 */
+	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT23 */
+};
+
+static struct s3c_irq_data init_s3c2412subint[32] = {
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */
+	{ .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */
+	{ .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */
+	{ .type = S3C_IRQTYPE_NONE, },
+	{ .type = S3C_IRQTYPE_NONE, },
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 21 }, /* SDI */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 21 }, /* CF */
+};
+
+void s3c2412_init_irq(void)
+{
+	pr_info("S3C2412: IRQ Support\n");
+
+#ifdef CONFIG_FIQ
+	init_FIQ(FIQ_START);
+#endif
+
+	s3c_intc[0] = s3c24xx_init_intc(NULL, &init_s3c2412base[0], NULL,
+					0x4a000000);
+	if (IS_ERR(s3c_intc[0])) {
+		pr_err("irq: could not create main interrupt controller\n");
+		return;
+	}
+
+	s3c24xx_init_intc(NULL, &init_s3c2412eint[0], s3c_intc[0], 0x560000a4);
+	s3c_intc[1] = s3c24xx_init_intc(NULL, &init_s3c2412subint[0],
+					s3c_intc[0], 0x4a000018);
+}
+#endif
+
+#ifdef CONFIG_CPU_S3C2416
+static struct s3c_irq_data init_s3c2416base[32] = {
+	{ .type = S3C_IRQTYPE_EINT, }, /* EINT0 */
+	{ .type = S3C_IRQTYPE_EINT, }, /* EINT1 */
+	{ .type = S3C_IRQTYPE_EINT, }, /* EINT2 */
+	{ .type = S3C_IRQTYPE_EINT, }, /* EINT3 */
+	{ .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */
+	{ .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */
+	{ .type = S3C_IRQTYPE_NONE, }, /* reserved */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* TICK */
+	{ .type = S3C_IRQTYPE_LEVEL, }, /* WDT/AC97 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */
+	{ .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */
+	{ .type = S3C_IRQTYPE_LEVEL, }, /* LCD */
+	{ .type = S3C_IRQTYPE_LEVEL, }, /* DMA */
+	{ .type = S3C_IRQTYPE_LEVEL, }, /* UART3 */
+	{ .type = S3C_IRQTYPE_NONE, }, /* reserved */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* SDI1 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* SDI0 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */
+	{ .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* NAND */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* USBD */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* USBH */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* IIC */
+	{ .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */
+	{ .type = S3C_IRQTYPE_NONE, },
+	{ .type = S3C_IRQTYPE_EDGE, }, /* RTC */
+	{ .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */
+};
+
+static struct s3c_irq_data init_s3c2416subint[32] = {
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */
+	{ .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */
+	{ .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */
+	{ .type = S3C_IRQTYPE_NONE }, /* reserved */
+	{ .type = S3C_IRQTYPE_NONE }, /* reserved */
+	{ .type = S3C_IRQTYPE_NONE }, /* reserved */
+	{ .type = S3C_IRQTYPE_NONE }, /* reserved */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD2 */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD3 */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD4 */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA0 */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA1 */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA2 */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA3 */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA4 */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA5 */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-RX */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-TX */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-ERR */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* WDT */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* AC97 */
+};
+
+static struct s3c_irq_data init_s3c2416_second[32] = {
+	{ .type = S3C_IRQTYPE_EDGE }, /* 2D */
+	{ .type = S3C_IRQTYPE_NONE }, /* reserved */
+	{ .type = S3C_IRQTYPE_NONE }, /* reserved */
+	{ .type = S3C_IRQTYPE_NONE }, /* reserved */
+	{ .type = S3C_IRQTYPE_EDGE }, /* PCM0 */
+	{ .type = S3C_IRQTYPE_NONE }, /* reserved */
+	{ .type = S3C_IRQTYPE_EDGE }, /* I2S0 */
+};
+
+void __init s3c2416_init_irq(void)
+{
+	pr_info("S3C2416: IRQ Support\n");
+
+#ifdef CONFIG_FIQ
+	init_FIQ(FIQ_START);
+#endif
+
+	s3c_intc[0] = s3c24xx_init_intc(NULL, &init_s3c2416base[0], NULL,
+					0x4a000000);
+	if (IS_ERR(s3c_intc[0])) {
+		pr_err("irq: could not create main interrupt controller\n");
+		return;
+	}
+
+	s3c24xx_init_intc(NULL, &init_eint[0], s3c_intc[0], 0x560000a4);
+	s3c_intc[1] = s3c24xx_init_intc(NULL, &init_s3c2416subint[0],
+					s3c_intc[0], 0x4a000018);
+
+	s3c_intc[2] = s3c24xx_init_intc(NULL, &init_s3c2416_second[0],
+					NULL, 0x4a000040);
+}
+
+#endif
+
+#ifdef CONFIG_CPU_S3C2440
+static struct s3c_irq_data init_s3c2440base[32] = {
+	{ .type = S3C_IRQTYPE_EINT, }, /* EINT0 */
+	{ .type = S3C_IRQTYPE_EINT, }, /* EINT1 */
+	{ .type = S3C_IRQTYPE_EINT, }, /* EINT2 */
+	{ .type = S3C_IRQTYPE_EINT, }, /* EINT3 */
+	{ .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */
+	{ .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */
+	{ .type = S3C_IRQTYPE_LEVEL, }, /* CAM */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* TICK */
+	{ .type = S3C_IRQTYPE_LEVEL, }, /* WDT/AC97 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */
+	{ .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* LCD */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* DMA0 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* DMA1 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* DMA2 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* DMA3 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* SDI */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */
+	{ .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */
+	{ .type = S3C_IRQTYPE_LEVEL, }, /* NFCON */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* USBD */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* USBH */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* IIC */
+	{ .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* SPI1 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* RTC */
+	{ .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */
+};
+
+static struct s3c_irq_data init_s3c2440subint[32] = {
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */
+	{ .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */
+	{ .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 }, /* CAM_C */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 }, /* CAM_P */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* WDT */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* AC97 */
+};
+
+void __init s3c2440_init_irq(void)
+{
+	pr_info("S3C2440: IRQ Support\n");
+
+#ifdef CONFIG_FIQ
+	init_FIQ(FIQ_START);
+#endif
+
+	s3c_intc[0] = s3c24xx_init_intc(NULL, &init_s3c2440base[0], NULL,
+					0x4a000000);
+	if (IS_ERR(s3c_intc[0])) {
+		pr_err("irq: could not create main interrupt controller\n");
+		return;
+	}
+
+	s3c24xx_init_intc(NULL, &init_eint[0], s3c_intc[0], 0x560000a4);
+	s3c_intc[1] = s3c24xx_init_intc(NULL, &init_s3c2440subint[0],
+					s3c_intc[0], 0x4a000018);
+}
+#endif
+
+#ifdef CONFIG_CPU_S3C2442
+static struct s3c_irq_data init_s3c2442base[32] = {
+	{ .type = S3C_IRQTYPE_EINT, }, /* EINT0 */
+	{ .type = S3C_IRQTYPE_EINT, }, /* EINT1 */
+	{ .type = S3C_IRQTYPE_EINT, }, /* EINT2 */
+	{ .type = S3C_IRQTYPE_EINT, }, /* EINT3 */
+	{ .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */
+	{ .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */
+	{ .type = S3C_IRQTYPE_LEVEL, }, /* CAM */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* TICK */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* WDT */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */
+	{ .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* LCD */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* DMA0 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* DMA1 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* DMA2 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* DMA3 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* SDI */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */
+	{ .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */
+	{ .type = S3C_IRQTYPE_LEVEL, }, /* NFCON */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* USBD */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* USBH */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* IIC */
+	{ .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* SPI1 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* RTC */
+	{ .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */
+};
+
+static struct s3c_irq_data init_s3c2442subint[32] = {
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */
+	{ .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */
+	{ .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 }, /* CAM_C */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 }, /* CAM_P */
+};
+
+void __init s3c2442_init_irq(void)
+{
+	pr_info("S3C2442: IRQ Support\n");
+
+#ifdef CONFIG_FIQ
+	init_FIQ(FIQ_START);
+#endif
+
+	s3c_intc[0] = s3c24xx_init_intc(NULL, &init_s3c2442base[0], NULL,
+					0x4a000000);
+	if (IS_ERR(s3c_intc[0])) {
+		pr_err("irq: could not create main interrupt controller\n");
+		return;
+	}
+
+	s3c24xx_init_intc(NULL, &init_eint[0], s3c_intc[0], 0x560000a4);
+	s3c_intc[1] = s3c24xx_init_intc(NULL, &init_s3c2442subint[0],
+					s3c_intc[0], 0x4a000018);
+}
+#endif
+
+#ifdef CONFIG_CPU_S3C2443
+static struct s3c_irq_data init_s3c2443base[32] = {
+	{ .type = S3C_IRQTYPE_EINT, }, /* EINT0 */
+	{ .type = S3C_IRQTYPE_EINT, }, /* EINT1 */
+	{ .type = S3C_IRQTYPE_EINT, }, /* EINT2 */
+	{ .type = S3C_IRQTYPE_EINT, }, /* EINT3 */
+	{ .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */
+	{ .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */
+	{ .type = S3C_IRQTYPE_LEVEL, }, /* CAM */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* TICK */
+	{ .type = S3C_IRQTYPE_LEVEL, }, /* WDT/AC97 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */
+	{ .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */
+	{ .type = S3C_IRQTYPE_LEVEL, }, /* LCD */
+	{ .type = S3C_IRQTYPE_LEVEL, }, /* DMA */
+	{ .type = S3C_IRQTYPE_LEVEL, }, /* UART3 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* CFON */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* SDI1 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* SDI0 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */
+	{ .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* NAND */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* USBD */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* USBH */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* IIC */
+	{ .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* SPI1 */
+	{ .type = S3C_IRQTYPE_EDGE, }, /* RTC */
+	{ .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */
+};
+
+
+static struct s3c_irq_data init_s3c2443subint[32] = {
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */
+	{ .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */
+	{ .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 }, /* CAM_C */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 }, /* CAM_P */
+	{ .type = S3C_IRQTYPE_NONE }, /* reserved */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD1 */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD2 */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD3 */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD4 */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA0 */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA1 */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA2 */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA3 */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA4 */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA5 */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-RX */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-TX */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-ERR */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* WDT */
+	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* AC97 */
+};
+
+void __init s3c2443_init_irq(void)
+{
+	pr_info("S3C2443: IRQ Support\n");
+
+#ifdef CONFIG_FIQ
+	init_FIQ(FIQ_START);
+#endif
+
+	s3c_intc[0] = s3c24xx_init_intc(NULL, &init_s3c2443base[0], NULL,
+					0x4a000000);
+	if (IS_ERR(s3c_intc[0])) {
+		pr_err("irq: could not create main interrupt controller\n");
+		return;
+	}
+
+	s3c24xx_init_intc(NULL, &init_eint[0], s3c_intc[0], 0x560000a4);
+	s3c_intc[1] = s3c24xx_init_intc(NULL, &init_s3c2443subint[0],
+					s3c_intc[0], 0x4a000018);
+}
+#endif
+
+#ifdef CONFIG_OF
+static int s3c24xx_irq_map_of(struct irq_domain *h, unsigned int virq,
+							irq_hw_number_t hw)
+{
+	unsigned int ctrl_num = hw / 32;
+	unsigned int intc_hw = hw % 32;
+	struct s3c_irq_intc *intc = s3c_intc[ctrl_num];
+	struct s3c_irq_intc *parent_intc = intc->parent;
+	struct s3c_irq_data *irq_data = &intc->irqs[intc_hw];
+
+	/* attach controller pointer to irq_data */
+	irq_data->intc = intc;
+	irq_data->offset = intc_hw;
+
+	if (!parent_intc)
+		irq_set_chip_and_handler(virq, &s3c_irq_chip, handle_edge_irq);
+	else
+		irq_set_chip_and_handler(virq, &s3c_irq_level_chip,
+					 handle_edge_irq);
+
+	irq_set_chip_data(virq, irq_data);
+
+	set_irq_flags(virq, IRQF_VALID);
+
+	return 0;
+}
+
+/* Translate our of irq notation
+ * format: <ctrl_num ctrl_irq parent_irq type>
+ */
+static int s3c24xx_irq_xlate_of(struct irq_domain *d, struct device_node *n,
+			const u32 *intspec, unsigned int intsize,
+			irq_hw_number_t *out_hwirq, unsigned int *out_type)
+{
+	struct s3c_irq_intc *intc;
+	struct s3c_irq_intc *parent_intc;
+	struct s3c_irq_data *irq_data;
+	struct s3c_irq_data *parent_irq_data;
+	int irqno;
+
+	if (WARN_ON(intsize < 4))
+		return -EINVAL;
+
+	if (intspec[0] > 2 || !s3c_intc[intspec[0]]) {
+		pr_err("controller number %d invalid\n", intspec[0]);
+		return -EINVAL;
+	}
+	intc = s3c_intc[intspec[0]];
+
+	*out_hwirq = intspec[0] * 32 + intspec[2];
+	*out_type = intspec[3] & IRQ_TYPE_SENSE_MASK;
+
+	parent_intc = intc->parent;
+	if (parent_intc) {
+		irq_data = &intc->irqs[intspec[2]];
+		irq_data->parent_irq = intspec[1];
+		parent_irq_data = &parent_intc->irqs[irq_data->parent_irq];
+		parent_irq_data->sub_intc = intc;
+		parent_irq_data->sub_bits |= (1UL << intspec[2]);
+
+		/* parent_intc is always s3c_intc[0], so no offset */
+		irqno = irq_create_mapping(parent_intc->domain, intspec[1]);
+		if (irqno < 0) {
+			pr_err("irq: could not map parent interrupt\n");
+			return irqno;
+		}
+
+		irq_set_chained_handler(irqno, s3c_irq_demux);
+	}
+
+	return 0;
+}
+
+static struct irq_domain_ops s3c24xx_irq_ops_of = {
+	.map = s3c24xx_irq_map_of,
+	.xlate = s3c24xx_irq_xlate_of,
+};
+
+struct s3c24xx_irq_of_ctrl {
+	char			*name;
+	unsigned long		offset;
+	struct s3c_irq_intc	**handle;
+	struct s3c_irq_intc	**parent;
+	struct irq_domain_ops	*ops;
+};
+
+static int __init s3c_init_intc_of(struct device_node *np,
+			struct device_node *interrupt_parent,
+			struct s3c24xx_irq_of_ctrl *s3c_ctrl, int num_ctrl)
+{
+	struct s3c_irq_intc *intc;
+	struct s3c24xx_irq_of_ctrl *ctrl;
+	struct irq_domain *domain;
+	void __iomem *reg_base;
+	int i;
+
+	reg_base = of_iomap(np, 0);
+	if (!reg_base) {
+		pr_err("irq-s3c24xx: could not map irq registers\n");
+		return -EINVAL;
+	}
+
+	domain = irq_domain_add_linear(np, num_ctrl * 32,
+						     &s3c24xx_irq_ops_of, NULL);
+	if (!domain) {
+		pr_err("irq: could not create irq-domain\n");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < num_ctrl; i++) {
+		ctrl = &s3c_ctrl[i];
+
+		pr_debug("irq: found controller %s\n", ctrl->name);
+
+		intc = kzalloc(sizeof(struct s3c_irq_intc), GFP_KERNEL);
+		if (!intc)
+			return -ENOMEM;
+
+		intc->domain = domain;
+		intc->irqs = kzalloc(sizeof(struct s3c_irq_data) * 32,
+				     GFP_KERNEL);
+		if (!intc->irqs) {
+			kfree(intc);
+			return -ENOMEM;
+		}
+
+		if (ctrl->parent) {
+			intc->reg_pending = reg_base + ctrl->offset;
+			intc->reg_mask = reg_base + ctrl->offset + 0x4;
+
+			if (*(ctrl->parent)) {
+				intc->parent = *(ctrl->parent);
+			} else {
+				pr_warn("irq: parent of %s missing\n",
+					ctrl->name);
+				kfree(intc->irqs);
+				kfree(intc);
+				continue;
+			}
+		} else {
+			intc->reg_pending = reg_base + ctrl->offset;
+			intc->reg_mask = reg_base + ctrl->offset + 0x08;
+			intc->reg_intpnd = reg_base + ctrl->offset + 0x10;
+		}
+
+		s3c24xx_clear_intc(intc);
+		s3c_intc[i] = intc;
+	}
+
+	set_handle_irq(s3c24xx_handle_irq);
+
+	return 0;
+}
+
+static struct s3c24xx_irq_of_ctrl s3c2410_ctrl[] = {
+	{
+		.name = "intc",
+		.offset = 0,
+	}, {
+		.name = "subintc",
+		.offset = 0x18,
+		.parent = &s3c_intc[0],
+	}
+};
+
+int __init s3c2410_init_intc_of(struct device_node *np,
+			struct device_node *interrupt_parent,
+			struct s3c24xx_irq_of_ctrl *ctrl, int num_ctrl)
+{
+	return s3c_init_intc_of(np, interrupt_parent,
+				s3c2410_ctrl, ARRAY_SIZE(s3c2410_ctrl));
+}
+IRQCHIP_DECLARE(s3c2410_irq, "samsung,s3c2410-irq", s3c2410_init_intc_of);
+
+static struct s3c24xx_irq_of_ctrl s3c2416_ctrl[] = {
+	{
+		.name = "intc",
+		.offset = 0,
+	}, {
+		.name = "subintc",
+		.offset = 0x18,
+		.parent = &s3c_intc[0],
+	}, {
+		.name = "intc2",
+		.offset = 0x40,
+	}
+};
+
+int __init s3c2416_init_intc_of(struct device_node *np,
+			struct device_node *interrupt_parent,
+			struct s3c24xx_irq_of_ctrl *ctrl, int num_ctrl)
+{
+	return s3c_init_intc_of(np, interrupt_parent,
+				s3c2416_ctrl, ARRAY_SIZE(s3c2416_ctrl));
+}
+IRQCHIP_DECLARE(s3c2416_irq, "samsung,s3c2416-irq", s3c2416_init_intc_of);
+#endif
diff --git a/drivers/irqchip/irq-sirfsoc.c b/drivers/irqchip/irq-sirfsoc.c
new file mode 100644
index 0000000..69ea44e
--- /dev/null
+++ b/drivers/irqchip/irq-sirfsoc.c
@@ -0,0 +1,126 @@
+/*
+ * 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 <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/irqdomain.h>
+#include <linux/syscore_ops.h>
+#include <asm/mach/irq.h>
+#include <asm/exception.h>
+#include "irqchip.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
+#define SIRFSOC_INIT_IRQ_ID		0x0038
+
+#define SIRFSOC_NUM_IRQS		128
+
+static struct irq_domain *sirfsoc_irqdomain;
+
+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 asmlinkage void __exception_irq_entry sirfsoc_handle_irq(struct pt_regs *regs)
+{
+	void __iomem *base = sirfsoc_irqdomain->host_data;
+	u32 irqstat, irqnr;
+
+	irqstat = readl_relaxed(base + SIRFSOC_INIT_IRQ_ID);
+	irqnr = irq_find_mapping(sirfsoc_irqdomain, irqstat & 0xff);
+
+	handle_IRQ(irqnr, regs);
+}
+
+static int __init sirfsoc_irq_init(struct device_node *np, struct device_node *parent)
+{
+	void __iomem *base = of_iomap(np, 0);
+	if (!base)
+		panic("unable to map intc cpu registers\n");
+
+	/* using legacy because irqchip_generic does not work with linear */
+	sirfsoc_irqdomain = irq_domain_add_legacy(np, SIRFSOC_NUM_IRQS, 0, 0,
+				 &irq_domain_simple_ops, base);
+
+	sirfsoc_alloc_gc(base, 0, 32);
+	sirfsoc_alloc_gc(base + 4, 32, SIRFSOC_NUM_IRQS - 32);
+
+	writel_relaxed(0, base + SIRFSOC_INT_RISC_LEVEL0);
+	writel_relaxed(0, base + SIRFSOC_INT_RISC_LEVEL1);
+
+	writel_relaxed(0, base + SIRFSOC_INT_RISC_MASK0);
+	writel_relaxed(0, base + SIRFSOC_INT_RISC_MASK1);
+
+	set_handle_irq(sirfsoc_handle_irq);
+
+	return 0;
+}
+IRQCHIP_DECLARE(sirfsoc_intc, "sirf,prima2-intc", sirfsoc_irq_init);
+
+struct sirfsoc_irq_status {
+	u32 mask0;
+	u32 mask1;
+	u32 level0;
+	u32 level1;
+};
+
+static struct sirfsoc_irq_status sirfsoc_irq_st;
+
+static int sirfsoc_irq_suspend(void)
+{
+	void __iomem *base = sirfsoc_irqdomain->host_data;
+
+	sirfsoc_irq_st.mask0 = readl_relaxed(base + SIRFSOC_INT_RISC_MASK0);
+	sirfsoc_irq_st.mask1 = readl_relaxed(base + SIRFSOC_INT_RISC_MASK1);
+	sirfsoc_irq_st.level0 = readl_relaxed(base + SIRFSOC_INT_RISC_LEVEL0);
+	sirfsoc_irq_st.level1 = readl_relaxed(base + SIRFSOC_INT_RISC_LEVEL1);
+
+	return 0;
+}
+
+static void sirfsoc_irq_resume(void)
+{
+	void __iomem *base = sirfsoc_irqdomain->host_data;
+
+	writel_relaxed(sirfsoc_irq_st.mask0, base + SIRFSOC_INT_RISC_MASK0);
+	writel_relaxed(sirfsoc_irq_st.mask1, base + SIRFSOC_INT_RISC_MASK1);
+	writel_relaxed(sirfsoc_irq_st.level0, base + SIRFSOC_INT_RISC_LEVEL0);
+	writel_relaxed(sirfsoc_irq_st.level1, base + SIRFSOC_INT_RISC_LEVEL1);
+}
+
+static struct syscore_ops sirfsoc_irq_syscore_ops = {
+	.suspend	= sirfsoc_irq_suspend,
+	.resume		= sirfsoc_irq_resume,
+};
+
+static int __init sirfsoc_irq_pm_init(void)
+{
+	if (!sirfsoc_irqdomain)
+		return 0;
+
+	register_syscore_ops(&sirfsoc_irq_syscore_ops);
+	return 0;
+}
+device_initcall(sirfsoc_irq_pm_init);
diff --git a/drivers/irqchip/irq-versatile-fpga.c b/drivers/irqchip/irq-versatile-fpga.c
index 9dbd82b..065b7a3 100644
--- a/drivers/irqchip/irq-versatile-fpga.c
+++ b/drivers/irqchip/irq-versatile-fpga.c
@@ -139,7 +139,7 @@ void __init fpga_irq_init(void __iomem *base, const char *name, int irq_start,
 	int i;
 
 	if (fpga_irq_id >= ARRAY_SIZE(fpga_irq_devices)) {
-		pr_err("%s: too few FPGA IRQ controllers, increase CONFIG_PLAT_VERSATILE_FPGA_IRQ_NR\n", __func__);
+		pr_err("%s: too few FPGA IRQ controllers, increase CONFIG_VERSATILE_FPGA_IRQ_NR\n", __func__);
 		return;
 	}
 	f = &fpga_irq_devices[fpga_irq_id];
diff --git a/drivers/irqchip/irq-vic.c b/drivers/irqchip/irq-vic.c
index 3cf97aa..884d11c 100644
--- a/drivers/irqchip/irq-vic.c
+++ b/drivers/irqchip/irq-vic.c
@@ -23,6 +23,7 @@
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/io.h>
+#include <linux/irq.h>
 #include <linux/irqdomain.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
@@ -33,7 +34,7 @@
 #include <linux/irqchip/arm-vic.h>
 
 #include <asm/exception.h>
-#include <asm/mach/irq.h>
+#include <asm/irq.h>
 
 #include "irqchip.h"
 
diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c
index 89562a8..ac6f72b 100644
--- a/drivers/isdn/capi/capi.c
+++ b/drivers/isdn/capi/capi.c
@@ -569,7 +569,6 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb)
 {
 	struct capidev *cdev = ap->private;
 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
-	struct tty_struct *tty;
 	struct capiminor *mp;
 	u16 datahandle;
 	struct capincci *np;
@@ -627,11 +626,7 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb)
 			 CAPIMSG_U16(skb->data, CAPIMSG_BASELEN + 4 + 2));
 		kfree_skb(skb);
 		capiminor_del_ack(mp, datahandle);
-		tty = tty_port_tty_get(&mp->port);
-		if (tty) {
-			tty_wakeup(tty);
-			tty_kref_put(tty);
-		}
+		tty_port_tty_wakeup(&mp->port);
 		handle_minor_send(mp);
 
 	} else {
diff --git a/drivers/isdn/capi/capidrv.c b/drivers/isdn/capi/capidrv.c
index 832bc80..cc9f192 100644
--- a/drivers/isdn/capi/capidrv.c
+++ b/drivers/isdn/capi/capidrv.c
@@ -469,8 +469,7 @@ static int capidrv_add_ack(struct capidrv_ncci *nccip,
 {
 	struct ncci_datahandle_queue *n, **pp;
 
-	n = (struct ncci_datahandle_queue *)
-		kmalloc(sizeof(struct ncci_datahandle_queue), GFP_ATOMIC);
+	n = kmalloc(sizeof(struct ncci_datahandle_queue), GFP_ATOMIC);
 	if (!n) {
 		printk(KERN_ERR "capidrv: kmalloc ncci_datahandle failed\n");
 		return -1;
diff --git a/drivers/isdn/divert/isdn_divert.c b/drivers/isdn/divert/isdn_divert.c
index db432e6..50749a7 100644
--- a/drivers/isdn/divert/isdn_divert.c
+++ b/drivers/isdn/divert/isdn_divert.c
@@ -441,8 +441,7 @@ static int isdn_divert_icall(isdn_ctrl *ic)
 
 		switch (dv->rule.action) {
 		case DEFLECT_IGNORE:
-			return (0);
-			break;
+			return 0;
 
 		case DEFLECT_ALERT:
 		case DEFLECT_PROCEED:
@@ -510,10 +509,9 @@ static int isdn_divert_icall(isdn_ctrl *ic)
 			break;
 
 		default:
-			return (0); /* ignore call */
-			break;
+			return 0; /* ignore call */
 		} /* switch action */
-		break;
+		break; /* will break the 'for' looping */
 	} /* scan_table */
 
 	if (cs) {
diff --git a/drivers/isdn/gigaset/capi.c b/drivers/isdn/gigaset/capi.c
index 03a0a01..3286903 100644
--- a/drivers/isdn/gigaset/capi.c
+++ b/drivers/isdn/gigaset/capi.c
@@ -2334,7 +2334,7 @@ static int gigaset_proc_show(struct seq_file *m, void *v)
 
 static int gigaset_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, gigaset_proc_show, PDE(inode)->data);
+	return single_open(file, gigaset_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations gigaset_proc_fops = {
diff --git a/drivers/isdn/gigaset/interface.c b/drivers/isdn/gigaset/interface.c
index e2b5396..600c79b 100644
--- a/drivers/isdn/gigaset/interface.c
+++ b/drivers/isdn/gigaset/interface.c
@@ -487,12 +487,8 @@ static const struct tty_operations if_ops = {
 static void if_wake(unsigned long data)
 {
 	struct cardstate *cs = (struct cardstate *)data;
-	struct tty_struct *tty = tty_port_tty_get(&cs->port);
 
-	if (tty) {
-		tty_wakeup(tty);
-		tty_kref_put(tty);
-	}
+	tty_port_tty_wakeup(&cs->port);
 }
 
 /*** interface to common ***/
diff --git a/drivers/isdn/hardware/avm/avm_cs.c b/drivers/isdn/hardware/avm/avm_cs.c
index c21353d..62b8030 100644
--- a/drivers/isdn/hardware/avm/avm_cs.c
+++ b/drivers/isdn/hardware/avm/avm_cs.c
@@ -163,16 +163,4 @@ static struct pcmcia_driver avmcs_driver = {
 	.remove	= avmcs_detach,
 	.id_table = avmcs_ids,
 };
-
-static int __init avmcs_init(void)
-{
-	return pcmcia_register_driver(&avmcs_driver);
-}
-
-static void __exit avmcs_exit(void)
-{
-	pcmcia_unregister_driver(&avmcs_driver);
-}
-
-module_init(avmcs_init);
-module_exit(avmcs_exit);
+module_pcmcia_driver(avmcs_driver);
diff --git a/drivers/isdn/hardware/avm/b1.c b/drivers/isdn/hardware/avm/b1.c
index 821f7ac..4d9b195 100644
--- a/drivers/isdn/hardware/avm/b1.c
+++ b/drivers/isdn/hardware/avm/b1.c
@@ -702,7 +702,7 @@ static int b1ctl_proc_show(struct seq_file *m, void *v)
 
 static int b1ctl_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, b1ctl_proc_show, PDE(inode)->data);
+	return single_open(file, b1ctl_proc_show, PDE_DATA(inode));
 }
 
 const struct file_operations b1ctl_proc_fops = {
diff --git a/drivers/isdn/hardware/avm/b1dma.c b/drivers/isdn/hardware/avm/b1dma.c
index 0896aa8..19b113f 100644
--- a/drivers/isdn/hardware/avm/b1dma.c
+++ b/drivers/isdn/hardware/avm/b1dma.c
@@ -944,7 +944,7 @@ static int b1dmactl_proc_show(struct seq_file *m, void *v)
 
 static int b1dmactl_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, b1dmactl_proc_show, PDE(inode)->data);
+	return single_open(file, b1dmactl_proc_show, PDE_DATA(inode));
 }
 
 const struct file_operations b1dmactl_proc_fops = {
diff --git a/drivers/isdn/hardware/avm/c4.c b/drivers/isdn/hardware/avm/c4.c
index 1d7fc44..5d00d72 100644
--- a/drivers/isdn/hardware/avm/c4.c
+++ b/drivers/isdn/hardware/avm/c4.c
@@ -1129,7 +1129,7 @@ static int c4_proc_show(struct seq_file *m, void *v)
 
 static int c4_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, c4_proc_show, PDE(inode)->data);
+	return single_open(file, c4_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations c4_proc_fops = {
diff --git a/drivers/isdn/hardware/eicon/divasproc.c b/drivers/isdn/hardware/eicon/divasproc.c
index 3a4165c..56ce98a 100644
--- a/drivers/isdn/hardware/eicon/divasproc.c
+++ b/drivers/isdn/hardware/eicon/divasproc.c
@@ -145,7 +145,7 @@ void remove_divas_proc(void)
 static ssize_t grp_opt_proc_write(struct file *file, const char __user *buffer,
 				  size_t count, loff_t *pos)
 {
-	diva_os_xdi_adapter_t *a = PDE(file_inode(file))->data;
+	diva_os_xdi_adapter_t *a = PDE_DATA(file_inode(file));
 	PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1];
 
 	if ((count == 1) || (count == 2)) {
@@ -172,7 +172,7 @@ static ssize_t grp_opt_proc_write(struct file *file, const char __user *buffer,
 static ssize_t d_l1_down_proc_write(struct file *file, const char __user *buffer,
 				    size_t count, loff_t *pos)
 {
-	diva_os_xdi_adapter_t *a = PDE(file_inode(file))->data;
+	diva_os_xdi_adapter_t *a = PDE_DATA(file_inode(file));
 	PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1];
 
 	if ((count == 1) || (count == 2)) {
@@ -210,7 +210,7 @@ static int d_l1_down_proc_show(struct seq_file *m, void *v)
 
 static int d_l1_down_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, d_l1_down_proc_show, PDE(inode)->data);
+	return single_open(file, d_l1_down_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations d_l1_down_proc_fops = {
@@ -236,7 +236,7 @@ static int grp_opt_proc_show(struct seq_file *m, void *v)
 
 static int grp_opt_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, grp_opt_proc_show, PDE(inode)->data);
+	return single_open(file, grp_opt_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations grp_opt_proc_fops = {
@@ -251,7 +251,7 @@ static const struct file_operations grp_opt_proc_fops = {
 static ssize_t info_proc_write(struct file *file, const char __user *buffer,
 			       size_t count, loff_t *pos)
 {
-	diva_os_xdi_adapter_t *a = PDE(file_inode(file))->data;
+	diva_os_xdi_adapter_t *a = PDE_DATA(file_inode(file));
 	PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1];
 	char c[4];
 
@@ -335,7 +335,7 @@ static int info_proc_show(struct seq_file *m, void *v)
 
 static int info_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, info_proc_show, PDE(inode)->data);
+	return single_open(file, info_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations info_proc_fops = {
diff --git a/drivers/isdn/hisax/avma1_cs.c b/drivers/isdn/hisax/avma1_cs.c
index 4e676bc..baad94e 100644
--- a/drivers/isdn/hisax/avma1_cs.c
+++ b/drivers/isdn/hisax/avma1_cs.c
@@ -159,16 +159,4 @@ static struct pcmcia_driver avma1cs_driver = {
 	.remove		= avma1cs_detach,
 	.id_table	= avma1cs_ids,
 };
-
-static int __init init_avma1_cs(void)
-{
-	return pcmcia_register_driver(&avma1cs_driver);
-}
-
-static void __exit exit_avma1_cs(void)
-{
-	pcmcia_unregister_driver(&avma1cs_driver);
-}
-
-module_init(init_avma1_cs);
-module_exit(exit_avma1_cs);
+module_pcmcia_driver(avma1cs_driver);
diff --git a/drivers/isdn/hisax/elsa_cs.c b/drivers/isdn/hisax/elsa_cs.c
index ebe5691..40f6fad 100644
--- a/drivers/isdn/hisax/elsa_cs.c
+++ b/drivers/isdn/hisax/elsa_cs.c
@@ -215,16 +215,4 @@ static struct pcmcia_driver elsa_cs_driver = {
 	.suspend	= elsa_suspend,
 	.resume		= elsa_resume,
 };
-
-static int __init init_elsa_cs(void)
-{
-	return pcmcia_register_driver(&elsa_cs_driver);
-}
-
-static void __exit exit_elsa_cs(void)
-{
-	pcmcia_unregister_driver(&elsa_cs_driver);
-}
-
-module_init(init_elsa_cs);
-module_exit(exit_elsa_cs);
+module_pcmcia_driver(elsa_cs_driver);
diff --git a/drivers/isdn/hisax/fsm.c b/drivers/isdn/hisax/fsm.c
index 1bb2910..c7a9471 100644
--- a/drivers/isdn/hisax/fsm.c
+++ b/drivers/isdn/hisax/fsm.c
@@ -26,7 +26,7 @@ FsmNew(struct Fsm *fsm, struct FsmNode *fnlist, int fncount)
 {
 	int i;
 
-	fsm->jumpmatrix = (FSMFNPTR *)
+	fsm->jumpmatrix =
 		kzalloc(sizeof(FSMFNPTR) * fsm->state_count * fsm->event_count, GFP_KERNEL);
 	if (!fsm->jumpmatrix)
 		return -ENOMEM;
diff --git a/drivers/isdn/hisax/hfc_sx.c b/drivers/isdn/hisax/hfc_sx.c
index 90f34ae..dc4574f 100644
--- a/drivers/isdn/hisax/hfc_sx.c
+++ b/drivers/isdn/hisax/hfc_sx.c
@@ -1479,7 +1479,7 @@ int setup_hfcsx(struct IsdnCard *card)
 			release_region(cs->hw.hfcsx.base, 2);
 			return (0);
 		}
-		if (!(cs->hw.hfcsx.extra = (void *)
+		if (!(cs->hw.hfcsx.extra =
 		      kmalloc(sizeof(struct hfcsx_extra), GFP_ATOMIC))) {
 			release_region(cs->hw.hfcsx.base, 2);
 			printk(KERN_WARNING "HFC-SX: unable to allocate memory\n");
diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c
index 90f8129..92ef62d 100644
--- a/drivers/isdn/hisax/sedlbauer_cs.c
+++ b/drivers/isdn/hisax/sedlbauer_cs.c
@@ -206,16 +206,4 @@ static struct pcmcia_driver sedlbauer_driver = {
 	.suspend	= sedlbauer_suspend,
 	.resume		= sedlbauer_resume,
 };
-
-static int __init init_sedlbauer_cs(void)
-{
-	return pcmcia_register_driver(&sedlbauer_driver);
-}
-
-static void __exit exit_sedlbauer_cs(void)
-{
-	pcmcia_unregister_driver(&sedlbauer_driver);
-}
-
-module_init(init_sedlbauer_cs);
-module_exit(exit_sedlbauer_cs);
+module_pcmcia_driver(sedlbauer_driver);
diff --git a/drivers/isdn/hisax/teles_cs.c b/drivers/isdn/hisax/teles_cs.c
index f2476ff..b8dd149 100644
--- a/drivers/isdn/hisax/teles_cs.c
+++ b/drivers/isdn/hisax/teles_cs.c
@@ -197,16 +197,4 @@ static struct pcmcia_driver teles_cs_driver = {
 	.suspend	= teles_suspend,
 	.resume		= teles_resume,
 };
-
-static int __init init_teles_cs(void)
-{
-	return pcmcia_register_driver(&teles_cs_driver);
-}
-
-static void __exit exit_teles_cs(void)
-{
-	pcmcia_unregister_driver(&teles_cs_driver);
-}
-
-module_init(init_teles_cs);
-module_exit(exit_teles_cs);
+module_pcmcia_driver(teles_cs_driver);
diff --git a/drivers/isdn/hysdn/hycapi.c b/drivers/isdn/hysdn/hycapi.c
index 931f916..00aad10 100644
--- a/drivers/isdn/hysdn/hycapi.c
+++ b/drivers/isdn/hysdn/hycapi.c
@@ -469,7 +469,7 @@ static int hycapi_proc_show(struct seq_file *m, void *v)
 
 static int hycapi_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, hycapi_proc_show, PDE(inode)->data);
+	return single_open(file, hycapi_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations hycapi_proc_fops = {
diff --git a/drivers/isdn/hysdn/hysdn_procconf.c b/drivers/isdn/hysdn/hysdn_procconf.c
index 8023d25..7307921 100644
--- a/drivers/isdn/hysdn/hysdn_procconf.c
+++ b/drivers/isdn/hysdn/hysdn_procconf.c
@@ -229,23 +229,12 @@ static int
 hysdn_conf_open(struct inode *ino, struct file *filep)
 {
 	hysdn_card *card;
-	struct proc_dir_entry *pd;
 	struct conf_writedata *cnf;
 	char *cp, *tmp;
 
 	/* now search the addressed card */
 	mutex_lock(&hysdn_conf_mutex);
-	card = card_root;
-	while (card) {
-		pd = card->procconf;
-		if (pd == PDE(ino))
-			break;
-		card = card->next;	/* search next entry */
-	}
-	if (!card) {
-		mutex_unlock(&hysdn_conf_mutex);
-		return (-ENODEV);	/* device is unknown/invalid */
-	}
+	card = PDE_DATA(ino);
 	if (card->debug_flags & (LOG_PROC_OPEN | LOG_PROC_ALL))
 		hysdn_addlog(card, "config open for uid=%d gid=%d mode=0x%x",
 			     filep->f_cred->fsuid, filep->f_cred->fsgid,
@@ -317,21 +306,9 @@ hysdn_conf_close(struct inode *ino, struct file *filep)
 	hysdn_card *card;
 	struct conf_writedata *cnf;
 	int retval = 0;
-	struct proc_dir_entry *pd;
 
 	mutex_lock(&hysdn_conf_mutex);
-	/* search the addressed card */
-	card = card_root;
-	while (card) {
-		pd = card->procconf;
-		if (pd == PDE(ino))
-			break;
-		card = card->next;	/* search next entry */
-	}
-	if (!card) {
-		mutex_unlock(&hysdn_conf_mutex);
-		return (-ENODEV);	/* device is unknown/invalid */
-	}
+	card = PDE_DATA(ino);
 	if (card->debug_flags & (LOG_PROC_OPEN | LOG_PROC_ALL))
 		hysdn_addlog(card, "config close for uid=%d gid=%d mode=0x%x",
 			     filep->f_cred->fsuid, filep->f_cred->fsgid,
@@ -394,10 +371,11 @@ hysdn_procconf_init(void)
 	while (card) {
 
 		sprintf(conf_name, "%s%d", PROC_CONF_BASENAME, card->myid);
-		if ((card->procconf = (void *) proc_create(conf_name,
+		if ((card->procconf = (void *) proc_create_data(conf_name,
 							   S_IFREG | S_IRUGO | S_IWUSR,
 							   hysdn_proc_entry,
-							   &conf_fops)) != NULL) {
+							   &conf_fops,
+							   card)) != NULL) {
 			hysdn_proclog_init(card);	/* init the log file entry */
 		}
 		card = card->next;	/* next entry */
diff --git a/drivers/isdn/hysdn/hysdn_proclog.c b/drivers/isdn/hysdn/hysdn_proclog.c
index 9a3ce93..b61e8d5 100644
--- a/drivers/isdn/hysdn/hysdn_proclog.c
+++ b/drivers/isdn/hysdn/hysdn_proclog.c
@@ -173,27 +173,14 @@ hysdn_log_read(struct file *file, char __user *buf, size_t count, loff_t *off)
 {
 	struct log_data *inf;
 	int len;
-	struct proc_dir_entry *pde = PDE(file_inode(file));
-	struct procdata *pd = NULL;
-	hysdn_card *card;
+	hysdn_card *card = PDE_DATA(file_inode(file));
 
 	if (!*((struct log_data **) file->private_data)) {
+		struct procdata *pd = card->proclog;
 		if (file->f_flags & O_NONBLOCK)
 			return (-EAGAIN);
 
-		/* sorry, but we need to search the card */
-		card = card_root;
-		while (card) {
-			pd = card->proclog;
-			if (pd->log == pde)
-				break;
-			card = card->next;	/* search next entry */
-		}
-		if (card)
-			interruptible_sleep_on(&(pd->rd_queue));
-		else
-			return (-EAGAIN);
-
+		interruptible_sleep_on(&(pd->rd_queue));
 	}
 	if (!(inf = *((struct log_data **) file->private_data)))
 		return (0);
@@ -215,27 +202,15 @@ hysdn_log_read(struct file *file, char __user *buf, size_t count, loff_t *off)
 static int
 hysdn_log_open(struct inode *ino, struct file *filep)
 {
-	hysdn_card *card;
-	struct procdata *pd = NULL;
-	unsigned long flags;
+	hysdn_card *card = PDE_DATA(ino);
 
 	mutex_lock(&hysdn_log_mutex);
-	card = card_root;
-	while (card) {
-		pd = card->proclog;
-		if (pd->log == PDE(ino))
-			break;
-		card = card->next;	/* search next entry */
-	}
-	if (!card) {
-		mutex_unlock(&hysdn_log_mutex);
-		return (-ENODEV);	/* device is unknown/invalid */
-	}
-	filep->private_data = card;	/* remember our own card */
-
 	if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE) {
 		/* write only access -> write log level only */
+		filep->private_data = card;	/* remember our own card */
 	} else if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) {
+		struct procdata *pd = card->proclog;
+		unsigned long flags;
 
 		/* read access -> log/debug read */
 		spin_lock_irqsave(&card->hysdn_lock, flags);
@@ -275,21 +250,13 @@ hysdn_log_close(struct inode *ino, struct file *filep)
 	} else {
 		/* read access -> log/debug read, mark one further file as closed */
 
-		pd = NULL;
 		inf = *((struct log_data **) filep->private_data);	/* get first log entry */
 		if (inf)
 			pd = (struct procdata *) inf->proc_ctrl;	/* still entries there */
 		else {
 			/* no info available -> search card */
-			card = card_root;
-			while (card) {
-				pd = card->proclog;
-				if (pd->log == PDE(ino))
-					break;
-				card = card->next;	/* search next entry */
-			}
-			if (card)
-				pd = card->proclog;	/* pointer to procfs log */
+			card = PDE_DATA(file_inode(filep));
+			pd = card->proclog;	/* pointer to procfs log */
 		}
 		if (pd)
 			pd->if_used--;	/* decrement interface usage count by one */
@@ -319,24 +286,12 @@ static unsigned int
 hysdn_log_poll(struct file *file, poll_table *wait)
 {
 	unsigned int mask = 0;
-	struct proc_dir_entry *pde = PDE(file_inode(file));
-	hysdn_card *card;
-	struct procdata *pd = NULL;
+	hysdn_card *card = PDE_DATA(file_inode(file));
+	struct procdata *pd = card->proclog;
 
 	if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE)
 		return (mask);	/* no polling for write supported */
 
-	/* we need to search the card */
-	card = card_root;
-	while (card) {
-		pd = card->proclog;
-		if (pd->log == pde)
-			break;
-		card = card->next;	/* search next entry */
-	}
-	if (!card)
-		return (mask);	/* card not found */
-
 	poll_wait(file, &(pd->rd_queue), wait);
 
 	if (*((struct log_data **) file->private_data))
@@ -373,9 +328,9 @@ hysdn_proclog_init(hysdn_card *card)
 
 	if ((pd = kzalloc(sizeof(struct procdata), GFP_KERNEL)) != NULL) {
 		sprintf(pd->log_name, "%s%d", PROC_LOG_BASENAME, card->myid);
-		pd->log = proc_create(pd->log_name,
+		pd->log = proc_create_data(pd->log_name,
 				      S_IFREG | S_IRUGO | S_IWUSR, hysdn_proc_entry,
-				      &log_fops);
+				      &log_fops, card);
 
 		init_waitqueue_head(&(pd->rd_queue));
 
diff --git a/drivers/isdn/i4l/isdn_net.c b/drivers/isdn/i4l/isdn_net.c
index babc621..88d657d 100644
--- a/drivers/isdn/i4l/isdn_net.c
+++ b/drivers/isdn/i4l/isdn_net.c
@@ -1385,7 +1385,7 @@ isdn_net_type_trans(struct sk_buff *skb, struct net_device *dev)
 		if (memcmp(eth->h_dest, dev->dev_addr, ETH_ALEN))
 			skb->pkt_type = PACKET_OTHERHOST;
 	}
-	if (ntohs(eth->h_proto) >= 1536)
+	if (ntohs(eth->h_proto) >= ETH_P_802_3_MIN)
 		return eth->h_proto;
 
 	rawp = skb->data;
diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c
index ebaebdf..3c5f249 100644
--- a/drivers/isdn/i4l/isdn_tty.c
+++ b/drivers/isdn/i4l/isdn_tty.c
@@ -1472,9 +1472,6 @@ isdn_tty_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 		    tty->termios.c_ospeed == old_termios->c_ospeed)
 			return;
 		isdn_tty_change_speed(info);
-		if ((old_termios->c_cflag & CRTSCTS) &&
-		    !(tty->termios.c_cflag & CRTSCTS))
-			tty->hw_stopped = 0;
 	}
 }
 
@@ -3427,7 +3424,6 @@ isdn_tty_parse_at(modem_info *info)
 			p++;
 			isdn_tty_cmd_ATA(info);
 			return;
-			break;
 		case 'D':
 			/* D - Dial */
 			if (info->msr & UART_MSR_DCD)
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index ec50824..d44806d 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -194,8 +194,8 @@ config LEDS_LP3944
 	  module will be called leds-lp3944.
 
 config LEDS_LP55XX_COMMON
-	tristate "Common Driver for TI/National LP5521 and LP5523/55231"
-	depends on LEDS_LP5521 || LEDS_LP5523
+	tristate "Common Driver for TI/National LP5521, LP5523/55231 and LP5562"
+	depends on LEDS_LP5521 || LEDS_LP5523 || LEDS_LP5562
 	select FW_LOADER
 	help
 	  This option supports common operations for LP5521 and LP5523/55231
@@ -222,6 +222,16 @@ config LEDS_LP5523
 	  Driver provides direct control via LED class and interface for
 	  programming the engines.
 
+config LEDS_LP5562
+	tristate "LED Support for TI LP5562 LED driver chip"
+	depends on LEDS_CLASS && I2C
+	select LEDS_LP55XX_COMMON
+	help
+	  If you say yes here you get support for TI LP5562 LED driver.
+	  It is 4 channels chip with programmable engines.
+	  Driver provides direct control via LED class and interface for
+	  programming the engines.
+
 config LEDS_LP8788
 	tristate "LED support for the TI LP8788 PMIC"
 	depends on LEDS_CLASS
@@ -469,106 +479,7 @@ config LEDS_BLINKM
 	  This option enables support for the BlinkM RGB LED connected
 	  through I2C. Say Y to enable support for the BlinkM LED.
 
-config LEDS_TRIGGERS
-	bool "LED Trigger support"
-	depends on LEDS_CLASS
-	help
-	  This option enables trigger support for the leds class.
-	  These triggers allow kernel events to drive the LEDs and can
-	  be configured via sysfs. If unsure, say Y.
-
 comment "LED Triggers"
-
-config LEDS_TRIGGER_TIMER
-	tristate "LED Timer Trigger"
-	depends on LEDS_TRIGGERS
-	help
-	  This allows LEDs to be controlled by a programmable timer
-	  via sysfs. Some LED hardware can be programmed to start
-	  blinking the LED without any further software interaction.
-	  For more details read Documentation/leds/leds-class.txt.
-
-	  If unsure, say Y.
-
-config LEDS_TRIGGER_ONESHOT
-	tristate "LED One-shot Trigger"
-	depends on LEDS_TRIGGERS
-	help
-	  This allows LEDs to blink in one-shot pulses with parameters
-	  controlled via sysfs.  It's useful to notify the user on
-	  sporadic events, when there are no clear begin and end trap points,
-	  or on dense events, where this blinks the LED at constant rate if
-	  rearmed continuously.
-
-	  It also shows how to use the led_blink_set_oneshot() function.
-
-	  If unsure, say Y.
-
-config LEDS_TRIGGER_IDE_DISK
-	bool "LED IDE Disk Trigger"
-	depends on IDE_GD_ATA
-	depends on LEDS_TRIGGERS
-	help
-	  This allows LEDs to be controlled by IDE disk activity.
-	  If unsure, say Y.
-
-config LEDS_TRIGGER_HEARTBEAT
-	tristate "LED Heartbeat Trigger"
-	depends on LEDS_TRIGGERS
-	help
-	  This allows LEDs to be controlled by a CPU load average.
-	  The flash frequency is a hyperbolic function of the 1-minute
-	  load average.
-	  If unsure, say Y.
-
-config LEDS_TRIGGER_BACKLIGHT
-	tristate "LED backlight Trigger"
-	depends on LEDS_TRIGGERS
-	help
-	  This allows LEDs to be controlled as a backlight device: they
-	  turn off and on when the display is blanked and unblanked.
-
-	  If unsure, say N.
-
-config LEDS_TRIGGER_CPU
-	bool "LED CPU Trigger"
-	depends on LEDS_TRIGGERS
-	help
-	  This allows LEDs to be controlled by active CPUs. This shows
-	  the active CPUs across an array of LEDs so you can see which
-	  CPUs are active on the system at any given moment.
-
-	  If unsure, say N.
-
-config LEDS_TRIGGER_GPIO
-	tristate "LED GPIO Trigger"
-	depends on LEDS_TRIGGERS
-	depends on GPIOLIB
-	help
-	  This allows LEDs to be controlled by gpio events. It's good
-	  when using gpios as switches and triggering the needed LEDs
-	  from there. One use case is n810's keypad LEDs that could
-	  be triggered by this trigger when user slides up to show
-	  keypad.
-
-	  If unsure, say N.
-
-config LEDS_TRIGGER_DEFAULT_ON
-	tristate "LED Default ON Trigger"
-	depends on LEDS_TRIGGERS
-	help
-	  This allows LEDs to be initialised in the ON state.
-	  If unsure, say Y.
-
-comment "iptables trigger is under Netfilter config (LED target)"
-	depends on LEDS_TRIGGERS
-
-config LEDS_TRIGGER_TRANSIENT
-	tristate "LED Transient Trigger"
-	depends on LEDS_TRIGGERS
-	help
-	  This allows one time activation of a transient state on
-	  GPIO/PWM based hardware.
-	  If unsure, say Y.
+source "drivers/leds/trigger/Kconfig"
 
 endif # NEW_LEDS
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 215e7e3..ac28977 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -26,6 +26,7 @@ obj-$(CONFIG_LEDS_LP3944)		+= leds-lp3944.o
 obj-$(CONFIG_LEDS_LP55XX_COMMON)	+= leds-lp55xx-common.o
 obj-$(CONFIG_LEDS_LP5521)		+= leds-lp5521.o
 obj-$(CONFIG_LEDS_LP5523)		+= leds-lp5523.o
+obj-$(CONFIG_LEDS_LP5562)		+= leds-lp5562.o
 obj-$(CONFIG_LEDS_LP8788)		+= leds-lp8788.o
 obj-$(CONFIG_LEDS_TCA6507)		+= leds-tca6507.o
 obj-$(CONFIG_LEDS_CLEVO_MAIL)		+= leds-clevo-mail.o
@@ -57,12 +58,4 @@ obj-$(CONFIG_LEDS_BLINKM)		+= leds-blinkm.o
 obj-$(CONFIG_LEDS_DAC124S085)		+= leds-dac124s085.o
 
 # LED Triggers
-obj-$(CONFIG_LEDS_TRIGGER_TIMER)	+= ledtrig-timer.o
-obj-$(CONFIG_LEDS_TRIGGER_ONESHOT)	+= ledtrig-oneshot.o
-obj-$(CONFIG_LEDS_TRIGGER_IDE_DISK)	+= ledtrig-ide-disk.o
-obj-$(CONFIG_LEDS_TRIGGER_HEARTBEAT)	+= ledtrig-heartbeat.o
-obj-$(CONFIG_LEDS_TRIGGER_BACKLIGHT)	+= ledtrig-backlight.o
-obj-$(CONFIG_LEDS_TRIGGER_GPIO)		+= ledtrig-gpio.o
-obj-$(CONFIG_LEDS_TRIGGER_CPU)		+= ledtrig-cpu.o
-obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON)	+= ledtrig-default-on.o
-obj-$(CONFIG_LEDS_TRIGGER_TRANSIENT)	+= ledtrig-transient.o
+obj-$(CONFIG_LEDS_TRIGGERS)		+= trigger/
diff --git a/drivers/leds/leds-asic3.c b/drivers/leds/leds-asic3.c
index b474745..cf9efe4 100644
--- a/drivers/leds/leds-asic3.c
+++ b/drivers/leds/leds-asic3.c
@@ -134,6 +134,7 @@ static int asic3_led_remove(struct platform_device *pdev)
 	return mfd_cell_disable(pdev);
 }
 
+#ifdef CONFIG_PM_SLEEP
 static int asic3_led_suspend(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
@@ -159,11 +160,9 @@ static int asic3_led_resume(struct device *dev)
 
 	return ret;
 }
+#endif
 
-static const struct dev_pm_ops asic3_led_pm_ops = {
-	.suspend	= asic3_led_suspend,
-	.resume		= asic3_led_resume,
-};
+static SIMPLE_DEV_PM_OPS(asic3_led_pm_ops, asic3_led_suspend, asic3_led_resume);
 
 static struct platform_driver asic3_led_driver = {
 	.probe		= asic3_led_probe,
diff --git a/drivers/leds/leds-atmel-pwm.c b/drivers/leds/leds-atmel-pwm.c
index 3867735..8a39c5b 100644
--- a/drivers/leds/leds-atmel-pwm.c
+++ b/drivers/leds/leds-atmel-pwm.c
@@ -113,7 +113,7 @@ err:
 	return status;
 }
 
-static int __exit pwmled_remove(struct platform_device *pdev)
+static int pwmled_remove(struct platform_device *pdev)
 {
 	const struct gpio_led_platform_data	*pdata;
 	struct pwmled				*leds;
@@ -140,7 +140,7 @@ static struct platform_driver pwmled_driver = {
 	},
 	/* REVISIT add suspend() and resume() methods */
 	.probe =	pwmled_probe,
-	.remove =	__exit_p(pwmled_remove),
+	.remove =	pwmled_remove,
 };
 
 module_platform_driver(pwmled_driver);
diff --git a/drivers/leds/leds-bd2802.c b/drivers/leds/leds-bd2802.c
index 8515170..2db0423 100644
--- a/drivers/leds/leds-bd2802.c
+++ b/drivers/leds/leds-bd2802.c
@@ -732,7 +732,7 @@ failed_unregister_dev_file:
 	return ret;
 }
 
-static int __exit bd2802_remove(struct i2c_client *client)
+static int bd2802_remove(struct i2c_client *client)
 {
 	struct bd2802_led *led = i2c_get_clientdata(client);
 	int i;
@@ -747,8 +747,7 @@ static int __exit bd2802_remove(struct i2c_client *client)
 	return 0;
 }
 
-#ifdef CONFIG_PM
-
+#ifdef CONFIG_PM_SLEEP
 static void bd2802_restore_state(struct bd2802_led *led)
 {
 	int i;
@@ -785,12 +784,9 @@ static int bd2802_resume(struct device *dev)
 
 	return 0;
 }
+#endif
 
 static SIMPLE_DEV_PM_OPS(bd2802_pm, bd2802_suspend, bd2802_resume);
-#define BD2802_PM (&bd2802_pm)
-#else		/* CONFIG_PM */
-#define BD2802_PM NULL
-#endif
 
 static const struct i2c_device_id bd2802_id[] = {
 	{ "BD2802", 0 },
@@ -801,10 +797,10 @@ MODULE_DEVICE_TABLE(i2c, bd2802_id);
 static struct i2c_driver bd2802_i2c_driver = {
 	.driver	= {
 		.name	= "BD2802",
-		.pm	= BD2802_PM,
+		.pm	= &bd2802_pm,
 	},
 	.probe		= bd2802_probe,
-	.remove		= __exit_p(bd2802_remove),
+	.remove		= bd2802_remove,
 	.id_table	= bd2802_id,
 };
 
diff --git a/drivers/leds/leds-lm355x.c b/drivers/leds/leds-lm355x.c
index 4117235..d81a8e7 100644
--- a/drivers/leds/leds-lm355x.c
+++ b/drivers/leds/leds-lm355x.c
@@ -477,6 +477,7 @@ static int lm355x_probe(struct i2c_client *client,
 	chip->cdev_flash.name = "flash";
 	chip->cdev_flash.max_brightness = 16;
 	chip->cdev_flash.brightness_set = lm355x_strobe_brightness_set;
+	chip->cdev_flash.default_trigger = "flash";
 	err = led_classdev_register((struct device *)
 				    &client->dev, &chip->cdev_flash);
 	if (err < 0)
@@ -486,6 +487,7 @@ static int lm355x_probe(struct i2c_client *client,
 	chip->cdev_torch.name = "torch";
 	chip->cdev_torch.max_brightness = 8;
 	chip->cdev_torch.brightness_set = lm355x_torch_brightness_set;
+	chip->cdev_torch.default_trigger = "torch";
 	err = led_classdev_register((struct device *)
 				    &client->dev, &chip->cdev_torch);
 	if (err < 0)
diff --git a/drivers/leds/leds-lm3642.c b/drivers/leds/leds-lm3642.c
index 9f428d9..f361bbe 100644
--- a/drivers/leds/leds-lm3642.c
+++ b/drivers/leds/leds-lm3642.c
@@ -363,6 +363,7 @@ static int lm3642_probe(struct i2c_client *client,
 	chip->cdev_flash.name = "flash";
 	chip->cdev_flash.max_brightness = 16;
 	chip->cdev_flash.brightness_set = lm3642_strobe_brightness_set;
+	chip->cdev_flash.default_trigger = "flash";
 	err = led_classdev_register((struct device *)
 				    &client->dev, &chip->cdev_flash);
 	if (err < 0) {
@@ -380,6 +381,7 @@ static int lm3642_probe(struct i2c_client *client,
 	chip->cdev_torch.name = "torch";
 	chip->cdev_torch.max_brightness = 8;
 	chip->cdev_torch.brightness_set = lm3642_torch_brightness_set;
+	chip->cdev_torch.default_trigger = "torch";
 	err = led_classdev_register((struct device *)
 				    &client->dev, &chip->cdev_torch);
 	if (err < 0) {
diff --git a/drivers/leds/leds-lp5521.c b/drivers/leds/leds-lp5521.c
index 1001347..19752c9 100644
--- a/drivers/leds/leds-lp5521.c
+++ b/drivers/leds/leds-lp5521.c
@@ -68,6 +68,18 @@
 #define LP5521_ENABLE_RUN_PROGRAM	\
 	(LP5521_ENABLE_DEFAULT | LP5521_EXEC_RUN)
 
+/* CONFIG register */
+#define LP5521_PWM_HF			0x40	/* PWM: 0 = 256Hz, 1 = 558Hz */
+#define LP5521_PWRSAVE_EN		0x20	/* 1 = Power save mode */
+#define LP5521_CP_MODE_OFF		0	/* Charge pump (CP) off */
+#define LP5521_CP_MODE_BYPASS		8	/* CP forced to bypass mode */
+#define LP5521_CP_MODE_1X5		0x10	/* CP forced to 1.5x mode */
+#define LP5521_CP_MODE_AUTO		0x18	/* Automatic mode selection */
+#define LP5521_R_TO_BATT		0x04	/* R out: 0 = CP, 1 = Vbat */
+#define LP5521_CLK_INT			0x01	/* Internal clock */
+#define LP5521_DEFAULT_CFG		\
+	(LP5521_PWM_HF | LP5521_PWRSAVE_EN | LP5521_CP_MODE_AUTO)
+
 /* Status */
 #define LP5521_EXT_CLK_USED		0x08
 
@@ -296,8 +308,11 @@ static int lp5521_post_init_device(struct lp55xx_chip *chip)
 	/* Set all PWMs to direct control mode */
 	ret = lp55xx_write(chip, LP5521_REG_OP_MODE, LP5521_CMD_DIRECT);
 
-	val = chip->pdata->update_config ?
-		: (LP5521_PWRSAVE_EN | LP5521_CP_MODE_AUTO | LP5521_R_TO_BATT);
+	/* Update configuration for the clock setting */
+	val = LP5521_DEFAULT_CFG;
+	if (!lp55xx_is_extclk_used(chip))
+		val |= LP5521_CLK_INT;
+
 	ret = lp55xx_write(chip, LP5521_REG_CONFIG, val);
 	if (ret)
 		return ret;
@@ -360,7 +375,8 @@ static ssize_t lp5521_selftest(struct device *dev,
 	mutex_lock(&chip->lock);
 	ret = lp5521_run_selftest(chip, buf);
 	mutex_unlock(&chip->lock);
-	return sprintf(buf, "%s\n", ret ? "FAIL" : "OK");
+
+	return scnprintf(buf, PAGE_SIZE, "%s\n", ret ? "FAIL" : "OK");
 }
 
 /* device attributes */
diff --git a/drivers/leds/leds-lp5562.c b/drivers/leds/leds-lp5562.c
new file mode 100644
index 0000000..513f239
--- /dev/null
+++ b/drivers/leds/leds-lp5562.c
@@ -0,0 +1,599 @@
+/*
+ * LP5562 LED driver
+ *
+ * Copyright (C) 2013 Texas Instruments
+ *
+ * Author: Milo(Woogyom) Kim <milo.kim@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.
+ */
+
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/leds.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/platform_data/leds-lp55xx.h>
+#include <linux/slab.h>
+
+#include "leds-lp55xx-common.h"
+
+#define LP5562_PROGRAM_LENGTH		32
+#define LP5562_MAX_LEDS			4
+
+/* ENABLE Register 00h */
+#define LP5562_REG_ENABLE		0x00
+#define LP5562_EXEC_ENG1_M		0x30
+#define LP5562_EXEC_ENG2_M		0x0C
+#define LP5562_EXEC_ENG3_M		0x03
+#define LP5562_EXEC_M			0x3F
+#define LP5562_MASTER_ENABLE		0x40	/* Chip master enable */
+#define LP5562_LOGARITHMIC_PWM		0x80	/* Logarithmic PWM adjustment */
+#define LP5562_EXEC_RUN			0x2A
+#define LP5562_ENABLE_DEFAULT	\
+	(LP5562_MASTER_ENABLE | LP5562_LOGARITHMIC_PWM)
+#define LP5562_ENABLE_RUN_PROGRAM	\
+	(LP5562_ENABLE_DEFAULT | LP5562_EXEC_RUN)
+
+/* OPMODE Register 01h */
+#define LP5562_REG_OP_MODE		0x01
+#define LP5562_MODE_ENG1_M		0x30
+#define LP5562_MODE_ENG2_M		0x0C
+#define LP5562_MODE_ENG3_M		0x03
+#define LP5562_LOAD_ENG1		0x10
+#define LP5562_LOAD_ENG2		0x04
+#define LP5562_LOAD_ENG3		0x01
+#define LP5562_RUN_ENG1			0x20
+#define LP5562_RUN_ENG2			0x08
+#define LP5562_RUN_ENG3			0x02
+#define LP5562_ENG1_IS_LOADING(mode)	\
+	((mode & LP5562_MODE_ENG1_M) == LP5562_LOAD_ENG1)
+#define LP5562_ENG2_IS_LOADING(mode)	\
+	((mode & LP5562_MODE_ENG2_M) == LP5562_LOAD_ENG2)
+#define LP5562_ENG3_IS_LOADING(mode)	\
+	((mode & LP5562_MODE_ENG3_M) == LP5562_LOAD_ENG3)
+
+/* BRIGHTNESS Registers */
+#define LP5562_REG_R_PWM		0x04
+#define LP5562_REG_G_PWM		0x03
+#define LP5562_REG_B_PWM		0x02
+#define LP5562_REG_W_PWM		0x0E
+
+/* CURRENT Registers */
+#define LP5562_REG_R_CURRENT		0x07
+#define LP5562_REG_G_CURRENT		0x06
+#define LP5562_REG_B_CURRENT		0x05
+#define LP5562_REG_W_CURRENT		0x0F
+
+/* CONFIG Register 08h */
+#define LP5562_REG_CONFIG		0x08
+#define LP5562_PWM_HF			0x40
+#define LP5562_PWRSAVE_EN		0x20
+#define LP5562_CLK_INT			0x01	/* Internal clock */
+#define LP5562_DEFAULT_CFG		(LP5562_PWM_HF | LP5562_PWRSAVE_EN)
+
+/* RESET Register 0Dh */
+#define LP5562_REG_RESET		0x0D
+#define LP5562_RESET			0xFF
+
+/* PROGRAM ENGINE Registers */
+#define LP5562_REG_PROG_MEM_ENG1	0x10
+#define LP5562_REG_PROG_MEM_ENG2	0x30
+#define LP5562_REG_PROG_MEM_ENG3	0x50
+
+/* LEDMAP Register 70h */
+#define LP5562_REG_ENG_SEL		0x70
+#define LP5562_ENG_SEL_PWM		0
+#define LP5562_ENG_FOR_RGB_M		0x3F
+#define LP5562_ENG_SEL_RGB		0x1B	/* R:ENG1, G:ENG2, B:ENG3 */
+#define LP5562_ENG_FOR_W_M		0xC0
+#define LP5562_ENG1_FOR_W		0x40	/* W:ENG1 */
+#define LP5562_ENG2_FOR_W		0x80	/* W:ENG2 */
+#define LP5562_ENG3_FOR_W		0xC0	/* W:ENG3 */
+
+/* Program Commands */
+#define LP5562_CMD_DISABLE		0x00
+#define LP5562_CMD_LOAD			0x15
+#define LP5562_CMD_RUN			0x2A
+#define LP5562_CMD_DIRECT		0x3F
+#define LP5562_PATTERN_OFF		0
+
+static inline void lp5562_wait_opmode_done(void)
+{
+	/* operation mode change needs to be longer than 153 us */
+	usleep_range(200, 300);
+}
+
+static inline void lp5562_wait_enable_done(void)
+{
+	/* it takes more 488 us to update ENABLE register */
+	usleep_range(500, 600);
+}
+
+static void lp5562_set_led_current(struct lp55xx_led *led, u8 led_current)
+{
+	u8 addr[] = {
+		LP5562_REG_R_CURRENT,
+		LP5562_REG_G_CURRENT,
+		LP5562_REG_B_CURRENT,
+		LP5562_REG_W_CURRENT,
+	};
+
+	led->led_current = led_current;
+	lp55xx_write(led->chip, addr[led->chan_nr], led_current);
+}
+
+static void lp5562_load_engine(struct lp55xx_chip *chip)
+{
+	enum lp55xx_engine_index idx = chip->engine_idx;
+	u8 mask[] = {
+		[LP55XX_ENGINE_1] = LP5562_MODE_ENG1_M,
+		[LP55XX_ENGINE_2] = LP5562_MODE_ENG2_M,
+		[LP55XX_ENGINE_3] = LP5562_MODE_ENG3_M,
+	};
+
+	u8 val[] = {
+		[LP55XX_ENGINE_1] = LP5562_LOAD_ENG1,
+		[LP55XX_ENGINE_2] = LP5562_LOAD_ENG2,
+		[LP55XX_ENGINE_3] = LP5562_LOAD_ENG3,
+	};
+
+	lp55xx_update_bits(chip, LP5562_REG_OP_MODE, mask[idx], val[idx]);
+
+	lp5562_wait_opmode_done();
+}
+
+static void lp5562_stop_engine(struct lp55xx_chip *chip)
+{
+	lp55xx_write(chip, LP5562_REG_OP_MODE, LP5562_CMD_DISABLE);
+	lp5562_wait_opmode_done();
+}
+
+static void lp5562_run_engine(struct lp55xx_chip *chip, bool start)
+{
+	int ret;
+	u8 mode;
+	u8 exec;
+
+	/* stop engine */
+	if (!start) {
+		lp55xx_write(chip, LP5562_REG_ENABLE, LP5562_ENABLE_DEFAULT);
+		lp5562_wait_enable_done();
+		lp5562_stop_engine(chip);
+		lp55xx_write(chip, LP5562_REG_ENG_SEL, LP5562_ENG_SEL_PWM);
+		lp55xx_write(chip, LP5562_REG_OP_MODE, LP5562_CMD_DIRECT);
+		lp5562_wait_opmode_done();
+		return;
+	}
+
+	/*
+	 * To run the engine,
+	 * operation mode and enable register should updated at the same time
+	 */
+
+	ret = lp55xx_read(chip, LP5562_REG_OP_MODE, &mode);
+	if (ret)
+		return;
+
+	ret = lp55xx_read(chip, LP5562_REG_ENABLE, &exec);
+	if (ret)
+		return;
+
+	/* change operation mode to RUN only when each engine is loading */
+	if (LP5562_ENG1_IS_LOADING(mode)) {
+		mode = (mode & ~LP5562_MODE_ENG1_M) | LP5562_RUN_ENG1;
+		exec = (exec & ~LP5562_EXEC_ENG1_M) | LP5562_RUN_ENG1;
+	}
+
+	if (LP5562_ENG2_IS_LOADING(mode)) {
+		mode = (mode & ~LP5562_MODE_ENG2_M) | LP5562_RUN_ENG2;
+		exec = (exec & ~LP5562_EXEC_ENG2_M) | LP5562_RUN_ENG2;
+	}
+
+	if (LP5562_ENG3_IS_LOADING(mode)) {
+		mode = (mode & ~LP5562_MODE_ENG3_M) | LP5562_RUN_ENG3;
+		exec = (exec & ~LP5562_EXEC_ENG3_M) | LP5562_RUN_ENG3;
+	}
+
+	lp55xx_write(chip, LP5562_REG_OP_MODE, mode);
+	lp5562_wait_opmode_done();
+
+	lp55xx_update_bits(chip, LP5562_REG_ENABLE, LP5562_EXEC_M, exec);
+	lp5562_wait_enable_done();
+}
+
+static int lp5562_update_firmware(struct lp55xx_chip *chip,
+					const u8 *data, size_t size)
+{
+	enum lp55xx_engine_index idx = chip->engine_idx;
+	u8 pattern[LP5562_PROGRAM_LENGTH] = {0};
+	u8 addr[] = {
+		[LP55XX_ENGINE_1] = LP5562_REG_PROG_MEM_ENG1,
+		[LP55XX_ENGINE_2] = LP5562_REG_PROG_MEM_ENG2,
+		[LP55XX_ENGINE_3] = LP5562_REG_PROG_MEM_ENG3,
+	};
+	unsigned cmd;
+	char c[3];
+	int program_size;
+	int nrchars;
+	int offset = 0;
+	int ret;
+	int i;
+
+	/* clear program memory before updating */
+	for (i = 0; i < LP5562_PROGRAM_LENGTH; i++)
+		lp55xx_write(chip, addr[idx] + i, 0);
+
+	i = 0;
+	while ((offset < size - 1) && (i < LP5562_PROGRAM_LENGTH)) {
+		/* separate sscanfs because length is working only for %s */
+		ret = sscanf(data + offset, "%2s%n ", c, &nrchars);
+		if (ret != 1)
+			goto err;
+
+		ret = sscanf(c, "%2x", &cmd);
+		if (ret != 1)
+			goto err;
+
+		pattern[i] = (u8)cmd;
+		offset += nrchars;
+		i++;
+	}
+
+	/* Each instruction is 16bit long. Check that length is even */
+	if (i % 2)
+		goto err;
+
+	program_size = i;
+	for (i = 0; i < program_size; i++)
+		lp55xx_write(chip, addr[idx] + i, pattern[i]);
+
+	return 0;
+
+err:
+	dev_err(&chip->cl->dev, "wrong pattern format\n");
+	return -EINVAL;
+}
+
+static void lp5562_firmware_loaded(struct lp55xx_chip *chip)
+{
+	const struct firmware *fw = chip->fw;
+
+	if (fw->size > LP5562_PROGRAM_LENGTH) {
+		dev_err(&chip->cl->dev, "firmware data size overflow: %zu\n",
+			fw->size);
+		return;
+	}
+
+	/*
+	 * Program momery sequence
+	 *  1) set engine mode to "LOAD"
+	 *  2) write firmware data into program memory
+	 */
+
+	lp5562_load_engine(chip);
+	lp5562_update_firmware(chip, fw->data, fw->size);
+}
+
+static int lp5562_post_init_device(struct lp55xx_chip *chip)
+{
+	int ret;
+	u8 cfg = LP5562_DEFAULT_CFG;
+
+	/* Set all PWMs to direct control mode */
+	ret = lp55xx_write(chip, LP5562_REG_OP_MODE, LP5562_CMD_DIRECT);
+	if (ret)
+		return ret;
+
+	lp5562_wait_opmode_done();
+
+	/* Update configuration for the clock setting */
+	if (!lp55xx_is_extclk_used(chip))
+		cfg |= LP5562_CLK_INT;
+
+	ret = lp55xx_write(chip, LP5562_REG_CONFIG, cfg);
+	if (ret)
+		return ret;
+
+	/* Initialize all channels PWM to zero -> leds off */
+	lp55xx_write(chip, LP5562_REG_R_PWM, 0);
+	lp55xx_write(chip, LP5562_REG_G_PWM, 0);
+	lp55xx_write(chip, LP5562_REG_B_PWM, 0);
+	lp55xx_write(chip, LP5562_REG_W_PWM, 0);
+
+	/* Set LED map as register PWM by default */
+	lp55xx_write(chip, LP5562_REG_ENG_SEL, LP5562_ENG_SEL_PWM);
+
+	return 0;
+}
+
+static void lp5562_led_brightness_work(struct work_struct *work)
+{
+	struct lp55xx_led *led = container_of(work, struct lp55xx_led,
+					      brightness_work);
+	struct lp55xx_chip *chip = led->chip;
+	u8 addr[] = {
+		LP5562_REG_R_PWM,
+		LP5562_REG_G_PWM,
+		LP5562_REG_B_PWM,
+		LP5562_REG_W_PWM,
+	};
+
+	mutex_lock(&chip->lock);
+	lp55xx_write(chip, addr[led->chan_nr], led->brightness);
+	mutex_unlock(&chip->lock);
+}
+
+static void lp5562_write_program_memory(struct lp55xx_chip *chip,
+					u8 base, const u8 *rgb, int size)
+{
+	int i;
+
+	if (!rgb || size <= 0)
+		return;
+
+	for (i = 0; i < size; i++)
+		lp55xx_write(chip, base + i, *(rgb + i));
+
+	lp55xx_write(chip, base + i, 0);
+	lp55xx_write(chip, base + i + 1, 0);
+}
+
+/* check the size of program count */
+static inline bool _is_pc_overflow(struct lp55xx_predef_pattern *ptn)
+{
+	return (ptn->size_r >= LP5562_PROGRAM_LENGTH ||
+		ptn->size_g >= LP5562_PROGRAM_LENGTH ||
+		ptn->size_b >= LP5562_PROGRAM_LENGTH);
+}
+
+static int lp5562_run_predef_led_pattern(struct lp55xx_chip *chip, int mode)
+{
+	struct lp55xx_predef_pattern *ptn;
+	int i;
+
+	if (mode == LP5562_PATTERN_OFF) {
+		lp5562_run_engine(chip, false);
+		return 0;
+	}
+
+	ptn = chip->pdata->patterns + (mode - 1);
+	if (!ptn || _is_pc_overflow(ptn)) {
+		dev_err(&chip->cl->dev, "invalid pattern data\n");
+		return -EINVAL;
+	}
+
+	lp5562_stop_engine(chip);
+
+	/* Set LED map as RGB */
+	lp55xx_write(chip, LP5562_REG_ENG_SEL, LP5562_ENG_SEL_RGB);
+
+	/* Load engines */
+	for (i = LP55XX_ENGINE_1; i <= LP55XX_ENGINE_3; i++) {
+		chip->engine_idx = i;
+		lp5562_load_engine(chip);
+	}
+
+	/* Clear program registers */
+	lp55xx_write(chip, LP5562_REG_PROG_MEM_ENG1, 0);
+	lp55xx_write(chip, LP5562_REG_PROG_MEM_ENG1 + 1, 0);
+	lp55xx_write(chip, LP5562_REG_PROG_MEM_ENG2, 0);
+	lp55xx_write(chip, LP5562_REG_PROG_MEM_ENG2 + 1, 0);
+	lp55xx_write(chip, LP5562_REG_PROG_MEM_ENG3, 0);
+	lp55xx_write(chip, LP5562_REG_PROG_MEM_ENG3 + 1, 0);
+
+	/* Program engines */
+	lp5562_write_program_memory(chip, LP5562_REG_PROG_MEM_ENG1,
+				ptn->r, ptn->size_r);
+	lp5562_write_program_memory(chip, LP5562_REG_PROG_MEM_ENG2,
+				ptn->g, ptn->size_g);
+	lp5562_write_program_memory(chip, LP5562_REG_PROG_MEM_ENG3,
+				ptn->b, ptn->size_b);
+
+	/* Run engines */
+	lp5562_run_engine(chip, true);
+
+	return 0;
+}
+
+static ssize_t lp5562_store_pattern(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t len)
+{
+	struct lp55xx_led *led = i2c_get_clientdata(to_i2c_client(dev));
+	struct lp55xx_chip *chip = led->chip;
+	struct lp55xx_predef_pattern *ptn = chip->pdata->patterns;
+	int num_patterns = chip->pdata->num_patterns;
+	unsigned long mode;
+	int ret;
+
+	ret = kstrtoul(buf, 0, &mode);
+	if (ret)
+		return ret;
+
+	if (mode > num_patterns || !ptn)
+		return -EINVAL;
+
+	mutex_lock(&chip->lock);
+	ret = lp5562_run_predef_led_pattern(chip, mode);
+	mutex_unlock(&chip->lock);
+
+	if (ret)
+		return ret;
+
+	return len;
+}
+
+static ssize_t lp5562_store_engine_mux(struct device *dev,
+				     struct device_attribute *attr,
+				     const char *buf, size_t len)
+{
+	struct lp55xx_led *led = i2c_get_clientdata(to_i2c_client(dev));
+	struct lp55xx_chip *chip = led->chip;
+	u8 mask;
+	u8 val;
+
+	/* LED map
+	 * R ... Engine 1 (fixed)
+	 * G ... Engine 2 (fixed)
+	 * B ... Engine 3 (fixed)
+	 * W ... Engine 1 or 2 or 3
+	 */
+
+	if (sysfs_streq(buf, "RGB")) {
+		mask = LP5562_ENG_FOR_RGB_M;
+		val = LP5562_ENG_SEL_RGB;
+	} else if (sysfs_streq(buf, "W")) {
+		enum lp55xx_engine_index idx = chip->engine_idx;
+
+		mask = LP5562_ENG_FOR_W_M;
+		switch (idx) {
+		case LP55XX_ENGINE_1:
+			val = LP5562_ENG1_FOR_W;
+			break;
+		case LP55XX_ENGINE_2:
+			val = LP5562_ENG2_FOR_W;
+			break;
+		case LP55XX_ENGINE_3:
+			val = LP5562_ENG3_FOR_W;
+			break;
+		default:
+			return -EINVAL;
+		}
+
+	} else {
+		dev_err(dev, "choose RGB or W\n");
+		return -EINVAL;
+	}
+
+	mutex_lock(&chip->lock);
+	lp55xx_update_bits(chip, LP5562_REG_ENG_SEL, mask, val);
+	mutex_unlock(&chip->lock);
+
+	return len;
+}
+
+static DEVICE_ATTR(led_pattern, S_IWUSR, NULL, lp5562_store_pattern);
+static DEVICE_ATTR(engine_mux, S_IWUSR, NULL, lp5562_store_engine_mux);
+
+static struct attribute *lp5562_attributes[] = {
+	&dev_attr_led_pattern.attr,
+	&dev_attr_engine_mux.attr,
+	NULL,
+};
+
+static const struct attribute_group lp5562_group = {
+	.attrs = lp5562_attributes,
+};
+
+/* Chip specific configurations */
+static struct lp55xx_device_config lp5562_cfg = {
+	.max_channel  = LP5562_MAX_LEDS,
+	.reset = {
+		.addr = LP5562_REG_RESET,
+		.val  = LP5562_RESET,
+	},
+	.enable = {
+		.addr = LP5562_REG_ENABLE,
+		.val  = LP5562_ENABLE_DEFAULT,
+	},
+	.post_init_device   = lp5562_post_init_device,
+	.set_led_current    = lp5562_set_led_current,
+	.brightness_work_fn = lp5562_led_brightness_work,
+	.run_engine         = lp5562_run_engine,
+	.firmware_cb        = lp5562_firmware_loaded,
+	.dev_attr_group     = &lp5562_group,
+};
+
+static int lp5562_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	int ret;
+	struct lp55xx_chip *chip;
+	struct lp55xx_led *led;
+	struct lp55xx_platform_data *pdata = client->dev.platform_data;
+
+	if (!pdata) {
+		dev_err(&client->dev, "no platform data\n");
+		return -EINVAL;
+	}
+
+	chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
+	if (!chip)
+		return -ENOMEM;
+
+	led = devm_kzalloc(&client->dev,
+			sizeof(*led) * pdata->num_channels, GFP_KERNEL);
+	if (!led)
+		return -ENOMEM;
+
+	chip->cl = client;
+	chip->pdata = pdata;
+	chip->cfg = &lp5562_cfg;
+
+	mutex_init(&chip->lock);
+
+	i2c_set_clientdata(client, led);
+
+	ret = lp55xx_init_device(chip);
+	if (ret)
+		goto err_init;
+
+	ret = lp55xx_register_leds(led, chip);
+	if (ret)
+		goto err_register_leds;
+
+	ret = lp55xx_register_sysfs(chip);
+	if (ret) {
+		dev_err(&client->dev, "registering sysfs failed\n");
+		goto err_register_sysfs;
+	}
+
+	return 0;
+
+err_register_sysfs:
+	lp55xx_unregister_leds(led, chip);
+err_register_leds:
+	lp55xx_deinit_device(chip);
+err_init:
+	return ret;
+}
+
+static int lp5562_remove(struct i2c_client *client)
+{
+	struct lp55xx_led *led = i2c_get_clientdata(client);
+	struct lp55xx_chip *chip = led->chip;
+
+	lp5562_stop_engine(chip);
+
+	lp55xx_unregister_sysfs(chip);
+	lp55xx_unregister_leds(led, chip);
+	lp55xx_deinit_device(chip);
+
+	return 0;
+}
+
+static const struct i2c_device_id lp5562_id[] = {
+	{ "lp5562", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, lp5562_id);
+
+static struct i2c_driver lp5562_driver = {
+	.driver = {
+		.name	= "lp5562",
+	},
+	.probe		= lp5562_probe,
+	.remove		= lp5562_remove,
+	.id_table	= lp5562_id,
+};
+
+module_i2c_driver(lp5562_driver);
+
+MODULE_DESCRIPTION("Texas Instruments LP5562 LED Driver");
+MODULE_AUTHOR("Milo Kim");
+MODULE_LICENSE("GPL");
diff --git a/drivers/leds/leds-lp55xx-common.c b/drivers/leds/leds-lp55xx-common.c
index d9eb841..ba34199 100644
--- a/drivers/leds/leds-lp55xx-common.c
+++ b/drivers/leds/leds-lp55xx-common.c
@@ -1,5 +1,5 @@
 /*
- * LP5521/LP5523/LP55231 Common Driver
+ * LP5521/LP5523/LP55231/LP5562 Common Driver
  *
  * Copyright 2012 Texas Instruments
  *
@@ -12,6 +12,7 @@
  * Derived from leds-lp5521.c, leds-lp5523.c
  */
 
+#include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/firmware.h>
 #include <linux/i2c.h>
@@ -21,6 +22,9 @@
 
 #include "leds-lp55xx-common.h"
 
+/* External clock rate */
+#define LP55XX_CLK_32K			32768
+
 static struct lp55xx_led *cdev_to_lp55xx_led(struct led_classdev *cdev)
 {
 	return container_of(cdev, struct lp55xx_led, cdev);
@@ -80,7 +84,7 @@ static ssize_t lp55xx_show_current(struct device *dev,
 {
 	struct lp55xx_led *led = dev_to_lp55xx_led(dev);
 
-	return sprintf(buf, "%d\n", led->led_current);
+	return scnprintf(buf, PAGE_SIZE, "%d\n", led->led_current);
 }
 
 static ssize_t lp55xx_store_current(struct device *dev,
@@ -113,7 +117,7 @@ static ssize_t lp55xx_show_max_current(struct device *dev,
 {
 	struct lp55xx_led *led = dev_to_lp55xx_led(dev);
 
-	return sprintf(buf, "%d\n", led->max_current);
+	return scnprintf(buf, PAGE_SIZE, "%d\n", led->max_current);
 }
 
 static DEVICE_ATTR(led_current, S_IRUGO | S_IWUSR, lp55xx_show_current,
@@ -357,6 +361,35 @@ int lp55xx_update_bits(struct lp55xx_chip *chip, u8 reg, u8 mask, u8 val)
 }
 EXPORT_SYMBOL_GPL(lp55xx_update_bits);
 
+bool lp55xx_is_extclk_used(struct lp55xx_chip *chip)
+{
+	struct clk *clk;
+	int err;
+
+	clk = devm_clk_get(&chip->cl->dev, "32k_clk");
+	if (IS_ERR(clk))
+		goto use_internal_clk;
+
+	err = clk_prepare_enable(clk);
+	if (err)
+		goto use_internal_clk;
+
+	if (clk_get_rate(clk) != LP55XX_CLK_32K) {
+		clk_disable_unprepare(clk);
+		goto use_internal_clk;
+	}
+
+	dev_info(&chip->cl->dev, "%dHz external clock used\n",	LP55XX_CLK_32K);
+
+	chip->clk = clk;
+	return true;
+
+use_internal_clk:
+	dev_info(&chip->cl->dev, "internal clock used\n");
+	return false;
+}
+EXPORT_SYMBOL_GPL(lp55xx_is_extclk_used);
+
 int lp55xx_init_device(struct lp55xx_chip *chip)
 {
 	struct lp55xx_platform_data *pdata;
@@ -421,6 +454,9 @@ void lp55xx_deinit_device(struct lp55xx_chip *chip)
 {
 	struct lp55xx_platform_data *pdata = chip->pdata;
 
+	if (chip->clk)
+		clk_disable_unprepare(chip->clk);
+
 	if (pdata->enable)
 		pdata->enable(0);
 
diff --git a/drivers/leds/leds-lp55xx-common.h b/drivers/leds/leds-lp55xx-common.h
index ece4761..fa6a078 100644
--- a/drivers/leds/leds-lp55xx-common.h
+++ b/drivers/leds/leds-lp55xx-common.h
@@ -83,6 +83,7 @@ struct lp55xx_device_config {
  */
 struct lp55xx_chip {
 	struct i2c_client *cl;
+	struct clk *clk;
 	struct lp55xx_platform_data *pdata;
 	struct mutex lock;	/* lock for user-space interface */
 	int num_leds;
@@ -117,6 +118,9 @@ extern int lp55xx_read(struct lp55xx_chip *chip, u8 reg, u8 *val);
 extern int lp55xx_update_bits(struct lp55xx_chip *chip, u8 reg,
 			u8 mask, u8 val);
 
+/* external clock detection */
+extern bool lp55xx_is_extclk_used(struct lp55xx_chip *chip);
+
 /* common device init/deinit functions */
 extern int lp55xx_init_device(struct lp55xx_chip *chip);
 extern void lp55xx_deinit_device(struct lp55xx_chip *chip);
diff --git a/drivers/leds/leds-lt3593.c b/drivers/leds/leds-lt3593.c
index c9b9e1f..ca48a7d 100644
--- a/drivers/leds/leds-lt3593.c
+++ b/drivers/leds/leds-lt3593.c
@@ -106,8 +106,9 @@ static int create_lt3593_led(const struct gpio_led *template,
 	if (!template->retain_state_suspended)
 		led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME;
 
-	ret = devm_gpio_request_one(parent, template->gpio,
-				    GPIOF_DIR_OUT | state, template->name);
+	ret = devm_gpio_request_one(parent, template->gpio, state ?
+				    GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW,
+				    template->name);
 	if (ret < 0)
 		return ret;
 
diff --git a/drivers/leds/leds-ns2.c b/drivers/leds/leds-ns2.c
index d978171..70137b1 100644
--- a/drivers/leds/leds-ns2.c
+++ b/drivers/leds/leds-ns2.c
@@ -193,7 +193,8 @@ create_ns2_led(struct platform_device *pdev, struct ns2_led_data *led_dat,
 	enum ns2_led_modes mode;
 
 	ret = devm_gpio_request_one(&pdev->dev, template->cmd,
-			GPIOF_DIR_OUT | gpio_get_value(template->cmd),
+			gpio_get_value(template->cmd) ?
+			GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW,
 			template->name);
 	if (ret) {
 		dev_err(&pdev->dev, "%s: failed to setup command GPIO\n",
@@ -202,7 +203,8 @@ create_ns2_led(struct platform_device *pdev, struct ns2_led_data *led_dat,
 	}
 
 	ret = devm_gpio_request_one(&pdev->dev, template->slow,
-			GPIOF_DIR_OUT | gpio_get_value(template->slow),
+			gpio_get_value(template->slow) ?
+			GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW,
 			template->name);
 	if (ret) {
 		dev_err(&pdev->dev, "%s: failed to setup slow GPIO\n",
@@ -306,10 +308,21 @@ static const struct of_device_id of_ns2_leds_match[] = {
 };
 #endif /* CONFIG_OF_GPIO */
 
+struct ns2_led_priv {
+	int num_leds;
+	struct ns2_led_data leds_data[];
+};
+
+static inline int sizeof_ns2_led_priv(int num_leds)
+{
+	return sizeof(struct ns2_led_priv) +
+		      (sizeof(struct ns2_led_data) * num_leds);
+}
+
 static int ns2_led_probe(struct platform_device *pdev)
 {
 	struct ns2_led_platform_data *pdata = pdev->dev.platform_data;
-	struct ns2_led_data *leds_data;
+	struct ns2_led_priv *priv;
 	int i;
 	int ret;
 
@@ -330,21 +343,23 @@ static int ns2_led_probe(struct platform_device *pdev)
 		return -EINVAL;
 #endif /* CONFIG_OF_GPIO */
 
-	leds_data = devm_kzalloc(&pdev->dev, sizeof(struct ns2_led_data) *
-				 pdata->num_leds, GFP_KERNEL);
-	if (!leds_data)
+	priv = devm_kzalloc(&pdev->dev,
+			    sizeof_ns2_led_priv(pdata->num_leds), GFP_KERNEL);
+	if (!priv)
 		return -ENOMEM;
+	priv->num_leds = pdata->num_leds;
 
-	for (i = 0; i < pdata->num_leds; i++) {
-		ret = create_ns2_led(pdev, &leds_data[i], &pdata->leds[i]);
+	for (i = 0; i < priv->num_leds; i++) {
+		ret = create_ns2_led(pdev, &priv->leds_data[i],
+				     &pdata->leds[i]);
 		if (ret < 0) {
 			for (i = i - 1; i >= 0; i--)
-				delete_ns2_led(&leds_data[i]);
+				delete_ns2_led(&priv->leds_data[i]);
 			return ret;
 		}
 	}
 
-	platform_set_drvdata(pdev, leds_data);
+	platform_set_drvdata(pdev, priv);
 
 	return 0;
 }
@@ -352,13 +367,12 @@ static int ns2_led_probe(struct platform_device *pdev)
 static int ns2_led_remove(struct platform_device *pdev)
 {
 	int i;
-	struct ns2_led_platform_data *pdata = pdev->dev.platform_data;
-	struct ns2_led_data *leds_data;
+	struct ns2_led_priv *priv;
 
-	leds_data = platform_get_drvdata(pdev);
+	priv = platform_get_drvdata(pdev);
 
-	for (i = 0; i < pdata->num_leds; i++)
-		delete_ns2_led(&leds_data[i]);
+	for (i = 0; i < priv->num_leds; i++)
+		delete_ns2_led(&priv->leds_data[i]);
 
 	platform_set_drvdata(pdev, NULL);
 
diff --git a/drivers/leds/leds-ot200.c b/drivers/leds/leds-ot200.c
index ee14662..98cae52 100644
--- a/drivers/leds/leds-ot200.c
+++ b/drivers/leds/leds-ot200.c
@@ -47,37 +47,37 @@ static struct ot200_led leds[] = {
 	{
 		.name = "led_1",
 		.port = 0x49,
-		.mask = BIT(7),
+		.mask = BIT(6),
 	},
 	{
 		.name = "led_2",
 		.port = 0x49,
-		.mask = BIT(6),
+		.mask = BIT(5),
 	},
 	{
 		.name = "led_3",
 		.port = 0x49,
-		.mask = BIT(5),
+		.mask = BIT(4),
 	},
 	{
 		.name = "led_4",
 		.port = 0x49,
-		.mask = BIT(4),
+		.mask = BIT(3),
 	},
 	{
 		.name = "led_5",
 		.port = 0x49,
-		.mask = BIT(3),
+		.mask = BIT(2),
 	},
 	{
 		.name = "led_6",
 		.port = 0x49,
-		.mask = BIT(2),
+		.mask = BIT(1),
 	},
 	{
 		.name = "led_7",
 		.port = 0x49,
-		.mask = BIT(1),
+		.mask = BIT(0),
 	}
 };
 
diff --git a/drivers/leds/leds-pwm.c b/drivers/leds/leds-pwm.c
index a1ea5f6..faf52c0 100644
--- a/drivers/leds/leds-pwm.c
+++ b/drivers/leds/leds-pwm.c
@@ -23,12 +23,16 @@
 #include <linux/pwm.h>
 #include <linux/leds_pwm.h>
 #include <linux/slab.h>
+#include <linux/workqueue.h>
 
 struct led_pwm_data {
 	struct led_classdev	cdev;
 	struct pwm_device	*pwm;
+	struct work_struct	work;
 	unsigned int		active_low;
 	unsigned int		period;
+	int			duty;
+	bool			can_sleep;
 };
 
 struct led_pwm_priv {
@@ -36,6 +40,26 @@ struct led_pwm_priv {
 	struct led_pwm_data leds[0];
 };
 
+static void __led_pwm_set(struct led_pwm_data *led_dat)
+{
+	int new_duty = led_dat->duty;
+
+	pwm_config(led_dat->pwm, new_duty, led_dat->period);
+
+	if (new_duty == 0)
+		pwm_disable(led_dat->pwm);
+	else
+		pwm_enable(led_dat->pwm);
+}
+
+static void led_pwm_work(struct work_struct *work)
+{
+	struct led_pwm_data *led_dat =
+		container_of(work, struct led_pwm_data, work);
+
+	__led_pwm_set(led_dat);
+}
+
 static void led_pwm_set(struct led_classdev *led_cdev,
 	enum led_brightness brightness)
 {
@@ -44,13 +68,12 @@ static void led_pwm_set(struct led_classdev *led_cdev,
 	unsigned int max = led_dat->cdev.max_brightness;
 	unsigned int period =  led_dat->period;
 
-	if (brightness == 0) {
-		pwm_config(led_dat->pwm, 0, period);
-		pwm_disable(led_dat->pwm);
-	} else {
-		pwm_config(led_dat->pwm, brightness * period / max, period);
-		pwm_enable(led_dat->pwm);
-	}
+	led_dat->duty = brightness * period / max;
+
+	if (led_dat->can_sleep)
+		schedule_work(&led_dat->work);
+	else
+		__led_pwm_set(led_dat);
 }
 
 static inline size_t sizeof_pwm_leds_priv(int num_leds)
@@ -100,6 +123,10 @@ static struct led_pwm_priv *led_pwm_create_of(struct platform_device *pdev)
 		led_dat->cdev.brightness = LED_OFF;
 		led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME;
 
+		led_dat->can_sleep = pwm_can_sleep(led_dat->pwm);
+		if (led_dat->can_sleep)
+			INIT_WORK(&led_dat->work, led_pwm_work);
+
 		ret = led_classdev_register(&pdev->dev, &led_dat->cdev);
 		if (ret < 0) {
 			dev_err(&pdev->dev, "failed to register for %s\n",
@@ -153,6 +180,10 @@ static int led_pwm_probe(struct platform_device *pdev)
 			led_dat->cdev.max_brightness = cur_led->max_brightness;
 			led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME;
 
+			led_dat->can_sleep = pwm_can_sleep(led_dat->pwm);
+			if (led_dat->can_sleep)
+				INIT_WORK(&led_dat->work, led_pwm_work);
+
 			ret = led_classdev_register(&pdev->dev, &led_dat->cdev);
 			if (ret < 0)
 				goto err;
@@ -180,8 +211,11 @@ static int led_pwm_remove(struct platform_device *pdev)
 	struct led_pwm_priv *priv = platform_get_drvdata(pdev);
 	int i;
 
-	for (i = 0; i < priv->num_leds; i++)
+	for (i = 0; i < priv->num_leds; i++) {
 		led_classdev_unregister(&priv->leds[i].cdev);
+		if (priv->leds[i].can_sleep)
+			cancel_work_sync(&priv->leds[i].work);
+	}
 
 	return 0;
 }
diff --git a/drivers/leds/leds-renesas-tpu.c b/drivers/leds/leds-renesas-tpu.c
index d3c2b7e..9483f1c 100644
--- a/drivers/leds/leds-renesas-tpu.c
+++ b/drivers/leds/leds-renesas-tpu.c
@@ -205,7 +205,8 @@ static void r_tpu_set_pin(struct r_tpu_priv *p, enum r_tpu_pin new_state,
 		gpio_free(cfg->pin_gpio_fn);
 
 	if (new_state == R_TPU_PIN_GPIO)
-		gpio_request_one(cfg->pin_gpio, GPIOF_DIR_OUT | !!brightness,
+		gpio_request_one(cfg->pin_gpio, !!brightness ?
+				GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW,
 				cfg->name);
 
 	if (new_state == R_TPU_PIN_GPIO_FN)
diff --git a/drivers/leds/leds-tca6507.c b/drivers/leds/leds-tca6507.c
index 070ba07..98fe021 100644
--- a/drivers/leds/leds-tca6507.c
+++ b/drivers/leds/leds-tca6507.c
@@ -85,6 +85,7 @@
 #include <linux/gpio.h>
 #include <linux/workqueue.h>
 #include <linux/leds-tca6507.h>
+#include <linux/of.h>
 
 /* LED select registers determine the source that drives LED outputs */
 #define TCA6507_LS_LED_OFF	0x0	/* Output HI-Z (off) */
@@ -724,7 +725,6 @@ tca6507_led_dt_init(struct i2c_client *client)
 	return ERR_PTR(-ENODEV);
 }
 
-#define of_tca6507_leds_match NULL
 #endif
 
 static int tca6507_probe(struct i2c_client *client,
@@ -813,7 +813,7 @@ static struct i2c_driver tca6507_driver = {
 	.driver   = {
 		.name    = "leds-tca6507",
 		.owner   = THIS_MODULE,
-		.of_match_table = of_tca6507_leds_match,
+		.of_match_table = of_match_ptr(of_tca6507_leds_match),
 	},
 	.probe    = tca6507_probe,
 	.remove   = tca6507_remove,
diff --git a/drivers/leds/leds-wm8350.c b/drivers/leds/leds-wm8350.c
index ed15157..8a181d5 100644
--- a/drivers/leds/leds-wm8350.c
+++ b/drivers/leds/leds-wm8350.c
@@ -129,7 +129,10 @@ static void wm8350_led_disable(struct wm8350_led *led)
 	ret = regulator_disable(led->isink);
 	if (ret != 0) {
 		dev_err(led->cdev.dev, "Failed to disable ISINK: %d\n", ret);
-		regulator_enable(led->dcdc);
+		ret = regulator_enable(led->dcdc);
+		if (ret != 0)
+			dev_err(led->cdev.dev, "Failed to reenable DCDC: %d\n",
+				ret);
 		return;
 	}
 
diff --git a/drivers/leds/ledtrig-backlight.c b/drivers/leds/ledtrig-backlight.c
deleted file mode 100644
index 027a2b1..0000000
--- a/drivers/leds/ledtrig-backlight.c
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Backlight emulation LED trigger
- *
- * Copyright 2008 (C) Rodolfo Giometti <giometti@linux.it>
- * Copyright 2008 (C) Eurotech S.p.A. <info@eurotech.it>
- *
- * This program is free software; you can 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/slab.h>
-#include <linux/init.h>
-#include <linux/fb.h>
-#include <linux/leds.h>
-#include "leds.h"
-
-#define BLANK		1
-#define UNBLANK		0
-
-struct bl_trig_notifier {
-	struct led_classdev *led;
-	int brightness;
-	int old_status;
-	struct notifier_block notifier;
-	unsigned invert;
-};
-
-static int fb_notifier_callback(struct notifier_block *p,
-				unsigned long event, void *data)
-{
-	struct bl_trig_notifier *n = container_of(p,
-					struct bl_trig_notifier, notifier);
-	struct led_classdev *led = n->led;
-	struct fb_event *fb_event = data;
-	int *blank = fb_event->data;
-	int new_status = *blank ? BLANK : UNBLANK;
-
-	switch (event) {
-	case FB_EVENT_BLANK:
-		if (new_status == n->old_status)
-			break;
-
-		if ((n->old_status == UNBLANK) ^ n->invert) {
-			n->brightness = led->brightness;
-			__led_set_brightness(led, LED_OFF);
-		} else {
-			__led_set_brightness(led, n->brightness);
-		}
-
-		n->old_status = new_status;
-
-		break;
-	}
-
-	return 0;
-}
-
-static ssize_t bl_trig_invert_show(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct led_classdev *led = dev_get_drvdata(dev);
-	struct bl_trig_notifier *n = led->trigger_data;
-
-	return sprintf(buf, "%u\n", n->invert);
-}
-
-static ssize_t bl_trig_invert_store(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t num)
-{
-	struct led_classdev *led = dev_get_drvdata(dev);
-	struct bl_trig_notifier *n = led->trigger_data;
-	unsigned long invert;
-	int ret;
-
-	ret = kstrtoul(buf, 10, &invert);
-	if (ret < 0)
-		return ret;
-
-	if (invert > 1)
-		return -EINVAL;
-
-	n->invert = invert;
-
-	/* After inverting, we need to update the LED. */
-	if ((n->old_status == BLANK) ^ n->invert)
-		__led_set_brightness(led, LED_OFF);
-	else
-		__led_set_brightness(led, n->brightness);
-
-	return num;
-}
-static DEVICE_ATTR(inverted, 0644, bl_trig_invert_show, bl_trig_invert_store);
-
-static void bl_trig_activate(struct led_classdev *led)
-{
-	int ret;
-
-	struct bl_trig_notifier *n;
-
-	n = kzalloc(sizeof(struct bl_trig_notifier), GFP_KERNEL);
-	led->trigger_data = n;
-	if (!n) {
-		dev_err(led->dev, "unable to allocate backlight trigger\n");
-		return;
-	}
-
-	ret = device_create_file(led->dev, &dev_attr_inverted);
-	if (ret)
-		goto err_invert;
-
-	n->led = led;
-	n->brightness = led->brightness;
-	n->old_status = UNBLANK;
-	n->notifier.notifier_call = fb_notifier_callback;
-
-	ret = fb_register_client(&n->notifier);
-	if (ret)
-		dev_err(led->dev, "unable to register backlight trigger\n");
-	led->activated = true;
-
-	return;
-
-err_invert:
-	led->trigger_data = NULL;
-	kfree(n);
-}
-
-static void bl_trig_deactivate(struct led_classdev *led)
-{
-	struct bl_trig_notifier *n =
-		(struct bl_trig_notifier *) led->trigger_data;
-
-	if (led->activated) {
-		device_remove_file(led->dev, &dev_attr_inverted);
-		fb_unregister_client(&n->notifier);
-		kfree(n);
-		led->activated = false;
-	}
-}
-
-static struct led_trigger bl_led_trigger = {
-	.name		= "backlight",
-	.activate	= bl_trig_activate,
-	.deactivate	= bl_trig_deactivate
-};
-
-static int __init bl_trig_init(void)
-{
-	return led_trigger_register(&bl_led_trigger);
-}
-
-static void __exit bl_trig_exit(void)
-{
-	led_trigger_unregister(&bl_led_trigger);
-}
-
-module_init(bl_trig_init);
-module_exit(bl_trig_exit);
-
-MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>");
-MODULE_DESCRIPTION("Backlight emulation LED trigger");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/leds/ledtrig-cpu.c b/drivers/leds/ledtrig-cpu.c
deleted file mode 100644
index 4239b39..0000000
--- a/drivers/leds/ledtrig-cpu.c
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * ledtrig-cpu.c - LED trigger based on CPU activity
- *
- * This LED trigger will be registered for each possible CPU and named as
- * cpu0, cpu1, cpu2, cpu3, etc.
- *
- * It can be bound to any LED just like other triggers using either a
- * board file or via sysfs interface.
- *
- * An API named ledtrig_cpu is exported for any user, who want to add CPU
- * activity indication in their code
- *
- * Copyright 2011 Linus Walleij <linus.walleij@linaro.org>
- * Copyright 2011 - 2012 Bryan Wu <bryan.wu@canonical.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/kernel.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/percpu.h>
-#include <linux/syscore_ops.h>
-#include <linux/rwsem.h>
-#include "leds.h"
-
-#define MAX_NAME_LEN	8
-
-struct led_trigger_cpu {
-	char name[MAX_NAME_LEN];
-	struct led_trigger *_trig;
-};
-
-static DEFINE_PER_CPU(struct led_trigger_cpu, cpu_trig);
-
-/**
- * ledtrig_cpu - emit a CPU event as a trigger
- * @evt: CPU event to be emitted
- *
- * Emit a CPU event on a CPU core, which will trigger a
- * binded LED to turn on or turn off.
- */
-void ledtrig_cpu(enum cpu_led_event ledevt)
-{
-	struct led_trigger_cpu *trig = &__get_cpu_var(cpu_trig);
-
-	/* Locate the correct CPU LED */
-	switch (ledevt) {
-	case CPU_LED_IDLE_END:
-	case CPU_LED_START:
-		/* Will turn the LED on, max brightness */
-		led_trigger_event(trig->_trig, LED_FULL);
-		break;
-
-	case CPU_LED_IDLE_START:
-	case CPU_LED_STOP:
-	case CPU_LED_HALTED:
-		/* Will turn the LED off */
-		led_trigger_event(trig->_trig, LED_OFF);
-		break;
-
-	default:
-		/* Will leave the LED as it is */
-		break;
-	}
-}
-EXPORT_SYMBOL(ledtrig_cpu);
-
-static int ledtrig_cpu_syscore_suspend(void)
-{
-	ledtrig_cpu(CPU_LED_STOP);
-	return 0;
-}
-
-static void ledtrig_cpu_syscore_resume(void)
-{
-	ledtrig_cpu(CPU_LED_START);
-}
-
-static void ledtrig_cpu_syscore_shutdown(void)
-{
-	ledtrig_cpu(CPU_LED_HALTED);
-}
-
-static struct syscore_ops ledtrig_cpu_syscore_ops = {
-	.shutdown	= ledtrig_cpu_syscore_shutdown,
-	.suspend	= ledtrig_cpu_syscore_suspend,
-	.resume		= ledtrig_cpu_syscore_resume,
-};
-
-static int __init ledtrig_cpu_init(void)
-{
-	int cpu;
-
-	/* Supports up to 9999 cpu cores */
-	BUILD_BUG_ON(CONFIG_NR_CPUS > 9999);
-
-	/*
-	 * Registering CPU led trigger for each CPU core here
-	 * ignores CPU hotplug, but after this CPU hotplug works
-	 * fine with this trigger.
-	 */
-	for_each_possible_cpu(cpu) {
-		struct led_trigger_cpu *trig = &per_cpu(cpu_trig, cpu);
-
-		snprintf(trig->name, MAX_NAME_LEN, "cpu%d", cpu);
-
-		led_trigger_register_simple(trig->name, &trig->_trig);
-	}
-
-	register_syscore_ops(&ledtrig_cpu_syscore_ops);
-
-	pr_info("ledtrig-cpu: registered to indicate activity on CPUs\n");
-
-	return 0;
-}
-module_init(ledtrig_cpu_init);
-
-static void __exit ledtrig_cpu_exit(void)
-{
-	int cpu;
-
-	for_each_possible_cpu(cpu) {
-		struct led_trigger_cpu *trig = &per_cpu(cpu_trig, cpu);
-
-		led_trigger_unregister_simple(trig->_trig);
-		trig->_trig = NULL;
-		memset(trig->name, 0, MAX_NAME_LEN);
-	}
-
-	unregister_syscore_ops(&ledtrig_cpu_syscore_ops);
-}
-module_exit(ledtrig_cpu_exit);
-
-MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
-MODULE_AUTHOR("Bryan Wu <bryan.wu@canonical.com>");
-MODULE_DESCRIPTION("CPU LED trigger");
-MODULE_LICENSE("GPL");
diff --git a/drivers/leds/ledtrig-default-on.c b/drivers/leds/ledtrig-default-on.c
deleted file mode 100644
index eac1f1b..0000000
--- a/drivers/leds/ledtrig-default-on.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * LED Kernel Default ON Trigger
- *
- * Copyright 2008 Nick Forbes <nick.forbes@incepta.com>
- *
- * Based on Richard Purdie's ledtrig-timer.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/init.h>
-#include <linux/leds.h>
-#include "leds.h"
-
-static void defon_trig_activate(struct led_classdev *led_cdev)
-{
-	__led_set_brightness(led_cdev, led_cdev->max_brightness);
-}
-
-static struct led_trigger defon_led_trigger = {
-	.name     = "default-on",
-	.activate = defon_trig_activate,
-};
-
-static int __init defon_trig_init(void)
-{
-	return led_trigger_register(&defon_led_trigger);
-}
-
-static void __exit defon_trig_exit(void)
-{
-	led_trigger_unregister(&defon_led_trigger);
-}
-
-module_init(defon_trig_init);
-module_exit(defon_trig_exit);
-
-MODULE_AUTHOR("Nick Forbes <nick.forbes@incepta.com>");
-MODULE_DESCRIPTION("Default-ON LED trigger");
-MODULE_LICENSE("GPL");
diff --git a/drivers/leds/ledtrig-gpio.c b/drivers/leds/ledtrig-gpio.c
deleted file mode 100644
index 72e3ebf..0000000
--- a/drivers/leds/ledtrig-gpio.c
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * ledtrig-gio.c - LED Trigger Based on GPIO events
- *
- * Copyright 2009 Felipe Balbi <me@felipebalbi.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/kernel.h>
-#include <linux/init.h>
-#include <linux/gpio.h>
-#include <linux/interrupt.h>
-#include <linux/workqueue.h>
-#include <linux/leds.h>
-#include <linux/slab.h>
-#include "leds.h"
-
-struct gpio_trig_data {
-	struct led_classdev *led;
-	struct work_struct work;
-
-	unsigned desired_brightness;	/* desired brightness when led is on */
-	unsigned inverted;		/* true when gpio is inverted */
-	unsigned gpio;			/* gpio that triggers the leds */
-};
-
-static irqreturn_t gpio_trig_irq(int irq, void *_led)
-{
-	struct led_classdev *led = _led;
-	struct gpio_trig_data *gpio_data = led->trigger_data;
-
-	/* just schedule_work since gpio_get_value can sleep */
-	schedule_work(&gpio_data->work);
-
-	return IRQ_HANDLED;
-};
-
-static void gpio_trig_work(struct work_struct *work)
-{
-	struct gpio_trig_data *gpio_data = container_of(work,
-			struct gpio_trig_data, work);
-	int tmp;
-
-	if (!gpio_data->gpio)
-		return;
-
-	tmp = gpio_get_value(gpio_data->gpio);
-	if (gpio_data->inverted)
-		tmp = !tmp;
-
-	if (tmp) {
-		if (gpio_data->desired_brightness)
-			__led_set_brightness(gpio_data->led,
-					   gpio_data->desired_brightness);
-		else
-			__led_set_brightness(gpio_data->led, LED_FULL);
-	} else {
-		__led_set_brightness(gpio_data->led, LED_OFF);
-	}
-}
-
-static ssize_t gpio_trig_brightness_show(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct led_classdev *led = dev_get_drvdata(dev);
-	struct gpio_trig_data *gpio_data = led->trigger_data;
-
-	return sprintf(buf, "%u\n", gpio_data->desired_brightness);
-}
-
-static ssize_t gpio_trig_brightness_store(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t n)
-{
-	struct led_classdev *led = dev_get_drvdata(dev);
-	struct gpio_trig_data *gpio_data = led->trigger_data;
-	unsigned desired_brightness;
-	int ret;
-
-	ret = sscanf(buf, "%u", &desired_brightness);
-	if (ret < 1 || desired_brightness > 255) {
-		dev_err(dev, "invalid value\n");
-		return -EINVAL;
-	}
-
-	gpio_data->desired_brightness = desired_brightness;
-
-	return n;
-}
-static DEVICE_ATTR(desired_brightness, 0644, gpio_trig_brightness_show,
-		gpio_trig_brightness_store);
-
-static ssize_t gpio_trig_inverted_show(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct led_classdev *led = dev_get_drvdata(dev);
-	struct gpio_trig_data *gpio_data = led->trigger_data;
-
-	return sprintf(buf, "%u\n", gpio_data->inverted);
-}
-
-static ssize_t gpio_trig_inverted_store(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t n)
-{
-	struct led_classdev *led = dev_get_drvdata(dev);
-	struct gpio_trig_data *gpio_data = led->trigger_data;
-	unsigned long inverted;
-	int ret;
-
-	ret = kstrtoul(buf, 10, &inverted);
-	if (ret < 0)
-		return ret;
-
-	if (inverted > 1)
-		return -EINVAL;
-
-	gpio_data->inverted = inverted;
-
-	/* After inverting, we need to update the LED. */
-	schedule_work(&gpio_data->work);
-
-	return n;
-}
-static DEVICE_ATTR(inverted, 0644, gpio_trig_inverted_show,
-		gpio_trig_inverted_store);
-
-static ssize_t gpio_trig_gpio_show(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct led_classdev *led = dev_get_drvdata(dev);
-	struct gpio_trig_data *gpio_data = led->trigger_data;
-
-	return sprintf(buf, "%u\n", gpio_data->gpio);
-}
-
-static ssize_t gpio_trig_gpio_store(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t n)
-{
-	struct led_classdev *led = dev_get_drvdata(dev);
-	struct gpio_trig_data *gpio_data = led->trigger_data;
-	unsigned gpio;
-	int ret;
-
-	ret = sscanf(buf, "%u", &gpio);
-	if (ret < 1) {
-		dev_err(dev, "couldn't read gpio number\n");
-		flush_work(&gpio_data->work);
-		return -EINVAL;
-	}
-
-	if (gpio_data->gpio == gpio)
-		return n;
-
-	if (!gpio) {
-		if (gpio_data->gpio != 0)
-			free_irq(gpio_to_irq(gpio_data->gpio), led);
-		gpio_data->gpio = 0;
-		return n;
-	}
-
-	ret = request_irq(gpio_to_irq(gpio), gpio_trig_irq,
-			IRQF_SHARED | IRQF_TRIGGER_RISING
-			| IRQF_TRIGGER_FALLING, "ledtrig-gpio", led);
-	if (ret) {
-		dev_err(dev, "request_irq failed with error %d\n", ret);
-	} else {
-		if (gpio_data->gpio != 0)
-			free_irq(gpio_to_irq(gpio_data->gpio), led);
-		gpio_data->gpio = gpio;
-	}
-
-	return ret ? ret : n;
-}
-static DEVICE_ATTR(gpio, 0644, gpio_trig_gpio_show, gpio_trig_gpio_store);
-
-static void gpio_trig_activate(struct led_classdev *led)
-{
-	struct gpio_trig_data *gpio_data;
-	int ret;
-
-	gpio_data = kzalloc(sizeof(*gpio_data), GFP_KERNEL);
-	if (!gpio_data)
-		return;
-
-	ret = device_create_file(led->dev, &dev_attr_gpio);
-	if (ret)
-		goto err_gpio;
-
-	ret = device_create_file(led->dev, &dev_attr_inverted);
-	if (ret)
-		goto err_inverted;
-
-	ret = device_create_file(led->dev, &dev_attr_desired_brightness);
-	if (ret)
-		goto err_brightness;
-
-	gpio_data->led = led;
-	led->trigger_data = gpio_data;
-	INIT_WORK(&gpio_data->work, gpio_trig_work);
-	led->activated = true;
-
-	return;
-
-err_brightness:
-	device_remove_file(led->dev, &dev_attr_inverted);
-
-err_inverted:
-	device_remove_file(led->dev, &dev_attr_gpio);
-
-err_gpio:
-	kfree(gpio_data);
-}
-
-static void gpio_trig_deactivate(struct led_classdev *led)
-{
-	struct gpio_trig_data *gpio_data = led->trigger_data;
-
-	if (led->activated) {
-		device_remove_file(led->dev, &dev_attr_gpio);
-		device_remove_file(led->dev, &dev_attr_inverted);
-		device_remove_file(led->dev, &dev_attr_desired_brightness);
-		flush_work(&gpio_data->work);
-		if (gpio_data->gpio != 0)
-			free_irq(gpio_to_irq(gpio_data->gpio), led);
-		kfree(gpio_data);
-		led->activated = false;
-	}
-}
-
-static struct led_trigger gpio_led_trigger = {
-	.name		= "gpio",
-	.activate	= gpio_trig_activate,
-	.deactivate	= gpio_trig_deactivate,
-};
-
-static int __init gpio_trig_init(void)
-{
-	return led_trigger_register(&gpio_led_trigger);
-}
-module_init(gpio_trig_init);
-
-static void __exit gpio_trig_exit(void)
-{
-	led_trigger_unregister(&gpio_led_trigger);
-}
-module_exit(gpio_trig_exit);
-
-MODULE_AUTHOR("Felipe Balbi <me@felipebalbi.com>");
-MODULE_DESCRIPTION("GPIO LED trigger");
-MODULE_LICENSE("GPL");
diff --git a/drivers/leds/ledtrig-heartbeat.c b/drivers/leds/ledtrig-heartbeat.c
deleted file mode 100644
index 1edc746..0000000
--- a/drivers/leds/ledtrig-heartbeat.c
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * LED Heartbeat Trigger
- *
- * Copyright (C) 2006 Atsushi Nemoto <anemo@mba.ocn.ne.jp>
- *
- * Based on Richard Purdie's ledtrig-timer.c and some arch's
- * CONFIG_HEARTBEAT 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/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/timer.h>
-#include <linux/sched.h>
-#include <linux/leds.h>
-#include <linux/reboot.h>
-#include "leds.h"
-
-static int panic_heartbeats;
-
-struct heartbeat_trig_data {
-	unsigned int phase;
-	unsigned int period;
-	struct timer_list timer;
-};
-
-static void led_heartbeat_function(unsigned long data)
-{
-	struct led_classdev *led_cdev = (struct led_classdev *) data;
-	struct heartbeat_trig_data *heartbeat_data = led_cdev->trigger_data;
-	unsigned long brightness = LED_OFF;
-	unsigned long delay = 0;
-
-	if (unlikely(panic_heartbeats)) {
-		led_set_brightness(led_cdev, LED_OFF);
-		return;
-	}
-
-	/* acts like an actual heart beat -- ie thump-thump-pause... */
-	switch (heartbeat_data->phase) {
-	case 0:
-		/*
-		 * The hyperbolic function below modifies the
-		 * heartbeat period length in dependency of the
-		 * current (1min) load. It goes through the points
-		 * f(0)=1260, f(1)=860, f(5)=510, f(inf)->300.
-		 */
-		heartbeat_data->period = 300 +
-			(6720 << FSHIFT) / (5 * avenrun[0] + (7 << FSHIFT));
-		heartbeat_data->period =
-			msecs_to_jiffies(heartbeat_data->period);
-		delay = msecs_to_jiffies(70);
-		heartbeat_data->phase++;
-		brightness = led_cdev->max_brightness;
-		break;
-	case 1:
-		delay = heartbeat_data->period / 4 - msecs_to_jiffies(70);
-		heartbeat_data->phase++;
-		break;
-	case 2:
-		delay = msecs_to_jiffies(70);
-		heartbeat_data->phase++;
-		brightness = led_cdev->max_brightness;
-		break;
-	default:
-		delay = heartbeat_data->period - heartbeat_data->period / 4 -
-			msecs_to_jiffies(70);
-		heartbeat_data->phase = 0;
-		break;
-	}
-
-	__led_set_brightness(led_cdev, brightness);
-	mod_timer(&heartbeat_data->timer, jiffies + delay);
-}
-
-static void heartbeat_trig_activate(struct led_classdev *led_cdev)
-{
-	struct heartbeat_trig_data *heartbeat_data;
-
-	heartbeat_data = kzalloc(sizeof(*heartbeat_data), GFP_KERNEL);
-	if (!heartbeat_data)
-		return;
-
-	led_cdev->trigger_data = heartbeat_data;
-	setup_timer(&heartbeat_data->timer,
-		    led_heartbeat_function, (unsigned long) led_cdev);
-	heartbeat_data->phase = 0;
-	led_heartbeat_function(heartbeat_data->timer.data);
-	led_cdev->activated = true;
-}
-
-static void heartbeat_trig_deactivate(struct led_classdev *led_cdev)
-{
-	struct heartbeat_trig_data *heartbeat_data = led_cdev->trigger_data;
-
-	if (led_cdev->activated) {
-		del_timer_sync(&heartbeat_data->timer);
-		kfree(heartbeat_data);
-		led_cdev->activated = false;
-	}
-}
-
-static struct led_trigger heartbeat_led_trigger = {
-	.name     = "heartbeat",
-	.activate = heartbeat_trig_activate,
-	.deactivate = heartbeat_trig_deactivate,
-};
-
-static int heartbeat_reboot_notifier(struct notifier_block *nb,
-				     unsigned long code, void *unused)
-{
-	led_trigger_unregister(&heartbeat_led_trigger);
-	return NOTIFY_DONE;
-}
-
-static int heartbeat_panic_notifier(struct notifier_block *nb,
-				     unsigned long code, void *unused)
-{
-	panic_heartbeats = 1;
-	return NOTIFY_DONE;
-}
-
-static struct notifier_block heartbeat_reboot_nb = {
-	.notifier_call = heartbeat_reboot_notifier,
-};
-
-static struct notifier_block heartbeat_panic_nb = {
-	.notifier_call = heartbeat_panic_notifier,
-};
-
-static int __init heartbeat_trig_init(void)
-{
-	int rc = led_trigger_register(&heartbeat_led_trigger);
-
-	if (!rc) {
-		atomic_notifier_chain_register(&panic_notifier_list,
-					       &heartbeat_panic_nb);
-		register_reboot_notifier(&heartbeat_reboot_nb);
-	}
-	return rc;
-}
-
-static void __exit heartbeat_trig_exit(void)
-{
-	unregister_reboot_notifier(&heartbeat_reboot_nb);
-	atomic_notifier_chain_unregister(&panic_notifier_list,
-					 &heartbeat_panic_nb);
-	led_trigger_unregister(&heartbeat_led_trigger);
-}
-
-module_init(heartbeat_trig_init);
-module_exit(heartbeat_trig_exit);
-
-MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>");
-MODULE_DESCRIPTION("Heartbeat LED trigger");
-MODULE_LICENSE("GPL");
diff --git a/drivers/leds/ledtrig-ide-disk.c b/drivers/leds/ledtrig-ide-disk.c
deleted file mode 100644
index 2cd7c0c..0000000
--- a/drivers/leds/ledtrig-ide-disk.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * LED IDE-Disk Activity Trigger
- *
- * Copyright 2006 Openedhand Ltd.
- *
- * Author: Richard Purdie <rpurdie@openedhand.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/kernel.h>
-#include <linux/init.h>
-#include <linux/leds.h>
-
-#define BLINK_DELAY 30
-
-DEFINE_LED_TRIGGER(ledtrig_ide);
-static unsigned long ide_blink_delay = BLINK_DELAY;
-
-void ledtrig_ide_activity(void)
-{
-	led_trigger_blink_oneshot(ledtrig_ide,
-				  &ide_blink_delay, &ide_blink_delay, 0);
-}
-EXPORT_SYMBOL(ledtrig_ide_activity);
-
-static int __init ledtrig_ide_init(void)
-{
-	led_trigger_register_simple("ide-disk", &ledtrig_ide);
-	return 0;
-}
-
-static void __exit ledtrig_ide_exit(void)
-{
-	led_trigger_unregister_simple(ledtrig_ide);
-}
-
-module_init(ledtrig_ide_init);
-module_exit(ledtrig_ide_exit);
-
-MODULE_AUTHOR("Richard Purdie <rpurdie@openedhand.com>");
-MODULE_DESCRIPTION("LED IDE Disk Activity Trigger");
-MODULE_LICENSE("GPL");
diff --git a/drivers/leds/ledtrig-oneshot.c b/drivers/leds/ledtrig-oneshot.c
deleted file mode 100644
index 2c029aa..0000000
--- a/drivers/leds/ledtrig-oneshot.c
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * One-shot LED Trigger
- *
- * Copyright 2012, Fabio Baltieri <fabio.baltieri@gmail.com>
- *
- * Based on ledtrig-timer.c by Richard Purdie <rpurdie@openedhand.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/kernel.h>
-#include <linux/init.h>
-#include <linux/device.h>
-#include <linux/ctype.h>
-#include <linux/slab.h>
-#include <linux/leds.h>
-#include "leds.h"
-
-#define DEFAULT_DELAY 100
-
-struct oneshot_trig_data {
-	unsigned int invert;
-};
-
-static ssize_t led_shot(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t size)
-{
-	struct led_classdev *led_cdev = dev_get_drvdata(dev);
-	struct oneshot_trig_data *oneshot_data = led_cdev->trigger_data;
-
-	led_blink_set_oneshot(led_cdev,
-			&led_cdev->blink_delay_on, &led_cdev->blink_delay_off,
-			oneshot_data->invert);
-
-	/* content is ignored */
-	return size;
-}
-static ssize_t led_invert_show(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct led_classdev *led_cdev = dev_get_drvdata(dev);
-	struct oneshot_trig_data *oneshot_data = led_cdev->trigger_data;
-
-	return sprintf(buf, "%u\n", oneshot_data->invert);
-}
-
-static ssize_t led_invert_store(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t size)
-{
-	struct led_classdev *led_cdev = dev_get_drvdata(dev);
-	struct oneshot_trig_data *oneshot_data = led_cdev->trigger_data;
-	unsigned long state;
-	int ret;
-
-	ret = kstrtoul(buf, 0, &state);
-	if (ret)
-		return ret;
-
-	oneshot_data->invert = !!state;
-
-	if (oneshot_data->invert)
-		__led_set_brightness(led_cdev, LED_FULL);
-	else
-		__led_set_brightness(led_cdev, LED_OFF);
-
-	return size;
-}
-
-static ssize_t led_delay_on_show(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct led_classdev *led_cdev = dev_get_drvdata(dev);
-
-	return sprintf(buf, "%lu\n", led_cdev->blink_delay_on);
-}
-
-static ssize_t led_delay_on_store(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t size)
-{
-	struct led_classdev *led_cdev = dev_get_drvdata(dev);
-	unsigned long state;
-	int ret;
-
-	ret = kstrtoul(buf, 0, &state);
-	if (ret)
-		return ret;
-
-	led_cdev->blink_delay_on = state;
-
-	return size;
-}
-static ssize_t led_delay_off_show(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct led_classdev *led_cdev = dev_get_drvdata(dev);
-
-	return sprintf(buf, "%lu\n", led_cdev->blink_delay_off);
-}
-
-static ssize_t led_delay_off_store(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t size)
-{
-	struct led_classdev *led_cdev = dev_get_drvdata(dev);
-	unsigned long state;
-	int ret;
-
-	ret = kstrtoul(buf, 0, &state);
-	if (ret)
-		return ret;
-
-	led_cdev->blink_delay_off = state;
-
-	return size;
-}
-
-static DEVICE_ATTR(delay_on, 0644, led_delay_on_show, led_delay_on_store);
-static DEVICE_ATTR(delay_off, 0644, led_delay_off_show, led_delay_off_store);
-static DEVICE_ATTR(invert, 0644, led_invert_show, led_invert_store);
-static DEVICE_ATTR(shot, 0200, NULL, led_shot);
-
-static void oneshot_trig_activate(struct led_classdev *led_cdev)
-{
-	struct oneshot_trig_data *oneshot_data;
-	int rc;
-
-	oneshot_data = kzalloc(sizeof(*oneshot_data), GFP_KERNEL);
-	if (!oneshot_data)
-		return;
-
-	led_cdev->trigger_data = oneshot_data;
-
-	rc = device_create_file(led_cdev->dev, &dev_attr_delay_on);
-	if (rc)
-		goto err_out_trig_data;
-	rc = device_create_file(led_cdev->dev, &dev_attr_delay_off);
-	if (rc)
-		goto err_out_delayon;
-	rc = device_create_file(led_cdev->dev, &dev_attr_invert);
-	if (rc)
-		goto err_out_delayoff;
-	rc = device_create_file(led_cdev->dev, &dev_attr_shot);
-	if (rc)
-		goto err_out_invert;
-
-	led_cdev->blink_delay_on = DEFAULT_DELAY;
-	led_cdev->blink_delay_off = DEFAULT_DELAY;
-
-	led_cdev->activated = true;
-
-	return;
-
-err_out_invert:
-	device_remove_file(led_cdev->dev, &dev_attr_invert);
-err_out_delayoff:
-	device_remove_file(led_cdev->dev, &dev_attr_delay_off);
-err_out_delayon:
-	device_remove_file(led_cdev->dev, &dev_attr_delay_on);
-err_out_trig_data:
-	kfree(led_cdev->trigger_data);
-}
-
-static void oneshot_trig_deactivate(struct led_classdev *led_cdev)
-{
-	struct oneshot_trig_data *oneshot_data = led_cdev->trigger_data;
-
-	if (led_cdev->activated) {
-		device_remove_file(led_cdev->dev, &dev_attr_delay_on);
-		device_remove_file(led_cdev->dev, &dev_attr_delay_off);
-		device_remove_file(led_cdev->dev, &dev_attr_invert);
-		device_remove_file(led_cdev->dev, &dev_attr_shot);
-		kfree(oneshot_data);
-		led_cdev->activated = false;
-	}
-
-	/* Stop blinking */
-	led_set_brightness(led_cdev, LED_OFF);
-}
-
-static struct led_trigger oneshot_led_trigger = {
-	.name     = "oneshot",
-	.activate = oneshot_trig_activate,
-	.deactivate = oneshot_trig_deactivate,
-};
-
-static int __init oneshot_trig_init(void)
-{
-	return led_trigger_register(&oneshot_led_trigger);
-}
-
-static void __exit oneshot_trig_exit(void)
-{
-	led_trigger_unregister(&oneshot_led_trigger);
-}
-
-module_init(oneshot_trig_init);
-module_exit(oneshot_trig_exit);
-
-MODULE_AUTHOR("Fabio Baltieri <fabio.baltieri@gmail.com>");
-MODULE_DESCRIPTION("One-shot LED trigger");
-MODULE_LICENSE("GPL");
diff --git a/drivers/leds/ledtrig-timer.c b/drivers/leds/ledtrig-timer.c
deleted file mode 100644
index f774d05..0000000
--- a/drivers/leds/ledtrig-timer.c
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * LED Kernel Timer Trigger
- *
- * Copyright 2005-2006 Openedhand Ltd.
- *
- * Author: Richard Purdie <rpurdie@openedhand.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/kernel.h>
-#include <linux/init.h>
-#include <linux/device.h>
-#include <linux/ctype.h>
-#include <linux/leds.h>
-#include "leds.h"
-
-static ssize_t led_delay_on_show(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct led_classdev *led_cdev = dev_get_drvdata(dev);
-
-	return sprintf(buf, "%lu\n", led_cdev->blink_delay_on);
-}
-
-static ssize_t led_delay_on_store(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t size)
-{
-	struct led_classdev *led_cdev = dev_get_drvdata(dev);
-	unsigned long state;
-	ssize_t ret = -EINVAL;
-
-	ret = kstrtoul(buf, 10, &state);
-	if (ret)
-		return ret;
-
-	led_blink_set(led_cdev, &state, &led_cdev->blink_delay_off);
-	led_cdev->blink_delay_on = state;
-
-	return size;
-}
-
-static ssize_t led_delay_off_show(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct led_classdev *led_cdev = dev_get_drvdata(dev);
-
-	return sprintf(buf, "%lu\n", led_cdev->blink_delay_off);
-}
-
-static ssize_t led_delay_off_store(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t size)
-{
-	struct led_classdev *led_cdev = dev_get_drvdata(dev);
-	unsigned long state;
-	ssize_t ret = -EINVAL;
-
-	ret = kstrtoul(buf, 10, &state);
-	if (ret)
-		return ret;
-
-	led_blink_set(led_cdev, &led_cdev->blink_delay_on, &state);
-	led_cdev->blink_delay_off = state;
-
-	return size;
-}
-
-static DEVICE_ATTR(delay_on, 0644, led_delay_on_show, led_delay_on_store);
-static DEVICE_ATTR(delay_off, 0644, led_delay_off_show, led_delay_off_store);
-
-static void timer_trig_activate(struct led_classdev *led_cdev)
-{
-	int rc;
-
-	led_cdev->trigger_data = NULL;
-
-	rc = device_create_file(led_cdev->dev, &dev_attr_delay_on);
-	if (rc)
-		return;
-	rc = device_create_file(led_cdev->dev, &dev_attr_delay_off);
-	if (rc)
-		goto err_out_delayon;
-
-	led_blink_set(led_cdev, &led_cdev->blink_delay_on,
-		      &led_cdev->blink_delay_off);
-	led_cdev->activated = true;
-
-	return;
-
-err_out_delayon:
-	device_remove_file(led_cdev->dev, &dev_attr_delay_on);
-}
-
-static void timer_trig_deactivate(struct led_classdev *led_cdev)
-{
-	if (led_cdev->activated) {
-		device_remove_file(led_cdev->dev, &dev_attr_delay_on);
-		device_remove_file(led_cdev->dev, &dev_attr_delay_off);
-		led_cdev->activated = false;
-	}
-
-	/* Stop blinking */
-	led_set_brightness(led_cdev, LED_OFF);
-}
-
-static struct led_trigger timer_led_trigger = {
-	.name     = "timer",
-	.activate = timer_trig_activate,
-	.deactivate = timer_trig_deactivate,
-};
-
-static int __init timer_trig_init(void)
-{
-	return led_trigger_register(&timer_led_trigger);
-}
-
-static void __exit timer_trig_exit(void)
-{
-	led_trigger_unregister(&timer_led_trigger);
-}
-
-module_init(timer_trig_init);
-module_exit(timer_trig_exit);
-
-MODULE_AUTHOR("Richard Purdie <rpurdie@openedhand.com>");
-MODULE_DESCRIPTION("Timer LED trigger");
-MODULE_LICENSE("GPL");
diff --git a/drivers/leds/ledtrig-transient.c b/drivers/leds/ledtrig-transient.c
deleted file mode 100644
index 398f104..0000000
--- a/drivers/leds/ledtrig-transient.c
+++ /dev/null
@@ -1,237 +0,0 @@
-/*
- * LED Kernel Transient Trigger
- *
- * Copyright (C) 2012 Shuah Khan <shuahkhan@gmail.com>
- *
- * Based on Richard Purdie's ledtrig-timer.c and Atsushi Nemoto's
- * ledtrig-heartbeat.c
- * Design and use-case input from Jonas Bonn <jonas@southpole.se> and
- * Neil Brown <neilb@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.
- *
- */
-/*
- * Transient trigger allows one shot timer activation. Please refer to
- * Documentation/leds/ledtrig-transient.txt for details
-*/
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/device.h>
-#include <linux/slab.h>
-#include <linux/timer.h>
-#include <linux/leds.h>
-#include "leds.h"
-
-struct transient_trig_data {
-	int activate;
-	int state;
-	int restore_state;
-	unsigned long duration;
-	struct timer_list timer;
-};
-
-static void transient_timer_function(unsigned long data)
-{
-	struct led_classdev *led_cdev = (struct led_classdev *) data;
-	struct transient_trig_data *transient_data = led_cdev->trigger_data;
-
-	transient_data->activate = 0;
-	__led_set_brightness(led_cdev, transient_data->restore_state);
-}
-
-static ssize_t transient_activate_show(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct led_classdev *led_cdev = dev_get_drvdata(dev);
-	struct transient_trig_data *transient_data = led_cdev->trigger_data;
-
-	return sprintf(buf, "%d\n", transient_data->activate);
-}
-
-static ssize_t transient_activate_store(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t size)
-{
-	struct led_classdev *led_cdev = dev_get_drvdata(dev);
-	struct transient_trig_data *transient_data = led_cdev->trigger_data;
-	unsigned long state;
-	ssize_t ret;
-
-	ret = kstrtoul(buf, 10, &state);
-	if (ret)
-		return ret;
-
-	if (state != 1 && state != 0)
-		return -EINVAL;
-
-	/* cancel the running timer */
-	if (state == 0 && transient_data->activate == 1) {
-		del_timer(&transient_data->timer);
-		transient_data->activate = state;
-		__led_set_brightness(led_cdev, transient_data->restore_state);
-		return size;
-	}
-
-	/* start timer if there is no active timer */
-	if (state == 1 && transient_data->activate == 0 &&
-	    transient_data->duration != 0) {
-		transient_data->activate = state;
-		__led_set_brightness(led_cdev, transient_data->state);
-		transient_data->restore_state =
-		    (transient_data->state == LED_FULL) ? LED_OFF : LED_FULL;
-		mod_timer(&transient_data->timer,
-			  jiffies + transient_data->duration);
-	}
-
-	/* state == 0 && transient_data->activate == 0
-		timer is not active - just return */
-	/* state == 1 && transient_data->activate == 1
-		timer is already active - just return */
-
-	return size;
-}
-
-static ssize_t transient_duration_show(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct led_classdev *led_cdev = dev_get_drvdata(dev);
-	struct transient_trig_data *transient_data = led_cdev->trigger_data;
-
-	return sprintf(buf, "%lu\n", transient_data->duration);
-}
-
-static ssize_t transient_duration_store(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t size)
-{
-	struct led_classdev *led_cdev = dev_get_drvdata(dev);
-	struct transient_trig_data *transient_data = led_cdev->trigger_data;
-	unsigned long state;
-	ssize_t ret;
-
-	ret = kstrtoul(buf, 10, &state);
-	if (ret)
-		return ret;
-
-	transient_data->duration = state;
-	return size;
-}
-
-static ssize_t transient_state_show(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct led_classdev *led_cdev = dev_get_drvdata(dev);
-	struct transient_trig_data *transient_data = led_cdev->trigger_data;
-	int state;
-
-	state = (transient_data->state == LED_FULL) ? 1 : 0;
-	return sprintf(buf, "%d\n", state);
-}
-
-static ssize_t transient_state_store(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t size)
-{
-	struct led_classdev *led_cdev = dev_get_drvdata(dev);
-	struct transient_trig_data *transient_data = led_cdev->trigger_data;
-	unsigned long state;
-	ssize_t ret;
-
-	ret = kstrtoul(buf, 10, &state);
-	if (ret)
-		return ret;
-
-	if (state != 1 && state != 0)
-		return -EINVAL;
-
-	transient_data->state = (state == 1) ? LED_FULL : LED_OFF;
-	return size;
-}
-
-static DEVICE_ATTR(activate, 0644, transient_activate_show,
-		   transient_activate_store);
-static DEVICE_ATTR(duration, 0644, transient_duration_show,
-		   transient_duration_store);
-static DEVICE_ATTR(state, 0644, transient_state_show, transient_state_store);
-
-static void transient_trig_activate(struct led_classdev *led_cdev)
-{
-	int rc;
-	struct transient_trig_data *tdata;
-
-	tdata = kzalloc(sizeof(struct transient_trig_data), GFP_KERNEL);
-	if (!tdata) {
-		dev_err(led_cdev->dev,
-			"unable to allocate transient trigger\n");
-		return;
-	}
-	led_cdev->trigger_data = tdata;
-
-	rc = device_create_file(led_cdev->dev, &dev_attr_activate);
-	if (rc)
-		goto err_out;
-
-	rc = device_create_file(led_cdev->dev, &dev_attr_duration);
-	if (rc)
-		goto err_out_duration;
-
-	rc = device_create_file(led_cdev->dev, &dev_attr_state);
-	if (rc)
-		goto err_out_state;
-
-	setup_timer(&tdata->timer, transient_timer_function,
-		    (unsigned long) led_cdev);
-	led_cdev->activated = true;
-
-	return;
-
-err_out_state:
-	device_remove_file(led_cdev->dev, &dev_attr_duration);
-err_out_duration:
-	device_remove_file(led_cdev->dev, &dev_attr_activate);
-err_out:
-	dev_err(led_cdev->dev, "unable to register transient trigger\n");
-	led_cdev->trigger_data = NULL;
-	kfree(tdata);
-}
-
-static void transient_trig_deactivate(struct led_classdev *led_cdev)
-{
-	struct transient_trig_data *transient_data = led_cdev->trigger_data;
-
-	if (led_cdev->activated) {
-		del_timer_sync(&transient_data->timer);
-		__led_set_brightness(led_cdev, transient_data->restore_state);
-		device_remove_file(led_cdev->dev, &dev_attr_activate);
-		device_remove_file(led_cdev->dev, &dev_attr_duration);
-		device_remove_file(led_cdev->dev, &dev_attr_state);
-		led_cdev->trigger_data = NULL;
-		led_cdev->activated = false;
-		kfree(transient_data);
-	}
-}
-
-static struct led_trigger transient_trigger = {
-	.name     = "transient",
-	.activate = transient_trig_activate,
-	.deactivate = transient_trig_deactivate,
-};
-
-static int __init transient_trig_init(void)
-{
-	return led_trigger_register(&transient_trigger);
-}
-
-static void __exit transient_trig_exit(void)
-{
-	led_trigger_unregister(&transient_trigger);
-}
-
-module_init(transient_trig_init);
-module_exit(transient_trig_exit);
-
-MODULE_AUTHOR("Shuah Khan <shuahkhan@gmail.com>");
-MODULE_DESCRIPTION("Transient LED trigger");
-MODULE_LICENSE("GPL");
diff --git a/drivers/leds/trigger/Kconfig b/drivers/leds/trigger/Kconfig
new file mode 100644
index 0000000..49794b4
--- /dev/null
+++ b/drivers/leds/trigger/Kconfig
@@ -0,0 +1,111 @@
+menuconfig LEDS_TRIGGERS
+	bool "LED Trigger support"
+	depends on LEDS_CLASS
+	help
+	  This option enables trigger support for the leds class.
+	  These triggers allow kernel events to drive the LEDs and can
+	  be configured via sysfs. If unsure, say Y.
+
+if LEDS_TRIGGERS
+
+config LEDS_TRIGGER_TIMER
+	tristate "LED Timer Trigger"
+	depends on LEDS_TRIGGERS
+	help
+	  This allows LEDs to be controlled by a programmable timer
+	  via sysfs. Some LED hardware can be programmed to start
+	  blinking the LED without any further software interaction.
+	  For more details read Documentation/leds/leds-class.txt.
+
+	  If unsure, say Y.
+
+config LEDS_TRIGGER_ONESHOT
+	tristate "LED One-shot Trigger"
+	depends on LEDS_TRIGGERS
+	help
+	  This allows LEDs to blink in one-shot pulses with parameters
+	  controlled via sysfs.  It's useful to notify the user on
+	  sporadic events, when there are no clear begin and end trap points,
+	  or on dense events, where this blinks the LED at constant rate if
+	  rearmed continuously.
+
+	  It also shows how to use the led_blink_set_oneshot() function.
+
+	  If unsure, say Y.
+
+config LEDS_TRIGGER_IDE_DISK
+	bool "LED IDE Disk Trigger"
+	depends on IDE_GD_ATA
+	depends on LEDS_TRIGGERS
+	help
+	  This allows LEDs to be controlled by IDE disk activity.
+	  If unsure, say Y.
+
+config LEDS_TRIGGER_HEARTBEAT
+	tristate "LED Heartbeat Trigger"
+	depends on LEDS_TRIGGERS
+	help
+	  This allows LEDs to be controlled by a CPU load average.
+	  The flash frequency is a hyperbolic function of the 1-minute
+	  load average.
+	  If unsure, say Y.
+
+config LEDS_TRIGGER_BACKLIGHT
+	tristate "LED backlight Trigger"
+	depends on LEDS_TRIGGERS
+	help
+	  This allows LEDs to be controlled as a backlight device: they
+	  turn off and on when the display is blanked and unblanked.
+
+	  If unsure, say N.
+
+config LEDS_TRIGGER_CPU
+	bool "LED CPU Trigger"
+	depends on LEDS_TRIGGERS
+	help
+	  This allows LEDs to be controlled by active CPUs. This shows
+	  the active CPUs across an array of LEDs so you can see which
+	  CPUs are active on the system at any given moment.
+
+	  If unsure, say N.
+
+config LEDS_TRIGGER_GPIO
+	tristate "LED GPIO Trigger"
+	depends on LEDS_TRIGGERS
+	depends on GPIOLIB
+	help
+	  This allows LEDs to be controlled by gpio events. It's good
+	  when using gpios as switches and triggering the needed LEDs
+	  from there. One use case is n810's keypad LEDs that could
+	  be triggered by this trigger when user slides up to show
+	  keypad.
+
+	  If unsure, say N.
+
+config LEDS_TRIGGER_DEFAULT_ON
+	tristate "LED Default ON Trigger"
+	depends on LEDS_TRIGGERS
+	help
+	  This allows LEDs to be initialised in the ON state.
+	  If unsure, say Y.
+
+comment "iptables trigger is under Netfilter config (LED target)"
+	depends on LEDS_TRIGGERS
+
+config LEDS_TRIGGER_TRANSIENT
+	tristate "LED Transient Trigger"
+	depends on LEDS_TRIGGERS
+	help
+	  This allows one time activation of a transient state on
+	  GPIO/PWM based hardware.
+	  If unsure, say Y.
+
+config LEDS_TRIGGER_CAMERA
+	tristate "LED Camera Flash/Torch Trigger"
+	depends on LEDS_TRIGGERS
+	help
+	  This allows LEDs to be controlled as a camera flash/torch device.
+	  This enables direct flash/torch on/off by the driver, kernel space.
+	  If unsure, say Y.
+
+endif # LEDS_TRIGGERS
diff --git a/drivers/leds/trigger/Makefile b/drivers/leds/trigger/Makefile
new file mode 100644
index 0000000..1abf48d
--- /dev/null
+++ b/drivers/leds/trigger/Makefile
@@ -0,0 +1,10 @@
+obj-$(CONFIG_LEDS_TRIGGER_TIMER)	+= ledtrig-timer.o
+obj-$(CONFIG_LEDS_TRIGGER_ONESHOT)	+= ledtrig-oneshot.o
+obj-$(CONFIG_LEDS_TRIGGER_IDE_DISK)	+= ledtrig-ide-disk.o
+obj-$(CONFIG_LEDS_TRIGGER_HEARTBEAT)	+= ledtrig-heartbeat.o
+obj-$(CONFIG_LEDS_TRIGGER_BACKLIGHT)	+= ledtrig-backlight.o
+obj-$(CONFIG_LEDS_TRIGGER_GPIO)		+= ledtrig-gpio.o
+obj-$(CONFIG_LEDS_TRIGGER_CPU)		+= ledtrig-cpu.o
+obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON)	+= ledtrig-default-on.o
+obj-$(CONFIG_LEDS_TRIGGER_TRANSIENT)	+= ledtrig-transient.o
+obj-$(CONFIG_LEDS_TRIGGER_CAMERA)	+= ledtrig-camera.o
diff --git a/drivers/leds/trigger/ledtrig-backlight.c b/drivers/leds/trigger/ledtrig-backlight.c
new file mode 100644
index 0000000..3c9c88a
--- /dev/null
+++ b/drivers/leds/trigger/ledtrig-backlight.c
@@ -0,0 +1,166 @@
+/*
+ * Backlight emulation LED trigger
+ *
+ * Copyright 2008 (C) Rodolfo Giometti <giometti@linux.it>
+ * Copyright 2008 (C) Eurotech S.p.A. <info@eurotech.it>
+ *
+ * This program is free software; you can 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/slab.h>
+#include <linux/init.h>
+#include <linux/fb.h>
+#include <linux/leds.h>
+#include "../leds.h"
+
+#define BLANK		1
+#define UNBLANK		0
+
+struct bl_trig_notifier {
+	struct led_classdev *led;
+	int brightness;
+	int old_status;
+	struct notifier_block notifier;
+	unsigned invert;
+};
+
+static int fb_notifier_callback(struct notifier_block *p,
+				unsigned long event, void *data)
+{
+	struct bl_trig_notifier *n = container_of(p,
+					struct bl_trig_notifier, notifier);
+	struct led_classdev *led = n->led;
+	struct fb_event *fb_event = data;
+	int *blank = fb_event->data;
+	int new_status = *blank ? BLANK : UNBLANK;
+
+	switch (event) {
+	case FB_EVENT_BLANK:
+		if (new_status == n->old_status)
+			break;
+
+		if ((n->old_status == UNBLANK) ^ n->invert) {
+			n->brightness = led->brightness;
+			__led_set_brightness(led, LED_OFF);
+		} else {
+			__led_set_brightness(led, n->brightness);
+		}
+
+		n->old_status = new_status;
+
+		break;
+	}
+
+	return 0;
+}
+
+static ssize_t bl_trig_invert_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct led_classdev *led = dev_get_drvdata(dev);
+	struct bl_trig_notifier *n = led->trigger_data;
+
+	return sprintf(buf, "%u\n", n->invert);
+}
+
+static ssize_t bl_trig_invert_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t num)
+{
+	struct led_classdev *led = dev_get_drvdata(dev);
+	struct bl_trig_notifier *n = led->trigger_data;
+	unsigned long invert;
+	int ret;
+
+	ret = kstrtoul(buf, 10, &invert);
+	if (ret < 0)
+		return ret;
+
+	if (invert > 1)
+		return -EINVAL;
+
+	n->invert = invert;
+
+	/* After inverting, we need to update the LED. */
+	if ((n->old_status == BLANK) ^ n->invert)
+		__led_set_brightness(led, LED_OFF);
+	else
+		__led_set_brightness(led, n->brightness);
+
+	return num;
+}
+static DEVICE_ATTR(inverted, 0644, bl_trig_invert_show, bl_trig_invert_store);
+
+static void bl_trig_activate(struct led_classdev *led)
+{
+	int ret;
+
+	struct bl_trig_notifier *n;
+
+	n = kzalloc(sizeof(struct bl_trig_notifier), GFP_KERNEL);
+	led->trigger_data = n;
+	if (!n) {
+		dev_err(led->dev, "unable to allocate backlight trigger\n");
+		return;
+	}
+
+	ret = device_create_file(led->dev, &dev_attr_inverted);
+	if (ret)
+		goto err_invert;
+
+	n->led = led;
+	n->brightness = led->brightness;
+	n->old_status = UNBLANK;
+	n->notifier.notifier_call = fb_notifier_callback;
+
+	ret = fb_register_client(&n->notifier);
+	if (ret)
+		dev_err(led->dev, "unable to register backlight trigger\n");
+	led->activated = true;
+
+	return;
+
+err_invert:
+	led->trigger_data = NULL;
+	kfree(n);
+}
+
+static void bl_trig_deactivate(struct led_classdev *led)
+{
+	struct bl_trig_notifier *n =
+		(struct bl_trig_notifier *) led->trigger_data;
+
+	if (led->activated) {
+		device_remove_file(led->dev, &dev_attr_inverted);
+		fb_unregister_client(&n->notifier);
+		kfree(n);
+		led->activated = false;
+	}
+}
+
+static struct led_trigger bl_led_trigger = {
+	.name		= "backlight",
+	.activate	= bl_trig_activate,
+	.deactivate	= bl_trig_deactivate
+};
+
+static int __init bl_trig_init(void)
+{
+	return led_trigger_register(&bl_led_trigger);
+}
+
+static void __exit bl_trig_exit(void)
+{
+	led_trigger_unregister(&bl_led_trigger);
+}
+
+module_init(bl_trig_init);
+module_exit(bl_trig_exit);
+
+MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>");
+MODULE_DESCRIPTION("Backlight emulation LED trigger");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/leds/trigger/ledtrig-camera.c b/drivers/leds/trigger/ledtrig-camera.c
new file mode 100644
index 0000000..9bd73a8
--- /dev/null
+++ b/drivers/leds/trigger/ledtrig-camera.c
@@ -0,0 +1,57 @@
+/*
+ * Camera Flash and Torch On/Off Trigger
+ *
+ * based on ledtrig-ide-disk.c
+ *
+ * Copyright 2013 Texas Instruments
+ *
+ * Author: Milo(Woogyom) Kim <milo.kim@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.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/leds.h>
+
+DEFINE_LED_TRIGGER(ledtrig_flash);
+DEFINE_LED_TRIGGER(ledtrig_torch);
+
+void ledtrig_flash_ctrl(bool on)
+{
+	enum led_brightness brt = on ? LED_FULL : LED_OFF;
+
+	led_trigger_event(ledtrig_flash, brt);
+}
+EXPORT_SYMBOL_GPL(ledtrig_flash_ctrl);
+
+void ledtrig_torch_ctrl(bool on)
+{
+	enum led_brightness brt = on ? LED_FULL : LED_OFF;
+
+	led_trigger_event(ledtrig_torch, brt);
+}
+EXPORT_SYMBOL_GPL(ledtrig_torch_ctrl);
+
+static int __init ledtrig_camera_init(void)
+{
+	led_trigger_register_simple("flash", &ledtrig_flash);
+	led_trigger_register_simple("torch", &ledtrig_torch);
+	return 0;
+}
+module_init(ledtrig_camera_init);
+
+static void __exit ledtrig_camera_exit(void)
+{
+	led_trigger_unregister_simple(ledtrig_torch);
+	led_trigger_unregister_simple(ledtrig_flash);
+}
+module_exit(ledtrig_camera_exit);
+
+MODULE_DESCRIPTION("LED Trigger for Camera Flash/Torch Control");
+MODULE_AUTHOR("Milo Kim");
+MODULE_LICENSE("GPL");
diff --git a/drivers/leds/trigger/ledtrig-cpu.c b/drivers/leds/trigger/ledtrig-cpu.c
new file mode 100644
index 0000000..118335e
--- /dev/null
+++ b/drivers/leds/trigger/ledtrig-cpu.c
@@ -0,0 +1,142 @@
+/*
+ * ledtrig-cpu.c - LED trigger based on CPU activity
+ *
+ * This LED trigger will be registered for each possible CPU and named as
+ * cpu0, cpu1, cpu2, cpu3, etc.
+ *
+ * It can be bound to any LED just like other triggers using either a
+ * board file or via sysfs interface.
+ *
+ * An API named ledtrig_cpu is exported for any user, who want to add CPU
+ * activity indication in their code
+ *
+ * Copyright 2011 Linus Walleij <linus.walleij@linaro.org>
+ * Copyright 2011 - 2012 Bryan Wu <bryan.wu@canonical.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/kernel.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/percpu.h>
+#include <linux/syscore_ops.h>
+#include <linux/rwsem.h>
+#include "../leds.h"
+
+#define MAX_NAME_LEN	8
+
+struct led_trigger_cpu {
+	char name[MAX_NAME_LEN];
+	struct led_trigger *_trig;
+};
+
+static DEFINE_PER_CPU(struct led_trigger_cpu, cpu_trig);
+
+/**
+ * ledtrig_cpu - emit a CPU event as a trigger
+ * @evt: CPU event to be emitted
+ *
+ * Emit a CPU event on a CPU core, which will trigger a
+ * binded LED to turn on or turn off.
+ */
+void ledtrig_cpu(enum cpu_led_event ledevt)
+{
+	struct led_trigger_cpu *trig = &__get_cpu_var(cpu_trig);
+
+	/* Locate the correct CPU LED */
+	switch (ledevt) {
+	case CPU_LED_IDLE_END:
+	case CPU_LED_START:
+		/* Will turn the LED on, max brightness */
+		led_trigger_event(trig->_trig, LED_FULL);
+		break;
+
+	case CPU_LED_IDLE_START:
+	case CPU_LED_STOP:
+	case CPU_LED_HALTED:
+		/* Will turn the LED off */
+		led_trigger_event(trig->_trig, LED_OFF);
+		break;
+
+	default:
+		/* Will leave the LED as it is */
+		break;
+	}
+}
+EXPORT_SYMBOL(ledtrig_cpu);
+
+static int ledtrig_cpu_syscore_suspend(void)
+{
+	ledtrig_cpu(CPU_LED_STOP);
+	return 0;
+}
+
+static void ledtrig_cpu_syscore_resume(void)
+{
+	ledtrig_cpu(CPU_LED_START);
+}
+
+static void ledtrig_cpu_syscore_shutdown(void)
+{
+	ledtrig_cpu(CPU_LED_HALTED);
+}
+
+static struct syscore_ops ledtrig_cpu_syscore_ops = {
+	.shutdown	= ledtrig_cpu_syscore_shutdown,
+	.suspend	= ledtrig_cpu_syscore_suspend,
+	.resume		= ledtrig_cpu_syscore_resume,
+};
+
+static int __init ledtrig_cpu_init(void)
+{
+	int cpu;
+
+	/* Supports up to 9999 cpu cores */
+	BUILD_BUG_ON(CONFIG_NR_CPUS > 9999);
+
+	/*
+	 * Registering CPU led trigger for each CPU core here
+	 * ignores CPU hotplug, but after this CPU hotplug works
+	 * fine with this trigger.
+	 */
+	for_each_possible_cpu(cpu) {
+		struct led_trigger_cpu *trig = &per_cpu(cpu_trig, cpu);
+
+		snprintf(trig->name, MAX_NAME_LEN, "cpu%d", cpu);
+
+		led_trigger_register_simple(trig->name, &trig->_trig);
+	}
+
+	register_syscore_ops(&ledtrig_cpu_syscore_ops);
+
+	pr_info("ledtrig-cpu: registered to indicate activity on CPUs\n");
+
+	return 0;
+}
+module_init(ledtrig_cpu_init);
+
+static void __exit ledtrig_cpu_exit(void)
+{
+	int cpu;
+
+	for_each_possible_cpu(cpu) {
+		struct led_trigger_cpu *trig = &per_cpu(cpu_trig, cpu);
+
+		led_trigger_unregister_simple(trig->_trig);
+		trig->_trig = NULL;
+		memset(trig->name, 0, MAX_NAME_LEN);
+	}
+
+	unregister_syscore_ops(&ledtrig_cpu_syscore_ops);
+}
+module_exit(ledtrig_cpu_exit);
+
+MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
+MODULE_AUTHOR("Bryan Wu <bryan.wu@canonical.com>");
+MODULE_DESCRIPTION("CPU LED trigger");
+MODULE_LICENSE("GPL");
diff --git a/drivers/leds/trigger/ledtrig-default-on.c b/drivers/leds/trigger/ledtrig-default-on.c
new file mode 100644
index 0000000..81a91be
--- /dev/null
+++ b/drivers/leds/trigger/ledtrig-default-on.c
@@ -0,0 +1,45 @@
+/*
+ * LED Kernel Default ON Trigger
+ *
+ * Copyright 2008 Nick Forbes <nick.forbes@incepta.com>
+ *
+ * Based on Richard Purdie's ledtrig-timer.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/init.h>
+#include <linux/leds.h>
+#include "../leds.h"
+
+static void defon_trig_activate(struct led_classdev *led_cdev)
+{
+	__led_set_brightness(led_cdev, led_cdev->max_brightness);
+}
+
+static struct led_trigger defon_led_trigger = {
+	.name     = "default-on",
+	.activate = defon_trig_activate,
+};
+
+static int __init defon_trig_init(void)
+{
+	return led_trigger_register(&defon_led_trigger);
+}
+
+static void __exit defon_trig_exit(void)
+{
+	led_trigger_unregister(&defon_led_trigger);
+}
+
+module_init(defon_trig_init);
+module_exit(defon_trig_exit);
+
+MODULE_AUTHOR("Nick Forbes <nick.forbes@incepta.com>");
+MODULE_DESCRIPTION("Default-ON LED trigger");
+MODULE_LICENSE("GPL");
diff --git a/drivers/leds/trigger/ledtrig-gpio.c b/drivers/leds/trigger/ledtrig-gpio.c
new file mode 100644
index 0000000..35812e3
--- /dev/null
+++ b/drivers/leds/trigger/ledtrig-gpio.c
@@ -0,0 +1,253 @@
+/*
+ * ledtrig-gio.c - LED Trigger Based on GPIO events
+ *
+ * Copyright 2009 Felipe Balbi <me@felipebalbi.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/kernel.h>
+#include <linux/init.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/leds.h>
+#include <linux/slab.h>
+#include "../leds.h"
+
+struct gpio_trig_data {
+	struct led_classdev *led;
+	struct work_struct work;
+
+	unsigned desired_brightness;	/* desired brightness when led is on */
+	unsigned inverted;		/* true when gpio is inverted */
+	unsigned gpio;			/* gpio that triggers the leds */
+};
+
+static irqreturn_t gpio_trig_irq(int irq, void *_led)
+{
+	struct led_classdev *led = _led;
+	struct gpio_trig_data *gpio_data = led->trigger_data;
+
+	/* just schedule_work since gpio_get_value can sleep */
+	schedule_work(&gpio_data->work);
+
+	return IRQ_HANDLED;
+};
+
+static void gpio_trig_work(struct work_struct *work)
+{
+	struct gpio_trig_data *gpio_data = container_of(work,
+			struct gpio_trig_data, work);
+	int tmp;
+
+	if (!gpio_data->gpio)
+		return;
+
+	tmp = gpio_get_value(gpio_data->gpio);
+	if (gpio_data->inverted)
+		tmp = !tmp;
+
+	if (tmp) {
+		if (gpio_data->desired_brightness)
+			__led_set_brightness(gpio_data->led,
+					   gpio_data->desired_brightness);
+		else
+			__led_set_brightness(gpio_data->led, LED_FULL);
+	} else {
+		__led_set_brightness(gpio_data->led, LED_OFF);
+	}
+}
+
+static ssize_t gpio_trig_brightness_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct led_classdev *led = dev_get_drvdata(dev);
+	struct gpio_trig_data *gpio_data = led->trigger_data;
+
+	return sprintf(buf, "%u\n", gpio_data->desired_brightness);
+}
+
+static ssize_t gpio_trig_brightness_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t n)
+{
+	struct led_classdev *led = dev_get_drvdata(dev);
+	struct gpio_trig_data *gpio_data = led->trigger_data;
+	unsigned desired_brightness;
+	int ret;
+
+	ret = sscanf(buf, "%u", &desired_brightness);
+	if (ret < 1 || desired_brightness > 255) {
+		dev_err(dev, "invalid value\n");
+		return -EINVAL;
+	}
+
+	gpio_data->desired_brightness = desired_brightness;
+
+	return n;
+}
+static DEVICE_ATTR(desired_brightness, 0644, gpio_trig_brightness_show,
+		gpio_trig_brightness_store);
+
+static ssize_t gpio_trig_inverted_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct led_classdev *led = dev_get_drvdata(dev);
+	struct gpio_trig_data *gpio_data = led->trigger_data;
+
+	return sprintf(buf, "%u\n", gpio_data->inverted);
+}
+
+static ssize_t gpio_trig_inverted_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t n)
+{
+	struct led_classdev *led = dev_get_drvdata(dev);
+	struct gpio_trig_data *gpio_data = led->trigger_data;
+	unsigned long inverted;
+	int ret;
+
+	ret = kstrtoul(buf, 10, &inverted);
+	if (ret < 0)
+		return ret;
+
+	if (inverted > 1)
+		return -EINVAL;
+
+	gpio_data->inverted = inverted;
+
+	/* After inverting, we need to update the LED. */
+	schedule_work(&gpio_data->work);
+
+	return n;
+}
+static DEVICE_ATTR(inverted, 0644, gpio_trig_inverted_show,
+		gpio_trig_inverted_store);
+
+static ssize_t gpio_trig_gpio_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct led_classdev *led = dev_get_drvdata(dev);
+	struct gpio_trig_data *gpio_data = led->trigger_data;
+
+	return sprintf(buf, "%u\n", gpio_data->gpio);
+}
+
+static ssize_t gpio_trig_gpio_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t n)
+{
+	struct led_classdev *led = dev_get_drvdata(dev);
+	struct gpio_trig_data *gpio_data = led->trigger_data;
+	unsigned gpio;
+	int ret;
+
+	ret = sscanf(buf, "%u", &gpio);
+	if (ret < 1) {
+		dev_err(dev, "couldn't read gpio number\n");
+		flush_work(&gpio_data->work);
+		return -EINVAL;
+	}
+
+	if (gpio_data->gpio == gpio)
+		return n;
+
+	if (!gpio) {
+		if (gpio_data->gpio != 0)
+			free_irq(gpio_to_irq(gpio_data->gpio), led);
+		gpio_data->gpio = 0;
+		return n;
+	}
+
+	ret = request_irq(gpio_to_irq(gpio), gpio_trig_irq,
+			IRQF_SHARED | IRQF_TRIGGER_RISING
+			| IRQF_TRIGGER_FALLING, "ledtrig-gpio", led);
+	if (ret) {
+		dev_err(dev, "request_irq failed with error %d\n", ret);
+	} else {
+		if (gpio_data->gpio != 0)
+			free_irq(gpio_to_irq(gpio_data->gpio), led);
+		gpio_data->gpio = gpio;
+	}
+
+	return ret ? ret : n;
+}
+static DEVICE_ATTR(gpio, 0644, gpio_trig_gpio_show, gpio_trig_gpio_store);
+
+static void gpio_trig_activate(struct led_classdev *led)
+{
+	struct gpio_trig_data *gpio_data;
+	int ret;
+
+	gpio_data = kzalloc(sizeof(*gpio_data), GFP_KERNEL);
+	if (!gpio_data)
+		return;
+
+	ret = device_create_file(led->dev, &dev_attr_gpio);
+	if (ret)
+		goto err_gpio;
+
+	ret = device_create_file(led->dev, &dev_attr_inverted);
+	if (ret)
+		goto err_inverted;
+
+	ret = device_create_file(led->dev, &dev_attr_desired_brightness);
+	if (ret)
+		goto err_brightness;
+
+	gpio_data->led = led;
+	led->trigger_data = gpio_data;
+	INIT_WORK(&gpio_data->work, gpio_trig_work);
+	led->activated = true;
+
+	return;
+
+err_brightness:
+	device_remove_file(led->dev, &dev_attr_inverted);
+
+err_inverted:
+	device_remove_file(led->dev, &dev_attr_gpio);
+
+err_gpio:
+	kfree(gpio_data);
+}
+
+static void gpio_trig_deactivate(struct led_classdev *led)
+{
+	struct gpio_trig_data *gpio_data = led->trigger_data;
+
+	if (led->activated) {
+		device_remove_file(led->dev, &dev_attr_gpio);
+		device_remove_file(led->dev, &dev_attr_inverted);
+		device_remove_file(led->dev, &dev_attr_desired_brightness);
+		flush_work(&gpio_data->work);
+		if (gpio_data->gpio != 0)
+			free_irq(gpio_to_irq(gpio_data->gpio), led);
+		kfree(gpio_data);
+		led->activated = false;
+	}
+}
+
+static struct led_trigger gpio_led_trigger = {
+	.name		= "gpio",
+	.activate	= gpio_trig_activate,
+	.deactivate	= gpio_trig_deactivate,
+};
+
+static int __init gpio_trig_init(void)
+{
+	return led_trigger_register(&gpio_led_trigger);
+}
+module_init(gpio_trig_init);
+
+static void __exit gpio_trig_exit(void)
+{
+	led_trigger_unregister(&gpio_led_trigger);
+}
+module_exit(gpio_trig_exit);
+
+MODULE_AUTHOR("Felipe Balbi <me@felipebalbi.com>");
+MODULE_DESCRIPTION("GPIO LED trigger");
+MODULE_LICENSE("GPL");
diff --git a/drivers/leds/trigger/ledtrig-heartbeat.c b/drivers/leds/trigger/ledtrig-heartbeat.c
new file mode 100644
index 0000000..5c8464a
--- /dev/null
+++ b/drivers/leds/trigger/ledtrig-heartbeat.c
@@ -0,0 +1,161 @@
+/*
+ * LED Heartbeat Trigger
+ *
+ * Copyright (C) 2006 Atsushi Nemoto <anemo@mba.ocn.ne.jp>
+ *
+ * Based on Richard Purdie's ledtrig-timer.c and some arch's
+ * CONFIG_HEARTBEAT 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/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/timer.h>
+#include <linux/sched.h>
+#include <linux/leds.h>
+#include <linux/reboot.h>
+#include "../leds.h"
+
+static int panic_heartbeats;
+
+struct heartbeat_trig_data {
+	unsigned int phase;
+	unsigned int period;
+	struct timer_list timer;
+};
+
+static void led_heartbeat_function(unsigned long data)
+{
+	struct led_classdev *led_cdev = (struct led_classdev *) data;
+	struct heartbeat_trig_data *heartbeat_data = led_cdev->trigger_data;
+	unsigned long brightness = LED_OFF;
+	unsigned long delay = 0;
+
+	if (unlikely(panic_heartbeats)) {
+		led_set_brightness(led_cdev, LED_OFF);
+		return;
+	}
+
+	/* acts like an actual heart beat -- ie thump-thump-pause... */
+	switch (heartbeat_data->phase) {
+	case 0:
+		/*
+		 * The hyperbolic function below modifies the
+		 * heartbeat period length in dependency of the
+		 * current (1min) load. It goes through the points
+		 * f(0)=1260, f(1)=860, f(5)=510, f(inf)->300.
+		 */
+		heartbeat_data->period = 300 +
+			(6720 << FSHIFT) / (5 * avenrun[0] + (7 << FSHIFT));
+		heartbeat_data->period =
+			msecs_to_jiffies(heartbeat_data->period);
+		delay = msecs_to_jiffies(70);
+		heartbeat_data->phase++;
+		brightness = led_cdev->max_brightness;
+		break;
+	case 1:
+		delay = heartbeat_data->period / 4 - msecs_to_jiffies(70);
+		heartbeat_data->phase++;
+		break;
+	case 2:
+		delay = msecs_to_jiffies(70);
+		heartbeat_data->phase++;
+		brightness = led_cdev->max_brightness;
+		break;
+	default:
+		delay = heartbeat_data->period - heartbeat_data->period / 4 -
+			msecs_to_jiffies(70);
+		heartbeat_data->phase = 0;
+		break;
+	}
+
+	__led_set_brightness(led_cdev, brightness);
+	mod_timer(&heartbeat_data->timer, jiffies + delay);
+}
+
+static void heartbeat_trig_activate(struct led_classdev *led_cdev)
+{
+	struct heartbeat_trig_data *heartbeat_data;
+
+	heartbeat_data = kzalloc(sizeof(*heartbeat_data), GFP_KERNEL);
+	if (!heartbeat_data)
+		return;
+
+	led_cdev->trigger_data = heartbeat_data;
+	setup_timer(&heartbeat_data->timer,
+		    led_heartbeat_function, (unsigned long) led_cdev);
+	heartbeat_data->phase = 0;
+	led_heartbeat_function(heartbeat_data->timer.data);
+	led_cdev->activated = true;
+}
+
+static void heartbeat_trig_deactivate(struct led_classdev *led_cdev)
+{
+	struct heartbeat_trig_data *heartbeat_data = led_cdev->trigger_data;
+
+	if (led_cdev->activated) {
+		del_timer_sync(&heartbeat_data->timer);
+		kfree(heartbeat_data);
+		led_cdev->activated = false;
+	}
+}
+
+static struct led_trigger heartbeat_led_trigger = {
+	.name     = "heartbeat",
+	.activate = heartbeat_trig_activate,
+	.deactivate = heartbeat_trig_deactivate,
+};
+
+static int heartbeat_reboot_notifier(struct notifier_block *nb,
+				     unsigned long code, void *unused)
+{
+	led_trigger_unregister(&heartbeat_led_trigger);
+	return NOTIFY_DONE;
+}
+
+static int heartbeat_panic_notifier(struct notifier_block *nb,
+				     unsigned long code, void *unused)
+{
+	panic_heartbeats = 1;
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block heartbeat_reboot_nb = {
+	.notifier_call = heartbeat_reboot_notifier,
+};
+
+static struct notifier_block heartbeat_panic_nb = {
+	.notifier_call = heartbeat_panic_notifier,
+};
+
+static int __init heartbeat_trig_init(void)
+{
+	int rc = led_trigger_register(&heartbeat_led_trigger);
+
+	if (!rc) {
+		atomic_notifier_chain_register(&panic_notifier_list,
+					       &heartbeat_panic_nb);
+		register_reboot_notifier(&heartbeat_reboot_nb);
+	}
+	return rc;
+}
+
+static void __exit heartbeat_trig_exit(void)
+{
+	unregister_reboot_notifier(&heartbeat_reboot_nb);
+	atomic_notifier_chain_unregister(&panic_notifier_list,
+					 &heartbeat_panic_nb);
+	led_trigger_unregister(&heartbeat_led_trigger);
+}
+
+module_init(heartbeat_trig_init);
+module_exit(heartbeat_trig_exit);
+
+MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>");
+MODULE_DESCRIPTION("Heartbeat LED trigger");
+MODULE_LICENSE("GPL");
diff --git a/drivers/leds/trigger/ledtrig-ide-disk.c b/drivers/leds/trigger/ledtrig-ide-disk.c
new file mode 100644
index 0000000..2cd7c0c
--- /dev/null
+++ b/drivers/leds/trigger/ledtrig-ide-disk.c
@@ -0,0 +1,47 @@
+/*
+ * LED IDE-Disk Activity Trigger
+ *
+ * Copyright 2006 Openedhand Ltd.
+ *
+ * Author: Richard Purdie <rpurdie@openedhand.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/kernel.h>
+#include <linux/init.h>
+#include <linux/leds.h>
+
+#define BLINK_DELAY 30
+
+DEFINE_LED_TRIGGER(ledtrig_ide);
+static unsigned long ide_blink_delay = BLINK_DELAY;
+
+void ledtrig_ide_activity(void)
+{
+	led_trigger_blink_oneshot(ledtrig_ide,
+				  &ide_blink_delay, &ide_blink_delay, 0);
+}
+EXPORT_SYMBOL(ledtrig_ide_activity);
+
+static int __init ledtrig_ide_init(void)
+{
+	led_trigger_register_simple("ide-disk", &ledtrig_ide);
+	return 0;
+}
+
+static void __exit ledtrig_ide_exit(void)
+{
+	led_trigger_unregister_simple(ledtrig_ide);
+}
+
+module_init(ledtrig_ide_init);
+module_exit(ledtrig_ide_exit);
+
+MODULE_AUTHOR("Richard Purdie <rpurdie@openedhand.com>");
+MODULE_DESCRIPTION("LED IDE Disk Activity Trigger");
+MODULE_LICENSE("GPL");
diff --git a/drivers/leds/trigger/ledtrig-oneshot.c b/drivers/leds/trigger/ledtrig-oneshot.c
new file mode 100644
index 0000000..cb4c746
--- /dev/null
+++ b/drivers/leds/trigger/ledtrig-oneshot.c
@@ -0,0 +1,204 @@
+/*
+ * One-shot LED Trigger
+ *
+ * Copyright 2012, Fabio Baltieri <fabio.baltieri@gmail.com>
+ *
+ * Based on ledtrig-timer.c by Richard Purdie <rpurdie@openedhand.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/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/ctype.h>
+#include <linux/slab.h>
+#include <linux/leds.h>
+#include "../leds.h"
+
+#define DEFAULT_DELAY 100
+
+struct oneshot_trig_data {
+	unsigned int invert;
+};
+
+static ssize_t led_shot(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	struct led_classdev *led_cdev = dev_get_drvdata(dev);
+	struct oneshot_trig_data *oneshot_data = led_cdev->trigger_data;
+
+	led_blink_set_oneshot(led_cdev,
+			&led_cdev->blink_delay_on, &led_cdev->blink_delay_off,
+			oneshot_data->invert);
+
+	/* content is ignored */
+	return size;
+}
+static ssize_t led_invert_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct led_classdev *led_cdev = dev_get_drvdata(dev);
+	struct oneshot_trig_data *oneshot_data = led_cdev->trigger_data;
+
+	return sprintf(buf, "%u\n", oneshot_data->invert);
+}
+
+static ssize_t led_invert_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	struct led_classdev *led_cdev = dev_get_drvdata(dev);
+	struct oneshot_trig_data *oneshot_data = led_cdev->trigger_data;
+	unsigned long state;
+	int ret;
+
+	ret = kstrtoul(buf, 0, &state);
+	if (ret)
+		return ret;
+
+	oneshot_data->invert = !!state;
+
+	if (oneshot_data->invert)
+		__led_set_brightness(led_cdev, LED_FULL);
+	else
+		__led_set_brightness(led_cdev, LED_OFF);
+
+	return size;
+}
+
+static ssize_t led_delay_on_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct led_classdev *led_cdev = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%lu\n", led_cdev->blink_delay_on);
+}
+
+static ssize_t led_delay_on_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	struct led_classdev *led_cdev = dev_get_drvdata(dev);
+	unsigned long state;
+	int ret;
+
+	ret = kstrtoul(buf, 0, &state);
+	if (ret)
+		return ret;
+
+	led_cdev->blink_delay_on = state;
+
+	return size;
+}
+static ssize_t led_delay_off_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct led_classdev *led_cdev = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%lu\n", led_cdev->blink_delay_off);
+}
+
+static ssize_t led_delay_off_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	struct led_classdev *led_cdev = dev_get_drvdata(dev);
+	unsigned long state;
+	int ret;
+
+	ret = kstrtoul(buf, 0, &state);
+	if (ret)
+		return ret;
+
+	led_cdev->blink_delay_off = state;
+
+	return size;
+}
+
+static DEVICE_ATTR(delay_on, 0644, led_delay_on_show, led_delay_on_store);
+static DEVICE_ATTR(delay_off, 0644, led_delay_off_show, led_delay_off_store);
+static DEVICE_ATTR(invert, 0644, led_invert_show, led_invert_store);
+static DEVICE_ATTR(shot, 0200, NULL, led_shot);
+
+static void oneshot_trig_activate(struct led_classdev *led_cdev)
+{
+	struct oneshot_trig_data *oneshot_data;
+	int rc;
+
+	oneshot_data = kzalloc(sizeof(*oneshot_data), GFP_KERNEL);
+	if (!oneshot_data)
+		return;
+
+	led_cdev->trigger_data = oneshot_data;
+
+	rc = device_create_file(led_cdev->dev, &dev_attr_delay_on);
+	if (rc)
+		goto err_out_trig_data;
+	rc = device_create_file(led_cdev->dev, &dev_attr_delay_off);
+	if (rc)
+		goto err_out_delayon;
+	rc = device_create_file(led_cdev->dev, &dev_attr_invert);
+	if (rc)
+		goto err_out_delayoff;
+	rc = device_create_file(led_cdev->dev, &dev_attr_shot);
+	if (rc)
+		goto err_out_invert;
+
+	led_cdev->blink_delay_on = DEFAULT_DELAY;
+	led_cdev->blink_delay_off = DEFAULT_DELAY;
+
+	led_cdev->activated = true;
+
+	return;
+
+err_out_invert:
+	device_remove_file(led_cdev->dev, &dev_attr_invert);
+err_out_delayoff:
+	device_remove_file(led_cdev->dev, &dev_attr_delay_off);
+err_out_delayon:
+	device_remove_file(led_cdev->dev, &dev_attr_delay_on);
+err_out_trig_data:
+	kfree(led_cdev->trigger_data);
+}
+
+static void oneshot_trig_deactivate(struct led_classdev *led_cdev)
+{
+	struct oneshot_trig_data *oneshot_data = led_cdev->trigger_data;
+
+	if (led_cdev->activated) {
+		device_remove_file(led_cdev->dev, &dev_attr_delay_on);
+		device_remove_file(led_cdev->dev, &dev_attr_delay_off);
+		device_remove_file(led_cdev->dev, &dev_attr_invert);
+		device_remove_file(led_cdev->dev, &dev_attr_shot);
+		kfree(oneshot_data);
+		led_cdev->activated = false;
+	}
+
+	/* Stop blinking */
+	led_set_brightness(led_cdev, LED_OFF);
+}
+
+static struct led_trigger oneshot_led_trigger = {
+	.name     = "oneshot",
+	.activate = oneshot_trig_activate,
+	.deactivate = oneshot_trig_deactivate,
+};
+
+static int __init oneshot_trig_init(void)
+{
+	return led_trigger_register(&oneshot_led_trigger);
+}
+
+static void __exit oneshot_trig_exit(void)
+{
+	led_trigger_unregister(&oneshot_led_trigger);
+}
+
+module_init(oneshot_trig_init);
+module_exit(oneshot_trig_exit);
+
+MODULE_AUTHOR("Fabio Baltieri <fabio.baltieri@gmail.com>");
+MODULE_DESCRIPTION("One-shot LED trigger");
+MODULE_LICENSE("GPL");
diff --git a/drivers/leds/trigger/ledtrig-timer.c b/drivers/leds/trigger/ledtrig-timer.c
new file mode 100644
index 0000000..8d09327
--- /dev/null
+++ b/drivers/leds/trigger/ledtrig-timer.c
@@ -0,0 +1,130 @@
+/*
+ * LED Kernel Timer Trigger
+ *
+ * Copyright 2005-2006 Openedhand Ltd.
+ *
+ * Author: Richard Purdie <rpurdie@openedhand.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/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/ctype.h>
+#include <linux/leds.h>
+
+static ssize_t led_delay_on_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct led_classdev *led_cdev = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%lu\n", led_cdev->blink_delay_on);
+}
+
+static ssize_t led_delay_on_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	struct led_classdev *led_cdev = dev_get_drvdata(dev);
+	unsigned long state;
+	ssize_t ret = -EINVAL;
+
+	ret = kstrtoul(buf, 10, &state);
+	if (ret)
+		return ret;
+
+	led_blink_set(led_cdev, &state, &led_cdev->blink_delay_off);
+	led_cdev->blink_delay_on = state;
+
+	return size;
+}
+
+static ssize_t led_delay_off_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct led_classdev *led_cdev = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%lu\n", led_cdev->blink_delay_off);
+}
+
+static ssize_t led_delay_off_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	struct led_classdev *led_cdev = dev_get_drvdata(dev);
+	unsigned long state;
+	ssize_t ret = -EINVAL;
+
+	ret = kstrtoul(buf, 10, &state);
+	if (ret)
+		return ret;
+
+	led_blink_set(led_cdev, &led_cdev->blink_delay_on, &state);
+	led_cdev->blink_delay_off = state;
+
+	return size;
+}
+
+static DEVICE_ATTR(delay_on, 0644, led_delay_on_show, led_delay_on_store);
+static DEVICE_ATTR(delay_off, 0644, led_delay_off_show, led_delay_off_store);
+
+static void timer_trig_activate(struct led_classdev *led_cdev)
+{
+	int rc;
+
+	led_cdev->trigger_data = NULL;
+
+	rc = device_create_file(led_cdev->dev, &dev_attr_delay_on);
+	if (rc)
+		return;
+	rc = device_create_file(led_cdev->dev, &dev_attr_delay_off);
+	if (rc)
+		goto err_out_delayon;
+
+	led_blink_set(led_cdev, &led_cdev->blink_delay_on,
+		      &led_cdev->blink_delay_off);
+	led_cdev->activated = true;
+
+	return;
+
+err_out_delayon:
+	device_remove_file(led_cdev->dev, &dev_attr_delay_on);
+}
+
+static void timer_trig_deactivate(struct led_classdev *led_cdev)
+{
+	if (led_cdev->activated) {
+		device_remove_file(led_cdev->dev, &dev_attr_delay_on);
+		device_remove_file(led_cdev->dev, &dev_attr_delay_off);
+		led_cdev->activated = false;
+	}
+
+	/* Stop blinking */
+	led_set_brightness(led_cdev, LED_OFF);
+}
+
+static struct led_trigger timer_led_trigger = {
+	.name     = "timer",
+	.activate = timer_trig_activate,
+	.deactivate = timer_trig_deactivate,
+};
+
+static int __init timer_trig_init(void)
+{
+	return led_trigger_register(&timer_led_trigger);
+}
+
+static void __exit timer_trig_exit(void)
+{
+	led_trigger_unregister(&timer_led_trigger);
+}
+
+module_init(timer_trig_init);
+module_exit(timer_trig_exit);
+
+MODULE_AUTHOR("Richard Purdie <rpurdie@openedhand.com>");
+MODULE_DESCRIPTION("Timer LED trigger");
+MODULE_LICENSE("GPL");
diff --git a/drivers/leds/trigger/ledtrig-transient.c b/drivers/leds/trigger/ledtrig-transient.c
new file mode 100644
index 0000000..e5abc00
--- /dev/null
+++ b/drivers/leds/trigger/ledtrig-transient.c
@@ -0,0 +1,237 @@
+/*
+ * LED Kernel Transient Trigger
+ *
+ * Copyright (C) 2012 Shuah Khan <shuahkhan@gmail.com>
+ *
+ * Based on Richard Purdie's ledtrig-timer.c and Atsushi Nemoto's
+ * ledtrig-heartbeat.c
+ * Design and use-case input from Jonas Bonn <jonas@southpole.se> and
+ * Neil Brown <neilb@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.
+ *
+ */
+/*
+ * Transient trigger allows one shot timer activation. Please refer to
+ * Documentation/leds/ledtrig-transient.txt for details
+*/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/timer.h>
+#include <linux/leds.h>
+#include "../leds.h"
+
+struct transient_trig_data {
+	int activate;
+	int state;
+	int restore_state;
+	unsigned long duration;
+	struct timer_list timer;
+};
+
+static void transient_timer_function(unsigned long data)
+{
+	struct led_classdev *led_cdev = (struct led_classdev *) data;
+	struct transient_trig_data *transient_data = led_cdev->trigger_data;
+
+	transient_data->activate = 0;
+	__led_set_brightness(led_cdev, transient_data->restore_state);
+}
+
+static ssize_t transient_activate_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct led_classdev *led_cdev = dev_get_drvdata(dev);
+	struct transient_trig_data *transient_data = led_cdev->trigger_data;
+
+	return sprintf(buf, "%d\n", transient_data->activate);
+}
+
+static ssize_t transient_activate_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	struct led_classdev *led_cdev = dev_get_drvdata(dev);
+	struct transient_trig_data *transient_data = led_cdev->trigger_data;
+	unsigned long state;
+	ssize_t ret;
+
+	ret = kstrtoul(buf, 10, &state);
+	if (ret)
+		return ret;
+
+	if (state != 1 && state != 0)
+		return -EINVAL;
+
+	/* cancel the running timer */
+	if (state == 0 && transient_data->activate == 1) {
+		del_timer(&transient_data->timer);
+		transient_data->activate = state;
+		__led_set_brightness(led_cdev, transient_data->restore_state);
+		return size;
+	}
+
+	/* start timer if there is no active timer */
+	if (state == 1 && transient_data->activate == 0 &&
+	    transient_data->duration != 0) {
+		transient_data->activate = state;
+		__led_set_brightness(led_cdev, transient_data->state);
+		transient_data->restore_state =
+		    (transient_data->state == LED_FULL) ? LED_OFF : LED_FULL;
+		mod_timer(&transient_data->timer,
+			  jiffies + transient_data->duration);
+	}
+
+	/* state == 0 && transient_data->activate == 0
+		timer is not active - just return */
+	/* state == 1 && transient_data->activate == 1
+		timer is already active - just return */
+
+	return size;
+}
+
+static ssize_t transient_duration_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct led_classdev *led_cdev = dev_get_drvdata(dev);
+	struct transient_trig_data *transient_data = led_cdev->trigger_data;
+
+	return sprintf(buf, "%lu\n", transient_data->duration);
+}
+
+static ssize_t transient_duration_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	struct led_classdev *led_cdev = dev_get_drvdata(dev);
+	struct transient_trig_data *transient_data = led_cdev->trigger_data;
+	unsigned long state;
+	ssize_t ret;
+
+	ret = kstrtoul(buf, 10, &state);
+	if (ret)
+		return ret;
+
+	transient_data->duration = state;
+	return size;
+}
+
+static ssize_t transient_state_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct led_classdev *led_cdev = dev_get_drvdata(dev);
+	struct transient_trig_data *transient_data = led_cdev->trigger_data;
+	int state;
+
+	state = (transient_data->state == LED_FULL) ? 1 : 0;
+	return sprintf(buf, "%d\n", state);
+}
+
+static ssize_t transient_state_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	struct led_classdev *led_cdev = dev_get_drvdata(dev);
+	struct transient_trig_data *transient_data = led_cdev->trigger_data;
+	unsigned long state;
+	ssize_t ret;
+
+	ret = kstrtoul(buf, 10, &state);
+	if (ret)
+		return ret;
+
+	if (state != 1 && state != 0)
+		return -EINVAL;
+
+	transient_data->state = (state == 1) ? LED_FULL : LED_OFF;
+	return size;
+}
+
+static DEVICE_ATTR(activate, 0644, transient_activate_show,
+		   transient_activate_store);
+static DEVICE_ATTR(duration, 0644, transient_duration_show,
+		   transient_duration_store);
+static DEVICE_ATTR(state, 0644, transient_state_show, transient_state_store);
+
+static void transient_trig_activate(struct led_classdev *led_cdev)
+{
+	int rc;
+	struct transient_trig_data *tdata;
+
+	tdata = kzalloc(sizeof(struct transient_trig_data), GFP_KERNEL);
+	if (!tdata) {
+		dev_err(led_cdev->dev,
+			"unable to allocate transient trigger\n");
+		return;
+	}
+	led_cdev->trigger_data = tdata;
+
+	rc = device_create_file(led_cdev->dev, &dev_attr_activate);
+	if (rc)
+		goto err_out;
+
+	rc = device_create_file(led_cdev->dev, &dev_attr_duration);
+	if (rc)
+		goto err_out_duration;
+
+	rc = device_create_file(led_cdev->dev, &dev_attr_state);
+	if (rc)
+		goto err_out_state;
+
+	setup_timer(&tdata->timer, transient_timer_function,
+		    (unsigned long) led_cdev);
+	led_cdev->activated = true;
+
+	return;
+
+err_out_state:
+	device_remove_file(led_cdev->dev, &dev_attr_duration);
+err_out_duration:
+	device_remove_file(led_cdev->dev, &dev_attr_activate);
+err_out:
+	dev_err(led_cdev->dev, "unable to register transient trigger\n");
+	led_cdev->trigger_data = NULL;
+	kfree(tdata);
+}
+
+static void transient_trig_deactivate(struct led_classdev *led_cdev)
+{
+	struct transient_trig_data *transient_data = led_cdev->trigger_data;
+
+	if (led_cdev->activated) {
+		del_timer_sync(&transient_data->timer);
+		__led_set_brightness(led_cdev, transient_data->restore_state);
+		device_remove_file(led_cdev->dev, &dev_attr_activate);
+		device_remove_file(led_cdev->dev, &dev_attr_duration);
+		device_remove_file(led_cdev->dev, &dev_attr_state);
+		led_cdev->trigger_data = NULL;
+		led_cdev->activated = false;
+		kfree(transient_data);
+	}
+}
+
+static struct led_trigger transient_trigger = {
+	.name     = "transient",
+	.activate = transient_trig_activate,
+	.deactivate = transient_trig_deactivate,
+};
+
+static int __init transient_trig_init(void)
+{
+	return led_trigger_register(&transient_trigger);
+}
+
+static void __exit transient_trig_exit(void)
+{
+	led_trigger_unregister(&transient_trigger);
+}
+
+module_init(transient_trig_init);
+module_exit(transient_trig_exit);
+
+MODULE_AUTHOR("Shuah Khan <shuahkhan@gmail.com>");
+MODULE_DESCRIPTION("Transient LED trigger");
+MODULE_LICENSE("GPL");
diff --git a/drivers/lguest/Kconfig b/drivers/lguest/Kconfig
index 89875ea..ee035ec 100644
--- a/drivers/lguest/Kconfig
+++ b/drivers/lguest/Kconfig
@@ -5,10 +5,9 @@ config LGUEST
 	---help---
 	  This is a very simple module which allows you to run
 	  multiple instances of the same Linux kernel, using the
-	  "lguest" command found in the Documentation/virtual/lguest
-	  directory.
+	  "lguest" command found in the tools/lguest directory.
 
 	  Note that "lguest" is pronounced to rhyme with "fell quest",
-	  not "rustyvisor". See Documentation/virtual/lguest/lguest.txt.
+	  not "rustyvisor". See tools/lguest/lguest.txt.
 
 	  If unsure, say N.  If curious, say M.  If masochistic, say Y.
diff --git a/drivers/lguest/page_tables.c b/drivers/lguest/page_tables.c
index 3b62be16..864baab 100644
--- a/drivers/lguest/page_tables.c
+++ b/drivers/lguest/page_tables.c
@@ -686,7 +686,7 @@ static unsigned int new_pgdir(struct lg_cpu *cpu,
 	 * We pick one entry at random to throw out.  Choosing the Least
 	 * Recently Used might be better, but this is easy.
 	 */
-	next = random32() % ARRAY_SIZE(cpu->lg->pgdirs);
+	next = prandom_u32() % ARRAY_SIZE(cpu->lg->pgdirs);
 	/* If it's never been allocated at all before, try now. */
 	if (!cpu->lg->pgdirs[next].pgdir) {
 		cpu->lg->pgdirs[next].pgdir =
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
index 22b8ce4..c31fbab 100644
--- a/drivers/macintosh/via-pmu.c
+++ b/drivers/macintosh/via-pmu.c
@@ -869,7 +869,7 @@ static int pmu_battery_proc_show(struct seq_file *m, void *v)
 
 static int pmu_battery_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, pmu_battery_proc_show, PDE(inode)->data);
+	return single_open(file, pmu_battery_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations pmu_battery_proc_fops = {
diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
index 9545c9f..438ea21 100644
--- a/drivers/mailbox/Kconfig
+++ b/drivers/mailbox/Kconfig
@@ -16,4 +16,45 @@ config PL320_MBOX
 	  Management Engine, primarily for cpufreq. Say Y here if you want
 	  to use the PL320 IPCM support.
 
+config OMAP1_MBOX
+       tristate "OMAP1 Mailbox framework support"
+       depends on ARCH_OMAP1
+       help
+         Mailbox implementation for OMAP chips with hardware for
+         interprocessor communication involving DSP in OMAP1. Say Y here
+         if you want to use OMAP1 Mailbox framework support.
+
+config OMAP2PLUS_MBOX
+       tristate "OMAP2+ Mailbox framework support"
+       depends on ARCH_OMAP2PLUS
+       help
+         Mailbox implementation for OMAP family chips with hardware for
+         interprocessor communication involving DSP, IVA1.0 and IVA2 in
+         OMAP2/3; or IPU, IVA HD and DSP in OMAP4. Say Y here if you want
+         to use OMAP2+ Mailbox framework support.
+
+config DBX500_MBOX
+	tristate "DBx500 Mailbox driver support"
+	depends on ARCH_U8500
+	help
+	  Say Y here if you want to use DBx500 Mailbox driver support for
+	  power coprocessor access on Ux500 and Ux540 families
+
+config MBOX_KFIFO_SIZE
+       int "Mailbox kfifo default buffer size (bytes)"
+       default 256
+       help
+         Specify the default size of mailbox's kfifo buffers (bytes).
+         This can also be changed at runtime (via the mbox_kfifo_size
+         module parameter).
+
+config MBOX_DATA_SIZE
+	int "Mailbox associated data max size (bytes)"
+	default 64 if DBX500_MBOX
+	default 4
+	help
+	  Specify the default size of mailbox's associated data buffer
+	  (bytes)
+          This can also be changed at runtime (via the mbox_kfifo_size
+          module parameter).
 endif
diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
index 543ad6a..ee5fb1e 100644
--- a/drivers/mailbox/Makefile
+++ b/drivers/mailbox/Makefile
@@ -1 +1,6 @@
 obj-$(CONFIG_PL320_MBOX)	+= pl320-ipc.o
+
+obj-$(CONFIG_MAILBOX)		+= mailbox.o
+obj-$(CONFIG_OMAP1_MBOX)	+= mailbox-omap1.o
+obj-$(CONFIG_OMAP2PLUS_MBOX)	+= mailbox-omap2.o
+obj-$(CONFIG_DBX500_MBOX)	+= mailbox-dbx500.o
diff --git a/drivers/mailbox/mailbox-dbx500.c b/drivers/mailbox/mailbox-dbx500.c
new file mode 100644
index 0000000..e9d2b0a
--- /dev/null
+++ b/drivers/mailbox/mailbox-dbx500.c
@@ -0,0 +1,648 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2012
+ *
+ * License Terms: GNU General Public License v2
+ * Author: Loic Pallardy <loic.pallardy@st.com> for ST-Ericsson
+ * DBX500 PRCM Mailbox driver
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/platform_data/mailbox-dbx500.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/irqdomain.h>
+
+#include "mailbox_internal.h"
+
+#define MAILBOX_LEGACY		0
+#define MAILBOX_UPAP		1
+
+enum {
+	MAILBOX_BLOCKING,
+	MAILBOX_ATOMIC,
+};
+
+/* CPU mailbox registers */
+#define PRCM_MBOX_CPU_VAL	0x0fc
+#define PRCM_MBOX_CPU_SET	0x100
+#define PRCM_MBOX_CPU_CLR	0x104
+
+#define PRCM_ARM_IT1_CLR	0x48C
+#define PRCM_ARM_IT1_VAL	0x494
+
+#define NUM_MB 8
+#define MBOX_BIT BIT
+#define ALL_MBOX_BITS (MBOX_BIT(NUM_MB) - 1)
+
+/* CPU mailbox shared memory */
+#define PRCM_MBOX_LEGACY_SIZE		0x220
+#define _PRCM_MBOX_HEADER		0x214 /* 16 bytes */
+#define PRCM_MBOX_HEADER_REQ_MB0	(_PRCM_MBOX_HEADER + 0x0)
+#define PRCM_MBOX_HEADER_REQ_MB1	(_PRCM_MBOX_HEADER + 0x1)
+#define PRCM_MBOX_HEADER_REQ_MB2	(_PRCM_MBOX_HEADER + 0x2)
+#define PRCM_MBOX_HEADER_REQ_MB3	(_PRCM_MBOX_HEADER + 0x3)
+#define PRCM_MBOX_HEADER_REQ_MB4	(_PRCM_MBOX_HEADER + 0x4)
+#define PRCM_MBOX_HEADER_REQ_MB5	(_PRCM_MBOX_HEADER + 0x5)
+#define PRCM_MBOX_HEADER_ACK_MB0	(_PRCM_MBOX_HEADER + 0x8)
+
+/* Req Mailboxes */
+#define PRCM_REQ_MB0			0x208 /* 12 bytes  */
+#define PRCM_REQ_MB1			0x1FC /* 12 bytes  */
+#define PRCM_REQ_MB2			0x1EC /* 16 bytes  */
+#define PRCM_REQ_MB3			0x78  /* 372 bytes  */
+#define PRCM_REQ_MB4			0x74  /* 4 bytes  */
+#define PRCM_REQ_MB5			0x70  /* 4 bytes  */
+#define PRCM_REQ_PASR			0x30 /* 4 bytes */
+
+/* Ack Mailboxes */
+#define PRCM_ACK_MB0			0x34 /* 52 bytes  */
+#define PRCM_ACK_MB1			0x30 /* 4 bytes */
+#define PRCM_ACK_MB2			0x2C /* 4 bytes */
+#define PRCM_ACK_MB3			0x28 /* 4 bytes */
+#define PRCM_ACK_MB4			0x24 /* 4 bytes */
+#define PRCM_ACK_MB5			0x20 /* 4 bytes */
+
+/* Ack Mailboxe sizes */
+#define PRCM_ACK_MB0_SIZE		0x24 /* 52 bytes  */
+#define PRCM_ACK_MB1_SIZE		0x4 /* 4 bytes */
+#define PRCM_ACK_MB2_SIZE		0x1 /* 1 bytes */
+#define PRCM_ACK_MB3_SIZE		0x2 /* 2 bytes */
+#define PRCM_ACK_MB4_SIZE		0x0 /* 0 bytes */
+#define PRCM_ACK_MB5_SIZE		0x4 /* 4 bytes */
+
+static void __iomem *mbox_base;
+static void __iomem *tcdm_mem_base;
+
+static u8 prcm_mbox_irq_mask; /* masked by default */
+static DEFINE_SPINLOCK(prcm_mbox_irqs_lock);
+
+struct dbx500_mbox_priv {
+	int			access_mode;
+	int			type;
+	int			header_size;
+	unsigned int		tx_header_offset;
+	unsigned int		rx_header_offset;
+	unsigned int		tx_offset;
+	unsigned int		rx_offset;
+	unsigned int		rx_size;
+	unsigned int		sw_irq;
+	bool			empty_flag;
+};
+
+static inline unsigned int mbox_read_reg(size_t ofs)
+{
+	return __raw_readl(mbox_base + ofs);
+}
+
+static inline void mbox_write_reg(u32 val, size_t ofs)
+{
+	__raw_writel(val, mbox_base + ofs);
+}
+
+/* Mailbox H/W preparations */
+static struct irq_chip dbx500_mbox_irq_chip;
+static struct irq_domain *dbx500_mbox_irq_domain;
+
+static int dbx500_mbox_startup(struct mailbox *mbox)
+{
+	/* Nothing to do */
+	return 0;
+}
+
+/* Mailbox IRQ handle functions */
+
+static void dbx500_mbox_enable_irq(struct mailbox *mbox, mailbox_irq_t irq)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&prcm_mbox_irqs_lock, flags);
+
+	prcm_mbox_irq_mask |= MBOX_BIT(mbox->id);
+
+	spin_unlock_irqrestore(&prcm_mbox_irqs_lock, flags);
+
+}
+
+static void dbx500_mbox_disable_irq(struct mailbox *mbox, mailbox_irq_t irq)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&prcm_mbox_irqs_lock, flags);
+
+	prcm_mbox_irq_mask &= ~MBOX_BIT(mbox->id);
+
+	spin_unlock_irqrestore(&prcm_mbox_irqs_lock, flags);
+
+}
+
+static void dbx500_mbox_ack_irq(struct mailbox *mbox, mailbox_irq_t irq)
+{
+	if (irq == IRQ_RX)
+		mbox_write_reg(MBOX_BIT(mbox->id), PRCM_ARM_IT1_CLR);
+}
+
+static int dbx500_mbox_is_irq(struct mailbox *mbox, mailbox_irq_t irq)
+{
+	struct dbx500_mbox_priv *priv = (struct dbx500_mbox_priv *)mbox->priv;
+
+	if (irq == IRQ_RX) {
+		if (mbox_read_reg(PRCM_ARM_IT1_VAL) & MBOX_BIT(mbox->id)) {
+			priv->empty_flag = true;
+			return 1;
+		} else {
+			return 0;
+		}
+	} else {
+		return 0;
+	}
+}
+
+/* message management */
+
+static int dbx500_mbox_is_ready(struct mailbox *mbox)
+{
+	return mbox_read_reg(PRCM_MBOX_CPU_VAL) & MBOX_BIT(mbox->id);
+}
+
+static int dbx500_mbox_write(struct mailbox *mbox,
+		struct mailbox_msg *msg)
+{
+	int j;
+	struct dbx500_mbox_priv *priv = (struct dbx500_mbox_priv *)mbox->priv;
+
+	if (msg->size && !msg->pdata)
+		return -EINVAL;
+
+	while (dbx500_mbox_is_ready(mbox))
+		cpu_relax();
+
+	/* write header */
+	if (priv->header_size)
+		writeb(msg->header, tcdm_mem_base + priv->tx_header_offset);
+
+	/* write data */
+	for (j = 0; j < msg->size; j++)
+		writeb(((unsigned char *)msg->pdata)[j],
+				tcdm_mem_base + priv->tx_offset + j);
+
+	/* send event */
+	mbox_write_reg(MBOX_BIT(mbox->id), PRCM_MBOX_CPU_SET);
+
+	return 0;
+}
+
+static void dbx500_mbox_read(struct mailbox *mbox, struct mailbox_msg *msg)
+{
+	struct dbx500_mbox_priv *priv = (struct dbx500_mbox_priv *)mbox->priv;
+
+	msg->header = readb(tcdm_mem_base + priv->rx_header_offset);
+	msg->pdata = (unsigned char *)(tcdm_mem_base + priv->rx_offset);
+
+	msg->size = priv->rx_size;
+	priv->empty_flag = false;
+}
+
+static int dbx500_mbox_empty(struct mailbox *mbox)
+{
+	struct dbx500_mbox_priv *priv = (struct dbx500_mbox_priv *)mbox->priv;
+	if (priv->empty_flag)
+		return 0;
+	else
+		return 1;
+}
+
+static int dbx500_mbox_poll_for_space(struct mailbox *mbox)
+{
+	return 0;
+}
+/*  interrupt management */
+
+/*  mask/unmask must be managed by SW */
+
+static void mbox_irq_mask(struct irq_data *d)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&prcm_mbox_irqs_lock, flags);
+
+	prcm_mbox_irq_mask &= ~MBOX_BIT(d->hwirq);
+
+	spin_unlock_irqrestore(&prcm_mbox_irqs_lock, flags);
+}
+
+static void mbox_irq_unmask(struct irq_data *d)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&prcm_mbox_irqs_lock, flags);
+
+	prcm_mbox_irq_mask |= MBOX_BIT(d->hwirq);
+
+	spin_unlock_irqrestore(&prcm_mbox_irqs_lock, flags);
+}
+
+static void mbox_irq_ack(struct irq_data *d)
+{
+	mbox_write_reg(MBOX_BIT(d->hwirq), PRCM_ARM_IT1_CLR);
+}
+
+static struct irq_chip dbx500_mbox_irq_chip = {
+	.name		= "dbx500_mbox",
+	.irq_disable	= mbox_irq_unmask,
+	.irq_ack	= mbox_irq_ack,
+	.irq_mask	= mbox_irq_mask,
+	.irq_unmask	= mbox_irq_unmask,
+};
+
+static int dbx500_mbox_irq_map(struct irq_domain *d, unsigned int irq,
+			       irq_hw_number_t hwirq)
+{
+	irq_set_chip_and_handler(irq, &dbx500_mbox_irq_chip,
+				handle_simple_irq);
+	set_irq_flags(irq, IRQF_VALID);
+
+	return 0;
+}
+
+static struct irq_domain_ops dbx500_mbox_irq_ops = {
+	.map    = dbx500_mbox_irq_map,
+	.xlate  = irq_domain_xlate_twocell,
+};
+
+static irqreturn_t dbx500_mbox_irq_handler(int irq, void *data)
+{
+	u32 bits;
+	u8 n;
+
+	bits = (mbox_read_reg(PRCM_ARM_IT1_VAL) & ALL_MBOX_BITS);
+	if (unlikely(!bits))
+		return IRQ_NONE;
+
+	bits &= prcm_mbox_irq_mask;
+
+	for (n = 0; bits; n++) {
+		if (bits & MBOX_BIT(n)) {
+			bits -= MBOX_BIT(n);
+			generic_handle_irq(
+				irq_find_mapping(dbx500_mbox_irq_domain, n));
+		}
+	}
+	return IRQ_HANDLED;
+}
+
+/* 5 mailboxes AP <--> PRCMU */
+static struct mailbox_ops dbx500_mbox_ops = {
+	.type		= MBOX_SHARED_MEM_TYPE,
+	.startup	= dbx500_mbox_startup,
+	.enable_irq	= dbx500_mbox_enable_irq,
+	.disable_irq	= dbx500_mbox_disable_irq,
+	.ack_irq	= dbx500_mbox_ack_irq,
+	.is_irq		= dbx500_mbox_is_irq,
+	.read		= dbx500_mbox_read,
+	.write		= dbx500_mbox_write,
+	.empty		= dbx500_mbox_empty,
+	.poll_for_space = dbx500_mbox_poll_for_space,
+};
+
+struct dbx500_mbox_priv mbox0_priv = {
+	.access_mode		= MAILBOX_ATOMIC,
+	.type			= MAILBOX_LEGACY,
+	.tx_header_offset	= PRCM_MBOX_HEADER_REQ_MB0,
+	.header_size		= 1,
+	.tx_offset		= PRCM_REQ_MB0,
+	.rx_header_offset	= PRCM_MBOX_HEADER_ACK_MB0,
+	.rx_offset		= PRCM_ACK_MB0,
+	.rx_size		= PRCM_ACK_MB0_SIZE,
+};
+
+struct mailbox mbox0_info = {
+	.name	= "mbox0",
+	.id	= 0,
+	.ops	= &dbx500_mbox_ops,
+	.priv	= &mbox0_priv,
+};
+
+struct dbx500_mbox_priv mbox1_priv = {
+	.access_mode		= MAILBOX_BLOCKING,
+	.type			= MAILBOX_LEGACY,
+	.tx_header_offset	= PRCM_MBOX_HEADER_REQ_MB1,
+	.header_size		= 1,
+	.tx_offset		= PRCM_REQ_MB1,
+	.rx_header_offset	= PRCM_MBOX_HEADER_REQ_MB1,
+	.rx_offset		= PRCM_ACK_MB1,
+	.rx_size		= PRCM_ACK_MB1_SIZE,
+};
+
+struct mailbox mbox1_info = {
+	.name	= "mbox1",
+	.id	= 1,
+	.ops	= &dbx500_mbox_ops,
+	.priv	= &mbox1_priv,
+};
+
+struct dbx500_mbox_priv mbox2_priv = {
+	.access_mode		= MAILBOX_BLOCKING,
+	.type			= MAILBOX_LEGACY,
+	.tx_header_offset	= PRCM_MBOX_HEADER_REQ_MB2,
+	.header_size		= 1,
+	.tx_offset		= PRCM_REQ_MB2,
+	.rx_header_offset	= PRCM_MBOX_HEADER_REQ_MB2,
+	.rx_offset		= PRCM_ACK_MB2,
+	.rx_size		= PRCM_ACK_MB2_SIZE,
+};
+
+struct mailbox mbox2_info = {
+	.name	= "mbox2",
+	.id	= 2,
+	.ops	= &dbx500_mbox_ops,
+	.priv	= &mbox2_priv,
+};
+
+struct dbx500_mbox_priv mbox3_priv = {
+	.access_mode		= MAILBOX_BLOCKING,
+	.type			= MAILBOX_LEGACY,
+	.tx_header_offset	= PRCM_MBOX_HEADER_REQ_MB3,
+	.header_size		= 1,
+	.tx_offset		= PRCM_REQ_MB3,
+	.rx_header_offset	= PRCM_MBOX_HEADER_REQ_MB3,
+	.rx_offset		= PRCM_ACK_MB3,
+	.rx_size		= PRCM_ACK_MB3_SIZE,
+};
+
+struct mailbox mbox3_info = {
+	.name	= "mbox3",
+	.id	= 3,
+	.ops	= &dbx500_mbox_ops,
+	.priv	= &mbox3_priv,
+};
+
+struct dbx500_mbox_priv mbox4_priv = {
+	.access_mode		= MAILBOX_BLOCKING,
+	.type			= MAILBOX_LEGACY,
+	.tx_header_offset	= PRCM_MBOX_HEADER_REQ_MB4,
+	.header_size		= 1,
+	.tx_offset		= PRCM_REQ_MB4,
+	.rx_header_offset	= PRCM_MBOX_HEADER_REQ_MB4,
+	.rx_offset		= PRCM_ACK_MB4,
+	.rx_size		= PRCM_ACK_MB4_SIZE,
+};
+
+struct mailbox mbox4_info = {
+	.name	= "mbox4",
+	.id	= 4,
+	.ops	= &dbx500_mbox_ops,
+	.priv	= &mbox4_priv,
+};
+
+struct dbx500_mbox_priv mbox5_priv = {
+	.access_mode		= MAILBOX_BLOCKING,
+	.type			= MAILBOX_LEGACY,
+	.tx_header_offset	= PRCM_MBOX_HEADER_REQ_MB5,
+	.header_size		= 1,
+	.tx_offset		= PRCM_REQ_MB5,
+	.rx_header_offset	= PRCM_MBOX_HEADER_REQ_MB5,
+	.rx_offset		= PRCM_ACK_MB5,
+	.rx_size		= PRCM_ACK_MB5_SIZE,
+};
+
+struct mailbox mbox5_info = {
+	.name	= "mbox5",
+	.id	= 5,
+	.ops	= &dbx500_mbox_ops,
+	.priv	= &mbox5_priv,
+};
+
+struct mailbox mbox6_info = {
+	.name	= "mbox6",
+	.id	= 6,
+	.ops	= &dbx500_mbox_ops,
+};
+
+struct mailbox mbox7_info = {
+	.name	= "mbox7",
+	.id	= 7,
+	.ops	= &dbx500_mbox_ops,
+};
+
+/* x540 mailbox definition */
+struct dbx500_mbox_priv mbox1_upap_priv = {
+	.access_mode	= MAILBOX_BLOCKING,
+	.type			= MAILBOX_UPAP,
+	.tx_header_offset	= 0,
+	.header_size	= 0,
+	.tx_offset	= 0,
+	.rx_offset	= 0, /* TODO to be replaced by dynamic detection */
+	.rx_size	= 0x40,
+};
+
+struct mailbox mbox1_upap_info = {
+	.name	= "mbox1_upap",
+	.id	= 1,
+	.ops	= &dbx500_mbox_ops,
+	.priv	= &mbox1_upap_priv,
+};
+
+struct mailbox *db8500_mboxes[] = { &mbox0_info, &mbox1_info, &mbox2_info,
+	&mbox3_info, &mbox4_info, &mbox5_info, &mbox6_info, &mbox7_info,
+	NULL };
+
+struct mailbox *dbx540_mboxes[] = { &mbox0_info, &mbox2_info,
+	&mbox3_info, &mbox4_info, &mbox5_info, &mbox6_info, &mbox7_info,
+	&mbox1_upap_info, NULL };
+
+static const struct of_device_id dbx500_mailbox_match[] = {
+	{ .compatible = "stericsson,db8500-mailbox",
+		.data = (void *)db8500_mboxes,
+	},
+	{ .compatible = "stericsson,db9540-mailbox",
+		.data = (void *)dbx540_mboxes,
+	},
+	{ /* sentinel */}
+};
+
+static int dbx500_mbox_probe(struct platform_device *pdev)
+{
+	const struct platform_device_id *platid = platform_get_device_id(pdev);
+	struct resource *mem;
+	int ret, i, irq;
+	u32 legacy_offset = 0;
+	u32 upap_offset = 0, upap_size = PRCM_MBOX_LEGACY_SIZE;
+	struct mailbox **list;
+	struct dbx500_plat_data *pdata = dev_get_platdata(&pdev->dev);
+	struct device_node *np = pdev->dev.of_node;
+	bool upap_used = false;
+
+	if (!pdata) {
+		if (np) {
+			if (of_property_read_u32(np, "legacy-offset",
+							&legacy_offset)) {
+				/* missing legacy-offset */
+				dev_err(&pdev->dev, "No legacy offset found\n");
+				return -ENODEV;
+			}
+			if (of_property_read_u32(np, "upap-offset",
+							&upap_offset)) {
+				dev_dbg(&pdev->dev, "No upap offset found\n");
+				upap_offset = -1;
+			}
+			list = (struct mailbox **)of_match_device(
+					dbx500_mailbox_match, &pdev->dev)->data;
+			if (!list) {
+				/* No mailbox configuration */
+				dev_err(&pdev->dev, "No configuration found\n");
+				return -ENODEV;
+			}
+		} else {
+			/* No mailbox configuration */
+			dev_err(&pdev->dev, "No configuration found\n");
+			return -ENODEV;
+		}
+	} else {
+		list = (struct mailbox **)platid->driver_data;
+		legacy_offset = pdata->legacy_offset;
+		upap_offset = pdata->upap_offset;
+	}
+
+	mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "prcm-reg");
+	mbox_base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
+	if (!mbox_base) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "prcmu-tcdm");
+	tcdm_mem_base = devm_ioremap(&pdev->dev, mem->start,
+							resource_size(mem));
+	if (!tcdm_mem_base) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	/* check mailbox offset values */
+	if (legacy_offset >= (resource_size(mem) - PRCM_MBOX_LEGACY_SIZE)) {
+		dev_err(&pdev->dev, "Incorrect legacy offset value\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	for (i = 0; list[i]; i++) {
+		struct mailbox *mbox = list[i];
+		struct dbx500_mbox_priv *priv =
+			(struct dbx500_mbox_priv *)mbox->priv;
+		if (!priv)
+			continue;
+		if (priv->type == MAILBOX_UPAP) {
+			upap_used = true;
+			upap_size += priv->rx_size;
+			break;
+		}
+	}
+
+	if (upap_used && (upap_offset >= (resource_size(mem) - upap_size))) {
+		dev_err(&pdev->dev, "Incorrect upap offset value\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	/* clean all mailboxes */
+	mbox_write_reg(ALL_MBOX_BITS, PRCM_ARM_IT1_CLR);
+	ret = request_irq(irq, dbx500_mbox_irq_handler,
+			IRQF_NO_SUSPEND, "db8500_mbox", NULL);
+	if (ret) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	dbx500_mbox_irq_domain = irq_domain_add_linear(
+		np, NUM_MB, &dbx500_mbox_irq_ops, NULL);
+
+	if (!dbx500_mbox_irq_domain) {
+		dev_err(&pdev->dev, "Failed to create irqdomain\n");
+		ret = -ENOSYS;
+		goto irq_free;
+	}
+
+	/*
+	 * Update mailbox shared memory buffer offset according to mailbox
+	 * type
+	 */
+	for (i = 0; list[i]; i++) {
+		struct mailbox *mbox = list[i];
+		struct dbx500_mbox_priv *priv =
+			(struct dbx500_mbox_priv *)mbox->priv;
+		if (!priv)
+			continue;
+		mbox->irq = irq_create_mapping(dbx500_mbox_irq_domain,
+								mbox->id);
+		if (priv->type == MAILBOX_LEGACY) {
+			priv->rx_offset += legacy_offset;
+			priv->rx_header_offset += legacy_offset;
+			priv->tx_offset += legacy_offset;
+			priv->tx_header_offset += legacy_offset;
+		} else if (priv->type == MAILBOX_UPAP) {
+			priv->tx_offset += upap_offset;
+			priv->rx_offset += upap_offset;
+		}
+	}
+
+	ret = mailbox_register(&pdev->dev, list);
+irq_free:
+	if (ret)
+		free_irq(irq, NULL);
+
+out:
+	return ret;
+}
+
+static int dbx500_mbox_remove(struct platform_device *pdev)
+{
+	mailbox_unregister();
+	iounmap(mbox_base);
+	return 0;
+}
+
+static const struct platform_device_id dbx500_mbox_id[] = {
+	{
+		.name = "db8500-mailbox",
+		.driver_data = (unsigned long) db8500_mboxes,
+	}, {
+		.name = "db9540-mailbox",
+		.driver_data = (unsigned long) dbx540_mboxes,
+	}, {
+		/* sentinel */
+	}
+};
+
+static struct platform_driver dbx500_mbox_driver = {
+	.probe = dbx500_mbox_probe,
+	.remove = dbx500_mbox_remove,
+	.driver = {
+		.name = "dbx500-mailbox",
+		.of_match_table = dbx500_mailbox_match,
+	},
+	.id_table = dbx500_mbox_id,
+};
+
+static int __init dbx500_mbox_init(void)
+{
+	return platform_driver_register(&dbx500_mbox_driver);
+}
+
+static void __exit dbx500_mbox_exit(void)
+{
+	platform_driver_unregister(&dbx500_mbox_driver);
+}
+
+postcore_initcall(dbx500_mbox_init);
+module_exit(dbx500_mbox_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("ST-Ericsson mailbox: dbx500 architecture specific functions");
+MODULE_AUTHOR("Loic Pallardy <loic.pallardy@st.com>");
+MODULE_ALIAS("platform:dbx500-mailbox");
diff --git a/drivers/mailbox/mailbox-omap1.c b/drivers/mailbox/mailbox-omap1.c
new file mode 100644
index 0000000..4441872
--- /dev/null
+++ b/drivers/mailbox/mailbox-omap1.c
@@ -0,0 +1,229 @@
+/*
+ * Mailbox reservation modules for OMAP1
+ *
+ * Copyright (C) 2006-2009 Nokia Corporation
+ * Written by: Hiroshi DOYU <Hiroshi.DOYU@nokia.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/module.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+
+#include "mailbox_internal.h"
+
+#define MAILBOX_ARM2DSP1		0x00
+#define MAILBOX_ARM2DSP1b		0x04
+#define MAILBOX_DSP2ARM1		0x08
+#define MAILBOX_DSP2ARM1b		0x0c
+#define MAILBOX_DSP2ARM2		0x10
+#define MAILBOX_DSP2ARM2b		0x14
+#define MAILBOX_ARM2DSP1_Flag		0x18
+#define MAILBOX_DSP2ARM1_Flag		0x1c
+#define MAILBOX_DSP2ARM2_Flag		0x20
+
+static void __iomem *mbox_base;
+
+struct omap_mbox1_fifo {
+	unsigned long cmd;
+	unsigned long data;
+	unsigned long flag;
+};
+
+struct omap_mbox1_priv {
+	struct omap_mbox1_fifo tx_fifo;
+	struct omap_mbox1_fifo rx_fifo;
+	u32 data;
+	bool empty_flag;
+};
+
+static inline int mbox_read_reg(size_t ofs)
+{
+	return __raw_readw(mbox_base + ofs);
+}
+
+static inline void mbox_write_reg(u32 val, size_t ofs)
+{
+	__raw_writew(val, mbox_base + ofs);
+}
+
+/* msg */
+static void omap1_mbox_fifo_read(struct mailbox *mbox, struct mailbox_msg *msg)
+{
+	struct omap_mbox1_priv *priv = mbox->priv;
+	struct omap_mbox1_fifo *fifo = &priv->rx_fifo;
+
+	priv->data = mbox_read_reg(fifo->data);
+	priv->data |= ((u32) mbox_read_reg(fifo->cmd)) << 16;
+	MAILBOX_FILL_MSG((*msg), 0, priv->data, 0);
+	priv->empty_flag = false;
+}
+
+static int
+omap1_mbox_fifo_write(struct mailbox *mbox, struct mailbox_msg *msg)
+{
+	struct omap_mbox1_fifo *fifo =
+		&((struct omap_mbox1_priv *)mbox->priv)->tx_fifo;
+	u32 data = (u32)msg->pdata;
+
+	mbox_write_reg(data & 0xffff, fifo->data);
+	mbox_write_reg(data >> 16, fifo->cmd);
+
+	return 0;
+}
+
+static int omap1_mbox_fifo_empty(struct mailbox *mbox)
+{
+	struct omap_mbox1_priv *priv = (struct omap_mbox1_priv *)mbox->priv;
+	if (priv->empty_flag)
+		return 0;
+	else
+		return 1;
+}
+
+static int omap1_mbox_fifo_full(struct mailbox *mbox)
+{
+	struct omap_mbox1_fifo *fifo =
+		&((struct omap_mbox1_priv *)mbox->priv)->rx_fifo;
+
+	return mbox_read_reg(fifo->flag);
+}
+
+static int omap1_mbox_poll_for_space(struct mailbox *mbox)
+{
+	int ret = 0, i = 1000;
+
+	while (omap1_mbox_fifo_full(mbox)) {
+		if (--i == 0)
+			return -1;
+		udelay(1);
+	}
+	return ret;
+}
+
+/* irq */
+static void
+omap1_mbox_enable_irq(struct mailbox *mbox, mailbox_type_t irq)
+{
+	if (irq == IRQ_RX)
+		enable_irq(mbox->irq);
+}
+
+static void
+omap1_mbox_disable_irq(struct mailbox *mbox, mailbox_type_t irq)
+{
+	if (irq == IRQ_RX)
+		disable_irq(mbox->irq);
+}
+
+static int
+omap1_mbox_is_irq(struct mailbox *mbox, mailbox_type_t irq)
+{
+	struct omap_mbox1_priv *priv = (struct omap_mbox1_priv *)mbox->priv;
+
+	if (irq == IRQ_TX)
+		return 0;
+	if (irq == IRQ_RX)
+		priv->empty_flag = true;
+
+	return 1;
+}
+
+static struct mailbox_ops omap1_mbox_ops = {
+	.type		= MBOX_HW_FIFO1_TYPE,
+	.read		= omap1_mbox_fifo_read,
+	.write		= omap1_mbox_fifo_write,
+	.empty		= omap1_mbox_fifo_empty,
+	.poll_for_space	= omap1_mbox_poll_for_space,
+	.enable_irq	= omap1_mbox_enable_irq,
+	.disable_irq	= omap1_mbox_disable_irq,
+	.is_irq		= omap1_mbox_is_irq,
+};
+
+/* FIXME: the following struct should be created automatically by the user id */
+
+/* DSP */
+static struct omap_mbox1_priv omap1_mbox_dsp_priv = {
+	.tx_fifo = {
+		.cmd	= MAILBOX_ARM2DSP1b,
+		.data	= MAILBOX_ARM2DSP1,
+		.flag	= MAILBOX_ARM2DSP1_Flag,
+	},
+	.rx_fifo = {
+		.cmd	= MAILBOX_DSP2ARM1b,
+		.data	= MAILBOX_DSP2ARM1,
+		.flag	= MAILBOX_DSP2ARM1_Flag,
+	},
+};
+
+static struct mailbox mbox_dsp_info = {
+	.name	= "dsp",
+	.ops	= &omap1_mbox_ops,
+	.priv	= &omap1_mbox_dsp_priv,
+};
+
+static struct mailbox *omap1_mboxes[] = { &mbox_dsp_info, NULL };
+
+static int omap1_mbox_probe(struct platform_device *pdev)
+{
+	struct resource *mem;
+	int ret;
+	struct mailbox **list;
+
+	list = omap1_mboxes;
+	list[0]->irq = platform_get_irq_byname(pdev, "dsp");
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem)
+		return -ENOMEM;
+
+	mbox_base = ioremap(mem->start, resource_size(mem));
+	if (!mbox_base)
+		return -ENOMEM;
+
+	ret = mailbox_register(&pdev->dev, list);
+	if (ret) {
+		iounmap(mbox_base);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int omap1_mbox_remove(struct platform_device *pdev)
+{
+	mailbox_unregister();
+	iounmap(mbox_base);
+	return 0;
+}
+
+static struct platform_driver omap1_mbox_driver = {
+	.probe	= omap1_mbox_probe,
+	.remove	= omap1_mbox_remove,
+	.driver	= {
+		.name	= "omap-mailbox",
+	},
+};
+
+static int __init omap1_mbox_init(void)
+{
+	return platform_driver_register(&omap1_mbox_driver);
+}
+
+static void __exit omap1_mbox_exit(void)
+{
+	platform_driver_unregister(&omap1_mbox_driver);
+}
+
+module_init(omap1_mbox_init);
+module_exit(omap1_mbox_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("omap mailbox: omap1 architecture specific functions");
+MODULE_AUTHOR("Hiroshi DOYU <Hiroshi.DOYU@nokia.com>");
+MODULE_ALIAS("platform:omap1-mailbox");
diff --git a/drivers/mailbox/mailbox-omap2.c b/drivers/mailbox/mailbox-omap2.c
new file mode 100644
index 0000000..eed5a3d
--- /dev/null
+++ b/drivers/mailbox/mailbox-omap2.c
@@ -0,0 +1,370 @@
+/*
+ * Mailbox reservation modules for OMAP2/3
+ *
+ * Copyright (C) 2006-2009 Nokia Corporation
+ * Written by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
+ *        and  Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/pm_runtime.h>
+#include <linux/platform_data/mailbox-omap.h>
+
+#include "mailbox_internal.h"
+
+#define MAILBOX_REVISION		0x000
+#define MAILBOX_MESSAGE(m)		(0x040 + 4 * (m))
+#define MAILBOX_FIFOSTATUS(m)		(0x080 + 4 * (m))
+#define MAILBOX_MSGSTATUS(m)		(0x0c0 + 4 * (m))
+#define MAILBOX_IRQSTATUS(u)		(0x100 + 8 * (u))
+#define MAILBOX_IRQENABLE(u)		(0x104 + 8 * (u))
+
+#define OMAP4_MAILBOX_IRQSTATUS(u)	(0x104 + 0x10 * (u))
+#define OMAP4_MAILBOX_IRQENABLE(u)	(0x108 + 0x10 * (u))
+#define OMAP4_MAILBOX_IRQENABLE_CLR(u)	(0x10c + 0x10 * (u))
+
+#define MAILBOX_IRQ_NEWMSG(m)		(1 << (2 * (m)))
+#define MAILBOX_IRQ_NOTFULL(m)		(1 << (2 * (m) + 1))
+
+#define MBOX_REG_SIZE			0x120
+
+#define OMAP4_MBOX_REG_SIZE		0x130
+
+#define MBOX_NR_REGS			(MBOX_REG_SIZE / sizeof(u32))
+#define OMAP4_MBOX_NR_REGS		(OMAP4_MBOX_REG_SIZE / sizeof(u32))
+
+static void __iomem *mbox_base;
+
+struct omap_mbox2_fifo {
+	unsigned long msg;
+	unsigned long fifo_stat;
+	unsigned long msg_stat;
+};
+
+struct omap_mbox2_priv {
+	struct omap_mbox2_fifo tx_fifo;
+	struct omap_mbox2_fifo rx_fifo;
+	unsigned long irqenable;
+	unsigned long irqstatus;
+	u32 newmsg_bit;
+	u32 notfull_bit;
+	u32 ctx[OMAP4_MBOX_NR_REGS];
+	unsigned long irqdisable;
+	u32 intr_type;
+	u32 data;
+};
+
+static void omap2_mbox_enable_irq(struct mailbox *mbox,
+		mailbox_type_t irq);
+
+static inline unsigned int mbox_read_reg(size_t ofs)
+{
+	return __raw_readl(mbox_base + ofs);
+}
+
+static inline void mbox_write_reg(u32 val, size_t ofs)
+{
+	__raw_writel(val, mbox_base + ofs);
+}
+
+/* Mailbox H/W preparations */
+static int omap2_mbox_startup(struct mailbox *mbox)
+{
+	u32 l;
+
+	pm_runtime_enable(mbox->dev->parent);
+	pm_runtime_get_sync(mbox->dev->parent);
+
+	l = mbox_read_reg(MAILBOX_REVISION);
+	pr_debug("omap mailbox rev %d.%d\n", (l & 0xf0) >> 4, (l & 0x0f));
+
+	return 0;
+}
+
+static void omap2_mbox_shutdown(struct mailbox *mbox)
+{
+	pm_runtime_put_sync(mbox->dev->parent);
+	pm_runtime_disable(mbox->dev->parent);
+}
+
+/* Mailbox FIFO handle functions */
+static void omap2_mbox_fifo_read(struct mailbox *mbox, struct mailbox_msg *msg)
+{
+	struct omap_mbox2_priv *priv = mbox->priv;
+	struct omap_mbox2_fifo *fifo = &priv->rx_fifo;
+	priv->data = mbox_read_reg(fifo->msg);
+	MAILBOX_FILL_MSG((*msg), 0, priv->data, 0);
+}
+
+static int omap2_mbox_fifo_write(struct mailbox *mbox, struct mailbox_msg *msg)
+{
+	struct omap_mbox2_fifo *fifo =
+		&((struct omap_mbox2_priv *)mbox->priv)->tx_fifo;
+
+	mbox_write_reg((u32)msg->pdata, fifo->msg);
+
+	return 0;
+}
+
+static int omap2_mbox_fifo_empty(struct mailbox *mbox)
+{
+	struct omap_mbox2_fifo *fifo =
+		&((struct omap_mbox2_priv *)mbox->priv)->rx_fifo;
+	return (mbox_read_reg(fifo->msg_stat) == 0);
+}
+
+static int omap2_mbox_fifo_full(struct mailbox *mbox)
+{
+	struct omap_mbox2_fifo *fifo =
+		&((struct omap_mbox2_priv *)mbox->priv)->tx_fifo;
+	return mbox_read_reg(fifo->fifo_stat);
+}
+
+static int omap2_mbox_poll_for_space(struct mailbox *mbox)
+{
+	if (omap2_mbox_fifo_full(mbox))
+		return -1;
+
+	return 0;
+}
+
+/* Mailbox IRQ handle functions */
+static void omap2_mbox_enable_irq(struct mailbox *mbox,
+		mailbox_type_t irq)
+{
+	struct omap_mbox2_priv *p = mbox->priv;
+	u32 l, bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
+
+	l = mbox_read_reg(p->irqenable);
+	l |= bit;
+	mbox_write_reg(l, p->irqenable);
+}
+
+static void omap2_mbox_disable_irq(struct mailbox *mbox,
+		mailbox_type_t irq)
+{
+	struct omap_mbox2_priv *p = mbox->priv;
+	u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
+
+	if (!p->intr_type)
+		bit = mbox_read_reg(p->irqdisable) & ~bit;
+
+	mbox_write_reg(bit, p->irqdisable);
+}
+
+static void omap2_mbox_ack_irq(struct mailbox *mbox,
+		mailbox_type_t irq)
+{
+	struct omap_mbox2_priv *p = mbox->priv;
+	u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
+
+	mbox_write_reg(bit, p->irqstatus);
+
+	/* Flush posted write for irq status to avoid spurious interrupts */
+	mbox_read_reg(p->irqstatus);
+}
+
+static int omap2_mbox_is_irq(struct mailbox *mbox,
+		mailbox_type_t irq)
+{
+	struct omap_mbox2_priv *p = mbox->priv;
+	u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
+	u32 enable = mbox_read_reg(p->irqenable);
+	u32 status = mbox_read_reg(p->irqstatus);
+
+	return (int)(enable & status & bit);
+}
+
+static void omap2_mbox_save_ctx(struct mailbox *mbox)
+{
+	int i;
+	struct omap_mbox2_priv *p = mbox->priv;
+	int nr_regs;
+
+	if (p->intr_type)
+		nr_regs = OMAP4_MBOX_NR_REGS;
+	else
+		nr_regs = MBOX_NR_REGS;
+	for (i = 0; i < nr_regs; i++) {
+		p->ctx[i] = mbox_read_reg(i * sizeof(u32));
+
+		dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__,
+				i, p->ctx[i]);
+	}
+}
+
+static void omap2_mbox_restore_ctx(struct mailbox *mbox)
+{
+	int i;
+	struct omap_mbox2_priv *p = mbox->priv;
+	int nr_regs;
+
+	if (p->intr_type)
+		nr_regs = OMAP4_MBOX_NR_REGS;
+	else
+		nr_regs = MBOX_NR_REGS;
+	for (i = 0; i < nr_regs; i++) {
+		mbox_write_reg(p->ctx[i], i * sizeof(u32));
+
+		dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__,
+				i, p->ctx[i]);
+	}
+}
+
+static struct mailbox_ops omap2_mbox_ops = {
+	.type		= MBOX_HW_FIFO2_TYPE,
+	.startup	= omap2_mbox_startup,
+	.shutdown	= omap2_mbox_shutdown,
+	.read		= omap2_mbox_fifo_read,
+	.write		= omap2_mbox_fifo_write,
+	.empty		= omap2_mbox_fifo_empty,
+	.poll_for_space	= omap2_mbox_poll_for_space,
+	.enable_irq	= omap2_mbox_enable_irq,
+	.disable_irq	= omap2_mbox_disable_irq,
+	.ack_irq	= omap2_mbox_ack_irq,
+	.is_irq		= omap2_mbox_is_irq,
+	.save_ctx	= omap2_mbox_save_ctx,
+	.restore_ctx	= omap2_mbox_restore_ctx,
+};
+
+static int omap2_mbox_probe(struct platform_device *pdev)
+{
+	struct resource *mem;
+	int ret;
+	struct mailbox **list, *mbox, *mboxblk;
+	struct omap_mbox2_priv *priv, *privblk;
+	struct omap_mbox_pdata *pdata = pdev->dev.platform_data;
+	struct omap_mbox_dev_info *info;
+	int i;
+
+	if (!pdata || !pdata->info_cnt || !pdata->info) {
+		pr_err("%s: platform not supported\n", __func__);
+		return -ENODEV;
+	}
+
+	/* allocate one extra for marking end of list */
+	list = kzalloc((pdata->info_cnt + 1) * sizeof(*list), GFP_KERNEL);
+	if (!list)
+		return -ENOMEM;
+
+	mboxblk = mbox = kzalloc(pdata->info_cnt * sizeof(*mbox), GFP_KERNEL);
+	if (!mboxblk) {
+		ret = -ENOMEM;
+		goto free_list;
+	}
+
+	privblk = priv = kzalloc(pdata->info_cnt * sizeof(*priv), GFP_KERNEL);
+	if (!privblk) {
+		ret = -ENOMEM;
+		goto free_mboxblk;
+	}
+
+	info = pdata->info;
+	for (i = 0; i < pdata->info_cnt; i++, info++, priv++) {
+		priv->tx_fifo.msg = MAILBOX_MESSAGE(info->tx_id);
+		priv->tx_fifo.fifo_stat = MAILBOX_FIFOSTATUS(info->tx_id);
+		priv->rx_fifo.msg =  MAILBOX_MESSAGE(info->rx_id);
+		priv->rx_fifo.msg_stat =  MAILBOX_MSGSTATUS(info->rx_id);
+		priv->notfull_bit = MAILBOX_IRQ_NOTFULL(info->tx_id);
+		priv->newmsg_bit = MAILBOX_IRQ_NEWMSG(info->rx_id);
+		if (pdata->intr_type) {
+			priv->irqenable = OMAP4_MAILBOX_IRQENABLE(info->usr_id);
+			priv->irqstatus = OMAP4_MAILBOX_IRQSTATUS(info->usr_id);
+			priv->irqdisable =
+				OMAP4_MAILBOX_IRQENABLE_CLR(info->usr_id);
+		} else {
+			priv->irqenable = MAILBOX_IRQENABLE(info->usr_id);
+			priv->irqstatus = MAILBOX_IRQSTATUS(info->usr_id);
+			priv->irqdisable = MAILBOX_IRQENABLE(info->usr_id);
+		}
+		priv->intr_type = pdata->intr_type;
+
+		mbox->priv = priv;
+		mbox->name = info->name;
+		mbox->ops = &omap2_mbox_ops;
+		mbox->irq = platform_get_irq(pdev, info->irq_id);
+		list[i] = mbox++;
+	}
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem) {
+		ret = -ENOMEM;
+		goto free_privblk;
+	}
+
+	mbox_base = ioremap(mem->start, resource_size(mem));
+	if (!mbox_base) {
+		ret = -ENOMEM;
+		goto free_privblk;
+	}
+
+	ret = mailbox_register(&pdev->dev, list);
+	if (ret)
+		goto unmap_mbox;
+	platform_set_drvdata(pdev, list);
+
+	return 0;
+
+unmap_mbox:
+	iounmap(mbox_base);
+free_privblk:
+	kfree(privblk);
+free_mboxblk:
+	kfree(mboxblk);
+free_list:
+	kfree(list);
+	return ret;
+}
+
+static int omap2_mbox_remove(struct platform_device *pdev)
+{
+	struct omap_mbox2_priv *privblk;
+	struct mailbox **list = platform_get_drvdata(pdev);
+	struct mailbox *mboxblk = list[0];
+
+	privblk = mboxblk->priv;
+	mailbox_unregister();
+	iounmap(mbox_base);
+	kfree(privblk);
+	kfree(mboxblk);
+	kfree(list);
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+static struct platform_driver omap2_mbox_driver = {
+	.probe	= omap2_mbox_probe,
+	.remove	= omap2_mbox_remove,
+	.driver	= {
+		.name = "omap-mailbox",
+	},
+};
+
+static int __init omap2_mbox_init(void)
+{
+	return platform_driver_register(&omap2_mbox_driver);
+}
+
+static void __exit omap2_mbox_exit(void)
+{
+	platform_driver_unregister(&omap2_mbox_driver);
+}
+
+module_init(omap2_mbox_init);
+module_exit(omap2_mbox_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("omap mailbox: omap2/3/4 architecture specific functions");
+MODULE_AUTHOR("Hiroshi DOYU <Hiroshi.DOYU@nokia.com>");
+MODULE_AUTHOR("Paul Mundt");
+MODULE_ALIAS("platform:omap2-mailbox");
diff --git a/drivers/mailbox/mailbox.c b/drivers/mailbox/mailbox.c
new file mode 100644
index 0000000..78e52c0
--- /dev/null
+++ b/drivers/mailbox/mailbox.c
@@ -0,0 +1,552 @@
+/*
+ * Mailbox framework
+ *
+ * Copyright (C) 2006-2009 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
+ * Author: Loic Pallardy <loic.pallardy@st.com> for ST-Ericsson
+ *
+ * This program is free software; you can 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/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/kfifo.h>
+#include <linux/err.h>
+#include <linux/notifier.h>
+#include <linux/module.h>
+
+#include "mailbox_internal.h"
+
+static struct mailbox **mboxes;
+
+static int mbox_configured;
+static DEFINE_MUTEX(mbox_configured_lock);
+
+static unsigned int mbox_kfifo_size = CONFIG_MBOX_KFIFO_SIZE;
+module_param(mbox_kfifo_size, uint, S_IRUGO);
+MODULE_PARM_DESC(mbox_kfifo_size, "Size of mailbox kfifo (bytes)");
+
+/* Mailbox FIFO handle functions */
+static inline void mbox_read(struct mailbox *mbox, struct mailbox_msg *msg)
+{
+	mbox->ops->read(mbox, msg);
+}
+static inline int mbox_write(struct mailbox *mbox, struct mailbox_msg *msg)
+{
+	return mbox->ops->write(mbox, msg);
+}
+static inline int mbox_empty(struct mailbox *mbox)
+{
+	return mbox->ops->empty(mbox);
+}
+
+/* Mailbox IRQ handle functions */
+static inline void ack_mbox_irq(struct mailbox *mbox, mailbox_irq_t irq)
+{
+	if (mbox->ops->ack_irq)
+		mbox->ops->ack_irq(mbox, irq);
+}
+static inline int is_mbox_irq(struct mailbox *mbox, mailbox_irq_t irq)
+{
+	return mbox->ops->is_irq(mbox, irq);
+}
+
+/*
+ * message sender
+ */
+static int __mbox_poll_for_space(struct mailbox *mbox)
+{
+	return mbox->ops->poll_for_space(mbox);
+}
+
+int mailbox_msg_send(struct mailbox *mbox, struct mailbox_msg *msg)
+{
+	struct mailbox_queue *mq = mbox->txq;
+	int ret = 0, len;
+
+	mutex_lock(&mq->mlock);
+
+	if (kfifo_avail(&mq->fifo) < (sizeof(*msg) + msg->size)) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	if (kfifo_is_empty(&mq->fifo) && !__mbox_poll_for_space(mbox)) {
+		ret = mbox_write(mbox, msg);
+		goto out;
+	}
+
+	len = kfifo_in(&mq->fifo, (unsigned char *)msg, sizeof(*msg));
+	WARN_ON(len != sizeof(*msg));
+
+	if (msg->size && msg->pdata) {
+		len = kfifo_in(&mq->fifo, (unsigned char *)msg->pdata,
+								msg->size);
+		WARN_ON(len != msg->size);
+	}
+
+	tasklet_schedule(&mbox->txq->tasklet);
+
+out:
+	mutex_unlock(&mq->mlock);
+	return ret;
+}
+EXPORT_SYMBOL(mailbox_msg_send);
+
+#define TRANSFER_TIMEOUT 30000 /* Becomes ~3s timeout */
+
+static struct mailbox_msg no_irq_msg_res;
+
+struct mailbox_msg *mailbox_msg_send_receive_no_irq(struct mailbox *mbox,
+		struct mailbox_msg *msg)
+{
+	int ret = 0;
+	int count = 0;
+
+	BUG_ON(!irqs_disabled());
+
+	if (likely(mbox->ops->write && mbox->ops->read)) {
+		if (__mbox_poll_for_space(mbox)) {
+			ret = -EBUSY;
+			goto out;
+		}
+		mbox->ops->write(mbox, msg);
+		while (!is_mbox_irq(mbox, IRQ_RX)) {
+			udelay(100);
+			cpu_relax();
+			count++;
+			if (count > TRANSFER_TIMEOUT) {
+				pr_err("%s: Error: transfer timed out\n",
+						__func__);
+				ret = -EINVAL;
+				goto out;
+			}
+		}
+		mbox->ops->read(mbox, &no_irq_msg_res);
+		ack_mbox_irq(mbox, IRQ_RX);
+	} else {
+		ret = -EINVAL;
+	}
+
+out:
+	BUG_ON(ret < 0);
+
+	return &no_irq_msg_res;
+}
+EXPORT_SYMBOL(mailbox_msg_send_receive_no_irq);
+
+int mailbox_msg_send_no_irq(struct mailbox *mbox,
+		struct mailbox_msg *msg)
+{
+	int ret = 0;
+
+	BUG_ON(!irqs_disabled());
+
+	if (likely(mbox->ops->write)) {
+		if (__mbox_poll_for_space(mbox)) {
+			ret = -EBUSY;
+			goto out;
+		}
+		mbox->ops->write(mbox, msg);
+	} else {
+		ret = -EINVAL;
+	}
+
+out:
+	WARN_ON(ret < 0);
+
+	return ret;
+}
+EXPORT_SYMBOL(mailbox_msg_send_no_irq);
+
+void mailbox_save_ctx(struct mailbox *mbox)
+{
+	if (!mbox->ops->save_ctx) {
+		dev_err(mbox->dev, "%s:\tno save\n", __func__);
+		return;
+	}
+
+	mbox->ops->save_ctx(mbox);
+}
+EXPORT_SYMBOL(mailbox_save_ctx);
+
+void mailbox_restore_ctx(struct mailbox *mbox)
+{
+	if (!mbox->ops->restore_ctx) {
+		dev_err(mbox->dev, "%s:\tno restore\n", __func__);
+		return;
+	}
+
+	mbox->ops->restore_ctx(mbox);
+}
+EXPORT_SYMBOL(mailbox_restore_ctx);
+
+void mailbox_enable_irq(struct mailbox *mbox, mailbox_irq_t irq)
+{
+	mbox->ops->enable_irq(mbox, irq);
+}
+EXPORT_SYMBOL(mailbox_enable_irq);
+
+void mailbox_disable_irq(struct mailbox *mbox, mailbox_irq_t irq)
+{
+	mbox->ops->disable_irq(mbox, irq);
+}
+EXPORT_SYMBOL(mailbox_disable_irq);
+
+static void mbox_tx_tasklet(unsigned long tx_data)
+{
+	struct mailbox *mbox = (struct mailbox *)tx_data;
+	struct mailbox_queue *mq = mbox->txq;
+	struct mailbox_msg msg;
+	int ret;
+	unsigned char tx_data_buf[CONFIG_MBOX_DATA_SIZE];
+
+	while (kfifo_len(&mq->fifo)) {
+		if (__mbox_poll_for_space(mbox)) {
+			mailbox_enable_irq(mbox, IRQ_TX);
+			break;
+		}
+
+		ret = kfifo_out(&mq->fifo, (unsigned char *)&msg, sizeof(msg));
+		WARN_ON(ret != sizeof(msg));
+
+		if (msg.size) {
+			ret = kfifo_out(&mq->fifo, tx_data_buf,
+							sizeof(msg.size));
+			WARN_ON(ret != msg.size);
+			msg.pdata = tx_data_buf;
+		}
+
+		ret = mbox_write(mbox, &msg);
+		WARN_ON(ret);
+	}
+}
+
+/*
+ * Message receiver(workqueue)
+ */
+static unsigned char rx_work_data[CONFIG_MBOX_DATA_SIZE];
+
+static void mbox_rx_work(struct work_struct *work)
+{
+	struct mailbox_queue *mq =
+		container_of(work, struct mailbox_queue, work);
+	int len;
+	struct mailbox *mbox = mq->mbox;
+	struct mailbox_msg msg;
+
+	while (kfifo_len(&mq->fifo) >= sizeof(msg)) {
+		len = kfifo_out(&mq->fifo, (unsigned char *)&msg, sizeof(msg));
+		WARN_ON(len != sizeof(msg));
+
+		if (msg.size) {
+			len = kfifo_out(&mq->fifo, rx_work_data, msg.size);
+			WARN_ON(len != msg.size);
+			msg.pdata = rx_work_data;
+		}
+
+		blocking_notifier_call_chain(&mbox->notifier, len,
+								(void *)&msg);
+		spin_lock_irq(&mq->lock);
+		if (mq->full) {
+			mq->full = false;
+			mailbox_enable_irq(mbox, IRQ_RX);
+		}
+		spin_unlock_irq(&mq->lock);
+	}
+}
+
+/*
+ * Mailbox interrupt handler
+ */
+static void __mbox_tx_interrupt(struct mailbox *mbox)
+{
+	mailbox_disable_irq(mbox, IRQ_TX);
+	ack_mbox_irq(mbox, IRQ_TX);
+	tasklet_schedule(&mbox->txq->tasklet);
+}
+
+static void __mbox_rx_interrupt(struct mailbox *mbox)
+{
+	struct mailbox_queue *mq = mbox->rxq;
+	struct mailbox_msg msg;
+	int len;
+
+	while (!mbox_empty(mbox)) {
+		if (unlikely(kfifo_avail(&mq->fifo) <
+				(sizeof(msg) + CONFIG_MBOX_DATA_SIZE))) {
+			mailbox_disable_irq(mbox, IRQ_RX);
+			mq->full = true;
+			goto nomem;
+		}
+
+		mbox_read(mbox, &msg);
+
+		len = kfifo_in(&mq->fifo, (unsigned char *)&msg, sizeof(msg));
+		WARN_ON(len != sizeof(msg));
+
+		if (msg.pdata && msg.size) {
+			len = kfifo_in(&mq->fifo, (unsigned char *)msg.pdata,
+					msg.size);
+			WARN_ON(len != msg.size);
+		}
+	}
+
+	/* no more messages in the fifo. clear IRQ source. */
+	ack_mbox_irq(mbox, IRQ_RX);
+nomem:
+	schedule_work(&mbox->rxq->work);
+}
+
+static irqreturn_t mbox_interrupt(int irq, void *p)
+{
+	struct mailbox *mbox = p;
+
+	if (is_mbox_irq(mbox, IRQ_TX))
+		__mbox_tx_interrupt(mbox);
+
+	if (is_mbox_irq(mbox, IRQ_RX))
+		__mbox_rx_interrupt(mbox);
+
+	return IRQ_HANDLED;
+}
+
+static struct mailbox_queue *mbox_queue_alloc(struct mailbox *mbox,
+		void (*work) (struct work_struct *),
+		void (*tasklet)(unsigned long))
+{
+	struct mailbox_queue *mq;
+
+	mq = kzalloc(sizeof(struct mailbox_queue), GFP_KERNEL);
+	if (!mq)
+		return NULL;
+
+	spin_lock_init(&mq->lock);
+	mutex_init(&mq->mlock);
+
+	if (kfifo_alloc(&mq->fifo, mbox_kfifo_size, GFP_KERNEL))
+		goto error;
+
+	if (work)
+		INIT_WORK(&mq->work, work);
+
+	if (tasklet)
+		tasklet_init(&mq->tasklet, tasklet, (unsigned long)mbox);
+	return mq;
+error:
+	kfree(mq);
+	return NULL;
+}
+
+static void mbox_queue_free(struct mailbox_queue *q)
+{
+	kfifo_free(&q->fifo);
+	kfree(q);
+}
+
+static int mailbox_startup(struct mailbox *mbox)
+{
+	int ret = 0;
+	struct mailbox_queue *mq;
+
+	mutex_lock(&mbox_configured_lock);
+	if (!mbox_configured++) {
+		if (likely(mbox->ops->startup)) {
+			ret = mbox->ops->startup(mbox);
+			if (unlikely(ret))
+				goto fail_startup;
+		} else
+			goto fail_startup;
+	}
+
+	if (!mbox->use_count++) {
+		mq = mbox_queue_alloc(mbox, NULL, mbox_tx_tasklet);
+		if (!mq) {
+			ret = -ENOMEM;
+			goto fail_alloc_txq;
+		}
+		mbox->txq = mq;
+
+		mq = mbox_queue_alloc(mbox, mbox_rx_work, NULL);
+		if (!mq) {
+			ret = -ENOMEM;
+			goto fail_alloc_rxq;
+		}
+		mbox->rxq = mq;
+		mq->mbox = mbox;
+		ret = request_irq(mbox->irq, mbox_interrupt,
+				IRQF_SHARED | IRQF_NO_SUSPEND,
+				mbox->name, mbox);
+		if (unlikely(ret)) {
+			pr_err("failed to register mailbox interrupt:%d\n",
+					ret);
+			goto fail_request_irq;
+		}
+
+		mailbox_enable_irq(mbox, IRQ_RX);
+	}
+	mutex_unlock(&mbox_configured_lock);
+	return 0;
+
+fail_request_irq:
+	mbox_queue_free(mbox->rxq);
+fail_alloc_rxq:
+	mbox_queue_free(mbox->txq);
+fail_alloc_txq:
+	if (mbox->ops->shutdown)
+		mbox->ops->shutdown(mbox);
+	mbox->use_count--;
+fail_startup:
+	mbox_configured--;
+	mutex_unlock(&mbox_configured_lock);
+	return ret;
+}
+
+static void mailbox_fini(struct mailbox *mbox)
+{
+	mutex_lock(&mbox_configured_lock);
+
+	if (!--mbox->use_count) {
+		mailbox_disable_irq(mbox, IRQ_RX);
+		free_irq(mbox->irq, mbox);
+		tasklet_kill(&mbox->txq->tasklet);
+		flush_work(&mbox->rxq->work);
+		mbox_queue_free(mbox->txq);
+		mbox_queue_free(mbox->rxq);
+	}
+
+	if (likely(mbox->ops->shutdown)) {
+		if (!--mbox_configured)
+			mbox->ops->shutdown(mbox);
+	}
+
+	mutex_unlock(&mbox_configured_lock);
+}
+
+struct mailbox *mailbox_get(const char *name, struct notifier_block *nb)
+{
+	struct mailbox *_mbox, *mbox = NULL;
+	int i, ret;
+
+	if (!mboxes)
+		return ERR_PTR(-EINVAL);
+
+	for (i = 0; (_mbox = mboxes[i]); i++) {
+		if (!strcmp(_mbox->name, name)) {
+			mbox = _mbox;
+			break;
+		}
+	}
+
+	if (!mbox)
+		return ERR_PTR(-ENOENT);
+
+	if (nb)
+		blocking_notifier_chain_register(&mbox->notifier, nb);
+
+	ret = mailbox_startup(mbox);
+	if (ret) {
+		blocking_notifier_chain_unregister(&mbox->notifier, nb);
+		return ERR_PTR(-ENODEV);
+	}
+
+	return mbox;
+}
+EXPORT_SYMBOL(mailbox_get);
+
+void mailbox_put(struct mailbox *mbox, struct notifier_block *nb)
+{
+	if (nb)
+		blocking_notifier_chain_unregister(&mbox->notifier, nb);
+	mailbox_fini(mbox);
+}
+EXPORT_SYMBOL(mailbox_put);
+
+static struct class mailbox_class = { .name = "mbox", };
+
+int mailbox_register(struct device *parent, struct mailbox **list)
+{
+	int ret;
+	int i;
+
+	mboxes = list;
+	if (!mboxes)
+		return -EINVAL;
+
+	for (i = 0; mboxes[i]; i++) {
+		struct mailbox *mbox = mboxes[i];
+		mbox->dev = device_create(&mailbox_class,
+				parent, 0, mbox, "%s", mbox->name);
+		if (IS_ERR(mbox->dev)) {
+			ret = PTR_ERR(mbox->dev);
+			goto err_out;
+		}
+
+		BLOCKING_INIT_NOTIFIER_HEAD(&mbox->notifier);
+	}
+	return 0;
+
+err_out:
+	while (i--)
+		device_unregister(mboxes[i]->dev);
+	return ret;
+}
+EXPORT_SYMBOL(mailbox_register);
+
+int mailbox_unregister(void)
+{
+	int i;
+
+	if (!mboxes)
+		return -EINVAL;
+
+	for (i = 0; mboxes[i]; i++)
+		device_unregister(mboxes[i]->dev);
+	mboxes = NULL;
+	return 0;
+}
+EXPORT_SYMBOL(mailbox_unregister);
+
+static int __init mailbox_init(void)
+{
+	int err;
+
+	err = class_register(&mailbox_class);
+	if (err)
+		return err;
+
+	/* kfifo size sanity check: alignment and minimal size */
+	mbox_kfifo_size = ALIGN(mbox_kfifo_size, sizeof(struct mailbox_msg));
+	mbox_kfifo_size = max_t(unsigned int, mbox_kfifo_size,
+			sizeof(struct mailbox_msg) + CONFIG_MBOX_DATA_SIZE);
+	return 0;
+}
+subsys_initcall(mailbox_init);
+
+static void __exit mailbox_exit(void)
+{
+	class_unregister(&mailbox_class);
+}
+module_exit(mailbox_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("mailbox framework: interrupt driven messaging");
+MODULE_AUTHOR("Toshihiro Kobayashi");
+MODULE_AUTHOR("Hiroshi DOYU");
diff --git a/drivers/mailbox/mailbox_internal.h b/drivers/mailbox/mailbox_internal.h
new file mode 100644
index 0000000..8aded95
--- /dev/null
+++ b/drivers/mailbox/mailbox_internal.h
@@ -0,0 +1,70 @@
+/*
+ * mailbox: interprocessor communication module
+ *
+ * This program is free software; you can 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 MAILBOX_INTERNAL_H
+#define MAILBOX_INTERNAL_H
+
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/kfifo.h>
+#include <linux/mailbox.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+
+typedef int __bitwise mailbox_type_t;
+#define MBOX_HW_FIFO1_TYPE	((__force mailbox_type_t) 1)
+#define MBOX_HW_FIFO2_TYPE	((__force mailbox_type_t) 2)
+#define MBOX_SHARED_MEM_TYPE	((__force mailbox_type_t) 3)
+
+struct mailbox_ops {
+	mailbox_type_t	type;
+	int		(*startup)(struct mailbox *mbox);
+	void		(*shutdown)(struct mailbox *mbox);
+	/* mailbox access */
+	void		(*read)(struct mailbox *mbox, struct mailbox_msg *msg);
+	int		(*write)(struct mailbox *mbox, struct mailbox_msg *msg);
+	int		(*empty)(struct mailbox *mbox);
+	int		(*poll_for_space)(struct mailbox *mbox);
+	/* irq */
+	void		(*enable_irq)(struct mailbox *mbox, mailbox_irq_t irq);
+	void		(*disable_irq)(struct mailbox *mbox, mailbox_irq_t irq);
+	void		(*ack_irq)(struct mailbox *mbox, mailbox_irq_t irq);
+	int		(*is_irq)(struct mailbox *mbox, mailbox_irq_t irq);
+	/* ctx */
+	void		(*save_ctx)(struct mailbox *mbox);
+	void		(*restore_ctx)(struct mailbox *mbox);
+};
+
+struct mailbox_queue {
+	spinlock_t		lock;
+	struct mutex		mlock;
+	struct kfifo		fifo;
+	struct work_struct	work;
+	struct tasklet_struct	tasklet;
+	struct mailbox		*mbox;
+	bool full;
+};
+
+struct mailbox {
+	const char		*name;
+	unsigned int		id;
+	unsigned int		irq;
+	struct mailbox_queue	*txq, *rxq;
+	struct mailbox_ops	*ops;
+	struct device		*dev;
+	void			*priv;
+	int			use_count;
+	struct blocking_notifier_head	notifier;
+};
+
+void mailbox_init_seq(struct mailbox *);
+
+int mailbox_register(struct device *parent, struct mailbox **);
+int mailbox_unregister(void);
+
+#endif /* MAILBOX_INTERNAL_H */
diff --git a/drivers/mailbox/pl320-ipc.c b/drivers/mailbox/pl320-ipc.c
index d873cba..f3755e0 100644
--- a/drivers/mailbox/pl320-ipc.c
+++ b/drivers/mailbox/pl320-ipc.c
@@ -26,7 +26,7 @@
 #include <linux/device.h>
 #include <linux/amba/bus.h>
 
-#include <linux/mailbox.h>
+#include <linux/pl320-ipc.h>
 
 #define IPCMxSOURCE(m)		((m) * 0x40)
 #define IPCMxDSET(m)		(((m) * 0x40) + 0x004)
diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig
index 4d8d90b..3bfc8f1 100644
--- a/drivers/md/Kconfig
+++ b/drivers/md/Kconfig
@@ -174,6 +174,8 @@ config MD_FAULTY
 
 	  In unsure, say N.
 
+source "drivers/md/bcache/Kconfig"
+
 config BLK_DEV_DM
 	tristate "Device mapper support"
 	---help---
diff --git a/drivers/md/Makefile b/drivers/md/Makefile
index 7ceeaef..1439fd4 100644
--- a/drivers/md/Makefile
+++ b/drivers/md/Makefile
@@ -29,6 +29,7 @@ obj-$(CONFIG_MD_RAID10)		+= raid10.o
 obj-$(CONFIG_MD_RAID456)	+= raid456.o
 obj-$(CONFIG_MD_MULTIPATH)	+= multipath.o
 obj-$(CONFIG_MD_FAULTY)		+= faulty.o
+obj-$(CONFIG_BCACHE)		+= bcache/
 obj-$(CONFIG_BLK_DEV_MD)	+= md-mod.o
 obj-$(CONFIG_BLK_DEV_DM)	+= dm-mod.o
 obj-$(CONFIG_DM_BUFIO)		+= dm-bufio.o
diff --git a/drivers/md/bcache/Kconfig b/drivers/md/bcache/Kconfig
new file mode 100644
index 0000000..05c220d
--- /dev/null
+++ b/drivers/md/bcache/Kconfig
@@ -0,0 +1,42 @@
+
+config BCACHE
+	tristate "Block device as cache"
+	select CLOSURES
+	---help---
+	Allows a block device to be used as cache for other devices; uses
+	a btree for indexing and the layout is optimized for SSDs.
+
+	See Documentation/bcache.txt for details.
+
+config BCACHE_DEBUG
+	bool "Bcache debugging"
+	depends on BCACHE
+	---help---
+	Don't select this option unless you're a developer
+
+	Enables extra debugging tools (primarily a fuzz tester)
+
+config BCACHE_EDEBUG
+	bool "Extended runtime checks"
+	depends on BCACHE
+	---help---
+	Don't select this option unless you're a developer
+
+	Enables extra runtime checks which significantly affect performance
+
+config BCACHE_CLOSURES_DEBUG
+	bool "Debug closures"
+	depends on BCACHE
+	select DEBUG_FS
+	---help---
+	Keeps all active closures in a linked list and provides a debugfs
+	interface to list them, which makes it possible to see asynchronous
+	operations that get stuck.
+
+# cgroup code needs to be updated:
+#
+#config CGROUP_BCACHE
+#	bool "Cgroup controls for bcache"
+#	depends on BCACHE && BLK_CGROUP
+#	---help---
+#	TODO
diff --git a/drivers/md/bcache/Makefile b/drivers/md/bcache/Makefile
new file mode 100644
index 0000000..0e9c825
--- /dev/null
+++ b/drivers/md/bcache/Makefile
@@ -0,0 +1,7 @@
+
+obj-$(CONFIG_BCACHE)	+= bcache.o
+
+bcache-y		:= alloc.o btree.o bset.o io.o journal.o writeback.o\
+	movinggc.o request.o super.o sysfs.o debug.o util.o trace.o stats.o closure.o
+
+CFLAGS_request.o	+= -Iblock
diff --git a/drivers/md/bcache/alloc.c b/drivers/md/bcache/alloc.c
new file mode 100644
index 0000000..2879487
--- /dev/null
+++ b/drivers/md/bcache/alloc.c
@@ -0,0 +1,573 @@
+/*
+ * Primary bucket allocation code
+ *
+ * Copyright 2012 Google, Inc.
+ *
+ * Allocation in bcache is done in terms of buckets:
+ *
+ * Each bucket has associated an 8 bit gen; this gen corresponds to the gen in
+ * btree pointers - they must match for the pointer to be considered valid.
+ *
+ * Thus (assuming a bucket has no dirty data or metadata in it) we can reuse a
+ * bucket simply by incrementing its gen.
+ *
+ * The gens (along with the priorities; it's really the gens are important but
+ * the code is named as if it's the priorities) are written in an arbitrary list
+ * of buckets on disk, with a pointer to them in the journal header.
+ *
+ * When we invalidate a bucket, we have to write its new gen to disk and wait
+ * for that write to complete before we use it - otherwise after a crash we
+ * could have pointers that appeared to be good but pointed to data that had
+ * been overwritten.
+ *
+ * Since the gens and priorities are all stored contiguously on disk, we can
+ * batch this up: We fill up the free_inc list with freshly invalidated buckets,
+ * call prio_write(), and when prio_write() finishes we pull buckets off the
+ * free_inc list and optionally discard them.
+ *
+ * free_inc isn't the only freelist - if it was, we'd often to sleep while
+ * priorities and gens were being written before we could allocate. c->free is a
+ * smaller freelist, and buckets on that list are always ready to be used.
+ *
+ * If we've got discards enabled, that happens when a bucket moves from the
+ * free_inc list to the free list.
+ *
+ * There is another freelist, because sometimes we have buckets that we know
+ * have nothing pointing into them - these we can reuse without waiting for
+ * priorities to be rewritten. These come from freed btree nodes and buckets
+ * that garbage collection discovered no longer had valid keys pointing into
+ * them (because they were overwritten). That's the unused list - buckets on the
+ * unused list move to the free list, optionally being discarded in the process.
+ *
+ * It's also important to ensure that gens don't wrap around - with respect to
+ * either the oldest gen in the btree or the gen on disk. This is quite
+ * difficult to do in practice, but we explicitly guard against it anyways - if
+ * a bucket is in danger of wrapping around we simply skip invalidating it that
+ * time around, and we garbage collect or rewrite the priorities sooner than we
+ * would have otherwise.
+ *
+ * bch_bucket_alloc() allocates a single bucket from a specific cache.
+ *
+ * bch_bucket_alloc_set() allocates one or more buckets from different caches
+ * out of a cache set.
+ *
+ * free_some_buckets() drives all the processes described above. It's called
+ * from bch_bucket_alloc() and a few other places that need to make sure free
+ * buckets are ready.
+ *
+ * invalidate_buckets_(lru|fifo)() find buckets that are available to be
+ * invalidated, and then invalidate them and stick them on the free_inc list -
+ * in either lru or fifo order.
+ */
+
+#include "bcache.h"
+#include "btree.h"
+
+#include <linux/random.h>
+
+#define MAX_IN_FLIGHT_DISCARDS		8U
+
+/* Bucket heap / gen */
+
+uint8_t bch_inc_gen(struct cache *ca, struct bucket *b)
+{
+	uint8_t ret = ++b->gen;
+
+	ca->set->need_gc = max(ca->set->need_gc, bucket_gc_gen(b));
+	WARN_ON_ONCE(ca->set->need_gc > BUCKET_GC_GEN_MAX);
+
+	if (CACHE_SYNC(&ca->set->sb)) {
+		ca->need_save_prio = max(ca->need_save_prio,
+					 bucket_disk_gen(b));
+		WARN_ON_ONCE(ca->need_save_prio > BUCKET_DISK_GEN_MAX);
+	}
+
+	return ret;
+}
+
+void bch_rescale_priorities(struct cache_set *c, int sectors)
+{
+	struct cache *ca;
+	struct bucket *b;
+	unsigned next = c->nbuckets * c->sb.bucket_size / 1024;
+	unsigned i;
+	int r;
+
+	atomic_sub(sectors, &c->rescale);
+
+	do {
+		r = atomic_read(&c->rescale);
+
+		if (r >= 0)
+			return;
+	} while (atomic_cmpxchg(&c->rescale, r, r + next) != r);
+
+	mutex_lock(&c->bucket_lock);
+
+	c->min_prio = USHRT_MAX;
+
+	for_each_cache(ca, c, i)
+		for_each_bucket(b, ca)
+			if (b->prio &&
+			    b->prio != BTREE_PRIO &&
+			    !atomic_read(&b->pin)) {
+				b->prio--;
+				c->min_prio = min(c->min_prio, b->prio);
+			}
+
+	mutex_unlock(&c->bucket_lock);
+}
+
+/* Discard/TRIM */
+
+struct discard {
+	struct list_head	list;
+	struct work_struct	work;
+	struct cache		*ca;
+	long			bucket;
+
+	struct bio		bio;
+	struct bio_vec		bv;
+};
+
+static void discard_finish(struct work_struct *w)
+{
+	struct discard *d = container_of(w, struct discard, work);
+	struct cache *ca = d->ca;
+	char buf[BDEVNAME_SIZE];
+
+	if (!test_bit(BIO_UPTODATE, &d->bio.bi_flags)) {
+		pr_notice("discard error on %s, disabling",
+			 bdevname(ca->bdev, buf));
+		d->ca->discard = 0;
+	}
+
+	mutex_lock(&ca->set->bucket_lock);
+
+	fifo_push(&ca->free, d->bucket);
+	list_add(&d->list, &ca->discards);
+	atomic_dec(&ca->discards_in_flight);
+
+	mutex_unlock(&ca->set->bucket_lock);
+
+	closure_wake_up(&ca->set->bucket_wait);
+	wake_up(&ca->set->alloc_wait);
+
+	closure_put(&ca->set->cl);
+}
+
+static void discard_endio(struct bio *bio, int error)
+{
+	struct discard *d = container_of(bio, struct discard, bio);
+	schedule_work(&d->work);
+}
+
+static void do_discard(struct cache *ca, long bucket)
+{
+	struct discard *d = list_first_entry(&ca->discards,
+					     struct discard, list);
+
+	list_del(&d->list);
+	d->bucket = bucket;
+
+	atomic_inc(&ca->discards_in_flight);
+	closure_get(&ca->set->cl);
+
+	bio_init(&d->bio);
+
+	d->bio.bi_sector	= bucket_to_sector(ca->set, d->bucket);
+	d->bio.bi_bdev		= ca->bdev;
+	d->bio.bi_rw		= REQ_WRITE|REQ_DISCARD;
+	d->bio.bi_max_vecs	= 1;
+	d->bio.bi_io_vec	= d->bio.bi_inline_vecs;
+	d->bio.bi_size		= bucket_bytes(ca);
+	d->bio.bi_end_io	= discard_endio;
+	bio_set_prio(&d->bio, IOPRIO_PRIO_VALUE(IOPRIO_CLASS_IDLE, 0));
+
+	submit_bio(0, &d->bio);
+}
+
+/* Allocation */
+
+static inline bool can_inc_bucket_gen(struct bucket *b)
+{
+	return bucket_gc_gen(b) < BUCKET_GC_GEN_MAX &&
+		bucket_disk_gen(b) < BUCKET_DISK_GEN_MAX;
+}
+
+bool bch_bucket_add_unused(struct cache *ca, struct bucket *b)
+{
+	BUG_ON(GC_MARK(b) || GC_SECTORS_USED(b));
+
+	if (fifo_used(&ca->free) > ca->watermark[WATERMARK_MOVINGGC] &&
+	    CACHE_REPLACEMENT(&ca->sb) == CACHE_REPLACEMENT_FIFO)
+		return false;
+
+	b->prio = 0;
+
+	if (can_inc_bucket_gen(b) &&
+	    fifo_push(&ca->unused, b - ca->buckets)) {
+		atomic_inc(&b->pin);
+		return true;
+	}
+
+	return false;
+}
+
+static bool can_invalidate_bucket(struct cache *ca, struct bucket *b)
+{
+	return GC_MARK(b) == GC_MARK_RECLAIMABLE &&
+		!atomic_read(&b->pin) &&
+		can_inc_bucket_gen(b);
+}
+
+static void invalidate_one_bucket(struct cache *ca, struct bucket *b)
+{
+	bch_inc_gen(ca, b);
+	b->prio = INITIAL_PRIO;
+	atomic_inc(&b->pin);
+	fifo_push(&ca->free_inc, b - ca->buckets);
+}
+
+#define bucket_prio(b)				\
+	(((unsigned) (b->prio - ca->set->min_prio)) * GC_SECTORS_USED(b))
+
+#define bucket_max_cmp(l, r)	(bucket_prio(l) < bucket_prio(r))
+#define bucket_min_cmp(l, r)	(bucket_prio(l) > bucket_prio(r))
+
+static void invalidate_buckets_lru(struct cache *ca)
+{
+	struct bucket *b;
+	ssize_t i;
+
+	ca->heap.used = 0;
+
+	for_each_bucket(b, ca) {
+		if (!can_invalidate_bucket(ca, b))
+			continue;
+
+		if (!GC_SECTORS_USED(b)) {
+			if (!bch_bucket_add_unused(ca, b))
+				return;
+		} else {
+			if (!heap_full(&ca->heap))
+				heap_add(&ca->heap, b, bucket_max_cmp);
+			else if (bucket_max_cmp(b, heap_peek(&ca->heap))) {
+				ca->heap.data[0] = b;
+				heap_sift(&ca->heap, 0, bucket_max_cmp);
+			}
+		}
+	}
+
+	if (ca->heap.used * 2 < ca->heap.size)
+		bch_queue_gc(ca->set);
+
+	for (i = ca->heap.used / 2 - 1; i >= 0; --i)
+		heap_sift(&ca->heap, i, bucket_min_cmp);
+
+	while (!fifo_full(&ca->free_inc)) {
+		if (!heap_pop(&ca->heap, b, bucket_min_cmp)) {
+			/* We don't want to be calling invalidate_buckets()
+			 * multiple times when it can't do anything
+			 */
+			ca->invalidate_needs_gc = 1;
+			bch_queue_gc(ca->set);
+			return;
+		}
+
+		invalidate_one_bucket(ca, b);
+	}
+}
+
+static void invalidate_buckets_fifo(struct cache *ca)
+{
+	struct bucket *b;
+	size_t checked = 0;
+
+	while (!fifo_full(&ca->free_inc)) {
+		if (ca->fifo_last_bucket <  ca->sb.first_bucket ||
+		    ca->fifo_last_bucket >= ca->sb.nbuckets)
+			ca->fifo_last_bucket = ca->sb.first_bucket;
+
+		b = ca->buckets + ca->fifo_last_bucket++;
+
+		if (can_invalidate_bucket(ca, b))
+			invalidate_one_bucket(ca, b);
+
+		if (++checked >= ca->sb.nbuckets) {
+			ca->invalidate_needs_gc = 1;
+			bch_queue_gc(ca->set);
+			return;
+		}
+	}
+}
+
+static void invalidate_buckets_random(struct cache *ca)
+{
+	struct bucket *b;
+	size_t checked = 0;
+
+	while (!fifo_full(&ca->free_inc)) {
+		size_t n;
+		get_random_bytes(&n, sizeof(n));
+
+		n %= (size_t) (ca->sb.nbuckets - ca->sb.first_bucket);
+		n += ca->sb.first_bucket;
+
+		b = ca->buckets + n;
+
+		if (can_invalidate_bucket(ca, b))
+			invalidate_one_bucket(ca, b);
+
+		if (++checked >= ca->sb.nbuckets / 2) {
+			ca->invalidate_needs_gc = 1;
+			bch_queue_gc(ca->set);
+			return;
+		}
+	}
+}
+
+static void invalidate_buckets(struct cache *ca)
+{
+	if (ca->invalidate_needs_gc)
+		return;
+
+	switch (CACHE_REPLACEMENT(&ca->sb)) {
+	case CACHE_REPLACEMENT_LRU:
+		invalidate_buckets_lru(ca);
+		break;
+	case CACHE_REPLACEMENT_FIFO:
+		invalidate_buckets_fifo(ca);
+		break;
+	case CACHE_REPLACEMENT_RANDOM:
+		invalidate_buckets_random(ca);
+		break;
+	}
+}
+
+#define allocator_wait(ca, cond)					\
+do {									\
+	DEFINE_WAIT(__wait);						\
+									\
+	while (!(cond)) {						\
+		prepare_to_wait(&ca->set->alloc_wait,			\
+				&__wait, TASK_INTERRUPTIBLE);		\
+									\
+		mutex_unlock(&(ca)->set->bucket_lock);			\
+		if (test_bit(CACHE_SET_STOPPING_2, &ca->set->flags)) {	\
+			finish_wait(&ca->set->alloc_wait, &__wait);	\
+			closure_return(cl);				\
+		}							\
+									\
+		schedule();						\
+		__set_current_state(TASK_RUNNING);			\
+		mutex_lock(&(ca)->set->bucket_lock);			\
+	}								\
+									\
+	finish_wait(&ca->set->alloc_wait, &__wait);			\
+} while (0)
+
+void bch_allocator_thread(struct closure *cl)
+{
+	struct cache *ca = container_of(cl, struct cache, alloc);
+
+	mutex_lock(&ca->set->bucket_lock);
+
+	while (1) {
+		while (1) {
+			long bucket;
+
+			if ((!atomic_read(&ca->set->prio_blocked) ||
+			     !CACHE_SYNC(&ca->set->sb)) &&
+			    !fifo_empty(&ca->unused))
+				fifo_pop(&ca->unused, bucket);
+			else if (!fifo_empty(&ca->free_inc))
+				fifo_pop(&ca->free_inc, bucket);
+			else
+				break;
+
+			allocator_wait(ca, (int) fifo_free(&ca->free) >
+				       atomic_read(&ca->discards_in_flight));
+
+			if (ca->discard) {
+				allocator_wait(ca, !list_empty(&ca->discards));
+				do_discard(ca, bucket);
+			} else {
+				fifo_push(&ca->free, bucket);
+				closure_wake_up(&ca->set->bucket_wait);
+			}
+		}
+
+		allocator_wait(ca, ca->set->gc_mark_valid);
+		invalidate_buckets(ca);
+
+		allocator_wait(ca, !atomic_read(&ca->set->prio_blocked) ||
+			       !CACHE_SYNC(&ca->set->sb));
+
+		if (CACHE_SYNC(&ca->set->sb) &&
+		    (!fifo_empty(&ca->free_inc) ||
+		     ca->need_save_prio > 64)) {
+			bch_prio_write(ca);
+		}
+	}
+}
+
+long bch_bucket_alloc(struct cache *ca, unsigned watermark, struct closure *cl)
+{
+	long r = -1;
+again:
+	wake_up(&ca->set->alloc_wait);
+
+	if (fifo_used(&ca->free) > ca->watermark[watermark] &&
+	    fifo_pop(&ca->free, r)) {
+		struct bucket *b = ca->buckets + r;
+#ifdef CONFIG_BCACHE_EDEBUG
+		size_t iter;
+		long i;
+
+		for (iter = 0; iter < prio_buckets(ca) * 2; iter++)
+			BUG_ON(ca->prio_buckets[iter] == (uint64_t) r);
+
+		fifo_for_each(i, &ca->free, iter)
+			BUG_ON(i == r);
+		fifo_for_each(i, &ca->free_inc, iter)
+			BUG_ON(i == r);
+		fifo_for_each(i, &ca->unused, iter)
+			BUG_ON(i == r);
+#endif
+		BUG_ON(atomic_read(&b->pin) != 1);
+
+		SET_GC_SECTORS_USED(b, ca->sb.bucket_size);
+
+		if (watermark <= WATERMARK_METADATA) {
+			SET_GC_MARK(b, GC_MARK_METADATA);
+			b->prio = BTREE_PRIO;
+		} else {
+			SET_GC_MARK(b, GC_MARK_RECLAIMABLE);
+			b->prio = INITIAL_PRIO;
+		}
+
+		return r;
+	}
+
+	pr_debug("alloc failure: blocked %i free %zu free_inc %zu unused %zu",
+		 atomic_read(&ca->set->prio_blocked), fifo_used(&ca->free),
+		 fifo_used(&ca->free_inc), fifo_used(&ca->unused));
+
+	if (cl) {
+		closure_wait(&ca->set->bucket_wait, cl);
+
+		if (closure_blocking(cl)) {
+			mutex_unlock(&ca->set->bucket_lock);
+			closure_sync(cl);
+			mutex_lock(&ca->set->bucket_lock);
+			goto again;
+		}
+	}
+
+	return -1;
+}
+
+void bch_bucket_free(struct cache_set *c, struct bkey *k)
+{
+	unsigned i;
+
+	for (i = 0; i < KEY_PTRS(k); i++) {
+		struct bucket *b = PTR_BUCKET(c, k, i);
+
+		SET_GC_MARK(b, 0);
+		SET_GC_SECTORS_USED(b, 0);
+		bch_bucket_add_unused(PTR_CACHE(c, k, i), b);
+	}
+}
+
+int __bch_bucket_alloc_set(struct cache_set *c, unsigned watermark,
+			   struct bkey *k, int n, struct closure *cl)
+{
+	int i;
+
+	lockdep_assert_held(&c->bucket_lock);
+	BUG_ON(!n || n > c->caches_loaded || n > 8);
+
+	bkey_init(k);
+
+	/* sort by free space/prio of oldest data in caches */
+
+	for (i = 0; i < n; i++) {
+		struct cache *ca = c->cache_by_alloc[i];
+		long b = bch_bucket_alloc(ca, watermark, cl);
+
+		if (b == -1)
+			goto err;
+
+		k->ptr[i] = PTR(ca->buckets[b].gen,
+				bucket_to_sector(c, b),
+				ca->sb.nr_this_dev);
+
+		SET_KEY_PTRS(k, i + 1);
+	}
+
+	return 0;
+err:
+	bch_bucket_free(c, k);
+	__bkey_put(c, k);
+	return -1;
+}
+
+int bch_bucket_alloc_set(struct cache_set *c, unsigned watermark,
+			 struct bkey *k, int n, struct closure *cl)
+{
+	int ret;
+	mutex_lock(&c->bucket_lock);
+	ret = __bch_bucket_alloc_set(c, watermark, k, n, cl);
+	mutex_unlock(&c->bucket_lock);
+	return ret;
+}
+
+/* Init */
+
+void bch_cache_allocator_exit(struct cache *ca)
+{
+	struct discard *d;
+
+	while (!list_empty(&ca->discards)) {
+		d = list_first_entry(&ca->discards, struct discard, list);
+		cancel_work_sync(&d->work);
+		list_del(&d->list);
+		kfree(d);
+	}
+}
+
+int bch_cache_allocator_init(struct cache *ca)
+{
+	unsigned i;
+
+	/*
+	 * Reserve:
+	 * Prio/gen writes first
+	 * Then 8 for btree allocations
+	 * Then half for the moving garbage collector
+	 */
+
+	ca->watermark[WATERMARK_PRIO] = 0;
+
+	ca->watermark[WATERMARK_METADATA] = prio_buckets(ca);
+
+	ca->watermark[WATERMARK_MOVINGGC] = 8 +
+		ca->watermark[WATERMARK_METADATA];
+
+	ca->watermark[WATERMARK_NONE] = ca->free.size / 2 +
+		ca->watermark[WATERMARK_MOVINGGC];
+
+	for (i = 0; i < MAX_IN_FLIGHT_DISCARDS; i++) {
+		struct discard *d = kzalloc(sizeof(*d), GFP_KERNEL);
+		if (!d)
+			return -ENOMEM;
+
+		d->ca = ca;
+		INIT_WORK(&d->work, discard_finish);
+		list_add(&d->list, &ca->discards);
+	}
+
+	return 0;
+}
diff --git a/drivers/md/bcache/bcache.h b/drivers/md/bcache/bcache.h
new file mode 100644
index 0000000..f057235
--- /dev/null
+++ b/drivers/md/bcache/bcache.h
@@ -0,0 +1,1232 @@
+#ifndef _BCACHE_H
+#define _BCACHE_H
+
+/*
+ * SOME HIGH LEVEL CODE DOCUMENTATION:
+ *
+ * Bcache mostly works with cache sets, cache devices, and backing devices.
+ *
+ * Support for multiple cache devices hasn't quite been finished off yet, but
+ * it's about 95% plumbed through. A cache set and its cache devices is sort of
+ * like a md raid array and its component devices. Most of the code doesn't care
+ * about individual cache devices, the main abstraction is the cache set.
+ *
+ * Multiple cache devices is intended to give us the ability to mirror dirty
+ * cached data and metadata, without mirroring clean cached data.
+ *
+ * Backing devices are different, in that they have a lifetime independent of a
+ * cache set. When you register a newly formatted backing device it'll come up
+ * in passthrough mode, and then you can attach and detach a backing device from
+ * a cache set at runtime - while it's mounted and in use. Detaching implicitly
+ * invalidates any cached data for that backing device.
+ *
+ * A cache set can have multiple (many) backing devices attached to it.
+ *
+ * There's also flash only volumes - this is the reason for the distinction
+ * between struct cached_dev and struct bcache_device. A flash only volume
+ * works much like a bcache device that has a backing device, except the
+ * "cached" data is always dirty. The end result is that we get thin
+ * provisioning with very little additional code.
+ *
+ * Flash only volumes work but they're not production ready because the moving
+ * garbage collector needs more work. More on that later.
+ *
+ * BUCKETS/ALLOCATION:
+ *
+ * Bcache is primarily designed for caching, which means that in normal
+ * operation all of our available space will be allocated. Thus, we need an
+ * efficient way of deleting things from the cache so we can write new things to
+ * it.
+ *
+ * To do this, we first divide the cache device up into buckets. A bucket is the
+ * unit of allocation; they're typically around 1 mb - anywhere from 128k to 2M+
+ * works efficiently.
+ *
+ * Each bucket has a 16 bit priority, and an 8 bit generation associated with
+ * it. The gens and priorities for all the buckets are stored contiguously and
+ * packed on disk (in a linked list of buckets - aside from the superblock, all
+ * of bcache's metadata is stored in buckets).
+ *
+ * The priority is used to implement an LRU. We reset a bucket's priority when
+ * we allocate it or on cache it, and every so often we decrement the priority
+ * of each bucket. It could be used to implement something more sophisticated,
+ * if anyone ever gets around to it.
+ *
+ * The generation is used for invalidating buckets. Each pointer also has an 8
+ * bit generation embedded in it; for a pointer to be considered valid, its gen
+ * must match the gen of the bucket it points into.  Thus, to reuse a bucket all
+ * we have to do is increment its gen (and write its new gen to disk; we batch
+ * this up).
+ *
+ * Bcache is entirely COW - we never write twice to a bucket, even buckets that
+ * contain metadata (including btree nodes).
+ *
+ * THE BTREE:
+ *
+ * Bcache is in large part design around the btree.
+ *
+ * At a high level, the btree is just an index of key -> ptr tuples.
+ *
+ * Keys represent extents, and thus have a size field. Keys also have a variable
+ * number of pointers attached to them (potentially zero, which is handy for
+ * invalidating the cache).
+ *
+ * The key itself is an inode:offset pair. The inode number corresponds to a
+ * backing device or a flash only volume. The offset is the ending offset of the
+ * extent within the inode - not the starting offset; this makes lookups
+ * slightly more convenient.
+ *
+ * Pointers contain the cache device id, the offset on that device, and an 8 bit
+ * generation number. More on the gen later.
+ *
+ * Index lookups are not fully abstracted - cache lookups in particular are
+ * still somewhat mixed in with the btree code, but things are headed in that
+ * direction.
+ *
+ * Updates are fairly well abstracted, though. There are two different ways of
+ * updating the btree; insert and replace.
+ *
+ * BTREE_INSERT will just take a list of keys and insert them into the btree -
+ * overwriting (possibly only partially) any extents they overlap with. This is
+ * used to update the index after a write.
+ *
+ * BTREE_REPLACE is really cmpxchg(); it inserts a key into the btree iff it is
+ * overwriting a key that matches another given key. This is used for inserting
+ * data into the cache after a cache miss, and for background writeback, and for
+ * the moving garbage collector.
+ *
+ * There is no "delete" operation; deleting things from the index is
+ * accomplished by either by invalidating pointers (by incrementing a bucket's
+ * gen) or by inserting a key with 0 pointers - which will overwrite anything
+ * previously present at that location in the index.
+ *
+ * This means that there are always stale/invalid keys in the btree. They're
+ * filtered out by the code that iterates through a btree node, and removed when
+ * a btree node is rewritten.
+ *
+ * BTREE NODES:
+ *
+ * Our unit of allocation is a bucket, and we we can't arbitrarily allocate and
+ * free smaller than a bucket - so, that's how big our btree nodes are.
+ *
+ * (If buckets are really big we'll only use part of the bucket for a btree node
+ * - no less than 1/4th - but a bucket still contains no more than a single
+ * btree node. I'd actually like to change this, but for now we rely on the
+ * bucket's gen for deleting btree nodes when we rewrite/split a node.)
+ *
+ * Anyways, btree nodes are big - big enough to be inefficient with a textbook
+ * btree implementation.
+ *
+ * The way this is solved is that btree nodes are internally log structured; we
+ * can append new keys to an existing btree node without rewriting it. This
+ * means each set of keys we write is sorted, but the node is not.
+ *
+ * We maintain this log structure in memory - keeping 1Mb of keys sorted would
+ * be expensive, and we have to distinguish between the keys we have written and
+ * the keys we haven't. So to do a lookup in a btree node, we have to search
+ * each sorted set. But we do merge written sets together lazily, so the cost of
+ * these extra searches is quite low (normally most of the keys in a btree node
+ * will be in one big set, and then there'll be one or two sets that are much
+ * smaller).
+ *
+ * This log structure makes bcache's btree more of a hybrid between a
+ * conventional btree and a compacting data structure, with some of the
+ * advantages of both.
+ *
+ * GARBAGE COLLECTION:
+ *
+ * We can't just invalidate any bucket - it might contain dirty data or
+ * metadata. If it once contained dirty data, other writes might overwrite it
+ * later, leaving no valid pointers into that bucket in the index.
+ *
+ * Thus, the primary purpose of garbage collection is to find buckets to reuse.
+ * It also counts how much valid data it each bucket currently contains, so that
+ * allocation can reuse buckets sooner when they've been mostly overwritten.
+ *
+ * It also does some things that are really internal to the btree
+ * implementation. If a btree node contains pointers that are stale by more than
+ * some threshold, it rewrites the btree node to avoid the bucket's generation
+ * wrapping around. It also merges adjacent btree nodes if they're empty enough.
+ *
+ * THE JOURNAL:
+ *
+ * Bcache's journal is not necessary for consistency; we always strictly
+ * order metadata writes so that the btree and everything else is consistent on
+ * disk in the event of an unclean shutdown, and in fact bcache had writeback
+ * caching (with recovery from unclean shutdown) before journalling was
+ * implemented.
+ *
+ * Rather, the journal is purely a performance optimization; we can't complete a
+ * write until we've updated the index on disk, otherwise the cache would be
+ * inconsistent in the event of an unclean shutdown. This means that without the
+ * journal, on random write workloads we constantly have to update all the leaf
+ * nodes in the btree, and those writes will be mostly empty (appending at most
+ * a few keys each) - highly inefficient in terms of amount of metadata writes,
+ * and it puts more strain on the various btree resorting/compacting code.
+ *
+ * The journal is just a log of keys we've inserted; on startup we just reinsert
+ * all the keys in the open journal entries. That means that when we're updating
+ * a node in the btree, we can wait until a 4k block of keys fills up before
+ * writing them out.
+ *
+ * For simplicity, we only journal updates to leaf nodes; updates to parent
+ * nodes are rare enough (since our leaf nodes are huge) that it wasn't worth
+ * the complexity to deal with journalling them (in particular, journal replay)
+ * - updates to non leaf nodes just happen synchronously (see btree_split()).
+ */
+
+#define pr_fmt(fmt) "bcache: %s() " fmt "\n", __func__
+
+#include <linux/bio.h>
+#include <linux/blktrace_api.h>
+#include <linux/kobject.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/rbtree.h>
+#include <linux/rwsem.h>
+#include <linux/types.h>
+#include <linux/workqueue.h>
+
+#include "util.h"
+#include "closure.h"
+
+struct bucket {
+	atomic_t	pin;
+	uint16_t	prio;
+	uint8_t		gen;
+	uint8_t		disk_gen;
+	uint8_t		last_gc; /* Most out of date gen in the btree */
+	uint8_t		gc_gen;
+	uint16_t	gc_mark;
+};
+
+/*
+ * I'd use bitfields for these, but I don't trust the compiler not to screw me
+ * as multiple threads touch struct bucket without locking
+ */
+
+BITMASK(GC_MARK,	 struct bucket, gc_mark, 0, 2);
+#define GC_MARK_RECLAIMABLE	0
+#define GC_MARK_DIRTY		1
+#define GC_MARK_METADATA	2
+BITMASK(GC_SECTORS_USED, struct bucket, gc_mark, 2, 14);
+
+struct bkey {
+	uint64_t	high;
+	uint64_t	low;
+	uint64_t	ptr[];
+};
+
+/* Enough for a key with 6 pointers */
+#define BKEY_PAD		8
+
+#define BKEY_PADDED(key)					\
+	union { struct bkey key; uint64_t key ## _pad[BKEY_PAD]; }
+
+/* Version 1: Backing device
+ * Version 2: Seed pointer into btree node checksum
+ * Version 3: New UUID format
+ */
+#define BCACHE_SB_VERSION	3
+
+#define SB_SECTOR		8
+#define SB_SIZE			4096
+#define SB_LABEL_SIZE		32
+#define SB_JOURNAL_BUCKETS	256U
+/* SB_JOURNAL_BUCKETS must be divisible by BITS_PER_LONG */
+#define MAX_CACHES_PER_SET	8
+
+#define BDEV_DATA_START		16	/* sectors */
+
+struct cache_sb {
+	uint64_t		csum;
+	uint64_t		offset;	/* sector where this sb was written */
+	uint64_t		version;
+#define CACHE_BACKING_DEV	1
+
+	uint8_t			magic[16];
+
+	uint8_t			uuid[16];
+	union {
+		uint8_t		set_uuid[16];
+		uint64_t	set_magic;
+	};
+	uint8_t			label[SB_LABEL_SIZE];
+
+	uint64_t		flags;
+	uint64_t		seq;
+	uint64_t		pad[8];
+
+	uint64_t		nbuckets;	/* device size */
+	uint16_t		block_size;	/* sectors */
+	uint16_t		bucket_size;	/* sectors */
+
+	uint16_t		nr_in_set;
+	uint16_t		nr_this_dev;
+
+	uint32_t		last_mount;	/* time_t */
+
+	uint16_t		first_bucket;
+	union {
+		uint16_t	njournal_buckets;
+		uint16_t	keys;
+	};
+	uint64_t		d[SB_JOURNAL_BUCKETS];	/* journal buckets */
+};
+
+BITMASK(CACHE_SYNC,		struct cache_sb, flags, 0, 1);
+BITMASK(CACHE_DISCARD,		struct cache_sb, flags, 1, 1);
+BITMASK(CACHE_REPLACEMENT,	struct cache_sb, flags, 2, 3);
+#define CACHE_REPLACEMENT_LRU	0U
+#define CACHE_REPLACEMENT_FIFO	1U
+#define CACHE_REPLACEMENT_RANDOM 2U
+
+BITMASK(BDEV_CACHE_MODE,	struct cache_sb, flags, 0, 4);
+#define CACHE_MODE_WRITETHROUGH	0U
+#define CACHE_MODE_WRITEBACK	1U
+#define CACHE_MODE_WRITEAROUND	2U
+#define CACHE_MODE_NONE		3U
+BITMASK(BDEV_STATE,		struct cache_sb, flags, 61, 2);
+#define BDEV_STATE_NONE		0U
+#define BDEV_STATE_CLEAN	1U
+#define BDEV_STATE_DIRTY	2U
+#define BDEV_STATE_STALE	3U
+
+/* Version 1: Seed pointer into btree node checksum
+ */
+#define BCACHE_BSET_VERSION	1
+
+/*
+ * This is the on disk format for btree nodes - a btree node on disk is a list
+ * of these; within each set the keys are sorted
+ */
+struct bset {
+	uint64_t		csum;
+	uint64_t		magic;
+	uint64_t		seq;
+	uint32_t		version;
+	uint32_t		keys;
+
+	union {
+		struct bkey	start[0];
+		uint64_t	d[0];
+	};
+};
+
+/*
+ * On disk format for priorities and gens - see super.c near prio_write() for
+ * more.
+ */
+struct prio_set {
+	uint64_t		csum;
+	uint64_t		magic;
+	uint64_t		seq;
+	uint32_t		version;
+	uint32_t		pad;
+
+	uint64_t		next_bucket;
+
+	struct bucket_disk {
+		uint16_t	prio;
+		uint8_t		gen;
+	} __attribute((packed)) data[];
+};
+
+struct uuid_entry {
+	union {
+		struct {
+			uint8_t		uuid[16];
+			uint8_t		label[32];
+			uint32_t	first_reg;
+			uint32_t	last_reg;
+			uint32_t	invalidated;
+
+			uint32_t	flags;
+			/* Size of flash only volumes */
+			uint64_t	sectors;
+		};
+
+		uint8_t	pad[128];
+	};
+};
+
+BITMASK(UUID_FLASH_ONLY,	struct uuid_entry, flags, 0, 1);
+
+#include "journal.h"
+#include "stats.h"
+struct search;
+struct btree;
+struct keybuf;
+
+struct keybuf_key {
+	struct rb_node		node;
+	BKEY_PADDED(key);
+	void			*private;
+};
+
+typedef bool (keybuf_pred_fn)(struct keybuf *, struct bkey *);
+
+struct keybuf {
+	keybuf_pred_fn		*key_predicate;
+
+	struct bkey		last_scanned;
+	spinlock_t		lock;
+
+	/*
+	 * Beginning and end of range in rb tree - so that we can skip taking
+	 * lock and checking the rb tree when we need to check for overlapping
+	 * keys.
+	 */
+	struct bkey		start;
+	struct bkey		end;
+
+	struct rb_root		keys;
+
+#define KEYBUF_NR		100
+	DECLARE_ARRAY_ALLOCATOR(struct keybuf_key, freelist, KEYBUF_NR);
+};
+
+struct bio_split_pool {
+	struct bio_set		*bio_split;
+	mempool_t		*bio_split_hook;
+};
+
+struct bio_split_hook {
+	struct closure		cl;
+	struct bio_split_pool	*p;
+	struct bio		*bio;
+	bio_end_io_t		*bi_end_io;
+	void			*bi_private;
+};
+
+struct bcache_device {
+	struct closure		cl;
+
+	struct kobject		kobj;
+
+	struct cache_set	*c;
+	unsigned		id;
+#define BCACHEDEVNAME_SIZE	12
+	char			name[BCACHEDEVNAME_SIZE];
+
+	struct gendisk		*disk;
+
+	/* If nonzero, we're closing */
+	atomic_t		closing;
+
+	/* If nonzero, we're detaching/unregistering from cache set */
+	atomic_t		detaching;
+
+	atomic_long_t		sectors_dirty;
+	unsigned long		sectors_dirty_gc;
+	unsigned long		sectors_dirty_last;
+	long			sectors_dirty_derivative;
+
+	mempool_t		*unaligned_bvec;
+	struct bio_set		*bio_split;
+
+	unsigned		data_csum:1;
+
+	int (*cache_miss)(struct btree *, struct search *,
+			  struct bio *, unsigned);
+	int (*ioctl) (struct bcache_device *, fmode_t, unsigned, unsigned long);
+
+	struct bio_split_pool	bio_split_hook;
+};
+
+struct io {
+	/* Used to track sequential IO so it can be skipped */
+	struct hlist_node	hash;
+	struct list_head	lru;
+
+	unsigned long		jiffies;
+	unsigned		sequential;
+	sector_t		last;
+};
+
+struct cached_dev {
+	struct list_head	list;
+	struct bcache_device	disk;
+	struct block_device	*bdev;
+
+	struct cache_sb		sb;
+	struct bio		sb_bio;
+	struct bio_vec		sb_bv[1];
+	struct closure_with_waitlist sb_write;
+
+	/* Refcount on the cache set. Always nonzero when we're caching. */
+	atomic_t		count;
+	struct work_struct	detach;
+
+	/*
+	 * Device might not be running if it's dirty and the cache set hasn't
+	 * showed up yet.
+	 */
+	atomic_t		running;
+
+	/*
+	 * Writes take a shared lock from start to finish; scanning for dirty
+	 * data to refill the rb tree requires an exclusive lock.
+	 */
+	struct rw_semaphore	writeback_lock;
+
+	/*
+	 * Nonzero, and writeback has a refcount (d->count), iff there is dirty
+	 * data in the cache. Protected by writeback_lock; must have an
+	 * shared lock to set and exclusive lock to clear.
+	 */
+	atomic_t		has_dirty;
+
+	struct ratelimit	writeback_rate;
+	struct delayed_work	writeback_rate_update;
+
+	/*
+	 * Internal to the writeback code, so read_dirty() can keep track of
+	 * where it's at.
+	 */
+	sector_t		last_read;
+
+	/* Number of writeback bios in flight */
+	atomic_t		in_flight;
+	struct closure_with_timer writeback;
+	struct closure_waitlist	writeback_wait;
+
+	struct keybuf		writeback_keys;
+
+	/* For tracking sequential IO */
+#define RECENT_IO_BITS	7
+#define RECENT_IO	(1 << RECENT_IO_BITS)
+	struct io		io[RECENT_IO];
+	struct hlist_head	io_hash[RECENT_IO + 1];
+	struct list_head	io_lru;
+	spinlock_t		io_lock;
+
+	struct cache_accounting	accounting;
+
+	/* The rest of this all shows up in sysfs */
+	unsigned		sequential_cutoff;
+	unsigned		readahead;
+
+	unsigned		sequential_merge:1;
+	unsigned		verify:1;
+
+	unsigned		writeback_metadata:1;
+	unsigned		writeback_running:1;
+	unsigned char		writeback_percent;
+	unsigned		writeback_delay;
+
+	int			writeback_rate_change;
+	int64_t			writeback_rate_derivative;
+	uint64_t		writeback_rate_target;
+
+	unsigned		writeback_rate_update_seconds;
+	unsigned		writeback_rate_d_term;
+	unsigned		writeback_rate_p_term_inverse;
+	unsigned		writeback_rate_d_smooth;
+};
+
+enum alloc_watermarks {
+	WATERMARK_PRIO,
+	WATERMARK_METADATA,
+	WATERMARK_MOVINGGC,
+	WATERMARK_NONE,
+	WATERMARK_MAX
+};
+
+struct cache {
+	struct cache_set	*set;
+	struct cache_sb		sb;
+	struct bio		sb_bio;
+	struct bio_vec		sb_bv[1];
+
+	struct kobject		kobj;
+	struct block_device	*bdev;
+
+	unsigned		watermark[WATERMARK_MAX];
+
+	struct closure		alloc;
+	struct workqueue_struct	*alloc_workqueue;
+
+	struct closure		prio;
+	struct prio_set		*disk_buckets;
+
+	/*
+	 * When allocating new buckets, prio_write() gets first dibs - since we
+	 * may not be allocate at all without writing priorities and gens.
+	 * prio_buckets[] contains the last buckets we wrote priorities to (so
+	 * gc can mark them as metadata), prio_next[] contains the buckets
+	 * allocated for the next prio write.
+	 */
+	uint64_t		*prio_buckets;
+	uint64_t		*prio_last_buckets;
+
+	/*
+	 * free: Buckets that are ready to be used
+	 *
+	 * free_inc: Incoming buckets - these are buckets that currently have
+	 * cached data in them, and we can't reuse them until after we write
+	 * their new gen to disk. After prio_write() finishes writing the new
+	 * gens/prios, they'll be moved to the free list (and possibly discarded
+	 * in the process)
+	 *
+	 * unused: GC found nothing pointing into these buckets (possibly
+	 * because all the data they contained was overwritten), so we only
+	 * need to discard them before they can be moved to the free list.
+	 */
+	DECLARE_FIFO(long, free);
+	DECLARE_FIFO(long, free_inc);
+	DECLARE_FIFO(long, unused);
+
+	size_t			fifo_last_bucket;
+
+	/* Allocation stuff: */
+	struct bucket		*buckets;
+
+	DECLARE_HEAP(struct bucket *, heap);
+
+	/*
+	 * max(gen - disk_gen) for all buckets. When it gets too big we have to
+	 * call prio_write() to keep gens from wrapping.
+	 */
+	uint8_t			need_save_prio;
+	unsigned		gc_move_threshold;
+
+	/*
+	 * If nonzero, we know we aren't going to find any buckets to invalidate
+	 * until a gc finishes - otherwise we could pointlessly burn a ton of
+	 * cpu
+	 */
+	unsigned		invalidate_needs_gc:1;
+
+	bool			discard; /* Get rid of? */
+
+	/*
+	 * We preallocate structs for issuing discards to buckets, and keep them
+	 * on this list when they're not in use; do_discard() issues discards
+	 * whenever there's work to do and is called by free_some_buckets() and
+	 * when a discard finishes.
+	 */
+	atomic_t		discards_in_flight;
+	struct list_head	discards;
+
+	struct journal_device	journal;
+
+	/* The rest of this all shows up in sysfs */
+#define IO_ERROR_SHIFT		20
+	atomic_t		io_errors;
+	atomic_t		io_count;
+
+	atomic_long_t		meta_sectors_written;
+	atomic_long_t		btree_sectors_written;
+	atomic_long_t		sectors_written;
+
+	struct bio_split_pool	bio_split_hook;
+};
+
+struct gc_stat {
+	size_t			nodes;
+	size_t			key_bytes;
+
+	size_t			nkeys;
+	uint64_t		data;	/* sectors */
+	uint64_t		dirty;	/* sectors */
+	unsigned		in_use; /* percent */
+};
+
+/*
+ * Flag bits, for how the cache set is shutting down, and what phase it's at:
+ *
+ * CACHE_SET_UNREGISTERING means we're not just shutting down, we're detaching
+ * all the backing devices first (their cached data gets invalidated, and they
+ * won't automatically reattach).
+ *
+ * CACHE_SET_STOPPING always gets set first when we're closing down a cache set;
+ * we'll continue to run normally for awhile with CACHE_SET_STOPPING set (i.e.
+ * flushing dirty data).
+ *
+ * CACHE_SET_STOPPING_2 gets set at the last phase, when it's time to shut down
+ * the allocation thread.
+ */
+#define CACHE_SET_UNREGISTERING		0
+#define	CACHE_SET_STOPPING		1
+#define	CACHE_SET_STOPPING_2		2
+
+struct cache_set {
+	struct closure		cl;
+
+	struct list_head	list;
+	struct kobject		kobj;
+	struct kobject		internal;
+	struct dentry		*debug;
+	struct cache_accounting accounting;
+
+	unsigned long		flags;
+
+	struct cache_sb		sb;
+
+	struct cache		*cache[MAX_CACHES_PER_SET];
+	struct cache		*cache_by_alloc[MAX_CACHES_PER_SET];
+	int			caches_loaded;
+
+	struct bcache_device	**devices;
+	struct list_head	cached_devs;
+	uint64_t		cached_dev_sectors;
+	struct closure		caching;
+
+	struct closure_with_waitlist sb_write;
+
+	mempool_t		*search;
+	mempool_t		*bio_meta;
+	struct bio_set		*bio_split;
+
+	/* For the btree cache */
+	struct shrinker		shrink;
+
+	/* For the allocator itself */
+	wait_queue_head_t	alloc_wait;
+
+	/* For the btree cache and anything allocation related */
+	struct mutex		bucket_lock;
+
+	/* log2(bucket_size), in sectors */
+	unsigned short		bucket_bits;
+
+	/* log2(block_size), in sectors */
+	unsigned short		block_bits;
+
+	/*
+	 * Default number of pages for a new btree node - may be less than a
+	 * full bucket
+	 */
+	unsigned		btree_pages;
+
+	/*
+	 * Lists of struct btrees; lru is the list for structs that have memory
+	 * allocated for actual btree node, freed is for structs that do not.
+	 *
+	 * We never free a struct btree, except on shutdown - we just put it on
+	 * the btree_cache_freed list and reuse it later. This simplifies the
+	 * code, and it doesn't cost us much memory as the memory usage is
+	 * dominated by buffers that hold the actual btree node data and those
+	 * can be freed - and the number of struct btrees allocated is
+	 * effectively bounded.
+	 *
+	 * btree_cache_freeable effectively is a small cache - we use it because
+	 * high order page allocations can be rather expensive, and it's quite
+	 * common to delete and allocate btree nodes in quick succession. It
+	 * should never grow past ~2-3 nodes in practice.
+	 */
+	struct list_head	btree_cache;
+	struct list_head	btree_cache_freeable;
+	struct list_head	btree_cache_freed;
+
+	/* Number of elements in btree_cache + btree_cache_freeable lists */
+	unsigned		bucket_cache_used;
+
+	/*
+	 * If we need to allocate memory for a new btree node and that
+	 * allocation fails, we can cannibalize another node in the btree cache
+	 * to satisfy the allocation. However, only one thread can be doing this
+	 * at a time, for obvious reasons - try_harder and try_wait are
+	 * basically a lock for this that we can wait on asynchronously. The
+	 * btree_root() macro releases the lock when it returns.
+	 */
+	struct closure		*try_harder;
+	struct closure_waitlist	try_wait;
+	uint64_t		try_harder_start;
+
+	/*
+	 * When we free a btree node, we increment the gen of the bucket the
+	 * node is in - but we can't rewrite the prios and gens until we
+	 * finished whatever it is we were doing, otherwise after a crash the
+	 * btree node would be freed but for say a split, we might not have the
+	 * pointers to the new nodes inserted into the btree yet.
+	 *
+	 * This is a refcount that blocks prio_write() until the new keys are
+	 * written.
+	 */
+	atomic_t		prio_blocked;
+	struct closure_waitlist	bucket_wait;
+
+	/*
+	 * For any bio we don't skip we subtract the number of sectors from
+	 * rescale; when it hits 0 we rescale all the bucket priorities.
+	 */
+	atomic_t		rescale;
+	/*
+	 * When we invalidate buckets, we use both the priority and the amount
+	 * of good data to determine which buckets to reuse first - to weight
+	 * those together consistently we keep track of the smallest nonzero
+	 * priority of any bucket.
+	 */
+	uint16_t		min_prio;
+
+	/*
+	 * max(gen - gc_gen) for all buckets. When it gets too big we have to gc
+	 * to keep gens from wrapping around.
+	 */
+	uint8_t			need_gc;
+	struct gc_stat		gc_stats;
+	size_t			nbuckets;
+
+	struct closure_with_waitlist gc;
+	/* Where in the btree gc currently is */
+	struct bkey		gc_done;
+
+	/*
+	 * The allocation code needs gc_mark in struct bucket to be correct, but
+	 * it's not while a gc is in progress. Protected by bucket_lock.
+	 */
+	int			gc_mark_valid;
+
+	/* Counts how many sectors bio_insert has added to the cache */
+	atomic_t		sectors_to_gc;
+
+	struct closure		moving_gc;
+	struct closure_waitlist	moving_gc_wait;
+	struct keybuf		moving_gc_keys;
+	/* Number of moving GC bios in flight */
+	atomic_t		in_flight;
+
+	struct btree		*root;
+
+#ifdef CONFIG_BCACHE_DEBUG
+	struct btree		*verify_data;
+	struct mutex		verify_lock;
+#endif
+
+	unsigned		nr_uuids;
+	struct uuid_entry	*uuids;
+	BKEY_PADDED(uuid_bucket);
+	struct closure_with_waitlist uuid_write;
+
+	/*
+	 * A btree node on disk could have too many bsets for an iterator to fit
+	 * on the stack - this is a single element mempool for btree_read_work()
+	 */
+	struct mutex		fill_lock;
+	struct btree_iter	*fill_iter;
+
+	/*
+	 * btree_sort() is a merge sort and requires temporary space - single
+	 * element mempool
+	 */
+	struct mutex		sort_lock;
+	struct bset		*sort;
+
+	/* List of buckets we're currently writing data to */
+	struct list_head	data_buckets;
+	spinlock_t		data_bucket_lock;
+
+	struct journal		journal;
+
+#define CONGESTED_MAX		1024
+	unsigned		congested_last_us;
+	atomic_t		congested;
+
+	/* The rest of this all shows up in sysfs */
+	unsigned		congested_read_threshold_us;
+	unsigned		congested_write_threshold_us;
+
+	spinlock_t		sort_time_lock;
+	struct time_stats	sort_time;
+	struct time_stats	btree_gc_time;
+	struct time_stats	btree_split_time;
+	spinlock_t		btree_read_time_lock;
+	struct time_stats	btree_read_time;
+	struct time_stats	try_harder_time;
+
+	atomic_long_t		cache_read_races;
+	atomic_long_t		writeback_keys_done;
+	atomic_long_t		writeback_keys_failed;
+	unsigned		error_limit;
+	unsigned		error_decay;
+	unsigned short		journal_delay_ms;
+	unsigned		verify:1;
+	unsigned		key_merging_disabled:1;
+	unsigned		gc_always_rewrite:1;
+	unsigned		shrinker_disabled:1;
+	unsigned		copy_gc_enabled:1;
+
+#define BUCKET_HASH_BITS	12
+	struct hlist_head	bucket_hash[1 << BUCKET_HASH_BITS];
+};
+
+static inline bool key_merging_disabled(struct cache_set *c)
+{
+#ifdef CONFIG_BCACHE_DEBUG
+	return c->key_merging_disabled;
+#else
+	return 0;
+#endif
+}
+
+struct bbio {
+	unsigned		submit_time_us;
+	union {
+		struct bkey	key;
+		uint64_t	_pad[3];
+		/*
+		 * We only need pad = 3 here because we only ever carry around a
+		 * single pointer - i.e. the pointer we're doing io to/from.
+		 */
+	};
+	struct bio		bio;
+};
+
+static inline unsigned local_clock_us(void)
+{
+	return local_clock() >> 10;
+}
+
+#define MAX_BSETS		4U
+
+#define BTREE_PRIO		USHRT_MAX
+#define INITIAL_PRIO		32768
+
+#define btree_bytes(c)		((c)->btree_pages * PAGE_SIZE)
+#define btree_blocks(b)							\
+	((unsigned) (KEY_SIZE(&b->key) >> (b)->c->block_bits))
+
+#define btree_default_blocks(c)						\
+	((unsigned) ((PAGE_SECTORS * (c)->btree_pages) >> (c)->block_bits))
+
+#define bucket_pages(c)		((c)->sb.bucket_size / PAGE_SECTORS)
+#define bucket_bytes(c)		((c)->sb.bucket_size << 9)
+#define block_bytes(c)		((c)->sb.block_size << 9)
+
+#define __set_bytes(i, k)	(sizeof(*(i)) + (k) * sizeof(uint64_t))
+#define set_bytes(i)		__set_bytes(i, i->keys)
+
+#define __set_blocks(i, k, c)	DIV_ROUND_UP(__set_bytes(i, k), block_bytes(c))
+#define set_blocks(i, c)	__set_blocks(i, (i)->keys, c)
+
+#define node(i, j)		((struct bkey *) ((i)->d + (j)))
+#define end(i)			node(i, (i)->keys)
+
+#define index(i, b)							\
+	((size_t) (((void *) i - (void *) (b)->sets[0].data) /		\
+		   block_bytes(b->c)))
+
+#define btree_data_space(b)	(PAGE_SIZE << (b)->page_order)
+
+#define prios_per_bucket(c)				\
+	((bucket_bytes(c) - sizeof(struct prio_set)) /	\
+	 sizeof(struct bucket_disk))
+#define prio_buckets(c)					\
+	DIV_ROUND_UP((size_t) (c)->sb.nbuckets, prios_per_bucket(c))
+
+#define JSET_MAGIC		0x245235c1a3625032ULL
+#define PSET_MAGIC		0x6750e15f87337f91ULL
+#define BSET_MAGIC		0x90135c78b99e07f5ULL
+
+#define jset_magic(c)		((c)->sb.set_magic ^ JSET_MAGIC)
+#define pset_magic(c)		((c)->sb.set_magic ^ PSET_MAGIC)
+#define bset_magic(c)		((c)->sb.set_magic ^ BSET_MAGIC)
+
+/* Bkey fields: all units are in sectors */
+
+#define KEY_FIELD(name, field, offset, size)				\
+	BITMASK(name, struct bkey, field, offset, size)
+
+#define PTR_FIELD(name, offset, size)					\
+	static inline uint64_t name(const struct bkey *k, unsigned i)	\
+	{ return (k->ptr[i] >> offset) & ~(((uint64_t) ~0) << size); }	\
+									\
+	static inline void SET_##name(struct bkey *k, unsigned i, uint64_t v)\
+	{								\
+		k->ptr[i] &= ~(~((uint64_t) ~0 << size) << offset);	\
+		k->ptr[i] |= v << offset;				\
+	}
+
+KEY_FIELD(KEY_PTRS,	high, 60, 3)
+KEY_FIELD(HEADER_SIZE,	high, 58, 2)
+KEY_FIELD(KEY_CSUM,	high, 56, 2)
+KEY_FIELD(KEY_PINNED,	high, 55, 1)
+KEY_FIELD(KEY_DIRTY,	high, 36, 1)
+
+KEY_FIELD(KEY_SIZE,	high, 20, 16)
+KEY_FIELD(KEY_INODE,	high, 0,  20)
+
+/* Next time I change the on disk format, KEY_OFFSET() won't be 64 bits */
+
+static inline uint64_t KEY_OFFSET(const struct bkey *k)
+{
+	return k->low;
+}
+
+static inline void SET_KEY_OFFSET(struct bkey *k, uint64_t v)
+{
+	k->low = v;
+}
+
+PTR_FIELD(PTR_DEV,		51, 12)
+PTR_FIELD(PTR_OFFSET,		8,  43)
+PTR_FIELD(PTR_GEN,		0,  8)
+
+#define PTR_CHECK_DEV		((1 << 12) - 1)
+
+#define PTR(gen, offset, dev)						\
+	((((uint64_t) dev) << 51) | ((uint64_t) offset) << 8 | gen)
+
+static inline size_t sector_to_bucket(struct cache_set *c, sector_t s)
+{
+	return s >> c->bucket_bits;
+}
+
+static inline sector_t bucket_to_sector(struct cache_set *c, size_t b)
+{
+	return ((sector_t) b) << c->bucket_bits;
+}
+
+static inline sector_t bucket_remainder(struct cache_set *c, sector_t s)
+{
+	return s & (c->sb.bucket_size - 1);
+}
+
+static inline struct cache *PTR_CACHE(struct cache_set *c,
+				      const struct bkey *k,
+				      unsigned ptr)
+{
+	return c->cache[PTR_DEV(k, ptr)];
+}
+
+static inline size_t PTR_BUCKET_NR(struct cache_set *c,
+				   const struct bkey *k,
+				   unsigned ptr)
+{
+	return sector_to_bucket(c, PTR_OFFSET(k, ptr));
+}
+
+static inline struct bucket *PTR_BUCKET(struct cache_set *c,
+					const struct bkey *k,
+					unsigned ptr)
+{
+	return PTR_CACHE(c, k, ptr)->buckets + PTR_BUCKET_NR(c, k, ptr);
+}
+
+/* Btree key macros */
+
+/*
+ * The high bit being set is a relic from when we used it to do binary
+ * searches - it told you where a key started. It's not used anymore,
+ * and can probably be safely dropped.
+ */
+#define KEY(dev, sector, len)						\
+((struct bkey) {							\
+	.high = (1ULL << 63) | ((uint64_t) (len) << 20) | (dev),	\
+	.low = (sector)							\
+})
+
+static inline void bkey_init(struct bkey *k)
+{
+	*k = KEY(0, 0, 0);
+}
+
+#define KEY_START(k)		(KEY_OFFSET(k) - KEY_SIZE(k))
+#define START_KEY(k)		KEY(KEY_INODE(k), KEY_START(k), 0)
+#define MAX_KEY			KEY(~(~0 << 20), ((uint64_t) ~0) >> 1, 0)
+#define ZERO_KEY		KEY(0, 0, 0)
+
+/*
+ * This is used for various on disk data structures - cache_sb, prio_set, bset,
+ * jset: The checksum is _always_ the first 8 bytes of these structs
+ */
+#define csum_set(i)							\
+	bch_crc64(((void *) (i)) + sizeof(uint64_t),			\
+	      ((void *) end(i)) - (((void *) (i)) + sizeof(uint64_t)))
+
+/* Error handling macros */
+
+#define btree_bug(b, ...)						\
+do {									\
+	if (bch_cache_set_error((b)->c, __VA_ARGS__))			\
+		dump_stack();						\
+} while (0)
+
+#define cache_bug(c, ...)						\
+do {									\
+	if (bch_cache_set_error(c, __VA_ARGS__))			\
+		dump_stack();						\
+} while (0)
+
+#define btree_bug_on(cond, b, ...)					\
+do {									\
+	if (cond)							\
+		btree_bug(b, __VA_ARGS__);				\
+} while (0)
+
+#define cache_bug_on(cond, c, ...)					\
+do {									\
+	if (cond)							\
+		cache_bug(c, __VA_ARGS__);				\
+} while (0)
+
+#define cache_set_err_on(cond, c, ...)					\
+do {									\
+	if (cond)							\
+		bch_cache_set_error(c, __VA_ARGS__);			\
+} while (0)
+
+/* Looping macros */
+
+#define for_each_cache(ca, cs, iter)					\
+	for (iter = 0; ca = cs->cache[iter], iter < (cs)->sb.nr_in_set; iter++)
+
+#define for_each_bucket(b, ca)						\
+	for (b = (ca)->buckets + (ca)->sb.first_bucket;			\
+	     b < (ca)->buckets + (ca)->sb.nbuckets; b++)
+
+static inline void __bkey_put(struct cache_set *c, struct bkey *k)
+{
+	unsigned i;
+
+	for (i = 0; i < KEY_PTRS(k); i++)
+		atomic_dec_bug(&PTR_BUCKET(c, k, i)->pin);
+}
+
+/* Blktrace macros */
+
+#define blktrace_msg(c, fmt, ...)					\
+do {									\
+	struct request_queue *q = bdev_get_queue(c->bdev);		\
+	if (q)								\
+		blk_add_trace_msg(q, fmt, ##__VA_ARGS__);		\
+} while (0)
+
+#define blktrace_msg_all(s, fmt, ...)					\
+do {									\
+	struct cache *_c;						\
+	unsigned i;							\
+	for_each_cache(_c, (s), i)					\
+		blktrace_msg(_c, fmt, ##__VA_ARGS__);			\
+} while (0)
+
+static inline void cached_dev_put(struct cached_dev *dc)
+{
+	if (atomic_dec_and_test(&dc->count))
+		schedule_work(&dc->detach);
+}
+
+static inline bool cached_dev_get(struct cached_dev *dc)
+{
+	if (!atomic_inc_not_zero(&dc->count))
+		return false;
+
+	/* Paired with the mb in cached_dev_attach */
+	smp_mb__after_atomic_inc();
+	return true;
+}
+
+/*
+ * bucket_gc_gen() returns the difference between the bucket's current gen and
+ * the oldest gen of any pointer into that bucket in the btree (last_gc).
+ *
+ * bucket_disk_gen() returns the difference between the current gen and the gen
+ * on disk; they're both used to make sure gens don't wrap around.
+ */
+
+static inline uint8_t bucket_gc_gen(struct bucket *b)
+{
+	return b->gen - b->last_gc;
+}
+
+static inline uint8_t bucket_disk_gen(struct bucket *b)
+{
+	return b->gen - b->disk_gen;
+}
+
+#define BUCKET_GC_GEN_MAX	96U
+#define BUCKET_DISK_GEN_MAX	64U
+
+#define kobj_attribute_write(n, fn)					\
+	static struct kobj_attribute ksysfs_##n = __ATTR(n, S_IWUSR, NULL, fn)
+
+#define kobj_attribute_rw(n, show, store)				\
+	static struct kobj_attribute ksysfs_##n =			\
+		__ATTR(n, S_IWUSR|S_IRUSR, show, store)
+
+/* Forward declarations */
+
+void bch_writeback_queue(struct cached_dev *);
+void bch_writeback_add(struct cached_dev *, unsigned);
+
+void bch_count_io_errors(struct cache *, int, const char *);
+void bch_bbio_count_io_errors(struct cache_set *, struct bio *,
+			      int, const char *);
+void bch_bbio_endio(struct cache_set *, struct bio *, int, const char *);
+void bch_bbio_free(struct bio *, struct cache_set *);
+struct bio *bch_bbio_alloc(struct cache_set *);
+
+struct bio *bch_bio_split(struct bio *, int, gfp_t, struct bio_set *);
+void bch_generic_make_request(struct bio *, struct bio_split_pool *);
+void __bch_submit_bbio(struct bio *, struct cache_set *);
+void bch_submit_bbio(struct bio *, struct cache_set *, struct bkey *, unsigned);
+
+uint8_t bch_inc_gen(struct cache *, struct bucket *);
+void bch_rescale_priorities(struct cache_set *, int);
+bool bch_bucket_add_unused(struct cache *, struct bucket *);
+void bch_allocator_thread(struct closure *);
+
+long bch_bucket_alloc(struct cache *, unsigned, struct closure *);
+void bch_bucket_free(struct cache_set *, struct bkey *);
+
+int __bch_bucket_alloc_set(struct cache_set *, unsigned,
+			   struct bkey *, int, struct closure *);
+int bch_bucket_alloc_set(struct cache_set *, unsigned,
+			 struct bkey *, int, struct closure *);
+
+__printf(2, 3)
+bool bch_cache_set_error(struct cache_set *, const char *, ...);
+
+void bch_prio_write(struct cache *);
+void bch_write_bdev_super(struct cached_dev *, struct closure *);
+
+extern struct workqueue_struct *bcache_wq, *bch_gc_wq;
+extern const char * const bch_cache_modes[];
+extern struct mutex bch_register_lock;
+extern struct list_head bch_cache_sets;
+
+extern struct kobj_type bch_cached_dev_ktype;
+extern struct kobj_type bch_flash_dev_ktype;
+extern struct kobj_type bch_cache_set_ktype;
+extern struct kobj_type bch_cache_set_internal_ktype;
+extern struct kobj_type bch_cache_ktype;
+
+void bch_cached_dev_release(struct kobject *);
+void bch_flash_dev_release(struct kobject *);
+void bch_cache_set_release(struct kobject *);
+void bch_cache_release(struct kobject *);
+
+int bch_uuid_write(struct cache_set *);
+void bcache_write_super(struct cache_set *);
+
+int bch_flash_dev_create(struct cache_set *c, uint64_t size);
+
+int bch_cached_dev_attach(struct cached_dev *, struct cache_set *);
+void bch_cached_dev_detach(struct cached_dev *);
+void bch_cached_dev_run(struct cached_dev *);
+void bcache_device_stop(struct bcache_device *);
+
+void bch_cache_set_unregister(struct cache_set *);
+void bch_cache_set_stop(struct cache_set *);
+
+struct cache_set *bch_cache_set_alloc(struct cache_sb *);
+void bch_btree_cache_free(struct cache_set *);
+int bch_btree_cache_alloc(struct cache_set *);
+void bch_writeback_init_cached_dev(struct cached_dev *);
+void bch_moving_init_cache_set(struct cache_set *);
+
+void bch_cache_allocator_exit(struct cache *ca);
+int bch_cache_allocator_init(struct cache *ca);
+
+void bch_debug_exit(void);
+int bch_debug_init(struct kobject *);
+void bch_writeback_exit(void);
+int bch_writeback_init(void);
+void bch_request_exit(void);
+int bch_request_init(void);
+void bch_btree_exit(void);
+int bch_btree_init(void);
+
+#endif /* _BCACHE_H */
diff --git a/drivers/md/bcache/bset.c b/drivers/md/bcache/bset.c
new file mode 100644
index 0000000..0b33aac
--- /dev/null
+++ b/drivers/md/bcache/bset.c
@@ -0,0 +1,1191 @@
+/*
+ * Code for working with individual keys, and sorted sets of keys with in a
+ * btree node
+ *
+ * Copyright 2012 Google, Inc.
+ */
+
+#include "bcache.h"
+#include "btree.h"
+#include "debug.h"
+
+#include <linux/random.h>
+
+/* Keylists */
+
+void bch_keylist_copy(struct keylist *dest, struct keylist *src)
+{
+	*dest = *src;
+
+	if (src->list == src->d) {
+		size_t n = (uint64_t *) src->top - src->d;
+		dest->top = (struct bkey *) &dest->d[n];
+		dest->list = dest->d;
+	}
+}
+
+int bch_keylist_realloc(struct keylist *l, int nptrs, struct cache_set *c)
+{
+	unsigned oldsize = (uint64_t *) l->top - l->list;
+	unsigned newsize = oldsize + 2 + nptrs;
+	uint64_t *new;
+
+	/* The journalling code doesn't handle the case where the keys to insert
+	 * is bigger than an empty write: If we just return -ENOMEM here,
+	 * bio_insert() and bio_invalidate() will insert the keys created so far
+	 * and finish the rest when the keylist is empty.
+	 */
+	if (newsize * sizeof(uint64_t) > block_bytes(c) - sizeof(struct jset))
+		return -ENOMEM;
+
+	newsize = roundup_pow_of_two(newsize);
+
+	if (newsize <= KEYLIST_INLINE ||
+	    roundup_pow_of_two(oldsize) == newsize)
+		return 0;
+
+	new = krealloc(l->list == l->d ? NULL : l->list,
+		       sizeof(uint64_t) * newsize, GFP_NOIO);
+
+	if (!new)
+		return -ENOMEM;
+
+	if (l->list == l->d)
+		memcpy(new, l->list, sizeof(uint64_t) * KEYLIST_INLINE);
+
+	l->list = new;
+	l->top = (struct bkey *) (&l->list[oldsize]);
+
+	return 0;
+}
+
+struct bkey *bch_keylist_pop(struct keylist *l)
+{
+	struct bkey *k = l->bottom;
+
+	if (k == l->top)
+		return NULL;
+
+	while (bkey_next(k) != l->top)
+		k = bkey_next(k);
+
+	return l->top = k;
+}
+
+/* Pointer validation */
+
+bool __bch_ptr_invalid(struct cache_set *c, int level, const struct bkey *k)
+{
+	unsigned i;
+
+	if (level && (!KEY_PTRS(k) || !KEY_SIZE(k) || KEY_DIRTY(k)))
+		goto bad;
+
+	if (!level && KEY_SIZE(k) > KEY_OFFSET(k))
+		goto bad;
+
+	if (!KEY_SIZE(k))
+		return true;
+
+	for (i = 0; i < KEY_PTRS(k); i++)
+		if (ptr_available(c, k, i)) {
+			struct cache *ca = PTR_CACHE(c, k, i);
+			size_t bucket = PTR_BUCKET_NR(c, k, i);
+			size_t r = bucket_remainder(c, PTR_OFFSET(k, i));
+
+			if (KEY_SIZE(k) + r > c->sb.bucket_size ||
+			    bucket <  ca->sb.first_bucket ||
+			    bucket >= ca->sb.nbuckets)
+				goto bad;
+		}
+
+	return false;
+bad:
+	cache_bug(c, "spotted bad key %s: %s", pkey(k), bch_ptr_status(c, k));
+	return true;
+}
+
+bool bch_ptr_bad(struct btree *b, const struct bkey *k)
+{
+	struct bucket *g;
+	unsigned i, stale;
+
+	if (!bkey_cmp(k, &ZERO_KEY) ||
+	    !KEY_PTRS(k) ||
+	    bch_ptr_invalid(b, k))
+		return true;
+
+	if (KEY_PTRS(k) && PTR_DEV(k, 0) == PTR_CHECK_DEV)
+		return true;
+
+	for (i = 0; i < KEY_PTRS(k); i++)
+		if (ptr_available(b->c, k, i)) {
+			g = PTR_BUCKET(b->c, k, i);
+			stale = ptr_stale(b->c, k, i);
+
+			btree_bug_on(stale > 96, b,
+				     "key too stale: %i, need_gc %u",
+				     stale, b->c->need_gc);
+
+			btree_bug_on(stale && KEY_DIRTY(k) && KEY_SIZE(k),
+				     b, "stale dirty pointer");
+
+			if (stale)
+				return true;
+
+#ifdef CONFIG_BCACHE_EDEBUG
+			if (!mutex_trylock(&b->c->bucket_lock))
+				continue;
+
+			if (b->level) {
+				if (KEY_DIRTY(k) ||
+				    g->prio != BTREE_PRIO ||
+				    (b->c->gc_mark_valid &&
+				     GC_MARK(g) != GC_MARK_METADATA))
+					goto bug;
+
+			} else {
+				if (g->prio == BTREE_PRIO)
+					goto bug;
+
+				if (KEY_DIRTY(k) &&
+				    b->c->gc_mark_valid &&
+				    GC_MARK(g) != GC_MARK_DIRTY)
+					goto bug;
+			}
+			mutex_unlock(&b->c->bucket_lock);
+#endif
+		}
+
+	return false;
+#ifdef CONFIG_BCACHE_EDEBUG
+bug:
+	mutex_unlock(&b->c->bucket_lock);
+	btree_bug(b,
+"inconsistent pointer %s: bucket %zu pin %i prio %i gen %i last_gc %i mark %llu gc_gen %i",
+		  pkey(k), PTR_BUCKET_NR(b->c, k, i), atomic_read(&g->pin),
+		  g->prio, g->gen, g->last_gc, GC_MARK(g), g->gc_gen);
+	return true;
+#endif
+}
+
+/* Key/pointer manipulation */
+
+void bch_bkey_copy_single_ptr(struct bkey *dest, const struct bkey *src,
+			      unsigned i)
+{
+	BUG_ON(i > KEY_PTRS(src));
+
+	/* Only copy the header, key, and one pointer. */
+	memcpy(dest, src, 2 * sizeof(uint64_t));
+	dest->ptr[0] = src->ptr[i];
+	SET_KEY_PTRS(dest, 1);
+	/* We didn't copy the checksum so clear that bit. */
+	SET_KEY_CSUM(dest, 0);
+}
+
+bool __bch_cut_front(const struct bkey *where, struct bkey *k)
+{
+	unsigned i, len = 0;
+
+	if (bkey_cmp(where, &START_KEY(k)) <= 0)
+		return false;
+
+	if (bkey_cmp(where, k) < 0)
+		len = KEY_OFFSET(k) - KEY_OFFSET(where);
+	else
+		bkey_copy_key(k, where);
+
+	for (i = 0; i < KEY_PTRS(k); i++)
+		SET_PTR_OFFSET(k, i, PTR_OFFSET(k, i) + KEY_SIZE(k) - len);
+
+	BUG_ON(len > KEY_SIZE(k));
+	SET_KEY_SIZE(k, len);
+	return true;
+}
+
+bool __bch_cut_back(const struct bkey *where, struct bkey *k)
+{
+	unsigned len = 0;
+
+	if (bkey_cmp(where, k) >= 0)
+		return false;
+
+	BUG_ON(KEY_INODE(where) != KEY_INODE(k));
+
+	if (bkey_cmp(where, &START_KEY(k)) > 0)
+		len = KEY_OFFSET(where) - KEY_START(k);
+
+	bkey_copy_key(k, where);
+
+	BUG_ON(len > KEY_SIZE(k));
+	SET_KEY_SIZE(k, len);
+	return true;
+}
+
+static uint64_t merge_chksums(struct bkey *l, struct bkey *r)
+{
+	return (l->ptr[KEY_PTRS(l)] + r->ptr[KEY_PTRS(r)]) &
+		~((uint64_t)1 << 63);
+}
+
+/* Tries to merge l and r: l should be lower than r
+ * Returns true if we were able to merge. If we did merge, l will be the merged
+ * key, r will be untouched.
+ */
+bool bch_bkey_try_merge(struct btree *b, struct bkey *l, struct bkey *r)
+{
+	unsigned i;
+
+	if (key_merging_disabled(b->c))
+		return false;
+
+	if (KEY_PTRS(l) != KEY_PTRS(r) ||
+	    KEY_DIRTY(l) != KEY_DIRTY(r) ||
+	    bkey_cmp(l, &START_KEY(r)))
+		return false;
+
+	for (i = 0; i < KEY_PTRS(l); i++)
+		if (l->ptr[i] + PTR(0, KEY_SIZE(l), 0) != r->ptr[i] ||
+		    PTR_BUCKET_NR(b->c, l, i) != PTR_BUCKET_NR(b->c, r, i))
+			return false;
+
+	/* Keys with no pointers aren't restricted to one bucket and could
+	 * overflow KEY_SIZE
+	 */
+	if (KEY_SIZE(l) + KEY_SIZE(r) > USHRT_MAX) {
+		SET_KEY_OFFSET(l, KEY_OFFSET(l) + USHRT_MAX - KEY_SIZE(l));
+		SET_KEY_SIZE(l, USHRT_MAX);
+
+		bch_cut_front(l, r);
+		return false;
+	}
+
+	if (KEY_CSUM(l)) {
+		if (KEY_CSUM(r))
+			l->ptr[KEY_PTRS(l)] = merge_chksums(l, r);
+		else
+			SET_KEY_CSUM(l, 0);
+	}
+
+	SET_KEY_OFFSET(l, KEY_OFFSET(l) + KEY_SIZE(r));
+	SET_KEY_SIZE(l, KEY_SIZE(l) + KEY_SIZE(r));
+
+	return true;
+}
+
+/* Binary tree stuff for auxiliary search trees */
+
+static unsigned inorder_next(unsigned j, unsigned size)
+{
+	if (j * 2 + 1 < size) {
+		j = j * 2 + 1;
+
+		while (j * 2 < size)
+			j *= 2;
+	} else
+		j >>= ffz(j) + 1;
+
+	return j;
+}
+
+static unsigned inorder_prev(unsigned j, unsigned size)
+{
+	if (j * 2 < size) {
+		j = j * 2;
+
+		while (j * 2 + 1 < size)
+			j = j * 2 + 1;
+	} else
+		j >>= ffs(j);
+
+	return j;
+}
+
+/* I have no idea why this code works... and I'm the one who wrote it
+ *
+ * However, I do know what it does:
+ * Given a binary tree constructed in an array (i.e. how you normally implement
+ * a heap), it converts a node in the tree - referenced by array index - to the
+ * index it would have if you did an inorder traversal.
+ *
+ * Also tested for every j, size up to size somewhere around 6 million.
+ *
+ * The binary tree starts at array index 1, not 0
+ * extra is a function of size:
+ *   extra = (size - rounddown_pow_of_two(size - 1)) << 1;
+ */
+static unsigned __to_inorder(unsigned j, unsigned size, unsigned extra)
+{
+	unsigned b = fls(j);
+	unsigned shift = fls(size - 1) - b;
+
+	j  ^= 1U << (b - 1);
+	j <<= 1;
+	j  |= 1;
+	j <<= shift;
+
+	if (j > extra)
+		j -= (j - extra) >> 1;
+
+	return j;
+}
+
+static unsigned to_inorder(unsigned j, struct bset_tree *t)
+{
+	return __to_inorder(j, t->size, t->extra);
+}
+
+static unsigned __inorder_to_tree(unsigned j, unsigned size, unsigned extra)
+{
+	unsigned shift;
+
+	if (j > extra)
+		j += j - extra;
+
+	shift = ffs(j);
+
+	j >>= shift;
+	j  |= roundup_pow_of_two(size) >> shift;
+
+	return j;
+}
+
+static unsigned inorder_to_tree(unsigned j, struct bset_tree *t)
+{
+	return __inorder_to_tree(j, t->size, t->extra);
+}
+
+#if 0
+void inorder_test(void)
+{
+	unsigned long done = 0;
+	ktime_t start = ktime_get();
+
+	for (unsigned size = 2;
+	     size < 65536000;
+	     size++) {
+		unsigned extra = (size - rounddown_pow_of_two(size - 1)) << 1;
+		unsigned i = 1, j = rounddown_pow_of_two(size - 1);
+
+		if (!(size % 4096))
+			printk(KERN_NOTICE "loop %u, %llu per us\n", size,
+			       done / ktime_us_delta(ktime_get(), start));
+
+		while (1) {
+			if (__inorder_to_tree(i, size, extra) != j)
+				panic("size %10u j %10u i %10u", size, j, i);
+
+			if (__to_inorder(j, size, extra) != i)
+				panic("size %10u j %10u i %10u", size, j, i);
+
+			if (j == rounddown_pow_of_two(size) - 1)
+				break;
+
+			BUG_ON(inorder_prev(inorder_next(j, size), size) != j);
+
+			j = inorder_next(j, size);
+			i++;
+		}
+
+		done += size - 1;
+	}
+}
+#endif
+
+/*
+ * Cacheline/offset <-> bkey pointer arithmatic:
+ *
+ * t->tree is a binary search tree in an array; each node corresponds to a key
+ * in one cacheline in t->set (BSET_CACHELINE bytes).
+ *
+ * This means we don't have to store the full index of the key that a node in
+ * the binary tree points to; to_inorder() gives us the cacheline, and then
+ * bkey_float->m gives us the offset within that cacheline, in units of 8 bytes.
+ *
+ * cacheline_to_bkey() and friends abstract out all the pointer arithmatic to
+ * make this work.
+ *
+ * To construct the bfloat for an arbitrary key we need to know what the key
+ * immediately preceding it is: we have to check if the two keys differ in the
+ * bits we're going to store in bkey_float->mantissa. t->prev[j] stores the size
+ * of the previous key so we can walk backwards to it from t->tree[j]'s key.
+ */
+
+static struct bkey *cacheline_to_bkey(struct bset_tree *t, unsigned cacheline,
+				      unsigned offset)
+{
+	return ((void *) t->data) + cacheline * BSET_CACHELINE + offset * 8;
+}
+
+static unsigned bkey_to_cacheline(struct bset_tree *t, struct bkey *k)
+{
+	return ((void *) k - (void *) t->data) / BSET_CACHELINE;
+}
+
+static unsigned bkey_to_cacheline_offset(struct bkey *k)
+{
+	return ((size_t) k & (BSET_CACHELINE - 1)) / sizeof(uint64_t);
+}
+
+static struct bkey *tree_to_bkey(struct bset_tree *t, unsigned j)
+{
+	return cacheline_to_bkey(t, to_inorder(j, t), t->tree[j].m);
+}
+
+static struct bkey *tree_to_prev_bkey(struct bset_tree *t, unsigned j)
+{
+	return (void *) (((uint64_t *) tree_to_bkey(t, j)) - t->prev[j]);
+}
+
+/*
+ * For the write set - the one we're currently inserting keys into - we don't
+ * maintain a full search tree, we just keep a simple lookup table in t->prev.
+ */
+static struct bkey *table_to_bkey(struct bset_tree *t, unsigned cacheline)
+{
+	return cacheline_to_bkey(t, cacheline, t->prev[cacheline]);
+}
+
+static inline uint64_t shrd128(uint64_t high, uint64_t low, uint8_t shift)
+{
+#ifdef CONFIG_X86_64
+	asm("shrd %[shift],%[high],%[low]"
+	    : [low] "+Rm" (low)
+	    : [high] "R" (high),
+	    [shift] "ci" (shift)
+	    : "cc");
+#else
+	low >>= shift;
+	low  |= (high << 1) << (63U - shift);
+#endif
+	return low;
+}
+
+static inline unsigned bfloat_mantissa(const struct bkey *k,
+				       struct bkey_float *f)
+{
+	const uint64_t *p = &k->low - (f->exponent >> 6);
+	return shrd128(p[-1], p[0], f->exponent & 63) & BKEY_MANTISSA_MASK;
+}
+
+static void make_bfloat(struct bset_tree *t, unsigned j)
+{
+	struct bkey_float *f = &t->tree[j];
+	struct bkey *m = tree_to_bkey(t, j);
+	struct bkey *p = tree_to_prev_bkey(t, j);
+
+	struct bkey *l = is_power_of_2(j)
+		? t->data->start
+		: tree_to_prev_bkey(t, j >> ffs(j));
+
+	struct bkey *r = is_power_of_2(j + 1)
+		? node(t->data, t->data->keys - bkey_u64s(&t->end))
+		: tree_to_bkey(t, j >> (ffz(j) + 1));
+
+	BUG_ON(m < l || m > r);
+	BUG_ON(bkey_next(p) != m);
+
+	if (KEY_INODE(l) != KEY_INODE(r))
+		f->exponent = fls64(KEY_INODE(r) ^ KEY_INODE(l)) + 64;
+	else
+		f->exponent = fls64(r->low ^ l->low);
+
+	f->exponent = max_t(int, f->exponent - BKEY_MANTISSA_BITS, 0);
+
+	/*
+	 * Setting f->exponent = 127 flags this node as failed, and causes the
+	 * lookup code to fall back to comparing against the original key.
+	 */
+
+	if (bfloat_mantissa(m, f) != bfloat_mantissa(p, f))
+		f->mantissa = bfloat_mantissa(m, f) - 1;
+	else
+		f->exponent = 127;
+}
+
+static void bset_alloc_tree(struct btree *b, struct bset_tree *t)
+{
+	if (t != b->sets) {
+		unsigned j = roundup(t[-1].size,
+				     64 / sizeof(struct bkey_float));
+
+		t->tree = t[-1].tree + j;
+		t->prev = t[-1].prev + j;
+	}
+
+	while (t < b->sets + MAX_BSETS)
+		t++->size = 0;
+}
+
+static void bset_build_unwritten_tree(struct btree *b)
+{
+	struct bset_tree *t = b->sets + b->nsets;
+
+	bset_alloc_tree(b, t);
+
+	if (t->tree != b->sets->tree + bset_tree_space(b)) {
+		t->prev[0] = bkey_to_cacheline_offset(t->data->start);
+		t->size = 1;
+	}
+}
+
+static void bset_build_written_tree(struct btree *b)
+{
+	struct bset_tree *t = b->sets + b->nsets;
+	struct bkey *k = t->data->start;
+	unsigned j, cacheline = 1;
+
+	bset_alloc_tree(b, t);
+
+	t->size = min_t(unsigned,
+			bkey_to_cacheline(t, end(t->data)),
+			b->sets->tree + bset_tree_space(b) - t->tree);
+
+	if (t->size < 2) {
+		t->size = 0;
+		return;
+	}
+
+	t->extra = (t->size - rounddown_pow_of_two(t->size - 1)) << 1;
+
+	/* First we figure out where the first key in each cacheline is */
+	for (j = inorder_next(0, t->size);
+	     j;
+	     j = inorder_next(j, t->size)) {
+		while (bkey_to_cacheline(t, k) != cacheline)
+			k = bkey_next(k);
+
+		t->prev[j] = bkey_u64s(k);
+		k = bkey_next(k);
+		cacheline++;
+		t->tree[j].m = bkey_to_cacheline_offset(k);
+	}
+
+	while (bkey_next(k) != end(t->data))
+		k = bkey_next(k);
+
+	t->end = *k;
+
+	/* Then we build the tree */
+	for (j = inorder_next(0, t->size);
+	     j;
+	     j = inorder_next(j, t->size))
+		make_bfloat(t, j);
+}
+
+void bch_bset_fix_invalidated_key(struct btree *b, struct bkey *k)
+{
+	struct bset_tree *t;
+	unsigned inorder, j = 1;
+
+	for (t = b->sets; t <= &b->sets[b->nsets]; t++)
+		if (k < end(t->data))
+			goto found_set;
+
+	BUG();
+found_set:
+	if (!t->size || !bset_written(b, t))
+		return;
+
+	inorder = bkey_to_cacheline(t, k);
+
+	if (k == t->data->start)
+		goto fix_left;
+
+	if (bkey_next(k) == end(t->data)) {
+		t->end = *k;
+		goto fix_right;
+	}
+
+	j = inorder_to_tree(inorder, t);
+
+	if (j &&
+	    j < t->size &&
+	    k == tree_to_bkey(t, j))
+fix_left:	do {
+			make_bfloat(t, j);
+			j = j * 2;
+		} while (j < t->size);
+
+	j = inorder_to_tree(inorder + 1, t);
+
+	if (j &&
+	    j < t->size &&
+	    k == tree_to_prev_bkey(t, j))
+fix_right:	do {
+			make_bfloat(t, j);
+			j = j * 2 + 1;
+		} while (j < t->size);
+}
+
+void bch_bset_fix_lookup_table(struct btree *b, struct bkey *k)
+{
+	struct bset_tree *t = &b->sets[b->nsets];
+	unsigned shift = bkey_u64s(k);
+	unsigned j = bkey_to_cacheline(t, k);
+
+	/* We're getting called from btree_split() or btree_gc, just bail out */
+	if (!t->size)
+		return;
+
+	/* k is the key we just inserted; we need to find the entry in the
+	 * lookup table for the first key that is strictly greater than k:
+	 * it's either k's cacheline or the next one
+	 */
+	if (j < t->size &&
+	    table_to_bkey(t, j) <= k)
+		j++;
+
+	/* Adjust all the lookup table entries, and find a new key for any that
+	 * have gotten too big
+	 */
+	for (; j < t->size; j++) {
+		t->prev[j] += shift;
+
+		if (t->prev[j] > 7) {
+			k = table_to_bkey(t, j - 1);
+
+			while (k < cacheline_to_bkey(t, j, 0))
+				k = bkey_next(k);
+
+			t->prev[j] = bkey_to_cacheline_offset(k);
+		}
+	}
+
+	if (t->size == b->sets->tree + bset_tree_space(b) - t->tree)
+		return;
+
+	/* Possibly add a new entry to the end of the lookup table */
+
+	for (k = table_to_bkey(t, t->size - 1);
+	     k != end(t->data);
+	     k = bkey_next(k))
+		if (t->size == bkey_to_cacheline(t, k)) {
+			t->prev[t->size] = bkey_to_cacheline_offset(k);
+			t->size++;
+		}
+}
+
+void bch_bset_init_next(struct btree *b)
+{
+	struct bset *i = write_block(b);
+
+	if (i != b->sets[0].data) {
+		b->sets[++b->nsets].data = i;
+		i->seq = b->sets[0].data->seq;
+	} else
+		get_random_bytes(&i->seq, sizeof(uint64_t));
+
+	i->magic	= bset_magic(b->c);
+	i->version	= 0;
+	i->keys		= 0;
+
+	bset_build_unwritten_tree(b);
+}
+
+struct bset_search_iter {
+	struct bkey *l, *r;
+};
+
+static struct bset_search_iter bset_search_write_set(struct btree *b,
+						     struct bset_tree *t,
+						     const struct bkey *search)
+{
+	unsigned li = 0, ri = t->size;
+
+	BUG_ON(!b->nsets &&
+	       t->size < bkey_to_cacheline(t, end(t->data)));
+
+	while (li + 1 != ri) {
+		unsigned m = (li + ri) >> 1;
+
+		if (bkey_cmp(table_to_bkey(t, m), search) > 0)
+			ri = m;
+		else
+			li = m;
+	}
+
+	return (struct bset_search_iter) {
+		table_to_bkey(t, li),
+		ri < t->size ? table_to_bkey(t, ri) : end(t->data)
+	};
+}
+
+static struct bset_search_iter bset_search_tree(struct btree *b,
+						struct bset_tree *t,
+						const struct bkey *search)
+{
+	struct bkey *l, *r;
+	struct bkey_float *f;
+	unsigned inorder, j, n = 1;
+
+	do {
+		unsigned p = n << 4;
+		p &= ((int) (p - t->size)) >> 31;
+
+		prefetch(&t->tree[p]);
+
+		j = n;
+		f = &t->tree[j];
+
+		/*
+		 * n = (f->mantissa > bfloat_mantissa())
+		 *	? j * 2
+		 *	: j * 2 + 1;
+		 *
+		 * We need to subtract 1 from f->mantissa for the sign bit trick
+		 * to work  - that's done in make_bfloat()
+		 */
+		if (likely(f->exponent != 127))
+			n = j * 2 + (((unsigned)
+				      (f->mantissa -
+				       bfloat_mantissa(search, f))) >> 31);
+		else
+			n = (bkey_cmp(tree_to_bkey(t, j), search) > 0)
+				? j * 2
+				: j * 2 + 1;
+	} while (n < t->size);
+
+	inorder = to_inorder(j, t);
+
+	/*
+	 * n would have been the node we recursed to - the low bit tells us if
+	 * we recursed left or recursed right.
+	 */
+	if (n & 1) {
+		l = cacheline_to_bkey(t, inorder, f->m);
+
+		if (++inorder != t->size) {
+			f = &t->tree[inorder_next(j, t->size)];
+			r = cacheline_to_bkey(t, inorder, f->m);
+		} else
+			r = end(t->data);
+	} else {
+		r = cacheline_to_bkey(t, inorder, f->m);
+
+		if (--inorder) {
+			f = &t->tree[inorder_prev(j, t->size)];
+			l = cacheline_to_bkey(t, inorder, f->m);
+		} else
+			l = t->data->start;
+	}
+
+	return (struct bset_search_iter) {l, r};
+}
+
+struct bkey *__bch_bset_search(struct btree *b, struct bset_tree *t,
+			       const struct bkey *search)
+{
+	struct bset_search_iter i;
+
+	/*
+	 * First, we search for a cacheline, then lastly we do a linear search
+	 * within that cacheline.
+	 *
+	 * To search for the cacheline, there's three different possibilities:
+	 *  * The set is too small to have a search tree, so we just do a linear
+	 *    search over the whole set.
+	 *  * The set is the one we're currently inserting into; keeping a full
+	 *    auxiliary search tree up to date would be too expensive, so we
+	 *    use a much simpler lookup table to do a binary search -
+	 *    bset_search_write_set().
+	 *  * Or we use the auxiliary search tree we constructed earlier -
+	 *    bset_search_tree()
+	 */
+
+	if (unlikely(!t->size)) {
+		i.l = t->data->start;
+		i.r = end(t->data);
+	} else if (bset_written(b, t)) {
+		/*
+		 * Each node in the auxiliary search tree covers a certain range
+		 * of bits, and keys above and below the set it covers might
+		 * differ outside those bits - so we have to special case the
+		 * start and end - handle that here:
+		 */
+
+		if (unlikely(bkey_cmp(search, &t->end) >= 0))
+			return end(t->data);
+
+		if (unlikely(bkey_cmp(search, t->data->start) < 0))
+			return t->data->start;
+
+		i = bset_search_tree(b, t, search);
+	} else
+		i = bset_search_write_set(b, t, search);
+
+#ifdef CONFIG_BCACHE_EDEBUG
+	BUG_ON(bset_written(b, t) &&
+	       i.l != t->data->start &&
+	       bkey_cmp(tree_to_prev_bkey(t,
+		  inorder_to_tree(bkey_to_cacheline(t, i.l), t)),
+			search) > 0);
+
+	BUG_ON(i.r != end(t->data) &&
+	       bkey_cmp(i.r, search) <= 0);
+#endif
+
+	while (likely(i.l != i.r) &&
+	       bkey_cmp(i.l, search) <= 0)
+		i.l = bkey_next(i.l);
+
+	return i.l;
+}
+
+/* Btree iterator */
+
+static inline bool btree_iter_cmp(struct btree_iter_set l,
+				  struct btree_iter_set r)
+{
+	int64_t c = bkey_cmp(&START_KEY(l.k), &START_KEY(r.k));
+
+	return c ? c > 0 : l.k < r.k;
+}
+
+static inline bool btree_iter_end(struct btree_iter *iter)
+{
+	return !iter->used;
+}
+
+void bch_btree_iter_push(struct btree_iter *iter, struct bkey *k,
+			 struct bkey *end)
+{
+	if (k != end)
+		BUG_ON(!heap_add(iter,
+				 ((struct btree_iter_set) { k, end }),
+				 btree_iter_cmp));
+}
+
+struct bkey *__bch_btree_iter_init(struct btree *b, struct btree_iter *iter,
+			       struct bkey *search, struct bset_tree *start)
+{
+	struct bkey *ret = NULL;
+	iter->size = ARRAY_SIZE(iter->data);
+	iter->used = 0;
+
+	for (; start <= &b->sets[b->nsets]; start++) {
+		ret = bch_bset_search(b, start, search);
+		bch_btree_iter_push(iter, ret, end(start->data));
+	}
+
+	return ret;
+}
+
+struct bkey *bch_btree_iter_next(struct btree_iter *iter)
+{
+	struct btree_iter_set unused;
+	struct bkey *ret = NULL;
+
+	if (!btree_iter_end(iter)) {
+		ret = iter->data->k;
+		iter->data->k = bkey_next(iter->data->k);
+
+		if (iter->data->k > iter->data->end) {
+			__WARN();
+			iter->data->k = iter->data->end;
+		}
+
+		if (iter->data->k == iter->data->end)
+			heap_pop(iter, unused, btree_iter_cmp);
+		else
+			heap_sift(iter, 0, btree_iter_cmp);
+	}
+
+	return ret;
+}
+
+struct bkey *bch_btree_iter_next_filter(struct btree_iter *iter,
+					struct btree *b, ptr_filter_fn fn)
+{
+	struct bkey *ret;
+
+	do {
+		ret = bch_btree_iter_next(iter);
+	} while (ret && fn(b, ret));
+
+	return ret;
+}
+
+struct bkey *bch_next_recurse_key(struct btree *b, struct bkey *search)
+{
+	struct btree_iter iter;
+
+	bch_btree_iter_init(b, &iter, search);
+	return bch_btree_iter_next_filter(&iter, b, bch_ptr_bad);
+}
+
+/* Mergesort */
+
+static void btree_sort_fixup(struct btree_iter *iter)
+{
+	while (iter->used > 1) {
+		struct btree_iter_set *top = iter->data, *i = top + 1;
+		struct bkey *k;
+
+		if (iter->used > 2 &&
+		    btree_iter_cmp(i[0], i[1]))
+			i++;
+
+		for (k = i->k;
+		     k != i->end && bkey_cmp(top->k, &START_KEY(k)) > 0;
+		     k = bkey_next(k))
+			if (top->k > i->k)
+				__bch_cut_front(top->k, k);
+			else if (KEY_SIZE(k))
+				bch_cut_back(&START_KEY(k), top->k);
+
+		if (top->k < i->k || k == i->k)
+			break;
+
+		heap_sift(iter, i - top, btree_iter_cmp);
+	}
+}
+
+static void btree_mergesort(struct btree *b, struct bset *out,
+			    struct btree_iter *iter,
+			    bool fixup, bool remove_stale)
+{
+	struct bkey *k, *last = NULL;
+	bool (*bad)(struct btree *, const struct bkey *) = remove_stale
+		? bch_ptr_bad
+		: bch_ptr_invalid;
+
+	while (!btree_iter_end(iter)) {
+		if (fixup && !b->level)
+			btree_sort_fixup(iter);
+
+		k = bch_btree_iter_next(iter);
+		if (bad(b, k))
+			continue;
+
+		if (!last) {
+			last = out->start;
+			bkey_copy(last, k);
+		} else if (b->level ||
+			   !bch_bkey_try_merge(b, last, k)) {
+			last = bkey_next(last);
+			bkey_copy(last, k);
+		}
+	}
+
+	out->keys = last ? (uint64_t *) bkey_next(last) - out->d : 0;
+
+	pr_debug("sorted %i keys", out->keys);
+	bch_check_key_order(b, out);
+}
+
+static void __btree_sort(struct btree *b, struct btree_iter *iter,
+			 unsigned start, unsigned order, bool fixup)
+{
+	uint64_t start_time;
+	bool remove_stale = !b->written;
+	struct bset *out = (void *) __get_free_pages(__GFP_NOWARN|GFP_NOIO,
+						     order);
+	if (!out) {
+		mutex_lock(&b->c->sort_lock);
+		out = b->c->sort;
+		order = ilog2(bucket_pages(b->c));
+	}
+
+	start_time = local_clock();
+
+	btree_mergesort(b, out, iter, fixup, remove_stale);
+	b->nsets = start;
+
+	if (!fixup && !start && b->written)
+		bch_btree_verify(b, out);
+
+	if (!start && order == b->page_order) {
+		/*
+		 * Our temporary buffer is the same size as the btree node's
+		 * buffer, we can just swap buffers instead of doing a big
+		 * memcpy()
+		 */
+
+		out->magic	= bset_magic(b->c);
+		out->seq	= b->sets[0].data->seq;
+		out->version	= b->sets[0].data->version;
+		swap(out, b->sets[0].data);
+
+		if (b->c->sort == b->sets[0].data)
+			b->c->sort = out;
+	} else {
+		b->sets[start].data->keys = out->keys;
+		memcpy(b->sets[start].data->start, out->start,
+		       (void *) end(out) - (void *) out->start);
+	}
+
+	if (out == b->c->sort)
+		mutex_unlock(&b->c->sort_lock);
+	else
+		free_pages((unsigned long) out, order);
+
+	if (b->written)
+		bset_build_written_tree(b);
+
+	if (!start) {
+		spin_lock(&b->c->sort_time_lock);
+		bch_time_stats_update(&b->c->sort_time, start_time);
+		spin_unlock(&b->c->sort_time_lock);
+	}
+}
+
+void bch_btree_sort_partial(struct btree *b, unsigned start)
+{
+	size_t oldsize = 0, order = b->page_order, keys = 0;
+	struct btree_iter iter;
+	__bch_btree_iter_init(b, &iter, NULL, &b->sets[start]);
+
+	BUG_ON(b->sets[b->nsets].data == write_block(b) &&
+	       (b->sets[b->nsets].size || b->nsets));
+
+	if (b->written)
+		oldsize = bch_count_data(b);
+
+	if (start) {
+		unsigned i;
+
+		for (i = start; i <= b->nsets; i++)
+			keys += b->sets[i].data->keys;
+
+		order = roundup_pow_of_two(__set_bytes(b->sets->data,
+						       keys)) / PAGE_SIZE;
+		if (order)
+			order = ilog2(order);
+	}
+
+	__btree_sort(b, &iter, start, order, false);
+
+	EBUG_ON(b->written && bch_count_data(b) != oldsize);
+}
+
+void bch_btree_sort_and_fix_extents(struct btree *b, struct btree_iter *iter)
+{
+	BUG_ON(!b->written);
+	__btree_sort(b, iter, 0, b->page_order, true);
+}
+
+void bch_btree_sort_into(struct btree *b, struct btree *new)
+{
+	uint64_t start_time = local_clock();
+
+	struct btree_iter iter;
+	bch_btree_iter_init(b, &iter, NULL);
+
+	btree_mergesort(b, new->sets->data, &iter, false, true);
+
+	spin_lock(&b->c->sort_time_lock);
+	bch_time_stats_update(&b->c->sort_time, start_time);
+	spin_unlock(&b->c->sort_time_lock);
+
+	bkey_copy_key(&new->key, &b->key);
+	new->sets->size = 0;
+}
+
+void bch_btree_sort_lazy(struct btree *b)
+{
+	if (b->nsets) {
+		unsigned i, j, keys = 0, total;
+
+		for (i = 0; i <= b->nsets; i++)
+			keys += b->sets[i].data->keys;
+
+		total = keys;
+
+		for (j = 0; j < b->nsets; j++) {
+			if (keys * 2 < total ||
+			    keys < 1000) {
+				bch_btree_sort_partial(b, j);
+				return;
+			}
+
+			keys -= b->sets[j].data->keys;
+		}
+
+		/* Must sort if b->nsets == 3 or we'll overflow */
+		if (b->nsets >= (MAX_BSETS - 1) - b->level) {
+			bch_btree_sort(b);
+			return;
+		}
+	}
+
+	bset_build_written_tree(b);
+}
+
+/* Sysfs stuff */
+
+struct bset_stats {
+	size_t nodes;
+	size_t sets_written, sets_unwritten;
+	size_t bytes_written, bytes_unwritten;
+	size_t floats, failed;
+};
+
+static int bch_btree_bset_stats(struct btree *b, struct btree_op *op,
+			    struct bset_stats *stats)
+{
+	struct bkey *k;
+	unsigned i;
+
+	stats->nodes++;
+
+	for (i = 0; i <= b->nsets; i++) {
+		struct bset_tree *t = &b->sets[i];
+		size_t bytes = t->data->keys * sizeof(uint64_t);
+		size_t j;
+
+		if (bset_written(b, t)) {
+			stats->sets_written++;
+			stats->bytes_written += bytes;
+
+			stats->floats += t->size - 1;
+
+			for (j = 1; j < t->size; j++)
+				if (t->tree[j].exponent == 127)
+					stats->failed++;
+		} else {
+			stats->sets_unwritten++;
+			stats->bytes_unwritten += bytes;
+		}
+	}
+
+	if (b->level) {
+		struct btree_iter iter;
+
+		for_each_key_filter(b, k, &iter, bch_ptr_bad) {
+			int ret = btree(bset_stats, k, b, op, stats);
+			if (ret)
+				return ret;
+		}
+	}
+
+	return 0;
+}
+
+int bch_bset_print_stats(struct cache_set *c, char *buf)
+{
+	struct btree_op op;
+	struct bset_stats t;
+	int ret;
+
+	bch_btree_op_init_stack(&op);
+	memset(&t, 0, sizeof(struct bset_stats));
+
+	ret = btree_root(bset_stats, c, &op, &t);
+	if (ret)
+		return ret;
+
+	return snprintf(buf, PAGE_SIZE,
+			"btree nodes:		%zu\n"
+			"written sets:		%zu\n"
+			"unwritten sets:		%zu\n"
+			"written key bytes:	%zu\n"
+			"unwritten key bytes:	%zu\n"
+			"floats:			%zu\n"
+			"failed:			%zu\n",
+			t.nodes,
+			t.sets_written, t.sets_unwritten,
+			t.bytes_written, t.bytes_unwritten,
+			t.floats, t.failed);
+}
diff --git a/drivers/md/bcache/bset.h b/drivers/md/bcache/bset.h
new file mode 100644
index 0000000..57a9cff
--- /dev/null
+++ b/drivers/md/bcache/bset.h
@@ -0,0 +1,379 @@
+#ifndef _BCACHE_BSET_H
+#define _BCACHE_BSET_H
+
+/*
+ * BKEYS:
+ *
+ * A bkey contains a key, a size field, a variable number of pointers, and some
+ * ancillary flag bits.
+ *
+ * We use two different functions for validating bkeys, bch_ptr_invalid and
+ * bch_ptr_bad().
+ *
+ * bch_ptr_invalid() primarily filters out keys and pointers that would be
+ * invalid due to some sort of bug, whereas bch_ptr_bad() filters out keys and
+ * pointer that occur in normal practice but don't point to real data.
+ *
+ * The one exception to the rule that ptr_invalid() filters out invalid keys is
+ * that it also filters out keys of size 0 - these are keys that have been
+ * completely overwritten. It'd be safe to delete these in memory while leaving
+ * them on disk, just unnecessary work - so we filter them out when resorting
+ * instead.
+ *
+ * We can't filter out stale keys when we're resorting, because garbage
+ * collection needs to find them to ensure bucket gens don't wrap around -
+ * unless we're rewriting the btree node those stale keys still exist on disk.
+ *
+ * We also implement functions here for removing some number of sectors from the
+ * front or the back of a bkey - this is mainly used for fixing overlapping
+ * extents, by removing the overlapping sectors from the older key.
+ *
+ * BSETS:
+ *
+ * A bset is an array of bkeys laid out contiguously in memory in sorted order,
+ * along with a header. A btree node is made up of a number of these, written at
+ * different times.
+ *
+ * There could be many of them on disk, but we never allow there to be more than
+ * 4 in memory - we lazily resort as needed.
+ *
+ * We implement code here for creating and maintaining auxiliary search trees
+ * (described below) for searching an individial bset, and on top of that we
+ * implement a btree iterator.
+ *
+ * BTREE ITERATOR:
+ *
+ * Most of the code in bcache doesn't care about an individual bset - it needs
+ * to search entire btree nodes and iterate over them in sorted order.
+ *
+ * The btree iterator code serves both functions; it iterates through the keys
+ * in a btree node in sorted order, starting from either keys after a specific
+ * point (if you pass it a search key) or the start of the btree node.
+ *
+ * AUXILIARY SEARCH TREES:
+ *
+ * Since keys are variable length, we can't use a binary search on a bset - we
+ * wouldn't be able to find the start of the next key. But binary searches are
+ * slow anyways, due to terrible cache behaviour; bcache originally used binary
+ * searches and that code topped out at under 50k lookups/second.
+ *
+ * So we need to construct some sort of lookup table. Since we only insert keys
+ * into the last (unwritten) set, most of the keys within a given btree node are
+ * usually in sets that are mostly constant. We use two different types of
+ * lookup tables to take advantage of this.
+ *
+ * Both lookup tables share in common that they don't index every key in the
+ * set; they index one key every BSET_CACHELINE bytes, and then a linear search
+ * is used for the rest.
+ *
+ * For sets that have been written to disk and are no longer being inserted
+ * into, we construct a binary search tree in an array - traversing a binary
+ * search tree in an array gives excellent locality of reference and is very
+ * fast, since both children of any node are adjacent to each other in memory
+ * (and their grandchildren, and great grandchildren...) - this means
+ * prefetching can be used to great effect.
+ *
+ * It's quite useful performance wise to keep these nodes small - not just
+ * because they're more likely to be in L2, but also because we can prefetch
+ * more nodes on a single cacheline and thus prefetch more iterations in advance
+ * when traversing this tree.
+ *
+ * Nodes in the auxiliary search tree must contain both a key to compare against
+ * (we don't want to fetch the key from the set, that would defeat the purpose),
+ * and a pointer to the key. We use a few tricks to compress both of these.
+ *
+ * To compress the pointer, we take advantage of the fact that one node in the
+ * search tree corresponds to precisely BSET_CACHELINE bytes in the set. We have
+ * a function (to_inorder()) that takes the index of a node in a binary tree and
+ * returns what its index would be in an inorder traversal, so we only have to
+ * store the low bits of the offset.
+ *
+ * The key is 84 bits (KEY_DEV + key->key, the offset on the device). To
+ * compress that,  we take advantage of the fact that when we're traversing the
+ * search tree at every iteration we know that both our search key and the key
+ * we're looking for lie within some range - bounded by our previous
+ * comparisons. (We special case the start of a search so that this is true even
+ * at the root of the tree).
+ *
+ * So we know the key we're looking for is between a and b, and a and b don't
+ * differ higher than bit 50, we don't need to check anything higher than bit
+ * 50.
+ *
+ * We don't usually need the rest of the bits, either; we only need enough bits
+ * to partition the key range we're currently checking.  Consider key n - the
+ * key our auxiliary search tree node corresponds to, and key p, the key
+ * immediately preceding n.  The lowest bit we need to store in the auxiliary
+ * search tree is the highest bit that differs between n and p.
+ *
+ * Note that this could be bit 0 - we might sometimes need all 80 bits to do the
+ * comparison. But we'd really like our nodes in the auxiliary search tree to be
+ * of fixed size.
+ *
+ * The solution is to make them fixed size, and when we're constructing a node
+ * check if p and n differed in the bits we needed them to. If they don't we
+ * flag that node, and when doing lookups we fallback to comparing against the
+ * real key. As long as this doesn't happen to often (and it seems to reliably
+ * happen a bit less than 1% of the time), we win - even on failures, that key
+ * is then more likely to be in cache than if we were doing binary searches all
+ * the way, since we're touching so much less memory.
+ *
+ * The keys in the auxiliary search tree are stored in (software) floating
+ * point, with an exponent and a mantissa. The exponent needs to be big enough
+ * to address all the bits in the original key, but the number of bits in the
+ * mantissa is somewhat arbitrary; more bits just gets us fewer failures.
+ *
+ * We need 7 bits for the exponent and 3 bits for the key's offset (since keys
+ * are 8 byte aligned); using 22 bits for the mantissa means a node is 4 bytes.
+ * We need one node per 128 bytes in the btree node, which means the auxiliary
+ * search trees take up 3% as much memory as the btree itself.
+ *
+ * Constructing these auxiliary search trees is moderately expensive, and we
+ * don't want to be constantly rebuilding the search tree for the last set
+ * whenever we insert another key into it. For the unwritten set, we use a much
+ * simpler lookup table - it's just a flat array, so index i in the lookup table
+ * corresponds to the i range of BSET_CACHELINE bytes in the set. Indexing
+ * within each byte range works the same as with the auxiliary search trees.
+ *
+ * These are much easier to keep up to date when we insert a key - we do it
+ * somewhat lazily; when we shift a key up we usually just increment the pointer
+ * to it, only when it would overflow do we go to the trouble of finding the
+ * first key in that range of bytes again.
+ */
+
+/* Btree key comparison/iteration */
+
+struct btree_iter {
+	size_t size, used;
+	struct btree_iter_set {
+		struct bkey *k, *end;
+	} data[MAX_BSETS];
+};
+
+struct bset_tree {
+	/*
+	 * We construct a binary tree in an array as if the array
+	 * started at 1, so that things line up on the same cachelines
+	 * better: see comments in bset.c at cacheline_to_bkey() for
+	 * details
+	 */
+
+	/* size of the binary tree and prev array */
+	unsigned	size;
+
+	/* function of size - precalculated for to_inorder() */
+	unsigned	extra;
+
+	/* copy of the last key in the set */
+	struct bkey	end;
+	struct bkey_float *tree;
+
+	/*
+	 * The nodes in the bset tree point to specific keys - this
+	 * array holds the sizes of the previous key.
+	 *
+	 * Conceptually it's a member of struct bkey_float, but we want
+	 * to keep bkey_float to 4 bytes and prev isn't used in the fast
+	 * path.
+	 */
+	uint8_t		*prev;
+
+	/* The actual btree node, with pointers to each sorted set */
+	struct bset	*data;
+};
+
+static __always_inline int64_t bkey_cmp(const struct bkey *l,
+					const struct bkey *r)
+{
+	return unlikely(KEY_INODE(l) != KEY_INODE(r))
+		? (int64_t) KEY_INODE(l) - (int64_t) KEY_INODE(r)
+		: (int64_t) KEY_OFFSET(l) - (int64_t) KEY_OFFSET(r);
+}
+
+static inline size_t bkey_u64s(const struct bkey *k)
+{
+	BUG_ON(KEY_CSUM(k) > 1);
+	return 2 + KEY_PTRS(k) + (KEY_CSUM(k) ? 1 : 0);
+}
+
+static inline size_t bkey_bytes(const struct bkey *k)
+{
+	return bkey_u64s(k) * sizeof(uint64_t);
+}
+
+static inline void bkey_copy(struct bkey *dest, const struct bkey *src)
+{
+	memcpy(dest, src, bkey_bytes(src));
+}
+
+static inline void bkey_copy_key(struct bkey *dest, const struct bkey *src)
+{
+	if (!src)
+		src = &KEY(0, 0, 0);
+
+	SET_KEY_INODE(dest, KEY_INODE(src));
+	SET_KEY_OFFSET(dest, KEY_OFFSET(src));
+}
+
+static inline struct bkey *bkey_next(const struct bkey *k)
+{
+	uint64_t *d = (void *) k;
+	return (struct bkey *) (d + bkey_u64s(k));
+}
+
+/* Keylists */
+
+struct keylist {
+	struct bkey		*top;
+	union {
+		uint64_t		*list;
+		struct bkey		*bottom;
+	};
+
+	/* Enough room for btree_split's keys without realloc */
+#define KEYLIST_INLINE		16
+	uint64_t		d[KEYLIST_INLINE];
+};
+
+static inline void bch_keylist_init(struct keylist *l)
+{
+	l->top = (void *) (l->list = l->d);
+}
+
+static inline void bch_keylist_push(struct keylist *l)
+{
+	l->top = bkey_next(l->top);
+}
+
+static inline void bch_keylist_add(struct keylist *l, struct bkey *k)
+{
+	bkey_copy(l->top, k);
+	bch_keylist_push(l);
+}
+
+static inline bool bch_keylist_empty(struct keylist *l)
+{
+	return l->top == (void *) l->list;
+}
+
+static inline void bch_keylist_free(struct keylist *l)
+{
+	if (l->list != l->d)
+		kfree(l->list);
+}
+
+void bch_keylist_copy(struct keylist *, struct keylist *);
+struct bkey *bch_keylist_pop(struct keylist *);
+int bch_keylist_realloc(struct keylist *, int, struct cache_set *);
+
+void bch_bkey_copy_single_ptr(struct bkey *, const struct bkey *,
+			      unsigned);
+bool __bch_cut_front(const struct bkey *, struct bkey *);
+bool __bch_cut_back(const struct bkey *, struct bkey *);
+
+static inline bool bch_cut_front(const struct bkey *where, struct bkey *k)
+{
+	BUG_ON(bkey_cmp(where, k) > 0);
+	return __bch_cut_front(where, k);
+}
+
+static inline bool bch_cut_back(const struct bkey *where, struct bkey *k)
+{
+	BUG_ON(bkey_cmp(where, &START_KEY(k)) < 0);
+	return __bch_cut_back(where, k);
+}
+
+const char *bch_ptr_status(struct cache_set *, const struct bkey *);
+bool __bch_ptr_invalid(struct cache_set *, int level, const struct bkey *);
+bool bch_ptr_bad(struct btree *, const struct bkey *);
+
+static inline uint8_t gen_after(uint8_t a, uint8_t b)
+{
+	uint8_t r = a - b;
+	return r > 128U ? 0 : r;
+}
+
+static inline uint8_t ptr_stale(struct cache_set *c, const struct bkey *k,
+				unsigned i)
+{
+	return gen_after(PTR_BUCKET(c, k, i)->gen, PTR_GEN(k, i));
+}
+
+static inline bool ptr_available(struct cache_set *c, const struct bkey *k,
+				 unsigned i)
+{
+	return (PTR_DEV(k, i) < MAX_CACHES_PER_SET) && PTR_CACHE(c, k, i);
+}
+
+
+typedef bool (*ptr_filter_fn)(struct btree *, const struct bkey *);
+
+struct bkey *bch_next_recurse_key(struct btree *, struct bkey *);
+struct bkey *bch_btree_iter_next(struct btree_iter *);
+struct bkey *bch_btree_iter_next_filter(struct btree_iter *,
+					struct btree *, ptr_filter_fn);
+
+void bch_btree_iter_push(struct btree_iter *, struct bkey *, struct bkey *);
+struct bkey *__bch_btree_iter_init(struct btree *, struct btree_iter *,
+				   struct bkey *, struct bset_tree *);
+
+/* 32 bits total: */
+#define BKEY_MID_BITS		3
+#define BKEY_EXPONENT_BITS	7
+#define BKEY_MANTISSA_BITS	22
+#define BKEY_MANTISSA_MASK	((1 << BKEY_MANTISSA_BITS) - 1)
+
+struct bkey_float {
+	unsigned	exponent:BKEY_EXPONENT_BITS;
+	unsigned	m:BKEY_MID_BITS;
+	unsigned	mantissa:BKEY_MANTISSA_BITS;
+} __packed;
+
+/*
+ * BSET_CACHELINE was originally intended to match the hardware cacheline size -
+ * it used to be 64, but I realized the lookup code would touch slightly less
+ * memory if it was 128.
+ *
+ * It definites the number of bytes (in struct bset) per struct bkey_float in
+ * the auxiliar search tree - when we're done searching the bset_float tree we
+ * have this many bytes left that we do a linear search over.
+ *
+ * Since (after level 5) every level of the bset_tree is on a new cacheline,
+ * we're touching one fewer cacheline in the bset tree in exchange for one more
+ * cacheline in the linear search - but the linear search might stop before it
+ * gets to the second cacheline.
+ */
+
+#define BSET_CACHELINE		128
+#define bset_tree_space(b)	(btree_data_space(b) / BSET_CACHELINE)
+
+#define bset_tree_bytes(b)	(bset_tree_space(b) * sizeof(struct bkey_float))
+#define bset_prev_bytes(b)	(bset_tree_space(b) * sizeof(uint8_t))
+
+void bch_bset_init_next(struct btree *);
+
+void bch_bset_fix_invalidated_key(struct btree *, struct bkey *);
+void bch_bset_fix_lookup_table(struct btree *, struct bkey *);
+
+struct bkey *__bch_bset_search(struct btree *, struct bset_tree *,
+			   const struct bkey *);
+
+static inline struct bkey *bch_bset_search(struct btree *b, struct bset_tree *t,
+					   const struct bkey *search)
+{
+	return search ? __bch_bset_search(b, t, search) : t->data->start;
+}
+
+bool bch_bkey_try_merge(struct btree *, struct bkey *, struct bkey *);
+void bch_btree_sort_lazy(struct btree *);
+void bch_btree_sort_into(struct btree *, struct btree *);
+void bch_btree_sort_and_fix_extents(struct btree *, struct btree_iter *);
+void bch_btree_sort_partial(struct btree *, unsigned);
+
+static inline void bch_btree_sort(struct btree *b)
+{
+	bch_btree_sort_partial(b, 0);
+}
+
+int bch_bset_print_stats(struct cache_set *, char *);
+
+#endif
diff --git a/drivers/md/bcache/btree.c b/drivers/md/bcache/btree.c
new file mode 100644
index 0000000..17799df
--- /dev/null
+++ b/drivers/md/bcache/btree.c
@@ -0,0 +1,2504 @@
+/*
+ * Copyright (C) 2010 Kent Overstreet <kent.overstreet@gmail.com>
+ *
+ * Uses a block device as cache for other block devices; optimized for SSDs.
+ * All allocation is done in buckets, which should match the erase block size
+ * of the device.
+ *
+ * Buckets containing cached data are kept on a heap sorted by priority;
+ * bucket priority is increased on cache hit, and periodically all the buckets
+ * on the heap have their priority scaled down. This currently is just used as
+ * an LRU but in the future should allow for more intelligent heuristics.
+ *
+ * Buckets have an 8 bit counter; freeing is accomplished by incrementing the
+ * counter. Garbage collection is used to remove stale pointers.
+ *
+ * Indexing is done via a btree; nodes are not necessarily fully sorted, rather
+ * as keys are inserted we only sort the pages that have not yet been written.
+ * When garbage collection is run, we resort the entire node.
+ *
+ * All configuration is done via sysfs; see Documentation/bcache.txt.
+ */
+
+#include "bcache.h"
+#include "btree.h"
+#include "debug.h"
+#include "request.h"
+
+#include <linux/slab.h>
+#include <linux/bitops.h>
+#include <linux/hash.h>
+#include <linux/random.h>
+#include <linux/rcupdate.h>
+#include <trace/events/bcache.h>
+
+/*
+ * Todo:
+ * register_bcache: Return errors out to userspace correctly
+ *
+ * Writeback: don't undirty key until after a cache flush
+ *
+ * Create an iterator for key pointers
+ *
+ * On btree write error, mark bucket such that it won't be freed from the cache
+ *
+ * Journalling:
+ *   Check for bad keys in replay
+ *   Propagate barriers
+ *   Refcount journal entries in journal_replay
+ *
+ * Garbage collection:
+ *   Finish incremental gc
+ *   Gc should free old UUIDs, data for invalid UUIDs
+ *
+ * Provide a way to list backing device UUIDs we have data cached for, and
+ * probably how long it's been since we've seen them, and a way to invalidate
+ * dirty data for devices that will never be attached again
+ *
+ * Keep 1 min/5 min/15 min statistics of how busy a block device has been, so
+ * that based on that and how much dirty data we have we can keep writeback
+ * from being starved
+ *
+ * Add a tracepoint or somesuch to watch for writeback starvation
+ *
+ * When btree depth > 1 and splitting an interior node, we have to make sure
+ * alloc_bucket() cannot fail. This should be true but is not completely
+ * obvious.
+ *
+ * Make sure all allocations get charged to the root cgroup
+ *
+ * Plugging?
+ *
+ * If data write is less than hard sector size of ssd, round up offset in open
+ * bucket to the next whole sector
+ *
+ * Also lookup by cgroup in get_open_bucket()
+ *
+ * Superblock needs to be fleshed out for multiple cache devices
+ *
+ * Add a sysfs tunable for the number of writeback IOs in flight
+ *
+ * Add a sysfs tunable for the number of open data buckets
+ *
+ * IO tracking: Can we track when one process is doing io on behalf of another?
+ * IO tracking: Don't use just an average, weigh more recent stuff higher
+ *
+ * Test module load/unload
+ */
+
+static const char * const op_types[] = {
+	"insert", "replace"
+};
+
+static const char *op_type(struct btree_op *op)
+{
+	return op_types[op->type];
+}
+
+#define MAX_NEED_GC		64
+#define MAX_SAVE_PRIO		72
+
+#define PTR_DIRTY_BIT		(((uint64_t) 1 << 36))
+
+#define PTR_HASH(c, k)							\
+	(((k)->ptr[0] >> c->bucket_bits) | PTR_GEN(k, 0))
+
+struct workqueue_struct *bch_gc_wq;
+static struct workqueue_struct *btree_io_wq;
+
+void bch_btree_op_init_stack(struct btree_op *op)
+{
+	memset(op, 0, sizeof(struct btree_op));
+	closure_init_stack(&op->cl);
+	op->lock = -1;
+	bch_keylist_init(&op->keys);
+}
+
+/* Btree key manipulation */
+
+static void bkey_put(struct cache_set *c, struct bkey *k, int level)
+{
+	if ((level && KEY_OFFSET(k)) || !level)
+		__bkey_put(c, k);
+}
+
+/* Btree IO */
+
+static uint64_t btree_csum_set(struct btree *b, struct bset *i)
+{
+	uint64_t crc = b->key.ptr[0];
+	void *data = (void *) i + 8, *end = end(i);
+
+	crc = bch_crc64_update(crc, data, end - data);
+	return crc ^ 0xffffffffffffffff;
+}
+
+static void btree_bio_endio(struct bio *bio, int error,
+			    struct batch_complete *batch)
+{
+	struct closure *cl = bio->bi_private;
+	struct btree *b = container_of(cl, struct btree, io.cl);
+
+	if (error)
+		set_btree_node_io_error(b);
+
+	bch_bbio_count_io_errors(b->c, bio, error, (bio->bi_rw & WRITE)
+				 ? "writing btree" : "reading btree");
+	closure_put(cl);
+}
+
+static void btree_bio_init(struct btree *b)
+{
+	BUG_ON(b->bio);
+	b->bio = bch_bbio_alloc(b->c);
+
+	b->bio->bi_end_io	= btree_bio_endio;
+	b->bio->bi_private	= &b->io.cl;
+}
+
+void bch_btree_read_done(struct closure *cl)
+{
+	struct btree *b = container_of(cl, struct btree, io.cl);
+	struct bset *i = b->sets[0].data;
+	struct btree_iter *iter = b->c->fill_iter;
+	const char *err = "bad btree header";
+	BUG_ON(b->nsets || b->written);
+
+	bch_bbio_free(b->bio, b->c);
+	b->bio = NULL;
+
+	mutex_lock(&b->c->fill_lock);
+	iter->used = 0;
+
+	if (btree_node_io_error(b) ||
+	    !i->seq)
+		goto err;
+
+	for (;
+	     b->written < btree_blocks(b) && i->seq == b->sets[0].data->seq;
+	     i = write_block(b)) {
+		err = "unsupported bset version";
+		if (i->version > BCACHE_BSET_VERSION)
+			goto err;
+
+		err = "bad btree header";
+		if (b->written + set_blocks(i, b->c) > btree_blocks(b))
+			goto err;
+
+		err = "bad magic";
+		if (i->magic != bset_magic(b->c))
+			goto err;
+
+		err = "bad checksum";
+		switch (i->version) {
+		case 0:
+			if (i->csum != csum_set(i))
+				goto err;
+			break;
+		case BCACHE_BSET_VERSION:
+			if (i->csum != btree_csum_set(b, i))
+				goto err;
+			break;
+		}
+
+		err = "empty set";
+		if (i != b->sets[0].data && !i->keys)
+			goto err;
+
+		bch_btree_iter_push(iter, i->start, end(i));
+
+		b->written += set_blocks(i, b->c);
+	}
+
+	err = "corrupted btree";
+	for (i = write_block(b);
+	     index(i, b) < btree_blocks(b);
+	     i = ((void *) i) + block_bytes(b->c))
+		if (i->seq == b->sets[0].data->seq)
+			goto err;
+
+	bch_btree_sort_and_fix_extents(b, iter);
+
+	i = b->sets[0].data;
+	err = "short btree key";
+	if (b->sets[0].size &&
+	    bkey_cmp(&b->key, &b->sets[0].end) < 0)
+		goto err;
+
+	if (b->written < btree_blocks(b))
+		bch_bset_init_next(b);
+out:
+
+	mutex_unlock(&b->c->fill_lock);
+
+	spin_lock(&b->c->btree_read_time_lock);
+	bch_time_stats_update(&b->c->btree_read_time, b->io_start_time);
+	spin_unlock(&b->c->btree_read_time_lock);
+
+	smp_wmb(); /* read_done is our write lock */
+	set_btree_node_read_done(b);
+
+	closure_return(cl);
+err:
+	set_btree_node_io_error(b);
+	bch_cache_set_error(b->c, "%s at bucket %zu, block %zu, %u keys",
+			    err, PTR_BUCKET_NR(b->c, &b->key, 0),
+			    index(i, b), i->keys);
+	goto out;
+}
+
+void bch_btree_read(struct btree *b)
+{
+	BUG_ON(b->nsets || b->written);
+
+	if (!closure_trylock(&b->io.cl, &b->c->cl))
+		BUG();
+
+	b->io_start_time = local_clock();
+
+	btree_bio_init(b);
+	b->bio->bi_rw	= REQ_META|READ_SYNC;
+	b->bio->bi_size	= KEY_SIZE(&b->key) << 9;
+
+	bch_bio_map(b->bio, b->sets[0].data);
+
+	pr_debug("%s", pbtree(b));
+	trace_bcache_btree_read(b->bio);
+	bch_submit_bbio(b->bio, b->c, &b->key, 0);
+
+	continue_at(&b->io.cl, bch_btree_read_done, system_wq);
+}
+
+static void btree_complete_write(struct btree *b, struct btree_write *w)
+{
+	if (w->prio_blocked &&
+	    !atomic_sub_return(w->prio_blocked, &b->c->prio_blocked))
+		wake_up(&b->c->alloc_wait);
+
+	if (w->journal) {
+		atomic_dec_bug(w->journal);
+		__closure_wake_up(&b->c->journal.wait);
+	}
+
+	if (w->owner)
+		closure_put(w->owner);
+
+	w->prio_blocked	= 0;
+	w->journal	= NULL;
+	w->owner	= NULL;
+}
+
+static void __btree_write_done(struct closure *cl)
+{
+	struct btree *b = container_of(cl, struct btree, io.cl);
+	struct btree_write *w = btree_prev_write(b);
+
+	bch_bbio_free(b->bio, b->c);
+	b->bio = NULL;
+	btree_complete_write(b, w);
+
+	if (btree_node_dirty(b))
+		queue_delayed_work(btree_io_wq, &b->work,
+				   msecs_to_jiffies(30000));
+
+	closure_return(cl);
+}
+
+static void btree_write_done(struct closure *cl)
+{
+	struct btree *b = container_of(cl, struct btree, io.cl);
+	struct bio_vec *bv;
+	int n;
+
+	__bio_for_each_segment(bv, b->bio, n, 0)
+		__free_page(bv->bv_page);
+
+	__btree_write_done(cl);
+}
+
+static void do_btree_write(struct btree *b)
+{
+	struct closure *cl = &b->io.cl;
+	struct bset *i = b->sets[b->nsets].data;
+	BKEY_PADDED(key) k;
+
+	i->version	= BCACHE_BSET_VERSION;
+	i->csum		= btree_csum_set(b, i);
+
+	btree_bio_init(b);
+	b->bio->bi_rw	= REQ_META|WRITE_SYNC;
+	b->bio->bi_size	= set_blocks(i, b->c) * block_bytes(b->c);
+	bch_bio_map(b->bio, i);
+
+	bkey_copy(&k.key, &b->key);
+	SET_PTR_OFFSET(&k.key, 0, PTR_OFFSET(&k.key, 0) + bset_offset(b, i));
+
+	if (!bch_bio_alloc_pages(b->bio, GFP_NOIO)) {
+		int j;
+		struct bio_vec *bv;
+		void *base = (void *) ((unsigned long) i & ~(PAGE_SIZE - 1));
+
+		bio_for_each_segment(bv, b->bio, j)
+			memcpy(page_address(bv->bv_page),
+			       base + j * PAGE_SIZE, PAGE_SIZE);
+
+		trace_bcache_btree_write(b->bio);
+		bch_submit_bbio(b->bio, b->c, &k.key, 0);
+
+		continue_at(cl, btree_write_done, NULL);
+	} else {
+		b->bio->bi_vcnt = 0;
+		bch_bio_map(b->bio, i);
+
+		trace_bcache_btree_write(b->bio);
+		bch_submit_bbio(b->bio, b->c, &k.key, 0);
+
+		closure_sync(cl);
+		__btree_write_done(cl);
+	}
+}
+
+static void __btree_write(struct btree *b)
+{
+	struct bset *i = b->sets[b->nsets].data;
+
+	BUG_ON(current->bio_list);
+
+	closure_lock(&b->io, &b->c->cl);
+	cancel_delayed_work(&b->work);
+
+	clear_bit(BTREE_NODE_dirty,	 &b->flags);
+	change_bit(BTREE_NODE_write_idx, &b->flags);
+
+	bch_check_key_order(b, i);
+	BUG_ON(b->written && !i->keys);
+
+	do_btree_write(b);
+
+	pr_debug("%s block %i keys %i", pbtree(b), b->written, i->keys);
+
+	b->written += set_blocks(i, b->c);
+	atomic_long_add(set_blocks(i, b->c) * b->c->sb.block_size,
+			&PTR_CACHE(b->c, &b->key, 0)->btree_sectors_written);
+
+	bch_btree_sort_lazy(b);
+
+	if (b->written < btree_blocks(b))
+		bch_bset_init_next(b);
+}
+
+static void btree_write_work(struct work_struct *w)
+{
+	struct btree *b = container_of(to_delayed_work(w), struct btree, work);
+
+	down_write(&b->lock);
+
+	if (btree_node_dirty(b))
+		__btree_write(b);
+	up_write(&b->lock);
+}
+
+void bch_btree_write(struct btree *b, bool now, struct btree_op *op)
+{
+	struct bset *i = b->sets[b->nsets].data;
+	struct btree_write *w = btree_current_write(b);
+
+	BUG_ON(b->written &&
+	       (b->written >= btree_blocks(b) ||
+		i->seq != b->sets[0].data->seq ||
+		!i->keys));
+
+	if (!btree_node_dirty(b)) {
+		set_btree_node_dirty(b);
+		queue_delayed_work(btree_io_wq, &b->work,
+				   msecs_to_jiffies(30000));
+	}
+
+	w->prio_blocked += b->prio_blocked;
+	b->prio_blocked = 0;
+
+	if (op && op->journal && !b->level) {
+		if (w->journal &&
+		    journal_pin_cmp(b->c, w, op)) {
+			atomic_dec_bug(w->journal);
+			w->journal = NULL;
+		}
+
+		if (!w->journal) {
+			w->journal = op->journal;
+			atomic_inc(w->journal);
+		}
+	}
+
+	if (current->bio_list)
+		return;
+
+	/* Force write if set is too big */
+	if (now ||
+	    b->level ||
+	    set_bytes(i) > PAGE_SIZE - 48) {
+		if (op && now) {
+			/* Must wait on multiple writes */
+			BUG_ON(w->owner);
+			w->owner = &op->cl;
+			closure_get(&op->cl);
+		}
+
+		__btree_write(b);
+	}
+	BUG_ON(!b->written);
+}
+
+/*
+ * Btree in memory cache - allocation/freeing
+ * mca -> memory cache
+ */
+
+static void mca_reinit(struct btree *b)
+{
+	unsigned i;
+
+	b->flags	= 0;
+	b->written	= 0;
+	b->nsets	= 0;
+
+	for (i = 0; i < MAX_BSETS; i++)
+		b->sets[i].size = 0;
+	/*
+	 * Second loop starts at 1 because b->sets[0]->data is the memory we
+	 * allocated
+	 */
+	for (i = 1; i < MAX_BSETS; i++)
+		b->sets[i].data = NULL;
+}
+
+#define mca_reserve(c)	(((c->root && c->root->level)		\
+			  ? c->root->level : 1) * 8 + 16)
+#define mca_can_free(c)						\
+	max_t(int, 0, c->bucket_cache_used - mca_reserve(c))
+
+static void mca_data_free(struct btree *b)
+{
+	struct bset_tree *t = b->sets;
+	BUG_ON(!closure_is_unlocked(&b->io.cl));
+
+	if (bset_prev_bytes(b) < PAGE_SIZE)
+		kfree(t->prev);
+	else
+		free_pages((unsigned long) t->prev,
+			   get_order(bset_prev_bytes(b)));
+
+	if (bset_tree_bytes(b) < PAGE_SIZE)
+		kfree(t->tree);
+	else
+		free_pages((unsigned long) t->tree,
+			   get_order(bset_tree_bytes(b)));
+
+	free_pages((unsigned long) t->data, b->page_order);
+
+	t->prev = NULL;
+	t->tree = NULL;
+	t->data = NULL;
+	list_move(&b->list, &b->c->btree_cache_freed);
+	b->c->bucket_cache_used--;
+}
+
+static void mca_bucket_free(struct btree *b)
+{
+	BUG_ON(btree_node_dirty(b));
+
+	b->key.ptr[0] = 0;
+	hlist_del_init_rcu(&b->hash);
+	list_move(&b->list, &b->c->btree_cache_freeable);
+}
+
+static unsigned btree_order(struct bkey *k)
+{
+	return ilog2(KEY_SIZE(k) / PAGE_SECTORS ?: 1);
+}
+
+static void mca_data_alloc(struct btree *b, struct bkey *k, gfp_t gfp)
+{
+	struct bset_tree *t = b->sets;
+	BUG_ON(t->data);
+
+	b->page_order = max_t(unsigned,
+			      ilog2(b->c->btree_pages),
+			      btree_order(k));
+
+	t->data = (void *) __get_free_pages(gfp, b->page_order);
+	if (!t->data)
+		goto err;
+
+	t->tree = bset_tree_bytes(b) < PAGE_SIZE
+		? kmalloc(bset_tree_bytes(b), gfp)
+		: (void *) __get_free_pages(gfp, get_order(bset_tree_bytes(b)));
+	if (!t->tree)
+		goto err;
+
+	t->prev = bset_prev_bytes(b) < PAGE_SIZE
+		? kmalloc(bset_prev_bytes(b), gfp)
+		: (void *) __get_free_pages(gfp, get_order(bset_prev_bytes(b)));
+	if (!t->prev)
+		goto err;
+
+	list_move(&b->list, &b->c->btree_cache);
+	b->c->bucket_cache_used++;
+	return;
+err:
+	mca_data_free(b);
+}
+
+static struct btree *mca_bucket_alloc(struct cache_set *c,
+				      struct bkey *k, gfp_t gfp)
+{
+	struct btree *b = kzalloc(sizeof(struct btree), gfp);
+	if (!b)
+		return NULL;
+
+	init_rwsem(&b->lock);
+	lockdep_set_novalidate_class(&b->lock);
+	INIT_LIST_HEAD(&b->list);
+	INIT_DELAYED_WORK(&b->work, btree_write_work);
+	b->c = c;
+	closure_init_unlocked(&b->io);
+
+	mca_data_alloc(b, k, gfp);
+	return b;
+}
+
+static int mca_reap(struct btree *b, struct closure *cl, unsigned min_order)
+{
+	lockdep_assert_held(&b->c->bucket_lock);
+
+	if (!down_write_trylock(&b->lock))
+		return -ENOMEM;
+
+	if (b->page_order < min_order) {
+		rw_unlock(true, b);
+		return -ENOMEM;
+	}
+
+	BUG_ON(btree_node_dirty(b) && !b->sets[0].data);
+
+	if (cl && btree_node_dirty(b))
+		bch_btree_write(b, true, NULL);
+
+	if (cl)
+		closure_wait_event_async(&b->io.wait, cl,
+			 atomic_read(&b->io.cl.remaining) == -1);
+
+	if (btree_node_dirty(b) ||
+	    !closure_is_unlocked(&b->io.cl) ||
+	    work_pending(&b->work.work)) {
+		rw_unlock(true, b);
+		return -EAGAIN;
+	}
+
+	return 0;
+}
+
+static int bch_mca_shrink(struct shrinker *shrink, struct shrink_control *sc)
+{
+	struct cache_set *c = container_of(shrink, struct cache_set, shrink);
+	struct btree *b, *t;
+	unsigned long i, nr = sc->nr_to_scan;
+
+	if (c->shrinker_disabled)
+		return 0;
+
+	if (c->try_harder)
+		return 0;
+
+	/*
+	 * If nr == 0, we're supposed to return the number of items we have
+	 * cached. Not allowed to return -1.
+	 */
+	if (!nr)
+		return mca_can_free(c) * c->btree_pages;
+
+	/* Return -1 if we can't do anything right now */
+	if (sc->gfp_mask & __GFP_WAIT)
+		mutex_lock(&c->bucket_lock);
+	else if (!mutex_trylock(&c->bucket_lock))
+		return -1;
+
+	nr /= c->btree_pages;
+	nr = min_t(unsigned long, nr, mca_can_free(c));
+
+	i = 0;
+	list_for_each_entry_safe(b, t, &c->btree_cache_freeable, list) {
+		if (!nr)
+			break;
+
+		if (++i > 3 &&
+		    !mca_reap(b, NULL, 0)) {
+			mca_data_free(b);
+			rw_unlock(true, b);
+			--nr;
+		}
+	}
+
+	/*
+	 * Can happen right when we first start up, before we've read in any
+	 * btree nodes
+	 */
+	if (list_empty(&c->btree_cache))
+		goto out;
+
+	for (i = 0; nr && i < c->bucket_cache_used; i++) {
+		b = list_first_entry(&c->btree_cache, struct btree, list);
+		list_rotate_left(&c->btree_cache);
+
+		if (!b->accessed &&
+		    !mca_reap(b, NULL, 0)) {
+			mca_bucket_free(b);
+			mca_data_free(b);
+			rw_unlock(true, b);
+			--nr;
+		} else
+			b->accessed = 0;
+	}
+out:
+	nr = mca_can_free(c) * c->btree_pages;
+	mutex_unlock(&c->bucket_lock);
+	return nr;
+}
+
+void bch_btree_cache_free(struct cache_set *c)
+{
+	struct btree *b;
+	struct closure cl;
+	closure_init_stack(&cl);
+
+	if (c->shrink.list.next)
+		unregister_shrinker(&c->shrink);
+
+	mutex_lock(&c->bucket_lock);
+
+#ifdef CONFIG_BCACHE_DEBUG
+	if (c->verify_data)
+		list_move(&c->verify_data->list, &c->btree_cache);
+#endif
+
+	list_splice(&c->btree_cache_freeable,
+		    &c->btree_cache);
+
+	while (!list_empty(&c->btree_cache)) {
+		b = list_first_entry(&c->btree_cache, struct btree, list);
+
+		if (btree_node_dirty(b))
+			btree_complete_write(b, btree_current_write(b));
+		clear_bit(BTREE_NODE_dirty, &b->flags);
+
+		mca_data_free(b);
+	}
+
+	while (!list_empty(&c->btree_cache_freed)) {
+		b = list_first_entry(&c->btree_cache_freed,
+				     struct btree, list);
+		list_del(&b->list);
+		cancel_delayed_work_sync(&b->work);
+		kfree(b);
+	}
+
+	mutex_unlock(&c->bucket_lock);
+}
+
+int bch_btree_cache_alloc(struct cache_set *c)
+{
+	unsigned i;
+
+	/* XXX: doesn't check for errors */
+
+	closure_init_unlocked(&c->gc);
+
+	for (i = 0; i < mca_reserve(c); i++)
+		mca_bucket_alloc(c, &ZERO_KEY, GFP_KERNEL);
+
+	list_splice_init(&c->btree_cache,
+			 &c->btree_cache_freeable);
+
+#ifdef CONFIG_BCACHE_DEBUG
+	mutex_init(&c->verify_lock);
+
+	c->verify_data = mca_bucket_alloc(c, &ZERO_KEY, GFP_KERNEL);
+
+	if (c->verify_data &&
+	    c->verify_data->sets[0].data)
+		list_del_init(&c->verify_data->list);
+	else
+		c->verify_data = NULL;
+#endif
+
+	c->shrink.shrink = bch_mca_shrink;
+	c->shrink.seeks = 4;
+	c->shrink.batch = c->btree_pages * 2;
+	register_shrinker(&c->shrink);
+
+	return 0;
+}
+
+/* Btree in memory cache - hash table */
+
+static struct hlist_head *mca_hash(struct cache_set *c, struct bkey *k)
+{
+	return &c->bucket_hash[hash_32(PTR_HASH(c, k), BUCKET_HASH_BITS)];
+}
+
+static struct btree *mca_find(struct cache_set *c, struct bkey *k)
+{
+	struct btree *b;
+
+	rcu_read_lock();
+	hlist_for_each_entry_rcu(b, mca_hash(c, k), hash)
+		if (PTR_HASH(c, &b->key) == PTR_HASH(c, k))
+			goto out;
+	b = NULL;
+out:
+	rcu_read_unlock();
+	return b;
+}
+
+static struct btree *mca_cannibalize(struct cache_set *c, struct bkey *k,
+				     int level, struct closure *cl)
+{
+	int ret = -ENOMEM;
+	struct btree *i;
+
+	if (!cl)
+		return ERR_PTR(-ENOMEM);
+
+	/*
+	 * Trying to free up some memory - i.e. reuse some btree nodes - may
+	 * require initiating IO to flush the dirty part of the node. If we're
+	 * running under generic_make_request(), that IO will never finish and
+	 * we would deadlock. Returning -EAGAIN causes the cache lookup code to
+	 * punt to workqueue and retry.
+	 */
+	if (current->bio_list)
+		return ERR_PTR(-EAGAIN);
+
+	if (c->try_harder && c->try_harder != cl) {
+		closure_wait_event_async(&c->try_wait, cl, !c->try_harder);
+		return ERR_PTR(-EAGAIN);
+	}
+
+	/* XXX: tracepoint */
+	c->try_harder = cl;
+	c->try_harder_start = local_clock();
+retry:
+	list_for_each_entry_reverse(i, &c->btree_cache, list) {
+		int r = mca_reap(i, cl, btree_order(k));
+		if (!r)
+			return i;
+		if (r != -ENOMEM)
+			ret = r;
+	}
+
+	if (ret == -EAGAIN &&
+	    closure_blocking(cl)) {
+		mutex_unlock(&c->bucket_lock);
+		closure_sync(cl);
+		mutex_lock(&c->bucket_lock);
+		goto retry;
+	}
+
+	return ERR_PTR(ret);
+}
+
+/*
+ * We can only have one thread cannibalizing other cached btree nodes at a time,
+ * or we'll deadlock. We use an open coded mutex to ensure that, which a
+ * cannibalize_bucket() will take. This means every time we unlock the root of
+ * the btree, we need to release this lock if we have it held.
+ */
+void bch_cannibalize_unlock(struct cache_set *c, struct closure *cl)
+{
+	if (c->try_harder == cl) {
+		bch_time_stats_update(&c->try_harder_time, c->try_harder_start);
+		c->try_harder = NULL;
+		__closure_wake_up(&c->try_wait);
+	}
+}
+
+static struct btree *mca_alloc(struct cache_set *c, struct bkey *k,
+			       int level, struct closure *cl)
+{
+	struct btree *b;
+
+	lockdep_assert_held(&c->bucket_lock);
+
+	if (mca_find(c, k))
+		return NULL;
+
+	/* btree_free() doesn't free memory; it sticks the node on the end of
+	 * the list. Check if there's any freed nodes there:
+	 */
+	list_for_each_entry(b, &c->btree_cache_freeable, list)
+		if (!mca_reap(b, NULL, btree_order(k)))
+			goto out;
+
+	/* We never free struct btree itself, just the memory that holds the on
+	 * disk node. Check the freed list before allocating a new one:
+	 */
+	list_for_each_entry(b, &c->btree_cache_freed, list)
+		if (!mca_reap(b, NULL, 0)) {
+			mca_data_alloc(b, k, __GFP_NOWARN|GFP_NOIO);
+			if (!b->sets[0].data)
+				goto err;
+			else
+				goto out;
+		}
+
+	b = mca_bucket_alloc(c, k, __GFP_NOWARN|GFP_NOIO);
+	if (!b)
+		goto err;
+
+	BUG_ON(!down_write_trylock(&b->lock));
+	if (!b->sets->data)
+		goto err;
+out:
+	BUG_ON(!closure_is_unlocked(&b->io.cl));
+
+	bkey_copy(&b->key, k);
+	list_move(&b->list, &c->btree_cache);
+	hlist_del_init_rcu(&b->hash);
+	hlist_add_head_rcu(&b->hash, mca_hash(c, k));
+
+	lock_set_subclass(&b->lock.dep_map, level + 1, _THIS_IP_);
+	b->level	= level;
+
+	mca_reinit(b);
+
+	return b;
+err:
+	if (b)
+		rw_unlock(true, b);
+
+	b = mca_cannibalize(c, k, level, cl);
+	if (!IS_ERR(b))
+		goto out;
+
+	return b;
+}
+
+/**
+ * bch_btree_node_get - find a btree node in the cache and lock it, reading it
+ * in from disk if necessary.
+ *
+ * If IO is necessary, it uses the closure embedded in struct btree_op to wait;
+ * if that closure is in non blocking mode, will return -EAGAIN.
+ *
+ * The btree node will have either a read or a write lock held, depending on
+ * level and op->lock.
+ */
+struct btree *bch_btree_node_get(struct cache_set *c, struct bkey *k,
+				 int level, struct btree_op *op)
+{
+	int i = 0;
+	bool write = level <= op->lock;
+	struct btree *b;
+
+	BUG_ON(level < 0);
+retry:
+	b = mca_find(c, k);
+
+	if (!b) {
+		mutex_lock(&c->bucket_lock);
+		b = mca_alloc(c, k, level, &op->cl);
+		mutex_unlock(&c->bucket_lock);
+
+		if (!b)
+			goto retry;
+		if (IS_ERR(b))
+			return b;
+
+		bch_btree_read(b);
+
+		if (!write)
+			downgrade_write(&b->lock);
+	} else {
+		rw_lock(write, b, level);
+		if (PTR_HASH(c, &b->key) != PTR_HASH(c, k)) {
+			rw_unlock(write, b);
+			goto retry;
+		}
+		BUG_ON(b->level != level);
+	}
+
+	b->accessed = 1;
+
+	for (; i <= b->nsets && b->sets[i].size; i++) {
+		prefetch(b->sets[i].tree);
+		prefetch(b->sets[i].data);
+	}
+
+	for (; i <= b->nsets; i++)
+		prefetch(b->sets[i].data);
+
+	if (!closure_wait_event(&b->io.wait, &op->cl,
+				btree_node_read_done(b))) {
+		rw_unlock(write, b);
+		b = ERR_PTR(-EAGAIN);
+	} else if (btree_node_io_error(b)) {
+		rw_unlock(write, b);
+		b = ERR_PTR(-EIO);
+	} else
+		BUG_ON(!b->written);
+
+	return b;
+}
+
+static void btree_node_prefetch(struct cache_set *c, struct bkey *k, int level)
+{
+	struct btree *b;
+
+	mutex_lock(&c->bucket_lock);
+	b = mca_alloc(c, k, level, NULL);
+	mutex_unlock(&c->bucket_lock);
+
+	if (!IS_ERR_OR_NULL(b)) {
+		bch_btree_read(b);
+		rw_unlock(true, b);
+	}
+}
+
+/* Btree alloc */
+
+static void btree_node_free(struct btree *b, struct btree_op *op)
+{
+	unsigned i;
+
+	/*
+	 * The BUG_ON() in btree_node_get() implies that we must have a write
+	 * lock on parent to free or even invalidate a node
+	 */
+	BUG_ON(op->lock <= b->level);
+	BUG_ON(b == b->c->root);
+	pr_debug("bucket %s", pbtree(b));
+
+	if (btree_node_dirty(b))
+		btree_complete_write(b, btree_current_write(b));
+	clear_bit(BTREE_NODE_dirty, &b->flags);
+
+	if (b->prio_blocked &&
+	    !atomic_sub_return(b->prio_blocked, &b->c->prio_blocked))
+		closure_wake_up(&b->c->bucket_wait);
+
+	b->prio_blocked = 0;
+
+	cancel_delayed_work(&b->work);
+
+	mutex_lock(&b->c->bucket_lock);
+
+	for (i = 0; i < KEY_PTRS(&b->key); i++) {
+		BUG_ON(atomic_read(&PTR_BUCKET(b->c, &b->key, i)->pin));
+
+		bch_inc_gen(PTR_CACHE(b->c, &b->key, i),
+			    PTR_BUCKET(b->c, &b->key, i));
+	}
+
+	bch_bucket_free(b->c, &b->key);
+	mca_bucket_free(b);
+	mutex_unlock(&b->c->bucket_lock);
+}
+
+struct btree *bch_btree_node_alloc(struct cache_set *c, int level,
+				   struct closure *cl)
+{
+	BKEY_PADDED(key) k;
+	struct btree *b = ERR_PTR(-EAGAIN);
+
+	mutex_lock(&c->bucket_lock);
+retry:
+	if (__bch_bucket_alloc_set(c, WATERMARK_METADATA, &k.key, 1, cl))
+		goto err;
+
+	SET_KEY_SIZE(&k.key, c->btree_pages * PAGE_SECTORS);
+
+	b = mca_alloc(c, &k.key, level, cl);
+	if (IS_ERR(b))
+		goto err_free;
+
+	if (!b) {
+		cache_bug(c,
+			"Tried to allocate bucket that was in btree cache");
+		__bkey_put(c, &k.key);
+		goto retry;
+	}
+
+	set_btree_node_read_done(b);
+	b->accessed = 1;
+	bch_bset_init_next(b);
+
+	mutex_unlock(&c->bucket_lock);
+	return b;
+err_free:
+	bch_bucket_free(c, &k.key);
+	__bkey_put(c, &k.key);
+err:
+	mutex_unlock(&c->bucket_lock);
+	return b;
+}
+
+static struct btree *btree_node_alloc_replacement(struct btree *b,
+						  struct closure *cl)
+{
+	struct btree *n = bch_btree_node_alloc(b->c, b->level, cl);
+	if (!IS_ERR_OR_NULL(n))
+		bch_btree_sort_into(b, n);
+
+	return n;
+}
+
+/* Garbage collection */
+
+uint8_t __bch_btree_mark_key(struct cache_set *c, int level, struct bkey *k)
+{
+	uint8_t stale = 0;
+	unsigned i;
+	struct bucket *g;
+
+	/*
+	 * ptr_invalid() can't return true for the keys that mark btree nodes as
+	 * freed, but since ptr_bad() returns true we'll never actually use them
+	 * for anything and thus we don't want mark their pointers here
+	 */
+	if (!bkey_cmp(k, &ZERO_KEY))
+		return stale;
+
+	for (i = 0; i < KEY_PTRS(k); i++) {
+		if (!ptr_available(c, k, i))
+			continue;
+
+		g = PTR_BUCKET(c, k, i);
+
+		if (gen_after(g->gc_gen, PTR_GEN(k, i)))
+			g->gc_gen = PTR_GEN(k, i);
+
+		if (ptr_stale(c, k, i)) {
+			stale = max(stale, ptr_stale(c, k, i));
+			continue;
+		}
+
+		cache_bug_on(GC_MARK(g) &&
+			     (GC_MARK(g) == GC_MARK_METADATA) != (level != 0),
+			     c, "inconsistent ptrs: mark = %llu, level = %i",
+			     GC_MARK(g), level);
+
+		if (level)
+			SET_GC_MARK(g, GC_MARK_METADATA);
+		else if (KEY_DIRTY(k))
+			SET_GC_MARK(g, GC_MARK_DIRTY);
+
+		/* guard against overflow */
+		SET_GC_SECTORS_USED(g, min_t(unsigned,
+					     GC_SECTORS_USED(g) + KEY_SIZE(k),
+					     (1 << 14) - 1));
+
+		BUG_ON(!GC_SECTORS_USED(g));
+	}
+
+	return stale;
+}
+
+#define btree_mark_key(b, k)	__bch_btree_mark_key(b->c, b->level, k)
+
+static int btree_gc_mark_node(struct btree *b, unsigned *keys,
+			      struct gc_stat *gc)
+{
+	uint8_t stale = 0;
+	unsigned last_dev = -1;
+	struct bcache_device *d = NULL;
+	struct bkey *k;
+	struct btree_iter iter;
+	struct bset_tree *t;
+
+	gc->nodes++;
+
+	for_each_key_filter(b, k, &iter, bch_ptr_invalid) {
+		if (last_dev != KEY_INODE(k)) {
+			last_dev = KEY_INODE(k);
+
+			d = KEY_INODE(k) < b->c->nr_uuids
+				? b->c->devices[last_dev]
+				: NULL;
+		}
+
+		stale = max(stale, btree_mark_key(b, k));
+
+		if (bch_ptr_bad(b, k))
+			continue;
+
+		*keys += bkey_u64s(k);
+
+		gc->key_bytes += bkey_u64s(k);
+		gc->nkeys++;
+
+		gc->data += KEY_SIZE(k);
+		if (KEY_DIRTY(k)) {
+			gc->dirty += KEY_SIZE(k);
+			if (d)
+				d->sectors_dirty_gc += KEY_SIZE(k);
+		}
+	}
+
+	for (t = b->sets; t <= &b->sets[b->nsets]; t++)
+		btree_bug_on(t->size &&
+			     bset_written(b, t) &&
+			     bkey_cmp(&b->key, &t->end) < 0,
+			     b, "found short btree key in gc");
+
+	return stale;
+}
+
+static struct btree *btree_gc_alloc(struct btree *b, struct bkey *k,
+				    struct btree_op *op)
+{
+	/*
+	 * We block priorities from being written for the duration of garbage
+	 * collection, so we can't sleep in btree_alloc() ->
+	 * bch_bucket_alloc_set(), or we'd risk deadlock - so we don't pass it
+	 * our closure.
+	 */
+	struct btree *n = btree_node_alloc_replacement(b, NULL);
+
+	if (!IS_ERR_OR_NULL(n)) {
+		swap(b, n);
+
+		memcpy(k->ptr, b->key.ptr,
+		       sizeof(uint64_t) * KEY_PTRS(&b->key));
+
+		__bkey_put(b->c, &b->key);
+		atomic_inc(&b->c->prio_blocked);
+		b->prio_blocked++;
+
+		btree_node_free(n, op);
+		up_write(&n->lock);
+	}
+
+	return b;
+}
+
+/*
+ * Leaving this at 2 until we've got incremental garbage collection done; it
+ * could be higher (and has been tested with 4) except that garbage collection
+ * could take much longer, adversely affecting latency.
+ */
+#define GC_MERGE_NODES	2U
+
+struct gc_merge_info {
+	struct btree	*b;
+	struct bkey	*k;
+	unsigned	keys;
+};
+
+static void btree_gc_coalesce(struct btree *b, struct btree_op *op,
+			      struct gc_stat *gc, struct gc_merge_info *r)
+{
+	unsigned nodes = 0, keys = 0, blocks;
+	int i;
+
+	while (nodes < GC_MERGE_NODES && r[nodes].b)
+		keys += r[nodes++].keys;
+
+	blocks = btree_default_blocks(b->c) * 2 / 3;
+
+	if (nodes < 2 ||
+	    __set_blocks(b->sets[0].data, keys, b->c) > blocks * (nodes - 1))
+		return;
+
+	for (i = nodes - 1; i >= 0; --i) {
+		if (r[i].b->written)
+			r[i].b = btree_gc_alloc(r[i].b, r[i].k, op);
+
+		if (r[i].b->written)
+			return;
+	}
+
+	for (i = nodes - 1; i > 0; --i) {
+		struct bset *n1 = r[i].b->sets->data;
+		struct bset *n2 = r[i - 1].b->sets->data;
+		struct bkey *k, *last = NULL;
+
+		keys = 0;
+
+		if (i == 1) {
+			/*
+			 * Last node we're not getting rid of - we're getting
+			 * rid of the node at r[0]. Have to try and fit all of
+			 * the remaining keys into this node; we can't ensure
+			 * they will always fit due to rounding and variable
+			 * length keys (shouldn't be possible in practice,
+			 * though)
+			 */
+			if (__set_blocks(n1, n1->keys + r->keys,
+					 b->c) > btree_blocks(r[i].b))
+				return;
+
+			keys = n2->keys;
+			last = &r->b->key;
+		} else
+			for (k = n2->start;
+			     k < end(n2);
+			     k = bkey_next(k)) {
+				if (__set_blocks(n1, n1->keys + keys +
+						 bkey_u64s(k), b->c) > blocks)
+					break;
+
+				last = k;
+				keys += bkey_u64s(k);
+			}
+
+		BUG_ON(__set_blocks(n1, n1->keys + keys,
+				    b->c) > btree_blocks(r[i].b));
+
+		if (last) {
+			bkey_copy_key(&r[i].b->key, last);
+			bkey_copy_key(r[i].k, last);
+		}
+
+		memcpy(end(n1),
+		       n2->start,
+		       (void *) node(n2, keys) - (void *) n2->start);
+
+		n1->keys += keys;
+
+		memmove(n2->start,
+			node(n2, keys),
+			(void *) end(n2) - (void *) node(n2, keys));
+
+		n2->keys -= keys;
+
+		r[i].keys	= n1->keys;
+		r[i - 1].keys	= n2->keys;
+	}
+
+	btree_node_free(r->b, op);
+	up_write(&r->b->lock);
+
+	pr_debug("coalesced %u nodes", nodes);
+
+	gc->nodes--;
+	nodes--;
+
+	memmove(&r[0], &r[1], sizeof(struct gc_merge_info) * nodes);
+	memset(&r[nodes], 0, sizeof(struct gc_merge_info));
+}
+
+static int btree_gc_recurse(struct btree *b, struct btree_op *op,
+			    struct closure *writes, struct gc_stat *gc)
+{
+	void write(struct btree *r)
+	{
+		if (!r->written)
+			bch_btree_write(r, true, op);
+		else if (btree_node_dirty(r)) {
+			BUG_ON(btree_current_write(r)->owner);
+			btree_current_write(r)->owner = writes;
+			closure_get(writes);
+
+			bch_btree_write(r, true, NULL);
+		}
+
+		up_write(&r->lock);
+	}
+
+	int ret = 0, stale;
+	unsigned i;
+	struct gc_merge_info r[GC_MERGE_NODES];
+
+	memset(r, 0, sizeof(r));
+
+	while ((r->k = bch_next_recurse_key(b, &b->c->gc_done))) {
+		r->b = bch_btree_node_get(b->c, r->k, b->level - 1, op);
+
+		if (IS_ERR(r->b)) {
+			ret = PTR_ERR(r->b);
+			break;
+		}
+
+		r->keys	= 0;
+		stale = btree_gc_mark_node(r->b, &r->keys, gc);
+
+		if (!b->written &&
+		    (r->b->level || stale > 10 ||
+		     b->c->gc_always_rewrite))
+			r->b = btree_gc_alloc(r->b, r->k, op);
+
+		if (r->b->level)
+			ret = btree_gc_recurse(r->b, op, writes, gc);
+
+		if (ret) {
+			write(r->b);
+			break;
+		}
+
+		bkey_copy_key(&b->c->gc_done, r->k);
+
+		if (!b->written)
+			btree_gc_coalesce(b, op, gc, r);
+
+		if (r[GC_MERGE_NODES - 1].b)
+			write(r[GC_MERGE_NODES - 1].b);
+
+		memmove(&r[1], &r[0],
+			sizeof(struct gc_merge_info) * (GC_MERGE_NODES - 1));
+
+		/* When we've got incremental GC working, we'll want to do
+		 * if (should_resched())
+		 *	return -EAGAIN;
+		 */
+		cond_resched();
+#if 0
+		if (need_resched()) {
+			ret = -EAGAIN;
+			break;
+		}
+#endif
+	}
+
+	for (i = 1; i < GC_MERGE_NODES && r[i].b; i++)
+		write(r[i].b);
+
+	/* Might have freed some children, must remove their keys */
+	if (!b->written)
+		bch_btree_sort(b);
+
+	return ret;
+}
+
+static int bch_btree_gc_root(struct btree *b, struct btree_op *op,
+			     struct closure *writes, struct gc_stat *gc)
+{
+	struct btree *n = NULL;
+	unsigned keys = 0;
+	int ret = 0, stale = btree_gc_mark_node(b, &keys, gc);
+
+	if (b->level || stale > 10)
+		n = btree_node_alloc_replacement(b, NULL);
+
+	if (!IS_ERR_OR_NULL(n))
+		swap(b, n);
+
+	if (b->level)
+		ret = btree_gc_recurse(b, op, writes, gc);
+
+	if (!b->written || btree_node_dirty(b)) {
+		atomic_inc(&b->c->prio_blocked);
+		b->prio_blocked++;
+		bch_btree_write(b, true, n ? op : NULL);
+	}
+
+	if (!IS_ERR_OR_NULL(n)) {
+		closure_sync(&op->cl);
+		bch_btree_set_root(b);
+		btree_node_free(n, op);
+		rw_unlock(true, b);
+	}
+
+	return ret;
+}
+
+static void btree_gc_start(struct cache_set *c)
+{
+	struct cache *ca;
+	struct bucket *b;
+	struct bcache_device **d;
+	unsigned i;
+
+	if (!c->gc_mark_valid)
+		return;
+
+	mutex_lock(&c->bucket_lock);
+
+	c->gc_mark_valid = 0;
+	c->gc_done = ZERO_KEY;
+
+	for_each_cache(ca, c, i)
+		for_each_bucket(b, ca) {
+			b->gc_gen = b->gen;
+			if (!atomic_read(&b->pin))
+				SET_GC_MARK(b, GC_MARK_RECLAIMABLE);
+		}
+
+	for (d = c->devices;
+	     d < c->devices + c->nr_uuids;
+	     d++)
+		if (*d)
+			(*d)->sectors_dirty_gc = 0;
+
+	mutex_unlock(&c->bucket_lock);
+}
+
+size_t bch_btree_gc_finish(struct cache_set *c)
+{
+	size_t available = 0;
+	struct bucket *b;
+	struct cache *ca;
+	struct bcache_device **d;
+	unsigned i;
+
+	mutex_lock(&c->bucket_lock);
+
+	set_gc_sectors(c);
+	c->gc_mark_valid = 1;
+	c->need_gc	= 0;
+
+	if (c->root)
+		for (i = 0; i < KEY_PTRS(&c->root->key); i++)
+			SET_GC_MARK(PTR_BUCKET(c, &c->root->key, i),
+				    GC_MARK_METADATA);
+
+	for (i = 0; i < KEY_PTRS(&c->uuid_bucket); i++)
+		SET_GC_MARK(PTR_BUCKET(c, &c->uuid_bucket, i),
+			    GC_MARK_METADATA);
+
+	for_each_cache(ca, c, i) {
+		uint64_t *i;
+
+		ca->invalidate_needs_gc = 0;
+
+		for (i = ca->sb.d; i < ca->sb.d + ca->sb.keys; i++)
+			SET_GC_MARK(ca->buckets + *i, GC_MARK_METADATA);
+
+		for (i = ca->prio_buckets;
+		     i < ca->prio_buckets + prio_buckets(ca) * 2; i++)
+			SET_GC_MARK(ca->buckets + *i, GC_MARK_METADATA);
+
+		for_each_bucket(b, ca) {
+			b->last_gc	= b->gc_gen;
+			c->need_gc	= max(c->need_gc, bucket_gc_gen(b));
+
+			if (!atomic_read(&b->pin) &&
+			    GC_MARK(b) == GC_MARK_RECLAIMABLE) {
+				available++;
+				if (!GC_SECTORS_USED(b))
+					bch_bucket_add_unused(ca, b);
+			}
+		}
+	}
+
+	for (d = c->devices;
+	     d < c->devices + c->nr_uuids;
+	     d++)
+		if (*d) {
+			unsigned long last =
+				atomic_long_read(&((*d)->sectors_dirty));
+			long difference = (*d)->sectors_dirty_gc - last;
+
+			pr_debug("sectors dirty off by %li", difference);
+
+			(*d)->sectors_dirty_last += difference;
+
+			atomic_long_set(&((*d)->sectors_dirty),
+					(*d)->sectors_dirty_gc);
+		}
+
+	mutex_unlock(&c->bucket_lock);
+	return available;
+}
+
+static void bch_btree_gc(struct closure *cl)
+{
+	struct cache_set *c = container_of(cl, struct cache_set, gc.cl);
+	int ret;
+	unsigned long available;
+	struct gc_stat stats;
+	struct closure writes;
+	struct btree_op op;
+
+	uint64_t start_time = local_clock();
+	trace_bcache_gc_start(c->sb.set_uuid);
+	blktrace_msg_all(c, "Starting gc");
+
+	memset(&stats, 0, sizeof(struct gc_stat));
+	closure_init_stack(&writes);
+	bch_btree_op_init_stack(&op);
+	op.lock = SHRT_MAX;
+
+	btree_gc_start(c);
+
+	ret = btree_root(gc_root, c, &op, &writes, &stats);
+	closure_sync(&op.cl);
+	closure_sync(&writes);
+
+	if (ret) {
+		blktrace_msg_all(c, "Stopped gc");
+		pr_warn("gc failed!");
+
+		continue_at(cl, bch_btree_gc, bch_gc_wq);
+	}
+
+	/* Possibly wait for new UUIDs or whatever to hit disk */
+	bch_journal_meta(c, &op.cl);
+	closure_sync(&op.cl);
+
+	available = bch_btree_gc_finish(c);
+
+	bch_time_stats_update(&c->btree_gc_time, start_time);
+
+	stats.key_bytes *= sizeof(uint64_t);
+	stats.dirty	<<= 9;
+	stats.data	<<= 9;
+	stats.in_use	= (c->nbuckets - available) * 100 / c->nbuckets;
+	memcpy(&c->gc_stats, &stats, sizeof(struct gc_stat));
+	blktrace_msg_all(c, "Finished gc");
+
+	trace_bcache_gc_end(c->sb.set_uuid);
+	wake_up(&c->alloc_wait);
+	closure_wake_up(&c->bucket_wait);
+
+	continue_at(cl, bch_moving_gc, bch_gc_wq);
+}
+
+void bch_queue_gc(struct cache_set *c)
+{
+	closure_trylock_call(&c->gc.cl, bch_btree_gc, bch_gc_wq, &c->cl);
+}
+
+/* Initial partial gc */
+
+static int bch_btree_check_recurse(struct btree *b, struct btree_op *op,
+				   unsigned long **seen)
+{
+	int ret;
+	unsigned i;
+	struct bkey *k;
+	struct bucket *g;
+	struct btree_iter iter;
+
+	for_each_key_filter(b, k, &iter, bch_ptr_invalid) {
+		for (i = 0; i < KEY_PTRS(k); i++) {
+			if (!ptr_available(b->c, k, i))
+				continue;
+
+			g = PTR_BUCKET(b->c, k, i);
+
+			if (!__test_and_set_bit(PTR_BUCKET_NR(b->c, k, i),
+						seen[PTR_DEV(k, i)]) ||
+			    !ptr_stale(b->c, k, i)) {
+				g->gen = PTR_GEN(k, i);
+
+				if (b->level)
+					g->prio = BTREE_PRIO;
+				else if (g->prio == BTREE_PRIO)
+					g->prio = INITIAL_PRIO;
+			}
+		}
+
+		btree_mark_key(b, k);
+	}
+
+	if (b->level) {
+		k = bch_next_recurse_key(b, &ZERO_KEY);
+
+		while (k) {
+			struct bkey *p = bch_next_recurse_key(b, k);
+			if (p)
+				btree_node_prefetch(b->c, p, b->level - 1);
+
+			ret = btree(check_recurse, k, b, op, seen);
+			if (ret)
+				return ret;
+
+			k = p;
+		}
+	}
+
+	return 0;
+}
+
+int bch_btree_check(struct cache_set *c, struct btree_op *op)
+{
+	int ret = -ENOMEM;
+	unsigned i;
+	unsigned long *seen[MAX_CACHES_PER_SET];
+
+	memset(seen, 0, sizeof(seen));
+
+	for (i = 0; c->cache[i]; i++) {
+		size_t n = DIV_ROUND_UP(c->cache[i]->sb.nbuckets, 8);
+		seen[i] = kmalloc(n, GFP_KERNEL);
+		if (!seen[i])
+			goto err;
+
+		/* Disables the seen array until prio_read() uses it too */
+		memset(seen[i], 0xFF, n);
+	}
+
+	ret = btree_root(check_recurse, c, op, seen);
+err:
+	for (i = 0; i < MAX_CACHES_PER_SET; i++)
+		kfree(seen[i]);
+	return ret;
+}
+
+/* Btree insertion */
+
+static void shift_keys(struct btree *b, struct bkey *where, struct bkey *insert)
+{
+	struct bset *i = b->sets[b->nsets].data;
+
+	memmove((uint64_t *) where + bkey_u64s(insert),
+		where,
+		(void *) end(i) - (void *) where);
+
+	i->keys += bkey_u64s(insert);
+	bkey_copy(where, insert);
+	bch_bset_fix_lookup_table(b, where);
+}
+
+static bool fix_overlapping_extents(struct btree *b,
+				    struct bkey *insert,
+				    struct btree_iter *iter,
+				    struct btree_op *op)
+{
+	void subtract_dirty(struct bkey *k, int sectors)
+	{
+		struct bcache_device *d = b->c->devices[KEY_INODE(k)];
+
+		if (KEY_DIRTY(k) && d)
+			atomic_long_sub(sectors, &d->sectors_dirty);
+	}
+
+	unsigned old_size, sectors_found = 0;
+
+	while (1) {
+		struct bkey *k = bch_btree_iter_next(iter);
+		if (!k ||
+		    bkey_cmp(&START_KEY(k), insert) >= 0)
+			break;
+
+		if (bkey_cmp(k, &START_KEY(insert)) <= 0)
+			continue;
+
+		old_size = KEY_SIZE(k);
+
+		/*
+		 * We might overlap with 0 size extents; we can't skip these
+		 * because if they're in the set we're inserting to we have to
+		 * adjust them so they don't overlap with the key we're
+		 * inserting. But we don't want to check them for BTREE_REPLACE
+		 * operations.
+		 */
+
+		if (op->type == BTREE_REPLACE &&
+		    KEY_SIZE(k)) {
+			/*
+			 * k might have been split since we inserted/found the
+			 * key we're replacing
+			 */
+			unsigned i;
+			uint64_t offset = KEY_START(k) -
+				KEY_START(&op->replace);
+
+			/* But it must be a subset of the replace key */
+			if (KEY_START(k) < KEY_START(&op->replace) ||
+			    KEY_OFFSET(k) > KEY_OFFSET(&op->replace))
+				goto check_failed;
+
+			/* We didn't find a key that we were supposed to */
+			if (KEY_START(k) > KEY_START(insert) + sectors_found)
+				goto check_failed;
+
+			if (KEY_PTRS(&op->replace) != KEY_PTRS(k))
+				goto check_failed;
+
+			/* skip past gen */
+			offset <<= 8;
+
+			BUG_ON(!KEY_PTRS(&op->replace));
+
+			for (i = 0; i < KEY_PTRS(&op->replace); i++)
+				if (k->ptr[i] != op->replace.ptr[i] + offset)
+					goto check_failed;
+
+			sectors_found = KEY_OFFSET(k) - KEY_START(insert);
+		}
+
+		if (bkey_cmp(insert, k) < 0 &&
+		    bkey_cmp(&START_KEY(insert), &START_KEY(k)) > 0) {
+			/*
+			 * We overlapped in the middle of an existing key: that
+			 * means we have to split the old key. But we have to do
+			 * slightly different things depending on whether the
+			 * old key has been written out yet.
+			 */
+
+			struct bkey *top;
+
+			subtract_dirty(k, KEY_SIZE(insert));
+
+			if (bkey_written(b, k)) {
+				/*
+				 * We insert a new key to cover the top of the
+				 * old key, and the old key is modified in place
+				 * to represent the bottom split.
+				 *
+				 * It's completely arbitrary whether the new key
+				 * is the top or the bottom, but it has to match
+				 * up with what btree_sort_fixup() does - it
+				 * doesn't check for this kind of overlap, it
+				 * depends on us inserting a new key for the top
+				 * here.
+				 */
+				top = bch_bset_search(b, &b->sets[b->nsets],
+						      insert);
+				shift_keys(b, top, k);
+			} else {
+				BKEY_PADDED(key) temp;
+				bkey_copy(&temp.key, k);
+				shift_keys(b, k, &temp.key);
+				top = bkey_next(k);
+			}
+
+			bch_cut_front(insert, top);
+			bch_cut_back(&START_KEY(insert), k);
+			bch_bset_fix_invalidated_key(b, k);
+			return false;
+		}
+
+		if (bkey_cmp(insert, k) < 0) {
+			bch_cut_front(insert, k);
+		} else {
+			if (bkey_written(b, k) &&
+			    bkey_cmp(&START_KEY(insert), &START_KEY(k)) <= 0) {
+				/*
+				 * Completely overwrote, so we don't have to
+				 * invalidate the binary search tree
+				 */
+				bch_cut_front(k, k);
+			} else {
+				__bch_cut_back(&START_KEY(insert), k);
+				bch_bset_fix_invalidated_key(b, k);
+			}
+		}
+
+		subtract_dirty(k, old_size - KEY_SIZE(k));
+	}
+
+check_failed:
+	if (op->type == BTREE_REPLACE) {
+		if (!sectors_found) {
+			op->insert_collision = true;
+			return true;
+		} else if (sectors_found < KEY_SIZE(insert)) {
+			SET_KEY_OFFSET(insert, KEY_OFFSET(insert) -
+				       (KEY_SIZE(insert) - sectors_found));
+			SET_KEY_SIZE(insert, sectors_found);
+		}
+	}
+
+	return false;
+}
+
+static bool btree_insert_key(struct btree *b, struct btree_op *op,
+			     struct bkey *k)
+{
+	struct bset *i = b->sets[b->nsets].data;
+	struct bkey *m, *prev;
+	const char *status = "insert";
+
+	BUG_ON(bkey_cmp(k, &b->key) > 0);
+	BUG_ON(b->level && !KEY_PTRS(k));
+	BUG_ON(!b->level && !KEY_OFFSET(k));
+
+	if (!b->level) {
+		struct btree_iter iter;
+		struct bkey search = KEY(KEY_INODE(k), KEY_START(k), 0);
+
+		/*
+		 * bset_search() returns the first key that is strictly greater
+		 * than the search key - but for back merging, we want to find
+		 * the first key that is greater than or equal to KEY_START(k) -
+		 * unless KEY_START(k) is 0.
+		 */
+		if (KEY_OFFSET(&search))
+			SET_KEY_OFFSET(&search, KEY_OFFSET(&search) - 1);
+
+		prev = NULL;
+		m = bch_btree_iter_init(b, &iter, &search);
+
+		if (fix_overlapping_extents(b, k, &iter, op))
+			return false;
+
+		while (m != end(i) &&
+		       bkey_cmp(k, &START_KEY(m)) > 0)
+			prev = m, m = bkey_next(m);
+
+		if (key_merging_disabled(b->c))
+			goto insert;
+
+		/* prev is in the tree, if we merge we're done */
+		status = "back merging";
+		if (prev &&
+		    bch_bkey_try_merge(b, prev, k))
+			goto merged;
+
+		status = "overwrote front";
+		if (m != end(i) &&
+		    KEY_PTRS(m) == KEY_PTRS(k) && !KEY_SIZE(m))
+			goto copy;
+
+		status = "front merge";
+		if (m != end(i) &&
+		    bch_bkey_try_merge(b, k, m))
+			goto copy;
+	} else
+		m = bch_bset_search(b, &b->sets[b->nsets], k);
+
+insert:	shift_keys(b, m, k);
+copy:	bkey_copy(m, k);
+merged:
+	bch_check_keys(b, "%s for %s at %s: %s", status,
+		       op_type(op), pbtree(b), pkey(k));
+	bch_check_key_order_msg(b, i, "%s for %s at %s: %s", status,
+				op_type(op), pbtree(b), pkey(k));
+
+	if (b->level && !KEY_OFFSET(k))
+		b->prio_blocked++;
+
+	pr_debug("%s for %s at %s: %s", status,
+		 op_type(op), pbtree(b), pkey(k));
+
+	return true;
+}
+
+bool bch_btree_insert_keys(struct btree *b, struct btree_op *op)
+{
+	bool ret = false;
+	struct bkey *k;
+	unsigned oldsize = bch_count_data(b);
+
+	while ((k = bch_keylist_pop(&op->keys))) {
+		bkey_put(b->c, k, b->level);
+		ret |= btree_insert_key(b, op, k);
+	}
+
+	BUG_ON(bch_count_data(b) < oldsize);
+	return ret;
+}
+
+bool bch_btree_insert_check_key(struct btree *b, struct btree_op *op,
+				   struct bio *bio)
+{
+	bool ret = false;
+	uint64_t btree_ptr = b->key.ptr[0];
+	unsigned long seq = b->seq;
+	BKEY_PADDED(k) tmp;
+
+	rw_unlock(false, b);
+	rw_lock(true, b, b->level);
+
+	if (b->key.ptr[0] != btree_ptr ||
+	    b->seq != seq + 1 ||
+	    should_split(b))
+		goto out;
+
+	op->replace = KEY(op->inode, bio_end(bio), bio_sectors(bio));
+
+	SET_KEY_PTRS(&op->replace, 1);
+	get_random_bytes(&op->replace.ptr[0], sizeof(uint64_t));
+
+	SET_PTR_DEV(&op->replace, 0, PTR_CHECK_DEV);
+
+	bkey_copy(&tmp.k, &op->replace);
+
+	BUG_ON(op->type != BTREE_INSERT);
+	BUG_ON(!btree_insert_key(b, op, &tmp.k));
+	bch_btree_write(b, false, NULL);
+	ret = true;
+out:
+	downgrade_write(&b->lock);
+	return ret;
+}
+
+static int btree_split(struct btree *b, struct btree_op *op)
+{
+	bool split, root = b == b->c->root;
+	struct btree *n1, *n2 = NULL, *n3 = NULL;
+	uint64_t start_time = local_clock();
+
+	if (b->level)
+		set_closure_blocking(&op->cl);
+
+	n1 = btree_node_alloc_replacement(b, &op->cl);
+	if (IS_ERR(n1))
+		goto err;
+
+	split = set_blocks(n1->sets[0].data, n1->c) > (btree_blocks(b) * 4) / 5;
+
+	pr_debug("%ssplitting at %s keys %i", split ? "" : "not ",
+		 pbtree(b), n1->sets[0].data->keys);
+
+	if (split) {
+		unsigned keys = 0;
+
+		n2 = bch_btree_node_alloc(b->c, b->level, &op->cl);
+		if (IS_ERR(n2))
+			goto err_free1;
+
+		if (root) {
+			n3 = bch_btree_node_alloc(b->c, b->level + 1, &op->cl);
+			if (IS_ERR(n3))
+				goto err_free2;
+		}
+
+		bch_btree_insert_keys(n1, op);
+
+		/* Has to be a linear search because we don't have an auxiliary
+		 * search tree yet
+		 */
+
+		while (keys < (n1->sets[0].data->keys * 3) / 5)
+			keys += bkey_u64s(node(n1->sets[0].data, keys));
+
+		bkey_copy_key(&n1->key, node(n1->sets[0].data, keys));
+		keys += bkey_u64s(node(n1->sets[0].data, keys));
+
+		n2->sets[0].data->keys = n1->sets[0].data->keys - keys;
+		n1->sets[0].data->keys = keys;
+
+		memcpy(n2->sets[0].data->start,
+		       end(n1->sets[0].data),
+		       n2->sets[0].data->keys * sizeof(uint64_t));
+
+		bkey_copy_key(&n2->key, &b->key);
+
+		bch_keylist_add(&op->keys, &n2->key);
+		bch_btree_write(n2, true, op);
+		rw_unlock(true, n2);
+	} else
+		bch_btree_insert_keys(n1, op);
+
+	bch_keylist_add(&op->keys, &n1->key);
+	bch_btree_write(n1, true, op);
+
+	if (n3) {
+		bkey_copy_key(&n3->key, &MAX_KEY);
+		bch_btree_insert_keys(n3, op);
+		bch_btree_write(n3, true, op);
+
+		closure_sync(&op->cl);
+		bch_btree_set_root(n3);
+		rw_unlock(true, n3);
+	} else if (root) {
+		op->keys.top = op->keys.bottom;
+		closure_sync(&op->cl);
+		bch_btree_set_root(n1);
+	} else {
+		unsigned i;
+
+		bkey_copy(op->keys.top, &b->key);
+		bkey_copy_key(op->keys.top, &ZERO_KEY);
+
+		for (i = 0; i < KEY_PTRS(&b->key); i++) {
+			uint8_t g = PTR_BUCKET(b->c, &b->key, i)->gen + 1;
+
+			SET_PTR_GEN(op->keys.top, i, g);
+		}
+
+		bch_keylist_push(&op->keys);
+		closure_sync(&op->cl);
+		atomic_inc(&b->c->prio_blocked);
+	}
+
+	rw_unlock(true, n1);
+	btree_node_free(b, op);
+
+	bch_time_stats_update(&b->c->btree_split_time, start_time);
+
+	return 0;
+err_free2:
+	__bkey_put(n2->c, &n2->key);
+	btree_node_free(n2, op);
+	rw_unlock(true, n2);
+err_free1:
+	__bkey_put(n1->c, &n1->key);
+	btree_node_free(n1, op);
+	rw_unlock(true, n1);
+err:
+	if (n3 == ERR_PTR(-EAGAIN) ||
+	    n2 == ERR_PTR(-EAGAIN) ||
+	    n1 == ERR_PTR(-EAGAIN))
+		return -EAGAIN;
+
+	pr_warn("couldn't split");
+	return -ENOMEM;
+}
+
+static int bch_btree_insert_recurse(struct btree *b, struct btree_op *op,
+				    struct keylist *stack_keys)
+{
+	if (b->level) {
+		int ret;
+		struct bkey *insert = op->keys.bottom;
+		struct bkey *k = bch_next_recurse_key(b, &START_KEY(insert));
+
+		if (!k) {
+			btree_bug(b, "no key to recurse on at level %i/%i",
+				  b->level, b->c->root->level);
+
+			op->keys.top = op->keys.bottom;
+			return -EIO;
+		}
+
+		if (bkey_cmp(insert, k) > 0) {
+			unsigned i;
+
+			if (op->type == BTREE_REPLACE) {
+				__bkey_put(b->c, insert);
+				op->keys.top = op->keys.bottom;
+				op->insert_collision = true;
+				return 0;
+			}
+
+			for (i = 0; i < KEY_PTRS(insert); i++)
+				atomic_inc(&PTR_BUCKET(b->c, insert, i)->pin);
+
+			bkey_copy(stack_keys->top, insert);
+
+			bch_cut_back(k, insert);
+			bch_cut_front(k, stack_keys->top);
+
+			bch_keylist_push(stack_keys);
+		}
+
+		ret = btree(insert_recurse, k, b, op, stack_keys);
+		if (ret)
+			return ret;
+	}
+
+	if (!bch_keylist_empty(&op->keys)) {
+		if (should_split(b)) {
+			if (op->lock <= b->c->root->level) {
+				BUG_ON(b->level);
+				op->lock = b->c->root->level + 1;
+				return -EINTR;
+			}
+			return btree_split(b, op);
+		}
+
+		BUG_ON(write_block(b) != b->sets[b->nsets].data);
+
+		if (bch_btree_insert_keys(b, op))
+			bch_btree_write(b, false, op);
+	}
+
+	return 0;
+}
+
+int bch_btree_insert(struct btree_op *op, struct cache_set *c)
+{
+	int ret = 0;
+	struct keylist stack_keys;
+
+	/*
+	 * Don't want to block with the btree locked unless we have to,
+	 * otherwise we get deadlocks with try_harder and between split/gc
+	 */
+	clear_closure_blocking(&op->cl);
+
+	BUG_ON(bch_keylist_empty(&op->keys));
+	bch_keylist_copy(&stack_keys, &op->keys);
+	bch_keylist_init(&op->keys);
+
+	while (!bch_keylist_empty(&stack_keys) ||
+	       !bch_keylist_empty(&op->keys)) {
+		if (bch_keylist_empty(&op->keys)) {
+			bch_keylist_add(&op->keys,
+					bch_keylist_pop(&stack_keys));
+			op->lock = 0;
+		}
+
+		ret = btree_root(insert_recurse, c, op, &stack_keys);
+
+		if (ret == -EAGAIN) {
+			ret = 0;
+			closure_sync(&op->cl);
+		} else if (ret) {
+			struct bkey *k;
+
+			pr_err("error %i trying to insert key for %s",
+			       ret, op_type(op));
+
+			while ((k = bch_keylist_pop(&stack_keys) ?:
+				    bch_keylist_pop(&op->keys)))
+				bkey_put(c, k, 0);
+		}
+	}
+
+	bch_keylist_free(&stack_keys);
+
+	if (op->journal)
+		atomic_dec_bug(op->journal);
+	op->journal = NULL;
+	return ret;
+}
+
+void bch_btree_set_root(struct btree *b)
+{
+	unsigned i;
+
+	BUG_ON(!b->written);
+
+	for (i = 0; i < KEY_PTRS(&b->key); i++)
+		BUG_ON(PTR_BUCKET(b->c, &b->key, i)->prio != BTREE_PRIO);
+
+	mutex_lock(&b->c->bucket_lock);
+	list_del_init(&b->list);
+	mutex_unlock(&b->c->bucket_lock);
+
+	b->c->root = b;
+	__bkey_put(b->c, &b->key);
+
+	bch_journal_meta(b->c, NULL);
+	pr_debug("%s for %pf", pbtree(b), __builtin_return_address(0));
+}
+
+/* Cache lookup */
+
+static int submit_partial_cache_miss(struct btree *b, struct btree_op *op,
+				     struct bkey *k)
+{
+	struct search *s = container_of(op, struct search, op);
+	struct bio *bio = &s->bio.bio;
+	int ret = 0;
+
+	while (!ret &&
+	       !op->lookup_done) {
+		unsigned sectors = INT_MAX;
+
+		if (KEY_INODE(k) == op->inode) {
+			if (KEY_START(k) <= bio->bi_sector)
+				break;
+
+			sectors = min_t(uint64_t, sectors,
+					KEY_START(k) - bio->bi_sector);
+		}
+
+		ret = s->d->cache_miss(b, s, bio, sectors);
+	}
+
+	return ret;
+}
+
+/*
+ * Read from a single key, handling the initial cache miss if the key starts in
+ * the middle of the bio
+ */
+static int submit_partial_cache_hit(struct btree *b, struct btree_op *op,
+				    struct bkey *k)
+{
+	struct search *s = container_of(op, struct search, op);
+	struct bio *bio = &s->bio.bio;
+	unsigned ptr;
+	struct bio *n;
+
+	int ret = submit_partial_cache_miss(b, op, k);
+	if (ret || op->lookup_done)
+		return ret;
+
+	/* XXX: figure out best pointer - for multiple cache devices */
+	ptr = 0;
+
+	PTR_BUCKET(b->c, k, ptr)->prio = INITIAL_PRIO;
+
+	while (!op->lookup_done &&
+	       KEY_INODE(k) == op->inode &&
+	       bio->bi_sector < KEY_OFFSET(k)) {
+		struct bkey *bio_key;
+		sector_t sector = PTR_OFFSET(k, ptr) +
+			(bio->bi_sector - KEY_START(k));
+		unsigned sectors = min_t(uint64_t, INT_MAX,
+					 KEY_OFFSET(k) - bio->bi_sector);
+
+		n = bch_bio_split(bio, sectors, GFP_NOIO, s->d->bio_split);
+		if (!n)
+			return -EAGAIN;
+
+		if (n == bio)
+			op->lookup_done = true;
+
+		bio_key = &container_of(n, struct bbio, bio)->key;
+
+		/*
+		 * The bucket we're reading from might be reused while our bio
+		 * is in flight, and we could then end up reading the wrong
+		 * data.
+		 *
+		 * We guard against this by checking (in cache_read_endio()) if
+		 * the pointer is stale again; if so, we treat it as an error
+		 * and reread from the backing device (but we don't pass that
+		 * error up anywhere).
+		 */
+
+		bch_bkey_copy_single_ptr(bio_key, k, ptr);
+		SET_PTR_OFFSET(bio_key, 0, sector);
+
+		n->bi_end_io	= bch_cache_read_endio;
+		n->bi_private	= &s->cl;
+
+		trace_bcache_cache_hit(n);
+		__bch_submit_bbio(n, b->c);
+	}
+
+	return 0;
+}
+
+int bch_btree_search_recurse(struct btree *b, struct btree_op *op)
+{
+	struct search *s = container_of(op, struct search, op);
+	struct bio *bio = &s->bio.bio;
+
+	int ret = 0;
+	struct bkey *k;
+	struct btree_iter iter;
+	bch_btree_iter_init(b, &iter, &KEY(op->inode, bio->bi_sector, 0));
+
+	pr_debug("at %s searching for %u:%llu", pbtree(b), op->inode,
+		 (uint64_t) bio->bi_sector);
+
+	do {
+		k = bch_btree_iter_next_filter(&iter, b, bch_ptr_bad);
+		if (!k) {
+			/*
+			 * b->key would be exactly what we want, except that
+			 * pointers to btree nodes have nonzero size - we
+			 * wouldn't go far enough
+			 */
+
+			ret = submit_partial_cache_miss(b, op,
+					&KEY(KEY_INODE(&b->key),
+					     KEY_OFFSET(&b->key), 0));
+			break;
+		}
+
+		ret = b->level
+			? btree(search_recurse, k, b, op)
+			: submit_partial_cache_hit(b, op, k);
+	} while (!ret &&
+		 !op->lookup_done);
+
+	return ret;
+}
+
+/* Keybuf code */
+
+static inline int keybuf_cmp(struct keybuf_key *l, struct keybuf_key *r)
+{
+	/* Overlapping keys compare equal */
+	if (bkey_cmp(&l->key, &START_KEY(&r->key)) <= 0)
+		return -1;
+	if (bkey_cmp(&START_KEY(&l->key), &r->key) >= 0)
+		return 1;
+	return 0;
+}
+
+static inline int keybuf_nonoverlapping_cmp(struct keybuf_key *l,
+					    struct keybuf_key *r)
+{
+	return clamp_t(int64_t, bkey_cmp(&l->key, &r->key), -1, 1);
+}
+
+static int bch_btree_refill_keybuf(struct btree *b, struct btree_op *op,
+				   struct keybuf *buf, struct bkey *end)
+{
+	struct btree_iter iter;
+	bch_btree_iter_init(b, &iter, &buf->last_scanned);
+
+	while (!array_freelist_empty(&buf->freelist)) {
+		struct bkey *k = bch_btree_iter_next_filter(&iter, b,
+							    bch_ptr_bad);
+
+		if (!b->level) {
+			if (!k) {
+				buf->last_scanned = b->key;
+				break;
+			}
+
+			buf->last_scanned = *k;
+			if (bkey_cmp(&buf->last_scanned, end) >= 0)
+				break;
+
+			if (buf->key_predicate(buf, k)) {
+				struct keybuf_key *w;
+
+				pr_debug("%s", pkey(k));
+
+				spin_lock(&buf->lock);
+
+				w = array_alloc(&buf->freelist);
+
+				w->private = NULL;
+				bkey_copy(&w->key, k);
+
+				if (RB_INSERT(&buf->keys, w, node, keybuf_cmp))
+					array_free(&buf->freelist, w);
+
+				spin_unlock(&buf->lock);
+			}
+		} else {
+			if (!k)
+				break;
+
+			btree(refill_keybuf, k, b, op, buf, end);
+			/*
+			 * Might get an error here, but can't really do anything
+			 * and it'll get logged elsewhere. Just read what we
+			 * can.
+			 */
+
+			if (bkey_cmp(&buf->last_scanned, end) >= 0)
+				break;
+
+			cond_resched();
+		}
+	}
+
+	return 0;
+}
+
+void bch_refill_keybuf(struct cache_set *c, struct keybuf *buf,
+			  struct bkey *end)
+{
+	struct bkey start = buf->last_scanned;
+	struct btree_op op;
+	bch_btree_op_init_stack(&op);
+
+	cond_resched();
+
+	btree_root(refill_keybuf, c, &op, buf, end);
+	closure_sync(&op.cl);
+
+	pr_debug("found %s keys from %llu:%llu to %llu:%llu",
+		 RB_EMPTY_ROOT(&buf->keys) ? "no" :
+		 array_freelist_empty(&buf->freelist) ? "some" : "a few",
+		 KEY_INODE(&start), KEY_OFFSET(&start),
+		 KEY_INODE(&buf->last_scanned), KEY_OFFSET(&buf->last_scanned));
+
+	spin_lock(&buf->lock);
+
+	if (!RB_EMPTY_ROOT(&buf->keys)) {
+		struct keybuf_key *w;
+		w = RB_FIRST(&buf->keys, struct keybuf_key, node);
+		buf->start	= START_KEY(&w->key);
+
+		w = RB_LAST(&buf->keys, struct keybuf_key, node);
+		buf->end	= w->key;
+	} else {
+		buf->start	= MAX_KEY;
+		buf->end	= MAX_KEY;
+	}
+
+	spin_unlock(&buf->lock);
+}
+
+static void __bch_keybuf_del(struct keybuf *buf, struct keybuf_key *w)
+{
+	rb_erase(&w->node, &buf->keys);
+	array_free(&buf->freelist, w);
+}
+
+void bch_keybuf_del(struct keybuf *buf, struct keybuf_key *w)
+{
+	spin_lock(&buf->lock);
+	__bch_keybuf_del(buf, w);
+	spin_unlock(&buf->lock);
+}
+
+bool bch_keybuf_check_overlapping(struct keybuf *buf, struct bkey *start,
+				  struct bkey *end)
+{
+	bool ret = false;
+	struct keybuf_key *p, *w, s;
+	s.key = *start;
+
+	if (bkey_cmp(end, &buf->start) <= 0 ||
+	    bkey_cmp(start, &buf->end) >= 0)
+		return false;
+
+	spin_lock(&buf->lock);
+	w = RB_GREATER(&buf->keys, s, node, keybuf_nonoverlapping_cmp);
+
+	while (w && bkey_cmp(&START_KEY(&w->key), end) < 0) {
+		p = w;
+		w = RB_NEXT(w, node);
+
+		if (p->private)
+			ret = true;
+		else
+			__bch_keybuf_del(buf, p);
+	}
+
+	spin_unlock(&buf->lock);
+	return ret;
+}
+
+struct keybuf_key *bch_keybuf_next(struct keybuf *buf)
+{
+	struct keybuf_key *w;
+	spin_lock(&buf->lock);
+
+	w = RB_FIRST(&buf->keys, struct keybuf_key, node);
+
+	while (w && w->private)
+		w = RB_NEXT(w, node);
+
+	if (w)
+		w->private = ERR_PTR(-EINTR);
+
+	spin_unlock(&buf->lock);
+	return w;
+}
+
+struct keybuf_key *bch_keybuf_next_rescan(struct cache_set *c,
+					     struct keybuf *buf,
+					     struct bkey *end)
+{
+	struct keybuf_key *ret;
+
+	while (1) {
+		ret = bch_keybuf_next(buf);
+		if (ret)
+			break;
+
+		if (bkey_cmp(&buf->last_scanned, end) >= 0) {
+			pr_debug("scan finished");
+			break;
+		}
+
+		bch_refill_keybuf(c, buf, end);
+	}
+
+	return ret;
+}
+
+void bch_keybuf_init(struct keybuf *buf, keybuf_pred_fn *fn)
+{
+	buf->key_predicate	= fn;
+	buf->last_scanned	= MAX_KEY;
+	buf->keys		= RB_ROOT;
+
+	spin_lock_init(&buf->lock);
+	array_allocator_init(&buf->freelist);
+}
+
+void bch_btree_exit(void)
+{
+	if (btree_io_wq)
+		destroy_workqueue(btree_io_wq);
+	if (bch_gc_wq)
+		destroy_workqueue(bch_gc_wq);
+}
+
+int __init bch_btree_init(void)
+{
+	if (!(bch_gc_wq = create_singlethread_workqueue("bch_btree_gc")) ||
+	    !(btree_io_wq = create_singlethread_workqueue("bch_btree_io")))
+		return -ENOMEM;
+
+	return 0;
+}
diff --git a/drivers/md/bcache/btree.h b/drivers/md/bcache/btree.h
new file mode 100644
index 0000000..af4a709
--- /dev/null
+++ b/drivers/md/bcache/btree.h
@@ -0,0 +1,405 @@
+#ifndef _BCACHE_BTREE_H
+#define _BCACHE_BTREE_H
+
+/*
+ * THE BTREE:
+ *
+ * At a high level, bcache's btree is relatively standard b+ tree. All keys and
+ * pointers are in the leaves; interior nodes only have pointers to the child
+ * nodes.
+ *
+ * In the interior nodes, a struct bkey always points to a child btree node, and
+ * the key is the highest key in the child node - except that the highest key in
+ * an interior node is always MAX_KEY. The size field refers to the size on disk
+ * of the child node - this would allow us to have variable sized btree nodes
+ * (handy for keeping the depth of the btree 1 by expanding just the root).
+ *
+ * Btree nodes are themselves log structured, but this is hidden fairly
+ * thoroughly. Btree nodes on disk will in practice have extents that overlap
+ * (because they were written at different times), but in memory we never have
+ * overlapping extents - when we read in a btree node from disk, the first thing
+ * we do is resort all the sets of keys with a mergesort, and in the same pass
+ * we check for overlapping extents and adjust them appropriately.
+ *
+ * struct btree_op is a central interface to the btree code. It's used for
+ * specifying read vs. write locking, and the embedded closure is used for
+ * waiting on IO or reserve memory.
+ *
+ * BTREE CACHE:
+ *
+ * Btree nodes are cached in memory; traversing the btree might require reading
+ * in btree nodes which is handled mostly transparently.
+ *
+ * bch_btree_node_get() looks up a btree node in the cache and reads it in from
+ * disk if necessary. This function is almost never called directly though - the
+ * btree() macro is used to get a btree node, call some function on it, and
+ * unlock the node after the function returns.
+ *
+ * The root is special cased - it's taken out of the cache's lru (thus pinning
+ * it in memory), so we can find the root of the btree by just dereferencing a
+ * pointer instead of looking it up in the cache. This makes locking a bit
+ * tricky, since the root pointer is protected by the lock in the btree node it
+ * points to - the btree_root() macro handles this.
+ *
+ * In various places we must be able to allocate memory for multiple btree nodes
+ * in order to make forward progress. To do this we use the btree cache itself
+ * as a reserve; if __get_free_pages() fails, we'll find a node in the btree
+ * cache we can reuse. We can't allow more than one thread to be doing this at a
+ * time, so there's a lock, implemented by a pointer to the btree_op closure -
+ * this allows the btree_root() macro to implicitly release this lock.
+ *
+ * BTREE IO:
+ *
+ * Btree nodes never have to be explicitly read in; bch_btree_node_get() handles
+ * this.
+ *
+ * For writing, we have two btree_write structs embeddded in struct btree - one
+ * write in flight, and one being set up, and we toggle between them.
+ *
+ * Writing is done with a single function -  bch_btree_write() really serves two
+ * different purposes and should be broken up into two different functions. When
+ * passing now = false, it merely indicates that the node is now dirty - calling
+ * it ensures that the dirty keys will be written at some point in the future.
+ *
+ * When passing now = true, bch_btree_write() causes a write to happen
+ * "immediately" (if there was already a write in flight, it'll cause the write
+ * to happen as soon as the previous write completes). It returns immediately
+ * though - but it takes a refcount on the closure in struct btree_op you passed
+ * to it, so a closure_sync() later can be used to wait for the write to
+ * complete.
+ *
+ * This is handy because btree_split() and garbage collection can issue writes
+ * in parallel, reducing the amount of time they have to hold write locks.
+ *
+ * LOCKING:
+ *
+ * When traversing the btree, we may need write locks starting at some level -
+ * inserting a key into the btree will typically only require a write lock on
+ * the leaf node.
+ *
+ * This is specified with the lock field in struct btree_op; lock = 0 means we
+ * take write locks at level <= 0, i.e. only leaf nodes. bch_btree_node_get()
+ * checks this field and returns the node with the appropriate lock held.
+ *
+ * If, after traversing the btree, the insertion code discovers it has to split
+ * then it must restart from the root and take new locks - to do this it changes
+ * the lock field and returns -EINTR, which causes the btree_root() macro to
+ * loop.
+ *
+ * Handling cache misses require a different mechanism for upgrading to a write
+ * lock. We do cache lookups with only a read lock held, but if we get a cache
+ * miss and we wish to insert this data into the cache, we have to insert a
+ * placeholder key to detect races - otherwise, we could race with a write and
+ * overwrite the data that was just written to the cache with stale data from
+ * the backing device.
+ *
+ * For this we use a sequence number that write locks and unlocks increment - to
+ * insert the check key it unlocks the btree node and then takes a write lock,
+ * and fails if the sequence number doesn't match.
+ */
+
+#include "bset.h"
+#include "debug.h"
+
+struct btree_write {
+	struct closure		*owner;
+	atomic_t		*journal;
+
+	/* If btree_split() frees a btree node, it writes a new pointer to that
+	 * btree node indicating it was freed; it takes a refcount on
+	 * c->prio_blocked because we can't write the gens until the new
+	 * pointer is on disk. This allows btree_write_endio() to release the
+	 * refcount that btree_split() took.
+	 */
+	int			prio_blocked;
+};
+
+struct btree {
+	/* Hottest entries first */
+	struct hlist_node	hash;
+
+	/* Key/pointer for this btree node */
+	BKEY_PADDED(key);
+
+	/* Single bit - set when accessed, cleared by shrinker */
+	unsigned long		accessed;
+	unsigned long		seq;
+	struct rw_semaphore	lock;
+	struct cache_set	*c;
+
+	unsigned long		flags;
+	uint16_t		written;	/* would be nice to kill */
+	uint8_t			level;
+	uint8_t			nsets;
+	uint8_t			page_order;
+
+	/*
+	 * Set of sorted keys - the real btree node - plus a binary search tree
+	 *
+	 * sets[0] is special; set[0]->tree, set[0]->prev and set[0]->data point
+	 * to the memory we have allocated for this btree node. Additionally,
+	 * set[0]->data points to the entire btree node as it exists on disk.
+	 */
+	struct bset_tree	sets[MAX_BSETS];
+
+	/* Used to refcount bio splits, also protects b->bio */
+	struct closure_with_waitlist	io;
+
+	/* Gets transferred to w->prio_blocked - see the comment there */
+	int			prio_blocked;
+
+	struct list_head	list;
+	struct delayed_work	work;
+
+	uint64_t		io_start_time;
+	struct btree_write	writes[2];
+	struct bio		*bio;
+};
+
+#define BTREE_FLAG(flag)						\
+static inline bool btree_node_ ## flag(struct btree *b)			\
+{	return test_bit(BTREE_NODE_ ## flag, &b->flags); }		\
+									\
+static inline void set_btree_node_ ## flag(struct btree *b)		\
+{	set_bit(BTREE_NODE_ ## flag, &b->flags); }			\
+
+enum btree_flags {
+	BTREE_NODE_read_done,
+	BTREE_NODE_io_error,
+	BTREE_NODE_dirty,
+	BTREE_NODE_write_idx,
+};
+
+BTREE_FLAG(read_done);
+BTREE_FLAG(io_error);
+BTREE_FLAG(dirty);
+BTREE_FLAG(write_idx);
+
+static inline struct btree_write *btree_current_write(struct btree *b)
+{
+	return b->writes + btree_node_write_idx(b);
+}
+
+static inline struct btree_write *btree_prev_write(struct btree *b)
+{
+	return b->writes + (btree_node_write_idx(b) ^ 1);
+}
+
+static inline unsigned bset_offset(struct btree *b, struct bset *i)
+{
+	return (((size_t) i) - ((size_t) b->sets->data)) >> 9;
+}
+
+static inline struct bset *write_block(struct btree *b)
+{
+	return ((void *) b->sets[0].data) + b->written * block_bytes(b->c);
+}
+
+static inline bool bset_written(struct btree *b, struct bset_tree *t)
+{
+	return t->data < write_block(b);
+}
+
+static inline bool bkey_written(struct btree *b, struct bkey *k)
+{
+	return k < write_block(b)->start;
+}
+
+static inline void set_gc_sectors(struct cache_set *c)
+{
+	atomic_set(&c->sectors_to_gc, c->sb.bucket_size * c->nbuckets / 8);
+}
+
+static inline bool bch_ptr_invalid(struct btree *b, const struct bkey *k)
+{
+	return __bch_ptr_invalid(b->c, b->level, k);
+}
+
+static inline struct bkey *bch_btree_iter_init(struct btree *b,
+					       struct btree_iter *iter,
+					       struct bkey *search)
+{
+	return __bch_btree_iter_init(b, iter, search, b->sets);
+}
+
+/* Looping macros */
+
+#define for_each_cached_btree(b, c, iter)				\
+	for (iter = 0;							\
+	     iter < ARRAY_SIZE((c)->bucket_hash);			\
+	     iter++)							\
+		hlist_for_each_entry_rcu((b), (c)->bucket_hash + iter, hash)
+
+#define for_each_key_filter(b, k, iter, filter)				\
+	for (bch_btree_iter_init((b), (iter), NULL);			\
+	     ((k) = bch_btree_iter_next_filter((iter), b, filter));)
+
+#define for_each_key(b, k, iter)					\
+	for (bch_btree_iter_init((b), (iter), NULL);			\
+	     ((k) = bch_btree_iter_next(iter));)
+
+/* Recursing down the btree */
+
+struct btree_op {
+	struct closure		cl;
+	struct cache_set	*c;
+
+	/* Journal entry we have a refcount on */
+	atomic_t		*journal;
+
+	/* Bio to be inserted into the cache */
+	struct bio		*cache_bio;
+
+	unsigned		inode;
+
+	uint16_t		write_prio;
+
+	/* Btree level at which we start taking write locks */
+	short			lock;
+
+	/* Btree insertion type */
+	enum {
+		BTREE_INSERT,
+		BTREE_REPLACE
+	} type:8;
+
+	unsigned		csum:1;
+	unsigned		skip:1;
+	unsigned		flush_journal:1;
+
+	unsigned		insert_data_done:1;
+	unsigned		lookup_done:1;
+	unsigned		insert_collision:1;
+
+	/* Anything after this point won't get zeroed in do_bio_hook() */
+
+	/* Keys to be inserted */
+	struct keylist		keys;
+	BKEY_PADDED(replace);
+};
+
+void bch_btree_op_init_stack(struct btree_op *);
+
+static inline void rw_lock(bool w, struct btree *b, int level)
+{
+	w ? down_write_nested(&b->lock, level + 1)
+	  : down_read_nested(&b->lock, level + 1);
+	if (w)
+		b->seq++;
+}
+
+static inline void rw_unlock(bool w, struct btree *b)
+{
+#ifdef CONFIG_BCACHE_EDEBUG
+	unsigned i;
+
+	if (w &&
+	    b->key.ptr[0] &&
+	    btree_node_read_done(b))
+		for (i = 0; i <= b->nsets; i++)
+			bch_check_key_order(b, b->sets[i].data);
+#endif
+
+	if (w)
+		b->seq++;
+	(w ? up_write : up_read)(&b->lock);
+}
+
+#define insert_lock(s, b)	((b)->level <= (s)->lock)
+
+/*
+ * These macros are for recursing down the btree - they handle the details of
+ * locking and looking up nodes in the cache for you. They're best treated as
+ * mere syntax when reading code that uses them.
+ *
+ * op->lock determines whether we take a read or a write lock at a given depth.
+ * If you've got a read lock and find that you need a write lock (i.e. you're
+ * going to have to split), set op->lock and return -EINTR; btree_root() will
+ * call you again and you'll have the correct lock.
+ */
+
+/**
+ * btree - recurse down the btree on a specified key
+ * @fn:		function to call, which will be passed the child node
+ * @key:	key to recurse on
+ * @b:		parent btree node
+ * @op:		pointer to struct btree_op
+ */
+#define btree(fn, key, b, op, ...)					\
+({									\
+	int _r, l = (b)->level - 1;					\
+	bool _w = l <= (op)->lock;					\
+	struct btree *_b = bch_btree_node_get((b)->c, key, l, op);	\
+	if (!IS_ERR(_b)) {						\
+		_r = bch_btree_ ## fn(_b, op, ##__VA_ARGS__);		\
+		rw_unlock(_w, _b);					\
+	} else								\
+		_r = PTR_ERR(_b);					\
+	_r;								\
+})
+
+/**
+ * btree_root - call a function on the root of the btree
+ * @fn:		function to call, which will be passed the child node
+ * @c:		cache set
+ * @op:		pointer to struct btree_op
+ */
+#define btree_root(fn, c, op, ...)					\
+({									\
+	int _r = -EINTR;						\
+	do {								\
+		struct btree *_b = (c)->root;				\
+		bool _w = insert_lock(op, _b);				\
+		rw_lock(_w, _b, _b->level);				\
+		if (_b == (c)->root &&					\
+		    _w == insert_lock(op, _b))				\
+			_r = bch_btree_ ## fn(_b, op, ##__VA_ARGS__);	\
+		rw_unlock(_w, _b);					\
+		bch_cannibalize_unlock(c, &(op)->cl);		\
+	} while (_r == -EINTR);						\
+									\
+	_r;								\
+})
+
+static inline bool should_split(struct btree *b)
+{
+	struct bset *i = write_block(b);
+	return b->written >= btree_blocks(b) ||
+		(i->seq == b->sets[0].data->seq &&
+		 b->written + __set_blocks(i, i->keys + 15, b->c)
+		 > btree_blocks(b));
+}
+
+void bch_btree_read_done(struct closure *);
+void bch_btree_read(struct btree *);
+void bch_btree_write(struct btree *b, bool now, struct btree_op *op);
+
+void bch_cannibalize_unlock(struct cache_set *, struct closure *);
+void bch_btree_set_root(struct btree *);
+struct btree *bch_btree_node_alloc(struct cache_set *, int, struct closure *);
+struct btree *bch_btree_node_get(struct cache_set *, struct bkey *,
+				int, struct btree_op *);
+
+bool bch_btree_insert_keys(struct btree *, struct btree_op *);
+bool bch_btree_insert_check_key(struct btree *, struct btree_op *,
+				   struct bio *);
+int bch_btree_insert(struct btree_op *, struct cache_set *);
+
+int bch_btree_search_recurse(struct btree *, struct btree_op *);
+
+void bch_queue_gc(struct cache_set *);
+size_t bch_btree_gc_finish(struct cache_set *);
+void bch_moving_gc(struct closure *);
+int bch_btree_check(struct cache_set *, struct btree_op *);
+uint8_t __bch_btree_mark_key(struct cache_set *, int, struct bkey *);
+
+void bch_keybuf_init(struct keybuf *, keybuf_pred_fn *);
+void bch_refill_keybuf(struct cache_set *, struct keybuf *, struct bkey *);
+bool bch_keybuf_check_overlapping(struct keybuf *, struct bkey *,
+				  struct bkey *);
+void bch_keybuf_del(struct keybuf *, struct keybuf_key *);
+struct keybuf_key *bch_keybuf_next(struct keybuf *);
+struct keybuf_key *bch_keybuf_next_rescan(struct cache_set *,
+					  struct keybuf *, struct bkey *);
+
+#endif
diff --git a/drivers/md/bcache/closure.c b/drivers/md/bcache/closure.c
new file mode 100644
index 0000000..bd05a9a
--- /dev/null
+++ b/drivers/md/bcache/closure.c
@@ -0,0 +1,345 @@
+/*
+ * Asynchronous refcounty things
+ *
+ * Copyright 2010, 2011 Kent Overstreet <kent.overstreet@gmail.com>
+ * Copyright 2012 Google, Inc.
+ */
+
+#include <linux/debugfs.h>
+#include <linux/module.h>
+#include <linux/seq_file.h>
+
+#include "closure.h"
+
+void closure_queue(struct closure *cl)
+{
+	struct workqueue_struct *wq = cl->wq;
+	if (wq) {
+		INIT_WORK(&cl->work, cl->work.func);
+		BUG_ON(!queue_work(wq, &cl->work));
+	} else
+		cl->fn(cl);
+}
+EXPORT_SYMBOL_GPL(closure_queue);
+
+#define CL_FIELD(type, field)					\
+	case TYPE_ ## type:					\
+	return &container_of(cl, struct type, cl)->field
+
+static struct closure_waitlist *closure_waitlist(struct closure *cl)
+{
+	switch (cl->type) {
+		CL_FIELD(closure_with_waitlist, wait);
+		CL_FIELD(closure_with_waitlist_and_timer, wait);
+	default:
+		return NULL;
+	}
+}
+
+static struct timer_list *closure_timer(struct closure *cl)
+{
+	switch (cl->type) {
+		CL_FIELD(closure_with_timer, timer);
+		CL_FIELD(closure_with_waitlist_and_timer, timer);
+	default:
+		return NULL;
+	}
+}
+
+static inline void closure_put_after_sub(struct closure *cl, int flags)
+{
+	int r = flags & CLOSURE_REMAINING_MASK;
+
+	BUG_ON(flags & CLOSURE_GUARD_MASK);
+	BUG_ON(!r && (flags & ~(CLOSURE_DESTRUCTOR|CLOSURE_BLOCKING)));
+
+	/* Must deliver precisely one wakeup */
+	if (r == 1 && (flags & CLOSURE_SLEEPING))
+		wake_up_process(cl->task);
+
+	if (!r) {
+		if (cl->fn && !(flags & CLOSURE_DESTRUCTOR)) {
+			/* CLOSURE_BLOCKING might be set - clear it */
+			atomic_set(&cl->remaining,
+				   CLOSURE_REMAINING_INITIALIZER);
+			closure_queue(cl);
+		} else {
+			struct closure *parent = cl->parent;
+			struct closure_waitlist *wait = closure_waitlist(cl);
+
+			closure_debug_destroy(cl);
+
+			atomic_set(&cl->remaining, -1);
+
+			if (wait)
+				closure_wake_up(wait);
+
+			if (cl->fn)
+				cl->fn(cl);
+
+			if (parent)
+				closure_put(parent);
+		}
+	}
+}
+
+/* For clearing flags with the same atomic op as a put */
+void closure_sub(struct closure *cl, int v)
+{
+	closure_put_after_sub(cl, atomic_sub_return(v, &cl->remaining));
+}
+EXPORT_SYMBOL_GPL(closure_sub);
+
+void closure_put(struct closure *cl)
+{
+	closure_put_after_sub(cl, atomic_dec_return(&cl->remaining));
+}
+EXPORT_SYMBOL_GPL(closure_put);
+
+static void set_waiting(struct closure *cl, unsigned long f)
+{
+#ifdef CONFIG_BCACHE_CLOSURES_DEBUG
+	cl->waiting_on = f;
+#endif
+}
+
+void __closure_wake_up(struct closure_waitlist *wait_list)
+{
+	struct llist_node *list;
+	struct closure *cl;
+	struct llist_node *reverse = NULL;
+
+	list = llist_del_all(&wait_list->list);
+
+	/* We first reverse the list to preserve FIFO ordering and fairness */
+
+	while (list) {
+		struct llist_node *t = list;
+		list = llist_next(list);
+
+		t->next = reverse;
+		reverse = t;
+	}
+
+	/* Then do the wakeups */
+
+	while (reverse) {
+		cl = container_of(reverse, struct closure, list);
+		reverse = llist_next(reverse);
+
+		set_waiting(cl, 0);
+		closure_sub(cl, CLOSURE_WAITING + 1);
+	}
+}
+EXPORT_SYMBOL_GPL(__closure_wake_up);
+
+bool closure_wait(struct closure_waitlist *list, struct closure *cl)
+{
+	if (atomic_read(&cl->remaining) & CLOSURE_WAITING)
+		return false;
+
+	set_waiting(cl, _RET_IP_);
+	atomic_add(CLOSURE_WAITING + 1, &cl->remaining);
+	llist_add(&cl->list, &list->list);
+
+	return true;
+}
+EXPORT_SYMBOL_GPL(closure_wait);
+
+/**
+ * closure_sync() - sleep until a closure a closure has nothing left to wait on
+ *
+ * Sleeps until the refcount hits 1 - the thread that's running the closure owns
+ * the last refcount.
+ */
+void closure_sync(struct closure *cl)
+{
+	while (1) {
+		__closure_start_sleep(cl);
+		closure_set_ret_ip(cl);
+
+		if ((atomic_read(&cl->remaining) &
+		     CLOSURE_REMAINING_MASK) == 1)
+			break;
+
+		schedule();
+	}
+
+	__closure_end_sleep(cl);
+}
+EXPORT_SYMBOL_GPL(closure_sync);
+
+/**
+ * closure_trylock() - try to acquire the closure, without waiting
+ * @cl:		closure to lock
+ *
+ * Returns true if the closure was succesfully locked.
+ */
+bool closure_trylock(struct closure *cl, struct closure *parent)
+{
+	if (atomic_cmpxchg(&cl->remaining, -1,
+			   CLOSURE_REMAINING_INITIALIZER) != -1)
+		return false;
+
+	closure_set_ret_ip(cl);
+
+	smp_mb();
+	cl->parent = parent;
+	if (parent)
+		closure_get(parent);
+
+	closure_debug_create(cl);
+	return true;
+}
+EXPORT_SYMBOL_GPL(closure_trylock);
+
+void __closure_lock(struct closure *cl, struct closure *parent,
+		    struct closure_waitlist *wait_list)
+{
+	struct closure wait;
+	closure_init_stack(&wait);
+
+	while (1) {
+		if (closure_trylock(cl, parent))
+			return;
+
+		closure_wait_event_sync(wait_list, &wait,
+					atomic_read(&cl->remaining) == -1);
+	}
+}
+EXPORT_SYMBOL_GPL(__closure_lock);
+
+static void closure_delay_timer_fn(unsigned long data)
+{
+	struct closure *cl = (struct closure *) data;
+	closure_sub(cl, CLOSURE_TIMER + 1);
+}
+
+void do_closure_timer_init(struct closure *cl)
+{
+	struct timer_list *timer = closure_timer(cl);
+
+	init_timer(timer);
+	timer->data	= (unsigned long) cl;
+	timer->function = closure_delay_timer_fn;
+}
+EXPORT_SYMBOL_GPL(do_closure_timer_init);
+
+bool __closure_delay(struct closure *cl, unsigned long delay,
+		     struct timer_list *timer)
+{
+	if (atomic_read(&cl->remaining) & CLOSURE_TIMER)
+		return false;
+
+	BUG_ON(timer_pending(timer));
+
+	timer->expires	= jiffies + delay;
+
+	atomic_add(CLOSURE_TIMER + 1, &cl->remaining);
+	add_timer(timer);
+	return true;
+}
+EXPORT_SYMBOL_GPL(__closure_delay);
+
+void __closure_flush(struct closure *cl, struct timer_list *timer)
+{
+	if (del_timer(timer))
+		closure_sub(cl, CLOSURE_TIMER + 1);
+}
+EXPORT_SYMBOL_GPL(__closure_flush);
+
+void __closure_flush_sync(struct closure *cl, struct timer_list *timer)
+{
+	if (del_timer_sync(timer))
+		closure_sub(cl, CLOSURE_TIMER + 1);
+}
+EXPORT_SYMBOL_GPL(__closure_flush_sync);
+
+#ifdef CONFIG_BCACHE_CLOSURES_DEBUG
+
+static LIST_HEAD(closure_list);
+static DEFINE_SPINLOCK(closure_list_lock);
+
+void closure_debug_create(struct closure *cl)
+{
+	unsigned long flags;
+
+	BUG_ON(cl->magic == CLOSURE_MAGIC_ALIVE);
+	cl->magic = CLOSURE_MAGIC_ALIVE;
+
+	spin_lock_irqsave(&closure_list_lock, flags);
+	list_add(&cl->all, &closure_list);
+	spin_unlock_irqrestore(&closure_list_lock, flags);
+}
+EXPORT_SYMBOL_GPL(closure_debug_create);
+
+void closure_debug_destroy(struct closure *cl)
+{
+	unsigned long flags;
+
+	BUG_ON(cl->magic != CLOSURE_MAGIC_ALIVE);
+	cl->magic = CLOSURE_MAGIC_DEAD;
+
+	spin_lock_irqsave(&closure_list_lock, flags);
+	list_del(&cl->all);
+	spin_unlock_irqrestore(&closure_list_lock, flags);
+}
+EXPORT_SYMBOL_GPL(closure_debug_destroy);
+
+static struct dentry *debug;
+
+#define work_data_bits(work) ((unsigned long *)(&(work)->data))
+
+static int debug_seq_show(struct seq_file *f, void *data)
+{
+	struct closure *cl;
+	spin_lock_irq(&closure_list_lock);
+
+	list_for_each_entry(cl, &closure_list, all) {
+		int r = atomic_read(&cl->remaining);
+
+		seq_printf(f, "%p: %pF -> %pf p %p r %i ",
+			   cl, (void *) cl->ip, cl->fn, cl->parent,
+			   r & CLOSURE_REMAINING_MASK);
+
+		seq_printf(f, "%s%s%s%s%s%s\n",
+			   test_bit(WORK_STRUCT_PENDING,
+				    work_data_bits(&cl->work)) ? "Q" : "",
+			   r & CLOSURE_RUNNING	? "R" : "",
+			   r & CLOSURE_BLOCKING	? "B" : "",
+			   r & CLOSURE_STACK	? "S" : "",
+			   r & CLOSURE_SLEEPING	? "Sl" : "",
+			   r & CLOSURE_TIMER	? "T" : "");
+
+		if (r & CLOSURE_WAITING)
+			seq_printf(f, " W %pF\n",
+				   (void *) cl->waiting_on);
+
+		seq_printf(f, "\n");
+	}
+
+	spin_unlock_irq(&closure_list_lock);
+	return 0;
+}
+
+static int debug_seq_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, debug_seq_show, NULL);
+}
+
+static const struct file_operations debug_ops = {
+	.owner		= THIS_MODULE,
+	.open		= debug_seq_open,
+	.read		= seq_read,
+	.release	= single_release
+};
+
+void __init closure_debug_init(void)
+{
+	debug = debugfs_create_file("closures", 0400, NULL, NULL, &debug_ops);
+}
+
+#endif
+
+MODULE_AUTHOR("Kent Overstreet <koverstreet@google.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/md/bcache/closure.h b/drivers/md/bcache/closure.h
new file mode 100644
index 0000000..0003992
--- /dev/null
+++ b/drivers/md/bcache/closure.h
@@ -0,0 +1,672 @@
+#ifndef _LINUX_CLOSURE_H
+#define _LINUX_CLOSURE_H
+
+#include <linux/llist.h>
+#include <linux/sched.h>
+#include <linux/workqueue.h>
+
+/*
+ * Closure is perhaps the most overused and abused term in computer science, but
+ * since I've been unable to come up with anything better you're stuck with it
+ * again.
+ *
+ * What are closures?
+ *
+ * They embed a refcount. The basic idea is they count "things that are in
+ * progress" - in flight bios, some other thread that's doing something else -
+ * anything you might want to wait on.
+ *
+ * The refcount may be manipulated with closure_get() and closure_put().
+ * closure_put() is where many of the interesting things happen, when it causes
+ * the refcount to go to 0.
+ *
+ * Closures can be used to wait on things both synchronously and asynchronously,
+ * and synchronous and asynchronous use can be mixed without restriction. To
+ * wait synchronously, use closure_sync() - you will sleep until your closure's
+ * refcount hits 1.
+ *
+ * To wait asynchronously, use
+ *   continue_at(cl, next_function, workqueue);
+ *
+ * passing it, as you might expect, the function to run when nothing is pending
+ * and the workqueue to run that function out of.
+ *
+ * continue_at() also, critically, is a macro that returns the calling function.
+ * There's good reason for this.
+ *
+ * To use safely closures asynchronously, they must always have a refcount while
+ * they are running owned by the thread that is running them. Otherwise, suppose
+ * you submit some bios and wish to have a function run when they all complete:
+ *
+ * foo_endio(struct bio *bio, int error)
+ * {
+ *	closure_put(cl);
+ * }
+ *
+ * closure_init(cl);
+ *
+ * do_stuff();
+ * closure_get(cl);
+ * bio1->bi_endio = foo_endio;
+ * bio_submit(bio1);
+ *
+ * do_more_stuff();
+ * closure_get(cl);
+ * bio2->bi_endio = foo_endio;
+ * bio_submit(bio2);
+ *
+ * continue_at(cl, complete_some_read, system_wq);
+ *
+ * If closure's refcount started at 0, complete_some_read() could run before the
+ * second bio was submitted - which is almost always not what you want! More
+ * importantly, it wouldn't be possible to say whether the original thread or
+ * complete_some_read()'s thread owned the closure - and whatever state it was
+ * associated with!
+ *
+ * So, closure_init() initializes a closure's refcount to 1 - and when a
+ * closure_fn is run, the refcount will be reset to 1 first.
+ *
+ * Then, the rule is - if you got the refcount with closure_get(), release it
+ * with closure_put() (i.e, in a bio->bi_endio function). If you have a refcount
+ * on a closure because you called closure_init() or you were run out of a
+ * closure - _always_ use continue_at(). Doing so consistently will help
+ * eliminate an entire class of particularly pernicious races.
+ *
+ * For a closure to wait on an arbitrary event, we need to introduce waitlists:
+ *
+ * struct closure_waitlist list;
+ * closure_wait_event(list, cl, condition);
+ * closure_wake_up(wait_list);
+ *
+ * These work analagously to wait_event() and wake_up() - except that instead of
+ * operating on the current thread (for wait_event()) and lists of threads, they
+ * operate on an explicit closure and lists of closures.
+ *
+ * Because it's a closure we can now wait either synchronously or
+ * asynchronously. closure_wait_event() returns the current value of the
+ * condition, and if it returned false continue_at() or closure_sync() can be
+ * used to wait for it to become true.
+ *
+ * It's useful for waiting on things when you can't sleep in the context in
+ * which you must check the condition (perhaps a spinlock held, or you might be
+ * beneath generic_make_request() - in which case you can't sleep on IO).
+ *
+ * closure_wait_event() will wait either synchronously or asynchronously,
+ * depending on whether the closure is in blocking mode or not. You can pick a
+ * mode explicitly with closure_wait_event_sync() and
+ * closure_wait_event_async(), which do just what you might expect.
+ *
+ * Lastly, you might have a wait list dedicated to a specific event, and have no
+ * need for specifying the condition - you just want to wait until someone runs
+ * closure_wake_up() on the appropriate wait list. In that case, just use
+ * closure_wait(). It will return either true or false, depending on whether the
+ * closure was already on a wait list or not - a closure can only be on one wait
+ * list at a time.
+ *
+ * Parents:
+ *
+ * closure_init() takes two arguments - it takes the closure to initialize, and
+ * a (possibly null) parent.
+ *
+ * If parent is non null, the new closure will have a refcount for its lifetime;
+ * a closure is considered to be "finished" when its refcount hits 0 and the
+ * function to run is null. Hence
+ *
+ * continue_at(cl, NULL, NULL);
+ *
+ * returns up the (spaghetti) stack of closures, precisely like normal return
+ * returns up the C stack. continue_at() with non null fn is better thought of
+ * as doing a tail call.
+ *
+ * All this implies that a closure should typically be embedded in a particular
+ * struct (which its refcount will normally control the lifetime of), and that
+ * struct can very much be thought of as a stack frame.
+ *
+ * Locking:
+ *
+ * Closures are based on work items but they can be thought of as more like
+ * threads - in that like threads and unlike work items they have a well
+ * defined lifetime; they are created (with closure_init()) and eventually
+ * complete after a continue_at(cl, NULL, NULL).
+ *
+ * Suppose you've got some larger structure with a closure embedded in it that's
+ * used for periodically doing garbage collection. You only want one garbage
+ * collection happening at a time, so the natural thing to do is protect it with
+ * a lock. However, it's difficult to use a lock protecting a closure correctly
+ * because the unlock should come after the last continue_to() (additionally, if
+ * you're using the closure asynchronously a mutex won't work since a mutex has
+ * to be unlocked by the same process that locked it).
+ *
+ * So to make it less error prone and more efficient, we also have the ability
+ * to use closures as locks:
+ *
+ * closure_init_unlocked();
+ * closure_trylock();
+ *
+ * That's all we need for trylock() - the last closure_put() implicitly unlocks
+ * it for you.  But for closure_lock(), we also need a wait list:
+ *
+ * struct closure_with_waitlist frobnicator_cl;
+ *
+ * closure_init_unlocked(&frobnicator_cl);
+ * closure_lock(&frobnicator_cl);
+ *
+ * A closure_with_waitlist embeds a closure and a wait list - much like struct
+ * delayed_work embeds a work item and a timer_list. The important thing is, use
+ * it exactly like you would a regular closure and closure_put() will magically
+ * handle everything for you.
+ *
+ * We've got closures that embed timers, too. They're called, appropriately
+ * enough:
+ * struct closure_with_timer;
+ *
+ * This gives you access to closure_delay(). It takes a refcount for a specified
+ * number of jiffies - you could then call closure_sync() (for a slightly
+ * convoluted version of msleep()) or continue_at() - which gives you the same
+ * effect as using a delayed work item, except you can reuse the work_struct
+ * already embedded in struct closure.
+ *
+ * Lastly, there's struct closure_with_waitlist_and_timer. It does what you
+ * probably expect, if you happen to need the features of both. (You don't
+ * really want to know how all this is implemented, but if I've done my job
+ * right you shouldn't have to care).
+ */
+
+struct closure;
+typedef void (closure_fn) (struct closure *);
+
+struct closure_waitlist {
+	struct llist_head	list;
+};
+
+enum closure_type {
+	TYPE_closure				= 0,
+	TYPE_closure_with_waitlist		= 1,
+	TYPE_closure_with_timer			= 2,
+	TYPE_closure_with_waitlist_and_timer	= 3,
+	MAX_CLOSURE_TYPE			= 3,
+};
+
+enum closure_state {
+	/*
+	 * CLOSURE_BLOCKING: Causes closure_wait_event() to block, instead of
+	 * waiting asynchronously
+	 *
+	 * CLOSURE_WAITING: Set iff the closure is on a waitlist. Must be set by
+	 * the thread that owns the closure, and cleared by the thread that's
+	 * waking up the closure.
+	 *
+	 * CLOSURE_SLEEPING: Must be set before a thread uses a closure to sleep
+	 * - indicates that cl->task is valid and closure_put() may wake it up.
+	 * Only set or cleared by the thread that owns the closure.
+	 *
+	 * CLOSURE_TIMER: Analagous to CLOSURE_WAITING, indicates that a closure
+	 * has an outstanding timer. Must be set by the thread that owns the
+	 * closure, and cleared by the timer function when the timer goes off.
+	 *
+	 * The rest are for debugging and don't affect behaviour:
+	 *
+	 * CLOSURE_RUNNING: Set when a closure is running (i.e. by
+	 * closure_init() and when closure_put() runs then next function), and
+	 * must be cleared before remaining hits 0. Primarily to help guard
+	 * against incorrect usage and accidentally transferring references.
+	 * continue_at() and closure_return() clear it for you, if you're doing
+	 * something unusual you can use closure_set_dead() which also helps
+	 * annotate where references are being transferred.
+	 *
+	 * CLOSURE_STACK: Sanity check - remaining should never hit 0 on a
+	 * closure with this flag set
+	 */
+
+	CLOSURE_BITS_START	= (1 << 19),
+	CLOSURE_DESTRUCTOR	= (1 << 19),
+	CLOSURE_BLOCKING	= (1 << 21),
+	CLOSURE_WAITING		= (1 << 23),
+	CLOSURE_SLEEPING	= (1 << 25),
+	CLOSURE_TIMER		= (1 << 27),
+	CLOSURE_RUNNING		= (1 << 29),
+	CLOSURE_STACK		= (1 << 31),
+};
+
+#define CLOSURE_GUARD_MASK					\
+	((CLOSURE_DESTRUCTOR|CLOSURE_BLOCKING|CLOSURE_WAITING|	\
+	  CLOSURE_SLEEPING|CLOSURE_TIMER|CLOSURE_RUNNING|CLOSURE_STACK) << 1)
+
+#define CLOSURE_REMAINING_MASK		(CLOSURE_BITS_START - 1)
+#define CLOSURE_REMAINING_INITIALIZER	(1|CLOSURE_RUNNING)
+
+struct closure {
+	union {
+		struct {
+			struct workqueue_struct *wq;
+			struct task_struct	*task;
+			struct llist_node	list;
+			closure_fn		*fn;
+		};
+		struct work_struct	work;
+	};
+
+	struct closure		*parent;
+
+	atomic_t		remaining;
+
+	enum closure_type	type;
+
+#ifdef CONFIG_BCACHE_CLOSURES_DEBUG
+#define CLOSURE_MAGIC_DEAD	0xc054dead
+#define CLOSURE_MAGIC_ALIVE	0xc054a11e
+
+	unsigned		magic;
+	struct list_head	all;
+	unsigned long		ip;
+	unsigned long		waiting_on;
+#endif
+};
+
+struct closure_with_waitlist {
+	struct closure		cl;
+	struct closure_waitlist	wait;
+};
+
+struct closure_with_timer {
+	struct closure		cl;
+	struct timer_list	timer;
+};
+
+struct closure_with_waitlist_and_timer {
+	struct closure		cl;
+	struct closure_waitlist	wait;
+	struct timer_list	timer;
+};
+
+extern unsigned invalid_closure_type(void);
+
+#define __CLOSURE_TYPE(cl, _t)						\
+	  __builtin_types_compatible_p(typeof(cl), struct _t)		\
+		? TYPE_ ## _t :						\
+
+#define __closure_type(cl)						\
+(									\
+	__CLOSURE_TYPE(cl, closure)					\
+	__CLOSURE_TYPE(cl, closure_with_waitlist)			\
+	__CLOSURE_TYPE(cl, closure_with_timer)				\
+	__CLOSURE_TYPE(cl, closure_with_waitlist_and_timer)		\
+	invalid_closure_type()						\
+)
+
+void closure_sub(struct closure *cl, int v);
+void closure_put(struct closure *cl);
+void closure_queue(struct closure *cl);
+void __closure_wake_up(struct closure_waitlist *list);
+bool closure_wait(struct closure_waitlist *list, struct closure *cl);
+void closure_sync(struct closure *cl);
+
+bool closure_trylock(struct closure *cl, struct closure *parent);
+void __closure_lock(struct closure *cl, struct closure *parent,
+		    struct closure_waitlist *wait_list);
+
+void do_closure_timer_init(struct closure *cl);
+bool __closure_delay(struct closure *cl, unsigned long delay,
+		     struct timer_list *timer);
+void __closure_flush(struct closure *cl, struct timer_list *timer);
+void __closure_flush_sync(struct closure *cl, struct timer_list *timer);
+
+#ifdef CONFIG_BCACHE_CLOSURES_DEBUG
+
+void closure_debug_init(void);
+void closure_debug_create(struct closure *cl);
+void closure_debug_destroy(struct closure *cl);
+
+#else
+
+static inline void closure_debug_init(void) {}
+static inline void closure_debug_create(struct closure *cl) {}
+static inline void closure_debug_destroy(struct closure *cl) {}
+
+#endif
+
+static inline void closure_set_ip(struct closure *cl)
+{
+#ifdef CONFIG_BCACHE_CLOSURES_DEBUG
+	cl->ip = _THIS_IP_;
+#endif
+}
+
+static inline void closure_set_ret_ip(struct closure *cl)
+{
+#ifdef CONFIG_BCACHE_CLOSURES_DEBUG
+	cl->ip = _RET_IP_;
+#endif
+}
+
+static inline void closure_get(struct closure *cl)
+{
+#ifdef CONFIG_BCACHE_CLOSURES_DEBUG
+	BUG_ON((atomic_inc_return(&cl->remaining) &
+		CLOSURE_REMAINING_MASK) <= 1);
+#else
+	atomic_inc(&cl->remaining);
+#endif
+}
+
+static inline void closure_set_stopped(struct closure *cl)
+{
+	atomic_sub(CLOSURE_RUNNING, &cl->remaining);
+}
+
+static inline bool closure_is_stopped(struct closure *cl)
+{
+	return !(atomic_read(&cl->remaining) & CLOSURE_RUNNING);
+}
+
+static inline bool closure_is_unlocked(struct closure *cl)
+{
+	return atomic_read(&cl->remaining) == -1;
+}
+
+static inline void do_closure_init(struct closure *cl, struct closure *parent,
+				   bool running)
+{
+	switch (cl->type) {
+	case TYPE_closure_with_timer:
+	case TYPE_closure_with_waitlist_and_timer:
+		do_closure_timer_init(cl);
+	default:
+		break;
+	}
+
+	cl->parent = parent;
+	if (parent)
+		closure_get(parent);
+
+	if (running) {
+		closure_debug_create(cl);
+		atomic_set(&cl->remaining, CLOSURE_REMAINING_INITIALIZER);
+	} else
+		atomic_set(&cl->remaining, -1);
+
+	closure_set_ip(cl);
+}
+
+/*
+ * Hack to get at the embedded closure if there is one, by doing an unsafe cast:
+ * the result of __closure_type() is thrown away, it's used merely for type
+ * checking.
+ */
+#define __to_internal_closure(cl)				\
+({								\
+	BUILD_BUG_ON(__closure_type(*cl) > MAX_CLOSURE_TYPE);	\
+	(struct closure *) cl;					\
+})
+
+#define closure_init_type(cl, parent, running)			\
+do {								\
+	struct closure *_cl = __to_internal_closure(cl);	\
+	_cl->type = __closure_type(*(cl));			\
+	do_closure_init(_cl, parent, running);			\
+} while (0)
+
+/**
+ * __closure_init() - Initialize a closure, skipping the memset()
+ *
+ * May be used instead of closure_init() when memory has already been zeroed.
+ */
+#define __closure_init(cl, parent)				\
+	closure_init_type(cl, parent, true)
+
+/**
+ * closure_init() - Initialize a closure, setting the refcount to 1
+ * @cl:		closure to initialize
+ * @parent:	parent of the new closure. cl will take a refcount on it for its
+ *		lifetime; may be NULL.
+ */
+#define closure_init(cl, parent)				\
+do {								\
+	memset((cl), 0, sizeof(*(cl)));				\
+	__closure_init(cl, parent);				\
+} while (0)
+
+static inline void closure_init_stack(struct closure *cl)
+{
+	memset(cl, 0, sizeof(struct closure));
+	atomic_set(&cl->remaining, CLOSURE_REMAINING_INITIALIZER|
+		   CLOSURE_BLOCKING|CLOSURE_STACK);
+}
+
+/**
+ * closure_init_unlocked() - Initialize a closure but leave it unlocked.
+ * @cl:		closure to initialize
+ *
+ * For when the closure will be used as a lock. The closure may not be used
+ * until after a closure_lock() or closure_trylock().
+ */
+#define closure_init_unlocked(cl)				\
+do {								\
+	memset((cl), 0, sizeof(*(cl)));				\
+	closure_init_type(cl, NULL, false);			\
+} while (0)
+
+/**
+ * closure_lock() - lock and initialize a closure.
+ * @cl:		the closure to lock
+ * @parent:	the new parent for this closure
+ *
+ * The closure must be of one of the types that has a waitlist (otherwise we
+ * wouldn't be able to sleep on contention).
+ *
+ * @parent has exactly the same meaning as in closure_init(); if non null, the
+ * closure will take a reference on @parent which will be released when it is
+ * unlocked.
+ */
+#define closure_lock(cl, parent)				\
+	__closure_lock(__to_internal_closure(cl), parent, &(cl)->wait)
+
+/**
+ * closure_delay() - delay some number of jiffies
+ * @cl:		the closure that will sleep
+ * @delay:	the delay in jiffies
+ *
+ * Takes a refcount on @cl which will be released after @delay jiffies; this may
+ * be used to have a function run after a delay with continue_at(), or
+ * closure_sync() may be used for a convoluted version of msleep().
+ */
+#define closure_delay(cl, delay)			\
+	__closure_delay(__to_internal_closure(cl), delay, &(cl)->timer)
+
+#define closure_flush(cl)				\
+	__closure_flush(__to_internal_closure(cl), &(cl)->timer)
+
+#define closure_flush_sync(cl)				\
+	__closure_flush_sync(__to_internal_closure(cl), &(cl)->timer)
+
+static inline void __closure_end_sleep(struct closure *cl)
+{
+	__set_current_state(TASK_RUNNING);
+
+	if (atomic_read(&cl->remaining) & CLOSURE_SLEEPING)
+		atomic_sub(CLOSURE_SLEEPING, &cl->remaining);
+}
+
+static inline void __closure_start_sleep(struct closure *cl)
+{
+	closure_set_ip(cl);
+	cl->task = current;
+	set_current_state(TASK_UNINTERRUPTIBLE);
+
+	if (!(atomic_read(&cl->remaining) & CLOSURE_SLEEPING))
+		atomic_add(CLOSURE_SLEEPING, &cl->remaining);
+}
+
+/**
+ * closure_blocking() - returns true if the closure is in blocking mode.
+ *
+ * If a closure is in blocking mode, closure_wait_event() will sleep until the
+ * condition is true instead of waiting asynchronously.
+ */
+static inline bool closure_blocking(struct closure *cl)
+{
+	return atomic_read(&cl->remaining) & CLOSURE_BLOCKING;
+}
+
+/**
+ * set_closure_blocking() - put a closure in blocking mode.
+ *
+ * If a closure is in blocking mode, closure_wait_event() will sleep until the
+ * condition is true instead of waiting asynchronously.
+ *
+ * Not thread safe - can only be called by the thread running the closure.
+ */
+static inline void set_closure_blocking(struct closure *cl)
+{
+	if (!closure_blocking(cl))
+		atomic_add(CLOSURE_BLOCKING, &cl->remaining);
+}
+
+/*
+ * Not thread safe - can only be called by the thread running the closure.
+ */
+static inline void clear_closure_blocking(struct closure *cl)
+{
+	if (closure_blocking(cl))
+		atomic_sub(CLOSURE_BLOCKING, &cl->remaining);
+}
+
+/**
+ * closure_wake_up() - wake up all closures on a wait list.
+ */
+static inline void closure_wake_up(struct closure_waitlist *list)
+{
+	smp_mb();
+	__closure_wake_up(list);
+}
+
+/*
+ * Wait on an event, synchronously or asynchronously - analogous to wait_event()
+ * but for closures.
+ *
+ * The loop is oddly structured so as to avoid a race; we must check the
+ * condition again after we've added ourself to the waitlist. We know if we were
+ * already on the waitlist because closure_wait() returns false; thus, we only
+ * schedule or break if closure_wait() returns false. If it returns true, we
+ * just loop again - rechecking the condition.
+ *
+ * The __closure_wake_up() is necessary because we may race with the event
+ * becoming true; i.e. we see event false -> wait -> recheck condition, but the
+ * thread that made the event true may have called closure_wake_up() before we
+ * added ourself to the wait list.
+ *
+ * We have to call closure_sync() at the end instead of just
+ * __closure_end_sleep() because a different thread might've called
+ * closure_wake_up() before us and gotten preempted before they dropped the
+ * refcount on our closure. If this was a stack allocated closure, that would be
+ * bad.
+ */
+#define __closure_wait_event(list, cl, condition, _block)		\
+({									\
+	bool block = _block;						\
+	typeof(condition) ret;						\
+									\
+	while (1) {							\
+		ret = (condition);					\
+		if (ret) {						\
+			__closure_wake_up(list);			\
+			if (block)					\
+				closure_sync(cl);			\
+									\
+			break;						\
+		}							\
+									\
+		if (block)						\
+			__closure_start_sleep(cl);			\
+									\
+		if (!closure_wait(list, cl)) {				\
+			if (!block)					\
+				break;					\
+									\
+			schedule();					\
+		}							\
+	}								\
+									\
+	ret;								\
+})
+
+/**
+ * closure_wait_event() - wait on a condition, synchronously or asynchronously.
+ * @list:	the wait list to wait on
+ * @cl:		the closure that is doing the waiting
+ * @condition:	a C expression for the event to wait for
+ *
+ * If the closure is in blocking mode, sleeps until the @condition evaluates to
+ * true - exactly like wait_event().
+ *
+ * If the closure is not in blocking mode, waits asynchronously; if the
+ * condition is currently false the @cl is put onto @list and returns. @list
+ * owns a refcount on @cl; closure_sync() or continue_at() may be used later to
+ * wait for another thread to wake up @list, which drops the refcount on @cl.
+ *
+ * Returns the value of @condition; @cl will be on @list iff @condition was
+ * false.
+ *
+ * closure_wake_up(@list) must be called after changing any variable that could
+ * cause @condition to become true.
+ */
+#define closure_wait_event(list, cl, condition)				\
+	__closure_wait_event(list, cl, condition, closure_blocking(cl))
+
+#define closure_wait_event_async(list, cl, condition)			\
+	__closure_wait_event(list, cl, condition, false)
+
+#define closure_wait_event_sync(list, cl, condition)			\
+	__closure_wait_event(list, cl, condition, true)
+
+static inline void set_closure_fn(struct closure *cl, closure_fn *fn,
+				  struct workqueue_struct *wq)
+{
+	BUG_ON(object_is_on_stack(cl));
+	closure_set_ip(cl);
+	cl->fn = fn;
+	cl->wq = wq;
+	/* between atomic_dec() in closure_put() */
+	smp_mb__before_atomic_dec();
+}
+
+#define continue_at(_cl, _fn, _wq)					\
+do {									\
+	set_closure_fn(_cl, _fn, _wq);					\
+	closure_sub(_cl, CLOSURE_RUNNING + 1);				\
+	return;								\
+} while (0)
+
+#define closure_return(_cl)	continue_at((_cl), NULL, NULL)
+
+#define continue_at_nobarrier(_cl, _fn, _wq)				\
+do {									\
+	set_closure_fn(_cl, _fn, _wq);					\
+	closure_queue(cl);						\
+	return;								\
+} while (0)
+
+#define closure_return_with_destructor(_cl, _destructor)		\
+do {									\
+	set_closure_fn(_cl, _destructor, NULL);				\
+	closure_sub(_cl, CLOSURE_RUNNING - CLOSURE_DESTRUCTOR + 1);	\
+	return;								\
+} while (0)
+
+static inline void closure_call(struct closure *cl, closure_fn fn,
+				struct workqueue_struct *wq,
+				struct closure *parent)
+{
+	closure_init(cl, parent);
+	continue_at_nobarrier(cl, fn, wq);
+}
+
+static inline void closure_trylock_call(struct closure *cl, closure_fn fn,
+					struct workqueue_struct *wq,
+					struct closure *parent)
+{
+	if (closure_trylock(cl, parent))
+		continue_at_nobarrier(cl, fn, wq);
+}
+
+#endif /* _LINUX_CLOSURE_H */
diff --git a/drivers/md/bcache/debug.c b/drivers/md/bcache/debug.c
new file mode 100644
index 0000000..732234d
--- /dev/null
+++ b/drivers/md/bcache/debug.c
@@ -0,0 +1,563 @@
+/*
+ * Assorted bcache debug code
+ *
+ * Copyright 2010, 2011 Kent Overstreet <kent.overstreet@gmail.com>
+ * Copyright 2012 Google, Inc.
+ */
+
+#include "bcache.h"
+#include "btree.h"
+#include "debug.h"
+#include "request.h"
+
+#include <linux/console.h>
+#include <linux/debugfs.h>
+#include <linux/module.h>
+#include <linux/random.h>
+#include <linux/seq_file.h>
+
+static struct dentry *debug;
+
+const char *bch_ptr_status(struct cache_set *c, const struct bkey *k)
+{
+	unsigned i;
+
+	for (i = 0; i < KEY_PTRS(k); i++)
+		if (ptr_available(c, k, i)) {
+			struct cache *ca = PTR_CACHE(c, k, i);
+			size_t bucket = PTR_BUCKET_NR(c, k, i);
+			size_t r = bucket_remainder(c, PTR_OFFSET(k, i));
+
+			if (KEY_SIZE(k) + r > c->sb.bucket_size)
+				return "bad, length too big";
+			if (bucket <  ca->sb.first_bucket)
+				return "bad, short offset";
+			if (bucket >= ca->sb.nbuckets)
+				return "bad, offset past end of device";
+			if (ptr_stale(c, k, i))
+				return "stale";
+		}
+
+	if (!bkey_cmp(k, &ZERO_KEY))
+		return "bad, null key";
+	if (!KEY_PTRS(k))
+		return "bad, no pointers";
+	if (!KEY_SIZE(k))
+		return "zeroed key";
+	return "";
+}
+
+struct keyprint_hack bch_pkey(const struct bkey *k)
+{
+	unsigned i = 0;
+	struct keyprint_hack r;
+	char *out = r.s, *end = r.s + KEYHACK_SIZE;
+
+#define p(...)	(out += scnprintf(out, end - out, __VA_ARGS__))
+
+	p("%llu:%llu len %llu -> [", KEY_INODE(k), KEY_OFFSET(k), KEY_SIZE(k));
+
+	if (KEY_PTRS(k))
+		while (1) {
+			p("%llu:%llu gen %llu",
+			  PTR_DEV(k, i), PTR_OFFSET(k, i), PTR_GEN(k, i));
+
+			if (++i == KEY_PTRS(k))
+				break;
+
+			p(", ");
+		}
+
+	p("]");
+
+	if (KEY_DIRTY(k))
+		p(" dirty");
+	if (KEY_CSUM(k))
+		p(" cs%llu %llx", KEY_CSUM(k), k->ptr[1]);
+#undef p
+	return r;
+}
+
+struct keyprint_hack bch_pbtree(const struct btree *b)
+{
+	struct keyprint_hack r;
+
+	snprintf(r.s, 40, "%li level %i/%i", PTR_BUCKET_NR(b->c, &b->key, 0),
+		 b->level, b->c->root ? b->c->root->level : -1);
+	return r;
+}
+
+#if defined(CONFIG_BCACHE_DEBUG) || defined(CONFIG_BCACHE_EDEBUG)
+
+static bool skipped_backwards(struct btree *b, struct bkey *k)
+{
+	return bkey_cmp(k, (!b->level)
+			? &START_KEY(bkey_next(k))
+			: bkey_next(k)) > 0;
+}
+
+static void dump_bset(struct btree *b, struct bset *i)
+{
+	struct bkey *k;
+	unsigned j;
+
+	for (k = i->start; k < end(i); k = bkey_next(k)) {
+		printk(KERN_ERR "block %zu key %zi/%u: %s", index(i, b),
+		       (uint64_t *) k - i->d, i->keys, pkey(k));
+
+		for (j = 0; j < KEY_PTRS(k); j++) {
+			size_t n = PTR_BUCKET_NR(b->c, k, j);
+			printk(" bucket %zu", n);
+
+			if (n >= b->c->sb.first_bucket && n < b->c->sb.nbuckets)
+				printk(" prio %i",
+				       PTR_BUCKET(b->c, k, j)->prio);
+		}
+
+		printk(" %s\n", bch_ptr_status(b->c, k));
+
+		if (bkey_next(k) < end(i) &&
+		    skipped_backwards(b, k))
+			printk(KERN_ERR "Key skipped backwards\n");
+	}
+}
+
+#endif
+
+#ifdef CONFIG_BCACHE_DEBUG
+
+void bch_btree_verify(struct btree *b, struct bset *new)
+{
+	struct btree *v = b->c->verify_data;
+	struct closure cl;
+	closure_init_stack(&cl);
+
+	if (!b->c->verify)
+		return;
+
+	closure_wait_event(&b->io.wait, &cl,
+			   atomic_read(&b->io.cl.remaining) == -1);
+
+	mutex_lock(&b->c->verify_lock);
+
+	bkey_copy(&v->key, &b->key);
+	v->written = 0;
+	v->level = b->level;
+
+	bch_btree_read(v);
+	closure_wait_event(&v->io.wait, &cl,
+			   atomic_read(&b->io.cl.remaining) == -1);
+
+	if (new->keys != v->sets[0].data->keys ||
+	    memcmp(new->start,
+		   v->sets[0].data->start,
+		   (void *) end(new) - (void *) new->start)) {
+		unsigned i, j;
+
+		console_lock();
+
+		printk(KERN_ERR "*** original memory node:\n");
+		for (i = 0; i <= b->nsets; i++)
+			dump_bset(b, b->sets[i].data);
+
+		printk(KERN_ERR "*** sorted memory node:\n");
+		dump_bset(b, new);
+
+		printk(KERN_ERR "*** on disk node:\n");
+		dump_bset(v, v->sets[0].data);
+
+		for (j = 0; j < new->keys; j++)
+			if (new->d[j] != v->sets[0].data->d[j])
+				break;
+
+		console_unlock();
+		panic("verify failed at %u\n", j);
+	}
+
+	mutex_unlock(&b->c->verify_lock);
+}
+
+static void data_verify_endio(struct bio *bio, int error)
+{
+	struct closure *cl = bio->bi_private;
+	closure_put(cl);
+}
+
+void bch_data_verify(struct search *s)
+{
+	char name[BDEVNAME_SIZE];
+	struct cached_dev *dc = container_of(s->d, struct cached_dev, disk);
+	struct closure *cl = &s->cl;
+	struct bio *check;
+	struct bio_vec *bv;
+	int i;
+
+	if (!s->unaligned_bvec)
+		bio_for_each_segment(bv, s->orig_bio, i)
+			bv->bv_offset = 0, bv->bv_len = PAGE_SIZE;
+
+	check = bio_clone(s->orig_bio, GFP_NOIO);
+	if (!check)
+		return;
+
+	if (bch_bio_alloc_pages(check, GFP_NOIO))
+		goto out_put;
+
+	check->bi_rw		= READ_SYNC;
+	check->bi_private	= cl;
+	check->bi_end_io	= data_verify_endio;
+
+	closure_bio_submit(check, cl, &dc->disk);
+	closure_sync(cl);
+
+	bio_for_each_segment(bv, s->orig_bio, i) {
+		void *p1 = kmap(bv->bv_page);
+		void *p2 = kmap(check->bi_io_vec[i].bv_page);
+
+		if (memcmp(p1 + bv->bv_offset,
+			   p2 + bv->bv_offset,
+			   bv->bv_len))
+			printk(KERN_ERR
+			       "bcache (%s): verify failed at sector %llu\n",
+			       bdevname(dc->bdev, name),
+			       (uint64_t) s->orig_bio->bi_sector);
+
+		kunmap(bv->bv_page);
+		kunmap(check->bi_io_vec[i].bv_page);
+	}
+
+	__bio_for_each_segment(bv, check, i, 0)
+		__free_page(bv->bv_page);
+out_put:
+	bio_put(check);
+}
+
+#endif
+
+#ifdef CONFIG_BCACHE_EDEBUG
+
+unsigned bch_count_data(struct btree *b)
+{
+	unsigned ret = 0;
+	struct btree_iter iter;
+	struct bkey *k;
+
+	if (!b->level)
+		for_each_key(b, k, &iter)
+			ret += KEY_SIZE(k);
+	return ret;
+}
+
+static void vdump_bucket_and_panic(struct btree *b, const char *fmt,
+				   va_list args)
+{
+	unsigned i;
+
+	console_lock();
+
+	for (i = 0; i <= b->nsets; i++)
+		dump_bset(b, b->sets[i].data);
+
+	vprintk(fmt, args);
+
+	console_unlock();
+
+	panic("at %s\n", pbtree(b));
+}
+
+void bch_check_key_order_msg(struct btree *b, struct bset *i,
+			     const char *fmt, ...)
+{
+	struct bkey *k;
+
+	if (!i->keys)
+		return;
+
+	for (k = i->start; bkey_next(k) < end(i); k = bkey_next(k))
+		if (skipped_backwards(b, k)) {
+			va_list args;
+			va_start(args, fmt);
+
+			vdump_bucket_and_panic(b, fmt, args);
+			va_end(args);
+		}
+}
+
+void bch_check_keys(struct btree *b, const char *fmt, ...)
+{
+	va_list args;
+	struct bkey *k, *p = NULL;
+	struct btree_iter iter;
+
+	if (b->level)
+		return;
+
+	for_each_key(b, k, &iter) {
+		if (p && bkey_cmp(&START_KEY(p), &START_KEY(k)) > 0) {
+			printk(KERN_ERR "Keys out of order:\n");
+			goto bug;
+		}
+
+		if (bch_ptr_invalid(b, k))
+			continue;
+
+		if (p && bkey_cmp(p, &START_KEY(k)) > 0) {
+			printk(KERN_ERR "Overlapping keys:\n");
+			goto bug;
+		}
+		p = k;
+	}
+	return;
+bug:
+	va_start(args, fmt);
+	vdump_bucket_and_panic(b, fmt, args);
+	va_end(args);
+}
+
+#endif
+
+#ifdef CONFIG_DEBUG_FS
+
+/* XXX: cache set refcounting */
+
+struct dump_iterator {
+	char			buf[PAGE_SIZE];
+	size_t			bytes;
+	struct cache_set	*c;
+	struct keybuf		keys;
+};
+
+static bool dump_pred(struct keybuf *buf, struct bkey *k)
+{
+	return true;
+}
+
+static ssize_t bch_dump_read(struct file *file, char __user *buf,
+			     size_t size, loff_t *ppos)
+{
+	struct dump_iterator *i = file->private_data;
+	ssize_t ret = 0;
+
+	while (size) {
+		struct keybuf_key *w;
+		unsigned bytes = min(i->bytes, size);
+
+		int err = copy_to_user(buf, i->buf, bytes);
+		if (err)
+			return err;
+
+		ret	 += bytes;
+		buf	 += bytes;
+		size	 -= bytes;
+		i->bytes -= bytes;
+		memmove(i->buf, i->buf + bytes, i->bytes);
+
+		if (i->bytes)
+			break;
+
+		w = bch_keybuf_next_rescan(i->c, &i->keys, &MAX_KEY);
+		if (!w)
+			break;
+
+		i->bytes = snprintf(i->buf, PAGE_SIZE, "%s\n", pkey(&w->key));
+		bch_keybuf_del(&i->keys, w);
+	}
+
+	return ret;
+}
+
+static int bch_dump_open(struct inode *inode, struct file *file)
+{
+	struct cache_set *c = inode->i_private;
+	struct dump_iterator *i;
+
+	i = kzalloc(sizeof(struct dump_iterator), GFP_KERNEL);
+	if (!i)
+		return -ENOMEM;
+
+	file->private_data = i;
+	i->c = c;
+	bch_keybuf_init(&i->keys, dump_pred);
+	i->keys.last_scanned = KEY(0, 0, 0);
+
+	return 0;
+}
+
+static int bch_dump_release(struct inode *inode, struct file *file)
+{
+	kfree(file->private_data);
+	return 0;
+}
+
+static const struct file_operations cache_set_debug_ops = {
+	.owner		= THIS_MODULE,
+	.open		= bch_dump_open,
+	.read		= bch_dump_read,
+	.release	= bch_dump_release
+};
+
+void bch_debug_init_cache_set(struct cache_set *c)
+{
+	if (!IS_ERR_OR_NULL(debug)) {
+		char name[50];
+		snprintf(name, 50, "bcache-%pU", c->sb.set_uuid);
+
+		c->debug = debugfs_create_file(name, 0400, debug, c,
+					       &cache_set_debug_ops);
+	}
+}
+
+#endif
+
+#ifdef CONFIG_BCACHE_DEBUG
+static ssize_t btree_fuzz(struct kobject *k, struct kobj_attribute *a,
+			  const char *buffer, size_t size)
+{
+	void dump(struct btree *b)
+	{
+		struct bset *i;
+
+		for (i = b->sets[0].data;
+		     index(i, b) < btree_blocks(b) &&
+		     i->seq == b->sets[0].data->seq;
+		     i = ((void *) i) + set_blocks(i, b->c) * block_bytes(b->c))
+			dump_bset(b, i);
+	}
+
+	struct cache_sb *sb;
+	struct cache_set *c;
+	struct btree *all[3], *b, *fill, *orig;
+	int j;
+
+	struct btree_op op;
+	bch_btree_op_init_stack(&op);
+
+	sb = kzalloc(sizeof(struct cache_sb), GFP_KERNEL);
+	if (!sb)
+		return -ENOMEM;
+
+	sb->bucket_size = 128;
+	sb->block_size = 4;
+
+	c = bch_cache_set_alloc(sb);
+	if (!c)
+		return -ENOMEM;
+
+	for (j = 0; j < 3; j++) {
+		BUG_ON(list_empty(&c->btree_cache));
+		all[j] = list_first_entry(&c->btree_cache, struct btree, list);
+		list_del_init(&all[j]->list);
+
+		all[j]->key = KEY(0, 0, c->sb.bucket_size);
+		bkey_copy_key(&all[j]->key, &MAX_KEY);
+	}
+
+	b = all[0];
+	fill = all[1];
+	orig = all[2];
+
+	while (1) {
+		for (j = 0; j < 3; j++)
+			all[j]->written = all[j]->nsets = 0;
+
+		bch_bset_init_next(b);
+
+		while (1) {
+			struct bset *i = write_block(b);
+			struct bkey *k = op.keys.top;
+			unsigned rand;
+
+			bkey_init(k);
+			rand = get_random_int();
+
+			op.type = rand & 1
+				? BTREE_INSERT
+				: BTREE_REPLACE;
+			rand >>= 1;
+
+			SET_KEY_SIZE(k, bucket_remainder(c, rand));
+			rand >>= c->bucket_bits;
+			rand &= 1024 * 512 - 1;
+			rand += c->sb.bucket_size;
+			SET_KEY_OFFSET(k, rand);
+#if 0
+			SET_KEY_PTRS(k, 1);
+#endif
+			bch_keylist_push(&op.keys);
+			bch_btree_insert_keys(b, &op);
+
+			if (should_split(b) ||
+			    set_blocks(i, b->c) !=
+			    __set_blocks(i, i->keys + 15, b->c)) {
+				i->csum = csum_set(i);
+
+				memcpy(write_block(fill),
+				       i, set_bytes(i));
+
+				b->written += set_blocks(i, b->c);
+				fill->written = b->written;
+				if (b->written == btree_blocks(b))
+					break;
+
+				bch_btree_sort_lazy(b);
+				bch_bset_init_next(b);
+			}
+		}
+
+		memcpy(orig->sets[0].data,
+		       fill->sets[0].data,
+		       btree_bytes(c));
+
+		bch_btree_sort(b);
+		fill->written = 0;
+		bch_btree_read_done(&fill->io.cl);
+
+		if (b->sets[0].data->keys != fill->sets[0].data->keys ||
+		    memcmp(b->sets[0].data->start,
+			   fill->sets[0].data->start,
+			   b->sets[0].data->keys * sizeof(uint64_t))) {
+			struct bset *i = b->sets[0].data;
+			struct bkey *k, *l;
+
+			for (k = i->start,
+			     l = fill->sets[0].data->start;
+			     k < end(i);
+			     k = bkey_next(k), l = bkey_next(l))
+				if (bkey_cmp(k, l) ||
+				    KEY_SIZE(k) != KEY_SIZE(l))
+					pr_err("key %zi differs: %s != %s",
+					       (uint64_t *) k - i->d,
+					       pkey(k), pkey(l));
+
+			for (j = 0; j < 3; j++) {
+				pr_err("**** Set %i ****", j);
+				dump(all[j]);
+			}
+			panic("\n");
+		}
+
+		pr_info("fuzz complete: %i keys", b->sets[0].data->keys);
+	}
+}
+
+kobj_attribute_write(fuzz, btree_fuzz);
+#endif
+
+void bch_debug_exit(void)
+{
+	if (!IS_ERR_OR_NULL(debug))
+		debugfs_remove_recursive(debug);
+}
+
+int __init bch_debug_init(struct kobject *kobj)
+{
+	int ret = 0;
+#ifdef CONFIG_BCACHE_DEBUG
+	ret = sysfs_create_file(kobj, &ksysfs_fuzz.attr);
+	if (ret)
+		return ret;
+#endif
+
+	debug = debugfs_create_dir("bcache", NULL);
+	return ret;
+}
diff --git a/drivers/md/bcache/debug.h b/drivers/md/bcache/debug.h
new file mode 100644
index 0000000..f9378a2
--- /dev/null
+++ b/drivers/md/bcache/debug.h
@@ -0,0 +1,54 @@
+#ifndef _BCACHE_DEBUG_H
+#define _BCACHE_DEBUG_H
+
+/* Btree/bkey debug printing */
+
+#define KEYHACK_SIZE 80
+struct keyprint_hack {
+	char s[KEYHACK_SIZE];
+};
+
+struct keyprint_hack bch_pkey(const struct bkey *k);
+struct keyprint_hack bch_pbtree(const struct btree *b);
+#define pkey(k)		(&bch_pkey(k).s[0])
+#define pbtree(b)	(&bch_pbtree(b).s[0])
+
+#ifdef CONFIG_BCACHE_EDEBUG
+
+unsigned bch_count_data(struct btree *);
+void bch_check_key_order_msg(struct btree *, struct bset *, const char *, ...);
+void bch_check_keys(struct btree *, const char *, ...);
+
+#define bch_check_key_order(b, i)			\
+	bch_check_key_order_msg(b, i, "keys out of order")
+#define EBUG_ON(cond)		BUG_ON(cond)
+
+#else /* EDEBUG */
+
+#define bch_count_data(b)				0
+#define bch_check_key_order(b, i)			do {} while (0)
+#define bch_check_key_order_msg(b, i, ...)		do {} while (0)
+#define bch_check_keys(b, ...)				do {} while (0)
+#define EBUG_ON(cond)					do {} while (0)
+
+#endif
+
+#ifdef CONFIG_BCACHE_DEBUG
+
+void bch_btree_verify(struct btree *, struct bset *);
+void bch_data_verify(struct search *);
+
+#else /* DEBUG */
+
+static inline void bch_btree_verify(struct btree *b, struct bset *i) {}
+static inline void bch_data_verify(struct search *s) {};
+
+#endif
+
+#ifdef CONFIG_DEBUG_FS
+void bch_debug_init_cache_set(struct cache_set *);
+#else
+static inline void bch_debug_init_cache_set(struct cache_set *c) {}
+#endif
+
+#endif
diff --git a/drivers/md/bcache/io.c b/drivers/md/bcache/io.c
new file mode 100644
index 0000000..8bb2759
--- /dev/null
+++ b/drivers/md/bcache/io.c
@@ -0,0 +1,392 @@
+/*
+ * Some low level IO code, and hacks for various block layer limitations
+ *
+ * Copyright 2010, 2011 Kent Overstreet <kent.overstreet@gmail.com>
+ * Copyright 2012 Google, Inc.
+ */
+
+#include "bcache.h"
+#include "bset.h"
+#include "debug.h"
+
+static void bch_bi_idx_hack_endio(struct bio *bio, int error,
+				  struct batch_complete *batch)
+{
+	struct bio *p = bio->bi_private;
+
+	bio_endio(p, error);
+	bio_put(bio);
+}
+
+static void bch_generic_make_request_hack(struct bio *bio)
+{
+	if (bio->bi_idx) {
+		struct bio *clone = bio_alloc(GFP_NOIO, bio_segments(bio));
+
+		memcpy(clone->bi_io_vec,
+		       bio_iovec(bio),
+		       bio_segments(bio) * sizeof(struct bio_vec));
+
+		clone->bi_sector	= bio->bi_sector;
+		clone->bi_bdev		= bio->bi_bdev;
+		clone->bi_rw		= bio->bi_rw;
+		clone->bi_vcnt		= bio_segments(bio);
+		clone->bi_size		= bio->bi_size;
+
+		clone->bi_private	= bio;
+		clone->bi_end_io	= bch_bi_idx_hack_endio;
+
+		bio = clone;
+	}
+
+	generic_make_request(bio);
+}
+
+/**
+ * bch_bio_split - split a bio
+ * @bio:	bio to split
+ * @sectors:	number of sectors to split from the front of @bio
+ * @gfp:	gfp mask
+ * @bs:		bio set to allocate from
+ *
+ * Allocates and returns a new bio which represents @sectors from the start of
+ * @bio, and updates @bio to represent the remaining sectors.
+ *
+ * If bio_sectors(@bio) was less than or equal to @sectors, returns @bio
+ * unchanged.
+ *
+ * The newly allocated bio will point to @bio's bi_io_vec, if the split was on a
+ * bvec boundry; it is the caller's responsibility to ensure that @bio is not
+ * freed before the split.
+ *
+ * If bch_bio_split() is running under generic_make_request(), it's not safe to
+ * allocate more than one bio from the same bio set. Therefore, if it is running
+ * under generic_make_request() it masks out __GFP_WAIT when doing the
+ * allocation. The caller must check for failure if there's any possibility of
+ * it being called from under generic_make_request(); it is then the caller's
+ * responsibility to retry from a safe context (by e.g. punting to workqueue).
+ */
+struct bio *bch_bio_split(struct bio *bio, int sectors,
+			  gfp_t gfp, struct bio_set *bs)
+{
+	unsigned idx = bio->bi_idx, vcnt = 0, nbytes = sectors << 9;
+	struct bio_vec *bv;
+	struct bio *ret = NULL;
+
+	BUG_ON(sectors <= 0);
+
+	/*
+	 * If we're being called from underneath generic_make_request() and we
+	 * already allocated any bios from this bio set, we risk deadlock if we
+	 * use the mempool. So instead, we possibly fail and let the caller punt
+	 * to workqueue or somesuch and retry in a safe context.
+	 */
+	if (current->bio_list)
+		gfp &= ~__GFP_WAIT;
+
+	if (sectors >= bio_sectors(bio))
+		return bio;
+
+	if (bio->bi_rw & REQ_DISCARD) {
+		ret = bio_alloc_bioset(gfp, 1, bs);
+		idx = 0;
+		goto out;
+	}
+
+	bio_for_each_segment(bv, bio, idx) {
+		vcnt = idx - bio->bi_idx;
+
+		if (!nbytes) {
+			ret = bio_alloc_bioset(gfp, vcnt, bs);
+			if (!ret)
+				return NULL;
+
+			memcpy(ret->bi_io_vec, bio_iovec(bio),
+			       sizeof(struct bio_vec) * vcnt);
+
+			break;
+		} else if (nbytes < bv->bv_len) {
+			ret = bio_alloc_bioset(gfp, ++vcnt, bs);
+			if (!ret)
+				return NULL;
+
+			memcpy(ret->bi_io_vec, bio_iovec(bio),
+			       sizeof(struct bio_vec) * vcnt);
+
+			ret->bi_io_vec[vcnt - 1].bv_len = nbytes;
+			bv->bv_offset	+= nbytes;
+			bv->bv_len	-= nbytes;
+			break;
+		}
+
+		nbytes -= bv->bv_len;
+	}
+out:
+	ret->bi_bdev	= bio->bi_bdev;
+	ret->bi_sector	= bio->bi_sector;
+	ret->bi_size	= sectors << 9;
+	ret->bi_rw	= bio->bi_rw;
+	ret->bi_vcnt	= vcnt;
+	ret->bi_max_vecs = vcnt;
+
+	bio->bi_sector	+= sectors;
+	bio->bi_size	-= sectors << 9;
+	bio->bi_idx	 = idx;
+
+	if (bio_integrity(bio)) {
+		if (bio_integrity_clone(ret, bio, gfp)) {
+			bio_put(ret);
+			return NULL;
+		}
+
+		bio_integrity_trim(ret, 0, bio_sectors(ret));
+		bio_integrity_trim(bio, bio_sectors(ret), bio_sectors(bio));
+	}
+
+	return ret;
+}
+
+static unsigned bch_bio_max_sectors(struct bio *bio)
+{
+	unsigned ret = bio_sectors(bio);
+	struct request_queue *q = bdev_get_queue(bio->bi_bdev);
+	struct bio_vec *bv, *end = bio_iovec(bio) +
+		min_t(int, bio_segments(bio), queue_max_segments(q));
+
+	struct bvec_merge_data bvm = {
+		.bi_bdev	= bio->bi_bdev,
+		.bi_sector	= bio->bi_sector,
+		.bi_size	= 0,
+		.bi_rw		= bio->bi_rw,
+	};
+
+	if (bio->bi_rw & REQ_DISCARD)
+		return min(ret, q->limits.max_discard_sectors);
+
+	if (bio_segments(bio) > queue_max_segments(q) ||
+	    q->merge_bvec_fn) {
+		ret = 0;
+
+		for (bv = bio_iovec(bio); bv < end; bv++) {
+			if (q->merge_bvec_fn &&
+			    q->merge_bvec_fn(q, &bvm, bv) < (int) bv->bv_len)
+				break;
+
+			ret		+= bv->bv_len >> 9;
+			bvm.bi_size	+= bv->bv_len;
+		}
+
+		if (ret >= (BIO_MAX_PAGES * PAGE_SIZE) >> 9)
+			return (BIO_MAX_PAGES * PAGE_SIZE) >> 9;
+	}
+
+	ret = min(ret, queue_max_sectors(q));
+
+	WARN_ON(!ret);
+	ret = max_t(int, ret, bio_iovec(bio)->bv_len >> 9);
+
+	return ret;
+}
+
+static void bch_bio_submit_split_done(struct closure *cl)
+{
+	struct bio_split_hook *s = container_of(cl, struct bio_split_hook, cl);
+
+	s->bio->bi_end_io = s->bi_end_io;
+	s->bio->bi_private = s->bi_private;
+	bio_endio(s->bio, 0);
+
+	closure_debug_destroy(&s->cl);
+	mempool_free(s, s->p->bio_split_hook);
+}
+
+static void bch_bio_submit_split_endio(struct bio *bio, int error,
+				       struct batch_complete *batch)
+{
+	struct closure *cl = bio->bi_private;
+	struct bio_split_hook *s = container_of(cl, struct bio_split_hook, cl);
+
+	if (error)
+		clear_bit(BIO_UPTODATE, &s->bio->bi_flags);
+
+	bio_put(bio);
+	closure_put(cl);
+}
+
+static void __bch_bio_submit_split(struct closure *cl)
+{
+	struct bio_split_hook *s = container_of(cl, struct bio_split_hook, cl);
+	struct bio *bio = s->bio, *n;
+
+	do {
+		n = bch_bio_split(bio, bch_bio_max_sectors(bio),
+				  GFP_NOIO, s->p->bio_split);
+		if (!n)
+			continue_at(cl, __bch_bio_submit_split, system_wq);
+
+		n->bi_end_io	= bch_bio_submit_split_endio;
+		n->bi_private	= cl;
+
+		closure_get(cl);
+		bch_generic_make_request_hack(n);
+	} while (n != bio);
+
+	continue_at(cl, bch_bio_submit_split_done, NULL);
+}
+
+void bch_generic_make_request(struct bio *bio, struct bio_split_pool *p)
+{
+	struct bio_split_hook *s;
+
+	if (!bio_has_data(bio) && !(bio->bi_rw & REQ_DISCARD))
+		goto submit;
+
+	if (bio_sectors(bio) <= bch_bio_max_sectors(bio))
+		goto submit;
+
+	s = mempool_alloc(p->bio_split_hook, GFP_NOIO);
+
+	s->bio		= bio;
+	s->p		= p;
+	s->bi_end_io	= bio->bi_end_io;
+	s->bi_private	= bio->bi_private;
+	bio_get(bio);
+
+	closure_call(&s->cl, __bch_bio_submit_split, NULL, NULL);
+	return;
+submit:
+	bch_generic_make_request_hack(bio);
+}
+
+/* Bios with headers */
+
+void bch_bbio_free(struct bio *bio, struct cache_set *c)
+{
+	struct bbio *b = container_of(bio, struct bbio, bio);
+	mempool_free(b, c->bio_meta);
+}
+
+struct bio *bch_bbio_alloc(struct cache_set *c)
+{
+	struct bbio *b = mempool_alloc(c->bio_meta, GFP_NOIO);
+	struct bio *bio = &b->bio;
+
+	bio_init(bio);
+	bio->bi_flags		|= BIO_POOL_NONE << BIO_POOL_OFFSET;
+	bio->bi_max_vecs	 = bucket_pages(c);
+	bio->bi_io_vec		 = bio->bi_inline_vecs;
+
+	return bio;
+}
+
+void __bch_submit_bbio(struct bio *bio, struct cache_set *c)
+{
+	struct bbio *b = container_of(bio, struct bbio, bio);
+
+	bio->bi_sector	= PTR_OFFSET(&b->key, 0);
+	bio->bi_bdev	= PTR_CACHE(c, &b->key, 0)->bdev;
+
+	b->submit_time_us = local_clock_us();
+	closure_bio_submit(bio, bio->bi_private, PTR_CACHE(c, &b->key, 0));
+}
+
+void bch_submit_bbio(struct bio *bio, struct cache_set *c,
+		     struct bkey *k, unsigned ptr)
+{
+	struct bbio *b = container_of(bio, struct bbio, bio);
+	bch_bkey_copy_single_ptr(&b->key, k, ptr);
+	__bch_submit_bbio(bio, c);
+}
+
+/* IO errors */
+
+void bch_count_io_errors(struct cache *ca, int error, const char *m)
+{
+	/*
+	 * The halflife of an error is:
+	 * log2(1/2)/log2(127/128) * refresh ~= 88 * refresh
+	 */
+
+	if (ca->set->error_decay) {
+		unsigned count = atomic_inc_return(&ca->io_count);
+
+		while (count > ca->set->error_decay) {
+			unsigned errors;
+			unsigned old = count;
+			unsigned new = count - ca->set->error_decay;
+
+			/*
+			 * First we subtract refresh from count; each time we
+			 * succesfully do so, we rescale the errors once:
+			 */
+
+			count = atomic_cmpxchg(&ca->io_count, old, new);
+
+			if (count == old) {
+				count = new;
+
+				errors = atomic_read(&ca->io_errors);
+				do {
+					old = errors;
+					new = ((uint64_t) errors * 127) / 128;
+					errors = atomic_cmpxchg(&ca->io_errors,
+								old, new);
+				} while (old != errors);
+			}
+		}
+	}
+
+	if (error) {
+		char buf[BDEVNAME_SIZE];
+		unsigned errors = atomic_add_return(1 << IO_ERROR_SHIFT,
+						    &ca->io_errors);
+		errors >>= IO_ERROR_SHIFT;
+
+		if (errors < ca->set->error_limit)
+			pr_err("%s: IO error on %s, recovering",
+			       bdevname(ca->bdev, buf), m);
+		else
+			bch_cache_set_error(ca->set,
+					    "%s: too many IO errors %s",
+					    bdevname(ca->bdev, buf), m);
+	}
+}
+
+void bch_bbio_count_io_errors(struct cache_set *c, struct bio *bio,
+			      int error, const char *m)
+{
+	struct bbio *b = container_of(bio, struct bbio, bio);
+	struct cache *ca = PTR_CACHE(c, &b->key, 0);
+
+	unsigned threshold = bio->bi_rw & REQ_WRITE
+		? c->congested_write_threshold_us
+		: c->congested_read_threshold_us;
+
+	if (threshold) {
+		unsigned t = local_clock_us();
+
+		int us = t - b->submit_time_us;
+		int congested = atomic_read(&c->congested);
+
+		if (us > (int) threshold) {
+			int ms = us / 1024;
+			c->congested_last_us = t;
+
+			ms = min(ms, CONGESTED_MAX + congested);
+			atomic_sub(ms, &c->congested);
+		} else if (congested < 0)
+			atomic_inc(&c->congested);
+	}
+
+	bch_count_io_errors(ca, error, m);
+}
+
+void bch_bbio_endio(struct cache_set *c, struct bio *bio,
+		    int error, const char *m)
+{
+	struct closure *cl = bio->bi_private;
+
+	bch_bbio_count_io_errors(c, bio, error, m);
+	bio_put(bio);
+	closure_put(cl);
+}
diff --git a/drivers/md/bcache/journal.c b/drivers/md/bcache/journal.c
new file mode 100644
index 0000000..034bcf9
--- /dev/null
+++ b/drivers/md/bcache/journal.c
@@ -0,0 +1,788 @@
+/*
+ * bcache journalling code, for btree insertions
+ *
+ * Copyright 2012 Google, Inc.
+ */
+
+#include "bcache.h"
+#include "btree.h"
+#include "debug.h"
+#include "request.h"
+
+/*
+ * Journal replay/recovery:
+ *
+ * This code is all driven from run_cache_set(); we first read the journal
+ * entries, do some other stuff, then we mark all the keys in the journal
+ * entries (same as garbage collection would), then we replay them - reinserting
+ * them into the cache in precisely the same order as they appear in the
+ * journal.
+ *
+ * We only journal keys that go in leaf nodes, which simplifies things quite a
+ * bit.
+ */
+
+static void journal_read_endio(struct bio *bio, int error,
+			       struct batch_complete *batch)
+{
+	struct closure *cl = bio->bi_private;
+	closure_put(cl);
+}
+
+static int journal_read_bucket(struct cache *ca, struct list_head *list,
+			       struct btree_op *op, unsigned bucket_index)
+{
+	struct journal_device *ja = &ca->journal;
+	struct bio *bio = &ja->bio;
+
+	struct journal_replay *i;
+	struct jset *j, *data = ca->set->journal.w[0].data;
+	unsigned len, left, offset = 0;
+	int ret = 0;
+	sector_t bucket = bucket_to_sector(ca->set, ca->sb.d[bucket_index]);
+
+	pr_debug("reading %llu", (uint64_t) bucket);
+
+	while (offset < ca->sb.bucket_size) {
+reread:		left = ca->sb.bucket_size - offset;
+		len = min_t(unsigned, left, PAGE_SECTORS * 8);
+
+		bio_reset(bio);
+		bio->bi_sector	= bucket + offset;
+		bio->bi_bdev	= ca->bdev;
+		bio->bi_rw	= READ;
+		bio->bi_size	= len << 9;
+
+		bio->bi_end_io	= journal_read_endio;
+		bio->bi_private = &op->cl;
+		bch_bio_map(bio, data);
+
+		closure_bio_submit(bio, &op->cl, ca);
+		closure_sync(&op->cl);
+
+		/* This function could be simpler now since we no longer write
+		 * journal entries that overlap bucket boundaries; this means
+		 * the start of a bucket will always have a valid journal entry
+		 * if it has any journal entries at all.
+		 */
+
+		j = data;
+		while (len) {
+			struct list_head *where;
+			size_t blocks, bytes = set_bytes(j);
+
+			if (j->magic != jset_magic(ca->set))
+				return ret;
+
+			if (bytes > left << 9)
+				return ret;
+
+			if (bytes > len << 9)
+				goto reread;
+
+			if (j->csum != csum_set(j))
+				return ret;
+
+			blocks = set_blocks(j, ca->set);
+
+			while (!list_empty(list)) {
+				i = list_first_entry(list,
+					struct journal_replay, list);
+				if (i->j.seq >= j->last_seq)
+					break;
+				list_del(&i->list);
+				kfree(i);
+			}
+
+			list_for_each_entry_reverse(i, list, list) {
+				if (j->seq == i->j.seq)
+					goto next_set;
+
+				if (j->seq < i->j.last_seq)
+					goto next_set;
+
+				if (j->seq > i->j.seq) {
+					where = &i->list;
+					goto add;
+				}
+			}
+
+			where = list;
+add:
+			i = kmalloc(offsetof(struct journal_replay, j) +
+				    bytes, GFP_KERNEL);
+			if (!i)
+				return -ENOMEM;
+			memcpy(&i->j, j, bytes);
+			list_add(&i->list, where);
+			ret = 1;
+
+			ja->seq[bucket_index] = j->seq;
+next_set:
+			offset	+= blocks * ca->sb.block_size;
+			len	-= blocks * ca->sb.block_size;
+			j = ((void *) j) + blocks * block_bytes(ca);
+		}
+	}
+
+	return ret;
+}
+
+int bch_journal_read(struct cache_set *c, struct list_head *list,
+			struct btree_op *op)
+{
+#define read_bucket(b)							\
+	({								\
+		int ret = journal_read_bucket(ca, list, op, b);		\
+		__set_bit(b, bitmap);					\
+		if (ret < 0)						\
+			return ret;					\
+		ret;							\
+	})
+
+	struct cache *ca;
+	unsigned iter;
+
+	for_each_cache(ca, c, iter) {
+		struct journal_device *ja = &ca->journal;
+		unsigned long bitmap[SB_JOURNAL_BUCKETS / BITS_PER_LONG];
+		unsigned i, l, r, m;
+		uint64_t seq;
+
+		bitmap_zero(bitmap, SB_JOURNAL_BUCKETS);
+		pr_debug("%u journal buckets", ca->sb.njournal_buckets);
+
+		/* Read journal buckets ordered by golden ratio hash to quickly
+		 * find a sequence of buckets with valid journal entries
+		 */
+		for (i = 0; i < ca->sb.njournal_buckets; i++) {
+			l = (i * 2654435769U) % ca->sb.njournal_buckets;
+
+			if (test_bit(l, bitmap))
+				break;
+
+			if (read_bucket(l))
+				goto bsearch;
+		}
+
+		/* If that fails, check all the buckets we haven't checked
+		 * already
+		 */
+		pr_debug("falling back to linear search");
+
+		for (l = 0; l < ca->sb.njournal_buckets; l++) {
+			if (test_bit(l, bitmap))
+				continue;
+
+			if (read_bucket(l))
+				goto bsearch;
+		}
+bsearch:
+		/* Binary search */
+		m = r = find_next_bit(bitmap, ca->sb.njournal_buckets, l + 1);
+		pr_debug("starting binary search, l %u r %u", l, r);
+
+		while (l + 1 < r) {
+			m = (l + r) >> 1;
+
+			if (read_bucket(m))
+				l = m;
+			else
+				r = m;
+		}
+
+		/* Read buckets in reverse order until we stop finding more
+		 * journal entries
+		 */
+		pr_debug("finishing up");
+		l = m;
+
+		while (1) {
+			if (!l--)
+				l = ca->sb.njournal_buckets - 1;
+
+			if (l == m)
+				break;
+
+			if (test_bit(l, bitmap))
+				continue;
+
+			if (!read_bucket(l))
+				break;
+		}
+
+		seq = 0;
+
+		for (i = 0; i < ca->sb.njournal_buckets; i++)
+			if (ja->seq[i] > seq) {
+				seq = ja->seq[i];
+				ja->cur_idx = ja->discard_idx =
+					ja->last_idx = i;
+
+			}
+	}
+
+	c->journal.seq = list_entry(list->prev,
+				    struct journal_replay,
+				    list)->j.seq;
+
+	return 0;
+#undef read_bucket
+}
+
+void bch_journal_mark(struct cache_set *c, struct list_head *list)
+{
+	atomic_t p = { 0 };
+	struct bkey *k;
+	struct journal_replay *i;
+	struct journal *j = &c->journal;
+	uint64_t last = j->seq;
+
+	/*
+	 * journal.pin should never fill up - we never write a journal
+	 * entry when it would fill up. But if for some reason it does, we
+	 * iterate over the list in reverse order so that we can just skip that
+	 * refcount instead of bugging.
+	 */
+
+	list_for_each_entry_reverse(i, list, list) {
+		BUG_ON(last < i->j.seq);
+		i->pin = NULL;
+
+		while (last-- != i->j.seq)
+			if (fifo_free(&j->pin) > 1) {
+				fifo_push_front(&j->pin, p);
+				atomic_set(&fifo_front(&j->pin), 0);
+			}
+
+		if (fifo_free(&j->pin) > 1) {
+			fifo_push_front(&j->pin, p);
+			i->pin = &fifo_front(&j->pin);
+			atomic_set(i->pin, 1);
+		}
+
+		for (k = i->j.start;
+		     k < end(&i->j);
+		     k = bkey_next(k)) {
+			unsigned j;
+
+			for (j = 0; j < KEY_PTRS(k); j++) {
+				struct bucket *g = PTR_BUCKET(c, k, j);
+				atomic_inc(&g->pin);
+
+				if (g->prio == BTREE_PRIO &&
+				    !ptr_stale(c, k, j))
+					g->prio = INITIAL_PRIO;
+			}
+
+			__bch_btree_mark_key(c, 0, k);
+		}
+	}
+}
+
+int bch_journal_replay(struct cache_set *s, struct list_head *list,
+			  struct btree_op *op)
+{
+	int ret = 0, keys = 0, entries = 0;
+	struct bkey *k;
+	struct journal_replay *i =
+		list_entry(list->prev, struct journal_replay, list);
+
+	uint64_t start = i->j.last_seq, end = i->j.seq, n = start;
+
+	list_for_each_entry(i, list, list) {
+		BUG_ON(i->pin && atomic_read(i->pin) != 1);
+
+		if (n != i->j.seq)
+			pr_err(
+		"journal entries %llu-%llu missing! (replaying %llu-%llu)\n",
+		n, i->j.seq - 1, start, end);
+
+		for (k = i->j.start;
+		     k < end(&i->j);
+		     k = bkey_next(k)) {
+			pr_debug("%s", pkey(k));
+			bkey_copy(op->keys.top, k);
+			bch_keylist_push(&op->keys);
+
+			op->journal = i->pin;
+			atomic_inc(op->journal);
+
+			ret = bch_btree_insert(op, s);
+			if (ret)
+				goto err;
+
+			BUG_ON(!bch_keylist_empty(&op->keys));
+			keys++;
+
+			cond_resched();
+		}
+
+		if (i->pin)
+			atomic_dec(i->pin);
+		n = i->j.seq + 1;
+		entries++;
+	}
+
+	pr_info("journal replay done, %i keys in %i entries, seq %llu",
+		keys, entries, end);
+
+	while (!list_empty(list)) {
+		i = list_first_entry(list, struct journal_replay, list);
+		list_del(&i->list);
+		kfree(i);
+	}
+err:
+	closure_sync(&op->cl);
+	return ret;
+}
+
+/* Journalling */
+
+static void btree_flush_write(struct cache_set *c)
+{
+	/*
+	 * Try to find the btree node with that references the oldest journal
+	 * entry, best is our current candidate and is locked if non NULL:
+	 */
+	struct btree *b, *best = NULL;
+	unsigned iter;
+
+	for_each_cached_btree(b, c, iter) {
+		if (!down_write_trylock(&b->lock))
+			continue;
+
+		if (!btree_node_dirty(b) ||
+		    !btree_current_write(b)->journal) {
+			rw_unlock(true, b);
+			continue;
+		}
+
+		if (!best)
+			best = b;
+		else if (journal_pin_cmp(c,
+					 btree_current_write(best),
+					 btree_current_write(b))) {
+			rw_unlock(true, best);
+			best = b;
+		} else
+			rw_unlock(true, b);
+	}
+
+	if (best)
+		goto out;
+
+	/* We can't find the best btree node, just pick the first */
+	list_for_each_entry(b, &c->btree_cache, list)
+		if (!b->level && btree_node_dirty(b)) {
+			best = b;
+			rw_lock(true, best, best->level);
+			goto found;
+		}
+
+out:
+	if (!best)
+		return;
+found:
+	if (btree_node_dirty(best))
+		bch_btree_write(best, true, NULL);
+	rw_unlock(true, best);
+}
+
+#define last_seq(j)	((j)->seq - fifo_used(&(j)->pin) + 1)
+
+static void journal_discard_endio(struct bio *bio, int error,
+				  struct batch_complete *batch)
+{
+	struct journal_device *ja =
+		container_of(bio, struct journal_device, discard_bio);
+	struct cache *ca = container_of(ja, struct cache, journal);
+
+	atomic_set(&ja->discard_in_flight, DISCARD_DONE);
+
+	closure_wake_up(&ca->set->journal.wait);
+	closure_put(&ca->set->cl);
+}
+
+static void journal_discard_work(struct work_struct *work)
+{
+	struct journal_device *ja =
+		container_of(work, struct journal_device, discard_work);
+
+	submit_bio(0, &ja->discard_bio);
+}
+
+static void do_journal_discard(struct cache *ca)
+{
+	struct journal_device *ja = &ca->journal;
+	struct bio *bio = &ja->discard_bio;
+
+	if (!ca->discard) {
+		ja->discard_idx = ja->last_idx;
+		return;
+	}
+
+	switch (atomic_read(&ja->discard_in_flight) == DISCARD_IN_FLIGHT) {
+	case DISCARD_IN_FLIGHT:
+		return;
+
+	case DISCARD_DONE:
+		ja->discard_idx = (ja->discard_idx + 1) %
+			ca->sb.njournal_buckets;
+
+		atomic_set(&ja->discard_in_flight, DISCARD_READY);
+		/* fallthrough */
+
+	case DISCARD_READY:
+		if (ja->discard_idx == ja->last_idx)
+			return;
+
+		atomic_set(&ja->discard_in_flight, DISCARD_IN_FLIGHT);
+
+		bio_init(bio);
+		bio->bi_sector		= bucket_to_sector(ca->set,
+						ca->sb.d[ja->discard_idx]);
+		bio->bi_bdev		= ca->bdev;
+		bio->bi_rw		= REQ_WRITE|REQ_DISCARD;
+		bio->bi_max_vecs	= 1;
+		bio->bi_io_vec		= bio->bi_inline_vecs;
+		bio->bi_size		= bucket_bytes(ca);
+		bio->bi_end_io		= journal_discard_endio;
+
+		closure_get(&ca->set->cl);
+		INIT_WORK(&ja->discard_work, journal_discard_work);
+		schedule_work(&ja->discard_work);
+	}
+}
+
+static void journal_reclaim(struct cache_set *c)
+{
+	struct bkey *k = &c->journal.key;
+	struct cache *ca;
+	uint64_t last_seq;
+	unsigned iter, n = 0;
+	atomic_t p;
+
+	while (!atomic_read(&fifo_front(&c->journal.pin)))
+		fifo_pop(&c->journal.pin, p);
+
+	last_seq = last_seq(&c->journal);
+
+	/* Update last_idx */
+
+	for_each_cache(ca, c, iter) {
+		struct journal_device *ja = &ca->journal;
+
+		while (ja->last_idx != ja->cur_idx &&
+		       ja->seq[ja->last_idx] < last_seq)
+			ja->last_idx = (ja->last_idx + 1) %
+				ca->sb.njournal_buckets;
+	}
+
+	for_each_cache(ca, c, iter)
+		do_journal_discard(ca);
+
+	if (c->journal.blocks_free)
+		return;
+
+	/*
+	 * Allocate:
+	 * XXX: Sort by free journal space
+	 */
+
+	for_each_cache(ca, c, iter) {
+		struct journal_device *ja = &ca->journal;
+		unsigned next = (ja->cur_idx + 1) % ca->sb.njournal_buckets;
+
+		/* No space available on this device */
+		if (next == ja->discard_idx)
+			continue;
+
+		ja->cur_idx = next;
+		k->ptr[n++] = PTR(0,
+				  bucket_to_sector(c, ca->sb.d[ja->cur_idx]),
+				  ca->sb.nr_this_dev);
+	}
+
+	bkey_init(k);
+	SET_KEY_PTRS(k, n);
+
+	if (n)
+		c->journal.blocks_free = c->sb.bucket_size >> c->block_bits;
+
+	if (!journal_full(&c->journal))
+		__closure_wake_up(&c->journal.wait);
+}
+
+void bch_journal_next(struct journal *j)
+{
+	atomic_t p = { 1 };
+
+	j->cur = (j->cur == j->w)
+		? &j->w[1]
+		: &j->w[0];
+
+	/*
+	 * The fifo_push() needs to happen at the same time as j->seq is
+	 * incremented for last_seq() to be calculated correctly
+	 */
+	BUG_ON(!fifo_push(&j->pin, p));
+	atomic_set(&fifo_back(&j->pin), 1);
+
+	j->cur->data->seq	= ++j->seq;
+	j->cur->need_write	= false;
+	j->cur->data->keys	= 0;
+
+	if (fifo_full(&j->pin))
+		pr_debug("journal_pin full (%zu)", fifo_used(&j->pin));
+}
+
+static void journal_write_endio(struct bio *bio, int error,
+				struct batch_complete *batch)
+{
+	struct journal_write *w = bio->bi_private;
+
+	cache_set_err_on(error, w->c, "journal io error");
+	closure_put(&w->c->journal.io.cl);
+}
+
+static void journal_write(struct closure *);
+
+static void journal_write_done(struct closure *cl)
+{
+	struct journal *j = container_of(cl, struct journal, io.cl);
+	struct cache_set *c = container_of(j, struct cache_set, journal);
+
+	struct journal_write *w = (j->cur == j->w)
+		? &j->w[1]
+		: &j->w[0];
+
+	__closure_wake_up(&w->wait);
+
+	if (c->journal_delay_ms)
+		closure_delay(&j->io, msecs_to_jiffies(c->journal_delay_ms));
+
+	continue_at(cl, journal_write, system_wq);
+}
+
+static void journal_write_unlocked(struct closure *cl)
+{
+	struct cache_set *c = container_of(cl, struct cache_set, journal.io.cl);
+	struct cache *ca;
+	struct journal_write *w = c->journal.cur;
+	struct bkey *k = &c->journal.key;
+	unsigned i, sectors = set_blocks(w->data, c) * c->sb.block_size;
+
+	struct bio *bio;
+	struct bio_list list;
+	bio_list_init(&list);
+
+	if (!w->need_write) {
+		/*
+		 * XXX: have to unlock closure before we unlock journal lock,
+		 * else we race with bch_journal(). But this way we race
+		 * against cache set unregister. Doh.
+		 */
+		set_closure_fn(cl, NULL, NULL);
+		closure_sub(cl, CLOSURE_RUNNING + 1);
+		spin_unlock(&c->journal.lock);
+		return;
+	} else if (journal_full(&c->journal)) {
+		journal_reclaim(c);
+		spin_unlock(&c->journal.lock);
+
+		btree_flush_write(c);
+		continue_at(cl, journal_write, system_wq);
+	}
+
+	c->journal.blocks_free -= set_blocks(w->data, c);
+
+	w->data->btree_level = c->root->level;
+
+	bkey_copy(&w->data->btree_root, &c->root->key);
+	bkey_copy(&w->data->uuid_bucket, &c->uuid_bucket);
+
+	for_each_cache(ca, c, i)
+		w->data->prio_bucket[ca->sb.nr_this_dev] = ca->prio_buckets[0];
+
+	w->data->magic		= jset_magic(c);
+	w->data->version	= BCACHE_JSET_VERSION;
+	w->data->last_seq	= last_seq(&c->journal);
+	w->data->csum		= csum_set(w->data);
+
+	for (i = 0; i < KEY_PTRS(k); i++) {
+		ca = PTR_CACHE(c, k, i);
+		bio = &ca->journal.bio;
+
+		atomic_long_add(sectors, &ca->meta_sectors_written);
+
+		bio_reset(bio);
+		bio->bi_sector	= PTR_OFFSET(k, i);
+		bio->bi_bdev	= ca->bdev;
+		bio->bi_rw	= REQ_WRITE|REQ_SYNC|REQ_META|REQ_FLUSH;
+		bio->bi_size	= sectors << 9;
+
+		bio->bi_end_io	= journal_write_endio;
+		bio->bi_private = w;
+		bch_bio_map(bio, w->data);
+
+		trace_bcache_journal_write(bio);
+		bio_list_add(&list, bio);
+
+		SET_PTR_OFFSET(k, i, PTR_OFFSET(k, i) + sectors);
+
+		ca->journal.seq[ca->journal.cur_idx] = w->data->seq;
+	}
+
+	atomic_dec_bug(&fifo_back(&c->journal.pin));
+	bch_journal_next(&c->journal);
+	journal_reclaim(c);
+
+	spin_unlock(&c->journal.lock);
+
+	while ((bio = bio_list_pop(&list)))
+		closure_bio_submit(bio, cl, c->cache[0]);
+
+	continue_at(cl, journal_write_done, NULL);
+}
+
+static void journal_write(struct closure *cl)
+{
+	struct cache_set *c = container_of(cl, struct cache_set, journal.io.cl);
+
+	spin_lock(&c->journal.lock);
+	journal_write_unlocked(cl);
+}
+
+static void __journal_try_write(struct cache_set *c, bool noflush)
+{
+	struct closure *cl = &c->journal.io.cl;
+
+	if (!closure_trylock(cl, &c->cl))
+		spin_unlock(&c->journal.lock);
+	else if (noflush && journal_full(&c->journal)) {
+		spin_unlock(&c->journal.lock);
+		continue_at(cl, journal_write, system_wq);
+	} else
+		journal_write_unlocked(cl);
+}
+
+#define journal_try_write(c)	__journal_try_write(c, false)
+
+void bch_journal_meta(struct cache_set *c, struct closure *cl)
+{
+	struct journal_write *w;
+
+	if (CACHE_SYNC(&c->sb)) {
+		spin_lock(&c->journal.lock);
+
+		w = c->journal.cur;
+		w->need_write = true;
+
+		if (cl)
+			BUG_ON(!closure_wait(&w->wait, cl));
+
+		__journal_try_write(c, true);
+	}
+}
+
+/*
+ * Entry point to the journalling code - bio_insert() and btree_invalidate()
+ * pass bch_journal() a list of keys to be journalled, and then
+ * bch_journal() hands those same keys off to btree_insert_async()
+ */
+
+void bch_journal(struct closure *cl)
+{
+	struct btree_op *op = container_of(cl, struct btree_op, cl);
+	struct cache_set *c = op->c;
+	struct journal_write *w;
+	size_t b, n = ((uint64_t *) op->keys.top) - op->keys.list;
+
+	if (op->type != BTREE_INSERT ||
+	    !CACHE_SYNC(&c->sb))
+		goto out;
+
+	/*
+	 * If we're looping because we errored, might already be waiting on
+	 * another journal write:
+	 */
+	while (atomic_read(&cl->parent->remaining) & CLOSURE_WAITING)
+		closure_sync(cl->parent);
+
+	spin_lock(&c->journal.lock);
+
+	if (journal_full(&c->journal)) {
+		/* XXX: tracepoint */
+		closure_wait(&c->journal.wait, cl);
+
+		journal_reclaim(c);
+		spin_unlock(&c->journal.lock);
+
+		btree_flush_write(c);
+		continue_at(cl, bch_journal, bcache_wq);
+	}
+
+	w = c->journal.cur;
+	w->need_write = true;
+	b = __set_blocks(w->data, w->data->keys + n, c);
+
+	if (b * c->sb.block_size > PAGE_SECTORS << JSET_BITS ||
+	    b > c->journal.blocks_free) {
+		/* XXX: If we were inserting so many keys that they won't fit in
+		 * an _empty_ journal write, we'll deadlock. For now, handle
+		 * this in bch_keylist_realloc() - but something to think about.
+		 */
+		BUG_ON(!w->data->keys);
+
+		/* XXX: tracepoint */
+		BUG_ON(!closure_wait(&w->wait, cl));
+
+		closure_flush(&c->journal.io);
+
+		journal_try_write(c);
+		continue_at(cl, bch_journal, bcache_wq);
+	}
+
+	memcpy(end(w->data), op->keys.list, n * sizeof(uint64_t));
+	w->data->keys += n;
+
+	op->journal = &fifo_back(&c->journal.pin);
+	atomic_inc(op->journal);
+
+	if (op->flush_journal) {
+		closure_flush(&c->journal.io);
+		closure_wait(&w->wait, cl->parent);
+	}
+
+	journal_try_write(c);
+out:
+	bch_btree_insert_async(cl);
+}
+
+void bch_journal_free(struct cache_set *c)
+{
+	free_pages((unsigned long) c->journal.w[1].data, JSET_BITS);
+	free_pages((unsigned long) c->journal.w[0].data, JSET_BITS);
+	free_fifo(&c->journal.pin);
+}
+
+int bch_journal_alloc(struct cache_set *c)
+{
+	struct journal *j = &c->journal;
+
+	closure_init_unlocked(&j->io);
+	spin_lock_init(&j->lock);
+
+	c->journal_delay_ms = 100;
+
+	j->w[0].c = c;
+	j->w[1].c = c;
+
+	if (!(init_fifo(&j->pin, JOURNAL_PIN, GFP_KERNEL)) ||
+	    !(j->w[0].data = (void *) __get_free_pages(GFP_KERNEL, JSET_BITS)) ||
+	    !(j->w[1].data = (void *) __get_free_pages(GFP_KERNEL, JSET_BITS)))
+		return -ENOMEM;
+
+	return 0;
+}
diff --git a/drivers/md/bcache/journal.h b/drivers/md/bcache/journal.h
new file mode 100644
index 0000000..3d78512
--- /dev/null
+++ b/drivers/md/bcache/journal.h
@@ -0,0 +1,215 @@
+#ifndef _BCACHE_JOURNAL_H
+#define _BCACHE_JOURNAL_H
+
+/*
+ * THE JOURNAL:
+ *
+ * The journal is treated as a circular buffer of buckets - a journal entry
+ * never spans two buckets. This means (not implemented yet) we can resize the
+ * journal at runtime, and will be needed for bcache on raw flash support.
+ *
+ * Journal entries contain a list of keys, ordered by the time they were
+ * inserted; thus journal replay just has to reinsert the keys.
+ *
+ * We also keep some things in the journal header that are logically part of the
+ * superblock - all the things that are frequently updated. This is for future
+ * bcache on raw flash support; the superblock (which will become another
+ * journal) can't be moved or wear leveled, so it contains just enough
+ * information to find the main journal, and the superblock only has to be
+ * rewritten when we want to move/wear level the main journal.
+ *
+ * Currently, we don't journal BTREE_REPLACE operations - this will hopefully be
+ * fixed eventually. This isn't a bug - BTREE_REPLACE is used for insertions
+ * from cache misses, which don't have to be journaled, and for writeback and
+ * moving gc we work around it by flushing the btree to disk before updating the
+ * gc information. But it is a potential issue with incremental garbage
+ * collection, and it's fragile.
+ *
+ * OPEN JOURNAL ENTRIES:
+ *
+ * Each journal entry contains, in the header, the sequence number of the last
+ * journal entry still open - i.e. that has keys that haven't been flushed to
+ * disk in the btree.
+ *
+ * We track this by maintaining a refcount for every open journal entry, in a
+ * fifo; each entry in the fifo corresponds to a particular journal
+ * entry/sequence number. When the refcount at the tail of the fifo goes to
+ * zero, we pop it off - thus, the size of the fifo tells us the number of open
+ * journal entries
+ *
+ * We take a refcount on a journal entry when we add some keys to a journal
+ * entry that we're going to insert (held by struct btree_op), and then when we
+ * insert those keys into the btree the btree write we're setting up takes a
+ * copy of that refcount (held by struct btree_write). That refcount is dropped
+ * when the btree write completes.
+ *
+ * A struct btree_write can only hold a refcount on a single journal entry, but
+ * might contain keys for many journal entries - we handle this by making sure
+ * it always has a refcount on the _oldest_ journal entry of all the journal
+ * entries it has keys for.
+ *
+ * JOURNAL RECLAIM:
+ *
+ * As mentioned previously, our fifo of refcounts tells us the number of open
+ * journal entries; from that and the current journal sequence number we compute
+ * last_seq - the oldest journal entry we still need. We write last_seq in each
+ * journal entry, and we also have to keep track of where it exists on disk so
+ * we don't overwrite it when we loop around the journal.
+ *
+ * To do that we track, for each journal bucket, the sequence number of the
+ * newest journal entry it contains - if we don't need that journal entry we
+ * don't need anything in that bucket anymore. From that we track the last
+ * journal bucket we still need; all this is tracked in struct journal_device
+ * and updated by journal_reclaim().
+ *
+ * JOURNAL FILLING UP:
+ *
+ * There are two ways the journal could fill up; either we could run out of
+ * space to write to, or we could have too many open journal entries and run out
+ * of room in the fifo of refcounts. Since those refcounts are decremented
+ * without any locking we can't safely resize that fifo, so we handle it the
+ * same way.
+ *
+ * If the journal fills up, we start flushing dirty btree nodes until we can
+ * allocate space for a journal write again - preferentially flushing btree
+ * nodes that are pinning the oldest journal entries first.
+ */
+
+#define BCACHE_JSET_VERSION_UUIDv1	1
+/* Always latest UUID format */
+#define BCACHE_JSET_VERSION_UUID	1
+#define BCACHE_JSET_VERSION		1
+
+/*
+ * On disk format for a journal entry:
+ * seq is monotonically increasing; every journal entry has its own unique
+ * sequence number.
+ *
+ * last_seq is the oldest journal entry that still has keys the btree hasn't
+ * flushed to disk yet.
+ *
+ * version is for on disk format changes.
+ */
+struct jset {
+	uint64_t		csum;
+	uint64_t		magic;
+	uint64_t		seq;
+	uint32_t		version;
+	uint32_t		keys;
+
+	uint64_t		last_seq;
+
+	BKEY_PADDED(uuid_bucket);
+	BKEY_PADDED(btree_root);
+	uint16_t		btree_level;
+	uint16_t		pad[3];
+
+	uint64_t		prio_bucket[MAX_CACHES_PER_SET];
+
+	union {
+		struct bkey	start[0];
+		uint64_t	d[0];
+	};
+};
+
+/*
+ * Only used for holding the journal entries we read in btree_journal_read()
+ * during cache_registration
+ */
+struct journal_replay {
+	struct list_head	list;
+	atomic_t		*pin;
+	struct jset		j;
+};
+
+/*
+ * We put two of these in struct journal; we used them for writes to the
+ * journal that are being staged or in flight.
+ */
+struct journal_write {
+	struct jset		*data;
+#define JSET_BITS		3
+
+	struct cache_set	*c;
+	struct closure_waitlist	wait;
+	bool			need_write;
+};
+
+/* Embedded in struct cache_set */
+struct journal {
+	spinlock_t		lock;
+	/* used when waiting because the journal was full */
+	struct closure_waitlist	wait;
+	struct closure_with_timer io;
+
+	/* Number of blocks free in the bucket(s) we're currently writing to */
+	unsigned		blocks_free;
+	uint64_t		seq;
+	DECLARE_FIFO(atomic_t, pin);
+
+	BKEY_PADDED(key);
+
+	struct journal_write	w[2], *cur;
+};
+
+/*
+ * Embedded in struct cache. First three fields refer to the array of journal
+ * buckets, in cache_sb.
+ */
+struct journal_device {
+	/*
+	 * For each journal bucket, contains the max sequence number of the
+	 * journal writes it contains - so we know when a bucket can be reused.
+	 */
+	uint64_t		seq[SB_JOURNAL_BUCKETS];
+
+	/* Journal bucket we're currently writing to */
+	unsigned		cur_idx;
+
+	/* Last journal bucket that still contains an open journal entry */
+	unsigned		last_idx;
+
+	/* Next journal bucket to be discarded */
+	unsigned		discard_idx;
+
+#define DISCARD_READY		0
+#define DISCARD_IN_FLIGHT	1
+#define DISCARD_DONE		2
+	/* 1 - discard in flight, -1 - discard completed */
+	atomic_t		discard_in_flight;
+
+	struct work_struct	discard_work;
+	struct bio		discard_bio;
+	struct bio_vec		discard_bv;
+
+	/* Bio for journal reads/writes to this device */
+	struct bio		bio;
+	struct bio_vec		bv[8];
+};
+
+#define journal_pin_cmp(c, l, r)				\
+	(fifo_idx(&(c)->journal.pin, (l)->journal) >		\
+	 fifo_idx(&(c)->journal.pin, (r)->journal))
+
+#define JOURNAL_PIN	20000
+
+#define journal_full(j)						\
+	(!(j)->blocks_free || fifo_free(&(j)->pin) <= 1)
+
+struct closure;
+struct cache_set;
+struct btree_op;
+
+void bch_journal(struct closure *);
+void bch_journal_next(struct journal *);
+void bch_journal_mark(struct cache_set *, struct list_head *);
+void bch_journal_meta(struct cache_set *, struct closure *);
+int bch_journal_read(struct cache_set *, struct list_head *,
+			struct btree_op *);
+int bch_journal_replay(struct cache_set *, struct list_head *,
+			  struct btree_op *);
+
+void bch_journal_free(struct cache_set *);
+int bch_journal_alloc(struct cache_set *);
+
+#endif /* _BCACHE_JOURNAL_H */
diff --git a/drivers/md/bcache/movinggc.c b/drivers/md/bcache/movinggc.c
new file mode 100644
index 0000000..8bf7ae1
--- /dev/null
+++ b/drivers/md/bcache/movinggc.c
@@ -0,0 +1,255 @@
+/*
+ * Moving/copying garbage collector
+ *
+ * Copyright 2012 Google, Inc.
+ */
+
+#include "bcache.h"
+#include "btree.h"
+#include "debug.h"
+#include "request.h"
+
+struct moving_io {
+	struct keybuf_key	*w;
+	struct search		s;
+	struct bbio		bio;
+};
+
+static bool moving_pred(struct keybuf *buf, struct bkey *k)
+{
+	struct cache_set *c = container_of(buf, struct cache_set,
+					   moving_gc_keys);
+	unsigned i;
+
+	for (i = 0; i < KEY_PTRS(k); i++) {
+		struct cache *ca = PTR_CACHE(c, k, i);
+		struct bucket *g = PTR_BUCKET(c, k, i);
+
+		if (GC_SECTORS_USED(g) < ca->gc_move_threshold)
+			return true;
+	}
+
+	return false;
+}
+
+/* Moving GC - IO loop */
+
+static void moving_io_destructor(struct closure *cl)
+{
+	struct moving_io *io = container_of(cl, struct moving_io, s.cl);
+	kfree(io);
+}
+
+static void write_moving_finish(struct closure *cl)
+{
+	struct moving_io *io = container_of(cl, struct moving_io, s.cl);
+	struct bio *bio = &io->bio.bio;
+	struct bio_vec *bv = bio_iovec_idx(bio, bio->bi_vcnt);
+
+	while (bv-- != bio->bi_io_vec)
+		__free_page(bv->bv_page);
+
+	pr_debug("%s %s", io->s.op.insert_collision
+		 ? "collision moving" : "moved",
+		 pkey(&io->w->key));
+
+	bch_keybuf_del(&io->s.op.c->moving_gc_keys, io->w);
+
+	atomic_dec_bug(&io->s.op.c->in_flight);
+	closure_wake_up(&io->s.op.c->moving_gc_wait);
+
+	closure_return_with_destructor(cl, moving_io_destructor);
+}
+
+static void read_moving_endio(struct bio *bio, int error,
+			      struct batch_complete *batch)
+{
+	struct moving_io *io = container_of(bio->bi_private,
+					    struct moving_io, s.cl);
+
+	if (error)
+		io->s.error = error;
+
+	bch_bbio_endio(io->s.op.c, bio, error, "reading data to move");
+}
+
+static void moving_init(struct moving_io *io)
+{
+	struct bio *bio = &io->bio.bio;
+
+	bio_init(bio);
+	bio_get(bio);
+	bio_set_prio(bio, IOPRIO_PRIO_VALUE(IOPRIO_CLASS_IDLE, 0));
+
+	bio->bi_size		= KEY_SIZE(&io->w->key) << 9;
+	bio->bi_max_vecs	= DIV_ROUND_UP(KEY_SIZE(&io->w->key),
+					       PAGE_SECTORS);
+	bio->bi_private		= &io->s.cl;
+	bio->bi_io_vec		= bio->bi_inline_vecs;
+	bch_bio_map(bio, NULL);
+}
+
+static void write_moving(struct closure *cl)
+{
+	struct search *s = container_of(cl, struct search, cl);
+	struct moving_io *io = container_of(s, struct moving_io, s);
+
+	if (!s->error) {
+		trace_bcache_write_moving(&io->bio.bio);
+
+		moving_init(io);
+
+		io->bio.bio.bi_sector	= KEY_START(&io->w->key);
+		s->op.lock		= -1;
+		s->op.write_prio	= 1;
+		s->op.cache_bio		= &io->bio.bio;
+
+		s->writeback		= KEY_DIRTY(&io->w->key);
+		s->op.csum		= KEY_CSUM(&io->w->key);
+
+		s->op.type = BTREE_REPLACE;
+		bkey_copy(&s->op.replace, &io->w->key);
+
+		closure_init(&s->op.cl, cl);
+		bch_insert_data(&s->op.cl);
+	}
+
+	continue_at(cl, write_moving_finish, NULL);
+}
+
+static void read_moving_submit(struct closure *cl)
+{
+	struct search *s = container_of(cl, struct search, cl);
+	struct moving_io *io = container_of(s, struct moving_io, s);
+	struct bio *bio = &io->bio.bio;
+
+	trace_bcache_read_moving(bio);
+	bch_submit_bbio(bio, s->op.c, &io->w->key, 0);
+
+	continue_at(cl, write_moving, bch_gc_wq);
+}
+
+static void read_moving(struct closure *cl)
+{
+	struct cache_set *c = container_of(cl, struct cache_set, moving_gc);
+	struct keybuf_key *w;
+	struct moving_io *io;
+	struct bio *bio;
+
+	/* XXX: if we error, background writeback could stall indefinitely */
+
+	while (!test_bit(CACHE_SET_STOPPING, &c->flags)) {
+		w = bch_keybuf_next_rescan(c, &c->moving_gc_keys, &MAX_KEY);
+		if (!w)
+			break;
+
+		io = kzalloc(sizeof(struct moving_io) + sizeof(struct bio_vec)
+			     * DIV_ROUND_UP(KEY_SIZE(&w->key), PAGE_SECTORS),
+			     GFP_KERNEL);
+		if (!io)
+			goto err;
+
+		w->private	= io;
+		io->w		= w;
+		io->s.op.inode	= KEY_INODE(&w->key);
+		io->s.op.c	= c;
+
+		moving_init(io);
+		bio = &io->bio.bio;
+
+		bio->bi_rw	= READ;
+		bio->bi_end_io	= read_moving_endio;
+
+		if (bch_bio_alloc_pages(bio, GFP_KERNEL))
+			goto err;
+
+		pr_debug("%s", pkey(&w->key));
+
+		closure_call(&io->s.cl, read_moving_submit, NULL, &c->gc.cl);
+
+		if (atomic_inc_return(&c->in_flight) >= 64) {
+			closure_wait_event(&c->moving_gc_wait, cl,
+					   atomic_read(&c->in_flight) < 64);
+			continue_at(cl, read_moving, bch_gc_wq);
+		}
+	}
+
+	if (0) {
+err:		if (!IS_ERR_OR_NULL(w->private))
+			kfree(w->private);
+
+		bch_keybuf_del(&c->moving_gc_keys, w);
+	}
+
+	closure_return(cl);
+}
+
+static bool bucket_cmp(struct bucket *l, struct bucket *r)
+{
+	return GC_SECTORS_USED(l) < GC_SECTORS_USED(r);
+}
+
+static unsigned bucket_heap_top(struct cache *ca)
+{
+	return GC_SECTORS_USED(heap_peek(&ca->heap));
+}
+
+void bch_moving_gc(struct closure *cl)
+{
+	struct cache_set *c = container_of(cl, struct cache_set, gc.cl);
+	struct cache *ca;
+	struct bucket *b;
+	unsigned i;
+
+	if (!c->copy_gc_enabled)
+		closure_return(cl);
+
+	mutex_lock(&c->bucket_lock);
+
+	for_each_cache(ca, c, i) {
+		unsigned sectors_to_move = 0;
+		unsigned reserve_sectors = ca->sb.bucket_size *
+			min(fifo_used(&ca->free), ca->free.size / 2);
+
+		ca->heap.used = 0;
+
+		for_each_bucket(b, ca) {
+			if (!GC_SECTORS_USED(b))
+				continue;
+
+			if (!heap_full(&ca->heap)) {
+				sectors_to_move += GC_SECTORS_USED(b);
+				heap_add(&ca->heap, b, bucket_cmp);
+			} else if (bucket_cmp(b, heap_peek(&ca->heap))) {
+				sectors_to_move -= bucket_heap_top(ca);
+				sectors_to_move += GC_SECTORS_USED(b);
+
+				ca->heap.data[0] = b;
+				heap_sift(&ca->heap, 0, bucket_cmp);
+			}
+		}
+
+		while (sectors_to_move > reserve_sectors) {
+			heap_pop(&ca->heap, b, bucket_cmp);
+			sectors_to_move -= GC_SECTORS_USED(b);
+		}
+
+		ca->gc_move_threshold = bucket_heap_top(ca);
+
+		pr_debug("threshold %u", ca->gc_move_threshold);
+	}
+
+	mutex_unlock(&c->bucket_lock);
+
+	c->moving_gc_keys.last_scanned = ZERO_KEY;
+
+	closure_init(&c->moving_gc, cl);
+	read_moving(&c->moving_gc);
+
+	closure_return(cl);
+}
+
+void bch_moving_init_cache_set(struct cache_set *c)
+{
+	bch_keybuf_init(&c->moving_gc_keys, moving_pred);
+}
diff --git a/drivers/md/bcache/request.c b/drivers/md/bcache/request.c
new file mode 100644
index 0000000..478f487
--- /dev/null
+++ b/drivers/md/bcache/request.c
@@ -0,0 +1,1414 @@
+/*
+ * Main bcache entry point - handle a read or a write request and decide what to
+ * do with it; the make_request functions are called by the block layer.
+ *
+ * Copyright 2010, 2011 Kent Overstreet <kent.overstreet@gmail.com>
+ * Copyright 2012 Google, Inc.
+ */
+
+#include "bcache.h"
+#include "btree.h"
+#include "debug.h"
+#include "request.h"
+
+#include <linux/cgroup.h>
+#include <linux/module.h>
+#include <linux/hash.h>
+#include <linux/random.h>
+#include "blk-cgroup.h"
+
+#include <trace/events/bcache.h>
+
+#define CUTOFF_CACHE_ADD	95
+#define CUTOFF_CACHE_READA	90
+#define CUTOFF_WRITEBACK	50
+#define CUTOFF_WRITEBACK_SYNC	75
+
+struct kmem_cache *bch_search_cache;
+
+static void check_should_skip(struct cached_dev *, struct search *);
+
+/* Cgroup interface */
+
+#ifdef CONFIG_CGROUP_BCACHE
+static struct bch_cgroup bcache_default_cgroup = { .cache_mode = -1 };
+
+static struct bch_cgroup *cgroup_to_bcache(struct cgroup *cgroup)
+{
+	struct cgroup_subsys_state *css;
+	return cgroup &&
+		(css = cgroup_subsys_state(cgroup, bcache_subsys_id))
+		? container_of(css, struct bch_cgroup, css)
+		: &bcache_default_cgroup;
+}
+
+struct bch_cgroup *bch_bio_to_cgroup(struct bio *bio)
+{
+	struct cgroup_subsys_state *css = bio->bi_css
+		? cgroup_subsys_state(bio->bi_css->cgroup, bcache_subsys_id)
+		: task_subsys_state(current, bcache_subsys_id);
+
+	return css
+		? container_of(css, struct bch_cgroup, css)
+		: &bcache_default_cgroup;
+}
+
+static ssize_t cache_mode_read(struct cgroup *cgrp, struct cftype *cft,
+			struct file *file,
+			char __user *buf, size_t nbytes, loff_t *ppos)
+{
+	char tmp[1024];
+	int len = bch_snprint_string_list(tmp, PAGE_SIZE, bch_cache_modes,
+					  cgroup_to_bcache(cgrp)->cache_mode + 1);
+
+	if (len < 0)
+		return len;
+
+	return simple_read_from_buffer(buf, nbytes, ppos, tmp, len);
+}
+
+static int cache_mode_write(struct cgroup *cgrp, struct cftype *cft,
+			    const char *buf)
+{
+	int v = bch_read_string_list(buf, bch_cache_modes);
+	if (v < 0)
+		return v;
+
+	cgroup_to_bcache(cgrp)->cache_mode = v - 1;
+	return 0;
+}
+
+static u64 bch_verify_read(struct cgroup *cgrp, struct cftype *cft)
+{
+	return cgroup_to_bcache(cgrp)->verify;
+}
+
+static int bch_verify_write(struct cgroup *cgrp, struct cftype *cft, u64 val)
+{
+	cgroup_to_bcache(cgrp)->verify = val;
+	return 0;
+}
+
+static u64 bch_cache_hits_read(struct cgroup *cgrp, struct cftype *cft)
+{
+	struct bch_cgroup *bcachecg = cgroup_to_bcache(cgrp);
+	return atomic_read(&bcachecg->stats.cache_hits);
+}
+
+static u64 bch_cache_misses_read(struct cgroup *cgrp, struct cftype *cft)
+{
+	struct bch_cgroup *bcachecg = cgroup_to_bcache(cgrp);
+	return atomic_read(&bcachecg->stats.cache_misses);
+}
+
+static u64 bch_cache_bypass_hits_read(struct cgroup *cgrp,
+					 struct cftype *cft)
+{
+	struct bch_cgroup *bcachecg = cgroup_to_bcache(cgrp);
+	return atomic_read(&bcachecg->stats.cache_bypass_hits);
+}
+
+static u64 bch_cache_bypass_misses_read(struct cgroup *cgrp,
+					   struct cftype *cft)
+{
+	struct bch_cgroup *bcachecg = cgroup_to_bcache(cgrp);
+	return atomic_read(&bcachecg->stats.cache_bypass_misses);
+}
+
+static struct cftype bch_files[] = {
+	{
+		.name		= "cache_mode",
+		.read		= cache_mode_read,
+		.write_string	= cache_mode_write,
+	},
+	{
+		.name		= "verify",
+		.read_u64	= bch_verify_read,
+		.write_u64	= bch_verify_write,
+	},
+	{
+		.name		= "cache_hits",
+		.read_u64	= bch_cache_hits_read,
+	},
+	{
+		.name		= "cache_misses",
+		.read_u64	= bch_cache_misses_read,
+	},
+	{
+		.name		= "cache_bypass_hits",
+		.read_u64	= bch_cache_bypass_hits_read,
+	},
+	{
+		.name		= "cache_bypass_misses",
+		.read_u64	= bch_cache_bypass_misses_read,
+	},
+	{ }	/* terminate */
+};
+
+static void init_bch_cgroup(struct bch_cgroup *cg)
+{
+	cg->cache_mode = -1;
+}
+
+static struct cgroup_subsys_state *bcachecg_create(struct cgroup *cgroup)
+{
+	struct bch_cgroup *cg;
+
+	cg = kzalloc(sizeof(*cg), GFP_KERNEL);
+	if (!cg)
+		return ERR_PTR(-ENOMEM);
+	init_bch_cgroup(cg);
+	return &cg->css;
+}
+
+static void bcachecg_destroy(struct cgroup *cgroup)
+{
+	struct bch_cgroup *cg = cgroup_to_bcache(cgroup);
+	free_css_id(&bcache_subsys, &cg->css);
+	kfree(cg);
+}
+
+struct cgroup_subsys bcache_subsys = {
+	.create		= bcachecg_create,
+	.destroy	= bcachecg_destroy,
+	.subsys_id	= bcache_subsys_id,
+	.name		= "bcache",
+	.module		= THIS_MODULE,
+};
+EXPORT_SYMBOL_GPL(bcache_subsys);
+#endif
+
+static unsigned cache_mode(struct cached_dev *dc, struct bio *bio)
+{
+#ifdef CONFIG_CGROUP_BCACHE
+	int r = bch_bio_to_cgroup(bio)->cache_mode;
+	if (r >= 0)
+		return r;
+#endif
+	return BDEV_CACHE_MODE(&dc->sb);
+}
+
+static bool verify(struct cached_dev *dc, struct bio *bio)
+{
+#ifdef CONFIG_CGROUP_BCACHE
+	if (bch_bio_to_cgroup(bio)->verify)
+		return true;
+#endif
+	return dc->verify;
+}
+
+static void bio_csum(struct bio *bio, struct bkey *k)
+{
+	struct bio_vec *bv;
+	uint64_t csum = 0;
+	int i;
+
+	bio_for_each_segment(bv, bio, i) {
+		void *d = kmap(bv->bv_page) + bv->bv_offset;
+		csum = bch_crc64_update(csum, d, bv->bv_len);
+		kunmap(bv->bv_page);
+	}
+
+	k->ptr[KEY_PTRS(k)] = csum & (~0ULL >> 1);
+}
+
+/* Insert data into cache */
+
+static void bio_invalidate(struct closure *cl)
+{
+	struct btree_op *op = container_of(cl, struct btree_op, cl);
+	struct bio *bio = op->cache_bio;
+
+	pr_debug("invalidating %i sectors from %llu",
+		 bio_sectors(bio), (uint64_t) bio->bi_sector);
+
+	while (bio_sectors(bio)) {
+		unsigned len = min(bio_sectors(bio), 1U << 14);
+
+		if (bch_keylist_realloc(&op->keys, 0, op->c))
+			goto out;
+
+		bio->bi_sector	+= len;
+		bio->bi_size	-= len << 9;
+
+		bch_keylist_add(&op->keys,
+				&KEY(op->inode, bio->bi_sector, len));
+	}
+
+	op->insert_data_done = true;
+	bio_put(bio);
+out:
+	continue_at(cl, bch_journal, bcache_wq);
+}
+
+struct open_bucket {
+	struct list_head	list;
+	struct task_struct	*last;
+	unsigned		sectors_free;
+	BKEY_PADDED(key);
+};
+
+void bch_open_buckets_free(struct cache_set *c)
+{
+	struct open_bucket *b;
+
+	while (!list_empty(&c->data_buckets)) {
+		b = list_first_entry(&c->data_buckets,
+				     struct open_bucket, list);
+		list_del(&b->list);
+		kfree(b);
+	}
+}
+
+int bch_open_buckets_alloc(struct cache_set *c)
+{
+	int i;
+
+	spin_lock_init(&c->data_bucket_lock);
+
+	for (i = 0; i < 6; i++) {
+		struct open_bucket *b = kzalloc(sizeof(*b), GFP_KERNEL);
+		if (!b)
+			return -ENOMEM;
+
+		list_add(&b->list, &c->data_buckets);
+	}
+
+	return 0;
+}
+
+/*
+ * We keep multiple buckets open for writes, and try to segregate different
+ * write streams for better cache utilization: first we look for a bucket where
+ * the last write to it was sequential with the current write, and failing that
+ * we look for a bucket that was last used by the same task.
+ *
+ * The ideas is if you've got multiple tasks pulling data into the cache at the
+ * same time, you'll get better cache utilization if you try to segregate their
+ * data and preserve locality.
+ *
+ * For example, say you've starting Firefox at the same time you're copying a
+ * bunch of files. Firefox will likely end up being fairly hot and stay in the
+ * cache awhile, but the data you copied might not be; if you wrote all that
+ * data to the same buckets it'd get invalidated at the same time.
+ *
+ * Both of those tasks will be doing fairly random IO so we can't rely on
+ * detecting sequential IO to segregate their data, but going off of the task
+ * should be a sane heuristic.
+ */
+static struct open_bucket *pick_data_bucket(struct cache_set *c,
+					    const struct bkey *search,
+					    struct task_struct *task,
+					    struct bkey *alloc)
+{
+	struct open_bucket *ret, *ret_task = NULL;
+
+	list_for_each_entry_reverse(ret, &c->data_buckets, list)
+		if (!bkey_cmp(&ret->key, search))
+			goto found;
+		else if (ret->last == task)
+			ret_task = ret;
+
+	ret = ret_task ?: list_first_entry(&c->data_buckets,
+					   struct open_bucket, list);
+found:
+	if (!ret->sectors_free && KEY_PTRS(alloc)) {
+		ret->sectors_free = c->sb.bucket_size;
+		bkey_copy(&ret->key, alloc);
+		bkey_init(alloc);
+	}
+
+	if (!ret->sectors_free)
+		ret = NULL;
+
+	return ret;
+}
+
+/*
+ * Allocates some space in the cache to write to, and k to point to the newly
+ * allocated space, and updates KEY_SIZE(k) and KEY_OFFSET(k) (to point to the
+ * end of the newly allocated space).
+ *
+ * May allocate fewer sectors than @sectors, KEY_SIZE(k) indicates how many
+ * sectors were actually allocated.
+ *
+ * If s->writeback is true, will not fail.
+ */
+static bool bch_alloc_sectors(struct bkey *k, unsigned sectors,
+			      struct search *s)
+{
+	struct cache_set *c = s->op.c;
+	struct open_bucket *b;
+	BKEY_PADDED(key) alloc;
+	struct closure cl, *w = NULL;
+	unsigned i;
+
+	if (s->writeback) {
+		closure_init_stack(&cl);
+		w = &cl;
+	}
+
+	/*
+	 * We might have to allocate a new bucket, which we can't do with a
+	 * spinlock held. So if we have to allocate, we drop the lock, allocate
+	 * and then retry. KEY_PTRS() indicates whether alloc points to
+	 * allocated bucket(s).
+	 */
+
+	bkey_init(&alloc.key);
+	spin_lock(&c->data_bucket_lock);
+
+	while (!(b = pick_data_bucket(c, k, s->task, &alloc.key))) {
+		unsigned watermark = s->op.write_prio
+			? WATERMARK_MOVINGGC
+			: WATERMARK_NONE;
+
+		spin_unlock(&c->data_bucket_lock);
+
+		if (bch_bucket_alloc_set(c, watermark, &alloc.key, 1, w))
+			return false;
+
+		spin_lock(&c->data_bucket_lock);
+	}
+
+	/*
+	 * If we had to allocate, we might race and not need to allocate the
+	 * second time we call find_data_bucket(). If we allocated a bucket but
+	 * didn't use it, drop the refcount bch_bucket_alloc_set() took:
+	 */
+	if (KEY_PTRS(&alloc.key))
+		__bkey_put(c, &alloc.key);
+
+	for (i = 0; i < KEY_PTRS(&b->key); i++)
+		EBUG_ON(ptr_stale(c, &b->key, i));
+
+	/* Set up the pointer to the space we're allocating: */
+
+	for (i = 0; i < KEY_PTRS(&b->key); i++)
+		k->ptr[i] = b->key.ptr[i];
+
+	sectors = min(sectors, b->sectors_free);
+
+	SET_KEY_OFFSET(k, KEY_OFFSET(k) + sectors);
+	SET_KEY_SIZE(k, sectors);
+	SET_KEY_PTRS(k, KEY_PTRS(&b->key));
+
+	/*
+	 * Move b to the end of the lru, and keep track of what this bucket was
+	 * last used for:
+	 */
+	list_move_tail(&b->list, &c->data_buckets);
+	bkey_copy_key(&b->key, k);
+	b->last = s->task;
+
+	b->sectors_free	-= sectors;
+
+	for (i = 0; i < KEY_PTRS(&b->key); i++) {
+		SET_PTR_OFFSET(&b->key, i, PTR_OFFSET(&b->key, i) + sectors);
+
+		atomic_long_add(sectors,
+				&PTR_CACHE(c, &b->key, i)->sectors_written);
+	}
+
+	if (b->sectors_free < c->sb.block_size)
+		b->sectors_free = 0;
+
+	/*
+	 * k takes refcounts on the buckets it points to until it's inserted
+	 * into the btree, but if we're done with this bucket we just transfer
+	 * get_data_bucket()'s refcount.
+	 */
+	if (b->sectors_free)
+		for (i = 0; i < KEY_PTRS(&b->key); i++)
+			atomic_inc(&PTR_BUCKET(c, &b->key, i)->pin);
+
+	spin_unlock(&c->data_bucket_lock);
+	return true;
+}
+
+static void bch_insert_data_error(struct closure *cl)
+{
+	struct btree_op *op = container_of(cl, struct btree_op, cl);
+
+	/*
+	 * Our data write just errored, which means we've got a bunch of keys to
+	 * insert that point to data that wasn't succesfully written.
+	 *
+	 * We don't have to insert those keys but we still have to invalidate
+	 * that region of the cache - so, if we just strip off all the pointers
+	 * from the keys we'll accomplish just that.
+	 */
+
+	struct bkey *src = op->keys.bottom, *dst = op->keys.bottom;
+
+	while (src != op->keys.top) {
+		struct bkey *n = bkey_next(src);
+
+		SET_KEY_PTRS(src, 0);
+		bkey_copy(dst, src);
+
+		dst = bkey_next(dst);
+		src = n;
+	}
+
+	op->keys.top = dst;
+
+	bch_journal(cl);
+}
+
+static void bch_insert_data_endio(struct bio *bio, int error,
+				  struct batch_complete *batch)
+{
+	struct closure *cl = bio->bi_private;
+	struct btree_op *op = container_of(cl, struct btree_op, cl);
+	struct search *s = container_of(op, struct search, op);
+
+	if (error) {
+		/* TODO: We could try to recover from this. */
+		if (s->writeback)
+			s->error = error;
+		else if (s->write)
+			set_closure_fn(cl, bch_insert_data_error, bcache_wq);
+		else
+			set_closure_fn(cl, NULL, NULL);
+	}
+
+	bch_bbio_endio(op->c, bio, error, "writing data to cache");
+}
+
+static void bch_insert_data_loop(struct closure *cl)
+{
+	struct btree_op *op = container_of(cl, struct btree_op, cl);
+	struct search *s = container_of(op, struct search, op);
+	struct bio *bio = op->cache_bio, *n;
+
+	if (op->skip)
+		return bio_invalidate(cl);
+
+	if (atomic_sub_return(bio_sectors(bio), &op->c->sectors_to_gc) < 0) {
+		set_gc_sectors(op->c);
+		bch_queue_gc(op->c);
+	}
+
+	do {
+		unsigned i;
+		struct bkey *k;
+		struct bio_set *split = s->d
+			? s->d->bio_split : op->c->bio_split;
+
+		/* 1 for the device pointer and 1 for the chksum */
+		if (bch_keylist_realloc(&op->keys,
+					1 + (op->csum ? 1 : 0),
+					op->c))
+			continue_at(cl, bch_journal, bcache_wq);
+
+		k = op->keys.top;
+		bkey_init(k);
+		SET_KEY_INODE(k, op->inode);
+		SET_KEY_OFFSET(k, bio->bi_sector);
+
+		if (!bch_alloc_sectors(k, bio_sectors(bio), s))
+			goto err;
+
+		n = bch_bio_split(bio, KEY_SIZE(k), GFP_NOIO, split);
+		if (!n) {
+			__bkey_put(op->c, k);
+			continue_at(cl, bch_insert_data_loop, bcache_wq);
+		}
+
+		n->bi_end_io	= bch_insert_data_endio;
+		n->bi_private	= cl;
+
+		if (s->writeback) {
+			SET_KEY_DIRTY(k, true);
+
+			for (i = 0; i < KEY_PTRS(k); i++)
+				SET_GC_MARK(PTR_BUCKET(op->c, k, i),
+					    GC_MARK_DIRTY);
+		}
+
+		SET_KEY_CSUM(k, op->csum);
+		if (KEY_CSUM(k))
+			bio_csum(n, k);
+
+		pr_debug("%s", pkey(k));
+		bch_keylist_push(&op->keys);
+
+		trace_bcache_cache_insert(n, n->bi_sector, n->bi_bdev);
+		n->bi_rw |= REQ_WRITE;
+		bch_submit_bbio(n, op->c, k, 0);
+	} while (n != bio);
+
+	op->insert_data_done = true;
+	continue_at(cl, bch_journal, bcache_wq);
+err:
+	/* bch_alloc_sectors() blocks if s->writeback = true */
+	BUG_ON(s->writeback);
+
+	/*
+	 * But if it's not a writeback write we'd rather just bail out if
+	 * there aren't any buckets ready to write to - it might take awhile and
+	 * we might be starving btree writes for gc or something.
+	 */
+
+	if (s->write) {
+		/*
+		 * Writethrough write: We can't complete the write until we've
+		 * updated the index. But we don't want to delay the write while
+		 * we wait for buckets to be freed up, so just invalidate the
+		 * rest of the write.
+		 */
+		op->skip = true;
+		return bio_invalidate(cl);
+	} else {
+		/*
+		 * From a cache miss, we can just insert the keys for the data
+		 * we have written or bail out if we didn't do anything.
+		 */
+		op->insert_data_done = true;
+		bio_put(bio);
+
+		if (!bch_keylist_empty(&op->keys))
+			continue_at(cl, bch_journal, bcache_wq);
+		else
+			closure_return(cl);
+	}
+}
+
+/**
+ * bch_insert_data - stick some data in the cache
+ *
+ * This is the starting point for any data to end up in a cache device; it could
+ * be from a normal write, or a writeback write, or a write to a flash only
+ * volume - it's also used by the moving garbage collector to compact data in
+ * mostly empty buckets.
+ *
+ * It first writes the data to the cache, creating a list of keys to be inserted
+ * (if the data had to be fragmented there will be multiple keys); after the
+ * data is written it calls bch_journal, and after the keys have been added to
+ * the next journal write they're inserted into the btree.
+ *
+ * It inserts the data in op->cache_bio; bi_sector is used for the key offset,
+ * and op->inode is used for the key inode.
+ *
+ * If op->skip is true, instead of inserting the data it invalidates the region
+ * of the cache represented by op->cache_bio and op->inode.
+ */
+void bch_insert_data(struct closure *cl)
+{
+	struct btree_op *op = container_of(cl, struct btree_op, cl);
+
+	bch_keylist_init(&op->keys);
+	bio_get(op->cache_bio);
+	bch_insert_data_loop(cl);
+}
+
+void bch_btree_insert_async(struct closure *cl)
+{
+	struct btree_op *op = container_of(cl, struct btree_op, cl);
+	struct search *s = container_of(op, struct search, op);
+
+	if (bch_btree_insert(op, op->c)) {
+		s->error		= -ENOMEM;
+		op->insert_data_done	= true;
+	}
+
+	if (op->insert_data_done) {
+		bch_keylist_free(&op->keys);
+		closure_return(cl);
+	} else
+		continue_at(cl, bch_insert_data_loop, bcache_wq);
+}
+
+/* Common code for the make_request functions */
+
+static void request_endio(struct bio *bio, int error,
+			  struct batch_complete *batch)
+{
+	struct closure *cl = bio->bi_private;
+
+	if (error) {
+		struct search *s = container_of(cl, struct search, cl);
+		s->error = error;
+		/* Only cache read errors are recoverable */
+		s->recoverable = false;
+	}
+
+	bio_put(bio);
+	closure_put(cl);
+}
+
+void bch_cache_read_endio(struct bio *bio, int error,
+			  struct batch_complete *batch)
+{
+	struct bbio *b = container_of(bio, struct bbio, bio);
+	struct closure *cl = bio->bi_private;
+	struct search *s = container_of(cl, struct search, cl);
+
+	/*
+	 * If the bucket was reused while our bio was in flight, we might have
+	 * read the wrong data. Set s->error but not error so it doesn't get
+	 * counted against the cache device, but we'll still reread the data
+	 * from the backing device.
+	 */
+
+	if (error)
+		s->error = error;
+	else if (ptr_stale(s->op.c, &b->key, 0)) {
+		atomic_long_inc(&s->op.c->cache_read_races);
+		s->error = -EINTR;
+	}
+
+	bch_bbio_endio(s->op.c, bio, error, "reading from cache");
+}
+
+static void bio_complete(struct search *s)
+{
+	if (s->orig_bio) {
+		int cpu, rw = bio_data_dir(s->orig_bio);
+		unsigned long duration = jiffies - s->start_time;
+
+		cpu = part_stat_lock();
+		part_round_stats(cpu, &s->d->disk->part0);
+		part_stat_add(cpu, &s->d->disk->part0, ticks[rw], duration);
+		part_stat_unlock();
+
+		trace_bcache_request_end(s, s->orig_bio);
+		bio_endio(s->orig_bio, s->error);
+		s->orig_bio = NULL;
+	}
+}
+
+static void do_bio_hook(struct search *s)
+{
+	struct bio *bio = &s->bio.bio;
+	memcpy(bio, s->orig_bio, sizeof(struct bio));
+
+	bio->bi_end_io		= request_endio;
+	bio->bi_private		= &s->cl;
+	atomic_set(&bio->bi_cnt, 3);
+}
+
+static void search_free(struct closure *cl)
+{
+	struct search *s = container_of(cl, struct search, cl);
+	bio_complete(s);
+
+	if (s->op.cache_bio)
+		bio_put(s->op.cache_bio);
+
+	if (s->unaligned_bvec)
+		mempool_free(s->bio.bio.bi_io_vec, s->d->unaligned_bvec);
+
+	closure_debug_destroy(cl);
+	mempool_free(s, s->d->c->search);
+}
+
+static struct search *search_alloc(struct bio *bio, struct bcache_device *d)
+{
+	struct bio_vec *bv;
+	struct search *s = mempool_alloc(d->c->search, GFP_NOIO);
+	memset(s, 0, offsetof(struct search, op.keys));
+
+	__closure_init(&s->cl, NULL);
+
+	s->op.inode		= d->id;
+	s->op.c			= d->c;
+	s->d			= d;
+	s->op.lock		= -1;
+	s->task			= current;
+	s->orig_bio		= bio;
+	s->write		= (bio->bi_rw & REQ_WRITE) != 0;
+	s->op.flush_journal	= (bio->bi_rw & REQ_FLUSH) != 0;
+	s->op.skip		= (bio->bi_rw & REQ_DISCARD) != 0;
+	s->recoverable		= 1;
+	s->start_time		= jiffies;
+	do_bio_hook(s);
+
+	if (bio->bi_size != bio_segments(bio) * PAGE_SIZE) {
+		bv = mempool_alloc(d->unaligned_bvec, GFP_NOIO);
+		memcpy(bv, bio_iovec(bio),
+		       sizeof(struct bio_vec) * bio_segments(bio));
+
+		s->bio.bio.bi_io_vec	= bv;
+		s->unaligned_bvec	= 1;
+	}
+
+	return s;
+}
+
+static void btree_read_async(struct closure *cl)
+{
+	struct btree_op *op = container_of(cl, struct btree_op, cl);
+
+	int ret = btree_root(search_recurse, op->c, op);
+
+	if (ret == -EAGAIN)
+		continue_at(cl, btree_read_async, bcache_wq);
+
+	closure_return(cl);
+}
+
+/* Cached devices */
+
+static void cached_dev_bio_complete(struct closure *cl)
+{
+	struct search *s = container_of(cl, struct search, cl);
+	struct cached_dev *dc = container_of(s->d, struct cached_dev, disk);
+
+	search_free(cl);
+	cached_dev_put(dc);
+}
+
+/* Process reads */
+
+static void cached_dev_read_complete(struct closure *cl)
+{
+	struct search *s = container_of(cl, struct search, cl);
+
+	if (s->op.insert_collision)
+		bch_mark_cache_miss_collision(s);
+
+	if (s->op.cache_bio) {
+		int i;
+		struct bio_vec *bv;
+
+		__bio_for_each_segment(bv, s->op.cache_bio, i, 0)
+			__free_page(bv->bv_page);
+	}
+
+	cached_dev_bio_complete(cl);
+}
+
+static void request_read_error(struct closure *cl)
+{
+	struct search *s = container_of(cl, struct search, cl);
+	struct bio_vec *bv;
+	int i;
+
+	if (s->recoverable) {
+		/* The cache read failed, but we can retry from the backing
+		 * device.
+		 */
+		pr_debug("recovering at sector %llu",
+			 (uint64_t) s->orig_bio->bi_sector);
+
+		s->error = 0;
+		bv = s->bio.bio.bi_io_vec;
+		do_bio_hook(s);
+		s->bio.bio.bi_io_vec = bv;
+
+		if (!s->unaligned_bvec)
+			bio_for_each_segment(bv, s->orig_bio, i)
+				bv->bv_offset = 0, bv->bv_len = PAGE_SIZE;
+		else
+			memcpy(s->bio.bio.bi_io_vec,
+			       bio_iovec(s->orig_bio),
+			       sizeof(struct bio_vec) *
+			       bio_segments(s->orig_bio));
+
+		/* XXX: invalidate cache */
+
+		trace_bcache_read_retry(&s->bio.bio);
+		closure_bio_submit(&s->bio.bio, &s->cl, s->d);
+	}
+
+	continue_at(cl, cached_dev_read_complete, NULL);
+}
+
+static void request_read_done(struct closure *cl)
+{
+	struct search *s = container_of(cl, struct search, cl);
+	struct cached_dev *dc = container_of(s->d, struct cached_dev, disk);
+
+	/*
+	 * s->cache_bio != NULL implies that we had a cache miss; cache_bio now
+	 * contains data ready to be inserted into the cache.
+	 *
+	 * First, we copy the data we just read from cache_bio's bounce buffers
+	 * to the buffers the original bio pointed to:
+	 */
+
+	if (s->op.cache_bio) {
+		struct bio_vec *src, *dst;
+		unsigned src_offset, dst_offset, bytes;
+		void *dst_ptr;
+
+		bio_reset(s->op.cache_bio);
+		s->op.cache_bio->bi_sector	= s->cache_miss->bi_sector;
+		s->op.cache_bio->bi_bdev	= s->cache_miss->bi_bdev;
+		s->op.cache_bio->bi_size	= s->cache_bio_sectors << 9;
+		bch_bio_map(s->op.cache_bio, NULL);
+
+		src = bio_iovec(s->op.cache_bio);
+		dst = bio_iovec(s->cache_miss);
+		src_offset = src->bv_offset;
+		dst_offset = dst->bv_offset;
+		dst_ptr = kmap(dst->bv_page);
+
+		while (1) {
+			if (dst_offset == dst->bv_offset + dst->bv_len) {
+				kunmap(dst->bv_page);
+				dst++;
+				if (dst == bio_iovec_idx(s->cache_miss,
+						s->cache_miss->bi_vcnt))
+					break;
+
+				dst_offset = dst->bv_offset;
+				dst_ptr = kmap(dst->bv_page);
+			}
+
+			if (src_offset == src->bv_offset + src->bv_len) {
+				src++;
+				if (src == bio_iovec_idx(s->op.cache_bio,
+						 s->op.cache_bio->bi_vcnt))
+					BUG();
+
+				src_offset = src->bv_offset;
+			}
+
+			bytes = min(dst->bv_offset + dst->bv_len - dst_offset,
+				    src->bv_offset + src->bv_len - src_offset);
+
+			memcpy(dst_ptr + dst_offset,
+			       page_address(src->bv_page) + src_offset,
+			       bytes);
+
+			src_offset	+= bytes;
+			dst_offset	+= bytes;
+		}
+
+		bio_put(s->cache_miss);
+		s->cache_miss = NULL;
+	}
+
+	if (verify(dc, &s->bio.bio) && s->recoverable)
+		bch_data_verify(s);
+
+	bio_complete(s);
+
+	if (s->op.cache_bio &&
+	    !test_bit(CACHE_SET_STOPPING, &s->op.c->flags)) {
+		s->op.type = BTREE_REPLACE;
+		closure_call(&s->op.cl, bch_insert_data, NULL, cl);
+	}
+
+	continue_at(cl, cached_dev_read_complete, NULL);
+}
+
+static void request_read_done_bh(struct closure *cl)
+{
+	struct search *s = container_of(cl, struct search, cl);
+	struct cached_dev *dc = container_of(s->d, struct cached_dev, disk);
+
+	bch_mark_cache_accounting(s, !s->cache_miss, s->op.skip);
+
+	if (s->error)
+		continue_at_nobarrier(cl, request_read_error, bcache_wq);
+	else if (s->op.cache_bio || verify(dc, &s->bio.bio))
+		continue_at_nobarrier(cl, request_read_done, bcache_wq);
+	else
+		continue_at_nobarrier(cl, cached_dev_read_complete, NULL);
+}
+
+static int cached_dev_cache_miss(struct btree *b, struct search *s,
+				 struct bio *bio, unsigned sectors)
+{
+	int ret = 0;
+	unsigned reada;
+	struct cached_dev *dc = container_of(s->d, struct cached_dev, disk);
+	struct bio *miss;
+
+	miss = bch_bio_split(bio, sectors, GFP_NOIO, s->d->bio_split);
+	if (!miss)
+		return -EAGAIN;
+
+	if (miss == bio)
+		s->op.lookup_done = true;
+
+	miss->bi_end_io		= request_endio;
+	miss->bi_private	= &s->cl;
+
+	if (s->cache_miss || s->op.skip)
+		goto out_submit;
+
+	if (miss != bio ||
+	    (bio->bi_rw & REQ_RAHEAD) ||
+	    (bio->bi_rw & REQ_META) ||
+	    s->op.c->gc_stats.in_use >= CUTOFF_CACHE_READA)
+		reada = 0;
+	else {
+		reada = min(dc->readahead >> 9,
+			    sectors - bio_sectors(miss));
+
+		if (bio_end(miss) + reada > bdev_sectors(miss->bi_bdev))
+			reada = bdev_sectors(miss->bi_bdev) - bio_end(miss);
+	}
+
+	s->cache_bio_sectors = bio_sectors(miss) + reada;
+	s->op.cache_bio = bio_alloc_bioset(GFP_NOWAIT,
+			DIV_ROUND_UP(s->cache_bio_sectors, PAGE_SECTORS),
+			dc->disk.bio_split);
+
+	if (!s->op.cache_bio)
+		goto out_submit;
+
+	s->op.cache_bio->bi_sector	= miss->bi_sector;
+	s->op.cache_bio->bi_bdev	= miss->bi_bdev;
+	s->op.cache_bio->bi_size	= s->cache_bio_sectors << 9;
+
+	s->op.cache_bio->bi_end_io	= request_endio;
+	s->op.cache_bio->bi_private	= &s->cl;
+
+	/* btree_search_recurse()'s btree iterator is no good anymore */
+	ret = -EINTR;
+	if (!bch_btree_insert_check_key(b, &s->op, s->op.cache_bio))
+		goto out_put;
+
+	bch_bio_map(s->op.cache_bio, NULL);
+	if (bch_bio_alloc_pages(s->op.cache_bio, __GFP_NOWARN|GFP_NOIO))
+		goto out_put;
+
+	s->cache_miss = miss;
+	bio_get(s->op.cache_bio);
+
+	trace_bcache_cache_miss(s->orig_bio);
+	closure_bio_submit(s->op.cache_bio, &s->cl, s->d);
+
+	return ret;
+out_put:
+	bio_put(s->op.cache_bio);
+	s->op.cache_bio = NULL;
+out_submit:
+	closure_bio_submit(miss, &s->cl, s->d);
+	return ret;
+}
+
+static void request_read(struct cached_dev *dc, struct search *s)
+{
+	struct closure *cl = &s->cl;
+
+	check_should_skip(dc, s);
+	closure_call(&s->op.cl, btree_read_async, NULL, cl);
+
+	continue_at(cl, request_read_done_bh, NULL);
+}
+
+/* Process writes */
+
+static void cached_dev_write_complete(struct closure *cl)
+{
+	struct search *s = container_of(cl, struct search, cl);
+	struct cached_dev *dc = container_of(s->d, struct cached_dev, disk);
+
+	up_read_non_owner(&dc->writeback_lock);
+	cached_dev_bio_complete(cl);
+}
+
+static bool should_writeback(struct cached_dev *dc, struct bio *bio)
+{
+	unsigned threshold = (bio->bi_rw & REQ_SYNC)
+		? CUTOFF_WRITEBACK_SYNC
+		: CUTOFF_WRITEBACK;
+
+	return !atomic_read(&dc->disk.detaching) &&
+		cache_mode(dc, bio) == CACHE_MODE_WRITEBACK &&
+		dc->disk.c->gc_stats.in_use < threshold;
+}
+
+static void request_write(struct cached_dev *dc, struct search *s)
+{
+	struct closure *cl = &s->cl;
+	struct bio *bio = &s->bio.bio;
+	struct bkey start, end;
+	start = KEY(dc->disk.id, bio->bi_sector, 0);
+	end = KEY(dc->disk.id, bio_end(bio), 0);
+
+	bch_keybuf_check_overlapping(&s->op.c->moving_gc_keys, &start, &end);
+
+	check_should_skip(dc, s);
+	down_read_non_owner(&dc->writeback_lock);
+
+	if (bch_keybuf_check_overlapping(&dc->writeback_keys, &start, &end)) {
+		s->op.skip	= false;
+		s->writeback	= true;
+	}
+
+	if (bio->bi_rw & REQ_DISCARD)
+		goto skip;
+
+	if (s->op.skip)
+		goto skip;
+
+	if (should_writeback(dc, s->orig_bio))
+		s->writeback = true;
+
+	if (!s->writeback) {
+		s->op.cache_bio = bio_clone_bioset(bio, GFP_NOIO,
+						   dc->disk.bio_split);
+
+		trace_bcache_writethrough(s->orig_bio);
+		closure_bio_submit(bio, cl, s->d);
+	} else {
+		s->op.cache_bio = bio;
+		trace_bcache_writeback(s->orig_bio);
+		bch_writeback_add(dc, bio_sectors(bio));
+	}
+out:
+	closure_call(&s->op.cl, bch_insert_data, NULL, cl);
+	continue_at(cl, cached_dev_write_complete, NULL);
+skip:
+	s->op.skip = true;
+	s->op.cache_bio = s->orig_bio;
+	bio_get(s->op.cache_bio);
+	trace_bcache_write_skip(s->orig_bio);
+
+	if ((bio->bi_rw & REQ_DISCARD) &&
+	    !blk_queue_discard(bdev_get_queue(dc->bdev)))
+		goto out;
+
+	closure_bio_submit(bio, cl, s->d);
+	goto out;
+}
+
+static void request_nodata(struct cached_dev *dc, struct search *s)
+{
+	struct closure *cl = &s->cl;
+	struct bio *bio = &s->bio.bio;
+
+	if (bio->bi_rw & REQ_DISCARD) {
+		request_write(dc, s);
+		return;
+	}
+
+	if (s->op.flush_journal)
+		bch_journal_meta(s->op.c, cl);
+
+	closure_bio_submit(bio, cl, s->d);
+
+	continue_at(cl, cached_dev_bio_complete, NULL);
+}
+
+/* Cached devices - read & write stuff */
+
+int bch_get_congested(struct cache_set *c)
+{
+	int i;
+
+	if (!c->congested_read_threshold_us &&
+	    !c->congested_write_threshold_us)
+		return 0;
+
+	i = (local_clock_us() - c->congested_last_us) / 1024;
+	if (i < 0)
+		return 0;
+
+	i += atomic_read(&c->congested);
+	if (i >= 0)
+		return 0;
+
+	i += CONGESTED_MAX;
+
+	return i <= 0 ? 1 : fract_exp_two(i, 6);
+}
+
+static void add_sequential(struct task_struct *t)
+{
+	ewma_add(t->sequential_io_avg,
+		 t->sequential_io, 8, 0);
+
+	t->sequential_io = 0;
+}
+
+static struct hlist_head *iohash(struct cached_dev *dc, uint64_t k)
+{
+	return &dc->io_hash[hash_64(k, RECENT_IO_BITS)];
+}
+
+static void check_should_skip(struct cached_dev *dc, struct search *s)
+{
+	struct cache_set *c = s->op.c;
+	struct bio *bio = &s->bio.bio;
+
+	long rand;
+	int cutoff = bch_get_congested(c);
+	unsigned mode = cache_mode(dc, bio);
+
+	if (atomic_read(&dc->disk.detaching) ||
+	    c->gc_stats.in_use > CUTOFF_CACHE_ADD ||
+	    (bio->bi_rw & REQ_DISCARD))
+		goto skip;
+
+	if (mode == CACHE_MODE_NONE ||
+	    (mode == CACHE_MODE_WRITEAROUND &&
+	     (bio->bi_rw & REQ_WRITE)))
+		goto skip;
+
+	if (bio->bi_sector   & (c->sb.block_size - 1) ||
+	    bio_sectors(bio) & (c->sb.block_size - 1)) {
+		pr_debug("skipping unaligned io");
+		goto skip;
+	}
+
+	if (!cutoff) {
+		cutoff = dc->sequential_cutoff >> 9;
+
+		if (!cutoff)
+			goto rescale;
+
+		if (mode == CACHE_MODE_WRITEBACK &&
+		    (bio->bi_rw & REQ_WRITE) &&
+		    (bio->bi_rw & REQ_SYNC))
+			goto rescale;
+	}
+
+	if (dc->sequential_merge) {
+		struct io *i;
+
+		spin_lock(&dc->io_lock);
+
+		hlist_for_each_entry(i, iohash(dc, bio->bi_sector), hash)
+			if (i->last == bio->bi_sector &&
+			    time_before(jiffies, i->jiffies))
+				goto found;
+
+		i = list_first_entry(&dc->io_lru, struct io, lru);
+
+		add_sequential(s->task);
+		i->sequential = 0;
+found:
+		if (i->sequential + bio->bi_size > i->sequential)
+			i->sequential	+= bio->bi_size;
+
+		i->last			 = bio_end(bio);
+		i->jiffies		 = jiffies + msecs_to_jiffies(5000);
+		s->task->sequential_io	 = i->sequential;
+
+		hlist_del(&i->hash);
+		hlist_add_head(&i->hash, iohash(dc, i->last));
+		list_move_tail(&i->lru, &dc->io_lru);
+
+		spin_unlock(&dc->io_lock);
+	} else {
+		s->task->sequential_io = bio->bi_size;
+
+		add_sequential(s->task);
+	}
+
+	rand = get_random_int();
+	cutoff -= bitmap_weight(&rand, BITS_PER_LONG);
+
+	if (cutoff <= (int) (max(s->task->sequential_io,
+				 s->task->sequential_io_avg) >> 9))
+		goto skip;
+
+rescale:
+	bch_rescale_priorities(c, bio_sectors(bio));
+	return;
+skip:
+	bch_mark_sectors_bypassed(s, bio_sectors(bio));
+	s->op.skip = true;
+}
+
+static void cached_dev_make_request(struct request_queue *q, struct bio *bio)
+{
+	struct search *s;
+	struct bcache_device *d = bio->bi_bdev->bd_disk->private_data;
+	struct cached_dev *dc = container_of(d, struct cached_dev, disk);
+	int cpu, rw = bio_data_dir(bio);
+
+	cpu = part_stat_lock();
+	part_stat_inc(cpu, &d->disk->part0, ios[rw]);
+	part_stat_add(cpu, &d->disk->part0, sectors[rw], bio_sectors(bio));
+	part_stat_unlock();
+
+	bio->bi_bdev = dc->bdev;
+	bio->bi_sector += BDEV_DATA_START;
+
+	if (cached_dev_get(dc)) {
+		s = search_alloc(bio, d);
+		trace_bcache_request_start(s, bio);
+
+		if (!bio_has_data(bio))
+			request_nodata(dc, s);
+		else if (rw)
+			request_write(dc, s);
+		else
+			request_read(dc, s);
+	} else {
+		if ((bio->bi_rw & REQ_DISCARD) &&
+		    !blk_queue_discard(bdev_get_queue(dc->bdev)))
+			bio_endio(bio, 0);
+		else
+			bch_generic_make_request(bio, &d->bio_split_hook);
+	}
+}
+
+static int cached_dev_ioctl(struct bcache_device *d, fmode_t mode,
+			    unsigned int cmd, unsigned long arg)
+{
+	struct cached_dev *dc = container_of(d, struct cached_dev, disk);
+	return __blkdev_driver_ioctl(dc->bdev, mode, cmd, arg);
+}
+
+static int cached_dev_congested(void *data, int bits)
+{
+	struct bcache_device *d = data;
+	struct cached_dev *dc = container_of(d, struct cached_dev, disk);
+	struct request_queue *q = bdev_get_queue(dc->bdev);
+	int ret = 0;
+
+	if (bdi_congested(&q->backing_dev_info, bits))
+		return 1;
+
+	if (cached_dev_get(dc)) {
+		unsigned i;
+		struct cache *ca;
+
+		for_each_cache(ca, d->c, i) {
+			q = bdev_get_queue(ca->bdev);
+			ret |= bdi_congested(&q->backing_dev_info, bits);
+		}
+
+		cached_dev_put(dc);
+	}
+
+	return ret;
+}
+
+void bch_cached_dev_request_init(struct cached_dev *dc)
+{
+	struct gendisk *g = dc->disk.disk;
+
+	g->queue->make_request_fn		= cached_dev_make_request;
+	g->queue->backing_dev_info.congested_fn = cached_dev_congested;
+	dc->disk.cache_miss			= cached_dev_cache_miss;
+	dc->disk.ioctl				= cached_dev_ioctl;
+}
+
+/* Flash backed devices */
+
+static int flash_dev_cache_miss(struct btree *b, struct search *s,
+				struct bio *bio, unsigned sectors)
+{
+	/* Zero fill bio */
+
+	while (bio->bi_idx != bio->bi_vcnt) {
+		struct bio_vec *bv = bio_iovec(bio);
+		unsigned j = min(bv->bv_len >> 9, sectors);
+
+		void *p = kmap(bv->bv_page);
+		memset(p + bv->bv_offset, 0, j << 9);
+		kunmap(bv->bv_page);
+
+		bv->bv_len	-= j << 9;
+		bv->bv_offset	+= j << 9;
+
+		if (bv->bv_len)
+			return 0;
+
+		bio->bi_sector	+= j;
+		bio->bi_size	-= j << 9;
+
+		bio->bi_idx++;
+		sectors		-= j;
+	}
+
+	s->op.lookup_done = true;
+
+	return 0;
+}
+
+static void flash_dev_make_request(struct request_queue *q, struct bio *bio)
+{
+	struct search *s;
+	struct closure *cl;
+	struct bcache_device *d = bio->bi_bdev->bd_disk->private_data;
+	int cpu, rw = bio_data_dir(bio);
+
+	cpu = part_stat_lock();
+	part_stat_inc(cpu, &d->disk->part0, ios[rw]);
+	part_stat_add(cpu, &d->disk->part0, sectors[rw], bio_sectors(bio));
+	part_stat_unlock();
+
+	s = search_alloc(bio, d);
+	cl = &s->cl;
+	bio = &s->bio.bio;
+
+	trace_bcache_request_start(s, bio);
+
+	if (bio_has_data(bio) && !rw) {
+		closure_call(&s->op.cl, btree_read_async, NULL, cl);
+	} else if (bio_has_data(bio) || s->op.skip) {
+		bch_keybuf_check_overlapping(&s->op.c->moving_gc_keys,
+					     &KEY(d->id, bio->bi_sector, 0),
+					     &KEY(d->id, bio_end(bio), 0));
+
+		s->writeback	= true;
+		s->op.cache_bio	= bio;
+
+		closure_call(&s->op.cl, bch_insert_data, NULL, cl);
+	} else {
+		/* No data - probably a cache flush */
+		if (s->op.flush_journal)
+			bch_journal_meta(s->op.c, cl);
+	}
+
+	continue_at(cl, search_free, NULL);
+}
+
+static int flash_dev_ioctl(struct bcache_device *d, fmode_t mode,
+			   unsigned int cmd, unsigned long arg)
+{
+	return -ENOTTY;
+}
+
+static int flash_dev_congested(void *data, int bits)
+{
+	struct bcache_device *d = data;
+	struct request_queue *q;
+	struct cache *ca;
+	unsigned i;
+	int ret = 0;
+
+	for_each_cache(ca, d->c, i) {
+		q = bdev_get_queue(ca->bdev);
+		ret |= bdi_congested(&q->backing_dev_info, bits);
+	}
+
+	return ret;
+}
+
+void bch_flash_dev_request_init(struct bcache_device *d)
+{
+	struct gendisk *g = d->disk;
+
+	g->queue->make_request_fn		= flash_dev_make_request;
+	g->queue->backing_dev_info.congested_fn = flash_dev_congested;
+	d->cache_miss				= flash_dev_cache_miss;
+	d->ioctl				= flash_dev_ioctl;
+}
+
+void bch_request_exit(void)
+{
+#ifdef CONFIG_CGROUP_BCACHE
+	cgroup_unload_subsys(&bcache_subsys);
+#endif
+	if (bch_search_cache)
+		kmem_cache_destroy(bch_search_cache);
+}
+
+int __init bch_request_init(void)
+{
+	bch_search_cache = KMEM_CACHE(search, 0);
+	if (!bch_search_cache)
+		return -ENOMEM;
+
+#ifdef CONFIG_CGROUP_BCACHE
+	cgroup_load_subsys(&bcache_subsys);
+	init_bch_cgroup(&bcache_default_cgroup);
+
+	cgroup_add_cftypes(&bcache_subsys, bch_files);
+#endif
+	return 0;
+}
diff --git a/drivers/md/bcache/request.h b/drivers/md/bcache/request.h
new file mode 100644
index 0000000..3b79462
--- /dev/null
+++ b/drivers/md/bcache/request.h
@@ -0,0 +1,61 @@
+#ifndef _BCACHE_REQUEST_H_
+#define _BCACHE_REQUEST_H_
+
+#include <linux/cgroup.h>
+
+struct search {
+	/* Stack frame for bio_complete */
+	struct closure		cl;
+
+	struct bcache_device	*d;
+	struct task_struct	*task;
+
+	struct bbio		bio;
+	struct bio		*orig_bio;
+	struct bio		*cache_miss;
+	unsigned		cache_bio_sectors;
+
+	unsigned		recoverable:1;
+	unsigned		unaligned_bvec:1;
+
+	unsigned		write:1;
+	unsigned		writeback:1;
+
+	/* IO error returned to s->bio */
+	short			error;
+	unsigned long		start_time;
+
+	/* Anything past op->keys won't get zeroed in do_bio_hook */
+	struct btree_op		op;
+};
+
+void bch_cache_read_endio(struct bio *, int, struct batch_complete *batch);
+int bch_get_congested(struct cache_set *);
+void bch_insert_data(struct closure *cl);
+void bch_btree_insert_async(struct closure *);
+
+void bch_open_buckets_free(struct cache_set *);
+int bch_open_buckets_alloc(struct cache_set *);
+
+void bch_cached_dev_request_init(struct cached_dev *dc);
+void bch_flash_dev_request_init(struct bcache_device *d);
+
+extern struct kmem_cache *bch_search_cache, *bch_passthrough_cache;
+
+struct bch_cgroup {
+#ifdef CONFIG_CGROUP_BCACHE
+	struct cgroup_subsys_state	css;
+#endif
+	/*
+	 * We subtract one from the index into bch_cache_modes[], so that
+	 * default == -1; this makes it so the rest match up with d->cache_mode,
+	 * and we use d->cache_mode if cgrp->cache_mode < 0
+	 */
+	short				cache_mode;
+	bool				verify;
+	struct cache_stat_collector	stats;
+};
+
+struct bch_cgroup *bch_bio_to_cgroup(struct bio *bio);
+
+#endif /* _BCACHE_REQUEST_H_ */
diff --git a/drivers/md/bcache/stats.c b/drivers/md/bcache/stats.c
new file mode 100644
index 0000000..64e6794
--- /dev/null
+++ b/drivers/md/bcache/stats.c
@@ -0,0 +1,246 @@
+/*
+ * bcache stats code
+ *
+ * Copyright 2012 Google, Inc.
+ */
+
+#include "bcache.h"
+#include "stats.h"
+#include "btree.h"
+#include "request.h"
+#include "sysfs.h"
+
+/*
+ * We keep absolute totals of various statistics, and addionally a set of three
+ * rolling averages.
+ *
+ * Every so often, a timer goes off and rescales the rolling averages.
+ * accounting_rescale[] is how many times the timer has to go off before we
+ * rescale each set of numbers; that gets us half lives of 5 minutes, one hour,
+ * and one day.
+ *
+ * accounting_delay is how often the timer goes off - 22 times in 5 minutes,
+ * and accounting_weight is what we use to rescale:
+ *
+ * pow(31 / 32, 22) ~= 1/2
+ *
+ * So that we don't have to increment each set of numbers every time we (say)
+ * get a cache hit, we increment a single atomic_t in acc->collector, and when
+ * the rescale function runs it resets the atomic counter to 0 and adds its
+ * old value to each of the exported numbers.
+ *
+ * To reduce rounding error, the numbers in struct cache_stats are all
+ * stored left shifted by 16, and scaled back in the sysfs show() function.
+ */
+
+static const unsigned DAY_RESCALE		= 288;
+static const unsigned HOUR_RESCALE		= 12;
+static const unsigned FIVE_MINUTE_RESCALE	= 1;
+static const unsigned accounting_delay		= (HZ * 300) / 22;
+static const unsigned accounting_weight		= 32;
+
+/* sysfs reading/writing */
+
+read_attribute(cache_hits);
+read_attribute(cache_misses);
+read_attribute(cache_bypass_hits);
+read_attribute(cache_bypass_misses);
+read_attribute(cache_hit_ratio);
+read_attribute(cache_readaheads);
+read_attribute(cache_miss_collisions);
+read_attribute(bypassed);
+
+SHOW(bch_stats)
+{
+	struct cache_stats *s =
+		container_of(kobj, struct cache_stats, kobj);
+#define var(stat)		(s->stat >> 16)
+	var_print(cache_hits);
+	var_print(cache_misses);
+	var_print(cache_bypass_hits);
+	var_print(cache_bypass_misses);
+
+	sysfs_print(cache_hit_ratio,
+		    DIV_SAFE(var(cache_hits) * 100,
+			     var(cache_hits) + var(cache_misses)));
+
+	var_print(cache_readaheads);
+	var_print(cache_miss_collisions);
+	sysfs_hprint(bypassed,	var(sectors_bypassed) << 9);
+#undef var
+	return 0;
+}
+
+STORE(bch_stats)
+{
+	return size;
+}
+
+static void bch_stats_release(struct kobject *k)
+{
+}
+
+static struct attribute *bch_stats_files[] = {
+	&sysfs_cache_hits,
+	&sysfs_cache_misses,
+	&sysfs_cache_bypass_hits,
+	&sysfs_cache_bypass_misses,
+	&sysfs_cache_hit_ratio,
+	&sysfs_cache_readaheads,
+	&sysfs_cache_miss_collisions,
+	&sysfs_bypassed,
+	NULL
+};
+static KTYPE(bch_stats);
+
+static void scale_accounting(unsigned long data);
+
+void bch_cache_accounting_init(struct cache_accounting *acc,
+			       struct closure *parent)
+{
+	kobject_init(&acc->total.kobj,		&bch_stats_ktype);
+	kobject_init(&acc->five_minute.kobj,	&bch_stats_ktype);
+	kobject_init(&acc->hour.kobj,		&bch_stats_ktype);
+	kobject_init(&acc->day.kobj,		&bch_stats_ktype);
+
+	closure_init(&acc->cl, parent);
+	init_timer(&acc->timer);
+	acc->timer.expires	= jiffies + accounting_delay;
+	acc->timer.data		= (unsigned long) acc;
+	acc->timer.function	= scale_accounting;
+	add_timer(&acc->timer);
+}
+
+int bch_cache_accounting_add_kobjs(struct cache_accounting *acc,
+				   struct kobject *parent)
+{
+	int ret = kobject_add(&acc->total.kobj, parent,
+			      "stats_total");
+	ret = ret ?: kobject_add(&acc->five_minute.kobj, parent,
+				 "stats_five_minute");
+	ret = ret ?: kobject_add(&acc->hour.kobj, parent,
+				 "stats_hour");
+	ret = ret ?: kobject_add(&acc->day.kobj, parent,
+				 "stats_day");
+	return ret;
+}
+
+void bch_cache_accounting_clear(struct cache_accounting *acc)
+{
+	memset(&acc->total.cache_hits,
+	       0,
+	       sizeof(unsigned long) * 7);
+}
+
+void bch_cache_accounting_destroy(struct cache_accounting *acc)
+{
+	kobject_put(&acc->total.kobj);
+	kobject_put(&acc->five_minute.kobj);
+	kobject_put(&acc->hour.kobj);
+	kobject_put(&acc->day.kobj);
+
+	atomic_set(&acc->closing, 1);
+	if (del_timer_sync(&acc->timer))
+		closure_return(&acc->cl);
+}
+
+/* EWMA scaling */
+
+static void scale_stat(unsigned long *stat)
+{
+	*stat =  ewma_add(*stat, 0, accounting_weight, 0);
+}
+
+static void scale_stats(struct cache_stats *stats, unsigned long rescale_at)
+{
+	if (++stats->rescale == rescale_at) {
+		stats->rescale = 0;
+		scale_stat(&stats->cache_hits);
+		scale_stat(&stats->cache_misses);
+		scale_stat(&stats->cache_bypass_hits);
+		scale_stat(&stats->cache_bypass_misses);
+		scale_stat(&stats->cache_readaheads);
+		scale_stat(&stats->cache_miss_collisions);
+		scale_stat(&stats->sectors_bypassed);
+	}
+}
+
+static void scale_accounting(unsigned long data)
+{
+	struct cache_accounting *acc = (struct cache_accounting *) data;
+
+#define move_stat(name) do {						\
+	unsigned t = atomic_xchg(&acc->collector.name, 0);		\
+	t <<= 16;							\
+	acc->five_minute.name += t;					\
+	acc->hour.name += t;						\
+	acc->day.name += t;						\
+	acc->total.name += t;						\
+} while (0)
+
+	move_stat(cache_hits);
+	move_stat(cache_misses);
+	move_stat(cache_bypass_hits);
+	move_stat(cache_bypass_misses);
+	move_stat(cache_readaheads);
+	move_stat(cache_miss_collisions);
+	move_stat(sectors_bypassed);
+
+	scale_stats(&acc->total, 0);
+	scale_stats(&acc->day, DAY_RESCALE);
+	scale_stats(&acc->hour, HOUR_RESCALE);
+	scale_stats(&acc->five_minute, FIVE_MINUTE_RESCALE);
+
+	acc->timer.expires += accounting_delay;
+
+	if (!atomic_read(&acc->closing))
+		add_timer(&acc->timer);
+	else
+		closure_return(&acc->cl);
+}
+
+static void mark_cache_stats(struct cache_stat_collector *stats,
+			     bool hit, bool bypass)
+{
+	if (!bypass)
+		if (hit)
+			atomic_inc(&stats->cache_hits);
+		else
+			atomic_inc(&stats->cache_misses);
+	else
+		if (hit)
+			atomic_inc(&stats->cache_bypass_hits);
+		else
+			atomic_inc(&stats->cache_bypass_misses);
+}
+
+void bch_mark_cache_accounting(struct search *s, bool hit, bool bypass)
+{
+	struct cached_dev *dc = container_of(s->d, struct cached_dev, disk);
+	mark_cache_stats(&dc->accounting.collector, hit, bypass);
+	mark_cache_stats(&s->op.c->accounting.collector, hit, bypass);
+#ifdef CONFIG_CGROUP_BCACHE
+	mark_cache_stats(&(bch_bio_to_cgroup(s->orig_bio)->stats), hit, bypass);
+#endif
+}
+
+void bch_mark_cache_readahead(struct search *s)
+{
+	struct cached_dev *dc = container_of(s->d, struct cached_dev, disk);
+	atomic_inc(&dc->accounting.collector.cache_readaheads);
+	atomic_inc(&s->op.c->accounting.collector.cache_readaheads);
+}
+
+void bch_mark_cache_miss_collision(struct search *s)
+{
+	struct cached_dev *dc = container_of(s->d, struct cached_dev, disk);
+	atomic_inc(&dc->accounting.collector.cache_miss_collisions);
+	atomic_inc(&s->op.c->accounting.collector.cache_miss_collisions);
+}
+
+void bch_mark_sectors_bypassed(struct search *s, int sectors)
+{
+	struct cached_dev *dc = container_of(s->d, struct cached_dev, disk);
+	atomic_add(sectors, &dc->accounting.collector.sectors_bypassed);
+	atomic_add(sectors, &s->op.c->accounting.collector.sectors_bypassed);
+}
diff --git a/drivers/md/bcache/stats.h b/drivers/md/bcache/stats.h
new file mode 100644
index 0000000..c7c7a8f
--- /dev/null
+++ b/drivers/md/bcache/stats.h
@@ -0,0 +1,58 @@
+#ifndef _BCACHE_STATS_H_
+#define _BCACHE_STATS_H_
+
+struct cache_stat_collector {
+	atomic_t cache_hits;
+	atomic_t cache_misses;
+	atomic_t cache_bypass_hits;
+	atomic_t cache_bypass_misses;
+	atomic_t cache_readaheads;
+	atomic_t cache_miss_collisions;
+	atomic_t sectors_bypassed;
+};
+
+struct cache_stats {
+	struct kobject		kobj;
+
+	unsigned long cache_hits;
+	unsigned long cache_misses;
+	unsigned long cache_bypass_hits;
+	unsigned long cache_bypass_misses;
+	unsigned long cache_readaheads;
+	unsigned long cache_miss_collisions;
+	unsigned long sectors_bypassed;
+
+	unsigned		rescale;
+};
+
+struct cache_accounting {
+	struct closure		cl;
+	struct timer_list	timer;
+	atomic_t		closing;
+
+	struct cache_stat_collector collector;
+
+	struct cache_stats total;
+	struct cache_stats five_minute;
+	struct cache_stats hour;
+	struct cache_stats day;
+};
+
+struct search;
+
+void bch_cache_accounting_init(struct cache_accounting *acc,
+			       struct closure *parent);
+
+int bch_cache_accounting_add_kobjs(struct cache_accounting *acc,
+				   struct kobject *parent);
+
+void bch_cache_accounting_clear(struct cache_accounting *acc);
+
+void bch_cache_accounting_destroy(struct cache_accounting *acc);
+
+void bch_mark_cache_accounting(struct search *s, bool hit, bool bypass);
+void bch_mark_cache_readahead(struct search *s);
+void bch_mark_cache_miss_collision(struct search *s);
+void bch_mark_sectors_bypassed(struct search *s, int sectors);
+
+#endif /* _BCACHE_STATS_H_ */
diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c
new file mode 100644
index 0000000..792ee01
--- /dev/null
+++ b/drivers/md/bcache/super.c
@@ -0,0 +1,1946 @@
+/*
+ * bcache setup/teardown code, and some metadata io - read a superblock and
+ * figure out what to do with it.
+ *
+ * Copyright 2010, 2011 Kent Overstreet <kent.overstreet@gmail.com>
+ * Copyright 2012 Google, Inc.
+ */
+
+#include "bcache.h"
+#include "btree.h"
+#include "debug.h"
+#include "request.h"
+
+#include <linux/buffer_head.h>
+#include <linux/debugfs.h>
+#include <linux/genhd.h>
+#include <linux/module.h>
+#include <linux/random.h>
+#include <linux/reboot.h>
+#include <linux/sysfs.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Kent Overstreet <kent.overstreet@gmail.com>");
+
+static const char bcache_magic[] = {
+	0xc6, 0x85, 0x73, 0xf6, 0x4e, 0x1a, 0x45, 0xca,
+	0x82, 0x65, 0xf5, 0x7f, 0x48, 0xba, 0x6d, 0x81
+};
+
+static const char invalid_uuid[] = {
+	0xa0, 0x3e, 0xf8, 0xed, 0x3e, 0xe1, 0xb8, 0x78,
+	0xc8, 0x50, 0xfc, 0x5e, 0xcb, 0x16, 0xcd, 0x99
+};
+
+/* Default is -1; we skip past it for struct cached_dev's cache mode */
+const char * const bch_cache_modes[] = {
+	"default",
+	"writethrough",
+	"writeback",
+	"writearound",
+	"none",
+	NULL
+};
+
+struct uuid_entry_v0 {
+	uint8_t		uuid[16];
+	uint8_t		label[32];
+	uint32_t	first_reg;
+	uint32_t	last_reg;
+	uint32_t	invalidated;
+	uint32_t	pad;
+};
+
+static struct kobject *bcache_kobj;
+struct mutex bch_register_lock;
+LIST_HEAD(bch_cache_sets);
+static LIST_HEAD(uncached_devices);
+
+static int bcache_major, bcache_minor;
+static wait_queue_head_t unregister_wait;
+struct workqueue_struct *bcache_wq;
+
+#define BTREE_MAX_PAGES		(256 * 1024 / PAGE_SIZE)
+
+static void bio_split_pool_free(struct bio_split_pool *p)
+{
+	if (p->bio_split)
+		bioset_free(p->bio_split);
+
+}
+
+static int bio_split_pool_init(struct bio_split_pool *p)
+{
+	p->bio_split = bioset_create(4, 0);
+	if (!p->bio_split)
+		return -ENOMEM;
+
+	p->bio_split_hook = mempool_create_kmalloc_pool(4,
+				sizeof(struct bio_split_hook));
+	if (!p->bio_split_hook)
+		return -ENOMEM;
+
+	return 0;
+}
+
+/* Superblock */
+
+static const char *read_super(struct cache_sb *sb, struct block_device *bdev,
+			      struct page **res)
+{
+	const char *err;
+	struct cache_sb *s;
+	struct buffer_head *bh = __bread(bdev, 1, SB_SIZE);
+	unsigned i;
+
+	if (!bh)
+		return "IO error";
+
+	s = (struct cache_sb *) bh->b_data;
+
+	sb->offset		= le64_to_cpu(s->offset);
+	sb->version		= le64_to_cpu(s->version);
+
+	memcpy(sb->magic,	s->magic, 16);
+	memcpy(sb->uuid,	s->uuid, 16);
+	memcpy(sb->set_uuid,	s->set_uuid, 16);
+	memcpy(sb->label,	s->label, SB_LABEL_SIZE);
+
+	sb->flags		= le64_to_cpu(s->flags);
+	sb->seq			= le64_to_cpu(s->seq);
+
+	sb->nbuckets		= le64_to_cpu(s->nbuckets);
+	sb->block_size		= le16_to_cpu(s->block_size);
+	sb->bucket_size		= le16_to_cpu(s->bucket_size);
+
+	sb->nr_in_set		= le16_to_cpu(s->nr_in_set);
+	sb->nr_this_dev		= le16_to_cpu(s->nr_this_dev);
+	sb->last_mount		= le32_to_cpu(s->last_mount);
+
+	sb->first_bucket	= le16_to_cpu(s->first_bucket);
+	sb->keys		= le16_to_cpu(s->keys);
+
+	for (i = 0; i < SB_JOURNAL_BUCKETS; i++)
+		sb->d[i] = le64_to_cpu(s->d[i]);
+
+	pr_debug("read sb version %llu, flags %llu, seq %llu, journal size %u",
+		 sb->version, sb->flags, sb->seq, sb->keys);
+
+	err = "Not a bcache superblock";
+	if (sb->offset != SB_SECTOR)
+		goto err;
+
+	if (memcmp(sb->magic, bcache_magic, 16))
+		goto err;
+
+	err = "Too many journal buckets";
+	if (sb->keys > SB_JOURNAL_BUCKETS)
+		goto err;
+
+	err = "Bad checksum";
+	if (s->csum != csum_set(s))
+		goto err;
+
+	err = "Bad UUID";
+	if (bch_is_zero(sb->uuid, 16))
+		goto err;
+
+	err = "Unsupported superblock version";
+	if (sb->version > BCACHE_SB_VERSION)
+		goto err;
+
+	err = "Bad block/bucket size";
+	if (!is_power_of_2(sb->block_size) || sb->block_size > PAGE_SECTORS ||
+	    !is_power_of_2(sb->bucket_size) || sb->bucket_size < PAGE_SECTORS)
+		goto err;
+
+	err = "Too many buckets";
+	if (sb->nbuckets > LONG_MAX)
+		goto err;
+
+	err = "Not enough buckets";
+	if (sb->nbuckets < 1 << 7)
+		goto err;
+
+	err = "Invalid superblock: device too small";
+	if (get_capacity(bdev->bd_disk) < sb->bucket_size * sb->nbuckets)
+		goto err;
+
+	if (sb->version == CACHE_BACKING_DEV)
+		goto out;
+
+	err = "Bad UUID";
+	if (bch_is_zero(sb->set_uuid, 16))
+		goto err;
+
+	err = "Bad cache device number in set";
+	if (!sb->nr_in_set ||
+	    sb->nr_in_set <= sb->nr_this_dev ||
+	    sb->nr_in_set > MAX_CACHES_PER_SET)
+		goto err;
+
+	err = "Journal buckets not sequential";
+	for (i = 0; i < sb->keys; i++)
+		if (sb->d[i] != sb->first_bucket + i)
+			goto err;
+
+	err = "Too many journal buckets";
+	if (sb->first_bucket + sb->keys > sb->nbuckets)
+		goto err;
+
+	err = "Invalid superblock: first bucket comes before end of super";
+	if (sb->first_bucket * sb->bucket_size < 16)
+		goto err;
+out:
+	sb->last_mount = get_seconds();
+	err = NULL;
+
+	get_page(bh->b_page);
+	*res = bh->b_page;
+err:
+	put_bh(bh);
+	return err;
+}
+
+static void write_bdev_super_endio(struct bio *bio, int error,
+				   struct batch_complete *batch)
+{
+	struct cached_dev *dc = bio->bi_private;
+	/* XXX: error checking */
+
+	closure_put(&dc->sb_write.cl);
+}
+
+static void __write_super(struct cache_sb *sb, struct bio *bio)
+{
+	struct cache_sb *out = page_address(bio->bi_io_vec[0].bv_page);
+	unsigned i;
+
+	bio->bi_sector	= SB_SECTOR;
+	bio->bi_rw	= REQ_SYNC|REQ_META;
+	bio->bi_size	= SB_SIZE;
+	bch_bio_map(bio, NULL);
+
+	out->offset		= cpu_to_le64(sb->offset);
+	out->version		= cpu_to_le64(sb->version);
+
+	memcpy(out->uuid,	sb->uuid, 16);
+	memcpy(out->set_uuid,	sb->set_uuid, 16);
+	memcpy(out->label,	sb->label, SB_LABEL_SIZE);
+
+	out->flags		= cpu_to_le64(sb->flags);
+	out->seq		= cpu_to_le64(sb->seq);
+
+	out->last_mount		= cpu_to_le32(sb->last_mount);
+	out->first_bucket	= cpu_to_le16(sb->first_bucket);
+	out->keys		= cpu_to_le16(sb->keys);
+
+	for (i = 0; i < sb->keys; i++)
+		out->d[i] = cpu_to_le64(sb->d[i]);
+
+	out->csum = csum_set(out);
+
+	pr_debug("ver %llu, flags %llu, seq %llu",
+		 sb->version, sb->flags, sb->seq);
+
+	submit_bio(REQ_WRITE, bio);
+}
+
+void bch_write_bdev_super(struct cached_dev *dc, struct closure *parent)
+{
+	struct closure *cl = &dc->sb_write.cl;
+	struct bio *bio = &dc->sb_bio;
+
+	closure_lock(&dc->sb_write, parent);
+
+	bio_reset(bio);
+	bio->bi_bdev	= dc->bdev;
+	bio->bi_end_io	= write_bdev_super_endio;
+	bio->bi_private = dc;
+
+	closure_get(cl);
+	__write_super(&dc->sb, bio);
+
+	closure_return(cl);
+}
+
+static void write_super_endio(struct bio *bio, int error,
+			      struct batch_complete *batch)
+{
+	struct cache *ca = bio->bi_private;
+
+	bch_count_io_errors(ca, error, "writing superblock");
+	closure_put(&ca->set->sb_write.cl);
+}
+
+void bcache_write_super(struct cache_set *c)
+{
+	struct closure *cl = &c->sb_write.cl;
+	struct cache *ca;
+	unsigned i;
+
+	closure_lock(&c->sb_write, &c->cl);
+
+	c->sb.seq++;
+
+	for_each_cache(ca, c, i) {
+		struct bio *bio = &ca->sb_bio;
+
+		ca->sb.version		= BCACHE_SB_VERSION;
+		ca->sb.seq		= c->sb.seq;
+		ca->sb.last_mount	= c->sb.last_mount;
+
+		SET_CACHE_SYNC(&ca->sb, CACHE_SYNC(&c->sb));
+
+		bio_reset(bio);
+		bio->bi_bdev	= ca->bdev;
+		bio->bi_end_io	= write_super_endio;
+		bio->bi_private = ca;
+
+		closure_get(cl);
+		__write_super(&ca->sb, bio);
+	}
+
+	closure_return(cl);
+}
+
+/* UUID io */
+
+static void uuid_endio(struct bio *bio, int error, struct batch_complete *batch)
+{
+	struct closure *cl = bio->bi_private;
+	struct cache_set *c = container_of(cl, struct cache_set, uuid_write.cl);
+
+	cache_set_err_on(error, c, "accessing uuids");
+	bch_bbio_free(bio, c);
+	closure_put(cl);
+}
+
+static void uuid_io(struct cache_set *c, unsigned long rw,
+		    struct bkey *k, struct closure *parent)
+{
+	struct closure *cl = &c->uuid_write.cl;
+	struct uuid_entry *u;
+	unsigned i;
+
+	BUG_ON(!parent);
+	closure_lock(&c->uuid_write, parent);
+
+	for (i = 0; i < KEY_PTRS(k); i++) {
+		struct bio *bio = bch_bbio_alloc(c);
+
+		bio->bi_rw	= REQ_SYNC|REQ_META|rw;
+		bio->bi_size	= KEY_SIZE(k) << 9;
+
+		bio->bi_end_io	= uuid_endio;
+		bio->bi_private = cl;
+		bch_bio_map(bio, c->uuids);
+
+		bch_submit_bbio(bio, c, k, i);
+
+		if (!(rw & WRITE))
+			break;
+	}
+
+	pr_debug("%s UUIDs at %s", rw & REQ_WRITE ? "wrote" : "read",
+		 pkey(&c->uuid_bucket));
+
+	for (u = c->uuids; u < c->uuids + c->nr_uuids; u++)
+		if (!bch_is_zero(u->uuid, 16))
+			pr_debug("Slot %zi: %pU: %s: 1st: %u last: %u inv: %u",
+				 u - c->uuids, u->uuid, u->label,
+				 u->first_reg, u->last_reg, u->invalidated);
+
+	closure_return(cl);
+}
+
+static char *uuid_read(struct cache_set *c, struct jset *j, struct closure *cl)
+{
+	struct bkey *k = &j->uuid_bucket;
+
+	if (__bch_ptr_invalid(c, 1, k))
+		return "bad uuid pointer";
+
+	bkey_copy(&c->uuid_bucket, k);
+	uuid_io(c, READ_SYNC, k, cl);
+
+	if (j->version < BCACHE_JSET_VERSION_UUIDv1) {
+		struct uuid_entry_v0	*u0 = (void *) c->uuids;
+		struct uuid_entry	*u1 = (void *) c->uuids;
+		int i;
+
+		closure_sync(cl);
+
+		/*
+		 * Since the new uuid entry is bigger than the old, we have to
+		 * convert starting at the highest memory address and work down
+		 * in order to do it in place
+		 */
+
+		for (i = c->nr_uuids - 1;
+		     i >= 0;
+		     --i) {
+			memcpy(u1[i].uuid,	u0[i].uuid, 16);
+			memcpy(u1[i].label,	u0[i].label, 32);
+
+			u1[i].first_reg		= u0[i].first_reg;
+			u1[i].last_reg		= u0[i].last_reg;
+			u1[i].invalidated	= u0[i].invalidated;
+
+			u1[i].flags	= 0;
+			u1[i].sectors	= 0;
+		}
+	}
+
+	return NULL;
+}
+
+static int __uuid_write(struct cache_set *c)
+{
+	BKEY_PADDED(key) k;
+	struct closure cl;
+	closure_init_stack(&cl);
+
+	lockdep_assert_held(&bch_register_lock);
+
+	if (bch_bucket_alloc_set(c, WATERMARK_METADATA, &k.key, 1, &cl))
+		return 1;
+
+	SET_KEY_SIZE(&k.key, c->sb.bucket_size);
+	uuid_io(c, REQ_WRITE, &k.key, &cl);
+	closure_sync(&cl);
+
+	bkey_copy(&c->uuid_bucket, &k.key);
+	__bkey_put(c, &k.key);
+	return 0;
+}
+
+int bch_uuid_write(struct cache_set *c)
+{
+	int ret = __uuid_write(c);
+
+	if (!ret)
+		bch_journal_meta(c, NULL);
+
+	return ret;
+}
+
+static struct uuid_entry *uuid_find(struct cache_set *c, const char *uuid)
+{
+	struct uuid_entry *u;
+
+	for (u = c->uuids;
+	     u < c->uuids + c->nr_uuids; u++)
+		if (!memcmp(u->uuid, uuid, 16))
+			return u;
+
+	return NULL;
+}
+
+static struct uuid_entry *uuid_find_empty(struct cache_set *c)
+{
+	static const char zero_uuid[16] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
+	return uuid_find(c, zero_uuid);
+}
+
+/*
+ * Bucket priorities/gens:
+ *
+ * For each bucket, we store on disk its
+   * 8 bit gen
+   * 16 bit priority
+ *
+ * See alloc.c for an explanation of the gen. The priority is used to implement
+ * lru (and in the future other) cache replacement policies; for most purposes
+ * it's just an opaque integer.
+ *
+ * The gens and the priorities don't have a whole lot to do with each other, and
+ * it's actually the gens that must be written out at specific times - it's no
+ * big deal if the priorities don't get written, if we lose them we just reuse
+ * buckets in suboptimal order.
+ *
+ * On disk they're stored in a packed array, and in as many buckets are required
+ * to fit them all. The buckets we use to store them form a list; the journal
+ * header points to the first bucket, the first bucket points to the second
+ * bucket, et cetera.
+ *
+ * This code is used by the allocation code; periodically (whenever it runs out
+ * of buckets to allocate from) the allocation code will invalidate some
+ * buckets, but it can't use those buckets until their new gens are safely on
+ * disk.
+ */
+
+static void prio_endio(struct bio *bio, int error,
+		       struct batch_complete *batch)
+{
+	struct cache *ca = bio->bi_private;
+
+	cache_set_err_on(error, ca->set, "accessing priorities");
+	bch_bbio_free(bio, ca->set);
+	closure_put(&ca->prio);
+}
+
+static void prio_io(struct cache *ca, uint64_t bucket, unsigned long rw)
+{
+	struct closure *cl = &ca->prio;
+	struct bio *bio = bch_bbio_alloc(ca->set);
+
+	closure_init_stack(cl);
+
+	bio->bi_sector	= bucket * ca->sb.bucket_size;
+	bio->bi_bdev	= ca->bdev;
+	bio->bi_rw	= REQ_SYNC|REQ_META|rw;
+	bio->bi_size	= bucket_bytes(ca);
+
+	bio->bi_end_io	= prio_endio;
+	bio->bi_private = ca;
+	bch_bio_map(bio, ca->disk_buckets);
+
+	closure_bio_submit(bio, &ca->prio, ca);
+	closure_sync(cl);
+}
+
+#define buckets_free(c)	"free %zu, free_inc %zu, unused %zu",		\
+	fifo_used(&c->free), fifo_used(&c->free_inc), fifo_used(&c->unused)
+
+void bch_prio_write(struct cache *ca)
+{
+	int i;
+	struct bucket *b;
+	struct closure cl;
+
+	closure_init_stack(&cl);
+
+	lockdep_assert_held(&ca->set->bucket_lock);
+
+	for (b = ca->buckets;
+	     b < ca->buckets + ca->sb.nbuckets; b++)
+		b->disk_gen = b->gen;
+
+	ca->disk_buckets->seq++;
+
+	atomic_long_add(ca->sb.bucket_size * prio_buckets(ca),
+			&ca->meta_sectors_written);
+
+	pr_debug("free %zu, free_inc %zu, unused %zu", fifo_used(&ca->free),
+		 fifo_used(&ca->free_inc), fifo_used(&ca->unused));
+	blktrace_msg(ca, "Starting priorities: " buckets_free(ca));
+
+	for (i = prio_buckets(ca) - 1; i >= 0; --i) {
+		long bucket;
+		struct prio_set *p = ca->disk_buckets;
+		struct bucket_disk *d = p->data;
+		struct bucket_disk *end = d + prios_per_bucket(ca);
+
+		for (b = ca->buckets + i * prios_per_bucket(ca);
+		     b < ca->buckets + ca->sb.nbuckets && d < end;
+		     b++, d++) {
+			d->prio = cpu_to_le16(b->prio);
+			d->gen = b->gen;
+		}
+
+		p->next_bucket	= ca->prio_buckets[i + 1];
+		p->magic	= pset_magic(ca);
+		p->csum		= bch_crc64(&p->magic, bucket_bytes(ca) - 8);
+
+		bucket = bch_bucket_alloc(ca, WATERMARK_PRIO, &cl);
+		BUG_ON(bucket == -1);
+
+		mutex_unlock(&ca->set->bucket_lock);
+		prio_io(ca, bucket, REQ_WRITE);
+		mutex_lock(&ca->set->bucket_lock);
+
+		ca->prio_buckets[i] = bucket;
+		atomic_dec_bug(&ca->buckets[bucket].pin);
+	}
+
+	mutex_unlock(&ca->set->bucket_lock);
+
+	bch_journal_meta(ca->set, &cl);
+	closure_sync(&cl);
+
+	mutex_lock(&ca->set->bucket_lock);
+
+	ca->need_save_prio = 0;
+
+	/*
+	 * Don't want the old priorities to get garbage collected until after we
+	 * finish writing the new ones, and they're journalled
+	 */
+	for (i = 0; i < prio_buckets(ca); i++)
+		ca->prio_last_buckets[i] = ca->prio_buckets[i];
+}
+
+static void prio_read(struct cache *ca, uint64_t bucket)
+{
+	struct prio_set *p = ca->disk_buckets;
+	struct bucket_disk *d = p->data + prios_per_bucket(ca), *end = d;
+	struct bucket *b;
+	unsigned bucket_nr = 0;
+
+	for (b = ca->buckets;
+	     b < ca->buckets + ca->sb.nbuckets;
+	     b++, d++) {
+		if (d == end) {
+			ca->prio_buckets[bucket_nr] = bucket;
+			ca->prio_last_buckets[bucket_nr] = bucket;
+			bucket_nr++;
+
+			prio_io(ca, bucket, READ_SYNC);
+
+			if (p->csum != bch_crc64(&p->magic, bucket_bytes(ca) - 8))
+				pr_warn("bad csum reading priorities");
+
+			if (p->magic != pset_magic(ca))
+				pr_warn("bad magic reading priorities");
+
+			bucket = p->next_bucket;
+			d = p->data;
+		}
+
+		b->prio = le16_to_cpu(d->prio);
+		b->gen = b->disk_gen = b->last_gc = b->gc_gen = d->gen;
+	}
+}
+
+/* Bcache device */
+
+static int open_dev(struct block_device *b, fmode_t mode)
+{
+	struct bcache_device *d = b->bd_disk->private_data;
+	if (atomic_read(&d->closing))
+		return -ENXIO;
+
+	closure_get(&d->cl);
+	return 0;
+}
+
+static int release_dev(struct gendisk *b, fmode_t mode)
+{
+	struct bcache_device *d = b->private_data;
+	closure_put(&d->cl);
+	return 0;
+}
+
+static int ioctl_dev(struct block_device *b, fmode_t mode,
+		     unsigned int cmd, unsigned long arg)
+{
+	struct bcache_device *d = b->bd_disk->private_data;
+	return d->ioctl(d, mode, cmd, arg);
+}
+
+static const struct block_device_operations bcache_ops = {
+	.open		= open_dev,
+	.release	= release_dev,
+	.ioctl		= ioctl_dev,
+	.owner		= THIS_MODULE,
+};
+
+void bcache_device_stop(struct bcache_device *d)
+{
+	if (!atomic_xchg(&d->closing, 1))
+		closure_queue(&d->cl);
+}
+
+static void bcache_device_detach(struct bcache_device *d)
+{
+	lockdep_assert_held(&bch_register_lock);
+
+	if (atomic_read(&d->detaching)) {
+		struct uuid_entry *u = d->c->uuids + d->id;
+
+		SET_UUID_FLASH_ONLY(u, 0);
+		memcpy(u->uuid, invalid_uuid, 16);
+		u->invalidated = cpu_to_le32(get_seconds());
+		bch_uuid_write(d->c);
+
+		atomic_set(&d->detaching, 0);
+	}
+
+	d->c->devices[d->id] = NULL;
+	closure_put(&d->c->caching);
+	d->c = NULL;
+}
+
+static void bcache_device_attach(struct bcache_device *d, struct cache_set *c,
+				 unsigned id)
+{
+	BUG_ON(test_bit(CACHE_SET_STOPPING, &c->flags));
+
+	d->id = id;
+	d->c = c;
+	c->devices[id] = d;
+
+	closure_get(&c->caching);
+}
+
+static void bcache_device_link(struct bcache_device *d, struct cache_set *c,
+			       const char *name)
+{
+	snprintf(d->name, BCACHEDEVNAME_SIZE,
+		 "%s%u", name, d->id);
+
+	WARN(sysfs_create_link(&d->kobj, &c->kobj, "cache") ||
+	     sysfs_create_link(&c->kobj, &d->kobj, d->name),
+	     "Couldn't create device <-> cache set symlinks");
+}
+
+static void bcache_device_free(struct bcache_device *d)
+{
+	lockdep_assert_held(&bch_register_lock);
+
+	pr_info("%s stopped", d->disk->disk_name);
+
+	if (d->c)
+		bcache_device_detach(d);
+
+	if (d->disk)
+		del_gendisk(d->disk);
+	if (d->disk && d->disk->queue)
+		blk_cleanup_queue(d->disk->queue);
+	if (d->disk)
+		put_disk(d->disk);
+
+	bio_split_pool_free(&d->bio_split_hook);
+	if (d->unaligned_bvec)
+		mempool_destroy(d->unaligned_bvec);
+	if (d->bio_split)
+		bioset_free(d->bio_split);
+
+	closure_debug_destroy(&d->cl);
+}
+
+static int bcache_device_init(struct bcache_device *d, unsigned block_size)
+{
+	struct request_queue *q;
+
+	if (!(d->bio_split = bioset_create(4, offsetof(struct bbio, bio))) ||
+	    !(d->unaligned_bvec = mempool_create_kmalloc_pool(1,
+				sizeof(struct bio_vec) * BIO_MAX_PAGES)) ||
+	    bio_split_pool_init(&d->bio_split_hook))
+
+		return -ENOMEM;
+
+	d->disk = alloc_disk(1);
+	if (!d->disk)
+		return -ENOMEM;
+
+	snprintf(d->disk->disk_name, DISK_NAME_LEN, "bcache%i", bcache_minor);
+
+	d->disk->major		= bcache_major;
+	d->disk->first_minor	= bcache_minor++;
+	d->disk->fops		= &bcache_ops;
+	d->disk->private_data	= d;
+
+	q = blk_alloc_queue(GFP_KERNEL);
+	if (!q)
+		return -ENOMEM;
+
+	blk_queue_make_request(q, NULL);
+	d->disk->queue			= q;
+	q->queuedata			= d;
+	q->backing_dev_info.congested_data = d;
+	q->limits.max_hw_sectors	= UINT_MAX;
+	q->limits.max_sectors		= UINT_MAX;
+	q->limits.max_segment_size	= UINT_MAX;
+	q->limits.max_segments		= BIO_MAX_PAGES;
+	q->limits.max_discard_sectors	= UINT_MAX;
+	q->limits.io_min		= block_size;
+	q->limits.logical_block_size	= block_size;
+	q->limits.physical_block_size	= block_size;
+	set_bit(QUEUE_FLAG_NONROT,	&d->disk->queue->queue_flags);
+	set_bit(QUEUE_FLAG_DISCARD,	&d->disk->queue->queue_flags);
+
+	return 0;
+}
+
+/* Cached device */
+
+static void calc_cached_dev_sectors(struct cache_set *c)
+{
+	uint64_t sectors = 0;
+	struct cached_dev *dc;
+
+	list_for_each_entry(dc, &c->cached_devs, list)
+		sectors += bdev_sectors(dc->bdev);
+
+	c->cached_dev_sectors = sectors;
+}
+
+void bch_cached_dev_run(struct cached_dev *dc)
+{
+	struct bcache_device *d = &dc->disk;
+
+	if (atomic_xchg(&dc->running, 1))
+		return;
+
+	if (!d->c &&
+	    BDEV_STATE(&dc->sb) != BDEV_STATE_NONE) {
+		struct closure cl;
+		closure_init_stack(&cl);
+
+		SET_BDEV_STATE(&dc->sb, BDEV_STATE_STALE);
+		bch_write_bdev_super(dc, &cl);
+		closure_sync(&cl);
+	}
+
+	add_disk(d->disk);
+#if 0
+	char *env[] = { "SYMLINK=label" , NULL };
+	kobject_uevent_env(&disk_to_dev(d->disk)->kobj, KOBJ_CHANGE, env);
+#endif
+	if (sysfs_create_link(&d->kobj, &disk_to_dev(d->disk)->kobj, "dev") ||
+	    sysfs_create_link(&disk_to_dev(d->disk)->kobj, &d->kobj, "bcache"))
+		pr_debug("error creating sysfs link");
+}
+
+static void cached_dev_detach_finish(struct work_struct *w)
+{
+	struct cached_dev *dc = container_of(w, struct cached_dev, detach);
+	char buf[BDEVNAME_SIZE];
+	struct closure cl;
+	closure_init_stack(&cl);
+
+	BUG_ON(!atomic_read(&dc->disk.detaching));
+	BUG_ON(atomic_read(&dc->count));
+
+	sysfs_remove_link(&dc->disk.c->kobj, dc->disk.name);
+	sysfs_remove_link(&dc->disk.kobj, "cache");
+
+	mutex_lock(&bch_register_lock);
+
+	memset(&dc->sb.set_uuid, 0, 16);
+	SET_BDEV_STATE(&dc->sb, BDEV_STATE_NONE);
+
+	bch_write_bdev_super(dc, &cl);
+	closure_sync(&cl);
+
+	bcache_device_detach(&dc->disk);
+	list_move(&dc->list, &uncached_devices);
+
+	mutex_unlock(&bch_register_lock);
+
+	pr_info("Caching disabled for %s", bdevname(dc->bdev, buf));
+
+	/* Drop ref we took in cached_dev_detach() */
+	closure_put(&dc->disk.cl);
+}
+
+void bch_cached_dev_detach(struct cached_dev *dc)
+{
+	lockdep_assert_held(&bch_register_lock);
+
+	if (atomic_read(&dc->disk.closing))
+		return;
+
+	if (atomic_xchg(&dc->disk.detaching, 1))
+		return;
+
+	/*
+	 * Block the device from being closed and freed until we're finished
+	 * detaching
+	 */
+	closure_get(&dc->disk.cl);
+
+	bch_writeback_queue(dc);
+	cached_dev_put(dc);
+}
+
+int bch_cached_dev_attach(struct cached_dev *dc, struct cache_set *c)
+{
+	uint32_t rtime = cpu_to_le32(get_seconds());
+	struct uuid_entry *u;
+	char buf[BDEVNAME_SIZE];
+
+	bdevname(dc->bdev, buf);
+
+	if (memcmp(dc->sb.set_uuid, c->sb.set_uuid, 16))
+		return -ENOENT;
+
+	if (dc->disk.c) {
+		pr_err("Can't attach %s: already attached", buf);
+		return -EINVAL;
+	}
+
+	if (test_bit(CACHE_SET_STOPPING, &c->flags)) {
+		pr_err("Can't attach %s: shutting down", buf);
+		return -EINVAL;
+	}
+
+	if (dc->sb.block_size < c->sb.block_size) {
+		/* Will die */
+		pr_err("Couldn't attach %s: block size less than set's block size",
+		       buf);
+		return -EINVAL;
+	}
+
+	u = uuid_find(c, dc->sb.uuid);
+
+	if (u &&
+	    (BDEV_STATE(&dc->sb) == BDEV_STATE_STALE ||
+	     BDEV_STATE(&dc->sb) == BDEV_STATE_NONE)) {
+		memcpy(u->uuid, invalid_uuid, 16);
+		u->invalidated = cpu_to_le32(get_seconds());
+		u = NULL;
+	}
+
+	if (!u) {
+		if (BDEV_STATE(&dc->sb) == BDEV_STATE_DIRTY) {
+			pr_err("Couldn't find uuid for %s in set", buf);
+			return -ENOENT;
+		}
+
+		u = uuid_find_empty(c);
+		if (!u) {
+			pr_err("Not caching %s, no room for UUID", buf);
+			return -EINVAL;
+		}
+	}
+
+	/* Deadlocks since we're called via sysfs...
+	sysfs_remove_file(&dc->kobj, &sysfs_attach);
+	 */
+
+	if (bch_is_zero(u->uuid, 16)) {
+		struct closure cl;
+		closure_init_stack(&cl);
+
+		memcpy(u->uuid, dc->sb.uuid, 16);
+		memcpy(u->label, dc->sb.label, SB_LABEL_SIZE);
+		u->first_reg = u->last_reg = rtime;
+		bch_uuid_write(c);
+
+		memcpy(dc->sb.set_uuid, c->sb.set_uuid, 16);
+		SET_BDEV_STATE(&dc->sb, BDEV_STATE_CLEAN);
+
+		bch_write_bdev_super(dc, &cl);
+		closure_sync(&cl);
+	} else {
+		u->last_reg = rtime;
+		bch_uuid_write(c);
+	}
+
+	bcache_device_attach(&dc->disk, c, u - c->uuids);
+	bcache_device_link(&dc->disk, c, "bdev");
+	list_move(&dc->list, &c->cached_devs);
+	calc_cached_dev_sectors(c);
+
+	smp_wmb();
+	/*
+	 * dc->c must be set before dc->count != 0 - paired with the mb in
+	 * cached_dev_get()
+	 */
+	atomic_set(&dc->count, 1);
+
+	if (BDEV_STATE(&dc->sb) == BDEV_STATE_DIRTY) {
+		atomic_set(&dc->has_dirty, 1);
+		atomic_inc(&dc->count);
+		bch_writeback_queue(dc);
+	}
+
+	bch_cached_dev_run(dc);
+
+	pr_info("Caching %s as %s on set %pU",
+		bdevname(dc->bdev, buf), dc->disk.disk->disk_name,
+		dc->disk.c->sb.set_uuid);
+	return 0;
+}
+
+void bch_cached_dev_release(struct kobject *kobj)
+{
+	struct cached_dev *dc = container_of(kobj, struct cached_dev,
+					     disk.kobj);
+	kfree(dc);
+	module_put(THIS_MODULE);
+}
+
+static void cached_dev_free(struct closure *cl)
+{
+	struct cached_dev *dc = container_of(cl, struct cached_dev, disk.cl);
+
+	cancel_delayed_work_sync(&dc->writeback_rate_update);
+
+	mutex_lock(&bch_register_lock);
+
+	bcache_device_free(&dc->disk);
+	list_del(&dc->list);
+
+	mutex_unlock(&bch_register_lock);
+
+	if (!IS_ERR_OR_NULL(dc->bdev)) {
+		blk_sync_queue(bdev_get_queue(dc->bdev));
+		blkdev_put(dc->bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
+	}
+
+	wake_up(&unregister_wait);
+
+	kobject_put(&dc->disk.kobj);
+}
+
+static void cached_dev_flush(struct closure *cl)
+{
+	struct cached_dev *dc = container_of(cl, struct cached_dev, disk.cl);
+	struct bcache_device *d = &dc->disk;
+
+	bch_cache_accounting_destroy(&dc->accounting);
+	kobject_del(&d->kobj);
+
+	continue_at(cl, cached_dev_free, system_wq);
+}
+
+static int cached_dev_init(struct cached_dev *dc, unsigned block_size)
+{
+	int err;
+	struct io *io;
+
+	closure_init(&dc->disk.cl, NULL);
+	set_closure_fn(&dc->disk.cl, cached_dev_flush, system_wq);
+
+	__module_get(THIS_MODULE);
+	INIT_LIST_HEAD(&dc->list);
+	kobject_init(&dc->disk.kobj, &bch_cached_dev_ktype);
+
+	bch_cache_accounting_init(&dc->accounting, &dc->disk.cl);
+
+	err = bcache_device_init(&dc->disk, block_size);
+	if (err)
+		goto err;
+
+	spin_lock_init(&dc->io_lock);
+	closure_init_unlocked(&dc->sb_write);
+	INIT_WORK(&dc->detach, cached_dev_detach_finish);
+
+	dc->sequential_merge		= true;
+	dc->sequential_cutoff		= 4 << 20;
+
+	INIT_LIST_HEAD(&dc->io_lru);
+	dc->sb_bio.bi_max_vecs	= 1;
+	dc->sb_bio.bi_io_vec	= dc->sb_bio.bi_inline_vecs;
+
+	for (io = dc->io; io < dc->io + RECENT_IO; io++) {
+		list_add(&io->lru, &dc->io_lru);
+		hlist_add_head(&io->hash, dc->io_hash + RECENT_IO);
+	}
+
+	bch_writeback_init_cached_dev(dc);
+	return 0;
+err:
+	bcache_device_stop(&dc->disk);
+	return err;
+}
+
+/* Cached device - bcache superblock */
+
+static const char *register_bdev(struct cache_sb *sb, struct page *sb_page,
+				 struct block_device *bdev,
+				 struct cached_dev *dc)
+{
+	char name[BDEVNAME_SIZE];
+	const char *err = "cannot allocate memory";
+	struct gendisk *g;
+	struct cache_set *c;
+
+	if (!dc || cached_dev_init(dc, sb->block_size << 9) != 0)
+		return err;
+
+	memcpy(&dc->sb, sb, sizeof(struct cache_sb));
+	dc->sb_bio.bi_io_vec[0].bv_page = sb_page;
+	dc->bdev = bdev;
+	dc->bdev->bd_holder = dc;
+
+	g = dc->disk.disk;
+
+	set_capacity(g, dc->bdev->bd_part->nr_sects - 16);
+
+	bch_cached_dev_request_init(dc);
+
+	err = "error creating kobject";
+	if (kobject_add(&dc->disk.kobj, &part_to_dev(bdev->bd_part)->kobj,
+			"bcache"))
+		goto err;
+	if (bch_cache_accounting_add_kobjs(&dc->accounting, &dc->disk.kobj))
+		goto err;
+
+	list_add(&dc->list, &uncached_devices);
+	list_for_each_entry(c, &bch_cache_sets, list)
+		bch_cached_dev_attach(dc, c);
+
+	if (BDEV_STATE(&dc->sb) == BDEV_STATE_NONE ||
+	    BDEV_STATE(&dc->sb) == BDEV_STATE_STALE)
+		bch_cached_dev_run(dc);
+
+	return NULL;
+err:
+	kobject_put(&dc->disk.kobj);
+	pr_notice("error opening %s: %s", bdevname(bdev, name), err);
+	/*
+	 * Return NULL instead of an error because kobject_put() cleans
+	 * everything up
+	 */
+	return NULL;
+}
+
+/* Flash only volumes */
+
+void bch_flash_dev_release(struct kobject *kobj)
+{
+	struct bcache_device *d = container_of(kobj, struct bcache_device,
+					       kobj);
+	kfree(d);
+}
+
+static void flash_dev_free(struct closure *cl)
+{
+	struct bcache_device *d = container_of(cl, struct bcache_device, cl);
+	bcache_device_free(d);
+	kobject_put(&d->kobj);
+}
+
+static void flash_dev_flush(struct closure *cl)
+{
+	struct bcache_device *d = container_of(cl, struct bcache_device, cl);
+
+	sysfs_remove_link(&d->c->kobj, d->name);
+	sysfs_remove_link(&d->kobj, "cache");
+	kobject_del(&d->kobj);
+	continue_at(cl, flash_dev_free, system_wq);
+}
+
+static int flash_dev_run(struct cache_set *c, struct uuid_entry *u)
+{
+	struct bcache_device *d = kzalloc(sizeof(struct bcache_device),
+					  GFP_KERNEL);
+	if (!d)
+		return -ENOMEM;
+
+	closure_init(&d->cl, NULL);
+	set_closure_fn(&d->cl, flash_dev_flush, system_wq);
+
+	kobject_init(&d->kobj, &bch_flash_dev_ktype);
+
+	if (bcache_device_init(d, block_bytes(c)))
+		goto err;
+
+	bcache_device_attach(d, c, u - c->uuids);
+	set_capacity(d->disk, u->sectors);
+	bch_flash_dev_request_init(d);
+	add_disk(d->disk);
+
+	if (kobject_add(&d->kobj, &disk_to_dev(d->disk)->kobj, "bcache"))
+		goto err;
+
+	bcache_device_link(d, c, "volume");
+
+	return 0;
+err:
+	kobject_put(&d->kobj);
+	return -ENOMEM;
+}
+
+static int flash_devs_run(struct cache_set *c)
+{
+	int ret = 0;
+	struct uuid_entry *u;
+
+	for (u = c->uuids;
+	     u < c->uuids + c->nr_uuids && !ret;
+	     u++)
+		if (UUID_FLASH_ONLY(u))
+			ret = flash_dev_run(c, u);
+
+	return ret;
+}
+
+int bch_flash_dev_create(struct cache_set *c, uint64_t size)
+{
+	struct uuid_entry *u;
+
+	if (test_bit(CACHE_SET_STOPPING, &c->flags))
+		return -EINTR;
+
+	u = uuid_find_empty(c);
+	if (!u) {
+		pr_err("Can't create volume, no room for UUID");
+		return -EINVAL;
+	}
+
+	get_random_bytes(u->uuid, 16);
+	memset(u->label, 0, 32);
+	u->first_reg = u->last_reg = cpu_to_le32(get_seconds());
+
+	SET_UUID_FLASH_ONLY(u, 1);
+	u->sectors = size >> 9;
+
+	bch_uuid_write(c);
+
+	return flash_dev_run(c, u);
+}
+
+/* Cache set */
+
+__printf(2, 3)
+bool bch_cache_set_error(struct cache_set *c, const char *fmt, ...)
+{
+	va_list args;
+
+	if (test_bit(CACHE_SET_STOPPING, &c->flags))
+		return false;
+
+	/* XXX: we can be called from atomic context
+	acquire_console_sem();
+	*/
+
+	printk(KERN_ERR "bcache: error on %pU: ", c->sb.set_uuid);
+
+	va_start(args, fmt);
+	vprintk(fmt, args);
+	va_end(args);
+
+	printk(", disabling caching\n");
+
+	bch_cache_set_unregister(c);
+	return true;
+}
+
+void bch_cache_set_release(struct kobject *kobj)
+{
+	struct cache_set *c = container_of(kobj, struct cache_set, kobj);
+	kfree(c);
+	module_put(THIS_MODULE);
+}
+
+static void cache_set_free(struct closure *cl)
+{
+	struct cache_set *c = container_of(cl, struct cache_set, cl);
+	struct cache *ca;
+	unsigned i;
+
+	if (!IS_ERR_OR_NULL(c->debug))
+		debugfs_remove(c->debug);
+
+	bch_open_buckets_free(c);
+	bch_btree_cache_free(c);
+	bch_journal_free(c);
+
+	for_each_cache(ca, c, i)
+		if (ca)
+			kobject_put(&ca->kobj);
+
+	free_pages((unsigned long) c->uuids, ilog2(bucket_pages(c)));
+	free_pages((unsigned long) c->sort, ilog2(bucket_pages(c)));
+
+	kfree(c->fill_iter);
+	if (c->bio_split)
+		bioset_free(c->bio_split);
+	if (c->bio_meta)
+		mempool_destroy(c->bio_meta);
+	if (c->search)
+		mempool_destroy(c->search);
+	kfree(c->devices);
+
+	mutex_lock(&bch_register_lock);
+	list_del(&c->list);
+	mutex_unlock(&bch_register_lock);
+
+	pr_info("Cache set %pU unregistered", c->sb.set_uuid);
+	wake_up(&unregister_wait);
+
+	closure_debug_destroy(&c->cl);
+	kobject_put(&c->kobj);
+}
+
+static void cache_set_flush(struct closure *cl)
+{
+	struct cache_set *c = container_of(cl, struct cache_set, caching);
+	struct btree *b;
+
+	/* Shut down allocator threads */
+	set_bit(CACHE_SET_STOPPING_2, &c->flags);
+	wake_up(&c->alloc_wait);
+
+	bch_cache_accounting_destroy(&c->accounting);
+
+	kobject_put(&c->internal);
+	kobject_del(&c->kobj);
+
+	if (!IS_ERR_OR_NULL(c->root))
+		list_add(&c->root->list, &c->btree_cache);
+
+	/* Should skip this if we're unregistering because of an error */
+	list_for_each_entry(b, &c->btree_cache, list)
+		if (btree_node_dirty(b))
+			bch_btree_write(b, true, NULL);
+
+	closure_return(cl);
+}
+
+static void __cache_set_unregister(struct closure *cl)
+{
+	struct cache_set *c = container_of(cl, struct cache_set, caching);
+	struct cached_dev *dc, *t;
+	size_t i;
+
+	mutex_lock(&bch_register_lock);
+
+	if (test_bit(CACHE_SET_UNREGISTERING, &c->flags))
+		list_for_each_entry_safe(dc, t, &c->cached_devs, list)
+			bch_cached_dev_detach(dc);
+
+	for (i = 0; i < c->nr_uuids; i++)
+		if (c->devices[i] && UUID_FLASH_ONLY(&c->uuids[i]))
+			bcache_device_stop(c->devices[i]);
+
+	mutex_unlock(&bch_register_lock);
+
+	continue_at(cl, cache_set_flush, system_wq);
+}
+
+void bch_cache_set_stop(struct cache_set *c)
+{
+	if (!test_and_set_bit(CACHE_SET_STOPPING, &c->flags))
+		closure_queue(&c->caching);
+}
+
+void bch_cache_set_unregister(struct cache_set *c)
+{
+	set_bit(CACHE_SET_UNREGISTERING, &c->flags);
+	bch_cache_set_stop(c);
+}
+
+#define alloc_bucket_pages(gfp, c)			\
+	((void *) __get_free_pages(__GFP_ZERO|gfp, ilog2(bucket_pages(c))))
+
+struct cache_set *bch_cache_set_alloc(struct cache_sb *sb)
+{
+	int iter_size;
+	struct cache_set *c = kzalloc(sizeof(struct cache_set), GFP_KERNEL);
+	if (!c)
+		return NULL;
+
+	__module_get(THIS_MODULE);
+	closure_init(&c->cl, NULL);
+	set_closure_fn(&c->cl, cache_set_free, system_wq);
+
+	closure_init(&c->caching, &c->cl);
+	set_closure_fn(&c->caching, __cache_set_unregister, system_wq);
+
+	/* Maybe create continue_at_noreturn() and use it here? */
+	closure_set_stopped(&c->cl);
+	closure_put(&c->cl);
+
+	kobject_init(&c->kobj, &bch_cache_set_ktype);
+	kobject_init(&c->internal, &bch_cache_set_internal_ktype);
+
+	bch_cache_accounting_init(&c->accounting, &c->cl);
+
+	memcpy(c->sb.set_uuid, sb->set_uuid, 16);
+	c->sb.block_size	= sb->block_size;
+	c->sb.bucket_size	= sb->bucket_size;
+	c->sb.nr_in_set		= sb->nr_in_set;
+	c->sb.last_mount	= sb->last_mount;
+	c->bucket_bits		= ilog2(sb->bucket_size);
+	c->block_bits		= ilog2(sb->block_size);
+	c->nr_uuids		= bucket_bytes(c) / sizeof(struct uuid_entry);
+
+	c->btree_pages		= c->sb.bucket_size / PAGE_SECTORS;
+	if (c->btree_pages > BTREE_MAX_PAGES)
+		c->btree_pages = max_t(int, c->btree_pages / 4,
+				       BTREE_MAX_PAGES);
+
+	init_waitqueue_head(&c->alloc_wait);
+	mutex_init(&c->bucket_lock);
+	mutex_init(&c->fill_lock);
+	mutex_init(&c->sort_lock);
+	spin_lock_init(&c->sort_time_lock);
+	closure_init_unlocked(&c->sb_write);
+	closure_init_unlocked(&c->uuid_write);
+	spin_lock_init(&c->btree_read_time_lock);
+	bch_moving_init_cache_set(c);
+
+	INIT_LIST_HEAD(&c->list);
+	INIT_LIST_HEAD(&c->cached_devs);
+	INIT_LIST_HEAD(&c->btree_cache);
+	INIT_LIST_HEAD(&c->btree_cache_freeable);
+	INIT_LIST_HEAD(&c->btree_cache_freed);
+	INIT_LIST_HEAD(&c->data_buckets);
+
+	c->search = mempool_create_slab_pool(32, bch_search_cache);
+	if (!c->search)
+		goto err;
+
+	iter_size = (sb->bucket_size / sb->block_size + 1) *
+		sizeof(struct btree_iter_set);
+
+	if (!(c->devices = kzalloc(c->nr_uuids * sizeof(void *), GFP_KERNEL)) ||
+	    !(c->bio_meta = mempool_create_kmalloc_pool(2,
+				sizeof(struct bbio) + sizeof(struct bio_vec) *
+				bucket_pages(c))) ||
+	    !(c->bio_split = bioset_create(4, offsetof(struct bbio, bio))) ||
+	    !(c->fill_iter = kmalloc(iter_size, GFP_KERNEL)) ||
+	    !(c->sort = alloc_bucket_pages(GFP_KERNEL, c)) ||
+	    !(c->uuids = alloc_bucket_pages(GFP_KERNEL, c)) ||
+	    bch_journal_alloc(c) ||
+	    bch_btree_cache_alloc(c) ||
+	    bch_open_buckets_alloc(c))
+		goto err;
+
+	c->fill_iter->size = sb->bucket_size / sb->block_size;
+
+	c->congested_read_threshold_us	= 2000;
+	c->congested_write_threshold_us	= 20000;
+	c->error_limit	= 8 << IO_ERROR_SHIFT;
+
+	return c;
+err:
+	bch_cache_set_unregister(c);
+	return NULL;
+}
+
+static void run_cache_set(struct cache_set *c)
+{
+	const char *err = "cannot allocate memory";
+	struct cached_dev *dc, *t;
+	struct cache *ca;
+	unsigned i;
+
+	struct btree_op op;
+	bch_btree_op_init_stack(&op);
+	op.lock = SHRT_MAX;
+
+	for_each_cache(ca, c, i)
+		c->nbuckets += ca->sb.nbuckets;
+
+	if (CACHE_SYNC(&c->sb)) {
+		LIST_HEAD(journal);
+		struct bkey *k;
+		struct jset *j;
+
+		err = "cannot allocate memory for journal";
+		if (bch_journal_read(c, &journal, &op))
+			goto err;
+
+		pr_debug("btree_journal_read() done");
+
+		err = "no journal entries found";
+		if (list_empty(&journal))
+			goto err;
+
+		j = &list_entry(journal.prev, struct journal_replay, list)->j;
+
+		err = "IO error reading priorities";
+		for_each_cache(ca, c, i)
+			prio_read(ca, j->prio_bucket[ca->sb.nr_this_dev]);
+
+		/*
+		 * If prio_read() fails it'll call cache_set_error and we'll
+		 * tear everything down right away, but if we perhaps checked
+		 * sooner we could avoid journal replay.
+		 */
+
+		k = &j->btree_root;
+
+		err = "bad btree root";
+		if (__bch_ptr_invalid(c, j->btree_level + 1, k))
+			goto err;
+
+		err = "error reading btree root";
+		c->root = bch_btree_node_get(c, k, j->btree_level, &op);
+		if (IS_ERR_OR_NULL(c->root))
+			goto err;
+
+		list_del_init(&c->root->list);
+		rw_unlock(true, c->root);
+
+		err = uuid_read(c, j, &op.cl);
+		if (err)
+			goto err;
+
+		err = "error in recovery";
+		if (bch_btree_check(c, &op))
+			goto err;
+
+		bch_journal_mark(c, &journal);
+		bch_btree_gc_finish(c);
+		pr_debug("btree_check() done");
+
+		/*
+		 * bcache_journal_next() can't happen sooner, or
+		 * btree_gc_finish() will give spurious errors about last_gc >
+		 * gc_gen - this is a hack but oh well.
+		 */
+		bch_journal_next(&c->journal);
+
+		for_each_cache(ca, c, i)
+			closure_call(&ca->alloc, bch_allocator_thread,
+				     system_wq, &c->cl);
+
+		/*
+		 * First place it's safe to allocate: btree_check() and
+		 * btree_gc_finish() have to run before we have buckets to
+		 * allocate, and bch_bucket_alloc_set() might cause a journal
+		 * entry to be written so bcache_journal_next() has to be called
+		 * first.
+		 *
+		 * If the uuids were in the old format we have to rewrite them
+		 * before the next journal entry is written:
+		 */
+		if (j->version < BCACHE_JSET_VERSION_UUID)
+			__uuid_write(c);
+
+		bch_journal_replay(c, &journal, &op);
+	} else {
+		pr_notice("invalidating existing data");
+		/* Don't want invalidate_buckets() to queue a gc yet */
+		closure_lock(&c->gc, NULL);
+
+		for_each_cache(ca, c, i) {
+			unsigned j;
+
+			ca->sb.keys = clamp_t(int, ca->sb.nbuckets >> 7,
+					      2, SB_JOURNAL_BUCKETS);
+
+			for (j = 0; j < ca->sb.keys; j++)
+				ca->sb.d[j] = ca->sb.first_bucket + j;
+		}
+
+		bch_btree_gc_finish(c);
+
+		for_each_cache(ca, c, i)
+			closure_call(&ca->alloc, bch_allocator_thread,
+				     ca->alloc_workqueue, &c->cl);
+
+		mutex_lock(&c->bucket_lock);
+		for_each_cache(ca, c, i)
+			bch_prio_write(ca);
+		mutex_unlock(&c->bucket_lock);
+
+		wake_up(&c->alloc_wait);
+
+		err = "cannot allocate new UUID bucket";
+		if (__uuid_write(c))
+			goto err_unlock_gc;
+
+		err = "cannot allocate new btree root";
+		c->root = bch_btree_node_alloc(c, 0, &op.cl);
+		if (IS_ERR_OR_NULL(c->root))
+			goto err_unlock_gc;
+
+		bkey_copy_key(&c->root->key, &MAX_KEY);
+		bch_btree_write(c->root, true, &op);
+
+		bch_btree_set_root(c->root);
+		rw_unlock(true, c->root);
+
+		/*
+		 * We don't want to write the first journal entry until
+		 * everything is set up - fortunately journal entries won't be
+		 * written until the SET_CACHE_SYNC() here:
+		 */
+		SET_CACHE_SYNC(&c->sb, true);
+
+		bch_journal_next(&c->journal);
+		bch_journal_meta(c, &op.cl);
+
+		/* Unlock */
+		closure_set_stopped(&c->gc.cl);
+		closure_put(&c->gc.cl);
+	}
+
+	closure_sync(&op.cl);
+	c->sb.last_mount = get_seconds();
+	bcache_write_super(c);
+
+	list_for_each_entry_safe(dc, t, &uncached_devices, list)
+		bch_cached_dev_attach(dc, c);
+
+	flash_devs_run(c);
+
+	return;
+err_unlock_gc:
+	closure_set_stopped(&c->gc.cl);
+	closure_put(&c->gc.cl);
+err:
+	closure_sync(&op.cl);
+	/* XXX: test this, it's broken */
+	bch_cache_set_error(c, err);
+}
+
+static bool can_attach_cache(struct cache *ca, struct cache_set *c)
+{
+	return ca->sb.block_size	== c->sb.block_size &&
+		ca->sb.bucket_size	== c->sb.block_size &&
+		ca->sb.nr_in_set	== c->sb.nr_in_set;
+}
+
+static const char *register_cache_set(struct cache *ca)
+{
+	char buf[12];
+	const char *err = "cannot allocate memory";
+	struct cache_set *c;
+
+	list_for_each_entry(c, &bch_cache_sets, list)
+		if (!memcmp(c->sb.set_uuid, ca->sb.set_uuid, 16)) {
+			if (c->cache[ca->sb.nr_this_dev])
+				return "duplicate cache set member";
+
+			if (!can_attach_cache(ca, c))
+				return "cache sb does not match set";
+
+			if (!CACHE_SYNC(&ca->sb))
+				SET_CACHE_SYNC(&c->sb, false);
+
+			goto found;
+		}
+
+	c = bch_cache_set_alloc(&ca->sb);
+	if (!c)
+		return err;
+
+	err = "error creating kobject";
+	if (kobject_add(&c->kobj, bcache_kobj, "%pU", c->sb.set_uuid) ||
+	    kobject_add(&c->internal, &c->kobj, "internal"))
+		goto err;
+
+	if (bch_cache_accounting_add_kobjs(&c->accounting, &c->kobj))
+		goto err;
+
+	bch_debug_init_cache_set(c);
+
+	list_add(&c->list, &bch_cache_sets);
+found:
+	sprintf(buf, "cache%i", ca->sb.nr_this_dev);
+	if (sysfs_create_link(&ca->kobj, &c->kobj, "set") ||
+	    sysfs_create_link(&c->kobj, &ca->kobj, buf))
+		goto err;
+
+	if (ca->sb.seq > c->sb.seq) {
+		c->sb.version		= ca->sb.version;
+		memcpy(c->sb.set_uuid, ca->sb.set_uuid, 16);
+		c->sb.flags             = ca->sb.flags;
+		c->sb.seq		= ca->sb.seq;
+		pr_debug("set version = %llu", c->sb.version);
+	}
+
+	ca->set = c;
+	ca->set->cache[ca->sb.nr_this_dev] = ca;
+	c->cache_by_alloc[c->caches_loaded++] = ca;
+
+	if (c->caches_loaded == c->sb.nr_in_set)
+		run_cache_set(c);
+
+	return NULL;
+err:
+	bch_cache_set_unregister(c);
+	return err;
+}
+
+/* Cache device */
+
+void bch_cache_release(struct kobject *kobj)
+{
+	struct cache *ca = container_of(kobj, struct cache, kobj);
+
+	if (ca->set)
+		ca->set->cache[ca->sb.nr_this_dev] = NULL;
+
+	bch_cache_allocator_exit(ca);
+
+	bio_split_pool_free(&ca->bio_split_hook);
+
+	if (ca->alloc_workqueue)
+		destroy_workqueue(ca->alloc_workqueue);
+
+	free_pages((unsigned long) ca->disk_buckets, ilog2(bucket_pages(ca)));
+	kfree(ca->prio_buckets);
+	vfree(ca->buckets);
+
+	free_heap(&ca->heap);
+	free_fifo(&ca->unused);
+	free_fifo(&ca->free_inc);
+	free_fifo(&ca->free);
+
+	if (ca->sb_bio.bi_inline_vecs[0].bv_page)
+		put_page(ca->sb_bio.bi_io_vec[0].bv_page);
+
+	if (!IS_ERR_OR_NULL(ca->bdev)) {
+		blk_sync_queue(bdev_get_queue(ca->bdev));
+		blkdev_put(ca->bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
+	}
+
+	kfree(ca);
+	module_put(THIS_MODULE);
+}
+
+static int cache_alloc(struct cache_sb *sb, struct cache *ca)
+{
+	size_t free;
+	struct bucket *b;
+
+	if (!ca)
+		return -ENOMEM;
+
+	__module_get(THIS_MODULE);
+	kobject_init(&ca->kobj, &bch_cache_ktype);
+
+	memcpy(&ca->sb, sb, sizeof(struct cache_sb));
+
+	INIT_LIST_HEAD(&ca->discards);
+
+	bio_init(&ca->sb_bio);
+	ca->sb_bio.bi_max_vecs	= 1;
+	ca->sb_bio.bi_io_vec	= ca->sb_bio.bi_inline_vecs;
+
+	bio_init(&ca->journal.bio);
+	ca->journal.bio.bi_max_vecs = 8;
+	ca->journal.bio.bi_io_vec = ca->journal.bio.bi_inline_vecs;
+
+	free = roundup_pow_of_two(ca->sb.nbuckets) >> 9;
+	free = max_t(size_t, free, (prio_buckets(ca) + 8) * 2);
+
+	if (!init_fifo(&ca->free,	free, GFP_KERNEL) ||
+	    !init_fifo(&ca->free_inc,	free << 2, GFP_KERNEL) ||
+	    !init_fifo(&ca->unused,	free << 2, GFP_KERNEL) ||
+	    !init_heap(&ca->heap,	free << 3, GFP_KERNEL) ||
+	    !(ca->buckets	= vmalloc(sizeof(struct bucket) *
+					  ca->sb.nbuckets)) ||
+	    !(ca->prio_buckets	= kzalloc(sizeof(uint64_t) * prio_buckets(ca) *
+					  2, GFP_KERNEL)) ||
+	    !(ca->disk_buckets	= alloc_bucket_pages(GFP_KERNEL, ca)) ||
+	    !(ca->alloc_workqueue = alloc_workqueue("bch_allocator", 0, 1)) ||
+	    bio_split_pool_init(&ca->bio_split_hook))
+		goto err;
+
+	ca->prio_last_buckets = ca->prio_buckets + prio_buckets(ca);
+
+	memset(ca->buckets, 0, ca->sb.nbuckets * sizeof(struct bucket));
+	for_each_bucket(b, ca)
+		atomic_set(&b->pin, 0);
+
+	if (bch_cache_allocator_init(ca))
+		goto err;
+
+	return 0;
+err:
+	kobject_put(&ca->kobj);
+	return -ENOMEM;
+}
+
+static const char *register_cache(struct cache_sb *sb, struct page *sb_page,
+				  struct block_device *bdev, struct cache *ca)
+{
+	char name[BDEVNAME_SIZE];
+	const char *err = "cannot allocate memory";
+
+	if (cache_alloc(sb, ca) != 0)
+		return err;
+
+	ca->sb_bio.bi_io_vec[0].bv_page = sb_page;
+	ca->bdev = bdev;
+	ca->bdev->bd_holder = ca;
+
+	if (blk_queue_discard(bdev_get_queue(ca->bdev)))
+		ca->discard = CACHE_DISCARD(&ca->sb);
+
+	err = "error creating kobject";
+	if (kobject_add(&ca->kobj, &part_to_dev(bdev->bd_part)->kobj, "bcache"))
+		goto err;
+
+	err = register_cache_set(ca);
+	if (err)
+		goto err;
+
+	pr_info("registered cache device %s", bdevname(bdev, name));
+
+	return NULL;
+err:
+	kobject_put(&ca->kobj);
+	pr_info("error opening %s: %s", bdevname(bdev, name), err);
+	/* Return NULL instead of an error because kobject_put() cleans
+	 * everything up
+	 */
+	return NULL;
+}
+
+/* Global interfaces/init */
+
+static ssize_t register_bcache(struct kobject *, struct kobj_attribute *,
+			       const char *, size_t);
+
+kobj_attribute_write(register,		register_bcache);
+kobj_attribute_write(register_quiet,	register_bcache);
+
+static ssize_t register_bcache(struct kobject *k, struct kobj_attribute *attr,
+			       const char *buffer, size_t size)
+{
+	ssize_t ret = size;
+	const char *err = "cannot allocate memory";
+	char *path = NULL;
+	struct cache_sb *sb = NULL;
+	struct block_device *bdev = NULL;
+	struct page *sb_page = NULL;
+
+	if (!try_module_get(THIS_MODULE))
+		return -EBUSY;
+
+	mutex_lock(&bch_register_lock);
+
+	if (!(path = kstrndup(buffer, size, GFP_KERNEL)) ||
+	    !(sb = kmalloc(sizeof(struct cache_sb), GFP_KERNEL)))
+		goto err;
+
+	err = "failed to open device";
+	bdev = blkdev_get_by_path(strim(path),
+				  FMODE_READ|FMODE_WRITE|FMODE_EXCL,
+				  sb);
+	if (bdev == ERR_PTR(-EBUSY))
+		err = "device busy";
+
+	if (IS_ERR(bdev) ||
+	    set_blocksize(bdev, 4096))
+		goto err;
+
+	err = read_super(sb, bdev, &sb_page);
+	if (err)
+		goto err_close;
+
+	if (sb->version == CACHE_BACKING_DEV) {
+		struct cached_dev *dc = kzalloc(sizeof(*dc), GFP_KERNEL);
+
+		err = register_bdev(sb, sb_page, bdev, dc);
+	} else {
+		struct cache *ca = kzalloc(sizeof(*ca), GFP_KERNEL);
+
+		err = register_cache(sb, sb_page, bdev, ca);
+	}
+
+	if (err) {
+		/* register_(bdev|cache) will only return an error if they
+		 * didn't get far enough to create the kobject - if they did,
+		 * the kobject destructor will do this cleanup.
+		 */
+		put_page(sb_page);
+err_close:
+		blkdev_put(bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
+err:
+		if (attr != &ksysfs_register_quiet)
+			pr_info("error opening %s: %s", path, err);
+		ret = -EINVAL;
+	}
+
+	kfree(sb);
+	kfree(path);
+	mutex_unlock(&bch_register_lock);
+	module_put(THIS_MODULE);
+	return ret;
+}
+
+static int bcache_reboot(struct notifier_block *n, unsigned long code, void *x)
+{
+	if (code == SYS_DOWN ||
+	    code == SYS_HALT ||
+	    code == SYS_POWER_OFF) {
+		DEFINE_WAIT(wait);
+		unsigned long start = jiffies;
+		bool stopped = false;
+
+		struct cache_set *c, *tc;
+		struct cached_dev *dc, *tdc;
+
+		mutex_lock(&bch_register_lock);
+
+		if (list_empty(&bch_cache_sets) &&
+		    list_empty(&uncached_devices))
+			goto out;
+
+		pr_info("Stopping all devices:");
+
+		list_for_each_entry_safe(c, tc, &bch_cache_sets, list)
+			bch_cache_set_stop(c);
+
+		list_for_each_entry_safe(dc, tdc, &uncached_devices, list)
+			bcache_device_stop(&dc->disk);
+
+		/* What's a condition variable? */
+		while (1) {
+			long timeout = start + 2 * HZ - jiffies;
+
+			stopped = list_empty(&bch_cache_sets) &&
+				list_empty(&uncached_devices);
+
+			if (timeout < 0 || stopped)
+				break;
+
+			prepare_to_wait(&unregister_wait, &wait,
+					TASK_UNINTERRUPTIBLE);
+
+			mutex_unlock(&bch_register_lock);
+			schedule_timeout(timeout);
+			mutex_lock(&bch_register_lock);
+		}
+
+		finish_wait(&unregister_wait, &wait);
+
+		if (stopped)
+			pr_info("All devices stopped");
+		else
+			pr_notice("Timeout waiting for devices to be closed");
+out:
+		mutex_unlock(&bch_register_lock);
+	}
+
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block reboot = {
+	.notifier_call	= bcache_reboot,
+	.priority	= INT_MAX, /* before any real devices */
+};
+
+static void bcache_exit(void)
+{
+	bch_debug_exit();
+	bch_writeback_exit();
+	bch_request_exit();
+	bch_btree_exit();
+	if (bcache_kobj)
+		kobject_put(bcache_kobj);
+	if (bcache_wq)
+		destroy_workqueue(bcache_wq);
+	unregister_blkdev(bcache_major, "bcache");
+	unregister_reboot_notifier(&reboot);
+}
+
+static int __init bcache_init(void)
+{
+	static const struct attribute *files[] = {
+		&ksysfs_register.attr,
+		&ksysfs_register_quiet.attr,
+		NULL
+	};
+
+	mutex_init(&bch_register_lock);
+	init_waitqueue_head(&unregister_wait);
+	register_reboot_notifier(&reboot);
+	closure_debug_init();
+
+	bcache_major = register_blkdev(0, "bcache");
+	if (bcache_major < 0)
+		return bcache_major;
+
+	if (!(bcache_wq = create_workqueue("bcache")) ||
+	    !(bcache_kobj = kobject_create_and_add("bcache", fs_kobj)) ||
+	    sysfs_create_files(bcache_kobj, files) ||
+	    bch_btree_init() ||
+	    bch_request_init() ||
+	    bch_writeback_init() ||
+	    bch_debug_init(bcache_kobj))
+		goto err;
+
+	return 0;
+err:
+	bcache_exit();
+	return -ENOMEM;
+}
+
+module_exit(bcache_exit);
+module_init(bcache_init);
diff --git a/drivers/md/bcache/sysfs.c b/drivers/md/bcache/sysfs.c
new file mode 100644
index 0000000..4d9cca4
--- /dev/null
+++ b/drivers/md/bcache/sysfs.c
@@ -0,0 +1,817 @@
+/*
+ * bcache sysfs interfaces
+ *
+ * Copyright 2010, 2011 Kent Overstreet <kent.overstreet@gmail.com>
+ * Copyright 2012 Google, Inc.
+ */
+
+#include "bcache.h"
+#include "sysfs.h"
+#include "btree.h"
+#include "request.h"
+
+#include <linux/sort.h>
+
+static const char * const cache_replacement_policies[] = {
+	"lru",
+	"fifo",
+	"random",
+	NULL
+};
+
+write_attribute(attach);
+write_attribute(detach);
+write_attribute(unregister);
+write_attribute(stop);
+write_attribute(clear_stats);
+write_attribute(trigger_gc);
+write_attribute(prune_cache);
+write_attribute(flash_vol_create);
+
+read_attribute(bucket_size);
+read_attribute(block_size);
+read_attribute(nbuckets);
+read_attribute(tree_depth);
+read_attribute(root_usage_percent);
+read_attribute(priority_stats);
+read_attribute(btree_cache_size);
+read_attribute(btree_cache_max_chain);
+read_attribute(cache_available_percent);
+read_attribute(written);
+read_attribute(btree_written);
+read_attribute(metadata_written);
+read_attribute(active_journal_entries);
+
+sysfs_time_stats_attribute(btree_gc,	sec, ms);
+sysfs_time_stats_attribute(btree_split, sec, us);
+sysfs_time_stats_attribute(btree_sort,	ms,  us);
+sysfs_time_stats_attribute(btree_read,	ms,  us);
+sysfs_time_stats_attribute(try_harder,	ms,  us);
+
+read_attribute(btree_nodes);
+read_attribute(btree_used_percent);
+read_attribute(average_key_size);
+read_attribute(dirty_data);
+read_attribute(bset_tree_stats);
+
+read_attribute(state);
+read_attribute(cache_read_races);
+read_attribute(writeback_keys_done);
+read_attribute(writeback_keys_failed);
+read_attribute(io_errors);
+read_attribute(congested);
+rw_attribute(congested_read_threshold_us);
+rw_attribute(congested_write_threshold_us);
+
+rw_attribute(sequential_cutoff);
+rw_attribute(sequential_merge);
+rw_attribute(data_csum);
+rw_attribute(cache_mode);
+rw_attribute(writeback_metadata);
+rw_attribute(writeback_running);
+rw_attribute(writeback_percent);
+rw_attribute(writeback_delay);
+rw_attribute(writeback_rate);
+
+rw_attribute(writeback_rate_update_seconds);
+rw_attribute(writeback_rate_d_term);
+rw_attribute(writeback_rate_p_term_inverse);
+rw_attribute(writeback_rate_d_smooth);
+read_attribute(writeback_rate_debug);
+
+rw_attribute(synchronous);
+rw_attribute(journal_delay_ms);
+rw_attribute(discard);
+rw_attribute(running);
+rw_attribute(label);
+rw_attribute(readahead);
+rw_attribute(io_error_limit);
+rw_attribute(io_error_halflife);
+rw_attribute(verify);
+rw_attribute(key_merging_disabled);
+rw_attribute(gc_always_rewrite);
+rw_attribute(freelist_percent);
+rw_attribute(cache_replacement_policy);
+rw_attribute(btree_shrinker_disabled);
+rw_attribute(copy_gc_enabled);
+rw_attribute(size);
+
+SHOW(__bch_cached_dev)
+{
+	struct cached_dev *dc = container_of(kobj, struct cached_dev,
+					     disk.kobj);
+	const char *states[] = { "no cache", "clean", "dirty", "inconsistent" };
+
+#define var(stat)		(dc->stat)
+
+	if (attr == &sysfs_cache_mode)
+		return bch_snprint_string_list(buf, PAGE_SIZE,
+					       bch_cache_modes + 1,
+					       BDEV_CACHE_MODE(&dc->sb));
+
+	sysfs_printf(data_csum,		"%i", dc->disk.data_csum);
+	var_printf(verify,		"%i");
+	var_printf(writeback_metadata,	"%i");
+	var_printf(writeback_running,	"%i");
+	var_print(writeback_delay);
+	var_print(writeback_percent);
+	sysfs_print(writeback_rate,	dc->writeback_rate.rate);
+
+	var_print(writeback_rate_update_seconds);
+	var_print(writeback_rate_d_term);
+	var_print(writeback_rate_p_term_inverse);
+	var_print(writeback_rate_d_smooth);
+
+	if (attr == &sysfs_writeback_rate_debug) {
+		char dirty[20];
+		char derivative[20];
+		char target[20];
+		bch_hprint(dirty,
+		       atomic_long_read(&dc->disk.sectors_dirty) << 9);
+		bch_hprint(derivative,	dc->writeback_rate_derivative << 9);
+		bch_hprint(target,	dc->writeback_rate_target << 9);
+
+		return sprintf(buf,
+			       "rate:\t\t%u\n"
+			       "change:\t\t%i\n"
+			       "dirty:\t\t%s\n"
+			       "derivative:\t%s\n"
+			       "target:\t\t%s\n",
+			       dc->writeback_rate.rate,
+			       dc->writeback_rate_change,
+			       dirty, derivative, target);
+	}
+
+	sysfs_hprint(dirty_data,
+		     atomic_long_read(&dc->disk.sectors_dirty) << 9);
+
+	var_printf(sequential_merge,	"%i");
+	var_hprint(sequential_cutoff);
+	var_hprint(readahead);
+
+	sysfs_print(running,		atomic_read(&dc->running));
+	sysfs_print(state,		states[BDEV_STATE(&dc->sb)]);
+
+	if (attr == &sysfs_label) {
+		memcpy(buf, dc->sb.label, SB_LABEL_SIZE);
+		buf[SB_LABEL_SIZE + 1] = '\0';
+		strcat(buf, "\n");
+		return strlen(buf);
+	}
+
+#undef var
+	return 0;
+}
+SHOW_LOCKED(bch_cached_dev)
+
+STORE(__cached_dev)
+{
+	struct cached_dev *dc = container_of(kobj, struct cached_dev,
+					     disk.kobj);
+	unsigned v = size;
+	struct cache_set *c;
+
+#define d_strtoul(var)		sysfs_strtoul(var, dc->var)
+#define d_strtoi_h(var)		sysfs_hatoi(var, dc->var)
+
+	sysfs_strtoul(data_csum,	dc->disk.data_csum);
+	d_strtoul(verify);
+	d_strtoul(writeback_metadata);
+	d_strtoul(writeback_running);
+	d_strtoul(writeback_delay);
+	sysfs_strtoul_clamp(writeback_rate,
+			    dc->writeback_rate.rate, 1, 1000000);
+	sysfs_strtoul_clamp(writeback_percent, dc->writeback_percent, 0, 40);
+
+	d_strtoul(writeback_rate_update_seconds);
+	d_strtoul(writeback_rate_d_term);
+	d_strtoul(writeback_rate_p_term_inverse);
+	sysfs_strtoul_clamp(writeback_rate_p_term_inverse,
+			    dc->writeback_rate_p_term_inverse, 1, INT_MAX);
+	d_strtoul(writeback_rate_d_smooth);
+
+	d_strtoul(sequential_merge);
+	d_strtoi_h(sequential_cutoff);
+	d_strtoi_h(readahead);
+
+	if (attr == &sysfs_clear_stats)
+		bch_cache_accounting_clear(&dc->accounting);
+
+	if (attr == &sysfs_running &&
+	    strtoul_or_return(buf))
+		bch_cached_dev_run(dc);
+
+	if (attr == &sysfs_cache_mode) {
+		ssize_t v = bch_read_string_list(buf, bch_cache_modes + 1);
+
+		if (v < 0)
+			return v;
+
+		if ((unsigned) v != BDEV_CACHE_MODE(&dc->sb)) {
+			SET_BDEV_CACHE_MODE(&dc->sb, v);
+			bch_write_bdev_super(dc, NULL);
+		}
+	}
+
+	if (attr == &sysfs_label) {
+		memcpy(dc->sb.label, buf, SB_LABEL_SIZE);
+		bch_write_bdev_super(dc, NULL);
+		if (dc->disk.c) {
+			memcpy(dc->disk.c->uuids[dc->disk.id].label,
+			       buf, SB_LABEL_SIZE);
+			bch_uuid_write(dc->disk.c);
+		}
+	}
+
+	if (attr == &sysfs_attach) {
+		if (bch_parse_uuid(buf, dc->sb.set_uuid) < 16)
+			return -EINVAL;
+
+		list_for_each_entry(c, &bch_cache_sets, list) {
+			v = bch_cached_dev_attach(dc, c);
+			if (!v)
+				return size;
+		}
+
+		pr_err("Can't attach %s: cache set not found", buf);
+		size = v;
+	}
+
+	if (attr == &sysfs_detach && dc->disk.c)
+		bch_cached_dev_detach(dc);
+
+	if (attr == &sysfs_stop)
+		bcache_device_stop(&dc->disk);
+
+	return size;
+}
+
+STORE(bch_cached_dev)
+{
+	struct cached_dev *dc = container_of(kobj, struct cached_dev,
+					     disk.kobj);
+
+	mutex_lock(&bch_register_lock);
+	size = __cached_dev_store(kobj, attr, buf, size);
+
+	if (attr == &sysfs_writeback_running)
+		bch_writeback_queue(dc);
+
+	if (attr == &sysfs_writeback_percent)
+		schedule_delayed_work(&dc->writeback_rate_update,
+				      dc->writeback_rate_update_seconds * HZ);
+
+	mutex_unlock(&bch_register_lock);
+	return size;
+}
+
+static struct attribute *bch_cached_dev_files[] = {
+	&sysfs_attach,
+	&sysfs_detach,
+	&sysfs_stop,
+#if 0
+	&sysfs_data_csum,
+#endif
+	&sysfs_cache_mode,
+	&sysfs_writeback_metadata,
+	&sysfs_writeback_running,
+	&sysfs_writeback_delay,
+	&sysfs_writeback_percent,
+	&sysfs_writeback_rate,
+	&sysfs_writeback_rate_update_seconds,
+	&sysfs_writeback_rate_d_term,
+	&sysfs_writeback_rate_p_term_inverse,
+	&sysfs_writeback_rate_d_smooth,
+	&sysfs_writeback_rate_debug,
+	&sysfs_dirty_data,
+	&sysfs_sequential_cutoff,
+	&sysfs_sequential_merge,
+	&sysfs_clear_stats,
+	&sysfs_running,
+	&sysfs_state,
+	&sysfs_label,
+	&sysfs_readahead,
+#ifdef CONFIG_BCACHE_DEBUG
+	&sysfs_verify,
+#endif
+	NULL
+};
+KTYPE(bch_cached_dev);
+
+SHOW(bch_flash_dev)
+{
+	struct bcache_device *d = container_of(kobj, struct bcache_device,
+					       kobj);
+	struct uuid_entry *u = &d->c->uuids[d->id];
+
+	sysfs_printf(data_csum,	"%i", d->data_csum);
+	sysfs_hprint(size,	u->sectors << 9);
+
+	if (attr == &sysfs_label) {
+		memcpy(buf, u->label, SB_LABEL_SIZE);
+		buf[SB_LABEL_SIZE + 1] = '\0';
+		strcat(buf, "\n");
+		return strlen(buf);
+	}
+
+	return 0;
+}
+
+STORE(__bch_flash_dev)
+{
+	struct bcache_device *d = container_of(kobj, struct bcache_device,
+					       kobj);
+	struct uuid_entry *u = &d->c->uuids[d->id];
+
+	sysfs_strtoul(data_csum,	d->data_csum);
+
+	if (attr == &sysfs_size) {
+		uint64_t v;
+		strtoi_h_or_return(buf, v);
+
+		u->sectors = v >> 9;
+		bch_uuid_write(d->c);
+		set_capacity(d->disk, u->sectors);
+	}
+
+	if (attr == &sysfs_label) {
+		memcpy(u->label, buf, SB_LABEL_SIZE);
+		bch_uuid_write(d->c);
+	}
+
+	if (attr == &sysfs_unregister) {
+		atomic_set(&d->detaching, 1);
+		bcache_device_stop(d);
+	}
+
+	return size;
+}
+STORE_LOCKED(bch_flash_dev)
+
+static struct attribute *bch_flash_dev_files[] = {
+	&sysfs_unregister,
+#if 0
+	&sysfs_data_csum,
+#endif
+	&sysfs_label,
+	&sysfs_size,
+	NULL
+};
+KTYPE(bch_flash_dev);
+
+SHOW(__bch_cache_set)
+{
+	unsigned root_usage(struct cache_set *c)
+	{
+		unsigned bytes = 0;
+		struct bkey *k;
+		struct btree *b;
+		struct btree_iter iter;
+
+		goto lock_root;
+
+		do {
+			rw_unlock(false, b);
+lock_root:
+			b = c->root;
+			rw_lock(false, b, b->level);
+		} while (b != c->root);
+
+		for_each_key_filter(b, k, &iter, bch_ptr_bad)
+			bytes += bkey_bytes(k);
+
+		rw_unlock(false, b);
+
+		return (bytes * 100) / btree_bytes(c);
+	}
+
+	size_t cache_size(struct cache_set *c)
+	{
+		size_t ret = 0;
+		struct btree *b;
+
+		mutex_lock(&c->bucket_lock);
+		list_for_each_entry(b, &c->btree_cache, list)
+			ret += 1 << (b->page_order + PAGE_SHIFT);
+
+		mutex_unlock(&c->bucket_lock);
+		return ret;
+	}
+
+	unsigned cache_max_chain(struct cache_set *c)
+	{
+		unsigned ret = 0;
+		struct hlist_head *h;
+
+		mutex_lock(&c->bucket_lock);
+
+		for (h = c->bucket_hash;
+		     h < c->bucket_hash + (1 << BUCKET_HASH_BITS);
+		     h++) {
+			unsigned i = 0;
+			struct hlist_node *p;
+
+			hlist_for_each(p, h)
+				i++;
+
+			ret = max(ret, i);
+		}
+
+		mutex_unlock(&c->bucket_lock);
+		return ret;
+	}
+
+	unsigned btree_used(struct cache_set *c)
+	{
+		return div64_u64(c->gc_stats.key_bytes * 100,
+				 (c->gc_stats.nodes ?: 1) * btree_bytes(c));
+	}
+
+	unsigned average_key_size(struct cache_set *c)
+	{
+		return c->gc_stats.nkeys
+			? div64_u64(c->gc_stats.data, c->gc_stats.nkeys)
+			: 0;
+	}
+
+	struct cache_set *c = container_of(kobj, struct cache_set, kobj);
+
+	sysfs_print(synchronous,		CACHE_SYNC(&c->sb));
+	sysfs_print(journal_delay_ms,		c->journal_delay_ms);
+	sysfs_hprint(bucket_size,		bucket_bytes(c));
+	sysfs_hprint(block_size,		block_bytes(c));
+	sysfs_print(tree_depth,			c->root->level);
+	sysfs_print(root_usage_percent,		root_usage(c));
+
+	sysfs_hprint(btree_cache_size,		cache_size(c));
+	sysfs_print(btree_cache_max_chain,	cache_max_chain(c));
+	sysfs_print(cache_available_percent,	100 - c->gc_stats.in_use);
+
+	sysfs_print_time_stats(&c->btree_gc_time,	btree_gc, sec, ms);
+	sysfs_print_time_stats(&c->btree_split_time,	btree_split, sec, us);
+	sysfs_print_time_stats(&c->sort_time,		btree_sort, ms, us);
+	sysfs_print_time_stats(&c->btree_read_time,	btree_read, ms, us);
+	sysfs_print_time_stats(&c->try_harder_time,	try_harder, ms, us);
+
+	sysfs_print(btree_used_percent,	btree_used(c));
+	sysfs_print(btree_nodes,	c->gc_stats.nodes);
+	sysfs_hprint(dirty_data,	c->gc_stats.dirty);
+	sysfs_hprint(average_key_size,	average_key_size(c));
+
+	sysfs_print(cache_read_races,
+		    atomic_long_read(&c->cache_read_races));
+
+	sysfs_print(writeback_keys_done,
+		    atomic_long_read(&c->writeback_keys_done));
+	sysfs_print(writeback_keys_failed,
+		    atomic_long_read(&c->writeback_keys_failed));
+
+	/* See count_io_errors for why 88 */
+	sysfs_print(io_error_halflife,	c->error_decay * 88);
+	sysfs_print(io_error_limit,	c->error_limit >> IO_ERROR_SHIFT);
+
+	sysfs_hprint(congested,
+		     ((uint64_t) bch_get_congested(c)) << 9);
+	sysfs_print(congested_read_threshold_us,
+		    c->congested_read_threshold_us);
+	sysfs_print(congested_write_threshold_us,
+		    c->congested_write_threshold_us);
+
+	sysfs_print(active_journal_entries,	fifo_used(&c->journal.pin));
+	sysfs_printf(verify,			"%i", c->verify);
+	sysfs_printf(key_merging_disabled,	"%i", c->key_merging_disabled);
+	sysfs_printf(gc_always_rewrite,		"%i", c->gc_always_rewrite);
+	sysfs_printf(btree_shrinker_disabled,	"%i", c->shrinker_disabled);
+	sysfs_printf(copy_gc_enabled,		"%i", c->copy_gc_enabled);
+
+	if (attr == &sysfs_bset_tree_stats)
+		return bch_bset_print_stats(c, buf);
+
+	return 0;
+}
+SHOW_LOCKED(bch_cache_set)
+
+STORE(__bch_cache_set)
+{
+	struct cache_set *c = container_of(kobj, struct cache_set, kobj);
+
+	if (attr == &sysfs_unregister)
+		bch_cache_set_unregister(c);
+
+	if (attr == &sysfs_stop)
+		bch_cache_set_stop(c);
+
+	if (attr == &sysfs_synchronous) {
+		bool sync = strtoul_or_return(buf);
+
+		if (sync != CACHE_SYNC(&c->sb)) {
+			SET_CACHE_SYNC(&c->sb, sync);
+			bcache_write_super(c);
+		}
+	}
+
+	if (attr == &sysfs_flash_vol_create) {
+		int r;
+		uint64_t v;
+		strtoi_h_or_return(buf, v);
+
+		r = bch_flash_dev_create(c, v);
+		if (r)
+			return r;
+	}
+
+	if (attr == &sysfs_clear_stats) {
+		atomic_long_set(&c->writeback_keys_done,	0);
+		atomic_long_set(&c->writeback_keys_failed,	0);
+
+		memset(&c->gc_stats, 0, sizeof(struct gc_stat));
+		bch_cache_accounting_clear(&c->accounting);
+	}
+
+	if (attr == &sysfs_trigger_gc)
+		bch_queue_gc(c);
+
+	if (attr == &sysfs_prune_cache) {
+		struct shrink_control sc;
+		sc.gfp_mask = GFP_KERNEL;
+		sc.nr_to_scan = strtoul_or_return(buf);
+		c->shrink.shrink(&c->shrink, &sc);
+	}
+
+	sysfs_strtoul(congested_read_threshold_us,
+		      c->congested_read_threshold_us);
+	sysfs_strtoul(congested_write_threshold_us,
+		      c->congested_write_threshold_us);
+
+	if (attr == &sysfs_io_error_limit)
+		c->error_limit = strtoul_or_return(buf) << IO_ERROR_SHIFT;
+
+	/* See count_io_errors() for why 88 */
+	if (attr == &sysfs_io_error_halflife)
+		c->error_decay = strtoul_or_return(buf) / 88;
+
+	sysfs_strtoul(journal_delay_ms,		c->journal_delay_ms);
+	sysfs_strtoul(verify,			c->verify);
+	sysfs_strtoul(key_merging_disabled,	c->key_merging_disabled);
+	sysfs_strtoul(gc_always_rewrite,	c->gc_always_rewrite);
+	sysfs_strtoul(btree_shrinker_disabled,	c->shrinker_disabled);
+	sysfs_strtoul(copy_gc_enabled,		c->copy_gc_enabled);
+
+	return size;
+}
+STORE_LOCKED(bch_cache_set)
+
+SHOW(bch_cache_set_internal)
+{
+	struct cache_set *c = container_of(kobj, struct cache_set, internal);
+	return bch_cache_set_show(&c->kobj, attr, buf);
+}
+
+STORE(bch_cache_set_internal)
+{
+	struct cache_set *c = container_of(kobj, struct cache_set, internal);
+	return bch_cache_set_store(&c->kobj, attr, buf, size);
+}
+
+static void bch_cache_set_internal_release(struct kobject *k)
+{
+}
+
+static struct attribute *bch_cache_set_files[] = {
+	&sysfs_unregister,
+	&sysfs_stop,
+	&sysfs_synchronous,
+	&sysfs_journal_delay_ms,
+	&sysfs_flash_vol_create,
+
+	&sysfs_bucket_size,
+	&sysfs_block_size,
+	&sysfs_tree_depth,
+	&sysfs_root_usage_percent,
+	&sysfs_btree_cache_size,
+	&sysfs_cache_available_percent,
+
+	&sysfs_average_key_size,
+	&sysfs_dirty_data,
+
+	&sysfs_io_error_limit,
+	&sysfs_io_error_halflife,
+	&sysfs_congested,
+	&sysfs_congested_read_threshold_us,
+	&sysfs_congested_write_threshold_us,
+	&sysfs_clear_stats,
+	NULL
+};
+KTYPE(bch_cache_set);
+
+static struct attribute *bch_cache_set_internal_files[] = {
+	&sysfs_active_journal_entries,
+
+	sysfs_time_stats_attribute_list(btree_gc, sec, ms)
+	sysfs_time_stats_attribute_list(btree_split, sec, us)
+	sysfs_time_stats_attribute_list(btree_sort, ms, us)
+	sysfs_time_stats_attribute_list(btree_read, ms, us)
+	sysfs_time_stats_attribute_list(try_harder, ms, us)
+
+	&sysfs_btree_nodes,
+	&sysfs_btree_used_percent,
+	&sysfs_btree_cache_max_chain,
+
+	&sysfs_bset_tree_stats,
+	&sysfs_cache_read_races,
+	&sysfs_writeback_keys_done,
+	&sysfs_writeback_keys_failed,
+
+	&sysfs_trigger_gc,
+	&sysfs_prune_cache,
+#ifdef CONFIG_BCACHE_DEBUG
+	&sysfs_verify,
+	&sysfs_key_merging_disabled,
+#endif
+	&sysfs_gc_always_rewrite,
+	&sysfs_btree_shrinker_disabled,
+	&sysfs_copy_gc_enabled,
+	NULL
+};
+KTYPE(bch_cache_set_internal);
+
+SHOW(__bch_cache)
+{
+	struct cache *ca = container_of(kobj, struct cache, kobj);
+
+	sysfs_hprint(bucket_size,	bucket_bytes(ca));
+	sysfs_hprint(block_size,	block_bytes(ca));
+	sysfs_print(nbuckets,		ca->sb.nbuckets);
+	sysfs_print(discard,		ca->discard);
+	sysfs_hprint(written, atomic_long_read(&ca->sectors_written) << 9);
+	sysfs_hprint(btree_written,
+		     atomic_long_read(&ca->btree_sectors_written) << 9);
+	sysfs_hprint(metadata_written,
+		     (atomic_long_read(&ca->meta_sectors_written) +
+		      atomic_long_read(&ca->btree_sectors_written)) << 9);
+
+	sysfs_print(io_errors,
+		    atomic_read(&ca->io_errors) >> IO_ERROR_SHIFT);
+
+	sysfs_print(freelist_percent, ca->free.size * 100 /
+		    ((size_t) ca->sb.nbuckets));
+
+	if (attr == &sysfs_cache_replacement_policy)
+		return bch_snprint_string_list(buf, PAGE_SIZE,
+					       cache_replacement_policies,
+					       CACHE_REPLACEMENT(&ca->sb));
+
+	if (attr == &sysfs_priority_stats) {
+		int cmp(const void *l, const void *r)
+		{	return *((uint16_t *) r) - *((uint16_t *) l); }
+
+		/* Number of quantiles we compute */
+		const unsigned nq = 31;
+
+		size_t n = ca->sb.nbuckets, i, unused, btree;
+		uint64_t sum = 0;
+		uint16_t q[nq], *p, *cached;
+		ssize_t ret;
+
+		cached = p = vmalloc(ca->sb.nbuckets * sizeof(uint16_t));
+		if (!p)
+			return -ENOMEM;
+
+		mutex_lock(&ca->set->bucket_lock);
+		for (i = ca->sb.first_bucket; i < n; i++)
+			p[i] = ca->buckets[i].prio;
+		mutex_unlock(&ca->set->bucket_lock);
+
+		sort(p, n, sizeof(uint16_t), cmp, NULL);
+
+		while (n &&
+		       !cached[n - 1])
+			--n;
+
+		unused = ca->sb.nbuckets - n;
+
+		while (cached < p + n &&
+		       *cached == BTREE_PRIO)
+			cached++;
+
+		btree = cached - p;
+		n -= btree;
+
+		for (i = 0; i < n; i++)
+			sum += INITIAL_PRIO - cached[i];
+
+		if (n)
+			do_div(sum, n);
+
+		for (i = 0; i < nq; i++)
+			q[i] = INITIAL_PRIO - cached[n * (i + 1) / (nq + 1)];
+
+		vfree(p);
+
+		ret = snprintf(buf, PAGE_SIZE,
+			       "Unused:		%zu%%\n"
+			       "Metadata:	%zu%%\n"
+			       "Average:	%llu\n"
+			       "Sectors per Q:	%zu\n"
+			       "Quantiles:	[",
+			       unused * 100 / (size_t) ca->sb.nbuckets,
+			       btree * 100 / (size_t) ca->sb.nbuckets, sum,
+			       n * ca->sb.bucket_size / (nq + 1));
+
+		for (i = 0; i < nq && ret < (ssize_t) PAGE_SIZE; i++)
+			ret += snprintf(buf + ret, PAGE_SIZE - ret,
+					i < nq - 1 ? "%u " : "%u]\n", q[i]);
+
+		buf[PAGE_SIZE - 1] = '\0';
+		return ret;
+	}
+
+	return 0;
+}
+SHOW_LOCKED(bch_cache)
+
+STORE(__bch_cache)
+{
+	struct cache *ca = container_of(kobj, struct cache, kobj);
+
+	if (attr == &sysfs_discard) {
+		bool v = strtoul_or_return(buf);
+
+		if (blk_queue_discard(bdev_get_queue(ca->bdev)))
+			ca->discard = v;
+
+		if (v != CACHE_DISCARD(&ca->sb)) {
+			SET_CACHE_DISCARD(&ca->sb, v);
+			bcache_write_super(ca->set);
+		}
+	}
+
+	if (attr == &sysfs_cache_replacement_policy) {
+		ssize_t v = bch_read_string_list(buf, cache_replacement_policies);
+
+		if (v < 0)
+			return v;
+
+		if ((unsigned) v != CACHE_REPLACEMENT(&ca->sb)) {
+			mutex_lock(&ca->set->bucket_lock);
+			SET_CACHE_REPLACEMENT(&ca->sb, v);
+			mutex_unlock(&ca->set->bucket_lock);
+
+			bcache_write_super(ca->set);
+		}
+	}
+
+	if (attr == &sysfs_freelist_percent) {
+		DECLARE_FIFO(long, free);
+		long i;
+		size_t p = strtoul_or_return(buf);
+
+		p = clamp_t(size_t,
+			    ((size_t) ca->sb.nbuckets * p) / 100,
+			    roundup_pow_of_two(ca->sb.nbuckets) >> 9,
+			    ca->sb.nbuckets / 2);
+
+		if (!init_fifo_exact(&free, p, GFP_KERNEL))
+			return -ENOMEM;
+
+		mutex_lock(&ca->set->bucket_lock);
+
+		fifo_move(&free, &ca->free);
+		fifo_swap(&free, &ca->free);
+
+		mutex_unlock(&ca->set->bucket_lock);
+
+		while (fifo_pop(&free, i))
+			atomic_dec(&ca->buckets[i].pin);
+
+		free_fifo(&free);
+	}
+
+	if (attr == &sysfs_clear_stats) {
+		atomic_long_set(&ca->sectors_written, 0);
+		atomic_long_set(&ca->btree_sectors_written, 0);
+		atomic_long_set(&ca->meta_sectors_written, 0);
+		atomic_set(&ca->io_count, 0);
+		atomic_set(&ca->io_errors, 0);
+	}
+
+	return size;
+}
+STORE_LOCKED(bch_cache)
+
+static struct attribute *bch_cache_files[] = {
+	&sysfs_bucket_size,
+	&sysfs_block_size,
+	&sysfs_nbuckets,
+	&sysfs_priority_stats,
+	&sysfs_discard,
+	&sysfs_written,
+	&sysfs_btree_written,
+	&sysfs_metadata_written,
+	&sysfs_io_errors,
+	&sysfs_clear_stats,
+	&sysfs_freelist_percent,
+	&sysfs_cache_replacement_policy,
+	NULL
+};
+KTYPE(bch_cache);
diff --git a/drivers/md/bcache/sysfs.h b/drivers/md/bcache/sysfs.h
new file mode 100644
index 0000000..0526fe9
--- /dev/null
+++ b/drivers/md/bcache/sysfs.h
@@ -0,0 +1,110 @@
+#ifndef _BCACHE_SYSFS_H_
+#define _BCACHE_SYSFS_H_
+
+#define KTYPE(type)							\
+struct kobj_type type ## _ktype = {					\
+	.release	= type ## _release,				\
+	.sysfs_ops	= &((const struct sysfs_ops) {			\
+		.show	= type ## _show,				\
+		.store	= type ## _store				\
+	}),								\
+	.default_attrs	= type ## _files				\
+}
+
+#define SHOW(fn)							\
+static ssize_t fn ## _show(struct kobject *kobj, struct attribute *attr,\
+			   char *buf)					\
+
+#define STORE(fn)							\
+static ssize_t fn ## _store(struct kobject *kobj, struct attribute *attr,\
+			    const char *buf, size_t size)		\
+
+#define SHOW_LOCKED(fn)							\
+SHOW(fn)								\
+{									\
+	ssize_t ret;							\
+	mutex_lock(&bch_register_lock);					\
+	ret = __ ## fn ## _show(kobj, attr, buf);			\
+	mutex_unlock(&bch_register_lock);				\
+	return ret;							\
+}
+
+#define STORE_LOCKED(fn)						\
+STORE(fn)								\
+{									\
+	ssize_t ret;							\
+	mutex_lock(&bch_register_lock);					\
+	ret = __ ## fn ## _store(kobj, attr, buf, size);		\
+	mutex_unlock(&bch_register_lock);				\
+	return ret;							\
+}
+
+#define __sysfs_attribute(_name, _mode)					\
+	static struct attribute sysfs_##_name =				\
+		{ .name = #_name, .mode = _mode }
+
+#define write_attribute(n)	__sysfs_attribute(n, S_IWUSR)
+#define read_attribute(n)	__sysfs_attribute(n, S_IRUGO)
+#define rw_attribute(n)		__sysfs_attribute(n, S_IRUGO|S_IWUSR)
+
+#define sysfs_printf(file, fmt, ...)					\
+do {									\
+	if (attr == &sysfs_ ## file)					\
+		return snprintf(buf, PAGE_SIZE, fmt "\n", __VA_ARGS__);	\
+} while (0)
+
+#define sysfs_print(file, var)						\
+do {									\
+	if (attr == &sysfs_ ## file)					\
+		return snprint(buf, PAGE_SIZE, var);			\
+} while (0)
+
+#define sysfs_hprint(file, val)						\
+do {									\
+	if (attr == &sysfs_ ## file) {					\
+		ssize_t ret = bch_hprint(buf, val);			\
+		strcat(buf, "\n");					\
+		return ret + 1;						\
+	}								\
+} while (0)
+
+#define var_printf(_var, fmt)	sysfs_printf(_var, fmt, var(_var))
+#define var_print(_var)		sysfs_print(_var, var(_var))
+#define var_hprint(_var)	sysfs_hprint(_var, var(_var))
+
+#define sysfs_strtoul(file, var)					\
+do {									\
+	if (attr == &sysfs_ ## file)					\
+		return strtoul_safe(buf, var) ?: (ssize_t) size;	\
+} while (0)
+
+#define sysfs_strtoul_clamp(file, var, min, max)			\
+do {									\
+	if (attr == &sysfs_ ## file)					\
+		return strtoul_safe_clamp(buf, var, min, max)		\
+			?: (ssize_t) size;				\
+} while (0)
+
+#define strtoul_or_return(cp)						\
+({									\
+	unsigned long _v;						\
+	int _r = kstrtoul(cp, 10, &_v);					\
+	if (_r)								\
+		return _r;						\
+	_v;								\
+})
+
+#define strtoi_h_or_return(cp, v)					\
+do {									\
+	int _r = strtoi_h(cp, &v);					\
+	if (_r)								\
+		return _r;						\
+} while (0)
+
+#define sysfs_hatoi(file, var)						\
+do {									\
+	if (attr == &sysfs_ ## file)					\
+		return strtoi_h(buf, &var) ?: (ssize_t) size;		\
+} while (0)
+
+#endif  /* _BCACHE_SYSFS_H_ */
diff --git a/drivers/md/bcache/trace.c b/drivers/md/bcache/trace.c
new file mode 100644
index 0000000..983f9bb
--- /dev/null
+++ b/drivers/md/bcache/trace.c
@@ -0,0 +1,26 @@
+#include "bcache.h"
+#include "btree.h"
+#include "request.h"
+
+#include <linux/module.h>
+
+#define CREATE_TRACE_POINTS
+#include <trace/events/bcache.h>
+
+EXPORT_TRACEPOINT_SYMBOL_GPL(bcache_request_start);
+EXPORT_TRACEPOINT_SYMBOL_GPL(bcache_request_end);
+EXPORT_TRACEPOINT_SYMBOL_GPL(bcache_passthrough);
+EXPORT_TRACEPOINT_SYMBOL_GPL(bcache_cache_hit);
+EXPORT_TRACEPOINT_SYMBOL_GPL(bcache_cache_miss);
+EXPORT_TRACEPOINT_SYMBOL_GPL(bcache_read_retry);
+EXPORT_TRACEPOINT_SYMBOL_GPL(bcache_writethrough);
+EXPORT_TRACEPOINT_SYMBOL_GPL(bcache_writeback);
+EXPORT_TRACEPOINT_SYMBOL_GPL(bcache_write_skip);
+EXPORT_TRACEPOINT_SYMBOL_GPL(bcache_btree_read);
+EXPORT_TRACEPOINT_SYMBOL_GPL(bcache_btree_write);
+EXPORT_TRACEPOINT_SYMBOL_GPL(bcache_write_dirty);
+EXPORT_TRACEPOINT_SYMBOL_GPL(bcache_read_dirty);
+EXPORT_TRACEPOINT_SYMBOL_GPL(bcache_journal_write);
+EXPORT_TRACEPOINT_SYMBOL_GPL(bcache_cache_insert);
+EXPORT_TRACEPOINT_SYMBOL_GPL(bcache_gc_start);
+EXPORT_TRACEPOINT_SYMBOL_GPL(bcache_gc_end);
diff --git a/drivers/md/bcache/util.c b/drivers/md/bcache/util.c
new file mode 100644
index 0000000..22324d8
--- /dev/null
+++ b/drivers/md/bcache/util.c
@@ -0,0 +1,377 @@
+/*
+ * random utiility code, for bcache but in theory not specific to bcache
+ *
+ * Copyright 2010, 2011 Kent Overstreet <kent.overstreet@gmail.com>
+ * Copyright 2012 Google, Inc.
+ */
+
+#include <linux/bio.h>
+#include <linux/blkdev.h>
+#include <linux/ctype.h>
+#include <linux/debugfs.h>
+#include <linux/module.h>
+#include <linux/seq_file.h>
+#include <linux/types.h>
+
+#include "util.h"
+
+#define simple_strtoint(c, end, base)	simple_strtol(c, end, base)
+#define simple_strtouint(c, end, base)	simple_strtoul(c, end, base)
+
+#define STRTO_H(name, type)					\
+int bch_ ## name ## _h(const char *cp, type *res)		\
+{								\
+	int u = 0;						\
+	char *e;						\
+	type i = simple_ ## name(cp, &e, 10);			\
+								\
+	switch (tolower(*e)) {					\
+	default:						\
+		return -EINVAL;					\
+	case 'y':						\
+	case 'z':						\
+		u++;						\
+	case 'e':						\
+		u++;						\
+	case 'p':						\
+		u++;						\
+	case 't':						\
+		u++;						\
+	case 'g':						\
+		u++;						\
+	case 'm':						\
+		u++;						\
+	case 'k':						\
+		u++;						\
+		if (e++ == cp)					\
+			return -EINVAL;				\
+	case '\n':						\
+	case '\0':						\
+		if (*e == '\n')					\
+			e++;					\
+	}							\
+								\
+	if (*e)							\
+		return -EINVAL;					\
+								\
+	while (u--) {						\
+		if ((type) ~0 > 0 &&				\
+		    (type) ~0 / 1024 <= i)			\
+			return -EINVAL;				\
+		if ((i > 0 && ANYSINT_MAX(type) / 1024 < i) ||	\
+		    (i < 0 && -ANYSINT_MAX(type) / 1024 > i))	\
+			return -EINVAL;				\
+		i *= 1024;					\
+	}							\
+								\
+	*res = i;						\
+	return 0;						\
+}								\
+
+STRTO_H(strtoint, int)
+STRTO_H(strtouint, unsigned int)
+STRTO_H(strtoll, long long)
+STRTO_H(strtoull, unsigned long long)
+
+ssize_t bch_hprint(char *buf, int64_t v)
+{
+	static const char units[] = "?kMGTPEZY";
+	char dec[3] = "";
+	int u, t = 0;
+
+	for (u = 0; v >= 1024 || v <= -1024; u++) {
+		t = v & ~(~0 << 10);
+		v >>= 10;
+	}
+
+	if (!u)
+		return sprintf(buf, "%llu", v);
+
+	if (v < 100 && v > -100)
+		sprintf(dec, ".%i", t / 100);
+
+	return sprintf(buf, "%lli%s%c", v, dec, units[u]);
+}
+
+ssize_t bch_snprint_string_list(char *buf, size_t size, const char * const list[],
+			    size_t selected)
+{
+	char *out = buf;
+	size_t i;
+
+	for (i = 0; list[i]; i++)
+		out += snprintf(out, buf + size - out,
+				i == selected ? "[%s] " : "%s ", list[i]);
+
+	out[-1] = '\n';
+	return out - buf;
+}
+
+ssize_t bch_read_string_list(const char *buf, const char * const list[])
+{
+	size_t i;
+	char *s, *d = kstrndup(buf, PAGE_SIZE - 1, GFP_KERNEL);
+	if (!d)
+		return -ENOMEM;
+
+	s = strim(d);
+
+	for (i = 0; list[i]; i++)
+		if (!strcmp(list[i], s))
+			break;
+
+	kfree(d);
+
+	if (!list[i])
+		return -EINVAL;
+
+	return i;
+}
+
+bool bch_is_zero(const char *p, size_t n)
+{
+	size_t i;
+
+	for (i = 0; i < n; i++)
+		if (p[i])
+			return false;
+	return true;
+}
+
+int bch_parse_uuid(const char *s, char *uuid)
+{
+	size_t i, j, x;
+	memset(uuid, 0, 16);
+
+	for (i = 0, j = 0;
+	     i < strspn(s, "-0123456789:ABCDEFabcdef") && j < 32;
+	     i++) {
+		x = s[i] | 32;
+
+		switch (x) {
+		case '0'...'9':
+			x -= '0';
+			break;
+		case 'a'...'f':
+			x -= 'a' - 10;
+			break;
+		default:
+			continue;
+		}
+
+		if (!(j & 1))
+			x <<= 4;
+		uuid[j++ >> 1] |= x;
+	}
+	return i;
+}
+
+void bch_time_stats_update(struct time_stats *stats, uint64_t start_time)
+{
+	uint64_t now		= local_clock();
+	uint64_t duration	= time_after64(now, start_time)
+		? now - start_time : 0;
+	uint64_t last		= time_after64(now, stats->last)
+		? now - stats->last : 0;
+
+	stats->max_duration = max(stats->max_duration, duration);
+
+	if (stats->last) {
+		ewma_add(stats->average_duration, duration, 8, 8);
+
+		if (stats->average_frequency)
+			ewma_add(stats->average_frequency, last, 8, 8);
+		else
+			stats->average_frequency  = last << 8;
+	} else {
+		stats->average_duration  = duration << 8;
+	}
+
+	stats->last = now ?: 1;
+}
+
+unsigned bch_next_delay(struct ratelimit *d, uint64_t done)
+{
+	uint64_t now = local_clock();
+
+	d->next += div_u64(done, d->rate);
+
+	return time_after64(d->next, now)
+		? div_u64(d->next - now, NSEC_PER_SEC / HZ)
+		: 0;
+}
+
+void bch_bio_map(struct bio *bio, void *base)
+{
+	size_t size = bio->bi_size;
+	struct bio_vec *bv = bio->bi_io_vec;
+
+	BUG_ON(!bio->bi_size);
+	BUG_ON(bio->bi_vcnt);
+
+	bv->bv_offset = base ? ((unsigned long) base) % PAGE_SIZE : 0;
+	goto start;
+
+	for (; size; bio->bi_vcnt++, bv++) {
+		bv->bv_offset	= 0;
+start:		bv->bv_len	= min_t(size_t, PAGE_SIZE - bv->bv_offset,
+					size);
+		if (base) {
+			bv->bv_page = is_vmalloc_addr(base)
+				? vmalloc_to_page(base)
+				: virt_to_page(base);
+
+			base += bv->bv_len;
+		}
+
+		size -= bv->bv_len;
+	}
+}
+
+int bch_bio_alloc_pages(struct bio *bio, gfp_t gfp)
+{
+	int i;
+	struct bio_vec *bv;
+
+	bio_for_each_segment(bv, bio, i) {
+		bv->bv_page = alloc_page(gfp);
+		if (!bv->bv_page) {
+			while (bv-- != bio->bi_io_vec + bio->bi_idx)
+				__free_page(bv->bv_page);
+			return -ENOMEM;
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group (Any
+ * use permitted, subject to terms of PostgreSQL license; see.)
+
+ * If we have a 64-bit integer type, then a 64-bit CRC looks just like the
+ * usual sort of implementation. (See Ross Williams' excellent introduction
+ * A PAINLESS GUIDE TO CRC ERROR DETECTION ALGORITHMS, available from
+ * ftp://ftp.rocksoft.com/papers/crc_v3.txt or several other net sites.)
+ * If we have no working 64-bit type, then fake it with two 32-bit registers.
+ *
+ * The present implementation is a normal (not "reflected", in Williams'
+ * terms) 64-bit CRC, using initial all-ones register contents and a final
+ * bit inversion. The chosen polynomial is borrowed from the DLT1 spec
+ * (ECMA-182, available from http://www.ecma.ch/ecma1/STAND/ECMA-182.HTM):
+ *
+ * x^64 + x^62 + x^57 + x^55 + x^54 + x^53 + x^52 + x^47 + x^46 + x^45 +
+ * x^40 + x^39 + x^38 + x^37 + x^35 + x^33 + x^32 + x^31 + x^29 + x^27 +
+ * x^24 + x^23 + x^22 + x^21 + x^19 + x^17 + x^13 + x^12 + x^10 + x^9 +
+ * x^7 + x^4 + x + 1
+*/
+
+static const uint64_t crc_table[256] = {
+	0x0000000000000000, 0x42F0E1EBA9EA3693, 0x85E1C3D753D46D26,
+	0xC711223CFA3E5BB5, 0x493366450E42ECDF, 0x0BC387AEA7A8DA4C,
+	0xCCD2A5925D9681F9, 0x8E224479F47CB76A, 0x9266CC8A1C85D9BE,
+	0xD0962D61B56FEF2D, 0x17870F5D4F51B498, 0x5577EEB6E6BB820B,
+	0xDB55AACF12C73561, 0x99A54B24BB2D03F2, 0x5EB4691841135847,
+	0x1C4488F3E8F96ED4, 0x663D78FF90E185EF, 0x24CD9914390BB37C,
+	0xE3DCBB28C335E8C9, 0xA12C5AC36ADFDE5A, 0x2F0E1EBA9EA36930,
+	0x6DFEFF5137495FA3, 0xAAEFDD6DCD770416, 0xE81F3C86649D3285,
+	0xF45BB4758C645C51, 0xB6AB559E258E6AC2, 0x71BA77A2DFB03177,
+	0x334A9649765A07E4, 0xBD68D2308226B08E, 0xFF9833DB2BCC861D,
+	0x388911E7D1F2DDA8, 0x7A79F00C7818EB3B, 0xCC7AF1FF21C30BDE,
+	0x8E8A101488293D4D, 0x499B3228721766F8, 0x0B6BD3C3DBFD506B,
+	0x854997BA2F81E701, 0xC7B97651866BD192, 0x00A8546D7C558A27,
+	0x4258B586D5BFBCB4, 0x5E1C3D753D46D260, 0x1CECDC9E94ACE4F3,
+	0xDBFDFEA26E92BF46, 0x990D1F49C77889D5, 0x172F5B3033043EBF,
+	0x55DFBADB9AEE082C, 0x92CE98E760D05399, 0xD03E790CC93A650A,
+	0xAA478900B1228E31, 0xE8B768EB18C8B8A2, 0x2FA64AD7E2F6E317,
+	0x6D56AB3C4B1CD584, 0xE374EF45BF6062EE, 0xA1840EAE168A547D,
+	0x66952C92ECB40FC8, 0x2465CD79455E395B, 0x3821458AADA7578F,
+	0x7AD1A461044D611C, 0xBDC0865DFE733AA9, 0xFF3067B657990C3A,
+	0x711223CFA3E5BB50, 0x33E2C2240A0F8DC3, 0xF4F3E018F031D676,
+	0xB60301F359DBE0E5, 0xDA050215EA6C212F, 0x98F5E3FE438617BC,
+	0x5FE4C1C2B9B84C09, 0x1D14202910527A9A, 0x93366450E42ECDF0,
+	0xD1C685BB4DC4FB63, 0x16D7A787B7FAA0D6, 0x5427466C1E109645,
+	0x4863CE9FF6E9F891, 0x0A932F745F03CE02, 0xCD820D48A53D95B7,
+	0x8F72ECA30CD7A324, 0x0150A8DAF8AB144E, 0x43A04931514122DD,
+	0x84B16B0DAB7F7968, 0xC6418AE602954FFB, 0xBC387AEA7A8DA4C0,
+	0xFEC89B01D3679253, 0x39D9B93D2959C9E6, 0x7B2958D680B3FF75,
+	0xF50B1CAF74CF481F, 0xB7FBFD44DD257E8C, 0x70EADF78271B2539,
+	0x321A3E938EF113AA, 0x2E5EB66066087D7E, 0x6CAE578BCFE24BED,
+	0xABBF75B735DC1058, 0xE94F945C9C3626CB, 0x676DD025684A91A1,
+	0x259D31CEC1A0A732, 0xE28C13F23B9EFC87, 0xA07CF2199274CA14,
+	0x167FF3EACBAF2AF1, 0x548F120162451C62, 0x939E303D987B47D7,
+	0xD16ED1D631917144, 0x5F4C95AFC5EDC62E, 0x1DBC74446C07F0BD,
+	0xDAAD56789639AB08, 0x985DB7933FD39D9B, 0x84193F60D72AF34F,
+	0xC6E9DE8B7EC0C5DC, 0x01F8FCB784FE9E69, 0x43081D5C2D14A8FA,
+	0xCD2A5925D9681F90, 0x8FDAB8CE70822903, 0x48CB9AF28ABC72B6,
+	0x0A3B7B1923564425, 0x70428B155B4EAF1E, 0x32B26AFEF2A4998D,
+	0xF5A348C2089AC238, 0xB753A929A170F4AB, 0x3971ED50550C43C1,
+	0x7B810CBBFCE67552, 0xBC902E8706D82EE7, 0xFE60CF6CAF321874,
+	0xE224479F47CB76A0, 0xA0D4A674EE214033, 0x67C58448141F1B86,
+	0x253565A3BDF52D15, 0xAB1721DA49899A7F, 0xE9E7C031E063ACEC,
+	0x2EF6E20D1A5DF759, 0x6C0603E6B3B7C1CA, 0xF6FAE5C07D3274CD,
+	0xB40A042BD4D8425E, 0x731B26172EE619EB, 0x31EBC7FC870C2F78,
+	0xBFC9838573709812, 0xFD39626EDA9AAE81, 0x3A28405220A4F534,
+	0x78D8A1B9894EC3A7, 0x649C294A61B7AD73, 0x266CC8A1C85D9BE0,
+	0xE17DEA9D3263C055, 0xA38D0B769B89F6C6, 0x2DAF4F0F6FF541AC,
+	0x6F5FAEE4C61F773F, 0xA84E8CD83C212C8A, 0xEABE6D3395CB1A19,
+	0x90C79D3FEDD3F122, 0xD2377CD44439C7B1, 0x15265EE8BE079C04,
+	0x57D6BF0317EDAA97, 0xD9F4FB7AE3911DFD, 0x9B041A914A7B2B6E,
+	0x5C1538ADB04570DB, 0x1EE5D94619AF4648, 0x02A151B5F156289C,
+	0x4051B05E58BC1E0F, 0x87409262A28245BA, 0xC5B073890B687329,
+	0x4B9237F0FF14C443, 0x0962D61B56FEF2D0, 0xCE73F427ACC0A965,
+	0x8C8315CC052A9FF6, 0x3A80143F5CF17F13, 0x7870F5D4F51B4980,
+	0xBF61D7E80F251235, 0xFD913603A6CF24A6, 0x73B3727A52B393CC,
+	0x31439391FB59A55F, 0xF652B1AD0167FEEA, 0xB4A25046A88DC879,
+	0xA8E6D8B54074A6AD, 0xEA16395EE99E903E, 0x2D071B6213A0CB8B,
+	0x6FF7FA89BA4AFD18, 0xE1D5BEF04E364A72, 0xA3255F1BE7DC7CE1,
+	0x64347D271DE22754, 0x26C49CCCB40811C7, 0x5CBD6CC0CC10FAFC,
+	0x1E4D8D2B65FACC6F, 0xD95CAF179FC497DA, 0x9BAC4EFC362EA149,
+	0x158E0A85C2521623, 0x577EEB6E6BB820B0, 0x906FC95291867B05,
+	0xD29F28B9386C4D96, 0xCEDBA04AD0952342, 0x8C2B41A1797F15D1,
+	0x4B3A639D83414E64, 0x09CA82762AAB78F7, 0x87E8C60FDED7CF9D,
+	0xC51827E4773DF90E, 0x020905D88D03A2BB, 0x40F9E43324E99428,
+	0x2CFFE7D5975E55E2, 0x6E0F063E3EB46371, 0xA91E2402C48A38C4,
+	0xEBEEC5E96D600E57, 0x65CC8190991CB93D, 0x273C607B30F68FAE,
+	0xE02D4247CAC8D41B, 0xA2DDA3AC6322E288, 0xBE992B5F8BDB8C5C,
+	0xFC69CAB42231BACF, 0x3B78E888D80FE17A, 0x7988096371E5D7E9,
+	0xF7AA4D1A85996083, 0xB55AACF12C735610, 0x724B8ECDD64D0DA5,
+	0x30BB6F267FA73B36, 0x4AC29F2A07BFD00D, 0x08327EC1AE55E69E,
+	0xCF235CFD546BBD2B, 0x8DD3BD16FD818BB8, 0x03F1F96F09FD3CD2,
+	0x41011884A0170A41, 0x86103AB85A2951F4, 0xC4E0DB53F3C36767,
+	0xD8A453A01B3A09B3, 0x9A54B24BB2D03F20, 0x5D45907748EE6495,
+	0x1FB5719CE1045206, 0x919735E51578E56C, 0xD367D40EBC92D3FF,
+	0x1476F63246AC884A, 0x568617D9EF46BED9, 0xE085162AB69D5E3C,
+	0xA275F7C11F7768AF, 0x6564D5FDE549331A, 0x279434164CA30589,
+	0xA9B6706FB8DFB2E3, 0xEB46918411358470, 0x2C57B3B8EB0BDFC5,
+	0x6EA7525342E1E956, 0x72E3DAA0AA188782, 0x30133B4B03F2B111,
+	0xF7021977F9CCEAA4, 0xB5F2F89C5026DC37, 0x3BD0BCE5A45A6B5D,
+	0x79205D0E0DB05DCE, 0xBE317F32F78E067B, 0xFCC19ED95E6430E8,
+	0x86B86ED5267CDBD3, 0xC4488F3E8F96ED40, 0x0359AD0275A8B6F5,
+	0x41A94CE9DC428066, 0xCF8B0890283E370C, 0x8D7BE97B81D4019F,
+	0x4A6ACB477BEA5A2A, 0x089A2AACD2006CB9, 0x14DEA25F3AF9026D,
+	0x562E43B4931334FE, 0x913F6188692D6F4B, 0xD3CF8063C0C759D8,
+	0x5DEDC41A34BBEEB2, 0x1F1D25F19D51D821, 0xD80C07CD676F8394,
+	0x9AFCE626CE85B507
+};
+
+uint64_t bch_crc64_update(uint64_t crc, const void *_data, size_t len)
+{
+	const unsigned char *data = _data;
+
+	while (len--) {
+		int i = ((int) (crc >> 56) ^ *data++) & 0xFF;
+		crc = crc_table[i] ^ (crc << 8);
+	}
+
+	return crc;
+}
+
+uint64_t bch_crc64(const void *data, size_t len)
+{
+	uint64_t crc = 0xffffffffffffffff;
+
+	crc = bch_crc64_update(crc, data, len);
+
+	return crc ^ 0xffffffffffffffff;
+}
diff --git a/drivers/md/bcache/util.h b/drivers/md/bcache/util.h
new file mode 100644
index 0000000..577393e
--- /dev/null
+++ b/drivers/md/bcache/util.h
@@ -0,0 +1,589 @@
+
+#ifndef _BCACHE_UTIL_H
+#define _BCACHE_UTIL_H
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/llist.h>
+#include <linux/ratelimit.h>
+#include <linux/vmalloc.h>
+#include <linux/workqueue.h>
+
+#include "closure.h"
+
+#define PAGE_SECTORS		(PAGE_SIZE / 512)
+
+struct closure;
+
+#include <trace/events/bcache.h>
+
+#ifdef CONFIG_BCACHE_EDEBUG
+
+#define atomic_dec_bug(v)	BUG_ON(atomic_dec_return(v) < 0)
+#define atomic_inc_bug(v, i)	BUG_ON(atomic_inc_return(v) <= i)
+
+#else /* EDEBUG */
+
+#define atomic_dec_bug(v)	atomic_dec(v)
+#define atomic_inc_bug(v, i)	atomic_inc(v)
+
+#endif
+
+#define BITMASK(name, type, field, offset, size)		\
+static inline uint64_t name(const type *k)			\
+{ return (k->field >> offset) & ~(((uint64_t) ~0) << size); }	\
+								\
+static inline void SET_##name(type *k, uint64_t v)		\
+{								\
+	k->field &= ~(~((uint64_t) ~0 << size) << offset);	\
+	k->field |= v << offset;				\
+}
+
+#define DECLARE_HEAP(type, name)					\
+	struct {							\
+		size_t size, used;					\
+		type *data;						\
+	} name
+
+#define init_heap(heap, _size, gfp)					\
+({									\
+	size_t _bytes;							\
+	(heap)->used = 0;						\
+	(heap)->size = (_size);						\
+	_bytes = (heap)->size * sizeof(*(heap)->data);			\
+	(heap)->data = NULL;						\
+	if (_bytes < KMALLOC_MAX_SIZE)					\
+		(heap)->data = kmalloc(_bytes, (gfp));			\
+	if ((!(heap)->data) && ((gfp) & GFP_KERNEL))			\
+		(heap)->data = vmalloc(_bytes);				\
+	(heap)->data;							\
+})
+
+#define free_heap(heap)							\
+do {									\
+	if (is_vmalloc_addr((heap)->data))				\
+		vfree((heap)->data);					\
+	else								\
+		kfree((heap)->data);					\
+	(heap)->data = NULL;						\
+} while (0)
+
+#define heap_swap(h, i, j)	swap((h)->data[i], (h)->data[j])
+
+#define heap_sift(h, i, cmp)						\
+do {									\
+	size_t _r, _j = i;						\
+									\
+	for (; _j * 2 + 1 < (h)->used; _j = _r) {			\
+		_r = _j * 2 + 1;					\
+		if (_r + 1 < (h)->used &&				\
+		    cmp((h)->data[_r], (h)->data[_r + 1]))		\
+			_r++;						\
+									\
+		if (cmp((h)->data[_r], (h)->data[_j]))			\
+			break;						\
+		heap_swap(h, _r, _j);					\
+	}								\
+} while (0)
+
+#define heap_sift_down(h, i, cmp)					\
+do {									\
+	while (i) {							\
+		size_t p = (i - 1) / 2;					\
+		if (cmp((h)->data[i], (h)->data[p]))			\
+			break;						\
+		heap_swap(h, i, p);					\
+		i = p;							\
+	}								\
+} while (0)
+
+#define heap_add(h, d, cmp)						\
+({									\
+	bool _r = !heap_full(h);					\
+	if (_r) {							\
+		size_t _i = (h)->used++;				\
+		(h)->data[_i] = d;					\
+									\
+		heap_sift_down(h, _i, cmp);				\
+		heap_sift(h, _i, cmp);					\
+	}								\
+	_r;								\
+})
+
+#define heap_pop(h, d, cmp)						\
+({									\
+	bool _r = (h)->used;						\
+	if (_r) {							\
+		(d) = (h)->data[0];					\
+		(h)->used--;						\
+		heap_swap(h, 0, (h)->used);				\
+		heap_sift(h, 0, cmp);					\
+	}								\
+	_r;								\
+})
+
+#define heap_peek(h)	((h)->size ? (h)->data[0] : NULL)
+
+#define heap_full(h)	((h)->used == (h)->size)
+
+#define DECLARE_FIFO(type, name)					\
+	struct {							\
+		size_t front, back, size, mask;				\
+		type *data;						\
+	} name
+
+#define fifo_for_each(c, fifo, iter)					\
+	for (iter = (fifo)->front;					\
+	     c = (fifo)->data[iter], iter != (fifo)->back;		\
+	     iter = (iter + 1) & (fifo)->mask)
+
+#define __init_fifo(fifo, gfp)						\
+({									\
+	size_t _allocated_size, _bytes;					\
+	BUG_ON(!(fifo)->size);						\
+									\
+	_allocated_size = roundup_pow_of_two((fifo)->size + 1);		\
+	_bytes = _allocated_size * sizeof(*(fifo)->data);		\
+									\
+	(fifo)->mask = _allocated_size - 1;				\
+	(fifo)->front = (fifo)->back = 0;				\
+	(fifo)->data = NULL;						\
+									\
+	if (_bytes < KMALLOC_MAX_SIZE)					\
+		(fifo)->data = kmalloc(_bytes, (gfp));			\
+	if ((!(fifo)->data) && ((gfp) & GFP_KERNEL))			\
+		(fifo)->data = vmalloc(_bytes);				\
+	(fifo)->data;							\
+})
+
+#define init_fifo_exact(fifo, _size, gfp)				\
+({									\
+	(fifo)->size = (_size);						\
+	__init_fifo(fifo, gfp);						\
+})
+
+#define init_fifo(fifo, _size, gfp)					\
+({									\
+	(fifo)->size = (_size);						\
+	if ((fifo)->size > 4)						\
+		(fifo)->size = roundup_pow_of_two((fifo)->size) - 1;	\
+	__init_fifo(fifo, gfp);						\
+})
+
+#define free_fifo(fifo)							\
+do {									\
+	if (is_vmalloc_addr((fifo)->data))				\
+		vfree((fifo)->data);					\
+	else								\
+		kfree((fifo)->data);					\
+	(fifo)->data = NULL;						\
+} while (0)
+
+#define fifo_used(fifo)		(((fifo)->back - (fifo)->front) & (fifo)->mask)
+#define fifo_free(fifo)		((fifo)->size - fifo_used(fifo))
+
+#define fifo_empty(fifo)	(!fifo_used(fifo))
+#define fifo_full(fifo)		(!fifo_free(fifo))
+
+#define fifo_front(fifo)	((fifo)->data[(fifo)->front])
+#define fifo_back(fifo)							\
+	((fifo)->data[((fifo)->back - 1) & (fifo)->mask])
+
+#define fifo_idx(fifo, p)	(((p) - &fifo_front(fifo)) & (fifo)->mask)
+
+#define fifo_push_back(fifo, i)						\
+({									\
+	bool _r = !fifo_full((fifo));					\
+	if (_r) {							\
+		(fifo)->data[(fifo)->back++] = (i);			\
+		(fifo)->back &= (fifo)->mask;				\
+	}								\
+	_r;								\
+})
+
+#define fifo_pop_front(fifo, i)						\
+({									\
+	bool _r = !fifo_empty((fifo));					\
+	if (_r) {							\
+		(i) = (fifo)->data[(fifo)->front++];			\
+		(fifo)->front &= (fifo)->mask;				\
+	}								\
+	_r;								\
+})
+
+#define fifo_push_front(fifo, i)					\
+({									\
+	bool _r = !fifo_full((fifo));					\
+	if (_r) {							\
+		--(fifo)->front;					\
+		(fifo)->front &= (fifo)->mask;				\
+		(fifo)->data[(fifo)->front] = (i);			\
+	}								\
+	_r;								\
+})
+
+#define fifo_pop_back(fifo, i)						\
+({									\
+	bool _r = !fifo_empty((fifo));					\
+	if (_r) {							\
+		--(fifo)->back;						\
+		(fifo)->back &= (fifo)->mask;				\
+		(i) = (fifo)->data[(fifo)->back]			\
+	}								\
+	_r;								\
+})
+
+#define fifo_push(fifo, i)	fifo_push_back(fifo, (i))
+#define fifo_pop(fifo, i)	fifo_pop_front(fifo, (i))
+
+#define fifo_swap(l, r)							\
+do {									\
+	swap((l)->front, (r)->front);					\
+	swap((l)->back, (r)->back);					\
+	swap((l)->size, (r)->size);					\
+	swap((l)->mask, (r)->mask);					\
+	swap((l)->data, (r)->data);					\
+} while (0)
+
+#define fifo_move(dest, src)						\
+do {									\
+	typeof(*((dest)->data)) _t;					\
+	while (!fifo_full(dest) &&					\
+	       fifo_pop(src, _t))					\
+		fifo_push(dest, _t);					\
+} while (0)
+
+/*
+ * Simple array based allocator - preallocates a number of elements and you can
+ * never allocate more than that, also has no locking.
+ *
+ * Handy because if you know you only need a fixed number of elements you don't
+ * have to worry about memory allocation failure, and sometimes a mempool isn't
+ * what you want.
+ *
+ * We treat the free elements as entries in a singly linked list, and the
+ * freelist as a stack - allocating and freeing push and pop off the freelist.
+ */
+
+#define DECLARE_ARRAY_ALLOCATOR(type, name, size)			\
+	struct {							\
+		type	*freelist;					\
+		type	data[size];					\
+	} name
+
+#define array_alloc(array)						\
+({									\
+	typeof((array)->freelist) _ret = (array)->freelist;		\
+									\
+	if (_ret)							\
+		(array)->freelist = *((typeof((array)->freelist) *) _ret);\
+									\
+	_ret;								\
+})
+
+#define array_free(array, ptr)						\
+do {									\
+	typeof((array)->freelist) _ptr = ptr;				\
+									\
+	*((typeof((array)->freelist) *) _ptr) = (array)->freelist;	\
+	(array)->freelist = _ptr;					\
+} while (0)
+
+#define array_allocator_init(array)					\
+do {									\
+	typeof((array)->freelist) _i;					\
+									\
+	BUILD_BUG_ON(sizeof((array)->data[0]) < sizeof(void *));	\
+	(array)->freelist = NULL;					\
+									\
+	for (_i = (array)->data;					\
+	     _i < (array)->data + ARRAY_SIZE((array)->data);		\
+	     _i++)							\
+		array_free(array, _i);					\
+} while (0)
+
+#define array_freelist_empty(array)	((array)->freelist == NULL)
+
+#define ANYSINT_MAX(t)							\
+	((((t) 1 << (sizeof(t) * 8 - 2)) - (t) 1) * (t) 2 + (t) 1)
+
+int bch_strtoint_h(const char *, int *);
+int bch_strtouint_h(const char *, unsigned int *);
+int bch_strtoll_h(const char *, long long *);
+int bch_strtoull_h(const char *, unsigned long long *);
+
+static inline int bch_strtol_h(const char *cp, long *res)
+{
+#if BITS_PER_LONG == 32
+	return bch_strtoint_h(cp, (int *) res);
+#else
+	return bch_strtoll_h(cp, (long long *) res);
+#endif
+}
+
+static inline int bch_strtoul_h(const char *cp, long *res)
+{
+#if BITS_PER_LONG == 32
+	return bch_strtouint_h(cp, (unsigned int *) res);
+#else
+	return bch_strtoull_h(cp, (unsigned long long *) res);
+#endif
+}
+
+#define strtoi_h(cp, res)						\
+	(__builtin_types_compatible_p(typeof(*res), int)		\
+	? bch_strtoint_h(cp, (void *) res)				\
+	: __builtin_types_compatible_p(typeof(*res), long)		\
+	? bch_strtol_h(cp, (void *) res)				\
+	: __builtin_types_compatible_p(typeof(*res), long long)		\
+	? bch_strtoll_h(cp, (void *) res)				\
+	: __builtin_types_compatible_p(typeof(*res), unsigned int)	\
+	? bch_strtouint_h(cp, (void *) res)				\
+	: __builtin_types_compatible_p(typeof(*res), unsigned long)	\
+	? bch_strtoul_h(cp, (void *) res)				\
+	: __builtin_types_compatible_p(typeof(*res), unsigned long long)\
+	? bch_strtoull_h(cp, (void *) res) : -EINVAL)
+
+#define strtoul_safe(cp, var)						\
+({									\
+	unsigned long _v;						\
+	int _r = kstrtoul(cp, 10, &_v);					\
+	if (!_r)							\
+		var = _v;						\
+	_r;								\
+})
+
+#define strtoul_safe_clamp(cp, var, min, max)				\
+({									\
+	unsigned long _v;						\
+	int _r = kstrtoul(cp, 10, &_v);					\
+	if (!_r)							\
+		var = clamp_t(typeof(var), _v, min, max);		\
+	_r;								\
+})
+
+#define snprint(buf, size, var)						\
+	snprintf(buf, size,						\
+		__builtin_types_compatible_p(typeof(var), int)		\
+		     ? "%i\n" :						\
+		__builtin_types_compatible_p(typeof(var), unsigned)	\
+		     ? "%u\n" :						\
+		__builtin_types_compatible_p(typeof(var), long)		\
+		     ? "%li\n" :					\
+		__builtin_types_compatible_p(typeof(var), unsigned long)\
+		     ? "%lu\n" :					\
+		__builtin_types_compatible_p(typeof(var), int64_t)	\
+		     ? "%lli\n" :					\
+		__builtin_types_compatible_p(typeof(var), uint64_t)	\
+		     ? "%llu\n" :					\
+		__builtin_types_compatible_p(typeof(var), const char *)	\
+		     ? "%s\n" : "%i\n", var)
+
+ssize_t bch_hprint(char *buf, int64_t v);
+
+bool bch_is_zero(const char *p, size_t n);
+int bch_parse_uuid(const char *s, char *uuid);
+
+ssize_t bch_snprint_string_list(char *buf, size_t size, const char * const list[],
+			    size_t selected);
+
+ssize_t bch_read_string_list(const char *buf, const char * const list[]);
+
+struct time_stats {
+	/*
+	 * all fields are in nanoseconds, averages are ewmas stored left shifted
+	 * by 8
+	 */
+	uint64_t	max_duration;
+	uint64_t	average_duration;
+	uint64_t	average_frequency;
+	uint64_t	last;
+};
+
+void bch_time_stats_update(struct time_stats *stats, uint64_t time);
+
+#define NSEC_PER_ns			1L
+#define NSEC_PER_us			NSEC_PER_USEC
+#define NSEC_PER_ms			NSEC_PER_MSEC
+#define NSEC_PER_sec			NSEC_PER_SEC
+
+#define __print_time_stat(stats, name, stat, units)			\
+	sysfs_print(name ## _ ## stat ## _ ## units,			\
+		    div_u64((stats)->stat >> 8, NSEC_PER_ ## units))
+
+#define sysfs_print_time_stats(stats, name,				\
+			       frequency_units,				\
+			       duration_units)				\
+do {									\
+	__print_time_stat(stats, name,					\
+			  average_frequency,	frequency_units);	\
+	__print_time_stat(stats, name,					\
+			  average_duration,	duration_units);	\
+	__print_time_stat(stats, name,					\
+			  max_duration,		duration_units);	\
+									\
+	sysfs_print(name ## _last_ ## frequency_units, (stats)->last	\
+		    ? div_s64(local_clock() - (stats)->last,		\
+			      NSEC_PER_ ## frequency_units)		\
+		    : -1LL);						\
+} while (0)
+
+#define sysfs_time_stats_attribute(name,				\
+				   frequency_units,			\
+				   duration_units)			\
+read_attribute(name ## _average_frequency_ ## frequency_units);		\
+read_attribute(name ## _average_duration_ ## duration_units);		\
+read_attribute(name ## _max_duration_ ## duration_units);		\
+read_attribute(name ## _last_ ## frequency_units)
+
+#define sysfs_time_stats_attribute_list(name,				\
+					frequency_units,		\
+					duration_units)			\
+&sysfs_ ## name ## _average_frequency_ ## frequency_units,		\
+&sysfs_ ## name ## _average_duration_ ## duration_units,		\
+&sysfs_ ## name ## _max_duration_ ## duration_units,			\
+&sysfs_ ## name ## _last_ ## frequency_units,
+
+#define ewma_add(ewma, val, weight, factor)				\
+({									\
+	(ewma) *= (weight) - 1;						\
+	(ewma) += (val) << factor;					\
+	(ewma) /= (weight);						\
+	(ewma) >> factor;						\
+})
+
+struct ratelimit {
+	uint64_t		next;
+	unsigned		rate;
+};
+
+static inline void ratelimit_reset(struct ratelimit *d)
+{
+	d->next = local_clock();
+}
+
+unsigned bch_next_delay(struct ratelimit *d, uint64_t done);
+
+#define __DIV_SAFE(n, d, zero)						\
+({									\
+	typeof(n) _n = (n);						\
+	typeof(d) _d = (d);						\
+	_d ? _n / _d : zero;						\
+})
+
+#define DIV_SAFE(n, d)	__DIV_SAFE(n, d, 0)
+
+#define container_of_or_null(ptr, type, member)				\
+({									\
+	typeof(ptr) _ptr = ptr;						\
+	_ptr ? container_of(_ptr, type, member) : NULL;			\
+})
+
+#define RB_INSERT(root, new, member, cmp)				\
+({									\
+	__label__ dup;							\
+	struct rb_node **n = &(root)->rb_node, *parent = NULL;		\
+	typeof(new) this;						\
+	int res, ret = -1;						\
+									\
+	while (*n) {							\
+		parent = *n;						\
+		this = container_of(*n, typeof(*(new)), member);	\
+		res = cmp(new, this);					\
+		if (!res)						\
+			goto dup;					\
+		n = res < 0						\
+			? &(*n)->rb_left				\
+			: &(*n)->rb_right;				\
+	}								\
+									\
+	rb_link_node(&(new)->member, parent, n);			\
+	rb_insert_color(&(new)->member, root);				\
+	ret = 0;							\
+dup:									\
+	ret;								\
+})
+
+#define RB_SEARCH(root, search, member, cmp)				\
+({									\
+	struct rb_node *n = (root)->rb_node;				\
+	typeof(&(search)) this, ret = NULL;				\
+	int res;							\
+									\
+	while (n) {							\
+		this = container_of(n, typeof(search), member);		\
+		res = cmp(&(search), this);				\
+		if (!res) {						\
+			ret = this;					\
+			break;						\
+		}							\
+		n = res < 0						\
+			? n->rb_left					\
+			: n->rb_right;					\
+	}								\
+	ret;								\
+})
+
+#define RB_GREATER(root, search, member, cmp)				\
+({									\
+	struct rb_node *n = (root)->rb_node;				\
+	typeof(&(search)) this, ret = NULL;				\
+	int res;							\
+									\
+	while (n) {							\
+		this = container_of(n, typeof(search), member);		\
+		res = cmp(&(search), this);				\
+		if (res < 0) {						\
+			ret = this;					\
+			n = n->rb_left;					\
+		} else							\
+			n = n->rb_right;				\
+	}								\
+	ret;								\
+})
+
+#define RB_FIRST(root, type, member)					\
+	container_of_or_null(rb_first(root), type, member)
+
+#define RB_LAST(root, type, member)					\
+	container_of_or_null(rb_last(root), type, member)
+
+#define RB_NEXT(ptr, member)						\
+	container_of_or_null(rb_next(&(ptr)->member), typeof(*ptr), member)
+
+#define RB_PREV(ptr, member)						\
+	container_of_or_null(rb_prev(&(ptr)->member), typeof(*ptr), member)
+
+/* Does linear interpolation between powers of two */
+static inline unsigned fract_exp_two(unsigned x, unsigned fract_bits)
+{
+	unsigned fract = x & ~(~0 << fract_bits);
+
+	x >>= fract_bits;
+	x   = 1 << x;
+	x  += (x * fract) >> fract_bits;
+
+	return x;
+}
+
+#define bio_end(bio)	((bio)->bi_sector + bio_sectors(bio))
+
+void bch_bio_map(struct bio *bio, void *base);
+
+int bch_bio_alloc_pages(struct bio *bio, gfp_t gfp);
+
+static inline sector_t bdev_sectors(struct block_device *bdev)
+{
+	return bdev->bd_inode->i_size >> 9;
+}
+
+#define closure_bio_submit(bio, cl, dev)				\
+do {									\
+	closure_get(cl);						\
+	bch_generic_make_request(bio, &(dev)->bio_split_hook);		\
+} while (0)
+
+uint64_t bch_crc64_update(uint64_t, const void *, size_t);
+uint64_t bch_crc64(const void *, size_t);
+
+#endif /* _BCACHE_UTIL_H */
diff --git a/drivers/md/bcache/writeback.c b/drivers/md/bcache/writeback.c
new file mode 100644
index 0000000..daf9347
--- /dev/null
+++ b/drivers/md/bcache/writeback.c
@@ -0,0 +1,416 @@
+/*
+ * background writeback - scan btree for dirty data and write it to the backing
+ * device
+ *
+ * Copyright 2010, 2011 Kent Overstreet <kent.overstreet@gmail.com>
+ * Copyright 2012 Google, Inc.
+ */
+
+#include "bcache.h"
+#include "btree.h"
+#include "debug.h"
+
+static struct workqueue_struct *dirty_wq;
+
+static void read_dirty(struct closure *);
+
+struct dirty_io {
+	struct closure		cl;
+	struct cached_dev	*dc;
+	struct bio		bio;
+};
+
+/* Rate limiting */
+
+static void __update_writeback_rate(struct cached_dev *dc)
+{
+	struct cache_set *c = dc->disk.c;
+	uint64_t cache_sectors = c->nbuckets * c->sb.bucket_size;
+	uint64_t cache_dirty_target =
+		div_u64(cache_sectors * dc->writeback_percent, 100);
+
+	int64_t target = div64_u64(cache_dirty_target * bdev_sectors(dc->bdev),
+				   c->cached_dev_sectors);
+
+	/* PD controller */
+
+	int change = 0;
+	int64_t error;
+	int64_t dirty = atomic_long_read(&dc->disk.sectors_dirty);
+	int64_t derivative = dirty - dc->disk.sectors_dirty_last;
+
+	dc->disk.sectors_dirty_last = dirty;
+
+	derivative *= dc->writeback_rate_d_term;
+	derivative = clamp(derivative, -dirty, dirty);
+
+	derivative = ewma_add(dc->disk.sectors_dirty_derivative, derivative,
+			      dc->writeback_rate_d_smooth, 0);
+
+	/* Avoid divide by zero */
+	if (!target)
+		goto out;
+
+	error = div64_s64((dirty + derivative - target) << 8, target);
+
+	change = div_s64((dc->writeback_rate.rate * error) >> 8,
+			 dc->writeback_rate_p_term_inverse);
+
+	/* Don't increase writeback rate if the device isn't keeping up */
+	if (change > 0 &&
+	    time_after64(local_clock(),
+			 dc->writeback_rate.next + 10 * NSEC_PER_MSEC))
+		change = 0;
+
+	dc->writeback_rate.rate =
+		clamp_t(int64_t, dc->writeback_rate.rate + change,
+			1, NSEC_PER_MSEC);
+out:
+	dc->writeback_rate_derivative = derivative;
+	dc->writeback_rate_change = change;
+	dc->writeback_rate_target = target;
+
+	schedule_delayed_work(&dc->writeback_rate_update,
+			      dc->writeback_rate_update_seconds * HZ);
+}
+
+static void update_writeback_rate(struct work_struct *work)
+{
+	struct cached_dev *dc = container_of(to_delayed_work(work),
+					     struct cached_dev,
+					     writeback_rate_update);
+
+	down_read(&dc->writeback_lock);
+
+	if (atomic_read(&dc->has_dirty) &&
+	    dc->writeback_percent)
+		__update_writeback_rate(dc);
+
+	up_read(&dc->writeback_lock);
+}
+
+static unsigned writeback_delay(struct cached_dev *dc, unsigned sectors)
+{
+	if (atomic_read(&dc->disk.detaching) ||
+	    !dc->writeback_percent)
+		return 0;
+
+	return bch_next_delay(&dc->writeback_rate, sectors * 10000000ULL);
+}
+
+/* Background writeback */
+
+static bool dirty_pred(struct keybuf *buf, struct bkey *k)
+{
+	return KEY_DIRTY(k);
+}
+
+static void dirty_init(struct keybuf_key *w)
+{
+	struct dirty_io *io = w->private;
+	struct bio *bio = &io->bio;
+
+	bio_init(bio);
+	if (!io->dc->writeback_percent)
+		bio_set_prio(bio, IOPRIO_PRIO_VALUE(IOPRIO_CLASS_IDLE, 0));
+
+	bio->bi_size		= KEY_SIZE(&w->key) << 9;
+	bio->bi_max_vecs	= DIV_ROUND_UP(KEY_SIZE(&w->key), PAGE_SECTORS);
+	bio->bi_private		= w;
+	bio->bi_io_vec		= bio->bi_inline_vecs;
+	bch_bio_map(bio, NULL);
+}
+
+static void refill_dirty(struct closure *cl)
+{
+	struct cached_dev *dc = container_of(cl, struct cached_dev,
+					     writeback.cl);
+	struct keybuf *buf = &dc->writeback_keys;
+	bool searched_from_start = false;
+	struct bkey end = MAX_KEY;
+	SET_KEY_INODE(&end, dc->disk.id);
+
+	if (!atomic_read(&dc->disk.detaching) &&
+	    !dc->writeback_running)
+		closure_return(cl);
+
+	down_write(&dc->writeback_lock);
+
+	if (!atomic_read(&dc->has_dirty)) {
+		SET_BDEV_STATE(&dc->sb, BDEV_STATE_CLEAN);
+		bch_write_bdev_super(dc, NULL);
+
+		up_write(&dc->writeback_lock);
+		closure_return(cl);
+	}
+
+	if (bkey_cmp(&buf->last_scanned, &end) >= 0) {
+		buf->last_scanned = KEY(dc->disk.id, 0, 0);
+		searched_from_start = true;
+	}
+
+	bch_refill_keybuf(dc->disk.c, buf, &end);
+
+	if (bkey_cmp(&buf->last_scanned, &end) >= 0 && searched_from_start) {
+		/* Searched the entire btree  - delay awhile */
+
+		if (RB_EMPTY_ROOT(&buf->keys)) {
+			atomic_set(&dc->has_dirty, 0);
+			cached_dev_put(dc);
+		}
+
+		if (!atomic_read(&dc->disk.detaching))
+			closure_delay(&dc->writeback, dc->writeback_delay * HZ);
+	}
+
+	up_write(&dc->writeback_lock);
+
+	ratelimit_reset(&dc->writeback_rate);
+
+	/* Punt to workqueue only so we don't recurse and blow the stack */
+	continue_at(cl, read_dirty, dirty_wq);
+}
+
+void bch_writeback_queue(struct cached_dev *dc)
+{
+	if (closure_trylock(&dc->writeback.cl, &dc->disk.cl)) {
+		if (!atomic_read(&dc->disk.detaching))
+			closure_delay(&dc->writeback, dc->writeback_delay * HZ);
+
+		continue_at(&dc->writeback.cl, refill_dirty, dirty_wq);
+	}
+}
+
+void bch_writeback_add(struct cached_dev *dc, unsigned sectors)
+{
+	atomic_long_add(sectors, &dc->disk.sectors_dirty);
+
+	if (!atomic_read(&dc->has_dirty) &&
+	    !atomic_xchg(&dc->has_dirty, 1)) {
+		atomic_inc(&dc->count);
+
+		if (BDEV_STATE(&dc->sb) != BDEV_STATE_DIRTY) {
+			SET_BDEV_STATE(&dc->sb, BDEV_STATE_DIRTY);
+			/* XXX: should do this synchronously */
+			bch_write_bdev_super(dc, NULL);
+		}
+
+		bch_writeback_queue(dc);
+
+		if (dc->writeback_percent)
+			schedule_delayed_work(&dc->writeback_rate_update,
+				      dc->writeback_rate_update_seconds * HZ);
+	}
+}
+
+/* Background writeback - IO loop */
+
+static void dirty_io_destructor(struct closure *cl)
+{
+	struct dirty_io *io = container_of(cl, struct dirty_io, cl);
+	kfree(io);
+}
+
+static void write_dirty_finish(struct closure *cl)
+{
+	struct dirty_io *io = container_of(cl, struct dirty_io, cl);
+	struct keybuf_key *w = io->bio.bi_private;
+	struct cached_dev *dc = io->dc;
+	struct bio_vec *bv = bio_iovec_idx(&io->bio, io->bio.bi_vcnt);
+
+	while (bv-- != io->bio.bi_io_vec)
+		__free_page(bv->bv_page);
+
+	/* This is kind of a dumb way of signalling errors. */
+	if (KEY_DIRTY(&w->key)) {
+		unsigned i;
+		struct btree_op op;
+		bch_btree_op_init_stack(&op);
+
+		op.type = BTREE_REPLACE;
+		bkey_copy(&op.replace, &w->key);
+
+		SET_KEY_DIRTY(&w->key, false);
+		bch_keylist_add(&op.keys, &w->key);
+
+		for (i = 0; i < KEY_PTRS(&w->key); i++)
+			atomic_inc(&PTR_BUCKET(dc->disk.c, &w->key, i)->pin);
+
+		pr_debug("clearing %s", pkey(&w->key));
+		bch_btree_insert(&op, dc->disk.c);
+		closure_sync(&op.cl);
+
+		atomic_long_inc(op.insert_collision
+				? &dc->disk.c->writeback_keys_failed
+				: &dc->disk.c->writeback_keys_done);
+	}
+
+	bch_keybuf_del(&dc->writeback_keys, w);
+	atomic_dec_bug(&dc->in_flight);
+
+	closure_wake_up(&dc->writeback_wait);
+
+	closure_return_with_destructor(cl, dirty_io_destructor);
+}
+
+static void dirty_endio(struct bio *bio, int error,
+			struct batch_complete *batch)
+{
+	struct keybuf_key *w = bio->bi_private;
+	struct dirty_io *io = w->private;
+
+	if (error)
+		SET_KEY_DIRTY(&w->key, false);
+
+	closure_put(&io->cl);
+}
+
+static void write_dirty(struct closure *cl)
+{
+	struct dirty_io *io = container_of(cl, struct dirty_io, cl);
+	struct keybuf_key *w = io->bio.bi_private;
+
+	dirty_init(w);
+	io->bio.bi_rw		= WRITE;
+	io->bio.bi_sector	= KEY_START(&w->key);
+	io->bio.bi_bdev		= io->dc->bdev;
+	io->bio.bi_end_io	= dirty_endio;
+
+	trace_bcache_write_dirty(&io->bio);
+	closure_bio_submit(&io->bio, cl, &io->dc->disk);
+
+	continue_at(cl, write_dirty_finish, dirty_wq);
+}
+
+static void read_dirty_endio(struct bio *bio, int error,
+			     struct batch_complete *batch)
+{
+	struct keybuf_key *w = bio->bi_private;
+	struct dirty_io *io = w->private;
+
+	bch_count_io_errors(PTR_CACHE(io->dc->disk.c, &w->key, 0),
+			    error, "reading dirty data from cache");
+
+	dirty_endio(bio, error, NULL);
+}
+
+static void read_dirty_submit(struct closure *cl)
+{
+	struct dirty_io *io = container_of(cl, struct dirty_io, cl);
+
+	trace_bcache_read_dirty(&io->bio);
+	closure_bio_submit(&io->bio, cl, &io->dc->disk);
+
+	continue_at(cl, write_dirty, dirty_wq);
+}
+
+static void read_dirty(struct closure *cl)
+{
+	struct cached_dev *dc = container_of(cl, struct cached_dev,
+					     writeback.cl);
+	unsigned delay = writeback_delay(dc, 0);
+	struct keybuf_key *w;
+	struct dirty_io *io;
+
+	/*
+	 * XXX: if we error, background writeback just spins. Should use some
+	 * mempools.
+	 */
+
+	while (1) {
+		w = bch_keybuf_next(&dc->writeback_keys);
+		if (!w)
+			break;
+
+		BUG_ON(ptr_stale(dc->disk.c, &w->key, 0));
+
+		if (delay > 0 &&
+		    (KEY_START(&w->key) != dc->last_read ||
+		     jiffies_to_msecs(delay) > 50)) {
+			w->private = NULL;
+
+			closure_delay(&dc->writeback, delay);
+			continue_at(cl, read_dirty, dirty_wq);
+		}
+
+		dc->last_read	= KEY_OFFSET(&w->key);
+
+		io = kzalloc(sizeof(struct dirty_io) + sizeof(struct bio_vec)
+			     * DIV_ROUND_UP(KEY_SIZE(&w->key), PAGE_SECTORS),
+			     GFP_KERNEL);
+		if (!io)
+			goto err;
+
+		w->private	= io;
+		io->dc		= dc;
+
+		dirty_init(w);
+		io->bio.bi_sector	= PTR_OFFSET(&w->key, 0);
+		io->bio.bi_bdev		= PTR_CACHE(dc->disk.c,
+						    &w->key, 0)->bdev;
+		io->bio.bi_rw		= READ;
+		io->bio.bi_end_io	= read_dirty_endio;
+
+		if (bch_bio_alloc_pages(&io->bio, GFP_KERNEL))
+			goto err_free;
+
+		pr_debug("%s", pkey(&w->key));
+
+		closure_call(&io->cl, read_dirty_submit, NULL, &dc->disk.cl);
+
+		delay = writeback_delay(dc, KEY_SIZE(&w->key));
+
+		atomic_inc(&dc->in_flight);
+
+		if (!closure_wait_event(&dc->writeback_wait, cl,
+					atomic_read(&dc->in_flight) < 64))
+			continue_at(cl, read_dirty, dirty_wq);
+	}
+
+	if (0) {
+err_free:
+		kfree(w->private);
+err:
+		bch_keybuf_del(&dc->writeback_keys, w);
+	}
+
+	refill_dirty(cl);
+}
+
+void bch_writeback_init_cached_dev(struct cached_dev *dc)
+{
+	closure_init_unlocked(&dc->writeback);
+	init_rwsem(&dc->writeback_lock);
+
+	bch_keybuf_init(&dc->writeback_keys, dirty_pred);
+
+	dc->writeback_metadata		= true;
+	dc->writeback_running		= true;
+	dc->writeback_percent		= 10;
+	dc->writeback_delay		= 30;
+	dc->writeback_rate.rate		= 1024;
+
+	dc->writeback_rate_update_seconds = 30;
+	dc->writeback_rate_d_term	= 16;
+	dc->writeback_rate_p_term_inverse = 64;
+	dc->writeback_rate_d_smooth	= 8;
+
+	INIT_DELAYED_WORK(&dc->writeback_rate_update, update_writeback_rate);
+	schedule_delayed_work(&dc->writeback_rate_update,
+			      dc->writeback_rate_update_seconds * HZ);
+}
+
+void bch_writeback_exit(void)
+{
+	if (dirty_wq)
+		destroy_workqueue(dirty_wq);
+}
+
+int __init bch_writeback_init(void)
+{
+	dirty_wq = create_singlethread_workqueue("bcache_writeback");
+	if (!dirty_wq)
+		return -ENOMEM;
+
+	return 0;
+}
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index 4fd9d6a..5a2c754 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -846,7 +846,7 @@ static void bitmap_file_set_bit(struct bitmap *bitmap, sector_t block)
 	if (test_bit(BITMAP_HOSTENDIAN, &bitmap->flags))
 		set_bit(bit, kaddr);
 	else
-		test_and_set_bit_le(bit, kaddr);
+		set_bit_le(bit, kaddr);
 	kunmap_atomic(kaddr);
 	pr_debug("set file bit %lu page %lu\n", bit, page->index);
 	/* record page number so it gets flushed to disk when unplug occurs */
@@ -868,7 +868,7 @@ static void bitmap_file_clear_bit(struct bitmap *bitmap, sector_t block)
 	if (test_bit(BITMAP_HOSTENDIAN, &bitmap->flags))
 		clear_bit(bit, paddr);
 	else
-		test_and_clear_bit_le(bit, paddr);
+		clear_bit_le(bit, paddr);
 	kunmap_atomic(paddr);
 	if (!test_page_attr(bitmap, page->index, BITMAP_PAGE_NEEDWRITE)) {
 		set_page_attr(bitmap, page->index, BITMAP_PAGE_PENDING);
diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c
index c608313..6f1b57a 100644
--- a/drivers/md/dm-bufio.c
+++ b/drivers/md/dm-bufio.c
@@ -472,7 +472,7 @@ static void dmio_complete(unsigned long error, void *context)
 {
 	struct dm_buffer *b = context;
 
-	b->bio.bi_end_io(&b->bio, error ? -EIO : 0);
+	b->bio.bi_end_io(&b->bio, error ? -EIO : 0, NULL);
 }
 
 static void use_dmio(struct dm_buffer *b, int rw, sector_t block,
@@ -503,7 +503,7 @@ static void use_dmio(struct dm_buffer *b, int rw, sector_t block,
 
 	r = dm_io(&io_req, 1, &region, NULL);
 	if (r)
-		end_io(&b->bio, r);
+		end_io(&b->bio, r, NULL);
 }
 
 static void use_inline_bio(struct dm_buffer *b, int rw, sector_t block,
@@ -570,7 +570,8 @@ static void submit_io(struct dm_buffer *b, int rw, sector_t block,
  * Set the error, clear B_WRITING bit and wake anyone who was waiting on
  * it.
  */
-static void write_endio(struct bio *bio, int error)
+static void write_endio(struct bio *bio, int error,
+			struct batch_complete *batch)
 {
 	struct dm_buffer *b = container_of(bio, struct dm_buffer, bio);
 
@@ -943,7 +944,7 @@ found_buffer:
  * The endio routine for reading: set the error, clear the bit and wake up
  * anyone waiting on the buffer.
  */
-static void read_endio(struct bio *bio, int error)
+static void read_endio(struct bio *bio, int error, struct batch_complete *batch)
 {
 	struct dm_buffer *b = container_of(bio, struct dm_buffer, bio);
 
diff --git a/drivers/md/dm-cache-policy.h b/drivers/md/dm-cache-policy.h
index 558bdfd..33369ca 100644
--- a/drivers/md/dm-cache-policy.h
+++ b/drivers/md/dm-cache-policy.h
@@ -130,8 +130,8 @@ struct dm_cache_policy {
 	 *
 	 * Must not block.
 	 *
-	 * Returns 1 iff in cache, 0 iff not, < 0 on error (-EWOULDBLOCK
-	 * would be typical).
+	 * Returns 0 if in cache, -ENOENT if not, < 0 for other errors
+	 * (-EWOULDBLOCK would be typical).
 	 */
 	int (*lookup)(struct dm_cache_policy *p, dm_oblock_t oblock, dm_cblock_t *cblock);
 
diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c
index 66120bd..c5ce8a3b 100644
--- a/drivers/md/dm-cache-target.c
+++ b/drivers/md/dm-cache-target.c
@@ -6,6 +6,7 @@
 
 #include "dm.h"
 #include "dm-bio-prison.h"
+#include "dm-bio-record.h"
 #include "dm-cache-metadata.h"
 
 #include <linux/dm-io.h>
@@ -201,10 +202,15 @@ struct per_bio_data {
 	unsigned req_nr:2;
 	struct dm_deferred_entry *all_io_entry;
 
-	/* writethrough fields */
+	/*
+	 * writethrough fields.  These MUST remain at the end of this
+	 * structure and the 'cache' member must be the first as it
+	 * is used to determine the offsetof the writethrough fields.
+	 */
 	struct cache *cache;
 	dm_cblock_t cblock;
 	bio_end_io_t *saved_bi_end_io;
+	struct dm_bio_details bio_details;
 };
 
 struct dm_cache_migration {
@@ -513,16 +519,28 @@ static void save_stats(struct cache *cache)
 /*----------------------------------------------------------------
  * Per bio data
  *--------------------------------------------------------------*/
-static struct per_bio_data *get_per_bio_data(struct bio *bio)
+
+/*
+ * If using writeback, leave out struct per_bio_data's writethrough fields.
+ */
+#define PB_DATA_SIZE_WB (offsetof(struct per_bio_data, cache))
+#define PB_DATA_SIZE_WT (sizeof(struct per_bio_data))
+
+static size_t get_per_bio_data_size(struct cache *cache)
+{
+	return cache->features.write_through ? PB_DATA_SIZE_WT : PB_DATA_SIZE_WB;
+}
+
+static struct per_bio_data *get_per_bio_data(struct bio *bio, size_t data_size)
 {
-	struct per_bio_data *pb = dm_per_bio_data(bio, sizeof(struct per_bio_data));
+	struct per_bio_data *pb = dm_per_bio_data(bio, data_size);
 	BUG_ON(!pb);
 	return pb;
 }
 
-static struct per_bio_data *init_per_bio_data(struct bio *bio)
+static struct per_bio_data *init_per_bio_data(struct bio *bio, size_t data_size)
 {
-	struct per_bio_data *pb = get_per_bio_data(bio);
+	struct per_bio_data *pb = get_per_bio_data(bio, data_size);
 
 	pb->tick = false;
 	pb->req_nr = dm_bio_get_target_bio_nr(bio);
@@ -556,7 +574,8 @@ static void remap_to_cache(struct cache *cache, struct bio *bio,
 static void check_if_tick_bio_needed(struct cache *cache, struct bio *bio)
 {
 	unsigned long flags;
-	struct per_bio_data *pb = get_per_bio_data(bio);
+	size_t pb_data_size = get_per_bio_data_size(cache);
+	struct per_bio_data *pb = get_per_bio_data(bio, pb_data_size);
 
 	spin_lock_irqsave(&cache->lock, flags);
 	if (cache->need_tick_bio &&
@@ -633,9 +652,10 @@ static void defer_writethrough_bio(struct cache *cache, struct bio *bio)
 	wake_worker(cache);
 }
 
-static void writethrough_endio(struct bio *bio, int err)
+static void writethrough_endio(struct bio *bio, int err,
+			       struct batch_complete *batch)
 {
-	struct per_bio_data *pb = get_per_bio_data(bio);
+	struct per_bio_data *pb = get_per_bio_data(bio, PB_DATA_SIZE_WT);
 	bio->bi_end_io = pb->saved_bi_end_io;
 
 	if (err) {
@@ -643,6 +663,7 @@ static void writethrough_endio(struct bio *bio, int err)
 		return;
 	}
 
+	dm_bio_restore(&pb->bio_details, bio);
 	remap_to_cache(pb->cache, bio, pb->cblock);
 
 	/*
@@ -662,11 +683,12 @@ static void writethrough_endio(struct bio *bio, int err)
 static void remap_to_origin_then_cache(struct cache *cache, struct bio *bio,
 				       dm_oblock_t oblock, dm_cblock_t cblock)
 {
-	struct per_bio_data *pb = get_per_bio_data(bio);
+	struct per_bio_data *pb = get_per_bio_data(bio, PB_DATA_SIZE_WT);
 
 	pb->cache = cache;
 	pb->cblock = cblock;
 	pb->saved_bi_end_io = bio->bi_end_io;
+	dm_bio_record(&pb->bio_details, bio);
 	bio->bi_end_io = writethrough_endio;
 
 	remap_to_origin_clear_discard(pb->cache, bio, oblock);
@@ -1035,7 +1057,8 @@ static void defer_bio(struct cache *cache, struct bio *bio)
 
 static void process_flush_bio(struct cache *cache, struct bio *bio)
 {
-	struct per_bio_data *pb = get_per_bio_data(bio);
+	size_t pb_data_size = get_per_bio_data_size(cache);
+	struct per_bio_data *pb = get_per_bio_data(bio, pb_data_size);
 
 	BUG_ON(bio->bi_size);
 	if (!pb->req_nr)
@@ -1107,7 +1130,8 @@ static void process_bio(struct cache *cache, struct prealloc *structs,
 	dm_oblock_t block = get_bio_block(cache, bio);
 	struct dm_bio_prison_cell *cell_prealloc, *old_ocell, *new_ocell;
 	struct policy_result lookup_result;
-	struct per_bio_data *pb = get_per_bio_data(bio);
+	size_t pb_data_size = get_per_bio_data_size(cache);
+	struct per_bio_data *pb = get_per_bio_data(bio, pb_data_size);
 	bool discarded_block = is_discarded_oblock(cache, block);
 	bool can_migrate = discarded_block || spare_migration_bandwidth(cache);
 
@@ -1881,7 +1905,6 @@ static int cache_create(struct cache_args *ca, struct cache **result)
 
 	cache->ti = ca->ti;
 	ti->private = cache;
-	ti->per_bio_data_size = sizeof(struct per_bio_data);
 	ti->num_flush_bios = 2;
 	ti->flush_supported = true;
 
@@ -1890,6 +1913,7 @@ static int cache_create(struct cache_args *ca, struct cache **result)
 	ti->discard_zeroes_data_unsupported = true;
 
 	memcpy(&cache->features, &ca->features, sizeof(cache->features));
+	ti->per_bio_data_size = get_per_bio_data_size(cache);
 
 	cache->callbacks.congested_fn = cache_is_congested;
 	dm_table_add_target_callbacks(ti->table, &cache->callbacks);
@@ -2092,6 +2116,7 @@ static int cache_map(struct dm_target *ti, struct bio *bio)
 
 	int r;
 	dm_oblock_t block = get_bio_block(cache, bio);
+	size_t pb_data_size = get_per_bio_data_size(cache);
 	bool can_migrate = false;
 	bool discarded_block;
 	struct dm_bio_prison_cell *cell;
@@ -2108,7 +2133,7 @@ static int cache_map(struct dm_target *ti, struct bio *bio)
 		return DM_MAPIO_REMAPPED;
 	}
 
-	pb = init_per_bio_data(bio);
+	pb = init_per_bio_data(bio, pb_data_size);
 
 	if (bio->bi_rw & (REQ_FLUSH | REQ_FUA | REQ_DISCARD)) {
 		defer_bio(cache, bio);
@@ -2193,7 +2218,8 @@ static int cache_end_io(struct dm_target *ti, struct bio *bio, int error)
 {
 	struct cache *cache = ti->private;
 	unsigned long flags;
-	struct per_bio_data *pb = get_per_bio_data(bio);
+	size_t pb_data_size = get_per_bio_data_size(cache);
+	struct per_bio_data *pb = get_per_bio_data(bio, pb_data_size);
 
 	if (pb->tick) {
 		policy_tick(cache->policy);
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index 13c1548..ec0e3c0 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -858,8 +858,7 @@ static void crypt_free_buffer_pages(struct crypt_config *cc, struct bio *clone)
 	unsigned int i;
 	struct bio_vec *bv;
 
-	for (i = 0; i < clone->bi_vcnt; i++) {
-		bv = bio_iovec_idx(clone, i);
+	bio_for_each_segment_all(bv, clone, i) {
 		BUG_ON(!bv->bv_page);
 		mempool_free(bv->bv_page, cc->page_pool);
 		bv->bv_page = NULL;
@@ -930,7 +929,8 @@ static void crypt_dec_pending(struct dm_crypt_io *io)
  * The work is done per CPU global for all dm-crypt instances.
  * They should not depend on each other and do not block.
  */
-static void crypt_endio(struct bio *clone, int error)
+static void crypt_endio(struct bio *clone, int error,
+			struct batch_complete *batch)
 {
 	struct dm_crypt_io *io = clone->bi_private;
 	struct crypt_config *cc = io->cc;
diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c
index ea49834..a727b26 100644
--- a/drivers/md/dm-io.c
+++ b/drivers/md/dm-io.c
@@ -136,7 +136,7 @@ static void dec_count(struct io *io, unsigned int region, int error)
 	}
 }
 
-static void endio(struct bio *bio, int error)
+static void endio(struct bio *bio, int error, struct batch_complete *batch)
 {
 	struct io *io;
 	unsigned region;
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index 51bb816..93d28e3 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -618,12 +618,13 @@ static struct pgpath *parse_path(struct dm_arg_set *as, struct path_selector *ps
 		 */
 		r = scsi_dh_attach(q, m->hw_handler_name);
 		if (r == -EBUSY) {
-			/*
-			 * Already attached to different hw_handler:
-			 * try to reattach with correct one.
-			 */
-			scsi_dh_detach(q);
-			r = scsi_dh_attach(q, m->hw_handler_name);
+			ti->error = "a different device handler is already attached";
+			attached_handler_name = scsi_dh_attached_handler_name(q, GFP_KERNEL);
+			DMERR("%s: Device handler %s already attached. "
+			      "Deactivate device to change device handler.",
+				p->path.dev->name, attached_handler_name);
+			kfree(attached_handler_name);
+			goto bad;
 		}
 
 		if (r < 0) {
diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c
index 311e3d3..1d3fe1a 100644
--- a/drivers/md/dm-raid.c
+++ b/drivers/md/dm-raid.c
@@ -1279,6 +1279,31 @@ static int raid_map(struct dm_target *ti, struct bio *bio)
 	return DM_MAPIO_SUBMITTED;
 }
 
+static const char *decipher_sync_action(struct mddev *mddev)
+{
+	if (test_bit(MD_RECOVERY_FROZEN, &mddev->recovery))
+		return "frozen";
+
+	if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) ||
+	    (!mddev->ro && test_bit(MD_RECOVERY_NEEDED, &mddev->recovery))) {
+		if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery))
+			return "reshape";
+
+		if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) {
+			if (!test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery))
+				return "resync";
+			else if (test_bit(MD_RECOVERY_CHECK, &mddev->recovery))
+				return "check";
+			return "repair";
+		}
+
+		if (test_bit(MD_RECOVERY_RECOVER, &mddev->recovery))
+			return "recover";
+	}
+
+	return "idle";
+}
+
 static void raid_status(struct dm_target *ti, status_type_t type,
 			unsigned status_flags, char *result, unsigned maxlen)
 {
@@ -1298,8 +1323,18 @@ static void raid_status(struct dm_target *ti, status_type_t type,
 			sync = rs->md.recovery_cp;
 
 		if (sync >= rs->md.resync_max_sectors) {
+			/*
+			 * Sync complete.
+			 */
 			array_in_sync = 1;
 			sync = rs->md.resync_max_sectors;
+		} else if (test_bit(MD_RECOVERY_REQUESTED, &rs->md.recovery)) {
+			/*
+			 * If "check" or "repair" is occurring, the array has
+			 * undergone and initial sync and the health characters
+			 * should not be 'a' anymore.
+			 */
+			array_in_sync = 1;
 		} else {
 			/*
 			 * The array may be doing an initial sync, or it may
@@ -1311,6 +1346,7 @@ static void raid_status(struct dm_target *ti, status_type_t type,
 				if (!test_bit(In_sync, &rs->dev[i].rdev.flags))
 					array_in_sync = 1;
 		}
+
 		/*
 		 * Status characters:
 		 *  'D' = Dead/Failed device
@@ -1339,6 +1375,21 @@ static void raid_status(struct dm_target *ti, status_type_t type,
 		       (unsigned long long) sync,
 		       (unsigned long long) rs->md.resync_max_sectors);
 
+		/*
+		 * Sync action:
+		 *   See Documentation/device-mapper/dm-raid.c for
+		 *   information on each of these states.
+		 */
+		DMEMIT(" %s", decipher_sync_action(&rs->md));
+
+		/*
+		 * resync_mismatches/mismatch_cnt
+		 *   This field shows the number of discrepancies found when
+		 *   performing a "check" of the array.
+		 */
+		DMEMIT(" %llu",
+		       (unsigned long long)
+		       atomic64_read(&rs->md.resync_mismatches));
 		break;
 	case STATUSTYPE_TABLE:
 		/* The string you would use to construct this array */
@@ -1425,7 +1476,62 @@ static void raid_status(struct dm_target *ti, status_type_t type,
 	}
 }
 
-static int raid_iterate_devices(struct dm_target *ti, iterate_devices_callout_fn fn, void *data)
+static int raid_message(struct dm_target *ti, unsigned argc, char **argv)
+{
+	struct raid_set *rs = ti->private;
+	struct mddev *mddev = &rs->md;
+
+	if (!strcasecmp(argv[0], "reshape")) {
+		DMERR("Reshape not supported.");
+		return -EINVAL;
+	}
+
+	if (!mddev->pers || !mddev->pers->sync_request)
+		return -EINVAL;
+
+	if (!strcasecmp(argv[0], "frozen"))
+		set_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
+	else
+		clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
+
+	if (!strcasecmp(argv[0], "idle") || !strcasecmp(argv[0], "frozen")) {
+		if (mddev->sync_thread) {
+			set_bit(MD_RECOVERY_INTR, &mddev->recovery);
+			md_reap_sync_thread(mddev);
+		}
+	} else if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) ||
+		   test_bit(MD_RECOVERY_NEEDED, &mddev->recovery))
+		return -EBUSY;
+	else if (!strcasecmp(argv[0], "resync"))
+		set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
+	else if (!strcasecmp(argv[0], "recover")) {
+		set_bit(MD_RECOVERY_RECOVER, &mddev->recovery);
+		set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
+	} else {
+		if (!strcasecmp(argv[0], "check"))
+			set_bit(MD_RECOVERY_CHECK, &mddev->recovery);
+		else if (!!strcasecmp(argv[0], "repair"))
+			return -EINVAL;
+		set_bit(MD_RECOVERY_REQUESTED, &mddev->recovery);
+		set_bit(MD_RECOVERY_SYNC, &mddev->recovery);
+	}
+	if (mddev->ro == 2) {
+		/* A write to sync_action is enough to justify
+		 * canceling read-auto mode
+		 */
+		mddev->ro = 0;
+		if (!mddev->suspended)
+			md_wakeup_thread(mddev->sync_thread);
+	}
+	set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
+	if (!mddev->suspended)
+		md_wakeup_thread(mddev->thread);
+
+	return 0;
+}
+
+static int raid_iterate_devices(struct dm_target *ti,
+				iterate_devices_callout_fn fn, void *data)
 {
 	struct raid_set *rs = ti->private;
 	unsigned i;
@@ -1482,12 +1588,13 @@ static void raid_resume(struct dm_target *ti)
 
 static struct target_type raid_target = {
 	.name = "raid",
-	.version = {1, 4, 2},
+	.version = {1, 5, 0},
 	.module = THIS_MODULE,
 	.ctr = raid_ctr,
 	.dtr = raid_dtr,
 	.map = raid_map,
 	.status = raid_status,
+	.message = raid_message,
 	.iterate_devices = raid_iterate_devices,
 	.io_hints = raid_io_hints,
 	.presuspend = raid_presuspend,
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
index d053098..699b5be 100644
--- a/drivers/md/dm-raid1.c
+++ b/drivers/md/dm-raid1.c
@@ -458,7 +458,7 @@ static void map_region(struct dm_io_region *io, struct mirror *m,
 {
 	io->bdev = m->dev->bdev;
 	io->sector = map_sector(m, bio);
-	io->count = bio->bi_size >> 9;
+	io->count = bio_sectors(bio);
 }
 
 static void hold_bio(struct mirror_set *ms, struct bio *bio)
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index c0e0702..eb32e35 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -1485,7 +1485,8 @@ static void start_copy(struct dm_snap_pending_exception *pe)
 	dm_kcopyd_copy(s->kcopyd_client, &src, 1, &dest, 0, copy_callback, pe);
 }
 
-static void full_bio_end_io(struct bio *bio, int error)
+static void full_bio_end_io(struct bio *bio, int error,
+			    struct batch_complete *batch)
 {
 	void *callback_data = bio->bi_private;
 
diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c
index d8837d3..ea5e878 100644
--- a/drivers/md/dm-stripe.c
+++ b/drivers/md/dm-stripe.c
@@ -258,7 +258,7 @@ static int stripe_map_range(struct stripe_c *sc, struct bio *bio,
 	sector_t begin, end;
 
 	stripe_map_range_sector(sc, bio->bi_sector, target_stripe, &begin);
-	stripe_map_range_sector(sc, bio->bi_sector + bio_sectors(bio),
+	stripe_map_range_sector(sc, bio_end_sector(bio),
 				target_stripe, &end);
 	if (begin < end) {
 		bio->bi_bdev = sc->stripe[target_stripe].dev->bdev;
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c
index 004ad165..905b75f 100644
--- a/drivers/md/dm-thin.c
+++ b/drivers/md/dm-thin.c
@@ -553,7 +553,8 @@ static void copy_complete(int read_err, unsigned long write_err, void *context)
 	spin_unlock_irqrestore(&pool->lock, flags);
 }
 
-static void overwrite_endio(struct bio *bio, int err)
+static void overwrite_endio(struct bio *bio, int err,
+			    struct batch_complete *batch)
 {
 	unsigned long flags;
 	struct dm_thin_endio_hook *h = dm_per_bio_data(bio, sizeof(struct dm_thin_endio_hook));
diff --git a/drivers/md/dm-verity.c b/drivers/md/dm-verity.c
index a746f1d..b373bb7 100644
--- a/drivers/md/dm-verity.c
+++ b/drivers/md/dm-verity.c
@@ -413,7 +413,8 @@ static void verity_work(struct work_struct *w)
 	verity_finish_io(io, verity_verify_io(io));
 }
 
-static void verity_end_io(struct bio *bio, int error)
+static void verity_end_io(struct bio *bio, int error,
+			  struct batch_complete *batch)
 {
 	struct dm_verity_io *io = bio->bi_private;
 
@@ -501,7 +502,7 @@ static int verity_map(struct dm_target *ti, struct bio *bio)
 		return -EIO;
 	}
 
-	if ((bio->bi_sector + bio_sectors(bio)) >>
+	if (bio_end_sector(bio) >>
 	    (v->data_dev_block_bits - SECTOR_SHIFT) > v->data_blocks) {
 		DMERR_LIMIT("io out of range");
 		return -EIO;
@@ -519,7 +520,7 @@ static int verity_map(struct dm_target *ti, struct bio *bio)
 
 	bio->bi_end_io = verity_end_io;
 	bio->bi_private = io;
-	io->io_vec_size = bio->bi_vcnt - bio->bi_idx;
+	io->io_vec_size = bio_segments(bio);
 	if (io->io_vec_size < DM_VERITY_IO_VEC_INLINE)
 		io->io_vec = io->io_vec_inline;
 	else
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 7e46926..142f271 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -616,7 +616,8 @@ static void dec_pending(struct dm_io *io, int error)
 	}
 }
 
-static void clone_endio(struct bio *bio, int error)
+static void clone_endio(struct bio *bio, int error,
+			struct batch_complete *batch)
 {
 	int r = 0;
 	struct dm_target_io *tio = bio->bi_private;
@@ -651,7 +652,8 @@ static void clone_endio(struct bio *bio, int error)
 /*
  * Partial completion handling for request-based dm
  */
-static void end_clone_bio(struct bio *clone, int error)
+static void end_clone_bio(struct bio *clone, int error,
+			  struct batch_complete *batch)
 {
 	struct dm_rq_clone_bio_info *info = clone->bi_private;
 	struct dm_rq_target_io *tio = info->tio;
@@ -695,7 +697,7 @@ static void end_clone_bio(struct bio *clone, int error)
 	 * Do not use blk_end_request() here, because it may complete
 	 * the original request before the clone, and break the ordering.
 	 */
-	blk_update_request(tio->orig, 0, nr_bytes);
+	blk_update_request(tio->orig, 0, nr_bytes, NULL);
 }
 
 /*
diff --git a/drivers/md/faulty.c b/drivers/md/faulty.c
index 5e7dc77..ac8af52 100644
--- a/drivers/md/faulty.c
+++ b/drivers/md/faulty.c
@@ -70,7 +70,8 @@
 #include <linux/seq_file.h>
 
 
-static void faulty_fail(struct bio *bio, int error)
+static void faulty_fail(struct bio *bio, int error,
+			struct batch_complete *batch)
 {
 	struct bio *b = bio->bi_private;
 
@@ -185,8 +186,7 @@ static void make_request(struct mddev *mddev, struct bio *bio)
 			return;
 		}
 
-		if (check_sector(conf, bio->bi_sector, bio->bi_sector+(bio->bi_size>>9),
-				 WRITE))
+		if (check_sector(conf, bio->bi_sector, bio_end_sector(bio), WRITE))
 			failit = 1;
 		if (check_mode(conf, WritePersistent)) {
 			add_sector(conf, bio->bi_sector, WritePersistent);
@@ -196,8 +196,7 @@ static void make_request(struct mddev *mddev, struct bio *bio)
 			failit = 1;
 	} else {
 		/* read request */
-		if (check_sector(conf, bio->bi_sector, bio->bi_sector + (bio->bi_size>>9),
-				 READ))
+		if (check_sector(conf, bio->bi_sector, bio_end_sector(bio), READ))
 			failit = 1;
 		if (check_mode(conf, ReadTransient))
 			failit = 1;
diff --git a/drivers/md/linear.c b/drivers/md/linear.c
index 2101483..f03fabd 100644
--- a/drivers/md/linear.c
+++ b/drivers/md/linear.c
@@ -317,8 +317,7 @@ static void linear_make_request(struct mddev *mddev, struct bio *bio)
 		bio_io_error(bio);
 		return;
 	}
-	if (unlikely(bio->bi_sector + (bio->bi_size >> 9) >
-		     tmp_dev->end_sector)) {
+	if (unlikely(bio_end_sector(bio) > tmp_dev->end_sector)) {
 		/* This bio crosses a device boundary, so we have to
 		 * split it.
 		 */
diff --git a/drivers/md/md.c b/drivers/md/md.c
index aeceedf..98e6a92 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -72,6 +72,9 @@ static DECLARE_WAIT_QUEUE_HEAD(resync_wait);
 static struct workqueue_struct *md_wq;
 static struct workqueue_struct *md_misc_wq;
 
+static int remove_and_add_spares(struct mddev *mddev,
+				 struct md_rdev *this);
+
 #define MD_BUG(x...) { printk("md: bug in file %s, line %d\n", __FILE__, __LINE__); md_print_devices(); }
 
 /*
@@ -194,21 +197,12 @@ void md_trim_bio(struct bio *bio, int offset, int size)
 	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;
-	}
+	bio_advance(bio, offset << 9);
+
+	bio->bi_size = size;
+
 	/* 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,
@@ -385,7 +379,8 @@ EXPORT_SYMBOL(mddev_congested);
  * Generic flush handling for md
  */
 
-static void md_end_flush(struct bio *bio, int err)
+static void md_end_flush(struct bio *bio, int err,
+			 struct batch_complete *batch)
 {
 	struct md_rdev *rdev = bio->bi_private;
 	struct mddev *mddev = rdev->mddev;
@@ -607,9 +602,9 @@ static struct mddev * mddev_find(dev_t unit)
 	goto retry;
 }
 
-static inline int mddev_lock(struct mddev * mddev)
+int md_queue_misc_work(struct work_struct *work)
 {
-	return mutex_lock_interruptible(&mddev->reconfig_mutex);
+	return queue_work(md_misc_wq, work);
 }
 
 static inline int mddev_is_locked(struct mddev *mddev)
@@ -624,7 +619,7 @@ static inline int mddev_trylock(struct mddev * mddev)
 
 static struct attribute_group md_redundancy_group;
 
-static void mddev_unlock(struct mddev * mddev)
+void mddev_unlock(struct mddev * mddev)
 {
 	if (mddev->to_remove) {
 		/* These cannot be removed under reconfig_mutex as
@@ -762,7 +757,8 @@ void md_rdev_clear(struct md_rdev *rdev)
 }
 EXPORT_SYMBOL_GPL(md_rdev_clear);
 
-static void super_written(struct bio *bio, int error)
+static void super_written(struct bio *bio, int error,
+			  struct batch_complete *batch)
 {
 	struct md_rdev *rdev = bio->bi_private;
 	struct mddev *mddev = rdev->mddev;
@@ -813,7 +809,8 @@ void md_super_wait(struct mddev *mddev)
 	finish_wait(&mddev->sb_wait, &wq);
 }
 
-static void bi_complete(struct bio *bio, int error)
+static void bi_complete(struct bio *bio, int error,
+			struct batch_complete *batch)
 {
 	complete((struct completion*)bio->bi_private);
 }
@@ -2411,6 +2408,11 @@ static void md_update_sb(struct mddev * mddev, int force_change)
 	int nospares = 0;
 	int any_badblocks_changed = 0;
 
+	if (mddev->ro) {
+		if (force_change)
+			set_bit(MD_CHANGE_DEVS, &mddev->flags);
+		return;
+	}
 repeat:
 	/* First make sure individual recovery_offsets are correct */
 	rdev_for_each(rdev, mddev) {
@@ -2800,12 +2802,10 @@ slot_store(struct md_rdev *rdev, const char *buf, size_t len)
 		/* personality does all needed checks */
 		if (rdev->mddev->pers->hot_remove_disk == NULL)
 			return -EINVAL;
-		err = rdev->mddev->pers->
-			hot_remove_disk(rdev->mddev, rdev);
-		if (err)
-			return err;
-		sysfs_unlink_rdev(rdev->mddev, rdev);
-		rdev->raid_disk = -1;
+		clear_bit(Blocked, &rdev->flags);
+		remove_and_add_spares(rdev->mddev, rdev);
+		if (rdev->raid_disk >= 0)
+			return -EBUSY;
 		set_bit(MD_RECOVERY_NEEDED, &rdev->mddev->recovery);
 		md_wakeup_thread(rdev->mddev->thread);
 	} else if (rdev->mddev->pers) {
@@ -4225,8 +4225,6 @@ action_show(struct mddev *mddev, char *page)
 	return sprintf(page, "%s\n", type);
 }
 
-static void reap_sync_thread(struct mddev *mddev);
-
 static ssize_t
 action_store(struct mddev *mddev, const char *page, size_t len)
 {
@@ -4241,7 +4239,7 @@ action_store(struct mddev *mddev, const char *page, size_t len)
 	if (cmd_match(page, "idle") || cmd_match(page, "frozen")) {
 		if (mddev->sync_thread) {
 			set_bit(MD_RECOVERY_INTR, &mddev->recovery);
-			reap_sync_thread(mddev);
+			md_reap_sync_thread(mddev);
 		}
 	} else if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) ||
 		   test_bit(MD_RECOVERY_NEEDED, &mddev->recovery))
@@ -5279,7 +5277,7 @@ static void __md_stop_writes(struct mddev *mddev)
 	if (mddev->sync_thread) {
 		set_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
 		set_bit(MD_RECOVERY_INTR, &mddev->recovery);
-		reap_sync_thread(mddev);
+		md_reap_sync_thread(mddev);
 	}
 
 	del_timer_sync(&mddev->safemode_timer);
@@ -5287,7 +5285,8 @@ static void __md_stop_writes(struct mddev *mddev)
 	bitmap_flush(mddev);
 	md_super_wait(mddev);
 
-	if (!mddev->in_sync || mddev->flags) {
+	if (mddev->ro == 0 &&
+	    (!mddev->in_sync || mddev->flags)) {
 		/* mark array as shutdown cleanly */
 		mddev->in_sync = 1;
 		md_update_sb(mddev, 1);
@@ -5810,7 +5809,7 @@ static int add_new_disk(struct mddev * mddev, mdu_disk_info_t *info)
 		else
 			sysfs_notify_dirent_safe(rdev->sysfs_state);
 
-		md_update_sb(mddev, 1);
+		set_bit(MD_CHANGE_DEVS, &mddev->flags);
 		if (mddev->degraded)
 			set_bit(MD_RECOVERY_RECOVER, &mddev->recovery);
 		set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
@@ -5877,6 +5876,9 @@ static int hot_remove_disk(struct mddev * mddev, dev_t dev)
 	if (!rdev)
 		return -ENXIO;
 
+	clear_bit(Blocked, &rdev->flags);
+	remove_and_add_spares(mddev, rdev);
+
 	if (rdev->raid_disk >= 0)
 		goto busy;
 
@@ -6490,6 +6492,28 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode,
 		err = md_set_readonly(mddev, bdev);
 		goto done_unlock;
 
+	case HOT_REMOVE_DISK:
+		err = hot_remove_disk(mddev, new_decode_dev(arg));
+		goto done_unlock;
+
+	case ADD_NEW_DISK:
+		/* We can support ADD_NEW_DISK on read-only arrays
+		 * on if we are re-adding a preexisting device.
+		 * So require mddev->pers and MD_DISK_SYNC.
+		 */
+		if (mddev->pers) {
+			mdu_disk_info_t info;
+			if (copy_from_user(&info, argp, sizeof(info)))
+				err = -EFAULT;
+			else if (!(info.state & (1<<MD_DISK_SYNC)))
+				/* Need to clear read-only for this */
+				break;
+			else
+				err = add_new_disk(mddev, &info);
+			goto done_unlock;
+		}
+		break;
+
 	case BLKROSET:
 		if (get_user(ro, (int __user *)(arg))) {
 			err = -EFAULT;
@@ -6560,10 +6584,6 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode,
 		goto done_unlock;
 	}
 
-	case HOT_REMOVE_DISK:
-		err = hot_remove_disk(mddev, new_decode_dev(arg));
-		goto done_unlock;
-
 	case HOT_ADD_DISK:
 		err = hot_add_disk(mddev, new_decode_dev(arg));
 		goto done_unlock;
@@ -7644,14 +7664,16 @@ void md_do_sync(struct md_thread *thread)
 }
 EXPORT_SYMBOL_GPL(md_do_sync);
 
-static int remove_and_add_spares(struct mddev *mddev)
+static int remove_and_add_spares(struct mddev *mddev,
+				 struct md_rdev *this)
 {
 	struct md_rdev *rdev;
 	int spares = 0;
 	int removed = 0;
 
 	rdev_for_each(rdev, mddev)
-		if (rdev->raid_disk >= 0 &&
+		if ((this == NULL || rdev == this) &&
+		    rdev->raid_disk >= 0 &&
 		    !test_bit(Blocked, &rdev->flags) &&
 		    (test_bit(Faulty, &rdev->flags) ||
 		     ! test_bit(In_sync, &rdev->flags)) &&
@@ -7666,74 +7688,52 @@ static int remove_and_add_spares(struct mddev *mddev)
 	if (removed && mddev->kobj.sd)
 		sysfs_notify(&mddev->kobj, NULL, "degraded");
 
+	if (this)
+		goto no_add;
+
 	rdev_for_each(rdev, mddev) {
 		if (rdev->raid_disk >= 0 &&
 		    !test_bit(In_sync, &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) {
-				if (sysfs_link_rdev(mddev, rdev))
-					/* failure here is OK */;
-				spares++;
-				md_new_event(mddev);
-				set_bit(MD_CHANGE_DEVS, &mddev->flags);
-			}
+		if (rdev->raid_disk >= 0)
+			continue;
+		if (test_bit(Faulty, &rdev->flags))
+			continue;
+		if (mddev->ro &&
+		    rdev->saved_raid_disk < 0)
+			continue;
+
+		rdev->recovery_offset = 0;
+		if (rdev->saved_raid_disk >= 0 && mddev->in_sync) {
+			spin_lock_irq(&mddev->write_lock);
+			if (mddev->in_sync)
+				/* OK, this device, which is in_sync,
+				 * will definitely be noticed before
+				 * the next write, so recovery isn't
+				 * needed.
+				 */
+				rdev->recovery_offset = mddev->recovery_cp;
+			spin_unlock_irq(&mddev->write_lock);
+		}
+		if (mddev->ro && rdev->recovery_offset != MaxSector)
+			/* not safe to add this disk now */
+			continue;
+		if (mddev->pers->
+		    hot_add_disk(mddev, rdev) == 0) {
+			if (sysfs_link_rdev(mddev, rdev))
+				/* failure here is OK */;
+			spares++;
+			md_new_event(mddev);
+			set_bit(MD_CHANGE_DEVS, &mddev->flags);
 		}
 	}
+no_add:
 	if (removed)
 		set_bit(MD_CHANGE_DEVS, &mddev->flags);
 	return spares;
 }
 
-static void reap_sync_thread(struct mddev *mddev)
-{
-	struct md_rdev *rdev;
-
-	/* resync has finished, collect result */
-	md_unregister_thread(&mddev->sync_thread);
-	if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery) &&
-	    !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) {
-		/* success...*/
-		/* activate any spares */
-		if (mddev->pers->spare_active(mddev)) {
-			sysfs_notify(&mddev->kobj, NULL,
-				     "degraded");
-			set_bit(MD_CHANGE_DEVS, &mddev->flags);
-		}
-	}
-	if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) &&
-	    mddev->pers->finish_reshape)
-		mddev->pers->finish_reshape(mddev);
-
-	/* If array is no-longer degraded, then any saved_raid_disk
-	 * information must be scrapped.  Also if any device is now
-	 * In_sync we must scrape the saved_raid_disk for that device
-	 * do the superblock for an incrementally recovered device
-	 * written out.
-	 */
-	rdev_for_each(rdev, mddev)
-		if (!mddev->degraded ||
-		    test_bit(In_sync, &rdev->flags))
-			rdev->saved_raid_disk = -1;
-
-	md_update_sb(mddev, 1);
-	clear_bit(MD_RECOVERY_RUNNING, &mddev->recovery);
-	clear_bit(MD_RECOVERY_SYNC, &mddev->recovery);
-	clear_bit(MD_RECOVERY_RESHAPE, &mddev->recovery);
-	clear_bit(MD_RECOVERY_REQUESTED, &mddev->recovery);
-	clear_bit(MD_RECOVERY_CHECK, &mddev->recovery);
-	/* flag recovery needed just to double check */
-	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);
-}
-
 /*
  * This routine is regularly called by all per-raid-array threads to
  * deal with generic issues like resync and super-block update.
@@ -7789,22 +7789,16 @@ void md_check_recovery(struct mddev *mddev)
 		int spares = 0;
 
 		if (mddev->ro) {
-			/* Only thing we do on a ro array is remove
-			 * failed devices.
+			/* On a read-only array we can:
+			 * - remove failed devices
+			 * - add already-in_sync devices if the array itself
+			 *   is in-sync.
+			 * As we only add devices that are already in-sync,
+			 * we can activate the spares immediately.
 			 */
-			struct md_rdev *rdev;
-			rdev_for_each(rdev, mddev)
-				if (rdev->raid_disk >= 0 &&
-				    !test_bit(Blocked, &rdev->flags) &&
-				    test_bit(Faulty, &rdev->flags) &&
-				    atomic_read(&rdev->nr_pending)==0) {
-					if (mddev->pers->hot_remove_disk(
-						    mddev, rdev) == 0) {
-						sysfs_unlink_rdev(mddev, rdev);
-						rdev->raid_disk = -1;
-					}
-				}
 			clear_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
+			remove_and_add_spares(mddev, NULL);
+			mddev->pers->spare_active(mddev);
 			goto unlock;
 		}
 
@@ -7836,7 +7830,7 @@ void md_check_recovery(struct mddev *mddev)
 			goto unlock;
 		}
 		if (mddev->sync_thread) {
-			reap_sync_thread(mddev);
+			md_reap_sync_thread(mddev);
 			goto unlock;
 		}
 		/* Set RUNNING before clearing NEEDED to avoid
@@ -7867,7 +7861,7 @@ void md_check_recovery(struct mddev *mddev)
 				goto unlock;
 			set_bit(MD_RECOVERY_RESHAPE, &mddev->recovery);
 			clear_bit(MD_RECOVERY_RECOVER, &mddev->recovery);
-		} else if ((spares = remove_and_add_spares(mddev))) {
+		} else if ((spares = remove_and_add_spares(mddev, NULL))) {
 			clear_bit(MD_RECOVERY_SYNC, &mddev->recovery);
 			clear_bit(MD_RECOVERY_CHECK, &mddev->recovery);
 			clear_bit(MD_RECOVERY_REQUESTED, &mddev->recovery);
@@ -7917,6 +7911,51 @@ void md_check_recovery(struct mddev *mddev)
 	}
 }
 
+void md_reap_sync_thread(struct mddev *mddev)
+{
+	struct md_rdev *rdev;
+
+	/* resync has finished, collect result */
+	md_unregister_thread(&mddev->sync_thread);
+	if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery) &&
+	    !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) {
+		/* success...*/
+		/* activate any spares */
+		if (mddev->pers->spare_active(mddev)) {
+			sysfs_notify(&mddev->kobj, NULL,
+				     "degraded");
+			set_bit(MD_CHANGE_DEVS, &mddev->flags);
+		}
+	}
+	if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) &&
+	    mddev->pers->finish_reshape)
+		mddev->pers->finish_reshape(mddev);
+
+	/* If array is no-longer degraded, then any saved_raid_disk
+	 * information must be scrapped.  Also if any device is now
+	 * In_sync we must scrape the saved_raid_disk for that device
+	 * do the superblock for an incrementally recovered device
+	 * written out.
+	 */
+	rdev_for_each(rdev, mddev)
+		if (!mddev->degraded ||
+		    test_bit(In_sync, &rdev->flags))
+			rdev->saved_raid_disk = -1;
+
+	md_update_sb(mddev, 1);
+	clear_bit(MD_RECOVERY_RUNNING, &mddev->recovery);
+	clear_bit(MD_RECOVERY_SYNC, &mddev->recovery);
+	clear_bit(MD_RECOVERY_RESHAPE, &mddev->recovery);
+	clear_bit(MD_RECOVERY_REQUESTED, &mddev->recovery);
+	clear_bit(MD_RECOVERY_CHECK, &mddev->recovery);
+	/* flag recovery needed just to double check */
+	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);
+}
+
 void md_wait_for_blocked_rdev(struct md_rdev *rdev, struct mddev *mddev)
 {
 	sysfs_notify_dirent_safe(rdev->sysfs_state);
@@ -8642,6 +8681,9 @@ EXPORT_SYMBOL(md_register_thread);
 EXPORT_SYMBOL(md_unregister_thread);
 EXPORT_SYMBOL(md_wakeup_thread);
 EXPORT_SYMBOL(md_check_recovery);
+EXPORT_SYMBOL(md_reap_sync_thread);
+EXPORT_SYMBOL(mddev_unlock);
+EXPORT_SYMBOL(md_queue_misc_work);
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("MD RAID framework");
 MODULE_ALIAS("md");
diff --git a/drivers/md/md.h b/drivers/md/md.h
index d90fb1a..2a43cba 100644
--- a/drivers/md/md.h
+++ b/drivers/md/md.h
@@ -567,6 +567,7 @@ extern struct md_thread *md_register_thread(
 extern void md_unregister_thread(struct md_thread **threadp);
 extern void md_wakeup_thread(struct md_thread *thread);
 extern void md_check_recovery(struct mddev *mddev);
+extern void md_reap_sync_thread(struct mddev *mddev);
 extern void md_write_start(struct mddev *mddev, struct bio *bi);
 extern void md_write_end(struct mddev *mddev);
 extern void md_done_sync(struct mddev *mddev, int blocks, int ok);
@@ -612,4 +613,12 @@ static inline int mddev_check_plugged(struct mddev *mddev)
 	return !!blk_check_plugged(md_unplug, mddev,
 				   sizeof(struct blk_plug_cb));
 }
+
+static inline int mddev_lock(struct mddev * mddev)
+{
+	return mutex_lock_interruptible(&mddev->reconfig_mutex);
+}
+extern void mddev_unlock(struct mddev *mddev);
+extern int md_queue_misc_work(struct work_struct *work);
+
 #endif /* _MD_MD_H */
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c
index 1642eae..fecad70 100644
--- a/drivers/md/multipath.c
+++ b/drivers/md/multipath.c
@@ -83,7 +83,8 @@ static void multipath_end_bh_io (struct multipath_bh *mp_bh, int err)
 	mempool_free(mp_bh, conf->pool);
 }
 
-static void multipath_end_request(struct bio *bio, int error)
+static void multipath_end_request(struct bio *bio, int error,
+				  struct batch_complete *batch)
 {
 	int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
 	struct multipath_bh *mp_bh = bio->bi_private;
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index 0505452..fcf65e5 100644
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -502,11 +502,11 @@ static inline int is_io_in_chunk_boundary(struct mddev *mddev,
 {
 	if (likely(is_power_of_2(chunk_sects))) {
 		return chunk_sects >= ((bio->bi_sector & (chunk_sects-1))
-					+ (bio->bi_size >> 9));
+					+ bio_sectors(bio));
 	} else{
 		sector_t sector = bio->bi_sector;
 		return chunk_sects >= (sector_div(sector, chunk_sects)
-						+ (bio->bi_size >> 9));
+						+ bio_sectors(bio));
 	}
 }
 
@@ -527,8 +527,7 @@ static void raid0_make_request(struct mddev *mddev, struct bio *bio)
 		sector_t sector = bio->bi_sector;
 		struct bio_pair *bp;
 		/* Sanity check -- queue functions should prevent this happening */
-		if ((bio->bi_vcnt != 1 && bio->bi_vcnt != 0) ||
-		    bio->bi_idx != 0)
+		if (bio_segments(bio) > 1)
 			goto bad_map;
 		/* This is a one page bio that upper layers
 		 * refuse to split for us, so we need to split it.
@@ -567,7 +566,7 @@ bad_map:
 	printk("md/raid0:%s: make_request bug: can't convert block across chunks"
 	       " or bigger than %dk %llu %d\n",
 	       mdname(mddev), chunk_sects / 2,
-	       (unsigned long long)bio->bi_sector, bio->bi_size >> 10);
+	       (unsigned long long)bio->bi_sector, bio_sectors(bio) / 2);
 
 	bio_io_error(bio);
 	return;
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index fd86b37..619ba71 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -92,7 +92,6 @@ static void r1bio_pool_free(void *r1_bio, void *data)
 static void * r1buf_pool_alloc(gfp_t gfp_flags, void *data)
 {
 	struct pool_info *pi = data;
-	struct page *page;
 	struct r1bio *r1_bio;
 	struct bio *bio;
 	int i, j;
@@ -122,14 +121,10 @@ static void * r1buf_pool_alloc(gfp_t gfp_flags, void *data)
 		j = 1;
 	while(j--) {
 		bio = r1_bio->bios[j];
-		for (i = 0; i < RESYNC_PAGES; i++) {
-			page = alloc_page(gfp_flags);
-			if (unlikely(!page))
-				goto out_free_pages;
+		bio->bi_vcnt = RESYNC_PAGES;
 
-			bio->bi_io_vec[i].bv_page = page;
-			bio->bi_vcnt = i+1;
-		}
+		if (bio_alloc_pages(bio, gfp_flags))
+			goto out_free_bio;
 	}
 	/* If not user-requests, copy the page pointers to all bios */
 	if (!test_bit(MD_RECOVERY_REQUESTED, &pi->mddev->recovery)) {
@@ -143,11 +138,6 @@ static void * r1buf_pool_alloc(gfp_t gfp_flags, void *data)
 
 	return r1_bio;
 
-out_free_pages:
-	for (j=0 ; j < pi->raid_disks; j++)
-		for (i=0; i < r1_bio->bios[j]->bi_vcnt ; i++)
-			put_page(r1_bio->bios[j]->bi_io_vec[i].bv_page);
-	j = -1;
 out_free_bio:
 	while (++j < pi->raid_disks)
 		bio_put(r1_bio->bios[j]);
@@ -267,7 +257,7 @@ static void raid_end_bio_io(struct r1bio *r1_bio)
 			 (bio_data_dir(bio) == WRITE) ? "write" : "read",
 			 (unsigned long long) bio->bi_sector,
 			 (unsigned long long) bio->bi_sector +
-			 (bio->bi_size >> 9) - 1);
+			 bio_sectors(bio) - 1);
 
 		call_bio_endio(r1_bio);
 	}
@@ -304,7 +294,8 @@ static int find_bio_disk(struct r1bio *r1_bio, struct bio *bio)
 	return mirror;
 }
 
-static void raid1_end_read_request(struct bio *bio, int error)
+static void raid1_end_read_request(struct bio *bio, int error,
+				   struct batch_complete *batch)
 {
 	int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
 	struct r1bio *r1_bio = bio->bi_private;
@@ -389,7 +380,8 @@ static void r1_bio_write_done(struct r1bio *r1_bio)
 	}
 }
 
-static void raid1_end_write_request(struct bio *bio, int error)
+static void raid1_end_write_request(struct bio *bio, int error,
+				    struct batch_complete *batch)
 {
 	int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
 	struct r1bio *r1_bio = bio->bi_private;
@@ -458,7 +450,7 @@ static void raid1_end_write_request(struct bio *bio, int error)
 					 " %llu-%llu\n",
 					 (unsigned long long) mbio->bi_sector,
 					 (unsigned long long) mbio->bi_sector +
-					 (mbio->bi_size >> 9) - 1);
+					 bio_sectors(mbio) - 1);
 				call_bio_endio(r1_bio);
 			}
 		}
@@ -925,7 +917,7 @@ static void alloc_behind_pages(struct bio *bio, struct r1bio *r1_bio)
 	if (unlikely(!bvecs))
 		return;
 
-	bio_for_each_segment(bvec, bio, i) {
+	bio_for_each_segment_all(bvec, bio, i) {
 		bvecs[i] = *bvec;
 		bvecs[i].bv_page = alloc_page(GFP_NOIO);
 		if (unlikely(!bvecs[i].bv_page))
@@ -1018,7 +1010,7 @@ static void make_request(struct mddev *mddev, struct bio * bio)
 	md_write_start(mddev, bio); /* wait on superblock update early */
 
 	if (bio_data_dir(bio) == WRITE &&
-	    bio->bi_sector + bio->bi_size/512 > mddev->suspend_lo &&
+	    bio_end_sector(bio) > mddev->suspend_lo &&
 	    bio->bi_sector < mddev->suspend_hi) {
 		/* As the suspend_* range is controlled by
 		 * userspace, we want an interruptible
@@ -1029,7 +1021,7 @@ static void make_request(struct mddev *mddev, struct bio * bio)
 			flush_signals(current);
 			prepare_to_wait(&conf->wait_barrier,
 					&w, TASK_INTERRUPTIBLE);
-			if (bio->bi_sector + bio->bi_size/512 <= mddev->suspend_lo ||
+			if (bio_end_sector(bio) <= mddev->suspend_lo ||
 			    bio->bi_sector >= mddev->suspend_hi)
 				break;
 			schedule();
@@ -1049,7 +1041,7 @@ static void make_request(struct mddev *mddev, struct bio * bio)
 	r1_bio = mempool_alloc(conf->r1bio_pool, GFP_NOIO);
 
 	r1_bio->master_bio = bio;
-	r1_bio->sectors = bio->bi_size >> 9;
+	r1_bio->sectors = bio_sectors(bio);
 	r1_bio->state = 0;
 	r1_bio->mddev = mddev;
 	r1_bio->sector = bio->bi_sector;
@@ -1127,7 +1119,7 @@ read_again:
 			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->sectors = bio_sectors(bio) - sectors_handled;
 			r1_bio->state = 0;
 			r1_bio->mddev = mddev;
 			r1_bio->sector = bio->bi_sector + sectors_handled;
@@ -1284,14 +1276,10 @@ read_again:
 			struct bio_vec *bvec;
 			int j;
 
-			/* Yes, I really want the '__' version so that
-			 * we clear any unused pointer in the io_vec, rather
-			 * than leave them unchanged.  This is important
-			 * because when we come to free the pages, we won't
-			 * know the original bi_idx, so we just free
-			 * them all
+			/*
+			 * We trimmed the bio, so _all is legit
 			 */
-			__bio_for_each_segment(bvec, mbio, j, 0)
+			bio_for_each_segment_all(bvec, mbio, 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);
@@ -1329,14 +1317,14 @@ read_again:
 	/* Mustn't call r1_bio_write_done before this next test,
 	 * as it could result in the bio being freed.
 	 */
-	if (sectors_handled < (bio->bi_size >> 9)) {
+	if (sectors_handled < bio_sectors(bio)) {
 		r1_bio_write_done(r1_bio);
 		/* 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->sectors = bio_sectors(bio) - sectors_handled;
 		r1_bio->state = 0;
 		r1_bio->mddev = mddev;
 		r1_bio->sector = bio->bi_sector + sectors_handled;
@@ -1621,7 +1609,8 @@ abort:
 }
 
 
-static void end_sync_read(struct bio *bio, int error)
+static void end_sync_read(struct bio *bio, int error,
+			  struct batch_complete *batch)
 {
 	struct r1bio *r1_bio = bio->bi_private;
 
@@ -1639,7 +1628,8 @@ static void end_sync_read(struct bio *bio, int error)
 		reschedule_retry(r1_bio);
 }
 
-static void end_sync_write(struct bio *bio, int error)
+static void end_sync_write(struct bio *bio, int error,
+			   struct batch_complete *batch)
 {
 	int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
 	struct r1bio *r1_bio = bio->bi_private;
@@ -1862,7 +1852,7 @@ static int process_checks(struct r1bio *r1_bio)
 		struct bio *sbio = r1_bio->bios[i];
 		int size;
 
-		if (r1_bio->bios[i]->bi_end_io != end_sync_read)
+		if (sbio->bi_end_io != end_sync_read)
 			continue;
 
 		if (test_bit(BIO_UPTODATE, &sbio->bi_flags)) {
@@ -1887,16 +1877,15 @@ static int process_checks(struct r1bio *r1_bio)
 			continue;
 		}
 		/* fixup the bio for reuse */
+		bio_reset(sbio);
 		sbio->bi_vcnt = vcnt;
 		sbio->bi_size = r1_bio->sectors << 9;
-		sbio->bi_idx = 0;
-		sbio->bi_phys_segments = 0;
-		sbio->bi_flags &= ~(BIO_POOL_MASK - 1);
-		sbio->bi_flags |= 1 << BIO_UPTODATE;
-		sbio->bi_next = NULL;
 		sbio->bi_sector = r1_bio->sector +
 			conf->mirrors[i].rdev->data_offset;
 		sbio->bi_bdev = conf->mirrors[i].rdev->bdev;
+		sbio->bi_end_io = end_sync_read;
+		sbio->bi_private = r1_bio;
+
 		size = sbio->bi_size;
 		for (j = 0; j < vcnt ; j++) {
 			struct bio_vec *bi;
@@ -1907,10 +1896,9 @@ static int process_checks(struct r1bio *r1_bio)
 			else
 				bi->bv_len = size;
 			size -= PAGE_SIZE;
-			memcpy(page_address(bi->bv_page),
-			       page_address(pbio->bi_io_vec[j].bv_page),
-			       PAGE_SIZE);
 		}
+
+		bio_copy_data(sbio, pbio);
 	}
 	return 0;
 }
@@ -1947,7 +1935,7 @@ static void sync_request_write(struct mddev *mddev, struct r1bio *r1_bio)
 		wbio->bi_rw = WRITE;
 		wbio->bi_end_io = end_sync_write;
 		atomic_inc(&r1_bio->remaining);
-		md_sync_acct(conf->mirrors[i].rdev->bdev, wbio->bi_size >> 9);
+		md_sync_acct(conf->mirrors[i].rdev->bdev, bio_sectors(wbio));
 
 		generic_make_request(wbio);
 	}
@@ -2059,32 +2047,11 @@ static void fix_read_error(struct r1conf *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(struct r1bio *r1_bio, int i)
 {
 	struct mddev *mddev = r1_bio->mddev;
 	struct r1conf *conf = mddev->private;
 	struct md_rdev *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.
@@ -2112,30 +2079,32 @@ static int narrow_write_error(struct r1bio *r1_bio, int i)
 		   & ~(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;
+		if (test_bit(R1BIO_BehindIO, &r1_bio->state)) {
+			unsigned vcnt = r1_bio->behind_page_count;
+			struct bio_vec *vec = r1_bio->behind_bvecs;
+
+			while (!vec->bv_page) {
+				vec++;
+				vcnt--;
+			}
+
+			wbio = bio_alloc_mddev(GFP_NOIO, vcnt, mddev);
+			memcpy(wbio->bi_io_vec, vec, vcnt * sizeof(struct bio_vec));
+
+			wbio->bi_vcnt = vcnt;
+		} else {
+			wbio = bio_clone_mddev(r1_bio->master_bio, GFP_NOIO, mddev);
+		}
+
 		wbio->bi_rw = WRITE;
-		wbio->bi_vcnt = vcnt;
+		wbio->bi_sector = r1_bio->sector;
 		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;
@@ -2284,8 +2253,7 @@ read_more:
 			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->sectors = bio_sectors(mbio) - sectors_handled;
 			r1_bio->state = 0;
 			set_bit(R1BIO_ReadError, &r1_bio->state);
 			r1_bio->mddev = mddev;
@@ -2459,18 +2427,7 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr, int *skipp
 	for (i = 0; i < conf->raid_disks * 2; i++) {
 		struct md_rdev *rdev;
 		bio = r1_bio->bios[i];
-
-		/* take from bio_init */
-		bio->bi_next = NULL;
-		bio->bi_flags &= ~(BIO_POOL_MASK-1);
-		bio->bi_flags |= 1 << BIO_UPTODATE;
-		bio->bi_rw = READ;
-		bio->bi_vcnt = 0;
-		bio->bi_idx = 0;
-		bio->bi_phys_segments = 0;
-		bio->bi_size = 0;
-		bio->bi_end_io = NULL;
-		bio->bi_private = NULL;
+		bio_reset(bio);
 
 		rdev = rcu_dereference(conf->mirrors[i].rdev);
 		if (rdev == NULL ||
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 77b562d..6005d96 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -101,7 +101,8 @@ static int enough(struct r10conf *conf, int ignore);
 static sector_t reshape_request(struct mddev *mddev, sector_t sector_nr,
 				int *skipped);
 static void reshape_request_write(struct mddev *mddev, struct r10bio *r10_bio);
-static void end_reshape_write(struct bio *bio, int error);
+static void end_reshape_write(struct bio *bio, int error,
+			      struct batch_complete *batch);
 static void end_reshape(struct r10conf *conf);
 
 static void * r10bio_pool_alloc(gfp_t gfp_flags, void *data)
@@ -358,7 +359,8 @@ static int find_bio_disk(struct r10conf *conf, struct r10bio *r10_bio,
 	return r10_bio->devs[slot].devnum;
 }
 
-static void raid10_end_read_request(struct bio *bio, int error)
+static void raid10_end_read_request(struct bio *bio, int error,
+				    struct batch_complete *batch)
 {
 	int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
 	struct r10bio *r10_bio = bio->bi_private;
@@ -441,7 +443,8 @@ static void one_write_done(struct r10bio *r10_bio)
 	}
 }
 
-static void raid10_end_write_request(struct bio *bio, int error)
+static void raid10_end_write_request(struct bio *bio, int error,
+				     struct batch_complete *batch)
 {
 	int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
 	struct r10bio *r10_bio = bio->bi_private;
@@ -1169,14 +1172,13 @@ static void make_request(struct mddev *mddev, struct bio * bio)
 	/* If this request crosses a chunk boundary, we need to
 	 * split it.  This will only happen for 1 PAGE (or less) requests.
 	 */
-	if (unlikely((bio->bi_sector & chunk_mask) + (bio->bi_size >> 9)
+	if (unlikely((bio->bi_sector & chunk_mask) + bio_sectors(bio)
 		     > chunk_sects
 		     && (conf->geo.near_copies < conf->geo.raid_disks
 			 || conf->prev.near_copies < conf->prev.raid_disks))) {
 		struct bio_pair *bp;
 		/* Sanity check -- queue functions should prevent this happening */
-		if ((bio->bi_vcnt != 1 && bio->bi_vcnt != 0) ||
-		    bio->bi_idx != 0)
+		if (bio_segments(bio) > 1)
 			goto bad_map;
 		/* This is a one page bio that upper layers
 		 * refuse to split for us, so we need to split it.
@@ -1209,7 +1211,7 @@ static void make_request(struct mddev *mddev, struct bio * bio)
 	bad_map:
 		printk("md/raid10:%s: make_request bug: can't convert block across chunks"
 		       " or bigger than %dk %llu %d\n", mdname(mddev), chunk_sects/2,
-		       (unsigned long long)bio->bi_sector, bio->bi_size >> 10);
+		       (unsigned long long)bio->bi_sector, bio_sectors(bio) / 2);
 
 		bio_io_error(bio);
 		return;
@@ -1224,7 +1226,7 @@ static void make_request(struct mddev *mddev, struct bio * bio)
 	 */
 	wait_barrier(conf);
 
-	sectors = bio->bi_size >> 9;
+	sectors = bio_sectors(bio);
 	while (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) &&
 	    bio->bi_sector < conf->reshape_progress &&
 	    bio->bi_sector + sectors > conf->reshape_progress) {
@@ -1326,8 +1328,7 @@ read_again:
 			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->sectors = bio_sectors(bio) - sectors_handled;
 			r10_bio->state = 0;
 			r10_bio->mddev = mddev;
 			r10_bio->sector = bio->bi_sector + sectors_handled;
@@ -1569,7 +1570,7 @@ retry_write:
 	 * after checking if we need to go around again.
 	 */
 
-	if (sectors_handled < (bio->bi_size >> 9)) {
+	if (sectors_handled < bio_sectors(bio)) {
 		one_write_done(r10_bio);
 		/* We need another r10_bio.  It has already been counted
 		 * in bio->bi_phys_segments.
@@ -1577,7 +1578,7 @@ retry_write:
 		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->sectors = bio_sectors(bio) - sectors_handled;
 
 		r10_bio->mddev = mddev;
 		r10_bio->sector = bio->bi_sector + sectors_handled;
@@ -1909,7 +1910,8 @@ abort:
 }
 
 
-static void end_sync_read(struct bio *bio, int error)
+static void end_sync_read(struct bio *bio, int error,
+			  struct batch_complete *batch)
 {
 	struct r10bio *r10_bio = bio->bi_private;
 	struct r10conf *conf = r10_bio->mddev->private;
@@ -1970,7 +1972,8 @@ static void end_sync_request(struct r10bio *r10_bio)
 	}
 }
 
-static void end_sync_write(struct bio *bio, int error)
+static void end_sync_write(struct bio *bio, int error,
+			   struct batch_complete *batch)
 {
 	int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
 	struct r10bio *r10_bio = bio->bi_private;
@@ -2079,13 +2082,10 @@ static void sync_request_write(struct mddev *mddev, struct r10bio *r10_bio)
 		 * First we need to fixup bv_offset, bv_len and
 		 * bi_vecs, as the read request might have corrupted these
 		 */
+		bio_reset(tbio);
+
 		tbio->bi_vcnt = vcnt;
 		tbio->bi_size = r10_bio->sectors << 9;
-		tbio->bi_idx = 0;
-		tbio->bi_phys_segments = 0;
-		tbio->bi_flags &= ~(BIO_POOL_MASK - 1);
-		tbio->bi_flags |= 1 << BIO_UPTODATE;
-		tbio->bi_next = NULL;
 		tbio->bi_rw = WRITE;
 		tbio->bi_private = r10_bio;
 		tbio->bi_sector = r10_bio->devs[i].addr;
@@ -2103,7 +2103,7 @@ static void sync_request_write(struct mddev *mddev, struct r10bio *r10_bio)
 		d = r10_bio->devs[i].devnum;
 		atomic_inc(&conf->mirrors[d].rdev->nr_pending);
 		atomic_inc(&r10_bio->remaining);
-		md_sync_acct(conf->mirrors[d].rdev->bdev, tbio->bi_size >> 9);
+		md_sync_acct(conf->mirrors[d].rdev->bdev, bio_sectors(tbio));
 
 		tbio->bi_sector += conf->mirrors[d].rdev->data_offset;
 		tbio->bi_bdev = conf->mirrors[d].rdev->bdev;
@@ -2128,7 +2128,7 @@ static void sync_request_write(struct mddev *mddev, struct r10bio *r10_bio)
 		d = r10_bio->devs[i].devnum;
 		atomic_inc(&r10_bio->remaining);
 		md_sync_acct(conf->mirrors[d].replacement->bdev,
-			     tbio->bi_size >> 9);
+			     bio_sectors(tbio));
 		generic_make_request(tbio);
 	}
 
@@ -2254,13 +2254,13 @@ static void recovery_request_write(struct mddev *mddev, struct r10bio *r10_bio)
 	wbio2 = r10_bio->devs[1].repl_bio;
 	if (wbio->bi_end_io) {
 		atomic_inc(&conf->mirrors[d].rdev->nr_pending);
-		md_sync_acct(conf->mirrors[d].rdev->bdev, wbio->bi_size >> 9);
+		md_sync_acct(conf->mirrors[d].rdev->bdev, bio_sectors(wbio));
 		generic_make_request(wbio);
 	}
 	if (wbio2 && wbio2->bi_end_io) {
 		atomic_inc(&conf->mirrors[d].replacement->nr_pending);
 		md_sync_acct(conf->mirrors[d].replacement->bdev,
-			     wbio2->bi_size >> 9);
+			     bio_sectors(wbio2));
 		generic_make_request(wbio2);
 	}
 }
@@ -2531,25 +2531,6 @@ static void fix_read_error(struct r10conf *conf, struct mddev *mddev, struct r10
 	}
 }
 
-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(struct r10bio *r10_bio, int i)
 {
 	struct bio *bio = r10_bio->master_bio;
@@ -2690,8 +2671,7 @@ read_more:
 		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->sectors = bio_sectors(mbio) - sectors_handled;
 		r10_bio->state = 0;
 		set_bit(R10BIO_ReadError,
 			&r10_bio->state);
@@ -2913,6 +2893,22 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr,
 		if (init_resync(conf))
 			return 0;
 
+	/*
+	 * Allow skipping a full rebuild for incremental assembly
+	 * of a clean array, like RAID1 does.
+	 */
+	if (mddev->bitmap == NULL &&
+	    mddev->recovery_cp == MaxSector &&
+	    !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery) &&
+	    conf->fullsync == 0) {
+		*skipped = 1;
+		max_sector = mddev->dev_sectors;
+		if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery) ||
+		    test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery))
+			max_sector = mddev->resync_max_sectors;
+		return max_sector - sector_nr;
+	}
+
  skipped:
 	max_sector = mddev->dev_sectors;
 	if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery) ||
@@ -3112,6 +3108,7 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr,
 					}
 				}
 				bio = r10_bio->devs[0].bio;
+				bio_reset(bio);
 				bio->bi_next = biolist;
 				biolist = bio;
 				bio->bi_private = r10_bio;
@@ -3136,6 +3133,7 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr,
 				rdev = mirror->rdev;
 				if (!test_bit(In_sync, &rdev->flags)) {
 					bio = r10_bio->devs[1].bio;
+					bio_reset(bio);
 					bio->bi_next = biolist;
 					biolist = bio;
 					bio->bi_private = r10_bio;
@@ -3164,6 +3162,7 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr,
 				if (rdev == NULL || bio == NULL ||
 				    test_bit(Faulty, &rdev->flags))
 					break;
+				bio_reset(bio);
 				bio->bi_next = biolist;
 				biolist = bio;
 				bio->bi_private = r10_bio;
@@ -3262,7 +3261,7 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr,
 				r10_bio->devs[i].repl_bio->bi_end_io = NULL;
 
 			bio = r10_bio->devs[i].bio;
-			bio->bi_end_io = NULL;
+			bio_reset(bio);
 			clear_bit(BIO_UPTODATE, &bio->bi_flags);
 			if (conf->mirrors[d].rdev == NULL ||
 			    test_bit(Faulty, &conf->mirrors[d].rdev->flags))
@@ -3299,6 +3298,7 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr,
 
 			/* Need to set up for writing to the replacement */
 			bio = r10_bio->devs[i].repl_bio;
+			bio_reset(bio);
 			clear_bit(BIO_UPTODATE, &bio->bi_flags);
 
 			sector = r10_bio->devs[i].addr;
@@ -3332,17 +3332,6 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr,
 		}
 	}
 
-	for (bio = biolist; bio ; bio=bio->bi_next) {
-
-		bio->bi_flags &= ~(BIO_POOL_MASK - 1);
-		if (bio->bi_end_io)
-			bio->bi_flags |= 1 << BIO_UPTODATE;
-		bio->bi_vcnt = 0;
-		bio->bi_idx = 0;
-		bio->bi_phys_segments = 0;
-		bio->bi_size = 0;
-	}
-
 	nr_sectors = 0;
 	if (sector_nr + max_sync < max_sector)
 		max_sector = sector_nr + max_sync;
@@ -4389,7 +4378,6 @@ read_more:
 	read_bio->bi_flags &= ~(BIO_POOL_MASK - 1);
 	read_bio->bi_flags |= 1 << BIO_UPTODATE;
 	read_bio->bi_vcnt = 0;
-	read_bio->bi_idx = 0;
 	read_bio->bi_size = 0;
 	r10_bio->master_bio = read_bio;
 	r10_bio->read_slot = r10_bio->devs[r10_bio->read_slot].devnum;
@@ -4413,17 +4401,14 @@ read_more:
 		}
 		if (!rdev2 || test_bit(Faulty, &rdev2->flags))
 			continue;
+
+		bio_reset(b);
 		b->bi_bdev = rdev2->bdev;
 		b->bi_sector = r10_bio->devs[s/2].addr + rdev2->new_data_offset;
 		b->bi_private = r10_bio;
 		b->bi_end_io = end_reshape_write;
 		b->bi_rw = WRITE;
-		b->bi_flags &= ~(BIO_POOL_MASK - 1);
-		b->bi_flags |= 1 << BIO_UPTODATE;
 		b->bi_next = blist;
-		b->bi_vcnt = 0;
-		b->bi_idx = 0;
-		b->bi_size = 0;
 		blist = b;
 	}
 
@@ -4612,7 +4597,8 @@ static int handle_reshape_read_error(struct mddev *mddev,
 	return 0;
 }
 
-static void end_reshape_write(struct bio *bio, int error)
+static void end_reshape_write(struct bio *bio, int error,
+			      struct batch_complete *batch)
 {
 	int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
 	struct r10bio *r10_bio = bio->bi_private;
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 24909eb..16637f6 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -90,7 +90,7 @@ static inline struct hlist_head *stripe_hash(struct r5conf *conf, sector_t sect)
  */
 static inline struct bio *r5_next_bio(struct bio *bio, sector_t sector)
 {
-	int sectors = bio->bi_size >> 9;
+	int sectors = bio_sectors(bio);
 	if (bio->bi_sector + sectors < sector + STRIPE_SECTORS)
 		return bio->bi_next;
 	else
@@ -198,6 +198,21 @@ static int stripe_operations_active(struct stripe_head *sh)
 	       test_bit(STRIPE_COMPUTE_RUN, &sh->state);
 }
 
+static void raid5_wakeup_stripe_thread(struct stripe_head *sh)
+{
+	struct r5conf *conf = sh->raid_conf;
+	struct raid5_percpu *percpu;
+	int i, orphaned = 1;
+
+	percpu = per_cpu_ptr(conf->percpu, sh->cpu);
+	for_each_cpu(i, &percpu->handle_threads) {
+		md_wakeup_thread(conf->aux_threads[i]->thread);
+		orphaned = 0;
+	}
+	if (orphaned)
+		md_wakeup_thread(conf->mddev->thread);
+}
+
 static void do_release_stripe(struct r5conf *conf, struct stripe_head *sh)
 {
 	BUG_ON(!list_empty(&sh->lru));
@@ -210,9 +225,19 @@ static void do_release_stripe(struct r5conf *conf, struct stripe_head *sh)
 			   sh->bm_seq - conf->seq_write > 0)
 			list_add_tail(&sh->lru, &conf->bitmap_list);
 		else {
+			int cpu = sh->cpu;
+			struct raid5_percpu *percpu;
+			if (!cpu_online(cpu)) {
+				cpu = cpumask_any(cpu_online_mask);
+				sh->cpu = cpu;
+			}
+			percpu = per_cpu_ptr(conf->percpu, cpu);
+
 			clear_bit(STRIPE_DELAYED, &sh->state);
 			clear_bit(STRIPE_BIT_DELAY, &sh->state);
-			list_add_tail(&sh->lru, &conf->handle_list);
+			list_add_tail(&sh->lru, &percpu->handle_list);
+			raid5_wakeup_stripe_thread(sh);
+			return;
 		}
 		md_wakeup_thread(conf->mddev->thread);
 	} else {
@@ -237,12 +262,46 @@ static void __release_stripe(struct r5conf *conf, struct stripe_head *sh)
 		do_release_stripe(conf, sh);
 }
 
+/* should hold conf->device_lock already */
+static int release_stripe_list(struct r5conf *conf)
+{
+	struct stripe_head *sh;
+	int count = 0;
+
+	llist_for_each_entry(sh, llist_del_all(&conf->released_stripes),
+			     release_list) {
+		/*
+		 * llist_del_all() uses cmpxchg, so implies a memory fence.
+		 * It's guaranteed the stripe isn't in released_stripes list
+		 * now, clearing STRIPE_ON_RELEASE_LIST is safe.
+		 */
+		clear_bit(STRIPE_ON_RELEASE_LIST, &sh->state);
+		/*
+		 * Don't worry the bit is set here, because if the bit is set
+		 * again, the count is always > 1. This is true for
+		 * STRIPE_ON_UNPLUG_LIST bit too.
+		 */
+		__release_stripe(conf, sh);
+		count++;
+	}
+	return count;
+}
+
 static void release_stripe(struct stripe_head *sh)
 {
 	struct r5conf *conf = sh->raid_conf;
 	unsigned long flags;
+	bool wakeup;
 
+	if (test_and_set_bit(STRIPE_ON_RELEASE_LIST, &sh->state))
+		goto slow_path;
+	wakeup = llist_add(&sh->release_list, &conf->released_stripes);
+	if (wakeup)
+		md_wakeup_thread(conf->mddev->thread);
+	return;
+slow_path:
 	local_irq_save(flags);
+	/* we are ok here if STRIPE_ON_RELEASE_LIST is set or not */
 	if (atomic_dec_and_lock(&sh->count, &conf->device_lock)) {
 		do_release_stripe(conf, sh);
 		spin_unlock(&conf->device_lock);
@@ -357,6 +416,7 @@ static void init_stripe(struct stripe_head *sh, sector_t sector, int previous)
 		raid5_build_block(sh, i, previous);
 	}
 	insert_hash(conf, sh);
+	sh->cpu = smp_processor_id();
 }
 
 static struct stripe_head *__find_stripe(struct r5conf *conf, sector_t sector,
@@ -489,7 +549,8 @@ get_active_stripe(struct r5conf *conf, sector_t sector,
 			if (atomic_read(&sh->count)) {
 				BUG_ON(!list_empty(&sh->lru)
 				    && !test_bit(STRIPE_EXPANDING, &sh->state)
-				    && !test_bit(STRIPE_ON_UNPLUG_LIST, &sh->state));
+				    && !test_bit(STRIPE_ON_UNPLUG_LIST, &sh->state)
+				    && !test_bit(STRIPE_ON_RELEASE_LIST, &sh->state));
 			} else {
 				if (!test_bit(STRIPE_HANDLE, &sh->state))
 					atomic_inc(&conf->active_stripes);
@@ -530,9 +591,11 @@ static int use_new_offset(struct r5conf *conf, struct stripe_head *sh)
 }
 
 static void
-raid5_end_read_request(struct bio *bi, int error);
+raid5_end_read_request(struct bio *bi, int error,
+		       struct batch_complete *batch);
 static void
-raid5_end_write_request(struct bio *bi, int error);
+raid5_end_write_request(struct bio *bi, int error,
+			struct batch_complete *batch);
 
 static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
 {
@@ -567,14 +630,6 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
 		bi = &sh->dev[i].req;
 		rbi = &sh->dev[i].rreq; /* For writing to replacement */
 
-		bi->bi_rw = rw;
-		rbi->bi_rw = rw;
-		if (rw & WRITE) {
-			bi->bi_end_io = raid5_end_write_request;
-			rbi->bi_end_io = raid5_end_write_request;
-		} else
-			bi->bi_end_io = raid5_end_read_request;
-
 		rcu_read_lock();
 		rrdev = rcu_dereference(conf->disks[i].replacement);
 		smp_mb(); /* Ensure that if rrdev is NULL, rdev won't be */
@@ -649,7 +704,14 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
 
 			set_bit(STRIPE_IO_STARTED, &sh->state);
 
+			bio_reset(bi);
 			bi->bi_bdev = rdev->bdev;
+			bi->bi_rw = rw;
+			bi->bi_end_io = (rw & WRITE)
+				? raid5_end_write_request
+				: raid5_end_read_request;
+			bi->bi_private = sh;
+
 			pr_debug("%s: for %llu schedule op %ld on disc %d\n",
 				__func__, (unsigned long long)sh->sector,
 				bi->bi_rw, i);
@@ -663,12 +725,9 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
 			if (test_bit(R5_ReadNoMerge, &sh->dev[i].flags))
 				bi->bi_rw |= REQ_FLUSH;
 
-			bi->bi_flags = 1 << BIO_UPTODATE;
-			bi->bi_idx = 0;
 			bi->bi_io_vec[0].bv_len = STRIPE_SIZE;
 			bi->bi_io_vec[0].bv_offset = 0;
 			bi->bi_size = STRIPE_SIZE;
-			bi->bi_next = NULL;
 			if (rrdev)
 				set_bit(R5_DOUBLE_LOCKED, &sh->dev[i].flags);
 
@@ -685,7 +744,13 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
 
 			set_bit(STRIPE_IO_STARTED, &sh->state);
 
+			bio_reset(rbi);
 			rbi->bi_bdev = rrdev->bdev;
+			rbi->bi_rw = rw;
+			BUG_ON(!(rw & WRITE));
+			rbi->bi_end_io = raid5_end_write_request;
+			rbi->bi_private = sh;
+
 			pr_debug("%s: for %llu schedule op %ld on "
 				 "replacement disc %d\n",
 				__func__, (unsigned long long)sh->sector,
@@ -697,12 +762,9 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
 			else
 				rbi->bi_sector = (sh->sector
 						  + rrdev->data_offset);
-			rbi->bi_flags = 1 << BIO_UPTODATE;
-			rbi->bi_idx = 0;
 			rbi->bi_io_vec[0].bv_len = STRIPE_SIZE;
 			rbi->bi_io_vec[0].bv_offset = 0;
 			rbi->bi_size = STRIPE_SIZE;
-			rbi->bi_next = NULL;
 			if (conf->mddev->gendisk)
 				trace_block_bio_remap(bdev_get_queue(rbi->bi_bdev),
 						      rbi, disk_devt(conf->mddev->gendisk),
@@ -1712,7 +1774,8 @@ static void shrink_stripes(struct r5conf *conf)
 	conf->slab_cache = NULL;
 }
 
-static void raid5_end_read_request(struct bio * bi, int error)
+static void raid5_end_read_request(struct bio *bi, int error,
+				   struct batch_complete *batch)
 {
 	struct stripe_head *sh = bi->bi_private;
 	struct r5conf *conf = sh->raid_conf;
@@ -1832,7 +1895,8 @@ static void raid5_end_read_request(struct bio * bi, int error)
 	release_stripe(sh);
 }
 
-static void raid5_end_write_request(struct bio *bi, int error)
+static void raid5_end_write_request(struct bio *bi, int error,
+				    struct batch_complete *batch)
 {
 	struct stripe_head *sh = bi->bi_private;
 	struct r5conf *conf = sh->raid_conf;
@@ -1885,8 +1949,15 @@ static void raid5_end_write_request(struct bio *bi, int error)
 					&rdev->mddev->recovery);
 		} else if (is_badblock(rdev, sh->sector,
 				       STRIPE_SECTORS,
-				       &first_bad, &bad_sectors))
+				       &first_bad, &bad_sectors)) {
 			set_bit(R5_MadeGood, &sh->dev[i].flags);
+			if (test_bit(R5_ReadError, &sh->dev[i].flags))
+				/* That was a successful write so make
+				 * sure it looks like we already did
+				 * a re-write.
+				 */
+				set_bit(R5_ReWrite, &sh->dev[i].flags);
+		}
 	}
 	rdev_dec_pending(rdev, conf->mddev);
 
@@ -2393,11 +2464,11 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in
 	} else
 		bip = &sh->dev[dd_idx].toread;
 	while (*bip && (*bip)->bi_sector < bi->bi_sector) {
-		if ((*bip)->bi_sector + ((*bip)->bi_size >> 9) > bi->bi_sector)
+		if (bio_end_sector(*bip) > bi->bi_sector)
 			goto overlap;
 		bip = & (*bip)->bi_next;
 	}
-	if (*bip && (*bip)->bi_sector < bi->bi_sector + ((bi->bi_size)>>9))
+	if (*bip && (*bip)->bi_sector < bio_end_sector(bi))
 		goto overlap;
 
 	BUG_ON(*bip && bi->bi_next && (*bip) != bi->bi_next);
@@ -2413,8 +2484,8 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in
 		     sector < sh->dev[dd_idx].sector + STRIPE_SECTORS &&
 			     bi && bi->bi_sector <= sector;
 		     bi = r5_next_bio(bi, sh->dev[dd_idx].sector)) {
-			if (bi->bi_sector + (bi->bi_size>>9) >= sector)
-				sector = bi->bi_sector + (bi->bi_size>>9);
+			if (bio_end_sector(bi) >= sector)
+				sector = bio_end_sector(bi);
 		}
 		if (sector >= sh->dev[dd_idx].sector + STRIPE_SECTORS)
 			set_bit(R5_OVERWRITE, &sh->dev[dd_idx].flags);
@@ -3758,12 +3829,19 @@ static void raid5_activate_delayed(struct r5conf *conf)
 		while (!list_empty(&conf->delayed_list)) {
 			struct list_head *l = conf->delayed_list.next;
 			struct stripe_head *sh;
+			int cpu;
 			sh = list_entry(l, struct stripe_head, lru);
 			list_del_init(l);
 			clear_bit(STRIPE_DELAYED, &sh->state);
 			if (!test_and_set_bit(STRIPE_PREREAD_ACTIVE, &sh->state))
 				atomic_inc(&conf->preread_active_stripes);
 			list_add_tail(&sh->lru, &conf->hold_list);
+			cpu = sh->cpu;
+			if (!cpu_online(cpu)) {
+				cpu = cpumask_any(cpu_online_mask);
+				sh->cpu = cpu;
+			}
+			raid5_wakeup_stripe_thread(sh);
 		}
 	}
 }
@@ -3840,7 +3918,7 @@ static int in_chunk_boundary(struct mddev *mddev, struct bio *bio)
 {
 	sector_t sector = bio->bi_sector + get_start_sect(bio->bi_bdev);
 	unsigned int chunk_sectors = mddev->chunk_sectors;
-	unsigned int bio_sectors = bio->bi_size >> 9;
+	unsigned int bio_sectors = bio_sectors(bio);
 
 	if (mddev->new_chunk_sectors < mddev->chunk_sectors)
 		chunk_sectors = mddev->new_chunk_sectors;
@@ -3896,7 +3974,8 @@ static struct bio *remove_bio_from_retry(struct r5conf *conf)
  *  first).
  *  If the read failed..
  */
-static void raid5_align_endio(struct bio *bi, int error)
+static void raid5_align_endio(struct bio *bi, int error,
+			      struct batch_complete *batch)
 {
 	struct bio* raid_bi  = bi->bi_private;
 	struct mddev *mddev;
@@ -3930,7 +4009,7 @@ static int bio_fits_rdev(struct bio *bi)
 {
 	struct request_queue *q = bdev_get_queue(bi->bi_bdev);
 
-	if ((bi->bi_size>>9) > queue_max_sectors(q))
+	if (bio_sectors(bi) > queue_max_sectors(q))
 		return 0;
 	blk_recount_segments(q, bi);
 	if (bi->bi_phys_segments > queue_max_segments(q))
@@ -3977,7 +4056,7 @@ static int chunk_aligned_read(struct mddev *mddev, struct bio * raid_bio)
 						    0,
 						    &dd_idx, NULL);
 
-	end_sector = align_bi->bi_sector + (align_bi->bi_size >> 9);
+	end_sector = bio_end_sector(align_bi);
 	rcu_read_lock();
 	rdev = rcu_dereference(conf->disks[dd_idx].replacement);
 	if (!rdev || test_bit(Faulty, &rdev->flags) ||
@@ -4000,7 +4079,7 @@ static int chunk_aligned_read(struct mddev *mddev, struct bio * raid_bio)
 		align_bi->bi_flags &= ~(1 << BIO_SEG_VALID);
 
 		if (!bio_fits_rdev(align_bi) ||
-		    is_badblock(rdev, align_bi->bi_sector, align_bi->bi_size>>9,
+		    is_badblock(rdev, align_bi->bi_sector, bio_sectors(align_bi),
 				&first_bad, &bad_sectors)) {
 			/* too big in some way, or has a known bad block */
 			bio_put(align_bi);
@@ -4041,18 +4120,29 @@ static int chunk_aligned_read(struct mddev *mddev, struct bio * raid_bio)
  * head of the hold_list has changed, i.e. the head was promoted to the
  * handle_list.
  */
-static struct stripe_head *__get_priority_stripe(struct r5conf *conf)
-{
-	struct stripe_head *sh;
-
+static struct stripe_head *__get_priority_stripe(struct r5conf *conf,
+	cpumask_t *mask)
+{
+	struct stripe_head *sh = NULL, *tmp;
+	struct list_head *handle_list = NULL;
+	int cpu;
+
+	/* Should we take action to avoid starvation of latter CPUs ? */
+	for_each_cpu(cpu, mask) {
+		struct raid5_percpu *percpu = per_cpu_ptr(conf->percpu, cpu);
+		if (!list_empty(&percpu->handle_list)) {
+			handle_list = &percpu->handle_list;
+			break;
+		}
+	}
 	pr_debug("%s: handle: %s hold: %s full_writes: %d bypass_count: %d\n",
 		  __func__,
-		  list_empty(&conf->handle_list) ? "empty" : "busy",
+		  !handle_list ? "empty" : "busy",
 		  list_empty(&conf->hold_list) ? "empty" : "busy",
 		  atomic_read(&conf->pending_full_writes), conf->bypass_count);
 
-	if (!list_empty(&conf->handle_list)) {
-		sh = list_entry(conf->handle_list.next, typeof(*sh), lru);
+	if (handle_list) {
+		sh = list_entry(handle_list->next, typeof(*sh), lru);
 
 		if (list_empty(&conf->hold_list))
 			conf->bypass_count = 0;
@@ -4070,12 +4160,23 @@ static struct stripe_head *__get_priority_stripe(struct r5conf *conf)
 		   ((conf->bypass_threshold &&
 		     conf->bypass_count > conf->bypass_threshold) ||
 		    atomic_read(&conf->pending_full_writes) == 0)) {
-		sh = list_entry(conf->hold_list.next,
-				typeof(*sh), lru);
-		conf->bypass_count -= conf->bypass_threshold;
-		if (conf->bypass_count < 0)
-			conf->bypass_count = 0;
-	} else
+
+		list_for_each_entry(tmp, &conf->hold_list,  lru) {
+			if (cpumask_test_cpu(tmp->cpu, mask) ||
+			    !cpu_online(tmp->cpu)) {
+				sh = tmp;
+				break;
+			}
+		}
+
+		if (sh) {
+			conf->bypass_count -= conf->bypass_threshold;
+			if (conf->bypass_count < 0)
+				conf->bypass_count = 0;
+		}
+	}
+
+	if (!sh)
 		return NULL;
 
 	list_del_init(&sh->lru);
@@ -4110,6 +4211,10 @@ static void raid5_unplug(struct blk_plug_cb *blk_cb, bool from_schedule)
 			 */
 			smp_mb__before_clear_bit();
 			clear_bit(STRIPE_ON_UNPLUG_LIST, &sh->state);
+			/*
+			 * STRIPE_ON_RELEASE_LIST could be set here. In that
+			 * case, the count is always > 1 here
+			 */
 			__release_stripe(conf, sh);
 			cnt++;
 		}
@@ -4262,7 +4367,7 @@ static void make_request(struct mddev *mddev, struct bio * bi)
 	}
 
 	logical_sector = bi->bi_sector & ~((sector_t)STRIPE_SECTORS-1);
-	last_sector = bi->bi_sector + (bi->bi_size>>9);
+	last_sector = bio_end_sector(bi);
 	bi->bi_next = NULL;
 	bi->bi_phys_segments = 1;	/* over-loaded to count active stripes */
 
@@ -4666,9 +4771,10 @@ static inline sector_t sync_request(struct mddev *mddev, sector_t sector_nr, int
 		*skipped = 1;
 		return rv;
 	}
-	if (!bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, 1) &&
-	    !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery) &&
-	    !conf->fullsync && sync_blocks >= STRIPE_SECTORS) {
+	if (!test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery) &&
+	    !conf->fullsync &&
+	    !bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, 1) &&
+	    sync_blocks >= STRIPE_SECTORS) {
 		/* we can skip this block, and probably more */
 		sync_blocks /= STRIPE_SECTORS;
 		*skipped = 1;
@@ -4725,7 +4831,7 @@ static int  retry_aligned_read(struct r5conf *conf, struct bio *raid_bio)
 	logical_sector = raid_bio->bi_sector & ~((sector_t)STRIPE_SECTORS-1);
 	sector = raid5_compute_sector(conf, logical_sector,
 				      0, &dd_idx, NULL);
-	last_sector = raid_bio->bi_sector + (raid_bio->bi_size>>9);
+	last_sector = bio_end_sector(raid_bio);
 
 	for (; logical_sector < last_sector;
 	     logical_sector += STRIPE_SECTORS,
@@ -4766,13 +4872,13 @@ static int  retry_aligned_read(struct r5conf *conf, struct bio *raid_bio)
 }
 
 #define MAX_STRIPE_BATCH 8
-static int handle_active_stripes(struct r5conf *conf)
+static int handle_active_stripes(struct r5conf *conf, cpumask_t *mask)
 {
 	struct stripe_head *batch[MAX_STRIPE_BATCH], *sh;
 	int i, batch_size = 0;
 
 	while (batch_size < MAX_STRIPE_BATCH &&
-			(sh = __get_priority_stripe(conf)) != NULL)
+			(sh = __get_priority_stripe(conf, mask)) != NULL)
 		batch[batch_size++] = sh;
 
 	if (batch_size == 0)
@@ -4790,6 +4896,37 @@ static int handle_active_stripes(struct r5conf *conf)
 	return batch_size;
 }
 
+static void raid5auxd(struct md_thread *thread)
+{
+	struct mddev *mddev = thread->mddev;
+	struct r5conf *conf = mddev->private;
+	struct blk_plug plug;
+	int handled;
+	struct raid5_auxth *auxth = thread->private;
+
+	pr_debug("+++ raid5auxd active\n");
+
+	blk_start_plug(&plug);
+	handled = 0;
+	spin_lock_irq(&conf->device_lock);
+	while (1) {
+		int batch_size, released;
+
+		released = release_stripe_list(conf);
+
+		batch_size = handle_active_stripes(conf, &auxth->work_mask);
+		if (!batch_size && !released)
+			break;
+		handled += batch_size;
+	}
+	pr_debug("%d stripes handled\n", handled);
+
+	spin_unlock_irq(&conf->device_lock);
+	blk_finish_plug(&plug);
+
+	pr_debug("--- raid5auxd inactive\n");
+}
+
 /*
  * This is our raid5 kernel thread.
  *
@@ -4813,7 +4950,9 @@ static void raid5d(struct md_thread *thread)
 	spin_lock_irq(&conf->device_lock);
 	while (1) {
 		struct bio *bio;
-		int batch_size;
+		int batch_size, released;
+
+		released = release_stripe_list(conf);
 
 		if (
 		    !list_empty(&conf->bitmap_list)) {
@@ -4837,8 +4976,8 @@ static void raid5d(struct md_thread *thread)
 			handled++;
 		}
 
-		batch_size = handle_active_stripes(conf);
-		if (!batch_size)
+		batch_size = handle_active_stripes(conf, &conf->work_mask);
+		if (!batch_size && !released)
 			break;
 		handled += batch_size;
 
@@ -4966,10 +5105,270 @@ stripe_cache_active_show(struct mddev *mddev, char *page)
 static struct md_sysfs_entry
 raid5_stripecache_active = __ATTR_RO(stripe_cache_active);
 
+static void raid5_update_threads_handle_mask(struct mddev *mddev)
+{
+	int cpu, i;
+	struct raid5_percpu *percpu;
+	struct r5conf *conf = mddev->private;
+
+	for_each_online_cpu(cpu) {
+		percpu = per_cpu_ptr(conf->percpu, cpu);
+		cpumask_clear(&percpu->handle_threads);
+	}
+	cpumask_copy(&conf->work_mask, cpu_online_mask);
+
+	for (i = 0; i < conf->aux_thread_num; i++) {
+		cpumask_t *work_mask = &conf->aux_threads[i]->work_mask;
+		for_each_cpu(cpu, work_mask) {
+			percpu = per_cpu_ptr(conf->percpu, cpu);
+			cpumask_set_cpu(i, &percpu->handle_threads);
+		}
+		cpumask_andnot(&conf->work_mask, &conf->work_mask,
+				work_mask);
+	}
+}
+
+struct raid5_auxth_sysfs {
+	struct attribute attr;
+	ssize_t (*show)(struct mddev *, struct raid5_auxth *, char *);
+	ssize_t (*store)(struct mddev *, struct raid5_auxth *,
+		const char *, size_t);
+};
+
+static ssize_t raid5_show_thread_cpulist(struct mddev *mddev,
+	struct raid5_auxth *thread, char *page)
+{
+	if (!mddev->private)
+		return 0;
+	return cpulist_scnprintf(page, PAGE_SIZE, &thread->work_mask);
+}
+
+static ssize_t
+raid5_store_thread_cpulist(struct mddev *mddev, struct raid5_auxth *thread,
+	const char *page, size_t len)
+{
+	struct r5conf *conf = mddev->private;
+	cpumask_var_t mask;
+
+	if (!conf)
+		return -ENODEV;
+	if (!alloc_cpumask_var(&mask, GFP_KERNEL))
+		return -ENOMEM;
+
+	if (cpulist_parse(page, mask)) {
+		free_cpumask_var(mask);
+		return -EINVAL;
+	}
+
+	get_online_cpus();
+	spin_lock_irq(&conf->device_lock);
+	cpumask_copy(&thread->work_mask, mask);
+	raid5_update_threads_handle_mask(mddev);
+	spin_unlock_irq(&conf->device_lock);
+	put_online_cpus();
+	set_cpus_allowed_ptr(thread->thread->tsk, mask);
+
+	free_cpumask_var(mask);
+	return len;
+}
+
+static struct raid5_auxth_sysfs thread_cpulist =
+__ATTR(cpulist, S_IRUGO|S_IWUSR, raid5_show_thread_cpulist,
+	raid5_store_thread_cpulist);
+
+static struct attribute *auxth_attrs[] = {
+	&thread_cpulist.attr,
+	NULL,
+};
+
+static ssize_t
+raid5_auxth_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
+{
+	struct raid5_auxth_sysfs *entry = container_of(attr,
+		struct raid5_auxth_sysfs, attr);
+	struct raid5_auxth *thread = container_of(kobj,
+		struct raid5_auxth, kobj);
+	struct mddev *mddev = thread->thread->mddev;
+	ssize_t ret;
+
+	if (!entry->show)
+		return -EIO;
+	mddev_lock(mddev);
+	ret = entry->show(mddev, thread, page);
+	mddev_unlock(mddev);
+	return ret;
+}
+
+static ssize_t
+raid5_auxth_attr_store(struct kobject *kobj, struct attribute *attr,
+	      const char *page, size_t length)
+{
+	struct raid5_auxth_sysfs *entry = container_of(attr,
+		struct raid5_auxth_sysfs, attr);
+	struct raid5_auxth *thread = container_of(kobj,
+		struct raid5_auxth, kobj);
+	struct mddev *mddev = thread->thread->mddev;
+	ssize_t ret;
+
+	if (!entry->store)
+		return -EIO;
+	if (!capable(CAP_SYS_ADMIN))
+		return -EACCES;
+	mddev_lock(mddev);
+	ret = entry->store(mddev, thread, page, length);
+	mddev_unlock(mddev);
+	return ret;
+}
+
+static void raid5_auxth_release(struct kobject *kobj)
+{
+	struct raid5_auxth *thread = container_of(kobj,
+		struct raid5_auxth, kobj);
+	kfree(thread);
+}
+
+static const struct sysfs_ops raid5_auxth_sysfsops = {
+	.show = raid5_auxth_attr_show,
+	.store = raid5_auxth_attr_store,
+};
+static struct kobj_type raid5_auxth_ktype = {
+	.release = raid5_auxth_release,
+	.sysfs_ops = &raid5_auxth_sysfsops,
+	.default_attrs = auxth_attrs,
+};
+
+static ssize_t
+raid5_show_auxthread_number(struct mddev *mddev, char *page)
+{
+	struct r5conf *conf = mddev->private;
+	if (conf)
+		return sprintf(page, "%d\n", conf->aux_thread_num);
+	else
+		return 0;
+}
+
+static void raid5_auxth_delete(struct work_struct *ws)
+{
+	struct raid5_auxth *thread = container_of(ws, struct raid5_auxth,
+		del_work);
+
+	kobject_del(&thread->kobj);
+	kobject_put(&thread->kobj);
+}
+
+static void __free_aux_thread(struct mddev *mddev, struct raid5_auxth *thread)
+{
+	md_unregister_thread(&thread->thread);
+	INIT_WORK(&thread->del_work, raid5_auxth_delete);
+	kobject_get(&thread->kobj);
+	md_queue_misc_work(&thread->del_work);
+}
+
+static struct raid5_auxth *__create_aux_thread(struct mddev *mddev, int i)
+{
+	struct raid5_auxth *thread;
+	char name[10];
+
+	thread = kzalloc(sizeof(*thread), GFP_KERNEL);
+	if (!thread)
+		return NULL;
+	snprintf(name, 10, "aux%d", i);
+	thread->thread = md_register_thread(raid5auxd, mddev, name);
+	if (!thread->thread) {
+		kfree(thread);
+		return NULL;
+	}
+	thread->thread->private = thread;
+
+	cpumask_copy(&thread->work_mask, cpu_online_mask);
+
+	if (kobject_init_and_add(&thread->kobj, &raid5_auxth_ktype,
+	    &mddev->kobj, "auxth%d", i)) {
+		md_unregister_thread(&thread->thread);
+		kfree(thread);
+		return NULL;
+	}
+	return thread;
+}
+
+static ssize_t
+raid5_store_auxthread_number(struct mddev *mddev, const char *page, size_t len)
+{
+	struct r5conf *conf = mddev->private;
+	unsigned long new;
+	int i;
+	struct raid5_auxth **threads;
+
+	if (len >= PAGE_SIZE)
+		return -EINVAL;
+	if (!conf)
+		return -ENODEV;
+
+	if (kstrtoul(page, 10, &new))
+		return -EINVAL;
+
+	if (new == conf->aux_thread_num)
+		return len;
+
+	/* There is no point creating more threads than cpu number */
+	if (new > num_online_cpus())
+		return -EINVAL;
+
+	if (new > conf->aux_thread_num) {
+		threads = kzalloc(sizeof(struct raid5_auxth *) * new,
+				GFP_KERNEL);
+		if (!threads)
+			return -ENOMEM;
+
+		i = conf->aux_thread_num;
+		while (i < new) {
+			threads[i] = __create_aux_thread(mddev, i);
+			if (!threads[i])
+				goto error;
+
+			i++;
+		}
+		memcpy(threads, conf->aux_threads,
+			sizeof(struct raid5_auxth *) * conf->aux_thread_num);
+		get_online_cpus();
+		spin_lock_irq(&conf->device_lock);
+		kfree(conf->aux_threads);
+		conf->aux_threads = threads;
+		conf->aux_thread_num = new;
+		raid5_update_threads_handle_mask(mddev);
+		spin_unlock_irq(&conf->device_lock);
+		put_online_cpus();
+	} else {
+		int old = conf->aux_thread_num;
+
+		get_online_cpus();
+		spin_lock_irq(&conf->device_lock);
+		conf->aux_thread_num = new;
+		raid5_update_threads_handle_mask(mddev);
+		spin_unlock_irq(&conf->device_lock);
+		put_online_cpus();
+		for (i = new; i < old; i++)
+			__free_aux_thread(mddev, conf->aux_threads[i]);
+	}
+
+	return len;
+error:
+	while (--i >= conf->aux_thread_num)
+		__free_aux_thread(mddev, threads[i]);
+	kfree(threads);
+	return -ENOMEM;
+}
+
+static struct md_sysfs_entry
+raid5_auxthread_number = __ATTR(auxthread_number, S_IRUGO|S_IWUSR,
+				raid5_show_auxthread_number,
+				raid5_store_auxthread_number);
+
 static struct attribute *raid5_attrs[] =  {
 	&raid5_stripecache_size.attr,
 	&raid5_stripecache_active.attr,
 	&raid5_preread_bypass_threshold.attr,
+	&raid5_auxthread_number.attr,
 	NULL,
 };
 static struct attribute_group raid5_attrs_group = {
@@ -5017,6 +5416,7 @@ static void raid5_free_percpu(struct r5conf *conf)
 
 static void free_conf(struct r5conf *conf)
 {
+	kfree(conf->aux_threads);
 	shrink_stripes(conf);
 	raid5_free_percpu(conf);
 	kfree(conf->disks);
@@ -5029,7 +5429,7 @@ static int raid456_cpu_notify(struct notifier_block *nfb, unsigned long action,
 			      void *hcpu)
 {
 	struct r5conf *conf = container_of(nfb, struct r5conf, cpu_notify);
-	long cpu = (long)hcpu;
+	long cpu = (long)hcpu, anycpu;
 	struct raid5_percpu *percpu = per_cpu_ptr(conf->percpu, cpu);
 
 	switch (action) {
@@ -5048,9 +5448,17 @@ static int raid456_cpu_notify(struct notifier_block *nfb, unsigned long action,
 			       __func__, cpu);
 			return notifier_from_errno(-ENOMEM);
 		}
+		INIT_LIST_HEAD(&(percpu->handle_list));
+		cpumask_clear(&percpu->handle_threads);
 		break;
 	case CPU_DEAD:
 	case CPU_DEAD_FROZEN:
+		spin_lock_irq(&conf->device_lock);
+		anycpu = cpumask_any(cpu_online_mask);
+		list_splice_tail_init(&percpu->handle_list,
+			&per_cpu_ptr(conf->percpu, anycpu)->handle_list);
+		spin_unlock_irq(&conf->device_lock);
+
 		safe_put_page(percpu->spare_page);
 		kfree(percpu->scribble);
 		percpu->spare_page = NULL;
@@ -5059,6 +5467,10 @@ static int raid456_cpu_notify(struct notifier_block *nfb, unsigned long action,
 	default:
 		break;
 	}
+
+	spin_lock_irq(&conf->device_lock);
+	raid5_update_threads_handle_mask(conf->mddev);
+	spin_unlock_irq(&conf->device_lock);
 	return NOTIFY_OK;
 }
 #endif
@@ -5079,20 +5491,24 @@ static int raid5_alloc_percpu(struct r5conf *conf)
 	get_online_cpus();
 	err = 0;
 	for_each_present_cpu(cpu) {
+		struct raid5_percpu *percpu = per_cpu_ptr(conf->percpu, cpu);
+
 		if (conf->level == 6) {
 			spare_page = alloc_page(GFP_KERNEL);
 			if (!spare_page) {
 				err = -ENOMEM;
 				break;
 			}
-			per_cpu_ptr(conf->percpu, cpu)->spare_page = spare_page;
+			percpu->spare_page = spare_page;
 		}
 		scribble = kmalloc(conf->scribble_len, GFP_KERNEL);
 		if (!scribble) {
 			err = -ENOMEM;
 			break;
 		}
-		per_cpu_ptr(conf->percpu, cpu)->scribble = scribble;
+		percpu->scribble = scribble;
+		INIT_LIST_HEAD(&percpu->handle_list);
+		cpumask_clear(&percpu->handle_threads);
 	}
 #ifdef CONFIG_HOTPLUG_CPU
 	conf->cpu_notify.notifier_call = raid456_cpu_notify;
@@ -5148,17 +5564,19 @@ static struct r5conf *setup_conf(struct mddev *mddev)
 	spin_lock_init(&conf->device_lock);
 	init_waitqueue_head(&conf->wait_for_stripe);
 	init_waitqueue_head(&conf->wait_for_overlap);
-	INIT_LIST_HEAD(&conf->handle_list);
 	INIT_LIST_HEAD(&conf->hold_list);
 	INIT_LIST_HEAD(&conf->delayed_list);
 	INIT_LIST_HEAD(&conf->bitmap_list);
 	INIT_LIST_HEAD(&conf->inactive_list);
+	init_llist_head(&conf->released_stripes);
 	atomic_set(&conf->active_stripes, 0);
 	atomic_set(&conf->preread_active_stripes, 0);
 	atomic_set(&conf->active_aligned_reads, 0);
 	conf->bypass_threshold = BYPASS_THRESHOLD;
 	conf->recovery_disabled = mddev->recovery_disabled - 1;
 
+	cpumask_copy(&conf->work_mask, cpu_online_mask);
+
 	conf->raid_disks = mddev->raid_disks;
 	if (mddev->reshape_position == MaxSector)
 		conf->previous_raid_disks = mddev->raid_disks;
@@ -5615,6 +6033,10 @@ abort:
 static int stop(struct mddev *mddev)
 {
 	struct r5conf *conf = mddev->private;
+	int i;
+
+	for (i = 0; i < conf->aux_thread_num; i++)
+		__free_aux_thread(mddev, conf->aux_threads[i]);
 
 	md_unregister_thread(&mddev->thread);
 	if (mddev->queue)
diff --git a/drivers/md/raid5.h b/drivers/md/raid5.h
index b0b663b..217cb19 100644
--- a/drivers/md/raid5.h
+++ b/drivers/md/raid5.h
@@ -197,6 +197,7 @@ enum reconstruct_states {
 struct stripe_head {
 	struct hlist_node	hash;
 	struct list_head	lru;	      /* inactive_list or handle_list */
+	struct llist_node	release_list;
 	struct r5conf		*raid_conf;
 	short			generation;	/* increments with every
 						 * reshape */
@@ -211,6 +212,7 @@ struct stripe_head {
 	enum check_states	check_state;
 	enum reconstruct_states reconstruct_state;
 	spinlock_t		stripe_lock;
+	int			cpu;
 	/**
 	 * struct stripe_operations
 	 * @target - STRIPE_OP_COMPUTE_BLK target
@@ -320,6 +322,7 @@ enum {
 	STRIPE_OPS_REQ_PENDING,
 	STRIPE_ON_UNPLUG_LIST,
 	STRIPE_DISCARD,
+	STRIPE_ON_RELEASE_LIST,
 };
 
 /*
@@ -362,6 +365,14 @@ struct disk_info {
 	struct md_rdev	*rdev, *replacement;
 };
 
+struct raid5_auxth {
+	struct md_thread	*thread;
+	/* which CPUs should the auxiliary thread handle stripes from */
+	cpumask_t		work_mask;
+	struct kobject		kobj;
+	struct work_struct	del_work;
+};
+
 struct r5conf {
 	struct hlist_head	*stripe_hashtbl;
 	struct mddev		*mddev;
@@ -430,6 +441,12 @@ struct r5conf {
 					      * lists and performing address
 					      * conversions
 					      */
+		struct list_head handle_list;
+		cpumask_t	handle_threads; /* Which threads can the CPU's
+						 * stripes be handled. It really
+						 * is a bitmap to aux_threads[],
+						 * but has max bits NR_CPUS
+						 */
 	} __percpu *percpu;
 	size_t			scribble_len; /* size of scribble region must be
 					       * associated with conf to handle
@@ -444,6 +461,7 @@ struct r5conf {
 	 */
 	atomic_t		active_stripes;
 	struct list_head	inactive_list;
+	struct llist_head	released_stripes;
 	wait_queue_head_t	wait_for_stripe;
 	wait_queue_head_t	wait_for_overlap;
 	int			inactive_blocked;	/* release of inactive stripes blocked,
@@ -457,6 +475,10 @@ struct r5conf {
 	 * the new thread here until we fully activate the array.
 	 */
 	struct md_thread	*thread;
+	int			aux_thread_num;
+	struct raid5_auxth	**aux_threads;
+	/* which CPUs should raid5d thread handle stripes from */
+	cpumask_t		work_mask;
 };
 
 /*
diff --git a/drivers/media/common/saa7146/saa7146_video.c b/drivers/media/common/saa7146/saa7146_video.c
index 4143d61..fe907f2 100644
--- a/drivers/media/common/saa7146/saa7146_video.c
+++ b/drivers/media/common/saa7146/saa7146_video.c
@@ -832,7 +832,7 @@ static int vidioc_g_std(struct file *file, void *fh, v4l2_std_id *norm)
 	}
 	*/
 
-static int vidioc_s_std(struct file *file, void *fh, v4l2_std_id *id)
+static int vidioc_s_std(struct file *file, void *fh, v4l2_std_id id)
 {
 	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
 	struct saa7146_vv *vv = dev->vv_data;
@@ -856,7 +856,7 @@ static int vidioc_s_std(struct file *file, void *fh, v4l2_std_id *id)
 	}
 
 	for (i = 0; i < dev->ext_vv_data->num_stds; i++)
-		if (*id & dev->ext_vv_data->stds[i].id)
+		if (id & dev->ext_vv_data->stds[i].id)
 			break;
 	if (i != dev->ext_vv_data->num_stds) {
 		vv->standard = &dev->ext_vv_data->stds[i];
diff --git a/drivers/media/common/siano/Kconfig b/drivers/media/common/siano/Kconfig
index 68f0f60..f3f5ec4 100644
--- a/drivers/media/common/siano/Kconfig
+++ b/drivers/media/common/siano/Kconfig
@@ -17,3 +17,15 @@ config SMS_SIANO_RC
 	default y
 	---help---
 	  Choose Y to select Remote Controller support for Siano driver.
+
+config SMS_SIANO_DEBUGFS
+	bool "Enable debugfs for smsdvb"
+	depends on SMS_SIANO_MDTV
+	depends on DEBUG_FS
+	depends on SMS_USB_DRV
+	---help---
+	  Choose Y to enable visualizing a dump of the frontend
+	  statistics response packets via debugfs. Currently, works
+	  only with Siano USB devices.
+
+	  Useful only for developers. In doubt, say N.
diff --git a/drivers/media/common/siano/Makefile b/drivers/media/common/siano/Makefile
index 81b1e98..4c0567f 100644
--- a/drivers/media/common/siano/Makefile
+++ b/drivers/media/common/siano/Makefile
@@ -1,4 +1,5 @@
 smsmdtv-objs := smscoreapi.o sms-cards.o smsendian.o
+smsdvb-objs := smsdvb-main.o
 
 obj-$(CONFIG_SMS_SIANO_MDTV) += smsmdtv.o smsdvb.o
 
@@ -6,6 +7,10 @@ ifeq ($(CONFIG_SMS_SIANO_RC),y)
   smsmdtv-objs += smsir.o
 endif
 
+ifeq ($(CONFIG_SMS_SIANO_DEBUGFS),y)
+  smsdvb-objs += smsdvb-debugfs.o
+endif
+
 ccflags-y += -Idrivers/media/dvb-core
 ccflags-y += $(extra-cflags-y) $(extra-cflags-m)
 
diff --git a/drivers/media/common/siano/sms-cards.c b/drivers/media/common/siano/sms-cards.c
index 680c781..8276999 100644
--- a/drivers/media/common/siano/sms-cards.c
+++ b/drivers/media/common/siano/sms-cards.c
@@ -28,43 +28,53 @@ MODULE_PARM_DESC(cards_dbg, "set debug level (info=1, adv=2 (or-able))");
 static struct sms_board sms_boards[] = {
 	[SMS_BOARD_UNKNOWN] = {
 		.name	= "Unknown board",
+		.type = SMS_UNKNOWN_TYPE,
+		.default_mode = DEVICE_MODE_NONE,
 	},
 	[SMS1XXX_BOARD_SIANO_STELLAR] = {
 		.name	= "Siano Stellar Digital Receiver",
 		.type	= SMS_STELLAR,
+		.default_mode = DEVICE_MODE_DVBT_BDA,
 	},
 	[SMS1XXX_BOARD_SIANO_NOVA_A] = {
 		.name	= "Siano Nova A Digital Receiver",
 		.type	= SMS_NOVA_A0,
+		.default_mode = DEVICE_MODE_DVBT_BDA,
 	},
 	[SMS1XXX_BOARD_SIANO_NOVA_B] = {
 		.name	= "Siano Nova B Digital Receiver",
 		.type	= SMS_NOVA_B0,
+		.default_mode = DEVICE_MODE_DVBT_BDA,
 	},
 	[SMS1XXX_BOARD_SIANO_VEGA] = {
 		.name	= "Siano Vega Digital Receiver",
 		.type	= SMS_VEGA,
+		.default_mode = DEVICE_MODE_CMMB,
 	},
 	[SMS1XXX_BOARD_HAUPPAUGE_CATAMOUNT] = {
 		.name	= "Hauppauge Catamount",
 		.type	= SMS_STELLAR,
-		.fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-stellar-dvbt-01.fw",
+		.fw[DEVICE_MODE_DVBT_BDA] = SMS_FW_DVBT_STELLAR,
+		.default_mode = DEVICE_MODE_DVBT_BDA,
 	},
 	[SMS1XXX_BOARD_HAUPPAUGE_OKEMO_A] = {
 		.name	= "Hauppauge Okemo-A",
 		.type	= SMS_NOVA_A0,
-		.fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-nova-a-dvbt-01.fw",
+		.fw[DEVICE_MODE_DVBT_BDA] = SMS_FW_DVBT_NOVA_A,
+		.default_mode = DEVICE_MODE_DVBT_BDA,
 	},
 	[SMS1XXX_BOARD_HAUPPAUGE_OKEMO_B] = {
 		.name	= "Hauppauge Okemo-B",
 		.type	= SMS_NOVA_B0,
-		.fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-nova-b-dvbt-01.fw",
+		.fw[DEVICE_MODE_DVBT_BDA] = SMS_FW_DVBT_NOVA_B,
+		.default_mode = DEVICE_MODE_DVBT_BDA,
 	},
 	[SMS1XXX_BOARD_HAUPPAUGE_WINDHAM] = {
 		.name	= "Hauppauge WinTV MiniStick",
 		.type	= SMS_NOVA_B0,
-		.fw[DEVICE_MODE_ISDBT_BDA] = "sms1xxx-hcw-55xxx-isdbt-02.fw",
-		.fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw",
+		.fw[DEVICE_MODE_ISDBT_BDA] = SMS_FW_ISDBT_HCW_55XXX,
+		.fw[DEVICE_MODE_DVBT_BDA]  = SMS_FW_DVBT_HCW_55XXX,
+		.default_mode = DEVICE_MODE_DVBT_BDA,
 		.rc_codes = RC_MAP_HAUPPAUGE,
 		.board_cfg.leds_power = 26,
 		.board_cfg.led0 = 27,
@@ -77,7 +87,8 @@ static struct sms_board sms_boards[] = {
 	[SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD] = {
 		.name	= "Hauppauge WinTV MiniCard",
 		.type	= SMS_NOVA_B0,
-		.fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw",
+		.fw[DEVICE_MODE_DVBT_BDA] = SMS_FW_DVBT_HCW_55XXX,
+		.default_mode = DEVICE_MODE_DVBT_BDA,
 		.lna_ctrl  = 29,
 		.board_cfg.foreign_lna0_ctrl = 29,
 		.rf_switch = 17,
@@ -86,18 +97,65 @@ static struct sms_board sms_boards[] = {
 	[SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2] = {
 		.name	= "Hauppauge WinTV MiniCard",
 		.type	= SMS_NOVA_B0,
-		.fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw",
+		.fw[DEVICE_MODE_DVBT_BDA] = SMS_FW_DVBT_HCW_55XXX,
+		.default_mode = DEVICE_MODE_DVBT_BDA,
 		.lna_ctrl  = -1,
 	},
 	[SMS1XXX_BOARD_SIANO_NICE] = {
-	/* 11 */
 		.name = "Siano Nice Digital Receiver",
 		.type = SMS_NOVA_B0,
+		.default_mode = DEVICE_MODE_DVBT_BDA,
 	},
 	[SMS1XXX_BOARD_SIANO_VENICE] = {
-	/* 12 */
 		.name = "Siano Venice Digital Receiver",
 		.type = SMS_VEGA,
+		.default_mode = DEVICE_MODE_CMMB,
+	},
+	[SMS1XXX_BOARD_SIANO_STELLAR_ROM] = {
+		.name = "Siano Stellar Digital Receiver ROM",
+		.type = SMS_STELLAR,
+		.default_mode = DEVICE_MODE_DVBT_BDA,
+		.intf_num = 1,
+	},
+	[SMS1XXX_BOARD_ZTE_DVB_DATA_CARD] = {
+		.name = "ZTE Data Card Digital Receiver",
+		.type = SMS_NOVA_B0,
+		.default_mode = DEVICE_MODE_DVBT_BDA,
+		.intf_num = 5,
+		.mtu = 15792,
+	},
+	[SMS1XXX_BOARD_ONDA_MDTV_DATA_CARD] = {
+		.name = "ONDA Data Card Digital Receiver",
+		.type = SMS_NOVA_B0,
+		.default_mode = DEVICE_MODE_DVBT_BDA,
+		.intf_num = 6,
+		.mtu = 15792,
+	},
+	[SMS1XXX_BOARD_SIANO_MING] = {
+		.name = "Siano Ming Digital Receiver",
+		.type = SMS_MING,
+		.default_mode = DEVICE_MODE_CMMB,
+	},
+	[SMS1XXX_BOARD_SIANO_PELE] = {
+		.name = "Siano Pele Digital Receiver",
+		.type = SMS_PELE,
+		.default_mode = DEVICE_MODE_ISDBT_BDA,
+	},
+	[SMS1XXX_BOARD_SIANO_RIO] = {
+		.name = "Siano Rio Digital Receiver",
+		.type = SMS_RIO,
+		.default_mode = DEVICE_MODE_ISDBT_BDA,
+	},
+	[SMS1XXX_BOARD_SIANO_DENVER_1530] = {
+		.name = "Siano Denver (ATSC-M/H) Digital Receiver",
+		.type = SMS_DENVER_1530,
+		.default_mode = DEVICE_MODE_ATSC,
+		.crystal = 2400,
+	},
+	[SMS1XXX_BOARD_SIANO_DENVER_2160] = {
+		.name = "Siano Denver (TDMB) Digital Receiver",
+		.type = SMS_DENVER_2160,
+		.default_mode = DEVICE_MODE_DAB_TDMB,
 	},
 };
 
@@ -109,20 +167,21 @@ struct sms_board *sms_get_board(unsigned id)
 }
 EXPORT_SYMBOL_GPL(sms_get_board);
 static inline void sms_gpio_assign_11xx_default_led_config(
-		struct smscore_gpio_config *pGpioConfig) {
-	pGpioConfig->Direction = SMS_GPIO_DIRECTION_OUTPUT;
-	pGpioConfig->InputCharacteristics =
-		SMS_GPIO_INPUT_CHARACTERISTICS_NORMAL;
-	pGpioConfig->OutputDriving = SMS_GPIO_OUTPUT_DRIVING_4mA;
-	pGpioConfig->OutputSlewRate = SMS_GPIO_OUTPUT_SLEW_RATE_0_45_V_NS;
-	pGpioConfig->PullUpDown = SMS_GPIO_PULL_UP_DOWN_NONE;
+		struct smscore_config_gpio *p_gpio_config) {
+	p_gpio_config->direction = SMS_GPIO_DIRECTION_OUTPUT;
+	p_gpio_config->inputcharacteristics =
+		SMS_GPIO_INPUTCHARACTERISTICS_NORMAL;
+	p_gpio_config->outputdriving = SMS_GPIO_OUTPUTDRIVING_4mA;
+	p_gpio_config->outputslewrate = SMS_GPIO_OUTPUT_SLEW_RATE_0_45_V_NS;
+	p_gpio_config->pullupdown = SMS_GPIO_PULLUPDOWN_NONE;
 }
 
 int sms_board_event(struct smscore_device_t *coredev,
-		enum SMS_BOARD_EVENTS gevent) {
-	struct smscore_gpio_config MyGpioConfig;
+		    enum SMS_BOARD_EVENTS gevent)
+{
+	struct smscore_config_gpio my_gpio_config;
 
-	sms_gpio_assign_11xx_default_led_config(&MyGpioConfig);
+	sms_gpio_assign_11xx_default_led_config(&my_gpio_config);
 
 	switch (gevent) {
 	case BOARD_EVENT_POWER_INIT: /* including hotplug */
@@ -182,8 +241,8 @@ static int sms_set_gpio(struct smscore_device_t *coredev, int pin, int enable)
 		.direction            = SMS_GPIO_DIRECTION_OUTPUT,
 		.pullupdown           = SMS_GPIO_PULLUPDOWN_NONE,
 		.inputcharacteristics = SMS_GPIO_INPUTCHARACTERISTICS_NORMAL,
-		.outputslewrate       = SMS_GPIO_OUTPUTSLEWRATE_FAST,
-		.outputdriving        = SMS_GPIO_OUTPUTDRIVING_4mA,
+		.outputslewrate       = SMS_GPIO_OUTPUT_SLEW_RATE_FAST,
+		.outputdriving        = SMS_GPIO_OUTPUTDRIVING_S_4mA,
 	};
 
 	if (pin == 0)
@@ -293,19 +352,7 @@ EXPORT_SYMBOL_GPL(sms_board_lna_control);
 
 int sms_board_load_modules(int id)
 {
-	switch (id) {
-	case SMS1XXX_BOARD_HAUPPAUGE_CATAMOUNT:
-	case SMS1XXX_BOARD_HAUPPAUGE_OKEMO_A:
-	case SMS1XXX_BOARD_HAUPPAUGE_OKEMO_B:
-	case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM:
-	case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD:
-	case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2:
-		request_module("smsdvb");
-		break;
-	default:
-		/* do nothing */
-		break;
-	}
+	request_module("smsdvb");
 	return 0;
 }
 EXPORT_SYMBOL_GPL(sms_board_load_modules);
diff --git a/drivers/media/common/siano/sms-cards.h b/drivers/media/common/siano/sms-cards.h
index d8cdf75..c63b544 100644
--- a/drivers/media/common/siano/sms-cards.h
+++ b/drivers/media/common/siano/sms-cards.h
@@ -37,6 +37,14 @@
 #define SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2 10
 #define SMS1XXX_BOARD_SIANO_NICE	11
 #define SMS1XXX_BOARD_SIANO_VENICE	12
+#define SMS1XXX_BOARD_SIANO_STELLAR_ROM 13
+#define SMS1XXX_BOARD_ZTE_DVB_DATA_CARD	14
+#define SMS1XXX_BOARD_ONDA_MDTV_DATA_CARD 15
+#define SMS1XXX_BOARD_SIANO_MING	16
+#define SMS1XXX_BOARD_SIANO_PELE	17
+#define SMS1XXX_BOARD_SIANO_RIO		18
+#define SMS1XXX_BOARD_SIANO_DENVER_1530	19
+#define SMS1XXX_BOARD_SIANO_DENVER_2160 20
 
 struct sms_board_gpio_cfg {
 	int lna_vhf_exist;
@@ -79,6 +87,12 @@ struct sms_board {
 
 	/* gpios */
 	int led_power, led_hi, led_lo, lna_ctrl, rf_switch;
+
+	char intf_num;
+	int default_mode;
+	unsigned int mtu;
+	unsigned int crystal;
+	struct sms_antenna_config_ST *antenna_config;
 };
 
 struct sms_board *sms_get_board(unsigned id);
diff --git a/drivers/media/common/siano/smscoreapi.c b/drivers/media/common/siano/smscoreapi.c
index 1842e64..ebb9ece 100644
--- a/drivers/media/common/siano/smscoreapi.c
+++ b/drivers/media/common/siano/smscoreapi.c
@@ -37,7 +37,6 @@
 #include "smscoreapi.h"
 #include "sms-cards.h"
 #include "smsir.h"
-#include "smsendian.h"
 
 static int sms_dbg;
 module_param_named(debug, sms_dbg, int, 0644);
@@ -58,11 +57,350 @@ struct smscore_client_t {
 	struct list_head entry;
 	struct smscore_device_t *coredev;
 	void			*context;
-	struct list_head 	idlist;
-	onresponse_t	onresponse_handler;
+	struct list_head	idlist;
+	onresponse_t		onresponse_handler;
 	onremove_t		onremove_handler;
 };
 
+static char *siano_msgs[] = {
+	[MSG_TYPE_BASE_VAL                           - MSG_TYPE_BASE_VAL] = "MSG_TYPE_BASE_VAL",
+	[MSG_SMS_GET_VERSION_REQ                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_GET_VERSION_REQ",
+	[MSG_SMS_GET_VERSION_RES                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_GET_VERSION_RES",
+	[MSG_SMS_MULTI_BRIDGE_CFG                    - MSG_TYPE_BASE_VAL] = "MSG_SMS_MULTI_BRIDGE_CFG",
+	[MSG_SMS_GPIO_CONFIG_REQ                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_GPIO_CONFIG_REQ",
+	[MSG_SMS_GPIO_CONFIG_RES                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_GPIO_CONFIG_RES",
+	[MSG_SMS_GPIO_SET_LEVEL_REQ                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_GPIO_SET_LEVEL_REQ",
+	[MSG_SMS_GPIO_SET_LEVEL_RES                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_GPIO_SET_LEVEL_RES",
+	[MSG_SMS_GPIO_GET_LEVEL_REQ                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_GPIO_GET_LEVEL_REQ",
+	[MSG_SMS_GPIO_GET_LEVEL_RES                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_GPIO_GET_LEVEL_RES",
+	[MSG_SMS_EEPROM_BURN_IND                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_EEPROM_BURN_IND",
+	[MSG_SMS_LOG_ENABLE_CHANGE_REQ               - MSG_TYPE_BASE_VAL] = "MSG_SMS_LOG_ENABLE_CHANGE_REQ",
+	[MSG_SMS_LOG_ENABLE_CHANGE_RES               - MSG_TYPE_BASE_VAL] = "MSG_SMS_LOG_ENABLE_CHANGE_RES",
+	[MSG_SMS_SET_MAX_TX_MSG_LEN_REQ              - MSG_TYPE_BASE_VAL] = "MSG_SMS_SET_MAX_TX_MSG_LEN_REQ",
+	[MSG_SMS_SET_MAX_TX_MSG_LEN_RES              - MSG_TYPE_BASE_VAL] = "MSG_SMS_SET_MAX_TX_MSG_LEN_RES",
+	[MSG_SMS_SPI_HALFDUPLEX_TOKEN_HOST_TO_DEVICE - MSG_TYPE_BASE_VAL] = "MSG_SMS_SPI_HALFDUPLEX_TOKEN_HOST_TO_DEVICE",
+	[MSG_SMS_SPI_HALFDUPLEX_TOKEN_DEVICE_TO_HOST - MSG_TYPE_BASE_VAL] = "MSG_SMS_SPI_HALFDUPLEX_TOKEN_DEVICE_TO_HOST",
+	[MSG_SMS_BACKGROUND_SCAN_FLAG_CHANGE_REQ     - MSG_TYPE_BASE_VAL] = "MSG_SMS_BACKGROUND_SCAN_FLAG_CHANGE_REQ",
+	[MSG_SMS_BACKGROUND_SCAN_FLAG_CHANGE_RES     - MSG_TYPE_BASE_VAL] = "MSG_SMS_BACKGROUND_SCAN_FLAG_CHANGE_RES",
+	[MSG_SMS_BACKGROUND_SCAN_SIGNAL_DETECTED_IND - MSG_TYPE_BASE_VAL] = "MSG_SMS_BACKGROUND_SCAN_SIGNAL_DETECTED_IND",
+	[MSG_SMS_BACKGROUND_SCAN_NO_SIGNAL_IND       - MSG_TYPE_BASE_VAL] = "MSG_SMS_BACKGROUND_SCAN_NO_SIGNAL_IND",
+	[MSG_SMS_CONFIGURE_RF_SWITCH_REQ             - MSG_TYPE_BASE_VAL] = "MSG_SMS_CONFIGURE_RF_SWITCH_REQ",
+	[MSG_SMS_CONFIGURE_RF_SWITCH_RES             - MSG_TYPE_BASE_VAL] = "MSG_SMS_CONFIGURE_RF_SWITCH_RES",
+	[MSG_SMS_MRC_PATH_DISCONNECT_REQ             - MSG_TYPE_BASE_VAL] = "MSG_SMS_MRC_PATH_DISCONNECT_REQ",
+	[MSG_SMS_MRC_PATH_DISCONNECT_RES             - MSG_TYPE_BASE_VAL] = "MSG_SMS_MRC_PATH_DISCONNECT_RES",
+	[MSG_SMS_RECEIVE_1SEG_THROUGH_FULLSEG_REQ    - MSG_TYPE_BASE_VAL] = "MSG_SMS_RECEIVE_1SEG_THROUGH_FULLSEG_REQ",
+	[MSG_SMS_RECEIVE_1SEG_THROUGH_FULLSEG_RES    - MSG_TYPE_BASE_VAL] = "MSG_SMS_RECEIVE_1SEG_THROUGH_FULLSEG_RES",
+	[MSG_SMS_RECEIVE_VHF_VIA_VHF_INPUT_REQ       - MSG_TYPE_BASE_VAL] = "MSG_SMS_RECEIVE_VHF_VIA_VHF_INPUT_REQ",
+	[MSG_SMS_RECEIVE_VHF_VIA_VHF_INPUT_RES       - MSG_TYPE_BASE_VAL] = "MSG_SMS_RECEIVE_VHF_VIA_VHF_INPUT_RES",
+	[MSG_WR_REG_RFT_REQ                          - MSG_TYPE_BASE_VAL] = "MSG_WR_REG_RFT_REQ",
+	[MSG_WR_REG_RFT_RES                          - MSG_TYPE_BASE_VAL] = "MSG_WR_REG_RFT_RES",
+	[MSG_RD_REG_RFT_REQ                          - MSG_TYPE_BASE_VAL] = "MSG_RD_REG_RFT_REQ",
+	[MSG_RD_REG_RFT_RES                          - MSG_TYPE_BASE_VAL] = "MSG_RD_REG_RFT_RES",
+	[MSG_RD_REG_ALL_RFT_REQ                      - MSG_TYPE_BASE_VAL] = "MSG_RD_REG_ALL_RFT_REQ",
+	[MSG_RD_REG_ALL_RFT_RES                      - MSG_TYPE_BASE_VAL] = "MSG_RD_REG_ALL_RFT_RES",
+	[MSG_HELP_INT                                - MSG_TYPE_BASE_VAL] = "MSG_HELP_INT",
+	[MSG_RUN_SCRIPT_INT                          - MSG_TYPE_BASE_VAL] = "MSG_RUN_SCRIPT_INT",
+	[MSG_SMS_EWS_INBAND_REQ                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_EWS_INBAND_REQ",
+	[MSG_SMS_EWS_INBAND_RES                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_EWS_INBAND_RES",
+	[MSG_SMS_RFS_SELECT_REQ                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_RFS_SELECT_REQ",
+	[MSG_SMS_RFS_SELECT_RES                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_RFS_SELECT_RES",
+	[MSG_SMS_MB_GET_VER_REQ                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_MB_GET_VER_REQ",
+	[MSG_SMS_MB_GET_VER_RES                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_MB_GET_VER_RES",
+	[MSG_SMS_MB_WRITE_CFGFILE_REQ                - MSG_TYPE_BASE_VAL] = "MSG_SMS_MB_WRITE_CFGFILE_REQ",
+	[MSG_SMS_MB_WRITE_CFGFILE_RES                - MSG_TYPE_BASE_VAL] = "MSG_SMS_MB_WRITE_CFGFILE_RES",
+	[MSG_SMS_MB_READ_CFGFILE_REQ                 - MSG_TYPE_BASE_VAL] = "MSG_SMS_MB_READ_CFGFILE_REQ",
+	[MSG_SMS_MB_READ_CFGFILE_RES                 - MSG_TYPE_BASE_VAL] = "MSG_SMS_MB_READ_CFGFILE_RES",
+	[MSG_SMS_RD_MEM_REQ                          - MSG_TYPE_BASE_VAL] = "MSG_SMS_RD_MEM_REQ",
+	[MSG_SMS_RD_MEM_RES                          - MSG_TYPE_BASE_VAL] = "MSG_SMS_RD_MEM_RES",
+	[MSG_SMS_WR_MEM_REQ                          - MSG_TYPE_BASE_VAL] = "MSG_SMS_WR_MEM_REQ",
+	[MSG_SMS_WR_MEM_RES                          - MSG_TYPE_BASE_VAL] = "MSG_SMS_WR_MEM_RES",
+	[MSG_SMS_UPDATE_MEM_REQ                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_UPDATE_MEM_REQ",
+	[MSG_SMS_UPDATE_MEM_RES                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_UPDATE_MEM_RES",
+	[MSG_SMS_ISDBT_ENABLE_FULL_PARAMS_SET_REQ    - MSG_TYPE_BASE_VAL] = "MSG_SMS_ISDBT_ENABLE_FULL_PARAMS_SET_REQ",
+	[MSG_SMS_ISDBT_ENABLE_FULL_PARAMS_SET_RES    - MSG_TYPE_BASE_VAL] = "MSG_SMS_ISDBT_ENABLE_FULL_PARAMS_SET_RES",
+	[MSG_SMS_RF_TUNE_REQ                         - MSG_TYPE_BASE_VAL] = "MSG_SMS_RF_TUNE_REQ",
+	[MSG_SMS_RF_TUNE_RES                         - MSG_TYPE_BASE_VAL] = "MSG_SMS_RF_TUNE_RES",
+	[MSG_SMS_ISDBT_ENABLE_HIGH_MOBILITY_REQ      - MSG_TYPE_BASE_VAL] = "MSG_SMS_ISDBT_ENABLE_HIGH_MOBILITY_REQ",
+	[MSG_SMS_ISDBT_ENABLE_HIGH_MOBILITY_RES      - MSG_TYPE_BASE_VAL] = "MSG_SMS_ISDBT_ENABLE_HIGH_MOBILITY_RES",
+	[MSG_SMS_ISDBT_SB_RECEPTION_REQ              - MSG_TYPE_BASE_VAL] = "MSG_SMS_ISDBT_SB_RECEPTION_REQ",
+	[MSG_SMS_ISDBT_SB_RECEPTION_RES              - MSG_TYPE_BASE_VAL] = "MSG_SMS_ISDBT_SB_RECEPTION_RES",
+	[MSG_SMS_GENERIC_EPROM_WRITE_REQ             - MSG_TYPE_BASE_VAL] = "MSG_SMS_GENERIC_EPROM_WRITE_REQ",
+	[MSG_SMS_GENERIC_EPROM_WRITE_RES             - MSG_TYPE_BASE_VAL] = "MSG_SMS_GENERIC_EPROM_WRITE_RES",
+	[MSG_SMS_GENERIC_EPROM_READ_REQ              - MSG_TYPE_BASE_VAL] = "MSG_SMS_GENERIC_EPROM_READ_REQ",
+	[MSG_SMS_GENERIC_EPROM_READ_RES              - MSG_TYPE_BASE_VAL] = "MSG_SMS_GENERIC_EPROM_READ_RES",
+	[MSG_SMS_EEPROM_WRITE_REQ                    - MSG_TYPE_BASE_VAL] = "MSG_SMS_EEPROM_WRITE_REQ",
+	[MSG_SMS_EEPROM_WRITE_RES                    - MSG_TYPE_BASE_VAL] = "MSG_SMS_EEPROM_WRITE_RES",
+	[MSG_SMS_CUSTOM_READ_REQ                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_CUSTOM_READ_REQ",
+	[MSG_SMS_CUSTOM_READ_RES                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_CUSTOM_READ_RES",
+	[MSG_SMS_CUSTOM_WRITE_REQ                    - MSG_TYPE_BASE_VAL] = "MSG_SMS_CUSTOM_WRITE_REQ",
+	[MSG_SMS_CUSTOM_WRITE_RES                    - MSG_TYPE_BASE_VAL] = "MSG_SMS_CUSTOM_WRITE_RES",
+	[MSG_SMS_INIT_DEVICE_REQ                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_INIT_DEVICE_REQ",
+	[MSG_SMS_INIT_DEVICE_RES                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_INIT_DEVICE_RES",
+	[MSG_SMS_ATSC_SET_ALL_IP_REQ                 - MSG_TYPE_BASE_VAL] = "MSG_SMS_ATSC_SET_ALL_IP_REQ",
+	[MSG_SMS_ATSC_SET_ALL_IP_RES                 - MSG_TYPE_BASE_VAL] = "MSG_SMS_ATSC_SET_ALL_IP_RES",
+	[MSG_SMS_ATSC_START_ENSEMBLE_REQ             - MSG_TYPE_BASE_VAL] = "MSG_SMS_ATSC_START_ENSEMBLE_REQ",
+	[MSG_SMS_ATSC_START_ENSEMBLE_RES             - MSG_TYPE_BASE_VAL] = "MSG_SMS_ATSC_START_ENSEMBLE_RES",
+	[MSG_SMS_SET_OUTPUT_MODE_REQ                 - MSG_TYPE_BASE_VAL] = "MSG_SMS_SET_OUTPUT_MODE_REQ",
+	[MSG_SMS_SET_OUTPUT_MODE_RES                 - MSG_TYPE_BASE_VAL] = "MSG_SMS_SET_OUTPUT_MODE_RES",
+	[MSG_SMS_ATSC_IP_FILTER_GET_LIST_REQ         - MSG_TYPE_BASE_VAL] = "MSG_SMS_ATSC_IP_FILTER_GET_LIST_REQ",
+	[MSG_SMS_ATSC_IP_FILTER_GET_LIST_RES         - MSG_TYPE_BASE_VAL] = "MSG_SMS_ATSC_IP_FILTER_GET_LIST_RES",
+	[MSG_SMS_SUB_CHANNEL_START_REQ               - MSG_TYPE_BASE_VAL] = "MSG_SMS_SUB_CHANNEL_START_REQ",
+	[MSG_SMS_SUB_CHANNEL_START_RES               - MSG_TYPE_BASE_VAL] = "MSG_SMS_SUB_CHANNEL_START_RES",
+	[MSG_SMS_SUB_CHANNEL_STOP_REQ                - MSG_TYPE_BASE_VAL] = "MSG_SMS_SUB_CHANNEL_STOP_REQ",
+	[MSG_SMS_SUB_CHANNEL_STOP_RES                - MSG_TYPE_BASE_VAL] = "MSG_SMS_SUB_CHANNEL_STOP_RES",
+	[MSG_SMS_ATSC_IP_FILTER_ADD_REQ              - MSG_TYPE_BASE_VAL] = "MSG_SMS_ATSC_IP_FILTER_ADD_REQ",
+	[MSG_SMS_ATSC_IP_FILTER_ADD_RES              - MSG_TYPE_BASE_VAL] = "MSG_SMS_ATSC_IP_FILTER_ADD_RES",
+	[MSG_SMS_ATSC_IP_FILTER_REMOVE_REQ           - MSG_TYPE_BASE_VAL] = "MSG_SMS_ATSC_IP_FILTER_REMOVE_REQ",
+	[MSG_SMS_ATSC_IP_FILTER_REMOVE_RES           - MSG_TYPE_BASE_VAL] = "MSG_SMS_ATSC_IP_FILTER_REMOVE_RES",
+	[MSG_SMS_ATSC_IP_FILTER_REMOVE_ALL_REQ       - MSG_TYPE_BASE_VAL] = "MSG_SMS_ATSC_IP_FILTER_REMOVE_ALL_REQ",
+	[MSG_SMS_ATSC_IP_FILTER_REMOVE_ALL_RES       - MSG_TYPE_BASE_VAL] = "MSG_SMS_ATSC_IP_FILTER_REMOVE_ALL_RES",
+	[MSG_SMS_WAIT_CMD                            - MSG_TYPE_BASE_VAL] = "MSG_SMS_WAIT_CMD",
+	[MSG_SMS_ADD_PID_FILTER_REQ                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_ADD_PID_FILTER_REQ",
+	[MSG_SMS_ADD_PID_FILTER_RES                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_ADD_PID_FILTER_RES",
+	[MSG_SMS_REMOVE_PID_FILTER_REQ               - MSG_TYPE_BASE_VAL] = "MSG_SMS_REMOVE_PID_FILTER_REQ",
+	[MSG_SMS_REMOVE_PID_FILTER_RES               - MSG_TYPE_BASE_VAL] = "MSG_SMS_REMOVE_PID_FILTER_RES",
+	[MSG_SMS_FAST_INFORMATION_CHANNEL_REQ        - MSG_TYPE_BASE_VAL] = "MSG_SMS_FAST_INFORMATION_CHANNEL_REQ",
+	[MSG_SMS_FAST_INFORMATION_CHANNEL_RES        - MSG_TYPE_BASE_VAL] = "MSG_SMS_FAST_INFORMATION_CHANNEL_RES",
+	[MSG_SMS_DAB_CHANNEL                         - MSG_TYPE_BASE_VAL] = "MSG_SMS_DAB_CHANNEL",
+	[MSG_SMS_GET_PID_FILTER_LIST_REQ             - MSG_TYPE_BASE_VAL] = "MSG_SMS_GET_PID_FILTER_LIST_REQ",
+	[MSG_SMS_GET_PID_FILTER_LIST_RES             - MSG_TYPE_BASE_VAL] = "MSG_SMS_GET_PID_FILTER_LIST_RES",
+	[MSG_SMS_POWER_DOWN_REQ                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_POWER_DOWN_REQ",
+	[MSG_SMS_POWER_DOWN_RES                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_POWER_DOWN_RES",
+	[MSG_SMS_ATSC_SLT_EXIST_IND                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_ATSC_SLT_EXIST_IND",
+	[MSG_SMS_ATSC_NO_SLT_IND                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_ATSC_NO_SLT_IND",
+	[MSG_SMS_GET_STATISTICS_REQ                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_GET_STATISTICS_REQ",
+	[MSG_SMS_GET_STATISTICS_RES                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_GET_STATISTICS_RES",
+	[MSG_SMS_SEND_DUMP                           - MSG_TYPE_BASE_VAL] = "MSG_SMS_SEND_DUMP",
+	[MSG_SMS_SCAN_START_REQ                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_SCAN_START_REQ",
+	[MSG_SMS_SCAN_START_RES                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_SCAN_START_RES",
+	[MSG_SMS_SCAN_STOP_REQ                       - MSG_TYPE_BASE_VAL] = "MSG_SMS_SCAN_STOP_REQ",
+	[MSG_SMS_SCAN_STOP_RES                       - MSG_TYPE_BASE_VAL] = "MSG_SMS_SCAN_STOP_RES",
+	[MSG_SMS_SCAN_PROGRESS_IND                   - MSG_TYPE_BASE_VAL] = "MSG_SMS_SCAN_PROGRESS_IND",
+	[MSG_SMS_SCAN_COMPLETE_IND                   - MSG_TYPE_BASE_VAL] = "MSG_SMS_SCAN_COMPLETE_IND",
+	[MSG_SMS_LOG_ITEM                            - MSG_TYPE_BASE_VAL] = "MSG_SMS_LOG_ITEM",
+	[MSG_SMS_DAB_SUBCHANNEL_RECONFIG_REQ         - MSG_TYPE_BASE_VAL] = "MSG_SMS_DAB_SUBCHANNEL_RECONFIG_REQ",
+	[MSG_SMS_DAB_SUBCHANNEL_RECONFIG_RES         - MSG_TYPE_BASE_VAL] = "MSG_SMS_DAB_SUBCHANNEL_RECONFIG_RES",
+	[MSG_SMS_HO_PER_SLICES_IND                   - MSG_TYPE_BASE_VAL] = "MSG_SMS_HO_PER_SLICES_IND",
+	[MSG_SMS_HO_INBAND_POWER_IND                 - MSG_TYPE_BASE_VAL] = "MSG_SMS_HO_INBAND_POWER_IND",
+	[MSG_SMS_MANUAL_DEMOD_REQ                    - MSG_TYPE_BASE_VAL] = "MSG_SMS_MANUAL_DEMOD_REQ",
+	[MSG_SMS_HO_TUNE_ON_REQ                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_HO_TUNE_ON_REQ",
+	[MSG_SMS_HO_TUNE_ON_RES                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_HO_TUNE_ON_RES",
+	[MSG_SMS_HO_TUNE_OFF_REQ                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_HO_TUNE_OFF_REQ",
+	[MSG_SMS_HO_TUNE_OFF_RES                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_HO_TUNE_OFF_RES",
+	[MSG_SMS_HO_PEEK_FREQ_REQ                    - MSG_TYPE_BASE_VAL] = "MSG_SMS_HO_PEEK_FREQ_REQ",
+	[MSG_SMS_HO_PEEK_FREQ_RES                    - MSG_TYPE_BASE_VAL] = "MSG_SMS_HO_PEEK_FREQ_RES",
+	[MSG_SMS_HO_PEEK_FREQ_IND                    - MSG_TYPE_BASE_VAL] = "MSG_SMS_HO_PEEK_FREQ_IND",
+	[MSG_SMS_MB_ATTEN_SET_REQ                    - MSG_TYPE_BASE_VAL] = "MSG_SMS_MB_ATTEN_SET_REQ",
+	[MSG_SMS_MB_ATTEN_SET_RES                    - MSG_TYPE_BASE_VAL] = "MSG_SMS_MB_ATTEN_SET_RES",
+	[MSG_SMS_ENABLE_STAT_IN_I2C_REQ              - MSG_TYPE_BASE_VAL] = "MSG_SMS_ENABLE_STAT_IN_I2C_REQ",
+	[MSG_SMS_ENABLE_STAT_IN_I2C_RES              - MSG_TYPE_BASE_VAL] = "MSG_SMS_ENABLE_STAT_IN_I2C_RES",
+	[MSG_SMS_SET_ANTENNA_CONFIG_REQ              - MSG_TYPE_BASE_VAL] = "MSG_SMS_SET_ANTENNA_CONFIG_REQ",
+	[MSG_SMS_SET_ANTENNA_CONFIG_RES              - MSG_TYPE_BASE_VAL] = "MSG_SMS_SET_ANTENNA_CONFIG_RES",
+	[MSG_SMS_GET_STATISTICS_EX_REQ               - MSG_TYPE_BASE_VAL] = "MSG_SMS_GET_STATISTICS_EX_REQ",
+	[MSG_SMS_GET_STATISTICS_EX_RES               - MSG_TYPE_BASE_VAL] = "MSG_SMS_GET_STATISTICS_EX_RES",
+	[MSG_SMS_SLEEP_RESUME_COMP_IND               - MSG_TYPE_BASE_VAL] = "MSG_SMS_SLEEP_RESUME_COMP_IND",
+	[MSG_SMS_SWITCH_HOST_INTERFACE_REQ           - MSG_TYPE_BASE_VAL] = "MSG_SMS_SWITCH_HOST_INTERFACE_REQ",
+	[MSG_SMS_SWITCH_HOST_INTERFACE_RES           - MSG_TYPE_BASE_VAL] = "MSG_SMS_SWITCH_HOST_INTERFACE_RES",
+	[MSG_SMS_DATA_DOWNLOAD_REQ                   - MSG_TYPE_BASE_VAL] = "MSG_SMS_DATA_DOWNLOAD_REQ",
+	[MSG_SMS_DATA_DOWNLOAD_RES                   - MSG_TYPE_BASE_VAL] = "MSG_SMS_DATA_DOWNLOAD_RES",
+	[MSG_SMS_DATA_VALIDITY_REQ                   - MSG_TYPE_BASE_VAL] = "MSG_SMS_DATA_VALIDITY_REQ",
+	[MSG_SMS_DATA_VALIDITY_RES                   - MSG_TYPE_BASE_VAL] = "MSG_SMS_DATA_VALIDITY_RES",
+	[MSG_SMS_SWDOWNLOAD_TRIGGER_REQ              - MSG_TYPE_BASE_VAL] = "MSG_SMS_SWDOWNLOAD_TRIGGER_REQ",
+	[MSG_SMS_SWDOWNLOAD_TRIGGER_RES              - MSG_TYPE_BASE_VAL] = "MSG_SMS_SWDOWNLOAD_TRIGGER_RES",
+	[MSG_SMS_SWDOWNLOAD_BACKDOOR_REQ             - MSG_TYPE_BASE_VAL] = "MSG_SMS_SWDOWNLOAD_BACKDOOR_REQ",
+	[MSG_SMS_SWDOWNLOAD_BACKDOOR_RES             - MSG_TYPE_BASE_VAL] = "MSG_SMS_SWDOWNLOAD_BACKDOOR_RES",
+	[MSG_SMS_GET_VERSION_EX_REQ                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_GET_VERSION_EX_REQ",
+	[MSG_SMS_GET_VERSION_EX_RES                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_GET_VERSION_EX_RES",
+	[MSG_SMS_CLOCK_OUTPUT_CONFIG_REQ             - MSG_TYPE_BASE_VAL] = "MSG_SMS_CLOCK_OUTPUT_CONFIG_REQ",
+	[MSG_SMS_CLOCK_OUTPUT_CONFIG_RES             - MSG_TYPE_BASE_VAL] = "MSG_SMS_CLOCK_OUTPUT_CONFIG_RES",
+	[MSG_SMS_I2C_SET_FREQ_REQ                    - MSG_TYPE_BASE_VAL] = "MSG_SMS_I2C_SET_FREQ_REQ",
+	[MSG_SMS_I2C_SET_FREQ_RES                    - MSG_TYPE_BASE_VAL] = "MSG_SMS_I2C_SET_FREQ_RES",
+	[MSG_SMS_GENERIC_I2C_REQ                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_GENERIC_I2C_REQ",
+	[MSG_SMS_GENERIC_I2C_RES                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_GENERIC_I2C_RES",
+	[MSG_SMS_DVBT_BDA_DATA                       - MSG_TYPE_BASE_VAL] = "MSG_SMS_DVBT_BDA_DATA",
+	[MSG_SW_RELOAD_REQ                           - MSG_TYPE_BASE_VAL] = "MSG_SW_RELOAD_REQ",
+	[MSG_SMS_DATA_MSG                            - MSG_TYPE_BASE_VAL] = "MSG_SMS_DATA_MSG",
+	[MSG_TABLE_UPLOAD_REQ                        - MSG_TYPE_BASE_VAL] = "MSG_TABLE_UPLOAD_REQ",
+	[MSG_TABLE_UPLOAD_RES                        - MSG_TYPE_BASE_VAL] = "MSG_TABLE_UPLOAD_RES",
+	[MSG_SW_RELOAD_START_REQ                     - MSG_TYPE_BASE_VAL] = "MSG_SW_RELOAD_START_REQ",
+	[MSG_SW_RELOAD_START_RES                     - MSG_TYPE_BASE_VAL] = "MSG_SW_RELOAD_START_RES",
+	[MSG_SW_RELOAD_EXEC_REQ                      - MSG_TYPE_BASE_VAL] = "MSG_SW_RELOAD_EXEC_REQ",
+	[MSG_SW_RELOAD_EXEC_RES                      - MSG_TYPE_BASE_VAL] = "MSG_SW_RELOAD_EXEC_RES",
+	[MSG_SMS_SPI_INT_LINE_SET_REQ                - MSG_TYPE_BASE_VAL] = "MSG_SMS_SPI_INT_LINE_SET_REQ",
+	[MSG_SMS_SPI_INT_LINE_SET_RES                - MSG_TYPE_BASE_VAL] = "MSG_SMS_SPI_INT_LINE_SET_RES",
+	[MSG_SMS_GPIO_CONFIG_EX_REQ                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_GPIO_CONFIG_EX_REQ",
+	[MSG_SMS_GPIO_CONFIG_EX_RES                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_GPIO_CONFIG_EX_RES",
+	[MSG_SMS_WATCHDOG_ACT_REQ                    - MSG_TYPE_BASE_VAL] = "MSG_SMS_WATCHDOG_ACT_REQ",
+	[MSG_SMS_WATCHDOG_ACT_RES                    - MSG_TYPE_BASE_VAL] = "MSG_SMS_WATCHDOG_ACT_RES",
+	[MSG_SMS_LOOPBACK_REQ                        - MSG_TYPE_BASE_VAL] = "MSG_SMS_LOOPBACK_REQ",
+	[MSG_SMS_LOOPBACK_RES                        - MSG_TYPE_BASE_VAL] = "MSG_SMS_LOOPBACK_RES",
+	[MSG_SMS_RAW_CAPTURE_START_REQ               - MSG_TYPE_BASE_VAL] = "MSG_SMS_RAW_CAPTURE_START_REQ",
+	[MSG_SMS_RAW_CAPTURE_START_RES               - MSG_TYPE_BASE_VAL] = "MSG_SMS_RAW_CAPTURE_START_RES",
+	[MSG_SMS_RAW_CAPTURE_ABORT_REQ               - MSG_TYPE_BASE_VAL] = "MSG_SMS_RAW_CAPTURE_ABORT_REQ",
+	[MSG_SMS_RAW_CAPTURE_ABORT_RES               - MSG_TYPE_BASE_VAL] = "MSG_SMS_RAW_CAPTURE_ABORT_RES",
+	[MSG_SMS_RAW_CAPTURE_COMPLETE_IND            - MSG_TYPE_BASE_VAL] = "MSG_SMS_RAW_CAPTURE_COMPLETE_IND",
+	[MSG_SMS_DATA_PUMP_IND                       - MSG_TYPE_BASE_VAL] = "MSG_SMS_DATA_PUMP_IND",
+	[MSG_SMS_DATA_PUMP_REQ                       - MSG_TYPE_BASE_VAL] = "MSG_SMS_DATA_PUMP_REQ",
+	[MSG_SMS_DATA_PUMP_RES                       - MSG_TYPE_BASE_VAL] = "MSG_SMS_DATA_PUMP_RES",
+	[MSG_SMS_FLASH_DL_REQ                        - MSG_TYPE_BASE_VAL] = "MSG_SMS_FLASH_DL_REQ",
+	[MSG_SMS_EXEC_TEST_1_REQ                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_EXEC_TEST_1_REQ",
+	[MSG_SMS_EXEC_TEST_1_RES                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_EXEC_TEST_1_RES",
+	[MSG_SMS_ENBALE_TS_INTERFACE_REQ             - MSG_TYPE_BASE_VAL] = "MSG_SMS_ENBALE_TS_INTERFACE_REQ",
+	[MSG_SMS_ENBALE_TS_INTERFACE_RES             - MSG_TYPE_BASE_VAL] = "MSG_SMS_ENBALE_TS_INTERFACE_RES",
+	[MSG_SMS_SPI_SET_BUS_WIDTH_REQ               - MSG_TYPE_BASE_VAL] = "MSG_SMS_SPI_SET_BUS_WIDTH_REQ",
+	[MSG_SMS_SPI_SET_BUS_WIDTH_RES               - MSG_TYPE_BASE_VAL] = "MSG_SMS_SPI_SET_BUS_WIDTH_RES",
+	[MSG_SMS_SEND_EMM_REQ                        - MSG_TYPE_BASE_VAL] = "MSG_SMS_SEND_EMM_REQ",
+	[MSG_SMS_SEND_EMM_RES                        - MSG_TYPE_BASE_VAL] = "MSG_SMS_SEND_EMM_RES",
+	[MSG_SMS_DISABLE_TS_INTERFACE_REQ            - MSG_TYPE_BASE_VAL] = "MSG_SMS_DISABLE_TS_INTERFACE_REQ",
+	[MSG_SMS_DISABLE_TS_INTERFACE_RES            - MSG_TYPE_BASE_VAL] = "MSG_SMS_DISABLE_TS_INTERFACE_RES",
+	[MSG_SMS_IS_BUF_FREE_REQ                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_IS_BUF_FREE_REQ",
+	[MSG_SMS_IS_BUF_FREE_RES                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_IS_BUF_FREE_RES",
+	[MSG_SMS_EXT_ANTENNA_REQ                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_EXT_ANTENNA_REQ",
+	[MSG_SMS_EXT_ANTENNA_RES                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_EXT_ANTENNA_RES",
+	[MSG_SMS_CMMB_GET_NET_OF_FREQ_REQ_OBSOLETE   - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_GET_NET_OF_FREQ_REQ_OBSOLETE",
+	[MSG_SMS_CMMB_GET_NET_OF_FREQ_RES_OBSOLETE   - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_GET_NET_OF_FREQ_RES_OBSOLETE",
+	[MSG_SMS_BATTERY_LEVEL_REQ                   - MSG_TYPE_BASE_VAL] = "MSG_SMS_BATTERY_LEVEL_REQ",
+	[MSG_SMS_BATTERY_LEVEL_RES                   - MSG_TYPE_BASE_VAL] = "MSG_SMS_BATTERY_LEVEL_RES",
+	[MSG_SMS_CMMB_INJECT_TABLE_REQ_OBSOLETE      - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_INJECT_TABLE_REQ_OBSOLETE",
+	[MSG_SMS_CMMB_INJECT_TABLE_RES_OBSOLETE      - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_INJECT_TABLE_RES_OBSOLETE",
+	[MSG_SMS_FM_RADIO_BLOCK_IND                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_FM_RADIO_BLOCK_IND",
+	[MSG_SMS_HOST_NOTIFICATION_IND               - MSG_TYPE_BASE_VAL] = "MSG_SMS_HOST_NOTIFICATION_IND",
+	[MSG_SMS_CMMB_GET_CONTROL_TABLE_REQ_OBSOLETE - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_GET_CONTROL_TABLE_REQ_OBSOLETE",
+	[MSG_SMS_CMMB_GET_CONTROL_TABLE_RES_OBSOLETE - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_GET_CONTROL_TABLE_RES_OBSOLETE",
+	[MSG_SMS_CMMB_GET_NETWORKS_REQ               - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_GET_NETWORKS_REQ",
+	[MSG_SMS_CMMB_GET_NETWORKS_RES               - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_GET_NETWORKS_RES",
+	[MSG_SMS_CMMB_START_SERVICE_REQ              - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_START_SERVICE_REQ",
+	[MSG_SMS_CMMB_START_SERVICE_RES              - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_START_SERVICE_RES",
+	[MSG_SMS_CMMB_STOP_SERVICE_REQ               - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_STOP_SERVICE_REQ",
+	[MSG_SMS_CMMB_STOP_SERVICE_RES               - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_STOP_SERVICE_RES",
+	[MSG_SMS_CMMB_ADD_CHANNEL_FILTER_REQ         - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_ADD_CHANNEL_FILTER_REQ",
+	[MSG_SMS_CMMB_ADD_CHANNEL_FILTER_RES         - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_ADD_CHANNEL_FILTER_RES",
+	[MSG_SMS_CMMB_REMOVE_CHANNEL_FILTER_REQ      - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_REMOVE_CHANNEL_FILTER_REQ",
+	[MSG_SMS_CMMB_REMOVE_CHANNEL_FILTER_RES      - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_REMOVE_CHANNEL_FILTER_RES",
+	[MSG_SMS_CMMB_START_CONTROL_INFO_REQ         - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_START_CONTROL_INFO_REQ",
+	[MSG_SMS_CMMB_START_CONTROL_INFO_RES         - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_START_CONTROL_INFO_RES",
+	[MSG_SMS_CMMB_STOP_CONTROL_INFO_REQ          - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_STOP_CONTROL_INFO_REQ",
+	[MSG_SMS_CMMB_STOP_CONTROL_INFO_RES          - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_STOP_CONTROL_INFO_RES",
+	[MSG_SMS_ISDBT_TUNE_REQ                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_ISDBT_TUNE_REQ",
+	[MSG_SMS_ISDBT_TUNE_RES                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_ISDBT_TUNE_RES",
+	[MSG_SMS_TRANSMISSION_IND                    - MSG_TYPE_BASE_VAL] = "MSG_SMS_TRANSMISSION_IND",
+	[MSG_SMS_PID_STATISTICS_IND                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_PID_STATISTICS_IND",
+	[MSG_SMS_POWER_DOWN_IND                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_POWER_DOWN_IND",
+	[MSG_SMS_POWER_DOWN_CONF                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_POWER_DOWN_CONF",
+	[MSG_SMS_POWER_UP_IND                        - MSG_TYPE_BASE_VAL] = "MSG_SMS_POWER_UP_IND",
+	[MSG_SMS_POWER_UP_CONF                       - MSG_TYPE_BASE_VAL] = "MSG_SMS_POWER_UP_CONF",
+	[MSG_SMS_POWER_MODE_SET_REQ                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_POWER_MODE_SET_REQ",
+	[MSG_SMS_POWER_MODE_SET_RES                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_POWER_MODE_SET_RES",
+	[MSG_SMS_DEBUG_HOST_EVENT_REQ                - MSG_TYPE_BASE_VAL] = "MSG_SMS_DEBUG_HOST_EVENT_REQ",
+	[MSG_SMS_DEBUG_HOST_EVENT_RES                - MSG_TYPE_BASE_VAL] = "MSG_SMS_DEBUG_HOST_EVENT_RES",
+	[MSG_SMS_NEW_CRYSTAL_REQ                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_NEW_CRYSTAL_REQ",
+	[MSG_SMS_NEW_CRYSTAL_RES                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_NEW_CRYSTAL_RES",
+	[MSG_SMS_CONFIG_SPI_REQ                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_CONFIG_SPI_REQ",
+	[MSG_SMS_CONFIG_SPI_RES                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_CONFIG_SPI_RES",
+	[MSG_SMS_I2C_SHORT_STAT_IND                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_I2C_SHORT_STAT_IND",
+	[MSG_SMS_START_IR_REQ                        - MSG_TYPE_BASE_VAL] = "MSG_SMS_START_IR_REQ",
+	[MSG_SMS_START_IR_RES                        - MSG_TYPE_BASE_VAL] = "MSG_SMS_START_IR_RES",
+	[MSG_SMS_IR_SAMPLES_IND                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_IR_SAMPLES_IND",
+	[MSG_SMS_CMMB_CA_SERVICE_IND                 - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_CA_SERVICE_IND",
+	[MSG_SMS_SLAVE_DEVICE_DETECTED               - MSG_TYPE_BASE_VAL] = "MSG_SMS_SLAVE_DEVICE_DETECTED",
+	[MSG_SMS_INTERFACE_LOCK_IND                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_INTERFACE_LOCK_IND",
+	[MSG_SMS_INTERFACE_UNLOCK_IND                - MSG_TYPE_BASE_VAL] = "MSG_SMS_INTERFACE_UNLOCK_IND",
+	[MSG_SMS_SEND_ROSUM_BUFF_REQ                 - MSG_TYPE_BASE_VAL] = "MSG_SMS_SEND_ROSUM_BUFF_REQ",
+	[MSG_SMS_SEND_ROSUM_BUFF_RES                 - MSG_TYPE_BASE_VAL] = "MSG_SMS_SEND_ROSUM_BUFF_RES",
+	[MSG_SMS_ROSUM_BUFF                          - MSG_TYPE_BASE_VAL] = "MSG_SMS_ROSUM_BUFF",
+	[MSG_SMS_SET_AES128_KEY_REQ                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_SET_AES128_KEY_REQ",
+	[MSG_SMS_SET_AES128_KEY_RES                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_SET_AES128_KEY_RES",
+	[MSG_SMS_MBBMS_WRITE_REQ                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_MBBMS_WRITE_REQ",
+	[MSG_SMS_MBBMS_WRITE_RES                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_MBBMS_WRITE_RES",
+	[MSG_SMS_MBBMS_READ_IND                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_MBBMS_READ_IND",
+	[MSG_SMS_IQ_STREAM_START_REQ                 - MSG_TYPE_BASE_VAL] = "MSG_SMS_IQ_STREAM_START_REQ",
+	[MSG_SMS_IQ_STREAM_START_RES                 - MSG_TYPE_BASE_VAL] = "MSG_SMS_IQ_STREAM_START_RES",
+	[MSG_SMS_IQ_STREAM_STOP_REQ                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_IQ_STREAM_STOP_REQ",
+	[MSG_SMS_IQ_STREAM_STOP_RES                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_IQ_STREAM_STOP_RES",
+	[MSG_SMS_IQ_STREAM_DATA_BLOCK                - MSG_TYPE_BASE_VAL] = "MSG_SMS_IQ_STREAM_DATA_BLOCK",
+	[MSG_SMS_GET_EEPROM_VERSION_REQ              - MSG_TYPE_BASE_VAL] = "MSG_SMS_GET_EEPROM_VERSION_REQ",
+	[MSG_SMS_GET_EEPROM_VERSION_RES              - MSG_TYPE_BASE_VAL] = "MSG_SMS_GET_EEPROM_VERSION_RES",
+	[MSG_SMS_SIGNAL_DETECTED_IND                 - MSG_TYPE_BASE_VAL] = "MSG_SMS_SIGNAL_DETECTED_IND",
+	[MSG_SMS_NO_SIGNAL_IND                       - MSG_TYPE_BASE_VAL] = "MSG_SMS_NO_SIGNAL_IND",
+	[MSG_SMS_MRC_SHUTDOWN_SLAVE_REQ              - MSG_TYPE_BASE_VAL] = "MSG_SMS_MRC_SHUTDOWN_SLAVE_REQ",
+	[MSG_SMS_MRC_SHUTDOWN_SLAVE_RES              - MSG_TYPE_BASE_VAL] = "MSG_SMS_MRC_SHUTDOWN_SLAVE_RES",
+	[MSG_SMS_MRC_BRINGUP_SLAVE_REQ               - MSG_TYPE_BASE_VAL] = "MSG_SMS_MRC_BRINGUP_SLAVE_REQ",
+	[MSG_SMS_MRC_BRINGUP_SLAVE_RES               - MSG_TYPE_BASE_VAL] = "MSG_SMS_MRC_BRINGUP_SLAVE_RES",
+	[MSG_SMS_EXTERNAL_LNA_CTRL_REQ               - MSG_TYPE_BASE_VAL] = "MSG_SMS_EXTERNAL_LNA_CTRL_REQ",
+	[MSG_SMS_EXTERNAL_LNA_CTRL_RES               - MSG_TYPE_BASE_VAL] = "MSG_SMS_EXTERNAL_LNA_CTRL_RES",
+	[MSG_SMS_SET_PERIODIC_STATISTICS_REQ         - MSG_TYPE_BASE_VAL] = "MSG_SMS_SET_PERIODIC_STATISTICS_REQ",
+	[MSG_SMS_SET_PERIODIC_STATISTICS_RES         - MSG_TYPE_BASE_VAL] = "MSG_SMS_SET_PERIODIC_STATISTICS_RES",
+	[MSG_SMS_CMMB_SET_AUTO_OUTPUT_TS0_REQ        - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_SET_AUTO_OUTPUT_TS0_REQ",
+	[MSG_SMS_CMMB_SET_AUTO_OUTPUT_TS0_RES        - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_SET_AUTO_OUTPUT_TS0_RES",
+	[LOCAL_TUNE                                  - MSG_TYPE_BASE_VAL] = "LOCAL_TUNE",
+	[LOCAL_IFFT_H_ICI                            - MSG_TYPE_BASE_VAL] = "LOCAL_IFFT_H_ICI",
+	[MSG_RESYNC_REQ                              - MSG_TYPE_BASE_VAL] = "MSG_RESYNC_REQ",
+	[MSG_SMS_CMMB_GET_MRC_STATISTICS_REQ         - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_GET_MRC_STATISTICS_REQ",
+	[MSG_SMS_CMMB_GET_MRC_STATISTICS_RES         - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_GET_MRC_STATISTICS_RES",
+	[MSG_SMS_LOG_EX_ITEM                         - MSG_TYPE_BASE_VAL] = "MSG_SMS_LOG_EX_ITEM",
+	[MSG_SMS_DEVICE_DATA_LOSS_IND                - MSG_TYPE_BASE_VAL] = "MSG_SMS_DEVICE_DATA_LOSS_IND",
+	[MSG_SMS_MRC_WATCHDOG_TRIGGERED_IND          - MSG_TYPE_BASE_VAL] = "MSG_SMS_MRC_WATCHDOG_TRIGGERED_IND",
+	[MSG_SMS_USER_MSG_REQ                        - MSG_TYPE_BASE_VAL] = "MSG_SMS_USER_MSG_REQ",
+	[MSG_SMS_USER_MSG_RES                        - MSG_TYPE_BASE_VAL] = "MSG_SMS_USER_MSG_RES",
+	[MSG_SMS_SMART_CARD_INIT_REQ                 - MSG_TYPE_BASE_VAL] = "MSG_SMS_SMART_CARD_INIT_REQ",
+	[MSG_SMS_SMART_CARD_INIT_RES                 - MSG_TYPE_BASE_VAL] = "MSG_SMS_SMART_CARD_INIT_RES",
+	[MSG_SMS_SMART_CARD_WRITE_REQ                - MSG_TYPE_BASE_VAL] = "MSG_SMS_SMART_CARD_WRITE_REQ",
+	[MSG_SMS_SMART_CARD_WRITE_RES                - MSG_TYPE_BASE_VAL] = "MSG_SMS_SMART_CARD_WRITE_RES",
+	[MSG_SMS_SMART_CARD_READ_IND                 - MSG_TYPE_BASE_VAL] = "MSG_SMS_SMART_CARD_READ_IND",
+	[MSG_SMS_TSE_ENABLE_REQ                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_TSE_ENABLE_REQ",
+	[MSG_SMS_TSE_ENABLE_RES                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_TSE_ENABLE_RES",
+	[MSG_SMS_CMMB_GET_SHORT_STATISTICS_REQ       - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_GET_SHORT_STATISTICS_REQ",
+	[MSG_SMS_CMMB_GET_SHORT_STATISTICS_RES       - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_GET_SHORT_STATISTICS_RES",
+	[MSG_SMS_LED_CONFIG_REQ                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_LED_CONFIG_REQ",
+	[MSG_SMS_LED_CONFIG_RES                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_LED_CONFIG_RES",
+	[MSG_PWM_ANTENNA_REQ                         - MSG_TYPE_BASE_VAL] = "MSG_PWM_ANTENNA_REQ",
+	[MSG_PWM_ANTENNA_RES                         - MSG_TYPE_BASE_VAL] = "MSG_PWM_ANTENNA_RES",
+	[MSG_SMS_CMMB_SMD_SN_REQ                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_SMD_SN_REQ",
+	[MSG_SMS_CMMB_SMD_SN_RES                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_SMD_SN_RES",
+	[MSG_SMS_CMMB_SET_CA_CW_REQ                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_SET_CA_CW_REQ",
+	[MSG_SMS_CMMB_SET_CA_CW_RES                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_SET_CA_CW_RES",
+	[MSG_SMS_CMMB_SET_CA_SALT_REQ                - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_SET_CA_SALT_REQ",
+	[MSG_SMS_CMMB_SET_CA_SALT_RES                - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_SET_CA_SALT_RES",
+	[MSG_SMS_NSCD_INIT_REQ                       - MSG_TYPE_BASE_VAL] = "MSG_SMS_NSCD_INIT_REQ",
+	[MSG_SMS_NSCD_INIT_RES                       - MSG_TYPE_BASE_VAL] = "MSG_SMS_NSCD_INIT_RES",
+	[MSG_SMS_NSCD_PROCESS_SECTION_REQ            - MSG_TYPE_BASE_VAL] = "MSG_SMS_NSCD_PROCESS_SECTION_REQ",
+	[MSG_SMS_NSCD_PROCESS_SECTION_RES            - MSG_TYPE_BASE_VAL] = "MSG_SMS_NSCD_PROCESS_SECTION_RES",
+	[MSG_SMS_DBD_CREATE_OBJECT_REQ               - MSG_TYPE_BASE_VAL] = "MSG_SMS_DBD_CREATE_OBJECT_REQ",
+	[MSG_SMS_DBD_CREATE_OBJECT_RES               - MSG_TYPE_BASE_VAL] = "MSG_SMS_DBD_CREATE_OBJECT_RES",
+	[MSG_SMS_DBD_CONFIGURE_REQ                   - MSG_TYPE_BASE_VAL] = "MSG_SMS_DBD_CONFIGURE_REQ",
+	[MSG_SMS_DBD_CONFIGURE_RES                   - MSG_TYPE_BASE_VAL] = "MSG_SMS_DBD_CONFIGURE_RES",
+	[MSG_SMS_DBD_SET_KEYS_REQ                    - MSG_TYPE_BASE_VAL] = "MSG_SMS_DBD_SET_KEYS_REQ",
+	[MSG_SMS_DBD_SET_KEYS_RES                    - MSG_TYPE_BASE_VAL] = "MSG_SMS_DBD_SET_KEYS_RES",
+	[MSG_SMS_DBD_PROCESS_HEADER_REQ              - MSG_TYPE_BASE_VAL] = "MSG_SMS_DBD_PROCESS_HEADER_REQ",
+	[MSG_SMS_DBD_PROCESS_HEADER_RES              - MSG_TYPE_BASE_VAL] = "MSG_SMS_DBD_PROCESS_HEADER_RES",
+	[MSG_SMS_DBD_PROCESS_DATA_REQ                - MSG_TYPE_BASE_VAL] = "MSG_SMS_DBD_PROCESS_DATA_REQ",
+	[MSG_SMS_DBD_PROCESS_DATA_RES                - MSG_TYPE_BASE_VAL] = "MSG_SMS_DBD_PROCESS_DATA_RES",
+	[MSG_SMS_DBD_PROCESS_GET_DATA_REQ            - MSG_TYPE_BASE_VAL] = "MSG_SMS_DBD_PROCESS_GET_DATA_REQ",
+	[MSG_SMS_DBD_PROCESS_GET_DATA_RES            - MSG_TYPE_BASE_VAL] = "MSG_SMS_DBD_PROCESS_GET_DATA_RES",
+	[MSG_SMS_NSCD_OPEN_SESSION_REQ               - MSG_TYPE_BASE_VAL] = "MSG_SMS_NSCD_OPEN_SESSION_REQ",
+	[MSG_SMS_NSCD_OPEN_SESSION_RES               - MSG_TYPE_BASE_VAL] = "MSG_SMS_NSCD_OPEN_SESSION_RES",
+	[MSG_SMS_SEND_HOST_DATA_TO_DEMUX_REQ         - MSG_TYPE_BASE_VAL] = "MSG_SMS_SEND_HOST_DATA_TO_DEMUX_REQ",
+	[MSG_SMS_SEND_HOST_DATA_TO_DEMUX_RES         - MSG_TYPE_BASE_VAL] = "MSG_SMS_SEND_HOST_DATA_TO_DEMUX_RES",
+	[MSG_LAST_MSG_TYPE                           - MSG_TYPE_BASE_VAL] = "MSG_LAST_MSG_TYPE",
+};
+
+char *smscore_translate_msg(enum msg_types msgtype)
+{
+	int i = msgtype - MSG_TYPE_BASE_VAL;
+	char *msg;
+
+	if (i < 0 || i > ARRAY_SIZE(siano_msgs))
+		return "Unknown msg type";
+
+	msg = siano_msgs[i];
+
+	if (!*msg)
+		return "Unknown msg type";
+
+	return msg;
+}
+EXPORT_SYMBOL_GPL(smscore_translate_msg);
+
 void smscore_set_board_id(struct smscore_device_t *core, int id)
 {
 	core->board_id = id;
@@ -96,7 +434,7 @@ static struct mutex g_smscore_deviceslock;
 static struct list_head g_smscore_registry;
 static struct mutex g_smscore_registrylock;
 
-static int default_mode = 4;
+static int default_mode = DEVICE_MODE_NONE;
 
 module_param(default_mode, int, 0644);
 MODULE_PARM_DESC(default_mode, "default firmware id (device mode)");
@@ -151,10 +489,10 @@ static enum sms_device_type_st smscore_registry_gettype(char *devpath)
 	else
 		sms_err("No registry found.");
 
-	return -1;
+	return -EINVAL;
 }
 
-void smscore_registry_setmode(char *devpath, int mode)
+static void smscore_registry_setmode(char *devpath, int mode)
 {
 	struct smscore_registry_entry_t *entry;
 
@@ -294,10 +632,11 @@ static struct
 smscore_buffer_t *smscore_createbuffer(u8 *buffer, void *common_buffer,
 				       dma_addr_t common_buffer_phys)
 {
-	struct smscore_buffer_t *cb =
-		kmalloc(sizeof(struct smscore_buffer_t), GFP_KERNEL);
+	struct smscore_buffer_t *cb;
+
+	cb = kzalloc(sizeof(struct smscore_buffer_t), GFP_KERNEL);
 	if (!cb) {
-		sms_info("kmalloc(...) failed");
+		sms_info("kzalloc(...) failed");
 		return NULL;
 	}
 
@@ -344,6 +683,7 @@ int smscore_register_device(struct smsdevice_params_t *params,
 	/* init completion events */
 	init_completion(&dev->version_ex_done);
 	init_completion(&dev->data_download_done);
+	init_completion(&dev->data_validity_done);
 	init_completion(&dev->trigger_done);
 	init_completion(&dev->init_device_done);
 	init_completion(&dev->reload_start_done);
@@ -370,9 +710,10 @@ int smscore_register_device(struct smsdevice_params_t *params,
 	for (buffer = dev->common_buffer;
 	     dev->num_buffers < params->num_buffers;
 	     dev->num_buffers++, buffer += params->buffer_size) {
-		struct smscore_buffer_t *cb =
-			smscore_createbuffer(buffer, dev->common_buffer,
-					     dev->common_buffer_phys);
+		struct smscore_buffer_t *cb;
+
+		cb = smscore_createbuffer(buffer, dev->common_buffer,
+					  dev->common_buffer_phys);
 		if (!cb) {
 			smscore_unregister_device(dev);
 			return -ENOMEM;
@@ -384,6 +725,7 @@ int smscore_register_device(struct smsdevice_params_t *params,
 	sms_info("allocated %d buffers", dev->num_buffers);
 
 	dev->mode = DEVICE_MODE_NONE;
+	dev->board_id = SMS_BOARD_UNKNOWN;
 	dev->context = params->context;
 	dev->device = params->device;
 	dev->setmode_handler = params->setmode_handler;
@@ -413,7 +755,13 @@ EXPORT_SYMBOL_GPL(smscore_register_device);
 
 static int smscore_sendrequest_and_wait(struct smscore_device_t *coredev,
 		void *buffer, size_t size, struct completion *completion) {
-	int rc = coredev->sendrequest_handler(coredev->context, buffer, size);
+	int rc;
+
+	if (completion == NULL)
+		return -EINVAL;
+	init_completion(completion);
+
+	rc = coredev->sendrequest_handler(coredev->context, buffer, size);
 	if (rc < 0) {
 		sms_info("sendrequest returned error %d", rc);
 		return rc;
@@ -444,24 +792,22 @@ static int smscore_init_ir(struct smscore_device_t *coredev)
 		if	(rc != 0)
 			sms_err("Error initialization DTV IR sub-module");
 		else {
-			buffer = kmalloc(sizeof(struct SmsMsgData_ST2) +
+			buffer = kmalloc(sizeof(struct sms_msg_data2) +
 						SMS_DMA_ALIGNMENT,
 						GFP_KERNEL | GFP_DMA);
 			if (buffer) {
-				struct SmsMsgData_ST2 *msg =
-				(struct SmsMsgData_ST2 *)
+				struct sms_msg_data2 *msg =
+				(struct sms_msg_data2 *)
 				SMS_ALIGN_ADDRESS(buffer);
 
-				SMS_INIT_MSG(&msg->xMsgHeader,
+				SMS_INIT_MSG(&msg->x_msg_header,
 						MSG_SMS_START_IR_REQ,
-						sizeof(struct SmsMsgData_ST2));
-				msg->msgData[0] = coredev->ir.controller;
-				msg->msgData[1] = coredev->ir.timeout;
+						sizeof(struct sms_msg_data2));
+				msg->msg_data[0] = coredev->ir.controller;
+				msg->msg_data[1] = coredev->ir.timeout;
 
-				smsendian_handle_tx_message(
-					(struct SmsMsgHdr_ST2 *)msg);
 				rc = smscore_sendrequest_and_wait(coredev, msg,
-						msg->xMsgHeader. msgLength,
+						msg->x_msg_header. msg_length,
 						&coredev->ir_init_done);
 
 				kfree(buffer);
@@ -476,21 +822,82 @@ static int smscore_init_ir(struct smscore_device_t *coredev)
 }
 
 /**
+ * configures device features according to board configuration structure.
+ *
+ * @param coredev pointer to a coredev object returned by
+ *                smscore_register_device
+ *
+ * @return 0 on success, <0 on error.
+ */
+static int smscore_configure_board(struct smscore_device_t *coredev)
+{
+	struct sms_board *board;
+
+	board = sms_get_board(coredev->board_id);
+	if (!board) {
+		sms_err("no board configuration exist.");
+		return -EINVAL;
+	}
+
+	if (board->mtu) {
+		struct sms_msg_data mtu_msg;
+		sms_debug("set max transmit unit %d", board->mtu);
+
+		mtu_msg.x_msg_header.msg_src_id = 0;
+		mtu_msg.x_msg_header.msg_dst_id = HIF_TASK;
+		mtu_msg.x_msg_header.msg_flags = 0;
+		mtu_msg.x_msg_header.msg_type = MSG_SMS_SET_MAX_TX_MSG_LEN_REQ;
+		mtu_msg.x_msg_header.msg_length = sizeof(mtu_msg);
+		mtu_msg.msg_data[0] = board->mtu;
+
+		coredev->sendrequest_handler(coredev->context, &mtu_msg,
+					     sizeof(mtu_msg));
+	}
+
+	if (board->crystal) {
+		struct sms_msg_data crys_msg;
+		sms_debug("set crystal value %d", board->crystal);
+
+		SMS_INIT_MSG(&crys_msg.x_msg_header,
+				MSG_SMS_NEW_CRYSTAL_REQ,
+				sizeof(crys_msg));
+		crys_msg.msg_data[0] = board->crystal;
+
+		coredev->sendrequest_handler(coredev->context, &crys_msg,
+					     sizeof(crys_msg));
+	}
+
+	return 0;
+}
+
+/**
  * sets initial device mode and notifies client hotplugs that device is ready
  *
  * @param coredev pointer to a coredev object returned by
- * 		  smscore_register_device
+ *		  smscore_register_device
  *
  * @return 0 on success, <0 on error.
  */
 int smscore_start_device(struct smscore_device_t *coredev)
 {
-	int rc = smscore_set_device_mode(
-			coredev, smscore_registry_getmode(coredev->devpath));
+	int rc;
+	int board_id = smscore_get_board_id(coredev);
+	int mode = smscore_registry_getmode(coredev->devpath);
+
+	/* Device is initialized as DEVICE_MODE_NONE */
+	if (board_id != SMS_BOARD_UNKNOWN && mode == DEVICE_MODE_NONE)
+		mode = sms_get_board(board_id)->default_mode;
+
+	rc = smscore_set_device_mode(coredev, mode);
 	if (rc < 0) {
 		sms_info("set device mode faile , rc %d", rc);
 		return rc;
 	}
+	rc = smscore_configure_board(coredev);
+	if (rc < 0) {
+		sms_info("configure board failed , rc %d", rc);
+		return rc;
+	}
 
 	kmutex_lock(&g_smscore_deviceslock);
 
@@ -509,18 +916,19 @@ EXPORT_SYMBOL_GPL(smscore_start_device);
 static int smscore_load_firmware_family2(struct smscore_device_t *coredev,
 					 void *buffer, size_t size)
 {
-	struct SmsFirmware_ST *firmware = (struct SmsFirmware_ST *) buffer;
-	struct SmsMsgHdr_ST *msg;
-	u32 mem_address;
-	u8 *payload = firmware->Payload;
+	struct sms_firmware *firmware = (struct sms_firmware *) buffer;
+	struct sms_msg_data4 *msg;
+	u32 mem_address,  calc_checksum = 0;
+	u32 i, *ptr;
+	u8 *payload = firmware->payload;
 	int rc = 0;
-	firmware->StartAddress = le32_to_cpu(firmware->StartAddress);
-	firmware->Length = le32_to_cpu(firmware->Length);
+	firmware->start_address = le32_to_cpu(firmware->start_address);
+	firmware->length = le32_to_cpu(firmware->length);
 
-	mem_address = firmware->StartAddress;
+	mem_address = firmware->start_address;
 
 	sms_info("loading FW to addr 0x%x size %d",
-		 mem_address, firmware->Length);
+		 mem_address, firmware->length);
 	if (coredev->preload_handler) {
 		rc = coredev->preload_handler(coredev->context);
 		if (rc < 0)
@@ -534,35 +942,36 @@ static int smscore_load_firmware_family2(struct smscore_device_t *coredev,
 
 	if (coredev->mode != DEVICE_MODE_NONE) {
 		sms_debug("sending reload command.");
-		SMS_INIT_MSG(msg, MSG_SW_RELOAD_START_REQ,
-			     sizeof(struct SmsMsgHdr_ST));
+		SMS_INIT_MSG(&msg->x_msg_header, MSG_SW_RELOAD_START_REQ,
+			     sizeof(struct sms_msg_hdr));
 		rc = smscore_sendrequest_and_wait(coredev, msg,
-						  msg->msgLength,
+						  msg->x_msg_header.msg_length,
 						  &coredev->reload_start_done);
+		if (rc < 0) {
+			sms_err("device reload failed, rc %d", rc);
+			goto exit_fw_download;
+		}
 		mem_address = *(u32 *) &payload[20];
 	}
 
+	for (i = 0, ptr = (u32 *)firmware->payload; i < firmware->length/4 ;
+	     i++, ptr++)
+		calc_checksum += *ptr;
+
 	while (size && rc >= 0) {
-		struct SmsDataDownload_ST *DataMsg =
-			(struct SmsDataDownload_ST *) msg;
-		int payload_size = min((int) size, SMS_MAX_PAYLOAD_SIZE);
+		struct sms_data_download *data_msg =
+			(struct sms_data_download *) msg;
+		int payload_size = min_t(int, size, SMS_MAX_PAYLOAD_SIZE);
 
-		SMS_INIT_MSG(msg, MSG_SMS_DATA_DOWNLOAD_REQ,
-			     (u16)(sizeof(struct SmsMsgHdr_ST) +
+		SMS_INIT_MSG(&msg->x_msg_header, MSG_SMS_DATA_DOWNLOAD_REQ,
+			     (u16)(sizeof(struct sms_msg_hdr) +
 				      sizeof(u32) + payload_size));
 
-		DataMsg->MemAddr = mem_address;
-		memcpy(DataMsg->Payload, payload, payload_size);
+		data_msg->mem_addr = mem_address;
+		memcpy(data_msg->payload, payload, payload_size);
 
-		if ((coredev->device_flags & SMS_ROM_NO_RESPONSE) &&
-		    (coredev->mode == DEVICE_MODE_NONE))
-			rc = coredev->sendrequest_handler(
-				coredev->context, DataMsg,
-				DataMsg->xMsgHeader.msgLength);
-		else
-			rc = smscore_sendrequest_and_wait(
-				coredev, DataMsg,
-				DataMsg->xMsgHeader.msgLength,
+		rc = smscore_sendrequest_and_wait(coredev, data_msg,
+				data_msg->x_msg_header.msg_length,
 				&coredev->data_download_done);
 
 		payload += payload_size;
@@ -570,50 +979,158 @@ static int smscore_load_firmware_family2(struct smscore_device_t *coredev,
 		mem_address += payload_size;
 	}
 
-	if (rc >= 0) {
-		if (coredev->mode == DEVICE_MODE_NONE) {
-			struct SmsMsgData_ST *TriggerMsg =
-				(struct SmsMsgData_ST *) msg;
-
-			SMS_INIT_MSG(msg, MSG_SMS_SWDOWNLOAD_TRIGGER_REQ,
-				     sizeof(struct SmsMsgHdr_ST) +
-				     sizeof(u32) * 5);
-
-			TriggerMsg->msgData[0] = firmware->StartAddress;
-						/* Entry point */
-			TriggerMsg->msgData[1] = 5; /* Priority */
-			TriggerMsg->msgData[2] = 0x200; /* Stack size */
-			TriggerMsg->msgData[3] = 0; /* Parameter */
-			TriggerMsg->msgData[4] = 4; /* Task ID */
-
-			if (coredev->device_flags & SMS_ROM_NO_RESPONSE) {
-				rc = coredev->sendrequest_handler(
-					coredev->context, TriggerMsg,
-					TriggerMsg->xMsgHeader.msgLength);
-				msleep(100);
-			} else
-				rc = smscore_sendrequest_and_wait(
-					coredev, TriggerMsg,
-					TriggerMsg->xMsgHeader.msgLength,
+	if (rc < 0)
+		goto exit_fw_download;
+
+	sms_err("sending MSG_SMS_DATA_VALIDITY_REQ expecting 0x%x",
+		calc_checksum);
+	SMS_INIT_MSG(&msg->x_msg_header, MSG_SMS_DATA_VALIDITY_REQ,
+			sizeof(msg->x_msg_header) +
+			sizeof(u32) * 3);
+	msg->msg_data[0] = firmware->start_address;
+		/* Entry point */
+	msg->msg_data[1] = firmware->length;
+	msg->msg_data[2] = 0; /* Regular checksum*/
+	rc = smscore_sendrequest_and_wait(coredev, msg,
+					  msg->x_msg_header.msg_length,
+					  &coredev->data_validity_done);
+	if (rc < 0)
+		goto exit_fw_download;
+
+	if (coredev->mode == DEVICE_MODE_NONE) {
+		struct sms_msg_data *trigger_msg =
+			(struct sms_msg_data *) msg;
+
+		sms_debug("sending MSG_SMS_SWDOWNLOAD_TRIGGER_REQ");
+		SMS_INIT_MSG(&msg->x_msg_header,
+				MSG_SMS_SWDOWNLOAD_TRIGGER_REQ,
+				sizeof(struct sms_msg_hdr) +
+				sizeof(u32) * 5);
+
+		trigger_msg->msg_data[0] = firmware->start_address;
+					/* Entry point */
+		trigger_msg->msg_data[1] = 6; /* Priority */
+		trigger_msg->msg_data[2] = 0x200; /* Stack size */
+		trigger_msg->msg_data[3] = 0; /* Parameter */
+		trigger_msg->msg_data[4] = 4; /* Task ID */
+
+		rc = smscore_sendrequest_and_wait(coredev, trigger_msg,
+					trigger_msg->x_msg_header.msg_length,
 					&coredev->trigger_done);
-		} else {
-			SMS_INIT_MSG(msg, MSG_SW_RELOAD_EXEC_REQ,
-				     sizeof(struct SmsMsgHdr_ST));
-
-			rc = coredev->sendrequest_handler(coredev->context,
-							  msg, msg->msgLength);
-		}
-		msleep(500);
+	} else {
+		SMS_INIT_MSG(&msg->x_msg_header, MSG_SW_RELOAD_EXEC_REQ,
+				sizeof(struct sms_msg_hdr));
+		rc = coredev->sendrequest_handler(coredev->context, msg,
+				msg->x_msg_header.msg_length);
 	}
 
-	sms_debug("rc=%d, postload=%p ", rc,
-		  coredev->postload_handler);
+	if (rc < 0)
+		goto exit_fw_download;
+
+	/*
+	 * backward compatibility - wait to device_ready_done for
+	 * not more than 400 ms
+	 */
+	msleep(400);
 
+exit_fw_download:
 	kfree(msg);
 
-	return ((rc >= 0) && coredev->postload_handler) ?
-		coredev->postload_handler(coredev->context) :
-		rc;
+	if (coredev->postload_handler) {
+		sms_debug("rc=%d, postload=0x%p", rc, coredev->postload_handler);
+		if (rc >= 0)
+			return coredev->postload_handler(coredev->context);
+	}
+
+	sms_debug("rc=%d", rc);
+	return rc;
+}
+
+static char *smscore_fw_lkup[][DEVICE_MODE_MAX] = {
+	[SMS_NOVA_A0] = {
+		[DEVICE_MODE_DVBT]		= SMS_FW_DVB_NOVA_12MHZ,
+		[DEVICE_MODE_DVBH]		= SMS_FW_DVB_NOVA_12MHZ,
+		[DEVICE_MODE_DAB_TDMB]		= SMS_FW_TDMB_NOVA_12MHZ,
+		[DEVICE_MODE_DVBT_BDA]		= SMS_FW_DVB_NOVA_12MHZ,
+		[DEVICE_MODE_ISDBT]		= SMS_FW_ISDBT_NOVA_12MHZ,
+		[DEVICE_MODE_ISDBT_BDA]		= SMS_FW_ISDBT_NOVA_12MHZ,
+	},
+	[SMS_NOVA_B0] = {
+		[DEVICE_MODE_DVBT]		= SMS_FW_DVB_NOVA_12MHZ_B0,
+		[DEVICE_MODE_DVBH]		= SMS_FW_DVB_NOVA_12MHZ_B0,
+		[DEVICE_MODE_DAB_TDMB]		= SMS_FW_TDMB_NOVA_12MHZ_B0,
+		[DEVICE_MODE_DVBT_BDA]		= SMS_FW_DVB_NOVA_12MHZ_B0,
+		[DEVICE_MODE_ISDBT]		= SMS_FW_ISDBT_NOVA_12MHZ_B0,
+		[DEVICE_MODE_ISDBT_BDA]		= SMS_FW_ISDBT_NOVA_12MHZ_B0,
+		[DEVICE_MODE_FM_RADIO]		= SMS_FW_FM_RADIO,
+		[DEVICE_MODE_FM_RADIO_BDA]	= SMS_FW_FM_RADIO,
+	},
+	[SMS_VEGA] = {
+		[DEVICE_MODE_CMMB]		= SMS_FW_CMMB_VEGA_12MHZ,
+	},
+	[SMS_VENICE] = {
+		[DEVICE_MODE_CMMB]		= SMS_FW_CMMB_VENICE_12MHZ,
+	},
+	[SMS_MING] = {
+		[DEVICE_MODE_CMMB]		= SMS_FW_CMMB_MING_APP,
+	},
+	[SMS_PELE] = {
+		[DEVICE_MODE_ISDBT]		= SMS_FW_ISDBT_PELE,
+		[DEVICE_MODE_ISDBT_BDA]		= SMS_FW_ISDBT_PELE,
+	},
+	[SMS_RIO] = {
+		[DEVICE_MODE_DVBT]		= SMS_FW_DVB_RIO,
+		[DEVICE_MODE_DVBH]		= SMS_FW_DVBH_RIO,
+		[DEVICE_MODE_DVBT_BDA]		= SMS_FW_DVB_RIO,
+		[DEVICE_MODE_ISDBT]		= SMS_FW_ISDBT_RIO,
+		[DEVICE_MODE_ISDBT_BDA]		= SMS_FW_ISDBT_RIO,
+		[DEVICE_MODE_FM_RADIO]		= SMS_FW_FM_RADIO_RIO,
+		[DEVICE_MODE_FM_RADIO_BDA]	= SMS_FW_FM_RADIO_RIO,
+	},
+	[SMS_DENVER_1530] = {
+		[DEVICE_MODE_ATSC]		= SMS_FW_ATSC_DENVER,
+	},
+	[SMS_DENVER_2160] = {
+		[DEVICE_MODE_DAB_TDMB]		= SMS_FW_TDMB_DENVER,
+	},
+};
+
+/**
+ * get firmware file name from one of the two mechanisms : sms_boards or
+ * smscore_fw_lkup.
+ * @param coredev pointer to a coredev object returned by
+ *		  smscore_register_device
+ * @param mode requested mode of operation
+ * @param lookup if 1, always get the fw filename from smscore_fw_lkup
+ *	 table. if 0, try first to get from sms_boards
+ *
+ * @return 0 on success, <0 on error.
+ */
+static char *smscore_get_fw_filename(struct smscore_device_t *coredev,
+			      int mode)
+{
+	char **fw;
+	int board_id = smscore_get_board_id(coredev);
+	enum sms_device_type_st type;
+
+	type = smscore_registry_gettype(coredev->devpath);
+
+	/* Prevent looking outside the smscore_fw_lkup table */
+	if (type <= SMS_UNKNOWN_TYPE || type >= SMS_NUM_OF_DEVICE_TYPES)
+		return NULL;
+	if (mode <= DEVICE_MODE_NONE || mode >= DEVICE_MODE_MAX)
+		return NULL;
+
+	sms_debug("trying to get fw name from sms_boards board_id %d mode %d",
+		  board_id, mode);
+	fw = sms_get_board(board_id)->fw;
+	if (!fw || !fw[mode]) {
+		sms_debug("cannot find fw name in sms_boards, getting from lookup table mode %d type %d",
+			  mode, type);
+		return smscore_fw_lkup[type][mode];
+	}
+
+	return fw[mode];
 }
 
 /**
@@ -627,41 +1144,46 @@ static int smscore_load_firmware_family2(struct smscore_device_t *coredev,
  * @return 0 on success, <0 on error.
  */
 static int smscore_load_firmware_from_file(struct smscore_device_t *coredev,
-					   char *filename,
+					   int mode,
 					   loadfirmware_t loadfirmware_handler)
 {
 	int rc = -ENOENT;
+	u8 *fw_buf;
+	u32 fw_buf_size;
 	const struct firmware *fw;
-	u8 *fw_buffer;
 
-	if (loadfirmware_handler == NULL && !(coredev->device_flags &
-					      SMS_DEVICE_FAMILY2))
+	char *fw_filename = smscore_get_fw_filename(coredev, mode);
+	if (!fw_filename) {
+		sms_info("mode %d not supported on this device", mode);
+		return -ENOENT;
+	}
+	sms_debug("Firmware name: %s", fw_filename);
+
+	if (loadfirmware_handler == NULL && !(coredev->device_flags
+			& SMS_DEVICE_FAMILY2))
 		return -EINVAL;
 
-	rc = request_firmware(&fw, filename, coredev->device);
+	rc = request_firmware(&fw, fw_filename, coredev->device);
 	if (rc < 0) {
-		sms_info("failed to open \"%s\"", filename);
+		sms_info("failed to open \"%s\"", fw_filename);
 		return rc;
 	}
-	sms_info("read FW %s, size=%zd", filename, fw->size);
-	fw_buffer = kmalloc(ALIGN(fw->size, SMS_ALLOC_ALIGNMENT),
-			    GFP_KERNEL | GFP_DMA);
-	if (fw_buffer) {
-		memcpy(fw_buffer, fw->data, fw->size);
-
-		rc = (coredev->device_flags & SMS_DEVICE_FAMILY2) ?
-		      smscore_load_firmware_family2(coredev,
-						    fw_buffer,
-						    fw->size) :
-		      loadfirmware_handler(coredev->context,
-					   fw_buffer, fw->size);
-
-		kfree(fw_buffer);
-	} else {
+	sms_info("read fw %s, buffer size=0x%zx", fw_filename, fw->size);
+	fw_buf = kmalloc(ALIGN(fw->size, SMS_ALLOC_ALIGNMENT),
+			 GFP_KERNEL | GFP_DMA);
+	if (!fw_buf) {
 		sms_info("failed to allocate firmware buffer");
-		rc = -ENOMEM;
+		return -ENOMEM;
 	}
+	memcpy(fw_buf, fw->data, fw->size);
+	fw_buf_size = fw->size;
+
+	rc = (coredev->device_flags & SMS_DEVICE_FAMILY2) ?
+		smscore_load_firmware_family2(coredev, fw_buf, fw_buf_size)
+		: loadfirmware_handler(coredev->context, fw_buf,
+		fw_buf_size);
 
+	kfree(fw_buf);
 	release_firmware(fw);
 
 	return rc;
@@ -703,14 +1225,15 @@ void smscore_unregister_device(struct smscore_device_t *coredev)
 		if (num_buffers == coredev->num_buffers)
 			break;
 		if (++retry > 10) {
-			sms_info("exiting although "
-				 "not all buffers released.");
+			sms_info("exiting although not all buffers released.");
 			break;
 		}
 
 		sms_info("waiting for %d buffer(s)",
 			 coredev->num_buffers - num_buffers);
+		kmutex_unlock(&g_smscore_deviceslock);
 		msleep(100);
+		kmutex_lock(&g_smscore_deviceslock);
 	}
 
 	sms_info("freed %d buffers", num_buffers);
@@ -719,8 +1242,7 @@ void smscore_unregister_device(struct smscore_device_t *coredev)
 		dma_free_coherent(NULL, coredev->common_buffer_size,
 			coredev->common_buffer, coredev->common_buffer_phys);
 
-	if (coredev->fw_buf != NULL)
-		kfree(coredev->fw_buf);
+	kfree(coredev->fw_buf);
 
 	list_del(&coredev->entry);
 	kfree(coredev);
@@ -733,19 +1255,19 @@ EXPORT_SYMBOL_GPL(smscore_unregister_device);
 
 static int smscore_detect_mode(struct smscore_device_t *coredev)
 {
-	void *buffer = kmalloc(sizeof(struct SmsMsgHdr_ST) + SMS_DMA_ALIGNMENT,
+	void *buffer = kmalloc(sizeof(struct sms_msg_hdr) + SMS_DMA_ALIGNMENT,
 			       GFP_KERNEL | GFP_DMA);
-	struct SmsMsgHdr_ST *msg =
-		(struct SmsMsgHdr_ST *) SMS_ALIGN_ADDRESS(buffer);
+	struct sms_msg_hdr *msg =
+		(struct sms_msg_hdr *) SMS_ALIGN_ADDRESS(buffer);
 	int rc;
 
 	if (!buffer)
 		return -ENOMEM;
 
 	SMS_INIT_MSG(msg, MSG_SMS_GET_VERSION_EX_REQ,
-		     sizeof(struct SmsMsgHdr_ST));
+		     sizeof(struct sms_msg_hdr));
 
-	rc = smscore_sendrequest_and_wait(coredev, msg, msg->msgLength,
+	rc = smscore_sendrequest_and_wait(coredev, msg, msg->msg_length,
 					  &coredev->version_ex_done);
 	if (rc == -ETIME) {
 		sms_err("MSG_SMS_GET_VERSION_EX_REQ failed first try");
@@ -753,11 +1275,11 @@ static int smscore_detect_mode(struct smscore_device_t *coredev)
 		if (wait_for_completion_timeout(&coredev->resume_done,
 						msecs_to_jiffies(5000))) {
 			rc = smscore_sendrequest_and_wait(
-				coredev, msg, msg->msgLength,
+				coredev, msg, msg->msg_length,
 				&coredev->version_ex_done);
 			if (rc < 0)
-				sms_err("MSG_SMS_GET_VERSION_EX_REQ failed "
-					"second try, rc %d", rc);
+				sms_err("MSG_SMS_GET_VERSION_EX_REQ failed second try, rc %d",
+					rc);
 		} else
 			rc = -ETIME;
 	}
@@ -767,31 +1289,39 @@ static int smscore_detect_mode(struct smscore_device_t *coredev)
 	return rc;
 }
 
-static char *smscore_fw_lkup[][SMS_NUM_OF_DEVICE_TYPES] = {
-	/*Stellar		NOVA A0		Nova B0		VEGA*/
-	/*DVBT*/
-	{"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"},
-	/*DVBH*/
-	{"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"},
-	/*TDMB*/
-	{"none", "tdmb_nova_12mhz.inp", "tdmb_nova_12mhz_b0.inp", "none"},
-	/*DABIP*/
-	{"none", "none", "none", "none"},
-	/*BDA*/
-	{"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"},
-	/*ISDBT*/
-	{"none", "isdbt_nova_12mhz.inp", "isdbt_nova_12mhz_b0.inp", "none"},
-	/*ISDBTBDA*/
-	{"none", "isdbt_nova_12mhz.inp", "isdbt_nova_12mhz_b0.inp", "none"},
-	/*CMMB*/
-	{"none", "none", "none", "cmmb_vega_12mhz.inp"}
-};
-
-static inline char *sms_get_fw_name(struct smscore_device_t *coredev,
-				    int mode, enum sms_device_type_st type)
+/**
+ * send init device request and wait for response
+ *
+ * @param coredev pointer to a coredev object returned by
+ *                smscore_register_device
+ * @param mode requested mode of operation
+ *
+ * @return 0 on success, <0 on error.
+ */
+static int smscore_init_device(struct smscore_device_t *coredev, int mode)
 {
-	char **fw = sms_get_board(smscore_get_board_id(coredev))->fw;
-	return (fw && fw[mode]) ? fw[mode] : smscore_fw_lkup[mode][type];
+	void *buffer;
+	struct sms_msg_data *msg;
+	int rc = 0;
+
+	buffer = kmalloc(sizeof(struct sms_msg_data) +
+			SMS_DMA_ALIGNMENT, GFP_KERNEL | GFP_DMA);
+	if (!buffer) {
+		sms_err("Could not allocate buffer for init device message.");
+		return -ENOMEM;
+	}
+
+	msg = (struct sms_msg_data *)SMS_ALIGN_ADDRESS(buffer);
+	SMS_INIT_MSG(&msg->x_msg_header, MSG_SMS_INIT_DEVICE_REQ,
+			sizeof(struct sms_msg_data));
+	msg->msg_data[0] = mode;
+
+	rc = smscore_sendrequest_and_wait(coredev, msg,
+			msg->x_msg_header. msg_length,
+			&coredev->init_device_done);
+
+	kfree(buffer);
+	return rc;
 }
 
 /**
@@ -806,13 +1336,11 @@ static inline char *sms_get_fw_name(struct smscore_device_t *coredev,
  */
 int smscore_set_device_mode(struct smscore_device_t *coredev, int mode)
 {
-	void *buffer;
 	int rc = 0;
-	enum sms_device_type_st type;
 
 	sms_debug("set device mode to %d", mode);
 	if (coredev->device_flags & SMS_DEVICE_FAMILY2) {
-		if (mode < DEVICE_MODE_DVBT || mode >= DEVICE_MODE_RAW_TUNER) {
+		if (mode <= DEVICE_MODE_NONE || mode >= DEVICE_MODE_MAX) {
 			sms_err("invalid mode specified %d", mode);
 			return -EINVAL;
 		}
@@ -833,58 +1361,21 @@ int smscore_set_device_mode(struct smscore_device_t *coredev, int mode)
 		}
 
 		if (!(coredev->modes_supported & (1 << mode))) {
-			char *fw_filename;
-
-			type = smscore_registry_gettype(coredev->devpath);
-			fw_filename = sms_get_fw_name(coredev, mode, type);
-
 			rc = smscore_load_firmware_from_file(coredev,
-							     fw_filename, NULL);
-			if (rc < 0) {
-				sms_warn("error %d loading firmware: %s, "
-					 "trying again with default firmware",
-					 rc, fw_filename);
-
-				/* try again with the default firmware */
-				fw_filename = smscore_fw_lkup[mode][type];
-				rc = smscore_load_firmware_from_file(coredev,
-							     fw_filename, NULL);
-
-				if (rc < 0) {
-					sms_warn("error %d loading "
-						 "firmware: %s", rc,
-						 fw_filename);
-					return rc;
-				}
-			}
-			sms_log("firmware download success: %s", fw_filename);
-		} else
-			sms_info("mode %d supported by running "
-				 "firmware", mode);
-
-		buffer = kmalloc(sizeof(struct SmsMsgData_ST) +
-				 SMS_DMA_ALIGNMENT, GFP_KERNEL | GFP_DMA);
-		if (buffer) {
-			struct SmsMsgData_ST *msg =
-				(struct SmsMsgData_ST *)
-					SMS_ALIGN_ADDRESS(buffer);
-
-			SMS_INIT_MSG(&msg->xMsgHeader, MSG_SMS_INIT_DEVICE_REQ,
-				     sizeof(struct SmsMsgData_ST));
-			msg->msgData[0] = mode;
-
-			rc = smscore_sendrequest_and_wait(
-				coredev, msg, msg->xMsgHeader.msgLength,
-				&coredev->init_device_done);
-
-			kfree(buffer);
+							     mode, NULL);
+			if (rc >= 0)
+				sms_info("firmware download success");
 		} else {
-			sms_err("Could not allocate buffer for "
-				"init device message.");
-			rc = -ENOMEM;
+			sms_info("mode %d is already supported by running firmware",
+				 mode);
+		}
+		if (coredev->fw_version >= 0x800) {
+			rc = smscore_init_device(coredev, mode);
+			if (rc < 0)
+				sms_err("device init failed, rc %d.", rc);
 		}
 	} else {
-		if (mode < DEVICE_MODE_DVBT || mode > DEVICE_MODE_DVBT_BDA) {
+		if (mode <= DEVICE_MODE_NONE || mode >= DEVICE_MODE_MAX) {
 			sms_err("invalid mode specified %d", mode);
 			return -EINVAL;
 		}
@@ -900,12 +1391,32 @@ int smscore_set_device_mode(struct smscore_device_t *coredev, int mode)
 	}
 
 	if (rc >= 0) {
+		char *buffer;
 		coredev->mode = mode;
 		coredev->device_flags &= ~SMS_DEVICE_NOT_READY;
+
+		buffer = kmalloc(sizeof(struct sms_msg_data) +
+				 SMS_DMA_ALIGNMENT, GFP_KERNEL | GFP_DMA);
+		if (buffer) {
+			struct sms_msg_data *msg = (struct sms_msg_data *) SMS_ALIGN_ADDRESS(buffer);
+
+			SMS_INIT_MSG(&msg->x_msg_header, MSG_SMS_INIT_DEVICE_REQ,
+				     sizeof(struct sms_msg_data));
+			msg->msg_data[0] = mode;
+
+			rc = smscore_sendrequest_and_wait(
+				coredev, msg, msg->x_msg_header.msg_length,
+				&coredev->init_device_done);
+
+			kfree(buffer);
+		}
 	}
 
 	if (rc < 0)
 		sms_err("return error code %d.", rc);
+	else
+		sms_debug("Success setting device mode.");
+
 	return rc;
 }
 
@@ -971,7 +1482,7 @@ found:
  */
 void smscore_onresponse(struct smscore_device_t *coredev,
 		struct smscore_buffer_t *cb) {
-	struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *) ((u8 *) cb->p
+	struct sms_msg_hdr *phdr = (struct sms_msg_hdr *) ((u8 *) cb->p
 			+ cb->offset);
 	struct smscore_client_t *client;
 	int rc = -EBUSY;
@@ -983,7 +1494,7 @@ void smscore_onresponse(struct smscore_device_t *coredev,
 		last_sample_time = time_now;
 
 	if (time_now - last_sample_time > 10000) {
-		sms_debug("\ndata rate %d bytes/secs",
+		sms_debug("data rate %d bytes/secs",
 			  (int)((data_total * 1000) /
 				(time_now - last_sample_time)));
 
@@ -993,14 +1504,14 @@ void smscore_onresponse(struct smscore_device_t *coredev,
 
 	data_total += cb->size;
 	/* Do we need to re-route? */
-	if ((phdr->msgType == MSG_SMS_HO_PER_SLICES_IND) ||
-			(phdr->msgType == MSG_SMS_TRANSMISSION_IND)) {
+	if ((phdr->msg_type == MSG_SMS_HO_PER_SLICES_IND) ||
+			(phdr->msg_type == MSG_SMS_TRANSMISSION_IND)) {
 		if (coredev->mode == DEVICE_MODE_DVBT_BDA)
-			phdr->msgDstId = DVBT_BDA_CONTROL_MSG_ID;
+			phdr->msg_dst_id = DVBT_BDA_CONTROL_MSG_ID;
 	}
 
 
-	client = smscore_find_client(coredev, phdr->msgType, phdr->msgDstId);
+	client = smscore_find_client(coredev, phdr->msg_type, phdr->msg_dst_id);
 
 	/* If no client registered for type & id,
 	 * check for control client where type is not registered */
@@ -1008,57 +1519,75 @@ void smscore_onresponse(struct smscore_device_t *coredev,
 		rc = client->onresponse_handler(client->context, cb);
 
 	if (rc < 0) {
-		switch (phdr->msgType) {
+		switch (phdr->msg_type) {
+		case MSG_SMS_ISDBT_TUNE_RES:
+			break;
+		case MSG_SMS_RF_TUNE_RES:
+			break;
+		case MSG_SMS_SIGNAL_DETECTED_IND:
+			break;
+		case MSG_SMS_NO_SIGNAL_IND:
+			break;
+		case MSG_SMS_SPI_INT_LINE_SET_RES:
+			break;
+		case MSG_SMS_INTERFACE_LOCK_IND:
+			break;
+		case MSG_SMS_INTERFACE_UNLOCK_IND:
+			break;
 		case MSG_SMS_GET_VERSION_EX_RES:
 		{
-			struct SmsVersionRes_ST *ver =
-				(struct SmsVersionRes_ST *) phdr;
-			sms_debug("MSG_SMS_GET_VERSION_EX_RES "
-				  "id %d prots 0x%x ver %d.%d",
-				  ver->FirmwareId, ver->SupportedProtocols,
-				  ver->RomVersionMajor, ver->RomVersionMinor);
-
-			coredev->mode = ver->FirmwareId == 255 ?
-				DEVICE_MODE_NONE : ver->FirmwareId;
-			coredev->modes_supported = ver->SupportedProtocols;
+			struct sms_version_res *ver =
+				(struct sms_version_res *) phdr;
+			sms_debug("Firmware id %d prots 0x%x ver %d.%d",
+				  ver->firmware_id, ver->supported_protocols,
+				  ver->rom_ver_major, ver->rom_ver_minor);
+
+			coredev->mode = ver->firmware_id == 255 ?
+				DEVICE_MODE_NONE : ver->firmware_id;
+			coredev->modes_supported = ver->supported_protocols;
+			coredev->fw_version = ver->rom_ver_major << 8 |
+					      ver->rom_ver_minor;
 
 			complete(&coredev->version_ex_done);
 			break;
 		}
 		case MSG_SMS_INIT_DEVICE_RES:
-			sms_debug("MSG_SMS_INIT_DEVICE_RES");
 			complete(&coredev->init_device_done);
 			break;
 		case MSG_SW_RELOAD_START_RES:
-			sms_debug("MSG_SW_RELOAD_START_RES");
 			complete(&coredev->reload_start_done);
 			break;
+		case MSG_SMS_DATA_VALIDITY_RES:
+		{
+			struct sms_msg_data *validity = (struct sms_msg_data *) phdr;
+
+			sms_err("MSG_SMS_DATA_VALIDITY_RES, checksum = 0x%x",
+				validity->msg_data[0]);
+			complete(&coredev->data_validity_done);
+			break;
+		}
 		case MSG_SMS_DATA_DOWNLOAD_RES:
 			complete(&coredev->data_download_done);
 			break;
 		case MSG_SW_RELOAD_EXEC_RES:
-			sms_debug("MSG_SW_RELOAD_EXEC_RES");
 			break;
 		case MSG_SMS_SWDOWNLOAD_TRIGGER_RES:
-			sms_debug("MSG_SMS_SWDOWNLOAD_TRIGGER_RES");
 			complete(&coredev->trigger_done);
 			break;
 		case MSG_SMS_SLEEP_RESUME_COMP_IND:
 			complete(&coredev->resume_done);
 			break;
 		case MSG_SMS_GPIO_CONFIG_EX_RES:
-			sms_debug("MSG_SMS_GPIO_CONFIG_EX_RES");
 			complete(&coredev->gpio_configuration_done);
 			break;
 		case MSG_SMS_GPIO_SET_LEVEL_RES:
-			sms_debug("MSG_SMS_GPIO_SET_LEVEL_RES");
 			complete(&coredev->gpio_set_level_done);
 			break;
 		case MSG_SMS_GPIO_GET_LEVEL_RES:
 		{
 			u32 *msgdata = (u32 *) phdr;
 			coredev->gpio_get_res = msgdata[1];
-			sms_debug("MSG_SMS_GPIO_GET_LEVEL_RES gpio level %d",
+			sms_debug("gpio level %d",
 					coredev->gpio_get_res);
 			complete(&coredev->gpio_get_level_done);
 			break;
@@ -1070,12 +1599,24 @@ void smscore_onresponse(struct smscore_device_t *coredev,
 			sms_ir_event(coredev,
 				(const char *)
 				((char *)phdr
-				+ sizeof(struct SmsMsgHdr_ST)),
-				(int)phdr->msgLength
-				- sizeof(struct SmsMsgHdr_ST));
+				+ sizeof(struct sms_msg_hdr)),
+				(int)phdr->msg_length
+				- sizeof(struct sms_msg_hdr));
+			break;
+
+		case MSG_SMS_DVBT_BDA_DATA:
+			/*
+			 * It can be received here, if the frontend is
+			 * tuned into a valid channel and the proper firmware
+			 * is loaded. That happens when the module got removed
+			 * and re-inserted, without powering the device off
+			 */
 			break;
 
 		default:
+			sms_debug("message %s(%d) not handled.",
+				  smscore_translate_msg(phdr->msg_type),
+				  phdr->msg_type);
 			break;
 		}
 		smscore_putbuffer(coredev, cb);
@@ -1257,7 +1798,7 @@ int smsclient_sendrequest(struct smscore_client_t *client,
 			  void *buffer, size_t size)
 {
 	struct smscore_device_t *coredev;
-	struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *) buffer;
+	struct sms_msg_hdr *phdr = (struct sms_msg_hdr *) buffer;
 	int rc;
 
 	if (client == NULL) {
@@ -1274,7 +1815,7 @@ int smsclient_sendrequest(struct smscore_client_t *client,
 	}
 
 	rc = smscore_validate_client(client->coredev, client, 0,
-				     phdr->msgSrcId);
+				     phdr->msg_src_id);
 	if (rc < 0)
 		return rc;
 
@@ -1288,16 +1829,16 @@ int smscore_configure_gpio(struct smscore_device_t *coredev, u32 pin,
 			   struct smscore_config_gpio *pinconfig)
 {
 	struct {
-		struct SmsMsgHdr_ST hdr;
+		struct sms_msg_hdr hdr;
 		u32 data[6];
 	} msg;
 
 	if (coredev->device_flags & SMS_DEVICE_FAMILY2) {
-		msg.hdr.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
-		msg.hdr.msgDstId = HIF_TASK;
-		msg.hdr.msgFlags = 0;
-		msg.hdr.msgType  = MSG_SMS_GPIO_CONFIG_EX_REQ;
-		msg.hdr.msgLength = sizeof(msg);
+		msg.hdr.msg_src_id = DVBT_BDA_CONTROL_MSG_ID;
+		msg.hdr.msg_dst_id = HIF_TASK;
+		msg.hdr.msg_flags = 0;
+		msg.hdr.msg_type  = MSG_SMS_GPIO_CONFIG_EX_REQ;
+		msg.hdr.msg_length = sizeof(msg);
 
 		msg.data[0] = pin;
 		msg.data[1] = pinconfig->pullupdown;
@@ -1306,16 +1847,16 @@ int smscore_configure_gpio(struct smscore_device_t *coredev, u32 pin,
 		msg.data[2] = pinconfig->outputslewrate == 0 ? 3 : 0;
 
 		switch (pinconfig->outputdriving) {
-		case SMS_GPIO_OUTPUTDRIVING_16mA:
+		case SMS_GPIO_OUTPUTDRIVING_S_16mA:
 			msg.data[3] = 7; /* Nova - 16mA */
 			break;
-		case SMS_GPIO_OUTPUTDRIVING_12mA:
+		case SMS_GPIO_OUTPUTDRIVING_S_12mA:
 			msg.data[3] = 5; /* Nova - 11mA */
 			break;
-		case SMS_GPIO_OUTPUTDRIVING_8mA:
+		case SMS_GPIO_OUTPUTDRIVING_S_8mA:
 			msg.data[3] = 3; /* Nova - 7mA */
 			break;
-		case SMS_GPIO_OUTPUTDRIVING_4mA:
+		case SMS_GPIO_OUTPUTDRIVING_S_4mA:
 		default:
 			msg.data[3] = 2; /* Nova - 4mA */
 			break;
@@ -1333,18 +1874,18 @@ int smscore_configure_gpio(struct smscore_device_t *coredev, u32 pin,
 int smscore_set_gpio(struct smscore_device_t *coredev, u32 pin, int level)
 {
 	struct {
-		struct SmsMsgHdr_ST hdr;
+		struct sms_msg_hdr hdr;
 		u32 data[3];
 	} msg;
 
 	if (pin > MAX_GPIO_PIN_NUMBER)
 		return -EINVAL;
 
-	msg.hdr.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
-	msg.hdr.msgDstId = HIF_TASK;
-	msg.hdr.msgFlags = 0;
-	msg.hdr.msgType  = MSG_SMS_GPIO_SET_LEVEL_REQ;
-	msg.hdr.msgLength = sizeof(msg);
+	msg.hdr.msg_src_id = DVBT_BDA_CONTROL_MSG_ID;
+	msg.hdr.msg_dst_id = HIF_TASK;
+	msg.hdr.msg_flags = 0;
+	msg.hdr.msg_type  = MSG_SMS_GPIO_SET_LEVEL_REQ;
+	msg.hdr.msg_length = sizeof(msg);
 
 	msg.data[0] = pin;
 	msg.data[1] = level ? 1 : 0;
@@ -1355,122 +1896,121 @@ int smscore_set_gpio(struct smscore_device_t *coredev, u32 pin, int level)
 }
 
 /* new GPIO management implementation */
-static int GetGpioPinParams(u32 PinNum, u32 *pTranslatedPinNum,
-		u32 *pGroupNum, u32 *pGroupCfg) {
-
-	*pGroupCfg = 1;
-
-	if (PinNum <= 1)	{
-		*pTranslatedPinNum = 0;
-		*pGroupNum = 9;
-		*pGroupCfg = 2;
-	} else if (PinNum >= 2 && PinNum <= 6) {
-		*pTranslatedPinNum = 2;
-		*pGroupNum = 0;
-		*pGroupCfg = 2;
-	} else if (PinNum >= 7 && PinNum <= 11) {
-		*pTranslatedPinNum = 7;
-		*pGroupNum = 1;
-	} else if (PinNum >= 12 && PinNum <= 15) {
-		*pTranslatedPinNum = 12;
-		*pGroupNum = 2;
-		*pGroupCfg = 3;
-	} else if (PinNum == 16) {
-		*pTranslatedPinNum = 16;
-		*pGroupNum = 23;
-	} else if (PinNum >= 17 && PinNum <= 24) {
-		*pTranslatedPinNum = 17;
-		*pGroupNum = 3;
-	} else if (PinNum == 25) {
-		*pTranslatedPinNum = 25;
-		*pGroupNum = 6;
-	} else if (PinNum >= 26 && PinNum <= 28) {
-		*pTranslatedPinNum = 26;
-		*pGroupNum = 4;
-	} else if (PinNum == 29) {
-		*pTranslatedPinNum = 29;
-		*pGroupNum = 5;
-		*pGroupCfg = 2;
-	} else if (PinNum == 30) {
-		*pTranslatedPinNum = 30;
-		*pGroupNum = 8;
-	} else if (PinNum == 31) {
-		*pTranslatedPinNum = 31;
-		*pGroupNum = 17;
+static int get_gpio_pin_params(u32 pin_num, u32 *p_translatedpin_num,
+		u32 *p_group_num, u32 *p_group_cfg) {
+
+	*p_group_cfg = 1;
+
+	if (pin_num <= 1)	{
+		*p_translatedpin_num = 0;
+		*p_group_num = 9;
+		*p_group_cfg = 2;
+	} else if (pin_num >= 2 && pin_num <= 6) {
+		*p_translatedpin_num = 2;
+		*p_group_num = 0;
+		*p_group_cfg = 2;
+	} else if (pin_num >= 7 && pin_num <= 11) {
+		*p_translatedpin_num = 7;
+		*p_group_num = 1;
+	} else if (pin_num >= 12 && pin_num <= 15) {
+		*p_translatedpin_num = 12;
+		*p_group_num = 2;
+		*p_group_cfg = 3;
+	} else if (pin_num == 16) {
+		*p_translatedpin_num = 16;
+		*p_group_num = 23;
+	} else if (pin_num >= 17 && pin_num <= 24) {
+		*p_translatedpin_num = 17;
+		*p_group_num = 3;
+	} else if (pin_num == 25) {
+		*p_translatedpin_num = 25;
+		*p_group_num = 6;
+	} else if (pin_num >= 26 && pin_num <= 28) {
+		*p_translatedpin_num = 26;
+		*p_group_num = 4;
+	} else if (pin_num == 29) {
+		*p_translatedpin_num = 29;
+		*p_group_num = 5;
+		*p_group_cfg = 2;
+	} else if (pin_num == 30) {
+		*p_translatedpin_num = 30;
+		*p_group_num = 8;
+	} else if (pin_num == 31) {
+		*p_translatedpin_num = 31;
+		*p_group_num = 17;
 	} else
 		return -1;
 
-	*pGroupCfg <<= 24;
+	*p_group_cfg <<= 24;
 
 	return 0;
 }
 
-int smscore_gpio_configure(struct smscore_device_t *coredev, u8 PinNum,
-		struct smscore_gpio_config *pGpioConfig) {
+int smscore_gpio_configure(struct smscore_device_t *coredev, u8 pin_num,
+		struct smscore_config_gpio *p_gpio_config) {
 
-	u32 totalLen;
-	u32 TranslatedPinNum = 0;
-	u32 GroupNum = 0;
-	u32 ElectricChar;
-	u32 groupCfg;
+	u32 total_len;
+	u32 translatedpin_num = 0;
+	u32 group_num = 0;
+	u32 electric_char;
+	u32 group_cfg;
 	void *buffer;
 	int rc;
 
-	struct SetGpioMsg {
-		struct SmsMsgHdr_ST xMsgHeader;
-		u32 msgData[6];
-	} *pMsg;
+	struct set_gpio_msg {
+		struct sms_msg_hdr x_msg_header;
+		u32 msg_data[6];
+	} *p_msg;
 
 
-	if (PinNum > MAX_GPIO_PIN_NUMBER)
+	if (pin_num > MAX_GPIO_PIN_NUMBER)
 		return -EINVAL;
 
-	if (pGpioConfig == NULL)
+	if (p_gpio_config == NULL)
 		return -EINVAL;
 
-	totalLen = sizeof(struct SmsMsgHdr_ST) + (sizeof(u32) * 6);
+	total_len = sizeof(struct sms_msg_hdr) + (sizeof(u32) * 6);
 
-	buffer = kmalloc(totalLen + SMS_DMA_ALIGNMENT,
+	buffer = kmalloc(total_len + SMS_DMA_ALIGNMENT,
 			GFP_KERNEL | GFP_DMA);
 	if (!buffer)
 		return -ENOMEM;
 
-	pMsg = (struct SetGpioMsg *) SMS_ALIGN_ADDRESS(buffer);
+	p_msg = (struct set_gpio_msg *) SMS_ALIGN_ADDRESS(buffer);
 
-	pMsg->xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
-	pMsg->xMsgHeader.msgDstId = HIF_TASK;
-	pMsg->xMsgHeader.msgFlags = 0;
-	pMsg->xMsgHeader.msgLength = (u16) totalLen;
-	pMsg->msgData[0] = PinNum;
+	p_msg->x_msg_header.msg_src_id = DVBT_BDA_CONTROL_MSG_ID;
+	p_msg->x_msg_header.msg_dst_id = HIF_TASK;
+	p_msg->x_msg_header.msg_flags = 0;
+	p_msg->x_msg_header.msg_length = (u16) total_len;
+	p_msg->msg_data[0] = pin_num;
 
 	if (!(coredev->device_flags & SMS_DEVICE_FAMILY2)) {
-		pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_CONFIG_REQ;
-		if (GetGpioPinParams(PinNum, &TranslatedPinNum, &GroupNum,
-				&groupCfg) != 0) {
+		p_msg->x_msg_header.msg_type = MSG_SMS_GPIO_CONFIG_REQ;
+		if (get_gpio_pin_params(pin_num, &translatedpin_num, &group_num,
+				&group_cfg) != 0) {
 			rc = -EINVAL;
 			goto free;
 		}
 
-		pMsg->msgData[1] = TranslatedPinNum;
-		pMsg->msgData[2] = GroupNum;
-		ElectricChar = (pGpioConfig->PullUpDown)
-				| (pGpioConfig->InputCharacteristics << 2)
-				| (pGpioConfig->OutputSlewRate << 3)
-				| (pGpioConfig->OutputDriving << 4);
-		pMsg->msgData[3] = ElectricChar;
-		pMsg->msgData[4] = pGpioConfig->Direction;
-		pMsg->msgData[5] = groupCfg;
+		p_msg->msg_data[1] = translatedpin_num;
+		p_msg->msg_data[2] = group_num;
+		electric_char = (p_gpio_config->pullupdown)
+				| (p_gpio_config->inputcharacteristics << 2)
+				| (p_gpio_config->outputslewrate << 3)
+				| (p_gpio_config->outputdriving << 4);
+		p_msg->msg_data[3] = electric_char;
+		p_msg->msg_data[4] = p_gpio_config->direction;
+		p_msg->msg_data[5] = group_cfg;
 	} else {
-		pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_CONFIG_EX_REQ;
-		pMsg->msgData[1] = pGpioConfig->PullUpDown;
-		pMsg->msgData[2] = pGpioConfig->OutputSlewRate;
-		pMsg->msgData[3] = pGpioConfig->OutputDriving;
-		pMsg->msgData[4] = pGpioConfig->Direction;
-		pMsg->msgData[5] = 0;
+		p_msg->x_msg_header.msg_type = MSG_SMS_GPIO_CONFIG_EX_REQ;
+		p_msg->msg_data[1] = p_gpio_config->pullupdown;
+		p_msg->msg_data[2] = p_gpio_config->outputslewrate;
+		p_msg->msg_data[3] = p_gpio_config->outputdriving;
+		p_msg->msg_data[4] = p_gpio_config->direction;
+		p_msg->msg_data[5] = 0;
 	}
 
-	smsendian_handle_tx_message((struct SmsMsgHdr_ST *)pMsg);
-	rc = smscore_sendrequest_and_wait(coredev, pMsg, totalLen,
+	rc = smscore_sendrequest_and_wait(coredev, p_msg, total_len,
 			&coredev->gpio_configuration_done);
 
 	if (rc != 0) {
@@ -1485,42 +2025,41 @@ free:
 	return rc;
 }
 
-int smscore_gpio_set_level(struct smscore_device_t *coredev, u8 PinNum,
-		u8 NewLevel) {
+int smscore_gpio_set_level(struct smscore_device_t *coredev, u8 pin_num,
+		u8 new_level) {
 
-	u32 totalLen;
+	u32 total_len;
 	int rc;
 	void *buffer;
 
-	struct SetGpioMsg {
-		struct SmsMsgHdr_ST xMsgHeader;
-		u32 msgData[3]; /* keep it 3 ! */
-	} *pMsg;
+	struct set_gpio_msg {
+		struct sms_msg_hdr x_msg_header;
+		u32 msg_data[3]; /* keep it 3 ! */
+	} *p_msg;
 
-	if ((NewLevel > 1) || (PinNum > MAX_GPIO_PIN_NUMBER))
+	if ((new_level > 1) || (pin_num > MAX_GPIO_PIN_NUMBER))
 		return -EINVAL;
 
-	totalLen = sizeof(struct SmsMsgHdr_ST) +
+	total_len = sizeof(struct sms_msg_hdr) +
 			(3 * sizeof(u32)); /* keep it 3 ! */
 
-	buffer = kmalloc(totalLen + SMS_DMA_ALIGNMENT,
+	buffer = kmalloc(total_len + SMS_DMA_ALIGNMENT,
 			GFP_KERNEL | GFP_DMA);
 	if (!buffer)
 		return -ENOMEM;
 
-	pMsg = (struct SetGpioMsg *) SMS_ALIGN_ADDRESS(buffer);
+	p_msg = (struct set_gpio_msg *) SMS_ALIGN_ADDRESS(buffer);
 
-	pMsg->xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
-	pMsg->xMsgHeader.msgDstId = HIF_TASK;
-	pMsg->xMsgHeader.msgFlags = 0;
-	pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_SET_LEVEL_REQ;
-	pMsg->xMsgHeader.msgLength = (u16) totalLen;
-	pMsg->msgData[0] = PinNum;
-	pMsg->msgData[1] = NewLevel;
+	p_msg->x_msg_header.msg_src_id = DVBT_BDA_CONTROL_MSG_ID;
+	p_msg->x_msg_header.msg_dst_id = HIF_TASK;
+	p_msg->x_msg_header.msg_flags = 0;
+	p_msg->x_msg_header.msg_type = MSG_SMS_GPIO_SET_LEVEL_REQ;
+	p_msg->x_msg_header.msg_length = (u16) total_len;
+	p_msg->msg_data[0] = pin_num;
+	p_msg->msg_data[1] = new_level;
 
 	/* Send message to SMS */
-	smsendian_handle_tx_message((struct SmsMsgHdr_ST *)pMsg);
-	rc = smscore_sendrequest_and_wait(coredev, pMsg, totalLen,
+	rc = smscore_sendrequest_and_wait(coredev, p_msg, total_len,
 			&coredev->gpio_set_level_done);
 
 	if (rc != 0) {
@@ -1534,42 +2073,41 @@ int smscore_gpio_set_level(struct smscore_device_t *coredev, u8 PinNum,
 	return rc;
 }
 
-int smscore_gpio_get_level(struct smscore_device_t *coredev, u8 PinNum,
+int smscore_gpio_get_level(struct smscore_device_t *coredev, u8 pin_num,
 		u8 *level) {
 
-	u32 totalLen;
+	u32 total_len;
 	int rc;
 	void *buffer;
 
-	struct SetGpioMsg {
-		struct SmsMsgHdr_ST xMsgHeader;
-		u32 msgData[2];
-	} *pMsg;
+	struct set_gpio_msg {
+		struct sms_msg_hdr x_msg_header;
+		u32 msg_data[2];
+	} *p_msg;
 
 
-	if (PinNum > MAX_GPIO_PIN_NUMBER)
+	if (pin_num > MAX_GPIO_PIN_NUMBER)
 		return -EINVAL;
 
-	totalLen = sizeof(struct SmsMsgHdr_ST) + (2 * sizeof(u32));
+	total_len = sizeof(struct sms_msg_hdr) + (2 * sizeof(u32));
 
-	buffer = kmalloc(totalLen + SMS_DMA_ALIGNMENT,
+	buffer = kmalloc(total_len + SMS_DMA_ALIGNMENT,
 			GFP_KERNEL | GFP_DMA);
 	if (!buffer)
 		return -ENOMEM;
 
-	pMsg = (struct SetGpioMsg *) SMS_ALIGN_ADDRESS(buffer);
+	p_msg = (struct set_gpio_msg *) SMS_ALIGN_ADDRESS(buffer);
 
-	pMsg->xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
-	pMsg->xMsgHeader.msgDstId = HIF_TASK;
-	pMsg->xMsgHeader.msgFlags = 0;
-	pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_GET_LEVEL_REQ;
-	pMsg->xMsgHeader.msgLength = (u16) totalLen;
-	pMsg->msgData[0] = PinNum;
-	pMsg->msgData[1] = 0;
+	p_msg->x_msg_header.msg_src_id = DVBT_BDA_CONTROL_MSG_ID;
+	p_msg->x_msg_header.msg_dst_id = HIF_TASK;
+	p_msg->x_msg_header.msg_flags = 0;
+	p_msg->x_msg_header.msg_type = MSG_SMS_GPIO_GET_LEVEL_REQ;
+	p_msg->x_msg_header.msg_length = (u16) total_len;
+	p_msg->msg_data[0] = pin_num;
+	p_msg->msg_data[1] = 0;
 
 	/* Send message to SMS */
-	smsendian_handle_tx_message((struct SmsMsgHdr_ST *)pMsg);
-	rc = smscore_sendrequest_and_wait(coredev, pMsg, totalLen,
+	rc = smscore_sendrequest_and_wait(coredev, p_msg, total_len,
 			&coredev->gpio_get_level_done);
 
 	if (rc != 0) {
@@ -1635,3 +2173,27 @@ module_exit(smscore_module_exit);
 MODULE_DESCRIPTION("Siano MDTV Core module");
 MODULE_AUTHOR("Siano Mobile Silicon, Inc. (uris@siano-ms.com)");
 MODULE_LICENSE("GPL");
+
+/* This should match what's defined at smscoreapi.h */
+MODULE_FIRMWARE(SMS_FW_ATSC_DENVER);
+MODULE_FIRMWARE(SMS_FW_CMMB_MING_APP);
+MODULE_FIRMWARE(SMS_FW_CMMB_VEGA_12MHZ);
+MODULE_FIRMWARE(SMS_FW_CMMB_VENICE_12MHZ);
+MODULE_FIRMWARE(SMS_FW_DVBH_RIO);
+MODULE_FIRMWARE(SMS_FW_DVB_NOVA_12MHZ_B0);
+MODULE_FIRMWARE(SMS_FW_DVB_NOVA_12MHZ);
+MODULE_FIRMWARE(SMS_FW_DVB_RIO);
+MODULE_FIRMWARE(SMS_FW_FM_RADIO);
+MODULE_FIRMWARE(SMS_FW_FM_RADIO_RIO);
+MODULE_FIRMWARE(SMS_FW_DVBT_HCW_55XXX);
+MODULE_FIRMWARE(SMS_FW_ISDBT_HCW_55XXX);
+MODULE_FIRMWARE(SMS_FW_ISDBT_NOVA_12MHZ_B0);
+MODULE_FIRMWARE(SMS_FW_ISDBT_NOVA_12MHZ);
+MODULE_FIRMWARE(SMS_FW_ISDBT_PELE);
+MODULE_FIRMWARE(SMS_FW_ISDBT_RIO);
+MODULE_FIRMWARE(SMS_FW_DVBT_NOVA_A);
+MODULE_FIRMWARE(SMS_FW_DVBT_NOVA_B);
+MODULE_FIRMWARE(SMS_FW_DVBT_STELLAR);
+MODULE_FIRMWARE(SMS_FW_TDMB_DENVER);
+MODULE_FIRMWARE(SMS_FW_TDMB_NOVA_12MHZ_B0);
+MODULE_FIRMWARE(SMS_FW_TDMB_NOVA_12MHZ);
diff --git a/drivers/media/common/siano/smscoreapi.h b/drivers/media/common/siano/smscoreapi.h
index c592ae0..d0799e3 100644
--- a/drivers/media/common/siano/smscoreapi.h
+++ b/drivers/media/common/siano/smscoreapi.h
@@ -40,9 +40,33 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #define kmutex_trylock(_p_) mutex_trylock(_p_)
 #define kmutex_unlock(_p_) mutex_unlock(_p_)
 
-#ifndef min
-#define min(a, b) (((a) < (b)) ? (a) : (b))
-#endif
+/*
+ * Define the firmware names used by the driver.
+ * Those should match what's used at smscoreapi.c and sms-cards.c
+ * including the MODULE_FIRMWARE() macros at the end of smscoreapi.c
+ */
+#define SMS_FW_ATSC_DENVER         "atsc_denver.inp"
+#define SMS_FW_CMMB_MING_APP       "cmmb_ming_app.inp"
+#define SMS_FW_CMMB_VEGA_12MHZ     "cmmb_vega_12mhz.inp"
+#define SMS_FW_CMMB_VENICE_12MHZ   "cmmb_venice_12mhz.inp"
+#define SMS_FW_DVBH_RIO            "dvbh_rio.inp"
+#define SMS_FW_DVB_NOVA_12MHZ_B0   "dvb_nova_12mhz_b0.inp"
+#define SMS_FW_DVB_NOVA_12MHZ      "dvb_nova_12mhz.inp"
+#define SMS_FW_DVB_RIO             "dvb_rio.inp"
+#define SMS_FW_FM_RADIO            "fm_radio.inp"
+#define SMS_FW_FM_RADIO_RIO        "fm_radio_rio.inp"
+#define SMS_FW_DVBT_HCW_55XXX      "sms1xxx-hcw-55xxx-dvbt-02.fw"
+#define SMS_FW_ISDBT_HCW_55XXX     "sms1xxx-hcw-55xxx-isdbt-02.fw"
+#define SMS_FW_ISDBT_NOVA_12MHZ_B0 "isdbt_nova_12mhz_b0.inp"
+#define SMS_FW_ISDBT_NOVA_12MHZ    "isdbt_nova_12mhz.inp"
+#define SMS_FW_ISDBT_PELE          "isdbt_pele.inp"
+#define SMS_FW_ISDBT_RIO           "isdbt_rio.inp"
+#define SMS_FW_DVBT_NOVA_A         "sms1xxx-nova-a-dvbt-01.fw"
+#define SMS_FW_DVBT_NOVA_B         "sms1xxx-nova-b-dvbt-01.fw"
+#define SMS_FW_DVBT_STELLAR        "sms1xxx-stellar-dvbt-01.fw"
+#define SMS_FW_TDMB_DENVER         "tdmb_denver.inp"
+#define SMS_FW_TDMB_NOVA_12MHZ_B0  "tdmb_nova_12mhz_b0.inp"
+#define SMS_FW_TDMB_NOVA_12MHZ     "tdmb_nova_12mhz.inp"
 
 #define SMS_PROTOCOL_MAX_RAOUNDTRIP_MS			(10000)
 #define SMS_ALLOC_ALIGNMENT				128
@@ -50,18 +74,31 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #define SMS_ALIGN_ADDRESS(addr) \
 	((((uintptr_t)(addr)) + (SMS_DMA_ALIGNMENT-1)) & ~(SMS_DMA_ALIGNMENT-1))
 
+#define SMS_DEVICE_FAMILY1				0
 #define SMS_DEVICE_FAMILY2				1
 #define SMS_ROM_NO_RESPONSE				2
 #define SMS_DEVICE_NOT_READY				0x8000000
 
 enum sms_device_type_st {
+	SMS_UNKNOWN_TYPE = -1,
 	SMS_STELLAR = 0,
 	SMS_NOVA_A0,
 	SMS_NOVA_B0,
 	SMS_VEGA,
+	SMS_VENICE,
+	SMS_MING,
+	SMS_PELE,
+	SMS_RIO,
+	SMS_DENVER_1530,
+	SMS_DENVER_2160,
 	SMS_NUM_OF_DEVICE_TYPES
 };
 
+enum sms_power_mode_st {
+	SMS_POWER_MODE_ACTIVE,
+	SMS_POWER_MODE_SUSPENDED
+};
+
 struct smscore_device_t;
 struct smscore_client_t;
 struct smscore_buffer_t;
@@ -149,6 +186,7 @@ struct smscore_device_t {
 
 	/* host <--> device messages */
 	struct completion version_ex_done, data_download_done, trigger_done;
+	struct completion data_validity_done, device_ready_done;
 	struct completion init_device_done, reload_start_done, resume_done;
 	struct completion gpio_configuration_done, gpio_set_level_done;
 	struct completion gpio_get_level_done, ir_init_done;
@@ -165,10 +203,17 @@ struct smscore_device_t {
 	/* Firmware */
 	u8 *fw_buf;
 	u32 fw_buf_size;
+	u16 fw_version;
 
 	/* Infrared (IR) */
 	struct ir_t ir;
 
+	/*
+	 * Identify if device is USB or not.
+	 * Used by smsdvb-sysfs to know the root node for debugfs
+	 */
+	bool is_usb_device;
+
 	int led_state;
 };
 
@@ -176,81 +221,363 @@ struct smscore_device_t {
 #define SMS_ANTENNA_GPIO_0					1
 #define SMS_ANTENNA_GPIO_1					0
 
-#define BW_8_MHZ							0
-#define BW_7_MHZ							1
-#define BW_6_MHZ							2
-#define BW_5_MHZ							3
-#define BW_ISDBT_1SEG						4
-#define BW_ISDBT_3SEG						5
+enum sms_bandwidth_mode {
+	BW_8_MHZ = 0,
+	BW_7_MHZ = 1,
+	BW_6_MHZ = 2,
+	BW_5_MHZ = 3,
+	BW_ISDBT_1SEG = 4,
+	BW_ISDBT_3SEG = 5,
+	BW_2_MHZ = 6,
+	BW_FM_RADIO = 7,
+	BW_ISDBT_13SEG = 8,
+	BW_1_5_MHZ = 15,
+	BW_UNKNOWN = 0xffff
+};
+
 
 #define MSG_HDR_FLAG_SPLIT_MSG				4
 
 #define MAX_GPIO_PIN_NUMBER					31
 
 #define HIF_TASK							11
+#define HIF_TASK_SLAVE					22
+#define HIF_TASK_SLAVE2					33
+#define HIF_TASK_SLAVE3					44
 #define SMS_HOST_LIB						150
 #define DVBT_BDA_CONTROL_MSG_ID				201
 
 #define SMS_MAX_PAYLOAD_SIZE				240
 #define SMS_TUNE_TIMEOUT					500
 
-#define MSG_SMS_GPIO_CONFIG_REQ				507
-#define MSG_SMS_GPIO_CONFIG_RES				508
-#define MSG_SMS_GPIO_SET_LEVEL_REQ			509
-#define MSG_SMS_GPIO_SET_LEVEL_RES			510
-#define MSG_SMS_GPIO_GET_LEVEL_REQ			511
-#define MSG_SMS_GPIO_GET_LEVEL_RES			512
-#define MSG_SMS_RF_TUNE_REQ					561
-#define MSG_SMS_RF_TUNE_RES					562
-#define MSG_SMS_INIT_DEVICE_REQ				578
-#define MSG_SMS_INIT_DEVICE_RES				579
-#define MSG_SMS_ADD_PID_FILTER_REQ			601
-#define MSG_SMS_ADD_PID_FILTER_RES			602
-#define MSG_SMS_REMOVE_PID_FILTER_REQ			603
-#define MSG_SMS_REMOVE_PID_FILTER_RES			604
-#define MSG_SMS_DAB_CHANNEL				607
-#define MSG_SMS_GET_PID_FILTER_LIST_REQ			608
-#define MSG_SMS_GET_PID_FILTER_LIST_RES			609
-#define MSG_SMS_GET_STATISTICS_RES			616
-#define MSG_SMS_GET_STATISTICS_REQ			615
-#define MSG_SMS_HO_PER_SLICES_IND			630
-#define MSG_SMS_SET_ANTENNA_CONFIG_REQ			651
-#define MSG_SMS_SET_ANTENNA_CONFIG_RES			652
-#define MSG_SMS_SLEEP_RESUME_COMP_IND			655
-#define MSG_SMS_DATA_DOWNLOAD_REQ			660
-#define MSG_SMS_DATA_DOWNLOAD_RES			661
-#define MSG_SMS_SWDOWNLOAD_TRIGGER_REQ		664
-#define MSG_SMS_SWDOWNLOAD_TRIGGER_RES		665
-#define MSG_SMS_SWDOWNLOAD_BACKDOOR_REQ		666
-#define MSG_SMS_SWDOWNLOAD_BACKDOOR_RES		667
-#define MSG_SMS_GET_VERSION_EX_REQ			668
-#define MSG_SMS_GET_VERSION_EX_RES			669
-#define MSG_SMS_SET_CLOCK_OUTPUT_REQ		670
-#define MSG_SMS_I2C_SET_FREQ_REQ			685
-#define MSG_SMS_GENERIC_I2C_REQ				687
-#define MSG_SMS_GENERIC_I2C_RES				688
-#define MSG_SMS_DVBT_BDA_DATA				693
-#define MSG_SW_RELOAD_REQ					697
-#define MSG_SMS_DATA_MSG					699
-#define MSG_SW_RELOAD_START_REQ				702
-#define MSG_SW_RELOAD_START_RES				703
-#define MSG_SW_RELOAD_EXEC_REQ				704
-#define MSG_SW_RELOAD_EXEC_RES				705
-#define MSG_SMS_SPI_INT_LINE_SET_REQ		710
-#define MSG_SMS_GPIO_CONFIG_EX_REQ			712
-#define MSG_SMS_GPIO_CONFIG_EX_RES			713
-#define MSG_SMS_ISDBT_TUNE_REQ				776
-#define MSG_SMS_ISDBT_TUNE_RES				777
-#define MSG_SMS_TRANSMISSION_IND			782
-#define MSG_SMS_START_IR_REQ				800
-#define MSG_SMS_START_IR_RES				801
-#define MSG_SMS_IR_SAMPLES_IND				802
-#define MSG_SMS_SIGNAL_DETECTED_IND			827
-#define MSG_SMS_NO_SIGNAL_IND				828
+enum msg_types {
+	MSG_TYPE_BASE_VAL = 500,
+	MSG_SMS_GET_VERSION_REQ = 503,
+	MSG_SMS_GET_VERSION_RES = 504,
+	MSG_SMS_MULTI_BRIDGE_CFG = 505,
+	MSG_SMS_GPIO_CONFIG_REQ = 507,
+	MSG_SMS_GPIO_CONFIG_RES = 508,
+	MSG_SMS_GPIO_SET_LEVEL_REQ = 509,
+	MSG_SMS_GPIO_SET_LEVEL_RES = 510,
+	MSG_SMS_GPIO_GET_LEVEL_REQ = 511,
+	MSG_SMS_GPIO_GET_LEVEL_RES = 512,
+	MSG_SMS_EEPROM_BURN_IND = 513,
+	MSG_SMS_LOG_ENABLE_CHANGE_REQ = 514,
+	MSG_SMS_LOG_ENABLE_CHANGE_RES = 515,
+	MSG_SMS_SET_MAX_TX_MSG_LEN_REQ = 516,
+	MSG_SMS_SET_MAX_TX_MSG_LEN_RES = 517,
+	MSG_SMS_SPI_HALFDUPLEX_TOKEN_HOST_TO_DEVICE = 518,
+	MSG_SMS_SPI_HALFDUPLEX_TOKEN_DEVICE_TO_HOST = 519,
+	MSG_SMS_BACKGROUND_SCAN_FLAG_CHANGE_REQ = 520,
+	MSG_SMS_BACKGROUND_SCAN_FLAG_CHANGE_RES = 521,
+	MSG_SMS_BACKGROUND_SCAN_SIGNAL_DETECTED_IND = 522,
+	MSG_SMS_BACKGROUND_SCAN_NO_SIGNAL_IND = 523,
+	MSG_SMS_CONFIGURE_RF_SWITCH_REQ = 524,
+	MSG_SMS_CONFIGURE_RF_SWITCH_RES = 525,
+	MSG_SMS_MRC_PATH_DISCONNECT_REQ = 526,
+	MSG_SMS_MRC_PATH_DISCONNECT_RES = 527,
+	MSG_SMS_RECEIVE_1SEG_THROUGH_FULLSEG_REQ = 528,
+	MSG_SMS_RECEIVE_1SEG_THROUGH_FULLSEG_RES = 529,
+	MSG_SMS_RECEIVE_VHF_VIA_VHF_INPUT_REQ = 530,
+	MSG_SMS_RECEIVE_VHF_VIA_VHF_INPUT_RES = 531,
+	MSG_WR_REG_RFT_REQ = 533,
+	MSG_WR_REG_RFT_RES = 534,
+	MSG_RD_REG_RFT_REQ = 535,
+	MSG_RD_REG_RFT_RES = 536,
+	MSG_RD_REG_ALL_RFT_REQ = 537,
+	MSG_RD_REG_ALL_RFT_RES = 538,
+	MSG_HELP_INT = 539,
+	MSG_RUN_SCRIPT_INT = 540,
+	MSG_SMS_EWS_INBAND_REQ = 541,
+	MSG_SMS_EWS_INBAND_RES = 542,
+	MSG_SMS_RFS_SELECT_REQ = 543,
+	MSG_SMS_RFS_SELECT_RES = 544,
+	MSG_SMS_MB_GET_VER_REQ = 545,
+	MSG_SMS_MB_GET_VER_RES = 546,
+	MSG_SMS_MB_WRITE_CFGFILE_REQ = 547,
+	MSG_SMS_MB_WRITE_CFGFILE_RES = 548,
+	MSG_SMS_MB_READ_CFGFILE_REQ = 549,
+	MSG_SMS_MB_READ_CFGFILE_RES = 550,
+	MSG_SMS_RD_MEM_REQ = 552,
+	MSG_SMS_RD_MEM_RES = 553,
+	MSG_SMS_WR_MEM_REQ = 554,
+	MSG_SMS_WR_MEM_RES = 555,
+	MSG_SMS_UPDATE_MEM_REQ = 556,
+	MSG_SMS_UPDATE_MEM_RES = 557,
+	MSG_SMS_ISDBT_ENABLE_FULL_PARAMS_SET_REQ = 558,
+	MSG_SMS_ISDBT_ENABLE_FULL_PARAMS_SET_RES = 559,
+	MSG_SMS_RF_TUNE_REQ = 561,
+	MSG_SMS_RF_TUNE_RES = 562,
+	MSG_SMS_ISDBT_ENABLE_HIGH_MOBILITY_REQ = 563,
+	MSG_SMS_ISDBT_ENABLE_HIGH_MOBILITY_RES = 564,
+	MSG_SMS_ISDBT_SB_RECEPTION_REQ = 565,
+	MSG_SMS_ISDBT_SB_RECEPTION_RES = 566,
+	MSG_SMS_GENERIC_EPROM_WRITE_REQ = 567,
+	MSG_SMS_GENERIC_EPROM_WRITE_RES = 568,
+	MSG_SMS_GENERIC_EPROM_READ_REQ = 569,
+	MSG_SMS_GENERIC_EPROM_READ_RES = 570,
+	MSG_SMS_EEPROM_WRITE_REQ = 571,
+	MSG_SMS_EEPROM_WRITE_RES = 572,
+	MSG_SMS_CUSTOM_READ_REQ = 574,
+	MSG_SMS_CUSTOM_READ_RES = 575,
+	MSG_SMS_CUSTOM_WRITE_REQ = 576,
+	MSG_SMS_CUSTOM_WRITE_RES = 577,
+	MSG_SMS_INIT_DEVICE_REQ = 578,
+	MSG_SMS_INIT_DEVICE_RES = 579,
+	MSG_SMS_ATSC_SET_ALL_IP_REQ = 580,
+	MSG_SMS_ATSC_SET_ALL_IP_RES = 581,
+	MSG_SMS_ATSC_START_ENSEMBLE_REQ = 582,
+	MSG_SMS_ATSC_START_ENSEMBLE_RES = 583,
+	MSG_SMS_SET_OUTPUT_MODE_REQ = 584,
+	MSG_SMS_SET_OUTPUT_MODE_RES = 585,
+	MSG_SMS_ATSC_IP_FILTER_GET_LIST_REQ = 586,
+	MSG_SMS_ATSC_IP_FILTER_GET_LIST_RES = 587,
+	MSG_SMS_SUB_CHANNEL_START_REQ = 589,
+	MSG_SMS_SUB_CHANNEL_START_RES = 590,
+	MSG_SMS_SUB_CHANNEL_STOP_REQ = 591,
+	MSG_SMS_SUB_CHANNEL_STOP_RES = 592,
+	MSG_SMS_ATSC_IP_FILTER_ADD_REQ = 593,
+	MSG_SMS_ATSC_IP_FILTER_ADD_RES = 594,
+	MSG_SMS_ATSC_IP_FILTER_REMOVE_REQ = 595,
+	MSG_SMS_ATSC_IP_FILTER_REMOVE_RES = 596,
+	MSG_SMS_ATSC_IP_FILTER_REMOVE_ALL_REQ = 597,
+	MSG_SMS_ATSC_IP_FILTER_REMOVE_ALL_RES = 598,
+	MSG_SMS_WAIT_CMD = 599,
+	MSG_SMS_ADD_PID_FILTER_REQ = 601,
+	MSG_SMS_ADD_PID_FILTER_RES = 602,
+	MSG_SMS_REMOVE_PID_FILTER_REQ = 603,
+	MSG_SMS_REMOVE_PID_FILTER_RES = 604,
+	MSG_SMS_FAST_INFORMATION_CHANNEL_REQ = 605,
+	MSG_SMS_FAST_INFORMATION_CHANNEL_RES = 606,
+	MSG_SMS_DAB_CHANNEL = 607,
+	MSG_SMS_GET_PID_FILTER_LIST_REQ = 608,
+	MSG_SMS_GET_PID_FILTER_LIST_RES = 609,
+	MSG_SMS_POWER_DOWN_REQ = 610,
+	MSG_SMS_POWER_DOWN_RES = 611,
+	MSG_SMS_ATSC_SLT_EXIST_IND = 612,
+	MSG_SMS_ATSC_NO_SLT_IND = 613,
+	MSG_SMS_GET_STATISTICS_REQ = 615,
+	MSG_SMS_GET_STATISTICS_RES = 616,
+	MSG_SMS_SEND_DUMP = 617,
+	MSG_SMS_SCAN_START_REQ = 618,
+	MSG_SMS_SCAN_START_RES = 619,
+	MSG_SMS_SCAN_STOP_REQ = 620,
+	MSG_SMS_SCAN_STOP_RES = 621,
+	MSG_SMS_SCAN_PROGRESS_IND = 622,
+	MSG_SMS_SCAN_COMPLETE_IND = 623,
+	MSG_SMS_LOG_ITEM = 624,
+	MSG_SMS_DAB_SUBCHANNEL_RECONFIG_REQ = 628,
+	MSG_SMS_DAB_SUBCHANNEL_RECONFIG_RES = 629,
+	MSG_SMS_HO_PER_SLICES_IND = 630,
+	MSG_SMS_HO_INBAND_POWER_IND = 631,
+	MSG_SMS_MANUAL_DEMOD_REQ = 632,
+	MSG_SMS_HO_TUNE_ON_REQ = 636,
+	MSG_SMS_HO_TUNE_ON_RES = 637,
+	MSG_SMS_HO_TUNE_OFF_REQ = 638,
+	MSG_SMS_HO_TUNE_OFF_RES = 639,
+	MSG_SMS_HO_PEEK_FREQ_REQ = 640,
+	MSG_SMS_HO_PEEK_FREQ_RES = 641,
+	MSG_SMS_HO_PEEK_FREQ_IND = 642,
+	MSG_SMS_MB_ATTEN_SET_REQ = 643,
+	MSG_SMS_MB_ATTEN_SET_RES = 644,
+	MSG_SMS_ENABLE_STAT_IN_I2C_REQ = 649,
+	MSG_SMS_ENABLE_STAT_IN_I2C_RES = 650,
+	MSG_SMS_SET_ANTENNA_CONFIG_REQ = 651,
+	MSG_SMS_SET_ANTENNA_CONFIG_RES = 652,
+	MSG_SMS_GET_STATISTICS_EX_REQ = 653,
+	MSG_SMS_GET_STATISTICS_EX_RES = 654,
+	MSG_SMS_SLEEP_RESUME_COMP_IND = 655,
+	MSG_SMS_SWITCH_HOST_INTERFACE_REQ = 656,
+	MSG_SMS_SWITCH_HOST_INTERFACE_RES = 657,
+	MSG_SMS_DATA_DOWNLOAD_REQ = 660,
+	MSG_SMS_DATA_DOWNLOAD_RES = 661,
+	MSG_SMS_DATA_VALIDITY_REQ = 662,
+	MSG_SMS_DATA_VALIDITY_RES = 663,
+	MSG_SMS_SWDOWNLOAD_TRIGGER_REQ = 664,
+	MSG_SMS_SWDOWNLOAD_TRIGGER_RES = 665,
+	MSG_SMS_SWDOWNLOAD_BACKDOOR_REQ = 666,
+	MSG_SMS_SWDOWNLOAD_BACKDOOR_RES = 667,
+	MSG_SMS_GET_VERSION_EX_REQ = 668,
+	MSG_SMS_GET_VERSION_EX_RES = 669,
+	MSG_SMS_CLOCK_OUTPUT_CONFIG_REQ = 670,
+	MSG_SMS_CLOCK_OUTPUT_CONFIG_RES = 671,
+	MSG_SMS_I2C_SET_FREQ_REQ = 685,
+	MSG_SMS_I2C_SET_FREQ_RES = 686,
+	MSG_SMS_GENERIC_I2C_REQ = 687,
+	MSG_SMS_GENERIC_I2C_RES = 688,
+	MSG_SMS_DVBT_BDA_DATA = 693,
+	MSG_SW_RELOAD_REQ = 697,
+	MSG_SMS_DATA_MSG = 699,
+	MSG_TABLE_UPLOAD_REQ = 700,
+	MSG_TABLE_UPLOAD_RES = 701,
+	MSG_SW_RELOAD_START_REQ = 702,
+	MSG_SW_RELOAD_START_RES = 703,
+	MSG_SW_RELOAD_EXEC_REQ = 704,
+	MSG_SW_RELOAD_EXEC_RES = 705,
+	MSG_SMS_SPI_INT_LINE_SET_REQ = 710,
+	MSG_SMS_SPI_INT_LINE_SET_RES = 711,
+	MSG_SMS_GPIO_CONFIG_EX_REQ = 712,
+	MSG_SMS_GPIO_CONFIG_EX_RES = 713,
+	MSG_SMS_WATCHDOG_ACT_REQ = 716,
+	MSG_SMS_WATCHDOG_ACT_RES = 717,
+	MSG_SMS_LOOPBACK_REQ = 718,
+	MSG_SMS_LOOPBACK_RES = 719,
+	MSG_SMS_RAW_CAPTURE_START_REQ = 720,
+	MSG_SMS_RAW_CAPTURE_START_RES = 721,
+	MSG_SMS_RAW_CAPTURE_ABORT_REQ = 722,
+	MSG_SMS_RAW_CAPTURE_ABORT_RES = 723,
+	MSG_SMS_RAW_CAPTURE_COMPLETE_IND = 728,
+	MSG_SMS_DATA_PUMP_IND = 729,
+	MSG_SMS_DATA_PUMP_REQ = 730,
+	MSG_SMS_DATA_PUMP_RES = 731,
+	MSG_SMS_FLASH_DL_REQ = 732,
+	MSG_SMS_EXEC_TEST_1_REQ = 734,
+	MSG_SMS_EXEC_TEST_1_RES = 735,
+	MSG_SMS_ENBALE_TS_INTERFACE_REQ = 736,
+	MSG_SMS_ENBALE_TS_INTERFACE_RES = 737,
+	MSG_SMS_SPI_SET_BUS_WIDTH_REQ = 738,
+	MSG_SMS_SPI_SET_BUS_WIDTH_RES = 739,
+	MSG_SMS_SEND_EMM_REQ = 740,
+	MSG_SMS_SEND_EMM_RES = 741,
+	MSG_SMS_DISABLE_TS_INTERFACE_REQ = 742,
+	MSG_SMS_DISABLE_TS_INTERFACE_RES = 743,
+	MSG_SMS_IS_BUF_FREE_REQ = 744,
+	MSG_SMS_IS_BUF_FREE_RES = 745,
+	MSG_SMS_EXT_ANTENNA_REQ = 746,
+	MSG_SMS_EXT_ANTENNA_RES = 747,
+	MSG_SMS_CMMB_GET_NET_OF_FREQ_REQ_OBSOLETE = 748,
+	MSG_SMS_CMMB_GET_NET_OF_FREQ_RES_OBSOLETE = 749,
+	MSG_SMS_BATTERY_LEVEL_REQ = 750,
+	MSG_SMS_BATTERY_LEVEL_RES = 751,
+	MSG_SMS_CMMB_INJECT_TABLE_REQ_OBSOLETE = 752,
+	MSG_SMS_CMMB_INJECT_TABLE_RES_OBSOLETE = 753,
+	MSG_SMS_FM_RADIO_BLOCK_IND = 754,
+	MSG_SMS_HOST_NOTIFICATION_IND = 755,
+	MSG_SMS_CMMB_GET_CONTROL_TABLE_REQ_OBSOLETE = 756,
+	MSG_SMS_CMMB_GET_CONTROL_TABLE_RES_OBSOLETE = 757,
+	MSG_SMS_CMMB_GET_NETWORKS_REQ = 760,
+	MSG_SMS_CMMB_GET_NETWORKS_RES = 761,
+	MSG_SMS_CMMB_START_SERVICE_REQ = 762,
+	MSG_SMS_CMMB_START_SERVICE_RES = 763,
+	MSG_SMS_CMMB_STOP_SERVICE_REQ = 764,
+	MSG_SMS_CMMB_STOP_SERVICE_RES = 765,
+	MSG_SMS_CMMB_ADD_CHANNEL_FILTER_REQ = 768,
+	MSG_SMS_CMMB_ADD_CHANNEL_FILTER_RES = 769,
+	MSG_SMS_CMMB_REMOVE_CHANNEL_FILTER_REQ = 770,
+	MSG_SMS_CMMB_REMOVE_CHANNEL_FILTER_RES = 771,
+	MSG_SMS_CMMB_START_CONTROL_INFO_REQ = 772,
+	MSG_SMS_CMMB_START_CONTROL_INFO_RES = 773,
+	MSG_SMS_CMMB_STOP_CONTROL_INFO_REQ = 774,
+	MSG_SMS_CMMB_STOP_CONTROL_INFO_RES = 775,
+	MSG_SMS_ISDBT_TUNE_REQ = 776,
+	MSG_SMS_ISDBT_TUNE_RES = 777,
+	MSG_SMS_TRANSMISSION_IND = 782,
+	MSG_SMS_PID_STATISTICS_IND = 783,
+	MSG_SMS_POWER_DOWN_IND = 784,
+	MSG_SMS_POWER_DOWN_CONF = 785,
+	MSG_SMS_POWER_UP_IND = 786,
+	MSG_SMS_POWER_UP_CONF = 787,
+	MSG_SMS_POWER_MODE_SET_REQ = 790,
+	MSG_SMS_POWER_MODE_SET_RES = 791,
+	MSG_SMS_DEBUG_HOST_EVENT_REQ = 792,
+	MSG_SMS_DEBUG_HOST_EVENT_RES = 793,
+	MSG_SMS_NEW_CRYSTAL_REQ = 794,
+	MSG_SMS_NEW_CRYSTAL_RES = 795,
+	MSG_SMS_CONFIG_SPI_REQ = 796,
+	MSG_SMS_CONFIG_SPI_RES = 797,
+	MSG_SMS_I2C_SHORT_STAT_IND = 798,
+	MSG_SMS_START_IR_REQ = 800,
+	MSG_SMS_START_IR_RES = 801,
+	MSG_SMS_IR_SAMPLES_IND = 802,
+	MSG_SMS_CMMB_CA_SERVICE_IND = 803,
+	MSG_SMS_SLAVE_DEVICE_DETECTED = 804,
+	MSG_SMS_INTERFACE_LOCK_IND = 805,
+	MSG_SMS_INTERFACE_UNLOCK_IND = 806,
+	MSG_SMS_SEND_ROSUM_BUFF_REQ = 810,
+	MSG_SMS_SEND_ROSUM_BUFF_RES = 811,
+	MSG_SMS_ROSUM_BUFF = 812,
+	MSG_SMS_SET_AES128_KEY_REQ = 815,
+	MSG_SMS_SET_AES128_KEY_RES = 816,
+	MSG_SMS_MBBMS_WRITE_REQ = 817,
+	MSG_SMS_MBBMS_WRITE_RES = 818,
+	MSG_SMS_MBBMS_READ_IND = 819,
+	MSG_SMS_IQ_STREAM_START_REQ = 820,
+	MSG_SMS_IQ_STREAM_START_RES = 821,
+	MSG_SMS_IQ_STREAM_STOP_REQ = 822,
+	MSG_SMS_IQ_STREAM_STOP_RES = 823,
+	MSG_SMS_IQ_STREAM_DATA_BLOCK = 824,
+	MSG_SMS_GET_EEPROM_VERSION_REQ = 825,
+	MSG_SMS_GET_EEPROM_VERSION_RES = 826,
+	MSG_SMS_SIGNAL_DETECTED_IND = 827,
+	MSG_SMS_NO_SIGNAL_IND = 828,
+	MSG_SMS_MRC_SHUTDOWN_SLAVE_REQ = 830,
+	MSG_SMS_MRC_SHUTDOWN_SLAVE_RES = 831,
+	MSG_SMS_MRC_BRINGUP_SLAVE_REQ = 832,
+	MSG_SMS_MRC_BRINGUP_SLAVE_RES = 833,
+	MSG_SMS_EXTERNAL_LNA_CTRL_REQ = 834,
+	MSG_SMS_EXTERNAL_LNA_CTRL_RES = 835,
+	MSG_SMS_SET_PERIODIC_STATISTICS_REQ = 836,
+	MSG_SMS_SET_PERIODIC_STATISTICS_RES = 837,
+	MSG_SMS_CMMB_SET_AUTO_OUTPUT_TS0_REQ = 838,
+	MSG_SMS_CMMB_SET_AUTO_OUTPUT_TS0_RES = 839,
+	LOCAL_TUNE = 850,
+	LOCAL_IFFT_H_ICI = 851,
+	MSG_RESYNC_REQ = 852,
+	MSG_SMS_CMMB_GET_MRC_STATISTICS_REQ = 853,
+	MSG_SMS_CMMB_GET_MRC_STATISTICS_RES = 854,
+	MSG_SMS_LOG_EX_ITEM = 855,
+	MSG_SMS_DEVICE_DATA_LOSS_IND = 856,
+	MSG_SMS_MRC_WATCHDOG_TRIGGERED_IND = 857,
+	MSG_SMS_USER_MSG_REQ = 858,
+	MSG_SMS_USER_MSG_RES = 859,
+	MSG_SMS_SMART_CARD_INIT_REQ = 860,
+	MSG_SMS_SMART_CARD_INIT_RES = 861,
+	MSG_SMS_SMART_CARD_WRITE_REQ = 862,
+	MSG_SMS_SMART_CARD_WRITE_RES = 863,
+	MSG_SMS_SMART_CARD_READ_IND = 864,
+	MSG_SMS_TSE_ENABLE_REQ = 866,
+	MSG_SMS_TSE_ENABLE_RES = 867,
+	MSG_SMS_CMMB_GET_SHORT_STATISTICS_REQ = 868,
+	MSG_SMS_CMMB_GET_SHORT_STATISTICS_RES = 869,
+	MSG_SMS_LED_CONFIG_REQ = 870,
+	MSG_SMS_LED_CONFIG_RES = 871,
+	MSG_PWM_ANTENNA_REQ = 872,
+	MSG_PWM_ANTENNA_RES = 873,
+	MSG_SMS_CMMB_SMD_SN_REQ = 874,
+	MSG_SMS_CMMB_SMD_SN_RES = 875,
+	MSG_SMS_CMMB_SET_CA_CW_REQ = 876,
+	MSG_SMS_CMMB_SET_CA_CW_RES = 877,
+	MSG_SMS_CMMB_SET_CA_SALT_REQ = 878,
+	MSG_SMS_CMMB_SET_CA_SALT_RES = 879,
+	MSG_SMS_NSCD_INIT_REQ = 880,
+	MSG_SMS_NSCD_INIT_RES = 881,
+	MSG_SMS_NSCD_PROCESS_SECTION_REQ = 882,
+	MSG_SMS_NSCD_PROCESS_SECTION_RES = 883,
+	MSG_SMS_DBD_CREATE_OBJECT_REQ = 884,
+	MSG_SMS_DBD_CREATE_OBJECT_RES = 885,
+	MSG_SMS_DBD_CONFIGURE_REQ = 886,
+	MSG_SMS_DBD_CONFIGURE_RES = 887,
+	MSG_SMS_DBD_SET_KEYS_REQ = 888,
+	MSG_SMS_DBD_SET_KEYS_RES = 889,
+	MSG_SMS_DBD_PROCESS_HEADER_REQ = 890,
+	MSG_SMS_DBD_PROCESS_HEADER_RES = 891,
+	MSG_SMS_DBD_PROCESS_DATA_REQ = 892,
+	MSG_SMS_DBD_PROCESS_DATA_RES = 893,
+	MSG_SMS_DBD_PROCESS_GET_DATA_REQ = 894,
+	MSG_SMS_DBD_PROCESS_GET_DATA_RES = 895,
+	MSG_SMS_NSCD_OPEN_SESSION_REQ = 896,
+	MSG_SMS_NSCD_OPEN_SESSION_RES = 897,
+	MSG_SMS_SEND_HOST_DATA_TO_DEMUX_REQ = 898,
+	MSG_SMS_SEND_HOST_DATA_TO_DEMUX_RES = 899,
+	MSG_LAST_MSG_TYPE = 900,
+};
 
 #define SMS_INIT_MSG_EX(ptr, type, src, dst, len) do { \
-	(ptr)->msgType = type; (ptr)->msgSrcId = src; (ptr)->msgDstId = dst; \
-	(ptr)->msgLength = len; (ptr)->msgFlags = 0; \
+	(ptr)->msg_type = type; \
+	(ptr)->msg_src_id = src; \
+	(ptr)->msg_dst_id = dst; \
+	(ptr)->msg_length = len; \
+	(ptr)->msg_flags = 0; \
 } while (0)
 
 #define SMS_INIT_MSG(ptr, type, len) \
@@ -277,228 +604,296 @@ enum SMS_DEVICE_MODE {
 	DEVICE_MODE_ISDBT_BDA,
 	DEVICE_MODE_CMMB,
 	DEVICE_MODE_RAW_TUNER,
+	DEVICE_MODE_FM_RADIO,
+	DEVICE_MODE_FM_RADIO_BDA,
+	DEVICE_MODE_ATSC,
 	DEVICE_MODE_MAX,
 };
 
-struct SmsMsgHdr_ST {
-	u16	msgType;
-	u8	msgSrcId;
-	u8	msgDstId;
-	u16	msgLength; /* Length of entire message, including header */
-	u16	msgFlags;
+struct sms_msg_hdr {
+	u16	msg_type;
+	u8	msg_src_id;
+	u8	msg_dst_id;
+	u16	msg_length; /* length of entire message, including header */
+	u16	msg_flags;
+};
+
+struct sms_msg_data {
+	struct sms_msg_hdr x_msg_header;
+	u32 msg_data[1];
 };
 
-struct SmsMsgData_ST {
-	struct SmsMsgHdr_ST xMsgHeader;
-	u32 msgData[1];
+struct sms_msg_data2 {
+	struct sms_msg_hdr x_msg_header;
+	u32 msg_data[2];
 };
 
-struct SmsMsgData_ST2 {
-	struct SmsMsgHdr_ST xMsgHeader;
-	u32 msgData[2];
+struct sms_msg_data4 {
+	struct sms_msg_hdr x_msg_header;
+	u32 msg_data[4];
 };
 
-struct SmsDataDownload_ST {
-	struct SmsMsgHdr_ST	xMsgHeader;
-	u32			MemAddr;
-	u8			Payload[SMS_MAX_PAYLOAD_SIZE];
+struct sms_data_download {
+	struct sms_msg_hdr	x_msg_header;
+	u32			mem_addr;
+	u8			payload[SMS_MAX_PAYLOAD_SIZE];
 };
 
-struct SmsVersionRes_ST {
-	struct SmsMsgHdr_ST	xMsgHeader;
+struct sms_version_res {
+	struct sms_msg_hdr	x_msg_header;
 
-	u16		ChipModel; /* e.g. 0x1102 for SMS-1102 "Nova" */
-	u8		Step; /* 0 - Step A */
-	u8		MetalFix; /* 0 - Metal 0 */
+	u16		chip_model; /* e.g. 0x1102 for SMS-1102 "Nova" */
+	u8		step; /* 0 - step A */
+	u8		metal_fix; /* 0 - Metal 0 */
 
-	/* FirmwareId 0xFF if ROM, otherwise the
+	/* firmware_id 0xFF if ROM, otherwise the
 	 * value indicated by SMSHOSTLIB_DEVICE_MODES_E */
-	u8 FirmwareId;
-	/* SupportedProtocols Bitwise OR combination of
+	u8 firmware_id;
+	/* supported_protocols Bitwise OR combination of
 					     * supported protocols */
-	u8 SupportedProtocols;
+	u8 supported_protocols;
 
-	u8		VersionMajor;
-	u8		VersionMinor;
-	u8		VersionPatch;
-	u8		VersionFieldPatch;
+	u8		version_major;
+	u8		version_minor;
+	u8		version_patch;
+	u8		version_field_patch;
 
-	u8		RomVersionMajor;
-	u8		RomVersionMinor;
-	u8		RomVersionPatch;
-	u8		RomVersionFieldPatch;
+	u8		rom_ver_major;
+	u8		rom_ver_minor;
+	u8		rom_ver_patch;
+	u8		rom_ver_field_patch;
 
 	u8		TextLabel[34];
 };
 
-struct SmsFirmware_ST {
-	u32			CheckSum;
-	u32			Length;
-	u32			StartAddress;
-	u8			Payload[1];
+struct sms_firmware {
+	u32			check_sum;
+	u32			length;
+	u32			start_address;
+	u8			payload[1];
 };
 
-/* Statistics information returned as response for
- * SmsHostApiGetStatistics_Req */
-struct SMSHOSTLIB_STATISTICS_ST {
-	u32 Reserved;		/* Reserved */
+/* statistics information returned as response for
+ * SmsHostApiGetstatistics_Req */
+struct sms_stats {
+	u32 reserved;		/* reserved */
 
 	/* Common parameters */
-	u32 IsRfLocked;		/* 0 - not locked, 1 - locked */
-	u32 IsDemodLocked;	/* 0 - not locked, 1 - locked */
-	u32 IsExternalLNAOn;	/* 0 - external LNA off, 1 - external LNA on */
+	u32 is_rf_locked;		/* 0 - not locked, 1 - locked */
+	u32 is_demod_locked;	/* 0 - not locked, 1 - locked */
+	u32 is_external_lna_on;	/* 0 - external LNA off, 1 - external LNA on */
 
 	/* Reception quality */
 	s32 SNR;		/* dB */
-	u32 BER;		/* Post Viterbi BER [1E-5] */
+	u32 ber;		/* Post Viterbi ber [1E-5] */
 	u32 FIB_CRC;		/* CRC errors percentage, valid only for DAB */
-	u32 TS_PER;		/* Transport stream PER,
+	u32 ts_per;		/* Transport stream PER,
 	0xFFFFFFFF indicate N/A, valid only for DVB-T/H */
 	u32 MFER;		/* DVB-H frame error rate in percentage,
 	0xFFFFFFFF indicate N/A, valid only for DVB-H */
 	s32 RSSI;		/* dBm */
-	s32 InBandPwr;		/* In band power in dBM */
-	s32 CarrierOffset;	/* Carrier Offset in bin/1024 */
+	s32 in_band_pwr;		/* In band power in dBM */
+	s32 carrier_offset;	/* Carrier Offset in bin/1024 */
 
 	/* Transmission parameters */
-	u32 Frequency;		/* Frequency in Hz */
-	u32 Bandwidth;		/* Bandwidth in MHz, valid only for DVB-T/H */
-	u32 TransmissionMode;	/* Transmission Mode, for DAB modes 1-4,
+	u32 frequency;		/* frequency in Hz */
+	u32 bandwidth;		/* bandwidth in MHz, valid only for DVB-T/H */
+	u32 transmission_mode;	/* Transmission Mode, for DAB modes 1-4,
 	for DVB-T/H FFT mode carriers in Kilos */
-	u32 ModemState;		/* from SMSHOSTLIB_DVB_MODEM_STATE_ET,
+	u32 modem_state;		/* from SMSHOSTLIB_DVB_MODEM_STATE_ET,
 	valid only for DVB-T/H */
-	u32 GuardInterval;	/* Guard Interval from
-	SMSHOSTLIB_GUARD_INTERVALS_ET, 	valid only for DVB-T/H */
-	u32 CodeRate;		/* Code Rate from SMSHOSTLIB_CODE_RATE_ET,
+	u32 guard_interval;	/* Guard Interval from
+	SMSHOSTLIB_GUARD_INTERVALS_ET,	valid only for DVB-T/H */
+	u32 code_rate;		/* Code Rate from SMSHOSTLIB_CODE_RATE_ET,
 	valid only for DVB-T/H */
-	u32 LPCodeRate;		/* Low Priority Code Rate from
+	u32 lp_code_rate;		/* Low Priority Code Rate from
 	SMSHOSTLIB_CODE_RATE_ET, valid only for DVB-T/H */
-	u32 Hierarchy;		/* Hierarchy from SMSHOSTLIB_HIERARCHY_ET,
+	u32 hierarchy;		/* hierarchy from SMSHOSTLIB_HIERARCHY_ET,
 	valid only for DVB-T/H */
-	u32 Constellation;	/* Constellation from
+	u32 constellation;	/* constellation from
 	SMSHOSTLIB_CONSTELLATION_ET, valid only for DVB-T/H */
 
 	/* Burst parameters, valid only for DVB-H */
-	u32 BurstSize;		/* Current burst size in bytes,
+	u32 burst_size;		/* Current burst size in bytes,
 	valid only for DVB-H */
-	u32 BurstDuration;	/* Current burst duration in mSec,
+	u32 burst_duration;	/* Current burst duration in mSec,
 	valid only for DVB-H */
-	u32 BurstCycleTime;	/* Current burst cycle time in mSec,
+	u32 burst_cycle_time;	/* Current burst cycle time in mSec,
 	valid only for DVB-H */
-	u32 CalculatedBurstCycleTime;/* Current burst cycle time in mSec,
+	u32 calc_burst_cycle_time;/* Current burst cycle time in mSec,
 	as calculated by demodulator, valid only for DVB-H */
-	u32 NumOfRows;		/* Number of rows in MPE table,
+	u32 num_of_rows;		/* Number of rows in MPE table,
 	valid only for DVB-H */
-	u32 NumOfPaddCols;	/* Number of padding columns in MPE table,
+	u32 num_of_padd_cols;	/* Number of padding columns in MPE table,
 	valid only for DVB-H */
-	u32 NumOfPunctCols;	/* Number of puncturing columns in MPE table,
+	u32 num_of_punct_cols;	/* Number of puncturing columns in MPE table,
 	valid only for DVB-H */
-	u32 ErrorTSPackets;	/* Number of erroneous
+	u32 error_ts_packets;	/* Number of erroneous
 	transport-stream packets */
-	u32 TotalTSPackets;	/* Total number of transport-stream packets */
-	u32 NumOfValidMpeTlbs;	/* Number of MPE tables which do not include
+	u32 total_ts_packets;	/* Total number of transport-stream packets */
+	u32 num_of_valid_mpe_tlbs;	/* Number of MPE tables which do not include
 	errors after MPE RS decoding */
-	u32 NumOfInvalidMpeTlbs;/* Number of MPE tables which include errors
+	u32 num_of_invalid_mpe_tlbs;/* Number of MPE tables which include errors
 	after MPE RS decoding */
-	u32 NumOfCorrectedMpeTlbs;/* Number of MPE tables which were
+	u32 num_of_corrected_mpe_tlbs;/* Number of MPE tables which were
 	corrected by MPE RS decoding */
 	/* Common params */
-	u32 BERErrorCount;	/* Number of errornous SYNC bits. */
-	u32 BERBitCount;	/* Total number of SYNC bits. */
+	u32 ber_error_count;	/* Number of errornous SYNC bits. */
+	u32 ber_bit_count;	/* Total number of SYNC bits. */
 
 	/* Interface information */
-	u32 SmsToHostTxErrors;	/* Total number of transmission errors. */
+	u32 sms_to_host_tx_errors;	/* Total number of transmission errors. */
 
 	/* DAB/T-DMB */
-	u32 PreBER; 		/* DAB/T-DMB only: Pre Viterbi BER [1E-5] */
+	u32 pre_ber;		/* DAB/T-DMB only: Pre Viterbi ber [1E-5] */
 
 	/* DVB-H TPS parameters */
-	u32 CellId;		/* TPS Cell ID in bits 15..0, bits 31..16 zero;
+	u32 cell_id;		/* TPS Cell ID in bits 15..0, bits 31..16 zero;
 	 if set to 0xFFFFFFFF cell_id not yet recovered */
-	u32 DvbhSrvIndHP;	/* DVB-H service indication info, bit 1 -
+	u32 dvbh_srv_ind_hp;	/* DVB-H service indication info, bit 1 -
 	Time Slicing indicator, bit 0 - MPE-FEC indicator */
-	u32 DvbhSrvIndLP;	/* DVB-H service indication info, bit 1 -
+	u32 dvbh_srv_ind_lp;	/* DVB-H service indication info, bit 1 -
 	Time Slicing indicator, bit 0 - MPE-FEC indicator */
 
-	u32 NumMPEReceived;	/* DVB-H, Num MPE section received */
+	u32 num_mpe_received;	/* DVB-H, Num MPE section received */
 
-	u32 ReservedFields[10];	/* Reserved */
+	u32 reservedFields[10];	/* reserved */
 };
 
-struct SmsMsgStatisticsInfo_ST {
-	u32 RequestResult;
+struct sms_msg_statistics_info {
+	u32 request_result;
 
-	struct SMSHOSTLIB_STATISTICS_ST Stat;
+	struct sms_stats stat;
 
 	/* Split the calc of the SNR in DAB */
-	u32 Signal; /* dB */
-	u32 Noise; /* dB */
+	u32 signal; /* dB */
+	u32 noise; /* dB */
 
 };
 
-struct SMSHOSTLIB_ISDBT_LAYER_STAT_ST {
+struct sms_isdbt_layer_stats {
 	/* Per-layer information */
-	u32 CodeRate; /* Code Rate from SMSHOSTLIB_CODE_RATE_ET,
+	u32 code_rate; /* Code Rate from SMSHOSTLIB_CODE_RATE_ET,
 		       * 255 means layer does not exist */
-	u32 Constellation; /* Constellation from SMSHOSTLIB_CONSTELLATION_ET,
+	u32 constellation; /* constellation from SMSHOSTLIB_CONSTELLATION_ET,
 			    * 255 means layer does not exist */
-	u32 BER; /* Post Viterbi BER [1E-5], 0xFFFFFFFF indicate N/A */
-	u32 BERErrorCount; /* Post Viterbi Error Bits Count */
-	u32 BERBitCount; /* Post Viterbi Total Bits Count */
-	u32 PreBER; /* Pre Viterbi BER [1E-5], 0xFFFFFFFF indicate N/A */
-	u32 TS_PER; /* Transport stream PER [%], 0xFFFFFFFF indicate N/A */
-	u32 ErrorTSPackets; /* Number of erroneous transport-stream packets */
-	u32 TotalTSPackets; /* Total number of transport-stream packets */
-	u32 TILdepthI; /* Time interleaver depth I parameter,
+	u32 ber; /* Post Viterbi ber [1E-5], 0xFFFFFFFF indicate N/A */
+	u32 ber_error_count; /* Post Viterbi Error Bits Count */
+	u32 ber_bit_count; /* Post Viterbi Total Bits Count */
+	u32 pre_ber; /* Pre Viterbi ber [1E-5], 0xFFFFFFFF indicate N/A */
+	u32 ts_per; /* Transport stream PER [%], 0xFFFFFFFF indicate N/A */
+	u32 error_ts_packets; /* Number of erroneous transport-stream packets */
+	u32 total_ts_packets; /* Total number of transport-stream packets */
+	u32 ti_ldepth_i; /* Time interleaver depth I parameter,
 			* 255 means layer does not exist */
-	u32 NumberOfSegments; /* Number of segments in layer A,
+	u32 number_of_segments; /* Number of segments in layer A,
 			       * 255 means layer does not exist */
-	u32 TMCCErrors; /* TMCC errors */
+	u32 tmcc_errors; /* TMCC errors */
 };
 
-struct SMSHOSTLIB_STATISTICS_ISDBT_ST {
-	u32 StatisticsType; /* Enumerator identifying the type of the
+struct sms_isdbt_stats {
+	u32 statistics_type; /* Enumerator identifying the type of the
 				* structure.  Values are the same as
 				* SMSHOSTLIB_DEVICE_MODES_E
 				*
 				* This field MUST always be first in any
 				* statistics structure */
 
-	u32 FullSize; /* Total size of the structure returned by the modem.
+	u32 full_size; /* Total size of the structure returned by the modem.
 		       * If the size requested by the host is smaller than
-		       * FullSize, the struct will be truncated */
+		       * full_size, the struct will be truncated */
 
 	/* Common parameters */
-	u32 IsRfLocked; /* 0 - not locked, 1 - locked */
-	u32 IsDemodLocked; /* 0 - not locked, 1 - locked */
-	u32 IsExternalLNAOn; /* 0 - external LNA off, 1 - external LNA on */
+	u32 is_rf_locked; /* 0 - not locked, 1 - locked */
+	u32 is_demod_locked; /* 0 - not locked, 1 - locked */
+	u32 is_external_lna_on; /* 0 - external LNA off, 1 - external LNA on */
 
 	/* Reception quality */
 	s32  SNR; /* dB */
 	s32  RSSI; /* dBm */
-	s32  InBandPwr; /* In band power in dBM */
-	s32  CarrierOffset; /* Carrier Offset in Hz */
+	s32  in_band_pwr; /* In band power in dBM */
+	s32  carrier_offset; /* Carrier Offset in Hz */
 
 	/* Transmission parameters */
-	u32 Frequency; /* Frequency in Hz */
-	u32 Bandwidth; /* Bandwidth in MHz */
-	u32 TransmissionMode; /* ISDB-T transmission mode */
-	u32 ModemState; /* 0 - Acquisition, 1 - Locked */
-	u32 GuardInterval; /* Guard Interval, 1 divided by value */
-	u32 SystemType; /* ISDB-T system type (ISDB-T / ISDB-Tsb) */
-	u32 PartialReception; /* TRUE - partial reception, FALSE otherwise */
-	u32 NumOfLayers; /* Number of ISDB-T layers in the network */
+	u32 frequency; /* frequency in Hz */
+	u32 bandwidth; /* bandwidth in MHz */
+	u32 transmission_mode; /* ISDB-T transmission mode */
+	u32 modem_state; /* 0 - Acquisition, 1 - Locked */
+	u32 guard_interval; /* Guard Interval, 1 divided by value */
+	u32 system_type; /* ISDB-T system type (ISDB-T / ISDB-Tsb) */
+	u32 partial_reception; /* TRUE - partial reception, FALSE otherwise */
+	u32 num_of_layers; /* Number of ISDB-T layers in the network */
 
 	/* Per-layer information */
 	/* Layers A, B and C */
-	struct SMSHOSTLIB_ISDBT_LAYER_STAT_ST	LayerInfo[3];
-	/* Per-layer statistics, see SMSHOSTLIB_ISDBT_LAYER_STAT_ST */
+	struct sms_isdbt_layer_stats	layer_info[3];
+	/* Per-layer statistics, see sms_isdbt_layer_stats */
 
 	/* Interface information */
-	u32 SmsToHostTxErrors; /* Total number of transmission errors. */
+	u32 sms_to_host_tx_errors; /* Total number of transmission errors. */
 };
 
-struct PID_STATISTICS_DATA_S {
+struct sms_isdbt_stats_ex {
+	u32 statistics_type; /* Enumerator identifying the type of the
+				* structure.  Values are the same as
+				* SMSHOSTLIB_DEVICE_MODES_E
+				*
+				* This field MUST always be first in any
+				* statistics structure */
+
+	u32 full_size; /* Total size of the structure returned by the modem.
+		       * If the size requested by the host is smaller than
+		       * full_size, the struct will be truncated */
+
+	/* Common parameters */
+	u32 is_rf_locked; /* 0 - not locked, 1 - locked */
+	u32 is_demod_locked; /* 0 - not locked, 1 - locked */
+	u32 is_external_lna_on; /* 0 - external LNA off, 1 - external LNA on */
+
+	/* Reception quality */
+	s32  SNR; /* dB */
+	s32  RSSI; /* dBm */
+	s32  in_band_pwr; /* In band power in dBM */
+	s32  carrier_offset; /* Carrier Offset in Hz */
+
+	/* Transmission parameters */
+	u32 frequency; /* frequency in Hz */
+	u32 bandwidth; /* bandwidth in MHz */
+	u32 transmission_mode; /* ISDB-T transmission mode */
+	u32 modem_state; /* 0 - Acquisition, 1 - Locked */
+	u32 guard_interval; /* Guard Interval, 1 divided by value */
+	u32 system_type; /* ISDB-T system type (ISDB-T / ISDB-Tsb) */
+	u32 partial_reception; /* TRUE - partial reception, FALSE otherwise */
+	u32 num_of_layers; /* Number of ISDB-T layers in the network */
+
+	u32 segment_number; /* Segment number for ISDB-Tsb */
+	u32 tune_bw;	   /* Tuned bandwidth - BW_ISDBT_1SEG / BW_ISDBT_3SEG */
+
+	/* Per-layer information */
+	/* Layers A, B and C */
+	struct sms_isdbt_layer_stats	layer_info[3];
+	/* Per-layer statistics, see sms_isdbt_layer_stats */
+
+	/* Interface information */
+	u32 reserved1;    /* Was sms_to_host_tx_errors - obsolete . */
+ /* Proprietary information */
+	u32 ext_antenna;    /* Obsolete field. */
+	u32 reception_quality;
+	u32 ews_alert_active;   /* signals if EWS alert is currently on */
+	u32 lna_on_off;	/* Internal LNA state: 0: OFF, 1: ON */
+
+	u32 rf_agc_level;	 /* RF AGC Level [linear units], full gain = 65535 (20dB) */
+	u32 bb_agc_level;    /* Baseband AGC level [linear units], full gain = 65535 (71.5dB) */
+	u32 fw_errors_counter;   /* Application errors - should be always zero */
+	u8 FwErrorsHistoryArr[8]; /* Last FW errors IDs - first is most recent, last is oldest */
+
+	s32  MRC_SNR;     /* dB */
+	u32 snr_full_res;    /* dB x 65536 */
+	u32 reserved4[4];
+};
+
+
+struct sms_pid_stats_data {
 	struct PID_BURST_S {
 		u32 size;
 		u32 padding_cols;
@@ -513,112 +908,155 @@ struct PID_STATISTICS_DATA_S {
 	u32 tot_cor_tbl;
 };
 
-struct PID_DATA_S {
+struct sms_pid_data {
 	u32 pid;
 	u32 num_rows;
-	struct PID_STATISTICS_DATA_S pid_statistics;
+	struct sms_pid_stats_data pid_statistics;
 };
 
 #define CORRECT_STAT_RSSI(_stat) ((_stat).RSSI *= -1)
-#define CORRECT_STAT_BANDWIDTH(_stat) (_stat.Bandwidth = 8 - _stat.Bandwidth)
+#define CORRECT_STAT_BANDWIDTH(_stat) (_stat.bandwidth = 8 - _stat.bandwidth)
 #define CORRECT_STAT_TRANSMISSON_MODE(_stat) \
-	if (_stat.TransmissionMode == 0) \
-		_stat.TransmissionMode = 2; \
-	else if (_stat.TransmissionMode == 1) \
-		_stat.TransmissionMode = 8; \
+	if (_stat.transmission_mode == 0) \
+		_stat.transmission_mode = 2; \
+	else if (_stat.transmission_mode == 1) \
+		_stat.transmission_mode = 8; \
 		else \
-			_stat.TransmissionMode = 4;
+			_stat.transmission_mode = 4;
 
-struct TRANSMISSION_STATISTICS_S {
-	u32 Frequency;		/* Frequency in Hz */
-	u32 Bandwidth;		/* Bandwidth in MHz */
-	u32 TransmissionMode;	/* FFT mode carriers in Kilos */
-	u32 GuardInterval;	/* Guard Interval from
+struct sms_tx_stats {
+	u32 frequency;		/* frequency in Hz */
+	u32 bandwidth;		/* bandwidth in MHz */
+	u32 transmission_mode;	/* FFT mode carriers in Kilos */
+	u32 guard_interval;	/* Guard Interval from
 	SMSHOSTLIB_GUARD_INTERVALS_ET */
-	u32 CodeRate;		/* Code Rate from SMSHOSTLIB_CODE_RATE_ET */
-	u32 LPCodeRate;		/* Low Priority Code Rate from
+	u32 code_rate;		/* Code Rate from SMSHOSTLIB_CODE_RATE_ET */
+	u32 lp_code_rate;		/* Low Priority Code Rate from
 	SMSHOSTLIB_CODE_RATE_ET */
-	u32 Hierarchy;		/* Hierarchy from SMSHOSTLIB_HIERARCHY_ET */
-	u32 Constellation;	/* Constellation from
+	u32 hierarchy;		/* hierarchy from SMSHOSTLIB_HIERARCHY_ET */
+	u32 constellation;	/* constellation from
 	SMSHOSTLIB_CONSTELLATION_ET */
 
 	/* DVB-H TPS parameters */
-	u32 CellId;		/* TPS Cell ID in bits 15..0, bits 31..16 zero;
+	u32 cell_id;		/* TPS Cell ID in bits 15..0, bits 31..16 zero;
 	 if set to 0xFFFFFFFF cell_id not yet recovered */
-	u32 DvbhSrvIndHP;	/* DVB-H service indication info, bit 1 -
+	u32 dvbh_srv_ind_hp;	/* DVB-H service indication info, bit 1 -
 	 Time Slicing indicator, bit 0 - MPE-FEC indicator */
-	u32 DvbhSrvIndLP;	/* DVB-H service indication info, bit 1 -
+	u32 dvbh_srv_ind_lp;	/* DVB-H service indication info, bit 1 -
 	 Time Slicing indicator, bit 0 - MPE-FEC indicator */
-	u32 IsDemodLocked;	/* 0 - not locked, 1 - locked */
+	u32 is_demod_locked;	/* 0 - not locked, 1 - locked */
+};
+
+struct sms_rx_stats {
+	u32 is_rf_locked;		/* 0 - not locked, 1 - locked */
+	u32 is_demod_locked;	/* 0 - not locked, 1 - locked */
+	u32 is_external_lna_on;	/* 0 - external LNA off, 1 - external LNA on */
+
+	u32 modem_state;		/* from SMSHOSTLIB_DVB_MODEM_STATE_ET */
+	s32 SNR;		/* dB */
+	u32 ber;		/* Post Viterbi ber [1E-5] */
+	u32 ber_error_count;	/* Number of erronous SYNC bits. */
+	u32 ber_bit_count;	/* Total number of SYNC bits. */
+	u32 ts_per;		/* Transport stream PER,
+	0xFFFFFFFF indicate N/A */
+	u32 MFER;		/* DVB-H frame error rate in percentage,
+	0xFFFFFFFF indicate N/A, valid only for DVB-H */
+	s32 RSSI;		/* dBm */
+	s32 in_band_pwr;		/* In band power in dBM */
+	s32 carrier_offset;	/* Carrier Offset in bin/1024 */
+	u32 error_ts_packets;	/* Number of erroneous
+	transport-stream packets */
+	u32 total_ts_packets;	/* Total number of transport-stream packets */
+
+	s32 MRC_SNR;		/* dB */
+	s32 MRC_RSSI;		/* dBm */
+	s32 mrc_in_band_pwr;	/* In band power in dBM */
 };
 
-struct RECEPTION_STATISTICS_S {
-	u32 IsRfLocked;		/* 0 - not locked, 1 - locked */
-	u32 IsDemodLocked;	/* 0 - not locked, 1 - locked */
-	u32 IsExternalLNAOn;	/* 0 - external LNA off, 1 - external LNA on */
+struct sms_rx_stats_ex {
+	u32 is_rf_locked;		/* 0 - not locked, 1 - locked */
+	u32 is_demod_locked;	/* 0 - not locked, 1 - locked */
+	u32 is_external_lna_on;	/* 0 - external LNA off, 1 - external LNA on */
 
-	u32 ModemState;		/* from SMSHOSTLIB_DVB_MODEM_STATE_ET */
+	u32 modem_state;		/* from SMSHOSTLIB_DVB_MODEM_STATE_ET */
 	s32 SNR;		/* dB */
-	u32 BER;		/* Post Viterbi BER [1E-5] */
-	u32 BERErrorCount;	/* Number of erronous SYNC bits. */
-	u32 BERBitCount;	/* Total number of SYNC bits. */
-	u32 TS_PER;		/* Transport stream PER,
+	u32 ber;		/* Post Viterbi ber [1E-5] */
+	u32 ber_error_count;	/* Number of erronous SYNC bits. */
+	u32 ber_bit_count;	/* Total number of SYNC bits. */
+	u32 ts_per;		/* Transport stream PER,
 	0xFFFFFFFF indicate N/A */
 	u32 MFER;		/* DVB-H frame error rate in percentage,
 	0xFFFFFFFF indicate N/A, valid only for DVB-H */
 	s32 RSSI;		/* dBm */
-	s32 InBandPwr;		/* In band power in dBM */
-	s32 CarrierOffset;	/* Carrier Offset in bin/1024 */
-	u32 ErrorTSPackets;	/* Number of erroneous
+	s32 in_band_pwr;		/* In band power in dBM */
+	s32 carrier_offset;	/* Carrier Offset in bin/1024 */
+	u32 error_ts_packets;	/* Number of erroneous
 	transport-stream packets */
-	u32 TotalTSPackets;	/* Total number of transport-stream packets */
+	u32 total_ts_packets;	/* Total number of transport-stream packets */
+
+	s32  ref_dev_ppm;
+	s32  freq_dev_hz;
 
 	s32 MRC_SNR;		/* dB */
 	s32 MRC_RSSI;		/* dBm */
-	s32 MRC_InBandPwr;	/* In band power in dBM */
+	s32 mrc_in_band_pwr;	/* In band power in dBM */
 };
 
 
-/* Statistics information returned as response for
- * SmsHostApiGetStatisticsEx_Req for DVB applications, SMS1100 and up */
-struct SMSHOSTLIB_STATISTICS_DVB_S {
+/* statistics information returned as response for
+ * SmsHostApiGetstatisticsEx_Req for DVB applications, SMS1100 and up */
+struct sms_stats_dvb {
 	/* Reception */
-	struct RECEPTION_STATISTICS_S ReceptionData;
+	struct sms_rx_stats reception_data;
 
 	/* Transmission parameters */
-	struct TRANSMISSION_STATISTICS_S TransmissionData;
+	struct sms_tx_stats transmission_data;
 
 	/* Burst parameters, valid only for DVB-H */
 #define	SRVM_MAX_PID_FILTERS 8
-	struct PID_DATA_S PidData[SRVM_MAX_PID_FILTERS];
+	struct sms_pid_data pid_data[SRVM_MAX_PID_FILTERS];
 };
 
-struct SRVM_SIGNAL_STATUS_S {
+/* statistics information returned as response for
+ * SmsHostApiGetstatisticsEx_Req for DVB applications, SMS1100 and up */
+struct sms_stats_dvb_ex {
+	/* Reception */
+	struct sms_rx_stats_ex reception_data;
+
+	/* Transmission parameters */
+	struct sms_tx_stats transmission_data;
+
+	/* Burst parameters, valid only for DVB-H */
+#define	SRVM_MAX_PID_FILTERS 8
+	struct sms_pid_data pid_data[SRVM_MAX_PID_FILTERS];
+};
+
+struct sms_srvm_signal_status {
 	u32 result;
 	u32 snr;
-	u32 tsPackets;
-	u32 etsPackets;
+	u32 ts_packets;
+	u32 ets_packets;
 	u32 constellation;
-	u32 hpCode;
-	u32 tpsSrvIndLP;
-	u32 tpsSrvIndHP;
-	u32 cellId;
+	u32 hp_code;
+	u32 tps_srv_ind_lp;
+	u32 tps_srv_ind_hp;
+	u32 cell_id;
 	u32 reason;
 
-	s32 inBandPower;
-	u32 requestId;
+	s32 in_band_power;
+	u32 request_id;
 };
 
-struct SMSHOSTLIB_I2C_REQ_ST {
-	u32	DeviceAddress; /* I2c device address */
-	u32	WriteCount; /* number of bytes to write */
-	u32	ReadCount; /* number of bytes to read */
+struct sms_i2c_req {
+	u32	device_address; /* I2c device address */
+	u32	write_count; /* number of bytes to write */
+	u32	read_count; /* number of bytes to read */
 	u8	Data[1];
 };
 
-struct SMSHOSTLIB_I2C_RES_ST {
-	u32	Status; /* non-zero value in case of failure */
-	u32	ReadCount; /* number of bytes read */
+struct sms_i2c_res {
+	u32	status; /* non-zero value in case of failure */
+	u32	read_count; /* number of bytes read */
 	u8	Data[1];
 };
 
@@ -638,59 +1076,39 @@ struct smscore_config_gpio {
 #define SMS_GPIO_INPUTCHARACTERISTICS_SCHMITT 1
 	u8 inputcharacteristics;
 
-#define SMS_GPIO_OUTPUTSLEWRATE_FAST 0
-#define SMS_GPIO_OUTPUTSLEWRATE_SLOW 1
-	u8 outputslewrate;
-
-#define SMS_GPIO_OUTPUTDRIVING_4mA  0
-#define SMS_GPIO_OUTPUTDRIVING_8mA  1
-#define SMS_GPIO_OUTPUTDRIVING_12mA 2
-#define SMS_GPIO_OUTPUTDRIVING_16mA 3
-	u8 outputdriving;
-};
-
-struct smscore_gpio_config {
-#define SMS_GPIO_DIRECTION_INPUT  0
-#define SMS_GPIO_DIRECTION_OUTPUT 1
-	u8 Direction;
-
-#define SMS_GPIO_PULL_UP_DOWN_NONE     0
-#define SMS_GPIO_PULL_UP_DOWN_PULLDOWN 1
-#define SMS_GPIO_PULL_UP_DOWN_PULLUP   2
-#define SMS_GPIO_PULL_UP_DOWN_KEEPER   3
-	u8 PullUpDown;
-
-#define SMS_GPIO_INPUT_CHARACTERISTICS_NORMAL  0
-#define SMS_GPIO_INPUT_CHARACTERISTICS_SCHMITT 1
-	u8 InputCharacteristics;
-
-#define SMS_GPIO_OUTPUT_SLEW_RATE_SLOW		1 /* 10xx */
-#define SMS_GPIO_OUTPUT_SLEW_RATE_FAST		0 /* 10xx */
+	/* 10xx */
+#define SMS_GPIO_OUTPUT_SLEW_RATE_FAST 0
+#define SMS_GPIO_OUTPUT_SLEW_WRATE_SLOW 1
 
+	/* 11xx */
+#define SMS_GPIO_OUTPUT_SLEW_RATE_0_45_V_NS	0
+#define SMS_GPIO_OUTPUT_SLEW_RATE_0_9_V_NS	1
+#define SMS_GPIO_OUTPUT_SLEW_RATE_1_7_V_NS	2
+#define SMS_GPIO_OUTPUT_SLEW_RATE_3_3_V_NS	3
 
-#define SMS_GPIO_OUTPUT_SLEW_RATE_0_45_V_NS	0 /* 11xx */
-#define SMS_GPIO_OUTPUT_SLEW_RATE_0_9_V_NS	1 /* 11xx */
-#define SMS_GPIO_OUTPUT_SLEW_RATE_1_7_V_NS	2 /* 11xx */
-#define SMS_GPIO_OUTPUT_SLEW_RATE_3_3_V_NS	3 /* 11xx */
-	u8 OutputSlewRate;
+	u8 outputslewrate;
 
-#define SMS_GPIO_OUTPUT_DRIVING_S_4mA		0 /* 10xx */
-#define SMS_GPIO_OUTPUT_DRIVING_S_8mA		1 /* 10xx */
-#define SMS_GPIO_OUTPUT_DRIVING_S_12mA		2 /* 10xx */
-#define SMS_GPIO_OUTPUT_DRIVING_S_16mA		3 /* 10xx */
+	/* 10xx */
+#define SMS_GPIO_OUTPUTDRIVING_S_4mA  0
+#define SMS_GPIO_OUTPUTDRIVING_S_8mA  1
+#define SMS_GPIO_OUTPUTDRIVING_S_12mA 2
+#define SMS_GPIO_OUTPUTDRIVING_S_16mA 3
+
+	/* 11xx*/
+#define SMS_GPIO_OUTPUTDRIVING_1_5mA	0
+#define SMS_GPIO_OUTPUTDRIVING_2_8mA	1
+#define SMS_GPIO_OUTPUTDRIVING_4mA	2
+#define SMS_GPIO_OUTPUTDRIVING_7mA	3
+#define SMS_GPIO_OUTPUTDRIVING_10mA	4
+#define SMS_GPIO_OUTPUTDRIVING_11mA	5
+#define SMS_GPIO_OUTPUTDRIVING_14mA	6
+#define SMS_GPIO_OUTPUTDRIVING_16mA	7
 
-#define SMS_GPIO_OUTPUT_DRIVING_1_5mA		0 /* 11xx */
-#define SMS_GPIO_OUTPUT_DRIVING_2_8mA		1 /* 11xx */
-#define SMS_GPIO_OUTPUT_DRIVING_4mA		2 /* 11xx */
-#define SMS_GPIO_OUTPUT_DRIVING_7mA		3 /* 11xx */
-#define SMS_GPIO_OUTPUT_DRIVING_10mA		4 /* 11xx */
-#define SMS_GPIO_OUTPUT_DRIVING_11mA		5 /* 11xx */
-#define SMS_GPIO_OUTPUT_DRIVING_14mA		6 /* 11xx */
-#define SMS_GPIO_OUTPUT_DRIVING_16mA		7 /* 11xx */
-	u8 OutputDriving;
+	u8 outputdriving;
 };
 
-extern void smscore_registry_setmode(char *devpath, int mode);
+char *smscore_translate_msg(enum msg_types msgtype);
+
 extern int smscore_registry_getmode(char *devpath);
 
 extern int smscore_register_hotplug(hotplug_t hotplug);
@@ -721,8 +1139,6 @@ extern void smscore_onresponse(struct smscore_device_t *coredev,
 extern int smscore_get_common_buffer_size(struct smscore_device_t *coredev);
 extern int smscore_map_common_buffer(struct smscore_device_t *coredev,
 				      struct vm_area_struct *vma);
-extern int smscore_get_fw_filename(struct smscore_device_t *coredev,
-				   int mode, char *filename);
 extern int smscore_send_fw_file(struct smscore_device_t *coredev,
 				u8 *ufwbuf, int size);
 
@@ -737,11 +1153,11 @@ int smscore_configure_gpio(struct smscore_device_t *coredev, u32 pin,
 int smscore_set_gpio(struct smscore_device_t *coredev, u32 pin, int level);
 
 /* new GPIO management */
-extern int smscore_gpio_configure(struct smscore_device_t *coredev, u8 PinNum,
-		struct smscore_gpio_config *pGpioConfig);
-extern int smscore_gpio_set_level(struct smscore_device_t *coredev, u8 PinNum,
-		u8 NewLevel);
-extern int smscore_gpio_get_level(struct smscore_device_t *coredev, u8 PinNum,
+extern int smscore_gpio_configure(struct smscore_device_t *coredev, u8 pin_num,
+		struct smscore_config_gpio *p_gpio_config);
+extern int smscore_gpio_set_level(struct smscore_device_t *coredev, u8 pin_num,
+		u8 new_level);
+extern int smscore_gpio_get_level(struct smscore_device_t *coredev, u8 pin_num,
 		u8 *level);
 
 void smscore_set_board_id(struct smscore_device_t *core, int id);
@@ -760,7 +1176,8 @@ int smscore_led_state(struct smscore_device_t *core, int led);
 
 #define dprintk(kern, lvl, fmt, arg...) do {\
 	if (sms_dbg & lvl) \
-		sms_printk(kern, fmt, ##arg); } while (0)
+		sms_printk(kern, fmt, ##arg); \
+} while (0)
 
 #define sms_log(fmt, arg...) sms_printk(KERN_INFO, fmt, ##arg)
 #define sms_err(fmt, arg...) \
diff --git a/drivers/media/common/siano/smsdvb-debugfs.c b/drivers/media/common/siano/smsdvb-debugfs.c
new file mode 100644
index 0000000..0bb4430
--- /dev/null
+++ b/drivers/media/common/siano/smsdvb-debugfs.c
@@ -0,0 +1,551 @@
+/***********************************************************************
+ *
+ * Copyright(c) 2013 Mauro Carvalho Chehab <mchehab@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, see <http://www.gnu.org/licenses/>.
+ *
+ ***********************************************************************/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/debugfs.h>
+#include <linux/spinlock.h>
+#include <linux/usb.h>
+
+#include "dmxdev.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+
+#include "smscoreapi.h"
+
+#include "smsdvb.h"
+
+static struct dentry *smsdvb_debugfs_usb_root;
+
+struct smsdvb_debugfs {
+	struct kref		refcount;
+	spinlock_t		lock;
+
+	char			stats_data[PAGE_SIZE];
+	unsigned		stats_count;
+	bool			stats_was_read;
+
+	wait_queue_head_t	stats_queue;
+};
+
+static void smsdvb_print_dvb_stats(struct smsdvb_debugfs *debug_data,
+			    struct sms_stats *p)
+{
+	int n = 0;
+	char *buf;
+
+	spin_lock(&debug_data->lock);
+	if (debug_data->stats_count) {
+		spin_unlock(&debug_data->lock);
+		return;
+	}
+
+	buf = debug_data->stats_data;
+
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "is_rf_locked = %d\n", p->is_rf_locked);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "is_demod_locked = %d\n", p->is_demod_locked);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "is_external_lna_on = %d\n", p->is_external_lna_on);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "SNR = %d\n", p->SNR);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "ber = %d\n", p->ber);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "FIB_CRC = %d\n", p->FIB_CRC);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "ts_per = %d\n", p->ts_per);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "MFER = %d\n", p->MFER);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "RSSI = %d\n", p->RSSI);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "in_band_pwr = %d\n", p->in_band_pwr);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "carrier_offset = %d\n", p->carrier_offset);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "modem_state = %d\n", p->modem_state);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "frequency = %d\n", p->frequency);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "bandwidth = %d\n", p->bandwidth);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "transmission_mode = %d\n", p->transmission_mode);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "modem_state = %d\n", p->modem_state);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "guard_interval = %d\n", p->guard_interval);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "code_rate = %d\n", p->code_rate);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "lp_code_rate = %d\n", p->lp_code_rate);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "hierarchy = %d\n", p->hierarchy);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "constellation = %d\n", p->constellation);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "burst_size = %d\n", p->burst_size);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "burst_duration = %d\n", p->burst_duration);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "burst_cycle_time = %d\n", p->burst_cycle_time);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "calc_burst_cycle_time = %d\n",
+		      p->calc_burst_cycle_time);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "num_of_rows = %d\n", p->num_of_rows);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "num_of_padd_cols = %d\n", p->num_of_padd_cols);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "num_of_punct_cols = %d\n", p->num_of_punct_cols);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "error_ts_packets = %d\n", p->error_ts_packets);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "total_ts_packets = %d\n", p->total_ts_packets);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "num_of_valid_mpe_tlbs = %d\n", p->num_of_valid_mpe_tlbs);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "num_of_invalid_mpe_tlbs = %d\n", p->num_of_invalid_mpe_tlbs);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "num_of_corrected_mpe_tlbs = %d\n", p->num_of_corrected_mpe_tlbs);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "ber_error_count = %d\n", p->ber_error_count);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "ber_bit_count = %d\n", p->ber_bit_count);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "sms_to_host_tx_errors = %d\n", p->sms_to_host_tx_errors);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "pre_ber = %d\n", p->pre_ber);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "cell_id = %d\n", p->cell_id);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "dvbh_srv_ind_hp = %d\n", p->dvbh_srv_ind_hp);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "dvbh_srv_ind_lp = %d\n", p->dvbh_srv_ind_lp);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "num_mpe_received = %d\n", p->num_mpe_received);
+
+	debug_data->stats_count = n;
+	spin_unlock(&debug_data->lock);
+	wake_up(&debug_data->stats_queue);
+}
+
+static void smsdvb_print_isdb_stats(struct smsdvb_debugfs *debug_data,
+			     struct sms_isdbt_stats *p)
+{
+	int i, n = 0;
+	char *buf;
+
+	spin_lock(&debug_data->lock);
+	if (debug_data->stats_count) {
+		spin_unlock(&debug_data->lock);
+		return;
+	}
+
+	buf = debug_data->stats_data;
+
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "statistics_type = %d\t", p->statistics_type);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "full_size = %d\n", p->full_size);
+
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "is_rf_locked = %d\t\t", p->is_rf_locked);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "is_demod_locked = %d\t", p->is_demod_locked);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "is_external_lna_on = %d\n", p->is_external_lna_on);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "SNR = %d dB\t\t", p->SNR);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "RSSI = %d dBm\t\t", p->RSSI);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "in_band_pwr = %d dBm\n", p->in_band_pwr);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "carrier_offset = %d\t", p->carrier_offset);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "bandwidth = %d\t\t", p->bandwidth);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "frequency = %d Hz\n", p->frequency);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "transmission_mode = %d\t", p->transmission_mode);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "modem_state = %d\t\t", p->modem_state);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "guard_interval = %d\n", p->guard_interval);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "system_type = %d\t\t", p->system_type);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "partial_reception = %d\t", p->partial_reception);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "num_of_layers = %d\n", p->num_of_layers);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "sms_to_host_tx_errors = %d\n", p->sms_to_host_tx_errors);
+
+	for (i = 0; i < 3; i++) {
+		if (p->layer_info[i].number_of_segments < 1 ||
+		    p->layer_info[i].number_of_segments > 13)
+			continue;
+
+		n += snprintf(&buf[n], PAGE_SIZE - n, "\nLayer %d\n", i);
+		n += snprintf(&buf[n], PAGE_SIZE - n, "\tcode_rate = %d\t",
+			      p->layer_info[i].code_rate);
+		n += snprintf(&buf[n], PAGE_SIZE - n, "constellation = %d\n",
+			      p->layer_info[i].constellation);
+		n += snprintf(&buf[n], PAGE_SIZE - n, "\tber = %-5d\t",
+			      p->layer_info[i].ber);
+		n += snprintf(&buf[n], PAGE_SIZE - n, "\tber_error_count = %-5d\t",
+			      p->layer_info[i].ber_error_count);
+		n += snprintf(&buf[n], PAGE_SIZE - n, "ber_bit_count = %-5d\n",
+			      p->layer_info[i].ber_bit_count);
+		n += snprintf(&buf[n], PAGE_SIZE - n, "\tpre_ber = %-5d\t",
+			      p->layer_info[i].pre_ber);
+		n += snprintf(&buf[n], PAGE_SIZE - n, "\tts_per = %-5d\n",
+			      p->layer_info[i].ts_per);
+		n += snprintf(&buf[n], PAGE_SIZE - n, "\terror_ts_packets = %-5d\t",
+			      p->layer_info[i].error_ts_packets);
+		n += snprintf(&buf[n], PAGE_SIZE - n, "total_ts_packets = %-5d\t",
+			      p->layer_info[i].total_ts_packets);
+		n += snprintf(&buf[n], PAGE_SIZE - n, "ti_ldepth_i = %d\n",
+			      p->layer_info[i].ti_ldepth_i);
+		n += snprintf(&buf[n], PAGE_SIZE - n,
+			      "\tnumber_of_segments = %d\t",
+			      p->layer_info[i].number_of_segments);
+		n += snprintf(&buf[n], PAGE_SIZE - n, "tmcc_errors = %d\n",
+			      p->layer_info[i].tmcc_errors);
+	}
+
+	debug_data->stats_count = n;
+	spin_unlock(&debug_data->lock);
+	wake_up(&debug_data->stats_queue);
+}
+
+static void smsdvb_print_isdb_stats_ex(struct smsdvb_debugfs *debug_data,
+				struct sms_isdbt_stats_ex *p)
+{
+	int i, n = 0;
+	char *buf;
+
+	spin_lock(&debug_data->lock);
+	if (debug_data->stats_count) {
+		spin_unlock(&debug_data->lock);
+		return;
+	}
+
+	buf = debug_data->stats_data;
+
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "statistics_type = %d\t", p->statistics_type);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "full_size = %d\n", p->full_size);
+
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "is_rf_locked = %d\t\t", p->is_rf_locked);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "is_demod_locked = %d\t", p->is_demod_locked);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "is_external_lna_on = %d\n", p->is_external_lna_on);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "SNR = %d dB\t\t", p->SNR);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "RSSI = %d dBm\t\t", p->RSSI);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "in_band_pwr = %d dBm\n", p->in_band_pwr);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "carrier_offset = %d\t", p->carrier_offset);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "bandwidth = %d\t\t", p->bandwidth);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "frequency = %d Hz\n", p->frequency);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "transmission_mode = %d\t", p->transmission_mode);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "modem_state = %d\t\t", p->modem_state);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "guard_interval = %d\n", p->guard_interval);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "system_type = %d\t\t", p->system_type);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "partial_reception = %d\t", p->partial_reception);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "num_of_layers = %d\n", p->num_of_layers);
+	n += snprintf(&buf[n], PAGE_SIZE - n, "segment_number = %d\t",
+		      p->segment_number);
+	n += snprintf(&buf[n], PAGE_SIZE - n, "tune_bw = %d\n",
+		      p->tune_bw);
+
+	for (i = 0; i < 3; i++) {
+		if (p->layer_info[i].number_of_segments < 1 ||
+		    p->layer_info[i].number_of_segments > 13)
+			continue;
+
+		n += snprintf(&buf[n], PAGE_SIZE - n, "\nLayer %d\n", i);
+		n += snprintf(&buf[n], PAGE_SIZE - n, "\tcode_rate = %d\t",
+			      p->layer_info[i].code_rate);
+		n += snprintf(&buf[n], PAGE_SIZE - n, "constellation = %d\n",
+			      p->layer_info[i].constellation);
+		n += snprintf(&buf[n], PAGE_SIZE - n, "\tber = %-5d\t",
+			      p->layer_info[i].ber);
+		n += snprintf(&buf[n], PAGE_SIZE - n, "\tber_error_count = %-5d\t",
+			      p->layer_info[i].ber_error_count);
+		n += snprintf(&buf[n], PAGE_SIZE - n, "ber_bit_count = %-5d\n",
+			      p->layer_info[i].ber_bit_count);
+		n += snprintf(&buf[n], PAGE_SIZE - n, "\tpre_ber = %-5d\t",
+			      p->layer_info[i].pre_ber);
+		n += snprintf(&buf[n], PAGE_SIZE - n, "\tts_per = %-5d\n",
+			      p->layer_info[i].ts_per);
+		n += snprintf(&buf[n], PAGE_SIZE - n, "\terror_ts_packets = %-5d\t",
+			      p->layer_info[i].error_ts_packets);
+		n += snprintf(&buf[n], PAGE_SIZE - n, "total_ts_packets = %-5d\t",
+			      p->layer_info[i].total_ts_packets);
+		n += snprintf(&buf[n], PAGE_SIZE - n, "ti_ldepth_i = %d\n",
+			      p->layer_info[i].ti_ldepth_i);
+		n += snprintf(&buf[n], PAGE_SIZE - n,
+			      "\tnumber_of_segments = %d\t",
+			      p->layer_info[i].number_of_segments);
+		n += snprintf(&buf[n], PAGE_SIZE - n, "tmcc_errors = %d\n",
+			      p->layer_info[i].tmcc_errors);
+	}
+
+
+	debug_data->stats_count = n;
+	spin_unlock(&debug_data->lock);
+
+	wake_up(&debug_data->stats_queue);
+}
+
+static int smsdvb_stats_open(struct inode *inode, struct file *file)
+{
+	struct smsdvb_client_t *client = inode->i_private;
+	struct smsdvb_debugfs *debug_data = client->debug_data;
+
+	kref_get(&debug_data->refcount);
+
+	spin_lock(&debug_data->lock);
+	debug_data->stats_count = 0;
+	debug_data->stats_was_read = false;
+	spin_unlock(&debug_data->lock);
+
+	file->private_data = debug_data;
+
+	return 0;
+}
+
+static void smsdvb_debugfs_data_release(struct kref *ref)
+{
+	struct smsdvb_debugfs *debug_data;
+
+	debug_data = container_of(ref, struct smsdvb_debugfs, refcount);
+	kfree(debug_data);
+}
+
+static int smsdvb_stats_wait_read(struct smsdvb_debugfs *debug_data)
+{
+	int rc = 1;
+
+	spin_lock(&debug_data->lock);
+
+	if (debug_data->stats_was_read)
+		goto exit;
+
+	rc = debug_data->stats_count;
+
+exit:
+	spin_unlock(&debug_data->lock);
+	return rc;
+}
+
+static unsigned int smsdvb_stats_poll(struct file *file, poll_table *wait)
+{
+	struct smsdvb_debugfs *debug_data = file->private_data;
+	int rc;
+
+	kref_get(&debug_data->refcount);
+
+	poll_wait(file, &debug_data->stats_queue, wait);
+
+	rc = smsdvb_stats_wait_read(debug_data);
+	if (rc > 0)
+		rc = POLLIN | POLLRDNORM;
+
+	kref_put(&debug_data->refcount, smsdvb_debugfs_data_release);
+
+	return rc;
+}
+
+static ssize_t smsdvb_stats_read(struct file *file, char __user *user_buf,
+				      size_t nbytes, loff_t *ppos)
+{
+	int rc = 0, len;
+	struct smsdvb_debugfs *debug_data = file->private_data;
+
+	kref_get(&debug_data->refcount);
+
+	if (file->f_flags & O_NONBLOCK) {
+		rc = smsdvb_stats_wait_read(debug_data);
+		if (!rc) {
+			rc = -EWOULDBLOCK;
+			goto ret;
+		}
+	} else {
+		rc = wait_event_interruptible(debug_data->stats_queue,
+				      smsdvb_stats_wait_read(debug_data));
+		if (rc < 0)
+			goto ret;
+	}
+
+	if (debug_data->stats_was_read) {
+		rc = 0;	/* EOF */
+		goto ret;
+	}
+
+	len = debug_data->stats_count - *ppos;
+	if (len >= 0)
+		rc = simple_read_from_buffer(user_buf, nbytes, ppos,
+					     debug_data->stats_data, len);
+	else
+		rc = 0;
+
+	if (*ppos >= debug_data->stats_count) {
+		spin_lock(&debug_data->lock);
+		debug_data->stats_was_read = true;
+		spin_unlock(&debug_data->lock);
+	}
+ret:
+	kref_put(&debug_data->refcount, smsdvb_debugfs_data_release);
+	return rc;
+}
+
+static int smsdvb_stats_release(struct inode *inode, struct file *file)
+{
+	struct smsdvb_debugfs *debug_data = file->private_data;
+
+	spin_lock(&debug_data->lock);
+	debug_data->stats_was_read = true;	/* return EOF to read() */
+	spin_unlock(&debug_data->lock);
+	wake_up_interruptible_sync(&debug_data->stats_queue);
+
+	kref_put(&debug_data->refcount, smsdvb_debugfs_data_release);
+	file->private_data = NULL;
+
+	return 0;
+}
+
+static const struct file_operations debugfs_stats_ops = {
+	.open = smsdvb_stats_open,
+	.poll = smsdvb_stats_poll,
+	.read = smsdvb_stats_read,
+	.release = smsdvb_stats_release,
+	.llseek = generic_file_llseek,
+};
+
+/*
+ * Functions used by smsdvb, in order to create the interfaces
+ */
+
+int smsdvb_debugfs_create(struct smsdvb_client_t *client)
+{
+	struct smscore_device_t *coredev = client->coredev;
+	struct dentry *d;
+	struct smsdvb_debugfs *debug_data;
+
+	if (!smsdvb_debugfs_usb_root || !coredev->is_usb_device)
+		return -ENODEV;
+
+	client->debugfs = debugfs_create_dir(coredev->devpath,
+					     smsdvb_debugfs_usb_root);
+	if (IS_ERR_OR_NULL(client->debugfs)) {
+		pr_info("Unable to create debugfs %s directory.\n",
+			coredev->devpath);
+		return -ENODEV;
+	}
+
+	d = debugfs_create_file("stats", S_IRUGO | S_IWUSR, client->debugfs,
+				client, &debugfs_stats_ops);
+	if (!d) {
+		debugfs_remove(client->debugfs);
+		return -ENOMEM;
+	}
+
+	debug_data = kzalloc(sizeof(*client->debug_data), GFP_KERNEL);
+	if (!debug_data)
+		return -ENOMEM;
+
+	client->debug_data        = debug_data;
+	client->prt_dvb_stats     = smsdvb_print_dvb_stats;
+	client->prt_isdb_stats    = smsdvb_print_isdb_stats;
+	client->prt_isdb_stats_ex = smsdvb_print_isdb_stats_ex;
+
+	init_waitqueue_head(&debug_data->stats_queue);
+	spin_lock_init(&debug_data->lock);
+	kref_init(&debug_data->refcount);
+
+	return 0;
+}
+
+void smsdvb_debugfs_release(struct smsdvb_client_t *client)
+{
+	if (!client->debugfs)
+		return;
+
+	client->prt_dvb_stats     = NULL;
+	client->prt_isdb_stats    = NULL;
+	client->prt_isdb_stats_ex = NULL;
+
+	debugfs_remove_recursive(client->debugfs);
+	kref_put(&client->debug_data->refcount, smsdvb_debugfs_data_release);
+
+	client->debug_data = NULL;
+	client->debugfs = NULL;
+}
+
+int smsdvb_debugfs_register(void)
+{
+	struct dentry *d;
+
+	/*
+	 * FIXME: This was written to debug Siano USB devices. So, it creates
+	 * the debugfs node under <debugfs>/usb.
+	 * A similar logic would be needed for Siano sdio devices, but, in that
+	 * case, usb_debug_root is not a good choice.
+	 *
+	 * Perhaps the right fix here would be to create another sysfs root
+	 * node for sdio-based boards, but this may need some logic at sdio
+	 * subsystem.
+	 */
+	d = debugfs_create_dir("smsdvb", usb_debug_root);
+	if (IS_ERR_OR_NULL(d)) {
+		sms_err("Couldn't create sysfs node for smsdvb");
+		return PTR_ERR(d);
+	} else {
+		smsdvb_debugfs_usb_root = d;
+	}
+	return 0;
+}
+
+void smsdvb_debugfs_unregister(void)
+{
+	debugfs_remove_recursive(smsdvb_debugfs_usb_root);
+	smsdvb_debugfs_usb_root = NULL;
+}
diff --git a/drivers/media/common/siano/smsdvb-main.c b/drivers/media/common/siano/smsdvb-main.c
new file mode 100644
index 0000000..297f1b2
--- /dev/null
+++ b/drivers/media/common/siano/smsdvb-main.c
@@ -0,0 +1,1230 @@
+/****************************************************************
+
+Siano Mobile Silicon, Inc.
+MDTV receiver kernel modules.
+Copyright (C) 2006-2008, Uri Shkolnik
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU 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/module.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <asm/div64.h>
+
+#include "dmxdev.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+
+#include "smscoreapi.h"
+#include "sms-cards.h"
+
+#include "smsdvb.h"
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+static struct list_head g_smsdvb_clients;
+static struct mutex g_smsdvb_clientslock;
+
+static int sms_dbg;
+module_param_named(debug, sms_dbg, int, 0644);
+MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))");
+
+
+u32 sms_to_guard_interval_table[] = {
+	[0] = GUARD_INTERVAL_1_32,
+	[1] = GUARD_INTERVAL_1_16,
+	[2] = GUARD_INTERVAL_1_8,
+	[3] = GUARD_INTERVAL_1_4,
+};
+
+u32 sms_to_code_rate_table[] = {
+	[0] = FEC_1_2,
+	[1] = FEC_2_3,
+	[2] = FEC_3_4,
+	[3] = FEC_5_6,
+	[4] = FEC_7_8,
+};
+
+
+u32 sms_to_hierarchy_table[] = {
+	[0] = HIERARCHY_NONE,
+	[1] = HIERARCHY_1,
+	[2] = HIERARCHY_2,
+	[3] = HIERARCHY_4,
+};
+
+u32 sms_to_modulation_table[] = {
+	[0] = QPSK,
+	[1] = QAM_16,
+	[2] = QAM_64,
+	[3] = DQPSK,
+};
+
+
+/* Events that may come from DVB v3 adapter */
+static void sms_board_dvb3_event(struct smsdvb_client_t *client,
+		enum SMS_DVB3_EVENTS event) {
+
+	struct smscore_device_t *coredev = client->coredev;
+	switch (event) {
+	case DVB3_EVENT_INIT:
+		sms_debug("DVB3_EVENT_INIT");
+		sms_board_event(coredev, BOARD_EVENT_BIND);
+		break;
+	case DVB3_EVENT_SLEEP:
+		sms_debug("DVB3_EVENT_SLEEP");
+		sms_board_event(coredev, BOARD_EVENT_POWER_SUSPEND);
+		break;
+	case DVB3_EVENT_HOTPLUG:
+		sms_debug("DVB3_EVENT_HOTPLUG");
+		sms_board_event(coredev, BOARD_EVENT_POWER_INIT);
+		break;
+	case DVB3_EVENT_FE_LOCK:
+		if (client->event_fe_state != DVB3_EVENT_FE_LOCK) {
+			client->event_fe_state = DVB3_EVENT_FE_LOCK;
+			sms_debug("DVB3_EVENT_FE_LOCK");
+			sms_board_event(coredev, BOARD_EVENT_FE_LOCK);
+		}
+		break;
+	case DVB3_EVENT_FE_UNLOCK:
+		if (client->event_fe_state != DVB3_EVENT_FE_UNLOCK) {
+			client->event_fe_state = DVB3_EVENT_FE_UNLOCK;
+			sms_debug("DVB3_EVENT_FE_UNLOCK");
+			sms_board_event(coredev, BOARD_EVENT_FE_UNLOCK);
+		}
+		break;
+	case DVB3_EVENT_UNC_OK:
+		if (client->event_unc_state != DVB3_EVENT_UNC_OK) {
+			client->event_unc_state = DVB3_EVENT_UNC_OK;
+			sms_debug("DVB3_EVENT_UNC_OK");
+			sms_board_event(coredev, BOARD_EVENT_MULTIPLEX_OK);
+		}
+		break;
+	case DVB3_EVENT_UNC_ERR:
+		if (client->event_unc_state != DVB3_EVENT_UNC_ERR) {
+			client->event_unc_state = DVB3_EVENT_UNC_ERR;
+			sms_debug("DVB3_EVENT_UNC_ERR");
+			sms_board_event(coredev, BOARD_EVENT_MULTIPLEX_ERRORS);
+		}
+		break;
+
+	default:
+		sms_err("Unknown dvb3 api event");
+		break;
+	}
+}
+
+static void smsdvb_stats_not_ready(struct dvb_frontend *fe)
+{
+	struct smsdvb_client_t *client =
+		container_of(fe, struct smsdvb_client_t, frontend);
+	struct smscore_device_t *coredev = client->coredev;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	int i, n_layers;
+
+	switch (smscore_get_device_mode(coredev)) {
+	case DEVICE_MODE_ISDBT:
+	case DEVICE_MODE_ISDBT_BDA:
+		n_layers = 4;
+	default:
+		n_layers = 1;
+	}
+
+	/* Global stats */
+	c->strength.len = 1;
+	c->cnr.len = 1;
+	c->strength.stat[0].scale = FE_SCALE_DECIBEL;
+	c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
+
+	/* Per-layer stats */
+	c->post_bit_error.len = n_layers;
+	c->post_bit_count.len = n_layers;
+	c->block_error.len = n_layers;
+	c->block_count.len = n_layers;
+
+	/*
+	 * Put all of them at FE_SCALE_NOT_AVAILABLE. They're dynamically
+	 * changed when the stats become available.
+	 */
+	for (i = 0; i < n_layers; i++) {
+		c->post_bit_error.stat[i].scale = FE_SCALE_NOT_AVAILABLE;
+		c->post_bit_count.stat[i].scale = FE_SCALE_NOT_AVAILABLE;
+		c->block_error.stat[i].scale = FE_SCALE_NOT_AVAILABLE;
+		c->block_count.stat[i].scale = FE_SCALE_NOT_AVAILABLE;
+	}
+}
+
+static inline int sms_to_mode(u32 mode)
+{
+	switch (mode) {
+	case 2:
+		return TRANSMISSION_MODE_2K;
+	case 4:
+		return TRANSMISSION_MODE_4K;
+	case 8:
+		return TRANSMISSION_MODE_8K;
+	}
+	return TRANSMISSION_MODE_AUTO;
+}
+
+static inline int sms_to_status(u32 is_demod_locked, u32 is_rf_locked)
+{
+	if (is_demod_locked)
+		return FE_HAS_SIGNAL  | FE_HAS_CARRIER | FE_HAS_VITERBI |
+		       FE_HAS_SYNC    | FE_HAS_LOCK;
+
+	if (is_rf_locked)
+		return FE_HAS_SIGNAL | FE_HAS_CARRIER;
+
+	return 0;
+}
+
+static inline u32 sms_to_bw(u32 value)
+{
+	return value * 1000000;
+}
+
+#define convert_from_table(value, table, defval) ({			\
+	u32 __ret;							\
+	if (value < ARRAY_SIZE(table))					\
+		__ret = table[value];					\
+	else								\
+		__ret = defval;						\
+	__ret;								\
+})
+
+#define sms_to_guard_interval(value)					\
+	convert_from_table(value, sms_to_guard_interval_table,		\
+			   GUARD_INTERVAL_AUTO);
+
+#define sms_to_code_rate(value)						\
+	convert_from_table(value, sms_to_code_rate_table,		\
+			   FEC_NONE);
+
+#define sms_to_hierarchy(value)						\
+	convert_from_table(value, sms_to_hierarchy_table,		\
+			   FEC_NONE);
+
+#define sms_to_modulation(value)					\
+	convert_from_table(value, sms_to_modulation_table,		\
+			   FEC_NONE);
+
+static void smsdvb_update_tx_params(struct smsdvb_client_t *client,
+				    struct sms_tx_stats *p)
+{
+	struct dvb_frontend *fe = &client->frontend;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+
+	c->frequency = p->frequency;
+	client->fe_status = sms_to_status(p->is_demod_locked, 0);
+	c->bandwidth_hz = sms_to_bw(p->bandwidth);
+	c->transmission_mode = sms_to_mode(p->transmission_mode);
+	c->guard_interval = sms_to_guard_interval(p->guard_interval);
+	c->code_rate_HP = sms_to_code_rate(p->code_rate);
+	c->code_rate_LP = sms_to_code_rate(p->lp_code_rate);
+	c->hierarchy = sms_to_hierarchy(p->hierarchy);
+	c->modulation = sms_to_modulation(p->constellation);
+}
+
+static void smsdvb_update_per_slices(struct smsdvb_client_t *client,
+				     struct RECEPTION_STATISTICS_PER_SLICES_S *p)
+{
+	struct dvb_frontend *fe = &client->frontend;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	u64 tmp;
+
+	client->fe_status = sms_to_status(p->is_demod_locked, p->is_rf_locked);
+	c->modulation = sms_to_modulation(p->constellation);
+
+	/* signal Strength, in DBm */
+	c->strength.stat[0].uvalue = p->in_band_power * 1000;
+
+	/* Carrier to noise ratio, in DB */
+	c->cnr.stat[0].svalue = p->snr * 1000;
+
+	/* PER/BER requires demod lock */
+	if (!p->is_demod_locked)
+		return;
+
+	/* TS PER */
+	client->last_per = c->block_error.stat[0].uvalue;
+	c->block_error.stat[0].scale = FE_SCALE_COUNTER;
+	c->block_count.stat[0].scale = FE_SCALE_COUNTER;
+	c->block_error.stat[0].uvalue += p->ets_packets;
+	c->block_count.stat[0].uvalue += p->ets_packets + p->ts_packets;
+
+	/* ber */
+	c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
+	c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
+	c->post_bit_error.stat[0].uvalue += p->ber_error_count;
+	c->post_bit_count.stat[0].uvalue += p->ber_bit_count;
+
+	/* Legacy PER/BER */
+	tmp = p->ets_packets * 65535;
+	do_div(tmp, p->ts_packets + p->ets_packets);
+	client->legacy_per = tmp;
+}
+
+static void smsdvb_update_dvb_stats(struct smsdvb_client_t *client,
+				    struct sms_stats *p)
+{
+	struct dvb_frontend *fe = &client->frontend;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+
+	if (client->prt_dvb_stats)
+		client->prt_dvb_stats(client->debug_data, p);
+
+	client->fe_status = sms_to_status(p->is_demod_locked, p->is_rf_locked);
+
+	/* Update DVB modulation parameters */
+	c->frequency = p->frequency;
+	client->fe_status = sms_to_status(p->is_demod_locked, 0);
+	c->bandwidth_hz = sms_to_bw(p->bandwidth);
+	c->transmission_mode = sms_to_mode(p->transmission_mode);
+	c->guard_interval = sms_to_guard_interval(p->guard_interval);
+	c->code_rate_HP = sms_to_code_rate(p->code_rate);
+	c->code_rate_LP = sms_to_code_rate(p->lp_code_rate);
+	c->hierarchy = sms_to_hierarchy(p->hierarchy);
+	c->modulation = sms_to_modulation(p->constellation);
+
+	/* update reception data */
+	c->lna = p->is_external_lna_on ? 1 : 0;
+
+	/* Carrier to noise ratio, in DB */
+	c->cnr.stat[0].svalue = p->SNR * 1000;
+
+	/* signal Strength, in DBm */
+	c->strength.stat[0].uvalue = p->in_band_pwr * 1000;
+
+	/* PER/BER requires demod lock */
+	if (!p->is_demod_locked)
+		return;
+
+	/* TS PER */
+	client->last_per = c->block_error.stat[0].uvalue;
+	c->block_error.stat[0].scale = FE_SCALE_COUNTER;
+	c->block_count.stat[0].scale = FE_SCALE_COUNTER;
+	c->block_error.stat[0].uvalue += p->error_ts_packets;
+	c->block_count.stat[0].uvalue += p->total_ts_packets;
+
+	/* ber */
+	c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
+	c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
+	c->post_bit_error.stat[0].uvalue += p->ber_error_count;
+	c->post_bit_count.stat[0].uvalue += p->ber_bit_count;
+
+	/* Legacy PER/BER */
+	client->legacy_ber = p->ber;
+};
+
+static void smsdvb_update_isdbt_stats(struct smsdvb_client_t *client,
+				      struct sms_isdbt_stats *p)
+{
+	struct dvb_frontend *fe = &client->frontend;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	struct sms_isdbt_layer_stats *lr;
+	int i, n_layers;
+
+	if (client->prt_isdb_stats)
+		client->prt_isdb_stats(client->debug_data, p);
+
+	client->fe_status = sms_to_status(p->is_demod_locked, p->is_rf_locked);
+
+	/*
+	 * Firmware 2.1 seems to report only lock status and
+	 * signal strength. The signal strength indicator is at the
+	 * wrong field.
+	 */
+	if (p->statistics_type == 0) {
+		c->strength.stat[0].uvalue = ((s32)p->transmission_mode) * 1000;
+		c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+		return;
+	}
+
+	/* Update ISDB-T transmission parameters */
+	c->frequency = p->frequency;
+	c->bandwidth_hz = sms_to_bw(p->bandwidth);
+	c->transmission_mode = sms_to_mode(p->transmission_mode);
+	c->guard_interval = sms_to_guard_interval(p->guard_interval);
+	c->isdbt_partial_reception = p->partial_reception ? 1 : 0;
+	n_layers = p->num_of_layers;
+	if (n_layers < 1)
+		n_layers = 1;
+	if (n_layers > 3)
+		n_layers = 3;
+	c->isdbt_layer_enabled = 0;
+
+	/* update reception data */
+	c->lna = p->is_external_lna_on ? 1 : 0;
+
+	/* Carrier to noise ratio, in DB */
+	c->cnr.stat[0].svalue = p->SNR * 1000;
+
+	/* signal Strength, in DBm */
+	c->strength.stat[0].uvalue = p->in_band_pwr * 1000;
+
+	/* PER/BER and per-layer stats require demod lock */
+	if (!p->is_demod_locked)
+		return;
+
+	client->last_per = c->block_error.stat[0].uvalue;
+
+	/* Clears global counters, as the code below will sum it again */
+	c->block_error.stat[0].uvalue = 0;
+	c->block_count.stat[0].uvalue = 0;
+	c->block_error.stat[0].scale = FE_SCALE_COUNTER;
+	c->block_count.stat[0].scale = FE_SCALE_COUNTER;
+	c->post_bit_error.stat[0].uvalue = 0;
+	c->post_bit_count.stat[0].uvalue = 0;
+	c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
+	c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
+
+	for (i = 0; i < n_layers; i++) {
+		lr = &p->layer_info[i];
+
+		/* Update per-layer transmission parameters */
+		if (lr->number_of_segments > 0 && lr->number_of_segments < 13) {
+			c->isdbt_layer_enabled |= 1 << i;
+			c->layer[i].segment_count = lr->number_of_segments;
+		} else {
+			continue;
+		}
+		c->layer[i].modulation = sms_to_modulation(lr->constellation);
+
+		/* TS PER */
+		c->block_error.stat[i + 1].scale = FE_SCALE_COUNTER;
+		c->block_count.stat[i + 1].scale = FE_SCALE_COUNTER;
+		c->block_error.stat[i + 1].uvalue += lr->error_ts_packets;
+		c->block_count.stat[i + 1].uvalue += lr->total_ts_packets;
+
+		/* Update global PER counter */
+		c->block_error.stat[0].uvalue += lr->error_ts_packets;
+		c->block_count.stat[0].uvalue += lr->total_ts_packets;
+
+		/* BER */
+		c->post_bit_error.stat[i + 1].scale = FE_SCALE_COUNTER;
+		c->post_bit_count.stat[i + 1].scale = FE_SCALE_COUNTER;
+		c->post_bit_error.stat[i + 1].uvalue += lr->ber_error_count;
+		c->post_bit_count.stat[i + 1].uvalue += lr->ber_bit_count;
+
+		/* Update global BER counter */
+		c->post_bit_error.stat[0].uvalue += lr->ber_error_count;
+		c->post_bit_count.stat[0].uvalue += lr->ber_bit_count;
+	}
+}
+
+static void smsdvb_update_isdbt_stats_ex(struct smsdvb_client_t *client,
+					 struct sms_isdbt_stats_ex *p)
+{
+	struct dvb_frontend *fe = &client->frontend;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	struct sms_isdbt_layer_stats *lr;
+	int i, n_layers;
+
+	if (client->prt_isdb_stats_ex)
+		client->prt_isdb_stats_ex(client->debug_data, p);
+
+	/* Update ISDB-T transmission parameters */
+	c->frequency = p->frequency;
+	client->fe_status = sms_to_status(p->is_demod_locked, 0);
+	c->bandwidth_hz = sms_to_bw(p->bandwidth);
+	c->transmission_mode = sms_to_mode(p->transmission_mode);
+	c->guard_interval = sms_to_guard_interval(p->guard_interval);
+	c->isdbt_partial_reception = p->partial_reception ? 1 : 0;
+	n_layers = p->num_of_layers;
+	if (n_layers < 1)
+		n_layers = 1;
+	if (n_layers > 3)
+		n_layers = 3;
+	c->isdbt_layer_enabled = 0;
+
+	/* update reception data */
+	c->lna = p->is_external_lna_on ? 1 : 0;
+
+	/* Carrier to noise ratio, in DB */
+	c->cnr.stat[0].svalue = p->SNR * 1000;
+
+	/* signal Strength, in DBm */
+	c->strength.stat[0].uvalue = p->in_band_pwr * 1000;
+
+	/* PER/BER and per-layer stats require demod lock */
+	if (!p->is_demod_locked)
+		return;
+
+	client->last_per = c->block_error.stat[0].uvalue;
+
+	/* Clears global counters, as the code below will sum it again */
+	c->block_error.stat[0].uvalue = 0;
+	c->block_count.stat[0].uvalue = 0;
+	c->block_error.stat[0].scale = FE_SCALE_COUNTER;
+	c->block_count.stat[0].scale = FE_SCALE_COUNTER;
+	c->post_bit_error.stat[0].uvalue = 0;
+	c->post_bit_count.stat[0].uvalue = 0;
+	c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
+	c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
+
+	c->post_bit_error.len = n_layers + 1;
+	c->post_bit_count.len = n_layers + 1;
+	c->block_error.len = n_layers + 1;
+	c->block_count.len = n_layers + 1;
+	for (i = 0; i < n_layers; i++) {
+		lr = &p->layer_info[i];
+
+		/* Update per-layer transmission parameters */
+		if (lr->number_of_segments > 0 && lr->number_of_segments < 13) {
+			c->isdbt_layer_enabled |= 1 << i;
+			c->layer[i].segment_count = lr->number_of_segments;
+		} else {
+			continue;
+		}
+		c->layer[i].modulation = sms_to_modulation(lr->constellation);
+
+		/* TS PER */
+		c->block_error.stat[i + 1].scale = FE_SCALE_COUNTER;
+		c->block_count.stat[i + 1].scale = FE_SCALE_COUNTER;
+		c->block_error.stat[i + 1].uvalue += lr->error_ts_packets;
+		c->block_count.stat[i + 1].uvalue += lr->total_ts_packets;
+
+		/* Update global PER counter */
+		c->block_error.stat[0].uvalue += lr->error_ts_packets;
+		c->block_count.stat[0].uvalue += lr->total_ts_packets;
+
+		/* ber */
+		c->post_bit_error.stat[i + 1].scale = FE_SCALE_COUNTER;
+		c->post_bit_count.stat[i + 1].scale = FE_SCALE_COUNTER;
+		c->post_bit_error.stat[i + 1].uvalue += lr->ber_error_count;
+		c->post_bit_count.stat[i + 1].uvalue += lr->ber_bit_count;
+
+		/* Update global ber counter */
+		c->post_bit_error.stat[0].uvalue += lr->ber_error_count;
+		c->post_bit_count.stat[0].uvalue += lr->ber_bit_count;
+	}
+}
+
+static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb)
+{
+	struct smsdvb_client_t *client = (struct smsdvb_client_t *) context;
+	struct sms_msg_hdr *phdr = (struct sms_msg_hdr *) (((u8 *) cb->p)
+			+ cb->offset);
+	void *p = phdr + 1;
+	struct dvb_frontend *fe = &client->frontend;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	bool is_status_update = false;
+
+	switch (phdr->msg_type) {
+	case MSG_SMS_DVBT_BDA_DATA:
+		/*
+		 * Only feed data to dvb demux if are there any feed listening
+		 * to it and if the device has tuned
+		 */
+		if (client->feed_users && client->has_tuned)
+			dvb_dmx_swfilter(&client->demux, p,
+					 cb->size - sizeof(struct sms_msg_hdr));
+		break;
+
+	case MSG_SMS_RF_TUNE_RES:
+	case MSG_SMS_ISDBT_TUNE_RES:
+		complete(&client->tune_done);
+		break;
+
+	case MSG_SMS_SIGNAL_DETECTED_IND:
+		client->fe_status = FE_HAS_SIGNAL  | FE_HAS_CARRIER |
+				    FE_HAS_VITERBI | FE_HAS_SYNC    |
+				    FE_HAS_LOCK;
+
+		is_status_update = true;
+		break;
+
+	case MSG_SMS_NO_SIGNAL_IND:
+		client->fe_status = 0;
+
+		is_status_update = true;
+		break;
+
+	case MSG_SMS_TRANSMISSION_IND:
+		smsdvb_update_tx_params(client, p);
+
+		is_status_update = true;
+		break;
+
+	case MSG_SMS_HO_PER_SLICES_IND:
+		smsdvb_update_per_slices(client, p);
+
+		is_status_update = true;
+		break;
+
+	case MSG_SMS_GET_STATISTICS_RES:
+		switch (smscore_get_device_mode(client->coredev)) {
+		case DEVICE_MODE_ISDBT:
+		case DEVICE_MODE_ISDBT_BDA:
+			smsdvb_update_isdbt_stats(client, p);
+			break;
+		default:
+			/* Skip sms_msg_statistics_info:request_result field */
+			smsdvb_update_dvb_stats(client, p + sizeof(u32));
+		}
+
+		is_status_update = true;
+		break;
+
+	/* Only for ISDB-T */
+	case MSG_SMS_GET_STATISTICS_EX_RES:
+		/* Skip sms_msg_statistics_info:request_result field? */
+		smsdvb_update_isdbt_stats_ex(client, p + sizeof(u32));
+		is_status_update = true;
+		break;
+	default:
+		sms_info("message not handled");
+	}
+	smscore_putbuffer(client->coredev, cb);
+
+	if (is_status_update) {
+		if (client->fe_status & FE_HAS_LOCK) {
+			sms_board_dvb3_event(client, DVB3_EVENT_FE_LOCK);
+			if (client->last_per == c->block_error.stat[0].uvalue)
+				sms_board_dvb3_event(client, DVB3_EVENT_UNC_OK);
+			else
+				sms_board_dvb3_event(client, DVB3_EVENT_UNC_ERR);
+			client->has_tuned = true;
+		} else {
+			smsdvb_stats_not_ready(fe);
+			client->has_tuned = false;
+			sms_board_dvb3_event(client, DVB3_EVENT_FE_UNLOCK);
+		}
+		complete(&client->stats_done);
+	}
+
+	return 0;
+}
+
+static void smsdvb_unregister_client(struct smsdvb_client_t *client)
+{
+	/* must be called under clientslock */
+
+	list_del(&client->entry);
+
+	smsdvb_debugfs_release(client);
+	smscore_unregister_client(client->smsclient);
+	dvb_unregister_frontend(&client->frontend);
+	dvb_dmxdev_release(&client->dmxdev);
+	dvb_dmx_release(&client->demux);
+	dvb_unregister_adapter(&client->adapter);
+	kfree(client);
+}
+
+static void smsdvb_onremove(void *context)
+{
+	kmutex_lock(&g_smsdvb_clientslock);
+
+	smsdvb_unregister_client((struct smsdvb_client_t *) context);
+
+	kmutex_unlock(&g_smsdvb_clientslock);
+}
+
+static int smsdvb_start_feed(struct dvb_demux_feed *feed)
+{
+	struct smsdvb_client_t *client =
+		container_of(feed->demux, struct smsdvb_client_t, demux);
+	struct sms_msg_data pid_msg;
+
+	sms_debug("add pid %d(%x)",
+		  feed->pid, feed->pid);
+
+	client->feed_users++;
+
+	pid_msg.x_msg_header.msg_src_id = DVBT_BDA_CONTROL_MSG_ID;
+	pid_msg.x_msg_header.msg_dst_id = HIF_TASK;
+	pid_msg.x_msg_header.msg_flags = 0;
+	pid_msg.x_msg_header.msg_type  = MSG_SMS_ADD_PID_FILTER_REQ;
+	pid_msg.x_msg_header.msg_length = sizeof(pid_msg);
+	pid_msg.msg_data[0] = feed->pid;
+
+	return smsclient_sendrequest(client->smsclient,
+				     &pid_msg, sizeof(pid_msg));
+}
+
+static int smsdvb_stop_feed(struct dvb_demux_feed *feed)
+{
+	struct smsdvb_client_t *client =
+		container_of(feed->demux, struct smsdvb_client_t, demux);
+	struct sms_msg_data pid_msg;
+
+	sms_debug("remove pid %d(%x)",
+		  feed->pid, feed->pid);
+
+	client->feed_users--;
+
+	pid_msg.x_msg_header.msg_src_id = DVBT_BDA_CONTROL_MSG_ID;
+	pid_msg.x_msg_header.msg_dst_id = HIF_TASK;
+	pid_msg.x_msg_header.msg_flags = 0;
+	pid_msg.x_msg_header.msg_type  = MSG_SMS_REMOVE_PID_FILTER_REQ;
+	pid_msg.x_msg_header.msg_length = sizeof(pid_msg);
+	pid_msg.msg_data[0] = feed->pid;
+
+	return smsclient_sendrequest(client->smsclient,
+				     &pid_msg, sizeof(pid_msg));
+}
+
+static int smsdvb_sendrequest_and_wait(struct smsdvb_client_t *client,
+					void *buffer, size_t size,
+					struct completion *completion)
+{
+	int rc;
+
+	rc = smsclient_sendrequest(client->smsclient, buffer, size);
+	if (rc < 0)
+		return rc;
+
+	return wait_for_completion_timeout(completion,
+					   msecs_to_jiffies(2000)) ?
+						0 : -ETIME;
+}
+
+static int smsdvb_send_statistics_request(struct smsdvb_client_t *client)
+{
+	int rc;
+	struct sms_msg_hdr msg;
+
+	/* Don't request stats too fast */
+	if (client->get_stats_jiffies &&
+	   (!time_after(jiffies, client->get_stats_jiffies)))
+		return 0;
+	client->get_stats_jiffies = jiffies + msecs_to_jiffies(100);
+
+	msg.msg_src_id = DVBT_BDA_CONTROL_MSG_ID;
+	msg.msg_dst_id = HIF_TASK;
+	msg.msg_flags = 0;
+	msg.msg_length = sizeof(msg);
+
+	switch (smscore_get_device_mode(client->coredev)) {
+	case DEVICE_MODE_ISDBT:
+	case DEVICE_MODE_ISDBT_BDA:
+		/*
+		* Check for firmware version, to avoid breaking for old cards
+		*/
+		if (client->coredev->fw_version >= 0x800)
+			msg.msg_type = MSG_SMS_GET_STATISTICS_EX_REQ;
+		else
+			msg.msg_type = MSG_SMS_GET_STATISTICS_REQ;
+		break;
+	default:
+		msg.msg_type = MSG_SMS_GET_STATISTICS_REQ;
+	}
+
+	rc = smsdvb_sendrequest_and_wait(client, &msg, sizeof(msg),
+					 &client->stats_done);
+
+	return rc;
+}
+
+static inline int led_feedback(struct smsdvb_client_t *client)
+{
+	if (!(client->fe_status & FE_HAS_LOCK))
+		return sms_board_led_feedback(client->coredev, SMS_LED_OFF);
+
+	return sms_board_led_feedback(client->coredev,
+				     (client->legacy_ber == 0) ?
+				     SMS_LED_HI : SMS_LED_LO);
+}
+
+static int smsdvb_read_status(struct dvb_frontend *fe, fe_status_t *stat)
+{
+	int rc;
+	struct smsdvb_client_t *client;
+	client = container_of(fe, struct smsdvb_client_t, frontend);
+
+	rc = smsdvb_send_statistics_request(client);
+
+	*stat = client->fe_status;
+
+	led_feedback(client);
+
+	return rc;
+}
+
+static int smsdvb_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	int rc;
+	struct smsdvb_client_t *client;
+
+	client = container_of(fe, struct smsdvb_client_t, frontend);
+
+	rc = smsdvb_send_statistics_request(client);
+
+	*ber = client->legacy_ber;
+
+	led_feedback(client);
+
+	return rc;
+}
+
+static int smsdvb_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	int rc;
+	s32 power = (s32) c->strength.stat[0].uvalue;
+	struct smsdvb_client_t *client;
+
+	client = container_of(fe, struct smsdvb_client_t, frontend);
+
+	rc = smsdvb_send_statistics_request(client);
+
+	if (power < -95)
+		*strength = 0;
+		else if (power > -29)
+			*strength = 65535;
+		else
+			*strength = (power + 95) * 65535 / 66;
+
+	led_feedback(client);
+
+	return rc;
+}
+
+static int smsdvb_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	int rc;
+	struct smsdvb_client_t *client;
+
+	client = container_of(fe, struct smsdvb_client_t, frontend);
+
+	rc = smsdvb_send_statistics_request(client);
+
+	/* Preferred scale for SNR with legacy API: 0.1 dB */
+	*snr = ((u32)c->cnr.stat[0].svalue) / 100;
+
+	led_feedback(client);
+
+	return rc;
+}
+
+static int smsdvb_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+	int rc;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	struct smsdvb_client_t *client;
+
+	client = container_of(fe, struct smsdvb_client_t, frontend);
+
+	rc = smsdvb_send_statistics_request(client);
+
+	*ucblocks = c->block_error.stat[0].uvalue;
+
+	led_feedback(client);
+
+	return rc;
+}
+
+static int smsdvb_get_tune_settings(struct dvb_frontend *fe,
+				    struct dvb_frontend_tune_settings *tune)
+{
+	sms_debug("");
+
+	tune->min_delay_ms = 400;
+	tune->step_size = 250000;
+	tune->max_drift = 0;
+	return 0;
+}
+
+static int smsdvb_dvbt_set_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	struct smsdvb_client_t *client =
+		container_of(fe, struct smsdvb_client_t, frontend);
+
+	struct {
+		struct sms_msg_hdr	msg;
+		u32		Data[3];
+	} msg;
+
+	int ret;
+
+	client->fe_status = 0;
+	client->event_fe_state = -1;
+	client->event_unc_state = -1;
+	fe->dtv_property_cache.delivery_system = SYS_DVBT;
+
+	msg.msg.msg_src_id = DVBT_BDA_CONTROL_MSG_ID;
+	msg.msg.msg_dst_id = HIF_TASK;
+	msg.msg.msg_flags = 0;
+	msg.msg.msg_type = MSG_SMS_RF_TUNE_REQ;
+	msg.msg.msg_length = sizeof(msg);
+	msg.Data[0] = c->frequency;
+	msg.Data[2] = 12000000;
+
+	sms_info("%s: freq %d band %d", __func__, c->frequency,
+		 c->bandwidth_hz);
+
+	switch (c->bandwidth_hz / 1000000) {
+	case 8:
+		msg.Data[1] = BW_8_MHZ;
+		break;
+	case 7:
+		msg.Data[1] = BW_7_MHZ;
+		break;
+	case 6:
+		msg.Data[1] = BW_6_MHZ;
+		break;
+	case 0:
+		return -EOPNOTSUPP;
+	default:
+		return -EINVAL;
+	}
+	/* Disable LNA, if any. An error is returned if no LNA is present */
+	ret = sms_board_lna_control(client->coredev, 0);
+	if (ret == 0) {
+		fe_status_t status;
+
+		/* tune with LNA off at first */
+		ret = smsdvb_sendrequest_and_wait(client, &msg, sizeof(msg),
+						  &client->tune_done);
+
+		smsdvb_read_status(fe, &status);
+
+		if (status & FE_HAS_LOCK)
+			return ret;
+
+		/* previous tune didn't lock - enable LNA and tune again */
+		sms_board_lna_control(client->coredev, 1);
+	}
+
+	return smsdvb_sendrequest_and_wait(client, &msg, sizeof(msg),
+					   &client->tune_done);
+}
+
+static int smsdvb_isdbt_set_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	struct smsdvb_client_t *client =
+		container_of(fe, struct smsdvb_client_t, frontend);
+	int board_id = smscore_get_board_id(client->coredev);
+	struct sms_board *board = sms_get_board(board_id);
+	enum sms_device_type_st type = board->type;
+	int ret;
+
+	struct {
+		struct sms_msg_hdr	msg;
+		u32		Data[4];
+	} msg;
+
+	fe->dtv_property_cache.delivery_system = SYS_ISDBT;
+
+	msg.msg.msg_src_id  = DVBT_BDA_CONTROL_MSG_ID;
+	msg.msg.msg_dst_id  = HIF_TASK;
+	msg.msg.msg_flags  = 0;
+	msg.msg.msg_type   = MSG_SMS_ISDBT_TUNE_REQ;
+	msg.msg.msg_length = sizeof(msg);
+
+	if (c->isdbt_sb_segment_idx == -1)
+		c->isdbt_sb_segment_idx = 0;
+
+	if (!c->isdbt_layer_enabled)
+		c->isdbt_layer_enabled = 7;
+
+	msg.Data[0] = c->frequency;
+	msg.Data[1] = BW_ISDBT_1SEG;
+	msg.Data[2] = 12000000;
+	msg.Data[3] = c->isdbt_sb_segment_idx;
+
+	if (c->isdbt_partial_reception) {
+		if ((type == SMS_PELE || type == SMS_RIO) &&
+		    c->isdbt_sb_segment_count > 3)
+			msg.Data[1] = BW_ISDBT_13SEG;
+		else if (c->isdbt_sb_segment_count > 1)
+			msg.Data[1] = BW_ISDBT_3SEG;
+	} else if (type == SMS_PELE || type == SMS_RIO)
+		msg.Data[1] = BW_ISDBT_13SEG;
+
+	c->bandwidth_hz = 6000000;
+
+	sms_info("%s: freq %d segwidth %d segindex %d", __func__,
+		 c->frequency, c->isdbt_sb_segment_count,
+		 c->isdbt_sb_segment_idx);
+
+	/* Disable LNA, if any. An error is returned if no LNA is present */
+	ret = sms_board_lna_control(client->coredev, 0);
+	if (ret == 0) {
+		fe_status_t status;
+
+		/* tune with LNA off at first */
+		ret = smsdvb_sendrequest_and_wait(client, &msg, sizeof(msg),
+						  &client->tune_done);
+
+		smsdvb_read_status(fe, &status);
+
+		if (status & FE_HAS_LOCK)
+			return ret;
+
+		/* previous tune didn't lock - enable LNA and tune again */
+		sms_board_lna_control(client->coredev, 1);
+	}
+	return smsdvb_sendrequest_and_wait(client, &msg, sizeof(msg),
+					   &client->tune_done);
+}
+
+static int smsdvb_set_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	struct smsdvb_client_t *client =
+		container_of(fe, struct smsdvb_client_t, frontend);
+	struct smscore_device_t *coredev = client->coredev;
+
+	smsdvb_stats_not_ready(fe);
+	c->strength.stat[0].uvalue = 0;
+	c->cnr.stat[0].uvalue = 0;
+
+	client->has_tuned = false;
+
+	switch (smscore_get_device_mode(coredev)) {
+	case DEVICE_MODE_DVBT:
+	case DEVICE_MODE_DVBT_BDA:
+		return smsdvb_dvbt_set_frontend(fe);
+	case DEVICE_MODE_ISDBT:
+	case DEVICE_MODE_ISDBT_BDA:
+		return smsdvb_isdbt_set_frontend(fe);
+	default:
+		return -EINVAL;
+	}
+}
+
+/* Nothing to do here, as stats are automatically updated */
+static int smsdvb_get_frontend(struct dvb_frontend *fe)
+{
+	return 0;
+}
+
+static int smsdvb_init(struct dvb_frontend *fe)
+{
+	struct smsdvb_client_t *client =
+		container_of(fe, struct smsdvb_client_t, frontend);
+
+	sms_board_power(client->coredev, 1);
+
+	sms_board_dvb3_event(client, DVB3_EVENT_INIT);
+	return 0;
+}
+
+static int smsdvb_sleep(struct dvb_frontend *fe)
+{
+	struct smsdvb_client_t *client =
+		container_of(fe, struct smsdvb_client_t, frontend);
+
+	sms_board_led_feedback(client->coredev, SMS_LED_OFF);
+	sms_board_power(client->coredev, 0);
+
+	sms_board_dvb3_event(client, DVB3_EVENT_SLEEP);
+
+	return 0;
+}
+
+static void smsdvb_release(struct dvb_frontend *fe)
+{
+	/* do nothing */
+}
+
+static struct dvb_frontend_ops smsdvb_fe_ops = {
+	.info = {
+		.name			= "Siano Mobile Digital MDTV Receiver",
+		.frequency_min		= 44250000,
+		.frequency_max		= 867250000,
+		.frequency_stepsize	= 250000,
+		.caps = FE_CAN_INVERSION_AUTO |
+			FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+			FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
+			FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
+			FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO |
+			FE_CAN_GUARD_INTERVAL_AUTO |
+			FE_CAN_RECOVER |
+			FE_CAN_HIERARCHY_AUTO,
+	},
+
+	.release = smsdvb_release,
+
+	.set_frontend = smsdvb_set_frontend,
+	.get_frontend = smsdvb_get_frontend,
+	.get_tune_settings = smsdvb_get_tune_settings,
+
+	.read_status = smsdvb_read_status,
+	.read_ber = smsdvb_read_ber,
+	.read_signal_strength = smsdvb_read_signal_strength,
+	.read_snr = smsdvb_read_snr,
+	.read_ucblocks = smsdvb_read_ucblocks,
+
+	.init = smsdvb_init,
+	.sleep = smsdvb_sleep,
+};
+
+static int smsdvb_hotplug(struct smscore_device_t *coredev,
+			  struct device *device, int arrival)
+{
+	struct smsclient_params_t params;
+	struct smsdvb_client_t *client;
+	int rc;
+
+	/* device removal handled by onremove callback */
+	if (!arrival)
+		return 0;
+	client = kzalloc(sizeof(struct smsdvb_client_t), GFP_KERNEL);
+	if (!client) {
+		sms_err("kmalloc() failed");
+		return -ENOMEM;
+	}
+
+	/* register dvb adapter */
+	rc = dvb_register_adapter(&client->adapter,
+				  sms_get_board(
+					smscore_get_board_id(coredev))->name,
+				  THIS_MODULE, device, adapter_nr);
+	if (rc < 0) {
+		sms_err("dvb_register_adapter() failed %d", rc);
+		goto adapter_error;
+	}
+
+	/* init dvb demux */
+	client->demux.dmx.capabilities = DMX_TS_FILTERING;
+	client->demux.filternum = 32; /* todo: nova ??? */
+	client->demux.feednum = 32;
+	client->demux.start_feed = smsdvb_start_feed;
+	client->demux.stop_feed = smsdvb_stop_feed;
+
+	rc = dvb_dmx_init(&client->demux);
+	if (rc < 0) {
+		sms_err("dvb_dmx_init failed %d", rc);
+		goto dvbdmx_error;
+	}
+
+	/* init dmxdev */
+	client->dmxdev.filternum = 32;
+	client->dmxdev.demux = &client->demux.dmx;
+	client->dmxdev.capabilities = 0;
+
+	rc = dvb_dmxdev_init(&client->dmxdev, &client->adapter);
+	if (rc < 0) {
+		sms_err("dvb_dmxdev_init failed %d", rc);
+		goto dmxdev_error;
+	}
+
+	/* init and register frontend */
+	memcpy(&client->frontend.ops, &smsdvb_fe_ops,
+	       sizeof(struct dvb_frontend_ops));
+
+	switch (smscore_get_device_mode(coredev)) {
+	case DEVICE_MODE_DVBT:
+	case DEVICE_MODE_DVBT_BDA:
+		client->frontend.ops.delsys[0] = SYS_DVBT;
+		break;
+	case DEVICE_MODE_ISDBT:
+	case DEVICE_MODE_ISDBT_BDA:
+		client->frontend.ops.delsys[0] = SYS_ISDBT;
+		break;
+	}
+
+	rc = dvb_register_frontend(&client->adapter, &client->frontend);
+	if (rc < 0) {
+		sms_err("frontend registration failed %d", rc);
+		goto frontend_error;
+	}
+
+	params.initial_id = 1;
+	params.data_type = MSG_SMS_DVBT_BDA_DATA;
+	params.onresponse_handler = smsdvb_onresponse;
+	params.onremove_handler = smsdvb_onremove;
+	params.context = client;
+
+	rc = smscore_register_client(coredev, &params, &client->smsclient);
+	if (rc < 0) {
+		sms_err("smscore_register_client() failed %d", rc);
+		goto client_error;
+	}
+
+	client->coredev = coredev;
+
+	init_completion(&client->tune_done);
+	init_completion(&client->stats_done);
+
+	kmutex_lock(&g_smsdvb_clientslock);
+
+	list_add(&client->entry, &g_smsdvb_clients);
+
+	kmutex_unlock(&g_smsdvb_clientslock);
+
+	client->event_fe_state = -1;
+	client->event_unc_state = -1;
+	sms_board_dvb3_event(client, DVB3_EVENT_HOTPLUG);
+
+	sms_info("success");
+	sms_board_setup(coredev);
+
+	if (smsdvb_debugfs_create(client) < 0)
+		sms_info("failed to create debugfs node");
+
+	return 0;
+
+client_error:
+	dvb_unregister_frontend(&client->frontend);
+
+frontend_error:
+	dvb_dmxdev_release(&client->dmxdev);
+
+dmxdev_error:
+	dvb_dmx_release(&client->demux);
+
+dvbdmx_error:
+	dvb_unregister_adapter(&client->adapter);
+
+adapter_error:
+	kfree(client);
+	return rc;
+}
+
+static int __init smsdvb_module_init(void)
+{
+	int rc;
+
+	INIT_LIST_HEAD(&g_smsdvb_clients);
+	kmutex_init(&g_smsdvb_clientslock);
+
+	smsdvb_debugfs_register();
+
+	rc = smscore_register_hotplug(smsdvb_hotplug);
+
+	sms_debug("");
+
+	return rc;
+}
+
+static void __exit smsdvb_module_exit(void)
+{
+	smscore_unregister_hotplug(smsdvb_hotplug);
+
+	kmutex_lock(&g_smsdvb_clientslock);
+
+	while (!list_empty(&g_smsdvb_clients))
+		smsdvb_unregister_client((struct smsdvb_client_t *)g_smsdvb_clients.next);
+
+	smsdvb_debugfs_unregister();
+
+	kmutex_unlock(&g_smsdvb_clientslock);
+}
+
+module_init(smsdvb_module_init);
+module_exit(smsdvb_module_exit);
+
+MODULE_DESCRIPTION("SMS DVB subsystem adaptation module");
+MODULE_AUTHOR("Siano Mobile Silicon, Inc. (uris@siano-ms.com)");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/common/siano/smsdvb.c b/drivers/media/common/siano/smsdvb.c
deleted file mode 100644
index aa77e54..0000000
--- a/drivers/media/common/siano/smsdvb.c
+++ /dev/null
@@ -1,1078 +0,0 @@
-/****************************************************************
-
-Siano Mobile Silicon, Inc.
-MDTV receiver kernel modules.
-Copyright (C) 2006-2008, Uri Shkolnik
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 2 of the License, or
-(at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU 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/module.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-
-#include "dmxdev.h"
-#include "dvbdev.h"
-#include "dvb_demux.h"
-#include "dvb_frontend.h"
-
-#include "smscoreapi.h"
-#include "smsendian.h"
-#include "sms-cards.h"
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-struct smsdvb_client_t {
-	struct list_head entry;
-
-	struct smscore_device_t *coredev;
-	struct smscore_client_t *smsclient;
-
-	struct dvb_adapter      adapter;
-	struct dvb_demux        demux;
-	struct dmxdev           dmxdev;
-	struct dvb_frontend     frontend;
-
-	fe_status_t             fe_status;
-
-	struct completion       tune_done;
-
-	struct SMSHOSTLIB_STATISTICS_DVB_S sms_stat_dvb;
-	int event_fe_state;
-	int event_unc_state;
-};
-
-static struct list_head g_smsdvb_clients;
-static struct mutex g_smsdvb_clientslock;
-
-static int sms_dbg;
-module_param_named(debug, sms_dbg, int, 0644);
-MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))");
-
-/* Events that may come from DVB v3 adapter */
-static void sms_board_dvb3_event(struct smsdvb_client_t *client,
-		enum SMS_DVB3_EVENTS event) {
-
-	struct smscore_device_t *coredev = client->coredev;
-	switch (event) {
-	case DVB3_EVENT_INIT:
-		sms_debug("DVB3_EVENT_INIT");
-		sms_board_event(coredev, BOARD_EVENT_BIND);
-		break;
-	case DVB3_EVENT_SLEEP:
-		sms_debug("DVB3_EVENT_SLEEP");
-		sms_board_event(coredev, BOARD_EVENT_POWER_SUSPEND);
-		break;
-	case DVB3_EVENT_HOTPLUG:
-		sms_debug("DVB3_EVENT_HOTPLUG");
-		sms_board_event(coredev, BOARD_EVENT_POWER_INIT);
-		break;
-	case DVB3_EVENT_FE_LOCK:
-		if (client->event_fe_state != DVB3_EVENT_FE_LOCK) {
-			client->event_fe_state = DVB3_EVENT_FE_LOCK;
-			sms_debug("DVB3_EVENT_FE_LOCK");
-			sms_board_event(coredev, BOARD_EVENT_FE_LOCK);
-		}
-		break;
-	case DVB3_EVENT_FE_UNLOCK:
-		if (client->event_fe_state != DVB3_EVENT_FE_UNLOCK) {
-			client->event_fe_state = DVB3_EVENT_FE_UNLOCK;
-			sms_debug("DVB3_EVENT_FE_UNLOCK");
-			sms_board_event(coredev, BOARD_EVENT_FE_UNLOCK);
-		}
-		break;
-	case DVB3_EVENT_UNC_OK:
-		if (client->event_unc_state != DVB3_EVENT_UNC_OK) {
-			client->event_unc_state = DVB3_EVENT_UNC_OK;
-			sms_debug("DVB3_EVENT_UNC_OK");
-			sms_board_event(coredev, BOARD_EVENT_MULTIPLEX_OK);
-		}
-		break;
-	case DVB3_EVENT_UNC_ERR:
-		if (client->event_unc_state != DVB3_EVENT_UNC_ERR) {
-			client->event_unc_state = DVB3_EVENT_UNC_ERR;
-			sms_debug("DVB3_EVENT_UNC_ERR");
-			sms_board_event(coredev, BOARD_EVENT_MULTIPLEX_ERRORS);
-		}
-		break;
-
-	default:
-		sms_err("Unknown dvb3 api event");
-		break;
-	}
-}
-
-
-static void smsdvb_update_dvb_stats(struct RECEPTION_STATISTICS_S *pReceptionData,
-				   struct SMSHOSTLIB_STATISTICS_ST *p)
-{
-	if (sms_dbg & 2) {
-		printk(KERN_DEBUG "Reserved = %d", p->Reserved);
-		printk(KERN_DEBUG "IsRfLocked = %d", p->IsRfLocked);
-		printk(KERN_DEBUG "IsDemodLocked = %d", p->IsDemodLocked);
-		printk(KERN_DEBUG "IsExternalLNAOn = %d", p->IsExternalLNAOn);
-		printk(KERN_DEBUG "SNR = %d", p->SNR);
-		printk(KERN_DEBUG "BER = %d", p->BER);
-		printk(KERN_DEBUG "FIB_CRC = %d", p->FIB_CRC);
-		printk(KERN_DEBUG "TS_PER = %d", p->TS_PER);
-		printk(KERN_DEBUG "MFER = %d", p->MFER);
-		printk(KERN_DEBUG "RSSI = %d", p->RSSI);
-		printk(KERN_DEBUG "InBandPwr = %d", p->InBandPwr);
-		printk(KERN_DEBUG "CarrierOffset = %d", p->CarrierOffset);
-		printk(KERN_DEBUG "Frequency = %d", p->Frequency);
-		printk(KERN_DEBUG "Bandwidth = %d", p->Bandwidth);
-		printk(KERN_DEBUG "TransmissionMode = %d", p->TransmissionMode);
-		printk(KERN_DEBUG "ModemState = %d", p->ModemState);
-		printk(KERN_DEBUG "GuardInterval = %d", p->GuardInterval);
-		printk(KERN_DEBUG "CodeRate = %d", p->CodeRate);
-		printk(KERN_DEBUG "LPCodeRate = %d", p->LPCodeRate);
-		printk(KERN_DEBUG "Hierarchy = %d", p->Hierarchy);
-		printk(KERN_DEBUG "Constellation = %d", p->Constellation);
-		printk(KERN_DEBUG "BurstSize = %d", p->BurstSize);
-		printk(KERN_DEBUG "BurstDuration = %d", p->BurstDuration);
-		printk(KERN_DEBUG "BurstCycleTime = %d", p->BurstCycleTime);
-		printk(KERN_DEBUG "CalculatedBurstCycleTime = %d", p->CalculatedBurstCycleTime);
-		printk(KERN_DEBUG "NumOfRows = %d", p->NumOfRows);
-		printk(KERN_DEBUG "NumOfPaddCols = %d", p->NumOfPaddCols);
-		printk(KERN_DEBUG "NumOfPunctCols = %d", p->NumOfPunctCols);
-		printk(KERN_DEBUG "ErrorTSPackets = %d", p->ErrorTSPackets);
-		printk(KERN_DEBUG "TotalTSPackets = %d", p->TotalTSPackets);
-		printk(KERN_DEBUG "NumOfValidMpeTlbs = %d", p->NumOfValidMpeTlbs);
-		printk(KERN_DEBUG "NumOfInvalidMpeTlbs = %d", p->NumOfInvalidMpeTlbs);
-		printk(KERN_DEBUG "NumOfCorrectedMpeTlbs = %d", p->NumOfCorrectedMpeTlbs);
-		printk(KERN_DEBUG "BERErrorCount = %d", p->BERErrorCount);
-		printk(KERN_DEBUG "BERBitCount = %d", p->BERBitCount);
-		printk(KERN_DEBUG "SmsToHostTxErrors = %d", p->SmsToHostTxErrors);
-		printk(KERN_DEBUG "PreBER = %d", p->PreBER);
-		printk(KERN_DEBUG "CellId = %d", p->CellId);
-		printk(KERN_DEBUG "DvbhSrvIndHP = %d", p->DvbhSrvIndHP);
-		printk(KERN_DEBUG "DvbhSrvIndLP = %d", p->DvbhSrvIndLP);
-		printk(KERN_DEBUG "NumMPEReceived = %d", p->NumMPEReceived);
-	}
-
-	pReceptionData->IsDemodLocked = p->IsDemodLocked;
-
-	pReceptionData->SNR = p->SNR;
-	pReceptionData->BER = p->BER;
-	pReceptionData->BERErrorCount = p->BERErrorCount;
-	pReceptionData->InBandPwr = p->InBandPwr;
-	pReceptionData->ErrorTSPackets = p->ErrorTSPackets;
-};
-
-
-static void smsdvb_update_isdbt_stats(struct RECEPTION_STATISTICS_S *pReceptionData,
-				    struct SMSHOSTLIB_STATISTICS_ISDBT_ST *p)
-{
-	int i;
-
-	if (sms_dbg & 2) {
-		printk(KERN_DEBUG "IsRfLocked = %d", p->IsRfLocked);
-		printk(KERN_DEBUG "IsDemodLocked = %d", p->IsDemodLocked);
-		printk(KERN_DEBUG "IsExternalLNAOn = %d", p->IsExternalLNAOn);
-		printk(KERN_DEBUG "SNR = %d", p->SNR);
-		printk(KERN_DEBUG "RSSI = %d", p->RSSI);
-		printk(KERN_DEBUG "InBandPwr = %d", p->InBandPwr);
-		printk(KERN_DEBUG "CarrierOffset = %d", p->CarrierOffset);
-		printk(KERN_DEBUG "Frequency = %d", p->Frequency);
-		printk(KERN_DEBUG "Bandwidth = %d", p->Bandwidth);
-		printk(KERN_DEBUG "TransmissionMode = %d", p->TransmissionMode);
-		printk(KERN_DEBUG "ModemState = %d", p->ModemState);
-		printk(KERN_DEBUG "GuardInterval = %d", p->GuardInterval);
-		printk(KERN_DEBUG "SystemType = %d", p->SystemType);
-		printk(KERN_DEBUG "PartialReception = %d", p->PartialReception);
-		printk(KERN_DEBUG "NumOfLayers = %d", p->NumOfLayers);
-		printk(KERN_DEBUG "SmsToHostTxErrors = %d", p->SmsToHostTxErrors);
-
-		for (i = 0; i < 3; i++) {
-			printk(KERN_DEBUG "%d: CodeRate = %d", i, p->LayerInfo[i].CodeRate);
-			printk(KERN_DEBUG "%d: Constellation = %d", i, p->LayerInfo[i].Constellation);
-			printk(KERN_DEBUG "%d: BER = %d", i, p->LayerInfo[i].BER);
-			printk(KERN_DEBUG "%d: BERErrorCount = %d", i, p->LayerInfo[i].BERErrorCount);
-			printk(KERN_DEBUG "%d: BERBitCount = %d", i, p->LayerInfo[i].BERBitCount);
-			printk(KERN_DEBUG "%d: PreBER = %d", i, p->LayerInfo[i].PreBER);
-			printk(KERN_DEBUG "%d: TS_PER = %d", i, p->LayerInfo[i].TS_PER);
-			printk(KERN_DEBUG "%d: ErrorTSPackets = %d", i, p->LayerInfo[i].ErrorTSPackets);
-			printk(KERN_DEBUG "%d: TotalTSPackets = %d", i, p->LayerInfo[i].TotalTSPackets);
-			printk(KERN_DEBUG "%d: TILdepthI = %d", i, p->LayerInfo[i].TILdepthI);
-			printk(KERN_DEBUG "%d: NumberOfSegments = %d", i, p->LayerInfo[i].NumberOfSegments);
-			printk(KERN_DEBUG "%d: TMCCErrors = %d", i, p->LayerInfo[i].TMCCErrors);
-		}
-	}
-
-	pReceptionData->IsDemodLocked = p->IsDemodLocked;
-
-	pReceptionData->SNR = p->SNR;
-	pReceptionData->InBandPwr = p->InBandPwr;
-
-	pReceptionData->ErrorTSPackets = 0;
-	pReceptionData->BER = 0;
-	pReceptionData->BERErrorCount = 0;
-	for (i = 0; i < 3; i++) {
-		pReceptionData->BER += p->LayerInfo[i].BER;
-		pReceptionData->BERErrorCount += p->LayerInfo[i].BERErrorCount;
-		pReceptionData->ErrorTSPackets += p->LayerInfo[i].ErrorTSPackets;
-	}
-}
-
-static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb)
-{
-	struct smsdvb_client_t *client = (struct smsdvb_client_t *) context;
-	struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *) (((u8 *) cb->p)
-			+ cb->offset);
-	u32 *pMsgData = (u32 *) phdr + 1;
-	/*u32 MsgDataLen = phdr->msgLength - sizeof(struct SmsMsgHdr_ST);*/
-	bool is_status_update = false;
-
-	smsendian_handle_rx_message((struct SmsMsgData_ST *) phdr);
-
-	switch (phdr->msgType) {
-	case MSG_SMS_DVBT_BDA_DATA:
-		dvb_dmx_swfilter(&client->demux, (u8 *)(phdr + 1),
-				 cb->size - sizeof(struct SmsMsgHdr_ST));
-		break;
-
-	case MSG_SMS_RF_TUNE_RES:
-	case MSG_SMS_ISDBT_TUNE_RES:
-		complete(&client->tune_done);
-		break;
-
-	case MSG_SMS_SIGNAL_DETECTED_IND:
-		sms_info("MSG_SMS_SIGNAL_DETECTED_IND");
-		client->sms_stat_dvb.TransmissionData.IsDemodLocked = true;
-		is_status_update = true;
-		break;
-
-	case MSG_SMS_NO_SIGNAL_IND:
-		sms_info("MSG_SMS_NO_SIGNAL_IND");
-		client->sms_stat_dvb.TransmissionData.IsDemodLocked = false;
-		is_status_update = true;
-		break;
-
-	case MSG_SMS_TRANSMISSION_IND: {
-		sms_info("MSG_SMS_TRANSMISSION_IND");
-
-		pMsgData++;
-		memcpy(&client->sms_stat_dvb.TransmissionData, pMsgData,
-				sizeof(struct TRANSMISSION_STATISTICS_S));
-
-		/* Mo need to correct guard interval
-		 * (as opposed to old statistics message).
-		 */
-		CORRECT_STAT_BANDWIDTH(client->sms_stat_dvb.TransmissionData);
-		CORRECT_STAT_TRANSMISSON_MODE(
-				client->sms_stat_dvb.TransmissionData);
-		is_status_update = true;
-		break;
-	}
-	case MSG_SMS_HO_PER_SLICES_IND: {
-		struct RECEPTION_STATISTICS_S *pReceptionData =
-				&client->sms_stat_dvb.ReceptionData;
-		struct SRVM_SIGNAL_STATUS_S SignalStatusData;
-
-		/*sms_info("MSG_SMS_HO_PER_SLICES_IND");*/
-		pMsgData++;
-		SignalStatusData.result = pMsgData[0];
-		SignalStatusData.snr = pMsgData[1];
-		SignalStatusData.inBandPower = (s32) pMsgData[2];
-		SignalStatusData.tsPackets = pMsgData[3];
-		SignalStatusData.etsPackets = pMsgData[4];
-		SignalStatusData.constellation = pMsgData[5];
-		SignalStatusData.hpCode = pMsgData[6];
-		SignalStatusData.tpsSrvIndLP = pMsgData[7] & 0x03;
-		SignalStatusData.tpsSrvIndHP = pMsgData[8] & 0x03;
-		SignalStatusData.cellId = pMsgData[9] & 0xFFFF;
-		SignalStatusData.reason = pMsgData[10];
-		SignalStatusData.requestId = pMsgData[11];
-		pReceptionData->IsRfLocked = pMsgData[16];
-		pReceptionData->IsDemodLocked = pMsgData[17];
-		pReceptionData->ModemState = pMsgData[12];
-		pReceptionData->SNR = pMsgData[1];
-		pReceptionData->BER = pMsgData[13];
-		pReceptionData->RSSI = pMsgData[14];
-		CORRECT_STAT_RSSI(client->sms_stat_dvb.ReceptionData);
-
-		pReceptionData->InBandPwr = (s32) pMsgData[2];
-		pReceptionData->CarrierOffset = (s32) pMsgData[15];
-		pReceptionData->TotalTSPackets = pMsgData[3];
-		pReceptionData->ErrorTSPackets = pMsgData[4];
-
-		/* TS PER */
-		if ((SignalStatusData.tsPackets + SignalStatusData.etsPackets)
-				> 0) {
-			pReceptionData->TS_PER = (SignalStatusData.etsPackets
-					* 100) / (SignalStatusData.tsPackets
-					+ SignalStatusData.etsPackets);
-		} else {
-			pReceptionData->TS_PER = 0;
-		}
-
-		pReceptionData->BERBitCount = pMsgData[18];
-		pReceptionData->BERErrorCount = pMsgData[19];
-
-		pReceptionData->MRC_SNR = pMsgData[20];
-		pReceptionData->MRC_InBandPwr = pMsgData[21];
-		pReceptionData->MRC_RSSI = pMsgData[22];
-
-		is_status_update = true;
-		break;
-	}
-	case MSG_SMS_GET_STATISTICS_RES: {
-		union {
-			struct SMSHOSTLIB_STATISTICS_ISDBT_ST  isdbt;
-			struct SmsMsgStatisticsInfo_ST         dvb;
-		} *p = (void *) (phdr + 1);
-		struct RECEPTION_STATISTICS_S *pReceptionData =
-				&client->sms_stat_dvb.ReceptionData;
-
-		sms_info("MSG_SMS_GET_STATISTICS_RES");
-
-		is_status_update = true;
-
-		switch (smscore_get_device_mode(client->coredev)) {
-		case DEVICE_MODE_ISDBT:
-		case DEVICE_MODE_ISDBT_BDA:
-			smsdvb_update_isdbt_stats(pReceptionData, &p->isdbt);
-			break;
-		default:
-			smsdvb_update_dvb_stats(pReceptionData, &p->dvb.Stat);
-		}
-		if (!pReceptionData->IsDemodLocked) {
-			pReceptionData->SNR = 0;
-			pReceptionData->BER = 0;
-			pReceptionData->BERErrorCount = 0;
-			pReceptionData->InBandPwr = 0;
-			pReceptionData->ErrorTSPackets = 0;
-		}
-
-		complete(&client->tune_done);
-		break;
-	}
-	default:
-		sms_info("Unhandled message %d", phdr->msgType);
-
-	}
-	smscore_putbuffer(client->coredev, cb);
-
-	if (is_status_update) {
-		if (client->sms_stat_dvb.ReceptionData.IsDemodLocked) {
-			client->fe_status = FE_HAS_SIGNAL | FE_HAS_CARRIER
-				| FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
-			sms_board_dvb3_event(client, DVB3_EVENT_FE_LOCK);
-			if (client->sms_stat_dvb.ReceptionData.ErrorTSPackets
-					== 0)
-				sms_board_dvb3_event(client, DVB3_EVENT_UNC_OK);
-			else
-				sms_board_dvb3_event(client,
-						DVB3_EVENT_UNC_ERR);
-
-		} else {
-			if (client->sms_stat_dvb.ReceptionData.IsRfLocked)
-				client->fe_status = FE_HAS_SIGNAL | FE_HAS_CARRIER;
-			else
-				client->fe_status = 0;
-			sms_board_dvb3_event(client, DVB3_EVENT_FE_UNLOCK);
-		}
-	}
-
-	return 0;
-}
-
-static void smsdvb_unregister_client(struct smsdvb_client_t *client)
-{
-	/* must be called under clientslock */
-
-	list_del(&client->entry);
-
-	smscore_unregister_client(client->smsclient);
-	dvb_unregister_frontend(&client->frontend);
-	dvb_dmxdev_release(&client->dmxdev);
-	dvb_dmx_release(&client->demux);
-	dvb_unregister_adapter(&client->adapter);
-	kfree(client);
-}
-
-static void smsdvb_onremove(void *context)
-{
-	kmutex_lock(&g_smsdvb_clientslock);
-
-	smsdvb_unregister_client((struct smsdvb_client_t *) context);
-
-	kmutex_unlock(&g_smsdvb_clientslock);
-}
-
-static int smsdvb_start_feed(struct dvb_demux_feed *feed)
-{
-	struct smsdvb_client_t *client =
-		container_of(feed->demux, struct smsdvb_client_t, demux);
-	struct SmsMsgData_ST PidMsg;
-
-	sms_debug("add pid %d(%x)",
-		  feed->pid, feed->pid);
-
-	PidMsg.xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
-	PidMsg.xMsgHeader.msgDstId = HIF_TASK;
-	PidMsg.xMsgHeader.msgFlags = 0;
-	PidMsg.xMsgHeader.msgType  = MSG_SMS_ADD_PID_FILTER_REQ;
-	PidMsg.xMsgHeader.msgLength = sizeof(PidMsg);
-	PidMsg.msgData[0] = feed->pid;
-
-	smsendian_handle_tx_message((struct SmsMsgHdr_ST *)&PidMsg);
-	return smsclient_sendrequest(client->smsclient,
-				     &PidMsg, sizeof(PidMsg));
-}
-
-static int smsdvb_stop_feed(struct dvb_demux_feed *feed)
-{
-	struct smsdvb_client_t *client =
-		container_of(feed->demux, struct smsdvb_client_t, demux);
-	struct SmsMsgData_ST PidMsg;
-
-	sms_debug("remove pid %d(%x)",
-		  feed->pid, feed->pid);
-
-	PidMsg.xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
-	PidMsg.xMsgHeader.msgDstId = HIF_TASK;
-	PidMsg.xMsgHeader.msgFlags = 0;
-	PidMsg.xMsgHeader.msgType  = MSG_SMS_REMOVE_PID_FILTER_REQ;
-	PidMsg.xMsgHeader.msgLength = sizeof(PidMsg);
-	PidMsg.msgData[0] = feed->pid;
-
-	smsendian_handle_tx_message((struct SmsMsgHdr_ST *)&PidMsg);
-	return smsclient_sendrequest(client->smsclient,
-				     &PidMsg, sizeof(PidMsg));
-}
-
-static int smsdvb_sendrequest_and_wait(struct smsdvb_client_t *client,
-					void *buffer, size_t size,
-					struct completion *completion)
-{
-	int rc;
-
-	smsendian_handle_tx_message((struct SmsMsgHdr_ST *)buffer);
-	rc = smsclient_sendrequest(client->smsclient, buffer, size);
-	if (rc < 0)
-		return rc;
-
-	return wait_for_completion_timeout(completion,
-					   msecs_to_jiffies(2000)) ?
-						0 : -ETIME;
-}
-
-static int smsdvb_send_statistics_request(struct smsdvb_client_t *client)
-{
-	int rc;
-	struct SmsMsgHdr_ST Msg = { MSG_SMS_GET_STATISTICS_REQ,
-				    DVBT_BDA_CONTROL_MSG_ID,
-				    HIF_TASK,
-				    sizeof(struct SmsMsgHdr_ST), 0 };
-
-	rc = smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
-					  &client->tune_done);
-
-	return rc;
-}
-
-static inline int led_feedback(struct smsdvb_client_t *client)
-{
-	if (client->fe_status & FE_HAS_LOCK)
-		return sms_board_led_feedback(client->coredev,
-			(client->sms_stat_dvb.ReceptionData.BER
-			== 0) ? SMS_LED_HI : SMS_LED_LO);
-	else
-		return sms_board_led_feedback(client->coredev, SMS_LED_OFF);
-}
-
-static int smsdvb_read_status(struct dvb_frontend *fe, fe_status_t *stat)
-{
-	int rc;
-	struct smsdvb_client_t *client;
-	client = container_of(fe, struct smsdvb_client_t, frontend);
-
-	rc = smsdvb_send_statistics_request(client);
-
-	*stat = client->fe_status;
-
-	led_feedback(client);
-
-	return rc;
-}
-
-static int smsdvb_read_ber(struct dvb_frontend *fe, u32 *ber)
-{
-	int rc;
-	struct smsdvb_client_t *client;
-	client = container_of(fe, struct smsdvb_client_t, frontend);
-
-	rc = smsdvb_send_statistics_request(client);
-
-	*ber = client->sms_stat_dvb.ReceptionData.BER;
-
-	led_feedback(client);
-
-	return rc;
-}
-
-static int smsdvb_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
-{
-	int rc;
-
-	struct smsdvb_client_t *client;
-	client = container_of(fe, struct smsdvb_client_t, frontend);
-
-	rc = smsdvb_send_statistics_request(client);
-
-	if (client->sms_stat_dvb.ReceptionData.InBandPwr < -95)
-		*strength = 0;
-		else if (client->sms_stat_dvb.ReceptionData.InBandPwr > -29)
-			*strength = 100;
-		else
-			*strength =
-				(client->sms_stat_dvb.ReceptionData.InBandPwr
-				+ 95) * 3 / 2;
-
-	led_feedback(client);
-
-	return rc;
-}
-
-static int smsdvb_read_snr(struct dvb_frontend *fe, u16 *snr)
-{
-	int rc;
-	struct smsdvb_client_t *client;
-	client = container_of(fe, struct smsdvb_client_t, frontend);
-
-	rc = smsdvb_send_statistics_request(client);
-
-	*snr = client->sms_stat_dvb.ReceptionData.SNR;
-
-	led_feedback(client);
-
-	return rc;
-}
-
-static int smsdvb_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
-{
-	int rc;
-	struct smsdvb_client_t *client;
-	client = container_of(fe, struct smsdvb_client_t, frontend);
-
-	rc = smsdvb_send_statistics_request(client);
-
-	*ucblocks = client->sms_stat_dvb.ReceptionData.ErrorTSPackets;
-
-	led_feedback(client);
-
-	return rc;
-}
-
-static int smsdvb_get_tune_settings(struct dvb_frontend *fe,
-				    struct dvb_frontend_tune_settings *tune)
-{
-	sms_debug("");
-
-	tune->min_delay_ms = 400;
-	tune->step_size = 250000;
-	tune->max_drift = 0;
-	return 0;
-}
-
-static int smsdvb_dvbt_set_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	struct smsdvb_client_t *client =
-		container_of(fe, struct smsdvb_client_t, frontend);
-
-	struct {
-		struct SmsMsgHdr_ST	Msg;
-		u32		Data[3];
-	} Msg;
-
-	int ret;
-
-	client->fe_status = FE_HAS_SIGNAL;
-	client->event_fe_state = -1;
-	client->event_unc_state = -1;
-	fe->dtv_property_cache.delivery_system = SYS_DVBT;
-
-	Msg.Msg.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
-	Msg.Msg.msgDstId = HIF_TASK;
-	Msg.Msg.msgFlags = 0;
-	Msg.Msg.msgType = MSG_SMS_RF_TUNE_REQ;
-	Msg.Msg.msgLength = sizeof(Msg);
-	Msg.Data[0] = c->frequency;
-	Msg.Data[2] = 12000000;
-
-	sms_info("%s: freq %d band %d", __func__, c->frequency,
-		 c->bandwidth_hz);
-
-	switch (c->bandwidth_hz / 1000000) {
-	case 8:
-		Msg.Data[1] = BW_8_MHZ;
-		break;
-	case 7:
-		Msg.Data[1] = BW_7_MHZ;
-		break;
-	case 6:
-		Msg.Data[1] = BW_6_MHZ;
-		break;
-	case 0:
-		return -EOPNOTSUPP;
-	default:
-		return -EINVAL;
-	}
-	/* Disable LNA, if any. An error is returned if no LNA is present */
-	ret = sms_board_lna_control(client->coredev, 0);
-	if (ret == 0) {
-		fe_status_t status;
-
-		/* tune with LNA off at first */
-		ret = smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
-						  &client->tune_done);
-
-		smsdvb_read_status(fe, &status);
-
-		if (status & FE_HAS_LOCK)
-			return ret;
-
-		/* previous tune didn't lock - enable LNA and tune again */
-		sms_board_lna_control(client->coredev, 1);
-	}
-
-	return smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
-					   &client->tune_done);
-}
-
-static int smsdvb_isdbt_set_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	struct smsdvb_client_t *client =
-		container_of(fe, struct smsdvb_client_t, frontend);
-
-	struct {
-		struct SmsMsgHdr_ST	Msg;
-		u32		Data[4];
-	} Msg;
-
-	fe->dtv_property_cache.delivery_system = SYS_ISDBT;
-
-	Msg.Msg.msgSrcId  = DVBT_BDA_CONTROL_MSG_ID;
-	Msg.Msg.msgDstId  = HIF_TASK;
-	Msg.Msg.msgFlags  = 0;
-	Msg.Msg.msgType   = MSG_SMS_ISDBT_TUNE_REQ;
-	Msg.Msg.msgLength = sizeof(Msg);
-
-	if (c->isdbt_sb_segment_idx == -1)
-		c->isdbt_sb_segment_idx = 0;
-
-	switch (c->isdbt_sb_segment_count) {
-	case 3:
-		Msg.Data[1] = BW_ISDBT_3SEG;
-		break;
-	case 1:
-		Msg.Data[1] = BW_ISDBT_1SEG;
-		break;
-	case 0:	/* AUTO */
-		switch (c->bandwidth_hz / 1000000) {
-		case 8:
-		case 7:
-			c->isdbt_sb_segment_count = 3;
-			Msg.Data[1] = BW_ISDBT_3SEG;
-			break;
-		case 6:
-			c->isdbt_sb_segment_count = 1;
-			Msg.Data[1] = BW_ISDBT_1SEG;
-			break;
-		default: /* Assumes 6 MHZ bw */
-			c->isdbt_sb_segment_count = 1;
-			c->bandwidth_hz = 6000;
-			Msg.Data[1] = BW_ISDBT_1SEG;
-			break;
-		}
-		break;
-	default:
-		sms_info("Segment count %d not supported", c->isdbt_sb_segment_count);
-		return -EINVAL;
-	}
-
-	Msg.Data[0] = c->frequency;
-	Msg.Data[2] = 12000000;
-	Msg.Data[3] = c->isdbt_sb_segment_idx;
-
-	sms_info("%s: freq %d segwidth %d segindex %d\n", __func__,
-		 c->frequency, c->isdbt_sb_segment_count,
-		 c->isdbt_sb_segment_idx);
-
-	return smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
-					   &client->tune_done);
-}
-
-static int smsdvb_set_frontend(struct dvb_frontend *fe)
-{
-	struct smsdvb_client_t *client =
-		container_of(fe, struct smsdvb_client_t, frontend);
-	struct smscore_device_t *coredev = client->coredev;
-
-	switch (smscore_get_device_mode(coredev)) {
-	case DEVICE_MODE_DVBT:
-	case DEVICE_MODE_DVBT_BDA:
-		return smsdvb_dvbt_set_frontend(fe);
-	case DEVICE_MODE_ISDBT:
-	case DEVICE_MODE_ISDBT_BDA:
-		return smsdvb_isdbt_set_frontend(fe);
-	default:
-		return -EINVAL;
-	}
-}
-
-static int smsdvb_get_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
-	struct smsdvb_client_t *client =
-		container_of(fe, struct smsdvb_client_t, frontend);
-	struct smscore_device_t *coredev = client->coredev;
-	struct TRANSMISSION_STATISTICS_S *td =
-		&client->sms_stat_dvb.TransmissionData;
-
-	switch (smscore_get_device_mode(coredev)) {
-	case DEVICE_MODE_DVBT:
-	case DEVICE_MODE_DVBT_BDA:
-		fep->frequency = td->Frequency;
-
-		switch (td->Bandwidth) {
-		case 6:
-			fep->bandwidth_hz = 6000000;
-			break;
-		case 7:
-			fep->bandwidth_hz = 7000000;
-			break;
-		case 8:
-			fep->bandwidth_hz = 8000000;
-			break;
-		}
-
-		switch (td->TransmissionMode) {
-		case 2:
-			fep->transmission_mode = TRANSMISSION_MODE_2K;
-			break;
-		case 8:
-			fep->transmission_mode = TRANSMISSION_MODE_8K;
-		}
-
-		switch (td->GuardInterval) {
-		case 0:
-			fep->guard_interval = GUARD_INTERVAL_1_32;
-			break;
-		case 1:
-			fep->guard_interval = GUARD_INTERVAL_1_16;
-			break;
-		case 2:
-			fep->guard_interval = GUARD_INTERVAL_1_8;
-			break;
-		case 3:
-			fep->guard_interval = GUARD_INTERVAL_1_4;
-			break;
-		}
-
-		switch (td->CodeRate) {
-		case 0:
-			fep->code_rate_HP = FEC_1_2;
-			break;
-		case 1:
-			fep->code_rate_HP = FEC_2_3;
-			break;
-		case 2:
-			fep->code_rate_HP = FEC_3_4;
-			break;
-		case 3:
-			fep->code_rate_HP = FEC_5_6;
-			break;
-		case 4:
-			fep->code_rate_HP = FEC_7_8;
-			break;
-		}
-
-		switch (td->LPCodeRate) {
-		case 0:
-			fep->code_rate_LP = FEC_1_2;
-			break;
-		case 1:
-			fep->code_rate_LP = FEC_2_3;
-			break;
-		case 2:
-			fep->code_rate_LP = FEC_3_4;
-			break;
-		case 3:
-			fep->code_rate_LP = FEC_5_6;
-			break;
-		case 4:
-			fep->code_rate_LP = FEC_7_8;
-			break;
-		}
-
-		switch (td->Constellation) {
-		case 0:
-			fep->modulation = QPSK;
-			break;
-		case 1:
-			fep->modulation = QAM_16;
-			break;
-		case 2:
-			fep->modulation = QAM_64;
-			break;
-		}
-
-		switch (td->Hierarchy) {
-		case 0:
-			fep->hierarchy = HIERARCHY_NONE;
-			break;
-		case 1:
-			fep->hierarchy = HIERARCHY_1;
-			break;
-		case 2:
-			fep->hierarchy = HIERARCHY_2;
-			break;
-		case 3:
-			fep->hierarchy = HIERARCHY_4;
-			break;
-		}
-
-		fep->inversion = INVERSION_AUTO;
-		break;
-	case DEVICE_MODE_ISDBT:
-	case DEVICE_MODE_ISDBT_BDA:
-		fep->frequency = td->Frequency;
-		fep->bandwidth_hz = 6000000;
-		/* todo: retrive the other parameters */
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int smsdvb_init(struct dvb_frontend *fe)
-{
-	struct smsdvb_client_t *client =
-		container_of(fe, struct smsdvb_client_t, frontend);
-
-	sms_board_power(client->coredev, 1);
-
-	sms_board_dvb3_event(client, DVB3_EVENT_INIT);
-	return 0;
-}
-
-static int smsdvb_sleep(struct dvb_frontend *fe)
-{
-	struct smsdvb_client_t *client =
-		container_of(fe, struct smsdvb_client_t, frontend);
-
-	sms_board_led_feedback(client->coredev, SMS_LED_OFF);
-	sms_board_power(client->coredev, 0);
-
-	sms_board_dvb3_event(client, DVB3_EVENT_SLEEP);
-
-	return 0;
-}
-
-static void smsdvb_release(struct dvb_frontend *fe)
-{
-	/* do nothing */
-}
-
-static struct dvb_frontend_ops smsdvb_fe_ops = {
-	.info = {
-		.name			= "Siano Mobile Digital MDTV Receiver",
-		.frequency_min		= 44250000,
-		.frequency_max		= 867250000,
-		.frequency_stepsize	= 250000,
-		.caps = FE_CAN_INVERSION_AUTO |
-			FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
-			FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
-			FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
-			FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO |
-			FE_CAN_GUARD_INTERVAL_AUTO |
-			FE_CAN_RECOVER |
-			FE_CAN_HIERARCHY_AUTO,
-	},
-
-	.release = smsdvb_release,
-
-	.set_frontend = smsdvb_set_frontend,
-	.get_frontend = smsdvb_get_frontend,
-	.get_tune_settings = smsdvb_get_tune_settings,
-
-	.read_status = smsdvb_read_status,
-	.read_ber = smsdvb_read_ber,
-	.read_signal_strength = smsdvb_read_signal_strength,
-	.read_snr = smsdvb_read_snr,
-	.read_ucblocks = smsdvb_read_ucblocks,
-
-	.init = smsdvb_init,
-	.sleep = smsdvb_sleep,
-};
-
-static int smsdvb_hotplug(struct smscore_device_t *coredev,
-			  struct device *device, int arrival)
-{
-	struct smsclient_params_t params;
-	struct smsdvb_client_t *client;
-	int rc;
-
-	/* device removal handled by onremove callback */
-	if (!arrival)
-		return 0;
-	client = kzalloc(sizeof(struct smsdvb_client_t), GFP_KERNEL);
-	if (!client) {
-		sms_err("kmalloc() failed");
-		return -ENOMEM;
-	}
-
-	/* register dvb adapter */
-	rc = dvb_register_adapter(&client->adapter,
-				  sms_get_board(
-					smscore_get_board_id(coredev))->name,
-				  THIS_MODULE, device, adapter_nr);
-	if (rc < 0) {
-		sms_err("dvb_register_adapter() failed %d", rc);
-		goto adapter_error;
-	}
-
-	/* init dvb demux */
-	client->demux.dmx.capabilities = DMX_TS_FILTERING;
-	client->demux.filternum = 32; /* todo: nova ??? */
-	client->demux.feednum = 32;
-	client->demux.start_feed = smsdvb_start_feed;
-	client->demux.stop_feed = smsdvb_stop_feed;
-
-	rc = dvb_dmx_init(&client->demux);
-	if (rc < 0) {
-		sms_err("dvb_dmx_init failed %d", rc);
-		goto dvbdmx_error;
-	}
-
-	/* init dmxdev */
-	client->dmxdev.filternum = 32;
-	client->dmxdev.demux = &client->demux.dmx;
-	client->dmxdev.capabilities = 0;
-
-	rc = dvb_dmxdev_init(&client->dmxdev, &client->adapter);
-	if (rc < 0) {
-		sms_err("dvb_dmxdev_init failed %d", rc);
-		goto dmxdev_error;
-	}
-
-	/* init and register frontend */
-	memcpy(&client->frontend.ops, &smsdvb_fe_ops,
-	       sizeof(struct dvb_frontend_ops));
-
-	switch (smscore_get_device_mode(coredev)) {
-	case DEVICE_MODE_DVBT:
-	case DEVICE_MODE_DVBT_BDA:
-		client->frontend.ops.delsys[0] = SYS_DVBT;
-		break;
-	case DEVICE_MODE_ISDBT:
-	case DEVICE_MODE_ISDBT_BDA:
-		client->frontend.ops.delsys[0] = SYS_ISDBT;
-		break;
-	}
-
-	rc = dvb_register_frontend(&client->adapter, &client->frontend);
-	if (rc < 0) {
-		sms_err("frontend registration failed %d", rc);
-		goto frontend_error;
-	}
-
-	params.initial_id = 1;
-	params.data_type = MSG_SMS_DVBT_BDA_DATA;
-	params.onresponse_handler = smsdvb_onresponse;
-	params.onremove_handler = smsdvb_onremove;
-	params.context = client;
-
-	rc = smscore_register_client(coredev, &params, &client->smsclient);
-	if (rc < 0) {
-		sms_err("smscore_register_client() failed %d", rc);
-		goto client_error;
-	}
-
-	client->coredev = coredev;
-
-	init_completion(&client->tune_done);
-
-	kmutex_lock(&g_smsdvb_clientslock);
-
-	list_add(&client->entry, &g_smsdvb_clients);
-
-	kmutex_unlock(&g_smsdvb_clientslock);
-
-	client->event_fe_state = -1;
-	client->event_unc_state = -1;
-	sms_board_dvb3_event(client, DVB3_EVENT_HOTPLUG);
-
-	sms_info("success");
-	sms_board_setup(coredev);
-
-	return 0;
-
-client_error:
-	dvb_unregister_frontend(&client->frontend);
-
-frontend_error:
-	dvb_dmxdev_release(&client->dmxdev);
-
-dmxdev_error:
-	dvb_dmx_release(&client->demux);
-
-dvbdmx_error:
-	dvb_unregister_adapter(&client->adapter);
-
-adapter_error:
-	kfree(client);
-	return rc;
-}
-
-static int __init smsdvb_module_init(void)
-{
-	int rc;
-
-	INIT_LIST_HEAD(&g_smsdvb_clients);
-	kmutex_init(&g_smsdvb_clientslock);
-
-	rc = smscore_register_hotplug(smsdvb_hotplug);
-
-	sms_debug("");
-
-	return rc;
-}
-
-static void __exit smsdvb_module_exit(void)
-{
-	smscore_unregister_hotplug(smsdvb_hotplug);
-
-	kmutex_lock(&g_smsdvb_clientslock);
-
-	while (!list_empty(&g_smsdvb_clients))
-	       smsdvb_unregister_client(
-			(struct smsdvb_client_t *) g_smsdvb_clients.next);
-
-	kmutex_unlock(&g_smsdvb_clientslock);
-}
-
-module_init(smsdvb_module_init);
-module_exit(smsdvb_module_exit);
-
-MODULE_DESCRIPTION("SMS DVB subsystem adaptation module");
-MODULE_AUTHOR("Siano Mobile Silicon, Inc. (uris@siano-ms.com)");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/common/siano/smsdvb.h b/drivers/media/common/siano/smsdvb.h
new file mode 100644
index 0000000..92c413b
--- /dev/null
+++ b/drivers/media/common/siano/smsdvb.h
@@ -0,0 +1,130 @@
+/***********************************************************************
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+
+ *  This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU 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/>.
+ *
+ ***********************************************************************/
+
+struct smsdvb_debugfs;
+struct smsdvb_client_t;
+
+typedef void (*sms_prt_dvb_stats_t)(struct smsdvb_debugfs *debug_data,
+				    struct sms_stats *p);
+
+typedef void (*sms_prt_isdb_stats_t)(struct smsdvb_debugfs *debug_data,
+				     struct sms_isdbt_stats *p);
+
+typedef void (*sms_prt_isdb_stats_ex_t)
+			(struct smsdvb_debugfs *debug_data,
+			 struct sms_isdbt_stats_ex *p);
+
+
+struct smsdvb_client_t {
+	struct list_head entry;
+
+	struct smscore_device_t *coredev;
+	struct smscore_client_t *smsclient;
+
+	struct dvb_adapter      adapter;
+	struct dvb_demux        demux;
+	struct dmxdev           dmxdev;
+	struct dvb_frontend     frontend;
+
+	fe_status_t             fe_status;
+
+	struct completion       tune_done;
+	struct completion       stats_done;
+
+	int last_per;
+
+	int legacy_ber, legacy_per;
+
+	int event_fe_state;
+	int event_unc_state;
+
+	unsigned long		get_stats_jiffies;
+
+	int			feed_users;
+	bool			has_tuned;
+
+	/* stats debugfs data */
+	struct dentry		*debugfs;
+
+	struct smsdvb_debugfs	*debug_data;
+
+	sms_prt_dvb_stats_t	prt_dvb_stats;
+	sms_prt_isdb_stats_t	prt_isdb_stats;
+	sms_prt_isdb_stats_ex_t	prt_isdb_stats_ex;
+};
+
+/*
+ * This struct is a mix of struct sms_rx_stats_ex and
+ * struct sms_srvm_signal_status.
+ * It was obtained by comparing the way it was filled by the original code
+ */
+struct RECEPTION_STATISTICS_PER_SLICES_S {
+	u32 result;
+	u32 snr;
+	s32 in_band_power;
+	u32 ts_packets;
+	u32 ets_packets;
+	u32 constellation;
+	u32 hp_code;
+	u32 tps_srv_ind_lp;
+	u32 tps_srv_ind_hp;
+	u32 cell_id;
+	u32 reason;
+	u32 request_id;
+	u32 modem_state;		/* from SMSHOSTLIB_DVB_MODEM_STATE_ET */
+
+	u32 ber;		/* Post Viterbi BER [1E-5] */
+	s32 RSSI;		/* dBm */
+	s32 carrier_offset;	/* Carrier Offset in bin/1024 */
+
+	u32 is_rf_locked;		/* 0 - not locked, 1 - locked */
+	u32 is_demod_locked;	/* 0 - not locked, 1 - locked */
+
+	u32 ber_bit_count;	/* Total number of SYNC bits. */
+	u32 ber_error_count;	/* Number of erronous SYNC bits. */
+
+	s32 MRC_SNR;		/* dB */
+	s32 mrc_in_band_pwr;	/* In band power in dBM */
+	s32 MRC_RSSI;		/* dBm */
+};
+
+/* From smsdvb-debugfs.c */
+#ifdef CONFIG_SMS_SIANO_DEBUGFS
+
+int smsdvb_debugfs_create(struct smsdvb_client_t *client);
+void smsdvb_debugfs_release(struct smsdvb_client_t *client);
+int smsdvb_debugfs_register(void);
+void smsdvb_debugfs_unregister(void);
+
+#else
+
+static inline int smsdvb_debugfs_create(struct smsdvb_client_t *client)
+{
+	return 0;
+}
+
+static inline void smsdvb_debugfs_release(struct smsdvb_client_t *client) {}
+
+static inline int smsdvb_debugfs_register(void)
+{
+	return 0;
+};
+
+static inline void smsdvb_debugfs_unregister(void) {};
+
+#endif
+
diff --git a/drivers/media/common/siano/smsendian.c b/drivers/media/common/siano/smsendian.c
index e2657c2..bfe831c 100644
--- a/drivers/media/common/siano/smsendian.c
+++ b/drivers/media/common/siano/smsendian.c
@@ -28,23 +28,23 @@
 void smsendian_handle_tx_message(void *buffer)
 {
 #ifdef __BIG_ENDIAN
-	struct SmsMsgData_ST *msg = (struct SmsMsgData_ST *)buffer;
+	struct sms_msg_data *msg = (struct sms_msg_data *)buffer;
 	int i;
-	int msgWords;
+	int msg_words;
 
-	switch (msg->xMsgHeader.msgType) {
+	switch (msg->x_msg_header.msg_type) {
 	case MSG_SMS_DATA_DOWNLOAD_REQ:
 	{
-		msg->msgData[0] = le32_to_cpu(msg->msgData[0]);
+		msg->msg_data[0] = le32_to_cpu(msg->msg_data[0]);
 		break;
 	}
 
 	default:
-		msgWords = (msg->xMsgHeader.msgLength -
-				sizeof(struct SmsMsgHdr_ST))/4;
+		msg_words = (msg->x_msg_header.msg_length -
+				sizeof(struct sms_msg_hdr))/4;
 
-		for (i = 0; i < msgWords; i++)
-			msg->msgData[i] = le32_to_cpu(msg->msgData[i]);
+		for (i = 0; i < msg_words; i++)
+			msg->msg_data[i] = le32_to_cpu(msg->msg_data[i]);
 
 		break;
 	}
@@ -55,16 +55,16 @@ EXPORT_SYMBOL_GPL(smsendian_handle_tx_message);
 void smsendian_handle_rx_message(void *buffer)
 {
 #ifdef __BIG_ENDIAN
-	struct SmsMsgData_ST *msg = (struct SmsMsgData_ST *)buffer;
+	struct sms_msg_data *msg = (struct sms_msg_data *)buffer;
 	int i;
-	int msgWords;
+	int msg_words;
 
-	switch (msg->xMsgHeader.msgType) {
+	switch (msg->x_msg_header.msg_type) {
 	case MSG_SMS_GET_VERSION_EX_RES:
 	{
-		struct SmsVersionRes_ST *ver =
-			(struct SmsVersionRes_ST *) msg;
-		ver->ChipModel = le16_to_cpu(ver->ChipModel);
+		struct sms_version_res *ver =
+			(struct sms_version_res *) msg;
+		ver->chip_model = le16_to_cpu(ver->chip_model);
 		break;
 	}
 
@@ -77,11 +77,11 @@ void smsendian_handle_rx_message(void *buffer)
 
 	default:
 	{
-		msgWords = (msg->xMsgHeader.msgLength -
-				sizeof(struct SmsMsgHdr_ST))/4;
+		msg_words = (msg->x_msg_header.msg_length -
+				sizeof(struct sms_msg_hdr))/4;
 
-		for (i = 0; i < msgWords; i++)
-			msg->msgData[i] = le32_to_cpu(msg->msgData[i]);
+		for (i = 0; i < msg_words; i++)
+			msg->msg_data[i] = le32_to_cpu(msg->msg_data[i]);
 
 		break;
 	}
@@ -93,11 +93,11 @@ EXPORT_SYMBOL_GPL(smsendian_handle_rx_message);
 void smsendian_handle_message_header(void *msg)
 {
 #ifdef __BIG_ENDIAN
-	struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *)msg;
+	struct sms_msg_hdr *phdr = (struct sms_msg_hdr *)msg;
 
-	phdr->msgType = le16_to_cpu(phdr->msgType);
-	phdr->msgLength = le16_to_cpu(phdr->msgLength);
-	phdr->msgFlags = le16_to_cpu(phdr->msgFlags);
+	phdr->msg_type = le16_to_cpu(phdr->msg_type);
+	phdr->msg_length = le16_to_cpu(phdr->msg_length);
+	phdr->msg_flags = le16_to_cpu(phdr->msg_flags);
 #endif /* __BIG_ENDIAN */
 }
 EXPORT_SYMBOL_GPL(smsendian_handle_message_header);
diff --git a/drivers/media/common/siano/smsir.h b/drivers/media/common/siano/smsir.h
index 69b59b9..fc8b792 100644
--- a/drivers/media/common/siano/smsir.h
+++ b/drivers/media/common/siano/smsir.h
@@ -40,7 +40,6 @@ struct ir_t {
 	char phys[32];
 
 	char *rc_codes;
-	u64 protocol;
 
 	u32 timeout;
 	u32 controller;
diff --git a/drivers/media/dvb-core/dmxdev.c b/drivers/media/dvb-core/dmxdev.c
index d81dbb2..8896993 100644
--- a/drivers/media/dvb-core/dmxdev.c
+++ b/drivers/media/dvb-core/dmxdev.c
@@ -852,7 +852,8 @@ static int dvb_dmxdev_filter_set(struct dmxdev *dmxdev,
 				 struct dmxdev_filter *dmxdevfilter,
 				 struct dmx_sct_filter_params *params)
 {
-	dprintk("function : %s\n", __func__);
+	dprintk("function : %s, PID=0x%04x, flags=%02x, timeout=%d\n",
+		__func__, params->pid, params->flags, params->timeout);
 
 	dvb_dmxdev_filter_stop(dmxdevfilter);
 
diff --git a/drivers/media/dvb-core/dvb_demux.c b/drivers/media/dvb-core/dvb_demux.c
index d319717..71641b2 100644
--- a/drivers/media/dvb-core/dvb_demux.c
+++ b/drivers/media/dvb-core/dvb_demux.c
@@ -440,20 +440,22 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
 		if (!dvb_demux_feed_err_pkts)
 			return;
 	} else /* if TEI bit is set, pid may be wrong- skip pkt counter */
-	if (demux->cnt_storage && dvb_demux_tscheck) {
-		/* check pkt counter */
-		if (pid < MAX_PID) {
-			if ((buf[3] & 0xf) != demux->cnt_storage[pid])
-				dprintk_tscheck("TS packet counter mismatch. "
-						"PID=0x%x expected 0x%x "
-						"got 0x%x\n",
+		if (demux->cnt_storage && dvb_demux_tscheck) {
+			/* check pkt counter */
+			if (pid < MAX_PID) {
+				if (buf[3] & 0x10)
+					demux->cnt_storage[pid] =
+						(demux->cnt_storage[pid] + 1) & 0xf;
+
+				if ((buf[3] & 0xf) != demux->cnt_storage[pid]) {
+					dprintk_tscheck("TS packet counter mismatch. PID=0x%x expected 0x%x got 0x%x\n",
 						pid, demux->cnt_storage[pid],
 						buf[3] & 0xf);
-
-			demux->cnt_storage[pid] = ((buf[3] & 0xf) + 1)&0xf;
+					demux->cnt_storage[pid] = buf[3] & 0xf;
+				}
+			}
+			/* end check */
 		}
-		/* end check */
-	}
 
 	list_for_each_entry(feed, &demux->feed_list, list_head) {
 		if ((feed->pid != pid) && (feed->pid != 0x2000))
diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c
index 6e50a75..57601c0 100644
--- a/drivers/media/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb-core/dvb_frontend.c
@@ -920,7 +920,7 @@ static int dvb_frontend_clear_cache(struct dvb_frontend *fe)
 	u32 delsys;
 
 	delsys = c->delivery_system;
-	memset(c, 0, sizeof(struct dtv_frontend_properties));
+	memset(c, 0, offsetof(struct dtv_frontend_properties, strength));
 	c->delivery_system = delsys;
 
 	c->state = DTV_CLEAR;
@@ -1509,9 +1509,74 @@ static bool is_dvbv3_delsys(u32 delsys)
 	return status;
 }
 
-static int set_delivery_system(struct dvb_frontend *fe, u32 desired_system)
+/**
+ * emulate_delivery_system - emulate a DVBv5 delivery system with a DVBv3 type
+ * @fe:			struct frontend;
+ * @delsys:			DVBv5 type that will be used for emulation
+ *
+ * Provides emulation for delivery systems that are compatible with the old
+ * DVBv3 call. Among its usages, it provices support for ISDB-T, and allows
+ * using a DVB-S2 only frontend just like it were a DVB-S, if the frontent
+ * parameters are compatible with DVB-S spec.
+ */
+static int emulate_delivery_system(struct dvb_frontend *fe, u32 delsys)
 {
-	int ncaps, i;
+	int i;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+
+	c->delivery_system = delsys;
+
+	/*
+	 * If the call is for ISDB-T, put it into full-seg, auto mode, TV
+	 */
+	if (c->delivery_system == SYS_ISDBT) {
+		dev_dbg(fe->dvb->device,
+			"%s: Using defaults for SYS_ISDBT\n",
+			__func__);
+
+		if (!c->bandwidth_hz)
+			c->bandwidth_hz = 6000000;
+
+		c->isdbt_partial_reception = 0;
+		c->isdbt_sb_mode = 0;
+		c->isdbt_sb_subchannel = 0;
+		c->isdbt_sb_segment_idx = 0;
+		c->isdbt_sb_segment_count = 0;
+		c->isdbt_layer_enabled = 7;
+		for (i = 0; i < 3; i++) {
+			c->layer[i].fec = FEC_AUTO;
+			c->layer[i].modulation = QAM_AUTO;
+			c->layer[i].interleaving = 0;
+			c->layer[i].segment_count = 0;
+		}
+	}
+	dev_dbg(fe->dvb->device, "%s: change delivery system on cache to %d\n",
+		__func__, c->delivery_system);
+
+	return 0;
+}
+
+/**
+ * dvbv5_set_delivery_system - Sets the delivery system for a DVBv5 API call
+ * @fe:			frontend struct
+ * @desired_system:	delivery system requested by the user
+ *
+ * A DVBv5 call know what's the desired system it wants. So, set it.
+ *
+ * There are, however, a few known issues with early DVBv5 applications that
+ * are also handled by this logic:
+ *
+ * 1) Some early apps use SYS_UNDEFINED as the desired delivery system.
+ *    This is an API violation, but, as we don't want to break userspace,
+ *    convert it to the first supported delivery system.
+ * 2) Some apps might be using a DVBv5 call in a wrong way, passing, for
+ *    example, SYS_DVBT instead of SYS_ISDBT. This is because early usage of
+ *    ISDB-T provided backward compat with DVB-T.
+ */
+static int dvbv5_set_delivery_system(struct dvb_frontend *fe,
+				     u32 desired_system)
+{
+	int ncaps;
 	u32 delsys = SYS_UNDEFINED;
 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 	enum dvbv3_emulation_type type;
@@ -1522,166 +1587,136 @@ static int set_delivery_system(struct dvb_frontend *fe, u32 desired_system)
 	 * assume that the application wants to use the first supported
 	 * delivery system.
 	 */
-	if (c->delivery_system == SYS_UNDEFINED)
-	        c->delivery_system = fe->ops.delsys[0];
+	if (desired_system == SYS_UNDEFINED)
+		desired_system = fe->ops.delsys[0];
 
-	if (desired_system == SYS_UNDEFINED) {
-		/*
-		 * A DVBv3 call doesn't know what's the desired system.
-		 * Also, DVBv3 applications don't know that ops.info->type
-		 * could be changed, and they simply dies when it doesn't
-		 * match.
-		 * So, don't change the current delivery system, as it
-		 * may be trying to do the wrong thing, like setting an
-		 * ISDB-T frontend as DVB-T. Instead, find the closest
-		 * DVBv3 system that matches the delivery system.
-		 */
-		if (is_dvbv3_delsys(c->delivery_system)) {
+	/*
+	 * This is a DVBv5 call. So, it likely knows the supported
+	 * delivery systems. So, check if the desired delivery system is
+	 * supported
+	 */
+	ncaps = 0;
+	while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) {
+		if (fe->ops.delsys[ncaps] == desired_system) {
+			c->delivery_system = desired_system;
 			dev_dbg(fe->dvb->device,
-					"%s: Using delivery system to %d\n",
-					__func__, c->delivery_system);
-			return 0;
-		}
-		type = dvbv3_type(c->delivery_system);
-		switch (type) {
-		case DVBV3_QPSK:
-			desired_system = SYS_DVBS;
-			break;
-		case DVBV3_QAM:
-			desired_system = SYS_DVBC_ANNEX_A;
-			break;
-		case DVBV3_ATSC:
-			desired_system = SYS_ATSC;
-			break;
-		case DVBV3_OFDM:
-			desired_system = SYS_DVBT;
-			break;
-		default:
-			dev_dbg(fe->dvb->device, "%s: This frontend doesn't support DVBv3 calls\n",
-					__func__);
-			return -EINVAL;
-		}
-		/*
-		 * Get a delivery system that is compatible with DVBv3
-		 * NOTE: in order for this to work with softwares like Kaffeine that
-		 *	uses a DVBv5 call for DVB-S2 and a DVBv3 call to go back to
-		 *	DVB-S, drivers that support both should put the SYS_DVBS entry
-		 *	before the SYS_DVBS2, otherwise it won't switch back to DVB-S.
-		 *	The real fix is that userspace applications should not use DVBv3
-		 *	and not trust on calling FE_SET_FRONTEND to switch the delivery
-		 *	system.
-		 */
-		ncaps = 0;
-		while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) {
-			if (fe->ops.delsys[ncaps] == desired_system) {
-				delsys = desired_system;
-				break;
-			}
-			ncaps++;
-		}
-		if (delsys == SYS_UNDEFINED) {
-			dev_dbg(fe->dvb->device, "%s: Couldn't find a delivery system that matches %d\n",
+					"%s: Changing delivery system to %d\n",
 					__func__, desired_system);
+			return 0;
 		}
-	} else {
-		/*
-		 * This is a DVBv5 call. So, it likely knows the supported
-		 * delivery systems.
-		 */
+		ncaps++;
+	}
 
-		/* Check if the desired delivery system is supported */
-		ncaps = 0;
-		while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) {
-			if (fe->ops.delsys[ncaps] == desired_system) {
-				c->delivery_system = desired_system;
-				dev_dbg(fe->dvb->device,
-						"%s: Changing delivery system to %d\n",
-						__func__, desired_system);
-				return 0;
-			}
-			ncaps++;
-		}
-		type = dvbv3_type(desired_system);
+	/*
+	 * The requested delivery system isn't supported. Maybe userspace
+	 * is requesting a DVBv3 compatible delivery system.
+	 *
+	 * The emulation only works if the desired system is one of the
+	 * delivery systems supported by DVBv3 API
+	 */
+	if (!is_dvbv3_delsys(desired_system)) {
+		dev_dbg(fe->dvb->device,
+			"%s: Delivery system %d not supported.\n",
+			__func__, desired_system);
+		return -EINVAL;
+	}
 
-		/*
-		 * The delivery system is not supported. See if it can be
-		 * emulated.
-		 * The emulation only works if the desired system is one of the
-		 * DVBv3 delivery systems
-		 */
-		if (!is_dvbv3_delsys(desired_system)) {
-			dev_dbg(fe->dvb->device,
-					"%s: can't use a DVBv3 FE_SET_FRONTEND call on this frontend\n",
-					__func__);
-			return -EINVAL;
-		}
+	type = dvbv3_type(desired_system);
 
-		/*
-		 * Get the last non-DVBv3 delivery system that has the same type
-		 * of the desired system
-		 */
-		ncaps = 0;
-		while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) {
-			if ((dvbv3_type(fe->ops.delsys[ncaps]) == type) &&
-			    !is_dvbv3_delsys(fe->ops.delsys[ncaps]))
-				delsys = fe->ops.delsys[ncaps];
-			ncaps++;
-		}
-		/* There's nothing compatible with the desired delivery system */
-		if (delsys == SYS_UNDEFINED) {
-			dev_dbg(fe->dvb->device,
-					"%s: Incompatible DVBv3 FE_SET_FRONTEND call for this frontend\n",
-					__func__);
-			return -EINVAL;
-		}
+	/*
+	* Get the last non-DVBv3 delivery system that has the same type
+	* of the desired system
+	*/
+	ncaps = 0;
+	while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) {
+		if (dvbv3_type(fe->ops.delsys[ncaps]) == type)
+			delsys = fe->ops.delsys[ncaps];
+		ncaps++;
 	}
 
-	c->delivery_system = delsys;
+	/* There's nothing compatible with the desired delivery system */
+	if (delsys == SYS_UNDEFINED) {
+		dev_dbg(fe->dvb->device,
+			"%s: Delivery system %d not supported on emulation mode.\n",
+			__func__, desired_system);
+		return -EINVAL;
+	}
+
+	dev_dbg(fe->dvb->device,
+		"%s: Using delivery system %d emulated as if it were %d\n",
+		__func__, delsys, desired_system);
+
+	return emulate_delivery_system(fe, desired_system);
+}
+
+/**
+ * dvbv3_set_delivery_system - Sets the delivery system for a DVBv3 API call
+ * @fe:	frontend struct
+ *
+ * A DVBv3 call doesn't know what's the desired system it wants. It also
+ * doesn't allow to switch between different types. Due to that, userspace
+ * should use DVBv5 instead.
+ * However, in order to avoid breaking userspace API, limited backward
+ * compatibility support is provided.
+ *
+ * There are some delivery systems that are incompatible with DVBv3 calls.
+ *
+ * This routine should work fine for frontends that support just one delivery
+ * system.
+ *
+ * For frontends that support multiple frontends:
+ * 1) It defaults to use the first supported delivery system. There's an
+ *    userspace application that allows changing it at runtime;
+ *
+ * 2) If the current delivery system is not compatible with DVBv3, it gets
+ *    the first one that it is compatible.
+ *
+ * NOTE: in order for this to work with applications like Kaffeine that
+ *	uses a DVBv5 call for DVB-S2 and a DVBv3 call to go back to
+ *	DVB-S, drivers that support both DVB-S and DVB-S2 should have the
+ *	SYS_DVBS entry before the SYS_DVBS2, otherwise it won't switch back
+ *	to DVB-S.
+ */
+static int dvbv3_set_delivery_system(struct dvb_frontend *fe)
+{
+	int ncaps;
+	u32 delsys = SYS_UNDEFINED;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+
+	/* If not set yet, defaults to the first supported delivery system */
+	if (c->delivery_system == SYS_UNDEFINED)
+		c->delivery_system = fe->ops.delsys[0];
 
 	/*
-	 * The DVBv3 or DVBv5 call is requesting a different system. So,
-	 * emulation is needed.
-	 *
-	 * Emulate newer delivery systems like ISDBT, DVBT and DTMB
-	 * for older DVBv5 applications. The emulation will try to use
-	 * the auto mode for most things, and will assume that the desired
-	 * delivery system is the last one at the ops.delsys[] array
+	 * Trivial case: just use the current one, if it already a DVBv3
+	 * delivery system
 	 */
-	dev_dbg(fe->dvb->device,
-			"%s: Using delivery system %d emulated as if it were a %d\n",
-			__func__, delsys, desired_system);
+	if (is_dvbv3_delsys(c->delivery_system)) {
+		dev_dbg(fe->dvb->device,
+				"%s: Using delivery system to %d\n",
+				__func__, c->delivery_system);
+		return 0;
+	}
 
 	/*
-	 * For now, handles ISDB-T calls. More code may be needed here for the
-	 * other emulated stuff
+	 * Seek for the first delivery system that it is compatible with a
+	 * DVBv3 standard
 	 */
-	if (type == DVBV3_OFDM) {
-		if (c->delivery_system == SYS_ISDBT) {
-			dev_dbg(fe->dvb->device,
-					"%s: Using defaults for SYS_ISDBT\n",
-					__func__);
-
-			if (!c->bandwidth_hz)
-				c->bandwidth_hz = 6000000;
-
-			c->isdbt_partial_reception = 0;
-			c->isdbt_sb_mode = 0;
-			c->isdbt_sb_subchannel = 0;
-			c->isdbt_sb_segment_idx = 0;
-			c->isdbt_sb_segment_count = 0;
-			c->isdbt_layer_enabled = 0;
-			for (i = 0; i < 3; i++) {
-				c->layer[i].fec = FEC_AUTO;
-				c->layer[i].modulation = QAM_AUTO;
-				c->layer[i].interleaving = 0;
-				c->layer[i].segment_count = 0;
-			}
+	ncaps = 0;
+	while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) {
+		if (dvbv3_type(fe->ops.delsys[ncaps]) != DVBV3_UNKNOWN) {
+			delsys = fe->ops.delsys[ncaps];
+			break;
 		}
+		ncaps++;
 	}
-	dev_dbg(fe->dvb->device, "%s: change delivery system on cache to %d\n",
-			__func__, c->delivery_system);
-
-	return 0;
+	if (delsys == SYS_UNDEFINED) {
+		dev_dbg(fe->dvb->device,
+			"%s: Couldn't find a delivery system that works with FE_SET_FRONTEND\n",
+			__func__);
+		return -EINVAL;
+	}
+	return emulate_delivery_system(fe, delsys);
 }
 
 static int dtv_property_process_set(struct dvb_frontend *fe,
@@ -1742,7 +1777,7 @@ static int dtv_property_process_set(struct dvb_frontend *fe,
 		c->rolloff = tvp->u.data;
 		break;
 	case DTV_DELIVERY_SYSTEM:
-		r = set_delivery_system(fe, tvp->u.data);
+		r = dvbv5_set_delivery_system(fe, tvp->u.data);
 		break;
 	case DTV_VOLTAGE:
 		c->voltage = tvp->u.data;
@@ -2335,7 +2370,7 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
 		break;
 
 	case FE_SET_FRONTEND:
-		err = set_delivery_system(fe, SYS_UNDEFINED);
+		err = dvbv3_set_delivery_system(fe);
 		if (err)
 			break;
 
@@ -2594,7 +2629,7 @@ int dvb_register_frontend(struct dvb_adapter* dvb,
 	 * first supported delivery system (ops->delsys[0])
 	 */
 
-        fe->dtv_property_cache.delivery_system = fe->ops.delsys[0];
+	fe->dtv_property_cache.delivery_system = fe->ops.delsys[0];
 	dvb_frontend_clear_cache(fe);
 
 	mutex_unlock(&frontend_mutex);
diff --git a/drivers/media/dvb-core/dvb_net.c b/drivers/media/dvb-core/dvb_net.c
index 44225b1..83a23af 100644
--- a/drivers/media/dvb-core/dvb_net.c
+++ b/drivers/media/dvb-core/dvb_net.c
@@ -185,7 +185,7 @@ static __be16 dvb_net_eth_type_trans(struct sk_buff *skb,
 			skb->pkt_type=PACKET_MULTICAST;
 	}
 
-	if (ntohs(eth->h_proto) >= 1536)
+	if (ntohs(eth->h_proto) >= ETH_P_802_3_MIN)
 		return eth->h_proto;
 
 	rawp = skb->data;
@@ -228,9 +228,9 @@ static int ule_test_sndu( struct dvb_net_priv *p )
 static int ule_bridged_sndu( struct dvb_net_priv *p )
 {
 	struct ethhdr *hdr = (struct ethhdr*) p->ule_next_hdr;
-	if(ntohs(hdr->h_proto) < 1536) {
+	if(ntohs(hdr->h_proto) < ETH_P_802_3_MIN) {
 		int framelen = p->ule_sndu_len - ((p->ule_next_hdr+sizeof(struct ethhdr)) - p->ule_skb->data);
-		/* A frame Type < 1536 for a bridged frame, introduces a LLC Length field. */
+		/* A frame Type < ETH_P_802_3_MIN for a bridged frame, introduces a LLC Length field. */
 		if(framelen != ntohs(hdr->h_proto)) {
 			return -1;
 		}
@@ -320,7 +320,7 @@ static int handle_ule_extensions( struct dvb_net_priv *p )
 			(int) p->ule_sndu_type, l, total_ext_len);
 #endif
 
-	} while (p->ule_sndu_type < 1536);
+	} while (p->ule_sndu_type < ETH_P_802_3_MIN);
 
 	return total_ext_len;
 }
@@ -712,7 +712,7 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
 				}
 
 				/* Handle ULE Extension Headers. */
-				if (priv->ule_sndu_type < 1536) {
+				if (priv->ule_sndu_type < ETH_P_802_3_MIN) {
 					/* There is an extension header.  Handle it accordingly. */
 					int l = handle_ule_extensions(priv);
 					if (l < 0) {
diff --git a/drivers/media/dvb-frontends/Kconfig b/drivers/media/dvb-frontends/Kconfig
index 6f809a7..0e2ec6f 100644
--- a/drivers/media/dvb-frontends/Kconfig
+++ b/drivers/media/dvb-frontends/Kconfig
@@ -210,7 +210,7 @@ config DVB_SI21XX
 config DVB_TS2020
 	tristate "Montage Tehnology TS2020 based tuners"
 	depends on DVB_CORE && I2C
-	default m if DVB_FE_CUSTOMISE
+	default m if !MEDIA_SUBDRV_AUTOSELECT
 	help
 	  A DVB-S/S2 silicon tuner. Say Y when you want to support this tuner.
 
diff --git a/drivers/media/dvb-frontends/a8293.h b/drivers/media/dvb-frontends/a8293.h
index ed29e55..b6ef642 100644
--- a/drivers/media/dvb-frontends/a8293.h
+++ b/drivers/media/dvb-frontends/a8293.h
@@ -21,12 +21,13 @@
 #ifndef A8293_H
 #define A8293_H
 
+#include <linux/kconfig.h>
+
 struct a8293_config {
 	u8 i2c_addr;
 };
 
-#if defined(CONFIG_DVB_A8293) || \
-	(defined(CONFIG_DVB_A8293_MODULE) && defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_A8293)
 extern struct dvb_frontend *a8293_attach(struct dvb_frontend *fe,
 	struct i2c_adapter *i2c, const struct a8293_config *cfg);
 #else
diff --git a/drivers/media/dvb-frontends/af9013.h b/drivers/media/dvb-frontends/af9013.h
index dc837d9..09273b2 100644
--- a/drivers/media/dvb-frontends/af9013.h
+++ b/drivers/media/dvb-frontends/af9013.h
@@ -25,6 +25,7 @@
 #ifndef AF9013_H
 #define AF9013_H
 
+#include <linux/kconfig.h>
 #include <linux/dvb/frontend.h>
 
 /* AF9013/5 GPIOs (mostly guessed)
@@ -102,8 +103,7 @@ struct af9013_config {
 	u8 gpio[4];
 };
 
-#if defined(CONFIG_DVB_AF9013) || \
-	(defined(CONFIG_DVB_AF9013_MODULE) && defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_AF9013)
 extern struct dvb_frontend *af9013_attach(const struct af9013_config *config,
 	struct i2c_adapter *i2c);
 #else
diff --git a/drivers/media/dvb-frontends/af9033.c b/drivers/media/dvb-frontends/af9033.c
index c9cad989..a777b4b 100644
--- a/drivers/media/dvb-frontends/af9033.c
+++ b/drivers/media/dvb-frontends/af9033.c
@@ -156,6 +156,37 @@ static int af9033_rd_reg_mask(struct af9033_state *state, u32 reg, u8 *val,
 	return 0;
 }
 
+/* write reg val table using reg addr auto increment */
+static int af9033_wr_reg_val_tab(struct af9033_state *state,
+		const struct reg_val *tab, int tab_len)
+{
+	int ret, i, j;
+	u8 buf[tab_len];
+
+	dev_dbg(&state->i2c->dev, "%s: tab_len=%d\n", __func__, tab_len);
+
+	for (i = 0, j = 0; i < tab_len; i++) {
+		buf[j] = tab[i].val;
+
+		if (i == tab_len - 1 || tab[i].reg != tab[i + 1].reg - 1) {
+			ret = af9033_wr_regs(state, tab[i].reg - j, buf, j + 1);
+			if (ret < 0)
+				goto err;
+
+			j = 0;
+		} else {
+			j++;
+		}
+	}
+
+	return 0;
+
+err:
+	dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
+
+	return ret;
+}
+
 static u32 af9033_div(struct af9033_state *state, u32 a, u32 b, u32 x)
 {
 	u32 r = 0, c = 0, i;
@@ -223,6 +254,7 @@ static int af9033_init(struct dvb_frontend *fe)
 		{ 0x80f986, state->ts_mode_parallel, 0x01 },
 		{ 0x00d827, 0x00, 0xff },
 		{ 0x00d829, 0x00, 0xff },
+		{ 0x800045, state->cfg.adc_multiplier, 0xff },
 	};
 
 	/* program clock control */
@@ -286,14 +318,29 @@ static int af9033_init(struct dvb_frontend *fe)
 
 	/* load OFSM settings */
 	dev_dbg(&state->i2c->dev, "%s: load ofsm settings\n", __func__);
-	len = ARRAY_SIZE(ofsm_init);
-	init = ofsm_init;
-	for (i = 0; i < len; i++) {
-		ret = af9033_wr_reg(state, init[i].reg, init[i].val);
-		if (ret < 0)
-			goto err;
+	switch (state->cfg.tuner) {
+	case AF9033_TUNER_IT9135_38:
+	case AF9033_TUNER_IT9135_51:
+	case AF9033_TUNER_IT9135_52:
+		len = ARRAY_SIZE(ofsm_init_it9135_v1);
+		init = ofsm_init_it9135_v1;
+		break;
+	case AF9033_TUNER_IT9135_60:
+	case AF9033_TUNER_IT9135_61:
+	case AF9033_TUNER_IT9135_62:
+		len = ARRAY_SIZE(ofsm_init_it9135_v2);
+		init = ofsm_init_it9135_v2;
+		break;
+	default:
+		len = ARRAY_SIZE(ofsm_init);
+		init = ofsm_init;
+		break;
 	}
 
+	ret = af9033_wr_reg_val_tab(state, init, len);
+	if (ret < 0)
+		goto err;
+
 	/* load tuner specific settings */
 	dev_dbg(&state->i2c->dev, "%s: load tuner specific settings\n",
 			__func__);
@@ -322,6 +369,30 @@ static int af9033_init(struct dvb_frontend *fe)
 		len = ARRAY_SIZE(tuner_init_fc0012);
 		init = tuner_init_fc0012;
 		break;
+	case AF9033_TUNER_IT9135_38:
+		len = ARRAY_SIZE(tuner_init_it9135_38);
+		init = tuner_init_it9135_38;
+		break;
+	case AF9033_TUNER_IT9135_51:
+		len = ARRAY_SIZE(tuner_init_it9135_51);
+		init = tuner_init_it9135_51;
+		break;
+	case AF9033_TUNER_IT9135_52:
+		len = ARRAY_SIZE(tuner_init_it9135_52);
+		init = tuner_init_it9135_52;
+		break;
+	case AF9033_TUNER_IT9135_60:
+		len = ARRAY_SIZE(tuner_init_it9135_60);
+		init = tuner_init_it9135_60;
+		break;
+	case AF9033_TUNER_IT9135_61:
+		len = ARRAY_SIZE(tuner_init_it9135_61);
+		init = tuner_init_it9135_61;
+		break;
+	case AF9033_TUNER_IT9135_62:
+		len = ARRAY_SIZE(tuner_init_it9135_62);
+		init = tuner_init_it9135_62;
+		break;
 	default:
 		dev_dbg(&state->i2c->dev, "%s: unsupported tuner ID=%d\n",
 				__func__, state->cfg.tuner);
@@ -329,11 +400,9 @@ static int af9033_init(struct dvb_frontend *fe)
 		goto err;
 	}
 
-	for (i = 0; i < len; i++) {
-		ret = af9033_wr_reg(state, init[i].reg, init[i].val);
-		if (ret < 0)
-			goto err;
-	}
+	ret = af9033_wr_reg_val_tab(state, init, len);
+	if (ret < 0)
+		goto err;
 
 	if (state->cfg.ts_mode == AF9033_TS_MODE_SERIAL) {
 		ret = af9033_wr_reg_mask(state, 0x00d91c, 0x01, 0x01);
@@ -349,6 +418,15 @@ static int af9033_init(struct dvb_frontend *fe)
 			goto err;
 	}
 
+	switch (state->cfg.tuner) {
+	case AF9033_TUNER_IT9135_60:
+	case AF9033_TUNER_IT9135_61:
+	case AF9033_TUNER_IT9135_62:
+		ret = af9033_wr_reg(state, 0x800000, 0x01);
+		if (ret < 0)
+			goto err;
+	}
+
 	state->bandwidth_hz = 0; /* force to program all parameters */
 
 	return 0;
@@ -415,7 +493,8 @@ err:
 static int af9033_get_tune_settings(struct dvb_frontend *fe,
 		struct dvb_frontend_tune_settings *fesettings)
 {
-	fesettings->min_delay_ms = 800;
+	/* 800 => 2000 because IT9135 v2 is slow to gain lock */
+	fesettings->min_delay_ms = 2000;
 	fesettings->step_size = 0;
 	fesettings->max_drift = 0;
 
@@ -498,17 +577,17 @@ static int af9033_set_frontend(struct dvb_frontend *fe)
 		if (spec_inv == -1)
 			freq_cw = 0x800000 - freq_cw;
 
-		/* get adc multiplies */
-		ret = af9033_rd_reg(state, 0x800045, &tmp);
-		if (ret < 0)
-			goto err;
-
-		if (tmp == 1)
+		if (state->cfg.adc_multiplier == AF9033_ADC_MULTIPLIER_2X)
 			freq_cw /= 2;
 
 		buf[0] = (freq_cw >>  0) & 0xff;
 		buf[1] = (freq_cw >>  8) & 0xff;
 		buf[2] = (freq_cw >> 16) & 0x7f;
+
+		/* FIXME: there seems to be calculation error here... */
+		if (if_frequency == 0)
+			buf[2] = 0;
+
 		ret = af9033_wr_regs(state, 0x800029, buf, 3);
 		if (ret < 0)
 			goto err;
@@ -934,13 +1013,24 @@ struct dvb_frontend *af9033_attach(const struct af9033_config *config,
 			buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);
 
 	/* sleep */
-	ret = af9033_wr_reg(state, 0x80004c, 1);
-	if (ret < 0)
-		goto err;
+	switch (state->cfg.tuner) {
+	case AF9033_TUNER_IT9135_38:
+	case AF9033_TUNER_IT9135_51:
+	case AF9033_TUNER_IT9135_52:
+	case AF9033_TUNER_IT9135_60:
+	case AF9033_TUNER_IT9135_61:
+	case AF9033_TUNER_IT9135_62:
+		/* IT9135 did not like to sleep at that early */
+		break;
+	default:
+		ret = af9033_wr_reg(state, 0x80004c, 1);
+		if (ret < 0)
+			goto err;
 
-	ret = af9033_wr_reg(state, 0x800000, 0);
-	if (ret < 0)
-		goto err;
+		ret = af9033_wr_reg(state, 0x800000, 0);
+		if (ret < 0)
+			goto err;
+	}
 
 	/* configure internal TS mode */
 	switch (state->cfg.ts_mode) {
diff --git a/drivers/media/dvb-frontends/af9033.h b/drivers/media/dvb-frontends/af9033.h
index 82bd8c1..c286e8f 100644
--- a/drivers/media/dvb-frontends/af9033.h
+++ b/drivers/media/dvb-frontends/af9033.h
@@ -22,6 +22,8 @@
 #ifndef AF9033_H
 #define AF9033_H
 
+#include <linux/kconfig.h>
+
 struct af9033_config {
 	/*
 	 * I2C address
@@ -36,6 +38,13 @@ struct af9033_config {
 	u32 clock;
 
 	/*
+	 * ADC multiplier
+	 */
+#define AF9033_ADC_MULTIPLIER_1X   0
+#define AF9033_ADC_MULTIPLIER_2X   1
+	u8 adc_multiplier;
+
+	/*
 	 * tuner
 	 */
 #define AF9033_TUNER_TUA9001     0x27 /* Infineon TUA 9001 */
@@ -44,6 +53,14 @@ struct af9033_config {
 #define AF9033_TUNER_MXL5007T    0xa0 /* MaxLinear MxL5007T */
 #define AF9033_TUNER_TDA18218    0xa1 /* NXP TDA 18218HN */
 #define AF9033_TUNER_FC2580      0x32 /* FCI FC2580 */
+/* 50-5f Omega */
+#define AF9033_TUNER_IT9135_38   0x38 /* Omega */
+#define AF9033_TUNER_IT9135_51   0x51 /* Omega LNA config 1 */
+#define AF9033_TUNER_IT9135_52   0x52 /* Omega LNA config 2 */
+/* 60-6f Omega v2 */
+#define AF9033_TUNER_IT9135_60   0x60 /* Omega v2 */
+#define AF9033_TUNER_IT9135_61   0x61 /* Omega v2 LNA config 1 */
+#define AF9033_TUNER_IT9135_62   0x62 /* Omega v2 LNA config 2 */
 	u8 tuner;
 
 	/*
@@ -61,8 +78,7 @@ struct af9033_config {
 };
 
 
-#if defined(CONFIG_DVB_AF9033) || \
-	(defined(CONFIG_DVB_AF9033_MODULE) && defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_AF9033)
 extern struct dvb_frontend *af9033_attach(const struct af9033_config *config,
 	struct i2c_adapter *i2c);
 #else
diff --git a/drivers/media/dvb-frontends/af9033_priv.h b/drivers/media/dvb-frontends/af9033_priv.h
index e9bd782..fc2ad58 100644
--- a/drivers/media/dvb-frontends/af9033_priv.h
+++ b/drivers/media/dvb-frontends/af9033_priv.h
@@ -547,5 +547,1509 @@ static const struct reg_val tuner_init_fc2580[] = {
 	{ 0x80f1e6, 0x01 },
 };
 
-#endif /* AF9033_PRIV_H */
+static const struct reg_val ofsm_init_it9135_v1[] = {
+	{ 0x800051, 0x01 },
+	{ 0x800070, 0x0a },
+	{ 0x80007e, 0x04 },
+	{ 0x800081, 0x0a },
+	{ 0x80008a, 0x01 },
+	{ 0x80008e, 0x01 },
+	{ 0x800092, 0x06 },
+	{ 0x800099, 0x01 },
+	{ 0x80009f, 0xe1 },
+	{ 0x8000a0, 0xcf },
+	{ 0x8000a3, 0x01 },
+	{ 0x8000a5, 0x01 },
+	{ 0x8000a6, 0x01 },
+	{ 0x8000a9, 0x00 },
+	{ 0x8000aa, 0x01 },
+	{ 0x8000b0, 0x01 },
+	{ 0x8000c2, 0x05 },
+	{ 0x8000c6, 0x19 },
+	{ 0x80f000, 0x0f },
+	{ 0x80f016, 0x10 },
+	{ 0x80f017, 0x04 },
+	{ 0x80f018, 0x05 },
+	{ 0x80f019, 0x04 },
+	{ 0x80f01a, 0x05 },
+	{ 0x80f021, 0x03 },
+	{ 0x80f022, 0x0a },
+	{ 0x80f023, 0x0a },
+	{ 0x80f02b, 0x00 },
+	{ 0x80f02c, 0x01 },
+	{ 0x80f064, 0x03 },
+	{ 0x80f065, 0xf9 },
+	{ 0x80f066, 0x03 },
+	{ 0x80f067, 0x01 },
+	{ 0x80f06f, 0xe0 },
+	{ 0x80f070, 0x03 },
+	{ 0x80f072, 0x0f },
+	{ 0x80f073, 0x03 },
+	{ 0x80f078, 0x00 },
+	{ 0x80f087, 0x00 },
+	{ 0x80f09b, 0x3f },
+	{ 0x80f09c, 0x00 },
+	{ 0x80f09d, 0x20 },
+	{ 0x80f09e, 0x00 },
+	{ 0x80f09f, 0x0c },
+	{ 0x80f0a0, 0x00 },
+	{ 0x80f130, 0x04 },
+	{ 0x80f132, 0x04 },
+	{ 0x80f144, 0x1a },
+	{ 0x80f146, 0x00 },
+	{ 0x80f14a, 0x01 },
+	{ 0x80f14c, 0x00 },
+	{ 0x80f14d, 0x00 },
+	{ 0x80f14f, 0x04 },
+	{ 0x80f158, 0x7f },
+	{ 0x80f15a, 0x00 },
+	{ 0x80f15b, 0x08 },
+	{ 0x80f15d, 0x03 },
+	{ 0x80f15e, 0x05 },
+	{ 0x80f163, 0x05 },
+	{ 0x80f166, 0x01 },
+	{ 0x80f167, 0x40 },
+	{ 0x80f168, 0x0f },
+	{ 0x80f17a, 0x00 },
+	{ 0x80f17b, 0x00 },
+	{ 0x80f183, 0x01 },
+	{ 0x80f19d, 0x40 },
+	{ 0x80f1bc, 0x36 },
+	{ 0x80f1bd, 0x00 },
+	{ 0x80f1cb, 0xa0 },
+	{ 0x80f1cc, 0x01 },
+	{ 0x80f204, 0x10 },
+	{ 0x80f214, 0x00 },
+	{ 0x80f40e, 0x0a },
+	{ 0x80f40f, 0x40 },
+	{ 0x80f410, 0x08 },
+	{ 0x80f55f, 0x0a },
+	{ 0x80f561, 0x15 },
+	{ 0x80f562, 0x20 },
+	{ 0x80f5df, 0xfb },
+	{ 0x80f5e0, 0x00 },
+	{ 0x80f5e3, 0x09 },
+	{ 0x80f5e4, 0x01 },
+	{ 0x80f5e5, 0x01 },
+	{ 0x80f5f8, 0x01 },
+	{ 0x80f5fd, 0x01 },
+	{ 0x80f600, 0x05 },
+	{ 0x80f601, 0x08 },
+	{ 0x80f602, 0x0b },
+	{ 0x80f603, 0x0e },
+	{ 0x80f604, 0x11 },
+	{ 0x80f605, 0x14 },
+	{ 0x80f606, 0x17 },
+	{ 0x80f607, 0x1f },
+	{ 0x80f60e, 0x00 },
+	{ 0x80f60f, 0x04 },
+	{ 0x80f610, 0x32 },
+	{ 0x80f611, 0x10 },
+	{ 0x80f707, 0xfc },
+	{ 0x80f708, 0x00 },
+	{ 0x80f709, 0x37 },
+	{ 0x80f70a, 0x00 },
+	{ 0x80f78b, 0x01 },
+	{ 0x80f80f, 0x40 },
+	{ 0x80f810, 0x54 },
+	{ 0x80f811, 0x5a },
+	{ 0x80f905, 0x01 },
+	{ 0x80fb06, 0x03 },
+	{ 0x80fd8b, 0x00 },
+};
+
+/* ITE Tech IT9135 Omega tuner init
+   AF9033_TUNER_IT9135_38   = 0x38 */
+static const struct reg_val tuner_init_it9135_38[] = {
+	{ 0x800043, 0x00 },
+	{ 0x800046, 0x38 },
+	{ 0x800051, 0x01 },
+	{ 0x80005f, 0x00 },
+	{ 0x800060, 0x00 },
+	{ 0x800068, 0x0a },
+	{ 0x800070, 0x0a },
+	{ 0x800071, 0x05 },
+	{ 0x800072, 0x02 },
+	{ 0x800075, 0x8c },
+	{ 0x800076, 0x8c },
+	{ 0x800077, 0x8c },
+	{ 0x800078, 0xc8 },
+	{ 0x800079, 0x01 },
+	{ 0x80007e, 0x04 },
+	{ 0x80007f, 0x00 },
+	{ 0x800081, 0x0a },
+	{ 0x800082, 0x12 },
+	{ 0x800083, 0x02 },
+	{ 0x800084, 0x0a },
+	{ 0x800085, 0x03 },
+	{ 0x800086, 0xc8 },
+	{ 0x800087, 0xb8 },
+	{ 0x800088, 0xd0 },
+	{ 0x800089, 0xc3 },
+	{ 0x80008a, 0x01 },
+	{ 0x80008e, 0x01 },
+	{ 0x800092, 0x06 },
+	{ 0x800093, 0x00 },
+	{ 0x800094, 0x00 },
+	{ 0x800095, 0x00 },
+	{ 0x800096, 0x00 },
+	{ 0x800099, 0x01 },
+	{ 0x80009b, 0x3c },
+	{ 0x80009c, 0x28 },
+	{ 0x80009f, 0xe1 },
+	{ 0x8000a0, 0xcf },
+	{ 0x8000a3, 0x01 },
+	{ 0x8000a4, 0x5a },
+	{ 0x8000a5, 0x01 },
+	{ 0x8000a6, 0x01 },
+	{ 0x8000a9, 0x00 },
+	{ 0x8000aa, 0x01 },
+	{ 0x8000b0, 0x01 },
+	{ 0x8000b3, 0x02 },
+	{ 0x8000b4, 0x32 },
+	{ 0x8000b6, 0x14 },
+	{ 0x8000c0, 0x11 },
+	{ 0x8000c1, 0x00 },
+	{ 0x8000c2, 0x05 },
+	{ 0x8000c4, 0x00 },
+	{ 0x8000c6, 0x19 },
+	{ 0x8000c7, 0x00 },
+	{ 0x8000cc, 0x2e },
+	{ 0x8000cd, 0x51 },
+	{ 0x8000ce, 0x33 },
+	{ 0x8000f3, 0x05 },
+	{ 0x8000f4, 0x8c },
+	{ 0x8000f5, 0x8c },
+	{ 0x8000f8, 0x03 },
+	{ 0x8000f9, 0x06 },
+	{ 0x8000fa, 0x06 },
+	{ 0x8000fc, 0x02 },
+	{ 0x8000fd, 0x02 },
+	{ 0x8000fe, 0x02 },
+	{ 0x8000ff, 0x09 },
+	{ 0x800100, 0x50 },
+	{ 0x800101, 0x7b },
+	{ 0x800102, 0x77 },
+	{ 0x800103, 0x00 },
+	{ 0x800104, 0x02 },
+	{ 0x800105, 0xc8 },
+	{ 0x800106, 0x05 },
+	{ 0x800107, 0x7b },
+	{ 0x800109, 0x02 },
+	{ 0x800115, 0x0a },
+	{ 0x800116, 0x03 },
+	{ 0x800117, 0x02 },
+	{ 0x800118, 0x80 },
+	{ 0x80011a, 0xc8 },
+	{ 0x80011b, 0x7b },
+	{ 0x80011c, 0x8a },
+	{ 0x80011d, 0xa0 },
+	{ 0x800122, 0x02 },
+	{ 0x800123, 0x18 },
+	{ 0x800124, 0xc3 },
+	{ 0x800127, 0x00 },
+	{ 0x800128, 0x07 },
+	{ 0x80012a, 0x53 },
+	{ 0x80012b, 0x51 },
+	{ 0x80012c, 0x4e },
+	{ 0x80012d, 0x43 },
+	{ 0x800137, 0x01 },
+	{ 0x800138, 0x00 },
+	{ 0x800139, 0x07 },
+	{ 0x80013a, 0x00 },
+	{ 0x80013b, 0x06 },
+	{ 0x80013d, 0x00 },
+	{ 0x80013e, 0x01 },
+	{ 0x80013f, 0x5b },
+	{ 0x800140, 0xc8 },
+	{ 0x800141, 0x59 },
+	{ 0x80f000, 0x0f },
+	{ 0x80f016, 0x10 },
+	{ 0x80f017, 0x04 },
+	{ 0x80f018, 0x05 },
+	{ 0x80f019, 0x04 },
+	{ 0x80f01a, 0x05 },
+	{ 0x80f01f, 0x8c },
+	{ 0x80f020, 0x00 },
+	{ 0x80f021, 0x03 },
+	{ 0x80f022, 0x0a },
+	{ 0x80f023, 0x0a },
+	{ 0x80f029, 0x8c },
+	{ 0x80f02a, 0x00 },
+	{ 0x80f02b, 0x00 },
+	{ 0x80f02c, 0x01 },
+	{ 0x80f064, 0x03 },
+	{ 0x80f065, 0xf9 },
+	{ 0x80f066, 0x03 },
+	{ 0x80f067, 0x01 },
+	{ 0x80f06f, 0xe0 },
+	{ 0x80f070, 0x03 },
+	{ 0x80f072, 0x0f },
+	{ 0x80f073, 0x03 },
+	{ 0x80f077, 0x01 },
+	{ 0x80f078, 0x00 },
+	{ 0x80f085, 0x00 },
+	{ 0x80f086, 0x02 },
+	{ 0x80f087, 0x00 },
+	{ 0x80f09b, 0x3f },
+	{ 0x80f09c, 0x00 },
+	{ 0x80f09d, 0x20 },
+	{ 0x80f09e, 0x00 },
+	{ 0x80f09f, 0x0c },
+	{ 0x80f0a0, 0x00 },
+	{ 0x80f130, 0x04 },
+	{ 0x80f132, 0x04 },
+	{ 0x80f144, 0x1a },
+	{ 0x80f146, 0x00 },
+	{ 0x80f14a, 0x01 },
+	{ 0x80f14c, 0x00 },
+	{ 0x80f14d, 0x00 },
+	{ 0x80f14f, 0x04 },
+	{ 0x80f158, 0x7f },
+	{ 0x80f15a, 0x00 },
+	{ 0x80f15b, 0x08 },
+	{ 0x80f15d, 0x03 },
+	{ 0x80f15e, 0x05 },
+	{ 0x80f163, 0x05 },
+	{ 0x80f166, 0x01 },
+	{ 0x80f167, 0x40 },
+	{ 0x80f168, 0x0f },
+	{ 0x80f17a, 0x00 },
+	{ 0x80f17b, 0x00 },
+	{ 0x80f183, 0x01 },
+	{ 0x80f19d, 0x40 },
+	{ 0x80f1bc, 0x36 },
+	{ 0x80f1bd, 0x00 },
+	{ 0x80f1cb, 0xa0 },
+	{ 0x80f1cc, 0x01 },
+	{ 0x80f204, 0x10 },
+	{ 0x80f214, 0x00 },
+	{ 0x80f24c, 0x88 },
+	{ 0x80f24d, 0x95 },
+	{ 0x80f24e, 0x9a },
+	{ 0x80f24f, 0x90 },
+	{ 0x80f25a, 0x07 },
+	{ 0x80f25b, 0xe8 },
+	{ 0x80f25c, 0x03 },
+	{ 0x80f25d, 0xb0 },
+	{ 0x80f25e, 0x04 },
+	{ 0x80f270, 0x01 },
+	{ 0x80f271, 0x02 },
+	{ 0x80f272, 0x01 },
+	{ 0x80f273, 0x02 },
+	{ 0x80f40e, 0x0a },
+	{ 0x80f40f, 0x40 },
+	{ 0x80f410, 0x08 },
+	{ 0x80f55f, 0x0a },
+	{ 0x80f561, 0x15 },
+	{ 0x80f562, 0x20 },
+	{ 0x80f5df, 0xfb },
+	{ 0x80f5e0, 0x00 },
+	{ 0x80f5e3, 0x09 },
+	{ 0x80f5e4, 0x01 },
+	{ 0x80f5e5, 0x01 },
+	{ 0x80f5f8, 0x01 },
+	{ 0x80f5fd, 0x01 },
+	{ 0x80f600, 0x05 },
+	{ 0x80f601, 0x08 },
+	{ 0x80f602, 0x0b },
+	{ 0x80f603, 0x0e },
+	{ 0x80f604, 0x11 },
+	{ 0x80f605, 0x14 },
+	{ 0x80f606, 0x17 },
+	{ 0x80f607, 0x1f },
+	{ 0x80f60e, 0x00 },
+	{ 0x80f60f, 0x04 },
+	{ 0x80f610, 0x32 },
+	{ 0x80f611, 0x10 },
+	{ 0x80f707, 0xfc },
+	{ 0x80f708, 0x00 },
+	{ 0x80f709, 0x37 },
+	{ 0x80f70a, 0x00 },
+	{ 0x80f78b, 0x01 },
+	{ 0x80f80f, 0x40 },
+	{ 0x80f810, 0x54 },
+	{ 0x80f811, 0x5a },
+	{ 0x80f905, 0x01 },
+	{ 0x80fb06, 0x03 },
+	{ 0x80fd8b, 0x00 },
+};
+
+/* ITE Tech IT9135 Omega LNA config 1 tuner init
+   AF9033_TUNER_IT9135_51   = 0x51 */
+static const struct reg_val tuner_init_it9135_51[] = {
+	{ 0x800043, 0x00 },
+	{ 0x800046, 0x51 },
+	{ 0x800051, 0x01 },
+	{ 0x80005f, 0x00 },
+	{ 0x800060, 0x00 },
+	{ 0x800068, 0x0a },
+	{ 0x800070, 0x0a },
+	{ 0x800071, 0x06 },
+	{ 0x800072, 0x02 },
+	{ 0x800075, 0x8c },
+	{ 0x800076, 0x8c },
+	{ 0x800077, 0x8c },
+	{ 0x800078, 0xc8 },
+	{ 0x800079, 0x01 },
+	{ 0x80007e, 0x04 },
+	{ 0x80007f, 0x00 },
+	{ 0x800081, 0x0a },
+	{ 0x800082, 0x12 },
+	{ 0x800083, 0x02 },
+	{ 0x800084, 0x0a },
+	{ 0x800085, 0x03 },
+	{ 0x800086, 0xc0 },
+	{ 0x800087, 0x96 },
+	{ 0x800088, 0xcf },
+	{ 0x800089, 0xc3 },
+	{ 0x80008a, 0x01 },
+	{ 0x80008e, 0x01 },
+	{ 0x800092, 0x06 },
+	{ 0x800093, 0x00 },
+	{ 0x800094, 0x00 },
+	{ 0x800095, 0x00 },
+	{ 0x800096, 0x00 },
+	{ 0x800099, 0x01 },
+	{ 0x80009b, 0x3c },
+	{ 0x80009c, 0x28 },
+	{ 0x80009f, 0xe1 },
+	{ 0x8000a0, 0xcf },
+	{ 0x8000a3, 0x01 },
+	{ 0x8000a4, 0x5a },
+	{ 0x8000a5, 0x01 },
+	{ 0x8000a6, 0x01 },
+	{ 0x8000a9, 0x00 },
+	{ 0x8000aa, 0x01 },
+	{ 0x8000b0, 0x01 },
+	{ 0x8000b3, 0x02 },
+	{ 0x8000b4, 0x3c },
+	{ 0x8000b6, 0x14 },
+	{ 0x8000c0, 0x11 },
+	{ 0x8000c1, 0x00 },
+	{ 0x8000c2, 0x05 },
+	{ 0x8000c4, 0x00 },
+	{ 0x8000c6, 0x19 },
+	{ 0x8000c7, 0x00 },
+	{ 0x8000cc, 0x2e },
+	{ 0x8000cd, 0x51 },
+	{ 0x8000ce, 0x33 },
+	{ 0x8000f3, 0x05 },
+	{ 0x8000f4, 0x8c },
+	{ 0x8000f5, 0x8c },
+	{ 0x8000f8, 0x03 },
+	{ 0x8000f9, 0x06 },
+	{ 0x8000fa, 0x06 },
+	{ 0x8000fc, 0x03 },
+	{ 0x8000fd, 0x02 },
+	{ 0x8000fe, 0x02 },
+	{ 0x8000ff, 0x09 },
+	{ 0x800100, 0x50 },
+	{ 0x800101, 0x7a },
+	{ 0x800102, 0x77 },
+	{ 0x800103, 0x01 },
+	{ 0x800104, 0x02 },
+	{ 0x800105, 0xb0 },
+	{ 0x800106, 0x02 },
+	{ 0x800107, 0x7a },
+	{ 0x800109, 0x02 },
+	{ 0x800115, 0x0a },
+	{ 0x800116, 0x03 },
+	{ 0x800117, 0x02 },
+	{ 0x800118, 0x80 },
+	{ 0x80011a, 0xc0 },
+	{ 0x80011b, 0x7a },
+	{ 0x80011c, 0xac },
+	{ 0x80011d, 0x8c },
+	{ 0x800122, 0x02 },
+	{ 0x800123, 0x70 },
+	{ 0x800124, 0xa4 },
+	{ 0x800127, 0x00 },
+	{ 0x800128, 0x07 },
+	{ 0x80012a, 0x53 },
+	{ 0x80012b, 0x51 },
+	{ 0x80012c, 0x4e },
+	{ 0x80012d, 0x43 },
+	{ 0x800137, 0x01 },
+	{ 0x800138, 0x00 },
+	{ 0x800139, 0x07 },
+	{ 0x80013a, 0x00 },
+	{ 0x80013b, 0x06 },
+	{ 0x80013d, 0x00 },
+	{ 0x80013e, 0x01 },
+	{ 0x80013f, 0x5b },
+	{ 0x800140, 0xc0 },
+	{ 0x800141, 0x59 },
+	{ 0x80f000, 0x0f },
+	{ 0x80f016, 0x10 },
+	{ 0x80f017, 0x04 },
+	{ 0x80f018, 0x05 },
+	{ 0x80f019, 0x04 },
+	{ 0x80f01a, 0x05 },
+	{ 0x80f01f, 0x8c },
+	{ 0x80f020, 0x00 },
+	{ 0x80f021, 0x03 },
+	{ 0x80f022, 0x0a },
+	{ 0x80f023, 0x0a },
+	{ 0x80f029, 0x8c },
+	{ 0x80f02a, 0x00 },
+	{ 0x80f02b, 0x00 },
+	{ 0x80f02c, 0x01 },
+	{ 0x80f064, 0x03 },
+	{ 0x80f065, 0xf9 },
+	{ 0x80f066, 0x03 },
+	{ 0x80f067, 0x01 },
+	{ 0x80f06f, 0xe0 },
+	{ 0x80f070, 0x03 },
+	{ 0x80f072, 0x0f },
+	{ 0x80f073, 0x03 },
+	{ 0x80f077, 0x01 },
+	{ 0x80f078, 0x00 },
+	{ 0x80f085, 0xc0 },
+	{ 0x80f086, 0x01 },
+	{ 0x80f087, 0x00 },
+	{ 0x80f09b, 0x3f },
+	{ 0x80f09c, 0x00 },
+	{ 0x80f09d, 0x20 },
+	{ 0x80f09e, 0x00 },
+	{ 0x80f09f, 0x0c },
+	{ 0x80f0a0, 0x00 },
+	{ 0x80f130, 0x04 },
+	{ 0x80f132, 0x04 },
+	{ 0x80f144, 0x1a },
+	{ 0x80f146, 0x00 },
+	{ 0x80f14a, 0x01 },
+	{ 0x80f14c, 0x00 },
+	{ 0x80f14d, 0x00 },
+	{ 0x80f14f, 0x04 },
+	{ 0x80f158, 0x7f },
+	{ 0x80f15a, 0x00 },
+	{ 0x80f15b, 0x08 },
+	{ 0x80f15d, 0x03 },
+	{ 0x80f15e, 0x05 },
+	{ 0x80f163, 0x05 },
+	{ 0x80f166, 0x01 },
+	{ 0x80f167, 0x40 },
+	{ 0x80f168, 0x0f },
+	{ 0x80f17a, 0x00 },
+	{ 0x80f17b, 0x00 },
+	{ 0x80f183, 0x01 },
+	{ 0x80f19d, 0x40 },
+	{ 0x80f1bc, 0x36 },
+	{ 0x80f1bd, 0x00 },
+	{ 0x80f1cb, 0xa0 },
+	{ 0x80f1cc, 0x01 },
+	{ 0x80f204, 0x10 },
+	{ 0x80f214, 0x00 },
+	{ 0x80f24c, 0x88 },
+	{ 0x80f24d, 0x95 },
+	{ 0x80f24e, 0x9a },
+	{ 0x80f24f, 0x90 },
+	{ 0x80f25a, 0x07 },
+	{ 0x80f25b, 0xe8 },
+	{ 0x80f25c, 0x03 },
+	{ 0x80f25d, 0xb0 },
+	{ 0x80f25e, 0x04 },
+	{ 0x80f270, 0x01 },
+	{ 0x80f271, 0x02 },
+	{ 0x80f272, 0x01 },
+	{ 0x80f273, 0x02 },
+	{ 0x80f40e, 0x0a },
+	{ 0x80f40f, 0x40 },
+	{ 0x80f410, 0x08 },
+	{ 0x80f55f, 0x0a },
+	{ 0x80f561, 0x15 },
+	{ 0x80f562, 0x20 },
+	{ 0x80f5df, 0xfb },
+	{ 0x80f5e0, 0x00 },
+	{ 0x80f5e3, 0x09 },
+	{ 0x80f5e4, 0x01 },
+	{ 0x80f5e5, 0x01 },
+	{ 0x80f5f8, 0x01 },
+	{ 0x80f5fd, 0x01 },
+	{ 0x80f600, 0x05 },
+	{ 0x80f601, 0x08 },
+	{ 0x80f602, 0x0b },
+	{ 0x80f603, 0x0e },
+	{ 0x80f604, 0x11 },
+	{ 0x80f605, 0x14 },
+	{ 0x80f606, 0x17 },
+	{ 0x80f607, 0x1f },
+	{ 0x80f60e, 0x00 },
+	{ 0x80f60f, 0x04 },
+	{ 0x80f610, 0x32 },
+	{ 0x80f611, 0x10 },
+	{ 0x80f707, 0xfc },
+	{ 0x80f708, 0x00 },
+	{ 0x80f709, 0x37 },
+	{ 0x80f70a, 0x00 },
+	{ 0x80f78b, 0x01 },
+	{ 0x80f80f, 0x40 },
+	{ 0x80f810, 0x54 },
+	{ 0x80f811, 0x5a },
+	{ 0x80f905, 0x01 },
+	{ 0x80fb06, 0x03 },
+	{ 0x80fd8b, 0x00 },
+};
+
+/* ITE Tech IT9135 Omega LNA config 2 tuner init
+   AF9033_TUNER_IT9135_52   = 0x52 */
+static const struct reg_val tuner_init_it9135_52[] = {
+	{ 0x800043, 0x00 },
+	{ 0x800046, 0x52 },
+	{ 0x800051, 0x01 },
+	{ 0x80005f, 0x00 },
+	{ 0x800060, 0x00 },
+	{ 0x800068, 0x10 },
+	{ 0x800070, 0x0a },
+	{ 0x800071, 0x05 },
+	{ 0x800072, 0x02 },
+	{ 0x800075, 0x8c },
+	{ 0x800076, 0x8c },
+	{ 0x800077, 0x8c },
+	{ 0x800078, 0xa0 },
+	{ 0x800079, 0x01 },
+	{ 0x80007e, 0x04 },
+	{ 0x80007f, 0x00 },
+	{ 0x800081, 0x0a },
+	{ 0x800082, 0x17 },
+	{ 0x800083, 0x03 },
+	{ 0x800084, 0x0a },
+	{ 0x800085, 0x03 },
+	{ 0x800086, 0xb3 },
+	{ 0x800087, 0x97 },
+	{ 0x800088, 0xc0 },
+	{ 0x800089, 0x9e },
+	{ 0x80008a, 0x01 },
+	{ 0x80008e, 0x01 },
+	{ 0x800092, 0x06 },
+	{ 0x800093, 0x00 },
+	{ 0x800094, 0x00 },
+	{ 0x800095, 0x00 },
+	{ 0x800096, 0x00 },
+	{ 0x800099, 0x01 },
+	{ 0x80009b, 0x3c },
+	{ 0x80009c, 0x28 },
+	{ 0x80009f, 0xe1 },
+	{ 0x8000a0, 0xcf },
+	{ 0x8000a3, 0x01 },
+	{ 0x8000a4, 0x5c },
+	{ 0x8000a5, 0x01 },
+	{ 0x8000a6, 0x01 },
+	{ 0x8000a9, 0x00 },
+	{ 0x8000aa, 0x01 },
+	{ 0x8000b0, 0x01 },
+	{ 0x8000b3, 0x02 },
+	{ 0x8000b4, 0x3c },
+	{ 0x8000b6, 0x14 },
+	{ 0x8000c0, 0x11 },
+	{ 0x8000c1, 0x00 },
+	{ 0x8000c2, 0x05 },
+	{ 0x8000c4, 0x00 },
+	{ 0x8000c6, 0x19 },
+	{ 0x8000c7, 0x00 },
+	{ 0x8000cc, 0x2e },
+	{ 0x8000cd, 0x51 },
+	{ 0x8000ce, 0x33 },
+	{ 0x8000f3, 0x05 },
+	{ 0x8000f4, 0x91 },
+	{ 0x8000f5, 0x8c },
+	{ 0x8000f8, 0x03 },
+	{ 0x8000f9, 0x06 },
+	{ 0x8000fa, 0x06 },
+	{ 0x8000fc, 0x03 },
+	{ 0x8000fd, 0x02 },
+	{ 0x8000fe, 0x02 },
+	{ 0x8000ff, 0x09 },
+	{ 0x800100, 0x50 },
+	{ 0x800101, 0x74 },
+	{ 0x800102, 0x77 },
+	{ 0x800103, 0x02 },
+	{ 0x800104, 0x02 },
+	{ 0x800105, 0xa4 },
+	{ 0x800106, 0x02 },
+	{ 0x800107, 0x6e },
+	{ 0x800109, 0x02 },
+	{ 0x800115, 0x0a },
+	{ 0x800116, 0x03 },
+	{ 0x800117, 0x02 },
+	{ 0x800118, 0x80 },
+	{ 0x80011a, 0xcd },
+	{ 0x80011b, 0x62 },
+	{ 0x80011c, 0xa4 },
+	{ 0x80011d, 0x8c },
+	{ 0x800122, 0x03 },
+	{ 0x800123, 0x18 },
+	{ 0x800124, 0x9e },
+	{ 0x800127, 0x00 },
+	{ 0x800128, 0x07 },
+	{ 0x80012a, 0x53 },
+	{ 0x80012b, 0x51 },
+	{ 0x80012c, 0x4e },
+	{ 0x80012d, 0x43 },
+	{ 0x800137, 0x00 },
+	{ 0x800138, 0x00 },
+	{ 0x800139, 0x07 },
+	{ 0x80013a, 0x00 },
+	{ 0x80013b, 0x06 },
+	{ 0x80013d, 0x00 },
+	{ 0x80013e, 0x01 },
+	{ 0x80013f, 0x5b },
+	{ 0x800140, 0xb6 },
+	{ 0x800141, 0x59 },
+	{ 0x80f000, 0x0f },
+	{ 0x80f016, 0x10 },
+	{ 0x80f017, 0x04 },
+	{ 0x80f018, 0x05 },
+	{ 0x80f019, 0x04 },
+	{ 0x80f01a, 0x05 },
+	{ 0x80f01f, 0x8c },
+	{ 0x80f020, 0x00 },
+	{ 0x80f021, 0x03 },
+	{ 0x80f022, 0x0a },
+	{ 0x80f023, 0x0a },
+	{ 0x80f029, 0x8c },
+	{ 0x80f02a, 0x00 },
+	{ 0x80f02b, 0x00 },
+	{ 0x80f02c, 0x01 },
+	{ 0x80f064, 0x03 },
+	{ 0x80f065, 0xf9 },
+	{ 0x80f066, 0x03 },
+	{ 0x80f067, 0x01 },
+	{ 0x80f06f, 0xe0 },
+	{ 0x80f070, 0x03 },
+	{ 0x80f072, 0x0f },
+	{ 0x80f073, 0x03 },
+	{ 0x80f077, 0x01 },
+	{ 0x80f078, 0x00 },
+	{ 0x80f085, 0xc0 },
+	{ 0x80f086, 0x01 },
+	{ 0x80f087, 0x00 },
+	{ 0x80f09b, 0x3f },
+	{ 0x80f09c, 0x00 },
+	{ 0x80f09d, 0x20 },
+	{ 0x80f09e, 0x00 },
+	{ 0x80f09f, 0x0c },
+	{ 0x80f0a0, 0x00 },
+	{ 0x80f130, 0x04 },
+	{ 0x80f132, 0x04 },
+	{ 0x80f144, 0x1a },
+	{ 0x80f146, 0x00 },
+	{ 0x80f14a, 0x01 },
+	{ 0x80f14c, 0x00 },
+	{ 0x80f14d, 0x00 },
+	{ 0x80f14f, 0x04 },
+	{ 0x80f158, 0x7f },
+	{ 0x80f15a, 0x00 },
+	{ 0x80f15b, 0x08 },
+	{ 0x80f15d, 0x03 },
+	{ 0x80f15e, 0x05 },
+	{ 0x80f163, 0x05 },
+	{ 0x80f166, 0x01 },
+	{ 0x80f167, 0x40 },
+	{ 0x80f168, 0x0f },
+	{ 0x80f17a, 0x00 },
+	{ 0x80f17b, 0x00 },
+	{ 0x80f183, 0x01 },
+	{ 0x80f19d, 0x40 },
+	{ 0x80f1bc, 0x36 },
+	{ 0x80f1bd, 0x00 },
+	{ 0x80f1cb, 0xa0 },
+	{ 0x80f1cc, 0x01 },
+	{ 0x80f204, 0x10 },
+	{ 0x80f214, 0x00 },
+	{ 0x80f24c, 0x88 },
+	{ 0x80f24d, 0x95 },
+	{ 0x80f24e, 0x9a },
+	{ 0x80f24f, 0x90 },
+	{ 0x80f25a, 0x07 },
+	{ 0x80f25b, 0xe8 },
+	{ 0x80f25c, 0x03 },
+	{ 0x80f25d, 0xb0 },
+	{ 0x80f25e, 0x04 },
+	{ 0x80f270, 0x01 },
+	{ 0x80f271, 0x02 },
+	{ 0x80f272, 0x01 },
+	{ 0x80f273, 0x02 },
+	{ 0x80f40e, 0x0a },
+	{ 0x80f40f, 0x40 },
+	{ 0x80f410, 0x08 },
+	{ 0x80f55f, 0x0a },
+	{ 0x80f561, 0x15 },
+	{ 0x80f562, 0x20 },
+	{ 0x80f5df, 0xfb },
+	{ 0x80f5e0, 0x00 },
+	{ 0x80f5e3, 0x09 },
+	{ 0x80f5e4, 0x01 },
+	{ 0x80f5e5, 0x01 },
+	{ 0x80f5f8, 0x01 },
+	{ 0x80f5fd, 0x01 },
+	{ 0x80f600, 0x05 },
+	{ 0x80f601, 0x08 },
+	{ 0x80f602, 0x0b },
+	{ 0x80f603, 0x0e },
+	{ 0x80f604, 0x11 },
+	{ 0x80f605, 0x14 },
+	{ 0x80f606, 0x17 },
+	{ 0x80f607, 0x1f },
+	{ 0x80f60e, 0x00 },
+	{ 0x80f60f, 0x04 },
+	{ 0x80f610, 0x32 },
+	{ 0x80f611, 0x10 },
+	{ 0x80f707, 0xfc },
+	{ 0x80f708, 0x00 },
+	{ 0x80f709, 0x37 },
+	{ 0x80f70a, 0x00 },
+	{ 0x80f78b, 0x01 },
+	{ 0x80f80f, 0x40 },
+	{ 0x80f810, 0x54 },
+	{ 0x80f811, 0x5a },
+	{ 0x80f905, 0x01 },
+	{ 0x80fb06, 0x03 },
+	{ 0x80fd8b, 0x00 },
+};
+
+static const struct reg_val ofsm_init_it9135_v2[] = {
+	{ 0x800051, 0x01 },
+	{ 0x800070, 0x0a },
+	{ 0x80007e, 0x04 },
+	{ 0x800081, 0x0a },
+	{ 0x80008a, 0x01 },
+	{ 0x80008e, 0x01 },
+	{ 0x800092, 0x06 },
+	{ 0x800099, 0x01 },
+	{ 0x80009f, 0xe1 },
+	{ 0x8000a0, 0xcf },
+	{ 0x8000a3, 0x01 },
+	{ 0x8000a5, 0x01 },
+	{ 0x8000a6, 0x01 },
+	{ 0x8000a9, 0x00 },
+	{ 0x8000aa, 0x01 },
+	{ 0x8000b0, 0x01 },
+	{ 0x8000c2, 0x05 },
+	{ 0x8000c6, 0x19 },
+	{ 0x80f000, 0x0f },
+	{ 0x80f02b, 0x00 },
+	{ 0x80f064, 0x03 },
+	{ 0x80f065, 0xf9 },
+	{ 0x80f066, 0x03 },
+	{ 0x80f067, 0x01 },
+	{ 0x80f06f, 0xe0 },
+	{ 0x80f070, 0x03 },
+	{ 0x80f072, 0x0f },
+	{ 0x80f073, 0x03 },
+	{ 0x80f078, 0x00 },
+	{ 0x80f087, 0x00 },
+	{ 0x80f09b, 0x3f },
+	{ 0x80f09c, 0x00 },
+	{ 0x80f09d, 0x20 },
+	{ 0x80f09e, 0x00 },
+	{ 0x80f09f, 0x0c },
+	{ 0x80f0a0, 0x00 },
+	{ 0x80f130, 0x04 },
+	{ 0x80f132, 0x04 },
+	{ 0x80f144, 0x1a },
+	{ 0x80f146, 0x00 },
+	{ 0x80f14a, 0x01 },
+	{ 0x80f14c, 0x00 },
+	{ 0x80f14d, 0x00 },
+	{ 0x80f14f, 0x04 },
+	{ 0x80f158, 0x7f },
+	{ 0x80f15a, 0x00 },
+	{ 0x80f15b, 0x08 },
+	{ 0x80f15d, 0x03 },
+	{ 0x80f15e, 0x05 },
+	{ 0x80f163, 0x05 },
+	{ 0x80f166, 0x01 },
+	{ 0x80f167, 0x40 },
+	{ 0x80f168, 0x0f },
+	{ 0x80f17a, 0x00 },
+	{ 0x80f17b, 0x00 },
+	{ 0x80f183, 0x01 },
+	{ 0x80f19d, 0x40 },
+	{ 0x80f1bc, 0x36 },
+	{ 0x80f1bd, 0x00 },
+	{ 0x80f1cb, 0xa0 },
+	{ 0x80f1cc, 0x01 },
+	{ 0x80f204, 0x10 },
+	{ 0x80f214, 0x00 },
+	{ 0x80f40e, 0x0a },
+	{ 0x80f40f, 0x40 },
+	{ 0x80f410, 0x08 },
+	{ 0x80f55f, 0x0a },
+	{ 0x80f561, 0x15 },
+	{ 0x80f562, 0x20 },
+	{ 0x80f5e3, 0x09 },
+	{ 0x80f5e4, 0x01 },
+	{ 0x80f5e5, 0x01 },
+	{ 0x80f600, 0x05 },
+	{ 0x80f601, 0x08 },
+	{ 0x80f602, 0x0b },
+	{ 0x80f603, 0x0e },
+	{ 0x80f604, 0x11 },
+	{ 0x80f605, 0x14 },
+	{ 0x80f606, 0x17 },
+	{ 0x80f607, 0x1f },
+	{ 0x80f60e, 0x00 },
+	{ 0x80f60f, 0x04 },
+	{ 0x80f610, 0x32 },
+	{ 0x80f611, 0x10 },
+	{ 0x80f707, 0xfc },
+	{ 0x80f708, 0x00 },
+	{ 0x80f709, 0x37 },
+	{ 0x80f70a, 0x00 },
+	{ 0x80f78b, 0x01 },
+	{ 0x80f80f, 0x40 },
+	{ 0x80f810, 0x54 },
+	{ 0x80f811, 0x5a },
+	{ 0x80f905, 0x01 },
+	{ 0x80fb06, 0x03 },
+	{ 0x80fd8b, 0x00 },
+};
+
+/* ITE Tech IT9135 Omega v2 tuner init
+   AF9033_TUNER_IT9135_60   = 0x60 */
+static const struct reg_val tuner_init_it9135_60[] = {
+	{ 0x800043, 0x00 },
+	{ 0x800046, 0x60 },
+	{ 0x800051, 0x01 },
+	{ 0x80005f, 0x00 },
+	{ 0x800060, 0x00 },
+	{ 0x800068, 0x0a },
+	{ 0x80006a, 0x03 },
+	{ 0x800070, 0x0a },
+	{ 0x800071, 0x05 },
+	{ 0x800072, 0x02 },
+	{ 0x800075, 0x8c },
+	{ 0x800076, 0x8c },
+	{ 0x800077, 0x8c },
+	{ 0x800078, 0x8c },
+	{ 0x800079, 0x01 },
+	{ 0x80007e, 0x04 },
+	{ 0x800081, 0x0a },
+	{ 0x800082, 0x18 },
+	{ 0x800084, 0x0a },
+	{ 0x800085, 0x33 },
+	{ 0x800086, 0xbe },
+	{ 0x800087, 0xa0 },
+	{ 0x800088, 0xc6 },
+	{ 0x800089, 0xb6 },
+	{ 0x80008a, 0x01 },
+	{ 0x80008e, 0x01 },
+	{ 0x800092, 0x06 },
+	{ 0x800093, 0x00 },
+	{ 0x800094, 0x00 },
+	{ 0x800095, 0x00 },
+	{ 0x800096, 0x00 },
+	{ 0x800099, 0x01 },
+	{ 0x80009b, 0x3c },
+	{ 0x80009c, 0x28 },
+	{ 0x80009f, 0xe1 },
+	{ 0x8000a0, 0xcf },
+	{ 0x8000a3, 0x01 },
+	{ 0x8000a4, 0x5a },
+	{ 0x8000a5, 0x01 },
+	{ 0x8000a6, 0x01 },
+	{ 0x8000a9, 0x00 },
+	{ 0x8000aa, 0x01 },
+	{ 0x8000b0, 0x01 },
+	{ 0x8000b3, 0x02 },
+	{ 0x8000b4, 0x3a },
+	{ 0x8000b6, 0x14 },
+	{ 0x8000c0, 0x11 },
+	{ 0x8000c1, 0x00 },
+	{ 0x8000c2, 0x05 },
+	{ 0x8000c3, 0x01 },
+	{ 0x8000c4, 0x00 },
+	{ 0x8000c6, 0x19 },
+	{ 0x8000c7, 0x00 },
+	{ 0x8000cb, 0x32 },
+	{ 0x8000cc, 0x2c },
+	{ 0x8000cd, 0x4f },
+	{ 0x8000ce, 0x30 },
+	{ 0x8000f3, 0x05 },
+	{ 0x8000f4, 0xa0 },
+	{ 0x8000f5, 0x8c },
+	{ 0x8000f8, 0x03 },
+	{ 0x8000f9, 0x06 },
+	{ 0x8000fa, 0x06 },
+	{ 0x8000fc, 0x03 },
+	{ 0x8000fd, 0x03 },
+	{ 0x8000fe, 0x02 },
+	{ 0x8000ff, 0x0a },
+	{ 0x800100, 0x50 },
+	{ 0x800101, 0x7b },
+	{ 0x800102, 0x8c },
+	{ 0x800103, 0x00 },
+	{ 0x800104, 0x02 },
+	{ 0x800105, 0xbe },
+	{ 0x800106, 0x00 },
+	{ 0x800109, 0x02 },
+	{ 0x800115, 0x0a },
+	{ 0x800116, 0x03 },
+	{ 0x80011a, 0xbe },
+	{ 0x800124, 0xae },
+	{ 0x800127, 0x00 },
+	{ 0x80012a, 0x56 },
+	{ 0x80012b, 0x50 },
+	{ 0x80012c, 0x47 },
+	{ 0x80012d, 0x42 },
+	{ 0x800137, 0x00 },
+	{ 0x80013b, 0x08 },
+	{ 0x80013f, 0x5b },
+	{ 0x800141, 0x59 },
+	{ 0x800142, 0xf9 },
+	{ 0x800143, 0x19 },
+	{ 0x800144, 0x00 },
+	{ 0x800145, 0x8c },
+	{ 0x800146, 0x8c },
+	{ 0x800147, 0x8c },
+	{ 0x800148, 0x6e },
+	{ 0x800149, 0x8c },
+	{ 0x80014a, 0x50 },
+	{ 0x80014b, 0x8c },
+	{ 0x80014d, 0xac },
+	{ 0x80014e, 0xc6 },
+	{ 0x80014f, 0x03 },
+	{ 0x800151, 0x1e },
+	{ 0x800153, 0xbc },
+	{ 0x800178, 0x09 },
+	{ 0x800181, 0x94 },
+	{ 0x800182, 0x6e },
+	{ 0x800185, 0x24 },
+	{ 0x800189, 0xbe },
+	{ 0x80018c, 0x03 },
+	{ 0x80018d, 0x5f },
+	{ 0x80018f, 0xa0 },
+	{ 0x800190, 0x5a },
+	{ 0x80ed02, 0xff },
+	{ 0x80ee42, 0xff },
+	{ 0x80ee82, 0xff },
+	{ 0x80f000, 0x0f },
+	{ 0x80f01f, 0x8c },
+	{ 0x80f020, 0x00 },
+	{ 0x80f029, 0x8c },
+	{ 0x80f02a, 0x00 },
+	{ 0x80f02b, 0x00 },
+	{ 0x80f064, 0x03 },
+	{ 0x80f065, 0xf9 },
+	{ 0x80f066, 0x03 },
+	{ 0x80f067, 0x01 },
+	{ 0x80f06f, 0xe0 },
+	{ 0x80f070, 0x03 },
+	{ 0x80f072, 0x0f },
+	{ 0x80f073, 0x03 },
+	{ 0x80f077, 0x01 },
+	{ 0x80f078, 0x00 },
+	{ 0x80f087, 0x00 },
+	{ 0x80f09b, 0x3f },
+	{ 0x80f09c, 0x00 },
+	{ 0x80f09d, 0x20 },
+	{ 0x80f09e, 0x00 },
+	{ 0x80f09f, 0x0c },
+	{ 0x80f0a0, 0x00 },
+	{ 0x80f130, 0x04 },
+	{ 0x80f132, 0x04 },
+	{ 0x80f144, 0x1a },
+	{ 0x80f146, 0x00 },
+	{ 0x80f14a, 0x01 },
+	{ 0x80f14c, 0x00 },
+	{ 0x80f14d, 0x00 },
+	{ 0x80f14f, 0x04 },
+	{ 0x80f158, 0x7f },
+	{ 0x80f15a, 0x00 },
+	{ 0x80f15b, 0x08 },
+	{ 0x80f15d, 0x03 },
+	{ 0x80f15e, 0x05 },
+	{ 0x80f163, 0x05 },
+	{ 0x80f166, 0x01 },
+	{ 0x80f167, 0x40 },
+	{ 0x80f168, 0x0f },
+	{ 0x80f17a, 0x00 },
+	{ 0x80f17b, 0x00 },
+	{ 0x80f183, 0x01 },
+	{ 0x80f19d, 0x40 },
+	{ 0x80f1bc, 0x36 },
+	{ 0x80f1bd, 0x00 },
+	{ 0x80f1cb, 0xa0 },
+	{ 0x80f1cc, 0x01 },
+	{ 0x80f204, 0x10 },
+	{ 0x80f214, 0x00 },
+	{ 0x80f24c, 0x88 },
+	{ 0x80f24d, 0x95 },
+	{ 0x80f24e, 0x9a },
+	{ 0x80f24f, 0x90 },
+	{ 0x80f25a, 0x07 },
+	{ 0x80f25b, 0xe8 },
+	{ 0x80f25c, 0x03 },
+	{ 0x80f25d, 0xb0 },
+	{ 0x80f25e, 0x04 },
+	{ 0x80f270, 0x01 },
+	{ 0x80f271, 0x02 },
+	{ 0x80f272, 0x01 },
+	{ 0x80f273, 0x02 },
+	{ 0x80f40e, 0x0a },
+	{ 0x80f40f, 0x40 },
+	{ 0x80f410, 0x08 },
+	{ 0x80f55f, 0x0a },
+	{ 0x80f561, 0x15 },
+	{ 0x80f562, 0x20 },
+	{ 0x80f5e3, 0x09 },
+	{ 0x80f5e4, 0x01 },
+	{ 0x80f5e5, 0x01 },
+	{ 0x80f600, 0x05 },
+	{ 0x80f601, 0x08 },
+	{ 0x80f602, 0x0b },
+	{ 0x80f603, 0x0e },
+	{ 0x80f604, 0x11 },
+	{ 0x80f605, 0x14 },
+	{ 0x80f606, 0x17 },
+	{ 0x80f607, 0x1f },
+	{ 0x80f60e, 0x00 },
+	{ 0x80f60f, 0x04 },
+	{ 0x80f610, 0x32 },
+	{ 0x80f611, 0x10 },
+	{ 0x80f707, 0xfc },
+	{ 0x80f708, 0x00 },
+	{ 0x80f709, 0x37 },
+	{ 0x80f70a, 0x00 },
+	{ 0x80f78b, 0x01 },
+	{ 0x80f80f, 0x40 },
+	{ 0x80f810, 0x54 },
+	{ 0x80f811, 0x5a },
+	{ 0x80f905, 0x01 },
+	{ 0x80fb06, 0x03 },
+	{ 0x80fd8b, 0x00 },
+};
+
+/* ITE Tech IT9135 Omega v2 LNA config 1 tuner init
+   AF9033_TUNER_IT9135_61   = 0x61 */
+static const struct reg_val tuner_init_it9135_61[] = {
+	{ 0x800043, 0x00 },
+	{ 0x800046, 0x61 },
+	{ 0x800051, 0x01 },
+	{ 0x80005f, 0x00 },
+	{ 0x800060, 0x00 },
+	{ 0x800068, 0x06 },
+	{ 0x80006a, 0x03 },
+	{ 0x800070, 0x0a },
+	{ 0x800071, 0x05 },
+	{ 0x800072, 0x02 },
+	{ 0x800075, 0x8c },
+	{ 0x800076, 0x8c },
+	{ 0x800077, 0x8c },
+	{ 0x800078, 0x90 },
+	{ 0x800079, 0x01 },
+	{ 0x80007e, 0x04 },
+	{ 0x800081, 0x0a },
+	{ 0x800082, 0x12 },
+	{ 0x800084, 0x0a },
+	{ 0x800085, 0x33 },
+	{ 0x800086, 0xbc },
+	{ 0x800087, 0x9c },
+	{ 0x800088, 0xcc },
+	{ 0x800089, 0xa8 },
+	{ 0x80008a, 0x01 },
+	{ 0x80008e, 0x01 },
+	{ 0x800092, 0x06 },
+	{ 0x800093, 0x00 },
+	{ 0x800094, 0x00 },
+	{ 0x800095, 0x00 },
+	{ 0x800096, 0x00 },
+	{ 0x800099, 0x01 },
+	{ 0x80009b, 0x3c },
+	{ 0x80009c, 0x28 },
+	{ 0x80009f, 0xe1 },
+	{ 0x8000a0, 0xcf },
+	{ 0x8000a3, 0x01 },
+	{ 0x8000a4, 0x5c },
+	{ 0x8000a5, 0x01 },
+	{ 0x8000a6, 0x01 },
+	{ 0x8000a9, 0x00 },
+	{ 0x8000aa, 0x01 },
+	{ 0x8000b0, 0x01 },
+	{ 0x8000b3, 0x02 },
+	{ 0x8000b4, 0x3a },
+	{ 0x8000b6, 0x14 },
+	{ 0x8000c0, 0x11 },
+	{ 0x8000c1, 0x00 },
+	{ 0x8000c2, 0x05 },
+	{ 0x8000c3, 0x01 },
+	{ 0x8000c4, 0x00 },
+	{ 0x8000c6, 0x19 },
+	{ 0x8000c7, 0x00 },
+	{ 0x8000cb, 0x32 },
+	{ 0x8000cc, 0x2c },
+	{ 0x8000cd, 0x4f },
+	{ 0x8000ce, 0x30 },
+	{ 0x8000f3, 0x05 },
+	{ 0x8000f4, 0xa0 },
+	{ 0x8000f5, 0x8c },
+	{ 0x8000f8, 0x03 },
+	{ 0x8000f9, 0x06 },
+	{ 0x8000fa, 0x06 },
+	{ 0x8000fc, 0x03 },
+	{ 0x8000fd, 0x03 },
+	{ 0x8000fe, 0x02 },
+	{ 0x8000ff, 0x08 },
+	{ 0x800100, 0x50 },
+	{ 0x800101, 0x7b },
+	{ 0x800102, 0x8c },
+	{ 0x800103, 0x01 },
+	{ 0x800104, 0x02 },
+	{ 0x800105, 0xc8 },
+	{ 0x800106, 0x00 },
+	{ 0x800109, 0x02 },
+	{ 0x800115, 0x0a },
+	{ 0x800116, 0x03 },
+	{ 0x80011a, 0xc6 },
+	{ 0x800124, 0xa8 },
+	{ 0x800127, 0x00 },
+	{ 0x80012a, 0x59 },
+	{ 0x80012b, 0x50 },
+	{ 0x80012c, 0x47 },
+	{ 0x80012d, 0x42 },
+	{ 0x800137, 0x00 },
+	{ 0x80013b, 0x05 },
+	{ 0x80013f, 0x5b },
+	{ 0x800141, 0x59 },
+	{ 0x800142, 0xf9 },
+	{ 0x800143, 0x59 },
+	{ 0x800144, 0x01 },
+	{ 0x800145, 0x8c },
+	{ 0x800146, 0x8c },
+	{ 0x800147, 0x8c },
+	{ 0x800148, 0x7b },
+	{ 0x800149, 0x8c },
+	{ 0x80014a, 0x50 },
+	{ 0x80014b, 0x8c },
+	{ 0x80014d, 0xa8 },
+	{ 0x80014e, 0xc6 },
+	{ 0x80014f, 0x03 },
+	{ 0x800151, 0x28 },
+	{ 0x800153, 0xcc },
+	{ 0x800178, 0x09 },
+	{ 0x800181, 0x9c },
+	{ 0x800182, 0x76 },
+	{ 0x800185, 0x28 },
+	{ 0x800189, 0xaa },
+	{ 0x80018c, 0x03 },
+	{ 0x80018d, 0x5f },
+	{ 0x80018f, 0xfb },
+	{ 0x800190, 0x5c },
+	{ 0x80ed02, 0xff },
+	{ 0x80ee42, 0xff },
+	{ 0x80ee82, 0xff },
+	{ 0x80f000, 0x0f },
+	{ 0x80f01f, 0x8c },
+	{ 0x80f020, 0x00 },
+	{ 0x80f029, 0x8c },
+	{ 0x80f02a, 0x00 },
+	{ 0x80f02b, 0x00 },
+	{ 0x80f064, 0x03 },
+	{ 0x80f065, 0xf9 },
+	{ 0x80f066, 0x03 },
+	{ 0x80f067, 0x01 },
+	{ 0x80f06f, 0xe0 },
+	{ 0x80f070, 0x03 },
+	{ 0x80f072, 0x0f },
+	{ 0x80f073, 0x03 },
+	{ 0x80f077, 0x01 },
+	{ 0x80f078, 0x00 },
+	{ 0x80f087, 0x00 },
+	{ 0x80f09b, 0x3f },
+	{ 0x80f09c, 0x00 },
+	{ 0x80f09d, 0x20 },
+	{ 0x80f09e, 0x00 },
+	{ 0x80f09f, 0x0c },
+	{ 0x80f0a0, 0x00 },
+	{ 0x80f130, 0x04 },
+	{ 0x80f132, 0x04 },
+	{ 0x80f144, 0x1a },
+	{ 0x80f146, 0x00 },
+	{ 0x80f14a, 0x01 },
+	{ 0x80f14c, 0x00 },
+	{ 0x80f14d, 0x00 },
+	{ 0x80f14f, 0x04 },
+	{ 0x80f158, 0x7f },
+	{ 0x80f15a, 0x00 },
+	{ 0x80f15b, 0x08 },
+	{ 0x80f15d, 0x03 },
+	{ 0x80f15e, 0x05 },
+	{ 0x80f163, 0x05 },
+	{ 0x80f166, 0x01 },
+	{ 0x80f167, 0x40 },
+	{ 0x80f168, 0x0f },
+	{ 0x80f17a, 0x00 },
+	{ 0x80f17b, 0x00 },
+	{ 0x80f183, 0x01 },
+	{ 0x80f19d, 0x40 },
+	{ 0x80f1bc, 0x36 },
+	{ 0x80f1bd, 0x00 },
+	{ 0x80f1cb, 0xa0 },
+	{ 0x80f1cc, 0x01 },
+	{ 0x80f204, 0x10 },
+	{ 0x80f214, 0x00 },
+	{ 0x80f24c, 0x88 },
+	{ 0x80f24d, 0x95 },
+	{ 0x80f24e, 0x9a },
+	{ 0x80f24f, 0x90 },
+	{ 0x80f25a, 0x07 },
+	{ 0x80f25b, 0xe8 },
+	{ 0x80f25c, 0x03 },
+	{ 0x80f25d, 0xb0 },
+	{ 0x80f25e, 0x04 },
+	{ 0x80f270, 0x01 },
+	{ 0x80f271, 0x02 },
+	{ 0x80f272, 0x01 },
+	{ 0x80f273, 0x02 },
+	{ 0x80f40e, 0x0a },
+	{ 0x80f40f, 0x40 },
+	{ 0x80f410, 0x08 },
+	{ 0x80f55f, 0x0a },
+	{ 0x80f561, 0x15 },
+	{ 0x80f562, 0x20 },
+	{ 0x80f5e3, 0x09 },
+	{ 0x80f5e4, 0x01 },
+	{ 0x80f5e5, 0x01 },
+	{ 0x80f600, 0x05 },
+	{ 0x80f601, 0x08 },
+	{ 0x80f602, 0x0b },
+	{ 0x80f603, 0x0e },
+	{ 0x80f604, 0x11 },
+	{ 0x80f605, 0x14 },
+	{ 0x80f606, 0x17 },
+	{ 0x80f607, 0x1f },
+	{ 0x80f60e, 0x00 },
+	{ 0x80f60f, 0x04 },
+	{ 0x80f610, 0x32 },
+	{ 0x80f611, 0x10 },
+	{ 0x80f707, 0xfc },
+	{ 0x80f708, 0x00 },
+	{ 0x80f709, 0x37 },
+	{ 0x80f70a, 0x00 },
+	{ 0x80f78b, 0x01 },
+	{ 0x80f80f, 0x40 },
+	{ 0x80f810, 0x54 },
+	{ 0x80f811, 0x5a },
+	{ 0x80f905, 0x01 },
+	{ 0x80fb06, 0x03 },
+	{ 0x80fd8b, 0x00 },
+};
+
+/* ITE Tech IT9135 Omega v2 LNA config 2 tuner init
+   AF9033_TUNER_IT9135_62   = 0x62 */
+static const struct reg_val tuner_init_it9135_62[] = {
+	{ 0x800043, 0x00 },
+	{ 0x800046, 0x62 },
+	{ 0x800051, 0x01 },
+	{ 0x80005f, 0x00 },
+	{ 0x800060, 0x00 },
+	{ 0x800068, 0x0a },
+	{ 0x80006a, 0x03 },
+	{ 0x800070, 0x0a },
+	{ 0x800071, 0x05 },
+	{ 0x800072, 0x02 },
+	{ 0x800075, 0x8c },
+	{ 0x800076, 0x8c },
+	{ 0x800077, 0x8c },
+	{ 0x800078, 0x8c },
+	{ 0x800079, 0x01 },
+	{ 0x80007e, 0x04 },
+	{ 0x800081, 0x0a },
+	{ 0x800082, 0x12 },
+	{ 0x800084, 0x0a },
+	{ 0x800085, 0x33 },
+	{ 0x800086, 0xb8 },
+	{ 0x800087, 0x9c },
+	{ 0x800088, 0xb2 },
+	{ 0x800089, 0xa6 },
+	{ 0x80008a, 0x01 },
+	{ 0x80008e, 0x01 },
+	{ 0x800092, 0x06 },
+	{ 0x800093, 0x00 },
+	{ 0x800094, 0x00 },
+	{ 0x800095, 0x00 },
+	{ 0x800096, 0x00 },
+	{ 0x800099, 0x01 },
+	{ 0x80009b, 0x3c },
+	{ 0x80009c, 0x28 },
+	{ 0x80009f, 0xe1 },
+	{ 0x8000a0, 0xcf },
+	{ 0x8000a3, 0x01 },
+	{ 0x8000a4, 0x5a },
+	{ 0x8000a5, 0x01 },
+	{ 0x8000a6, 0x01 },
+	{ 0x8000a9, 0x00 },
+	{ 0x8000aa, 0x01 },
+	{ 0x8000b0, 0x01 },
+	{ 0x8000b3, 0x02 },
+	{ 0x8000b4, 0x3a },
+	{ 0x8000b6, 0x14 },
+	{ 0x8000c0, 0x11 },
+	{ 0x8000c1, 0x00 },
+	{ 0x8000c2, 0x05 },
+	{ 0x8000c3, 0x01 },
+	{ 0x8000c4, 0x00 },
+	{ 0x8000c6, 0x19 },
+	{ 0x8000c7, 0x00 },
+	{ 0x8000cb, 0x32 },
+	{ 0x8000cc, 0x2c },
+	{ 0x8000cd, 0x4f },
+	{ 0x8000ce, 0x30 },
+	{ 0x8000f3, 0x05 },
+	{ 0x8000f4, 0x8c },
+	{ 0x8000f5, 0x8c },
+	{ 0x8000f8, 0x03 },
+	{ 0x8000f9, 0x06 },
+	{ 0x8000fa, 0x06 },
+	{ 0x8000fc, 0x02 },
+	{ 0x8000fd, 0x03 },
+	{ 0x8000fe, 0x02 },
+	{ 0x8000ff, 0x09 },
+	{ 0x800100, 0x50 },
+	{ 0x800101, 0x6e },
+	{ 0x800102, 0x8c },
+	{ 0x800103, 0x02 },
+	{ 0x800104, 0x02 },
+	{ 0x800105, 0xc2 },
+	{ 0x800106, 0x00 },
+	{ 0x800109, 0x02 },
+	{ 0x800115, 0x0a },
+	{ 0x800116, 0x03 },
+	{ 0x80011a, 0xb8 },
+	{ 0x800124, 0xa8 },
+	{ 0x800127, 0x00 },
+	{ 0x80012a, 0x53 },
+	{ 0x80012b, 0x51 },
+	{ 0x80012c, 0x4e },
+	{ 0x80012d, 0x43 },
+	{ 0x800137, 0x00 },
+	{ 0x80013b, 0x05 },
+	{ 0x80013f, 0x5b },
+	{ 0x800141, 0x59 },
+	{ 0x800142, 0xf9 },
+	{ 0x800143, 0x59 },
+	{ 0x800144, 0x00 },
+	{ 0x800145, 0x8c },
+	{ 0x800146, 0x8c },
+	{ 0x800147, 0x8c },
+	{ 0x800148, 0x7b },
+	{ 0x800149, 0x8c },
+	{ 0x80014a, 0x50 },
+	{ 0x80014b, 0x70 },
+	{ 0x80014d, 0x96 },
+	{ 0x80014e, 0xd0 },
+	{ 0x80014f, 0x03 },
+	{ 0x800151, 0x28 },
+	{ 0x800153, 0xb2 },
+	{ 0x800178, 0x09 },
+	{ 0x800181, 0x9c },
+	{ 0x800182, 0x6e },
+	{ 0x800185, 0x24 },
+	{ 0x800189, 0xb8 },
+	{ 0x80018c, 0x03 },
+	{ 0x80018d, 0x5f },
+	{ 0x80018f, 0xfb },
+	{ 0x800190, 0x5a },
+	{ 0x80ed02, 0xff },
+	{ 0x80ee42, 0xff },
+	{ 0x80ee82, 0xff },
+	{ 0x80f000, 0x0f },
+	{ 0x80f01f, 0x8c },
+	{ 0x80f020, 0x00 },
+	{ 0x80f029, 0x8c },
+	{ 0x80f02a, 0x00 },
+	{ 0x80f02b, 0x00 },
+	{ 0x80f064, 0x03 },
+	{ 0x80f065, 0xf9 },
+	{ 0x80f066, 0x03 },
+	{ 0x80f067, 0x01 },
+	{ 0x80f06f, 0xe0 },
+	{ 0x80f070, 0x03 },
+	{ 0x80f072, 0x0f },
+	{ 0x80f073, 0x03 },
+	{ 0x80f077, 0x01 },
+	{ 0x80f078, 0x00 },
+	{ 0x80f087, 0x00 },
+	{ 0x80f09b, 0x3f },
+	{ 0x80f09c, 0x00 },
+	{ 0x80f09d, 0x20 },
+	{ 0x80f09e, 0x00 },
+	{ 0x80f09f, 0x0c },
+	{ 0x80f0a0, 0x00 },
+	{ 0x80f130, 0x04 },
+	{ 0x80f132, 0x04 },
+	{ 0x80f144, 0x1a },
+	{ 0x80f146, 0x00 },
+	{ 0x80f14a, 0x01 },
+	{ 0x80f14c, 0x00 },
+	{ 0x80f14d, 0x00 },
+	{ 0x80f14f, 0x04 },
+	{ 0x80f158, 0x7f },
+	{ 0x80f15a, 0x00 },
+	{ 0x80f15b, 0x08 },
+	{ 0x80f15d, 0x03 },
+	{ 0x80f15e, 0x05 },
+	{ 0x80f163, 0x05 },
+	{ 0x80f166, 0x01 },
+	{ 0x80f167, 0x40 },
+	{ 0x80f168, 0x0f },
+	{ 0x80f17a, 0x00 },
+	{ 0x80f17b, 0x00 },
+	{ 0x80f183, 0x01 },
+	{ 0x80f19d, 0x40 },
+	{ 0x80f1bc, 0x36 },
+	{ 0x80f1bd, 0x00 },
+	{ 0x80f1cb, 0xa0 },
+	{ 0x80f1cc, 0x01 },
+	{ 0x80f204, 0x10 },
+	{ 0x80f214, 0x00 },
+	{ 0x80f24c, 0x88 },
+	{ 0x80f24d, 0x95 },
+	{ 0x80f24e, 0x9a },
+	{ 0x80f24f, 0x90 },
+	{ 0x80f25a, 0x07 },
+	{ 0x80f25b, 0xe8 },
+	{ 0x80f25c, 0x03 },
+	{ 0x80f25d, 0xb0 },
+	{ 0x80f25e, 0x04 },
+	{ 0x80f270, 0x01 },
+	{ 0x80f271, 0x02 },
+	{ 0x80f272, 0x01 },
+	{ 0x80f273, 0x02 },
+	{ 0x80f40e, 0x0a },
+	{ 0x80f40f, 0x40 },
+	{ 0x80f410, 0x08 },
+	{ 0x80f55f, 0x0a },
+	{ 0x80f561, 0x15 },
+	{ 0x80f562, 0x20 },
+	{ 0x80f5e3, 0x09 },
+	{ 0x80f5e4, 0x01 },
+	{ 0x80f5e5, 0x01 },
+	{ 0x80f600, 0x05 },
+	{ 0x80f601, 0x08 },
+	{ 0x80f602, 0x0b },
+	{ 0x80f603, 0x0e },
+	{ 0x80f604, 0x11 },
+	{ 0x80f605, 0x14 },
+	{ 0x80f606, 0x17 },
+	{ 0x80f607, 0x1f },
+	{ 0x80f60e, 0x00 },
+	{ 0x80f60f, 0x04 },
+	{ 0x80f610, 0x32 },
+	{ 0x80f611, 0x10 },
+	{ 0x80f707, 0xfc },
+	{ 0x80f708, 0x00 },
+	{ 0x80f709, 0x37 },
+	{ 0x80f70a, 0x00 },
+	{ 0x80f78b, 0x01 },
+	{ 0x80f80f, 0x40 },
+	{ 0x80f810, 0x54 },
+	{ 0x80f811, 0x5a },
+	{ 0x80f905, 0x01 },
+	{ 0x80fb06, 0x03 },
+	{ 0x80fd8b, 0x00 },
+};
 
+#endif /* AF9033_PRIV_H */
diff --git a/drivers/media/dvb-frontends/atbm8830.h b/drivers/media/dvb-frontends/atbm8830.h
index 0242733..8e0ac98 100644
--- a/drivers/media/dvb-frontends/atbm8830.h
+++ b/drivers/media/dvb-frontends/atbm8830.h
@@ -22,6 +22,7 @@
 #ifndef __ATBM8830_H__
 #define __ATBM8830_H__
 
+#include <linux/kconfig.h>
 #include <linux/dvb/frontend.h>
 #include <linux/i2c.h>
 
@@ -60,8 +61,7 @@ struct atbm8830_config {
 	u8 agc_hold_loop;
 };
 
-#if defined(CONFIG_DVB_ATBM8830) || \
-	(defined(CONFIG_DVB_ATBM8830_MODULE) && defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_ATBM8830)
 extern struct dvb_frontend *atbm8830_attach(const struct atbm8830_config *config,
 		struct i2c_adapter *i2c);
 #else
diff --git a/drivers/media/dvb-frontends/au8522.h b/drivers/media/dvb-frontends/au8522.h
index 565dcf3..83fe9a6 100644
--- a/drivers/media/dvb-frontends/au8522.h
+++ b/drivers/media/dvb-frontends/au8522.h
@@ -22,6 +22,7 @@
 #ifndef __AU8522_H__
 #define __AU8522_H__
 
+#include <linux/kconfig.h>
 #include <linux/dvb/frontend.h>
 
 enum au8522_if_freq {
@@ -60,8 +61,7 @@ struct au8522_config {
 	enum au8522_if_freq qam_if;
 };
 
-#if defined(CONFIG_DVB_AU8522) || 				\
-	    (defined(CONFIG_DVB_AU8522_MODULE) && defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_AU8522_DTV)
 extern struct dvb_frontend *au8522_attach(const struct au8522_config *config,
 					  struct i2c_adapter *i2c);
 #else
diff --git a/drivers/media/dvb-frontends/au8522_decoder.c b/drivers/media/dvb-frontends/au8522_decoder.c
index 5243ba6..2099f21 100644
--- a/drivers/media/dvb-frontends/au8522_decoder.c
+++ b/drivers/media/dvb-frontends/au8522_decoder.c
@@ -229,15 +229,11 @@ static void setup_decoder_defaults(struct au8522_state *state, u8 input_mode)
 	/* Provide reasonable defaults for picture tuning values */
 	au8522_writereg(state, AU8522_TVDEC_SHARPNESSREG009H, 0x07);
 	au8522_writereg(state, AU8522_TVDEC_BRIGHTNESS_REG00AH, 0xed);
-	state->brightness = 0xed - 128;
 	au8522_writereg(state, AU8522_TVDEC_CONTRAST_REG00BH, 0x79);
-	state->contrast = 0x79;
 	au8522_writereg(state, AU8522_TVDEC_SATURATION_CB_REG00CH, 0x80);
 	au8522_writereg(state, AU8522_TVDEC_SATURATION_CR_REG00DH, 0x80);
-	state->saturation = 0x80;
 	au8522_writereg(state, AU8522_TVDEC_HUE_H_REG00EH, 0x00);
 	au8522_writereg(state, AU8522_TVDEC_HUE_L_REG00FH, 0x00);
-	state->hue = 0x00;
 
 	/* Other decoder registers */
 	au8522_writereg(state, AU8522_TVDEC_INT_MASK_REG010H, 0x00);
@@ -489,75 +485,32 @@ static void set_audio_input(struct au8522_state *state, int aud_input)
 
 /* ----------------------------------------------------------------------- */
 
-static int au8522_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+static int au8522_s_ctrl(struct v4l2_ctrl *ctrl)
 {
-	struct au8522_state *state = to_state(sd);
+	struct au8522_state *state =
+		container_of(ctrl->handler, struct au8522_state, hdl);
 
 	switch (ctrl->id) {
 	case V4L2_CID_BRIGHTNESS:
-		state->brightness = ctrl->value;
 		au8522_writereg(state, AU8522_TVDEC_BRIGHTNESS_REG00AH,
-				ctrl->value - 128);
+				ctrl->val - 128);
 		break;
 	case V4L2_CID_CONTRAST:
-		state->contrast = ctrl->value;
 		au8522_writereg(state, AU8522_TVDEC_CONTRAST_REG00BH,
-				ctrl->value);
+				ctrl->val);
 		break;
 	case V4L2_CID_SATURATION:
-		state->saturation = ctrl->value;
 		au8522_writereg(state, AU8522_TVDEC_SATURATION_CB_REG00CH,
-				ctrl->value);
+				ctrl->val);
 		au8522_writereg(state, AU8522_TVDEC_SATURATION_CR_REG00DH,
-				ctrl->value);
+				ctrl->val);
 		break;
 	case V4L2_CID_HUE:
-		state->hue = ctrl->value;
 		au8522_writereg(state, AU8522_TVDEC_HUE_H_REG00EH,
-				ctrl->value >> 8);
+				ctrl->val >> 8);
 		au8522_writereg(state, AU8522_TVDEC_HUE_L_REG00FH,
-				ctrl->value & 0xFF);
-		break;
-	case V4L2_CID_AUDIO_VOLUME:
-	case V4L2_CID_AUDIO_BASS:
-	case V4L2_CID_AUDIO_TREBLE:
-	case V4L2_CID_AUDIO_BALANCE:
-	case V4L2_CID_AUDIO_MUTE:
-		/* Not yet implemented */
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int au8522_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
-{
-	struct au8522_state *state = to_state(sd);
-
-	/* Note that we are using values cached in the state structure instead
-	   of reading the registers due to issues with i2c reads not working
-	   properly/consistently yet on the HVR-950q */
-
-	switch (ctrl->id) {
-	case V4L2_CID_BRIGHTNESS:
-		ctrl->value = state->brightness;
-		break;
-	case V4L2_CID_CONTRAST:
-		ctrl->value = state->contrast;
+				ctrl->val & 0xFF);
 		break;
-	case V4L2_CID_SATURATION:
-		ctrl->value = state->saturation;
-		break;
-	case V4L2_CID_HUE:
-		ctrl->value = state->hue;
-		break;
-	case V4L2_CID_AUDIO_VOLUME:
-	case V4L2_CID_AUDIO_BASS:
-	case V4L2_CID_AUDIO_TREBLE:
-	case V4L2_CID_AUDIO_BALANCE:
-	case V4L2_CID_AUDIO_MUTE:
-		/* Not yet supported */
 	default:
 		return -EINVAL;
 	}
@@ -583,7 +536,7 @@ static int au8522_g_register(struct v4l2_subdev *sd,
 }
 
 static int au8522_s_register(struct v4l2_subdev *sd,
-			     struct v4l2_dbg_register *reg)
+			     const struct v4l2_dbg_register *reg)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 	struct au8522_state *state = to_state(sd);
@@ -616,26 +569,6 @@ static int au8522_s_stream(struct v4l2_subdev *sd, int enable)
 	return 0;
 }
 
-static int au8522_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
-{
-	switch (qc->id) {
-	case V4L2_CID_CONTRAST:
-		return v4l2_ctrl_query_fill(qc, 0, 255, 1,
-					    AU8522_TVDEC_CONTRAST_REG00BH_CVBS);
-	case V4L2_CID_BRIGHTNESS:
-		return v4l2_ctrl_query_fill(qc, 0, 255, 1, 109);
-	case V4L2_CID_SATURATION:
-		return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128);
-	case V4L2_CID_HUE:
-		return v4l2_ctrl_query_fill(qc, -32768, 32768, 1, 0);
-	default:
-		break;
-	}
-
-	qc->type = 0;
-	return -EINVAL;
-}
-
 static int au8522_reset(struct v4l2_subdev *sd, u32 val)
 {
 	struct au8522_state *state = to_state(sd);
@@ -712,20 +645,11 @@ static int au8522_g_chip_ident(struct v4l2_subdev *sd,
 	return v4l2_chip_ident_i2c_client(client, chip, state->id, state->rev);
 }
 
-static int au8522_log_status(struct v4l2_subdev *sd)
-{
-	/* FIXME: Add some status info here */
-	return 0;
-}
-
 /* ----------------------------------------------------------------------- */
 
 static const struct v4l2_subdev_core_ops au8522_core_ops = {
-	.log_status = au8522_log_status,
+	.log_status = v4l2_ctrl_subdev_log_status,
 	.g_chip_ident = au8522_g_chip_ident,
-	.g_ctrl = au8522_g_ctrl,
-	.s_ctrl = au8522_s_ctrl,
-	.queryctrl = au8522_queryctrl,
 	.reset = au8522_reset,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 	.g_register = au8522_g_register,
@@ -753,12 +677,17 @@ static const struct v4l2_subdev_ops au8522_ops = {
 	.video = &au8522_video_ops,
 };
 
+static const struct v4l2_ctrl_ops au8522_ctrl_ops = {
+	.s_ctrl = au8522_s_ctrl,
+};
+
 /* ----------------------------------------------------------------------- */
 
 static int au8522_probe(struct i2c_client *client,
 			const struct i2c_device_id *did)
 {
 	struct au8522_state *state;
+	struct v4l2_ctrl_handler *hdl;
 	struct v4l2_subdev *sd;
 	int instance;
 	struct au8522_config *demod_config;
@@ -799,6 +728,27 @@ static int au8522_probe(struct i2c_client *client,
 	sd = &state->sd;
 	v4l2_i2c_subdev_init(sd, client, &au8522_ops);
 
+	hdl = &state->hdl;
+	v4l2_ctrl_handler_init(hdl, 4);
+	v4l2_ctrl_new_std(hdl, &au8522_ctrl_ops,
+			V4L2_CID_BRIGHTNESS, 0, 255, 1, 109);
+	v4l2_ctrl_new_std(hdl, &au8522_ctrl_ops,
+			V4L2_CID_CONTRAST, 0, 255, 1,
+			AU8522_TVDEC_CONTRAST_REG00BH_CVBS);
+	v4l2_ctrl_new_std(hdl, &au8522_ctrl_ops,
+			V4L2_CID_SATURATION, 0, 255, 1, 128);
+	v4l2_ctrl_new_std(hdl, &au8522_ctrl_ops,
+			V4L2_CID_HUE, -32768, 32767, 1, 0);
+	sd->ctrl_handler = hdl;
+	if (hdl->error) {
+		int err = hdl->error;
+
+		v4l2_ctrl_handler_free(hdl);
+		kfree(demod_config);
+		kfree(state);
+		return err;
+	}
+
 	state->c = client;
 	state->vid_input = AU8522_COMPOSITE_CH1;
 	state->aud_input = AU8522_AUDIO_NONE;
@@ -815,6 +765,7 @@ static int au8522_remove(struct i2c_client *client)
 {
 	struct v4l2_subdev *sd = i2c_get_clientdata(client);
 	v4l2_device_unregister_subdev(sd);
+	v4l2_ctrl_handler_free(sd->ctrl_handler);
 	au8522_release_state(to_state(sd));
 	return 0;
 }
diff --git a/drivers/media/dvb-frontends/au8522_priv.h b/drivers/media/dvb-frontends/au8522_priv.h
index 0529699..aa0f16d 100644
--- a/drivers/media/dvb-frontends/au8522_priv.h
+++ b/drivers/media/dvb-frontends/au8522_priv.h
@@ -29,6 +29,7 @@
 #include <linux/delay.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
 #include <linux/i2c.h>
 #include "dvb_frontend.h"
 #include "au8522.h"
@@ -65,10 +66,7 @@ struct au8522_state {
 	int aud_input;
 	u32 id;
 	u32 rev;
-	u8 brightness;
-	u8 contrast;
-	u8 saturation;
-	s16 hue;
+	struct v4l2_ctrl_handler hdl;
 };
 
 /* These are routines shared by both the VSB/QAM demodulator and the analog
diff --git a/drivers/media/dvb-frontends/cx22702.h b/drivers/media/dvb-frontends/cx22702.h
index f154e1f..0b1a6c2 100644
--- a/drivers/media/dvb-frontends/cx22702.h
+++ b/drivers/media/dvb-frontends/cx22702.h
@@ -28,6 +28,7 @@
 #ifndef CX22702_H
 #define CX22702_H
 
+#include <linux/kconfig.h>
 #include <linux/dvb/frontend.h>
 
 struct cx22702_config {
@@ -40,8 +41,7 @@ struct cx22702_config {
 	u8 output_mode;
 };
 
-#if defined(CONFIG_DVB_CX22702) || (defined(CONFIG_DVB_CX22702_MODULE) \
-	&& defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_CX22702)
 extern struct dvb_frontend *cx22702_attach(
 	const struct cx22702_config *config,
 	struct i2c_adapter *i2c);
diff --git a/drivers/media/dvb-frontends/cx24113.h b/drivers/media/dvb-frontends/cx24113.h
index 01eb7b9..782711b 100644
--- a/drivers/media/dvb-frontends/cx24113.h
+++ b/drivers/media/dvb-frontends/cx24113.h
@@ -22,6 +22,8 @@
 #ifndef CX24113_H
 #define CX24113_H
 
+#include <linux/kconfig.h>
+
 struct dvb_frontend;
 
 struct cx24113_config {
@@ -30,8 +32,7 @@ struct cx24113_config {
 	u32 xtal_khz;
 };
 
-#if defined(CONFIG_DVB_TUNER_CX24113) || \
-	(defined(CONFIG_DVB_TUNER_CX24113_MODULE) && defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_TUNER_CX24113)
 extern struct dvb_frontend *cx24113_attach(struct dvb_frontend *,
 	const struct cx24113_config *config, struct i2c_adapter *i2c);
 
diff --git a/drivers/media/dvb-frontends/cx24116.h b/drivers/media/dvb-frontends/cx24116.h
index 7d90ab9..2ec84fa 100644
--- a/drivers/media/dvb-frontends/cx24116.h
+++ b/drivers/media/dvb-frontends/cx24116.h
@@ -21,6 +21,7 @@
 #ifndef CX24116_H
 #define CX24116_H
 
+#include <linux/kconfig.h>
 #include <linux/dvb/frontend.h>
 
 struct cx24116_config {
@@ -40,8 +41,7 @@ struct cx24116_config {
 	u16 i2c_wr_max;
 };
 
-#if defined(CONFIG_DVB_CX24116) || \
-	(defined(CONFIG_DVB_CX24116_MODULE) && defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_CX24116)
 extern struct dvb_frontend *cx24116_attach(
 	const struct cx24116_config *config,
 	struct i2c_adapter *i2c);
diff --git a/drivers/media/dvb-frontends/cx24123.h b/drivers/media/dvb-frontends/cx24123.h
index 51ae866..102e70d 100644
--- a/drivers/media/dvb-frontends/cx24123.h
+++ b/drivers/media/dvb-frontends/cx24123.h
@@ -21,6 +21,7 @@
 #ifndef CX24123_H
 #define CX24123_H
 
+#include <linux/kconfig.h>
 #include <linux/dvb/frontend.h>
 
 struct cx24123_config {
@@ -38,8 +39,7 @@ struct cx24123_config {
 	void (*agc_callback) (struct dvb_frontend *);
 };
 
-#if defined(CONFIG_DVB_CX24123) || (defined(CONFIG_DVB_CX24123_MODULE) \
-	&& defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_CX24123)
 extern struct dvb_frontend *cx24123_attach(const struct cx24123_config *config,
 					   struct i2c_adapter *i2c);
 extern struct i2c_adapter *cx24123_get_tuner_i2c_adapter(struct dvb_frontend *);
diff --git a/drivers/media/dvb-frontends/cxd2820r.h b/drivers/media/dvb-frontends/cxd2820r.h
index 6acc21c..82b3d93 100644
--- a/drivers/media/dvb-frontends/cxd2820r.h
+++ b/drivers/media/dvb-frontends/cxd2820r.h
@@ -22,6 +22,7 @@
 #ifndef CXD2820R_H
 #define CXD2820R_H
 
+#include <linux/kconfig.h>
 #include <linux/dvb/frontend.h>
 
 #define CXD2820R_GPIO_D (0 << 0) /* disable */
@@ -65,8 +66,7 @@ struct cxd2820r_config {
 };
 
 
-#if defined(CONFIG_DVB_CXD2820R) || \
-	(defined(CONFIG_DVB_CXD2820R_MODULE) && defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_CXD2820R)
 extern struct dvb_frontend *cxd2820r_attach(
 	const struct cxd2820r_config *config,
 	struct i2c_adapter *i2c,
diff --git a/drivers/media/dvb-frontends/dib3000mc.h b/drivers/media/dvb-frontends/dib3000mc.h
index d75ffad..129d142 100644
--- a/drivers/media/dvb-frontends/dib3000mc.h
+++ b/drivers/media/dvb-frontends/dib3000mc.h
@@ -13,6 +13,8 @@
 #ifndef DIB3000MC_H
 #define DIB3000MC_H
 
+#include <linux/kconfig.h>
+
 #include "dibx000_common.h"
 
 struct dib3000mc_config {
@@ -39,8 +41,7 @@ struct dib3000mc_config {
 #define DEFAULT_DIB3000MC_I2C_ADDRESS 16
 #define DEFAULT_DIB3000P_I2C_ADDRESS  24
 
-#if defined(CONFIG_DVB_DIB3000MC) || (defined(CONFIG_DVB_DIB3000MC_MODULE) && \
-				      defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_DIB3000MC)
 extern struct dvb_frontend *dib3000mc_attach(struct i2c_adapter *i2c_adap,
 					     u8 i2c_addr,
 					     struct dib3000mc_config *cfg);
diff --git a/drivers/media/dvb-frontends/dib7000m.h b/drivers/media/dvb-frontends/dib7000m.h
index 81fcf22..b585413 100644
--- a/drivers/media/dvb-frontends/dib7000m.h
+++ b/drivers/media/dvb-frontends/dib7000m.h
@@ -1,6 +1,8 @@
 #ifndef DIB7000M_H
 #define DIB7000M_H
 
+#include <linux/kconfig.h>
+
 #include "dibx000_common.h"
 
 struct dib7000m_config {
@@ -38,8 +40,7 @@ struct dib7000m_config {
 
 #define DEFAULT_DIB7000M_I2C_ADDRESS 18
 
-#if defined(CONFIG_DVB_DIB7000M) || (defined(CONFIG_DVB_DIB7000M_MODULE) && \
-				     defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_DIB7000M)
 extern struct dvb_frontend *dib7000m_attach(struct i2c_adapter *i2c_adap,
 					    u8 i2c_addr,
 					    struct dib7000m_config *cfg);
diff --git a/drivers/media/dvb-frontends/dib7000p.h b/drivers/media/dvb-frontends/dib7000p.h
index b61b03a..cf5e779 100644
--- a/drivers/media/dvb-frontends/dib7000p.h
+++ b/drivers/media/dvb-frontends/dib7000p.h
@@ -1,6 +1,8 @@
 #ifndef DIB7000P_H
 #define DIB7000P_H
 
+#include <linux/kconfig.h>
+
 #include "dibx000_common.h"
 
 struct dib7000p_config {
@@ -44,8 +46,7 @@ struct dib7000p_config {
 
 #define DEFAULT_DIB7000P_I2C_ADDRESS 18
 
-#if defined(CONFIG_DVB_DIB7000P) || (defined(CONFIG_DVB_DIB7000P_MODULE) && \
-					defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_DIB7000P)
 extern struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg);
 extern struct i2c_adapter *dib7000p_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int);
 extern int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[]);
diff --git a/drivers/media/dvb-frontends/drxd.h b/drivers/media/dvb-frontends/drxd.h
index 216c8c3..5f1d6b5 100644
--- a/drivers/media/dvb-frontends/drxd.h
+++ b/drivers/media/dvb-frontends/drxd.h
@@ -24,6 +24,7 @@
 #ifndef _DRXD_H_
 #define _DRXD_H_
 
+#include <linux/kconfig.h>
 #include <linux/types.h>
 #include <linux/i2c.h>
 
@@ -51,8 +52,7 @@ struct drxd_config {
 	 s16(*osc_deviation) (void *priv, s16 dev, int flag);
 };
 
-#if defined(CONFIG_DVB_DRXD) || \
-			(defined(CONFIG_DVB_DRXD_MODULE) && defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_DRXD)
 extern
 struct dvb_frontend *drxd_attach(const struct drxd_config *config,
 				 void *priv, struct i2c_adapter *i2c,
diff --git a/drivers/media/dvb-frontends/drxk.h b/drivers/media/dvb-frontends/drxk.h
index 94fecfb..e666718 100644
--- a/drivers/media/dvb-frontends/drxk.h
+++ b/drivers/media/dvb-frontends/drxk.h
@@ -1,6 +1,7 @@
 #ifndef _DRXK_H_
 #define _DRXK_H_
 
+#include <linux/kconfig.h>
 #include <linux/types.h>
 #include <linux/i2c.h>
 
@@ -52,8 +53,7 @@ struct drxk_config {
 	int		 qam_demod_parameter_count;
 };
 
-#if defined(CONFIG_DVB_DRXK) || (defined(CONFIG_DVB_DRXK_MODULE) \
-        && defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_DRXK)
 extern struct dvb_frontend *drxk_attach(const struct drxk_config *config,
 					struct i2c_adapter *i2c);
 #else
diff --git a/drivers/media/dvb-frontends/drxk_hard.c b/drivers/media/dvb-frontends/drxk_hard.c
index c2fc7da0d..ec24d71 100644
--- a/drivers/media/dvb-frontends/drxk_hard.c
+++ b/drivers/media/dvb-frontends/drxk_hard.c
@@ -1947,8 +1947,7 @@ static int ShutDown(struct drxk_state *state)
 	return 0;
 }
 
-static int GetLockStatus(struct drxk_state *state, u32 *pLockStatus,
-			 u32 Time)
+static int GetLockStatus(struct drxk_state *state, u32 *pLockStatus)
 {
 	int status = -EINVAL;
 
@@ -2490,32 +2489,6 @@ error:
 	return status;
 }
 
-static int ReadIFAgc(struct drxk_state *state, u32 *pValue)
-{
-	u16 agcDacLvl;
-	int status;
-	u16 Level = 0;
-
-	dprintk(1, "\n");
-
-	status = read16(state, IQM_AF_AGC_IF__A, &agcDacLvl);
-	if (status < 0) {
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-		return status;
-	}
-
-	*pValue = 0;
-
-	if (agcDacLvl > DRXK_AGC_DAC_OFFSET)
-		Level = agcDacLvl - DRXK_AGC_DAC_OFFSET;
-	if (Level < 14000)
-		*pValue = (14000 - Level) / 4;
-	else
-		*pValue = 0;
-
-	return status;
-}
-
 static int GetQAMSignalToNoise(struct drxk_state *state,
 			       s32 *pSignalToNoise)
 {
@@ -2654,12 +2627,7 @@ static int GetDVBTSignalToNoise(struct drxk_state *state,
 		/* log(x) x = (16bits + 16bits) << 15 ->32 bits  */
 		c = Log10Times100(SqrErrIQ);
 
-		iMER = a + b;
-		/* No negative MER, clip to zero */
-		if (iMER > c)
-			iMER -= c;
-		else
-			iMER = 0;
+		iMER = a + b - c;
 	}
 	*pSignalToNoise = iMER;
 
@@ -6380,46 +6348,257 @@ static int drxk_set_parameters(struct dvb_frontend *fe)
 	fe->ops.tuner_ops.get_if_frequency(fe, &IF);
 	Start(state, 0, IF);
 
+	/* After set_frontend, stats aren't avaliable */
+	p->strength.stat[0].scale = FE_SCALE_RELATIVE;
+	p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+	p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+	p->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+	p->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+	p->pre_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+	p->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+	p->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+
 	/* printk(KERN_DEBUG "drxk: %s IF=%d done\n", __func__, IF); */
 
 	return 0;
 }
 
-static int drxk_read_status(struct dvb_frontend *fe, fe_status_t *status)
+static int get_strength(struct drxk_state *state, u64 *strength)
 {
+	int status;
+	struct SCfgAgc   rfAgc, ifAgc;
+	u32          totalGain  = 0;
+	u32          atten      = 0;
+	u32          agcRange   = 0;
+	u16            scu_lvl  = 0;
+	u16            scu_coc  = 0;
+	/* FIXME: those are part of the tuner presets */
+	u16 tunerRfGain         = 50; /* Default value on az6007 driver */
+	u16 tunerIfGain         = 40; /* Default value on az6007 driver */
+
+	*strength = 0;
+
+	if (IsDVBT(state)) {
+		rfAgc = state->m_dvbtRfAgcCfg;
+		ifAgc = state->m_dvbtIfAgcCfg;
+	} else if (IsQAM(state)) {
+		rfAgc = state->m_qamRfAgcCfg;
+		ifAgc = state->m_qamIfAgcCfg;
+	} else {
+		rfAgc = state->m_atvRfAgcCfg;
+		ifAgc = state->m_atvIfAgcCfg;
+	}
+
+	if (rfAgc.ctrlMode == DRXK_AGC_CTRL_AUTO) {
+		/* SCU outputLevel */
+		status = read16(state, SCU_RAM_AGC_RF_IACCU_HI__A, &scu_lvl);
+		if (status < 0)
+			return status;
+
+		/* SCU c.o.c. */
+		read16(state, SCU_RAM_AGC_RF_IACCU_HI_CO__A, &scu_coc);
+		if (status < 0)
+			return status;
+
+		if (((u32) scu_lvl + (u32) scu_coc) < 0xffff)
+			rfAgc.outputLevel = scu_lvl + scu_coc;
+		else
+			rfAgc.outputLevel = 0xffff;
+
+		/* Take RF gain into account */
+		totalGain += tunerRfGain;
+
+		/* clip output value */
+		if (rfAgc.outputLevel < rfAgc.minOutputLevel)
+			rfAgc.outputLevel = rfAgc.minOutputLevel;
+		if (rfAgc.outputLevel > rfAgc.maxOutputLevel)
+			rfAgc.outputLevel = rfAgc.maxOutputLevel;
+
+		agcRange = (u32) (rfAgc.maxOutputLevel - rfAgc.minOutputLevel);
+		if (agcRange > 0) {
+			atten += 100UL *
+				((u32)(tunerRfGain)) *
+				((u32)(rfAgc.outputLevel - rfAgc.minOutputLevel))
+				/ agcRange;
+		}
+	}
+
+	if (ifAgc.ctrlMode == DRXK_AGC_CTRL_AUTO) {
+		status = read16(state, SCU_RAM_AGC_IF_IACCU_HI__A,
+				&ifAgc.outputLevel);
+		if (status < 0)
+			return status;
+
+		status = read16(state, SCU_RAM_AGC_INGAIN_TGT_MIN__A,
+				&ifAgc.top);
+		if (status < 0)
+			return status;
+
+		/* Take IF gain into account */
+		totalGain += (u32) tunerIfGain;
+
+		/* clip output value */
+		if (ifAgc.outputLevel < ifAgc.minOutputLevel)
+			ifAgc.outputLevel = ifAgc.minOutputLevel;
+		if (ifAgc.outputLevel > ifAgc.maxOutputLevel)
+			ifAgc.outputLevel = ifAgc.maxOutputLevel;
+
+		agcRange  = (u32) (ifAgc.maxOutputLevel - ifAgc.minOutputLevel);
+		if (agcRange > 0) {
+			atten += 100UL *
+				((u32)(tunerIfGain)) *
+				((u32)(ifAgc.outputLevel - ifAgc.minOutputLevel))
+				/ agcRange;
+		}
+	}
+
+	/*
+	 * Convert to 0..65535 scale.
+	 * If it can't be measured (AGC is disabled), just show 100%.
+	 */
+	if (totalGain > 0)
+		*strength = (65535UL * atten / totalGain / 100);
+	else
+		*strength = 65535;
+
+	return 0;
+}
+
+static int drxk_get_stats(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 	struct drxk_state *state = fe->demodulator_priv;
+	int status;
 	u32 stat;
-
-	dprintk(1, "\n");
+	u16 reg16;
+	u32 post_bit_count;
+	u32 post_bit_err_count;
+	u32 post_bit_error_scale;
+	u32 pre_bit_err_count;
+	u32 pre_bit_count;
+	u32 pkt_count;
+	u32 pkt_error_count;
+	s32 cnr;
 
 	if (state->m_DrxkState == DRXK_NO_DEV)
 		return -ENODEV;
 	if (state->m_DrxkState == DRXK_UNINITIALIZED)
 		return -EAGAIN;
 
-	*status = 0;
-	GetLockStatus(state, &stat, 0);
+	/* get status */
+	state->fe_status = 0;
+	GetLockStatus(state, &stat);
 	if (stat == MPEG_LOCK)
-		*status |= 0x1f;
+		state->fe_status |= 0x1f;
 	if (stat == FEC_LOCK)
-		*status |= 0x0f;
+		state->fe_status |= 0x0f;
 	if (stat == DEMOD_LOCK)
-		*status |= 0x07;
-	return 0;
+		state->fe_status |= 0x07;
+
+	/*
+	 * Estimate signal strength from AGC
+	 */
+	get_strength(state, &c->strength.stat[0].uvalue);
+	c->strength.stat[0].scale = FE_SCALE_RELATIVE;
+
+
+	if (stat >= DEMOD_LOCK) {
+		GetSignalToNoise(state, &cnr);
+		c->cnr.stat[0].svalue = cnr * 100;
+		c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
+	} else {
+		c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+	}
+
+	if (stat < FEC_LOCK) {
+		c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+		c->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+		c->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+		c->pre_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+		c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+		c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+		return 0;
+	}
+
+	/* Get post BER */
+
+	/* BER measurement is valid if at least FEC lock is achieved */
+
+	/* OFDM_EC_VD_REQ_SMB_CNT__A and/or OFDM_EC_VD_REQ_BIT_CNT can be written
+		to set nr of symbols or bits over which
+		to measure EC_VD_REG_ERR_BIT_CNT__A . See CtrlSetCfg(). */
+
+	/* Read registers for post/preViterbi BER calculation */
+	status = read16(state, OFDM_EC_VD_ERR_BIT_CNT__A, &reg16);
+	if (status < 0)
+		goto error;
+	pre_bit_err_count = reg16;
+
+	status = read16(state, OFDM_EC_VD_IN_BIT_CNT__A , &reg16);
+	if (status < 0)
+		goto error;
+	pre_bit_count = reg16;
+
+	/* Number of bit-errors */
+	status = read16(state, FEC_RS_NR_BIT_ERRORS__A, &reg16);
+	if (status < 0)
+		goto error;
+	post_bit_err_count = reg16;
+
+	status = read16(state, FEC_RS_MEASUREMENT_PRESCALE__A, &reg16);
+	if (status < 0)
+		goto error;
+	post_bit_error_scale = reg16;
+
+	status = read16(state, FEC_RS_MEASUREMENT_PERIOD__A, &reg16);
+	if (status < 0)
+		goto error;
+	pkt_count = reg16;
+
+	status = read16(state, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, &reg16);
+	if (status < 0)
+		goto error;
+	pkt_error_count = reg16;
+	write16(state, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, 0);
+
+	post_bit_err_count *= post_bit_error_scale;
+
+	post_bit_count = pkt_count * 204 * 8;
+
+	/* Store the results */
+	c->block_error.stat[0].scale = FE_SCALE_COUNTER;
+	c->block_error.stat[0].uvalue += pkt_error_count;
+	c->block_count.stat[0].scale = FE_SCALE_COUNTER;
+	c->block_count.stat[0].uvalue += pkt_count;
+
+	c->pre_bit_error.stat[0].scale = FE_SCALE_COUNTER;
+	c->pre_bit_error.stat[0].uvalue += pre_bit_err_count;
+	c->pre_bit_count.stat[0].scale = FE_SCALE_COUNTER;
+	c->pre_bit_count.stat[0].uvalue += pre_bit_count;
+
+	c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
+	c->post_bit_error.stat[0].uvalue += post_bit_err_count;
+	c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
+	c->post_bit_count.stat[0].uvalue += post_bit_count;
+
+error:
+	return status;
 }
 
-static int drxk_read_ber(struct dvb_frontend *fe, u32 *ber)
+
+static int drxk_read_status(struct dvb_frontend *fe, fe_status_t *status)
 {
 	struct drxk_state *state = fe->demodulator_priv;
+	int rc;
 
 	dprintk(1, "\n");
 
-	if (state->m_DrxkState == DRXK_NO_DEV)
-		return -ENODEV;
-	if (state->m_DrxkState == DRXK_UNINITIALIZED)
-		return -EAGAIN;
+	rc = drxk_get_stats(fe);
+	if (rc < 0)
+		return rc;
+
+	*status = state->fe_status;
 
-	*ber = 0;
 	return 0;
 }
 
@@ -6427,7 +6606,7 @@ static int drxk_read_signal_strength(struct dvb_frontend *fe,
 				     u16 *strength)
 {
 	struct drxk_state *state = fe->demodulator_priv;
-	u32 val = 0;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 
 	dprintk(1, "\n");
 
@@ -6436,8 +6615,7 @@ static int drxk_read_signal_strength(struct dvb_frontend *fe,
 	if (state->m_DrxkState == DRXK_UNINITIALIZED)
 		return -EAGAIN;
 
-	ReadIFAgc(state, &val);
-	*strength = val & 0xffff;
+	*strength = c->strength.stat[0].uvalue;
 	return 0;
 }
 
@@ -6454,6 +6632,10 @@ static int drxk_read_snr(struct dvb_frontend *fe, u16 *snr)
 		return -EAGAIN;
 
 	GetSignalToNoise(state, &snr2);
+
+	/* No negative SNR, clip to zero */
+	if (snr2 < 0)
+		snr2 = 0;
 	*snr = snr2 & 0xffff;
 	return 0;
 }
@@ -6529,7 +6711,6 @@ static struct dvb_frontend_ops drxk_ops = {
 	.get_tune_settings = drxk_get_tune_settings,
 
 	.read_status = drxk_read_status,
-	.read_ber = drxk_read_ber,
 	.read_signal_strength = drxk_read_signal_strength,
 	.read_snr = drxk_read_snr,
 	.read_ucblocks = drxk_read_ucblocks,
@@ -6538,6 +6719,7 @@ static struct dvb_frontend_ops drxk_ops = {
 struct dvb_frontend *drxk_attach(const struct drxk_config *config,
 				 struct i2c_adapter *i2c)
 {
+	struct dtv_frontend_properties *p;
 	struct drxk_state *state = NULL;
 	u8 adr = config->adr;
 	int status;
@@ -6618,6 +6800,27 @@ struct dvb_frontend *drxk_attach(const struct drxk_config *config,
 	} else if (init_drxk(state) < 0)
 		goto error;
 
+
+	/* Initialize stats */
+	p = &state->frontend.dtv_property_cache;
+	p->strength.len = 1;
+	p->cnr.len = 1;
+	p->block_error.len = 1;
+	p->block_count.len = 1;
+	p->pre_bit_error.len = 1;
+	p->pre_bit_count.len = 1;
+	p->post_bit_error.len = 1;
+	p->post_bit_count.len = 1;
+
+	p->strength.stat[0].scale = FE_SCALE_RELATIVE;
+	p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+	p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+	p->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+	p->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+	p->pre_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+	p->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+	p->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+
 	printk(KERN_INFO "drxk: frontend initialized.\n");
 	return &state->frontend;
 
diff --git a/drivers/media/dvb-frontends/drxk_hard.h b/drivers/media/dvb-frontends/drxk_hard.h
index d18a896..b8424f1 100644
--- a/drivers/media/dvb-frontends/drxk_hard.h
+++ b/drivers/media/dvb-frontends/drxk_hard.h
@@ -345,6 +345,8 @@ struct drxk_state {
 	bool	antenna_dvbt;
 	u16	antenna_gpio;
 
+	fe_status_t fe_status;
+
 	/* Firmware */
 	const char *microcode_name;
 	struct completion fw_wait_load;
diff --git a/drivers/media/dvb-frontends/drxk_map.h b/drivers/media/dvb-frontends/drxk_map.h
index 23e16c1..761613f 100644
--- a/drivers/media/dvb-frontends/drxk_map.h
+++ b/drivers/media/dvb-frontends/drxk_map.h
@@ -10,6 +10,7 @@
 #define    FEC_RS_COMM_EXEC_STOP                                           0x0
 #define  FEC_RS_MEASUREMENT_PERIOD__A                                      0x1C30012
 #define  FEC_RS_MEASUREMENT_PRESCALE__A                                    0x1C30013
+#define FEC_RS_NR_BIT_ERRORS__A                                            0x1C30014
 #define  FEC_OC_MODE__A                                                    0x1C40011
 #define    FEC_OC_MODE_PARITY__M                                           0x1
 #define  FEC_OC_DTO_MODE__A                                                0x1C40014
@@ -129,6 +130,8 @@
 #define  OFDM_EC_SB_PRIOR__A                                               0x3410013
 #define    OFDM_EC_SB_PRIOR_HI                                             0x0
 #define    OFDM_EC_SB_PRIOR_LO                                             0x1
+#define OFDM_EC_VD_ERR_BIT_CNT__A                                          0x3420017
+#define OFDM_EC_VD_IN_BIT_CNT__A                                           0x3420018
 #define  OFDM_EQ_TOP_TD_TPS_CONST__A                                       0x3010054
 #define  OFDM_EQ_TOP_TD_TPS_CONST__M                                       0x3
 #define    OFDM_EQ_TOP_TD_TPS_CONST_64QAM                                  0x2
diff --git a/drivers/media/dvb-frontends/ds3000.h b/drivers/media/dvb-frontends/ds3000.h
index 478ad66..f9c21fb 100644
--- a/drivers/media/dvb-frontends/ds3000.h
+++ b/drivers/media/dvb-frontends/ds3000.h
@@ -22,6 +22,7 @@
 #ifndef DS3000_H
 #define DS3000_H
 
+#include <linux/kconfig.h>
 #include <linux/dvb/frontend.h>
 
 struct ds3000_config {
@@ -34,8 +35,7 @@ struct ds3000_config {
 	void (*set_lock_led)(struct dvb_frontend *fe, int offon);
 };
 
-#if defined(CONFIG_DVB_DS3000) || \
-			(defined(CONFIG_DVB_DS3000_MODULE) && defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_DS3000)
 extern struct dvb_frontend *ds3000_attach(const struct ds3000_config *config,
 					struct i2c_adapter *i2c);
 #else
diff --git a/drivers/media/dvb-frontends/dvb_dummy_fe.h b/drivers/media/dvb-frontends/dvb_dummy_fe.h
index 1fcb987..0cbf961 100644
--- a/drivers/media/dvb-frontends/dvb_dummy_fe.h
+++ b/drivers/media/dvb-frontends/dvb_dummy_fe.h
@@ -22,11 +22,11 @@
 #ifndef DVB_DUMMY_FE_H
 #define DVB_DUMMY_FE_H
 
+#include <linux/kconfig.h>
 #include <linux/dvb/frontend.h>
 #include "dvb_frontend.h"
 
-#if defined(CONFIG_DVB_DUMMY_FE) || (defined(CONFIG_DVB_DUMMY_FE_MODULE) && \
-defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_DUMMY_FE)
 extern struct dvb_frontend* dvb_dummy_fe_ofdm_attach(void);
 extern struct dvb_frontend* dvb_dummy_fe_qpsk_attach(void);
 extern struct dvb_frontend* dvb_dummy_fe_qam_attach(void);
diff --git a/drivers/media/dvb-frontends/ec100.h b/drivers/media/dvb-frontends/ec100.h
index b847971..3755840 100644
--- a/drivers/media/dvb-frontends/ec100.h
+++ b/drivers/media/dvb-frontends/ec100.h
@@ -22,6 +22,7 @@
 #ifndef EC100_H
 #define EC100_H
 
+#include <linux/kconfig.h>
 #include <linux/dvb/frontend.h>
 
 struct ec100_config {
@@ -30,8 +31,7 @@ struct ec100_config {
 };
 
 
-#if defined(CONFIG_DVB_EC100) || \
-	(defined(CONFIG_DVB_EC100_MODULE) && defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_EC100)
 extern struct dvb_frontend *ec100_attach(const struct ec100_config *config,
 	struct i2c_adapter *i2c);
 #else
diff --git a/drivers/media/dvb-frontends/hd29l2.h b/drivers/media/dvb-frontends/hd29l2.h
index 4ad00d7..05cd130 100644
--- a/drivers/media/dvb-frontends/hd29l2.h
+++ b/drivers/media/dvb-frontends/hd29l2.h
@@ -23,6 +23,7 @@
 #ifndef HD29L2_H
 #define HD29L2_H
 
+#include <linux/kconfig.h>
 #include <linux/dvb/frontend.h>
 
 struct hd29l2_config {
@@ -50,8 +51,7 @@ struct hd29l2_config {
 };
 
 
-#if defined(CONFIG_DVB_HD29L2) || \
-	(defined(CONFIG_DVB_HD29L2_MODULE) && defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_HD29L2)
 extern struct dvb_frontend *hd29l2_attach(const struct hd29l2_config *config,
 	struct i2c_adapter *i2c);
 #else
diff --git a/drivers/media/dvb-frontends/it913x-fe.h b/drivers/media/dvb-frontends/it913x-fe.h
index 07fa459..df0ad42 100644
--- a/drivers/media/dvb-frontends/it913x-fe.h
+++ b/drivers/media/dvb-frontends/it913x-fe.h
@@ -21,6 +21,7 @@
 #ifndef IT913X_FE_H
 #define IT913X_FE_H
 
+#include <linux/kconfig.h>
 #include <linux/dvb/frontend.h>
 #include "dvb_frontend.h"
 
@@ -38,8 +39,7 @@ struct ite_config {
 	u8 read_slevel;
 };
 
-#if defined(CONFIG_DVB_IT913X_FE) || (defined(CONFIG_DVB_IT913X_FE_MODULE) && \
-defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_IT913X_FE)
 extern struct dvb_frontend *it913x_fe_attach(struct i2c_adapter *i2c_adap,
 			u8 i2c_addr, struct ite_config *config);
 #else
diff --git a/drivers/media/dvb-frontends/ix2505v.h b/drivers/media/dvb-frontends/ix2505v.h
index 67e89d6..1a735a7 100644
--- a/drivers/media/dvb-frontends/ix2505v.h
+++ b/drivers/media/dvb-frontends/ix2505v.h
@@ -20,6 +20,7 @@
 #ifndef DVB_IX2505V_H
 #define DVB_IX2505V_H
 
+#include <linux/kconfig.h>
 #include <linux/i2c.h>
 #include "dvb_frontend.h"
 
@@ -48,8 +49,7 @@ struct ix2505v_config {
 
 };
 
-#if defined(CONFIG_DVB_IX2505V) || \
-	(defined(CONFIG_DVB_IX2505V_MODULE) && defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_IX2505V)
 extern struct dvb_frontend *ix2505v_attach(struct dvb_frontend *fe,
 	const struct ix2505v_config *config, struct i2c_adapter *i2c);
 #else
diff --git a/drivers/media/dvb-frontends/lg2160.h b/drivers/media/dvb-frontends/lg2160.h
index 9e2c0f4..a5f0368 100644
--- a/drivers/media/dvb-frontends/lg2160.h
+++ b/drivers/media/dvb-frontends/lg2160.h
@@ -22,6 +22,7 @@
 #ifndef _LG2160_H_
 #define _LG2160_H_
 
+#include <linux/kconfig.h>
 #include <linux/i2c.h>
 #include "dvb_frontend.h"
 
@@ -66,8 +67,7 @@ struct lg2160_config {
 	enum lg_chip_type lg_chip;
 };
 
-#if defined(CONFIG_DVB_LG2160) || (defined(CONFIG_DVB_LG2160_MODULE) && \
-				     defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_LG2160)
 extern
 struct dvb_frontend *lg2160_attach(const struct lg2160_config *config,
 				     struct i2c_adapter *i2c_adap);
diff --git a/drivers/media/dvb-frontends/lgdt3305.h b/drivers/media/dvb-frontends/lgdt3305.h
index 02172ec..d9ab556 100644
--- a/drivers/media/dvb-frontends/lgdt3305.h
+++ b/drivers/media/dvb-frontends/lgdt3305.h
@@ -22,6 +22,7 @@
 #ifndef _LGDT3305_H_
 #define _LGDT3305_H_
 
+#include <linux/kconfig.h>
 #include <linux/i2c.h>
 #include "dvb_frontend.h"
 
@@ -73,8 +74,7 @@ struct lgdt3305_config {
 	enum lgdt_demod_chip_type demod_chip;
 };
 
-#if defined(CONFIG_DVB_LGDT3305) || (defined(CONFIG_DVB_LGDT3305_MODULE) && \
-				     defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_LGDT3305)
 extern
 struct dvb_frontend *lgdt3305_attach(const struct lgdt3305_config *config,
 				     struct i2c_adapter *i2c_adap);
diff --git a/drivers/media/dvb-frontends/lgs8gl5.h b/drivers/media/dvb-frontends/lgs8gl5.h
index d1417678..c2da596 100644
--- a/drivers/media/dvb-frontends/lgs8gl5.h
+++ b/drivers/media/dvb-frontends/lgs8gl5.h
@@ -23,6 +23,7 @@
 #ifndef LGS8GL5_H
 #define LGS8GL5_H
 
+#include <linux/kconfig.h>
 #include <linux/dvb/frontend.h>
 
 struct lgs8gl5_config {
@@ -30,8 +31,7 @@ struct lgs8gl5_config {
 	u8 demod_address;
 };
 
-#if defined(CONFIG_DVB_LGS8GL5) || \
-	(defined(CONFIG_DVB_LGS8GL5_MODULE) && defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_LGS8GL5)
 extern struct dvb_frontend *lgs8gl5_attach(
 	const struct lgs8gl5_config *config, struct i2c_adapter *i2c);
 #else
diff --git a/drivers/media/dvb-frontends/lgs8gxx.h b/drivers/media/dvb-frontends/lgs8gxx.h
index 33c3c5e..dadb78b 100644
--- a/drivers/media/dvb-frontends/lgs8gxx.h
+++ b/drivers/media/dvb-frontends/lgs8gxx.h
@@ -26,6 +26,7 @@
 #ifndef __LGS8GXX_H__
 #define __LGS8GXX_H__
 
+#include <linux/kconfig.h>
 #include <linux/dvb/frontend.h>
 #include <linux/i2c.h>
 
@@ -79,8 +80,7 @@ struct lgs8gxx_config {
 	u8 tuner_address;
 };
 
-#if defined(CONFIG_DVB_LGS8GXX) || \
-	(defined(CONFIG_DVB_LGS8GXX_MODULE) && defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_LGS8GXX)
 extern struct dvb_frontend *lgs8gxx_attach(const struct lgs8gxx_config *config,
 					   struct i2c_adapter *i2c);
 #else
diff --git a/drivers/media/dvb-frontends/lnbh24.h b/drivers/media/dvb-frontends/lnbh24.h
index c059b16..b327a4f 100644
--- a/drivers/media/dvb-frontends/lnbh24.h
+++ b/drivers/media/dvb-frontends/lnbh24.h
@@ -23,6 +23,8 @@
 #ifndef _LNBH24_H
 #define _LNBH24_H
 
+#include <linux/kconfig.h>
+
 /* system register bits */
 #define LNBH24_OLF	0x01
 #define LNBH24_OTF	0x02
@@ -35,8 +37,7 @@
 
 #include <linux/dvb/frontend.h>
 
-#if defined(CONFIG_DVB_LNBP21) || (defined(CONFIG_DVB_LNBP21_MODULE) \
-							&& defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_LNBP21)
 /* override_set and override_clear control which
    system register bits (above) to always set & clear */
 extern struct dvb_frontend *lnbh24_attach(struct dvb_frontend *fe,
diff --git a/drivers/media/dvb-frontends/lnbp21.h b/drivers/media/dvb-frontends/lnbp21.h
index fcdf1c6..dbcbcc2 100644
--- a/drivers/media/dvb-frontends/lnbp21.h
+++ b/drivers/media/dvb-frontends/lnbp21.h
@@ -27,6 +27,8 @@
 #ifndef _LNBP21_H
 #define _LNBP21_H
 
+#include <linux/kconfig.h>
+
 /* system register bits */
 /* [RO] 0=OK; 1=over current limit flag */
 #define LNBP21_OLF	0x01
@@ -55,8 +57,7 @@
 
 #include <linux/dvb/frontend.h>
 
-#if defined(CONFIG_DVB_LNBP21) || (defined(CONFIG_DVB_LNBP21_MODULE) \
-							&& defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_LNBP21)
 /* override_set and override_clear control which
  system register bits (above) to always set & clear */
 extern struct dvb_frontend *lnbp21_attach(struct dvb_frontend *fe,
diff --git a/drivers/media/dvb-frontends/lnbp22.h b/drivers/media/dvb-frontends/lnbp22.h
index 63e2dec..63861b3 100644
--- a/drivers/media/dvb-frontends/lnbp22.h
+++ b/drivers/media/dvb-frontends/lnbp22.h
@@ -28,6 +28,8 @@
 #ifndef _LNBP22_H
 #define _LNBP22_H
 
+#include <linux/kconfig.h>
+
 /* Enable */
 #define LNBP22_EN	  0x10
 /* Voltage selection */
@@ -37,8 +39,7 @@
 
 #include <linux/dvb/frontend.h>
 
-#if defined(CONFIG_DVB_LNBP22) || \
-		(defined(CONFIG_DVB_LNBP22_MODULE) && defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_LNBP22)
 /*
  * override_set and override_clear control which system register bits (above)
  * to always set & clear
diff --git a/drivers/media/dvb-frontends/m88rs2000.h b/drivers/media/dvb-frontends/m88rs2000.h
index 5a8023e..14ce31e 100644
--- a/drivers/media/dvb-frontends/m88rs2000.h
+++ b/drivers/media/dvb-frontends/m88rs2000.h
@@ -20,6 +20,7 @@
 #ifndef M88RS2000_H
 #define M88RS2000_H
 
+#include <linux/kconfig.h>
 #include <linux/dvb/frontend.h>
 #include "dvb_frontend.h"
 
@@ -40,8 +41,7 @@ enum {
 	CALL_IS_READ,
 };
 
-#if defined(CONFIG_DVB_M88RS2000) || (defined(CONFIG_DVB_M88RS2000_MODULE) && \
-							defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_M88RS2000)
 extern struct dvb_frontend *m88rs2000_attach(
 	const struct m88rs2000_config *config, struct i2c_adapter *i2c);
 #else
diff --git a/drivers/media/dvb-frontends/mb86a20s.c b/drivers/media/dvb-frontends/mb86a20s.c
index f19cd73..d04b52e 100644
--- a/drivers/media/dvb-frontends/mb86a20s.c
+++ b/drivers/media/dvb-frontends/mb86a20s.c
@@ -24,6 +24,18 @@ static int debug = 1;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
 
+enum mb86a20s_bandwidth {
+	MB86A20S_13SEG = 0,
+	MB86A20S_13SEG_PARTIAL = 1,
+	MB86A20S_1SEG = 2,
+	MB86A20S_3SEG = 3,
+};
+
+u8 mb86a20s_subchannel[] = {
+	0xb0, 0xc0, 0xd0, 0xe0,
+	0xf0, 0x00, 0x10, 0x20,
+};
+
 struct mb86a20s_state {
 	struct i2c_adapter *i2c;
 	const struct mb86a20s_config *config;
@@ -31,7 +43,13 @@ struct mb86a20s_state {
 
 	struct dvb_frontend frontend;
 
+	u32 if_freq;
+	enum mb86a20s_bandwidth bw;
+	bool inversion;
+	u32 subchannel;
+
 	u32 estimated_rate[3];
+	unsigned long get_strength_time;
 
 	bool need_init;
 };
@@ -47,35 +65,33 @@ struct regdata {
  * Initialization sequence: Use whatevere default values that PV SBTVD
  * does on its initialisation, obtained via USB snoop
  */
-static struct regdata mb86a20s_init[] = {
+static struct regdata mb86a20s_init1[] = {
 	{ 0x70, 0x0f },
 	{ 0x70, 0xff },
 	{ 0x08, 0x01 },
-	{ 0x09, 0x3e },
-	{ 0x50, 0xd1 }, { 0x51, 0x22 },
-	{ 0x39, 0x01 },
-	{ 0x71, 0x00 },
-	{ 0x28, 0x2a }, { 0x29, 0x00 }, { 0x2a, 0xff }, { 0x2b, 0x80 },
-	{ 0x28, 0x20 }, { 0x29, 0x33 }, { 0x2a, 0xdf }, { 0x2b, 0xa9 },
+	{ 0x50, 0xd1 }, { 0x51, 0x20 },
+};
+
+static struct regdata mb86a20s_init2[] = {
 	{ 0x28, 0x22 }, { 0x29, 0x00 }, { 0x2a, 0x1f }, { 0x2b, 0xf0 },
 	{ 0x3b, 0x21 },
-	{ 0x3c, 0x3a },
+	{ 0x3c, 0x38 },
 	{ 0x01, 0x0d },
-	{ 0x04, 0x08 }, { 0x05, 0x05 },
+	{ 0x04, 0x08 }, { 0x05, 0x03 },
 	{ 0x04, 0x0e }, { 0x05, 0x00 },
-	{ 0x04, 0x0f }, { 0x05, 0x14 },
-	{ 0x04, 0x0b }, { 0x05, 0x8c },
+	{ 0x04, 0x0f }, { 0x05, 0x37 },
+	{ 0x04, 0x0b }, { 0x05, 0x78 },
 	{ 0x04, 0x00 }, { 0x05, 0x00 },
-	{ 0x04, 0x01 }, { 0x05, 0x07 },
-	{ 0x04, 0x02 }, { 0x05, 0x0f },
-	{ 0x04, 0x03 }, { 0x05, 0xa0 },
+	{ 0x04, 0x01 }, { 0x05, 0x1e },
+	{ 0x04, 0x02 }, { 0x05, 0x07 },
+	{ 0x04, 0x03 }, { 0x05, 0xd0 },
 	{ 0x04, 0x09 }, { 0x05, 0x00 },
 	{ 0x04, 0x0a }, { 0x05, 0xff },
-	{ 0x04, 0x27 }, { 0x05, 0x64 },
+	{ 0x04, 0x27 }, { 0x05, 0x00 },
 	{ 0x04, 0x28 }, { 0x05, 0x00 },
-	{ 0x04, 0x1e }, { 0x05, 0xff },
-	{ 0x04, 0x29 }, { 0x05, 0x0a },
-	{ 0x04, 0x32 }, { 0x05, 0x0a },
+	{ 0x04, 0x1e }, { 0x05, 0x00 },
+	{ 0x04, 0x29 }, { 0x05, 0x64 },
+	{ 0x04, 0x32 }, { 0x05, 0x02 },
 	{ 0x04, 0x14 }, { 0x05, 0x02 },
 	{ 0x04, 0x04 }, { 0x05, 0x00 },
 	{ 0x04, 0x05 }, { 0x05, 0x22 },
@@ -142,39 +158,39 @@ static struct regdata mb86a20s_init[] = {
 	{ 0x50, 0xd5 }, { 0x51, 0x01 },		/* Serial */
 	{ 0x50, 0xd6 }, { 0x51, 0x1f },
 	{ 0x50, 0xd2 }, { 0x51, 0x03 },
-	{ 0x50, 0xd7 }, { 0x51, 0x3f },
-	{ 0x28, 0x74 }, { 0x29, 0x00 }, { 0x28, 0x74 }, { 0x29, 0x40 },
-	{ 0x28, 0x46 }, { 0x29, 0x2c }, { 0x28, 0x46 }, { 0x29, 0x0c },
+	{ 0x50, 0xd7 }, { 0x51, 0xbf },
+	{ 0x28, 0x74 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0xff },
+	{ 0x28, 0x46 }, { 0x29, 0x00 }, { 0x2a, 0x1a }, { 0x2b, 0x0c },
 
 	{ 0x04, 0x40 }, { 0x05, 0x00 },
-	{ 0x28, 0x00 }, { 0x29, 0x10 },
-	{ 0x28, 0x05 }, { 0x29, 0x02 },
+	{ 0x28, 0x00 }, { 0x2b, 0x08 },
+	{ 0x28, 0x05 }, { 0x2b, 0x00 },
 	{ 0x1c, 0x01 },
-	{ 0x28, 0x06 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x03 },
-	{ 0x28, 0x07 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x0d },
-	{ 0x28, 0x08 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x02 },
-	{ 0x28, 0x09 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x01 },
-	{ 0x28, 0x0a }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x21 },
-	{ 0x28, 0x0b }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x29 },
-	{ 0x28, 0x0c }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x16 },
-	{ 0x28, 0x0d }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x31 },
-	{ 0x28, 0x0e }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x0e },
-	{ 0x28, 0x0f }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x4e },
-	{ 0x28, 0x10 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x46 },
-	{ 0x28, 0x11 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x0f },
-	{ 0x28, 0x12 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x56 },
-	{ 0x28, 0x13 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x35 },
-	{ 0x28, 0x14 }, { 0x29, 0x00 }, { 0x2a, 0x01 }, { 0x2b, 0xbe },
-	{ 0x28, 0x15 }, { 0x29, 0x00 }, { 0x2a, 0x01 }, { 0x2b, 0x84 },
-	{ 0x28, 0x16 }, { 0x29, 0x00 }, { 0x2a, 0x03 }, { 0x2b, 0xee },
-	{ 0x28, 0x17 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x98 },
-	{ 0x28, 0x18 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x9f },
-	{ 0x28, 0x19 }, { 0x29, 0x00 }, { 0x2a, 0x07 }, { 0x2b, 0xb2 },
-	{ 0x28, 0x1a }, { 0x29, 0x00 }, { 0x2a, 0x06 }, { 0x2b, 0xc2 },
-	{ 0x28, 0x1b }, { 0x29, 0x00 }, { 0x2a, 0x07 }, { 0x2b, 0x4a },
-	{ 0x28, 0x1c }, { 0x29, 0x00 }, { 0x2a, 0x01 }, { 0x2b, 0xbc },
-	{ 0x28, 0x1d }, { 0x29, 0x00 }, { 0x2a, 0x04 }, { 0x2b, 0xba },
-	{ 0x28, 0x1e }, { 0x29, 0x00 }, { 0x2a, 0x06 }, { 0x2b, 0x14 },
+	{ 0x28, 0x06 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x1f },
+	{ 0x28, 0x07 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x18 },
+	{ 0x28, 0x08 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x12 },
+	{ 0x28, 0x09 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x30 },
+	{ 0x28, 0x0a }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x37 },
+	{ 0x28, 0x0b }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x02 },
+	{ 0x28, 0x0c }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x09 },
+	{ 0x28, 0x0d }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x06 },
+	{ 0x28, 0x0e }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x7b },
+	{ 0x28, 0x0f }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x76 },
+	{ 0x28, 0x10 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x7d },
+	{ 0x28, 0x11 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x08 },
+	{ 0x28, 0x12 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x0b },
+	{ 0x28, 0x13 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x00 },
+	{ 0x28, 0x14 }, { 0x29, 0x00 }, { 0x2a, 0x01 }, { 0x2b, 0xf2 },
+	{ 0x28, 0x15 }, { 0x29, 0x00 }, { 0x2a, 0x01 }, { 0x2b, 0xf3 },
+	{ 0x28, 0x16 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x05 },
+	{ 0x28, 0x17 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x16 },
+	{ 0x28, 0x18 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x0f },
+	{ 0x28, 0x19 }, { 0x29, 0x00 }, { 0x2a, 0x07 }, { 0x2b, 0xef },
+	{ 0x28, 0x1a }, { 0x29, 0x00 }, { 0x2a, 0x07 }, { 0x2b, 0xd8 },
+	{ 0x28, 0x1b }, { 0x29, 0x00 }, { 0x2a, 0x07 }, { 0x2b, 0xf1 },
+	{ 0x28, 0x1c }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x3d },
+	{ 0x28, 0x1d }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x94 },
+	{ 0x28, 0x1e }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0xba },
 	{ 0x50, 0x1e }, { 0x51, 0x5d },
 	{ 0x50, 0x22 }, { 0x51, 0x00 },
 	{ 0x50, 0x23 }, { 0x51, 0xc8 },
@@ -183,6 +199,8 @@ static struct regdata mb86a20s_init[] = {
 	{ 0x50, 0x26 }, { 0x51, 0x00 },
 	{ 0x50, 0x27 }, { 0x51, 0xc3 },
 	{ 0x50, 0x39 }, { 0x51, 0x02 },
+	{ 0xec, 0x0f },
+	{ 0xeb, 0x1f },
 	{ 0x28, 0x6a }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x00 },
 	{ 0xd0, 0x00 },
 };
@@ -308,15 +326,23 @@ static int mb86a20s_read_status(struct dvb_frontend *fe, fe_status_t *status)
 	dev_dbg(&state->i2c->dev, "%s: Status = 0x%02x (state = %d)\n",
 		 __func__, *status, val);
 
-	return 0;
+	return val;
 }
 
 static int mb86a20s_read_signal_strength(struct dvb_frontend *fe)
 {
 	struct mb86a20s_state *state = fe->demodulator_priv;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 	int rc;
 	unsigned rf_max, rf_min, rf;
 
+	if (state->get_strength_time &&
+	   (!time_after(jiffies, state->get_strength_time)))
+		return c->strength.stat[0].uvalue;
+
+	/* Reset its value if an error happen */
+	c->strength.stat[0].uvalue = 0;
+
 	/* Does a binary search to get RF strength */
 	rf_max = 0xfff;
 	rf_min = 0;
@@ -331,7 +357,7 @@ static int mb86a20s_read_signal_strength(struct dvb_frontend *fe)
 		rc = mb86a20s_writereg(state, 0x04, 0x20);
 		if (rc < 0)
 			return rc;
-		rc = mb86a20s_writereg(state, 0x04, rf);
+		rc = mb86a20s_writereg(state, 0x05, rf);
 		if (rc < 0)
 			return rc;
 
@@ -346,15 +372,19 @@ static int mb86a20s_read_signal_strength(struct dvb_frontend *fe)
 			rf = (rf_max + rf_min) / 2;
 
 			/* Rescale it from 2^12 (4096) to 2^16 */
-			rf <<= (16 - 12);
+			rf = rf << (16 - 12);
+			if (rf)
+				rf |= (1 << 12) - 1;
+
 			dev_dbg(&state->i2c->dev,
 				"%s: signal strength = %d (%d < RF=%d < %d)\n",
 				__func__, rf, rf_min, rf >> 4, rf_max);
-			return rf;
+			c->strength.stat[0].uvalue = rf;
+			state->get_strength_time = jiffies +
+						   msecs_to_jiffies(1000);
+			return 0;
 		}
 	} while (1);
-
-	return 0;
 }
 
 static int mb86a20s_get_modulation(struct mb86a20s_state *state,
@@ -735,7 +765,6 @@ static int mb86a20s_reset_counters(struct dvb_frontend *fe)
 
 	/* Reset the counters, if the channel changed */
 	if (state->last_frequency != c->frequency) {
-		memset(&c->strength, 0, sizeof(c->strength));
 		memset(&c->cnr, 0, sizeof(c->cnr));
 		memset(&c->pre_bit_error, 0, sizeof(c->pre_bit_error));
 		memset(&c->pre_bit_count, 0, sizeof(c->pre_bit_count));
@@ -1095,7 +1124,7 @@ static int mb86a20s_get_blk_error(struct dvb_frontend *fe,
 	if (rc < 0)
 		return rc;
 	*error |= rc;
-	dev_err(&state->i2c->dev, "%s: block error for layer %c: %d.\n",
+	dev_dbg(&state->i2c->dev, "%s: block error for layer %c: %d.\n",
 		__func__, 'A' + layer, *error);
 
 	/* Read Bit Count */
@@ -1386,7 +1415,7 @@ static int mb86a20s_get_main_CNR(struct dvb_frontend *fe)
 		return rc;
 
 	if (!(rc & 0x40)) {
-		dev_info(&state->i2c->dev, "%s: CNR is not available yet.\n",
+		dev_dbg(&state->i2c->dev, "%s: CNR is not available yet.\n",
 			 __func__);
 		return -EBUSY;
 	}
@@ -1441,7 +1470,7 @@ static int mb86a20s_get_blk_error_layer_CNR(struct dvb_frontend *fe)
 
 	/* Check if data is available */
 	if (!(rc & 0x01)) {
-		dev_info(&state->i2c->dev,
+		dev_dbg(&state->i2c->dev,
 			"%s: MER measures aren't available yet.\n", __func__);
 		return -EBUSY;
 	}
@@ -1560,7 +1589,7 @@ static void mb86a20s_stats_not_ready(struct dvb_frontend *fe)
 	}
 }
 
-static int mb86a20s_get_stats(struct dvb_frontend *fe)
+static int mb86a20s_get_stats(struct dvb_frontend *fe, int status_nr)
 {
 	struct mb86a20s_state *state = fe->demodulator_priv;
 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
@@ -1580,6 +1609,14 @@ static int mb86a20s_get_stats(struct dvb_frontend *fe)
 	/* Get per-layer stats */
 	mb86a20s_get_blk_error_layer_CNR(fe);
 
+	/*
+	 * At state 7, only CNR is available
+	 * For BER measures, state=9 is required
+	 * FIXME: we may get MER measures with state=8
+	 */
+	if (status_nr < 9)
+		return 0;
+
 	for (i = 0; i < 3; i++) {
 		if (c->isdbt_layer_enabled & (1 << i)) {
 			/* Layer is active and has rc segments */
@@ -1737,8 +1774,10 @@ static int mb86a20s_get_stats(struct dvb_frontend *fe)
 static int mb86a20s_initfe(struct dvb_frontend *fe)
 {
 	struct mb86a20s_state *state = fe->demodulator_priv;
+	u64 pll;
+	u32 fclk;
 	int rc;
-	u8  regD5 = 1;
+	u8  regD5 = 1, reg71, reg09 = 0x3a;
 
 	dev_dbg(&state->i2c->dev, "%s called.\n", __func__);
 
@@ -1746,9 +1785,77 @@ static int mb86a20s_initfe(struct dvb_frontend *fe)
 		fe->ops.i2c_gate_ctrl(fe, 0);
 
 	/* Initialize the frontend */
-	rc = mb86a20s_writeregdata(state, mb86a20s_init);
+	rc = mb86a20s_writeregdata(state, mb86a20s_init1);
+	if (rc < 0)
+		goto err;
+
+	if (!state->inversion)
+		reg09 |= 0x04;
+	rc = mb86a20s_writereg(state, 0x09, reg09);
+	if (rc < 0)
+		goto err;
+	if (!state->bw)
+		reg71 = 1;
+	else
+		reg71 = 0;
+	rc = mb86a20s_writereg(state, 0x39, reg71);
+	if (rc < 0)
+		goto err;
+	rc = mb86a20s_writereg(state, 0x71, state->bw);
 	if (rc < 0)
 		goto err;
+	if (state->subchannel) {
+		rc = mb86a20s_writereg(state, 0x44, state->subchannel);
+		if (rc < 0)
+			goto err;
+	}
+
+	fclk = state->config->fclk;
+	if (!fclk)
+		fclk = 32571428;
+
+	/* Adjust IF frequency to match tuner */
+	if (fe->ops.tuner_ops.get_if_frequency)
+		fe->ops.tuner_ops.get_if_frequency(fe, &state->if_freq);
+
+	if (!state->if_freq)
+		state->if_freq = 3300000;
+
+	pll = (((u64)1) << 34) * state->if_freq;
+	do_div(pll, 63 * fclk);
+	pll = (1 << 25) - pll;
+	rc = mb86a20s_writereg(state, 0x28, 0x2a);
+	if (rc < 0)
+		goto err;
+	rc = mb86a20s_writereg(state, 0x29, (pll >> 16) & 0xff);
+	if (rc < 0)
+		goto err;
+	rc = mb86a20s_writereg(state, 0x2a, (pll >> 8) & 0xff);
+	if (rc < 0)
+		goto err;
+	rc = mb86a20s_writereg(state, 0x2b, pll & 0xff);
+	if (rc < 0)
+		goto err;
+	dev_dbg(&state->i2c->dev, "%s: fclk=%d, IF=%d, clock reg=0x%06llx\n",
+		__func__, fclk, state->if_freq, (long long)pll);
+
+	/* pll = freq[Hz] * 2^24/10^6 / 16.285714286 */
+	pll = state->if_freq * 1677721600L;
+	do_div(pll, 1628571429L);
+	rc = mb86a20s_writereg(state, 0x28, 0x20);
+	if (rc < 0)
+		goto err;
+	rc = mb86a20s_writereg(state, 0x29, (pll >> 16) & 0xff);
+	if (rc < 0)
+		goto err;
+	rc = mb86a20s_writereg(state, 0x2a, (pll >> 8) & 0xff);
+	if (rc < 0)
+		goto err;
+	rc = mb86a20s_writereg(state, 0x2b, pll & 0xff);
+	if (rc < 0)
+		goto err;
+	dev_dbg(&state->i2c->dev, "%s: IF=%d, IF reg=0x%06llx\n",
+		__func__, state->if_freq, (long long)pll);
 
 	if (!state->config->is_serial) {
 		regD5 &= ~1;
@@ -1761,6 +1868,11 @@ static int mb86a20s_initfe(struct dvb_frontend *fe)
 			goto err;
 	}
 
+	rc = mb86a20s_writeregdata(state, mb86a20s_init2);
+	if (rc < 0)
+		goto err;
+
+
 err:
 	if (fe->ops.i2c_gate_ctrl)
 		fe->ops.i2c_gate_ctrl(fe, 1);
@@ -1779,15 +1891,34 @@ err:
 static int mb86a20s_set_frontend(struct dvb_frontend *fe)
 {
 	struct mb86a20s_state *state = fe->demodulator_priv;
-	int rc;
-#if 0
-	/*
-	 * FIXME: Properly implement the set frontend properties
-	 */
 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-#endif
+	int rc, if_freq;
 	dev_dbg(&state->i2c->dev, "%s called.\n", __func__);
 
+	if (!c->isdbt_layer_enabled)
+		c->isdbt_layer_enabled = 7;
+
+	if (c->isdbt_layer_enabled == 1)
+		state->bw = MB86A20S_1SEG;
+	else if (c->isdbt_partial_reception)
+		state->bw = MB86A20S_13SEG_PARTIAL;
+	else
+		state->bw = MB86A20S_13SEG;
+
+	if (c->inversion == INVERSION_ON)
+		state->inversion = true;
+	else
+		state->inversion = false;
+
+	if (!c->isdbt_sb_mode) {
+		state->subchannel = 0;
+	} else {
+		if (c->isdbt_sb_subchannel > ARRAY_SIZE(mb86a20s_subchannel))
+			c->isdbt_sb_subchannel = 0;
+
+		state->subchannel = mb86a20s_subchannel[c->isdbt_sb_subchannel];
+	}
+
 	/*
 	 * Gate should already be opened, but it doesn't hurt to
 	 * double-check
@@ -1796,6 +1927,9 @@ static int mb86a20s_set_frontend(struct dvb_frontend *fe)
 		fe->ops.i2c_gate_ctrl(fe, 1);
 	fe->ops.tuner_ops.set_params(fe);
 
+	if (fe->ops.tuner_ops.get_if_frequency)
+		fe->ops.tuner_ops.get_if_frequency(fe, &if_freq);
+
 	/*
 	 * Make it more reliable: if, for some reason, the initial
 	 * device initialization doesn't happen, initialize it when
@@ -1805,15 +1939,22 @@ static int mb86a20s_set_frontend(struct dvb_frontend *fe)
 	 * the agc callback logic is not called during DVB attach time,
 	 * causing mb86a20s to not be initialized with Kworld SBTVD.
 	 * So, this hack is needed, in order to make Kworld SBTVD to work.
+	 *
+	 * It is also needed to change the IF after the initial init.
+	 *
+	 * HACK: Always init the frontend when set_frontend is called:
+	 * it was noticed that, on some devices, it fails to lock on a
+	 * different channel. So, it is better to reset everything, even
+	 * wasting some time, than to loose channel lock.
 	 */
-	if (state->need_init)
-		mb86a20s_initfe(fe);
+	mb86a20s_initfe(fe);
 
 	if (fe->ops.i2c_gate_ctrl)
 		fe->ops.i2c_gate_ctrl(fe, 0);
 
 	rc = mb86a20s_writeregdata(state, mb86a20s_reset_reception);
 	mb86a20s_reset_counters(fe);
+	mb86a20s_stats_not_ready(fe);
 
 	if (fe->ops.i2c_gate_ctrl)
 		fe->ops.i2c_gate_ctrl(fe, 1);
@@ -1825,8 +1966,7 @@ static int mb86a20s_read_status_and_stats(struct dvb_frontend *fe,
 					  fe_status_t *status)
 {
 	struct mb86a20s_state *state = fe->demodulator_priv;
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	int rc;
+	int rc, status_nr;
 
 	dev_dbg(&state->i2c->dev, "%s called.\n", __func__);
 
@@ -1834,12 +1974,12 @@ static int mb86a20s_read_status_and_stats(struct dvb_frontend *fe,
 		fe->ops.i2c_gate_ctrl(fe, 0);
 
 	/* Get lock */
-	rc = mb86a20s_read_status(fe, status);
-	if (!(*status & FE_HAS_LOCK)) {
+	status_nr = mb86a20s_read_status(fe, status);
+	if (status_nr < 7) {
 		mb86a20s_stats_not_ready(fe);
 		mb86a20s_reset_frontend_cache(fe);
 	}
-	if (rc < 0) {
+	if (status_nr < 0) {
 		dev_err(&state->i2c->dev,
 			"%s: Can't read frontend lock status\n", __func__);
 		goto error;
@@ -1856,10 +1996,8 @@ static int mb86a20s_read_status_and_stats(struct dvb_frontend *fe,
 		rc = 0;		/* Status is OK */
 		goto error;
 	}
-	/* Fill signal strength */
-	c->strength.stat[0].uvalue = rc;
 
-	if (*status & FE_HAS_LOCK) {
+	if (status_nr >= 7) {
 		/* Get TMCC info*/
 		rc = mb86a20s_get_frontend(fe);
 		if (rc < 0) {
@@ -1870,7 +2008,7 @@ static int mb86a20s_read_status_and_stats(struct dvb_frontend *fe,
 		}
 
 		/* Get statistics */
-		rc = mb86a20s_get_stats(fe);
+		rc = mb86a20s_get_stats(fe, status_nr);
 		if (rc < 0 && rc != -EBUSY) {
 			dev_err(&state->i2c->dev,
 				"%s: Can't get FE statistics.\n", __func__);
@@ -1994,7 +2132,7 @@ static struct dvb_frontend_ops mb86a20s_ops = {
 	/* Use dib8000 values per default */
 	.info = {
 		.name = "Fujitsu mb86A20s",
-		.caps = FE_CAN_INVERSION_AUTO | FE_CAN_RECOVER |
+		.caps = FE_CAN_RECOVER  |
 			FE_CAN_FEC_1_2  | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
 			FE_CAN_FEC_5_6  | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
 			FE_CAN_QPSK     | FE_CAN_QAM_16  | FE_CAN_QAM_64 |
diff --git a/drivers/media/dvb-frontends/mb86a20s.h b/drivers/media/dvb-frontends/mb86a20s.h
index bf22e77..6627a39 100644
--- a/drivers/media/dvb-frontends/mb86a20s.h
+++ b/drivers/media/dvb-frontends/mb86a20s.h
@@ -16,21 +16,25 @@
 #ifndef MB86A20S_H
 #define MB86A20S_H
 
+#include <linux/kconfig.h>
 #include <linux/dvb/frontend.h>
 
 /**
  * struct mb86a20s_config - Define the per-device attributes of the frontend
  *
+ * @fclk:		Clock frequency. If zero, assumes the default
+ *			(32.57142 Mhz)
  * @demod_address:	the demodulator's i2c address
+ * @is_serial:		if true, TS is serial. Otherwise, TS is parallel
  */
 
 struct mb86a20s_config {
-	u8 demod_address;
-	bool is_serial;
+	u32	fclk;
+	u8	demod_address;
+	bool	is_serial;
 };
 
-#if defined(CONFIG_DVB_MB86A20S) || (defined(CONFIG_DVB_MB86A20S_MODULE) \
-	&& defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_MB86A20S)
 extern struct dvb_frontend *mb86a20s_attach(const struct mb86a20s_config *config,
 					   struct i2c_adapter *i2c);
 extern struct i2c_adapter *mb86a20s_get_tuner_i2c_adapter(struct dvb_frontend *);
diff --git a/drivers/media/dvb-frontends/rtl2830.h b/drivers/media/dvb-frontends/rtl2830.h
index f4349a1..3313847 100644
--- a/drivers/media/dvb-frontends/rtl2830.h
+++ b/drivers/media/dvb-frontends/rtl2830.h
@@ -21,6 +21,7 @@
 #ifndef RTL2830_H
 #define RTL2830_H
 
+#include <linux/kconfig.h>
 #include <linux/dvb/frontend.h>
 
 struct rtl2830_config {
@@ -59,8 +60,7 @@ struct rtl2830_config {
 	u8 agc_targ_val;
 };
 
-#if defined(CONFIG_DVB_RTL2830) || \
-	(defined(CONFIG_DVB_RTL2830_MODULE) && defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_RTL2830)
 extern struct dvb_frontend *rtl2830_attach(
 	const struct rtl2830_config *config,
 	struct i2c_adapter *i2c
diff --git a/drivers/media/dvb-frontends/rtl2832.h b/drivers/media/dvb-frontends/rtl2832.h
index 785a466..fefba0e 100644
--- a/drivers/media/dvb-frontends/rtl2832.h
+++ b/drivers/media/dvb-frontends/rtl2832.h
@@ -21,6 +21,7 @@
 #ifndef RTL2832_H
 #define RTL2832_H
 
+#include <linux/kconfig.h>
 #include <linux/dvb/frontend.h>
 
 struct rtl2832_config {
@@ -54,8 +55,7 @@ struct rtl2832_config {
 	u8 tuner;
 };
 
-#if defined(CONFIG_DVB_RTL2832) || \
-	(defined(CONFIG_DVB_RTL2832_MODULE) && defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_RTL2832)
 extern struct dvb_frontend *rtl2832_attach(
 	const struct rtl2832_config *cfg,
 	struct i2c_adapter *i2c
diff --git a/drivers/media/dvb-frontends/s5h1409.h b/drivers/media/dvb-frontends/s5h1409.h
index 91f2ebd..63b1e0a 100644
--- a/drivers/media/dvb-frontends/s5h1409.h
+++ b/drivers/media/dvb-frontends/s5h1409.h
@@ -22,6 +22,7 @@
 #ifndef __S5H1409_H__
 #define __S5H1409_H__
 
+#include <linux/kconfig.h>
 #include <linux/dvb/frontend.h>
 
 struct s5h1409_config {
@@ -66,8 +67,7 @@ struct s5h1409_config {
 	u8 hvr1600_opt;
 };
 
-#if defined(CONFIG_DVB_S5H1409) || (defined(CONFIG_DVB_S5H1409_MODULE) \
-	&& defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_S5H1409)
 extern struct dvb_frontend *s5h1409_attach(const struct s5h1409_config *config,
 					   struct i2c_adapter *i2c);
 #else
diff --git a/drivers/media/dvb-frontends/s5h1411.h b/drivers/media/dvb-frontends/s5h1411.h
index 45ec0f8..e4f5687 100644
--- a/drivers/media/dvb-frontends/s5h1411.h
+++ b/drivers/media/dvb-frontends/s5h1411.h
@@ -22,6 +22,7 @@
 #ifndef __S5H1411_H__
 #define __S5H1411_H__
 
+#include <linux/kconfig.h>
 #include <linux/dvb/frontend.h>
 
 #define S5H1411_I2C_TOP_ADDR (0x32 >> 1)
@@ -68,8 +69,7 @@ struct s5h1411_config {
 	u8 status_mode;
 };
 
-#if defined(CONFIG_DVB_S5H1411) || \
-	(defined(CONFIG_DVB_S5H1411_MODULE) && defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_S5H1411)
 extern struct dvb_frontend *s5h1411_attach(const struct s5h1411_config *config,
 					   struct i2c_adapter *i2c);
 #else
diff --git a/drivers/media/dvb-frontends/s5h1432.h b/drivers/media/dvb-frontends/s5h1432.h
index b57438c..70917dd 100644
--- a/drivers/media/dvb-frontends/s5h1432.h
+++ b/drivers/media/dvb-frontends/s5h1432.h
@@ -22,6 +22,7 @@
 #ifndef __S5H1432_H__
 #define __S5H1432_H__
 
+#include <linux/kconfig.h>
 #include <linux/dvb/frontend.h>
 
 #define S5H1432_I2C_TOP_ADDR (0x02 >> 1)
@@ -74,8 +75,7 @@ struct s5h1432_config {
 	u8 status_mode;
 };
 
-#if defined(CONFIG_DVB_S5H1432) || \
-	(defined(CONFIG_DVB_S5H1432_MODULE) && defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_S5H1432)
 extern struct dvb_frontend *s5h1432_attach(const struct s5h1432_config *config,
 					   struct i2c_adapter *i2c);
 #else
diff --git a/drivers/media/dvb-frontends/s921.h b/drivers/media/dvb-frontends/s921.h
index f220d82..8d5e2a6 100644
--- a/drivers/media/dvb-frontends/s921.h
+++ b/drivers/media/dvb-frontends/s921.h
@@ -17,6 +17,7 @@
 #ifndef S921_H
 #define S921_H
 
+#include <linux/kconfig.h>
 #include <linux/dvb/frontend.h>
 
 struct s921_config {
@@ -24,8 +25,7 @@ struct s921_config {
 	u8 demod_address;
 };
 
-#if defined(CONFIG_DVB_S921) || (defined(CONFIG_DVB_S921_MODULE) \
-	&& defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_S921)
 extern struct dvb_frontend *s921_attach(const struct s921_config *config,
 					   struct i2c_adapter *i2c);
 extern struct i2c_adapter *s921_get_tuner_i2c_adapter(struct dvb_frontend *);
diff --git a/drivers/media/dvb-frontends/si21xx.h b/drivers/media/dvb-frontends/si21xx.h
index 141b5b8..1509fed 100644
--- a/drivers/media/dvb-frontends/si21xx.h
+++ b/drivers/media/dvb-frontends/si21xx.h
@@ -1,6 +1,7 @@
 #ifndef SI21XX_H
 #define SI21XX_H
 
+#include <linux/kconfig.h>
 #include <linux/dvb/frontend.h>
 #include "dvb_frontend.h"
 
@@ -12,8 +13,7 @@ struct si21xx_config {
 	int min_delay_ms;
 };
 
-#if defined(CONFIG_DVB_SI21XX) || \
-		(defined(CONFIG_DVB_SI21XX_MODULE) && defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_SI21XX)
 extern struct dvb_frontend *si21xx_attach(const struct si21xx_config *config,
 						struct i2c_adapter *i2c);
 #else
diff --git a/drivers/media/dvb-frontends/stb6000.h b/drivers/media/dvb-frontends/stb6000.h
index 7be479c..a768189 100644
--- a/drivers/media/dvb-frontends/stb6000.h
+++ b/drivers/media/dvb-frontends/stb6000.h
@@ -23,6 +23,7 @@
 #ifndef __DVB_STB6000_H__
 #define __DVB_STB6000_H__
 
+#include <linux/kconfig.h>
 #include <linux/i2c.h>
 #include "dvb_frontend.h"
 
@@ -34,8 +35,7 @@
  * @param i2c i2c adapter to use.
  * @return FE pointer on success, NULL on failure.
  */
-#if defined(CONFIG_DVB_STB6000) || (defined(CONFIG_DVB_STB6000_MODULE) \
-							&& defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_STB6000)
 extern struct dvb_frontend *stb6000_attach(struct dvb_frontend *fe, int addr,
 					   struct i2c_adapter *i2c);
 #else
diff --git a/drivers/media/dvb-frontends/stv0288.h b/drivers/media/dvb-frontends/stv0288.h
index f2b53db..a0bd931 100644
--- a/drivers/media/dvb-frontends/stv0288.h
+++ b/drivers/media/dvb-frontends/stv0288.h
@@ -27,6 +27,7 @@
 #ifndef STV0288_H
 #define STV0288_H
 
+#include <linux/kconfig.h>
 #include <linux/dvb/frontend.h>
 #include "dvb_frontend.h"
 
@@ -42,8 +43,7 @@ struct stv0288_config {
 	int (*set_ts_params)(struct dvb_frontend *fe, int is_punctured);
 };
 
-#if defined(CONFIG_DVB_STV0288) || (defined(CONFIG_DVB_STV0288_MODULE) && \
-							defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_STV0288)
 extern struct dvb_frontend *stv0288_attach(const struct stv0288_config *config,
 					   struct i2c_adapter *i2c);
 #else
diff --git a/drivers/media/dvb-frontends/stv0367.h b/drivers/media/dvb-frontends/stv0367.h
index 93cc4a5..ea80b34 100644
--- a/drivers/media/dvb-frontends/stv0367.h
+++ b/drivers/media/dvb-frontends/stv0367.h
@@ -26,6 +26,7 @@
 #ifndef STV0367_H
 #define STV0367_H
 
+#include <linux/kconfig.h>
 #include <linux/dvb/frontend.h>
 #include "dvb_frontend.h"
 
@@ -38,8 +39,7 @@ struct stv0367_config {
 	int clk_pol;
 };
 
-#if defined(CONFIG_DVB_STV0367) || (defined(CONFIG_DVB_STV0367_MODULE) \
-							&& defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_STV0367)
 extern struct
 dvb_frontend *stv0367ter_attach(const struct stv0367_config *config,
 					struct i2c_adapter *i2c);
diff --git a/drivers/media/dvb-frontends/stv0900.h b/drivers/media/dvb-frontends/stv0900.h
index 91c7ee8..e2a6dc6 100644
--- a/drivers/media/dvb-frontends/stv0900.h
+++ b/drivers/media/dvb-frontends/stv0900.h
@@ -26,6 +26,7 @@
 #ifndef STV0900_H
 #define STV0900_H
 
+#include <linux/kconfig.h>
 #include <linux/dvb/frontend.h>
 #include "dvb_frontend.h"
 
@@ -57,8 +58,7 @@ struct stv0900_config {
 	void (*set_lock_led)(struct dvb_frontend *fe, int offon);
 };
 
-#if defined(CONFIG_DVB_STV0900) || (defined(CONFIG_DVB_STV0900_MODULE) \
-							&& defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_STV0900)
 extern struct dvb_frontend *stv0900_attach(const struct stv0900_config *config,
 					struct i2c_adapter *i2c, int demod);
 #else
diff --git a/drivers/media/dvb-frontends/stv090x.c b/drivers/media/dvb-frontends/stv090x.c
index f36eeef..56d470a 100644
--- a/drivers/media/dvb-frontends/stv090x.c
+++ b/drivers/media/dvb-frontends/stv090x.c
@@ -3906,12 +3906,12 @@ static int stv090x_sleep(struct dvb_frontend *fe)
 		reg = stv090x_read_reg(state, STV090x_TSTTNR1);
 		STV090x_SETFIELD(reg, ADC1_PON_FIELD, 0);
 		if (stv090x_write_reg(state, STV090x_TSTTNR1, reg) < 0)
-			goto err;
+			goto err_unlock;
 		/* power off DiSEqC 1 */
 		reg = stv090x_read_reg(state, STV090x_TSTTNR2);
 		STV090x_SETFIELD(reg, DISEQC1_PON_FIELD, 0);
 		if (stv090x_write_reg(state, STV090x_TSTTNR2, reg) < 0)
-			goto err;
+			goto err_unlock;
 
 		/* check whether path 2 is already sleeping, that is when
 		   ADC2 is off */
@@ -3930,7 +3930,7 @@ static int stv090x_sleep(struct dvb_frontend *fe)
 		if (full_standby)
 			STV090x_SETFIELD(reg, STOP_CLKFEC_FIELD, 1);
 		if (stv090x_write_reg(state, STV090x_STOPCLK1, reg) < 0)
-			goto err;
+			goto err_unlock;
 		reg = stv090x_read_reg(state, STV090x_STOPCLK2);
 		/* sampling 1 clock */
 		STV090x_SETFIELD(reg, STOP_CLKSAMP1_FIELD, 1);
@@ -3941,7 +3941,7 @@ static int stv090x_sleep(struct dvb_frontend *fe)
 		if (full_standby)
 			STV090x_SETFIELD(reg, STOP_CLKTS_FIELD, 1);
 		if (stv090x_write_reg(state, STV090x_STOPCLK2, reg) < 0)
-			goto err;
+			goto err_unlock;
 		break;
 
 	case STV090x_DEMODULATOR_1:
@@ -3949,12 +3949,12 @@ static int stv090x_sleep(struct dvb_frontend *fe)
 		reg = stv090x_read_reg(state, STV090x_TSTTNR3);
 		STV090x_SETFIELD(reg, ADC2_PON_FIELD, 0);
 		if (stv090x_write_reg(state, STV090x_TSTTNR3, reg) < 0)
-			goto err;
+			goto err_unlock;
 		/* power off DiSEqC 2 */
 		reg = stv090x_read_reg(state, STV090x_TSTTNR4);
 		STV090x_SETFIELD(reg, DISEQC2_PON_FIELD, 0);
 		if (stv090x_write_reg(state, STV090x_TSTTNR4, reg) < 0)
-			goto err;
+			goto err_unlock;
 
 		/* check whether path 1 is already sleeping, that is when
 		   ADC1 is off */
@@ -3973,7 +3973,7 @@ static int stv090x_sleep(struct dvb_frontend *fe)
 		if (full_standby)
 			STV090x_SETFIELD(reg, STOP_CLKFEC_FIELD, 1);
 		if (stv090x_write_reg(state, STV090x_STOPCLK1, reg) < 0)
-			goto err;
+			goto err_unlock;
 		reg = stv090x_read_reg(state, STV090x_STOPCLK2);
 		/* sampling 2 clock */
 		STV090x_SETFIELD(reg, STOP_CLKSAMP2_FIELD, 1);
@@ -3984,7 +3984,7 @@ static int stv090x_sleep(struct dvb_frontend *fe)
 		if (full_standby)
 			STV090x_SETFIELD(reg, STOP_CLKTS_FIELD, 1);
 		if (stv090x_write_reg(state, STV090x_STOPCLK2, reg) < 0)
-			goto err;
+			goto err_unlock;
 		break;
 
 	default:
@@ -3997,7 +3997,7 @@ static int stv090x_sleep(struct dvb_frontend *fe)
 		reg = stv090x_read_reg(state, STV090x_SYNTCTRL);
 		STV090x_SETFIELD(reg, STANDBY_FIELD, 0x01);
 		if (stv090x_write_reg(state, STV090x_SYNTCTRL, reg) < 0)
-			goto err;
+			goto err_unlock;
 	}
 
 	mutex_unlock(&state->internal->demod_lock);
@@ -4005,8 +4005,10 @@ static int stv090x_sleep(struct dvb_frontend *fe)
 
 err_gateoff:
 	stv090x_i2c_gate_ctrl(state, 0);
-err:
+	goto err;
+err_unlock:
 	mutex_unlock(&state->internal->demod_lock);
+err:
 	dprintk(FE_ERROR, 1, "I/O error");
 	return -1;
 }
diff --git a/drivers/media/dvb-frontends/stv6110.h b/drivers/media/dvb-frontends/stv6110.h
index fe71bba..8fa07e6 100644
--- a/drivers/media/dvb-frontends/stv6110.h
+++ b/drivers/media/dvb-frontends/stv6110.h
@@ -25,6 +25,7 @@
 #ifndef __DVB_STV6110_H__
 #define __DVB_STV6110_H__
 
+#include <linux/kconfig.h>
 #include <linux/i2c.h>
 #include "dvb_frontend.h"
 
@@ -45,8 +46,7 @@ struct stv6110_config {
 	u8 clk_div;	/* divisor value for the output clock */
 };
 
-#if defined(CONFIG_DVB_STV6110) || (defined(CONFIG_DVB_STV6110_MODULE) \
-							&& defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_STV6110)
 extern struct dvb_frontend *stv6110_attach(struct dvb_frontend *fe,
 					const struct stv6110_config *config,
 					struct i2c_adapter *i2c);
diff --git a/drivers/media/dvb-frontends/tda10048.h b/drivers/media/dvb-frontends/tda10048.h
index fb2ef5a..5e7bf4e 100644
--- a/drivers/media/dvb-frontends/tda10048.h
+++ b/drivers/media/dvb-frontends/tda10048.h
@@ -22,6 +22,7 @@
 #ifndef TDA10048_H
 #define TDA10048_H
 
+#include <linux/kconfig.h>
 #include <linux/dvb/frontend.h>
 #include <linux/firmware.h>
 
@@ -72,8 +73,7 @@ struct tda10048_config {
 	u8 pll_n;
 };
 
-#if defined(CONFIG_DVB_TDA10048) || \
-	(defined(CONFIG_DVB_TDA10048_MODULE) && defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_TDA10048)
 extern struct dvb_frontend *tda10048_attach(
 	const struct tda10048_config *config,
 	struct i2c_adapter *i2c);
diff --git a/drivers/media/dvb-frontends/tda10071.h b/drivers/media/dvb-frontends/tda10071.h
index bff1c38..f9542f6 100644
--- a/drivers/media/dvb-frontends/tda10071.h
+++ b/drivers/media/dvb-frontends/tda10071.h
@@ -21,6 +21,7 @@
 #ifndef TDA10071_H
 #define TDA10071_H
 
+#include <linux/kconfig.h>
 #include <linux/dvb/frontend.h>
 
 struct tda10071_config {
@@ -71,8 +72,7 @@ struct tda10071_config {
 };
 
 
-#if defined(CONFIG_DVB_TDA10071) || \
-	(defined(CONFIG_DVB_TDA10071_MODULE) && defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_TDA10071)
 extern struct dvb_frontend *tda10071_attach(
 	const struct tda10071_config *config, struct i2c_adapter *i2c);
 #else
diff --git a/drivers/media/dvb-frontends/tda18271c2dd.h b/drivers/media/dvb-frontends/tda18271c2dd.h
index 1389c74..dd84f7b 100644
--- a/drivers/media/dvb-frontends/tda18271c2dd.h
+++ b/drivers/media/dvb-frontends/tda18271c2dd.h
@@ -1,7 +1,9 @@
 #ifndef _TDA18271C2DD_H_
 #define _TDA18271C2DD_H_
-#if defined(CONFIG_DVB_TDA18271C2DD) || (defined(CONFIG_DVB_TDA18271C2DD_MODULE) \
-        && defined(MODULE))
+
+#include <linux/kconfig.h>
+
+#if IS_ENABLED(CONFIG_DVB_TDA18271C2DD)
 struct dvb_frontend *tda18271c2dd_attach(struct dvb_frontend *fe,
 					 struct i2c_adapter *i2c, u8 adr);
 #else
diff --git a/drivers/media/dvb-frontends/ts2020.h b/drivers/media/dvb-frontends/ts2020.h
index c7e64af..5bcb9a7 100644
--- a/drivers/media/dvb-frontends/ts2020.h
+++ b/drivers/media/dvb-frontends/ts2020.h
@@ -22,6 +22,7 @@
 #ifndef TS2020_H
 #define TS2020_H
 
+#include <linux/kconfig.h>
 #include <linux/dvb/frontend.h>
 
 struct ts2020_config {
@@ -29,8 +30,7 @@ struct ts2020_config {
 	u8 clk_out_div;
 };
 
-#if defined(CONFIG_DVB_TS2020) || \
-	(defined(CONFIG_DVB_TS2020_MODULE) && defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_TS2020)
 
 extern struct dvb_frontend *ts2020_attach(
 	struct dvb_frontend *fe,
diff --git a/drivers/media/dvb-frontends/zl10036.h b/drivers/media/dvb-frontends/zl10036.h
index d84b8f8..5f1e821 100644
--- a/drivers/media/dvb-frontends/zl10036.h
+++ b/drivers/media/dvb-frontends/zl10036.h
@@ -21,6 +21,7 @@
 #ifndef DVB_ZL10036_H
 #define DVB_ZL10036_H
 
+#include <linux/kconfig.h>
 #include <linux/i2c.h>
 #include "dvb_frontend.h"
 
@@ -37,8 +38,7 @@ struct zl10036_config {
 	int rf_loop_enable;
 };
 
-#if defined(CONFIG_DVB_ZL10036) || \
-	(defined(CONFIG_DVB_ZL10036_MODULE) && defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_ZL10036)
 extern struct dvb_frontend *zl10036_attach(struct dvb_frontend *fe,
 	const struct zl10036_config *config, struct i2c_adapter *i2c);
 #else
diff --git a/drivers/media/dvb-frontends/zl10039.h b/drivers/media/dvb-frontends/zl10039.h
index 5eee7ea..750b9bc 100644
--- a/drivers/media/dvb-frontends/zl10039.h
+++ b/drivers/media/dvb-frontends/zl10039.h
@@ -22,8 +22,9 @@
 #ifndef ZL10039_H
 #define ZL10039_H
 
-#if defined(CONFIG_DVB_ZL10039) || (defined(CONFIG_DVB_ZL10039_MODULE) \
-	    && defined(MODULE))
+#include <linux/kconfig.h>
+
+#if IS_ENABLED(CONFIG_DVB_ZL10039)
 struct dvb_frontend *zl10039_attach(struct dvb_frontend *fe,
 					u8 i2c_addr,
 					struct i2c_adapter *i2c);
diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
index 7b771ba..9e7ce8b 100644
--- a/drivers/media/i2c/Kconfig
+++ b/drivers/media/i2c/Kconfig
@@ -112,6 +112,15 @@ config VIDEO_TLV320AIC23B
 	  To compile this driver as a module, choose M here: the
 	  module will be called tlv320aic23b.
 
+config VIDEO_UDA1342
+	tristate "Philips UDA1342 audio codec"
+	depends on VIDEO_V4L2 && I2C
+	---help---
+	  Support for the Philips UDA1342 audio codec.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called uda1342.
+
 config VIDEO_WM8775
 	tristate "Wolfson Microelectronics WM8775 audio ADC with input mixer"
 	depends on VIDEO_V4L2 && I2C
@@ -133,7 +142,7 @@ config VIDEO_WM8739
 	  module will be called wm8739.
 
 config VIDEO_VP27SMPX
-	tristate "Panasonic VP27s internal MPX"
+	tristate "Panasonic VP27's internal MPX"
 	depends on VIDEO_V4L2 && I2C
 	---help---
 	  Support for the internal MPX of the Panasonic VP27s tuner.
@@ -141,6 +150,15 @@ config VIDEO_VP27SMPX
 	  To compile this driver as a module, choose M here: the
 	  module will be called vp27smpx.
 
+config VIDEO_SONY_BTF_MPX
+	tristate "Sony BTF's internal MPX"
+	depends on VIDEO_V4L2 && I2C
+	help
+	  Support for the internal MPX of the Sony BTF-PG472Z tuner.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called sony-btf-mpx.
+
 comment "RDS decoders"
 
 config VIDEO_SAA6588
@@ -283,6 +301,35 @@ config VIDEO_TVP7002
 	  To compile this driver as a module, choose M here: the
 	  module will be called tvp7002.
 
+config VIDEO_TW2804
+	tristate "Techwell TW2804 multiple video decoder"
+	depends on VIDEO_V4L2 && I2C
+	---help---
+	  Support for the Techwell tw2804 multiple video decoder.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called tw2804.
+
+config VIDEO_TW9903
+	tristate "Techwell TW9903 video decoder"
+	depends on VIDEO_V4L2 && I2C
+	---help---
+	  Support for the Techwell tw9903 multi-standard video decoder
+	  with high quality down scaler.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called tw9903.
+
+config VIDEO_TW9906
+	tristate "Techwell TW9906 video decoder"
+	depends on VIDEO_V4L2 && I2C
+	---help---
+	  Support for the Techwell tw9906 enhanced multi-standard comb filter
+	  video decoder with YCbCr input support.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called tw9906.
+
 config VIDEO_VPX3220
 	tristate "vpx3220a, vpx3216b & vpx3214c video decoders"
 	depends on VIDEO_V4L2 && I2C
@@ -386,6 +433,17 @@ config VIDEO_APTINA_PLL
 config VIDEO_SMIAPP_PLL
 	tristate
 
+config VIDEO_OV7640
+	tristate "OmniVision OV7640 sensor support"
+	depends on I2C && VIDEO_V4L2
+	depends on MEDIA_CAMERA_SUPPORT
+	---help---
+	  This is a Video4Linux2 sensor-level driver for the OmniVision
+	  OV7640 camera.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ov7640.
+
 config VIDEO_OV7670
 	tristate "OmniVision OV7670 sensor support"
 	depends on I2C && VIDEO_V4L2
@@ -550,10 +608,10 @@ config VIDEO_UPD64083
 comment "Miscelaneous helper chips"
 
 config VIDEO_THS7303
-	tristate "THS7303 Video Amplifier"
-	depends on I2C
+	tristate "THS7303/53 Video Amplifier"
+	depends on VIDEO_V4L2 && I2C
 	help
-	  Support for TI THS7303 video amplifier
+	  Support for TI THS7303/53 video amplifier
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called ths7303.
diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile
index cfefd30..720f42d 100644
--- a/drivers/media/i2c/Makefile
+++ b/drivers/media/i2c/Makefile
@@ -37,16 +37,22 @@ obj-$(CONFIG_VIDEO_THS7303) += ths7303.o
 obj-$(CONFIG_VIDEO_TVP5150) += tvp5150.o
 obj-$(CONFIG_VIDEO_TVP514X) += tvp514x.o
 obj-$(CONFIG_VIDEO_TVP7002) += tvp7002.o
+obj-$(CONFIG_VIDEO_TW2804) += tw2804.o
+obj-$(CONFIG_VIDEO_TW9903) += tw9903.o
+obj-$(CONFIG_VIDEO_TW9906) += tw9906.o
 obj-$(CONFIG_VIDEO_CS5345) += cs5345.o
 obj-$(CONFIG_VIDEO_CS53L32A) += cs53l32a.o
 obj-$(CONFIG_VIDEO_M52790) += m52790.o
 obj-$(CONFIG_VIDEO_TLV320AIC23B) += tlv320aic23b.o
+obj-$(CONFIG_VIDEO_UDA1342) += uda1342.o
 obj-$(CONFIG_VIDEO_WM8775) += wm8775.o
 obj-$(CONFIG_VIDEO_WM8739) += wm8739.o
 obj-$(CONFIG_VIDEO_VP27SMPX) += vp27smpx.o
+obj-$(CONFIG_VIDEO_SONY_BTF_MPX) += sony-btf-mpx.o
 obj-$(CONFIG_VIDEO_UPD64031A) += upd64031a.o
 obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o
-obj-$(CONFIG_VIDEO_OV7670) 	+= ov7670.o
+obj-$(CONFIG_VIDEO_OV7640) += ov7640.o
+obj-$(CONFIG_VIDEO_OV7670) += ov7670.o
 obj-$(CONFIG_VIDEO_OV9650) += ov9650.o
 obj-$(CONFIG_VIDEO_TCM825X) += tcm825x.o
 obj-$(CONFIG_VIDEO_MT9M032) += mt9m032.o
diff --git a/drivers/media/i2c/ad9389b.c b/drivers/media/i2c/ad9389b.c
index c2886b6..58344b6 100644
--- a/drivers/media/i2c/ad9389b.c
+++ b/drivers/media/i2c/ad9389b.c
@@ -354,7 +354,7 @@ static int ad9389b_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *
 	return 0;
 }
 
-static int ad9389b_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
+static int ad9389b_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 
diff --git a/drivers/media/i2c/adp1653.c b/drivers/media/i2c/adp1653.c
index df16380..ef75abe 100644
--- a/drivers/media/i2c/adp1653.c
+++ b/drivers/media/i2c/adp1653.c
@@ -447,7 +447,7 @@ free_and_quit:
 	return ret;
 }
 
-static int __exit adp1653_remove(struct i2c_client *client)
+static int adp1653_remove(struct i2c_client *client)
 {
 	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
 	struct adp1653_flash *flash = to_adp1653_flash(subdev);
@@ -476,7 +476,7 @@ static struct i2c_driver adp1653_i2c_driver = {
 		.pm	= &adp1653_pm_ops,
 	},
 	.probe		= adp1653_probe,
-	.remove		= __exit_p(adp1653_remove),
+	.remove		= adp1653_remove,
 	.id_table	= adp1653_id_table,
 };
 
diff --git a/drivers/media/i2c/adv7183.c b/drivers/media/i2c/adv7183.c
index 6fed5b7..56a1fa4 100644
--- a/drivers/media/i2c/adv7183.c
+++ b/drivers/media/i2c/adv7183.c
@@ -507,7 +507,7 @@ static int adv7183_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *
 	return 0;
 }
 
-static int adv7183_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
+static int adv7183_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 
diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index f47555b..31a63c9 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -699,7 +699,7 @@ static int adv7604_g_register(struct v4l2_subdev *sd,
 }
 
 static int adv7604_s_register(struct v4l2_subdev *sd,
-					struct v4l2_dbg_register *reg)
+					const struct v4l2_dbg_register *reg)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 
diff --git a/drivers/media/i2c/ak881x.c b/drivers/media/i2c/ak881x.c
index ba67465..fd47465 100644
--- a/drivers/media/i2c/ak881x.c
+++ b/drivers/media/i2c/ak881x.c
@@ -101,7 +101,7 @@ static int ak881x_g_register(struct v4l2_subdev *sd,
 }
 
 static int ak881x_s_register(struct v4l2_subdev *sd,
-			     struct v4l2_dbg_register *reg)
+			     const struct v4l2_dbg_register *reg)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 
diff --git a/drivers/media/i2c/cs5345.c b/drivers/media/i2c/cs5345.c
index c8581e2..1d2f7c8 100644
--- a/drivers/media/i2c/cs5345.c
+++ b/drivers/media/i2c/cs5345.c
@@ -110,7 +110,7 @@ static int cs5345_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *r
 	return 0;
 }
 
-static int cs5345_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
+static int cs5345_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 
diff --git a/drivers/media/i2c/cx25840/cx25840-core.c b/drivers/media/i2c/cx25840/cx25840-core.c
index f4149eb..12fb9b2 100644
--- a/drivers/media/i2c/cx25840/cx25840-core.c
+++ b/drivers/media/i2c/cx25840/cx25840-core.c
@@ -1671,7 +1671,7 @@ static int cx25840_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *
 	return 0;
 }
 
-static int cx25840_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
+static int cx25840_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 
@@ -1835,7 +1835,7 @@ static int cx25840_s_audio_routing(struct v4l2_subdev *sd,
 	return set_input(client, state->vid_input, input);
 }
 
-static int cx25840_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *freq)
+static int cx25840_s_frequency(struct v4l2_subdev *sd, const struct v4l2_frequency *freq)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 
@@ -1881,7 +1881,7 @@ static int cx25840_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
 	return 0;
 }
 
-static int cx25840_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
+static int cx25840_s_tuner(struct v4l2_subdev *sd, const struct v4l2_tuner *vt)
 {
 	struct cx25840_state *state = to_state(sd);
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
diff --git a/drivers/media/i2c/ir-kbd-i2c.c b/drivers/media/i2c/ir-kbd-i2c.c
index 08ae067..2586e46 100644
--- a/drivers/media/i2c/ir-kbd-i2c.c
+++ b/drivers/media/i2c/ir-kbd-i2c.c
@@ -423,6 +423,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	 */
 	rc->map_name       = ir->ir_codes;
 	rc->allowed_protos = rc_type;
+	rc->enabled_protocols = rc_type;
 	if (!rc->driver_name)
 		rc->driver_name = MODULE_NAME;
 
diff --git a/drivers/media/i2c/m52790.c b/drivers/media/i2c/m52790.c
index 0991576..39f50fd 100644
--- a/drivers/media/i2c/m52790.c
+++ b/drivers/media/i2c/m52790.c
@@ -96,7 +96,7 @@ static int m52790_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *r
 	return 0;
 }
 
-static int m52790_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
+static int m52790_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg)
 {
 	struct m52790_state *state = to_state(sd);
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
diff --git a/drivers/media/i2c/msp3400-driver.c b/drivers/media/i2c/msp3400-driver.c
index 766305f..54a9dd3 100644
--- a/drivers/media/i2c/msp3400-driver.c
+++ b/drivers/media/i2c/msp3400-driver.c
@@ -445,7 +445,7 @@ static int msp_s_radio(struct v4l2_subdev *sd)
 	return 0;
 }
 
-static int msp_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *freq)
+static int msp_s_frequency(struct v4l2_subdev *sd, const struct v4l2_frequency *freq)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 
@@ -535,7 +535,7 @@ static int msp_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
 	return 0;
 }
 
-static int msp_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
+static int msp_s_tuner(struct v4l2_subdev *sd, const struct v4l2_tuner *vt)
 {
 	struct msp_state *state = to_state(sd);
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
diff --git a/drivers/media/i2c/mt9m032.c b/drivers/media/i2c/mt9m032.c
index f80c1d7e..2526b66 100644
--- a/drivers/media/i2c/mt9m032.c
+++ b/drivers/media/i2c/mt9m032.c
@@ -548,7 +548,7 @@ static int mt9m032_g_register(struct v4l2_subdev *sd,
 }
 
 static int mt9m032_s_register(struct v4l2_subdev *sd,
-			      struct v4l2_dbg_register *reg)
+			      const struct v4l2_dbg_register *reg)
 {
 	struct mt9m032 *sensor = to_mt9m032(sd);
 	struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev);
diff --git a/drivers/media/i2c/mt9v011.c b/drivers/media/i2c/mt9v011.c
index 73b7688..3f415fd 100644
--- a/drivers/media/i2c/mt9v011.c
+++ b/drivers/media/i2c/mt9v011.c
@@ -421,7 +421,7 @@ static int mt9v011_g_register(struct v4l2_subdev *sd,
 }
 
 static int mt9v011_s_register(struct v4l2_subdev *sd,
-			      struct v4l2_dbg_register *reg)
+			      const struct v4l2_dbg_register *reg)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 
diff --git a/drivers/media/i2c/ov7640.c b/drivers/media/i2c/ov7640.c
new file mode 100644
index 0000000..b0cc927
--- /dev/null
+++ b/drivers/media/i2c/ov7640.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2005-2006 Micronas USA 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., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-chip-ident.h>
+#include <linux/slab.h>
+
+MODULE_DESCRIPTION("OmniVision ov7640 sensor driver");
+MODULE_LICENSE("GPL v2");
+
+static const u8 initial_registers[] = {
+	0x12, 0x80,
+	0x12, 0x54,
+	0x14, 0x24,
+	0x15, 0x01,
+	0x28, 0x20,
+	0x75, 0x82,
+	0xFF, 0xFF, /* Terminator (reg 0xFF is unused) */
+};
+
+static int write_regs(struct i2c_client *client, const u8 *regs)
+{
+	int i;
+
+	for (i = 0; regs[i] != 0xFF; i += 2)
+		if (i2c_smbus_write_byte_data(client, regs[i], regs[i + 1]) < 0)
+			return -1;
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct v4l2_subdev_ops ov7640_ops;
+
+static int ov7640_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	struct i2c_adapter *adapter = client->adapter;
+	struct v4l2_subdev *sd;
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		return -ENODEV;
+
+	sd = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
+	if (sd == NULL)
+		return -ENOMEM;
+	v4l2_i2c_subdev_init(sd, client, &ov7640_ops);
+
+	client->flags = I2C_CLIENT_SCCB;
+
+	v4l_info(client, "chip found @ 0x%02x (%s)\n",
+			client->addr << 1, client->adapter->name);
+
+	if (write_regs(client, initial_registers) < 0) {
+		v4l_err(client, "error initializing OV7640\n");
+		kfree(sd);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+
+static int ov7640_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+
+	v4l2_device_unregister_subdev(sd);
+	kfree(sd);
+	return 0;
+}
+
+static const struct i2c_device_id ov7640_id[] = {
+	{ "ov7640", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, ov7640_id);
+
+static struct i2c_driver ov7640_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "ov7640",
+	},
+	.probe = ov7640_probe,
+	.remove = ov7640_remove,
+	.id_table = ov7640_id,
+};
+module_i2c_driver(ov7640_driver);
diff --git a/drivers/media/i2c/ov7670.c b/drivers/media/i2c/ov7670.c
index 05ed5b8..617ad3f 100644
--- a/drivers/media/i2c/ov7670.c
+++ b/drivers/media/i2c/ov7670.c
@@ -1487,7 +1487,7 @@ static int ov7670_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *r
 	return ret;
 }
 
-static int ov7670_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
+static int ov7670_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 
diff --git a/drivers/media/i2c/saa6588.c b/drivers/media/i2c/saa6588.c
index 0caac50..b4e1ccb 100644
--- a/drivers/media/i2c/saa6588.c
+++ b/drivers/media/i2c/saa6588.c
@@ -435,7 +435,7 @@ static int saa6588_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
 	return 0;
 }
 
-static int saa6588_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
+static int saa6588_s_tuner(struct v4l2_subdev *sd, const struct v4l2_tuner *vt)
 {
 	struct saa6588 *s = to_saa6588(sd);
 
diff --git a/drivers/media/i2c/saa7115.c b/drivers/media/i2c/saa7115.c
index 6b6788c..52c717d 100644
--- a/drivers/media/i2c/saa7115.c
+++ b/drivers/media/i2c/saa7115.c
@@ -83,9 +83,10 @@ struct saa711x_state {
 	u32 ident;
 	u32 audclk_freq;
 	u32 crystal_freq;
-	u8 ucgc;
+	bool ucgc;
 	u8 cgcdiv;
-	u8 apll;
+	bool apll;
+	bool double_asclk;
 };
 
 static inline struct saa711x_state *to_state(struct v4l2_subdev *sd)
@@ -732,8 +733,12 @@ static int saa711x_s_clock_freq(struct v4l2_subdev *sd, u32 freq)
 	if (state->apll)
 		acc |= 0x08;
 
+	if (state->double_asclk) {
+		acpf <<= 1;
+		acni <<= 1;
+	}
 	saa711x_write(sd, R_38_CLK_RATIO_AMXCLK_TO_ASCLK, 0x03);
-	saa711x_write(sd, R_39_CLK_RATIO_ASCLK_TO_ALRCLK, 0x10);
+	saa711x_write(sd, R_39_CLK_RATIO_ASCLK_TO_ALRCLK, 0x10 << state->double_asclk);
 	saa711x_write(sd, R_3A_AUD_CLK_GEN_BASIC_SETUP, acc);
 
 	saa711x_write(sd, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD, acpf & 0xff);
@@ -1259,6 +1264,12 @@ static int saa711x_s_routing(struct v4l2_subdev *sd,
 				(saa711x_read(sd, R_83_X_PORT_I_O_ENA_AND_OUT_CLK) & 0xfe) |
 				(state->output & 0x01));
 	}
+	if (state->ident > V4L2_IDENT_SAA7111A) {
+		if (config & SAA7115_IDQ_IS_DEFAULT)
+			saa711x_write(sd, R_85_I_PORT_SIGNAL_POLAR, 0x20);
+		else
+			saa711x_write(sd, R_85_I_PORT_SIGNAL_POLAR, 0x21);
+	}
 	return 0;
 }
 
@@ -1296,9 +1307,10 @@ static int saa711x_s_crystal_freq(struct v4l2_subdev *sd, u32 freq, u32 flags)
 	if (freq != SAA7115_FREQ_32_11_MHZ && freq != SAA7115_FREQ_24_576_MHZ)
 		return -EINVAL;
 	state->crystal_freq = freq;
+	state->double_asclk = flags & SAA7115_FREQ_FL_DOUBLE_ASCLK;
 	state->cgcdiv = (flags & SAA7115_FREQ_FL_CGCDIV) ? 3 : 4;
-	state->ucgc = (flags & SAA7115_FREQ_FL_UCGC) ? 1 : 0;
-	state->apll = (flags & SAA7115_FREQ_FL_APLL) ? 1 : 0;
+	state->ucgc = flags & SAA7115_FREQ_FL_UCGC;
+	state->apll = flags & SAA7115_FREQ_FL_APLL;
 	saa711x_s_clock_freq(sd, state->audclk_freq);
 	return 0;
 }
@@ -1354,6 +1366,34 @@ static int saa711x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
 	 */
 
 	reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
+
+	if (state->ident == V4L2_IDENT_SAA7115) {
+		reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC);
+
+		v4l2_dbg(1, debug, sd, "Status byte 1 (0x1e)=0x%02x\n", reg1e);
+
+		switch (reg1e & 0x03) {
+		case 1:
+			*std &= V4L2_STD_NTSC;
+			break;
+		case 2:
+			/*
+			 * V4L2_STD_PAL just cover the european PAL standards.
+			 * This is wrong, as the device could also be using an
+			 * other PAL standard.
+			 */
+			*std &= V4L2_STD_PAL   | V4L2_STD_PAL_N  | V4L2_STD_PAL_Nc |
+				V4L2_STD_PAL_M | V4L2_STD_PAL_60;
+			break;
+		case 3:
+			*std &= V4L2_STD_SECAM;
+			break;
+		default:
+			/* Can't detect anything */
+			break;
+		}
+	}
+
 	v4l2_dbg(1, debug, sd, "Status byte 2 (0x1f)=0x%02x\n", reg1f);
 
 	/* horizontal/vertical not locked */
@@ -1365,34 +1405,6 @@ static int saa711x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
 	else
 		*std &= V4L2_STD_625_50;
 
-	if (state->ident != V4L2_IDENT_SAA7115)
-		goto ret;
-
-	reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC);
-
-	switch (reg1e & 0x03) {
-	case 1:
-		*std &= V4L2_STD_NTSC;
-		break;
-	case 2:
-		/*
-		 * V4L2_STD_PAL just cover the european PAL standards.
-		 * This is wrong, as the device could also be using an
-		 * other PAL standard.
-		 */
-		*std &= V4L2_STD_PAL   | V4L2_STD_PAL_N  | V4L2_STD_PAL_Nc |
-			V4L2_STD_PAL_M | V4L2_STD_PAL_60;
-		break;
-	case 3:
-		*std &= V4L2_STD_SECAM;
-		break;
-	default:
-		/* Can't detect anything */
-		break;
-	}
-
-	v4l2_dbg(1, debug, sd, "Status byte 1 (0x1e)=0x%02x\n", reg1e);
-
 ret:
 	v4l2_dbg(1, debug, sd, "detected std mask = %08Lx\n", *std);
 
@@ -1428,7 +1440,7 @@ static int saa711x_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *
 	return 0;
 }
 
-static int saa711x_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
+static int saa711x_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 
diff --git a/drivers/media/i2c/saa7127.c b/drivers/media/i2c/saa7127.c
index b745f68..8a47ac1 100644
--- a/drivers/media/i2c/saa7127.c
+++ b/drivers/media/i2c/saa7127.c
@@ -672,7 +672,7 @@ static int saa7127_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *
 	return 0;
 }
 
-static int saa7127_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
+static int saa7127_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 
diff --git a/drivers/media/i2c/saa717x.c b/drivers/media/i2c/saa717x.c
index 1e84466..cf3a0aa 100644
--- a/drivers/media/i2c/saa717x.c
+++ b/drivers/media/i2c/saa717x.c
@@ -988,7 +988,7 @@ static int saa717x_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *
 	return 0;
 }
 
-static int saa717x_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
+static int saa717x_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 	u16 addr = reg->reg & 0xffff;
@@ -1113,7 +1113,7 @@ static int saa717x_s_stream(struct v4l2_subdev *sd, int enable)
 }
 
 /* change audio mode */
-static int saa717x_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
+static int saa717x_s_tuner(struct v4l2_subdev *sd, const struct v4l2_tuner *vt)
 {
 	struct saa717x_state *decoder = to_state(sd);
 	int audio_mode;
diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c
index 83c7ed7..cae4f46 100644
--- a/drivers/media/i2c/smiapp/smiapp-core.c
+++ b/drivers/media/i2c/smiapp/smiapp-core.c
@@ -2833,7 +2833,7 @@ static int smiapp_probe(struct i2c_client *client,
 				 sensor->src->pads, 0);
 }
 
-static int __exit smiapp_remove(struct i2c_client *client)
+static int smiapp_remove(struct i2c_client *client)
 {
 	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
 	struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
@@ -2881,7 +2881,7 @@ static struct i2c_driver smiapp_i2c_driver = {
 		.pm = &smiapp_pm_ops,
 	},
 	.probe	= smiapp_probe,
-	.remove	= __exit_p(smiapp_remove),
+	.remove	= smiapp_remove,
 	.id_table = smiapp_id_table,
 };
 
diff --git a/drivers/media/i2c/soc_camera/Kconfig b/drivers/media/i2c/soc_camera/Kconfig
index 6dff2b7..23d352f 100644
--- a/drivers/media/i2c/soc_camera/Kconfig
+++ b/drivers/media/i2c/soc_camera/Kconfig
@@ -9,7 +9,6 @@ config SOC_CAMERA_IMX074
 config SOC_CAMERA_MT9M001
 	tristate "mt9m001 support"
 	depends on SOC_CAMERA && I2C
-	select GPIO_PCA953X if MT9M001_PCA9536_SWITCH
 	help
 	  This driver supports MT9M001 cameras from Micron, monochrome
 	  and colour models.
@@ -36,7 +35,6 @@ config SOC_CAMERA_MT9T112
 config SOC_CAMERA_MT9V022
 	tristate "mt9v022 and mt9v024 support"
 	depends on SOC_CAMERA && I2C
-	select GPIO_PCA953X if MT9V022_PCA9536_SWITCH
 	help
 	  This driver supports MT9V022 cameras from Micron
 
diff --git a/drivers/media/i2c/soc_camera/mt9m001.c b/drivers/media/i2c/soc_camera/mt9m001.c
index bcdc861..dd90898 100644
--- a/drivers/media/i2c/soc_camera/mt9m001.c
+++ b/drivers/media/i2c/soc_camera/mt9m001.c
@@ -360,7 +360,7 @@ static int mt9m001_g_register(struct v4l2_subdev *sd,
 }
 
 static int mt9m001_s_register(struct v4l2_subdev *sd,
-			      struct v4l2_dbg_register *reg)
+			      const struct v4l2_dbg_register *reg)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 
diff --git a/drivers/media/i2c/soc_camera/mt9m111.c b/drivers/media/i2c/soc_camera/mt9m111.c
index bbc4ff9..8bd4e0d 100644
--- a/drivers/media/i2c/soc_camera/mt9m111.c
+++ b/drivers/media/i2c/soc_camera/mt9m111.c
@@ -641,7 +641,7 @@ static int mt9m111_g_register(struct v4l2_subdev *sd,
 }
 
 static int mt9m111_s_register(struct v4l2_subdev *sd,
-			      struct v4l2_dbg_register *reg)
+			      const struct v4l2_dbg_register *reg)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 
@@ -701,11 +701,11 @@ static int mt9m111_set_global_gain(struct mt9m111 *mt9m111, int gain)
 	return reg_write(GLOBAL_GAIN, val);
 }
 
-static int mt9m111_set_autoexposure(struct mt9m111 *mt9m111, int on)
+static int mt9m111_set_autoexposure(struct mt9m111 *mt9m111, int val)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
 
-	if (on)
+	if (val == V4L2_EXPOSURE_AUTO)
 		return reg_set(OPER_MODE_CTRL, MT9M111_OPMODE_AUTOEXPO_EN);
 	return reg_clear(OPER_MODE_CTRL, MT9M111_OPMODE_AUTOEXPO_EN);
 }
@@ -785,8 +785,6 @@ static int mt9m111_init(struct mt9m111 *mt9m111)
 	struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
 	int ret;
 
-	/* Default HIGHPOWER context */
-	mt9m111->ctx = &context_b;
 	ret = mt9m111_enable(mt9m111);
 	if (!ret)
 		ret = mt9m111_reset(mt9m111);
@@ -975,6 +973,9 @@ static int mt9m111_probe(struct i2c_client *client,
 	if (!mt9m111)
 		return -ENOMEM;
 
+	/* Default HIGHPOWER context */
+	mt9m111->ctx = &context_b;
+
 	v4l2_i2c_subdev_init(&mt9m111->subdev, client, &mt9m111_subdev_ops);
 	v4l2_ctrl_handler_init(&mt9m111->hdl, 5);
 	v4l2_ctrl_new_std(&mt9m111->hdl, &mt9m111_ctrl_ops,
diff --git a/drivers/media/i2c/soc_camera/mt9t031.c b/drivers/media/i2c/soc_camera/mt9t031.c
index d80d044..26a15b8 100644
--- a/drivers/media/i2c/soc_camera/mt9t031.c
+++ b/drivers/media/i2c/soc_camera/mt9t031.c
@@ -430,7 +430,7 @@ static int mt9t031_g_register(struct v4l2_subdev *sd,
 }
 
 static int mt9t031_s_register(struct v4l2_subdev *sd,
-			      struct v4l2_dbg_register *reg)
+			      const struct v4l2_dbg_register *reg)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 
diff --git a/drivers/media/i2c/soc_camera/mt9t112.c b/drivers/media/i2c/soc_camera/mt9t112.c
index 188e29b..a7256b7 100644
--- a/drivers/media/i2c/soc_camera/mt9t112.c
+++ b/drivers/media/i2c/soc_camera/mt9t112.c
@@ -766,7 +766,7 @@ static int mt9t112_g_register(struct v4l2_subdev *sd,
 }
 
 static int mt9t112_s_register(struct v4l2_subdev *sd,
-			      struct v4l2_dbg_register *reg)
+			      const struct v4l2_dbg_register *reg)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 	int ret;
diff --git a/drivers/media/i2c/soc_camera/mt9v022.c b/drivers/media/i2c/soc_camera/mt9v022.c
index a5e65d6..a295e59 100644
--- a/drivers/media/i2c/soc_camera/mt9v022.c
+++ b/drivers/media/i2c/soc_camera/mt9v022.c
@@ -275,6 +275,7 @@ static int mt9v022_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 	struct mt9v022 *mt9v022 = to_mt9v022(client);
 	struct v4l2_rect rect = a->c;
+	int min_row, min_blank;
 	int ret;
 
 	/* Bayer format - even size lengths */
@@ -310,13 +311,21 @@ static int mt9v022_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)
 		ret = reg_write(client, MT9V022_COLUMN_START, rect.left);
 	if (!ret)
 		ret = reg_write(client, MT9V022_ROW_START, rect.top);
+	/*
+	 * mt9v022: min total row time is 660 columns, min blanking is 43
+	 * mt9v024: min total row time is 690 columns, min blanking is 61
+	 */
+	if (is_mt9v024(mt9v022->chip_version)) {
+		min_row = 690;
+		min_blank = 61;
+	} else {
+		min_row = 660;
+		min_blank = 43;
+	}
 	if (!ret)
-		/*
-		 * Default 94, Phytec driver says:
-		 * "width + horizontal blank >= 660"
-		 */
 		ret = v4l2_ctrl_s_ctrl(mt9v022->hblank,
-				rect.width > 660 - 43 ? 43 : 660 - rect.width);
+				rect.width > min_row - min_blank ?
+				min_blank : min_row - rect.width);
 	if (!ret)
 		ret = v4l2_ctrl_s_ctrl(mt9v022->vblank, 45);
 	if (!ret)
@@ -488,7 +497,7 @@ static int mt9v022_g_register(struct v4l2_subdev *sd,
 }
 
 static int mt9v022_s_register(struct v4l2_subdev *sd,
-			      struct v4l2_dbg_register *reg)
+			      const struct v4l2_dbg_register *reg)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 
diff --git a/drivers/media/i2c/soc_camera/ov2640.c b/drivers/media/i2c/soc_camera/ov2640.c
index 0f520f6..e316842 100644
--- a/drivers/media/i2c/soc_camera/ov2640.c
+++ b/drivers/media/i2c/soc_camera/ov2640.c
@@ -756,7 +756,7 @@ static int ov2640_g_register(struct v4l2_subdev *sd,
 }
 
 static int ov2640_s_register(struct v4l2_subdev *sd,
-			     struct v4l2_dbg_register *reg)
+			     const struct v4l2_dbg_register *reg)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 
diff --git a/drivers/media/i2c/soc_camera/ov5642.c b/drivers/media/i2c/soc_camera/ov5642.c
index 9d53309..9aa56de 100644
--- a/drivers/media/i2c/soc_camera/ov5642.c
+++ b/drivers/media/i2c/soc_camera/ov5642.c
@@ -708,7 +708,7 @@ static int ov5642_get_register(struct v4l2_subdev *sd, struct v4l2_dbg_register
 	return ret;
 }
 
-static int ov5642_set_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
+static int ov5642_set_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 
diff --git a/drivers/media/i2c/soc_camera/ov6650.c b/drivers/media/i2c/soc_camera/ov6650.c
index dbe4f56..991202d 100644
--- a/drivers/media/i2c/soc_camera/ov6650.c
+++ b/drivers/media/i2c/soc_camera/ov6650.c
@@ -421,7 +421,7 @@ static int ov6650_get_register(struct v4l2_subdev *sd,
 }
 
 static int ov6650_set_register(struct v4l2_subdev *sd,
-				struct v4l2_dbg_register *reg)
+				const struct v4l2_dbg_register *reg)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 
diff --git a/drivers/media/i2c/soc_camera/ov772x.c b/drivers/media/i2c/soc_camera/ov772x.c
index fbeb5b2..713d62e 100644
--- a/drivers/media/i2c/soc_camera/ov772x.c
+++ b/drivers/media/i2c/soc_camera/ov772x.c
@@ -652,7 +652,7 @@ static int ov772x_g_register(struct v4l2_subdev *sd,
 }
 
 static int ov772x_s_register(struct v4l2_subdev *sd,
-			     struct v4l2_dbg_register *reg)
+			     const struct v4l2_dbg_register *reg)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 
diff --git a/drivers/media/i2c/soc_camera/ov9640.c b/drivers/media/i2c/soc_camera/ov9640.c
index 0599304..20ca62d 100644
--- a/drivers/media/i2c/soc_camera/ov9640.c
+++ b/drivers/media/i2c/soc_camera/ov9640.c
@@ -322,7 +322,7 @@ static int ov9640_get_register(struct v4l2_subdev *sd,
 }
 
 static int ov9640_set_register(struct v4l2_subdev *sd,
-				struct v4l2_dbg_register *reg)
+				const struct v4l2_dbg_register *reg)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 
diff --git a/drivers/media/i2c/soc_camera/ov9740.c b/drivers/media/i2c/soc_camera/ov9740.c
index 2f236da..012bd62 100644
--- a/drivers/media/i2c/soc_camera/ov9740.c
+++ b/drivers/media/i2c/soc_camera/ov9740.c
@@ -835,7 +835,7 @@ static int ov9740_get_register(struct v4l2_subdev *sd,
 }
 
 static int ov9740_set_register(struct v4l2_subdev *sd,
-			       struct v4l2_dbg_register *reg)
+			       const struct v4l2_dbg_register *reg)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 
diff --git a/drivers/media/i2c/soc_camera/rj54n1cb0c.c b/drivers/media/i2c/soc_camera/rj54n1cb0c.c
index 5c92679..1f9ec3b 100644
--- a/drivers/media/i2c/soc_camera/rj54n1cb0c.c
+++ b/drivers/media/i2c/soc_camera/rj54n1cb0c.c
@@ -1161,7 +1161,7 @@ static int rj54n1_g_register(struct v4l2_subdev *sd,
 }
 
 static int rj54n1_s_register(struct v4l2_subdev *sd,
-			     struct v4l2_dbg_register *reg)
+			     const struct v4l2_dbg_register *reg)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 
diff --git a/drivers/media/i2c/soc_camera/tw9910.c b/drivers/media/i2c/soc_camera/tw9910.c
index 7d20746..bad90b1 100644
--- a/drivers/media/i2c/soc_camera/tw9910.c
+++ b/drivers/media/i2c/soc_camera/tw9910.c
@@ -554,7 +554,7 @@ static int tw9910_g_register(struct v4l2_subdev *sd,
 }
 
 static int tw9910_s_register(struct v4l2_subdev *sd,
-			     struct v4l2_dbg_register *reg)
+			     const struct v4l2_dbg_register *reg)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 
diff --git a/drivers/media/i2c/sony-btf-mpx.c b/drivers/media/i2c/sony-btf-mpx.c
new file mode 100644
index 0000000..38cbea9
--- /dev/null
+++ b/drivers/media/i2c/sony-btf-mpx.c
@@ -0,0 +1,399 @@
+/*
+ * Copyright (C) 2005-2006 Micronas USA 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., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/videodev2.h>
+#include <media/tuner.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-device.h>
+#include <linux/slab.h>
+
+MODULE_DESCRIPTION("sony-btf-mpx driver");
+MODULE_LICENSE("GPL v2");
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "debug level 0=off(default) 1=on\n");
+
+/* #define MPX_DEBUG */
+
+/*
+ * Note:
+ *
+ * AS(IF/MPX) pin:      LOW      HIGH/OPEN
+ * IF/MPX address:   0x42/0x40   0x43/0x44
+ */
+
+
+static int force_mpx_mode = -1;
+module_param(force_mpx_mode, int, 0644);
+
+struct sony_btf_mpx {
+	struct v4l2_subdev sd;
+	int mpxmode;
+	u32 audmode;
+};
+
+static inline struct sony_btf_mpx *to_state(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct sony_btf_mpx, sd);
+}
+
+static int mpx_write(struct i2c_client *client, int dev, int addr, int val)
+{
+	u8 buffer[5];
+	struct i2c_msg msg;
+
+	buffer[0] = dev;
+	buffer[1] = addr >> 8;
+	buffer[2] = addr & 0xff;
+	buffer[3] = val >> 8;
+	buffer[4] = val & 0xff;
+	msg.addr = client->addr;
+	msg.flags = 0;
+	msg.len = 5;
+	msg.buf = buffer;
+	i2c_transfer(client->adapter, &msg, 1);
+	return 0;
+}
+
+/*
+ * MPX register values for the BTF-PG472Z:
+ *
+ *                                 FM_     NICAM_  SCART_
+ *          MODUS  SOURCE    ACB   PRESCAL PRESCAL PRESCAL SYSTEM  VOLUME
+ *         10/0030 12/0008 12/0013 12/000E 12/0010 12/0000 10/0020 12/0000
+ *         ---------------------------------------------------------------
+ * Auto     1003    0020    0100    2603    5000    XXXX    0001    7500
+ *
+ * B/G
+ *  Mono    1003    0020    0100    2603    5000    XXXX    0003    7500
+ *  A2      1003    0020    0100    2601    5000    XXXX    0003    7500
+ *  NICAM   1003    0120    0100    2603    5000    XXXX    0008    7500
+ *
+ * I
+ *  Mono    1003    0020    0100    2603    7900    XXXX    000A    7500
+ *  NICAM   1003    0120    0100    2603    7900    XXXX    000A    7500
+ *
+ * D/K
+ *  Mono    1003    0020    0100    2603    5000    XXXX    0004    7500
+ *  A2-1    1003    0020    0100    2601    5000    XXXX    0004    7500
+ *  A2-2    1003    0020    0100    2601    5000    XXXX    0005    7500
+ *  A2-3    1003    0020    0100    2601    5000    XXXX    0007    7500
+ *  NICAM   1003    0120    0100    2603    5000    XXXX    000B    7500
+ *
+ * L/L'
+ *  Mono    0003    0200    0100    7C03    5000    2200    0009    7500
+ *  NICAM   0003    0120    0100    7C03    5000    XXXX    0009    7500
+ *
+ * M
+ *  Mono    1003    0200    0100    2B03    5000    2B00    0002    7500
+ *
+ * For Asia, replace the 0x26XX in FM_PRESCALE with 0x14XX.
+ *
+ * Bilingual selection in A2/NICAM:
+ *
+ *         High byte of SOURCE     Left chan   Right chan
+ *                 0x01              MAIN         SUB
+ *                 0x03              MAIN         MAIN
+ *                 0x04              SUB          SUB
+ *
+ * Force mono in NICAM by setting the high byte of SOURCE to 0x02 (L/L') or
+ * 0x00 (all other bands).  Force mono in A2 with FMONO_A2:
+ *
+ *                      FMONO_A2
+ *                      10/0022
+ *                      --------
+ *     Forced mono ON     07F0
+ *     Forced mono OFF    0190
+ */
+
+static const struct {
+	enum { AUD_MONO, AUD_A2, AUD_NICAM, AUD_NICAM_L } audio_mode;
+	u16 modus;
+	u16 source;
+	u16 acb;
+	u16 fm_prescale;
+	u16 nicam_prescale;
+	u16 scart_prescale;
+	u16 system;
+	u16 volume;
+} mpx_audio_modes[] = {
+	/* Auto */	{ AUD_MONO,	0x1003, 0x0020, 0x0100, 0x2603,
+					0x5000, 0x0000, 0x0001, 0x7500 },
+	/* B/G Mono */	{ AUD_MONO,	0x1003, 0x0020, 0x0100, 0x2603,
+					0x5000, 0x0000, 0x0003, 0x7500 },
+	/* B/G A2 */	{ AUD_A2,	0x1003, 0x0020, 0x0100, 0x2601,
+					0x5000, 0x0000, 0x0003, 0x7500 },
+	/* B/G NICAM */ { AUD_NICAM,	0x1003, 0x0120, 0x0100, 0x2603,
+					0x5000, 0x0000, 0x0008, 0x7500 },
+	/* I Mono */	{ AUD_MONO,	0x1003, 0x0020, 0x0100, 0x2603,
+					0x7900, 0x0000, 0x000A, 0x7500 },
+	/* I NICAM */	{ AUD_NICAM,	0x1003, 0x0120, 0x0100, 0x2603,
+					0x7900, 0x0000, 0x000A, 0x7500 },
+	/* D/K Mono */	{ AUD_MONO,	0x1003, 0x0020, 0x0100, 0x2603,
+					0x5000, 0x0000, 0x0004, 0x7500 },
+	/* D/K A2-1 */	{ AUD_A2,	0x1003, 0x0020, 0x0100, 0x2601,
+					0x5000, 0x0000, 0x0004, 0x7500 },
+	/* D/K A2-2 */	{ AUD_A2,	0x1003, 0x0020, 0x0100, 0x2601,
+					0x5000, 0x0000, 0x0005, 0x7500 },
+	/* D/K A2-3 */	{ AUD_A2,	0x1003, 0x0020, 0x0100, 0x2601,
+					0x5000, 0x0000, 0x0007, 0x7500 },
+	/* D/K NICAM */	{ AUD_NICAM,	0x1003, 0x0120, 0x0100, 0x2603,
+					0x5000, 0x0000, 0x000B, 0x7500 },
+	/* L/L' Mono */	{ AUD_MONO,	0x0003, 0x0200, 0x0100, 0x7C03,
+					0x5000, 0x2200, 0x0009, 0x7500 },
+	/* L/L' NICAM */{ AUD_NICAM_L,	0x0003, 0x0120, 0x0100, 0x7C03,
+					0x5000, 0x0000, 0x0009, 0x7500 },
+};
+
+#define MPX_NUM_MODES	ARRAY_SIZE(mpx_audio_modes)
+
+static int mpx_setup(struct sony_btf_mpx *t)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&t->sd);
+	u16 source = 0;
+	u8 buffer[3];
+	struct i2c_msg msg;
+	int mode = t->mpxmode;
+
+	/* reset MPX */
+	buffer[0] = 0x00;
+	buffer[1] = 0x80;
+	buffer[2] = 0x00;
+	msg.addr = client->addr;
+	msg.flags = 0;
+	msg.len = 3;
+	msg.buf = buffer;
+	i2c_transfer(client->adapter, &msg, 1);
+	buffer[1] = 0x00;
+	i2c_transfer(client->adapter, &msg, 1);
+
+	if (t->audmode != V4L2_TUNER_MODE_MONO)
+		mode++;
+
+	if (mpx_audio_modes[mode].audio_mode != AUD_MONO) {
+		switch (t->audmode) {
+		case V4L2_TUNER_MODE_MONO:
+			switch (mpx_audio_modes[mode].audio_mode) {
+			case AUD_A2:
+				source = mpx_audio_modes[mode].source;
+				break;
+			case AUD_NICAM:
+				source = 0x0000;
+				break;
+			case AUD_NICAM_L:
+				source = 0x0200;
+				break;
+			default:
+				break;
+			}
+			break;
+		case V4L2_TUNER_MODE_STEREO:
+			source = mpx_audio_modes[mode].source;
+			break;
+		case V4L2_TUNER_MODE_LANG1:
+			source = 0x0300;
+			break;
+		case V4L2_TUNER_MODE_LANG2:
+			source = 0x0400;
+			break;
+		}
+		source |= mpx_audio_modes[mode].source & 0x00ff;
+	} else
+		source = mpx_audio_modes[mode].source;
+
+	mpx_write(client, 0x10, 0x0030, mpx_audio_modes[mode].modus);
+	mpx_write(client, 0x12, 0x0008, source);
+	mpx_write(client, 0x12, 0x0013, mpx_audio_modes[mode].acb);
+	mpx_write(client, 0x12, 0x000e,
+			mpx_audio_modes[mode].fm_prescale);
+	mpx_write(client, 0x12, 0x0010,
+			mpx_audio_modes[mode].nicam_prescale);
+	mpx_write(client, 0x12, 0x000d,
+			mpx_audio_modes[mode].scart_prescale);
+	mpx_write(client, 0x10, 0x0020, mpx_audio_modes[mode].system);
+	mpx_write(client, 0x12, 0x0000, mpx_audio_modes[mode].volume);
+	if (mpx_audio_modes[mode].audio_mode == AUD_A2)
+		mpx_write(client, 0x10, 0x0022,
+			t->audmode == V4L2_TUNER_MODE_MONO ? 0x07f0 : 0x0190);
+
+#ifdef MPX_DEBUG
+	{
+		u8 buf1[3], buf2[2];
+		struct i2c_msg msgs[2];
+
+		v4l2_info(client,
+			"MPX registers: %04x %04x %04x %04x %04x %04x %04x %04x\n",
+			mpx_audio_modes[mode].modus,
+			source,
+			mpx_audio_modes[mode].acb,
+			mpx_audio_modes[mode].fm_prescale,
+			mpx_audio_modes[mode].nicam_prescale,
+			mpx_audio_modes[mode].scart_prescale,
+			mpx_audio_modes[mode].system,
+			mpx_audio_modes[mode].volume);
+		buf1[0] = 0x11;
+		buf1[1] = 0x00;
+		buf1[2] = 0x7e;
+		msgs[0].addr = client->addr;
+		msgs[0].flags = 0;
+		msgs[0].len = 3;
+		msgs[0].buf = buf1;
+		msgs[1].addr = client->addr;
+		msgs[1].flags = I2C_M_RD;
+		msgs[1].len = 2;
+		msgs[1].buf = buf2;
+		i2c_transfer(client->adapter, msgs, 2);
+		v4l2_info(client, "MPX system: %02x%02x\n",
+				buf2[0], buf2[1]);
+		buf1[0] = 0x11;
+		buf1[1] = 0x02;
+		buf1[2] = 0x00;
+		i2c_transfer(client->adapter, msgs, 2);
+		v4l2_info(client, "MPX status: %02x%02x\n",
+				buf2[0], buf2[1]);
+	}
+#endif
+	return 0;
+}
+
+
+static int sony_btf_mpx_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
+{
+	struct sony_btf_mpx *t = to_state(sd);
+	int default_mpx_mode = 0;
+
+	if (std & V4L2_STD_PAL_BG)
+		default_mpx_mode = 1;
+	else if (std & V4L2_STD_PAL_I)
+		default_mpx_mode = 4;
+	else if (std & V4L2_STD_PAL_DK)
+		default_mpx_mode = 6;
+	else if (std & V4L2_STD_SECAM_L)
+		default_mpx_mode = 11;
+
+	if (default_mpx_mode != t->mpxmode) {
+		t->mpxmode = default_mpx_mode;
+		mpx_setup(t);
+	}
+	return 0;
+}
+
+static int sony_btf_mpx_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
+{
+	struct sony_btf_mpx *t = to_state(sd);
+
+	vt->capability = V4L2_TUNER_CAP_NORM |
+		V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 |
+		V4L2_TUNER_CAP_LANG2;
+	vt->rxsubchans = V4L2_TUNER_SUB_MONO |
+		V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_LANG1 |
+		V4L2_TUNER_SUB_LANG2;
+	vt->audmode = t->audmode;
+	return 0;
+}
+
+static int sony_btf_mpx_s_tuner(struct v4l2_subdev *sd, const struct v4l2_tuner *vt)
+{
+	struct sony_btf_mpx *t = to_state(sd);
+
+	if (vt->type != V4L2_TUNER_ANALOG_TV)
+		return -EINVAL;
+
+	if (vt->audmode != t->audmode) {
+		t->audmode = vt->audmode;
+		mpx_setup(t);
+	}
+	return 0;
+}
+
+/* --------------------------------------------------------------------------*/
+
+static const struct v4l2_subdev_core_ops sony_btf_mpx_core_ops = {
+	.s_std = sony_btf_mpx_s_std,
+};
+
+static const struct v4l2_subdev_tuner_ops sony_btf_mpx_tuner_ops = {
+	.s_tuner = sony_btf_mpx_s_tuner,
+	.g_tuner = sony_btf_mpx_g_tuner,
+};
+
+static const struct v4l2_subdev_ops sony_btf_mpx_ops = {
+	.core = &sony_btf_mpx_core_ops,
+	.tuner = &sony_btf_mpx_tuner_ops,
+};
+
+/* --------------------------------------------------------------------------*/
+
+static int sony_btf_mpx_probe(struct i2c_client *client,
+				const struct i2c_device_id *id)
+{
+	struct sony_btf_mpx *t;
+	struct v4l2_subdev *sd;
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK))
+		return -ENODEV;
+
+	v4l_info(client, "chip found @ 0x%x (%s)\n",
+			client->addr << 1, client->adapter->name);
+
+	t = kzalloc(sizeof(struct sony_btf_mpx), GFP_KERNEL);
+	if (t == NULL)
+		return -ENOMEM;
+
+	sd = &t->sd;
+	v4l2_i2c_subdev_init(sd, client, &sony_btf_mpx_ops);
+
+	/* Initialize sony_btf_mpx */
+	t->mpxmode = 0;
+	t->audmode = V4L2_TUNER_MODE_STEREO;
+
+	return 0;
+}
+
+static int sony_btf_mpx_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+
+	v4l2_device_unregister_subdev(sd);
+	kfree(to_state(sd));
+
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct i2c_device_id sony_btf_mpx_id[] = {
+	{ "sony-btf-mpx", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, sony_btf_mpx_id);
+
+static struct i2c_driver sony_btf_mpx_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "sony-btf-mpx",
+	},
+	.probe = sony_btf_mpx_probe,
+	.remove = sony_btf_mpx_remove,
+	.id_table = sony_btf_mpx_id,
+};
+module_i2c_driver(sony_btf_mpx_driver);
diff --git a/drivers/media/i2c/tda7432.c b/drivers/media/i2c/tda7432.c
index f7707e6..28b5121 100644
--- a/drivers/media/i2c/tda7432.c
+++ b/drivers/media/i2c/tda7432.c
@@ -35,6 +35,7 @@
 
 #include <media/v4l2-device.h>
 #include <media/v4l2-ioctl.h>
+#include <media/v4l2-ctrls.h>
 #include <media/i2c-addr.h>
 
 #ifndef VIDEO_AUDIO_BALANCE
@@ -60,13 +61,17 @@ MODULE_PARM_DESC(maxvol, "Set maximium volume to +20dB(0) else +0dB(1). Default
 
 struct tda7432 {
 	struct v4l2_subdev sd;
-	int addr;
-	int input;
-	int volume;
-	int muted;
-	int bass, treble;
-	int lf, lr, rf, rr;
-	int loud;
+	struct v4l2_ctrl_handler hdl;
+	struct {
+		/* bass/treble cluster */
+		struct v4l2_ctrl *bass;
+		struct v4l2_ctrl *treble;
+	};
+	struct {
+		/* mute/balance cluster */
+		struct v4l2_ctrl *mute;
+		struct v4l2_ctrl *balance;
+	};
 };
 
 static inline struct tda7432 *to_state(struct v4l2_subdev *sd)
@@ -74,6 +79,11 @@ static inline struct tda7432 *to_state(struct v4l2_subdev *sd)
 	return container_of(sd, struct tda7432, sd);
 }
 
+static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
+{
+	return &container_of(ctrl->handler, struct tda7432, hdl)->sd;
+}
+
 /* The TDA7432 is made by STS-Thompson
  * http://www.st.com
  * http://us.st.com/stonline/books/pdf/docs/4056.pdf
@@ -227,24 +237,22 @@ static int tda7432_write(struct v4l2_subdev *sd, int subaddr, int val)
 static int tda7432_set(struct v4l2_subdev *sd)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
-	struct tda7432 *t = to_state(sd);
 	unsigned char buf[16];
 
-	v4l2_dbg(1, debug, sd,
-		"tda7432: 7432_set(0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x)\n",
-		t->input, t->volume, t->bass, t->treble, t->lf, t->lr,
-		t->rf, t->rr, t->loud);
 	buf[0]  = TDA7432_IN;
-	buf[1]  = t->input;
-	buf[2]  = t->volume;
-	buf[3]  = t->bass;
-	buf[4]	= t->treble;
-	buf[5]  = t->lf;
-	buf[6]  = t->lr;
-	buf[7]  = t->rf;
-	buf[8]  = t->rr;
-	buf[9]  = t->loud;
-	if (10 != i2c_master_send(client, buf, 10)) {
+	buf[1]  = TDA7432_STEREO_IN |  /* Main (stereo) input   */
+		  TDA7432_BASS_SYM  |  /* Symmetric bass cut    */
+		  TDA7432_BASS_NORM;   /* Normal bass range     */
+	buf[2]  = 0x3b;
+	if (loudness)			 /* Turn loudness on?     */
+		buf[2] |= TDA7432_LD_ON;
+	buf[3]  = TDA7432_TREBLE_0DB | (TDA7432_BASS_0DB << 4);
+	buf[4]  = TDA7432_ATTEN_0DB;
+	buf[5]  = TDA7432_ATTEN_0DB;
+	buf[6]  = TDA7432_ATTEN_0DB;
+	buf[7]  = TDA7432_ATTEN_0DB;
+	buf[8]  = loudness;
+	if (9 != i2c_master_send(client, buf, 9)) {
 		v4l2_err(sd, "I/O error, trying tda7432_set\n");
 		return -1;
 	}
@@ -252,174 +260,86 @@ static int tda7432_set(struct v4l2_subdev *sd)
 	return 0;
 }
 
-static void do_tda7432_init(struct v4l2_subdev *sd)
-{
-	struct tda7432 *t = to_state(sd);
-
-	v4l2_dbg(2, debug, sd, "In tda7432_init\n");
-
-	t->input  = TDA7432_STEREO_IN |  /* Main (stereo) input   */
-		    TDA7432_BASS_SYM  |  /* Symmetric bass cut    */
-		    TDA7432_BASS_NORM;   /* Normal bass range     */
-	t->volume =  0x3b ;				 /* -27dB Volume            */
-	if (loudness)			 /* Turn loudness on?     */
-		t->volume |= TDA7432_LD_ON;
-	t->muted    = 1;
-	t->treble   = TDA7432_TREBLE_0DB; /* 0dB Treble            */
-	t->bass		= TDA7432_BASS_0DB; 	 /* 0dB Bass              */
-	t->lf     = TDA7432_ATTEN_0DB;	 /* 0dB attenuation       */
-	t->lr     = TDA7432_ATTEN_0DB;	 /* 0dB attenuation       */
-	t->rf     = TDA7432_ATTEN_0DB;	 /* 0dB attenuation       */
-	t->rr     = TDA7432_ATTEN_0DB;	 /* 0dB attenuation       */
-	t->loud   = loudness;		 /* insmod parameter      */
-
-	tda7432_set(sd);
-}
-
-static int tda7432_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+static int tda7432_log_status(struct v4l2_subdev *sd)
 {
-	struct tda7432 *t = to_state(sd);
+	struct tda7432 *state = to_state(sd);
 
-	switch (ctrl->id) {
-	case V4L2_CID_AUDIO_MUTE:
-		ctrl->value=t->muted;
-		return 0;
-	case V4L2_CID_AUDIO_VOLUME:
-		if (!maxvol){  /* max +20db */
-			ctrl->value = ( 0x6f - (t->volume & 0x7F) ) * 630;
-		} else {       /* max 0db   */
-			ctrl->value = ( 0x6f - (t->volume & 0x7F) ) * 829;
-		}
-		return 0;
-	case V4L2_CID_AUDIO_BALANCE:
-	{
-		if ( (t->lf) < (t->rf) )
-			/* right is attenuated, balance shifted left */
-			ctrl->value = (32768 - 1057*(t->rf));
-		else
-			/* left is attenuated, balance shifted right */
-			ctrl->value = (32768 + 1057*(t->lf));
-		return 0;
-	}
-	case V4L2_CID_AUDIO_BASS:
-	{
-		/* Bass/treble 4 bits each */
-		int bass=t->bass;
-		if(bass >= 0x8)
-			bass = ~(bass - 0x8) & 0xf;
-		ctrl->value = (bass << 12)+(bass << 8)+(bass << 4)+(bass);
-		return 0;
-	}
-	case V4L2_CID_AUDIO_TREBLE:
-	{
-		int treble=t->treble;
-		if(treble >= 0x8)
-			treble = ~(treble - 0x8) & 0xf;
-		ctrl->value = (treble << 12)+(treble << 8)+(treble << 4)+(treble);
-		return 0;
-	}
-	}
-	return -EINVAL;
+	v4l2_ctrl_handler_log_status(&state->hdl, sd->name);
+	return 0;
 }
 
-static int tda7432_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+static int tda7432_s_ctrl(struct v4l2_ctrl *ctrl)
 {
+	struct v4l2_subdev *sd = to_sd(ctrl);
 	struct tda7432 *t = to_state(sd);
+	u8 bass, treble, volume;
+	u8 lf, lr, rf, rr;
 
 	switch (ctrl->id) {
 	case V4L2_CID_AUDIO_MUTE:
-		t->muted=ctrl->value;
-		break;
-	case V4L2_CID_AUDIO_VOLUME:
-		if(!maxvol){ /* max +20db */
-			t->volume = 0x6f - ((ctrl->value)/630);
-		} else {    /* max 0db   */
-			t->volume = 0x6f - ((ctrl->value)/829);
-		}
-		if (loudness)		/* Turn on the loudness bit */
-			t->volume |= TDA7432_LD_ON;
-
-		tda7432_write(sd, TDA7432_VL, t->volume);
-		return 0;
-	case V4L2_CID_AUDIO_BALANCE:
-		if (ctrl->value < 32768) {
+		if (t->balance->val < 0) {
 			/* shifted to left, attenuate right */
-			t->rr = (32768 - ctrl->value)/1057;
-			t->rf = t->rr;
-			t->lr = TDA7432_ATTEN_0DB;
-			t->lf = TDA7432_ATTEN_0DB;
-		} else if(ctrl->value > 32769) {
+			rr = rf = -t->balance->val;
+			lr = lf = TDA7432_ATTEN_0DB;
+		} else if (t->balance->val > 0) {
 			/* shifted to right, attenuate left */
-			t->lf = (ctrl->value - 32768)/1057;
-			t->lr = t->lf;
-			t->rr = TDA7432_ATTEN_0DB;
-			t->rf = TDA7432_ATTEN_0DB;
+			rr = rf = TDA7432_ATTEN_0DB;
+			lr = lf = t->balance->val;
 		} else {
 			/* centered */
-			t->rr = TDA7432_ATTEN_0DB;
-			t->rf = TDA7432_ATTEN_0DB;
-			t->lf = TDA7432_ATTEN_0DB;
-			t->lr = TDA7432_ATTEN_0DB;
+			rr = rf = TDA7432_ATTEN_0DB;
+			lr = lf = TDA7432_ATTEN_0DB;
 		}
-		break;
-	case V4L2_CID_AUDIO_BASS:
-		t->bass = ctrl->value >> 12;
-		if(t->bass>= 0x8)
-				t->bass = (~t->bass & 0xf) + 0x8 ;
-
-		tda7432_write(sd, TDA7432_TN, 0x10 | (t->bass << 4) | t->treble);
+		if (t->mute->val) {
+			lf |= TDA7432_MUTE;
+			lr |= TDA7432_MUTE;
+			lf |= TDA7432_MUTE;
+			rr |= TDA7432_MUTE;
+		}
+		/* Mute & update balance*/
+		tda7432_write(sd, TDA7432_LF, lf);
+		tda7432_write(sd, TDA7432_LR, lr);
+		tda7432_write(sd, TDA7432_RF, rf);
+		tda7432_write(sd, TDA7432_RR, rr);
 		return 0;
-	case V4L2_CID_AUDIO_TREBLE:
-		t->treble= ctrl->value >> 12;
-		if(t->treble>= 0x8)
-				t->treble = (~t->treble & 0xf) + 0x8 ;
+	case V4L2_CID_AUDIO_VOLUME:
+		volume = 0x6f - ctrl->val;
+		if (loudness)		/* Turn on the loudness bit */
+			volume |= TDA7432_LD_ON;
 
-		tda7432_write(sd, TDA7432_TN, 0x10 | (t->bass << 4) | t->treble);
+		tda7432_write(sd, TDA7432_VL, volume);
 		return 0;
-	default:
-		return -EINVAL;
-	}
-
-	/* Used for both mute and balance changes */
-	if (t->muted)
-	{
-		/* Mute & update balance*/
-		tda7432_write(sd, TDA7432_LF, t->lf | TDA7432_MUTE);
-		tda7432_write(sd, TDA7432_LR, t->lr | TDA7432_MUTE);
-		tda7432_write(sd, TDA7432_RF, t->rf | TDA7432_MUTE);
-		tda7432_write(sd, TDA7432_RR, t->rr | TDA7432_MUTE);
-	} else {
-		tda7432_write(sd, TDA7432_LF, t->lf);
-		tda7432_write(sd, TDA7432_LR, t->lr);
-		tda7432_write(sd, TDA7432_RF, t->rf);
-		tda7432_write(sd, TDA7432_RR, t->rr);
-	}
-	return 0;
-}
-
-static int tda7432_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
-{
-	switch (qc->id) {
-	case V4L2_CID_AUDIO_VOLUME:
-		return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, 58880);
-	case V4L2_CID_AUDIO_MUTE:
-		return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0);
-	case V4L2_CID_AUDIO_BALANCE:
 	case V4L2_CID_AUDIO_BASS:
-	case V4L2_CID_AUDIO_TREBLE:
-		return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, 32768);
+		bass = t->bass->val;
+		treble = t->treble->val;
+		if (bass >= 0x8)
+			bass = 14 - (bass - 8);
+		if (treble >= 0x8)
+			treble = 14 - (treble - 8);
+
+		tda7432_write(sd, TDA7432_TN, 0x10 | (bass << 4) | treble);
+		return 0;
 	}
 	return -EINVAL;
 }
 
 /* ----------------------------------------------------------------------- */
 
-static const struct v4l2_subdev_core_ops tda7432_core_ops = {
-	.queryctrl = tda7432_queryctrl,
-	.g_ctrl = tda7432_g_ctrl,
+static const struct v4l2_ctrl_ops tda7432_ctrl_ops = {
 	.s_ctrl = tda7432_s_ctrl,
 };
 
+static const struct v4l2_subdev_core_ops tda7432_core_ops = {
+	.log_status = tda7432_log_status,
+	.g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
+	.try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
+	.s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
+	.g_ctrl = v4l2_subdev_g_ctrl,
+	.s_ctrl = v4l2_subdev_s_ctrl,
+	.queryctrl = v4l2_subdev_queryctrl,
+	.querymenu = v4l2_subdev_querymenu,
+};
+
 static const struct v4l2_subdev_ops tda7432_ops = {
 	.core = &tda7432_core_ops,
 };
@@ -444,6 +364,28 @@ static int tda7432_probe(struct i2c_client *client,
 		return -ENOMEM;
 	sd = &t->sd;
 	v4l2_i2c_subdev_init(sd, client, &tda7432_ops);
+	v4l2_ctrl_handler_init(&t->hdl, 5);
+	v4l2_ctrl_new_std(&t->hdl, &tda7432_ctrl_ops,
+		V4L2_CID_AUDIO_VOLUME, 0, maxvol ? 0x68 : 0x4f, 1, maxvol ? 0x5d : 0x47);
+	t->mute = v4l2_ctrl_new_std(&t->hdl, &tda7432_ctrl_ops,
+		V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
+	t->balance = v4l2_ctrl_new_std(&t->hdl, &tda7432_ctrl_ops,
+		V4L2_CID_AUDIO_BALANCE, -31, 31, 1, 0);
+	t->bass = v4l2_ctrl_new_std(&t->hdl, &tda7432_ctrl_ops,
+		V4L2_CID_AUDIO_BASS, 0, 14, 1, 7);
+	t->treble = v4l2_ctrl_new_std(&t->hdl, &tda7432_ctrl_ops,
+		V4L2_CID_AUDIO_TREBLE, 0, 14, 1, 7);
+	sd->ctrl_handler = &t->hdl;
+	if (t->hdl.error) {
+		int err = t->hdl.error;
+
+		v4l2_ctrl_handler_free(&t->hdl);
+		kfree(t);
+		return err;
+	}
+	v4l2_ctrl_cluster(2, &t->bass);
+	v4l2_ctrl_cluster(2, &t->mute);
+	v4l2_ctrl_handler_setup(&t->hdl);
 	if (loudness < 0 || loudness > 15) {
 		v4l2_warn(sd, "loudness parameter must be between 0 and 15\n");
 		if (loudness < 0)
@@ -452,17 +394,19 @@ static int tda7432_probe(struct i2c_client *client,
 			loudness = 15;
 	}
 
-	do_tda7432_init(sd);
+	tda7432_set(sd);
 	return 0;
 }
 
 static int tda7432_remove(struct i2c_client *client)
 {
 	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct tda7432 *t = to_state(sd);
 
-	do_tda7432_init(sd);
+	tda7432_set(sd);
 	v4l2_device_unregister_subdev(sd);
-	kfree(to_state(sd));
+	v4l2_ctrl_handler_free(&t->hdl);
+	kfree(t);
 	return 0;
 }
 
diff --git a/drivers/media/i2c/tda9840.c b/drivers/media/i2c/tda9840.c
index 3d7ddd9..01441e3 100644
--- a/drivers/media/i2c/tda9840.c
+++ b/drivers/media/i2c/tda9840.c
@@ -87,7 +87,7 @@ static int tda9840_status(struct v4l2_subdev *sd)
 	return byte & 0x60;
 }
 
-static int tda9840_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *t)
+static int tda9840_s_tuner(struct v4l2_subdev *sd, const struct v4l2_tuner *t)
 {
 	int stat = tda9840_status(sd);
 	int byte;
diff --git a/drivers/media/i2c/ths7303.c b/drivers/media/i2c/ths7303.c
index e747524..c433955 100644
--- a/drivers/media/i2c/ths7303.c
+++ b/drivers/media/i2c/ths7303.c
@@ -1,7 +1,15 @@
 /*
- * ths7303- THS7303 Video Amplifier driver
+ * ths7303/53- THS7303/53 Video Amplifier driver
  *
  * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
+ * Copyright 2013 Cisco Systems, Inc. and/or its affiliates.
+ *
+ * Author: Chaithrika U S <chaithrika@ti.com>
+ *
+ * Contributors:
+ *     Hans Verkuil <hans.verkuil@cisco.com>
+ *     Lad, Prabhakar <prabhakar.lad@ti.com>
+ *     Martin Bugge <marbugge@cisco.com>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
@@ -13,25 +21,27 @@
  * GNU General Public License for more details.
  */
 
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/ctype.h>
-#include <linux/slab.h>
 #include <linux/i2c.h>
-#include <linux/device.h>
-#include <linux/delay.h>
 #include <linux/module.h>
-#include <linux/uaccess.h>
-#include <linux/videodev2.h>
+#include <linux/slab.h>
 
-#include <media/v4l2-device.h>
-#include <media/v4l2-subdev.h>
+#include <media/ths7303.h>
 #include <media/v4l2-chip-ident.h>
+#include <media/v4l2-device.h>
 
 #define THS7303_CHANNEL_1	1
 #define THS7303_CHANNEL_2	2
 #define THS7303_CHANNEL_3	3
 
+struct ths7303_state {
+	struct v4l2_subdev		sd;
+	struct ths7303_platform_data	pdata;
+	struct v4l2_bt_timings		bt;
+	int std_id;
+	int stream_on;
+	int driver_data;
+};
+
 enum ths7303_filter_mode {
 	THS7303_FILTER_MODE_480I_576I,
 	THS7303_FILTER_MODE_480P_576P,
@@ -48,64 +58,84 @@ static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Debug level 0-1");
 
+static inline struct ths7303_state *to_state(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct ths7303_state, sd);
+}
+
+static int ths7303_read(struct v4l2_subdev *sd, u8 reg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	return i2c_smbus_read_byte_data(client, reg);
+}
+
+static int ths7303_write(struct v4l2_subdev *sd, u8 reg, u8 val)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	int ret;
+	int i;
+
+	for (i = 0; i < 3; i++) {
+		ret = i2c_smbus_write_byte_data(client, reg, val);
+		if (ret == 0)
+			return 0;
+	}
+	return ret;
+}
+
 /* following function is used to set ths7303 */
 int ths7303_setval(struct v4l2_subdev *sd, enum ths7303_filter_mode mode)
 {
-	u8 input_bias_chroma = 3;
-	u8 input_bias_luma = 3;
-	int disable = 0;
-	int err = 0;
-	u8 val = 0;
-	u8 temp;
-
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct ths7303_state *state = to_state(sd);
+	struct ths7303_platform_data *pdata = &state->pdata;
+	u8 val, sel = 0;
+	int err, disable = 0;
 
 	if (!client)
 		return -EINVAL;
 
 	switch (mode) {
 	case THS7303_FILTER_MODE_1080P:
-		val = (3 << 6);
-		val |= (3 << 3);
+		sel = 0x3;	/*1080p and SXGA/UXGA */
 		break;
 	case THS7303_FILTER_MODE_720P_1080I:
-		val = (2 << 6);
-		val |= (2 << 3);
+		sel = 0x2;	/*720p, 1080i and SVGA/XGA */
 		break;
 	case THS7303_FILTER_MODE_480P_576P:
-		val = (1 << 6);
-		val |= (1 << 3);
+		sel = 0x1;	/* EDTV 480p/576p and VGA */
 		break;
 	case THS7303_FILTER_MODE_480I_576I:
+		sel = 0x0;	/* SDTV, S-Video, 480i/576i */
 		break;
-	case THS7303_FILTER_MODE_DISABLE:
-		pr_info("mode disabled\n");
-		/* disable all channels */
-		disable = 1;
 	default:
 		/* disable all channels */
 		disable = 1;
 	}
-	/* Setup channel 2 - Luma - Green */
-	temp = val;
+
+	val = (sel << 6) | (sel << 3);
 	if (!disable)
-		val |= input_bias_luma;
-	err = i2c_smbus_write_byte_data(client, THS7303_CHANNEL_2, val);
+		val |= (pdata->ch_1 & 0x27);
+	err = ths7303_write(sd, THS7303_CHANNEL_1, val);
 	if (err)
 		goto out;
 
-	/* setup two chroma channels */
+	val = (sel << 6) | (sel << 3);
 	if (!disable)
-		temp |= input_bias_chroma;
-
-	err = i2c_smbus_write_byte_data(client, THS7303_CHANNEL_1, temp);
+		val |= (pdata->ch_2 & 0x27);
+	err = ths7303_write(sd, THS7303_CHANNEL_2, val);
 	if (err)
 		goto out;
 
-	err = i2c_smbus_write_byte_data(client, THS7303_CHANNEL_3, temp);
+	val = (sel << 6) | (sel << 3);
+	if (!disable)
+		val |= (pdata->ch_3 & 0x27);
+	err = ths7303_write(sd, THS7303_CHANNEL_3, val);
 	if (err)
 		goto out;
-	return err;
+
+	return 0;
 out:
 	pr_info("write byte data failed\n");
 	return err;
@@ -113,49 +143,209 @@ out:
 
 static int ths7303_s_std_output(struct v4l2_subdev *sd, v4l2_std_id norm)
 {
-	if (norm & (V4L2_STD_ALL & ~V4L2_STD_SECAM))
+	struct ths7303_state *state = to_state(sd);
+
+	if (norm & (V4L2_STD_ALL & ~V4L2_STD_SECAM)) {
+		state->std_id = 1;
+		state->bt.pixelclock = 0;
 		return ths7303_setval(sd, THS7303_FILTER_MODE_480I_576I);
-	else
-		return ths7303_setval(sd, THS7303_FILTER_MODE_DISABLE);
+	}
+
+	return ths7303_setval(sd, THS7303_FILTER_MODE_DISABLE);
 }
 
-/* for setting filter for HD output */
-static int ths7303_s_dv_timings(struct v4l2_subdev *sd,
-			       struct v4l2_dv_timings *dv_timings)
+static int ths7303_config(struct v4l2_subdev *sd)
 {
-	u32 height = dv_timings->bt.height;
-	int interlaced = dv_timings->bt.interlaced;
-	int res = 0;
+	struct ths7303_state *state = to_state(sd);
+	int res;
+
+	if (!state->stream_on) {
+		ths7303_write(sd, THS7303_CHANNEL_1,
+			      (ths7303_read(sd, THS7303_CHANNEL_1) & 0xf8) |
+			      0x00);
+		ths7303_write(sd, THS7303_CHANNEL_2,
+			      (ths7303_read(sd, THS7303_CHANNEL_2) & 0xf8) |
+			      0x00);
+		ths7303_write(sd, THS7303_CHANNEL_3,
+			      (ths7303_read(sd, THS7303_CHANNEL_3) & 0xf8) |
+			      0x00);
+		return 0;
+	}
 
-	if (height == 1080 && !interlaced)
+	if (state->bt.pixelclock > 120000000)
 		res = ths7303_setval(sd, THS7303_FILTER_MODE_1080P);
-	else if ((height == 720 && !interlaced) ||
-			(height == 1080 && interlaced))
+	else if (state->bt.pixelclock > 70000000)
 		res = ths7303_setval(sd, THS7303_FILTER_MODE_720P_1080I);
-	else if ((height == 480 || height == 576) && !interlaced)
+	else if (state->bt.pixelclock > 20000000)
 		res = ths7303_setval(sd, THS7303_FILTER_MODE_480P_576P);
+	else if (state->std_id)
+		res = ths7303_setval(sd, THS7303_FILTER_MODE_480I_576I);
 	else
 		/* disable all channels */
 		res = ths7303_setval(sd, THS7303_FILTER_MODE_DISABLE);
 
 	return res;
+
+}
+
+static int ths7303_s_stream(struct v4l2_subdev *sd, int enable)
+{
+	struct ths7303_state *state = to_state(sd);
+
+	state->stream_on = enable;
+
+	return ths7303_config(sd);
+}
+
+/* for setting filter for HD output */
+static int ths7303_s_dv_timings(struct v4l2_subdev *sd,
+			       struct v4l2_dv_timings *dv_timings)
+{
+	struct ths7303_state *state = to_state(sd);
+
+	if (!dv_timings || dv_timings->type != V4L2_DV_BT_656_1120)
+		return -EINVAL;
+
+	state->bt = dv_timings->bt;
+	state->std_id = 0;
+
+	return ths7303_config(sd);
 }
 
 static int ths7303_g_chip_ident(struct v4l2_subdev *sd,
 				struct v4l2_dbg_chip_ident *chip)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct ths7303_state *state = to_state(sd);
 
-	return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_THS7303, 0);
+	return v4l2_chip_ident_i2c_client(client, chip, state->driver_data, 0);
 }
 
 static const struct v4l2_subdev_video_ops ths7303_video_ops = {
+	.s_stream	= ths7303_s_stream,
 	.s_std_output	= ths7303_s_std_output,
-	.s_dv_timings    = ths7303_s_dv_timings,
+	.s_dv_timings   = ths7303_s_dv_timings,
 };
 
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+
+static int ths7303_g_register(struct v4l2_subdev *sd,
+			      struct v4l2_dbg_register *reg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	if (!v4l2_chip_match_i2c_client(client, &reg->match))
+		return -EINVAL;
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	reg->size = 1;
+	reg->val = ths7303_read(sd, reg->reg);
+	return 0;
+}
+
+static int ths7303_s_register(struct v4l2_subdev *sd,
+			      const struct v4l2_dbg_register *reg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	if (!v4l2_chip_match_i2c_client(client, &reg->match))
+		return -EINVAL;
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	ths7303_write(sd, reg->reg, reg->val);
+	return 0;
+}
+#endif
+
+static const char * const stc_lpf_sel_txt[4] = {
+	"500-kHz Filter",
+	"2.5-MHz Filter",
+	"5-MHz Filter",
+	"5-MHz Filter",
+};
+
+static const char * const in_mux_sel_txt[2] = {
+	"Input A Select",
+	"Input B Select",
+};
+
+static const char * const lpf_freq_sel_txt[4] = {
+	"9-MHz LPF",
+	"16-MHz LPF",
+	"35-MHz LPF",
+	"Bypass LPF",
+};
+
+static const char * const in_bias_sel_dis_cont_txt[8] = {
+	"Disable Channel",
+	"Mute Function - No Output",
+	"DC Bias Select",
+	"DC Bias + 250 mV Offset Select",
+	"AC Bias Select",
+	"Sync Tip Clamp with low bias",
+	"Sync Tip Clamp with mid bias",
+	"Sync Tip Clamp with high bias",
+};
+
+static void ths7303_log_channel_status(struct v4l2_subdev *sd, u8 reg)
+{
+	u8 val = ths7303_read(sd, reg);
+
+	if ((val & 0x7) == 0) {
+		v4l2_info(sd, "Channel %d Off\n", reg);
+		return;
+	}
+
+	v4l2_info(sd, "Channel %d On\n", reg);
+	v4l2_info(sd, "  value 0x%x\n", val);
+	v4l2_info(sd, "  %s\n", stc_lpf_sel_txt[(val >> 6) & 0x3]);
+	v4l2_info(sd, "  %s\n", in_mux_sel_txt[(val >> 5) & 0x1]);
+	v4l2_info(sd, "  %s\n", lpf_freq_sel_txt[(val >> 3) & 0x3]);
+	v4l2_info(sd, "  %s\n", in_bias_sel_dis_cont_txt[(val >> 0) & 0x7]);
+}
+
+static int ths7303_log_status(struct v4l2_subdev *sd)
+{
+	struct ths7303_state *state = to_state(sd);
+
+	v4l2_info(sd, "stream %s\n", state->stream_on ? "On" : "Off");
+
+	if (state->bt.pixelclock) {
+		struct v4l2_bt_timings *bt = bt = &state->bt;
+		u32 frame_width, frame_height;
+
+		frame_width = bt->width + bt->hfrontporch +
+			      bt->hsync + bt->hbackporch;
+		frame_height = bt->height + bt->vfrontporch +
+			       bt->vsync + bt->vbackporch;
+		v4l2_info(sd,
+			  "timings: %dx%d%s%d (%dx%d). Pix freq. = %d Hz. Polarities = 0x%x\n",
+			  bt->width, bt->height, bt->interlaced ? "i" : "p",
+			  (frame_height * frame_width) > 0 ?
+			  (int)bt->pixelclock /
+			  (frame_height * frame_width) : 0,
+			  frame_width, frame_height,
+			  (int)bt->pixelclock, bt->polarities);
+	} else {
+		v4l2_info(sd, "no timings set\n");
+	}
+
+	ths7303_log_channel_status(sd, THS7303_CHANNEL_1);
+	ths7303_log_channel_status(sd, THS7303_CHANNEL_2);
+	ths7303_log_channel_status(sd, THS7303_CHANNEL_3);
+
+	return 0;
+}
+
 static const struct v4l2_subdev_core_ops ths7303_core_ops = {
 	.g_chip_ident = ths7303_g_chip_ident,
+	.log_status = ths7303_log_status,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.g_register = ths7303_g_register,
+	.s_register = ths7303_s_register,
+#endif
 };
 
 static const struct v4l2_subdev_ops ths7303_ops = {
@@ -163,11 +353,38 @@ static const struct v4l2_subdev_ops ths7303_ops = {
 	.video 	= &ths7303_video_ops,
 };
 
+static int ths7303_setup(struct v4l2_subdev *sd)
+{
+	struct ths7303_state *state = to_state(sd);
+	struct ths7303_platform_data *pdata = &state->pdata;
+	int ret;
+	u8 mask;
+
+	state->stream_on = pdata->init_enable;
+
+	mask = state->stream_on ? 0xff : 0xf8;
+
+	ret = ths7303_write(sd, THS7303_CHANNEL_1, pdata->ch_1 & mask);
+	if (ret)
+		return ret;
+
+	ret = ths7303_write(sd, THS7303_CHANNEL_2, pdata->ch_2 & mask);
+	if (ret)
+		return ret;
+
+	ret = ths7303_write(sd, THS7303_CHANNEL_3, pdata->ch_3 & mask);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
 static int ths7303_probe(struct i2c_client *client,
 			const struct i2c_device_id *id)
 {
+	struct ths7303_platform_data *pdata = client->dev.platform_data;
+	struct ths7303_state *state;
 	struct v4l2_subdev *sd;
-	v4l2_std_id std_id = V4L2_STD_NTSC;
 
 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 		return -ENODEV;
@@ -175,13 +392,28 @@ static int ths7303_probe(struct i2c_client *client,
 	v4l_info(client, "chip found @ 0x%x (%s)\n",
 			client->addr << 1, client->adapter->name);
 
-	sd = devm_kzalloc(&client->dev, sizeof(struct v4l2_subdev), GFP_KERNEL);
-	if (sd == NULL)
+	state = devm_kzalloc(&client->dev, sizeof(struct ths7303_state),
+			     GFP_KERNEL);
+	if (!state)
 		return -ENOMEM;
 
+	if (!pdata)
+		v4l_warn(client, "No platform data, using default data!\n");
+	else
+		state->pdata = *pdata;
+
+	sd = &state->sd;
 	v4l2_i2c_subdev_init(sd, client, &ths7303_ops);
 
-	return ths7303_s_std_output(sd, std_id);
+	/* store the driver data to differntiate the chip */
+	state->driver_data = (int)id->driver_data;
+
+	if (ths7303_setup(sd) < 0) {
+		v4l_err(client, "init failed\n");
+		return -EIO;
+	}
+
+	return 0;
 }
 
 static int ths7303_remove(struct i2c_client *client)
@@ -194,7 +426,8 @@ static int ths7303_remove(struct i2c_client *client)
 }
 
 static const struct i2c_device_id ths7303_id[] = {
-	{"ths7303", 0},
+	{"ths7303", V4L2_IDENT_THS7303},
+	{"ths7353", V4L2_IDENT_THS7353},
 	{},
 };
 
@@ -203,7 +436,7 @@ MODULE_DEVICE_TABLE(i2c, ths7303_id);
 static struct i2c_driver ths7303_driver = {
 	.driver = {
 		.owner	= THIS_MODULE,
-		.name	= "ths7303",
+		.name	= "ths73x3",
 	},
 	.probe		= ths7303_probe,
 	.remove		= ths7303_remove,
diff --git a/drivers/media/i2c/tvaudio.c b/drivers/media/i2c/tvaudio.c
index e3b33b7..b72a59d 100644
--- a/drivers/media/i2c/tvaudio.c
+++ b/drivers/media/i2c/tvaudio.c
@@ -1761,7 +1761,7 @@ static int tvaudio_s_routing(struct v4l2_subdev *sd,
 	return 0;
 }
 
-static int tvaudio_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
+static int tvaudio_s_tuner(struct v4l2_subdev *sd, const struct v4l2_tuner *vt)
 {
 	struct CHIPSTATE *chip = to_state(sd);
 	struct CHIPDESC *desc = chip->desc;
@@ -1803,7 +1803,7 @@ static int tvaudio_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
 
 	vt->audmode = chip->audmode;
 	vt->rxsubchans = desc->getrxsubchans(chip);
-	vt->capability = V4L2_TUNER_CAP_STEREO |
+	vt->capability |= V4L2_TUNER_CAP_STEREO |
 		V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2;
 
 	return 0;
@@ -1817,7 +1817,7 @@ static int tvaudio_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
 	return 0;
 }
 
-static int tvaudio_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *freq)
+static int tvaudio_s_frequency(struct v4l2_subdev *sd, const struct v4l2_frequency *freq)
 {
 	struct CHIPSTATE *chip = to_state(sd);
 	struct CHIPDESC *desc = chip->desc;
diff --git a/drivers/media/i2c/tvp514x.c b/drivers/media/i2c/tvp514x.c
index aa94ebc..ab8f3fe 100644
--- a/drivers/media/i2c/tvp514x.c
+++ b/drivers/media/i2c/tvp514x.c
@@ -12,6 +12,7 @@
  *     Hardik Shah <hardik.shah@ti.com>
  *     Manjunath Hadli <mrh@ti.com>
  *     Karicheri Muralidharan <m-karicheri2@ti.com>
+ *     Prabhakar Lad <prabhakar.lad@ti.com>
  *
  * This package is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -33,6 +34,7 @@
 #include <linux/delay.h>
 #include <linux/videodev2.h>
 #include <linux/module.h>
+#include <linux/v4l2-mediabus.h>
 
 #include <media/v4l2-device.h>
 #include <media/v4l2-common.h>
@@ -40,12 +42,10 @@
 #include <media/v4l2-chip-ident.h>
 #include <media/v4l2-ctrls.h>
 #include <media/tvp514x.h>
+#include <media/media-entity.h>
 
 #include "tvp514x_regs.h"
 
-/* Module Name */
-#define TVP514X_MODULE_NAME		"tvp514x"
-
 /* Private macros for TVP */
 #define I2C_RETRY_COUNT                 (5)
 #define LOCK_RETRY_COUNT                (5)
@@ -91,6 +91,9 @@ static int tvp514x_s_stream(struct v4l2_subdev *sd, int enable);
  * @pdata: Board specific
  * @ver: Chip version
  * @streaming: TVP5146/47 decoder streaming - enabled or disabled.
+ * @pix: Current pixel format
+ * @num_fmts: Number of formats
+ * @fmt_list: Format list
  * @current_std: Current standard
  * @num_stds: Number of standards
  * @std_list: Standards list
@@ -106,12 +109,20 @@ struct tvp514x_decoder {
 	int ver;
 	int streaming;
 
+	struct v4l2_pix_format pix;
+	int num_fmts;
+	const struct v4l2_fmtdesc *fmt_list;
+
 	enum tvp514x_std current_std;
 	int num_stds;
 	const struct tvp514x_std_info *std_list;
 	/* Input and Output Routing parameters */
 	u32 input;
 	u32 output;
+
+	/* mc related members */
+	struct media_pad pad;
+	struct v4l2_mbus_framefmt format;
 };
 
 /* TVP514x default register values */
@@ -200,6 +211,21 @@ static struct tvp514x_reg tvp514x_reg_list_default[] = {
 };
 
 /**
+ * List of image formats supported by TVP5146/47 decoder
+ * Currently we are using 8 bit mode only, but can be
+ * extended to 10/20 bit mode.
+ */
+static const struct v4l2_fmtdesc tvp514x_fmt_list[] = {
+	{
+	 .index		= 0,
+	 .type		= V4L2_BUF_TYPE_VIDEO_CAPTURE,
+	 .flags		= 0,
+	 .description	= "8-bit UYVY 4:2:2 Format",
+	 .pixelformat	= V4L2_PIX_FMT_UYVY,
+	},
+};
+
+/**
  * Supported standards -
  *
  * Currently supports two standards only, need to add support for rest of the
@@ -733,7 +759,7 @@ tvp514x_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index,
 }
 
 /**
- * tvp514x_mbus_fmt_cap() - V4L2 decoder interface handler for try/s/g_mbus_fmt
+ * tvp514x_mbus_fmt() - V4L2 decoder interface handler for try/s/g_mbus_fmt
  * @sd: pointer to standard V4L2 sub-device structure
  * @f: pointer to the mediabus format structure
  *
@@ -751,12 +777,11 @@ tvp514x_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f)
 	/* Calculate height and width based on current standard */
 	current_std = decoder->current_std;
 
-	f->code = V4L2_MBUS_FMT_YUYV10_2X10;
+	f->code = V4L2_MBUS_FMT_YUYV8_2X8;
 	f->width = decoder->std_list[current_std].width;
 	f->height = decoder->std_list[current_std].height;
 	f->field = V4L2_FIELD_INTERLACED;
 	f->colorspace = V4L2_COLORSPACE_SMPTE170M;
-
 	v4l2_dbg(1, debug, sd, "MBUS_FMT: Width - %d, Height - %d\n",
 			f->width, f->height);
 	return 0;
@@ -892,6 +917,88 @@ static const struct v4l2_ctrl_ops tvp514x_ctrl_ops = {
 	.s_ctrl = tvp514x_s_ctrl,
 };
 
+/**
+ * tvp514x_enum_mbus_code() - V4L2 decoder interface handler for enum_mbus_code
+ * @sd: pointer to standard V4L2 sub-device structure
+ * @fh: file handle
+ * @code: pointer to v4l2_subdev_mbus_code_enum structure
+ *
+ * Enumertaes mbus codes supported
+ */
+static int tvp514x_enum_mbus_code(struct v4l2_subdev *sd,
+				  struct v4l2_subdev_fh *fh,
+				  struct v4l2_subdev_mbus_code_enum *code)
+{
+	u32 pad = code->pad;
+	u32 index = code->index;
+
+	memset(code, 0, sizeof(*code));
+	code->index = index;
+	code->pad = pad;
+
+	if (index != 0)
+		return -EINVAL;
+
+	code->code = V4L2_MBUS_FMT_YUYV8_2X8;
+
+	return 0;
+}
+
+/**
+ * tvp514x_get_pad_format() - V4L2 decoder interface handler for get pad format
+ * @sd: pointer to standard V4L2 sub-device structure
+ * @fh: file handle
+ * @format: pointer to v4l2_subdev_format structure
+ *
+ * Retrieves pad format which is active or tried based on requirement
+ */
+static int tvp514x_get_pad_format(struct v4l2_subdev *sd,
+				  struct v4l2_subdev_fh *fh,
+				  struct v4l2_subdev_format *format)
+{
+	struct tvp514x_decoder *decoder = to_decoder(sd);
+	__u32 which = format->which;
+
+	if (which == V4L2_SUBDEV_FORMAT_ACTIVE) {
+		format->format = decoder->format;
+		return 0;
+	}
+
+	format->format.code = V4L2_MBUS_FMT_YUYV8_2X8;
+	format->format.width = tvp514x_std_list[decoder->current_std].width;
+	format->format.height = tvp514x_std_list[decoder->current_std].height;
+	format->format.colorspace = V4L2_COLORSPACE_SMPTE170M;
+	format->format.field = V4L2_FIELD_INTERLACED;
+
+	return 0;
+}
+
+/**
+ * tvp514x_set_pad_format() - V4L2 decoder interface handler for set pad format
+ * @sd: pointer to standard V4L2 sub-device structure
+ * @fh: file handle
+ * @format: pointer to v4l2_subdev_format structure
+ *
+ * Set pad format for the output pad
+ */
+static int tvp514x_set_pad_format(struct v4l2_subdev *sd,
+				  struct v4l2_subdev_fh *fh,
+				  struct v4l2_subdev_format *fmt)
+{
+	struct tvp514x_decoder *decoder = to_decoder(sd);
+
+	if (fmt->format.field != V4L2_FIELD_INTERLACED ||
+	    fmt->format.code != V4L2_MBUS_FMT_YUYV8_2X8 ||
+	    fmt->format.colorspace != V4L2_COLORSPACE_SMPTE170M ||
+	    fmt->format.width != tvp514x_std_list[decoder->current_std].width ||
+	    fmt->format.height != tvp514x_std_list[decoder->current_std].height)
+		return -EINVAL;
+
+	decoder->format = fmt->format;
+
+	return 0;
+}
+
 static const struct v4l2_subdev_core_ops tvp514x_core_ops = {
 	.g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
 	.try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
@@ -915,13 +1022,33 @@ static const struct v4l2_subdev_video_ops tvp514x_video_ops = {
 	.s_stream = tvp514x_s_stream,
 };
 
+static const struct v4l2_subdev_pad_ops tvp514x_pad_ops = {
+	.enum_mbus_code = tvp514x_enum_mbus_code,
+	.get_fmt = tvp514x_get_pad_format,
+	.set_fmt = tvp514x_set_pad_format,
+};
+
 static const struct v4l2_subdev_ops tvp514x_ops = {
 	.core = &tvp514x_core_ops,
 	.video = &tvp514x_video_ops,
+	.pad = &tvp514x_pad_ops,
 };
 
 static struct tvp514x_decoder tvp514x_dev = {
 	.streaming = 0,
+	.fmt_list = tvp514x_fmt_list,
+	.num_fmts = ARRAY_SIZE(tvp514x_fmt_list),
+	.pix = {
+		/* Default to NTSC 8-bit YUV 422 */
+		.width		= NTSC_NUM_ACTIVE_PIXELS,
+		.height		= NTSC_NUM_ACTIVE_LINES,
+		.pixelformat	= V4L2_PIX_FMT_UYVY,
+		.field		= V4L2_FIELD_INTERLACED,
+		.bytesperline	= NTSC_NUM_ACTIVE_PIXELS * 2,
+		.sizeimage	= NTSC_NUM_ACTIVE_PIXELS * 2 *
+					NTSC_NUM_ACTIVE_LINES,
+		.colorspace	= V4L2_COLORSPACE_SMPTE170M,
+		},
 	.current_std = STD_NTSC_MJ,
 	.std_list = tvp514x_std_list,
 	.num_stds = ARRAY_SIZE(tvp514x_std_list),
@@ -941,6 +1068,7 @@ tvp514x_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
 	struct tvp514x_decoder *decoder;
 	struct v4l2_subdev *sd;
+	int ret;
 
 	/* Check if the adapter supports the needed features */
 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
@@ -981,7 +1109,21 @@ tvp514x_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	/* Register with V4L2 layer as slave device */
 	sd = &decoder->sd;
 	v4l2_i2c_subdev_init(sd, client, &tvp514x_ops);
-
+	strlcpy(sd->name, TVP514X_MODULE_NAME, sizeof(sd->name));
+
+#if defined(CONFIG_MEDIA_CONTROLLER)
+	decoder->pad.flags = MEDIA_PAD_FL_SOURCE;
+	decoder->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+	decoder->sd.entity.flags |= MEDIA_ENT_T_V4L2_SUBDEV_DECODER;
+
+	ret = media_entity_init(&decoder->sd.entity, 1, &decoder->pad, 0);
+	if (ret < 0) {
+		v4l2_err(sd, "%s decoder driver failed to register !!\n",
+			 sd->name);
+		kfree(decoder);
+		return ret;
+	}
+#endif
 	v4l2_ctrl_handler_init(&decoder->hdl, 5);
 	v4l2_ctrl_new_std(&decoder->hdl, &tvp514x_ctrl_ops,
 		V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
@@ -995,10 +1137,10 @@ tvp514x_probe(struct i2c_client *client, const struct i2c_device_id *id)
 		V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
 	sd->ctrl_handler = &decoder->hdl;
 	if (decoder->hdl.error) {
-		int err = decoder->hdl.error;
+		ret = decoder->hdl.error;
 
 		v4l2_ctrl_handler_free(&decoder->hdl);
-		return err;
+		return ret;
 	}
 	v4l2_ctrl_handler_setup(&decoder->hdl);
 
@@ -1021,6 +1163,9 @@ static int tvp514x_remove(struct i2c_client *client)
 	struct tvp514x_decoder *decoder = to_decoder(sd);
 
 	v4l2_device_unregister_subdev(sd);
+#if defined(CONFIG_MEDIA_CONTROLLER)
+	media_entity_cleanup(&decoder->sd.entity);
+#endif
 	v4l2_ctrl_handler_free(&decoder->hdl);
 	return 0;
 }
diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
index 5967e1a0..485159a 100644
--- a/drivers/media/i2c/tvp5150.c
+++ b/drivers/media/i2c/tvp5150.c
@@ -1067,7 +1067,7 @@ static int tvp5150_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *
 	return 0;
 }
 
-static int tvp5150_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
+static int tvp5150_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 
diff --git a/drivers/media/i2c/tvp7002.c b/drivers/media/i2c/tvp7002.c
index 537f6b4..027809c 100644
--- a/drivers/media/i2c/tvp7002.c
+++ b/drivers/media/i2c/tvp7002.c
@@ -326,9 +326,8 @@ static const struct i2c_reg_value tvp7002_parms_720P50[] = {
 	{ TVP7002_EOR, 0xff, TVP7002_RESERVED }
 };
 
-/* Preset definition for handling device operation */
-struct tvp7002_preset_definition {
-	u32 preset;
+/* Timings definition for handling device operation */
+struct tvp7002_timings_definition {
 	struct v4l2_dv_timings timings;
 	const struct i2c_reg_value *p_settings;
 	enum v4l2_colorspace color_space;
@@ -339,10 +338,9 @@ struct tvp7002_preset_definition {
 	u16 cpl_max;
 };
 
-/* Struct list for digital video presets */
-static const struct tvp7002_preset_definition tvp7002_presets[] = {
+/* Struct list for digital video timings */
+static const struct tvp7002_timings_definition tvp7002_timings[] = {
 	{
-		V4L2_DV_720P60,
 		V4L2_DV_BT_CEA_1280X720P60,
 		tvp7002_parms_720P60,
 		V4L2_COLORSPACE_REC709,
@@ -353,7 +351,6 @@ static const struct tvp7002_preset_definition tvp7002_presets[] = {
 		153
 	},
 	{
-		V4L2_DV_1080I60,
 		V4L2_DV_BT_CEA_1920X1080I60,
 		tvp7002_parms_1080I60,
 		V4L2_COLORSPACE_REC709,
@@ -364,7 +361,6 @@ static const struct tvp7002_preset_definition tvp7002_presets[] = {
 		205
 	},
 	{
-		V4L2_DV_1080I50,
 		V4L2_DV_BT_CEA_1920X1080I50,
 		tvp7002_parms_1080I50,
 		V4L2_COLORSPACE_REC709,
@@ -375,7 +371,6 @@ static const struct tvp7002_preset_definition tvp7002_presets[] = {
 		245
 	},
 	{
-		V4L2_DV_720P50,
 		V4L2_DV_BT_CEA_1280X720P50,
 		tvp7002_parms_720P50,
 		V4L2_COLORSPACE_REC709,
@@ -386,7 +381,6 @@ static const struct tvp7002_preset_definition tvp7002_presets[] = {
 		183
 	},
 	{
-		V4L2_DV_1080P60,
 		V4L2_DV_BT_CEA_1920X1080P60,
 		tvp7002_parms_1080P60,
 		V4L2_COLORSPACE_REC709,
@@ -397,7 +391,6 @@ static const struct tvp7002_preset_definition tvp7002_presets[] = {
 		102
 	},
 	{
-		V4L2_DV_480P59_94,
 		V4L2_DV_BT_CEA_720X480P59_94,
 		tvp7002_parms_480P,
 		V4L2_COLORSPACE_SMPTE170M,
@@ -408,7 +401,6 @@ static const struct tvp7002_preset_definition tvp7002_presets[] = {
 		0xffff
 	},
 	{
-		V4L2_DV_576P50,
 		V4L2_DV_BT_CEA_720X576P50,
 		tvp7002_parms_576P,
 		V4L2_COLORSPACE_SMPTE170M,
@@ -420,7 +412,7 @@ static const struct tvp7002_preset_definition tvp7002_presets[] = {
 	}
 };
 
-#define NUM_PRESETS	ARRAY_SIZE(tvp7002_presets)
+#define NUM_TIMINGS ARRAY_SIZE(tvp7002_timings)
 
 /* Device definition */
 struct tvp7002 {
@@ -431,7 +423,7 @@ struct tvp7002 {
 	int ver;
 	int streaming;
 
-	const struct tvp7002_preset_definition *current_preset;
+	const struct tvp7002_timings_definition *current_timings;
 };
 
 /*
@@ -588,32 +580,6 @@ static int tvp7002_write_inittab(struct v4l2_subdev *sd,
 	return error;
 }
 
-/*
- * tvp7002_s_dv_preset() - Set digital video preset
- * @sd: ptr to v4l2_subdev struct
- * @dv_preset: ptr to v4l2_dv_preset struct
- *
- * Set the digital video preset for a TVP7002 decoder device.
- * Returns zero when successful or -EINVAL if register access fails.
- */
-static int tvp7002_s_dv_preset(struct v4l2_subdev *sd,
-					struct v4l2_dv_preset *dv_preset)
-{
-	struct tvp7002 *device = to_tvp7002(sd);
-	u32 preset;
-	int i;
-
-	for (i = 0; i < NUM_PRESETS; i++) {
-		preset = tvp7002_presets[i].preset;
-		if (preset == dv_preset->preset) {
-			device->current_preset = &tvp7002_presets[i];
-			return tvp7002_write_inittab(sd, tvp7002_presets[i].p_settings);
-		}
-	}
-
-	return -EINVAL;
-}
-
 static int tvp7002_s_dv_timings(struct v4l2_subdev *sd,
 					struct v4l2_dv_timings *dv_timings)
 {
@@ -623,12 +589,12 @@ static int tvp7002_s_dv_timings(struct v4l2_subdev *sd,
 
 	if (dv_timings->type != V4L2_DV_BT_656_1120)
 		return -EINVAL;
-	for (i = 0; i < NUM_PRESETS; i++) {
-		const struct v4l2_bt_timings *t = &tvp7002_presets[i].timings.bt;
+	for (i = 0; i < NUM_TIMINGS; i++) {
+		const struct v4l2_bt_timings *t = &tvp7002_timings[i].timings.bt;
 
 		if (!memcmp(bt, t, &bt->standards - &bt->width)) {
-			device->current_preset = &tvp7002_presets[i];
-			return tvp7002_write_inittab(sd, tvp7002_presets[i].p_settings);
+			device->current_timings = &tvp7002_timings[i];
+			return tvp7002_write_inittab(sd, tvp7002_timings[i].p_settings);
 		}
 	}
 	return -EINVAL;
@@ -639,7 +605,7 @@ static int tvp7002_g_dv_timings(struct v4l2_subdev *sd,
 {
 	struct tvp7002 *device = to_tvp7002(sd);
 
-	*dv_timings = device->current_preset->timings;
+	*dv_timings = device->current_timings->timings;
 	return 0;
 }
 
@@ -677,19 +643,13 @@ static int tvp7002_s_ctrl(struct v4l2_ctrl *ctrl)
 static int tvp7002_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f)
 {
 	struct tvp7002 *device = to_tvp7002(sd);
-	struct v4l2_dv_enum_preset e_preset;
-	int error;
+	const struct v4l2_bt_timings *bt = &device->current_timings->timings.bt;
 
-	/* Calculate height and width based on current standard */
-	error = v4l_fill_dv_preset_info(device->current_preset->preset, &e_preset);
-	if (error)
-		return error;
-
-	f->width = e_preset.width;
-	f->height = e_preset.height;
+	f->width = bt->width;
+	f->height = bt->height;
 	f->code = V4L2_MBUS_FMT_YUYV10_1X20;
-	f->field = device->current_preset->scanmode;
-	f->colorspace = device->current_preset->color_space;
+	f->field = device->current_timings->scanmode;
+	f->colorspace = device->current_timings->color_space;
 
 	v4l2_dbg(1, debug, sd, "MBUS_FMT: Width - %d, Height - %d",
 			f->width, f->height);
@@ -697,16 +657,16 @@ static int tvp7002_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f
 }
 
 /*
- * tvp7002_query_dv_preset() - query DV preset
+ * tvp7002_query_dv() - query DV timings
  * @sd: pointer to standard V4L2 sub-device structure
- * @qpreset: standard V4L2 v4l2_dv_preset structure
+ * @index: index into the tvp7002_timings array
  *
- * Returns the current DV preset by TVP7002. If no active input is
+ * Returns the current DV timings detected by TVP7002. If no active input is
  * detected, returns -EINVAL
  */
 static int tvp7002_query_dv(struct v4l2_subdev *sd, int *index)
 {
-	const struct tvp7002_preset_definition *presets = tvp7002_presets;
+	const struct tvp7002_timings_definition *timings = tvp7002_timings;
 	u8 progressive;
 	u32 lpfr;
 	u32 cpln;
@@ -717,7 +677,7 @@ static int tvp7002_query_dv(struct v4l2_subdev *sd, int *index)
 	u8 cpl_msb;
 
 	/* Return invalid index if no active input is detected */
-	*index = NUM_PRESETS;
+	*index = NUM_TIMINGS;
 
 	/* Read standards from device registers */
 	tvp7002_read_err(sd, TVP7002_L_FRAME_STAT_LSBS, &lpf_lsb, &error);
@@ -738,39 +698,23 @@ static int tvp7002_query_dv(struct v4l2_subdev *sd, int *index)
 	progressive = (lpf_msb & TVP7002_INPR_MASK) >> TVP7002_IP_SHIFT;
 
 	/* Do checking of video modes */
-	for (*index = 0; *index < NUM_PRESETS; (*index)++, presets++)
-		if (lpfr == presets->lines_per_frame &&
-			progressive == presets->progressive) {
-			if (presets->cpl_min == 0xffff)
+	for (*index = 0; *index < NUM_TIMINGS; (*index)++, timings++)
+		if (lpfr == timings->lines_per_frame &&
+			progressive == timings->progressive) {
+			if (timings->cpl_min == 0xffff)
 				break;
-			if (cpln >= presets->cpl_min && cpln <= presets->cpl_max)
+			if (cpln >= timings->cpl_min && cpln <= timings->cpl_max)
 				break;
 		}
 
-	if (*index == NUM_PRESETS) {
+	if (*index == NUM_TIMINGS) {
 		v4l2_dbg(1, debug, sd, "detection failed: lpf = %x, cpl = %x\n",
 								lpfr, cpln);
 		return -ENOLINK;
 	}
 
 	/* Update lines per frame and clocks per line info */
-	v4l2_dbg(1, debug, sd, "detected preset: %d\n", *index);
-	return 0;
-}
-
-static int tvp7002_query_dv_preset(struct v4l2_subdev *sd,
-					struct v4l2_dv_preset *qpreset)
-{
-	int index;
-	int err = tvp7002_query_dv(sd, &index);
-
-	if (err || index == NUM_PRESETS) {
-		qpreset->preset = V4L2_DV_INVALID;
-		if (err == -ENOLINK)
-			err = 0;
-		return err;
-	}
-	qpreset->preset = tvp7002_presets[index].preset;
+	v4l2_dbg(1, debug, sd, "detected timings: %d\n", *index);
 	return 0;
 }
 
@@ -782,7 +726,7 @@ static int tvp7002_query_dv_timings(struct v4l2_subdev *sd,
 
 	if (err)
 		return err;
-	*timings = tvp7002_presets[index].timings;
+	*timings = tvp7002_timings[index].timings;
 	return 0;
 }
 
@@ -824,7 +768,7 @@ static int tvp7002_g_register(struct v4l2_subdev *sd,
  * -EPERM if call not allowed.
  */
 static int tvp7002_s_register(struct v4l2_subdev *sd,
-						struct v4l2_dbg_register *reg)
+						const struct v4l2_dbg_register *reg)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 
@@ -896,35 +840,21 @@ static int tvp7002_s_stream(struct v4l2_subdev *sd, int enable)
  */
 static int tvp7002_log_status(struct v4l2_subdev *sd)
 {
-	const struct tvp7002_preset_definition *presets = tvp7002_presets;
 	struct tvp7002 *device = to_tvp7002(sd);
-	struct v4l2_dv_enum_preset e_preset;
-	struct v4l2_dv_preset detected;
-	int i;
-
-	detected.preset = V4L2_DV_INVALID;
-	/* Find my current standard*/
-	tvp7002_query_dv_preset(sd, &detected);
+	const struct v4l2_bt_timings *bt;
+	int detected;
 
-	/* Print standard related code values */
-	for (i = 0; i < NUM_PRESETS; i++, presets++)
-		if (presets->preset == detected.preset)
-			break;
+	/* Find my current timings */
+	tvp7002_query_dv(sd, &detected);
 
-	if (v4l_fill_dv_preset_info(device->current_preset->preset, &e_preset))
-		return -EINVAL;
-
-	v4l2_info(sd, "Selected DV Preset: %s\n", e_preset.name);
-	v4l2_info(sd, "   Pixels per line: %u\n", e_preset.width);
-	v4l2_info(sd, "   Lines per frame: %u\n\n", e_preset.height);
-	if (i == NUM_PRESETS) {
-		v4l2_info(sd, "Detected DV Preset: None\n");
+	bt = &device->current_timings->timings.bt;
+	v4l2_info(sd, "Selected DV Timings: %ux%u\n", bt->width, bt->height);
+	if (detected == NUM_TIMINGS) {
+		v4l2_info(sd, "Detected DV Timings: None\n");
 	} else {
-		if (v4l_fill_dv_preset_info(presets->preset, &e_preset))
-			return -EINVAL;
-		v4l2_info(sd, "Detected DV Preset: %s\n", e_preset.name);
-		v4l2_info(sd, "  Pixels per line: %u\n", e_preset.width);
-		v4l2_info(sd, "  Lines per frame: %u\n\n", e_preset.height);
+		bt = &tvp7002_timings[detected].timings.bt;
+		v4l2_info(sd, "Detected DV Timings: %ux%u\n",
+				bt->width, bt->height);
 	}
 	v4l2_info(sd, "Streaming enabled: %s\n",
 					device->streaming ? "yes" : "no");
@@ -935,31 +865,14 @@ static int tvp7002_log_status(struct v4l2_subdev *sd)
 	return 0;
 }
 
-/*
- * tvp7002_enum_dv_presets() - Enum supported digital video formats
- * @sd: pointer to standard V4L2 sub-device structure
- * @preset: pointer to format struct
- *
- * Enumerate supported digital video formats.
- */
-static int tvp7002_enum_dv_presets(struct v4l2_subdev *sd,
-		struct v4l2_dv_enum_preset *preset)
-{
-	/* Check requested format index is within range */
-	if (preset->index >= NUM_PRESETS)
-		return -EINVAL;
-
-	return v4l_fill_dv_preset_info(tvp7002_presets[preset->index].preset, preset);
-}
-
 static int tvp7002_enum_dv_timings(struct v4l2_subdev *sd,
 		struct v4l2_enum_dv_timings *timings)
 {
 	/* Check requested format index is within range */
-	if (timings->index >= NUM_PRESETS)
+	if (timings->index >= NUM_TIMINGS)
 		return -EINVAL;
 
-	timings->timings = tvp7002_presets[timings->index].timings;
+	timings->timings = tvp7002_timings[timings->index].timings;
 	return 0;
 }
 
@@ -986,9 +899,6 @@ static const struct v4l2_subdev_core_ops tvp7002_core_ops = {
 
 /* Specific video subsystem operation handlers */
 static const struct v4l2_subdev_video_ops tvp7002_video_ops = {
-	.enum_dv_presets = tvp7002_enum_dv_presets,
-	.s_dv_preset = tvp7002_s_dv_preset,
-	.query_dv_preset = tvp7002_query_dv_preset,
 	.g_dv_timings = tvp7002_g_dv_timings,
 	.s_dv_timings = tvp7002_s_dv_timings,
 	.enum_dv_timings = tvp7002_enum_dv_timings,
@@ -1019,7 +929,7 @@ static int tvp7002_probe(struct i2c_client *c, const struct i2c_device_id *id)
 {
 	struct v4l2_subdev *sd;
 	struct tvp7002 *device;
-	struct v4l2_dv_preset preset;
+	struct v4l2_dv_timings timings;
 	int polarity_a;
 	int polarity_b;
 	u8 revision;
@@ -1043,7 +953,7 @@ static int tvp7002_probe(struct i2c_client *c, const struct i2c_device_id *id)
 
 	sd = &device->sd;
 	device->pdata = c->dev.platform_data;
-	device->current_preset = tvp7002_presets;
+	device->current_timings = tvp7002_timings;
 
 	/* Tell v4l2 the device is ready */
 	v4l2_i2c_subdev_init(sd, c, &tvp7002_ops);
@@ -1080,8 +990,8 @@ static int tvp7002_probe(struct i2c_client *c, const struct i2c_device_id *id)
 		return error;
 
 	/* Set registers according to default video mode */
-	preset.preset = device->current_preset->preset;
-	error = tvp7002_s_dv_preset(sd, &preset);
+	timings = device->current_timings->timings;
+	error = tvp7002_s_dv_timings(sd, &timings);
 
 	v4l2_ctrl_handler_init(&device->hdl, 1);
 	v4l2_ctrl_new_std(&device->hdl, &tvp7002_ctrl_ops,
diff --git a/drivers/media/i2c/tw2804.c b/drivers/media/i2c/tw2804.c
new file mode 100644
index 0000000..c5dc2c3
--- /dev/null
+++ b/drivers/media/i2c/tw2804.c
@@ -0,0 +1,453 @@
+/*
+ * Copyright (C) 2005-2006 Micronas USA 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., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/videodev2.h>
+#include <linux/ioctl.h>
+#include <linux/slab.h>
+#include <media/v4l2-subdev.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-ctrls.h>
+
+#define TW2804_REG_AUTOGAIN		0x02
+#define TW2804_REG_HUE			0x0f
+#define TW2804_REG_SATURATION		0x10
+#define TW2804_REG_CONTRAST		0x11
+#define TW2804_REG_BRIGHTNESS		0x12
+#define TW2804_REG_COLOR_KILLER		0x14
+#define TW2804_REG_GAIN			0x3c
+#define TW2804_REG_CHROMA_GAIN		0x3d
+#define TW2804_REG_BLUE_BALANCE		0x3e
+#define TW2804_REG_RED_BALANCE		0x3f
+
+struct tw2804 {
+	struct v4l2_subdev sd;
+	struct v4l2_ctrl_handler hdl;
+	u8 channel:2;
+	u8 input:1;
+	int norm;
+};
+
+static const u8 global_registers[] = {
+	0x39, 0x00,
+	0x3a, 0xff,
+	0x3b, 0x84,
+	0x3c, 0x80,
+	0x3d, 0x80,
+	0x3e, 0x82,
+	0x3f, 0x82,
+	0x78, 0x00,
+	0xff, 0xff, /* Terminator (reg 0xff does not exist) */
+};
+
+static const u8 channel_registers[] = {
+	0x01, 0xc4,
+	0x02, 0xa5,
+	0x03, 0x20,
+	0x04, 0xd0,
+	0x05, 0x20,
+	0x06, 0xd0,
+	0x07, 0x88,
+	0x08, 0x20,
+	0x09, 0x07,
+	0x0a, 0xf0,
+	0x0b, 0x07,
+	0x0c, 0xf0,
+	0x0d, 0x40,
+	0x0e, 0xd2,
+	0x0f, 0x80,
+	0x10, 0x80,
+	0x11, 0x80,
+	0x12, 0x80,
+	0x13, 0x1f,
+	0x14, 0x00,
+	0x15, 0x00,
+	0x16, 0x00,
+	0x17, 0x00,
+	0x18, 0xff,
+	0x19, 0xff,
+	0x1a, 0xff,
+	0x1b, 0xff,
+	0x1c, 0xff,
+	0x1d, 0xff,
+	0x1e, 0xff,
+	0x1f, 0xff,
+	0x20, 0x07,
+	0x21, 0x07,
+	0x22, 0x00,
+	0x23, 0x91,
+	0x24, 0x51,
+	0x25, 0x03,
+	0x26, 0x00,
+	0x27, 0x00,
+	0x28, 0x00,
+	0x29, 0x00,
+	0x2a, 0x00,
+	0x2b, 0x00,
+	0x2c, 0x00,
+	0x2d, 0x00,
+	0x2e, 0x00,
+	0x2f, 0x00,
+	0x30, 0x00,
+	0x31, 0x00,
+	0x32, 0x00,
+	0x33, 0x00,
+	0x34, 0x00,
+	0x35, 0x00,
+	0x36, 0x00,
+	0x37, 0x00,
+	0xff, 0xff, /* Terminator (reg 0xff does not exist) */
+};
+
+static int write_reg(struct i2c_client *client, u8 reg, u8 value, u8 channel)
+{
+	return i2c_smbus_write_byte_data(client, reg | (channel << 6), value);
+}
+
+static int write_regs(struct i2c_client *client, const u8 *regs, u8 channel)
+{
+	int ret;
+	int i;
+
+	for (i = 0; regs[i] != 0xff; i += 2) {
+		ret = i2c_smbus_write_byte_data(client,
+				regs[i] | (channel << 6), regs[i + 1]);
+		if (ret < 0)
+			return ret;
+	}
+	return 0;
+}
+
+static int read_reg(struct i2c_client *client, u8 reg, u8 channel)
+{
+	return i2c_smbus_read_byte_data(client, (reg) | (channel << 6));
+}
+
+static inline struct tw2804 *to_state(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct tw2804, sd);
+}
+
+static inline struct tw2804 *to_state_from_ctrl(struct v4l2_ctrl *ctrl)
+{
+	return container_of(ctrl->handler, struct tw2804, hdl);
+}
+
+static int tw2804_log_status(struct v4l2_subdev *sd)
+{
+	struct tw2804 *state = to_state(sd);
+
+	v4l2_info(sd, "Standard: %s\n",
+			state->norm & V4L2_STD_525_60 ? "60 Hz" : "50 Hz");
+	v4l2_info(sd, "Channel: %d\n", state->channel);
+	v4l2_info(sd, "Input: %d\n", state->input);
+	return v4l2_ctrl_subdev_log_status(sd);
+}
+
+/*
+ * These volatile controls are needed because all four channels share
+ * these controls. So a change made to them through one channel would
+ * require another channel to be updated.
+ *
+ * Normally this would have been done in a different way, but since the one
+ * board that uses this driver sees this single chip as if it was on four
+ * different i2c adapters (each adapter belonging to a separate instance of
+ * the same USB driver) there is no reliable method that I have found to let
+ * the instances know about each other.
+ *
+ * So implementing these global registers as volatile is the best we can do.
+ */
+static int tw2804_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct tw2804 *state = to_state_from_ctrl(ctrl);
+	struct i2c_client *client = v4l2_get_subdevdata(&state->sd);
+
+	switch (ctrl->id) {
+	case V4L2_CID_GAIN:
+		ctrl->val = read_reg(client, TW2804_REG_GAIN, 0);
+		return 0;
+
+	case V4L2_CID_CHROMA_GAIN:
+		ctrl->val = read_reg(client, TW2804_REG_CHROMA_GAIN, 0);
+		return 0;
+
+	case V4L2_CID_BLUE_BALANCE:
+		ctrl->val = read_reg(client, TW2804_REG_BLUE_BALANCE, 0);
+		return 0;
+
+	case V4L2_CID_RED_BALANCE:
+		ctrl->val = read_reg(client, TW2804_REG_RED_BALANCE, 0);
+		return 0;
+	}
+	return 0;
+}
+
+static int tw2804_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct tw2804 *state = to_state_from_ctrl(ctrl);
+	struct i2c_client *client = v4l2_get_subdevdata(&state->sd);
+	int addr;
+	int reg;
+
+	switch (ctrl->id) {
+	case V4L2_CID_AUTOGAIN:
+		addr = TW2804_REG_AUTOGAIN;
+		reg = read_reg(client, addr, state->channel);
+		if (reg < 0)
+			return reg;
+		if (ctrl->val == 0)
+			reg &= ~(1 << 7);
+		else
+			reg |= 1 << 7;
+		return write_reg(client, addr, reg, state->channel);
+
+	case V4L2_CID_COLOR_KILLER:
+		addr = TW2804_REG_COLOR_KILLER;
+		reg = read_reg(client, addr, state->channel);
+		if (reg < 0)
+			return reg;
+		reg = (reg & ~(0x03)) | (ctrl->val == 0 ? 0x02 : 0x03);
+		return write_reg(client, addr, reg, state->channel);
+
+	case V4L2_CID_GAIN:
+		return write_reg(client, TW2804_REG_GAIN, ctrl->val, 0);
+
+	case V4L2_CID_CHROMA_GAIN:
+		return write_reg(client, TW2804_REG_CHROMA_GAIN, ctrl->val, 0);
+
+	case V4L2_CID_BLUE_BALANCE:
+		return write_reg(client, TW2804_REG_BLUE_BALANCE, ctrl->val, 0);
+
+	case V4L2_CID_RED_BALANCE:
+		return write_reg(client, TW2804_REG_RED_BALANCE, ctrl->val, 0);
+
+	case V4L2_CID_BRIGHTNESS:
+		return write_reg(client, TW2804_REG_BRIGHTNESS,
+				ctrl->val, state->channel);
+
+	case V4L2_CID_CONTRAST:
+		return write_reg(client, TW2804_REG_CONTRAST,
+				ctrl->val, state->channel);
+
+	case V4L2_CID_SATURATION:
+		return write_reg(client, TW2804_REG_SATURATION,
+				ctrl->val, state->channel);
+
+	case V4L2_CID_HUE:
+		return write_reg(client, TW2804_REG_HUE,
+				ctrl->val, state->channel);
+
+	default:
+		break;
+	}
+	return -EINVAL;
+}
+
+static int tw2804_s_std(struct v4l2_subdev *sd, v4l2_std_id norm)
+{
+	struct tw2804 *dec = to_state(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	bool is_60hz = norm & V4L2_STD_525_60;
+	u8 regs[] = {
+		0x01, is_60hz ? 0xc4 : 0x84,
+		0x09, is_60hz ? 0x07 : 0x04,
+		0x0a, is_60hz ? 0xf0 : 0x20,
+		0x0b, is_60hz ? 0x07 : 0x04,
+		0x0c, is_60hz ? 0xf0 : 0x20,
+		0x0d, is_60hz ? 0x40 : 0x4a,
+		0x16, is_60hz ? 0x00 : 0x40,
+		0x17, is_60hz ? 0x00 : 0x40,
+		0x20, is_60hz ? 0x07 : 0x0f,
+		0x21, is_60hz ? 0x07 : 0x0f,
+		0xff, 0xff,
+	};
+
+	write_regs(client, regs, dec->channel);
+	dec->norm = norm;
+	return 0;
+}
+
+static int tw2804_s_video_routing(struct v4l2_subdev *sd, u32 input, u32 output,
+	u32 config)
+{
+	struct tw2804 *dec = to_state(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	int reg;
+
+	if (config && config - 1 != dec->channel) {
+		if (config > 4) {
+			dev_err(&client->dev,
+				"channel %d is not between 1 and 4!\n", config);
+			return -EINVAL;
+		}
+		dec->channel = config - 1;
+		dev_dbg(&client->dev, "initializing TW2804 channel %d\n",
+			dec->channel);
+		if (dec->channel == 0 &&
+				write_regs(client, global_registers, 0) < 0) {
+			dev_err(&client->dev,
+				"error initializing TW2804 global registers\n");
+			return -EIO;
+		}
+		if (write_regs(client, channel_registers, dec->channel) < 0) {
+			dev_err(&client->dev,
+				"error initializing TW2804 channel %d\n",
+				dec->channel);
+			return -EIO;
+		}
+	}
+
+	if (input > 1)
+		return -EINVAL;
+
+	if (input == dec->input)
+		return 0;
+
+	reg = read_reg(client, 0x22, dec->channel);
+
+	if (reg >= 0) {
+		if (input == 0)
+			reg &= ~(1 << 2);
+		else
+			reg |= 1 << 2;
+		reg = write_reg(client, 0x22, reg, dec->channel);
+	}
+
+	if (reg >= 0)
+		dec->input = input;
+	else
+		return reg;
+	return 0;
+}
+
+static const struct v4l2_ctrl_ops tw2804_ctrl_ops = {
+	.g_volatile_ctrl = tw2804_g_volatile_ctrl,
+	.s_ctrl = tw2804_s_ctrl,
+};
+
+static const struct v4l2_subdev_video_ops tw2804_video_ops = {
+	.s_routing = tw2804_s_video_routing,
+};
+
+static const struct v4l2_subdev_core_ops tw2804_core_ops = {
+	.log_status = tw2804_log_status,
+	.s_std = tw2804_s_std,
+};
+
+static const struct v4l2_subdev_ops tw2804_ops = {
+	.core = &tw2804_core_ops,
+	.video = &tw2804_video_ops,
+};
+
+static int tw2804_probe(struct i2c_client *client,
+			    const struct i2c_device_id *id)
+{
+	struct i2c_adapter *adapter = client->adapter;
+	struct tw2804 *state;
+	struct v4l2_subdev *sd;
+	struct v4l2_ctrl *ctrl;
+	int err;
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		return -ENODEV;
+
+	state = kzalloc(sizeof(struct tw2804), GFP_KERNEL);
+
+	if (state == NULL)
+		return -ENOMEM;
+	sd = &state->sd;
+	v4l2_i2c_subdev_init(sd, client, &tw2804_ops);
+	state->channel = -1;
+	state->norm = V4L2_STD_NTSC;
+
+	v4l2_ctrl_handler_init(&state->hdl, 10);
+	v4l2_ctrl_new_std(&state->hdl, &tw2804_ctrl_ops,
+				V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
+	v4l2_ctrl_new_std(&state->hdl, &tw2804_ctrl_ops,
+				V4L2_CID_CONTRAST, 0, 255, 1, 128);
+	v4l2_ctrl_new_std(&state->hdl, &tw2804_ctrl_ops,
+				V4L2_CID_SATURATION, 0, 255, 1, 128);
+	v4l2_ctrl_new_std(&state->hdl, &tw2804_ctrl_ops,
+				V4L2_CID_HUE, 0, 255, 1, 128);
+	v4l2_ctrl_new_std(&state->hdl, &tw2804_ctrl_ops,
+				V4L2_CID_COLOR_KILLER, 0, 1, 1, 0);
+	v4l2_ctrl_new_std(&state->hdl, &tw2804_ctrl_ops,
+				V4L2_CID_AUTOGAIN, 0, 1, 1, 0);
+	ctrl = v4l2_ctrl_new_std(&state->hdl, &tw2804_ctrl_ops,
+				V4L2_CID_GAIN, 0, 255, 1, 128);
+	if (ctrl)
+		ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
+	ctrl = v4l2_ctrl_new_std(&state->hdl, &tw2804_ctrl_ops,
+				V4L2_CID_CHROMA_GAIN, 0, 255, 1, 128);
+	if (ctrl)
+		ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
+	ctrl = v4l2_ctrl_new_std(&state->hdl, &tw2804_ctrl_ops,
+				V4L2_CID_BLUE_BALANCE, 0, 255, 1, 122);
+	if (ctrl)
+		ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
+	ctrl = v4l2_ctrl_new_std(&state->hdl, &tw2804_ctrl_ops,
+				V4L2_CID_RED_BALANCE, 0, 255, 1, 122);
+	if (ctrl)
+		ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
+	sd->ctrl_handler = &state->hdl;
+	err = state->hdl.error;
+	if (err) {
+		v4l2_ctrl_handler_free(&state->hdl);
+		kfree(state);
+		return err;
+	}
+
+	v4l_info(client, "chip found @ 0x%02x (%s)\n",
+			client->addr << 1, client->adapter->name);
+
+	return 0;
+}
+
+static int tw2804_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct tw2804 *state = to_state(sd);
+
+	v4l2_device_unregister_subdev(sd);
+	v4l2_ctrl_handler_free(&state->hdl);
+	kfree(state);
+	return 0;
+}
+
+static const struct i2c_device_id tw2804_id[] = {
+	{ "tw2804", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, tw2804_id);
+
+static struct i2c_driver tw2804_driver = {
+	.driver = {
+		.name	= "tw2804",
+	},
+	.probe		= tw2804_probe,
+	.remove		= tw2804_remove,
+	.id_table	= tw2804_id,
+};
+
+module_i2c_driver(tw2804_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("TW2804/TW2802 V4L2 i2c driver");
+MODULE_AUTHOR("Micronas USA Inc");
diff --git a/drivers/media/i2c/tw9903.c b/drivers/media/i2c/tw9903.c
new file mode 100644
index 0000000..87880b1
--- /dev/null
+++ b/drivers/media/i2c/tw9903.c
@@ -0,0 +1,279 @@
+/*
+ * Copyright (C) 2005-2006 Micronas USA 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., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/videodev2.h>
+#include <linux/ioctl.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
+#include <linux/slab.h>
+
+MODULE_DESCRIPTION("TW9903 I2C subdev driver");
+MODULE_LICENSE("GPL v2");
+
+/*
+ * This driver is based on the wis-tw9903.c source that was in
+ * drivers/staging/media/go7007. That source had commented out code for
+ * saturation and scaling (neither seemed to work). If anyone ever gets
+ * hardware to test this driver, then that code might be useful to look at.
+ * You need to get the kernel sources of, say, kernel 3.8 where that
+ * wis-tw9903 driver is still present.
+ */
+
+struct tw9903 {
+	struct v4l2_subdev sd;
+	struct v4l2_ctrl_handler hdl;
+	v4l2_std_id norm;
+};
+
+static inline struct tw9903 *to_state(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct tw9903, sd);
+}
+
+static const u8 initial_registers[] = {
+	0x02, 0x44, /* input 1, composite */
+	0x03, 0x92, /* correct digital format */
+	0x04, 0x00,
+	0x05, 0x80, /* or 0x00 for PAL */
+	0x06, 0x40, /* second internal current reference */
+	0x07, 0x02, /* window */
+	0x08, 0x14, /* window */
+	0x09, 0xf0, /* window */
+	0x0a, 0x81, /* window */
+	0x0b, 0xd0, /* window */
+	0x0c, 0x8c,
+	0x0d, 0x00, /* scaling */
+	0x0e, 0x11, /* scaling */
+	0x0f, 0x00, /* scaling */
+	0x10, 0x00, /* brightness */
+	0x11, 0x60, /* contrast */
+	0x12, 0x01, /* sharpness */
+	0x13, 0x7f, /* U gain */
+	0x14, 0x5a, /* V gain */
+	0x15, 0x00, /* hue */
+	0x16, 0xc3, /* sharpness */
+	0x18, 0x00,
+	0x19, 0x58, /* vbi */
+	0x1a, 0x80,
+	0x1c, 0x0f, /* video norm */
+	0x1d, 0x7f, /* video norm */
+	0x20, 0xa0, /* clamping gain (working 0x50) */
+	0x21, 0x22,
+	0x22, 0xf0,
+	0x23, 0xfe,
+	0x24, 0x3c,
+	0x25, 0x38,
+	0x26, 0x44,
+	0x27, 0x20,
+	0x28, 0x00,
+	0x29, 0x15,
+	0x2a, 0xa0,
+	0x2b, 0x44,
+	0x2c, 0x37,
+	0x2d, 0x00,
+	0x2e, 0xa5, /* burst PLL control (working: a9) */
+	0x2f, 0xe0, /* 0xea is blue test frame -- 0xe0 for normal */
+	0x31, 0x00,
+	0x33, 0x22,
+	0x34, 0x11,
+	0x35, 0x35,
+	0x3b, 0x05,
+	0x06, 0xc0, /* reset device */
+	0x00, 0x00, /* Terminator (reg 0x00 is read-only) */
+};
+
+static int write_reg(struct v4l2_subdev *sd, u8 reg, u8 value)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	return i2c_smbus_write_byte_data(client, reg, value);
+}
+
+static int write_regs(struct v4l2_subdev *sd, const u8 *regs)
+{
+	int i;
+
+	for (i = 0; regs[i] != 0x00; i += 2)
+		if (write_reg(sd, regs[i], regs[i + 1]) < 0)
+			return -1;
+	return 0;
+}
+
+static int tw9903_s_video_routing(struct v4l2_subdev *sd, u32 input,
+				      u32 output, u32 config)
+{
+	write_reg(sd, 0x02, 0x40 | (input << 1));
+	return 0;
+}
+
+static int tw9903_s_std(struct v4l2_subdev *sd, v4l2_std_id norm)
+{
+	struct tw9903 *dec = to_state(sd);
+	bool is_60hz = norm & V4L2_STD_525_60;
+	static const u8 config_60hz[] = {
+		0x05, 0x80,
+		0x07, 0x02,
+		0x08, 0x14,
+		0x09, 0xf0,
+		0,    0,
+	};
+	static const u8 config_50hz[] = {
+		0x05, 0x00,
+		0x07, 0x12,
+		0x08, 0x18,
+		0x09, 0x20,
+		0,    0,
+	};
+
+	write_regs(sd, is_60hz ? config_60hz : config_50hz);
+	dec->norm = norm;
+	return 0;
+}
+
+
+static int tw9903_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct tw9903 *dec = container_of(ctrl->handler, struct tw9903, hdl);
+	struct v4l2_subdev *sd = &dec->sd;
+
+	switch (ctrl->id) {
+	case V4L2_CID_BRIGHTNESS:
+		write_reg(sd, 0x10, ctrl->val);
+		break;
+	case V4L2_CID_CONTRAST:
+		write_reg(sd, 0x11, ctrl->val);
+		break;
+	case V4L2_CID_HUE:
+		write_reg(sd, 0x15, ctrl->val);
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int tw9903_log_status(struct v4l2_subdev *sd)
+{
+	struct tw9903 *dec = to_state(sd);
+	bool is_60hz = dec->norm & V4L2_STD_525_60;
+
+	v4l2_info(sd, "Standard: %d Hz\n", is_60hz ? 60 : 50);
+	v4l2_ctrl_subdev_log_status(sd);
+	return 0;
+}
+
+/* --------------------------------------------------------------------------*/
+
+static const struct v4l2_ctrl_ops tw9903_ctrl_ops = {
+	.s_ctrl = tw9903_s_ctrl,
+};
+
+static const struct v4l2_subdev_core_ops tw9903_core_ops = {
+	.log_status = tw9903_log_status,
+	.s_std = tw9903_s_std,
+};
+
+static const struct v4l2_subdev_video_ops tw9903_video_ops = {
+	.s_routing = tw9903_s_video_routing,
+};
+
+static const struct v4l2_subdev_ops tw9903_ops = {
+	.core = &tw9903_core_ops,
+	.video = &tw9903_video_ops,
+};
+
+/* --------------------------------------------------------------------------*/
+
+static int tw9903_probe(struct i2c_client *client,
+			     const struct i2c_device_id *id)
+{
+	struct tw9903 *dec;
+	struct v4l2_subdev *sd;
+	struct v4l2_ctrl_handler *hdl;
+
+	/* Check if the adapter supports the needed features */
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		return -EIO;
+
+	v4l_info(client, "chip found @ 0x%02x (%s)\n",
+			client->addr << 1, client->adapter->name);
+
+	dec = kzalloc(sizeof(struct tw9903), GFP_KERNEL);
+	if (dec == NULL)
+		return -ENOMEM;
+	sd = &dec->sd;
+	v4l2_i2c_subdev_init(sd, client, &tw9903_ops);
+	hdl = &dec->hdl;
+	v4l2_ctrl_handler_init(hdl, 4);
+	v4l2_ctrl_new_std(hdl, &tw9903_ctrl_ops,
+		V4L2_CID_BRIGHTNESS, -128, 127, 1, 0);
+	v4l2_ctrl_new_std(hdl, &tw9903_ctrl_ops,
+		V4L2_CID_CONTRAST, 0, 255, 1, 0x60);
+	v4l2_ctrl_new_std(hdl, &tw9903_ctrl_ops,
+		V4L2_CID_HUE, -128, 127, 1, 0);
+	sd->ctrl_handler = hdl;
+	if (hdl->error) {
+		int err = hdl->error;
+
+		v4l2_ctrl_handler_free(hdl);
+		kfree(dec);
+		return err;
+	}
+
+	/* Initialize tw9903 */
+	dec->norm = V4L2_STD_NTSC;
+
+	if (write_regs(sd, initial_registers) < 0) {
+		v4l2_err(client, "error initializing TW9903\n");
+		kfree(dec);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int tw9903_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+
+	v4l2_device_unregister_subdev(sd);
+	v4l2_ctrl_handler_free(&to_state(sd)->hdl);
+	kfree(to_state(sd));
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct i2c_device_id tw9903_id[] = {
+	{ "tw9903", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, tw9903_id);
+
+static struct i2c_driver tw9903_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "tw9903",
+	},
+	.probe = tw9903_probe,
+	.remove = tw9903_remove,
+	.id_table = tw9903_id,
+};
+module_i2c_driver(tw9903_driver);
diff --git a/drivers/media/i2c/tw9906.c b/drivers/media/i2c/tw9906.c
new file mode 100644
index 0000000..accd79e
--- /dev/null
+++ b/drivers/media/i2c/tw9906.c
@@ -0,0 +1,247 @@
+/*
+ * Copyright (C) 2005-2006 Micronas USA 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., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/videodev2.h>
+#include <linux/ioctl.h>
+#include <linux/slab.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
+
+MODULE_DESCRIPTION("TW9906 I2C subdev driver");
+MODULE_LICENSE("GPL v2");
+
+struct tw9906 {
+	struct v4l2_subdev sd;
+	struct v4l2_ctrl_handler hdl;
+	v4l2_std_id norm;
+};
+
+static inline struct tw9906 *to_state(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct tw9906, sd);
+}
+
+static const u8 initial_registers[] = {
+	0x02, 0x40, /* input 0, composite */
+	0x03, 0xa2, /* correct digital format */
+	0x05, 0x81, /* or 0x01 for PAL */
+	0x07, 0x02, /* window */
+	0x08, 0x14, /* window */
+	0x09, 0xf0, /* window */
+	0x0a, 0x10, /* window */
+	0x0b, 0xd0, /* window */
+	0x0d, 0x00, /* scaling */
+	0x0e, 0x11, /* scaling */
+	0x0f, 0x00, /* scaling */
+	0x10, 0x00, /* brightness */
+	0x11, 0x60, /* contrast */
+	0x12, 0x11, /* sharpness */
+	0x13, 0x7e, /* U gain */
+	0x14, 0x7e, /* V gain */
+	0x15, 0x00, /* hue */
+	0x19, 0x57, /* vbi */
+	0x1a, 0x0f,
+	0x1b, 0x40,
+	0x29, 0x03,
+	0x55, 0x00,
+	0x6b, 0x26,
+	0x6c, 0x36,
+	0x6d, 0xf0,
+	0x6e, 0x41,
+	0x6f, 0x13,
+	0xad, 0x70,
+	0x00, 0x00, /* Terminator (reg 0x00 is read-only) */
+};
+
+static int write_reg(struct v4l2_subdev *sd, u8 reg, u8 value)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	return i2c_smbus_write_byte_data(client, reg, value);
+}
+
+static int write_regs(struct v4l2_subdev *sd, const u8 *regs)
+{
+	int i;
+
+	for (i = 0; regs[i] != 0x00; i += 2)
+		if (write_reg(sd, regs[i], regs[i + 1]) < 0)
+			return -1;
+	return 0;
+}
+
+static int tw9906_s_video_routing(struct v4l2_subdev *sd, u32 input,
+				      u32 output, u32 config)
+{
+	write_reg(sd, 0x02, 0x40 | (input << 1));
+	return 0;
+}
+
+static int tw9906_s_std(struct v4l2_subdev *sd, v4l2_std_id norm)
+{
+	struct tw9906 *dec = to_state(sd);
+	bool is_60hz = norm & V4L2_STD_525_60;
+	static const u8 config_60hz[] = {
+		0x05, 0x81,
+		0x07, 0x02,
+		0x08, 0x14,
+		0x09, 0xf0,
+		0,    0,
+	};
+	static const u8 config_50hz[] = {
+		0x05, 0x01,
+		0x07, 0x12,
+		0x08, 0x18,
+		0x09, 0x20,
+		0,    0,
+	};
+
+	write_regs(sd, is_60hz ? config_60hz : config_50hz);
+	dec->norm = norm;
+	return 0;
+}
+
+static int tw9906_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct tw9906 *dec = container_of(ctrl->handler, struct tw9906, hdl);
+	struct v4l2_subdev *sd = &dec->sd;
+
+	switch (ctrl->id) {
+	case V4L2_CID_BRIGHTNESS:
+		write_reg(sd, 0x10, ctrl->val);
+		break;
+	case V4L2_CID_CONTRAST:
+		write_reg(sd, 0x11, ctrl->val);
+		break;
+	case V4L2_CID_HUE:
+		write_reg(sd, 0x15, ctrl->val);
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int tw9906_log_status(struct v4l2_subdev *sd)
+{
+	struct tw9906 *dec = to_state(sd);
+	bool is_60hz = dec->norm & V4L2_STD_525_60;
+
+	v4l2_info(sd, "Standard: %d Hz\n", is_60hz ? 60 : 50);
+	v4l2_ctrl_subdev_log_status(sd);
+	return 0;
+}
+
+/* --------------------------------------------------------------------------*/
+
+static const struct v4l2_ctrl_ops tw9906_ctrl_ops = {
+	.s_ctrl = tw9906_s_ctrl,
+};
+
+static const struct v4l2_subdev_core_ops tw9906_core_ops = {
+	.log_status = tw9906_log_status,
+	.s_std = tw9906_s_std,
+};
+
+static const struct v4l2_subdev_video_ops tw9906_video_ops = {
+	.s_routing = tw9906_s_video_routing,
+};
+
+static const struct v4l2_subdev_ops tw9906_ops = {
+	.core = &tw9906_core_ops,
+	.video = &tw9906_video_ops,
+};
+
+static int tw9906_probe(struct i2c_client *client,
+			     const struct i2c_device_id *id)
+{
+	struct tw9906 *dec;
+	struct v4l2_subdev *sd;
+	struct v4l2_ctrl_handler *hdl;
+
+	/* Check if the adapter supports the needed features */
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		return -EIO;
+
+	v4l_info(client, "chip found @ 0x%02x (%s)\n",
+			client->addr << 1, client->adapter->name);
+
+	dec = kzalloc(sizeof(struct tw9906), GFP_KERNEL);
+	if (dec == NULL)
+		return -ENOMEM;
+	sd = &dec->sd;
+	v4l2_i2c_subdev_init(sd, client, &tw9906_ops);
+	hdl = &dec->hdl;
+	v4l2_ctrl_handler_init(hdl, 4);
+	v4l2_ctrl_new_std(hdl, &tw9906_ctrl_ops,
+		V4L2_CID_BRIGHTNESS, -128, 127, 1, 0);
+	v4l2_ctrl_new_std(hdl, &tw9906_ctrl_ops,
+		V4L2_CID_CONTRAST, 0, 255, 1, 0x60);
+	v4l2_ctrl_new_std(hdl, &tw9906_ctrl_ops,
+		V4L2_CID_HUE, -128, 127, 1, 0);
+	sd->ctrl_handler = hdl;
+	if (hdl->error) {
+		int err = hdl->error;
+
+		v4l2_ctrl_handler_free(hdl);
+		kfree(dec);
+		return err;
+	}
+
+	/* Initialize tw9906 */
+	dec->norm = V4L2_STD_NTSC;
+
+	if (write_regs(sd, initial_registers) < 0) {
+		v4l2_err(client, "error initializing TW9906\n");
+		kfree(dec);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int tw9906_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+
+	v4l2_device_unregister_subdev(sd);
+	v4l2_ctrl_handler_free(&to_state(sd)->hdl);
+	kfree(to_state(sd));
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct i2c_device_id tw9906_id[] = {
+	{ "tw9906", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, tw9906_id);
+
+static struct i2c_driver tw9906_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "tw9906",
+	},
+	.probe = tw9906_probe,
+	.remove = tw9906_remove,
+	.id_table = tw9906_id,
+};
+module_i2c_driver(tw9906_driver);
diff --git a/drivers/media/i2c/uda1342.c b/drivers/media/i2c/uda1342.c
new file mode 100644
index 0000000..3af4085
--- /dev/null
+++ b/drivers/media/i2c/uda1342.c
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2005-2006 Micronas USA 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., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-device.h>
+#include <media/uda1342.h>
+#include <linux/slab.h>
+
+static int write_reg(struct i2c_client *client, int reg, int value)
+{
+	/* UDA1342 wants MSB first, but SMBus sends LSB first */
+	i2c_smbus_write_word_data(client, reg, swab16(value));
+	return 0;
+}
+
+static int uda1342_s_routing(struct v4l2_subdev *sd,
+		u32 input, u32 output, u32 config)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	switch (input) {
+	case UDA1342_IN1:
+		write_reg(client, 0x00, 0x1241); /* select input 1 */
+		break;
+	case UDA1342_IN2:
+		write_reg(client, 0x00, 0x1441); /* select input 2 */
+		break;
+	default:
+		v4l2_err(sd, "input %d not supported\n", input);
+		break;
+	}
+	return 0;
+}
+
+static const struct v4l2_subdev_audio_ops uda1342_audio_ops = {
+	.s_routing = uda1342_s_routing,
+};
+
+static const struct v4l2_subdev_ops uda1342_ops = {
+	.audio = &uda1342_audio_ops,
+};
+
+static int uda1342_probe(struct i2c_client *client,
+			     const struct i2c_device_id *id)
+{
+	struct i2c_adapter *adapter = client->adapter;
+	struct v4l2_subdev *sd;
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA))
+		return -ENODEV;
+
+	dev_dbg(&client->dev, "initializing UDA1342 at address %d on %s\n",
+		client->addr, adapter->name);
+
+	sd = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
+	if (sd == NULL)
+		return -ENOMEM;
+
+	v4l2_i2c_subdev_init(sd, client, &uda1342_ops);
+
+	write_reg(client, 0x00, 0x8000); /* reset registers */
+	write_reg(client, 0x00, 0x1241); /* select input 1 */
+
+	v4l_info(client, "chip found @ 0x%02x (%s)\n",
+			client->addr << 1, client->adapter->name);
+
+	return 0;
+}
+
+static int uda1342_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+
+	v4l2_device_unregister_subdev(sd);
+	kfree(sd);
+	return 0;
+}
+
+static const struct i2c_device_id uda1342_id[] = {
+	{ "uda1342", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, uda1342_id);
+
+static struct i2c_driver uda1342_driver = {
+	.driver = {
+		.name	= "uda1342",
+	},
+	.probe		= uda1342_probe,
+	.remove		= uda1342_remove,
+	.id_table	= uda1342_id,
+};
+
+module_i2c_driver(uda1342_driver);
+
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/i2c/upd64031a.c b/drivers/media/i2c/upd64031a.c
index 1e74465..f0a0921 100644
--- a/drivers/media/i2c/upd64031a.c
+++ b/drivers/media/i2c/upd64031a.c
@@ -111,7 +111,7 @@ static void upd64031a_write(struct v4l2_subdev *sd, u8 reg, u8 val)
 /* ------------------------------------------------------------------------ */
 
 /* The input changed due to new input or channel changed */
-static int upd64031a_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *freq)
+static int upd64031a_s_frequency(struct v4l2_subdev *sd, const struct v4l2_frequency *freq)
 {
 	struct upd64031a_state *state = to_state(sd);
 	u8 reg = state->regs[R00];
@@ -175,7 +175,7 @@ static int upd64031a_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register
 	return 0;
 }
 
-static int upd64031a_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
+static int upd64031a_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 
diff --git a/drivers/media/i2c/upd64083.c b/drivers/media/i2c/upd64083.c
index 75d6acc..343e021 100644
--- a/drivers/media/i2c/upd64083.c
+++ b/drivers/media/i2c/upd64083.c
@@ -133,7 +133,7 @@ static int upd64083_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register
 	return 0;
 }
 
-static int upd64083_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
+static int upd64083_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 
diff --git a/drivers/media/i2c/vp27smpx.c b/drivers/media/i2c/vp27smpx.c
index 7cfbc9d..e71f139 100644
--- a/drivers/media/i2c/vp27smpx.c
+++ b/drivers/media/i2c/vp27smpx.c
@@ -90,7 +90,7 @@ static int vp27smpx_s_std(struct v4l2_subdev *sd, v4l2_std_id norm)
 	return 0;
 }
 
-static int vp27smpx_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
+static int vp27smpx_s_tuner(struct v4l2_subdev *sd, const struct v4l2_tuner *vt)
 {
 	struct vp27smpx_state *state = to_state(sd);
 
diff --git a/drivers/media/i2c/vs6624.c b/drivers/media/i2c/vs6624.c
index 9ac1b8c3..f366fad 100644
--- a/drivers/media/i2c/vs6624.c
+++ b/drivers/media/i2c/vs6624.c
@@ -748,7 +748,7 @@ static int vs6624_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *r
 	return 0;
 }
 
-static int vs6624_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
+static int vs6624_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 
diff --git a/drivers/media/i2c/wm8775.c b/drivers/media/i2c/wm8775.c
index bee77ea..27c27b4 100644
--- a/drivers/media/i2c/wm8775.c
+++ b/drivers/media/i2c/wm8775.c
@@ -174,7 +174,7 @@ static int wm8775_log_status(struct v4l2_subdev *sd)
 	return 0;
 }
 
-static int wm8775_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *freq)
+static int wm8775_s_frequency(struct v4l2_subdev *sd, const struct v4l2_frequency *freq)
 {
 	wm8775_set_audio(sd, 0);
 	return 0;
diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c
index d01fcb7..99b80b6 100644
--- a/drivers/media/media-device.c
+++ b/drivers/media/media-device.c
@@ -20,10 +20,11 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#include <linux/types.h>
+#include <linux/compat.h>
+#include <linux/export.h>
 #include <linux/ioctl.h>
 #include <linux/media.h>
-#include <linux/export.h>
+#include <linux/types.h>
 
 #include <media/media-device.h>
 #include <media/media-devnode.h>
@@ -124,35 +125,31 @@ static void media_device_kpad_to_upad(const struct media_pad *kpad,
 	upad->flags = kpad->flags;
 }
 
-static long media_device_enum_links(struct media_device *mdev,
-				    struct media_links_enum __user *ulinks)
+static long __media_device_enum_links(struct media_device *mdev,
+				      struct media_links_enum *links)
 {
 	struct media_entity *entity;
-	struct media_links_enum links;
 
-	if (copy_from_user(&links, ulinks, sizeof(links)))
-		return -EFAULT;
-
-	entity = find_entity(mdev, links.entity);
+	entity = find_entity(mdev, links->entity);
 	if (entity == NULL)
 		return -EINVAL;
 
-	if (links.pads) {
+	if (links->pads) {
 		unsigned int p;
 
 		for (p = 0; p < entity->num_pads; p++) {
 			struct media_pad_desc pad;
 			media_device_kpad_to_upad(&entity->pads[p], &pad);
-			if (copy_to_user(&links.pads[p], &pad, sizeof(pad)))
+			if (copy_to_user(&links->pads[p], &pad, sizeof(pad)))
 				return -EFAULT;
 		}
 	}
 
-	if (links.links) {
+	if (links->links) {
 		struct media_link_desc __user *ulink;
 		unsigned int l;
 
-		for (l = 0, ulink = links.links; l < entity->num_links; l++) {
+		for (l = 0, ulink = links->links; l < entity->num_links; l++) {
 			struct media_link_desc link;
 
 			/* Ignore backlinks. */
@@ -169,8 +166,26 @@ static long media_device_enum_links(struct media_device *mdev,
 			ulink++;
 		}
 	}
+
+	return 0;
+}
+
+static long media_device_enum_links(struct media_device *mdev,
+				    struct media_links_enum __user *ulinks)
+{
+	struct media_links_enum links;
+	int rval;
+
+	if (copy_from_user(&links, ulinks, sizeof(links)))
+		return -EFAULT;
+
+	rval = __media_device_enum_links(mdev, &links);
+	if (rval < 0)
+		return rval;
+
 	if (copy_to_user(ulinks, &links, sizeof(*ulinks)))
 		return -EFAULT;
+
 	return 0;
 }
 
@@ -251,10 +266,71 @@ static long media_device_ioctl(struct file *filp, unsigned int cmd,
 	return ret;
 }
 
+#ifdef CONFIG_COMPAT
+
+struct media_links_enum32 {
+	__u32 entity;
+	compat_uptr_t pads; /* struct media_pad_desc * */
+	compat_uptr_t links; /* struct media_link_desc * */
+	__u32 reserved[4];
+};
+
+static long media_device_enum_links32(struct media_device *mdev,
+				      struct media_links_enum32 __user *ulinks)
+{
+	struct media_links_enum links;
+	compat_uptr_t pads_ptr, links_ptr;
+
+	memset(&links, 0, sizeof(links));
+
+	if (get_user(links.entity, &ulinks->entity)
+	    || get_user(pads_ptr, &ulinks->pads)
+	    || get_user(links_ptr, &ulinks->links))
+		return -EFAULT;
+
+	links.pads = compat_ptr(pads_ptr);
+	links.links = compat_ptr(links_ptr);
+
+	return __media_device_enum_links(mdev, &links);
+}
+
+#define MEDIA_IOC_ENUM_LINKS32		_IOWR('|', 0x02, struct media_links_enum32)
+
+static long media_device_compat_ioctl(struct file *filp, unsigned int cmd,
+				      unsigned long arg)
+{
+	struct media_devnode *devnode = media_devnode_data(filp);
+	struct media_device *dev = to_media_device(devnode);
+	long ret;
+
+	switch (cmd) {
+	case MEDIA_IOC_DEVICE_INFO:
+	case MEDIA_IOC_ENUM_ENTITIES:
+	case MEDIA_IOC_SETUP_LINK:
+		return media_device_ioctl(filp, cmd, arg);
+
+	case MEDIA_IOC_ENUM_LINKS32:
+		mutex_lock(&dev->graph_mutex);
+		ret = media_device_enum_links32(dev,
+				(struct media_links_enum32 __user *)arg);
+		mutex_unlock(&dev->graph_mutex);
+		break;
+
+	default:
+		ret = -ENOIOCTLCMD;
+	}
+
+	return ret;
+}
+#endif /* CONFIG_COMPAT */
+
 static const struct media_file_operations media_device_fops = {
 	.owner = THIS_MODULE,
 	.open = media_device_open,
 	.ioctl = media_device_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl = media_device_compat_ioctl,
+#endif /* CONFIG_COMPAT */
 	.release = media_device_close,
 };
 
diff --git a/drivers/media/media-devnode.c b/drivers/media/media-devnode.c
index 023b2a1..fb0f046 100644
--- a/drivers/media/media-devnode.c
+++ b/drivers/media/media-devnode.c
@@ -116,19 +116,41 @@ static unsigned int media_poll(struct file *filp,
 	return mdev->fops->poll(filp, poll);
 }
 
-static long media_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+static long
+__media_ioctl(struct file *filp, unsigned int cmd, unsigned long arg,
+	      long (*ioctl_func)(struct file *filp, unsigned int cmd,
+				 unsigned long arg))
 {
 	struct media_devnode *mdev = media_devnode_data(filp);
 
-	if (!mdev->fops->ioctl)
+	if (!ioctl_func)
 		return -ENOTTY;
 
 	if (!media_devnode_is_registered(mdev))
 		return -EIO;
 
-	return mdev->fops->ioctl(filp, cmd, arg);
+	return ioctl_func(filp, cmd, arg);
+}
+
+static long media_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+	struct media_devnode *mdev = media_devnode_data(filp);
+
+	return __media_ioctl(filp, cmd, arg, mdev->fops->ioctl);
 }
 
+#ifdef CONFIG_COMPAT
+
+static long media_compat_ioctl(struct file *filp, unsigned int cmd,
+			       unsigned long arg)
+{
+	struct media_devnode *mdev = media_devnode_data(filp);
+
+	return __media_ioctl(filp, cmd, arg, mdev->fops->compat_ioctl);
+}
+
+#endif /* CONFIG_COMPAT */
+
 /* Override for the open function */
 static int media_open(struct inode *inode, struct file *filp)
 {
@@ -188,6 +210,9 @@ static const struct file_operations media_devnode_fops = {
 	.write = media_write,
 	.open = media_open,
 	.unlocked_ioctl = media_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl = media_compat_ioctl,
+#endif /* CONFIG_COMPAT */
 	.release = media_release,
 	.poll = media_poll,
 	.llseek = no_llseek,
diff --git a/drivers/media/mmc/siano/smssdio.c b/drivers/media/mmc/siano/smssdio.c
index 15d3493..912c281 100644
--- a/drivers/media/mmc/siano/smssdio.c
+++ b/drivers/media/mmc/siano/smssdio.c
@@ -43,6 +43,7 @@
 
 #include "smscoreapi.h"
 #include "sms-cards.h"
+#include "smsendian.h"
 
 /* Registers */
 
@@ -61,6 +62,16 @@ static const struct sdio_device_id smssdio_ids[] = {
 	 .driver_data = SMS1XXX_BOARD_SIANO_VEGA},
 	{SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_VENICE),
 	 .driver_data = SMS1XXX_BOARD_SIANO_VEGA},
+	{SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, 0x302),
+	.driver_data = SMS1XXX_BOARD_SIANO_MING},
+	{SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, 0x500),
+	.driver_data = SMS1XXX_BOARD_SIANO_PELE},
+	{SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, 0x600),
+	.driver_data = SMS1XXX_BOARD_SIANO_RIO},
+	{SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, 0x700),
+	.driver_data = SMS1XXX_BOARD_SIANO_DENVER_2160},
+	{SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, 0x800),
+	.driver_data = SMS1XXX_BOARD_SIANO_DENVER_1530},
 	{ /* end: all zeroes */ },
 };
 
@@ -87,6 +98,7 @@ static int smssdio_sendrequest(void *context, void *buffer, size_t size)
 
 	sdio_claim_host(smsdev->func);
 
+	smsendian_handle_tx_message((struct sms_msg_data *) buffer);
 	while (size >= smsdev->func->cur_blksize) {
 		ret = sdio_memcpy_toio(smsdev->func, SMSSDIO_DATA,
 					buffer, smsdev->func->cur_blksize);
@@ -118,7 +130,7 @@ static void smssdio_interrupt(struct sdio_func *func)
 
 	struct smssdio_device *smsdev;
 	struct smscore_buffer_t *cb;
-	struct SmsMsgHdr_ST *hdr;
+	struct sms_msg_hdr *hdr;
 	size_t size;
 
 	smsdev = sdio_get_drvdata(func);
@@ -151,20 +163,20 @@ static void smssdio_interrupt(struct sdio_func *func)
 
 		hdr = cb->p;
 
-		if (hdr->msgFlags & MSG_HDR_FLAG_SPLIT_MSG) {
+		if (hdr->msg_flags & MSG_HDR_FLAG_SPLIT_MSG) {
 			smsdev->split_cb = cb;
 			return;
 		}
 
-		if (hdr->msgLength > smsdev->func->cur_blksize)
-			size = hdr->msgLength - smsdev->func->cur_blksize;
+		if (hdr->msg_length > smsdev->func->cur_blksize)
+			size = hdr->msg_length - smsdev->func->cur_blksize;
 		else
 			size = 0;
 	} else {
 		cb = smsdev->split_cb;
 		hdr = cb->p;
 
-		size = hdr->msgLength - sizeof(struct SmsMsgHdr_ST);
+		size = hdr->msg_length - sizeof(struct sms_msg_hdr);
 
 		smsdev->split_cb = NULL;
 	}
@@ -172,7 +184,7 @@ static void smssdio_interrupt(struct sdio_func *func)
 	if (size) {
 		void *buffer;
 
-		buffer = cb->p + (hdr->msgLength - size);
+		buffer = cb->p + (hdr->msg_length - size);
 		size = ALIGN(size, SMSSDIO_BLOCK_SIZE);
 
 		BUG_ON(smsdev->func->cur_blksize != SMSSDIO_BLOCK_SIZE);
@@ -218,9 +230,10 @@ static void smssdio_interrupt(struct sdio_func *func)
 		}
 	}
 
-	cb->size = hdr->msgLength;
+	cb->size = hdr->msg_length;
 	cb->offset = 0;
 
+	smsendian_handle_rx_message((struct sms_msg_data *) cb->p);
 	smscore_onresponse(smsdev->coredev, cb);
 }
 
diff --git a/drivers/media/parport/pms.c b/drivers/media/parport/pms.c
index 77f9c92..66c957a 100644
--- a/drivers/media/parport/pms.c
+++ b/drivers/media/parport/pms.c
@@ -735,12 +735,12 @@ static int pms_g_std(struct file *file, void *fh, v4l2_std_id *std)
 	return 0;
 }
 
-static int pms_s_std(struct file *file, void *fh, v4l2_std_id *std)
+static int pms_s_std(struct file *file, void *fh, v4l2_std_id std)
 {
 	struct pms *dev = video_drvdata(file);
 	int ret = 0;
 
-	dev->std = *std;
+	dev->std = std;
 	if (dev->std & V4L2_STD_NTSC) {
 		pms_framerate(dev, 30);
 		pms_secamcross(dev, 0);
diff --git a/drivers/media/pci/bt8xx/bttv-cards.c b/drivers/media/pci/bt8xx/bttv-cards.c
index c4c5917..b7dc921 100644
--- a/drivers/media/pci/bt8xx/bttv-cards.c
+++ b/drivers/media/pci/bt8xx/bttv-cards.c
@@ -3547,6 +3547,16 @@ void bttv_init_card2(struct bttv *btv)
 	if (btv->sd_msp34xx)
 		return;
 
+	/* Now see if we can find one of the tvaudio devices. */
+	btv->sd_tvaudio = v4l2_i2c_new_subdev(&btv->c.v4l2_dev,
+		&btv->c.i2c_adap, "tvaudio", 0, tvaudio_addrs());
+	if (btv->sd_tvaudio) {
+		/* There may be two tvaudio chips on the card, so try to
+		   find another. */
+		v4l2_i2c_new_subdev(&btv->c.v4l2_dev,
+			&btv->c.i2c_adap, "tvaudio", 0, tvaudio_addrs());
+	}
+
 	/* it might also be a tda7432. */
 	if (!bttv_tvcards[btv->c.type].no_tda7432) {
 		static const unsigned short addrs[] = {
@@ -3554,14 +3564,11 @@ void bttv_init_card2(struct bttv *btv)
 			I2C_CLIENT_END
 		};
 
-		if (v4l2_i2c_new_subdev(&btv->c.v4l2_dev,
-				&btv->c.i2c_adap, "tda7432", 0, addrs))
+		btv->sd_tda7432 = v4l2_i2c_new_subdev(&btv->c.v4l2_dev,
+				&btv->c.i2c_adap, "tda7432", 0, addrs);
+		if (btv->sd_tda7432)
 			return;
 	}
-
-	/* Now see if we can find one of the tvaudio devices. */
-	btv->sd_tvaudio = v4l2_i2c_new_subdev(&btv->c.v4l2_dev,
-		&btv->c.i2c_adap, "tvaudio", 0, tvaudio_addrs());
 	if (btv->sd_tvaudio)
 		return;
 
@@ -3940,7 +3947,7 @@ static void avermedia_eeprom(struct bttv *btv)
 u32 bttv_tda9880_setnorm(struct bttv *btv, u32 gpiobits)
 {
 
-	if (btv->audio == TVAUDIO_INPUT_TUNER) {
+	if (btv->audio_input == TVAUDIO_INPUT_TUNER) {
 		if (bttv_tvnorms[btv->tvnorm].v4l2_id & V4L2_STD_MN)
 			gpiobits |= 0x10000;
 		else
diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c
index 54579e4..e7d0884 100644
--- a/drivers/media/pci/bt8xx/bttv-driver.c
+++ b/drivers/media/pci/bt8xx/bttv-driver.c
@@ -49,6 +49,8 @@
 #include "bttvp.h"
 #include <media/v4l2-common.h>
 #include <media/v4l2-ioctl.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-chip-ident.h>
 #include <media/tvaudio.h>
 #include <media/msp3400.h>
 
@@ -93,7 +95,7 @@ static unsigned int combfilter;
 static unsigned int lumafilter;
 static unsigned int automute    = 1;
 static unsigned int chroma_agc;
-static unsigned int adc_crush   = 1;
+static unsigned int agc_crush   = 1;
 static unsigned int whitecrush_upper = 0xCF;
 static unsigned int whitecrush_lower = 0x7F;
 static unsigned int vcr_hack;
@@ -125,7 +127,7 @@ module_param(combfilter,        int, 0444);
 module_param(lumafilter,        int, 0444);
 module_param(automute,          int, 0444);
 module_param(chroma_agc,        int, 0444);
-module_param(adc_crush,         int, 0444);
+module_param(agc_crush,         int, 0444);
 module_param(whitecrush_upper,  int, 0444);
 module_param(whitecrush_lower,  int, 0444);
 module_param(vcr_hack,          int, 0444);
@@ -138,27 +140,27 @@ module_param_array(video_nr,    int, NULL, 0444);
 module_param_array(radio_nr,    int, NULL, 0444);
 module_param_array(vbi_nr,      int, NULL, 0444);
 
-MODULE_PARM_DESC(radio,"The TV card supports radio, default is 0 (no)");
-MODULE_PARM_DESC(bigendian,"byte order of the framebuffer, default is native endian");
-MODULE_PARM_DESC(bttv_verbose,"verbose startup messages, default is 1 (yes)");
-MODULE_PARM_DESC(bttv_gpio,"log gpio changes, default is 0 (no)");
-MODULE_PARM_DESC(bttv_debug,"debug messages, default is 0 (no)");
-MODULE_PARM_DESC(irq_debug,"irq handler debug messages, default is 0 (no)");
+MODULE_PARM_DESC(radio, "The TV card supports radio, default is 0 (no)");
+MODULE_PARM_DESC(bigendian, "byte order of the framebuffer, default is native endian");
+MODULE_PARM_DESC(bttv_verbose, "verbose startup messages, default is 1 (yes)");
+MODULE_PARM_DESC(bttv_gpio, "log gpio changes, default is 0 (no)");
+MODULE_PARM_DESC(bttv_debug, "debug messages, default is 0 (no)");
+MODULE_PARM_DESC(irq_debug, "irq handler debug messages, default is 0 (no)");
 MODULE_PARM_DESC(disable_ir, "disable infrared remote support");
-MODULE_PARM_DESC(gbuffers,"number of capture buffers. range 2-32, default 8");
-MODULE_PARM_DESC(gbufsize,"size of the capture buffers, default is 0x208000");
-MODULE_PARM_DESC(reset_crop,"reset cropping parameters at open(), default "
+MODULE_PARM_DESC(gbuffers, "number of capture buffers. range 2-32, default 8");
+MODULE_PARM_DESC(gbufsize, "size of the capture buffers, default is 0x208000");
+MODULE_PARM_DESC(reset_crop, "reset cropping parameters at open(), default "
 		 "is 1 (yes) for compatibility with older applications");
-MODULE_PARM_DESC(automute,"mute audio on bad/missing video signal, default is 1 (yes)");
-MODULE_PARM_DESC(chroma_agc,"enables the AGC of chroma signal, default is 0 (no)");
-MODULE_PARM_DESC(adc_crush,"enables the luminance ADC crush, default is 1 (yes)");
-MODULE_PARM_DESC(whitecrush_upper,"sets the white crush upper value, default is 207");
-MODULE_PARM_DESC(whitecrush_lower,"sets the white crush lower value, default is 127");
-MODULE_PARM_DESC(vcr_hack,"enables the VCR hack (improves synch on poor VCR tapes), default is 0 (no)");
-MODULE_PARM_DESC(irq_iswitch,"switch inputs in irq handler");
-MODULE_PARM_DESC(uv_ratio,"ratio between u and v gains, default is 50");
-MODULE_PARM_DESC(full_luma_range,"use the full luma range, default is 0 (no)");
-MODULE_PARM_DESC(coring,"set the luma coring level, default is 0 (no)");
+MODULE_PARM_DESC(automute, "mute audio on bad/missing video signal, default is 1 (yes)");
+MODULE_PARM_DESC(chroma_agc, "enables the AGC of chroma signal, default is 0 (no)");
+MODULE_PARM_DESC(agc_crush, "enables the luminance AGC crush, default is 1 (yes)");
+MODULE_PARM_DESC(whitecrush_upper, "sets the white crush upper value, default is 207");
+MODULE_PARM_DESC(whitecrush_lower, "sets the white crush lower value, default is 127");
+MODULE_PARM_DESC(vcr_hack, "enables the VCR hack (improves synch on poor VCR tapes), default is 0 (no)");
+MODULE_PARM_DESC(irq_iswitch, "switch inputs in irq handler");
+MODULE_PARM_DESC(uv_ratio, "ratio between u and v gains, default is 50");
+MODULE_PARM_DESC(full_luma_range, "use the full luma range, default is 0 (no)");
+MODULE_PARM_DESC(coring, "set the luma coring level, default is 0 (no)");
 MODULE_PARM_DESC(video_nr, "video device numbers");
 MODULE_PARM_DESC(vbi_nr, "vbi device numbers");
 MODULE_PARM_DESC(radio_nr, "radio device numbers");
@@ -168,6 +170,17 @@ MODULE_AUTHOR("Ralph Metzler & Marcus Metzler & Gerd Knorr");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(BTTV_VERSION);
 
+#define V4L2_CID_PRIVATE_COMBFILTER		(V4L2_CID_USER_BTTV_BASE + 0)
+#define V4L2_CID_PRIVATE_AUTOMUTE		(V4L2_CID_USER_BTTV_BASE + 1)
+#define V4L2_CID_PRIVATE_LUMAFILTER		(V4L2_CID_USER_BTTV_BASE + 2)
+#define V4L2_CID_PRIVATE_AGC_CRUSH		(V4L2_CID_USER_BTTV_BASE + 3)
+#define V4L2_CID_PRIVATE_VCR_HACK		(V4L2_CID_USER_BTTV_BASE + 4)
+#define V4L2_CID_PRIVATE_WHITECRUSH_LOWER	(V4L2_CID_USER_BTTV_BASE + 5)
+#define V4L2_CID_PRIVATE_WHITECRUSH_UPPER	(V4L2_CID_USER_BTTV_BASE + 6)
+#define V4L2_CID_PRIVATE_UV_RATIO		(V4L2_CID_USER_BTTV_BASE + 7)
+#define V4L2_CID_PRIVATE_FULL_LUMA_RANGE	(V4L2_CID_USER_BTTV_BASE + 8)
+#define V4L2_CID_PRIVATE_CORING			(V4L2_CID_USER_BTTV_BASE + 9)
+
 /* ----------------------------------------------------------------------- */
 /* sysfs                                                                   */
 
@@ -632,198 +645,6 @@ static const struct bttv_format formats[] = {
 static const unsigned int FORMATS = ARRAY_SIZE(formats);
 
 /* ----------------------------------------------------------------------- */
-
-#define V4L2_CID_PRIVATE_CHROMA_AGC  (V4L2_CID_PRIVATE_BASE + 0)
-#define V4L2_CID_PRIVATE_COMBFILTER  (V4L2_CID_PRIVATE_BASE + 1)
-#define V4L2_CID_PRIVATE_AUTOMUTE    (V4L2_CID_PRIVATE_BASE + 2)
-#define V4L2_CID_PRIVATE_LUMAFILTER  (V4L2_CID_PRIVATE_BASE + 3)
-#define V4L2_CID_PRIVATE_AGC_CRUSH   (V4L2_CID_PRIVATE_BASE + 4)
-#define V4L2_CID_PRIVATE_VCR_HACK    (V4L2_CID_PRIVATE_BASE + 5)
-#define V4L2_CID_PRIVATE_WHITECRUSH_UPPER   (V4L2_CID_PRIVATE_BASE + 6)
-#define V4L2_CID_PRIVATE_WHITECRUSH_LOWER   (V4L2_CID_PRIVATE_BASE + 7)
-#define V4L2_CID_PRIVATE_UV_RATIO    (V4L2_CID_PRIVATE_BASE + 8)
-#define V4L2_CID_PRIVATE_FULL_LUMA_RANGE    (V4L2_CID_PRIVATE_BASE + 9)
-#define V4L2_CID_PRIVATE_CORING      (V4L2_CID_PRIVATE_BASE + 10)
-#define V4L2_CID_PRIVATE_LASTP1      (V4L2_CID_PRIVATE_BASE + 11)
-
-static const struct v4l2_queryctrl no_ctl = {
-	.name  = "42",
-	.flags = V4L2_CTRL_FLAG_DISABLED,
-};
-static const struct v4l2_queryctrl bttv_ctls[] = {
-	/* --- video --- */
-	{
-		.id            = V4L2_CID_BRIGHTNESS,
-		.name          = "Brightness",
-		.minimum       = 0,
-		.maximum       = 65535,
-		.step          = 256,
-		.default_value = 32768,
-		.type          = V4L2_CTRL_TYPE_INTEGER,
-	},{
-		.id            = V4L2_CID_CONTRAST,
-		.name          = "Contrast",
-		.minimum       = 0,
-		.maximum       = 65535,
-		.step          = 128,
-		.default_value = 27648,
-		.type          = V4L2_CTRL_TYPE_INTEGER,
-	},{
-		.id            = V4L2_CID_SATURATION,
-		.name          = "Saturation",
-		.minimum       = 0,
-		.maximum       = 65535,
-		.step          = 128,
-		.default_value = 32768,
-		.type          = V4L2_CTRL_TYPE_INTEGER,
-	},{
-		.id            = V4L2_CID_COLOR_KILLER,
-		.name          = "Color killer",
-		.minimum       = 0,
-		.maximum       = 1,
-		.type          = V4L2_CTRL_TYPE_BOOLEAN,
-	}, {
-		.id            = V4L2_CID_HUE,
-		.name          = "Hue",
-		.minimum       = 0,
-		.maximum       = 65535,
-		.step          = 256,
-		.default_value = 32768,
-		.type          = V4L2_CTRL_TYPE_INTEGER,
-	},
-	/* --- audio --- */
-	{
-		.id            = V4L2_CID_AUDIO_MUTE,
-		.name          = "Mute",
-		.minimum       = 0,
-		.maximum       = 1,
-		.type          = V4L2_CTRL_TYPE_BOOLEAN,
-	},{
-		.id            = V4L2_CID_AUDIO_VOLUME,
-		.name          = "Volume",
-		.minimum       = 0,
-		.maximum       = 65535,
-		.step          = 65535/100,
-		.default_value = 65535,
-		.type          = V4L2_CTRL_TYPE_INTEGER,
-	},{
-		.id            = V4L2_CID_AUDIO_BALANCE,
-		.name          = "Balance",
-		.minimum       = 0,
-		.maximum       = 65535,
-		.step          = 65535/100,
-		.default_value = 32768,
-		.type          = V4L2_CTRL_TYPE_INTEGER,
-	},{
-		.id            = V4L2_CID_AUDIO_BASS,
-		.name          = "Bass",
-		.minimum       = 0,
-		.maximum       = 65535,
-		.step          = 65535/100,
-		.default_value = 32768,
-		.type          = V4L2_CTRL_TYPE_INTEGER,
-	},{
-		.id            = V4L2_CID_AUDIO_TREBLE,
-		.name          = "Treble",
-		.minimum       = 0,
-		.maximum       = 65535,
-		.step          = 65535/100,
-		.default_value = 32768,
-		.type          = V4L2_CTRL_TYPE_INTEGER,
-	},
-	/* --- private --- */
-	{
-		.id            = V4L2_CID_PRIVATE_CHROMA_AGC,
-		.name          = "chroma agc",
-		.minimum       = 0,
-		.maximum       = 1,
-		.type          = V4L2_CTRL_TYPE_BOOLEAN,
-	},{
-		.id            = V4L2_CID_PRIVATE_COMBFILTER,
-		.name          = "combfilter",
-		.minimum       = 0,
-		.maximum       = 1,
-		.type          = V4L2_CTRL_TYPE_BOOLEAN,
-	},{
-		.id            = V4L2_CID_PRIVATE_AUTOMUTE,
-		.name          = "automute",
-		.minimum       = 0,
-		.maximum       = 1,
-		.type          = V4L2_CTRL_TYPE_BOOLEAN,
-	},{
-		.id            = V4L2_CID_PRIVATE_LUMAFILTER,
-		.name          = "luma decimation filter",
-		.minimum       = 0,
-		.maximum       = 1,
-		.type          = V4L2_CTRL_TYPE_BOOLEAN,
-	},{
-		.id            = V4L2_CID_PRIVATE_AGC_CRUSH,
-		.name          = "agc crush",
-		.minimum       = 0,
-		.maximum       = 1,
-		.type          = V4L2_CTRL_TYPE_BOOLEAN,
-	},{
-		.id            = V4L2_CID_PRIVATE_VCR_HACK,
-		.name          = "vcr hack",
-		.minimum       = 0,
-		.maximum       = 1,
-		.type          = V4L2_CTRL_TYPE_BOOLEAN,
-	},{
-		.id            = V4L2_CID_PRIVATE_WHITECRUSH_UPPER,
-		.name          = "whitecrush upper",
-		.minimum       = 0,
-		.maximum       = 255,
-		.step          = 1,
-		.default_value = 0xCF,
-		.type          = V4L2_CTRL_TYPE_INTEGER,
-	},{
-		.id            = V4L2_CID_PRIVATE_WHITECRUSH_LOWER,
-		.name          = "whitecrush lower",
-		.minimum       = 0,
-		.maximum       = 255,
-		.step          = 1,
-		.default_value = 0x7F,
-		.type          = V4L2_CTRL_TYPE_INTEGER,
-	},{
-		.id            = V4L2_CID_PRIVATE_UV_RATIO,
-		.name          = "uv ratio",
-		.minimum       = 0,
-		.maximum       = 100,
-		.step          = 1,
-		.default_value = 50,
-		.type          = V4L2_CTRL_TYPE_INTEGER,
-	},{
-		.id            = V4L2_CID_PRIVATE_FULL_LUMA_RANGE,
-		.name          = "full luma range",
-		.minimum       = 0,
-		.maximum       = 1,
-		.type          = V4L2_CTRL_TYPE_BOOLEAN,
-	},{
-		.id            = V4L2_CID_PRIVATE_CORING,
-		.name          = "coring",
-		.minimum       = 0,
-		.maximum       = 3,
-		.step          = 1,
-		.default_value = 0,
-		.type          = V4L2_CTRL_TYPE_INTEGER,
-	}
-
-
-
-};
-
-static const struct v4l2_queryctrl *ctrl_by_id(int id)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(bttv_ctls); i++)
-		if (bttv_ctls[i].id == id)
-			return bttv_ctls+i;
-
-	return NULL;
-}
-
-/* ----------------------------------------------------------------------- */
 /* resource management                                                     */
 
 /*
@@ -1178,23 +999,20 @@ static char *audio_modes[] = {
 	"audio: intern", "audio: mute"
 };
 
-static int
-audio_mux(struct bttv *btv, int input, int mute)
+static void
+audio_mux_gpio(struct bttv *btv, int input, int mute)
 {
-	int gpio_val, signal;
-	struct v4l2_control ctrl;
+	int gpio_val, signal, mute_gpio;
 
 	gpio_inout(bttv_tvcards[btv->c.type].gpiomask,
 		   bttv_tvcards[btv->c.type].gpiomask);
 	signal = btread(BT848_DSTATUS) & BT848_DSTATUS_HLOC;
 
-	btv->mute = mute;
-	btv->audio = input;
-
 	/* automute */
-	mute = mute || (btv->opt_automute && !signal && !btv->radio_user);
+	mute_gpio = mute || (btv->opt_automute && (!signal || !btv->users)
+				&& !btv->has_radio_tuner);
 
-	if (mute)
+	if (mute_gpio)
 		gpio_val = bttv_tvcards[btv->c.type].gpiomute;
 	else
 		gpio_val = bttv_tvcards[btv->c.type].gpiomux[input];
@@ -1210,13 +1028,39 @@ audio_mux(struct bttv *btv, int input, int mute)
 	}
 
 	if (bttv_gpio)
-		bttv_gpio_tracking(btv, audio_modes[mute ? 4 : input]);
-	if (in_interrupt())
-		return 0;
+		bttv_gpio_tracking(btv, audio_modes[mute_gpio ? 4 : input]);
+}
+
+static int
+audio_mute(struct bttv *btv, int mute)
+{
+	struct v4l2_ctrl *ctrl;
+
+	audio_mux_gpio(btv, btv->audio_input, mute);
+
+	if (btv->sd_msp34xx) {
+		ctrl = v4l2_ctrl_find(btv->sd_msp34xx->ctrl_handler, V4L2_CID_AUDIO_MUTE);
+		if (ctrl)
+			v4l2_ctrl_s_ctrl(ctrl, mute);
+	}
+	if (btv->sd_tvaudio) {
+		ctrl = v4l2_ctrl_find(btv->sd_tvaudio->ctrl_handler, V4L2_CID_AUDIO_MUTE);
+		if (ctrl)
+			v4l2_ctrl_s_ctrl(ctrl, mute);
+	}
+	if (btv->sd_tda7432) {
+		ctrl = v4l2_ctrl_find(btv->sd_tda7432->ctrl_handler, V4L2_CID_AUDIO_MUTE);
+		if (ctrl)
+			v4l2_ctrl_s_ctrl(ctrl, mute);
+	}
+	return 0;
+}
+
+static int
+audio_input(struct bttv *btv, int input)
+{
+	audio_mux_gpio(btv, input, btv->mute);
 
-	ctrl.id = V4L2_CID_AUDIO_MUTE;
-	ctrl.value = btv->mute;
-	bttv_call_all(btv, core, s_ctrl, &ctrl);
 	if (btv->sd_msp34xx) {
 		u32 in;
 
@@ -1265,23 +1109,11 @@ audio_mux(struct bttv *btv, int input, int mute)
 	}
 	if (btv->sd_tvaudio) {
 		v4l2_subdev_call(btv->sd_tvaudio, audio, s_routing,
-				input, 0, 0);
+				 input, 0, 0);
 	}
 	return 0;
 }
 
-static inline int
-audio_mute(struct bttv *btv, int mute)
-{
-	return audio_mux(btv, btv->audio, mute);
-}
-
-static inline int
-audio_input(struct bttv *btv, int input)
-{
-	return audio_mux(btv, input, btv->mute);
-}
-
 static void
 bttv_crop_calc_limits(struct bttv_crop *c)
 {
@@ -1375,8 +1207,9 @@ set_input(struct bttv *btv, unsigned int input, unsigned int norm)
 	} else {
 		video_mux(btv,input);
 	}
-	audio_input(btv, (btv->tuner_type != TUNER_ABSENT && input == 0) ?
-			 TVAUDIO_INPUT_TUNER : TVAUDIO_INPUT_EXTERN);
+	btv->audio_input = (btv->tuner_type != TUNER_ABSENT && input == 0) ?
+				TVAUDIO_INPUT_TUNER : TVAUDIO_INPUT_EXTERN;
+	audio_input(btv, btv->audio_input);
 	set_tvnorm(btv, norm);
 }
 
@@ -1404,8 +1237,6 @@ static void init_irqreg(struct bttv *btv)
 
 static void init_bt848(struct bttv *btv)
 {
-	int val;
-
 	if (bttv_tvcards[btv->c.type].no_video) {
 		/* very basic init only */
 		init_irqreg(btv);
@@ -1425,30 +1256,10 @@ static void init_bt848(struct bttv *btv)
 		BT848_GPIO_DMA_CTL_GPINTI,
 		BT848_GPIO_DMA_CTL);
 
-	val = btv->opt_chroma_agc ? BT848_SCLOOP_CAGC : 0;
-	btwrite(val, BT848_E_SCLOOP);
-	btwrite(val, BT848_O_SCLOOP);
-
 	btwrite(0x20, BT848_E_VSCALE_HI);
 	btwrite(0x20, BT848_O_VSCALE_HI);
-	btwrite(BT848_ADC_RESERVED | (btv->opt_adc_crush ? BT848_ADC_CRUSH : 0),
-		BT848_ADC);
-
-	btwrite(whitecrush_upper, BT848_WC_UP);
-	btwrite(whitecrush_lower, BT848_WC_DOWN);
-
-	if (btv->opt_lumafilter) {
-		btwrite(0, BT848_E_CONTROL);
-		btwrite(0, BT848_O_CONTROL);
-	} else {
-		btwrite(BT848_CONTROL_LDEC, BT848_E_CONTROL);
-		btwrite(BT848_CONTROL_LDEC, BT848_O_CONTROL);
-	}
 
-	bt848_bright(btv,   btv->bright);
-	bt848_hue(btv,      btv->hue);
-	bt848_contrast(btv, btv->contrast);
-	bt848_sat(btv,      btv->saturation);
+	v4l2_ctrl_handler_setup(&btv->ctrl_handler);
 
 	/* interrupt */
 	init_irqreg(btv);
@@ -1470,103 +1281,26 @@ static void bttv_reinit_bt848(struct bttv *btv)
 	set_input(btv, btv->input, btv->tvnorm);
 }
 
-static int bttv_g_ctrl(struct file *file, void *priv,
-					struct v4l2_control *c)
+static int bttv_s_ctrl(struct v4l2_ctrl *c)
 {
-	struct bttv_fh *fh = priv;
-	struct bttv *btv = fh->btv;
-
-	switch (c->id) {
-	case V4L2_CID_BRIGHTNESS:
-		c->value = btv->bright;
-		break;
-	case V4L2_CID_HUE:
-		c->value = btv->hue;
-		break;
-	case V4L2_CID_CONTRAST:
-		c->value = btv->contrast;
-		break;
-	case V4L2_CID_SATURATION:
-		c->value = btv->saturation;
-		break;
-	case V4L2_CID_COLOR_KILLER:
-		c->value = btv->opt_color_killer;
-		break;
-
-	case V4L2_CID_AUDIO_MUTE:
-	case V4L2_CID_AUDIO_VOLUME:
-	case V4L2_CID_AUDIO_BALANCE:
-	case V4L2_CID_AUDIO_BASS:
-	case V4L2_CID_AUDIO_TREBLE:
-		bttv_call_all(btv, core, g_ctrl, c);
-		break;
-
-	case V4L2_CID_PRIVATE_CHROMA_AGC:
-		c->value = btv->opt_chroma_agc;
-		break;
-	case V4L2_CID_PRIVATE_COMBFILTER:
-		c->value = btv->opt_combfilter;
-		break;
-	case V4L2_CID_PRIVATE_LUMAFILTER:
-		c->value = btv->opt_lumafilter;
-		break;
-	case V4L2_CID_PRIVATE_AUTOMUTE:
-		c->value = btv->opt_automute;
-		break;
-	case V4L2_CID_PRIVATE_AGC_CRUSH:
-		c->value = btv->opt_adc_crush;
-		break;
-	case V4L2_CID_PRIVATE_VCR_HACK:
-		c->value = btv->opt_vcr_hack;
-		break;
-	case V4L2_CID_PRIVATE_WHITECRUSH_UPPER:
-		c->value = btv->opt_whitecrush_upper;
-		break;
-	case V4L2_CID_PRIVATE_WHITECRUSH_LOWER:
-		c->value = btv->opt_whitecrush_lower;
-		break;
-	case V4L2_CID_PRIVATE_UV_RATIO:
-		c->value = btv->opt_uv_ratio;
-		break;
-	case V4L2_CID_PRIVATE_FULL_LUMA_RANGE:
-		c->value = btv->opt_full_luma_range;
-		break;
-	case V4L2_CID_PRIVATE_CORING:
-		c->value = btv->opt_coring;
-		break;
-	default:
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static int bttv_s_ctrl(struct file *file, void *f,
-					struct v4l2_control *c)
-{
-	int err;
-	struct bttv_fh *fh = f;
-	struct bttv *btv = fh->btv;
-
-	err = v4l2_prio_check(&btv->prio, fh->prio);
-	if (0 != err)
-		return err;
+	struct bttv *btv = container_of(c->handler, struct bttv, ctrl_handler);
+	int val;
 
 	switch (c->id) {
 	case V4L2_CID_BRIGHTNESS:
-		bt848_bright(btv, c->value);
+		bt848_bright(btv, c->val);
 		break;
 	case V4L2_CID_HUE:
-		bt848_hue(btv, c->value);
+		bt848_hue(btv, c->val);
 		break;
 	case V4L2_CID_CONTRAST:
-		bt848_contrast(btv, c->value);
+		bt848_contrast(btv, c->val);
 		break;
 	case V4L2_CID_SATURATION:
-		bt848_sat(btv, c->value);
+		bt848_sat(btv, c->val);
 		break;
 	case V4L2_CID_COLOR_KILLER:
-		btv->opt_color_killer = c->value;
-		if (btv->opt_color_killer) {
+		if (c->val) {
 			btor(BT848_SCLOOP_CKILL, BT848_E_SCLOOP);
 			btor(BT848_SCLOOP_CKILL, BT848_O_SCLOOP);
 		} else {
@@ -1575,36 +1309,23 @@ static int bttv_s_ctrl(struct file *file, void *f,
 		}
 		break;
 	case V4L2_CID_AUDIO_MUTE:
-		audio_mute(btv, c->value);
-		/* fall through */
-	case V4L2_CID_AUDIO_VOLUME:
-		if (btv->volume_gpio)
-			btv->volume_gpio(btv, c->value);
-
-		bttv_call_all(btv, core, s_ctrl, c);
+		audio_mute(btv, c->val);
+		btv->mute = c->val;
 		break;
-	case V4L2_CID_AUDIO_BALANCE:
-	case V4L2_CID_AUDIO_BASS:
-	case V4L2_CID_AUDIO_TREBLE:
-		bttv_call_all(btv, core, s_ctrl, c);
+	case V4L2_CID_AUDIO_VOLUME:
+		btv->volume_gpio(btv, c->val);
 		break;
 
-	case V4L2_CID_PRIVATE_CHROMA_AGC:
-		btv->opt_chroma_agc = c->value;
-		if (btv->opt_chroma_agc) {
-			btor(BT848_SCLOOP_CAGC, BT848_E_SCLOOP);
-			btor(BT848_SCLOOP_CAGC, BT848_O_SCLOOP);
-		} else {
-			btand(~BT848_SCLOOP_CAGC, BT848_E_SCLOOP);
-			btand(~BT848_SCLOOP_CAGC, BT848_O_SCLOOP);
-		}
+	case V4L2_CID_CHROMA_AGC:
+		val = c->val ? BT848_SCLOOP_CAGC : 0;
+		btwrite(val, BT848_E_SCLOOP);
+		btwrite(val, BT848_O_SCLOOP);
 		break;
 	case V4L2_CID_PRIVATE_COMBFILTER:
-		btv->opt_combfilter = c->value;
+		btv->opt_combfilter = c->val;
 		break;
 	case V4L2_CID_PRIVATE_LUMAFILTER:
-		btv->opt_lumafilter = c->value;
-		if (btv->opt_lumafilter) {
+		if (c->val) {
 			btand(~BT848_CONTROL_LDEC, BT848_E_CONTROL);
 			btand(~BT848_CONTROL_LDEC, BT848_O_CONTROL);
 		} else {
@@ -1613,36 +1334,31 @@ static int bttv_s_ctrl(struct file *file, void *f,
 		}
 		break;
 	case V4L2_CID_PRIVATE_AUTOMUTE:
-		btv->opt_automute = c->value;
+		btv->opt_automute = c->val;
 		break;
 	case V4L2_CID_PRIVATE_AGC_CRUSH:
-		btv->opt_adc_crush = c->value;
 		btwrite(BT848_ADC_RESERVED |
-				(btv->opt_adc_crush ? BT848_ADC_CRUSH : 0),
+				(c->val ? BT848_ADC_CRUSH : 0),
 				BT848_ADC);
 		break;
 	case V4L2_CID_PRIVATE_VCR_HACK:
-		btv->opt_vcr_hack = c->value;
+		btv->opt_vcr_hack = c->val;
 		break;
 	case V4L2_CID_PRIVATE_WHITECRUSH_UPPER:
-		btv->opt_whitecrush_upper = c->value;
-		btwrite(c->value, BT848_WC_UP);
+		btwrite(c->val, BT848_WC_UP);
 		break;
 	case V4L2_CID_PRIVATE_WHITECRUSH_LOWER:
-		btv->opt_whitecrush_lower = c->value;
-		btwrite(c->value, BT848_WC_DOWN);
+		btwrite(c->val, BT848_WC_DOWN);
 		break;
 	case V4L2_CID_PRIVATE_UV_RATIO:
-		btv->opt_uv_ratio = c->value;
+		btv->opt_uv_ratio = c->val;
 		bt848_sat(btv, btv->saturation);
 		break;
 	case V4L2_CID_PRIVATE_FULL_LUMA_RANGE:
-		btv->opt_full_luma_range = c->value;
-		btaor((c->value<<7), ~BT848_OFORM_RANGE, BT848_OFORM);
+		btaor((c->val << 7), ~BT848_OFORM_RANGE, BT848_OFORM);
 		break;
 	case V4L2_CID_PRIVATE_CORING:
-		btv->opt_coring = c->value;
-		btaor((c->value<<5), ~BT848_OFORM_CORE32, BT848_OFORM);
+		btaor((c->val << 5), ~BT848_OFORM_CORE32, BT848_OFORM);
 		break;
 	default:
 		return -EINVAL;
@@ -1652,6 +1368,121 @@ static int bttv_s_ctrl(struct file *file, void *f,
 
 /* ----------------------------------------------------------------------- */
 
+static const struct v4l2_ctrl_ops bttv_ctrl_ops = {
+	.s_ctrl = bttv_s_ctrl,
+};
+
+static struct v4l2_ctrl_config bttv_ctrl_combfilter = {
+	.ops = &bttv_ctrl_ops,
+	.id = V4L2_CID_PRIVATE_COMBFILTER,
+	.name = "Comb Filter",
+	.type = V4L2_CTRL_TYPE_BOOLEAN,
+	.min = 0,
+	.max = 1,
+	.step = 1,
+	.def = 1,
+};
+
+static struct v4l2_ctrl_config bttv_ctrl_automute = {
+	.ops = &bttv_ctrl_ops,
+	.id = V4L2_CID_PRIVATE_AUTOMUTE,
+	.name = "Auto Mute",
+	.type = V4L2_CTRL_TYPE_BOOLEAN,
+	.min = 0,
+	.max = 1,
+	.step = 1,
+	.def = 1,
+};
+
+static struct v4l2_ctrl_config bttv_ctrl_lumafilter = {
+	.ops = &bttv_ctrl_ops,
+	.id = V4L2_CID_PRIVATE_LUMAFILTER,
+	.name = "Luma Decimation Filter",
+	.type = V4L2_CTRL_TYPE_BOOLEAN,
+	.min = 0,
+	.max = 1,
+	.step = 1,
+	.def = 1,
+};
+
+static struct v4l2_ctrl_config bttv_ctrl_agc_crush = {
+	.ops = &bttv_ctrl_ops,
+	.id = V4L2_CID_PRIVATE_AGC_CRUSH,
+	.name = "AGC Crush",
+	.type = V4L2_CTRL_TYPE_BOOLEAN,
+	.min = 0,
+	.max = 1,
+	.step = 1,
+	.def = 1,
+};
+
+static struct v4l2_ctrl_config bttv_ctrl_vcr_hack = {
+	.ops = &bttv_ctrl_ops,
+	.id = V4L2_CID_PRIVATE_VCR_HACK,
+	.name = "VCR Hack",
+	.type = V4L2_CTRL_TYPE_BOOLEAN,
+	.min = 0,
+	.max = 1,
+	.step = 1,
+	.def = 1,
+};
+
+static struct v4l2_ctrl_config bttv_ctrl_whitecrush_lower = {
+	.ops = &bttv_ctrl_ops,
+	.id = V4L2_CID_PRIVATE_WHITECRUSH_LOWER,
+	.name = "Whitecrush Lower",
+	.type = V4L2_CTRL_TYPE_INTEGER,
+	.min = 0,
+	.max = 255,
+	.step = 1,
+	.def = 0x7f,
+};
+
+static struct v4l2_ctrl_config bttv_ctrl_whitecrush_upper = {
+	.ops = &bttv_ctrl_ops,
+	.id = V4L2_CID_PRIVATE_WHITECRUSH_UPPER,
+	.name = "Whitecrush Upper",
+	.type = V4L2_CTRL_TYPE_INTEGER,
+	.min = 0,
+	.max = 255,
+	.step = 1,
+	.def = 0xcf,
+};
+
+static struct v4l2_ctrl_config bttv_ctrl_uv_ratio = {
+	.ops = &bttv_ctrl_ops,
+	.id = V4L2_CID_PRIVATE_UV_RATIO,
+	.name = "UV Ratio",
+	.type = V4L2_CTRL_TYPE_INTEGER,
+	.min = 0,
+	.max = 100,
+	.step = 1,
+	.def = 50,
+};
+
+static struct v4l2_ctrl_config bttv_ctrl_full_luma = {
+	.ops = &bttv_ctrl_ops,
+	.id = V4L2_CID_PRIVATE_FULL_LUMA_RANGE,
+	.name = "Full Luma Range",
+	.type = V4L2_CTRL_TYPE_BOOLEAN,
+	.min = 0,
+	.max = 1,
+	.step = 1,
+};
+
+static struct v4l2_ctrl_config bttv_ctrl_coring = {
+	.ops = &bttv_ctrl_ops,
+	.id = V4L2_CID_PRIVATE_CORING,
+	.name = "Coring",
+	.type = V4L2_CTRL_TYPE_INTEGER,
+	.min = 0,
+	.max = 3,
+	.step = 1,
+};
+
+
+/* ----------------------------------------------------------------------- */
+
 void bttv_gpio_tracking(struct bttv *btv, char *comment)
 {
 	unsigned int outbits, data;
@@ -1881,25 +1712,33 @@ static struct videobuf_queue_ops bttv_video_qops = {
 	.buf_release  = buffer_release,
 };
 
-static int bttv_s_std(struct file *file, void *priv, v4l2_std_id *id)
+static void radio_enable(struct bttv *btv)
+{
+	/* Switch to the radio tuner */
+	if (!btv->has_radio_tuner) {
+		btv->has_radio_tuner = 1;
+		bttv_call_all(btv, tuner, s_radio);
+		btv->audio_input = TVAUDIO_INPUT_RADIO;
+		audio_input(btv, btv->audio_input);
+	}
+}
+
+static int bttv_s_std(struct file *file, void *priv, v4l2_std_id id)
 {
 	struct bttv_fh *fh  = priv;
 	struct bttv *btv = fh->btv;
 	unsigned int i;
-	int err;
-
-	err = v4l2_prio_check(&btv->prio, fh->prio);
-	if (err)
-		goto err;
+	int err = 0;
 
 	for (i = 0; i < BTTV_TVNORMS; i++)
-		if (*id & bttv_tvnorms[i].v4l2_id)
+		if (id & bttv_tvnorms[i].v4l2_id)
 			break;
 	if (i == BTTV_TVNORMS) {
 		err = -EINVAL;
 		goto err;
 	}
 
+	btv->std = id;
 	set_tvnorm(btv, i);
 
 err:
@@ -1907,6 +1746,15 @@ err:
 	return err;
 }
 
+static int bttv_g_std(struct file *file, void *priv, v4l2_std_id *id)
+{
+	struct bttv_fh *fh  = priv;
+	struct bttv *btv = fh->btv;
+
+	*id = btv->std;
+	return 0;
+}
+
 static int bttv_querystd(struct file *file, void *f, v4l2_std_id *id)
 {
 	struct bttv_fh *fh = f;
@@ -1932,7 +1780,7 @@ static int bttv_enum_input(struct file *file, void *priv,
 	}
 
 	i->type     = V4L2_INPUT_TYPE_CAMERA;
-	i->audioset = 1;
+	i->audioset = 0;
 
 	if (btv->tuner_type != TUNER_ABSENT && i->index == 0) {
 		sprintf(i->name, "Television");
@@ -1974,49 +1822,29 @@ static int bttv_s_input(struct file *file, void *priv, unsigned int i)
 	struct bttv_fh *fh  = priv;
 	struct bttv *btv = fh->btv;
 
-	int err;
-
-	err = v4l2_prio_check(&btv->prio, fh->prio);
-	if (unlikely(err))
-		goto err;
-
-	if (i > bttv_tvcards[btv->c.type].video_inputs) {
-		err = -EINVAL;
-		goto err;
-	}
+	if (i >= bttv_tvcards[btv->c.type].video_inputs)
+		return -EINVAL;
 
 	set_input(btv, i, btv->tvnorm);
-
-err:
 	return 0;
 }
 
 static int bttv_s_tuner(struct file *file, void *priv,
-					struct v4l2_tuner *t)
+					const struct v4l2_tuner *t)
 {
 	struct bttv_fh *fh  = priv;
 	struct bttv *btv = fh->btv;
-	int err;
 
-	if (unlikely(0 != t->index))
+	if (t->index)
 		return -EINVAL;
 
-	if (unlikely(btv->tuner_type == TUNER_ABSENT)) {
-		err = -EINVAL;
-		goto err;
-	}
-
-	err = v4l2_prio_check(&btv->prio, fh->prio);
-	if (unlikely(err))
-		goto err;
-
 	bttv_call_all(btv, tuner, s_tuner, t);
 
-	if (btv->audio_mode_gpio)
-		btv->audio_mode_gpio(btv, t, 1);
-
-err:
+	if (btv->audio_mode_gpio) {
+		struct v4l2_tuner copy = *t;
 
+		btv->audio_mode_gpio(btv, &copy, 1);
+	}
 	return 0;
 }
 
@@ -2026,49 +1854,81 @@ static int bttv_g_frequency(struct file *file, void *priv,
 	struct bttv_fh *fh  = priv;
 	struct bttv *btv = fh->btv;
 
-	f->type = btv->radio_user ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
-	f->frequency = btv->freq;
+	if (f->tuner)
+		return -EINVAL;
+
+	if (f->type == V4L2_TUNER_RADIO)
+		radio_enable(btv);
+	f->frequency = f->type == V4L2_TUNER_RADIO ?
+				btv->radio_freq : btv->tv_freq;
 
 	return 0;
 }
 
+static void bttv_set_frequency(struct bttv *btv, const struct v4l2_frequency *f)
+{
+	struct v4l2_frequency new_freq = *f;
+
+	bttv_call_all(btv, tuner, s_frequency, f);
+	/* s_frequency may clamp the frequency, so get the actual
+	   frequency before assigning radio/tv_freq. */
+	bttv_call_all(btv, tuner, g_frequency, &new_freq);
+	if (new_freq.type == V4L2_TUNER_RADIO) {
+		radio_enable(btv);
+		btv->radio_freq = new_freq.frequency;
+		if (btv->has_matchbox)
+			tea5757_set_freq(btv, btv->radio_freq);
+	} else {
+		btv->tv_freq = new_freq.frequency;
+	}
+}
+
 static int bttv_s_frequency(struct file *file, void *priv,
-					struct v4l2_frequency *f)
+					const struct v4l2_frequency *f)
 {
 	struct bttv_fh *fh  = priv;
 	struct bttv *btv = fh->btv;
-	int err;
 
-	if (unlikely(f->tuner != 0))
+	if (f->tuner)
 		return -EINVAL;
 
-	err = v4l2_prio_check(&btv->prio, fh->prio);
-	if (unlikely(err))
-		goto err;
-
-	if (unlikely(f->type != (btv->radio_user
-		? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV))) {
-		err = -EINVAL;
-		goto err;
-	}
-	btv->freq = f->frequency;
-	bttv_call_all(btv, tuner, s_frequency, f);
-	if (btv->has_matchbox && btv->radio_user)
-		tea5757_set_freq(btv, btv->freq);
-err:
-
+	bttv_set_frequency(btv, f);
 	return 0;
 }
 
 static int bttv_log_status(struct file *file, void *f)
 {
+	struct video_device *vdev = video_devdata(file);
 	struct bttv_fh *fh  = f;
 	struct bttv *btv = fh->btv;
 
+	v4l2_ctrl_handler_log_status(vdev->ctrl_handler, btv->c.v4l2_dev.name);
 	bttv_call_all(btv, core, log_status);
 	return 0;
 }
 
+static int bttv_g_chip_ident(struct file *file, void *f, struct v4l2_dbg_chip_ident *chip)
+{
+	struct bttv_fh *fh  = f;
+	struct bttv *btv = fh->btv;
+
+	chip->ident = V4L2_IDENT_NONE;
+	chip->revision = 0;
+	if (chip->match.type == V4L2_CHIP_MATCH_HOST) {
+		if (v4l2_chip_match_host(&chip->match)) {
+			chip->ident = btv->id;
+			if (chip->ident == PCI_DEVICE_ID_FUSION879)
+				chip->ident = V4L2_IDENT_BT879;
+		}
+		return 0;
+	}
+	if (chip->match.type != V4L2_CHIP_MATCH_I2C_DRIVER &&
+	    chip->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
+		return -EINVAL;
+	/* TODO: is this correct? */
+	return bttv_call_all_err(btv, core, g_chip_ident, chip);
+}
+
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 static int bttv_g_register(struct file *file, void *f,
 					struct v4l2_dbg_register *reg)
@@ -2079,8 +1939,12 @@ static int bttv_g_register(struct file *file, void *f,
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
 
-	if (!v4l2_chip_match_host(&reg->match))
-		return -EINVAL;
+	if (!v4l2_chip_match_host(&reg->match)) {
+		/* TODO: subdev errors should not be ignored, this should become a
+		   subdev helper function. */
+		bttv_call_all(btv, core, g_register, reg);
+		return 0;
+	}
 
 	/* bt848 has a 12-bit register space */
 	reg->reg &= 0xfff;
@@ -2091,7 +1955,7 @@ static int bttv_g_register(struct file *file, void *f,
 }
 
 static int bttv_s_register(struct file *file, void *f,
-					struct v4l2_dbg_register *reg)
+					const struct v4l2_dbg_register *reg)
 {
 	struct bttv_fh *fh = f;
 	struct bttv *btv = fh->btv;
@@ -2099,12 +1963,15 @@ static int bttv_s_register(struct file *file, void *f,
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
 
-	if (!v4l2_chip_match_host(&reg->match))
-		return -EINVAL;
+	if (!v4l2_chip_match_host(&reg->match)) {
+		/* TODO: subdev errors should not be ignored, this should become a
+		   subdev helper function. */
+		bttv_call_all(btv, core, s_register, reg);
+		return 0;
+	}
 
 	/* bt848 has a 12-bit register space */
-	reg->reg &= 0xfff;
-	btwrite(reg->val, reg->reg);
+	btwrite(reg->val, reg->reg & 0xfff);
 
 	return 0;
 }
@@ -2273,22 +2140,33 @@ limit_scaled_size_lock       (struct bttv_fh *               fh,
    may also adjust the current cropping parameters to get closer
    to the desired window size. */
 static int
-verify_window_lock		(struct bttv_fh *               fh,
-			 struct v4l2_window *           win,
-			 int                            adjust_size,
-			 int                            adjust_crop)
+verify_window_lock(struct bttv_fh *fh, struct v4l2_window *win,
+			 int adjust_size, int adjust_crop)
 {
 	enum v4l2_field field;
 	unsigned int width_mask;
 	int rc;
 
-	if (win->w.width  < 48 || win->w.height < 32)
-		return -EINVAL;
+	if (win->w.width < 48)
+		win->w.width = 48;
+	if (win->w.height < 32)
+		win->w.height = 32;
 	if (win->clipcount > 2048)
-		return -EINVAL;
+		win->clipcount = 2048;
 
+	win->chromakey = 0;
+	win->global_alpha = 0;
 	field = win->field;
 
+	switch (field) {
+	case V4L2_FIELD_TOP:
+	case V4L2_FIELD_BOTTOM:
+	case V4L2_FIELD_INTERLACED:
+		break;
+	default:
+		field = V4L2_FIELD_ANY;
+		break;
+	}
 	if (V4L2_FIELD_ANY == field) {
 		__s32 height2;
 
@@ -2297,18 +2175,11 @@ verify_window_lock		(struct bttv_fh *               fh,
 			? V4L2_FIELD_INTERLACED
 			: V4L2_FIELD_TOP;
 	}
-	switch (field) {
-	case V4L2_FIELD_TOP:
-	case V4L2_FIELD_BOTTOM:
-	case V4L2_FIELD_INTERLACED:
-		break;
-	default:
-		return -EINVAL;
-	}
+	win->field = field;
 
-	/* 4-byte alignment. */
 	if (NULL == fh->ovfmt)
 		return -EINVAL;
+	/* 4-byte alignment. */
 	width_mask = ~0;
 	switch (fh->ovfmt->depth) {
 	case 8:
@@ -2333,8 +2204,6 @@ verify_window_lock		(struct bttv_fh *               fh,
 			       adjust_size, adjust_crop);
 	if (0 != rc)
 		return rc;
-
-	win->field = field;
 	return 0;
 }
 
@@ -2491,6 +2360,7 @@ static int bttv_g_fmt_vid_cap(struct file *file, void *priv,
 				fh->width, fh->height);
 	f->fmt.pix.field        = fh->cap.field;
 	f->fmt.pix.pixelformat  = fh->fmt->fourcc;
+	f->fmt.pix.colorspace   = V4L2_COLORSPACE_SMPTE170M;
 
 	return 0;
 }
@@ -2514,6 +2384,7 @@ static int bttv_try_fmt_vid_cap(struct file *file, void *priv,
 	struct bttv *btv = fh->btv;
 	enum v4l2_field field;
 	__s32 width, height;
+	__s32 height2;
 	int rc;
 
 	fmt = format_by_fourcc(f->fmt.pix.pixelformat);
@@ -2522,30 +2393,25 @@ static int bttv_try_fmt_vid_cap(struct file *file, void *priv,
 
 	field = f->fmt.pix.field;
 
-	if (V4L2_FIELD_ANY == field) {
-		__s32 height2;
-
-		height2 = btv->crop[!!fh->do_crop].rect.height >> 1;
-		field = (f->fmt.pix.height > height2)
-			? V4L2_FIELD_INTERLACED
-			: V4L2_FIELD_BOTTOM;
-	}
-
-	if (V4L2_FIELD_SEQ_BT == field)
-		field = V4L2_FIELD_SEQ_TB;
-
 	switch (field) {
 	case V4L2_FIELD_TOP:
 	case V4L2_FIELD_BOTTOM:
 	case V4L2_FIELD_ALTERNATE:
 	case V4L2_FIELD_INTERLACED:
 		break;
+	case V4L2_FIELD_SEQ_BT:
 	case V4L2_FIELD_SEQ_TB:
-		if (fmt->flags & FORMAT_FLAGS_PLANAR)
-			return -EINVAL;
+		if (!(fmt->flags & FORMAT_FLAGS_PLANAR)) {
+			field = V4L2_FIELD_SEQ_TB;
+			break;
+		}
+		/* fall through */
+	default: /* FIELD_ANY case */
+		height2 = btv->crop[!!fh->do_crop].rect.height >> 1;
+		field = (f->fmt.pix.height > height2)
+			? V4L2_FIELD_INTERLACED
+			: V4L2_FIELD_BOTTOM;
 		break;
-	default:
-		return -EINVAL;
 	}
 
 	width = f->fmt.pix.width;
@@ -2562,6 +2428,7 @@ static int bttv_try_fmt_vid_cap(struct file *file, void *priv,
 	/* update data for the application */
 	f->fmt.pix.field = field;
 	pix_format_set_size(&f->fmt.pix, fmt, width, height);
+	f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
 
 	return 0;
 }
@@ -2571,9 +2438,10 @@ static int bttv_try_fmt_vid_overlay(struct file *file, void *priv,
 {
 	struct bttv_fh *fh = priv;
 
-	return verify_window_lock(fh, &f->fmt.win,
+	verify_window_lock(fh, &f->fmt.win,
 			/* adjust_size */ 1,
 			/* adjust_crop */ 0);
+	return 0;
 }
 
 static int bttv_s_fmt_vid_cap(struct file *file, void *priv,
@@ -2640,6 +2508,7 @@ static int bttv_s_fmt_vid_overlay(struct file *file, void *priv,
 static int bttv_querycap(struct file *file, void  *priv,
 				struct v4l2_capability *cap)
 {
+	struct video_device *vdev = video_devdata(file);
 	struct bttv_fh *fh = priv;
 	struct bttv *btv = fh->btv;
 
@@ -2652,11 +2521,15 @@ static int bttv_querycap(struct file *file, void  *priv,
 		 "PCI:%s", pci_name(btv->c.pci));
 	cap->capabilities =
 		V4L2_CAP_VIDEO_CAPTURE |
-		V4L2_CAP_VBI_CAPTURE |
 		V4L2_CAP_READWRITE |
-		V4L2_CAP_STREAMING;
+		V4L2_CAP_STREAMING |
+		V4L2_CAP_DEVICE_CAPS;
 	if (no_overlay <= 0)
 		cap->capabilities |= V4L2_CAP_VIDEO_OVERLAY;
+	if (btv->vbi_dev)
+		cap->capabilities |= V4L2_CAP_VBI_CAPTURE;
+	if (btv->radio_dev)
+		cap->capabilities |= V4L2_CAP_RADIO;
 
 	/*
 	 * No need to lock here: those vars are initialized during board
@@ -2666,6 +2539,25 @@ static int bttv_querycap(struct file *file, void  *priv,
 		cap->capabilities |= V4L2_CAP_RDS_CAPTURE;
 	if (btv->tuner_type != TUNER_ABSENT)
 		cap->capabilities |= V4L2_CAP_TUNER;
+	if (vdev->vfl_type == VFL_TYPE_GRABBER)
+		cap->device_caps = cap->capabilities &
+			(V4L2_CAP_VIDEO_CAPTURE |
+			 V4L2_CAP_READWRITE |
+			 V4L2_CAP_STREAMING |
+			 V4L2_CAP_VIDEO_OVERLAY |
+			 V4L2_CAP_TUNER);
+	else if (vdev->vfl_type == VFL_TYPE_VBI)
+		cap->device_caps = cap->capabilities &
+			(V4L2_CAP_VBI_CAPTURE |
+			 V4L2_CAP_READWRITE |
+			 V4L2_CAP_STREAMING |
+			 V4L2_CAP_TUNER);
+	else {
+		cap->device_caps = V4L2_CAP_RADIO | V4L2_CAP_TUNER;
+		if (btv->has_saa6588)
+			cap->device_caps |= V4L2_CAP_READWRITE |
+						V4L2_CAP_RDS_CAPTURE;
+	}
 	return 0;
 }
 
@@ -2728,6 +2620,7 @@ static int bttv_g_fbuf(struct file *file, void *f,
 
 	*fb = btv->fbuf;
 	fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING;
+	fb->flags = V4L2_FBUF_FLAG_PRIMARY;
 	if (fh->ovfmt)
 		fb->fmt.pixelformat  = fh->ovfmt->fourcc;
 	return 0;
@@ -2901,36 +2794,15 @@ static int bttv_streamoff(struct file *file, void *priv,
 	return 0;
 }
 
-static int bttv_queryctrl(struct file *file, void *priv,
-					struct v4l2_queryctrl *c)
-{
-	struct bttv_fh *fh = priv;
-	struct bttv *btv = fh->btv;
-	const struct v4l2_queryctrl *ctrl;
-
-	if ((c->id <  V4L2_CID_BASE ||
-	     c->id >= V4L2_CID_LASTP1) &&
-	    (c->id <  V4L2_CID_PRIVATE_BASE ||
-	     c->id >= V4L2_CID_PRIVATE_LASTP1))
-		return -EINVAL;
-
-	if (!btv->volume_gpio && (c->id == V4L2_CID_AUDIO_VOLUME))
-		*c = no_ctl;
-	else {
-		ctrl = ctrl_by_id(c->id);
-
-		*c = (NULL != ctrl) ? *ctrl : no_ctl;
-	}
-
-	return 0;
-}
-
 static int bttv_g_parm(struct file *file, void *f,
 				struct v4l2_streamparm *parm)
 {
 	struct bttv_fh *fh = f;
 	struct bttv *btv = fh->btv;
 
+	if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+	parm->parm.capture.readbuffers = gbuffers;
 	v4l2_video_std_frame_period(bttv_tvnorms[btv->tvnorm].v4l2_id,
 				    &parm->parm.capture.timeperframe);
 
@@ -2943,15 +2815,13 @@ static int bttv_g_tuner(struct file *file, void *priv,
 	struct bttv_fh *fh = priv;
 	struct bttv *btv = fh->btv;
 
-	if (btv->tuner_type == TUNER_ABSENT)
-		return -EINVAL;
 	if (0 != t->index)
 		return -EINVAL;
 
 	t->rxsubchans = V4L2_TUNER_SUB_MONO;
+	t->capability = V4L2_TUNER_CAP_NORM;
 	bttv_call_all(btv, tuner, g_tuner, t);
 	strcpy(t->name, "Television");
-	t->capability = V4L2_TUNER_CAP_NORM;
 	t->type       = V4L2_TUNER_ANALOG_TV;
 	if (btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC)
 		t->signal = 0xffff;
@@ -2962,28 +2832,6 @@ static int bttv_g_tuner(struct file *file, void *priv,
 	return 0;
 }
 
-static int bttv_g_priority(struct file *file, void *f, enum v4l2_priority *p)
-{
-	struct bttv_fh *fh = f;
-	struct bttv *btv = fh->btv;
-
-	*p = v4l2_prio_max(&btv->prio);
-
-	return 0;
-}
-
-static int bttv_s_priority(struct file *file, void *f,
-					enum v4l2_priority prio)
-{
-	struct bttv_fh *fh = f;
-	struct bttv *btv = fh->btv;
-	int	rc;
-
-	rc = v4l2_prio_change(&btv->prio, &fh->prio, prio);
-
-	return rc;
-}
-
 static int bttv_cropcap(struct file *file, void *priv,
 				struct v4l2_cropcap *cap)
 {
@@ -3036,11 +2884,6 @@ static int bttv_s_crop(struct file *file, void *f, const struct v4l2_crop *crop)
 	/* Make sure tvnorm, vbi_end and the current cropping
 	   parameters remain consistent until we're done. Note
 	   read() may change vbi_end in check_alloc_btres_lock(). */
-	retval = v4l2_prio_check(&btv->prio, fh->prio);
-	if (0 != retval) {
-		return retval;
-	}
-
 	retval = -EBUSY;
 
 	if (locked_btres(fh->btv, VIDEO_RESOURCES)) {
@@ -3098,23 +2941,6 @@ static int bttv_s_crop(struct file *file, void *f, const struct v4l2_crop *crop)
 	return 0;
 }
 
-static int bttv_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
-{
-	if (unlikely(a->index))
-		return -EINVAL;
-
-	strcpy(a->name, "audio");
-	return 0;
-}
-
-static int bttv_s_audio(struct file *file, void *priv, const struct v4l2_audio *a)
-{
-	if (unlikely(a->index))
-		return -EINVAL;
-
-	return 0;
-}
-
 static ssize_t bttv_read(struct file *file, char __user *data,
 			 size_t count, loff_t *ppos)
 {
@@ -3154,34 +2980,43 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait)
 	struct bttv_fh *fh = file->private_data;
 	struct bttv_buffer *buf;
 	enum v4l2_field field;
-	unsigned int rc = POLLERR;
+	unsigned int rc = 0;
+	unsigned long req_events = poll_requested_events(wait);
+
+	if (v4l2_event_pending(&fh->fh))
+		rc = POLLPRI;
+	else if (req_events & POLLPRI)
+		poll_wait(file, &fh->fh.wait, wait);
+
+	if (!(req_events & (POLLIN | POLLRDNORM)))
+		return rc;
 
 	if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) {
 		if (!check_alloc_btres_lock(fh->btv,fh,RESOURCE_VBI))
-			return POLLERR;
-		return videobuf_poll_stream(file, &fh->vbi, wait);
+			return rc | POLLERR;
+		return rc | videobuf_poll_stream(file, &fh->vbi, wait);
 	}
 
 	if (check_btres(fh,RESOURCE_VIDEO_STREAM)) {
 		/* streaming capture */
 		if (list_empty(&fh->cap.stream))
-			goto err;
+			return rc | POLLERR;
 		buf = list_entry(fh->cap.stream.next,struct bttv_buffer,vb.stream);
 	} else {
 		/* read() capture */
 		if (NULL == fh->cap.read_buf) {
 			/* need to capture a new frame */
 			if (locked_btres(fh->btv,RESOURCE_VIDEO_STREAM))
-				goto err;
+				return rc | POLLERR;
 			fh->cap.read_buf = videobuf_sg_alloc(fh->cap.msize);
 			if (NULL == fh->cap.read_buf)
-				goto err;
+				return rc | POLLERR;
 			fh->cap.read_buf->memory = V4L2_MEMORY_USERPTR;
 			field = videobuf_next_field(&fh->cap);
 			if (0 != fh->cap.ops->buf_prepare(&fh->cap,fh->cap.read_buf,field)) {
 				kfree (fh->cap.read_buf);
 				fh->cap.read_buf = NULL;
-				goto err;
+				return rc | POLLERR;
 			}
 			fh->cap.ops->buf_queue(&fh->cap,fh->cap.read_buf);
 			fh->cap.read_off = 0;
@@ -3192,10 +3027,7 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait)
 	poll_wait(file, &buf->vb.done, wait);
 	if (buf->vb.state == VIDEOBUF_DONE ||
 	    buf->vb.state == VIDEOBUF_ERROR)
-		rc =  POLLIN|POLLRDNORM;
-	else
-		rc = 0;
-err:
+		rc = rc | POLLIN|POLLRDNORM;
 	return rc;
 }
 
@@ -3224,15 +3056,15 @@ static int bttv_open(struct file *file)
 	fh = kmalloc(sizeof(*fh), GFP_KERNEL);
 	if (unlikely(!fh))
 		return -ENOMEM;
+	btv->users++;
 	file->private_data = fh;
 
 	*fh = btv->init;
+	v4l2_fh_init(&fh->fh, vdev);
 
 	fh->type = type;
 	fh->ov.setup_ok = 0;
 
-	v4l2_prio_open(&btv->prio, &fh->prio);
-
 	videobuf_queue_sg_init(&fh->cap, &bttv_video_qops,
 			    &btv->c.pci->dev, &btv->s_lock,
 			    V4L2_BUF_TYPE_VIDEO_CAPTURE,
@@ -3247,8 +3079,7 @@ static int bttv_open(struct file *file)
 			    fh, &btv->lock);
 	set_tvnorm(btv,btv->tvnorm);
 	set_input(btv, btv->input, btv->tvnorm);
-
-	btv->users++;
+	audio_mute(btv, btv->mute);
 
 	/* The V4L2 spec requires one global set of cropping parameters
 	   which only change on request. These are stored in btv->crop[1].
@@ -3267,6 +3098,7 @@ static int bttv_open(struct file *file)
 	bttv_vbi_fmt_reset(&fh->vbi_fmt, btv->tvnorm);
 
 	bttv_field_count(btv);
+	v4l2_fh_add(&fh->fh);
 	return 0;
 }
 
@@ -3302,16 +3134,17 @@ static int bttv_release(struct file *file)
 
 	videobuf_mmap_free(&fh->cap);
 	videobuf_mmap_free(&fh->vbi);
-	v4l2_prio_close(&btv->prio, fh->prio);
 	file->private_data = NULL;
-	kfree(fh);
 
 	btv->users--;
 	bttv_field_count(btv);
 
 	if (!btv->users)
-		audio_mute(btv, 1);
+		audio_mute(btv, btv->mute);
 
+	v4l2_fh_del(&fh->fh);
+	v4l2_fh_exit(&fh->fh);
+	kfree(fh);
 	return 0;
 }
 
@@ -3350,20 +3183,16 @@ static const struct v4l2_ioctl_ops bttv_ioctl_ops = {
 	.vidioc_g_fmt_vbi_cap           = bttv_g_fmt_vbi_cap,
 	.vidioc_try_fmt_vbi_cap         = bttv_try_fmt_vbi_cap,
 	.vidioc_s_fmt_vbi_cap           = bttv_s_fmt_vbi_cap,
-	.vidioc_g_audio                 = bttv_g_audio,
-	.vidioc_s_audio                 = bttv_s_audio,
 	.vidioc_cropcap                 = bttv_cropcap,
 	.vidioc_reqbufs                 = bttv_reqbufs,
 	.vidioc_querybuf                = bttv_querybuf,
 	.vidioc_qbuf                    = bttv_qbuf,
 	.vidioc_dqbuf                   = bttv_dqbuf,
 	.vidioc_s_std                   = bttv_s_std,
+	.vidioc_g_std                   = bttv_g_std,
 	.vidioc_enum_input              = bttv_enum_input,
 	.vidioc_g_input                 = bttv_g_input,
 	.vidioc_s_input                 = bttv_s_input,
-	.vidioc_queryctrl               = bttv_queryctrl,
-	.vidioc_g_ctrl                  = bttv_g_ctrl,
-	.vidioc_s_ctrl                  = bttv_s_ctrl,
 	.vidioc_streamon                = bttv_streamon,
 	.vidioc_streamoff               = bttv_streamoff,
 	.vidioc_g_tuner                 = bttv_g_tuner,
@@ -3373,13 +3202,14 @@ static const struct v4l2_ioctl_ops bttv_ioctl_ops = {
 	.vidioc_g_fbuf                  = bttv_g_fbuf,
 	.vidioc_s_fbuf                  = bttv_s_fbuf,
 	.vidioc_overlay                 = bttv_overlay,
-	.vidioc_g_priority              = bttv_g_priority,
-	.vidioc_s_priority              = bttv_s_priority,
 	.vidioc_g_parm                  = bttv_g_parm,
 	.vidioc_g_frequency             = bttv_g_frequency,
 	.vidioc_s_frequency             = bttv_s_frequency,
 	.vidioc_log_status		= bttv_log_status,
 	.vidioc_querystd		= bttv_querystd,
+	.vidioc_subscribe_event		= v4l2_ctrl_subscribe_event,
+	.vidioc_unsubscribe_event	= v4l2_event_unsubscribe,
+	.vidioc_g_chip_ident		= bttv_g_chip_ident,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 	.vidioc_g_register		= bttv_g_register,
 	.vidioc_s_register		= bttv_s_register,
@@ -3390,7 +3220,6 @@ static struct video_device bttv_video_template = {
 	.fops         = &bttv_fops,
 	.ioctl_ops    = &bttv_ioctl_ops,
 	.tvnorms      = BTTV_NORMS,
-	.current_norm = V4L2_STD_PAL,
 };
 
 /* ----------------------------------------------------------------------- */
@@ -3412,13 +3241,12 @@ static int radio_open(struct file *file)
 		return -ENOMEM;
 	file->private_data = fh;
 	*fh = btv->init;
-
-	v4l2_prio_open(&btv->prio, &fh->prio);
+	v4l2_fh_init(&fh->fh, vdev);
 
 	btv->radio_user++;
+	audio_mute(btv, btv->mute);
 
-	bttv_call_all(btv, tuner, s_radio);
-	audio_input(btv,TVAUDIO_INPUT_RADIO);
+	v4l2_fh_add(&fh->fh);
 
 	return 0;
 }
@@ -3429,28 +3257,17 @@ static int radio_release(struct file *file)
 	struct bttv *btv = fh->btv;
 	struct saa6588_command cmd;
 
-	v4l2_prio_close(&btv->prio, fh->prio);
 	file->private_data = NULL;
+	v4l2_fh_del(&fh->fh);
+	v4l2_fh_exit(&fh->fh);
 	kfree(fh);
 
 	btv->radio_user--;
 
 	bttv_call_all(btv, core, ioctl, SAA6588_CMD_CLOSE, &cmd);
 
-	return 0;
-}
-
-static int radio_querycap(struct file *file, void *priv,
-					struct v4l2_capability *cap)
-{
-	struct bttv_fh *fh = priv;
-	struct bttv *btv = fh->btv;
-
-	strcpy(cap->driver, "bttv");
-	strlcpy(cap->card, btv->radio_dev->name, sizeof(cap->card));
-	sprintf(cap->bus_info, "PCI:%s", pci_name(btv->c.pci));
-	cap->capabilities = V4L2_CAP_TUNER;
-
+	if (btv->radio_user == 0)
+		btv->has_radio_tuner = 0;
 	return 0;
 }
 
@@ -3459,12 +3276,11 @@ static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
 	struct bttv_fh *fh = priv;
 	struct bttv *btv = fh->btv;
 
-	if (btv->tuner_type == TUNER_ABSENT)
-		return -EINVAL;
 	if (0 != t->index)
 		return -EINVAL;
 	strcpy(t->name, "Radio");
 	t->type = V4L2_TUNER_RADIO;
+	radio_enable(btv);
 
 	bttv_call_all(btv, tuner, g_tuner, t);
 
@@ -3474,31 +3290,8 @@ static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
 	return 0;
 }
 
-static int radio_enum_input(struct file *file, void *priv,
-				struct v4l2_input *i)
-{
-	if (i->index != 0)
-		return -EINVAL;
-
-	strcpy(i->name, "Radio");
-	i->type = V4L2_INPUT_TYPE_TUNER;
-
-	return 0;
-}
-
-static int radio_g_audio(struct file *file, void *priv,
-					struct v4l2_audio *a)
-{
-	if (unlikely(a->index))
-		return -EINVAL;
-
-	strcpy(a->name, "Radio");
-
-	return 0;
-}
-
 static int radio_s_tuner(struct file *file, void *priv,
-					struct v4l2_tuner *t)
+					const struct v4l2_tuner *t)
 {
 	struct bttv_fh *fh = priv;
 	struct bttv *btv = fh->btv;
@@ -3506,56 +3299,11 @@ static int radio_s_tuner(struct file *file, void *priv,
 	if (0 != t->index)
 		return -EINVAL;
 
+	radio_enable(btv);
 	bttv_call_all(btv, tuner, s_tuner, t);
 	return 0;
 }
 
-static int radio_s_audio(struct file *file, void *priv,
-					const struct v4l2_audio *a)
-{
-	if (unlikely(a->index))
-		return -EINVAL;
-
-	return 0;
-}
-
-static int radio_s_input(struct file *filp, void *priv, unsigned int i)
-{
-	if (unlikely(i))
-		return -EINVAL;
-
-	return 0;
-}
-
-static int radio_s_std(struct file *file, void *fh, v4l2_std_id *norm)
-{
-	return 0;
-}
-
-static int radio_queryctrl(struct file *file, void *priv,
-					struct v4l2_queryctrl *c)
-{
-	const struct v4l2_queryctrl *ctrl;
-
-	if (c->id <  V4L2_CID_BASE ||
-			c->id >= V4L2_CID_LASTP1)
-		return -EINVAL;
-
-	if (c->id == V4L2_CID_AUDIO_MUTE) {
-		ctrl = ctrl_by_id(c->id);
-		*c = *ctrl;
-	} else
-		*c = no_ctl;
-
-	return 0;
-}
-
-static int radio_g_input(struct file *filp, void *priv, unsigned int *i)
-{
-	*i = 0;
-	return 0;
-}
-
 static ssize_t radio_read(struct file *file, char __user *data,
 			 size_t count, loff_t *ppos)
 {
@@ -3566,6 +3314,7 @@ static ssize_t radio_read(struct file *file, char __user *data,
 	cmd.buffer = data;
 	cmd.instance = file;
 	cmd.result = -ENODEV;
+	radio_enable(btv);
 
 	bttv_call_all(btv, core, ioctl, SAA6588_CMD_READ, &cmd);
 
@@ -3576,10 +3325,18 @@ static unsigned int radio_poll(struct file *file, poll_table *wait)
 {
 	struct bttv_fh *fh = file->private_data;
 	struct bttv *btv = fh->btv;
+	unsigned long req_events = poll_requested_events(wait);
 	struct saa6588_command cmd;
+	unsigned int res = 0;
+
+	if (v4l2_event_pending(&fh->fh))
+		res = POLLPRI;
+	else if (req_events & POLLPRI)
+		poll_wait(file, &fh->fh.wait, wait);
+	radio_enable(btv);
 	cmd.instance = file;
 	cmd.event_list = wait;
-	cmd.result = -ENODEV;
+	cmd.result = res;
 	bttv_call_all(btv, core, ioctl, SAA6588_CMD_POLL, &cmd);
 
 	return cmd.result;
@@ -3596,20 +3353,14 @@ static const struct v4l2_file_operations radio_fops =
 };
 
 static const struct v4l2_ioctl_ops radio_ioctl_ops = {
-	.vidioc_querycap        = radio_querycap,
+	.vidioc_querycap        = bttv_querycap,
+	.vidioc_log_status	= bttv_log_status,
 	.vidioc_g_tuner         = radio_g_tuner,
-	.vidioc_enum_input      = radio_enum_input,
-	.vidioc_g_audio         = radio_g_audio,
 	.vidioc_s_tuner         = radio_s_tuner,
-	.vidioc_s_audio         = radio_s_audio,
-	.vidioc_s_input         = radio_s_input,
-	.vidioc_s_std           = radio_s_std,
-	.vidioc_queryctrl       = radio_queryctrl,
-	.vidioc_g_input         = radio_g_input,
-	.vidioc_g_ctrl          = bttv_g_ctrl,
-	.vidioc_s_ctrl          = bttv_s_ctrl,
 	.vidioc_g_frequency     = bttv_g_frequency,
 	.vidioc_s_frequency     = bttv_s_frequency,
+	.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
+	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
 };
 
 static struct video_device radio_template = {
@@ -4112,7 +3863,8 @@ static irqreturn_t bttv_irq(int irq, void *dev_id)
 			bttv_irq_switch_video(btv);
 
 		if ((astat & BT848_INT_HLOCK)  &&  btv->opt_automute)
-			audio_mute(btv, btv->mute);  /* trigger automute */
+			/* trigger automute */
+			audio_mux_gpio(btv, btv->audio_input, btv->mute);
 
 		if (astat & (BT848_INT_SCERR|BT848_INT_OCERR)) {
 			pr_info("%d: %s%s @ %08x,",
@@ -4161,7 +3913,7 @@ static irqreturn_t bttv_irq(int irq, void *dev_id)
 
 
 /* ----------------------------------------------------------------------- */
-/* initialitation                                                          */
+/* initialization                                                          */
 
 static struct video_device *vdev_init(struct bttv *btv,
 				      const struct video_device *template,
@@ -4176,10 +3928,17 @@ static struct video_device *vdev_init(struct bttv *btv,
 	vfd->v4l2_dev = &btv->c.v4l2_dev;
 	vfd->release = video_device_release;
 	vfd->debug   = bttv_debug;
+	set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
 	video_set_drvdata(vfd, btv);
 	snprintf(vfd->name, sizeof(vfd->name), "BT%d%s %s (%s)",
 		 btv->id, (btv->id==848 && btv->revision==0x12) ? "A" : "",
 		 type_name, bttv_tvcards[btv->c.type].name);
+	if (btv->tuner_type == TUNER_ABSENT) {
+		v4l2_disable_ioctl(vfd, VIDIOC_G_FREQUENCY);
+		v4l2_disable_ioctl(vfd, VIDIOC_S_FREQUENCY);
+		v4l2_disable_ioctl(vfd, VIDIOC_G_TUNER);
+		v4l2_disable_ioctl(vfd, VIDIOC_S_TUNER);
+	}
 	return vfd;
 }
 
@@ -4247,6 +4006,7 @@ static int bttv_register_video(struct bttv *btv)
 	btv->radio_dev = vdev_init(btv, &radio_template, "radio");
 	if (NULL == btv->radio_dev)
 		goto err;
+	btv->radio_dev->ctrl_handler = &btv->radio_ctrl_handler;
 	if (video_register_device(btv->radio_dev, VFL_TYPE_RADIO,
 				  radio_nr[btv->c.nr]) < 0)
 		goto err;
@@ -4277,9 +4037,15 @@ static void pci_set_command(struct pci_dev *dev)
 
 static int bttv_probe(struct pci_dev *dev, const struct pci_device_id *pci_id)
 {
+	struct v4l2_frequency init_freq = {
+		.tuner = 0,
+		.type = V4L2_TUNER_ANALOG_TV,
+		.frequency = 980,
+	};
 	int result;
 	unsigned char lat;
 	struct bttv *btv;
+	struct v4l2_ctrl_handler *hdl;
 
 	if (bttv_num == BTTV_MAX)
 		return -ENOMEM;
@@ -4301,7 +4067,6 @@ static int bttv_probe(struct pci_dev *dev, const struct pci_device_id *pci_id)
 	INIT_LIST_HEAD(&btv->c.subs);
 	INIT_LIST_HEAD(&btv->capture);
 	INIT_LIST_HEAD(&btv->vcapture);
-	v4l2_prio_init(&btv->prio);
 
 	init_timer(&btv->timeout);
 	btv->timeout.function = bttv_irq_timeout;
@@ -4339,6 +4104,10 @@ static int bttv_probe(struct pci_dev *dev, const struct pci_device_id *pci_id)
 		pr_warn("%d: v4l2_device_register() failed\n", btv->c.nr);
 		goto fail0;
 	}
+	hdl = &btv->ctrl_handler;
+	v4l2_ctrl_handler_init(hdl, 20);
+	btv->c.v4l2_dev.ctrl_handler = hdl;
+	v4l2_ctrl_handler_init(&btv->radio_ctrl_handler, 6);
 
 	btv->revision = dev->revision;
 	pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
@@ -4375,16 +4144,19 @@ static int bttv_probe(struct pci_dev *dev, const struct pci_device_id *pci_id)
 
 	/* init options from insmod args */
 	btv->opt_combfilter = combfilter;
-	btv->opt_lumafilter = lumafilter;
+	bttv_ctrl_combfilter.def = combfilter;
+	bttv_ctrl_lumafilter.def = lumafilter;
 	btv->opt_automute   = automute;
-	btv->opt_chroma_agc = chroma_agc;
-	btv->opt_adc_crush  = adc_crush;
+	bttv_ctrl_automute.def = automute;
+	bttv_ctrl_agc_crush.def = agc_crush;
 	btv->opt_vcr_hack   = vcr_hack;
-	btv->opt_whitecrush_upper  = whitecrush_upper;
-	btv->opt_whitecrush_lower  = whitecrush_lower;
+	bttv_ctrl_vcr_hack.def = vcr_hack;
+	bttv_ctrl_whitecrush_upper.def = whitecrush_upper;
+	bttv_ctrl_whitecrush_lower.def = whitecrush_lower;
 	btv->opt_uv_ratio   = uv_ratio;
-	btv->opt_full_luma_range   = full_luma_range;
-	btv->opt_coring     = coring;
+	bttv_ctrl_uv_ratio.def = uv_ratio;
+	bttv_ctrl_full_luma.def = full_luma_range;
+	bttv_ctrl_coring.def = coring;
 
 	/* fill struct bttv with some useful defaults */
 	btv->init.btv         = btv;
@@ -4393,8 +4165,39 @@ static int bttv_probe(struct pci_dev *dev, const struct pci_device_id *pci_id)
 	btv->init.fmt         = format_by_fourcc(V4L2_PIX_FMT_BGR24);
 	btv->init.width       = 320;
 	btv->init.height      = 240;
+	btv->init.ov.w.width  = 320;
+	btv->init.ov.w.height = 240;
+	btv->init.ov.field    = V4L2_FIELD_INTERLACED;
 	btv->input = 0;
 
+	v4l2_ctrl_new_std(hdl, &bttv_ctrl_ops,
+			V4L2_CID_BRIGHTNESS, 0, 0xff00, 0x100, 32768);
+	v4l2_ctrl_new_std(hdl, &bttv_ctrl_ops,
+			V4L2_CID_CONTRAST, 0, 0xff80, 0x80, 0x6c00);
+	v4l2_ctrl_new_std(hdl, &bttv_ctrl_ops,
+			V4L2_CID_SATURATION, 0, 0xff80, 0x80, 32768);
+	v4l2_ctrl_new_std(hdl, &bttv_ctrl_ops,
+			V4L2_CID_COLOR_KILLER, 0, 1, 1, 0);
+	v4l2_ctrl_new_std(hdl, &bttv_ctrl_ops,
+			V4L2_CID_HUE, 0, 0xff00, 0x100, 32768);
+	v4l2_ctrl_new_std(hdl, &bttv_ctrl_ops,
+			V4L2_CID_CHROMA_AGC, 0, 1, 1, !!chroma_agc);
+	v4l2_ctrl_new_std(hdl, &bttv_ctrl_ops,
+		V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
+	if (btv->volume_gpio)
+		v4l2_ctrl_new_std(hdl, &bttv_ctrl_ops,
+			V4L2_CID_AUDIO_VOLUME, 0, 0xff00, 0x100, 0xff00);
+	v4l2_ctrl_new_custom(hdl, &bttv_ctrl_combfilter, NULL);
+	v4l2_ctrl_new_custom(hdl, &bttv_ctrl_automute, NULL);
+	v4l2_ctrl_new_custom(hdl, &bttv_ctrl_lumafilter, NULL);
+	v4l2_ctrl_new_custom(hdl, &bttv_ctrl_agc_crush, NULL);
+	v4l2_ctrl_new_custom(hdl, &bttv_ctrl_vcr_hack, NULL);
+	v4l2_ctrl_new_custom(hdl, &bttv_ctrl_whitecrush_lower, NULL);
+	v4l2_ctrl_new_custom(hdl, &bttv_ctrl_whitecrush_upper, NULL);
+	v4l2_ctrl_new_custom(hdl, &bttv_ctrl_uv_ratio, NULL);
+	v4l2_ctrl_new_custom(hdl, &bttv_ctrl_full_luma, NULL);
+	v4l2_ctrl_new_custom(hdl, &bttv_ctrl_coring, NULL);
+
 	/* initialize hardware */
 	if (bttv_gpio)
 		bttv_gpio_tracking(btv,"pre-init");
@@ -4417,21 +4220,34 @@ static int bttv_probe(struct pci_dev *dev, const struct pci_device_id *pci_id)
 	/* some card-specific stuff (needs working i2c) */
 	bttv_init_card2(btv);
 	bttv_init_tuner(btv);
+	if (btv->tuner_type != TUNER_ABSENT) {
+		bttv_set_frequency(btv, &init_freq);
+		btv->radio_freq = 90500 * 16; /* 90.5Mhz default */
+	}
+	btv->std = V4L2_STD_PAL;
 	init_irqreg(btv);
+	v4l2_ctrl_handler_setup(hdl);
+	if (hdl->error) {
+		result = hdl->error;
+		goto fail2;
+	}
+	/* mute device */
+	audio_mute(btv, 1);
 
 	/* register video4linux + input */
 	if (!bttv_tvcards[btv->c.type].no_video) {
-		bttv_register_video(btv);
-		bt848_bright(btv,32768);
-		bt848_contrast(btv, 27648);
-		bt848_hue(btv,32768);
-		bt848_sat(btv,32768);
-		audio_mute(btv, 1);
+		v4l2_ctrl_add_handler(&btv->radio_ctrl_handler, hdl,
+				v4l2_ctrl_radio_filter);
+		if (btv->radio_ctrl_handler.error) {
+			result = btv->radio_ctrl_handler.error;
+			goto fail2;
+		}
 		set_input(btv, 0, btv->tvnorm);
 		bttv_crop_reset(&btv->crop[0], btv->tvnorm);
 		btv->crop[1] = btv->crop[0]; /* current = default */
 		disclaim_vbi_lines(btv);
 		disclaim_video_lines(btv);
+		bttv_register_video(btv);
 	}
 
 	/* add subdevices and autoload dvb-bt8xx if needed */
@@ -4453,6 +4269,8 @@ fail2:
 	free_irq(btv->c.pci->irq,btv);
 
 fail1:
+	v4l2_ctrl_handler_free(&btv->ctrl_handler);
+	v4l2_ctrl_handler_free(&btv->radio_ctrl_handler);
 	v4l2_device_unregister(&btv->c.v4l2_dev);
 
 fail0:
@@ -4494,9 +4312,11 @@ static void bttv_remove(struct pci_dev *pci_dev)
 	bttv_unregister_video(btv);
 
 	/* free allocated memory */
+	v4l2_ctrl_handler_free(&btv->ctrl_handler);
+	v4l2_ctrl_handler_free(&btv->radio_ctrl_handler);
 	btcx_riscmem_free(btv->c.pci,&btv->main);
 
-	/* free ressources */
+	/* free resources */
 	free_irq(btv->c.pci->irq,btv);
 	iounmap(btv->bt848_mmio);
 	release_mem_region(pci_resource_start(btv->c.pci,0),
diff --git a/drivers/media/pci/bt8xx/bttv-i2c.c b/drivers/media/pci/bt8xx/bttv-i2c.c
index c63c643..d43911d 100644
--- a/drivers/media/pci/bt8xx/bttv-i2c.c
+++ b/drivers/media/pci/bt8xx/bttv-i2c.c
@@ -394,3 +394,11 @@ int init_bttv_i2c(struct bttv *btv)
 
 	return btv->i2c_rc;
 }
+
+int fini_bttv_i2c(struct bttv *btv)
+{
+	if (btv->i2c_rc == 0)
+		i2c_del_adapter(&btv->c.i2c_adap);
+
+	return 0;
+}
diff --git a/drivers/media/pci/bt8xx/bttv-input.c b/drivers/media/pci/bt8xx/bttv-input.c
index 04207a7..f368213 100644
--- a/drivers/media/pci/bt8xx/bttv-input.c
+++ b/drivers/media/pci/bt8xx/bttv-input.c
@@ -375,6 +375,7 @@ void init_bttv_i2c_ir(struct bttv *btv)
 		I2C_CLIENT_END
 	};
 	struct i2c_board_info info;
+	struct i2c_client *i2c_dev;
 
 	if (0 != btv->i2c_rc)
 		return;
@@ -390,7 +391,12 @@ void init_bttv_i2c_ir(struct bttv *btv)
 		btv->init_data.ir_codes = RC_MAP_PV951;
 		info.addr = 0x4b;
 		break;
-	default:
+	}
+
+	if (btv->init_data.name) {
+		info.platform_data = &btv->init_data;
+		i2c_dev = i2c_new_device(&btv->c.i2c_adap, &info);
+	} else {
 		/*
 		 * The external IR receiver is at i2c address 0x34 (0x35 for
 		 * reads).  Future Hauppauge cards will have an internal
@@ -399,24 +405,14 @@ void init_bttv_i2c_ir(struct bttv *btv)
 		 * internal.
 		 * That's why we probe 0x1a (~0x34) first. CB
 		 */
-
-		i2c_new_probed_device(&btv->c.i2c_adap, &info, addr_list, NULL);
-		return;
+		i2c_dev = i2c_new_probed_device(&btv->c.i2c_adap, &info, addr_list, NULL);
 	}
+	if (NULL == i2c_dev)
+		return;
 
-	if (btv->init_data.name)
-		info.platform_data = &btv->init_data;
-	i2c_new_device(&btv->c.i2c_adap, &info);
-
-	return;
-}
-
-int fini_bttv_i2c(struct bttv *btv)
-{
-	if (0 != btv->i2c_rc)
-		return 0;
-
-	return i2c_del_adapter(&btv->c.i2c_adap);
+#if defined(CONFIG_MODULES) && defined(MODULE)
+	request_module("ir-kbd-i2c");
+#endif
 }
 
 int bttv_input_init(struct bttv *btv)
diff --git a/drivers/media/pci/bt8xx/bttv.h b/drivers/media/pci/bt8xx/bttv.h
index 79a1124..6139ce2 100644
--- a/drivers/media/pci/bt8xx/bttv.h
+++ b/drivers/media/pci/bt8xx/bttv.h
@@ -359,6 +359,9 @@ void bttv_gpio_bits(struct bttv_core *core, u32 mask, u32 bits);
 #define bttv_call_all(btv, o, f, args...) \
 	v4l2_device_call_all(&btv->c.v4l2_dev, 0, o, f, ##args)
 
+#define bttv_call_all_err(btv, o, f, args...) \
+	v4l2_device_call_until_err(&btv->c.v4l2_dev, 0, o, f, ##args)
+
 extern int bttv_I2CRead(struct bttv *btv, unsigned char addr, char *probe_for);
 extern int bttv_I2CWrite(struct bttv *btv, unsigned char addr, unsigned char b1,
 			 unsigned char b2, int both);
diff --git a/drivers/media/pci/bt8xx/bttvp.h b/drivers/media/pci/bt8xx/bttvp.h
index 9ec0adb..9c1cc2c 100644
--- a/drivers/media/pci/bt8xx/bttvp.h
+++ b/drivers/media/pci/bt8xx/bttvp.h
@@ -33,9 +33,11 @@
 #include <linux/input.h>
 #include <linux/mutex.h>
 #include <linux/scatterlist.h>
+#include <linux/device.h>
 #include <asm/io.h>
 #include <media/v4l2-common.h>
-#include <linux/device.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-fh.h>
 #include <media/videobuf-dma-sg.h>
 #include <media/tveeprom.h>
 #include <media/rc-core.h>
@@ -214,11 +216,11 @@ struct bttv_crop {
 };
 
 struct bttv_fh {
+	/* This must be the first field in this struct */
+	struct v4l2_fh		 fh;
+
 	struct bttv              *btv;
 	int resources;
-#ifdef VIDIOC_G_PRIORITY
-	enum v4l2_priority       prio;
-#endif
 	enum v4l2_buf_type       type;
 
 	/* video capture */
@@ -298,6 +300,10 @@ extern int no_overlay;
 /* bttv-input.c                                               */
 
 extern void init_bttv_i2c_ir(struct bttv *btv);
+
+/* ---------------------------------------------------------- */
+/* bttv-i2c.c                                                 */
+extern int init_bttv_i2c(struct bttv *btv);
 extern int fini_bttv_i2c(struct bttv *btv);
 
 /* ---------------------------------------------------------- */
@@ -308,7 +314,6 @@ extern unsigned int bttv_verbose;
 extern unsigned int bttv_debug;
 extern unsigned int bttv_gpio;
 extern void bttv_gpio_tracking(struct bttv *btv, char *comment);
-extern int init_bttv_i2c(struct bttv *btv);
 
 #define dprintk(fmt, ...)			\
 do {						\
@@ -393,12 +398,17 @@ struct bttv {
 	wait_queue_head_t          i2c_queue;
 	struct v4l2_subdev 	  *sd_msp34xx;
 	struct v4l2_subdev 	  *sd_tvaudio;
+	struct v4l2_subdev	  *sd_tda7432;
 
 	/* video4linux (1) */
 	struct video_device *video_dev;
 	struct video_device *radio_dev;
 	struct video_device *vbi_dev;
 
+	/* controls */
+	struct v4l2_ctrl_handler   ctrl_handler;
+	struct v4l2_ctrl_handler   radio_ctrl_handler;
+
 	/* infrared remote */
 	int has_remote;
 	struct bttv_ir *remote;
@@ -410,38 +420,30 @@ struct bttv {
 	spinlock_t s_lock;
 	struct mutex lock;
 	int resources;
-#ifdef VIDIOC_G_PRIORITY
-	struct v4l2_prio_state prio;
-#endif
 
 	/* video state */
 	unsigned int input;
-	unsigned int audio;
+	unsigned int audio_input;
 	unsigned int mute;
-	unsigned long freq;
+	unsigned long tv_freq;
 	unsigned int tvnorm;
+	v4l2_std_id std;
 	int hue, contrast, bright, saturation;
 	struct v4l2_framebuffer fbuf;
 	unsigned int field_count;
 
 	/* various options */
 	int opt_combfilter;
-	int opt_lumafilter;
 	int opt_automute;
-	int opt_chroma_agc;
-	int opt_color_killer;
-	int opt_adc_crush;
 	int opt_vcr_hack;
-	int opt_whitecrush_upper;
-	int opt_whitecrush_lower;
 	int opt_uv_ratio;
-	int opt_full_luma_range;
-	int opt_coring;
 
 	/* radio data/state */
 	int has_radio;
+	int has_radio_tuner;
 	int radio_user;
 	int radio_uses_msp_demodulator;
+	unsigned long radio_freq;
 
 	/* miro/pinnacle + Aimslab VHX
 	   philips matchbox (tea5757 radio tuner) support */
diff --git a/drivers/media/pci/cx18/cx18-av-core.c b/drivers/media/pci/cx18/cx18-av-core.c
index f164b7f..38b1d64 100644
--- a/drivers/media/pci/cx18/cx18-av-core.c
+++ b/drivers/media/pci/cx18/cx18-av-core.c
@@ -576,7 +576,7 @@ static void input_change(struct cx18 *cx)
 }
 
 static int cx18_av_s_frequency(struct v4l2_subdev *sd,
-			       struct v4l2_frequency *freq)
+			       const struct v4l2_frequency *freq)
 {
 	struct cx18 *cx = v4l2_get_subdevdata(sd);
 	input_change(cx);
@@ -809,7 +809,7 @@ static int cx18_av_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
 	return 0;
 }
 
-static int cx18_av_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
+static int cx18_av_s_tuner(struct v4l2_subdev *sd, const struct v4l2_tuner *vt)
 {
 	struct cx18_av_state *state = to_cx18_av_state(sd);
 	struct cx18 *cx = v4l2_get_subdevdata(sd);
@@ -1266,7 +1266,7 @@ static int cx18_av_g_register(struct v4l2_subdev *sd,
 }
 
 static int cx18_av_s_register(struct v4l2_subdev *sd,
-			      struct v4l2_dbg_register *reg)
+			      const struct v4l2_dbg_register *reg)
 {
 	struct cx18 *cx = v4l2_get_subdevdata(sd);
 
diff --git a/drivers/media/pci/cx18/cx18-driver.c b/drivers/media/pci/cx18/cx18-driver.c
index 613e5ae..67b61cf 100644
--- a/drivers/media/pci/cx18/cx18-driver.c
+++ b/drivers/media/pci/cx18/cx18-driver.c
@@ -1243,7 +1243,7 @@ int cx18_init_on_first_open(struct cx18 *cx)
 	   in one place. */
 	cx->std++;		/* Force full standard initialization */
 	std = (cx->tuner_std == V4L2_STD_ALL) ? V4L2_STD_NTSC_M : cx->tuner_std;
-	cx18_s_std(NULL, &fh, &std);
+	cx18_s_std(NULL, &fh, std);
 	cx18_s_frequency(NULL, &fh, &vf);
 	return 0;
 }
diff --git a/drivers/media/pci/cx18/cx18-ioctl.c b/drivers/media/pci/cx18/cx18-ioctl.c
index cd8d2c2..aee7b6d 100644
--- a/drivers/media/pci/cx18/cx18-ioctl.c
+++ b/drivers/media/pci/cx18/cx18-ioctl.c
@@ -415,42 +415,34 @@ static int cx18_g_chip_ident(struct file *file, void *fh,
 }
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
-static int cx18_cxc(struct cx18 *cx, unsigned int cmd, void *arg)
-{
-	struct v4l2_dbg_register *regs = arg;
-
-	if (!capable(CAP_SYS_ADMIN))
-		return -EPERM;
-	if (regs->reg >= CX18_MEM_OFFSET + CX18_MEM_SIZE)
-		return -EINVAL;
-
-	regs->size = 4;
-	if (cmd == VIDIOC_DBG_S_REGISTER)
-		cx18_write_enc(cx, regs->val, regs->reg);
-	else
-		regs->val = cx18_read_enc(cx, regs->reg);
-	return 0;
-}
-
 static int cx18_g_register(struct file *file, void *fh,
 				struct v4l2_dbg_register *reg)
 {
 	struct cx18 *cx = fh2id(fh)->cx;
 
-	if (v4l2_chip_match_host(&reg->match))
-		return cx18_cxc(cx, VIDIOC_DBG_G_REGISTER, reg);
+	if (v4l2_chip_match_host(&reg->match)) {
+		if (reg->reg >= CX18_MEM_OFFSET + CX18_MEM_SIZE)
+			return -EINVAL;
+		reg->size = 4;
+		reg->val = cx18_read_enc(cx, reg->reg);
+		return 0;
+	}
 	/* FIXME - errors shouldn't be ignored */
 	cx18_call_all(cx, core, g_register, reg);
 	return 0;
 }
 
 static int cx18_s_register(struct file *file, void *fh,
-				struct v4l2_dbg_register *reg)
+				const struct v4l2_dbg_register *reg)
 {
 	struct cx18 *cx = fh2id(fh)->cx;
 
-	if (v4l2_chip_match_host(&reg->match))
-		return cx18_cxc(cx, VIDIOC_DBG_S_REGISTER, reg);
+	if (v4l2_chip_match_host(&reg->match)) {
+		if (reg->reg >= CX18_MEM_OFFSET + CX18_MEM_SIZE)
+			return -EINVAL;
+		cx18_write_enc(cx, reg->val, reg->reg);
+		return 0;
+	}
 	/* FIXME - errors shouldn't be ignored */
 	cx18_call_all(cx, core, s_register, reg);
 	return 0;
@@ -614,7 +606,7 @@ static int cx18_g_frequency(struct file *file, void *fh,
 	return 0;
 }
 
-int cx18_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf)
+int cx18_s_frequency(struct file *file, void *fh, const struct v4l2_frequency *vf)
 {
 	struct cx18_open_id *id = fh2id(fh);
 	struct cx18 *cx = id->cx;
@@ -637,15 +629,15 @@ static int cx18_g_std(struct file *file, void *fh, v4l2_std_id *std)
 	return 0;
 }
 
-int cx18_s_std(struct file *file, void *fh, v4l2_std_id *std)
+int cx18_s_std(struct file *file, void *fh, v4l2_std_id std)
 {
 	struct cx18_open_id *id = fh2id(fh);
 	struct cx18 *cx = id->cx;
 
-	if ((*std & V4L2_STD_ALL) == 0)
+	if ((std & V4L2_STD_ALL) == 0)
 		return -EINVAL;
 
-	if (*std == cx->std)
+	if (std == cx->std)
 		return 0;
 
 	if (test_bit(CX18_F_I_RADIO_USER, &cx->i_flags) ||
@@ -656,8 +648,8 @@ int cx18_s_std(struct file *file, void *fh, v4l2_std_id *std)
 		return -EBUSY;
 	}
 
-	cx->std = *std;
-	cx->is_60hz = (*std & V4L2_STD_525_60) ? 1 : 0;
+	cx->std = std;
+	cx->is_60hz = (std & V4L2_STD_525_60) ? 1 : 0;
 	cx->is_50hz = !cx->is_60hz;
 	cx2341x_handler_set_50hz(&cx->cxhdl, cx->is_50hz);
 	cx->cxhdl.width = 720;
@@ -673,7 +665,7 @@ int cx18_s_std(struct file *file, void *fh, v4l2_std_id *std)
 	return 0;
 }
 
-static int cx18_s_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
+static int cx18_s_tuner(struct file *file, void *fh, const struct v4l2_tuner *vt)
 {
 	struct cx18_open_id *id = fh2id(fh);
 	struct cx18 *cx = id->cx;
@@ -1118,7 +1110,7 @@ static int cx18_log_status(struct file *file, void *fh)
 }
 
 static long cx18_default(struct file *file, void *fh, bool valid_prio,
-							int cmd, void *arg)
+			 unsigned int cmd, void *arg)
 {
 	struct cx18 *cx = fh2id(fh)->cx;
 
diff --git a/drivers/media/pci/cx18/cx18-ioctl.h b/drivers/media/pci/cx18/cx18-ioctl.h
index 2f9dd59..4343396 100644
--- a/drivers/media/pci/cx18/cx18-ioctl.h
+++ b/drivers/media/pci/cx18/cx18-ioctl.h
@@ -26,6 +26,6 @@ u16 cx18_service2vbi(int type);
 void cx18_expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal);
 u16 cx18_get_service_set(struct v4l2_sliced_vbi_format *fmt);
 void cx18_set_funcs(struct video_device *vdev);
-int cx18_s_std(struct file *file, void *fh, v4l2_std_id *std);
-int cx18_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf);
+int cx18_s_std(struct file *file, void *fh, v4l2_std_id std);
+int cx18_s_frequency(struct file *file, void *fh, const struct v4l2_frequency *vf);
 int cx18_s_input(struct file *file, void *fh, unsigned int inp);
diff --git a/drivers/media/pci/cx23885/altera-ci.h b/drivers/media/pci/cx23885/altera-ci.h
index 70e4fd6..4998c96 100644
--- a/drivers/media/pci/cx23885/altera-ci.h
+++ b/drivers/media/pci/cx23885/altera-ci.h
@@ -24,6 +24,8 @@
 #ifndef __ALTERA_CI_H
 #define __ALTERA_CI_H
 
+#include <linux/kconfig.h>
+
 #define ALT_DATA	0x000000ff
 #define ALT_TDI		0x00008000
 #define ALT_TDO		0x00004000
@@ -41,8 +43,7 @@ struct altera_ci_config {
 	int (*fpga_rw) (void *dev, int ad_rg, int val, int rw);
 };
 
-#if defined(CONFIG_MEDIA_ALTERA_CI) || (defined(CONFIG_MEDIA_ALTERA_CI_MODULE) \
-							&& defined(MODULE))
+#if IS_ENABLED(CONFIG_MEDIA_ALTERA_CI)
 
 extern int altera_ci_init(struct altera_ci_config *config, int ci_nr);
 extern void altera_ci_release(void *dev, int ci_nr);
diff --git a/drivers/media/pci/cx23885/cx23885-417.c b/drivers/media/pci/cx23885/cx23885-417.c
index 5d5052d..6dea11a 100644
--- a/drivers/media/pci/cx23885/cx23885-417.c
+++ b/drivers/media/pci/cx23885/cx23885-417.c
@@ -1222,14 +1222,14 @@ static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id)
 	return 0;
 }
 
-static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *id)
+static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id)
 {
 	struct cx23885_fh  *fh  = file->private_data;
 	struct cx23885_dev *dev = fh->dev;
 	unsigned int i;
 
 	for (i = 0; i < ARRAY_SIZE(cx23885_tvnorms); i++)
-		if (*id & cx23885_tvnorms[i].id)
+		if (id & cx23885_tvnorms[i].id)
 			break;
 	if (i == ARRAY_SIZE(cx23885_tvnorms))
 		return -EINVAL;
@@ -1237,7 +1237,7 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *id)
 
 	/* Have the drier core notify the subdevices */
 	mutex_lock(&dev->lock);
-	cx23885_set_tvnorm(dev, *id);
+	cx23885_set_tvnorm(dev, id);
 	mutex_unlock(&dev->lock);
 
 	return 0;
@@ -1280,7 +1280,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
 }
 
 static int vidioc_s_tuner(struct file *file, void *priv,
-				struct v4l2_tuner *t)
+				const struct v4l2_tuner *t)
 {
 	struct cx23885_fh  *fh  = file->private_data;
 	struct cx23885_dev *dev = fh->dev;
@@ -1311,7 +1311,7 @@ static int vidioc_g_frequency(struct file *file, void *priv,
 }
 
 static int vidioc_s_frequency(struct file *file, void *priv,
-	struct v4l2_frequency *f)
+	const struct v4l2_frequency *f)
 {
 	return cx23885_set_frequency(file, priv, f);
 }
diff --git a/drivers/media/pci/cx23885/cx23885-ioctl.c b/drivers/media/pci/cx23885/cx23885-ioctl.c
index ea9a614..acdb6d5 100644
--- a/drivers/media/pci/cx23885/cx23885-ioctl.c
+++ b/drivers/media/pci/cx23885/cx23885-ioctl.c
@@ -158,18 +158,17 @@ int cx23885_g_register(struct file *file, void *fh,
 }
 
 static int cx23885_s_host_register(struct cx23885_dev *dev,
-				   struct v4l2_dbg_register *reg)
+				   const struct v4l2_dbg_register *reg)
 {
 	if ((reg->reg & 0x3) != 0 || reg->reg >= pci_resource_len(dev->pci, 0))
 		return -EINVAL;
 
-	reg->size = 4;
 	cx_write(reg->reg, reg->val);
 	return 0;
 }
 
 static int cx23417_s_register(struct cx23885_dev *dev,
-			      struct v4l2_dbg_register *reg)
+			      const struct v4l2_dbg_register *reg)
 {
 	if (dev->v4l_device == NULL)
 		return -EINVAL;
@@ -179,13 +178,11 @@ static int cx23417_s_register(struct cx23885_dev *dev,
 
 	if (mc417_register_write(dev, (u16) reg->reg, (u32) reg->val))
 		return -EINVAL; /* V4L2 spec, but -EREMOTEIO really */
-
-	reg->size = 4;
 	return 0;
 }
 
 int cx23885_s_register(struct file *file, void *fh,
-		       struct v4l2_dbg_register *reg)
+		       const struct v4l2_dbg_register *reg)
 {
 	struct cx23885_dev *dev = ((struct cx23885_fh *)fh)->dev;
 
diff --git a/drivers/media/pci/cx23885/cx23885-ioctl.h b/drivers/media/pci/cx23885/cx23885-ioctl.h
index 315be0c..a608096 100644
--- a/drivers/media/pci/cx23885/cx23885-ioctl.h
+++ b/drivers/media/pci/cx23885/cx23885-ioctl.h
@@ -33,7 +33,7 @@ int cx23885_g_register(struct file *file, void *fh,
 
 
 int cx23885_s_register(struct file *file, void *fh,
-		       struct v4l2_dbg_register *reg);
+		       const struct v4l2_dbg_register *reg);
 
 #endif
 #endif
diff --git a/drivers/media/pci/cx23885/cx23885-video.c b/drivers/media/pci/cx23885/cx23885-video.c
index 5991bc8..ed08c89 100644
--- a/drivers/media/pci/cx23885/cx23885-video.c
+++ b/drivers/media/pci/cx23885/cx23885-video.c
@@ -1259,13 +1259,13 @@ static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id)
 	return 0;
 }
 
-static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *tvnorms)
+static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id tvnorms)
 {
 	struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
 	dprintk(1, "%s()\n", __func__);
 
 	mutex_lock(&dev->lock);
-	cx23885_set_tvnorm(dev, *tvnorms);
+	cx23885_set_tvnorm(dev, tvnorms);
 	mutex_unlock(&dev->lock);
 
 	return 0;
@@ -1486,7 +1486,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
 }
 
 static int vidioc_s_tuner(struct file *file, void *priv,
-				struct v4l2_tuner *t)
+				const struct v4l2_tuner *t)
 {
 	struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
 
@@ -1518,7 +1518,7 @@ static int vidioc_g_frequency(struct file *file, void *priv,
 	return 0;
 }
 
-static int cx23885_set_freq(struct cx23885_dev *dev, struct v4l2_frequency *f)
+static int cx23885_set_freq(struct cx23885_dev *dev, const struct v4l2_frequency *f)
 {
 	struct v4l2_control ctrl;
 
@@ -1550,7 +1550,7 @@ static int cx23885_set_freq(struct cx23885_dev *dev, struct v4l2_frequency *f)
 }
 
 static int cx23885_set_freq_via_ops(struct cx23885_dev *dev,
-	struct v4l2_frequency *f)
+	const struct v4l2_frequency *f)
 {
 	struct v4l2_control ctrl;
 	struct videobuf_dvb_frontend *vfe;
@@ -1608,7 +1608,7 @@ static int cx23885_set_freq_via_ops(struct cx23885_dev *dev,
 }
 
 int cx23885_set_frequency(struct file *file, void *priv,
-	struct v4l2_frequency *f)
+	const struct v4l2_frequency *f)
 {
 	struct cx23885_fh *fh = priv;
 	struct cx23885_dev *dev = fh->dev;
@@ -1628,7 +1628,7 @@ int cx23885_set_frequency(struct file *file, void *priv,
 }
 
 static int vidioc_s_frequency(struct file *file, void *priv,
-	struct v4l2_frequency *f)
+	const struct v4l2_frequency *f)
 {
 	return cx23885_set_frequency(file, priv, f);
 }
diff --git a/drivers/media/pci/cx23885/cx23885.h b/drivers/media/pci/cx23885/cx23885.h
index 59c322d..5687d3f 100644
--- a/drivers/media/pci/cx23885/cx23885.h
+++ b/drivers/media/pci/cx23885/cx23885.h
@@ -587,7 +587,7 @@ extern void cx23885_video_wakeup(struct cx23885_dev *dev,
 int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i);
 int cx23885_set_input(struct file *file, void *priv, unsigned int i);
 int cx23885_get_input(struct file *file, void *priv, unsigned int *i);
-int cx23885_set_frequency(struct file *file, void *priv, struct v4l2_frequency *f);
+int cx23885_set_frequency(struct file *file, void *priv, const struct v4l2_frequency *f);
 int cx23885_set_control(struct cx23885_dev *dev, struct v4l2_control *ctl);
 int cx23885_get_control(struct cx23885_dev *dev, struct v4l2_control *ctl);
 int cx23885_set_tvnorm(struct cx23885_dev *dev, v4l2_std_id norm);
diff --git a/drivers/media/pci/cx23885/cx23888-ir.c b/drivers/media/pci/cx23885/cx23888-ir.c
index d51eed0..fa672fe 100644
--- a/drivers/media/pci/cx23885/cx23888-ir.c
+++ b/drivers/media/pci/cx23885/cx23888-ir.c
@@ -1124,7 +1124,7 @@ static int cx23888_ir_g_register(struct v4l2_subdev *sd,
 }
 
 static int cx23888_ir_s_register(struct v4l2_subdev *sd,
-				 struct v4l2_dbg_register *reg)
+				 const struct v4l2_dbg_register *reg)
 {
 	struct cx23888_ir_state *state = to_state(sd);
 	u32 addr = CX23888_IR_REG_BASE + (u32) reg->reg;
diff --git a/drivers/media/pci/cx25821/cx25821-audio-upstream.c b/drivers/media/pci/cx25821/cx25821-audio-upstream.c
index 87491ca..ea97320 100644
--- a/drivers/media/pci/cx25821/cx25821-audio-upstream.c
+++ b/drivers/media/pci/cx25821/cx25821-audio-upstream.c
@@ -728,26 +728,17 @@ int cx25821_audio_upstream_init(struct cx25821_dev *dev, int channel_select)
 	dev->_audio_lines_count = LINES_PER_AUDIO_BUFFER;
 	_line_size = AUDIO_LINE_SIZE;
 
-	if (dev->input_audiofilename) {
+	if ((dev->input_audiofilename) &&
+	    (strcmp(dev->input_audiofilename, "") != 0))
 		dev->_audiofilename = kstrdup(dev->input_audiofilename,
 					      GFP_KERNEL);
-
-		if (!dev->_audiofilename) {
-			err = -ENOMEM;
-			goto error;
-		}
-
-		/* Default if filename is empty string */
-		if (strcmp(dev->input_audiofilename, "") == 0)
-			dev->_audiofilename = "/root/audioGOOD.wav";
-	} else {
+	else
 		dev->_audiofilename = kstrdup(_defaultAudioName,
 					      GFP_KERNEL);
 
-		if (!dev->_audiofilename) {
-			err = -ENOMEM;
-			goto error;
-		}
+	if (!dev->_audiofilename) {
+		err = -ENOMEM;
+		goto error;
 	}
 
 	cx25821_sram_channel_setup_upstream_audio(dev, sram_ch,
diff --git a/drivers/media/pci/cx25821/cx25821-video.c b/drivers/media/pci/cx25821/cx25821-video.c
index d4de021..1465591 100644
--- a/drivers/media/pci/cx25821/cx25821-video.c
+++ b/drivers/media/pci/cx25821/cx25821-video.c
@@ -1203,7 +1203,7 @@ int cx25821_vidioc_s_priority(struct file *file, void *f,
 }
 
 #ifdef TUNER_FLAG
-int cx25821_vidioc_s_std(struct file *file, void *priv, v4l2_std_id * tvnorms)
+int cx25821_vidioc_s_std(struct file *file, void *priv, v4l2_std_id tvnorms)
 {
 	struct cx25821_fh *fh = priv;
 	struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
@@ -1218,11 +1218,11 @@ int cx25821_vidioc_s_std(struct file *file, void *priv, v4l2_std_id * tvnorms)
 			return err;
 	}
 
-	if (dev->tvnorm == *tvnorms)
+	if (dev->tvnorm == tvnorms)
 		return 0;
 
 	mutex_lock(&dev->lock);
-	cx25821_set_tvnorm(dev, *tvnorms);
+	cx25821_set_tvnorm(dev, tvnorms);
 	mutex_unlock(&dev->lock);
 
 	medusa_set_videostandard(dev);
@@ -1312,7 +1312,7 @@ int cx25821_vidioc_g_frequency(struct file *file, void *priv,
 	return 0;
 }
 
-int cx25821_set_freq(struct cx25821_dev *dev, struct v4l2_frequency *f)
+int cx25821_set_freq(struct cx25821_dev *dev, const struct v4l2_frequency *f)
 {
 	mutex_lock(&dev->lock);
 	dev->freq = f->frequency;
@@ -1328,7 +1328,7 @@ int cx25821_set_freq(struct cx25821_dev *dev, struct v4l2_frequency *f)
 }
 
 int cx25821_vidioc_s_frequency(struct file *file, void *priv,
-			       struct v4l2_frequency *f)
+			       const struct v4l2_frequency *f)
 {
 	struct cx25821_fh *fh = priv;
 	struct cx25821_dev *dev;
@@ -1364,7 +1364,7 @@ int cx25821_vidioc_g_register(struct file *file, void *fh,
 }
 
 int cx25821_vidioc_s_register(struct file *file, void *fh,
-		      struct v4l2_dbg_register *reg)
+		      const struct v4l2_dbg_register *reg)
 {
 	struct cx25821_dev *dev = ((struct cx25821_fh *)fh)->dev;
 
@@ -1397,7 +1397,7 @@ int cx25821_vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
 	return 0;
 }
 
-int cx25821_vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
+int cx25821_vidioc_s_tuner(struct file *file, void *priv, const struct v4l2_tuner *t)
 {
 	struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
 	struct cx25821_fh *fh = priv;
diff --git a/drivers/media/pci/cx25821/cx25821-video.h b/drivers/media/pci/cx25821/cx25821-video.h
index c265e35..11ba5eb 100644
--- a/drivers/media/pci/cx25821/cx25821-video.h
+++ b/drivers/media/pci/cx25821/cx25821-video.h
@@ -135,7 +135,7 @@ extern int cx25821_vidioc_querybuf(struct file *file, void *priv,
 extern int cx25821_vidioc_qbuf(struct file *file, void *priv,
 			       struct v4l2_buffer *p);
 extern int cx25821_vidioc_s_std(struct file *file, void *priv,
-				v4l2_std_id *tvnorms);
+				v4l2_std_id tvnorms);
 extern int cx25821_enum_input(struct cx25821_dev *dev, struct v4l2_input *i);
 extern int cx25821_vidioc_enum_input(struct file *file, void *priv,
 				     struct v4l2_input *i);
@@ -149,17 +149,17 @@ extern int cx25821_vidioc_g_fmt_vid_cap(struct file *file, void *priv,
 					struct v4l2_format *f);
 extern int cx25821_vidioc_g_frequency(struct file *file, void *priv,
 				      struct v4l2_frequency *f);
-extern int cx25821_set_freq(struct cx25821_dev *dev, struct v4l2_frequency *f);
+extern int cx25821_set_freq(struct cx25821_dev *dev, const struct v4l2_frequency *f);
 extern int cx25821_vidioc_s_frequency(struct file *file, void *priv,
-				      struct v4l2_frequency *f);
+				      const struct v4l2_frequency *f);
 extern int cx25821_vidioc_g_register(struct file *file, void *fh,
 				     struct v4l2_dbg_register *reg);
 extern int cx25821_vidioc_s_register(struct file *file, void *fh,
-				     struct v4l2_dbg_register *reg);
+				     const struct v4l2_dbg_register *reg);
 extern int cx25821_vidioc_g_tuner(struct file *file, void *priv,
 				  struct v4l2_tuner *t);
 extern int cx25821_vidioc_s_tuner(struct file *file, void *priv,
-				  struct v4l2_tuner *t);
+				  const struct v4l2_tuner *t);
 
 extern int cx25821_is_valid_width(u32 width, v4l2_std_id tvnorm);
 extern int cx25821_is_valid_height(u32 height, v4l2_std_id tvnorm);
diff --git a/drivers/media/pci/cx88/cx88-blackbird.c b/drivers/media/pci/cx88/cx88-blackbird.c
index a6ff8a6..150bb76 100644
--- a/drivers/media/pci/cx88/cx88-blackbird.c
+++ b/drivers/media/pci/cx88/cx88-blackbird.c
@@ -815,7 +815,7 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
 }
 
 static int vidioc_s_frequency (struct file *file, void *priv,
-				struct v4l2_frequency *f)
+				const struct v4l2_frequency *f)
 {
 	struct cx8802_fh  *fh   = priv;
 	struct cx8802_dev *dev  = fh->dev;
@@ -918,7 +918,7 @@ static int vidioc_g_tuner (struct file *file, void *priv,
 }
 
 static int vidioc_s_tuner (struct file *file, void *priv,
-				struct v4l2_tuner *t)
+				const struct v4l2_tuner *t)
 {
 	struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;
 
@@ -939,12 +939,12 @@ static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *tvnorm)
 	return 0;
 }
 
-static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *id)
+static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id)
 {
 	struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;
 
 	mutex_lock(&core->lock);
-	cx88_set_tvnorm(core,*id);
+	cx88_set_tvnorm(core, id);
 	mutex_unlock(&core->lock);
 	return 0;
 }
diff --git a/drivers/media/pci/cx88/cx88-video.c b/drivers/media/pci/cx88/cx88-video.c
index bc78354..e3f6181 100644
--- a/drivers/media/pci/cx88/cx88-video.c
+++ b/drivers/media/pci/cx88/cx88-video.c
@@ -1193,12 +1193,12 @@ static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *tvnorm)
 	return 0;
 }
 
-static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *tvnorms)
+static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id tvnorms)
 {
 	struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
 
 	mutex_lock(&core->lock);
-	cx88_set_tvnorm(core,*tvnorms);
+	cx88_set_tvnorm(core, tvnorms);
 	mutex_unlock(&core->lock);
 
 	return 0;
@@ -1289,7 +1289,7 @@ static int vidioc_g_tuner (struct file *file, void *priv,
 }
 
 static int vidioc_s_tuner (struct file *file, void *priv,
-				struct v4l2_tuner *t)
+				const struct v4l2_tuner *t)
 {
 	struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
 
@@ -1321,8 +1321,10 @@ static int vidioc_g_frequency (struct file *file, void *priv,
 }
 
 int cx88_set_freq (struct cx88_core  *core,
-				struct v4l2_frequency *f)
+				const struct v4l2_frequency *f)
 {
+	struct v4l2_frequency new_freq = *f;
+
 	if (unlikely(UNSET == core->board.tuner_type))
 		return -EINVAL;
 	if (unlikely(f->tuner != 0))
@@ -1331,8 +1333,8 @@ int cx88_set_freq (struct cx88_core  *core,
 	mutex_lock(&core->lock);
 	cx88_newstation(core);
 	call_all(core, tuner, s_frequency, f);
-	call_all(core, tuner, g_frequency, f);
-	core->freq = f->frequency;
+	call_all(core, tuner, g_frequency, &new_freq);
+	core->freq = new_freq.frequency;
 
 	/* When changing channels it is required to reset TVAUDIO */
 	msleep (10);
@@ -1345,7 +1347,7 @@ int cx88_set_freq (struct cx88_core  *core,
 EXPORT_SYMBOL(cx88_set_freq);
 
 static int vidioc_s_frequency (struct file *file, void *priv,
-				struct v4l2_frequency *f)
+				const struct v4l2_frequency *f)
 {
 	struct cx8800_fh  *fh   = priv;
 	struct cx88_core  *core = fh->dev->core;
@@ -1378,7 +1380,7 @@ static int vidioc_g_register (struct file *file, void *fh,
 }
 
 static int vidioc_s_register (struct file *file, void *fh,
-				struct v4l2_dbg_register *reg)
+				const struct v4l2_dbg_register *reg)
 {
 	struct cx88_core *core = ((struct cx8800_fh*)fh)->dev->core;
 
@@ -1407,20 +1409,15 @@ static int radio_g_tuner (struct file *file, void *priv,
 	return 0;
 }
 
-/* FIXME: Should add a standard for radio */
-
 static int radio_s_tuner (struct file *file, void *priv,
-				struct v4l2_tuner *t)
+				const struct v4l2_tuner *t)
 {
 	struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
 
 	if (0 != t->index)
 		return -EINVAL;
-	if (t->audmode > V4L2_TUNER_MODE_STEREO)
-		t->audmode = V4L2_TUNER_MODE_STEREO;
 
 	call_all(core, tuner, s_tuner, t);
-
 	return 0;
 }
 
diff --git a/drivers/media/pci/cx88/cx88.h b/drivers/media/pci/cx88/cx88.h
index feff53c..eca02c2 100644
--- a/drivers/media/pci/cx88/cx88.h
+++ b/drivers/media/pci/cx88/cx88.h
@@ -740,7 +740,7 @@ void cx8802_cancel_buffers(struct cx8802_dev *dev);
 /* ----------------------------------------------------------- */
 /* cx88-video.c*/
 int cx88_enum_input (struct cx88_core  *core,struct v4l2_input *i);
-int cx88_set_freq (struct cx88_core  *core,struct v4l2_frequency *f);
+int cx88_set_freq(struct cx88_core  *core, const struct v4l2_frequency *f);
 int cx88_video_mux(struct cx88_core *core, unsigned int input);
 void cx88_querycap(struct file *file, struct cx88_core *core,
 		struct v4l2_capability *cap);
diff --git a/drivers/media/pci/ivtv/ivtv-driver.c b/drivers/media/pci/ivtv/ivtv-driver.c
index 2928e72..07b8460 100644
--- a/drivers/media/pci/ivtv/ivtv-driver.c
+++ b/drivers/media/pci/ivtv/ivtv-driver.c
@@ -1387,7 +1387,7 @@ int ivtv_init_on_first_open(struct ivtv *itv)
 	if (!itv->has_cx23415)
 		write_reg_sync(0x03, IVTV_REG_DMACONTROL);
 
-	ivtv_s_std_enc(itv, &itv->tuner_std);
+	ivtv_s_std_enc(itv, itv->tuner_std);
 
 	/* Default interrupts enabled. For the PVR350 this includes the
 	   decoder VSYNC interrupt, which is always on. It is not only used
@@ -1397,7 +1397,7 @@ int ivtv_init_on_first_open(struct ivtv *itv)
 	if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
 		ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_INIT | IVTV_IRQ_DEC_VSYNC);
 		ivtv_set_osd_alpha(itv);
-		ivtv_s_std_dec(itv, &itv->tuner_std);
+		ivtv_s_std_dec(itv, itv->tuner_std);
 	} else {
 		ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_INIT);
 	}
diff --git a/drivers/media/pci/ivtv/ivtv-firmware.c b/drivers/media/pci/ivtv/ivtv-firmware.c
index 68387d4..ed73edd 100644
--- a/drivers/media/pci/ivtv/ivtv-firmware.c
+++ b/drivers/media/pci/ivtv/ivtv-firmware.c
@@ -302,7 +302,7 @@ static int ivtv_firmware_restart(struct ivtv *itv)
 	/* Restore encoder video standard */
 	std = itv->std;
 	itv->std = 0;
-	ivtv_s_std_enc(itv, &std);
+	ivtv_s_std_enc(itv, std);
 
 	if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
 		ivtv_init_mpeg_decoder(itv);
@@ -310,7 +310,7 @@ static int ivtv_firmware_restart(struct ivtv *itv)
 		/* Restore decoder video standard */
 		std = itv->std_out;
 		itv->std_out = 0;
-		ivtv_s_std_dec(itv, &std);
+		ivtv_s_std_dec(itv, std);
 
 		/* Restore framebuffer if active */
 		if (itv->ivtvfb_restore)
diff --git a/drivers/media/pci/ivtv/ivtv-gpio.c b/drivers/media/pci/ivtv/ivtv-gpio.c
index 8f0d077..af52def 100644
--- a/drivers/media/pci/ivtv/ivtv-gpio.c
+++ b/drivers/media/pci/ivtv/ivtv-gpio.c
@@ -192,7 +192,7 @@ static int subdev_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
 	return 0;
 }
 
-static int subdev_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
+static int subdev_s_tuner(struct v4l2_subdev *sd, const struct v4l2_tuner *vt)
 {
 	struct ivtv *itv = sd_to_ivtv(sd);
 	u16 mask, data;
diff --git a/drivers/media/pci/ivtv/ivtv-ioctl.c b/drivers/media/pci/ivtv/ivtv-ioctl.c
index 7a8b0d0..9cbbce0 100644
--- a/drivers/media/pci/ivtv/ivtv-ioctl.c
+++ b/drivers/media/pci/ivtv/ivtv-ioctl.c
@@ -711,28 +711,26 @@ static int ivtv_g_chip_ident(struct file *file, void *fh, struct v4l2_dbg_chip_i
 }
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
-static int ivtv_itvc(struct ivtv *itv, unsigned int cmd, void *arg)
+static int ivtv_itvc(struct ivtv *itv, bool get, u64 reg, u64 *val)
 {
-	struct v4l2_dbg_register *regs = arg;
 	volatile u8 __iomem *reg_start;
 
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
-	if (regs->reg >= IVTV_REG_OFFSET && regs->reg < IVTV_REG_OFFSET + IVTV_REG_SIZE)
+	if (reg >= IVTV_REG_OFFSET && reg < IVTV_REG_OFFSET + IVTV_REG_SIZE)
 		reg_start = itv->reg_mem - IVTV_REG_OFFSET;
-	else if (itv->has_cx23415 && regs->reg >= IVTV_DECODER_OFFSET &&
-			regs->reg < IVTV_DECODER_OFFSET + IVTV_DECODER_SIZE)
+	else if (itv->has_cx23415 && reg >= IVTV_DECODER_OFFSET &&
+			reg < IVTV_DECODER_OFFSET + IVTV_DECODER_SIZE)
 		reg_start = itv->dec_mem - IVTV_DECODER_OFFSET;
-	else if (regs->reg < IVTV_ENCODER_SIZE)
+	else if (reg < IVTV_ENCODER_SIZE)
 		reg_start = itv->enc_mem;
 	else
 		return -EINVAL;
 
-	regs->size = 4;
-	if (cmd == VIDIOC_DBG_G_REGISTER)
-		regs->val = readl(regs->reg + reg_start);
+	if (get)
+		*val = readl(reg + reg_start);
 	else
-		writel(regs->val, regs->reg + reg_start);
+		writel(*val, reg + reg_start);
 	return 0;
 }
 
@@ -740,20 +738,25 @@ static int ivtv_g_register(struct file *file, void *fh, struct v4l2_dbg_register
 {
 	struct ivtv *itv = fh2id(fh)->itv;
 
-	if (v4l2_chip_match_host(&reg->match))
-		return ivtv_itvc(itv, VIDIOC_DBG_G_REGISTER, reg);
+	if (v4l2_chip_match_host(&reg->match)) {
+		reg->size = 4;
+		return ivtv_itvc(itv, true, reg->reg, &reg->val);
+	}
 	/* TODO: subdev errors should not be ignored, this should become a
 	   subdev helper function. */
 	ivtv_call_all(itv, core, g_register, reg);
 	return 0;
 }
 
-static int ivtv_s_register(struct file *file, void *fh, struct v4l2_dbg_register *reg)
+static int ivtv_s_register(struct file *file, void *fh, const struct v4l2_dbg_register *reg)
 {
 	struct ivtv *itv = fh2id(fh)->itv;
 
-	if (v4l2_chip_match_host(&reg->match))
-		return ivtv_itvc(itv, VIDIOC_DBG_S_REGISTER, reg);
+	if (v4l2_chip_match_host(&reg->match)) {
+		u64 val = reg->val;
+
+		return ivtv_itvc(itv, false, reg->reg, &val);
+	}
 	/* TODO: subdev errors should not be ignored, this should become a
 	   subdev helper function. */
 	ivtv_call_all(itv, core, s_register, reg);
@@ -1078,7 +1081,7 @@ static int ivtv_g_frequency(struct file *file, void *fh, struct v4l2_frequency *
 	return 0;
 }
 
-int ivtv_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf)
+int ivtv_s_frequency(struct file *file, void *fh, const struct v4l2_frequency *vf)
 {
 	struct ivtv *itv = fh2id(fh)->itv;
 	struct ivtv_stream *s = &itv->streams[fh2id(fh)->type];
@@ -1103,10 +1106,10 @@ static int ivtv_g_std(struct file *file, void *fh, v4l2_std_id *std)
 	return 0;
 }
 
-void ivtv_s_std_enc(struct ivtv *itv, v4l2_std_id *std)
+void ivtv_s_std_enc(struct ivtv *itv, v4l2_std_id std)
 {
-	itv->std = *std;
-	itv->is_60hz = (*std & V4L2_STD_525_60) ? 1 : 0;
+	itv->std = std;
+	itv->is_60hz = (std & V4L2_STD_525_60) ? 1 : 0;
 	itv->is_50hz = !itv->is_60hz;
 	cx2341x_handler_set_50hz(&itv->cxhdl, itv->is_50hz);
 	itv->cxhdl.width = 720;
@@ -1122,15 +1125,15 @@ void ivtv_s_std_enc(struct ivtv *itv, v4l2_std_id *std)
 	ivtv_call_all(itv, core, s_std, itv->std);
 }
 
-void ivtv_s_std_dec(struct ivtv *itv, v4l2_std_id *std)
+void ivtv_s_std_dec(struct ivtv *itv, v4l2_std_id std)
 {
 	struct yuv_playback_info *yi = &itv->yuv_info;
 	DEFINE_WAIT(wait);
 	int f;
 
 	/* set display standard */
-	itv->std_out = *std;
-	itv->is_out_60hz = (*std & V4L2_STD_525_60) ? 1 : 0;
+	itv->std_out = std;
+	itv->is_out_60hz = (std & V4L2_STD_525_60) ? 1 : 0;
 	itv->is_out_50hz = !itv->is_out_60hz;
 	ivtv_call_all(itv, video, s_std_output, itv->std_out);
 
@@ -1168,14 +1171,14 @@ void ivtv_s_std_dec(struct ivtv *itv, v4l2_std_id *std)
 	}
 }
 
-static int ivtv_s_std(struct file *file, void *fh, v4l2_std_id *std)
+static int ivtv_s_std(struct file *file, void *fh, v4l2_std_id std)
 {
 	struct ivtv *itv = fh2id(fh)->itv;
 
-	if ((*std & V4L2_STD_ALL) == 0)
+	if ((std & V4L2_STD_ALL) == 0)
 		return -EINVAL;
 
-	if (*std == itv->std)
+	if (std == itv->std)
 		return 0;
 
 	if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ||
@@ -1196,7 +1199,7 @@ static int ivtv_s_std(struct file *file, void *fh, v4l2_std_id *std)
 	return 0;
 }
 
-static int ivtv_s_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
+static int ivtv_s_tuner(struct file *file, void *fh, const struct v4l2_tuner *vt)
 {
 	struct ivtv_open_id *id = fh2id(fh);
 	struct ivtv *itv = id->itv;
@@ -1804,7 +1807,7 @@ static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg)
 }
 
 static long ivtv_default(struct file *file, void *fh, bool valid_prio,
-			 int cmd, void *arg)
+			 unsigned int cmd, void *arg)
 {
 	struct ivtv *itv = fh2id(fh)->itv;
 
diff --git a/drivers/media/pci/ivtv/ivtv-ioctl.h b/drivers/media/pci/ivtv/ivtv-ioctl.h
index 7c553d1..75c3977 100644
--- a/drivers/media/pci/ivtv/ivtv-ioctl.h
+++ b/drivers/media/pci/ivtv/ivtv-ioctl.h
@@ -27,9 +27,9 @@ u16 ivtv_get_service_set(struct v4l2_sliced_vbi_format *fmt);
 void ivtv_set_osd_alpha(struct ivtv *itv);
 int ivtv_set_speed(struct ivtv *itv, int speed);
 void ivtv_set_funcs(struct video_device *vdev);
-void ivtv_s_std_enc(struct ivtv *itv, v4l2_std_id *std);
-void ivtv_s_std_dec(struct ivtv *itv, v4l2_std_id *std);
-int ivtv_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf);
+void ivtv_s_std_enc(struct ivtv *itv, v4l2_std_id std);
+void ivtv_s_std_dec(struct ivtv *itv, v4l2_std_id std);
+int ivtv_s_frequency(struct file *file, void *fh, const struct v4l2_frequency *vf);
 int ivtv_s_input(struct file *file, void *fh, unsigned int inp);
 
 #endif
diff --git a/drivers/media/pci/ivtv/ivtvfb.c b/drivers/media/pci/ivtv/ivtvfb.c
index 05b94aa..9ff1230 100644
--- a/drivers/media/pci/ivtv/ivtvfb.c
+++ b/drivers/media/pci/ivtv/ivtvfb.c
@@ -1171,8 +1171,7 @@ static void ivtvfb_release_buffers (struct ivtv *itv)
 		fb_dealloc_cmap(&oi->ivtvfb_info.cmap);
 
 	/* Release pseudo palette */
-	if (oi->ivtvfb_info.pseudo_palette)
-		kfree(oi->ivtvfb_info.pseudo_palette);
+	kfree(oi->ivtvfb_info.pseudo_palette);
 
 #ifdef CONFIG_MTRR
 	if (oi->fb_end_aligned_physaddr) {
diff --git a/drivers/media/pci/mantis/mantis_i2c.c b/drivers/media/pci/mantis/mantis_i2c.c
index 937fb9d..895ddba 100644
--- a/drivers/media/pci/mantis/mantis_i2c.c
+++ b/drivers/media/pci/mantis/mantis_i2c.c
@@ -261,6 +261,8 @@ int mantis_i2c_exit(struct mantis_pci *mantis)
 	mmwrite((intmask & ~MANTIS_INT_I2CDONE), MANTIS_INT_MASK);
 
 	dprintk(MANTIS_DEBUG, 1, "Removing I2C adapter");
-	return i2c_del_adapter(&mantis->adapter);
+	i2c_del_adapter(&mantis->adapter);
+
+	return 0;
 }
 EXPORT_SYMBOL_GPL(mantis_i2c_exit);
diff --git a/drivers/media/pci/meye/meye.c b/drivers/media/pci/meye/meye.c
index 7859c43..2381b05 100644
--- a/drivers/media/pci/meye/meye.c
+++ b/drivers/media/pci/meye/meye.c
@@ -1410,7 +1410,7 @@ static int vidioc_streamoff(struct file *file, void *fh, enum v4l2_buf_type i)
 }
 
 static long vidioc_default(struct file *file, void *fh, bool valid_prio,
-						int cmd, void *arg)
+			   unsigned int cmd, void *arg)
 {
 	switch (cmd) {
 	case MEYEIOC_G_PARAMS:
diff --git a/drivers/media/pci/saa7134/saa7134-empress.c b/drivers/media/pci/saa7134/saa7134-empress.c
index 4df79c6..66a7081 100644
--- a/drivers/media/pci/saa7134/saa7134-empress.c
+++ b/drivers/media/pci/saa7134/saa7134-empress.c
@@ -428,7 +428,7 @@ static int empress_g_chip_ident(struct file *file, void *fh,
 	return -EINVAL;
 }
 
-static int empress_s_std(struct file *file, void *priv, v4l2_std_id *id)
+static int empress_s_std(struct file *file, void *priv, v4l2_std_id id)
 {
 	struct saa7134_dev *dev = file->private_data;
 
diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c
index 7c503fb..1363e97 100644
--- a/drivers/media/pci/saa7134/saa7134-video.c
+++ b/drivers/media/pci/saa7134/saa7134-video.c
@@ -1828,7 +1828,7 @@ static int saa7134_querycap(struct file *file, void  *priv,
 	return 0;
 }
 
-int saa7134_s_std_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, v4l2_std_id *id)
+int saa7134_s_std_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, v4l2_std_id id)
 {
 	unsigned long flags;
 	unsigned int i;
@@ -1849,17 +1849,17 @@ int saa7134_s_std_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, v4l2_
 	}
 
 	for (i = 0; i < TVNORMS; i++)
-		if (*id == tvnorms[i].id)
+		if (id == tvnorms[i].id)
 			break;
 
 	if (i == TVNORMS)
 		for (i = 0; i < TVNORMS; i++)
-			if (*id & tvnorms[i].id)
+			if (id & tvnorms[i].id)
 				break;
 	if (i == TVNORMS)
 		return -EINVAL;
 
-	if ((*id & V4L2_STD_SECAM) && (secam[0] != '-')) {
+	if ((id & V4L2_STD_SECAM) && (secam[0] != '-')) {
 		if (secam[0] == 'L' || secam[0] == 'l') {
 			if (secam[1] == 'C' || secam[1] == 'c')
 				fixup = V4L2_STD_SECAM_LC;
@@ -1879,7 +1879,7 @@ int saa7134_s_std_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, v4l2_
 			return -EINVAL;
 	}
 
-	*id = tvnorms[i].id;
+	id = tvnorms[i].id;
 
 	mutex_lock(&dev->lock);
 	if (fh && res_check(fh, RESOURCE_OVERLAY)) {
@@ -1901,7 +1901,7 @@ int saa7134_s_std_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, v4l2_
 }
 EXPORT_SYMBOL_GPL(saa7134_s_std_internal);
 
-static int saa7134_s_std(struct file *file, void *priv, v4l2_std_id *id)
+static int saa7134_s_std(struct file *file, void *priv, v4l2_std_id id)
 {
 	struct saa7134_fh *fh = priv;
 
@@ -2023,7 +2023,7 @@ static int saa7134_g_tuner(struct file *file, void *priv,
 }
 
 static int saa7134_s_tuner(struct file *file, void *priv,
-					struct v4l2_tuner *t)
+					const struct v4l2_tuner *t)
 {
 	struct saa7134_fh *fh = priv;
 	struct saa7134_dev *dev = fh->dev;
@@ -2057,7 +2057,7 @@ static int saa7134_g_frequency(struct file *file, void *priv,
 }
 
 static int saa7134_s_frequency(struct file *file, void *priv,
-					struct v4l2_frequency *f)
+					const struct v4l2_frequency *f)
 {
 	struct saa7134_fh *fh = priv;
 	struct saa7134_dev *dev = fh->dev;
@@ -2300,7 +2300,7 @@ static int vidioc_g_register (struct file *file, void *priv,
 }
 
 static int vidioc_s_register (struct file *file, void *priv,
-				struct v4l2_dbg_register *reg)
+				const struct v4l2_dbg_register *reg)
 {
 	struct saa7134_fh *fh = priv;
 	struct saa7134_dev *dev = fh->dev;
@@ -2347,7 +2347,7 @@ static int radio_g_tuner(struct file *file, void *priv,
 	return 0;
 }
 static int radio_s_tuner(struct file *file, void *priv,
-					struct v4l2_tuner *t)
+					const struct v4l2_tuner *t)
 {
 	struct saa7134_fh *fh = file->private_data;
 	struct saa7134_dev *dev = fh->dev;
@@ -2396,7 +2396,7 @@ static int radio_s_input(struct file *filp, void *priv, unsigned int i)
 	return 0;
 }
 
-static int radio_s_std(struct file *file, void *fh, v4l2_std_id *norm)
+static int radio_s_std(struct file *file, void *fh, v4l2_std_id norm)
 {
 	return 0;
 }
diff --git a/drivers/media/pci/saa7134/saa7134.h b/drivers/media/pci/saa7134/saa7134.h
index 71eefef..62169dd 100644
--- a/drivers/media/pci/saa7134/saa7134.h
+++ b/drivers/media/pci/saa7134/saa7134.h
@@ -766,7 +766,7 @@ extern struct video_device saa7134_radio_template;
 int saa7134_s_ctrl_internal(struct saa7134_dev *dev,  struct saa7134_fh *fh, struct v4l2_control *c);
 int saa7134_g_ctrl_internal(struct saa7134_dev *dev,  struct saa7134_fh *fh, struct v4l2_control *c);
 int saa7134_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *c);
-int saa7134_s_std_internal(struct saa7134_dev *dev,  struct saa7134_fh *fh, v4l2_std_id *id);
+int saa7134_s_std_internal(struct saa7134_dev *dev,  struct saa7134_fh *fh, v4l2_std_id id);
 
 int saa7134_videoport_init(struct saa7134_dev *dev);
 void saa7134_set_tvnorm_hw(struct saa7134_dev *dev);
diff --git a/drivers/media/pci/saa7146/mxb.c b/drivers/media/pci/saa7146/mxb.c
index 91369da..71e8bea 100644
--- a/drivers/media/pci/saa7146/mxb.c
+++ b/drivers/media/pci/saa7146/mxb.c
@@ -560,7 +560,7 @@ static int vidioc_g_tuner(struct file *file, void *fh, struct v4l2_tuner *t)
 	return call_all(dev, tuner, g_tuner, t);
 }
 
-static int vidioc_s_tuner(struct file *file, void *fh, struct v4l2_tuner *t)
+static int vidioc_s_tuner(struct file *file, void *fh, const struct v4l2_tuner *t)
 {
 	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
 	struct mxb *mxb = (struct mxb *)dev->ext_priv;
@@ -595,7 +595,7 @@ static int vidioc_g_frequency(struct file *file, void *fh, struct v4l2_frequency
 	return 0;
 }
 
-static int vidioc_s_frequency(struct file *file, void *fh, struct v4l2_frequency *f)
+static int vidioc_s_frequency(struct file *file, void *fh, const struct v4l2_frequency *f)
 {
 	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
 	struct mxb *mxb = (struct mxb *)dev->ext_priv;
@@ -612,8 +612,8 @@ static int vidioc_s_frequency(struct file *file, void *fh, struct v4l2_frequency
 	/* tune in desired frequency */
 	tuner_call(mxb, tuner, s_frequency, f);
 	/* let the tuner subdev clamp the frequency to the tuner range */
-	tuner_call(mxb, tuner, g_frequency, f);
 	mxb->cur_freq = *f;
+	tuner_call(mxb, tuner, g_frequency, &mxb->cur_freq);
 	if (mxb->cur_audinput == 0)
 		mxb_update_audmode(mxb);
 
@@ -680,7 +680,7 @@ static int vidioc_g_register(struct file *file, void *fh, struct v4l2_dbg_regist
 	return 0;
 }
 
-static int vidioc_s_register(struct file *file, void *fh, struct v4l2_dbg_register *reg)
+static int vidioc_s_register(struct file *file, void *fh, const struct v4l2_dbg_register *reg)
 {
 	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
 
@@ -688,7 +688,6 @@ static int vidioc_s_register(struct file *file, void *fh, struct v4l2_dbg_regist
 		return -EPERM;
 	if (v4l2_chip_match_host(&reg->match)) {
 		saa7146_write(dev, reg->reg, reg->val);
-		reg->size = 4;
 		return 0;
 	}
 	return call_all(dev, core, s_register, reg);
diff --git a/drivers/media/pci/saa7164/saa7164-encoder.c b/drivers/media/pci/saa7164/saa7164-encoder.c
index 9bb0903..0b74fb2 100644
--- a/drivers/media/pci/saa7164/saa7164-encoder.c
+++ b/drivers/media/pci/saa7164/saa7164-encoder.c
@@ -211,17 +211,17 @@ static int saa7164_encoder_initialize(struct saa7164_port *port)
 }
 
 /* -- V4L2 --------------------------------------------------------- */
-static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *id)
+static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id)
 {
 	struct saa7164_encoder_fh *fh = file->private_data;
 	struct saa7164_port *port = fh->port;
 	struct saa7164_dev *dev = port->dev;
 	unsigned int i;
 
-	dprintk(DBGLVL_ENC, "%s(id=0x%x)\n", __func__, (u32)*id);
+	dprintk(DBGLVL_ENC, "%s(id=0x%x)\n", __func__, (u32)id);
 
 	for (i = 0; i < ARRAY_SIZE(saa7164_tvnorms); i++) {
-		if (*id & saa7164_tvnorms[i].id)
+		if (id & saa7164_tvnorms[i].id)
 			break;
 	}
 	if (i == ARRAY_SIZE(saa7164_tvnorms))
@@ -234,7 +234,7 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *id)
 	 */
 	saa7164_api_set_audio_std(port);
 
-	dprintk(DBGLVL_ENC, "%s(id=0x%x) OK\n", __func__, (u32)*id);
+	dprintk(DBGLVL_ENC, "%s(id=0x%x) OK\n", __func__, (u32)id);
 
 	return 0;
 }
@@ -318,7 +318,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
 }
 
 static int vidioc_s_tuner(struct file *file, void *priv,
-	struct v4l2_tuner *t)
+	const struct v4l2_tuner *t)
 {
 	/* Update the A/V core */
 	return 0;
@@ -337,7 +337,7 @@ static int vidioc_g_frequency(struct file *file, void *priv,
 }
 
 static int vidioc_s_frequency(struct file *file, void *priv,
-	struct v4l2_frequency *f)
+	const struct v4l2_frequency *f)
 {
 	struct saa7164_encoder_fh *fh = file->private_data;
 	struct saa7164_port *port = fh->port;
@@ -1313,7 +1313,7 @@ static int saa7164_g_register(struct file *file, void *fh,
 }
 
 static int saa7164_s_register(struct file *file, void *fh,
-			      struct v4l2_dbg_register *reg)
+			      const struct v4l2_dbg_register *reg)
 {
 	struct saa7164_port *port = ((struct saa7164_encoder_fh *)fh)->port;
 	struct saa7164_dev *dev = port->dev;
diff --git a/drivers/media/pci/saa7164/saa7164-vbi.c b/drivers/media/pci/saa7164/saa7164-vbi.c
index b453229..da224eb 100644
--- a/drivers/media/pci/saa7164/saa7164-vbi.c
+++ b/drivers/media/pci/saa7164/saa7164-vbi.c
@@ -183,17 +183,17 @@ static int saa7164_vbi_initialize(struct saa7164_port *port)
 }
 
 /* -- V4L2 --------------------------------------------------------- */
-static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *id)
+static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id)
 {
 	struct saa7164_vbi_fh *fh = file->private_data;
 	struct saa7164_port *port = fh->port;
 	struct saa7164_dev *dev = port->dev;
 	unsigned int i;
 
-	dprintk(DBGLVL_VBI, "%s(id=0x%x)\n", __func__, (u32)*id);
+	dprintk(DBGLVL_VBI, "%s(id=0x%x)\n", __func__, (u32)id);
 
 	for (i = 0; i < ARRAY_SIZE(saa7164_tvnorms); i++) {
-		if (*id & saa7164_tvnorms[i].id)
+		if (id & saa7164_tvnorms[i].id)
 			break;
 	}
 	if (i == ARRAY_SIZE(saa7164_tvnorms))
@@ -206,7 +206,7 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *id)
 	 */
 	saa7164_api_set_audio_std(port);
 
-	dprintk(DBGLVL_VBI, "%s(id=0x%x) OK\n", __func__, (u32)*id);
+	dprintk(DBGLVL_VBI, "%s(id=0x%x) OK\n", __func__, (u32)id);
 
 	return 0;
 }
@@ -290,7 +290,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
 }
 
 static int vidioc_s_tuner(struct file *file, void *priv,
-	struct v4l2_tuner *t)
+	const struct v4l2_tuner *t)
 {
 	/* Update the A/V core */
 	return 0;
@@ -309,7 +309,7 @@ static int vidioc_g_frequency(struct file *file, void *priv,
 }
 
 static int vidioc_s_frequency(struct file *file, void *priv,
-	struct v4l2_frequency *f)
+	const struct v4l2_frequency *f)
 {
 	struct saa7164_vbi_fh *fh = file->private_data;
 	struct saa7164_port *port = fh->port;
diff --git a/drivers/media/pci/sta2x11/sta2x11_vip.c b/drivers/media/pci/sta2x11/sta2x11_vip.c
index 4b703fe..7005695 100644
--- a/drivers/media/pci/sta2x11/sta2x11_vip.c
+++ b/drivers/media/pci/sta2x11/sta2x11_vip.c
@@ -439,22 +439,22 @@ static int vidioc_querycap(struct file *file, void *priv,
  *
  * other, returned from video DAC.
  */
-static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *std)
+static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id std)
 {
 	struct sta2x11_vip *vip = video_drvdata(file);
 	v4l2_std_id oldstd = vip->std, newstd;
 	int status;
 
-	if (V4L2_STD_ALL == *std) {
-		v4l2_subdev_call(vip->decoder, core, s_std, *std);
+	if (V4L2_STD_ALL == std) {
+		v4l2_subdev_call(vip->decoder, core, s_std, std);
 		ssleep(2);
 		v4l2_subdev_call(vip->decoder, video, querystd, &newstd);
 		v4l2_subdev_call(vip->decoder, video, g_input_status, &status);
 		if (status & V4L2_IN_ST_NO_SIGNAL)
 			return -EIO;
-		*std = vip->std = newstd;
-		if (oldstd != *std) {
-			if (V4L2_STD_525_60 & (*std))
+		std = vip->std = newstd;
+		if (oldstd != std) {
+			if (V4L2_STD_525_60 & std)
 				vip->format = formats_60[0];
 			else
 				vip->format = formats_50[0];
@@ -462,14 +462,14 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *std)
 		return 0;
 	}
 
-	if (oldstd != *std) {
-		if (V4L2_STD_525_60 & (*std))
+	if (oldstd != std) {
+		if (V4L2_STD_525_60 & std)
 			vip->format = formats_60[0];
 		else
 			vip->format = formats_50[0];
 	}
 
-	return v4l2_subdev_call(vip->decoder, core, s_std, *std);
+	return v4l2_subdev_call(vip->decoder, core, s_std, std);
 }
 
 /**
diff --git a/drivers/media/pci/ttpci/av7110_v4l.c b/drivers/media/pci/ttpci/av7110_v4l.c
index 730e906..6c4076a 100644
--- a/drivers/media/pci/ttpci/av7110_v4l.c
+++ b/drivers/media/pci/ttpci/av7110_v4l.c
@@ -366,7 +366,7 @@ static int vidioc_g_tuner(struct file *file, void *fh, struct v4l2_tuner *t)
 	return 0;
 }
 
-static int vidioc_s_tuner(struct file *file, void *fh, struct v4l2_tuner *t)
+static int vidioc_s_tuner(struct file *file, void *fh, const struct v4l2_tuner *t)
 {
 	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
 	struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
@@ -426,7 +426,7 @@ static int vidioc_g_frequency(struct file *file, void *fh, struct v4l2_frequency
 	return 0;
 }
 
-static int vidioc_s_frequency(struct file *file, void *fh, struct v4l2_frequency *f)
+static int vidioc_s_frequency(struct file *file, void *fh, const struct v4l2_frequency *f)
 {
 	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
 	struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
diff --git a/drivers/media/pci/zoran/zoran_driver.c b/drivers/media/pci/zoran/zoran_driver.c
index 2e8f518..1168a84 100644
--- a/drivers/media/pci/zoran/zoran_driver.c
+++ b/drivers/media/pci/zoran/zoran_driver.c
@@ -2435,14 +2435,14 @@ static int zoran_g_std(struct file *file, void *__fh, v4l2_std_id *std)
 	return 0;
 }
 
-static int zoran_s_std(struct file *file, void *__fh, v4l2_std_id *std)
+static int zoran_s_std(struct file *file, void *__fh, v4l2_std_id std)
 {
 	struct zoran_fh *fh = __fh;
 	struct zoran *zr = fh->zr;
 	int res = 0;
 
 	mutex_lock(&zr->resource_lock);
-	res = zoran_set_norm(zr, *std);
+	res = zoran_set_norm(zr, std);
 	if (res)
 		goto sstd_unlock_and_return;
 
diff --git a/drivers/media/pci/zoran/zoran_procfs.c b/drivers/media/pci/zoran/zoran_procfs.c
index e084b0a..07a104d 100644
--- a/drivers/media/pci/zoran/zoran_procfs.c
+++ b/drivers/media/pci/zoran/zoran_procfs.c
@@ -130,14 +130,14 @@ static int zoran_show(struct seq_file *p, void *v)
 
 static int zoran_open(struct inode *inode, struct file *file)
 {
-	struct zoran *data = PDE(inode)->data;
+	struct zoran *data = PDE_DATA(inode);
 	return single_open(file, zoran_show, data);
 }
 
 static ssize_t zoran_write(struct file *file, const char __user *buffer,
 			size_t count, loff_t *ppos)
 {
-	struct zoran *zr = PDE(file_inode(file))->data;
+	struct zoran *zr = PDE_DATA(file_inode(file));
 	char *string, *sp;
 	char *line, *ldelim, *varname, *svar, *tdelim;
 
diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
index 05d7b63..077eeeb 100644
--- a/drivers/media/platform/Kconfig
+++ b/drivers/media/platform/Kconfig
@@ -204,7 +204,7 @@ config VIDEO_SAMSUNG_EXYNOS_GSC
 
 config VIDEO_SH_VEU
 	tristate "SuperH VEU mem2mem video processing driver"
-	depends on VIDEO_DEV && VIDEO_V4L2
+	depends on VIDEO_DEV && VIDEO_V4L2 && GENERIC_HARDIRQS && HAS_DMA
 	select VIDEOBUF2_DMA_CONTIG
 	select V4L2_MEM2MEM_DEV
 	help
diff --git a/drivers/media/platform/blackfin/bfin_capture.c b/drivers/media/platform/blackfin/bfin_capture.c
index 5f209d5..0e55b08 100644
--- a/drivers/media/platform/blackfin/bfin_capture.c
+++ b/drivers/media/platform/blackfin/bfin_capture.c
@@ -384,7 +384,7 @@ static int bcap_start_streaming(struct vb2_queue *vq, unsigned int count)
 	params.ppi_control = bcap_dev->cfg->ppi_control;
 	params.int_mask = bcap_dev->cfg->int_mask;
 	if (bcap_dev->cfg->inputs[bcap_dev->cur_input].capabilities
-			& V4L2_IN_CAP_CUSTOM_TIMINGS) {
+			& V4L2_IN_CAP_DV_TIMINGS) {
 		struct v4l2_bt_timings *bt = &bcap_dev->dv_timings.bt;
 
 		params.hdelay = bt->hsync + bt->hbackporch;
@@ -633,7 +633,7 @@ static int bcap_g_std(struct file *file, void *priv, v4l2_std_id *std)
 	return 0;
 }
 
-static int bcap_s_std(struct file *file, void *priv, v4l2_std_id *std)
+static int bcap_s_std(struct file *file, void *priv, v4l2_std_id std)
 {
 	struct bcap_device *bcap_dev = video_drvdata(file);
 	int ret;
@@ -641,11 +641,11 @@ static int bcap_s_std(struct file *file, void *priv, v4l2_std_id *std)
 	if (vb2_is_busy(&bcap_dev->buffer_queue))
 		return -EBUSY;
 
-	ret = v4l2_subdev_call(bcap_dev->sd, core, s_std, *std);
+	ret = v4l2_subdev_call(bcap_dev->sd, core, s_std, std);
 	if (ret < 0)
 		return ret;
 
-	bcap_dev->std = *std;
+	bcap_dev->std = std;
 	return 0;
 }
 
@@ -890,7 +890,7 @@ static int bcap_dbg_g_register(struct file *file, void *priv,
 }
 
 static int bcap_dbg_s_register(struct file *file, void *priv,
-		struct v4l2_dbg_register *reg)
+		const struct v4l2_dbg_register *reg)
 {
 	struct bcap_device *bcap_dev = video_drvdata(file);
 
@@ -1029,6 +1029,7 @@ static int bcap_probe(struct platform_device *pdev)
 	q->buf_struct_size = sizeof(struct bcap_buffer);
 	q->ops = &bcap_video_qops;
 	q->mem_ops = &vb2_dma_contig_memops;
+	q->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
 
 	vb2_queue_init(q);
 
@@ -1110,7 +1111,7 @@ static int bcap_probe(struct platform_device *pdev)
 		}
 		bcap_dev->std = std;
 	}
-	if (config->inputs[0].capabilities & V4L2_IN_CAP_CUSTOM_TIMINGS) {
+	if (config->inputs[0].capabilities & V4L2_IN_CAP_DV_TIMINGS) {
 		struct v4l2_dv_timings dv_timings;
 		ret = v4l2_subdev_call(bcap_dev->sd, video,
 				g_dv_timings, &dv_timings);
diff --git a/drivers/media/platform/davinci/dm355_ccdc.c b/drivers/media/platform/davinci/dm355_ccdc.c
index 4277e4a..2364dba 100644
--- a/drivers/media/platform/davinci/dm355_ccdc.c
+++ b/drivers/media/platform/davinci/dm355_ccdc.c
@@ -85,7 +85,7 @@ static struct ccdc_oper_config {
 			.mfilt1 = CCDC_NO_MEDIAN_FILTER1,
 			.mfilt2 = CCDC_NO_MEDIAN_FILTER2,
 			.alaw = {
-				.gama_wd = 2,
+				.gamma_wd = 2,
 			},
 			.blk_clamp = {
 				.sample_pixel = 1,
@@ -303,8 +303,8 @@ static int validate_ccdc_param(struct ccdc_config_params_raw *ccdcparam)
 	}
 
 	if (ccdcparam->alaw.enable) {
-		if (ccdcparam->alaw.gama_wd < CCDC_GAMMA_BITS_13_4 ||
-		    ccdcparam->alaw.gama_wd > CCDC_GAMMA_BITS_09_0) {
+		if (ccdcparam->alaw.gamma_wd < CCDC_GAMMA_BITS_13_4 ||
+		    ccdcparam->alaw.gamma_wd > CCDC_GAMMA_BITS_09_0) {
 			dev_dbg(ccdc_cfg.dev, "Invalid value of ALAW\n");
 			return -EINVAL;
 		}
@@ -680,8 +680,8 @@ static int ccdc_config_raw(void)
 	/* Enable and configure aLaw register if needed */
 	if (config_params->alaw.enable) {
 		val |= (CCDC_ALAW_ENABLE |
-			((config_params->alaw.gama_wd &
-			CCDC_ALAW_GAMA_WD_MASK) <<
+			((config_params->alaw.gamma_wd &
+			CCDC_ALAW_GAMMA_WD_MASK) <<
 			CCDC_GAMMAWD_INPUT_SHIFT));
 	}
 
diff --git a/drivers/media/platform/davinci/dm355_ccdc_regs.h b/drivers/media/platform/davinci/dm355_ccdc_regs.h
index d6d2ef0..2e1946e 100644
--- a/drivers/media/platform/davinci/dm355_ccdc_regs.h
+++ b/drivers/media/platform/davinci/dm355_ccdc_regs.h
@@ -153,7 +153,7 @@
 #define CCDC_VDHDEN_ENABLE			(1 << 16)
 #define CCDC_LPF_ENABLE				(1 << 14)
 #define CCDC_ALAW_ENABLE			1
-#define CCDC_ALAW_GAMA_WD_MASK			7
+#define CCDC_ALAW_GAMMA_WD_MASK			7
 #define CCDC_REC656IF_BT656_EN			3
 
 #define CCDC_FMTCFG_FMTMODE_MASK 		3
diff --git a/drivers/media/platform/davinci/dm644x_ccdc.c b/drivers/media/platform/davinci/dm644x_ccdc.c
index 318e805..971d639 100644
--- a/drivers/media/platform/davinci/dm644x_ccdc.c
+++ b/drivers/media/platform/davinci/dm644x_ccdc.c
@@ -228,9 +228,12 @@ static void ccdc_readregs(void)
 static int validate_ccdc_param(struct ccdc_config_params_raw *ccdcparam)
 {
 	if (ccdcparam->alaw.enable) {
-		if ((ccdcparam->alaw.gama_wd > CCDC_GAMMA_BITS_09_0) ||
-		    (ccdcparam->alaw.gama_wd < CCDC_GAMMA_BITS_15_6) ||
-		    (ccdcparam->alaw.gama_wd < ccdcparam->data_sz)) {
+		u8 max_gamma = ccdc_gamma_width_max_bit(ccdcparam->alaw.gamma_wd);
+		u8 max_data = ccdc_data_size_max_bit(ccdcparam->data_sz);
+
+		if ((ccdcparam->alaw.gamma_wd > CCDC_GAMMA_BITS_09_0) ||
+		    (ccdcparam->alaw.gamma_wd < CCDC_GAMMA_BITS_15_6) ||
+		    (max_gamma > max_data)) {
 			dev_dbg(ccdc_cfg.dev, "\nInvalid data line select");
 			return -1;
 		}
@@ -560,8 +563,8 @@ void ccdc_config_raw(void)
 
 	/* Enable and configure aLaw register if needed */
 	if (config_params->alaw.enable) {
-		val = ((config_params->alaw.gama_wd &
-		      CCDC_ALAW_GAMA_WD_MASK) | CCDC_ALAW_ENABLE);
+		val = ((config_params->alaw.gamma_wd &
+		      CCDC_ALAW_GAMMA_WD_MASK) | CCDC_ALAW_ENABLE);
 		regw(val, CCDC_ALAW);
 		dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to ALAW...\n", val);
 	}
diff --git a/drivers/media/platform/davinci/dm644x_ccdc_regs.h b/drivers/media/platform/davinci/dm644x_ccdc_regs.h
index 90370e4..2b0aca5 100644
--- a/drivers/media/platform/davinci/dm644x_ccdc_regs.h
+++ b/drivers/media/platform/davinci/dm644x_ccdc_regs.h
@@ -84,7 +84,7 @@
 #define CCDC_VDHDEN_ENABLE			(1 << 16)
 #define CCDC_LPF_ENABLE				(1 << 14)
 #define CCDC_ALAW_ENABLE			(1 << 3)
-#define CCDC_ALAW_GAMA_WD_MASK			7
+#define CCDC_ALAW_GAMMA_WD_MASK			7
 #define CCDC_BLK_CLAMP_ENABLE			(1 << 31)
 #define CCDC_BLK_SGAIN_MASK			0x1F
 #define CCDC_BLK_ST_PXL_MASK			0x7FFF
diff --git a/drivers/media/platform/davinci/isif.c b/drivers/media/platform/davinci/isif.c
index 5050f92..abc3ae3 100644
--- a/drivers/media/platform/davinci/isif.c
+++ b/drivers/media/platform/davinci/isif.c
@@ -604,7 +604,7 @@ static int isif_config_raw(void)
 	if (module_params->compress.alg == ISIF_ALAW)
 		val |= ISIF_ALAW_ENABLE;
 
-	val |= (params->data_msb << ISIF_ALAW_GAMA_WD_SHIFT);
+	val |= (params->data_msb << ISIF_ALAW_GAMMA_WD_SHIFT);
 	regw(val, CGAMMAWD);
 
 	/* Configure DPCM compression settings */
diff --git a/drivers/media/platform/davinci/isif_regs.h b/drivers/media/platform/davinci/isif_regs.h
index aa69a46..3993aec 100644
--- a/drivers/media/platform/davinci/isif_regs.h
+++ b/drivers/media/platform/davinci/isif_regs.h
@@ -203,8 +203,8 @@
 #define ISIF_LPF_MASK				1
 
 /* GAMMAWD registers */
-#define ISIF_ALAW_GAMA_WD_MASK			0xF
-#define ISIF_ALAW_GAMA_WD_SHIFT			1
+#define ISIF_ALAW_GAMMA_WD_MASK			0xF
+#define ISIF_ALAW_GAMMA_WD_SHIFT		1
 #define ISIF_ALAW_ENABLE			1
 #define ISIF_GAMMAWD_CFA_SHIFT			5
 
diff --git a/drivers/media/platform/davinci/vpbe.c b/drivers/media/platform/davinci/vpbe.c
index 4ca0f9a..33b9660 100644
--- a/drivers/media/platform/davinci/vpbe.c
+++ b/drivers/media/platform/davinci/vpbe.c
@@ -344,7 +344,7 @@ static int vpbe_s_dv_timings(struct vpbe_device *vpbe_dev,
 		return -EINVAL;
 
 	for (i = 0; i < output->num_modes; i++) {
-		if (output->modes[i].timings_type == VPBE_ENC_CUSTOM_TIMINGS &&
+		if (output->modes[i].timings_type == VPBE_ENC_DV_TIMINGS &&
 		    !memcmp(&output->modes[i].dv_timings,
 				dv_timings, sizeof(*dv_timings)))
 			break;
@@ -385,7 +385,7 @@ static int vpbe_g_dv_timings(struct vpbe_device *vpbe_dev,
 		     struct v4l2_dv_timings *dv_timings)
 {
 	if (vpbe_dev->current_timings.timings_type &
-	  VPBE_ENC_CUSTOM_TIMINGS) {
+	  VPBE_ENC_DV_TIMINGS) {
 		*dv_timings = vpbe_dev->current_timings.dv_timings;
 		return 0;
 	}
@@ -412,7 +412,7 @@ static int vpbe_enum_dv_timings(struct vpbe_device *vpbe_dev,
 		return -EINVAL;
 
 	for (i = 0; i < output->num_modes; i++) {
-		if (output->modes[i].timings_type == VPBE_ENC_CUSTOM_TIMINGS) {
+		if (output->modes[i].timings_type == VPBE_ENC_DV_TIMINGS) {
 			if (j == timings->index)
 				break;
 			j++;
@@ -431,7 +431,7 @@ static int vpbe_enum_dv_timings(struct vpbe_device *vpbe_dev,
  * Sets the standard if supported by the current encoder. Return the status.
  * 0 - success & -EINVAL on error
  */
-static int vpbe_s_std(struct vpbe_device *vpbe_dev, v4l2_std_id *std_id)
+static int vpbe_s_std(struct vpbe_device *vpbe_dev, v4l2_std_id std_id)
 {
 	struct vpbe_config *cfg = vpbe_dev->cfg;
 	int out_index = vpbe_dev->current_out_index;
@@ -442,14 +442,14 @@ static int vpbe_s_std(struct vpbe_device *vpbe_dev, v4l2_std_id *std_id)
 		V4L2_OUT_CAP_STD))
 		return -EINVAL;
 
-	ret = vpbe_get_std_info(vpbe_dev, *std_id);
+	ret = vpbe_get_std_info(vpbe_dev, std_id);
 	if (ret)
 		return ret;
 
 	mutex_lock(&vpbe_dev->lock);
 
 	ret = v4l2_subdev_call(vpbe_dev->encoders[sd_index], video,
-			       s_std_output, *std_id);
+			       s_std_output, std_id);
 	/* set the lcd controller output for the given mode */
 	if (!ret) {
 		struct osd_state *osd_device = vpbe_dev->osd_device;
@@ -513,9 +513,9 @@ static int vpbe_set_mode(struct vpbe_device *vpbe_dev,
 			 */
 			if (preset_mode->timings_type & VPBE_ENC_STD)
 				return vpbe_s_std(vpbe_dev,
-						 &preset_mode->std_id);
+						 preset_mode->std_id);
 			if (preset_mode->timings_type &
-						VPBE_ENC_CUSTOM_TIMINGS) {
+						VPBE_ENC_DV_TIMINGS) {
 				dv_timings =
 					preset_mode->dv_timings;
 				return vpbe_s_dv_timings(vpbe_dev, &dv_timings);
diff --git a/drivers/media/platform/davinci/vpbe_display.c b/drivers/media/platform/davinci/vpbe_display.c
index 5e6b0ca..1802f11 100644
--- a/drivers/media/platform/davinci/vpbe_display.c
+++ b/drivers/media/platform/davinci/vpbe_display.c
@@ -983,7 +983,7 @@ static int vpbe_display_try_fmt(struct file *file, void *priv,
  * 0 - success & -EINVAL on error
  */
 static int vpbe_display_s_std(struct file *file, void *priv,
-				v4l2_std_id *std_id)
+				v4l2_std_id std_id)
 {
 	struct vpbe_fh *fh = priv;
 	struct vpbe_layer *layer = fh->layer;
@@ -1176,10 +1176,6 @@ vpbe_display_s_dv_timings(struct file *file, void *priv,
 			"Failed to set the dv timings info\n");
 		return -EINVAL;
 	}
-	/* set the current norm to zero to be consistent. If STD is used
-	 * v4l2 layer will set the norm properly on successful s_std call
-	 */
-	layer->video_dev.current_norm = 0;
 
 	return 0;
 }
@@ -1202,7 +1198,7 @@ vpbe_display_g_dv_timings(struct file *file, void *priv,
 	/* Get the given standard in the encoder */
 
 	if (vpbe_dev->current_timings.timings_type &
-				VPBE_ENC_CUSTOM_TIMINGS) {
+				VPBE_ENC_DV_TIMINGS) {
 		*dv_timings = vpbe_dev->current_timings.dv_timings;
 	} else {
 		return -EINVAL;
@@ -1404,6 +1400,7 @@ static int vpbe_display_reqbufs(struct file *file, void *priv,
 	q->ops = &video_qops;
 	q->mem_ops = &vb2_dma_contig_memops;
 	q->buf_struct_size = sizeof(struct vpbe_disp_buffer);
+	q->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
 
 	ret = vb2_queue_init(q);
 	if (ret) {
@@ -1600,7 +1597,7 @@ static int vpbe_display_g_register(struct file *file, void *priv,
 }
 
 static int vpbe_display_s_register(struct file *file, void *priv,
-			struct v4l2_dbg_register *reg)
+			const struct v4l2_dbg_register *reg)
 {
 	return 0;
 }
@@ -1693,12 +1690,8 @@ static int init_vpbe_layer(int i, struct vpbe_display *disp_dev,
 	vbd->vfl_dir	= VFL_DIR_TX;
 
 	if (disp_dev->vpbe_dev->current_timings.timings_type &
-			VPBE_ENC_STD) {
+			VPBE_ENC_STD)
 		vbd->tvnorms = (V4L2_STD_525_60 | V4L2_STD_625_50);
-		vbd->current_norm =
-			disp_dev->vpbe_dev->current_timings.std_id;
-	} else
-		vbd->current_norm = 0;
 
 	snprintf(vbd->name, sizeof(vbd->name),
 			"DaVinci_VPBE Display_DRIVER_V%d.%d.%d",
diff --git a/drivers/media/platform/davinci/vpbe_osd.c b/drivers/media/platform/davinci/vpbe_osd.c
index 12ad17c..396a51c 100644
--- a/drivers/media/platform/davinci/vpbe_osd.c
+++ b/drivers/media/platform/davinci/vpbe_osd.c
@@ -52,6 +52,9 @@ static struct platform_device_id vpbe_osd_devtype[] = {
 		.name = DM355_VPBE_OSD_SUBDEV_NAME,
 		.driver_data = VPBE_VERSION_3,
 	},
+	{
+		/* sentinel */
+	}
 };
 
 MODULE_DEVICE_TABLE(platform, vpbe_osd_devtype);
diff --git a/drivers/media/platform/davinci/vpbe_venc.c b/drivers/media/platform/davinci/vpbe_venc.c
index bdbebd5..f15f211 100644
--- a/drivers/media/platform/davinci/vpbe_venc.c
+++ b/drivers/media/platform/davinci/vpbe_venc.c
@@ -51,6 +51,9 @@ static struct platform_device_id vpbe_venc_devtype[] = {
 		.name = DM355_VPBE_VENC_SUBDEV_NAME,
 		.driver_data = VPBE_VERSION_3,
 	},
+	{
+		/* sentinel */
+	}
 };
 
 MODULE_DEVICE_TABLE(platform, vpbe_venc_devtype);
@@ -313,7 +316,7 @@ static int venc_set_480p59_94(struct v4l2_subdev *sd)
 		return -EINVAL;
 
 	/* Setup clock at VPSS & VENC for SD */
-	if (pdata->setup_clock(VPBE_ENC_CUSTOM_TIMINGS, 27000000) < 0)
+	if (pdata->setup_clock(VPBE_ENC_DV_TIMINGS, 27000000) < 0)
 		return -EINVAL;
 
 	venc_enabledigitaloutput(sd, 0);
@@ -360,7 +363,7 @@ static int venc_set_576p50(struct v4l2_subdev *sd)
 	    venc->venc_type != VPBE_VERSION_2)
 		return -EINVAL;
 	/* Setup clock at VPSS & VENC for SD */
-	if (pdata->setup_clock(VPBE_ENC_CUSTOM_TIMINGS, 27000000) < 0)
+	if (pdata->setup_clock(VPBE_ENC_DV_TIMINGS, 27000000) < 0)
 		return -EINVAL;
 
 	venc_enabledigitaloutput(sd, 0);
@@ -400,7 +403,7 @@ static int venc_set_720p60_internal(struct v4l2_subdev *sd)
 	struct venc_state *venc = to_state(sd);
 	struct venc_platform_data *pdata = venc->pdata;
 
-	if (pdata->setup_clock(VPBE_ENC_CUSTOM_TIMINGS, 74250000) < 0)
+	if (pdata->setup_clock(VPBE_ENC_DV_TIMINGS, 74250000) < 0)
 		return -EINVAL;
 
 	venc_enabledigitaloutput(sd, 0);
@@ -428,7 +431,7 @@ static int venc_set_1080i30_internal(struct v4l2_subdev *sd)
 	struct venc_state *venc = to_state(sd);
 	struct venc_platform_data *pdata = venc->pdata;
 
-	if (pdata->setup_clock(VPBE_ENC_CUSTOM_TIMINGS, 74250000) < 0)
+	if (pdata->setup_clock(VPBE_ENC_DV_TIMINGS, 74250000) < 0)
 		return -EINVAL;
 
 	venc_enabledigitaloutput(sd, 0);
diff --git a/drivers/media/platform/davinci/vpfe_capture.c b/drivers/media/platform/davinci/vpfe_capture.c
index 28d019d..8c50d30 100644
--- a/drivers/media/platform/davinci/vpfe_capture.c
+++ b/drivers/media/platform/davinci/vpfe_capture.c
@@ -376,7 +376,7 @@ static int vpfe_config_ccdc_image_format(struct vpfe_device *vpfe_dev)
  * values in ccdc
  */
 static int vpfe_config_image_format(struct vpfe_device *vpfe_dev,
-				    const v4l2_std_id *std_id)
+				    v4l2_std_id std_id)
 {
 	struct vpfe_subdev_info *sdinfo = vpfe_dev->current_subdev;
 	struct v4l2_mbus_framefmt mbus_fmt;
@@ -384,7 +384,7 @@ static int vpfe_config_image_format(struct vpfe_device *vpfe_dev,
 	int i, ret = 0;
 
 	for (i = 0; i < ARRAY_SIZE(vpfe_standards); i++) {
-		if (vpfe_standards[i].std_id & *std_id) {
+		if (vpfe_standards[i].std_id & std_id) {
 			vpfe_dev->std_info.active_pixels =
 					vpfe_standards[i].width;
 			vpfe_dev->std_info.active_lines =
@@ -461,7 +461,7 @@ static int vpfe_initialize_device(struct vpfe_device *vpfe_dev)
 
 	/* Configure the default format information */
 	ret = vpfe_config_image_format(vpfe_dev,
-				&vpfe_standards[vpfe_dev->std_index].std_id);
+				vpfe_standards[vpfe_dev->std_index].std_id);
 	if (ret)
 		return ret;
 
@@ -1107,6 +1107,7 @@ static int vpfe_g_input(struct file *file, void *priv, unsigned int *index)
 static int vpfe_s_input(struct file *file, void *priv, unsigned int index)
 {
 	struct vpfe_device *vpfe_dev = video_drvdata(file);
+	struct v4l2_subdev *sd;
 	struct vpfe_subdev_info *sdinfo;
 	int subdev_index, inp_index;
 	struct vpfe_route *route;
@@ -1138,14 +1139,15 @@ static int vpfe_s_input(struct file *file, void *priv, unsigned int index)
 	}
 
 	sdinfo = &vpfe_dev->cfg->sub_devs[subdev_index];
+	sd = vpfe_dev->sd[subdev_index];
 	route = &sdinfo->routes[inp_index];
 	if (route && sdinfo->can_route) {
 		input = route->input;
 		output = route->output;
 	}
 
-	ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id,
-					 video, s_routing, input, output, 0);
+	if (sd)
+		ret = v4l2_subdev_call(sd, video, s_routing, input, output, 0);
 
 	if (ret) {
 		v4l2_err(&vpfe_dev->v4l2_dev,
@@ -1154,6 +1156,8 @@ static int vpfe_s_input(struct file *file, void *priv, unsigned int index)
 		goto unlock_out;
 	}
 	vpfe_dev->current_subdev = sdinfo;
+	if (sd)
+		vpfe_dev->v4l2_dev.ctrl_handler = sd->ctrl_handler;
 	vpfe_dev->current_input = index;
 	vpfe_dev->std_index = 0;
 
@@ -1164,7 +1168,7 @@ static int vpfe_s_input(struct file *file, void *priv, unsigned int index)
 
 	/* set the default image parameters in the device */
 	ret = vpfe_config_image_format(vpfe_dev,
-				&vpfe_standards[vpfe_dev->std_index].std_id);
+				vpfe_standards[vpfe_dev->std_index].std_id);
 unlock_out:
 	mutex_unlock(&vpfe_dev->lock);
 	return ret;
@@ -1189,7 +1193,7 @@ static int vpfe_querystd(struct file *file, void *priv, v4l2_std_id *std_id)
 	return ret;
 }
 
-static int vpfe_s_std(struct file *file, void *priv, v4l2_std_id *std_id)
+static int vpfe_s_std(struct file *file, void *priv, v4l2_std_id std_id)
 {
 	struct vpfe_device *vpfe_dev = video_drvdata(file);
 	struct vpfe_subdev_info *sdinfo;
@@ -1211,7 +1215,7 @@ static int vpfe_s_std(struct file *file, void *priv, v4l2_std_id *std_id)
 	}
 
 	ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id,
-					 core, s_std, *std_id);
+					 core, s_std, std_id);
 	if (ret < 0) {
 		v4l2_err(&vpfe_dev->v4l2_dev, "Failed to set standard\n");
 		goto unlock_out;
@@ -1439,41 +1443,6 @@ static int vpfe_dqbuf(struct file *file, void *priv,
 				      buf, file->f_flags & O_NONBLOCK);
 }
 
-static int vpfe_queryctrl(struct file *file, void *priv,
-		struct v4l2_queryctrl *qctrl)
-{
-	struct vpfe_device *vpfe_dev = video_drvdata(file);
-	struct vpfe_subdev_info *sdinfo;
-
-	sdinfo = vpfe_dev->current_subdev;
-
-	return v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id,
-					 core, queryctrl, qctrl);
-
-}
-
-static int vpfe_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl)
-{
-	struct vpfe_device *vpfe_dev = video_drvdata(file);
-	struct vpfe_subdev_info *sdinfo;
-
-	sdinfo = vpfe_dev->current_subdev;
-
-	return v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id,
-					 core, g_ctrl, ctrl);
-}
-
-static int vpfe_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl)
-{
-	struct vpfe_device *vpfe_dev = video_drvdata(file);
-	struct vpfe_subdev_info *sdinfo;
-
-	sdinfo = vpfe_dev->current_subdev;
-
-	return v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id,
-					 core, s_ctrl, ctrl);
-}
-
 /*
  * vpfe_calculate_offsets : This function calculates buffers offset
  * for top and bottom field
@@ -1717,7 +1686,7 @@ unlock_out:
 
 
 static long vpfe_param_handler(struct file *file, void *priv,
-		bool valid_prio, int cmd, void *param)
+		bool valid_prio, unsigned int cmd, void *param)
 {
 	struct vpfe_device *vpfe_dev = video_drvdata(file);
 	int ret = 0;
@@ -1781,9 +1750,6 @@ static const struct v4l2_ioctl_ops vpfe_ioctl_ops = {
 	.vidioc_querystd	 = vpfe_querystd,
 	.vidioc_s_std		 = vpfe_s_std,
 	.vidioc_g_std		 = vpfe_g_std,
-	.vidioc_queryctrl	 = vpfe_queryctrl,
-	.vidioc_g_ctrl		 = vpfe_g_ctrl,
-	.vidioc_s_ctrl		 = vpfe_s_ctrl,
 	.vidioc_reqbufs		 = vpfe_reqbufs,
 	.vidioc_querybuf	 = vpfe_querybuf,
 	.vidioc_qbuf		 = vpfe_qbuf,
@@ -1918,7 +1884,6 @@ static int vpfe_probe(struct platform_device *pdev)
 	vfd->fops		= &vpfe_fops;
 	vfd->ioctl_ops		= &vpfe_ioctl_ops;
 	vfd->tvnorms		= 0;
-	vfd->current_norm	= V4L2_STD_PAL;
 	vfd->v4l2_dev 		= &vpfe_dev->v4l2_dev;
 	snprintf(vfd->name, sizeof(vfd->name),
 		 "%s_V%d.%d.%d",
@@ -2007,6 +1972,7 @@ static int vpfe_probe(struct platform_device *pdev)
 
 	/* set first sub device as current one */
 	vpfe_dev->current_subdev = &vpfe_cfg->sub_devs[0];
+	vpfe_dev->v4l2_dev.ctrl_handler = vpfe_dev->sd[0]->ctrl_handler;
 
 	/* We have at least one sub device to work with */
 	mutex_unlock(&ccdc_lock);
diff --git a/drivers/media/platform/davinci/vpif.c b/drivers/media/platform/davinci/vpif.c
index 28638a8..3bc4db8 100644
--- a/drivers/media/platform/davinci/vpif.c
+++ b/drivers/media/platform/davinci/vpif.c
@@ -44,13 +44,15 @@ static struct resource	*res;
 spinlock_t vpif_lock;
 
 void __iomem *vpif_base;
+EXPORT_SYMBOL_GPL(vpif_base);
+
 struct clk *vpif_clk;
 
 /**
- * ch_params: video standard configuration parameters for vpif
+ * vpif_ch_params: video standard configuration parameters for vpif
  * The table must include all presets from supported subdevices.
  */
-const struct vpif_channel_config_params ch_params[] = {
+const struct vpif_channel_config_params vpif_ch_params[] = {
 	/* HDTV formats */
 	{
 		.name = "480p59_94",
@@ -220,8 +222,10 @@ const struct vpif_channel_config_params ch_params[] = {
 		.stdid = V4L2_STD_625_50,
 	},
 };
+EXPORT_SYMBOL_GPL(vpif_ch_params);
 
-const unsigned int vpif_ch_params_count = ARRAY_SIZE(ch_params);
+const unsigned int vpif_ch_params_count = ARRAY_SIZE(vpif_ch_params);
+EXPORT_SYMBOL_GPL(vpif_ch_params_count);
 
 static inline void vpif_wr_bit(u32 reg, u32 bit, u32 val)
 {
diff --git a/drivers/media/platform/davinci/vpif.h b/drivers/media/platform/davinci/vpif.h
index a1ab6a0..9956e67 100644
--- a/drivers/media/platform/davinci/vpif.h
+++ b/drivers/media/platform/davinci/vpif.h
@@ -638,7 +638,7 @@ struct vpif_channel_config_params {
 };
 
 extern const unsigned int vpif_ch_params_count;
-extern const struct vpif_channel_config_params ch_params[];
+extern const struct vpif_channel_config_params vpif_ch_params[];
 
 struct vpif_video_params;
 struct vpif_params;
diff --git a/drivers/media/platform/davinci/vpif_capture.c b/drivers/media/platform/davinci/vpif_capture.c
index 5892d2b..5f98df1 100644
--- a/drivers/media/platform/davinci/vpif_capture.c
+++ b/drivers/media/platform/davinci/vpif_capture.c
@@ -563,7 +563,7 @@ static int vpif_update_std_info(struct channel_obj *ch)
 	vpif_dbg(2, debug, "vpif_update_std_info\n");
 
 	for (index = 0; index < vpif_ch_params_count; index++) {
-		config = &ch_params[index];
+		config = &vpif_ch_params[index];
 		if (config->hd_sd == 0) {
 			vpif_dbg(2, debug, "SD format\n");
 			if (config->stdid & vid_ch->stdid) {
@@ -1035,6 +1035,7 @@ static int vpif_reqbufs(struct file *file, void *priv,
 	q->ops = &video_qops;
 	q->mem_ops = &vb2_dma_contig_memops;
 	q->buf_struct_size = sizeof(struct vpif_cap_buffer);
+	q->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
 
 	ret = vb2_queue_init(q);
 	if (ret) {
@@ -1394,7 +1395,7 @@ static int vpif_g_std(struct file *file, void *priv, v4l2_std_id *std)
  * @priv: file handle
  * @std_id: ptr to std id
  */
-static int vpif_s_std(struct file *file, void *priv, v4l2_std_id *std_id)
+static int vpif_s_std(struct file *file, void *priv, v4l2_std_id std_id)
 {
 	struct vpif_fh *fh = priv;
 	struct channel_obj *ch = fh->channel;
@@ -1423,7 +1424,7 @@ static int vpif_s_std(struct file *file, void *priv, v4l2_std_id *std_id)
 	fh->initialized = 1;
 
 	/* Call encoder subdevice function to set the standard */
-	ch->video.stdid = *std_id;
+	ch->video.stdid = std_id;
 	memset(&ch->video.dv_timings, 0, sizeof(ch->video.dv_timings));
 
 	/* Get the information about the standard */
@@ -1436,7 +1437,7 @@ static int vpif_s_std(struct file *file, void *priv, v4l2_std_id *std_id)
 	vpif_config_format(ch);
 
 	/* set standard in the sub device */
-	ret = v4l2_subdev_call(ch->sd, core, s_std, *std_id);
+	ret = v4l2_subdev_call(ch->sd, core, s_std, std_id);
 	if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV) {
 		vpif_dbg(1, debug, "Failed to set standard for sub devices\n");
 		return ret;
@@ -1923,7 +1924,8 @@ static int vpif_dbg_g_register(struct file *file, void *priv,
  * Returns zero or -EINVAL if write operations fails.
  */
 static int vpif_dbg_s_register(struct file *file, void *priv,
-		struct v4l2_dbg_register *reg){
+		const struct v4l2_dbg_register *reg)
+{
 	struct vpif_fh *fh = priv;
 	struct channel_obj *ch = fh->channel;
 
diff --git a/drivers/media/platform/davinci/vpif_display.c b/drivers/media/platform/davinci/vpif_display.c
index dd249c9..1b3fb5c 100644
--- a/drivers/media/platform/davinci/vpif_display.c
+++ b/drivers/media/platform/davinci/vpif_display.c
@@ -511,7 +511,7 @@ static int vpif_update_std_info(struct channel_obj *ch)
 	int i;
 
 	for (i = 0; i < vpif_ch_params_count; i++) {
-		config = &ch_params[i];
+		config = &vpif_ch_params[i];
 		if (config->hd_sd == 0) {
 			vpif_dbg(2, debug, "SD format\n");
 			if (config->stdid & vid_ch->stdid) {
@@ -1001,6 +1001,7 @@ static int vpif_reqbufs(struct file *file, void *priv,
 	q->ops = &video_qops;
 	q->mem_ops = &vb2_dma_contig_memops;
 	q->buf_struct_size = sizeof(struct vpif_disp_buffer);
+	q->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
 
 	ret = vb2_queue_init(q);
 	if (ret) {
@@ -1058,14 +1059,14 @@ static int vpif_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
 	return vb2_qbuf(&common->buffer_queue, buf);
 }
 
-static int vpif_s_std(struct file *file, void *priv, v4l2_std_id *std_id)
+static int vpif_s_std(struct file *file, void *priv, v4l2_std_id std_id)
 {
 	struct vpif_fh *fh = priv;
 	struct channel_obj *ch = fh->channel;
 	struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
 	int ret = 0;
 
-	if (!(*std_id & VPIF_V4L2_STD))
+	if (!(std_id & VPIF_V4L2_STD))
 		return -EINVAL;
 
 	if (common->started) {
@@ -1074,7 +1075,7 @@ static int vpif_s_std(struct file *file, void *priv, v4l2_std_id *std_id)
 	}
 
 	/* Call encoder subdevice function to set the standard */
-	ch->video.stdid = *std_id;
+	ch->video.stdid = std_id;
 	memset(&ch->video.dv_timings, 0, sizeof(ch->video.dv_timings));
 	/* Get the information about the standard */
 	if (vpif_update_resolution(ch))
@@ -1092,14 +1093,14 @@ static int vpif_s_std(struct file *file, void *priv, v4l2_std_id *std_id)
 	vpif_config_format(ch);
 
 	ret = v4l2_device_call_until_err(&vpif_obj.v4l2_dev, 1, video,
-						s_std_output, *std_id);
+						s_std_output, std_id);
 	if (ret < 0) {
 		vpif_err("Failed to set output standard\n");
 		return ret;
 	}
 
 	ret = v4l2_device_call_until_err(&vpif_obj.v4l2_dev, 1, core,
-							s_std, *std_id);
+							s_std, std_id);
 	if (ret < 0)
 		vpif_err("Failed to set standard for sub devices\n");
 	return ret;
@@ -1567,7 +1568,8 @@ static int vpif_dbg_g_register(struct file *file, void *priv,
  * Returns zero or -EINVAL if write operations fails.
  */
 static int vpif_dbg_s_register(struct file *file, void *priv,
-		struct v4l2_dbg_register *reg){
+		const struct v4l2_dbg_register *reg)
+{
 	struct vpif_fh *fh = priv;
 	struct channel_obj *ch = fh->channel;
 
diff --git a/drivers/media/platform/fsl-viu.c b/drivers/media/platform/fsl-viu.c
index 5f7db3f..3a6a0dc 100644
--- a/drivers/media/platform/fsl-viu.c
+++ b/drivers/media/platform/fsl-viu.c
@@ -957,12 +957,12 @@ static int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *std_id)
 	return 0;
 }
 
-static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *id)
+static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id)
 {
 	struct viu_fh *fh = priv;
 
-	fh->dev->std = *id;
-	decoder_call(fh->dev, core, s_std, *id);
+	fh->dev->std = id;
+	decoder_call(fh->dev, core, s_std, id);
 	return 0;
 }
 
diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c b/drivers/media/platform/marvell-ccic/mcam-core.c
index 92a33f0..64ab91e 100644
--- a/drivers/media/platform/marvell-ccic/mcam-core.c
+++ b/drivers/media/platform/marvell-ccic/mcam-core.c
@@ -1357,7 +1357,7 @@ static int mcam_vidioc_s_input(struct file *filp, void *priv, unsigned int i)
 }
 
 /* from vivi.c */
-static int mcam_vidioc_s_std(struct file *filp, void *priv, v4l2_std_id *a)
+static int mcam_vidioc_s_std(struct file *filp, void *priv, v4l2_std_id a)
 {
 	return 0;
 }
@@ -1445,7 +1445,7 @@ static int mcam_vidioc_g_register(struct file *file, void *priv,
 }
 
 static int mcam_vidioc_s_register(struct file *file, void *priv,
-		struct v4l2_dbg_register *reg)
+		const struct v4l2_dbg_register *reg)
 {
 	struct mcam_camera *cam = priv;
 
diff --git a/drivers/media/platform/omap/omap_vout.c b/drivers/media/platform/omap/omap_vout.c
index 96c4a17..477268a 100644
--- a/drivers/media/platform/omap/omap_vout.c
+++ b/drivers/media/platform/omap/omap_vout.c
@@ -648,9 +648,12 @@ static void omap_vout_isr(void *arg, unsigned int irqstatus)
 
 	/* First save the configuration in ovelray structure */
 	ret = omapvid_init(vout, addr);
-	if (ret)
+	if (ret) {
 		printk(KERN_ERR VOUT_NAME
 			"failed to set overlay info\n");
+		goto vout_isr_err;
+	}
+
 	/* Enable the pipeline and set the Go bit */
 	ret = omapvid_apply_changes(vout);
 	if (ret)
@@ -1660,13 +1663,16 @@ static int vidioc_streamon(struct file *file, void *fh, enum v4l2_buf_type i)
 	mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD
 		| DISPC_IRQ_VSYNC2;
 
-	omap_dispc_register_isr(omap_vout_isr, vout, mask);
-
 	/* First save the configuration in ovelray structure */
 	ret = omapvid_init(vout, addr);
-	if (ret)
+	if (ret) {
 		v4l2_err(&vout->vid_dev->v4l2_dev,
 				"failed to set overlay info\n");
+		goto streamon_err1;
+	}
+
+	omap_dispc_register_isr(omap_vout_isr, vout, mask);
+
 	/* Enable the pipeline and set the Go bit */
 	ret = omapvid_apply_changes(vout);
 	if (ret)
diff --git a/drivers/media/platform/s3c-camif/camif-capture.c b/drivers/media/platform/s3c-camif/camif-capture.c
index a55793c..70438a0 100644
--- a/drivers/media/platform/s3c-camif/camif-capture.c
+++ b/drivers/media/platform/s3c-camif/camif-capture.c
@@ -934,12 +934,19 @@ static int s3c_camif_reqbufs(struct file *file, void *priv,
 		vp->owner = NULL;
 
 	ret = vb2_reqbufs(&vp->vb_queue, rb);
-	if (!ret) {
-		vp->reqbufs_count = rb->count;
-		if (vp->owner == NULL && rb->count > 0)
-			vp->owner = priv;
+	if (ret < 0)
+		return ret;
+
+	if (rb->count && rb->count < CAMIF_REQ_BUFS_MIN) {
+		rb->count = 0;
+		vb2_reqbufs(&vp->vb_queue, rb);
+		ret = -ENOMEM;
 	}
 
+	vp->reqbufs_count = rb->count;
+	if (vp->owner == NULL && rb->count > 0)
+		vp->owner = priv;
+
 	return ret;
 }
 
@@ -1153,6 +1160,7 @@ int s3c_camif_register_video_node(struct camif_dev *camif, int idx)
 	q->mem_ops = &vb2_dma_contig_memops;
 	q->buf_struct_size = sizeof(struct camif_buffer);
 	q->drv_priv = vp;
+	q->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
 
 	ret = vb2_queue_init(q);
 	if (ret)
diff --git a/drivers/media/platform/s5p-fimc/fimc-capture.c b/drivers/media/platform/s5p-fimc/fimc-capture.c
index f553cc2..87b6842 100644
--- a/drivers/media/platform/s5p-fimc/fimc-capture.c
+++ b/drivers/media/platform/s5p-fimc/fimc-capture.c
@@ -1797,6 +1797,7 @@ static int fimc_register_capture_device(struct fimc_dev *fimc,
 	q->ops = &fimc_capture_qops;
 	q->mem_ops = &vb2_dma_contig_memops;
 	q->buf_struct_size = sizeof(struct fimc_vid_buffer);
+	q->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
 
 	ret = vb2_queue_init(q);
 	if (ret)
diff --git a/drivers/media/platform/s5p-fimc/fimc-lite.c b/drivers/media/platform/s5p-fimc/fimc-lite.c
index bbc35de..8ebefdb 100644
--- a/drivers/media/platform/s5p-fimc/fimc-lite.c
+++ b/drivers/media/platform/s5p-fimc/fimc-lite.c
@@ -1325,6 +1325,7 @@ static int fimc_lite_subdev_registered(struct v4l2_subdev *sd)
 	q->mem_ops = &vb2_dma_contig_memops;
 	q->buf_struct_size = sizeof(struct flite_buffer);
 	q->drv_priv = fimc;
+	q->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
 
 	ret = vb2_queue_init(q);
 	if (ret < 0)
diff --git a/drivers/media/platform/s5p-g2d/g2d.c b/drivers/media/platform/s5p-g2d/g2d.c
index aaaf276..14d663d 100644
--- a/drivers/media/platform/s5p-g2d/g2d.c
+++ b/drivers/media/platform/s5p-g2d/g2d.c
@@ -18,6 +18,7 @@
 #include <linux/slab.h>
 #include <linux/clk.h>
 #include <linux/interrupt.h>
+#include <linux/of.h>
 
 #include <linux/platform_device.h>
 #include <media/v4l2-mem2mem.h>
@@ -695,11 +696,14 @@ static struct v4l2_m2m_ops g2d_m2m_ops = {
 	.unlock		= g2d_unlock,
 };
 
+static const struct of_device_id exynos_g2d_match[];
+
 static int g2d_probe(struct platform_device *pdev)
 {
 	struct g2d_dev *dev;
 	struct video_device *vfd;
 	struct resource *res;
+	const struct of_device_id *of_id;
 	int ret = 0;
 
 	dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
@@ -794,7 +798,17 @@ static int g2d_probe(struct platform_device *pdev)
 	}
 
 	def_frame.stride = (def_frame.width * def_frame.fmt->depth) >> 3;
-	dev->variant = g2d_get_drv_data(pdev);
+
+	if (!pdev->dev.of_node) {
+		dev->variant = g2d_get_drv_data(pdev);
+	} else {
+		of_id = of_match_node(exynos_g2d_match, pdev->dev.of_node);
+		if (!of_id) {
+			ret = -ENODEV;
+			goto unreg_video_dev;
+		}
+		dev->variant = (struct g2d_variant *)of_id->data;
+	}
 
 	return 0;
 
@@ -835,13 +849,25 @@ static int g2d_remove(struct platform_device *pdev)
 }
 
 static struct g2d_variant g2d_drvdata_v3x = {
-	.hw_rev = TYPE_G2D_3X,
+	.hw_rev = TYPE_G2D_3X, /* Revision 3.0 for S5PV210 and Exynos4210 */
 };
 
 static struct g2d_variant g2d_drvdata_v4x = {
 	.hw_rev = TYPE_G2D_4X, /* Revision 4.1 for Exynos4X12 and Exynos5 */
 };
 
+static const struct of_device_id exynos_g2d_match[] = {
+	{
+		.compatible = "samsung,s5pv210-g2d",
+		.data = &g2d_drvdata_v3x,
+	}, {
+		.compatible = "samsung,exynos4212-g2d",
+		.data = &g2d_drvdata_v4x,
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, exynos_g2d_match);
+
 static struct platform_device_id g2d_driver_ids[] = {
 	{
 		.name = "s5p-g2d",
@@ -861,6 +887,7 @@ static struct platform_driver g2d_pdrv = {
 	.driver		= {
 		.name = G2D_NAME,
 		.owner = THIS_MODULE,
+		.of_match_table = exynos_g2d_match,
 	},
 };
 
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c
index 1cb6d57..7379dc6 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
@@ -804,6 +804,7 @@ static int s5p_mfc_open(struct file *file)
 		goto err_queue_init;
 	}
 	q->mem_ops = (struct vb2_mem_ops *)&vb2_dma_contig_memops;
+	q->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_COPY;
 	ret = vb2_queue_init(q);
 	if (ret) {
 		mfc_err("Failed to initialize videobuf2 queue(capture)\n");
@@ -825,6 +826,7 @@ static int s5p_mfc_open(struct file *file)
 		goto err_queue_init;
 	}
 	q->mem_ops = (struct vb2_mem_ops *)&vb2_dma_contig_memops;
+	q->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_COPY;
 	ret = vb2_queue_init(q);
 	if (ret) {
 		mfc_err("Failed to initialize videobuf2 queue(output)\n");
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c
index 13877808..ad4f1df 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c
@@ -16,7 +16,7 @@
 #include "s5p_mfc_debug.h"
 
 /* This function is used to send a command to the MFC */
-int s5p_mfc_cmd_host2risc_v5(struct s5p_mfc_dev *dev, int cmd,
+static int s5p_mfc_cmd_host2risc_v5(struct s5p_mfc_dev *dev, int cmd,
 				struct s5p_mfc_cmd_args *args)
 {
 	int cur_cmd;
@@ -41,7 +41,7 @@ int s5p_mfc_cmd_host2risc_v5(struct s5p_mfc_dev *dev, int cmd,
 }
 
 /* Initialize the MFC */
-int s5p_mfc_sys_init_cmd_v5(struct s5p_mfc_dev *dev)
+static int s5p_mfc_sys_init_cmd_v5(struct s5p_mfc_dev *dev)
 {
 	struct s5p_mfc_cmd_args h2r_args;
 
@@ -52,7 +52,7 @@ int s5p_mfc_sys_init_cmd_v5(struct s5p_mfc_dev *dev)
 }
 
 /* Suspend the MFC hardware */
-int s5p_mfc_sleep_cmd_v5(struct s5p_mfc_dev *dev)
+static int s5p_mfc_sleep_cmd_v5(struct s5p_mfc_dev *dev)
 {
 	struct s5p_mfc_cmd_args h2r_args;
 
@@ -61,7 +61,7 @@ int s5p_mfc_sleep_cmd_v5(struct s5p_mfc_dev *dev)
 }
 
 /* Wake up the MFC hardware */
-int s5p_mfc_wakeup_cmd_v5(struct s5p_mfc_dev *dev)
+static int s5p_mfc_wakeup_cmd_v5(struct s5p_mfc_dev *dev)
 {
 	struct s5p_mfc_cmd_args h2r_args;
 
@@ -71,7 +71,7 @@ int s5p_mfc_wakeup_cmd_v5(struct s5p_mfc_dev *dev)
 }
 
 
-int s5p_mfc_open_inst_cmd_v5(struct s5p_mfc_ctx *ctx)
+static int s5p_mfc_open_inst_cmd_v5(struct s5p_mfc_ctx *ctx)
 {
 	struct s5p_mfc_dev *dev = ctx->dev;
 	struct s5p_mfc_cmd_args h2r_args;
@@ -124,7 +124,7 @@ int s5p_mfc_open_inst_cmd_v5(struct s5p_mfc_ctx *ctx)
 	return ret;
 }
 
-int s5p_mfc_close_inst_cmd_v5(struct s5p_mfc_ctx *ctx)
+static int s5p_mfc_close_inst_cmd_v5(struct s5p_mfc_ctx *ctx)
 {
 	struct s5p_mfc_dev *dev = ctx->dev;
 	struct s5p_mfc_cmd_args h2r_args;
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c
index 754bfbc..5708fc3 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c
@@ -17,7 +17,7 @@
 #include "s5p_mfc_intr.h"
 #include "s5p_mfc_opr.h"
 
-int s5p_mfc_cmd_host2risc_v6(struct s5p_mfc_dev *dev, int cmd,
+static int s5p_mfc_cmd_host2risc_v6(struct s5p_mfc_dev *dev, int cmd,
 				struct s5p_mfc_cmd_args *args)
 {
 	mfc_debug(2, "Issue the command: %d\n", cmd);
@@ -32,7 +32,7 @@ int s5p_mfc_cmd_host2risc_v6(struct s5p_mfc_dev *dev, int cmd,
 	return 0;
 }
 
-int s5p_mfc_sys_init_cmd_v6(struct s5p_mfc_dev *dev)
+static int s5p_mfc_sys_init_cmd_v6(struct s5p_mfc_dev *dev)
 {
 	struct s5p_mfc_cmd_args h2r_args;
 	struct s5p_mfc_buf_size_v6 *buf_size = dev->variant->buf_size->priv;
@@ -44,7 +44,7 @@ int s5p_mfc_sys_init_cmd_v6(struct s5p_mfc_dev *dev)
 					&h2r_args);
 }
 
-int s5p_mfc_sleep_cmd_v6(struct s5p_mfc_dev *dev)
+static int s5p_mfc_sleep_cmd_v6(struct s5p_mfc_dev *dev)
 {
 	struct s5p_mfc_cmd_args h2r_args;
 
@@ -53,7 +53,7 @@ int s5p_mfc_sleep_cmd_v6(struct s5p_mfc_dev *dev)
 			&h2r_args);
 }
 
-int s5p_mfc_wakeup_cmd_v6(struct s5p_mfc_dev *dev)
+static int s5p_mfc_wakeup_cmd_v6(struct s5p_mfc_dev *dev)
 {
 	struct s5p_mfc_cmd_args h2r_args;
 
@@ -63,7 +63,7 @@ int s5p_mfc_wakeup_cmd_v6(struct s5p_mfc_dev *dev)
 }
 
 /* Open a new instance and get its number */
-int s5p_mfc_open_inst_cmd_v6(struct s5p_mfc_ctx *ctx)
+static int s5p_mfc_open_inst_cmd_v6(struct s5p_mfc_ctx *ctx)
 {
 	struct s5p_mfc_dev *dev = ctx->dev;
 	struct s5p_mfc_cmd_args h2r_args;
@@ -121,7 +121,7 @@ int s5p_mfc_open_inst_cmd_v6(struct s5p_mfc_ctx *ctx)
 }
 
 /* Close instance */
-int s5p_mfc_close_inst_cmd_v6(struct s5p_mfc_ctx *ctx)
+static int s5p_mfc_close_inst_cmd_v6(struct s5p_mfc_ctx *ctx)
 {
 	struct s5p_mfc_dev *dev = ctx->dev;
 	struct s5p_mfc_cmd_args h2r_args;
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c
index f61dba8..c7ad329 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c
@@ -34,7 +34,7 @@
 #define OFFSETB(x)		(((x) - dev->bank2) >> MFC_OFFSET_SHIFT)
 
 /* Allocate temporary buffers for decoding */
-int s5p_mfc_alloc_dec_temp_buffers_v5(struct s5p_mfc_ctx *ctx)
+static int s5p_mfc_alloc_dec_temp_buffers_v5(struct s5p_mfc_ctx *ctx)
 {
 	struct s5p_mfc_dev *dev = ctx->dev;
 	struct s5p_mfc_buf_size_v5 *buf_size = dev->variant->buf_size->priv;
@@ -55,13 +55,13 @@ int s5p_mfc_alloc_dec_temp_buffers_v5(struct s5p_mfc_ctx *ctx)
 
 
 /* Release temporary buffers for decoding */
-void s5p_mfc_release_dec_desc_buffer_v5(struct s5p_mfc_ctx *ctx)
+static void s5p_mfc_release_dec_desc_buffer_v5(struct s5p_mfc_ctx *ctx)
 {
 	s5p_mfc_release_priv_buf(ctx->dev->mem_dev_l, &ctx->dsc);
 }
 
 /* Allocate codec buffers */
-int s5p_mfc_alloc_codec_buffers_v5(struct s5p_mfc_ctx *ctx)
+static int s5p_mfc_alloc_codec_buffers_v5(struct s5p_mfc_ctx *ctx)
 {
 	struct s5p_mfc_dev *dev = ctx->dev;
 	unsigned int enc_ref_y_size = 0;
@@ -193,14 +193,14 @@ int s5p_mfc_alloc_codec_buffers_v5(struct s5p_mfc_ctx *ctx)
 }
 
 /* Release buffers allocated for codec */
-void s5p_mfc_release_codec_buffers_v5(struct s5p_mfc_ctx *ctx)
+static void s5p_mfc_release_codec_buffers_v5(struct s5p_mfc_ctx *ctx)
 {
 	s5p_mfc_release_priv_buf(ctx->dev->mem_dev_l, &ctx->bank1);
 	s5p_mfc_release_priv_buf(ctx->dev->mem_dev_r, &ctx->bank2);
 }
 
 /* Allocate memory for instance data buffer */
-int s5p_mfc_alloc_instance_buffer_v5(struct s5p_mfc_ctx *ctx)
+static int s5p_mfc_alloc_instance_buffer_v5(struct s5p_mfc_ctx *ctx)
 {
 	struct s5p_mfc_dev *dev = ctx->dev;
 	struct s5p_mfc_buf_size_v5 *buf_size = dev->variant->buf_size->priv;
@@ -241,20 +241,20 @@ int s5p_mfc_alloc_instance_buffer_v5(struct s5p_mfc_ctx *ctx)
 }
 
 /* Release instance buffer */
-void s5p_mfc_release_instance_buffer_v5(struct s5p_mfc_ctx *ctx)
+static void s5p_mfc_release_instance_buffer_v5(struct s5p_mfc_ctx *ctx)
 {
 	s5p_mfc_release_priv_buf(ctx->dev->mem_dev_l, &ctx->ctx);
 	s5p_mfc_release_priv_buf(ctx->dev->mem_dev_l, &ctx->shm);
 }
 
-int s5p_mfc_alloc_dev_context_buffer_v5(struct s5p_mfc_dev *dev)
+static int s5p_mfc_alloc_dev_context_buffer_v5(struct s5p_mfc_dev *dev)
 {
 	/* NOP */
 
 	return 0;
 }
 
-void s5p_mfc_release_dev_context_buffer_v5(struct s5p_mfc_dev *dev)
+static void s5p_mfc_release_dev_context_buffer_v5(struct s5p_mfc_dev *dev)
 {
 	/* NOP */
 }
@@ -273,7 +273,7 @@ static unsigned int s5p_mfc_read_info_v5(struct s5p_mfc_ctx *ctx,
 	return readl(ctx->shm.virt + ofs);
 }
 
-void s5p_mfc_dec_calc_dpb_size_v5(struct s5p_mfc_ctx *ctx)
+static void s5p_mfc_dec_calc_dpb_size_v5(struct s5p_mfc_ctx *ctx)
 {
 	unsigned int guard_width, guard_height;
 
@@ -315,7 +315,7 @@ void s5p_mfc_dec_calc_dpb_size_v5(struct s5p_mfc_ctx *ctx)
 	}
 }
 
-void s5p_mfc_enc_calc_src_size_v5(struct s5p_mfc_ctx *ctx)
+static void s5p_mfc_enc_calc_src_size_v5(struct s5p_mfc_ctx *ctx)
 {
 	if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M) {
 		ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12M_HALIGN);
@@ -361,8 +361,9 @@ static void s5p_mfc_set_shared_buffer(struct s5p_mfc_ctx *ctx)
 }
 
 /* Set registers for decoding stream buffer */
-int s5p_mfc_set_dec_stream_buffer_v5(struct s5p_mfc_ctx *ctx, int buf_addr,
-		  unsigned int start_num_byte, unsigned int buf_size)
+static int s5p_mfc_set_dec_stream_buffer_v5(struct s5p_mfc_ctx *ctx,
+		int buf_addr, unsigned int start_num_byte,
+		unsigned int buf_size)
 {
 	struct s5p_mfc_dev *dev = ctx->dev;
 
@@ -374,7 +375,7 @@ int s5p_mfc_set_dec_stream_buffer_v5(struct s5p_mfc_ctx *ctx, int buf_addr,
 }
 
 /* Set decoding frame buffer */
-int s5p_mfc_set_dec_frame_buffer_v5(struct s5p_mfc_ctx *ctx)
+static int s5p_mfc_set_dec_frame_buffer_v5(struct s5p_mfc_ctx *ctx)
 {
 	unsigned int frame_size, i;
 	unsigned int frame_size_ch, frame_size_mv;
@@ -506,7 +507,7 @@ int s5p_mfc_set_dec_frame_buffer_v5(struct s5p_mfc_ctx *ctx)
 }
 
 /* Set registers for encoding stream buffer */
-int s5p_mfc_set_enc_stream_buffer_v5(struct s5p_mfc_ctx *ctx,
+static int s5p_mfc_set_enc_stream_buffer_v5(struct s5p_mfc_ctx *ctx,
 		unsigned long addr, unsigned int size)
 {
 	struct s5p_mfc_dev *dev = ctx->dev;
@@ -516,7 +517,7 @@ int s5p_mfc_set_enc_stream_buffer_v5(struct s5p_mfc_ctx *ctx,
 	return 0;
 }
 
-void s5p_mfc_set_enc_frame_buffer_v5(struct s5p_mfc_ctx *ctx,
+static void s5p_mfc_set_enc_frame_buffer_v5(struct s5p_mfc_ctx *ctx,
 		unsigned long y_addr, unsigned long c_addr)
 {
 	struct s5p_mfc_dev *dev = ctx->dev;
@@ -525,7 +526,7 @@ void s5p_mfc_set_enc_frame_buffer_v5(struct s5p_mfc_ctx *ctx,
 	mfc_write(dev, OFFSETB(c_addr), S5P_FIMV_ENC_SI_CH0_CUR_C_ADR);
 }
 
-void s5p_mfc_get_enc_frame_buffer_v5(struct s5p_mfc_ctx *ctx,
+static void s5p_mfc_get_enc_frame_buffer_v5(struct s5p_mfc_ctx *ctx,
 		unsigned long *y_addr, unsigned long *c_addr)
 {
 	struct s5p_mfc_dev *dev = ctx->dev;
@@ -537,7 +538,7 @@ void s5p_mfc_get_enc_frame_buffer_v5(struct s5p_mfc_ctx *ctx,
 }
 
 /* Set encoding ref & codec buffer */
-int s5p_mfc_set_enc_ref_buffer_v5(struct s5p_mfc_ctx *ctx)
+static int s5p_mfc_set_enc_ref_buffer_v5(struct s5p_mfc_ctx *ctx)
 {
 	struct s5p_mfc_dev *dev = ctx->dev;
 	size_t buf_addr1, buf_addr2;
@@ -1041,7 +1042,7 @@ static int s5p_mfc_set_enc_params_h263(struct s5p_mfc_ctx *ctx)
 }
 
 /* Initialize decoding */
-int s5p_mfc_init_decode_v5(struct s5p_mfc_ctx *ctx)
+static int s5p_mfc_init_decode_v5(struct s5p_mfc_ctx *ctx)
 {
 	struct s5p_mfc_dev *dev = ctx->dev;
 
@@ -1077,7 +1078,7 @@ static void s5p_mfc_set_flush(struct s5p_mfc_ctx *ctx, int flush)
 }
 
 /* Decode a single frame */
-int s5p_mfc_decode_one_frame_v5(struct s5p_mfc_ctx *ctx,
+static int s5p_mfc_decode_one_frame_v5(struct s5p_mfc_ctx *ctx,
 					enum s5p_mfc_decode_arg last_frame)
 {
 	struct s5p_mfc_dev *dev = ctx->dev;
@@ -1106,7 +1107,7 @@ int s5p_mfc_decode_one_frame_v5(struct s5p_mfc_ctx *ctx,
 	return 0;
 }
 
-int s5p_mfc_init_encode_v5(struct s5p_mfc_ctx *ctx)
+static int s5p_mfc_init_encode_v5(struct s5p_mfc_ctx *ctx)
 {
 	struct s5p_mfc_dev *dev = ctx->dev;
 
@@ -1128,7 +1129,7 @@ int s5p_mfc_init_encode_v5(struct s5p_mfc_ctx *ctx)
 }
 
 /* Encode a single frame */
-int s5p_mfc_encode_one_frame_v5(struct s5p_mfc_ctx *ctx)
+static int s5p_mfc_encode_one_frame_v5(struct s5p_mfc_ctx *ctx)
 {
 	struct s5p_mfc_dev *dev = ctx->dev;
 	int cmd;
@@ -1353,7 +1354,7 @@ static int s5p_mfc_run_init_dec_buffers(struct s5p_mfc_ctx *ctx)
 }
 
 /* Try running an operation on hardware */
-void s5p_mfc_try_run_v5(struct s5p_mfc_dev *dev)
+static void s5p_mfc_try_run_v5(struct s5p_mfc_dev *dev)
 {
 	struct s5p_mfc_ctx *ctx;
 	int new_ctx;
@@ -1469,7 +1470,7 @@ void s5p_mfc_try_run_v5(struct s5p_mfc_dev *dev)
 }
 
 
-void s5p_mfc_cleanup_queue_v5(struct list_head *lh, struct vb2_queue *vq)
+static void s5p_mfc_cleanup_queue_v5(struct list_head *lh, struct vb2_queue *vq)
 {
 	struct s5p_mfc_buf *b;
 	int i;
@@ -1483,52 +1484,52 @@ void s5p_mfc_cleanup_queue_v5(struct list_head *lh, struct vb2_queue *vq)
 	}
 }
 
-void s5p_mfc_clear_int_flags_v5(struct s5p_mfc_dev *dev)
+static void s5p_mfc_clear_int_flags_v5(struct s5p_mfc_dev *dev)
 {
 	mfc_write(dev, 0, S5P_FIMV_RISC_HOST_INT);
 	mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD);
 	mfc_write(dev, 0xffff, S5P_FIMV_SI_RTN_CHID);
 }
 
-int s5p_mfc_get_dspl_y_adr_v5(struct s5p_mfc_dev *dev)
+static int s5p_mfc_get_dspl_y_adr_v5(struct s5p_mfc_dev *dev)
 {
 	return mfc_read(dev, S5P_FIMV_SI_DISPLAY_Y_ADR) << MFC_OFFSET_SHIFT;
 }
 
-int s5p_mfc_get_dec_y_adr_v5(struct s5p_mfc_dev *dev)
+static int s5p_mfc_get_dec_y_adr_v5(struct s5p_mfc_dev *dev)
 {
 	return mfc_read(dev, S5P_FIMV_SI_DECODE_Y_ADR) << MFC_OFFSET_SHIFT;
 }
 
-int s5p_mfc_get_dspl_status_v5(struct s5p_mfc_dev *dev)
+static int s5p_mfc_get_dspl_status_v5(struct s5p_mfc_dev *dev)
 {
 	return mfc_read(dev, S5P_FIMV_SI_DISPLAY_STATUS);
 }
 
-int s5p_mfc_get_dec_status_v5(struct s5p_mfc_dev *dev)
+static int s5p_mfc_get_dec_status_v5(struct s5p_mfc_dev *dev)
 {
 	return mfc_read(dev, S5P_FIMV_SI_DECODE_STATUS);
 }
 
-int s5p_mfc_get_dec_frame_type_v5(struct s5p_mfc_dev *dev)
+static int s5p_mfc_get_dec_frame_type_v5(struct s5p_mfc_dev *dev)
 {
 	return mfc_read(dev, S5P_FIMV_DECODE_FRAME_TYPE) &
 		S5P_FIMV_DECODE_FRAME_MASK;
 }
 
-int s5p_mfc_get_disp_frame_type_v5(struct s5p_mfc_ctx *ctx)
+static int s5p_mfc_get_disp_frame_type_v5(struct s5p_mfc_ctx *ctx)
 {
 	return (s5p_mfc_read_info_v5(ctx, DISP_PIC_FRAME_TYPE) >>
 			S5P_FIMV_SHARED_DISP_FRAME_TYPE_SHIFT) &
 			S5P_FIMV_DECODE_FRAME_MASK;
 }
 
-int s5p_mfc_get_consumed_stream_v5(struct s5p_mfc_dev *dev)
+static int s5p_mfc_get_consumed_stream_v5(struct s5p_mfc_dev *dev)
 {
 	return mfc_read(dev, S5P_FIMV_SI_CONSUMED_BYTES);
 }
 
-int s5p_mfc_get_int_reason_v5(struct s5p_mfc_dev *dev)
+static int s5p_mfc_get_int_reason_v5(struct s5p_mfc_dev *dev)
 {
 	int reason;
 	reason = mfc_read(dev, S5P_FIMV_RISC2HOST_CMD) &
@@ -1576,98 +1577,98 @@ int s5p_mfc_get_int_reason_v5(struct s5p_mfc_dev *dev)
 	return reason;
 }
 
-int s5p_mfc_get_int_err_v5(struct s5p_mfc_dev *dev)
+static int s5p_mfc_get_int_err_v5(struct s5p_mfc_dev *dev)
 {
 	return mfc_read(dev, S5P_FIMV_RISC2HOST_ARG2);
 }
 
-int s5p_mfc_err_dec_v5(unsigned int err)
+static int s5p_mfc_err_dec_v5(unsigned int err)
 {
 	return (err & S5P_FIMV_ERR_DEC_MASK) >> S5P_FIMV_ERR_DEC_SHIFT;
 }
 
-int s5p_mfc_err_dspl_v5(unsigned int err)
+static int s5p_mfc_err_dspl_v5(unsigned int err)
 {
 	return (err & S5P_FIMV_ERR_DSPL_MASK) >> S5P_FIMV_ERR_DSPL_SHIFT;
 }
 
-int s5p_mfc_get_img_width_v5(struct s5p_mfc_dev *dev)
+static int s5p_mfc_get_img_width_v5(struct s5p_mfc_dev *dev)
 {
 	return mfc_read(dev, S5P_FIMV_SI_HRESOL);
 }
 
-int s5p_mfc_get_img_height_v5(struct s5p_mfc_dev *dev)
+static int s5p_mfc_get_img_height_v5(struct s5p_mfc_dev *dev)
 {
 	return mfc_read(dev, S5P_FIMV_SI_VRESOL);
 }
 
-int s5p_mfc_get_dpb_count_v5(struct s5p_mfc_dev *dev)
+static int s5p_mfc_get_dpb_count_v5(struct s5p_mfc_dev *dev)
 {
 	return mfc_read(dev, S5P_FIMV_SI_BUF_NUMBER);
 }
 
-int s5p_mfc_get_mv_count_v5(struct s5p_mfc_dev *dev)
+static int s5p_mfc_get_mv_count_v5(struct s5p_mfc_dev *dev)
 {
 	/* NOP */
 	return -1;
 }
 
-int s5p_mfc_get_inst_no_v5(struct s5p_mfc_dev *dev)
+static int s5p_mfc_get_inst_no_v5(struct s5p_mfc_dev *dev)
 {
 	return mfc_read(dev, S5P_FIMV_RISC2HOST_ARG1);
 }
 
-int s5p_mfc_get_enc_strm_size_v5(struct s5p_mfc_dev *dev)
+static int s5p_mfc_get_enc_strm_size_v5(struct s5p_mfc_dev *dev)
 {
 	return mfc_read(dev, S5P_FIMV_ENC_SI_STRM_SIZE);
 }
 
-int s5p_mfc_get_enc_slice_type_v5(struct s5p_mfc_dev *dev)
+static int s5p_mfc_get_enc_slice_type_v5(struct s5p_mfc_dev *dev)
 {
 	return mfc_read(dev, S5P_FIMV_ENC_SI_SLICE_TYPE);
 }
 
-int s5p_mfc_get_enc_dpb_count_v5(struct s5p_mfc_dev *dev)
+static int s5p_mfc_get_enc_dpb_count_v5(struct s5p_mfc_dev *dev)
 {
 	return -1;
 }
 
-int s5p_mfc_get_enc_pic_count_v5(struct s5p_mfc_dev *dev)
+static int s5p_mfc_get_enc_pic_count_v5(struct s5p_mfc_dev *dev)
 {
 	return mfc_read(dev, S5P_FIMV_ENC_SI_PIC_CNT);
 }
 
-int s5p_mfc_get_sei_avail_status_v5(struct s5p_mfc_ctx *ctx)
+static int s5p_mfc_get_sei_avail_status_v5(struct s5p_mfc_ctx *ctx)
 {
 	return s5p_mfc_read_info_v5(ctx, FRAME_PACK_SEI_AVAIL);
 }
 
-int s5p_mfc_get_mvc_num_views_v5(struct s5p_mfc_dev *dev)
+static int s5p_mfc_get_mvc_num_views_v5(struct s5p_mfc_dev *dev)
 {
 	return -1;
 }
 
-int s5p_mfc_get_mvc_view_id_v5(struct s5p_mfc_dev *dev)
+static int s5p_mfc_get_mvc_view_id_v5(struct s5p_mfc_dev *dev)
 {
 	return -1;
 }
 
-unsigned int s5p_mfc_get_pic_type_top_v5(struct s5p_mfc_ctx *ctx)
+static unsigned int s5p_mfc_get_pic_type_top_v5(struct s5p_mfc_ctx *ctx)
 {
 	return s5p_mfc_read_info_v5(ctx, PIC_TIME_TOP);
 }
 
-unsigned int s5p_mfc_get_pic_type_bot_v5(struct s5p_mfc_ctx *ctx)
+static unsigned int s5p_mfc_get_pic_type_bot_v5(struct s5p_mfc_ctx *ctx)
 {
 	return s5p_mfc_read_info_v5(ctx, PIC_TIME_BOT);
 }
 
-unsigned int s5p_mfc_get_crop_info_h_v5(struct s5p_mfc_ctx *ctx)
+static unsigned int s5p_mfc_get_crop_info_h_v5(struct s5p_mfc_ctx *ctx)
 {
 	return s5p_mfc_read_info_v5(ctx, CROP_INFO_H);
 }
 
-unsigned int s5p_mfc_get_crop_info_v_v5(struct s5p_mfc_ctx *ctx)
+static unsigned int s5p_mfc_get_crop_info_v_v5(struct s5p_mfc_ctx *ctx)
 {
 	return s5p_mfc_read_info_v5(ctx, CROP_INFO_V);
 }
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
index beb6dba..0513e4f 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
@@ -49,7 +49,7 @@
 #define OFFSETB(x)		(((x) - dev->port_b) >> S5P_FIMV_MEM_OFFSET)
 
 /* Allocate temporary buffers for decoding */
-int s5p_mfc_alloc_dec_temp_buffers_v6(struct s5p_mfc_ctx *ctx)
+static int s5p_mfc_alloc_dec_temp_buffers_v6(struct s5p_mfc_ctx *ctx)
 {
 	/* NOP */
 
@@ -57,19 +57,19 @@ int s5p_mfc_alloc_dec_temp_buffers_v6(struct s5p_mfc_ctx *ctx)
 }
 
 /* Release temproary buffers for decoding */
-void s5p_mfc_release_dec_desc_buffer_v6(struct s5p_mfc_ctx *ctx)
+static void s5p_mfc_release_dec_desc_buffer_v6(struct s5p_mfc_ctx *ctx)
 {
 	/* NOP */
 }
 
-int s5p_mfc_get_dec_status_v6(struct s5p_mfc_dev *dev)
+static int s5p_mfc_get_dec_status_v6(struct s5p_mfc_dev *dev)
 {
 	/* NOP */
 	return -1;
 }
 
 /* Allocate codec buffers */
-int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx)
+static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx)
 {
 	struct s5p_mfc_dev *dev = ctx->dev;
 	unsigned int mb_width, mb_height;
@@ -203,13 +203,13 @@ int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx)
 }
 
 /* Release buffers allocated for codec */
-void s5p_mfc_release_codec_buffers_v6(struct s5p_mfc_ctx *ctx)
+static void s5p_mfc_release_codec_buffers_v6(struct s5p_mfc_ctx *ctx)
 {
 	s5p_mfc_release_priv_buf(ctx->dev->mem_dev_l, &ctx->bank1);
 }
 
 /* Allocate memory for instance data buffer */
-int s5p_mfc_alloc_instance_buffer_v6(struct s5p_mfc_ctx *ctx)
+static int s5p_mfc_alloc_instance_buffer_v6(struct s5p_mfc_ctx *ctx)
 {
 	struct s5p_mfc_dev *dev = ctx->dev;
 	struct s5p_mfc_buf_size_v6 *buf_size = dev->variant->buf_size->priv;
@@ -258,13 +258,13 @@ int s5p_mfc_alloc_instance_buffer_v6(struct s5p_mfc_ctx *ctx)
 }
 
 /* Release instance buffer */
-void s5p_mfc_release_instance_buffer_v6(struct s5p_mfc_ctx *ctx)
+static void s5p_mfc_release_instance_buffer_v6(struct s5p_mfc_ctx *ctx)
 {
 	s5p_mfc_release_priv_buf(ctx->dev->mem_dev_l, &ctx->ctx);
 }
 
 /* Allocate context buffers for SYS_INIT */
-int s5p_mfc_alloc_dev_context_buffer_v6(struct s5p_mfc_dev *dev)
+static int s5p_mfc_alloc_dev_context_buffer_v6(struct s5p_mfc_dev *dev)
 {
 	struct s5p_mfc_buf_size_v6 *buf_size = dev->variant->buf_size->priv;
 	int ret;
@@ -287,7 +287,7 @@ int s5p_mfc_alloc_dev_context_buffer_v6(struct s5p_mfc_dev *dev)
 }
 
 /* Release context buffers for SYS_INIT */
-void s5p_mfc_release_dev_context_buffer_v6(struct s5p_mfc_dev *dev)
+static void s5p_mfc_release_dev_context_buffer_v6(struct s5p_mfc_dev *dev)
 {
 	s5p_mfc_release_priv_buf(dev->mem_dev_l, &dev->ctx_buf);
 }
@@ -306,7 +306,7 @@ static int calc_plane(int width, int height)
 		(mbY * S5P_FIMV_NUM_PIXELS_IN_MB_ROW_V6);
 }
 
-void s5p_mfc_dec_calc_dpb_size_v6(struct s5p_mfc_ctx *ctx)
+static void s5p_mfc_dec_calc_dpb_size_v6(struct s5p_mfc_ctx *ctx)
 {
 	ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN_V6);
 	ctx->buf_height = ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN_V6);
@@ -326,7 +326,7 @@ void s5p_mfc_dec_calc_dpb_size_v6(struct s5p_mfc_ctx *ctx)
 	}
 }
 
-void s5p_mfc_enc_calc_src_size_v6(struct s5p_mfc_ctx *ctx)
+static void s5p_mfc_enc_calc_src_size_v6(struct s5p_mfc_ctx *ctx)
 {
 	unsigned int mb_width, mb_height;
 
@@ -339,8 +339,9 @@ void s5p_mfc_enc_calc_src_size_v6(struct s5p_mfc_ctx *ctx)
 }
 
 /* Set registers for decoding stream buffer */
-int s5p_mfc_set_dec_stream_buffer_v6(struct s5p_mfc_ctx *ctx, int buf_addr,
-		  unsigned int start_num_byte, unsigned int strm_size)
+static int s5p_mfc_set_dec_stream_buffer_v6(struct s5p_mfc_ctx *ctx,
+			int buf_addr, unsigned int start_num_byte,
+			unsigned int strm_size)
 {
 	struct s5p_mfc_dev *dev = ctx->dev;
 	struct s5p_mfc_buf_size *buf_size = dev->variant->buf_size;
@@ -359,7 +360,7 @@ int s5p_mfc_set_dec_stream_buffer_v6(struct s5p_mfc_ctx *ctx, int buf_addr,
 }
 
 /* Set decoding frame buffer */
-int s5p_mfc_set_dec_frame_buffer_v6(struct s5p_mfc_ctx *ctx)
+static int s5p_mfc_set_dec_frame_buffer_v6(struct s5p_mfc_ctx *ctx)
 {
 	unsigned int frame_size, i;
 	unsigned int frame_size_ch, frame_size_mv;
@@ -440,7 +441,7 @@ int s5p_mfc_set_dec_frame_buffer_v6(struct s5p_mfc_ctx *ctx)
 }
 
 /* Set registers for encoding stream buffer */
-int s5p_mfc_set_enc_stream_buffer_v6(struct s5p_mfc_ctx *ctx,
+static int s5p_mfc_set_enc_stream_buffer_v6(struct s5p_mfc_ctx *ctx,
 		unsigned long addr, unsigned int size)
 {
 	struct s5p_mfc_dev *dev = ctx->dev;
@@ -454,7 +455,7 @@ int s5p_mfc_set_enc_stream_buffer_v6(struct s5p_mfc_ctx *ctx,
 	return 0;
 }
 
-void s5p_mfc_set_enc_frame_buffer_v6(struct s5p_mfc_ctx *ctx,
+static void s5p_mfc_set_enc_frame_buffer_v6(struct s5p_mfc_ctx *ctx,
 		unsigned long y_addr, unsigned long c_addr)
 {
 	struct s5p_mfc_dev *dev = ctx->dev;
@@ -466,7 +467,7 @@ void s5p_mfc_set_enc_frame_buffer_v6(struct s5p_mfc_ctx *ctx,
 	mfc_debug(2, "enc src c buf addr: 0x%08lx", c_addr);
 }
 
-void s5p_mfc_get_enc_frame_buffer_v6(struct s5p_mfc_ctx *ctx,
+static void s5p_mfc_get_enc_frame_buffer_v6(struct s5p_mfc_ctx *ctx,
 		unsigned long *y_addr, unsigned long *c_addr)
 {
 	struct s5p_mfc_dev *dev = ctx->dev;
@@ -483,7 +484,7 @@ void s5p_mfc_get_enc_frame_buffer_v6(struct s5p_mfc_ctx *ctx,
 }
 
 /* Set encoding ref & codec buffer */
-int s5p_mfc_set_enc_ref_buffer_v6(struct s5p_mfc_ctx *ctx)
+static int s5p_mfc_set_enc_ref_buffer_v6(struct s5p_mfc_ctx *ctx)
 {
 	struct s5p_mfc_dev *dev = ctx->dev;
 	size_t buf_addr1;
@@ -1147,7 +1148,7 @@ static int s5p_mfc_set_enc_params_h263(struct s5p_mfc_ctx *ctx)
 }
 
 /* Initialize decoding */
-int s5p_mfc_init_decode_v6(struct s5p_mfc_ctx *ctx)
+static int s5p_mfc_init_decode_v6(struct s5p_mfc_ctx *ctx)
 {
 	struct s5p_mfc_dev *dev = ctx->dev;
 	unsigned int reg = 0;
@@ -1215,7 +1216,7 @@ static inline void s5p_mfc_set_flush(struct s5p_mfc_ctx *ctx, int flush)
 }
 
 /* Decode a single frame */
-int s5p_mfc_decode_one_frame_v6(struct s5p_mfc_ctx *ctx,
+static int s5p_mfc_decode_one_frame_v6(struct s5p_mfc_ctx *ctx,
 			enum s5p_mfc_decode_arg last_frame)
 {
 	struct s5p_mfc_dev *dev = ctx->dev;
@@ -1244,7 +1245,7 @@ int s5p_mfc_decode_one_frame_v6(struct s5p_mfc_ctx *ctx,
 	return 0;
 }
 
-int s5p_mfc_init_encode_v6(struct s5p_mfc_ctx *ctx)
+static int s5p_mfc_init_encode_v6(struct s5p_mfc_ctx *ctx)
 {
 	struct s5p_mfc_dev *dev = ctx->dev;
 
@@ -1267,7 +1268,7 @@ int s5p_mfc_init_encode_v6(struct s5p_mfc_ctx *ctx)
 	return 0;
 }
 
-int s5p_mfc_h264_set_aso_slice_order_v6(struct s5p_mfc_ctx *ctx)
+static int s5p_mfc_h264_set_aso_slice_order_v6(struct s5p_mfc_ctx *ctx)
 {
 	struct s5p_mfc_dev *dev = ctx->dev;
 	struct s5p_mfc_enc_params *p = &ctx->enc_params;
@@ -1283,7 +1284,7 @@ int s5p_mfc_h264_set_aso_slice_order_v6(struct s5p_mfc_ctx *ctx)
 }
 
 /* Encode a single frame */
-int s5p_mfc_encode_one_frame_v6(struct s5p_mfc_ctx *ctx)
+static int s5p_mfc_encode_one_frame_v6(struct s5p_mfc_ctx *ctx)
 {
 	struct s5p_mfc_dev *dev = ctx->dev;
 
@@ -1312,7 +1313,7 @@ static inline int s5p_mfc_get_new_ctx(struct s5p_mfc_dev *dev)
 	int cnt;
 
 	spin_lock_irqsave(&dev->condlock, flags);
-	mfc_debug(2, "Previos context: %d (bits %08lx)\n", dev->curr_ctx,
+	mfc_debug(2, "Previous context: %d (bits %08lx)\n", dev->curr_ctx,
 							dev->ctx_work_bits);
 	new_ctx = (dev->curr_ctx + 1) % MFC_NUM_CONTEXTS;
 	cnt = 0;
@@ -1540,7 +1541,7 @@ static inline int s5p_mfc_run_init_enc_buffers(struct s5p_mfc_ctx *ctx)
 }
 
 /* Try running an operation on hardware */
-void s5p_mfc_try_run_v6(struct s5p_mfc_dev *dev)
+static void s5p_mfc_try_run_v6(struct s5p_mfc_dev *dev)
 {
 	struct s5p_mfc_ctx *ctx;
 	int new_ctx;
@@ -1663,7 +1664,7 @@ void s5p_mfc_try_run_v6(struct s5p_mfc_dev *dev)
 }
 
 
-void s5p_mfc_cleanup_queue_v6(struct list_head *lh, struct vb2_queue *vq)
+static void s5p_mfc_cleanup_queue_v6(struct list_head *lh, struct vb2_queue *vq)
 {
 	struct s5p_mfc_buf *b;
 	int i;
@@ -1677,13 +1678,13 @@ void s5p_mfc_cleanup_queue_v6(struct list_head *lh, struct vb2_queue *vq)
 	}
 }
 
-void s5p_mfc_clear_int_flags_v6(struct s5p_mfc_dev *dev)
+static void s5p_mfc_clear_int_flags_v6(struct s5p_mfc_dev *dev)
 {
 	mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD_V6);
 	mfc_write(dev, 0, S5P_FIMV_RISC2HOST_INT_V6);
 }
 
-void s5p_mfc_write_info_v6(struct s5p_mfc_ctx *ctx, unsigned int data,
+static void s5p_mfc_write_info_v6(struct s5p_mfc_ctx *ctx, unsigned int data,
 		unsigned int ofs)
 {
 	struct s5p_mfc_dev *dev = ctx->dev;
@@ -1693,7 +1694,8 @@ void s5p_mfc_write_info_v6(struct s5p_mfc_ctx *ctx, unsigned int data,
 	s5p_mfc_clock_off();
 }
 
-unsigned int s5p_mfc_read_info_v6(struct s5p_mfc_ctx *ctx, unsigned int ofs)
+static unsigned int
+s5p_mfc_read_info_v6(struct s5p_mfc_ctx *ctx, unsigned int ofs)
 {
 	struct s5p_mfc_dev *dev = ctx->dev;
 	int ret;
@@ -1705,140 +1707,140 @@ unsigned int s5p_mfc_read_info_v6(struct s5p_mfc_ctx *ctx, unsigned int ofs)
 	return ret;
 }
 
-int s5p_mfc_get_dspl_y_adr_v6(struct s5p_mfc_dev *dev)
+static int s5p_mfc_get_dspl_y_adr_v6(struct s5p_mfc_dev *dev)
 {
 	return mfc_read(dev, S5P_FIMV_D_DISPLAY_LUMA_ADDR_V6);
 }
 
-int s5p_mfc_get_dec_y_adr_v6(struct s5p_mfc_dev *dev)
+static int s5p_mfc_get_dec_y_adr_v6(struct s5p_mfc_dev *dev)
 {
 	return mfc_read(dev, S5P_FIMV_D_DECODED_LUMA_ADDR_V6);
 }
 
-int s5p_mfc_get_dspl_status_v6(struct s5p_mfc_dev *dev)
+static int s5p_mfc_get_dspl_status_v6(struct s5p_mfc_dev *dev)
 {
 	return mfc_read(dev, S5P_FIMV_D_DISPLAY_STATUS_V6);
 }
 
-int s5p_mfc_get_decoded_status_v6(struct s5p_mfc_dev *dev)
+static int s5p_mfc_get_decoded_status_v6(struct s5p_mfc_dev *dev)
 {
 	return mfc_read(dev, S5P_FIMV_D_DECODED_STATUS_V6);
 }
 
-int s5p_mfc_get_dec_frame_type_v6(struct s5p_mfc_dev *dev)
+static int s5p_mfc_get_dec_frame_type_v6(struct s5p_mfc_dev *dev)
 {
 	return mfc_read(dev, S5P_FIMV_D_DECODED_FRAME_TYPE_V6) &
 		S5P_FIMV_DECODE_FRAME_MASK_V6;
 }
 
-int s5p_mfc_get_disp_frame_type_v6(struct s5p_mfc_ctx *ctx)
+static int s5p_mfc_get_disp_frame_type_v6(struct s5p_mfc_ctx *ctx)
 {
 	return mfc_read(ctx->dev, S5P_FIMV_D_DISPLAY_FRAME_TYPE_V6) &
 		S5P_FIMV_DECODE_FRAME_MASK_V6;
 }
 
-int s5p_mfc_get_consumed_stream_v6(struct s5p_mfc_dev *dev)
+static int s5p_mfc_get_consumed_stream_v6(struct s5p_mfc_dev *dev)
 {
 	return mfc_read(dev, S5P_FIMV_D_DECODED_NAL_SIZE_V6);
 }
 
-int s5p_mfc_get_int_reason_v6(struct s5p_mfc_dev *dev)
+static int s5p_mfc_get_int_reason_v6(struct s5p_mfc_dev *dev)
 {
 	return mfc_read(dev, S5P_FIMV_RISC2HOST_CMD_V6) &
 		S5P_FIMV_RISC2HOST_CMD_MASK;
 }
 
-int s5p_mfc_get_int_err_v6(struct s5p_mfc_dev *dev)
+static int s5p_mfc_get_int_err_v6(struct s5p_mfc_dev *dev)
 {
 	return mfc_read(dev, S5P_FIMV_ERROR_CODE_V6);
 }
 
-int s5p_mfc_err_dec_v6(unsigned int err)
+static int s5p_mfc_err_dec_v6(unsigned int err)
 {
 	return (err & S5P_FIMV_ERR_DEC_MASK_V6) >> S5P_FIMV_ERR_DEC_SHIFT_V6;
 }
 
-int s5p_mfc_err_dspl_v6(unsigned int err)
+static int s5p_mfc_err_dspl_v6(unsigned int err)
 {
 	return (err & S5P_FIMV_ERR_DSPL_MASK_V6) >> S5P_FIMV_ERR_DSPL_SHIFT_V6;
 }
 
-int s5p_mfc_get_img_width_v6(struct s5p_mfc_dev *dev)
+static int s5p_mfc_get_img_width_v6(struct s5p_mfc_dev *dev)
 {
 	return mfc_read(dev, S5P_FIMV_D_DISPLAY_FRAME_WIDTH_V6);
 }
 
-int s5p_mfc_get_img_height_v6(struct s5p_mfc_dev *dev)
+static int s5p_mfc_get_img_height_v6(struct s5p_mfc_dev *dev)
 {
 	return mfc_read(dev, S5P_FIMV_D_DISPLAY_FRAME_HEIGHT_V6);
 }
 
-int s5p_mfc_get_dpb_count_v6(struct s5p_mfc_dev *dev)
+static int s5p_mfc_get_dpb_count_v6(struct s5p_mfc_dev *dev)
 {
 	return mfc_read(dev, S5P_FIMV_D_MIN_NUM_DPB_V6);
 }
 
-int s5p_mfc_get_mv_count_v6(struct s5p_mfc_dev *dev)
+static int s5p_mfc_get_mv_count_v6(struct s5p_mfc_dev *dev)
 {
 	return mfc_read(dev, S5P_FIMV_D_MIN_NUM_MV_V6);
 }
 
-int s5p_mfc_get_inst_no_v6(struct s5p_mfc_dev *dev)
+static int s5p_mfc_get_inst_no_v6(struct s5p_mfc_dev *dev)
 {
 	return mfc_read(dev, S5P_FIMV_RET_INSTANCE_ID_V6);
 }
 
-int s5p_mfc_get_enc_dpb_count_v6(struct s5p_mfc_dev *dev)
+static int s5p_mfc_get_enc_dpb_count_v6(struct s5p_mfc_dev *dev)
 {
 	return mfc_read(dev, S5P_FIMV_E_NUM_DPB_V6);
 }
 
-int s5p_mfc_get_enc_strm_size_v6(struct s5p_mfc_dev *dev)
+static int s5p_mfc_get_enc_strm_size_v6(struct s5p_mfc_dev *dev)
 {
 	return mfc_read(dev, S5P_FIMV_E_STREAM_SIZE_V6);
 }
 
-int s5p_mfc_get_enc_slice_type_v6(struct s5p_mfc_dev *dev)
+static int s5p_mfc_get_enc_slice_type_v6(struct s5p_mfc_dev *dev)
 {
 	return mfc_read(dev, S5P_FIMV_E_SLICE_TYPE_V6);
 }
 
-int s5p_mfc_get_enc_pic_count_v6(struct s5p_mfc_dev *dev)
+static int s5p_mfc_get_enc_pic_count_v6(struct s5p_mfc_dev *dev)
 {
 	return mfc_read(dev, S5P_FIMV_E_PICTURE_COUNT_V6);
 }
 
-int s5p_mfc_get_sei_avail_status_v6(struct s5p_mfc_ctx *ctx)
+static int s5p_mfc_get_sei_avail_status_v6(struct s5p_mfc_ctx *ctx)
 {
 	return mfc_read(ctx->dev, S5P_FIMV_D_FRAME_PACK_SEI_AVAIL_V6);
 }
 
-int s5p_mfc_get_mvc_num_views_v6(struct s5p_mfc_dev *dev)
+static int s5p_mfc_get_mvc_num_views_v6(struct s5p_mfc_dev *dev)
 {
 	return mfc_read(dev, S5P_FIMV_D_MVC_NUM_VIEWS_V6);
 }
 
-int s5p_mfc_get_mvc_view_id_v6(struct s5p_mfc_dev *dev)
+static int s5p_mfc_get_mvc_view_id_v6(struct s5p_mfc_dev *dev)
 {
 	return mfc_read(dev, S5P_FIMV_D_MVC_VIEW_ID_V6);
 }
 
-unsigned int s5p_mfc_get_pic_type_top_v6(struct s5p_mfc_ctx *ctx)
+static unsigned int s5p_mfc_get_pic_type_top_v6(struct s5p_mfc_ctx *ctx)
 {
 	return s5p_mfc_read_info_v6(ctx, PIC_TIME_TOP_V6);
 }
 
-unsigned int s5p_mfc_get_pic_type_bot_v6(struct s5p_mfc_ctx *ctx)
+static unsigned int s5p_mfc_get_pic_type_bot_v6(struct s5p_mfc_ctx *ctx)
 {
 	return s5p_mfc_read_info_v6(ctx, PIC_TIME_BOT_V6);
 }
 
-unsigned int s5p_mfc_get_crop_info_h_v6(struct s5p_mfc_ctx *ctx)
+static unsigned int s5p_mfc_get_crop_info_h_v6(struct s5p_mfc_ctx *ctx)
 {
 	return s5p_mfc_read_info_v6(ctx, CROP_INFO_H_V6);
 }
 
-unsigned int s5p_mfc_get_crop_info_v_v6(struct s5p_mfc_ctx *ctx)
+static unsigned int s5p_mfc_get_crop_info_v_v6(struct s5p_mfc_ctx *ctx)
 {
 	return s5p_mfc_read_info_v6(ctx, CROP_INFO_V_V6);
 }
diff --git a/drivers/media/platform/s5p-tv/hdmi_drv.c b/drivers/media/platform/s5p-tv/hdmi_drv.c
index 8de1b3d..4e86626 100644
--- a/drivers/media/platform/s5p-tv/hdmi_drv.c
+++ b/drivers/media/platform/s5p-tv/hdmi_drv.c
@@ -31,6 +31,7 @@
 #include <linux/pm_runtime.h>
 #include <linux/clk.h>
 #include <linux/regulator/consumer.h>
+#include <linux/v4l2-dv-timings.h>
 
 #include <media/s5p_hdmi.h>
 #include <media/v4l2-common.h>
@@ -43,9 +44,6 @@ MODULE_AUTHOR("Tomasz Stanislawski, <t.stanislaws@samsung.com>");
 MODULE_DESCRIPTION("Samsung HDMI");
 MODULE_LICENSE("GPL");
 
-/* default preset configured on probe */
-#define HDMI_DEFAULT_PRESET V4L2_DV_480P59_94
-
 struct hdmi_pulse {
 	u32 beg;
 	u32 end;
@@ -91,8 +89,8 @@ struct hdmi_device {
 	const struct hdmi_timings *cur_conf;
 	/** flag indicating that timings are dirty */
 	int cur_conf_dirty;
-	/** current preset */
-	u32 cur_preset;
+	/** current timings */
+	struct v4l2_dv_timings cur_timings;
 	/** other resources */
 	struct hdmi_resources res;
 };
@@ -252,7 +250,6 @@ static int hdmi_conf_apply(struct hdmi_device *hdmi_dev)
 {
 	struct device *dev = hdmi_dev->dev;
 	const struct hdmi_timings *conf = hdmi_dev->cur_conf;
-	struct v4l2_dv_preset preset;
 	int ret;
 
 	dev_dbg(dev, "%s\n", __func__);
@@ -267,11 +264,11 @@ static int hdmi_conf_apply(struct hdmi_device *hdmi_dev)
 	hdmi_write_mask(hdmi_dev, HDMI_PHY_RSTOUT,  0, HDMI_PHY_SW_RSTOUT);
 	mdelay(10);
 
-	/* configure presets */
-	preset.preset = hdmi_dev->cur_preset;
-	ret = v4l2_subdev_call(hdmi_dev->phy_sd, video, s_dv_preset, &preset);
+	/* configure timings */
+	ret = v4l2_subdev_call(hdmi_dev->phy_sd, video, s_dv_timings,
+				&hdmi_dev->cur_timings);
 	if (ret) {
-		dev_err(dev, "failed to set preset (%u)\n", preset.preset);
+		dev_err(dev, "failed to set timings\n");
 		return ret;
 	}
 
@@ -475,33 +472,26 @@ static const struct hdmi_timings hdmi_timings_1080p50 = {
 	.vsyn[0] = { .beg = 0 + 4, .end = 5 + 4},
 };
 
+/* default hdmi_timings index of the timings configured on probe */
+#define HDMI_DEFAULT_TIMINGS_IDX (0)
+
 static const struct {
-	u32 preset;
-	const struct hdmi_timings *timings;
+	bool reduced_fps;
+	const struct v4l2_dv_timings dv_timings;
+	const struct hdmi_timings *hdmi_timings;
 } hdmi_timings[] = {
-	{ V4L2_DV_480P59_94, &hdmi_timings_480p },
-	{ V4L2_DV_576P50, &hdmi_timings_576p50 },
-	{ V4L2_DV_720P50, &hdmi_timings_720p50 },
-	{ V4L2_DV_720P59_94, &hdmi_timings_720p60 },
-	{ V4L2_DV_720P60, &hdmi_timings_720p60 },
-	{ V4L2_DV_1080P24, &hdmi_timings_1080p24 },
-	{ V4L2_DV_1080P30, &hdmi_timings_1080p60 },
-	{ V4L2_DV_1080P50, &hdmi_timings_1080p50 },
-	{ V4L2_DV_1080I50, &hdmi_timings_1080i50 },
-	{ V4L2_DV_1080I60, &hdmi_timings_1080i60 },
-	{ V4L2_DV_1080P60, &hdmi_timings_1080p60 },
+	{ false, V4L2_DV_BT_CEA_720X480P59_94, &hdmi_timings_480p    },
+	{ false, V4L2_DV_BT_CEA_720X576P50,    &hdmi_timings_576p50  },
+	{ false, V4L2_DV_BT_CEA_1280X720P50,   &hdmi_timings_720p50  },
+	{ true,  V4L2_DV_BT_CEA_1280X720P60,   &hdmi_timings_720p60  },
+	{ false, V4L2_DV_BT_CEA_1920X1080P24,  &hdmi_timings_1080p24 },
+	{ false, V4L2_DV_BT_CEA_1920X1080P30,  &hdmi_timings_1080p60 },
+	{ false, V4L2_DV_BT_CEA_1920X1080P50,  &hdmi_timings_1080p50 },
+	{ false, V4L2_DV_BT_CEA_1920X1080I50,  &hdmi_timings_1080i50 },
+	{ false, V4L2_DV_BT_CEA_1920X1080I60,  &hdmi_timings_1080i60 },
+	{ false, V4L2_DV_BT_CEA_1920X1080P60,  &hdmi_timings_1080p60 },
 };
 
-static const struct hdmi_timings *hdmi_preset2timings(u32 preset)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(hdmi_timings); ++i)
-		if (hdmi_timings[i].preset == preset)
-			return  hdmi_timings[i].timings;
-	return NULL;
-}
-
 static int hdmi_streamon(struct hdmi_device *hdev)
 {
 	struct device *dev = hdev->dev;
@@ -621,29 +611,33 @@ static int hdmi_s_power(struct v4l2_subdev *sd, int on)
 	return IS_ERR_VALUE(ret) ? ret : 0;
 }
 
-static int hdmi_s_dv_preset(struct v4l2_subdev *sd,
-	struct v4l2_dv_preset *preset)
+static int hdmi_s_dv_timings(struct v4l2_subdev *sd,
+	struct v4l2_dv_timings *timings)
 {
 	struct hdmi_device *hdev = sd_to_hdmi_dev(sd);
 	struct device *dev = hdev->dev;
-	const struct hdmi_timings *conf;
+	int i;
 
-	conf = hdmi_preset2timings(preset->preset);
-	if (conf == NULL) {
-		dev_err(dev, "preset (%u) not supported\n", preset->preset);
+	for (i = 0; i < ARRAY_SIZE(hdmi_timings); i++)
+		if (v4l_match_dv_timings(&hdmi_timings[i].dv_timings,
+					timings, 0))
+			break;
+	if (i == ARRAY_SIZE(hdmi_timings)) {
+		dev_err(dev, "timings not supported\n");
 		return -EINVAL;
 	}
-	hdev->cur_conf = conf;
+	hdev->cur_conf = hdmi_timings[i].hdmi_timings;
 	hdev->cur_conf_dirty = 1;
-	hdev->cur_preset = preset->preset;
+	hdev->cur_timings = *timings;
+	if (!hdmi_timings[i].reduced_fps)
+		hdev->cur_timings.bt.flags &= ~V4L2_DV_FL_CAN_REDUCE_FPS;
 	return 0;
 }
 
-static int hdmi_g_dv_preset(struct v4l2_subdev *sd,
-	struct v4l2_dv_preset *preset)
+static int hdmi_g_dv_timings(struct v4l2_subdev *sd,
+	struct v4l2_dv_timings *timings)
 {
-	memset(preset, 0, sizeof(*preset));
-	preset->preset = sd_to_hdmi_dev(sd)->cur_preset;
+	*timings = sd_to_hdmi_dev(sd)->cur_timings;
 	return 0;
 }
 
@@ -670,13 +664,33 @@ static int hdmi_g_mbus_fmt(struct v4l2_subdev *sd,
 	return 0;
 }
 
-static int hdmi_enum_dv_presets(struct v4l2_subdev *sd,
-	struct v4l2_dv_enum_preset *preset)
+static int hdmi_enum_dv_timings(struct v4l2_subdev *sd,
+	struct v4l2_enum_dv_timings *timings)
 {
-	if (preset->index >= ARRAY_SIZE(hdmi_timings))
+	if (timings->index >= ARRAY_SIZE(hdmi_timings))
 		return -EINVAL;
-	return v4l_fill_dv_preset_info(hdmi_timings[preset->index].preset,
-		preset);
+	timings->timings = hdmi_timings[timings->index].dv_timings;
+	if (!hdmi_timings[timings->index].reduced_fps)
+		timings->timings.bt.flags &= ~V4L2_DV_FL_CAN_REDUCE_FPS;
+	return 0;
+}
+
+static int hdmi_dv_timings_cap(struct v4l2_subdev *sd,
+	struct v4l2_dv_timings_cap *cap)
+{
+	struct hdmi_device *hdev = sd_to_hdmi_dev(sd);
+
+	/* Let the phy fill in the pixelclock range */
+	v4l2_subdev_call(hdev->phy_sd, video, dv_timings_cap, cap);
+	cap->type = V4L2_DV_BT_656_1120;
+	cap->bt.min_width = 720;
+	cap->bt.max_width = 1920;
+	cap->bt.min_height = 480;
+	cap->bt.max_height = 1080;
+	cap->bt.standards = V4L2_DV_BT_STD_CEA861;
+	cap->bt.capabilities = V4L2_DV_BT_CAP_INTERLACED |
+			       V4L2_DV_BT_CAP_PROGRESSIVE;
+	return 0;
 }
 
 static const struct v4l2_subdev_core_ops hdmi_sd_core_ops = {
@@ -684,9 +698,10 @@ static const struct v4l2_subdev_core_ops hdmi_sd_core_ops = {
 };
 
 static const struct v4l2_subdev_video_ops hdmi_sd_video_ops = {
-	.s_dv_preset = hdmi_s_dv_preset,
-	.g_dv_preset = hdmi_g_dv_preset,
-	.enum_dv_presets = hdmi_enum_dv_presets,
+	.s_dv_timings = hdmi_s_dv_timings,
+	.g_dv_timings = hdmi_g_dv_timings,
+	.enum_dv_timings = hdmi_enum_dv_timings,
+	.dv_timings_cap = hdmi_dv_timings_cap,
 	.g_mbus_fmt = hdmi_g_mbus_fmt,
 	.s_stream = hdmi_s_stream,
 };
@@ -956,9 +971,11 @@ static int hdmi_probe(struct platform_device *pdev)
 	sd->owner = THIS_MODULE;
 
 	strlcpy(sd->name, "s5p-hdmi", sizeof(sd->name));
-	hdmi_dev->cur_preset = HDMI_DEFAULT_PRESET;
-	/* FIXME: missing fail preset is not supported */
-	hdmi_dev->cur_conf = hdmi_preset2timings(hdmi_dev->cur_preset);
+	hdmi_dev->cur_timings =
+		hdmi_timings[HDMI_DEFAULT_TIMINGS_IDX].dv_timings;
+	/* FIXME: missing fail timings is not supported */
+	hdmi_dev->cur_conf =
+		hdmi_timings[HDMI_DEFAULT_TIMINGS_IDX].hdmi_timings;
 	hdmi_dev->cur_conf_dirty = 1;
 
 	/* storing subdev for call that have only access to struct device */
diff --git a/drivers/media/platform/s5p-tv/hdmiphy_drv.c b/drivers/media/platform/s5p-tv/hdmiphy_drv.c
index 80717ce..e19a0af 100644
--- a/drivers/media/platform/s5p-tv/hdmiphy_drv.c
+++ b/drivers/media/platform/s5p-tv/hdmiphy_drv.c
@@ -176,35 +176,9 @@ static inline struct hdmiphy_ctx *sd_to_ctx(struct v4l2_subdev *sd)
 	return container_of(sd, struct hdmiphy_ctx, sd);
 }
 
-static unsigned long hdmiphy_preset_to_pixclk(u32 preset)
+static const u8 *hdmiphy_find_conf(unsigned long pixclk,
+		const struct hdmiphy_conf *conf)
 {
-	static const unsigned long pixclk[] = {
-		[V4L2_DV_480P59_94] =  27000000,
-		[V4L2_DV_576P50]    =  27000000,
-		[V4L2_DV_720P59_94] =  74176000,
-		[V4L2_DV_720P50]    =  74250000,
-		[V4L2_DV_720P60]    =  74250000,
-		[V4L2_DV_1080P24]   =  74250000,
-		[V4L2_DV_1080P30]   =  74250000,
-		[V4L2_DV_1080I50]   =  74250000,
-		[V4L2_DV_1080I60]   =  74250000,
-		[V4L2_DV_1080P50]   = 148500000,
-		[V4L2_DV_1080P60]   = 148500000,
-	};
-	if (preset < ARRAY_SIZE(pixclk))
-		return pixclk[preset];
-	else
-		return 0;
-}
-
-static const u8 *hdmiphy_find_conf(u32 preset, const struct hdmiphy_conf *conf)
-{
-	unsigned long pixclk;
-
-	pixclk = hdmiphy_preset_to_pixclk(preset);
-	if (!pixclk)
-		return NULL;
-
 	for (; conf->pixclk; ++conf)
 		if (conf->pixclk == pixclk)
 			return conf->data;
@@ -217,8 +191,8 @@ static int hdmiphy_s_power(struct v4l2_subdev *sd, int on)
 	return 0;
 }
 
-static int hdmiphy_s_dv_preset(struct v4l2_subdev *sd,
-	struct v4l2_dv_preset *preset)
+static int hdmiphy_s_dv_timings(struct v4l2_subdev *sd,
+	struct v4l2_dv_timings *timings)
 {
 	const u8 *data;
 	u8 buffer[32];
@@ -226,9 +200,12 @@ static int hdmiphy_s_dv_preset(struct v4l2_subdev *sd,
 	struct hdmiphy_ctx *ctx = sd_to_ctx(sd);
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 	struct device *dev = &client->dev;
+	unsigned long pixclk = timings->bt.pixelclock;
 
-	dev_info(dev, "s_dv_preset(preset = %d)\n", preset->preset);
-	data = hdmiphy_find_conf(preset->preset, ctx->conf_tab);
+	dev_info(dev, "s_dv_timings\n");
+	if ((timings->bt.flags & V4L2_DV_FL_REDUCED_FPS) && pixclk == 74250000)
+		pixclk = 74176000;
+	data = hdmiphy_find_conf(pixclk, ctx->conf_tab);
 	if (!data) {
 		dev_err(dev, "format not supported\n");
 		return -EINVAL;
@@ -245,6 +222,17 @@ static int hdmiphy_s_dv_preset(struct v4l2_subdev *sd,
 	return 0;
 }
 
+static int hdmiphy_dv_timings_cap(struct v4l2_subdev *sd,
+	struct v4l2_dv_timings_cap *cap)
+{
+	cap->type = V4L2_DV_BT_656_1120;
+	/* The phy only determines the pixelclock, leave the other values
+	 * at 0 to signify that we have no information for them. */
+	cap->bt.min_pixelclock = 27000000;
+	cap->bt.max_pixelclock = 148500000;
+	return 0;
+}
+
 static int hdmiphy_s_stream(struct v4l2_subdev *sd, int enable)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
@@ -270,7 +258,8 @@ static const struct v4l2_subdev_core_ops hdmiphy_core_ops = {
 };
 
 static const struct v4l2_subdev_video_ops hdmiphy_video_ops = {
-	.s_dv_preset = hdmiphy_s_dv_preset,
+	.s_dv_timings = hdmiphy_s_dv_timings,
+	.dv_timings_cap = hdmiphy_dv_timings_cap,
 	.s_stream =  hdmiphy_s_stream,
 };
 
diff --git a/drivers/media/platform/s5p-tv/mixer_video.c b/drivers/media/platform/s5p-tv/mixer_video.c
index 82142a2..ef0efdf 100644
--- a/drivers/media/platform/s5p-tv/mixer_video.c
+++ b/drivers/media/platform/s5p-tv/mixer_video.c
@@ -501,8 +501,8 @@ fail:
 	return -ERANGE;
 }
 
-static int mxr_enum_dv_presets(struct file *file, void *fh,
-	struct v4l2_dv_enum_preset *preset)
+static int mxr_enum_dv_timings(struct file *file, void *fh,
+	struct v4l2_enum_dv_timings *timings)
 {
 	struct mxr_layer *layer = video_drvdata(file);
 	struct mxr_device *mdev = layer->mdev;
@@ -510,14 +510,14 @@ static int mxr_enum_dv_presets(struct file *file, void *fh,
 
 	/* lock protects from changing sd_out */
 	mutex_lock(&mdev->mutex);
-	ret = v4l2_subdev_call(to_outsd(mdev), video, enum_dv_presets, preset);
+	ret = v4l2_subdev_call(to_outsd(mdev), video, enum_dv_timings, timings);
 	mutex_unlock(&mdev->mutex);
 
 	return ret ? -EINVAL : 0;
 }
 
-static int mxr_s_dv_preset(struct file *file, void *fh,
-	struct v4l2_dv_preset *preset)
+static int mxr_s_dv_timings(struct file *file, void *fh,
+	struct v4l2_dv_timings *timings)
 {
 	struct mxr_layer *layer = video_drvdata(file);
 	struct mxr_device *mdev = layer->mdev;
@@ -526,7 +526,7 @@ static int mxr_s_dv_preset(struct file *file, void *fh,
 	/* lock protects from changing sd_out */
 	mutex_lock(&mdev->mutex);
 
-	/* preset change cannot be done while there is an entity
+	/* timings change cannot be done while there is an entity
 	 * dependant on output configuration
 	 */
 	if (mdev->n_output > 0) {
@@ -534,7 +534,7 @@ static int mxr_s_dv_preset(struct file *file, void *fh,
 		return -EBUSY;
 	}
 
-	ret = v4l2_subdev_call(to_outsd(mdev), video, s_dv_preset, preset);
+	ret = v4l2_subdev_call(to_outsd(mdev), video, s_dv_timings, timings);
 
 	mutex_unlock(&mdev->mutex);
 
@@ -544,8 +544,8 @@ static int mxr_s_dv_preset(struct file *file, void *fh,
 	return ret ? -EINVAL : 0;
 }
 
-static int mxr_g_dv_preset(struct file *file, void *fh,
-	struct v4l2_dv_preset *preset)
+static int mxr_g_dv_timings(struct file *file, void *fh,
+	struct v4l2_dv_timings *timings)
 {
 	struct mxr_layer *layer = video_drvdata(file);
 	struct mxr_device *mdev = layer->mdev;
@@ -553,13 +553,28 @@ static int mxr_g_dv_preset(struct file *file, void *fh,
 
 	/* lock protects from changing sd_out */
 	mutex_lock(&mdev->mutex);
-	ret = v4l2_subdev_call(to_outsd(mdev), video, g_dv_preset, preset);
+	ret = v4l2_subdev_call(to_outsd(mdev), video, g_dv_timings, timings);
 	mutex_unlock(&mdev->mutex);
 
 	return ret ? -EINVAL : 0;
 }
 
-static int mxr_s_std(struct file *file, void *fh, v4l2_std_id *norm)
+static int mxr_dv_timings_cap(struct file *file, void *fh,
+	struct v4l2_dv_timings_cap *cap)
+{
+	struct mxr_layer *layer = video_drvdata(file);
+	struct mxr_device *mdev = layer->mdev;
+	int ret;
+
+	/* lock protects from changing sd_out */
+	mutex_lock(&mdev->mutex);
+	ret = v4l2_subdev_call(to_outsd(mdev), video, dv_timings_cap, cap);
+	mutex_unlock(&mdev->mutex);
+
+	return ret ? -EINVAL : 0;
+}
+
+static int mxr_s_std(struct file *file, void *fh, v4l2_std_id norm)
 {
 	struct mxr_layer *layer = video_drvdata(file);
 	struct mxr_device *mdev = layer->mdev;
@@ -576,7 +591,7 @@ static int mxr_s_std(struct file *file, void *fh, v4l2_std_id *norm)
 		return -EBUSY;
 	}
 
-	ret = v4l2_subdev_call(to_outsd(mdev), video, s_std_output, *norm);
+	ret = v4l2_subdev_call(to_outsd(mdev), video, s_std_output, norm);
 
 	mutex_unlock(&mdev->mutex);
 
@@ -616,8 +631,8 @@ static int mxr_enum_output(struct file *file, void *fh, struct v4l2_output *a)
 	/* try to obtain supported tv norms */
 	v4l2_subdev_call(sd, video, g_tvnorms_output, &a->std);
 	a->capabilities = 0;
-	if (sd->ops->video && sd->ops->video->s_dv_preset)
-		a->capabilities |= V4L2_OUT_CAP_PRESETS;
+	if (sd->ops->video && sd->ops->video->s_dv_timings)
+		a->capabilities |= V4L2_OUT_CAP_DV_TIMINGS;
 	if (sd->ops->video && sd->ops->video->s_std_output)
 		a->capabilities |= V4L2_OUT_CAP_STD;
 	a->type = V4L2_OUTPUT_TYPE_ANALOG;
@@ -738,10 +753,11 @@ static const struct v4l2_ioctl_ops mxr_ioctl_ops = {
 	/* Streaming control */
 	.vidioc_streamon = mxr_streamon,
 	.vidioc_streamoff = mxr_streamoff,
-	/* Preset functions */
-	.vidioc_enum_dv_presets = mxr_enum_dv_presets,
-	.vidioc_s_dv_preset = mxr_s_dv_preset,
-	.vidioc_g_dv_preset = mxr_g_dv_preset,
+	/* DV Timings functions */
+	.vidioc_enum_dv_timings = mxr_enum_dv_timings,
+	.vidioc_s_dv_timings = mxr_s_dv_timings,
+	.vidioc_g_dv_timings = mxr_g_dv_timings,
+	.vidioc_dv_timings_cap = mxr_dv_timings_cap,
 	/* analog TV standard functions */
 	.vidioc_s_std = mxr_s_std,
 	.vidioc_g_std = mxr_g_std,
diff --git a/drivers/media/platform/sh_veu.c b/drivers/media/platform/sh_veu.c
index cb54c69..0b32cc3 100644
--- a/drivers/media/platform/sh_veu.c
+++ b/drivers/media/platform/sh_veu.c
@@ -10,6 +10,7 @@
  * published by the Free Software Foundation
  */
 
+#include <linux/err.h>
 #include <linux/fs.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -1164,9 +1165,9 @@ static int sh_veu_probe(struct platform_device *pdev)
 
 	veu->is_2h = resource_size(reg_res) == 0x22c;
 
-	veu->base = devm_request_and_ioremap(&pdev->dev, reg_res);
-	if (!veu->base)
-		return -ENOMEM;
+	veu->base = devm_ioremap_resource(&pdev->dev, reg_res);
+	if (IS_ERR(veu->base))
+		return PTR_ERR(veu->base);
 
 	ret = devm_request_threaded_irq(&pdev->dev, irq, sh_veu_isr, sh_veu_bh,
 					0, "veu", veu);
@@ -1248,18 +1249,7 @@ static struct platform_driver __refdata sh_veu_pdrv = {
 	},
 };
 
-static int __init sh_veu_init(void)
-{
-	return platform_driver_probe(&sh_veu_pdrv, sh_veu_probe);
-}
-
-static void __exit sh_veu_exit(void)
-{
-	platform_driver_unregister(&sh_veu_pdrv);
-}
-
-module_init(sh_veu_init);
-module_exit(sh_veu_exit);
+module_platform_driver_probe(sh_veu_pdrv, sh_veu_probe);
 
 MODULE_DESCRIPTION("sh-mobile VEU mem2mem driver");
 MODULE_AUTHOR("Guennadi Liakhovetski, <g.liakhovetski@gmx.de>");
diff --git a/drivers/media/platform/sh_vou.c b/drivers/media/platform/sh_vou.c
index 66c8da1..7d02350 100644
--- a/drivers/media/platform/sh_vou.c
+++ b/drivers/media/platform/sh_vou.c
@@ -881,29 +881,29 @@ static u32 sh_vou_ntsc_mode(enum sh_vou_bus_fmt bus_fmt)
 	}
 }
 
-static int sh_vou_s_std(struct file *file, void *priv, v4l2_std_id *std_id)
+static int sh_vou_s_std(struct file *file, void *priv, v4l2_std_id std_id)
 {
 	struct sh_vou_device *vou_dev = video_drvdata(file);
 	int ret;
 
-	dev_dbg(vou_dev->v4l2_dev.dev, "%s(): 0x%llx\n", __func__, *std_id);
+	dev_dbg(vou_dev->v4l2_dev.dev, "%s(): 0x%llx\n", __func__, std_id);
 
-	if (*std_id & ~vou_dev->vdev->tvnorms)
+	if (std_id & ~vou_dev->vdev->tvnorms)
 		return -EINVAL;
 
 	ret = v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, video,
-					 s_std_output, *std_id);
+					 s_std_output, std_id);
 	/* Shall we continue, if the subdev doesn't support .s_std_output()? */
 	if (ret < 0 && ret != -ENOIOCTLCMD)
 		return ret;
 
-	if (*std_id & V4L2_STD_525_60)
+	if (std_id & V4L2_STD_525_60)
 		sh_vou_reg_ab_set(vou_dev, VOUCR,
 			sh_vou_ntsc_mode(vou_dev->pdata->bus_fmt) << 29, 7 << 29);
 	else
 		sh_vou_reg_ab_set(vou_dev, VOUCR, 5 << 29, 7 << 29);
 
-	vou_dev->std = *std_id;
+	vou_dev->std = std_id;
 
 	return 0;
 }
@@ -1266,7 +1266,7 @@ static int sh_vou_g_register(struct file *file, void *fh,
 }
 
 static int sh_vou_s_register(struct file *file, void *fh,
-				 struct v4l2_dbg_register *reg)
+				 const struct v4l2_dbg_register *reg)
 {
 	struct sh_vou_device *vou_dev = video_drvdata(file);
 
@@ -1485,18 +1485,7 @@ static struct platform_driver __refdata sh_vou = {
 	},
 };
 
-static int __init sh_vou_init(void)
-{
-	return platform_driver_probe(&sh_vou, sh_vou_probe);
-}
-
-static void __exit sh_vou_exit(void)
-{
-	platform_driver_unregister(&sh_vou);
-}
-
-module_init(sh_vou_init);
-module_exit(sh_vou_exit);
+module_platform_driver_probe(sh_vou, sh_vou_probe);
 
 MODULE_DESCRIPTION("SuperH VOU driver");
 MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
diff --git a/drivers/media/platform/soc_camera/atmel-isi.c b/drivers/media/platform/soc_camera/atmel-isi.c
index 82dbf99..c314ff9 100644
--- a/drivers/media/platform/soc_camera/atmel-isi.c
+++ b/drivers/media/platform/soc_camera/atmel-isi.c
@@ -514,6 +514,7 @@ static int isi_camera_init_videobuf(struct vb2_queue *q,
 	q->buf_struct_size = sizeof(struct frame_buffer);
 	q->ops = &isi_video_qops;
 	q->mem_ops = &vb2_dma_contig_memops;
+	q->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
 
 	return vb2_queue_init(q);
 }
diff --git a/drivers/media/platform/soc_camera/mx1_camera.c b/drivers/media/platform/soc_camera/mx1_camera.c
index 25b2a28..4389f43 100644
--- a/drivers/media/platform/soc_camera/mx1_camera.c
+++ b/drivers/media/platform/soc_camera/mx1_camera.c
@@ -859,18 +859,7 @@ static struct platform_driver mx1_camera_driver = {
 	.remove		= __exit_p(mx1_camera_remove),
 };
 
-static int __init mx1_camera_init(void)
-{
-	return platform_driver_probe(&mx1_camera_driver, mx1_camera_probe);
-}
-
-static void __exit mx1_camera_exit(void)
-{
-	return platform_driver_unregister(&mx1_camera_driver);
-}
-
-module_init(mx1_camera_init);
-module_exit(mx1_camera_exit);
+module_platform_driver_probe(mx1_camera_driver, mx1_camera_probe);
 
 MODULE_DESCRIPTION("i.MX1/i.MXL SoC Camera Host driver");
 MODULE_AUTHOR("Paulius Zaleckas <paulius.zaleckas@teltonika.lt>");
diff --git a/drivers/media/platform/soc_camera/mx2_camera.c b/drivers/media/platform/soc_camera/mx2_camera.c
index ffba7d9..048c26a 100644
--- a/drivers/media/platform/soc_camera/mx2_camera.c
+++ b/drivers/media/platform/soc_camera/mx2_camera.c
@@ -797,6 +797,7 @@ static int mx2_camera_init_videobuf(struct vb2_queue *q,
 	q->ops = &mx2_videobuf_ops;
 	q->mem_ops = &vb2_dma_contig_memops;
 	q->buf_struct_size = sizeof(struct mx2_buffer);
+	q->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
 
 	return vb2_queue_init(q);
 }
diff --git a/drivers/media/platform/soc_camera/mx3_camera.c b/drivers/media/platform/soc_camera/mx3_camera.c
index f5cbb92..2c3bd69 100644
--- a/drivers/media/platform/soc_camera/mx3_camera.c
+++ b/drivers/media/platform/soc_camera/mx3_camera.c
@@ -455,6 +455,7 @@ static int mx3_camera_init_videobuf(struct vb2_queue *q,
 	q->ops = &mx3_videobuf_ops;
 	q->mem_ops = &vb2_dma_contig_memops;
 	q->buf_struct_size = sizeof(struct mx3_camera_buffer);
+	q->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
 
 	return vb2_queue_init(q);
 }
diff --git a/drivers/media/platform/soc_camera/omap1_camera.c b/drivers/media/platform/soc_camera/omap1_camera.c
index 2547bf8..9689a6e 100644
--- a/drivers/media/platform/soc_camera/omap1_camera.c
+++ b/drivers/media/platform/soc_camera/omap1_camera.c
@@ -1546,7 +1546,7 @@ static struct soc_camera_host_ops omap1_host_ops = {
 	.poll		= omap1_cam_poll,
 };
 
-static int __init omap1_cam_probe(struct platform_device *pdev)
+static int omap1_cam_probe(struct platform_device *pdev)
 {
 	struct omap1_cam_dev *pcdev;
 	struct resource *res;
@@ -1677,7 +1677,7 @@ exit:
 	return err;
 }
 
-static int __exit omap1_cam_remove(struct platform_device *pdev)
+static int omap1_cam_remove(struct platform_device *pdev)
 {
 	struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev);
 	struct omap1_cam_dev *pcdev = container_of(soc_host,
@@ -1709,7 +1709,7 @@ static struct platform_driver omap1_cam_driver = {
 		.name	= DRIVER_NAME,
 	},
 	.probe		= omap1_cam_probe,
-	.remove		= __exit_p(omap1_cam_remove),
+	.remove		= omap1_cam_remove,
 };
 
 module_platform_driver(omap1_cam_driver);
diff --git a/drivers/media/platform/soc_camera/pxa_camera.c b/drivers/media/platform/soc_camera/pxa_camera.c
index 395e2e0..42abbce 100644
--- a/drivers/media/platform/soc_camera/pxa_camera.c
+++ b/drivers/media/platform/soc_camera/pxa_camera.c
@@ -15,6 +15,7 @@
 #include <linux/io.h>
 #include <linux/delay.h>
 #include <linux/dma-mapping.h>
+#include <linux/err.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/interrupt.h>
@@ -1710,9 +1711,10 @@ static int pxa_camera_probe(struct platform_device *pdev)
 	/*
 	 * Request the regions.
 	 */
-	base = devm_request_and_ioremap(&pdev->dev, res);
-	if (!base)
-		return -ENOMEM;
+	base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
 	pcdev->irq = irq;
 	pcdev->base = base;
 
diff --git a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
index bb08a46..d7294ef 100644
--- a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
+++ b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
@@ -20,6 +20,7 @@
 #include <linux/completion.h>
 #include <linux/delay.h>
 #include <linux/dma-mapping.h>
+#include <linux/err.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/interrupt.h>
@@ -2026,6 +2027,7 @@ static int sh_mobile_ceu_init_videobuf(struct vb2_queue *q,
 	q->ops = &sh_mobile_ceu_videobuf_ops;
 	q->mem_ops = &vb2_dma_contig_memops;
 	q->buf_struct_size = sizeof(struct sh_mobile_ceu_buffer);
+	q->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
 
 	return vb2_queue_init(q);
 }
@@ -2110,11 +2112,9 @@ static int sh_mobile_ceu_probe(struct platform_device *pdev)
 	pcdev->max_width = pcdev->pdata->max_width ? : 2560;
 	pcdev->max_height = pcdev->pdata->max_height ? : 1920;
 
-	base = devm_request_and_ioremap(&pdev->dev, res);
-	if (!base) {
-		dev_err(&pdev->dev, "Unable to ioremap CEU registers.\n");
-		return -ENXIO;
-	}
+	base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
 
 	pcdev->irq = irq;
 	pcdev->base = base;
diff --git a/drivers/media/platform/soc_camera/sh_mobile_csi2.c b/drivers/media/platform/soc_camera/sh_mobile_csi2.c
index 42c559e..09cb4fc 100644
--- a/drivers/media/platform/soc_camera/sh_mobile_csi2.c
+++ b/drivers/media/platform/soc_camera/sh_mobile_csi2.c
@@ -9,6 +9,7 @@
  */
 
 #include <linux/delay.h>
+#include <linux/err.h>
 #include <linux/i2c.h>
 #include <linux/io.h>
 #include <linux/platform_device.h>
@@ -324,11 +325,9 @@ static int sh_csi2_probe(struct platform_device *pdev)
 
 	priv->irq = irq;
 
-	priv->base = devm_request_and_ioremap(&pdev->dev, res);
-	if (!priv->base) {
-		dev_err(&pdev->dev, "Unable to ioremap CSI2 registers.\n");
-		return -ENXIO;
-	}
+	priv->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(priv->base))
+		return PTR_ERR(priv->base);
 
 	priv->pdev = pdev;
 	platform_set_drvdata(pdev, priv);
diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c
index 8ec9805..bf55abf 100644
--- a/drivers/media/platform/soc_camera/soc_camera.c
+++ b/drivers/media/platform/soc_camera/soc_camera.c
@@ -256,12 +256,12 @@ static int soc_camera_s_input(struct file *file, void *priv, unsigned int i)
 	return 0;
 }
 
-static int soc_camera_s_std(struct file *file, void *priv, v4l2_std_id *a)
+static int soc_camera_s_std(struct file *file, void *priv, v4l2_std_id a)
 {
 	struct soc_camera_device *icd = file->private_data;
 	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
 
-	return v4l2_subdev_call(sd, core, s_std, *a);
+	return v4l2_subdev_call(sd, core, s_std, a);
 }
 
 static int soc_camera_g_std(struct file *file, void *priv, v4l2_std_id *a)
@@ -1042,7 +1042,7 @@ static int soc_camera_g_register(struct file *file, void *fh,
 }
 
 static int soc_camera_s_register(struct file *file, void *fh,
-				 struct v4l2_dbg_register *reg)
+				 const struct v4l2_dbg_register *reg)
 {
 	struct soc_camera_device *icd = file->private_data;
 	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
diff --git a/drivers/media/platform/timblogiw.c b/drivers/media/platform/timblogiw.c
index c3a2a44..a2f7bdd 100644
--- a/drivers/media/platform/timblogiw.c
+++ b/drivers/media/platform/timblogiw.c
@@ -78,7 +78,7 @@ struct timblogiw_buffer {
 	struct timblogiw_fh	*fh;
 };
 
-const struct timblogiw_tvnorm timblogiw_tvnorms[] = {
+static const struct timblogiw_tvnorm timblogiw_tvnorms[] = {
 	{
 		.std			= V4L2_STD_PAL,
 		.width			= 720,
@@ -336,7 +336,7 @@ static int timblogiw_g_std(struct file *file, void  *priv, v4l2_std_id *std)
 	return 0;
 }
 
-static int timblogiw_s_std(struct file *file, void  *priv, v4l2_std_id *std)
+static int timblogiw_s_std(struct file *file, void  *priv, v4l2_std_id std)
 {
 	struct video_device *vdev = video_devdata(file);
 	struct timblogiw *lw = video_get_drvdata(vdev);
@@ -348,10 +348,10 @@ static int timblogiw_s_std(struct file *file, void  *priv, v4l2_std_id *std)
 	mutex_lock(&lw->lock);
 
 	if (TIMBLOGIW_HAS_DECODER(lw))
-		err = v4l2_subdev_call(lw->sd_enc, core, s_std, *std);
+		err = v4l2_subdev_call(lw->sd_enc, core, s_std, std);
 
 	if (!err)
-		fh->cur_norm = timblogiw_get_norm(*std);
+		fh->cur_norm = timblogiw_get_norm(std);
 
 	mutex_unlock(&lw->lock);
 
diff --git a/drivers/media/platform/via-camera.c b/drivers/media/platform/via-camera.c
index b051c4a..a794cd6 100644
--- a/drivers/media/platform/via-camera.c
+++ b/drivers/media/platform/via-camera.c
@@ -847,7 +847,7 @@ static int viacam_s_input(struct file *filp, void *priv, unsigned int i)
 	return 0;
 }
 
-static int viacam_s_std(struct file *filp, void *priv, v4l2_std_id *std)
+static int viacam_s_std(struct file *filp, void *priv, v4l2_std_id std)
 {
 	return 0;
 }
diff --git a/drivers/media/platform/vino.c b/drivers/media/platform/vino.c
index eb5d6f9..c6af974 100644
--- a/drivers/media/platform/vino.c
+++ b/drivers/media/platform/vino.c
@@ -3042,7 +3042,7 @@ static int vino_g_std(struct file *file, void *__fh,
 }
 
 static int vino_s_std(struct file *file, void *__fh,
-			   v4l2_std_id *std)
+			   v4l2_std_id std)
 {
 	struct vino_channel_settings *vcs = video_drvdata(file);
 	unsigned long flags;
@@ -3056,7 +3056,7 @@ static int vino_s_std(struct file *file, void *__fh,
 	}
 
 	/* check if the standard is valid for the current input */
-	if ((*std) & vino_inputs[vcs->input].std) {
+	if (std & vino_inputs[vcs->input].std) {
 		dprintk("standard accepted\n");
 
 		/* change the video norm for SAA7191
@@ -3065,13 +3065,13 @@ static int vino_s_std(struct file *file, void *__fh,
 		if (vcs->input == VINO_INPUT_D1)
 			goto out;
 
-		if ((*std) & V4L2_STD_PAL) {
+		if (std & V4L2_STD_PAL) {
 			ret = vino_set_data_norm(vcs, VINO_DATA_NORM_PAL,
 						 &flags);
-		} else if ((*std) & V4L2_STD_NTSC) {
+		} else if (std & V4L2_STD_NTSC) {
 			ret = vino_set_data_norm(vcs, VINO_DATA_NORM_NTSC,
 						 &flags);
-		} else if ((*std) & V4L2_STD_SECAM) {
+		} else if (std & V4L2_STD_SECAM) {
 			ret = vino_set_data_norm(vcs, VINO_DATA_NORM_SECAM,
 						 &flags);
 		} else {
diff --git a/drivers/media/platform/vivi.c b/drivers/media/platform/vivi.c
index 8a33a71..85bc314 100644
--- a/drivers/media/platform/vivi.c
+++ b/drivers/media/platform/vivi.c
@@ -1093,6 +1093,15 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
 		return 0;
 
 	dev->input = i;
+	/*
+	 * Modify the brightness range depending on the input.
+	 * This makes it easy to use vivi to test if applications can
+	 * handle control range modifications and is also how this is
+	 * typically used in practice as different inputs may be hooked
+	 * up to different receivers with different control ranges.
+	 */
+	v4l2_ctrl_modify_range(dev->brightness,
+			128 * i, 255 + 128 * i, 1, 127 + 128 * i);
 	precalculate_bars(dev);
 	precalculate_line(dev);
 	return 0;
@@ -1429,6 +1438,7 @@ static int __init vivi_create_instance(int inst)
 	q->buf_struct_size = sizeof(struct vivi_buffer);
 	q->ops = &vivi_video_qops;
 	q->mem_ops = &vb2_vmalloc_memops;
+	q->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
 
 	ret = vb2_queue_init(q);
 	if (ret)
diff --git a/drivers/media/radio/dsbr100.c b/drivers/media/radio/dsbr100.c
index 63b112b..142c2ee 100644
--- a/drivers/media/radio/dsbr100.c
+++ b/drivers/media/radio/dsbr100.c
@@ -208,13 +208,13 @@ static int vidioc_g_tuner(struct file *file, void *priv,
 }
 
 static int vidioc_s_tuner(struct file *file, void *priv,
-				struct v4l2_tuner *v)
+				const struct v4l2_tuner *v)
 {
 	return v->index ? -EINVAL : 0;
 }
 
 static int vidioc_s_frequency(struct file *file, void *priv,
-				struct v4l2_frequency *f)
+				const struct v4l2_frequency *f)
 {
 	struct dsbr100_device *radio = video_drvdata(file);
 
diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c
index 643d80a..545c04c 100644
--- a/drivers/media/radio/radio-cadet.c
+++ b/drivers/media/radio/radio-cadet.c
@@ -90,6 +90,26 @@ static u16 sigtable[2][4] = {
 	{ 2185, 4369, 13107, 65535 },
 };
 
+static const struct v4l2_frequency_band bands[] = {
+	{
+		.index = 0,
+		.type = V4L2_TUNER_RADIO,
+		.capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_FREQ_BANDS,
+		.rangelow = 8320,      /* 520 kHz */
+		.rangehigh = 26400,    /* 1650 kHz */
+		.modulation = V4L2_BAND_MODULATION_AM,
+	}, {
+		.index = 1,
+		.type = V4L2_TUNER_RADIO,
+		.capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_RDS |
+			V4L2_TUNER_CAP_RDS_BLOCK_IO | V4L2_TUNER_CAP_LOW |
+			V4L2_TUNER_CAP_FREQ_BANDS,
+		.rangelow = 1400000,   /* 87.5 MHz */
+		.rangehigh = 1728000,  /* 108.0 MHz */
+		.modulation = V4L2_BAND_MODULATION_FM,
+	},
+};
+
 
 static int cadet_getstereo(struct cadet *dev)
 {
@@ -196,6 +216,8 @@ static void cadet_setfreq(struct cadet *dev, unsigned freq)
 	int i, j, test;
 	int curvol;
 
+	freq = clamp(freq, bands[dev->is_fm_band].rangelow,
+			   bands[dev->is_fm_band].rangehigh);
 	dev->curfreq = freq;
 	/*
 	 * Formulate a fifo command
@@ -337,26 +359,6 @@ static int vidioc_querycap(struct file *file, void *priv,
 	return 0;
 }
 
-static const struct v4l2_frequency_band bands[] = {
-	{
-		.index = 0,
-		.type = V4L2_TUNER_RADIO,
-		.capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_FREQ_BANDS,
-		.rangelow = 8320,      /* 520 kHz */
-		.rangehigh = 26400,    /* 1650 kHz */
-		.modulation = V4L2_BAND_MODULATION_AM,
-	}, {
-		.index = 1,
-		.type = V4L2_TUNER_RADIO,
-		.capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_RDS |
-			V4L2_TUNER_CAP_RDS_BLOCK_IO | V4L2_TUNER_CAP_LOW |
-			V4L2_TUNER_CAP_FREQ_BANDS,
-		.rangelow = 1400000,   /* 87.5 MHz */
-		.rangehigh = 1728000,  /* 108.0 MHz */
-		.modulation = V4L2_BAND_MODULATION_FM,
-	},
-};
-
 static int vidioc_g_tuner(struct file *file, void *priv,
 				struct v4l2_tuner *v)
 {
@@ -388,7 +390,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
 }
 
 static int vidioc_s_tuner(struct file *file, void *priv,
-				struct v4l2_tuner *v)
+				const struct v4l2_tuner *v)
 {
 	return v->index ? -EINVAL : 0;
 }
@@ -418,7 +420,7 @@ static int vidioc_g_frequency(struct file *file, void *priv,
 
 
 static int vidioc_s_frequency(struct file *file, void *priv,
-				struct v4l2_frequency *f)
+				const struct v4l2_frequency *f)
 {
 	struct cadet *dev = video_drvdata(file);
 
@@ -426,8 +428,6 @@ static int vidioc_s_frequency(struct file *file, void *priv,
 		return -EINVAL;
 	dev->is_fm_band =
 		f->frequency >= (bands[0].rangehigh + bands[1].rangelow) / 2;
-	clamp(f->frequency, bands[dev->is_fm_band].rangelow,
-			    bands[dev->is_fm_band].rangehigh);
 	cadet_setfreq(dev, f->frequency);
 	return 0;
 }
diff --git a/drivers/media/radio/radio-isa.c b/drivers/media/radio/radio-isa.c
index 84b7b9f..6ff3508 100644
--- a/drivers/media/radio/radio-isa.c
+++ b/drivers/media/radio/radio-isa.c
@@ -51,8 +51,8 @@ static int radio_isa_querycap(struct file *file, void  *priv,
 	strlcpy(v->card, isa->drv->card, sizeof(v->card));
 	snprintf(v->bus_info, sizeof(v->bus_info), "ISA:%s", isa->v4l2_dev.name);
 
-	v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
-	v->device_caps = v->capabilities | V4L2_CAP_DEVICE_CAPS;
+	v->device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
+	v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS;
 	return 0;
 }
 
@@ -87,7 +87,7 @@ static int radio_isa_g_tuner(struct file *file, void *priv,
 }
 
 static int radio_isa_s_tuner(struct file *file, void *priv,
-				struct v4l2_tuner *v)
+				const struct v4l2_tuner *v)
 {
 	struct radio_isa_card *isa = video_drvdata(file);
 	const struct radio_isa_ops *ops = isa->drv->ops;
@@ -102,17 +102,18 @@ static int radio_isa_s_tuner(struct file *file, void *priv,
 }
 
 static int radio_isa_s_frequency(struct file *file, void *priv,
-				struct v4l2_frequency *f)
+				const struct v4l2_frequency *f)
 {
 	struct radio_isa_card *isa = video_drvdata(file);
+	u32 freq = f->frequency;
 	int res;
 
 	if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
 		return -EINVAL;
-	f->frequency = clamp(f->frequency, FREQ_LOW, FREQ_HIGH);
-	res = isa->drv->ops->s_frequency(isa, f->frequency);
+	freq = clamp(freq, FREQ_LOW, FREQ_HIGH);
+	res = isa->drv->ops->s_frequency(isa, freq);
 	if (res == 0)
-		isa->freq = f->frequency;
+		isa->freq = freq;
 	return res;
 }
 
diff --git a/drivers/media/radio/radio-keene.c b/drivers/media/radio/radio-keene.c
index 296941a..4c9ae76 100644
--- a/drivers/media/radio/radio-keene.c
+++ b/drivers/media/radio/radio-keene.c
@@ -215,15 +215,15 @@ static int vidioc_s_modulator(struct file *file, void *priv,
 }
 
 static int vidioc_s_frequency(struct file *file, void *priv,
-				struct v4l2_frequency *f)
+				const struct v4l2_frequency *f)
 {
 	struct keene_device *radio = video_drvdata(file);
+	unsigned freq = f->frequency;
 
 	if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
 		return -EINVAL;
-	f->frequency = clamp(f->frequency,
-			FREQ_MIN * FREQ_MUL, FREQ_MAX * FREQ_MUL);
-	return keene_cmd_main(radio, f->frequency, true);
+	freq = clamp(freq, FREQ_MIN * FREQ_MUL, FREQ_MAX * FREQ_MUL);
+	return keene_cmd_main(radio, freq, true);
 }
 
 static int vidioc_g_frequency(struct file *file, void *priv,
diff --git a/drivers/media/radio/radio-ma901.c b/drivers/media/radio/radio-ma901.c
index c61f590..a85b064 100644
--- a/drivers/media/radio/radio-ma901.c
+++ b/drivers/media/radio/radio-ma901.c
@@ -239,7 +239,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
 
 /* vidioc_s_tuner - set tuner attributes */
 static int vidioc_s_tuner(struct file *file, void *priv,
-				struct v4l2_tuner *v)
+				const struct v4l2_tuner *v)
 {
 	struct ma901radio_device *radio = video_drvdata(file);
 
@@ -257,7 +257,7 @@ static int vidioc_s_tuner(struct file *file, void *priv,
 
 /* vidioc_s_frequency - set tuner radio frequency */
 static int vidioc_s_frequency(struct file *file, void *priv,
-				struct v4l2_frequency *f)
+				const struct v4l2_frequency *f)
 {
 	struct ma901radio_device *radio = video_drvdata(file);
 
@@ -347,9 +347,20 @@ static void usb_ma901radio_release(struct v4l2_device *v4l2_dev)
 static int usb_ma901radio_probe(struct usb_interface *intf,
 				const struct usb_device_id *id)
 {
+	struct usb_device *dev = interface_to_usbdev(intf);
 	struct ma901radio_device *radio;
 	int retval = 0;
 
+	/* Masterkit MA901 usb radio has the same USB ID as many others
+	 * Atmel V-USB devices. Let's make additional checks to be sure
+	 * that this is our device.
+	 */
+
+	if (dev->product && dev->manufacturer &&
+		(strncmp(dev->product, "MA901", 5) != 0
+		|| strncmp(dev->manufacturer, "www.masterkit.ru", 16) != 0))
+		return -ENODEV;
+
 	radio = kzalloc(sizeof(struct ma901radio_device), GFP_KERNEL);
 	if (!radio) {
 		dev_err(&intf->dev, "kzalloc for ma901radio_device failed\n");
diff --git a/drivers/media/radio/radio-miropcm20.c b/drivers/media/radio/radio-miropcm20.c
index 3d0ff44..a7e93d7 100644
--- a/drivers/media/radio/radio-miropcm20.c
+++ b/drivers/media/radio/radio-miropcm20.c
@@ -103,16 +103,18 @@ static int vidioc_g_tuner(struct file *file, void *priv,
 }
 
 static int vidioc_s_tuner(struct file *file, void *priv,
-				struct v4l2_tuner *v)
+				const struct v4l2_tuner *v)
 {
 	struct pcm20 *dev = video_drvdata(file);
 
 	if (v->index)
 		return -EINVAL;
 	if (v->audmode > V4L2_TUNER_MODE_STEREO)
-		v->audmode = V4L2_TUNER_MODE_STEREO;
+		dev->audmode = V4L2_TUNER_MODE_STEREO;
+	else
+		dev->audmode = v->audmode;
 	snd_aci_cmd(dev->aci, ACI_SET_TUNERMONO,
-			v->audmode == V4L2_TUNER_MODE_MONO, -1);
+			dev->audmode == V4L2_TUNER_MODE_MONO, -1);
 	return 0;
 }
 
@@ -131,14 +133,14 @@ static int vidioc_g_frequency(struct file *file, void *priv,
 
 
 static int vidioc_s_frequency(struct file *file, void *priv,
-				struct v4l2_frequency *f)
+				const struct v4l2_frequency *f)
 {
 	struct pcm20 *dev = video_drvdata(file);
 
 	if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
 		return -EINVAL;
 
-	dev->freq = clamp(f->frequency, 87 * 16000U, 108 * 16000U);
+	dev->freq = clamp_t(u32, f->frequency, 87 * 16000U, 108 * 16000U);
 	pcm20_setfreq(dev, dev->freq);
 	return 0;
 }
diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c
index 9c5a267..a360227 100644
--- a/drivers/media/radio/radio-mr800.c
+++ b/drivers/media/radio/radio-mr800.c
@@ -203,10 +203,14 @@ static int amradio_set_mute(struct amradio_device *radio, bool mute)
 /* set a frequency, freq is defined by v4l's TUNER_LOW, i.e. 1/16th kHz */
 static int amradio_set_freq(struct amradio_device *radio, int freq)
 {
-	unsigned short freq_send = 0x10 + (freq >> 3) / 25;
+	unsigned short freq_send;
 	u8 buf[3];
 	int retval;
 
+	/* we need to be sure that frequency isn't out of range */
+	freq = clamp_t(unsigned, freq, FREQ_MIN * FREQ_MUL, FREQ_MAX * FREQ_MUL);
+	freq_send = 0x10 + (freq >> 3) / 25;
+
 	/* frequency is calculated from freq_send and placed in first 2 bytes */
 	buf[0] = (freq_send >> 8) & 0xff;
 	buf[1] = freq_send & 0xff;
@@ -305,7 +309,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
 
 /* vidioc_s_tuner - set tuner attributes */
 static int vidioc_s_tuner(struct file *file, void *priv,
-				struct v4l2_tuner *v)
+				const struct v4l2_tuner *v)
 {
 	struct amradio_device *radio = video_drvdata(file);
 
@@ -323,14 +327,13 @@ static int vidioc_s_tuner(struct file *file, void *priv,
 
 /* vidioc_s_frequency - set tuner radio frequency */
 static int vidioc_s_frequency(struct file *file, void *priv,
-				struct v4l2_frequency *f)
+				const struct v4l2_frequency *f)
 {
 	struct amradio_device *radio = video_drvdata(file);
 
 	if (f->tuner != 0)
 		return -EINVAL;
-	return amradio_set_freq(radio, clamp_t(unsigned, f->frequency,
-				FREQ_MIN * FREQ_MUL, FREQ_MAX * FREQ_MUL));
+	return amradio_set_freq(radio, f->frequency);
 }
 
 /* vidioc_g_frequency - get tuner radio frequency */
@@ -389,6 +392,7 @@ static int vidioc_s_hw_freq_seek(struct file *file, void *priv,
 			continue;
 		amradio_send_cmd(radio, AMRADIO_GET_FREQ, 0, NULL, 0, true);
 		if (radio->buffer[1] || radio->buffer[2]) {
+			/* To check: sometimes radio->curfreq is set to out of range value */
 			radio->curfreq = (radio->buffer[1] << 8) | radio->buffer[2];
 			radio->curfreq = (radio->curfreq - 0x10) * 200;
 			amradio_send_cmd(radio, AMRADIO_STOP_SEARCH,
diff --git a/drivers/media/radio/radio-rtrack2.c b/drivers/media/radio/radio-rtrack2.c
index b1f844c..09cfbc3 100644
--- a/drivers/media/radio/radio-rtrack2.c
+++ b/drivers/media/radio/radio-rtrack2.c
@@ -8,6 +8,8 @@
  *
  * Converted to the radio-isa framework by Hans Verkuil <hans.verkuil@cisco.com>
  * Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org>
+ *
+ * Fully tested with actual hardware and the v4l2-compliance tool.
  */
 
 #include <linux/module.h>	/* Modules 			*/
@@ -81,8 +83,7 @@ static int rtrack2_s_frequency(struct radio_isa_card *isa, u32 freq)
 			zero(isa);
 
 	outb_p(0xc8, isa->io);
-	if (!v4l2_ctrl_g_ctrl(isa->mute))
-		outb_p(0, isa->io);
+	outb_p(v4l2_ctrl_g_ctrl(isa->mute), isa->io);
 	return 0;
 }
 
diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c
index 637a555..adfcc61 100644
--- a/drivers/media/radio/radio-sf16fmi.c
+++ b/drivers/media/radio/radio-sf16fmi.c
@@ -145,13 +145,13 @@ static int vidioc_g_tuner(struct file *file, void *priv,
 }
 
 static int vidioc_s_tuner(struct file *file, void *priv,
-					struct v4l2_tuner *v)
+					const struct v4l2_tuner *v)
 {
 	return v->index ? -EINVAL : 0;
 }
 
 static int vidioc_s_frequency(struct file *file, void *priv,
-					struct v4l2_frequency *f)
+					const struct v4l2_frequency *f)
 {
 	struct fmi *fmi = video_drvdata(file);
 
diff --git a/drivers/media/radio/radio-shark.c b/drivers/media/radio/radio-shark.c
index 8c309c7..8fa18ab 100644
--- a/drivers/media/radio/radio-shark.c
+++ b/drivers/media/radio/radio-shark.c
@@ -284,7 +284,7 @@ static void shark_resume_leds(struct shark_device *shark)
 static int shark_register_leds(struct shark_device *shark, struct device *dev)
 {
 	v4l2_warn(&shark->v4l2_dev,
-		  "CONFIG_LED_CLASS not enabled, LED support disabled\n");
+		  "CONFIG_LEDS_CLASS not enabled, LED support disabled\n");
 	return 0;
 }
 static inline void shark_unregister_leds(struct shark_device *shark) { }
diff --git a/drivers/media/radio/radio-shark2.c b/drivers/media/radio/radio-shark2.c
index ef65ebb..9fb6697 100644
--- a/drivers/media/radio/radio-shark2.c
+++ b/drivers/media/radio/radio-shark2.c
@@ -250,7 +250,7 @@ static void shark_resume_leds(struct shark_device *shark)
 static int shark_register_leds(struct shark_device *shark, struct device *dev)
 {
 	v4l2_warn(&shark->v4l2_dev,
-		  "CONFIG_LED_CLASS not enabled, LED support disabled\n");
+		  "CONFIG_LEDS_CLASS not enabled, LED support disabled\n");
 	return 0;
 }
 static inline void shark_unregister_leds(struct shark_device *shark) { }
diff --git a/drivers/media/radio/radio-si4713.c b/drivers/media/radio/radio-si4713.c
index 1507c9d..38b3f15 100644
--- a/drivers/media/radio/radio-si4713.c
+++ b/drivers/media/radio/radio-si4713.c
@@ -39,10 +39,11 @@ module_param(radio_nr, int, 0);
 MODULE_PARM_DESC(radio_nr,
 		 "Minor number for radio device (-1 ==> auto assign)");
 
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Eduardo Valentin <eduardo.valentin@nokia.com>");
 MODULE_DESCRIPTION("Platform driver for Si4713 FM Radio Transmitter");
 MODULE_VERSION("0.0.1");
+MODULE_ALIAS("platform:radio-si4713");
 
 /* Driver state struct */
 struct radio_si4713_device {
@@ -94,7 +95,7 @@ static int radio_si4713_querycap(struct file *file, void *priv,
 {
 	strlcpy(capability->driver, "radio-si4713", sizeof(capability->driver));
 	strlcpy(capability->card, "Silicon Labs Si4713 Modulator",
-				sizeof(capability->card));
+		sizeof(capability->card));
 	capability->capabilities = V4L2_CAP_MODULATOR | V4L2_CAP_RDS_OUTPUT;
 
 	return 0;
@@ -102,7 +103,7 @@ static int radio_si4713_querycap(struct file *file, void *priv,
 
 /* radio_si4713_queryctrl - enumerate control items */
 static int radio_si4713_queryctrl(struct file *file, void *priv,
-						struct v4l2_queryctrl *qc)
+				  struct v4l2_queryctrl *qc)
 {
 	/* Must be sorted from low to high control ID! */
 	static const u32 user_ctrls[] = {
@@ -152,7 +153,7 @@ static int radio_si4713_queryctrl(struct file *file, void *priv,
 		return v4l2_ctrl_query_fill(qc, 0, 0, 0, 0);
 
 	return v4l2_device_call_until_err(&rsdev->v4l2_dev, 0, core,
-						queryctrl, qc);
+					  queryctrl, qc);
 }
 
 /*
@@ -165,66 +166,66 @@ static inline struct v4l2_device *get_v4l2_dev(struct file *file)
 }
 
 static int radio_si4713_g_ext_ctrls(struct file *file, void *p,
-						struct v4l2_ext_controls *vecs)
+				    struct v4l2_ext_controls *vecs)
 {
 	return v4l2_device_call_until_err(get_v4l2_dev(file), 0, core,
-							g_ext_ctrls, vecs);
+					  g_ext_ctrls, vecs);
 }
 
 static int radio_si4713_s_ext_ctrls(struct file *file, void *p,
-						struct v4l2_ext_controls *vecs)
+				    struct v4l2_ext_controls *vecs)
 {
 	return v4l2_device_call_until_err(get_v4l2_dev(file), 0, core,
-							s_ext_ctrls, vecs);
+					  s_ext_ctrls, vecs);
 }
 
 static int radio_si4713_g_ctrl(struct file *file, void *p,
-						struct v4l2_control *vc)
+			       struct v4l2_control *vc)
 {
 	return v4l2_device_call_until_err(get_v4l2_dev(file), 0, core,
-							g_ctrl, vc);
+					  g_ctrl, vc);
 }
 
 static int radio_si4713_s_ctrl(struct file *file, void *p,
-						struct v4l2_control *vc)
+			       struct v4l2_control *vc)
 {
 	return v4l2_device_call_until_err(get_v4l2_dev(file), 0, core,
-							s_ctrl, vc);
+					  s_ctrl, vc);
 }
 
 static int radio_si4713_g_modulator(struct file *file, void *p,
-						struct v4l2_modulator *vm)
+				    struct v4l2_modulator *vm)
 {
 	return v4l2_device_call_until_err(get_v4l2_dev(file), 0, tuner,
-							g_modulator, vm);
+					  g_modulator, vm);
 }
 
 static int radio_si4713_s_modulator(struct file *file, void *p,
-						const struct v4l2_modulator *vm)
+				    const struct v4l2_modulator *vm)
 {
 	return v4l2_device_call_until_err(get_v4l2_dev(file), 0, tuner,
-							s_modulator, vm);
+					  s_modulator, vm);
 }
 
 static int radio_si4713_g_frequency(struct file *file, void *p,
-						struct v4l2_frequency *vf)
+				    struct v4l2_frequency *vf)
 {
 	return v4l2_device_call_until_err(get_v4l2_dev(file), 0, tuner,
-							g_frequency, vf);
+					  g_frequency, vf);
 }
 
 static int radio_si4713_s_frequency(struct file *file, void *p,
-						struct v4l2_frequency *vf)
+				    const struct v4l2_frequency *vf)
 {
 	return v4l2_device_call_until_err(get_v4l2_dev(file), 0, tuner,
-							s_frequency, vf);
+					  s_frequency, vf);
 }
 
 static long radio_si4713_default(struct file *file, void *p,
-				bool valid_prio, int cmd, void *arg)
+				 bool valid_prio, unsigned int cmd, void *arg)
 {
 	return v4l2_device_call_until_err(get_v4l2_dev(file), 0, core,
-							ioctl, cmd, arg);
+					  ioctl, cmd, arg);
 }
 
 static struct v4l2_ioctl_ops radio_si4713_ioctl_ops = {
@@ -285,13 +286,13 @@ static int radio_si4713_pdriver_probe(struct platform_device *pdev)
 	adapter = i2c_get_adapter(pdata->i2c_bus);
 	if (!adapter) {
 		dev_err(&pdev->dev, "Cannot get i2c adapter %d\n",
-							pdata->i2c_bus);
+			pdata->i2c_bus);
 		rval = -ENODEV;
 		goto unregister_v4l2_dev;
 	}
 
 	sd = v4l2_i2c_new_subdev_board(&rsdev->v4l2_dev, adapter,
-					pdata->subdev_board_info, NULL);
+				       pdata->subdev_board_info, NULL);
 	if (!sd) {
 		dev_err(&pdev->dev, "Cannot get v4l2 subdevice\n");
 		rval = -ENODEV;
@@ -306,7 +307,7 @@ static int radio_si4713_pdriver_probe(struct platform_device *pdev)
 	}
 
 	memcpy(rsdev->radio_dev, &radio_si4713_vdev_template,
-			sizeof(radio_si4713_vdev_template));
+	       sizeof(radio_si4713_vdev_template));
 	video_set_drvdata(rsdev->radio_dev, rsdev);
 	if (video_register_device(rsdev->radio_dev, VFL_TYPE_RADIO, radio_nr)) {
 		dev_err(&pdev->dev, "Could not register video device.\n");
@@ -328,16 +329,15 @@ exit:
 }
 
 /* radio_si4713_pdriver_remove - remove the device */
-static int __exit radio_si4713_pdriver_remove(struct platform_device *pdev)
+static int radio_si4713_pdriver_remove(struct platform_device *pdev)
 {
 	struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev);
-	struct radio_si4713_device *rsdev = container_of(v4l2_dev,
-						struct radio_si4713_device,
-						v4l2_dev);
 	struct v4l2_subdev *sd = list_entry(v4l2_dev->subdevs.next,
 					    struct v4l2_subdev, list);
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct radio_si4713_device *rsdev;
 
+	rsdev = container_of(v4l2_dev, struct radio_si4713_device, v4l2_dev);
 	video_unregister_device(rsdev->radio_dev);
 	i2c_put_adapter(client->adapter);
 	v4l2_device_unregister(&rsdev->v4l2_dev);
@@ -348,9 +348,10 @@ static int __exit radio_si4713_pdriver_remove(struct platform_device *pdev)
 static struct platform_driver radio_si4713_pdriver = {
 	.driver		= {
 		.name	= "radio-si4713",
+		.owner	= THIS_MODULE,
 	},
 	.probe		= radio_si4713_pdriver_probe,
-	.remove         = __exit_p(radio_si4713_pdriver_remove),
+	.remove         = radio_si4713_pdriver_remove,
 };
 
 module_platform_driver(radio_si4713_pdriver);
diff --git a/drivers/media/radio/radio-tea5764.c b/drivers/media/radio/radio-tea5764.c
index 1978516..38d563d 100644
--- a/drivers/media/radio/radio-tea5764.c
+++ b/drivers/media/radio/radio-tea5764.c
@@ -339,7 +339,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
 }
 
 static int vidioc_s_tuner(struct file *file, void *priv,
-				struct v4l2_tuner *v)
+				const struct v4l2_tuner *v)
 {
 	struct tea5764_device *radio = video_drvdata(file);
 
@@ -351,7 +351,7 @@ static int vidioc_s_tuner(struct file *file, void *priv,
 }
 
 static int vidioc_s_frequency(struct file *file, void *priv,
-				struct v4l2_frequency *f)
+				const struct v4l2_frequency *f)
 {
 	struct tea5764_device *radio = video_drvdata(file);
 
diff --git a/drivers/media/radio/radio-tea5777.c b/drivers/media/radio/radio-tea5777.c
index 4b5190d..e245597 100644
--- a/drivers/media/radio/radio-tea5777.c
+++ b/drivers/media/radio/radio-tea5777.c
@@ -336,7 +336,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
 }
 
 static int vidioc_s_tuner(struct file *file, void *priv,
-					struct v4l2_tuner *v)
+					const struct v4l2_tuner *v)
 {
 	struct radio_tea5777 *tea = video_drvdata(file);
 	u32 orig_audmode = tea->audmode;
@@ -344,10 +344,9 @@ static int vidioc_s_tuner(struct file *file, void *priv,
 	if (v->index)
 		return -EINVAL;
 
-	if (v->audmode > V4L2_TUNER_MODE_STEREO)
-		v->audmode = V4L2_TUNER_MODE_STEREO;
-
 	tea->audmode = v->audmode;
+	if (tea->audmode > V4L2_TUNER_MODE_STEREO)
+		tea->audmode = V4L2_TUNER_MODE_STEREO;
 
 	if (tea->audmode != orig_audmode && tea->band == BAND_FM)
 		return radio_tea5777_set_freq(tea);
@@ -368,7 +367,7 @@ static int vidioc_g_frequency(struct file *file, void *priv,
 }
 
 static int vidioc_s_frequency(struct file *file, void *priv,
-					struct v4l2_frequency *f)
+					const struct v4l2_frequency *f)
 {
 	struct radio_tea5777 *tea = video_drvdata(file);
 
diff --git a/drivers/media/radio/radio-timb.c b/drivers/media/radio/radio-timb.c
index b87effe..bb7b143 100644
--- a/drivers/media/radio/radio-timb.c
+++ b/drivers/media/radio/radio-timb.c
@@ -56,7 +56,7 @@ static int timbradio_vidioc_g_tuner(struct file *file, void *priv,
 }
 
 static int timbradio_vidioc_s_tuner(struct file *file, void *priv,
-	struct v4l2_tuner *v)
+	const struct v4l2_tuner *v)
 {
 	struct timbradio *tr = video_drvdata(file);
 	return v4l2_subdev_call(tr->sd_tuner, tuner, s_tuner, v);
@@ -91,7 +91,7 @@ static int timbradio_vidioc_s_audio(struct file *file, void *priv,
 }
 
 static int timbradio_vidioc_s_frequency(struct file *file, void *priv,
-	struct v4l2_frequency *f)
+	const struct v4l2_frequency *f)
 {
 	struct timbradio *tr = video_drvdata(file);
 	return v4l2_subdev_call(tr->sd_tuner, tuner, s_frequency, f);
diff --git a/drivers/media/radio/radio-wl1273.c b/drivers/media/radio/radio-wl1273.c
index 02151e0..97c2c18 100644
--- a/drivers/media/radio/radio-wl1273.c
+++ b/drivers/media/radio/radio-wl1273.c
@@ -1559,7 +1559,7 @@ out:
 }
 
 static int wl1273_fm_vidioc_s_tuner(struct file *file, void *priv,
-				    struct v4l2_tuner *tuner)
+				    const struct v4l2_tuner *tuner)
 {
 	struct wl1273_device *radio = video_get_drvdata(video_devdata(file));
 	struct wl1273_core *core = radio->core;
@@ -1640,7 +1640,7 @@ static int wl1273_fm_vidioc_g_frequency(struct file *file, void *priv,
 }
 
 static int wl1273_fm_vidioc_s_frequency(struct file *file, void *priv,
-					struct v4l2_frequency *freq)
+					const struct v4l2_frequency *freq)
 {
 	struct wl1273_device *radio = video_get_drvdata(video_devdata(file));
 	struct wl1273_core *core = radio->core;
diff --git a/drivers/media/radio/si470x/radio-si470x-common.c b/drivers/media/radio/si470x/radio-si470x-common.c
index 1898938..5c57e5b 100644
--- a/drivers/media/radio/si470x/radio-si470x-common.c
+++ b/drivers/media/radio/si470x/radio-si470x-common.c
@@ -636,7 +636,7 @@ static int si470x_vidioc_g_tuner(struct file *file, void *priv,
  * si470x_vidioc_s_tuner - set tuner attributes
  */
 static int si470x_vidioc_s_tuner(struct file *file, void *priv,
-		struct v4l2_tuner *tuner)
+		const struct v4l2_tuner *tuner)
 {
 	struct si470x_device *radio = video_drvdata(file);
 
@@ -678,7 +678,7 @@ static int si470x_vidioc_g_frequency(struct file *file, void *priv,
  * si470x_vidioc_s_frequency - set tuner or modulator radio frequency
  */
 static int si470x_vidioc_s_frequency(struct file *file, void *priv,
-		struct v4l2_frequency *freq)
+		const struct v4l2_frequency *freq)
 {
 	struct si470x_device *radio = video_drvdata(file);
 	int retval;
diff --git a/drivers/media/radio/si4713-i2c.c b/drivers/media/radio/si4713-i2c.c
index bd61b3b..e305c14 100644
--- a/drivers/media/radio/si4713-i2c.c
+++ b/drivers/media/radio/si4713-i2c.c
@@ -1212,7 +1212,7 @@ exit:
 	return rval;
 }
 
-static int si4713_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f);
+static int si4713_s_frequency(struct v4l2_subdev *sd, const struct v4l2_frequency *f);
 static int si4713_s_modulator(struct v4l2_subdev *sd, const struct v4l2_modulator *);
 /*
  * si4713_setup - Sets the device up with current configuration.
@@ -1950,7 +1950,7 @@ unlock:
 }
 
 /* si4713_s_frequency - set tuner or modulator radio frequency */
-static int si4713_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f)
+static int si4713_s_frequency(struct v4l2_subdev *sd, const struct v4l2_frequency *f)
 {
 	struct si4713_device *sdev = to_si4713_device(sd);
 	int rval = 0;
@@ -1970,7 +1970,6 @@ static int si4713_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f)
 		rval = 0;
 	}
 	sdev->frequency = frequency;
-	f->frequency = si4713_to_v4l2(frequency);
 
 unlock:
 	mutex_unlock(&sdev->mutex);
diff --git a/drivers/media/radio/tef6862.c b/drivers/media/radio/tef6862.c
index b18c2dc..82c6c94 100644
--- a/drivers/media/radio/tef6862.c
+++ b/drivers/media/radio/tef6862.c
@@ -96,12 +96,12 @@ static int tef6862_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *v)
 	return 0;
 }
 
-static int tef6862_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *v)
+static int tef6862_s_tuner(struct v4l2_subdev *sd, const struct v4l2_tuner *v)
 {
 	return v->index ? -EINVAL : 0;
 }
 
-static int tef6862_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f)
+static int tef6862_s_frequency(struct v4l2_subdev *sd, const struct v4l2_frequency *f)
 {
 	struct tef6862_state *state = to_state(sd);
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
diff --git a/drivers/media/radio/wl128x/fmdrv_v4l2.c b/drivers/media/radio/wl128x/fmdrv_v4l2.c
index 0a8ee8f..5dec323 100644
--- a/drivers/media/radio/wl128x/fmdrv_v4l2.c
+++ b/drivers/media/radio/wl128x/fmdrv_v4l2.c
@@ -331,7 +331,7 @@ static int fm_v4l2_vidioc_g_tuner(struct file *file, void *priv,
  * Should we set other tuner attributes, too?
  */
 static int fm_v4l2_vidioc_s_tuner(struct file *file, void *priv,
-		struct v4l2_tuner *tuner)
+		const struct v4l2_tuner *tuner)
 {
 	struct fmdev *fmdev = video_drvdata(file);
 	u16 aud_mode;
@@ -388,7 +388,7 @@ static int fm_v4l2_vidioc_g_freq(struct file *file, void *priv,
 
 /* Set tuner or modulator radio frequency */
 static int fm_v4l2_vidioc_s_freq(struct file *file, void *priv,
-		struct v4l2_frequency *freq)
+		const struct v4l2_frequency *freq)
 {
 	struct fmdev *fmdev = video_drvdata(file);
 
@@ -396,9 +396,7 @@ static int fm_v4l2_vidioc_s_freq(struct file *file, void *priv,
 	 * As V4L2_TUNER_CAP_LOW is set 1 user sends the frequency
 	 * in units of 62.5 Hz.
 	 */
-	freq->frequency = (u32)(freq->frequency / 16);
-
-	return fmc_set_freq(fmdev, freq->frequency);
+	return fmc_set_freq(fmdev, freq->frequency / 16);
 }
 
 /* Set hardware frequency seek. If current mode is NOT RX, set it RX. */
diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c
index dec203b..b8f9f85 100644
--- a/drivers/media/rc/imon.c
+++ b/drivers/media/rc/imon.c
@@ -112,6 +112,7 @@ struct imon_context {
 	bool tx_control;
 	unsigned char usb_rx_buf[8];
 	unsigned char usb_tx_buf[8];
+	unsigned int send_packet_delay;
 
 	struct tx_t {
 		unsigned char data_buf[35];	/* user data buffer */
@@ -185,6 +186,10 @@ enum {
 	IMON_KEY_PANEL	= 2,
 };
 
+enum {
+	IMON_NEED_20MS_PKT_DELAY = 1
+};
+
 /*
  * USB Device ID for iMON USB Control Boards
  *
@@ -215,7 +220,7 @@ static struct usb_device_id imon_usb_id_table[] = {
 	/* SoundGraph iMON OEM Touch LCD (IR & 4.3" VGA LCD) */
 	{ USB_DEVICE(0x15c2, 0x0035) },
 	/* SoundGraph iMON OEM VFD (IR & VFD) */
-	{ USB_DEVICE(0x15c2, 0x0036) },
+	{ USB_DEVICE(0x15c2, 0x0036), .driver_info = IMON_NEED_20MS_PKT_DELAY },
 	/* device specifics unknown */
 	{ USB_DEVICE(0x15c2, 0x0037) },
 	/* SoundGraph iMON OEM LCD (IR & LCD) */
@@ -535,12 +540,12 @@ static int send_packet(struct imon_context *ictx)
 	kfree(control_req);
 
 	/*
-	 * Induce a mandatory 5ms delay before returning, as otherwise,
+	 * Induce a mandatory delay before returning, as otherwise,
 	 * send_packet can get called so rapidly as to overwhelm the device,
 	 * particularly on faster systems and/or those with quirky usb.
 	 */
-	timeout = msecs_to_jiffies(5);
-	set_current_state(TASK_UNINTERRUPTIBLE);
+	timeout = msecs_to_jiffies(ictx->send_packet_delay);
+	set_current_state(TASK_INTERRUPTIBLE);
 	schedule_timeout(timeout);
 
 	return retval;
@@ -1568,11 +1573,6 @@ static void imon_incoming_packet(struct imon_context *ictx,
 	if (press_type < 0)
 		goto not_input_data;
 
-	spin_lock_irqsave(&ictx->kc_lock, flags);
-	if (ictx->kc == KEY_UNKNOWN)
-		goto unknown_key;
-	spin_unlock_irqrestore(&ictx->kc_lock, flags);
-
 	if (ktype != IMON_KEY_PANEL) {
 		if (press_type == 0)
 			rc_keyup(ictx->rdev);
@@ -1615,12 +1615,6 @@ static void imon_incoming_packet(struct imon_context *ictx,
 
 	return;
 
-unknown_key:
-	spin_unlock_irqrestore(&ictx->kc_lock, flags);
-	dev_info(dev, "%s: unknown keypress, code 0x%llx\n", __func__,
-		 (long long)scancode);
-	return;
-
 not_input_data:
 	if (len != 8) {
 		dev_warn(dev, "imon %s: invalid incoming packet "
@@ -2335,6 +2329,10 @@ static int imon_probe(struct usb_interface *interface,
 
 	}
 
+	/* default send_packet delay is 5ms but some devices need more */
+	ictx->send_packet_delay = id->driver_info & IMON_NEED_20MS_PKT_DELAY ?
+				  20 : 5;
+
 	usb_set_intfdata(interface, ictx);
 
 	if (ifnum == 0) {
diff --git a/drivers/media/rc/ir-jvc-decoder.c b/drivers/media/rc/ir-jvc-decoder.c
index 69edffb..3948138 100644
--- a/drivers/media/rc/ir-jvc-decoder.c
+++ b/drivers/media/rc/ir-jvc-decoder.c
@@ -47,7 +47,7 @@ static int ir_jvc_decode(struct rc_dev *dev, struct ir_raw_event ev)
 {
 	struct jvc_dec *data = &dev->raw->jvc;
 
-	if (!(dev->raw->enabled_protocols & RC_BIT_JVC))
+	if (!(dev->enabled_protocols & RC_BIT_JVC))
 		return 0;
 
 	if (!is_timing_event(ev)) {
diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c
index 9945e5e..ff4d93d 100644
--- a/drivers/media/rc/ir-lirc-codec.c
+++ b/drivers/media/rc/ir-lirc-codec.c
@@ -35,7 +35,7 @@ static int ir_lirc_decode(struct rc_dev *dev, struct ir_raw_event ev)
 	struct lirc_codec *lirc = &dev->raw->lirc;
 	int sample;
 
-	if (!(dev->raw->enabled_protocols & RC_BIT_LIRC))
+	if (!(dev->enabled_protocols & RC_BIT_LIRC))
 		return 0;
 
 	if (!dev->raw->lirc.drv || !dev->raw->lirc.drv->rbuf)
diff --git a/drivers/media/rc/ir-mce_kbd-decoder.c b/drivers/media/rc/ir-mce_kbd-decoder.c
index 33fafa4..9f3c9b5 100644
--- a/drivers/media/rc/ir-mce_kbd-decoder.c
+++ b/drivers/media/rc/ir-mce_kbd-decoder.c
@@ -216,7 +216,7 @@ static int ir_mce_kbd_decode(struct rc_dev *dev, struct ir_raw_event ev)
 	u32 scancode;
 	unsigned long delay;
 
-	if (!(dev->raw->enabled_protocols & RC_BIT_MCE_KBD))
+	if (!(dev->enabled_protocols & RC_BIT_MCE_KBD))
 		return 0;
 
 	if (!is_timing_event(ev)) {
diff --git a/drivers/media/rc/ir-nec-decoder.c b/drivers/media/rc/ir-nec-decoder.c
index a47ee36..9a90094 100644
--- a/drivers/media/rc/ir-nec-decoder.c
+++ b/drivers/media/rc/ir-nec-decoder.c
@@ -52,7 +52,7 @@ static int ir_nec_decode(struct rc_dev *dev, struct ir_raw_event ev)
 	u8 address, not_address, command, not_command;
 	bool send_32bits = false;
 
-	if (!(dev->raw->enabled_protocols & RC_BIT_NEC))
+	if (!(dev->enabled_protocols & RC_BIT_NEC))
 		return 0;
 
 	if (!is_timing_event(ev)) {
diff --git a/drivers/media/rc/ir-raw.c b/drivers/media/rc/ir-raw.c
index 17c94be..5c42750 100644
--- a/drivers/media/rc/ir-raw.c
+++ b/drivers/media/rc/ir-raw.c
@@ -256,7 +256,7 @@ int ir_raw_event_register(struct rc_dev *dev)
 		return -ENOMEM;
 
 	dev->raw->dev = dev;
-	dev->raw->enabled_protocols = ~0;
+	dev->enabled_protocols = ~0;
 	rc = kfifo_alloc(&dev->raw->kfifo,
 			 sizeof(struct ir_raw_event) * MAX_IR_EVENT_SIZE,
 			 GFP_KERNEL);
diff --git a/drivers/media/rc/ir-rc5-decoder.c b/drivers/media/rc/ir-rc5-decoder.c
index 5b4d1dd..4e53a31 100644
--- a/drivers/media/rc/ir-rc5-decoder.c
+++ b/drivers/media/rc/ir-rc5-decoder.c
@@ -52,7 +52,7 @@ static int ir_rc5_decode(struct rc_dev *dev, struct ir_raw_event ev)
 	u8 toggle;
 	u32 scancode;
 
-	if (!(dev->raw->enabled_protocols & (RC_BIT_RC5 | RC_BIT_RC5X)))
+	if (!(dev->enabled_protocols & (RC_BIT_RC5 | RC_BIT_RC5X)))
 		return 0;
 
 	if (!is_timing_event(ev)) {
@@ -128,7 +128,7 @@ again:
 		if (data->wanted_bits == RC5X_NBITS) {
 			/* RC5X */
 			u8 xdata, command, system;
-			if (!(dev->raw->enabled_protocols & RC_BIT_RC5X)) {
+			if (!(dev->enabled_protocols & RC_BIT_RC5X)) {
 				data->state = STATE_INACTIVE;
 				return 0;
 			}
@@ -145,7 +145,7 @@ again:
 		} else {
 			/* RC5 */
 			u8 command, system;
-			if (!(dev->raw->enabled_protocols & RC_BIT_RC5)) {
+			if (!(dev->enabled_protocols & RC_BIT_RC5)) {
 				data->state = STATE_INACTIVE;
 				return 0;
 			}
diff --git a/drivers/media/rc/ir-rc5-sz-decoder.c b/drivers/media/rc/ir-rc5-sz-decoder.c
index fd807a8..865fe84 100644
--- a/drivers/media/rc/ir-rc5-sz-decoder.c
+++ b/drivers/media/rc/ir-rc5-sz-decoder.c
@@ -48,7 +48,7 @@ static int ir_rc5_sz_decode(struct rc_dev *dev, struct ir_raw_event ev)
 	u8 toggle, command, system;
 	u32 scancode;
 
-	if (!(dev->raw->enabled_protocols & RC_BIT_RC5_SZ))
+	if (!(dev->enabled_protocols & RC_BIT_RC5_SZ))
 		return 0;
 
 	if (!is_timing_event(ev)) {
diff --git a/drivers/media/rc/ir-rc6-decoder.c b/drivers/media/rc/ir-rc6-decoder.c
index e19072f..7cba7d3 100644
--- a/drivers/media/rc/ir-rc6-decoder.c
+++ b/drivers/media/rc/ir-rc6-decoder.c
@@ -89,7 +89,7 @@ static int ir_rc6_decode(struct rc_dev *dev, struct ir_raw_event ev)
 	u32 scancode;
 	u8 toggle;
 
-	if (!(dev->raw->enabled_protocols &
+	if (!(dev->enabled_protocols &
 	      (RC_BIT_RC6_0 | RC_BIT_RC6_6A_20 | RC_BIT_RC6_6A_24 |
 	       RC_BIT_RC6_6A_32 | RC_BIT_RC6_MCE)))
 		return 0;
diff --git a/drivers/media/rc/ir-rx51.c b/drivers/media/rc/ir-rx51.c
index 8ead492..31b955b 100644
--- a/drivers/media/rc/ir-rx51.c
+++ b/drivers/media/rc/ir-rx51.c
@@ -464,14 +464,14 @@ static int lirc_rx51_probe(struct platform_device *dev)
 	return 0;
 }
 
-static int __exit lirc_rx51_remove(struct platform_device *dev)
+static int lirc_rx51_remove(struct platform_device *dev)
 {
 	return lirc_unregister_driver(lirc_rx51_driver.minor);
 }
 
 struct platform_driver lirc_rx51_platform_driver = {
 	.probe		= lirc_rx51_probe,
-	.remove		= __exit_p(lirc_rx51_remove),
+	.remove		= lirc_rx51_remove,
 	.suspend	= lirc_rx51_suspend,
 	.resume		= lirc_rx51_resume,
 	.driver		= {
diff --git a/drivers/media/rc/ir-sanyo-decoder.c b/drivers/media/rc/ir-sanyo-decoder.c
index 7e69a3b..0a06205 100644
--- a/drivers/media/rc/ir-sanyo-decoder.c
+++ b/drivers/media/rc/ir-sanyo-decoder.c
@@ -58,7 +58,7 @@ static int ir_sanyo_decode(struct rc_dev *dev, struct ir_raw_event ev)
 	u32 scancode;
 	u8 address, command, not_command;
 
-	if (!(dev->raw->enabled_protocols & RC_BIT_SANYO))
+	if (!(dev->enabled_protocols & RC_BIT_SANYO))
 		return 0;
 
 	if (!is_timing_event(ev)) {
diff --git a/drivers/media/rc/ir-sony-decoder.c b/drivers/media/rc/ir-sony-decoder.c
index fb91434..29ab9c2 100644
--- a/drivers/media/rc/ir-sony-decoder.c
+++ b/drivers/media/rc/ir-sony-decoder.c
@@ -45,7 +45,7 @@ static int ir_sony_decode(struct rc_dev *dev, struct ir_raw_event ev)
 	u32 scancode;
 	u8 device, subdevice, function;
 
-	if (!(dev->raw->enabled_protocols &
+	if (!(dev->enabled_protocols &
 	      (RC_BIT_SONY12 | RC_BIT_SONY15 | RC_BIT_SONY20)))
 		return 0;
 
@@ -124,7 +124,7 @@ static int ir_sony_decode(struct rc_dev *dev, struct ir_raw_event ev)
 
 		switch (data->count) {
 		case 12:
-			if (!(dev->raw->enabled_protocols & RC_BIT_SONY12)) {
+			if (!(dev->enabled_protocols & RC_BIT_SONY12)) {
 				data->state = STATE_INACTIVE;
 				return 0;
 			}
@@ -133,7 +133,7 @@ static int ir_sony_decode(struct rc_dev *dev, struct ir_raw_event ev)
 			function  = bitrev8((data->bits >>  4) & 0xFE);
 			break;
 		case 15:
-			if (!(dev->raw->enabled_protocols & RC_BIT_SONY15)) {
+			if (!(dev->enabled_protocols & RC_BIT_SONY15)) {
 				data->state = STATE_INACTIVE;
 				return 0;
 			}
@@ -142,7 +142,7 @@ static int ir_sony_decode(struct rc_dev *dev, struct ir_raw_event ev)
 			function  = bitrev8((data->bits >>  7) & 0xFE);
 			break;
 		case 20:
-			if (!(dev->raw->enabled_protocols & RC_BIT_SONY20)) {
+			if (!(dev->enabled_protocols & RC_BIT_SONY20)) {
 				data->state = STATE_INACTIVE;
 				return 0;
 			}
diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h
index 5d87287..70a180b 100644
--- a/drivers/media/rc/rc-core-priv.h
+++ b/drivers/media/rc/rc-core-priv.h
@@ -39,7 +39,6 @@ struct ir_raw_event_ctrl {
 	ktime_t				last_event;	/* when last event occurred */
 	enum raw_event_type		last_type;	/* last event type */
 	struct rc_dev			*dev;		/* pointer to the parent rc_dev */
-	u64				enabled_protocols; /* enabled raw protocol decoders */
 
 	/* raw decoder state follows */
 	struct ir_raw_event prev_ev;
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index 759a40a..1cf382a 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -715,14 +715,14 @@ static void ir_close(struct input_dev *idev)
 }
 
 /* class for /sys/class/rc */
-static char *ir_devnode(struct device *dev, umode_t *mode)
+static char *rc_devnode(struct device *dev, umode_t *mode)
 {
 	return kasprintf(GFP_KERNEL, "rc/%s", dev_name(dev));
 }
 
-static struct class ir_input_class = {
+static struct class rc_class = {
 	.name		= "rc",
-	.devnode	= ir_devnode,
+	.devnode	= rc_devnode,
 };
 
 /*
@@ -783,13 +783,12 @@ static ssize_t show_protocols(struct device *device,
 
 	mutex_lock(&dev->lock);
 
-	if (dev->driver_type == RC_DRIVER_SCANCODE) {
-		enabled = dev->rc_map.rc_type;
+	enabled = dev->enabled_protocols;
+	if (dev->driver_type == RC_DRIVER_SCANCODE)
 		allowed = dev->allowed_protos;
-	} else if (dev->raw) {
-		enabled = dev->raw->enabled_protocols;
+	else if (dev->raw)
 		allowed = ir_raw_get_allowed_protocols();
-	} else {
+	else {
 		mutex_unlock(&dev->lock);
 		return -ENODEV;
 	}
@@ -847,7 +846,6 @@ static ssize_t store_protocols(struct device *device,
 	u64 type;
 	u64 mask;
 	int rc, i, count = 0;
-	unsigned long flags;
 	ssize_t ret;
 
 	/* Device is being removed */
@@ -856,15 +854,12 @@ static ssize_t store_protocols(struct device *device,
 
 	mutex_lock(&dev->lock);
 
-	if (dev->driver_type == RC_DRIVER_SCANCODE)
-		type = dev->rc_map.rc_type;
-	else if (dev->raw)
-		type = dev->raw->enabled_protocols;
-	else {
+	if (dev->driver_type != RC_DRIVER_SCANCODE && !dev->raw) {
 		IR_dprintk(1, "Protocol switching not supported\n");
 		ret = -EINVAL;
 		goto out;
 	}
+	type = dev->enabled_protocols;
 
 	while ((tmp = strsep((char **) &data, " \n")) != NULL) {
 		if (!*tmp)
@@ -922,14 +917,7 @@ static ssize_t store_protocols(struct device *device,
 		}
 	}
 
-	if (dev->driver_type == RC_DRIVER_SCANCODE) {
-		spin_lock_irqsave(&dev->rc_map.lock, flags);
-		dev->rc_map.rc_type = type;
-		spin_unlock_irqrestore(&dev->rc_map.lock, flags);
-	} else {
-		dev->raw->enabled_protocols = type;
-	}
-
+	dev->enabled_protocols = type;
 	IR_dprintk(1, "Current protocol(s): 0x%llx\n",
 		   (long long)type);
 
@@ -1016,7 +1004,7 @@ struct rc_dev *rc_allocate_device(void)
 	setup_timer(&dev->timer_keyup, ir_timer_keyup, (unsigned long)dev);
 
 	dev->dev.type = &rc_dev_type;
-	dev->dev.class = &ir_input_class;
+	dev->dev.class = &rc_class;
 	device_initialize(&dev->dev);
 
 	__module_get(THIS_MODULE);
@@ -1068,9 +1056,8 @@ int rc_register_device(struct rc_dev *dev)
 	/*
 	 * Take the lock here, as the device sysfs node will appear
 	 * when device_add() is called, which may trigger an ir-keytable udev
-	 * rule, which will in turn call show_protocols and access either
-	 * dev->rc_map.rc_type or dev->raw->enabled_protocols before it has
-	 * been initialized.
+	 * rule, which will in turn call show_protocols and access
+	 * dev->enabled_protocols before it has been initialized.
 	 */
 	mutex_lock(&dev->lock);
 
@@ -1132,6 +1119,7 @@ int rc_register_device(struct rc_dev *dev)
 		rc = dev->change_protocol(dev, &rc_type);
 		if (rc < 0)
 			goto out_raw;
+		dev->enabled_protocols = rc_type;
 	}
 
 	mutex_unlock(&dev->lock);
@@ -1190,7 +1178,7 @@ EXPORT_SYMBOL_GPL(rc_unregister_device);
 
 static int __init rc_core_init(void)
 {
-	int rc = class_register(&ir_input_class);
+	int rc = class_register(&rc_class);
 	if (rc) {
 		printk(KERN_ERR "rc_core: unable to register rc class\n");
 		return rc;
@@ -1203,11 +1191,11 @@ static int __init rc_core_init(void)
 
 static void __exit rc_core_exit(void)
 {
-	class_unregister(&ir_input_class);
+	class_unregister(&rc_class);
 	rc_map_unregister(&empty_map);
 }
 
-module_init(rc_core_init);
+subsys_initcall(rc_core_init);
 module_exit(rc_core_exit);
 
 int rc_core_debug;    /* ir_debug level (0,1,2) */
diff --git a/drivers/media/rc/redrat3.c b/drivers/media/rc/redrat3.c
index 1b37fe2..12167a6 100644
--- a/drivers/media/rc/redrat3.c
+++ b/drivers/media/rc/redrat3.c
@@ -45,6 +45,7 @@
  *
  */
 
+#include <asm/unaligned.h>
 #include <linux/device.h>
 #include <linux/module.h>
 #include <linux/slab.h>
@@ -53,7 +54,6 @@
 #include <media/rc-core.h>
 
 /* Driver Information */
-#define DRIVER_VERSION "0.70"
 #define DRIVER_AUTHOR "Jarod Wilson <jarod@redhat.com>"
 #define DRIVER_AUTHOR2 "The Dweller, Stephen Cox"
 #define DRIVER_DESC "RedRat3 USB IR Transceiver Driver"
@@ -129,25 +129,11 @@ static int debug;
 /* USB bulk-in IR data endpoint address */
 #define RR3_BULK_IN_EP_ADDR	0x82
 
-/* Raw Modulated signal data value offsets */
-#define RR3_PAUSE_OFFSET	0
-#define RR3_FREQ_COUNT_OFFSET	4
-#define RR3_NUM_PERIOD_OFFSET	6
-#define RR3_MAX_LENGTHS_OFFSET	8
-#define RR3_NUM_LENGTHS_OFFSET	9
-#define RR3_MAX_SIGS_OFFSET	10
-#define RR3_NUM_SIGS_OFFSET	12
-#define RR3_REPEATS_OFFSET	14
-
 /* Size of the fixed-length portion of the signal */
-#define RR3_HEADER_LENGTH	15
 #define RR3_DRIVER_MAXLENS	128
 #define RR3_MAX_SIG_SIZE	512
-#define RR3_MAX_BUF_SIZE	\
-	((2 * RR3_HEADER_LENGTH) + RR3_DRIVER_MAXLENS + RR3_MAX_SIG_SIZE)
 #define RR3_TIME_UNIT		50
 #define RR3_END_OF_SIGNAL	0x7f
-#define RR3_TX_HEADER_OFFSET	4
 #define RR3_TX_TRAILER_LEN	2
 #define RR3_RX_MIN_TIMEOUT	5
 #define RR3_RX_MAX_TIMEOUT	2000
@@ -159,6 +145,32 @@ static int debug;
 #define USB_RR3USB_PRODUCT_ID	0x0001
 #define USB_RR3IIUSB_PRODUCT_ID	0x0005
 
+struct redrat3_header {
+	__be16 length;
+	__be16 transfer_type;
+} __packed;
+
+/* sending and receiving irdata */
+struct redrat3_irdata {
+	struct redrat3_header header;
+	__be32 pause;
+	__be16 mod_freq_count;
+	__be16 num_periods;
+	__u8 max_lengths;
+	__u8 no_lengths;
+	__be16 max_sig_size;
+	__be16 sig_size;
+	__u8 no_repeats;
+	__be16 lens[RR3_DRIVER_MAXLENS]; /* not aligned */
+	__u8 sigdata[RR3_MAX_SIG_SIZE];
+} __packed;
+
+/* firmware errors */
+struct redrat3_error {
+	struct redrat3_header header;
+	__be16 fw_error;
+} __packed;
+
 /* table of devices that work with this driver */
 static struct usb_device_id redrat3_dev_table[] = {
 	/* Original version of the RedRat3 */
@@ -180,20 +192,15 @@ struct redrat3_dev {
 	/* the receive endpoint */
 	struct usb_endpoint_descriptor *ep_in;
 	/* the buffer to receive data */
-	unsigned char *bulk_in_buf;
+	void *bulk_in_buf;
 	/* urb used to read ir data */
 	struct urb *read_urb;
 
 	/* the send endpoint */
 	struct usb_endpoint_descriptor *ep_out;
-	/* the buffer to send data */
-	unsigned char *bulk_out_buf;
-	/* the urb used to send data */
-	struct urb *write_urb;
 
 	/* usb dma */
 	dma_addr_t dma_in;
-	dma_addr_t dma_out;
 
 	/* rx signal timeout timer */
 	struct timer_list rx_timeout;
@@ -205,72 +212,15 @@ struct redrat3_dev {
 	bool transmitting;
 
 	/* store for current packet */
-	char pbuf[RR3_MAX_BUF_SIZE];
-	u16 pktlen;
-	u16 pkttype;
+	struct redrat3_irdata irdata;
 	u16 bytes_read;
-	/* indicate whether we are going to reprocess
-	 * the USB callback with a bigger buffer */
-	int buftoosmall;
-	char *datap;
 
 	u32 carrier;
 
-	char name[128];
+	char name[64];
 	char phys[64];
 };
 
-/* All incoming data buffers adhere to a very specific data format */
-struct redrat3_signal_header {
-	u16 length;	/* Length of data being transferred */
-	u16 transfer_type; /* Type of data transferred */
-	u32 pause;	/* Pause between main and repeat signals */
-	u16 mod_freq_count; /* Value of timer on mod. freq. measurement */
-	u16 no_periods;	/* No. of periods over which mod. freq. is measured */
-	u8 max_lengths;	/* Max no. of lengths (i.e. size of array) */
-	u8 no_lengths;	/* Actual no. of elements in lengths array */
-	u16 max_sig_size; /* Max no. of values in signal data array */
-	u16 sig_size;	/* Acuto no. of values in signal data array */
-	u8 no_repeats;	/* No. of repeats of repeat signal section */
-	/* Here forward is the lengths and signal data */
-};
-
-static void redrat3_dump_signal_header(struct redrat3_signal_header *header)
-{
-	pr_info("%s:\n", __func__);
-	pr_info(" * length: %u, transfer_type: 0x%02x\n",
-		header->length, header->transfer_type);
-	pr_info(" * pause: %u, freq_count: %u, no_periods: %u\n",
-		header->pause, header->mod_freq_count, header->no_periods);
-	pr_info(" * lengths: %u (max: %u)\n",
-		header->no_lengths, header->max_lengths);
-	pr_info(" * sig_size: %u (max: %u)\n",
-		header->sig_size, header->max_sig_size);
-	pr_info(" * repeats: %u\n", header->no_repeats);
-}
-
-static void redrat3_dump_signal_data(char *buffer, u16 len)
-{
-	int offset, i;
-	char *data_vals;
-
-	pr_info("%s:", __func__);
-
-	offset = RR3_TX_HEADER_OFFSET + RR3_HEADER_LENGTH
-		 + (RR3_DRIVER_MAXLENS * sizeof(u16));
-
-	/* read RR3_DRIVER_MAXLENS from ctrl msg */
-	data_vals = buffer + offset;
-
-	for (i = 0; i < len; i++) {
-		if (i % 10 == 0)
-			pr_cont("\n * ");
-		pr_cont("%02x ", *data_vals++);
-	}
-
-	pr_cont("\n");
-}
-
 /*
  * redrat3_issue_async
  *
@@ -283,7 +233,6 @@ static void redrat3_issue_async(struct redrat3_dev *rr3)
 
 	rr3_ftr(rr3->dev, "Entering %s\n", __func__);
 
-	memset(rr3->bulk_in_buf, 0, rr3->ep_in->wMaxPacketSize);
 	res = usb_submit_urb(rr3->read_urb, GFP_ATOMIC);
 	if (res)
 		rr3_dbg(rr3->dev, "%s: receive request FAILED! "
@@ -352,13 +301,14 @@ static void redrat3_dump_fw_error(struct redrat3_dev *rr3, int code)
 	}
 }
 
-static u32 redrat3_val_to_mod_freq(struct redrat3_signal_header *ph)
+static u32 redrat3_val_to_mod_freq(struct redrat3_irdata *irdata)
 {
 	u32 mod_freq = 0;
+	u16 mod_freq_count = be16_to_cpu(irdata->mod_freq_count);
 
-	if (ph->mod_freq_count != 0)
-		mod_freq = (RR3_CLK * ph->no_periods) /
-				(ph->mod_freq_count * RR3_CLK_PER_COUNT);
+	if (mod_freq_count != 0)
+		mod_freq = (RR3_CLK * be16_to_cpu(irdata->num_periods)) /
+			(mod_freq_count * RR3_CLK_PER_COUNT);
 
 	return mod_freq;
 }
@@ -396,7 +346,6 @@ static u32 redrat3_us_to_len(u32 microsec)
 
 	/* don't allow zero lengths to go back, breaks lirc */
 	return result ? result : 1;
-
 }
 
 /* timer callback to send reset event */
@@ -411,16 +360,11 @@ static void redrat3_rx_timeout(unsigned long data)
 static void redrat3_process_ir_data(struct redrat3_dev *rr3)
 {
 	DEFINE_IR_RAW_EVENT(rawir);
-	struct redrat3_signal_header header;
 	struct device *dev;
-	int i, trailer = 0;
+	unsigned i, trailer = 0;
+	unsigned sig_size, single_len, offset, val;
 	unsigned long delay;
-	u32 mod_freq, single_len;
-	u16 *len_vals;
-	u8 *data_vals;
-	u32 tmp32;
-	u16 tmp16;
-	char *sig_data;
+	u32 mod_freq;
 
 	if (!rr3) {
 		pr_err("%s called with no context!\n", __func__);
@@ -430,57 +374,20 @@ static void redrat3_process_ir_data(struct redrat3_dev *rr3)
 	rr3_ftr(rr3->dev, "Entered %s\n", __func__);
 
 	dev = rr3->dev;
-	sig_data = rr3->pbuf;
-
-	header.length = rr3->pktlen;
-	header.transfer_type = rr3->pkttype;
-
-	/* Sanity check */
-	if (!(header.length >= RR3_HEADER_LENGTH))
-		dev_warn(dev, "read returned less than rr3 header len\n");
 
 	/* Make sure we reset the IR kfifo after a bit of inactivity */
 	delay = usecs_to_jiffies(rr3->hw_timeout);
 	mod_timer(&rr3->rx_timeout, jiffies + delay);
 
-	memcpy(&tmp32, sig_data + RR3_PAUSE_OFFSET, sizeof(tmp32));
-	header.pause = be32_to_cpu(tmp32);
-
-	memcpy(&tmp16, sig_data + RR3_FREQ_COUNT_OFFSET, sizeof(tmp16));
-	header.mod_freq_count = be16_to_cpu(tmp16);
-
-	memcpy(&tmp16, sig_data + RR3_NUM_PERIOD_OFFSET, sizeof(tmp16));
-	header.no_periods = be16_to_cpu(tmp16);
-
-	header.max_lengths = sig_data[RR3_MAX_LENGTHS_OFFSET];
-	header.no_lengths = sig_data[RR3_NUM_LENGTHS_OFFSET];
-
-	memcpy(&tmp16, sig_data + RR3_MAX_SIGS_OFFSET, sizeof(tmp16));
-	header.max_sig_size = be16_to_cpu(tmp16);
-
-	memcpy(&tmp16, sig_data + RR3_NUM_SIGS_OFFSET, sizeof(tmp16));
-	header.sig_size = be16_to_cpu(tmp16);
-
-	header.no_repeats= sig_data[RR3_REPEATS_OFFSET];
-
-	if (debug) {
-		redrat3_dump_signal_header(&header);
-		redrat3_dump_signal_data(sig_data, header.sig_size);
-	}
-
-	mod_freq = redrat3_val_to_mod_freq(&header);
+	mod_freq = redrat3_val_to_mod_freq(&rr3->irdata);
 	rr3_dbg(dev, "Got mod_freq of %u\n", mod_freq);
 
-	/* Here we pull out the 'length' values from the signal */
-	len_vals = (u16 *)(sig_data + RR3_HEADER_LENGTH);
-
-	data_vals = sig_data + RR3_HEADER_LENGTH +
-		    (header.max_lengths * sizeof(u16));
-
 	/* process each rr3 encoded byte into an int */
-	for (i = 0; i < header.sig_size; i++) {
-		u16 val = len_vals[data_vals[i]];
-		single_len = redrat3_len_to_us((u32)be16_to_cpu(val));
+	sig_size = be16_to_cpu(rr3->irdata.sig_size);
+	for (i = 0; i < sig_size; i++) {
+		offset = rr3->irdata.sigdata[i];
+		val = get_unaligned_be16(&rr3->irdata.lens[offset]);
+		single_len = redrat3_len_to_us(val);
 
 		/* we should always get pulse/space/pulse/space samples */
 		if (i % 2)
@@ -515,8 +422,6 @@ static void redrat3_process_ir_data(struct redrat3_dev *rr3)
 
 	rr3_dbg(dev, "calling ir_raw_event_handle\n");
 	ir_raw_event_handle(rr3->rc);
-
-	return;
 }
 
 /* Util fn to send rr3 cmds */
@@ -540,7 +445,7 @@ static u8 redrat3_send_cmd(int cmd, struct redrat3_dev *rr3)
 			__func__, res, *data);
 		res = -EIO;
 	} else
-		res = (u8)data[0];
+		res = data[0];
 
 	kfree(data);
 
@@ -598,22 +503,18 @@ static inline void redrat3_delete(struct redrat3_dev *rr3,
 {
 	rr3_ftr(rr3->dev, "%s cleaning up\n", __func__);
 	usb_kill_urb(rr3->read_urb);
-	usb_kill_urb(rr3->write_urb);
 
 	usb_free_urb(rr3->read_urb);
-	usb_free_urb(rr3->write_urb);
 
-	usb_free_coherent(udev, rr3->ep_in->wMaxPacketSize,
+	usb_free_coherent(udev, le16_to_cpu(rr3->ep_in->wMaxPacketSize),
 			  rr3->bulk_in_buf, rr3->dma_in);
-	usb_free_coherent(udev, rr3->ep_out->wMaxPacketSize,
-			  rr3->bulk_out_buf, rr3->dma_out);
 
 	kfree(rr3);
 }
 
 static u32 redrat3_get_timeout(struct redrat3_dev *rr3)
 {
-	u32 *tmp;
+	__be32 *tmp;
 	u32 timeout = MS_TO_US(150); /* a sane default, if things go haywire */
 	int len, ret, pipe;
 
@@ -628,14 +529,16 @@ static u32 redrat3_get_timeout(struct redrat3_dev *rr3)
 	ret = usb_control_msg(rr3->udev, pipe, RR3_GET_IR_PARAM,
 			      USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
 			      RR3_IR_IO_SIG_TIMEOUT, 0, tmp, len, HZ * 5);
-	if (ret != len) {
+	if (ret != len)
 		dev_warn(rr3->dev, "Failed to read timeout from hardware\n");
-		return timeout;
+	else {
+		timeout = redrat3_len_to_us(be32_to_cpup(tmp));
+
+		rr3_dbg(rr3->dev, "Got timeout of %d ms\n", timeout / 1000);
 	}
 
-	timeout = redrat3_len_to_us(be32_to_cpu(*tmp));
+	kfree(tmp);
 
-	rr3_dbg(rr3->dev, "Got timeout of %d ms\n", timeout / 1000);
 	return timeout;
 }
 
@@ -652,7 +555,7 @@ static void redrat3_reset(struct redrat3_dev *rr3)
 	rxpipe = usb_rcvctrlpipe(udev, 0);
 	txpipe = usb_sndctrlpipe(udev, 0);
 
-	val = kzalloc(len, GFP_KERNEL);
+	val = kmalloc(len, GFP_KERNEL);
 	if (!val) {
 		dev_err(dev, "Memory allocation failure\n");
 		return;
@@ -706,82 +609,74 @@ static void redrat3_get_firmware_rev(struct redrat3_dev *rr3)
 	rr3_ftr(rr3->dev, "Exiting %s\n", __func__);
 }
 
-static void redrat3_read_packet_start(struct redrat3_dev *rr3, int len)
+static void redrat3_read_packet_start(struct redrat3_dev *rr3, unsigned len)
 {
-	u16 tx_error;
-	u16 hdrlen;
+	struct redrat3_header *header = rr3->bulk_in_buf;
+	unsigned pktlen, pkttype;
 
 	rr3_ftr(rr3->dev, "Entering %s\n", __func__);
 
 	/* grab the Length and type of transfer */
-	memcpy(&(rr3->pktlen), (unsigned char *) rr3->bulk_in_buf,
-	       sizeof(rr3->pktlen));
-	memcpy(&(rr3->pkttype), ((unsigned char *) rr3->bulk_in_buf +
-		sizeof(rr3->pktlen)),
-	       sizeof(rr3->pkttype));
+	pktlen = be16_to_cpu(header->length);
+	pkttype = be16_to_cpu(header->transfer_type);
 
-	/*data needs conversion to know what its real values are*/
-	rr3->pktlen = be16_to_cpu(rr3->pktlen);
-	rr3->pkttype = be16_to_cpu(rr3->pkttype);
+	if (pktlen > sizeof(rr3->irdata)) {
+		dev_warn(rr3->dev, "packet length %u too large\n", pktlen);
+		return;
+	}
 
-	switch (rr3->pkttype) {
+	switch (pkttype) {
 	case RR3_ERROR:
-		memcpy(&tx_error, ((unsigned char *)rr3->bulk_in_buf
-			+ (sizeof(rr3->pktlen) + sizeof(rr3->pkttype))),
-		       sizeof(tx_error));
-		tx_error = be16_to_cpu(tx_error);
-		redrat3_dump_fw_error(rr3, tx_error);
+		if (len >= sizeof(struct redrat3_error)) {
+			struct redrat3_error *error = rr3->bulk_in_buf;
+			unsigned fw_error = be16_to_cpu(error->fw_error);
+			redrat3_dump_fw_error(rr3, fw_error);
+		}
 		break;
 
 	case RR3_MOD_SIGNAL_IN:
-		hdrlen = sizeof(rr3->pktlen) + sizeof(rr3->pkttype);
+		memcpy(&rr3->irdata, rr3->bulk_in_buf, len);
 		rr3->bytes_read = len;
-		rr3->bytes_read -= hdrlen;
-		rr3->datap = &(rr3->pbuf[0]);
-
-		memcpy(rr3->datap, ((unsigned char *)rr3->bulk_in_buf + hdrlen),
-		       rr3->bytes_read);
-		rr3->datap += rr3->bytes_read;
 		rr3_dbg(rr3->dev, "bytes_read %d, pktlen %d\n",
-			rr3->bytes_read, rr3->pktlen);
+			rr3->bytes_read, pktlen);
 		break;
 
 	default:
-		rr3_dbg(rr3->dev, "ignoring packet with type 0x%02x, "
-			"len of %d, 0x%02x\n", rr3->pkttype, len, rr3->pktlen);
+		rr3_dbg(rr3->dev, "ignoring packet with type 0x%02x, len of %d, 0x%02x\n",
+						pkttype, len, pktlen);
 		break;
 	}
 }
 
-static void redrat3_read_packet_continue(struct redrat3_dev *rr3, int len)
+static void redrat3_read_packet_continue(struct redrat3_dev *rr3, unsigned len)
 {
+	void *irdata = &rr3->irdata;
 
 	rr3_ftr(rr3->dev, "Entering %s\n", __func__);
 
-	memcpy(rr3->datap, (unsigned char *)rr3->bulk_in_buf, len);
-	rr3->datap += len;
+	if (len + rr3->bytes_read > sizeof(rr3->irdata)) {
+		dev_warn(rr3->dev, "too much data for packet\n");
+		rr3->bytes_read = 0;
+		return;
+	}
+
+	memcpy(irdata + rr3->bytes_read, rr3->bulk_in_buf, len);
 
 	rr3->bytes_read += len;
-	rr3_dbg(rr3->dev, "bytes_read %d, pktlen %d\n",
-		rr3->bytes_read, rr3->pktlen);
+	rr3_dbg(rr3->dev, "bytes_read %d, pktlen %d\n", rr3->bytes_read,
+				 be16_to_cpu(rr3->irdata.header.length));
 }
 
 /* gather IR data from incoming urb, process it when we have enough */
-static int redrat3_get_ir_data(struct redrat3_dev *rr3, int len)
+static int redrat3_get_ir_data(struct redrat3_dev *rr3, unsigned len)
 {
 	struct device *dev = rr3->dev;
+	unsigned pkttype;
 	int ret = 0;
 
 	rr3_ftr(dev, "Entering %s\n", __func__);
 
-	if (rr3->pktlen > RR3_MAX_BUF_SIZE) {
-		dev_err(rr3->dev, "error: packet larger than buffer\n");
-		ret = -EINVAL;
-		goto out;
-	}
-
-	if ((rr3->bytes_read == 0) &&
-	    (len >= (sizeof(rr3->pkttype) + sizeof(rr3->pktlen)))) {
+	if (rr3->bytes_read == 0 && len >= sizeof(struct redrat3_header)) {
 		redrat3_read_packet_start(rr3, len);
 	} else if (rr3->bytes_read != 0) {
 		redrat3_read_packet_continue(rr3, len);
@@ -791,31 +686,25 @@ static int redrat3_get_ir_data(struct redrat3_dev *rr3, int len)
 		goto out;
 	}
 
-	if (rr3->bytes_read > rr3->pktlen) {
-		dev_err(dev, "bytes_read (%d) greater than pktlen (%d)\n",
-			rr3->bytes_read, rr3->pktlen);
-		ret = -EINVAL;
-		goto out;
-	} else if (rr3->bytes_read < rr3->pktlen)
+	if (rr3->bytes_read < be16_to_cpu(rr3->irdata.header.length))
 		/* we're still accumulating data */
 		return 0;
 
 	/* if we get here, we've got IR data to decode */
-	if (rr3->pkttype == RR3_MOD_SIGNAL_IN)
+	pkttype = be16_to_cpu(rr3->irdata.header.transfer_type);
+	if (pkttype == RR3_MOD_SIGNAL_IN)
 		redrat3_process_ir_data(rr3);
 	else
-		rr3_dbg(dev, "discarding non-signal data packet "
-			"(type 0x%02x)\n", rr3->pkttype);
+		rr3_dbg(dev, "discarding non-signal data packet (type 0x%02x)\n",
+								pkttype);
 
 out:
 	rr3->bytes_read = 0;
-	rr3->pktlen = 0;
-	rr3->pkttype = 0;
 	return ret;
 }
 
 /* callback function from USB when async USB request has completed */
-static void redrat3_handle_async(struct urb *urb, struct pt_regs *regs)
+static void redrat3_handle_async(struct urb *urb)
 {
 	struct redrat3_dev *rr3;
 	int ret;
@@ -851,34 +740,16 @@ static void redrat3_handle_async(struct urb *urb, struct pt_regs *regs)
 	default:
 		dev_warn(rr3->dev, "Error: urb status = %d\n", urb->status);
 		rr3->bytes_read = 0;
-		rr3->pktlen = 0;
-		rr3->pkttype = 0;
 		break;
 	}
 }
 
-static void redrat3_write_bulk_callback(struct urb *urb, struct pt_regs *regs)
-{
-	struct redrat3_dev *rr3;
-	int len;
-
-	if (!urb)
-		return;
-
-	rr3 = urb->context;
-	if (rr3) {
-		len = urb->actual_length;
-		rr3_ftr(rr3->dev, "%s: called (status=%d len=%d)\n",
-			__func__, urb->status, len);
-	}
-}
-
 static u16 mod_freq_to_val(unsigned int mod_freq)
 {
 	int mult = 6000000;
 
 	/* Clk used in mod. freq. generation is CLK24/4. */
-	return (u16)(65536 - (mult / mod_freq));
+	return 65536 - (mult / mod_freq);
 }
 
 static int redrat3_set_tx_carrier(struct rc_dev *rcdev, u32 carrier)
@@ -900,17 +771,12 @@ static int redrat3_transmit_ir(struct rc_dev *rcdev, unsigned *txbuf,
 {
 	struct redrat3_dev *rr3 = rcdev->priv;
 	struct device *dev = rr3->dev;
-	struct redrat3_signal_header header;
-	int i, j, ret, ret_len, offset;
+	struct redrat3_irdata *irdata = NULL;
+	int ret, ret_len;
 	int lencheck, cur_sample_len, pipe;
-	char *buffer = NULL, *sigdata = NULL;
 	int *sample_lens = NULL;
-	u32 tmpi;
-	u16 tmps;
-	u8 *datap;
 	u8 curlencheck = 0;
-	u16 *lengths_ptr;
-	int sendbuf_len;
+	unsigned i, sendbuf_len;
 
 	rr3_ftr(dev, "Entering %s\n", __func__);
 
@@ -931,8 +797,19 @@ static int redrat3_transmit_ir(struct rc_dev *rcdev, unsigned *txbuf,
 		goto out;
 	}
 
+	irdata = kzalloc(sizeof(*irdata), GFP_KERNEL);
+	if (!irdata) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
 	for (i = 0; i < count; i++) {
 		cur_sample_len = redrat3_us_to_len(txbuf[i]);
+		if (cur_sample_len > 0xffff) {
+			dev_warn(dev, "transmit period of %uus truncated to %uus\n",
+					txbuf[i], redrat3_len_to_us(0xffff));
+			cur_sample_len = 0xffff;
+		}
 		for (lencheck = 0; lencheck < curlencheck; lencheck++) {
 			if (sample_lens[lencheck] == cur_sample_len)
 				break;
@@ -944,94 +821,41 @@ static int redrat3_transmit_ir(struct rc_dev *rcdev, unsigned *txbuf,
 				/* now convert the value to a proper
 				 * rr3 value.. */
 				sample_lens[curlencheck] = cur_sample_len;
+				put_unaligned_be16(cur_sample_len,
+						&irdata->lens[curlencheck]);
 				curlencheck++;
 			} else {
 				count = i - 1;
 				break;
 			}
 		}
+		irdata->sigdata[i] = lencheck;
 	}
 
-	sigdata = kzalloc((count + RR3_TX_TRAILER_LEN), GFP_KERNEL);
-	if (!sigdata) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	sigdata[count] = RR3_END_OF_SIGNAL;
-	sigdata[count + 1] = RR3_END_OF_SIGNAL;
-	for (i = 0; i < count; i++) {
-		for (j = 0; j < curlencheck; j++) {
-			if (sample_lens[j] == redrat3_us_to_len(txbuf[i]))
-				sigdata[i] = j;
-		}
-	}
-
-	offset = RR3_TX_HEADER_OFFSET;
-	sendbuf_len = RR3_HEADER_LENGTH + (sizeof(u16) * RR3_DRIVER_MAXLENS)
-			+ count + RR3_TX_TRAILER_LEN + offset;
-
-	buffer = kzalloc(sendbuf_len, GFP_KERNEL);
-	if (!buffer) {
-		ret = -ENOMEM;
-		goto out;
-	}
+	irdata->sigdata[count] = RR3_END_OF_SIGNAL;
+	irdata->sigdata[count + 1] = RR3_END_OF_SIGNAL;
 
+	sendbuf_len = offsetof(struct redrat3_irdata,
+					sigdata[count + RR3_TX_TRAILER_LEN]);
 	/* fill in our packet header */
-	header.length = sendbuf_len - offset;
-	header.transfer_type = RR3_MOD_SIGNAL_OUT;
-	header.pause = redrat3_len_to_us(100);
-	header.mod_freq_count = mod_freq_to_val(rr3->carrier);
-	header.no_periods = 0; /* n/a to transmit */
-	header.max_lengths = RR3_DRIVER_MAXLENS;
-	header.no_lengths = curlencheck;
-	header.max_sig_size = RR3_MAX_SIG_SIZE;
-	header.sig_size = count + RR3_TX_TRAILER_LEN;
-	/* we currently rely on repeat handling in the IR encoding source */
-	header.no_repeats = 0;
-
-	tmps = cpu_to_be16(header.length);
-	memcpy(buffer, &tmps, 2);
-
-	tmps = cpu_to_be16(header.transfer_type);
-	memcpy(buffer + 2, &tmps, 2);
-
-	tmpi = cpu_to_be32(header.pause);
-	memcpy(buffer + offset, &tmpi, sizeof(tmpi));
-
-	tmps = cpu_to_be16(header.mod_freq_count);
-	memcpy(buffer + offset + RR3_FREQ_COUNT_OFFSET, &tmps, 2);
-
-	buffer[offset + RR3_NUM_LENGTHS_OFFSET] = header.no_lengths;
-
-	tmps = cpu_to_be16(header.sig_size);
-	memcpy(buffer + offset + RR3_NUM_SIGS_OFFSET, &tmps, 2);
-
-	buffer[offset + RR3_REPEATS_OFFSET] = header.no_repeats;
-
-	lengths_ptr = (u16 *)(buffer + offset + RR3_HEADER_LENGTH);
-	for (i = 0; i < curlencheck; ++i)
-		lengths_ptr[i] = cpu_to_be16(sample_lens[i]);
-
-	datap = (u8 *)(buffer + offset + RR3_HEADER_LENGTH +
-			    (sizeof(u16) * RR3_DRIVER_MAXLENS));
-	memcpy(datap, sigdata, (count + RR3_TX_TRAILER_LEN));
-
-	if (debug) {
-		redrat3_dump_signal_header(&header);
-		redrat3_dump_signal_data(buffer, header.sig_size);
-	}
+	irdata->header.length = cpu_to_be16(sendbuf_len -
+						sizeof(struct redrat3_header));
+	irdata->header.transfer_type = cpu_to_be16(RR3_MOD_SIGNAL_OUT);
+	irdata->pause = cpu_to_be32(redrat3_len_to_us(100));
+	irdata->mod_freq_count = cpu_to_be16(mod_freq_to_val(rr3->carrier));
+	irdata->no_lengths = curlencheck;
+	irdata->sig_size = cpu_to_be16(count + RR3_TX_TRAILER_LEN);
 
 	pipe = usb_sndbulkpipe(rr3->udev, rr3->ep_out->bEndpointAddress);
-	tmps = usb_bulk_msg(rr3->udev, pipe, buffer,
+	ret = usb_bulk_msg(rr3->udev, pipe, irdata,
 			    sendbuf_len, &ret_len, 10 * HZ);
-	rr3_dbg(dev, "sent %d bytes, (ret %d)\n", ret_len, tmps);
+	rr3_dbg(dev, "sent %d bytes, (ret %d)\n", ret_len, ret);
 
 	/* now tell the hardware to transmit what we sent it */
 	pipe = usb_rcvctrlpipe(rr3->udev, 0);
 	ret = usb_control_msg(rr3->udev, pipe, RR3_TX_SEND_SIGNAL,
 			      USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
-			      0, 0, buffer, 2, HZ * 10);
+			      0, 0, irdata, 2, HZ * 10);
 
 	if (ret < 0)
 		dev_err(dev, "Error: control msg send failed, rc %d\n", ret);
@@ -1040,8 +864,7 @@ static int redrat3_transmit_ir(struct rc_dev *rcdev, unsigned *txbuf,
 
 out:
 	kfree(sample_lens);
-	kfree(buffer);
-	kfree(sigdata);
+	kfree(irdata);
 
 	rr3->transmitting = false;
 	/* rr3 re-enables rc detector because it was enabled before */
@@ -1165,38 +988,18 @@ static int redrat3_dev_probe(struct usb_interface *intf,
 	}
 
 	rr3->ep_in = ep_in;
-	rr3->bulk_in_buf = usb_alloc_coherent(udev, ep_in->wMaxPacketSize,
-					      GFP_ATOMIC, &rr3->dma_in);
+	rr3->bulk_in_buf = usb_alloc_coherent(udev,
+		le16_to_cpu(ep_in->wMaxPacketSize), GFP_ATOMIC, &rr3->dma_in);
 	if (!rr3->bulk_in_buf) {
 		dev_err(dev, "Read buffer allocation failure\n");
 		goto error;
 	}
 
 	pipe = usb_rcvbulkpipe(udev, ep_in->bEndpointAddress);
-	usb_fill_bulk_urb(rr3->read_urb, udev, pipe,
-			  rr3->bulk_in_buf, ep_in->wMaxPacketSize,
-			  (usb_complete_t)redrat3_handle_async, rr3);
-
-	/* set up bulk-out endpoint*/
-	rr3->write_urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!rr3->write_urb) {
-		dev_err(dev, "Write urb allocation failure\n");
-		goto error;
-	}
+	usb_fill_bulk_urb(rr3->read_urb, udev, pipe, rr3->bulk_in_buf,
+		le16_to_cpu(ep_in->wMaxPacketSize), redrat3_handle_async, rr3);
 
 	rr3->ep_out = ep_out;
-	rr3->bulk_out_buf = usb_alloc_coherent(udev, ep_out->wMaxPacketSize,
-					       GFP_ATOMIC, &rr3->dma_out);
-	if (!rr3->bulk_out_buf) {
-		dev_err(dev, "Write buffer allocation failure\n");
-		goto error;
-	}
-
-	pipe = usb_sndbulkpipe(udev, ep_out->bEndpointAddress);
-	usb_fill_bulk_urb(rr3->write_urb, udev, pipe,
-			  rr3->bulk_out_buf, ep_out->wMaxPacketSize,
-			  (usb_complete_t)redrat3_write_bulk_callback, rr3);
-
 	rr3->udev = udev;
 
 	redrat3_reset(rr3);
diff --git a/drivers/media/tuners/Kconfig b/drivers/media/tuners/Kconfig
index e8fdf71..ffabd66 100644
--- a/drivers/media/tuners/Kconfig
+++ b/drivers/media/tuners/Kconfig
@@ -241,4 +241,11 @@ config MEDIA_TUNER_TUA9001
 	default m if !MEDIA_SUBDRV_AUTOSELECT
 	help
 	  Infineon TUA 9001 silicon tuner driver.
+
+config MEDIA_TUNER_IT913X
+	tristate "ITE Tech IT913x silicon tuner"
+	depends on MEDIA_SUPPORT && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  ITE Tech IT913x silicon tuner driver.
 endmenu
diff --git a/drivers/media/tuners/Makefile b/drivers/media/tuners/Makefile
index 5e569b1..f136a6d 100644
--- a/drivers/media/tuners/Makefile
+++ b/drivers/media/tuners/Makefile
@@ -34,6 +34,7 @@ obj-$(CONFIG_MEDIA_TUNER_TUA9001) += tua9001.o
 obj-$(CONFIG_MEDIA_TUNER_FC0011) += fc0011.o
 obj-$(CONFIG_MEDIA_TUNER_FC0012) += fc0012.o
 obj-$(CONFIG_MEDIA_TUNER_FC0013) += fc0013.o
+obj-$(CONFIG_MEDIA_TUNER_IT913X) += it913x.o
 
 ccflags-y += -I$(srctree)/drivers/media/dvb-core
 ccflags-y += -I$(srctree)/drivers/media/dvb-frontends
diff --git a/drivers/media/tuners/e4000.h b/drivers/media/tuners/e4000.h
index 71b1935..3783a0b 100644
--- a/drivers/media/tuners/e4000.h
+++ b/drivers/media/tuners/e4000.h
@@ -21,6 +21,7 @@
 #ifndef E4000_H
 #define E4000_H
 
+#include <linux/kconfig.h>
 #include "dvb_frontend.h"
 
 struct e4000_config {
@@ -36,8 +37,7 @@ struct e4000_config {
 	u32 clock;
 };
 
-#if defined(CONFIG_MEDIA_TUNER_E4000) || \
-	(defined(CONFIG_MEDIA_TUNER_E4000_MODULE) && defined(MODULE))
+#if IS_ENABLED(CONFIG_MEDIA_TUNER_E4000)
 extern struct dvb_frontend *e4000_attach(struct dvb_frontend *fe,
 		struct i2c_adapter *i2c, const struct e4000_config *cfg);
 #else
diff --git a/drivers/media/tuners/fc0011.h b/drivers/media/tuners/fc0011.h
index 0ee581f..43ec893 100644
--- a/drivers/media/tuners/fc0011.h
+++ b/drivers/media/tuners/fc0011.h
@@ -1,6 +1,7 @@
 #ifndef LINUX_FC0011_H_
 #define LINUX_FC0011_H_
 
+#include <linux/kconfig.h>
 #include "dvb_frontend.h"
 
 
@@ -22,8 +23,7 @@ enum fc0011_fe_callback_commands {
 	FC0011_FE_CALLBACK_RESET,
 };
 
-#if defined(CONFIG_MEDIA_TUNER_FC0011) ||\
-    defined(CONFIG_MEDIA_TUNER_FC0011_MODULE)
+#if IS_ENABLED(CONFIG_MEDIA_TUNER_FC0011)
 struct dvb_frontend *fc0011_attach(struct dvb_frontend *fe,
 				   struct i2c_adapter *i2c,
 				   const struct fc0011_config *config);
diff --git a/drivers/media/tuners/fc0012.h b/drivers/media/tuners/fc0012.h
index 54508fc..1d08057 100644
--- a/drivers/media/tuners/fc0012.h
+++ b/drivers/media/tuners/fc0012.h
@@ -21,6 +21,7 @@
 #ifndef _FC0012_H_
 #define _FC0012_H_
 
+#include <linux/kconfig.h>
 #include "dvb_frontend.h"
 #include "fc001x-common.h"
 
@@ -48,8 +49,7 @@ struct fc0012_config {
 	bool clock_out;
 };
 
-#if defined(CONFIG_MEDIA_TUNER_FC0012) || \
-	(defined(CONFIG_MEDIA_TUNER_FC0012_MODULE) && defined(MODULE))
+#if IS_ENABLED(CONFIG_MEDIA_TUNER_FC0012)
 extern struct dvb_frontend *fc0012_attach(struct dvb_frontend *fe,
 					struct i2c_adapter *i2c,
 					const struct fc0012_config *cfg);
diff --git a/drivers/media/tuners/fc0013.h b/drivers/media/tuners/fc0013.h
index 594efd6..d65d5b3 100644
--- a/drivers/media/tuners/fc0013.h
+++ b/drivers/media/tuners/fc0013.h
@@ -22,11 +22,11 @@
 #ifndef _FC0013_H_
 #define _FC0013_H_
 
+#include <linux/kconfig.h>
 #include "dvb_frontend.h"
 #include "fc001x-common.h"
 
-#if defined(CONFIG_MEDIA_TUNER_FC0013) || \
-	(defined(CONFIG_MEDIA_TUNER_FC0013_MODULE) && defined(MODULE))
+#if IS_ENABLED(CONFIG_MEDIA_TUNER_FC0013)
 extern struct dvb_frontend *fc0013_attach(struct dvb_frontend *fe,
 					struct i2c_adapter *i2c,
 					u8 i2c_address, int dual_master,
diff --git a/drivers/media/tuners/fc2580.h b/drivers/media/tuners/fc2580.h
index 222601e..9c43c1c 100644
--- a/drivers/media/tuners/fc2580.h
+++ b/drivers/media/tuners/fc2580.h
@@ -21,6 +21,7 @@
 #ifndef FC2580_H
 #define FC2580_H
 
+#include <linux/kconfig.h>
 #include "dvb_frontend.h"
 
 struct fc2580_config {
@@ -36,8 +37,7 @@ struct fc2580_config {
 	u32 clock;
 };
 
-#if defined(CONFIG_MEDIA_TUNER_FC2580) || \
-	(defined(CONFIG_MEDIA_TUNER_FC2580_MODULE) && defined(MODULE))
+#if IS_ENABLED(CONFIG_MEDIA_TUNER_FC2580)
 extern struct dvb_frontend *fc2580_attach(struct dvb_frontend *fe,
 	struct i2c_adapter *i2c, const struct fc2580_config *cfg);
 #else
diff --git a/drivers/media/tuners/it913x.c b/drivers/media/tuners/it913x.c
new file mode 100644
index 0000000..4d7a247
--- /dev/null
+++ b/drivers/media/tuners/it913x.c
@@ -0,0 +1,447 @@
+/*
+ * ITE Tech IT9137 silicon tuner driver
+ *
+ *  Copyright (C) 2011 Malcolm Priestley (tvboxspy@gmail.com)
+ *  IT9137 Copyright (C) ITE Tech 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., 675 Mass Ave, Cambridge, MA 02139, USA.=
+ */
+
+#include "it913x_priv.h"
+
+struct it913x_state {
+	struct i2c_adapter *i2c_adap;
+	u8 i2c_addr;
+	u8 chip_ver;
+	u8 tuner_type;
+	u8 firmware_ver;
+	u16 tun_xtal;
+	u8 tun_fdiv;
+	u8 tun_clk_mode;
+	u32 tun_fn_min;
+};
+
+/* read multiple registers */
+static int it913x_rd_regs(struct it913x_state *state,
+		u32 reg, u8 *data, u8 count)
+{
+	int ret;
+	u8 b[3];
+	struct i2c_msg msg[2] = {
+		{ .addr = state->i2c_addr, .flags = 0,
+			.buf = b, .len = sizeof(b) },
+		{ .addr = state->i2c_addr, .flags = I2C_M_RD,
+			.buf = data, .len = count }
+	};
+	b[0] = (u8)(reg >> 16) & 0xff;
+	b[1] = (u8)(reg >> 8) & 0xff;
+	b[2] = (u8) reg & 0xff;
+	b[0] |= 0x80; /* All reads from demodulator */
+
+	ret = i2c_transfer(state->i2c_adap, msg, 2);
+
+	return ret;
+}
+
+/* read single register */
+static int it913x_rd_reg(struct it913x_state *state, u32 reg)
+{
+	int ret;
+	u8 b[1];
+	ret = it913x_rd_regs(state, reg, &b[0], sizeof(b));
+	return (ret < 0) ? -ENODEV : b[0];
+}
+
+/* write multiple registers */
+static int it913x_wr_regs(struct it913x_state *state,
+		u8 pro, u32 reg, u8 buf[], u8 count)
+{
+	u8 b[256];
+	struct i2c_msg msg[1] = {
+		{ .addr = state->i2c_addr, .flags = 0,
+		  .buf = b, .len = 3 + count }
+	};
+	int ret;
+	b[0] = (u8)(reg >> 16) & 0xff;
+	b[1] = (u8)(reg >> 8) & 0xff;
+	b[2] = (u8) reg & 0xff;
+	memcpy(&b[3], buf, count);
+
+	if (pro == PRO_DMOD)
+		b[0] |= 0x80;
+
+	ret = i2c_transfer(state->i2c_adap, msg, 1);
+
+	if (ret < 0)
+		return -EIO;
+
+	return 0;
+}
+
+/* write single register */
+static int it913x_wr_reg(struct it913x_state *state,
+		u8 pro, u32 reg, u32 data)
+{
+	int ret;
+	u8 b[4];
+	u8 s;
+
+	b[0] = data >> 24;
+	b[1] = (data >> 16) & 0xff;
+	b[2] = (data >> 8) & 0xff;
+	b[3] = data & 0xff;
+	/* expand write as needed */
+	if (data < 0x100)
+		s = 3;
+	else if (data < 0x1000)
+		s = 2;
+	else if (data < 0x100000)
+		s = 1;
+	else
+		s = 0;
+
+	ret = it913x_wr_regs(state, pro, reg, &b[s], sizeof(b) - s);
+
+	return ret;
+}
+
+static int it913x_script_loader(struct it913x_state *state,
+		struct it913xset *loadscript)
+{
+	int ret, i;
+	if (loadscript == NULL)
+		return -EINVAL;
+
+	for (i = 0; i < 1000; ++i) {
+		if (loadscript[i].pro == 0xff)
+			break;
+		ret = it913x_wr_regs(state, loadscript[i].pro,
+			loadscript[i].address,
+			loadscript[i].reg, loadscript[i].count);
+		if (ret < 0)
+			return -ENODEV;
+	}
+	return 0;
+}
+
+static int it913x_init(struct dvb_frontend *fe)
+{
+	struct it913x_state *state = fe->tuner_priv;
+	int ret, i, reg;
+	u8 val, nv_val;
+	u8 nv[] = {48, 32, 24, 16, 12, 8, 6, 4, 2};
+	u8 b[2];
+
+	reg = it913x_rd_reg(state, 0xec86);
+	switch (reg) {
+	case 0:
+		state->tun_clk_mode = reg;
+		state->tun_xtal = 2000;
+		state->tun_fdiv = 3;
+		val = 16;
+		break;
+	case -ENODEV:
+		return -ENODEV;
+	case 1:
+	default:
+		state->tun_clk_mode = reg;
+		state->tun_xtal = 640;
+		state->tun_fdiv = 1;
+		val = 6;
+		break;
+	}
+
+	reg = it913x_rd_reg(state, 0xed03);
+
+	if (reg < 0)
+		return -ENODEV;
+	else if (reg < ARRAY_SIZE(nv))
+		nv_val = nv[reg];
+	else
+		nv_val = 2;
+
+	for (i = 0; i < 50; i++) {
+		ret = it913x_rd_regs(state, 0xed23, &b[0], sizeof(b));
+		reg = (b[1] << 8) + b[0];
+		if (reg > 0)
+			break;
+		if (ret < 0)
+			return -ENODEV;
+		udelay(2000);
+	}
+	state->tun_fn_min = state->tun_xtal * reg;
+	state->tun_fn_min /= (state->tun_fdiv * nv_val);
+	dev_dbg(&state->i2c_adap->dev, "%s: Tuner fn_min %d\n", __func__,
+			state->tun_fn_min);
+
+	if (state->chip_ver > 1)
+		msleep(50);
+	else {
+		for (i = 0; i < 50; i++) {
+			reg = it913x_rd_reg(state, 0xec82);
+			if (reg > 0)
+				break;
+			if (reg < 0)
+				return -ENODEV;
+			udelay(2000);
+		}
+	}
+
+	/* Power Up Tuner - common all versions */
+	ret = it913x_wr_reg(state, PRO_DMOD, 0xec40, 0x1);
+	ret |= it913x_wr_reg(state, PRO_DMOD, 0xfba8, 0x0);
+	ret |= it913x_wr_reg(state, PRO_DMOD, 0xec57, 0x0);
+	ret |= it913x_wr_reg(state, PRO_DMOD, 0xec58, 0x0);
+
+	return it913x_wr_reg(state, PRO_DMOD, 0xed81, val);
+}
+
+static int it9137_set_params(struct dvb_frontend *fe)
+{
+	struct it913x_state *state = fe->tuner_priv;
+	struct it913xset *set_tuner = set_it9137_template;
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	u32 bandwidth = p->bandwidth_hz;
+	u32 frequency_m = p->frequency;
+	int ret, reg;
+	u32 frequency = frequency_m / 1000;
+	u32 freq, temp_f, tmp;
+	u16 iqik_m_cal;
+	u16 n_div;
+	u8 n;
+	u8 l_band;
+	u8 lna_band;
+	u8 bw;
+
+	if (state->firmware_ver == 1)
+		set_tuner = set_it9135_template;
+	else
+		set_tuner = set_it9137_template;
+
+	dev_dbg(&state->i2c_adap->dev, "%s: Tuner Frequency %d Bandwidth %d\n",
+			__func__, frequency, bandwidth);
+
+	if (frequency >= 51000 && frequency <= 440000) {
+		l_band = 0;
+		lna_band = 0;
+	} else if (frequency > 440000 && frequency <= 484000) {
+		l_band = 1;
+		lna_band = 1;
+	} else if (frequency > 484000 && frequency <= 533000) {
+		l_band = 1;
+		lna_band = 2;
+	} else if (frequency > 533000 && frequency <= 587000) {
+		l_band = 1;
+		lna_band = 3;
+	} else if (frequency > 587000 && frequency <= 645000) {
+		l_band = 1;
+		lna_band = 4;
+	} else if (frequency > 645000 && frequency <= 710000) {
+		l_band = 1;
+		lna_band = 5;
+	} else if (frequency > 710000 && frequency <= 782000) {
+		l_band = 1;
+		lna_band = 6;
+	} else if (frequency > 782000 && frequency <= 860000) {
+		l_band = 1;
+		lna_band = 7;
+	} else if (frequency > 1450000 && frequency <= 1492000) {
+		l_band = 1;
+		lna_band = 0;
+	} else if (frequency > 1660000 && frequency <= 1685000) {
+		l_band = 1;
+		lna_band = 1;
+	} else
+		return -EINVAL;
+	set_tuner[0].reg[0] = lna_band;
+
+	switch (bandwidth) {
+	case 5000000:
+		bw = 0;
+		break;
+	case 6000000:
+		bw = 2;
+		break;
+	case 7000000:
+		bw = 4;
+		break;
+	default:
+	case 8000000:
+		bw = 6;
+		break;
+	}
+
+	set_tuner[1].reg[0] = bw;
+	set_tuner[2].reg[0] = 0xa0 | (l_band << 3);
+
+	if (frequency > 53000 && frequency <= 74000) {
+		n_div = 48;
+		n = 0;
+	} else if (frequency > 74000 && frequency <= 111000) {
+		n_div = 32;
+		n = 1;
+	} else if (frequency > 111000 && frequency <= 148000) {
+		n_div = 24;
+		n = 2;
+	} else if (frequency > 148000 && frequency <= 222000) {
+		n_div = 16;
+		n = 3;
+	} else if (frequency > 222000 && frequency <= 296000) {
+		n_div = 12;
+		n = 4;
+	} else if (frequency > 296000 && frequency <= 445000) {
+		n_div = 8;
+		n = 5;
+	} else if (frequency > 445000 && frequency <= state->tun_fn_min) {
+		n_div = 6;
+		n = 6;
+	} else if (frequency > state->tun_fn_min && frequency <= 950000) {
+		n_div = 4;
+		n = 7;
+	} else if (frequency > 1450000 && frequency <= 1680000) {
+		n_div = 2;
+		n = 0;
+	} else
+		return -EINVAL;
+
+	reg = it913x_rd_reg(state, 0xed81);
+	iqik_m_cal = (u16)reg * n_div;
+
+	if (reg < 0x20) {
+		if (state->tun_clk_mode == 0)
+			iqik_m_cal = (iqik_m_cal * 9) >> 5;
+		else
+			iqik_m_cal >>= 1;
+	} else {
+		iqik_m_cal = 0x40 - iqik_m_cal;
+		if (state->tun_clk_mode == 0)
+			iqik_m_cal = ~((iqik_m_cal * 9) >> 5);
+		else
+			iqik_m_cal = ~(iqik_m_cal >> 1);
+	}
+
+	temp_f = frequency * (u32)n_div * (u32)state->tun_fdiv;
+	freq = temp_f / state->tun_xtal;
+	tmp = freq * state->tun_xtal;
+
+	if ((temp_f - tmp) >= (state->tun_xtal >> 1))
+		freq++;
+
+	freq += (u32) n << 13;
+	/* Frequency OMEGA_IQIK_M_CAL_MID*/
+	temp_f = freq + (u32)iqik_m_cal;
+
+	set_tuner[3].reg[0] =  temp_f & 0xff;
+	set_tuner[4].reg[0] =  (temp_f >> 8) & 0xff;
+
+	dev_dbg(&state->i2c_adap->dev, "%s: High Frequency = %04x\n",
+			__func__, temp_f);
+
+	/* Lower frequency */
+	set_tuner[5].reg[0] =  freq & 0xff;
+	set_tuner[6].reg[0] =  (freq >> 8) & 0xff;
+
+	dev_dbg(&state->i2c_adap->dev, "%s: low Frequency = %04x\n",
+			__func__, freq);
+
+	ret = it913x_script_loader(state, set_tuner);
+
+	return (ret < 0) ? -ENODEV : 0;
+}
+
+/* Power sequence */
+/* Power Up	Tuner on -> Frontend suspend off -> Tuner clk on */
+/* Power Down	Frontend suspend on -> Tuner clk off -> Tuner off */
+
+static int it913x_sleep(struct dvb_frontend *fe)
+{
+	struct it913x_state *state = fe->tuner_priv;
+	return it913x_script_loader(state, it9137_tuner_off);
+}
+
+static int it913x_release(struct dvb_frontend *fe)
+{
+	kfree(fe->tuner_priv);
+	return 0;
+}
+
+static const struct dvb_tuner_ops it913x_tuner_ops = {
+	.info = {
+		.name           = "ITE Tech IT913X",
+		.frequency_min  = 174000000,
+		.frequency_max  = 862000000,
+	},
+
+	.release = it913x_release,
+
+	.init = it913x_init,
+	.sleep = it913x_sleep,
+	.set_params = it9137_set_params,
+};
+
+struct dvb_frontend *it913x_attach(struct dvb_frontend *fe,
+		struct i2c_adapter *i2c_adap, u8 i2c_addr, u8 config)
+{
+	struct it913x_state *state = NULL;
+
+	/* allocate memory for the internal state */
+	state = kzalloc(sizeof(struct it913x_state), GFP_KERNEL);
+	if (state == NULL)
+		return NULL;
+
+	state->i2c_adap = i2c_adap;
+	state->i2c_addr = i2c_addr;
+
+	switch (config) {
+	case AF9033_TUNER_IT9135_38:
+	case AF9033_TUNER_IT9135_51:
+	case AF9033_TUNER_IT9135_52:
+		state->chip_ver = 0x01;
+		break;
+	case AF9033_TUNER_IT9135_60:
+	case AF9033_TUNER_IT9135_61:
+	case AF9033_TUNER_IT9135_62:
+		state->chip_ver = 0x02;
+		break;
+	default:
+		dev_dbg(&i2c_adap->dev,
+				"%s: invalid config=%02x\n", __func__, config);
+		goto error;
+	}
+
+	state->tuner_type = config;
+	state->firmware_ver = 1;
+
+	fe->tuner_priv = state;
+	memcpy(&fe->ops.tuner_ops, &it913x_tuner_ops,
+			sizeof(struct dvb_tuner_ops));
+
+	dev_info(&i2c_adap->dev,
+			"%s: ITE Tech IT913X successfully attached\n",
+			KBUILD_MODNAME);
+	dev_dbg(&i2c_adap->dev, "%s: config=%02x chip_ver=%02x\n",
+			__func__, config, state->chip_ver);
+
+	return fe;
+error:
+	kfree(state);
+	return NULL;
+}
+EXPORT_SYMBOL(it913x_attach);
+
+MODULE_DESCRIPTION("ITE Tech IT913X silicon tuner driver");
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/tuners/it913x.h b/drivers/media/tuners/it913x.h
new file mode 100644
index 0000000..12dd36b
--- /dev/null
+++ b/drivers/media/tuners/it913x.h
@@ -0,0 +1,45 @@
+/*
+ * ITE Tech IT9137 silicon tuner driver
+ *
+ *  Copyright (C) 2011 Malcolm Priestley (tvboxspy@gmail.com)
+ *  IT9137 Copyright (C) ITE Tech 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., 675 Mass Ave, Cambridge, MA 02139, USA.=
+ */
+
+#ifndef IT913X_H
+#define IT913X_H
+
+#include "dvb_frontend.h"
+
+#if defined(CONFIG_MEDIA_TUNER_IT913X) || \
+	(defined(CONFIG_MEDIA_TUNER_IT913X_MODULE) && defined(MODULE))
+extern struct dvb_frontend *it913x_attach(struct dvb_frontend *fe,
+	struct i2c_adapter *i2c_adap,
+	u8 i2c_addr,
+	u8 config);
+#else
+static inline struct dvb_frontend *it913x_attach(struct dvb_frontend *fe,
+	struct i2c_adapter *i2c_adap,
+	u8 i2c_addr,
+	u8 config)
+{
+	pr_warn("%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif
+
+#endif
diff --git a/drivers/media/tuners/it913x_priv.h b/drivers/media/tuners/it913x_priv.h
new file mode 100644
index 0000000..00dcf3c
--- /dev/null
+++ b/drivers/media/tuners/it913x_priv.h
@@ -0,0 +1,78 @@
+/*
+ * ITE Tech IT9137 silicon tuner driver
+ *
+ *  Copyright (C) 2011 Malcolm Priestley (tvboxspy@gmail.com)
+ *  IT9137 Copyright (C) ITE Tech 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., 675 Mass Ave, Cambridge, MA 02139, USA.=
+ */
+
+#ifndef IT913X_PRIV_H
+#define IT913X_PRIV_H
+
+#include "it913x.h"
+#include "af9033.h"
+
+#define PRO_LINK		0x0
+#define PRO_DMOD		0x1
+#define TRIGGER_OFSM		0x0000
+
+struct it913xset {	u32 pro;
+			u32 address;
+			u8 reg[15];
+			u8 count;
+};
+
+/* Tuner setting scripts (still keeping it9137) */
+static struct it913xset it9137_tuner_off[] = {
+	{PRO_DMOD, 0xfba8, {0x01}, 0x01}, /* Tuner Clock Off  */
+	{PRO_DMOD, 0xec40, {0x00}, 0x01}, /* Power Down Tuner */
+	{PRO_DMOD, 0xec02, {0x3f, 0x1f, 0x3f, 0x3f}, 0x04},
+	{PRO_DMOD, 0xec06, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+				0x00, 0x00, 0x00, 0x00}, 0x0c},
+	{PRO_DMOD, 0xec12, {0x00, 0x00, 0x00, 0x00}, 0x04},
+	{PRO_DMOD, 0xec17, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+				0x00}, 0x09},
+	{PRO_DMOD, 0xec22, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+				0x00, 0x00}, 0x0a},
+	{PRO_DMOD, 0xec20, {0x00}, 0x01},
+	{PRO_DMOD, 0xec3f, {0x01}, 0x01},
+	{0xff, 0x0000, {0x00}, 0x00}, /* Terminating Entry */
+};
+
+static struct it913xset set_it9135_template[] = {
+	{PRO_DMOD, 0xee06, {0x00}, 0x01},
+	{PRO_DMOD, 0xec56, {0x00}, 0x01},
+	{PRO_DMOD, 0xec4c, {0x00}, 0x01},
+	{PRO_DMOD, 0xec4d, {0x00}, 0x01},
+	{PRO_DMOD, 0xec4e, {0x00}, 0x01},
+	{PRO_DMOD, 0x011e, {0x00}, 0x01}, /* Older Devices */
+	{PRO_DMOD, 0x011f, {0x00}, 0x01},
+	{0xff, 0x0000, {0x00}, 0x00}, /* Terminating Entry */
+};
+
+static struct it913xset set_it9137_template[] = {
+	{PRO_DMOD, 0xee06, {0x00}, 0x01},
+	{PRO_DMOD, 0xec56, {0x00}, 0x01},
+	{PRO_DMOD, 0xec4c, {0x00}, 0x01},
+	{PRO_DMOD, 0xec4d, {0x00}, 0x01},
+	{PRO_DMOD, 0xec4e, {0x00}, 0x01},
+	{PRO_DMOD, 0xec4f, {0x00}, 0x01},
+	{PRO_DMOD, 0xec50, {0x00}, 0x01},
+	{0xff, 0x0000, {0x00}, 0x00}, /* Terminating Entry */
+};
+
+#endif
diff --git a/drivers/media/tuners/max2165.h b/drivers/media/tuners/max2165.h
index c063c36..26e1dc6 100644
--- a/drivers/media/tuners/max2165.h
+++ b/drivers/media/tuners/max2165.h
@@ -22,6 +22,8 @@
 #ifndef __MAX2165_H__
 #define __MAX2165_H__
 
+#include <linux/kconfig.h>
+
 struct dvb_frontend;
 struct i2c_adapter;
 
@@ -30,8 +32,7 @@ struct max2165_config {
 	u8 osc_clk; /* in MHz, selectable values: 4,16,18,20,22,24,26,28 */
 };
 
-#if defined(CONFIG_MEDIA_TUNER_MAX2165) || \
-    (defined(CONFIG_MEDIA_TUNER_MAX2165_MODULE) && defined(MODULE))
+#if IS_ENABLED(CONFIG_MEDIA_TUNER_MAX2165)
 extern struct dvb_frontend *max2165_attach(struct dvb_frontend *fe,
 	struct i2c_adapter *i2c,
 	struct max2165_config *cfg);
diff --git a/drivers/media/tuners/mc44s803.h b/drivers/media/tuners/mc44s803.h
index 34f3892..9aae50a 100644
--- a/drivers/media/tuners/mc44s803.h
+++ b/drivers/media/tuners/mc44s803.h
@@ -22,6 +22,8 @@
 #ifndef MC44S803_H
 #define MC44S803_H
 
+#include <linux/kconfig.h>
+
 struct dvb_frontend;
 struct i2c_adapter;
 
@@ -30,8 +32,7 @@ struct mc44s803_config {
 	u8 dig_out;
 };
 
-#if defined(CONFIG_MEDIA_TUNER_MC44S803) || \
-    (defined(CONFIG_MEDIA_TUNER_MC44S803_MODULE) && defined(MODULE))
+#if IS_ENABLED(CONFIG_MEDIA_TUNER_MC44S803)
 extern struct dvb_frontend *mc44s803_attach(struct dvb_frontend *fe,
 	 struct i2c_adapter *i2c, struct mc44s803_config *cfg);
 #else
diff --git a/drivers/media/tuners/mxl5005s.h b/drivers/media/tuners/mxl5005s.h
index fc8a1ff..ae8db88 100644
--- a/drivers/media/tuners/mxl5005s.h
+++ b/drivers/media/tuners/mxl5005s.h
@@ -23,6 +23,8 @@
 #ifndef __MXL5005S_H
 #define __MXL5005S_H
 
+#include <linux/kconfig.h>
+
 #include <linux/i2c.h>
 #include "dvb_frontend.h"
 
@@ -116,8 +118,7 @@ struct mxl5005s_config {
 	u8 AgcMasterByte;
 };
 
-#if defined(CONFIG_MEDIA_TUNER_MXL5005S) || \
-	(defined(CONFIG_MEDIA_TUNER_MXL5005S_MODULE) && defined(MODULE))
+#if IS_ENABLED(CONFIG_MEDIA_TUNER_MXL5005S)
 extern struct dvb_frontend *mxl5005s_attach(struct dvb_frontend *fe,
 					    struct i2c_adapter *i2c,
 					    struct mxl5005s_config *config);
diff --git a/drivers/media/tuners/tda18212.h b/drivers/media/tuners/tda18212.h
index 9bd5da4..7e0d503 100644
--- a/drivers/media/tuners/tda18212.h
+++ b/drivers/media/tuners/tda18212.h
@@ -21,6 +21,7 @@
 #ifndef TDA18212_H
 #define TDA18212_H
 
+#include <linux/kconfig.h>
 #include "dvb_frontend.h"
 
 struct tda18212_config {
@@ -36,8 +37,7 @@ struct tda18212_config {
 	u16 if_dvbc;
 };
 
-#if defined(CONFIG_MEDIA_TUNER_TDA18212) || \
-	(defined(CONFIG_MEDIA_TUNER_TDA18212_MODULE) && defined(MODULE))
+#if IS_ENABLED(CONFIG_MEDIA_TUNER_TDA18212)
 extern struct dvb_frontend *tda18212_attach(struct dvb_frontend *fe,
 	struct i2c_adapter *i2c, struct tda18212_config *cfg);
 #else
diff --git a/drivers/media/tuners/tda18218.h b/drivers/media/tuners/tda18218.h
index b4180d1..366410e 100644
--- a/drivers/media/tuners/tda18218.h
+++ b/drivers/media/tuners/tda18218.h
@@ -21,6 +21,7 @@
 #ifndef TDA18218_H
 #define TDA18218_H
 
+#include <linux/kconfig.h>
 #include "dvb_frontend.h"
 
 struct tda18218_config {
@@ -29,8 +30,7 @@ struct tda18218_config {
 	u8 loop_through:1;
 };
 
-#if defined(CONFIG_MEDIA_TUNER_TDA18218) || \
-	(defined(CONFIG_MEDIA_TUNER_TDA18218_MODULE) && defined(MODULE))
+#if IS_ENABLED(CONFIG_MEDIA_TUNER_TDA18218)
 extern struct dvb_frontend *tda18218_attach(struct dvb_frontend *fe,
 	struct i2c_adapter *i2c, struct tda18218_config *cfg);
 #else
diff --git a/drivers/media/tuners/tua9001.h b/drivers/media/tuners/tua9001.h
index cf5b815..26358da 100644
--- a/drivers/media/tuners/tua9001.h
+++ b/drivers/media/tuners/tua9001.h
@@ -21,6 +21,7 @@
 #ifndef TUA9001_H
 #define TUA9001_H
 
+#include <linux/kconfig.h>
 #include "dvb_frontend.h"
 
 struct tua9001_config {
@@ -50,8 +51,7 @@ struct tua9001_config {
 #define TUA9001_CMD_RESETN  1
 #define TUA9001_CMD_RXEN    2
 
-#if defined(CONFIG_MEDIA_TUNER_TUA9001) || \
-	(defined(CONFIG_MEDIA_TUNER_TUA9001_MODULE) && defined(MODULE))
+#if IS_ENABLED(CONFIG_MEDIA_TUNER_TUA9001)
 extern struct dvb_frontend *tua9001_attach(struct dvb_frontend *fe,
 		struct i2c_adapter *i2c, struct tua9001_config *cfg);
 #else
diff --git a/drivers/media/tuners/tuner-types.c b/drivers/media/tuners/tuner-types.c
index 2da4440..98bc15a 100644
--- a/drivers/media/tuners/tuner-types.c
+++ b/drivers/media/tuners/tuner-types.c
@@ -1381,6 +1381,58 @@ static struct tuner_params tuner_philips_fq1236_mk5_params[] = {
 	},
 };
 
+/* --------- Sony BTF-PG472Z PAL/SECAM ------- */
+
+static struct tuner_range tuner_sony_btf_pg472z_ranges[] = {
+	{ 16 * 144.25 /*MHz*/, 0xc6, 0x01, },
+	{ 16 * 427.25 /*MHz*/, 0xc6, 0x02, },
+	{ 16 * 999.99        , 0xc6, 0x04, },
+};
+
+static struct tuner_params tuner_sony_btf_pg472z_params[] = {
+	{
+		.type   = TUNER_PARAM_TYPE_PAL,
+		.ranges = tuner_sony_btf_pg472z_ranges,
+		.count  = ARRAY_SIZE(tuner_sony_btf_pg472z_ranges),
+		.has_tda9887 = 1,
+		.port1_active = 1,
+		.port2_invert_for_secam_lc = 1,
+	},
+};
+
+/* 90-99 */
+/* --------- Sony BTF-PG467Z NTSC-M-JP ------- */
+
+static struct tuner_range tuner_sony_btf_pg467z_ranges[] = {
+	{ 16 * 220.25 /*MHz*/, 0xc6, 0x01, },
+	{ 16 * 467.25 /*MHz*/, 0xc6, 0x02, },
+	{ 16 * 999.99        , 0xc6, 0x04, },
+};
+
+static struct tuner_params tuner_sony_btf_pg467z_params[] = {
+	{
+		.type   = TUNER_PARAM_TYPE_NTSC,
+		.ranges = tuner_sony_btf_pg467z_ranges,
+		.count  = ARRAY_SIZE(tuner_sony_btf_pg467z_ranges),
+	},
+};
+
+/* --------- Sony BTF-PG463Z NTSC-M ------- */
+
+static struct tuner_range tuner_sony_btf_pg463z_ranges[] = {
+	{ 16 * 130.25 /*MHz*/, 0xc6, 0x01, },
+	{ 16 * 364.25 /*MHz*/, 0xc6, 0x02, },
+	{ 16 * 999.99        , 0xc6, 0x04, },
+};
+
+static struct tuner_params tuner_sony_btf_pg463z_params[] = {
+	{
+		.type   = TUNER_PARAM_TYPE_NTSC,
+		.ranges = tuner_sony_btf_pg463z_ranges,
+		.count  = ARRAY_SIZE(tuner_sony_btf_pg463z_ranges),
+	},
+};
+
 /* --------------------------------------------------------------------- */
 
 struct tunertype tuners[] = {
@@ -1872,6 +1924,23 @@ struct tunertype tuners[] = {
 		.name   = "Xceive 5000C tuner",
 		/* see xc5000.c for details */
 	},
+	[TUNER_SONY_BTF_PG472Z] = {
+		.name   = "Sony BTF-PG472Z PAL/SECAM",
+		.params = tuner_sony_btf_pg472z_params,
+		.count  = ARRAY_SIZE(tuner_sony_btf_pg472z_params),
+	},
+
+	/* 90-99 */
+	[TUNER_SONY_BTF_PK467Z] = {
+		.name   = "Sony BTF-PK467Z NTSC-M-JP",
+		.params = tuner_sony_btf_pg467z_params,
+		.count  = ARRAY_SIZE(tuner_sony_btf_pg467z_params),
+	},
+	[TUNER_SONY_BTF_PB463Z] = {
+		.name   = "Sony BTF-PB463Z NTSC-M",
+		.params = tuner_sony_btf_pg463z_params,
+		.count  = ARRAY_SIZE(tuner_sony_btf_pg463z_params),
+	},
 };
 EXPORT_SYMBOL(tuners);
 
diff --git a/drivers/media/tuners/tuner-xc2028.c b/drivers/media/tuners/tuner-xc2028.c
index 0945173..878d2c4 100644
--- a/drivers/media/tuners/tuner-xc2028.c
+++ b/drivers/media/tuners/tuner-xc2028.c
@@ -1378,8 +1378,7 @@ static int xc2028_set_config(struct dvb_frontend *fe, void *priv_cfg)
 	 * For the firmware name, keep a local copy of the string,
 	 * in order to avoid troubles during device release.
 	 */
-	if (priv->ctrl.fname)
-		kfree(priv->ctrl.fname);
+	kfree(priv->ctrl.fname);
 	memcpy(&priv->ctrl, p, sizeof(priv->ctrl));
 	if (p->fname) {
 		priv->ctrl.fname = kstrdup(p->fname, GFP_KERNEL);
diff --git a/drivers/media/tuners/xc5000.c b/drivers/media/tuners/xc5000.c
index d6be1b6..5cd09a6 100644
--- a/drivers/media/tuners/xc5000.c
+++ b/drivers/media/tuners/xc5000.c
@@ -422,13 +422,19 @@ static int xc_initialize(struct xc5000_priv *priv)
 }
 
 static int xc_SetTVStandard(struct xc5000_priv *priv,
-	u16 VideoMode, u16 AudioMode)
+	u16 VideoMode, u16 AudioMode, u8 RadioMode)
 {
 	int ret;
 	dprintk(1, "%s(0x%04x,0x%04x)\n", __func__, VideoMode, AudioMode);
-	dprintk(1, "%s() Standard = %s\n",
-		__func__,
-		XC5000_Standard[priv->video_standard].Name);
+	if (RadioMode) {
+		dprintk(1, "%s() Standard = %s\n",
+			__func__,
+			XC5000_Standard[RadioMode].Name);
+	} else {
+		dprintk(1, "%s() Standard = %s\n",
+			__func__,
+			XC5000_Standard[priv->video_standard].Name);
+	}
 
 	ret = xc_write_reg(priv, XREG_VIDEO_MODE, VideoMode);
 	if (ret == XC_RESULT_SUCCESS)
@@ -824,7 +830,7 @@ static int xc5000_set_params(struct dvb_frontend *fe)
 
 	ret = xc_SetTVStandard(priv,
 		XC5000_Standard[priv->video_standard].VideoMode,
-		XC5000_Standard[priv->video_standard].AudioMode);
+		XC5000_Standard[priv->video_standard].AudioMode, 0);
 	if (ret != XC_RESULT_SUCCESS) {
 		printk(KERN_ERR "xc5000: xc_SetTVStandard failed\n");
 		return -EREMOTEIO;
@@ -940,7 +946,7 @@ tune_channel:
 
 	ret = xc_SetTVStandard(priv,
 		XC5000_Standard[priv->video_standard].VideoMode,
-		XC5000_Standard[priv->video_standard].AudioMode);
+		XC5000_Standard[priv->video_standard].AudioMode, 0);
 	if (ret != XC_RESULT_SUCCESS) {
 		printk(KERN_ERR "xc5000: xc_SetTVStandard failed\n");
 		return -EREMOTEIO;
@@ -1003,7 +1009,7 @@ static int xc5000_set_radio_freq(struct dvb_frontend *fe,
 	priv->rf_mode = XC_RF_MODE_AIR;
 
 	ret = xc_SetTVStandard(priv, XC5000_Standard[radio_input].VideoMode,
-			       XC5000_Standard[radio_input].AudioMode);
+			       XC5000_Standard[radio_input].AudioMode, radio_input);
 
 	if (ret != XC_RESULT_SUCCESS) {
 		printk(KERN_ERR "xc5000: xc_SetTVStandard failed\n");
diff --git a/drivers/media/tuners/xc5000.h b/drivers/media/tuners/xc5000.h
index b1a5474..7245cae 100644
--- a/drivers/media/tuners/xc5000.h
+++ b/drivers/media/tuners/xc5000.h
@@ -22,6 +22,7 @@
 #ifndef __XC5000_H__
 #define __XC5000_H__
 
+#include <linux/kconfig.h>
 #include <linux/firmware.h>
 
 struct dvb_frontend;
@@ -56,8 +57,7 @@ struct xc5000_config {
  * it's passed back to a bridge during tuner_callback().
  */
 
-#if defined(CONFIG_MEDIA_TUNER_XC5000) || \
-    (defined(CONFIG_MEDIA_TUNER_XC5000_MODULE) && defined(MODULE))
+#if IS_ENABLED(CONFIG_MEDIA_TUNER_XC5000)
 extern struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe,
 					  struct i2c_adapter *i2c,
 					  const struct xc5000_config *cfg);
diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c
index 1e6f40e..bd9d19a 100644
--- a/drivers/media/usb/au0828/au0828-core.c
+++ b/drivers/media/usb/au0828/au0828-core.c
@@ -125,6 +125,26 @@ static int recv_control_msg(struct au0828_dev *dev, u16 request, u32 value,
 	return status;
 }
 
+static void au0828_usb_release(struct au0828_dev *dev)
+{
+	/* I2C */
+	au0828_i2c_unregister(dev);
+
+	kfree(dev);
+}
+
+#ifdef CONFIG_VIDEO_AU0828_V4L2
+static void au0828_usb_v4l2_release(struct v4l2_device *v4l2_dev)
+{
+	struct au0828_dev *dev =
+		container_of(v4l2_dev, struct au0828_dev, v4l2_dev);
+
+	v4l2_ctrl_handler_free(&dev->v4l2_ctrl_hdl);
+	v4l2_device_unregister(&dev->v4l2_dev);
+	au0828_usb_release(dev);
+}
+#endif
+
 static void au0828_usb_disconnect(struct usb_interface *interface)
 {
 	struct au0828_dev *dev = usb_get_intfdata(interface);
@@ -134,26 +154,19 @@ static void au0828_usb_disconnect(struct usb_interface *interface)
 	/* Digital TV */
 	au0828_dvb_unregister(dev);
 
-#ifdef CONFIG_VIDEO_AU0828_V4L2
-	if (AUVI_INPUT(0).type != AU0828_VMUX_UNDEFINED)
-		au0828_analog_unregister(dev);
-#endif
-
-	/* I2C */
-	au0828_i2c_unregister(dev);
-
-#ifdef CONFIG_VIDEO_AU0828_V4L2
-	v4l2_device_unregister(&dev->v4l2_dev);
-#endif
-
 	usb_set_intfdata(interface, NULL);
-
 	mutex_lock(&dev->mutex);
 	dev->usbdev = NULL;
 	mutex_unlock(&dev->mutex);
-
-	kfree(dev);
-
+#ifdef CONFIG_VIDEO_AU0828_V4L2
+	if (AUVI_INPUT(0).type != AU0828_VMUX_UNDEFINED) {
+		au0828_analog_unregister(dev);
+		v4l2_device_disconnect(&dev->v4l2_dev);
+		v4l2_device_put(&dev->v4l2_dev);
+		return;
+	}
+#endif
+	au0828_usb_release(dev);
 }
 
 static int au0828_usb_probe(struct usb_interface *interface,
@@ -202,15 +215,27 @@ static int au0828_usb_probe(struct usb_interface *interface,
 	dev->boardnr = id->driver_info;
 
 #ifdef CONFIG_VIDEO_AU0828_V4L2
+	dev->v4l2_dev.release = au0828_usb_v4l2_release;
+
 	/* Create the v4l2_device */
 	retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev);
 	if (retval) {
-		printk(KERN_ERR "%s() v4l2_device_register failed\n",
+		pr_err("%s() v4l2_device_register failed\n",
+		       __func__);
+		mutex_unlock(&dev->lock);
+		kfree(dev);
+		return retval;
+	}
+	/* This control handler will inherit the controls from au8522 */
+	retval = v4l2_ctrl_handler_init(&dev->v4l2_ctrl_hdl, 4);
+	if (retval) {
+		pr_err("%s() v4l2_ctrl_handler_init failed\n",
 		       __func__);
 		mutex_unlock(&dev->lock);
 		kfree(dev);
-		return -EIO;
+		return retval;
 	}
+	dev->v4l2_dev.ctrl_handler = &dev->v4l2_ctrl_hdl;
 #endif
 
 	/* Power Up the bridge */
diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c
index 8b9e826..75ac994 100644
--- a/drivers/media/usb/au0828/au0828-video.c
+++ b/drivers/media/usb/au0828/au0828-video.c
@@ -35,6 +35,7 @@
 #include <linux/suspend.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-ioctl.h>
+#include <media/v4l2-event.h>
 #include <media/v4l2-chip-ident.h>
 #include <media/tuner.h>
 #include "au0828.h"
@@ -58,6 +59,12 @@ do {\
 	} \
   } while (0)
 
+static inline void i2c_gate_ctrl(struct au0828_dev *dev, int val)
+{
+	if (dev->dvb.frontend && dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl)
+		dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl(dev->dvb.frontend, val);
+}
+
 static inline void print_err_status(struct au0828_dev *dev,
 				    int packet, int status)
 {
@@ -988,20 +995,22 @@ static int au0828_v4l2_open(struct file *filp)
 
 	fh->type = type;
 	fh->dev = dev;
+	v4l2_fh_init(&fh->fh, vdev);
 	filp->private_data = fh;
 
-	if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) {
+	if (mutex_lock_interruptible(&dev->lock)) {
+		kfree(fh);
+		return -ERESTARTSYS;
+	}
+	if (dev->users == 0) {
 		/* set au0828 interface0 to AS5 here again */
 		ret = usb_set_interface(dev->usbdev, 0, 5);
 		if (ret < 0) {
+			mutex_unlock(&dev->lock);
 			printk(KERN_INFO "Au0828 can't set alternate to 5!\n");
+			kfree(fh);
 			return -EBUSY;
 		}
-		dev->width = NTSC_STD_W;
-		dev->height = NTSC_STD_H;
-		dev->frame_size = dev->width * dev->height * 2;
-		dev->field_size = dev->width * dev->height;
-		dev->bytesperline = dev->width * 2;
 
 		au0828_analog_stream_enable(dev);
 		au0828_analog_stream_reset(dev);
@@ -1014,6 +1023,7 @@ static int au0828_v4l2_open(struct file *filp)
 	}
 
 	dev->users++;
+	mutex_unlock(&dev->lock);
 
 	videobuf_queue_vmalloc_init(&fh->vb_vidq, &au0828_video_qops,
 				    NULL, &dev->slock,
@@ -1023,14 +1033,13 @@ static int au0828_v4l2_open(struct file *filp)
 				    &dev->lock);
 
 	/* VBI Setup */
-	dev->vbi_width = 720;
-	dev->vbi_height = 1;
 	videobuf_queue_vmalloc_init(&fh->vb_vbiq, &au0828_vbi_qops,
 				    NULL, &dev->slock,
 				    V4L2_BUF_TYPE_VBI_CAPTURE,
 				    V4L2_FIELD_SEQ_TB,
 				    sizeof(struct au0828_buffer), fh,
 				    &dev->lock);
+	v4l2_fh_add(&fh->fh);
 	return ret;
 }
 
@@ -1040,6 +1049,9 @@ static int au0828_v4l2_close(struct file *filp)
 	struct au0828_fh *fh = filp->private_data;
 	struct au0828_dev *dev = fh->dev;
 
+	v4l2_fh_del(&fh->fh);
+	v4l2_fh_exit(&fh->fh);
+	mutex_lock(&dev->lock);
 	if (res_check(fh, AU0828_RESOURCE_VIDEO)) {
 		/* Cancel timeout thread in case they didn't call streamoff */
 		dev->vid_timeout_running = 0;
@@ -1058,19 +1070,14 @@ static int au0828_v4l2_close(struct file *filp)
 		res_free(fh, AU0828_RESOURCE_VBI);
 	}
 
-	if (dev->users == 1) {
-		if (dev->dev_state & DEV_DISCONNECTED) {
-			au0828_analog_unregister(dev);
-			kfree(dev);
-			return 0;
-		}
-
+	if (dev->users == 1 && video_is_registered(video_devdata(filp))) {
 		au0828_analog_stream_disable(dev);
 
 		au0828_uninit_isoc(dev);
 
 		/* Save some power by putting tuner to sleep */
 		v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_power, 0);
+		dev->std_set_in_tuner_core = 0;
 
 		/* When close the device, set the usb intf0 into alt0 to free
 		   USB bandwidth */
@@ -1078,6 +1085,7 @@ static int au0828_v4l2_close(struct file *filp)
 		if (ret < 0)
 			printk(KERN_INFO "Au0828 can't set alternate to 0!\n");
 	}
+	mutex_unlock(&dev->lock);
 
 	videobuf_mmap_free(&fh->vb_vidq);
 	videobuf_mmap_free(&fh->vb_vbiq);
@@ -1087,6 +1095,26 @@ static int au0828_v4l2_close(struct file *filp)
 	return 0;
 }
 
+/* Must be called with dev->lock held */
+static void au0828_init_tuner(struct au0828_dev *dev)
+{
+	struct v4l2_frequency f = {
+		.frequency = dev->ctrl_freq,
+		.type = V4L2_TUNER_ANALOG_TV,
+	};
+
+	if (dev->std_set_in_tuner_core)
+		return;
+	dev->std_set_in_tuner_core = 1;
+	i2c_gate_ctrl(dev, 1);
+	/* If we've never sent the standard in tuner core, do so now.
+	   We don't do this at device probe because we don't want to
+	   incur the cost of a firmware load */
+	v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, dev->std);
+	v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, &f);
+	i2c_gate_ctrl(dev, 0);
+}
+
 static ssize_t au0828_v4l2_read(struct file *filp, char __user *buf,
 				size_t count, loff_t *pos)
 {
@@ -1098,6 +1126,11 @@ static ssize_t au0828_v4l2_read(struct file *filp, char __user *buf,
 	if (rc < 0)
 		return rc;
 
+	if (mutex_lock_interruptible(&dev->lock))
+		return -ERESTARTSYS;
+	au0828_init_tuner(dev);
+	mutex_unlock(&dev->lock);
+
 	if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
 		if (res_locked(dev, AU0828_RESOURCE_VIDEO))
 			return -EBUSY;
@@ -1128,23 +1161,32 @@ static unsigned int au0828_v4l2_poll(struct file *filp, poll_table *wait)
 {
 	struct au0828_fh *fh = filp->private_data;
 	struct au0828_dev *dev = fh->dev;
-	int rc;
+	unsigned long req_events = poll_requested_events(wait);
+	unsigned int res;
 
-	rc = check_dev(dev);
-	if (rc < 0)
-		return rc;
+	if (check_dev(dev) < 0)
+		return POLLERR;
+
+	res = v4l2_ctrl_poll(filp, wait);
+	if (!(req_events & (POLLIN | POLLRDNORM)))
+		return res;
+
+	if (mutex_lock_interruptible(&dev->lock))
+		return -ERESTARTSYS;
+	au0828_init_tuner(dev);
+	mutex_unlock(&dev->lock);
 
 	if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
 		if (!res_get(fh, AU0828_RESOURCE_VIDEO))
 			return POLLERR;
-		return videobuf_poll_stream(filp, &fh->vb_vidq, wait);
-	} else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
+		return res | videobuf_poll_stream(filp, &fh->vb_vidq, wait);
+	}
+	if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
 		if (!res_get(fh, AU0828_RESOURCE_VBI))
 			return POLLERR;
-		return videobuf_poll_stream(filp, &fh->vb_vbiq, wait);
-	} else {
-		return POLLERR;
+		return res | videobuf_poll_stream(filp, &fh->vb_vbiq, wait);
 	}
+	return POLLERR;
 }
 
 static int au0828_v4l2_mmap(struct file *filp, struct vm_area_struct *vma)
@@ -1172,9 +1214,6 @@ static int au0828_set_format(struct au0828_dev *dev, unsigned int cmd,
 	int width = format->fmt.pix.width;
 	int height = format->fmt.pix.height;
 
-	if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		return -EINVAL;
-
 	/* If they are demanding a format other than the one we support,
 	   bail out (tvtime asks for UYVY and then retries with YUYV) */
 	if (format->fmt.pix.pixelformat != V4L2_PIX_FMT_UYVY)
@@ -1193,6 +1232,7 @@ static int au0828_set_format(struct au0828_dev *dev, unsigned int cmd,
 	format->fmt.pix.sizeimage = width * height * 2;
 	format->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
 	format->fmt.pix.field = V4L2_FIELD_INTERLACED;
+	format->fmt.pix.priv = 0;
 
 	if (cmd == VIDIOC_TRY_FMT)
 		return 0;
@@ -1226,35 +1266,28 @@ static int au0828_set_format(struct au0828_dev *dev, unsigned int cmd,
 }
 
 
-static int vidioc_queryctrl(struct file *file, void *priv,
-			    struct v4l2_queryctrl *qc)
-{
-	struct au0828_fh *fh = priv;
-	struct au0828_dev *dev = fh->dev;
-	v4l2_device_call_all(&dev->v4l2_dev, 0, core, queryctrl, qc);
-	if (qc->type)
-		return 0;
-	else
-		return -EINVAL;
-}
-
 static int vidioc_querycap(struct file *file, void  *priv,
 			   struct v4l2_capability *cap)
 {
-	struct au0828_fh *fh  = priv;
+	struct video_device *vdev = video_devdata(file);
+	struct au0828_fh *fh = priv;
 	struct au0828_dev *dev = fh->dev;
 
 	strlcpy(cap->driver, "au0828", sizeof(cap->driver));
 	strlcpy(cap->card, dev->board.name, sizeof(cap->card));
-	strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info));
+	usb_make_path(dev->usbdev, cap->bus_info, sizeof(cap->bus_info));
 
-	/*set the device capabilities */
-	cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
-		V4L2_CAP_VBI_CAPTURE |
-		V4L2_CAP_AUDIO |
+	/* set the device capabilities */
+	cap->device_caps = V4L2_CAP_AUDIO |
 		V4L2_CAP_READWRITE |
 		V4L2_CAP_STREAMING |
 		V4L2_CAP_TUNER;
+	if (vdev->vfl_type == VFL_TYPE_GRABBER)
+		cap->device_caps |= V4L2_CAP_VIDEO_CAPTURE;
+	else
+		cap->device_caps |= V4L2_CAP_VBI_CAPTURE;
+	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS |
+		V4L2_CAP_VBI_CAPTURE | V4L2_CAP_VIDEO_CAPTURE;
 	return 0;
 }
 
@@ -1286,6 +1319,7 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
 	f->fmt.pix.sizeimage = dev->frame_size;
 	f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; /* NTSC/PAL */
 	f->fmt.pix.field = V4L2_FIELD_INTERLACED;
+	f->fmt.pix.priv = 0;
 	return 0;
 }
 
@@ -1320,24 +1354,34 @@ out:
 	return rc;
 }
 
-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)
 {
 	struct au0828_fh *fh = priv;
 	struct au0828_dev *dev = fh->dev;
 
-	if (dev->dvb.frontend && dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl)
-		dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl(dev->dvb.frontend, 1);
+	dev->std = norm;
+
+	au0828_init_tuner(dev);
+
+	i2c_gate_ctrl(dev, 1);
 
 	/* FIXME: when we support something other than NTSC, we are going to
 	   have to make the au0828 bridge adjust the size of its capture
 	   buffer, which is currently hardcoded at 720x480 */
 
-	v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, *norm);
-	dev->std_set_in_tuner_core = 1;
+	v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, norm);
 
-	if (dev->dvb.frontend && dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl)
-		dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl(dev->dvb.frontend, 0);
+	i2c_gate_ctrl(dev, 0);
+
+	return 0;
+}
+
+static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm)
+{
+	struct au0828_fh *fh = priv;
+	struct au0828_dev *dev = fh->dev;
 
+	*norm = dev->std;
 	return 0;
 }
 
@@ -1368,10 +1412,13 @@ static int vidioc_enum_input(struct file *file, void *priv,
 	input->index = tmp;
 	strcpy(input->name, inames[AUVI_INPUT(tmp).type]);
 	if ((AUVI_INPUT(tmp).type == AU0828_VMUX_TELEVISION) ||
-	    (AUVI_INPUT(tmp).type == AU0828_VMUX_CABLE))
+	    (AUVI_INPUT(tmp).type == AU0828_VMUX_CABLE)) {
 		input->type |= V4L2_INPUT_TYPE_TUNER;
-	else
+		input->audioset = 1;
+	} else {
 		input->type |= V4L2_INPUT_TYPE_CAMERA;
+		input->audioset = 2;
+	}
 
 	input->std = dev->vdev->tvnorms;
 
@@ -1386,32 +1433,25 @@ static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
 	return 0;
 }
 
-static int vidioc_s_input(struct file *file, void *priv, unsigned int index)
+static void au0828_s_input(struct au0828_dev *dev, int index)
 {
-	struct au0828_fh *fh = priv;
-	struct au0828_dev *dev = fh->dev;
 	int i;
 
-	dprintk(1, "VIDIOC_S_INPUT in function %s, input=%d\n", __func__,
-		index);
-	if (index >= AU0828_MAX_INPUT)
-		return -EINVAL;
-	if (AUVI_INPUT(index).type == 0)
-		return -EINVAL;
-	dev->ctrl_input = index;
-
 	switch (AUVI_INPUT(index).type) {
 	case AU0828_VMUX_SVIDEO:
 		dev->input_type = AU0828_VMUX_SVIDEO;
+		dev->ctrl_ainput = 1;
 		break;
 	case AU0828_VMUX_COMPOSITE:
 		dev->input_type = AU0828_VMUX_COMPOSITE;
+		dev->ctrl_ainput = 1;
 		break;
 	case AU0828_VMUX_TELEVISION:
 		dev->input_type = AU0828_VMUX_TELEVISION;
+		dev->ctrl_ainput = 0;
 		break;
 	default:
-		dprintk(1, "VIDIOC_S_INPUT unknown input type set [%d]\n",
+		dprintk(1, "unknown input type set [%d]\n",
 			AUVI_INPUT(index).type);
 		break;
 	}
@@ -1442,55 +1482,60 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int index)
 
 	v4l2_device_call_all(&dev->v4l2_dev, 0, audio, s_routing,
 			AUVI_INPUT(index).amux, 0, 0);
-	return 0;
 }
 
-static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
+static int vidioc_s_input(struct file *file, void *priv, unsigned int index)
 {
 	struct au0828_fh *fh = priv;
 	struct au0828_dev *dev = fh->dev;
-	unsigned int index = a->index;
 
+	dprintk(1, "VIDIOC_S_INPUT in function %s, input=%d\n", __func__,
+		index);
+	if (index >= AU0828_MAX_INPUT)
+		return -EINVAL;
+	if (AUVI_INPUT(index).type == 0)
+		return -EINVAL;
+	dev->ctrl_input = index;
+	au0828_s_input(dev, index);
+	return 0;
+}
+
+static int vidioc_enumaudio(struct file *file, void *priv, struct v4l2_audio *a)
+{
 	if (a->index > 1)
 		return -EINVAL;
 
-	index = dev->ctrl_ainput;
-	if (index == 0)
+	if (a->index == 0)
 		strcpy(a->name, "Television");
 	else
 		strcpy(a->name, "Line in");
 
 	a->capability = V4L2_AUDCAP_STEREO;
-	a->index = index;
 	return 0;
 }
 
-static int vidioc_s_audio(struct file *file, void *priv, const struct v4l2_audio *a)
+static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
 {
 	struct au0828_fh *fh = priv;
 	struct au0828_dev *dev = fh->dev;
-	if (a->index != dev->ctrl_ainput)
-		return -EINVAL;
-	return 0;
-}
 
-static int vidioc_g_ctrl(struct file *file, void *priv,
-			 struct v4l2_control *ctrl)
-{
-	struct au0828_fh *fh = priv;
-	struct au0828_dev *dev = fh->dev;
+	a->index = dev->ctrl_ainput;
+	if (a->index == 0)
+		strcpy(a->name, "Television");
+	else
+		strcpy(a->name, "Line in");
 
-	v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_ctrl, ctrl);
+	a->capability = V4L2_AUDCAP_STEREO;
 	return 0;
-
 }
 
-static int vidioc_s_ctrl(struct file *file, void *priv,
-				struct v4l2_control *ctrl)
+static int vidioc_s_audio(struct file *file, void *priv, const struct v4l2_audio *a)
 {
 	struct au0828_fh *fh = priv;
 	struct au0828_dev *dev = fh->dev;
-	v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_ctrl, ctrl);
+
+	if (a->index != dev->ctrl_ainput)
+		return -EINVAL;
 	return 0;
 }
 
@@ -1503,12 +1548,16 @@ static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
 		return -EINVAL;
 
 	strcpy(t->name, "Auvitek tuner");
+
+	au0828_init_tuner(dev);
+	i2c_gate_ctrl(dev, 1);
 	v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t);
+	i2c_gate_ctrl(dev, 0);
 	return 0;
 }
 
 static int vidioc_s_tuner(struct file *file, void *priv,
-				struct v4l2_tuner *t)
+				const struct v4l2_tuner *t)
 {
 	struct au0828_fh *fh = priv;
 	struct au0828_dev *dev = fh->dev;
@@ -1516,15 +1565,10 @@ static int vidioc_s_tuner(struct file *file, void *priv,
 	if (t->index != 0)
 		return -EINVAL;
 
-	t->type = V4L2_TUNER_ANALOG_TV;
-
-	if (dev->dvb.frontend && dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl)
-		dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl(dev->dvb.frontend, 1);
-
+	au0828_init_tuner(dev);
+	i2c_gate_ctrl(dev, 1);
 	v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t);
-
-	if (dev->dvb.frontend && dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl)
-		dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl(dev->dvb.frontend, 0);
+	i2c_gate_ctrl(dev, 0);
 
 	dprintk(1, "VIDIOC_S_TUNER: signal = %x, afc = %x\n", t->signal,
 		t->afc);
@@ -1539,40 +1583,31 @@ static int vidioc_g_frequency(struct file *file, void *priv,
 	struct au0828_fh *fh = priv;
 	struct au0828_dev *dev = fh->dev;
 
-	freq->type = V4L2_TUNER_ANALOG_TV;
+	if (freq->tuner != 0)
+		return -EINVAL;
 	freq->frequency = dev->ctrl_freq;
 	return 0;
 }
 
 static int vidioc_s_frequency(struct file *file, void *priv,
-				struct v4l2_frequency *freq)
+				const struct v4l2_frequency *freq)
 {
 	struct au0828_fh *fh = priv;
 	struct au0828_dev *dev = fh->dev;
+	struct v4l2_frequency new_freq = *freq;
 
 	if (freq->tuner != 0)
 		return -EINVAL;
-	if (freq->type != V4L2_TUNER_ANALOG_TV)
-		return -EINVAL;
-
-	dev->ctrl_freq = freq->frequency;
 
-	if (dev->dvb.frontend && dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl)
-		dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl(dev->dvb.frontend, 1);
-
-	if (dev->std_set_in_tuner_core == 0) {
-	  /* If we've never sent the standard in tuner core, do so now.  We
-	     don't do this at device probe because we don't want to incur
-	     the cost of a firmware load */
-	  v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std,
-			       dev->vdev->tvnorms);
-	  dev->std_set_in_tuner_core = 1;
-	}
+	au0828_init_tuner(dev);
+	i2c_gate_ctrl(dev, 1);
 
 	v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, freq);
+	/* Get the actual set (and possibly clamped) frequency */
+	v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_frequency, &new_freq);
+	dev->ctrl_freq = new_freq.frequency;
 
-	if (dev->dvb.frontend && dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl)
-		dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl(dev->dvb.frontend, 0);
+	i2c_gate_ctrl(dev, 0);
 
 	au0828_analog_stream_reset(dev);
 
@@ -1598,6 +1633,7 @@ static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv,
 	format->fmt.vbi.count[1] = dev->vbi_height;
 	format->fmt.vbi.start[0] = 21;
 	format->fmt.vbi.start[1] = 284;
+	memset(format->fmt.vbi.reserved, 0, sizeof(format->fmt.vbi.reserved));
 
 	return 0;
 }
@@ -1664,6 +1700,7 @@ static int vidioc_streamon(struct file *file, void *priv,
 	if (unlikely(!res_get(fh, get_ressource(fh))))
 		return -EBUSY;
 
+	au0828_init_tuner(dev);
 	if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
 		au0828_analog_stream_enable(dev);
 		v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 1);
@@ -1756,7 +1793,7 @@ static int vidioc_g_register(struct file *file, void *priv,
 }
 
 static int vidioc_s_register(struct file *file, void *priv,
-			     struct v4l2_dbg_register *reg)
+			     const struct v4l2_dbg_register *reg)
 {
 	struct au0828_fh *fh = priv;
 	struct au0828_dev *dev = fh->dev;
@@ -1773,6 +1810,15 @@ static int vidioc_s_register(struct file *file, void *priv,
 }
 #endif
 
+static int vidioc_log_status(struct file *file, void *fh)
+{
+	struct video_device *vdev = video_devdata(file);
+
+	v4l2_ctrl_log_status(file, fh);
+	v4l2_device_call_all(vdev->v4l2_dev, 0, core, log_status);
+	return 0;
+}
+
 static int vidioc_reqbufs(struct file *file, void *priv,
 			  struct v4l2_requestbuffers *rb)
 {
@@ -1872,7 +1918,9 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = {
 	.vidioc_try_fmt_vid_cap     = vidioc_try_fmt_vid_cap,
 	.vidioc_s_fmt_vid_cap       = vidioc_s_fmt_vid_cap,
 	.vidioc_g_fmt_vbi_cap       = vidioc_g_fmt_vbi_cap,
+	.vidioc_try_fmt_vbi_cap     = vidioc_g_fmt_vbi_cap,
 	.vidioc_s_fmt_vbi_cap       = vidioc_g_fmt_vbi_cap,
+	.vidioc_enumaudio           = vidioc_enumaudio,
 	.vidioc_g_audio             = vidioc_g_audio,
 	.vidioc_s_audio             = vidioc_s_audio,
 	.vidioc_cropcap             = vidioc_cropcap,
@@ -1881,12 +1929,10 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = {
 	.vidioc_qbuf                = vidioc_qbuf,
 	.vidioc_dqbuf               = vidioc_dqbuf,
 	.vidioc_s_std               = vidioc_s_std,
+	.vidioc_g_std               = vidioc_g_std,
 	.vidioc_enum_input          = vidioc_enum_input,
 	.vidioc_g_input             = vidioc_g_input,
 	.vidioc_s_input             = vidioc_s_input,
-	.vidioc_queryctrl           = vidioc_queryctrl,
-	.vidioc_g_ctrl              = vidioc_g_ctrl,
-	.vidioc_s_ctrl              = vidioc_s_ctrl,
 	.vidioc_streamon            = vidioc_streamon,
 	.vidioc_streamoff           = vidioc_streamoff,
 	.vidioc_g_tuner             = vidioc_g_tuner,
@@ -1898,6 +1944,9 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = {
 	.vidioc_s_register          = vidioc_s_register,
 #endif
 	.vidioc_g_chip_ident        = vidioc_g_chip_ident,
+	.vidioc_log_status	    = vidioc_log_status,
+	.vidioc_subscribe_event     = v4l2_ctrl_subscribe_event,
+	.vidioc_unsubscribe_event   = v4l2_event_unsubscribe,
 };
 
 static const struct video_device au0828_video_template = {
@@ -1905,7 +1954,6 @@ static const struct video_device au0828_video_template = {
 	.release                    = video_device_release,
 	.ioctl_ops 		    = &video_ioctl_ops,
 	.tvnorms                    = V4L2_STD_NTSC_M,
-	.current_norm               = V4L2_STD_NTSC_M,
 };
 
 /**************************************************************************/
@@ -1972,7 +2020,12 @@ int au0828_analog_register(struct au0828_dev *dev,
 	dev->field_size = dev->width * dev->height;
 	dev->frame_size = dev->field_size << 1;
 	dev->bytesperline = dev->width << 1;
+	dev->vbi_width = 720;
+	dev->vbi_height = 1;
 	dev->ctrl_ainput = 0;
+	dev->ctrl_freq = 960;
+	dev->std = V4L2_STD_NTSC_M;
+	au0828_s_input(dev, 0);
 
 	/* allocate and fill v4l2 video struct */
 	dev->vdev = video_device_alloc();
@@ -1991,14 +2044,16 @@ int au0828_analog_register(struct au0828_dev *dev,
 
 	/* Fill the video capture device struct */
 	*dev->vdev = au0828_video_template;
-	dev->vdev->parent = &dev->usbdev->dev;
+	dev->vdev->v4l2_dev = &dev->v4l2_dev;
 	dev->vdev->lock = &dev->lock;
+	set_bit(V4L2_FL_USE_FH_PRIO, &dev->vdev->flags);
 	strcpy(dev->vdev->name, "au0828a video");
 
 	/* Setup the VBI device */
 	*dev->vbi_dev = au0828_video_template;
-	dev->vbi_dev->parent = &dev->usbdev->dev;
+	dev->vbi_dev->v4l2_dev = &dev->v4l2_dev;
 	dev->vbi_dev->lock = &dev->lock;
+	set_bit(V4L2_FL_USE_FH_PRIO, &dev->vbi_dev->flags);
 	strcpy(dev->vbi_dev->name, "au0828a vbi");
 
 	/* Register the v4l2 device */
diff --git a/drivers/media/usb/au0828/au0828.h b/drivers/media/usb/au0828/au0828.h
index e579ff6..ef1f57f 100644
--- a/drivers/media/usb/au0828/au0828.h
+++ b/drivers/media/usb/au0828/au0828.h
@@ -28,6 +28,8 @@
 #include <linux/videodev2.h>
 #include <media/videobuf-vmalloc.h>
 #include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-fh.h>
 
 /* DVB */
 #include "demux.h"
@@ -118,6 +120,9 @@ enum au0828_dev_state {
 };
 
 struct au0828_fh {
+	/* must be the first field of this struct! */
+	struct v4l2_fh fh;
+
 	struct au0828_dev *dev;
 	unsigned int  resources;
 
@@ -202,6 +207,7 @@ struct au0828_dev {
 #ifdef CONFIG_VIDEO_AU0828_V4L2
 	/* Analog */
 	struct v4l2_device v4l2_dev;
+	struct v4l2_ctrl_handler v4l2_ctrl_hdl;
 #endif
 	int users;
 	unsigned int resources;	/* resources in use */
@@ -216,6 +222,7 @@ struct au0828_dev {
 	int vbi_width;
 	int vbi_height;
 	u32 vbi_read;
+	v4l2_std_id std;
 	u32 field_size;
 	u32 frame_size;
 	u32 bytesperline;
diff --git a/drivers/media/usb/cx231xx/cx231xx-417.c b/drivers/media/usb/cx231xx/cx231xx-417.c
index 28688db..f548db8 100644
--- a/drivers/media/usb/cx231xx/cx231xx-417.c
+++ b/drivers/media/usb/cx231xx/cx231xx-417.c
@@ -34,11 +34,12 @@
 #include <linux/vmalloc.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-ioctl.h>
+#include <media/v4l2-event.h>
 #include <media/cx2341x.h>
+#include <media/tuner.h>
 #include <linux/usb.h>
 
 #include "cx231xx.h"
-/*#include "cx23885-ioctl.h"*/
 
 #define CX231xx_FIRM_IMAGE_SIZE 376836
 #define CX231xx_FIRM_IMAGE_NAME "v4l-cx23885-enc.fw"
@@ -75,9 +76,11 @@
 static unsigned int mpegbufs = 8;
 module_param(mpegbufs, int, 0644);
 MODULE_PARM_DESC(mpegbufs, "number of mpeg buffers, range 2-32");
+
 static unsigned int mpeglines = 128;
 module_param(mpeglines, int, 0644);
 MODULE_PARM_DESC(mpeglines, "number of lines in an MPEG buffer, range 2-32");
+
 static unsigned int mpeglinesize = 512;
 module_param(mpeglinesize, int, 0644);
 MODULE_PARM_DESC(mpeglinesize,
@@ -86,10 +89,10 @@ MODULE_PARM_DESC(mpeglinesize,
 static unsigned int v4l_debug = 1;
 module_param(v4l_debug, int, 0644);
 MODULE_PARM_DESC(v4l_debug, "enable V4L debug messages");
-struct cx231xx_dmaqueue *dma_qq;
+
 #define dprintk(level, fmt, arg...)\
 	do { if (v4l_debug >= level) \
-		printk(KERN_INFO "%s: " fmt, \
+		pr_info("%s: " fmt, \
 		(dev) ? dev->name : "cx231xx[?]", ## arg); \
 	} while (0)
 
@@ -131,11 +134,13 @@ static struct cx231xx_tvnorm cx231xx_tvnorms[] = {
 };
 
 /* ------------------------------------------------------------------ */
+
 enum cx231xx_capture_type {
 	CX231xx_MPEG_CAPTURE,
 	CX231xx_RAW_CAPTURE,
 	CX231xx_RAW_PASSTHRU_CAPTURE
 };
+
 enum cx231xx_capture_bits {
 	CX231xx_RAW_BITS_NONE             = 0x00,
 	CX231xx_RAW_BITS_YUV_CAPTURE      = 0x01,
@@ -144,33 +149,40 @@ enum cx231xx_capture_bits {
 	CX231xx_RAW_BITS_PASSTHRU_CAPTURE = 0x08,
 	CX231xx_RAW_BITS_TO_HOST_CAPTURE  = 0x10
 };
+
 enum cx231xx_capture_end {
 	CX231xx_END_AT_GOP, /* stop at the end of gop, generate irq */
 	CX231xx_END_NOW, /* stop immediately, no irq */
 };
+
 enum cx231xx_framerate {
 	CX231xx_FRAMERATE_NTSC_30, /* NTSC: 30fps */
 	CX231xx_FRAMERATE_PAL_25   /* PAL: 25fps */
 };
+
 enum cx231xx_stream_port {
 	CX231xx_OUTPUT_PORT_MEMORY,
 	CX231xx_OUTPUT_PORT_STREAMING,
 	CX231xx_OUTPUT_PORT_SERIAL
 };
+
 enum cx231xx_data_xfer_status {
 	CX231xx_MORE_BUFFERS_FOLLOW,
 	CX231xx_LAST_BUFFER,
 };
+
 enum cx231xx_picture_mask {
 	CX231xx_PICTURE_MASK_NONE,
 	CX231xx_PICTURE_MASK_I_FRAMES,
 	CX231xx_PICTURE_MASK_I_P_FRAMES = 0x3,
 	CX231xx_PICTURE_MASK_ALL_FRAMES = 0x7,
 };
+
 enum cx231xx_vbi_mode_bits {
 	CX231xx_VBI_BITS_SLICED,
 	CX231xx_VBI_BITS_RAW,
 };
+
 enum cx231xx_vbi_insertion_bits {
 	CX231xx_VBI_BITS_INSERT_IN_XTENSION_USR_DATA,
 	CX231xx_VBI_BITS_INSERT_IN_PRIVATE_PACKETS = 0x1 << 1,
@@ -178,56 +190,69 @@ enum cx231xx_vbi_insertion_bits {
 	CX231xx_VBI_BITS_SEPARATE_STREAM_USR_DATA = 0x4 << 1,
 	CX231xx_VBI_BITS_SEPARATE_STREAM_PRV_DATA = 0x5 << 1,
 };
+
 enum cx231xx_dma_unit {
 	CX231xx_DMA_BYTES,
 	CX231xx_DMA_FRAMES,
 };
+
 enum cx231xx_dma_transfer_status_bits {
 	CX231xx_DMA_TRANSFER_BITS_DONE = 0x01,
 	CX231xx_DMA_TRANSFER_BITS_ERROR = 0x04,
 	CX231xx_DMA_TRANSFER_BITS_LL_ERROR = 0x10,
 };
+
 enum cx231xx_pause {
 	CX231xx_PAUSE_ENCODING,
 	CX231xx_RESUME_ENCODING,
 };
+
 enum cx231xx_copyright {
 	CX231xx_COPYRIGHT_OFF,
 	CX231xx_COPYRIGHT_ON,
 };
+
 enum cx231xx_notification_type {
 	CX231xx_NOTIFICATION_REFRESH,
 };
+
 enum cx231xx_notification_status {
 	CX231xx_NOTIFICATION_OFF,
 	CX231xx_NOTIFICATION_ON,
 };
+
 enum cx231xx_notification_mailbox {
 	CX231xx_NOTIFICATION_NO_MAILBOX = -1,
 };
+
 enum cx231xx_field1_lines {
 	CX231xx_FIELD1_SAA7114 = 0x00EF, /* 239 */
 	CX231xx_FIELD1_SAA7115 = 0x00F0, /* 240 */
 	CX231xx_FIELD1_MICRONAS = 0x0105, /* 261 */
 };
+
 enum cx231xx_field2_lines {
 	CX231xx_FIELD2_SAA7114 = 0x00EF, /* 239 */
 	CX231xx_FIELD2_SAA7115 = 0x00F0, /* 240 */
 	CX231xx_FIELD2_MICRONAS = 0x0106, /* 262 */
 };
+
 enum cx231xx_custom_data_type {
 	CX231xx_CUSTOM_EXTENSION_USR_DATA,
 	CX231xx_CUSTOM_PRIVATE_PACKET,
 };
+
 enum cx231xx_mute {
 	CX231xx_UNMUTE,
 	CX231xx_MUTE,
 };
+
 enum cx231xx_mute_video_mask {
 	CX231xx_MUTE_VIDEO_V_MASK = 0x0000FF00,
 	CX231xx_MUTE_VIDEO_U_MASK = 0x00FF0000,
 	CX231xx_MUTE_VIDEO_Y_MASK = 0xFF000000,
 };
+
 enum cx231xx_mute_video_shift {
 	CX231xx_MUTE_VIDEO_V_SHIFT = 8,
 	CX231xx_MUTE_VIDEO_U_SHIFT = 16,
@@ -296,41 +321,43 @@ enum cx231xx_mute_video_shift {
 
 
 #define CX23417_GPIO_MASK 0xFC0003FF
-static int setITVCReg(struct cx231xx *dev, u32 gpio_direction, u32 value)
+
+static int set_itvc_reg(struct cx231xx *dev, u32 gpio_direction, u32 value)
 {
 	int status = 0;
 	u32 _gpio_direction = 0;
 
 	_gpio_direction = _gpio_direction & CX23417_GPIO_MASK;
-	_gpio_direction = _gpio_direction|gpio_direction;
+	_gpio_direction = _gpio_direction | gpio_direction;
 	status = cx231xx_send_gpio_cmd(dev, _gpio_direction,
 			 (u8 *)&value, 4, 0, 0);
 	return status;
 }
-static int getITVCReg(struct cx231xx *dev, u32 gpio_direction, u32 *pValue)
+
+static int get_itvc_reg(struct cx231xx *dev, u32 gpio_direction, u32 *val_ptr)
 {
 	int status = 0;
 	u32 _gpio_direction = 0;
 
 	_gpio_direction = _gpio_direction & CX23417_GPIO_MASK;
-	_gpio_direction = _gpio_direction|gpio_direction;
+	_gpio_direction = _gpio_direction | gpio_direction;
 
 	status = cx231xx_send_gpio_cmd(dev, _gpio_direction,
-		 (u8 *)pValue, 4, 0, 1);
+		 (u8 *)val_ptr, 4, 0, 1);
 	return status;
 }
 
-static int waitForMciComplete(struct cx231xx *dev)
+static int wait_for_mci_complete(struct cx231xx *dev)
 {
 	u32 gpio;
-	u32 gpio_driection = 0;
+	u32 gpio_direction = 0;
 	u8 count = 0;
-	getITVCReg(dev, gpio_driection, &gpio);
+	get_itvc_reg(dev, gpio_direction, &gpio);
 
 	while (!(gpio&0x020000)) {
 		msleep(10);
 
-		getITVCReg(dev, gpio_driection, &gpio);
+		get_itvc_reg(dev, gpio_direction, &gpio);
 
 		if (count++ > 100) {
 			dprintk(3, "ERROR: Timeout - gpio=%x\n", gpio);
@@ -345,57 +372,57 @@ static int mc417_register_write(struct cx231xx *dev, u16 address, u32 value)
 	u32 temp;
 	int status = 0;
 
-	temp = 0x82|MCI_REGISTER_DATA_BYTE0|((value&0x000000FF)<<8);
-	temp = temp<<10;
-	status = setITVCReg(dev, ITVC_WRITE_DIR, temp);
+	temp = 0x82 | MCI_REGISTER_DATA_BYTE0 | ((value & 0x000000FF) << 8);
+	temp = temp << 10;
+	status = set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
 	if (status < 0)
 		return status;
-	temp = temp|((0x05)<<10);
-	setITVCReg(dev, ITVC_WRITE_DIR, temp);
+	temp = temp | (0x05 << 10);
+	set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
 
 	/*write data byte 1;*/
-	temp = 0x82|MCI_REGISTER_DATA_BYTE1|(value&0x0000FF00);
-	temp = temp<<10;
-	setITVCReg(dev, ITVC_WRITE_DIR, temp);
-	temp = temp|((0x05)<<10);
-	setITVCReg(dev, ITVC_WRITE_DIR, temp);
+	temp = 0x82 | MCI_REGISTER_DATA_BYTE1 | (value & 0x0000FF00);
+	temp = temp << 10;
+	set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
+	temp = temp | (0x05 << 10);
+	set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
 
 	/*write data byte 2;*/
-	temp = 0x82|MCI_REGISTER_DATA_BYTE2|((value&0x00FF0000)>>8);
-	temp = temp<<10;
-	setITVCReg(dev, ITVC_WRITE_DIR, temp);
-	temp = temp|((0x05)<<10);
-	setITVCReg(dev, ITVC_WRITE_DIR, temp);
+	temp = 0x82 | MCI_REGISTER_DATA_BYTE2 | ((value & 0x00FF0000) >> 8);
+	temp = temp << 10;
+	set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
+	temp = temp | (0x05 << 10);
+	set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
 
 	/*write data byte 3;*/
-	temp = 0x82|MCI_REGISTER_DATA_BYTE3|((value&0xFF000000)>>16);
-	temp = temp<<10;
-	setITVCReg(dev, ITVC_WRITE_DIR, temp);
-	temp = temp|((0x05)<<10);
-	setITVCReg(dev, ITVC_WRITE_DIR, temp);
+	temp = 0x82 | MCI_REGISTER_DATA_BYTE3 | ((value & 0xFF000000) >> 16);
+	temp = temp << 10;
+	set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
+	temp = temp | (0x05 << 10);
+	set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
 
 	/*write address byte 0;*/
-	temp = 0x82|MCI_REGISTER_ADDRESS_BYTE0|((address&0x000000FF)<<8);
-	temp = temp<<10;
-	setITVCReg(dev, ITVC_WRITE_DIR, temp);
-	temp = temp|((0x05)<<10);
-	setITVCReg(dev, ITVC_WRITE_DIR, temp);
+	temp = 0x82 | MCI_REGISTER_ADDRESS_BYTE0 | ((address & 0x000000FF) << 8);
+	temp = temp << 10;
+	set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
+	temp = temp | (0x05 << 10);
+	set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
 
 	/*write address byte 1;*/
-	temp = 0x82|MCI_REGISTER_ADDRESS_BYTE1|(address&0x0000FF00);
-	temp = temp<<10;
-	setITVCReg(dev, ITVC_WRITE_DIR, temp);
-	temp = temp|((0x05)<<10);
-	setITVCReg(dev, ITVC_WRITE_DIR, temp);
+	temp = 0x82 | MCI_REGISTER_ADDRESS_BYTE1 | (address & 0x0000FF00);
+	temp = temp << 10;
+	set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
+	temp = temp | (0x05 << 10);
+	set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
 
 	/*Write that the mode is write.*/
 	temp = 0x82 | MCI_REGISTER_MODE | MCI_MODE_REGISTER_WRITE;
-	temp = temp<<10;
-	setITVCReg(dev, ITVC_WRITE_DIR, temp);
-	temp = temp|((0x05)<<10);
-	setITVCReg(dev, ITVC_WRITE_DIR, temp);
+	temp = temp << 10;
+	set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
+	temp = temp | (0x05 << 10);
+	set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
 
-	return waitForMciComplete(dev);
+	return wait_for_mci_complete(dev);
 }
 
 static int mc417_register_read(struct cx231xx *dev, u16 address, u32 *value)
@@ -407,70 +434,68 @@ static int mc417_register_read(struct cx231xx *dev, u16 address, u32 *value)
 
 	temp = 0x82 | MCI_REGISTER_ADDRESS_BYTE0 | ((address & 0x00FF) << 8);
 	temp = temp << 10;
-	setITVCReg(dev, ITVC_WRITE_DIR, temp);
+	set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
 	temp = temp | ((0x05) << 10);
-	setITVCReg(dev, ITVC_WRITE_DIR, temp);
+	set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
 
 	/*write address byte 1;*/
 	temp = 0x82 | MCI_REGISTER_ADDRESS_BYTE1 | (address & 0xFF00);
 	temp = temp << 10;
-	setITVCReg(dev, ITVC_WRITE_DIR, temp);
+	set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
 	temp = temp | ((0x05) << 10);
-	setITVCReg(dev, ITVC_WRITE_DIR, temp);
+	set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
 
 	/*write that the mode is read;*/
 	temp = 0x82 | MCI_REGISTER_MODE | MCI_MODE_REGISTER_READ;
 	temp = temp << 10;
-	setITVCReg(dev, ITVC_WRITE_DIR, temp);
+	set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
 	temp = temp | ((0x05) << 10);
-	setITVCReg(dev, ITVC_WRITE_DIR, temp);
+	set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
 
 	/*wait for the MIRDY line to be asserted ,
 	signalling that the read is done;*/
-	ret = waitForMciComplete(dev);
+	ret = wait_for_mci_complete(dev);
 
 	/*switch the DATA- GPIO to input mode;*/
 
 	/*Read data byte 0;*/
 	temp = (0x82 | MCI_REGISTER_DATA_BYTE0) << 10;
-	setITVCReg(dev, ITVC_READ_DIR, temp);
+	set_itvc_reg(dev, ITVC_READ_DIR, temp);
 	temp = ((0x81 | MCI_REGISTER_DATA_BYTE0) << 10);
-	setITVCReg(dev, ITVC_READ_DIR, temp);
-	getITVCReg(dev, ITVC_READ_DIR, &temp);
+	set_itvc_reg(dev, ITVC_READ_DIR, temp);
+	get_itvc_reg(dev, ITVC_READ_DIR, &temp);
 	return_value |= ((temp & 0x03FC0000) >> 18);
-	setITVCReg(dev, ITVC_READ_DIR, (0x87 << 10));
+	set_itvc_reg(dev, ITVC_READ_DIR, (0x87 << 10));
 
 	/* Read data byte 1;*/
 	temp = (0x82 | MCI_REGISTER_DATA_BYTE1) << 10;
-	setITVCReg(dev, ITVC_READ_DIR, temp);
+	set_itvc_reg(dev, ITVC_READ_DIR, temp);
 	temp = ((0x81 | MCI_REGISTER_DATA_BYTE1) << 10);
-	setITVCReg(dev, ITVC_READ_DIR, temp);
-	getITVCReg(dev, ITVC_READ_DIR, &temp);
+	set_itvc_reg(dev, ITVC_READ_DIR, temp);
+	get_itvc_reg(dev, ITVC_READ_DIR, &temp);
 
 	return_value |= ((temp & 0x03FC0000) >> 10);
-	setITVCReg(dev, ITVC_READ_DIR, (0x87 << 10));
+	set_itvc_reg(dev, ITVC_READ_DIR, (0x87 << 10));
 
 	/*Read data byte 2;*/
 	temp = (0x82 | MCI_REGISTER_DATA_BYTE2) << 10;
-	setITVCReg(dev, ITVC_READ_DIR, temp);
+	set_itvc_reg(dev, ITVC_READ_DIR, temp);
 	temp = ((0x81 | MCI_REGISTER_DATA_BYTE2) << 10);
-	setITVCReg(dev, ITVC_READ_DIR, temp);
-	getITVCReg(dev, ITVC_READ_DIR, &temp);
+	set_itvc_reg(dev, ITVC_READ_DIR, temp);
+	get_itvc_reg(dev, ITVC_READ_DIR, &temp);
 	return_value |= ((temp & 0x03FC0000) >> 2);
-	setITVCReg(dev, ITVC_READ_DIR, (0x87 << 10));
+	set_itvc_reg(dev, ITVC_READ_DIR, (0x87 << 10));
 
 	/*Read data byte 3;*/
 	temp = (0x82 | MCI_REGISTER_DATA_BYTE3) << 10;
-	setITVCReg(dev, ITVC_READ_DIR, temp);
+	set_itvc_reg(dev, ITVC_READ_DIR, temp);
 	temp = ((0x81 | MCI_REGISTER_DATA_BYTE3) << 10);
-	setITVCReg(dev, ITVC_READ_DIR, temp);
-	getITVCReg(dev, ITVC_READ_DIR, &temp);
+	set_itvc_reg(dev, ITVC_READ_DIR, temp);
+	get_itvc_reg(dev, ITVC_READ_DIR, &temp);
 	return_value |= ((temp & 0x03FC0000) << 6);
-	setITVCReg(dev, ITVC_READ_DIR, (0x87 << 10));
+	set_itvc_reg(dev, ITVC_READ_DIR, (0x87 << 10));
 
 	*value  = return_value;
-
-
 	return ret;
 }
 
@@ -481,59 +506,59 @@ static int mc417_memory_write(struct cx231xx *dev, u32 address, u32 value)
 	u32 temp;
 	int ret = 0;
 
-	temp = 0x82 | MCI_MEMORY_DATA_BYTE0|((value & 0x000000FF) << 8);
+	temp = 0x82 | MCI_MEMORY_DATA_BYTE0 | ((value & 0x000000FF) << 8);
 	temp = temp << 10;
-	ret = setITVCReg(dev, ITVC_WRITE_DIR, temp);
+	ret = set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
 	if (ret < 0)
 		return ret;
-	temp = temp | ((0x05) << 10);
-	setITVCReg(dev, ITVC_WRITE_DIR, temp);
+	temp = temp | (0x05 << 10);
+	set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
 
 	/*write data byte 1;*/
 	temp = 0x82 | MCI_MEMORY_DATA_BYTE1 | (value & 0x0000FF00);
 	temp = temp << 10;
-	setITVCReg(dev, ITVC_WRITE_DIR, temp);
-	temp = temp | ((0x05) << 10);
-	setITVCReg(dev, ITVC_WRITE_DIR, temp);
+	set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
+	temp = temp | (0x05 << 10);
+	set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
 
 	/*write data byte 2;*/
-	temp = 0x82|MCI_MEMORY_DATA_BYTE2|((value&0x00FF0000)>>8);
-	temp = temp<<10;
-	setITVCReg(dev, ITVC_WRITE_DIR, temp);
-	temp = temp|((0x05)<<10);
-	setITVCReg(dev, ITVC_WRITE_DIR, temp);
+	temp = 0x82 | MCI_MEMORY_DATA_BYTE2 | ((value & 0x00FF0000) >> 8);
+	temp = temp << 10;
+	set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
+	temp = temp | (0x05 << 10);
+	set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
 
 	/*write data byte 3;*/
-	temp = 0x82|MCI_MEMORY_DATA_BYTE3|((value&0xFF000000)>>16);
-	temp = temp<<10;
-	setITVCReg(dev, ITVC_WRITE_DIR, temp);
-	temp = temp|((0x05)<<10);
-	setITVCReg(dev, ITVC_WRITE_DIR, temp);
+	temp = 0x82 | MCI_MEMORY_DATA_BYTE3 | ((value & 0xFF000000) >> 16);
+	temp = temp << 10;
+	set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
+	temp = temp | (0x05 << 10);
+	set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
 
 	/* write address byte 2;*/
-	temp = 0x82|MCI_MEMORY_ADDRESS_BYTE2 | MCI_MODE_MEMORY_WRITE |
-		((address & 0x003F0000)>>8);
-	temp = temp<<10;
-	setITVCReg(dev, ITVC_WRITE_DIR, temp);
-	temp = temp|((0x05)<<10);
-	setITVCReg(dev, ITVC_WRITE_DIR, temp);
+	temp = 0x82 | MCI_MEMORY_ADDRESS_BYTE2 | MCI_MODE_MEMORY_WRITE |
+		((address & 0x003F0000) >> 8);
+	temp = temp << 10;
+	set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
+	temp = temp | (0x05 << 10);
+	set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
 
 	/* write address byte 1;*/
-	temp = 0x82|MCI_MEMORY_ADDRESS_BYTE1 | (address & 0xFF00);
-	temp = temp<<10;
-	setITVCReg(dev, ITVC_WRITE_DIR, temp);
-	temp = temp|((0x05)<<10);
-	setITVCReg(dev, ITVC_WRITE_DIR, temp);
+	temp = 0x82 | MCI_MEMORY_ADDRESS_BYTE1 | (address & 0xFF00);
+	temp = temp << 10;
+	set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
+	temp = temp | (0x05 << 10);
+	set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
 
 	/* write address byte 0;*/
-	temp = 0x82|MCI_MEMORY_ADDRESS_BYTE0|((address & 0x00FF)<<8);
-	temp = temp<<10;
-	setITVCReg(dev, ITVC_WRITE_DIR, temp);
-	temp = temp|((0x05)<<10);
-	setITVCReg(dev, ITVC_WRITE_DIR, temp);
+	temp = 0x82 | MCI_MEMORY_ADDRESS_BYTE0 | ((address & 0x00FF) << 8);
+	temp = temp << 10;
+	set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
+	temp = temp | (0x05 << 10);
+	set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
 
 	/*wait for MIRDY line;*/
-	waitForMciComplete(dev);
+	wait_for_mci_complete(dev);
 
 	return 0;
 }
@@ -545,68 +570,68 @@ static int mc417_memory_read(struct cx231xx *dev, u32 address, u32 *value)
 	int ret = 0;
 
 	/*write address byte 2;*/
-	temp = 0x82|MCI_MEMORY_ADDRESS_BYTE2 | MCI_MODE_MEMORY_READ |
-		((address & 0x003F0000)>>8);
-	temp = temp<<10;
-	ret = setITVCReg(dev, ITVC_WRITE_DIR, temp);
+	temp = 0x82 | MCI_MEMORY_ADDRESS_BYTE2 | MCI_MODE_MEMORY_READ |
+		((address & 0x003F0000) >> 8);
+	temp = temp << 10;
+	ret = set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
 	if (ret < 0)
 		return ret;
-	temp = temp|((0x05)<<10);
-	setITVCReg(dev, ITVC_WRITE_DIR, temp);
+	temp = temp | (0x05 << 10);
+	set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
 
 	/*write address byte 1*/
-	temp = 0x82|MCI_MEMORY_ADDRESS_BYTE1 | (address & 0xFF00);
-	temp = temp<<10;
-	setITVCReg(dev, ITVC_WRITE_DIR, temp);
-	temp = temp|((0x05)<<10);
-	setITVCReg(dev, ITVC_WRITE_DIR, temp);
+	temp = 0x82 | MCI_MEMORY_ADDRESS_BYTE1 | (address & 0xFF00);
+	temp = temp << 10;
+	set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
+	temp = temp | (0x05 << 10);
+	set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
 
 	/*write address byte 0*/
-	temp = 0x82|MCI_MEMORY_ADDRESS_BYTE0 | ((address & 0x00FF)<<8);
-	temp = temp<<10;
-	setITVCReg(dev, ITVC_WRITE_DIR, temp);
-	temp = temp|((0x05)<<10);
-	setITVCReg(dev, ITVC_WRITE_DIR, temp);
+	temp = 0x82 | MCI_MEMORY_ADDRESS_BYTE0 | ((address & 0x00FF) << 8);
+	temp = temp << 10;
+	set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
+	temp = temp | (0x05 << 10);
+	set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
 
 	/*Wait for MIRDY line*/
-	ret = waitForMciComplete(dev);
+	ret = wait_for_mci_complete(dev);
 
 
 	/*Read data byte 3;*/
-	temp = (0x82|MCI_MEMORY_DATA_BYTE3)<<10;
-	setITVCReg(dev, ITVC_READ_DIR, temp);
-	temp = ((0x81|MCI_MEMORY_DATA_BYTE3)<<10);
-	setITVCReg(dev, ITVC_READ_DIR, temp);
-	getITVCReg(dev, ITVC_READ_DIR, &temp);
-	return_value |= ((temp&0x03FC0000)<<6);
-	setITVCReg(dev, ITVC_READ_DIR, (0x87<<10));
+	temp = (0x82 | MCI_MEMORY_DATA_BYTE3) << 10;
+	set_itvc_reg(dev, ITVC_READ_DIR, temp);
+	temp = ((0x81 | MCI_MEMORY_DATA_BYTE3) << 10);
+	set_itvc_reg(dev, ITVC_READ_DIR, temp);
+	get_itvc_reg(dev, ITVC_READ_DIR, &temp);
+	return_value |= ((temp & 0x03FC0000) << 6);
+	set_itvc_reg(dev, ITVC_READ_DIR, (0x87 << 10));
 
 	/*Read data byte 2;*/
-	temp = (0x82|MCI_MEMORY_DATA_BYTE2)<<10;
-	setITVCReg(dev, ITVC_READ_DIR, temp);
-	temp = ((0x81|MCI_MEMORY_DATA_BYTE2)<<10);
-	setITVCReg(dev, ITVC_READ_DIR, temp);
-	getITVCReg(dev, ITVC_READ_DIR, &temp);
-	return_value |= ((temp&0x03FC0000)>>2);
-	setITVCReg(dev, ITVC_READ_DIR, (0x87<<10));
+	temp = (0x82 | MCI_MEMORY_DATA_BYTE2) << 10;
+	set_itvc_reg(dev, ITVC_READ_DIR, temp);
+	temp = ((0x81 | MCI_MEMORY_DATA_BYTE2) << 10);
+	set_itvc_reg(dev, ITVC_READ_DIR, temp);
+	get_itvc_reg(dev, ITVC_READ_DIR, &temp);
+	return_value |= ((temp & 0x03FC0000) >> 2);
+	set_itvc_reg(dev, ITVC_READ_DIR, (0x87 << 10));
 
 	/* Read data byte 1;*/
-	temp = (0x82|MCI_MEMORY_DATA_BYTE1)<<10;
-	setITVCReg(dev, ITVC_READ_DIR, temp);
-	temp = ((0x81|MCI_MEMORY_DATA_BYTE1)<<10);
-	setITVCReg(dev, ITVC_READ_DIR, temp);
-	getITVCReg(dev, ITVC_READ_DIR, &temp);
-	return_value |= ((temp&0x03FC0000)>>10);
-	setITVCReg(dev, ITVC_READ_DIR, (0x87<<10));
+	temp = (0x82 | MCI_MEMORY_DATA_BYTE1) << 10;
+	set_itvc_reg(dev, ITVC_READ_DIR, temp);
+	temp = ((0x81 | MCI_MEMORY_DATA_BYTE1) << 10);
+	set_itvc_reg(dev, ITVC_READ_DIR, temp);
+	get_itvc_reg(dev, ITVC_READ_DIR, &temp);
+	return_value |= ((temp & 0x03FC0000) >> 10);
+	set_itvc_reg(dev, ITVC_READ_DIR, (0x87 << 10));
 
 	/*Read data byte 0;*/
-	temp = (0x82|MCI_MEMORY_DATA_BYTE0)<<10;
-	setITVCReg(dev, ITVC_READ_DIR, temp);
-	temp = ((0x81|MCI_MEMORY_DATA_BYTE0)<<10);
-	setITVCReg(dev, ITVC_READ_DIR, temp);
-	getITVCReg(dev, ITVC_READ_DIR, &temp);
-	return_value |= ((temp&0x03FC0000)>>18);
-	setITVCReg(dev, ITVC_READ_DIR, (0x87<<10));
+	temp = (0x82 | MCI_MEMORY_DATA_BYTE0) << 10;
+	set_itvc_reg(dev, ITVC_READ_DIR, temp);
+	temp = ((0x81 | MCI_MEMORY_DATA_BYTE0) << 10);
+	set_itvc_reg(dev, ITVC_READ_DIR, temp);
+	get_itvc_reg(dev, ITVC_READ_DIR, &temp);
+	return_value |= ((temp & 0x03FC0000) >> 18);
+	set_itvc_reg(dev, ITVC_READ_DIR, (0x87 << 10));
 
 	*value  = return_value;
 	return ret;
@@ -619,94 +644,91 @@ static char *cmd_to_str(int cmd)
 {
 	switch (cmd) {
 	case CX2341X_ENC_PING_FW:
-		return  "PING_FW";
+		return "PING_FW";
 	case CX2341X_ENC_START_CAPTURE:
-		return  "START_CAPTURE";
+		return "START_CAPTURE";
 	case CX2341X_ENC_STOP_CAPTURE:
-		return  "STOP_CAPTURE";
+		return "STOP_CAPTURE";
 	case CX2341X_ENC_SET_AUDIO_ID:
-		return  "SET_AUDIO_ID";
+		return "SET_AUDIO_ID";
 	case CX2341X_ENC_SET_VIDEO_ID:
-		return  "SET_VIDEO_ID";
+		return "SET_VIDEO_ID";
 	case CX2341X_ENC_SET_PCR_ID:
-		return  "SET_PCR_PID";
+		return "SET_PCR_PID";
 	case CX2341X_ENC_SET_FRAME_RATE:
-		return  "SET_FRAME_RATE";
+		return "SET_FRAME_RATE";
 	case CX2341X_ENC_SET_FRAME_SIZE:
-		return  "SET_FRAME_SIZE";
+		return "SET_FRAME_SIZE";
 	case CX2341X_ENC_SET_BIT_RATE:
-		return  "SET_BIT_RATE";
+		return "SET_BIT_RATE";
 	case CX2341X_ENC_SET_GOP_PROPERTIES:
-		return  "SET_GOP_PROPERTIES";
+		return "SET_GOP_PROPERTIES";
 	case CX2341X_ENC_SET_ASPECT_RATIO:
-		return  "SET_ASPECT_RATIO";
+		return "SET_ASPECT_RATIO";
 	case CX2341X_ENC_SET_DNR_FILTER_MODE:
-		return  "SET_DNR_FILTER_PROPS";
+		return "SET_DNR_FILTER_PROPS";
 	case CX2341X_ENC_SET_DNR_FILTER_PROPS:
-		return  "SET_DNR_FILTER_PROPS";
+		return "SET_DNR_FILTER_PROPS";
 	case CX2341X_ENC_SET_CORING_LEVELS:
-		return  "SET_CORING_LEVELS";
+		return "SET_CORING_LEVELS";
 	case CX2341X_ENC_SET_SPATIAL_FILTER_TYPE:
-		return  "SET_SPATIAL_FILTER_TYPE";
+		return "SET_SPATIAL_FILTER_TYPE";
 	case CX2341X_ENC_SET_VBI_LINE:
-		return  "SET_VBI_LINE";
+		return "SET_VBI_LINE";
 	case CX2341X_ENC_SET_STREAM_TYPE:
-		return  "SET_STREAM_TYPE";
+		return "SET_STREAM_TYPE";
 	case CX2341X_ENC_SET_OUTPUT_PORT:
-		return  "SET_OUTPUT_PORT";
+		return "SET_OUTPUT_PORT";
 	case CX2341X_ENC_SET_AUDIO_PROPERTIES:
-		return  "SET_AUDIO_PROPERTIES";
+		return "SET_AUDIO_PROPERTIES";
 	case CX2341X_ENC_HALT_FW:
-		return  "HALT_FW";
+		return "HALT_FW";
 	case CX2341X_ENC_GET_VERSION:
-		return  "GET_VERSION";
+		return "GET_VERSION";
 	case CX2341X_ENC_SET_GOP_CLOSURE:
-		return  "SET_GOP_CLOSURE";
+		return "SET_GOP_CLOSURE";
 	case CX2341X_ENC_GET_SEQ_END:
-		return  "GET_SEQ_END";
+		return "GET_SEQ_END";
 	case CX2341X_ENC_SET_PGM_INDEX_INFO:
-		return  "SET_PGM_INDEX_INFO";
+		return "SET_PGM_INDEX_INFO";
 	case CX2341X_ENC_SET_VBI_CONFIG:
-		return  "SET_VBI_CONFIG";
+		return "SET_VBI_CONFIG";
 	case CX2341X_ENC_SET_DMA_BLOCK_SIZE:
-		return  "SET_DMA_BLOCK_SIZE";
+		return "SET_DMA_BLOCK_SIZE";
 	case CX2341X_ENC_GET_PREV_DMA_INFO_MB_10:
-		return  "GET_PREV_DMA_INFO_MB_10";
+		return "GET_PREV_DMA_INFO_MB_10";
 	case CX2341X_ENC_GET_PREV_DMA_INFO_MB_9:
-		return  "GET_PREV_DMA_INFO_MB_9";
+		return "GET_PREV_DMA_INFO_MB_9";
 	case CX2341X_ENC_SCHED_DMA_TO_HOST:
-		return  "SCHED_DMA_TO_HOST";
+		return "SCHED_DMA_TO_HOST";
 	case CX2341X_ENC_INITIALIZE_INPUT:
-		return  "INITIALIZE_INPUT";
+		return "INITIALIZE_INPUT";
 	case CX2341X_ENC_SET_FRAME_DROP_RATE:
-		return  "SET_FRAME_DROP_RATE";
+		return "SET_FRAME_DROP_RATE";
 	case CX2341X_ENC_PAUSE_ENCODER:
-		return  "PAUSE_ENCODER";
+		return "PAUSE_ENCODER";
 	case CX2341X_ENC_REFRESH_INPUT:
-		return  "REFRESH_INPUT";
+		return "REFRESH_INPUT";
 	case CX2341X_ENC_SET_COPYRIGHT:
-		return  "SET_COPYRIGHT";
+		return "SET_COPYRIGHT";
 	case CX2341X_ENC_SET_EVENT_NOTIFICATION:
-		return  "SET_EVENT_NOTIFICATION";
+		return "SET_EVENT_NOTIFICATION";
 	case CX2341X_ENC_SET_NUM_VSYNC_LINES:
-		return  "SET_NUM_VSYNC_LINES";
+		return "SET_NUM_VSYNC_LINES";
 	case CX2341X_ENC_SET_PLACEHOLDER:
-		return  "SET_PLACEHOLDER";
+		return "SET_PLACEHOLDER";
 	case CX2341X_ENC_MUTE_VIDEO:
-		return  "MUTE_VIDEO";
+		return "MUTE_VIDEO";
 	case CX2341X_ENC_MUTE_AUDIO:
-		return  "MUTE_AUDIO";
+		return "MUTE_AUDIO";
 	case CX2341X_ENC_MISC:
-		return  "MISC";
+		return "MISC";
 	default:
 		return "UNKNOWN";
 	}
 }
 
-static int cx231xx_mbox_func(void *priv,
-			     u32 command,
-			     int in,
-			     int out,
+static int cx231xx_mbox_func(void *priv, u32 command, int in, int out,
 			     u32 data[CX2341X_MBOX_MAX_DATA])
 {
 	struct cx231xx *dev = priv;
@@ -721,11 +743,9 @@ static int cx231xx_mbox_func(void *priv,
 	   without side effects */
 	mc417_memory_read(dev, dev->cx23417_mailbox - 4, &value);
 	if (value != 0x12345678) {
-		dprintk(3,
-			"Firmware and/or mailbox pointer not initialized "
-			"or corrupted, signature = 0x%x, cmd = %s\n", value,
-			cmd_to_str(command));
-		return -1;
+		dprintk(3, "Firmware and/or mailbox pointer not initialized or corrupted, signature = 0x%x, cmd = %s\n",
+			value, cmd_to_str(command));
+		return -EIO;
 	}
 
 	/* This read looks at 32 bits, but flag is only 8 bits.
@@ -733,9 +753,9 @@ static int cx231xx_mbox_func(void *priv,
 	 */
 	mc417_memory_read(dev, dev->cx23417_mailbox, &flag);
 	if (flag) {
-		dprintk(3, "ERROR: Mailbox appears to be in use "
-			"(%x), cmd = %s\n", flag, cmd_to_str(command));
-		return -1;
+		dprintk(3, "ERROR: Mailbox appears to be in use (%x), cmd = %s\n",
+				flag, cmd_to_str(command));
+		return -EBUSY;
 	}
 
 	flag |= 1; /* tell 'em we're working on it */
@@ -764,7 +784,7 @@ static int cx231xx_mbox_func(void *priv,
 			break;
 		if (time_after(jiffies, timeout)) {
 			dprintk(3, "ERROR: API Mailbox timeout\n");
-			return -1;
+			return -EIO;
 		}
 		udelay(10);
 	}
@@ -781,17 +801,14 @@ static int cx231xx_mbox_func(void *priv,
 	flag = 0;
 	mc417_memory_write(dev, dev->cx23417_mailbox, flag);
 
-	return retval;
+	return 0;
 }
 
 /* We don't need to call the API often, so using just one
  * mailbox will probably suffice
  */
-static int cx231xx_api_cmd(struct cx231xx *dev,
-			   u32 command,
-			   u32 inputcnt,
-			   u32 outputcnt,
-			   ...)
+static int cx231xx_api_cmd(struct cx231xx *dev, u32 command,
+		u32 inputcnt, u32 outputcnt, ...)
 {
 	u32 data[CX2341X_MBOX_MAX_DATA];
 	va_list vargs;
@@ -813,6 +830,7 @@ static int cx231xx_api_cmd(struct cx231xx *dev,
 	return err;
 }
 
+
 static int cx231xx_find_mailbox(struct cx231xx *dev)
 {
 	u32 signature[4] = {
@@ -834,81 +852,80 @@ static int cx231xx_find_mailbox(struct cx231xx *dev)
 		else
 			signaturecnt = 0;
 		if (4 == signaturecnt) {
-			dprintk(1, "Mailbox signature found at 0x%x\n", i+1);
-			return i+1;
+			dprintk(1, "Mailbox signature found at 0x%x\n", i + 1);
+			return i + 1;
 		}
 	}
 	dprintk(3, "Mailbox signature values not found!\n");
 	return -1;
 }
 
-static void mciWriteMemoryToGPIO(struct cx231xx *dev, u32 address, u32 value,
+static void mci_write_memory_to_gpio(struct cx231xx *dev, u32 address, u32 value,
 		u32 *p_fw_image)
 {
-
 	u32 temp = 0;
 	int i = 0;
 
-	temp = 0x82|MCI_MEMORY_DATA_BYTE0|((value&0x000000FF)<<8);
-	temp = temp<<10;
+	temp = 0x82 | MCI_MEMORY_DATA_BYTE0 | ((value & 0x000000FF) << 8);
+	temp = temp << 10;
 	*p_fw_image = temp;
 	p_fw_image++;
-	temp = temp|((0x05)<<10);
+	temp = temp | (0x05 << 10);
 	*p_fw_image = temp;
 	p_fw_image++;
 
 	/*write data byte 1;*/
-	temp = 0x82|MCI_MEMORY_DATA_BYTE1|(value&0x0000FF00);
-	temp = temp<<10;
+	temp = 0x82 | MCI_MEMORY_DATA_BYTE1 | (value & 0x0000FF00);
+	temp = temp << 10;
 	*p_fw_image = temp;
 	p_fw_image++;
-	temp = temp|((0x05)<<10);
+	temp = temp | (0x05 << 10);
 	*p_fw_image = temp;
 	p_fw_image++;
 
 	/*write data byte 2;*/
-	temp = 0x82|MCI_MEMORY_DATA_BYTE2|((value&0x00FF0000)>>8);
-	temp = temp<<10;
+	temp = 0x82 | MCI_MEMORY_DATA_BYTE2 | ((value & 0x00FF0000) >> 8);
+	temp = temp << 10;
 	*p_fw_image = temp;
 	p_fw_image++;
-	temp = temp|((0x05)<<10);
+	temp = temp | (0x05 << 10);
 	*p_fw_image = temp;
 	p_fw_image++;
 
 	/*write data byte 3;*/
-	temp = 0x82|MCI_MEMORY_DATA_BYTE3|((value&0xFF000000)>>16);
-	temp = temp<<10;
+	temp = 0x82 | MCI_MEMORY_DATA_BYTE3 | ((value & 0xFF000000) >> 16);
+	temp = temp << 10;
 	*p_fw_image = temp;
 	p_fw_image++;
-	temp = temp|((0x05)<<10);
+	temp = temp | (0x05 << 10);
 	*p_fw_image = temp;
 	p_fw_image++;
 
 	/* write address byte 2;*/
-	temp = 0x82|MCI_MEMORY_ADDRESS_BYTE2 | MCI_MODE_MEMORY_WRITE |
-		((address & 0x003F0000)>>8);
-	temp = temp<<10;
+	temp = 0x82 | MCI_MEMORY_ADDRESS_BYTE2 | MCI_MODE_MEMORY_WRITE |
+		((address & 0x003F0000) >> 8);
+	temp = temp << 10;
 	*p_fw_image = temp;
 	p_fw_image++;
-	temp = temp|((0x05)<<10);
+	temp = temp | (0x05 << 10);
 	*p_fw_image = temp;
 	p_fw_image++;
 
 	/* write address byte 1;*/
-	temp = 0x82|MCI_MEMORY_ADDRESS_BYTE1 | (address & 0xFF00);
-	temp = temp<<10;
+	temp = 0x82 | MCI_MEMORY_ADDRESS_BYTE1 | (address & 0xFF00);
+	temp = temp << 10;
 	*p_fw_image = temp;
 	p_fw_image++;
-	temp = temp|((0x05)<<10);
+	temp = temp | (0x05 << 10);
 	*p_fw_image = temp;
 	p_fw_image++;
 
 	/* write address byte 0;*/
-	temp = 0x82|MCI_MEMORY_ADDRESS_BYTE0|((address & 0x00FF)<<8);
-	temp = temp<<10;
+	temp = 0x82 | MCI_MEMORY_ADDRESS_BYTE0 | ((address & 0x00FF) << 8);
+	temp = temp << 10;
 	*p_fw_image = temp;
 	p_fw_image++;
-	temp = temp|((0x05)<<10);
+	temp = temp | (0x05 << 10);
 	*p_fw_image = temp;
 	p_fw_image++;
 
@@ -971,8 +988,7 @@ static int cx231xx_load_firmware(struct cx231xx *dev)
 		IVTV_REG_APU, 0);
 
 	if (retval != 0) {
-		printk(KERN_ERR "%s: Error with mc417_register_write\n",
-			__func__);
+		pr_err("%s: Error with mc417_register_write\n", __func__);
 		return -1;
 	}
 
@@ -980,25 +996,21 @@ static int cx231xx_load_firmware(struct cx231xx *dev)
 				  &dev->udev->dev);
 
 	if (retval != 0) {
-		printk(KERN_ERR
-			"ERROR: Hotplug firmware request failed (%s).\n",
+		pr_err("ERROR: Hotplug firmware request failed (%s).\n",
 			CX231xx_FIRM_IMAGE_NAME);
-		printk(KERN_ERR "Please fix your hotplug setup, the board will "
-			"not work without firmware loaded!\n");
+		pr_err("Please fix your hotplug setup, the board will not work without firmware loaded!\n");
 		return -1;
 	}
 
 	if (firmware->size != CX231xx_FIRM_IMAGE_SIZE) {
-		printk(KERN_ERR "ERROR: Firmware size mismatch "
-			"(have %zd, expected %d)\n",
+		pr_err("ERROR: Firmware size mismatch (have %zd, expected %d)\n",
 			firmware->size, CX231xx_FIRM_IMAGE_SIZE);
 		release_firmware(firmware);
 		return -1;
 	}
 
 	if (0 != memcmp(firmware->data, magic, 8)) {
-		printk(KERN_ERR
-			"ERROR: Firmware magic mismatch, wrong file?\n");
+		pr_err("ERROR: Firmware magic mismatch, wrong file?\n");
 		release_firmware(firmware);
 		return -1;
 	}
@@ -1013,7 +1025,7 @@ static int cx231xx_load_firmware(struct cx231xx *dev)
 		 transfer_size += 4) {
 		fw_data = *p_fw_data;
 
-		 mciWriteMemoryToGPIO(dev, address, fw_data, p_current_fw);
+		mci_write_memory_to_gpio(dev, address, fw_data, p_current_fw);
 		address = address + 1;
 		p_current_fw += 20;
 		p_fw_data += 1;
@@ -1045,7 +1057,7 @@ static int cx231xx_load_firmware(struct cx231xx *dev)
 	retval |= mc417_register_write(dev, IVTV_REG_HW_BLOCKS,
 		IVTV_CMD_HW_BLOCKS_RST);
 	if (retval < 0) {
-		printk(KERN_ERR "%s: Error with mc417_register_write\n",
+		pr_err("%s: Error with mc417_register_write\n",
 			__func__);
 		return retval;
 	}
@@ -1057,7 +1069,7 @@ static int cx231xx_load_firmware(struct cx231xx *dev)
 	retval |= mc417_register_write(dev, IVTV_REG_VPU, value & 0xFFFFFFE8);
 
 	if (retval < 0) {
-		printk(KERN_ERR "%s: Error with mc417_register_write\n",
+		pr_err("%s: Error with mc417_register_write\n",
 			__func__);
 		return retval;
 	}
@@ -1082,10 +1094,10 @@ static void cx231xx_codec_settings(struct cx231xx *dev)
 	cx231xx_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0,
 				dev->ts1.height, dev->ts1.width);
 
-	dev->mpeg_params.width = dev->ts1.width;
-	dev->mpeg_params.height = dev->ts1.height;
+	dev->mpeg_ctrl_handler.width = dev->ts1.width;
+	dev->mpeg_ctrl_handler.height = dev->ts1.height;
 
-	cx2341x_update(dev, cx231xx_mbox_func, NULL, &dev->mpeg_params);
+	cx2341x_handler_setup(&dev->mpeg_ctrl_handler);
 
 	cx231xx_api_cmd(dev, CX2341X_ENC_MISC, 2, 0, 3, 1);
 	cx231xx_api_cmd(dev, CX2341X_ENC_MISC, 2, 0, 4, 1);
@@ -1105,27 +1117,25 @@ static int cx231xx_initialize_codec(struct cx231xx *dev)
 		dprintk(2, "%s() PING OK\n", __func__);
 		retval = cx231xx_load_firmware(dev);
 		if (retval < 0) {
-			printk(KERN_ERR "%s() f/w load failed\n", __func__);
+			pr_err("%s() f/w load failed\n", __func__);
 			return retval;
 		}
 		retval = cx231xx_find_mailbox(dev);
 		if (retval < 0) {
-			printk(KERN_ERR "%s() mailbox < 0, error\n",
+			pr_err("%s() mailbox < 0, error\n",
 				__func__);
 			return -1;
 		}
 		dev->cx23417_mailbox = retval;
 		retval = cx231xx_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0);
 		if (retval < 0) {
-			printk(KERN_ERR
-				"ERROR: cx23417 firmware ping failed!\n");
+			pr_err("ERROR: cx23417 firmware ping failed!\n");
 			return -1;
 		}
 		retval = cx231xx_api_cmd(dev, CX2341X_ENC_GET_VERSION, 0, 1,
 			&version);
 		if (retval < 0) {
-			printk(KERN_ERR "ERROR: cx23417 firmware get encoder :"
-				"version failed!\n");
+			pr_err("ERROR: cx23417 firmware get encoder: version failed!\n");
 			return -1;
 		}
 		dprintk(1, "cx23417 firmware version is 0x%08x\n", version);
@@ -1134,7 +1144,7 @@ static int cx231xx_initialize_codec(struct cx231xx *dev)
 
 	for (i = 0; i < 1; i++) {
 		retval = mc417_register_read(dev, 0x20f8, &val);
-		dprintk(3, "***before enable656() VIM Capture Lines =%d ***\n",
+		dprintk(3, "***before enable656() VIM Capture Lines = %d ***\n",
 				 val);
 		if (retval < 0)
 			return retval;
@@ -1202,7 +1212,7 @@ static int cx231xx_initialize_codec(struct cx231xx *dev)
 
 	for (i = 0; i < 1; i++) {
 		mc417_register_read(dev, 0x20f8, &val);
-	dprintk(3, "***VIM Capture Lines =%d ***\n", val);
+		dprintk(3, "***VIM Capture Lines =%d ***\n", val);
 	}
 
 	return 0;
@@ -1223,6 +1233,7 @@ static int bb_buf_setup(struct videobuf_queue *q,
 
 	return 0;
 }
+
 static void free_buffer(struct videobuf_queue *vq, struct cx231xx_buffer *buf)
 {
 	struct cx231xx_fh *fh = vq->priv_data;
@@ -1249,91 +1260,85 @@ static void free_buffer(struct videobuf_queue *vq, struct cx231xx_buffer *buf)
 static void buffer_copy(struct cx231xx *dev, char *data, int len, struct urb *urb,
 		struct cx231xx_dmaqueue *dma_q)
 {
-		void *vbuf;
-		struct cx231xx_buffer *buf;
-		u32 tail_data = 0;
-		char *p_data;
-
-		if (dma_q->mpeg_buffer_done == 0) {
-			if (list_empty(&dma_q->active))
-				return;
-
-			buf = list_entry(dma_q->active.next,
-					struct cx231xx_buffer, vb.queue);
-			dev->video_mode.isoc_ctl.buf = buf;
-			dma_q->mpeg_buffer_done = 1;
-		}
-		/* Fill buffer */
-		buf = dev->video_mode.isoc_ctl.buf;
-		vbuf = videobuf_to_vmalloc(&buf->vb);
-
-		if ((dma_q->mpeg_buffer_completed+len) <
-		   mpeglines*mpeglinesize) {
-			if (dma_q->add_ps_package_head ==
-			   CX231XX_NEED_ADD_PS_PACKAGE_HEAD) {
-				memcpy(vbuf+dma_q->mpeg_buffer_completed,
-				       dma_q->ps_head, 3);
-				dma_q->mpeg_buffer_completed =
-				  dma_q->mpeg_buffer_completed + 3;
-				dma_q->add_ps_package_head =
-				  CX231XX_NONEED_PS_PACKAGE_HEAD;
-			}
-			memcpy(vbuf+dma_q->mpeg_buffer_completed, data, len);
-			dma_q->mpeg_buffer_completed =
-			  dma_q->mpeg_buffer_completed + len;
-		} else {
-			dma_q->mpeg_buffer_done = 0;
-
-			tail_data =
-			  mpeglines*mpeglinesize - dma_q->mpeg_buffer_completed;
-			memcpy(vbuf+dma_q->mpeg_buffer_completed,
-			       data, tail_data);
-
-			buf->vb.state = VIDEOBUF_DONE;
-			buf->vb.field_count++;
-			v4l2_get_timestamp(&buf->vb.ts);
-			list_del(&buf->vb.queue);
-			wake_up(&buf->vb.done);
-			dma_q->mpeg_buffer_completed = 0;
-
-			if (len - tail_data > 0) {
-				p_data = data + tail_data;
-				dma_q->left_data_count = len - tail_data;
-				memcpy(dma_q->p_left_data,
-				       p_data, len - tail_data);
-			}
-
-		}
-
-	    return;
-}
-
-static void buffer_filled(char *data, int len, struct urb *urb,
-		struct cx231xx_dmaqueue *dma_q)
-{
-		void *vbuf;
-		struct cx231xx_buffer *buf;
+	void *vbuf;
+	struct cx231xx_buffer *buf;
+	u32 tail_data = 0;
+	char *p_data;
 
+	if (dma_q->mpeg_buffer_done == 0) {
 		if (list_empty(&dma_q->active))
 			return;
 
-
 		buf = list_entry(dma_q->active.next,
-				 struct cx231xx_buffer, vb.queue);
+				struct cx231xx_buffer, vb.queue);
+		dev->video_mode.isoc_ctl.buf = buf;
+		dma_q->mpeg_buffer_done = 1;
+	}
+	/* Fill buffer */
+	buf = dev->video_mode.isoc_ctl.buf;
+	vbuf = videobuf_to_vmalloc(&buf->vb);
+
+	if ((dma_q->mpeg_buffer_completed+len) <
+			mpeglines*mpeglinesize) {
+		if (dma_q->add_ps_package_head ==
+				CX231XX_NEED_ADD_PS_PACKAGE_HEAD) {
+			memcpy(vbuf+dma_q->mpeg_buffer_completed,
+					dma_q->ps_head, 3);
+			dma_q->mpeg_buffer_completed =
+				dma_q->mpeg_buffer_completed + 3;
+			dma_q->add_ps_package_head =
+				CX231XX_NONEED_PS_PACKAGE_HEAD;
+		}
+		memcpy(vbuf+dma_q->mpeg_buffer_completed, data, len);
+		dma_q->mpeg_buffer_completed =
+			dma_q->mpeg_buffer_completed + len;
+	} else {
+		dma_q->mpeg_buffer_done = 0;
 
+		tail_data =
+			mpeglines*mpeglinesize - dma_q->mpeg_buffer_completed;
+		memcpy(vbuf+dma_q->mpeg_buffer_completed,
+				data, tail_data);
 
-		/* Fill buffer */
-		vbuf = videobuf_to_vmalloc(&buf->vb);
-		memcpy(vbuf, data, len);
 		buf->vb.state = VIDEOBUF_DONE;
 		buf->vb.field_count++;
 		v4l2_get_timestamp(&buf->vb.ts);
 		list_del(&buf->vb.queue);
 		wake_up(&buf->vb.done);
+		dma_q->mpeg_buffer_completed = 0;
 
-	    return;
+		if (len - tail_data > 0) {
+			p_data = data + tail_data;
+			dma_q->left_data_count = len - tail_data;
+			memcpy(dma_q->p_left_data,
+					p_data, len - tail_data);
+		}
+	}
 }
-static inline int cx231xx_isoc_copy(struct cx231xx *dev, struct urb *urb)
+
+static void buffer_filled(char *data, int len, struct urb *urb,
+		struct cx231xx_dmaqueue *dma_q)
+{
+	void *vbuf;
+	struct cx231xx_buffer *buf;
+
+	if (list_empty(&dma_q->active))
+		return;
+
+	buf = list_entry(dma_q->active.next,
+			struct cx231xx_buffer, vb.queue);
+
+	/* Fill buffer */
+	vbuf = videobuf_to_vmalloc(&buf->vb);
+	memcpy(vbuf, data, len);
+	buf->vb.state = VIDEOBUF_DONE;
+	buf->vb.field_count++;
+	v4l2_get_timestamp(&buf->vb.ts);
+	list_del(&buf->vb.queue);
+	wake_up(&buf->vb.done);
+}
+
+static int cx231xx_isoc_copy(struct cx231xx *dev, struct urb *urb)
 {
 	struct cx231xx_dmaqueue *dma_q = urb->context;
 	unsigned char *p_buffer;
@@ -1358,11 +1363,9 @@ static inline int cx231xx_isoc_copy(struct cx231xx *dev, struct urb *urb)
 
 	return 0;
 }
-static inline int cx231xx_bulk_copy(struct cx231xx *dev, struct urb *urb)
-{
 
-	/*char *outp;*/
-	/*struct cx231xx_buffer *buf;*/
+static int cx231xx_bulk_copy(struct cx231xx *dev, struct urb *urb)
+{
 	struct cx231xx_dmaqueue *dma_q = urb->context;
 	unsigned char *p_buffer, *buffer;
 	u32 buffer_size = 0;
@@ -1393,8 +1396,6 @@ static int bb_buf_prepare(struct videobuf_queue *q,
 	int rc = 0, urb_init = 0;
 	int size = fh->dev->ts1.ts_packet_size * fh->dev->ts1.ts_packet_count;
 
-	dma_qq = &dev->video_mode.vidq;
-
 	if (0 != buf->vb.baddr  &&  buf->vb.bsize < size)
 		return -EINVAL;
 	buf->vb.width = fh->dev->ts1.ts_packet_size;
@@ -1482,36 +1483,6 @@ static struct videobuf_queue_ops cx231xx_qops = {
 
 /* ------------------------------------------------------------------ */
 
-static const u32 *ctrl_classes[] = {
-	cx2341x_mpeg_ctrls,
-	NULL
-};
-
-static int cx231xx_queryctrl(struct cx231xx *dev,
-	struct v4l2_queryctrl *qctrl)
-{
-	qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id);
-	if (qctrl->id == 0)
-		return -EINVAL;
-
-	/* MPEG V4L2 controls */
-	if (cx2341x_ctrl_query(&dev->mpeg_params, qctrl))
-		qctrl->flags |= V4L2_CTRL_FLAG_DISABLED;
-
-	return 0;
-}
-
-static int cx231xx_querymenu(struct cx231xx *dev,
-	struct v4l2_querymenu *qmenu)
-{
-	struct v4l2_queryctrl qctrl;
-
-	qctrl.id = qmenu->id;
-	cx231xx_queryctrl(dev, &qctrl);
-	return v4l2_ctrl_query_menu(qmenu, &qctrl,
-		cx2341x_ctrl_get_menu(&dev->mpeg_params, qmenu->id));
-}
-
 static int vidioc_g_std(struct file *file, void *fh0, v4l2_std_id *norm)
 {
 	struct cx231xx_fh  *fh  = file->private_data;
@@ -1520,14 +1491,15 @@ static int vidioc_g_std(struct file *file, void *fh0, v4l2_std_id *norm)
 	*norm = dev->encodernorm.id;
 	return 0;
 }
-static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *id)
+
+static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id)
 {
 	struct cx231xx_fh  *fh  = file->private_data;
 	struct cx231xx *dev = fh->dev;
 	unsigned int i;
 
 	for (i = 0; i < ARRAY_SIZE(cx231xx_tvnorms); i++)
-		if (*id & cx231xx_tvnorms[i].id)
+		if (id & cx231xx_tvnorms[i].id)
 			break;
 	if (i == ARRAY_SIZE(cx231xx_tvnorms))
 		return -EINVAL;
@@ -1537,12 +1509,12 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *id)
 		dprintk(3, "encodernorm set to NTSC\n");
 		dev->norm = V4L2_STD_NTSC;
 		dev->ts1.height = 480;
-		dev->mpeg_params.is_50hz = 0;
+		cx2341x_handler_set_50hz(&dev->mpeg_ctrl_handler, false);
 	} else {
 		dprintk(3, "encodernorm set to PAL\n");
 		dev->norm = V4L2_STD_PAL_B;
 		dev->ts1.height = 576;
-		dev->mpeg_params.is_50hz = 1;
+		cx2341x_handler_set_50hz(&dev->mpeg_ctrl_handler, true);
 	}
 	call_all(dev, core, s_std, dev->norm);
 	/* do mode control overrides */
@@ -1551,161 +1523,23 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *id)
 	dprintk(3, "exit vidioc_s_std() i=0x%x\n", i);
 	return 0;
 }
-static int vidioc_g_audio(struct file *file, void *fh,
-					struct v4l2_audio *a)
-{
-		struct v4l2_audio *vin = a;
-
-		int ret = -EINVAL;
-		if (vin->index > 0)
-			return ret;
-		strncpy(vin->name, "VideoGrabber Audio", 14);
-		vin->capability = V4L2_AUDCAP_STEREO;
-return 0;
-}
-static int vidioc_enumaudio(struct file *file, void *fh,
-					struct v4l2_audio *a)
-{
-		struct v4l2_audio *vin = a;
-
-		int ret = -EINVAL;
-
-		if (vin->index > 0)
-			return ret;
-		strncpy(vin->name, "VideoGrabber Audio", 14);
-		vin->capability = V4L2_AUDCAP_STEREO;
-
-
-return 0;
-}
-static const char *iname[] = {
-	[CX231XX_VMUX_COMPOSITE1] = "Composite1",
-	[CX231XX_VMUX_SVIDEO]     = "S-Video",
-	[CX231XX_VMUX_TELEVISION] = "Television",
-	[CX231XX_VMUX_CABLE]      = "Cable TV",
-	[CX231XX_VMUX_DVB]        = "DVB",
-	[CX231XX_VMUX_DEBUG]      = "for debug only",
-};
-static int vidioc_enum_input(struct file *file, void *priv,
-				struct v4l2_input *i)
-{
-	struct cx231xx_fh  *fh  = file->private_data;
-	struct cx231xx *dev = fh->dev;
-	struct cx231xx_input *input;
-	int n;
-	dprintk(3, "enter vidioc_enum_input()i->index=%d\n", i->index);
-
-	if (i->index >= 4)
-		return -EINVAL;
-
-
-	input = &cx231xx_boards[dev->model].input[i->index];
-
-	if (input->type == 0)
-		return -EINVAL;
-
-	/* FIXME
-	 * strcpy(i->name, input->name); */
-
-	n = i->index;
-	strcpy(i->name, iname[INPUT(n)->type]);
-
-	if (input->type == CX231XX_VMUX_TELEVISION ||
-	    input->type == CX231XX_VMUX_CABLE)
-		i->type = V4L2_INPUT_TYPE_TUNER;
-	else
-		i->type  = V4L2_INPUT_TYPE_CAMERA;
-
-
-	return 0;
-}
-
-static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
-{
-	*i = 0;
-	return  0;
-}
-
-static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
-{
-	struct cx231xx_fh  *fh  = file->private_data;
-	struct cx231xx *dev = fh->dev;
-
-	dprintk(3, "enter vidioc_s_input() i=%d\n", i);
-
-	mutex_lock(&dev->lock);
-
-	video_mux(dev, i);
-
-	mutex_unlock(&dev->lock);
-
-	if (i >= 4)
-		return -EINVAL;
-	dev->input = i;
-	dprintk(3, "exit vidioc_s_input()\n");
-	return 0;
-}
-
-static int vidioc_g_tuner(struct file *file, void *priv,
-				struct v4l2_tuner *t)
-{
-	return 0;
-}
-
-static int vidioc_s_tuner(struct file *file, void *priv,
-				struct v4l2_tuner *t)
-{
-	return 0;
-}
-
-static int vidioc_g_frequency(struct file *file, void *priv,
-				struct v4l2_frequency *f)
-{
-	return 0;
-}
-
-static int vidioc_s_frequency(struct file *file, void *priv,
-				struct v4l2_frequency *f)
-{
-
-
-	return 0;
-}
 
 static int vidioc_s_ctrl(struct file *file, void *priv,
 				struct v4l2_control *ctl)
 {
 	struct cx231xx_fh  *fh  = file->private_data;
 	struct cx231xx *dev = fh->dev;
+
 	dprintk(3, "enter vidioc_s_ctrl()\n");
 	/* Update the A/V core */
 	call_all(dev, core, s_ctrl, ctl);
 	dprintk(3, "exit vidioc_s_ctrl()\n");
 	return 0;
 }
-static struct v4l2_capability pvr_capability = {
-	.driver         = "cx231xx",
-	.card           = "VideoGrabber",
-	.bus_info       = "usb",
-	.version        = 1,
-	.capabilities   = (V4L2_CAP_VIDEO_CAPTURE |
-			   V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_RADIO |
-			 V4L2_CAP_STREAMING | V4L2_CAP_READWRITE),
-};
-static int vidioc_querycap(struct file *file, void  *priv,
-				struct v4l2_capability *cap)
-{
-
-
-
-		memcpy(cap, &pvr_capability, sizeof(struct v4l2_capability));
-	return 0;
-}
 
 static int vidioc_enum_fmt_vid_cap(struct file *file, void  *priv,
 					struct v4l2_fmtdesc *f)
 {
-
 	if (f->index != 0)
 		return -EINVAL;
 
@@ -1720,17 +1554,18 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
 {
 	struct cx231xx_fh  *fh  = file->private_data;
 	struct cx231xx *dev = fh->dev;
+
 	dprintk(3, "enter vidioc_g_fmt_vid_cap()\n");
-	f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
+	f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
 	f->fmt.pix.bytesperline = 0;
-	f->fmt.pix.sizeimage    =
-		dev->ts1.ts_packet_size * dev->ts1.ts_packet_count;
-	f->fmt.pix.colorspace   = 0;
-	f->fmt.pix.width        = dev->ts1.width;
-	f->fmt.pix.height       = dev->ts1.height;
-	f->fmt.pix.field        = fh->vidq.field;
-	dprintk(1, "VIDIOC_G_FMT: w: %d, h: %d, f: %d\n",
-		dev->ts1.width, dev->ts1.height, fh->vidq.field);
+	f->fmt.pix.sizeimage = mpeglines * mpeglinesize;
+	f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+	f->fmt.pix.width = dev->ts1.width;
+	f->fmt.pix.height = dev->ts1.height;
+	f->fmt.pix.field = V4L2_FIELD_INTERLACED;
+	f->fmt.pix.priv = 0;
+	dprintk(1, "VIDIOC_G_FMT: w: %d, h: %d\n",
+		dev->ts1.width, dev->ts1.height);
 	dprintk(3, "exit vidioc_g_fmt_vid_cap()\n");
 	return 0;
 }
@@ -1740,25 +1575,20 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
 {
 	struct cx231xx_fh  *fh  = file->private_data;
 	struct cx231xx *dev = fh->dev;
+
 	dprintk(3, "enter vidioc_try_fmt_vid_cap()\n");
-	f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
+	f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
 	f->fmt.pix.bytesperline = 0;
-	f->fmt.pix.sizeimage    =
-		dev->ts1.ts_packet_size * dev->ts1.ts_packet_count;
-	f->fmt.pix.colorspace   = 0;
-	dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n",
-		dev->ts1.width, dev->ts1.height, fh->vidq.field);
+	f->fmt.pix.sizeimage = mpeglines * mpeglinesize;
+	f->fmt.pix.field = V4L2_FIELD_INTERLACED;
+	f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+	f->fmt.pix.priv = 0;
+	dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d\n",
+		dev->ts1.width, dev->ts1.height);
 	dprintk(3, "exit vidioc_try_fmt_vid_cap()\n");
 	return 0;
 }
 
-static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
-				struct v4l2_format *f)
-{
-
-	return 0;
-}
-
 static int vidioc_reqbufs(struct file *file, void *priv,
 				struct v4l2_requestbuffers *p)
 {
@@ -1795,22 +1625,22 @@ static int vidioc_streamon(struct file *file, void *priv,
 				enum v4l2_buf_type i)
 {
 	struct cx231xx_fh  *fh  = file->private_data;
-
 	struct cx231xx *dev = fh->dev;
+
 	dprintk(3, "enter vidioc_streamon()\n");
-		cx231xx_set_alt_setting(dev, INDEX_TS1, 0);
-		cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);
-		if (dev->USE_ISO)
-			cx231xx_init_isoc(dev, CX231XX_NUM_PACKETS,
-				       CX231XX_NUM_BUFS,
-				       dev->video_mode.max_pkt_size,
-				       cx231xx_isoc_copy);
-		else {
-			cx231xx_init_bulk(dev, 320,
-				       5,
-				       dev->ts1_mode.max_pkt_size,
-				       cx231xx_bulk_copy);
-		}
+	cx231xx_set_alt_setting(dev, INDEX_TS1, 0);
+	cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);
+	if (dev->USE_ISO)
+		cx231xx_init_isoc(dev, CX231XX_NUM_PACKETS,
+				CX231XX_NUM_BUFS,
+				dev->video_mode.max_pkt_size,
+				cx231xx_isoc_copy);
+	else {
+		cx231xx_init_bulk(dev, 320,
+				5,
+				dev->ts1_mode.max_pkt_size,
+				cx231xx_bulk_copy);
+	}
 	dprintk(3, "exit vidioc_streamon()\n");
 	return videobuf_streamon(&fh->vidq);
 }
@@ -1822,117 +1652,25 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
 	return videobuf_streamoff(&fh->vidq);
 }
 
-static int vidioc_g_ext_ctrls(struct file *file, void *priv,
-				struct v4l2_ext_controls *f)
-{
-	struct cx231xx_fh  *fh  = priv;
-	struct cx231xx *dev = fh->dev;
-	dprintk(3, "enter vidioc_g_ext_ctrls()\n");
-	if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
-		return -EINVAL;
-	dprintk(3, "exit vidioc_g_ext_ctrls()\n");
-	return cx2341x_ext_ctrls(&dev->mpeg_params, 0, f, VIDIOC_G_EXT_CTRLS);
-}
-
-static int vidioc_s_ext_ctrls(struct file *file, void *priv,
-				struct v4l2_ext_controls *f)
-{
-	struct cx231xx_fh  *fh  = priv;
-	struct cx231xx *dev = fh->dev;
-	struct cx2341x_mpeg_params p;
-	int err;
-	dprintk(3, "enter vidioc_s_ext_ctrls()\n");
-	if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
-		return -EINVAL;
-
-	p = dev->mpeg_params;
-	err = cx2341x_ext_ctrls(&p, 0, f, VIDIOC_TRY_EXT_CTRLS);
-	if (err == 0) {
-		err = cx2341x_update(dev, cx231xx_mbox_func,
-			&dev->mpeg_params, &p);
-		dev->mpeg_params = p;
-	}
-
-	return err;
-
-
-return 0;
-}
-
-static int vidioc_try_ext_ctrls(struct file *file, void *priv,
-				struct v4l2_ext_controls *f)
-{
-	struct cx231xx_fh  *fh  = priv;
-	struct cx231xx *dev = fh->dev;
-	struct cx2341x_mpeg_params p;
-	int err;
-	dprintk(3, "enter vidioc_try_ext_ctrls()\n");
-	if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
-		return -EINVAL;
-
-	p = dev->mpeg_params;
-	err = cx2341x_ext_ctrls(&p, 0, f, VIDIOC_TRY_EXT_CTRLS);
-	dprintk(3, "exit vidioc_try_ext_ctrls() err=%d\n", err);
-	return err;
-}
-
 static int vidioc_log_status(struct file *file, void *priv)
 {
 	struct cx231xx_fh  *fh  = priv;
 	struct cx231xx *dev = fh->dev;
-	char name[32 + 2];
 
-	snprintf(name, sizeof(name), "%s/2", dev->name);
-	dprintk(3,
-		"%s/2: ============  START LOG STATUS  ============\n",
-	       dev->name);
 	call_all(dev, core, log_status);
-	cx2341x_log_status(&dev->mpeg_params, name);
-	dprintk(3,
-		"%s/2: =============  END LOG STATUS  =============\n",
-	       dev->name);
-	return 0;
-}
-
-static int vidioc_querymenu(struct file *file, void *priv,
-				struct v4l2_querymenu *a)
-{
-	struct cx231xx_fh  *fh  = priv;
-	struct cx231xx *dev = fh->dev;
-	dprintk(3, "enter vidioc_querymenu()\n");
-	dprintk(3, "exit vidioc_querymenu()\n");
-	return cx231xx_querymenu(dev, a);
-}
-
-static int vidioc_queryctrl(struct file *file, void *priv,
-				struct v4l2_queryctrl *c)
-{
-	struct cx231xx_fh  *fh  = priv;
-	struct cx231xx *dev = fh->dev;
-	dprintk(3, "enter vidioc_queryctrl()\n");
-	dprintk(3, "exit vidioc_queryctrl()\n");
-	return cx231xx_queryctrl(dev, c);
+	return v4l2_ctrl_log_status(file, priv);
 }
 
 static int mpeg_open(struct file *file)
 {
-	int minor = video_devdata(file)->minor;
-	struct cx231xx *h, *dev = NULL;
-	/*struct list_head *list;*/
+	struct video_device *vdev = video_devdata(file);
+	struct cx231xx *dev = video_drvdata(file);
 	struct cx231xx_fh *fh;
-	/*u32 value = 0;*/
 
 	dprintk(2, "%s()\n", __func__);
 
-	list_for_each_entry(h, &cx231xx_devlist, devlist) {
-		if (h->v4l_device->minor == minor)
-			dev = h;
-	}
-
-	if (dev == NULL)
-		return -ENODEV;
-
-	mutex_lock(&dev->lock);
+	if (mutex_lock_interruptible(&dev->lock))
+		return -ERESTARTSYS;
 
 	/* allocate + initialize per filehandle data */
 	fh = kzalloc(sizeof(*fh), GFP_KERNEL);
@@ -1942,29 +1680,30 @@ static int mpeg_open(struct file *file)
 	}
 
 	file->private_data = fh;
-	fh->dev      = dev;
+	v4l2_fh_init(&fh->fh, vdev);
+	fh->dev = dev;
 
 
 	videobuf_queue_vmalloc_init(&fh->vidq, &cx231xx_qops,
 			    NULL, &dev->video_mode.slock,
 			    V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_INTERLACED,
-			    sizeof(struct cx231xx_buffer), fh, NULL);
+			    sizeof(struct cx231xx_buffer), fh, &dev->lock);
 /*
 	videobuf_queue_sg_init(&fh->vidq, &cx231xx_qops,
 			    &dev->udev->dev, &dev->ts1.slock,
 			    V4L2_BUF_TYPE_VIDEO_CAPTURE,
 			    V4L2_FIELD_INTERLACED,
 			    sizeof(struct cx231xx_buffer),
-			    fh, NULL);
+			    fh, &dev->lock);
 */
 
-
 	cx231xx_set_alt_setting(dev, INDEX_VANC, 1);
 	cx231xx_set_gpio_value(dev, 2, 0);
 
 	cx231xx_initialize_codec(dev);
 
 	mutex_unlock(&dev->lock);
+	v4l2_fh_add(&fh->fh);
 	cx231xx_start_TS1(dev);
 
 	return 0;
@@ -1977,25 +1716,20 @@ static int mpeg_release(struct file *file)
 
 	dprintk(3, "mpeg_release()! dev=0x%p\n", dev);
 
-	if (!dev) {
-		dprintk(3, "abort!!!\n");
-		return 0;
-	}
-
 	mutex_lock(&dev->lock);
 
 	cx231xx_stop_TS1(dev);
 
-		/* do this before setting alternate! */
-		if (dev->USE_ISO)
-			cx231xx_uninit_isoc(dev);
-		else
-			cx231xx_uninit_bulk(dev);
-		cx231xx_set_mode(dev, CX231XX_SUSPEND);
+	/* do this before setting alternate! */
+	if (dev->USE_ISO)
+		cx231xx_uninit_isoc(dev);
+	else
+		cx231xx_uninit_bulk(dev);
+	cx231xx_set_mode(dev, CX231XX_SUSPEND);
 
-		cx231xx_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0,
-				CX231xx_END_NOW, CX231xx_MPEG_CAPTURE,
-				CX231xx_RAW_BITS_NONE);
+	cx231xx_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0,
+			CX231xx_END_NOW, CX231xx_MPEG_CAPTURE,
+			CX231xx_RAW_BITS_NONE);
 
 	/* FIXME: Review this crap */
 	/* Shut device down on last close */
@@ -2015,7 +1749,8 @@ static int mpeg_release(struct file *file)
 		videobuf_read_stop(&fh->vidq);
 
 	videobuf_mmap_free(&fh->vidq);
-	file->private_data = NULL;
+	v4l2_fh_del(&fh->fh);
+	v4l2_fh_exit(&fh->fh);
 	kfree(fh);
 	mutex_unlock(&dev->lock);
 	return 0;
@@ -2027,7 +1762,6 @@ static ssize_t mpeg_read(struct file *file, char __user *data,
 	struct cx231xx_fh *fh = file->private_data;
 	struct cx231xx *dev = fh->dev;
 
-
 	/* Deal w/ A/V decoder * and mpeg encoder sync issues. */
 	/* Start mpeg encoder on first read. */
 	if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) {
@@ -2044,12 +1778,23 @@ static ssize_t mpeg_read(struct file *file, char __user *data,
 static unsigned int mpeg_poll(struct file *file,
 	struct poll_table_struct *wait)
 {
+	unsigned long req_events = poll_requested_events(wait);
 	struct cx231xx_fh *fh = file->private_data;
-	/*struct cx231xx *dev = fh->dev;*/
+	struct cx231xx *dev = fh->dev;
+	unsigned int res = 0;
+
+	if (v4l2_event_pending(&fh->fh))
+		res |= POLLPRI;
+	else
+		poll_wait(file, &fh->fh.wait, wait);
 
-	/*dprintk(2, "%s\n", __func__);*/
+	if (!(req_events & (POLLIN | POLLRDNORM)))
+		return res;
 
-	return videobuf_poll_stream(file, &fh->vidq, wait);
+	mutex_lock(&dev->lock);
+	res |= videobuf_poll_stream(file, &fh->vidq, wait);
+	mutex_unlock(&dev->lock);
+	return res;
 }
 
 static int mpeg_mmap(struct file *file, struct vm_area_struct *vma)
@@ -2069,44 +1814,39 @@ static struct v4l2_file_operations mpeg_fops = {
 	.read	       = mpeg_read,
 	.poll          = mpeg_poll,
 	.mmap	       = mpeg_mmap,
-	.ioctl	       = video_ioctl2,
+	.unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops mpeg_ioctl_ops = {
 	.vidioc_s_std		 = vidioc_s_std,
 	.vidioc_g_std		 = vidioc_g_std,
-	.vidioc_enum_input	 = vidioc_enum_input,
-	.vidioc_enumaudio	 = vidioc_enumaudio,
-	.vidioc_g_audio		 = vidioc_g_audio,
-	.vidioc_g_input		 = vidioc_g_input,
-	.vidioc_s_input		 = vidioc_s_input,
-	.vidioc_g_tuner		 = vidioc_g_tuner,
-	.vidioc_s_tuner		 = vidioc_s_tuner,
-	.vidioc_g_frequency	 = vidioc_g_frequency,
-	.vidioc_s_frequency	 = vidioc_s_frequency,
+	.vidioc_g_tuner          = cx231xx_g_tuner,
+	.vidioc_s_tuner          = cx231xx_s_tuner,
+	.vidioc_g_frequency      = cx231xx_g_frequency,
+	.vidioc_s_frequency      = cx231xx_s_frequency,
+	.vidioc_enum_input	 = cx231xx_enum_input,
+	.vidioc_g_input		 = cx231xx_g_input,
+	.vidioc_s_input		 = cx231xx_s_input,
 	.vidioc_s_ctrl		 = vidioc_s_ctrl,
-	.vidioc_querycap	 = vidioc_querycap,
+	.vidioc_querycap	 = cx231xx_querycap,
 	.vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
 	.vidioc_g_fmt_vid_cap	 = vidioc_g_fmt_vid_cap,
 	.vidioc_try_fmt_vid_cap	 = vidioc_try_fmt_vid_cap,
-	.vidioc_s_fmt_vid_cap	 = vidioc_s_fmt_vid_cap,
+	.vidioc_s_fmt_vid_cap	 = vidioc_try_fmt_vid_cap,
 	.vidioc_reqbufs		 = vidioc_reqbufs,
 	.vidioc_querybuf	 = vidioc_querybuf,
 	.vidioc_qbuf		 = vidioc_qbuf,
 	.vidioc_dqbuf		 = vidioc_dqbuf,
 	.vidioc_streamon	 = vidioc_streamon,
 	.vidioc_streamoff	 = vidioc_streamoff,
-	.vidioc_g_ext_ctrls	 = vidioc_g_ext_ctrls,
-	.vidioc_s_ext_ctrls	 = vidioc_s_ext_ctrls,
-	.vidioc_try_ext_ctrls	 = vidioc_try_ext_ctrls,
 	.vidioc_log_status	 = vidioc_log_status,
-	.vidioc_querymenu	 = vidioc_querymenu,
-	.vidioc_queryctrl	 = vidioc_queryctrl,
-/*	.vidioc_g_chip_ident	 = cx231xx_g_chip_ident,*/
+	.vidioc_g_chip_ident	 = cx231xx_g_chip_ident,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
-/*	.vidioc_g_register	 = cx231xx_g_register,*/
-/*	.vidioc_s_register	 = cx231xx_s_register,*/
+	.vidioc_g_register	 = cx231xx_g_register,
+	.vidioc_s_register	 = cx231xx_s_register,
 #endif
+	.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
+	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
 };
 
 static struct video_device cx231xx_mpeg_template = {
@@ -2114,8 +1854,7 @@ static struct video_device cx231xx_mpeg_template = {
 	.fops          = &mpeg_fops,
 	.ioctl_ops     = &mpeg_ioctl_ops,
 	.minor         = -1,
-	.tvnorms       = CX231xx_NORMS,
-	.current_norm  = V4L2_STD_NTSC_M,
+	.tvnorms       = V4L2_STD_ALL,
 };
 
 void cx231xx_417_unregister(struct cx231xx *dev)
@@ -2128,10 +1867,44 @@ void cx231xx_417_unregister(struct cx231xx *dev)
 			video_unregister_device(dev->v4l_device);
 		else
 			video_device_release(dev->v4l_device);
+		v4l2_ctrl_handler_free(&dev->mpeg_ctrl_handler.hdl);
 		dev->v4l_device = NULL;
 	}
 }
 
+static int cx231xx_s_video_encoding(struct cx2341x_handler *cxhdl, u32 val)
+{
+	struct cx231xx *dev = container_of(cxhdl, struct cx231xx, mpeg_ctrl_handler);
+	int is_mpeg1 = val == V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
+	struct v4l2_mbus_framefmt fmt;
+
+	/* fix videodecoder resolution */
+	fmt.width = cxhdl->width / (is_mpeg1 ? 2 : 1);
+	fmt.height = cxhdl->height;
+	fmt.code = V4L2_MBUS_FMT_FIXED;
+	v4l2_subdev_call(dev->sd_cx25840, video, s_mbus_fmt, &fmt);
+	return 0;
+}
+
+static int cx231xx_s_audio_sampling_freq(struct cx2341x_handler *cxhdl, u32 idx)
+{
+	static const u32 freqs[3] = { 44100, 48000, 32000 };
+	struct cx231xx *dev = container_of(cxhdl, struct cx231xx, mpeg_ctrl_handler);
+
+	/* The audio clock of the digitizer must match the codec sample
+	   rate otherwise you get some very strange effects. */
+	if (idx < ARRAY_SIZE(freqs))
+		call_all(dev, audio, s_clock_freq, freqs[idx]);
+	return 0;
+}
+
+static struct cx2341x_handler_ops cx231xx_ops = {
+	/* needed for the video clock freq */
+	.s_audio_sampling_freq = cx231xx_s_audio_sampling_freq,
+	/* needed for setting up the video resolution */
+	.s_video_encoding = cx231xx_s_video_encoding,
+};
+
 static struct video_device *cx231xx_video_dev_alloc(
 	struct cx231xx *dev,
 	struct usb_device *usbdev,
@@ -2145,12 +1918,21 @@ static struct video_device *cx231xx_video_dev_alloc(
 	if (NULL == vfd)
 		return NULL;
 	*vfd = *template;
-	vfd->minor = -1;
 	snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name,
 		type, cx231xx_boards[dev->model].name);
 
 	vfd->v4l2_dev = &dev->v4l2_dev;
+	vfd->lock = &dev->lock;
 	vfd->release = video_device_release;
+	set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
+	vfd->ctrl_handler = &dev->mpeg_ctrl_handler.hdl;
+	video_set_drvdata(vfd, dev);
+	if (dev->tuner_type == TUNER_ABSENT) {
+		v4l2_disable_ioctl(vfd, VIDIOC_G_FREQUENCY);
+		v4l2_disable_ioctl(vfd, VIDIOC_S_FREQUENCY);
+		v4l2_disable_ioctl(vfd, VIDIOC_G_TUNER);
+		v4l2_disable_ioctl(vfd, VIDIOC_S_TUNER);
+	}
 
 	return vfd;
 
@@ -2173,10 +1955,27 @@ int cx231xx_417_register(struct cx231xx *dev)
 		tsport->height = 576;
 
 	tsport->width = 720;
-	cx2341x_fill_defaults(&dev->mpeg_params);
+	err = cx2341x_handler_init(&dev->mpeg_ctrl_handler, 50);
+	if (err) {
+		dprintk(3, "%s: can't init cx2341x controls\n", dev->name);
+		return err;
+	}
+	dev->mpeg_ctrl_handler.func = cx231xx_mbox_func;
+	dev->mpeg_ctrl_handler.priv = dev;
+	dev->mpeg_ctrl_handler.ops = &cx231xx_ops;
+	if (dev->sd_cx25840)
+		v4l2_ctrl_add_handler(&dev->mpeg_ctrl_handler.hdl,
+				dev->sd_cx25840->ctrl_handler, NULL);
+	if (dev->mpeg_ctrl_handler.hdl.error) {
+		err = dev->mpeg_ctrl_handler.hdl.error;
+		dprintk(3, "%s: can't add cx25840 controls\n", dev->name);
+		v4l2_ctrl_handler_free(&dev->mpeg_ctrl_handler.hdl);
+		return err;
+	}
 	dev->norm = V4L2_STD_NTSC;
 
-	dev->mpeg_params.port = CX2341X_PORT_SERIAL;
+	dev->mpeg_ctrl_handler.port = CX2341X_PORT_SERIAL;
+	cx2341x_handler_set_50hz(&dev->mpeg_ctrl_handler, false);
 
 	/* Allocate and initialize V4L video device */
 	dev->v4l_device = cx231xx_video_dev_alloc(dev,
@@ -2185,6 +1984,7 @@ int cx231xx_417_register(struct cx231xx *dev)
 		VFL_TYPE_GRABBER, -1);
 	if (err < 0) {
 		dprintk(3, "%s: can't register mpeg device\n", dev->name);
+		v4l2_ctrl_handler_free(&dev->mpeg_ctrl_handler.hdl);
 		return err;
 	}
 
diff --git a/drivers/media/usb/cx231xx/cx231xx-audio.c b/drivers/media/usb/cx231xx/cx231xx-audio.c
index b4c99c7..81a1d97 100644
--- a/drivers/media/usb/cx231xx/cx231xx-audio.c
+++ b/drivers/media/usb/cx231xx/cx231xx-audio.c
@@ -449,9 +449,6 @@ static int snd_cx231xx_capture_open(struct snd_pcm_substream *substream)
 		return -ENODEV;
 	}
 
-	/* Sets volume, mute, etc */
-	dev->mute = 0;
-
 	/* set alternate setting for audio interface */
 	/* 1 - 48000 samples per sec */
 	mutex_lock(&dev->lock);
@@ -503,7 +500,6 @@ static int snd_cx231xx_pcm_close(struct snd_pcm_substream *substream)
 		return ret;
 	}
 
-	dev->mute = 1;
 	dev->adev.users--;
 	mutex_unlock(&dev->lock);
 
@@ -708,8 +704,8 @@ static int cx231xx_audio_init(struct cx231xx *dev)
 					    audio_index + 1];
 
 	adev->end_point_addr =
-	    le16_to_cpu(uif->altsetting[0].endpoint[isoc_pipe].desc.
-			bEndpointAddress);
+	    uif->altsetting[0].endpoint[isoc_pipe].desc.
+			bEndpointAddress;
 
 	adev->num_alt = uif->num_altsetting;
 	cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n",
diff --git a/drivers/media/usb/cx231xx/cx231xx-avcore.c b/drivers/media/usb/cx231xx/cx231xx-avcore.c
index 7222079..235ba65 100644
--- a/drivers/media/usb/cx231xx/cx231xx-avcore.c
+++ b/drivers/media/usb/cx231xx/cx231xx-avcore.c
@@ -357,6 +357,7 @@ int cx231xx_afe_update_power_control(struct cx231xx *dev,
 	case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID:
 	case CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL:
 	case CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC:
+	case CX231XX_BOARD_OTG102:
 		if (avmode == POLARIS_AVMODE_ANALOGT_TV) {
 			while (afe_power_status != (FLD_PWRDN_TUNING_BIAS |
 						FLD_PWRDN_ENABLE_PLL)) {
@@ -1720,6 +1721,7 @@ int cx231xx_dif_set_standard(struct cx231xx *dev, u32 standard)
 	case CX231XX_BOARD_CNXT_RDU_250:
 	case CX231XX_BOARD_CNXT_VIDEO_GRABBER:
 	case CX231XX_BOARD_HAUPPAUGE_EXETER:
+	case CX231XX_BOARD_OTG102:
 		func_mode = 0x03;
 		break;
 	case CX231XX_BOARD_CNXT_RDE_253S:
@@ -2133,7 +2135,7 @@ int cx231xx_tuner_post_channel_change(struct cx231xx *dev)
 
 	status = vid_blk_write_word(dev, DIF_AGC_IF_REF, dwval);
 
-	return status;
+	return status == sizeof(dwval) ? 0 : -EIO;
 }
 
 /******************************************************************************
@@ -2221,7 +2223,7 @@ int cx231xx_set_power_mode(struct cx231xx *dev, enum AV_MODE mode)
 	if (status < 0)
 		return status;
 
-	tmp = *((u32 *) value);
+	tmp = le32_to_cpu(*((u32 *) value));
 
 	switch (mode) {
 	case POLARIS_AVMODE_ENXTERNAL_AV:
@@ -2442,7 +2444,7 @@ int cx231xx_power_suspend(struct cx231xx *dev)
 	if (status > 0)
 		return status;
 
-	tmp = *((u32 *) value);
+	tmp = le32_to_cpu(*((u32 *) value));
 	tmp &= (~PWR_MODE_MASK);
 
 	value[0] = (u8) tmp;
@@ -2470,7 +2472,7 @@ int cx231xx_start_stream(struct cx231xx *dev, u32 ep_mask)
 	if (status < 0)
 		return status;
 
-	tmp = *((u32 *) value);
+	tmp = le32_to_cpu(*((u32 *) value));
 	tmp |= ep_mask;
 	value[0] = (u8) tmp;
 	value[1] = (u8) (tmp >> 8);
@@ -2495,7 +2497,7 @@ int cx231xx_stop_stream(struct cx231xx *dev, u32 ep_mask)
 	if (status < 0)
 		return status;
 
-	tmp = *((u32 *) value);
+	tmp = le32_to_cpu(*((u32 *) value));
 	tmp &= (~ep_mask);
 	value[0] = (u8) tmp;
 	value[1] = (u8) (tmp >> 8);
@@ -2638,20 +2640,23 @@ EXPORT_SYMBOL_GPL(cx231xx_capture_start);
 /*****************************************************************************
 *                   G P I O   B I T control functions                        *
 ******************************************************************************/
-int cx231xx_set_gpio_bit(struct cx231xx *dev, u32 gpio_bit, u8 *gpio_val)
+static int cx231xx_set_gpio_bit(struct cx231xx *dev, u32 gpio_bit, u32 gpio_val)
 {
 	int status = 0;
 
-	status = cx231xx_send_gpio_cmd(dev, gpio_bit, gpio_val, 4, 0, 0);
+	gpio_val = cpu_to_le32(gpio_val);
+	status = cx231xx_send_gpio_cmd(dev, gpio_bit, (u8 *)&gpio_val, 4, 0, 0);
 
 	return status;
 }
 
-int cx231xx_get_gpio_bit(struct cx231xx *dev, u32 gpio_bit, u8 *gpio_val)
+static int cx231xx_get_gpio_bit(struct cx231xx *dev, u32 gpio_bit, u32 *gpio_val)
 {
+	u32 tmp;
 	int status = 0;
 
-	status = cx231xx_send_gpio_cmd(dev, gpio_bit, gpio_val, 4, 0, 1);
+	status = cx231xx_send_gpio_cmd(dev, gpio_bit, (u8 *)&tmp, 4, 0, 1);
+	*gpio_val = le32_to_cpu(tmp);
 
 	return status;
 }
@@ -2683,7 +2688,7 @@ int cx231xx_set_gpio_direction(struct cx231xx *dev,
 	else
 		value = dev->gpio_dir | (1 << pin_number);
 
-	status = cx231xx_set_gpio_bit(dev, value, (u8 *) &dev->gpio_val);
+	status = cx231xx_set_gpio_bit(dev, value, dev->gpio_val);
 
 	/* cache the value for future */
 	dev->gpio_dir = value;
@@ -2717,7 +2722,7 @@ int cx231xx_set_gpio_value(struct cx231xx *dev, int pin_number, int pin_value)
 		value = dev->gpio_dir | (1 << pin_number);
 		dev->gpio_dir = value;
 		status = cx231xx_set_gpio_bit(dev, dev->gpio_dir,
-					      (u8 *) &dev->gpio_val);
+					      dev->gpio_val);
 		value = 0;
 	}
 
@@ -2730,7 +2735,7 @@ int cx231xx_set_gpio_value(struct cx231xx *dev, int pin_number, int pin_value)
 	dev->gpio_val = value;
 
 	/* toggle bit0 of GP_IO */
-	status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val);
+	status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, dev->gpio_val);
 
 	return status;
 }
@@ -2748,7 +2753,7 @@ int cx231xx_gpio_i2c_start(struct cx231xx *dev)
 	dev->gpio_val |= 1 << dev->board.tuner_scl_gpio;
 	dev->gpio_val |= 1 << dev->board.tuner_sda_gpio;
 
-	status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val);
+	status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, dev->gpio_val);
 	if (status < 0)
 		return -EINVAL;
 
@@ -2756,7 +2761,7 @@ int cx231xx_gpio_i2c_start(struct cx231xx *dev)
 	dev->gpio_val |= 1 << dev->board.tuner_scl_gpio;
 	dev->gpio_val &= ~(1 << dev->board.tuner_sda_gpio);
 
-	status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val);
+	status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, dev->gpio_val);
 	if (status < 0)
 		return -EINVAL;
 
@@ -2764,7 +2769,7 @@ int cx231xx_gpio_i2c_start(struct cx231xx *dev)
 	dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio);
 	dev->gpio_val &= ~(1 << dev->board.tuner_sda_gpio);
 
-	status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val);
+	status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, dev->gpio_val);
 	if (status < 0)
 		return -EINVAL;
 
@@ -2782,7 +2787,7 @@ int cx231xx_gpio_i2c_end(struct cx231xx *dev)
 	dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio);
 	dev->gpio_val &= ~(1 << dev->board.tuner_sda_gpio);
 
-	status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val);
+	status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, dev->gpio_val);
 	if (status < 0)
 		return -EINVAL;
 
@@ -2790,7 +2795,7 @@ int cx231xx_gpio_i2c_end(struct cx231xx *dev)
 	dev->gpio_val |= 1 << dev->board.tuner_scl_gpio;
 	dev->gpio_val &= ~(1 << dev->board.tuner_sda_gpio);
 
-	status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val);
+	status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, dev->gpio_val);
 	if (status < 0)
 		return -EINVAL;
 
@@ -2800,7 +2805,7 @@ int cx231xx_gpio_i2c_end(struct cx231xx *dev)
 	dev->gpio_dir &= ~(1 << dev->board.tuner_sda_gpio);
 
 	status =
-	    cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val);
+	    cx231xx_set_gpio_bit(dev, dev->gpio_dir, dev->gpio_val);
 	if (status < 0)
 		return -EINVAL;
 
@@ -2822,33 +2827,33 @@ int cx231xx_gpio_i2c_write_byte(struct cx231xx *dev, u8 data)
 			dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio);
 			dev->gpio_val &= ~(1 << dev->board.tuner_sda_gpio);
 			status = cx231xx_set_gpio_bit(dev, dev->gpio_dir,
-						      (u8 *)&dev->gpio_val);
+						      dev->gpio_val);
 
 			/* set SCL to output 1; set SDA to output 0     */
 			dev->gpio_val |= 1 << dev->board.tuner_scl_gpio;
 			status = cx231xx_set_gpio_bit(dev, dev->gpio_dir,
-						      (u8 *)&dev->gpio_val);
+						      dev->gpio_val);
 
 			/* set SCL to output 0; set SDA to output 0     */
 			dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio);
 			status = cx231xx_set_gpio_bit(dev, dev->gpio_dir,
-						      (u8 *)&dev->gpio_val);
+						      dev->gpio_val);
 		} else {
 			/* set SCL to output 0; set SDA to output 1     */
 			dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio);
 			dev->gpio_val |= 1 << dev->board.tuner_sda_gpio;
 			status = cx231xx_set_gpio_bit(dev, dev->gpio_dir,
-						      (u8 *)&dev->gpio_val);
+						      dev->gpio_val);
 
 			/* set SCL to output 1; set SDA to output 1     */
 			dev->gpio_val |= 1 << dev->board.tuner_scl_gpio;
 			status = cx231xx_set_gpio_bit(dev, dev->gpio_dir,
-						      (u8 *)&dev->gpio_val);
+						      dev->gpio_val);
 
 			/* set SCL to output 0; set SDA to output 1     */
 			dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio);
 			status = cx231xx_set_gpio_bit(dev, dev->gpio_dir,
-						      (u8 *)&dev->gpio_val);
+						      dev->gpio_val);
 		}
 	}
 	return status;
@@ -2867,17 +2872,17 @@ int cx231xx_gpio_i2c_read_byte(struct cx231xx *dev, u8 *buf)
 		/* set SCL to output 0; set SDA to input */
 		dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio);
 		status = cx231xx_set_gpio_bit(dev, dev->gpio_dir,
-					      (u8 *)&dev->gpio_val);
+					      dev->gpio_val);
 
 		/* set SCL to output 1; set SDA to input */
 		dev->gpio_val |= 1 << dev->board.tuner_scl_gpio;
 		status = cx231xx_set_gpio_bit(dev, dev->gpio_dir,
-					      (u8 *)&dev->gpio_val);
+					      dev->gpio_val);
 
 		/* get SDA data bit */
 		gpio_logic_value = dev->gpio_val;
 		status = cx231xx_get_gpio_bit(dev, dev->gpio_dir,
-					      (u8 *)&dev->gpio_val);
+					      &dev->gpio_val);
 		if ((dev->gpio_val & (1 << dev->board.tuner_sda_gpio)) != 0)
 			value |= (1 << (8 - i - 1));
 
@@ -2888,7 +2893,7 @@ int cx231xx_gpio_i2c_read_byte(struct cx231xx *dev, u8 *buf)
 	   !!!set SDA to input, never to modify SDA direction at
 	   the same times */
 	dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio);
-	status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val);
+	status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, dev->gpio_val);
 
 	/* store the value */
 	*buf = value & 0xff;
@@ -2909,12 +2914,12 @@ int cx231xx_gpio_i2c_read_ack(struct cx231xx *dev)
 	dev->gpio_dir &= ~(1 << dev->board.tuner_scl_gpio);
 
 	gpio_logic_value = dev->gpio_val;
-	status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val);
+	status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, dev->gpio_val);
 
 	do {
 		msleep(2);
 		status = cx231xx_get_gpio_bit(dev, dev->gpio_dir,
-					      (u8 *)&dev->gpio_val);
+					      &dev->gpio_val);
 		nCnt--;
 	} while (((dev->gpio_val &
 			  (1 << dev->board.tuner_scl_gpio)) == 0) &&
@@ -2929,7 +2934,7 @@ int cx231xx_gpio_i2c_read_ack(struct cx231xx *dev)
 	 * through clock stretch, slave has given a SCL signal,
 	 * so the SDA data can be directly read.
 	 */
-	status = cx231xx_get_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val);
+	status = cx231xx_get_gpio_bit(dev, dev->gpio_dir, &dev->gpio_val);
 
 	if ((dev->gpio_val & 1 << dev->board.tuner_sda_gpio) == 0) {
 		dev->gpio_val = gpio_logic_value;
@@ -2945,7 +2950,7 @@ int cx231xx_gpio_i2c_read_ack(struct cx231xx *dev)
 	dev->gpio_val = gpio_logic_value;
 	dev->gpio_dir |= (1 << dev->board.tuner_scl_gpio);
 	dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio);
-	status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val);
+	status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, dev->gpio_val);
 
 	return status;
 }
@@ -2956,24 +2961,24 @@ int cx231xx_gpio_i2c_write_ack(struct cx231xx *dev)
 
 	/* set SDA to ouput */
 	dev->gpio_dir |= 1 << dev->board.tuner_sda_gpio;
-	status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val);
+	status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, dev->gpio_val);
 
 	/* set SCL = 0 (output); set SDA = 0 (output) */
 	dev->gpio_val &= ~(1 << dev->board.tuner_sda_gpio);
 	dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio);
-	status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val);
+	status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, dev->gpio_val);
 
 	/* set SCL = 1 (output); set SDA = 0 (output) */
 	dev->gpio_val |= 1 << dev->board.tuner_scl_gpio;
-	status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val);
+	status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, dev->gpio_val);
 
 	/* set SCL = 0 (output); set SDA = 0 (output) */
 	dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio);
-	status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val);
+	status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, dev->gpio_val);
 
 	/* set SDA to input,and then the slave will read data from SDA. */
 	dev->gpio_dir &= ~(1 << dev->board.tuner_sda_gpio);
-	status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val);
+	status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, dev->gpio_val);
 
 	return status;
 }
@@ -2985,15 +2990,15 @@ int cx231xx_gpio_i2c_write_nak(struct cx231xx *dev)
 	/* set scl to output ; set sda to input */
 	dev->gpio_dir |= 1 << dev->board.tuner_scl_gpio;
 	dev->gpio_dir &= ~(1 << dev->board.tuner_sda_gpio);
-	status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val);
+	status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, dev->gpio_val);
 
 	/* set scl to output 0; set sda to input */
 	dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio);
-	status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val);
+	status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, dev->gpio_val);
 
 	/* set scl to output 1; set sda to input */
 	dev->gpio_val |= 1 << dev->board.tuner_scl_gpio;
-	status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val);
+	status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, dev->gpio_val);
 
 	return status;
 }
diff --git a/drivers/media/usb/cx231xx/cx231xx-cards.c b/drivers/media/usb/cx231xx/cx231xx-cards.c
index 8d52956..13249e5 100644
--- a/drivers/media/usb/cx231xx/cx231xx-cards.c
+++ b/drivers/media/usb/cx231xx/cx231xx-cards.c
@@ -263,7 +263,11 @@ struct cx231xx_board cx231xx_boards[] = {
 		.norm = V4L2_STD_PAL,
 		.no_alt_vanc = 1,
 		.external_av = 1,
-		.has_417 = 1,
+		.dont_use_port_3 = 1,
+		/* Actually, it has a 417, but it isn't working correctly.
+		 * So set to 0 for now until someone can manage to get this
+		 * to work reliably. */
+		.has_417 = 0,
 
 		.input = {{
 				.type = CX231XX_VMUX_COMPOSITE1,
@@ -630,6 +634,39 @@ struct cx231xx_board cx231xx_boards[] = {
 			.gpio = NULL,
 		} },
 	},
+	[CX231XX_BOARD_OTG102] = {
+		.name = "Geniatech OTG102",
+		.tuner_type = TUNER_ABSENT,
+		.decoder = CX231XX_AVDECODER,
+		.output_mode = OUT_MODE_VIP11,
+		.ctl_pin_status_mask = 0xFFFFFFC4,
+		.agc_analog_digital_select_gpio = 0x0c, 
+			/* According with PV CxPlrCAP.inf file */
+		.gpio_pin_status_mask = 0x4001000,
+		.norm = V4L2_STD_NTSC,
+		.no_alt_vanc = 1,
+		.external_av = 1,
+		.dont_use_port_3 = 1,
+		/*.has_417 = 1, */
+		/* This board is believed to have a hardware encoding chip
+		 * supporting mpeg1/2/4, but as the 417 is apparently not
+		 * working for the reference board it is not here either. */
+
+		.input = {{
+				.type = CX231XX_VMUX_COMPOSITE1,
+				.vmux = CX231XX_VIN_2_1,
+				.amux = CX231XX_AMUX_LINE_IN,
+				.gpio = NULL,
+			}, {
+				.type = CX231XX_VMUX_SVIDEO,
+				.vmux = CX231XX_VIN_1_1 |
+					(CX231XX_VIN_1_2 << 8) |
+					CX25840_SVIDEO_ON,
+				.amux = CX231XX_AMUX_LINE_IN,
+				.gpio = NULL,
+			}
+		},
+	},
 };
 const unsigned int cx231xx_bcount = ARRAY_SIZE(cx231xx_boards);
 
@@ -671,6 +708,8 @@ struct usb_device_id cx231xx_id_table[] = {
 	 .driver_info = CX231XX_BOARD_ICONBIT_U100},
 	{USB_DEVICE(0x0fd9, 0x0037),
 	 .driver_info = CX231XX_BOARD_ELGATO_VIDEO_CAPTURE_V2},
+	{USB_DEVICE(0x1f4d, 0x0102),
+	 .driver_info = CX231XX_BOARD_OTG102},
 	{},
 };
 
@@ -846,8 +885,6 @@ void cx231xx_card_setup(struct cx231xx *dev)
 int cx231xx_config(struct cx231xx *dev)
 {
 	/* TBD need to add cx231xx specific code */
-	dev->mute = 1;		/* maybe not the right place... */
-	dev->volume = 0x1f;
 
 	return 0;
 }
@@ -1187,8 +1224,8 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
 	uif = udev->actconfig->interface[dev->current_pcb_config.
 		       hs_config_info[0].interface_info.video_index + 1];
 
-	dev->video_mode.end_point_addr = le16_to_cpu(uif->altsetting[0].
-			endpoint[isoc_pipe].desc.bEndpointAddress);
+	dev->video_mode.end_point_addr = uif->altsetting[0].
+			endpoint[isoc_pipe].desc.bEndpointAddress;
 
 	dev->video_mode.num_alt = uif->num_altsetting;
 	cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n",
@@ -1221,8 +1258,8 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
 				       vanc_index + 1];
 
 	dev->vbi_mode.end_point_addr =
-	    le16_to_cpu(uif->altsetting[0].endpoint[isoc_pipe].desc.
-			bEndpointAddress);
+	    uif->altsetting[0].endpoint[isoc_pipe].desc.
+			bEndpointAddress;
 
 	dev->vbi_mode.num_alt = uif->num_altsetting;
 	cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n",
@@ -1256,8 +1293,8 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
 				       hanc_index + 1];
 
 	dev->sliced_cc_mode.end_point_addr =
-	    le16_to_cpu(uif->altsetting[0].endpoint[isoc_pipe].desc.
-			bEndpointAddress);
+	    uif->altsetting[0].endpoint[isoc_pipe].desc.
+			bEndpointAddress;
 
 	dev->sliced_cc_mode.num_alt = uif->num_altsetting;
 	cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n",
@@ -1292,8 +1329,8 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
 					       ts1_index + 1];
 
 		dev->ts1_mode.end_point_addr =
-		    le16_to_cpu(uif->altsetting[0].endpoint[isoc_pipe].
-				desc.bEndpointAddress);
+		    uif->altsetting[0].endpoint[isoc_pipe].
+				desc.bEndpointAddress;
 
 		dev->ts1_mode.num_alt = uif->num_altsetting;
 		cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n",
diff --git a/drivers/media/usb/cx231xx/cx231xx-core.c b/drivers/media/usb/cx231xx/cx231xx-core.c
index 05358d4..4ba3ce0 100644
--- a/drivers/media/usb/cx231xx/cx231xx-core.c
+++ b/drivers/media/usb/cx231xx/cx231xx-core.c
@@ -1488,7 +1488,7 @@ int cx231xx_mode_register(struct cx231xx *dev, u16 address, u32 mode)
 	if (status < 0)
 		return status;
 
-	tmp = *((u32 *) value);
+	tmp = le32_to_cpu(*((u32 *) value));
 	tmp |= mode;
 
 	value[0] = (u8) tmp;
diff --git a/drivers/media/usb/cx231xx/cx231xx-dvb.c b/drivers/media/usb/cx231xx/cx231xx-dvb.c
index 7c4e360..14e2610 100644
--- a/drivers/media/usb/cx231xx/cx231xx-dvb.c
+++ b/drivers/media/usb/cx231xx/cx231xx-dvb.c
@@ -89,8 +89,8 @@ static struct tda18271_std_map cnxt_rde253s_tda18271_std_map = {
 };
 
 static struct tda18271_std_map mb86a20s_tda18271_config = {
-	.dvbt_6   = { .if_freq = 3300, .agc_mode = 3, .std = 4,
-		      .if_lvl = 7, .rfagc_top = 0x37, },
+	.dvbt_6   = { .if_freq = 4000, .agc_mode = 3, .std = 4,
+		      .if_lvl = 0, .rfagc_top = 0x37, },
 };
 
 static struct tda18271_config cnxt_rde253s_tunerconfig = {
diff --git a/drivers/media/usb/cx231xx/cx231xx-pcb-cfg.c b/drivers/media/usb/cx231xx/cx231xx-pcb-cfg.c
index 7473c33..d7308ab 100644
--- a/drivers/media/usb/cx231xx/cx231xx-pcb-cfg.c
+++ b/drivers/media/usb/cx231xx/cx231xx-pcb-cfg.c
@@ -672,7 +672,7 @@ u32 initialize_cx231xx(struct cx231xx *dev)
 	pcb config it is related to */
 	cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, BOARD_CFG_STAT, data, 4);
 
-	config_info = *((u32 *) data);
+	config_info = le32_to_cpu(*((u32 *) data));
 	usb_speed = (u8) (config_info & 0x1);
 
 	/* Verify this device belongs to Bus power or Self power device */
diff --git a/drivers/media/usb/cx231xx/cx231xx-pcb-cfg.h b/drivers/media/usb/cx231xx/cx231xx-pcb-cfg.h
index f5e46e8..b3c6190 100644
--- a/drivers/media/usb/cx231xx/cx231xx-pcb-cfg.h
+++ b/drivers/media/usb/cx231xx/cx231xx-pcb-cfg.h
@@ -68,11 +68,6 @@ enum USB_SPEED{
 	HIGH_SPEED = 0x1	/* 1: high speed */
 };
 
-enum _true_false{
-	FALSE = 0,
-	TRUE = 1
-};
-
 #define TS_MASK         0x6
 enum TS_PORT{
 	NO_TS_PORT = 0x0,	/* 2'b00: Neither port used. PCB not a Hybrid,
diff --git a/drivers/media/usb/cx231xx/cx231xx-vbi.c b/drivers/media/usb/cx231xx/cx231xx-vbi.c
index 46e3892..1340ff2 100644
--- a/drivers/media/usb/cx231xx/cx231xx-vbi.c
+++ b/drivers/media/usb/cx231xx/cx231xx-vbi.c
@@ -70,10 +70,10 @@ static inline void print_err_status(struct cx231xx *dev, int packet, int status)
 		break;
 	}
 	if (packet < 0) {
-		cx231xx_err(DRIVER_NAME "URB status %d [%s].\n", status,
+		cx231xx_err("URB status %d [%s].\n", status,
 			    errmsg);
 	} else {
-		cx231xx_err(DRIVER_NAME "URB packet %d, status %d [%s].\n",
+		cx231xx_err("URB packet %d, status %d [%s].\n",
 			    packet, status, errmsg);
 	}
 }
@@ -317,7 +317,7 @@ static void cx231xx_irq_vbi_callback(struct urb *urb)
 	case -ESHUTDOWN:
 		return;
 	default:		/* error */
-		cx231xx_err(DRIVER_NAME "urb completition error %d.\n",
+		cx231xx_err("urb completition error %d.\n",
 			    urb->status);
 		break;
 	}
@@ -332,7 +332,7 @@ static void cx231xx_irq_vbi_callback(struct urb *urb)
 
 	urb->status = usb_submit_urb(urb, GFP_ATOMIC);
 	if (urb->status) {
-		cx231xx_err(DRIVER_NAME "urb resubmit failed (error=%i)\n",
+		cx231xx_err("urb resubmit failed (error=%i)\n",
 			    urb->status);
 	}
 }
@@ -345,7 +345,7 @@ void cx231xx_uninit_vbi_isoc(struct cx231xx *dev)
 	struct urb *urb;
 	int i;
 
-	cx231xx_info(DRIVER_NAME "cx231xx: called cx231xx_uninit_vbi_isoc\n");
+	cx231xx_info("called cx231xx_uninit_vbi_isoc\n");
 
 	dev->vbi_mode.bulk_ctl.nfields = -1;
 	for (i = 0; i < dev->vbi_mode.bulk_ctl.num_bufs; i++) {
@@ -394,7 +394,7 @@ int cx231xx_init_vbi_isoc(struct cx231xx *dev, int max_packets,
 	struct urb *urb;
 	int rc;
 
-	cx231xx_info(DRIVER_NAME "cx231xx: called cx231xx_prepare_isoc\n");
+	cx231xx_info("called cx231xx_vbi_isoc\n");
 
 	/* De-allocates all pending stuff */
 	cx231xx_uninit_vbi_isoc(dev);
@@ -442,8 +442,7 @@ int cx231xx_init_vbi_isoc(struct cx231xx *dev, int max_packets,
 
 		urb = usb_alloc_urb(0, GFP_KERNEL);
 		if (!urb) {
-			cx231xx_err(DRIVER_NAME
-				    ": cannot alloc bulk_ctl.urb %i\n", i);
+			cx231xx_err("cannot alloc bulk_ctl.urb %i\n", i);
 			cx231xx_uninit_vbi_isoc(dev);
 			return -ENOMEM;
 		}
@@ -453,8 +452,7 @@ int cx231xx_init_vbi_isoc(struct cx231xx *dev, int max_packets,
 		dev->vbi_mode.bulk_ctl.transfer_buffer[i] =
 		    kzalloc(sb_size, GFP_KERNEL);
 		if (!dev->vbi_mode.bulk_ctl.transfer_buffer[i]) {
-			cx231xx_err(DRIVER_NAME
-				    ": unable to allocate %i bytes for transfer"
+			cx231xx_err("unable to allocate %i bytes for transfer"
 				    " buffer %i%s\n", sb_size, i,
 				    in_interrupt() ? " while in int" : "");
 			cx231xx_uninit_vbi_isoc(dev);
@@ -473,8 +471,7 @@ int cx231xx_init_vbi_isoc(struct cx231xx *dev, int max_packets,
 	for (i = 0; i < dev->vbi_mode.bulk_ctl.num_bufs; i++) {
 		rc = usb_submit_urb(dev->vbi_mode.bulk_ctl.urb[i], GFP_ATOMIC);
 		if (rc) {
-			cx231xx_err(DRIVER_NAME
-				    ": submit of urb %i failed (error=%i)\n", i,
+			cx231xx_err("submit of urb %i failed (error=%i)\n", i,
 				    rc);
 			cx231xx_uninit_vbi_isoc(dev);
 			return rc;
@@ -526,7 +523,7 @@ static inline void vbi_buffer_filled(struct cx231xx *dev,
 				     struct cx231xx_buffer *buf)
 {
 	/* Advice that buffer was filled */
-	/* cx231xx_info(DRIVER_NAME "[%p/%d] wakeup\n", buf, buf->vb.i); */
+	/* cx231xx_info("[%p/%d] wakeup\n", buf, buf->vb.i); */
 
 	buf->vb.state = VIDEOBUF_DONE;
 	buf->vb.field_count++;
@@ -618,7 +615,7 @@ static inline void get_next_vbi_buf(struct cx231xx_dmaqueue *dma_q,
 	char *outp;
 
 	if (list_empty(&dma_q->active)) {
-		cx231xx_err(DRIVER_NAME ": No active queue to serve\n");
+		cx231xx_err("No active queue to serve\n");
 		dev->vbi_mode.bulk_ctl.buf = NULL;
 		*buf = NULL;
 		return;
diff --git a/drivers/media/usb/cx231xx/cx231xx-video.c b/drivers/media/usb/cx231xx/cx231xx-video.c
index 06376d9..cd22147 100644
--- a/drivers/media/usb/cx231xx/cx231xx-video.c
+++ b/drivers/media/usb/cx231xx/cx231xx-video.c
@@ -35,6 +35,7 @@
 
 #include <media/v4l2-common.h>
 #include <media/v4l2-ioctl.h>
+#include <media/v4l2-event.h>
 #include <media/v4l2-chip-ident.h>
 #include <media/msp3400.h>
 #include <media/tuner.h>
@@ -100,125 +101,6 @@ static struct cx231xx_fmt format[] = {
 	 },
 };
 
-/* supported controls */
-/* Common to all boards */
-
-/* ------------------------------------------------------------------- */
-
-static const struct v4l2_queryctrl no_ctl = {
-	.name = "42",
-	.flags = V4L2_CTRL_FLAG_DISABLED,
-};
-
-static struct cx231xx_ctrl cx231xx_ctls[] = {
-	/* --- video --- */
-	{
-		.v = {
-			.id = V4L2_CID_BRIGHTNESS,
-			.name = "Brightness",
-			.minimum = 0x00,
-			.maximum = 0xff,
-			.step = 1,
-			.default_value = 0x7f,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-		},
-		.off = 128,
-		.reg = LUMA_CTRL,
-		.mask = 0x00ff,
-		.shift = 0,
-	}, {
-		.v = {
-			.id = V4L2_CID_CONTRAST,
-			.name = "Contrast",
-			.minimum = 0,
-			.maximum = 0xff,
-			.step = 1,
-			.default_value = 0x3f,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-		},
-		.off = 0,
-		.reg = LUMA_CTRL,
-		.mask = 0xff00,
-		.shift = 8,
-	}, {
-		.v = {
-			.id = V4L2_CID_HUE,
-			.name = "Hue",
-			.minimum = 0,
-			.maximum = 0xff,
-			.step = 1,
-			.default_value = 0x7f,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-		},
-		.off = 128,
-		.reg = CHROMA_CTRL,
-		.mask = 0xff0000,
-		.shift = 16,
-	}, {
-	/* strictly, this only describes only U saturation.
-	* V saturation is handled specially through code.
-	*/
-		.v = {
-			.id = V4L2_CID_SATURATION,
-			.name = "Saturation",
-			.minimum = 0,
-			.maximum = 0xff,
-			.step = 1,
-			.default_value = 0x7f,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-		},
-		.off = 0,
-		.reg = CHROMA_CTRL,
-		.mask = 0x00ff,
-		.shift = 0,
-	}, {
-		/* --- audio --- */
-		.v = {
-			.id = V4L2_CID_AUDIO_MUTE,
-			.name = "Mute",
-			.minimum = 0,
-			.maximum = 1,
-			.default_value = 1,
-			.type = V4L2_CTRL_TYPE_BOOLEAN,
-		},
-		.reg = PATH1_CTL1,
-		.mask = (0x1f << 24),
-		.shift = 24,
-	}, {
-		.v = {
-			.id = V4L2_CID_AUDIO_VOLUME,
-			.name = "Volume",
-			.minimum = 0,
-			.maximum = 0x3f,
-			.step = 1,
-			.default_value = 0x3f,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-		},
-		.reg = PATH1_VOL_CTL,
-		.mask = 0xff,
-		.shift = 0,
-	}
-};
-static const int CX231XX_CTLS = ARRAY_SIZE(cx231xx_ctls);
-
-static const u32 cx231xx_user_ctrls[] = {
-	V4L2_CID_USER_CLASS,
-	V4L2_CID_BRIGHTNESS,
-	V4L2_CID_CONTRAST,
-	V4L2_CID_SATURATION,
-	V4L2_CID_HUE,
-	V4L2_CID_AUDIO_VOLUME,
-#if 0
-	V4L2_CID_AUDIO_BALANCE,
-#endif
-	V4L2_CID_AUDIO_MUTE,
-	0
-};
-
-static const u32 *ctrl_classes[] = {
-	cx231xx_user_ctrls,
-	NULL
-};
 
 /* ------------------------------------------------------------------
 	Video buffer and parser functions
@@ -1005,6 +887,7 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
 	f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
 
 	f->fmt.pix.field = V4L2_FIELD_INTERLACED;
+	f->fmt.pix.priv = 0;
 
 	return 0;
 }
@@ -1045,10 +928,11 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
 	f->fmt.pix.width = width;
 	f->fmt.pix.height = height;
 	f->fmt.pix.pixelformat = fmt->fourcc;
-	f->fmt.pix.bytesperline = (dev->width * fmt->depth + 7) >> 3;
+	f->fmt.pix.bytesperline = (width * fmt->depth + 7) >> 3;
 	f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * height;
 	f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
 	f->fmt.pix.field = V4L2_FIELD_INTERLACED;
+	f->fmt.pix.priv = 0;
 
 	return 0;
 }
@@ -1103,39 +987,39 @@ static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id)
 	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)
 {
 	struct cx231xx_fh *fh = priv;
 	struct cx231xx *dev = fh->dev;
 	struct v4l2_mbus_framefmt mbus_fmt;
-	struct v4l2_format f;
 	int rc;
 
 	rc = check_dev(dev);
 	if (rc < 0)
 		return rc;
 
-	cx231xx_info("vidioc_s_std : 0x%x\n", (unsigned int)*norm);
+	if (dev->norm == norm)
+		return 0;
 
-	dev->norm = *norm;
+	if (videobuf_queue_is_busy(&fh->vb_vidq))
+		return -EBUSY;
+
+	dev->norm = norm;
 
 	/* Adjusts width/height, if needed */
-	f.fmt.pix.width = dev->width;
-	f.fmt.pix.height = dev->height;
-	vidioc_try_fmt_vid_cap(file, priv, &f);
+	dev->width = 720;
+	dev->height = (dev->norm & V4L2_STD_625_50) ? 576 : 480;
 
 	call_all(dev, core, s_std, dev->norm);
 
 	/* We need to reset basic properties in the decoder related to
 	   resolution (since a standard change effects things like the number
 	   of lines in VACT, etc) */
-	v4l2_fill_mbus_format(&mbus_fmt, &f.fmt.pix, V4L2_MBUS_FMT_FIXED);
+	memset(&mbus_fmt, 0, sizeof(mbus_fmt));
+	mbus_fmt.code = V4L2_MBUS_FMT_FIXED;
+	mbus_fmt.width = dev->width;
+	mbus_fmt.height = dev->height;
 	call_all(dev, video, s_mbus_fmt, &mbus_fmt);
-	v4l2_fill_pix_format(&f.fmt.pix, &mbus_fmt);
-
-	/* set new image size */
-	dev->width = f.fmt.pix.width;
-	dev->height = f.fmt.pix.height;
 
 	/* do mode control overrides */
 	cx231xx_do_mode_ctrl_overrides(dev);
@@ -1152,7 +1036,7 @@ static const char *iname[] = {
 	[CX231XX_VMUX_DEBUG]      = "for debug only",
 };
 
-static int vidioc_enum_input(struct file *file, void *priv,
+int cx231xx_enum_input(struct file *file, void *priv,
 			     struct v4l2_input *i)
 {
 	struct cx231xx_fh *fh = priv;
@@ -1192,7 +1076,7 @@ static int vidioc_enum_input(struct file *file, void *priv,
 	return 0;
 }
 
-static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
+int cx231xx_g_input(struct file *file, void *priv, unsigned int *i)
 {
 	struct cx231xx_fh *fh = priv;
 	struct cx231xx *dev = fh->dev;
@@ -1202,7 +1086,7 @@ static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
 	return 0;
 }
 
-static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
+int cx231xx_s_input(struct file *file, void *priv, unsigned int i)
 {
 	struct cx231xx_fh *fh = priv;
 	struct cx231xx *dev = fh->dev;
@@ -1231,117 +1115,7 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
 	return 0;
 }
 
-static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
-{
-	struct cx231xx_fh *fh = priv;
-	struct cx231xx *dev = fh->dev;
-
-	switch (a->index) {
-	case CX231XX_AMUX_VIDEO:
-		strcpy(a->name, "Television");
-		break;
-	case CX231XX_AMUX_LINE_IN:
-		strcpy(a->name, "Line In");
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	a->index = dev->ctl_ainput;
-	a->capability = V4L2_AUDCAP_STEREO;
-
-	return 0;
-}
-
-static int vidioc_s_audio(struct file *file, void *priv, const struct v4l2_audio *a)
-{
-	struct cx231xx_fh *fh = priv;
-	struct cx231xx *dev = fh->dev;
-	int status = 0;
-
-	/* Doesn't allow manual routing */
-	if (a->index != dev->ctl_ainput)
-		return -EINVAL;
-
-	dev->ctl_ainput = INPUT(a->index)->amux;
-	status = cx231xx_set_audio_input(dev, dev->ctl_ainput);
-
-	return status;
-}
-
-static int vidioc_queryctrl(struct file *file, void *priv,
-			    struct v4l2_queryctrl *qc)
-{
-	struct cx231xx_fh *fh = priv;
-	struct cx231xx *dev = fh->dev;
-	int id = qc->id;
-	int i;
-	int rc;
-
-	rc = check_dev(dev);
-	if (rc < 0)
-		return rc;
-
-	qc->id = v4l2_ctrl_next(ctrl_classes, qc->id);
-	if (unlikely(qc->id == 0))
-		return -EINVAL;
-
-	memset(qc, 0, sizeof(*qc));
-
-	qc->id = id;
-
-	if (qc->id < V4L2_CID_BASE || qc->id >= V4L2_CID_LASTP1)
-		return -EINVAL;
-
-	for (i = 0; i < CX231XX_CTLS; i++)
-		if (cx231xx_ctls[i].v.id == qc->id)
-			break;
-
-	if (i == CX231XX_CTLS) {
-		*qc = no_ctl;
-		return 0;
-	}
-	*qc = cx231xx_ctls[i].v;
-
-	call_all(dev, core, queryctrl, qc);
-
-	if (qc->type)
-		return 0;
-	else
-		return -EINVAL;
-}
-
-static int vidioc_g_ctrl(struct file *file, void *priv,
-			 struct v4l2_control *ctrl)
-{
-	struct cx231xx_fh *fh = priv;
-	struct cx231xx *dev = fh->dev;
-	int rc;
-
-	rc = check_dev(dev);
-	if (rc < 0)
-		return rc;
-
-	call_all(dev, core, g_ctrl, ctrl);
-	return rc;
-}
-
-static int vidioc_s_ctrl(struct file *file, void *priv,
-			 struct v4l2_control *ctrl)
-{
-	struct cx231xx_fh *fh = priv;
-	struct cx231xx *dev = fh->dev;
-	int rc;
-
-	rc = check_dev(dev);
-	if (rc < 0)
-		return rc;
-
-	call_all(dev, core, s_ctrl, ctrl);
-	return rc;
-}
-
-static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
+int cx231xx_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
 {
 	struct cx231xx_fh *fh = priv;
 	struct cx231xx *dev = fh->dev;
@@ -1360,11 +1134,12 @@ static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
 	t->capability = V4L2_TUNER_CAP_NORM;
 	t->rangehigh = 0xffffffffUL;
 	t->signal = 0xffff;	/* LOCKED */
+	call_all(dev, tuner, g_tuner, t);
 
 	return 0;
 }
 
-static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
+int cx231xx_s_tuner(struct file *file, void *priv, const struct v4l2_tuner *t)
 {
 	struct cx231xx_fh *fh = priv;
 	struct cx231xx *dev = fh->dev;
@@ -1382,25 +1157,26 @@ static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
 	return 0;
 }
 
-static int vidioc_g_frequency(struct file *file, void *priv,
+int cx231xx_g_frequency(struct file *file, void *priv,
 			      struct v4l2_frequency *f)
 {
 	struct cx231xx_fh *fh = priv;
 	struct cx231xx *dev = fh->dev;
 
-	f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
-	f->frequency = dev->ctl_freq;
+	if (f->tuner)
+		return -EINVAL;
 
-	call_all(dev, tuner, g_frequency, f);
+	f->frequency = dev->ctl_freq;
 
 	return 0;
 }
 
-static int vidioc_s_frequency(struct file *file, void *priv,
-			      struct v4l2_frequency *f)
+int cx231xx_s_frequency(struct file *file, void *priv,
+			      const struct v4l2_frequency *f)
 {
 	struct cx231xx_fh *fh = priv;
 	struct cx231xx *dev = fh->dev;
+	struct v4l2_frequency new_freq = *f;
 	int rc;
 	u32 if_frequency = 5400000;
 
@@ -1415,16 +1191,12 @@ static int vidioc_s_frequency(struct file *file, void *priv,
 	if (0 != f->tuner)
 		return -EINVAL;
 
-	if (unlikely(0 == fh->radio && f->type != V4L2_TUNER_ANALOG_TV))
-		return -EINVAL;
-	if (unlikely(1 == fh->radio && f->type != V4L2_TUNER_RADIO))
-		return -EINVAL;
-
 	/* set pre channel change settings in DIF first */
 	rc = cx231xx_tuner_pre_channel_change(dev);
 
-	dev->ctl_freq = f->frequency;
 	call_all(dev, tuner, s_frequency, f);
+	call_all(dev, tuner, g_frequency, &new_freq);
+	dev->ctl_freq = new_freq.frequency;
 
 	/* set post channel change settings in DIF first */
 	rc = cx231xx_tuner_post_channel_change(dev);
@@ -1456,6 +1228,19 @@ static int vidioc_s_frequency(struct file *file, void *priv,
 	return rc;
 }
 
+int cx231xx_g_chip_ident(struct file *file, void *fh,
+			struct v4l2_dbg_chip_ident *chip)
+{
+	chip->ident = V4L2_IDENT_NONE;
+	chip->revision = 0;
+	if (chip->match.type == V4L2_CHIP_MATCH_HOST) {
+		if (v4l2_chip_match_host(&chip->match))
+			chip->ident = V4L2_IDENT_CX23100;
+		return 0;
+	}
+	return -EINVAL;
+}
+
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 
 /*
@@ -1471,7 +1256,7 @@ static int vidioc_s_frequency(struct file *file, void *priv,
   if type == i2caddr, then <chip> is the 7-bit I2C address
 */
 
-static int vidioc_g_register(struct file *file, void *priv,
+int cx231xx_g_register(struct file *file, void *priv,
 			     struct v4l2_dbg_register *reg)
 {
 	struct cx231xx_fh *fh = priv;
@@ -1618,8 +1403,8 @@ static int vidioc_g_register(struct file *file, void *priv,
 	return ret;
 }
 
-static int vidioc_s_register(struct file *file, void *priv,
-			     struct v4l2_dbg_register *reg)
+int cx231xx_s_register(struct file *file, void *priv,
+			     const struct v4l2_dbg_register *reg)
 {
 	struct cx231xx_fh *fh = priv;
 	struct cx231xx *dev = fh->dev;
@@ -1837,9 +1622,6 @@ static int vidioc_streamoff(struct file *file, void *priv,
 	if (rc < 0)
 		return rc;
 
-	if ((fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
-	    (fh->type != V4L2_BUF_TYPE_VBI_CAPTURE))
-		return -EINVAL;
 	if (type != fh->type)
 		return -EINVAL;
 
@@ -1851,9 +1633,10 @@ static int vidioc_streamoff(struct file *file, void *priv,
 	return 0;
 }
 
-static int vidioc_querycap(struct file *file, void *priv,
+int cx231xx_querycap(struct file *file, void *priv,
 			   struct v4l2_capability *cap)
 {
+	struct video_device *vdev = video_devdata(file);
 	struct cx231xx_fh *fh = priv;
 	struct cx231xx *dev = fh->dev;
 
@@ -1861,17 +1644,22 @@ static int vidioc_querycap(struct file *file, void *priv,
 	strlcpy(cap->card, cx231xx_boards[dev->model].name, sizeof(cap->card));
 	usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
 
-	cap->capabilities = V4L2_CAP_VBI_CAPTURE |
-#if 0
-		V4L2_CAP_SLICED_VBI_CAPTURE |
-#endif
-		V4L2_CAP_VIDEO_CAPTURE	|
-		V4L2_CAP_AUDIO		|
-		V4L2_CAP_READWRITE	|
-		V4L2_CAP_STREAMING;
-
+	if (vdev->vfl_type == VFL_TYPE_RADIO)
+		cap->device_caps = V4L2_CAP_RADIO;
+	else {
+		cap->device_caps = V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
+		if (vdev->vfl_type == VFL_TYPE_VBI)
+			cap->device_caps |= V4L2_CAP_VBI_CAPTURE;
+		else
+			cap->device_caps |= V4L2_CAP_VIDEO_CAPTURE;
+	}
 	if (dev->tuner_type != TUNER_ABSENT)
-		cap->capabilities |= V4L2_CAP_TUNER;
+		cap->device_caps |= V4L2_CAP_TUNER;
+	cap->capabilities = cap->device_caps | V4L2_CAP_READWRITE |
+		V4L2_CAP_VBI_CAPTURE | V4L2_CAP_VIDEO_CAPTURE |
+		V4L2_CAP_STREAMING | V4L2_CAP_DEVICE_CAPS;
+	if (dev->radio_dev)
+		cap->capabilities |= V4L2_CAP_RADIO;
 
 	return 0;
 }
@@ -1888,47 +1676,6 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
 	return 0;
 }
 
-/* Sliced VBI ioctls */
-static int vidioc_g_fmt_sliced_vbi_cap(struct file *file, void *priv,
-				       struct v4l2_format *f)
-{
-	struct cx231xx_fh *fh = priv;
-	struct cx231xx *dev = fh->dev;
-	int rc;
-
-	rc = check_dev(dev);
-	if (rc < 0)
-		return rc;
-
-	f->fmt.sliced.service_set = 0;
-
-	call_all(dev, vbi, g_sliced_fmt, &f->fmt.sliced);
-
-	if (f->fmt.sliced.service_set == 0)
-		rc = -EINVAL;
-
-	return rc;
-}
-
-static int vidioc_try_set_sliced_vbi_cap(struct file *file, void *priv,
-					 struct v4l2_format *f)
-{
-	struct cx231xx_fh *fh = priv;
-	struct cx231xx *dev = fh->dev;
-	int rc;
-
-	rc = check_dev(dev);
-	if (rc < 0)
-		return rc;
-
-	call_all(dev, vbi, g_sliced_fmt, &f->fmt.sliced);
-
-	if (f->fmt.sliced.service_set == 0)
-		return -EINVAL;
-
-	return 0;
-}
-
 /* RAW VBI ioctls */
 
 static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv,
@@ -1936,6 +1683,7 @@ static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv,
 {
 	struct cx231xx_fh *fh = priv;
 	struct cx231xx *dev = fh->dev;
+
 	f->fmt.vbi.sampling_rate = 6750000 * 4;
 	f->fmt.vbi.samples_per_line = VBI_LINE_LENGTH;
 	f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
@@ -1947,6 +1695,7 @@ static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv,
 	f->fmt.vbi.start[1] = (dev->norm & V4L2_STD_625_50) ?
 	    PAL_VBI_START_LINE + 312 : NTSC_VBI_START_LINE + 263;
 	f->fmt.vbi.count[1] = f->fmt.vbi.count[0];
+	memset(f->fmt.vbi.reserved, 0, sizeof(f->fmt.vbi.reserved));
 
 	return 0;
 
@@ -1958,12 +1707,6 @@ static int vidioc_try_fmt_vbi_cap(struct file *file, void *priv,
 	struct cx231xx_fh *fh = priv;
 	struct cx231xx *dev = fh->dev;
 
-	if (dev->vbi_stream_on && !fh->stream_on) {
-		cx231xx_errdev("%s device in use by another fh\n", __func__);
-		return -EBUSY;
-	}
-
-	f->type = V4L2_BUF_TYPE_VBI_CAPTURE;
 	f->fmt.vbi.sampling_rate = 6750000 * 4;
 	f->fmt.vbi.samples_per_line = VBI_LINE_LENGTH;
 	f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
@@ -1976,11 +1719,25 @@ static int vidioc_try_fmt_vbi_cap(struct file *file, void *priv,
 	f->fmt.vbi.start[1] = (dev->norm & V4L2_STD_625_50) ?
 	    PAL_VBI_START_LINE + 312 : NTSC_VBI_START_LINE + 263;
 	f->fmt.vbi.count[1] = f->fmt.vbi.count[0];
+	memset(f->fmt.vbi.reserved, 0, sizeof(f->fmt.vbi.reserved));
 
 	return 0;
 
 }
 
+static int vidioc_s_fmt_vbi_cap(struct file *file, void *priv,
+				  struct v4l2_format *f)
+{
+	struct cx231xx_fh *fh = priv;
+	struct cx231xx *dev = fh->dev;
+
+	if (dev->vbi_stream_on && !fh->stream_on) {
+		cx231xx_errdev("%s device in use by another fh\n", __func__);
+		return -EBUSY;
+	}
+	return vidioc_try_fmt_vbi_cap(file, priv, f);
+}
+
 static int vidioc_reqbufs(struct file *file, void *priv,
 			  struct v4l2_requestbuffers *rb)
 {
@@ -2038,58 +1795,24 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
 /* RADIO ESPECIFIC IOCTLS                                      */
 /* ----------------------------------------------------------- */
 
-static int radio_querycap(struct file *file, void *priv,
-			  struct v4l2_capability *cap)
-{
-	struct cx231xx *dev = ((struct cx231xx_fh *)priv)->dev;
-
-	strlcpy(cap->driver, "cx231xx", sizeof(cap->driver));
-	strlcpy(cap->card, cx231xx_boards[dev->model].name, sizeof(cap->card));
-	usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
-
-	cap->capabilities = V4L2_CAP_TUNER;
-	return 0;
-}
-
 static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
 {
 	struct cx231xx *dev = ((struct cx231xx_fh *)priv)->dev;
 
-	if (unlikely(t->index > 0))
+	if (t->index)
 		return -EINVAL;
 
 	strcpy(t->name, "Radio");
-	t->type = V4L2_TUNER_RADIO;
-
-	call_all(dev, tuner, s_tuner, t);
-
-	return 0;
-}
 
-static int radio_enum_input(struct file *file, void *priv, struct v4l2_input *i)
-{
-	if (i->index != 0)
-		return -EINVAL;
-	strcpy(i->name, "Radio");
-	i->type = V4L2_INPUT_TYPE_TUNER;
+	call_all(dev, tuner, g_tuner, t);
 
 	return 0;
 }
-
-static int radio_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
-{
-	if (unlikely(a->index))
-		return -EINVAL;
-
-	strcpy(a->name, "Radio");
-	return 0;
-}
-
-static int radio_s_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
+static int radio_s_tuner(struct file *file, void *priv, const struct v4l2_tuner *t)
 {
 	struct cx231xx *dev = ((struct cx231xx_fh *)priv)->dev;
 
-	if (0 != t->index)
+	if (t->index)
 		return -EINVAL;
 
 	call_all(dev, tuner, s_tuner, t);
@@ -2097,36 +1820,6 @@ static int radio_s_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
 	return 0;
 }
 
-static int radio_s_audio(struct file *file, void *fh, const struct v4l2_audio *a)
-{
-	return 0;
-}
-
-static int radio_s_input(struct file *file, void *fh, unsigned int i)
-{
-	return 0;
-}
-
-static int radio_queryctrl(struct file *file, void *priv,
-			   struct v4l2_queryctrl *c)
-{
-	int i;
-
-	if (c->id < V4L2_CID_BASE || c->id >= V4L2_CID_LASTP1)
-		return -EINVAL;
-	if (c->id == V4L2_CID_AUDIO_MUTE) {
-		for (i = 0; i < CX231XX_CTLS; i++) {
-			if (cx231xx_ctls[i].v.id == c->id)
-				break;
-		}
-		if (i == CX231XX_CTLS)
-			return -EINVAL;
-		*c = cx231xx_ctls[i].v;
-	} else
-		*c = no_ctl;
-	return 0;
-}
-
 /*
  * cx231xx_v4l2_open()
  * inits the device and starts isoc transfer
@@ -2174,14 +1867,11 @@ static int cx231xx_v4l2_open(struct file *filp)
 		return -ERESTARTSYS;
 	}
 	fh->dev = dev;
-	fh->radio = radio;
 	fh->type = fh_type;
 	filp->private_data = fh;
+	v4l2_fh_init(&fh->fh, vdev);
 
 	if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) {
-		dev->width = norm_maxw(dev);
-		dev->height = norm_maxh(dev);
-
 		/* Power up in Analog TV mode */
 		if (dev->board.external_av)
 			cx231xx_set_power_mode(dev,
@@ -2204,7 +1894,7 @@ static int cx231xx_v4l2_open(struct file *filp)
 		dev->video_input = dev->video_input > 2 ? 2 : dev->video_input;
 
 	}
-	if (fh->radio) {
+	if (radio) {
 		cx231xx_videodbg("video_open: setting radio device\n");
 
 		/* cx231xx_start_radio(dev); */
@@ -2232,6 +1922,7 @@ static int cx231xx_v4l2_open(struct file *filp)
 					    fh, &dev->lock);
 	}
 	mutex_unlock(&dev->lock);
+	v4l2_fh_add(&fh->fh);
 
 	return errCode;
 }
@@ -2275,6 +1966,8 @@ void cx231xx_release_analog_resources(struct cx231xx *dev)
 			video_device_release(dev->vdev);
 		dev->vdev = NULL;
 	}
+	v4l2_ctrl_handler_free(&dev->ctrl_handler);
+	v4l2_ctrl_handler_free(&dev->radio_ctrl_handler);
 }
 
 /*
@@ -2324,12 +2017,15 @@ static int cx231xx_close(struct file *filp)
 			else
 				cx231xx_set_alt_setting(dev, INDEX_HANC, 0);
 
+			v4l2_fh_del(&fh->fh);
+			v4l2_fh_exit(&fh->fh);
 			kfree(fh);
 			dev->users--;
 			wake_up_interruptible_nr(&dev->open, 1);
 			return 0;
 		}
 
+	v4l2_fh_del(&fh->fh);
 	dev->users--;
 	if (!dev->users) {
 		videobuf_stop(&fh->vb_vidq);
@@ -2356,6 +2052,7 @@ static int cx231xx_close(struct file *filp)
 		/* set alternate 0 */
 		cx231xx_set_alt_setting(dev, INDEX_VIDEO, 0);
 	}
+	v4l2_fh_exit(&fh->fh);
 	kfree(fh);
 	wake_up_interruptible_nr(&dev->open, 1);
 	return 0;
@@ -2412,29 +2109,37 @@ cx231xx_v4l2_read(struct file *filp, char __user *buf, size_t count,
  */
 static unsigned int cx231xx_v4l2_poll(struct file *filp, poll_table *wait)
 {
+	unsigned long req_events = poll_requested_events(wait);
 	struct cx231xx_fh *fh = filp->private_data;
 	struct cx231xx *dev = fh->dev;
+	unsigned res = 0;
 	int rc;
 
 	rc = check_dev(dev);
 	if (rc < 0)
-		return rc;
+		return POLLERR;
 
 	rc = res_get(fh);
 
 	if (unlikely(rc < 0))
 		return POLLERR;
 
+	if (v4l2_event_pending(&fh->fh))
+		res |= POLLPRI;
+	else
+		poll_wait(filp, &fh->fh.wait, wait);
+
+	if (!(req_events & (POLLIN | POLLRDNORM)))
+		return res;
+
 	if ((V4L2_BUF_TYPE_VIDEO_CAPTURE == fh->type) ||
 	    (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type)) {
-		unsigned int res;
-
 		mutex_lock(&dev->lock);
-		res = videobuf_poll_stream(filp, &fh->vb_vidq, wait);
+		res |= videobuf_poll_stream(filp, &fh->vb_vidq, wait);
 		mutex_unlock(&dev->lock);
 		return res;
 	}
-	return POLLERR;
+	return res | POLLERR;
 }
 
 /*
@@ -2479,41 +2184,37 @@ static const struct v4l2_file_operations cx231xx_v4l_fops = {
 };
 
 static const struct v4l2_ioctl_ops video_ioctl_ops = {
-	.vidioc_querycap               = vidioc_querycap,
+	.vidioc_querycap               = cx231xx_querycap,
 	.vidioc_enum_fmt_vid_cap       = vidioc_enum_fmt_vid_cap,
 	.vidioc_g_fmt_vid_cap          = vidioc_g_fmt_vid_cap,
 	.vidioc_try_fmt_vid_cap        = vidioc_try_fmt_vid_cap,
 	.vidioc_s_fmt_vid_cap          = vidioc_s_fmt_vid_cap,
 	.vidioc_g_fmt_vbi_cap          = vidioc_g_fmt_vbi_cap,
 	.vidioc_try_fmt_vbi_cap        = vidioc_try_fmt_vbi_cap,
-	.vidioc_s_fmt_vbi_cap          = vidioc_try_fmt_vbi_cap,
-	.vidioc_g_audio                =  vidioc_g_audio,
-	.vidioc_s_audio                = vidioc_s_audio,
+	.vidioc_s_fmt_vbi_cap          = vidioc_s_fmt_vbi_cap,
 	.vidioc_cropcap                = vidioc_cropcap,
-	.vidioc_g_fmt_sliced_vbi_cap   = vidioc_g_fmt_sliced_vbi_cap,
-	.vidioc_try_fmt_sliced_vbi_cap = vidioc_try_set_sliced_vbi_cap,
 	.vidioc_reqbufs                = vidioc_reqbufs,
 	.vidioc_querybuf               = vidioc_querybuf,
 	.vidioc_qbuf                   = vidioc_qbuf,
 	.vidioc_dqbuf                  = vidioc_dqbuf,
 	.vidioc_s_std                  = vidioc_s_std,
 	.vidioc_g_std                  = vidioc_g_std,
-	.vidioc_enum_input             = vidioc_enum_input,
-	.vidioc_g_input                = vidioc_g_input,
-	.vidioc_s_input                = vidioc_s_input,
-	.vidioc_queryctrl              = vidioc_queryctrl,
-	.vidioc_g_ctrl                 = vidioc_g_ctrl,
-	.vidioc_s_ctrl                 = vidioc_s_ctrl,
+	.vidioc_enum_input             = cx231xx_enum_input,
+	.vidioc_g_input                = cx231xx_g_input,
+	.vidioc_s_input                = cx231xx_s_input,
 	.vidioc_streamon               = vidioc_streamon,
 	.vidioc_streamoff              = vidioc_streamoff,
-	.vidioc_g_tuner                = vidioc_g_tuner,
-	.vidioc_s_tuner                = vidioc_s_tuner,
-	.vidioc_g_frequency            = vidioc_g_frequency,
-	.vidioc_s_frequency            = vidioc_s_frequency,
+	.vidioc_g_tuner                = cx231xx_g_tuner,
+	.vidioc_s_tuner                = cx231xx_s_tuner,
+	.vidioc_g_frequency            = cx231xx_g_frequency,
+	.vidioc_s_frequency            = cx231xx_s_frequency,
+	.vidioc_g_chip_ident           = cx231xx_g_chip_ident,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
-	.vidioc_g_register             = vidioc_g_register,
-	.vidioc_s_register             = vidioc_s_register,
+	.vidioc_g_register             = cx231xx_g_register,
+	.vidioc_s_register             = cx231xx_s_register,
 #endif
+	.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
+	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
 };
 
 static struct video_device cx231xx_vbi_template;
@@ -2523,33 +2224,29 @@ static const struct video_device cx231xx_video_template = {
 	.release      = video_device_release,
 	.ioctl_ops    = &video_ioctl_ops,
 	.tvnorms      = V4L2_STD_ALL,
-	.current_norm = V4L2_STD_PAL,
 };
 
 static const struct v4l2_file_operations radio_fops = {
 	.owner   = THIS_MODULE,
 	.open   = cx231xx_v4l2_open,
 	.release = cx231xx_v4l2_close,
-	.ioctl   = video_ioctl2,
+	.poll = v4l2_ctrl_poll,
+	.unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops radio_ioctl_ops = {
-	.vidioc_querycap    = radio_querycap,
+	.vidioc_querycap    = cx231xx_querycap,
 	.vidioc_g_tuner     = radio_g_tuner,
-	.vidioc_enum_input  = radio_enum_input,
-	.vidioc_g_audio     = radio_g_audio,
 	.vidioc_s_tuner     = radio_s_tuner,
-	.vidioc_s_audio     = radio_s_audio,
-	.vidioc_s_input     = radio_s_input,
-	.vidioc_queryctrl   = radio_queryctrl,
-	.vidioc_g_ctrl      = vidioc_g_ctrl,
-	.vidioc_s_ctrl      = vidioc_s_ctrl,
-	.vidioc_g_frequency = vidioc_g_frequency,
-	.vidioc_s_frequency = vidioc_s_frequency,
+	.vidioc_g_frequency = cx231xx_g_frequency,
+	.vidioc_s_frequency = cx231xx_s_frequency,
+	.vidioc_g_chip_ident = cx231xx_g_chip_ident,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
-	.vidioc_g_register  = vidioc_g_register,
-	.vidioc_s_register  = vidioc_s_register,
+	.vidioc_g_register  = cx231xx_g_register,
+	.vidioc_s_register  = cx231xx_s_register,
 #endif
+	.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
+	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
 };
 
 static struct video_device cx231xx_radio_template = {
@@ -2575,10 +2272,17 @@ static struct video_device *cx231xx_vdev_init(struct cx231xx *dev,
 	vfd->release = video_device_release;
 	vfd->debug = video_debug;
 	vfd->lock = &dev->lock;
+	set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
 
 	snprintf(vfd->name, sizeof(vfd->name), "%s %s", dev->name, type_name);
 
 	video_set_drvdata(vfd, dev);
+	if (dev->tuner_type == TUNER_ABSENT) {
+		v4l2_disable_ioctl(vfd, VIDIOC_G_FREQUENCY);
+		v4l2_disable_ioctl(vfd, VIDIOC_S_FREQUENCY);
+		v4l2_disable_ioctl(vfd, VIDIOC_G_TUNER);
+		v4l2_disable_ioctl(vfd, VIDIOC_S_TUNER);
+	}
 	return vfd;
 }
 
@@ -2590,7 +2294,7 @@ int cx231xx_register_analog_devices(struct cx231xx *dev)
 		     dev->name, CX231XX_VERSION);
 
 	/* set default norm */
-	/*dev->norm = cx231xx_video_template.current_norm; */
+	dev->norm = V4L2_STD_PAL;
 	dev->width = norm_maxw(dev);
 	dev->height = norm_maxh(dev);
 	dev->interlaced = 0;
@@ -2601,9 +2305,23 @@ int cx231xx_register_analog_devices(struct cx231xx *dev)
 	/* Set the initial input */
 	video_mux(dev, dev->video_input);
 
-	/* Audio defaults */
-	dev->mute = 1;
-	dev->volume = 0x1f;
+	call_all(dev, core, s_std, dev->norm);
+
+	v4l2_ctrl_handler_init(&dev->ctrl_handler, 10);
+	v4l2_ctrl_handler_init(&dev->radio_ctrl_handler, 5);
+
+	if (dev->sd_cx25840) {
+		v4l2_ctrl_add_handler(&dev->ctrl_handler,
+				dev->sd_cx25840->ctrl_handler, NULL);
+		v4l2_ctrl_add_handler(&dev->radio_ctrl_handler,
+				dev->sd_cx25840->ctrl_handler,
+				v4l2_ctrl_radio_filter);
+	}
+
+	if (dev->ctrl_handler.error)
+		return dev->ctrl_handler.error;
+	if (dev->radio_ctrl_handler.error)
+		return dev->radio_ctrl_handler.error;
 
 	/* enable vbi capturing */
 	/* write code here...  */
@@ -2615,6 +2333,7 @@ int cx231xx_register_analog_devices(struct cx231xx *dev)
 		return -ENODEV;
 	}
 
+	dev->vdev->ctrl_handler = &dev->ctrl_handler;
 	/* register v4l2 video video_device */
 	ret = video_register_device(dev->vdev, VFL_TYPE_GRABBER,
 				    video_nr[dev->devno]);
@@ -2634,6 +2353,11 @@ int cx231xx_register_analog_devices(struct cx231xx *dev)
 	/* Allocate and fill vbi video_device struct */
 	dev->vbi_dev = cx231xx_vdev_init(dev, &cx231xx_vbi_template, "vbi");
 
+	if (!dev->vbi_dev) {
+		cx231xx_errdev("cannot allocate video_device.\n");
+		return -ENODEV;
+	}
+	dev->vbi_dev->ctrl_handler = &dev->ctrl_handler;
 	/* register v4l2 vbi video_device */
 	ret = video_register_device(dev->vbi_dev, VFL_TYPE_VBI,
 				    vbi_nr[dev->devno]);
@@ -2652,6 +2376,7 @@ int cx231xx_register_analog_devices(struct cx231xx *dev)
 			cx231xx_errdev("cannot allocate video_device.\n");
 			return -ENODEV;
 		}
+		dev->radio_dev->ctrl_handler = &dev->radio_ctrl_handler;
 		ret = video_register_device(dev->radio_dev, VFL_TYPE_RADIO,
 					    radio_nr[dev->devno]);
 		if (ret < 0) {
diff --git a/drivers/media/usb/cx231xx/cx231xx.h b/drivers/media/usb/cx231xx/cx231xx.h
index 3e11462..5ad9fd6 100644
--- a/drivers/media/usb/cx231xx/cx231xx.h
+++ b/drivers/media/usb/cx231xx/cx231xx.h
@@ -33,6 +33,8 @@
 
 #include <media/videobuf-vmalloc.h>
 #include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-fh.h>
 #include <media/rc-core.h>
 #include <media/ir-kbd-i2c.h>
 #include <media/videobuf-dvb.h>
@@ -69,6 +71,7 @@
 #define CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL 14
 #define CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC 15
 #define CX231XX_BOARD_ELGATO_VIDEO_CAPTURE_V2 16
+#define CX231XX_BOARD_OTG102 17
 
 /* Limits minimum and default number of buffers */
 #define CX231XX_MIN_BUF                 4
@@ -428,27 +431,12 @@ struct cx231xx_audio {
 struct cx231xx;
 
 struct cx231xx_fh {
+	struct v4l2_fh fh;
 	struct cx231xx *dev;
 	unsigned int stream_on:1;	/* Locks streams */
-	int radio;
-
-	struct videobuf_queue vb_vidq;
-
 	enum v4l2_buf_type type;
 
-
-
-/*following is copyed from cx23885.h*/
-	u32                        resources;
-
-	/* video overlay */
-	struct v4l2_window         win;
-	struct v4l2_clip           *clips;
-	unsigned int               nclips;
-
-	/* video capture */
-	struct cx23417_fmt         *fmt;
-	unsigned int               width, height;
+	struct videobuf_queue vb_vidq;
 
 	/* vbi capture */
 	struct videobuf_queue      vidq;
@@ -516,14 +504,6 @@ struct cx231xx_tvnorm {
 	u32		cxoformat;
 };
 
-struct cx231xx_ctrl {
-	struct v4l2_queryctrl v;
-	u32 off;
-	u32 reg;
-	u32 mask;
-	u32 shift;
-};
-
 enum TRANSFER_TYPE {
 	Raw_Video = 0,
 	Audio,
@@ -631,6 +611,9 @@ struct cx231xx {
 	struct v4l2_device v4l2_dev;
 	struct v4l2_subdev *sd_cx25840;
 	struct v4l2_subdev *sd_tuner;
+	struct v4l2_ctrl_handler ctrl_handler;
+	struct v4l2_ctrl_handler radio_ctrl_handler;
+	struct cx2341x_handler mpeg_ctrl_handler;
 
 	struct work_struct wq_trigger;		/* Trigger to start/stop audio for alsa module */
 	atomic_t	   stream_started;	/* stream should be running if true */
@@ -653,8 +636,6 @@ struct cx231xx {
 	v4l2_std_id norm;	/* selected tv norm */
 	int ctl_freq;		/* selected frequency */
 	unsigned int ctl_ainput;	/* selected audio input */
-	int mute;
-	int volume;
 
 	/* frame properties */
 	int width;		/* current frame width */
@@ -736,7 +717,6 @@ struct cx231xx {
 	u8 USE_ISO;
 	struct cx231xx_tvnorm      encodernorm;
 	struct cx231xx_tsport      ts1, ts2;
-	struct cx2341x_mpeg_params mpeg_params;
 	struct video_device        *v4l_device;
 	atomic_t                   v4l_reader_count;
 	u32                        freq;
@@ -866,8 +846,6 @@ int cx231xx_send_usb_command(struct cx231xx_i2c *i2c_bus,
 /* Gpio related functions */
 int cx231xx_send_gpio_cmd(struct cx231xx *dev, u32 gpio_bit, u8 *gpio_val,
 			  u8 len, u8 request, u8 direction);
-int cx231xx_set_gpio_bit(struct cx231xx *dev, u32 gpio_bit, u8 *gpio_val);
-int cx231xx_get_gpio_bit(struct cx231xx *dev, u32 gpio_bit, u8 *gpio_val);
 int cx231xx_set_gpio_value(struct cx231xx *dev, int pin_number, int pin_value);
 int cx231xx_set_gpio_direction(struct cx231xx *dev, int pin_number,
 			       int pin_value);
@@ -955,6 +933,23 @@ int cx231xx_register_extension(struct cx231xx_ops *dev);
 void cx231xx_unregister_extension(struct cx231xx_ops *dev);
 void cx231xx_init_extension(struct cx231xx *dev);
 void cx231xx_close_extension(struct cx231xx *dev);
+int cx231xx_querycap(struct file *file, void *priv,
+			   struct v4l2_capability *cap);
+int cx231xx_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t);
+int cx231xx_s_tuner(struct file *file, void *priv, const struct v4l2_tuner *t);
+int cx231xx_g_frequency(struct file *file, void *priv,
+			      struct v4l2_frequency *f);
+int cx231xx_s_frequency(struct file *file, void *priv,
+			      const struct v4l2_frequency *f);
+int cx231xx_enum_input(struct file *file, void *priv,
+			     struct v4l2_input *i);
+int cx231xx_g_input(struct file *file, void *priv, unsigned int *i);
+int cx231xx_s_input(struct file *file, void *priv, unsigned int i);
+int cx231xx_g_chip_ident(struct file *file, void *fh, struct v4l2_dbg_chip_ident *chip);
+int cx231xx_g_register(struct file *file, void *priv,
+			     struct v4l2_dbg_register *reg);
+int cx231xx_s_register(struct file *file, void *priv,
+			     const struct v4l2_dbg_register *reg);
 
 /* Provided by cx231xx-cards.c */
 extern void cx231xx_pre_card_setup(struct cx231xx *dev);
diff --git a/drivers/media/usb/dvb-usb-v2/Kconfig b/drivers/media/usb/dvb-usb-v2/Kconfig
index 692224d..2d4abfa 100644
--- a/drivers/media/usb/dvb-usb-v2/Kconfig
+++ b/drivers/media/usb/dvb-usb-v2/Kconfig
@@ -41,6 +41,7 @@ config DVB_USB_AF9035
 	select MEDIA_TUNER_MXL5007T if MEDIA_SUBDRV_AUTOSELECT
 	select MEDIA_TUNER_TDA18218 if MEDIA_SUBDRV_AUTOSELECT
 	select MEDIA_TUNER_FC2580 if MEDIA_SUBDRV_AUTOSELECT
+	select MEDIA_TUNER_IT913X if MEDIA_SUBDRV_AUTOSELECT
 	help
 	  Say Y here to support the Afatech AF9035 based DVB USB receiver.
 
diff --git a/drivers/media/usb/dvb-usb-v2/af9015.c b/drivers/media/usb/dvb-usb-v2/af9015.c
index b86d0f2..d556042 100644
--- a/drivers/media/usb/dvb-usb-v2/af9015.c
+++ b/drivers/media/usb/dvb-usb-v2/af9015.c
@@ -30,22 +30,22 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
 static int af9015_ctrl_msg(struct dvb_usb_device *d, struct req_t *req)
 {
-#define BUF_LEN 63
 #define REQ_HDR_LEN 8 /* send header size */
 #define ACK_HDR_LEN 2 /* rece header size */
 	struct af9015_state *state = d_to_priv(d);
 	int ret, wlen, rlen;
-	u8 buf[BUF_LEN];
 	u8 write = 1;
 
-	buf[0] = req->cmd;
-	buf[1] = state->seq++;
-	buf[2] = req->i2c_addr;
-	buf[3] = req->addr >> 8;
-	buf[4] = req->addr & 0xff;
-	buf[5] = req->mbox;
-	buf[6] = req->addr_len;
-	buf[7] = req->data_len;
+	mutex_lock(&d->usb_mutex);
+
+	state->buf[0] = req->cmd;
+	state->buf[1] = state->seq++;
+	state->buf[2] = req->i2c_addr;
+	state->buf[3] = req->addr >> 8;
+	state->buf[4] = req->addr & 0xff;
+	state->buf[5] = req->mbox;
+	state->buf[6] = req->addr_len;
+	state->buf[7] = req->data_len;
 
 	switch (req->cmd) {
 	case GET_CONFIG:
@@ -55,14 +55,14 @@ static int af9015_ctrl_msg(struct dvb_usb_device *d, struct req_t *req)
 		break;
 	case READ_I2C:
 		write = 0;
-		buf[2] |= 0x01; /* set I2C direction */
+		state->buf[2] |= 0x01; /* set I2C direction */
 	case WRITE_I2C:
-		buf[0] = READ_WRITE_I2C;
+		state->buf[0] = READ_WRITE_I2C;
 		break;
 	case WRITE_MEMORY:
 		if (((req->addr & 0xff00) == 0xff00) ||
 		    ((req->addr & 0xff00) == 0xae00))
-			buf[0] = WRITE_VIRTUAL_MEMORY;
+			state->buf[0] = WRITE_VIRTUAL_MEMORY;
 	case WRITE_VIRTUAL_MEMORY:
 	case COPY_FIRMWARE:
 	case DOWNLOAD_FIRMWARE:
@@ -90,7 +90,7 @@ static int af9015_ctrl_msg(struct dvb_usb_device *d, struct req_t *req)
 	rlen = ACK_HDR_LEN;
 	if (write) {
 		wlen += req->data_len;
-		memcpy(&buf[REQ_HDR_LEN], req->data, req->data_len);
+		memcpy(&state->buf[REQ_HDR_LEN], req->data, req->data_len);
 	} else {
 		rlen += req->data_len;
 	}
@@ -99,22 +99,25 @@ static int af9015_ctrl_msg(struct dvb_usb_device *d, struct req_t *req)
 	if (req->cmd == DOWNLOAD_FIRMWARE || req->cmd == RECONNECT_USB)
 		rlen = 0;
 
-	ret = dvb_usbv2_generic_rw(d, buf, wlen, buf, rlen);
+	ret = dvb_usbv2_generic_rw_locked(d,
+			state->buf, wlen, state->buf, rlen);
 	if (ret)
 		goto error;
 
 	/* check status */
-	if (rlen && buf[1]) {
+	if (rlen && state->buf[1]) {
 		dev_err(&d->udev->dev, "%s: command failed=%d\n",
-				KBUILD_MODNAME, buf[1]);
+				KBUILD_MODNAME, state->buf[1]);
 		ret = -EIO;
 		goto error;
 	}
 
 	/* read request, copy returned data to return buf */
 	if (!write)
-		memcpy(req->data, &buf[ACK_HDR_LEN], req->data_len);
+		memcpy(req->data, &state->buf[ACK_HDR_LEN], req->data_len);
 error:
+	mutex_unlock(&d->usb_mutex);
+
 	return ret;
 }
 
@@ -1317,6 +1320,43 @@ static int af9015_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc)
 	#define af9015_get_rc_config NULL
 #endif
 
+static int af9015_probe(struct usb_interface *intf,
+		const struct usb_device_id *id)
+{
+	struct usb_device *udev = interface_to_usbdev(intf);
+	char manufacturer[sizeof("ITE Technologies, Inc.")];
+
+	memset(manufacturer, 0, sizeof(manufacturer));
+	usb_string(udev, udev->descriptor.iManufacturer,
+			manufacturer, sizeof(manufacturer));
+	/*
+	 * There is two devices having same ID but different chipset. One uses
+	 * AF9015 and the other IT9135 chipset. Only difference seen on lsusb
+	 * is iManufacturer string.
+	 *
+	 * idVendor           0x0ccd TerraTec Electronic GmbH
+	 * idProduct          0x0099
+	 * bcdDevice            2.00
+	 * iManufacturer           1 Afatech
+	 * iProduct                2 DVB-T 2
+	 *
+	 * idVendor           0x0ccd TerraTec Electronic GmbH
+	 * idProduct          0x0099
+	 * bcdDevice            2.00
+	 * iManufacturer           1 ITE Technologies, Inc.
+	 * iProduct                2 DVB-T TV Stick
+	 */
+	if ((le16_to_cpu(udev->descriptor.idVendor) == USB_VID_TERRATEC) &&
+			(le16_to_cpu(udev->descriptor.idProduct) == 0x0099)) {
+		if (!strcmp("ITE Technologies, Inc.", manufacturer)) {
+			dev_dbg(&udev->dev, "%s: rejecting device\n", __func__);
+			return -ENODEV;
+		}
+	}
+
+	return dvb_usbv2_probe(intf, id);
+}
+
 /* interface 0 is used by DVB-T receiver and
    interface 1 is for remote controller (HID) */
 static struct dvb_usb_device_properties af9015_props = {
@@ -1425,6 +1465,7 @@ static const struct usb_device_id af9015_id_table[] = {
 		&af9015_props, "AverMedia AVerTV Volar M (A815Mac)", NULL) },
 	{ DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_STICK_RC,
 		&af9015_props, "TerraTec Cinergy T Stick RC", RC_MAP_TERRATEC_SLIM_2) },
+	/* XXX: that same ID [0ccd:0099] is used by af9035 driver too */
 	{ DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_STICK_DUAL_RC,
 		&af9015_props, "TerraTec Cinergy T Stick Dual RC", RC_MAP_TERRATEC_SLIM) },
 	{ DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A850T,
@@ -1441,7 +1482,7 @@ MODULE_DEVICE_TABLE(usb, af9015_id_table);
 static struct usb_driver af9015_usb_driver = {
 	.name = KBUILD_MODNAME,
 	.id_table = af9015_id_table,
-	.probe = dvb_usbv2_probe,
+	.probe = af9015_probe,
 	.disconnect = dvb_usbv2_disconnect,
 	.suspend = dvb_usbv2_suspend,
 	.resume = dvb_usbv2_resume,
diff --git a/drivers/media/usb/dvb-usb-v2/af9015.h b/drivers/media/usb/dvb-usb-v2/af9015.h
index 533637d..3a6f3ad 100644
--- a/drivers/media/usb/dvb-usb-v2/af9015.h
+++ b/drivers/media/usb/dvb-usb-v2/af9015.h
@@ -115,7 +115,9 @@ enum af9015_ir_mode {
 	AF9015_IR_MODE_POLLING, /* just guess */
 };
 
+#define BUF_LEN 63
 struct af9015_state {
+	u8 buf[BUF_LEN]; /* bulk USB control message */
 	u8 ir_mode;
 	u8 rc_repeat;
 	u32 rc_keycode;
diff --git a/drivers/media/usb/dvb-usb-v2/af9035.c b/drivers/media/usb/dvb-usb-v2/af9035.c
index f11cc42..b638fc1 100644
--- a/drivers/media/usb/dvb-usb-v2/af9035.c
+++ b/drivers/media/usb/dvb-usb-v2/af9035.c
@@ -41,79 +41,84 @@ static u16 af9035_checksum(const u8 *buf, size_t len)
 
 static int af9035_ctrl_msg(struct dvb_usb_device *d, struct usb_req *req)
 {
-#define BUF_LEN 64
 #define REQ_HDR_LEN 4 /* send header size */
 #define ACK_HDR_LEN 3 /* rece header size */
 #define CHECKSUM_LEN 2
 #define USB_TIMEOUT 2000
 	struct state *state = d_to_priv(d);
 	int ret, wlen, rlen;
-	u8 buf[BUF_LEN];
 	u16 checksum, tmp_checksum;
 
+	mutex_lock(&d->usb_mutex);
+
 	/* buffer overflow check */
 	if (req->wlen > (BUF_LEN - REQ_HDR_LEN - CHECKSUM_LEN) ||
 			req->rlen > (BUF_LEN - ACK_HDR_LEN - CHECKSUM_LEN)) {
 		dev_err(&d->udev->dev, "%s: too much data wlen=%d rlen=%d\n",
 				__func__, req->wlen, req->rlen);
-		return -EINVAL;
+		ret = -EINVAL;
+		goto exit;
 	}
 
-	buf[0] = REQ_HDR_LEN + req->wlen + CHECKSUM_LEN - 1;
-	buf[1] = req->mbox;
-	buf[2] = req->cmd;
-	buf[3] = state->seq++;
-	memcpy(&buf[REQ_HDR_LEN], req->wbuf, req->wlen);
+	state->buf[0] = REQ_HDR_LEN + req->wlen + CHECKSUM_LEN - 1;
+	state->buf[1] = req->mbox;
+	state->buf[2] = req->cmd;
+	state->buf[3] = state->seq++;
+	memcpy(&state->buf[REQ_HDR_LEN], req->wbuf, req->wlen);
 
 	wlen = REQ_HDR_LEN + req->wlen + CHECKSUM_LEN;
 	rlen = ACK_HDR_LEN + req->rlen + CHECKSUM_LEN;
 
 	/* calc and add checksum */
-	checksum = af9035_checksum(buf, buf[0] - 1);
-	buf[buf[0] - 1] = (checksum >> 8);
-	buf[buf[0] - 0] = (checksum & 0xff);
+	checksum = af9035_checksum(state->buf, state->buf[0] - 1);
+	state->buf[state->buf[0] - 1] = (checksum >> 8);
+	state->buf[state->buf[0] - 0] = (checksum & 0xff);
 
 	/* no ack for these packets */
 	if (req->cmd == CMD_FW_DL)
 		rlen = 0;
 
-	ret = dvb_usbv2_generic_rw(d, buf, wlen, buf, rlen);
+	ret = dvb_usbv2_generic_rw_locked(d,
+			state->buf, wlen, state->buf, rlen);
 	if (ret)
-		goto err;
+		goto exit;
 
 	/* no ack for those packets */
 	if (req->cmd == CMD_FW_DL)
 		goto exit;
 
 	/* verify checksum */
-	checksum = af9035_checksum(buf, rlen - 2);
-	tmp_checksum = (buf[rlen - 2] << 8) | buf[rlen - 1];
+	checksum = af9035_checksum(state->buf, rlen - 2);
+	tmp_checksum = (state->buf[rlen - 2] << 8) | state->buf[rlen - 1];
 	if (tmp_checksum != checksum) {
 		dev_err(&d->udev->dev, "%s: command=%02x checksum mismatch " \
 				"(%04x != %04x)\n", KBUILD_MODNAME, req->cmd,
 				tmp_checksum, checksum);
 		ret = -EIO;
-		goto err;
+		goto exit;
 	}
 
 	/* check status */
-	if (buf[2]) {
+	if (state->buf[2]) {
+		/* fw returns status 1 when IR code was not received */
+		if (req->cmd == CMD_IR_GET || state->buf[2] == 1) {
+			ret = 1;
+			goto exit;
+		}
+
 		dev_dbg(&d->udev->dev, "%s: command=%02x failed fw error=%d\n",
-				__func__, req->cmd, buf[2]);
+				__func__, req->cmd, state->buf[2]);
 		ret = -EIO;
-		goto err;
+		goto exit;
 	}
 
 	/* read request, copy returned data to return buf */
 	if (req->rlen)
-		memcpy(req->rbuf, &buf[ACK_HDR_LEN], req->rlen);
-
+		memcpy(req->rbuf, &state->buf[ACK_HDR_LEN], req->rlen);
 exit:
-	return 0;
-
-err:
-	dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
-
+	mutex_unlock(&d->usb_mutex);
+	if (ret < 0)
+		dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
 	return ret;
 }
 
@@ -292,12 +297,40 @@ static struct i2c_algorithm af9035_i2c_algo = {
 
 static int af9035_identify_state(struct dvb_usb_device *d, const char **name)
 {
+	struct state *state = d_to_priv(d);
 	int ret;
 	u8 wbuf[1] = { 1 };
 	u8 rbuf[4];
 	struct usb_req req = { CMD_FW_QUERYINFO, 0, sizeof(wbuf), wbuf,
 			sizeof(rbuf), rbuf };
 
+	ret = af9035_rd_regs(d, 0x1222, rbuf, 3);
+	if (ret < 0)
+		goto err;
+
+	state->chip_version = rbuf[0];
+	state->chip_type = rbuf[2] << 8 | rbuf[1] << 0;
+
+	ret = af9035_rd_reg(d, 0x384f, &state->prechip_version);
+	if (ret < 0)
+		goto err;
+
+	dev_info(&d->udev->dev,
+			"%s: prechip_version=%02x chip_version=%02x chip_type=%04x\n",
+			__func__, state->prechip_version, state->chip_version,
+			state->chip_type);
+
+	if (state->chip_type == 0x9135) {
+		if (state->chip_version == 0x02)
+			*name = AF9035_FIRMWARE_IT9135_V2;
+		else
+			*name = AF9035_FIRMWARE_IT9135_V1;
+		state->eeprom_addr = EEPROM_BASE_IT9135;
+	} else {
+		*name = AF9035_FIRMWARE_AF9035;
+		state->eeprom_addr = EEPROM_BASE_AF9035;
+	}
+
 	ret = af9035_ctrl_msg(d, &req);
 	if (ret < 0)
 		goto err;
@@ -316,66 +349,19 @@ err:
 	return ret;
 }
 
-static int af9035_download_firmware(struct dvb_usb_device *d,
+static int af9035_download_firmware_old(struct dvb_usb_device *d,
 		const struct firmware *fw)
 {
 	int ret, i, j, len;
 	u8 wbuf[1];
-	u8 rbuf[4];
 	struct usb_req req = { 0, 0, 0, NULL, 0, NULL };
 	struct usb_req req_fw_dl = { CMD_FW_DL, 0, 0, wbuf, 0, NULL };
-	struct usb_req req_fw_ver = { CMD_FW_QUERYINFO, 0, 1, wbuf, 4, rbuf } ;
-	u8 hdr_core, tmp;
+	u8 hdr_core;
 	u16 hdr_addr, hdr_data_len, hdr_checksum;
 	#define MAX_DATA 58
 	#define HDR_SIZE 7
 
 	/*
-	 * In case of dual tuner configuration we need to do some extra
-	 * initialization in order to download firmware to slave demod too,
-	 * which is done by master demod.
-	 * Master feeds also clock and controls power via GPIO.
-	 */
-	ret = af9035_rd_reg(d, EEPROM_DUAL_MODE, &tmp);
-	if (ret < 0)
-		goto err;
-
-	if (tmp) {
-		/* configure gpioh1, reset & power slave demod */
-		ret = af9035_wr_reg_mask(d, 0x00d8b0, 0x01, 0x01);
-		if (ret < 0)
-			goto err;
-
-		ret = af9035_wr_reg_mask(d, 0x00d8b1, 0x01, 0x01);
-		if (ret < 0)
-			goto err;
-
-		ret = af9035_wr_reg_mask(d, 0x00d8af, 0x00, 0x01);
-		if (ret < 0)
-			goto err;
-
-		usleep_range(10000, 50000);
-
-		ret = af9035_wr_reg_mask(d, 0x00d8af, 0x01, 0x01);
-		if (ret < 0)
-			goto err;
-
-		/* tell the slave I2C address */
-		ret = af9035_rd_reg(d, EEPROM_2ND_DEMOD_ADDR, &tmp);
-		if (ret < 0)
-			goto err;
-
-		ret = af9035_wr_reg(d, 0x00417f, tmp);
-		if (ret < 0)
-			goto err;
-
-		/* enable clock out */
-		ret = af9035_wr_reg_mask(d, 0x00d81a, 0x01, 0x01);
-		if (ret < 0)
-			goto err;
-	}
-
-	/*
 	 * Thanks to Daniel Glöckner <daniel-gl@gmx.net> about that info!
 	 *
 	 * byte 0: MCS 51 core
@@ -441,28 +427,6 @@ static int af9035_download_firmware(struct dvb_usb_device *d,
 	if (i)
 		dev_warn(&d->udev->dev, "%s: bad firmware\n", KBUILD_MODNAME);
 
-	/* firmware loaded, request boot */
-	req.cmd = CMD_FW_BOOT;
-	ret = af9035_ctrl_msg(d, &req);
-	if (ret < 0)
-		goto err;
-
-	/* ensure firmware starts */
-	wbuf[0] = 1;
-	ret = af9035_ctrl_msg(d, &req_fw_ver);
-	if (ret < 0)
-		goto err;
-
-	if (!(rbuf[0] || rbuf[1] || rbuf[2] || rbuf[3])) {
-		dev_err(&d->udev->dev, "%s: firmware did not run\n",
-				KBUILD_MODNAME);
-		ret = -ENODEV;
-		goto err;
-	}
-
-	dev_info(&d->udev->dev, "%s: firmware version=%d.%d.%d.%d",
-			KBUILD_MODNAME, rbuf[0], rbuf[1], rbuf[2], rbuf[3]);
-
 	return 0;
 
 err:
@@ -471,15 +435,11 @@ err:
 	return ret;
 }
 
-static int af9035_download_firmware_it9135(struct dvb_usb_device *d,
+static int af9035_download_firmware_new(struct dvb_usb_device *d,
 		const struct firmware *fw)
 {
 	int ret, i, i_prev;
-	u8 wbuf[1];
-	u8 rbuf[4];
-	struct usb_req req = { 0, 0, 0, NULL, 0, NULL };
 	struct usb_req req_fw_dl = { CMD_FW_SCATTER_WR, 0, 0, NULL, 0, NULL };
-	struct usb_req req_fw_ver = { CMD_FW_QUERYINFO, 0, 1, wbuf, 4, rbuf } ;
 	#define HDR_SIZE 7
 
 	/*
@@ -494,7 +454,6 @@ static int af9035_download_firmware_it9135(struct dvb_usb_device *d,
 	 * 5: addr LSB
 	 * 6: count of data bytes ?
 	 */
-
 	for (i = HDR_SIZE, i_prev = 0; i <= fw->size; i++) {
 		if (i == fw->size ||
 				(fw->data[i + 0] == 0x03 &&
@@ -513,6 +472,86 @@ static int af9035_download_firmware_it9135(struct dvb_usb_device *d,
 		}
 	}
 
+	return 0;
+
+err:
+	dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
+
+	return ret;
+}
+
+static int af9035_download_firmware(struct dvb_usb_device *d,
+		const struct firmware *fw)
+{
+	struct state *state = d_to_priv(d);
+	int ret;
+	u8 wbuf[1];
+	u8 rbuf[4];
+	u8 tmp;
+	struct usb_req req = { 0, 0, 0, NULL, 0, NULL };
+	struct usb_req req_fw_ver = { CMD_FW_QUERYINFO, 0, 1, wbuf, 4, rbuf } ;
+	dev_dbg(&d->udev->dev, "%s:\n", __func__);
+
+	/*
+	 * In case of dual tuner configuration we need to do some extra
+	 * initialization in order to download firmware to slave demod too,
+	 * which is done by master demod.
+	 * Master feeds also clock and controls power via GPIO.
+	 */
+	ret = af9035_rd_reg(d, state->eeprom_addr + EEPROM_DUAL_MODE, &tmp);
+	if (ret < 0)
+		goto err;
+
+	if (tmp) {
+		/* configure gpioh1, reset & power slave demod */
+		ret = af9035_wr_reg_mask(d, 0x00d8b0, 0x01, 0x01);
+		if (ret < 0)
+			goto err;
+
+		ret = af9035_wr_reg_mask(d, 0x00d8b1, 0x01, 0x01);
+		if (ret < 0)
+			goto err;
+
+		ret = af9035_wr_reg_mask(d, 0x00d8af, 0x00, 0x01);
+		if (ret < 0)
+			goto err;
+
+		usleep_range(10000, 50000);
+
+		ret = af9035_wr_reg_mask(d, 0x00d8af, 0x01, 0x01);
+		if (ret < 0)
+			goto err;
+
+		/* tell the slave I2C address */
+		ret = af9035_rd_reg(d,
+				state->eeprom_addr + EEPROM_2ND_DEMOD_ADDR,
+				&tmp);
+		if (ret < 0)
+			goto err;
+
+		if (state->chip_type == 0x9135) {
+			ret = af9035_wr_reg(d, 0x004bfb, tmp);
+			if (ret < 0)
+				goto err;
+		} else {
+			ret = af9035_wr_reg(d, 0x00417f, tmp);
+			if (ret < 0)
+				goto err;
+
+			/* enable clock out */
+			ret = af9035_wr_reg_mask(d, 0x00d81a, 0x01, 0x01);
+			if (ret < 0)
+				goto err;
+		}
+	}
+
+	if (fw->data[0] == 0x01)
+		ret = af9035_download_firmware_old(d, fw);
+	else
+		ret = af9035_download_firmware_new(d, fw);
+	if (ret < 0)
+		goto err;
+
 	/* firmware loaded, request boot */
 	req.cmd = CMD_FW_BOOT;
 	ret = af9035_ctrl_msg(d, &req);
@@ -546,15 +585,42 @@ err:
 static int af9035_read_config(struct dvb_usb_device *d)
 {
 	struct state *state = d_to_priv(d);
-	int ret, i, eeprom_shift = 0;
+	int ret, i;
 	u8 tmp;
-	u16 tmp16;
+	u16 tmp16, addr;
 
 	/* demod I2C "address" */
 	state->af9033_config[0].i2c_addr = 0x38;
+	state->af9033_config[0].adc_multiplier = AF9033_ADC_MULTIPLIER_2X;
+	state->af9033_config[1].adc_multiplier = AF9033_ADC_MULTIPLIER_2X;
+	state->af9033_config[0].ts_mode = AF9033_TS_MODE_USB;
+	state->af9033_config[1].ts_mode = AF9033_TS_MODE_SERIAL;
+
+	/* eeprom memory mapped location */
+	if (state->chip_type == 0x9135) {
+		if (state->chip_version == 0x02) {
+			state->af9033_config[0].tuner = AF9033_TUNER_IT9135_60;
+			state->af9033_config[1].tuner = AF9033_TUNER_IT9135_60;
+			tmp16 = 0x00461d;
+		} else {
+			state->af9033_config[0].tuner = AF9033_TUNER_IT9135_38;
+			state->af9033_config[1].tuner = AF9033_TUNER_IT9135_38;
+			tmp16 = 0x00461b;
+		}
+
+		/* check if eeprom exists */
+		ret = af9035_rd_reg(d, tmp16, &tmp);
+		if (ret < 0)
+			goto err;
+
+		if (tmp == 0x00) {
+			dev_dbg(&d->udev->dev, "%s: no eeprom\n", __func__);
+			goto skip_eeprom;
+		}
+	}
 
 	/* check if there is dual tuners */
-	ret = af9035_rd_reg(d, EEPROM_DUAL_MODE, &tmp);
+	ret = af9035_rd_reg(d, state->eeprom_addr + EEPROM_DUAL_MODE, &tmp);
 	if (ret < 0)
 		goto err;
 
@@ -564,7 +630,9 @@ static int af9035_read_config(struct dvb_usb_device *d)
 
 	if (state->dual_mode) {
 		/* read 2nd demodulator I2C address */
-		ret = af9035_rd_reg(d, EEPROM_2ND_DEMOD_ADDR, &tmp);
+		ret = af9035_rd_reg(d,
+				state->eeprom_addr + EEPROM_2ND_DEMOD_ADDR,
+				&tmp);
 		if (ret < 0)
 			goto err;
 
@@ -573,17 +641,25 @@ static int af9035_read_config(struct dvb_usb_device *d)
 				__func__, tmp);
 	}
 
+	addr = state->eeprom_addr;
+
 	for (i = 0; i < state->dual_mode + 1; i++) {
 		/* tuner */
-		ret = af9035_rd_reg(d, EEPROM_1_TUNER_ID + eeprom_shift, &tmp);
+		ret = af9035_rd_reg(d, addr + EEPROM_1_TUNER_ID, &tmp);
 		if (ret < 0)
 			goto err;
 
-		state->af9033_config[i].tuner = tmp;
+		if (tmp == 0x00)
+			dev_dbg(&d->udev->dev,
+					"%s: [%d]tuner not set, using default\n",
+					__func__, i);
+		else
+			state->af9033_config[i].tuner = tmp;
+
 		dev_dbg(&d->udev->dev, "%s: [%d]tuner=%02x\n",
-				__func__, i, tmp);
+				__func__, i, state->af9033_config[i].tuner);
 
-		switch (tmp) {
+		switch (state->af9033_config[i].tuner) {
 		case AF9033_TUNER_TUA9001:
 		case AF9033_TUNER_FC0011:
 		case AF9033_TUNER_MXL5007T:
@@ -592,32 +668,46 @@ static int af9035_read_config(struct dvb_usb_device *d)
 		case AF9033_TUNER_FC0012:
 			state->af9033_config[i].spec_inv = 1;
 			break;
+		case AF9033_TUNER_IT9135_38:
+		case AF9033_TUNER_IT9135_51:
+		case AF9033_TUNER_IT9135_52:
+		case AF9033_TUNER_IT9135_60:
+		case AF9033_TUNER_IT9135_61:
+		case AF9033_TUNER_IT9135_62:
+			break;
 		default:
-			dev_warn(&d->udev->dev, "%s: tuner id=%02x not " \
-					"supported, please report!",
+			dev_warn(&d->udev->dev,
+					"%s: tuner id=%02x not supported, please report!",
 					KBUILD_MODNAME, tmp);
 		}
 
 		/* disable dual mode if driver does not support it */
 		if (i == 1)
-			switch (tmp) {
+			switch (state->af9033_config[i].tuner) {
 			case AF9033_TUNER_FC0012:
+			case AF9033_TUNER_IT9135_38:
+			case AF9033_TUNER_IT9135_51:
+			case AF9033_TUNER_IT9135_52:
+			case AF9033_TUNER_IT9135_60:
+			case AF9033_TUNER_IT9135_61:
+			case AF9033_TUNER_IT9135_62:
+			case AF9033_TUNER_MXL5007T:
 				break;
 			default:
 				state->dual_mode = false;
-				dev_info(&d->udev->dev, "%s: driver does not " \
-						"support 2nd tuner and will " \
-						"disable it", KBUILD_MODNAME);
+				dev_info(&d->udev->dev,
+						"%s: driver does not support 2nd tuner and will disable it",
+						KBUILD_MODNAME);
 		}
 
 		/* tuner IF frequency */
-		ret = af9035_rd_reg(d, EEPROM_1_IFFREQ_L + eeprom_shift, &tmp);
+		ret = af9035_rd_reg(d, addr + EEPROM_1_IF_L, &tmp);
 		if (ret < 0)
 			goto err;
 
 		tmp16 = tmp;
 
-		ret = af9035_rd_reg(d, EEPROM_1_IFFREQ_H + eeprom_shift, &tmp);
+		ret = af9035_rd_reg(d, addr + EEPROM_1_IF_H, &tmp);
 		if (ret < 0)
 			goto err;
 
@@ -625,9 +715,10 @@ static int af9035_read_config(struct dvb_usb_device *d)
 
 		dev_dbg(&d->udev->dev, "%s: [%d]IF=%d\n", __func__, i, tmp16);
 
-		eeprom_shift = 0x10; /* shift for the 2nd tuner params */
+		addr += 0x10; /* shift for the 2nd tuner params */
 	}
 
+skip_eeprom:
 	/* get demod clock */
 	ret = af9035_rd_reg(d, 0x00d800, &tmp);
 	if (ret < 0)
@@ -635,34 +726,12 @@ static int af9035_read_config(struct dvb_usb_device *d)
 
 	tmp = (tmp >> 0) & 0x0f;
 
-	for (i = 0; i < ARRAY_SIZE(state->af9033_config); i++)
-		state->af9033_config[i].clock = clock_lut[tmp];
-
-	return 0;
-
-err:
-	dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
-
-	return ret;
-}
-
-static int af9035_read_config_it9135(struct dvb_usb_device *d)
-{
-	struct state *state = d_to_priv(d);
-	int ret, i;
-	u8 tmp;
-
-	state->dual_mode = false;
-
-	/* get demod clock */
-	ret = af9035_rd_reg(d, 0x00d800, &tmp);
-	if (ret < 0)
-		goto err;
-
-	tmp = (tmp >> 0) & 0x0f;
-
-	for (i = 0; i < ARRAY_SIZE(state->af9033_config); i++)
-		state->af9033_config[i].clock = clock_lut_it9135[tmp];
+	for (i = 0; i < ARRAY_SIZE(state->af9033_config); i++) {
+		if (state->chip_type == 0x9135)
+			state->af9033_config[i].clock = clock_lut_it9135[tmp];
+		else
+			state->af9033_config[i].clock = clock_lut_af9035[tmp];
+	}
 
 	return 0;
 
@@ -821,7 +890,12 @@ static int af9035_frontend_callback(void *adapter_priv, int component,
 static int af9035_get_adapter_count(struct dvb_usb_device *d)
 {
 	struct state *state = d_to_priv(d);
-	return state->dual_mode + 1;
+
+	/* disable 2nd adapter as we don't have PID filters implemented */
+	if (d->udev->speed == USB_SPEED_FULL)
+		return 1;
+	else
+		return state->dual_mode + 1;
 }
 
 static int af9035_frontend_attach(struct dvb_usb_adapter *adap)
@@ -829,6 +903,7 @@ static int af9035_frontend_attach(struct dvb_usb_adapter *adap)
 	struct state *state = adap_to_priv(adap);
 	struct dvb_usb_device *d = adap_to_d(adap);
 	int ret;
+	dev_dbg(&d->udev->dev, "%s:\n", __func__);
 
 	if (!state->af9033_config[adap->id].tuner) {
 		/* unsupported tuner */
@@ -836,20 +911,6 @@ static int af9035_frontend_attach(struct dvb_usb_adapter *adap)
 		goto err;
 	}
 
-	if (adap->id == 0) {
-		state->af9033_config[0].ts_mode = AF9033_TS_MODE_USB;
-		state->af9033_config[1].ts_mode = AF9033_TS_MODE_SERIAL;
-
-		ret = af9035_wr_reg(d, 0x00417f,
-				state->af9033_config[1].i2c_addr);
-		if (ret < 0)
-			goto err;
-
-		ret = af9035_wr_reg(d, 0x00d81a, state->dual_mode);
-		if (ret < 0)
-			goto err;
-	}
-
 	/* attach demodulator */
 	adap->fe[0] = dvb_attach(af9033_attach, &state->af9033_config[adap->id],
 			&d->i2c_adap);
@@ -928,6 +989,8 @@ static int af9035_tuner_attach(struct dvb_usb_adapter *adap)
 	struct dvb_frontend *fe;
 	struct i2c_msg msg[1];
 	u8 tuner_addr;
+	dev_dbg(&d->udev->dev, "%s:\n", __func__);
+
 	/*
 	 * XXX: Hack used in that function: we abuse unused I2C address bit [7]
 	 * to carry info about used I2C bus for dual tuner configuration.
@@ -1082,6 +1145,17 @@ static int af9035_tuner_attach(struct dvb_usb_adapter *adap)
 		fe = dvb_attach(fc0012_attach, adap->fe[0], &d->i2c_adap,
 				&af9035_fc0012_config[adap->id]);
 		break;
+	case AF9033_TUNER_IT9135_38:
+	case AF9033_TUNER_IT9135_51:
+	case AF9033_TUNER_IT9135_52:
+	case AF9033_TUNER_IT9135_60:
+	case AF9033_TUNER_IT9135_61:
+	case AF9033_TUNER_IT9135_62:
+		/* attach tuner */
+		fe = dvb_attach(it913x_attach, adap->fe[0], &d->i2c_adap,
+				state->af9033_config[adap->id].i2c_addr,
+				state->af9033_config[0].tuner);
+		break;
 	default:
 		fe = NULL;
 	}
@@ -1103,8 +1177,8 @@ static int af9035_init(struct dvb_usb_device *d)
 {
 	struct state *state = d_to_priv(d);
 	int ret, i;
-	u16 frame_size = 87 * 188 / 4;
-	u8  packet_size = 512 / 4;
+	u16 frame_size = (d->udev->speed == USB_SPEED_FULL ? 5 : 87) * 188 / 4;
+	u8 packet_size = (d->udev->speed == USB_SPEED_FULL ? 64 : 512) / 4;
 	struct reg_val_mask tab[] = {
 		{ 0x80f99d, 0x01, 0x01 },
 		{ 0x80f9a4, 0x01, 0x01 },
@@ -1149,40 +1223,49 @@ err:
 #if IS_ENABLED(CONFIG_RC_CORE)
 static int af9035_rc_query(struct dvb_usb_device *d)
 {
-	unsigned int key;
-	unsigned char b[4];
 	int ret;
-	struct usb_req req = { CMD_IR_GET, 0, 0, NULL, 4, b };
+	u32 key;
+	u8 buf[4];
+	struct usb_req req = { CMD_IR_GET, 0, 0, NULL, 4, buf };
 
 	ret = af9035_ctrl_msg(d, &req);
-	if (ret < 0)
+	if (ret == 1)
+		return 0;
+	else if (ret < 0)
 		goto err;
 
-	if ((b[2] + b[3]) == 0xff) {
-		if ((b[0] + b[1]) == 0xff) {
-			/* NEC */
-			key = b[0] << 8 | b[2];
+	if ((buf[2] + buf[3]) == 0xff) {
+		if ((buf[0] + buf[1]) == 0xff) {
+			/* NEC standard 16bit */
+			key = buf[0] << 8 | buf[2];
 		} else {
-			/* ext. NEC */
-			key = b[0] << 16 | b[1] << 8 | b[2];
+			/* NEC extended 24bit */
+			key = buf[0] << 16 | buf[1] << 8 | buf[2];
 		}
 	} else {
-		key = b[0] << 24 | b[1] << 16 | b[2] << 8 | b[3];
+		/* NEC full code 32bit */
+		key = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3];
 	}
 
+	dev_dbg(&d->udev->dev, "%s: %*ph\n", __func__, 4, buf);
+
 	rc_keydown(d->rc_dev, key, 0);
 
-err:
-	/* ignore errors */
 	return 0;
+
+err:
+	dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
+
+	return ret;
 }
 
 static int af9035_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc)
 {
+	struct state *state = d_to_priv(d);
 	int ret;
 	u8 tmp;
 
-	ret = af9035_rd_reg(d, EEPROM_IR_MODE, &tmp);
+	ret = af9035_rd_reg(d, state->eeprom_addr + EEPROM_IR_MODE, &tmp);
 	if (ret < 0)
 		goto err;
 
@@ -1190,7 +1273,8 @@ static int af9035_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc)
 
 	/* don't activate rc if in HID mode or if not available */
 	if (tmp == 5) {
-		ret = af9035_rd_reg(d, EEPROM_IR_TYPE, &tmp);
+		ret = af9035_rd_reg(d, state->eeprom_addr + EEPROM_IR_TYPE,
+				&tmp);
 		if (ret < 0)
 			goto err;
 
@@ -1225,6 +1309,109 @@ err:
 	#define af9035_get_rc_config NULL
 #endif
 
+static int af9035_get_stream_config(struct dvb_frontend *fe, u8 *ts_type,
+		struct usb_data_stream_properties *stream)
+{
+	struct dvb_usb_device *d = fe_to_d(fe);
+	dev_dbg(&d->udev->dev, "%s: adap=%d\n", __func__, fe_to_adap(fe)->id);
+
+	if (d->udev->speed == USB_SPEED_FULL)
+		stream->u.bulk.buffersize = 5 * 188;
+
+	return 0;
+}
+
+/*
+ * FIXME: PID filter is property of demodulator and should be moved to the
+ * correct driver. Also we support only adapter #0 PID filter and will
+ * disable adapter #1 if USB1.1 is used.
+ */
+static int af9035_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff)
+{
+	struct dvb_usb_device *d = adap_to_d(adap);
+	int ret;
+
+	dev_dbg(&d->udev->dev, "%s: onoff=%d\n", __func__, onoff);
+
+	ret = af9035_wr_reg_mask(d, 0x80f993, onoff, 0x01);
+	if (ret < 0)
+		goto err;
+
+	return 0;
+
+err:
+	dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
+
+	return ret;
+}
+
+static int af9035_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid,
+		int onoff)
+{
+	struct dvb_usb_device *d = adap_to_d(adap);
+	int ret;
+	u8 wbuf[2] = {(pid >> 0) & 0xff, (pid >> 8) & 0xff};
+
+	dev_dbg(&d->udev->dev, "%s: index=%d pid=%04x onoff=%d\n",
+			__func__, index, pid, onoff);
+
+	ret = af9035_wr_regs(d, 0x80f996, wbuf, 2);
+	if (ret < 0)
+		goto err;
+
+	ret = af9035_wr_reg(d, 0x80f994, onoff);
+	if (ret < 0)
+		goto err;
+
+	ret = af9035_wr_reg(d, 0x80f995, index);
+	if (ret < 0)
+		goto err;
+
+	return 0;
+
+err:
+	dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
+
+	return ret;
+}
+
+static int af9035_probe(struct usb_interface *intf,
+		const struct usb_device_id *id)
+{
+	struct usb_device *udev = interface_to_usbdev(intf);
+	char manufacturer[sizeof("Afatech")];
+
+	memset(manufacturer, 0, sizeof(manufacturer));
+	usb_string(udev, udev->descriptor.iManufacturer,
+			manufacturer, sizeof(manufacturer));
+	/*
+	 * There is two devices having same ID but different chipset. One uses
+	 * AF9015 and the other IT9135 chipset. Only difference seen on lsusb
+	 * is iManufacturer string.
+	 *
+	 * idVendor           0x0ccd TerraTec Electronic GmbH
+	 * idProduct          0x0099
+	 * bcdDevice            2.00
+	 * iManufacturer           1 Afatech
+	 * iProduct                2 DVB-T 2
+	 *
+	 * idVendor           0x0ccd TerraTec Electronic GmbH
+	 * idProduct          0x0099
+	 * bcdDevice            2.00
+	 * iManufacturer           1 ITE Technologies, Inc.
+	 * iProduct                2 DVB-T TV Stick
+	 */
+	if ((le16_to_cpu(udev->descriptor.idVendor) == USB_VID_TERRATEC) &&
+			(le16_to_cpu(udev->descriptor.idProduct) == 0x0099)) {
+		if (!strcmp("Afatech", manufacturer)) {
+			dev_dbg(&udev->dev, "%s: rejecting device\n", __func__);
+			return -ENODEV;
+		}
+	}
+
+	return dvb_usbv2_probe(intf, id);
+}
+
 /* interface 0 is used by DVB-T receiver and
    interface 1 is for remote controller (HID) */
 static const struct dvb_usb_device_properties af9035_props = {
@@ -1237,7 +1424,6 @@ static const struct dvb_usb_device_properties af9035_props = {
 	.generic_bulk_ctrl_endpoint_response = 0x81,
 
 	.identify_state = af9035_identify_state,
-	.firmware = AF9035_FIRMWARE_AF9035,
 	.download_firmware = af9035_download_firmware,
 
 	.i2c_algo = &af9035_i2c_algo,
@@ -1246,40 +1432,18 @@ static const struct dvb_usb_device_properties af9035_props = {
 	.tuner_attach = af9035_tuner_attach,
 	.init = af9035_init,
 	.get_rc_config = af9035_get_rc_config,
+	.get_stream_config = af9035_get_stream_config,
 
 	.get_adapter_count = af9035_get_adapter_count,
 	.adapter = {
 		{
-			.stream = DVB_USB_STREAM_BULK(0x84, 6, 87 * 188),
-		}, {
-			.stream = DVB_USB_STREAM_BULK(0x85, 6, 87 * 188),
-		},
-	},
-};
-
-static const struct dvb_usb_device_properties it9135_props = {
-	.driver_name = KBUILD_MODNAME,
-	.owner = THIS_MODULE,
-	.adapter_nr = adapter_nr,
-	.size_of_priv = sizeof(struct state),
+			.caps = DVB_USB_ADAP_HAS_PID_FILTER |
+				DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 
-	.generic_bulk_ctrl_endpoint = 0x02,
-	.generic_bulk_ctrl_endpoint_response = 0x81,
-
-	.identify_state = af9035_identify_state,
-	.firmware = AF9035_FIRMWARE_IT9135,
-	.download_firmware = af9035_download_firmware_it9135,
+			.pid_filter_count = 32,
+			.pid_filter_ctrl = af9035_pid_filter_ctrl,
+			.pid_filter = af9035_pid_filter,
 
-	.i2c_algo = &af9035_i2c_algo,
-	.read_config = af9035_read_config_it9135,
-	.frontend_attach = af9035_frontend_attach,
-	.tuner_attach = af9035_tuner_attach,
-	.init = af9035_init,
-	.get_rc_config = af9035_get_rc_config,
-
-	.num_adapters = 1,
-	.adapter = {
-		{
 			.stream = DVB_USB_STREAM_BULK(0x84, 6, 87 * 188),
 		}, {
 			.stream = DVB_USB_STREAM_BULK(0x85, 6, 87 * 188),
@@ -1288,6 +1452,7 @@ static const struct dvb_usb_device_properties it9135_props = {
 };
 
 static const struct usb_device_id af9035_id_table[] = {
+	/* AF9035 devices */
 	{ DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_9035,
 		&af9035_props, "Afatech AF9035 reference design", NULL) },
 	{ DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_1000,
@@ -1312,6 +1477,18 @@ static const struct usb_device_id af9035_id_table[] = {
 		&af9035_props, "AVerMedia Twinstar (A825)", NULL) },
 	{ DVB_USB_DEVICE(USB_VID_ASUS, USB_PID_ASUS_U3100MINI_PLUS,
 		&af9035_props, "Asus U3100Mini Plus", NULL) },
+        { DVB_USB_DEVICE(USB_VID_TERRATEC, 0x00aa,
+		&af9035_props, "TerraTec Cinergy T Stick (rev. 2)", NULL) },
+	/* IT9135 devices */
+#if 0
+	{ DVB_USB_DEVICE(0x048d, 0x9135,
+		&af9035_props, "IT9135 reference design", NULL) },
+	{ DVB_USB_DEVICE(0x048d, 0x9006,
+		&af9035_props, "IT9135 reference design", NULL) },
+#endif
+	/* XXX: that same ID [0ccd:0099] is used by af9015 driver too */
+	{ DVB_USB_DEVICE(USB_VID_TERRATEC, 0x0099,
+		&af9035_props, "TerraTec Cinergy T Stick Dual RC (rev. 2)", NULL) },
 	{ }
 };
 MODULE_DEVICE_TABLE(usb, af9035_id_table);
@@ -1319,7 +1496,7 @@ MODULE_DEVICE_TABLE(usb, af9035_id_table);
 static struct usb_driver af9035_usb_driver = {
 	.name = KBUILD_MODNAME,
 	.id_table = af9035_id_table,
-	.probe = dvb_usbv2_probe,
+	.probe = af9035_probe,
 	.disconnect = dvb_usbv2_disconnect,
 	.suspend = dvb_usbv2_suspend,
 	.resume = dvb_usbv2_resume,
@@ -1334,4 +1511,5 @@ MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
 MODULE_DESCRIPTION("Afatech AF9035 driver");
 MODULE_LICENSE("GPL");
 MODULE_FIRMWARE(AF9035_FIRMWARE_AF9035);
-MODULE_FIRMWARE(AF9035_FIRMWARE_IT9135);
+MODULE_FIRMWARE(AF9035_FIRMWARE_IT9135_V1);
+MODULE_FIRMWARE(AF9035_FIRMWARE_IT9135_V2);
diff --git a/drivers/media/usb/dvb-usb-v2/af9035.h b/drivers/media/usb/dvb-usb-v2/af9035.h
index 29f3eec..0f42b6c 100644
--- a/drivers/media/usb/dvb-usb-v2/af9035.h
+++ b/drivers/media/usb/dvb-usb-v2/af9035.h
@@ -30,6 +30,7 @@
 #include "mxl5007t.h"
 #include "tda18218.h"
 #include "fc2580.h"
+#include "it913x.h"
 
 struct reg_val {
 	u32 reg;
@@ -52,12 +53,18 @@ struct usb_req {
 };
 
 struct state {
+#define BUF_LEN 64
+	u8 buf[BUF_LEN];
 	u8 seq; /* packet sequence number */
-	bool dual_mode;
+	u8 prechip_version;
+	u8 chip_version;
+	u16 chip_type;
+	u8 dual_mode:1;
+	u16 eeprom_addr;
 	struct af9033_config af9033_config[2];
 };
 
-u32 clock_lut[] = {
+static const u32 clock_lut_af9035[] = {
 	20480000, /*      FPGA */
 	16384000, /* 16.38 MHz */
 	20480000, /* 20.48 MHz */
@@ -72,7 +79,7 @@ u32 clock_lut[] = {
 	12000000, /* 12.00 MHz */
 };
 
-u32 clock_lut_it9135[] = {
+static const u32 clock_lut_it9135[] = {
 	12000000, /* 12.00 MHz */
 	20480000, /* 20.48 MHz */
 	36000000, /* 36.00 MHz */
@@ -86,19 +93,31 @@ u32 clock_lut_it9135[] = {
 };
 
 #define AF9035_FIRMWARE_AF9035 "dvb-usb-af9035-02.fw"
-#define AF9035_FIRMWARE_IT9135 "dvb-usb-it9135-01.fw"
+#define AF9035_FIRMWARE_IT9135_V1 "dvb-usb-it9135-01.fw"
+#define AF9035_FIRMWARE_IT9135_V2 "dvb-usb-it9135-02.fw"
 
-/* EEPROM locations */
-#define EEPROM_IR_MODE            0x430d
-#define EEPROM_DUAL_MODE          0x4326
-#define EEPROM_2ND_DEMOD_ADDR     0x4327
-#define EEPROM_IR_TYPE            0x4329
-#define EEPROM_1_IFFREQ_L         0x432d
-#define EEPROM_1_IFFREQ_H         0x432e
-#define EEPROM_1_TUNER_ID         0x4331
-#define EEPROM_2_IFFREQ_L         0x433d
-#define EEPROM_2_IFFREQ_H         0x433e
-#define EEPROM_2_TUNER_ID         0x4341
+/*
+ * eeprom is memory mapped as read only. Writing that memory mapped address
+ * will not corrupt eeprom.
+ *
+ * eeprom has value 0x00 single mode and 0x03 for dual mode as far as I have
+ * seen to this day.
+ */
+
+#define EEPROM_BASE_AF9035        0x42fd
+#define EEPROM_BASE_IT9135        0x499c
+#define EEPROM_SHIFT                0x10
+
+#define EEPROM_IR_MODE              0x10
+#define EEPROM_DUAL_MODE            0x29
+#define EEPROM_2ND_DEMOD_ADDR       0x2a
+#define EEPROM_IR_TYPE              0x2c
+#define EEPROM_1_IF_L               0x30
+#define EEPROM_1_IF_H               0x31
+#define EEPROM_1_TUNER_ID           0x34
+#define EEPROM_2_IF_L               0x40
+#define EEPROM_2_IF_H               0x41
+#define EEPROM_2_TUNER_ID           0x44
 
 /* USB commands */
 #define CMD_MEM_RD                  0x00
diff --git a/drivers/media/usb/dvb-usb-v2/anysee.c b/drivers/media/usb/dvb-usb-v2/anysee.c
index a20d691..2e76274 100644
--- a/drivers/media/usb/dvb-usb-v2/anysee.c
+++ b/drivers/media/usb/dvb-usb-v2/anysee.c
@@ -45,25 +45,24 @@
 #include "cxd2820r.h"
 
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-static DEFINE_MUTEX(anysee_usb_mutex);
 
-static int anysee_ctrl_msg(struct dvb_usb_device *d, u8 *sbuf, u8 slen,
-	u8 *rbuf, u8 rlen)
+static int anysee_ctrl_msg(struct dvb_usb_device *d,
+		u8 *sbuf, u8 slen, u8 *rbuf, u8 rlen)
 {
 	struct anysee_state *state = d_to_priv(d);
 	int act_len, ret, i;
-	u8 buf[64];
 
-	memcpy(&buf[0], sbuf, slen);
-	buf[60] = state->seq++;
+	mutex_lock(&d->usb_mutex);
 
-	mutex_lock(&anysee_usb_mutex);
+	memcpy(&state->buf[0], sbuf, slen);
+	state->buf[60] = state->seq++;
 
-	dev_dbg(&d->udev->dev, "%s: >>> %*ph\n", __func__, slen, buf);
+	dev_dbg(&d->udev->dev, "%s: >>> %*ph\n", __func__, slen, state->buf);
 
 	/* We need receive one message more after dvb_usb_generic_rw due
 	   to weird transaction flow, which is 1 x send + 2 x receive. */
-	ret = dvb_usbv2_generic_rw(d, buf, sizeof(buf), buf, sizeof(buf));
+	ret = dvb_usbv2_generic_rw_locked(d, state->buf, sizeof(state->buf),
+			state->buf, sizeof(state->buf));
 	if (ret)
 		goto error_unlock;
 
@@ -82,20 +81,19 @@ static int anysee_ctrl_msg(struct dvb_usb_device *d, u8 *sbuf, u8 slen,
 	for (i = 0; i < 3; i++) {
 		/* receive 2nd answer */
 		ret = usb_bulk_msg(d->udev, usb_rcvbulkpipe(d->udev,
-			d->props->generic_bulk_ctrl_endpoint), buf, sizeof(buf),
-			&act_len, 2000);
-
+				d->props->generic_bulk_ctrl_endpoint),
+				state->buf, sizeof(state->buf), &act_len, 2000);
 		if (ret) {
-			dev_dbg(&d->udev->dev, "%s: recv bulk message " \
-					"failed=%d\n", __func__, ret);
+			dev_dbg(&d->udev->dev,
+					"%s: recv bulk message failed=%d\n",
+					__func__, ret);
 		} else {
 			dev_dbg(&d->udev->dev, "%s: <<< %*ph\n", __func__,
-					rlen, buf);
-
-			if (buf[63] != 0x4f)
-				dev_dbg(&d->udev->dev, "%s: cmd failed\n",
-						__func__);
+					rlen, state->buf);
 
+			if (state->buf[63] != 0x4f)
+				dev_dbg(&d->udev->dev,
+						"%s: cmd failed\n", __func__);
 			break;
 		}
 	}
@@ -109,11 +107,10 @@ static int anysee_ctrl_msg(struct dvb_usb_device *d, u8 *sbuf, u8 slen,
 
 	/* read request, copy returned data to return buf */
 	if (rbuf && rlen)
-		memcpy(rbuf, buf, rlen);
+		memcpy(rbuf, state->buf, rlen);
 
 error_unlock:
-	mutex_unlock(&anysee_usb_mutex);
-
+	mutex_unlock(&d->usb_mutex);
 	return ret;
 }
 
@@ -884,9 +881,8 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
 	if (!adap->fe[0]) {
 		/* we have no frontend :-( */
 		ret = -ENODEV;
-		dev_err(&d->udev->dev, "%s: Unsupported Anysee version. " \
-				"Please report the " \
-				"<linux-media@vger.kernel.org>.\n",
+		dev_err(&d->udev->dev,
+				"%s: Unsupported Anysee version. Please report the <linux-media@vger.kernel.org>.\n",
 				KBUILD_MODNAME);
 	}
 error:
diff --git a/drivers/media/usb/dvb-usb-v2/anysee.h b/drivers/media/usb/dvb-usb-v2/anysee.h
index c1a4273..8f426d9 100644
--- a/drivers/media/usb/dvb-usb-v2/anysee.h
+++ b/drivers/media/usb/dvb-usb-v2/anysee.h
@@ -52,8 +52,9 @@ enum cmd {
 };
 
 struct anysee_state {
-	u8 hw; /* PCB ID */
+	u8 buf[64];
 	u8 seq;
+	u8 hw; /* PCB ID */
 	u8 fe_id:1; /* frondend ID */
 	u8 has_ci:1;
 	u8 ci_attached:1;
diff --git a/drivers/media/usb/dvb-usb-v2/cypress_firmware.c b/drivers/media/usb/dvb-usb-v2/cypress_firmware.c
index 211df54..cfb1733 100644
--- a/drivers/media/usb/dvb-usb-v2/cypress_firmware.c
+++ b/drivers/media/usb/dvb-usb-v2/cypress_firmware.c
@@ -71,9 +71,8 @@ int usbv2_cypress_load_firmware(struct usb_device *udev,
 		if (ret < 0) {
 			goto err_kfree;
 		} else if (ret != hx->len) {
-			dev_err(&udev->dev, "%s: error while transferring " \
-					"firmware (transferred size=%d, " \
-					"block size=%d)\n",
+			dev_err(&udev->dev,
+					"%s: error while transferring firmware (transferred size=%d, block size=%d)\n",
 					KBUILD_MODNAME, ret, hx->len);
 			ret = -EIO;
 			goto err_kfree;
diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb.h b/drivers/media/usb/dvb-usb-v2/dvb_usb.h
index 3cac8bd..658c6d4 100644
--- a/drivers/media/usb/dvb-usb-v2/dvb_usb.h
+++ b/drivers/media/usb/dvb-usb-v2/dvb_usb.h
@@ -329,13 +329,16 @@ struct dvb_usb_adapter {
 	u8 feed_count;
 	u8 max_feed_count;
 	s8 active_fe;
+#define ADAP_INIT                0
+#define ADAP_SLEEP               1
+#define ADAP_STREAMING           2
+	unsigned long state_bits;
 
 	/* dvb */
 	struct dvb_adapter   dvb_adap;
 	struct dmxdev        dmxdev;
 	struct dvb_demux     demux;
 	struct dvb_net       dvb_net;
-	struct mutex         sync_mutex;
 
 	struct dvb_frontend *fe[MAX_NO_OF_FE_PER_ADAP];
 	int (*fe_init[MAX_NO_OF_FE_PER_ADAP]) (struct dvb_frontend *);
@@ -400,5 +403,9 @@ extern int dvb_usbv2_reset_resume(struct usb_interface *);
 /* the generic read/write method for device control */
 extern int dvb_usbv2_generic_rw(struct dvb_usb_device *, u8 *, u16, u8 *, u16);
 extern int dvb_usbv2_generic_write(struct dvb_usb_device *, u8 *, u16);
+/* caller must hold lock when locked versions are called */
+extern int dvb_usbv2_generic_rw_locked(struct dvb_usb_device *,
+		u8 *, u16, u8 *, u16);
+extern int dvb_usbv2_generic_write_locked(struct dvb_usb_device *, u8 *, u16);
 
 #endif
diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
index 0867920..19f6737 100644
--- a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
+++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
@@ -28,10 +28,11 @@ MODULE_PARM_DESC(disable_rc_polling,
 static int dvb_usb_force_pid_filter_usage;
 module_param_named(force_pid_filter_usage, dvb_usb_force_pid_filter_usage,
 		int, 0444);
-MODULE_PARM_DESC(force_pid_filter_usage, "force all DVB USB devices to use a " \
-		"PID filter, if any (default: 0)");
+MODULE_PARM_DESC(force_pid_filter_usage,
+		"force all DVB USB devices to use a PID filter, if any (default: 0)");
 
-static int dvb_usbv2_download_firmware(struct dvb_usb_device *d, const char *name)
+static int dvb_usbv2_download_firmware(struct dvb_usb_device *d,
+		const char *name)
 {
 	int ret;
 	const struct firmware *fw;
@@ -44,10 +45,9 @@ static int dvb_usbv2_download_firmware(struct dvb_usb_device *d, const char *nam
 
 	ret = request_firmware(&fw, name, &d->udev->dev);
 	if (ret < 0) {
-		dev_err(&d->udev->dev, "%s: Did not find the firmware file "\
-				"'%s'. Please see linux/Documentation/dvb/ " \
-				"for more details on firmware-problems. " \
-				"Status %d\n", KBUILD_MODNAME, name, ret);
+		dev_err(&d->udev->dev,
+				"%s: Did not find the firmware file '%s'. Please see linux/Documentation/dvb/ for more details on firmware-problems. Status %d\n",
+				KBUILD_MODNAME, name, ret);
 		goto err;
 	}
 
@@ -181,9 +181,9 @@ static int dvb_usbv2_remote_init(struct dvb_usb_device *d)
 		/* initialize a work queue for handling polling */
 		INIT_DELAYED_WORK(&d->rc_query_work,
 				dvb_usb_read_remote_control);
-		dev_info(&d->udev->dev, "%s: schedule remote query interval " \
-				"to %d msecs\n", KBUILD_MODNAME,
-				d->rc.interval);
+		dev_info(&d->udev->dev,
+				"%s: schedule remote query interval to %d msecs\n",
+				KBUILD_MODNAME, d->rc.interval);
 		schedule_delayed_work(&d->rc_query_work,
 				msecs_to_jiffies(d->rc.interval));
 		d->rc_polling_active = true;
@@ -253,128 +253,159 @@ static int dvb_usbv2_adapter_stream_exit(struct dvb_usb_adapter *adap)
 	return usb_urb_exitv2(&adap->stream);
 }
 
-static inline int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed,
-		int count)
+static int wait_schedule(void *ptr)
+{
+	schedule();
+
+	return 0;
+}
+
+static int dvb_usb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
 {
 	struct dvb_usb_adapter *adap = dvbdmxfeed->demux->priv;
 	struct dvb_usb_device *d = adap_to_d(adap);
-	int ret;
-	dev_dbg(&d->udev->dev, "%s: adap=%d active_fe=%d feed_type=%d " \
-			"setting pid [%s]: %04x (%04d) at index %d '%s'\n",
+	int ret = 0;
+	struct usb_data_stream_properties stream_props;
+	dev_dbg(&d->udev->dev,
+			"%s: adap=%d active_fe=%d feed_type=%d setting pid [%s]: %04x (%04d) at index %d\n",
 			__func__, adap->id, adap->active_fe, dvbdmxfeed->type,
 			adap->pid_filtering ? "yes" : "no", dvbdmxfeed->pid,
-			dvbdmxfeed->pid, dvbdmxfeed->index,
-			(count == 1) ? "on" : "off");
+			dvbdmxfeed->pid, dvbdmxfeed->index);
+
+	/* wait init is done */
+	wait_on_bit(&adap->state_bits, ADAP_INIT, wait_schedule,
+			TASK_UNINTERRUPTIBLE);
 
 	if (adap->active_fe == -1)
 		return -EINVAL;
 
-	adap->feed_count += count;
-
-	/* stop feeding if it is last pid */
-	if (adap->feed_count == 0) {
-		dev_dbg(&d->udev->dev, "%s: stop feeding\n", __func__);
-
-		if (d->props->streaming_ctrl) {
-			ret = d->props->streaming_ctrl(
-					adap->fe[adap->active_fe], 0);
-			if (ret < 0) {
-				dev_err(&d->udev->dev, "%s: streaming_ctrl() " \
-						"failed=%d\n", KBUILD_MODNAME,
-						ret);
-				usb_urb_killv2(&adap->stream);
-				goto err_mutex_unlock;
-			}
-		}
-		usb_urb_killv2(&adap->stream);
-		mutex_unlock(&adap->sync_mutex);
-	}
+	/* skip feed setup if we are already feeding */
+	if (adap->feed_count++ > 0)
+		goto skip_feed_start;
 
-	/* activate the pid on the device pid filter */
-	if (adap->props->caps & DVB_USB_ADAP_HAS_PID_FILTER &&
-			adap->pid_filtering && adap->props->pid_filter) {
-		ret = adap->props->pid_filter(adap, dvbdmxfeed->index,
-				dvbdmxfeed->pid, (count == 1) ? 1 : 0);
-		if (ret < 0)
-			dev_err(&d->udev->dev, "%s: pid_filter() failed=%d\n",
+	/* set 'streaming' status bit */
+	set_bit(ADAP_STREAMING, &adap->state_bits);
+
+	/* resolve input and output streaming parameters */
+	if (d->props->get_stream_config) {
+		memcpy(&stream_props, &adap->props->stream,
+				sizeof(struct usb_data_stream_properties));
+		ret = d->props->get_stream_config(adap->fe[adap->active_fe],
+				&adap->ts_type, &stream_props);
+		if (ret)
+			dev_err(&d->udev->dev,
+					"%s: get_stream_config() failed=%d\n",
 					KBUILD_MODNAME, ret);
+	} else {
+		stream_props = adap->props->stream;
 	}
 
-	/* start feeding if it is first pid */
-	if (adap->feed_count == 1 && count == 1) {
-		struct usb_data_stream_properties stream_props;
-		mutex_lock(&adap->sync_mutex);
-		dev_dbg(&d->udev->dev, "%s: start feeding\n", __func__);
+	switch (adap->ts_type) {
+	case DVB_USB_FE_TS_TYPE_204:
+		adap->stream.complete = dvb_usb_data_complete_204;
+		break;
+	case DVB_USB_FE_TS_TYPE_RAW:
+		adap->stream.complete = dvb_usb_data_complete_raw;
+		break;
+	case DVB_USB_FE_TS_TYPE_188:
+	default:
+		adap->stream.complete = dvb_usb_data_complete;
+		break;
+	}
 
-		/* resolve input and output streaming paramters */
-		if (d->props->get_stream_config) {
-			memcpy(&stream_props, &adap->props->stream,
-				sizeof(struct usb_data_stream_properties));
-			ret = d->props->get_stream_config(
-					adap->fe[adap->active_fe],
-					&adap->ts_type, &stream_props);
-			if (ret < 0)
-				goto err_mutex_unlock;
-		} else {
-			stream_props = adap->props->stream;
-		}
+	/* submit USB streaming packets */
+	usb_urb_submitv2(&adap->stream, &stream_props);
 
-		switch (adap->ts_type) {
-		case DVB_USB_FE_TS_TYPE_204:
-			adap->stream.complete = dvb_usb_data_complete_204;
-			break;
-		case DVB_USB_FE_TS_TYPE_RAW:
-			adap->stream.complete = dvb_usb_data_complete_raw;
-			break;
-		case DVB_USB_FE_TS_TYPE_188:
-		default:
-			adap->stream.complete = dvb_usb_data_complete;
-			break;
-		}
+	/* enable HW PID filter */
+	if (adap->pid_filtering && adap->props->pid_filter_ctrl) {
+		ret = adap->props->pid_filter_ctrl(adap, 1);
+		if (ret)
+			dev_err(&d->udev->dev,
+					"%s: pid_filter_ctrl() failed=%d\n",
+					KBUILD_MODNAME, ret);
+	}
 
-		usb_urb_submitv2(&adap->stream, &stream_props);
-
-		if (adap->props->caps & DVB_USB_ADAP_HAS_PID_FILTER &&
-				adap->props->caps &
-				DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF &&
-				adap->props->pid_filter_ctrl) {
-			ret = adap->props->pid_filter_ctrl(adap,
-					adap->pid_filtering);
-			if (ret < 0) {
-				dev_err(&d->udev->dev, "%s: " \
-						"pid_filter_ctrl() failed=%d\n",
-						KBUILD_MODNAME, ret);
-				goto err_mutex_unlock;
-			}
-		}
+	/* ask device to start streaming */
+	if (d->props->streaming_ctrl) {
+		ret = d->props->streaming_ctrl(adap->fe[adap->active_fe], 1);
+		if (ret)
+			dev_err(&d->udev->dev,
+					"%s: streaming_ctrl() failed=%d\n",
+					KBUILD_MODNAME, ret);
+	}
+skip_feed_start:
 
-		if (d->props->streaming_ctrl) {
-			ret = d->props->streaming_ctrl(
-					adap->fe[adap->active_fe], 1);
-			if (ret < 0) {
-				dev_err(&d->udev->dev, "%s: streaming_ctrl() " \
-						"failed=%d\n", KBUILD_MODNAME,
-						ret);
-				goto err_mutex_unlock;
-			}
-		}
+	/* add PID to device HW PID filter */
+	if (adap->pid_filtering && adap->props->pid_filter) {
+		ret = adap->props->pid_filter(adap, dvbdmxfeed->index,
+				dvbdmxfeed->pid, 1);
+		if (ret)
+			dev_err(&d->udev->dev, "%s: pid_filter() failed=%d\n",
+					KBUILD_MODNAME, ret);
 	}
 
-	return 0;
-err_mutex_unlock:
-	mutex_unlock(&adap->sync_mutex);
-	dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
+	if (ret)
+		dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
 	return ret;
 }
 
-static int dvb_usb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
-{
-	return dvb_usb_ctrl_feed(dvbdmxfeed, 1);
-}
-
 static int dvb_usb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
 {
-	return dvb_usb_ctrl_feed(dvbdmxfeed, -1);
+	struct dvb_usb_adapter *adap = dvbdmxfeed->demux->priv;
+	struct dvb_usb_device *d = adap_to_d(adap);
+	int ret = 0;
+	dev_dbg(&d->udev->dev,
+			"%s: adap=%d active_fe=%d feed_type=%d setting pid [%s]: %04x (%04d) at index %d\n",
+			__func__, adap->id, adap->active_fe, dvbdmxfeed->type,
+			adap->pid_filtering ? "yes" : "no", dvbdmxfeed->pid,
+			dvbdmxfeed->pid, dvbdmxfeed->index);
+
+	if (adap->active_fe == -1)
+		return -EINVAL;
+
+	/* remove PID from device HW PID filter */
+	if (adap->pid_filtering && adap->props->pid_filter) {
+		ret = adap->props->pid_filter(adap, dvbdmxfeed->index,
+				dvbdmxfeed->pid, 0);
+		if (ret)
+			dev_err(&d->udev->dev, "%s: pid_filter() failed=%d\n",
+					KBUILD_MODNAME, ret);
+	}
+
+	/* we cannot stop streaming until last PID is removed */
+	if (--adap->feed_count > 0)
+		goto skip_feed_stop;
+
+	/* ask device to stop streaming */
+	if (d->props->streaming_ctrl) {
+		ret = d->props->streaming_ctrl(adap->fe[adap->active_fe], 0);
+		if (ret)
+			dev_err(&d->udev->dev,
+					"%s: streaming_ctrl() failed=%d\n",
+					KBUILD_MODNAME, ret);
+	}
+
+	/* disable HW PID filter */
+	if (adap->pid_filtering && adap->props->pid_filter_ctrl) {
+		ret = adap->props->pid_filter_ctrl(adap, 0);
+		if (ret)
+			dev_err(&d->udev->dev,
+					"%s: pid_filter_ctrl() failed=%d\n",
+					KBUILD_MODNAME, ret);
+	}
+
+	/* kill USB streaming packets */
+	usb_urb_killv2(&adap->stream);
+
+	/* clear 'streaming' status bit */
+	clear_bit(ADAP_STREAMING, &adap->state_bits);
+	smp_mb__after_clear_bit();
+	wake_up_bit(&adap->state_bits, ADAP_STREAMING);
+skip_feed_stop:
+
+	if (ret)
+		dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
 }
 
 static int dvb_usbv2_adapter_dvb_init(struct dvb_usb_adapter *adap)
@@ -435,8 +466,6 @@ static int dvb_usbv2_adapter_dvb_init(struct dvb_usb_adapter *adap)
 		goto err_dvb_net_init;
 	}
 
-	mutex_init(&adap->sync_mutex);
-
 	return 0;
 err_dvb_net_init:
 	dvb_dmxdev_release(&adap->dmxdev);
@@ -500,7 +529,7 @@ static int dvb_usb_fe_init(struct dvb_frontend *fe)
 
 	if (!adap->suspend_resume_active) {
 		adap->active_fe = fe->id;
-		mutex_lock(&adap->sync_mutex);
+		set_bit(ADAP_INIT, &adap->state_bits);
 	}
 
 	ret = dvb_usbv2_device_power_ctrl(d, 1);
@@ -519,8 +548,11 @@ static int dvb_usb_fe_init(struct dvb_frontend *fe)
 			goto err;
 	}
 err:
-	if (!adap->suspend_resume_active)
-		mutex_unlock(&adap->sync_mutex);
+	if (!adap->suspend_resume_active) {
+		clear_bit(ADAP_INIT, &adap->state_bits);
+		smp_mb__after_clear_bit();
+		wake_up_bit(&adap->state_bits, ADAP_INIT);
+	}
 
 	dev_dbg(&d->udev->dev, "%s: ret=%d\n", __func__, ret);
 	return ret;
@@ -534,8 +566,11 @@ static int dvb_usb_fe_sleep(struct dvb_frontend *fe)
 	dev_dbg(&d->udev->dev, "%s: adap=%d fe=%d\n", __func__, adap->id,
 			fe->id);
 
-	if (!adap->suspend_resume_active)
-		mutex_lock(&adap->sync_mutex);
+	if (!adap->suspend_resume_active) {
+		set_bit(ADAP_SLEEP, &adap->state_bits);
+		wait_on_bit(&adap->state_bits, ADAP_STREAMING, wait_schedule,
+				TASK_UNINTERRUPTIBLE);
+	}
 
 	if (adap->fe_sleep[fe->id]) {
 		ret = adap->fe_sleep[fe->id](fe);
@@ -555,7 +590,9 @@ static int dvb_usb_fe_sleep(struct dvb_frontend *fe)
 err:
 	if (!adap->suspend_resume_active) {
 		adap->active_fe = -1;
-		mutex_unlock(&adap->sync_mutex);
+		clear_bit(ADAP_SLEEP, &adap->state_bits);
+		smp_mb__after_clear_bit();
+		wake_up_bit(&adap->state_bits, ADAP_SLEEP);
 	}
 
 	dev_dbg(&d->udev->dev, "%s: ret=%d\n", __func__, ret);
@@ -574,8 +611,9 @@ static int dvb_usbv2_adapter_frontend_init(struct dvb_usb_adapter *adap)
 	if (d->props->frontend_attach) {
 		ret = d->props->frontend_attach(adap);
 		if (ret < 0) {
-			dev_dbg(&d->udev->dev, "%s: frontend_attach() " \
-					"failed=%d\n", __func__, ret);
+			dev_dbg(&d->udev->dev,
+					"%s: frontend_attach() failed=%d\n",
+					__func__, ret);
 			goto err_dvb_frontend_detach;
 		}
 	} else {
@@ -595,8 +633,9 @@ static int dvb_usbv2_adapter_frontend_init(struct dvb_usb_adapter *adap)
 
 		ret = dvb_register_frontend(&adap->dvb_adap, adap->fe[i]);
 		if (ret < 0) {
-			dev_err(&d->udev->dev, "%s: frontend%d registration " \
-					"failed\n", KBUILD_MODNAME, i);
+			dev_err(&d->udev->dev,
+					"%s: frontend%d registration failed\n",
+					KBUILD_MODNAME, i);
 			goto err_dvb_unregister_frontend;
 		}
 
@@ -670,33 +709,33 @@ static int dvb_usbv2_adapter_init(struct dvb_usb_device *d)
 		/* speed - when running at FULL speed we need a HW PID filter */
 		if (d->udev->speed == USB_SPEED_FULL &&
 				!(adap->props->caps & DVB_USB_ADAP_HAS_PID_FILTER)) {
-			dev_err(&d->udev->dev, "%s: this USB2.0 device " \
-					"cannot be run on a USB1.1 port (it " \
-					"lacks a hardware PID filter)\n",
+			dev_err(&d->udev->dev,
+					"%s: this USB2.0 device cannot be run on a USB1.1 port (it lacks a hardware PID filter)\n",
 					KBUILD_MODNAME);
 			ret = -ENODEV;
 			goto err;
 		} else if ((d->udev->speed == USB_SPEED_FULL &&
 				adap->props->caps & DVB_USB_ADAP_HAS_PID_FILTER) ||
 				(adap->props->caps & DVB_USB_ADAP_NEED_PID_FILTERING)) {
-			dev_info(&d->udev->dev, "%s: will use the device's " \
-					"hardware PID filter " \
-					"(table count: %d)\n", KBUILD_MODNAME,
+			dev_info(&d->udev->dev,
+					"%s: will use the device's hardware PID filter (table count: %d)\n",
+					KBUILD_MODNAME,
 					adap->props->pid_filter_count);
 			adap->pid_filtering  = 1;
 			adap->max_feed_count = adap->props->pid_filter_count;
 		} else {
-			dev_info(&d->udev->dev, "%s: will pass the complete " \
-					"MPEG2 transport stream to the " \
-					"software demuxer\n", KBUILD_MODNAME);
+			dev_info(&d->udev->dev,
+					"%s: will pass the complete MPEG2 transport stream to the software demuxer\n",
+					KBUILD_MODNAME);
 			adap->pid_filtering  = 0;
 			adap->max_feed_count = 255;
 		}
 
 		if (!adap->pid_filtering && dvb_usb_force_pid_filter_usage &&
 				adap->props->caps & DVB_USB_ADAP_HAS_PID_FILTER) {
-			dev_info(&d->udev->dev, "%s: PID filter enabled by " \
-					"module option\n", KBUILD_MODNAME);
+			dev_info(&d->udev->dev,
+					"%s: PID filter enabled by module option\n",
+					KBUILD_MODNAME);
 			adap->pid_filtering  = 1;
 			adap->max_feed_count = adap->props->pid_filter_count;
 		}
@@ -825,8 +864,9 @@ static void dvb_usbv2_init_work(struct work_struct *work)
 		if (ret == 0) {
 			;
 		} else if (ret == COLD) {
-			dev_info(&d->udev->dev, "%s: found a '%s' in cold " \
-					"state\n", KBUILD_MODNAME, d->name);
+			dev_info(&d->udev->dev,
+					"%s: found a '%s' in cold state\n",
+					KBUILD_MODNAME, d->name);
 
 			if (!name)
 				name = d->props->firmware;
@@ -868,8 +908,9 @@ static void dvb_usbv2_init_work(struct work_struct *work)
 	if (ret < 0)
 		goto err_usb_driver_release_interface;
 
-	dev_info(&d->udev->dev, "%s: '%s' successfully initialized and " \
-			"connected\n", KBUILD_MODNAME, d->name);
+	dev_info(&d->udev->dev,
+			"%s: '%s' successfully initialized and connected\n",
+			KBUILD_MODNAME, d->name);
 
 	return;
 err_usb_driver_release_interface:
diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_urb.c b/drivers/media/usb/dvb-usb-v2/dvb_usb_urb.c
index 5716662..33ff97e 100644
--- a/drivers/media/usb/dvb-usb-v2/dvb_usb_urb.c
+++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_urb.c
@@ -21,8 +21,8 @@
 
 #include "dvb_usb_common.h"
 
-int dvb_usbv2_generic_rw(struct dvb_usb_device *d, u8 *wbuf, u16 wlen, u8 *rbuf,
-		u16 rlen)
+static int dvb_usb_v2_generic_io(struct dvb_usb_device *d,
+		u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
 {
 	int ret, actual_length;
 
@@ -32,8 +32,6 @@ int dvb_usbv2_generic_rw(struct dvb_usb_device *d, u8 *wbuf, u16 wlen, u8 *rbuf,
 		return -EINVAL;
 	}
 
-	mutex_lock(&d->usb_mutex);
-
 	dev_dbg(&d->udev->dev, "%s: >>> %*ph\n", __func__, wlen, wbuf);
 
 	ret = usb_bulk_msg(d->udev, usb_sndbulkpipe(d->udev,
@@ -56,20 +54,51 @@ int dvb_usbv2_generic_rw(struct dvb_usb_device *d, u8 *wbuf, u16 wlen, u8 *rbuf,
 				d->props->generic_bulk_ctrl_endpoint_response),
 				rbuf, rlen, &actual_length, 2000);
 		if (ret)
-			dev_err(&d->udev->dev, "%s: 2nd usb_bulk_msg() " \
-					"failed=%d\n", KBUILD_MODNAME, ret);
+			dev_err(&d->udev->dev,
+					"%s: 2nd usb_bulk_msg() failed=%d\n",
+					KBUILD_MODNAME, ret);
 
 		dev_dbg(&d->udev->dev, "%s: <<< %*ph\n", __func__,
 				actual_length, rbuf);
 	}
 
+	return ret;
+}
+
+int dvb_usbv2_generic_rw(struct dvb_usb_device *d,
+		u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
+{
+	int ret;
+
+	mutex_lock(&d->usb_mutex);
+	ret = dvb_usb_v2_generic_io(d, wbuf, wlen, rbuf, rlen);
 	mutex_unlock(&d->usb_mutex);
+
 	return ret;
 }
 EXPORT_SYMBOL(dvb_usbv2_generic_rw);
 
 int dvb_usbv2_generic_write(struct dvb_usb_device *d, u8 *buf, u16 len)
 {
-	return dvb_usbv2_generic_rw(d, buf, len, NULL, 0);
+	int ret;
+
+	mutex_lock(&d->usb_mutex);
+	ret = dvb_usb_v2_generic_io(d, buf, len, NULL, 0);
+	mutex_unlock(&d->usb_mutex);
+
+	return ret;
 }
 EXPORT_SYMBOL(dvb_usbv2_generic_write);
+
+int dvb_usbv2_generic_rw_locked(struct dvb_usb_device *d,
+		u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
+{
+	return dvb_usb_v2_generic_io(d, wbuf, wlen, rbuf, rlen);
+}
+EXPORT_SYMBOL(dvb_usbv2_generic_rw_locked);
+
+int dvb_usbv2_generic_write_locked(struct dvb_usb_device *d, u8 *buf, u16 len)
+{
+	return dvb_usb_v2_generic_io(d, buf, len, NULL, 0);
+}
+EXPORT_SYMBOL(dvb_usbv2_generic_write_locked);
diff --git a/drivers/media/usb/dvb-usb-v2/it913x.c b/drivers/media/usb/dvb-usb-v2/it913x.c
index 8338479..e48cdeb 100644
--- a/drivers/media/usb/dvb-usb-v2/it913x.c
+++ b/drivers/media/usb/dvb-usb-v2/it913x.c
@@ -218,6 +218,7 @@ static int it913x_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff)
 
 	deb_info(1, "PID_C  (%02x)", onoff);
 
+	st->pid_filter_onoff = adap->pid_filtering;
 	ret = it913x_wr_reg(d, pro, PID_EN, st->pid_filter_onoff);
 
 	mutex_unlock(&d->i2c_mutex);
diff --git a/drivers/media/usb/dvb-usb-v2/lmedm04.c b/drivers/media/usb/dvb-usb-v2/lmedm04.c
index f30c58c..b3fd0ff 100644
--- a/drivers/media/usb/dvb-usb-v2/lmedm04.c
+++ b/drivers/media/usb/dvb-usb-v2/lmedm04.c
@@ -1241,10 +1241,13 @@ static int lme2510_get_stream_config(struct dvb_frontend *fe, u8 *ts_type,
 		struct usb_data_stream_properties *stream)
 {
 	struct dvb_usb_adapter *adap = fe_to_adap(fe);
-	struct dvb_usb_device *d = adap_to_d(adap);
+	struct dvb_usb_device *d;
 
 	if (adap == NULL)
 		return 0;
+
+	d = adap_to_d(adap);
+
 	/* Turn PID filter on the fly by module option */
 	if (pid_filter == 2) {
 		adap->pid_filtering  = 1;
@@ -1299,8 +1302,7 @@ static void lme2510_exit(struct dvb_usb_device *d)
 
 	if (d != NULL) {
 		usb_buffer = lme2510_exit_int(d);
-		if (usb_buffer != NULL)
-			kfree(usb_buffer);
+		kfree(usb_buffer);
 	}
 }
 
diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.h b/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.h
index 432706a..3f3f8bf 100644
--- a/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.h
+++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.h
@@ -21,6 +21,7 @@
 #ifndef __MXL111SF_DEMOD_H__
 #define __MXL111SF_DEMOD_H__
 
+#include <linux/kconfig.h>
 #include "dvb_frontend.h"
 #include "mxl111sf.h"
 
@@ -31,8 +32,7 @@ struct mxl111sf_demod_config {
 			    struct mxl111sf_reg_ctrl_info *ctrl_reg_info);
 };
 
-#if defined(CONFIG_DVB_USB_MXL111SF) || \
-	(defined(CONFIG_DVB_USB_MXL111SF_MODULE) && defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_USB_MXL111SF)
 extern
 struct dvb_frontend *mxl111sf_demod_attach(struct mxl111sf_state *mxl_state,
 					   struct mxl111sf_demod_config *cfg);
diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.h b/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.h
index ff33396..90f583e 100644
--- a/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.h
+++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.h
@@ -21,8 +21,8 @@
 #ifndef __MXL111SF_TUNER_H__
 #define __MXL111SF_TUNER_H__
 
+#include <linux/kconfig.h>
 #include "dvb_frontend.h"
-
 #include "mxl111sf.h"
 
 enum mxl_if_freq {
@@ -60,8 +60,7 @@ struct mxl111sf_tuner_config {
 
 /* ------------------------------------------------------------------------ */
 
-#if defined(CONFIG_DVB_USB_MXL111SF) || \
-	(defined(CONFIG_DVB_USB_MXL111SF_MODULE) && defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_USB_MXL111SF)
 extern
 struct dvb_frontend *mxl111sf_tuner_attach(struct dvb_frontend *fe,
 					   struct mxl111sf_state *mxl_state,
diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
index d98387a..3d128a5 100644
--- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
+++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
@@ -1372,6 +1372,8 @@ static const struct usb_device_id rtl28xxu_id_table[] = {
 		&rtl2832u_props, "Digivox Micro Hd", NULL) },
 	{ DVB_USB_DEVICE(USB_VID_COMPRO, 0x0620,
 		&rtl2832u_props, "Compro VideoMate U620F", NULL) },
+	{ DVB_USB_DEVICE(USB_VID_KWORLD_2, 0xd394,
+		&rtl2832u_props, "MaxMedia HU394-T", NULL) },
 	{ }
 };
 MODULE_DEVICE_TABLE(usb, rtl28xxu_id_table);
diff --git a/drivers/media/usb/dvb-usb-v2/usb_urb.c b/drivers/media/usb/dvb-usb-v2/usb_urb.c
index 7346f85..ca8f3c2 100644
--- a/drivers/media/usb/dvb-usb-v2/usb_urb.c
+++ b/drivers/media/usb/dvb-usb-v2/usb_urb.c
@@ -22,8 +22,8 @@ static void usb_urb_complete(struct urb *urb)
 	int i;
 	u8 *b;
 
-	dev_dbg_ratelimited(&stream->udev->dev, "%s: %s urb completed " \
-			"status=%d length=%d/%d pack_num=%d errors=%d\n",
+	dev_dbg_ratelimited(&stream->udev->dev,
+			"%s: %s urb completed status=%d length=%d/%d pack_num=%d errors=%d\n",
 			__func__, ptype == PIPE_ISOCHRONOUS ? "isoc" : "bulk",
 			urb->status, urb->actual_length,
 			urb->transfer_buffer_length,
@@ -49,8 +49,8 @@ static void usb_urb_complete(struct urb *urb)
 	case PIPE_ISOCHRONOUS:
 		for (i = 0; i < urb->number_of_packets; i++) {
 			if (urb->iso_frame_desc[i].status != 0)
-				dev_dbg(&stream->udev->dev, "%s: iso frame " \
-						"descriptor has an error=%d\n",
+				dev_dbg(&stream->udev->dev,
+						"%s: iso frame descriptor has an error=%d\n",
 						__func__,
 						urb->iso_frame_desc[i].status);
 			else if (urb->iso_frame_desc[i].actual_length > 0)
@@ -67,8 +67,9 @@ static void usb_urb_complete(struct urb *urb)
 			stream->complete(stream, b, urb->actual_length);
 		break;
 	default:
-		dev_err(&stream->udev->dev, "%s: unknown endpoint type in " \
-				"completition handler\n", KBUILD_MODNAME);
+		dev_err(&stream->udev->dev,
+				"%s: unknown endpoint type in completition handler\n",
+				KBUILD_MODNAME);
 		return;
 	}
 	usb_submit_urb(urb, GFP_ATOMIC);
@@ -101,8 +102,8 @@ int usb_urb_submitv2(struct usb_data_stream *stream,
 		dev_dbg(&stream->udev->dev, "%s: submit urb=%d\n", __func__, i);
 		ret = usb_submit_urb(stream->urb_list[i], GFP_ATOMIC);
 		if (ret) {
-			dev_err(&stream->udev->dev, "%s: could not submit " \
-					"urb no. %d - get them all back\n",
+			dev_err(&stream->udev->dev,
+					"%s: could not submit urb no. %d - get them all back\n",
 					KBUILD_MODNAME, i);
 			usb_urb_killv2(stream);
 			return ret;
@@ -229,8 +230,9 @@ static int usb_alloc_stream_buffers(struct usb_data_stream *stream, int num,
 	stream->buf_num = 0;
 	stream->buf_size = size;
 
-	dev_dbg(&stream->udev->dev, "%s: all in all I will use %lu bytes for " \
-			"streaming\n", __func__,  num * size);
+	dev_dbg(&stream->udev->dev,
+			"%s: all in all I will use %lu bytes for streaming\n",
+			__func__,  num * size);
 
 	for (stream->buf_num = 0; stream->buf_num < num; stream->buf_num++) {
 		stream->buf_list[stream->buf_num] = usb_alloc_coherent(
@@ -274,8 +276,8 @@ int usb_urb_reconfig(struct usb_data_stream *stream,
 	}
 
 	if (stream->buf_num < props->count || stream->buf_size < buf_size) {
-		dev_err(&stream->udev->dev, "%s: cannot reconfigure as " \
-				"allocated buffers are too small\n",
+		dev_err(&stream->udev->dev,
+				"%s: cannot reconfigure as allocated buffers are too small\n",
 				KBUILD_MODNAME);
 		return -EINVAL;
 	}
@@ -321,8 +323,9 @@ int usb_urb_initv2(struct usb_data_stream *stream,
 	memcpy(&stream->props, props, sizeof(*props));
 
 	if (!stream->complete) {
-		dev_err(&stream->udev->dev, "%s: there is no data callback - " \
-				"this doesn't make sense\n", KBUILD_MODNAME);
+		dev_err(&stream->udev->dev,
+				"%s: there is no data callback - this doesn't make sense\n",
+				KBUILD_MODNAME);
 		return -EINVAL;
 	}
 
@@ -343,8 +346,9 @@ int usb_urb_initv2(struct usb_data_stream *stream,
 
 		return usb_urb_alloc_isoc_urbs(stream);
 	default:
-		dev_err(&stream->udev->dev, "%s: unknown urb-type for data " \
-				"transfer\n", KBUILD_MODNAME);
+		dev_err(&stream->udev->dev,
+				"%s: unknown urb-type for data transfer\n",
+				KBUILD_MODNAME);
 		return -EINVAL;
 	}
 }
diff --git a/drivers/media/usb/dvb-usb/cinergyT2-fe.c b/drivers/media/usb/dvb-usb/cinergyT2-fe.c
index 1efc028..c890fe4 100644
--- a/drivers/media/usb/dvb-usb/cinergyT2-fe.c
+++ b/drivers/media/usb/dvb-usb/cinergyT2-fe.c
@@ -300,8 +300,7 @@ static int cinergyt2_fe_set_frontend(struct dvb_frontend *fe)
 static void cinergyt2_fe_release(struct dvb_frontend *fe)
 {
 	struct cinergyt2_fe_state *state = fe->demodulator_priv;
-	if (state != NULL)
-		kfree(state);
+	kfree(state);
 }
 
 static struct dvb_frontend_ops cinergyt2_fe_ops;
diff --git a/drivers/media/usb/dvb-usb/dibusb-common.c b/drivers/media/usb/dvb-usb/dibusb-common.c
index af0d432..c2dded9 100644
--- a/drivers/media/usb/dvb-usb/dibusb-common.c
+++ b/drivers/media/usb/dvb-usb/dibusb-common.c
@@ -8,6 +8,8 @@
  *
  * see Documentation/dvb/README.dvb-usb for more information
  */
+
+#include <linux/kconfig.h>
 #include "dibusb.h"
 
 static int debug;
@@ -232,8 +234,7 @@ static struct dibx000_agc_config dib3000p_panasonic_agc_config = {
 	.agc2_slope2 = 0x1e,
 };
 
-#if defined(CONFIG_DVB_DIB3000MC) || 					\
-	(defined(CONFIG_DVB_DIB3000MC_MODULE) && defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_DIB3000MC)
 
 static struct dib3000mc_config mod3000p_dib3000p_config = {
 	&dib3000p_panasonic_agc_config,
diff --git a/drivers/media/usb/dvb-usb/dw2102.c b/drivers/media/usb/dvb-usb/dw2102.c
index 9578a67..6e237b6 100644
--- a/drivers/media/usb/dvb-usb/dw2102.c
+++ b/drivers/media/usb/dvb-usb/dw2102.c
@@ -29,7 +29,6 @@
 #include "stb6100.h"
 #include "stb6100_proc.h"
 #include "m88rs2000.h"
-#include "ts2020.h"
 
 #ifndef USB_PID_DW2102
 #define USB_PID_DW2102 0x2102
@@ -79,6 +78,10 @@
 #define USB_PID_TEVII_S632 0xd632
 #endif
 
+#ifndef USB_PID_GOTVIEW_SAT_HD
+#define USB_PID_GOTVIEW_SAT_HD 0x5456
+#endif
+
 #define DW210X_READ_MSG 0
 #define DW210X_WRITE_MSG 1
 
@@ -1548,6 +1551,8 @@ enum dw2102_table_entry {
 	X3M_SPC1400HD,
 	TEVII_S421,
 	TEVII_S632,
+	TERRATEC_CINERGY_S2_R2,
+	GOTVIEW_SAT_HD,
 };
 
 static struct usb_device_id dw2102_table[] = {
@@ -1568,6 +1573,8 @@ static struct usb_device_id dw2102_table[] = {
 	[X3M_SPC1400HD] = {USB_DEVICE(0x1f4d, 0x3100)},
 	[TEVII_S421] = {USB_DEVICE(0x9022, USB_PID_TEVII_S421)},
 	[TEVII_S632] = {USB_DEVICE(0x9022, USB_PID_TEVII_S632)},
+	[TERRATEC_CINERGY_S2_R2] = {USB_DEVICE(USB_VID_TERRATEC, 0x00b0)},
+	[GOTVIEW_SAT_HD] = {USB_DEVICE(0x1FE1, USB_PID_GOTVIEW_SAT_HD)},
 	{ }
 };
 
@@ -1968,7 +1975,7 @@ static struct dvb_usb_device_properties su3000_properties = {
 		}},
 		}
 	},
-	.num_device_descs = 3,
+	.num_device_descs = 5,
 	.devices = {
 		{ "SU3000HD DVB-S USB2.0",
 			{ &dw2102_table[GENIATECH_SU3000], NULL },
@@ -1982,6 +1989,14 @@ static struct dvb_usb_device_properties su3000_properties = {
 			{ &dw2102_table[X3M_SPC1400HD], NULL },
 			{ NULL },
 		},
+		{ "Terratec Cinergy S2 USB HD Rev.2",
+			{ &dw2102_table[TERRATEC_CINERGY_S2_R2], NULL },
+			{ NULL },
+		},
+		{ "GOTVIEW Satellite HD",
+			{ &dw2102_table[GOTVIEW_SAT_HD], NULL },
+			{ NULL },
+		},
 	}
 };
 
diff --git a/drivers/media/usb/dvb-usb/m920x.c b/drivers/media/usb/dvb-usb/m920x.c
index 92afeb2..79b31ae 100644
--- a/drivers/media/usb/dvb-usb/m920x.c
+++ b/drivers/media/usb/dvb-usb/m920x.c
@@ -68,13 +68,13 @@ static inline int m920x_write_seq(struct usb_device *udev, u8 request,
 				  struct m920x_inits *seq)
 {
 	int ret;
-	while (seq->address) {
+	do {
 		ret = m920x_write(udev, request, seq->data, seq->address);
 		if (ret != 0)
 			return ret;
 
 		seq++;
-	}
+	} while (seq->address);
 
 	return ret;
 }
diff --git a/drivers/media/usb/dvb-usb/opera1.c b/drivers/media/usb/dvb-usb/opera1.c
index c8a9504..16ba90a 100644
--- a/drivers/media/usb/dvb-usb/opera1.c
+++ b/drivers/media/usb/dvb-usb/opera1.c
@@ -151,7 +151,7 @@ static int opera1_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
 			break;
 		}
 		if (dvb_usb_opera1_debug & 0x10)
-			info("sending i2c mesage %d %d", tmp, msg[i].len);
+			info("sending i2c message %d %d", tmp, msg[i].len);
 	}
 	mutex_unlock(&d->i2c_mutex);
 	return num;
diff --git a/drivers/media/usb/em28xx/Kconfig b/drivers/media/usb/em28xx/Kconfig
index c754a80..ca5ee6a 100644
--- a/drivers/media/usb/em28xx/Kconfig
+++ b/drivers/media/usb/em28xx/Kconfig
@@ -46,6 +46,7 @@ config VIDEO_EM28XX_DVB
 	select DVB_A8293 if MEDIA_SUBDRV_AUTOSELECT
 	select DVB_MT352 if MEDIA_SUBDRV_AUTOSELECT
 	select DVB_S5H1409 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_MB86A20S if MEDIA_SUBDRV_AUTOSELECT
 	select MEDIA_TUNER_QT1010 if MEDIA_SUBDRV_AUTOSELECT
 	select MEDIA_TUNER_TDA18271 if MEDIA_SUBDRV_AUTOSELECT
 	---help---
diff --git a/drivers/media/usb/em28xx/Makefile b/drivers/media/usb/em28xx/Makefile
index 634fb92..ad6d485 100644
--- a/drivers/media/usb/em28xx/Makefile
+++ b/drivers/media/usb/em28xx/Makefile
@@ -1,5 +1,5 @@
 em28xx-y +=	em28xx-video.o em28xx-i2c.o em28xx-cards.o
-em28xx-y +=	em28xx-core.o  em28xx-vbi.o
+em28xx-y +=	em28xx-core.o  em28xx-vbi.o em28xx-camera.o
 
 em28xx-alsa-objs := em28xx-audio.o
 em28xx-rc-objs := em28xx-input.o
diff --git a/drivers/media/usb/em28xx/em28xx-camera.c b/drivers/media/usb/em28xx/em28xx-camera.c
new file mode 100644
index 0000000..73cc50a
--- /dev/null
+++ b/drivers/media/usb/em28xx/em28xx-camera.c
@@ -0,0 +1,434 @@
+/*
+   em28xx-camera.c - driver for Empia EM25xx/27xx/28xx USB video capture devices
+
+   Copyright (C) 2009 Mauro Carvalho Chehab <mchehab@infradead.org>
+   Copyright (C) 2013 Frank Schäfer <fschaefer.oss@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
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You 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/i2c.h>
+#include <media/soc_camera.h>
+#include <media/mt9v011.h>
+#include <media/v4l2-common.h>
+
+#include "em28xx.h"
+
+
+/* Possible i2c addresses of Micron sensors */
+static unsigned short micron_sensor_addrs[] = {
+	0xb8 >> 1,   /* MT9V111, MT9V403 */
+	0xba >> 1,   /* MT9M001/011/111/112, MT9V011/012/112, MT9D011 */
+	0x90 >> 1,   /* MT9V012/112, MT9D011 (alternative address) */
+	I2C_CLIENT_END
+};
+
+/* Possible i2c addresses of Omnivision sensors */
+static unsigned short omnivision_sensor_addrs[] = {
+	0x42 >> 1,   /* OV7725, OV7670/60/48 */
+	0x60 >> 1,   /* OV2640, OV9650/53/55 */
+	I2C_CLIENT_END
+};
+
+
+static struct soc_camera_link camlink = {
+	.bus_id = 0,
+	.flags = 0,
+	.module_name = "em28xx",
+};
+
+
+/* FIXME: Should be replaced by a proper mt9m111 driver */
+static int em28xx_initialize_mt9m111(struct em28xx *dev)
+{
+	int i;
+	unsigned char regs[][3] = {
+		{ 0x0d, 0x00, 0x01, },  /* reset and use defaults */
+		{ 0x0d, 0x00, 0x00, },
+		{ 0x0a, 0x00, 0x21, },
+		{ 0x21, 0x04, 0x00, },  /* full readout speed, no row/col skipping */
+	};
+
+	for (i = 0; i < ARRAY_SIZE(regs); i++)
+		i2c_master_send(&dev->i2c_client[dev->def_i2c_bus],
+				&regs[i][0], 3);
+
+	return 0;
+}
+
+
+/* FIXME: Should be replaced by a proper mt9m001 driver */
+static int em28xx_initialize_mt9m001(struct em28xx *dev)
+{
+	int i;
+	unsigned char regs[][3] = {
+		{ 0x0d, 0x00, 0x01, },
+		{ 0x0d, 0x00, 0x00, },
+		{ 0x04, 0x05, 0x00, },	/* hres = 1280 */
+		{ 0x03, 0x04, 0x00, },  /* vres = 1024 */
+		{ 0x20, 0x11, 0x00, },
+		{ 0x06, 0x00, 0x10, },
+		{ 0x2b, 0x00, 0x24, },
+		{ 0x2e, 0x00, 0x24, },
+		{ 0x35, 0x00, 0x24, },
+		{ 0x2d, 0x00, 0x20, },
+		{ 0x2c, 0x00, 0x20, },
+		{ 0x09, 0x0a, 0xd4, },
+		{ 0x35, 0x00, 0x57, },
+	};
+
+	for (i = 0; i < ARRAY_SIZE(regs); i++)
+		i2c_master_send(&dev->i2c_client[dev->def_i2c_bus],
+				&regs[i][0], 3);
+
+	return 0;
+}
+
+
+/*
+ * Probes Micron sensors with 8 bit address and 16 bit register width
+ */
+static int em28xx_probe_sensor_micron(struct em28xx *dev)
+{
+	int ret, i;
+	char *name;
+	u8 reg;
+	__be16 id_be;
+	u16 id;
+
+	struct i2c_client client = dev->i2c_client[dev->def_i2c_bus];
+
+	dev->em28xx_sensor = EM28XX_NOSENSOR;
+	for (i = 0; micron_sensor_addrs[i] != I2C_CLIENT_END; i++) {
+		client.addr = micron_sensor_addrs[i];
+		/* NOTE: i2c_smbus_read_word_data() doesn't work with BE data */
+		/* Read chip ID from register 0x00 */
+		reg = 0x00;
+		ret = i2c_master_send(&client, &reg, 1);
+		if (ret < 0) {
+			if (ret != -ENODEV)
+				em28xx_errdev("couldn't read from i2c device 0x%02x: error %i\n",
+					      client.addr << 1, ret);
+			continue;
+		}
+		ret = i2c_master_recv(&client, (u8 *)&id_be, 2);
+		if (ret < 0) {
+			em28xx_errdev("couldn't read from i2c device 0x%02x: error %i\n",
+				      client.addr << 1, ret);
+			continue;
+		}
+		id = be16_to_cpu(id_be);
+		/* Read chip ID from register 0xff */
+		reg = 0xff;
+		ret = i2c_master_send(&client, &reg, 1);
+		if (ret < 0) {
+			em28xx_errdev("couldn't read from i2c device 0x%02x: error %i\n",
+				      client.addr << 1, ret);
+			continue;
+		}
+		ret = i2c_master_recv(&client, (u8 *)&id_be, 2);
+		if (ret < 0) {
+			em28xx_errdev("couldn't read from i2c device 0x%02x: error %i\n",
+				      client.addr << 1, ret);
+			continue;
+		}
+		/* Validate chip ID to be sure we have a Micron device */
+		if (id != be16_to_cpu(id_be))
+			continue;
+		/* Check chip ID */
+		id = be16_to_cpu(id_be);
+		switch (id) {
+		case 0x1222:
+			name = "MT9V012"; /* MI370 */ /* 640x480 */
+			break;
+		case 0x1229:
+			name = "MT9V112"; /* 640x480 */
+			break;
+		case 0x1433:
+			name = "MT9M011"; /* 1280x1024 */
+			break;
+		case 0x143a:    /* found in the ECS G200 */
+			name = "MT9M111"; /* MI1310 */ /* 1280x1024 */
+			dev->em28xx_sensor = EM28XX_MT9M111;
+			break;
+		case 0x148c:
+			name = "MT9M112"; /* MI1320 */ /* 1280x1024 */
+			break;
+		case 0x1511:
+			name = "MT9D011"; /* MI2010 */ /* 1600x1200 */
+			break;
+		case 0x8232:
+		case 0x8243:	/* rev B */
+			name = "MT9V011"; /* MI360 */ /* 640x480 */
+			dev->em28xx_sensor = EM28XX_MT9V011;
+			break;
+		case 0x8431:
+			name = "MT9M001"; /* 1280x1024 */
+			dev->em28xx_sensor = EM28XX_MT9M001;
+			break;
+		default:
+			em28xx_info("unknown Micron sensor detected: 0x%04x\n",
+				    id);
+			return 0;
+		}
+
+		if (dev->em28xx_sensor == EM28XX_NOSENSOR)
+			em28xx_info("unsupported sensor detected: %s\n", name);
+		else
+			em28xx_info("sensor %s detected\n", name);
+
+		dev->i2c_client[dev->def_i2c_bus].addr = client.addr;
+		return 0;
+	}
+
+	return -ENODEV;
+}
+
+/*
+ * Probes Omnivision sensors with 8 bit address and register width
+ */
+static int em28xx_probe_sensor_omnivision(struct em28xx *dev)
+{
+	int ret, i;
+	char *name;
+	u8 reg;
+	u16 id;
+	struct i2c_client client = dev->i2c_client[dev->def_i2c_bus];
+
+	dev->em28xx_sensor = EM28XX_NOSENSOR;
+	/* NOTE: these devices have the register auto incrementation disabled
+	 * by default, so we have to use single byte reads !              */
+	for (i = 0; omnivision_sensor_addrs[i] != I2C_CLIENT_END; i++) {
+		client.addr = omnivision_sensor_addrs[i];
+		/* Read manufacturer ID from registers 0x1c-0x1d (BE) */
+		reg = 0x1c;
+		ret = i2c_smbus_read_byte_data(&client, reg);
+		if (ret < 0) {
+			if (ret != -ENODEV)
+				em28xx_errdev("couldn't read from i2c device 0x%02x: error %i\n",
+					      client.addr << 1, ret);
+			continue;
+		}
+		id = ret << 8;
+		reg = 0x1d;
+		ret = i2c_smbus_read_byte_data(&client, reg);
+		if (ret < 0) {
+			em28xx_errdev("couldn't read from i2c device 0x%02x: error %i\n",
+				      client.addr << 1, ret);
+			continue;
+		}
+		id += ret;
+		/* Check manufacturer ID */
+		if (id != 0x7fa2)
+			continue;
+		/* Read product ID from registers 0x0a-0x0b (BE) */
+		reg = 0x0a;
+		ret = i2c_smbus_read_byte_data(&client, reg);
+		if (ret < 0) {
+			em28xx_errdev("couldn't read from i2c device 0x%02x: error %i\n",
+				      client.addr << 1, ret);
+			continue;
+		}
+		id = ret << 8;
+		reg = 0x0b;
+		ret = i2c_smbus_read_byte_data(&client, reg);
+		if (ret < 0) {
+			em28xx_errdev("couldn't read from i2c device 0x%02x: error %i\n",
+				      client.addr << 1, ret);
+			continue;
+		}
+		id += ret;
+		/* Check product ID */
+		switch (id) {
+		case 0x2642:
+			name = "OV2640";
+			dev->em28xx_sensor = EM28XX_OV2640;
+			break;
+		case 0x7648:
+			name = "OV7648";
+			break;
+		case 0x7660:
+			name = "OV7660";
+			break;
+		case 0x7673:
+			name = "OV7670";
+			break;
+		case 0x7720:
+			name = "OV7720";
+			break;
+		case 0x7721:
+			name = "OV7725";
+			break;
+		case 0x9648: /* Rev 2 */
+		case 0x9649: /* Rev 3 */
+			name = "OV9640";
+			break;
+		case 0x9650:
+		case 0x9652: /* OV9653 */
+			name = "OV9650";
+			break;
+		case 0x9656: /* Rev 4 */
+		case 0x9657: /* Rev 5 */
+			name = "OV9655";
+			break;
+		default:
+			em28xx_info("unknown OmniVision sensor detected: 0x%04x\n",
+				    id);
+			return 0;
+		}
+
+		if (dev->em28xx_sensor == EM28XX_NOSENSOR)
+			em28xx_info("unsupported sensor detected: %s\n", name);
+		else
+			em28xx_info("sensor %s detected\n", name);
+
+		dev->i2c_client[dev->def_i2c_bus].addr = client.addr;
+		return 0;
+	}
+
+	return -ENODEV;
+}
+
+int em28xx_detect_sensor(struct em28xx *dev)
+{
+	int ret;
+
+	ret = em28xx_probe_sensor_micron(dev);
+
+	if (dev->em28xx_sensor == EM28XX_NOSENSOR && ret < 0)
+		ret = em28xx_probe_sensor_omnivision(dev);
+
+	/*
+	 * NOTE: the Windows driver also probes i2c addresses
+	 *       0x22 (Samsung ?) and 0x66 (Kodak ?)
+	 */
+
+	if (dev->em28xx_sensor == EM28XX_NOSENSOR && ret < 0) {
+		em28xx_info("No sensor detected\n");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+int em28xx_init_camera(struct em28xx *dev)
+{
+	switch (dev->em28xx_sensor) {
+	case EM28XX_MT9V011:
+	{
+		struct mt9v011_platform_data pdata;
+		struct i2c_board_info mt9v011_info = {
+			.type = "mt9v011",
+			.addr = dev->i2c_client[dev->def_i2c_bus].addr,
+			.platform_data = &pdata,
+		};
+
+		dev->sensor_xres = 640;
+		dev->sensor_yres = 480;
+
+		/*
+		 * FIXME: mt9v011 uses I2S speed as xtal clk - at least with
+		 * the Silvercrest cam I have here for testing - for higher
+		 * resolutions, a high clock cause horizontal artifacts, so we
+		 * need to use a lower xclk frequency.
+		 * Yet, it would be possible to adjust xclk depending on the
+		 * desired resolution, since this affects directly the
+		 * frame rate.
+		 */
+		dev->board.xclk = EM28XX_XCLK_FREQUENCY_4_3MHZ;
+		em28xx_write_reg(dev, EM28XX_R0F_XCLK, dev->board.xclk);
+		dev->sensor_xtal = 4300000;
+		pdata.xtal = dev->sensor_xtal;
+		if (NULL ==
+		    v4l2_i2c_new_subdev_board(&dev->v4l2_dev,
+					      &dev->i2c_adap[dev->def_i2c_bus],
+					      &mt9v011_info, NULL))
+			return -ENODEV;
+		/* probably means GRGB 16 bit bayer */
+		dev->vinmode = 0x0d;
+		dev->vinctl = 0x00;
+
+		break;
+	}
+	case EM28XX_MT9M001:
+		dev->sensor_xres = 1280;
+		dev->sensor_yres = 1024;
+
+		em28xx_initialize_mt9m001(dev);
+
+		/* probably means BGGR 16 bit bayer */
+		dev->vinmode = 0x0c;
+		dev->vinctl = 0x00;
+
+		break;
+	case EM28XX_MT9M111:
+		dev->sensor_xres = 640;
+		dev->sensor_yres = 512;
+
+		dev->board.xclk = EM28XX_XCLK_FREQUENCY_48MHZ;
+		em28xx_write_reg(dev, EM28XX_R0F_XCLK, dev->board.xclk);
+		em28xx_initialize_mt9m111(dev);
+
+		dev->vinmode = 0x0a;
+		dev->vinctl = 0x00;
+
+		break;
+	case EM28XX_OV2640:
+	{
+		struct v4l2_subdev *subdev;
+		struct i2c_board_info ov2640_info = {
+			.type = "ov2640",
+			.flags = I2C_CLIENT_SCCB,
+			.addr = dev->i2c_client[dev->def_i2c_bus].addr,
+			.platform_data = &camlink,
+		};
+		struct v4l2_mbus_framefmt fmt;
+
+		/*
+		 * FIXME: sensor supports resolutions up to 1600x1200, but
+		 * resolution setting/switching needs to be modified to
+		 * - switch sensor output resolution (including further
+		 *   configuration changes)
+		 * - adjust bridge xclk
+		 * - disable 16 bit (12 bit) output formats on high resolutions
+		 */
+		dev->sensor_xres = 640;
+		dev->sensor_yres = 480;
+
+		subdev =
+		     v4l2_i2c_new_subdev_board(&dev->v4l2_dev,
+					       &dev->i2c_adap[dev->def_i2c_bus],
+					       &ov2640_info, NULL);
+
+		fmt.code = V4L2_MBUS_FMT_YUYV8_2X8;
+		fmt.width = 640;
+		fmt.height = 480;
+		v4l2_subdev_call(subdev, video, s_mbus_fmt, &fmt);
+
+		/* NOTE: for UXGA=1600x1200 switch to 12MHz */
+		dev->board.xclk = EM28XX_XCLK_FREQUENCY_24MHZ;
+		em28xx_write_reg(dev, EM28XX_R0F_XCLK, dev->board.xclk);
+		dev->vinmode = 0x08;
+		dev->vinctl = 0x00;
+
+		break;
+	}
+	case EM28XX_NOSENSOR:
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c
index 54a03b20..1d3866f 100644
--- a/drivers/media/usb/em28xx/em28xx-cards.c
+++ b/drivers/media/usb/em28xx/em28xx-cards.c
@@ -34,7 +34,6 @@
 #include <media/saa7115.h>
 #include <media/tvp5150.h>
 #include <media/tvaudio.h>
-#include <media/mt9v011.h>
 #include <media/i2c-addr.h>
 #include <media/tveeprom.h>
 #include <media/v4l2-common.h>
@@ -345,6 +344,18 @@ static struct em28xx_reg_seq pctv_460e[] = {
 	{             -1,   -1,   -1,  -1},
 };
 
+static struct em28xx_reg_seq c3tech_digital_duo_digital[] = {
+	{EM2874_R80_GPIO,	0xff,	0xff,	10},
+	{EM2874_R80_GPIO,	0xfd,	0xff,	10}, /* xc5000 reset */
+	{EM2874_R80_GPIO,	0xf9,	0xff,	35},
+	{EM2874_R80_GPIO,	0xfd,	0xff,	10},
+	{EM2874_R80_GPIO,	0xff,	0xff,	10},
+	{EM2874_R80_GPIO,	0xfe,	0xff,	10},
+	{EM2874_R80_GPIO,	0xbe,	0xff,	10},
+	{EM2874_R80_GPIO,	0xfe,	0xff,	20},
+	{ -1,			-1,	-1,	-1},
+};
+
 #if 0
 static struct em28xx_reg_seq hauppauge_930c_gpio[] = {
 	{EM2874_R80_GPIO,	0x6f,	0xff,	10},
@@ -958,8 +969,8 @@ struct em28xx_board em28xx_boards[] = {
 #else
 		.tuner_type   = TUNER_ABSENT,
 #endif
-		.i2c_speed    = EM2874_I2C_SECONDARY_BUS_SELECT |
-				EM28XX_I2C_CLK_WAIT_ENABLE |
+		.def_i2c_bus  = 1,
+		.i2c_speed    = EM28XX_I2C_CLK_WAIT_ENABLE |
 				EM28XX_I2C_FREQ_400_KHZ,
 	},
 	[EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C] = {
@@ -974,17 +985,27 @@ struct em28xx_board em28xx_boards[] = {
 		.tuner_type   = TUNER_ABSENT,
 #endif
 		.ir_codes     = RC_MAP_HAUPPAUGE,
-		.i2c_speed    = EM2874_I2C_SECONDARY_BUS_SELECT |
-				EM28XX_I2C_CLK_WAIT_ENABLE |
+		.def_i2c_bus  = 1,
+		.i2c_speed    = EM28XX_I2C_CLK_WAIT_ENABLE |
 				EM28XX_I2C_FREQ_400_KHZ,
 	},
+	[EM2884_BOARD_C3TECH_DIGITAL_DUO] = {
+		.name         = "C3 Tech Digital Duo HDTV/SDTV USB",
+		.has_dvb      = 1,
+		/* FIXME: Add analog support - need a saa7136 driver */
+		.tuner_type = TUNER_ABSENT,	/* Digital-only TDA18271HD */
+		.ir_codes     = RC_MAP_EMPTY,
+		.def_i2c_bus  = 1,
+		.i2c_speed    = EM28XX_I2C_CLK_WAIT_ENABLE,
+		.dvb_gpio     = c3tech_digital_duo_digital,
+	},
 	[EM2884_BOARD_CINERGY_HTC_STICK] = {
 		.name         = "Terratec Cinergy HTC Stick",
 		.has_dvb      = 1,
 		.ir_codes     = RC_MAP_NEC_TERRATEC_CINERGY_XS,
 		.tuner_type   = TUNER_ABSENT,
-		.i2c_speed    = EM2874_I2C_SECONDARY_BUS_SELECT |
-				EM28XX_I2C_CLK_WAIT_ENABLE |
+		.def_i2c_bus  = 1,
+		.i2c_speed    = EM28XX_I2C_CLK_WAIT_ENABLE |
 				EM28XX_I2C_FREQ_400_KHZ,
 	},
 	[EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900] = {
@@ -1404,8 +1425,8 @@ struct em28xx_board em28xx_boards[] = {
 	},
 
 	[EM2874_BOARD_LEADERSHIP_ISDBT] = {
-		.i2c_speed      = EM2874_I2C_SECONDARY_BUS_SELECT |
-				  EM28XX_I2C_CLK_WAIT_ENABLE |
+		.def_i2c_bus	= 1,
+		.i2c_speed      = EM28XX_I2C_CLK_WAIT_ENABLE |
 				  EM28XX_I2C_FREQ_100_KHZ,
 		.xclk		= EM28XX_XCLK_FREQUENCY_10MHZ,
 		.name		= "EM2874 Leadership ISDBT",
@@ -1917,8 +1938,8 @@ struct em28xx_board em28xx_boards[] = {
 	 * Empia EM28174, Sony CXD2820R and NXP TDA18271HD/C2 */
 	[EM28174_BOARD_PCTV_290E] = {
 		.name          = "PCTV nanoStick T2 290e",
-		.i2c_speed      = EM2874_I2C_SECONDARY_BUS_SELECT |
-			EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_FREQ_100_KHZ,
+		.def_i2c_bus   = 1,
+		.i2c_speed     = EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_FREQ_100_KHZ,
 		.tuner_type    = TUNER_ABSENT,
 		.tuner_gpio    = pctv_290e,
 		.has_dvb       = 1,
@@ -1927,8 +1948,8 @@ struct em28xx_board em28xx_boards[] = {
 	/* 2013:024f PCTV DVB-S2 Stick 460e
 	 * Empia EM28174, NXP TDA10071, Conexant CX24118A and Allegro A8293 */
 	[EM28174_BOARD_PCTV_460E] = {
-		.i2c_speed     = EM2874_I2C_SECONDARY_BUS_SELECT |
-			EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_FREQ_400_KHZ,
+		.def_i2c_bus   = 1,
+		.i2c_speed     = EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_FREQ_400_KHZ,
 		.name          = "PCTV DVB-S2 Stick (460e)",
 		.tuner_type    = TUNER_ABSENT,
 		.tuner_gpio    = pctv_460e,
@@ -1958,8 +1979,8 @@ struct em28xx_board em28xx_boards[] = {
 		.tuner_type    = TUNER_ABSENT,
 		.tuner_gpio    = maxmedia_ub425_tc,
 		.has_dvb       = 1,
-		.i2c_speed     = EM2874_I2C_SECONDARY_BUS_SELECT |
-				EM28XX_I2C_CLK_WAIT_ENABLE |
+		.def_i2c_bus   = 1,
+		.i2c_speed     = EM28XX_I2C_CLK_WAIT_ENABLE |
 				EM28XX_I2C_FREQ_400_KHZ,
 	},
 	/* 2304:0242 PCTV QuatroStick (510e)
@@ -1970,8 +1991,8 @@ struct em28xx_board em28xx_boards[] = {
 		.tuner_gpio    = pctv_510e,
 		.has_dvb       = 1,
 		.ir_codes      = RC_MAP_PINNACLE_PCTV_HD,
-		.i2c_speed     = EM2874_I2C_SECONDARY_BUS_SELECT |
-				EM28XX_I2C_CLK_WAIT_ENABLE |
+		.def_i2c_bus   = 1,
+		.i2c_speed     = EM28XX_I2C_CLK_WAIT_ENABLE |
 				EM28XX_I2C_FREQ_400_KHZ,
 	},
 	/* 2013:0251 PCTV QuatroStick nano (520e)
@@ -1982,8 +2003,8 @@ struct em28xx_board em28xx_boards[] = {
 		.tuner_gpio    = pctv_520e,
 		.has_dvb       = 1,
 		.ir_codes      = RC_MAP_PINNACLE_PCTV_HD,
-		.i2c_speed     = EM2874_I2C_SECONDARY_BUS_SELECT |
-				EM28XX_I2C_CLK_WAIT_ENABLE |
+		.def_i2c_bus   = 1,
+		.i2c_speed     = EM28XX_I2C_CLK_WAIT_ENABLE |
 				EM28XX_I2C_FREQ_400_KHZ,
 	},
 	[EM2884_BOARD_TERRATEC_HTC_USB_XS] = {
@@ -1991,8 +2012,8 @@ struct em28xx_board em28xx_boards[] = {
 		.has_dvb      = 1,
 		.ir_codes     = RC_MAP_NEC_TERRATEC_CINERGY_XS,
 		.tuner_type   = TUNER_ABSENT,
-		.i2c_speed    = EM2874_I2C_SECONDARY_BUS_SELECT |
-				EM28XX_I2C_CLK_WAIT_ENABLE |
+		.def_i2c_bus  = 1,
+		.i2c_speed    = EM28XX_I2C_CLK_WAIT_ENABLE |
 				EM28XX_I2C_FREQ_400_KHZ,
 	},
 };
@@ -2144,6 +2165,8 @@ struct usb_device_id em28xx_id_table[] = {
 			.driver_info = EM28174_BOARD_PCTV_460E },
 	{ USB_DEVICE(0x2040, 0x1605),
 			.driver_info = EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C },
+	{ USB_DEVICE(0x1b80, 0xe755),
+			.driver_info = EM2884_BOARD_C3TECH_DIGITAL_DUO },
 	{ USB_DEVICE(0xeb1a, 0x5006),
 			.driver_info = EM2860_BOARD_HT_VIDBOX_NW03 },
 	{ USB_DEVICE(0x1b80, 0xe309), /* Sveon STV40 */
@@ -2183,6 +2206,7 @@ static struct em28xx_hash_table em28xx_i2c_hash[] = {
 	{0x4ba50080, EM2861_BOARD_GADMEI_UTV330PLUS, TUNER_TNF_5335MF},
 	{0x6b800080, EM2874_BOARD_LEADERSHIP_ISDBT, TUNER_ABSENT},
 };
+/* NOTE: introduce a separate hash table for devices with 16 bit eeproms */
 
 /* I2C possible address to saa7115, tvp5150, msp3400, tvaudio */
 static unsigned short saa711x_addrs[] = {
@@ -2204,8 +2228,9 @@ static unsigned short msp3400_addrs[] = {
 
 int em28xx_tuner_callback(void *ptr, int component, int command, int arg)
 {
+	struct em28xx_i2c_bus *i2c_bus = ptr;
+	struct em28xx *dev = i2c_bus->dev;
 	int rc = 0;
-	struct em28xx *dev = ptr;
 
 	if (dev->tuner_type != TUNER_XC2028 && dev->tuner_type != TUNER_XC5000)
 		return 0;
@@ -2233,145 +2258,9 @@ static inline void em28xx_set_model(struct em28xx *dev)
 	if (!dev->board.i2c_speed)
 		dev->board.i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE |
 				       EM28XX_I2C_FREQ_100_KHZ;
-}
-
-
-/* FIXME: Should be replaced by a proper mt9m111 driver */
-static int em28xx_initialize_mt9m111(struct em28xx *dev)
-{
-	int i;
-	unsigned char regs[][3] = {
-		{ 0x0d, 0x00, 0x01, },  /* reset and use defaults */
-		{ 0x0d, 0x00, 0x00, },
-		{ 0x0a, 0x00, 0x21, },
-		{ 0x21, 0x04, 0x00, },  /* full readout speed, no row/col skipping */
-	};
-
-	for (i = 0; i < ARRAY_SIZE(regs); i++)
-		i2c_master_send(&dev->i2c_client, &regs[i][0], 3);
-
-	return 0;
-}
-
-
-/* FIXME: Should be replaced by a proper mt9m001 driver */
-static int em28xx_initialize_mt9m001(struct em28xx *dev)
-{
-	int i;
-	unsigned char regs[][3] = {
-		{ 0x0d, 0x00, 0x01, },
-		{ 0x0d, 0x00, 0x00, },
-		{ 0x04, 0x05, 0x00, },	/* hres = 1280 */
-		{ 0x03, 0x04, 0x00, },  /* vres = 1024 */
-		{ 0x20, 0x11, 0x00, },
-		{ 0x06, 0x00, 0x10, },
-		{ 0x2b, 0x00, 0x24, },
-		{ 0x2e, 0x00, 0x24, },
-		{ 0x35, 0x00, 0x24, },
-		{ 0x2d, 0x00, 0x20, },
-		{ 0x2c, 0x00, 0x20, },
-		{ 0x09, 0x0a, 0xd4, },
-		{ 0x35, 0x00, 0x57, },
-	};
-
-	for (i = 0; i < ARRAY_SIZE(regs); i++)
-		i2c_master_send(&dev->i2c_client, &regs[i][0], 3);
-
-	return 0;
-}
-
-/* HINT method: webcam I2C chips
- *
- * This method works for webcams with Micron sensors
- */
-static int em28xx_hint_sensor(struct em28xx *dev)
-{
-	int rc;
-	char *sensor_name;
-	unsigned char cmd;
-	__be16 version_be;
-	u16 version;
-
-	/* Micron sensor detection */
-	dev->i2c_client.addr = 0xba >> 1;
-	cmd = 0;
-	i2c_master_send(&dev->i2c_client, &cmd, 1);
-	rc = i2c_master_recv(&dev->i2c_client, (char *)&version_be, 2);
-	if (rc != 2)
-		return -EINVAL;
-
-	version = be16_to_cpu(version_be);
-	switch (version) {
-	case 0x8232:		/* mt9v011 640x480 1.3 Mpix sensor */
-	case 0x8243:		/* mt9v011 rev B 640x480 1.3 Mpix sensor */
-		dev->model = EM2820_BOARD_SILVERCREST_WEBCAM;
-		em28xx_set_model(dev);
-
-		sensor_name = "mt9v011";
-		dev->em28xx_sensor = EM28XX_MT9V011;
-		dev->sensor_xres = 640;
-		dev->sensor_yres = 480;
-		/*
-		 * FIXME: mt9v011 uses I2S speed as xtal clk - at least with
-		 * the Silvercrest cam I have here for testing - for higher
-		 * resolutions, a high clock cause horizontal artifacts, so we
-		 * need to use a lower xclk frequency.
-		 * Yet, it would be possible to adjust xclk depending on the
-		 * desired resolution, since this affects directly the
-		 * frame rate.
-		 */
-		dev->board.xclk = EM28XX_XCLK_FREQUENCY_4_3MHZ;
-		dev->sensor_xtal = 4300000;
-
-		/* probably means GRGB 16 bit bayer */
-		dev->vinmode = 0x0d;
-		dev->vinctl = 0x00;
-
-		break;
-
-	case 0x143a:    /* MT9M111 as found in the ECS G200 */
-		dev->model = EM2750_BOARD_UNKNOWN;
-		em28xx_set_model(dev);
-
-		sensor_name = "mt9m111";
-		dev->board.xclk = EM28XX_XCLK_FREQUENCY_48MHZ;
-		dev->em28xx_sensor = EM28XX_MT9M111;
-		em28xx_initialize_mt9m111(dev);
-		dev->sensor_xres = 640;
-		dev->sensor_yres = 512;
-
-		dev->vinmode = 0x0a;
-		dev->vinctl = 0x00;
-
-		break;
-
-	case 0x8431:
-		dev->model = EM2750_BOARD_UNKNOWN;
-		em28xx_set_model(dev);
-
-		sensor_name = "mt9m001";
-		dev->em28xx_sensor = EM28XX_MT9M001;
-		em28xx_initialize_mt9m001(dev);
-		dev->sensor_xres = 1280;
-		dev->sensor_yres = 1024;
-
-		/* probably means BGGR 16 bit bayer */
-		dev->vinmode = 0x0c;
-		dev->vinctl = 0x00;
 
-		break;
-	default:
-		printk("Unknown Micron Sensor 0x%04x\n", version);
-		return -EINVAL;
-	}
-
-	/* Setup webcam defaults */
-	em28xx_pre_card_setup(dev);
-
-	em28xx_errdev("Sensor is %s, using model %s entry.\n",
-		      sensor_name, em28xx_boards[dev->model].name);
-
-	return 0;
+	/* Should be initialized early, for I2C to work */
+	dev->def_i2c_bus = dev->board.def_i2c_bus;
 }
 
 /* Since em28xx_pre_card_setup() requires a proper dev->model,
@@ -2599,6 +2488,18 @@ static int em28xx_hint_board(struct em28xx *dev)
 {
 	int i;
 
+	if (dev->board.is_webcam) {
+		if (dev->em28xx_sensor == EM28XX_MT9V011) {
+			dev->model = EM2820_BOARD_SILVERCREST_WEBCAM;
+		} else if (dev->em28xx_sensor == EM28XX_MT9M001 ||
+			   dev->em28xx_sensor == EM28XX_MT9M111) {
+			dev->model = EM2750_BOARD_UNKNOWN;
+		}
+		/* FIXME: IMPROVE ! */
+
+		return 0;
+	}
+
 	/* HINT method: EEPROM
 	 *
 	 * This method works only for boards with eeprom.
@@ -2638,7 +2539,7 @@ static int em28xx_hint_board(struct em28xx *dev)
 
 	/* user did not request i2c scanning => do it now */
 	if (!dev->i2c_hash)
-		em28xx_do_i2c_scan(dev);
+		em28xx_do_i2c_scan(dev, dev->def_i2c_bus);
 
 	for (i = 0; i < ARRAY_SIZE(em28xx_i2c_hash); i++) {
 		if (dev->i2c_hash == em28xx_i2c_hash[i].hash) {
@@ -2684,16 +2585,16 @@ static void em28xx_card_setup(struct em28xx *dev)
 	 * If sensor is not found, then it isn't a webcam.
 	 */
 	if (dev->board.is_webcam) {
-		if (em28xx_hint_sensor(dev) < 0)
+		if (em28xx_detect_sensor(dev) < 0)
 			dev->board.is_webcam = 0;
 		else
 			dev->progressive = 1;
 	}
 
-	if (!dev->board.is_webcam) {
-		switch (dev->model) {
-		case EM2820_BOARD_UNKNOWN:
-		case EM2800_BOARD_UNKNOWN:
+	switch (dev->model) {
+	case EM2750_BOARD_UNKNOWN:
+	case EM2820_BOARD_UNKNOWN:
+	case EM2800_BOARD_UNKNOWN:
 		/*
 		 * The K-WORLD DVB-T 310U is detected as an MSI Digivox AD.
 		 *
@@ -2714,9 +2615,8 @@ static void em28xx_card_setup(struct em28xx *dev)
 			em28xx_pre_card_setup(dev);
 		}
 		break;
-		default:
-			em28xx_set_model(dev);
-		}
+	default:
+		em28xx_set_model(dev);
 	}
 
 	em28xx_info("Identified as %s (card=%d)\n",
@@ -2736,15 +2636,19 @@ static void em28xx_card_setup(struct em28xx *dev)
 	case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2:
 	case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850:
 	case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950:
+	case EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C:
 	{
 		struct tveeprom tv;
+
+		if (dev->eedata == NULL)
+			break;
 #if defined(CONFIG_MODULES) && defined(MODULE)
 		request_module("tveeprom");
 #endif
 		/* Call first TVeeprom */
 
-		dev->i2c_client.addr = 0xa0 >> 1;
-		tveeprom_hauppauge_analog(&dev->i2c_client, &tv, dev->eedata);
+		dev->i2c_client[dev->def_i2c_bus].addr = 0xa0 >> 1;
+		tveeprom_hauppauge_analog(&dev->i2c_client[dev->def_i2c_bus], &tv, dev->eedata);
 
 		dev->tuner_type = tv.tuner_type;
 
@@ -2791,7 +2695,7 @@ static void em28xx_card_setup(struct em28xx *dev)
 		em28xx_set_mode(dev, EM28XX_ANALOG_MODE);
 		break;
 
-/*
+		/*
 		 * The Dikom DK300 is detected as an Kworld VS-DVB-T 323UR.
 		 *
 		 * This occurs because they share identical USB vendor and
@@ -2826,51 +2730,41 @@ static void em28xx_card_setup(struct em28xx *dev)
 				"addresses)\n\n");
 	}
 
+	/* Free eeprom data memory */
+	kfree(dev->eedata);
+	dev->eedata = NULL;
+
 	/* Allow override tuner type by a module parameter */
 	if (tuner >= 0)
 		dev->tuner_type = tuner;
 
 	/* request some modules */
 	if (dev->board.has_msp34xx)
-		v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
+		v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap[dev->def_i2c_bus],
 			"msp3400", 0, msp3400_addrs);
 
 	if (dev->board.decoder == EM28XX_SAA711X)
-		v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
+		v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap[dev->def_i2c_bus],
 			"saa7115_auto", 0, saa711x_addrs);
 
 	if (dev->board.decoder == EM28XX_TVP5150)
-		v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
+		v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap[dev->def_i2c_bus],
 			"tvp5150", 0, tvp5150_addrs);
 
-	if (dev->em28xx_sensor == EM28XX_MT9V011) {
-		struct mt9v011_platform_data pdata;
-		struct i2c_board_info mt9v011_info = {
-			.type = "mt9v011",
-			.addr = 0xba >> 1,
-			.platform_data = &pdata,
-		};
-
-		pdata.xtal = dev->sensor_xtal;
-		v4l2_i2c_new_subdev_board(&dev->v4l2_dev, &dev->i2c_adap,
-				&mt9v011_info, NULL);
-	}
-
-
 	if (dev->board.adecoder == EM28XX_TVAUDIO)
-		v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
+		v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap[dev->def_i2c_bus],
 			"tvaudio", dev->board.tvaudio_addr, NULL);
 
 	if (dev->board.tuner_type != TUNER_ABSENT) {
 		int has_demod = (dev->tda9887_conf & TDA9887_PRESENT);
 
 		if (dev->board.radio.type)
-			v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
+			v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap[dev->def_i2c_bus],
 				"tuner", dev->board.radio_addr, NULL);
 
 		if (has_demod)
 			v4l2_i2c_new_subdev(&dev->v4l2_dev,
-				&dev->i2c_adap, "tuner",
+				&dev->i2c_adap[dev->def_i2c_bus], "tuner",
 				0, v4l2_i2c_tuner_addrs(ADDRS_DEMOD));
 		if (dev->tuner_addr == 0) {
 			enum v4l2_i2c_tuner_type type =
@@ -2878,18 +2772,20 @@ static void em28xx_card_setup(struct em28xx *dev)
 			struct v4l2_subdev *sd;
 
 			sd = v4l2_i2c_new_subdev(&dev->v4l2_dev,
-				&dev->i2c_adap, "tuner",
+				&dev->i2c_adap[dev->def_i2c_bus], "tuner",
 				0, v4l2_i2c_tuner_addrs(type));
 
 			if (sd)
 				dev->tuner_addr = v4l2_i2c_subdev_addr(sd);
 		} else {
-			v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
+			v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap[dev->def_i2c_bus],
 				"tuner", dev->tuner_addr, NULL);
 		}
 	}
 
 	em28xx_tuner_setup(dev);
+
+	em28xx_init_camera(dev);
 }
 
 
@@ -2941,7 +2837,9 @@ void em28xx_release_resources(struct em28xx *dev)
 
 	em28xx_release_analog_resources(dev);
 
-	em28xx_i2c_unregister(dev);
+	if (dev->def_i2c_bus)
+		em28xx_i2c_unregister(dev, 1);
+	em28xx_i2c_unregister(dev, 0);
 
 	v4l2_ctrl_handler_free(&dev->ctrl_handler);
 
@@ -3002,6 +2900,12 @@ static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev,
 		case CHIP_ID_EM2750:
 			chip_name = "em2750";
 			break;
+		case CHIP_ID_EM2765:
+			chip_name = "em2765";
+			dev->wait_after_write = 0;
+			dev->is_em25xx = 1;
+			dev->eeprom_addrwidth_16bit = 1;
+			break;
 		case CHIP_ID_EM2820:
 			chip_name = "em2710/2820";
 			break;
@@ -3019,11 +2923,13 @@ static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev,
 			chip_name = "em2874";
 			dev->reg_gpio_num = EM2874_R80_GPIO;
 			dev->wait_after_write = 0;
+			dev->eeprom_addrwidth_16bit = 1;
 			break;
 		case CHIP_ID_EM28174:
 			chip_name = "em28174";
 			dev->reg_gpio_num = EM2874_R80_GPIO;
 			dev->wait_after_write = 0;
+			dev->eeprom_addrwidth_16bit = 1;
 			break;
 		case CHIP_ID_EM2883:
 			chip_name = "em2882/3";
@@ -3033,6 +2939,7 @@ static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev,
 			chip_name = "em2884";
 			dev->reg_gpio_num = EM2874_R80_GPIO;
 			dev->wait_after_write = 0;
+			dev->eeprom_addrwidth_16bit = 1;
 			break;
 		default:
 			printk(KERN_INFO DRIVER_NAME
@@ -3091,17 +2998,37 @@ static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev,
 		return retval;
 	}
 
-	v4l2_ctrl_handler_init(hdl, 4);
+	v4l2_ctrl_handler_init(hdl, 8);
 	dev->v4l2_dev.ctrl_handler = hdl;
 
-	/* register i2c bus */
-	retval = em28xx_i2c_register(dev);
+	rt_mutex_init(&dev->i2c_bus_lock);
+
+	/* register i2c bus 0 */
+	if (dev->board.is_em2800)
+		retval = em28xx_i2c_register(dev, 0, EM28XX_I2C_ALGO_EM2800);
+	else
+		retval = em28xx_i2c_register(dev, 0, EM28XX_I2C_ALGO_EM28XX);
 	if (retval < 0) {
-		em28xx_errdev("%s: em28xx_i2c_register - error [%d]!\n",
+		em28xx_errdev("%s: em28xx_i2c_register bus 0 - error [%d]!\n",
 			__func__, retval);
 		goto unregister_dev;
 	}
 
+	/* register i2c bus 1 */
+	if (dev->def_i2c_bus) {
+		if (dev->is_em25xx)
+			retval = em28xx_i2c_register(dev, 1,
+						  EM28XX_I2C_ALGO_EM25XX_BUS_B);
+		else
+			retval = em28xx_i2c_register(dev, 1,
+							EM28XX_I2C_ALGO_EM28XX);
+		if (retval < 0) {
+			em28xx_errdev("%s: em28xx_i2c_register bus 1 - error [%d]!\n",
+				__func__, retval);
+			goto unregister_dev;
+		}
+	}
+
 	/*
 	 * Default format, used for tvp5150 or saa711x output formats
 	 */
@@ -3160,11 +3087,6 @@ static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev,
 		msleep(3);
 	}
 
-	v4l2_ctrl_handler_setup(&dev->ctrl_handler);
-	retval = dev->ctrl_handler.error;
-	if (retval)
-		goto fail;
-
 	retval = em28xx_register_analog_devices(dev);
 	if (retval < 0) {
 		goto fail;
@@ -3176,7 +3098,9 @@ static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev,
 	return 0;
 
 fail:
-	em28xx_i2c_unregister(dev);
+	if (dev->def_i2c_bus)
+		em28xx_i2c_unregister(dev, 1);
+	em28xx_i2c_unregister(dev, 0);
 	v4l2_ctrl_handler_free(&dev->ctrl_handler);
 
 unregister_dev:
@@ -3292,14 +3216,15 @@ static int em28xx_usb_probe(struct usb_interface *interface,
 						dev->analog_ep_bulk =
 							    e->bEndpointAddress;
 					} else {
-						has_dvb = true;
 						if (usb_endpoint_xfer_isoc(e)) {
 							dev->dvb_ep_isoc = e->bEndpointAddress;
 							if (size > dev->dvb_max_pkt_size_isoc) {
+								has_dvb = true; /* see NOTE (~) */
 								dev->dvb_max_pkt_size_isoc = size;
 								dev->dvb_alt_isoc = i;
 							}
 						} else {
+							has_dvb = true;
 							dev->dvb_ep_bulk = e->bEndpointAddress;
 						}
 					}
@@ -3326,6 +3251,12 @@ static int em28xx_usb_probe(struct usb_interface *interface,
 			 * so far. But there might be devices for which this
 			 * logic is not sufficient...
 			 */
+			/*
+			 * NOTE (~): some manufacturers (e.g. Terratec) disable
+			 * endpoints by setting wMaxPacketSize to 0 bytes for
+			 * all alt settings. So far, we've seen this for
+			 * DVB isoc endpoints only.
+			 */
 		}
 	}
 
diff --git a/drivers/media/usb/em28xx/em28xx-core.c b/drivers/media/usb/em28xx/em28xx-core.c
index aaedd11..a802128 100644
--- a/drivers/media/usb/em28xx/em28xx-core.c
+++ b/drivers/media/usb/em28xx/em28xx-core.c
@@ -607,12 +607,12 @@ EXPORT_SYMBOL_GPL(em28xx_audio_setup);
 
 int em28xx_colorlevels_set_default(struct em28xx *dev)
 {
-	em28xx_write_reg(dev, EM28XX_R20_YGAIN, 0x10);	/* contrast */
-	em28xx_write_reg(dev, EM28XX_R21_YOFFSET, 0x00);	/* brightness */
-	em28xx_write_reg(dev, EM28XX_R22_UVGAIN, 0x10);	/* saturation */
-	em28xx_write_reg(dev, EM28XX_R23_UOFFSET, 0x00);
-	em28xx_write_reg(dev, EM28XX_R24_VOFFSET, 0x00);
-	em28xx_write_reg(dev, EM28XX_R25_SHARPNESS, 0x00);
+	em28xx_write_reg(dev, EM28XX_R20_YGAIN, CONTRAST_DEFAULT);
+	em28xx_write_reg(dev, EM28XX_R21_YOFFSET, BRIGHTNESS_DEFAULT);
+	em28xx_write_reg(dev, EM28XX_R22_UVGAIN, SATURATION_DEFAULT);
+	em28xx_write_reg(dev, EM28XX_R23_UOFFSET, BLUE_BALANCE_DEFAULT);
+	em28xx_write_reg(dev, EM28XX_R24_VOFFSET, RED_BALANCE_DEFAULT);
+	em28xx_write_reg(dev, EM28XX_R25_SHARPNESS, SHARPNESS_DEFAULT);
 
 	em28xx_write_reg(dev, EM28XX_R14_GAMMA, 0x20);
 	em28xx_write_reg(dev, EM28XX_R15_RGAIN, 0x20);
@@ -681,6 +681,11 @@ int em28xx_vbi_supported(struct em28xx *dev)
 	if (disable_vbi == 1)
 		return 0;
 
+	if (dev->board.is_webcam)
+		return 0;
+
+	/* FIXME: check subdevices for VBI support */
+
 	if (dev->chip_id == CHIP_ID_EM2860 ||
 	    dev->chip_id == CHIP_ID_EM2883)
 		return 1;
@@ -692,12 +697,23 @@ int em28xx_vbi_supported(struct em28xx *dev)
 int em28xx_set_outfmt(struct em28xx *dev)
 {
 	int ret;
-	u8 vinctrl;
-
-	ret = em28xx_write_reg_bits(dev, EM28XX_R27_OUTFMT,
-				dev->format->reg | 0x20, 0xff);
+	u8 fmt, vinctrl;
+
+	fmt = dev->format->reg;
+	if (!dev->is_em25xx)
+		fmt |= 0x20;
+	/*
+	 * NOTE: it's not clear if this is really needed !
+	 * The datasheets say bit 5 is a reserved bit and devices seem to work
+	 * fine without it. But the Windows driver sets it for em2710/50+em28xx
+	 * devices and we've always been setting it, too.
+	 *
+	 * em2765 (em25xx, em276x/7x/8x) devices do NOT work with this bit set,
+	 * it's likely used for an additional (compressed ?) format there.
+	 */
+	ret = em28xx_write_reg(dev, EM28XX_R27_OUTFMT, fmt);
 	if (ret < 0)
-			return ret;
+		return ret;
 
 	ret = em28xx_write_reg(dev, EM28XX_R10_VINMODE, dev->vinmode);
 	if (ret < 0)
@@ -751,6 +767,13 @@ static void em28xx_capture_area_set(struct em28xx *dev, u8 hstart, u8 vstart,
 	em28xx_write_regs(dev, EM28XX_R1E_CWIDTH, &cwidth, 1);
 	em28xx_write_regs(dev, EM28XX_R1F_CHEIGHT, &cheight, 1);
 	em28xx_write_regs(dev, EM28XX_R1B_OFLOW, &overflow, 1);
+
+	/* FIXME: function/meaning of these registers ? */
+	/* FIXME: align width+height to multiples of 4 ?! */
+	if (dev->is_em25xx) {
+		em28xx_write_reg(dev, 0x34, width >> 4);
+		em28xx_write_reg(dev, 0x35, height >> 4);
+	}
 }
 
 static int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v)
diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c
index a81ec2e..42a6a26 100644
--- a/drivers/media/usb/em28xx/em28xx-dvb.c
+++ b/drivers/media/usb/em28xx/em28xx-dvb.c
@@ -50,6 +50,7 @@
 #include "tda10071.h"
 #include "a8293.h"
 #include "qt1010.h"
+#include "mb86a20s.h"
 
 MODULE_DESCRIPTION("driver for em28xx based DVB cards");
 MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
@@ -220,8 +221,6 @@ static int em28xx_stop_streaming(struct em28xx_dvb *dvb)
 
 	em28xx_stop_urbs(dev);
 
-	em28xx_set_mode(dev, EM28XX_SUSPEND);
-
 	return 0;
 }
 
@@ -465,10 +464,10 @@ static void hauppauge_hvr930c_init(struct em28xx *dev)
 	em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x44);
 	msleep(10);
 
-	dev->i2c_client.addr = 0x82 >> 1;
+	dev->i2c_client[dev->def_i2c_bus].addr = 0x82 >> 1;
 
 	for (i = 0; i < ARRAY_SIZE(regs); i++)
-		i2c_master_send(&dev->i2c_client, regs[i].r, regs[i].len);
+		i2c_master_send(&dev->i2c_client[dev->def_i2c_bus], regs[i].r, regs[i].len);
 	em28xx_gpio_set(dev, hauppauge_hvr930c_end);
 
 	msleep(100);
@@ -522,10 +521,10 @@ static void terratec_h5_init(struct em28xx *dev)
 	em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x45);
 	msleep(10);
 
-	dev->i2c_client.addr = 0x82 >> 1;
+	dev->i2c_client[dev->def_i2c_bus].addr = 0x82 >> 1;
 
 	for (i = 0; i < ARRAY_SIZE(regs); i++)
-		i2c_master_send(&dev->i2c_client, regs[i].r, regs[i].len);
+		i2c_master_send(&dev->i2c_client[dev->def_i2c_bus], regs[i].r, regs[i].len);
 	em28xx_gpio_set(dev, terratec_h5_end);
 };
 
@@ -575,10 +574,10 @@ static void terratec_htc_stick_init(struct em28xx *dev)
 	em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x44);
 	msleep(10);
 
-	dev->i2c_client.addr = 0x82 >> 1;
+	dev->i2c_client[dev->def_i2c_bus].addr = 0x82 >> 1;
 
 	for (i = 0; i < ARRAY_SIZE(regs); i++)
-		i2c_master_send(&dev->i2c_client, regs[i].r, regs[i].len);
+		i2c_master_send(&dev->i2c_client[dev->def_i2c_bus], regs[i].r, regs[i].len);
 
 	em28xx_gpio_set(dev, terratec_htc_stick_end);
 };
@@ -633,10 +632,10 @@ static void terratec_htc_usb_xs_init(struct em28xx *dev)
 	em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x44);
 	msleep(10);
 
-	dev->i2c_client.addr = 0x82 >> 1;
+	dev->i2c_client[dev->def_i2c_bus].addr = 0x82 >> 1;
 
 	for (i = 0; i < ARRAY_SIZE(regs); i++)
-		i2c_master_send(&dev->i2c_client, regs[i].r, regs[i].len);
+		i2c_master_send(&dev->i2c_client[dev->def_i2c_bus], regs[i].r, regs[i].len);
 
 	em28xx_gpio_set(dev, terratec_htc_usb_xs_end);
 };
@@ -662,10 +661,10 @@ static void pctv_520e_init(struct em28xx *dev)
 		{{ 0x01, 0x00, 0x73, 0xaf }, 4},
 	};
 
-	dev->i2c_client.addr = 0x82 >> 1; /* 0x41 */
+	dev->i2c_client[dev->def_i2c_bus].addr = 0x82 >> 1; /* 0x41 */
 
 	for (i = 0; i < ARRAY_SIZE(regs); i++)
-		i2c_master_send(&dev->i2c_client, regs[i].r, regs[i].len);
+		i2c_master_send(&dev->i2c_client[dev->def_i2c_bus], regs[i].r, regs[i].len);
 };
 
 static int em28xx_pctv_290e_set_lna(struct dvb_frontend *fe)
@@ -768,9 +767,25 @@ static struct zl10353_config em28xx_zl10353_no_i2c_gate_dev = {
 };
 static struct qt1010_config em28xx_qt1010_config = {
 	.i2c_address = 0x62
+};
+
+static const struct mb86a20s_config c3tech_duo_mb86a20s_config = {
+	.demod_address = 0x10,
+	.is_serial = true,
+};
+
+static struct tda18271_std_map mb86a20s_tda18271_config = {
+	.dvbt_6   = { .if_freq = 4000, .agc_mode = 3, .std = 4,
+		      .if_lvl = 1, .rfagc_top = 0x37, },
+};
 
+static struct tda18271_config c3tech_duo_tda18271_config = {
+	.std_map = &mb86a20s_tda18271_config,
+	.gate    = TDA18271_GATE_DIGITAL,
+	.small_i2c = TDA18271_03_BYTE_CHUNK_INIT,
 };
 
+
 /* ------------------------------------------------------------------ */
 
 static int em28xx_attach_xc3028(u8 addr, struct em28xx *dev)
@@ -779,7 +794,7 @@ static int em28xx_attach_xc3028(u8 addr, struct em28xx *dev)
 	struct xc2028_config cfg;
 
 	memset(&cfg, 0, sizeof(cfg));
-	cfg.i2c_adap  = &dev->i2c_adap;
+	cfg.i2c_adap  = &dev->i2c_adap[dev->def_i2c_bus];
 	cfg.i2c_addr  = addr;
 
 	if (!dev->dvb->fe[0]) {
@@ -962,7 +977,7 @@ static int em28xx_dvb_init(struct em28xx *dev)
 	switch (dev->model) {
 	case EM2874_BOARD_LEADERSHIP_ISDBT:
 		dvb->fe[0] = dvb_attach(s921_attach,
-				&sharp_isdbt, &dev->i2c_adap);
+				&sharp_isdbt, &dev->i2c_adap[dev->def_i2c_bus]);
 
 		if (!dvb->fe[0]) {
 			result = -EINVAL;
@@ -976,7 +991,7 @@ static int em28xx_dvb_init(struct em28xx *dev)
 	case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600:
 		dvb->fe[0] = dvb_attach(lgdt330x_attach,
 					   &em2880_lgdt3303_dev,
-					   &dev->i2c_adap);
+					   &dev->i2c_adap[dev->def_i2c_bus]);
 		if (em28xx_attach_xc3028(0x61, dev) < 0) {
 			result = -EINVAL;
 			goto out_free;
@@ -985,7 +1000,7 @@ static int em28xx_dvb_init(struct em28xx *dev)
 	case EM2880_BOARD_KWORLD_DVB_310U:
 		dvb->fe[0] = dvb_attach(zl10353_attach,
 					   &em28xx_zl10353_with_xc3028,
-					   &dev->i2c_adap);
+					   &dev->i2c_adap[dev->def_i2c_bus]);
 		if (em28xx_attach_xc3028(0x61, dev) < 0) {
 			result = -EINVAL;
 			goto out_free;
@@ -996,7 +1011,7 @@ static int em28xx_dvb_init(struct em28xx *dev)
 	case EM2880_BOARD_EMPIRE_DUAL_TV:
 		dvb->fe[0] = dvb_attach(zl10353_attach,
 					   &em28xx_zl10353_xc3028_no_i2c_gate,
-					   &dev->i2c_adap);
+					   &dev->i2c_adap[dev->def_i2c_bus]);
 		if (em28xx_attach_xc3028(0x61, dev) < 0) {
 			result = -EINVAL;
 			goto out_free;
@@ -1009,13 +1024,13 @@ static int em28xx_dvb_init(struct em28xx *dev)
 	case EM2882_BOARD_KWORLD_VS_DVBT:
 		dvb->fe[0] = dvb_attach(zl10353_attach,
 					   &em28xx_zl10353_xc3028_no_i2c_gate,
-					   &dev->i2c_adap);
+					   &dev->i2c_adap[dev->def_i2c_bus]);
 		if (dvb->fe[0] == NULL) {
 			/* This board could have either a zl10353 or a mt352.
 			   If the chip id isn't for zl10353, try mt352 */
 			dvb->fe[0] = dvb_attach(mt352_attach,
 						   &terratec_xs_mt352_cfg,
-						   &dev->i2c_adap);
+						   &dev->i2c_adap[dev->def_i2c_bus]);
 		}
 
 		if (em28xx_attach_xc3028(0x61, dev) < 0) {
@@ -1026,16 +1041,16 @@ static int em28xx_dvb_init(struct em28xx *dev)
 	case EM2870_BOARD_KWORLD_355U:
 		dvb->fe[0] = dvb_attach(zl10353_attach,
 					   &em28xx_zl10353_no_i2c_gate_dev,
-					   &dev->i2c_adap);
+					   &dev->i2c_adap[dev->def_i2c_bus]);
 		if (dvb->fe[0] != NULL)
 			dvb_attach(qt1010_attach, dvb->fe[0],
-				   &dev->i2c_adap, &em28xx_qt1010_config);
+				   &dev->i2c_adap[dev->def_i2c_bus], &em28xx_qt1010_config);
 		break;
 	case EM2883_BOARD_KWORLD_HYBRID_330U:
 	case EM2882_BOARD_EVGA_INDTUBE:
 		dvb->fe[0] = dvb_attach(s5h1409_attach,
 					   &em28xx_s5h1409_with_xc3028,
-					   &dev->i2c_adap);
+					   &dev->i2c_adap[dev->def_i2c_bus]);
 		if (em28xx_attach_xc3028(0x61, dev) < 0) {
 			result = -EINVAL;
 			goto out_free;
@@ -1044,10 +1059,10 @@ static int em28xx_dvb_init(struct em28xx *dev)
 	case EM2882_BOARD_KWORLD_ATSC_315U:
 		dvb->fe[0] = dvb_attach(lgdt330x_attach,
 					   &em2880_lgdt3303_dev,
-					   &dev->i2c_adap);
+					   &dev->i2c_adap[dev->def_i2c_bus]);
 		if (dvb->fe[0] != NULL) {
 			if (!dvb_attach(simple_tuner_attach, dvb->fe[0],
-				&dev->i2c_adap, 0x61, TUNER_THOMSON_DTT761X)) {
+				&dev->i2c_adap[dev->def_i2c_bus], 0x61, TUNER_THOMSON_DTT761X)) {
 				result = -EINVAL;
 				goto out_free;
 			}
@@ -1056,7 +1071,7 @@ static int em28xx_dvb_init(struct em28xx *dev)
 	case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2:
 	case EM2882_BOARD_PINNACLE_HYBRID_PRO_330E:
 		dvb->fe[0] = dvb_attach(drxd_attach, &em28xx_drxd, NULL,
-					   &dev->i2c_adap, &dev->udev->dev);
+					   &dev->i2c_adap[dev->def_i2c_bus], &dev->udev->dev);
 		if (em28xx_attach_xc3028(0x61, dev) < 0) {
 			result = -EINVAL;
 			goto out_free;
@@ -1066,10 +1081,10 @@ static int em28xx_dvb_init(struct em28xx *dev)
 		/* Philips CU1216L NIM (Philips TDA10023 + Infineon TUA6034) */
 		dvb->fe[0] = dvb_attach(tda10023_attach,
 			&em28xx_tda10023_config,
-			&dev->i2c_adap, 0x48);
+			&dev->i2c_adap[dev->def_i2c_bus], 0x48);
 		if (dvb->fe[0]) {
 			if (!dvb_attach(simple_tuner_attach, dvb->fe[0],
-				&dev->i2c_adap, 0x60, TUNER_PHILIPS_CU1216L)) {
+				&dev->i2c_adap[dev->def_i2c_bus], 0x60, TUNER_PHILIPS_CU1216L)) {
 				result = -EINVAL;
 				goto out_free;
 			}
@@ -1078,10 +1093,10 @@ static int em28xx_dvb_init(struct em28xx *dev)
 	case EM2870_BOARD_KWORLD_A340:
 		dvb->fe[0] = dvb_attach(lgdt3305_attach,
 					   &em2870_lgdt3304_dev,
-					   &dev->i2c_adap);
+					   &dev->i2c_adap[dev->def_i2c_bus]);
 		if (dvb->fe[0] != NULL)
 			dvb_attach(tda18271_attach, dvb->fe[0], 0x60,
-				   &dev->i2c_adap, &kworld_a340_config);
+				   &dev->i2c_adap[dev->def_i2c_bus], &kworld_a340_config);
 		break;
 	case EM28174_BOARD_PCTV_290E:
 		/* set default GPIO0 for LNA, used if GPIOLIB is undefined */
@@ -1089,14 +1104,14 @@ static int em28xx_dvb_init(struct em28xx *dev)
 				CXD2820R_GPIO_L;
 		dvb->fe[0] = dvb_attach(cxd2820r_attach,
 					&em28xx_cxd2820r_config,
-					&dev->i2c_adap,
+					&dev->i2c_adap[dev->def_i2c_bus],
 					&dvb->lna_gpio);
 		if (dvb->fe[0]) {
 			/* FE 0 attach tuner */
 			if (!dvb_attach(tda18271_attach,
 					dvb->fe[0],
 					0x60,
-					&dev->i2c_adap,
+					&dev->i2c_adap[dev->def_i2c_bus],
 					&em28xx_cxd2820r_tda18271_config)) {
 
 				dvb_frontend_detach(dvb->fe[0]);
@@ -1126,7 +1141,7 @@ static int em28xx_dvb_init(struct em28xx *dev)
 		hauppauge_hvr930c_init(dev);
 
 		dvb->fe[0] = dvb_attach(drxk_attach,
-					&hauppauge_930c_drxk, &dev->i2c_adap);
+					&hauppauge_930c_drxk, &dev->i2c_adap[dev->def_i2c_bus]);
 		if (!dvb->fe[0]) {
 			result = -EINVAL;
 			goto out_free;
@@ -1144,7 +1159,7 @@ static int em28xx_dvb_init(struct em28xx *dev)
 
 		if (dvb->fe[0]->ops.i2c_gate_ctrl)
 			dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 1);
-		if (!dvb_attach(xc5000_attach, dvb->fe[0], &dev->i2c_adap,
+		if (!dvb_attach(xc5000_attach, dvb->fe[0], &dev->i2c_adap[dev->def_i2c_bus],
 				&cfg)) {
 			result = -EINVAL;
 			goto out_free;
@@ -1157,7 +1172,7 @@ static int em28xx_dvb_init(struct em28xx *dev)
 	case EM2884_BOARD_TERRATEC_H5:
 		terratec_h5_init(dev);
 
-		dvb->fe[0] = dvb_attach(drxk_attach, &terratec_h5_drxk, &dev->i2c_adap);
+		dvb->fe[0] = dvb_attach(drxk_attach, &terratec_h5_drxk, &dev->i2c_adap[dev->def_i2c_bus]);
 		if (!dvb->fe[0]) {
 			result = -EINVAL;
 			goto out_free;
@@ -1171,7 +1186,7 @@ static int em28xx_dvb_init(struct em28xx *dev)
 		/* Attach tda18271 to DVB-C frontend */
 		if (dvb->fe[0]->ops.i2c_gate_ctrl)
 			dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 1);
-		if (!dvb_attach(tda18271c2dd_attach, dvb->fe[0], &dev->i2c_adap, 0x60)) {
+		if (!dvb_attach(tda18271c2dd_attach, dvb->fe[0], &dev->i2c_adap[dev->def_i2c_bus], 0x60)) {
 			result = -EINVAL;
 			goto out_free;
 		}
@@ -1179,20 +1194,29 @@ static int em28xx_dvb_init(struct em28xx *dev)
 			dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 0);
 
 		break;
+	case EM2884_BOARD_C3TECH_DIGITAL_DUO:
+		dvb->fe[0] = dvb_attach(mb86a20s_attach,
+					   &c3tech_duo_mb86a20s_config,
+					   &dev->i2c_adap[dev->def_i2c_bus]);
+		if (dvb->fe[0] != NULL)
+			dvb_attach(tda18271_attach, dvb->fe[0], 0x60,
+				   &dev->i2c_adap[dev->def_i2c_bus],
+				   &c3tech_duo_tda18271_config);
+		break;
 	case EM28174_BOARD_PCTV_460E:
 		/* attach demod */
 		dvb->fe[0] = dvb_attach(tda10071_attach,
-			&em28xx_tda10071_config, &dev->i2c_adap);
+			&em28xx_tda10071_config, &dev->i2c_adap[dev->def_i2c_bus]);
 
 		/* attach SEC */
 		if (dvb->fe[0])
-			dvb_attach(a8293_attach, dvb->fe[0], &dev->i2c_adap,
+			dvb_attach(a8293_attach, dvb->fe[0], &dev->i2c_adap[dev->def_i2c_bus],
 				&em28xx_a8293_config);
 		break;
 	case EM2874_BOARD_MAXMEDIA_UB425_TC:
 		/* attach demodulator */
 		dvb->fe[0] = dvb_attach(drxk_attach, &maxmedia_ub425_tc_drxk,
-				&dev->i2c_adap);
+				&dev->i2c_adap[dev->def_i2c_bus]);
 
 		if (dvb->fe[0]) {
 			/* disable I2C-gate */
@@ -1200,7 +1224,7 @@ static int em28xx_dvb_init(struct em28xx *dev)
 
 			/* attach tuner */
 			if (!dvb_attach(tda18271c2dd_attach, dvb->fe[0],
-					&dev->i2c_adap, 0x60)) {
+					&dev->i2c_adap[dev->def_i2c_bus], 0x60)) {
 				dvb_frontend_detach(dvb->fe[0]);
 				result = -EINVAL;
 				goto out_free;
@@ -1218,12 +1242,12 @@ static int em28xx_dvb_init(struct em28xx *dev)
 
 		/* attach demodulator */
 		dvb->fe[0] = dvb_attach(drxk_attach, &pctv_520e_drxk,
-				&dev->i2c_adap);
+				&dev->i2c_adap[dev->def_i2c_bus]);
 
 		if (dvb->fe[0]) {
 			/* attach tuner */
 			if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60,
-					&dev->i2c_adap,
+					&dev->i2c_adap[dev->def_i2c_bus],
 					&em28xx_cxd2820r_tda18271_config)) {
 				dvb_frontend_detach(dvb->fe[0]);
 				result = -EINVAL;
@@ -1236,7 +1260,7 @@ static int em28xx_dvb_init(struct em28xx *dev)
 
 		/* attach demodulator */
 		dvb->fe[0] = dvb_attach(drxk_attach, &terratec_htc_stick_drxk,
-					&dev->i2c_adap);
+					&dev->i2c_adap[dev->def_i2c_bus]);
 		if (!dvb->fe[0]) {
 			result = -EINVAL;
 			goto out_free;
@@ -1244,7 +1268,7 @@ static int em28xx_dvb_init(struct em28xx *dev)
 
 		/* Attach the demodulator. */
 		if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60,
-				&dev->i2c_adap,
+				&dev->i2c_adap[dev->def_i2c_bus],
 				&em28xx_cxd2820r_tda18271_config)) {
 			result = -EINVAL;
 			goto out_free;
@@ -1255,7 +1279,7 @@ static int em28xx_dvb_init(struct em28xx *dev)
 
 		/* attach demodulator */
 		dvb->fe[0] = dvb_attach(drxk_attach, &terratec_htc_stick_drxk,
-					&dev->i2c_adap);
+					&dev->i2c_adap[dev->def_i2c_bus]);
 		if (!dvb->fe[0]) {
 			result = -EINVAL;
 			goto out_free;
@@ -1263,7 +1287,7 @@ static int em28xx_dvb_init(struct em28xx *dev)
 
 		/* Attach the demodulator. */
 		if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60,
-				&dev->i2c_adap,
+				&dev->i2c_adap[dev->def_i2c_bus],
 				&em28xx_cxd2820r_tda18271_config)) {
 			result = -EINVAL;
 			goto out_free;
diff --git a/drivers/media/usb/em28xx/em28xx-i2c.c b/drivers/media/usb/em28xx/em28xx-i2c.c
index 8532c1d..4851cc2 100644
--- a/drivers/media/usb/em28xx/em28xx-i2c.c
+++ b/drivers/media/usb/em28xx/em28xx-i2c.c
@@ -5,6 +5,7 @@
 		      Markus Rechberger <mrechberger@gmail.com>
 		      Mauro Carvalho Chehab <mchehab@infradead.org>
 		      Sascha Sommer <saschasommer@freenet.de>
+   Copyright (C) 2013 Frank Schäfer <fschaefer.oss@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
@@ -41,14 +42,6 @@ static unsigned int i2c_debug;
 module_param(i2c_debug, int, 0644);
 MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
 
-#define dprintk2(lvl, fmt, args...)			\
-do {							\
-	if (i2c_debug >= lvl) {				\
-		printk(KERN_DEBUG "%s at %s: " fmt,	\
-		       dev->name, __func__ , ##args);	\
-      } 						\
-} while (0)
-
 /*
  * em2800_i2c_send_bytes()
  * send up to 4 bytes to the em2800 i2c device
@@ -76,8 +69,8 @@ static int em2800_i2c_send_bytes(struct em28xx *dev, u8 addr, u8 *buf, u16 len)
 	/* trigger write */
 	ret = dev->em28xx_write_regs(dev, 4 - len, &b2[4 - len], 2 + len);
 	if (ret != 2 + len) {
-		em28xx_warn("failed to trigger write to i2c address 0x%x "
-			    "(error=%i)\n", addr, ret);
+		em28xx_warn("failed to trigger write to i2c address 0x%x (error=%i)\n",
+			    addr, ret);
 		return (ret < 0) ? ret : -EIO;
 	}
 	/* wait for completion */
@@ -89,8 +82,8 @@ static int em2800_i2c_send_bytes(struct em28xx *dev, u8 addr, u8 *buf, u16 len)
 		} else if (ret == 0x94 + len - 1) {
 			return -ENODEV;
 		} else if (ret < 0) {
-			em28xx_warn("failed to get i2c transfer status from "
-				    "bridge register (error=%i)\n", ret);
+			em28xx_warn("failed to get i2c transfer status from bridge register (error=%i)\n",
+				    ret);
 			return ret;
 		}
 		msleep(5);
@@ -118,8 +111,8 @@ static int em2800_i2c_recv_bytes(struct em28xx *dev, u8 addr, u8 *buf, u16 len)
 	buf2[0] = addr;
 	ret = dev->em28xx_write_regs(dev, 0x04, buf2, 2);
 	if (ret != 2) {
-		em28xx_warn("failed to trigger read from i2c address 0x%x "
-			    "(error=%i)\n", addr, ret);
+		em28xx_warn("failed to trigger read from i2c address 0x%x (error=%i)\n",
+			    addr, ret);
 		return (ret < 0) ? ret : -EIO;
 	}
 
@@ -132,8 +125,8 @@ static int em2800_i2c_recv_bytes(struct em28xx *dev, u8 addr, u8 *buf, u16 len)
 		} else if (ret == 0x94 + len - 1) {
 			return -ENODEV;
 		} else if (ret < 0) {
-			em28xx_warn("failed to get i2c transfer status from "
-				    "bridge register (error=%i)\n", ret);
+			em28xx_warn("failed to get i2c transfer status from bridge register (error=%i)\n",
+				    ret);
 			return ret;
 		}
 		msleep(5);
@@ -144,9 +137,8 @@ static int em2800_i2c_recv_bytes(struct em28xx *dev, u8 addr, u8 *buf, u16 len)
 	/* get the received message */
 	ret = dev->em28xx_read_reg_req_len(dev, 0x00, 4-len, buf2, len);
 	if (ret != len) {
-		em28xx_warn("reading from i2c device at 0x%x failed: "
-			    "couldn't get the received message from the bridge "
-			    "(error=%i)\n", addr, ret);
+		em28xx_warn("reading from i2c device at 0x%x failed: couldn't get the received message from the bridge (error=%i)\n",
+			    addr, ret);
 		return (ret < 0) ? ret : -EIO;
 	}
 	for (i = 0; i < len; i++)
@@ -180,19 +172,20 @@ static int em28xx_i2c_send_bytes(struct em28xx *dev, u16 addr, u8 *buf,
 
 	if (len < 1 || len > 64)
 		return -EOPNOTSUPP;
-	/* NOTE: limited by the USB ctrl message constraints
-	 * Zero length reads always succeed, even if no device is connected */
+	/*
+	 * NOTE: limited by the USB ctrl message constraints
+	 * Zero length reads always succeed, even if no device is connected
+	 */
 
 	/* Write to i2c device */
 	ret = dev->em28xx_write_regs_req(dev, stop ? 2 : 3, addr, buf, len);
 	if (ret != len) {
 		if (ret < 0) {
-			em28xx_warn("writing to i2c device at 0x%x failed "
-				    "(error=%i)\n", addr, ret);
+			em28xx_warn("writing to i2c device at 0x%x failed (error=%i)\n",
+				    addr, ret);
 			return ret;
 		} else {
-			em28xx_warn("%i bytes write to i2c device at 0x%x "
-				    "requested, but %i bytes written\n",
+			em28xx_warn("%i bytes write to i2c device at 0x%x requested, but %i bytes written\n",
 				    len, addr, ret);
 			return -EIO;
 		}
@@ -207,14 +200,16 @@ static int em28xx_i2c_send_bytes(struct em28xx *dev, u16 addr, u8 *buf,
 		} else if (ret == 0x10) {
 			return -ENODEV;
 		} else if (ret < 0) {
-			em28xx_warn("failed to read i2c transfer status from "
-				    "bridge (error=%i)\n", ret);
+			em28xx_warn("failed to read i2c transfer status from bridge (error=%i)\n",
+				    ret);
 			return ret;
 		}
 		msleep(5);
-		/* NOTE: do we really have to wait for success ?
-		   Never seen anything else than 0x00 or 0x10
-		   (even with high payload) ...			*/
+		/*
+		 * NOTE: do we really have to wait for success ?
+		 * Never seen anything else than 0x00 or 0x10
+		 * (even with high payload) ...
+		 */
 	}
 	em28xx_warn("write to i2c device at 0x%x timed out\n", addr);
 	return -EIO;
@@ -230,29 +225,32 @@ static int em28xx_i2c_recv_bytes(struct em28xx *dev, u16 addr, u8 *buf, u16 len)
 
 	if (len < 1 || len > 64)
 		return -EOPNOTSUPP;
-	/* NOTE: limited by the USB ctrl message constraints
-	 * Zero length reads always succeed, even if no device is connected */
+	/*
+	 * NOTE: limited by the USB ctrl message constraints
+	 * Zero length reads always succeed, even if no device is connected
+	 */
 
 	/* Read data from i2c device */
 	ret = dev->em28xx_read_reg_req_len(dev, 2, addr, buf, len);
-	if (ret != len) {
-		if (ret < 0) {
-			em28xx_warn("reading from i2c device at 0x%x failed "
-				    "(error=%i)\n", addr, ret);
-			return ret;
-		} else {
-			em28xx_warn("%i bytes requested from i2c device at "
-				    "0x%x, but %i bytes received\n",
-				    len, addr, ret);
-			return -EIO;
-		}
+	if (ret < 0) {
+		em28xx_warn("reading from i2c device at 0x%x failed (error=%i)\n",
+			    addr, ret);
+		return ret;
 	}
+	/*
+	 * NOTE: some devices with two i2c busses have the bad habit to return 0
+	 * bytes if we are on bus B AND there was no write attempt to the
+	 * specified slave address before AND no device is present at the
+	 * requested slave address.
+	 * Anyway, the next check will fail with -ENODEV in this case, so avoid
+	 * spamming the system log on device probing and do nothing here.
+	 */
 
 	/* Check success of the i2c operation */
 	ret = dev->em28xx_read_reg(dev, 0x05);
 	if (ret < 0) {
-		em28xx_warn("failed to read i2c transfer status from "
-			    "bridge (error=%i)\n", ret);
+		em28xx_warn("failed to read i2c transfer status from bridge (error=%i)\n",
+			    ret);
 		return ret;
 	}
 	if (ret > 0) {
@@ -282,77 +280,254 @@ static int em28xx_i2c_check_for_device(struct em28xx *dev, u16 addr)
 }
 
 /*
+ * em25xx_bus_B_send_bytes
+ * write bytes to the i2c device
+ */
+static int em25xx_bus_B_send_bytes(struct em28xx *dev, u16 addr, u8 *buf,
+				   u16 len)
+{
+	int ret;
+
+	if (len < 1 || len > 64)
+		return -EOPNOTSUPP;
+	/*
+	 * NOTE: limited by the USB ctrl message constraints
+	 * Zero length reads always succeed, even if no device is connected
+	 */
+
+	/* Set register and write value */
+	ret = dev->em28xx_write_regs_req(dev, 0x06, addr, buf, len);
+	if (ret != len) {
+		if (ret < 0) {
+			em28xx_warn("writing to i2c device at 0x%x failed (error=%i)\n",
+				    addr, ret);
+			return ret;
+		} else {
+			em28xx_warn("%i bytes write to i2c device at 0x%x requested, but %i bytes written\n",
+				    len, addr, ret);
+			return -EIO;
+		}
+	}
+	/* Check success */
+	ret = dev->em28xx_read_reg_req(dev, 0x08, 0x0000);
+	/*
+	 * NOTE: the only error we've seen so far is
+	 * 0x01 when the slave device is not present
+	 */
+	if (!ret)
+		return len;
+	else if (ret > 0)
+		return -ENODEV;
+
+	return ret;
+	/*
+	 * NOTE: With chip types (other chip IDs) which actually don't support
+	 * this operation, it seems to succeed ALWAYS ! (even if there is no
+	 * slave device or even no second i2c bus provided)
+	 */
+}
+
+/*
+ * em25xx_bus_B_recv_bytes
+ * read bytes from the i2c device
+ */
+static int em25xx_bus_B_recv_bytes(struct em28xx *dev, u16 addr, u8 *buf,
+				   u16 len)
+{
+	int ret;
+
+	if (len < 1 || len > 64)
+		return -EOPNOTSUPP;
+	/*
+	 * NOTE: limited by the USB ctrl message constraints
+	 * Zero length reads always succeed, even if no device is connected
+	 */
+
+	/* Read value */
+	ret = dev->em28xx_read_reg_req_len(dev, 0x06, addr, buf, len);
+	if (ret < 0) {
+		em28xx_warn("reading from i2c device at 0x%x failed (error=%i)\n",
+			    addr, ret);
+		return ret;
+	}
+	/*
+	 * NOTE: some devices with two i2c busses have the bad habit to return 0
+	 * bytes if we are on bus B AND there was no write attempt to the
+	 * specified slave address before AND no device is present at the
+	 * requested slave address.
+	 * Anyway, the next check will fail with -ENODEV in this case, so avoid
+	 * spamming the system log on device probing and do nothing here.
+	 */
+
+	/* Check success */
+	ret = dev->em28xx_read_reg_req(dev, 0x08, 0x0000);
+	/*
+	 * NOTE: the only error we've seen so far is
+	 * 0x01 when the slave device is not present
+	 */
+	if (!ret)
+		return len;
+	else if (ret > 0)
+		return -ENODEV;
+
+	return ret;
+	/*
+	 * NOTE: With chip types (other chip IDs) which actually don't support
+	 * this operation, it seems to succeed ALWAYS ! (even if there is no
+	 * slave device or even no second i2c bus provided)
+	 */
+}
+
+/*
+ * em25xx_bus_B_check_for_device()
+ * check if there is a i2c device at the supplied address
+ */
+static int em25xx_bus_B_check_for_device(struct em28xx *dev, u16 addr)
+{
+	u8 buf;
+	int ret;
+
+	ret = em25xx_bus_B_recv_bytes(dev, addr, &buf, 1);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+	/*
+	 * NOTE: With chips which do not support this operation,
+	 * it seems to succeed ALWAYS ! (even if no device connected)
+	 */
+}
+
+static inline int i2c_check_for_device(struct em28xx_i2c_bus *i2c_bus, u16 addr)
+{
+	struct em28xx *dev = i2c_bus->dev;
+	int rc = -EOPNOTSUPP;
+
+	if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM28XX)
+		rc = em28xx_i2c_check_for_device(dev, addr);
+	else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM2800)
+		rc = em2800_i2c_check_for_device(dev, addr);
+	else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM25XX_BUS_B)
+		rc = em25xx_bus_B_check_for_device(dev, addr);
+	if (rc == -ENODEV) {
+		if (i2c_debug)
+			printk(" no device\n");
+	}
+	return rc;
+}
+
+static inline int i2c_recv_bytes(struct em28xx_i2c_bus *i2c_bus,
+				 struct i2c_msg msg)
+{
+	struct em28xx *dev = i2c_bus->dev;
+	u16 addr = msg.addr << 1;
+	int byte, rc = -EOPNOTSUPP;
+
+	if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM28XX)
+		rc = em28xx_i2c_recv_bytes(dev, addr, msg.buf, msg.len);
+	else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM2800)
+		rc = em2800_i2c_recv_bytes(dev, addr, msg.buf, msg.len);
+	else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM25XX_BUS_B)
+		rc = em25xx_bus_B_recv_bytes(dev, addr, msg.buf, msg.len);
+	if (i2c_debug) {
+		for (byte = 0; byte < msg.len; byte++)
+			printk(" %02x", msg.buf[byte]);
+	}
+	return rc;
+}
+
+static inline int i2c_send_bytes(struct em28xx_i2c_bus *i2c_bus,
+				 struct i2c_msg msg, int stop)
+{
+	struct em28xx *dev = i2c_bus->dev;
+	u16 addr = msg.addr << 1;
+	int byte, rc = -EOPNOTSUPP;
+
+	if (i2c_debug) {
+		for (byte = 0; byte < msg.len; byte++)
+			printk(" %02x", msg.buf[byte]);
+	}
+	if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM28XX)
+		rc = em28xx_i2c_send_bytes(dev, addr, msg.buf, msg.len, stop);
+	else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM2800)
+		rc = em2800_i2c_send_bytes(dev, addr, msg.buf, msg.len);
+	else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM25XX_BUS_B)
+		rc = em25xx_bus_B_send_bytes(dev, addr, msg.buf, msg.len);
+	return rc;
+}
+
+/*
  * em28xx_i2c_xfer()
  * the main i2c transfer function
  */
 static int em28xx_i2c_xfer(struct i2c_adapter *i2c_adap,
 			   struct i2c_msg msgs[], int num)
 {
-	struct em28xx *dev = i2c_adap->algo_data;
-	int addr, rc, i, byte;
+	struct em28xx_i2c_bus *i2c_bus = i2c_adap->algo_data;
+	struct em28xx *dev = i2c_bus->dev;
+	unsigned bus = i2c_bus->bus;
+	int addr, rc, i;
+	u8 reg;
+
+	rc = rt_mutex_trylock(&dev->i2c_bus_lock);
+	if (rc < 0)
+		return rc;
+
+	/* Switch I2C bus if needed */
+	if (bus != dev->cur_i2c_bus &&
+	    i2c_bus->algo_type == EM28XX_I2C_ALGO_EM28XX) {
+		if (bus == 1)
+			reg = EM2874_I2C_SECONDARY_BUS_SELECT;
+		else
+			reg = 0;
+		em28xx_write_reg_bits(dev, EM28XX_R06_I2C_CLK, reg,
+				      EM2874_I2C_SECONDARY_BUS_SELECT);
+		dev->cur_i2c_bus = bus;
+	}
 
-	if (num <= 0)
+	if (num <= 0) {
+		rt_mutex_unlock(&dev->i2c_bus_lock);
 		return 0;
+	}
 	for (i = 0; i < num; i++) {
 		addr = msgs[i].addr << 1;
-		dprintk2(2, "%s %s addr=%x len=%d:",
-			 (msgs[i].flags & I2C_M_RD) ? "read" : "write",
-			 i == num - 1 ? "stop" : "nonstop", addr, msgs[i].len);
+		if (i2c_debug)
+			printk(KERN_DEBUG "%s at %s: %s %s addr=%02x len=%d:",
+			       dev->name, __func__ ,
+			       (msgs[i].flags & I2C_M_RD) ? "read" : "write",
+			       i == num - 1 ? "stop" : "nonstop",
+			       addr, msgs[i].len);
 		if (!msgs[i].len) { /* no len: check only for device presence */
-			if (dev->board.is_em2800)
-				rc = em2800_i2c_check_for_device(dev, addr);
-			else
-				rc = em28xx_i2c_check_for_device(dev, addr);
+			rc = i2c_check_for_device(i2c_bus, addr);
 			if (rc == -ENODEV) {
-				if (i2c_debug >= 2)
-					printk(" no device\n");
+				rt_mutex_unlock(&dev->i2c_bus_lock);
 				return rc;
 			}
 		} else if (msgs[i].flags & I2C_M_RD) {
 			/* read bytes */
-			if (dev->board.is_em2800)
-				rc = em2800_i2c_recv_bytes(dev, addr,
-							   msgs[i].buf,
-							   msgs[i].len);
-			else
-				rc = em28xx_i2c_recv_bytes(dev, addr,
-							   msgs[i].buf,
-							   msgs[i].len);
-			if (i2c_debug >= 2) {
-				for (byte = 0; byte < msgs[i].len; byte++)
-					printk(" %02x", msgs[i].buf[byte]);
-			}
+			rc = i2c_recv_bytes(i2c_bus, msgs[i]);
 		} else {
 			/* write bytes */
-			if (i2c_debug >= 2) {
-				for (byte = 0; byte < msgs[i].len; byte++)
-					printk(" %02x", msgs[i].buf[byte]);
-			}
-			if (dev->board.is_em2800)
-				rc = em2800_i2c_send_bytes(dev, addr,
-							   msgs[i].buf,
-							   msgs[i].len);
-			else
-				rc = em28xx_i2c_send_bytes(dev, addr,
-							   msgs[i].buf,
-							   msgs[i].len,
-							   i == num - 1);
+			rc = i2c_send_bytes(i2c_bus, msgs[i], i == num - 1);
 		}
 		if (rc < 0) {
-			if (i2c_debug >= 2)
+			if (i2c_debug)
 				printk(" ERROR: %i\n", rc);
+			rt_mutex_unlock(&dev->i2c_bus_lock);
 			return rc;
 		}
-		if (i2c_debug >= 2)
+		if (i2c_debug)
 			printk("\n");
 	}
 
+	rt_mutex_unlock(&dev->i2c_bus_lock);
 	return num;
 }
 
-/* based on linux/sunrpc/svcauth.h and linux/hash.h
+/*
+ * based on linux/sunrpc/svcauth.h and linux/hash.h
  * The original hash function returns a different value, if arch is x86_64
- *  or i386.
+ * or i386.
  */
 static inline unsigned long em28xx_hash_mem(char *buf, int length, int bits)
 {
@@ -375,127 +550,230 @@ static inline unsigned long em28xx_hash_mem(char *buf, int length, int bits)
 	return (hash >> (32 - bits)) & 0xffffffffUL;
 }
 
-static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len)
+/*
+ * Helper function to read data blocks from i2c clients with 8 or 16 bit
+ * address width, 8 bit register width and auto incrementation been activated
+ */
+static int em28xx_i2c_read_block(struct em28xx *dev, unsigned bus, u16 addr,
+				 bool addr_w16, u16 len, u8 *data)
 {
-	unsigned char buf, *p = eedata;
-	struct em28xx_eeprom *em_eeprom = (void *)eedata;
-	int i, err, size = len, block, block_max;
-
-	if (dev->chip_id == CHIP_ID_EM2874 ||
-	    dev->chip_id == CHIP_ID_EM28174 ||
-	    dev->chip_id == CHIP_ID_EM2884) {
-		/* Empia switched to a 16-bit addressable eeprom in newer
-		   devices.  While we could certainly write a routine to read
-		   the eeprom, there is nothing of use in there that cannot be
-		   accessed through registers, and there is the risk that we
-		   could corrupt the eeprom (since a 16-bit read call is
-		   interpreted as a write call by 8-bit eeproms).
-		*/
-		return 0;
+	int remain = len, rsize, rsize_max, ret;
+	u8 buf[2];
+
+	/* Sanity check */
+	if (addr + remain > (addr_w16 * 0xff00 + 0xff + 1))
+		return -EINVAL;
+	/* Select address */
+	buf[0] = addr >> 8;
+	buf[1] = addr & 0xff;
+	ret = i2c_master_send(&dev->i2c_client[bus], buf + !addr_w16, 1 + addr_w16);
+	if (ret < 0)
+		return ret;
+	/* Read data */
+	if (dev->board.is_em2800)
+		rsize_max = 4;
+	else
+		rsize_max = 64;
+	while (remain > 0) {
+		if (remain > rsize_max)
+			rsize = rsize_max;
+		else
+			rsize = remain;
+
+		ret = i2c_master_recv(&dev->i2c_client[bus], data, rsize);
+		if (ret < 0)
+			return ret;
+
+		remain -= rsize;
+		data += rsize;
 	}
 
-	dev->i2c_client.addr = 0xa0 >> 1;
+	return len;
+}
+
+static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned bus,
+			     u8 **eedata, u16 *eedata_len)
+{
+	const u16 len = 256;
+	/*
+	 * FIXME common length/size for bytes to read, to display, hash
+	 * calculation and returned device dataset. Simplifies the code a lot,
+	 * but we might have to deal with multiple sizes in the future !
+	 */
+	int i, err;
+	struct em28xx_eeprom *dev_config;
+	u8 buf, *data;
+
+	*eedata = NULL;
+	*eedata_len = 0;
+
+	/* EEPROM is always on i2c bus 0 on all known devices. */
+
+	dev->i2c_client[bus].addr = 0xa0 >> 1;
 
 	/* Check if board has eeprom */
-	err = i2c_master_recv(&dev->i2c_client, &buf, 0);
+	err = i2c_master_recv(&dev->i2c_client[bus], &buf, 0);
 	if (err < 0) {
-		em28xx_errdev("board has no eeprom\n");
-		memset(eedata, 0, len);
+		em28xx_info("board has no eeprom\n");
 		return -ENODEV;
 	}
 
-	buf = 0;
-
-	err = i2c_master_send(&dev->i2c_client, &buf, 1);
-	if (err != 1) {
-		printk(KERN_INFO "%s: Huh, no eeprom present (err=%d)?\n",
-		       dev->name, err);
-		return err;
+	data = kzalloc(len, GFP_KERNEL);
+	if (data == NULL)
+		return -ENOMEM;
+
+	/* Read EEPROM content */
+	err = em28xx_i2c_read_block(dev, bus, 0x0000,
+				    dev->eeprom_addrwidth_16bit,
+				    len, data);
+	if (err != len) {
+		em28xx_errdev("failed to read eeprom (err=%d)\n", err);
+		goto error;
 	}
 
-	if (dev->board.is_em2800)
-		block_max = 4;
-	else
-		block_max = 64;
-
-	while (size > 0) {
-		if (size > block_max)
-			block = block_max;
-		else
-			block = size;
-
-		if (block !=
-		    (err = i2c_master_recv(&dev->i2c_client, p, block))) {
-			printk(KERN_WARNING
-			       "%s: i2c eeprom read error (err=%d)\n",
-			       dev->name, err);
-			return err;
-		}
-		size -= block;
-		p += block;
-	}
+	/* Display eeprom content */
 	for (i = 0; i < len; i++) {
-		if (0 == (i % 16))
-			printk(KERN_INFO "%s: i2c eeprom %02x:", dev->name, i);
-		printk(" %02x", eedata[i]);
+		if (0 == (i % 16)) {
+			if (dev->eeprom_addrwidth_16bit)
+				em28xx_info("i2c eeprom %04x:", i);
+			else
+				em28xx_info("i2c eeprom %02x:", i);
+		}
+		printk(" %02x", data[i]);
 		if (15 == (i % 16))
 			printk("\n");
 	}
+	if (dev->eeprom_addrwidth_16bit)
+		em28xx_info("i2c eeprom %04x: ... (skipped)\n", i);
+
+	if (dev->eeprom_addrwidth_16bit &&
+	    data[0] == 0x26 && data[3] == 0x00) {
+		/* new eeprom format; size 4-64kb */
+		u16 mc_start;
+		u16 hwconf_offset;
+
+		dev->hash = em28xx_hash_mem(data, len, 32);
+		mc_start = (data[1] << 8) + 4;	/* usually 0x0004 */
+
+		em28xx_info("EEPROM ID = %02x %02x %02x %02x, EEPROM hash = 0x%08lx\n",
+			    data[0], data[1], data[2], data[3], dev->hash);
+		em28xx_info("EEPROM info:\n");
+		em28xx_info("\tmicrocode start address = 0x%04x, boot configuration = 0x%02x\n",
+			    mc_start, data[2]);
+		/*
+		 * boot configuration (address 0x0002):
+		 * [0]   microcode download speed: 1 = 400 kHz; 0 = 100 kHz
+		 * [1]   always selects 12 kb RAM
+		 * [2]   USB device speed: 1 = force Full Speed; 0 = auto detect
+		 * [4]   1 = force fast mode and no suspend for device testing
+		 * [5:7] USB PHY tuning registers; determined by device
+		 *       characterization
+		 */
+
+		/*
+		 * Read hardware config dataset offset from address
+		 * (microcode start + 46)
+		 */
+		err = em28xx_i2c_read_block(dev, bus, mc_start + 46, 1, 2,
+					    data);
+		if (err != 2) {
+			em28xx_errdev("failed to read hardware configuration data from eeprom (err=%d)\n",
+				      err);
+			goto error;
+		}
 
-	if (em_eeprom->id == 0x9567eb1a)
-		dev->hash = em28xx_hash_mem(eedata, len, 32);
+		/* Calculate hardware config dataset start address */
+		hwconf_offset = mc_start + data[0] + (data[1] << 8);
+
+		/* Read hardware config dataset */
+		/*
+		 * NOTE: the microcode copy can be multiple pages long, but
+		 * we assume the hardware config dataset is the same as in
+		 * the old eeprom and not longer than 256 bytes.
+		 * tveeprom is currently also limited to 256 bytes.
+		 */
+		err = em28xx_i2c_read_block(dev, bus, hwconf_offset, 1, len,
+					    data);
+		if (err != len) {
+			em28xx_errdev("failed to read hardware configuration data from eeprom (err=%d)\n",
+				      err);
+			goto error;
+		}
 
-	printk(KERN_INFO "%s: EEPROM ID= 0x%08x, EEPROM hash = 0x%08lx\n",
-	       dev->name, em_eeprom->id, dev->hash);
+		/* Verify hardware config dataset */
+		/* NOTE: not all devices provide this type of dataset */
+		if (data[0] != 0x1a || data[1] != 0xeb ||
+		    data[2] != 0x67 || data[3] != 0x95) {
+			em28xx_info("\tno hardware configuration dataset found in eeprom\n");
+			kfree(data);
+			return 0;
+		}
 
-	printk(KERN_INFO "%s: EEPROM info:\n", dev->name);
+		/* TODO: decrypt eeprom data for camera bridges (em25xx, em276x+) */
+
+	} else if (!dev->eeprom_addrwidth_16bit &&
+		   data[0] == 0x1a && data[1] == 0xeb &&
+		   data[2] == 0x67 && data[3] == 0x95) {
+		dev->hash = em28xx_hash_mem(data, len, 32);
+		em28xx_info("EEPROM ID = %02x %02x %02x %02x, EEPROM hash = 0x%08lx\n",
+			    data[0], data[1], data[2], data[3], dev->hash);
+		em28xx_info("EEPROM info:\n");
+	} else {
+		em28xx_info("unknown eeprom format or eeprom corrupted !\n");
+		err = -ENODEV;
+		goto error;
+	}
 
-	switch (em_eeprom->chip_conf >> 4 & 0x3) {
+	*eedata = data;
+	*eedata_len = len;
+	dev_config = (void *)eedata;
+
+	switch (le16_to_cpu(dev_config->chip_conf) >> 4 & 0x3) {
 	case 0:
-		printk(KERN_INFO "%s:\tNo audio on board.\n", dev->name);
+		em28xx_info("\tNo audio on board.\n");
 		break;
 	case 1:
-		printk(KERN_INFO "%s:\tAC97 audio (5 sample rates)\n",
-				 dev->name);
+		em28xx_info("\tAC97 audio (5 sample rates)\n");
 		break;
 	case 2:
-		printk(KERN_INFO "%s:\tI2S audio, sample rate=32k\n",
-				 dev->name);
+		em28xx_info("\tI2S audio, sample rate=32k\n");
 		break;
 	case 3:
-		printk(KERN_INFO "%s:\tI2S audio, 3 sample rates\n",
-				 dev->name);
+		em28xx_info("\tI2S audio, 3 sample rates\n");
 		break;
 	}
 
-	if (em_eeprom->chip_conf & 1 << 3)
-		printk(KERN_INFO "%s:\tUSB Remote wakeup capable\n", dev->name);
+	if (le16_to_cpu(dev_config->chip_conf) & 1 << 3)
+		em28xx_info("\tUSB Remote wakeup capable\n");
 
-	if (em_eeprom->chip_conf & 1 << 2)
-		printk(KERN_INFO "%s:\tUSB Self power capable\n", dev->name);
+	if (le16_to_cpu(dev_config->chip_conf) & 1 << 2)
+		em28xx_info("\tUSB Self power capable\n");
 
-	switch (em_eeprom->chip_conf & 0x3) {
+	switch (le16_to_cpu(dev_config->chip_conf) & 0x3) {
 	case 0:
-		printk(KERN_INFO "%s:\t500mA max power\n", dev->name);
+		em28xx_info("\t500mA max power\n");
 		break;
 	case 1:
-		printk(KERN_INFO "%s:\t400mA max power\n", dev->name);
+		em28xx_info("\t400mA max power\n");
 		break;
 	case 2:
-		printk(KERN_INFO "%s:\t300mA max power\n", dev->name);
+		em28xx_info("\t300mA max power\n");
 		break;
 	case 3:
-		printk(KERN_INFO "%s:\t200mA max power\n", dev->name);
+		em28xx_info("\t200mA max power\n");
 		break;
 	}
-	printk(KERN_INFO "%s:\tTable at 0x%02x, strings=0x%04x, 0x%04x, 0x%04x\n",
-				dev->name,
-				em_eeprom->string_idx_table,
-				em_eeprom->string1,
-				em_eeprom->string2,
-				em_eeprom->string3);
+	em28xx_info("\tTable at offset 0x%02x, strings=0x%04x, 0x%04x, 0x%04x\n",
+		    dev_config->string_idx_table,
+		    le16_to_cpu(dev_config->string1),
+		    le16_to_cpu(dev_config->string2),
+		    le16_to_cpu(dev_config->string3));
 
 	return 0;
+
+error:
+	kfree(data);
+	return err;
 }
 
 /* ----------------------------------------------------------- */
@@ -503,13 +781,20 @@ static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len)
 /*
  * functionality()
  */
-static u32 functionality(struct i2c_adapter *adap)
+static u32 functionality(struct i2c_adapter *i2c_adap)
 {
-	struct em28xx *dev = adap->algo_data;
-	u32 func_flags = I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
-	if (dev->board.is_em2800)
-		func_flags &= ~I2C_FUNC_SMBUS_WRITE_BLOCK_DATA;
-	return func_flags;
+	struct em28xx_i2c_bus *i2c_bus = i2c_adap->algo_data;
+
+	if ((i2c_bus->algo_type == EM28XX_I2C_ALGO_EM28XX) ||
+	    (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM25XX_BUS_B)) {
+		return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+	} else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM2800)  {
+		return (I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL) &
+			~I2C_FUNC_SMBUS_WRITE_BLOCK_DATA;
+	}
+
+	WARN(1, "Unknown i2c bus algorithm.\n");
+	return 0;
 }
 
 static struct i2c_algorithm em28xx_algo = {
@@ -556,7 +841,7 @@ static char *i2c_devs[128] = {
  * do_i2c_scan()
  * check i2c address range for devices
  */
-void em28xx_do_i2c_scan(struct em28xx *dev)
+void em28xx_do_i2c_scan(struct em28xx *dev, unsigned bus)
 {
 	u8 i2c_devicelist[128];
 	unsigned char buf;
@@ -565,55 +850,68 @@ void em28xx_do_i2c_scan(struct em28xx *dev)
 	memset(i2c_devicelist, 0, ARRAY_SIZE(i2c_devicelist));
 
 	for (i = 0; i < ARRAY_SIZE(i2c_devs); i++) {
-		dev->i2c_client.addr = i;
-		rc = i2c_master_recv(&dev->i2c_client, &buf, 0);
+		dev->i2c_client[bus].addr = i;
+		rc = i2c_master_recv(&dev->i2c_client[bus], &buf, 0);
 		if (rc < 0)
 			continue;
 		i2c_devicelist[i] = i;
-		printk(KERN_INFO "%s: found i2c device @ 0x%x [%s]\n",
-		       dev->name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???");
+		em28xx_info("found i2c device @ 0x%x on bus %d [%s]\n",
+			    i << 1, bus, i2c_devs[i] ? i2c_devs[i] : "???");
 	}
 
-	dev->i2c_hash = em28xx_hash_mem(i2c_devicelist,
-					ARRAY_SIZE(i2c_devicelist), 32);
+	if (bus == dev->def_i2c_bus)
+		dev->i2c_hash = em28xx_hash_mem(i2c_devicelist,
+						ARRAY_SIZE(i2c_devicelist), 32);
 }
 
 /*
  * em28xx_i2c_register()
  * register i2c bus
  */
-int em28xx_i2c_register(struct em28xx *dev)
+int em28xx_i2c_register(struct em28xx *dev, unsigned bus,
+			enum em28xx_i2c_algo_type algo_type)
 {
 	int retval;
 
 	BUG_ON(!dev->em28xx_write_regs || !dev->em28xx_read_reg);
 	BUG_ON(!dev->em28xx_write_regs_req || !dev->em28xx_read_reg_req);
-	dev->i2c_adap = em28xx_adap_template;
-	dev->i2c_adap.dev.parent = &dev->udev->dev;
-	strcpy(dev->i2c_adap.name, dev->name);
-	dev->i2c_adap.algo_data = dev;
-	i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev);
 
-	retval = i2c_add_adapter(&dev->i2c_adap);
+	if (bus >= NUM_I2C_BUSES)
+		return -ENODEV;
+
+	dev->i2c_adap[bus] = em28xx_adap_template;
+	dev->i2c_adap[bus].dev.parent = &dev->udev->dev;
+	strcpy(dev->i2c_adap[bus].name, dev->name);
+
+	dev->i2c_bus[bus].bus = bus;
+	dev->i2c_bus[bus].algo_type = algo_type;
+	dev->i2c_bus[bus].dev = dev;
+	dev->i2c_adap[bus].algo_data = &dev->i2c_bus[bus];
+	i2c_set_adapdata(&dev->i2c_adap[bus], &dev->v4l2_dev);
+
+	retval = i2c_add_adapter(&dev->i2c_adap[bus]);
 	if (retval < 0) {
 		em28xx_errdev("%s: i2c_add_adapter failed! retval [%d]\n",
 			__func__, retval);
 		return retval;
 	}
 
-	dev->i2c_client = em28xx_client_template;
-	dev->i2c_client.adapter = &dev->i2c_adap;
+	dev->i2c_client[bus] = em28xx_client_template;
+	dev->i2c_client[bus].adapter = &dev->i2c_adap[bus];
 
-	retval = em28xx_i2c_eeprom(dev, dev->eedata, sizeof(dev->eedata));
-	if ((retval < 0) && (retval != -ENODEV)) {
-		em28xx_errdev("%s: em28xx_i2_eeprom failed! retval [%d]\n",
-			__func__, retval);
+	/* Up to now, all eeproms are at bus 0 */
+	if (!bus) {
+		retval = em28xx_i2c_eeprom(dev, bus, &dev->eedata, &dev->eedata_len);
+		if ((retval < 0) && (retval != -ENODEV)) {
+			em28xx_errdev("%s: em28xx_i2_eeprom failed! retval [%d]\n",
+				__func__, retval);
 
-		return retval;
+			return retval;
+		}
 	}
 
 	if (i2c_scan)
-		em28xx_do_i2c_scan(dev);
+		em28xx_do_i2c_scan(dev, bus);
 
 	return 0;
 }
@@ -622,8 +920,11 @@ int em28xx_i2c_register(struct em28xx *dev)
  * em28xx_i2c_unregister()
  * unregister i2c_bus
  */
-int em28xx_i2c_unregister(struct em28xx *dev)
+int em28xx_i2c_unregister(struct em28xx *dev, unsigned bus)
 {
-	i2c_del_adapter(&dev->i2c_adap);
+	if (bus >= NUM_I2C_BUSES)
+		return -ENODEV;
+
+	i2c_del_adapter(&dev->i2c_adap[bus]);
 	return 0;
 }
diff --git a/drivers/media/usb/em28xx/em28xx-input.c b/drivers/media/usb/em28xx/em28xx-input.c
index 1bef990..466b19d 100644
--- a/drivers/media/usb/em28xx/em28xx-input.c
+++ b/drivers/media/usb/em28xx/em28xx-input.c
@@ -280,11 +280,12 @@ static int em2874_polling_getkey(struct em28xx_IR *ir,
 
 static int em28xx_i2c_ir_handle_key(struct em28xx_IR *ir)
 {
+	struct em28xx *dev = ir->dev;
 	static u32 ir_key;
 	int rc;
 	struct i2c_client client;
 
-	client.adapter = &ir->dev->i2c_adap;
+	client.adapter = &ir->dev->i2c_adap[dev->def_i2c_bus];
 	client.addr = ir->i2c_dev_addr;
 
 	rc = ir->get_key_i2c(&client, &ir_key);
@@ -461,7 +462,7 @@ static int em28xx_probe_i2c_ir(struct em28xx *dev)
 	};
 
 	while (addr_list[i] != I2C_CLIENT_END) {
-		if (i2c_probe_func_quick_read(&dev->i2c_adap, addr_list[i]) == 1)
+		if (i2c_probe_func_quick_read(&dev->i2c_adap[dev->def_i2c_bus], addr_list[i]) == 1)
 			return addr_list[i];
 		i++;
 	}
diff --git a/drivers/media/usb/em28xx/em28xx-reg.h b/drivers/media/usb/em28xx/em28xx-reg.h
index 885089e..622871d 100644
--- a/drivers/media/usb/em28xx/em28xx-reg.h
+++ b/drivers/media/usb/em28xx/em28xx-reg.h
@@ -48,7 +48,7 @@
 #define EM28XX_CHIPCFG2_TS_PACKETSIZE_752	0x03
 
 
-	/* GPIO/GPO registers */
+/* GPIO/GPO registers */
 #define EM2880_R04_GPO	0x04    /* em2880-em2883 only */
 #define EM28XX_R08_GPIO	0x08	/* em2820 or upper */
 
@@ -120,12 +120,23 @@
 #define EM28XX_R1E_CWIDTH	0x1e
 #define EM28XX_R1F_CHEIGHT	0x1f
 
-#define EM28XX_R20_YGAIN	0x20
-#define EM28XX_R21_YOFFSET	0x21
-#define EM28XX_R22_UVGAIN	0x22
-#define EM28XX_R23_UOFFSET	0x23
-#define EM28XX_R24_VOFFSET	0x24
-#define EM28XX_R25_SHARPNESS	0x25
+#define EM28XX_R20_YGAIN	0x20 /* contrast [0:4]   */
+#define   CONTRAST_DEFAULT	0x10
+
+#define EM28XX_R21_YOFFSET	0x21 /* brightness       */	/* signed */
+#define   BRIGHTNESS_DEFAULT	0x00
+
+#define EM28XX_R22_UVGAIN	0x22 /* saturation [0:4] */
+#define   SATURATION_DEFAULT	0x10
+
+#define EM28XX_R23_UOFFSET	0x23 /* blue balance     */	/* signed */
+#define   BLUE_BALANCE_DEFAULT	0x00
+
+#define EM28XX_R24_VOFFSET	0x24 /* red balance      */	/* signed */
+#define   RED_BALANCE_DEFAULT	0x00
+
+#define EM28XX_R25_SHARPNESS	0x25 /* sharpness [0:4]  */
+#define   SHARPNESS_DEFAULT	0x00
 
 #define EM28XX_R26_COMPR	0x26
 #define EM28XX_R27_OUTFMT	0x27
@@ -152,8 +163,17 @@
 #define EM28XX_R31_HSCALEHIGH	0x31
 #define EM28XX_R32_VSCALELOW	0x32
 #define EM28XX_R33_VSCALEHIGH	0x33
+#define   EM28XX_HVSCALE_MAX	0x3fff /* => 20% */
+
 #define EM28XX_R34_VBI_START_H	0x34
 #define EM28XX_R35_VBI_START_V	0x35
+/*
+ * NOTE: the EM276x (and EM25xx, EM277x/8x ?) (camera bridges) use these
+ * registers for a different unknown purpose.
+ *   => register 0x34 is set to capture width / 16
+ *   => register 0x35 is set to capture height / 16
+ */
+
 #define EM28XX_R36_VBI_WIDTH	0x36
 #define EM28XX_R37_VBI_HEIGHT	0x37
 
@@ -206,6 +226,7 @@ enum em28xx_chip_id {
 	CHIP_ID_EM2860 = 34,
 	CHIP_ID_EM2870 = 35,
 	CHIP_ID_EM2883 = 36,
+	CHIP_ID_EM2765 = 54,
 	CHIP_ID_EM2874 = 65,
 	CHIP_ID_EM2884 = 68,
 	CHIP_ID_EM28174 = 113,
diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c
index 32bd7de..ef1959b 100644
--- a/drivers/media/usb/em28xx/em28xx-video.c
+++ b/drivers/media/usb/em28xx/em28xx-video.c
@@ -52,7 +52,7 @@
 
 #define DRIVER_DESC         "Empia em28xx based USB video device driver"
 
-#define EM28XX_VERSION "0.1.3"
+#define EM28XX_VERSION "0.2.0"
 
 #define em28xx_videodbg(fmt, arg...) do {\
 	if (video_debug) \
@@ -76,6 +76,16 @@ MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 MODULE_VERSION(EM28XX_VERSION);
 
+
+#define EM25XX_FRMDATAHDR_BYTE1			0x02
+#define EM25XX_FRMDATAHDR_BYTE2_STILL_IMAGE	0x20
+#define EM25XX_FRMDATAHDR_BYTE2_FRAME_END	0x02
+#define EM25XX_FRMDATAHDR_BYTE2_FRAME_ID	0x01
+#define EM25XX_FRMDATAHDR_BYTE2_MASK	(EM25XX_FRMDATAHDR_BYTE2_STILL_IMAGE | \
+					 EM25XX_FRMDATAHDR_BYTE2_FRAME_END |   \
+					 EM25XX_FRMDATAHDR_BYTE2_FRAME_ID)
+
+
 static unsigned int video_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = -1U };
 static unsigned int vbi_nr[]   = {[0 ... (EM28XX_MAXBOARDS - 1)] = -1U };
 static unsigned int radio_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = -1U };
@@ -408,6 +418,62 @@ static inline void process_frame_data_em28xx(struct em28xx *dev,
 		em28xx_copy_video(dev, buf, data_pkt, data_len);
 }
 
+/*
+ * Process data packet according to the em25xx/em276x/7x/8x frame data format
+ */
+static inline void process_frame_data_em25xx(struct em28xx *dev,
+					     unsigned char *data_pkt,
+					     unsigned int  data_len)
+{
+	struct em28xx_buffer    *buf = dev->usb_ctl.vid_buf;
+	struct em28xx_dmaqueue  *dmaq = &dev->vidq;
+	bool frame_end = 0;
+
+	/* Check for header */
+	/* NOTE: at least with bulk transfers, only the first packet
+	 * has a header and has always set the FRAME_END bit         */
+	if (data_len >= 2) {	/* em25xx header is only 2 bytes long */
+		if ((data_pkt[0] == EM25XX_FRMDATAHDR_BYTE1) &&
+		    ((data_pkt[1] & ~EM25XX_FRMDATAHDR_BYTE2_MASK) == 0x00)) {
+			dev->top_field = !(data_pkt[1] &
+					   EM25XX_FRMDATAHDR_BYTE2_FRAME_ID);
+			frame_end = data_pkt[1] &
+				    EM25XX_FRMDATAHDR_BYTE2_FRAME_END;
+			data_pkt += 2;
+			data_len -= 2;
+		}
+
+		/* Finish field and prepare next (BULK only) */
+		if (dev->analog_xfer_bulk && frame_end) {
+			buf = finish_field_prepare_next(dev, buf, dmaq);
+			dev->usb_ctl.vid_buf = buf;
+		}
+		/* NOTE: in ISOC mode when a new frame starts and buf==NULL,
+		 * we COULD already prepare a buffer here to avoid skipping the
+		 * first frame.
+		 */
+	}
+
+	/* Copy data */
+	if (buf != NULL && data_len > 0)
+		em28xx_copy_video(dev, buf, data_pkt, data_len);
+
+	/* Finish frame (ISOC only) => avoids lag of 1 frame */
+	if (!dev->analog_xfer_bulk && frame_end) {
+		buf = finish_field_prepare_next(dev, buf, dmaq);
+		dev->usb_ctl.vid_buf = buf;
+	}
+
+	/* NOTE: Tested with USB bulk transfers only !
+	 * The wording in the datasheet suggests that isoc might work different.
+	 * The current code assumes that with isoc transfers each packet has a
+	 * header like with the other em28xx devices.
+	 */
+	/* NOTE: Support for interlaced mode is pure theory. It has not been
+	 * tested and it is unknown if these devices actually support it. */
+	/* NOTE: No VBI support yet (these chips likely do not support VBI). */
+}
+
 /* Processes and copies the URB data content (video and VBI data) */
 static inline int em28xx_urb_data_copy(struct em28xx *dev, struct urb *urb)
 {
@@ -460,7 +526,13 @@ static inline int em28xx_urb_data_copy(struct em28xx *dev, struct urb *urb)
 			continue;
 		}
 
-		process_frame_data_em28xx(dev, usb_data_pkt, usb_data_len);
+		if (dev->is_em25xx)
+			process_frame_data_em25xx(dev,
+						  usb_data_pkt, usb_data_len);
+		else
+			process_frame_data_em28xx(dev,
+						  usb_data_pkt, usb_data_len);
+
 	}
 	return 1;
 }
@@ -700,6 +772,7 @@ int em28xx_vb2_setup(struct em28xx *dev)
 	q = &dev->vb_vidq;
 	q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 	q->io_modes = VB2_READ | VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
+	q->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
 	q->drv_priv = dev;
 	q->buf_struct_size = sizeof(struct em28xx_buffer);
 	q->ops = &em28xx_video_qops;
@@ -713,6 +786,7 @@ int em28xx_vb2_setup(struct em28xx *dev)
 	q = &dev->vb_vbiq;
 	q->type = V4L2_BUF_TYPE_VBI_CAPTURE;
 	q->io_modes = VB2_READ | VB2_MMAP | VB2_USERPTR;
+	q->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
 	q->drv_priv = dev;
 	q->buf_struct_size = sizeof(struct em28xx_buffer);
 	q->ops = &em28xx_vbi_qops;
@@ -782,33 +856,45 @@ void em28xx_ctrl_notify(struct v4l2_ctrl *ctrl, void *priv)
 static int em28xx_s_ctrl(struct v4l2_ctrl *ctrl)
 {
 	struct em28xx *dev = container_of(ctrl->handler, struct em28xx, ctrl_handler);
+	int ret = -EINVAL;
 
 	switch (ctrl->id) {
 	case V4L2_CID_AUDIO_MUTE:
 		dev->mute = ctrl->val;
+		ret = em28xx_audio_analog_set(dev);
 		break;
 	case V4L2_CID_AUDIO_VOLUME:
 		dev->volume = ctrl->val;
+		ret = em28xx_audio_analog_set(dev);
+		break;
+	case V4L2_CID_CONTRAST:
+		ret = em28xx_write_reg(dev, EM28XX_R20_YGAIN, ctrl->val);
+		break;
+	case V4L2_CID_BRIGHTNESS:
+		ret = em28xx_write_reg(dev, EM28XX_R21_YOFFSET, ctrl->val);
+		break;
+	case V4L2_CID_SATURATION:
+		ret = em28xx_write_reg(dev, EM28XX_R22_UVGAIN, ctrl->val);
+		break;
+	case V4L2_CID_BLUE_BALANCE:
+		ret = em28xx_write_reg(dev, EM28XX_R23_UOFFSET, ctrl->val);
+		break;
+	case V4L2_CID_RED_BALANCE:
+		ret = em28xx_write_reg(dev, EM28XX_R24_VOFFSET, ctrl->val);
+		break;
+	case V4L2_CID_SHARPNESS:
+		ret = em28xx_write_reg(dev, EM28XX_R25_SHARPNESS, ctrl->val);
 		break;
 	}
 
-	return em28xx_audio_analog_set(dev);
+	return (ret < 0) ? ret : 0;
 }
 
 const struct v4l2_ctrl_ops em28xx_ctrl_ops = {
 	.s_ctrl = em28xx_s_ctrl,
 };
 
-static int check_dev(struct em28xx *dev)
-{
-	if (dev->disconnected) {
-		em28xx_errdev("v4l2 ioctl: device not present\n");
-		return -ENODEV;
-	}
-	return 0;
-}
-
-static void get_scale(struct em28xx *dev,
+static void size_to_scale(struct em28xx *dev,
 			unsigned int width, unsigned int height,
 			unsigned int *hscale, unsigned int *vscale)
 {
@@ -816,12 +902,23 @@ static void get_scale(struct em28xx *dev,
 	unsigned int          maxh = norm_maxh(dev);
 
 	*hscale = (((unsigned long)maxw) << 12) / width - 4096L;
-	if (*hscale >= 0x4000)
-		*hscale = 0x3fff;
+	if (*hscale > EM28XX_HVSCALE_MAX)
+		*hscale = EM28XX_HVSCALE_MAX;
 
 	*vscale = (((unsigned long)maxh) << 12) / height - 4096L;
-	if (*vscale >= 0x4000)
-		*vscale = 0x3fff;
+	if (*vscale > EM28XX_HVSCALE_MAX)
+		*vscale = EM28XX_HVSCALE_MAX;
+}
+
+static void scale_to_size(struct em28xx *dev,
+			  unsigned int hscale, unsigned int vscale,
+			  unsigned int *width, unsigned int *height)
+{
+	unsigned int          maxw = norm_maxw(dev);
+	unsigned int          maxh = norm_maxh(dev);
+
+	*width = (((unsigned long)maxw) << 12) / (hscale + 4096L);
+	*height = (((unsigned long)maxh) << 12) / (vscale + 4096L);
 }
 
 /* ------------------------------------------------------------------
@@ -898,10 +995,8 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
 				      1, 0);
 	}
 
-	get_scale(dev, width, height, &hscale, &vscale);
-
-	width = (((unsigned long)maxw) << 12) / (hscale + 4096L);
-	height = (((unsigned long)maxh) << 12) / (vscale + 4096L);
+	size_to_scale(dev, width, height, &hscale, &vscale);
+	scale_to_size(dev, hscale, hscale, &width, &height);
 
 	f->fmt.pix.width = width;
 	f->fmt.pix.height = height;
@@ -932,7 +1027,7 @@ static int em28xx_set_video_format(struct em28xx *dev, unsigned int fourcc,
 	dev->height = height;
 
 	/* set new image size */
-	get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale);
+	size_to_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale);
 
 	em28xx_resolution_set(dev);
 
@@ -957,13 +1052,6 @@ static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm)
 {
 	struct em28xx_fh   *fh  = priv;
 	struct em28xx      *dev = fh->dev;
-	int                rc;
-
-	if (dev->board.is_webcam)
-		return -ENOTTY;
-	rc = check_dev(dev);
-	if (rc < 0)
-		return rc;
 
 	*norm = dev->norm;
 
@@ -974,48 +1062,35 @@ static int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *norm)
 {
 	struct em28xx_fh   *fh  = priv;
 	struct em28xx      *dev = fh->dev;
-	int                rc;
-
-	if (dev->board.is_webcam)
-		return -ENOTTY;
-	rc = check_dev(dev);
-	if (rc < 0)
-		return rc;
 
 	v4l2_device_call_all(&dev->v4l2_dev, 0, video, querystd, norm);
 
 	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)
 {
 	struct em28xx_fh   *fh  = priv;
 	struct em28xx      *dev = fh->dev;
 	struct v4l2_format f;
-	int                rc;
 
-	if (dev->board.is_webcam)
-		return -ENOTTY;
-	if (*norm == dev->norm)
+	if (norm == dev->norm)
 		return 0;
-	rc = check_dev(dev);
-	if (rc < 0)
-		return rc;
 
 	if (dev->streaming_users > 0)
 		return -EBUSY;
 
-	dev->norm = *norm;
+	dev->norm = norm;
 
 	/* Adjusts width/height, if needed */
 	f.fmt.pix.width = 720;
-	f.fmt.pix.height = (*norm & V4L2_STD_525_60) ? 480 : 576;
+	f.fmt.pix.height = (norm & V4L2_STD_525_60) ? 480 : 576;
 	vidioc_try_fmt_vid_cap(file, priv, &f);
 
 	/* set new image size */
 	dev->width = f.fmt.pix.width;
 	dev->height = f.fmt.pix.height;
-	get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale);
+	size_to_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale);
 
 	em28xx_resolution_set(dev);
 	v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, dev->norm);
@@ -1030,9 +1105,6 @@ static int vidioc_g_parm(struct file *file, void *priv,
 	struct em28xx      *dev = fh->dev;
 	int rc = 0;
 
-	if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		return -EINVAL;
-
 	p->parm.capture.readbuffers = EM28XX_MIN_BUF;
 	if (dev->board.is_webcam)
 		rc = v4l2_device_call_until_err(&dev->v4l2_dev, 0,
@@ -1050,12 +1122,6 @@ static int vidioc_s_parm(struct file *file, void *priv,
 	struct em28xx_fh   *fh  = priv;
 	struct em28xx      *dev = fh->dev;
 
-	if (!dev->board.is_webcam)
-		return -ENOTTY;
-
-	if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		return -EINVAL;
-
 	p->parm.capture.readbuffers = EM28XX_MIN_BUF;
 	return v4l2_device_call_until_err(&dev->v4l2_dev, 0, video, s_parm, p);
 }
@@ -1116,11 +1182,6 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
 {
 	struct em28xx_fh   *fh  = priv;
 	struct em28xx      *dev = fh->dev;
-	int                rc;
-
-	rc = check_dev(dev);
-	if (rc < 0)
-		return rc;
 
 	if (i >= MAX_EM28XX_INPUT)
 		return -EINVAL;
@@ -1136,9 +1197,6 @@ static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
 	struct em28xx_fh   *fh    = priv;
 	struct em28xx      *dev   = fh->dev;
 
-	if (!dev->audio_mode.has_audio)
-		return -EINVAL;
-
 	switch (a->index) {
 	case EM28XX_AMUX_VIDEO:
 		strcpy(a->name, "Television");
@@ -1179,10 +1237,6 @@ static int vidioc_s_audio(struct file *file, void *priv, const struct v4l2_audio
 	struct em28xx_fh   *fh  = priv;
 	struct em28xx      *dev = fh->dev;
 
-
-	if (!dev->audio_mode.has_audio)
-		return -EINVAL;
-
 	if (a->index >= MAX_EM28XX_INPUT)
 		return -EINVAL;
 	if (0 == INPUT(a->index)->type)
@@ -1202,11 +1256,6 @@ static int vidioc_g_tuner(struct file *file, void *priv,
 {
 	struct em28xx_fh      *fh  = priv;
 	struct em28xx         *dev = fh->dev;
-	int                   rc;
-
-	rc = check_dev(dev);
-	if (rc < 0)
-		return rc;
 
 	if (0 != t->index)
 		return -EINVAL;
@@ -1218,15 +1267,10 @@ static int vidioc_g_tuner(struct file *file, void *priv,
 }
 
 static int vidioc_s_tuner(struct file *file, void *priv,
-				struct v4l2_tuner *t)
+				const struct v4l2_tuner *t)
 {
 	struct em28xx_fh      *fh  = priv;
 	struct em28xx         *dev = fh->dev;
-	int                   rc;
-
-	rc = check_dev(dev);
-	if (rc < 0)
-		return rc;
 
 	if (0 != t->index)
 		return -EINVAL;
@@ -1249,39 +1293,22 @@ static int vidioc_g_frequency(struct file *file, void *priv,
 }
 
 static int vidioc_s_frequency(struct file *file, void *priv,
-				struct v4l2_frequency *f)
+				const struct v4l2_frequency *f)
 {
+	struct v4l2_frequency new_freq = *f;
 	struct em28xx_fh      *fh  = priv;
 	struct em28xx         *dev = fh->dev;
-	int                   rc;
-
-	rc = check_dev(dev);
-	if (rc < 0)
-		return rc;
 
 	if (0 != f->tuner)
 		return -EINVAL;
 
 	v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, f);
-	v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_frequency, f);
-	dev->ctl_freq = f->frequency;
+	v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_frequency, &new_freq);
+	dev->ctl_freq = new_freq.frequency;
 
 	return 0;
 }
 
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-static int em28xx_reg_len(int reg)
-{
-	switch (reg) {
-	case EM28XX_R40_AC97LSB:
-	case EM28XX_R30_HSCALELOW:
-	case EM28XX_R32_VSCALELOW:
-		return 2;
-	default:
-		return 1;
-	}
-}
-
 static int vidioc_g_chip_ident(struct file *file, void *priv,
 	       struct v4l2_dbg_chip_ident *chip)
 {
@@ -1290,9 +1317,9 @@ static int vidioc_g_chip_ident(struct file *file, void *priv,
 
 	chip->ident = V4L2_IDENT_NONE;
 	chip->revision = 0;
-	if (chip->match.type == V4L2_CHIP_MATCH_HOST) {
-		if (v4l2_chip_match_host(&chip->match))
-			chip->ident = V4L2_IDENT_NONE;
+	if (chip->match.type == V4L2_CHIP_MATCH_BRIDGE) {
+		if (chip->match.addr > 1)
+			return -EINVAL;
 		return 0;
 	}
 	if (chip->match.type != V4L2_CHIP_MATCH_I2C_DRIVER &&
@@ -1304,6 +1331,33 @@ static int vidioc_g_chip_ident(struct file *file, void *priv,
 	return 0;
 }
 
+static int vidioc_g_chip_name(struct file *file, void *priv,
+	       struct v4l2_dbg_chip_name *chip)
+{
+	struct em28xx_fh      *fh  = priv;
+	struct em28xx         *dev = fh->dev;
+
+	if (chip->match.addr > 1)
+		return -EINVAL;
+	if (chip->match.addr == 1)
+		strlcpy(chip->name, "ac97", sizeof(chip->name));
+	else
+		strlcpy(chip->name, dev->v4l2_dev.name, sizeof(chip->name));
+	return 0;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int em28xx_reg_len(int reg)
+{
+	switch (reg) {
+	case EM28XX_R40_AC97LSB:
+	case EM28XX_R30_HSCALELOW:
+	case EM28XX_R32_VSCALELOW:
+		return 2;
+	default:
+		return 1;
+	}
+}
 
 static int vidioc_g_register(struct file *file, void *priv,
 			     struct v4l2_dbg_register *reg)
@@ -1313,6 +1367,12 @@ static int vidioc_g_register(struct file *file, void *priv,
 	int ret;
 
 	switch (reg->match.type) {
+	case V4L2_CHIP_MATCH_BRIDGE:
+		if (reg->match.addr > 1)
+			return -EINVAL;
+		if (!reg->match.addr)
+			break;
+		/* fall-through */
 	case V4L2_CHIP_MATCH_AC97:
 		ret = em28xx_read_ac97(dev, reg->reg);
 		if (ret < 0)
@@ -1329,8 +1389,7 @@ static int vidioc_g_register(struct file *file, void *priv,
 		v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg);
 		return 0;
 	default:
-		if (!v4l2_chip_match_host(&reg->match))
-			return -EINVAL;
+		return -EINVAL;
 	}
 
 	/* Match host */
@@ -1356,13 +1415,19 @@ static int vidioc_g_register(struct file *file, void *priv,
 }
 
 static int vidioc_s_register(struct file *file, void *priv,
-			     struct v4l2_dbg_register *reg)
+			     const struct v4l2_dbg_register *reg)
 {
 	struct em28xx_fh      *fh  = priv;
 	struct em28xx         *dev = fh->dev;
 	__le16 buf;
 
 	switch (reg->match.type) {
+	case V4L2_CHIP_MATCH_BRIDGE:
+		if (reg->match.addr > 1)
+			return -EINVAL;
+		if (!reg->match.addr)
+			break;
+		/* fall-through */
 	case V4L2_CHIP_MATCH_AC97:
 		return em28xx_write_ac97(dev, reg->reg, reg->val);
 	case V4L2_CHIP_MATCH_I2C_DRIVER:
@@ -1373,8 +1438,7 @@ static int vidioc_s_register(struct file *file, void *priv,
 		v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg);
 		return 0;
 	default:
-		if (!v4l2_chip_match_host(&reg->match))
-			return -EINVAL;
+		return -EINVAL;
 	}
 
 	/* Match host */
@@ -1386,26 +1450,6 @@ static int vidioc_s_register(struct file *file, void *priv,
 #endif
 
 
-static int vidioc_cropcap(struct file *file, void *priv,
-					struct v4l2_cropcap *cc)
-{
-	struct em28xx_fh      *fh  = priv;
-	struct em28xx         *dev = fh->dev;
-
-	if (cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		return -EINVAL;
-
-	cc->bounds.left = 0;
-	cc->bounds.top = 0;
-	cc->bounds.width = dev->width;
-	cc->bounds.height = dev->height;
-	cc->defrect = cc->bounds;
-	cc->pixelaspect.numerator = 54;	/* 4:3 FIXME: remove magic numbers */
-	cc->pixelaspect.denominator = 59;
-
-	return 0;
-}
-
 static int vidioc_querycap(struct file *file, void  *priv,
 					struct v4l2_capability *cap)
 {
@@ -1482,8 +1526,12 @@ static int vidioc_enum_framesizes(struct file *file, void *priv,
 
 	/* Report a continuous range */
 	fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
-	fsize->stepwise.min_width = 48;
-	fsize->stepwise.min_height = 32;
+	scale_to_size(dev, EM28XX_HVSCALE_MAX, EM28XX_HVSCALE_MAX,
+		      &fsize->stepwise.min_width, &fsize->stepwise.min_height);
+	if (fsize->stepwise.min_width < 48)
+		fsize->stepwise.min_width = 48;
+	if (fsize->stepwise.min_height < 38)
+		fsize->stepwise.min_height = 38;
 	fsize->stepwise.max_width = maxw;
 	fsize->stepwise.max_height = maxh;
 	fsize->stepwise.step_width = 1;
@@ -1522,35 +1570,6 @@ static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv,
 	return 0;
 }
 
-static int vidioc_s_fmt_vbi_cap(struct file *file, void *priv,
-				struct v4l2_format *format)
-{
-	struct em28xx_fh      *fh  = priv;
-	struct em28xx         *dev = fh->dev;
-
-	format->fmt.vbi.samples_per_line = dev->vbi_width;
-	format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
-	format->fmt.vbi.offset = 0;
-	format->fmt.vbi.flags = 0;
-	format->fmt.vbi.sampling_rate = 6750000 * 4 / 2;
-	format->fmt.vbi.count[0] = dev->vbi_height;
-	format->fmt.vbi.count[1] = dev->vbi_height;
-	memset(format->fmt.vbi.reserved, 0, sizeof(format->fmt.vbi.reserved));
-
-	/* Varies by video standard (NTSC, PAL, etc.) */
-	if (dev->norm & V4L2_STD_525_60) {
-		/* NTSC */
-		format->fmt.vbi.start[0] = 10;
-		format->fmt.vbi.start[1] = 273;
-	} else if (dev->norm & V4L2_STD_625_50) {
-		/* PAL */
-		format->fmt.vbi.start[0] = 6;
-		format->fmt.vbi.start[1] = 318;
-	}
-
-	return 0;
-}
-
 /* ----------------------------------------------------------- */
 /* RADIO ESPECIFIC IOCTLS                                      */
 /* ----------------------------------------------------------- */
@@ -1564,7 +1583,6 @@ static int radio_g_tuner(struct file *file, void *priv,
 		return -EINVAL;
 
 	strcpy(t->name, "Radio");
-	t->type = V4L2_TUNER_RADIO;
 
 	v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t);
 
@@ -1572,7 +1590,7 @@ static int radio_g_tuner(struct file *file, void *priv,
 }
 
 static int radio_s_tuner(struct file *file, void *priv,
-			 struct v4l2_tuner *t)
+			 const struct v4l2_tuner *t)
 {
 	struct em28xx *dev = ((struct em28xx_fh *)priv)->dev;
 
@@ -1749,11 +1767,10 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = {
 	.vidioc_s_fmt_vid_cap       = vidioc_s_fmt_vid_cap,
 	.vidioc_g_fmt_vbi_cap       = vidioc_g_fmt_vbi_cap,
 	.vidioc_try_fmt_vbi_cap     = vidioc_g_fmt_vbi_cap,
-	.vidioc_s_fmt_vbi_cap       = vidioc_s_fmt_vbi_cap,
+	.vidioc_s_fmt_vbi_cap       = vidioc_g_fmt_vbi_cap,
 	.vidioc_enum_framesizes     = vidioc_enum_framesizes,
 	.vidioc_g_audio             = vidioc_g_audio,
 	.vidioc_s_audio             = vidioc_s_audio,
-	.vidioc_cropcap             = vidioc_cropcap,
 
 	.vidioc_reqbufs             = vb2_ioctl_reqbufs,
 	.vidioc_create_bufs         = vb2_ioctl_create_bufs,
@@ -1778,10 +1795,11 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = {
 	.vidioc_s_frequency         = vidioc_s_frequency,
 	.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
 	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+	.vidioc_g_chip_ident        = vidioc_g_chip_ident,
+	.vidioc_g_chip_name         = vidioc_g_chip_name,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 	.vidioc_g_register          = vidioc_g_register,
 	.vidioc_s_register          = vidioc_s_register,
-	.vidioc_g_chip_ident        = vidioc_g_chip_ident,
 #endif
 };
 
@@ -1808,6 +1826,8 @@ static const struct v4l2_ioctl_ops radio_ioctl_ops = {
 	.vidioc_s_frequency   = vidioc_s_frequency,
 	.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
 	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+	.vidioc_g_chip_ident  = vidioc_g_chip_ident,
+	.vidioc_g_chip_name   = vidioc_g_chip_name,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 	.vidioc_g_register    = vidioc_g_register,
 	.vidioc_s_register    = vidioc_s_register,
@@ -1887,9 +1907,42 @@ int em28xx_register_analog_devices(struct em28xx *dev)
 			 (EM28XX_XCLK_AUDIO_UNMUTE | val));
 
 	em28xx_set_outfmt(dev);
-	em28xx_colorlevels_set_default(dev);
 	em28xx_compression_disable(dev);
 
+	/* Add image controls */
+	/* NOTE: at this point, the subdevices are already registered, so bridge
+	 * controls are only added/enabled when no subdevice provides them */
+	if (NULL == v4l2_ctrl_find(&dev->ctrl_handler, V4L2_CID_CONTRAST))
+		v4l2_ctrl_new_std(&dev->ctrl_handler, &em28xx_ctrl_ops,
+				  V4L2_CID_CONTRAST,
+				  0, 0x1f, 1, CONTRAST_DEFAULT);
+	if (NULL == v4l2_ctrl_find(&dev->ctrl_handler, V4L2_CID_BRIGHTNESS))
+		v4l2_ctrl_new_std(&dev->ctrl_handler, &em28xx_ctrl_ops,
+				  V4L2_CID_BRIGHTNESS,
+				  -0x80, 0x7f, 1, BRIGHTNESS_DEFAULT);
+	if (NULL == v4l2_ctrl_find(&dev->ctrl_handler, V4L2_CID_SATURATION))
+		v4l2_ctrl_new_std(&dev->ctrl_handler, &em28xx_ctrl_ops,
+				  V4L2_CID_SATURATION,
+				  0, 0x1f, 1, SATURATION_DEFAULT);
+	if (NULL == v4l2_ctrl_find(&dev->ctrl_handler, V4L2_CID_BLUE_BALANCE))
+		v4l2_ctrl_new_std(&dev->ctrl_handler, &em28xx_ctrl_ops,
+				  V4L2_CID_BLUE_BALANCE,
+				  -0x30, 0x30, 1, BLUE_BALANCE_DEFAULT);
+	if (NULL == v4l2_ctrl_find(&dev->ctrl_handler, V4L2_CID_RED_BALANCE))
+		v4l2_ctrl_new_std(&dev->ctrl_handler, &em28xx_ctrl_ops,
+				  V4L2_CID_RED_BALANCE,
+				  -0x30, 0x30, 1, RED_BALANCE_DEFAULT);
+	if (NULL == v4l2_ctrl_find(&dev->ctrl_handler, V4L2_CID_SHARPNESS))
+		v4l2_ctrl_new_std(&dev->ctrl_handler, &em28xx_ctrl_ops,
+				  V4L2_CID_SHARPNESS,
+				  0, 0x0f, 1, SHARPNESS_DEFAULT);
+
+	/* Reset image controls */
+	em28xx_colorlevels_set_default(dev);
+	v4l2_ctrl_handler_setup(&dev->ctrl_handler);
+	if (dev->ctrl_handler.error)
+		return dev->ctrl_handler.error;
+
 	/* allocate and fill video video_device struct */
 	dev->vdev = em28xx_vdev_init(dev, &em28xx_video_template, "video");
 	if (!dev->vdev) {
@@ -1899,6 +1952,25 @@ int em28xx_register_analog_devices(struct em28xx *dev)
 	dev->vdev->queue = &dev->vb_vidq;
 	dev->vdev->queue->lock = &dev->vb_queue_lock;
 
+	/* disable inapplicable ioctls */
+	if (dev->board.is_webcam) {
+		v4l2_disable_ioctl(dev->vdev, VIDIOC_QUERYSTD);
+		v4l2_disable_ioctl(dev->vdev, VIDIOC_G_STD);
+		v4l2_disable_ioctl(dev->vdev, VIDIOC_S_STD);
+	} else {
+		v4l2_disable_ioctl(dev->vdev, VIDIOC_S_PARM);
+	}
+	if (dev->tuner_type == TUNER_ABSENT) {
+		v4l2_disable_ioctl(dev->vdev, VIDIOC_G_TUNER);
+		v4l2_disable_ioctl(dev->vdev, VIDIOC_S_TUNER);
+		v4l2_disable_ioctl(dev->vdev, VIDIOC_G_FREQUENCY);
+		v4l2_disable_ioctl(dev->vdev, VIDIOC_S_FREQUENCY);
+	}
+	if (!dev->audio_mode.has_audio) {
+		v4l2_disable_ioctl(dev->vdev, VIDIOC_G_AUDIO);
+		v4l2_disable_ioctl(dev->vdev, VIDIOC_S_AUDIO);
+	}
+
 	/* register v4l2 video video_device */
 	ret = video_register_device(dev->vdev, VFL_TYPE_GRABBER,
 				       video_nr[dev->devno]);
@@ -1916,6 +1988,19 @@ int em28xx_register_analog_devices(struct em28xx *dev)
 		dev->vbi_dev->queue = &dev->vb_vbiq;
 		dev->vbi_dev->queue->lock = &dev->vb_vbi_queue_lock;
 
+		/* disable inapplicable ioctls */
+		v4l2_disable_ioctl(dev->vdev, VIDIOC_S_PARM);
+		if (dev->tuner_type == TUNER_ABSENT) {
+			v4l2_disable_ioctl(dev->vbi_dev, VIDIOC_G_TUNER);
+			v4l2_disable_ioctl(dev->vbi_dev, VIDIOC_S_TUNER);
+			v4l2_disable_ioctl(dev->vbi_dev, VIDIOC_G_FREQUENCY);
+			v4l2_disable_ioctl(dev->vbi_dev, VIDIOC_S_FREQUENCY);
+		}
+		if (!dev->audio_mode.has_audio) {
+			v4l2_disable_ioctl(dev->vbi_dev, VIDIOC_G_AUDIO);
+			v4l2_disable_ioctl(dev->vbi_dev, VIDIOC_S_AUDIO);
+		}
+
 		/* register v4l2 vbi video_device */
 		ret = video_register_device(dev->vbi_dev, VFL_TYPE_VBI,
 					    vbi_nr[dev->devno]);
diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h
index 5f0b2c5..a9323b6 100644
--- a/drivers/media/usb/em28xx/em28xx.h
+++ b/drivers/media/usb/em28xx/em28xx.h
@@ -42,28 +42,28 @@
 #include "em28xx-reg.h"
 
 /* Boards supported by driver */
-#define EM2800_BOARD_UNKNOWN			0
-#define EM2820_BOARD_UNKNOWN			1
-#define EM2820_BOARD_TERRATEC_CINERGY_250	2
-#define EM2820_BOARD_PINNACLE_USB_2		3
-#define EM2820_BOARD_HAUPPAUGE_WINTV_USB_2      4
-#define EM2820_BOARD_MSI_VOX_USB_2              5
-#define EM2800_BOARD_TERRATEC_CINERGY_200       6
-#define EM2800_BOARD_LEADTEK_WINFAST_USBII      7
-#define EM2800_BOARD_KWORLD_USB2800             8
-#define EM2820_BOARD_PINNACLE_DVC_90		9
-#define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900	10
-#define EM2880_BOARD_TERRATEC_HYBRID_XS		11
-#define EM2820_BOARD_KWORLD_PVRTV2800RF		12
-#define EM2880_BOARD_TERRATEC_PRODIGY_XS	13
-#define EM2820_BOARD_PROLINK_PLAYTV_USB2	14
-#define EM2800_BOARD_VGEAR_POCKETTV             15
-#define EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950	16
-#define EM2880_BOARD_PINNACLE_PCTV_HD_PRO	17
-#define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2	18
-#define EM2860_BOARD_SAA711X_REFERENCE_DESIGN	19
-#define EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600   20
-#define EM2800_BOARD_GRABBEEX_USB2800           21
+#define EM2800_BOARD_UNKNOWN			  0
+#define EM2820_BOARD_UNKNOWN			  1
+#define EM2820_BOARD_TERRATEC_CINERGY_250	  2
+#define EM2820_BOARD_PINNACLE_USB_2		  3
+#define EM2820_BOARD_HAUPPAUGE_WINTV_USB_2	  4
+#define EM2820_BOARD_MSI_VOX_USB_2		  5
+#define EM2800_BOARD_TERRATEC_CINERGY_200	  6
+#define EM2800_BOARD_LEADTEK_WINFAST_USBII	  7
+#define EM2800_BOARD_KWORLD_USB2800		  8
+#define EM2820_BOARD_PINNACLE_DVC_90		  9
+#define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900	  10
+#define EM2880_BOARD_TERRATEC_HYBRID_XS		  11
+#define EM2820_BOARD_KWORLD_PVRTV2800RF		  12
+#define EM2880_BOARD_TERRATEC_PRODIGY_XS	  13
+#define EM2820_BOARD_PROLINK_PLAYTV_USB2	  14
+#define EM2800_BOARD_VGEAR_POCKETTV		  15
+#define EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950	  16
+#define EM2880_BOARD_PINNACLE_PCTV_HD_PRO	  17
+#define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2	  18
+#define EM2860_BOARD_SAA711X_REFERENCE_DESIGN	  19
+#define EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600	  20
+#define EM2800_BOARD_GRABBEEX_USB2800		  21
 #define EM2750_BOARD_UNKNOWN			  22
 #define EM2750_BOARD_DLCW_130			  23
 #define EM2820_BOARD_DLINK_USB_TV		  24
@@ -99,36 +99,37 @@
 #define EM2882_BOARD_KWORLD_VS_DVBT		  54
 #define EM2882_BOARD_TERRATEC_HYBRID_XS		  55
 #define EM2882_BOARD_PINNACLE_HYBRID_PRO_330E	  56
-#define EM2883_BOARD_KWORLD_HYBRID_330U                  57
+#define EM2883_BOARD_KWORLD_HYBRID_330U		  57
 #define EM2820_BOARD_COMPRO_VIDEOMATE_FORYOU	  58
 #define EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850	  60
 #define EM2820_BOARD_PROLINK_PLAYTV_BOX4_USB2	  61
 #define EM2820_BOARD_GADMEI_TVR200		  62
-#define EM2860_BOARD_KAIOMY_TVNPC_U2              63
-#define EM2860_BOARD_EASYCAP                      64
+#define EM2860_BOARD_KAIOMY_TVNPC_U2		  63
+#define EM2860_BOARD_EASYCAP			  64
 #define EM2820_BOARD_IODATA_GVMVP_SZ		  65
 #define EM2880_BOARD_EMPIRE_DUAL_TV		  66
 #define EM2860_BOARD_TERRATEC_GRABBY		  67
 #define EM2860_BOARD_TERRATEC_AV350		  68
 #define EM2882_BOARD_KWORLD_ATSC_315U		  69
 #define EM2882_BOARD_EVGA_INDTUBE		  70
-#define EM2820_BOARD_SILVERCREST_WEBCAM           71
-#define EM2861_BOARD_GADMEI_UTV330PLUS           72
-#define EM2870_BOARD_REDDO_DVB_C_USB_BOX          73
+#define EM2820_BOARD_SILVERCREST_WEBCAM		  71
+#define EM2861_BOARD_GADMEI_UTV330PLUS		  72
+#define EM2870_BOARD_REDDO_DVB_C_USB_BOX	  73
 #define EM2800_BOARD_VC211A			  74
 #define EM2882_BOARD_DIKOM_DK300		  75
 #define EM2870_BOARD_KWORLD_A340		  76
 #define EM2874_BOARD_LEADERSHIP_ISDBT		  77
-#define EM28174_BOARD_PCTV_290E                   78
+#define EM28174_BOARD_PCTV_290E			  78
 #define EM2884_BOARD_TERRATEC_H5		  79
-#define EM28174_BOARD_PCTV_460E                   80
+#define EM28174_BOARD_PCTV_460E			  80
 #define EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C	  81
 #define EM2884_BOARD_CINERGY_HTC_STICK		  82
-#define EM2860_BOARD_HT_VIDBOX_NW03 		  83
-#define EM2874_BOARD_MAXMEDIA_UB425_TC            84
-#define EM2884_BOARD_PCTV_510E                    85
-#define EM2884_BOARD_PCTV_520E                    86
+#define EM2860_BOARD_HT_VIDBOX_NW03		  83
+#define EM2874_BOARD_MAXMEDIA_UB425_TC		  84
+#define EM2884_BOARD_PCTV_510E			  85
+#define EM2884_BOARD_PCTV_520E			  86
 #define EM2884_BOARD_TERRATEC_HTC_USB_XS	  87
+#define EM2884_BOARD_C3TECH_DIGITAL_DUO		  88
 
 /* Limits minimum and default number of buffers */
 #define EM28XX_MIN_BUF 4
@@ -157,6 +158,9 @@
 #define EM28XX_NUM_BUFS 5
 #define EM28XX_DVB_NUM_BUFS 5
 
+/* max number of I2C buses on em28xx devices */
+#define NUM_I2C_BUSES	2
+
 /* isoc transfers: number of packets for each buffer
    windows requests only 64 packets .. so we better do the same
    this is what I found out for all alternate numbers there!
@@ -172,27 +176,6 @@
 
 #define EM28XX_INTERLACED_DEFAULT 1
 
-/*
-#define (use usbview if you want to get the other alternate number infos)
-#define
-#define alternate number 2
-#define 			Endpoint Address: 82
-			Direction: in
-			Attribute: 1
-			Type: Isoc
-			Max Packet Size: 1448
-			Interval: 125us
-
-  alternate number 7
-
-			Endpoint Address: 82
-			Direction: in
-			Attribute: 1
-			Type: Isoc
-			Max Packet Size: 3072
-			Interval: 125us
-*/
-
 /* time in msecs to wait for i2c writes to finish */
 #define EM2800_I2C_XFER_TIMEOUT		20
 
@@ -381,6 +364,7 @@ enum em28xx_sensor {
 	EM28XX_MT9V011,
 	EM28XX_MT9M001,
 	EM28XX_MT9M111,
+	EM28XX_OV2640,
 };
 
 enum em28xx_adecoder {
@@ -393,6 +377,7 @@ struct em28xx_board {
 	int vchannels;
 	int tuner_type;
 	int tuner_addr;
+	unsigned def_i2c_bus;	/* Default I2C bus */
 
 	/* i2c flags */
 	unsigned int tda9887_conf;
@@ -426,15 +411,15 @@ struct em28xx_board {
 };
 
 struct em28xx_eeprom {
-	u32 id;			/* 0x9567eb1a */
-	u16 vendor_ID;
-	u16 product_ID;
+	u8 id[4];			/* 1a eb 67 95 */
+	__le16 vendor_ID;
+	__le16 product_ID;
 
-	u16 chip_conf;
+	__le16 chip_conf;
 
-	u16 board_conf;
+	__le16 board_conf;
 
-	u16 string1, string2, string3;
+	__le16 string1, string2, string3;
 
 	u8 string_idx_table;
 };
@@ -477,6 +462,20 @@ struct em28xx_fh {
 	enum v4l2_buf_type           type;
 };
 
+enum em28xx_i2c_algo_type {
+	EM28XX_I2C_ALGO_EM28XX = 0,
+	EM28XX_I2C_ALGO_EM2800,
+	EM28XX_I2C_ALGO_EM25XX_BUS_B,
+};
+
+struct em28xx_i2c_bus {
+	struct em28xx *dev;
+
+	unsigned bus;
+	enum em28xx_i2c_algo_type algo_type;
+};
+
+
 /* main device struct */
 struct em28xx {
 	/* generic device properties */
@@ -484,6 +483,7 @@ struct em28xx {
 	int model;		/* index in the device_data struct */
 	int devno;		/* marks the number of this device */
 	enum em28xx_chip_id chip_id;
+	unsigned int is_em25xx:1;	/* em25xx/em276x/7x/8x family bridge */
 
 	unsigned char disconnected:1;	/* device has been diconnected */
 
@@ -491,8 +491,6 @@ struct em28xx {
 
 	struct v4l2_device v4l2_dev;
 	struct v4l2_ctrl_handler ctrl_handler;
-	/* provides ac97 mute and volume overrides */
-	struct v4l2_ctrl_handler ac97_ctrl_handler;
 	struct em28xx_board board;
 
 	/* Webcam specific fields */
@@ -511,8 +509,8 @@ struct em28xx {
 	unsigned int is_audio_only:1;
 
 	/* Controls audio streaming */
-	struct work_struct wq_trigger;              /* Trigger to start/stop audio for alsa module */
-	 atomic_t       stream_started;      /* stream should be running if true */
+	struct work_struct wq_trigger;	/* Trigger to start/stop audio for alsa module */
+	atomic_t       stream_started;	/* stream should be running if true */
 
 	struct em28xx_fmt *format;
 
@@ -530,9 +528,17 @@ struct em28xx {
 	int tuner_type;		/* type of the tuner */
 	int tuner_addr;		/* tuner address */
 	int tda9887_conf;
+
 	/* i2c i/o */
-	struct i2c_adapter i2c_adap;
-	struct i2c_client i2c_client;
+	struct i2c_adapter i2c_adap[NUM_I2C_BUSES];
+	struct i2c_client i2c_client[NUM_I2C_BUSES];
+	struct em28xx_i2c_bus i2c_bus[NUM_I2C_BUSES];
+
+	unsigned char eeprom_addrwidth_16bit:1;
+	unsigned def_i2c_bus;	/* Default I2C bus */
+	unsigned cur_i2c_bus;	/* Current I2C bus */
+	struct rt_mutex i2c_bus_lock;
+
 	/* video for linux */
 	int users;		/* user count for exclusive use */
 	int streaming_users;    /* Number of actively streaming users */
@@ -584,7 +590,9 @@ struct em28xx {
 	/* resources in use */
 	unsigned int resources;
 
-	unsigned char eedata[256];
+	/* eeprom content */
+	u8 *eedata;
+	u16 eedata_len;
 
 	/* Isoc control struct */
 	struct em28xx_dmaqueue vidq;
@@ -600,7 +608,7 @@ struct em28xx {
 	u8 analog_ep_isoc;	/* address of isoc endpoint for analog */
 	u8 analog_ep_bulk;	/* address of bulk endpoint for analog */
 	u8 dvb_ep_isoc;		/* address of isoc endpoint for DVB */
-	u8 dvb_ep_bulk;		/* address of bulk endpoint for DVC */
+	u8 dvb_ep_bulk;		/* address of bulk endpoint for DVB */
 	int alt;		/* alternate setting */
 	int max_pkt_size;	/* max packet size of the selected ep at alt */
 	int packet_multiplier;	/* multiplier for wMaxPacketSize, used for
@@ -651,16 +659,12 @@ struct em28xx_ops {
 };
 
 /* Provided by em28xx-i2c.c */
-void em28xx_do_i2c_scan(struct em28xx *dev);
-int  em28xx_i2c_register(struct em28xx *dev);
-int  em28xx_i2c_unregister(struct em28xx *dev);
+void em28xx_do_i2c_scan(struct em28xx *dev, unsigned bus);
+int  em28xx_i2c_register(struct em28xx *dev, unsigned bus,
+			 enum em28xx_i2c_algo_type algo_type);
+int  em28xx_i2c_unregister(struct em28xx *dev, unsigned bus);
 
 /* Provided by em28xx-core.c */
-
-u32 em28xx_request_buffers(struct em28xx *dev, u32 count);
-void em28xx_queue_unusedframes(struct em28xx *dev);
-void em28xx_release_buffers(struct em28xx *dev);
-
 int em28xx_read_reg_req_len(struct em28xx *dev, u8 req, u16 reg,
 			    char *buf, int len);
 int em28xx_read_reg_req(struct em28xx *dev, u8 req, u16 reg);
@@ -693,7 +697,6 @@ int em28xx_init_usb_xfer(struct em28xx *dev, enum em28xx_mode mode,
 					(struct em28xx *dev, struct urb *urb));
 void em28xx_uninit_usb_xfer(struct em28xx *dev, enum em28xx_mode mode);
 void em28xx_stop_urbs(struct em28xx *dev);
-int em28xx_isoc_dvb_max_packetsize(struct em28xx *dev);
 int em28xx_set_mode(struct em28xx *dev, enum em28xx_mode set_mode);
 int em28xx_gpio_set(struct em28xx *dev, struct em28xx_reg_seq *gpio);
 void em28xx_wake_i2c(struct em28xx *dev);
@@ -712,16 +715,18 @@ int em28xx_stop_vbi_streaming(struct vb2_queue *vq);
 extern const struct v4l2_ctrl_ops em28xx_ctrl_ops;
 
 /* Provided by em28xx-cards.c */
-extern int em2800_variant_detect(struct usb_device *udev, int model);
 extern struct em28xx_board em28xx_boards[];
 extern struct usb_device_id em28xx_id_table[];
-extern const unsigned int em28xx_bcount;
 int em28xx_tuner_callback(void *ptr, int component, int command, int arg);
 void em28xx_release_resources(struct em28xx *dev);
 
 /* Provided by em28xx-vbi.c */
 extern struct vb2_ops em28xx_vbi_qops;
 
+/* Provided by em28xx-camera.c */
+int em28xx_detect_sensor(struct em28xx *dev);
+int em28xx_init_camera(struct em28xx *dev);
+
 /* printk macros */
 
 #define em28xx_err(fmt, arg...) do {\
@@ -744,72 +749,6 @@ static inline int em28xx_compression_disable(struct em28xx *dev)
 	return em28xx_write_reg(dev, EM28XX_R26_COMPR, 0x00);
 }
 
-static inline int em28xx_contrast_get(struct em28xx *dev)
-{
-	return em28xx_read_reg(dev, EM28XX_R20_YGAIN) & 0x1f;
-}
-
-static inline int em28xx_brightness_get(struct em28xx *dev)
-{
-	return em28xx_read_reg(dev, EM28XX_R21_YOFFSET);
-}
-
-static inline int em28xx_saturation_get(struct em28xx *dev)
-{
-	return em28xx_read_reg(dev, EM28XX_R22_UVGAIN) & 0x1f;
-}
-
-static inline int em28xx_u_balance_get(struct em28xx *dev)
-{
-	return em28xx_read_reg(dev, EM28XX_R23_UOFFSET);
-}
-
-static inline int em28xx_v_balance_get(struct em28xx *dev)
-{
-	return em28xx_read_reg(dev, EM28XX_R24_VOFFSET);
-}
-
-static inline int em28xx_gamma_get(struct em28xx *dev)
-{
-	return em28xx_read_reg(dev, EM28XX_R14_GAMMA) & 0x3f;
-}
-
-static inline int em28xx_contrast_set(struct em28xx *dev, s32 val)
-{
-	u8 tmp = (u8) val;
-	return em28xx_write_regs(dev, EM28XX_R20_YGAIN, &tmp, 1);
-}
-
-static inline int em28xx_brightness_set(struct em28xx *dev, s32 val)
-{
-	u8 tmp = (u8) val;
-	return em28xx_write_regs(dev, EM28XX_R21_YOFFSET, &tmp, 1);
-}
-
-static inline int em28xx_saturation_set(struct em28xx *dev, s32 val)
-{
-	u8 tmp = (u8) val;
-	return em28xx_write_regs(dev, EM28XX_R22_UVGAIN, &tmp, 1);
-}
-
-static inline int em28xx_u_balance_set(struct em28xx *dev, s32 val)
-{
-	u8 tmp = (u8) val;
-	return em28xx_write_regs(dev, EM28XX_R23_UOFFSET, &tmp, 1);
-}
-
-static inline int em28xx_v_balance_set(struct em28xx *dev, s32 val)
-{
-	u8 tmp = (u8) val;
-	return em28xx_write_regs(dev, EM28XX_R24_VOFFSET, &tmp, 1);
-}
-
-static inline int em28xx_gamma_set(struct em28xx *dev, s32 val)
-{
-	u8 tmp = (u8) val;
-	return em28xx_write_regs(dev, EM28XX_R14_GAMMA, &tmp, 1);
-}
-
 /*FIXME: maxw should be dependent of alt mode */
 static inline unsigned int norm_maxw(struct em28xx *dev)
 {
diff --git a/drivers/media/usb/gspca/autogain_functions.h b/drivers/media/usb/gspca/autogain_functions.h
deleted file mode 100644
index d625eaf..0000000
--- a/drivers/media/usb/gspca/autogain_functions.h
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Functions for auto gain.
- *
- * 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
- */
-
-#ifdef WANT_REGULAR_AUTOGAIN
-/* auto gain and exposure algorithm based on the knee algorithm described here:
-   http://ytse.tricolour.net/docs/LowLightOptimization.html
-
-   Returns 0 if no changes were made, 1 if the gain and or exposure settings
-   where changed. */
-static inline int auto_gain_n_exposure(
-			struct gspca_dev *gspca_dev,
-			int avg_lum,
-			int desired_avg_lum,
-			int deadzone,
-			int gain_knee,
-			int exposure_knee)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-	int i, steps, gain, orig_gain, exposure, orig_exposure;
-	int retval = 0;
-
-	orig_gain = gain = sd->ctrls[GAIN].val;
-	orig_exposure = exposure = sd->ctrls[EXPOSURE].val;
-
-	/* If we are of a multiple of deadzone, do multiple steps to reach the
-	   desired lumination fast (with the risc of a slight overshoot) */
-	steps = abs(desired_avg_lum - avg_lum) / deadzone;
-
-	PDEBUG(D_FRAM, "autogain: lum: %d, desired: %d, steps: %d",
-		avg_lum, desired_avg_lum, steps);
-
-	for (i = 0; i < steps; i++) {
-		if (avg_lum > desired_avg_lum) {
-			if (gain > gain_knee)
-				gain--;
-			else if (exposure > exposure_knee)
-				exposure--;
-			else if (gain > sd->ctrls[GAIN].def)
-				gain--;
-			else if (exposure > sd->ctrls[EXPOSURE].min)
-				exposure--;
-			else if (gain > sd->ctrls[GAIN].min)
-				gain--;
-			else
-				break;
-		} else {
-			if (gain < sd->ctrls[GAIN].def)
-				gain++;
-			else if (exposure < exposure_knee)
-				exposure++;
-			else if (gain < gain_knee)
-				gain++;
-			else if (exposure < sd->ctrls[EXPOSURE].max)
-				exposure++;
-			else if (gain < sd->ctrls[GAIN].max)
-				gain++;
-			else
-				break;
-		}
-	}
-
-	if (gain != orig_gain) {
-		sd->ctrls[GAIN].val = gain;
-		setgain(gspca_dev);
-		retval = 1;
-	}
-	if (exposure != orig_exposure) {
-		sd->ctrls[EXPOSURE].val = exposure;
-		setexposure(gspca_dev);
-		retval = 1;
-	}
-
-	if (retval)
-		PDEBUG(D_FRAM, "autogain: changed gain: %d, expo: %d",
-			gain, exposure);
-	return retval;
-}
-#endif
-
-#ifdef WANT_COARSE_EXPO_AUTOGAIN
-/* Autogain + exposure algorithm for cameras with a coarse exposure control
-   (usually this means we can only control the clockdiv to change exposure)
-   As changing the clockdiv so that the fps drops from 30 to 15 fps for
-   example, will lead to a huge exposure change (it effectively doubles),
-   this algorithm normally tries to only adjust the gain (between 40 and
-   80 %) and if that does not help, only then changes exposure. This leads
-   to a much more stable image then using the knee algorithm which at
-   certain points of the knee graph will only try to adjust exposure,
-   which leads to oscilating as one exposure step is huge.
-
-   Note this assumes that the sd struct for the cam in question has
-   exp_too_low_cnt and exp_too_high_cnt int members for use by this function.
-
-   Returns 0 if no changes were made, 1 if the gain and or exposure settings
-   where changed. */
-static inline int coarse_grained_expo_autogain(
-			struct gspca_dev *gspca_dev,
-			int avg_lum,
-			int desired_avg_lum,
-			int deadzone)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-	int steps, gain, orig_gain, exposure, orig_exposure;
-	int gain_low, gain_high;
-	int retval = 0;
-
-	orig_gain = gain = sd->ctrls[GAIN].val;
-	orig_exposure = exposure = sd->ctrls[EXPOSURE].val;
-
-	gain_low = (sd->ctrls[GAIN].max - sd->ctrls[GAIN].min) / 5 * 2;
-	gain_low += sd->ctrls[GAIN].min;
-	gain_high = (sd->ctrls[GAIN].max - sd->ctrls[GAIN].min) / 5 * 4;
-	gain_high += sd->ctrls[GAIN].min;
-
-	/* If we are of a multiple of deadzone, do multiple steps to reach the
-	   desired lumination fast (with the risc of a slight overshoot) */
-	steps = (desired_avg_lum - avg_lum) / deadzone;
-
-	PDEBUG(D_FRAM, "autogain: lum: %d, desired: %d, steps: %d",
-		avg_lum, desired_avg_lum, steps);
-
-	if ((gain + steps) > gain_high &&
-	    exposure < sd->ctrls[EXPOSURE].max) {
-		gain = gain_high;
-		sd->exp_too_low_cnt++;
-		sd->exp_too_high_cnt = 0;
-	} else if ((gain + steps) < gain_low &&
-		   exposure > sd->ctrls[EXPOSURE].min) {
-		gain = gain_low;
-		sd->exp_too_high_cnt++;
-		sd->exp_too_low_cnt = 0;
-	} else {
-		gain += steps;
-		if (gain > sd->ctrls[GAIN].max)
-			gain = sd->ctrls[GAIN].max;
-		else if (gain < sd->ctrls[GAIN].min)
-			gain = sd->ctrls[GAIN].min;
-		sd->exp_too_high_cnt = 0;
-		sd->exp_too_low_cnt = 0;
-	}
-
-	if (sd->exp_too_high_cnt > 3) {
-		exposure--;
-		sd->exp_too_high_cnt = 0;
-	} else if (sd->exp_too_low_cnt > 3) {
-		exposure++;
-		sd->exp_too_low_cnt = 0;
-	}
-
-	if (gain != orig_gain) {
-		sd->ctrls[GAIN].val = gain;
-		setgain(gspca_dev);
-		retval = 1;
-	}
-	if (exposure != orig_exposure) {
-		sd->ctrls[EXPOSURE].val = exposure;
-		setexposure(gspca_dev);
-		retval = 1;
-	}
-
-	if (retval)
-		PDEBUG(D_FRAM, "autogain: changed gain: %d, expo: %d",
-			gain, exposure);
-	return retval;
-}
-#endif
diff --git a/drivers/media/usb/gspca/benq.c b/drivers/media/usb/gspca/benq.c
index 352f321..05f406d 100644
--- a/drivers/media/usb/gspca/benq.c
+++ b/drivers/media/usb/gspca/benq.c
@@ -186,7 +186,7 @@ static void sd_isoc_irq(struct urb *urb)
 		/* check the packet status and length */
 		if (urb0->iso_frame_desc[i].actual_length != SD_PKT_SZ
 		    || urb->iso_frame_desc[i].actual_length != SD_PKT_SZ) {
-			PDEBUG(D_ERR, "ISOC bad lengths %d / %d",
+			PERR("ISOC bad lengths %d / %d",
 				urb0->iso_frame_desc[i].actual_length,
 				urb->iso_frame_desc[i].actual_length);
 			gspca_dev->last_packet_type = DISCARD_PACKET;
diff --git a/drivers/media/usb/gspca/conex.c b/drivers/media/usb/gspca/conex.c
index c9052f2..38714df 100644
--- a/drivers/media/usb/gspca/conex.c
+++ b/drivers/media/usb/gspca/conex.c
@@ -73,12 +73,11 @@ static void reg_r(struct gspca_dev *gspca_dev,
 {
 	struct usb_device *dev = gspca_dev->dev;
 
-#ifdef GSPCA_DEBUG
 	if (len > USB_BUF_SZ) {
-		pr_err("reg_r: buffer overflow\n");
+		PERR("reg_r: buffer overflow\n");
 		return;
 	}
-#endif
+
 	usb_control_msg(dev,
 			usb_rcvctrlpipe(dev, 0),
 			0,
@@ -113,13 +112,12 @@ static void reg_w(struct gspca_dev *gspca_dev,
 {
 	struct usb_device *dev = gspca_dev->dev;
 
-#ifdef GSPCA_DEBUG
 	if (len > USB_BUF_SZ) {
-		pr_err("reg_w: buffer overflow\n");
+		PERR("reg_w: buffer overflow\n");
 		return;
 	}
 	PDEBUG(D_USBO, "reg write [%02x] = %02x..", index, *buffer);
-#endif
+
 	memcpy(gspca_dev->usb_buf, buffer, len);
 	usb_control_msg(dev,
 			usb_sndctrlpipe(dev, 0),
@@ -689,7 +687,7 @@ static void cx11646_jpeg(struct gspca_dev*gspca_dev)
 		reg_w_val(gspca_dev, 0x0053, 0x00);
 	} while (--retry);
 	if (retry == 0)
-		PDEBUG(D_ERR, "Damned Errors sending jpeg Table");
+		PERR("Damned Errors sending jpeg Table");
 	/* send the qtable now */
 	reg_r(gspca_dev, 0x0001, 1);		/* -> 0x18 */
 	length = 8;
diff --git a/drivers/media/usb/gspca/cpia1.c b/drivers/media/usb/gspca/cpia1.c
index 1dcdd9f..064b530 100644
--- a/drivers/media/usb/gspca/cpia1.c
+++ b/drivers/media/usb/gspca/cpia1.c
@@ -421,8 +421,7 @@ static int cpia_usb_transferCmd(struct gspca_dev *gspca_dev, u8 *command)
 		pipe = usb_sndctrlpipe(gspca_dev->dev, 0);
 		requesttype = USB_TYPE_VENDOR | USB_RECIP_DEVICE;
 	} else {
-		PDEBUG(D_ERR, "Unexpected first byte of command: %x",
-		       command[0]);
+		PERR("Unexpected first byte of command: %x", command[0]);
 		return -EINVAL;
 	}
 
@@ -701,7 +700,7 @@ static void reset_camera_params(struct gspca_dev *gspca_dev)
 	params->qx3.cradled = 0;
 }
 
-static void printstatus(struct cam_params *params)
+static void printstatus(struct gspca_dev *gspca_dev, struct cam_params *params)
 {
 	PDEBUG(D_PROBE, "status: %02x %02x %02x %02x %02x %02x %02x %02x",
 	       params->status.systemState, params->status.grabState,
@@ -725,10 +724,9 @@ static int goto_low_power(struct gspca_dev *gspca_dev)
 
 	if (sd->params.status.systemState != LO_POWER_STATE) {
 		if (sd->params.status.systemState != WARM_BOOT_STATE) {
-			PDEBUG(D_ERR,
-			       "unexpected state after lo power cmd: %02x",
-			       sd->params.status.systemState);
-			printstatus(&sd->params);
+			PERR("unexpected state after lo power cmd: %02x",
+			     sd->params.status.systemState);
+			printstatus(gspca_dev, &sd->params);
 		}
 		return -EIO;
 	}
@@ -756,9 +754,9 @@ static int goto_high_power(struct gspca_dev *gspca_dev)
 		return ret;
 
 	if (sd->params.status.systemState != HI_POWER_STATE) {
-		PDEBUG(D_ERR, "unexpected state after hi power cmd: %02x",
-			       sd->params.status.systemState);
-		printstatus(&sd->params);
+		PERR("unexpected state after hi power cmd: %02x",
+		     sd->params.status.systemState);
+		printstatus(gspca_dev, &sd->params);
 		return -EIO;
 	}
 
@@ -1449,8 +1447,8 @@ static int sd_config(struct gspca_dev *gspca_dev,
 	sd->params.version.firmwareVersion = 0;
 	get_version_information(gspca_dev);
 	if (sd->params.version.firmwareVersion != 1) {
-		PDEBUG(D_ERR, "only firmware version 1 is supported (got: %d)",
-		       sd->params.version.firmwareVersion);
+		PERR("only firmware version 1 is supported (got: %d)",
+		     sd->params.version.firmwareVersion);
 		return -ENODEV;
 	}
 
@@ -1475,9 +1473,9 @@ static int sd_start(struct gspca_dev *gspca_dev)
 	/* Start the camera in low power mode */
 	if (goto_low_power(gspca_dev)) {
 		if (sd->params.status.systemState != WARM_BOOT_STATE) {
-			PDEBUG(D_ERR, "unexpected systemstate: %02x",
-			       sd->params.status.systemState);
-			printstatus(&sd->params);
+			PERR("unexpected systemstate: %02x",
+			     sd->params.status.systemState);
+			printstatus(gspca_dev, &sd->params);
 			return -ENODEV;
 		}
 
@@ -1523,9 +1521,8 @@ static int sd_start(struct gspca_dev *gspca_dev)
 		return ret;
 
 	if (sd->params.status.fatalError) {
-		PDEBUG(D_ERR, "fatal_error: %04x, vp_status: %04x",
-		       sd->params.status.fatalError,
-		       sd->params.status.vpStatus);
+		PERR("fatal_error: %04x, vp_status: %04x",
+		     sd->params.status.fatalError, sd->params.status.vpStatus);
 		return -EIO;
 	}
 
diff --git a/drivers/media/usb/gspca/etoms.c b/drivers/media/usb/gspca/etoms.c
index 38f68e1..26c9ee1 100644
--- a/drivers/media/usb/gspca/etoms.c
+++ b/drivers/media/usb/gspca/etoms.c
@@ -163,12 +163,11 @@ static void reg_r(struct gspca_dev *gspca_dev,
 {
 	struct usb_device *dev = gspca_dev->dev;
 
-#ifdef GSPCA_DEBUG
 	if (len > USB_BUF_SZ) {
-		pr_err("reg_r: buffer overflow\n");
+		PERR("reg_r: buffer overflow\n");
 		return;
 	}
-#endif
+
 	usb_control_msg(dev,
 			usb_rcvctrlpipe(dev, 0),
 			0,
@@ -201,13 +200,12 @@ static void reg_w(struct gspca_dev *gspca_dev,
 {
 	struct usb_device *dev = gspca_dev->dev;
 
-#ifdef GSPCA_DEBUG
 	if (len > USB_BUF_SZ) {
 		pr_err("reg_w: buffer overflow\n");
 		return;
 	}
 	PDEBUG(D_USBO, "reg write [%02x] = %02x..", index, *buffer);
-#endif
+
 	memcpy(gspca_dev->usb_buf, buffer, len);
 	usb_control_msg(dev,
 			usb_sndctrlpipe(dev, 0),
@@ -274,7 +272,7 @@ static int et_video(struct gspca_dev *gspca_dev,
 		     : 0);		/* stopvideo */
 	ret = Et_WaitStatus(gspca_dev);
 	if (ret != 0)
-		PDEBUG(D_ERR, "timeout video on/off");
+		PERR("timeout video on/off");
 	return ret;
 }
 
@@ -768,9 +766,7 @@ static const struct sd_desc sd_desc = {
 /* -- module initialisation -- */
 static const struct usb_device_id device_table[] = {
 	{USB_DEVICE(0x102c, 0x6151), .driver_info = SENSOR_PAS106},
-#if !defined CONFIG_USB_ET61X251 && !defined CONFIG_USB_ET61X251_MODULE
 	{USB_DEVICE(0x102c, 0x6251), .driver_info = SENSOR_TAS5130CXX},
-#endif
 	{}
 };
 
diff --git a/drivers/media/usb/gspca/gl860/gl860.c b/drivers/media/usb/gspca/gl860/gl860.c
index ced3b71..cb1e64c 100644
--- a/drivers/media/usb/gspca/gl860/gl860.c
+++ b/drivers/media/usb/gspca/gl860/gl860.c
@@ -58,115 +58,135 @@ MODULE_PARM_DESC(sensor,
 
 /*============================ webcam controls =============================*/
 
-/* Functions to get and set a control value */
-#define SD_SETGET(thename) \
-static int sd_set_##thename(struct gspca_dev *gspca_dev, s32 val)\
-{\
-	struct sd *sd = (struct sd *) gspca_dev;\
-\
-	sd->vcur.thename = val;\
-	if (gspca_dev->streaming)\
-		sd->waitSet = 1;\
-	return 0;\
-} \
-static int sd_get_##thename(struct gspca_dev *gspca_dev, s32 *val)\
-{\
-	struct sd *sd = (struct sd *) gspca_dev;\
-\
-	*val = sd->vcur.thename;\
-	return 0;\
-}
+static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct gspca_dev *gspca_dev =
+		container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
+	struct sd *sd = (struct sd *) gspca_dev;
 
-SD_SETGET(mirror)
-SD_SETGET(flip)
-SD_SETGET(AC50Hz)
-SD_SETGET(backlight)
-SD_SETGET(brightness)
-SD_SETGET(gamma)
-SD_SETGET(hue)
-SD_SETGET(saturation)
-SD_SETGET(sharpness)
-SD_SETGET(whitebal)
-SD_SETGET(contrast)
-
-#define GL860_NCTRLS 11
-
-/* control table */
-static struct ctrl sd_ctrls_mi1320[GL860_NCTRLS];
-static struct ctrl sd_ctrls_mi2020[GL860_NCTRLS];
-static struct ctrl sd_ctrls_ov2640[GL860_NCTRLS];
-static struct ctrl sd_ctrls_ov9655[GL860_NCTRLS];
-
-#define SET_MY_CTRL(theid, \
-	thetype, thelabel, thename) \
-	if (sd->vmax.thename != 0) {\
-		sd_ctrls[nCtrls].qctrl.id   = theid;\
-		sd_ctrls[nCtrls].qctrl.type = thetype;\
-		strcpy(sd_ctrls[nCtrls].qctrl.name, thelabel);\
-		sd_ctrls[nCtrls].qctrl.minimum = 0;\
-		sd_ctrls[nCtrls].qctrl.maximum = sd->vmax.thename;\
-		sd_ctrls[nCtrls].qctrl.default_value = sd->vcur.thename;\
-		sd_ctrls[nCtrls].qctrl.step = \
-			(sd->vmax.thename < 16) ? 1 : sd->vmax.thename/16;\
-		sd_ctrls[nCtrls].set = sd_set_##thename;\
-		sd_ctrls[nCtrls].get = sd_get_##thename;\
-		nCtrls++;\
+	switch (ctrl->id) {
+	case V4L2_CID_BRIGHTNESS:
+		sd->vcur.brightness = ctrl->val;
+		break;
+	case V4L2_CID_CONTRAST:
+		sd->vcur.contrast = ctrl->val;
+		break;
+	case V4L2_CID_SATURATION:
+		sd->vcur.saturation = ctrl->val;
+		break;
+	case V4L2_CID_HUE:
+		sd->vcur.hue = ctrl->val;
+		break;
+	case V4L2_CID_GAMMA:
+		sd->vcur.gamma = ctrl->val;
+		break;
+	case V4L2_CID_HFLIP:
+		sd->vcur.mirror = ctrl->val;
+		break;
+	case V4L2_CID_VFLIP:
+		sd->vcur.flip = ctrl->val;
+		break;
+	case V4L2_CID_POWER_LINE_FREQUENCY:
+		sd->vcur.AC50Hz = ctrl->val;
+		break;
+	case V4L2_CID_WHITE_BALANCE_TEMPERATURE:
+		sd->vcur.whitebal = ctrl->val;
+		break;
+	case V4L2_CID_SHARPNESS:
+		sd->vcur.sharpness = ctrl->val;
+		break;
+	case V4L2_CID_BACKLIGHT_COMPENSATION:
+		sd->vcur.backlight = ctrl->val;
+		break;
+	default:
+		return -EINVAL;
 	}
 
-static int gl860_build_control_table(struct gspca_dev *gspca_dev)
+	if (gspca_dev->streaming)
+		sd->waitSet = 1;
+
+	return 0;
+}
+
+static const struct v4l2_ctrl_ops sd_ctrl_ops = {
+	.s_ctrl = sd_s_ctrl,
+};
+
+static int sd_init_controls(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	struct ctrl *sd_ctrls;
-	int nCtrls = 0;
-
-	if (_MI1320_)
-		sd_ctrls = sd_ctrls_mi1320;
-	else if (_MI2020_)
-		sd_ctrls = sd_ctrls_mi2020;
-	else if (_OV2640_)
-		sd_ctrls = sd_ctrls_ov2640;
-	else if (_OV9655_)
-		sd_ctrls = sd_ctrls_ov9655;
-	else
-		return 0;
-
-	memset(sd_ctrls, 0, GL860_NCTRLS * sizeof(struct ctrl));
-
-	SET_MY_CTRL(V4L2_CID_BRIGHTNESS,
-		V4L2_CTRL_TYPE_INTEGER, "Brightness", brightness)
-	SET_MY_CTRL(V4L2_CID_SHARPNESS,
-		V4L2_CTRL_TYPE_INTEGER, "Sharpness", sharpness)
-	SET_MY_CTRL(V4L2_CID_CONTRAST,
-		V4L2_CTRL_TYPE_INTEGER, "Contrast", contrast)
-	SET_MY_CTRL(V4L2_CID_GAMMA,
-		V4L2_CTRL_TYPE_INTEGER, "Gamma", gamma)
-	SET_MY_CTRL(V4L2_CID_HUE,
-		V4L2_CTRL_TYPE_INTEGER, "Palette", hue)
-	SET_MY_CTRL(V4L2_CID_SATURATION,
-		V4L2_CTRL_TYPE_INTEGER, "Saturation", saturation)
-	SET_MY_CTRL(V4L2_CID_WHITE_BALANCE_TEMPERATURE,
-		V4L2_CTRL_TYPE_INTEGER, "White Bal.", whitebal)
-	SET_MY_CTRL(V4L2_CID_BACKLIGHT_COMPENSATION,
-		V4L2_CTRL_TYPE_INTEGER, "Backlight" , backlight)
-
-	SET_MY_CTRL(V4L2_CID_HFLIP,
-		V4L2_CTRL_TYPE_BOOLEAN, "Mirror", mirror)
-	SET_MY_CTRL(V4L2_CID_VFLIP,
-		V4L2_CTRL_TYPE_BOOLEAN, "Flip", flip)
-	SET_MY_CTRL(V4L2_CID_POWER_LINE_FREQUENCY,
-		V4L2_CTRL_TYPE_BOOLEAN, "AC power 50Hz", AC50Hz)
-
-	return nCtrls;
+	struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
+
+	gspca_dev->vdev.ctrl_handler = hdl;
+	v4l2_ctrl_handler_init(hdl, 11);
+
+	if (sd->vmax.brightness)
+		v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_BRIGHTNESS,
+				  0, sd->vmax.brightness, 1,
+				  sd->vcur.brightness);
+
+	if (sd->vmax.contrast)
+		v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_CONTRAST,
+				  0, sd->vmax.contrast, 1,
+				  sd->vcur.contrast);
+
+	if (sd->vmax.saturation)
+		v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_SATURATION,
+				  0, sd->vmax.saturation, 1,
+				  sd->vcur.saturation);
+
+	if (sd->vmax.hue)
+		v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_HUE,
+				  0, sd->vmax.hue, 1, sd->vcur.hue);
+
+	if (sd->vmax.gamma)
+		v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_GAMMA,
+				  0, sd->vmax.gamma, 1, sd->vcur.gamma);
+
+	if (sd->vmax.mirror)
+		v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_HFLIP,
+				  0, sd->vmax.mirror, 1, sd->vcur.mirror);
+
+	if (sd->vmax.flip)
+		v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_VFLIP,
+				  0, sd->vmax.flip, 1, sd->vcur.flip);
+
+	if (sd->vmax.AC50Hz)
+		v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
+				  V4L2_CID_POWER_LINE_FREQUENCY,
+				  sd->vmax.AC50Hz, 0, sd->vcur.AC50Hz);
+
+	if (sd->vmax.whitebal)
+		v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+				  V4L2_CID_WHITE_BALANCE_TEMPERATURE,
+				  0, sd->vmax.whitebal, 1, sd->vcur.whitebal);
+
+	if (sd->vmax.sharpness)
+		v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_SHARPNESS,
+				  0, sd->vmax.sharpness, 1,
+				  sd->vcur.sharpness);
+
+	if (sd->vmax.backlight)
+		v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+				  V4L2_CID_BACKLIGHT_COMPENSATION,
+				  0, sd->vmax.backlight, 1,
+				  sd->vcur.backlight);
+
+	if (hdl->error) {
+		pr_err("Could not initialize controls\n");
+		return hdl->error;
+	}
+
+	return 0;
 }
 
 /*==================== sud-driver structure initialisation =================*/
 
 static const struct sd_desc sd_desc_mi1320 = {
 	.name        = MODULE_NAME,
-	.ctrls       = sd_ctrls_mi1320,
-	.nctrls      = GL860_NCTRLS,
 	.config      = sd_config,
 	.init        = sd_init,
+	.init_controls = sd_init_controls,
 	.isoc_init   = sd_isoc_init,
 	.start       = sd_start,
 	.stop0       = sd_stop0,
@@ -176,10 +196,9 @@ static const struct sd_desc sd_desc_mi1320 = {
 
 static const struct sd_desc sd_desc_mi2020 = {
 	.name        = MODULE_NAME,
-	.ctrls       = sd_ctrls_mi2020,
-	.nctrls      = GL860_NCTRLS,
 	.config      = sd_config,
 	.init        = sd_init,
+	.init_controls = sd_init_controls,
 	.isoc_init   = sd_isoc_init,
 	.start       = sd_start,
 	.stop0       = sd_stop0,
@@ -189,10 +208,9 @@ static const struct sd_desc sd_desc_mi2020 = {
 
 static const struct sd_desc sd_desc_ov2640 = {
 	.name        = MODULE_NAME,
-	.ctrls       = sd_ctrls_ov2640,
-	.nctrls      = GL860_NCTRLS,
 	.config      = sd_config,
 	.init        = sd_init,
+	.init_controls = sd_init_controls,
 	.isoc_init   = sd_isoc_init,
 	.start       = sd_start,
 	.stop0       = sd_stop0,
@@ -202,10 +220,9 @@ static const struct sd_desc sd_desc_ov2640 = {
 
 static const struct sd_desc sd_desc_ov9655 = {
 	.name        = MODULE_NAME,
-	.ctrls       = sd_ctrls_ov9655,
-	.nctrls      = GL860_NCTRLS,
 	.config      = sd_config,
 	.init        = sd_init,
+	.init_controls = sd_init_controls,
 	.isoc_init   = sd_isoc_init,
 	.start       = sd_start,
 	.stop0       = sd_stop0,
@@ -371,7 +388,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
 	dev_init_settings(gspca_dev);
 	if (AC50Hz != 0xff)
 		((struct sd *) gspca_dev)->vcur.AC50Hz = AC50Hz;
-	gl860_build_control_table(gspca_dev);
 
 	return 0;
 }
@@ -566,7 +582,7 @@ int gl860_RTx(struct gspca_dev *gspca_dev,
 		pr_err("ctrl transfer failed %4d [p%02x r%d v%04x i%04x len%d]\n",
 		       r, pref, req, val, index, len);
 	else if (len > 1 && r < len)
-		PDEBUG(D_ERR, "short ctrl transfer %d/%d", r, len);
+		PERR("short ctrl transfer %d/%d", r, len);
 
 	msleep(1);
 
diff --git a/drivers/media/usb/gspca/gspca.c b/drivers/media/usb/gspca/gspca.c
index 3564bdb..5995ec4 100644
--- a/drivers/media/usb/gspca/gspca.c
+++ b/drivers/media/usb/gspca/gspca.c
@@ -60,14 +60,14 @@ MODULE_DESCRIPTION("GSPCA USB Camera Driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(GSPCA_VERSION);
 
-#ifdef GSPCA_DEBUG
-int gspca_debug = D_ERR | D_PROBE;
+int gspca_debug;
 EXPORT_SYMBOL(gspca_debug);
 
-static void PDEBUG_MODE(char *txt, __u32 pixfmt, int w, int h)
+static void PDEBUG_MODE(struct gspca_dev *gspca_dev, int debug, char *txt,
+			__u32 pixfmt, int w, int h)
 {
 	if ((pixfmt >> 24) >= '0' && (pixfmt >> 24) <= 'z') {
-		PDEBUG(D_CONF|D_STREAM, "%s %c%c%c%c %dx%d",
+		PDEBUG(debug, "%s %c%c%c%c %dx%d",
 			txt,
 			pixfmt & 0xff,
 			(pixfmt >> 8) & 0xff,
@@ -75,15 +75,12 @@ static void PDEBUG_MODE(char *txt, __u32 pixfmt, int w, int h)
 			pixfmt >> 24,
 			w, h);
 	} else {
-		PDEBUG(D_CONF|D_STREAM, "%s 0x%08x %dx%d",
+		PDEBUG(debug, "%s 0x%08x %dx%d",
 			txt,
 			pixfmt,
 			w, h);
 	}
 }
-#else
-#define PDEBUG_MODE(txt, pixfmt, w, h)
-#endif
 
 /* specific memory types - !! should be different from V4L2_MEMORY_xxx */
 #define GSPCA_MEMORY_NO 0	/* V4L2_MEMORY_xxx starts from 1 */
@@ -129,7 +126,7 @@ static void int_irq(struct urb *urb)
 	case 0:
 		if (gspca_dev->sd_desc->int_pkt_scan(gspca_dev,
 		    urb->transfer_buffer, urb->actual_length) < 0) {
-			PDEBUG(D_ERR, "Unknown packet received");
+			PERR("Unknown packet received");
 		}
 		break;
 
@@ -143,7 +140,7 @@ static void int_irq(struct urb *urb)
 		break;
 
 	default:
-		PDEBUG(D_ERR, "URB error %i, resubmitting", urb->status);
+		PERR("URB error %i, resubmitting", urb->status);
 		urb->status = 0;
 		ret = 0;
 	}
@@ -229,7 +226,7 @@ static int alloc_and_submit_int_urb(struct gspca_dev *gspca_dev,
 	urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 	ret = usb_submit_urb(urb, GFP_KERNEL);
 	if (ret < 0) {
-		PDEBUG(D_ERR, "submit int URB failed with error %i", ret);
+		PERR("submit int URB failed with error %i", ret);
 		goto error_submit;
 	}
 	gspca_dev->int_urb = urb;
@@ -315,7 +312,7 @@ static void fill_frame(struct gspca_dev *gspca_dev,
 		if (gspca_dev->frozen)
 			return;
 #endif
-		PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status);
+		PERR("urb status: %d", urb->status);
 		urb->status = 0;
 		goto resubmit;
 	}
@@ -388,7 +385,7 @@ static void bulk_irq(struct urb *urb)
 		if (gspca_dev->frozen)
 			return;
 #endif
-		PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status);
+		PERR("urb status: %d", urb->status);
 		urb->status = 0;
 		goto resubmit;
 	}
@@ -460,7 +457,7 @@ void gspca_frame_add(struct gspca_dev *gspca_dev,
 	/* append the packet to the frame buffer */
 	if (len > 0) {
 		if (gspca_dev->image_len + len > gspca_dev->frsz) {
-			PDEBUG(D_ERR|D_PACK, "frame overflow %d > %d",
+			PERR("frame overflow %d > %d",
 				gspca_dev->image_len + len,
 				gspca_dev->frsz);
 			packet_type = DISCARD_PACKET;
@@ -570,11 +567,10 @@ static void destroy_urbs(struct gspca_dev *gspca_dev)
 
 		gspca_dev->urb[i] = NULL;
 		usb_kill_urb(urb);
-		if (urb->transfer_buffer != NULL)
-			usb_free_coherent(gspca_dev->dev,
-					  urb->transfer_buffer_length,
-					  urb->transfer_buffer,
-					  urb->transfer_dma);
+		usb_free_coherent(gspca_dev->dev,
+				  urb->transfer_buffer_length,
+				  urb->transfer_buffer,
+				  urb->transfer_dma);
 		usb_free_urb(urb);
 	}
 }
@@ -960,9 +956,7 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev)
 		/* the bandwidth is not wide enough
 		 * negotiate or try a lower alternate setting */
 retry:
-		PDEBUG(D_ERR|D_STREAM,
-			"alt %d - bandwidth not wide enough - trying again",
-			alt);
+		PERR("alt %d - bandwidth not wide enough, trying again", alt);
 		msleep(20);	/* wait for kill complete */
 		if (gspca_dev->sd_desc->isoc_nego) {
 			ret = gspca_dev->sd_desc->isoc_nego(gspca_dev);
@@ -984,7 +978,6 @@ out:
 
 static void gspca_set_default_mode(struct gspca_dev *gspca_dev)
 {
-	struct gspca_ctrl *ctrl;
 	int i;
 
 	i = gspca_dev->cam.nmodes - 1;	/* take the highest mode */
@@ -993,17 +986,8 @@ static void gspca_set_default_mode(struct gspca_dev *gspca_dev)
 	gspca_dev->height = gspca_dev->cam.cam_mode[i].height;
 	gspca_dev->pixfmt = gspca_dev->cam.cam_mode[i].pixelformat;
 
-	/* set the current control values to their default values
-	 * which may have changed in sd_init() */
 	/* does nothing if ctrl_handler == NULL */
 	v4l2_ctrl_handler_setup(gspca_dev->vdev.ctrl_handler);
-	ctrl = gspca_dev->cam.ctrls;
-	if (ctrl != NULL) {
-		for (i = 0;
-		     i < gspca_dev->sd_desc->nctrls;
-		     i++, ctrl++)
-			ctrl->val = ctrl->def;
-	}
 }
 
 static int wxh_to_mode(struct gspca_dev *gspca_dev,
@@ -1055,7 +1039,7 @@ static int vidioc_g_register(struct file *file, void *priv,
 }
 
 static int vidioc_s_register(struct file *file, void *priv,
-			struct v4l2_dbg_register *reg)
+			const struct v4l2_dbg_register *reg)
 {
 	struct gspca_dev *gspca_dev = video_drvdata(file);
 
@@ -1137,10 +1121,9 @@ static int try_fmt_vid_cap(struct gspca_dev *gspca_dev,
 	w = fmt->fmt.pix.width;
 	h = fmt->fmt.pix.height;
 
-#ifdef GSPCA_DEBUG
-	if (gspca_debug & D_CONF)
-		PDEBUG_MODE("try fmt cap", fmt->fmt.pix.pixelformat, w, h);
-#endif
+	PDEBUG_MODE(gspca_dev, D_CONF, "try fmt cap",
+		    fmt->fmt.pix.pixelformat, w, h);
+
 	/* search the closest mode for width and height */
 	mode = wxh_to_mode(gspca_dev, w, h);
 
@@ -1153,8 +1136,6 @@ static int try_fmt_vid_cap(struct gspca_dev *gspca_dev,
 					fmt->fmt.pix.pixelformat);
 		if (mode2 >= 0)
 			mode = mode2;
-/*		else
-			;		 * no chance, return this mode */
 	}
 	fmt->fmt.pix = gspca_dev->cam.cam_mode[mode];
 	/* some drivers use priv internally, zero it before giving it to
@@ -1290,15 +1271,6 @@ static int dev_open(struct file *file)
 	if (!try_module_get(gspca_dev->module))
 		return -ENODEV;
 
-#ifdef GSPCA_DEBUG
-	/* activate the v4l2 debug */
-	if (gspca_debug & D_V4L2)
-		gspca_dev->vdev.debug |= V4L2_DEBUG_IOCTL
-					| V4L2_DEBUG_IOCTL_ARG;
-	else
-		gspca_dev->vdev.debug &= ~(V4L2_DEBUG_IOCTL
-					| V4L2_DEBUG_IOCTL_ARG);
-#endif
 	return v4l2_fh_open(file);
 }
 
@@ -1357,134 +1329,6 @@ static int vidioc_querycap(struct file *file, void  *priv,
 	return 0;
 }
 
-static int get_ctrl(struct gspca_dev *gspca_dev,
-				   int id)
-{
-	const struct ctrl *ctrls;
-	int i;
-
-	for (i = 0, ctrls = gspca_dev->sd_desc->ctrls;
-	     i < gspca_dev->sd_desc->nctrls;
-	     i++, ctrls++) {
-		if (gspca_dev->ctrl_dis & (1 << i))
-			continue;
-		if (id == ctrls->qctrl.id)
-			return i;
-	}
-	return -1;
-}
-
-static int vidioc_queryctrl(struct file *file, void *priv,
-			   struct v4l2_queryctrl *q_ctrl)
-{
-	struct gspca_dev *gspca_dev = video_drvdata(file);
-	const struct ctrl *ctrls;
-	struct gspca_ctrl *gspca_ctrl;
-	int i, idx;
-	u32 id;
-
-	id = q_ctrl->id;
-	if (id & V4L2_CTRL_FLAG_NEXT_CTRL) {
-		id &= V4L2_CTRL_ID_MASK;
-		id++;
-		idx = -1;
-		for (i = 0; i < gspca_dev->sd_desc->nctrls; i++) {
-			if (gspca_dev->ctrl_dis & (1 << i))
-				continue;
-			if (gspca_dev->sd_desc->ctrls[i].qctrl.id < id)
-				continue;
-			if (idx >= 0
-			 && gspca_dev->sd_desc->ctrls[i].qctrl.id
-				    > gspca_dev->sd_desc->ctrls[idx].qctrl.id)
-				continue;
-			idx = i;
-		}
-	} else {
-		idx = get_ctrl(gspca_dev, id);
-	}
-	if (idx < 0)
-		return -EINVAL;
-	ctrls = &gspca_dev->sd_desc->ctrls[idx];
-	memcpy(q_ctrl, &ctrls->qctrl, sizeof *q_ctrl);
-	if (gspca_dev->cam.ctrls != NULL) {
-		gspca_ctrl = &gspca_dev->cam.ctrls[idx];
-		q_ctrl->default_value = gspca_ctrl->def;
-		q_ctrl->minimum = gspca_ctrl->min;
-		q_ctrl->maximum = gspca_ctrl->max;
-	}
-	if (gspca_dev->ctrl_inac & (1 << idx))
-		q_ctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
-	return 0;
-}
-
-static int vidioc_s_ctrl(struct file *file, void *priv,
-			 struct v4l2_control *ctrl)
-{
-	struct gspca_dev *gspca_dev = video_drvdata(file);
-	const struct ctrl *ctrls;
-	struct gspca_ctrl *gspca_ctrl;
-	int idx;
-
-	idx = get_ctrl(gspca_dev, ctrl->id);
-	if (idx < 0)
-		return -EINVAL;
-	if (gspca_dev->ctrl_inac & (1 << idx))
-		return -EINVAL;
-	ctrls = &gspca_dev->sd_desc->ctrls[idx];
-	if (gspca_dev->cam.ctrls != NULL) {
-		gspca_ctrl = &gspca_dev->cam.ctrls[idx];
-		if (ctrl->value < gspca_ctrl->min
-		    || ctrl->value > gspca_ctrl->max)
-			return -ERANGE;
-	} else {
-		gspca_ctrl = NULL;
-		if (ctrl->value < ctrls->qctrl.minimum
-		    || ctrl->value > ctrls->qctrl.maximum)
-			return -ERANGE;
-	}
-	PDEBUG(D_CONF, "set ctrl [%08x] = %d", ctrl->id, ctrl->value);
-	gspca_dev->usb_err = 0;
-	if (ctrls->set != NULL)
-		return ctrls->set(gspca_dev, ctrl->value);
-	if (gspca_ctrl != NULL) {
-		gspca_ctrl->val = ctrl->value;
-		if (ctrls->set_control != NULL
-		 && gspca_dev->streaming)
-			ctrls->set_control(gspca_dev);
-	}
-	return gspca_dev->usb_err;
-}
-
-static int vidioc_g_ctrl(struct file *file, void *priv,
-			 struct v4l2_control *ctrl)
-{
-	struct gspca_dev *gspca_dev = video_drvdata(file);
-	const struct ctrl *ctrls;
-	int idx;
-
-	idx = get_ctrl(gspca_dev, ctrl->id);
-	if (idx < 0)
-		return -EINVAL;
-	ctrls = &gspca_dev->sd_desc->ctrls[idx];
-
-	gspca_dev->usb_err = 0;
-	if (ctrls->get != NULL)
-		return ctrls->get(gspca_dev, &ctrl->value);
-	if (gspca_dev->cam.ctrls != NULL)
-		ctrl->value = gspca_dev->cam.ctrls[idx].val;
-	return 0;
-}
-
-static int vidioc_querymenu(struct file *file, void *priv,
-			    struct v4l2_querymenu *qmenu)
-{
-	struct gspca_dev *gspca_dev = video_drvdata(file);
-
-	if (!gspca_dev->sd_desc->querymenu)
-		return -ENOTTY;
-	return gspca_dev->sd_desc->querymenu(gspca_dev, qmenu);
-}
-
 static int vidioc_enum_input(struct file *file, void *priv,
 				struct v4l2_input *input)
 {
@@ -1621,14 +1465,8 @@ static int vidioc_streamon(struct file *file, void *priv,
 		if (ret < 0)
 			goto out;
 	}
-#ifdef GSPCA_DEBUG
-	if (gspca_debug & D_STREAM) {
-		PDEBUG_MODE("stream on OK",
-			gspca_dev->pixfmt,
-			gspca_dev->width,
-			gspca_dev->height);
-	}
-#endif
+	PDEBUG_MODE(gspca_dev, D_STREAM, "stream on OK", gspca_dev->pixfmt,
+		    gspca_dev->width, gspca_dev->height);
 	ret = 0;
 out:
 	mutex_unlock(&gspca_dev->queue_lock);
@@ -1879,8 +1717,7 @@ static int vidioc_dqbuf(struct file *file, void *priv,
 		if (copy_to_user((__u8 __user *) frame->v4l2_buf.m.userptr,
 				 frame->data,
 				 frame->v4l2_buf.bytesused)) {
-			PDEBUG(D_ERR|D_STREAM,
-				"dqbuf cp to user failed");
+			PERR("dqbuf cp to user failed");
 			ret = -EFAULT;
 		}
 	}
@@ -2092,8 +1929,7 @@ static ssize_t dev_read(struct file *file, char __user *data,
 		count = frame->v4l2_buf.bytesused;
 	ret = copy_to_user(data, frame->data, count);
 	if (ret != 0) {
-		PDEBUG(D_ERR|D_STREAM,
-			"read cp to user lack %d / %zd", ret, count);
+		PERR("read cp to user lack %d / %zd", ret, count);
 		ret = -EFAULT;
 		goto out;
 	}
@@ -2125,10 +1961,6 @@ static const struct v4l2_ioctl_ops dev_ioctl_ops = {
 	.vidioc_g_fmt_vid_cap	= vidioc_g_fmt_vid_cap,
 	.vidioc_s_fmt_vid_cap	= vidioc_s_fmt_vid_cap,
 	.vidioc_streamon	= vidioc_streamon,
-	.vidioc_queryctrl	= vidioc_queryctrl,
-	.vidioc_g_ctrl		= vidioc_g_ctrl,
-	.vidioc_s_ctrl		= vidioc_s_ctrl,
-	.vidioc_querymenu	= vidioc_querymenu,
 	.vidioc_enum_input	= vidioc_enum_input,
 	.vidioc_g_input		= vidioc_g_input,
 	.vidioc_s_input		= vidioc_s_input,
@@ -2157,22 +1989,6 @@ static const struct video_device gspca_template = {
 	.release = video_device_release_empty, /* We use v4l2_dev.release */
 };
 
-/* initialize the controls */
-static void ctrls_init(struct gspca_dev *gspca_dev)
-{
-	struct gspca_ctrl *ctrl;
-	int i;
-
-	for (i = 0, ctrl = gspca_dev->cam.ctrls;
-	     i < gspca_dev->sd_desc->nctrls;
-	     i++, ctrl++) {
-		ctrl->def = gspca_dev->sd_desc->ctrls[i].qctrl.default_value;
-		ctrl->val = ctrl->def;
-		ctrl->min = gspca_dev->sd_desc->ctrls[i].qctrl.minimum;
-		ctrl->max = gspca_dev->sd_desc->ctrls[i].qctrl.maximum;
-	}
-}
-
 /*
  * probe and create a new gspca device
  *
@@ -2249,8 +2065,6 @@ int gspca_dev_probe2(struct usb_interface *intf,
 	ret = sd_desc->config(gspca_dev, id);
 	if (ret < 0)
 		goto out;
-	if (gspca_dev->cam.ctrls != NULL)
-		ctrls_init(gspca_dev);
 	ret = sd_desc->init(gspca_dev);
 	if (ret < 0)
 		goto out;
@@ -2450,10 +2264,6 @@ static void __exit gspca_exit(void)
 module_init(gspca_init);
 module_exit(gspca_exit);
 
-#ifdef GSPCA_DEBUG
 module_param_named(debug, gspca_debug, int, 0644);
 MODULE_PARM_DESC(debug,
-		"Debug (bit) 0x01:error 0x02:probe 0x04:config"
-		" 0x08:stream 0x10:frame 0x20:packet"
-		" 0x0100: v4l2");
-#endif
+		"1:probe 2:config 3:stream 4:frame 5:packet 6:usbi 7:usbo");
diff --git a/drivers/media/usb/gspca/gspca.h b/drivers/media/usb/gspca/gspca.h
index 5559932..ef8efeb 100644
--- a/drivers/media/usb/gspca/gspca.h
+++ b/drivers/media/usb/gspca/gspca.h
@@ -10,30 +10,26 @@
 #include <media/v4l2-device.h>
 #include <linux/mutex.h>
 
-/* compilation option */
-/*#define GSPCA_DEBUG 1*/
 
-#ifdef GSPCA_DEBUG
-/* GSPCA our debug messages */
+
+/* GSPCA debug codes */
+
+#define D_PROBE  1
+#define D_CONF   2
+#define D_STREAM 3
+#define D_FRAM   4
+#define D_PACK   5
+#define D_USBI   6
+#define D_USBO   7
+
 extern int gspca_debug;
-#define PDEBUG(level, fmt, ...)					\
-do {								\
-	if (gspca_debug & (level))				\
-		pr_info(fmt, ##__VA_ARGS__);			\
-} while (0)
 
-#define D_ERR  0x01
-#define D_PROBE 0x02
-#define D_CONF 0x04
-#define D_STREAM 0x08
-#define D_FRAM 0x10
-#define D_PACK 0x20
-#define D_USBI 0x00
-#define D_USBO 0x00
-#define D_V4L2 0x0100
-#else
-#define PDEBUG(level, fmt, ...) do {} while(0)
-#endif
+
+#define PDEBUG(level, fmt, ...) \
+	v4l2_dbg(level, gspca_debug, &gspca_dev->v4l2_dev, fmt, ##__VA_ARGS__)
+
+#define PERR(fmt, ...) \
+	v4l2_err(&gspca_dev->v4l2_dev, fmt, ##__VA_ARGS__)
 
 #define GSPCA_MAX_FRAMES 16	/* maximum number of video frame buffers */
 /* image transfers */
@@ -46,20 +42,11 @@ struct framerates {
 	int nrates;
 };
 
-/* control definition */
-struct gspca_ctrl {
-	s16 val;	/* current value */
-	s16 def;	/* default value */
-	s16 min, max;	/* minimum and maximum values */
-};
-
 /* device information - set at probe time */
 struct cam {
 	const struct v4l2_pix_format *cam_mode;	/* size nmodes */
 	const struct framerates *mode_framerates; /* must have size nmodes,
 						   * just like cam_mode */
-	struct gspca_ctrl *ctrls;	/* control table - size nctrls */
-					/* may be NULL */
 	u32 bulk_size;		/* buffer size when image transfer by bulk */
 	u32 input_flags;	/* value for ENUM_INPUT status flags */
 	u8 nmodes;		/* size of cam_mode */
@@ -87,14 +74,14 @@ typedef int (*cam_get_jpg_op) (struct gspca_dev *,
 				struct v4l2_jpegcompression *);
 typedef int (*cam_set_jpg_op) (struct gspca_dev *,
 				const struct v4l2_jpegcompression *);
-typedef int (*cam_reg_op) (struct gspca_dev *,
+typedef int (*cam_get_reg_op) (struct gspca_dev *,
 				struct v4l2_dbg_register *);
+typedef int (*cam_set_reg_op) (struct gspca_dev *,
+				const struct v4l2_dbg_register *);
 typedef int (*cam_ident_op) (struct gspca_dev *,
 				struct v4l2_dbg_chip_ident *);
 typedef void (*cam_streamparm_op) (struct gspca_dev *,
 				  struct v4l2_streamparm *);
-typedef int (*cam_qmnu_op) (struct gspca_dev *,
-			struct v4l2_querymenu *);
 typedef void (*cam_pkt_op) (struct gspca_dev *gspca_dev,
 				u8 *data,
 				int len);
@@ -102,20 +89,10 @@ typedef int (*cam_int_pkt_op) (struct gspca_dev *gspca_dev,
 				u8 *data,
 				int len);
 
-struct ctrl {
-	struct v4l2_queryctrl qctrl;
-	int (*set)(struct gspca_dev *, __s32);
-	int (*get)(struct gspca_dev *, __s32 *);
-	cam_v_op set_control;
-};
-
 /* subdriver description */
 struct sd_desc {
 /* information */
 	const char *name;	/* sub-driver name */
-/* controls */
-	const struct ctrl *ctrls;	/* static control definition */
-	int nctrls;
 /* mandatory operations */
 	cam_cf_op config;	/* called on probe */
 	cam_op init;		/* called on probe and resume */
@@ -130,12 +107,11 @@ struct sd_desc {
 	cam_v_op dq_callback;	/* called when a frame has been dequeued */
 	cam_get_jpg_op get_jcomp;
 	cam_set_jpg_op set_jcomp;
-	cam_qmnu_op querymenu;
 	cam_streamparm_op get_streamparm;
 	cam_streamparm_op set_streamparm;
 #ifdef CONFIG_VIDEO_ADV_DEBUG
-	cam_reg_op set_register;
-	cam_reg_op get_register;
+	cam_set_reg_op set_register;
+	cam_get_reg_op get_register;
 #endif
 	cam_ident_op get_chip_ident;
 #if IS_ENABLED(CONFIG_INPUT)
@@ -174,8 +150,6 @@ struct gspca_dev {
 
 	struct cam cam;				/* device information */
 	const struct sd_desc *sd_desc;		/* subdriver description */
-	unsigned ctrl_dis;		/* disabled controls (bit map) */
-	unsigned ctrl_inac;		/* inactive controls (bit map) */
 	struct v4l2_ctrl_handler ctrl_handler;
 
 	/* autogain and exposure or gain control cluster, these are global as
diff --git a/drivers/media/usb/gspca/jeilinj.c b/drivers/media/usb/gspca/jeilinj.c
index 1ba29fe..8da3dde 100644
--- a/drivers/media/usb/gspca/jeilinj.c
+++ b/drivers/media/usb/gspca/jeilinj.c
@@ -266,7 +266,7 @@ static int jlj_start(struct gspca_dev *gspca_dev)
 	msleep(2);
 	setfreq(gspca_dev, v4l2_ctrl_g_ctrl(sd->freq));
 	if (gspca_dev->usb_err < 0)
-		PDEBUG(D_ERR, "Start streaming command failed");
+		PERR("Start streaming command failed");
 	return gspca_dev->usb_err;
 }
 
diff --git a/drivers/media/usb/gspca/konica.c b/drivers/media/usb/gspca/konica.c
index 61e25db..39c96bb 100644
--- a/drivers/media/usb/gspca/konica.c
+++ b/drivers/media/usb/gspca/konica.c
@@ -277,7 +277,7 @@ static void sd_isoc_irq(struct urb *urb)
 		if (gspca_dev->frozen)
 			return;
 #endif
-		PDEBUG(D_ERR, "urb status: %d", urb->status);
+		PERR("urb status: %d", urb->status);
 		st = usb_submit_urb(urb, GFP_ATOMIC);
 		if (st < 0)
 			pr_err("resubmit urb error %d\n", st);
@@ -295,33 +295,30 @@ static void sd_isoc_irq(struct urb *urb)
 	sd->last_data_urb = NULL;
 
 	if (!data_urb || data_urb->start_frame != status_urb->start_frame) {
-		PDEBUG(D_ERR|D_PACK, "lost sync on frames");
+		PERR("lost sync on frames");
 		goto resubmit;
 	}
 
 	if (data_urb->number_of_packets != status_urb->number_of_packets) {
-		PDEBUG(D_ERR|D_PACK,
-		       "no packets does not match, data: %d, status: %d",
-		       data_urb->number_of_packets,
-		       status_urb->number_of_packets);
+		PERR("no packets does not match, data: %d, status: %d",
+		     data_urb->number_of_packets,
+		     status_urb->number_of_packets);
 		goto resubmit;
 	}
 
 	for (i = 0; i < status_urb->number_of_packets; i++) {
 		if (data_urb->iso_frame_desc[i].status ||
 		    status_urb->iso_frame_desc[i].status) {
-			PDEBUG(D_ERR|D_PACK,
-			       "pkt %d data-status %d, status-status %d", i,
-			       data_urb->iso_frame_desc[i].status,
-			       status_urb->iso_frame_desc[i].status);
+			PERR("pkt %d data-status %d, status-status %d", i,
+			     data_urb->iso_frame_desc[i].status,
+			     status_urb->iso_frame_desc[i].status);
 			gspca_dev->last_packet_type = DISCARD_PACKET;
 			continue;
 		}
 
 		if (status_urb->iso_frame_desc[i].actual_length != 1) {
-			PDEBUG(D_ERR|D_PACK,
-			       "bad status packet length %d",
-			       status_urb->iso_frame_desc[i].actual_length);
+			PERR("bad status packet length %d",
+			     status_urb->iso_frame_desc[i].actual_length);
 			gspca_dev->last_packet_type = DISCARD_PACKET;
 			continue;
 		}
@@ -366,12 +363,11 @@ resubmit:
 	if (data_urb) {
 		st = usb_submit_urb(data_urb, GFP_ATOMIC);
 		if (st < 0)
-			PDEBUG(D_ERR|D_PACK,
-			       "usb_submit_urb(data_urb) ret %d", st);
+			PERR("usb_submit_urb(data_urb) ret %d", st);
 	}
 	st = usb_submit_urb(status_urb, GFP_ATOMIC);
 	if (st < 0)
-		pr_err("usb_submit_urb(status_urb) ret %d\n", st);
+		PERR("usb_submit_urb(status_urb) ret %d\n", st);
 }
 
 static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
diff --git a/drivers/media/usb/gspca/m5602/m5602_bridge.h b/drivers/media/usb/gspca/m5602/m5602_bridge.h
index 51af3ee..19eb1a6 100644
--- a/drivers/media/usb/gspca/m5602/m5602_bridge.h
+++ b/drivers/media/usb/gspca/m5602/m5602_bridge.h
@@ -136,16 +136,33 @@ struct sd {
 	/* A pointer to the currently connected sensor */
 	const struct m5602_sensor *sensor;
 
-	struct sd_desc *desc;
-
-	/* Sensor private data */
-	void *sensor_priv;
-
 	/* The current frame's id, used to detect frame boundaries */
 	u8 frame_id;
 
 	/* The current frame count */
 	u32 frame_count;
+
+	/* Camera rotation polling thread for "flipable" cams */
+	struct task_struct *rotation_thread;
+
+	struct { /* auto-white-bal + green/red/blue balance control cluster */
+		struct v4l2_ctrl *auto_white_bal;
+		struct v4l2_ctrl *red_bal;
+		struct v4l2_ctrl *blue_bal;
+		struct v4l2_ctrl *green_bal;
+	};
+	struct { /* autoexpo / expo cluster */
+		struct v4l2_ctrl *autoexpo;
+		struct v4l2_ctrl *expo;
+	};
+	struct { /* autogain / gain cluster */
+		struct v4l2_ctrl *autogain;
+		struct v4l2_ctrl *gain;
+	};
+	struct { /* hflip/vflip cluster */
+		struct v4l2_ctrl *hflip;
+		struct v4l2_ctrl *vflip;
+	};
 };
 
 int m5602_read_bridge(
diff --git a/drivers/media/usb/gspca/m5602/m5602_core.c b/drivers/media/usb/gspca/m5602/m5602_core.c
index ed22638..d926e62 100644
--- a/drivers/media/usb/gspca/m5602/m5602_core.c
+++ b/drivers/media/usb/gspca/m5602/m5602_core.c
@@ -41,6 +41,7 @@ MODULE_DEVICE_TABLE(usb, m5602_table);
 int m5602_read_bridge(struct sd *sd, const u8 address, u8 *i2c_data)
 {
 	int err;
+	struct gspca_dev *gspca_dev = (struct gspca_dev *) sd;
 	struct usb_device *udev = sd->gspca_dev.dev;
 	__u8 *buf = sd->gspca_dev.usb_buf;
 
@@ -62,6 +63,7 @@ int m5602_read_bridge(struct sd *sd, const u8 address, u8 *i2c_data)
 int m5602_write_bridge(struct sd *sd, const u8 address, const u8 i2c_data)
 {
 	int err;
+	struct gspca_dev *gspca_dev = (struct gspca_dev *) sd;
 	struct usb_device *udev = sd->gspca_dev.dev;
 	__u8 *buf = sd->gspca_dev.usb_buf;
 
@@ -98,6 +100,7 @@ int m5602_read_sensor(struct sd *sd, const u8 address,
 		       u8 *i2c_data, const u8 len)
 {
 	int err, i;
+	struct gspca_dev *gspca_dev = (struct gspca_dev *) sd;
 
 	if (!len || len > sd->sensor->i2c_regW)
 		return -EINVAL;
@@ -147,6 +150,7 @@ int m5602_write_sensor(struct sd *sd, const u8 address,
 {
 	int err, i;
 	u8 *p;
+	struct gspca_dev *gspca_dev = (struct gspca_dev *) sd;
 	struct usb_device *udev = sd->gspca_dev.dev;
 	__u8 *buf = sd->gspca_dev.usb_buf;
 
@@ -252,6 +256,16 @@ static int m5602_init(struct gspca_dev *gspca_dev)
 	return err;
 }
 
+static int m5602_init_controls(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	if (!sd->sensor->init_controls)
+		return 0;
+
+	return sd->sensor->init_controls(sd);
+}
+
 static int m5602_start_transfer(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
@@ -336,11 +350,12 @@ static void m5602_stop_transfer(struct gspca_dev *gspca_dev)
 		sd->sensor->stop(sd);
 }
 
-/* sub-driver description, the ctrl and nctrl is filled at probe time */
-static struct sd_desc sd_desc = {
+/* sub-driver description */
+static const struct sd_desc sd_desc = {
 	.name		= MODULE_NAME,
 	.config		= m5602_configure,
 	.init		= m5602_init,
+	.init_controls	= m5602_init_controls,
 	.start		= m5602_start_transfer,
 	.stopN		= m5602_stop_transfer,
 	.pkt_scan	= m5602_urb_complete
@@ -355,7 +370,6 @@ static int m5602_configure(struct gspca_dev *gspca_dev,
 	int err;
 
 	cam = &gspca_dev->cam;
-	sd->desc = &sd_desc;
 
 	if (dump_bridge)
 		m5602_dump_bridge(sd);
@@ -368,7 +382,7 @@ static int m5602_configure(struct gspca_dev *gspca_dev,
 	return 0;
 
 fail:
-	PDEBUG(D_ERR, "ALi m5602 webcam failed");
+	PERR("ALi m5602 webcam failed");
 	cam->cam_mode = NULL;
 	cam->nmodes = 0;
 
diff --git a/drivers/media/usb/gspca/m5602/m5602_mt9m111.c b/drivers/media/usb/gspca/m5602/m5602_mt9m111.c
index 6268aa2..cfa4663 100644
--- a/drivers/media/usb/gspca/m5602/m5602_mt9m111.c
+++ b/drivers/media/usb/gspca/m5602/m5602_mt9m111.c
@@ -20,22 +20,8 @@
 
 #include "m5602_mt9m111.h"
 
-static int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
-static int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
-static int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
-static int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
-static int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
-static int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val);
-static int mt9m111_set_auto_white_balance(struct gspca_dev *gspca_dev,
-					 __s32 val);
-static int mt9m111_get_auto_white_balance(struct gspca_dev *gspca_dev,
-					  __s32 *val);
-static int mt9m111_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val);
-static int mt9m111_set_green_balance(struct gspca_dev *gspca_dev, __s32 val);
-static int mt9m111_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val);
-static int mt9m111_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val);
-static int mt9m111_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val);
-static int mt9m111_set_red_balance(struct gspca_dev *gspca_dev, __s32 val);
+static int mt9m111_s_ctrl(struct v4l2_ctrl *ctrl);
+static void mt9m111_dump_registers(struct sd *sd);
 
 static struct v4l2_pix_format mt9m111_modes[] = {
 	{
@@ -50,118 +36,27 @@ static struct v4l2_pix_format mt9m111_modes[] = {
 	}
 };
 
-static const struct ctrl mt9m111_ctrls[] = {
-#define VFLIP_IDX 0
-	{
-		{
-			.id		= V4L2_CID_VFLIP,
-			.type           = V4L2_CTRL_TYPE_BOOLEAN,
-			.name           = "vertical flip",
-			.minimum        = 0,
-			.maximum        = 1,
-			.step           = 1,
-			.default_value  = 0
-		},
-		.set = mt9m111_set_vflip,
-		.get = mt9m111_get_vflip
-	},
-#define HFLIP_IDX 1
-	{
-		{
-			.id             = V4L2_CID_HFLIP,
-			.type           = V4L2_CTRL_TYPE_BOOLEAN,
-			.name           = "horizontal flip",
-			.minimum        = 0,
-			.maximum        = 1,
-			.step           = 1,
-			.default_value  = 0
-		},
-		.set = mt9m111_set_hflip,
-		.get = mt9m111_get_hflip
-	},
-#define GAIN_IDX 2
-	{
-		{
-			.id             = V4L2_CID_GAIN,
-			.type           = V4L2_CTRL_TYPE_INTEGER,
-			.name           = "gain",
-			.minimum        = 0,
-			.maximum        = (INITIAL_MAX_GAIN - 1) * 2 * 2 * 2,
-			.step           = 1,
-			.default_value  = MT9M111_DEFAULT_GAIN,
-			.flags          = V4L2_CTRL_FLAG_SLIDER
-		},
-		.set = mt9m111_set_gain,
-		.get = mt9m111_get_gain
-	},
-#define AUTO_WHITE_BALANCE_IDX 3
-	{
-		{
-			.id             = V4L2_CID_AUTO_WHITE_BALANCE,
-			.type           = V4L2_CTRL_TYPE_BOOLEAN,
-			.name           = "auto white balance",
-			.minimum        = 0,
-			.maximum        = 1,
-			.step           = 1,
-			.default_value  = 0,
-		},
-		.set = mt9m111_set_auto_white_balance,
-		.get = mt9m111_get_auto_white_balance
-	},
-#define GREEN_BALANCE_IDX 4
-	{
-		{
-			.id		= M5602_V4L2_CID_GREEN_BALANCE,
-			.type		= V4L2_CTRL_TYPE_INTEGER,
-			.name		= "green balance",
-			.minimum	= 0x00,
-			.maximum	= 0x7ff,
-			.step		= 0x1,
-			.default_value	= MT9M111_GREEN_GAIN_DEFAULT,
-			.flags		= V4L2_CTRL_FLAG_SLIDER
-		},
-		.set = mt9m111_set_green_balance,
-		.get = mt9m111_get_green_balance
-	},
-#define BLUE_BALANCE_IDX 5
-	{
-		{
-			.id		= V4L2_CID_BLUE_BALANCE,
-			.type		= V4L2_CTRL_TYPE_INTEGER,
-			.name		= "blue balance",
-			.minimum	= 0x00,
-			.maximum	= 0x7ff,
-			.step		= 0x1,
-			.default_value	= MT9M111_BLUE_GAIN_DEFAULT,
-			.flags		= V4L2_CTRL_FLAG_SLIDER
-		},
-		.set = mt9m111_set_blue_balance,
-		.get = mt9m111_get_blue_balance
-	},
-#define RED_BALANCE_IDX 5
-	{
-		{
-			.id		= V4L2_CID_RED_BALANCE,
-			.type		= V4L2_CTRL_TYPE_INTEGER,
-			.name		= "red balance",
-			.minimum	= 0x00,
-			.maximum	= 0x7ff,
-			.step		= 0x1,
-			.default_value	= MT9M111_RED_GAIN_DEFAULT,
-			.flags		= V4L2_CTRL_FLAG_SLIDER
-		},
-		.set = mt9m111_set_red_balance,
-		.get = mt9m111_get_red_balance
-	},
+static const struct v4l2_ctrl_ops mt9m111_ctrl_ops = {
+	.s_ctrl = mt9m111_s_ctrl,
 };
 
-static void mt9m111_dump_registers(struct sd *sd);
+static const struct v4l2_ctrl_config mt9m111_greenbal_cfg = {
+	.ops	= &mt9m111_ctrl_ops,
+	.id	= M5602_V4L2_CID_GREEN_BALANCE,
+	.name	= "Green Balance",
+	.type	= V4L2_CTRL_TYPE_INTEGER,
+	.min	= 0,
+	.max	= 0x7ff,
+	.step	= 1,
+	.def	= MT9M111_GREEN_GAIN_DEFAULT,
+	.flags	= V4L2_CTRL_FLAG_SLIDER,
+};
 
 int mt9m111_probe(struct sd *sd)
 {
 	u8 data[2] = {0x00, 0x00};
 	int i;
-	s32 *sensor_settings;
+	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
 
 	if (force_sensor) {
 		if (force_sensor == MT9M111_SENSOR) {
@@ -200,19 +95,8 @@ int mt9m111_probe(struct sd *sd)
 	return -ENODEV;
 
 sensor_found:
-	sensor_settings = kmalloc(ARRAY_SIZE(mt9m111_ctrls) * sizeof(s32),
-				  GFP_KERNEL);
-	if (!sensor_settings)
-		return -ENOMEM;
-
 	sd->gspca_dev.cam.cam_mode = mt9m111_modes;
 	sd->gspca_dev.cam.nmodes = ARRAY_SIZE(mt9m111_modes);
-	sd->desc->ctrls = mt9m111_ctrls;
-	sd->desc->nctrls = ARRAY_SIZE(mt9m111_ctrls);
-
-	for (i = 0; i < ARRAY_SIZE(mt9m111_ctrls); i++)
-		sensor_settings[i] = mt9m111_ctrls[i].qctrl.default_value;
-	sd->sensor_priv = sensor_settings;
 
 	return 0;
 }
@@ -220,7 +104,6 @@ sensor_found:
 int mt9m111_init(struct sd *sd)
 {
 	int i, err = 0;
-	s32 *sensor_settings = sd->sensor_priv;
 
 	/* Init the sensor */
 	for (i = 0; i < ARRAY_SIZE(init_mt9m111) && !err; i++) {
@@ -241,30 +124,45 @@ int mt9m111_init(struct sd *sd)
 	if (dump_sensor)
 		mt9m111_dump_registers(sd);
 
-	err = mt9m111_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]);
-	if (err < 0)
-		return err;
-
-	err = mt9m111_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]);
-	if (err < 0)
-		return err;
-
-	err = mt9m111_set_green_balance(&sd->gspca_dev,
-					 sensor_settings[GREEN_BALANCE_IDX]);
-	if (err < 0)
-		return err;
+	return 0;
+}
 
-	err = mt9m111_set_blue_balance(&sd->gspca_dev,
-					 sensor_settings[BLUE_BALANCE_IDX]);
-	if (err < 0)
-		return err;
+int mt9m111_init_controls(struct sd *sd)
+{
+	struct v4l2_ctrl_handler *hdl = &sd->gspca_dev.ctrl_handler;
+
+	sd->gspca_dev.vdev.ctrl_handler = hdl;
+	v4l2_ctrl_handler_init(hdl, 7);
+
+	sd->auto_white_bal = v4l2_ctrl_new_std(hdl, &mt9m111_ctrl_ops,
+					       V4L2_CID_AUTO_WHITE_BALANCE,
+					       0, 1, 1, 0);
+	sd->green_bal = v4l2_ctrl_new_custom(hdl, &mt9m111_greenbal_cfg, NULL);
+	sd->red_bal = v4l2_ctrl_new_std(hdl, &mt9m111_ctrl_ops,
+					V4L2_CID_RED_BALANCE, 0, 0x7ff, 1,
+					MT9M111_RED_GAIN_DEFAULT);
+	sd->blue_bal = v4l2_ctrl_new_std(hdl, &mt9m111_ctrl_ops,
+					V4L2_CID_BLUE_BALANCE, 0, 0x7ff, 1,
+					MT9M111_BLUE_GAIN_DEFAULT);
+
+	v4l2_ctrl_new_std(hdl, &mt9m111_ctrl_ops, V4L2_CID_GAIN, 0,
+			  (INITIAL_MAX_GAIN - 1) * 2 * 2 * 2, 1,
+			  MT9M111_DEFAULT_GAIN);
+
+	sd->hflip = v4l2_ctrl_new_std(hdl, &mt9m111_ctrl_ops, V4L2_CID_HFLIP,
+				      0, 1, 1, 0);
+	sd->vflip = v4l2_ctrl_new_std(hdl, &mt9m111_ctrl_ops, V4L2_CID_VFLIP,
+				      0, 1, 1, 0);
+
+	if (hdl->error) {
+		pr_err("Could not initialize controls\n");
+		return hdl->error;
+	}
 
-	err = mt9m111_set_red_balance(&sd->gspca_dev,
-					sensor_settings[RED_BALANCE_IDX]);
-	if (err < 0)
-		return err;
+	v4l2_ctrl_auto_cluster(4, &sd->auto_white_bal, 0, false);
+	v4l2_ctrl_cluster(2, &sd->hflip);
 
-	return mt9m111_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
+	return 0;
 }
 
 int mt9m111_start(struct sd *sd)
@@ -272,7 +170,7 @@ int mt9m111_start(struct sd *sd)
 	int i, err = 0;
 	u8 data[2];
 	struct cam *cam = &sd->gspca_dev.cam;
-	s32 *sensor_settings = sd->sensor_priv;
+	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
 
 	int width = cam->cam_mode[sd->gspca_dev.curr_mode].width - 1;
 	int height = cam->cam_mode[sd->gspca_dev.curr_mode].height;
@@ -333,26 +231,11 @@ int mt9m111_start(struct sd *sd)
 
 	switch (width) {
 	case 640:
-		PDEBUG(D_V4L2, "Configuring camera for VGA mode");
-		data[0] = MT9M111_RMB_OVER_SIZED;
-		data[1] = MT9M111_RMB_ROW_SKIP_2X |
-			  MT9M111_RMB_COLUMN_SKIP_2X |
-			  (sensor_settings[VFLIP_IDX] << 0) |
-			  (sensor_settings[HFLIP_IDX] << 1);
-
-		err = m5602_write_sensor(sd,
-					 MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
+		PDEBUG(D_CONF, "Configuring camera for VGA mode");
 		break;
 
 	case 320:
-		PDEBUG(D_V4L2, "Configuring camera for QVGA mode");
-		data[0] = MT9M111_RMB_OVER_SIZED;
-		data[1] = MT9M111_RMB_ROW_SKIP_4X |
-				MT9M111_RMB_COLUMN_SKIP_4X |
-				(sensor_settings[VFLIP_IDX] << 0) |
-				(sensor_settings[HFLIP_IDX] << 1);
-		err = m5602_write_sensor(sd,
-					 MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
+		PDEBUG(D_CONF, "Configuring camera for QVGA mode");
 		break;
 	}
 	return err;
@@ -361,105 +244,46 @@ int mt9m111_start(struct sd *sd)
 void mt9m111_disconnect(struct sd *sd)
 {
 	sd->sensor = NULL;
-	kfree(sd->sensor_priv);
-}
-
-static int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
-
-	*val = sensor_settings[VFLIP_IDX];
-	PDEBUG(D_V4L2, "Read vertical flip %d", *val);
-
-	return 0;
-}
-
-static int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
-{
-	int err;
-	u8 data[2] = {0x00, 0x00};
-	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
-
-	PDEBUG(D_V4L2, "Set vertical flip to %d", val);
-
-	sensor_settings[VFLIP_IDX] = val;
-
-	/* The mt9m111 is flipped by default */
-	val = !val;
-
-	/* Set the correct page map */
-	err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
-	if (err < 0)
-		return err;
-
-	err = m5602_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
-	if (err < 0)
-		return err;
-
-	data[1] = (data[1] & 0xfe) | val;
-	err = m5602_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
-				   data, 2);
-	return err;
-}
-
-static int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
-
-	*val = sensor_settings[HFLIP_IDX];
-	PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
-
-	return 0;
 }
 
-static int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
+static int mt9m111_set_hvflip(struct gspca_dev *gspca_dev)
 {
 	int err;
 	u8 data[2] = {0x00, 0x00};
 	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
+	int hflip;
+	int vflip;
 
-	PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
-
-	sensor_settings[HFLIP_IDX] = val;
+	PDEBUG(D_CONF, "Set hvflip to %d %d", sd->hflip->val, sd->vflip->val);
 
 	/* The mt9m111 is flipped by default */
-	val = !val;
+	hflip = !sd->hflip->val;
+	vflip = !sd->vflip->val;
 
 	/* Set the correct page map */
 	err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
 	if (err < 0)
 		return err;
 
-	err = m5602_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
-	if (err < 0)
-		return err;
-
-	data[1] = (data[1] & 0xfd) | ((val << 1) & 0x02);
+	data[0] = MT9M111_RMB_OVER_SIZED;
+	if (gspca_dev->width == 640) {
+		data[1] = MT9M111_RMB_ROW_SKIP_2X |
+			  MT9M111_RMB_COLUMN_SKIP_2X |
+			  (hflip << 1) | vflip;
+	} else {
+		data[1] = MT9M111_RMB_ROW_SKIP_4X |
+			  MT9M111_RMB_COLUMN_SKIP_4X |
+			  (hflip << 1) | vflip;
+	}
 	err = m5602_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
 					data, 2);
 	return err;
 }
 
-static int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
-
-	*val = sensor_settings[GAIN_IDX];
-	PDEBUG(D_V4L2, "Read gain %d", *val);
-
-	return 0;
-}
-
 static int mt9m111_set_auto_white_balance(struct gspca_dev *gspca_dev,
 					  __s32 val)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
 	int err;
 	u8 data[2];
 
@@ -467,33 +291,19 @@ static int mt9m111_set_auto_white_balance(struct gspca_dev *gspca_dev,
 	if (err < 0)
 		return err;
 
-	sensor_settings[AUTO_WHITE_BALANCE_IDX] = val & 0x01;
 	data[1] = ((data[1] & 0xfd) | ((val & 0x01) << 1));
 
 	err = m5602_write_sensor(sd, MT9M111_CP_OPERATING_MODE_CTL, data, 2);
 
-	PDEBUG(D_V4L2, "Set auto white balance %d", val);
+	PDEBUG(D_CONF, "Set auto white balance %d", val);
 	return err;
 }
 
-static int mt9m111_get_auto_white_balance(struct gspca_dev *gspca_dev,
-					  __s32 *val) {
-	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
-
-	*val = sensor_settings[AUTO_WHITE_BALANCE_IDX];
-	PDEBUG(D_V4L2, "Read auto white balance %d", *val);
-	return 0;
-}
-
 static int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val)
 {
 	int err, tmp;
 	u8 data[2] = {0x00, 0x00};
 	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
-
-	sensor_settings[GAIN_IDX] = val;
 
 	/* Set the correct page map */
 	err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
@@ -518,7 +328,7 @@ static int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val)
 
 	data[1] = (tmp & 0xff);
 	data[0] = (tmp & 0xff00) >> 8;
-	PDEBUG(D_V4L2, "tmp=%d, data[1]=%d, data[0]=%d", tmp,
+	PDEBUG(D_CONF, "tmp=%d, data[1]=%d, data[0]=%d", tmp,
 	       data[1], data[0]);
 
 	err = m5602_write_sensor(sd, MT9M111_SC_GLOBAL_GAIN,
@@ -532,13 +342,11 @@ static int mt9m111_set_green_balance(struct gspca_dev *gspca_dev, __s32 val)
 	int err;
 	u8 data[2];
 	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
 
-	sensor_settings[GREEN_BALANCE_IDX] = val;
 	data[1] = (val & 0xff);
 	data[0] = (val & 0xff00) >> 8;
 
-	PDEBUG(D_V4L2, "Set green balance %d", val);
+	PDEBUG(D_CONF, "Set green balance %d", val);
 	err = m5602_write_sensor(sd, MT9M111_SC_GREEN_1_GAIN,
 				 data, 2);
 	if (err < 0)
@@ -548,66 +356,68 @@ static int mt9m111_set_green_balance(struct gspca_dev *gspca_dev, __s32 val)
 				  data, 2);
 }
 
-static int mt9m111_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
-
-	*val = sensor_settings[GREEN_BALANCE_IDX];
-	PDEBUG(D_V4L2, "Read green balance %d", *val);
-	return 0;
-}
-
 static int mt9m111_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
 {
 	u8 data[2];
 	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
 
-	sensor_settings[BLUE_BALANCE_IDX] = val;
 	data[1] = (val & 0xff);
 	data[0] = (val & 0xff00) >> 8;
 
-	PDEBUG(D_V4L2, "Set blue balance %d", val);
+	PDEBUG(D_CONF, "Set blue balance %d", val);
 
 	return m5602_write_sensor(sd, MT9M111_SC_BLUE_GAIN,
 				  data, 2);
 }
 
-static int mt9m111_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
-
-	*val = sensor_settings[BLUE_BALANCE_IDX];
-	PDEBUG(D_V4L2, "Read blue balance %d", *val);
-	return 0;
-}
-
 static int mt9m111_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
 {
 	u8 data[2];
 	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
 
-	sensor_settings[RED_BALANCE_IDX] = val;
 	data[1] = (val & 0xff);
 	data[0] = (val & 0xff00) >> 8;
 
-	PDEBUG(D_V4L2, "Set red balance %d", val);
+	PDEBUG(D_CONF, "Set red balance %d", val);
 
 	return m5602_write_sensor(sd, MT9M111_SC_RED_GAIN,
 				  data, 2);
 }
 
-static int mt9m111_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val)
+static int mt9m111_s_ctrl(struct v4l2_ctrl *ctrl)
 {
+	struct gspca_dev *gspca_dev =
+		container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
 	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
+	int err;
 
-	*val = sensor_settings[RED_BALANCE_IDX];
-	PDEBUG(D_V4L2, "Read red balance %d", *val);
-	return 0;
+	if (!gspca_dev->streaming)
+		return 0;
+
+	switch (ctrl->id) {
+	case V4L2_CID_AUTO_WHITE_BALANCE:
+		err = mt9m111_set_auto_white_balance(gspca_dev, ctrl->val);
+		if (err || ctrl->val)
+			return err;
+		err = mt9m111_set_green_balance(gspca_dev, sd->green_bal->val);
+		if (err)
+			return err;
+		err = mt9m111_set_red_balance(gspca_dev, sd->red_bal->val);
+		if (err)
+			return err;
+		err = mt9m111_set_blue_balance(gspca_dev, sd->blue_bal->val);
+		break;
+	case V4L2_CID_GAIN:
+		err = mt9m111_set_gain(gspca_dev, ctrl->val);
+		break;
+	case V4L2_CID_HFLIP:
+		err = mt9m111_set_hvflip(gspca_dev);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return err;
 }
 
 static void mt9m111_dump_registers(struct sd *sd)
diff --git a/drivers/media/usb/gspca/m5602/m5602_mt9m111.h b/drivers/media/usb/gspca/m5602/m5602_mt9m111.h
index 8c672b5..07448d3 100644
--- a/drivers/media/usb/gspca/m5602/m5602_mt9m111.h
+++ b/drivers/media/usb/gspca/m5602/m5602_mt9m111.h
@@ -110,6 +110,7 @@ extern bool dump_sensor;
 
 int mt9m111_probe(struct sd *sd);
 int mt9m111_init(struct sd *sd);
+int mt9m111_init_controls(struct sd *sd);
 int mt9m111_start(struct sd *sd);
 void mt9m111_disconnect(struct sd *sd);
 
@@ -121,6 +122,7 @@ static const struct m5602_sensor mt9m111 = {
 
 	.probe = mt9m111_probe,
 	.init = mt9m111_init,
+	.init_controls = mt9m111_init_controls,
 	.disconnect = mt9m111_disconnect,
 	.start = mt9m111_start,
 };
diff --git a/drivers/media/usb/gspca/m5602/m5602_ov7660.c b/drivers/media/usb/gspca/m5602/m5602_ov7660.c
index 9a14835..64b3b03 100644
--- a/drivers/media/usb/gspca/m5602/m5602_ov7660.c
+++ b/drivers/media/usb/gspca/m5602/m5602_ov7660.c
@@ -20,111 +20,8 @@
 
 #include "m5602_ov7660.h"
 
-static int ov7660_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
-static int ov7660_set_gain(struct gspca_dev *gspca_dev, __s32 val);
-static int ov7660_get_auto_white_balance(struct gspca_dev *gspca_dev,
-					 __s32 *val);
-static int ov7660_set_auto_white_balance(struct gspca_dev *gspca_dev,
-					 __s32 val);
-static int ov7660_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val);
-static int ov7660_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val);
-static int ov7660_get_auto_exposure(struct gspca_dev *gspca_dev, __s32 *val);
-static int ov7660_set_auto_exposure(struct gspca_dev *gspca_dev, __s32 val);
-static int ov7660_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
-static int ov7660_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
-static int ov7660_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
-static int ov7660_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
-
-static const struct ctrl ov7660_ctrls[] = {
-#define GAIN_IDX 1
-	{
-		{
-			.id		= V4L2_CID_GAIN,
-			.type		= V4L2_CTRL_TYPE_INTEGER,
-			.name		= "gain",
-			.minimum	= 0x00,
-			.maximum	= 0xff,
-			.step		= 0x1,
-			.default_value	= OV7660_DEFAULT_GAIN,
-			.flags		= V4L2_CTRL_FLAG_SLIDER
-		},
-		.set = ov7660_set_gain,
-		.get = ov7660_get_gain
-	},
-#define BLUE_BALANCE_IDX 2
-#define RED_BALANCE_IDX 3
-#define AUTO_WHITE_BALANCE_IDX 4
-	{
-		{
-			.id		= V4L2_CID_AUTO_WHITE_BALANCE,
-			.type		= V4L2_CTRL_TYPE_BOOLEAN,
-			.name		= "auto white balance",
-			.minimum	= 0,
-			.maximum	= 1,
-			.step		= 1,
-			.default_value	= 1
-		},
-		.set = ov7660_set_auto_white_balance,
-		.get = ov7660_get_auto_white_balance
-	},
-#define AUTO_GAIN_CTRL_IDX 5
-	{
-		{
-			.id		= V4L2_CID_AUTOGAIN,
-			.type		= V4L2_CTRL_TYPE_BOOLEAN,
-			.name		= "auto gain control",
-			.minimum	= 0,
-			.maximum	= 1,
-			.step		= 1,
-			.default_value	= 1
-		},
-		.set = ov7660_set_auto_gain,
-		.get = ov7660_get_auto_gain
-	},
-#define AUTO_EXPOSURE_IDX 6
-	{
-		{
-			.id		= V4L2_CID_EXPOSURE_AUTO,
-			.type		= V4L2_CTRL_TYPE_BOOLEAN,
-			.name		= "auto exposure",
-			.minimum	= 0,
-			.maximum	= 1,
-			.step		= 1,
-			.default_value	= 1
-		},
-		.set = ov7660_set_auto_exposure,
-		.get = ov7660_get_auto_exposure
-	},
-#define HFLIP_IDX 7
-	{
-		{
-			.id		= V4L2_CID_HFLIP,
-			.type		= V4L2_CTRL_TYPE_BOOLEAN,
-			.name		= "horizontal flip",
-			.minimum	= 0,
-			.maximum	= 1,
-			.step		= 1,
-			.default_value	= 0
-		},
-		.set = ov7660_set_hflip,
-		.get = ov7660_get_hflip
-	},
-#define VFLIP_IDX 8
-	{
-		{
-			.id		= V4L2_CID_VFLIP,
-			.type		= V4L2_CTRL_TYPE_BOOLEAN,
-			.name		= "vertical flip",
-			.minimum	= 0,
-			.maximum	= 1,
-			.step		= 1,
-			.default_value	= 0
-		},
-		.set = ov7660_set_vflip,
-		.get = ov7660_get_vflip
-	},
-
-};
+static int ov7660_s_ctrl(struct v4l2_ctrl *ctrl);
+static void ov7660_dump_registers(struct sd *sd);
 
 static struct v4l2_pix_format ov7660_modes[] = {
 	{
@@ -140,15 +37,15 @@ static struct v4l2_pix_format ov7660_modes[] = {
 	}
 };
 
-static void ov7660_dump_registers(struct sd *sd);
+static const struct v4l2_ctrl_ops ov7660_ctrl_ops = {
+	.s_ctrl = ov7660_s_ctrl,
+};
 
 int ov7660_probe(struct sd *sd)
 {
 	int err = 0, i;
 	u8 prod_id = 0, ver_id = 0;
 
-	s32 *sensor_settings;
-
 	if (force_sensor) {
 		if (force_sensor == OV7660_SENSOR) {
 			pr_info("Forcing an %s sensor\n", ov7660.name);
@@ -191,27 +88,15 @@ int ov7660_probe(struct sd *sd)
 	return -ENODEV;
 
 sensor_found:
-	sensor_settings = kmalloc(
-		ARRAY_SIZE(ov7660_ctrls) * sizeof(s32), GFP_KERNEL);
-	if (!sensor_settings)
-		return -ENOMEM;
-
 	sd->gspca_dev.cam.cam_mode = ov7660_modes;
 	sd->gspca_dev.cam.nmodes = ARRAY_SIZE(ov7660_modes);
-	sd->desc->ctrls = ov7660_ctrls;
-	sd->desc->nctrls = ARRAY_SIZE(ov7660_ctrls);
-
-	for (i = 0; i < ARRAY_SIZE(ov7660_ctrls); i++)
-		sensor_settings[i] = ov7660_ctrls[i].qctrl.default_value;
-	sd->sensor_priv = sensor_settings;
 
 	return 0;
 }
 
 int ov7660_init(struct sd *sd)
 {
-	int i, err = 0;
-	s32 *sensor_settings = sd->sensor_priv;
+	int i, err;
 
 	/* Init the sensor */
 	for (i = 0; i < ARRAY_SIZE(init_ov7660); i++) {
@@ -226,38 +111,47 @@ int ov7660_init(struct sd *sd)
 			err = m5602_write_sensor(sd,
 				init_ov7660[i][1], data, 1);
 		}
+		if (err < 0)
+			return err;
 	}
 
 	if (dump_sensor)
 		ov7660_dump_registers(sd);
 
-	err = ov7660_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
-	if (err < 0)
-		return err;
+	return 0;
+}
 
-	err = ov7660_set_auto_white_balance(&sd->gspca_dev,
-		sensor_settings[AUTO_WHITE_BALANCE_IDX]);
-	if (err < 0)
-		return err;
+int ov7660_init_controls(struct sd *sd)
+{
+	struct v4l2_ctrl_handler *hdl = &sd->gspca_dev.ctrl_handler;
 
-	err = ov7660_set_auto_gain(&sd->gspca_dev,
-		sensor_settings[AUTO_GAIN_CTRL_IDX]);
-	if (err < 0)
-		return err;
+	sd->gspca_dev.vdev.ctrl_handler = hdl;
+	v4l2_ctrl_handler_init(hdl, 6);
 
-	err = ov7660_set_auto_exposure(&sd->gspca_dev,
-		sensor_settings[AUTO_EXPOSURE_IDX]);
-	if (err < 0)
-		return err;
-	err = ov7660_set_hflip(&sd->gspca_dev,
-		sensor_settings[HFLIP_IDX]);
-	if (err < 0)
-		return err;
+	v4l2_ctrl_new_std(hdl, &ov7660_ctrl_ops, V4L2_CID_AUTO_WHITE_BALANCE,
+			  0, 1, 1, 1);
+	v4l2_ctrl_new_std_menu(hdl, &ov7660_ctrl_ops,
+			  V4L2_CID_EXPOSURE_AUTO, 1, 0, V4L2_EXPOSURE_AUTO);
 
-	err = ov7660_set_vflip(&sd->gspca_dev,
-		sensor_settings[VFLIP_IDX]);
+	sd->autogain = v4l2_ctrl_new_std(hdl, &ov7660_ctrl_ops,
+					 V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
+	sd->gain = v4l2_ctrl_new_std(hdl, &ov7660_ctrl_ops, V4L2_CID_GAIN, 0,
+				     255, 1, OV7660_DEFAULT_GAIN);
 
-	return err;
+	sd->hflip = v4l2_ctrl_new_std(hdl, &ov7660_ctrl_ops, V4L2_CID_HFLIP,
+				      0, 1, 1, 0);
+	sd->vflip = v4l2_ctrl_new_std(hdl, &ov7660_ctrl_ops, V4L2_CID_VFLIP,
+				      0, 1, 1, 0);
+
+	if (hdl->error) {
+		pr_err("Could not initialize controls\n");
+		return hdl->error;
+	}
+
+	v4l2_ctrl_auto_cluster(2, &sd->autogain, 0, false);
+	v4l2_ctrl_cluster(2, &sd->hflip);
+
+	return 0;
 }
 
 int ov7660_start(struct sd *sd)
@@ -275,56 +169,29 @@ void ov7660_disconnect(struct sd *sd)
 	ov7660_stop(sd);
 
 	sd->sensor = NULL;
-	kfree(sd->sensor_priv);
-}
-
-static int ov7660_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
-
-	*val = sensor_settings[GAIN_IDX];
-	PDEBUG(D_V4L2, "Read gain %d", *val);
-	return 0;
 }
 
 static int ov7660_set_gain(struct gspca_dev *gspca_dev, __s32 val)
 {
 	int err;
-	u8 i2c_data;
+	u8 i2c_data = val;
 	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
 
-	PDEBUG(D_V4L2, "Setting gain to %d", val);
-
-	sensor_settings[GAIN_IDX] = val;
+	PDEBUG(D_CONF, "Setting gain to %d", val);
 
 	err = m5602_write_sensor(sd, OV7660_GAIN, &i2c_data, 1);
 	return err;
 }
 
-
-static int ov7660_get_auto_white_balance(struct gspca_dev *gspca_dev,
-					 __s32 *val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
-
-	*val = sensor_settings[AUTO_WHITE_BALANCE_IDX];
-	return 0;
-}
-
 static int ov7660_set_auto_white_balance(struct gspca_dev *gspca_dev,
 					 __s32 val)
 {
 	int err;
 	u8 i2c_data;
 	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
 
-	PDEBUG(D_V4L2, "Set auto white balance to %d", val);
+	PDEBUG(D_CONF, "Set auto white balance to %d", val);
 
-	sensor_settings[AUTO_WHITE_BALANCE_IDX] = val;
 	err = m5602_read_sensor(sd, OV7660_COM8, &i2c_data, 1);
 	if (err < 0)
 		return err;
@@ -335,26 +202,14 @@ static int ov7660_set_auto_white_balance(struct gspca_dev *gspca_dev,
 	return err;
 }
 
-static int ov7660_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
-
-	*val = sensor_settings[AUTO_GAIN_CTRL_IDX];
-	PDEBUG(D_V4L2, "Read auto gain control %d", *val);
-	return 0;
-}
-
 static int ov7660_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val)
 {
 	int err;
 	u8 i2c_data;
 	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
 
-	PDEBUG(D_V4L2, "Set auto gain control to %d", val);
+	PDEBUG(D_CONF, "Set auto gain control to %d", val);
 
-	sensor_settings[AUTO_GAIN_CTRL_IDX] = val;
 	err = m5602_read_sensor(sd, OV7660_COM8, &i2c_data, 1);
 	if (err < 0)
 		return err;
@@ -364,94 +219,69 @@ static int ov7660_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val)
 	return m5602_write_sensor(sd, OV7660_COM8, &i2c_data, 1);
 }
 
-static int ov7660_get_auto_exposure(struct gspca_dev *gspca_dev, __s32 *val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
-
-	*val = sensor_settings[AUTO_EXPOSURE_IDX];
-	PDEBUG(D_V4L2, "Read auto exposure control %d", *val);
-	return 0;
-}
-
 static int ov7660_set_auto_exposure(struct gspca_dev *gspca_dev,
 				    __s32 val)
 {
 	int err;
 	u8 i2c_data;
 	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
 
-	PDEBUG(D_V4L2, "Set auto exposure control to %d", val);
+	PDEBUG(D_CONF, "Set auto exposure control to %d", val);
 
-	sensor_settings[AUTO_EXPOSURE_IDX] = val;
 	err = m5602_read_sensor(sd, OV7660_COM8, &i2c_data, 1);
 	if (err < 0)
 		return err;
 
+	val = (val == V4L2_EXPOSURE_AUTO);
 	i2c_data = ((i2c_data & 0xfe) | ((val & 0x01) << 0));
 
 	return m5602_write_sensor(sd, OV7660_COM8, &i2c_data, 1);
 }
 
-static int ov7660_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
-
-	*val = sensor_settings[HFLIP_IDX];
-	PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
-	return 0;
-}
-
-static int ov7660_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
+static int ov7660_set_hvflip(struct gspca_dev *gspca_dev)
 {
 	int err;
 	u8 i2c_data;
 	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
 
-	PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
+	PDEBUG(D_CONF, "Set hvflip to %d, %d", sd->hflip->val, sd->vflip->val);
 
-	sensor_settings[HFLIP_IDX] = val;
-
-	i2c_data = ((val & 0x01) << 5) |
-		(sensor_settings[VFLIP_IDX] << 4);
+	i2c_data = (sd->hflip->val << 5) | (sd->vflip->val << 4);
 
 	err = m5602_write_sensor(sd, OV7660_MVFP, &i2c_data, 1);
 
 	return err;
 }
 
-static int ov7660_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
+static int ov7660_s_ctrl(struct v4l2_ctrl *ctrl)
 {
+	struct gspca_dev *gspca_dev =
+		container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
 	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
-
-	*val = sensor_settings[VFLIP_IDX];
-	PDEBUG(D_V4L2, "Read vertical flip %d", *val);
-
-	return 0;
-}
-
-static int ov7660_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
-{
 	int err;
-	u8 i2c_data;
-	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
-
-	PDEBUG(D_V4L2, "Set vertical flip to %d", val);
-	sensor_settings[VFLIP_IDX] = val;
 
-	i2c_data = ((val & 0x01) << 4) | (sensor_settings[VFLIP_IDX] << 5);
-	err = m5602_write_sensor(sd, OV7660_MVFP, &i2c_data, 1);
-	if (err < 0)
-		return err;
-
-	/* When vflip is toggled we need to readjust the bridge hsync/vsync */
-	if (gspca_dev->streaming)
-		err = ov7660_start(sd);
+	if (!gspca_dev->streaming)
+		return 0;
+
+	switch (ctrl->id) {
+	case V4L2_CID_AUTO_WHITE_BALANCE:
+		err = ov7660_set_auto_white_balance(gspca_dev, ctrl->val);
+		break;
+	case V4L2_CID_EXPOSURE_AUTO:
+		err = ov7660_set_auto_exposure(gspca_dev, ctrl->val);
+		break;
+	case V4L2_CID_AUTOGAIN:
+		err = ov7660_set_auto_gain(gspca_dev, ctrl->val);
+		if (err || ctrl->val)
+			return err;
+		err = ov7660_set_gain(gspca_dev, sd->gain->val);
+		break;
+	case V4L2_CID_HFLIP:
+		err = ov7660_set_hvflip(gspca_dev);
+		break;
+	default:
+		return -EINVAL;
+	}
 
 	return err;
 }
diff --git a/drivers/media/usb/gspca/m5602/m5602_ov7660.h b/drivers/media/usb/gspca/m5602/m5602_ov7660.h
index 2b6a13b..6fece1c 100644
--- a/drivers/media/usb/gspca/m5602/m5602_ov7660.h
+++ b/drivers/media/usb/gspca/m5602/m5602_ov7660.h
@@ -90,6 +90,8 @@ extern bool dump_sensor;
 
 int ov7660_probe(struct sd *sd);
 int ov7660_init(struct sd *sd);
+int ov7660_init(struct sd *sd);
+int ov7660_init_controls(struct sd *sd);
 int ov7660_start(struct sd *sd);
 int ov7660_stop(struct sd *sd);
 void ov7660_disconnect(struct sd *sd);
@@ -100,6 +102,7 @@ static const struct m5602_sensor ov7660 = {
 	.i2c_regW = 1,
 	.probe = ov7660_probe,
 	.init = ov7660_init,
+	.init_controls = ov7660_init_controls,
 	.start = ov7660_start,
 	.stop = ov7660_stop,
 	.disconnect = ov7660_disconnect,
diff --git a/drivers/media/usb/gspca/m5602/m5602_ov9650.c b/drivers/media/usb/gspca/m5602/m5602_ov9650.c
index 2114a8b..59bc62b 100644
--- a/drivers/media/usb/gspca/m5602/m5602_ov9650.c
+++ b/drivers/media/usb/gspca/m5602/m5602_ov9650.c
@@ -20,26 +20,8 @@
 
 #include "m5602_ov9650.h"
 
-static int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
-static int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
-static int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
-static int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val);
-static int ov9650_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val);
-static int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val);
-static int ov9650_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val);
-static int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val);
-static int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
-static int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
-static int ov9650_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
-static int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
-static int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev,
-					 __s32 *val);
-static int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev,
-					 __s32 val);
-static int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val);
-static int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val);
-static int ov9650_get_auto_exposure(struct gspca_dev *gspca_dev, __s32 *val);
-static int ov9650_set_auto_exposure(struct gspca_dev *gspca_dev, __s32 val);
+static int ov9650_s_ctrl(struct v4l2_ctrl *ctrl);
+static void ov9650_dump_registers(struct sd *sd);
 
 /* Vertically and horizontally flips the image if matched, needed for machines
    where the sensor is mounted upside down */
@@ -113,140 +95,6 @@ static
 	{}
 };
 
-static const struct ctrl ov9650_ctrls[] = {
-#define EXPOSURE_IDX 0
-	{
-		{
-			.id		= V4L2_CID_EXPOSURE,
-			.type		= V4L2_CTRL_TYPE_INTEGER,
-			.name		= "exposure",
-			.minimum	= 0x00,
-			.maximum	= 0x1ff,
-			.step		= 0x4,
-			.default_value	= EXPOSURE_DEFAULT,
-			.flags		= V4L2_CTRL_FLAG_SLIDER
-		},
-		.set = ov9650_set_exposure,
-		.get = ov9650_get_exposure
-	},
-#define GAIN_IDX 1
-	{
-		{
-			.id		= V4L2_CID_GAIN,
-			.type		= V4L2_CTRL_TYPE_INTEGER,
-			.name		= "gain",
-			.minimum	= 0x00,
-			.maximum	= 0x3ff,
-			.step		= 0x1,
-			.default_value	= GAIN_DEFAULT,
-			.flags		= V4L2_CTRL_FLAG_SLIDER
-		},
-		.set = ov9650_set_gain,
-		.get = ov9650_get_gain
-	},
-#define RED_BALANCE_IDX 2
-	{
-		{
-			.id		= V4L2_CID_RED_BALANCE,
-			.type		= V4L2_CTRL_TYPE_INTEGER,
-			.name		= "red balance",
-			.minimum	= 0x00,
-			.maximum	= 0xff,
-			.step		= 0x1,
-			.default_value	= RED_GAIN_DEFAULT,
-			.flags		= V4L2_CTRL_FLAG_SLIDER
-		},
-		.set = ov9650_set_red_balance,
-		.get = ov9650_get_red_balance
-	},
-#define BLUE_BALANCE_IDX 3
-	{
-		{
-			.id		= V4L2_CID_BLUE_BALANCE,
-			.type		= V4L2_CTRL_TYPE_INTEGER,
-			.name		= "blue balance",
-			.minimum	= 0x00,
-			.maximum	= 0xff,
-			.step		= 0x1,
-			.default_value	= BLUE_GAIN_DEFAULT,
-			.flags		= V4L2_CTRL_FLAG_SLIDER
-		},
-		.set = ov9650_set_blue_balance,
-		.get = ov9650_get_blue_balance
-	},
-#define HFLIP_IDX 4
-	{
-		{
-			.id		= V4L2_CID_HFLIP,
-			.type		= V4L2_CTRL_TYPE_BOOLEAN,
-			.name		= "horizontal flip",
-			.minimum	= 0,
-			.maximum	= 1,
-			.step		= 1,
-			.default_value	= 0
-		},
-		.set = ov9650_set_hflip,
-		.get = ov9650_get_hflip
-	},
-#define VFLIP_IDX 5
-	{
-		{
-			.id		= V4L2_CID_VFLIP,
-			.type		= V4L2_CTRL_TYPE_BOOLEAN,
-			.name		= "vertical flip",
-			.minimum	= 0,
-			.maximum	= 1,
-			.step		= 1,
-			.default_value	= 0
-		},
-		.set = ov9650_set_vflip,
-		.get = ov9650_get_vflip
-	},
-#define AUTO_WHITE_BALANCE_IDX 6
-	{
-		{
-			.id		= V4L2_CID_AUTO_WHITE_BALANCE,
-			.type		= V4L2_CTRL_TYPE_BOOLEAN,
-			.name		= "auto white balance",
-			.minimum	= 0,
-			.maximum	= 1,
-			.step		= 1,
-			.default_value	= 1
-		},
-		.set = ov9650_set_auto_white_balance,
-		.get = ov9650_get_auto_white_balance
-	},
-#define AUTO_GAIN_CTRL_IDX 7
-	{
-		{
-			.id		= V4L2_CID_AUTOGAIN,
-			.type		= V4L2_CTRL_TYPE_BOOLEAN,
-			.name		= "auto gain control",
-			.minimum	= 0,
-			.maximum	= 1,
-			.step		= 1,
-			.default_value	= 1
-		},
-		.set = ov9650_set_auto_gain,
-		.get = ov9650_get_auto_gain
-	},
-#define AUTO_EXPOSURE_IDX 8
-	{
-		{
-			.id		= V4L2_CID_EXPOSURE_AUTO,
-			.type		= V4L2_CTRL_TYPE_BOOLEAN,
-			.name		= "auto exposure",
-			.minimum	= 0,
-			.maximum	= 1,
-			.step		= 1,
-			.default_value	= 1
-		},
-		.set = ov9650_set_auto_exposure,
-		.get = ov9650_get_auto_exposure
-	}
-
-};
-
 static struct v4l2_pix_format ov9650_modes[] = {
 	{
 		176,
@@ -291,13 +139,15 @@ static struct v4l2_pix_format ov9650_modes[] = {
 	}
 };
 
-static void ov9650_dump_registers(struct sd *sd);
+static const struct v4l2_ctrl_ops ov9650_ctrl_ops = {
+	.s_ctrl = ov9650_s_ctrl,
+};
 
 int ov9650_probe(struct sd *sd)
 {
 	int err = 0;
 	u8 prod_id = 0, ver_id = 0, i;
-	s32 *sensor_settings;
+	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
 
 	if (force_sensor) {
 		if (force_sensor == OV9650_SENSOR) {
@@ -338,19 +188,9 @@ int ov9650_probe(struct sd *sd)
 	return -ENODEV;
 
 sensor_found:
-	sensor_settings = kmalloc(
-		ARRAY_SIZE(ov9650_ctrls) * sizeof(s32), GFP_KERNEL);
-	if (!sensor_settings)
-		return -ENOMEM;
-
 	sd->gspca_dev.cam.cam_mode = ov9650_modes;
 	sd->gspca_dev.cam.nmodes = ARRAY_SIZE(ov9650_modes);
-	sd->desc->ctrls = ov9650_ctrls;
-	sd->desc->nctrls = ARRAY_SIZE(ov9650_ctrls);
 
-	for (i = 0; i < ARRAY_SIZE(ov9650_ctrls); i++)
-		sensor_settings[i] = ov9650_ctrls[i].qctrl.default_value;
-	sd->sensor_priv = sensor_settings;
 	return 0;
 }
 
@@ -358,7 +198,6 @@ int ov9650_init(struct sd *sd)
 {
 	int i, err = 0;
 	u8 data;
-	s32 *sensor_settings = sd->sensor_priv;
 
 	if (dump_sensor)
 		ov9650_dump_registers(sd);
@@ -372,46 +211,52 @@ int ov9650_init(struct sd *sd)
 			err = m5602_write_bridge(sd, init_ov9650[i][1], data);
 	}
 
-	err = ov9650_set_exposure(&sd->gspca_dev,
-				   sensor_settings[EXPOSURE_IDX]);
-	if (err < 0)
-		return err;
-
-	err = ov9650_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
-	if (err < 0)
-		return err;
-
-	err = ov9650_set_red_balance(&sd->gspca_dev,
-				      sensor_settings[RED_BALANCE_IDX]);
-	if (err < 0)
-		return err;
-
-	err = ov9650_set_blue_balance(&sd->gspca_dev,
-				       sensor_settings[BLUE_BALANCE_IDX]);
-	if (err < 0)
-		return err;
-
-	err = ov9650_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]);
-	if (err < 0)
-		return err;
-
-	err = ov9650_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]);
-	if (err < 0)
-		return err;
+	return 0;
+}
 
-	err = ov9650_set_auto_exposure(&sd->gspca_dev,
-				sensor_settings[AUTO_EXPOSURE_IDX]);
-	if (err < 0)
-		return err;
+int ov9650_init_controls(struct sd *sd)
+{
+	struct v4l2_ctrl_handler *hdl = &sd->gspca_dev.ctrl_handler;
+
+	sd->gspca_dev.vdev.ctrl_handler = hdl;
+	v4l2_ctrl_handler_init(hdl, 9);
+
+	sd->auto_white_bal = v4l2_ctrl_new_std(hdl, &ov9650_ctrl_ops,
+					       V4L2_CID_AUTO_WHITE_BALANCE,
+					       0, 1, 1, 1);
+	sd->red_bal = v4l2_ctrl_new_std(hdl, &ov9650_ctrl_ops,
+					V4L2_CID_RED_BALANCE, 0, 255, 1,
+					RED_GAIN_DEFAULT);
+	sd->blue_bal = v4l2_ctrl_new_std(hdl, &ov9650_ctrl_ops,
+					V4L2_CID_BLUE_BALANCE, 0, 255, 1,
+					BLUE_GAIN_DEFAULT);
+
+	sd->autoexpo = v4l2_ctrl_new_std_menu(hdl, &ov9650_ctrl_ops,
+			  V4L2_CID_EXPOSURE_AUTO, 1, 0, V4L2_EXPOSURE_AUTO);
+	sd->expo = v4l2_ctrl_new_std(hdl, &ov9650_ctrl_ops, V4L2_CID_EXPOSURE,
+			  0, 0x1ff, 4, EXPOSURE_DEFAULT);
+
+	sd->autogain = v4l2_ctrl_new_std(hdl, &ov9650_ctrl_ops,
+					 V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
+	sd->gain = v4l2_ctrl_new_std(hdl, &ov9650_ctrl_ops, V4L2_CID_GAIN, 0,
+				     0x3ff, 1, GAIN_DEFAULT);
+
+	sd->hflip = v4l2_ctrl_new_std(hdl, &ov9650_ctrl_ops, V4L2_CID_HFLIP,
+				      0, 1, 1, 0);
+	sd->vflip = v4l2_ctrl_new_std(hdl, &ov9650_ctrl_ops, V4L2_CID_VFLIP,
+				      0, 1, 1, 0);
+
+	if (hdl->error) {
+		pr_err("Could not initialize controls\n");
+		return hdl->error;
+	}
 
-	err = ov9650_set_auto_white_balance(&sd->gspca_dev,
-				sensor_settings[AUTO_WHITE_BALANCE_IDX]);
-	if (err < 0)
-		return err;
+	v4l2_ctrl_auto_cluster(3, &sd->auto_white_bal, 0, false);
+	v4l2_ctrl_auto_cluster(2, &sd->autoexpo, 0, false);
+	v4l2_ctrl_auto_cluster(2, &sd->autogain, 0, false);
+	v4l2_ctrl_cluster(2, &sd->hflip);
 
-	err = ov9650_set_auto_gain(&sd->gspca_dev,
-				sensor_settings[AUTO_GAIN_CTRL_IDX]);
-	return err;
+	return 0;
 }
 
 int ov9650_start(struct sd *sd)
@@ -419,17 +264,17 @@ int ov9650_start(struct sd *sd)
 	u8 data;
 	int i, err = 0;
 	struct cam *cam = &sd->gspca_dev.cam;
-	s32 *sensor_settings = sd->sensor_priv;
 
 	int width = cam->cam_mode[sd->gspca_dev.curr_mode].width;
 	int height = cam->cam_mode[sd->gspca_dev.curr_mode].height;
 	int ver_offs = cam->cam_mode[sd->gspca_dev.curr_mode].priv;
 	int hor_offs = OV9650_LEFT_OFFSET;
+	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
 
 	if ((!dmi_check_system(ov9650_flip_dmi_table) &&
-		sensor_settings[VFLIP_IDX]) ||
+		sd->vflip->val) ||
 		(dmi_check_system(ov9650_flip_dmi_table) &&
-		!sensor_settings[VFLIP_IDX]))
+		!sd->vflip->val))
 		ver_offs--;
 
 	if (width <= 320)
@@ -508,7 +353,7 @@ int ov9650_start(struct sd *sd)
 
 	switch (width) {
 	case 640:
-		PDEBUG(D_V4L2, "Configuring camera for VGA mode");
+		PDEBUG(D_CONF, "Configuring camera for VGA mode");
 
 		data = OV9650_VGA_SELECT | OV9650_RGB_SELECT |
 		       OV9650_RAW_RGB_SELECT;
@@ -516,7 +361,7 @@ int ov9650_start(struct sd *sd)
 		break;
 
 	case 352:
-		PDEBUG(D_V4L2, "Configuring camera for CIF mode");
+		PDEBUG(D_CONF, "Configuring camera for CIF mode");
 
 		data = OV9650_CIF_SELECT | OV9650_RGB_SELECT |
 				OV9650_RAW_RGB_SELECT;
@@ -524,7 +369,7 @@ int ov9650_start(struct sd *sd)
 		break;
 
 	case 320:
-		PDEBUG(D_V4L2, "Configuring camera for QVGA mode");
+		PDEBUG(D_CONF, "Configuring camera for QVGA mode");
 
 		data = OV9650_QVGA_SELECT | OV9650_RGB_SELECT |
 				OV9650_RAW_RGB_SELECT;
@@ -532,7 +377,7 @@ int ov9650_start(struct sd *sd)
 		break;
 
 	case 176:
-		PDEBUG(D_V4L2, "Configuring camera for QCIF mode");
+		PDEBUG(D_CONF, "Configuring camera for QCIF mode");
 
 		data = OV9650_QCIF_SELECT | OV9650_RGB_SELECT |
 			OV9650_RAW_RGB_SELECT;
@@ -553,29 +398,16 @@ void ov9650_disconnect(struct sd *sd)
 	ov9650_stop(sd);
 
 	sd->sensor = NULL;
-	kfree(sd->sensor_priv);
-}
-
-static int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
-
-	*val = sensor_settings[EXPOSURE_IDX];
-	PDEBUG(D_V4L2, "Read exposure %d", *val);
-	return 0;
 }
 
 static int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
 	u8 i2c_data;
 	int err;
 
-	PDEBUG(D_V4L2, "Set exposure to %d", val);
+	PDEBUG(D_CONF, "Set exposure to %d", val);
 
-	sensor_settings[EXPOSURE_IDX] = val;
 	/* The 6 MSBs */
 	i2c_data = (val >> 10) & 0x3f;
 	err = m5602_write_sensor(sd, OV9650_AECHM,
@@ -596,26 +428,13 @@ static int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
 	return err;
 }
 
-static int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
-
-	*val = sensor_settings[GAIN_IDX];
-	PDEBUG(D_V4L2, "Read gain %d", *val);
-	return 0;
-}
-
 static int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val)
 {
 	int err;
 	u8 i2c_data;
 	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
 
-	PDEBUG(D_V4L2, "Setting gain to %d", val);
-
-	sensor_settings[GAIN_IDX] = val;
+	PDEBUG(D_CONF, "Setting gain to %d", val);
 
 	/* The 2 MSB */
 	/* Read the OV9650_VREF register first to avoid
@@ -637,117 +456,46 @@ static int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val)
 	return err;
 }
 
-static int ov9650_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
-
-	*val = sensor_settings[RED_BALANCE_IDX];
-	PDEBUG(D_V4L2, "Read red gain %d", *val);
-	return 0;
-}
-
 static int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
 {
 	int err;
 	u8 i2c_data;
 	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
 
-	PDEBUG(D_V4L2, "Set red gain to %d", val);
-
-	sensor_settings[RED_BALANCE_IDX] = val;
+	PDEBUG(D_CONF, "Set red gain to %d", val);
 
 	i2c_data = val & 0xff;
 	err = m5602_write_sensor(sd, OV9650_RED, &i2c_data, 1);
 	return err;
 }
 
-static int ov9650_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
-
-	*val = sensor_settings[BLUE_BALANCE_IDX];
-	PDEBUG(D_V4L2, "Read blue gain %d", *val);
-
-	return 0;
-}
-
 static int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
 {
 	int err;
 	u8 i2c_data;
 	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
-
-	PDEBUG(D_V4L2, "Set blue gain to %d", val);
 
-	sensor_settings[BLUE_BALANCE_IDX] = val;
+	PDEBUG(D_CONF, "Set blue gain to %d", val);
 
 	i2c_data = val & 0xff;
 	err = m5602_write_sensor(sd, OV9650_BLUE, &i2c_data, 1);
 	return err;
 }
 
-static int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
-
-	*val = sensor_settings[HFLIP_IDX];
-	PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
-	return 0;
-}
-
-static int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
+static int ov9650_set_hvflip(struct gspca_dev *gspca_dev)
 {
 	int err;
 	u8 i2c_data;
 	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
+	int hflip = sd->hflip->val;
+	int vflip = sd->vflip->val;
 
-	PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
-
-	sensor_settings[HFLIP_IDX] = val;
-
-	if (!dmi_check_system(ov9650_flip_dmi_table))
-		i2c_data = ((val & 0x01) << 5) |
-				(sensor_settings[VFLIP_IDX] << 4);
-	else
-		i2c_data = ((val & 0x01) << 5) |
-				(!sensor_settings[VFLIP_IDX] << 4);
-
-	err = m5602_write_sensor(sd, OV9650_MVFP, &i2c_data, 1);
-
-	return err;
-}
-
-static int ov9650_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
-
-	*val = sensor_settings[VFLIP_IDX];
-	PDEBUG(D_V4L2, "Read vertical flip %d", *val);
-
-	return 0;
-}
-
-static int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
-{
-	int err;
-	u8 i2c_data;
-	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
-
-	PDEBUG(D_V4L2, "Set vertical flip to %d", val);
-	sensor_settings[VFLIP_IDX] = val;
+	PDEBUG(D_CONF, "Set hvflip to %d %d", hflip, vflip);
 
 	if (dmi_check_system(ov9650_flip_dmi_table))
-		val = !val;
+		vflip = !vflip;
 
-	i2c_data = ((val & 0x01) << 4) | (sensor_settings[VFLIP_IDX] << 5);
+	i2c_data = (hflip << 5) | (vflip << 4);
 	err = m5602_write_sensor(sd, OV9650_MVFP, &i2c_data, 1);
 	if (err < 0)
 		return err;
@@ -759,57 +507,34 @@ static int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
 	return err;
 }
 
-static int ov9650_get_auto_exposure(struct gspca_dev *gspca_dev, __s32 *val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
-
-	*val = sensor_settings[AUTO_EXPOSURE_IDX];
-	PDEBUG(D_V4L2, "Read auto exposure control %d", *val);
-	return 0;
-}
-
 static int ov9650_set_auto_exposure(struct gspca_dev *gspca_dev,
 				    __s32 val)
 {
 	int err;
 	u8 i2c_data;
 	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
 
-	PDEBUG(D_V4L2, "Set auto exposure control to %d", val);
+	PDEBUG(D_CONF, "Set auto exposure control to %d", val);
 
-	sensor_settings[AUTO_EXPOSURE_IDX] = val;
 	err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
 	if (err < 0)
 		return err;
 
+	val = (val == V4L2_EXPOSURE_AUTO);
 	i2c_data = ((i2c_data & 0xfe) | ((val & 0x01) << 0));
 
 	return m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1);
 }
 
-static int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev,
-					 __s32 *val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
-
-	*val = sensor_settings[AUTO_WHITE_BALANCE_IDX];
-	return 0;
-}
-
 static int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev,
 					 __s32 val)
 {
 	int err;
 	u8 i2c_data;
 	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
 
-	PDEBUG(D_V4L2, "Set auto white balance to %d", val);
+	PDEBUG(D_CONF, "Set auto white balance to %d", val);
 
-	sensor_settings[AUTO_WHITE_BALANCE_IDX] = val;
 	err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
 	if (err < 0)
 		return err;
@@ -820,26 +545,14 @@ static int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev,
 	return err;
 }
 
-static int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
-
-	*val = sensor_settings[AUTO_GAIN_CTRL_IDX];
-	PDEBUG(D_V4L2, "Read auto gain control %d", *val);
-	return 0;
-}
-
 static int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val)
 {
 	int err;
 	u8 i2c_data;
 	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
 
-	PDEBUG(D_V4L2, "Set auto gain control to %d", val);
+	PDEBUG(D_CONF, "Set auto gain control to %d", val);
 
-	sensor_settings[AUTO_GAIN_CTRL_IDX] = val;
 	err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
 	if (err < 0)
 		return err;
@@ -849,6 +562,48 @@ static int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val)
 	return m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1);
 }
 
+static int ov9650_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct gspca_dev *gspca_dev =
+		container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
+	struct sd *sd = (struct sd *) gspca_dev;
+	int err;
+
+	if (!gspca_dev->streaming)
+		return 0;
+
+	switch (ctrl->id) {
+	case V4L2_CID_AUTO_WHITE_BALANCE:
+		err = ov9650_set_auto_white_balance(gspca_dev, ctrl->val);
+		if (err || ctrl->val)
+			return err;
+		err = ov9650_set_red_balance(gspca_dev, sd->red_bal->val);
+		if (err)
+			return err;
+		err = ov9650_set_blue_balance(gspca_dev, sd->blue_bal->val);
+		break;
+	case V4L2_CID_EXPOSURE_AUTO:
+		err = ov9650_set_auto_exposure(gspca_dev, ctrl->val);
+		if (err || ctrl->val == V4L2_EXPOSURE_AUTO)
+			return err;
+		err = ov9650_set_exposure(gspca_dev, sd->expo->val);
+		break;
+	case V4L2_CID_AUTOGAIN:
+		err = ov9650_set_auto_gain(gspca_dev, ctrl->val);
+		if (err || ctrl->val)
+			return err;
+		err = ov9650_set_gain(gspca_dev, sd->gain->val);
+		break;
+	case V4L2_CID_HFLIP:
+		err = ov9650_set_hvflip(gspca_dev);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return err;
+}
+
 static void ov9650_dump_registers(struct sd *sd)
 {
 	int address;
diff --git a/drivers/media/usb/gspca/m5602/m5602_ov9650.h b/drivers/media/usb/gspca/m5602/m5602_ov9650.h
index f7aa5bf..f9f5870 100644
--- a/drivers/media/usb/gspca/m5602/m5602_ov9650.h
+++ b/drivers/media/usb/gspca/m5602/m5602_ov9650.h
@@ -139,6 +139,7 @@ extern bool dump_sensor;
 
 int ov9650_probe(struct sd *sd);
 int ov9650_init(struct sd *sd);
+int ov9650_init_controls(struct sd *sd);
 int ov9650_start(struct sd *sd);
 int ov9650_stop(struct sd *sd);
 void ov9650_disconnect(struct sd *sd);
@@ -149,6 +150,7 @@ static const struct m5602_sensor ov9650 = {
 	.i2c_regW = 1,
 	.probe = ov9650_probe,
 	.init = ov9650_init,
+	.init_controls = ov9650_init_controls,
 	.start = ov9650_start,
 	.stop = ov9650_stop,
 	.disconnect = ov9650_disconnect,
diff --git a/drivers/media/usb/gspca/m5602/m5602_po1030.c b/drivers/media/usb/gspca/m5602/m5602_po1030.c
index b877169..4bf5c43 100644
--- a/drivers/media/usb/gspca/m5602/m5602_po1030.c
+++ b/drivers/media/usb/gspca/m5602/m5602_po1030.c
@@ -20,28 +20,8 @@
 
 #include "m5602_po1030.h"
 
-static int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
-static int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
-static int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
-static int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val);
-static int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val);
-static int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val);
-static int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val);
-static int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val);
-static int po1030_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val);
-static int po1030_set_green_balance(struct gspca_dev *gspca_dev, __s32 val);
-static int po1030_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
-static int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
-static int po1030_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
-static int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
-static int po1030_set_auto_white_balance(struct gspca_dev *gspca_dev,
-					 __s32 val);
-static int po1030_get_auto_white_balance(struct gspca_dev *gspca_dev,
-					 __s32 *val);
-static int po1030_set_auto_exposure(struct gspca_dev *gspca_dev,
-					 __s32 val);
-static int po1030_get_auto_exposure(struct gspca_dev *gspca_dev,
-					 __s32 *val);
+static int po1030_s_ctrl(struct v4l2_ctrl *ctrl);
+static void po1030_dump_registers(struct sd *sd);
 
 static struct v4l2_pix_format po1030_modes[] = {
 	{
@@ -56,146 +36,26 @@ static struct v4l2_pix_format po1030_modes[] = {
 	}
 };
 
-static const struct ctrl po1030_ctrls[] = {
-#define GAIN_IDX 0
-	{
-		{
-			.id		= V4L2_CID_GAIN,
-			.type		= V4L2_CTRL_TYPE_INTEGER,
-			.name		= "gain",
-			.minimum	= 0x00,
-			.maximum	= 0x4f,
-			.step		= 0x1,
-			.default_value	= PO1030_GLOBAL_GAIN_DEFAULT,
-			.flags		= V4L2_CTRL_FLAG_SLIDER
-		},
-		.set = po1030_set_gain,
-		.get = po1030_get_gain
-	},
-#define EXPOSURE_IDX 1
-	{
-		{
-			.id		= V4L2_CID_EXPOSURE,
-			.type		= V4L2_CTRL_TYPE_INTEGER,
-			.name		= "exposure",
-			.minimum	= 0x00,
-			.maximum	= 0x02ff,
-			.step		= 0x1,
-			.default_value	= PO1030_EXPOSURE_DEFAULT,
-			.flags		= V4L2_CTRL_FLAG_SLIDER
-		},
-		.set = po1030_set_exposure,
-		.get = po1030_get_exposure
-	},
-#define RED_BALANCE_IDX 2
-	{
-		{
-			.id		= V4L2_CID_RED_BALANCE,
-			.type		= V4L2_CTRL_TYPE_INTEGER,
-			.name		= "red balance",
-			.minimum	= 0x00,
-			.maximum	= 0xff,
-			.step		= 0x1,
-			.default_value	= PO1030_RED_GAIN_DEFAULT,
-			.flags		= V4L2_CTRL_FLAG_SLIDER
-		},
-		.set = po1030_set_red_balance,
-		.get = po1030_get_red_balance
-	},
-#define BLUE_BALANCE_IDX 3
-	{
-		{
-			.id		= V4L2_CID_BLUE_BALANCE,
-			.type		= V4L2_CTRL_TYPE_INTEGER,
-			.name		= "blue balance",
-			.minimum	= 0x00,
-			.maximum	= 0xff,
-			.step		= 0x1,
-			.default_value	= PO1030_BLUE_GAIN_DEFAULT,
-			.flags		= V4L2_CTRL_FLAG_SLIDER
-		},
-		.set = po1030_set_blue_balance,
-		.get = po1030_get_blue_balance
-	},
-#define HFLIP_IDX 4
-	{
-		{
-			.id		= V4L2_CID_HFLIP,
-			.type		= V4L2_CTRL_TYPE_BOOLEAN,
-			.name		= "horizontal flip",
-			.minimum	= 0,
-			.maximum	= 1,
-			.step		= 1,
-			.default_value	= 0,
-		},
-		.set = po1030_set_hflip,
-		.get = po1030_get_hflip
-	},
-#define VFLIP_IDX 5
-	{
-		{
-			.id		= V4L2_CID_VFLIP,
-			.type		= V4L2_CTRL_TYPE_BOOLEAN,
-			.name		= "vertical flip",
-			.minimum	= 0,
-			.maximum	= 1,
-			.step		= 1,
-			.default_value	= 0,
-		},
-		.set = po1030_set_vflip,
-		.get = po1030_get_vflip
-	},
-#define AUTO_WHITE_BALANCE_IDX 6
-	{
-		{
-			.id		= V4L2_CID_AUTO_WHITE_BALANCE,
-			.type		= V4L2_CTRL_TYPE_BOOLEAN,
-			.name		= "auto white balance",
-			.minimum	= 0,
-			.maximum	= 1,
-			.step		= 1,
-			.default_value	= 0,
-		},
-		.set = po1030_set_auto_white_balance,
-		.get = po1030_get_auto_white_balance
-	},
-#define AUTO_EXPOSURE_IDX 7
-	{
-		{
-			.id		= V4L2_CID_EXPOSURE_AUTO,
-			.type		= V4L2_CTRL_TYPE_BOOLEAN,
-			.name		= "auto exposure",
-			.minimum	= 0,
-			.maximum	= 1,
-			.step		= 1,
-			.default_value	= 0,
-		},
-		.set = po1030_set_auto_exposure,
-		.get = po1030_get_auto_exposure
-	},
-#define GREEN_BALANCE_IDX 8
-	{
-		{
-			.id		= M5602_V4L2_CID_GREEN_BALANCE,
-			.type		= V4L2_CTRL_TYPE_INTEGER,
-			.name		= "green balance",
-			.minimum	= 0x00,
-			.maximum	= 0xff,
-			.step		= 0x1,
-			.default_value	= PO1030_GREEN_GAIN_DEFAULT,
-			.flags		= V4L2_CTRL_FLAG_SLIDER
-		},
-		.set = po1030_set_green_balance,
-		.get = po1030_get_green_balance
-	},
+static const struct v4l2_ctrl_ops po1030_ctrl_ops = {
+	.s_ctrl = po1030_s_ctrl,
 };
 
-static void po1030_dump_registers(struct sd *sd);
+static const struct v4l2_ctrl_config po1030_greenbal_cfg = {
+	.ops	= &po1030_ctrl_ops,
+	.id	= M5602_V4L2_CID_GREEN_BALANCE,
+	.name	= "Green Balance",
+	.type	= V4L2_CTRL_TYPE_INTEGER,
+	.min	= 0,
+	.max	= 255,
+	.step	= 1,
+	.def	= PO1030_GREEN_GAIN_DEFAULT,
+	.flags	= V4L2_CTRL_FLAG_SLIDER,
+};
 
 int po1030_probe(struct sd *sd)
 {
 	u8 dev_id_h = 0, i;
-	s32 *sensor_settings;
+	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
 
 	if (force_sensor) {
 		if (force_sensor == PO1030_SENSOR) {
@@ -229,26 +89,14 @@ int po1030_probe(struct sd *sd)
 	return -ENODEV;
 
 sensor_found:
-	sensor_settings = kmalloc(
-		ARRAY_SIZE(po1030_ctrls) * sizeof(s32), GFP_KERNEL);
-	if (!sensor_settings)
-		return -ENOMEM;
-
 	sd->gspca_dev.cam.cam_mode = po1030_modes;
 	sd->gspca_dev.cam.nmodes = ARRAY_SIZE(po1030_modes);
-	sd->desc->ctrls = po1030_ctrls;
-	sd->desc->nctrls = ARRAY_SIZE(po1030_ctrls);
-
-	for (i = 0; i < ARRAY_SIZE(po1030_ctrls); i++)
-		sensor_settings[i] = po1030_ctrls[i].qctrl.default_value;
-	sd->sensor_priv = sensor_settings;
 
 	return 0;
 }
 
 int po1030_init(struct sd *sd)
 {
-	s32 *sensor_settings = sd->sensor_priv;
 	int i, err = 0;
 
 	/* Init the sensor */
@@ -279,46 +127,50 @@ int po1030_init(struct sd *sd)
 	if (dump_sensor)
 		po1030_dump_registers(sd);
 
-	err = po1030_set_exposure(&sd->gspca_dev,
-				   sensor_settings[EXPOSURE_IDX]);
-	if (err < 0)
-		return err;
-
-	err = po1030_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
-	if (err < 0)
-		return err;
-
-	err = po1030_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]);
-	if (err < 0)
-		return err;
-
-	err = po1030_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]);
-	if (err < 0)
-		return err;
-
-	err = po1030_set_red_balance(&sd->gspca_dev,
-				      sensor_settings[RED_BALANCE_IDX]);
-	if (err < 0)
-		return err;
-
-	err = po1030_set_blue_balance(&sd->gspca_dev,
-				      sensor_settings[BLUE_BALANCE_IDX]);
-	if (err < 0)
-		return err;
+	return 0;
+}
 
-	err = po1030_set_green_balance(&sd->gspca_dev,
-				       sensor_settings[GREEN_BALANCE_IDX]);
-	if (err < 0)
-		return err;
+int po1030_init_controls(struct sd *sd)
+{
+	struct v4l2_ctrl_handler *hdl = &sd->gspca_dev.ctrl_handler;
+
+	sd->gspca_dev.vdev.ctrl_handler = hdl;
+	v4l2_ctrl_handler_init(hdl, 9);
+
+	sd->auto_white_bal = v4l2_ctrl_new_std(hdl, &po1030_ctrl_ops,
+					       V4L2_CID_AUTO_WHITE_BALANCE,
+					       0, 1, 1, 0);
+	sd->green_bal = v4l2_ctrl_new_custom(hdl, &po1030_greenbal_cfg, NULL);
+	sd->red_bal = v4l2_ctrl_new_std(hdl, &po1030_ctrl_ops,
+					V4L2_CID_RED_BALANCE, 0, 255, 1,
+					PO1030_RED_GAIN_DEFAULT);
+	sd->blue_bal = v4l2_ctrl_new_std(hdl, &po1030_ctrl_ops,
+					V4L2_CID_BLUE_BALANCE, 0, 255, 1,
+					PO1030_BLUE_GAIN_DEFAULT);
+
+	sd->autoexpo = v4l2_ctrl_new_std_menu(hdl, &po1030_ctrl_ops,
+			  V4L2_CID_EXPOSURE_AUTO, 1, 0, V4L2_EXPOSURE_MANUAL);
+	sd->expo = v4l2_ctrl_new_std(hdl, &po1030_ctrl_ops, V4L2_CID_EXPOSURE,
+			  0, 0x2ff, 1, PO1030_EXPOSURE_DEFAULT);
+
+	sd->gain = v4l2_ctrl_new_std(hdl, &po1030_ctrl_ops, V4L2_CID_GAIN, 0,
+				     0x4f, 1, PO1030_GLOBAL_GAIN_DEFAULT);
+
+	sd->hflip = v4l2_ctrl_new_std(hdl, &po1030_ctrl_ops, V4L2_CID_HFLIP,
+				      0, 1, 1, 0);
+	sd->vflip = v4l2_ctrl_new_std(hdl, &po1030_ctrl_ops, V4L2_CID_VFLIP,
+				      0, 1, 1, 0);
+
+	if (hdl->error) {
+		pr_err("Could not initialize controls\n");
+		return hdl->error;
+	}
 
-	err = po1030_set_auto_white_balance(&sd->gspca_dev,
-				sensor_settings[AUTO_WHITE_BALANCE_IDX]);
-	if (err < 0)
-		return err;
+	v4l2_ctrl_auto_cluster(4, &sd->auto_white_bal, 0, false);
+	v4l2_ctrl_auto_cluster(2, &sd->autoexpo, 0, false);
+	v4l2_ctrl_cluster(2, &sd->hflip);
 
-	err = po1030_set_auto_exposure(&sd->gspca_dev,
-				sensor_settings[AUTO_EXPOSURE_IDX]);
-	return err;
+	return 0;
 }
 
 int po1030_start(struct sd *sd)
@@ -448,28 +300,16 @@ int po1030_start(struct sd *sd)
 	return err;
 }
 
-static int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
-
-	*val = sensor_settings[EXPOSURE_IDX];
-	PDEBUG(D_V4L2, "Exposure read as %d", *val);
-	return 0;
-}
-
 static int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
 	u8 i2c_data;
 	int err;
 
-	sensor_settings[EXPOSURE_IDX] = val;
-	PDEBUG(D_V4L2, "Set exposure to %d", val & 0xffff);
+	PDEBUG(D_CONF, "Set exposure to %d", val & 0xffff);
 
 	i2c_data = ((val & 0xff00) >> 8);
-	PDEBUG(D_V4L2, "Set exposure to high byte to 0x%x",
+	PDEBUG(D_CONF, "Set exposure to high byte to 0x%x",
 	       i2c_data);
 
 	err = m5602_write_sensor(sd, PO1030_INTEGLINES_H,
@@ -478,7 +318,7 @@ static int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
 		return err;
 
 	i2c_data = (val & 0xff);
-	PDEBUG(D_V4L2, "Set exposure to low byte to 0x%x",
+	PDEBUG(D_CONF, "Set exposure to low byte to 0x%x",
 	       i2c_data);
 	err = m5602_write_sensor(sd, PO1030_INTEGLINES_M,
 				  &i2c_data, 1);
@@ -486,91 +326,32 @@ static int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
 	return err;
 }
 
-static int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
-
-	*val = sensor_settings[GAIN_IDX];
-	PDEBUG(D_V4L2, "Read global gain %d", *val);
-	return 0;
-}
-
 static int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
 	u8 i2c_data;
 	int err;
 
-	sensor_settings[GAIN_IDX] = val;
-
 	i2c_data = val & 0xff;
-	PDEBUG(D_V4L2, "Set global gain to %d", i2c_data);
+	PDEBUG(D_CONF, "Set global gain to %d", i2c_data);
 	err = m5602_write_sensor(sd, PO1030_GLOBALGAIN,
 				 &i2c_data, 1);
 	return err;
 }
 
-static int po1030_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
-
-	*val = sensor_settings[HFLIP_IDX];
-	PDEBUG(D_V4L2, "Read hflip %d", *val);
-
-	return 0;
-}
-
-static int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
-	u8 i2c_data;
-	int err;
-
-	sensor_settings[HFLIP_IDX] = val;
-
-	PDEBUG(D_V4L2, "Set hflip %d", val);
-	err = m5602_read_sensor(sd, PO1030_CONTROL2, &i2c_data, 1);
-	if (err < 0)
-		return err;
-
-	i2c_data = (0x7f & i2c_data) | ((val & 0x01) << 7);
-
-	err = m5602_write_sensor(sd, PO1030_CONTROL2,
-				 &i2c_data, 1);
-
-	return err;
-}
-
-static int po1030_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
+static int po1030_set_hvflip(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
-
-	*val = sensor_settings[VFLIP_IDX];
-	PDEBUG(D_V4L2, "Read vflip %d", *val);
-
-	return 0;
-}
-
-static int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
 	u8 i2c_data;
 	int err;
 
-	sensor_settings[VFLIP_IDX] = val;
-
-	PDEBUG(D_V4L2, "Set vflip %d", val);
+	PDEBUG(D_CONF, "Set hvflip %d %d", sd->hflip->val, sd->vflip->val);
 	err = m5602_read_sensor(sd, PO1030_CONTROL2, &i2c_data, 1);
 	if (err < 0)
 		return err;
 
-	i2c_data = (i2c_data & 0xbf) | ((val & 0x01) << 6);
+	i2c_data = (0x3f & i2c_data) | (sd->hflip->val << 7) |
+		   (sd->vflip->val << 6);
 
 	err = m5602_write_sensor(sd, PO1030_CONTROL2,
 				 &i2c_data, 1);
@@ -578,81 +359,41 @@ static int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
 	return err;
 }
 
-static int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
-
-	*val = sensor_settings[RED_BALANCE_IDX];
-	PDEBUG(D_V4L2, "Read red gain %d", *val);
-	return 0;
-}
-
 static int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
 	u8 i2c_data;
 	int err;
 
-	sensor_settings[RED_BALANCE_IDX] = val;
-
 	i2c_data = val & 0xff;
-	PDEBUG(D_V4L2, "Set red gain to %d", i2c_data);
+	PDEBUG(D_CONF, "Set red gain to %d", i2c_data);
 	err = m5602_write_sensor(sd, PO1030_RED_GAIN,
 				  &i2c_data, 1);
 	return err;
 }
 
-static int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
-
-	*val = sensor_settings[BLUE_BALANCE_IDX];
-	PDEBUG(D_V4L2, "Read blue gain %d", *val);
-
-	return 0;
-}
-
 static int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
 	u8 i2c_data;
 	int err;
 
-	sensor_settings[BLUE_BALANCE_IDX] = val;
-
 	i2c_data = val & 0xff;
-	PDEBUG(D_V4L2, "Set blue gain to %d", i2c_data);
+	PDEBUG(D_CONF, "Set blue gain to %d", i2c_data);
 	err = m5602_write_sensor(sd, PO1030_BLUE_GAIN,
 				  &i2c_data, 1);
 
 	return err;
 }
 
-static int po1030_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
-
-	*val = sensor_settings[GREEN_BALANCE_IDX];
-	PDEBUG(D_V4L2, "Read green gain %d", *val);
-
-	return 0;
-}
-
 static int po1030_set_green_balance(struct gspca_dev *gspca_dev, __s32 val)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
 	u8 i2c_data;
 	int err;
 
-	sensor_settings[GREEN_BALANCE_IDX] = val;
 	i2c_data = val & 0xff;
-	PDEBUG(D_V4L2, "Set green gain to %d", i2c_data);
+	PDEBUG(D_CONF, "Set green gain to %d", i2c_data);
 
 	err = m5602_write_sensor(sd, PO1030_GREEN_1_GAIN,
 			   &i2c_data, 1);
@@ -663,63 +404,36 @@ static int po1030_set_green_balance(struct gspca_dev *gspca_dev, __s32 val)
 				 &i2c_data, 1);
 }
 
-static int po1030_get_auto_white_balance(struct gspca_dev *gspca_dev,
-					 __s32 *val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
-
-	*val = sensor_settings[AUTO_WHITE_BALANCE_IDX];
-	PDEBUG(D_V4L2, "Auto white balancing is %d", *val);
-
-	return 0;
-}
-
 static int po1030_set_auto_white_balance(struct gspca_dev *gspca_dev,
 					 __s32 val)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
 	u8 i2c_data;
 	int err;
 
-	sensor_settings[AUTO_WHITE_BALANCE_IDX] = val;
-
 	err = m5602_read_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1);
 	if (err < 0)
 		return err;
 
-	PDEBUG(D_V4L2, "Set auto white balance to %d", val);
+	PDEBUG(D_CONF, "Set auto white balance to %d", val);
 	i2c_data = (i2c_data & 0xfe) | (val & 0x01);
 	err = m5602_write_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1);
 	return err;
 }
 
-static int po1030_get_auto_exposure(struct gspca_dev *gspca_dev,
-				    __s32 *val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
-
-	*val = sensor_settings[AUTO_EXPOSURE_IDX];
-	PDEBUG(D_V4L2, "Auto exposure is %d", *val);
-	return 0;
-}
-
 static int po1030_set_auto_exposure(struct gspca_dev *gspca_dev,
 				    __s32 val)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
 	u8 i2c_data;
 	int err;
 
-	sensor_settings[AUTO_EXPOSURE_IDX] = val;
 	err = m5602_read_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1);
 	if (err < 0)
 		return err;
 
-	PDEBUG(D_V4L2, "Set auto exposure to %d", val);
+	PDEBUG(D_CONF, "Set auto exposure to %d", val);
+	val = (val == V4L2_EXPOSURE_AUTO);
 	i2c_data = (i2c_data & 0xfd) | ((val & 0x01) << 1);
 	return m5602_write_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1);
 }
@@ -727,7 +441,48 @@ static int po1030_set_auto_exposure(struct gspca_dev *gspca_dev,
 void po1030_disconnect(struct sd *sd)
 {
 	sd->sensor = NULL;
-	kfree(sd->sensor_priv);
+}
+
+static int po1030_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct gspca_dev *gspca_dev =
+		container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
+	struct sd *sd = (struct sd *) gspca_dev;
+	int err;
+
+	if (!gspca_dev->streaming)
+		return 0;
+
+	switch (ctrl->id) {
+	case V4L2_CID_AUTO_WHITE_BALANCE:
+		err = po1030_set_auto_white_balance(gspca_dev, ctrl->val);
+		if (err || ctrl->val)
+			return err;
+		err = po1030_set_green_balance(gspca_dev, sd->green_bal->val);
+		if (err)
+			return err;
+		err = po1030_set_red_balance(gspca_dev, sd->red_bal->val);
+		if (err)
+			return err;
+		err = po1030_set_blue_balance(gspca_dev, sd->blue_bal->val);
+		break;
+	case V4L2_CID_EXPOSURE_AUTO:
+		err = po1030_set_auto_exposure(gspca_dev, ctrl->val);
+		if (err || ctrl->val == V4L2_EXPOSURE_AUTO)
+			return err;
+		err = po1030_set_exposure(gspca_dev, sd->expo->val);
+		break;
+	case V4L2_CID_GAIN:
+		err = po1030_set_gain(gspca_dev, ctrl->val);
+		break;
+	case V4L2_CID_HFLIP:
+		err = po1030_set_hvflip(gspca_dev);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return err;
 }
 
 static void po1030_dump_registers(struct sd *sd)
diff --git a/drivers/media/usb/gspca/m5602/m5602_po1030.h b/drivers/media/usb/gspca/m5602/m5602_po1030.h
index 81a2bcb..a6ab761 100644
--- a/drivers/media/usb/gspca/m5602/m5602_po1030.h
+++ b/drivers/media/usb/gspca/m5602/m5602_po1030.h
@@ -151,6 +151,7 @@ extern bool dump_sensor;
 
 int po1030_probe(struct sd *sd);
 int po1030_init(struct sd *sd);
+int po1030_init_controls(struct sd *sd);
 int po1030_start(struct sd *sd);
 void po1030_disconnect(struct sd *sd);
 
@@ -162,6 +163,7 @@ static const struct m5602_sensor po1030 = {
 
 	.probe = po1030_probe,
 	.init = po1030_init,
+	.init_controls = po1030_init_controls,
 	.start = po1030_start,
 	.disconnect = po1030_disconnect,
 };
diff --git a/drivers/media/usb/gspca/m5602/m5602_s5k4aa.c b/drivers/media/usb/gspca/m5602/m5602_s5k4aa.c
index c8e1572..7d12599 100644
--- a/drivers/media/usb/gspca/m5602/m5602_s5k4aa.c
+++ b/drivers/media/usb/gspca/m5602/m5602_s5k4aa.c
@@ -20,18 +20,12 @@
 
 #include "m5602_s5k4aa.h"
 
-static int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
-static int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
-static int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
-static int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
-static int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
-static int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
-static int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
-static int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val);
-static int s5k4aa_get_noise(struct gspca_dev *gspca_dev, __s32 *val);
-static int s5k4aa_set_noise(struct gspca_dev *gspca_dev, __s32 val);
-static int s5k4aa_get_brightness(struct gspca_dev *gspca_dev, __s32 *val);
-static int s5k4aa_set_brightness(struct gspca_dev *gspca_dev, __s32 val);
+static int s5k4aa_s_ctrl(struct v4l2_ctrl *ctrl);
+static void s5k4aa_dump_registers(struct sd *sd);
+
+static const struct v4l2_ctrl_ops s5k4aa_ctrl_ops = {
+	.s_ctrl = s5k4aa_s_ctrl,
+};
 
 static
     const
@@ -147,104 +141,12 @@ static struct v4l2_pix_format s5k4aa_modes[] = {
 	}
 };
 
-static const struct ctrl s5k4aa_ctrls[] = {
-#define VFLIP_IDX 0
-	{
-		{
-			.id		= V4L2_CID_VFLIP,
-			.type		= V4L2_CTRL_TYPE_BOOLEAN,
-			.name		= "vertical flip",
-			.minimum	= 0,
-			.maximum	= 1,
-			.step		= 1,
-			.default_value	= 0
-		},
-		.set = s5k4aa_set_vflip,
-		.get = s5k4aa_get_vflip
-	},
-#define HFLIP_IDX 1
-	{
-		{
-			.id		= V4L2_CID_HFLIP,
-			.type		= V4L2_CTRL_TYPE_BOOLEAN,
-			.name		= "horizontal flip",
-			.minimum	= 0,
-			.maximum	= 1,
-			.step		= 1,
-			.default_value	= 0
-		},
-		.set = s5k4aa_set_hflip,
-		.get = s5k4aa_get_hflip
-	},
-#define GAIN_IDX 2
-	{
-		{
-			.id		= V4L2_CID_GAIN,
-			.type		= V4L2_CTRL_TYPE_INTEGER,
-			.name		= "Gain",
-			.minimum	= 0,
-			.maximum	= 127,
-			.step		= 1,
-			.default_value	= S5K4AA_DEFAULT_GAIN,
-			.flags		= V4L2_CTRL_FLAG_SLIDER
-		},
-		.set = s5k4aa_set_gain,
-		.get = s5k4aa_get_gain
-	},
-#define EXPOSURE_IDX 3
-	{
-		{
-			.id		= V4L2_CID_EXPOSURE,
-			.type		= V4L2_CTRL_TYPE_INTEGER,
-			.name		= "Exposure",
-			.minimum	= 13,
-			.maximum	= 0xfff,
-			.step		= 1,
-			.default_value	= 0x100,
-			.flags		= V4L2_CTRL_FLAG_SLIDER
-		},
-		.set = s5k4aa_set_exposure,
-		.get = s5k4aa_get_exposure
-	},
-#define NOISE_SUPP_IDX 4
-	{
-		{
-			.id		= V4L2_CID_PRIVATE_BASE,
-			.type		= V4L2_CTRL_TYPE_BOOLEAN,
-			.name		= "Noise suppression (smoothing)",
-			.minimum	= 0,
-			.maximum	= 1,
-			.step		= 1,
-			.default_value	= 1,
-		},
-			.set = s5k4aa_set_noise,
-			.get = s5k4aa_get_noise
-	},
-#define BRIGHTNESS_IDX 5
-	{
-		{
-			.id		= V4L2_CID_BRIGHTNESS,
-			.type		= V4L2_CTRL_TYPE_INTEGER,
-			.name		= "Brightness",
-			.minimum	= 0,
-			.maximum	= 0x1f,
-			.step		= 1,
-			.default_value	= S5K4AA_DEFAULT_BRIGHTNESS,
-		},
-			.set = s5k4aa_set_brightness,
-			.get = s5k4aa_get_brightness
-	},
-
-};
-
-static void s5k4aa_dump_registers(struct sd *sd);
-
 int s5k4aa_probe(struct sd *sd)
 {
 	u8 prod_id[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
 	const u8 expected_prod_id[6] = {0x00, 0x10, 0x00, 0x4b, 0x33, 0x75};
+	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
 	int i, err = 0;
-	s32 *sensor_settings;
 
 	if (force_sensor) {
 		if (force_sensor == S5K4AA_SENSOR) {
@@ -303,19 +205,8 @@ int s5k4aa_probe(struct sd *sd)
 		pr_info("Detected a s5k4aa sensor\n");
 
 sensor_found:
-	sensor_settings = kmalloc(
-		ARRAY_SIZE(s5k4aa_ctrls) * sizeof(s32), GFP_KERNEL);
-	if (!sensor_settings)
-		return -ENOMEM;
-
 	sd->gspca_dev.cam.cam_mode = s5k4aa_modes;
 	sd->gspca_dev.cam.nmodes = ARRAY_SIZE(s5k4aa_modes);
-	sd->desc->ctrls = s5k4aa_ctrls;
-	sd->desc->nctrls = ARRAY_SIZE(s5k4aa_ctrls);
-
-	for (i = 0; i < ARRAY_SIZE(s5k4aa_ctrls); i++)
-		sensor_settings[i] = s5k4aa_ctrls[i].qctrl.default_value;
-	sd->sensor_priv = sensor_settings;
 
 	return 0;
 }
@@ -325,11 +216,11 @@ int s5k4aa_start(struct sd *sd)
 	int i, err = 0;
 	u8 data[2];
 	struct cam *cam = &sd->gspca_dev.cam;
-	s32 *sensor_settings = sd->sensor_priv;
+	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
 
 	switch (cam->cam_mode[sd->gspca_dev.curr_mode].width) {
 	case 1280:
-		PDEBUG(D_V4L2, "Configuring camera for SXGA mode");
+		PDEBUG(D_CONF, "Configuring camera for SXGA mode");
 
 		for (i = 0; i < ARRAY_SIZE(SXGA_s5k4aa); i++) {
 			switch (SXGA_s5k4aa[i][0]) {
@@ -359,13 +250,10 @@ int s5k4aa_start(struct sd *sd)
 				return -EINVAL;
 			}
 		}
-		err = s5k4aa_set_noise(&sd->gspca_dev, 0);
-		if (err < 0)
-			return err;
 		break;
 
 	case 640:
-		PDEBUG(D_V4L2, "Configuring camera for VGA mode");
+		PDEBUG(D_CONF, "Configuring camera for VGA mode");
 
 		for (i = 0; i < ARRAY_SIZE(VGA_s5k4aa); i++) {
 			switch (VGA_s5k4aa[i][0]) {
@@ -395,37 +283,12 @@ int s5k4aa_start(struct sd *sd)
 				return -EINVAL;
 			}
 		}
-		err = s5k4aa_set_noise(&sd->gspca_dev, 1);
-		if (err < 0)
-			return err;
 		break;
 	}
 	if (err < 0)
 		return err;
 
-	err = s5k4aa_set_exposure(&sd->gspca_dev,
-				   sensor_settings[EXPOSURE_IDX]);
-	if (err < 0)
-		return err;
-
-	err = s5k4aa_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
-	if (err < 0)
-		return err;
-
-	err = s5k4aa_set_brightness(&sd->gspca_dev,
-				     sensor_settings[BRIGHTNESS_IDX]);
-	if (err < 0)
-		return err;
-
-	err = s5k4aa_set_noise(&sd->gspca_dev, sensor_settings[NOISE_SUPP_IDX]);
-	if (err < 0)
-		return err;
-
-	err = s5k4aa_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]);
-	if (err < 0)
-		return err;
-
-	return s5k4aa_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]);
+	return 0;
 }
 
 int s5k4aa_init(struct sd *sd)
@@ -466,13 +329,36 @@ int s5k4aa_init(struct sd *sd)
 	return err;
 }
 
-static int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
+int s5k4aa_init_controls(struct sd *sd)
 {
-	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
+	struct v4l2_ctrl_handler *hdl = &sd->gspca_dev.ctrl_handler;
+
+	sd->gspca_dev.vdev.ctrl_handler = hdl;
+	v4l2_ctrl_handler_init(hdl, 6);
 
-	*val = sensor_settings[EXPOSURE_IDX];
-	PDEBUG(D_V4L2, "Read exposure %d", *val);
+	v4l2_ctrl_new_std(hdl, &s5k4aa_ctrl_ops, V4L2_CID_BRIGHTNESS,
+			  0, 0x1f, 1, S5K4AA_DEFAULT_BRIGHTNESS);
+
+	v4l2_ctrl_new_std(hdl, &s5k4aa_ctrl_ops, V4L2_CID_EXPOSURE,
+			  13, 0xfff, 1, 0x100);
+
+	v4l2_ctrl_new_std(hdl, &s5k4aa_ctrl_ops, V4L2_CID_GAIN,
+			  0, 127, 1, S5K4AA_DEFAULT_GAIN);
+
+	v4l2_ctrl_new_std(hdl, &s5k4aa_ctrl_ops, V4L2_CID_SHARPNESS,
+			  0, 1, 1, 1);
+
+	sd->hflip = v4l2_ctrl_new_std(hdl, &s5k4aa_ctrl_ops, V4L2_CID_HFLIP,
+				      0, 1, 1, 0);
+	sd->vflip = v4l2_ctrl_new_std(hdl, &s5k4aa_ctrl_ops, V4L2_CID_VFLIP,
+				      0, 1, 1, 0);
+
+	if (hdl->error) {
+		pr_err("Could not initialize controls\n");
+		return hdl->error;
+	}
+
+	v4l2_ctrl_cluster(2, &sd->hflip);
 
 	return 0;
 }
@@ -480,12 +366,10 @@ static int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
 static int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
 	u8 data = S5K4AA_PAGE_MAP_2;
 	int err;
 
-	sensor_settings[EXPOSURE_IDX] = val;
-	PDEBUG(D_V4L2, "Set exposure to %d", val);
+	PDEBUG(D_CONF, "Set exposure to %d", val);
 	err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
 	if (err < 0)
 		return err;
@@ -499,27 +383,15 @@ static int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
 	return err;
 }
 
-static int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
+static int s5k4aa_set_hvflip(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
-
-	*val = sensor_settings[VFLIP_IDX];
-	PDEBUG(D_V4L2, "Read vertical flip %d", *val);
-
-	return 0;
-}
-
-static int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
 	u8 data = S5K4AA_PAGE_MAP_2;
 	int err;
+	int hflip = sd->hflip->val;
+	int vflip = sd->vflip->val;
 
-	sensor_settings[VFLIP_IDX] = val;
-
-	PDEBUG(D_V4L2, "Set vertical flip to %d", val);
+	PDEBUG(D_CONF, "Set hvflip %d %d", hflip, vflip);
 	err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
 	if (err < 0)
 		return err;
@@ -528,93 +400,48 @@ static int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
 	if (err < 0)
 		return err;
 
-	if (dmi_check_system(s5k4aa_vflip_dmi_table))
-		val = !val;
+	if (dmi_check_system(s5k4aa_vflip_dmi_table)) {
+		hflip = !hflip;
+		vflip = !vflip;
+	}
 
-	data = ((data & ~S5K4AA_RM_V_FLIP) | ((val & 0x01) << 7));
+	data = (data & 0x7f) | (vflip << 7) | (hflip << 6);
 	err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
 	if (err < 0)
 		return err;
 
-	err = m5602_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
+	err = m5602_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
 	if (err < 0)
 		return err;
-	if (val)
+	if (hflip)
 		data &= 0xfe;
 	else
 		data |= 0x01;
-	err = m5602_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
-	return err;
-}
-
-static int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
-
-	*val = sensor_settings[HFLIP_IDX];
-	PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
-
-	return 0;
-}
-
-static int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
-	u8 data = S5K4AA_PAGE_MAP_2;
-	int err;
-
-	sensor_settings[HFLIP_IDX] = val;
-
-	PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
-	err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
-	if (err < 0)
-		return err;
-
-	err = m5602_read_sensor(sd, S5K4AA_READ_MODE, &data, 1);
-	if (err < 0)
-		return err;
-
-	if (dmi_check_system(s5k4aa_vflip_dmi_table))
-		val = !val;
-
-	data = ((data & ~S5K4AA_RM_H_FLIP) | ((val & 0x01) << 6));
-	err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
+	err = m5602_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
 	if (err < 0)
 		return err;
 
-	err = m5602_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
+	err = m5602_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
 	if (err < 0)
 		return err;
-	if (val)
+	if (vflip)
 		data &= 0xfe;
 	else
 		data |= 0x01;
-	err = m5602_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
-	return err;
-}
-
-static int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
+	err = m5602_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
+	if (err < 0)
+		return err;
 
-	*val = sensor_settings[GAIN_IDX];
-	PDEBUG(D_V4L2, "Read gain %d", *val);
 	return 0;
 }
 
 static int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
 	u8 data = S5K4AA_PAGE_MAP_2;
 	int err;
 
-	sensor_settings[GAIN_IDX] = val;
-
-	PDEBUG(D_V4L2, "Set gain to %d", val);
+	PDEBUG(D_CONF, "Set gain to %d", val);
 	err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
 	if (err < 0)
 		return err;
@@ -625,26 +452,13 @@ static int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val)
 	return err;
 }
 
-static int s5k4aa_get_brightness(struct gspca_dev *gspca_dev, __s32 *val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
-
-	*val = sensor_settings[BRIGHTNESS_IDX];
-	PDEBUG(D_V4L2, "Read brightness %d", *val);
-	return 0;
-}
-
 static int s5k4aa_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
 	u8 data = S5K4AA_PAGE_MAP_2;
 	int err;
 
-	sensor_settings[BRIGHTNESS_IDX] = val;
-
-	PDEBUG(D_V4L2, "Set brightness to %d", val);
+	PDEBUG(D_CONF, "Set brightness to %d", val);
 	err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
 	if (err < 0)
 		return err;
@@ -653,26 +467,13 @@ static int s5k4aa_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
 	return m5602_write_sensor(sd, S5K4AA_BRIGHTNESS, &data, 1);
 }
 
-static int s5k4aa_get_noise(struct gspca_dev *gspca_dev, __s32 *val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
-
-	*val = sensor_settings[NOISE_SUPP_IDX];
-	PDEBUG(D_V4L2, "Read noise %d", *val);
-	return 0;
-}
-
 static int s5k4aa_set_noise(struct gspca_dev *gspca_dev, __s32 val)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
 	u8 data = S5K4AA_PAGE_MAP_2;
 	int err;
 
-	sensor_settings[NOISE_SUPP_IDX] = val;
-
-	PDEBUG(D_V4L2, "Set noise to %d", val);
+	PDEBUG(D_CONF, "Set noise to %d", val);
 	err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
 	if (err < 0)
 		return err;
@@ -681,10 +482,41 @@ static int s5k4aa_set_noise(struct gspca_dev *gspca_dev, __s32 val)
 	return m5602_write_sensor(sd, S5K4AA_NOISE_SUPP, &data, 1);
 }
 
+static int s5k4aa_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct gspca_dev *gspca_dev =
+		container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
+	int err;
+
+	if (!gspca_dev->streaming)
+		return 0;
+
+	switch (ctrl->id) {
+	case V4L2_CID_BRIGHTNESS:
+		err = s5k4aa_set_brightness(gspca_dev, ctrl->val);
+		break;
+	case V4L2_CID_EXPOSURE:
+		err = s5k4aa_set_exposure(gspca_dev, ctrl->val);
+		break;
+	case V4L2_CID_GAIN:
+		err = s5k4aa_set_gain(gspca_dev, ctrl->val);
+		break;
+	case V4L2_CID_SHARPNESS:
+		err = s5k4aa_set_noise(gspca_dev, ctrl->val);
+		break;
+	case V4L2_CID_HFLIP:
+		err = s5k4aa_set_hvflip(gspca_dev);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return err;
+}
+
 void s5k4aa_disconnect(struct sd *sd)
 {
 	sd->sensor = NULL;
-	kfree(sd->sensor_priv);
 }
 
 static void s5k4aa_dump_registers(struct sd *sd)
diff --git a/drivers/media/usb/gspca/m5602/m5602_s5k4aa.h b/drivers/media/usb/gspca/m5602/m5602_s5k4aa.h
index 8e0035e..9953e97 100644
--- a/drivers/media/usb/gspca/m5602/m5602_s5k4aa.h
+++ b/drivers/media/usb/gspca/m5602/m5602_s5k4aa.h
@@ -69,6 +69,7 @@ extern bool dump_sensor;
 
 int s5k4aa_probe(struct sd *sd);
 int s5k4aa_init(struct sd *sd);
+int s5k4aa_init_controls(struct sd *sd);
 int s5k4aa_start(struct sd *sd);
 void s5k4aa_disconnect(struct sd *sd);
 
@@ -79,6 +80,7 @@ static const struct m5602_sensor s5k4aa = {
 
 	.probe = s5k4aa_probe,
 	.init = s5k4aa_init,
+	.init_controls = s5k4aa_init_controls,
 	.start = s5k4aa_start,
 	.disconnect = s5k4aa_disconnect,
 };
diff --git a/drivers/media/usb/gspca/m5602/m5602_s5k83a.c b/drivers/media/usb/gspca/m5602/m5602_s5k83a.c
index 1de743a..7cbc3a0 100644
--- a/drivers/media/usb/gspca/m5602/m5602_s5k83a.c
+++ b/drivers/media/usb/gspca/m5602/m5602_s5k83a.c
@@ -21,16 +21,11 @@
 #include <linux/kthread.h>
 #include "m5602_s5k83a.h"
 
-static int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val);
-static int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
-static int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val);
-static int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val);
-static int s5k83a_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
-static int s5k83a_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
-static int s5k83a_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
-static int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
-static int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
-static int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
+static int s5k83a_s_ctrl(struct v4l2_ctrl *ctrl);
+
+static const struct v4l2_ctrl_ops s5k83a_ctrl_ops = {
+	.s_ctrl = s5k83a_s_ctrl,
+};
 
 static struct v4l2_pix_format s5k83a_modes[] = {
 	{
@@ -46,83 +41,6 @@ static struct v4l2_pix_format s5k83a_modes[] = {
 	}
 };
 
-static const struct ctrl s5k83a_ctrls[] = {
-#define GAIN_IDX 0
-	{
-		{
-			.id = V4L2_CID_GAIN,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "gain",
-			.minimum = 0x00,
-			.maximum = 0xff,
-			.step = 0x01,
-			.default_value = S5K83A_DEFAULT_GAIN,
-			.flags = V4L2_CTRL_FLAG_SLIDER
-		},
-			.set = s5k83a_set_gain,
-			.get = s5k83a_get_gain
-
-	},
-#define BRIGHTNESS_IDX 1
-	{
-		{
-			.id = V4L2_CID_BRIGHTNESS,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "brightness",
-			.minimum = 0x00,
-			.maximum = 0xff,
-			.step = 0x01,
-			.default_value = S5K83A_DEFAULT_BRIGHTNESS,
-			.flags = V4L2_CTRL_FLAG_SLIDER
-		},
-			.set = s5k83a_set_brightness,
-			.get = s5k83a_get_brightness,
-	},
-#define EXPOSURE_IDX 2
-	{
-		{
-			.id = V4L2_CID_EXPOSURE,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "exposure",
-			.minimum = 0x00,
-			.maximum = S5K83A_MAXIMUM_EXPOSURE,
-			.step = 0x01,
-			.default_value = S5K83A_DEFAULT_EXPOSURE,
-			.flags = V4L2_CTRL_FLAG_SLIDER
-		},
-			.set = s5k83a_set_exposure,
-			.get = s5k83a_get_exposure
-	},
-#define HFLIP_IDX 3
-	{
-		{
-			.id = V4L2_CID_HFLIP,
-			.type = V4L2_CTRL_TYPE_BOOLEAN,
-			.name = "horizontal flip",
-			.minimum = 0,
-			.maximum = 1,
-			.step = 1,
-			.default_value = 0
-		},
-			.set = s5k83a_set_hflip,
-			.get = s5k83a_get_hflip
-	},
-#define VFLIP_IDX 4
-	{
-		{
-			.id = V4L2_CID_VFLIP,
-			.type = V4L2_CTRL_TYPE_BOOLEAN,
-			.name = "vertical flip",
-			.minimum = 0,
-			.maximum = 1,
-			.step = 1,
-			.default_value = 0
-		},
-		.set = s5k83a_set_vflip,
-		.get = s5k83a_get_vflip
-	}
-};
-
 static void s5k83a_dump_registers(struct sd *sd);
 static int s5k83a_get_rotation(struct sd *sd, u8 *reg_data);
 static int s5k83a_set_led_indication(struct sd *sd, u8 val);
@@ -131,9 +49,9 @@ static int s5k83a_set_flip_real(struct gspca_dev *gspca_dev,
 
 int s5k83a_probe(struct sd *sd)
 {
-	struct s5k83a_priv *sens_priv;
 	u8 prod_id = 0, ver_id = 0;
 	int i, err = 0;
+	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
 
 	if (force_sensor) {
 		if (force_sensor == S5K83A_SENSOR) {
@@ -173,38 +91,18 @@ int s5k83a_probe(struct sd *sd)
 		pr_info("Detected a s5k83a sensor\n");
 
 sensor_found:
-	sens_priv = kmalloc(
-		sizeof(struct s5k83a_priv), GFP_KERNEL);
-	if (!sens_priv)
-		return -ENOMEM;
-
-	sens_priv->settings =
-	kmalloc(sizeof(s32)*ARRAY_SIZE(s5k83a_ctrls), GFP_KERNEL);
-	if (!sens_priv->settings) {
-		kfree(sens_priv);
-		return -ENOMEM;
-	}
-
 	sd->gspca_dev.cam.cam_mode = s5k83a_modes;
 	sd->gspca_dev.cam.nmodes = ARRAY_SIZE(s5k83a_modes);
-	sd->desc->ctrls = s5k83a_ctrls;
-	sd->desc->nctrls = ARRAY_SIZE(s5k83a_ctrls);
 
 	/* null the pointer! thread is't running now */
-	sens_priv->rotation_thread = NULL;
-
-	for (i = 0; i < ARRAY_SIZE(s5k83a_ctrls); i++)
-		sens_priv->settings[i] = s5k83a_ctrls[i].qctrl.default_value;
+	sd->rotation_thread = NULL;
 
-	sd->sensor_priv = sens_priv;
 	return 0;
 }
 
 int s5k83a_init(struct sd *sd)
 {
 	int i, err = 0;
-	s32 *sensor_settings =
-			((struct s5k83a_priv *) sd->sensor_priv)->settings;
 
 	for (i = 0; i < ARRAY_SIZE(init_s5k83a) && !err; i++) {
 		u8 data[2] = {0x00, 0x00};
@@ -237,33 +135,44 @@ int s5k83a_init(struct sd *sd)
 	if (dump_sensor)
 		s5k83a_dump_registers(sd);
 
-	err = s5k83a_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
-	if (err < 0)
-		return err;
+	return err;
+}
 
-	err = s5k83a_set_brightness(&sd->gspca_dev,
-				     sensor_settings[BRIGHTNESS_IDX]);
-	if (err < 0)
-		return err;
+int s5k83a_init_controls(struct sd *sd)
+{
+	struct v4l2_ctrl_handler *hdl = &sd->gspca_dev.ctrl_handler;
 
-	err = s5k83a_set_exposure(&sd->gspca_dev,
-				   sensor_settings[EXPOSURE_IDX]);
-	if (err < 0)
-		return err;
+	sd->gspca_dev.vdev.ctrl_handler = hdl;
+	v4l2_ctrl_handler_init(hdl, 6);
 
-	err = s5k83a_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]);
-	if (err < 0)
-		return err;
+	v4l2_ctrl_new_std(hdl, &s5k83a_ctrl_ops, V4L2_CID_BRIGHTNESS,
+			  0, 255, 1, S5K83A_DEFAULT_BRIGHTNESS);
 
-	err = s5k83a_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]);
+	v4l2_ctrl_new_std(hdl, &s5k83a_ctrl_ops, V4L2_CID_EXPOSURE,
+			  0, S5K83A_MAXIMUM_EXPOSURE, 1,
+			  S5K83A_DEFAULT_EXPOSURE);
 
-	return err;
+	v4l2_ctrl_new_std(hdl, &s5k83a_ctrl_ops, V4L2_CID_GAIN,
+			  0, 255, 1, S5K83A_DEFAULT_GAIN);
+
+	sd->hflip = v4l2_ctrl_new_std(hdl, &s5k83a_ctrl_ops, V4L2_CID_HFLIP,
+				      0, 1, 1, 0);
+	sd->vflip = v4l2_ctrl_new_std(hdl, &s5k83a_ctrl_ops, V4L2_CID_VFLIP,
+				      0, 1, 1, 0);
+
+	if (hdl->error) {
+		pr_err("Could not initialize controls\n");
+		return hdl->error;
+	}
+
+	v4l2_ctrl_cluster(2, &sd->hflip);
+
+	return 0;
 }
 
 static int rotation_thread_function(void *data)
 {
 	struct sd *sd = (struct sd *) data;
-	struct s5k83a_priv *sens_priv = sd->sensor_priv;
 	u8 reg, previous_rotation = 0;
 	__s32 vflip, hflip;
 
@@ -277,8 +186,8 @@ static int rotation_thread_function(void *data)
 			previous_rotation = reg;
 			pr_info("Camera was flipped\n");
 
-			s5k83a_get_vflip((struct gspca_dev *) sd, &vflip);
-			s5k83a_get_hflip((struct gspca_dev *) sd, &hflip);
+			hflip = sd->hflip->val;
+			vflip = sd->vflip->val;
 
 			if (reg) {
 				vflip = !vflip;
@@ -294,26 +203,25 @@ static int rotation_thread_function(void *data)
 
 	/* return to "front" flip */
 	if (previous_rotation) {
-		s5k83a_get_vflip((struct gspca_dev *) sd, &vflip);
-		s5k83a_get_hflip((struct gspca_dev *) sd, &hflip);
+		hflip = sd->hflip->val;
+		vflip = sd->vflip->val;
 		s5k83a_set_flip_real((struct gspca_dev *) sd, vflip, hflip);
 	}
 
-	sens_priv->rotation_thread = NULL;
+	sd->rotation_thread = NULL;
 	return 0;
 }
 
 int s5k83a_start(struct sd *sd)
 {
 	int i, err = 0;
-	struct s5k83a_priv *sens_priv = sd->sensor_priv;
 
 	/* Create another thread, polling the GPIO ports of the camera to check
 	   if it got rotated. This is how the windows driver does it so we have
 	   to assume that there is no better way of accomplishing this */
-	sens_priv->rotation_thread = kthread_create(rotation_thread_function,
-						    sd, "rotation thread");
-	wake_up_process(sens_priv->rotation_thread);
+	sd->rotation_thread = kthread_create(rotation_thread_function,
+					     sd, "rotation thread");
+	wake_up_process(sd->rotation_thread);
 
 	/* Preinit the sensor */
 	for (i = 0; i < ARRAY_SIZE(start_s5k83a) && !err; i++) {
@@ -333,32 +241,17 @@ int s5k83a_start(struct sd *sd)
 
 int s5k83a_stop(struct sd *sd)
 {
-	struct s5k83a_priv *sens_priv = sd->sensor_priv;
-
-	if (sens_priv->rotation_thread)
-		kthread_stop(sens_priv->rotation_thread);
+	if (sd->rotation_thread)
+		kthread_stop(sd->rotation_thread);
 
 	return s5k83a_set_led_indication(sd, 0);
 }
 
 void s5k83a_disconnect(struct sd *sd)
 {
-	struct s5k83a_priv *sens_priv = sd->sensor_priv;
-
 	s5k83a_stop(sd);
 
 	sd->sensor = NULL;
-	kfree(sens_priv->settings);
-	kfree(sens_priv);
-}
-
-static int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-	struct s5k83a_priv *sens_priv = sd->sensor_priv;
-
-	*val = sens_priv->settings[GAIN_IDX];
-	return 0;
 }
 
 static int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val)
@@ -366,9 +259,6 @@ static int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val)
 	int err;
 	u8 data[2];
 	struct sd *sd = (struct sd *) gspca_dev;
-	struct s5k83a_priv *sens_priv = sd->sensor_priv;
-
-	sens_priv->settings[GAIN_IDX] = val;
 
 	data[0] = 0x00;
 	data[1] = 0x20;
@@ -391,60 +281,29 @@ static int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val)
 	return err;
 }
 
-static int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-	struct s5k83a_priv *sens_priv = sd->sensor_priv;
-
-	*val = sens_priv->settings[BRIGHTNESS_IDX];
-	return 0;
-}
-
 static int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
 {
 	int err;
 	u8 data[1];
 	struct sd *sd = (struct sd *) gspca_dev;
-	struct s5k83a_priv *sens_priv = sd->sensor_priv;
 
-	sens_priv->settings[BRIGHTNESS_IDX] = val;
 	data[0] = val;
 	err = m5602_write_sensor(sd, S5K83A_BRIGHTNESS, data, 1);
 	return err;
 }
 
-static int s5k83a_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-	struct s5k83a_priv *sens_priv = sd->sensor_priv;
-
-	*val = sens_priv->settings[EXPOSURE_IDX];
-	return 0;
-}
-
 static int s5k83a_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
 {
 	int err;
 	u8 data[2];
 	struct sd *sd = (struct sd *) gspca_dev;
-	struct s5k83a_priv *sens_priv = sd->sensor_priv;
 
-	sens_priv->settings[EXPOSURE_IDX] = val;
 	data[0] = 0;
 	data[1] = val;
 	err = m5602_write_sensor(sd, S5K83A_EXPOSURE, data, 2);
 	return err;
 }
 
-static int s5k83a_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-	struct s5k83a_priv *sens_priv = sd->sensor_priv;
-
-	*val = sens_priv->settings[VFLIP_IDX];
-	return 0;
-}
-
 static int s5k83a_set_flip_real(struct gspca_dev *gspca_dev,
 				__s32 vflip, __s32 hflip)
 {
@@ -476,60 +335,52 @@ static int s5k83a_set_flip_real(struct gspca_dev *gspca_dev,
 	return err;
 }
 
-static int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
+static int s5k83a_set_hvflip(struct gspca_dev *gspca_dev)
 {
 	int err;
 	u8 reg;
-	__s32 hflip;
 	struct sd *sd = (struct sd *) gspca_dev;
-	struct s5k83a_priv *sens_priv = sd->sensor_priv;
-
-	sens_priv->settings[VFLIP_IDX] = val;
-
-	s5k83a_get_hflip(gspca_dev, &hflip);
+	int hflip = sd->hflip->val;
+	int vflip = sd->vflip->val;
 
 	err = s5k83a_get_rotation(sd, &reg);
 	if (err < 0)
 		return err;
 	if (reg) {
-		val = !val;
 		hflip = !hflip;
+		vflip = !vflip;
 	}
 
-	err = s5k83a_set_flip_real(gspca_dev, val, hflip);
+	err = s5k83a_set_flip_real(gspca_dev, vflip, hflip);
 	return err;
 }
 
-static int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-	struct s5k83a_priv *sens_priv = sd->sensor_priv;
-
-	*val = sens_priv->settings[HFLIP_IDX];
-	return 0;
-}
-
-static int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
+static int s5k83a_s_ctrl(struct v4l2_ctrl *ctrl)
 {
+	struct gspca_dev *gspca_dev =
+		container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
 	int err;
-	u8 reg;
-	__s32 vflip;
-	struct sd *sd = (struct sd *) gspca_dev;
-	struct s5k83a_priv *sens_priv = sd->sensor_priv;
-
-	sens_priv->settings[HFLIP_IDX] = val;
 
-	s5k83a_get_vflip(gspca_dev, &vflip);
-
-	err = s5k83a_get_rotation(sd, &reg);
-	if (err < 0)
-		return err;
-	if (reg) {
-		val = !val;
-		vflip = !vflip;
+	if (!gspca_dev->streaming)
+		return 0;
+
+	switch (ctrl->id) {
+	case V4L2_CID_BRIGHTNESS:
+		err = s5k83a_set_brightness(gspca_dev, ctrl->val);
+		break;
+	case V4L2_CID_EXPOSURE:
+		err = s5k83a_set_exposure(gspca_dev, ctrl->val);
+		break;
+	case V4L2_CID_GAIN:
+		err = s5k83a_set_gain(gspca_dev, ctrl->val);
+		break;
+	case V4L2_CID_HFLIP:
+		err = s5k83a_set_hvflip(gspca_dev);
+		break;
+	default:
+		return -EINVAL;
 	}
 
-	err = s5k83a_set_flip_real(gspca_dev, vflip, val);
 	return err;
 }
 
diff --git a/drivers/media/usb/gspca/m5602/m5602_s5k83a.h b/drivers/media/usb/gspca/m5602/m5602_s5k83a.h
index 7995224..d61b918 100644
--- a/drivers/media/usb/gspca/m5602/m5602_s5k83a.h
+++ b/drivers/media/usb/gspca/m5602/m5602_s5k83a.h
@@ -45,6 +45,7 @@ extern bool dump_sensor;
 
 int s5k83a_probe(struct sd *sd);
 int s5k83a_init(struct sd *sd);
+int s5k83a_init_controls(struct sd *sd);
 int s5k83a_start(struct sd *sd);
 int s5k83a_stop(struct sd *sd);
 void s5k83a_disconnect(struct sd *sd);
@@ -53,6 +54,7 @@ static const struct m5602_sensor s5k83a = {
 	.name = "S5K83A",
 	.probe = s5k83a_probe,
 	.init = s5k83a_init,
+	.init_controls = s5k83a_init_controls,
 	.start = s5k83a_start,
 	.stop = s5k83a_stop,
 	.disconnect = s5k83a_disconnect,
@@ -60,13 +62,6 @@ static const struct m5602_sensor s5k83a = {
 	.i2c_regW = 2,
 };
 
-struct s5k83a_priv {
-	/* We use another thread periodically
-	   probing the orientation of the camera */
-	struct task_struct *rotation_thread;
-	s32 *settings;
-};
-
 static const unsigned char preinit_s5k83a[][4] = {
 	{BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
 	{BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
diff --git a/drivers/media/usb/gspca/m5602/m5602_sensor.h b/drivers/media/usb/gspca/m5602/m5602_sensor.h
index edff4f1..48341b4 100644
--- a/drivers/media/usb/gspca/m5602/m5602_sensor.h
+++ b/drivers/media/usb/gspca/m5602/m5602_sensor.h
@@ -57,6 +57,9 @@ struct m5602_sensor {
 	/* Performs a initialization sequence */
 	int (*init)(struct sd *sd);
 
+	/* Controls initialization, maybe NULL */
+	int (*init_controls)(struct sd *sd);
+
 	/* Executed when the camera starts to send data */
 	int (*start)(struct sd *sd);
 
diff --git a/drivers/media/usb/gspca/mr97310a.c b/drivers/media/usb/gspca/mr97310a.c
index 8f4714d..68bb2f3 100644
--- a/drivers/media/usb/gspca/mr97310a.c
+++ b/drivers/media/usb/gspca/mr97310a.c
@@ -289,7 +289,7 @@ static int zero_the_pointer(struct gspca_dev *gspca_dev)
 			return err_code;
 	}
 	if (status != 0x0a)
-		PDEBUG(D_ERR, "status is %02x", status);
+		PERR("status is %02x", status);
 
 	tries = 0;
 	while (tries < 4) {
@@ -330,7 +330,7 @@ static void stream_stop(struct gspca_dev *gspca_dev)
 	gspca_dev->usb_buf[0] = 0x01;
 	gspca_dev->usb_buf[1] = 0x00;
 	if (mr_write(gspca_dev, 2) < 0)
-		PDEBUG(D_ERR, "Stream Stop failed");
+		PERR("Stream Stop failed");
 }
 
 static void lcd_stop(struct gspca_dev *gspca_dev)
@@ -338,7 +338,7 @@ static void lcd_stop(struct gspca_dev *gspca_dev)
 	gspca_dev->usb_buf[0] = 0x19;
 	gspca_dev->usb_buf[1] = 0x54;
 	if (mr_write(gspca_dev, 2) < 0)
-		PDEBUG(D_ERR, "LCD Stop failed");
+		PERR("LCD Stop failed");
 }
 
 static int isoc_enable(struct gspca_dev *gspca_dev)
@@ -1026,7 +1026,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
 	struct sd *sd = (struct sd *) gspca_dev;
 	unsigned char *sof;
 
-	sof = pac_find_sof(&sd->sof_read, data, len);
+	sof = pac_find_sof(gspca_dev, &sd->sof_read, data, len);
 	if (sof) {
 		int n;
 
diff --git a/drivers/media/usb/gspca/ov519.c b/drivers/media/usb/gspca/ov519.c
index 9ad19a7..a3958ee 100644
--- a/drivers/media/usb/gspca/ov519.c
+++ b/drivers/media/usb/gspca/ov519.c
@@ -2034,6 +2034,7 @@ static unsigned char ov7670_abs_to_sm(unsigned char v)
 /* Write a OV519 register */
 static void reg_w(struct sd *sd, u16 index, u16 value)
 {
+	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
 	int ret, req = 0;
 
 	if (sd->gspca_dev.usb_err < 0)
@@ -2071,7 +2072,7 @@ static void reg_w(struct sd *sd, u16 index, u16 value)
 			sd->gspca_dev.usb_buf, 1, 500);
 leave:
 	if (ret < 0) {
-		pr_err("reg_w %02x failed %d\n", index, ret);
+		PERR("reg_w %02x failed %d\n", index, ret);
 		sd->gspca_dev.usb_err = ret;
 		return;
 	}
@@ -2081,6 +2082,7 @@ leave:
 /* returns: negative is error, pos or zero is data */
 static int reg_r(struct sd *sd, u16 index)
 {
+	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
 	int ret;
 	int req;
 
@@ -2110,7 +2112,7 @@ static int reg_r(struct sd *sd, u16 index)
 		PDEBUG(D_USBI, "GET %02x 0000 %04x %02x",
 			req, index, ret);
 	} else {
-		pr_err("reg_r %02x failed %d\n", index, ret);
+		PERR("reg_r %02x failed %d\n", index, ret);
 		sd->gspca_dev.usb_err = ret;
 	}
 
@@ -2121,6 +2123,7 @@ static int reg_r(struct sd *sd, u16 index)
 static int reg_r8(struct sd *sd,
 		  u16 index)
 {
+	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
 	int ret;
 
 	if (sd->gspca_dev.usb_err < 0)
@@ -2135,7 +2138,7 @@ static int reg_r8(struct sd *sd,
 	if (ret >= 0) {
 		ret = sd->gspca_dev.usb_buf[0];
 	} else {
-		pr_err("reg_r8 %02x failed %d\n", index, ret);
+		PERR("reg_r8 %02x failed %d\n", index, ret);
 		sd->gspca_dev.usb_err = ret;
 	}
 
@@ -2174,6 +2177,7 @@ static void reg_w_mask(struct sd *sd,
  */
 static void ov518_reg_w32(struct sd *sd, u16 index, u32 value, int n)
 {
+	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
 	int ret;
 
 	if (sd->gspca_dev.usb_err < 0)
@@ -2188,13 +2192,14 @@ static void ov518_reg_w32(struct sd *sd, u16 index, u32 value, int n)
 			0, index,
 			sd->gspca_dev.usb_buf, n, 500);
 	if (ret < 0) {
-		pr_err("reg_w32 %02x failed %d\n", index, ret);
+		PERR("reg_w32 %02x failed %d\n", index, ret);
 		sd->gspca_dev.usb_err = ret;
 	}
 }
 
 static void ov511_i2c_w(struct sd *sd, u8 reg, u8 value)
 {
+	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
 	int rc, retries;
 
 	PDEBUG(D_USBO, "ov511_i2c_w %02x %02x", reg, value);
@@ -2228,6 +2233,7 @@ static void ov511_i2c_w(struct sd *sd, u8 reg, u8 value)
 
 static int ov511_i2c_r(struct sd *sd, u8 reg)
 {
+	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
 	int rc, value, retries;
 
 	/* Two byte write cycle */
@@ -2300,6 +2306,8 @@ static void ov518_i2c_w(struct sd *sd,
 		u8 reg,
 		u8 value)
 {
+	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
+
 	PDEBUG(D_USBO, "ov518_i2c_w %02x %02x", reg, value);
 
 	/* Select camera register */
@@ -2325,6 +2333,7 @@ static void ov518_i2c_w(struct sd *sd,
  */
 static int ov518_i2c_r(struct sd *sd, u8 reg)
 {
+	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
 	int value;
 
 	/* Select camera register */
@@ -2345,6 +2354,7 @@ static int ov518_i2c_r(struct sd *sd, u8 reg)
 
 static void ovfx2_i2c_w(struct sd *sd, u8 reg, u8 value)
 {
+	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
 	int ret;
 
 	if (sd->gspca_dev.usb_err < 0)
@@ -2357,7 +2367,7 @@ static void ovfx2_i2c_w(struct sd *sd, u8 reg, u8 value)
 			(u16) value, (u16) reg, NULL, 0, 500);
 
 	if (ret < 0) {
-		pr_err("ovfx2_i2c_w %02x failed %d\n", reg, ret);
+		PERR("ovfx2_i2c_w %02x failed %d\n", reg, ret);
 		sd->gspca_dev.usb_err = ret;
 	}
 
@@ -2366,6 +2376,7 @@ static void ovfx2_i2c_w(struct sd *sd, u8 reg, u8 value)
 
 static int ovfx2_i2c_r(struct sd *sd, u8 reg)
 {
+	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
 	int ret;
 
 	if (sd->gspca_dev.usb_err < 0)
@@ -2381,7 +2392,7 @@ static int ovfx2_i2c_r(struct sd *sd, u8 reg)
 		ret = sd->gspca_dev.usb_buf[0];
 		PDEBUG(D_USBI, "ovfx2_i2c_r %02x %02x", reg, ret);
 	} else {
-		pr_err("ovfx2_i2c_r %02x failed %d\n", reg, ret);
+		PERR("ovfx2_i2c_r %02x failed %d\n", reg, ret);
 		sd->gspca_dev.usb_err = ret;
 	}
 
@@ -2478,6 +2489,8 @@ static void i2c_w_mask(struct sd *sd,
  * registers while the camera is streaming */
 static inline void ov51x_stop(struct sd *sd)
 {
+	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
+
 	PDEBUG(D_STREAM, "stopping");
 	sd->stopped = 1;
 	switch (sd->bridge) {
@@ -2507,6 +2520,8 @@ static inline void ov51x_stop(struct sd *sd)
  * actually stopped (for performance). */
 static inline void ov51x_restart(struct sd *sd)
 {
+	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
+
 	PDEBUG(D_STREAM, "restarting");
 	if (!sd->stopped)
 		return;
@@ -2545,6 +2560,7 @@ static void ov51x_set_slave_ids(struct sd *sd, u8 slave);
 static int init_ov_sensor(struct sd *sd, u8 slave)
 {
 	int i;
+	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
 
 	ov51x_set_slave_ids(sd, slave);
 
@@ -2624,10 +2640,11 @@ static void write_i2c_regvals(struct sd *sd,
 /* This initializes the OV2x10 / OV3610 / OV3620 / OV9600 */
 static void ov_hires_configure(struct sd *sd)
 {
+	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
 	int high, low;
 
 	if (sd->bridge != BRIDGE_OVFX2) {
-		pr_err("error hires sensors only supported with ovfx2\n");
+		PERR("error hires sensors only supported with ovfx2\n");
 		return;
 	}
 
@@ -2662,7 +2679,7 @@ static void ov_hires_configure(struct sd *sd)
 		}
 		break;
 	}
-	pr_err("Error unknown sensor type: %02x%02x\n", high, low);
+	PERR("Error unknown sensor type: %02x%02x\n", high, low);
 }
 
 /* This initializes the OV8110, OV8610 sensor. The OV8110 uses
@@ -2670,6 +2687,7 @@ static void ov_hires_configure(struct sd *sd)
  */
 static void ov8xx0_configure(struct sd *sd)
 {
+	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
 	int rc;
 
 	PDEBUG(D_PROBE, "starting ov8xx0 configuration");
@@ -2677,13 +2695,13 @@ static void ov8xx0_configure(struct sd *sd)
 	/* Detect sensor (sub)type */
 	rc = i2c_r(sd, OV7610_REG_COM_I);
 	if (rc < 0) {
-		PDEBUG(D_ERR, "Error detecting sensor type");
+		PERR("Error detecting sensor type");
 		return;
 	}
 	if ((rc & 3) == 1)
 		sd->sensor = SEN_OV8610;
 	else
-		pr_err("Unknown image sensor version: %d\n", rc & 3);
+		PERR("Unknown image sensor version: %d\n", rc & 3);
 }
 
 /* This initializes the OV7610, OV7620, or OV76BE sensor. The OV76BE uses
@@ -2691,6 +2709,7 @@ static void ov8xx0_configure(struct sd *sd)
  */
 static void ov7xx0_configure(struct sd *sd)
 {
+	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
 	int rc, high, low;
 
 	PDEBUG(D_PROBE, "starting OV7xx0 configuration");
@@ -2701,7 +2720,7 @@ static void ov7xx0_configure(struct sd *sd)
 	/* add OV7670 here
 	 * it appears to be wrongly detected as a 7610 by default */
 	if (rc < 0) {
-		pr_err("Error detecting sensor type\n");
+		PERR("Error detecting sensor type\n");
 		return;
 	}
 	if ((rc & 3) == 3) {
@@ -2729,19 +2748,19 @@ static void ov7xx0_configure(struct sd *sd)
 		/* try to read product id registers */
 		high = i2c_r(sd, 0x0a);
 		if (high < 0) {
-			pr_err("Error detecting camera chip PID\n");
+			PERR("Error detecting camera chip PID\n");
 			return;
 		}
 		low = i2c_r(sd, 0x0b);
 		if (low < 0) {
-			pr_err("Error detecting camera chip VER\n");
+			PERR("Error detecting camera chip VER\n");
 			return;
 		}
 		if (high == 0x76) {
 			switch (low) {
 			case 0x30:
-				pr_err("Sensor is an OV7630/OV7635\n");
-				pr_err("7630 is not supported by this driver\n");
+				PERR("Sensor is an OV7630/OV7635\n");
+				PERR("7630 is not supported by this driver\n");
 				return;
 			case 0x40:
 				PDEBUG(D_PROBE, "Sensor is an OV7645");
@@ -2760,7 +2779,7 @@ static void ov7xx0_configure(struct sd *sd)
 				sd->sensor = SEN_OV7660;
 				break;
 			default:
-				pr_err("Unknown sensor: 0x76%02x\n", low);
+				PERR("Unknown sensor: 0x76%02x\n", low);
 				return;
 			}
 		} else {
@@ -2768,20 +2787,22 @@ static void ov7xx0_configure(struct sd *sd)
 			sd->sensor = SEN_OV7620;
 		}
 	} else {
-		pr_err("Unknown image sensor version: %d\n", rc & 3);
+		PERR("Unknown image sensor version: %d\n", rc & 3);
 	}
 }
 
 /* This initializes the OV6620, OV6630, OV6630AE, or OV6630AF sensor. */
 static void ov6xx0_configure(struct sd *sd)
 {
+	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
 	int rc;
+
 	PDEBUG(D_PROBE, "starting OV6xx0 configuration");
 
 	/* Detect sensor (sub)type */
 	rc = i2c_r(sd, OV7610_REG_COM_I);
 	if (rc < 0) {
-		pr_err("Error detecting sensor type\n");
+		PERR("Error detecting sensor type\n");
 		return;
 	}
 
@@ -2810,7 +2831,7 @@ static void ov6xx0_configure(struct sd *sd)
 		pr_warn("WARNING: Sensor is an OV66307. Your camera may have been misdetected in previous driver versions.\n");
 		break;
 	default:
-		pr_err("FATAL: Unknown sensor version: 0x%02x\n", rc);
+		PERR("FATAL: Unknown sensor version: 0x%02x\n", rc);
 		return;
 	}
 
@@ -2907,6 +2928,7 @@ static void ov51x_upload_quan_tables(struct sd *sd)
 		7, 7, 7, 7, 7, 7, 8, 8
 	};
 
+	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
 	const unsigned char *pYTable, *pUVTable;
 	unsigned char val0, val1;
 	int i, size, reg = R51x_COMP_LUT_BEGIN;
@@ -3300,7 +3322,7 @@ static int sd_init(struct gspca_dev *gspca_dev)
 	} else if (init_ov_sensor(sd, OV_HIRES_SID) >= 0) {
 		ov_hires_configure(sd);
 	} else {
-		pr_err("Can't determine sensor slave IDs\n");
+		PERR("Can't determine sensor slave IDs\n");
 		goto error;
 	}
 
@@ -3433,7 +3455,7 @@ static int sd_init(struct gspca_dev *gspca_dev)
 	}
 	return gspca_dev->usb_err;
 error:
-	PDEBUG(D_ERR, "OV519 Config failed");
+	PERR("OV519 Config failed");
 	return -EINVAL;
 }
 
@@ -3459,6 +3481,7 @@ static int sd_isoc_init(struct gspca_dev *gspca_dev)
  */
 static void ov511_mode_init_regs(struct sd *sd)
 {
+	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
 	int hsegs, vsegs, packet_size, fps, needed;
 	int interlaced = 0;
 	struct usb_host_interface *alt;
@@ -3467,7 +3490,7 @@ static void ov511_mode_init_regs(struct sd *sd)
 	intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
 	alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
 	if (!alt) {
-		pr_err("Couldn't get altsetting\n");
+		PERR("Couldn't get altsetting\n");
 		sd->gspca_dev.usb_err = -EIO;
 		return;
 	}
@@ -3583,6 +3606,7 @@ static void ov511_mode_init_regs(struct sd *sd)
  */
 static void ov518_mode_init_regs(struct sd *sd)
 {
+	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
 	int hsegs, vsegs, packet_size;
 	struct usb_host_interface *alt;
 	struct usb_interface *intf;
@@ -3590,7 +3614,7 @@ static void ov518_mode_init_regs(struct sd *sd)
 	intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
 	alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
 	if (!alt) {
-		pr_err("Couldn't get altsetting\n");
+		PERR("Couldn't get altsetting\n");
 		sd->gspca_dev.usb_err = -EIO;
 		return;
 	}
@@ -3750,6 +3774,8 @@ static void ov519_mode_init_regs(struct sd *sd)
 		/* windows reads 0x55 at this point, why? */
 	};
 
+	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
+
 	/******** Set the mode ********/
 	switch (sd->sensor) {
 	default:
@@ -3865,11 +3891,10 @@ static void ov519_mode_init_regs(struct sd *sd)
 
 static void mode_init_ov_sensor_regs(struct sd *sd)
 {
-	struct gspca_dev *gspca_dev;
+	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
 	int qvga, xstart, xend, ystart, yend;
 	u8 v;
 
-	gspca_dev = &sd->gspca_dev;
 	qvga = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv & 1;
 
 	/******** Mode (VGA/QVGA) and sensor specific regs ********/
@@ -4304,7 +4329,7 @@ static void ov511_pkt_scan(struct gspca_dev *gspca_dev,
 			/* Frame end */
 			if ((in[9] + 1) * 8 != gspca_dev->width ||
 			    (in[10] + 1) * 8 != gspca_dev->height) {
-				PDEBUG(D_ERR, "Invalid frame size, got: %dx%d,"
+				PERR("Invalid frame size, got: %dx%d,"
 					" requested: %dx%d\n",
 					(in[9] + 1) * 8, (in[10] + 1) * 8,
 					gspca_dev->width, gspca_dev->height);
@@ -4355,7 +4380,7 @@ static void ov518_pkt_scan(struct gspca_dev *gspca_dev,
 		   except that they may contain part of the footer), are
 		   numbered 0 */
 		else if (sd->packet_nr == 0 || data[len]) {
-			PDEBUG(D_ERR, "Invalid packet nr: %d (expect: %d)",
+			PERR("Invalid packet nr: %d (expect: %d)",
 				(int)data[len], (int)sd->packet_nr);
 			gspca_dev->last_packet_type = DISCARD_PACKET;
 			return;
@@ -4898,7 +4923,7 @@ static int sd_init_controls(struct gspca_dev *gspca_dev)
 			QUALITY_MIN, QUALITY_MAX, 1, QUALITY_DEF);
 
 	if (hdl->error) {
-		pr_err("Could not initialize controls\n");
+		PERR("Could not initialize controls\n");
 		return hdl->error;
 	}
 	if (gspca_dev->autogain)
diff --git a/drivers/media/usb/gspca/ov534.c b/drivers/media/usb/gspca/ov534.c
index bb09d78..2e28c81 100644
--- a/drivers/media/usb/gspca/ov534.c
+++ b/drivers/media/usb/gspca/ov534.c
@@ -690,7 +690,7 @@ static int sccb_check_status(struct gspca_dev *gspca_dev)
 		case 0x03:
 			break;
 		default:
-			PDEBUG(D_ERR, "sccb status 0x%02x, attempt %d/5",
+			PERR("sccb status 0x%02x, attempt %d/5",
 			       data, i + 1);
 		}
 	}
diff --git a/drivers/media/usb/gspca/pac207.c b/drivers/media/usb/gspca/pac207.c
index 3b75097..83519be 100644
--- a/drivers/media/usb/gspca/pac207.c
+++ b/drivers/media/usb/gspca/pac207.c
@@ -373,7 +373,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
 	struct sd *sd = (struct sd *) gspca_dev;
 	unsigned char *sof;
 
-	sof = pac_find_sof(&sd->sof_read, data, len);
+	sof = pac_find_sof(gspca_dev, &sd->sof_read, data, len);
 	if (sof) {
 		int n;
 
diff --git a/drivers/media/usb/gspca/pac7302.c b/drivers/media/usb/gspca/pac7302.c
index add6f72..6008c8d 100644
--- a/drivers/media/usb/gspca/pac7302.c
+++ b/drivers/media/usb/gspca/pac7302.c
@@ -344,13 +344,10 @@ static void reg_w_var(struct gspca_dev *gspca_dev,
 			reg_w_page(gspca_dev, page3, page3_len);
 			break;
 		default:
-#ifdef GSPCA_DEBUG
 			if (len > USB_BUF_SZ) {
-				PDEBUG(D_ERR|D_STREAM,
-					"Incorrect variable sequence");
+				PERR("Incorrect variable sequence");
 				return;
 			}
-#endif
 			while (len > 0) {
 				if (len < 8) {
 					reg_w_buf(gspca_dev,
@@ -795,7 +792,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
 	u8 *image;
 	u8 *sof;
 
-	sof = pac_find_sof(&sd->sof_read, data, len);
+	sof = pac_find_sof(gspca_dev, &sd->sof_read, data, len);
 	if (sof) {
 		int n, lum_offset, footer_length;
 
@@ -843,7 +840,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 static int sd_dbg_s_register(struct gspca_dev *gspca_dev,
-			struct v4l2_dbg_register *reg)
+			const struct v4l2_dbg_register *reg)
 {
 	u8 index;
 	u8 value;
diff --git a/drivers/media/usb/gspca/pac7311.c b/drivers/media/usb/gspca/pac7311.c
index a12dfbf..1a5bdc8 100644
--- a/drivers/media/usb/gspca/pac7311.c
+++ b/drivers/media/usb/gspca/pac7311.c
@@ -262,8 +262,7 @@ static void reg_w_var(struct gspca_dev *gspca_dev,
 			break;
 		default:
 			if (len > USB_BUF_SZ) {
-				PDEBUG(D_ERR|D_STREAM,
-					"Incorrect variable sequence");
+				PERR("Incorrect variable sequence");
 				return;
 			}
 			while (len > 0) {
@@ -575,7 +574,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
 	u8 *image;
 	unsigned char *sof;
 
-	sof = pac_find_sof(&sd->sof_read, data, len);
+	sof = pac_find_sof(gspca_dev, &sd->sof_read, data, len);
 	if (sof) {
 		int n, lum_offset, footer_length;
 
diff --git a/drivers/media/usb/gspca/pac_common.h b/drivers/media/usb/gspca/pac_common.h
index 8462a7c..fbc5e22 100644
--- a/drivers/media/usb/gspca/pac_common.h
+++ b/drivers/media/usb/gspca/pac_common.h
@@ -71,7 +71,7 @@ static const unsigned char pac_sof_marker[5] =
 	   +----------+
 */
 
-static unsigned char *pac_find_sof(u8 *sof_read,
+static unsigned char *pac_find_sof(struct gspca_dev *gspca_dev, u8 *sof_read,
 					unsigned char *m, int len)
 {
 	int i;
diff --git a/drivers/media/usb/gspca/sn9c2028.c b/drivers/media/usb/gspca/sn9c2028.c
index 03fa3fd..39b6b2e 100644
--- a/drivers/media/usb/gspca/sn9c2028.c
+++ b/drivers/media/usb/gspca/sn9c2028.c
@@ -650,13 +650,13 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
 
 	result = sn9c2028_read1(gspca_dev);
 	if (result < 0)
-		PDEBUG(D_ERR, "Camera Stop read failed");
+		PERR("Camera Stop read failed");
 
 	memset(data, 0, 6);
 	data[0] = 0x14;
 	result = sn9c2028_command(gspca_dev, data);
 	if (result < 0)
-		PDEBUG(D_ERR, "Camera Stop command failed");
+		PERR("Camera Stop command failed");
 }
 
 /* Include sn9c2028 sof detection functions */
diff --git a/drivers/media/usb/gspca/sn9c20x.c b/drivers/media/usb/gspca/sn9c20x.c
index 4ec544f..ead9a1f 100644
--- a/drivers/media/usb/gspca/sn9c20x.c
+++ b/drivers/media/usb/gspca/sn9c20x.c
@@ -1598,7 +1598,7 @@ static int sd_dbg_g_register(struct gspca_dev *gspca_dev,
 }
 
 static int sd_dbg_s_register(struct gspca_dev *gspca_dev,
-			struct v4l2_dbg_register *reg)
+			const struct v4l2_dbg_register *reg)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 
diff --git a/drivers/media/usb/gspca/sonixb.c b/drivers/media/usb/gspca/sonixb.c
index 104ae25..3fe207e 100644
--- a/drivers/media/usb/gspca/sonixb.c
+++ b/drivers/media/usb/gspca/sonixb.c
@@ -1379,27 +1379,6 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
 	}
 }
 
-static int sd_querymenu(struct gspca_dev *gspca_dev,
-			struct v4l2_querymenu *menu)
-{
-	switch (menu->id) {
-	case V4L2_CID_POWER_LINE_FREQUENCY:
-		switch (menu->index) {
-		case 0:		/* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
-			strcpy((char *) menu->name, "NoFliker");
-			return 0;
-		case 1:		/* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
-			strcpy((char *) menu->name, "50 Hz");
-			return 0;
-		case 2:		/* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
-			strcpy((char *) menu->name, "60 Hz");
-			return 0;
-		}
-		break;
-	}
-	return -EINVAL;
-}
-
 #if IS_ENABLED(CONFIG_INPUT)
 static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
 			u8 *data,		/* interrupt packet data */
@@ -1428,7 +1407,6 @@ static const struct sd_desc sd_desc = {
 	.start = sd_start,
 	.stopN = sd_stopN,
 	.pkt_scan = sd_pkt_scan,
-	.querymenu = sd_querymenu,
 	.dq_callback = do_autogain,
 #if IS_ENABLED(CONFIG_INPUT)
 	.int_pkt_scan = sd_int_pkt_scan,
diff --git a/drivers/media/usb/gspca/sonixj.c b/drivers/media/usb/gspca/sonixj.c
index 671d0c6..3b5ccb1 100644
--- a/drivers/media/usb/gspca/sonixj.c
+++ b/drivers/media/usb/gspca/sonixj.c
@@ -31,32 +31,26 @@ MODULE_AUTHOR("Jean-François Moine <http://moinejf.free.fr>");
 MODULE_DESCRIPTION("GSPCA/SONIX JPEG USB Camera Driver");
 MODULE_LICENSE("GPL");
 
-/* controls */
-enum e_ctrl {
-	BRIGHTNESS,
-	CONTRAST,
-	COLORS,
-	BLUE,
-	RED,
-	GAMMA,
-	EXPOSURE,
-	AUTOGAIN,
-	GAIN,
-	HFLIP,
-	VFLIP,
-	SHARPNESS,
-	ILLUM,
-	FREQ,
-	NCTRLS		/* number of controls */
-};
-
 /* specific webcam descriptor */
 struct sd {
 	struct gspca_dev gspca_dev;	/* !! must be the first item */
 
-	struct gspca_ctrl ctrls[NCTRLS];
-
 	atomic_t avg_lum;
+	struct v4l2_ctrl *brightness;
+	struct v4l2_ctrl *contrast;
+	struct v4l2_ctrl *saturation;
+	struct { /* red/blue balance control cluster */
+		struct v4l2_ctrl *red_bal;
+		struct v4l2_ctrl *blue_bal;
+	};
+	struct { /* hflip/vflip control cluster */
+		struct v4l2_ctrl *vflip;
+		struct v4l2_ctrl *hflip;
+	};
+	struct v4l2_ctrl *gamma;
+	struct v4l2_ctrl *illum;
+	struct v4l2_ctrl *sharpness;
+	struct v4l2_ctrl *freq;
 	u32 exposure;
 
 	struct work_struct work;
@@ -127,283 +121,6 @@ static void qual_upd(struct work_struct *work);
 #define SEN_CLK_EN	0x20	/* enable sensor clock */
 #define DEF_EN		0x80	/* defect pixel by 0: soft, 1: hard */
 
-/* V4L2 controls supported by the driver */
-static void setbrightness(struct gspca_dev *gspca_dev);
-static void setcontrast(struct gspca_dev *gspca_dev);
-static void setcolors(struct gspca_dev *gspca_dev);
-static void setredblue(struct gspca_dev *gspca_dev);
-static void setgamma(struct gspca_dev *gspca_dev);
-static void setexposure(struct gspca_dev *gspca_dev);
-static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
-static void setgain(struct gspca_dev *gspca_dev);
-static void sethvflip(struct gspca_dev *gspca_dev);
-static void setsharpness(struct gspca_dev *gspca_dev);
-static void setillum(struct gspca_dev *gspca_dev);
-static void setfreq(struct gspca_dev *gspca_dev);
-
-static const struct ctrl sd_ctrls[NCTRLS] = {
-[BRIGHTNESS] = {
-	    {
-		.id      = V4L2_CID_BRIGHTNESS,
-		.type    = V4L2_CTRL_TYPE_INTEGER,
-		.name    = "Brightness",
-		.minimum = 0,
-		.maximum = 0xff,
-		.step    = 1,
-		.default_value = 0x80,
-	    },
-	    .set_control = setbrightness
-	},
-[CONTRAST] = {
-	    {
-		.id      = V4L2_CID_CONTRAST,
-		.type    = V4L2_CTRL_TYPE_INTEGER,
-		.name    = "Contrast",
-		.minimum = 0,
-#define CONTRAST_MAX 127
-		.maximum = CONTRAST_MAX,
-		.step    = 1,
-		.default_value = 20,
-	    },
-	    .set_control = setcontrast
-	},
-[COLORS] = {
-	    {
-		.id      = V4L2_CID_SATURATION,
-		.type    = V4L2_CTRL_TYPE_INTEGER,
-		.name    = "Saturation",
-		.minimum = 0,
-		.maximum = 40,
-		.step    = 1,
-#define COLORS_DEF 25
-		.default_value = COLORS_DEF,
-	    },
-	    .set_control = setcolors
-	},
-[BLUE] = {
-	    {
-		.id      = V4L2_CID_BLUE_BALANCE,
-		.type    = V4L2_CTRL_TYPE_INTEGER,
-		.name    = "Blue Balance",
-		.minimum = 24,
-		.maximum = 40,
-		.step    = 1,
-		.default_value = 32,
-	    },
-	    .set_control = setredblue
-	},
-[RED] = {
-	    {
-		.id      = V4L2_CID_RED_BALANCE,
-		.type    = V4L2_CTRL_TYPE_INTEGER,
-		.name    = "Red Balance",
-		.minimum = 24,
-		.maximum = 40,
-		.step    = 1,
-		.default_value = 32,
-	    },
-	    .set_control = setredblue
-	},
-[GAMMA] = {
-	    {
-		.id      = V4L2_CID_GAMMA,
-		.type    = V4L2_CTRL_TYPE_INTEGER,
-		.name    = "Gamma",
-		.minimum = 0,
-		.maximum = 40,
-		.step    = 1,
-#define GAMMA_DEF 20
-		.default_value = GAMMA_DEF,
-	    },
-	    .set_control = setgamma
-	},
-[EXPOSURE] = {
-	    {
-		.id      = V4L2_CID_EXPOSURE,
-		.type    = V4L2_CTRL_TYPE_INTEGER,
-		.name    = "Exposure",
-		.minimum = 500,
-		.maximum = 1500,
-		.step    = 1,
-		.default_value = 1024
-	    },
-	    .set_control = setexposure
-	},
-[AUTOGAIN] = {
-	    {
-		.id      = V4L2_CID_AUTOGAIN,
-		.type    = V4L2_CTRL_TYPE_BOOLEAN,
-		.name    = "Auto Gain",
-		.minimum = 0,
-		.maximum = 1,
-		.step    = 1,
-		.default_value = 1
-	    },
-	    .set = sd_setautogain,
-	},
-[GAIN] = {
-	    {
-		.id      = V4L2_CID_GAIN,
-		.type    = V4L2_CTRL_TYPE_INTEGER,
-		.name    = "Gain",
-		.minimum = 4,
-		.maximum = 49,
-		.step    = 1,
-		.default_value = 15
-	    },
-	    .set_control = setgain
-	},
-[HFLIP] = {
-	    {
-		.id      = V4L2_CID_HFLIP,
-		.type    = V4L2_CTRL_TYPE_BOOLEAN,
-		.name    = "Mirror",
-		.minimum = 0,
-		.maximum = 1,
-		.step    = 1,
-		.default_value = 0,
-	    },
-	    .set_control = sethvflip
-	},
-[VFLIP] = {
-	    {
-		.id      = V4L2_CID_VFLIP,
-		.type    = V4L2_CTRL_TYPE_BOOLEAN,
-		.name    = "Vflip",
-		.minimum = 0,
-		.maximum = 1,
-		.step    = 1,
-		.default_value = 0,
-	    },
-	    .set_control = sethvflip
-	},
-[SHARPNESS] = {
-	    {
-		.id	 = V4L2_CID_SHARPNESS,
-		.type    = V4L2_CTRL_TYPE_INTEGER,
-		.name    = "Sharpness",
-		.minimum = 0,
-		.maximum = 255,
-		.step    = 1,
-		.default_value = 90,
-	    },
-	    .set_control = setsharpness
-	},
-[ILLUM] = {
-	    {
-		.id      = V4L2_CID_ILLUMINATORS_1,
-		.type    = V4L2_CTRL_TYPE_BOOLEAN,
-		.name    = "Illuminator / infrared",
-		.minimum = 0,
-		.maximum = 1,
-		.step    = 1,
-		.default_value = 0,
-	    },
-	    .set_control = setillum
-	},
-/* ov7630/ov7648/ov7660 only */
-[FREQ] = {
-	    {
-		.id	 = V4L2_CID_POWER_LINE_FREQUENCY,
-		.type    = V4L2_CTRL_TYPE_MENU,
-		.name    = "Light frequency filter",
-		.minimum = 0,
-		.maximum = 2,	/* 0: 0, 1: 50Hz, 2:60Hz */
-		.step    = 1,
-		.default_value = 1,
-	    },
-	    .set_control = setfreq
-	},
-};
-
-/* table of the disabled controls */
-static const __u32 ctrl_dis[] = {
-[SENSOR_ADCM1700] =	(1 << EXPOSURE) |
-			(1 << AUTOGAIN) |
-			(1 << GAIN) |
-			(1 << HFLIP) |
-			(1 << VFLIP) |
-			(1 << FREQ),
-
-[SENSOR_GC0307] =	(1 << EXPOSURE) |
-			(1 << GAIN) |
-			(1 << HFLIP) |
-			(1 << VFLIP) |
-			(1 << FREQ),
-
-[SENSOR_HV7131R] =	(1 << EXPOSURE) |
-			(1 << GAIN) |
-			(1 << HFLIP) |
-			(1 << FREQ),
-
-[SENSOR_MI0360] =	(1 << EXPOSURE) |
-			(1 << GAIN) |
-			(1 << HFLIP) |
-			(1 << VFLIP) |
-			(1 << FREQ),
-
-[SENSOR_MI0360B] =	(1 << EXPOSURE) |
-			(1 << GAIN) |
-			(1 << HFLIP) |
-			(1 << VFLIP) |
-			(1 << FREQ),
-
-[SENSOR_MO4000] =	(1 << EXPOSURE) |
-			(1 << GAIN) |
-			(1 << HFLIP) |
-			(1 << VFLIP) |
-			(1 << FREQ),
-
-[SENSOR_MT9V111] =	(1 << EXPOSURE) |
-			(1 << GAIN) |
-			(1 << HFLIP) |
-			(1 << VFLIP) |
-			(1 << FREQ),
-
-[SENSOR_OM6802] =	(1 << EXPOSURE) |
-			(1 << GAIN) |
-			(1 << HFLIP) |
-			(1 << VFLIP) |
-			(1 << FREQ),
-
-[SENSOR_OV7630] =	(1 << EXPOSURE) |
-			(1 << GAIN) |
-			(1 << HFLIP),
-
-[SENSOR_OV7648] =	(1 << EXPOSURE) |
-			(1 << GAIN) |
-			(1 << HFLIP),
-
-[SENSOR_OV7660] =	(1 << EXPOSURE) |
-			(1 << AUTOGAIN) |
-			(1 << GAIN) |
-			(1 << HFLIP) |
-			(1 << VFLIP),
-
-[SENSOR_PO1030] =	(1 << EXPOSURE) |
-			(1 << AUTOGAIN) |
-			(1 << GAIN) |
-			(1 << HFLIP) |
-			(1 << VFLIP) |
-			(1 << FREQ),
-
-[SENSOR_PO2030N] =	(1 << FREQ),
-
-[SENSOR_SOI768] =	(1 << EXPOSURE) |
-			(1 << AUTOGAIN) |
-			(1 << GAIN) |
-			(1 << HFLIP) |
-			(1 << VFLIP) |
-			(1 << FREQ),
-
-[SENSOR_SP80708] =	(1 << EXPOSURE) |
-			(1 << AUTOGAIN) |
-			(1 << GAIN) |
-			(1 << HFLIP) |
-			(1 << VFLIP) |
-			(1 << FREQ),
-};
-
 static const struct v4l2_pix_format cif_mode[] = {
 	{352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 		.bytesperline = 352,
@@ -1442,12 +1159,11 @@ static void reg_r(struct gspca_dev *gspca_dev,
 
 	if (gspca_dev->usb_err < 0)
 		return;
-#ifdef GSPCA_DEBUG
 	if (len > USB_BUF_SZ) {
-		pr_err("reg_r: buffer overflow\n");
+		PERR("reg_r: buffer overflow\n");
 		return;
 	}
-#endif
+
 	ret = usb_control_msg(gspca_dev->dev,
 			usb_rcvctrlpipe(gspca_dev->dev, 0),
 			0,
@@ -1496,12 +1212,12 @@ static void reg_w(struct gspca_dev *gspca_dev,
 		return;
 	PDEBUG(D_USBO, "reg_w [%04x] = %02x %02x ..",
 		value, buffer[0], buffer[1]);
-#ifdef GSPCA_DEBUG
+
 	if (len > USB_BUF_SZ) {
-		pr_err("reg_w: buffer overflow\n");
+		PERR("reg_w: buffer overflow\n");
 		return;
 	}
-#endif
+
 	memcpy(gspca_dev->usb_buf, buffer, len);
 	ret = usb_control_msg(gspca_dev->dev,
 			usb_sndctrlpipe(gspca_dev->dev, 0),
@@ -1822,7 +1538,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
 		cam->nmodes = ARRAY_SIZE(vga_mode);
 	}
 	cam->npkt = 24;			/* 24 packets per ISOC message */
-	cam->ctrls = sd->ctrls;
 
 	sd->ag_cnt = -1;
 	sd->quality = QUALITY_DEF;
@@ -1888,9 +1603,6 @@ static int sd_init(struct gspca_dev *gspca_dev)
 		break;
 	}
 
-	if (sd->sensor == SENSOR_OM6802)
-		sd->ctrls[SHARPNESS].def = 0x10;
-
 	/* Note we do not disable the sensor clock here (power saving mode),
 	   as that also disables the button on the cam. */
 	reg_w1(gspca_dev, 0xf1, 0x00);
@@ -1899,13 +1611,92 @@ static int sd_init(struct gspca_dev *gspca_dev)
 	sn9c1xx = sn_tb[sd->sensor];
 	sd->i2c_addr = sn9c1xx[9];
 
-	gspca_dev->ctrl_dis = ctrl_dis[sd->sensor];
-	if (!(sd->flags & F_ILLUM))
-		gspca_dev->ctrl_dis |= (1 << ILLUM);
-
 	return gspca_dev->usb_err;
 }
 
+static int sd_s_ctrl(struct v4l2_ctrl *ctrl);
+
+static const struct v4l2_ctrl_ops sd_ctrl_ops = {
+	.s_ctrl = sd_s_ctrl,
+};
+
+/* this function is called at probe time */
+static int sd_init_controls(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
+
+	gspca_dev->vdev.ctrl_handler = hdl;
+	v4l2_ctrl_handler_init(hdl, 14);
+
+	sd->brightness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+			V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
+#define CONTRAST_MAX 127
+	sd->contrast = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+			V4L2_CID_CONTRAST, 0, CONTRAST_MAX, 1, 20);
+#define COLORS_DEF 25
+	sd->saturation = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+			V4L2_CID_SATURATION, 0, 40, 1, COLORS_DEF);
+	sd->red_bal = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+			V4L2_CID_RED_BALANCE, 24, 40, 1, 32);
+	sd->blue_bal = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+			V4L2_CID_BLUE_BALANCE, 24, 40, 1, 32);
+#define GAMMA_DEF 20
+	sd->gamma = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+			V4L2_CID_GAMMA, 0, 40, 1, GAMMA_DEF);
+
+	if (sd->sensor == SENSOR_OM6802)
+		sd->sharpness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+			V4L2_CID_SHARPNESS, 0, 255, 1, 16);
+	else
+		sd->sharpness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+			V4L2_CID_SHARPNESS, 0, 255, 1, 90);
+
+	if (sd->flags & F_ILLUM)
+		sd->illum = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+			V4L2_CID_ILLUMINATORS_1, 0, 1, 1, 0);
+
+	if (sd->sensor == SENSOR_PO2030N) {
+		gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+			V4L2_CID_EXPOSURE, 500, 1500, 1, 1024);
+		gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+			V4L2_CID_GAIN, 4, 49, 1, 15);
+		sd->hflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+			V4L2_CID_HFLIP, 0, 1, 1, 0);
+	}
+
+	if (sd->sensor != SENSOR_ADCM1700 && sd->sensor != SENSOR_OV7660 &&
+	    sd->sensor != SENSOR_PO1030 && sd->sensor != SENSOR_SOI768 &&
+	    sd->sensor != SENSOR_SP80708)
+		gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+			V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
+
+	if (sd->sensor == SENSOR_HV7131R || sd->sensor == SENSOR_OV7630 ||
+	    sd->sensor == SENSOR_OV7648 || sd->sensor == SENSOR_PO2030N)
+		sd->vflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+			V4L2_CID_VFLIP, 0, 1, 1, 0);
+
+	if (sd->sensor == SENSOR_OV7630 || sd->sensor == SENSOR_OV7648 ||
+	    sd->sensor == SENSOR_OV7660)
+		sd->freq = v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
+			V4L2_CID_POWER_LINE_FREQUENCY,
+			V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0,
+			V4L2_CID_POWER_LINE_FREQUENCY_50HZ);
+
+	if (hdl->error) {
+		pr_err("Could not initialize controls\n");
+		return hdl->error;
+	}
+
+	v4l2_ctrl_cluster(2, &sd->red_bal);
+	if (sd->sensor == SENSOR_PO2030N) {
+		v4l2_ctrl_cluster(2, &sd->vflip);
+		v4l2_ctrl_auto_cluster(3, &gspca_dev->autogain, 0, false);
+	}
+
+	return 0;
+}
+
 static u32 expo_adjust(struct gspca_dev *gspca_dev,
 			u32 expo)
 {
@@ -2014,10 +1805,9 @@ static void setbrightness(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 	unsigned int expo;
-	int brightness;
+	int brightness = sd->brightness->val;
 	u8 k2;
 
-	brightness = sd->ctrls[BRIGHTNESS].val;
 	k2 = (brightness - 0x80) >> 2;
 	switch (sd->sensor) {
 	case SENSOR_ADCM1700:
@@ -2064,7 +1854,7 @@ static void setcontrast(struct gspca_dev *gspca_dev)
 	u8 k2;
 	u8 contrast[6];
 
-	k2 = sd->ctrls[CONTRAST].val * 37 / (CONTRAST_MAX + 1)
+	k2 = sd->contrast->val * 37 / (CONTRAST_MAX + 1)
 				+ 37;		/* 37..73 */
 	contrast[0] = (k2 + 1) / 2;		/* red */
 	contrast[1] = 0;
@@ -2090,7 +1880,7 @@ static void setcolors(struct gspca_dev *gspca_dev)
 		 60, -51, -9		/* VR VG VB */
 	};
 
-	colors = sd->ctrls[COLORS].val;
+	colors = sd->saturation->val;
 	if (sd->sensor == SENSOR_MI0360B)
 		uv = uv_mi0360b;
 	else
@@ -2112,14 +1902,14 @@ static void setredblue(struct gspca_dev *gspca_dev)
 			{0xc1, 0x6e, 0x16, 0x00, 0x40, 0x00, 0x00, 0x10};
 
 		/* 0x40 = normal value = gain x 1 */
-		rg1b[3] = sd->ctrls[RED].val * 2;
-		rg1b[5] = sd->ctrls[BLUE].val * 2;
+		rg1b[3] = sd->red_bal->val * 2;
+		rg1b[5] = sd->blue_bal->val * 2;
 		i2c_w8(gspca_dev, rg1b);
 		return;
 	}
-	reg_w1(gspca_dev, 0x05, sd->ctrls[RED].val);
+	reg_w1(gspca_dev, 0x05, sd->red_bal->val);
 /*	reg_w1(gspca_dev, 0x07, 32); */
-	reg_w1(gspca_dev, 0x06, sd->ctrls[BLUE].val);
+	reg_w1(gspca_dev, 0x06, sd->blue_bal->val);
 }
 
 static void setgamma(struct gspca_dev *gspca_dev)
@@ -2153,7 +1943,7 @@ static void setgamma(struct gspca_dev *gspca_dev)
 		break;
 	}
 
-	val = sd->ctrls[GAMMA].val;
+	val = sd->gamma->val;
 	for (i = 0; i < sizeof gamma; i++)
 		gamma[i] = gamma_base[i]
 			+ delta[i] * (val - GAMMA_DEF) / 32;
@@ -2168,11 +1958,11 @@ static void setexposure(struct gspca_dev *gspca_dev)
 		u8 rexpo[] =		/* 1a: expo H, 1b: expo M */
 			{0xa1, 0x6e, 0x1a, 0x00, 0x40, 0x00, 0x00, 0x10};
 
-		rexpo[3] = sd->ctrls[EXPOSURE].val >> 8;
+		rexpo[3] = gspca_dev->exposure->val >> 8;
 		i2c_w8(gspca_dev, rexpo);
 		msleep(6);
 		rexpo[2] = 0x1b;
-		rexpo[3] = sd->ctrls[EXPOSURE].val;
+		rexpo[3] = gspca_dev->exposure->val;
 		i2c_w8(gspca_dev, rexpo);
 	}
 }
@@ -2181,8 +1971,6 @@ static void setautogain(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 
-	if (gspca_dev->ctrl_dis & (1 << AUTOGAIN))
-		return;
 	switch (sd->sensor) {
 	case SENSOR_OV7630:
 	case SENSOR_OV7648: {
@@ -2192,13 +1980,13 @@ static void setautogain(struct gspca_dev *gspca_dev)
 			comb = 0xc0;
 		else
 			comb = 0xa0;
-		if (sd->ctrls[AUTOGAIN].val)
+		if (gspca_dev->autogain->val)
 			comb |= 0x03;
 		i2c_w1(&sd->gspca_dev, 0x13, comb);
 		return;
 	    }
 	}
-	if (sd->ctrls[AUTOGAIN].val)
+	if (gspca_dev->autogain->val)
 		sd->ag_cnt = AG_CNT_START;
 	else
 		sd->ag_cnt = -1;
@@ -2212,7 +2000,7 @@ static void setgain(struct gspca_dev *gspca_dev)
 		u8 rgain[] =		/* 15: gain */
 			{0xa1, 0x6e, 0x15, 0x00, 0x40, 0x00, 0x00, 0x15};
 
-		rgain[3] = sd->ctrls[GAIN].val;
+		rgain[3] = gspca_dev->gain->val;
 		i2c_w8(gspca_dev, rgain);
 	}
 }
@@ -2225,19 +2013,19 @@ static void sethvflip(struct gspca_dev *gspca_dev)
 	switch (sd->sensor) {
 	case SENSOR_HV7131R:
 		comn = 0x18;			/* clkdiv = 1, ablcen = 1 */
-		if (sd->ctrls[VFLIP].val)
+		if (sd->vflip->val)
 			comn |= 0x01;
 		i2c_w1(gspca_dev, 0x01, comn);	/* sctra */
 		break;
 	case SENSOR_OV7630:
 		comn = 0x02;
-		if (!sd->ctrls[VFLIP].val)
+		if (!sd->vflip->val)
 			comn |= 0x80;
 		i2c_w1(gspca_dev, 0x75, comn);
 		break;
 	case SENSOR_OV7648:
 		comn = 0x06;
-		if (sd->ctrls[VFLIP].val)
+		if (sd->vflip->val)
 			comn |= 0x80;
 		i2c_w1(gspca_dev, 0x75, comn);
 		break;
@@ -2251,9 +2039,9 @@ static void sethvflip(struct gspca_dev *gspca_dev)
 		 * bit3-0: X
 		 */
 		comn = 0x0a;
-		if (sd->ctrls[HFLIP].val)
+		if (sd->hflip->val)
 			comn |= 0x80;
-		if (sd->ctrls[VFLIP].val)
+		if (sd->vflip->val)
 			comn |= 0x40;
 		i2c_w1(&sd->gspca_dev, 0x1e, comn);
 		break;
@@ -2264,23 +2052,21 @@ static void setsharpness(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 
-	reg_w1(gspca_dev, 0x99, sd->ctrls[SHARPNESS].val);
+	reg_w1(gspca_dev, 0x99, sd->sharpness->val);
 }
 
 static void setillum(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 
-	if (gspca_dev->ctrl_dis & (1 << ILLUM))
-		return;
 	switch (sd->sensor) {
 	case SENSOR_ADCM1700:
 		reg_w1(gspca_dev, 0x02,				/* gpio */
-			sd->ctrls[ILLUM].val ? 0x64 : 0x60);
+			sd->illum->val ? 0x64 : 0x60);
 		break;
 	case SENSOR_MT9V111:
 		reg_w1(gspca_dev, 0x02,
-			sd->ctrls[ILLUM].val ? 0x77 : 0x74);
+			sd->illum->val ? 0x77 : 0x74);
 /* should have been: */
 /*						0x55 : 0x54);	* 370i */
 /*						0x66 : 0x64);	* Clip */
@@ -2292,13 +2078,11 @@ static void setfreq(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 
-	if (gspca_dev->ctrl_dis & (1 << FREQ))
-		return;
 	if (sd->sensor == SENSOR_OV7660) {
 		u8 com8;
 
 		com8 = 0xdf;		/* auto gain/wb/expo */
-		switch (sd->ctrls[FREQ].val) {
+		switch (sd->freq->val) {
 		case 0: /* Banding filter disabled */
 			i2c_w1(gspca_dev, 0x13, com8 | 0x20);
 			break;
@@ -2326,7 +2110,7 @@ static void setfreq(struct gspca_dev *gspca_dev)
 			break;
 		}
 
-		switch (sd->ctrls[FREQ].val) {
+		switch (sd->freq->val) {
 		case 0: /* Banding filter disabled */
 			break;
 		case 1: /* 50 hz (filter on and framerate adj) */
@@ -2698,17 +2482,6 @@ static int sd_start(struct gspca_dev *gspca_dev)
 	sd->reg01 = reg01;
 	sd->reg17 = reg17;
 
-	sethvflip(gspca_dev);
-	setbrightness(gspca_dev);
-	setcontrast(gspca_dev);
-	setcolors(gspca_dev);
-	setautogain(gspca_dev);
-	if (!(gspca_dev->ctrl_inac & ((1 << EXPOSURE) | (1 << GAIN)))) {
-		setexposure(gspca_dev);
-		setgain(gspca_dev);
-	}
-	setfreq(gspca_dev);
-
 	sd->pktsz = sd->npkt = 0;
 	sd->nchg = sd->short_mark = 0;
 	sd->work_thread = create_singlethread_workqueue(MODULE_NAME);
@@ -2803,9 +2576,6 @@ static void sd_stop0(struct gspca_dev *gspca_dev)
 	}
 }
 
-#define WANT_REGULAR_AUTOGAIN
-#include "autogain_functions.h"
-
 static void do_autogain(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
@@ -2825,7 +2595,7 @@ static void do_autogain(struct gspca_dev *gspca_dev)
 	PDEBUG(D_FRAM, "mean lum %d", delta);
 
 	if (sd->sensor == SENSOR_PO2030N) {
-		auto_gain_n_exposure(gspca_dev, delta, luma_mean, luma_delta,
+		gspca_expo_autogain(gspca_dev, delta, luma_mean, luma_delta,
 					15, 1024);
 		return;
 	}
@@ -3042,39 +2812,53 @@ marker_found:
 	}
 }
 
-static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
+static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
 {
-	struct sd *sd = (struct sd *) gspca_dev;
+	struct gspca_dev *gspca_dev =
+		container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
 
-	sd->ctrls[AUTOGAIN].val = val;
-	if (val)
-		gspca_dev->ctrl_inac |= (1 << EXPOSURE) | (1 << GAIN);
-	else
-		gspca_dev->ctrl_inac &= ~(1 << EXPOSURE) & ~(1 << GAIN);
-	if (gspca_dev->streaming)
-		setautogain(gspca_dev);
-	return gspca_dev->usb_err;
-}
+	gspca_dev->usb_err = 0;
 
-static int sd_querymenu(struct gspca_dev *gspca_dev,
-			struct v4l2_querymenu *menu)
-{
-	switch (menu->id) {
+	if (!gspca_dev->streaming)
+		return 0;
+
+	switch (ctrl->id) {
+	case V4L2_CID_BRIGHTNESS:
+		setbrightness(gspca_dev);
+		break;
+	case V4L2_CID_CONTRAST:
+		setcontrast(gspca_dev);
+		break;
+	case V4L2_CID_SATURATION:
+		setcolors(gspca_dev);
+		break;
+	case V4L2_CID_RED_BALANCE:
+		setredblue(gspca_dev);
+		break;
+	case V4L2_CID_GAMMA:
+		setgamma(gspca_dev);
+		break;
+	case V4L2_CID_AUTOGAIN:
+		setautogain(gspca_dev);
+		setexposure(gspca_dev);
+		setgain(gspca_dev);
+		break;
+	case V4L2_CID_VFLIP:
+		sethvflip(gspca_dev);
+		break;
+	case V4L2_CID_SHARPNESS:
+		setsharpness(gspca_dev);
+		break;
+	case V4L2_CID_ILLUMINATORS_1:
+		setillum(gspca_dev);
+		break;
 	case V4L2_CID_POWER_LINE_FREQUENCY:
-		switch (menu->index) {
-		case 0:		/* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
-			strcpy((char *) menu->name, "NoFliker");
-			return 0;
-		case 1:		/* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
-			strcpy((char *) menu->name, "50 Hz");
-			return 0;
-		case 2:		/* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
-			strcpy((char *) menu->name, "60 Hz");
-			return 0;
-		}
+		setfreq(gspca_dev);
 		break;
+	default:
+		return -EINVAL;
 	}
-	return -EINVAL;
+	return gspca_dev->usb_err;
 }
 
 #if IS_ENABLED(CONFIG_INPUT)
@@ -3099,16 +2883,14 @@ static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
 /* sub-driver description */
 static const struct sd_desc sd_desc = {
 	.name = MODULE_NAME,
-	.ctrls = sd_ctrls,
-	.nctrls = NCTRLS,
 	.config = sd_config,
 	.init = sd_init,
+	.init_controls = sd_init_controls,
 	.start = sd_start,
 	.stopN = sd_stopN,
 	.stop0 = sd_stop0,
 	.pkt_scan = sd_pkt_scan,
 	.dq_callback = do_autogain,
-	.querymenu = sd_querymenu,
 #if IS_ENABLED(CONFIG_INPUT)
 	.int_pkt_scan = sd_int_pkt_scan,
 #endif
diff --git a/drivers/media/usb/gspca/spca1528.c b/drivers/media/usb/gspca/spca1528.c
index 14d6352..688592b 100644
--- a/drivers/media/usb/gspca/spca1528.c
+++ b/drivers/media/usb/gspca/spca1528.c
@@ -146,7 +146,7 @@ static void wait_status_0(struct gspca_dev *gspca_dev)
 		w += 15;
 		msleep(w);
 	} while (--i > 0);
-	PDEBUG(D_ERR, "wait_status_0 timeout");
+	PERR("wait_status_0 timeout");
 	gspca_dev->usb_err = -ETIME;
 }
 
@@ -164,7 +164,7 @@ static void wait_status_1(struct gspca_dev *gspca_dev)
 			return;
 		}
 	} while (--i > 0);
-	PDEBUG(D_ERR, "wait_status_1 timeout");
+	PERR("wait_status_1 timeout");
 	gspca_dev->usb_err = -ETIME;
 }
 
diff --git a/drivers/media/usb/gspca/spca500.c b/drivers/media/usb/gspca/spca500.c
index 25cb68d..9f8bf51 100644
--- a/drivers/media/usb/gspca/spca500.c
+++ b/drivers/media/usb/gspca/spca500.c
@@ -489,7 +489,7 @@ static int spca500_full_reset(struct gspca_dev *gspca_dev)
 		return err;
 	err = reg_r_wait(gspca_dev, 0x06, 0, 0);
 	if (err < 0) {
-		PDEBUG(D_ERR, "reg_r_wait() failed");
+		PERR("reg_r_wait() failed");
 		return err;
 	}
 	/* all ok */
@@ -505,7 +505,7 @@ static int spca500_full_reset(struct gspca_dev *gspca_dev)
 static int spca500_synch310(struct gspca_dev *gspca_dev)
 {
 	if (usb_set_interface(gspca_dev->dev, gspca_dev->iface, 0) < 0) {
-		PDEBUG(D_ERR, "Set packet size: set interface error");
+		PERR("Set packet size: set interface error");
 		goto error;
 	}
 	spca500_ping310(gspca_dev);
@@ -519,7 +519,7 @@ static int spca500_synch310(struct gspca_dev *gspca_dev)
 	if (usb_set_interface(gspca_dev->dev,
 				gspca_dev->iface,
 				gspca_dev->alt) < 0) {
-		PDEBUG(D_ERR, "Set packet size: set interface error");
+		PERR("Set packet size: set interface error");
 		goto error;
 	}
 	return 0;
@@ -544,7 +544,7 @@ static void spca500_reinit(struct gspca_dev *gspca_dev)
 	err = spca50x_setup_qtable(gspca_dev, 0x00, 0x8800, 0x8840,
 				 qtable_pocketdv);
 	if (err < 0)
-		PDEBUG(D_ERR|D_STREAM, "spca50x_setup_qtable failed on init");
+		PERR("spca50x_setup_qtable failed on init");
 
 	/* set qtable index */
 	reg_w(gspca_dev, 0x00, 0x8880, 2);
@@ -639,7 +639,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
 					   0x00, 0x8800, 0x8840,
 					   qtable_creative_pccam);
 		if (err < 0)
-			PDEBUG(D_ERR, "spca50x_setup_qtable failed");
+			PERR("spca50x_setup_qtable failed");
 		/* Init SDRAM - needed for SDRAM access */
 		reg_w(gspca_dev, 0x00, 0x870a, 0x04);
 
@@ -647,7 +647,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
 		reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
 		msleep(500);
 		if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
-			PDEBUG(D_ERR, "reg_r_wait() failed");
+			PERR("reg_r_wait() failed");
 
 		reg_r(gspca_dev, 0x816b, 1);
 		Data = gspca_dev->usb_buf[0];
@@ -660,13 +660,13 @@ static int sd_start(struct gspca_dev *gspca_dev)
 		/* enable drop packet */
 		err = reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
 		if (err < 0)
-			PDEBUG(D_ERR, "failed to enable drop packet");
+			PERR("failed to enable drop packet");
 		reg_w(gspca_dev, 0x00, 0x8880, 3);
 		err = spca50x_setup_qtable(gspca_dev,
 					   0x00, 0x8800, 0x8840,
 					   qtable_creative_pccam);
 		if (err < 0)
-			PDEBUG(D_ERR, "spca50x_setup_qtable failed");
+			PERR("spca50x_setup_qtable failed");
 
 		/* Init SDRAM - needed for SDRAM access */
 		reg_w(gspca_dev, 0x00, 0x870a, 0x04);
@@ -675,7 +675,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
 		reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
 
 		if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
-			PDEBUG(D_ERR, "reg_r_wait() failed");
+			PERR("reg_r_wait() failed");
 
 		reg_r(gspca_dev, 0x816b, 1);
 		Data = gspca_dev->usb_buf[0];
@@ -689,18 +689,18 @@ static int sd_start(struct gspca_dev *gspca_dev)
 		/* do a full reset */
 		err = spca500_full_reset(gspca_dev);
 		if (err < 0)
-			PDEBUG(D_ERR, "spca500_full_reset failed");
+			PERR("spca500_full_reset failed");
 
 		/* enable drop packet */
 		err = reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
 		if (err < 0)
-			PDEBUG(D_ERR, "failed to enable drop packet");
+			PERR("failed to enable drop packet");
 		reg_w(gspca_dev, 0x00, 0x8880, 3);
 		err = spca50x_setup_qtable(gspca_dev,
 					   0x00, 0x8800, 0x8840,
 					   qtable_creative_pccam);
 		if (err < 0)
-			PDEBUG(D_ERR, "spca50x_setup_qtable failed");
+			PERR("spca50x_setup_qtable failed");
 
 		spca500_setmode(gspca_dev, xmult, ymult);
 		reg_w(gspca_dev, 0x20, 0x0001, 0x0004);
@@ -709,7 +709,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
 		reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
 
 		if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
-			PDEBUG(D_ERR, "reg_r_wait() failed");
+			PERR("reg_r_wait() failed");
 
 		reg_r(gspca_dev, 0x816b, 1);
 		Data = gspca_dev->usb_buf[0];
@@ -722,7 +722,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
 		/* do a full reset */
 		err = spca500_full_reset(gspca_dev);
 		if (err < 0)
-			PDEBUG(D_ERR, "spca500_full_reset failed");
+			PERR("spca500_full_reset failed");
 		/* enable drop packet */
 		reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
 		reg_w(gspca_dev, 0x00, 0x8880, 0);
@@ -730,7 +730,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
 					   0x00, 0x8800, 0x8840,
 					   qtable_kodak_ez200);
 		if (err < 0)
-			PDEBUG(D_ERR, "spca50x_setup_qtable failed");
+			PERR("spca50x_setup_qtable failed");
 		spca500_setmode(gspca_dev, xmult, ymult);
 
 		reg_w(gspca_dev, 0x20, 0x0001, 0x0004);
@@ -739,7 +739,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
 		reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
 
 		if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
-			PDEBUG(D_ERR, "reg_r_wait() failed");
+			PERR("reg_r_wait() failed");
 
 		reg_r(gspca_dev, 0x816b, 1);
 		Data = gspca_dev->usb_buf[0];
@@ -765,7 +765,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
 		err = spca50x_setup_qtable(gspca_dev,
 				   0x00, 0x8800, 0x8840, qtable_pocketdv);
 		if (err < 0)
-			PDEBUG(D_ERR, "spca50x_setup_qtable failed");
+			PERR("spca50x_setup_qtable failed");
 		reg_w(gspca_dev, 0x00, 0x8880, 2);
 
 		/* familycam Quicksmart pocketDV stuff */
@@ -795,7 +795,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
 					0x00, 0x8800,
 					0x8840, qtable_creative_pccam);
 		if (err < 0)
-			PDEBUG(D_ERR, "spca50x_setup_qtable failed");
+			PERR("spca50x_setup_qtable failed");
 		reg_w(gspca_dev, 0x00, 0x8880, 3);
 		reg_w(gspca_dev, 0x00, 0x800a, 0x00);
 		/* Init SDRAM - needed for SDRAM access */
diff --git a/drivers/media/usb/gspca/spca501.c b/drivers/media/usb/gspca/spca501.c
index 3b7f777..d92fd17 100644
--- a/drivers/media/usb/gspca/spca501.c
+++ b/drivers/media/usb/gspca/spca501.c
@@ -1756,10 +1756,11 @@ static const __u16 spca501c_mysterious_init_data[][3] = {
 	{}
 };
 
-static int reg_write(struct usb_device *dev,
-		     __u16 req, __u16 index, __u16 value)
+static int reg_write(struct gspca_dev *gspca_dev,
+					__u16 req, __u16 index, __u16 value)
 {
 	int ret;
+	struct usb_device *dev = gspca_dev->dev;
 
 	ret = usb_control_msg(dev,
 			usb_sndctrlpipe(dev, 0),
@@ -1774,17 +1775,15 @@ static int reg_write(struct usb_device *dev,
 }
 
 
-static int write_vector(struct gspca_dev *gspca_dev,
-			const __u16 data[][3])
+static int write_vector(struct gspca_dev *gspca_dev, const __u16 data[][3])
 {
-	struct usb_device *dev = gspca_dev->dev;
 	int ret, i = 0;
 
 	while (data[i][0] != 0 || data[i][1] != 0 || data[i][2] != 0) {
-		ret = reg_write(dev, data[i][0], data[i][2], data[i][1]);
+		ret = reg_write(gspca_dev, data[i][0], data[i][2],
+								data[i][1]);
 		if (ret < 0) {
-			PDEBUG(D_ERR,
-				"Reg write failed for 0x%02x,0x%02x,0x%02x",
+			PERR("Reg write failed for 0x%02x,0x%02x,0x%02x",
 				data[i][0], data[i][1], data[i][2]);
 			return ret;
 		}
@@ -1795,30 +1794,28 @@ static int write_vector(struct gspca_dev *gspca_dev,
 
 static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
 {
-	reg_write(gspca_dev->dev, SPCA501_REG_CCDSP, 0x12, val);
+	reg_write(gspca_dev, SPCA501_REG_CCDSP, 0x12, val);
 }
 
 static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
 {
-	reg_write(gspca_dev->dev, 0x00, 0x00,
-				  (val >> 8) & 0xff);
-	reg_write(gspca_dev->dev, 0x00, 0x01,
-				  val & 0xff);
+	reg_write(gspca_dev, 0x00, 0x00, (val >> 8) & 0xff);
+	reg_write(gspca_dev, 0x00, 0x01, val & 0xff);
 }
 
 static void setcolors(struct gspca_dev *gspca_dev, s32 val)
 {
-	reg_write(gspca_dev->dev, SPCA501_REG_CCDSP, 0x0c, val);
+	reg_write(gspca_dev, SPCA501_REG_CCDSP, 0x0c, val);
 }
 
 static void setblue_balance(struct gspca_dev *gspca_dev, s32 val)
 {
-	reg_write(gspca_dev->dev, SPCA501_REG_CCDSP, 0x11, val);
+	reg_write(gspca_dev, SPCA501_REG_CCDSP, 0x11, val);
 }
 
 static void setred_balance(struct gspca_dev *gspca_dev, s32 val)
 {
-	reg_write(gspca_dev->dev, SPCA501_REG_CCDSP, 0x13, val);
+	reg_write(gspca_dev, SPCA501_REG_CCDSP, 0x13, val);
 }
 
 /* this function is called at probe time */
@@ -1868,7 +1865,6 @@ error:
 static int sd_start(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	struct usb_device *dev = gspca_dev->dev;
 	int mode;
 
 	switch (sd->subtype) {
@@ -1895,20 +1891,20 @@ static int sd_start(struct gspca_dev *gspca_dev)
 
 	/* Enable ISO packet machine CTRL reg=2,
 	 * index=1 bitmask=0x2 (bit ordinal 1) */
-	reg_write(dev, SPCA50X_REG_USB, 0x6, 0x94);
+	reg_write(gspca_dev, SPCA50X_REG_USB, 0x6, 0x94);
 	switch (mode) {
 	case 0: /* 640x480 */
-		reg_write(dev, SPCA50X_REG_USB, 0x07, 0x004a);
+		reg_write(gspca_dev, SPCA50X_REG_USB, 0x07, 0x004a);
 		break;
 	case 1: /* 320x240 */
-		reg_write(dev, SPCA50X_REG_USB, 0x07, 0x104a);
+		reg_write(gspca_dev, SPCA50X_REG_USB, 0x07, 0x104a);
 		break;
 	default:
 /*	case 2:  * 160x120 */
-		reg_write(dev, SPCA50X_REG_USB, 0x07, 0x204a);
+		reg_write(gspca_dev, SPCA50X_REG_USB, 0x07, 0x204a);
 		break;
 	}
-	reg_write(dev, SPCA501_REG_CTLRL, 0x01, 0x02);
+	reg_write(gspca_dev, SPCA501_REG_CTLRL, 0x01, 0x02);
 
 	return 0;
 }
@@ -1917,7 +1913,7 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
 {
 	/* Disable ISO packet
 	 * machine CTRL reg=2, index=1 bitmask=0x0 (bit ordinal 1) */
-	reg_write(gspca_dev->dev, SPCA501_REG_CTLRL, 0x01, 0x00);
+	reg_write(gspca_dev, SPCA501_REG_CTLRL, 0x01, 0x00);
 }
 
 /* called on streamoff with alt 0 and on disconnect */
@@ -1925,7 +1921,7 @@ static void sd_stop0(struct gspca_dev *gspca_dev)
 {
 	if (!gspca_dev->present)
 		return;
-	reg_write(gspca_dev->dev, SPCA501_REG_CTLRL, 0x05, 0x00);
+	reg_write(gspca_dev, SPCA501_REG_CTLRL, 0x05, 0x00);
 }
 
 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
diff --git a/drivers/media/usb/gspca/spca505.c b/drivers/media/usb/gspca/spca505.c
index bc7d67c..232b330 100644
--- a/drivers/media/usb/gspca/spca505.c
+++ b/drivers/media/usb/gspca/spca505.c
@@ -544,10 +544,11 @@ static const u8 spca505b_open_data_ccd[][3] = {
 	{}
 };
 
-static int reg_write(struct usb_device *dev,
+static int reg_write(struct gspca_dev *gspca_dev,
 		     u16 req, u16 index, u16 value)
 {
 	int ret;
+	struct usb_device *dev = gspca_dev->dev;
 
 	ret = usb_control_msg(dev,
 			usb_sndctrlpipe(dev, 0),
@@ -584,11 +585,11 @@ static int reg_read(struct gspca_dev *gspca_dev,
 static int write_vector(struct gspca_dev *gspca_dev,
 			const u8 data[][3])
 {
-	struct usb_device *dev = gspca_dev->dev;
 	int ret, i = 0;
 
 	while (data[i][0] != 0) {
-		ret = reg_write(dev, data[i][0], data[i][2], data[i][1]);
+		ret = reg_write(gspca_dev, data[i][0], data[i][2],
+								data[i][1]);
 		if (ret < 0)
 			return ret;
 		i++;
@@ -629,14 +630,13 @@ static int sd_init(struct gspca_dev *gspca_dev)
 
 static void setbrightness(struct gspca_dev *gspca_dev, s32 brightness)
 {
-	reg_write(gspca_dev->dev, 0x05, 0x00, (255 - brightness) >> 6);
-	reg_write(gspca_dev->dev, 0x05, 0x01, (255 - brightness) << 2);
+	reg_write(gspca_dev, 0x05, 0x00, (255 - brightness) >> 6);
+	reg_write(gspca_dev, 0x05, 0x01, (255 - brightness) << 2);
 }
 
 static int sd_start(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	struct usb_device *dev = gspca_dev->dev;
 	int ret, mode;
 	static u8 mode_tb[][3] = {
 	/*	  r00   r06   r07	*/
@@ -654,9 +654,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
 	ret = reg_read(gspca_dev, 0x06, 0x16);
 
 	if (ret < 0) {
-		PDEBUG(D_ERR|D_CONF,
-		       "register read failed err: %d",
-		       ret);
+		PERR("register read failed err: %d", ret);
 		return ret;
 	}
 	if (ret != 0x0101) {
@@ -664,22 +662,22 @@ static int sd_start(struct gspca_dev *gspca_dev)
 		       ret);
 	}
 
-	ret = reg_write(gspca_dev->dev, 0x06, 0x16, 0x0a);
+	ret = reg_write(gspca_dev, 0x06, 0x16, 0x0a);
 	if (ret < 0)
 		return ret;
-	reg_write(gspca_dev->dev, 0x05, 0xc2, 0x12);
+	reg_write(gspca_dev, 0x05, 0xc2, 0x12);
 
 	/* necessary because without it we can see stream
 	 * only once after loading module */
 	/* stopping usb registers Tomasz change */
-	reg_write(dev, 0x02, 0x00, 0x00);
+	reg_write(gspca_dev, 0x02, 0x00, 0x00);
 
 	mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
-	reg_write(dev, SPCA50X_REG_COMPRESS, 0x00, mode_tb[mode][0]);
-	reg_write(dev, SPCA50X_REG_COMPRESS, 0x06, mode_tb[mode][1]);
-	reg_write(dev, SPCA50X_REG_COMPRESS, 0x07, mode_tb[mode][2]);
+	reg_write(gspca_dev, SPCA50X_REG_COMPRESS, 0x00, mode_tb[mode][0]);
+	reg_write(gspca_dev, SPCA50X_REG_COMPRESS, 0x06, mode_tb[mode][1]);
+	reg_write(gspca_dev, SPCA50X_REG_COMPRESS, 0x07, mode_tb[mode][2]);
 
-	return reg_write(dev, SPCA50X_REG_USB,
+	return reg_write(gspca_dev, SPCA50X_REG_USB,
 			 SPCA50X_USB_CTRL,
 			 SPCA50X_CUSB_ENABLE);
 }
@@ -687,7 +685,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
 static void sd_stopN(struct gspca_dev *gspca_dev)
 {
 	/* Disable ISO packet machine */
-	reg_write(gspca_dev->dev, 0x02, 0x00, 0x00);
+	reg_write(gspca_dev, 0x02, 0x00, 0x00);
 }
 
 /* called on streamoff with alt 0 and on disconnect */
@@ -697,11 +695,11 @@ static void sd_stop0(struct gspca_dev *gspca_dev)
 		return;
 
 	/* This maybe reset or power control */
-	reg_write(gspca_dev->dev, 0x03, 0x03, 0x20);
-	reg_write(gspca_dev->dev, 0x03, 0x01, 0x00);
-	reg_write(gspca_dev->dev, 0x03, 0x00, 0x01);
-	reg_write(gspca_dev->dev, 0x05, 0x10, 0x01);
-	reg_write(gspca_dev->dev, 0x05, 0x11, 0x0f);
+	reg_write(gspca_dev, 0x03, 0x03, 0x20);
+	reg_write(gspca_dev, 0x03, 0x01, 0x00);
+	reg_write(gspca_dev, 0x03, 0x00, 0x01);
+	reg_write(gspca_dev, 0x05, 0x10, 0x01);
+	reg_write(gspca_dev, 0x05, 0x11, 0x0f);
 }
 
 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
diff --git a/drivers/media/usb/gspca/spca508.c b/drivers/media/usb/gspca/spca508.c
index 1286b41..75f2beb 100644
--- a/drivers/media/usb/gspca/spca508.c
+++ b/drivers/media/usb/gspca/spca508.c
@@ -1241,10 +1241,10 @@ static const u16 spca508_vista_init_data[][2] = {
 	{}
 };
 
-static int reg_write(struct usb_device *dev,
-			u16 index, u16 value)
+static int reg_write(struct gspca_dev *gspca_dev, u16 index, u16 value)
 {
 	int ret;
+	struct usb_device *dev = gspca_dev->dev;
 
 	ret = usb_control_msg(dev,
 			usb_sndctrlpipe(dev, 0),
@@ -1286,22 +1286,21 @@ static int reg_read(struct gspca_dev *gspca_dev,
 static int ssi_w(struct gspca_dev *gspca_dev,
 		u16 reg, u16 val)
 {
-	struct usb_device *dev = gspca_dev->dev;
 	int ret, retry;
 
-	ret = reg_write(dev, 0x8802, reg >> 8);
+	ret = reg_write(gspca_dev, 0x8802, reg >> 8);
 	if (ret < 0)
 		goto out;
-	ret = reg_write(dev, 0x8801, reg & 0x00ff);
+	ret = reg_write(gspca_dev, 0x8801, reg & 0x00ff);
 	if (ret < 0)
 		goto out;
 	if ((reg & 0xff00) == 0x1000) {		/* if 2 bytes */
-		ret = reg_write(dev, 0x8805, val & 0x00ff);
+		ret = reg_write(gspca_dev, 0x8805, val & 0x00ff);
 		if (ret < 0)
 			goto out;
 		val >>= 8;
 	}
-	ret = reg_write(dev, 0x8800, val);
+	ret = reg_write(gspca_dev, 0x8800, val);
 	if (ret < 0)
 		goto out;
 
@@ -1314,8 +1313,7 @@ static int ssi_w(struct gspca_dev *gspca_dev,
 		if (gspca_dev->usb_buf[0] == 0)
 			break;
 		if (--retry <= 0) {
-			PDEBUG(D_ERR, "ssi_w busy %02x",
-					gspca_dev->usb_buf[0]);
+			PERR("ssi_w busy %02x", gspca_dev->usb_buf[0]);
 			ret = -1;
 			break;
 		}
@@ -1329,7 +1327,6 @@ out:
 static int write_vector(struct gspca_dev *gspca_dev,
 			const u16 (*data)[2])
 {
-	struct usb_device *dev = gspca_dev->dev;
 	int ret = 0;
 
 	while ((*data)[1] != 0) {
@@ -1337,7 +1334,8 @@ static int write_vector(struct gspca_dev *gspca_dev,
 			if ((*data)[1] == 0xdd00)	/* delay */
 				msleep((*data)[0]);
 			else
-				ret = reg_write(dev, (*data)[1], (*data)[0]);
+				ret = reg_write(gspca_dev, (*data)[1],
+								(*data)[0]);
 		} else {
 			ret = ssi_w(gspca_dev, (*data)[1], (*data)[0]);
 		}
@@ -1363,8 +1361,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
 		spca508cs110_init_data,		/* MicroInnovationIC200 4 */
 		spca508_init_data,		/* ViewQuestVQ110 5 */
 	};
-
-#ifdef GSPCA_DEBUG
 	int data1, data2;
 
 	/* Read from global register the USB product and vendor IDs, just to
@@ -1381,7 +1377,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
 
 	data1 = reg_read(gspca_dev, 0x8621);
 	PDEBUG(D_PROBE, "Window 1 average luminance: %d", data1);
-#endif
 
 	cam = &gspca_dev->cam;
 	cam->cam_mode = sif_mode;
@@ -1404,26 +1399,26 @@ static int sd_start(struct gspca_dev *gspca_dev)
 	int mode;
 
 	mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
-	reg_write(gspca_dev->dev, 0x8500, mode);
+	reg_write(gspca_dev, 0x8500, mode);
 	switch (mode) {
 	case 0:
 	case 1:
-		reg_write(gspca_dev->dev, 0x8700, 0x28);	/* clock */
+		reg_write(gspca_dev, 0x8700, 0x28); /* clock */
 		break;
 	default:
 /*	case 2: */
 /*	case 3: */
-		reg_write(gspca_dev->dev, 0x8700, 0x23);	/* clock */
+		reg_write(gspca_dev, 0x8700, 0x23); /* clock */
 		break;
 	}
-	reg_write(gspca_dev->dev, 0x8112, 0x10 | 0x20);
+	reg_write(gspca_dev, 0x8112, 0x10 | 0x20);
 	return 0;
 }
 
 static void sd_stopN(struct gspca_dev *gspca_dev)
 {
 	/* Video ISO disable, Video Drop Packet enable: */
-	reg_write(gspca_dev->dev, 0x8112, 0x20);
+	reg_write(gspca_dev, 0x8112, 0x20);
 }
 
 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
@@ -1450,10 +1445,10 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
 static void setbrightness(struct gspca_dev *gspca_dev, s32 brightness)
 {
 	/* MX seem contrast */
-	reg_write(gspca_dev->dev, 0x8651, brightness);
-	reg_write(gspca_dev->dev, 0x8652, brightness);
-	reg_write(gspca_dev->dev, 0x8653, brightness);
-	reg_write(gspca_dev->dev, 0x8654, brightness);
+	reg_write(gspca_dev, 0x8651, brightness);
+	reg_write(gspca_dev, 0x8652, brightness);
+	reg_write(gspca_dev, 0x8653, brightness);
+	reg_write(gspca_dev, 0x8654, brightness);
 }
 
 static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
diff --git a/drivers/media/usb/gspca/spca561.c b/drivers/media/usb/gspca/spca561.c
index d1db3d8..403d71c 100644
--- a/drivers/media/usb/gspca/spca561.c
+++ b/drivers/media/usb/gspca/spca561.c
@@ -285,9 +285,10 @@ static const __u16 spca561_161rev12A_data2[][2] = {
 	{}
 };
 
-static void reg_w_val(struct usb_device *dev, __u16 index, __u8 value)
+static void reg_w_val(struct gspca_dev *gspca_dev, __u16 index, __u8 value)
 {
 	int ret;
+	struct usb_device *dev = gspca_dev->dev;
 
 	ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
 			      0,		/* request */
@@ -301,12 +302,11 @@ static void reg_w_val(struct usb_device *dev, __u16 index, __u8 value)
 static void write_vector(struct gspca_dev *gspca_dev,
 			const __u16 data[][2])
 {
-	struct usb_device *dev = gspca_dev->dev;
 	int i;
 
 	i = 0;
 	while (data[i][1] != 0) {
-		reg_w_val(dev, data[i][1], data[i][0]);
+		reg_w_val(gspca_dev, data[i][1], data[i][0]);
 		i++;
 	}
 }
@@ -339,9 +339,9 @@ static void i2c_write(struct gspca_dev *gspca_dev, __u16 value, __u16 reg)
 {
 	int retry = 60;
 
-	reg_w_val(gspca_dev->dev, 0x8801, reg);
-	reg_w_val(gspca_dev->dev, 0x8805, value);
-	reg_w_val(gspca_dev->dev, 0x8800, value >> 8);
+	reg_w_val(gspca_dev, 0x8801, reg);
+	reg_w_val(gspca_dev, 0x8805, value);
+	reg_w_val(gspca_dev, 0x8800, value >> 8);
 	do {
 		reg_r(gspca_dev, 0x8803, 1);
 		if (!gspca_dev->usb_buf[0])
@@ -355,9 +355,9 @@ static int i2c_read(struct gspca_dev *gspca_dev, __u16 reg, __u8 mode)
 	int retry = 60;
 	__u8 value;
 
-	reg_w_val(gspca_dev->dev, 0x8804, 0x92);
-	reg_w_val(gspca_dev->dev, 0x8801, reg);
-	reg_w_val(gspca_dev->dev, 0x8802, mode | 0x01);
+	reg_w_val(gspca_dev, 0x8804, 0x92);
+	reg_w_val(gspca_dev, 0x8801, reg);
+	reg_w_val(gspca_dev, 0x8802, mode | 0x01);
 	do {
 		reg_r(gspca_dev, 0x8803, 1);
 		if (!gspca_dev->usb_buf[0]) {
@@ -459,14 +459,13 @@ static int sd_init_72a(struct gspca_dev *gspca_dev)
 	write_sensor_72a(gspca_dev, rev72a_init_sensor1);
 	write_vector(gspca_dev, rev72a_init_data2);
 	write_sensor_72a(gspca_dev, rev72a_init_sensor2);
-	reg_w_val(gspca_dev->dev, 0x8112, 0x30);
+	reg_w_val(gspca_dev, 0x8112, 0x30);
 	return 0;
 }
 
 static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	struct usb_device *dev = gspca_dev->dev;
 	__u16 reg;
 
 	if (sd->chip_revision == Rev012A)
@@ -474,16 +473,15 @@ static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
 	else
 		reg = 0x8611;
 
-	reg_w_val(dev, reg + 0, val);		/* R */
-	reg_w_val(dev, reg + 1, val);		/* Gr */
-	reg_w_val(dev, reg + 2, val);		/* B */
-	reg_w_val(dev, reg + 3, val);		/* Gb */
+	reg_w_val(gspca_dev, reg + 0, val);		/* R */
+	reg_w_val(gspca_dev, reg + 1, val);		/* Gr */
+	reg_w_val(gspca_dev, reg + 2, val);		/* B */
+	reg_w_val(gspca_dev, reg + 3, val);		/* Gb */
 }
 
 static void setwhite(struct gspca_dev *gspca_dev, s32 white, s32 contrast)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	struct usb_device *dev = gspca_dev->dev;
 	__u8 blue, red;
 	__u16 reg;
 
@@ -496,11 +494,11 @@ static void setwhite(struct gspca_dev *gspca_dev, s32 white, s32 contrast)
 		reg = 0x8651;
 		red += contrast - 0x20;
 		blue += contrast - 0x20;
-		reg_w_val(dev, 0x8652, contrast + 0x20); /* Gr */
-		reg_w_val(dev, 0x8654, contrast + 0x20); /* Gb */
+		reg_w_val(gspca_dev, 0x8652, contrast + 0x20); /* Gr */
+		reg_w_val(gspca_dev, 0x8654, contrast + 0x20); /* Gb */
 	}
-	reg_w_val(dev, reg, red);
-	reg_w_val(dev, reg + 2, blue);
+	reg_w_val(gspca_dev, reg, red);
+	reg_w_val(gspca_dev, reg + 2, blue);
 }
 
 /* rev 12a only */
@@ -570,7 +568,6 @@ static void setautogain(struct gspca_dev *gspca_dev, s32 val)
 
 static int sd_start_12a(struct gspca_dev *gspca_dev)
 {
-	struct usb_device *dev = gspca_dev->dev;
 	int mode;
 	static const __u8 Reg8391[8] =
 		{0x92, 0x30, 0x20, 0x00, 0x0c, 0x00, 0x00, 0x00};
@@ -578,34 +575,33 @@ static int sd_start_12a(struct gspca_dev *gspca_dev)
 	mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
 	if (mode <= 1) {
 		/* Use compression on 320x240 and above */
-		reg_w_val(dev, 0x8500, 0x10 | mode);
+		reg_w_val(gspca_dev, 0x8500, 0x10 | mode);
 	} else {
 		/* I couldn't get the compression to work below 320x240
 		 * Fortunately at these resolutions the bandwidth
 		 * is sufficient to push raw frames at ~20fps */
-		reg_w_val(dev, 0x8500, mode);
+		reg_w_val(gspca_dev, 0x8500, mode);
 	}		/* -- qq@kuku.eu.org */
 
 	gspca_dev->usb_buf[0] = 0xaa;
 	gspca_dev->usb_buf[1] = 0x00;
 	reg_w_buf(gspca_dev, 0x8307, 2);
 	/* clock - lower 0x8X values lead to fps > 30 */
-	reg_w_val(gspca_dev->dev, 0x8700, 0x8a);
+	reg_w_val(gspca_dev, 0x8700, 0x8a);
 					/* 0x8f 0x85 0x27 clock */
-	reg_w_val(gspca_dev->dev, 0x8112, 0x1e | 0x20);
-	reg_w_val(gspca_dev->dev, 0x850b, 0x03);
+	reg_w_val(gspca_dev, 0x8112, 0x1e | 0x20);
+	reg_w_val(gspca_dev, 0x850b, 0x03);
 	memcpy(gspca_dev->usb_buf, Reg8391, 8);
 	reg_w_buf(gspca_dev, 0x8391, 8);
 	reg_w_buf(gspca_dev, 0x8390, 8);
 
 	/* Led ON (bit 3 -> 0 */
-	reg_w_val(gspca_dev->dev, 0x8114, 0x00);
+	reg_w_val(gspca_dev, 0x8114, 0x00);
 	return 0;
 }
 static int sd_start_72a(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	struct usb_device *dev = gspca_dev->dev;
 	int Clck;
 	int mode;
 
@@ -630,15 +626,15 @@ static int sd_start_72a(struct gspca_dev *gspca_dev)
 		Clck = 0x21;
 		break;
 	}
-	reg_w_val(dev, 0x8700, Clck);	/* 0x27 clock */
-	reg_w_val(dev, 0x8702, 0x81);
-	reg_w_val(dev, 0x8500, mode);	/* mode */
+	reg_w_val(gspca_dev, 0x8700, Clck);	/* 0x27 clock */
+	reg_w_val(gspca_dev, 0x8702, 0x81);
+	reg_w_val(gspca_dev, 0x8500, mode);	/* mode */
 	write_sensor_72a(gspca_dev, rev72a_init_sensor2);
 	setwhite(gspca_dev, v4l2_ctrl_g_ctrl(sd->hue),
 			v4l2_ctrl_g_ctrl(sd->contrast));
 /*	setbrightness(gspca_dev);	 * fixme: bad values */
 	setautogain(gspca_dev, v4l2_ctrl_g_ctrl(sd->autogain));
-	reg_w_val(dev, 0x8112, 0x10 | 0x20);
+	reg_w_val(gspca_dev, 0x8112, 0x10 | 0x20);
 	return 0;
 }
 
@@ -647,12 +643,12 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
 	struct sd *sd = (struct sd *) gspca_dev;
 
 	if (sd->chip_revision == Rev012A) {
-		reg_w_val(gspca_dev->dev, 0x8112, 0x0e);
+		reg_w_val(gspca_dev, 0x8112, 0x0e);
 		/* Led Off (bit 3 -> 1 */
-		reg_w_val(gspca_dev->dev, 0x8114, 0x08);
+		reg_w_val(gspca_dev, 0x8114, 0x08);
 	} else {
-		reg_w_val(gspca_dev->dev, 0x8112, 0x20);
-/*		reg_w_val(gspca_dev->dev, 0x8102, 0x00); ?? */
+		reg_w_val(gspca_dev, 0x8112, 0x20);
+/*		reg_w_val(gspca_dev, 0x8102, 0x00); ?? */
 	}
 }
 
@@ -736,7 +732,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
 
 		/* This should never happen */
 		if (len < 2) {
-			PDEBUG(D_ERR, "Short SOF packet, ignoring");
+			PERR("Short SOF packet, ignoring");
 			gspca_dev->last_packet_type = DISCARD_PACKET;
 			return;
 		}
diff --git a/drivers/media/usb/gspca/sq905.c b/drivers/media/usb/gspca/sq905.c
index 1d99f10..a7ae0ec 100644
--- a/drivers/media/usb/gspca/sq905.c
+++ b/drivers/media/usb/gspca/sq905.c
@@ -387,7 +387,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
 	}
 
 	if (ret < 0) {
-		PDEBUG(D_ERR, "Start streaming command failed");
+		PERR("Start streaming command failed");
 		return ret;
 	}
 	/* Start the workqueue function to do the streaming */
diff --git a/drivers/media/usb/gspca/sq905c.c b/drivers/media/usb/gspca/sq905c.c
index 410cdcb..acb19fb 100644
--- a/drivers/media/usb/gspca/sq905c.c
+++ b/drivers/media/usb/gspca/sq905c.c
@@ -215,13 +215,13 @@ static int sd_config(struct gspca_dev *gspca_dev,
 
 	ret = sq905c_command(gspca_dev, SQ905C_GET_ID, 0);
 	if (ret < 0) {
-		PDEBUG(D_ERR, "Get version command failed");
+		PERR("Get version command failed");
 		return ret;
 	}
 
 	ret = sq905c_read(gspca_dev, 0xf5, 0, 20);
 	if (ret < 0) {
-		PDEBUG(D_ERR, "Reading version command failed");
+		PERR("Reading version command failed");
 		return ret;
 	}
 	/* Note we leave out the usb id and the manufacturing date */
@@ -286,7 +286,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
 	}
 
 	if (ret < 0) {
-		PDEBUG(D_ERR, "Start streaming command failed");
+		PERR("Start streaming command failed");
 		return ret;
 	}
 	/* Start the workqueue function to do the streaming */
diff --git a/drivers/media/usb/gspca/sq930x.c b/drivers/media/usb/gspca/sq930x.c
index 7e8748b..b10d082 100644
--- a/drivers/media/usb/gspca/sq930x.c
+++ b/drivers/media/usb/gspca/sq930x.c
@@ -541,13 +541,11 @@ static void ucbus_write(struct gspca_dev *gspca_dev,
 	if (gspca_dev->usb_err < 0)
 		return;
 
-#ifdef GSPCA_DEBUG
 	if ((batchsize - 1) * 3 > USB_BUF_SZ) {
-		pr_err("Bug: usb_buf overflow\n");
+		PERR("Bug: usb_buf overflow\n");
 		gspca_dev->usb_err = -ENOMEM;
 		return;
 	}
-#endif
 
 	for (;;) {
 		len = ncmds;
diff --git a/drivers/media/usb/gspca/stv0680.c b/drivers/media/usb/gspca/stv0680.c
index 6760527..9c08276 100644
--- a/drivers/media/usb/gspca/stv0680.c
+++ b/drivers/media/usb/gspca/stv0680.c
@@ -86,7 +86,7 @@ static int stv_sndctrl(struct gspca_dev *gspca_dev, int set, u8 req, u16 val,
 static int stv0680_handle_error(struct gspca_dev *gspca_dev, int ret)
 {
 	stv_sndctrl(gspca_dev, 0, 0x80, 0, 0x02); /* Get Last Error */
-	PDEBUG(D_ERR, "last error: %i,  command = 0x%x",
+	PERR("last error: %i,  command = 0x%x",
 	       gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]);
 	return ret;
 }
@@ -98,7 +98,7 @@ static int stv0680_get_video_mode(struct gspca_dev *gspca_dev)
 	gspca_dev->usb_buf[0] = 0x0f;
 
 	if (stv_sndctrl(gspca_dev, 0, 0x87, 0, 0x08) != 0x08) {
-		PDEBUG(D_ERR, "Get_Camera_Mode failed");
+		PERR("Get_Camera_Mode failed");
 		return stv0680_handle_error(gspca_dev, -EIO);
 	}
 
@@ -116,13 +116,13 @@ static int stv0680_set_video_mode(struct gspca_dev *gspca_dev, u8 mode)
 	gspca_dev->usb_buf[0] = mode;
 
 	if (stv_sndctrl(gspca_dev, 3, 0x07, 0x0100, 0x08) != 0x08) {
-		PDEBUG(D_ERR, "Set_Camera_Mode failed");
+		PERR("Set_Camera_Mode failed");
 		return stv0680_handle_error(gspca_dev, -EIO);
 	}
 
 	/* Verify we got what we've asked for */
 	if (stv0680_get_video_mode(gspca_dev) != mode) {
-		PDEBUG(D_ERR, "Error setting camera video mode!");
+		PERR("Error setting camera video mode!");
 		return -EIO;
 	}
 
@@ -146,7 +146,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
 	/* ping camera to be sure STV0680 is present */
 	if (stv_sndctrl(gspca_dev, 0, 0x88, 0x5678, 0x02) != 0x02 ||
 	    gspca_dev->usb_buf[0] != 0x56 || gspca_dev->usb_buf[1] != 0x78) {
-		PDEBUG(D_ERR, "STV(e): camera ping failed!!");
+		PERR("STV(e): camera ping failed!!");
 		return stv0680_handle_error(gspca_dev, -ENODEV);
 	}
 
@@ -156,7 +156,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
 
 	if (stv_sndctrl(gspca_dev, 2, 0x06, 0x0200, 0x22) != 0x22 ||
 	    gspca_dev->usb_buf[7] != 0xa0 || gspca_dev->usb_buf[8] != 0x23) {
-		PDEBUG(D_ERR, "Could not get descriptor 0200.");
+		PERR("Could not get descriptor 0200.");
 		return stv0680_handle_error(gspca_dev, -ENODEV);
 	}
 	if (stv_sndctrl(gspca_dev, 0, 0x8a, 0, 0x02) != 0x02)
@@ -167,7 +167,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
 		return stv0680_handle_error(gspca_dev, -ENODEV);
 
 	if (!(gspca_dev->usb_buf[7] & 0x09)) {
-		PDEBUG(D_ERR, "Camera supports neither CIF nor QVGA mode");
+		PERR("Camera supports neither CIF nor QVGA mode");
 		return -ENODEV;
 	}
 	if (gspca_dev->usb_buf[7] & 0x01)
diff --git a/drivers/media/usb/gspca/stv06xx/stv06xx.c b/drivers/media/usb/gspca/stv06xx/stv06xx.c
index 657160b..55ee7a6 100644
--- a/drivers/media/usb/gspca/stv06xx/stv06xx.c
+++ b/drivers/media/usb/gspca/stv06xx/stv06xx.c
@@ -42,8 +42,10 @@ static bool dump_sensor;
 int stv06xx_write_bridge(struct sd *sd, u16 address, u16 i2c_data)
 {
 	int err;
+	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
 	struct usb_device *udev = sd->gspca_dev.dev;
 	__u8 *buf = sd->gspca_dev.usb_buf;
+
 	u8 len = (i2c_data > 0xff) ? 2 : 1;
 
 	buf[0] = i2c_data & 0xff;
@@ -62,6 +64,7 @@ int stv06xx_write_bridge(struct sd *sd, u16 address, u16 i2c_data)
 int stv06xx_read_bridge(struct sd *sd, u16 address, u8 *i2c_data)
 {
 	int err;
+	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
 	struct usb_device *udev = sd->gspca_dev.dev;
 	__u8 *buf = sd->gspca_dev.usb_buf;
 
@@ -110,6 +113,7 @@ static int stv06xx_write_sensor_finish(struct sd *sd)
 int stv06xx_write_sensor_bytes(struct sd *sd, const u8 *data, u8 len)
 {
 	int err, i, j;
+	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
 	struct usb_device *udev = sd->gspca_dev.dev;
 	__u8 *buf = sd->gspca_dev.usb_buf;
 
@@ -139,6 +143,7 @@ int stv06xx_write_sensor_bytes(struct sd *sd, const u8 *data, u8 len)
 int stv06xx_write_sensor_words(struct sd *sd, const u16 *data, u8 len)
 {
 	int err, i, j;
+	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
 	struct usb_device *udev = sd->gspca_dev.dev;
 	__u8 *buf = sd->gspca_dev.usb_buf;
 
@@ -170,6 +175,7 @@ int stv06xx_write_sensor_words(struct sd *sd, const u16 *data, u8 len)
 int stv06xx_read_sensor(struct sd *sd, const u8 address, u16 *value)
 {
 	int err;
+	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
 	struct usb_device *udev = sd->gspca_dev.dev;
 	__u8 *buf = sd->gspca_dev.usb_buf;
 
@@ -283,7 +289,7 @@ static int stv06xx_start(struct gspca_dev *gspca_dev)
 	intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
 	alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
 	if (!alt) {
-		PDEBUG(D_ERR, "Couldn't get altsetting");
+		PERR("Couldn't get altsetting");
 		return -EIO;
 	}
 
@@ -341,7 +347,7 @@ static int stv06xx_isoc_nego(struct gspca_dev *gspca_dev)
 
 	ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1);
 	if (ret < 0)
-		PDEBUG(D_ERR|D_STREAM, "set alt 1 err %d", ret);
+		PERR("set alt 1 err %d", ret);
 
 	return ret;
 }
@@ -406,7 +412,7 @@ static void stv06xx_pkt_scan(struct gspca_dev *gspca_dev,
 		len -= 4;
 
 		if (len < chunk_len) {
-			PDEBUG(D_ERR, "URB packet length is smaller"
+			PERR("URB packet length is smaller"
 				" than the specified chunk length");
 			gspca_dev->last_packet_type = DISCARD_PACKET;
 			return;
@@ -449,7 +455,7 @@ frame_data:
 				sd->to_skip = gspca_dev->width * 4;
 
 			if (chunk_len)
-				PDEBUG(D_ERR, "Chunk length is "
+				PERR("Chunk length is "
 					      "non-zero on a SOF");
 			break;
 
@@ -463,7 +469,7 @@ frame_data:
 					NULL, 0);
 
 			if (chunk_len)
-				PDEBUG(D_ERR, "Chunk length is "
+				PERR("Chunk length is "
 					      "non-zero on a EOF");
 			break;
 
@@ -596,7 +602,6 @@ MODULE_DEVICE_TABLE(usb, device_table);
 static int sd_probe(struct usb_interface *intf,
 			const struct usb_device_id *id)
 {
-	PDEBUG(D_PROBE, "Probing for a stv06xx device");
 	return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
 			       THIS_MODULE);
 }
diff --git a/drivers/media/usb/gspca/stv06xx/stv06xx_hdcs.c b/drivers/media/usb/gspca/stv06xx/stv06xx_hdcs.c
index 06fa54c5e..2220b70 100644
--- a/drivers/media/usb/gspca/stv06xx/stv06xx_hdcs.c
+++ b/drivers/media/usb/gspca/stv06xx/stv06xx_hdcs.c
@@ -255,7 +255,7 @@ static int hdcs_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
 		if (err < 0)
 			return err;
 	}
-	PDEBUG(D_V4L2, "Writing exposure %d, rowexp %d, srowexp %d",
+	PDEBUG(D_CONF, "Writing exposure %d, rowexp %d, srowexp %d",
 	       val, rowexp, srowexp);
 	return err;
 }
@@ -280,7 +280,7 @@ static int hdcs_set_gains(struct sd *sd, u8 g)
 
 static int hdcs_set_gain(struct gspca_dev *gspca_dev, __s32 val)
 {
-	PDEBUG(D_V4L2, "Writing gain %d", val);
+	PDEBUG(D_CONF, "Writing gain %d", val);
 	return hdcs_set_gains((struct sd *) gspca_dev,
 			       val & 0xff);
 }
@@ -467,6 +467,8 @@ static int hdcs_probe_1020(struct sd *sd)
 
 static int hdcs_start(struct sd *sd)
 {
+	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
+
 	PDEBUG(D_STREAM, "Starting stream");
 
 	return hdcs_set_state(sd, HDCS_STATE_RUN);
@@ -474,6 +476,8 @@ static int hdcs_start(struct sd *sd)
 
 static int hdcs_stop(struct sd *sd)
 {
+	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
+
 	PDEBUG(D_STREAM, "Halting stream");
 
 	return hdcs_set_state(sd, HDCS_STATE_SLEEP);
diff --git a/drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.c b/drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.c
index cdfc3d0..8206b77 100644
--- a/drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.c
+++ b/drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.c
@@ -190,6 +190,7 @@ static int pb0100_start(struct sd *sd)
 	int err, packet_size, max_packet_size;
 	struct usb_host_interface *alt;
 	struct usb_interface *intf;
+	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
 	struct cam *cam = &sd->gspca_dev.cam;
 	u32 mode = cam->cam_mode[sd->gspca_dev.curr_mode].priv;
 
@@ -239,6 +240,7 @@ static int pb0100_start(struct sd *sd)
 
 static int pb0100_stop(struct sd *sd)
 {
+	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
 	int err;
 
 	err = stv06xx_write_sensor(sd, PB_ABORTFRAME, 1);
@@ -334,7 +336,7 @@ static int pb0100_set_gain(struct gspca_dev *gspca_dev, __s32 val)
 	err = stv06xx_write_sensor(sd, PB_G1GAIN, val);
 	if (!err)
 		err = stv06xx_write_sensor(sd, PB_G2GAIN, val);
-	PDEBUG(D_V4L2, "Set green gain to %d, status: %d", val, err);
+	PDEBUG(D_CONF, "Set green gain to %d, status: %d", val, err);
 
 	if (!err)
 		err = pb0100_set_red_balance(gspca_dev, ctrls->red->val);
@@ -357,7 +359,7 @@ static int pb0100_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
 		val = 255;
 
 	err = stv06xx_write_sensor(sd, PB_RGAIN, val);
-	PDEBUG(D_V4L2, "Set red gain to %d, status: %d", val, err);
+	PDEBUG(D_CONF, "Set red gain to %d, status: %d", val, err);
 
 	return err;
 }
@@ -375,7 +377,7 @@ static int pb0100_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
 		val = 255;
 
 	err = stv06xx_write_sensor(sd, PB_BGAIN, val);
-	PDEBUG(D_V4L2, "Set blue gain to %d, status: %d", val, err);
+	PDEBUG(D_CONF, "Set blue gain to %d, status: %d", val, err);
 
 	return err;
 }
@@ -386,7 +388,7 @@ static int pb0100_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
 	int err;
 
 	err = stv06xx_write_sensor(sd, PB_RINTTIME, val);
-	PDEBUG(D_V4L2, "Set exposure to %d, status: %d", val, err);
+	PDEBUG(D_CONF, "Set exposure to %d, status: %d", val, err);
 
 	return err;
 }
@@ -406,7 +408,7 @@ static int pb0100_set_autogain(struct gspca_dev *gspca_dev, __s32 val)
 		val = 0;
 
 	err = stv06xx_write_sensor(sd, PB_EXPGAIN, val);
-	PDEBUG(D_V4L2, "Set autogain to %d (natural: %d), status: %d",
+	PDEBUG(D_CONF, "Set autogain to %d (natural: %d), status: %d",
 	       val, ctrls->natural->val, err);
 
 	return err;
@@ -428,7 +430,7 @@ static int pb0100_set_autogain_target(struct gspca_dev *gspca_dev, __s32 val)
 	if (!err)
 		err = stv06xx_write_sensor(sd, PB_R22, darkpixels);
 
-	PDEBUG(D_V4L2, "Set autogain target to %d, status: %d", val, err);
+	PDEBUG(D_CONF, "Set autogain target to %d, status: %d", val, err);
 
 	return err;
 }
diff --git a/drivers/media/usb/gspca/stv06xx/stv06xx_st6422.c b/drivers/media/usb/gspca/stv06xx/stv06xx_st6422.c
index 8a57990..515a9e1 100644
--- a/drivers/media/usb/gspca/stv06xx/stv06xx_st6422.c
+++ b/drivers/media/usb/gspca/stv06xx/stv06xx_st6422.c
@@ -279,6 +279,8 @@ static int st6422_start(struct sd *sd)
 
 static int st6422_stop(struct sd *sd)
 {
+	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
+
 	PDEBUG(D_STREAM, "Halting stream");
 
 	return 0;
diff --git a/drivers/media/usb/gspca/stv06xx/stv06xx_vv6410.c b/drivers/media/usb/gspca/stv06xx/stv06xx_vv6410.c
index e95fa89..bf3e5c3 100644
--- a/drivers/media/usb/gspca/stv06xx/stv06xx_vv6410.c
+++ b/drivers/media/usb/gspca/stv06xx/stv06xx_vv6410.c
@@ -131,6 +131,7 @@ static int vv6410_init(struct sd *sd)
 static int vv6410_start(struct sd *sd)
 {
 	int err;
+	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
 	struct cam *cam = &sd->gspca_dev.cam;
 	u32 priv = cam->cam_mode[sd->gspca_dev.curr_mode].priv;
 
@@ -163,6 +164,7 @@ static int vv6410_start(struct sd *sd)
 
 static int vv6410_stop(struct sd *sd)
 {
+	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
 	int err;
 
 	/* Turn off LED */
@@ -208,7 +210,7 @@ static int vv6410_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
 	else
 		i2c_data &= ~VV6410_HFLIP;
 
-	PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
+	PDEBUG(D_CONF, "Set horizontal flip to %d", val);
 	err = stv06xx_write_sensor(sd, VV6410_DATAFORMAT, i2c_data);
 
 	return (err < 0) ? err : 0;
@@ -229,7 +231,7 @@ static int vv6410_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
 	else
 		i2c_data &= ~VV6410_VFLIP;
 
-	PDEBUG(D_V4L2, "Set vertical flip to %d", val);
+	PDEBUG(D_CONF, "Set vertical flip to %d", val);
 	err = stv06xx_write_sensor(sd, VV6410_DATAFORMAT, i2c_data);
 
 	return (err < 0) ? err : 0;
@@ -240,7 +242,7 @@ static int vv6410_set_analog_gain(struct gspca_dev *gspca_dev, __s32 val)
 	int err;
 	struct sd *sd = (struct sd *) gspca_dev;
 
-	PDEBUG(D_V4L2, "Set analog gain to %d", val);
+	PDEBUG(D_CONF, "Set analog gain to %d", val);
 	err = stv06xx_write_sensor(sd, VV6410_ANALOGGAIN, 0xf0 | (val & 0xf));
 
 	return (err < 0) ? err : 0;
@@ -257,7 +259,7 @@ static int vv6410_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
 	fine = val % VV6410_CIF_LINELENGTH;
 	coarse = min(512, val / VV6410_CIF_LINELENGTH);
 
-	PDEBUG(D_V4L2, "Set coarse exposure to %d, fine expsure to %d",
+	PDEBUG(D_CONF, "Set coarse exposure to %d, fine expsure to %d",
 	       coarse, fine);
 
 	err = stv06xx_write_sensor(sd, VV6410_FINEH, fine >> 8);
diff --git a/drivers/media/usb/gspca/sunplus.c b/drivers/media/usb/gspca/sunplus.c
index 9ccfcb1..af8767a 100644
--- a/drivers/media/usb/gspca/sunplus.c
+++ b/drivers/media/usb/gspca/sunplus.c
@@ -251,12 +251,10 @@ static void reg_r(struct gspca_dev *gspca_dev,
 {
 	int ret;
 
-#ifdef GSPCA_DEBUG
 	if (len > USB_BUF_SZ) {
-		pr_err("reg_r: buffer overflow\n");
+		PERR("reg_r: buffer overflow\n");
 		return;
 	}
-#endif
 	if (gspca_dev->usb_err < 0)
 		return;
 	ret = usb_control_msg(gspca_dev->dev,
@@ -357,12 +355,14 @@ static void spca504_acknowledged_command(struct gspca_dev *gspca_dev,
 	PDEBUG(D_FRAM, "after wait 0x%04x", gspca_dev->usb_buf[0]);
 }
 
-#ifdef GSPCA_DEBUG
 static void spca504_read_info(struct gspca_dev *gspca_dev)
 {
 	int i;
 	u8 info[6];
 
+	if (gspca_debug < D_STREAM)
+		return;
+
 	for (i = 0; i < 6; i++) {
 		reg_r(gspca_dev, 0, i, 1);
 		info[i] = gspca_dev->usb_buf[0];
@@ -373,7 +373,6 @@ static void spca504_read_info(struct gspca_dev *gspca_dev)
 		info[0], info[1], info[2],
 		info[3], info[4], info[5]);
 }
-#endif
 
 static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev,
 			u8 req,
@@ -432,11 +431,13 @@ static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev)
 	}
 }
 
-#ifdef GSPCA_DEBUG
 static void spca50x_GetFirmware(struct gspca_dev *gspca_dev)
 {
 	u8 *data;
 
+	if (gspca_debug < D_STREAM)
+		return;
+
 	data = gspca_dev->usb_buf;
 	reg_r(gspca_dev, 0x20, 0, 5);
 	PDEBUG(D_STREAM, "FirmWare: %d %d %d %d %d",
@@ -444,7 +445,6 @@ static void spca50x_GetFirmware(struct gspca_dev *gspca_dev)
 	reg_r(gspca_dev, 0x23, 0, 64);
 	reg_r(gspca_dev, 0x23, 1, 64);
 }
-#endif
 
 static void spca504B_SetSizeType(struct gspca_dev *gspca_dev)
 {
@@ -457,9 +457,8 @@ static void spca504B_SetSizeType(struct gspca_dev *gspca_dev)
 		reg_w_riv(gspca_dev, 0x31, 0, 0);
 		spca504B_WaitCmdStatus(gspca_dev);
 		spca504B_PollingDataReady(gspca_dev);
-#ifdef GSPCA_DEBUG
 		spca50x_GetFirmware(gspca_dev);
-#endif
+
 		reg_w_1(gspca_dev, 0x24, 0, 8, 2);		/* type */
 		reg_r(gspca_dev, 0x24, 8, 1);
 
@@ -645,14 +644,10 @@ static int sd_init(struct gspca_dev *gspca_dev)
 		/* fall thru */
 	case BRIDGE_SPCA533:
 		spca504B_PollingDataReady(gspca_dev);
-#ifdef GSPCA_DEBUG
 		spca50x_GetFirmware(gspca_dev);
-#endif
 		break;
 	case BRIDGE_SPCA536:
-#ifdef GSPCA_DEBUG
 		spca50x_GetFirmware(gspca_dev);
-#endif
 		reg_r(gspca_dev, 0x00, 0x5002, 1);
 		reg_w_1(gspca_dev, 0x24, 0, 0, 0);
 		reg_r(gspca_dev, 0x24, 0, 1);
@@ -678,9 +673,7 @@ static int sd_init(struct gspca_dev *gspca_dev)
 /*	case BRIDGE_SPCA504: */
 		PDEBUG(D_STREAM, "Opening SPCA504");
 		if (sd->subtype == AiptekMiniPenCam13) {
-#ifdef GSPCA_DEBUG
 			spca504_read_info(gspca_dev);
-#endif
 
 			/* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
 			spca504A_acknowledged_command(gspca_dev, 0x24,
@@ -752,9 +745,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
 		break;
 	case BRIDGE_SPCA504:
 		if (sd->subtype == AiptekMiniPenCam13) {
-#ifdef GSPCA_DEBUG
 			spca504_read_info(gspca_dev);
-#endif
 
 			/* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
 			spca504A_acknowledged_command(gspca_dev, 0x24,
@@ -766,9 +757,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
 							0, 0, 0x9d, 1);
 		} else {
 			spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
-#ifdef GSPCA_DEBUG
 			spca504_read_info(gspca_dev);
-#endif
 			spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
 			spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
 		}
diff --git a/drivers/media/usb/gspca/vc032x.c b/drivers/media/usb/gspca/vc032x.c
index e500795..c00ac57 100644
--- a/drivers/media/usb/gspca/vc032x.c
+++ b/drivers/media/usb/gspca/vc032x.c
@@ -2927,7 +2927,6 @@ static void reg_r(struct gspca_dev *gspca_dev,
 		  u16 len)
 {
 	reg_r_i(gspca_dev, req, index, len);
-#ifdef GSPCA_DEBUG
 	if (gspca_dev->usb_err < 0)
 		return;
 	if (len == 1)
@@ -2936,7 +2935,6 @@ static void reg_r(struct gspca_dev *gspca_dev,
 	else
 		PDEBUG(D_USBI, "GET %02x 0001 %04x %*ph",
 				req, index, 3, gspca_dev->usb_buf);
-#endif
 }
 
 static void reg_w_i(struct gspca_dev *gspca_dev,
@@ -2964,11 +2962,9 @@ static void reg_w(struct gspca_dev *gspca_dev,
 			    u16 value,
 			    u16 index)
 {
-#ifdef GSPCA_DEBUG
 	if (gspca_dev->usb_err < 0)
 		return;
 	PDEBUG(D_USBO, "SET %02x %04x %04x", req, value, index);
-#endif
 	reg_w_i(gspca_dev, req, value, index);
 }
 
@@ -3044,8 +3040,7 @@ static int vc032x_probe_sensor(struct gspca_dev *gspca_dev)
 		if (value == 0 && ptsensor_info->IdAdd == 0x82)
 			value = read_sensor_register(gspca_dev, 0x83);
 		if (value != 0) {
-			PDEBUG(D_ERR|D_PROBE, "Sensor ID %04x (%d)",
-				value, i);
+			PDEBUG(D_PROBE, "Sensor ID %04x (%d)", value, i);
 			if (value == ptsensor_info->VpId)
 				return ptsensor_info->sensorId;
 
@@ -3069,14 +3064,12 @@ static void i2c_write(struct gspca_dev *gspca_dev,
 {
 	int retry;
 
-#ifdef GSPCA_DEBUG
 	if (gspca_dev->usb_err < 0)
 		return;
 	if (size == 1)
 		PDEBUG(D_USBO, "i2c_w %02x %02x", reg, *val);
 	else
 		PDEBUG(D_USBO, "i2c_w %02x %02x%02x", reg, *val, val[1]);
-#endif
 	reg_r_i(gspca_dev, 0xa1, 0xb33f, 1);
 /*fixme:should check if (!(gspca_dev->usb_buf[0] & 0x02)) error*/
 	reg_w_i(gspca_dev, 0xa0, size, 0xb334);
diff --git a/drivers/media/usb/gspca/w996Xcf.c b/drivers/media/usb/gspca/w996Xcf.c
index 9e3a909..2165da0 100644
--- a/drivers/media/usb/gspca/w996Xcf.c
+++ b/drivers/media/usb/gspca/w996Xcf.c
@@ -232,6 +232,7 @@ static void w9968cf_smbus_write_nack(struct sd *sd)
 
 static void w9968cf_smbus_read_ack(struct sd *sd)
 {
+	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
 	int sda;
 
 	/* Ensure SDA is high before raising clock to avoid a spurious stop */
@@ -248,6 +249,7 @@ static void w9968cf_smbus_read_ack(struct sd *sd)
 /* SMBus protocol: S Addr Wr [A] Subaddr [A] Value [A] P */
 static void w9968cf_i2c_w(struct sd *sd, u8 reg, u8 value)
 {
+	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
 	u16* data = (u16 *)sd->gspca_dev.usb_buf;
 
 	data[0] = 0x082f | ((sd->sensor_addr & 0x80) ? 0x1500 : 0x0);
@@ -297,6 +299,7 @@ static void w9968cf_i2c_w(struct sd *sd, u8 reg, u8 value)
 /* SMBus protocol: S Addr Wr [A] Subaddr [A] P S Addr+1 Rd [A] [Value] NA P */
 static int w9968cf_i2c_r(struct sd *sd, u8 reg)
 {
+	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
 	int ret = 0;
 	u8 value;
 
@@ -326,7 +329,7 @@ static int w9968cf_i2c_r(struct sd *sd, u8 reg)
 		ret = value;
 		PDEBUG(D_USBI, "i2c [0x%02X] -> 0x%02X", reg, value);
 	} else
-		PDEBUG(D_ERR, "i2c read [0x%02x] failed", reg);
+		PERR("i2c read [0x%02x] failed", reg);
 
 	return ret;
 }
diff --git a/drivers/media/usb/gspca/zc3xx.c b/drivers/media/usb/gspca/zc3xx.c
index a8dc421..cbfc2f9 100644
--- a/drivers/media/usb/gspca/zc3xx.c
+++ b/drivers/media/usb/gspca/zc3xx.c
@@ -6259,12 +6259,11 @@ static int vga_3wr_probe(struct gspca_dev *gspca_dev)
 	retword |= i2c_read(gspca_dev, 0x01);		/* ID 1 */
 	PDEBUG(D_PROBE, "probe 3wr vga 2 0x%04x", retword);
 	if (retword == 0x2030) {
-#ifdef GSPCA_DEBUG
 		u8 retbyte;
 
 		retbyte = i2c_read(gspca_dev, 0x02);	/* revision number */
 		PDEBUG(D_PROBE, "sensor PO2030 rev 0x%02x", retbyte);
-#endif
+
 		send_unknown(gspca_dev, SENSOR_PO2030);
 		return retword;
 	}
diff --git a/drivers/media/usb/hdpvr/hdpvr-core.c b/drivers/media/usb/hdpvr/hdpvr-core.c
index 5c61935..73195fe 100644
--- a/drivers/media/usb/hdpvr/hdpvr-core.c
+++ b/drivers/media/usb/hdpvr/hdpvr-core.c
@@ -196,6 +196,7 @@ static int device_authorization(struct hdpvr_device *dev)
 	hex_dump_to_buffer(response, 8, 16, 1, print_buf, 5*buf_size+1, 0);
 	v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, " response: %s\n",
 		 print_buf);
+	kfree(print_buf);
 #endif
 
 	msleep(100);
diff --git a/drivers/media/usb/hdpvr/hdpvr-video.c b/drivers/media/usb/hdpvr/hdpvr-video.c
index da6b779..2983bf0 100644
--- a/drivers/media/usb/hdpvr/hdpvr-video.c
+++ b/drivers/media/usb/hdpvr/hdpvr-video.c
@@ -10,6 +10,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/kconfig.h>
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -581,13 +582,13 @@ static int vidioc_querycap(struct file *file, void  *priv,
 }
 
 static int vidioc_s_std(struct file *file, void *private_data,
-			v4l2_std_id *std)
+			v4l2_std_id std)
 {
 	struct hdpvr_fh *fh = file->private_data;
 	struct hdpvr_device *dev = fh->dev;
 	u8 std_type = 1;
 
-	if (*std & (V4L2_STD_NTSC | V4L2_STD_PAL_60))
+	if (std & (V4L2_STD_NTSC | V4L2_STD_PAL_60))
 		std_type = 0;
 
 	return hdpvr_config_call(dev, CTRL_VIDEO_STD_TYPE, std_type);
@@ -1238,7 +1239,7 @@ static void hdpvr_device_release(struct video_device *vdev)
 	v4l2_device_unregister(&dev->v4l2_dev);
 
 	/* deregister I2C adapter */
-#if defined(CONFIG_I2C) || (CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
 	mutex_lock(&dev->i2c_mutex);
 	i2c_del_adapter(&dev->i2c_adapter);
 	mutex_unlock(&dev->i2c_mutex);
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c
index 299751a..e11267f 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c
+++ b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c
@@ -5165,7 +5165,7 @@ static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw)
 
 
 int pvr2_hdw_register_access(struct pvr2_hdw *hdw,
-			     struct v4l2_dbg_match *match, u64 reg_id,
+			     const struct v4l2_dbg_match *match, u64 reg_id,
 			     int setFl, u64 *val_ptr)
 {
 #ifdef CONFIG_VIDEO_ADV_DEBUG
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-hdw.h b/drivers/media/usb/pvrusb2/pvrusb2-hdw.h
index 8060fc6..91bae93 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-hdw.h
+++ b/drivers/media/usb/pvrusb2/pvrusb2-hdw.h
@@ -240,7 +240,7 @@ void pvr2_hdw_v4l_store_minor_number(struct pvr2_hdw *,
    setFl   - true to set the register, false to read it
    val_ptr - storage location for source / result. */
 int pvr2_hdw_register_access(struct pvr2_hdw *,
-			     struct v4l2_dbg_match *match, u64 reg_id,
+			     const struct v4l2_dbg_match *match, u64 reg_id,
 			     int setFl, u64 *val_ptr);
 
 /* The following entry points are all lower level things you normally don't
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c b/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c
index 34c3b6e..a8a65fa 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c
+++ b/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c
@@ -196,13 +196,13 @@ static int pvr2_g_std(struct file *file, void *priv, v4l2_std_id *std)
 	return ret;
 }
 
-static int pvr2_s_std(struct file *file, void *priv, v4l2_std_id *std)
+static int pvr2_s_std(struct file *file, void *priv, v4l2_std_id std)
 {
 	struct pvr2_v4l2_fh *fh = file->private_data;
 	struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
 
 	return pvr2_ctrl_set_value(
-		pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_STDCUR), *std);
+		pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_STDCUR), std);
 }
 
 static int pvr2_querystd(struct file *file, void *priv, v4l2_std_id *std)
@@ -352,7 +352,7 @@ static int pvr2_g_tuner(struct file *file, void *priv, struct v4l2_tuner *vt)
 	return pvr2_hdw_get_tuner_status(hdw, vt);
 }
 
-static int pvr2_s_tuner(struct file *file, void *priv, struct v4l2_tuner *vt)
+static int pvr2_s_tuner(struct file *file, void *priv, const struct v4l2_tuner *vt)
 {
 	struct pvr2_v4l2_fh *fh = file->private_data;
 	struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
@@ -365,7 +365,7 @@ static int pvr2_s_tuner(struct file *file, void *priv, struct v4l2_tuner *vt)
 			vt->audmode);
 }
 
-static int pvr2_s_frequency(struct file *file, void *priv, struct v4l2_frequency *vf)
+static int pvr2_s_frequency(struct file *file, void *priv, const struct v4l2_frequency *vf)
 {
 	struct pvr2_v4l2_fh *fh = file->private_data;
 	struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
@@ -815,7 +815,7 @@ static int pvr2_g_register(struct file *file, void *priv, struct v4l2_dbg_regist
 	return ret;
 }
 
-static int pvr2_s_register(struct file *file, void *priv, struct v4l2_dbg_register *req)
+static int pvr2_s_register(struct file *file, void *priv, const struct v4l2_dbg_register *req)
 {
 	struct pvr2_v4l2_fh *fh = file->private_data;
 	struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
diff --git a/drivers/media/usb/pwc/pwc-if.c b/drivers/media/usb/pwc/pwc-if.c
index 5ec15cb..77bbf78 100644
--- a/drivers/media/usb/pwc/pwc-if.c
+++ b/drivers/media/usb/pwc/pwc-if.c
@@ -1001,6 +1001,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
 	pdev->vb_queue.buf_struct_size = sizeof(struct pwc_frame_buf);
 	pdev->vb_queue.ops = &pwc_vb_queue_ops;
 	pdev->vb_queue.mem_ops = &vb2_vmalloc_memops;
+	pdev->vb_queue.timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
 	rc = vb2_queue_init(&pdev->vb_queue);
 	if (rc < 0) {
 		PWC_ERROR("Oops, could not initialize vb2 queue.\n");
diff --git a/drivers/media/usb/s2255/s2255drv.c b/drivers/media/usb/s2255/s2255drv.c
index 498c57e..ab97e7d 100644
--- a/drivers/media/usb/s2255/s2255drv.c
+++ b/drivers/media/usb/s2255/s2255drv.c
@@ -43,12 +43,14 @@
 #include <linux/slab.h>
 #include <linux/videodev2.h>
 #include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <linux/usb.h>
 #include <media/videobuf-vmalloc.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-ioctl.h>
-#include <linux/vmalloc.h>
-#include <linux/usb.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-event.h>
 
 #define S2255_VERSION		"1.22.1"
 #define FIRMWARE_FILE_NAME "f2255usb.bin"
@@ -217,12 +219,15 @@ struct s2255_dev;
 
 struct s2255_channel {
 	struct video_device	vdev;
+	struct v4l2_ctrl_handler hdl;
+	struct v4l2_ctrl	*jpegqual_ctrl;
 	int			resources;
 	struct s2255_dmaqueue	vidq;
 	struct s2255_bufferi	buffer;
 	struct s2255_mode	mode;
+	v4l2_std_id		std;
 	/* jpeg compression */
-	struct v4l2_jpegcompression jc;
+	unsigned		jpegqual;
 	/* capture parameters (for high quality mode full size) */
 	struct v4l2_captureparm cap_parm;
 	int			cur_frame;
@@ -292,6 +297,8 @@ struct s2255_buffer {
 };
 
 struct s2255_fh {
+	/* this must be the first field in this struct */
+	struct v4l2_fh		fh;
 	struct s2255_dev	*dev;
 	struct videobuf_queue	vb_vidq;
 	enum v4l2_buf_type	type;
@@ -306,7 +313,7 @@ struct s2255_fh {
 /* Need DSP version 5+ for video status feature */
 #define S2255_MIN_DSP_STATUS      5
 #define S2255_MIN_DSP_COLORFILTER 8
-#define S2255_NORMS		(V4L2_STD_PAL | V4L2_STD_NTSC)
+#define S2255_NORMS		(V4L2_STD_ALL)
 
 /* private V4L2 controls */
 
@@ -336,7 +343,7 @@ struct s2255_fh {
  */
 #define S2255_V4L2_YC_ON  1
 #define S2255_V4L2_YC_OFF 0
-#define V4L2_CID_PRIVATE_COLORFILTER (V4L2_CID_PRIVATE_BASE + 0)
+#define V4L2_CID_S2255_COLORFILTER (V4L2_CID_USER_S2255_BASE + 0)
 
 /* frame prefix size (sent once every frame) */
 #define PREFIX_SIZE		512
@@ -409,11 +416,6 @@ MODULE_DEVICE_TABLE(usb, s2255_table);
 /* JPEG formats must be defined last to support jpeg_enable parameter */
 static const struct s2255_fmt formats[] = {
 	{
-		.name = "4:2:2, planar, YUV422P",
-		.fourcc = V4L2_PIX_FMT_YUV422P,
-		.depth = 16
-
-	}, {
 		.name = "4:2:2, packed, YUYV",
 		.fourcc = V4L2_PIX_FMT_YUYV,
 		.depth = 16
@@ -423,6 +425,11 @@ static const struct s2255_fmt formats[] = {
 		.fourcc = V4L2_PIX_FMT_UYVY,
 		.depth = 16
 	}, {
+		.name = "4:2:2, planar, YUV422P",
+		.fourcc = V4L2_PIX_FMT_YUV422P,
+		.depth = 16
+
+	}, {
 		.name = "8bpp GREY",
 		.fourcc = V4L2_PIX_FMT_GREY,
 		.depth = 8
@@ -437,27 +444,27 @@ static const struct s2255_fmt formats[] = {
 	}
 };
 
-static int norm_maxw(struct video_device *vdev)
+static int norm_maxw(struct s2255_channel *channel)
 {
-	return (vdev->current_norm & V4L2_STD_NTSC) ?
+	return (channel->std & V4L2_STD_525_60) ?
 	    LINE_SZ_4CIFS_NTSC : LINE_SZ_4CIFS_PAL;
 }
 
-static int norm_maxh(struct video_device *vdev)
+static int norm_maxh(struct s2255_channel *channel)
 {
-	return (vdev->current_norm & V4L2_STD_NTSC) ?
+	return (channel->std & V4L2_STD_525_60) ?
 	    (NUM_LINES_1CIFS_NTSC * 2) : (NUM_LINES_1CIFS_PAL * 2);
 }
 
-static int norm_minw(struct video_device *vdev)
+static int norm_minw(struct s2255_channel *channel)
 {
-	return (vdev->current_norm & V4L2_STD_NTSC) ?
+	return (channel->std & V4L2_STD_525_60) ?
 	    LINE_SZ_1CIFS_NTSC : LINE_SZ_1CIFS_PAL;
 }
 
-static int norm_minh(struct video_device *vdev)
+static int norm_minh(struct s2255_channel *channel)
 {
-	return (vdev->current_norm & V4L2_STD_NTSC) ?
+	return (channel->std & V4L2_STD_525_60) ?
 	    (NUM_LINES_1CIFS_NTSC) : (NUM_LINES_1CIFS_PAL);
 }
 
@@ -515,7 +522,7 @@ static void s2255_timer(unsigned long user_data)
 
 
 /* this loads the firmware asynchronously.
-   Originally this was done synchroously in probe.
+   Originally this was done synchronously in probe.
    But it is better to load it asynchronously here than block
    inside the probe function. Blocking inside probe affects boot time.
    FW loading is triggered by the timer in the probe function
@@ -719,10 +726,10 @@ static int buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
 	if (channel->fmt == NULL)
 		return -EINVAL;
 
-	if ((w < norm_minw(&channel->vdev)) ||
-	    (w > norm_maxw(&channel->vdev)) ||
-	    (h < norm_minh(&channel->vdev)) ||
-	    (h > norm_maxh(&channel->vdev))) {
+	if ((w < norm_minw(channel)) ||
+	    (w > norm_maxw(channel)) ||
+	    (h < norm_minh(channel)) ||
+	    (h > norm_maxh(channel))) {
 		dprintk(4, "invalid buffer prepare\n");
 		return -EINVAL;
 	}
@@ -810,37 +817,17 @@ static void res_free(struct s2255_fh *fh)
 	dprintk(1, "res: put\n");
 }
 
-static int vidioc_querymenu(struct file *file, void *priv,
-			    struct v4l2_querymenu *qmenu)
-{
-	static const char *colorfilter[] = {
-		"Off",
-		"On",
-		NULL
-	};
-	if (qmenu->id == V4L2_CID_PRIVATE_COLORFILTER) {
-		int i;
-		const char **menu_items = colorfilter;
-		for (i = 0; i < qmenu->index && menu_items[i]; i++)
-			; /* do nothing (from v4l2-common.c) */
-		if (menu_items[i] == NULL || menu_items[i][0] == '\0')
-			return -EINVAL;
-		strlcpy(qmenu->name, menu_items[qmenu->index],
-			sizeof(qmenu->name));
-		return 0;
-	}
-	return v4l2_ctrl_query_menu(qmenu, NULL, NULL);
-}
-
 static int vidioc_querycap(struct file *file, void *priv,
 			   struct v4l2_capability *cap)
 {
 	struct s2255_fh *fh = file->private_data;
 	struct s2255_dev *dev = fh->dev;
+
 	strlcpy(cap->driver, "s2255", sizeof(cap->driver));
 	strlcpy(cap->card, "s2255", sizeof(cap->card));
 	usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
-	cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
+	cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
+	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
 	return 0;
 }
 
@@ -865,13 +852,20 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
 {
 	struct s2255_fh *fh = priv;
 	struct s2255_channel *channel = fh->channel;
+	int is_ntsc = channel->std & V4L2_STD_525_60;
 
 	f->fmt.pix.width = channel->width;
 	f->fmt.pix.height = channel->height;
-	f->fmt.pix.field = fh->vb_vidq.field;
+	if (f->fmt.pix.height >=
+	    (is_ntsc ? NUM_LINES_1CIFS_NTSC : NUM_LINES_1CIFS_PAL) * 2)
+		f->fmt.pix.field = V4L2_FIELD_INTERLACED;
+	else
+		f->fmt.pix.field = V4L2_FIELD_TOP;
 	f->fmt.pix.pixelformat = channel->fmt->fourcc;
 	f->fmt.pix.bytesperline = f->fmt.pix.width * (channel->fmt->depth >> 3);
 	f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
+	f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+	f->fmt.pix.priv = 0;
 	return 0;
 }
 
@@ -880,12 +874,9 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
 {
 	const struct s2255_fmt *fmt;
 	enum v4l2_field field;
-	int  b_any_field = 0;
 	struct s2255_fh *fh = priv;
 	struct s2255_channel *channel = fh->channel;
-	int is_ntsc;
-	is_ntsc =
-		(channel->vdev.current_norm & V4L2_STD_NTSC) ? 1 : 0;
+	int is_ntsc = channel->std & V4L2_STD_525_60;
 
 	fmt = format_by_fourcc(f->fmt.pix.pixelformat);
 
@@ -893,8 +884,6 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
 		return -EINVAL;
 
 	field = f->fmt.pix.field;
-	if (field == V4L2_FIELD_ANY)
-		b_any_field = 1;
 
 	dprintk(50, "%s NTSC: %d suggested width: %d, height: %d\n",
 		__func__, is_ntsc, f->fmt.pix.width, f->fmt.pix.height);
@@ -902,24 +891,10 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
 		/* NTSC */
 		if (f->fmt.pix.height >= NUM_LINES_1CIFS_NTSC * 2) {
 			f->fmt.pix.height = NUM_LINES_1CIFS_NTSC * 2;
-			if (b_any_field) {
-				field = V4L2_FIELD_SEQ_TB;
-			} else if (!((field == V4L2_FIELD_INTERLACED) ||
-				      (field == V4L2_FIELD_SEQ_TB) ||
-				      (field == V4L2_FIELD_INTERLACED_TB))) {
-				dprintk(1, "unsupported field setting\n");
-				return -EINVAL;
-			}
+			field = V4L2_FIELD_INTERLACED;
 		} else {
 			f->fmt.pix.height = NUM_LINES_1CIFS_NTSC;
-			if (b_any_field) {
-				field = V4L2_FIELD_TOP;
-			} else if (!((field == V4L2_FIELD_TOP) ||
-				      (field == V4L2_FIELD_BOTTOM))) {
-				dprintk(1, "unsupported field setting\n");
-				return -EINVAL;
-			}
-
+			field = V4L2_FIELD_TOP;
 		}
 		if (f->fmt.pix.width >= LINE_SZ_4CIFS_NTSC)
 			f->fmt.pix.width = LINE_SZ_4CIFS_NTSC;
@@ -933,41 +908,25 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
 		/* PAL */
 		if (f->fmt.pix.height >= NUM_LINES_1CIFS_PAL * 2) {
 			f->fmt.pix.height = NUM_LINES_1CIFS_PAL * 2;
-			if (b_any_field) {
-				field = V4L2_FIELD_SEQ_TB;
-			} else if (!((field == V4L2_FIELD_INTERLACED) ||
-				      (field == V4L2_FIELD_SEQ_TB) ||
-				      (field == V4L2_FIELD_INTERLACED_TB))) {
-				dprintk(1, "unsupported field setting\n");
-				return -EINVAL;
-			}
+			field = V4L2_FIELD_INTERLACED;
 		} else {
 			f->fmt.pix.height = NUM_LINES_1CIFS_PAL;
-			if (b_any_field) {
-				field = V4L2_FIELD_TOP;
-			} else if (!((field == V4L2_FIELD_TOP) ||
-				     (field == V4L2_FIELD_BOTTOM))) {
-				dprintk(1, "unsupported field setting\n");
-				return -EINVAL;
-			}
+			field = V4L2_FIELD_TOP;
 		}
-		if (f->fmt.pix.width >= LINE_SZ_4CIFS_PAL) {
+		if (f->fmt.pix.width >= LINE_SZ_4CIFS_PAL)
 			f->fmt.pix.width = LINE_SZ_4CIFS_PAL;
-			field = V4L2_FIELD_SEQ_TB;
-		} else if (f->fmt.pix.width >= LINE_SZ_2CIFS_PAL) {
+		else if (f->fmt.pix.width >= LINE_SZ_2CIFS_PAL)
 			f->fmt.pix.width = LINE_SZ_2CIFS_PAL;
-			field = V4L2_FIELD_TOP;
-		} else if (f->fmt.pix.width >= LINE_SZ_1CIFS_PAL) {
+		else if (f->fmt.pix.width >= LINE_SZ_1CIFS_PAL)
 			f->fmt.pix.width = LINE_SZ_1CIFS_PAL;
-			field = V4L2_FIELD_TOP;
-		} else {
+		else
 			f->fmt.pix.width = LINE_SZ_1CIFS_PAL;
-			field = V4L2_FIELD_TOP;
-		}
 	}
 	f->fmt.pix.field = field;
 	f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3;
 	f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
+	f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+	f->fmt.pix.priv = 0;
 	dprintk(50, "%s: set width %d height %d field %d\n", __func__,
 		f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field);
 	return 0;
@@ -1012,8 +971,8 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
 	channel->height = f->fmt.pix.height;
 	fh->vb_vidq.field = f->fmt.pix.field;
 	fh->type = f->type;
-	if (channel->width > norm_minw(&channel->vdev)) {
-		if (channel->height > norm_minh(&channel->vdev)) {
+	if (channel->width > norm_minw(channel)) {
+		if (channel->height > norm_minh(channel)) {
 			if (channel->cap_parm.capturemode &
 			    V4L2_MODE_HIGHQUALITY)
 				mode.scale = SCALE_4CIFSI;
@@ -1035,7 +994,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
 	case V4L2_PIX_FMT_MJPEG:
 		mode.color &= ~MASK_COLOR;
 		mode.color |= COLOR_JPG;
-		mode.color |= (channel->jc.quality << 8);
+		mode.color |= (channel->jpegqual << 8);
 		break;
 	case V4L2_PIX_FMT_YUV422P:
 		mode.color &= ~MASK_COLOR;
@@ -1198,6 +1157,8 @@ static int s2255_set_mode(struct s2255_channel *channel,
 	__le32 *buffer;
 	unsigned long chn_rev;
 	struct s2255_dev *dev = to_s2255_dev(channel->vdev.v4l2_dev);
+	int i;
+
 	chn_rev = G_chnmap[channel->idx];
 	dprintk(3, "%s channel: %d\n", __func__, channel->idx);
 	/* if JPEG, set the quality */
@@ -1205,7 +1166,7 @@ static int s2255_set_mode(struct s2255_channel *channel,
 		mode->color &= ~MASK_COLOR;
 		mode->color |= COLOR_JPG;
 		mode->color &= ~MASK_JPG_QUALITY;
-		mode->color |= (channel->jc.quality << 8);
+		mode->color |= (channel->jpegqual << 8);
 	}
 	/* save the mode */
 	channel->mode = *mode;
@@ -1220,7 +1181,8 @@ static int s2255_set_mode(struct s2255_channel *channel,
 	buffer[0] = IN_DATA_TOKEN;
 	buffer[1] = (__le32) cpu_to_le32(chn_rev);
 	buffer[2] = CMD_SET_MODE;
-	memcpy(&buffer[3], &channel->mode, sizeof(struct s2255_mode));
+	for (i = 0; i < sizeof(struct s2255_mode) / sizeof(u32); i++)
+		buffer[3 + i] = cpu_to_le32(((u32 *)&channel->mode)[i]);
 	channel->setmode_ready = 0;
 	res = s2255_write_config(dev->udev, (unsigned char *)buffer, 512);
 	if (debug)
@@ -1332,12 +1294,14 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
 	return 0;
 }
 
-static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *i)
+static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id i)
 {
 	struct s2255_fh *fh = priv;
 	struct s2255_mode mode;
 	struct videobuf_queue *q = &fh->vb_vidq;
+	struct s2255_channel *channel = fh->channel;
 	int ret = 0;
+
 	mutex_lock(&q->vb_lock);
 	if (videobuf_queue_is_busy(q)) {
 		dprintk(1, "queue busy\n");
@@ -1350,24 +1314,30 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *i)
 		goto out_s_std;
 	}
 	mode = fh->channel->mode;
-	if (*i & V4L2_STD_NTSC) {
-		dprintk(4, "%s NTSC\n", __func__);
+	if (i & V4L2_STD_525_60) {
+		dprintk(4, "%s 60 Hz\n", __func__);
 		/* if changing format, reset frame decimation/intervals */
 		if (mode.format != FORMAT_NTSC) {
 			mode.restart = 1;
 			mode.format = FORMAT_NTSC;
 			mode.fdec = FDEC_1;
+			channel->width = LINE_SZ_4CIFS_NTSC;
+			channel->height = NUM_LINES_4CIFS_NTSC * 2;
 		}
-	} else if (*i & V4L2_STD_PAL) {
-		dprintk(4, "%s PAL\n", __func__);
+	} else if (i & V4L2_STD_625_50) {
+		dprintk(4, "%s 50 Hz\n", __func__);
 		if (mode.format != FORMAT_PAL) {
 			mode.restart = 1;
 			mode.format = FORMAT_PAL;
 			mode.fdec = FDEC_1;
+			channel->width = LINE_SZ_4CIFS_PAL;
+			channel->height = NUM_LINES_4CIFS_PAL * 2;
 		}
 	} else {
 		ret = -EINVAL;
+		goto out_s_std;
 	}
+	fh->channel->std = i;
 	if (mode.restart)
 		s2255_set_mode(fh->channel, &mode);
 out_s_std:
@@ -1375,6 +1345,14 @@ out_s_std:
 	return ret;
 }
 
+static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *i)
+{
+	struct s2255_fh *fh = priv;
+
+	*i = fh->channel->std;
+	return 0;
+}
+
 /* Sensoray 2255 is a multiple channel capture device.
    It does not have a "crossbar" of inputs.
    We use one V4L device per channel. The user must
@@ -1427,110 +1405,36 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
 	return 0;
 }
 
-/* --- controls ---------------------------------------------- */
-static int vidioc_queryctrl(struct file *file, void *priv,
-			    struct v4l2_queryctrl *qc)
-{
-	struct s2255_fh *fh = priv;
-	struct s2255_channel *channel = fh->channel;
-	struct s2255_dev *dev = fh->dev;
-	switch (qc->id) {
-	case V4L2_CID_BRIGHTNESS:
-		v4l2_ctrl_query_fill(qc, -127, 127, 1, DEF_BRIGHT);
-		break;
-	case V4L2_CID_CONTRAST:
-		v4l2_ctrl_query_fill(qc, 0, 255, 1, DEF_CONTRAST);
-		break;
-	case V4L2_CID_SATURATION:
-		v4l2_ctrl_query_fill(qc, 0, 255, 1, DEF_SATURATION);
-		break;
-	case V4L2_CID_HUE:
-		v4l2_ctrl_query_fill(qc, 0, 255, 1, DEF_HUE);
-		break;
-	case V4L2_CID_PRIVATE_COLORFILTER:
-		if (dev->dsp_fw_ver < S2255_MIN_DSP_COLORFILTER)
-			return -EINVAL;
-		if ((dev->pid == 0x2257) && (channel->idx > 1))
-			return -EINVAL;
-		strlcpy(qc->name, "Color Filter", sizeof(qc->name));
-		qc->type = V4L2_CTRL_TYPE_MENU;
-		qc->minimum = 0;
-		qc->maximum = 1;
-		qc->step = 1;
-		qc->default_value = 1;
-		qc->flags = 0;
-		break;
-	default:
-		return -EINVAL;
-	}
-	dprintk(4, "%s, id %d\n", __func__, qc->id);
-	return 0;
-}
-
-static int vidioc_g_ctrl(struct file *file, void *priv,
-			 struct v4l2_control *ctrl)
-{
-	struct s2255_fh *fh = priv;
-	struct s2255_dev *dev = fh->dev;
-	struct s2255_channel *channel = fh->channel;
-	switch (ctrl->id) {
-	case V4L2_CID_BRIGHTNESS:
-		ctrl->value = channel->mode.bright;
-		break;
-	case V4L2_CID_CONTRAST:
-		ctrl->value = channel->mode.contrast;
-		break;
-	case V4L2_CID_SATURATION:
-		ctrl->value = channel->mode.saturation;
-		break;
-	case V4L2_CID_HUE:
-		ctrl->value = channel->mode.hue;
-		break;
-	case V4L2_CID_PRIVATE_COLORFILTER:
-		if (dev->dsp_fw_ver < S2255_MIN_DSP_COLORFILTER)
-			return -EINVAL;
-		if ((dev->pid == 0x2257) && (channel->idx > 1))
-			return -EINVAL;
-		ctrl->value = !((channel->mode.color & MASK_INPUT_TYPE) >> 16);
-		break;
-	default:
-		return -EINVAL;
-	}
-	dprintk(4, "%s, id %d val %d\n", __func__, ctrl->id, ctrl->value);
-	return 0;
-}
-
-static int vidioc_s_ctrl(struct file *file, void *priv,
-			 struct v4l2_control *ctrl)
+static int s2255_s_ctrl(struct v4l2_ctrl *ctrl)
 {
-	struct s2255_fh *fh = priv;
-	struct s2255_channel *channel = fh->channel;
-	struct s2255_dev *dev = to_s2255_dev(channel->vdev.v4l2_dev);
+	struct s2255_channel *channel =
+		container_of(ctrl->handler, struct s2255_channel, hdl);
 	struct s2255_mode mode;
+
 	mode = channel->mode;
 	dprintk(4, "%s\n", __func__);
+
 	/* update the mode to the corresponding value */
 	switch (ctrl->id) {
 	case V4L2_CID_BRIGHTNESS:
-		mode.bright = ctrl->value;
+		mode.bright = ctrl->val;
 		break;
 	case V4L2_CID_CONTRAST:
-		mode.contrast = ctrl->value;
+		mode.contrast = ctrl->val;
 		break;
 	case V4L2_CID_HUE:
-		mode.hue = ctrl->value;
+		mode.hue = ctrl->val;
 		break;
 	case V4L2_CID_SATURATION:
-		mode.saturation = ctrl->value;
+		mode.saturation = ctrl->val;
 		break;
-	case V4L2_CID_PRIVATE_COLORFILTER:
-		if (dev->dsp_fw_ver < S2255_MIN_DSP_COLORFILTER)
-			return -EINVAL;
-		if ((dev->pid == 0x2257) && (channel->idx > 1))
-			return -EINVAL;
+	case V4L2_CID_S2255_COLORFILTER:
 		mode.color &= ~MASK_INPUT_TYPE;
-		mode.color |= ((ctrl->value ? 0 : 1) << 16);
+		mode.color |= !ctrl->val << 16;
 		break;
+	case V4L2_CID_JPEG_COMPRESSION_QUALITY:
+		channel->jpegqual = ctrl->val;
+		return 0;
 	default:
 		return -EINVAL;
 	}
@@ -1539,7 +1443,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
 	   some V4L programs restart stream unnecessarily
 	   after a s_crtl.
 	*/
-	s2255_set_mode(fh->channel, &mode);
+	s2255_set_mode(channel, &mode);
 	return 0;
 }
 
@@ -1548,7 +1452,9 @@ static int vidioc_g_jpegcomp(struct file *file, void *priv,
 {
 	struct s2255_fh *fh = priv;
 	struct s2255_channel *channel = fh->channel;
-	*jc = channel->jc;
+
+	memset(jc, 0, sizeof(*jc));
+	jc->quality = channel->jpegqual;
 	dprintk(2, "%s: quality %d\n", __func__, jc->quality);
 	return 0;
 }
@@ -1560,7 +1466,7 @@ static int vidioc_s_jpegcomp(struct file *file, void *priv,
 	struct s2255_channel *channel = fh->channel;
 	if (jc->quality < 0 || jc->quality > 100)
 		return -EINVAL;
-	channel->jc.quality = jc->quality;
+	v4l2_ctrl_s_ctrl(channel->jpegqual_ctrl, jc->quality);
 	dprintk(2, "%s: quality %d\n", __func__, jc->quality);
 	return 0;
 }
@@ -1573,7 +1479,6 @@ static int vidioc_g_parm(struct file *file, void *priv,
 	struct s2255_channel *channel = fh->channel;
 	if (sp->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
 		return -EINVAL;
-	memset(sp, 0, sizeof(struct v4l2_streamparm));
 	sp->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
 	sp->parm.capture.capturemode = channel->cap_parm.capturemode;
 	def_num = (channel->mode.format == FORMAT_NTSC) ? 1001 : 1000;
@@ -1643,36 +1548,64 @@ static int vidioc_s_parm(struct file *file, void *priv,
 	return 0;
 }
 
+#define NUM_SIZE_ENUMS 3
+static const struct v4l2_frmsize_discrete ntsc_sizes[] = {
+	{ 640, 480 },
+	{ 640, 240 },
+	{ 320, 240 },
+};
+static const struct v4l2_frmsize_discrete pal_sizes[] = {
+	{ 704, 576 },
+	{ 704, 288 },
+	{ 352, 288 },
+};
+
+static int vidioc_enum_framesizes(struct file *file, void *priv,
+			    struct v4l2_frmsizeenum *fe)
+{
+	struct s2255_fh *fh = priv;
+	struct s2255_channel *channel = fh->channel;
+	int is_ntsc = channel->std & V4L2_STD_525_60;
+	const struct s2255_fmt *fmt;
+
+	if (fe->index >= NUM_SIZE_ENUMS)
+		return -EINVAL;
+
+	fmt = format_by_fourcc(fe->pixel_format);
+	if (fmt == NULL)
+		return -EINVAL;
+	fe->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+	fe->discrete = is_ntsc ?  ntsc_sizes[fe->index] : pal_sizes[fe->index];
+	return 0;
+}
+
 static int vidioc_enum_frameintervals(struct file *file, void *priv,
 			    struct v4l2_frmivalenum *fe)
 {
-	int is_ntsc = 0;
+	struct s2255_fh *fh = priv;
+	struct s2255_channel *channel = fh->channel;
+	const struct s2255_fmt *fmt;
+	const struct v4l2_frmsize_discrete *sizes;
+	int is_ntsc = channel->std & V4L2_STD_525_60;
 #define NUM_FRAME_ENUMS 4
 	int frm_dec[NUM_FRAME_ENUMS] = {1, 2, 3, 5};
+	int i;
+
 	if (fe->index >= NUM_FRAME_ENUMS)
 		return -EINVAL;
-	switch (fe->width) {
-	case 640:
-		if (fe->height != 240 && fe->height != 480)
-			return -EINVAL;
-		is_ntsc = 1;
-		break;
-	case 320:
-		if (fe->height != 240)
-			return -EINVAL;
-		is_ntsc = 1;
-		break;
-	case 704:
-		if (fe->height != 288 && fe->height != 576)
-			return -EINVAL;
-		break;
-	case 352:
-		if (fe->height != 288)
-			return -EINVAL;
-		break;
-	default:
+
+	fmt = format_by_fourcc(fe->pixel_format);
+	if (fmt == NULL)
 		return -EINVAL;
-	}
+
+	sizes = is_ntsc ? ntsc_sizes : pal_sizes;
+	for (i = 0; i < NUM_SIZE_ENUMS; i++, sizes++)
+		if (fe->width == sizes->width &&
+		    fe->height == sizes->height)
+			break;
+	if (i == NUM_SIZE_ENUMS)
+		return -EINVAL;
+
 	fe->type = V4L2_FRMIVAL_TYPE_DISCRETE;
 	fe->discrete.denominator = is_ntsc ? 30000 : 25000;
 	fe->discrete.numerator = (is_ntsc ? 1001 : 1000) * frm_dec[fe->index];
@@ -1757,7 +1690,9 @@ static int __s2255_open(struct file *file)
 	fh = kzalloc(sizeof(*fh), GFP_KERNEL);
 	if (NULL == fh)
 		return -ENOMEM;
-	file->private_data = fh;
+	v4l2_fh_init(&fh->fh, vdev);
+	v4l2_fh_add(&fh->fh);
+	file->private_data = &fh->fh;
 	fh->dev = dev;
 	fh->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 	fh->channel = channel;
@@ -1800,12 +1735,13 @@ static unsigned int s2255_poll(struct file *file,
 {
 	struct s2255_fh *fh = file->private_data;
 	struct s2255_dev *dev = fh->dev;
-	int rc;
+	int rc = v4l2_ctrl_poll(file, wait);
+
 	dprintk(100, "%s\n", __func__);
 	if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type)
 		return POLLERR;
 	mutex_lock(&dev->lock);
-	rc = videobuf_poll_stream(file, &fh->vb_vidq, wait);
+	rc |= videobuf_poll_stream(file, &fh->vb_vidq, wait);
 	mutex_unlock(&dev->lock);
 	return rc;
 }
@@ -1852,6 +1788,8 @@ static int s2255_release(struct file *file)
 	videobuf_mmap_free(&fh->vb_vidq);
 	mutex_unlock(&dev->lock);
 	dprintk(1, "%s (dev=%s)\n", __func__, video_device_node_name(vdev));
+	v4l2_fh_del(&fh->fh);
+	v4l2_fh_exit(&fh->fh);
 	kfree(fh);
 	return 0;
 }
@@ -1886,7 +1824,6 @@ static const struct v4l2_file_operations s2255_fops_v4l = {
 };
 
 static const struct v4l2_ioctl_ops s2255_ioctl_ops = {
-	.vidioc_querymenu = vidioc_querymenu,
 	.vidioc_querycap = vidioc_querycap,
 	.vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
 	.vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
@@ -1897,26 +1834,33 @@ static const struct v4l2_ioctl_ops s2255_ioctl_ops = {
 	.vidioc_qbuf = vidioc_qbuf,
 	.vidioc_dqbuf = vidioc_dqbuf,
 	.vidioc_s_std = vidioc_s_std,
+	.vidioc_g_std = vidioc_g_std,
 	.vidioc_enum_input = vidioc_enum_input,
 	.vidioc_g_input = vidioc_g_input,
 	.vidioc_s_input = vidioc_s_input,
-	.vidioc_queryctrl = vidioc_queryctrl,
-	.vidioc_g_ctrl = vidioc_g_ctrl,
-	.vidioc_s_ctrl = vidioc_s_ctrl,
 	.vidioc_streamon = vidioc_streamon,
 	.vidioc_streamoff = vidioc_streamoff,
 	.vidioc_s_jpegcomp = vidioc_s_jpegcomp,
 	.vidioc_g_jpegcomp = vidioc_g_jpegcomp,
 	.vidioc_s_parm = vidioc_s_parm,
 	.vidioc_g_parm = vidioc_g_parm,
+	.vidioc_enum_framesizes = vidioc_enum_framesizes,
 	.vidioc_enum_frameintervals = vidioc_enum_frameintervals,
+	.vidioc_log_status  = v4l2_ctrl_log_status,
+	.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
+	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
 };
 
 static void s2255_video_device_release(struct video_device *vdev)
 {
 	struct s2255_dev *dev = to_s2255_dev(vdev->v4l2_dev);
-	dprintk(4, "%s, chnls: %d \n", __func__,
+	struct s2255_channel *channel =
+		container_of(vdev, struct s2255_channel, vdev);
+
+	v4l2_ctrl_handler_free(&channel->hdl);
+	dprintk(4, "%s, chnls: %d\n", __func__,
 		atomic_read(&dev->num_channels));
+
 	if (atomic_dec_and_test(&dev->num_channels))
 		s2255_destroy(dev);
 	return;
@@ -1928,7 +1872,20 @@ static struct video_device template = {
 	.ioctl_ops = &s2255_ioctl_ops,
 	.release = s2255_video_device_release,
 	.tvnorms = S2255_NORMS,
-	.current_norm = V4L2_STD_NTSC_M,
+};
+
+static const struct v4l2_ctrl_ops s2255_ctrl_ops = {
+	.s_ctrl = s2255_s_ctrl,
+};
+
+static const struct v4l2_ctrl_config color_filter_ctrl = {
+	.ops = &s2255_ctrl_ops,
+	.name = "Color Filter",
+	.id = V4L2_CID_S2255_COLORFILTER,
+	.type = V4L2_CTRL_TYPE_BOOLEAN,
+	.max = 1,
+	.step = 1,
+	.def = 1,
 };
 
 static int s2255_probe_v4l(struct s2255_dev *dev)
@@ -1945,11 +1902,36 @@ static int s2255_probe_v4l(struct s2255_dev *dev)
 	for (i = 0; i < MAX_CHANNELS; i++) {
 		channel = &dev->channel[i];
 		INIT_LIST_HEAD(&channel->vidq.active);
+
+		v4l2_ctrl_handler_init(&channel->hdl, 6);
+		v4l2_ctrl_new_std(&channel->hdl, &s2255_ctrl_ops,
+				V4L2_CID_BRIGHTNESS, -127, 127, 1, DEF_BRIGHT);
+		v4l2_ctrl_new_std(&channel->hdl, &s2255_ctrl_ops,
+				V4L2_CID_CONTRAST, 0, 255, 1, DEF_CONTRAST);
+		v4l2_ctrl_new_std(&channel->hdl, &s2255_ctrl_ops,
+				V4L2_CID_SATURATION, 0, 255, 1, DEF_SATURATION);
+		v4l2_ctrl_new_std(&channel->hdl, &s2255_ctrl_ops,
+				V4L2_CID_HUE, 0, 255, 1, DEF_HUE);
+		channel->jpegqual_ctrl = v4l2_ctrl_new_std(&channel->hdl,
+				&s2255_ctrl_ops,
+				V4L2_CID_JPEG_COMPRESSION_QUALITY,
+				0, 100, 1, S2255_DEF_JPEG_QUAL);
+		if (dev->dsp_fw_ver >= S2255_MIN_DSP_COLORFILTER &&
+		    (dev->pid != 0x2257 || channel->idx <= 1))
+			v4l2_ctrl_new_custom(&channel->hdl, &color_filter_ctrl, NULL);
+		if (channel->hdl.error) {
+			ret = channel->hdl.error;
+			v4l2_ctrl_handler_free(&channel->hdl);
+			dev_err(&dev->udev->dev, "couldn't register control\n");
+			break;
+		}
 		channel->vidq.dev = dev;
 		/* register 4 video devices */
 		channel->vdev = template;
+		channel->vdev.ctrl_handler = &channel->hdl;
 		channel->vdev.lock = &dev->lock;
 		channel->vdev.v4l2_dev = &dev->v4l2_dev;
+		set_bit(V4L2_FL_USE_FH_PRIO, &channel->vdev.flags);
 		video_set_drvdata(&channel->vdev, channel);
 		if (video_nr == -1)
 			ret = video_register_device(&channel->vdev,
@@ -2300,9 +2282,10 @@ static int s2255_board_init(struct s2255_dev *dev)
 		channel->mode = mode_def;
 		if (dev->pid == 0x2257 && j > 1)
 			channel->mode.color |= (1 << 16);
-		channel->jc.quality = S2255_DEF_JPEG_QUAL;
+		channel->jpegqual = S2255_DEF_JPEG_QUAL;
 		channel->width = LINE_SZ_4CIFS_NTSC;
 		channel->height = NUM_LINES_4CIFS_NTSC * 2;
+		channel->std = V4L2_STD_NTSC_M;
 		channel->fmt = &formats[0];
 		channel->mode.restart = 1;
 		channel->req_image_size = get_transfer_size(&mode_def);
@@ -2531,7 +2514,7 @@ static int s2255_probe(struct usb_interface *interface,
 		return -ENOMEM;
 	}
 	atomic_set(&dev->num_channels, 0);
-	dev->pid = id->idProduct;
+	dev->pid = le16_to_cpu(id->idProduct);
 	dev->fw_data = kzalloc(sizeof(struct s2255_fw), GFP_KERNEL);
 	if (!dev->fw_data)
 		goto errorFWDATA1;
@@ -2601,7 +2584,7 @@ static int s2255_probe(struct usb_interface *interface,
 		/* make sure firmware is the latest */
 		__le32 *pRel;
 		pRel = (__le32 *) &dev->fw_data->fw->data[fw_size - 4];
-		printk(KERN_INFO "s2255 dsp fw version %x\n", *pRel);
+		printk(KERN_INFO "s2255 dsp fw version %x\n", le32_to_cpu(*pRel));
 		dev->dsp_fw_ver = le32_to_cpu(*pRel);
 		if (dev->dsp_fw_ver < S2255_CUR_DSP_FWVER)
 			printk(KERN_INFO "s2255: f2255usb.bin out of date.\n");
diff --git a/drivers/media/usb/siano/smsusb.c b/drivers/media/usb/siano/smsusb.c
index de2c102..03761c6 100644
--- a/drivers/media/usb/siano/smsusb.c
+++ b/drivers/media/usb/siano/smsusb.c
@@ -35,16 +35,23 @@ module_param_named(debug, sms_dbg, int, 0644);
 MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))");
 
 #define USB1_BUFFER_SIZE		0x1000
-#define USB2_BUFFER_SIZE		0x4000
+#define USB2_BUFFER_SIZE		0x2000
 
 #define MAX_BUFFERS		50
 #define MAX_URBS		10
 
 struct smsusb_device_t;
 
+enum smsusb_state {
+	SMSUSB_DISCONNECTED,
+	SMSUSB_SUSPENDED,
+	SMSUSB_ACTIVE
+};
+
 struct smsusb_urb_t {
+	struct list_head entry;
 	struct smscore_buffer_t *cb;
-	struct smsusb_device_t	*dev;
+	struct smsusb_device_t *dev;
 
 	struct urb urb;
 };
@@ -57,11 +64,23 @@ struct smsusb_device_t {
 
 	int		response_alignment;
 	int		buffer_size;
+
+	unsigned char in_ep;
+	unsigned char out_ep;
+	enum smsusb_state state;
 };
 
 static int smsusb_submit_urb(struct smsusb_device_t *dev,
 			     struct smsusb_urb_t *surb);
 
+/**
+ * Completing URB's callback handler - top half (interrupt context)
+ * adds completing sms urb to the global surbs list and activtes the worker
+ * thread the surb
+ * IMPORTANT - blocking functions must not be called from here !!!
+
+ * @param urb pointer to a completing urb object
+ */
 static void smsusb_onresponse(struct urb *urb)
 {
 	struct smsusb_urb_t *surb = (struct smsusb_urb_t *) urb->context;
@@ -74,26 +93,26 @@ static void smsusb_onresponse(struct urb *urb)
 	}
 
 	if ((urb->actual_length > 0) && (urb->status == 0)) {
-		struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *)surb->cb->p;
+		struct sms_msg_hdr *phdr = (struct sms_msg_hdr *)surb->cb->p;
 
 		smsendian_handle_message_header(phdr);
-		if (urb->actual_length >= phdr->msgLength) {
-			surb->cb->size = phdr->msgLength;
+		if (urb->actual_length >= phdr->msg_length) {
+			surb->cb->size = phdr->msg_length;
 
 			if (dev->response_alignment &&
-			    (phdr->msgFlags & MSG_HDR_FLAG_SPLIT_MSG)) {
+			    (phdr->msg_flags & MSG_HDR_FLAG_SPLIT_MSG)) {
 
 				surb->cb->offset =
 					dev->response_alignment +
-					((phdr->msgFlags >> 8) & 3);
+					((phdr->msg_flags >> 8) & 3);
 
 				/* sanity check */
-				if (((int) phdr->msgLength +
+				if (((int) phdr->msg_length +
 				     surb->cb->offset) > urb->actual_length) {
 					sms_err("invalid response "
 						"msglen %d offset %d "
 						"size %d",
-						phdr->msgLength,
+						phdr->msg_length,
 						surb->cb->offset,
 						urb->actual_length);
 					goto exit_and_resubmit;
@@ -102,16 +121,22 @@ static void smsusb_onresponse(struct urb *urb)
 				/* move buffer pointer and
 				 * copy header to its new location */
 				memcpy((char *) phdr + surb->cb->offset,
-				       phdr, sizeof(struct SmsMsgHdr_ST));
+				       phdr, sizeof(struct sms_msg_hdr));
 			} else
 				surb->cb->offset = 0;
 
+			sms_debug("received %s(%d) size: %d",
+				  smscore_translate_msg(phdr->msg_type),
+				  phdr->msg_type, phdr->msg_length);
+
+			smsendian_handle_rx_message((struct sms_msg_data *) phdr);
+
 			smscore_onresponse(dev->coredev, surb->cb);
 			surb->cb = NULL;
 		} else {
 			sms_err("invalid response "
 				"msglen %d actual %d",
-				phdr->msgLength, urb->actual_length);
+				phdr->msg_length, urb->actual_length);
 		}
 	} else
 		sms_err("error, urb status %d, %d bytes",
@@ -136,7 +161,7 @@ static int smsusb_submit_urb(struct smsusb_device_t *dev,
 	usb_fill_bulk_urb(
 		&surb->urb,
 		dev->udev,
-		usb_rcvbulkpipe(dev->udev, 0x81),
+		usb_rcvbulkpipe(dev->udev, dev->in_ep),
 		surb->cb->p,
 		dev->buffer_size,
 		smsusb_onresponse,
@@ -181,9 +206,18 @@ static int smsusb_start_streaming(struct smsusb_device_t *dev)
 static int smsusb_sendrequest(void *context, void *buffer, size_t size)
 {
 	struct smsusb_device_t *dev = (struct smsusb_device_t *) context;
+	struct sms_msg_hdr *phdr = (struct sms_msg_hdr *) buffer;
 	int dummy;
 
-	smsendian_handle_message_header((struct SmsMsgHdr_ST *)buffer);
+	if (dev->state != SMSUSB_ACTIVE)
+		return -ENOENT;
+
+	sms_debug("sending %s(%d) size: %d",
+		  smscore_translate_msg(phdr->msg_type), phdr->msg_type,
+		  phdr->msg_length);
+
+	smsendian_handle_tx_message((struct sms_msg_data *) phdr);
+	smsendian_handle_message_header((struct sms_msg_hdr *)buffer);
 	return usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, 2),
 			    buffer, size, &dummy, 1000);
 }
@@ -276,15 +310,15 @@ static void smsusb1_detectmode(void *context, int *mode)
 
 static int smsusb1_setmode(void *context, int mode)
 {
-	struct SmsMsgHdr_ST Msg = { MSG_SW_RELOAD_REQ, 0, HIF_TASK,
-			     sizeof(struct SmsMsgHdr_ST), 0 };
+	struct sms_msg_hdr msg = { MSG_SW_RELOAD_REQ, 0, HIF_TASK,
+			     sizeof(struct sms_msg_hdr), 0 };
 
 	if (mode < DEVICE_MODE_DVBT || mode > DEVICE_MODE_DVBT_BDA) {
 		sms_err("invalid firmware id specified %d", mode);
 		return -EINVAL;
 	}
 
-	return smsusb_sendrequest(context, &Msg, sizeof(Msg));
+	return smsusb_sendrequest(context, &msg, sizeof(msg));
 }
 
 static void smsusb_term_device(struct usb_interface *intf)
@@ -292,13 +326,15 @@ static void smsusb_term_device(struct usb_interface *intf)
 	struct smsusb_device_t *dev = usb_get_intfdata(intf);
 
 	if (dev) {
+		dev->state = SMSUSB_DISCONNECTED;
+
 		smsusb_stop_streaming(dev);
 
 		/* unregister from smscore */
 		if (dev->coredev)
 			smscore_unregister_device(dev->coredev);
 
-		sms_info("device %p destroyed", dev);
+		sms_info("device 0x%p destroyed", dev);
 		kfree(dev);
 	}
 
@@ -321,6 +357,7 @@ static int smsusb_init_device(struct usb_interface *intf, int board_id)
 	memset(&params, 0, sizeof(params));
 	usb_set_intfdata(intf, dev);
 	dev->udev = interface_to_usbdev(intf);
+	dev->state = SMSUSB_DISCONNECTED;
 
 	params.device_type = sms_get_board(board_id)->type;
 
@@ -331,21 +368,29 @@ static int smsusb_init_device(struct usb_interface *intf, int board_id)
 		params.setmode_handler = smsusb1_setmode;
 		params.detectmode_handler = smsusb1_detectmode;
 		break;
-	default:
+	case SMS_UNKNOWN_TYPE:
 		sms_err("Unspecified sms device type!");
 		/* fall-thru */
-	case SMS_NOVA_A0:
-	case SMS_NOVA_B0:
-	case SMS_VEGA:
+	default:
 		dev->buffer_size = USB2_BUFFER_SIZE;
 		dev->response_alignment =
 		    le16_to_cpu(dev->udev->ep_in[1]->desc.wMaxPacketSize) -
-		    sizeof(struct SmsMsgHdr_ST);
+		    sizeof(struct sms_msg_hdr);
 
 		params.flags |= SMS_DEVICE_FAMILY2;
 		break;
 	}
 
+	for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) {
+		if (intf->cur_altsetting->endpoint[i].desc. bEndpointAddress & USB_DIR_IN)
+			dev->in_ep = intf->cur_altsetting->endpoint[i].desc.bEndpointAddress;
+		else
+			dev->out_ep = intf->cur_altsetting->endpoint[i].desc.bEndpointAddress;
+	}
+
+	sms_info("in_ep = %02x, out_ep = %02x",
+		dev->in_ep, dev->out_ep);
+
 	params.device = &dev->udev->dev;
 	params.buffer_size = dev->buffer_size;
 	params.num_buffers = MAX_BUFFERS;
@@ -363,6 +408,8 @@ static int smsusb_init_device(struct usb_interface *intf, int board_id)
 
 	smscore_set_board_id(dev->coredev, board_id);
 
+	dev->coredev->is_usb_device = true;
+
 	/* initialize urbs */
 	for (i = 0; i < MAX_URBS; i++) {
 		dev->surbs[i].dev = dev;
@@ -377,6 +424,8 @@ static int smsusb_init_device(struct usb_interface *intf, int board_id)
 		return rc;
 	}
 
+	dev->state = SMSUSB_ACTIVE;
+
 	rc = smscore_start_device(dev->coredev);
 	if (rc < 0) {
 		sms_err("smscore_start_device(...) failed");
@@ -384,7 +433,7 @@ static int smsusb_init_device(struct usb_interface *intf, int board_id)
 		return rc;
 	}
 
-	sms_info("device %p created", dev);
+	sms_info("device 0x%p created", dev);
 
 	return rc;
 }
@@ -396,12 +445,21 @@ static int smsusb_probe(struct usb_interface *intf,
 	char devpath[32];
 	int i, rc;
 
-	rc = usb_clear_halt(udev, usb_rcvbulkpipe(udev, 0x81));
-	rc = usb_clear_halt(udev, usb_rcvbulkpipe(udev, 0x02));
+	sms_info("interface number %d",
+		 intf->cur_altsetting->desc.bInterfaceNumber);
 
-	if (intf->num_altsetting > 0) {
-		rc = usb_set_interface(
-			udev, intf->cur_altsetting->desc.bInterfaceNumber, 0);
+	if (sms_get_board(id->driver_info)->intf_num !=
+	    intf->cur_altsetting->desc.bInterfaceNumber) {
+		sms_err("interface number is %d expecting %d",
+			sms_get_board(id->driver_info)->intf_num,
+			intf->cur_altsetting->desc.bInterfaceNumber);
+		return -ENODEV;
+	}
+
+	if (intf->num_altsetting > 1) {
+		rc = usb_set_interface(udev,
+				       intf->cur_altsetting->desc.bInterfaceNumber,
+				       0);
 		if (rc < 0) {
 			sms_err("usb_set_interface failed, rc %d", rc);
 			return rc;
@@ -410,19 +468,27 @@ static int smsusb_probe(struct usb_interface *intf,
 
 	sms_info("smsusb_probe %d",
 	       intf->cur_altsetting->desc.bInterfaceNumber);
-	for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++)
+	for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) {
 		sms_info("endpoint %d %02x %02x %d", i,
 		       intf->cur_altsetting->endpoint[i].desc.bEndpointAddress,
 		       intf->cur_altsetting->endpoint[i].desc.bmAttributes,
 		       intf->cur_altsetting->endpoint[i].desc.wMaxPacketSize);
-
+		if (intf->cur_altsetting->endpoint[i].desc.bEndpointAddress &
+		    USB_DIR_IN)
+			rc = usb_clear_halt(udev, usb_rcvbulkpipe(udev,
+				intf->cur_altsetting->endpoint[i].desc.bEndpointAddress));
+		else
+			rc = usb_clear_halt(udev, usb_sndbulkpipe(udev,
+				intf->cur_altsetting->endpoint[i].desc.bEndpointAddress));
+	}
 	if ((udev->actconfig->desc.bNumInterfaces == 2) &&
 	    (intf->cur_altsetting->desc.bInterfaceNumber == 0)) {
 		sms_err("rom interface 0 is not used");
 		return -ENODEV;
 	}
 
-	if (intf->cur_altsetting->desc.bInterfaceNumber == 1) {
+	if (id->driver_info == SMS1XXX_BOARD_SIANO_STELLAR_ROM) {
+		sms_info("stellar device was found.");
 		snprintf(devpath, sizeof(devpath), "usb\\%d-%s",
 			 udev->bus->busnum, udev->devpath);
 		sms_info("stellar device was found.");
@@ -445,7 +511,9 @@ static void smsusb_disconnect(struct usb_interface *intf)
 static int smsusb_suspend(struct usb_interface *intf, pm_message_t msg)
 {
 	struct smsusb_device_t *dev = usb_get_intfdata(intf);
-	printk(KERN_INFO "%s: Entering status %d.\n", __func__, msg.event);
+	printk(KERN_INFO "%s  Entering status %d.\n", __func__, msg.event);
+	dev->state = SMSUSB_SUSPENDED;
+	/*smscore_set_power_mode(dev, SMS_POWER_MODE_SUSPENDED);*/
 	smsusb_stop_streaming(dev);
 	return 0;
 }
@@ -456,9 +524,9 @@ static int smsusb_resume(struct usb_interface *intf)
 	struct smsusb_device_t *dev = usb_get_intfdata(intf);
 	struct usb_device *udev = interface_to_usbdev(intf);
 
-	printk(KERN_INFO "%s: Entering.\n", __func__);
-	usb_clear_halt(udev, usb_rcvbulkpipe(udev, 0x81));
-	usb_clear_halt(udev, usb_rcvbulkpipe(udev, 0x02));
+	printk(KERN_INFO "%s  Entering.\n", __func__);
+	usb_clear_halt(udev, usb_rcvbulkpipe(udev, dev->in_ep));
+	usb_clear_halt(udev, usb_sndbulkpipe(udev, dev->out_ep));
 
 	for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++)
 		printk(KERN_INFO "endpoint %d %02x %02x %d\n", i,
@@ -546,6 +614,26 @@ static const struct usb_device_id smsusb_id_table[] = {
 		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
 	{ USB_DEVICE(0x2040, 0xf5a0),
 		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
+	{ USB_DEVICE(0x187f, 0x0202),
+		.driver_info = SMS1XXX_BOARD_SIANO_NICE },
+	{ USB_DEVICE(0x187f, 0x0301),
+		.driver_info = SMS1XXX_BOARD_SIANO_VENICE },
+	{ USB_DEVICE(0x187f, 0x0302),
+		.driver_info = SMS1XXX_BOARD_SIANO_VENICE },
+	{ USB_DEVICE(0x187f, 0x0310),
+		.driver_info = SMS1XXX_BOARD_SIANO_MING },
+	{ USB_DEVICE(0x187f, 0x0500),
+		.driver_info = SMS1XXX_BOARD_SIANO_PELE },
+	{ USB_DEVICE(0x187f, 0x0600),
+		.driver_info = SMS1XXX_BOARD_SIANO_RIO },
+	{ USB_DEVICE(0x187f, 0x0700),
+		.driver_info = SMS1XXX_BOARD_SIANO_DENVER_2160 },
+	{ USB_DEVICE(0x187f, 0x0800),
+		.driver_info = SMS1XXX_BOARD_SIANO_DENVER_1530 },
+	{ USB_DEVICE(0x19D2, 0x0086),
+		.driver_info = SMS1XXX_BOARD_ZTE_DVB_DATA_CARD },
+	{ USB_DEVICE(0x19D2, 0x0078),
+		.driver_info = SMS1XXX_BOARD_ONDA_MDTV_DATA_CARD },
 	{ } /* Terminating entry */
 	};
 
diff --git a/drivers/media/usb/stk1160/stk1160-v4l.c b/drivers/media/usb/stk1160/stk1160-v4l.c
index 6694f9e..a59153d2 100644
--- a/drivers/media/usb/stk1160/stk1160-v4l.c
+++ b/drivers/media/usb/stk1160/stk1160-v4l.c
@@ -375,7 +375,7 @@ static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm)
 	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)
 {
 	struct stk1160 *dev = video_drvdata(file);
 	struct vb2_queue *q = &dev->vb_vidq;
@@ -388,7 +388,7 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm)
 		return -ENODEV;
 
 	/* We need to set this now, before we call stk1160_set_std */
-	dev->norm = *norm;
+	dev->norm = norm;
 
 	/* This is taken from saa7115 video decoder */
 	if (dev->norm & V4L2_STD_525_60) {
@@ -458,7 +458,7 @@ static int vidioc_g_chip_ident(struct file *file, void *priv,
 	       struct v4l2_dbg_chip_ident *chip)
 {
 	switch (chip->match.type) {
-	case V4L2_CHIP_MATCH_HOST:
+	case V4L2_CHIP_MATCH_BRIDGE:
 		chip->ident = V4L2_IDENT_NONE;
 		chip->revision = 0;
 		return 0;
@@ -476,9 +476,6 @@ static int vidioc_g_register(struct file *file, void *priv,
 	u8 val;
 
 	switch (reg->match.type) {
-	case V4L2_CHIP_MATCH_AC97:
-		/* TODO: Support me please :-( */
-		return -EINVAL;
 	case V4L2_CHIP_MATCH_I2C_DRIVER:
 		v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg);
 		return 0;
@@ -500,13 +497,11 @@ static int vidioc_g_register(struct file *file, void *priv,
 }
 
 static int vidioc_s_register(struct file *file, void *priv,
-			     struct v4l2_dbg_register *reg)
+			     const struct v4l2_dbg_register *reg)
 {
 	struct stk1160 *dev = video_drvdata(file);
 
 	switch (reg->match.type) {
-	case V4L2_CHIP_MATCH_AC97:
-		return -EINVAL;
 	case V4L2_CHIP_MATCH_I2C_DRIVER:
 		v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg);
 		return 0;
@@ -687,6 +682,7 @@ int stk1160_vb2_setup(struct stk1160 *dev)
 	q->buf_struct_size = sizeof(struct stk1160_buffer);
 	q->ops = &stk1160_video_qops;
 	q->mem_ops = &vb2_vmalloc_memops;
+	q->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
 
 	rc = vb2_queue_init(q);
 	if (rc < 0)
diff --git a/drivers/media/usb/stkwebcam/stk-webcam.c b/drivers/media/usb/stkwebcam/stk-webcam.c
index 4cbab08..c43c8d3 100644
--- a/drivers/media/usb/stkwebcam/stk-webcam.c
+++ b/drivers/media/usb/stkwebcam/stk-webcam.c
@@ -35,6 +35,7 @@
 #include <linux/videodev2.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-ioctl.h>
+#include <media/v4l2-event.h>
 
 #include "stk-webcam.h"
 
@@ -63,7 +64,39 @@ static struct usb_device_id stkwebcam_table[] = {
 };
 MODULE_DEVICE_TABLE(usb, stkwebcam_table);
 
-/* The stk webcam laptop module is mounted upside down in some laptops :( */
+/*
+ * The stk webcam laptop module is mounted upside down in some laptops :(
+ *
+ * Some background information (thanks to Hans de Goede for providing this):
+ *
+ * 1) Once upon a time the stkwebcam driver was written
+ *
+ * 2) The webcam in question was used mostly in Asus laptop models, including
+ * the laptop of the original author of the driver, and in these models, in
+ * typical Asus fashion (see the long long list for uvc cams inside v4l-utils),
+ * they mounted the webcam-module the wrong way up. So the hflip and vflip
+ * module options were given a default value of 1 (the correct value for
+ * upside down mounted models)
+ *
+ * 3) Years later I got a bug report from a user with a laptop with stkwebcam,
+ * where the module was actually mounted the right way up, and thus showed
+ * upside down under Linux. So now I was facing the choice of 2 options:
+ *
+ * a) Add a not-upside-down list to stkwebcam, which overrules the default.
+ *
+ * b) Do it like all the other drivers do, and make the default right for
+ *    cams mounted the proper way and add an upside-down model list, with
+ *    models where we need to flip-by-default.
+ *
+ * Despite knowing that going b) would cause a period of pain where we were
+ * building the table I opted to go for option b), since a) is just too ugly,
+ * and worse different from how every other driver does it leading to
+ * confusion in the long run. This change was made in kernel 3.6.
+ *
+ * So for any user report about upside-down images since kernel 3.6 ask them
+ * to provide the output of 'sudo dmidecode' so the laptop can be added in
+ * the table below.
+ */
 static const struct dmi_system_id stk_upside_down_dmi_table[] = {
 	{
 		.ident = "ASUS G1",
@@ -71,6 +104,12 @@ static const struct dmi_system_id stk_upside_down_dmi_table[] = {
 			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
 			DMI_MATCH(DMI_PRODUCT_NAME, "G1")
 		}
+	}, {
+		.ident = "ASUS F3JC",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "F3JC")
+		}
 	},
 	{}
 };
@@ -565,31 +604,31 @@ static void stk_free_buffers(struct stk_camera *dev)
 
 static int v4l_stk_open(struct file *fp)
 {
-	static int first_init = 1; /* webcam LED management */
-	struct stk_camera *dev;
-	struct video_device *vdev;
-
-	vdev = video_devdata(fp);
-	dev = vdev_to_camera(vdev);
+	struct stk_camera *dev = video_drvdata(fp);
+	int err;
 
 	if (dev == NULL || !is_present(dev))
 		return -ENXIO;
 
-	if (!first_init)
+	if (mutex_lock_interruptible(&dev->lock))
+		return -ERESTARTSYS;
+	if (!dev->first_init)
 		stk_camera_write_reg(dev, 0x0, 0x24);
 	else
-		first_init = 0;
-
-	fp->private_data = dev;
-	usb_autopm_get_interface(dev->interface);
+		dev->first_init = 0;
 
-	return 0;
+	err = v4l2_fh_open(fp);
+	if (!err)
+		usb_autopm_get_interface(dev->interface);
+	mutex_unlock(&dev->lock);
+	return err;
 }
 
 static int v4l_stk_release(struct file *fp)
 {
-	struct stk_camera *dev = fp->private_data;
+	struct stk_camera *dev = video_drvdata(fp);
 
+	mutex_lock(&dev->lock);
 	if (dev->owner == fp) {
 		stk_stop_stream(dev);
 		stk_free_buffers(dev);
@@ -600,22 +639,22 @@ static int v4l_stk_release(struct file *fp)
 
 	if (is_present(dev))
 		usb_autopm_put_interface(dev->interface);
-
-	return 0;
+	mutex_unlock(&dev->lock);
+	return v4l2_fh_release(fp);
 }
 
-static ssize_t v4l_stk_read(struct file *fp, char __user *buf,
+static ssize_t stk_read(struct file *fp, char __user *buf,
 		size_t count, loff_t *f_pos)
 {
 	int i;
 	int ret;
 	unsigned long flags;
 	struct stk_sio_buffer *sbuf;
-	struct stk_camera *dev = fp->private_data;
+	struct stk_camera *dev = video_drvdata(fp);
 
 	if (!is_present(dev))
 		return -EIO;
-	if (dev->owner && dev->owner != fp)
+	if (dev->owner && (!dev->reading || dev->owner != fp))
 		return -EBUSY;
 	dev->owner = fp;
 	if (!is_streaming(dev)) {
@@ -623,6 +662,7 @@ static ssize_t v4l_stk_read(struct file *fp, char __user *buf,
 			|| stk_allocate_buffers(dev, 3)
 			|| stk_start_stream(dev))
 			return -ENOMEM;
+		dev->reading = 1;
 		spin_lock_irqsave(&dev->spinlock, flags);
 		for (i = 0; i < dev->n_sbufs; i++) {
 			list_add_tail(&dev->sio_bufs[i].list, &dev->sio_avail);
@@ -665,9 +705,23 @@ static ssize_t v4l_stk_read(struct file *fp, char __user *buf,
 	return count;
 }
 
+static ssize_t v4l_stk_read(struct file *fp, char __user *buf,
+		size_t count, loff_t *f_pos)
+{
+	struct stk_camera *dev = video_drvdata(fp);
+	int ret;
+
+	if (mutex_lock_interruptible(&dev->lock))
+		return -ERESTARTSYS;
+	ret = stk_read(fp, buf, count, f_pos);
+	mutex_unlock(&dev->lock);
+	return ret;
+}
+
 static unsigned int v4l_stk_poll(struct file *fp, poll_table *wait)
 {
-	struct stk_camera *dev = fp->private_data;
+	struct stk_camera *dev = video_drvdata(fp);
+	unsigned res = v4l2_ctrl_poll(fp, wait);
 
 	poll_wait(fp, &dev->wait_frame, wait);
 
@@ -675,9 +729,9 @@ static unsigned int v4l_stk_poll(struct file *fp, poll_table *wait)
 		return POLLERR;
 
 	if (!list_empty(&dev->sio_full))
-		return POLLIN | POLLRDNORM;
+		return res | POLLIN | POLLRDNORM;
 
-	return 0;
+	return res;
 }
 
 
@@ -703,7 +757,7 @@ static int v4l_stk_mmap(struct file *fp, struct vm_area_struct *vma)
 	unsigned int i;
 	int ret;
 	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
-	struct stk_camera *dev = fp->private_data;
+	struct stk_camera *dev = video_drvdata(fp);
 	struct stk_sio_buffer *sbuf = NULL;
 
 	if (!(vma->vm_flags & VM_WRITE) || !(vma->vm_flags & VM_SHARED))
@@ -733,12 +787,15 @@ static int v4l_stk_mmap(struct file *fp, struct vm_area_struct *vma)
 static int stk_vidioc_querycap(struct file *filp,
 		void *priv, struct v4l2_capability *cap)
 {
+	struct stk_camera *dev = video_drvdata(filp);
+
 	strcpy(cap->driver, "stk");
 	strcpy(cap->card, "stk");
-	cap->version = DRIVER_VERSION_NUM;
+	usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
 
-	cap->capabilities = V4L2_CAP_VIDEO_CAPTURE
+	cap->device_caps = V4L2_CAP_VIDEO_CAPTURE
 		| V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
+	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
 	return 0;
 }
 
@@ -762,111 +819,28 @@ static int stk_vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
 
 static int stk_vidioc_s_input(struct file *filp, void *priv, unsigned int i)
 {
-	if (i != 0)
-		return -EINVAL;
-	else
-		return 0;
-}
-
-/* from vivi.c */
-static int stk_vidioc_s_std(struct file *filp, void *priv, v4l2_std_id *a)
-{
-	return 0;
-}
-
-/* List of all V4Lv2 controls supported by the driver */
-static struct v4l2_queryctrl stk_controls[] = {
-	{
-		.id      = V4L2_CID_BRIGHTNESS,
-		.type    = V4L2_CTRL_TYPE_INTEGER,
-		.name    = "Brightness",
-		.minimum = 0,
-		.maximum = 0xffff,
-		.step    = 0x0100,
-		.default_value = 0x6000,
-	},
-	{
-		.id      = V4L2_CID_HFLIP,
-		.type    = V4L2_CTRL_TYPE_BOOLEAN,
-		.name    = "Horizontal Flip",
-		.minimum = 0,
-		.maximum = 1,
-		.step    = 1,
-		.default_value = 1,
-	},
-	{
-		.id      = V4L2_CID_VFLIP,
-		.type    = V4L2_CTRL_TYPE_BOOLEAN,
-		.name    = "Vertical Flip",
-		.minimum = 0,
-		.maximum = 1,
-		.step    = 1,
-		.default_value = 1,
-	},
-};
-
-static int stk_vidioc_queryctrl(struct file *filp,
-		void *priv, struct v4l2_queryctrl *c)
-{
-	int i;
-	int nbr;
-	nbr = ARRAY_SIZE(stk_controls);
-
-	for (i = 0; i < nbr; i++) {
-		if (stk_controls[i].id == c->id) {
-			memcpy(c, &stk_controls[i],
-				sizeof(struct v4l2_queryctrl));
-			return 0;
-		}
-	}
-	return -EINVAL;
+	return i ? -EINVAL : 0;
 }
 
-static int stk_vidioc_g_ctrl(struct file *filp,
-		void *priv, struct v4l2_control *c)
+static int stk_s_ctrl(struct v4l2_ctrl *ctrl)
 {
-	struct stk_camera *dev = priv;
-	switch (c->id) {
-	case V4L2_CID_BRIGHTNESS:
-		c->value = dev->vsettings.brightness;
-		break;
-	case V4L2_CID_HFLIP:
-		if (dmi_check_system(stk_upside_down_dmi_table))
-			c->value = !dev->vsettings.hflip;
-		else
-			c->value = dev->vsettings.hflip;
-		break;
-	case V4L2_CID_VFLIP:
-		if (dmi_check_system(stk_upside_down_dmi_table))
-			c->value = !dev->vsettings.vflip;
-		else
-			c->value = dev->vsettings.vflip;
-		break;
-	default:
-		return -EINVAL;
-	}
-	return 0;
-}
+	struct stk_camera *dev =
+		container_of(ctrl->handler, struct stk_camera, hdl);
 
-static int stk_vidioc_s_ctrl(struct file *filp,
-		void *priv, struct v4l2_control *c)
-{
-	struct stk_camera *dev = priv;
-	switch (c->id) {
+	switch (ctrl->id) {
 	case V4L2_CID_BRIGHTNESS:
-		dev->vsettings.brightness = c->value;
-		return stk_sensor_set_brightness(dev, c->value >> 8);
+		return stk_sensor_set_brightness(dev, ctrl->val);
 	case V4L2_CID_HFLIP:
 		if (dmi_check_system(stk_upside_down_dmi_table))
-			dev->vsettings.hflip = !c->value;
+			dev->vsettings.hflip = !ctrl->val;
 		else
-			dev->vsettings.hflip = c->value;
+			dev->vsettings.hflip = ctrl->val;
 		return 0;
 	case V4L2_CID_VFLIP:
 		if (dmi_check_system(stk_upside_down_dmi_table))
-			dev->vsettings.vflip = !c->value;
+			dev->vsettings.vflip = !ctrl->val;
 		else
-			dev->vsettings.vflip = c->value;
+			dev->vsettings.vflip = ctrl->val;
 		return 0;
 	default:
 		return -EINVAL;
@@ -921,7 +895,7 @@ static int stk_vidioc_g_fmt_vid_cap(struct file *filp,
 		void *priv, struct v4l2_format *f)
 {
 	struct v4l2_pix_format *pix_format = &f->fmt.pix;
-	struct stk_camera *dev = priv;
+	struct stk_camera *dev = video_drvdata(filp);
 	int i;
 
 	for (i = 0; i < ARRAY_SIZE(stk_sizes) &&
@@ -942,11 +916,12 @@ static int stk_vidioc_g_fmt_vid_cap(struct file *filp,
 		pix_format->bytesperline = 2 * pix_format->width;
 	pix_format->sizeimage = pix_format->bytesperline
 				* pix_format->height;
+	pix_format->priv = 0;
 	return 0;
 }
 
-static int stk_vidioc_try_fmt_vid_cap(struct file *filp,
-		void *priv, struct v4l2_format *fmtd)
+static int stk_try_fmt_vid_cap(struct file *filp,
+		struct v4l2_format *fmtd, int *idx)
 {
 	int i;
 	switch (fmtd->fmt.pix.pixelformat) {
@@ -968,11 +943,13 @@ static int stk_vidioc_try_fmt_vid_cap(struct file *filp,
 			< abs(fmtd->fmt.pix.width - stk_sizes[i].w))) {
 		fmtd->fmt.pix.height = stk_sizes[i-1].h;
 		fmtd->fmt.pix.width = stk_sizes[i-1].w;
-		fmtd->fmt.pix.priv = i - 1;
+		if (idx)
+			*idx = i - 1;
 	} else {
 		fmtd->fmt.pix.height = stk_sizes[i].h;
 		fmtd->fmt.pix.width = stk_sizes[i].w;
-		fmtd->fmt.pix.priv = i;
+		if (idx)
+			*idx = i;
 	}
 
 	fmtd->fmt.pix.field = V4L2_FIELD_NONE;
@@ -983,9 +960,16 @@ static int stk_vidioc_try_fmt_vid_cap(struct file *filp,
 		fmtd->fmt.pix.bytesperline = 2 * fmtd->fmt.pix.width;
 	fmtd->fmt.pix.sizeimage = fmtd->fmt.pix.bytesperline
 		* fmtd->fmt.pix.height;
+	fmtd->fmt.pix.priv = 0;
 	return 0;
 }
 
+static int stk_vidioc_try_fmt_vid_cap(struct file *filp,
+		void *priv, struct v4l2_format *fmtd)
+{
+	return stk_try_fmt_vid_cap(filp, fmtd, NULL);
+}
+
 static int stk_setup_format(struct stk_camera *dev)
 {
 	int i = 0;
@@ -1026,7 +1010,8 @@ static int stk_vidioc_s_fmt_vid_cap(struct file *filp,
 		void *priv, struct v4l2_format *fmtd)
 {
 	int ret;
-	struct stk_camera *dev = priv;
+	int idx;
+	struct stk_camera *dev = video_drvdata(filp);
 
 	if (dev == NULL)
 		return -ENODEV;
@@ -1034,17 +1019,16 @@ static int stk_vidioc_s_fmt_vid_cap(struct file *filp,
 		return -ENODEV;
 	if (is_streaming(dev))
 		return -EBUSY;
-	if (dev->owner && dev->owner != filp)
+	if (dev->owner)
 		return -EBUSY;
-	ret = stk_vidioc_try_fmt_vid_cap(filp, priv, fmtd);
+	ret = stk_try_fmt_vid_cap(filp, fmtd, &idx);
 	if (ret)
 		return ret;
-	dev->owner = filp;
 
 	dev->vsettings.palette = fmtd->fmt.pix.pixelformat;
 	stk_free_buffers(dev);
 	dev->frame_size = fmtd->fmt.pix.sizeimage;
-	dev->vsettings.mode = stk_sizes[fmtd->fmt.pix.priv].m;
+	dev->vsettings.mode = stk_sizes[idx].m;
 
 	stk_initialise(dev);
 	return stk_setup_format(dev);
@@ -1053,7 +1037,7 @@ static int stk_vidioc_s_fmt_vid_cap(struct file *filp,
 static int stk_vidioc_reqbufs(struct file *filp,
 		void *priv, struct v4l2_requestbuffers *rb)
 {
-	struct stk_camera *dev = priv;
+	struct stk_camera *dev = video_drvdata(filp);
 
 	if (dev == NULL)
 		return -ENODEV;
@@ -1062,6 +1046,13 @@ static int stk_vidioc_reqbufs(struct file *filp,
 	if (is_streaming(dev)
 		|| (dev->owner && dev->owner != filp))
 		return -EBUSY;
+	stk_free_buffers(dev);
+	if (rb->count == 0) {
+		stk_camera_write_reg(dev, 0x0, 0x49); /* turn off the LED */
+		unset_initialised(dev);
+		dev->owner = NULL;
+		return 0;
+	}
 	dev->owner = filp;
 
 	/*FIXME If they ask for zero, we must stop streaming and free */
@@ -1079,7 +1070,7 @@ static int stk_vidioc_reqbufs(struct file *filp,
 static int stk_vidioc_querybuf(struct file *filp,
 		void *priv, struct v4l2_buffer *buf)
 {
-	struct stk_camera *dev = priv;
+	struct stk_camera *dev = video_drvdata(filp);
 	struct stk_sio_buffer *sbuf;
 
 	if (buf->index >= dev->n_sbufs)
@@ -1092,7 +1083,7 @@ static int stk_vidioc_querybuf(struct file *filp,
 static int stk_vidioc_qbuf(struct file *filp,
 		void *priv, struct v4l2_buffer *buf)
 {
-	struct stk_camera *dev = priv;
+	struct stk_camera *dev = video_drvdata(filp);
 	struct stk_sio_buffer *sbuf;
 	unsigned long flags;
 
@@ -1116,7 +1107,7 @@ static int stk_vidioc_qbuf(struct file *filp,
 static int stk_vidioc_dqbuf(struct file *filp,
 		void *priv, struct v4l2_buffer *buf)
 {
-	struct stk_camera *dev = priv;
+	struct stk_camera *dev = video_drvdata(filp);
 	struct stk_sio_buffer *sbuf;
 	unsigned long flags;
 	int ret;
@@ -1149,7 +1140,7 @@ static int stk_vidioc_dqbuf(struct file *filp,
 static int stk_vidioc_streamon(struct file *filp,
 		void *priv, enum v4l2_buf_type type)
 {
-	struct stk_camera *dev = priv;
+	struct stk_camera *dev = video_drvdata(filp);
 	if (is_streaming(dev))
 		return 0;
 	if (dev->sio_bufs == NULL)
@@ -1161,7 +1152,7 @@ static int stk_vidioc_streamon(struct file *filp,
 static int stk_vidioc_streamoff(struct file *filp,
 		void *priv, enum v4l2_buf_type type)
 {
-	struct stk_camera *dev = priv;
+	struct stk_camera *dev = video_drvdata(filp);
 	unsigned long flags;
 	int i;
 	stk_stop_stream(dev);
@@ -1206,6 +1197,10 @@ static int stk_vidioc_enum_framesizes(struct file *filp,
 	}
 }
 
+static const struct v4l2_ctrl_ops stk_ctrl_ops = {
+	.s_ctrl = stk_s_ctrl,
+};
+
 static struct v4l2_file_operations v4l_stk_fops = {
 	.owner = THIS_MODULE,
 	.open = v4l_stk_open,
@@ -1213,7 +1208,7 @@ static struct v4l2_file_operations v4l_stk_fops = {
 	.read = v4l_stk_read,
 	.poll = v4l_stk_poll,
 	.mmap = v4l_stk_mmap,
-	.ioctl = video_ioctl2,
+	.unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops v4l_stk_ioctl_ops = {
@@ -1225,18 +1220,17 @@ static const struct v4l2_ioctl_ops v4l_stk_ioctl_ops = {
 	.vidioc_enum_input = stk_vidioc_enum_input,
 	.vidioc_s_input = stk_vidioc_s_input,
 	.vidioc_g_input = stk_vidioc_g_input,
-	.vidioc_s_std = stk_vidioc_s_std,
 	.vidioc_reqbufs = stk_vidioc_reqbufs,
 	.vidioc_querybuf = stk_vidioc_querybuf,
 	.vidioc_qbuf = stk_vidioc_qbuf,
 	.vidioc_dqbuf = stk_vidioc_dqbuf,
 	.vidioc_streamon = stk_vidioc_streamon,
 	.vidioc_streamoff = stk_vidioc_streamoff,
-	.vidioc_queryctrl = stk_vidioc_queryctrl,
-	.vidioc_g_ctrl = stk_vidioc_g_ctrl,
-	.vidioc_s_ctrl = stk_vidioc_s_ctrl,
 	.vidioc_g_parm = stk_vidioc_g_parm,
 	.vidioc_enum_framesizes = stk_vidioc_enum_framesizes,
+	.vidioc_log_status = v4l2_ctrl_log_status,
+	.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
+	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
 };
 
 static void stk_v4l_dev_release(struct video_device *vd)
@@ -1251,8 +1245,6 @@ static void stk_v4l_dev_release(struct video_device *vd)
 
 static struct video_device stk_v4l_data = {
 	.name = "stkwebcam",
-	.tvnorms = V4L2_STD_UNKNOWN,
-	.current_norm = V4L2_STD_UNKNOWN,
 	.fops = &v4l_stk_fops,
 	.ioctl_ops = &v4l_stk_ioctl_ops,
 	.release = stk_v4l_dev_release,
@@ -1264,8 +1256,11 @@ static int stk_register_video_device(struct stk_camera *dev)
 	int err;
 
 	dev->vdev = stk_v4l_data;
+	dev->vdev.lock = &dev->lock;
 	dev->vdev.debug = debug;
-	dev->vdev.parent = &dev->interface->dev;
+	dev->vdev.v4l2_dev = &dev->v4l2_dev;
+	set_bit(V4L2_FL_USE_FH_PRIO, &dev->vdev.flags);
+	video_set_drvdata(&dev->vdev, dev);
 	err = video_register_device(&dev->vdev, VFL_TYPE_GRABBER, -1);
 	if (err)
 		STK_ERROR("v4l registration failed\n");
@@ -1281,8 +1276,9 @@ static int stk_register_video_device(struct stk_camera *dev)
 static int stk_camera_probe(struct usb_interface *interface,
 		const struct usb_device_id *id)
 {
-	int i;
+	struct v4l2_ctrl_handler *hdl;
 	int err = 0;
+	int i;
 
 	struct stk_camera *dev = NULL;
 	struct usb_device *udev = interface_to_usbdev(interface);
@@ -1294,9 +1290,31 @@ static int stk_camera_probe(struct usb_interface *interface,
 		STK_ERROR("Out of memory !\n");
 		return -ENOMEM;
 	}
+	err = v4l2_device_register(&interface->dev, &dev->v4l2_dev);
+	if (err < 0) {
+		dev_err(&udev->dev, "couldn't register v4l2_device\n");
+		kfree(dev);
+		return err;
+	}
+	hdl = &dev->hdl;
+	v4l2_ctrl_handler_init(hdl, 3);
+	v4l2_ctrl_new_std(hdl, &stk_ctrl_ops,
+			  V4L2_CID_BRIGHTNESS, 0, 0xff, 0x1, 0x60);
+	v4l2_ctrl_new_std(hdl, &stk_ctrl_ops,
+			  V4L2_CID_HFLIP, 0, 1, 1, 1);
+	v4l2_ctrl_new_std(hdl, &stk_ctrl_ops,
+			  V4L2_CID_VFLIP, 0, 1, 1, 1);
+	if (hdl->error) {
+		err = hdl->error;
+		dev_err(&udev->dev, "couldn't register control\n");
+		goto error;
+	}
+	dev->v4l2_dev.ctrl_handler = hdl;
 
 	spin_lock_init(&dev->spinlock);
+	mutex_init(&dev->lock);
 	init_waitqueue_head(&dev->wait_frame);
+	dev->first_init = 1; /* webcam LED management */
 
 	dev->udev = udev;
 	dev->interface = interface;
@@ -1337,7 +1355,6 @@ static int stk_camera_probe(struct usb_interface *interface,
 		err = -ENODEV;
 		goto error;
 	}
-	dev->vsettings.brightness = 0x7fff;
 	dev->vsettings.palette = V4L2_PIX_FMT_RGB565;
 	dev->vsettings.mode = MODE_VGA;
 	dev->frame_size = 640 * 480 * 2;
@@ -1354,6 +1371,8 @@ static int stk_camera_probe(struct usb_interface *interface,
 	return 0;
 
 error:
+	v4l2_ctrl_handler_free(hdl);
+	v4l2_device_unregister(&dev->v4l2_dev);
 	kfree(dev);
 	return err;
 }
@@ -1371,6 +1390,8 @@ static void stk_camera_disconnect(struct usb_interface *interface)
 		 video_device_node_name(&dev->vdev));
 
 	video_unregister_device(&dev->vdev);
+	v4l2_ctrl_handler_free(&dev->hdl);
+	v4l2_device_unregister(&dev->v4l2_dev);
 }
 
 #ifdef CONFIG_PM
diff --git a/drivers/media/usb/stkwebcam/stk-webcam.h b/drivers/media/usb/stkwebcam/stk-webcam.h
index 9f67366..9bbfa3d 100644
--- a/drivers/media/usb/stkwebcam/stk-webcam.h
+++ b/drivers/media/usb/stkwebcam/stk-webcam.h
@@ -23,6 +23,8 @@
 #define STKWEBCAM_H
 
 #include <linux/usb.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
 #include <media/v4l2-common.h>
 
 #define DRIVER_VERSION		"v0.0.1"
@@ -59,7 +61,6 @@ enum stk_mode {MODE_VGA, MODE_SXGA, MODE_CIF, MODE_QVGA, MODE_QCIF};
 
 struct stk_video {
 	enum stk_mode mode;
-	int brightness;
 	__u32 palette;
 	int hflip;
 	int vflip;
@@ -91,11 +92,15 @@ struct regval {
 };
 
 struct stk_camera {
+	struct v4l2_device v4l2_dev;
+	struct v4l2_ctrl_handler hdl;
 	struct video_device vdev;
 	struct usb_device *udev;
 	struct usb_interface *interface;
 	int webcam_model;
 	struct file *owner;
+	struct mutex lock;
+	int first_init;
 
 	u8 isoc_ep;
 
@@ -113,6 +118,7 @@ struct stk_camera {
 
 	int frame_size;
 	/* Streaming buffers */
+	int reading;
 	unsigned int n_sbufs;
 	struct stk_sio_buffer *sio_bufs;
 	struct list_head sio_avail;
diff --git a/drivers/media/usb/tlg2300/pd-common.h b/drivers/media/usb/tlg2300/pd-common.h
index 5dd73b7..9e23ad32 100644
--- a/drivers/media/usb/tlg2300/pd-common.h
+++ b/drivers/media/usb/tlg2300/pd-common.h
@@ -10,6 +10,7 @@
 #include <linux/poll.h>
 #include <media/videobuf-vmalloc.h>
 #include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
 
 #include "dvb_frontend.h"
 #include "dvbdev.h"
@@ -25,7 +26,6 @@
 #define POSEIDON_STATE_ANALOG		(0x0001)
 #define POSEIDON_STATE_FM		(0x0002)
 #define POSEIDON_STATE_DVBT		(0x0004)
-#define POSEIDON_STATE_VBI		(0x0008)
 #define POSEIDON_STATE_DISCONNECT	(0x0080)
 
 #define PM_SUSPEND_DELAY	3
@@ -35,11 +35,11 @@
 #define V4L_PAL_VBI_FRAMESIZE	(V4L_PAL_VBI_LINES * 1440 * 2)
 #define V4L_NTSC_VBI_FRAMESIZE	(V4L_NTSC_VBI_LINES * 1440 * 2)
 
-#define TUNER_FREQ_MIN		(45000000)
-#define TUNER_FREQ_MAX		(862000000)
+#define TUNER_FREQ_MIN		(45000000U)
+#define TUNER_FREQ_MAX		(862000000U)
 
 struct vbi_data {
-	struct video_device	*v_dev;
+	struct video_device	v_dev;
 	struct video_data	*video;
 	struct front_face	*front;
 
@@ -62,7 +62,8 @@ struct running_context {
 
 struct video_data {
 	/* v4l2 video device */
-	struct video_device	*v_dev;
+	struct video_device	v_dev;
+	struct v4l2_ctrl_handler ctrl_handler;
 
 	/* the working context */
 	struct running_context	context;
@@ -115,10 +116,10 @@ struct poseidon_audio {
 
 struct radio_data {
 	__u32		fm_freq;
-	int		users;
 	unsigned int	is_radio_streaming;
 	int		pre_emphasis;
-	struct video_device *fm_dev;
+	struct video_device fm_dev;
+	struct v4l2_ctrl_handler ctrl_handler;
 };
 
 #define DVB_SBUF_NUM		4
@@ -233,7 +234,6 @@ void dvb_stop_streaming(struct pd_dvb_adapter *);
 /* FM */
 int poseidon_fm_init(struct poseidon *);
 int poseidon_fm_exit(struct poseidon *);
-struct video_device *vdev_init(struct poseidon *, struct video_device *);
 
 /* vendor command ops */
 int send_set_req(struct poseidon*, u8, s32, s32*);
@@ -249,7 +249,6 @@ void free_all_urb_generic(struct urb **urb_array, int num);
 
 /* misc */
 void poseidon_delete(struct kref *kref);
-void destroy_video_device(struct video_device **v_dev);
 extern int debug_mode;
 void set_debug_mode(struct video_device *vfd, int debug_mode);
 
@@ -269,13 +268,4 @@ void set_debug_mode(struct video_device *vfd, int debug_mode);
 				log();\
 		} while (0)
 
-#define logs(f) do { \
-			if ((debug_mode & 0x4) && \
-				(f)->type == V4L2_BUF_TYPE_VBI_CAPTURE) \
-					log("type : VBI");\
-								\
-			if ((debug_mode & 0x8) && \
-				(f)->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) \
-					log("type : VIDEO");\
-		} while (0)
 #endif
diff --git a/drivers/media/usb/tlg2300/pd-main.c b/drivers/media/usb/tlg2300/pd-main.c
index 7b1f6eb..e07e4c6 100644
--- a/drivers/media/usb/tlg2300/pd-main.c
+++ b/drivers/media/usb/tlg2300/pd-main.c
@@ -55,7 +55,6 @@ MODULE_PARM_DESC(debug_mode, "0 = disable, 1 = enable, 2 = verbose");
 
 #define TLG2300_FIRMWARE "tlg2300_firmware.bin"
 static const char *firmware_name = TLG2300_FIRMWARE;
-static struct usb_driver poseidon_driver;
 static LIST_HEAD(pd_device_list);
 
 /*
@@ -268,7 +267,8 @@ static inline void set_map_flags(struct poseidon *pd, struct usb_device *udev)
 static inline int get_autopm_ref(struct poseidon *pd)
 {
 	return  pd->video_data.users + pd->vbi_data.users + pd->audio.users
-		+ atomic_read(&pd->dvb_data.users) + pd->radio_data.users;
+		+ atomic_read(&pd->dvb_data.users) +
+		!list_empty(&pd->radio_data.fm_dev.fh_list);
 }
 
 /* fixup something for poseidon */
@@ -316,7 +316,7 @@ static int poseidon_suspend(struct usb_interface *intf, pm_message_t msg)
 		if (get_pm_count(pd) <= 0 && !in_hibernation(pd)) {
 			pd->msg.event = PM_EVENT_AUTO_SUSPEND;
 			pd->pm_resume = NULL; /*  a good guard */
-			printk(KERN_DEBUG "\n\t+ TLG2300 auto suspend +\n\n");
+			printk(KERN_DEBUG "TLG2300 auto suspend\n");
 		}
 		return 0;
 	}
@@ -331,7 +331,7 @@ static int poseidon_resume(struct usb_interface *intf)
 
 	if (!pd)
 		return 0;
-	printk(KERN_DEBUG "\n\t ++ TLG2300 resume ++\n\n");
+	printk(KERN_DEBUG "TLG2300 resume\n");
 
 	if (!is_working(pd)) {
 		if (PM_EVENT_AUTO_SUSPEND == pd->msg.event)
@@ -431,15 +431,11 @@ static int poseidon_probe(struct usb_interface *interface,
 	usb_set_intfdata(interface, pd);
 
 	if (new_one) {
-		struct device *dev = &interface->dev;
-
 		logpm(pd);
 		mutex_init(&pd->lock);
 
 		/* register v4l2 device */
-		snprintf(pd->v4l2_dev.name, sizeof(pd->v4l2_dev.name), "%s %s",
-			dev->driver->name, dev_name(dev));
-		ret = v4l2_device_register(NULL, &pd->v4l2_dev);
+		ret = v4l2_device_register(&interface->dev, &pd->v4l2_dev);
 
 		/* register devices in directory /dev */
 		ret = pd_video_init(pd);
@@ -530,7 +526,7 @@ module_init(poseidon_init);
 module_exit(poseidon_exit);
 
 MODULE_AUTHOR("Telegent Systems");
-MODULE_DESCRIPTION("For tlg2300-based USB device ");
+MODULE_DESCRIPTION("For tlg2300-based USB device");
 MODULE_LICENSE("GPL");
 MODULE_VERSION("0.0.2");
 MODULE_FIRMWARE(TLG2300_FIRMWARE);
diff --git a/drivers/media/usb/tlg2300/pd-radio.c b/drivers/media/usb/tlg2300/pd-radio.c
index 25eeb16..ea6070b 100644
--- a/drivers/media/usb/tlg2300/pd-radio.c
+++ b/drivers/media/usb/tlg2300/pd-radio.c
@@ -9,6 +9,8 @@
 #include <linux/mm.h>
 #include <linux/mutex.h>
 #include <media/v4l2-ioctl.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-fh.h>
 #include <linux/sched.h>
 
 #include "pd-common.h"
@@ -18,8 +20,8 @@ static int set_frequency(struct poseidon *p, __u32 frequency);
 static int poseidon_fm_close(struct file *filp);
 static int poseidon_fm_open(struct file *filp);
 
-#define TUNER_FREQ_MIN_FM 76000000
-#define TUNER_FREQ_MAX_FM 108000000
+#define TUNER_FREQ_MIN_FM 76000000U
+#define TUNER_FREQ_MAX_FM 108000000U
 
 #define MAX_PREEMPHASIS (V4L2_PREEMPHASIS_75_uS + 1)
 static int preemphasis[MAX_PREEMPHASIS] = {
@@ -77,13 +79,9 @@ static int pm_fm_resume(struct poseidon *p)
 
 static int poseidon_fm_open(struct file *filp)
 {
-	struct video_device *vfd = video_devdata(filp);
-	struct poseidon *p = video_get_drvdata(vfd);
+	struct poseidon *p = video_drvdata(filp);
 	int ret = 0;
 
-	if (!p)
-		return -1;
-
 	mutex_lock(&p->lock);
 	if (p->state & POSEIDON_STATE_DISCONNECT) {
 		ret = -ENODEV;
@@ -94,9 +92,14 @@ static int poseidon_fm_open(struct file *filp)
 		ret = -EBUSY;
 		goto out;
 	}
+	ret = v4l2_fh_open(filp);
+	if (ret)
+		goto out;
 
 	usb_autopm_get_interface(p->interface);
 	if (0 == p->state) {
+		struct video_device *vfd = &p->radio_data.fm_dev;
+
 		/* default pre-emphasis */
 		if (p->radio_data.pre_emphasis == 0)
 			p->radio_data.pre_emphasis = TLG_TUNE_ASTD_FM_EUR;
@@ -109,9 +112,7 @@ static int poseidon_fm_open(struct file *filp)
 		}
 		p->state |= POSEIDON_STATE_FM;
 	}
-	p->radio_data.users++;
 	kref_get(&p->kref);
-	filp->private_data = p;
 out:
 	mutex_unlock(&p->lock);
 	return ret;
@@ -119,13 +120,12 @@ out:
 
 static int poseidon_fm_close(struct file *filp)
 {
-	struct poseidon *p = filp->private_data;
+	struct poseidon *p = video_drvdata(filp);
 	struct radio_data *fm = &p->radio_data;
 	uint32_t status;
 
 	mutex_lock(&p->lock);
-	fm->users--;
-	if (0 == fm->users)
+	if (v4l2_fh_is_singular_file(filp))
 		p->state &= ~POSEIDON_STATE_FM;
 
 	if (fm->is_radio_streaming && filp == p->file_for_stream) {
@@ -136,19 +136,23 @@ static int poseidon_fm_close(struct file *filp)
 	mutex_unlock(&p->lock);
 
 	kref_put(&p->kref, poseidon_delete);
-	filp->private_data = NULL;
-	return 0;
+	return v4l2_fh_release(filp);
 }
 
 static int vidioc_querycap(struct file *file, void *priv,
 			struct v4l2_capability *v)
 {
-	struct poseidon *p = file->private_data;
+	struct poseidon *p = video_drvdata(file);
 
 	strlcpy(v->driver, "tele-radio", sizeof(v->driver));
 	strlcpy(v->card, "Telegent Poseidon", sizeof(v->card));
 	usb_make_path(p->udev, v->bus_info, sizeof(v->bus_info));
-	v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
+	v->device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
+	/* Report all capabilities of the USB device */
+	v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS |
+			V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VBI_CAPTURE |
+			V4L2_CAP_AUDIO | V4L2_CAP_STREAMING |
+			V4L2_CAP_READWRITE;
 	return 0;
 }
 
@@ -156,27 +160,29 @@ static const struct v4l2_file_operations poseidon_fm_fops = {
 	.owner         = THIS_MODULE,
 	.open          = poseidon_fm_open,
 	.release       = poseidon_fm_close,
-	.ioctl	       = video_ioctl2,
+	.poll		= v4l2_ctrl_poll,
+	.unlocked_ioctl = video_ioctl2,
 };
 
 static int tlg_fm_vidioc_g_tuner(struct file *file, void *priv,
 				 struct v4l2_tuner *vt)
 {
+	struct poseidon *p = video_drvdata(file);
 	struct tuner_fm_sig_stat_s fm_stat = {};
 	int ret, status, count = 5;
-	struct poseidon *p = file->private_data;
 
 	if (vt->index != 0)
 		return -EINVAL;
 
 	vt->type	= V4L2_TUNER_RADIO;
-	vt->capability	= V4L2_TUNER_CAP_STEREO;
-	vt->rangelow	= TUNER_FREQ_MIN_FM / 62500;
-	vt->rangehigh	= TUNER_FREQ_MAX_FM / 62500;
+	vt->capability	= V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LOW;
+	vt->rangelow	= TUNER_FREQ_MIN_FM * 2 / 125;
+	vt->rangehigh	= TUNER_FREQ_MAX_FM * 2 / 125;
 	vt->rxsubchans	= V4L2_TUNER_SUB_STEREO;
 	vt->audmode	= V4L2_TUNER_MODE_STEREO;
 	vt->signal	= 0;
 	vt->afc 	= 0;
+	strlcpy(vt->name, "Radio", sizeof(vt->name));
 
 	mutex_lock(&p->lock);
 	ret = send_get_req(p, TUNER_STATUS, TLG_MODE_FM_RADIO,
@@ -205,8 +211,10 @@ static int tlg_fm_vidioc_g_tuner(struct file *file, void *priv,
 static int fm_get_freq(struct file *file, void *priv,
 		       struct v4l2_frequency *argp)
 {
-	struct poseidon *p = file->private_data;
+	struct poseidon *p = video_drvdata(file);
 
+	if (argp->tuner)
+		return -EINVAL;
 	argp->frequency = p->radio_data.fm_freq;
 	return 0;
 }
@@ -221,11 +229,8 @@ static int set_frequency(struct poseidon *p, __u32 frequency)
 	ret = send_set_req(p, TUNER_AUD_ANA_STD,
 				p->radio_data.pre_emphasis, &status);
 
-	freq =  (frequency * 125) * 500 / 1000;/* kHZ */
-	if (freq < TUNER_FREQ_MIN_FM/1000 || freq > TUNER_FREQ_MAX_FM/1000) {
-		ret = -EINVAL;
-		goto error;
-	}
+	freq = (frequency * 125) / 2; /* Hz */
+	freq = clamp(freq, TUNER_FREQ_MIN_FM, TUNER_FREQ_MAX_FM);
 
 	ret = send_set_req(p, TUNE_FREQ_SELECT, freq, &status);
 	if (ret < 0)
@@ -240,18 +245,20 @@ static int set_frequency(struct poseidon *p, __u32 frequency)
 				TLG_TUNE_PLAY_SVC_START, &status);
 		p->radio_data.is_radio_streaming = 1;
 	}
-	p->radio_data.fm_freq = frequency;
+	p->radio_data.fm_freq = freq * 2 / 125;
 error:
 	mutex_unlock(&p->lock);
 	return ret;
 }
 
 static int fm_set_freq(struct file *file, void *priv,
-		       struct v4l2_frequency *argp)
+		       const struct v4l2_frequency *argp)
 {
-	struct poseidon *p = file->private_data;
+	struct poseidon *p = video_drvdata(file);
 
-	p->file_for_stream  = file;
+	if (argp->tuner)
+		return -EINVAL;
+	p->file_for_stream = file;
 #ifdef CONFIG_PM
 	p->pm_suspend = pm_fm_suspend;
 	p->pm_resume  = pm_fm_resume;
@@ -259,163 +266,75 @@ static int fm_set_freq(struct file *file, void *priv,
 	return set_frequency(p, argp->frequency);
 }
 
-static int tlg_fm_vidioc_g_ctrl(struct file *file, void *priv,
-		struct v4l2_control *arg)
-{
-	return 0;
-}
-
-static int tlg_fm_vidioc_g_exts_ctrl(struct file *file, void *fh,
-				struct v4l2_ext_controls *ctrls)
-{
-	struct poseidon *p = file->private_data;
-	int i;
-
-	if (ctrls->ctrl_class != V4L2_CTRL_CLASS_FM_TX)
-		return -EINVAL;
-
-	for (i = 0; i < ctrls->count; i++) {
-		struct v4l2_ext_control *ctrl = ctrls->controls + i;
-
-		if (ctrl->id != V4L2_CID_TUNE_PREEMPHASIS)
-			continue;
-
-		if (i < MAX_PREEMPHASIS)
-			ctrl->value = p->radio_data.pre_emphasis;
-	}
-	return 0;
-}
-
-static int tlg_fm_vidioc_s_exts_ctrl(struct file *file, void *fh,
-			struct v4l2_ext_controls *ctrls)
-{
-	int i;
-
-	if (ctrls->ctrl_class != V4L2_CTRL_CLASS_FM_TX)
-		return -EINVAL;
-
-	for (i = 0; i < ctrls->count; i++) {
-		struct v4l2_ext_control *ctrl = ctrls->controls + i;
-
-		if (ctrl->id != V4L2_CID_TUNE_PREEMPHASIS)
-			continue;
-
-		if (ctrl->value >= 0 && ctrl->value < MAX_PREEMPHASIS) {
-			struct poseidon *p = file->private_data;
-			int pre_emphasis = preemphasis[ctrl->value];
-			u32 status;
-
-			send_set_req(p, TUNER_AUD_ANA_STD,
-						pre_emphasis, &status);
-			p->radio_data.pre_emphasis = pre_emphasis;
-		}
-	}
-	return 0;
-}
-
-static int tlg_fm_vidioc_s_ctrl(struct file *file, void *priv,
-		struct v4l2_control *ctrl)
+static int tlg_fm_s_ctrl(struct v4l2_ctrl *ctrl)
 {
-	return 0;
-}
-
-static int tlg_fm_vidioc_queryctrl(struct file *file, void *priv,
-		struct v4l2_queryctrl *ctrl)
-{
-	if (!(ctrl->id & V4L2_CTRL_FLAG_NEXT_CTRL))
-		return -EINVAL;
+	struct poseidon *p = container_of(ctrl->handler, struct poseidon,
+						radio_data.ctrl_handler);
+	int pre_emphasis;
+	u32 status;
 
-	ctrl->id &= ~V4L2_CTRL_FLAG_NEXT_CTRL;
-	if (ctrl->id != V4L2_CID_TUNE_PREEMPHASIS) {
-		/* return the next supported control */
-		ctrl->id = V4L2_CID_TUNE_PREEMPHASIS;
-		v4l2_ctrl_query_fill(ctrl, V4L2_PREEMPHASIS_DISABLED,
-					V4L2_PREEMPHASIS_75_uS, 1,
-					V4L2_PREEMPHASIS_50_uS);
-		ctrl->flags = V4L2_CTRL_FLAG_UPDATE;
+	switch (ctrl->id) {
+	case V4L2_CID_TUNE_PREEMPHASIS:
+		pre_emphasis = preemphasis[ctrl->val];
+		send_set_req(p, TUNER_AUD_ANA_STD, pre_emphasis, &status);
+		p->radio_data.pre_emphasis = pre_emphasis;
 		return 0;
 	}
 	return -EINVAL;
 }
 
-static int tlg_fm_vidioc_querymenu(struct file *file, void *fh,
-				struct v4l2_querymenu *qmenu)
-{
-	return v4l2_ctrl_query_menu(qmenu, NULL, NULL);
-}
-
-static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *vt)
+static int vidioc_s_tuner(struct file *file, void *priv, const struct v4l2_tuner *vt)
 {
 	return vt->index > 0 ? -EINVAL : 0;
 }
-static int vidioc_s_audio(struct file *file, void *priv, const struct v4l2_audio *va)
-{
-	return (va->index != 0) ? -EINVAL : 0;
-}
-
-static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
-{
-	a->index    = 0;
-	a->mode    = 0;
-	a->capability = V4L2_AUDCAP_STEREO;
-	strcpy(a->name, "Radio");
-	return 0;
-}
-
-static int vidioc_s_input(struct file *filp, void *priv, u32 i)
-{
-	return (i != 0) ? -EINVAL : 0;
-}
 
-static int vidioc_g_input(struct file *filp, void *priv, u32 *i)
-{
-	return (*i != 0) ? -EINVAL : 0;
-}
+static const struct v4l2_ctrl_ops tlg_fm_ctrl_ops = {
+	.s_ctrl = tlg_fm_s_ctrl,
+};
 
 static const struct v4l2_ioctl_ops poseidon_fm_ioctl_ops = {
 	.vidioc_querycap    = vidioc_querycap,
-	.vidioc_g_audio     = vidioc_g_audio,
-	.vidioc_s_audio     = vidioc_s_audio,
-	.vidioc_g_input     = vidioc_g_input,
-	.vidioc_s_input     = vidioc_s_input,
-	.vidioc_queryctrl   = tlg_fm_vidioc_queryctrl,
-	.vidioc_querymenu   = tlg_fm_vidioc_querymenu,
-	.vidioc_g_ctrl      = tlg_fm_vidioc_g_ctrl,
-	.vidioc_s_ctrl      = tlg_fm_vidioc_s_ctrl,
-	.vidioc_s_ext_ctrls = tlg_fm_vidioc_s_exts_ctrl,
-	.vidioc_g_ext_ctrls = tlg_fm_vidioc_g_exts_ctrl,
 	.vidioc_s_tuner     = vidioc_s_tuner,
 	.vidioc_g_tuner     = tlg_fm_vidioc_g_tuner,
 	.vidioc_g_frequency = fm_get_freq,
 	.vidioc_s_frequency = fm_set_freq,
+	.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
+	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
 };
 
 static struct video_device poseidon_fm_template = {
 	.name       = "Telegent-Radio",
 	.fops       = &poseidon_fm_fops,
 	.minor      = -1,
-	.release    = video_device_release,
+	.release    = video_device_release_empty,
 	.ioctl_ops  = &poseidon_fm_ioctl_ops,
 };
 
 int poseidon_fm_init(struct poseidon *p)
 {
-	struct video_device *fm_dev;
-
-	fm_dev = vdev_init(p, &poseidon_fm_template);
-	if (fm_dev == NULL)
-		return -1;
-
-	if (video_register_device(fm_dev, VFL_TYPE_RADIO, -1) < 0) {
-		video_device_release(fm_dev);
-		return -1;
+	struct video_device *vfd = &p->radio_data.fm_dev;
+	struct v4l2_ctrl_handler *hdl = &p->radio_data.ctrl_handler;
+
+	*vfd = poseidon_fm_template;
+
+	set_frequency(p, TUNER_FREQ_MIN_FM);
+	v4l2_ctrl_handler_init(hdl, 1);
+	v4l2_ctrl_new_std_menu(hdl, &tlg_fm_ctrl_ops, V4L2_CID_TUNE_PREEMPHASIS,
+			V4L2_PREEMPHASIS_75_uS, 0, V4L2_PREEMPHASIS_50_uS);
+	if (hdl->error) {
+		v4l2_ctrl_handler_free(hdl);
+		return hdl->error;
 	}
-	p->radio_data.fm_dev = fm_dev;
-	return 0;
+	vfd->v4l2_dev = &p->v4l2_dev;
+	vfd->ctrl_handler = hdl;
+	set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
+	video_set_drvdata(vfd, p);
+	return video_register_device(vfd, VFL_TYPE_RADIO, -1);
 }
 
 int poseidon_fm_exit(struct poseidon *p)
 {
-	destroy_video_device(&p->radio_data.fm_dev);
+	video_unregister_device(&p->radio_data.fm_dev);
+	v4l2_ctrl_handler_free(&p->radio_data.ctrl_handler);
 	return 0;
 }
diff --git a/drivers/media/usb/tlg2300/pd-video.c b/drivers/media/usb/tlg2300/pd-video.c
index 2172337..8df668d 100644
--- a/drivers/media/usb/tlg2300/pd-video.c
+++ b/drivers/media/usb/tlg2300/pd-video.c
@@ -8,6 +8,7 @@
 
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-dev.h>
+#include <media/v4l2-ctrls.h>
 
 #include "pd-common.h"
 #include "vendorcmds.h"
@@ -82,31 +83,6 @@ static const struct pd_input pd_inputs[] = {
 };
 static const unsigned int POSEIDON_INPUTS = ARRAY_SIZE(pd_inputs);
 
-struct poseidon_control {
-	struct v4l2_queryctrl v4l2_ctrl;
-	enum cmd_custom_param_id vc_id;
-};
-
-static struct poseidon_control controls[] = {
-	{
-		{ V4L2_CID_BRIGHTNESS, V4L2_CTRL_TYPE_INTEGER,
-			"brightness", 0, 10000, 1, 100, 0, },
-		CUST_PARM_ID_BRIGHTNESS_CTRL
-	}, {
-		{ V4L2_CID_CONTRAST, V4L2_CTRL_TYPE_INTEGER,
-			"contrast", 0, 10000, 1, 100, 0, },
-		CUST_PARM_ID_CONTRAST_CTRL,
-	}, {
-		{ V4L2_CID_HUE, V4L2_CTRL_TYPE_INTEGER,
-			"hue", 0, 10000, 1, 100, 0, },
-		CUST_PARM_ID_HUE_CTRL,
-	}, {
-		{ V4L2_CID_SATURATION, V4L2_CTRL_TYPE_INTEGER,
-			"saturation", 0, 10000, 1, 100, 0, },
-		CUST_PARM_ID_SATURATION_CTRL,
-	},
-};
-
 struct video_std_to_audio_std {
 	v4l2_std_id	video_std;
 	int 		audio_std;
@@ -142,17 +118,20 @@ static int get_audio_std(v4l2_std_id v4l2_std)
 static int vidioc_querycap(struct file *file, void *fh,
 			struct v4l2_capability *cap)
 {
-	struct front_face *front = fh;
-	struct poseidon *p = front->pd;
-
-	logs(front);
+	struct video_device *vdev = video_devdata(file);
+	struct poseidon *p = video_get_drvdata(vdev);
 
 	strcpy(cap->driver, "tele-video");
 	strcpy(cap->card, "Telegent Poseidon");
 	usb_make_path(p->udev, cap->bus_info, sizeof(cap->bus_info));
-	cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER |
-				V4L2_CAP_AUDIO | V4L2_CAP_STREAMING |
-				V4L2_CAP_READWRITE | V4L2_CAP_VBI_CAPTURE;
+	cap->device_caps = V4L2_CAP_TUNER | V4L2_CAP_AUDIO |
+			V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;
+	if (vdev->vfl_type == VFL_TYPE_VBI)
+		cap->device_caps |= V4L2_CAP_VBI_CAPTURE;
+	else
+		cap->device_caps |= V4L2_CAP_VIDEO_CAPTURE;
+	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS |
+		V4L2_CAP_RADIO | V4L2_CAP_VBI_CAPTURE | V4L2_CAP_VIDEO_CAPTURE;
 	return 0;
 }
 
@@ -223,7 +202,6 @@ static void submit_frame(struct front_face *front)
  */
 static void end_field(struct video_data *video)
 {
-	/* logs(video->front); */
 	if (1 == video->field_count)
 		submit_frame(video->front);
 	else
@@ -718,17 +696,10 @@ static int vidioc_g_fmt(struct file *file, void *fh, struct v4l2_format *f)
 	struct front_face *front = fh;
 	struct poseidon *pd = front->pd;
 
-	logs(front);
 	f->fmt.pix = pd->video_data.context.pix;
 	return 0;
 }
 
-static int vidioc_try_fmt(struct file *file, void *fh,
-		struct v4l2_format *f)
-{
-	return 0;
-}
-
 /*
  * VLC calls VIDIOC_S_STD before VIDIOC_S_FMT, while
  * Mplayer calls them in the reverse order.
@@ -787,7 +758,6 @@ static int vidioc_s_fmt(struct file *file, void *fh, struct v4l2_format *f)
 	struct front_face *front	= fh;
 	struct poseidon *pd		= front->pd;
 
-	logs(front);
 	/* stop VBI here */
 	if (V4L2_BUF_TYPE_VIDEO_CAPTURE != f->type)
 		return -EINVAL;
@@ -828,11 +798,10 @@ static int vidioc_g_fmt_vbi(struct file *file, void *fh,
 		vbi_fmt->count[1] = V4L_PAL_VBI_LINES;
 	}
 	vbi_fmt->flags = V4L2_VBI_UNSYNC;
-	logs(front);
 	return 0;
 }
 
-static int set_std(struct poseidon *pd, v4l2_std_id *norm)
+static int set_std(struct poseidon *pd, v4l2_std_id norm)
 {
 	struct video_data *video = &pd->video_data;
 	struct vbi_data *vbi	= &pd->vbi_data;
@@ -842,7 +811,7 @@ static int set_std(struct poseidon *pd, v4l2_std_id *norm)
 	int height;
 
 	for (i = 0; i < POSEIDON_TVNORMS; i++) {
-		if (*norm & poseidon_tvnorms[i].v4l2_id) {
+		if (norm & poseidon_tvnorms[i].v4l2_id) {
 			param = poseidon_tvnorms[i].tlg_tvnorm;
 			log("name : %s", poseidon_tvnorms[i].name);
 			goto found;
@@ -877,17 +846,23 @@ out:
 	return ret;
 }
 
-static int vidioc_s_std(struct file *file, void *fh, v4l2_std_id *norm)
+static int vidioc_s_std(struct file *file, void *fh, v4l2_std_id norm)
 {
 	struct front_face *front = fh;
-	logs(front);
+
 	return set_std(front->pd, norm);
 }
 
-static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *in)
+static int vidioc_g_std(struct file *file, void *fh, v4l2_std_id *norm)
 {
 	struct front_face *front = fh;
 
+	*norm = front->pd->video_data.context.tvnormid;
+	return 0;
+}
+
+static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *in)
+{
 	if (in->index >= POSEIDON_INPUTS)
 		return -EINVAL;
 	strcpy(in->name, pd_inputs[in->index].name);
@@ -897,11 +872,10 @@ static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *in)
 	 * the audio input index mixed with this video input,
 	 * Poseidon only have one audio/video, set to "0"
 	 */
-	in->audioset	= 0;
+	in->audioset	= 1;
 	in->tuner	= 0;
 	in->std		= V4L2_STD_ALL;
 	in->status	= 0;
-	logs(front);
 	return 0;
 }
 
@@ -911,7 +885,6 @@ static int vidioc_g_input(struct file *file, void *fh, unsigned int *i)
 	struct poseidon *pd = front->pd;
 	struct running_context *context = &pd->video_data.context;
 
-	logs(front);
 	*i = context->sig_index;
 	return 0;
 }
@@ -934,68 +907,28 @@ static int vidioc_s_input(struct file *file, void *fh, unsigned int i)
 	return 0;
 }
 
-static struct poseidon_control *check_control_id(__u32 id)
-{
-	struct poseidon_control *control = &controls[0];
-	int array_size = ARRAY_SIZE(controls);
-
-	for (; control < &controls[array_size]; control++)
-		if (control->v4l2_ctrl.id  == id)
-			return control;
-	return NULL;
-}
-
-static int vidioc_queryctrl(struct file *file, void *fh,
-			struct v4l2_queryctrl *a)
-{
-	struct poseidon_control *control = NULL;
-
-	control = check_control_id(a->id);
-	if (!control)
-		return -EINVAL;
-
-	*a = control->v4l2_ctrl;
-	return 0;
-}
-
-static int vidioc_g_ctrl(struct file *file, void *fh, struct v4l2_control *ctrl)
-{
-	struct front_face *front = fh;
-	struct poseidon *pd = front->pd;
-	struct poseidon_control *control = NULL;
-	struct tuner_custom_parameter_s tuner_param;
-	s32 ret = 0, cmd_status;
-
-	control = check_control_id(ctrl->id);
-	if (!control)
-		return -EINVAL;
-
-	mutex_lock(&pd->lock);
-	ret = send_get_req(pd, TUNER_CUSTOM_PARAMETER, control->vc_id,
-			&tuner_param, &cmd_status, sizeof(tuner_param));
-	mutex_unlock(&pd->lock);
-
-	if (ret || cmd_status)
-		return -1;
-
-	ctrl->value = tuner_param.param_value;
-	return 0;
-}
-
-static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *a)
+static int tlg_s_ctrl(struct v4l2_ctrl *c)
 {
+	struct poseidon *pd = container_of(c->handler, struct poseidon,
+						video_data.ctrl_handler);
 	struct tuner_custom_parameter_s param = {0};
-	struct poseidon_control *control = NULL;
-	struct front_face *front	= fh;
-	struct poseidon *pd		= front->pd;
 	s32 ret = 0, cmd_status, params;
 
-	control = check_control_id(a->id);
-	if (!control)
-		return -EINVAL;
-
-	param.param_value = a->value;
-	param.param_id	= control->vc_id;
+	switch (c->id) {
+	case V4L2_CID_BRIGHTNESS:
+		param.param_id = CUST_PARM_ID_BRIGHTNESS_CTRL;
+		break;
+	case V4L2_CID_CONTRAST:
+		param.param_id = CUST_PARM_ID_CONTRAST_CTRL;
+		break;
+	case V4L2_CID_HUE:
+		param.param_id = CUST_PARM_ID_HUE_CTRL;
+		break;
+	case V4L2_CID_SATURATION:
+		param.param_id = CUST_PARM_ID_SATURATION_CTRL;
+		break;
+	}
+	param.param_value = c->val;
 	params = *(s32 *)&param; /* temp code */
 
 	mutex_lock(&pd->lock);
@@ -1079,7 +1012,6 @@ static int vidioc_g_tuner(struct file *file, void *fh, struct v4l2_tuner *tuner)
 	tuner->rxsubchans = pd_audio_modes[index].v4l2_audio_sub;
 	tuner->audmode = pd_audio_modes[index].v4l2_audio_mode;
 	tuner->afc = 0;
-	logs(front);
 	return 0;
 }
 
@@ -1099,7 +1031,7 @@ static int pd_vidioc_s_tuner(struct poseidon *pd, int index)
 	return ret;
 }
 
-static int vidioc_s_tuner(struct file *file, void *fh, struct v4l2_tuner *a)
+static int vidioc_s_tuner(struct file *file, void *fh, const struct v4l2_tuner *a)
 {
 	struct front_face *front	= fh;
 	struct poseidon *pd		= front->pd;
@@ -1107,7 +1039,6 @@ static int vidioc_s_tuner(struct file *file, void *fh, struct v4l2_tuner *a)
 
 	if (0 != a->index)
 		return -EINVAL;
-	logs(front);
 	for (index = 0; index < POSEIDON_AUDIOMODS; index++)
 		if (a->audmode == pd_audio_modes[index].v4l2_audio_mode)
 			return pd_vidioc_s_tuner(pd, index);
@@ -1128,51 +1059,51 @@ static int vidioc_g_frequency(struct file *file, void *fh,
 	return 0;
 }
 
-static int set_frequency(struct poseidon *pd, __u32 frequency)
+static int set_frequency(struct poseidon *pd, u32 *frequency)
 {
 	s32 ret = 0, param, cmd_status;
 	struct running_context *context = &pd->video_data.context;
 
-	param = frequency * 62500 / 1000;
-	if (param < TUNER_FREQ_MIN/1000 || param > TUNER_FREQ_MAX / 1000)
-		return -EINVAL;
+	*frequency = clamp(*frequency,
+			TUNER_FREQ_MIN / 62500, TUNER_FREQ_MAX / 62500);
+	param = (*frequency) * 62500 / 1000;
 
 	mutex_lock(&pd->lock);
 	ret = send_set_req(pd, TUNE_FREQ_SELECT, param, &cmd_status);
 	ret = send_set_req(pd, TAKE_REQUEST, 0, &cmd_status);
 
 	msleep(250); /* wait for a while until the hardware is ready. */
-	context->freq = frequency;
+	context->freq = *frequency;
 	mutex_unlock(&pd->lock);
 	return ret;
 }
 
 static int vidioc_s_frequency(struct file *file, void *fh,
-				struct v4l2_frequency *freq)
+				const struct v4l2_frequency *freq)
 {
 	struct front_face *front = fh;
 	struct poseidon *pd = front->pd;
+	u32 frequency = freq->frequency;
 
-	logs(front);
+	if (freq->tuner)
+		return -EINVAL;
 #ifdef CONFIG_PM
 	pd->pm_suspend = pm_video_suspend;
 	pd->pm_resume = pm_video_resume;
 #endif
-	return set_frequency(pd, freq->frequency);
+	return set_frequency(pd, &frequency);
 }
 
 static int vidioc_reqbufs(struct file *file, void *fh,
 				struct v4l2_requestbuffers *b)
 {
 	struct front_face *front = file->private_data;
-	logs(front);
 	return videobuf_reqbufs(&front->q, b);
 }
 
 static int vidioc_querybuf(struct file *file, void *fh, struct v4l2_buffer *b)
 {
 	struct front_face *front = file->private_data;
-	logs(front);
 	return videobuf_querybuf(&front->q, b);
 }
 
@@ -1261,7 +1192,6 @@ static int vidioc_streamon(struct file *file, void *fh,
 {
 	struct front_face *front = fh;
 
-	logs(front);
 	if (unlikely(type != front->type))
 		return -EINVAL;
 	return videobuf_streamon(&front->q);
@@ -1272,7 +1202,6 @@ static int vidioc_streamoff(struct file *file, void *fh,
 {
 	struct front_face *front = file->private_data;
 
-	logs(front);
 	if (unlikely(type != front->type))
 		return -EINVAL;
 	return videobuf_streamoff(&front->q);
@@ -1341,11 +1270,11 @@ static int restore_v4l2_context(struct poseidon *pd,
 
 	pd_video_checkmode(pd);
 
-	set_std(pd, &context->tvnormid);
+	set_std(pd, context->tvnormid);
 	vidioc_s_input(NULL, front, context->sig_index);
 	pd_vidioc_s_tuner(pd, context->audio_idx);
 	pd_vidioc_s_fmt(pd, &context->pix);
-	set_frequency(pd, context->freq);
+	set_frequency(pd, &context->freq);
 	return 0;
 }
 
@@ -1406,12 +1335,14 @@ static int pd_video_open(struct file *file)
 	mutex_lock(&pd->lock);
 	usb_autopm_get_interface(pd->interface);
 
-	if (vfd->vfl_type == VFL_TYPE_GRABBER
-		&& !(pd->state & POSEIDON_STATE_ANALOG)) {
-		front = kzalloc(sizeof(struct front_face), GFP_KERNEL);
-		if (!front)
-			goto out;
-
+	if (pd->state && !(pd->state & POSEIDON_STATE_ANALOG)) {
+		ret = -EBUSY;
+		goto out;
+	}
+	front = kzalloc(sizeof(struct front_face), GFP_KERNEL);
+	if (!front)
+		goto out;
+	if (vfd->vfl_type == VFL_TYPE_GRABBER) {
 		pd->cur_transfer_mode	= usb_transfer_mode;/* bulk or iso */
 		init_video_context(&pd->video_data.context);
 
@@ -1422,7 +1353,6 @@ static int pd_video_open(struct file *file)
 			goto out;
 		}
 
-		pd->state		|= POSEIDON_STATE_ANALOG;
 		front->type		= V4L2_BUF_TYPE_VIDEO_CAPTURE;
 		pd->video_data.users++;
 		set_debug_mode(vfd, debug_mode);
@@ -1433,13 +1363,7 @@ static int pd_video_open(struct file *file)
 				V4L2_FIELD_INTERLACED,/* video is interlacd */
 				sizeof(struct videobuf_buffer),/*it's enough*/
 				front, NULL);
-	} else if (vfd->vfl_type == VFL_TYPE_VBI
-		&& !(pd->state & POSEIDON_STATE_VBI)) {
-		front = kzalloc(sizeof(struct front_face), GFP_KERNEL);
-		if (!front)
-			goto out;
-
-		pd->state	|= POSEIDON_STATE_VBI;
+	} else {
 		front->type	= V4L2_BUF_TYPE_VBI_CAPTURE;
 		pd->vbi_data.front = front;
 		pd->vbi_data.users++;
@@ -1450,19 +1374,15 @@ static int pd_video_open(struct file *file)
 				V4L2_FIELD_NONE, /* vbi is NONE mode */
 				sizeof(struct videobuf_buffer),
 				front, NULL);
-	} else {
-		/* maybe add FM support here */
-		log("other ");
-		ret = -EINVAL;
-		goto out;
 	}
 
-	front->pd		= pd;
-	front->curr_frame	= NULL;
+	pd->state |= POSEIDON_STATE_ANALOG;
+	front->pd = pd;
+	front->curr_frame = NULL;
 	INIT_LIST_HEAD(&front->active);
 	spin_lock_init(&front->queue_lock);
 
-	file->private_data	= front;
+	file->private_data = front;
 	kref_get(&pd->kref);
 
 	mutex_unlock(&pd->lock);
@@ -1479,12 +1399,9 @@ static int pd_video_release(struct file *file)
 	struct poseidon *pd = front->pd;
 	s32 cmd_status = 0;
 
-	logs(front);
 	mutex_lock(&pd->lock);
 
 	if (front->type	== V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-		pd->state &= ~POSEIDON_STATE_ANALOG;
-
 		/* stop the device, and free the URBs */
 		usb_transfer_stop(&pd->video_data);
 		free_all_urb(&pd->video_data);
@@ -1496,10 +1413,11 @@ static int pd_video_release(struct file *file)
 		pd->file_for_stream = NULL;
 		pd->video_data.users--;
 	} else if (front->type	== V4L2_BUF_TYPE_VBI_CAPTURE) {
-		pd->state &= ~POSEIDON_STATE_VBI;
 		pd->vbi_data.front = NULL;
 		pd->vbi_data.users--;
 	}
+	if (!pd->vbi_data.users && !pd->video_data.users)
+		pd->state &= ~POSEIDON_STATE_ANALOG;
 	videobuf_stop(&front->q);
 	videobuf_mmap_free(&front->q);
 
@@ -1551,7 +1469,6 @@ static const struct v4l2_ioctl_ops pd_video_ioctl_ops = {
 	.vidioc_enum_fmt_vid_cap	= vidioc_enum_fmt,
 	.vidioc_s_fmt_vid_cap	= vidioc_s_fmt,
 	.vidioc_g_fmt_vbi_cap	= vidioc_g_fmt_vbi, /* VBI */
-	.vidioc_try_fmt_vid_cap = vidioc_try_fmt,
 
 	/* Input */
 	.vidioc_g_input		= vidioc_g_input,
@@ -1566,6 +1483,7 @@ static const struct v4l2_ioctl_ops pd_video_ioctl_ops = {
 	/* Tuner ioctls */
 	.vidioc_g_tuner		= vidioc_g_tuner,
 	.vidioc_s_tuner		= vidioc_s_tuner,
+	.vidioc_g_std		= vidioc_g_std,
 	.vidioc_s_std		= vidioc_s_std,
 	.vidioc_g_frequency	= vidioc_g_frequency,
 	.vidioc_s_frequency	= vidioc_s_frequency,
@@ -1579,59 +1497,29 @@ static const struct v4l2_ioctl_ops pd_video_ioctl_ops = {
 	/* Stream on/off */
 	.vidioc_streamon	= vidioc_streamon,
 	.vidioc_streamoff	= vidioc_streamoff,
-
-	/* Control handling */
-	.vidioc_queryctrl	= vidioc_queryctrl,
-	.vidioc_g_ctrl		= vidioc_g_ctrl,
-	.vidioc_s_ctrl		= vidioc_s_ctrl,
 };
 
 static struct video_device pd_video_template = {
 	.name = "Telegent-Video",
 	.fops = &pd_video_fops,
 	.minor = -1,
-	.release = video_device_release,
+	.release = video_device_release_empty,
 	.tvnorms = V4L2_STD_ALL,
 	.ioctl_ops = &pd_video_ioctl_ops,
 };
 
-struct video_device *vdev_init(struct poseidon *pd, struct video_device *tmp)
-{
-	struct video_device *vfd;
-
-	vfd = video_device_alloc();
-	if (vfd == NULL)
-		return NULL;
-	*vfd		= *tmp;
-	vfd->minor	= -1;
-	vfd->v4l2_dev	= &pd->v4l2_dev;
-	/*vfd->parent	= &(pd->udev->dev); */
-	vfd->release	= video_device_release;
-	video_set_drvdata(vfd, pd);
-	return vfd;
-}
-
-void destroy_video_device(struct video_device **v_dev)
-{
-	struct video_device *dev = *v_dev;
-
-	if (dev == NULL)
-		return;
-
-	if (video_is_registered(dev))
-		video_unregister_device(dev);
-	else
-		video_device_release(dev);
-	*v_dev = NULL;
-}
+static const struct v4l2_ctrl_ops tlg_ctrl_ops = {
+	.s_ctrl = tlg_s_ctrl,
+};
 
 void pd_video_exit(struct poseidon *pd)
 {
 	struct video_data *video = &pd->video_data;
 	struct vbi_data *vbi = &pd->vbi_data;
 
-	destroy_video_device(&video->v_dev);
-	destroy_video_device(&vbi->v_dev);
+	video_unregister_device(&video->v_dev);
+	video_unregister_device(&vbi->v_dev);
+	v4l2_ctrl_handler_free(&video->ctrl_handler);
 	log();
 }
 
@@ -1639,23 +1527,39 @@ int pd_video_init(struct poseidon *pd)
 {
 	struct video_data *video = &pd->video_data;
 	struct vbi_data *vbi	= &pd->vbi_data;
+	struct v4l2_ctrl_handler *hdl = &video->ctrl_handler;
+	u32 freq = TUNER_FREQ_MIN / 62500;
 	int ret = -ENOMEM;
 
-	video->v_dev = vdev_init(pd, &pd_video_template);
-	if (video->v_dev == NULL)
-		goto out;
+	v4l2_ctrl_handler_init(hdl, 4);
+	v4l2_ctrl_new_std(hdl, &tlg_ctrl_ops, V4L2_CID_BRIGHTNESS,
+			0, 10000, 1, 100);
+	v4l2_ctrl_new_std(hdl, &tlg_ctrl_ops, V4L2_CID_CONTRAST,
+			0, 10000, 1, 100);
+	v4l2_ctrl_new_std(hdl, &tlg_ctrl_ops, V4L2_CID_HUE,
+			0, 10000, 1, 100);
+	v4l2_ctrl_new_std(hdl, &tlg_ctrl_ops, V4L2_CID_SATURATION,
+			0, 10000, 1, 100);
+	if (hdl->error) {
+		v4l2_ctrl_handler_free(hdl);
+		return hdl->error;
+	}
+	set_frequency(pd, &freq);
+	video->v_dev = pd_video_template;
+	video->v_dev.v4l2_dev = &pd->v4l2_dev;
+	video->v_dev.ctrl_handler = hdl;
+	video_set_drvdata(&video->v_dev, pd);
 
-	ret = video_register_device(video->v_dev, VFL_TYPE_GRABBER, -1);
+	ret = video_register_device(&video->v_dev, VFL_TYPE_GRABBER, -1);
 	if (ret != 0)
 		goto out;
 
 	/* VBI uses the same template as video */
-	vbi->v_dev = vdev_init(pd, &pd_video_template);
-	if (vbi->v_dev == NULL) {
-		ret = -ENOMEM;
-		goto out;
-	}
-	ret = video_register_device(vbi->v_dev, VFL_TYPE_VBI, -1);
+	vbi->v_dev = pd_video_template;
+	vbi->v_dev.v4l2_dev = &pd->v4l2_dev;
+	vbi->v_dev.ctrl_handler = hdl;
+	video_set_drvdata(&vbi->v_dev, pd);
+	ret = video_register_device(&vbi->v_dev, VFL_TYPE_VBI, -1);
 	if (ret != 0)
 		goto out;
 	log("register VIDEO/VBI devices");
@@ -1665,4 +1569,3 @@ out:
 	pd_video_exit(pd);
 	return ret;
 }
-
diff --git a/drivers/media/usb/tm6000/tm6000-video.c b/drivers/media/usb/tm6000/tm6000-video.c
index 1a68579..a78de1d 100644
--- a/drivers/media/usb/tm6000/tm6000-video.c
+++ b/drivers/media/usb/tm6000/tm6000-video.c
@@ -1056,13 +1056,13 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
 	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;
 	struct tm6000_core *dev = fh->dev;
 
-	dev->norm = *norm;
+	dev->norm = norm;
 	rc = tm6000_init_analog_mode(dev);
 
 	fh->width  = dev->width;
@@ -1134,7 +1134,7 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
 
 	dev->input = i;
 
-	rc = vidioc_s_std(file, priv, &dev->vfd->current_norm);
+	rc = vidioc_s_std(file, priv, dev->vfd->current_norm);
 
 	return rc;
 }
@@ -1215,7 +1215,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
 }
 
 static int vidioc_s_tuner(struct file *file, void *priv,
-				struct v4l2_tuner *t)
+				const struct v4l2_tuner *t)
 {
 	struct tm6000_fh   *fh  = priv;
 	struct tm6000_core *dev = fh->dev;
@@ -1255,7 +1255,7 @@ static int vidioc_g_frequency(struct file *file, void *priv,
 }
 
 static int vidioc_s_frequency(struct file *file, void *priv,
-				struct v4l2_frequency *f)
+				const struct v4l2_frequency *f)
 {
 	struct tm6000_fh   *fh  = priv;
 	struct tm6000_core *dev = fh->dev;
@@ -1293,18 +1293,14 @@ static int radio_g_tuner(struct file *file, void *priv,
 }
 
 static int radio_s_tuner(struct file *file, void *priv,
-					struct v4l2_tuner *t)
+					const struct v4l2_tuner *t)
 {
 	struct tm6000_fh *fh = file->private_data;
 	struct tm6000_core *dev = fh->dev;
 
 	if (0 != t->index)
 		return -EINVAL;
-	if (t->audmode > V4L2_TUNER_MODE_STEREO)
-		t->audmode = V4L2_TUNER_MODE_STEREO;
-
 	v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t);
-
 	return 0;
 }
 
diff --git a/drivers/media/usb/usbvision/usbvision-video.c b/drivers/media/usb/usbvision/usbvision-video.c
index cd1fe78..d34c2af 100644
--- a/drivers/media/usb/usbvision/usbvision-video.c
+++ b/drivers/media/usb/usbvision/usbvision-video.c
@@ -483,7 +483,7 @@ static int vidioc_g_register(struct file *file, void *priv,
 }
 
 static int vidioc_s_register(struct file *file, void *priv,
-				struct v4l2_dbg_register *reg)
+				const struct v4l2_dbg_register *reg)
 {
 	struct usb_usbvision *usbvision = video_drvdata(file);
 	int err_code;
@@ -595,11 +595,11 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int input)
 	return 0;
 }
 
-static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *id)
+static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id)
 {
 	struct usb_usbvision *usbvision = video_drvdata(file);
 
-	usbvision->tvnorm_id = *id;
+	usbvision->tvnorm_id = id;
 
 	call_all(usbvision, core, s_std, usbvision->tvnorm_id);
 	/* propagate the change to the decoder */
@@ -628,7 +628,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
 }
 
 static int vidioc_s_tuner(struct file *file, void *priv,
-				struct v4l2_tuner *vt)
+				const struct v4l2_tuner *vt)
 {
 	struct usb_usbvision *usbvision = video_drvdata(file);
 
@@ -657,7 +657,7 @@ static int vidioc_g_frequency(struct file *file, void *priv,
 }
 
 static int vidioc_s_frequency(struct file *file, void *priv,
-				struct v4l2_frequency *freq)
+				const struct v4l2_frequency *freq)
 {
 	struct usb_usbvision *usbvision = video_drvdata(file);
 
diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c
index 61e28de..a2f4501 100644
--- a/drivers/media/usb/uvc/uvc_ctrl.c
+++ b/drivers/media/usb/uvc/uvc_ctrl.c
@@ -1487,7 +1487,7 @@ int uvc_ctrl_set(struct uvc_video_chain *chain,
 			step = mapping->get(mapping, UVC_GET_RES,
 					uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES));
 			if (!(step & value))
-				return -ERANGE;
+				return -EINVAL;
 		}
 
 		break;
diff --git a/drivers/media/usb/uvc/uvc_queue.c b/drivers/media/usb/uvc/uvc_queue.c
index 6c233a5..cd962be 100644
--- a/drivers/media/usb/uvc/uvc_queue.c
+++ b/drivers/media/usb/uvc/uvc_queue.c
@@ -149,6 +149,7 @@ int uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type,
 	queue->queue.buf_struct_size = sizeof(struct uvc_buffer);
 	queue->queue.ops = &uvc_queue_qops;
 	queue->queue.mem_ops = &vb2_vmalloc_memops;
+	queue->queue.timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
 	ret = vb2_queue_init(&queue->queue);
 	if (ret)
 		return ret;
diff --git a/drivers/media/v4l2-core/Kconfig b/drivers/media/v4l2-core/Kconfig
index 976d029..8c05565 100644
--- a/drivers/media/v4l2-core/Kconfig
+++ b/drivers/media/v4l2-core/Kconfig
@@ -67,6 +67,7 @@ config VIDEOBUF2_MEMOPS
 
 config VIDEOBUF2_DMA_CONTIG
 	tristate
+	depends on HAS_DMA
 	select VIDEOBUF2_CORE
 	select VIDEOBUF2_MEMOPS
 	select DMA_SHARED_BUFFER
diff --git a/drivers/media/v4l2-core/tuner-core.c b/drivers/media/v4l2-core/tuner-core.c
index b5a8aac..cf9a9af 100644
--- a/drivers/media/v4l2-core/tuner-core.c
+++ b/drivers/media/v4l2-core/tuner-core.c
@@ -220,22 +220,22 @@ static void fe_standby(struct dvb_frontend *fe)
 
 static int fe_has_signal(struct dvb_frontend *fe)
 {
-	u16 strength = 0;
+	u16 strength;
 
-	if (fe->ops.tuner_ops.get_rf_strength)
-		fe->ops.tuner_ops.get_rf_strength(fe, &strength);
+	if (fe->ops.tuner_ops.get_rf_strength(fe, &strength) < 0)
+		return 0;
 
 	return strength;
 }
 
 static int fe_get_afc(struct dvb_frontend *fe)
 {
-	s32 afc = 0;
+	s32 afc;
 
-	if (fe->ops.tuner_ops.get_afc)
-		fe->ops.tuner_ops.get_afc(fe, &afc);
+	if (fe->ops.tuner_ops.get_afc(fe, &afc) < 0)
+		return 0;
 
-	return 0;
+	return afc;
 }
 
 static int fe_set_config(struct dvb_frontend *fe, void *priv_cfg)
@@ -253,11 +253,9 @@ static int fe_set_config(struct dvb_frontend *fe, void *priv_cfg)
 
 static void tuner_status(struct dvb_frontend *fe);
 
-static struct analog_demod_ops tuner_analog_ops = {
+static const struct analog_demod_ops tuner_analog_ops = {
 	.set_params     = fe_set_params,
 	.standby        = fe_standby,
-	.has_signal     = fe_has_signal,
-	.get_afc        = fe_get_afc,
 	.set_config     = fe_set_config,
 	.tuner_status   = tuner_status
 };
@@ -453,6 +451,11 @@ static void set_type(struct i2c_client *c, unsigned int type,
 		memcpy(analog_ops, &tuner_analog_ops,
 		       sizeof(struct analog_demod_ops));
 
+		if (fe_tuner_ops->get_rf_strength)
+			analog_ops->has_signal = fe_has_signal;
+		if (fe_tuner_ops->get_afc)
+			analog_ops->get_afc = fe_get_afc;
+
 	} else {
 		t->name = analog_ops->info.name;
 	}
@@ -1134,7 +1137,7 @@ static int tuner_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
 	return 0;
 }
 
-static int tuner_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f)
+static int tuner_s_frequency(struct v4l2_subdev *sd, const struct v4l2_frequency *f)
 {
 	struct tuner *t = to_tuner(sd);
 
@@ -1233,7 +1236,7 @@ static int tuner_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
  * Note: vt->type should be initialized before calling it.
  * This is done by either video_ioctl2 or by the bridge driver.
  */
-static int tuner_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
+static int tuner_s_tuner(struct v4l2_subdev *sd, const struct v4l2_tuner *vt)
 {
 	struct tuner *t = to_tuner(sd);
 
diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c
index aa044f4..f8fac9c 100644
--- a/drivers/media/v4l2-core/v4l2-common.c
+++ b/drivers/media/v4l2-core/v4l2-common.c
@@ -230,7 +230,7 @@ EXPORT_SYMBOL(v4l2_ctrl_next);
 int v4l2_chip_match_host(const struct v4l2_dbg_match *match)
 {
 	switch (match->type) {
-	case V4L2_CHIP_MATCH_HOST:
+	case V4L2_CHIP_MATCH_BRIDGE:
 		return match->addr == 0;
 	default:
 		return 0;
@@ -251,12 +251,12 @@ int v4l2_chip_match_i2c_client(struct i2c_client *c, const struct v4l2_dbg_match
 		if (c->driver == NULL || c->driver->driver.name == NULL)
 			return 0;
 		len = strlen(c->driver->driver.name);
-		/* legacy drivers have a ' suffix, don't try to match that */
-		if (len && c->driver->driver.name[len - 1] == '\'')
-			len--;
 		return len && !strncmp(c->driver->driver.name, match->name, len);
 	case V4L2_CHIP_MATCH_I2C_ADDR:
 		return c->addr == match->addr;
+	case V4L2_CHIP_MATCH_SUBDEV_IDX:
+	case V4L2_CHIP_MATCH_SUBDEV_NAME:
+		return 1;
 	default:
 		return 0;
 	}
@@ -551,53 +551,6 @@ void v4l_bound_align_image(u32 *w, unsigned int wmin, unsigned int wmax,
 EXPORT_SYMBOL_GPL(v4l_bound_align_image);
 
 /**
- * v4l_fill_dv_preset_info - fill description of a digital video preset
- * @preset - preset value
- * @info - pointer to struct v4l2_dv_enum_preset
- *
- * drivers can use this helper function to fill description of dv preset
- * in info.
- */
-int v4l_fill_dv_preset_info(u32 preset, struct v4l2_dv_enum_preset *info)
-{
-	static const struct v4l2_dv_preset_info {
-		u16 width;
-		u16 height;
-		const char *name;
-	} dv_presets[] = {
-		{ 0, 0, "Invalid" },		/* V4L2_DV_INVALID */
-		{ 720,  480, "480p@59.94" },	/* V4L2_DV_480P59_94 */
-		{ 720,  576, "576p@50" },	/* V4L2_DV_576P50 */
-		{ 1280, 720, "720p@24" },	/* V4L2_DV_720P24 */
-		{ 1280, 720, "720p@25" },	/* V4L2_DV_720P25 */
-		{ 1280, 720, "720p@30" },	/* V4L2_DV_720P30 */
-		{ 1280, 720, "720p@50" },	/* V4L2_DV_720P50 */
-		{ 1280, 720, "720p@59.94" },	/* V4L2_DV_720P59_94 */
-		{ 1280, 720, "720p@60" },	/* V4L2_DV_720P60 */
-		{ 1920, 1080, "1080i@29.97" },	/* V4L2_DV_1080I29_97 */
-		{ 1920, 1080, "1080i@30" },	/* V4L2_DV_1080I30 */
-		{ 1920, 1080, "1080i@25" },	/* V4L2_DV_1080I25 */
-		{ 1920, 1080, "1080i@50" },	/* V4L2_DV_1080I50 */
-		{ 1920, 1080, "1080i@60" },	/* V4L2_DV_1080I60 */
-		{ 1920, 1080, "1080p@24" },	/* V4L2_DV_1080P24 */
-		{ 1920, 1080, "1080p@25" },	/* V4L2_DV_1080P25 */
-		{ 1920, 1080, "1080p@30" },	/* V4L2_DV_1080P30 */
-		{ 1920, 1080, "1080p@50" },	/* V4L2_DV_1080P50 */
-		{ 1920, 1080, "1080p@60" },	/* V4L2_DV_1080P60 */
-	};
-
-	if (info == NULL || preset >= ARRAY_SIZE(dv_presets))
-		return -EINVAL;
-
-	info->preset = preset;
-	info->width = dv_presets[preset].width;
-	info->height = dv_presets[preset].height;
-	strlcpy(info->name, dv_presets[preset].name, sizeof(info->name));
-	return 0;
-}
-EXPORT_SYMBOL_GPL(v4l_fill_dv_preset_info);
-
-/**
  * v4l_match_dv_timings - check if two timings match
  * @t1 - compare this v4l2_dv_timings struct...
  * @t2 - with this struct.
diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index 7157af3..f129551 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -1076,10 +1076,6 @@ long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
 	case VIDIOC_DBG_G_REGISTER:
 	case VIDIOC_DBG_G_CHIP_IDENT:
 	case VIDIOC_S_HW_FREQ_SEEK:
-	case VIDIOC_ENUM_DV_PRESETS:
-	case VIDIOC_S_DV_PRESET:
-	case VIDIOC_G_DV_PRESET:
-	case VIDIOC_QUERY_DV_PRESET:
 	case VIDIOC_S_DV_TIMINGS:
 	case VIDIOC_G_DV_TIMINGS:
 	case VIDIOC_DQEVENT:
diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
index 6b28b58..f662df3 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -695,6 +695,7 @@ const char *v4l2_ctrl_get_name(u32 id)
 	case V4L2_CID_MPEG_VIDEO_DEC_PTS:			return "Video Decoder PTS";
 	case V4L2_CID_MPEG_VIDEO_DEC_FRAME:			return "Video Decoder Frame Count";
 	case V4L2_CID_MPEG_VIDEO_VBV_DELAY:			return "Initial Delay for VBV Control";
+	case V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER:		return "Repeat Sequence Header";
 
 	/* CAMERA controls */
 	/* Keep the order of the 'case's the same as in videodev2.h! */
@@ -844,6 +845,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
 	case V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM:
 	case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE:
 	case V4L2_CID_MPEG_VIDEO_MPEG4_QPEL:
+	case V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER:
 	case V4L2_CID_WIDE_DYNAMIC_RANGE:
 	case V4L2_CID_IMAGE_STABILIZATION:
 		*type = V4L2_CTRL_TYPE_BOOLEAN;
@@ -1362,11 +1364,13 @@ static inline int handler_set_err(struct v4l2_ctrl_handler *hdl, int err)
 }
 
 /* Initialize the handler */
-int v4l2_ctrl_handler_init(struct v4l2_ctrl_handler *hdl,
-			   unsigned nr_of_controls_hint)
+int v4l2_ctrl_handler_init_class(struct v4l2_ctrl_handler *hdl,
+				 unsigned nr_of_controls_hint,
+				 struct lock_class_key *key, const char *name)
 {
 	hdl->lock = &hdl->_lock;
 	mutex_init(hdl->lock);
+	lockdep_set_class_and_name(hdl->lock, key, name);
 	INIT_LIST_HEAD(&hdl->ctrls);
 	INIT_LIST_HEAD(&hdl->ctrl_refs);
 	hdl->nr_of_buckets = 1 + nr_of_controls_hint / 8;
@@ -1375,7 +1379,7 @@ int v4l2_ctrl_handler_init(struct v4l2_ctrl_handler *hdl,
 	hdl->error = hdl->buckets ? 0 : -ENOMEM;
 	return hdl->error;
 }
-EXPORT_SYMBOL(v4l2_ctrl_handler_init);
+EXPORT_SYMBOL(v4l2_ctrl_handler_init_class);
 
 /* Free all controls and control refs */
 void v4l2_ctrl_handler_free(struct v4l2_ctrl_handler *hdl)
diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c
index de1e9ab..670b9ca 100644
--- a/drivers/media/v4l2-core/v4l2-dev.c
+++ b/drivers/media/v4l2-core/v4l2-dev.c
@@ -591,9 +591,10 @@ static void determine_valid_ioctls(struct video_device *vdev)
 	SET_VALID_IOCTL(ops, VIDIOC_G_FREQUENCY, vidioc_g_frequency);
 	SET_VALID_IOCTL(ops, VIDIOC_S_FREQUENCY, vidioc_s_frequency);
 	SET_VALID_IOCTL(ops, VIDIOC_LOG_STATUS, vidioc_log_status);
+	set_bit(_IOC_NR(VIDIOC_DBG_G_CHIP_NAME), valid_ioctls);
 #ifdef CONFIG_VIDEO_ADV_DEBUG
-	SET_VALID_IOCTL(ops, VIDIOC_DBG_G_REGISTER, vidioc_g_register);
-	SET_VALID_IOCTL(ops, VIDIOC_DBG_S_REGISTER, vidioc_s_register);
+	set_bit(_IOC_NR(VIDIOC_DBG_G_REGISTER), valid_ioctls);
+	set_bit(_IOC_NR(VIDIOC_DBG_S_REGISTER), valid_ioctls);
 #endif
 	SET_VALID_IOCTL(ops, VIDIOC_DBG_G_CHIP_IDENT, vidioc_g_chip_ident);
 	/* yes, really vidioc_subscribe_event */
@@ -685,7 +686,6 @@ static void determine_valid_ioctls(struct video_device *vdev)
 			SET_VALID_IOCTL(ops, VIDIOC_ENUMAUDIO, vidioc_enumaudio);
 			SET_VALID_IOCTL(ops, VIDIOC_G_AUDIO, vidioc_g_audio);
 			SET_VALID_IOCTL(ops, VIDIOC_S_AUDIO, vidioc_s_audio);
-			SET_VALID_IOCTL(ops, VIDIOC_QUERY_DV_PRESET, vidioc_query_dv_preset);
 			SET_VALID_IOCTL(ops, VIDIOC_QUERY_DV_TIMINGS, vidioc_query_dv_timings);
 		}
 		if (is_tx) {
@@ -708,9 +708,6 @@ static void determine_valid_ioctls(struct video_device *vdev)
 					(ops->vidioc_g_std || vdev->current_norm)))
 			set_bit(_IOC_NR(VIDIOC_G_PARM), valid_ioctls);
 		SET_VALID_IOCTL(ops, VIDIOC_S_PARM, vidioc_s_parm);
-		SET_VALID_IOCTL(ops, VIDIOC_ENUM_DV_PRESETS, vidioc_enum_dv_presets);
-		SET_VALID_IOCTL(ops, VIDIOC_S_DV_PRESET, vidioc_s_dv_preset);
-		SET_VALID_IOCTL(ops, VIDIOC_G_DV_PRESET, vidioc_g_dv_preset);
 		SET_VALID_IOCTL(ops, VIDIOC_S_DV_TIMINGS, vidioc_s_dv_timings);
 		SET_VALID_IOCTL(ops, VIDIOC_G_DV_TIMINGS, vidioc_g_dv_timings);
 		SET_VALID_IOCTL(ops, VIDIOC_ENUM_DV_TIMINGS, vidioc_enum_dv_timings);
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
index aa6e7c7..336ed2d 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -35,6 +35,8 @@
 	memset((u8 *)(p) + offsetof(typeof(*(p)), field) + sizeof((p)->field), \
 	0, sizeof(*(p)) - offsetof(typeof(*(p)), field) - sizeof((p)->field))
 
+#define is_valid_ioctl(vfd, cmd) test_bit(_IOC_NR(cmd), (vfd)->valid_ioctls)
+
 struct std_descr {
 	v4l2_std_id std;
 	const char *descr;
@@ -167,9 +169,11 @@ static void v4l_print_querycap(const void *arg, bool write_only)
 {
 	const struct v4l2_capability *p = arg;
 
-	pr_cont("driver=%s, card=%s, bus=%s, version=0x%08x, "
+	pr_cont("driver=%.*s, card=%.*s, bus=%.*s, version=0x%08x, "
 		"capabilities=0x%08x, device_caps=0x%08x\n",
-		p->driver, p->card, p->bus_info,
+		(int)sizeof(p->driver), p->driver,
+		(int)sizeof(p->card), p->card,
+		(int)sizeof(p->bus_info), p->bus_info,
 		p->version, p->capabilities, p->device_caps);
 }
 
@@ -177,20 +181,21 @@ static void v4l_print_enuminput(const void *arg, bool write_only)
 {
 	const struct v4l2_input *p = arg;
 
-	pr_cont("index=%u, name=%s, type=%u, audioset=0x%x, tuner=%u, "
+	pr_cont("index=%u, name=%.*s, type=%u, audioset=0x%x, tuner=%u, "
 		"std=0x%08Lx, status=0x%x, capabilities=0x%x\n",
-		p->index, p->name, p->type, p->audioset, p->tuner,
-		(unsigned long long)p->std, p->status, p->capabilities);
+		p->index, (int)sizeof(p->name), p->name, p->type, p->audioset,
+		p->tuner, (unsigned long long)p->std, p->status,
+		p->capabilities);
 }
 
 static void v4l_print_enumoutput(const void *arg, bool write_only)
 {
 	const struct v4l2_output *p = arg;
 
-	pr_cont("index=%u, name=%s, type=%u, audioset=0x%x, "
+	pr_cont("index=%u, name=%.*s, type=%u, audioset=0x%x, "
 		"modulator=%u, std=0x%08Lx, capabilities=0x%x\n",
-		p->index, p->name, p->type, p->audioset, p->modulator,
-		(unsigned long long)p->std, p->capabilities);
+		p->index, (int)sizeof(p->name), p->name, p->type, p->audioset,
+		p->modulator, (unsigned long long)p->std, p->capabilities);
 }
 
 static void v4l_print_audio(const void *arg, bool write_only)
@@ -200,8 +205,9 @@ static void v4l_print_audio(const void *arg, bool write_only)
 	if (write_only)
 		pr_cont("index=%u, mode=0x%x\n", p->index, p->mode);
 	else
-		pr_cont("index=%u, name=%s, capability=0x%x, mode=0x%x\n",
-			p->index, p->name, p->capability, p->mode);
+		pr_cont("index=%u, name=%.*s, capability=0x%x, mode=0x%x\n",
+			p->index, (int)sizeof(p->name), p->name,
+			p->capability, p->mode);
 }
 
 static void v4l_print_audioout(const void *arg, bool write_only)
@@ -211,21 +217,22 @@ static void v4l_print_audioout(const void *arg, bool write_only)
 	if (write_only)
 		pr_cont("index=%u\n", p->index);
 	else
-		pr_cont("index=%u, name=%s, capability=0x%x, mode=0x%x\n",
-			p->index, p->name, p->capability, p->mode);
+		pr_cont("index=%u, name=%.*s, capability=0x%x, mode=0x%x\n",
+			p->index, (int)sizeof(p->name), p->name,
+			p->capability, p->mode);
 }
 
 static void v4l_print_fmtdesc(const void *arg, bool write_only)
 {
 	const struct v4l2_fmtdesc *p = arg;
 
-	pr_cont("index=%u, type=%s, flags=0x%x, pixelformat=%c%c%c%c, description='%s'\n",
+	pr_cont("index=%u, type=%s, flags=0x%x, pixelformat=%c%c%c%c, description='%.*s'\n",
 		p->index, prt_names(p->type, v4l2_type_names),
 		p->flags, (p->pixelformat & 0xff),
 		(p->pixelformat >>  8) & 0xff,
 		(p->pixelformat >> 16) & 0xff,
 		(p->pixelformat >> 24) & 0xff,
-		p->description);
+		(int)sizeof(p->description), p->description);
 }
 
 static void v4l_print_format(const void *arg, bool write_only)
@@ -348,9 +355,9 @@ static void v4l_print_modulator(const void *arg, bool write_only)
 	if (write_only)
 		pr_cont("index=%u, txsubchans=0x%x", p->index, p->txsubchans);
 	else
-		pr_cont("index=%u, name=%s, capability=0x%x, "
+		pr_cont("index=%u, name=%.*s, capability=0x%x, "
 			"rangelow=%u, rangehigh=%u, txsubchans=0x%x\n",
-			p->index, p->name, p->capability,
+			p->index, (int)sizeof(p->name), p->name, p->capability,
 			p->rangelow, p->rangehigh, p->txsubchans);
 }
 
@@ -361,10 +368,10 @@ static void v4l_print_tuner(const void *arg, bool write_only)
 	if (write_only)
 		pr_cont("index=%u, audmode=%u\n", p->index, p->audmode);
 	else
-		pr_cont("index=%u, name=%s, type=%u, capability=0x%x, "
+		pr_cont("index=%u, name=%.*s, type=%u, capability=0x%x, "
 			"rangelow=%u, rangehigh=%u, signal=%u, afc=%d, "
 			"rxsubchans=0x%x, audmode=%u\n",
-			p->index, p->name, p->type,
+			p->index, (int)sizeof(p->name), p->name, p->type,
 			p->capability, p->rangelow,
 			p->rangehigh, p->signal, p->afc,
 			p->rxsubchans, p->audmode);
@@ -382,9 +389,9 @@ static void v4l_print_standard(const void *arg, bool write_only)
 {
 	const struct v4l2_standard *p = arg;
 
-	pr_cont("index=%u, id=0x%Lx, name=%s, fps=%u/%u, "
+	pr_cont("index=%u, id=0x%Lx, name=%.*s, fps=%u/%u, "
 		"framelines=%u\n", p->index,
-		(unsigned long long)p->id, p->name,
+		(unsigned long long)p->id, (int)sizeof(p->name), p->name,
 		p->frameperiod.numerator,
 		p->frameperiod.denominator,
 		p->framelines);
@@ -504,9 +511,9 @@ static void v4l_print_queryctrl(const void *arg, bool write_only)
 {
 	const struct v4l2_queryctrl *p = arg;
 
-	pr_cont("id=0x%x, type=%d, name=%s, min/max=%d/%d, "
+	pr_cont("id=0x%x, type=%d, name=%.*s, min/max=%d/%d, "
 		"step=%d, default=%d, flags=0x%08x\n",
-			p->id, p->type, p->name,
+			p->id, p->type, (int)sizeof(p->name), p->name,
 			p->minimum, p->maximum,
 			p->step, p->default_value, p->flags);
 }
@@ -622,40 +629,43 @@ static void v4l_print_dbg_chip_ident(const void *arg, bool write_only)
 	const struct v4l2_dbg_chip_ident *p = arg;
 
 	pr_cont("type=%u, ", p->match.type);
-	if (p->match.type == V4L2_CHIP_MATCH_I2C_DRIVER)
-		pr_cont("name=%s, ", p->match.name);
+	if (p->match.type == V4L2_CHIP_MATCH_I2C_DRIVER ||
+	    p->match.type == V4L2_CHIP_MATCH_SUBDEV_NAME)
+		pr_cont("name=%.*s, ",
+				(int)sizeof(p->match.name), p->match.name);
 	else
 		pr_cont("addr=%u, ", p->match.addr);
 	pr_cont("chip_ident=%u, revision=0x%x\n",
 			p->ident, p->revision);
 }
 
-static void v4l_print_dbg_register(const void *arg, bool write_only)
+static void v4l_print_dbg_chip_name(const void *arg, bool write_only)
 {
-	const struct v4l2_dbg_register *p = arg;
+	const struct v4l2_dbg_chip_name *p = arg;
 
 	pr_cont("type=%u, ", p->match.type);
-	if (p->match.type == V4L2_CHIP_MATCH_I2C_DRIVER)
-		pr_cont("name=%s, ", p->match.name);
+	if (p->match.type == V4L2_CHIP_MATCH_I2C_DRIVER ||
+	    p->match.type == V4L2_CHIP_MATCH_SUBDEV_NAME)
+		pr_cont("name=%.*s, ",
+				(int)sizeof(p->match.name), p->match.name);
 	else
 		pr_cont("addr=%u, ", p->match.addr);
-	pr_cont("reg=0x%llx, val=0x%llx\n",
-			p->reg, p->val);
-}
-
-static void v4l_print_dv_enum_presets(const void *arg, bool write_only)
-{
-	const struct v4l2_dv_enum_preset *p = arg;
-
-	pr_cont("index=%u, preset=%u, name=%s, width=%u, height=%u\n",
-			p->index, p->preset, p->name, p->width, p->height);
+	pr_cont("name=%.*s\n", (int)sizeof(p->name), p->name);
 }
 
-static void v4l_print_dv_preset(const void *arg, bool write_only)
+static void v4l_print_dbg_register(const void *arg, bool write_only)
 {
-	const struct v4l2_dv_preset *p = arg;
+	const struct v4l2_dbg_register *p = arg;
 
-	pr_cont("preset=%u\n", p->preset);
+	pr_cont("type=%u, ", p->match.type);
+	if (p->match.type == V4L2_CHIP_MATCH_I2C_DRIVER ||
+	    p->match.type == V4L2_CHIP_MATCH_SUBDEV_NAME)
+		pr_cont("name=%.*s, ",
+				(int)sizeof(p->match.name), p->match.name);
+	else
+		pr_cont("addr=%u, ", p->match.addr);
+	pr_cont("reg=0x%llx, val=0x%llx\n",
+			p->reg, p->val);
 }
 
 static void v4l_print_dv_timings(const void *arg, bool write_only)
@@ -997,20 +1007,17 @@ static int v4l_s_priority(const struct v4l2_ioctl_ops *ops,
 static int v4l_enuminput(const struct v4l2_ioctl_ops *ops,
 				struct file *file, void *fh, void *arg)
 {
+	struct video_device *vfd = video_devdata(file);
 	struct v4l2_input *p = arg;
 
 	/*
-	 * We set the flags for CAP_PRESETS, CAP_DV_TIMINGS &
+	 * We set the flags for CAP_DV_TIMINGS &
 	 * CAP_STD here based on ioctl handler provided by the
 	 * driver. If the driver doesn't support these
 	 * for a specific input, it must override these flags.
 	 */
-	if (ops->vidioc_s_std)
+	if (is_valid_ioctl(vfd, VIDIOC_S_STD))
 		p->capabilities |= V4L2_IN_CAP_STD;
-	if (ops->vidioc_s_dv_preset)
-		p->capabilities |= V4L2_IN_CAP_PRESETS;
-	if (ops->vidioc_s_dv_timings)
-		p->capabilities |= V4L2_IN_CAP_DV_TIMINGS;
 
 	return ops->vidioc_enum_input(file, fh, p);
 }
@@ -1018,20 +1025,17 @@ static int v4l_enuminput(const struct v4l2_ioctl_ops *ops,
 static int v4l_enumoutput(const struct v4l2_ioctl_ops *ops,
 				struct file *file, void *fh, void *arg)
 {
+	struct video_device *vfd = video_devdata(file);
 	struct v4l2_output *p = arg;
 
 	/*
-	 * We set the flags for CAP_PRESETS, CAP_DV_TIMINGS &
+	 * We set the flags for CAP_DV_TIMINGS &
 	 * CAP_STD here based on ioctl handler provided by the
 	 * driver. If the driver doesn't support these
 	 * for a specific output, it must override these flags.
 	 */
-	if (ops->vidioc_s_std)
+	if (is_valid_ioctl(vfd, VIDIOC_S_STD))
 		p->capabilities |= V4L2_OUT_CAP_STD;
-	if (ops->vidioc_s_dv_preset)
-		p->capabilities |= V4L2_OUT_CAP_PRESETS;
-	if (ops->vidioc_s_dv_timings)
-		p->capabilities |= V4L2_OUT_CAP_DV_TIMINGS;
 
 	return ops->vidioc_enum_output(file, fh, p);
 }
@@ -1316,7 +1320,7 @@ static int v4l_s_frequency(const struct v4l2_ioctl_ops *ops,
 				struct file *file, void *fh, void *arg)
 {
 	struct video_device *vfd = video_devdata(file);
-	struct v4l2_frequency *p = arg;
+	const struct v4l2_frequency *p = arg;
 	enum v4l2_tuner_type type;
 
 	type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
@@ -1383,15 +1387,15 @@ static int v4l_s_std(const struct v4l2_ioctl_ops *ops,
 				struct file *file, void *fh, void *arg)
 {
 	struct video_device *vfd = video_devdata(file);
-	v4l2_std_id *id = arg, norm;
+	v4l2_std_id id = *(v4l2_std_id *)arg, norm;
 	int ret;
 
-	norm = (*id) & vfd->tvnorms;
+	norm = id & vfd->tvnorms;
 	if (vfd->tvnorms && !norm)	/* Check if std is supported */
 		return -EINVAL;
 
 	/* Calls the specific handler */
-	ret = ops->vidioc_s_std(file, fh, &norm);
+	ret = ops->vidioc_s_std(file, fh, norm);
 
 	/* Updates standard information */
 	if (ret >= 0)
@@ -1513,7 +1517,7 @@ static int v4l_g_parm(const struct v4l2_ioctl_ops *ops,
 	    p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
 		return -EINVAL;
 	p->parm.capture.readbuffers = 2;
-	if (ops->vidioc_g_std)
+	if (is_valid_ioctl(vfd, VIDIOC_G_STD) && ops->vidioc_g_std)
 		ret = ops->vidioc_g_std(file, fh, &std);
 	if (ret == 0)
 		v4l2_video_std_frame_period(std,
@@ -1787,15 +1791,38 @@ static int v4l_log_status(const struct v4l2_ioctl_ops *ops,
 	return ret;
 }
 
+static bool v4l_dbg_found_match(const struct v4l2_dbg_match *match,
+		struct v4l2_subdev *sd, int idx)
+{
+	if (match->type == V4L2_CHIP_MATCH_SUBDEV_IDX)
+		return match->addr == idx;
+	return !strcmp(match->name, sd->name);
+}
+
 static int v4l_dbg_g_register(const struct v4l2_ioctl_ops *ops,
 				struct file *file, void *fh, void *arg)
 {
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 	struct v4l2_dbg_register *p = arg;
+	struct video_device *vfd = video_devdata(file);
+	struct v4l2_subdev *sd;
+	int idx = 0;
 
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
-	return ops->vidioc_g_register(file, fh, p);
+	if (p->match.type == V4L2_CHIP_MATCH_SUBDEV_IDX ||
+	    p->match.type == V4L2_CHIP_MATCH_SUBDEV_NAME) {
+		if (vfd->v4l2_dev == NULL)
+			return -EINVAL;
+		v4l2_device_for_each_subdev(sd, vfd->v4l2_dev) {
+			if (v4l_dbg_found_match(&p->match, sd, idx++))
+				return v4l2_subdev_call(sd, core, g_register, p);
+		}
+		return -EINVAL;
+	}
+	if (ops->vidioc_g_register)
+		return ops->vidioc_g_register(file, fh, p);
+	return -EINVAL;
 #else
 	return -ENOTTY;
 #endif
@@ -1805,11 +1832,26 @@ static int v4l_dbg_s_register(const struct v4l2_ioctl_ops *ops,
 				struct file *file, void *fh, void *arg)
 {
 #ifdef CONFIG_VIDEO_ADV_DEBUG
-	struct v4l2_dbg_register *p = arg;
+	const struct v4l2_dbg_register *p = arg;
+	struct video_device *vfd = video_devdata(file);
+	struct v4l2_subdev *sd;
+	int idx = 0;
 
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
-	return ops->vidioc_s_register(file, fh, p);
+	if (p->match.type == V4L2_CHIP_MATCH_SUBDEV_IDX ||
+	    p->match.type == V4L2_CHIP_MATCH_SUBDEV_NAME) {
+		if (vfd->v4l2_dev == NULL)
+			return -EINVAL;
+		v4l2_device_for_each_subdev(sd, vfd->v4l2_dev) {
+			if (v4l_dbg_found_match(&p->match, sd, idx++))
+				return v4l2_subdev_call(sd, core, s_register, p);
+		}
+		return -EINVAL;
+	}
+	if (ops->vidioc_s_register)
+		return ops->vidioc_s_register(file, fh, p);
+	return -EINVAL;
 #else
 	return -ENOTTY;
 #endif
@@ -1822,9 +1864,61 @@ static int v4l_dbg_g_chip_ident(const struct v4l2_ioctl_ops *ops,
 
 	p->ident = V4L2_IDENT_NONE;
 	p->revision = 0;
+	if (p->match.type == V4L2_CHIP_MATCH_SUBDEV_NAME ||
+	    p->match.type == V4L2_CHIP_MATCH_SUBDEV_IDX)
+		return -EINVAL;
 	return ops->vidioc_g_chip_ident(file, fh, p);
 }
 
+static int v4l_dbg_g_chip_name(const struct v4l2_ioctl_ops *ops,
+				struct file *file, void *fh, void *arg)
+{
+	struct video_device *vfd = video_devdata(file);
+	struct v4l2_dbg_chip_name *p = arg;
+	struct v4l2_subdev *sd;
+	int idx = 0;
+
+	switch (p->match.type) {
+	case V4L2_CHIP_MATCH_BRIDGE:
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+		if (ops->vidioc_s_register)
+			p->flags |= V4L2_CHIP_FL_WRITABLE;
+		if (ops->vidioc_g_register)
+			p->flags |= V4L2_CHIP_FL_READABLE;
+#endif
+		if (ops->vidioc_g_chip_name)
+			return ops->vidioc_g_chip_name(file, fh, arg);
+		if (p->match.addr)
+			return -EINVAL;
+		if (vfd->v4l2_dev)
+			strlcpy(p->name, vfd->v4l2_dev->name, sizeof(p->name));
+		else if (vfd->parent)
+			strlcpy(p->name, vfd->parent->driver->name, sizeof(p->name));
+		else
+			strlcpy(p->name, "bridge", sizeof(p->name));
+		return 0;
+
+	case V4L2_CHIP_MATCH_SUBDEV_IDX:
+	case V4L2_CHIP_MATCH_SUBDEV_NAME:
+		if (vfd->v4l2_dev == NULL)
+			break;
+		v4l2_device_for_each_subdev(sd, vfd->v4l2_dev) {
+			if (v4l_dbg_found_match(&p->match, sd, idx++)) {
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+				if (sd->ops->core && sd->ops->core->s_register)
+					p->flags |= V4L2_CHIP_FL_WRITABLE;
+				if (sd->ops->core && sd->ops->core->g_register)
+					p->flags |= V4L2_CHIP_FL_READABLE;
+#endif
+				strlcpy(p->name, sd->name, sizeof(p->name));
+				return 0;
+			}
+		}
+		break;
+	}
+	return -EINVAL;
+}
+
 static int v4l_dqevent(const struct v4l2_ioctl_ops *ops,
 				struct file *file, void *fh, void *arg)
 {
@@ -1873,7 +1967,7 @@ static int v4l_enum_freq_bands(const struct v4l2_ioctl_ops *ops,
 		return -EINVAL;
 	if (ops->vidioc_enum_freq_bands)
 		return ops->vidioc_enum_freq_bands(file, fh, p);
-	if (ops->vidioc_g_tuner) {
+	if (is_valid_ioctl(vfd, VIDIOC_G_TUNER)) {
 		struct v4l2_tuner t = {
 			.index = p->tuner,
 			.type = type,
@@ -1891,7 +1985,7 @@ static int v4l_enum_freq_bands(const struct v4l2_ioctl_ops *ops,
 			V4L2_BAND_MODULATION_FM : V4L2_BAND_MODULATION_VSB;
 		return 0;
 	}
-	if (ops->vidioc_g_modulator) {
+	if (is_valid_ioctl(vfd, VIDIOC_G_MODULATOR)) {
 		struct v4l2_modulator m = {
 			.index = p->tuner,
 		};
@@ -2028,10 +2122,6 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = {
 	IOCTL_INFO_FNC(VIDIOC_DBG_G_REGISTER, v4l_dbg_g_register, v4l_print_dbg_register, 0),
 	IOCTL_INFO_FNC(VIDIOC_DBG_G_CHIP_IDENT, v4l_dbg_g_chip_ident, v4l_print_dbg_chip_ident, 0),
 	IOCTL_INFO_FNC(VIDIOC_S_HW_FREQ_SEEK, v4l_s_hw_freq_seek, v4l_print_hw_freq_seek, INFO_FL_PRIO),
-	IOCTL_INFO_STD(VIDIOC_ENUM_DV_PRESETS, vidioc_enum_dv_presets, v4l_print_dv_enum_presets, 0),
-	IOCTL_INFO_STD(VIDIOC_S_DV_PRESET, vidioc_s_dv_preset, v4l_print_dv_preset, INFO_FL_PRIO),
-	IOCTL_INFO_STD(VIDIOC_G_DV_PRESET, vidioc_g_dv_preset, v4l_print_dv_preset, 0),
-	IOCTL_INFO_STD(VIDIOC_QUERY_DV_PRESET, vidioc_query_dv_preset, v4l_print_dv_preset, 0),
 	IOCTL_INFO_STD(VIDIOC_S_DV_TIMINGS, vidioc_s_dv_timings, v4l_print_dv_timings, INFO_FL_PRIO),
 	IOCTL_INFO_STD(VIDIOC_G_DV_TIMINGS, vidioc_g_dv_timings, v4l_print_dv_timings, 0),
 	IOCTL_INFO_FNC(VIDIOC_DQEVENT, v4l_dqevent, v4l_print_event, 0),
@@ -2043,6 +2133,7 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = {
 	IOCTL_INFO_STD(VIDIOC_QUERY_DV_TIMINGS, vidioc_query_dv_timings, v4l_print_dv_timings, 0),
 	IOCTL_INFO_STD(VIDIOC_DV_TIMINGS_CAP, vidioc_dv_timings_cap, v4l_print_dv_timings_cap, INFO_FL_CLEAR(v4l2_dv_timings_cap, type)),
 	IOCTL_INFO_FNC(VIDIOC_ENUM_FREQ_BANDS, v4l_enum_freq_bands, v4l_print_freq_band, 0),
+	IOCTL_INFO_FNC(VIDIOC_DBG_G_CHIP_NAME, v4l_dbg_g_chip_name, v4l_print_dbg_chip_name, INFO_FL_CLEAR(v4l2_dbg_chip_name, match)),
 };
 #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
 
@@ -2147,11 +2238,6 @@ static long __video_do_ioctl(struct file *file,
 	}
 
 	write_only = _IOC_DIR(cmd) == _IOC_WRITE;
-	if (write_only && debug > V4L2_DEBUG_IOCTL) {
-		v4l_printk_ioctl(video_device_node_name(vfd), cmd);
-		pr_cont(": ");
-		info->debug(arg, write_only);
-	}
 	if (info->flags & INFO_FL_STD) {
 		typedef int (*vidioc_op)(struct file *file, void *fh, void *p);
 		const void *p = vfd->ioctl_ops;
@@ -2170,16 +2256,10 @@ static long __video_do_ioctl(struct file *file,
 
 done:
 	if (debug) {
-		if (write_only && debug > V4L2_DEBUG_IOCTL) {
-			if (ret < 0)
-				printk(KERN_DEBUG "%s: error %ld\n",
-					video_device_node_name(vfd), ret);
-			return ret;
-		}
 		v4l_printk_ioctl(video_device_node_name(vfd), cmd);
 		if (ret < 0)
-			pr_cont(": error %ld\n", ret);
-		else if (debug == V4L2_DEBUG_IOCTL)
+			pr_cont(": error %ld", ret);
+		if (debug == V4L2_DEBUG_IOCTL)
 			pr_cont("\n");
 		else if (_IOC_DIR(cmd) == _IOC_NONE)
 			info->debug(arg, write_only);
diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c
index da99cf7..66f599f 100644
--- a/drivers/media/v4l2-core/v4l2-mem2mem.c
+++ b/drivers/media/v4l2-core/v4l2-mem2mem.c
@@ -230,12 +230,15 @@ static void v4l2_m2m_try_schedule(struct v4l2_m2m_ctx *m2m_ctx)
 		dprintk("No input buffers available\n");
 		return;
 	}
+	spin_lock_irqsave(&m2m_ctx->cap_q_ctx.rdy_spinlock, flags);
 	if (list_empty(&m2m_ctx->cap_q_ctx.rdy_queue)) {
+		spin_unlock_irqrestore(&m2m_ctx->cap_q_ctx.rdy_spinlock, flags);
 		spin_unlock_irqrestore(&m2m_ctx->out_q_ctx.rdy_spinlock, flags);
 		spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags_job);
 		dprintk("No output buffers available\n");
 		return;
 	}
+	spin_unlock_irqrestore(&m2m_ctx->cap_q_ctx.rdy_spinlock, flags);
 	spin_unlock_irqrestore(&m2m_ctx->out_q_ctx.rdy_spinlock, flags);
 
 	if (m2m_dev->m2m_ops->job_ready
@@ -405,10 +408,35 @@ EXPORT_SYMBOL_GPL(v4l2_m2m_streamon);
 int v4l2_m2m_streamoff(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
 		       enum v4l2_buf_type type)
 {
-	struct vb2_queue *vq;
+	struct v4l2_m2m_dev *m2m_dev;
+	struct v4l2_m2m_queue_ctx *q_ctx;
+	unsigned long flags_job, flags;
+	int ret;
 
-	vq = v4l2_m2m_get_vq(m2m_ctx, type);
-	return vb2_streamoff(vq, type);
+	q_ctx = get_queue_ctx(m2m_ctx, type);
+	ret = vb2_streamoff(&q_ctx->q, type);
+	if (ret)
+		return ret;
+
+	m2m_dev = m2m_ctx->m2m_dev;
+	spin_lock_irqsave(&m2m_dev->job_spinlock, flags_job);
+	/* We should not be scheduled anymore, since we're dropping a queue. */
+	INIT_LIST_HEAD(&m2m_ctx->queue);
+	m2m_ctx->job_flags = 0;
+
+	spin_lock_irqsave(&q_ctx->rdy_spinlock, flags);
+	/* Drop queue, since streamoff returns device to the same state as after
+	 * calling reqbufs. */
+	INIT_LIST_HEAD(&q_ctx->rdy_queue);
+	spin_unlock_irqrestore(&q_ctx->rdy_spinlock, flags);
+
+	if (m2m_dev->curr_ctx == m2m_ctx) {
+		m2m_dev->curr_ctx = NULL;
+		wake_up(&m2m_ctx->finished);
+	}
+	spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags_job);
+
+	return 0;
 }
 EXPORT_SYMBOL_GPL(v4l2_m2m_streamoff);
 
diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c
index db1235d..02bb5e7 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -57,7 +57,7 @@ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
 	/* Allocate memory for all planes in this buffer */
 	for (plane = 0; plane < vb->num_planes; ++plane) {
 		mem_priv = call_memop(q, alloc, q->alloc_ctx[plane],
-				      q->plane_sizes[plane]);
+				      q->plane_sizes[plane], q->gfp_flags);
 		if (IS_ERR_OR_NULL(mem_priv))
 			goto free;
 
@@ -403,7 +403,7 @@ static void __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
 	 * Clear any buffer state related flags.
 	 */
 	b->flags &= ~V4L2_BUFFER_MASK_FLAGS;
-	b->flags |= V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+	b->flags |= q->timestamp_type;
 
 	switch (vb->state) {
 	case VB2_BUF_STATE_QUEUED:
@@ -855,7 +855,7 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state)
 		return;
 
 	dprintk(4, "Done processing on buffer %d, state: %d\n",
-			vb->v4l2_buf.index, vb->state);
+			vb->v4l2_buf.index, state);
 
 	/* sync buffers */
 	for (plane = 0; plane < vb->num_planes; ++plane)
@@ -2039,9 +2039,13 @@ int vb2_queue_init(struct vb2_queue *q)
 	    WARN_ON(!q->type)		  ||
 	    WARN_ON(!q->io_modes)	  ||
 	    WARN_ON(!q->ops->queue_setup) ||
-	    WARN_ON(!q->ops->buf_queue))
+	    WARN_ON(!q->ops->buf_queue)   ||
+	    WARN_ON(q->timestamp_type & ~V4L2_BUF_FLAG_TIMESTAMP_MASK))
 		return -EINVAL;
 
+	/* Warn that the driver should choose an appropriate timestamp type */
+	WARN_ON(q->timestamp_type == V4L2_BUF_FLAG_TIMESTAMP_UNKNOWN);
+
 	INIT_LIST_HEAD(&q->queued_list);
 	INIT_LIST_HEAD(&q->done_list);
 	spin_lock_init(&q->done_lock);
diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c b/drivers/media/v4l2-core/videobuf2-dma-contig.c
index 10beaee..ae35d25 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-contig.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c
@@ -152,7 +152,7 @@ static void vb2_dc_put(void *buf_priv)
 	kfree(buf);
 }
 
-static void *vb2_dc_alloc(void *alloc_ctx, unsigned long size)
+static void *vb2_dc_alloc(void *alloc_ctx, unsigned long size, gfp_t gfp_flags)
 {
 	struct vb2_dc_conf *conf = alloc_ctx;
 	struct device *dev = conf->dev;
@@ -165,7 +165,8 @@ static void *vb2_dc_alloc(void *alloc_ctx, unsigned long size)
 	/* align image size to PAGE_SIZE */
 	size = PAGE_ALIGN(size);
 
-	buf->vaddr = dma_alloc_coherent(dev, size, &buf->dma_addr, GFP_KERNEL);
+	buf->vaddr = dma_alloc_coherent(dev, size, &buf->dma_addr,
+						GFP_KERNEL | gfp_flags);
 	if (!buf->vaddr) {
 		dev_err(dev, "dma_alloc_coherent of size %ld failed\n", size);
 		kfree(buf);
diff --git a/drivers/media/v4l2-core/videobuf2-dma-sg.c b/drivers/media/v4l2-core/videobuf2-dma-sg.c
index 25c3b36..59522b2 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-sg.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-sg.c
@@ -21,6 +21,15 @@
 #include <media/videobuf2-memops.h>
 #include <media/videobuf2-dma-sg.h>
 
+static int debug;
+module_param(debug, int, 0644);
+
+#define dprintk(level, fmt, arg...)					\
+	do {								\
+		if (debug >= level)					\
+			printk(KERN_DEBUG "vb2-dma-sg: " fmt, ## arg);	\
+	} while (0)
+
 struct vb2_dma_sg_buf {
 	void				*vaddr;
 	struct page			**pages;
@@ -33,7 +42,7 @@ struct vb2_dma_sg_buf {
 
 static void vb2_dma_sg_put(void *buf_priv);
 
-static void *vb2_dma_sg_alloc(void *alloc_ctx, unsigned long size)
+static void *vb2_dma_sg_alloc(void *alloc_ctx, unsigned long size, gfp_t gfp_flags)
 {
 	struct vb2_dma_sg_buf *buf;
 	int i;
@@ -60,7 +69,8 @@ static void *vb2_dma_sg_alloc(void *alloc_ctx, unsigned long size)
 		goto fail_pages_array_alloc;
 
 	for (i = 0; i < buf->sg_desc.num_pages; ++i) {
-		buf->pages[i] = alloc_page(GFP_KERNEL | __GFP_ZERO | __GFP_NOWARN);
+		buf->pages[i] = alloc_page(GFP_KERNEL | __GFP_ZERO |
+					   __GFP_NOWARN | gfp_flags);
 		if (NULL == buf->pages[i])
 			goto fail_pages_alloc;
 		sg_set_page(&buf->sg_desc.sglist[i],
@@ -73,7 +83,7 @@ static void *vb2_dma_sg_alloc(void *alloc_ctx, unsigned long size)
 
 	atomic_inc(&buf->refcount);
 
-	printk(KERN_DEBUG "%s: Allocated buffer of %d pages\n",
+	dprintk(1, "%s: Allocated buffer of %d pages\n",
 		__func__, buf->sg_desc.num_pages);
 	return buf;
 
@@ -96,7 +106,7 @@ static void vb2_dma_sg_put(void *buf_priv)
 	int i = buf->sg_desc.num_pages;
 
 	if (atomic_dec_and_test(&buf->refcount)) {
-		printk(KERN_DEBUG "%s: Freeing buffer of %d pages\n", __func__,
+		dprintk(1, "%s: Freeing buffer of %d pages\n", __func__,
 			buf->sg_desc.num_pages);
 		if (buf->vaddr)
 			vm_unmap_ram(buf->vaddr, buf->sg_desc.num_pages);
@@ -162,7 +172,7 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
 	return buf;
 
 userptr_fail_get_user_pages:
-	printk(KERN_DEBUG "get_user_pages requested/got: %d/%d]\n",
+	dprintk(1, "get_user_pages requested/got: %d/%d]\n",
 	       num_pages_from_user, buf->sg_desc.num_pages);
 	while (--num_pages_from_user >= 0)
 		put_page(buf->pages[num_pages_from_user]);
@@ -185,7 +195,7 @@ static void vb2_dma_sg_put_userptr(void *buf_priv)
 	struct vb2_dma_sg_buf *buf = buf_priv;
 	int i = buf->sg_desc.num_pages;
 
-	printk(KERN_DEBUG "%s: Releasing userspace buffer of %d pages\n",
+	dprintk(1, "%s: Releasing userspace buffer of %d pages\n",
 	       __func__, buf->sg_desc.num_pages);
 	if (buf->vaddr)
 		vm_unmap_ram(buf->vaddr, buf->sg_desc.num_pages);
diff --git a/drivers/media/v4l2-core/videobuf2-vmalloc.c b/drivers/media/v4l2-core/videobuf2-vmalloc.c
index a47fd4f..313d977 100644
--- a/drivers/media/v4l2-core/videobuf2-vmalloc.c
+++ b/drivers/media/v4l2-core/videobuf2-vmalloc.c
@@ -35,11 +35,11 @@ struct vb2_vmalloc_buf {
 
 static void vb2_vmalloc_put(void *buf_priv);
 
-static void *vb2_vmalloc_alloc(void *alloc_ctx, unsigned long size)
+static void *vb2_vmalloc_alloc(void *alloc_ctx, unsigned long size, gfp_t gfp_flags)
 {
 	struct vb2_vmalloc_buf *buf;
 
-	buf = kzalloc(sizeof(*buf), GFP_KERNEL);
+	buf = kzalloc(sizeof(*buf), GFP_KERNEL | gfp_flags);
 	if (!buf)
 		return NULL;
 
diff --git a/drivers/memory/emif.c b/drivers/memory/emif.c
index df08736..cadf1cc 100644
--- a/drivers/memory/emif.c
+++ b/drivers/memory/emif.c
@@ -25,6 +25,7 @@
 #include <linux/module.h>
 #include <linux/list.h>
 #include <linux/spinlock.h>
+#include <linux/pm.h>
 #include <memory/jedec_ddr.h>
 #include "emif.h"
 #include "of_memory.h"
@@ -256,6 +257,41 @@ static void set_lpmode(struct emif_data *emif, u8 lpmode)
 	u32 temp;
 	void __iomem *base = emif->base;
 
+	/*
+	 * Workaround for errata i743 - LPDDR2 Power-Down State is Not
+	 * Efficient
+	 *
+	 * i743 DESCRIPTION:
+	 * The EMIF supports power-down state for low power. The EMIF
+	 * automatically puts the SDRAM into power-down after the memory is
+	 * not accessed for a defined number of cycles and the
+	 * EMIF_PWR_MGMT_CTRL[10:8] REG_LP_MODE bit field is set to 0x4.
+	 * As the EMIF supports automatic output impedance calibration, a ZQ
+	 * calibration long command is issued every time it exits active
+	 * power-down and precharge power-down modes. The EMIF waits and
+	 * blocks any other command during this calibration.
+	 * The EMIF does not allow selective disabling of ZQ calibration upon
+	 * exit of power-down mode. Due to very short periods of power-down
+	 * cycles, ZQ calibration overhead creates bandwidth issues and
+	 * increases overall system power consumption. On the other hand,
+	 * issuing ZQ calibration long commands when exiting self-refresh is
+	 * still required.
+	 *
+	 * WORKAROUND
+	 * Because there is no power consumption benefit of the power-down due
+	 * to the calibration and there is a performance risk, the guideline
+	 * is to not allow power-down state and, therefore, to not have set
+	 * the EMIF_PWR_MGMT_CTRL[10:8] REG_LP_MODE bit field to 0x4.
+	 */
+	if ((emif->plat_data->ip_rev == EMIF_4D) &&
+	    (EMIF_LP_MODE_PWR_DN == lpmode)) {
+		WARN_ONCE(1,
+			  "REG_LP_MODE = LP_MODE_PWR_DN(4) is prohibited by"
+			  "erratum i743 switch to LP_MODE_SELF_REFRESH(2)\n");
+		/* rollback LP_MODE to Self-refresh mode */
+		lpmode = EMIF_LP_MODE_SELF_REFRESH;
+	}
+
 	temp = readl(base + EMIF_POWER_MANAGEMENT_CONTROL);
 	temp &= ~LP_MODE_MASK;
 	temp |= (lpmode << LP_MODE_SHIFT);
@@ -715,6 +751,8 @@ static u32 get_pwr_mgmt_ctrl(u32 freq, struct emif_data *emif, u32 ip_rev)
 	u32 timeout_perf	= EMIF_LP_MODE_TIMEOUT_PERFORMANCE;
 	u32 timeout_pwr		= EMIF_LP_MODE_TIMEOUT_POWER;
 	u32 freq_threshold	= EMIF_LP_MODE_FREQ_THRESHOLD;
+	u32 mask;
+	u8 shift;
 
 	struct emif_custom_configs *cust_cfgs = emif->plat_data->custom_configs;
 
@@ -728,37 +766,59 @@ static u32 get_pwr_mgmt_ctrl(u32 freq, struct emif_data *emif, u32 ip_rev)
 	/* Timeout based on DDR frequency */
 	timeout = freq >= freq_threshold ? timeout_perf : timeout_pwr;
 
-	/* The value to be set in register is "log2(timeout) - 3" */
+	/*
+	 * The value to be set in register is "log2(timeout) - 3"
+	 * if timeout < 16 load 0 in register
+	 * if timeout is not a power of 2, round to next highest power of 2
+	 */
 	if (timeout < 16) {
 		timeout = 0;
 	} else {
-		timeout = __fls(timeout) - 3;
 		if (timeout & (timeout - 1))
-			timeout++;
+			timeout <<= 1;
+		timeout = __fls(timeout) - 3;
 	}
 
 	switch (lpmode) {
 	case EMIF_LP_MODE_CLOCK_STOP:
-		pwr_mgmt_ctrl = (timeout << CS_TIM_SHIFT) |
-					SR_TIM_MASK | PD_TIM_MASK;
+		shift = CS_TIM_SHIFT;
+		mask = CS_TIM_MASK;
 		break;
 	case EMIF_LP_MODE_SELF_REFRESH:
 		/* Workaround for errata i735 */
 		if (timeout < 6)
 			timeout = 6;
 
-		pwr_mgmt_ctrl = (timeout << SR_TIM_SHIFT) |
-					CS_TIM_MASK | PD_TIM_MASK;
+		shift = SR_TIM_SHIFT;
+		mask = SR_TIM_MASK;
 		break;
 	case EMIF_LP_MODE_PWR_DN:
-		pwr_mgmt_ctrl = (timeout << PD_TIM_SHIFT) |
-					CS_TIM_MASK | SR_TIM_MASK;
+		shift = PD_TIM_SHIFT;
+		mask = PD_TIM_MASK;
 		break;
 	case EMIF_LP_MODE_DISABLE:
 	default:
-		pwr_mgmt_ctrl = CS_TIM_MASK |
-					PD_TIM_MASK | SR_TIM_MASK;
+		mask = 0;
+		shift = 0;
+		break;
 	}
+	/* Round to maximum in case of overflow, BUT warn! */
+	if (lpmode != EMIF_LP_MODE_DISABLE && timeout > mask >> shift) {
+		pr_err("TIMEOUT Overflow - lpmode=%d perf=%d pwr=%d freq=%d\n",
+		       lpmode,
+		       timeout_perf,
+		       timeout_pwr,
+		       freq_threshold);
+		WARN(1, "timeout=0x%02x greater than 0x%02x. Using max\n",
+		     timeout, mask >> shift);
+		timeout = mask >> shift;
+	}
+
+	/* Setup required timing */
+	pwr_mgmt_ctrl = (timeout << shift) & mask;
+	/* setup a default mask for rest of the modes */
+	pwr_mgmt_ctrl |= (SR_TIM_MASK | CS_TIM_MASK | PD_TIM_MASK) &
+			  ~mask;
 
 	/* No CS_TIM in EMIF_4D5 */
 	if (ip_rev == EMIF_4D5)
@@ -815,6 +875,8 @@ static void setup_registers(struct emif_data *emif, struct emif_regs *regs)
 
 	writel(regs->sdram_tim2_shdw, base + EMIF_SDRAM_TIMING_2_SHDW);
 	writel(regs->phy_ctrl_1_shdw, base + EMIF_DDR_PHY_CTRL_1_SHDW);
+	writel(regs->pwr_mgmt_ctrl_shdw,
+	       base + EMIF_POWER_MANAGEMENT_CTRL_SHDW);
 
 	/* Settings specific for EMIF4D5 */
 	if (emif->plat_data->ip_rev != EMIF_4D5)
@@ -892,6 +954,7 @@ static irqreturn_t handle_temp_alert(void __iomem *base, struct emif_data *emif)
 {
 	u32		old_temp_level;
 	irqreturn_t	ret = IRQ_HANDLED;
+	struct emif_custom_configs *custom_configs;
 
 	spin_lock_irqsave(&emif_lock, irq_state);
 	old_temp_level = emif->temperature_level;
@@ -904,6 +967,29 @@ static irqreturn_t handle_temp_alert(void __iomem *base, struct emif_data *emif)
 		goto out;
 	}
 
+	custom_configs = emif->plat_data->custom_configs;
+
+	/*
+	 * IF we detect higher than "nominal rating" from DDR sensor
+	 * on an unsupported DDR part, shutdown system
+	 */
+	if (custom_configs && !(custom_configs->mask &
+				EMIF_CUSTOM_CONFIG_EXTENDED_TEMP_PART)) {
+		if (emif->temperature_level >= SDRAM_TEMP_HIGH_DERATE_REFRESH) {
+			dev_err(emif->dev,
+				"%s:NOT Extended temperature capable memory."
+				"Converting MR4=0x%02x as shutdown event\n",
+				__func__, emif->temperature_level);
+			/*
+			 * Temperature far too high - do kernel_power_off()
+			 * from thread context
+			 */
+			emif->temperature_level = SDRAM_TEMP_VERY_HIGH_SHUTDOWN;
+			ret = IRQ_WAKE_THREAD;
+			goto out;
+		}
+	}
+
 	if (emif->temperature_level < old_temp_level ||
 		emif->temperature_level == SDRAM_TEMP_VERY_HIGH_SHUTDOWN) {
 		/*
@@ -965,7 +1051,14 @@ static irqreturn_t emif_threaded_isr(int irq, void *dev_id)
 
 	if (emif->temperature_level == SDRAM_TEMP_VERY_HIGH_SHUTDOWN) {
 		dev_emerg(emif->dev, "SDRAM temperature exceeds operating limit.. Needs shut down!!!\n");
-		kernel_power_off();
+
+		/* If we have Power OFF ability, use it, else try restarting */
+		if (pm_power_off) {
+			kernel_power_off();
+		} else {
+			WARN(1, "FIXME: NO pm_power_off!!! trying restart\n");
+			kernel_restart("SDRAM Over-temp Emergency restart");
+		}
 		return IRQ_HANDLED;
 	}
 
@@ -1170,7 +1263,7 @@ static void __init_or_module of_get_custom_configs(struct device_node *np_emif,
 {
 	struct emif_custom_configs	*cust_cfgs = NULL;
 	int				len;
-	const int			*lpmode, *poll_intvl;
+	const __be32			*lpmode, *poll_intvl;
 
 	lpmode = of_get_property(np_emif, "low-power-mode", &len);
 	poll_intvl = of_get_property(np_emif, "temp-alert-poll-interval", &len);
@@ -1184,7 +1277,7 @@ static void __init_or_module of_get_custom_configs(struct device_node *np_emif,
 
 	if (lpmode) {
 		cust_cfgs->mask |= EMIF_CUSTOM_CONFIG_LPMODE;
-		cust_cfgs->lpmode = *lpmode;
+		cust_cfgs->lpmode = be32_to_cpup(lpmode);
 		of_property_read_u32(np_emif,
 				"low-power-mode-timeout-performance",
 				&cust_cfgs->lpmode_timeout_performance);
@@ -1199,9 +1292,13 @@ static void __init_or_module of_get_custom_configs(struct device_node *np_emif,
 	if (poll_intvl) {
 		cust_cfgs->mask |=
 				EMIF_CUSTOM_CONFIG_TEMP_ALERT_POLL_INTERVAL;
-		cust_cfgs->temp_alert_poll_interval_ms = *poll_intvl;
+		cust_cfgs->temp_alert_poll_interval_ms =
+						be32_to_cpup(poll_intvl);
 	}
 
+	if (of_find_property(np_emif, "extended-temp-part", &len))
+		cust_cfgs->mask |= EMIF_CUSTOM_CONFIG_EXTENDED_TEMP_PART;
+
 	if (!is_custom_config_valid(cust_cfgs, emif->dev)) {
 		devm_kfree(emif->dev, cust_cfgs);
 		return;
@@ -1407,7 +1504,7 @@ static struct emif_data *__init_or_module get_device_details(
 	if (pd->timings) {
 		temp = devm_kzalloc(dev, size, GFP_KERNEL);
 		if (temp) {
-			memcpy(temp, pd->timings, sizeof(*pd->timings));
+			memcpy(temp, pd->timings, size);
 			pd->timings = temp;
 		} else {
 			dev_warn(dev, "%s:%d: allocation error\n", __func__,
@@ -1841,18 +1938,8 @@ static struct platform_driver emif_driver = {
 	},
 };
 
-static int __init_or_module emif_register(void)
-{
-	return platform_driver_probe(&emif_driver, emif_probe);
-}
-
-static void __exit emif_unregister(void)
-{
-	platform_driver_unregister(&emif_driver);
-}
+module_platform_driver_probe(emif_driver, emif_probe);
 
-module_init(emif_register);
-module_exit(emif_unregister);
 MODULE_DESCRIPTION("TI EMIF SDRAM Controller Driver");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:emif");
diff --git a/drivers/memory/tegra30-mc.c b/drivers/memory/tegra30-mc.c
index 0b97598..f4ae074 100644
--- a/drivers/memory/tegra30-mc.c
+++ b/drivers/memory/tegra30-mc.c
@@ -268,6 +268,7 @@ static const u32 tegra30_mc_ctx[] = {
 	MC_INTMASK,
 };
 
+#ifdef CONFIG_PM
 static int tegra30_mc_suspend(struct device *dev)
 {
 	int i;
@@ -291,6 +292,7 @@ static int tegra30_mc_resume(struct device *dev)
 	mc_readl(mc, MC_TIMING_CONTROL);
 	return 0;
 }
+#endif
 
 static UNIVERSAL_DEV_PM_OPS(tegra30_mc_pm,
 			    tegra30_mc_suspend,
diff --git a/drivers/memstick/host/r592.c b/drivers/memstick/host/r592.c
index a7c5b31..9718661 100644
--- a/drivers/memstick/host/r592.c
+++ b/drivers/memstick/host/r592.c
@@ -847,7 +847,7 @@ static void r592_remove(struct pci_dev *pdev)
 			dev->dummy_dma_page_physical_address);
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int r592_suspend(struct device *core_dev)
 {
 	struct pci_dev *pdev = to_pci_dev(core_dev);
@@ -870,10 +870,10 @@ static int r592_resume(struct device *core_dev)
 	r592_update_card_detect(dev);
 	return 0;
 }
-
-SIMPLE_DEV_PM_OPS(r592_pm_ops, r592_suspend, r592_resume);
 #endif
 
+static SIMPLE_DEV_PM_OPS(r592_pm_ops, r592_suspend, r592_resume);
+
 MODULE_DEVICE_TABLE(pci, r592_pci_id_tbl);
 
 static struct pci_driver r852_pci_driver = {
@@ -881,9 +881,7 @@ static struct pci_driver r852_pci_driver = {
 	.id_table	= r592_pci_id_tbl,
 	.probe		= r592_probe,
 	.remove		= r592_remove,
-#ifdef CONFIG_PM
 	.driver.pm	= &r592_pm_ops,
-#endif
 };
 
 static __init int r592_module_init(void)
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index fb69baa..767ff4d 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -6656,7 +6656,7 @@ static int mpt_summary_proc_show(struct seq_file *m, void *v)
 
 static int mpt_summary_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, mpt_summary_proc_show, PDE(inode)->data);
+	return single_open(file, mpt_summary_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations mpt_summary_proc_fops = {
@@ -6805,7 +6805,7 @@ static int mpt_iocinfo_proc_show(struct seq_file *m, void *v)
 
 static int mpt_iocinfo_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, mpt_iocinfo_proc_show, PDE(inode)->data);
+	return single_open(file, mpt_iocinfo_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations mpt_iocinfo_proc_fops = {
diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c
index c13cd9b..fd75108 100644
--- a/drivers/message/fusion/mptfc.c
+++ b/drivers/message/fusion/mptfc.c
@@ -109,7 +109,7 @@ static int mptfc_host_reset(struct scsi_cmnd *SCpnt);
 static struct scsi_host_template mptfc_driver_template = {
 	.module				= THIS_MODULE,
 	.proc_name			= "mptfc",
-	.proc_info			= mptscsih_proc_info,
+	.show_info			= mptscsih_show_info,
 	.name				= "MPT FC Host",
 	.info				= mptscsih_info,
 	.queuecommand			= mptfc_qcmd,
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
index fa43c39..dd239bd 100644
--- a/drivers/message/fusion/mptsas.c
+++ b/drivers/message/fusion/mptsas.c
@@ -1977,7 +1977,7 @@ done:
 static struct scsi_host_template mptsas_driver_template = {
 	.module				= THIS_MODULE,
 	.proc_name			= "mptsas",
-	.proc_info			= mptscsih_proc_info,
+	.show_info			= mptscsih_show_info,
 	.name				= "MPT SAS Host",
 	.info				= mptscsih_info,
 	.queuecommand			= mptsas_qcmd,
@@ -2235,10 +2235,10 @@ static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
 	}
 
 	/* do we need to support multiple segments? */
-	if (req->bio->bi_vcnt > 1 || rsp->bio->bi_vcnt > 1) {
+	if (bio_segments(req->bio) > 1 || bio_segments(rsp->bio) > 1) {
 		printk(MYIOC_s_ERR_FMT "%s: multiple segments req %u %u, rsp %u %u\n",
-		    ioc->name, __func__, req->bio->bi_vcnt, blk_rq_bytes(req),
-		    rsp->bio->bi_vcnt, blk_rq_bytes(rsp));
+		    ioc->name, __func__, bio_segments(req->bio), blk_rq_bytes(req),
+		    bio_segments(rsp->bio), blk_rq_bytes(rsp));
 		return -EINVAL;
 	}
 
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index 164afa7..727819c 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -1284,101 +1284,17 @@ mptscsih_info(struct Scsi_Host *SChost)
 	return h->info_kbuf;
 }
 
-struct info_str {
-	char *buffer;
-	int   length;
-	int   offset;
-	int   pos;
-};
-
-static void
-mptscsih_copy_mem_info(struct info_str *info, char *data, int len)
-{
-	if (info->pos + len > info->length)
-		len = info->length - info->pos;
-
-	if (info->pos + len < info->offset) {
-		info->pos += len;
-		return;
-	}
-
-	if (info->pos < info->offset) {
-	        data += (info->offset - info->pos);
-	        len  -= (info->offset - info->pos);
-	}
-
-	if (len > 0) {
-                memcpy(info->buffer + info->pos, data, len);
-                info->pos += len;
-	}
-}
-
-static int
-mptscsih_copy_info(struct info_str *info, char *fmt, ...)
-{
-	va_list args;
-	char buf[81];
-	int len;
-
-	va_start(args, fmt);
-	len = vsprintf(buf, fmt, args);
-	va_end(args);
-
-	mptscsih_copy_mem_info(info, buf, len);
-	return len;
-}
-
-static int
-mptscsih_host_info(MPT_ADAPTER *ioc, char *pbuf, off_t offset, int len)
-{
-	struct info_str info;
-
-	info.buffer	= pbuf;
-	info.length	= len;
-	info.offset	= offset;
-	info.pos	= 0;
-
-	mptscsih_copy_info(&info, "%s: %s, ", ioc->name, ioc->prod_name);
-	mptscsih_copy_info(&info, "%s%08xh, ", MPT_FW_REV_MAGIC_ID_STRING, ioc->facts.FWVersion.Word);
-	mptscsih_copy_info(&info, "Ports=%d, ", ioc->facts.NumberOfPorts);
-	mptscsih_copy_info(&info, "MaxQ=%d\n", ioc->req_depth);
-
-	return ((info.pos > info.offset) ? info.pos - info.offset : 0);
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/**
- *	mptscsih_proc_info - Return information about MPT adapter
- * 	@host:   scsi host struct
- * 	@buffer: if write, user data; if read, buffer for user
- *	@start: returns the buffer address
- * 	@offset: if write, 0; if read, the current offset into the buffer from
- * 		 the previous read.
- * 	@length: if write, return length;
- *	@func:   write = 1; read = 0
- *
- *	(linux scsi_host_template.info routine)
- */
-int
-mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
-			int length, int func)
+int mptscsih_show_info(struct seq_file *m, struct Scsi_Host *host)
 {
 	MPT_SCSI_HOST	*hd = shost_priv(host);
 	MPT_ADAPTER	*ioc = hd->ioc;
-	int size = 0;
 
-	if (func) {
-		/*
-		 * write is not supported
-		 */
-	} else {
-		if (start)
-			*start = buffer;
-
-		size = mptscsih_host_info(ioc, buffer, offset, length);
-	}
+	seq_printf(m, "%s: %s, ", ioc->name, ioc->prod_name);
+	seq_printf(m, "%s%08xh, ", MPT_FW_REV_MAGIC_ID_STRING, ioc->facts.FWVersion.Word);
+	seq_printf(m, "Ports=%d, ", ioc->facts.NumberOfPorts);
+	seq_printf(m, "MaxQ=%d\n", ioc->req_depth);
 
-	return size;
+	return 0;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -3348,7 +3264,7 @@ EXPORT_SYMBOL(mptscsih_shutdown);
 EXPORT_SYMBOL(mptscsih_suspend);
 EXPORT_SYMBOL(mptscsih_resume);
 #endif
-EXPORT_SYMBOL(mptscsih_proc_info);
+EXPORT_SYMBOL(mptscsih_show_info);
 EXPORT_SYMBOL(mptscsih_info);
 EXPORT_SYMBOL(mptscsih_qcmd);
 EXPORT_SYMBOL(mptscsih_slave_destroy);
diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h
index 43e75ff..83f5031 100644
--- a/drivers/message/fusion/mptscsih.h
+++ b/drivers/message/fusion/mptscsih.h
@@ -111,7 +111,7 @@ extern void mptscsih_shutdown(struct pci_dev *);
 extern int mptscsih_suspend(struct pci_dev *pdev, pm_message_t state);
 extern int mptscsih_resume(struct pci_dev *pdev);
 #endif
-extern int mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, int length, int func);
+extern int mptscsih_show_info(struct seq_file *, struct Scsi_Host *);
 extern const char * mptscsih_info(struct Scsi_Host *SChost);
 extern int mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *));
 extern int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel,
diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c
index c3aabde..5653e50 100644
--- a/drivers/message/fusion/mptspi.c
+++ b/drivers/message/fusion/mptspi.c
@@ -831,7 +831,7 @@ static void mptspi_slave_destroy(struct scsi_device *sdev)
 static struct scsi_host_template mptspi_driver_template = {
 	.module				= THIS_MODULE,
 	.proc_name			= "mptspi",
-	.proc_info			= mptscsih_proc_info,
+	.show_info			= mptscsih_show_info,
 	.name				= "MPT SPI Host",
 	.info				= mptscsih_info,
 	.queuecommand			= mptspi_qcmd,
diff --git a/drivers/message/i2o/i2o_config.c b/drivers/message/i2o/i2o_config.c
index 5451bef..a60c188 100644
--- a/drivers/message/i2o/i2o_config.c
+++ b/drivers/message/i2o/i2o_config.c
@@ -687,6 +687,11 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd,
 		}
 		size = size >> 16;
 		size *= 4;
+		if (size > sizeof(rmsg)) {
+			rcode = -EINVAL;
+			goto sg_list_cleanup;
+		}
+
 		/* Copy in the user's I2O command */
 		if (copy_from_user(rmsg, user_msg, size)) {
 			rcode = -EFAULT;
@@ -922,6 +927,11 @@ static int i2o_cfg_passthru(unsigned long arg)
 		}
 		size = size >> 16;
 		size *= 4;
+		if (size > sizeof(rmsg)) {
+			rcode = -EFAULT;
+			goto sg_list_cleanup;
+		}
+
 		/* Copy in the user's I2O command */
 		if (copy_from_user(rmsg, user_msg, size)) {
 			rcode = -EFAULT;
diff --git a/drivers/message/i2o/i2o_proc.c b/drivers/message/i2o/i2o_proc.c
index 8001aa6..70a840f 100644
--- a/drivers/message/i2o/i2o_proc.c
+++ b/drivers/message/i2o/i2o_proc.c
@@ -1599,98 +1599,98 @@ static int i2o_seq_show_sensors(struct seq_file *seq, void *v)
 
 static int i2o_seq_open_hrt(struct inode *inode, struct file *file)
 {
-	return single_open(file, i2o_seq_show_hrt, PDE(inode)->data);
+	return single_open(file, i2o_seq_show_hrt, PDE_DATA(inode));
 };
 
 static int i2o_seq_open_lct(struct inode *inode, struct file *file)
 {
-	return single_open(file, i2o_seq_show_lct, PDE(inode)->data);
+	return single_open(file, i2o_seq_show_lct, PDE_DATA(inode));
 };
 
 static int i2o_seq_open_status(struct inode *inode, struct file *file)
 {
-	return single_open(file, i2o_seq_show_status, PDE(inode)->data);
+	return single_open(file, i2o_seq_show_status, PDE_DATA(inode));
 };
 
 static int i2o_seq_open_hw(struct inode *inode, struct file *file)
 {
-	return single_open(file, i2o_seq_show_hw, PDE(inode)->data);
+	return single_open(file, i2o_seq_show_hw, PDE_DATA(inode));
 };
 
 static int i2o_seq_open_ddm_table(struct inode *inode, struct file *file)
 {
-	return single_open(file, i2o_seq_show_ddm_table, PDE(inode)->data);
+	return single_open(file, i2o_seq_show_ddm_table, PDE_DATA(inode));
 };
 
 static int i2o_seq_open_driver_store(struct inode *inode, struct file *file)
 {
-	return single_open(file, i2o_seq_show_driver_store, PDE(inode)->data);
+	return single_open(file, i2o_seq_show_driver_store, PDE_DATA(inode));
 };
 
 static int i2o_seq_open_drivers_stored(struct inode *inode, struct file *file)
 {
-	return single_open(file, i2o_seq_show_drivers_stored, PDE(inode)->data);
+	return single_open(file, i2o_seq_show_drivers_stored, PDE_DATA(inode));
 };
 
 static int i2o_seq_open_groups(struct inode *inode, struct file *file)
 {
-	return single_open(file, i2o_seq_show_groups, PDE(inode)->data);
+	return single_open(file, i2o_seq_show_groups, PDE_DATA(inode));
 };
 
 static int i2o_seq_open_phys_device(struct inode *inode, struct file *file)
 {
-	return single_open(file, i2o_seq_show_phys_device, PDE(inode)->data);
+	return single_open(file, i2o_seq_show_phys_device, PDE_DATA(inode));
 };
 
 static int i2o_seq_open_claimed(struct inode *inode, struct file *file)
 {
-	return single_open(file, i2o_seq_show_claimed, PDE(inode)->data);
+	return single_open(file, i2o_seq_show_claimed, PDE_DATA(inode));
 };
 
 static int i2o_seq_open_users(struct inode *inode, struct file *file)
 {
-	return single_open(file, i2o_seq_show_users, PDE(inode)->data);
+	return single_open(file, i2o_seq_show_users, PDE_DATA(inode));
 };
 
 static int i2o_seq_open_priv_msgs(struct inode *inode, struct file *file)
 {
-	return single_open(file, i2o_seq_show_priv_msgs, PDE(inode)->data);
+	return single_open(file, i2o_seq_show_priv_msgs, PDE_DATA(inode));
 };
 
 static int i2o_seq_open_authorized_users(struct inode *inode, struct file *file)
 {
 	return single_open(file, i2o_seq_show_authorized_users,
-			   PDE(inode)->data);
+			   PDE_DATA(inode));
 };
 
 static int i2o_seq_open_dev_identity(struct inode *inode, struct file *file)
 {
-	return single_open(file, i2o_seq_show_dev_identity, PDE(inode)->data);
+	return single_open(file, i2o_seq_show_dev_identity, PDE_DATA(inode));
 };
 
 static int i2o_seq_open_ddm_identity(struct inode *inode, struct file *file)
 {
-	return single_open(file, i2o_seq_show_ddm_identity, PDE(inode)->data);
+	return single_open(file, i2o_seq_show_ddm_identity, PDE_DATA(inode));
 };
 
 static int i2o_seq_open_uinfo(struct inode *inode, struct file *file)
 {
-	return single_open(file, i2o_seq_show_uinfo, PDE(inode)->data);
+	return single_open(file, i2o_seq_show_uinfo, PDE_DATA(inode));
 };
 
 static int i2o_seq_open_sgl_limits(struct inode *inode, struct file *file)
 {
-	return single_open(file, i2o_seq_show_sgl_limits, PDE(inode)->data);
+	return single_open(file, i2o_seq_show_sgl_limits, PDE_DATA(inode));
 };
 
 static int i2o_seq_open_sensors(struct inode *inode, struct file *file)
 {
-	return single_open(file, i2o_seq_show_sensors, PDE(inode)->data);
+	return single_open(file, i2o_seq_show_sensors, PDE_DATA(inode));
 };
 
 static int i2o_seq_open_dev_name(struct inode *inode, struct file *file)
 {
-	return single_open(file, i2o_seq_show_dev_name, PDE(inode)->data);
+	return single_open(file, i2o_seq_show_dev_name, PDE_DATA(inode));
 };
 
 static const struct file_operations i2o_seq_fops_lct = {
@@ -1895,25 +1895,6 @@ static int i2o_proc_create_entries(struct proc_dir_entry *dir,
 }
 
 /**
- *	i2o_proc_subdir_remove - Remove child entries from a proc entry
- *	@dir: proc dir entry from which the childs should be removed
- *
- *	Iterate over each i2o proc entry under dir and remove it. If the child
- *	also has entries, remove them too.
- */
-static void i2o_proc_subdir_remove(struct proc_dir_entry *dir)
-{
-	struct proc_dir_entry *pe, *tmp;
-	pe = dir->subdir;
-	while (pe) {
-		tmp = pe->next;
-		i2o_proc_subdir_remove(pe);
-		remove_proc_entry(pe->name, dir);
-		pe = tmp;
-	}
-};
-
-/**
  *	i2o_proc_device_add - Add an I2O device to the proc dir
  *	@dir: proc dir entry to which the device should be added
  *	@dev: I2O device which should be added
@@ -1988,31 +1969,6 @@ static int i2o_proc_iop_add(struct proc_dir_entry *dir,
 }
 
 /**
- *	i2o_proc_iop_remove - Removes an I2O controller from the i2o proc tree
- *	@dir: parent proc dir entry
- *	@c: I2O controller which should be removed
- *
- *	Iterate over each i2o proc entry and search controller c. If it is found
- *	remove it from the tree.
- */
-static void i2o_proc_iop_remove(struct proc_dir_entry *dir,
-				struct i2o_controller *c)
-{
-	struct proc_dir_entry *pe, *tmp;
-
-	pe = dir->subdir;
-	while (pe) {
-		tmp = pe->next;
-		if (pe->data == c) {
-			i2o_proc_subdir_remove(pe);
-			remove_proc_entry(pe->name, dir);
-		}
-		osm_debug("removing IOP /proc/i2o/%s\n", c->name);
-		pe = tmp;
-	}
-}
-
-/**
  *	i2o_proc_fs_create - Create the i2o proc fs.
  *
  *	Iterate over each I2O controller and create the entries for it.
@@ -2042,12 +1998,7 @@ static int __init i2o_proc_fs_create(void)
  */
 static int __exit i2o_proc_fs_destroy(void)
 {
-	struct i2o_controller *c;
-
-	list_for_each_entry(c, &i2o_controllers, list)
-	    i2o_proc_iop_remove(i2o_proc_dir_root, c);
-
-	remove_proc_entry("i2o", NULL);
+	remove_proc_subtree("i2o", NULL);
 
 	return 0;
 };
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index c346941..f3c6692 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -21,6 +21,35 @@ config MFD_88PM860X
 	  select individual components like voltage regulators, RTC and
 	  battery-charger under the corresponding menus.
 
+config MFD_CROS_EC
+	tristate "Support ChromeOS Embedded Controller"
+	select MFD_CORE
+	help
+	  If you say Y here you get support for the ChromeOS Embedded
+	  Controller (EC) providing keyboard, battery and power services.
+	  You also ned to enable the driver for the bus you are using. The
+	  protocol for talking to the EC is defined by the bus driver.
+
+config MFD_CROS_EC_I2C
+	tristate "ChromeOS Embedded Controller (I2C)"
+	depends on MFD_CROS_EC && I2C
+
+	help
+	  If you say Y here, you get support for talking to the ChromeOS
+	  EC through an I2C bus. This uses a simple byte-level protocol with
+	  a checksum. Failing accesses will be retried three times to
+	  improve reliability.
+
+config MFD_CROS_EC_SPI
+	tristate "ChromeOS Embedded Controller (SPI)"
+	depends on MFD_CROS_EC && SPI
+
+	---help---
+	  If you say Y here, you get support for talking to the ChromeOS EC
+	  through a SPI bus, using a byte-level protocol. Since the EC's
+	  response time cannot be guaranteed, we support ignoring
+	  'pre-amble' bytes before the response actually starts.
+
 config MFD_88PM800
 	tristate "Support Marvell 88PM800"
 	depends on I2C=y && GENERIC_HARDIRQS
@@ -991,7 +1020,7 @@ config MFD_PM8XXX
 
 config MFD_PM8921_CORE
 	tristate "Qualcomm PM8921 PMIC chip"
-	depends on MSM_SSBI
+	depends on SSBI && BROKEN
 	select MFD_CORE
 	select MFD_PM8XXX
 	help
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index b90409c..f62a583 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -8,6 +8,9 @@ obj-$(CONFIG_MFD_88PM800)	+= 88pm800.o 88pm80x.o
 obj-$(CONFIG_MFD_88PM805)	+= 88pm805.o 88pm80x.o
 obj-$(CONFIG_MFD_SM501)		+= sm501.o
 obj-$(CONFIG_MFD_ASIC3)		+= asic3.o tmio_core.o
+obj-$(CONFIG_MFD_CROS_EC)	+= cros_ec.o
+obj-$(CONFIG_MFD_CROS_EC_I2C)	+= cros_ec_i2c.o
+obj-$(CONFIG_MFD_CROS_EC_SPI)	+= cros_ec_spi.o
 
 rtsx_pci-objs			:= rtsx_pcr.o rts5209.o rts5229.o rtl8411.o rts5227.o
 obj-$(CONFIG_MFD_RTSX_PCI)	+= rtsx_pci.o
diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c
index 7c84ced..f276352 100644
--- a/drivers/mfd/ab8500-core.c
+++ b/drivers/mfd/ab8500-core.c
@@ -95,6 +95,7 @@
 #define AB8500_IT_MASK22_REG		0x55
 #define AB8500_IT_MASK23_REG		0x56
 #define AB8500_IT_MASK24_REG		0x57
+#define AB8500_IT_MASK25_REG		0x58
 
 /*
  * latch hierarchy registers
@@ -102,15 +103,25 @@
 #define AB8500_IT_LATCHHIER1_REG	0x60
 #define AB8500_IT_LATCHHIER2_REG	0x61
 #define AB8500_IT_LATCHHIER3_REG	0x62
+#define AB8540_IT_LATCHHIER4_REG	0x63
 
 #define AB8500_IT_LATCHHIER_NUM		3
+#define AB8540_IT_LATCHHIER_NUM		4
 
 #define AB8500_REV_REG			0x80
 #define AB8500_IC_NAME_REG		0x82
 #define AB8500_SWITCH_OFF_STATUS	0x00
 
 #define AB8500_TURN_ON_STATUS		0x00
+#define AB8505_TURN_ON_STATUS_2	0x04
 
+#define AB8500_CH_USBCH_STAT1_REG	0x02
+#define VBUS_DET_DBNC100		0x02
+#define VBUS_DET_DBNC1			0x01
+
+static DEFINE_SPINLOCK(on_stat_lock);
+static u8 turn_on_stat_mask = 0xFF;
+static u8 turn_on_stat_set;
 static bool no_bm; /* No battery management */
 module_param(no_bm, bool, S_IRUGO);
 
@@ -130,9 +141,15 @@ static const int ab8500_irq_regoffset[AB8500_NUM_IRQ_REGS] = {
 	0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21,
 };
 
-/* AB9540 support */
+/* AB9540 / AB8505 support */
 static const int ab9540_irq_regoffset[AB9540_NUM_IRQ_REGS] = {
-	0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21, 12, 13, 24,
+	0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21, 12, 13, 24, 5, 22, 23
+};
+
+/* AB8540 support */
+static const int ab8540_irq_regoffset[AB8540_NUM_IRQ_REGS] = {
+	0, 1, 2, 3, 4, -1, -1, -1, -1, 11, 18, 19, 20, 21, 12, 13, 24, 5, 22, 23,
+	25, 26, 27, 28, 29, 30, 31,
 };
 
 static const char ab8500_version_str[][7] = {
@@ -352,6 +369,9 @@ static void ab8500_irq_sync_unlock(struct irq_data *data)
 			is_ab8500_1p1_or_earlier(ab8500))
 			continue;
 
+		if (ab8500->irq_reg_offset[i] < 0)
+			continue;
+
 		ab8500->oldmask[i] = new;
 
 		reg = AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i];
@@ -423,6 +443,18 @@ static struct irq_chip ab8500_irq_chip = {
 	.irq_set_type		= ab8500_irq_set_type,
 };
 
+static void update_latch_offset(u8 *offset, int i)
+{
+	/* Fix inconsistent ITFromLatch25 bit mapping... */
+	if (unlikely(*offset == 17))
+			*offset = 24;
+	/* Fix inconsistent ab8540 bit mapping... */
+	if (unlikely(*offset == 16))
+			*offset = 25;
+	if ((i==3) && (*offset >= 24))
+			*offset += 2;
+}
+
 static int ab8500_handle_hierarchical_line(struct ab8500 *ab8500,
 					int latch_offset, u8 latch_val)
 {
@@ -474,9 +506,7 @@ static int ab8500_handle_hierarchical_latch(struct ab8500 *ab8500,
 		latch_bit = __ffs(hier_val);
 		latch_offset = (hier_offset << 3) + latch_bit;
 
-		/* Fix inconsistent ITFromLatch25 bit mapping... */
-		if (unlikely(latch_offset == 17))
-			latch_offset = 24;
+		update_latch_offset(&latch_offset, hier_offset);
 
 		status = get_register_interruptible(ab8500,
 				AB8500_INTERRUPT,
@@ -504,7 +534,7 @@ static irqreturn_t ab8500_hierarchical_irq(int irq, void *dev)
 	dev_vdbg(ab8500->dev, "interrupt\n");
 
 	/*  Hierarchical interrupt version */
-	for (i = 0; i < AB8500_IT_LATCHHIER_NUM; i++) {
+	for (i = 0; i < (ab8500->it_latchhier_num); i++) {
 		int status;
 		u8 hier_val;
 
@@ -520,63 +550,6 @@ static irqreturn_t ab8500_hierarchical_irq(int irq, void *dev)
 	return IRQ_HANDLED;
 }
 
-/**
- * ab8500_irq_get_virq(): Map an interrupt on a chip to a virtual IRQ
- *
- * @ab8500: ab8500_irq controller to operate on.
- * @irq: index of the interrupt requested in the chip IRQs
- *
- * Useful for drivers to request their own IRQs.
- */
-static int ab8500_irq_get_virq(struct ab8500 *ab8500, int irq)
-{
-	if (!ab8500)
-		return -EINVAL;
-
-	return irq_create_mapping(ab8500->domain, irq);
-}
-
-static irqreturn_t ab8500_irq(int irq, void *dev)
-{
-	struct ab8500 *ab8500 = dev;
-	int i;
-
-	dev_vdbg(ab8500->dev, "interrupt\n");
-
-	atomic_inc(&ab8500->transfer_ongoing);
-
-	for (i = 0; i < ab8500->mask_size; i++) {
-		int regoffset = ab8500->irq_reg_offset[i];
-		int status;
-		u8 value;
-
-		/*
-		 * Interrupt register 12 doesn't exist prior to AB8500 version
-		 * 2.0
-		 */
-		if (regoffset == 11 && is_ab8500_1p1_or_earlier(ab8500))
-			continue;
-
-		status = get_register_interruptible(ab8500, AB8500_INTERRUPT,
-			AB8500_IT_LATCH1_REG + regoffset, &value);
-		if (status < 0 || value == 0)
-			continue;
-
-		do {
-			int bit = __ffs(value);
-			int line = i * 8 + bit;
-			int virq = ab8500_irq_get_virq(ab8500, line);
-
-			handle_nested_irq(virq);
-			ab8500_debug_register_interrupt(line);
-			value &= ~(1 << bit);
-
-		} while (value);
-	}
-	atomic_dec(&ab8500->transfer_ongoing);
-	return IRQ_HANDLED;
-}
-
 static int ab8500_irq_map(struct irq_domain *d, unsigned int virq,
 				irq_hw_number_t hwirq)
 {
@@ -607,7 +580,9 @@ static int ab8500_irq_init(struct ab8500 *ab8500, struct device_node *np)
 {
 	int num_irqs;
 
-	if (is_ab9540(ab8500))
+	if (is_ab8540(ab8500))
+		num_irqs = AB8540_NR_IRQS;
+	else if (is_ab9540(ab8500))
 		num_irqs = AB9540_NR_IRQS;
 	else if (is_ab8505(ab8500))
 		num_irqs = AB8505_NR_IRQS;
@@ -650,6 +625,15 @@ static struct resource ab8500_gpadc_resources[] = {
 	},
 };
 
+static struct resource ab8505_gpadc_resources[] = {
+	{
+		.name	= "SW_CONV_END",
+		.start	= AB8500_INT_GP_SW_ADC_CONV_END,
+		.end	= AB8500_INT_GP_SW_ADC_CONV_END,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
 static struct resource ab8500_rtc_resources[] = {
 	{
 		.name	= "60S",
@@ -973,6 +957,30 @@ static struct resource ab8505_iddet_resources[] = {
 		.end   = AB8505_INT_KEYSTUCK,
 		.flags = IORESOURCE_IRQ,
 	},
+	{
+		.name = "VBUS_DET_R",
+		.start = AB8500_INT_VBUS_DET_R,
+		.end = AB8500_INT_VBUS_DET_R,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name = "VBUS_DET_F",
+		.start = AB8500_INT_VBUS_DET_F,
+		.end = AB8500_INT_VBUS_DET_F,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name = "ID_DET_PLUGR",
+		.start = AB8500_INT_ID_DET_PLUGR,
+		.end = AB8500_INT_ID_DET_PLUGR,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name = "ID_DET_PLUGF",
+		.start = AB8500_INT_ID_DET_PLUGF,
+		.end = AB8500_INT_ID_DET_PLUGF,
+		.flags = IORESOURCE_IRQ,
+	},
 };
 
 static struct resource ab8500_temp_resources[] = {
@@ -984,7 +992,42 @@ static struct resource ab8500_temp_resources[] = {
 	},
 };
 
-static struct mfd_cell abx500_common_devs[] = {
+static struct mfd_cell ab8500_bm_devs[] = {
+	{
+		.name = "ab8500-charger",
+		.of_compatible = "stericsson,ab8500-charger",
+		.num_resources = ARRAY_SIZE(ab8500_charger_resources),
+		.resources = ab8500_charger_resources,
+		.platform_data = &ab8500_bm_data,
+		.pdata_size = sizeof(ab8500_bm_data),
+	},
+	{
+		.name = "ab8500-btemp",
+		.of_compatible = "stericsson,ab8500-btemp",
+		.num_resources = ARRAY_SIZE(ab8500_btemp_resources),
+		.resources = ab8500_btemp_resources,
+		.platform_data = &ab8500_bm_data,
+		.pdata_size = sizeof(ab8500_bm_data),
+	},
+	{
+		.name = "ab8500-fg",
+		.of_compatible = "stericsson,ab8500-fg",
+		.num_resources = ARRAY_SIZE(ab8500_fg_resources),
+		.resources = ab8500_fg_resources,
+		.platform_data = &ab8500_bm_data,
+		.pdata_size = sizeof(ab8500_bm_data),
+	},
+	{
+		.name = "ab8500-chargalg",
+		.of_compatible = "stericsson,ab8500-chargalg",
+		.num_resources = ARRAY_SIZE(ab8500_chargalg_resources),
+		.resources = ab8500_chargalg_resources,
+		.platform_data = &ab8500_bm_data,
+		.pdata_size = sizeof(ab8500_bm_data),
+	},
+};
+
+static struct mfd_cell ab8500_devs[] = {
 #ifdef CONFIG_DEBUG_FS
 	{
 		.name = "ab8500-debug",
@@ -1007,7 +1050,6 @@ static struct mfd_cell abx500_common_devs[] = {
 	},
 	{
 		.name = "ab8500-gpadc",
-		.of_compatible = "stericsson,ab8500-gpadc",
 		.num_resources = ARRAY_SIZE(ab8500_gpadc_resources),
 		.resources = ab8500_gpadc_resources,
 	},
@@ -1024,6 +1066,7 @@ static struct mfd_cell abx500_common_devs[] = {
 		.resources = ab8500_av_acc_detect_resources,
 	},
 	{
+
 		.name = "ab8500-poweron-key",
 		.of_compatible = "stericsson,ab8500-poweron-key",
 		.num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources),
@@ -1053,82 +1096,220 @@ static struct mfd_cell abx500_common_devs[] = {
 		.of_compatible = "stericsson,ab8500-denc",
 	},
 	{
+		.name = "ab8500-gpio",
+		.of_compatible = "stericsson,ab8500-gpio",
+	},
+	{
 		.name = "abx500-temp",
 		.of_compatible = "stericsson,abx500-temp",
 		.num_resources = ARRAY_SIZE(ab8500_temp_resources),
 		.resources = ab8500_temp_resources,
 	},
+	{
+		.name = "ab8500-usb",
+		.num_resources = ARRAY_SIZE(ab8500_usb_resources),
+		.resources = ab8500_usb_resources,
+	},
+	{
+		.name = "ab8500-codec",
+	},
 };
 
-static struct mfd_cell ab8500_bm_devs[] = {
+static struct mfd_cell ab9540_devs[] = {
+#ifdef CONFIG_DEBUG_FS
 	{
-		.name = "ab8500-charger",
-		.of_compatible = "stericsson,ab8500-charger",
-		.num_resources = ARRAY_SIZE(ab8500_charger_resources),
-		.resources = ab8500_charger_resources,
-		.platform_data = &ab8500_bm_data,
-		.pdata_size = sizeof(ab8500_bm_data),
+		.name = "ab8500-debug",
+		.num_resources = ARRAY_SIZE(ab8500_debug_resources),
+		.resources = ab8500_debug_resources,
 	},
+#endif
 	{
-		.name = "ab8500-btemp",
-		.of_compatible = "stericsson,ab8500-btemp",
-		.num_resources = ARRAY_SIZE(ab8500_btemp_resources),
-		.resources = ab8500_btemp_resources,
-		.platform_data = &ab8500_bm_data,
-		.pdata_size = sizeof(ab8500_bm_data),
+		.name = "ab8500-sysctrl",
 	},
 	{
-		.name = "ab8500-fg",
-		.of_compatible = "stericsson,ab8500-fg",
-		.num_resources = ARRAY_SIZE(ab8500_fg_resources),
-		.resources = ab8500_fg_resources,
-		.platform_data = &ab8500_bm_data,
-		.pdata_size = sizeof(ab8500_bm_data),
+		.name = "ab8500-regulator",
 	},
 	{
-		.name = "ab8500-chargalg",
-		.of_compatible = "stericsson,ab8500-chargalg",
-		.num_resources = ARRAY_SIZE(ab8500_chargalg_resources),
-		.resources = ab8500_chargalg_resources,
-		.platform_data = &ab8500_bm_data,
-		.pdata_size = sizeof(ab8500_bm_data),
+		.name = "abx500-clk",
+		.of_compatible = "stericsson,abx500-clk",
+	},
+	{
+		.name = "ab8500-gpadc",
+		.of_compatible = "stericsson,ab8500-gpadc",
+		.num_resources = ARRAY_SIZE(ab8500_gpadc_resources),
+		.resources = ab8500_gpadc_resources,
+	},
+	{
+		.name = "ab8500-rtc",
+		.num_resources = ARRAY_SIZE(ab8500_rtc_resources),
+		.resources = ab8500_rtc_resources,
+	},
+	{
+		.name = "ab8500-acc-det",
+		.num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources),
+		.resources = ab8500_av_acc_detect_resources,
+	},
+	{
+		.name = "ab8500-poweron-key",
+		.num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources),
+		.resources = ab8500_poweronkey_db_resources,
+	},
+	{
+		.name = "ab8500-pwm",
+		.id = 1,
+	},
+	{
+		.name = "ab8500-leds",
+	},
+	{
+		.name = "abx500-temp",
+		.num_resources = ARRAY_SIZE(ab8500_temp_resources),
+		.resources = ab8500_temp_resources,
+	},
+	{
+		.name = "pinctrl-ab9540",
+		.of_compatible = "stericsson,ab9540-gpio",
+	},
+	{
+		.name = "ab9540-usb",
+		.num_resources = ARRAY_SIZE(ab8500_usb_resources),
+		.resources = ab8500_usb_resources,
+	},
+	{
+		.name = "ab9540-codec",
+	},
+	{
+		.name = "ab-iddet",
+		.num_resources = ARRAY_SIZE(ab8505_iddet_resources),
+		.resources = ab8505_iddet_resources,
 	},
 };
 
-static struct mfd_cell ab8500_devs[] = {
+/* Device list for ab8505  */
+static struct mfd_cell ab8505_devs[] = {
+#ifdef CONFIG_DEBUG_FS
 	{
-		.name = "pinctrl-ab8500",
-		.of_compatible = "stericsson,ab8500-gpio",
+		.name = "ab8500-debug",
+		.num_resources = ARRAY_SIZE(ab8500_debug_resources),
+		.resources = ab8500_debug_resources,
+	},
+#endif
+	{
+		.name = "ab8500-sysctrl",
+	},
+	{
+		.name = "ab8500-regulator",
+	},
+	{
+		.name = "abx500-clk",
+		.of_compatible = "stericsson,abx500-clk",
+	},
+	{
+		.name = "ab8500-gpadc",
+		.num_resources = ARRAY_SIZE(ab8505_gpadc_resources),
+		.resources = ab8505_gpadc_resources,
+	},
+	{
+		.name = "ab8500-rtc",
+		.num_resources = ARRAY_SIZE(ab8500_rtc_resources),
+		.resources = ab8500_rtc_resources,
+	},
+	{
+		.name = "ab8500-acc-det",
+		.num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources),
+		.resources = ab8500_av_acc_detect_resources,
+	},
+	{
+		.name = "ab8500-poweron-key",
+		.num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources),
+		.resources = ab8500_poweronkey_db_resources,
+	},
+	{
+		.name = "ab8500-pwm",
+		.id = 1,
+	},
+	{
+		.name = "ab8500-leds",
+	},
+	{
+		.name = "ab8500-gpio",
 	},
 	{
 		.name = "ab8500-usb",
-		.of_compatible = "stericsson,ab8500-usb",
 		.num_resources = ARRAY_SIZE(ab8500_usb_resources),
 		.resources = ab8500_usb_resources,
 	},
 	{
 		.name = "ab8500-codec",
-		.of_compatible = "stericsson,ab8500-codec",
+	},
+	{
+		.name = "ab-iddet",
+		.num_resources = ARRAY_SIZE(ab8505_iddet_resources),
+		.resources = ab8505_iddet_resources,
 	},
 };
 
-static struct mfd_cell ab9540_devs[] = {
+static struct mfd_cell ab8540_devs[] = {
+#ifdef CONFIG_DEBUG_FS
 	{
-		.name = "pinctrl-ab9540",
-		.of_compatible = "stericsson,ab9540-gpio",
+		.name = "ab8500-debug",
+		.num_resources = ARRAY_SIZE(ab8500_debug_resources),
+		.resources = ab8500_debug_resources,
+	},
+#endif
+	{
+		.name = "ab8500-sysctrl",
 	},
 	{
-		.name = "ab9540-usb",
+		.name = "ab8500-regulator",
+	},
+	{
+		.name = "abx500-clk",
+		.of_compatible = "stericsson,abx500-clk",
+	},
+	{
+		.name = "ab8500-gpadc",
+		.num_resources = ARRAY_SIZE(ab8505_gpadc_resources),
+		.resources = ab8505_gpadc_resources,
+	},
+	{
+		.name = "ab8500-rtc",
+		.num_resources = ARRAY_SIZE(ab8500_rtc_resources),
+		.resources = ab8500_rtc_resources,
+	},
+	{
+		.name = "ab8500-acc-det",
+		.num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources),
+		.resources = ab8500_av_acc_detect_resources,
+	},
+	{
+		.name = "ab8500-poweron-key",
+		.num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources),
+		.resources = ab8500_poweronkey_db_resources,
+	},
+	{
+		.name = "ab8500-pwm",
+		.id = 1,
+	},
+	{
+		.name = "ab8500-leds",
+	},
+	{
+		.name = "abx500-temp",
+		.num_resources = ARRAY_SIZE(ab8500_temp_resources),
+		.resources = ab8500_temp_resources,
+	},
+	{
+		.name = "ab8500-gpio",
+	},
+	{
+		.name = "ab8540-usb",
 		.num_resources = ARRAY_SIZE(ab8500_usb_resources),
 		.resources = ab8500_usb_resources,
 	},
 	{
-		.name = "ab9540-codec",
+		.name = "ab8540-codec",
 	},
-};
-
-/* Device list common to ab9540 and ab8505 */
-static struct mfd_cell ab9540_ab8505_devs[] = {
 	{
 		.name = "ab-iddet",
 		.num_resources = ARRAY_SIZE(ab8505_iddet_resources),
@@ -1142,6 +1323,7 @@ static ssize_t show_chip_id(struct device *dev,
 	struct ab8500 *ab8500;
 
 	ab8500 = dev_get_drvdata(dev);
+
 	return sprintf(buf, "%#x\n", ab8500 ? ab8500->chip_id : -EINVAL);
 }
 
@@ -1171,6 +1353,15 @@ static ssize_t show_switch_off_status(struct device *dev,
 	return sprintf(buf, "%#x\n", value);
 }
 
+/* use mask and set to override the register turn_on_stat value */
+void ab8500_override_turn_on_stat(u8 mask, u8 set)
+{
+	spin_lock(&on_stat_lock);
+	turn_on_stat_mask = mask;
+	turn_on_stat_set = set;
+	spin_unlock(&on_stat_lock);
+}
+
 /*
  * ab8500 has turned on due to (TURN_ON_STATUS):
  * 0x01 PORnVbat
@@ -1194,9 +1385,38 @@ static ssize_t show_turn_on_status(struct device *dev,
 		AB8500_TURN_ON_STATUS, &value);
 	if (ret < 0)
 		return ret;
+
+	/*
+	 * In L9540, turn_on_status register is not updated correctly if
+	 * the device is rebooted with AC/USB charger connected. Due to
+	 * this, the device boots android instead of entering into charge
+	 * only mode. Read the AC/USB status register to detect the charger
+	 * presence and update the turn on status manually.
+	 */
+	if (is_ab9540(ab8500)) {
+		spin_lock(&on_stat_lock);
+		value = (value & turn_on_stat_mask) | turn_on_stat_set;
+		spin_unlock(&on_stat_lock);
+	}
+
 	return sprintf(buf, "%#x\n", value);
 }
 
+static ssize_t show_turn_on_status_2(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	int ret;
+	u8 value;
+	struct ab8500 *ab8500;
+
+	ab8500 = dev_get_drvdata(dev);
+	ret = get_register_interruptible(ab8500, AB8500_SYS_CTRL1_BLOCK,
+		AB8505_TURN_ON_STATUS_2, &value);
+	if (ret < 0)
+		return ret;
+	return sprintf(buf, "%#x\n", (value & 0x1));
+}
+
 static ssize_t show_ab9540_dbbrstn(struct device *dev,
 				struct device_attribute *attr, char *buf)
 {
@@ -1253,6 +1473,7 @@ exit:
 static DEVICE_ATTR(chip_id, S_IRUGO, show_chip_id, NULL);
 static DEVICE_ATTR(switch_off_status, S_IRUGO, show_switch_off_status, NULL);
 static DEVICE_ATTR(turn_on_status, S_IRUGO, show_turn_on_status, NULL);
+static DEVICE_ATTR(turn_on_status_2, S_IRUGO, show_turn_on_status_2, NULL);
 static DEVICE_ATTR(dbbrstn, S_IRUGO | S_IWUSR,
 			show_ab9540_dbbrstn, store_ab9540_dbbrstn);
 
@@ -1263,6 +1484,11 @@ static struct attribute *ab8500_sysfs_entries[] = {
 	NULL,
 };
 
+static struct attribute *ab8505_sysfs_entries[] = {
+	&dev_attr_turn_on_status_2.attr,
+	NULL,
+};
+
 static struct attribute *ab9540_sysfs_entries[] = {
 	&dev_attr_chip_id.attr,
 	&dev_attr_switch_off_status.attr,
@@ -1275,6 +1501,10 @@ static struct attribute_group ab8500_attr_group = {
 	.attrs	= ab8500_sysfs_entries,
 };
 
+static struct attribute_group ab8505_attr_group = {
+	.attrs	= ab8505_sysfs_entries,
+};
+
 static struct attribute_group ab9540_attr_group = {
 	.attrs	= ab9540_sysfs_entries,
 };
@@ -1290,6 +1520,15 @@ static int ab8500_probe(struct platform_device *pdev)
 		"Battery level lower than power on reset threshold",
 		"Power on key 1 pressed longer than 10 seconds",
 		"DB8500 thermal shutdown"};
+	static char *turn_on_status[] = {
+		"Battery rising (Vbat)",
+		"Power On Key 1 dbF",
+		"Power On Key 2 dbF",
+		"RTC Alarm",
+		"Main Charger Detect",
+		"Vbus Detect (USB)",
+		"USB ID Detect",
+		"UART Factory Mode Detect"};
 	struct ab8500_platform_data *plat = dev_get_platdata(&pdev->dev);
 	const struct platform_device_id *platid = platform_get_device_id(pdev);
 	enum ab8500_version version = AB8500_VERSION_UNDEFINED;
@@ -1351,13 +1590,20 @@ static int ab8500_probe(struct platform_device *pdev)
 			ab8500->chip_id >> 4,
 			ab8500->chip_id & 0x0F);
 
-	/* Configure AB8500 or AB9540 IRQ */
-	if (is_ab9540(ab8500) || is_ab8505(ab8500)) {
+	/* Configure AB8540 */
+	if (is_ab8540(ab8500)) {
+		ab8500->mask_size = AB8540_NUM_IRQ_REGS;
+		ab8500->irq_reg_offset = ab8540_irq_regoffset;
+		ab8500->it_latchhier_num = AB8540_IT_LATCHHIER_NUM;
+	}/* Configure AB8500 or AB9540 IRQ */
+	else if (is_ab9540(ab8500) || is_ab8505(ab8500)) {
 		ab8500->mask_size = AB9540_NUM_IRQ_REGS;
 		ab8500->irq_reg_offset = ab9540_irq_regoffset;
+		ab8500->it_latchhier_num = AB8500_IT_LATCHHIER_NUM;
 	} else {
 		ab8500->mask_size = AB8500_NUM_IRQ_REGS;
 		ab8500->irq_reg_offset = ab8500_irq_regoffset;
+		ab8500->it_latchhier_num = AB8500_IT_LATCHHIER_NUM;
 	}
 	ab8500->mask = devm_kzalloc(&pdev->dev, ab8500->mask_size, GFP_KERNEL);
 	if (!ab8500->mask)
@@ -1396,10 +1642,36 @@ static int ab8500_probe(struct platform_device *pdev)
 	} else {
 		printk(KERN_CONT " None\n");
 	}
+	ret = get_register_interruptible(ab8500, AB8500_SYS_CTRL1_BLOCK,
+		AB8500_TURN_ON_STATUS, &value);
+	if (ret < 0)
+		return ret;
+	dev_info(ab8500->dev, "turn on reason(s) (%#x): ", value);
+
+	if (value) {
+		for (i = 0; i < ARRAY_SIZE(turn_on_status); i++) {
+			if (value & 1)
+				printk("\"%s\" ", turn_on_status[i]);
+			value = value >> 1;
+		}
+		printk("\n");
+	} else {
+		printk("None\n");
+	}
 
 	if (plat && plat->init)
 		plat->init(ab8500);
 
+	if (is_ab9540(ab8500)) {
+		ret = get_register_interruptible(ab8500, AB8500_CHARGER,
+			AB8500_CH_USBCH_STAT1_REG, &value);
+		if (ret < 0)
+			return ret;
+		if ((value & VBUS_DET_DBNC1) && (value & VBUS_DET_DBNC100))
+			ab8500_override_turn_on_stat(~AB8500_POW_KEY_1_ON,
+						     AB8500_VBUS_DET);
+	}
+
 	/* Clear and mask all interrupts */
 	for (i = 0; i < ab8500->mask_size; i++) {
 		/*
@@ -1410,6 +1682,9 @@ static int ab8500_probe(struct platform_device *pdev)
 				is_ab8500_1p1_or_earlier(ab8500))
 			continue;
 
+		if (ab8500->irq_reg_offset[i] < 0)
+			continue;
+
 		get_register_interruptible(ab8500, AB8500_INTERRUPT,
 			AB8500_IT_LATCH1_REG + ab8500->irq_reg_offset[i],
 			&value);
@@ -1428,26 +1703,10 @@ static int ab8500_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
-	/*  Activate this feature only in ab9540 */
-	/*  till tests are done on ab8500 1p2 or later*/
-	if (is_ab9540(ab8500)) {
-		ret = devm_request_threaded_irq(&pdev->dev, ab8500->irq, NULL,
-						ab8500_hierarchical_irq,
-						IRQF_ONESHOT | IRQF_NO_SUSPEND,
-						"ab8500", ab8500);
-	}
-	else {
-		ret = devm_request_threaded_irq(&pdev->dev, ab8500->irq, NULL,
-						ab8500_irq,
-						IRQF_ONESHOT | IRQF_NO_SUSPEND,
-						"ab8500", ab8500);
-		if (ret)
-			return ret;
-	}
-
-	ret = mfd_add_devices(ab8500->dev, 0, abx500_common_devs,
-			ARRAY_SIZE(abx500_common_devs), NULL,
-			ab8500->irq_base, ab8500->domain);
+	ret = devm_request_threaded_irq(&pdev->dev, ab8500->irq, NULL,
+			ab8500_hierarchical_irq,
+			IRQF_ONESHOT | IRQF_NO_SUSPEND,
+			"ab8500", ab8500);
 	if (ret)
 		return ret;
 
@@ -1455,6 +1714,14 @@ static int ab8500_probe(struct platform_device *pdev)
 		ret = mfd_add_devices(ab8500->dev, 0, ab9540_devs,
 				ARRAY_SIZE(ab9540_devs), NULL,
 				ab8500->irq_base, ab8500->domain);
+	else if (is_ab8540(ab8500))
+		ret = mfd_add_devices(ab8500->dev, 0, ab8540_devs,
+			      ARRAY_SIZE(ab8540_devs), NULL,
+			      ab8500->irq_base, ab8500->domain);
+	else if (is_ab8505(ab8500))
+		ret = mfd_add_devices(ab8500->dev, 0, ab8505_devs,
+			      ARRAY_SIZE(ab8505_devs), NULL,
+			      ab8500->irq_base, ab8500->domain);
 	else
 		ret = mfd_add_devices(ab8500->dev, 0, ab8500_devs,
 				ARRAY_SIZE(ab8500_devs), NULL,
@@ -1462,13 +1729,6 @@ static int ab8500_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
-	if (is_ab9540(ab8500) || is_ab8505(ab8500))
-		ret = mfd_add_devices(ab8500->dev, 0, ab9540_ab8505_devs,
-				ARRAY_SIZE(ab9540_ab8505_devs), NULL,
-				ab8500->irq_base, ab8500->domain);
-	if (ret)
-		return ret;
-
 	if (!no_bm) {
 		/* Add battery management devices */
 		ret = mfd_add_devices(ab8500->dev, 0, ab8500_bm_devs,
@@ -1478,12 +1738,19 @@ static int ab8500_probe(struct platform_device *pdev)
 			dev_err(ab8500->dev, "error adding bm devices\n");
 	}
 
-	if (is_ab9540(ab8500))
+	if (((is_ab8505(ab8500) || is_ab9540(ab8500)) &&
+			ab8500->chip_id >= AB8500_CUT2P0) || is_ab8540(ab8500))
 		ret = sysfs_create_group(&ab8500->dev->kobj,
 					&ab9540_attr_group);
 	else
 		ret = sysfs_create_group(&ab8500->dev->kobj,
 					&ab8500_attr_group);
+
+	if ((is_ab8505(ab8500) || is_ab9540(ab8500)) &&
+			ab8500->chip_id >= AB8500_CUT2P0)
+		ret = sysfs_create_group(&ab8500->dev->kobj,
+					 &ab8505_attr_group);
+
 	if (ret)
 		dev_err(ab8500->dev, "error creating sysfs entries\n");
 
@@ -1494,11 +1761,16 @@ static int ab8500_remove(struct platform_device *pdev)
 {
 	struct ab8500 *ab8500 = platform_get_drvdata(pdev);
 
-	if (is_ab9540(ab8500))
+	if (((is_ab8505(ab8500) || is_ab9540(ab8500)) &&
+			ab8500->chip_id >= AB8500_CUT2P0) || is_ab8540(ab8500))
 		sysfs_remove_group(&ab8500->dev->kobj, &ab9540_attr_group);
 	else
 		sysfs_remove_group(&ab8500->dev->kobj, &ab8500_attr_group);
 
+	if ((is_ab8505(ab8500) || is_ab9540(ab8500)) &&
+			ab8500->chip_id >= AB8500_CUT2P0)
+		sysfs_remove_group(&ab8500->dev->kobj, &ab8505_attr_group);
+
 	mfd_remove_devices(ab8500->dev);
 
 	return 0;
diff --git a/drivers/mfd/ab8500-debugfs.c b/drivers/mfd/ab8500-debugfs.c
index 45fe3c5..b88bbbc 100644
--- a/drivers/mfd/ab8500-debugfs.c
+++ b/drivers/mfd/ab8500-debugfs.c
@@ -80,6 +80,7 @@
 #include <linux/interrupt.h>
 #include <linux/kobject.h>
 #include <linux/slab.h>
+#include <linux/irq.h>
 
 #include <linux/mfd/abx500.h>
 #include <linux/mfd/abx500/ab8500.h>
@@ -90,6 +91,9 @@
 #include <linux/ctype.h>
 #endif
 
+/* TODO: this file should not reference IRQ_DB8500_AB8500! */
+#include <mach/irqs.h>
+
 static u32 debug_bank;
 static u32 debug_address;
 
@@ -101,6 +105,11 @@ static int num_irqs;
 static struct device_attribute **dev_attr;
 static char **event_name;
 
+static u8 avg_sample = SAMPLE_16;
+static u8 trig_edge = RISING_EDGE;
+static u8 conv_type = ADC_SW;
+static u8 trig_timer;
+
 /**
  * struct ab8500_reg_range
  * @first: the first address of the range
@@ -150,7 +159,9 @@ static struct hwreg_cfg hwreg_cfg = {
 
 #define AB8500_REV_REG 0x80
 
-static struct ab8500_prcmu_ranges debug_ranges[AB8500_NUM_BANKS] = {
+static struct ab8500_prcmu_ranges *debug_ranges;
+
+struct ab8500_prcmu_ranges ab8500_debug_ranges[AB8500_NUM_BANKS] = {
 	[0x0] = {
 		.num_ranges = 0,
 		.range = NULL,
@@ -354,7 +365,7 @@ static struct ab8500_prcmu_ranges debug_ranges[AB8500_NUM_BANKS] = {
 			},
 			{
 				.first = 0xf5,
-				.last =	0xf6,
+				.last = 0xf6,
 			},
 		},
 	},
@@ -479,699 +490,2081 @@ static struct ab8500_prcmu_ranges debug_ranges[AB8500_NUM_BANKS] = {
 	},
 };
 
-static irqreturn_t ab8500_debug_handler(int irq, void *data)
-{
-	char buf[16];
-	struct kobject *kobj = (struct kobject *)data;
-	unsigned int irq_abb = irq - irq_first;
-
-	if (irq_abb < num_irqs)
-		irq_count[irq_abb]++;
-	/*
-	 * This makes it possible to use poll for events (POLLPRI | POLLERR)
-	 * from userspace on sysfs file named <irq-nr>
-	 */
-	sprintf(buf, "%d", irq);
-	sysfs_notify(kobj, NULL, buf);
-
-	return IRQ_HANDLED;
-}
-
-/* Prints to seq_file or log_buf */
-static int ab8500_registers_print(struct device *dev, u32 bank,
-				struct seq_file *s)
-{
-	unsigned int i;
-
-	for (i = 0; i < debug_ranges[bank].num_ranges; i++) {
-		u32 reg;
-
-		for (reg = debug_ranges[bank].range[i].first;
-			reg <= debug_ranges[bank].range[i].last;
-			reg++) {
-			u8 value;
-			int err;
-
-			err = abx500_get_register_interruptible(dev,
-				(u8)bank, (u8)reg, &value);
-			if (err < 0) {
-				dev_err(dev, "ab->read fail %d\n", err);
-				return err;
-			}
-
-			if (s) {
-				err = seq_printf(s, "  [%u/0x%02X]: 0x%02X\n",
-					bank, reg, value);
-				if (err < 0) {
-					dev_err(dev,
-					"seq_printf overflow bank=%d reg=%d\n",
-						bank, reg);
-					/* Error is not returned here since
-					 * the output is wanted in any case */
-					return 0;
-				}
-			} else {
-				printk(KERN_INFO" [%u/0x%02X]: 0x%02X\n", bank,
-					reg, value);
-			}
-		}
-	}
-	return 0;
-}
-
-static int ab8500_print_bank_registers(struct seq_file *s, void *p)
-{
-	struct device *dev = s->private;
-	u32 bank = debug_bank;
-
-	seq_printf(s, AB8500_NAME_STRING " register values:\n");
-
-	seq_printf(s, " bank %u:\n", bank);
-
-	ab8500_registers_print(dev, bank, s);
-	return 0;
-}
-
-static int ab8500_registers_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, ab8500_print_bank_registers, inode->i_private);
-}
-
-static const struct file_operations ab8500_registers_fops = {
-	.open = ab8500_registers_open,
-	.read = seq_read,
-	.llseek = seq_lseek,
-	.release = single_release,
-	.owner = THIS_MODULE,
-};
-
-static int ab8500_print_all_banks(struct seq_file *s, void *p)
-{
-	struct device *dev = s->private;
-	unsigned int i;
-	int err;
-
-	seq_printf(s, AB8500_NAME_STRING " register values:\n");
-
-	for (i = 1; i < AB8500_NUM_BANKS; i++) {
-		err = seq_printf(s, " bank %u:\n", i);
-		if (err < 0)
-			dev_err(dev, "seq_printf overflow, bank=%d\n", i);
-
-		ab8500_registers_print(dev, i, s);
-	}
-	return 0;
-}
-
-/* Dump registers to kernel log */
-void ab8500_dump_all_banks(struct device *dev)
-{
-	unsigned int i;
-
-	printk(KERN_INFO"ab8500 register values:\n");
-
-	for (i = 1; i < AB8500_NUM_BANKS; i++) {
-		printk(KERN_INFO" bank %u:\n", i);
-		ab8500_registers_print(dev, i, NULL);
-	}
-}
-
-static int ab8500_all_banks_open(struct inode *inode, struct file *file)
-{
-	struct seq_file *s;
-	int err;
-
-	err = single_open(file, ab8500_print_all_banks, inode->i_private);
-	if (!err) {
-		/* Default buf size in seq_read is not enough */
-		s = (struct seq_file *)file->private_data;
-		s->size = (PAGE_SIZE * 2);
-		s->buf = kmalloc(s->size, GFP_KERNEL);
-		if (!s->buf) {
-			single_release(inode, file);
-			err = -ENOMEM;
-		}
-	}
-	return err;
-}
-
-static const struct file_operations ab8500_all_banks_fops = {
-	.open = ab8500_all_banks_open,
-	.read = seq_read,
-	.llseek = seq_lseek,
-	.release = single_release,
-	.owner = THIS_MODULE,
-};
-
-static int ab8500_bank_print(struct seq_file *s, void *p)
-{
-	return seq_printf(s, "%d\n", debug_bank);
-}
-
-static int ab8500_bank_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, ab8500_bank_print, inode->i_private);
-}
-
-static ssize_t ab8500_bank_write(struct file *file,
-	const char __user *user_buf,
-	size_t count, loff_t *ppos)
-{
-	struct device *dev = ((struct seq_file *)(file->private_data))->private;
-	unsigned long user_bank;
-	int err;
-
-	/* Get userspace string and assure termination */
-	err = kstrtoul_from_user(user_buf, count, 0, &user_bank);
-	if (err)
-		return err;
-
-	if (user_bank >= AB8500_NUM_BANKS) {
-		dev_err(dev, "debugfs error input > number of banks\n");
-		return -EINVAL;
-	}
-
-	debug_bank = user_bank;
-
-	return count;
-}
-
-static int ab8500_address_print(struct seq_file *s, void *p)
-{
-	return seq_printf(s, "0x%02X\n", debug_address);
-}
-
-static int ab8500_address_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, ab8500_address_print, inode->i_private);
-}
-
-static ssize_t ab8500_address_write(struct file *file,
-	const char __user *user_buf,
-	size_t count, loff_t *ppos)
-{
-	struct device *dev = ((struct seq_file *)(file->private_data))->private;
-	unsigned long user_address;
-	int err;
-
-	/* Get userspace string and assure termination */
-	err = kstrtoul_from_user(user_buf, count, 0, &user_address);
-	if (err)
-		return err;
-
-	if (user_address > 0xff) {
-		dev_err(dev, "debugfs error input > 0xff\n");
-		return -EINVAL;
-	}
-	debug_address = user_address;
-	return count;
-}
-
-static int ab8500_val_print(struct seq_file *s, void *p)
-{
-	struct device *dev = s->private;
-	int ret;
-	u8 regvalue;
-
-	ret = abx500_get_register_interruptible(dev,
-		(u8)debug_bank, (u8)debug_address, &regvalue);
-	if (ret < 0) {
-		dev_err(dev, "abx500_get_reg fail %d, %d\n",
-			ret, __LINE__);
-		return -EINVAL;
-	}
-	seq_printf(s, "0x%02X\n", regvalue);
-
-	return 0;
-}
-
-static int ab8500_val_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, ab8500_val_print, inode->i_private);
-}
-
-static ssize_t ab8500_val_write(struct file *file,
-	const char __user *user_buf,
-	size_t count, loff_t *ppos)
-{
-	struct device *dev = ((struct seq_file *)(file->private_data))->private;
-	unsigned long user_val;
-	int err;
-
-	/* Get userspace string and assure termination */
-	err = kstrtoul_from_user(user_buf, count, 0, &user_val);
-	if (err)
-		return err;
-
-	if (user_val > 0xff) {
-		dev_err(dev, "debugfs error input > 0xff\n");
-		return -EINVAL;
-	}
-	err = abx500_set_register_interruptible(dev,
-		(u8)debug_bank, debug_address, (u8)user_val);
-	if (err < 0) {
-		printk(KERN_ERR "abx500_set_reg failed %d, %d", err, __LINE__);
-		return -EINVAL;
-	}
-
-	return count;
-}
-
-/*
- * Interrupt status
- */
-static u32 num_interrupts[AB8500_MAX_NR_IRQS];
-static int num_interrupt_lines;
-
-void ab8500_debug_register_interrupt(int line)
+struct ab8500_prcmu_ranges ab8505_debug_ranges[AB8500_NUM_BANKS] = {
+	[0x0] = {
+		.num_ranges = 0,
+		.range = NULL,
+	},
+	[AB8500_SYS_CTRL1_BLOCK] = {
+		.num_ranges = 5,
+		.range = (struct ab8500_reg_range[]) {
+			{
+				.first = 0x00,
+				.last = 0x04,
+			},
+			{
+				.first = 0x42,
+				.last = 0x42,
+			},
+			{
+				.first = 0x52,
+				.last = 0x52,
+			},
+			{
+				.first = 0x54,
+				.last = 0x57,
+			},
+			{
+				.first = 0x80,
+				.last = 0x83,
+			},
+		},
+	},
+	[AB8500_SYS_CTRL2_BLOCK] = {
+		.num_ranges = 5,
+		.range = (struct ab8500_reg_range[]) {
+			{
+				.first = 0x00,
+				.last = 0x0D,
+			},
+			{
+				.first = 0x0F,
+				.last = 0x17,
+			},
+			{
+				.first = 0x20,
+				.last = 0x20,
+			},
+			{
+				.first = 0x30,
+				.last = 0x30,
+			},
+			{
+				.first = 0x32,
+				.last = 0x3A,
+			},
+		},
+	},
+	[AB8500_REGU_CTRL1] = {
+		.num_ranges = 3,
+		.range = (struct ab8500_reg_range[]) {
+			{
+				.first = 0x00,
+				.last = 0x00,
+			},
+			{
+				.first = 0x03,
+				.last = 0x11,
+			},
+			{
+				.first = 0x80,
+				.last = 0x86,
+			},
+		},
+	},
+	[AB8500_REGU_CTRL2] = {
+		.num_ranges = 6,
+		.range = (struct ab8500_reg_range[]) {
+			{
+				.first = 0x00,
+				.last = 0x06,
+			},
+			{
+				.first = 0x08,
+				.last = 0x15,
+			},
+			{
+				.first = 0x17,
+				.last = 0x19,
+			},
+			{
+				.first = 0x1B,
+				.last = 0x1D,
+			},
+			{
+				.first = 0x1F,
+				.last = 0x30,
+			},
+			{
+				.first = 0x40,
+				.last = 0x48,
+			},
+			/* 0x80-0x8B is SIM registers and should
+			 * not be accessed from here */
+		},
+	},
+	[AB8500_USB] = {
+		.num_ranges = 3,
+		.range = (struct ab8500_reg_range[]) {
+			{
+				.first = 0x80,
+				.last = 0x83,
+			},
+			{
+				.first = 0x87,
+				.last = 0x8A,
+			},
+			{
+				.first = 0x91,
+				.last = 0x94,
+			},
+		},
+	},
+	[AB8500_TVOUT] = {
+		.num_ranges = 0,
+		.range = NULL,
+	},
+	[AB8500_DBI] = {
+		.num_ranges = 0,
+		.range = NULL,
+	},
+	[AB8500_ECI_AV_ACC] = {
+		.num_ranges = 1,
+		.range = (struct ab8500_reg_range[]) {
+			{
+				.first = 0x80,
+				.last = 0x82,
+			},
+		},
+	},
+	[AB8500_RESERVED] = {
+		.num_ranges = 0,
+		.range = NULL,
+	},
+	[AB8500_GPADC] = {
+		.num_ranges = 1,
+		.range = (struct ab8500_reg_range[]) {
+			{
+				.first = 0x00,
+				.last = 0x08,
+			},
+		},
+	},
+	[AB8500_CHARGER] = {
+		.num_ranges = 9,
+		.range = (struct ab8500_reg_range[]) {
+			{
+				.first = 0x02,
+				.last = 0x03,
+			},
+			{
+				.first = 0x05,
+				.last = 0x05,
+			},
+			{
+				.first = 0x40,
+				.last = 0x44,
+			},
+			{
+				.first = 0x50,
+				.last = 0x57,
+			},
+			{
+				.first = 0x60,
+				.last = 0x60,
+			},
+			{
+				.first = 0xA0,
+				.last = 0xA7,
+			},
+			{
+				.first = 0xAF,
+				.last = 0xB2,
+			},
+			{
+				.first = 0xC0,
+				.last = 0xC2,
+			},
+			{
+				.first = 0xF5,
+				.last = 0xF5,
+			},
+		},
+	},
+	[AB8500_GAS_GAUGE] = {
+		.num_ranges = 3,
+		.range = (struct ab8500_reg_range[]) {
+			{
+				.first = 0x00,
+				.last = 0x00,
+			},
+			{
+				.first = 0x07,
+				.last = 0x0A,
+			},
+			{
+				.first = 0x10,
+				.last = 0x14,
+			},
+		},
+	},
+	[AB8500_AUDIO] = {
+		.num_ranges = 1,
+		.range = (struct ab8500_reg_range[]) {
+			{
+				.first = 0x00,
+				.last = 0x83,
+			},
+		},
+	},
+	[AB8500_INTERRUPT] = {
+		.num_ranges = 11,
+		.range = (struct ab8500_reg_range[]) {
+			{
+				.first = 0x00,
+				.last = 0x04,
+			},
+			{
+				.first = 0x06,
+				.last = 0x07,
+			},
+			{
+				.first = 0x09,
+				.last = 0x09,
+			},
+			{
+				.first = 0x0B,
+				.last = 0x0C,
+			},
+			{
+				.first = 0x12,
+				.last = 0x15,
+			},
+			{
+				.first = 0x18,
+				.last = 0x18,
+			},
+			/* Latch registers should not be read here */
+			{
+				.first = 0x40,
+				.last = 0x44,
+			},
+			{
+				.first = 0x46,
+				.last = 0x49,
+			},
+			{
+				.first = 0x4B,
+				.last = 0x4D,
+			},
+			{
+				.first = 0x52,
+				.last = 0x55,
+			},
+			{
+				.first = 0x58,
+				.last = 0x58,
+			},
+			/* LatchHier registers should not be read here */
+		},
+	},
+	[AB8500_RTC] = {
+		.num_ranges = 2,
+		.range = (struct ab8500_reg_range[]) {
+			{
+				.first = 0x00,
+				.last = 0x14,
+			},
+			{
+				.first = 0x16,
+				.last = 0x17,
+			},
+		},
+	},
+	[AB8500_MISC] = {
+		.num_ranges = 8,
+		.range = (struct ab8500_reg_range[]) {
+			{
+				.first = 0x00,
+				.last = 0x06,
+			},
+			{
+				.first = 0x10,
+				.last = 0x16,
+			},
+			{
+				.first = 0x20,
+				.last = 0x26,
+			},
+			{
+				.first = 0x30,
+				.last = 0x36,
+			},
+			{
+				.first = 0x40,
+				.last = 0x46,
+			},
+			{
+				.first = 0x50,
+				.last = 0x50,
+			},
+			{
+				.first = 0x60,
+				.last = 0x6B,
+			},
+			{
+				.first = 0x80,
+				.last = 0x82,
+			},
+		},
+	},
+	[AB8500_DEVELOPMENT] = {
+		.num_ranges = 2,
+		.range = (struct ab8500_reg_range[]) {
+			{
+				.first = 0x00,
+				.last = 0x00,
+			},
+			{
+				.first = 0x05,
+				.last = 0x05,
+			},
+		},
+	},
+	[AB8500_DEBUG] = {
+		.num_ranges = 1,
+		.range = (struct ab8500_reg_range[]) {
+			{
+				.first = 0x05,
+				.last = 0x07,
+			},
+		},
+	},
+	[AB8500_PROD_TEST] = {
+		.num_ranges = 0,
+		.range = NULL,
+	},
+	[AB8500_STE_TEST] = {
+		.num_ranges = 0,
+		.range = NULL,
+	},
+	[AB8500_OTP_EMUL] = {
+		.num_ranges = 1,
+		.range = (struct ab8500_reg_range[]) {
+			{
+				.first = 0x01,
+				.last = 0x15,
+			},
+		},
+	},
+};
+
+struct ab8500_prcmu_ranges ab8540_debug_ranges[AB8500_NUM_BANKS] = {
+	[AB8500_M_FSM_RANK] = {
+		.num_ranges = 1,
+		.range = (struct ab8500_reg_range[]) {
+			{
+				.first = 0x00,
+				.last = 0x0B,
+			},
+		},
+	},
+	[AB8500_SYS_CTRL1_BLOCK] = {
+		.num_ranges = 6,
+		.range = (struct ab8500_reg_range[]) {
+			{
+				.first = 0x00,
+				.last = 0x04,
+			},
+			{
+				.first = 0x42,
+				.last = 0x42,
+			},
+			{
+				.first = 0x50,
+				.last = 0x54,
+			},
+			{
+				.first = 0x57,
+				.last = 0x57,
+			},
+			{
+				.first = 0x80,
+				.last = 0x83,
+			},
+			{
+				.first = 0x90,
+				.last = 0x90,
+			},
+		},
+	},
+	[AB8500_SYS_CTRL2_BLOCK] = {
+		.num_ranges = 5,
+		.range = (struct ab8500_reg_range[]) {
+			{
+				.first = 0x00,
+				.last = 0x0D,
+			},
+			{
+				.first = 0x0F,
+				.last = 0x10,
+			},
+			{
+				.first = 0x20,
+				.last = 0x21,
+			},
+			{
+				.first = 0x32,
+				.last = 0x3C,
+			},
+			{
+				.first = 0x40,
+				.last = 0x42,
+			},
+		},
+	},
+	[AB8500_REGU_CTRL1] = {
+		.num_ranges = 4,
+		.range = (struct ab8500_reg_range[]) {
+			{
+				.first = 0x03,
+				.last = 0x15,
+			},
+			{
+				.first = 0x20,
+				.last = 0x20,
+			},
+			{
+				.first = 0x80,
+				.last = 0x85,
+			},
+			{
+				.first = 0x87,
+				.last = 0x88,
+			},
+		},
+	},
+	[AB8500_REGU_CTRL2] = {
+		.num_ranges = 8,
+		.range = (struct ab8500_reg_range[]) {
+			{
+				.first = 0x00,
+				.last = 0x06,
+			},
+			{
+				.first = 0x08,
+				.last = 0x15,
+			},
+			{
+				.first = 0x17,
+				.last = 0x19,
+			},
+			{
+				.first = 0x1B,
+				.last = 0x1D,
+			},
+			{
+				.first = 0x1F,
+				.last = 0x2F,
+			},
+			{
+				.first = 0x31,
+				.last = 0x3A,
+			},
+			{
+				.first = 0x43,
+				.last = 0x44,
+			},
+			{
+				.first = 0x48,
+				.last = 0x49,
+			},
+		},
+	},
+	[AB8500_USB] = {
+		.num_ranges = 3,
+		.range = (struct ab8500_reg_range[]) {
+			{
+				.first = 0x80,
+				.last = 0x83,
+			},
+			{
+				.first = 0x87,
+				.last = 0x8A,
+			},
+			{
+				.first = 0x91,
+				.last = 0x94,
+			},
+		},
+	},
+	[AB8500_TVOUT] = {
+		.num_ranges = 0,
+		.range = NULL
+	},
+	[AB8500_DBI] = {
+		.num_ranges = 4,
+		.range = (struct ab8500_reg_range[]) {
+			{
+				.first = 0x00,
+				.last = 0x07,
+			},
+			{
+				.first = 0x10,
+				.last = 0x11,
+			},
+			{
+				.first = 0x20,
+				.last = 0x21,
+			},
+			{
+				.first = 0x30,
+				.last = 0x43,
+			},
+		},
+	},
+	[AB8500_ECI_AV_ACC] = {
+		.num_ranges = 2,
+		.range = (struct ab8500_reg_range[]) {
+			{
+				.first = 0x00,
+				.last = 0x03,
+			},
+			{
+				.first = 0x80,
+				.last = 0x82,
+			},
+		},
+	},
+	[AB8500_RESERVED] = {
+		.num_ranges = 0,
+		.range = NULL,
+	},
+	[AB8500_GPADC] = {
+		.num_ranges = 4,
+		.range = (struct ab8500_reg_range[]) {
+			{
+				.first = 0x00,
+				.last = 0x01,
+			},
+			{
+				.first = 0x04,
+				.last = 0x06,
+			},
+			{
+				.first = 0x09,
+				.last = 0x0A,
+			},
+			{
+				.first = 0x10,
+				.last = 0x14,
+			},
+		},
+	},
+	[AB8500_CHARGER] = {
+		.num_ranges = 10,
+		.range = (struct ab8500_reg_range[]) {
+			{
+				.first = 0x00,
+				.last = 0x00,
+			},
+			{
+				.first = 0x02,
+				.last = 0x05,
+			},
+			{
+				.first = 0x40,
+				.last = 0x44,
+			},
+			{
+				.first = 0x50,
+				.last = 0x57,
+			},
+			{
+				.first = 0x60,
+				.last = 0x60,
+			},
+			{
+				.first = 0x70,
+				.last = 0x70,
+			},
+			{
+				.first = 0xA0,
+				.last = 0xA9,
+			},
+			{
+				.first = 0xAF,
+				.last = 0xB2,
+			},
+			{
+				.first = 0xC0,
+				.last = 0xC6,
+			},
+			{
+				.first = 0xF5,
+				.last = 0xF5,
+			},
+		},
+	},
+	[AB8500_GAS_GAUGE] = {
+		.num_ranges = 3,
+		.range = (struct ab8500_reg_range[]) {
+			{
+				.first = 0x00,
+				.last = 0x00,
+			},
+			{
+				.first = 0x07,
+				.last = 0x0A,
+			},
+			{
+				.first = 0x10,
+				.last = 0x14,
+			},
+		},
+	},
+	[AB8500_AUDIO] = {
+		.num_ranges = 1,
+		.range = (struct ab8500_reg_range[]) {
+			{
+				.first = 0x00,
+				.last = 0x9f,
+			},
+		},
+	},
+	[AB8500_INTERRUPT] = {
+		.num_ranges = 6,
+		.range = (struct ab8500_reg_range[]) {
+			{
+				.first = 0x00,
+				.last = 0x05,
+			},
+			{
+				.first = 0x0B,
+				.last = 0x0D,
+			},
+			{
+				.first = 0x12,
+				.last = 0x20,
+			},
+			/* Latch registers should not be read here */
+			{
+				.first = 0x40,
+				.last = 0x45,
+			},
+			{
+				.first = 0x4B,
+				.last = 0x4D,
+			},
+			{
+				.first = 0x52,
+				.last = 0x60,
+			},
+			/* LatchHier registers should not be read here */
+		},
+	},
+	[AB8500_RTC] = {
+		.num_ranges = 3,
+		.range = (struct ab8500_reg_range[]) {
+			{
+				.first = 0x00,
+				.last = 0x07,
+			},
+			{
+				.first = 0x0B,
+				.last = 0x18,
+			},
+			{
+				.first = 0x20,
+				.last = 0x25,
+			},
+		},
+	},
+	[AB8500_MISC] = {
+		.num_ranges = 9,
+		.range = (struct ab8500_reg_range[]) {
+			{
+				.first = 0x00,
+				.last = 0x06,
+			},
+			{
+				.first = 0x10,
+				.last = 0x16,
+			},
+			{
+				.first = 0x20,
+				.last = 0x26,
+			},
+			{
+				.first = 0x30,
+				.last = 0x36,
+			},
+			{
+				.first = 0x40,
+				.last = 0x49,
+			},
+			{
+				.first = 0x50,
+				.last = 0x50,
+			},
+			{
+				.first = 0x60,
+				.last = 0x6B,
+			},
+			{
+				.first = 0x70,
+				.last = 0x74,
+			},
+			{
+				.first = 0x80,
+				.last = 0x82,
+			},
+		},
+	},
+	[AB8500_DEVELOPMENT] = {
+		.num_ranges = 3,
+		.range = (struct ab8500_reg_range[]) {
+			{
+				.first = 0x00,
+				.last = 0x01,
+			},
+			{
+				.first = 0x06,
+				.last = 0x06,
+			},
+			{
+				.first = 0x10,
+				.last = 0x21,
+			},
+		},
+	},
+	[AB8500_DEBUG] = {
+		.num_ranges = 3,
+		.range = (struct ab8500_reg_range[]) {
+			{
+				.first = 0x01,
+				.last = 0x0C,
+			},
+			{
+				.first = 0x0E,
+				.last = 0x11,
+			},
+			{
+				.first = 0x80,
+				.last = 0x81,
+			},
+		},
+	},
+	[AB8500_PROD_TEST] = {
+		.num_ranges = 0,
+		.range = NULL,
+	},
+	[AB8500_STE_TEST] = {
+		.num_ranges = 0,
+		.range = NULL,
+	},
+	[AB8500_OTP_EMUL] = {
+		.num_ranges = 1,
+		.range = (struct ab8500_reg_range[]) {
+			{
+				.first = 0x00,
+				.last = 0x3F,
+			},
+		},
+	},
+};
+
+
+static irqreturn_t ab8500_debug_handler(int irq, void *data)
+{
+	char buf[16];
+	struct kobject *kobj = (struct kobject *)data;
+	unsigned int irq_abb = irq - irq_first;
+
+	if (irq_abb < num_irqs)
+		irq_count[irq_abb]++;
+	/*
+	 * This makes it possible to use poll for events (POLLPRI | POLLERR)
+	 * from userspace on sysfs file named <irq-nr>
+	 */
+	sprintf(buf, "%d", irq);
+	sysfs_notify(kobj, NULL, buf);
+
+	return IRQ_HANDLED;
+}
+
+/* Prints to seq_file or log_buf */
+static int ab8500_registers_print(struct device *dev, u32 bank,
+				struct seq_file *s)
+{
+	unsigned int i;
+
+	for (i = 0; i < debug_ranges[bank].num_ranges; i++) {
+		u32 reg;
+
+		for (reg = debug_ranges[bank].range[i].first;
+			reg <= debug_ranges[bank].range[i].last;
+			reg++) {
+			u8 value;
+			int err;
+
+			err = abx500_get_register_interruptible(dev,
+				(u8)bank, (u8)reg, &value);
+			if (err < 0) {
+				dev_err(dev, "ab->read fail %d\n", err);
+				return err;
+			}
+
+			if (s) {
+				err = seq_printf(s, "  [0x%02X/0x%02X]: 0x%02X\n",
+					bank, reg, value);
+				if (err < 0) {
+					/* Error is not returned here since
+					 * the output is wanted in any case */
+					return 0;
+				}
+			} else {
+				printk(KERN_INFO" [0x%02X/0x%02X]: 0x%02X\n",
+					bank, reg, value);
+			}
+		}
+	}
+	return 0;
+}
+
+static int ab8500_print_bank_registers(struct seq_file *s, void *p)
+{
+	struct device *dev = s->private;
+	u32 bank = debug_bank;
+
+	seq_printf(s, AB8500_NAME_STRING " register values:\n");
+
+	seq_printf(s, " bank 0x%02X:\n", bank);
+
+	ab8500_registers_print(dev, bank, s);
+	return 0;
+}
+
+static int ab8500_registers_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, ab8500_print_bank_registers, inode->i_private);
+}
+
+static const struct file_operations ab8500_registers_fops = {
+	.open = ab8500_registers_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+	.owner = THIS_MODULE,
+};
+
+static int ab8500_print_all_banks(struct seq_file *s, void *p)
+{
+	struct device *dev = s->private;
+	unsigned int i;
+	int err;
+
+	seq_printf(s, AB8500_NAME_STRING " register values:\n");
+
+	for (i = 0; i < AB8500_NUM_BANKS; i++) {
+		err = seq_printf(s, " bank 0x%02X:\n", i);
+
+		ab8500_registers_print(dev, i, s);
+	}
+	return 0;
+}
+
+/* Dump registers to kernel log */
+void ab8500_dump_all_banks(struct device *dev)
+{
+	unsigned int i;
+
+	printk(KERN_INFO"ab8500 register values:\n");
+
+	for (i = 1; i < AB8500_NUM_BANKS; i++) {
+		printk(KERN_INFO" bank 0x%02X:\n", i);
+		ab8500_registers_print(dev, i, NULL);
+	}
+}
+
+/* Space for 500 registers. */
+#define DUMP_MAX_REGS 700
+struct ab8500_register_dump
+{
+	u8 bank;
+	u8 reg;
+	u8 value;
+} ab8500_complete_register_dump[DUMP_MAX_REGS];
+
+extern int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size);
+
+/* This shall only be called upon kernel panic! */
+void ab8500_dump_all_banks_to_mem(void)
+{
+	int i, r = 0;
+	u8 bank;
+	int err = 0;
+
+	pr_info("Saving all ABB registers at \"ab8500_complete_register_dump\" "
+		"for crash analyze.\n");
+
+	for (bank = 0; bank < AB8500_NUM_BANKS; bank++) {
+		for (i = 0; i < debug_ranges[bank].num_ranges; i++) {
+			u8 reg;
+
+			for (reg = debug_ranges[bank].range[i].first;
+			     reg <= debug_ranges[bank].range[i].last;
+			     reg++) {
+				u8 value;
+
+				err = prcmu_abb_read(bank, reg, &value, 1);
+
+				if (err < 0)
+					goto out;
+
+				ab8500_complete_register_dump[r].bank = bank;
+				ab8500_complete_register_dump[r].reg = reg;
+				ab8500_complete_register_dump[r].value = value;
+
+				r++;
+
+				if (r >= DUMP_MAX_REGS) {
+					pr_err("%s: too many register to dump!\n",
+						__func__);
+					err = -EINVAL;
+					goto out;
+				}
+			}
+		}
+	}
+out:
+	if (err >= 0)
+		pr_info("Saved all ABB registers.\n");
+	else
+		pr_info("Failed to save all ABB registers.\n");
+}
+
+static int ab8500_all_banks_open(struct inode *inode, struct file *file)
+{
+	struct seq_file *s;
+	int err;
+
+	err = single_open(file, ab8500_print_all_banks, inode->i_private);
+	if (!err) {
+		/* Default buf size in seq_read is not enough */
+		s = (struct seq_file *)file->private_data;
+		s->size = (PAGE_SIZE * 2);
+		s->buf = kmalloc(s->size, GFP_KERNEL);
+		if (!s->buf) {
+			single_release(inode, file);
+			err = -ENOMEM;
+		}
+	}
+	return err;
+}
+
+static const struct file_operations ab8500_all_banks_fops = {
+	.open = ab8500_all_banks_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+	.owner = THIS_MODULE,
+};
+
+static int ab8500_bank_print(struct seq_file *s, void *p)
+{
+	return seq_printf(s, "0x%02X\n", debug_bank);
+}
+
+static int ab8500_bank_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, ab8500_bank_print, inode->i_private);
+}
+
+static ssize_t ab8500_bank_write(struct file *file,
+	const char __user *user_buf,
+	size_t count, loff_t *ppos)
+{
+	struct device *dev = ((struct seq_file *)(file->private_data))->private;
+	unsigned long user_bank;
+	int err;
+
+	err = kstrtoul_from_user(user_buf, count, 0, &user_bank);
+	if (err)
+		return err;
+
+	if (user_bank >= AB8500_NUM_BANKS) {
+		dev_err(dev, "debugfs error input > number of banks\n");
+		return -EINVAL;
+	}
+
+	debug_bank = user_bank;
+
+	return count;
+}
+
+static int ab8500_address_print(struct seq_file *s, void *p)
+{
+	return seq_printf(s, "0x%02X\n", debug_address);
+}
+
+static int ab8500_address_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, ab8500_address_print, inode->i_private);
+}
+
+static ssize_t ab8500_address_write(struct file *file,
+				    const char __user *user_buf,
+				    size_t count, loff_t *ppos)
+{
+	struct device *dev = ((struct seq_file *)(file->private_data))->private;
+	unsigned long user_address;
+	int err;
+
+	err = kstrtoul_from_user(user_buf, count, 0, &user_address);
+	if (err)
+		return err;
+
+	if (user_address > 0xff) {
+		dev_err(dev, "debugfs error input > 0xff\n");
+		return -EINVAL;
+	}
+	debug_address = user_address;
+
+	return count;
+}
+
+static int ab8500_val_print(struct seq_file *s, void *p)
+{
+	struct device *dev = s->private;
+	int ret;
+	u8 regvalue;
+
+	ret = abx500_get_register_interruptible(dev,
+		(u8)debug_bank, (u8)debug_address, &regvalue);
+	if (ret < 0) {
+		dev_err(dev, "abx500_get_reg fail %d, %d\n",
+			ret, __LINE__);
+		return -EINVAL;
+	}
+	seq_printf(s, "0x%02X\n", regvalue);
+
+	return 0;
+}
+
+static int ab8500_val_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, ab8500_val_print, inode->i_private);
+}
+
+static ssize_t ab8500_val_write(struct file *file,
+				const char __user *user_buf,
+				size_t count, loff_t *ppos)
+{
+	struct device *dev = ((struct seq_file *)(file->private_data))->private;
+	unsigned long user_val;
+	int err;
+
+	err = kstrtoul_from_user(user_buf, count, 0, &user_val);
+	if (err)
+		return err;
+
+	if (user_val > 0xff) {
+		dev_err(dev, "debugfs error input > 0xff\n");
+		return -EINVAL;
+	}
+	err = abx500_set_register_interruptible(dev,
+		(u8)debug_bank, debug_address, (u8)user_val);
+	if (err < 0) {
+		printk(KERN_ERR "abx500_set_reg failed %d, %d", err, __LINE__);
+		return -EINVAL;
+	}
+
+	return count;
+}
+
+/*
+ * Interrupt status
+ */
+static u32 num_interrupts[AB8500_MAX_NR_IRQS];
+static u32 num_wake_interrupts[AB8500_MAX_NR_IRQS];
+static int num_interrupt_lines;
+
+bool __attribute__((weak)) suspend_test_wake_cause_interrupt_is_mine(u32 my_int)
+{
+	return false;
+}
+
+void ab8500_debug_register_interrupt(int line)
+{
+	if (line < num_interrupt_lines) {
+		num_interrupts[line]++;
+		if (suspend_test_wake_cause_interrupt_is_mine(IRQ_DB8500_AB8500))
+			num_wake_interrupts[line]++;
+	}
+}
+
+static int ab8500_interrupts_print(struct seq_file *s, void *p)
+{
+	int line;
+
+	seq_printf(s, "name: number:  number of: wake:\n");
+
+	for (line = 0; line < num_interrupt_lines; line++) {
+		struct irq_desc *desc = irq_to_desc(line + irq_first);
+		struct irqaction *action = desc->action;
+
+		seq_printf(s, "%3i:  %6i %4i", line,
+			   num_interrupts[line],
+			   num_wake_interrupts[line]);
+
+		if (desc && desc->name)
+			seq_printf(s, "-%-8s", desc->name);
+		if (action) {
+			seq_printf(s, "  %s", action->name);
+			while ((action = action->next) != NULL)
+				seq_printf(s, ", %s", action->name);
+		}
+		seq_putc(s, '\n');
+	}
+
+	return 0;
+}
+
+static int ab8500_interrupts_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, ab8500_interrupts_print, inode->i_private);
+}
+
+/*
+ * - HWREG DB8500 formated routines
+ */
+static int ab8500_hwreg_print(struct seq_file *s, void *d)
+{
+	struct device *dev = s->private;
+	int ret;
+	u8 regvalue;
+
+	ret = abx500_get_register_interruptible(dev,
+		(u8)hwreg_cfg.bank, (u8)hwreg_cfg.addr, &regvalue);
+	if (ret < 0) {
+		dev_err(dev, "abx500_get_reg fail %d, %d\n",
+			ret, __LINE__);
+		return -EINVAL;
+	}
+
+	if (hwreg_cfg.shift >= 0)
+		regvalue >>= hwreg_cfg.shift;
+	else
+		regvalue <<= -hwreg_cfg.shift;
+	regvalue &= hwreg_cfg.mask;
+
+	if (REG_FMT_DEC(&hwreg_cfg))
+		seq_printf(s, "%d\n", regvalue);
+	else
+		seq_printf(s, "0x%02X\n", regvalue);
+	return 0;
+}
+
+static int ab8500_hwreg_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, ab8500_hwreg_print, inode->i_private);
+}
+
+#define AB8500_SUPPLY_CONTROL_CONFIG_1 0x01
+#define AB8500_SUPPLY_CONTROL_REG 0x00
+#define AB8500_FIRST_SIM_REG 0x80
+#define AB8500_LAST_SIM_REG 0x8B
+#define AB8505_LAST_SIM_REG 0x8C
+
+static int ab8500_print_modem_registers(struct seq_file *s, void *p)
+{
+	struct device *dev = s->private;
+	struct ab8500 *ab8500;
+	int err;
+	u8 value;
+	u8 orig_value;
+	u32 bank = AB8500_REGU_CTRL2;
+	u32 last_sim_reg = AB8500_LAST_SIM_REG;
+	u32 reg;
+
+	ab8500 = dev_get_drvdata(dev->parent);
+	dev_warn(dev, "WARNING! This operation can interfer with modem side\n"
+		"and should only be done with care\n");
+
+	err = abx500_get_register_interruptible(dev,
+		AB8500_REGU_CTRL1, AB8500_SUPPLY_CONTROL_REG, &orig_value);
+	if (err < 0) {
+		dev_err(dev, "ab->read fail %d\n", err);
+		return err;
+	}
+	/* Config 1 will allow APE side to read SIM registers */
+	err = abx500_set_register_interruptible(dev,
+		AB8500_REGU_CTRL1, AB8500_SUPPLY_CONTROL_REG,
+		AB8500_SUPPLY_CONTROL_CONFIG_1);
+	if (err < 0) {
+		dev_err(dev, "ab->write fail %d\n", err);
+		return err;
+	}
+
+	seq_printf(s, " bank 0x%02X:\n", bank);
+
+	if (is_ab9540(ab8500) || is_ab8505(ab8500))
+		last_sim_reg = AB8505_LAST_SIM_REG;
+
+	for (reg = AB8500_FIRST_SIM_REG; reg <= last_sim_reg; reg++) {
+		err = abx500_get_register_interruptible(dev,
+			bank, reg, &value);
+		if (err < 0) {
+			dev_err(dev, "ab->read fail %d\n", err);
+			return err;
+		}
+		err = seq_printf(s, "  [0x%02X/0x%02X]: 0x%02X\n",
+			bank, reg, value);
+	}
+	err = abx500_set_register_interruptible(dev,
+		AB8500_REGU_CTRL1, AB8500_SUPPLY_CONTROL_REG, orig_value);
+	if (err < 0) {
+		dev_err(dev, "ab->write fail %d\n", err);
+		return err;
+	}
+	return 0;
+}
+
+static int ab8500_modem_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, ab8500_print_modem_registers, inode->i_private);
+}
+
+static const struct file_operations ab8500_modem_fops = {
+	.open = ab8500_modem_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+	.owner = THIS_MODULE,
+};
+
+static int ab8500_gpadc_bat_ctrl_print(struct seq_file *s, void *p)
+{
+	int bat_ctrl_raw;
+	int bat_ctrl_convert;
+	struct ab8500_gpadc *gpadc;
+
+	gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
+	bat_ctrl_raw = ab8500_gpadc_read_raw(gpadc, BAT_CTRL,
+		avg_sample, trig_edge, trig_timer, conv_type);
+	bat_ctrl_convert = ab8500_gpadc_ad_to_voltage(gpadc,
+		BAT_CTRL, bat_ctrl_raw);
+
+	return seq_printf(s, "%d,0x%X\n",
+		bat_ctrl_convert, bat_ctrl_raw);
+}
+
+static int ab8500_gpadc_bat_ctrl_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, ab8500_gpadc_bat_ctrl_print, inode->i_private);
+}
+
+static const struct file_operations ab8500_gpadc_bat_ctrl_fops = {
+	.open = ab8500_gpadc_bat_ctrl_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+	.owner = THIS_MODULE,
+};
+
+static int ab8500_gpadc_btemp_ball_print(struct seq_file *s, void *p)
+{
+	int btemp_ball_raw;
+	int btemp_ball_convert;
+	struct ab8500_gpadc *gpadc;
+
+	gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
+	btemp_ball_raw = ab8500_gpadc_read_raw(gpadc, BTEMP_BALL,
+		avg_sample, trig_edge, trig_timer, conv_type);
+	btemp_ball_convert = ab8500_gpadc_ad_to_voltage(gpadc, BTEMP_BALL,
+		btemp_ball_raw);
+
+	return seq_printf(s,
+		"%d,0x%X\n", btemp_ball_convert, btemp_ball_raw);
+}
+
+static int ab8500_gpadc_btemp_ball_open(struct inode *inode,
+					struct file *file)
+{
+	return single_open(file, ab8500_gpadc_btemp_ball_print, inode->i_private);
+}
+
+static const struct file_operations ab8500_gpadc_btemp_ball_fops = {
+	.open = ab8500_gpadc_btemp_ball_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+	.owner = THIS_MODULE,
+};
+
+static int ab8500_gpadc_main_charger_v_print(struct seq_file *s, void *p)
+{
+	int main_charger_v_raw;
+	int main_charger_v_convert;
+	struct ab8500_gpadc *gpadc;
+
+	gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
+	main_charger_v_raw = ab8500_gpadc_read_raw(gpadc, MAIN_CHARGER_V,
+		avg_sample, trig_edge, trig_timer, conv_type);
+	main_charger_v_convert = ab8500_gpadc_ad_to_voltage(gpadc,
+		MAIN_CHARGER_V, main_charger_v_raw);
+
+	return seq_printf(s, "%d,0x%X\n",
+			main_charger_v_convert, main_charger_v_raw);
+}
+
+static int ab8500_gpadc_main_charger_v_open(struct inode *inode,
+					    struct file *file)
 {
-	if (line < num_interrupt_lines)
-		num_interrupts[line]++;
+	return single_open(file, ab8500_gpadc_main_charger_v_print,
+		inode->i_private);
 }
 
-static int ab8500_interrupts_print(struct seq_file *s, void *p)
+static const struct file_operations ab8500_gpadc_main_charger_v_fops = {
+	.open = ab8500_gpadc_main_charger_v_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+	.owner = THIS_MODULE,
+};
+
+static int ab8500_gpadc_acc_detect1_print(struct seq_file *s, void *p)
 {
-	int line;
+	int acc_detect1_raw;
+	int acc_detect1_convert;
+	struct ab8500_gpadc *gpadc;
 
-	seq_printf(s, "irq:  number of\n");
+	gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
+	acc_detect1_raw = ab8500_gpadc_read_raw(gpadc, ACC_DETECT1,
+		avg_sample, trig_edge, trig_timer, conv_type);
+	acc_detect1_convert = ab8500_gpadc_ad_to_voltage(gpadc, ACC_DETECT1,
+		acc_detect1_raw);
 
-	for (line = 0; line < num_interrupt_lines; line++)
-		seq_printf(s, "%3i:  %6i\n", line, num_interrupts[line]);
+	return seq_printf(s, "%d,0x%X\n",
+		acc_detect1_convert, acc_detect1_raw);
+}
 
-	return 0;
+static int ab8500_gpadc_acc_detect1_open(struct inode *inode,
+					 struct file *file)
+{
+	return single_open(file, ab8500_gpadc_acc_detect1_print,
+		inode->i_private);
 }
 
-static int ab8500_interrupts_open(struct inode *inode, struct file *file)
+static const struct file_operations ab8500_gpadc_acc_detect1_fops = {
+	.open = ab8500_gpadc_acc_detect1_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+	.owner = THIS_MODULE,
+};
+
+static int ab8500_gpadc_acc_detect2_print(struct seq_file *s, void *p)
 {
-	return single_open(file, ab8500_interrupts_print, inode->i_private);
+	int acc_detect2_raw;
+	int acc_detect2_convert;
+	struct ab8500_gpadc *gpadc;
+
+	gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
+	acc_detect2_raw = ab8500_gpadc_read_raw(gpadc, ACC_DETECT2,
+		avg_sample, trig_edge, trig_timer, conv_type);
+	acc_detect2_convert = ab8500_gpadc_ad_to_voltage(gpadc,
+		ACC_DETECT2, acc_detect2_raw);
+
+	return seq_printf(s, "%d,0x%X\n",
+		acc_detect2_convert, acc_detect2_raw);
 }
 
-/*
- * - HWREG DB8500 formated routines
- */
-static int ab8500_hwreg_print(struct seq_file *s, void *d)
+static int ab8500_gpadc_acc_detect2_open(struct inode *inode,
+		struct file *file)
 {
-	struct device *dev = s->private;
-	int ret;
-	u8 regvalue;
+	return single_open(file, ab8500_gpadc_acc_detect2_print,
+		inode->i_private);
+}
 
-	ret = abx500_get_register_interruptible(dev,
-		(u8)hwreg_cfg.bank, (u8)hwreg_cfg.addr, &regvalue);
-	if (ret < 0) {
-		dev_err(dev, "abx500_get_reg fail %d, %d\n",
-			ret, __LINE__);
-		return -EINVAL;
-	}
+static const struct file_operations ab8500_gpadc_acc_detect2_fops = {
+	.open = ab8500_gpadc_acc_detect2_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+	.owner = THIS_MODULE,
+};
 
-	if (hwreg_cfg.shift >= 0)
-		regvalue >>= hwreg_cfg.shift;
-	else
-		regvalue <<= -hwreg_cfg.shift;
-	regvalue &= hwreg_cfg.mask;
+static int ab8500_gpadc_aux1_print(struct seq_file *s, void *p)
+{
+	int aux1_raw;
+	int aux1_convert;
+	struct ab8500_gpadc *gpadc;
 
-	if (REG_FMT_DEC(&hwreg_cfg))
-		seq_printf(s, "%d\n", regvalue);
-	else
-		seq_printf(s, "0x%02X\n", regvalue);
-	return 0;
+	gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
+	aux1_raw = ab8500_gpadc_read_raw(gpadc, ADC_AUX1,
+		avg_sample, trig_edge, trig_timer, conv_type);
+	aux1_convert = ab8500_gpadc_ad_to_voltage(gpadc, ADC_AUX1,
+		aux1_raw);
+
+	return seq_printf(s, "%d,0x%X\n",
+		aux1_convert, aux1_raw);
 }
 
-static int ab8500_hwreg_open(struct inode *inode, struct file *file)
+static int ab8500_gpadc_aux1_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, ab8500_hwreg_print, inode->i_private);
+	return single_open(file, ab8500_gpadc_aux1_print, inode->i_private);
+}
+
+static const struct file_operations ab8500_gpadc_aux1_fops = {
+	.open = ab8500_gpadc_aux1_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+	.owner = THIS_MODULE,
+};
+
+static int ab8500_gpadc_aux2_print(struct seq_file *s, void *p)
+{
+	int aux2_raw;
+	int aux2_convert;
+	struct ab8500_gpadc *gpadc;
+
+	gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
+	aux2_raw = ab8500_gpadc_read_raw(gpadc, ADC_AUX2,
+		avg_sample, trig_edge, trig_timer, conv_type);
+	aux2_convert = ab8500_gpadc_ad_to_voltage(gpadc, ADC_AUX2,
+		aux2_raw);
+
+	return seq_printf(s, "%d,0x%X\n",
+			aux2_convert, aux2_raw);
+}
+
+static int ab8500_gpadc_aux2_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, ab8500_gpadc_aux2_print, inode->i_private);
+}
+
+static const struct file_operations ab8500_gpadc_aux2_fops = {
+	.open = ab8500_gpadc_aux2_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+	.owner = THIS_MODULE,
+};
+
+static int ab8500_gpadc_main_bat_v_print(struct seq_file *s, void *p)
+{
+	int main_bat_v_raw;
+	int main_bat_v_convert;
+	struct ab8500_gpadc *gpadc;
+
+	gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
+	main_bat_v_raw = ab8500_gpadc_read_raw(gpadc, MAIN_BAT_V,
+		avg_sample, trig_edge, trig_timer, conv_type);
+	main_bat_v_convert = ab8500_gpadc_ad_to_voltage(gpadc, MAIN_BAT_V,
+		main_bat_v_raw);
+
+	return seq_printf(s, "%d,0x%X\n",
+		main_bat_v_convert, main_bat_v_raw);
+}
+
+static int ab8500_gpadc_main_bat_v_open(struct inode *inode,
+					struct file *file)
+{
+	return single_open(file, ab8500_gpadc_main_bat_v_print, inode->i_private);
+}
+
+static const struct file_operations ab8500_gpadc_main_bat_v_fops = {
+	.open = ab8500_gpadc_main_bat_v_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+	.owner = THIS_MODULE,
+};
+
+static int ab8500_gpadc_vbus_v_print(struct seq_file *s, void *p)
+{
+	int vbus_v_raw;
+	int vbus_v_convert;
+	struct ab8500_gpadc *gpadc;
+
+	gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
+	vbus_v_raw =  ab8500_gpadc_read_raw(gpadc, VBUS_V,
+		avg_sample, trig_edge, trig_timer, conv_type);
+	vbus_v_convert = ab8500_gpadc_ad_to_voltage(gpadc, VBUS_V,
+		vbus_v_raw);
+
+	return seq_printf(s, "%d,0x%X\n",
+		vbus_v_convert, vbus_v_raw);
+}
+
+static int ab8500_gpadc_vbus_v_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, ab8500_gpadc_vbus_v_print, inode->i_private);
+}
+
+static const struct file_operations ab8500_gpadc_vbus_v_fops = {
+	.open = ab8500_gpadc_vbus_v_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+	.owner = THIS_MODULE,
+};
+
+static int ab8500_gpadc_main_charger_c_print(struct seq_file *s, void *p)
+{
+	int main_charger_c_raw;
+	int main_charger_c_convert;
+	struct ab8500_gpadc *gpadc;
+
+	gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
+	main_charger_c_raw = ab8500_gpadc_read_raw(gpadc, MAIN_CHARGER_C,
+		avg_sample, trig_edge, trig_timer, conv_type);
+	main_charger_c_convert = ab8500_gpadc_ad_to_voltage(gpadc,
+		MAIN_CHARGER_C, main_charger_c_raw);
+
+	return seq_printf(s, "%d,0x%X\n",
+		main_charger_c_convert, main_charger_c_raw);
+}
+
+static int ab8500_gpadc_main_charger_c_open(struct inode *inode,
+		struct file *file)
+{
+	return single_open(file, ab8500_gpadc_main_charger_c_print,
+		inode->i_private);
+}
+
+static const struct file_operations ab8500_gpadc_main_charger_c_fops = {
+	.open = ab8500_gpadc_main_charger_c_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+	.owner = THIS_MODULE,
+};
+
+static int ab8500_gpadc_usb_charger_c_print(struct seq_file *s, void *p)
+{
+	int usb_charger_c_raw;
+	int usb_charger_c_convert;
+	struct ab8500_gpadc *gpadc;
+
+	gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
+	usb_charger_c_raw = ab8500_gpadc_read_raw(gpadc, USB_CHARGER_C,
+		avg_sample, trig_edge, trig_timer, conv_type);
+	usb_charger_c_convert = ab8500_gpadc_ad_to_voltage(gpadc,
+		USB_CHARGER_C, usb_charger_c_raw);
+
+	return seq_printf(s, "%d,0x%X\n",
+		usb_charger_c_convert, usb_charger_c_raw);
+}
+
+static int ab8500_gpadc_usb_charger_c_open(struct inode *inode,
+		struct file *file)
+{
+	return single_open(file, ab8500_gpadc_usb_charger_c_print,
+		inode->i_private);
+}
+
+static const struct file_operations ab8500_gpadc_usb_charger_c_fops = {
+	.open = ab8500_gpadc_usb_charger_c_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+	.owner = THIS_MODULE,
+};
+
+static int ab8500_gpadc_bk_bat_v_print(struct seq_file *s, void *p)
+{
+	int bk_bat_v_raw;
+	int bk_bat_v_convert;
+	struct ab8500_gpadc *gpadc;
+
+	gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
+	bk_bat_v_raw = ab8500_gpadc_read_raw(gpadc, BK_BAT_V,
+		avg_sample, trig_edge, trig_timer, conv_type);
+	bk_bat_v_convert = ab8500_gpadc_ad_to_voltage(gpadc,
+		BK_BAT_V, bk_bat_v_raw);
+
+	return seq_printf(s, "%d,0x%X\n",
+		bk_bat_v_convert, bk_bat_v_raw);
+}
+
+static int ab8500_gpadc_bk_bat_v_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, ab8500_gpadc_bk_bat_v_print, inode->i_private);
 }
 
-static int ab8500_gpadc_bat_ctrl_print(struct seq_file *s, void *p)
+static const struct file_operations ab8500_gpadc_bk_bat_v_fops = {
+	.open = ab8500_gpadc_bk_bat_v_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+	.owner = THIS_MODULE,
+};
+
+static int ab8500_gpadc_die_temp_print(struct seq_file *s, void *p)
 {
-	int bat_ctrl_raw;
-	int bat_ctrl_convert;
+	int die_temp_raw;
+	int die_temp_convert;
 	struct ab8500_gpadc *gpadc;
 
 	gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
-	bat_ctrl_raw = ab8500_gpadc_read_raw(gpadc, BAT_CTRL);
-	bat_ctrl_convert = ab8500_gpadc_ad_to_voltage(gpadc,
-			BAT_CTRL, bat_ctrl_raw);
+	die_temp_raw = ab8500_gpadc_read_raw(gpadc, DIE_TEMP,
+		avg_sample, trig_edge, trig_timer, conv_type);
+	die_temp_convert = ab8500_gpadc_ad_to_voltage(gpadc, DIE_TEMP,
+		die_temp_raw);
 
 	return seq_printf(s, "%d,0x%X\n",
-			bat_ctrl_convert, bat_ctrl_raw);
+		die_temp_convert, die_temp_raw);
 }
 
-static int ab8500_gpadc_bat_ctrl_open(struct inode *inode, struct file *file)
+static int ab8500_gpadc_die_temp_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, ab8500_gpadc_bat_ctrl_print, inode->i_private);
+	return single_open(file, ab8500_gpadc_die_temp_print, inode->i_private);
 }
 
-static const struct file_operations ab8500_gpadc_bat_ctrl_fops = {
-	.open = ab8500_gpadc_bat_ctrl_open,
+static const struct file_operations ab8500_gpadc_die_temp_fops = {
+	.open = ab8500_gpadc_die_temp_open,
 	.read = seq_read,
 	.llseek = seq_lseek,
 	.release = single_release,
 	.owner = THIS_MODULE,
 };
 
-static int ab8500_gpadc_btemp_ball_print(struct seq_file *s, void *p)
+static int ab8500_gpadc_usb_id_print(struct seq_file *s, void *p)
 {
-	int btemp_ball_raw;
-	int btemp_ball_convert;
+	int usb_id_raw;
+	int usb_id_convert;
 	struct ab8500_gpadc *gpadc;
 
 	gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
-	btemp_ball_raw = ab8500_gpadc_read_raw(gpadc, BTEMP_BALL);
-	btemp_ball_convert = ab8500_gpadc_ad_to_voltage(gpadc, BTEMP_BALL,
-			btemp_ball_raw);
+	usb_id_raw = ab8500_gpadc_read_raw(gpadc, USB_ID,
+		avg_sample, trig_edge, trig_timer, conv_type);
+	usb_id_convert = ab8500_gpadc_ad_to_voltage(gpadc, USB_ID,
+		usb_id_raw);
 
-	return seq_printf(s,
-			"%d,0x%X\n", btemp_ball_convert, btemp_ball_raw);
+	return seq_printf(s, "%d,0x%X\n",
+		usb_id_convert, usb_id_raw);
 }
 
-static int ab8500_gpadc_btemp_ball_open(struct inode *inode,
-		struct file *file)
+static int ab8500_gpadc_usb_id_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, ab8500_gpadc_btemp_ball_print, inode->i_private);
+	return single_open(file, ab8500_gpadc_usb_id_print, inode->i_private);
 }
 
-static const struct file_operations ab8500_gpadc_btemp_ball_fops = {
-	.open = ab8500_gpadc_btemp_ball_open,
+static const struct file_operations ab8500_gpadc_usb_id_fops = {
+	.open = ab8500_gpadc_usb_id_open,
 	.read = seq_read,
 	.llseek = seq_lseek,
 	.release = single_release,
 	.owner = THIS_MODULE,
 };
 
-static int ab8500_gpadc_main_charger_v_print(struct seq_file *s, void *p)
+static int ab8540_gpadc_xtal_temp_print(struct seq_file *s, void *p)
 {
-	int main_charger_v_raw;
-	int main_charger_v_convert;
+	int xtal_temp_raw;
+	int xtal_temp_convert;
 	struct ab8500_gpadc *gpadc;
 
 	gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
-	main_charger_v_raw = ab8500_gpadc_read_raw(gpadc, MAIN_CHARGER_V);
-	main_charger_v_convert = ab8500_gpadc_ad_to_voltage(gpadc,
-			MAIN_CHARGER_V, main_charger_v_raw);
+	xtal_temp_raw = ab8500_gpadc_read_raw(gpadc, XTAL_TEMP,
+		avg_sample, trig_edge, trig_timer, conv_type);
+	xtal_temp_convert = ab8500_gpadc_ad_to_voltage(gpadc, XTAL_TEMP,
+		xtal_temp_raw);
 
 	return seq_printf(s, "%d,0x%X\n",
-			main_charger_v_convert, main_charger_v_raw);
+		xtal_temp_convert, xtal_temp_raw);
 }
 
-static int ab8500_gpadc_main_charger_v_open(struct inode *inode,
-		struct file *file)
+static int ab8540_gpadc_xtal_temp_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, ab8500_gpadc_main_charger_v_print,
-			inode->i_private);
+	return single_open(file, ab8540_gpadc_xtal_temp_print,
+		inode->i_private);
 }
 
-static const struct file_operations ab8500_gpadc_main_charger_v_fops = {
-	.open = ab8500_gpadc_main_charger_v_open,
+static const struct file_operations ab8540_gpadc_xtal_temp_fops = {
+	.open = ab8540_gpadc_xtal_temp_open,
 	.read = seq_read,
 	.llseek = seq_lseek,
 	.release = single_release,
 	.owner = THIS_MODULE,
 };
 
-static int ab8500_gpadc_acc_detect1_print(struct seq_file *s, void *p)
+static int ab8540_gpadc_vbat_true_meas_print(struct seq_file *s, void *p)
 {
-	int acc_detect1_raw;
-	int acc_detect1_convert;
+	int vbat_true_meas_raw;
+	int vbat_true_meas_convert;
 	struct ab8500_gpadc *gpadc;
 
 	gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
-	acc_detect1_raw = ab8500_gpadc_read_raw(gpadc, ACC_DETECT1);
-	acc_detect1_convert = ab8500_gpadc_ad_to_voltage(gpadc, ACC_DETECT1,
-			acc_detect1_raw);
+	vbat_true_meas_raw = ab8500_gpadc_read_raw(gpadc, VBAT_TRUE_MEAS,
+		avg_sample, trig_edge, trig_timer, conv_type);
+	vbat_true_meas_convert = ab8500_gpadc_ad_to_voltage(gpadc, VBAT_TRUE_MEAS,
+		vbat_true_meas_raw);
 
 	return seq_printf(s, "%d,0x%X\n",
-			acc_detect1_convert, acc_detect1_raw);
+		vbat_true_meas_convert, vbat_true_meas_raw);
 }
 
-static int ab8500_gpadc_acc_detect1_open(struct inode *inode,
+static int ab8540_gpadc_vbat_true_meas_open(struct inode *inode,
 		struct file *file)
 {
-	return single_open(file, ab8500_gpadc_acc_detect1_print,
-			inode->i_private);
+	return single_open(file, ab8540_gpadc_vbat_true_meas_print,
+		inode->i_private);
 }
 
-static const struct file_operations ab8500_gpadc_acc_detect1_fops = {
-	.open = ab8500_gpadc_acc_detect1_open,
+static const struct file_operations ab8540_gpadc_vbat_true_meas_fops = {
+	.open = ab8540_gpadc_vbat_true_meas_open,
 	.read = seq_read,
 	.llseek = seq_lseek,
 	.release = single_release,
 	.owner = THIS_MODULE,
 };
 
-static int ab8500_gpadc_acc_detect2_print(struct seq_file *s, void *p)
+static int ab8540_gpadc_bat_ctrl_and_ibat_print(struct seq_file *s, void *p)
 {
-	int acc_detect2_raw;
-	int acc_detect2_convert;
+	int bat_ctrl_raw;
+	int bat_ctrl_convert;
+	int ibat_raw;
+	int ibat_convert;
 	struct ab8500_gpadc *gpadc;
 
 	gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
-	acc_detect2_raw = ab8500_gpadc_read_raw(gpadc, ACC_DETECT2);
-	acc_detect2_convert = ab8500_gpadc_ad_to_voltage(gpadc,
-	    ACC_DETECT2, acc_detect2_raw);
+	bat_ctrl_raw = ab8500_gpadc_double_read_raw(gpadc, BAT_CTRL_AND_IBAT,
+		avg_sample, trig_edge, trig_timer, conv_type, &ibat_raw);
 
-	return seq_printf(s, "%d,0x%X\n",
-			acc_detect2_convert, acc_detect2_raw);
+	bat_ctrl_convert = ab8500_gpadc_ad_to_voltage(gpadc, BAT_CTRL,
+		bat_ctrl_raw);
+	ibat_convert = ab8500_gpadc_ad_to_voltage(gpadc, IBAT_VIRTUAL_CHANNEL,
+		ibat_raw);
+
+	return seq_printf(s, "%d,0x%X\n"  "%d,0x%X\n",
+		bat_ctrl_convert, bat_ctrl_raw,
+		ibat_convert, ibat_raw);
 }
 
-static int ab8500_gpadc_acc_detect2_open(struct inode *inode,
+static int ab8540_gpadc_bat_ctrl_and_ibat_open(struct inode *inode,
 		struct file *file)
 {
-	return single_open(file, ab8500_gpadc_acc_detect2_print,
-	    inode->i_private);
+	return single_open(file, ab8540_gpadc_bat_ctrl_and_ibat_print,
+		inode->i_private);
 }
 
-static const struct file_operations ab8500_gpadc_acc_detect2_fops = {
-	.open = ab8500_gpadc_acc_detect2_open,
+static const struct file_operations ab8540_gpadc_bat_ctrl_and_ibat_fops = {
+	.open = ab8540_gpadc_bat_ctrl_and_ibat_open,
 	.read = seq_read,
 	.llseek = seq_lseek,
 	.release = single_release,
 	.owner = THIS_MODULE,
 };
 
-static int ab8500_gpadc_aux1_print(struct seq_file *s, void *p)
+static int ab8540_gpadc_vbat_meas_and_ibat_print(struct seq_file *s, void *p)
 {
-	int aux1_raw;
-	int aux1_convert;
+	int vbat_meas_raw;
+	int vbat_meas_convert;
+	int ibat_raw;
+	int ibat_convert;
 	struct ab8500_gpadc *gpadc;
 
 	gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
-	aux1_raw = ab8500_gpadc_read_raw(gpadc, ADC_AUX1);
-	aux1_convert = ab8500_gpadc_ad_to_voltage(gpadc, ADC_AUX1,
-			aux1_raw);
-
-	return seq_printf(s, "%d,0x%X\n",
-			aux1_convert, aux1_raw);
+	vbat_meas_raw = ab8500_gpadc_double_read_raw(gpadc, VBAT_MEAS_AND_IBAT,
+		avg_sample, trig_edge, trig_timer, conv_type, &ibat_raw);
+	vbat_meas_convert = ab8500_gpadc_ad_to_voltage(gpadc, MAIN_BAT_V,
+		vbat_meas_raw);
+	ibat_convert = ab8500_gpadc_ad_to_voltage(gpadc, IBAT_VIRTUAL_CHANNEL,
+		ibat_raw);
+
+	return seq_printf(s, "%d,0x%X\n"  "%d,0x%X\n",
+		vbat_meas_convert, vbat_meas_raw,
+		ibat_convert, ibat_raw);
 }
 
-static int ab8500_gpadc_aux1_open(struct inode *inode, struct file *file)
+static int ab8540_gpadc_vbat_meas_and_ibat_open(struct inode *inode,
+		struct file *file)
 {
-	return single_open(file, ab8500_gpadc_aux1_print, inode->i_private);
+	return single_open(file, ab8540_gpadc_vbat_meas_and_ibat_print,
+		inode->i_private);
 }
 
-static const struct file_operations ab8500_gpadc_aux1_fops = {
-	.open = ab8500_gpadc_aux1_open,
+static const struct file_operations ab8540_gpadc_vbat_meas_and_ibat_fops = {
+	.open = ab8540_gpadc_vbat_meas_and_ibat_open,
 	.read = seq_read,
 	.llseek = seq_lseek,
 	.release = single_release,
 	.owner = THIS_MODULE,
 };
 
-static int ab8500_gpadc_aux2_print(struct seq_file *s, void *p)
+static int ab8540_gpadc_vbat_true_meas_and_ibat_print(struct seq_file *s, void *p)
 {
-	int aux2_raw;
-	int aux2_convert;
+	int vbat_true_meas_raw;
+	int vbat_true_meas_convert;
+	int ibat_raw;
+	int ibat_convert;
 	struct ab8500_gpadc *gpadc;
 
 	gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
-	aux2_raw = ab8500_gpadc_read_raw(gpadc, ADC_AUX2);
-	aux2_convert = ab8500_gpadc_ad_to_voltage(gpadc, ADC_AUX2,
-			aux2_raw);
-
-	return seq_printf(s, "%d,0x%X\n",
-			aux2_convert, aux2_raw);
+	vbat_true_meas_raw = ab8500_gpadc_double_read_raw(gpadc,
+			VBAT_TRUE_MEAS_AND_IBAT, avg_sample, trig_edge,
+			trig_timer, conv_type, &ibat_raw);
+	vbat_true_meas_convert = ab8500_gpadc_ad_to_voltage(gpadc,
+			VBAT_TRUE_MEAS, vbat_true_meas_raw);
+	ibat_convert = ab8500_gpadc_ad_to_voltage(gpadc, IBAT_VIRTUAL_CHANNEL,
+		ibat_raw);
+
+	return seq_printf(s, "%d,0x%X\n"  "%d,0x%X\n",
+		vbat_true_meas_convert, vbat_true_meas_raw,
+		ibat_convert, ibat_raw);
 }
 
-static int ab8500_gpadc_aux2_open(struct inode *inode, struct file *file)
+static int ab8540_gpadc_vbat_true_meas_and_ibat_open(struct inode *inode,
+		struct file *file)
 {
-	return single_open(file, ab8500_gpadc_aux2_print, inode->i_private);
+	return single_open(file, ab8540_gpadc_vbat_true_meas_and_ibat_print,
+		inode->i_private);
 }
 
-static const struct file_operations ab8500_gpadc_aux2_fops = {
-	.open = ab8500_gpadc_aux2_open,
+static const struct file_operations ab8540_gpadc_vbat_true_meas_and_ibat_fops = {
+	.open = ab8540_gpadc_vbat_true_meas_and_ibat_open,
 	.read = seq_read,
 	.llseek = seq_lseek,
 	.release = single_release,
 	.owner = THIS_MODULE,
 };
 
-static int ab8500_gpadc_main_bat_v_print(struct seq_file *s, void *p)
+static int ab8540_gpadc_bat_temp_and_ibat_print(struct seq_file *s, void *p)
 {
-	int main_bat_v_raw;
-	int main_bat_v_convert;
+	int bat_temp_raw;
+	int bat_temp_convert;
+	int ibat_raw;
+	int ibat_convert;
 	struct ab8500_gpadc *gpadc;
 
 	gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
-	main_bat_v_raw = ab8500_gpadc_read_raw(gpadc, MAIN_BAT_V);
-	main_bat_v_convert = ab8500_gpadc_ad_to_voltage(gpadc, MAIN_BAT_V,
-			main_bat_v_raw);
-
-	return seq_printf(s, "%d,0x%X\n",
-			main_bat_v_convert, main_bat_v_raw);
+	bat_temp_raw = ab8500_gpadc_double_read_raw(gpadc, BAT_TEMP_AND_IBAT,
+		avg_sample, trig_edge, trig_timer, conv_type, &ibat_raw);
+	bat_temp_convert = ab8500_gpadc_ad_to_voltage(gpadc, BTEMP_BALL,
+		bat_temp_raw);
+	ibat_convert = ab8500_gpadc_ad_to_voltage(gpadc, IBAT_VIRTUAL_CHANNEL,
+		ibat_raw);
+
+	return seq_printf(s, "%d,0x%X\n"  "%d,0x%X\n",
+		bat_temp_convert, bat_temp_raw,
+		ibat_convert, ibat_raw);
 }
 
-static int ab8500_gpadc_main_bat_v_open(struct inode *inode,
+static int ab8540_gpadc_bat_temp_and_ibat_open(struct inode *inode,
 		struct file *file)
 {
-	return single_open(file, ab8500_gpadc_main_bat_v_print, inode->i_private);
+	return single_open(file, ab8540_gpadc_bat_temp_and_ibat_print,
+		inode->i_private);
 }
 
-static const struct file_operations ab8500_gpadc_main_bat_v_fops = {
-	.open = ab8500_gpadc_main_bat_v_open,
+static const struct file_operations ab8540_gpadc_bat_temp_and_ibat_fops = {
+	.open = ab8540_gpadc_bat_temp_and_ibat_open,
 	.read = seq_read,
 	.llseek = seq_lseek,
 	.release = single_release,
 	.owner = THIS_MODULE,
 };
 
-static int ab8500_gpadc_vbus_v_print(struct seq_file *s, void *p)
+static int ab8540_gpadc_otp_cal_print(struct seq_file *s, void *p)
 {
-	int vbus_v_raw;
-	int vbus_v_convert;
 	struct ab8500_gpadc *gpadc;
+	u16 vmain_l, vmain_h, btemp_l, btemp_h;
+	u16 vbat_l, vbat_h, ibat_l, ibat_h;
 
 	gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
-	vbus_v_raw = ab8500_gpadc_read_raw(gpadc, VBUS_V);
-	vbus_v_convert = ab8500_gpadc_ad_to_voltage(gpadc, VBUS_V,
-			vbus_v_raw);
-
-	return seq_printf(s, "%d,0x%X\n",
-			vbus_v_convert, vbus_v_raw);
+	ab8540_gpadc_get_otp(gpadc, &vmain_l, &vmain_h, &btemp_l, &btemp_h,
+			&vbat_l, &vbat_h, &ibat_l, &ibat_h);
+	return seq_printf(s, "VMAIN_L:0x%X\n"
+		"VMAIN_H:0x%X\n"
+		"BTEMP_L:0x%X\n"
+		"BTEMP_H:0x%X\n"
+		"VBAT_L:0x%X\n"
+		"VBAT_H:0x%X\n"
+		"IBAT_L:0x%X\n"
+		"IBAT_H:0x%X\n",
+		vmain_l, vmain_h, btemp_l, btemp_h, vbat_l, vbat_h, ibat_l, ibat_h);
 }
 
-static int ab8500_gpadc_vbus_v_open(struct inode *inode, struct file *file)
+static int ab8540_gpadc_otp_cal_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, ab8500_gpadc_vbus_v_print, inode->i_private);
+	return single_open(file, ab8540_gpadc_otp_cal_print, inode->i_private);
 }
 
-static const struct file_operations ab8500_gpadc_vbus_v_fops = {
-	.open = ab8500_gpadc_vbus_v_open,
+static const struct file_operations ab8540_gpadc_otp_calib_fops = {
+	.open = ab8540_gpadc_otp_cal_open,
 	.read = seq_read,
 	.llseek = seq_lseek,
 	.release = single_release,
 	.owner = THIS_MODULE,
 };
 
-static int ab8500_gpadc_main_charger_c_print(struct seq_file *s, void *p)
+static int ab8500_gpadc_avg_sample_print(struct seq_file *s, void *p)
 {
-	int main_charger_c_raw;
-	int main_charger_c_convert;
-	struct ab8500_gpadc *gpadc;
-
-	gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
-	main_charger_c_raw = ab8500_gpadc_read_raw(gpadc, MAIN_CHARGER_C);
-	main_charger_c_convert = ab8500_gpadc_ad_to_voltage(gpadc,
-			MAIN_CHARGER_C, main_charger_c_raw);
+	return seq_printf(s, "%d\n", avg_sample);
+}
 
-	return seq_printf(s, "%d,0x%X\n",
-			main_charger_c_convert, main_charger_c_raw);
+static int ab8500_gpadc_avg_sample_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, ab8500_gpadc_avg_sample_print,
+		inode->i_private);
 }
 
-static int ab8500_gpadc_main_charger_c_open(struct inode *inode,
-		struct file *file)
+static ssize_t ab8500_gpadc_avg_sample_write(struct file *file,
+	const char __user *user_buf,
+	size_t count, loff_t *ppos)
 {
-	return single_open(file, ab8500_gpadc_main_charger_c_print,
-			inode->i_private);
+	struct device *dev = ((struct seq_file *)(file->private_data))->private;
+	unsigned long user_avg_sample;
+	int err;
+
+	err = kstrtoul_from_user(user_buf, count, 0, &user_avg_sample);
+	if (err)
+		return err;
+
+	if ((user_avg_sample == SAMPLE_1) || (user_avg_sample == SAMPLE_4)
+			|| (user_avg_sample == SAMPLE_8)
+			|| (user_avg_sample == SAMPLE_16)) {
+		avg_sample = (u8) user_avg_sample;
+	} else {
+		dev_err(dev, "debugfs error input: "
+			"should be egal to 1, 4, 8 or 16\n");
+		return -EINVAL;
+	}
+
+	return count;
 }
 
-static const struct file_operations ab8500_gpadc_main_charger_c_fops = {
-	.open = ab8500_gpadc_main_charger_c_open,
+static const struct file_operations ab8500_gpadc_avg_sample_fops = {
+	.open = ab8500_gpadc_avg_sample_open,
 	.read = seq_read,
+	.write = ab8500_gpadc_avg_sample_write,
 	.llseek = seq_lseek,
 	.release = single_release,
 	.owner = THIS_MODULE,
 };
 
-static int ab8500_gpadc_usb_charger_c_print(struct seq_file *s, void *p)
+static int ab8500_gpadc_trig_edge_print(struct seq_file *s, void *p)
 {
-	int usb_charger_c_raw;
-	int usb_charger_c_convert;
-	struct ab8500_gpadc *gpadc;
-
-	gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
-	usb_charger_c_raw = ab8500_gpadc_read_raw(gpadc, USB_CHARGER_C);
-	usb_charger_c_convert = ab8500_gpadc_ad_to_voltage(gpadc,
-	    USB_CHARGER_C, usb_charger_c_raw);
+	return seq_printf(s, "%d\n", trig_edge);
+}
 
-	return seq_printf(s, "%d,0x%X\n",
-			usb_charger_c_convert, usb_charger_c_raw);
+static int ab8500_gpadc_trig_edge_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, ab8500_gpadc_trig_edge_print,
+		inode->i_private);
 }
 
-static int ab8500_gpadc_usb_charger_c_open(struct inode *inode,
-		struct file *file)
+static ssize_t ab8500_gpadc_trig_edge_write(struct file *file,
+	const char __user *user_buf,
+	size_t count, loff_t *ppos)
 {
-	return single_open(file, ab8500_gpadc_usb_charger_c_print,
-	    inode->i_private);
+	struct device *dev = ((struct seq_file *)(file->private_data))->private;
+	unsigned long user_trig_edge;
+	int err;
+
+	err = kstrtoul_from_user(user_buf, count, 0, &user_trig_edge);
+	if (err)
+		return err;
+
+	if ((user_trig_edge == RISING_EDGE)
+			|| (user_trig_edge == FALLING_EDGE)) {
+		trig_edge = (u8) user_trig_edge;
+	} else {
+		dev_err(dev, "Wrong input:\n"
+			"Enter 0. Rising edge\n"
+			"Enter 1. Falling edge\n");
+		return -EINVAL;
+	}
+
+	return count;
 }
 
-static const struct file_operations ab8500_gpadc_usb_charger_c_fops = {
-	.open = ab8500_gpadc_usb_charger_c_open,
+static const struct file_operations ab8500_gpadc_trig_edge_fops = {
+	.open = ab8500_gpadc_trig_edge_open,
 	.read = seq_read,
+	.write = ab8500_gpadc_trig_edge_write,
 	.llseek = seq_lseek,
 	.release = single_release,
 	.owner = THIS_MODULE,
 };
 
-static int ab8500_gpadc_bk_bat_v_print(struct seq_file *s, void *p)
+static int ab8500_gpadc_trig_timer_print(struct seq_file *s, void *p)
 {
-	int bk_bat_v_raw;
-	int bk_bat_v_convert;
-	struct ab8500_gpadc *gpadc;
-
-	gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
-	bk_bat_v_raw = ab8500_gpadc_read_raw(gpadc, BK_BAT_V);
-	bk_bat_v_convert = ab8500_gpadc_ad_to_voltage(gpadc,
-			BK_BAT_V, bk_bat_v_raw);
+	return seq_printf(s, "%d\n", trig_timer);
+}
 
-	return seq_printf(s, "%d,0x%X\n",
-			bk_bat_v_convert, bk_bat_v_raw);
+static int ab8500_gpadc_trig_timer_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, ab8500_gpadc_trig_timer_print,
+		inode->i_private);
 }
 
-static int ab8500_gpadc_bk_bat_v_open(struct inode *inode, struct file *file)
+static ssize_t ab8500_gpadc_trig_timer_write(struct file *file,
+	const char __user *user_buf,
+	size_t count, loff_t *ppos)
 {
-	return single_open(file, ab8500_gpadc_bk_bat_v_print, inode->i_private);
+	struct device *dev = ((struct seq_file *)(file->private_data))->private;
+	unsigned long user_trig_timer;
+	int err;
+
+	err = kstrtoul_from_user(user_buf, count, 0, &user_trig_timer);
+	if (err)
+		return err;
+
+	if ((user_trig_timer >= 0) && (user_trig_timer <= 255)) {
+		trig_timer = (u8) user_trig_timer;
+	} else {
+		dev_err(dev, "debugfs error input: "
+			"should be beetween 0 to 255\n");
+		return -EINVAL;
+	}
+
+	return count;
 }
 
-static const struct file_operations ab8500_gpadc_bk_bat_v_fops = {
-	.open = ab8500_gpadc_bk_bat_v_open,
+static const struct file_operations ab8500_gpadc_trig_timer_fops = {
+	.open = ab8500_gpadc_trig_timer_open,
 	.read = seq_read,
+	.write = ab8500_gpadc_trig_timer_write,
 	.llseek = seq_lseek,
 	.release = single_release,
 	.owner = THIS_MODULE,
 };
 
-static int ab8500_gpadc_die_temp_print(struct seq_file *s, void *p)
+static int ab8500_gpadc_conv_type_print(struct seq_file *s, void *p)
 {
-	int die_temp_raw;
-	int die_temp_convert;
-	struct ab8500_gpadc *gpadc;
-
-	gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
-	die_temp_raw = ab8500_gpadc_read_raw(gpadc, DIE_TEMP);
-	die_temp_convert = ab8500_gpadc_ad_to_voltage(gpadc, DIE_TEMP,
-			die_temp_raw);
+	return seq_printf(s, "%d\n", conv_type);
+}
 
-	return seq_printf(s, "%d,0x%X\n",
-			die_temp_convert, die_temp_raw);
+static int ab8500_gpadc_conv_type_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, ab8500_gpadc_conv_type_print,
+		inode->i_private);
 }
 
-static int ab8500_gpadc_die_temp_open(struct inode *inode, struct file *file)
+static ssize_t ab8500_gpadc_conv_type_write(struct file *file,
+	const char __user *user_buf,
+	size_t count, loff_t *ppos)
 {
-	return single_open(file, ab8500_gpadc_die_temp_print, inode->i_private);
+	struct device *dev = ((struct seq_file *)(file->private_data))->private;
+	unsigned long user_conv_type;
+	int err;
+
+	err = kstrtoul_from_user(user_buf, count, 0, &user_conv_type);
+	if (err)
+		return err;
+
+	if ((user_conv_type == ADC_SW)
+			|| (user_conv_type == ADC_HW)) {
+		conv_type = (u8) user_conv_type;
+	} else {
+		dev_err(dev, "Wrong input:\n"
+			"Enter 0. ADC SW conversion\n"
+			"Enter 1. ADC HW conversion\n");
+		return -EINVAL;
+	}
+
+	return count;
 }
 
-static const struct file_operations ab8500_gpadc_die_temp_fops = {
-	.open = ab8500_gpadc_die_temp_open,
+static const struct file_operations ab8500_gpadc_conv_type_fops = {
+	.open = ab8500_gpadc_conv_type_open,
 	.read = seq_read,
+	.write = ab8500_gpadc_conv_type_write,
 	.llseek = seq_lseek,
 	.release = single_release,
 	.owner = THIS_MODULE,
@@ -1352,7 +2745,7 @@ static int ab8500_subscribe_unsubscribe_open(struct inode *inode,
 					     struct file *file)
 {
 	return single_open(file, ab8500_subscribe_unsubscribe_print,
-			   inode->i_private);
+		inode->i_private);
 }
 
 /*
@@ -1382,21 +2775,14 @@ static ssize_t ab8500_subscribe_write(struct file *file,
 				      size_t count, loff_t *ppos)
 {
 	struct device *dev = ((struct seq_file *)(file->private_data))->private;
-	char buf[32];
-	int buf_size;
 	unsigned long user_val;
 	int err;
 	unsigned int irq_index;
 
-	/* Get userspace string and assure termination */
-	buf_size = min(count, (sizeof(buf)-1));
-	if (copy_from_user(buf, user_buf, buf_size))
-		return -EFAULT;
-	buf[buf_size] = 0;
-
-	err = strict_strtoul(buf, 0, &user_val);
+	err = kstrtoul_from_user(user_buf, count, 0, &user_val);
 	if (err)
-		return -EINVAL;
+		return err;
+
 	if (user_val < irq_first) {
 		dev_err(dev, "debugfs error input < %d\n", irq_first);
 		return -EINVAL;
@@ -1416,7 +2802,7 @@ static ssize_t ab8500_subscribe_write(struct file *file,
 	 */
 	dev_attr[irq_index] = kmalloc(sizeof(struct device_attribute),
 		GFP_KERNEL);
-	event_name[irq_index] = kmalloc(buf_size, GFP_KERNEL);
+	event_name[irq_index] = kmalloc(count, GFP_KERNEL);
 	sprintf(event_name[irq_index], "%lu", user_val);
 	dev_attr[irq_index]->show = show_irq;
 	dev_attr[irq_index]->store = NULL;
@@ -1438,7 +2824,7 @@ static ssize_t ab8500_subscribe_write(struct file *file,
 		return err;
 	}
 
-	return buf_size;
+	return count;
 }
 
 static ssize_t ab8500_unsubscribe_write(struct file *file,
@@ -1446,21 +2832,14 @@ static ssize_t ab8500_unsubscribe_write(struct file *file,
 					size_t count, loff_t *ppos)
 {
 	struct device *dev = ((struct seq_file *)(file->private_data))->private;
-	char buf[32];
-	int buf_size;
 	unsigned long user_val;
 	int err;
 	unsigned int irq_index;
 
-	/* Get userspace string and assure termination */
-	buf_size = min(count, (sizeof(buf)-1));
-	if (copy_from_user(buf, user_buf, buf_size))
-		return -EFAULT;
-	buf[buf_size] = 0;
-
-	err = strict_strtoul(buf, 0, &user_val);
+	err = kstrtoul_from_user(user_buf, count, 0, &user_val);
 	if (err)
-		return -EINVAL;
+		return err;
+
 	if (user_val < irq_first) {
 		dev_err(dev, "debugfs error input < %d\n", irq_first);
 		return -EINVAL;
@@ -1485,7 +2864,7 @@ static ssize_t ab8500_unsubscribe_write(struct file *file,
 	kfree(event_name[irq_index]);
 	kfree(dev_attr[irq_index]);
 
-	return buf_size;
+	return count;
 }
 
 /*
@@ -1583,7 +2962,7 @@ static int ab8500_debug_probe(struct platform_device *plf)
 	irq_first = platform_get_irq_byname(plf, "IRQ_FIRST");
 	if (irq_first < 0) {
 		dev_err(&plf->dev, "First irq not found, err %d\n",
-				irq_first);
+			irq_first);
 		ret = irq_first;
 		goto out_freeevent_name;
 	}
@@ -1591,9 +2970,9 @@ static int ab8500_debug_probe(struct platform_device *plf)
 	irq_last = platform_get_irq_byname(plf, "IRQ_LAST");
 	if (irq_last < 0) {
 		dev_err(&plf->dev, "Last irq not found, err %d\n",
-				irq_last);
+			irq_last);
 		ret = irq_last;
-                goto out_freeevent_name;
+		goto out_freeevent_name;
 	}
 
 	ab8500_dir = debugfs_create_dir(AB8500_NAME_STRING, NULL);
@@ -1601,124 +2980,198 @@ static int ab8500_debug_probe(struct platform_device *plf)
 		goto err;
 
 	ab8500_gpadc_dir = debugfs_create_dir(AB8500_ADC_NAME_STRING,
-	    ab8500_dir);
+		ab8500_dir);
 	if (!ab8500_gpadc_dir)
 		goto err;
 
 	file = debugfs_create_file("all-bank-registers", S_IRUGO,
-	    ab8500_dir, &plf->dev, &ab8500_registers_fops);
+		ab8500_dir, &plf->dev, &ab8500_registers_fops);
 	if (!file)
 		goto err;
 
 	file = debugfs_create_file("all-banks", S_IRUGO,
-	    ab8500_dir, &plf->dev, &ab8500_all_banks_fops);
+		ab8500_dir, &plf->dev, &ab8500_all_banks_fops);
 	if (!file)
 		goto err;
 
-	file = debugfs_create_file("register-bank", (S_IRUGO | S_IWUSR),
-	    ab8500_dir, &plf->dev, &ab8500_bank_fops);
+	file = debugfs_create_file("register-bank", (S_IRUGO | S_IWUSR | S_IWGRP),
+		ab8500_dir, &plf->dev, &ab8500_bank_fops);
 	if (!file)
 		goto err;
 
-	file = debugfs_create_file("register-address", (S_IRUGO | S_IWUSR),
-	    ab8500_dir, &plf->dev, &ab8500_address_fops);
+	file = debugfs_create_file("register-address", (S_IRUGO | S_IWUSR | S_IWGRP),
+		ab8500_dir, &plf->dev, &ab8500_address_fops);
 	if (!file)
 		goto err;
 
-	file = debugfs_create_file("register-value", (S_IRUGO | S_IWUSR),
-	    ab8500_dir, &plf->dev, &ab8500_val_fops);
+	file = debugfs_create_file("register-value", (S_IRUGO | S_IWUSR | S_IWGRP),
+		ab8500_dir, &plf->dev, &ab8500_val_fops);
 	if (!file)
 		goto err;
 
-	file = debugfs_create_file("irq-subscribe", (S_IRUGO | S_IWUSR),
-	    ab8500_dir, &plf->dev, &ab8500_subscribe_fops);
+	file = debugfs_create_file("irq-subscribe", (S_IRUGO | S_IWUSR | S_IWGRP),
+		ab8500_dir, &plf->dev, &ab8500_subscribe_fops);
 	if (!file)
 		goto err;
 
-	if (is_ab8500(ab8500))
+	if (is_ab8500(ab8500)) {
+		debug_ranges = ab8500_debug_ranges;
 		num_interrupt_lines = AB8500_NR_IRQS;
-	else if (is_ab8505(ab8500))
+	} else if (is_ab8505(ab8500)) {
+		debug_ranges = ab8505_debug_ranges;
 		num_interrupt_lines = AB8505_NR_IRQS;
-	else if (is_ab9540(ab8500))
+	} else if (is_ab9540(ab8500)) {
+		debug_ranges = ab8505_debug_ranges;
 		num_interrupt_lines = AB9540_NR_IRQS;
+	} else if (is_ab8540(ab8500)) {
+		debug_ranges = ab8540_debug_ranges;
+		num_interrupt_lines = AB8540_NR_IRQS;
+	}
 
 	file = debugfs_create_file("interrupts", (S_IRUGO),
-	    ab8500_dir, &plf->dev, &ab8500_interrupts_fops);
+		ab8500_dir, &plf->dev, &ab8500_interrupts_fops);
+	if (!file)
+		goto err;
+
+	file = debugfs_create_file("irq-unsubscribe", (S_IRUGO | S_IWUSR | S_IWGRP),
+		ab8500_dir, &plf->dev, &ab8500_unsubscribe_fops);
 	if (!file)
 		goto err;
 
-	file = debugfs_create_file("irq-unsubscribe", (S_IRUGO | S_IWUSR),
-	    ab8500_dir, &plf->dev, &ab8500_unsubscribe_fops);
+	file = debugfs_create_file("hwreg", (S_IRUGO | S_IWUSR | S_IWGRP),
+		ab8500_dir, &plf->dev, &ab8500_hwreg_fops);
 	if (!file)
 		goto err;
 
-	file = debugfs_create_file("hwreg", (S_IRUGO | S_IWUSR),
-	    ab8500_dir, &plf->dev, &ab8500_hwreg_fops);
+	file = debugfs_create_file("all-modem-registers", (S_IRUGO | S_IWUSR | S_IWGRP),
+		ab8500_dir, &plf->dev, &ab8500_modem_fops);
 	if (!file)
 		goto err;
 
-	file = debugfs_create_file("bat_ctrl", (S_IRUGO | S_IWUSR),
-	    ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_bat_ctrl_fops);
+	file = debugfs_create_file("bat_ctrl", (S_IRUGO | S_IWUSR | S_IWGRP),
+		ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_bat_ctrl_fops);
 	if (!file)
 		goto err;
 
-	file = debugfs_create_file("btemp_ball", (S_IRUGO | S_IWUSR),
-	    ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_btemp_ball_fops);
+	file = debugfs_create_file("btemp_ball", (S_IRUGO | S_IWUSR | S_IWGRP),
+		ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_btemp_ball_fops);
 	if (!file)
 		goto err;
 
-	file = debugfs_create_file("main_charger_v", (S_IRUGO | S_IWUSR),
-	    ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_main_charger_v_fops);
+	file = debugfs_create_file("main_charger_v", (S_IRUGO | S_IWUSR | S_IWGRP),
+		ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_main_charger_v_fops);
 	if (!file)
 		goto err;
 
-	file = debugfs_create_file("acc_detect1", (S_IRUGO | S_IWUSR),
-	    ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_acc_detect1_fops);
+	file = debugfs_create_file("acc_detect1", (S_IRUGO | S_IWUSR | S_IWGRP),
+		ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_acc_detect1_fops);
 	if (!file)
 		goto err;
 
-	file = debugfs_create_file("acc_detect2", (S_IRUGO | S_IWUSR),
-	    ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_acc_detect2_fops);
+	file = debugfs_create_file("acc_detect2", (S_IRUGO | S_IWUSR | S_IWGRP),
+		ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_acc_detect2_fops);
 	if (!file)
 		goto err;
 
-	file = debugfs_create_file("adc_aux1", (S_IRUGO | S_IWUSR),
-	    ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_aux1_fops);
+	file = debugfs_create_file("adc_aux1", (S_IRUGO | S_IWUSR | S_IWGRP),
+		ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_aux1_fops);
 	if (!file)
 		goto err;
 
-	file = debugfs_create_file("adc_aux2", (S_IRUGO | S_IWUSR),
-	    ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_aux2_fops);
+	file = debugfs_create_file("adc_aux2", (S_IRUGO | S_IWUSR | S_IWGRP),
+		ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_aux2_fops);
 	if (!file)
 		goto err;
 
-	file = debugfs_create_file("main_bat_v", (S_IRUGO | S_IWUSR),
-	    ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_main_bat_v_fops);
+	file = debugfs_create_file("main_bat_v", (S_IRUGO | S_IWUSR | S_IWGRP),
+		ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_main_bat_v_fops);
 	if (!file)
 		goto err;
 
-	file = debugfs_create_file("vbus_v", (S_IRUGO | S_IWUSR),
-	    ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_vbus_v_fops);
+	file = debugfs_create_file("vbus_v", (S_IRUGO | S_IWUSR | S_IWGRP),
+		ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_vbus_v_fops);
 	if (!file)
 		goto err;
 
-	file = debugfs_create_file("main_charger_c", (S_IRUGO | S_IWUSR),
-	    ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_main_charger_c_fops);
+	file = debugfs_create_file("main_charger_c", (S_IRUGO | S_IWUSR | S_IWGRP),
+		ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_main_charger_c_fops);
+	if (!file)
+		goto err;
+
+	file = debugfs_create_file("usb_charger_c", (S_IRUGO | S_IWUSR | S_IWGRP),
+		ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_usb_charger_c_fops);
+	if (!file)
+		goto err;
+
+	file = debugfs_create_file("bk_bat_v", (S_IRUGO | S_IWUSR | S_IWGRP),
+		ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_bk_bat_v_fops);
+	if (!file)
+		goto err;
+
+	file = debugfs_create_file("die_temp", (S_IRUGO | S_IWUSR | S_IWGRP),
+		ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_die_temp_fops);
+	if (!file)
+		goto err;
+
+	file = debugfs_create_file("usb_id", (S_IRUGO | S_IWUSR | S_IWGRP),
+		ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_usb_id_fops);
+	if (!file)
+		goto err;
+
+	if (is_ab8540(ab8500)) {
+		file = debugfs_create_file("xtal_temp", (S_IRUGO | S_IWUSR | S_IWGRP),
+			ab8500_gpadc_dir, &plf->dev, &ab8540_gpadc_xtal_temp_fops);
+		if (!file)
+			goto err;
+		file = debugfs_create_file("vbattruemeas", (S_IRUGO | S_IWUSR | S_IWGRP),
+			ab8500_gpadc_dir, &plf->dev,
+			&ab8540_gpadc_vbat_true_meas_fops);
+		if (!file)
+			goto err;
+		file = debugfs_create_file("batctrl_and_ibat",
+			(S_IRUGO | S_IWUGO), ab8500_gpadc_dir,
+			&plf->dev, &ab8540_gpadc_bat_ctrl_and_ibat_fops);
+		if (!file)
+			goto err;
+		file = debugfs_create_file("vbatmeas_and_ibat",
+			(S_IRUGO | S_IWUGO), ab8500_gpadc_dir,
+			&plf->dev,
+			&ab8540_gpadc_vbat_meas_and_ibat_fops);
+		if (!file)
+			goto err;
+		file = debugfs_create_file("vbattruemeas_and_ibat",
+			(S_IRUGO | S_IWUGO), ab8500_gpadc_dir,
+			&plf->dev,
+			&ab8540_gpadc_vbat_true_meas_and_ibat_fops);
+		if (!file)
+			goto err;
+		file = debugfs_create_file("battemp_and_ibat",
+			(S_IRUGO | S_IWUGO), ab8500_gpadc_dir,
+			&plf->dev, &ab8540_gpadc_bat_temp_and_ibat_fops);
+		if (!file)
+			goto err;
+		file = debugfs_create_file("otp_calib", (S_IRUGO | S_IWUSR | S_IWGRP),
+			ab8500_gpadc_dir, &plf->dev, &ab8540_gpadc_otp_calib_fops);
+		if (!file)
+			goto err;
+	}
+	file = debugfs_create_file("avg_sample", (S_IRUGO | S_IWUSR | S_IWGRP),
+		ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_avg_sample_fops);
 	if (!file)
 		goto err;
 
-	file = debugfs_create_file("usb_charger_c", (S_IRUGO | S_IWUSR),
-	    ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_usb_charger_c_fops);
+	file = debugfs_create_file("trig_edge", (S_IRUGO | S_IWUSR | S_IWGRP),
+		ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_trig_edge_fops);
 	if (!file)
 		goto err;
 
-	file = debugfs_create_file("bk_bat_v", (S_IRUGO | S_IWUSR),
-	    ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_bk_bat_v_fops);
+	file = debugfs_create_file("trig_timer", (S_IRUGO | S_IWUSR | S_IWGRP),
+		ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_trig_timer_fops);
 	if (!file)
 		goto err;
 
-	file = debugfs_create_file("die_temp", (S_IRUGO | S_IWUSR),
-	    ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_die_temp_fops);
+	file = debugfs_create_file("conv_type", (S_IRUGO | S_IWUSR | S_IWGRP),
+		ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_conv_type_fops);
 	if (!file)
 		goto err;
 
diff --git a/drivers/mfd/ab8500-gpadc.c b/drivers/mfd/ab8500-gpadc.c
index 5f341a5..65f7228 100644
--- a/drivers/mfd/ab8500-gpadc.c
+++ b/drivers/mfd/ab8500-gpadc.c
@@ -37,6 +37,13 @@
 #define AB8500_GPADC_AUTODATAL_REG	0x07
 #define AB8500_GPADC_AUTODATAH_REG	0x08
 #define AB8500_GPADC_MUX_CTRL_REG	0x09
+#define AB8540_GPADC_MANDATA2L_REG	0x09
+#define AB8540_GPADC_MANDATA2H_REG	0x0A
+#define AB8540_GPADC_APEAAX_REG		0x10
+#define AB8540_GPADC_APEAAT_REG		0x11
+#define AB8540_GPADC_APEAAM_REG		0x12
+#define AB8540_GPADC_APEAAH_REG		0x13
+#define AB8540_GPADC_APEAAL_REG		0x14
 
 /*
  * OTP register offsets
@@ -49,19 +56,29 @@
 #define AB8500_GPADC_CAL_5		0x13
 #define AB8500_GPADC_CAL_6		0x14
 #define AB8500_GPADC_CAL_7		0x15
+/* New calibration for 8540 */
+#define AB8540_GPADC_OTP4_REG_7	0x38
+#define AB8540_GPADC_OTP4_REG_6	0x39
+#define AB8540_GPADC_OTP4_REG_5	0x3A
 
 /* gpadc constants */
 #define EN_VINTCORE12			0x04
 #define EN_VTVOUT			0x02
 #define EN_GPADC			0x01
 #define DIS_GPADC			0x00
-#define SW_AVG_16			0x60
+#define AVG_1				0x00
+#define AVG_4				0x20
+#define AVG_8				0x40
+#define AVG_16				0x60
 #define ADC_SW_CONV			0x04
 #define EN_ICHAR			0x80
 #define BTEMP_PULL_UP			0x08
 #define EN_BUF				0x40
 #define DIS_ZERO			0x00
 #define GPADC_BUSY			0x01
+#define EN_FALLING			0x10
+#define EN_TRIG_EDGE			0x02
+#define EN_VBIAS_XTAL_TEMP		0x02
 
 /* GPADC constants from AB8500 spec, UM0836 */
 #define ADC_RESOLUTION			1024
@@ -80,8 +97,21 @@
 #define ADC_CH_BKBAT_MIN		0
 #define ADC_CH_BKBAT_MAX		3200
 
+/* GPADC constants from AB8540 spec */
+#define ADC_CH_IBAT_MIN			(-6000) /* mA range measured by ADC for ibat*/
+#define ADC_CH_IBAT_MAX			6000
+#define ADC_CH_IBAT_MIN_V		(-60)	/* mV range measured by ADC for ibat*/
+#define ADC_CH_IBAT_MAX_V		60
+#define IBAT_VDROP_L			(-56)  /* mV */
+#define IBAT_VDROP_H			56
+
 /* This is used to not lose precision when dividing to get gain and offset */
-#define CALIB_SCALE			1000
+#define CALIB_SCALE		1000
+/*
+ * Number of bits shift used to not lose precision
+ * when dividing to get ibat gain.
+ */
+#define CALIB_SHIFT_IBAT	20
 
 /* Time in ms before disabling regulator */
 #define GPADC_AUDOSUSPEND_DELAY		1
@@ -92,6 +122,7 @@ enum cal_channels {
 	ADC_INPUT_VMAIN = 0,
 	ADC_INPUT_BTEMP,
 	ADC_INPUT_VBAT,
+	ADC_INPUT_IBAT,
 	NBR_CAL_INPUTS,
 };
 
@@ -102,8 +133,10 @@ enum cal_channels {
  * @offset:		Offset of the ADC channel
  */
 struct adc_cal_data {
-	u64 gain;
-	u64 offset;
+	s64 gain;
+	s64 offset;
+	u16 otp_calib_hi;
+	u16 otp_calib_lo;
 };
 
 /**
@@ -116,7 +149,10 @@ struct adc_cal_data {
  *				the completion of gpadc conversion
  * @ab8500_gpadc_lock:		structure of type mutex
  * @regu:			pointer to the struct regulator
- * @irq:			interrupt number that is used by gpadc
+ * @irq_sw:			interrupt number that is used by gpadc for Sw
+ *				conversion
+ * @irq_hw:			interrupt number that is used by gpadc for Hw
+ *				conversion
  * @cal_data			array of ADC calibration data structs
  */
 struct ab8500_gpadc {
@@ -126,7 +162,8 @@ struct ab8500_gpadc {
 	struct completion ab8500_gpadc_complete;
 	struct mutex ab8500_gpadc_lock;
 	struct regulator *regu;
-	int irq;
+	int irq_sw;
+	int irq_hw;
 	struct adc_cal_data cal_data[NBR_CAL_INPUTS];
 };
 
@@ -171,6 +208,7 @@ int ab8500_gpadc_ad_to_voltage(struct ab8500_gpadc *gpadc, u8 channel,
 			gpadc->cal_data[ADC_INPUT_VMAIN].offset) / CALIB_SCALE;
 		break;
 
+	case XTAL_TEMP:
 	case BAT_CTRL:
 	case BTEMP_BALL:
 	case ACC_DETECT1:
@@ -189,6 +227,7 @@ int ab8500_gpadc_ad_to_voltage(struct ab8500_gpadc *gpadc, u8 channel,
 		break;
 
 	case MAIN_BAT_V:
+	case VBAT_TRUE_MEAS:
 		/* For some reason we don't have calibrated data */
 		if (!gpadc->cal_data[ADC_INPUT_VBAT].gain) {
 			res = ADC_CH_VBAT_MIN + (ADC_CH_VBAT_MAX -
@@ -232,6 +271,20 @@ int ab8500_gpadc_ad_to_voltage(struct ab8500_gpadc *gpadc, u8 channel,
 			ADC_RESOLUTION;
 		break;
 
+	case IBAT_VIRTUAL_CHANNEL:
+		/* For some reason we don't have calibrated data */
+		if (!gpadc->cal_data[ADC_INPUT_IBAT].gain) {
+			res = ADC_CH_IBAT_MIN + (ADC_CH_IBAT_MAX -
+				ADC_CH_IBAT_MIN) * ad_value /
+				ADC_RESOLUTION;
+			break;
+		}
+		/* Here we can use the calibrated data */
+		res = (int) (ad_value * gpadc->cal_data[ADC_INPUT_IBAT].gain +
+				gpadc->cal_data[ADC_INPUT_IBAT].offset)
+				>> CALIB_SHIFT_IBAT;
+		break;
+
 	default:
 		dev_err(gpadc->dev,
 			"unknown channel, not possible to convert\n");
@@ -244,25 +297,35 @@ int ab8500_gpadc_ad_to_voltage(struct ab8500_gpadc *gpadc, u8 channel,
 EXPORT_SYMBOL(ab8500_gpadc_ad_to_voltage);
 
 /**
- * ab8500_gpadc_convert() - gpadc conversion
+ * ab8500_gpadc_sw_hw_convert() - gpadc conversion
  * @channel:	analog channel to be converted to digital data
+ * @avg_sample:  number of ADC sample to average
+ * @trig_egde:  selected ADC trig edge
+ * @trig_timer: selected ADC trigger delay timer
+ * @conv_type: selected conversion type (HW or SW conversion)
  *
  * This function converts the selected analog i/p to digital
  * data.
  */
-int ab8500_gpadc_convert(struct ab8500_gpadc *gpadc, u8 channel)
+int ab8500_gpadc_sw_hw_convert(struct ab8500_gpadc *gpadc, u8 channel,
+		u8 avg_sample, u8 trig_edge, u8 trig_timer, u8 conv_type)
 {
 	int ad_value;
 	int voltage;
 
-	ad_value = ab8500_gpadc_read_raw(gpadc, channel);
-	if (ad_value < 0) {
-		dev_err(gpadc->dev, "GPADC raw value failed ch: %d\n", channel);
+	ad_value = ab8500_gpadc_read_raw(gpadc, channel, avg_sample,
+			trig_edge, trig_timer, conv_type);
+/* On failure retry a second time */
+	if (ad_value < 0)
+		ad_value = ab8500_gpadc_read_raw(gpadc, channel, avg_sample,
+			trig_edge, trig_timer, conv_type);
+if (ad_value < 0) {
+		dev_err(gpadc->dev, "GPADC raw value failed ch: %d\n",
+				channel);
 		return ad_value;
 	}
 
 	voltage = ab8500_gpadc_ad_to_voltage(gpadc, channel, ad_value);
-
 	if (voltage < 0)
 		dev_err(gpadc->dev, "GPADC to voltage conversion failed ch:"
 			" %d AD: 0x%x\n", channel, ad_value);
@@ -274,21 +337,46 @@ EXPORT_SYMBOL(ab8500_gpadc_convert);
 /**
  * ab8500_gpadc_read_raw() - gpadc read
  * @channel:	analog channel to be read
+ * @avg_sample:  number of ADC sample to average
+ * @trig_edge:  selected trig edge
+ * @trig_timer: selected ADC trigger delay timer
+ * @conv_type: selected conversion type (HW or SW conversion)
  *
- * This function obtains the raw ADC value, this then needs
- * to be converted by calling ab8500_gpadc_ad_to_voltage()
+ * This function obtains the raw ADC value for an hardware conversion,
+ * this then needs to be converted by calling ab8500_gpadc_ad_to_voltage()
  */
-int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel)
+int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel,
+		u8 avg_sample, u8 trig_edge, u8 trig_timer, u8 conv_type)
+{
+	int raw_data;
+	raw_data = ab8500_gpadc_double_read_raw(gpadc, channel,
+			avg_sample, trig_edge, trig_timer, conv_type, NULL);
+	return raw_data;
+}
+
+int ab8500_gpadc_double_read_raw(struct ab8500_gpadc *gpadc, u8 channel,
+		u8 avg_sample, u8 trig_edge, u8 trig_timer, u8 conv_type,
+		int *ibat)
 {
 	int ret;
 	int looplimit = 0;
-	u8 val, low_data, high_data;
+	unsigned long completion_timeout;
+	u8 val, low_data, high_data, low_data2, high_data2;
+	u8 val_reg1 = 0;
+	unsigned int delay_min = 0;
+	unsigned int delay_max = 0;
+	u8 data_low_addr, data_high_addr;
 
 	if (!gpadc)
 		return -ENODEV;
 
-	mutex_lock(&gpadc->ab8500_gpadc_lock);
+	/* check if convertion is supported */
+	if ((gpadc->irq_sw < 0) && (conv_type == ADC_SW))
+		return -ENOTSUPP;
+	if ((gpadc->irq_hw < 0) && (conv_type == ADC_HW))
+		return -ENOTSUPP;
 
+	mutex_lock(&gpadc->ab8500_gpadc_lock);
 	/* Enable VTVout LDO this is required for GPADC */
 	pm_runtime_get_sync(gpadc->dev);
 
@@ -309,16 +397,34 @@ int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel)
 	}
 
 	/* Enable GPADC */
-	ret = abx500_mask_and_set_register_interruptible(gpadc->dev,
-		AB8500_GPADC, AB8500_GPADC_CTRL1_REG, EN_GPADC, EN_GPADC);
-	if (ret < 0) {
-		dev_err(gpadc->dev, "gpadc_conversion: enable gpadc failed\n");
-		goto out;
+	val_reg1 |= EN_GPADC;
+
+	/* Select the channel source and set average samples */
+	switch (avg_sample) {
+	case SAMPLE_1:
+		val = channel | AVG_1;
+		break;
+	case SAMPLE_4:
+		val = channel | AVG_4;
+		break;
+	case SAMPLE_8:
+		val = channel | AVG_8;
+		break;
+	default:
+		val = channel | AVG_16;
+		break;
 	}
 
-	/* Select the channel source and set average samples to 16 */
-	ret = abx500_set_register_interruptible(gpadc->dev, AB8500_GPADC,
-		AB8500_GPADC_CTRL2_REG, (channel | SW_AVG_16));
+	if (conv_type == ADC_HW) {
+		ret = abx500_set_register_interruptible(gpadc->dev,
+				AB8500_GPADC, AB8500_GPADC_CTRL3_REG, val);
+		val_reg1 |= EN_TRIG_EDGE;
+		if (trig_edge)
+			val_reg1 |= EN_FALLING;
+	}
+	else
+		ret = abx500_set_register_interruptible(gpadc->dev,
+				AB8500_GPADC, AB8500_GPADC_CTRL2_REG, val);
 	if (ret < 0) {
 		dev_err(gpadc->dev,
 			"gpadc_conversion: set avg samples failed\n");
@@ -333,71 +439,129 @@ int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel)
 	switch (channel) {
 	case MAIN_CHARGER_C:
 	case USB_CHARGER_C:
-		ret = abx500_mask_and_set_register_interruptible(gpadc->dev,
-			AB8500_GPADC, AB8500_GPADC_CTRL1_REG,
-			EN_BUF | EN_ICHAR,
-			EN_BUF | EN_ICHAR);
+		val_reg1 |= EN_BUF | EN_ICHAR;
 		break;
 	case BTEMP_BALL:
 		if (!is_ab8500_2p0_or_earlier(gpadc->parent)) {
-			/* Turn on btemp pull-up on ABB 3.0 */
-			ret = abx500_mask_and_set_register_interruptible(
-				gpadc->dev,
-				AB8500_GPADC, AB8500_GPADC_CTRL1_REG,
-				EN_BUF | BTEMP_PULL_UP,
-				EN_BUF | BTEMP_PULL_UP);
-
-		 /*
-		  * Delay might be needed for ABB8500 cut 3.0, if not, remove
-		  * when hardware will be available
-		  */
-			usleep_range(1000, 1000);
+			val_reg1 |= EN_BUF | BTEMP_PULL_UP;
+			/*
+			* Delay might be needed for ABB8500 cut 3.0, if not,
+			* remove when hardware will be availible
+			*/
+			delay_min = 1000; /* Delay in micro seconds */
+			delay_max = 10000; /* large range to optimise sleep mode */
 			break;
 		}
 		/* Intentional fallthrough */
 	default:
-		ret = abx500_mask_and_set_register_interruptible(gpadc->dev,
-			AB8500_GPADC, AB8500_GPADC_CTRL1_REG, EN_BUF, EN_BUF);
+		val_reg1 |= EN_BUF;
 		break;
 	}
+
+	/* Write configuration to register */
+	ret = abx500_set_register_interruptible(gpadc->dev,
+		AB8500_GPADC, AB8500_GPADC_CTRL1_REG, val_reg1);
 	if (ret < 0) {
 		dev_err(gpadc->dev,
-			"gpadc_conversion: select falling edge failed\n");
+			"gpadc_conversion: set Control register failed\n");
 		goto out;
 	}
 
-	ret = abx500_mask_and_set_register_interruptible(gpadc->dev,
-		AB8500_GPADC, AB8500_GPADC_CTRL1_REG, ADC_SW_CONV, ADC_SW_CONV);
-	if (ret < 0) {
-		dev_err(gpadc->dev,
-			"gpadc_conversion: start s/w conversion failed\n");
-		goto out;
+	if (delay_min != 0)
+		usleep_range(delay_min, delay_max);
+
+	if (conv_type == ADC_HW) {
+		/* Set trigger delay timer */
+		ret = abx500_set_register_interruptible(gpadc->dev,
+			AB8500_GPADC, AB8500_GPADC_AUTO_TIMER_REG, trig_timer);
+		if (ret < 0) {
+			dev_err(gpadc->dev,
+				"gpadc_conversion: trig timer failed\n");
+			goto out;
+		}
+		completion_timeout = 2 * HZ;
+		data_low_addr = AB8500_GPADC_AUTODATAL_REG;
+		data_high_addr = AB8500_GPADC_AUTODATAH_REG;
+	} else {
+		/* Start SW conversion */
+		ret = abx500_mask_and_set_register_interruptible(gpadc->dev,
+			AB8500_GPADC, AB8500_GPADC_CTRL1_REG,
+			ADC_SW_CONV, ADC_SW_CONV);
+		if (ret < 0) {
+			dev_err(gpadc->dev,
+				"gpadc_conversion: start s/w conv failed\n");
+			goto out;
+		}
+		completion_timeout = msecs_to_jiffies(CONVERSION_TIME);
+		data_low_addr = AB8500_GPADC_MANDATAL_REG;
+		data_high_addr = AB8500_GPADC_MANDATAH_REG;
 	}
+
 	/* wait for completion of conversion */
 	if (!wait_for_completion_timeout(&gpadc->ab8500_gpadc_complete,
-					 msecs_to_jiffies(CONVERSION_TIME))) {
+			completion_timeout)) {
 		dev_err(gpadc->dev,
-			"timeout: didn't receive GPADC conversion interrupt\n");
+			"timeout didn't receive GPADC conv interrupt\n");
 		ret = -EINVAL;
 		goto out;
 	}
 
 	/* Read the converted RAW data */
-	ret = abx500_get_register_interruptible(gpadc->dev, AB8500_GPADC,
-		AB8500_GPADC_MANDATAL_REG, &low_data);
+	ret = abx500_get_register_interruptible(gpadc->dev,
+			AB8500_GPADC, data_low_addr, &low_data);
 	if (ret < 0) {
 		dev_err(gpadc->dev, "gpadc_conversion: read low data failed\n");
 		goto out;
 	}
 
-	ret = abx500_get_register_interruptible(gpadc->dev, AB8500_GPADC,
-		AB8500_GPADC_MANDATAH_REG, &high_data);
+	ret = abx500_get_register_interruptible(gpadc->dev,
+		AB8500_GPADC, data_high_addr, &high_data);
 	if (ret < 0) {
-		dev_err(gpadc->dev,
-			"gpadc_conversion: read high data failed\n");
+		dev_err(gpadc->dev, "gpadc_conversion: read high data failed\n");
 		goto out;
 	}
 
+	/* Check if double convertion is required */
+	if ((channel == BAT_CTRL_AND_IBAT) ||
+			(channel == VBAT_MEAS_AND_IBAT) ||
+			(channel == VBAT_TRUE_MEAS_AND_IBAT) ||
+			(channel == BAT_TEMP_AND_IBAT)) {
+
+		if (conv_type == ADC_HW) {
+			/* not supported */
+			ret = -ENOTSUPP;
+			dev_err(gpadc->dev,
+				"gpadc_conversion: only SW double conversion supported\n");
+			goto out;
+		} else {
+			/* Read the converted RAW data 2 */
+			ret = abx500_get_register_interruptible(gpadc->dev,
+				AB8500_GPADC, AB8540_GPADC_MANDATA2L_REG,
+				&low_data2);
+			if (ret < 0) {
+				dev_err(gpadc->dev,
+					"gpadc_conversion: read sw low data 2 failed\n");
+				goto out;
+			}
+
+			ret = abx500_get_register_interruptible(gpadc->dev,
+				AB8500_GPADC, AB8540_GPADC_MANDATA2H_REG,
+				&high_data2);
+			if (ret < 0) {
+				dev_err(gpadc->dev,
+					"gpadc_conversion: read sw high data 2 failed\n");
+				goto out;
+			}
+			if (ibat != NULL) {
+				*ibat = (high_data2 << 8) | low_data2;
+			} else {
+				dev_warn(gpadc->dev,
+					"gpadc_conversion: ibat not stored\n");
+			}
+
+		}
+	}
+
 	/* Disable GPADC */
 	ret = abx500_set_register_interruptible(gpadc->dev, AB8500_GPADC,
 		AB8500_GPADC_CTRL1_REG, DIS_GPADC);
@@ -406,6 +570,7 @@ int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel)
 		goto out;
 	}
 
+	/* Disable VTVout LDO this is required for GPADC */
 	pm_runtime_mark_last_busy(gpadc->dev);
 	pm_runtime_put_autosuspend(gpadc->dev);
 
@@ -422,9 +587,7 @@ out:
 	 */
 	(void) abx500_set_register_interruptible(gpadc->dev, AB8500_GPADC,
 		AB8500_GPADC_CTRL1_REG, DIS_GPADC);
-
 	pm_runtime_put(gpadc->dev);
-
 	mutex_unlock(&gpadc->ab8500_gpadc_lock);
 	dev_err(gpadc->dev,
 		"gpadc_conversion: Failed to AD convert channel %d\n", channel);
@@ -433,16 +596,16 @@ out:
 EXPORT_SYMBOL(ab8500_gpadc_read_raw);
 
 /**
- * ab8500_bm_gpswadcconvend_handler() - isr for s/w gpadc conversion completion
+ * ab8500_bm_gpadcconvend_handler() - isr for gpadc conversion completion
  * @irq:	irq number
  * @data:	pointer to the data passed during request irq
  *
- * This is a interrupt service routine for s/w gpadc conversion completion.
+ * This is a interrupt service routine for gpadc conversion completion.
  * Notifies the gpadc completion is completed and the converted raw value
  * can be read from the registers.
  * Returns IRQ status(IRQ_HANDLED)
  */
-static irqreturn_t ab8500_bm_gpswadcconvend_handler(int irq, void *_gpadc)
+static irqreturn_t ab8500_bm_gpadcconvend_handler(int irq, void *_gpadc)
 {
 	struct ab8500_gpadc *gpadc = _gpadc;
 
@@ -461,15 +624,27 @@ static int otp_cal_regs[] = {
 	AB8500_GPADC_CAL_7,
 };
 
+static int otp4_cal_regs[] = {
+	AB8540_GPADC_OTP4_REG_7,
+	AB8540_GPADC_OTP4_REG_6,
+	AB8540_GPADC_OTP4_REG_5,
+};
+
 static void ab8500_gpadc_read_calibration_data(struct ab8500_gpadc *gpadc)
 {
 	int i;
 	int ret[ARRAY_SIZE(otp_cal_regs)];
 	u8 gpadc_cal[ARRAY_SIZE(otp_cal_regs)];
-
+	int ret_otp4[ARRAY_SIZE(otp4_cal_regs)];
+	u8 gpadc_otp4[ARRAY_SIZE(otp4_cal_regs)];
 	int vmain_high, vmain_low;
 	int btemp_high, btemp_low;
 	int vbat_high, vbat_low;
+	int ibat_high, ibat_low;
+	s64 V_gain, V_offset, V2A_gain, V2A_offset;
+	struct ab8500 *ab8500;
+
+	ab8500 = gpadc->parent;
 
 	/* First we read all OTP registers and store the error code */
 	for (i = 0; i < ARRAY_SIZE(otp_cal_regs); i++) {
@@ -489,7 +664,7 @@ static void ab8500_gpadc_read_calibration_data(struct ab8500_gpadc *gpadc)
 	 * bt_h/l = btemp_high/low
 	 * vb_h/l = vbat_high/low
 	 *
-	 * Data bits:
+	 * Data bits 8500/9540:
 	 * | 7	   | 6	   | 5	   | 4	   | 3	   | 2	   | 1	   | 0
 	 * |.......|.......|.......|.......|.......|.......|.......|.......
 	 * |						   | vm_h9 | vm_h8
@@ -507,6 +682,35 @@ static void ab8500_gpadc_read_calibration_data(struct ab8500_gpadc *gpadc)
 	 * | vb_l5 | vb_l4 | vb_l3 | vb_l2 | vb_l1 | vb_l0 |
 	 * |.......|.......|.......|.......|.......|.......|.......|.......
 	 *
+	 * Data bits 8540:
+	 * OTP2
+	 * | 7	   | 6	   | 5	   | 4	   | 3	   | 2	   | 1	   | 0
+	 * |.......|.......|.......|.......|.......|.......|.......|.......
+	 * |
+	 * |.......|.......|.......|.......|.......|.......|.......|.......
+	 * | vm_h9 | vm_h8 | vm_h7 | vm_h6 | vm_h5 | vm_h4 | vm_h3 | vm_h2
+	 * |.......|.......|.......|.......|.......|.......|.......|.......
+	 * | vm_h1 | vm_h0 | vm_l4 | vm_l3 | vm_l2 | vm_l1 | vm_l0 | bt_h9
+	 * |.......|.......|.......|.......|.......|.......|.......|.......
+	 * | bt_h8 | bt_h7 | bt_h6 | bt_h5 | bt_h4 | bt_h3 | bt_h2 | bt_h1
+	 * |.......|.......|.......|.......|.......|.......|.......|.......
+	 * | bt_h0 | bt_l4 | bt_l3 | bt_l2 | bt_l1 | bt_l0 | vb_h9 | vb_h8
+	 * |.......|.......|.......|.......|.......|.......|.......|.......
+	 * | vb_h7 | vb_h6 | vb_h5 | vb_h4 | vb_h3 | vb_h2 | vb_h1 | vb_h0
+	 * |.......|.......|.......|.......|.......|.......|.......|.......
+	 * | vb_l5 | vb_l4 | vb_l3 | vb_l2 | vb_l1 | vb_l0 |
+	 * |.......|.......|.......|.......|.......|.......|.......|.......
+	 *
+	 * Data bits 8540:
+	 * OTP4
+	 * | 7	   | 6	   | 5	   | 4	   | 3	   | 2	   | 1	   | 0
+	 * |.......|.......|.......|.......|.......|.......|.......|.......
+	 * |					   | ib_h9 | ib_h8 | ib_h7
+	 * |.......|.......|.......|.......|.......|.......|.......|.......
+	 * | ib_h6 | ib_h5 | ib_h4 | ib_h3 | ib_h2 | ib_h1 | ib_h0 | ib_l5
+	 * |.......|.......|.......|.......|.......|.......|.......|.......
+	 * | ib_l4 | ib_l3 | ib_l2 | ib_l1 | ib_l0 |
+	 *
 	 *
 	 * Ideal output ADC codes corresponding to injected input voltages
 	 * during manufacturing is:
@@ -519,38 +723,116 @@ static void ab8500_gpadc_read_calibration_data(struct ab8500_gpadc *gpadc)
 	 * vbat_low:   Vin = 2380mV  / ADC ideal code = 33
 	 */
 
-	/* Calculate gain and offset for VMAIN if all reads succeeded */
-	if (!(ret[0] < 0 || ret[1] < 0 || ret[2] < 0)) {
-		vmain_high = (((gpadc_cal[0] & 0x03) << 8) |
-			((gpadc_cal[1] & 0x3F) << 2) |
-			((gpadc_cal[2] & 0xC0) >> 6));
+	if (is_ab8540(ab8500)) {
+		/* Calculate gain and offset for VMAIN if all reads succeeded*/
+		if (!(ret[1] < 0 || ret[2] < 0)) {
+			vmain_high = (((gpadc_cal[1] & 0xFF) << 2) |
+				((gpadc_cal[2] & 0xC0) >> 6));
+			vmain_low = ((gpadc_cal[2] & 0x3E) >> 1);
+
+			gpadc->cal_data[ADC_INPUT_VMAIN].otp_calib_hi =
+				(u16)vmain_high;
+			gpadc->cal_data[ADC_INPUT_VMAIN].otp_calib_lo =
+				(u16)vmain_low;
+
+			gpadc->cal_data[ADC_INPUT_VMAIN].gain = CALIB_SCALE *
+				(19500 - 315) / (vmain_high - vmain_low);
+			gpadc->cal_data[ADC_INPUT_VMAIN].offset = CALIB_SCALE *
+				19500 - (CALIB_SCALE * (19500 - 315) /
+				(vmain_high - vmain_low)) * vmain_high;
+		} else {
+		gpadc->cal_data[ADC_INPUT_VMAIN].gain = 0;
+		}
 
-		vmain_low = ((gpadc_cal[2] & 0x3E) >> 1);
+		/* Read IBAT calibration Data */
+		for (i = 0; i < ARRAY_SIZE(otp4_cal_regs); i++) {
+			ret_otp4[i] = abx500_get_register_interruptible(
+					gpadc->dev, AB8500_OTP_EMUL,
+					otp4_cal_regs[i],  &gpadc_otp4[i]);
+			if (ret_otp4[i] < 0)
+				dev_err(gpadc->dev,
+					"%s: read otp4 reg 0x%02x failed\n",
+					__func__, otp4_cal_regs[i]);
+		}
 
-		gpadc->cal_data[ADC_INPUT_VMAIN].gain = CALIB_SCALE *
-			(19500 - 315) /	(vmain_high - vmain_low);
+		/* Calculate gain and offset for IBAT if all reads succeeded */
+		if (!(ret_otp4[0] < 0 || ret_otp4[1] < 0 || ret_otp4[2] < 0)) {
+			ibat_high = (((gpadc_otp4[0] & 0x07) << 7) |
+				((gpadc_otp4[1] & 0xFE) >> 1));
+			ibat_low = (((gpadc_otp4[1] & 0x01) << 5) |
+				((gpadc_otp4[2] & 0xF8) >> 3));
+
+			gpadc->cal_data[ADC_INPUT_IBAT].otp_calib_hi =
+				(u16)ibat_high;
+			gpadc->cal_data[ADC_INPUT_IBAT].otp_calib_lo =
+				(u16)ibat_low;
+
+			V_gain = ((IBAT_VDROP_H - IBAT_VDROP_L)
+				<< CALIB_SHIFT_IBAT) / (ibat_high - ibat_low);
+
+			V_offset = (IBAT_VDROP_H << CALIB_SHIFT_IBAT) -
+				(((IBAT_VDROP_H - IBAT_VDROP_L) <<
+				CALIB_SHIFT_IBAT) / (ibat_high - ibat_low))
+				* ibat_high;
+			/*
+			 * Result obtained is in mV (at a scale factor),
+			 * we need to calculate gain and offset to get mA
+			 */
+			V2A_gain = (ADC_CH_IBAT_MAX - ADC_CH_IBAT_MIN)/
+				(ADC_CH_IBAT_MAX_V - ADC_CH_IBAT_MIN_V);
+			V2A_offset = ((ADC_CH_IBAT_MAX_V * ADC_CH_IBAT_MIN -
+				ADC_CH_IBAT_MAX * ADC_CH_IBAT_MIN_V)
+				<< CALIB_SHIFT_IBAT)
+				/ (ADC_CH_IBAT_MAX_V - ADC_CH_IBAT_MIN_V);
+
+			gpadc->cal_data[ADC_INPUT_IBAT].gain = V_gain * V2A_gain;
+			gpadc->cal_data[ADC_INPUT_IBAT].offset = V_offset *
+				V2A_gain + V2A_offset;
+		} else {
+			gpadc->cal_data[ADC_INPUT_IBAT].gain = 0;
+		}
 
-		gpadc->cal_data[ADC_INPUT_VMAIN].offset = CALIB_SCALE * 19500 -
-			(CALIB_SCALE * (19500 - 315) /
-			 (vmain_high - vmain_low)) * vmain_high;
+		dev_dbg(gpadc->dev, "IBAT gain %llu offset %llu\n",
+			gpadc->cal_data[ADC_INPUT_IBAT].gain,
+			gpadc->cal_data[ADC_INPUT_IBAT].offset);
 	} else {
-		gpadc->cal_data[ADC_INPUT_VMAIN].gain = 0;
+		/* Calculate gain and offset for VMAIN if all reads succeeded */
+		if (!(ret[0] < 0 || ret[1] < 0 || ret[2] < 0)) {
+			vmain_high = (((gpadc_cal[0] & 0x03) << 8) |
+				((gpadc_cal[1] & 0x3F) << 2) |
+				((gpadc_cal[2] & 0xC0) >> 6));
+			vmain_low = ((gpadc_cal[2] & 0x3E) >> 1);
+
+			gpadc->cal_data[ADC_INPUT_VMAIN].otp_calib_hi =
+				(u16)vmain_high;
+			gpadc->cal_data[ADC_INPUT_VMAIN].otp_calib_lo =
+				(u16)vmain_low;
+
+			gpadc->cal_data[ADC_INPUT_VMAIN].gain = CALIB_SCALE *
+				(19500 - 315) / (vmain_high - vmain_low);
+
+			gpadc->cal_data[ADC_INPUT_VMAIN].offset = CALIB_SCALE *
+				19500 - (CALIB_SCALE * (19500 - 315) /
+				(vmain_high - vmain_low)) * vmain_high;
+		} else {
+			gpadc->cal_data[ADC_INPUT_VMAIN].gain = 0;
+		}
 	}
 
 	/* Calculate gain and offset for BTEMP if all reads succeeded */
 	if (!(ret[2] < 0 || ret[3] < 0 || ret[4] < 0)) {
 		btemp_high = (((gpadc_cal[2] & 0x01) << 9) |
-			(gpadc_cal[3] << 1) |
-			((gpadc_cal[4] & 0x80) >> 7));
-
+			(gpadc_cal[3] << 1) | ((gpadc_cal[4] & 0x80) >> 7));
 		btemp_low = ((gpadc_cal[4] & 0x7C) >> 2);
 
+		gpadc->cal_data[ADC_INPUT_BTEMP].otp_calib_hi = (u16)btemp_high;
+		gpadc->cal_data[ADC_INPUT_BTEMP].otp_calib_lo = (u16)btemp_low;
+
 		gpadc->cal_data[ADC_INPUT_BTEMP].gain =
 			CALIB_SCALE * (1300 - 21) / (btemp_high - btemp_low);
-
 		gpadc->cal_data[ADC_INPUT_BTEMP].offset = CALIB_SCALE * 1300 -
-			(CALIB_SCALE * (1300 - 21) /
-			(btemp_high - btemp_low)) * btemp_high;
+			(CALIB_SCALE * (1300 - 21) / (btemp_high - btemp_low))
+			* btemp_high;
 	} else {
 		gpadc->cal_data[ADC_INPUT_BTEMP].gain = 0;
 	}
@@ -560,9 +842,11 @@ static void ab8500_gpadc_read_calibration_data(struct ab8500_gpadc *gpadc)
 		vbat_high = (((gpadc_cal[4] & 0x03) << 8) | gpadc_cal[5]);
 		vbat_low = ((gpadc_cal[6] & 0xFC) >> 2);
 
+		gpadc->cal_data[ADC_INPUT_VBAT].otp_calib_hi = (u16)vbat_high;
+		gpadc->cal_data[ADC_INPUT_VBAT].otp_calib_lo = (u16)vbat_low;
+
 		gpadc->cal_data[ADC_INPUT_VBAT].gain = CALIB_SCALE *
 			(4700 - 2380) /	(vbat_high - vbat_low);
-
 		gpadc->cal_data[ADC_INPUT_VBAT].offset = CALIB_SCALE * 4700 -
 			(CALIB_SCALE * (4700 - 2380) /
 			(vbat_high - vbat_low)) * vbat_high;
@@ -608,6 +892,31 @@ static int ab8500_gpadc_runtime_idle(struct device *dev)
 	return 0;
 }
 
+static int ab8500_gpadc_suspend(struct device *dev)
+{
+	struct ab8500_gpadc *gpadc = dev_get_drvdata(dev);
+
+	mutex_lock(&gpadc->ab8500_gpadc_lock);
+
+	pm_runtime_get_sync(dev);
+
+	regulator_disable(gpadc->regu);
+	return 0;
+}
+
+static int ab8500_gpadc_resume(struct device *dev)
+{
+	struct ab8500_gpadc *gpadc = dev_get_drvdata(dev);
+
+	regulator_enable(gpadc->regu);
+
+	pm_runtime_mark_last_busy(gpadc->dev);
+	pm_runtime_put_autosuspend(gpadc->dev);
+
+	mutex_unlock(&gpadc->ab8500_gpadc_lock);
+	return 0;
+}
+
 static int ab8500_gpadc_probe(struct platform_device *pdev)
 {
 	int ret = 0;
@@ -619,13 +928,13 @@ static int ab8500_gpadc_probe(struct platform_device *pdev)
 		return -ENOMEM;
 	}
 
-	gpadc->irq = platform_get_irq_byname(pdev, "SW_CONV_END");
-	if (gpadc->irq < 0) {
-		dev_err(&pdev->dev, "failed to get platform irq-%d\n",
-			gpadc->irq);
-		ret = gpadc->irq;
-		goto fail;
-	}
+	gpadc->irq_sw = platform_get_irq_byname(pdev, "SW_CONV_END");
+	if (gpadc->irq_sw < 0)
+		dev_err(gpadc->dev, "failed to get platform sw_conv_end irq\n");
+
+	gpadc->irq_hw = platform_get_irq_byname(pdev, "HW_CONV_END");
+	if (gpadc->irq_hw < 0)
+		dev_err(gpadc->dev, "failed to get platform hw_conv_end irq\n");
 
 	gpadc->dev = &pdev->dev;
 	gpadc->parent = dev_get_drvdata(pdev->dev.parent);
@@ -634,15 +943,31 @@ static int ab8500_gpadc_probe(struct platform_device *pdev)
 	/* Initialize completion used to notify completion of conversion */
 	init_completion(&gpadc->ab8500_gpadc_complete);
 
-	/* Register interrupt  - SwAdcComplete */
-	ret = request_threaded_irq(gpadc->irq, NULL,
-		ab8500_bm_gpswadcconvend_handler,
-		IRQF_ONESHOT | IRQF_NO_SUSPEND | IRQF_SHARED,
-				"ab8500-gpadc", gpadc);
-	if (ret < 0) {
-		dev_err(gpadc->dev, "Failed to register interrupt, irq: %d\n",
-			gpadc->irq);
-		goto fail;
+	/* Register interrupts */
+	if (gpadc->irq_sw >= 0) {
+		ret = request_threaded_irq(gpadc->irq_sw, NULL,
+			ab8500_bm_gpadcconvend_handler,
+			IRQF_NO_SUSPEND | IRQF_SHARED, "ab8500-gpadc-sw",
+			gpadc);
+		if (ret < 0) {
+			dev_err(gpadc->dev,
+				"Failed to register interrupt irq: %d\n",
+				gpadc->irq_sw);
+			goto fail;
+		}
+	}
+
+	if (gpadc->irq_hw >= 0) {
+		ret = request_threaded_irq(gpadc->irq_hw, NULL,
+			ab8500_bm_gpadcconvend_handler,
+			IRQF_NO_SUSPEND | IRQF_SHARED, "ab8500-gpadc-hw",
+			gpadc);
+		if (ret < 0) {
+			dev_err(gpadc->dev,
+				"Failed to register interrupt irq: %d\n",
+				gpadc->irq_hw);
+			goto fail_irq;
+		}
 	}
 
 	/* VTVout LDO used to power up ab8500-GPADC */
@@ -669,11 +994,13 @@ static int ab8500_gpadc_probe(struct platform_device *pdev)
 	ab8500_gpadc_read_calibration_data(gpadc);
 	list_add_tail(&gpadc->node, &ab8500_gpadc_list);
 	dev_dbg(gpadc->dev, "probe success\n");
+
 	return 0;
 
 fail_enable:
 fail_irq:
-	free_irq(gpadc->irq, gpadc);
+	free_irq(gpadc->irq_sw, gpadc);
+	free_irq(gpadc->irq_hw, gpadc);
 fail:
 	kfree(gpadc);
 	gpadc = NULL;
@@ -687,7 +1014,10 @@ static int ab8500_gpadc_remove(struct platform_device *pdev)
 	/* remove this gpadc entry from the list */
 	list_del(&gpadc->node);
 	/* remove interrupt  - completion of Sw ADC conversion */
-	free_irq(gpadc->irq, gpadc);
+	if (gpadc->irq_sw >= 0)
+		free_irq(gpadc->irq_sw, gpadc);
+	if (gpadc->irq_hw >= 0)
+		free_irq(gpadc->irq_hw, gpadc);
 
 	pm_runtime_get_sync(gpadc->dev);
 	pm_runtime_disable(gpadc->dev);
@@ -707,6 +1037,9 @@ static const struct dev_pm_ops ab8500_gpadc_pm_ops = {
 	SET_RUNTIME_PM_OPS(ab8500_gpadc_runtime_suspend,
 			   ab8500_gpadc_runtime_resume,
 			   ab8500_gpadc_runtime_idle)
+	SET_SYSTEM_SLEEP_PM_OPS(ab8500_gpadc_suspend,
+				ab8500_gpadc_resume)
+
 };
 
 static struct platform_driver ab8500_gpadc_driver = {
@@ -729,10 +1062,30 @@ static void __exit ab8500_gpadc_exit(void)
 	platform_driver_unregister(&ab8500_gpadc_driver);
 }
 
+/**
+ * ab8540_gpadc_get_otp() - returns OTP values
+ *
+ */
+void ab8540_gpadc_get_otp(struct ab8500_gpadc *gpadc,
+			u16 *vmain_l, u16 *vmain_h, u16 *btemp_l, u16 *btemp_h,
+			u16 *vbat_l, u16 *vbat_h, u16 *ibat_l, u16 *ibat_h)
+{
+	*vmain_l = gpadc->cal_data[ADC_INPUT_VMAIN].otp_calib_lo;
+	*vmain_h = gpadc->cal_data[ADC_INPUT_VMAIN].otp_calib_hi;
+	*btemp_l = gpadc->cal_data[ADC_INPUT_BTEMP].otp_calib_lo;
+	*btemp_h = gpadc->cal_data[ADC_INPUT_BTEMP].otp_calib_hi;
+	*vbat_l = gpadc->cal_data[ADC_INPUT_VBAT].otp_calib_lo;
+	*vbat_h = gpadc->cal_data[ADC_INPUT_VBAT].otp_calib_hi;
+	*ibat_l = gpadc->cal_data[ADC_INPUT_IBAT].otp_calib_lo;
+	*ibat_h = gpadc->cal_data[ADC_INPUT_IBAT].otp_calib_hi;
+	return ;
+}
+
 subsys_initcall_sync(ab8500_gpadc_init);
 module_exit(ab8500_gpadc_exit);
 
 MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("Arun R Murthy, Daniel Willerud, Johan Palsson");
+MODULE_AUTHOR("Arun R Murthy, Daniel Willerud, Johan Palsson,"
+		"M'boumba Cedric Madianga");
 MODULE_ALIAS("platform:ab8500_gpadc");
 MODULE_DESCRIPTION("AB8500 GPADC driver");
diff --git a/drivers/mfd/ab8500-sysctrl.c b/drivers/mfd/ab8500-sysctrl.c
index 108fd86..272479c 100644
--- a/drivers/mfd/ab8500-sysctrl.c
+++ b/drivers/mfd/ab8500-sysctrl.c
@@ -15,19 +15,30 @@
 #include <linux/mfd/abx500/ab8500.h>
 #include <linux/mfd/abx500/ab8500-sysctrl.h>
 
+/* RtcCtrl bits */
+#define AB8500_ALARM_MIN_LOW  0x08
+#define AB8500_ALARM_MIN_MID 0x09
+#define RTC_CTRL 0x0B
+#define RTC_ALARM_ENABLE 0x4
+
 static struct device *sysctrl_dev;
 
 void ab8500_power_off(void)
 {
 	sigset_t old;
 	sigset_t all;
-	static char *pss[] = {"ab8500_ac", "ab8500_usb"};
+	static char *pss[] = {"ab8500_ac", "pm2301", "ab8500_usb"};
 	int i;
 	bool charger_present = false;
 	union power_supply_propval val;
 	struct power_supply *psy;
 	int ret;
 
+	if (sysctrl_dev == NULL) {
+		pr_err("%s: sysctrl not initialized\n", __func__);
+		return;
+	}
+
 	/*
 	 * If we have a charger connected and we're powering off,
 	 * reboot into charge-only mode.
@@ -74,6 +85,63 @@ shutdown:
 	}
 }
 
+/*
+ * Use the AB WD to reset the platform. It will perform a hard
+ * reset instead of a soft reset. Write the reset reason to
+ * the AB before reset, which can be read upon restart.
+ */
+void ab8500_restart(char mode, const char *cmd)
+{
+	struct ab8500_platform_data *plat;
+	struct ab8500_sysctrl_platform_data *pdata;
+	u16 reason = 0;
+	u8 val;
+
+	if (sysctrl_dev == NULL) {
+		pr_err("%s: sysctrl not initialized\n", __func__);
+		return;
+	}
+
+	plat = dev_get_platdata(sysctrl_dev->parent);
+	pdata = plat->sysctrl;
+	if (pdata->reboot_reason_code)
+		reason = pdata->reboot_reason_code(cmd);
+	else
+		pr_warn("[%s] No reboot reason set. Default reason %d\n",
+			__func__, reason);
+
+	/*
+	 * Disable RTC alarm, just a precaution so that no alarm
+	 * is running when WD reset is executed.
+	 */
+	abx500_get_register_interruptible(sysctrl_dev, AB8500_RTC,
+		RTC_CTRL , &val);
+	abx500_set_register_interruptible(sysctrl_dev, AB8500_RTC,
+		RTC_CTRL , (val & ~RTC_ALARM_ENABLE));
+
+	/*
+	 * Android is not using the RTC alarm registers during reboot
+	 * so we borrow them for writing the reason of reset
+	 */
+
+	/* reason[8 LSB] */
+	val = reason & 0xFF;
+	abx500_set_register_interruptible(sysctrl_dev, AB8500_RTC,
+		AB8500_ALARM_MIN_LOW , val);
+
+	/* reason[8 MSB] */
+	val = (reason>>8) & 0xFF;
+	abx500_set_register_interruptible(sysctrl_dev, AB8500_RTC,
+		AB8500_ALARM_MIN_MID , val);
+
+	/* Setting WD timeout to 0 */
+	ab8500_sysctrl_write(AB8500_MAINWDOGTIMER, 0xFF, 0x0);
+
+	/* Setting the parameters to AB8500 WD*/
+	ab8500_sysctrl_write(AB8500_MAINWDOGCTRL, 0xFF, (AB8500_ENABLE_WD |
+		AB8500_WD_RESTART_ON_EXPIRE | AB8500_KICK_WD));
+}
+
 static inline bool valid_bank(u8 bank)
 {
 	return ((bank == AB8500_SYS_CTRL1_BLOCK) ||
@@ -85,7 +153,7 @@ int ab8500_sysctrl_read(u16 reg, u8 *value)
 	u8 bank;
 
 	if (sysctrl_dev == NULL)
-		return -EAGAIN;
+		return -EINVAL;
 
 	bank = (reg >> 8);
 	if (!valid_bank(bank))
@@ -101,7 +169,7 @@ int ab8500_sysctrl_write(u16 reg, u8 mask, u8 value)
 	u8 bank;
 
 	if (sysctrl_dev == NULL)
-		return -EAGAIN;
+		return -EINVAL;
 
 	bank = (reg >> 8);
 	if (!valid_bank(bank))
@@ -114,28 +182,36 @@ EXPORT_SYMBOL(ab8500_sysctrl_write);
 
 static int ab8500_sysctrl_probe(struct platform_device *pdev)
 {
+	struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent);
 	struct ab8500_platform_data *plat;
 	struct ab8500_sysctrl_platform_data *pdata;
 
-	sysctrl_dev = &pdev->dev;
 	plat = dev_get_platdata(pdev->dev.parent);
+
+	if (!(plat && plat->sysctrl))
+		return -EINVAL;
+
 	if (plat->pm_power_off)
 		pm_power_off = ab8500_power_off;
 
 	pdata = plat->sysctrl;
 
 	if (pdata) {
-		int ret, i, j;
+		int last, ret, i, j;
+
+		if (is_ab8505(ab8500))
+			last = AB8500_SYSCLKREQ4RFCLKBUF;
+		else
+			last = AB8500_SYSCLKREQ8RFCLKBUF;
 
-		for (i = AB8500_SYSCLKREQ1RFCLKBUF;
-		     i <= AB8500_SYSCLKREQ8RFCLKBUF; i++) {
+		for (i = AB8500_SYSCLKREQ1RFCLKBUF; i <= last; i++) {
 			j = i - AB8500_SYSCLKREQ1RFCLKBUF;
 			ret = ab8500_sysctrl_write(i, 0xff,
-						   pdata->initial_req_buf_config[j]);
+					pdata->initial_req_buf_config[j]);
 			dev_dbg(&pdev->dev,
-				"Setting SysClkReq%dRfClkBuf 0x%X\n",
-				j + 1,
-				pdata->initial_req_buf_config[j]);
+					"Setting SysClkReq%dRfClkBuf 0x%X\n",
+					j + 1,
+					pdata->initial_req_buf_config[j]);
 			if (ret < 0) {
 				dev_err(&pdev->dev,
 					"unable to set sysClkReq%dRfClkBuf: "
diff --git a/drivers/mfd/as3711.c b/drivers/mfd/as3711.c
index e994c96..01e4141 100644
--- a/drivers/mfd/as3711.c
+++ b/drivers/mfd/as3711.c
@@ -112,16 +112,34 @@ static const struct regmap_config as3711_regmap_config = {
 	.cache_type = REGCACHE_RBTREE,
 };
 
+#ifdef CONFIG_OF
+static struct of_device_id as3711_of_match[] = {
+	{.compatible = "ams,as3711",},
+	{}
+};
+MODULE_DEVICE_TABLE(of, as3711_of_match);
+#endif
+
 static int as3711_i2c_probe(struct i2c_client *client,
 			    const struct i2c_device_id *id)
 {
 	struct as3711 *as3711;
-	struct as3711_platform_data *pdata = client->dev.platform_data;
+	struct as3711_platform_data *pdata;
 	unsigned int id1, id2;
 	int ret;
 
-	if (!pdata)
-		dev_dbg(&client->dev, "Platform data not found\n");
+	if (!client->dev.of_node) {
+		pdata = client->dev.platform_data;
+		if (!pdata)
+			dev_dbg(&client->dev, "Platform data not found\n");
+	} else {
+		pdata = devm_kzalloc(&client->dev,
+				     sizeof(*pdata), GFP_KERNEL);
+		if (!pdata) {
+			dev_err(&client->dev, "Failed to allocate pdata\n");
+			return -ENOMEM;
+		}
+	}
 
 	as3711 = devm_kzalloc(&client->dev, sizeof(struct as3711), GFP_KERNEL);
 	if (!as3711) {
@@ -193,7 +211,8 @@ static struct i2c_driver as3711_i2c_driver = {
 	.driver = {
 		   .name = "as3711",
 		   .owner = THIS_MODULE,
-		   },
+		   .of_match_table = of_match_ptr(as3711_of_match),
+	},
 	.probe = as3711_i2c_probe,
 	.remove = as3711_i2c_remove,
 	.id_table = as3711_i2c_id,
diff --git a/drivers/mfd/cros_ec.c b/drivers/mfd/cros_ec.c
new file mode 100644
index 0000000..10cd14e
--- /dev/null
+++ b/drivers/mfd/cros_ec.c
@@ -0,0 +1,196 @@
+/*
+ * ChromeOS EC multi-function device
+ *
+ * Copyright (C) 2012 Google, 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.
+ *
+ * The ChromeOS EC multi function device is used to mux all the requests
+ * to the EC device for its multiple features: keyboard controller,
+ * battery charging and regulator control, firmware update.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/cros_ec.h>
+#include <linux/mfd/cros_ec_commands.h>
+
+int cros_ec_prepare_tx(struct cros_ec_device *ec_dev,
+		       struct cros_ec_msg *msg)
+{
+	uint8_t *out;
+	int csum, i;
+
+	BUG_ON(msg->out_len > EC_HOST_PARAM_SIZE);
+	out = ec_dev->dout;
+	out[0] = EC_CMD_VERSION0 + msg->version;
+	out[1] = msg->cmd;
+	out[2] = msg->out_len;
+	csum = out[0] + out[1] + out[2];
+	for (i = 0; i < msg->out_len; i++)
+		csum += out[EC_MSG_TX_HEADER_BYTES + i] = msg->out_buf[i];
+	out[EC_MSG_TX_HEADER_BYTES + msg->out_len] = (uint8_t)(csum & 0xff);
+
+	return EC_MSG_TX_PROTO_BYTES + msg->out_len;
+}
+EXPORT_SYMBOL(cros_ec_prepare_tx);
+
+static int cros_ec_command_sendrecv(struct cros_ec_device *ec_dev,
+		uint16_t cmd, void *out_buf, int out_len,
+		void *in_buf, int in_len)
+{
+	struct cros_ec_msg msg;
+
+	msg.version = cmd >> 8;
+	msg.cmd = cmd & 0xff;
+	msg.out_buf = out_buf;
+	msg.out_len = out_len;
+	msg.in_buf = in_buf;
+	msg.in_len = in_len;
+
+	return ec_dev->command_xfer(ec_dev, &msg);
+}
+
+static int cros_ec_command_recv(struct cros_ec_device *ec_dev,
+		uint16_t cmd, void *buf, int buf_len)
+{
+	return cros_ec_command_sendrecv(ec_dev, cmd, NULL, 0, buf, buf_len);
+}
+
+static int cros_ec_command_send(struct cros_ec_device *ec_dev,
+		uint16_t cmd, void *buf, int buf_len)
+{
+	return cros_ec_command_sendrecv(ec_dev, cmd, buf, buf_len, NULL, 0);
+}
+
+static irqreturn_t ec_irq_thread(int irq, void *data)
+{
+	struct cros_ec_device *ec_dev = data;
+
+	if (device_may_wakeup(ec_dev->dev))
+		pm_wakeup_event(ec_dev->dev, 0);
+
+	blocking_notifier_call_chain(&ec_dev->event_notifier, 1, ec_dev);
+
+	return IRQ_HANDLED;
+}
+
+static struct mfd_cell cros_devs[] = {
+	{
+		.name = "cros-ec-keyb",
+		.id = 1,
+		.of_compatible = "google,cros-ec-keyb",
+	},
+};
+
+int cros_ec_register(struct cros_ec_device *ec_dev)
+{
+	struct device *dev = ec_dev->dev;
+	int err = 0;
+
+	BLOCKING_INIT_NOTIFIER_HEAD(&ec_dev->event_notifier);
+
+	ec_dev->command_send = cros_ec_command_send;
+	ec_dev->command_recv = cros_ec_command_recv;
+	ec_dev->command_sendrecv = cros_ec_command_sendrecv;
+
+	if (ec_dev->din_size) {
+		ec_dev->din = kmalloc(ec_dev->din_size, GFP_KERNEL);
+		if (!ec_dev->din) {
+			err = -ENOMEM;
+			goto fail_din;
+		}
+	}
+	if (ec_dev->dout_size) {
+		ec_dev->dout = kmalloc(ec_dev->dout_size, GFP_KERNEL);
+		if (!ec_dev->dout) {
+			err = -ENOMEM;
+			goto fail_dout;
+		}
+	}
+
+	if (!ec_dev->irq) {
+		dev_dbg(dev, "no valid IRQ: %d\n", ec_dev->irq);
+		goto fail_irq;
+	}
+
+	err = request_threaded_irq(ec_dev->irq, NULL, ec_irq_thread,
+				   IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+				   "chromeos-ec", ec_dev);
+	if (err) {
+		dev_err(dev, "request irq %d: error %d\n", ec_dev->irq, err);
+		goto fail_irq;
+	}
+
+	err = mfd_add_devices(dev, 0, cros_devs,
+			      ARRAY_SIZE(cros_devs),
+			      NULL, ec_dev->irq, NULL);
+	if (err) {
+		dev_err(dev, "failed to add mfd devices\n");
+		goto fail_mfd;
+	}
+
+	dev_info(dev, "Chrome EC (%s)\n", ec_dev->name);
+
+	return 0;
+
+fail_mfd:
+	free_irq(ec_dev->irq, ec_dev);
+fail_irq:
+	kfree(ec_dev->dout);
+fail_dout:
+	kfree(ec_dev->din);
+fail_din:
+	return err;
+}
+EXPORT_SYMBOL(cros_ec_register);
+
+int cros_ec_remove(struct cros_ec_device *ec_dev)
+{
+	mfd_remove_devices(ec_dev->dev);
+	free_irq(ec_dev->irq, ec_dev);
+	kfree(ec_dev->dout);
+	kfree(ec_dev->din);
+
+	return 0;
+}
+EXPORT_SYMBOL(cros_ec_remove);
+
+#ifdef CONFIG_PM_SLEEP
+int cros_ec_suspend(struct cros_ec_device *ec_dev)
+{
+	struct device *dev = ec_dev->dev;
+
+	if (device_may_wakeup(dev))
+		ec_dev->wake_enabled = !enable_irq_wake(ec_dev->irq);
+
+	disable_irq(ec_dev->irq);
+	ec_dev->was_wake_device = ec_dev->wake_enabled;
+
+	return 0;
+}
+EXPORT_SYMBOL(cros_ec_suspend);
+
+int cros_ec_resume(struct cros_ec_device *ec_dev)
+{
+	enable_irq(ec_dev->irq);
+
+	if (ec_dev->wake_enabled) {
+		disable_irq_wake(ec_dev->irq);
+		ec_dev->wake_enabled = 0;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(cros_ec_resume);
+
+#endif
diff --git a/drivers/mfd/cros_ec_i2c.c b/drivers/mfd/cros_ec_i2c.c
new file mode 100644
index 0000000..1230446
--- /dev/null
+++ b/drivers/mfd/cros_ec_i2c.c
@@ -0,0 +1,201 @@
+/*
+ * ChromeOS EC multi-function device (I2C)
+ *
+ * Copyright (C) 2012 Google, 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/cros_ec.h>
+#include <linux/mfd/cros_ec_commands.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+static inline struct cros_ec_device *to_ec_dev(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+
+	return i2c_get_clientdata(client);
+}
+
+static int cros_ec_command_xfer(struct cros_ec_device *ec_dev,
+				struct cros_ec_msg *msg)
+{
+	struct i2c_client *client = ec_dev->priv;
+	int ret = -ENOMEM;
+	int i;
+	int packet_len;
+	u8 *out_buf = NULL;
+	u8 *in_buf = NULL;
+	u8 sum;
+	struct i2c_msg i2c_msg[2];
+
+	i2c_msg[0].addr = client->addr;
+	i2c_msg[0].flags = 0;
+	i2c_msg[1].addr = client->addr;
+	i2c_msg[1].flags = I2C_M_RD;
+
+	/*
+	 * allocate larger packet (one byte for checksum, one byte for
+	 * length, and one for result code)
+	 */
+	packet_len = msg->in_len + 3;
+	in_buf = kzalloc(packet_len, GFP_KERNEL);
+	if (!in_buf)
+		goto done;
+	i2c_msg[1].len = packet_len;
+	i2c_msg[1].buf = (char *)in_buf;
+
+	/*
+	 * allocate larger packet (one byte for checksum, one for
+	 * command code, one for length, and one for command version)
+	 */
+	packet_len = msg->out_len + 4;
+	out_buf = kzalloc(packet_len, GFP_KERNEL);
+	if (!out_buf)
+		goto done;
+	i2c_msg[0].len = packet_len;
+	i2c_msg[0].buf = (char *)out_buf;
+
+	out_buf[0] = EC_CMD_VERSION0 + msg->version;
+	out_buf[1] = msg->cmd;
+	out_buf[2] = msg->out_len;
+
+	/* copy message payload and compute checksum */
+	sum = out_buf[0] + out_buf[1] + out_buf[2];
+	for (i = 0; i < msg->out_len; i++) {
+		out_buf[3 + i] = msg->out_buf[i];
+		sum += out_buf[3 + i];
+	}
+	out_buf[3 + msg->out_len] = sum;
+
+	/* send command to EC and read answer */
+	ret = i2c_transfer(client->adapter, i2c_msg, 2);
+	if (ret < 0) {
+		dev_err(ec_dev->dev, "i2c transfer failed: %d\n", ret);
+		goto done;
+	} else if (ret != 2) {
+		dev_err(ec_dev->dev, "failed to get response: %d\n", ret);
+		ret = -EIO;
+		goto done;
+	}
+
+	/* check response error code */
+	if (i2c_msg[1].buf[0]) {
+		dev_warn(ec_dev->dev, "command 0x%02x returned an error %d\n",
+			 msg->cmd, i2c_msg[1].buf[0]);
+		ret = -EINVAL;
+		goto done;
+	}
+
+	/* copy response packet payload and compute checksum */
+	sum = in_buf[0] + in_buf[1];
+	for (i = 0; i < msg->in_len; i++) {
+		msg->in_buf[i] = in_buf[2 + i];
+		sum += in_buf[2 + i];
+	}
+	dev_dbg(ec_dev->dev, "packet: %*ph, sum = %02x\n",
+		i2c_msg[1].len, in_buf, sum);
+	if (sum != in_buf[2 + msg->in_len]) {
+		dev_err(ec_dev->dev, "bad packet checksum\n");
+		ret = -EBADMSG;
+		goto done;
+	}
+
+	ret = 0;
+ done:
+	kfree(in_buf);
+	kfree(out_buf);
+	return ret;
+}
+
+static int cros_ec_probe_i2c(struct i2c_client *client,
+			     const struct i2c_device_id *dev_id)
+{
+	struct device *dev = &client->dev;
+	struct cros_ec_device *ec_dev = NULL;
+	int err;
+
+ 	ec_dev = devm_kzalloc(dev, sizeof(*ec_dev), GFP_KERNEL);
+	if (!ec_dev)
+		return -ENOMEM;
+
+	i2c_set_clientdata(client, ec_dev);
+	ec_dev->name = "I2C";
+	ec_dev->dev = dev;
+	ec_dev->priv = client;
+	ec_dev->irq = client->irq;
+	ec_dev->command_xfer = cros_ec_command_xfer;
+	ec_dev->ec_name = client->name;
+	ec_dev->phys_name = client->adapter->name;
+	ec_dev->parent = &client->dev;
+
+	err = cros_ec_register(ec_dev);
+	if (err) {
+		dev_err(dev, "cannot register EC\n");
+		return err;
+	}
+
+	return 0;
+}
+
+static int cros_ec_remove_i2c(struct i2c_client *client)
+{
+	struct cros_ec_device *ec_dev = i2c_get_clientdata(client);
+
+	cros_ec_remove(ec_dev);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int cros_ec_i2c_suspend(struct device *dev)
+{
+	struct cros_ec_device *ec_dev = to_ec_dev(dev);
+
+	return cros_ec_suspend(ec_dev);
+}
+
+static int cros_ec_i2c_resume(struct device *dev)
+{
+	struct cros_ec_device *ec_dev = to_ec_dev(dev);
+
+	return cros_ec_resume(ec_dev);
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(cros_ec_i2c_pm_ops, cros_ec_i2c_suspend,
+			  cros_ec_i2c_resume);
+
+static const struct i2c_device_id cros_ec_i2c_id[] = {
+	{ "cros-ec-i2c", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, cros_ec_i2c_id);
+
+static struct i2c_driver cros_ec_driver = {
+	.driver	= {
+		.name	= "cros-ec-i2c",
+		.owner	= THIS_MODULE,
+		.pm	= &cros_ec_i2c_pm_ops,
+	},
+	.probe		= cros_ec_probe_i2c,
+	.remove		= cros_ec_remove_i2c,
+	.id_table	= cros_ec_i2c_id,
+};
+
+module_i2c_driver(cros_ec_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("ChromeOS EC multi function device");
diff --git a/drivers/mfd/cros_ec_spi.c b/drivers/mfd/cros_ec_spi.c
new file mode 100644
index 0000000..19193cf
--- /dev/null
+++ b/drivers/mfd/cros_ec_spi.c
@@ -0,0 +1,375 @@
+/*
+ * ChromeOS EC multi-function device (SPI)
+ *
+ * Copyright (C) 2012 Google, 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.
+ */
+
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mfd/cros_ec.h>
+#include <linux/mfd/cros_ec_commands.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/spi/spi.h>
+
+
+/* The header byte, which follows the preamble */
+#define EC_MSG_HEADER			0xec
+
+/*
+ * Number of EC preamble bytes we read at a time. Since it takes
+ * about 400-500us for the EC to respond there is not a lot of
+ * point in tuning this. If the EC could respond faster then
+ * we could increase this so that might expect the preamble and
+ * message to occur in a single transaction. However, the maximum
+ * SPI transfer size is 256 bytes, so at 5MHz we need a response
+ * time of perhaps <320us (200 bytes / 1600 bits).
+ */
+#define EC_MSG_PREAMBLE_COUNT		32
+
+/*
+  * We must get a response from the EC in 5ms. This is a very long
+  * time, but the flash write command can take 2-3ms. The EC command
+  * processing is currently not very fast (about 500us). We could
+  * look at speeding this up and making the flash write command a
+  * 'slow' command, requiring a GET_STATUS wait loop, like flash
+  * erase.
+  */
+#define EC_MSG_DEADLINE_MS		5
+
+/*
+  * Time between raising the SPI chip select (for the end of a
+  * transaction) and dropping it again (for the next transaction).
+  * If we go too fast, the EC will miss the transaction. It seems
+  * that 50us is enough with the 16MHz STM32 EC.
+  */
+#define EC_SPI_RECOVERY_TIME_NS	(50 * 1000)
+
+/**
+ * struct cros_ec_spi - information about a SPI-connected EC
+ *
+ * @spi: SPI device we are connected to
+ * @last_transfer_ns: time that we last finished a transfer, or 0 if there
+ *	if no record
+ */
+struct cros_ec_spi {
+	struct spi_device *spi;
+	s64 last_transfer_ns;
+};
+
+static void debug_packet(struct device *dev, const char *name, u8 *ptr,
+			  int len)
+{
+#ifdef DEBUG
+	int i;
+
+	dev_dbg(dev, "%s: ", name);
+	for (i = 0; i < len; i++)
+		dev_cont(dev, " %02x", ptr[i]);
+#endif
+}
+
+/**
+ * cros_ec_spi_receive_response - Receive a response from the EC.
+ *
+ * This function has two phases: reading the preamble bytes (since if we read
+ * data from the EC before it is ready to send, we just get preamble) and
+ * reading the actual message.
+ *
+ * The received data is placed into ec_dev->din.
+ *
+ * @ec_dev: ChromeOS EC device
+ * @need_len: Number of message bytes we need to read
+ */
+static int cros_ec_spi_receive_response(struct cros_ec_device *ec_dev,
+					int need_len)
+{
+	struct cros_ec_spi *ec_spi = ec_dev->priv;
+	struct spi_transfer trans;
+	struct spi_message msg;
+	u8 *ptr, *end;
+	int ret;
+	unsigned long deadline;
+	int todo;
+
+	/* Receive data until we see the header byte */
+	deadline = jiffies + msecs_to_jiffies(EC_MSG_DEADLINE_MS);
+	do {
+		memset(&trans, '\0', sizeof(trans));
+		trans.cs_change = 1;
+		trans.rx_buf = ptr = ec_dev->din;
+		trans.len = EC_MSG_PREAMBLE_COUNT;
+
+		spi_message_init(&msg);
+		spi_message_add_tail(&trans, &msg);
+		ret = spi_sync(ec_spi->spi, &msg);
+		if (ret < 0) {
+			dev_err(ec_dev->dev, "spi transfer failed: %d\n", ret);
+			return ret;
+		}
+
+		for (end = ptr + EC_MSG_PREAMBLE_COUNT; ptr != end; ptr++) {
+			if (*ptr == EC_MSG_HEADER) {
+				dev_dbg(ec_dev->dev, "msg found at %ld\n",
+					ptr - ec_dev->din);
+				break;
+			}
+		}
+
+		if (time_after(jiffies, deadline)) {
+			dev_warn(ec_dev->dev, "EC failed to respond in time\n");
+			return -ETIMEDOUT;
+		}
+	} while (ptr == end);
+
+	/*
+	 * ptr now points to the header byte. Copy any valid data to the
+	 * start of our buffer
+	 */
+	todo = end - ++ptr;
+	BUG_ON(todo < 0 || todo > ec_dev->din_size);
+	todo = min(todo, need_len);
+	memmove(ec_dev->din, ptr, todo);
+	ptr = ec_dev->din + todo;
+	dev_dbg(ec_dev->dev, "need %d, got %d bytes from preamble\n",
+		 need_len, todo);
+	need_len -= todo;
+
+	/* Receive data until we have it all */
+	while (need_len > 0) {
+		/*
+		 * We can't support transfers larger than the SPI FIFO size
+		 * unless we have DMA. We don't have DMA on the ISP SPI ports
+		 * for Exynos. We need a way of asking SPI driver for
+		 * maximum-supported transfer size.
+		 */
+		todo = min(need_len, 256);
+		dev_dbg(ec_dev->dev, "loop, todo=%d, need_len=%d, ptr=%ld\n",
+			todo, need_len, ptr - ec_dev->din);
+
+		memset(&trans, '\0', sizeof(trans));
+		trans.cs_change = 1;
+		trans.rx_buf = ptr;
+		trans.len = todo;
+		spi_message_init(&msg);
+		spi_message_add_tail(&trans, &msg);
+
+		/* send command to EC and read answer */
+		BUG_ON((u8 *)trans.rx_buf - ec_dev->din + todo >
+				ec_dev->din_size);
+		ret = spi_sync(ec_spi->spi, &msg);
+		if (ret < 0) {
+			dev_err(ec_dev->dev, "spi transfer failed: %d\n", ret);
+			return ret;
+		}
+
+		debug_packet(ec_dev->dev, "interim", ptr, todo);
+		ptr += todo;
+		need_len -= todo;
+	}
+
+	dev_dbg(ec_dev->dev, "loop done, ptr=%ld\n", ptr - ec_dev->din);
+
+	return 0;
+}
+
+/**
+ * cros_ec_command_spi_xfer - Transfer a message over SPI and receive the reply
+ *
+ * @ec_dev: ChromeOS EC device
+ * @ec_msg: Message to transfer
+ */
+static int cros_ec_command_spi_xfer(struct cros_ec_device *ec_dev,
+				    struct cros_ec_msg *ec_msg)
+{
+	struct cros_ec_spi *ec_spi = ec_dev->priv;
+	struct spi_transfer trans;
+	struct spi_message msg;
+	int i, len;
+	u8 *ptr;
+	int sum;
+	int ret = 0, final_ret;
+	struct timespec ts;
+
+	len = cros_ec_prepare_tx(ec_dev, ec_msg);
+	dev_dbg(ec_dev->dev, "prepared, len=%d\n", len);
+
+	/* If it's too soon to do another transaction, wait */
+	if (ec_spi->last_transfer_ns) {
+		struct timespec ts;
+		unsigned long delay;	/* The delay completed so far */
+
+		ktime_get_ts(&ts);
+		delay = timespec_to_ns(&ts) - ec_spi->last_transfer_ns;
+		if (delay < EC_SPI_RECOVERY_TIME_NS)
+			ndelay(delay);
+	}
+
+	/* Transmit phase - send our message */
+	debug_packet(ec_dev->dev, "out", ec_dev->dout, len);
+	memset(&trans, '\0', sizeof(trans));
+	trans.tx_buf = ec_dev->dout;
+	trans.len = len;
+	trans.cs_change = 1;
+	spi_message_init(&msg);
+	spi_message_add_tail(&trans, &msg);
+	ret = spi_sync(ec_spi->spi, &msg);
+
+	/* Get the response */
+	if (!ret) {
+		ret = cros_ec_spi_receive_response(ec_dev,
+				ec_msg->in_len + EC_MSG_TX_PROTO_BYTES);
+	} else {
+		dev_err(ec_dev->dev, "spi transfer failed: %d\n", ret);
+	}
+
+	/* turn off CS */
+	spi_message_init(&msg);
+	final_ret = spi_sync(ec_spi->spi, &msg);
+	ktime_get_ts(&ts);
+	ec_spi->last_transfer_ns = timespec_to_ns(&ts);
+	if (!ret)
+		ret = final_ret;
+	if (ret < 0) {
+		dev_err(ec_dev->dev, "spi transfer failed: %d\n", ret);
+		return ret;
+	}
+
+	/* check response error code */
+	ptr = ec_dev->din;
+	if (ptr[0]) {
+		dev_warn(ec_dev->dev, "command 0x%02x returned an error %d\n",
+			 ec_msg->cmd, ptr[0]);
+		debug_packet(ec_dev->dev, "in_err", ptr, len);
+		return -EINVAL;
+	}
+	len = ptr[1];
+	sum = ptr[0] + ptr[1];
+	if (len > ec_msg->in_len) {
+		dev_err(ec_dev->dev, "packet too long (%d bytes, expected %d)",
+			len, ec_msg->in_len);
+		return -ENOSPC;
+	}
+
+	/* copy response packet payload and compute checksum */
+	for (i = 0; i < len; i++) {
+		sum += ptr[i + 2];
+		if (ec_msg->in_len)
+			ec_msg->in_buf[i] = ptr[i + 2];
+	}
+	sum &= 0xff;
+
+	debug_packet(ec_dev->dev, "in", ptr, len + 3);
+
+	if (sum != ptr[len + 2]) {
+		dev_err(ec_dev->dev,
+			"bad packet checksum, expected %02x, got %02x\n",
+			sum, ptr[len + 2]);
+		return -EBADMSG;
+	}
+
+	return 0;
+}
+
+static int cros_ec_probe_spi(struct spi_device *spi)
+{
+	struct device *dev = &spi->dev;
+	struct cros_ec_device *ec_dev;
+	struct cros_ec_spi *ec_spi;
+	int err;
+
+	spi->bits_per_word = 8;
+	spi->mode = SPI_MODE_0;
+	err = spi_setup(spi);
+	if (err < 0)
+		return err;
+
+	ec_spi = devm_kzalloc(dev, sizeof(*ec_spi), GFP_KERNEL);
+	if (ec_spi == NULL)
+		return -ENOMEM;
+	ec_spi->spi = spi;
+	ec_dev = devm_kzalloc(dev, sizeof(*ec_dev), GFP_KERNEL);
+	if (!ec_dev)
+		return -ENOMEM;
+
+	spi_set_drvdata(spi, ec_dev);
+	ec_dev->name = "SPI";
+	ec_dev->dev = dev;
+	ec_dev->priv = ec_spi;
+	ec_dev->irq = spi->irq;
+	ec_dev->command_xfer = cros_ec_command_spi_xfer;
+	ec_dev->ec_name = ec_spi->spi->modalias;
+	ec_dev->phys_name = dev_name(&ec_spi->spi->dev);
+	ec_dev->parent = &ec_spi->spi->dev;
+	ec_dev->din_size = EC_MSG_BYTES + EC_MSG_PREAMBLE_COUNT;
+	ec_dev->dout_size = EC_MSG_BYTES;
+
+	err = cros_ec_register(ec_dev);
+	if (err) {
+		dev_err(dev, "cannot register EC\n");
+		return err;
+	}
+
+	return 0;
+}
+
+static int cros_ec_remove_spi(struct spi_device *spi)
+{
+	struct cros_ec_device *ec_dev;
+
+	ec_dev = spi_get_drvdata(spi);
+	cros_ec_remove(ec_dev);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int cros_ec_spi_suspend(struct device *dev)
+{
+	struct cros_ec_device *ec_dev = dev_get_drvdata(dev);
+
+	return cros_ec_suspend(ec_dev);
+}
+
+static int cros_ec_spi_resume(struct device *dev)
+{
+	struct cros_ec_device *ec_dev = dev_get_drvdata(dev);
+
+	return cros_ec_resume(ec_dev);
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(cros_ec_spi_pm_ops, cros_ec_spi_suspend,
+			 cros_ec_spi_resume);
+
+static const struct spi_device_id cros_ec_spi_id[] = {
+	{ "cros-ec-spi", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(spi, cros_ec_spi_id);
+
+static struct spi_driver cros_ec_driver_spi = {
+	.driver	= {
+		.name	= "cros-ec-spi",
+		.owner	= THIS_MODULE,
+		.pm	= &cros_ec_spi_pm_ops,
+	},
+	.probe		= cros_ec_probe_spi,
+	.remove		= cros_ec_remove_spi,
+	.id_table	= cros_ec_spi_id,
+};
+
+module_spi_driver(cros_ec_driver_spi);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("ChromeOS EC multi function device (SPI)");
diff --git a/drivers/mfd/pm8921-core.c b/drivers/mfd/pm8921-core.c
index d4b297c..ecc137f 100644
--- a/drivers/mfd/pm8921-core.c
+++ b/drivers/mfd/pm8921-core.c
@@ -17,7 +17,7 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/err.h>
-#include <linux/msm_ssbi.h>
+#include <linux/ssbi.h>
 #include <linux/mfd/core.h>
 #include <linux/mfd/pm8xxx/pm8921.h>
 #include <linux/mfd/pm8xxx/core.h>
@@ -35,7 +35,7 @@ static int pm8921_readb(const struct device *dev, u16 addr, u8 *val)
 	const struct pm8xxx_drvdata *pm8921_drvdata = dev_get_drvdata(dev);
 	const struct pm8921 *pmic = pm8921_drvdata->pm_chip_data;
 
-	return msm_ssbi_read(pmic->dev->parent, addr, val, 1);
+	return ssbi_read(pmic->dev->parent, addr, val, 1);
 }
 
 static int pm8921_writeb(const struct device *dev, u16 addr, u8 val)
@@ -43,7 +43,7 @@ static int pm8921_writeb(const struct device *dev, u16 addr, u8 val)
 	const struct pm8xxx_drvdata *pm8921_drvdata = dev_get_drvdata(dev);
 	const struct pm8921 *pmic = pm8921_drvdata->pm_chip_data;
 
-	return msm_ssbi_write(pmic->dev->parent, addr, &val, 1);
+	return ssbi_write(pmic->dev->parent, addr, &val, 1);
 }
 
 static int pm8921_read_buf(const struct device *dev, u16 addr, u8 *buf,
@@ -52,7 +52,7 @@ static int pm8921_read_buf(const struct device *dev, u16 addr, u8 *buf,
 	const struct pm8xxx_drvdata *pm8921_drvdata = dev_get_drvdata(dev);
 	const struct pm8921 *pmic = pm8921_drvdata->pm_chip_data;
 
-	return msm_ssbi_read(pmic->dev->parent, addr, buf, cnt);
+	return ssbi_read(pmic->dev->parent, addr, buf, cnt);
 }
 
 static int pm8921_write_buf(const struct device *dev, u16 addr, u8 *buf,
@@ -61,7 +61,7 @@ static int pm8921_write_buf(const struct device *dev, u16 addr, u8 *buf,
 	const struct pm8xxx_drvdata *pm8921_drvdata = dev_get_drvdata(dev);
 	const struct pm8921 *pmic = pm8921_drvdata->pm_chip_data;
 
-	return msm_ssbi_write(pmic->dev->parent, addr, buf, cnt);
+	return ssbi_write(pmic->dev->parent, addr, buf, cnt);
 }
 
 static int pm8921_read_irq_stat(const struct device *dev, int irq)
@@ -124,7 +124,7 @@ static int pm8921_probe(struct platform_device *pdev)
 	}
 
 	/* Read PMIC chip revision */
-	rc = msm_ssbi_read(pdev->dev.parent, REG_HWREV, &val, sizeof(val));
+	rc = ssbi_read(pdev->dev.parent, REG_HWREV, &val, sizeof(val));
 	if (rc) {
 		pr_err("Failed to read hw rev reg %d:rc=%d\n", REG_HWREV, rc);
 		goto err_read_rev;
@@ -133,7 +133,7 @@ static int pm8921_probe(struct platform_device *pdev)
 	rev = val;
 
 	/* Read PMIC chip revision 2 */
-	rc = msm_ssbi_read(pdev->dev.parent, REG_HWREV_2, &val, sizeof(val));
+	rc = ssbi_read(pdev->dev.parent, REG_HWREV_2, &val, sizeof(val));
 	if (rc) {
 		pr_err("Failed to read hw rev 2 reg %d:rc=%d\n",
 			REG_HWREV_2, rc);
diff --git a/drivers/mfd/wm5102-tables.c b/drivers/mfd/wm5102-tables.c
index a433f58..f70c495 100644
--- a/drivers/mfd/wm5102-tables.c
+++ b/drivers/mfd/wm5102-tables.c
@@ -290,12 +290,14 @@ static const struct reg_default wm5102_reg_default[] = {
 	{ 0x00000176, 0x0000 },   /* R374   - FLL1 Control 6 */ 
 	{ 0x00000177, 0x0181 },   /* R375   - FLL1 Loop Filter Test 1 */ 
 	{ 0x00000178, 0x0000 },   /* R376   - FLL1 NCO Test 0 */
+	{ 0x00000179, 0x0000 },   /* R377   - FLL1 Control 7 */
 	{ 0x00000181, 0x0000 },   /* R385   - FLL1 Synchroniser 1 */ 
 	{ 0x00000182, 0x0000 },   /* R386   - FLL1 Synchroniser 2 */ 
 	{ 0x00000183, 0x0000 },   /* R387   - FLL1 Synchroniser 3 */ 
 	{ 0x00000184, 0x0000 },   /* R388   - FLL1 Synchroniser 4 */ 
 	{ 0x00000185, 0x0000 },   /* R389   - FLL1 Synchroniser 5 */ 
 	{ 0x00000186, 0x0000 },   /* R390   - FLL1 Synchroniser 6 */ 
+	{ 0x00000187, 0x0001 },   /* R391   - FLL1 Synchroniser 7 */
 	{ 0x00000189, 0x0000 },   /* R393   - FLL1 Spread Spectrum */ 
 	{ 0x0000018A, 0x0004 },   /* R394   - FLL1 GPIO Clock */ 
 	{ 0x00000191, 0x0000 },   /* R401   - FLL2 Control 1 */ 
@@ -306,12 +308,14 @@ static const struct reg_default wm5102_reg_default[] = {
 	{ 0x00000196, 0x0000 },   /* R406   - FLL2 Control 6 */ 
 	{ 0x00000197, 0x0000 },   /* R407   - FLL2 Loop Filter Test 1 */ 
 	{ 0x00000198, 0x0000 },   /* R408   - FLL2 NCO Test 0 */
+	{ 0x00000199, 0x0000 },   /* R409   - FLL2 Control 7 */
 	{ 0x000001A1, 0x0000 },   /* R417   - FLL2 Synchroniser 1 */ 
 	{ 0x000001A2, 0x0000 },   /* R418   - FLL2 Synchroniser 2 */ 
 	{ 0x000001A3, 0x0000 },   /* R419   - FLL2 Synchroniser 3 */ 
 	{ 0x000001A4, 0x0000 },   /* R420   - FLL2 Synchroniser 4 */ 
 	{ 0x000001A5, 0x0000 },   /* R421   - FLL2 Synchroniser 5 */ 
 	{ 0x000001A6, 0x0000 },   /* R422   - FLL2 Synchroniser 6 */ 
+	{ 0x000001A7, 0x0001 },   /* R423   - FLL2 Synchroniser 7 */
 	{ 0x000001A9, 0x0000 },   /* R425   - FLL2 Spread Spectrum */ 
 	{ 0x000001AA, 0x0004 },   /* R426   - FLL2 GPIO Clock */ 
 	{ 0x00000200, 0x0006 },   /* R512   - Mic Charge Pump 1 */ 
@@ -331,6 +335,10 @@ static const struct reg_default wm5102_reg_default[] = {
 	{ 0x000002A3, 0x1102 },   /* R675   - Mic Detect 1 */ 
 	{ 0x000002A4, 0x009F },   /* R676   - Mic Detect 2 */ 
 	{ 0x000002A5, 0x0000 },   /* R677   - Mic Detect 3 */ 
+	{ 0x000002A6, 0x3737 },   /* R678   - Mic Detect Level 1 */
+	{ 0x000002A7, 0x372C },   /* R679   - Mic Detect Level 2 */
+	{ 0x000002A8, 0x1422 },   /* R680   - Mic Detect Level 3 */
+	{ 0x000002A9, 0x030A },   /* R681   - Mic Detect Level 4 */
 	{ 0x000002C3, 0x0000 },   /* R707   - Mic noise mix control 1 */ 
 	{ 0x000002CB, 0x0000 },   /* R715   - Isolation control */ 
 	{ 0x000002D3, 0x0000 },   /* R723   - Jack detect analogue */ 
@@ -1051,12 +1059,14 @@ static bool wm5102_readable_register(struct device *dev, unsigned int reg)
 	case ARIZONA_FLL1_CONTROL_6:
 	case ARIZONA_FLL1_LOOP_FILTER_TEST_1:
 	case ARIZONA_FLL1_NCO_TEST_0:
+	case ARIZONA_FLL1_CONTROL_7:
 	case ARIZONA_FLL1_SYNCHRONISER_1:
 	case ARIZONA_FLL1_SYNCHRONISER_2:
 	case ARIZONA_FLL1_SYNCHRONISER_3:
 	case ARIZONA_FLL1_SYNCHRONISER_4:
 	case ARIZONA_FLL1_SYNCHRONISER_5:
 	case ARIZONA_FLL1_SYNCHRONISER_6:
+	case ARIZONA_FLL1_SYNCHRONISER_7:
 	case ARIZONA_FLL1_SPREAD_SPECTRUM:
 	case ARIZONA_FLL1_GPIO_CLOCK:
 	case ARIZONA_FLL2_CONTROL_1:
@@ -1067,12 +1077,14 @@ static bool wm5102_readable_register(struct device *dev, unsigned int reg)
 	case ARIZONA_FLL2_CONTROL_6:
 	case ARIZONA_FLL2_LOOP_FILTER_TEST_1:
 	case ARIZONA_FLL2_NCO_TEST_0:
+	case ARIZONA_FLL2_CONTROL_7:
 	case ARIZONA_FLL2_SYNCHRONISER_1:
 	case ARIZONA_FLL2_SYNCHRONISER_2:
 	case ARIZONA_FLL2_SYNCHRONISER_3:
 	case ARIZONA_FLL2_SYNCHRONISER_4:
 	case ARIZONA_FLL2_SYNCHRONISER_5:
 	case ARIZONA_FLL2_SYNCHRONISER_6:
+	case ARIZONA_FLL2_SYNCHRONISER_7:
 	case ARIZONA_FLL2_SPREAD_SPECTRUM:
 	case ARIZONA_FLL2_GPIO_CLOCK:
 	case ARIZONA_MIC_CHARGE_PUMP_1:
@@ -1090,6 +1102,10 @@ static bool wm5102_readable_register(struct device *dev, unsigned int reg)
 	case ARIZONA_MIC_DETECT_1:
 	case ARIZONA_MIC_DETECT_2:
 	case ARIZONA_MIC_DETECT_3:
+	case ARIZONA_MIC_DETECT_LEVEL_1:
+	case ARIZONA_MIC_DETECT_LEVEL_2:
+	case ARIZONA_MIC_DETECT_LEVEL_3:
+	case ARIZONA_MIC_DETECT_LEVEL_4:
 	case ARIZONA_MIC_NOISE_MIX_CONTROL_1:
 	case ARIZONA_ISOLATION_CONTROL:
 	case ARIZONA_JACK_DETECT_ANALOGUE:
@@ -1161,6 +1177,8 @@ static bool wm5102_readable_register(struct device *dev, unsigned int reg)
 	case ARIZONA_NOISE_GATE_CONTROL:
 	case ARIZONA_PDM_SPK1_CTRL_1:
 	case ARIZONA_PDM_SPK1_CTRL_2:
+	case ARIZONA_SPK_CTRL_2:
+	case ARIZONA_SPK_CTRL_3:
 	case ARIZONA_DAC_COMP_1:
 	case ARIZONA_DAC_COMP_2:
 	case ARIZONA_DAC_COMP_3:
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index e83fdfe..b9e5654 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -93,6 +93,14 @@ config ATMEL_TCB_CLKSRC_BLOCK
 	  TC can be used for other purposes, such as PWM generation and
 	  interval timing.
 
+config DUMMY_IRQ
+	tristate "Dummy IRQ handler"
+	default n
+	---help---
+	  This module accepts a single 'irq' parameter, which it should register for.
+	  The sole purpose of this module is to help with debugging of systems on
+	  which spurious IRQs would happen on disabled IRQ vector.
+
 config IBM_ASM
 	tristate "Device driver for IBM RSA service processor"
 	depends on X86 && PCI && INPUT
@@ -418,7 +426,7 @@ config TI_DAC7512
 
 config VMWARE_BALLOON
 	tristate "VMware Balloon Driver"
-	depends on X86
+	depends on X86 && HYPERVISOR_GUEST
 	help
 	  This is VMware physical memory management driver which acts
 	  like a "balloon" that can be inflated to reclaim physical pages
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 35a1463..865cbc6 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_ATMEL_TCLIB)	+= atmel_tclib.o
 obj-$(CONFIG_BMP085)		+= bmp085.o
 obj-$(CONFIG_BMP085_I2C)	+= bmp085-i2c.o
 obj-$(CONFIG_BMP085_SPI)	+= bmp085-spi.o
+obj-$(CONFIG_DUMMY_IRQ)		+= dummy-irq.o
 obj-$(CONFIG_ICS932S401)	+= ics932s401.o
 obj-$(CONFIG_LKDTM)		+= lkdtm.o
 obj-$(CONFIG_TIFM_CORE)       	+= tifm_core.o
@@ -49,6 +50,5 @@ obj-y				+= carma/
 obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o
 obj-$(CONFIG_ALTERA_STAPL)	+=altera-stapl/
 obj-$(CONFIG_INTEL_MEI)		+= mei/
-obj-$(CONFIG_MAX8997_MUIC)	+= max8997-muic.o
 obj-$(CONFIG_VMWARE_VMCI)	+= vmw_vmci/
 obj-$(CONFIG_LATTICE_ECP3_CONFIG)	+= lattice-ecp3-config.o
diff --git a/drivers/misc/apds990x.c b/drivers/misc/apds990x.c
index 0e67f82..98f9bb2 100644
--- a/drivers/misc/apds990x.c
+++ b/drivers/misc/apds990x.c
@@ -700,9 +700,6 @@ static ssize_t apds990x_lux_calib_store(struct device *dev,
 	if (strict_strtoul(buf, 0, &value))
 		return -EINVAL;
 
-	if (chip->lux_calib > APDS_RANGE)
-		return -EINVAL;
-
 	chip->lux_calib = value;
 
 	return len;
@@ -1204,7 +1201,7 @@ static int apds990x_remove(struct i2c_client *client)
 	return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int apds990x_suspend(struct device *dev)
 {
 	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
@@ -1227,10 +1224,6 @@ static int apds990x_resume(struct device *dev)
 
 	return 0;
 }
-#else
-#define apds990x_suspend  NULL
-#define apds990x_resume	  NULL
-#define apds990x_shutdown NULL
 #endif
 
 #ifdef CONFIG_PM_RUNTIME
diff --git a/drivers/misc/arm-charlcd.c b/drivers/misc/arm-charlcd.c
index fe8616a..48651ef 100644
--- a/drivers/misc/arm-charlcd.c
+++ b/drivers/misc/arm-charlcd.c
@@ -378,18 +378,7 @@ static struct platform_driver charlcd_driver = {
 	.remove = __exit_p(charlcd_remove),
 };
 
-static int __init charlcd_init(void)
-{
-	return platform_driver_probe(&charlcd_driver, charlcd_probe);
-}
-
-static void __exit charlcd_exit(void)
-{
-	platform_driver_unregister(&charlcd_driver);
-}
-
-module_init(charlcd_init);
-module_exit(charlcd_exit);
+module_platform_driver_probe(charlcd_driver, charlcd_probe);
 
 MODULE_AUTHOR("Linus Walleij <triad@df.lth.se>");
 MODULE_DESCRIPTION("ARM Character LCD Driver");
diff --git a/drivers/misc/atmel_pwm.c b/drivers/misc/atmel_pwm.c
index 28f5aaa..494d050 100644
--- a/drivers/misc/atmel_pwm.c
+++ b/drivers/misc/atmel_pwm.c
@@ -393,17 +393,7 @@ static struct platform_driver atmel_pwm_driver = {
 	 */
 };
 
-static int __init pwm_init(void)
-{
-	return platform_driver_probe(&atmel_pwm_driver, pwm_probe);
-}
-module_init(pwm_init);
-
-static void __exit pwm_exit(void)
-{
-	platform_driver_unregister(&atmel_pwm_driver);
-}
-module_exit(pwm_exit);
+module_platform_driver_probe(atmel_pwm_driver, pwm_probe);
 
 MODULE_DESCRIPTION("Driver for AT32/AT91 PWM module");
 MODULE_LICENSE("GPL");
diff --git a/drivers/misc/bh1770glc.c b/drivers/misc/bh1770glc.c
index 2ed8fc3..f4975f7 100644
--- a/drivers/misc/bh1770glc.c
+++ b/drivers/misc/bh1770glc.c
@@ -1310,7 +1310,7 @@ static int bh1770_remove(struct i2c_client *client)
 	return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int bh1770_suspend(struct device *dev)
 {
 	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
@@ -1346,11 +1346,6 @@ static int bh1770_resume(struct device *dev)
 	}
 	return ret;
 }
-
-#else
-#define bh1770_suspend	NULL
-#define bh1770_shutdown NULL
-#define bh1770_resume	NULL
 #endif
 
 #ifdef CONFIG_PM_RUNTIME
diff --git a/drivers/misc/bh1780gli.c b/drivers/misc/bh1780gli.c
index cf03d0a..818f3a0 100644
--- a/drivers/misc/bh1780gli.c
+++ b/drivers/misc/bh1780gli.c
@@ -196,7 +196,7 @@ static int bh1780_remove(struct i2c_client *client)
 	return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int bh1780_suspend(struct device *dev)
 {
 	struct bh1780_data *ddata;
@@ -235,11 +235,9 @@ static int bh1780_resume(struct device *dev)
 
 	return 0;
 }
+#endif /* CONFIG_PM_SLEEP */
+
 static SIMPLE_DEV_PM_OPS(bh1780_pm, bh1780_suspend, bh1780_resume);
-#define BH1780_PMOPS (&bh1780_pm)
-#else
-#define BH1780_PMOPS NULL
-#endif /* CONFIG_PM */
 
 static const struct i2c_device_id bh1780_id[] = {
 	{ "bh1780", 0 },
@@ -252,7 +250,7 @@ static struct i2c_driver bh1780_driver = {
 	.id_table	= bh1780_id,
 	.driver = {
 		.name = "bh1780",
-		.pm	= BH1780_PMOPS,
+		.pm	= &bh1780_pm,
 	},
 };
 
diff --git a/drivers/misc/cs5535-mfgpt.c b/drivers/misc/cs5535-mfgpt.c
index 9858f36..effd8c6 100644
--- a/drivers/misc/cs5535-mfgpt.c
+++ b/drivers/misc/cs5535-mfgpt.c
@@ -24,8 +24,11 @@
 
 static int mfgpt_reset_timers;
 module_param_named(mfgptfix, mfgpt_reset_timers, int, 0644);
-MODULE_PARM_DESC(mfgptfix, "Reset the MFGPT timers during init; "
-		"required by some broken BIOSes (ie, TinyBIOS < 0.99).");
+MODULE_PARM_DESC(mfgptfix, "Try to reset the MFGPT timers during init; "
+		"required by some broken BIOSes (ie, TinyBIOS < 0.99) or kexec "
+		"(1 = reset the MFGPT using an undocumented bit, "
+		"2 = perform a soft reset by unconfiguring all timers); "
+		"use what works best for you.");
 
 struct cs5535_mfgpt_timer {
 	struct cs5535_mfgpt_chip *chip;
@@ -256,6 +259,28 @@ static void reset_all_timers(void)
 }
 
 /*
+ * This is another sledgehammer to reset all MFGPT timers.
+ * Instead of using the undocumented bit method it clears
+ * IRQ, NMI and RESET settings.
+ */
+static void soft_reset(void)
+{
+	int i;
+	struct cs5535_mfgpt_timer t;
+
+	for (i = 0; i < MFGPT_MAX_TIMERS; i++) {
+		t.nr = i;
+
+		cs5535_mfgpt_toggle_event(&t, MFGPT_CMP1, MFGPT_EVENT_RESET, 0);
+		cs5535_mfgpt_toggle_event(&t, MFGPT_CMP2, MFGPT_EVENT_RESET, 0);
+		cs5535_mfgpt_toggle_event(&t, MFGPT_CMP1, MFGPT_EVENT_NMI, 0);
+		cs5535_mfgpt_toggle_event(&t, MFGPT_CMP2, MFGPT_EVENT_NMI, 0);
+		cs5535_mfgpt_toggle_event(&t, MFGPT_CMP1, MFGPT_EVENT_IRQ, 0);
+		cs5535_mfgpt_toggle_event(&t, MFGPT_CMP2, MFGPT_EVENT_IRQ, 0);
+	}
+}
+
+/*
  * Check whether any MFGPTs are available for the kernel to use.  In most
  * cases, firmware that uses AMD's VSA code will claim all timers during
  * bootup; we certainly don't want to take them if they're already in use.
@@ -271,15 +296,17 @@ static int scan_timers(struct cs5535_mfgpt_chip *mfgpt)
 	int i;
 
 	/* bios workaround */
-	if (mfgpt_reset_timers)
+	if (mfgpt_reset_timers == 1)
 		reset_all_timers();
+	else if (mfgpt_reset_timers == 2)
+		soft_reset();
 
 	/* just to be safe, protect this section w/ lock */
 	spin_lock_irqsave(&mfgpt->lock, flags);
 	for (i = 0; i < MFGPT_MAX_TIMERS; i++) {
 		timer.nr = i;
 		val = cs5535_mfgpt_read(&timer, MFGPT_REG_SETUP);
-		if (!(val & MFGPT_SETUP_SETUP)) {
+		if (!(val & MFGPT_SETUP_SETUP) || mfgpt_reset_timers == 2) {
 			__set_bit(i, mfgpt->avail);
 			timers++;
 		}
@@ -294,6 +321,12 @@ static int cs5535_mfgpt_probe(struct platform_device *pdev)
 	struct resource *res;
 	int err = -EIO, t;
 
+	if (mfgpt_reset_timers < 0 || mfgpt_reset_timers > 2) {
+		dev_err(&pdev->dev, "Bad mfgpt_reset_timers value: %i\n",
+			mfgpt_reset_timers);
+		goto done;
+	}
+
 	/* There are two ways to get the MFGPT base address; one is by
 	 * fetching it from MSR_LBAR_MFGPT, the other is by reading the
 	 * PCI BAR info.  The latter method is easier (especially across
diff --git a/drivers/misc/dummy-irq.c b/drivers/misc/dummy-irq.c
new file mode 100644
index 0000000..7014167
--- /dev/null
+++ b/drivers/misc/dummy-irq.c
@@ -0,0 +1,59 @@
+/*
+ * Dummy IRQ handler driver.
+ *
+ * This module only registers itself as a handler that is specified to it
+ * by the 'irq' parameter.
+ *
+ * The sole purpose of this module is to help with debugging of systems on
+ * which spurious IRQs would happen on disabled IRQ vector.
+ *
+ * Copyright (C) 2013 Jiri Kosina
+ */
+
+/*
+ * This program is free software; you can 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/irq.h>
+#include <linux/interrupt.h>
+
+static int irq;
+
+static irqreturn_t dummy_interrupt(int irq, void *dev_id)
+{
+	static int count = 0;
+
+	if (count == 0) {
+		printk(KERN_INFO "dummy-irq: interrupt occured on IRQ %d\n",
+				irq);
+		count++;
+	}
+
+	return IRQ_NONE;
+}
+
+static int __init dummy_irq_init(void)
+{
+	if (request_irq(irq, &dummy_interrupt, IRQF_SHARED, "dummy_irq", &irq)) {
+		printk(KERN_ERR "dummy-irq: cannot register IRQ %d\n", irq);
+		return -EIO;
+	}
+	printk(KERN_INFO "dummy-irq: registered for IRQ %d\n", irq);
+	return 0;
+}
+
+static void __exit dummy_irq_exit(void)
+{
+	printk(KERN_INFO "dummy-irq unloaded\n");
+	free_irq(irq, &irq);
+}
+
+module_init(dummy_irq_init);
+module_exit(dummy_irq_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jiri Kosina");
+module_param(irq, uint, 0444);
+MODULE_PARM_DESC(irq, "The IRQ to register for");
diff --git a/drivers/misc/ep93xx_pwm.c b/drivers/misc/ep93xx_pwm.c
index 16d7179..96787ec 100644
--- a/drivers/misc/ep93xx_pwm.c
+++ b/drivers/misc/ep93xx_pwm.c
@@ -365,18 +365,7 @@ static struct platform_driver ep93xx_pwm_driver = {
 	.remove		= __exit_p(ep93xx_pwm_remove),
 };
 
-static int __init ep93xx_pwm_init(void)
-{
-	return platform_driver_probe(&ep93xx_pwm_driver, ep93xx_pwm_probe);
-}
-
-static void __exit ep93xx_pwm_exit(void)
-{
-	platform_driver_unregister(&ep93xx_pwm_driver);
-}
-
-module_init(ep93xx_pwm_init);
-module_exit(ep93xx_pwm_exit);
+module_platform_driver_probe(ep93xx_pwm_driver, ep93xx_pwm_probe);
 
 MODULE_AUTHOR("Matthieu Crapet <mcrapet@gmail.com>, "
 	      "H Hartley Sweeten <hsweeten@visionengravers.com>");
diff --git a/drivers/misc/mei/Kconfig b/drivers/misc/mei/Kconfig
index d21b4d0..c76fa31 100644
--- a/drivers/misc/mei/Kconfig
+++ b/drivers/misc/mei/Kconfig
@@ -10,10 +10,9 @@ config INTEL_MEI
 	  <http://software.intel.com/en-us/manageability/>
 
 config INTEL_MEI_ME
-	bool "ME Enabled Intel Chipsets"
-	depends on INTEL_MEI
+	tristate "ME Enabled Intel Chipsets"
+	select INTEL_MEI
 	depends on X86 && PCI && WATCHDOG_CORE
-	default y
 	help
 	  MEI support for ME Enabled Intel chipsets.
 
diff --git a/drivers/misc/mei/Makefile b/drivers/misc/mei/Makefile
index 040af6c..1b29f7c 100644
--- a/drivers/misc/mei/Makefile
+++ b/drivers/misc/mei/Makefile
@@ -10,5 +10,8 @@ mei-objs += client.o
 mei-objs += main.o
 mei-objs += amthif.o
 mei-objs += wd.o
-mei-$(CONFIG_INTEL_MEI_ME) += pci-me.o
-mei-$(CONFIG_INTEL_MEI_ME) += hw-me.o
+mei-objs += bus.o
+
+obj-$(CONFIG_INTEL_MEI_ME) += mei-me.o
+mei-me-objs := pci-me.o
+mei-me-objs += hw-me.o
diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c
index c86d7e3..9a5e8c7 100644
--- a/drivers/misc/mei/amthif.c
+++ b/drivers/misc/mei/amthif.c
@@ -449,7 +449,7 @@ int mei_amthif_irq_write_complete(struct mei_device *dev, s32 *slots,
 	struct mei_msg_hdr mei_hdr;
 	struct mei_cl *cl = cb->cl;
 	size_t len = dev->iamthif_msg_buf_size - dev->iamthif_msg_buf_index;
-	size_t msg_slots = mei_data2slots(len);
+	u32 msg_slots = mei_data2slots(len);
 
 	mei_hdr.host_addr = cl->host_client_id;
 	mei_hdr.me_addr = cl->me_client_id;
@@ -566,12 +566,13 @@ int mei_amthif_irq_read_message(struct mei_cl_cb *complete_list,
  */
 int mei_amthif_irq_read(struct mei_device *dev, s32 *slots)
 {
+	u32 msg_slots = mei_data2slots(sizeof(struct hbm_flow_control));
 
-	if (((*slots) * sizeof(u32)) < (sizeof(struct mei_msg_hdr)
-			+ sizeof(struct hbm_flow_control))) {
+	if (*slots < msg_slots)
 		return -EMSGSIZE;
-	}
-	*slots -= mei_data2slots(sizeof(struct hbm_flow_control));
+
+	*slots -= msg_slots;
+
 	if (mei_hbm_cl_flow_control_req(dev, &dev->iamthif_cl)) {
 		dev_dbg(&dev->pdev->dev, "iamthif flow control failed\n");
 		return -EIO;
diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c
new file mode 100644
index 0000000..8dbcb15
--- /dev/null
+++ b/drivers/misc/mei/bus.c
@@ -0,0 +1,496 @@
+/*
+ * Intel Management Engine Interface (Intel MEI) Linux driver
+ * Copyright (c) 2012-2013, 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.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/mei_cl_bus.h>
+
+#include "mei_dev.h"
+#include "hw-me.h"
+#include "client.h"
+
+#define to_mei_cl_driver(d) container_of(d, struct mei_cl_driver, driver)
+#define to_mei_cl_device(d) container_of(d, struct mei_cl_device, dev)
+
+static int mei_cl_device_match(struct device *dev, struct device_driver *drv)
+{
+	struct mei_cl_device *device = to_mei_cl_device(dev);
+	struct mei_cl_driver *driver = to_mei_cl_driver(drv);
+	const struct mei_cl_device_id *id;
+
+	if (!device)
+		return 0;
+
+	if (!driver || !driver->id_table)
+		return 0;
+
+	id = driver->id_table;
+
+	while (id->name[0]) {
+		if (!strcmp(dev_name(dev), id->name))
+			return 1;
+
+		id++;
+	}
+
+	return 0;
+}
+
+static int mei_cl_device_probe(struct device *dev)
+{
+	struct mei_cl_device *device = to_mei_cl_device(dev);
+	struct mei_cl_driver *driver;
+	struct mei_cl_device_id id;
+
+	if (!device)
+		return 0;
+
+	driver = to_mei_cl_driver(dev->driver);
+	if (!driver || !driver->probe)
+		return -ENODEV;
+
+	dev_dbg(dev, "Device probe\n");
+
+	strncpy(id.name, dev_name(dev), MEI_CL_NAME_SIZE);
+
+	return driver->probe(device, &id);
+}
+
+static int mei_cl_device_remove(struct device *dev)
+{
+	struct mei_cl_device *device = to_mei_cl_device(dev);
+	struct mei_cl_driver *driver;
+
+	if (!device || !dev->driver)
+		return 0;
+
+	if (device->event_cb) {
+		device->event_cb = NULL;
+		cancel_work_sync(&device->event_work);
+	}
+
+	driver = to_mei_cl_driver(dev->driver);
+	if (!driver->remove) {
+		dev->driver = NULL;
+
+		return 0;
+	}
+
+	return driver->remove(device);
+}
+
+static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
+			     char *buf)
+{
+	int len;
+
+	len = snprintf(buf, PAGE_SIZE, "mei:%s\n", dev_name(dev));
+
+	return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
+}
+
+static struct device_attribute mei_cl_dev_attrs[] = {
+	__ATTR_RO(modalias),
+	__ATTR_NULL,
+};
+
+static int mei_cl_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+	if (add_uevent_var(env, "MODALIAS=mei:%s", dev_name(dev)))
+		return -ENOMEM;
+
+	return 0;
+}
+
+static struct bus_type mei_cl_bus_type = {
+	.name		= "mei",
+	.dev_attrs	= mei_cl_dev_attrs,
+	.match		= mei_cl_device_match,
+	.probe		= mei_cl_device_probe,
+	.remove		= mei_cl_device_remove,
+	.uevent		= mei_cl_uevent,
+};
+
+static void mei_cl_dev_release(struct device *dev)
+{
+	kfree(to_mei_cl_device(dev));
+}
+
+static struct device_type mei_cl_device_type = {
+	.release	= mei_cl_dev_release,
+};
+
+static struct mei_cl *mei_bus_find_mei_cl_by_uuid(struct mei_device *dev,
+						uuid_le uuid)
+{
+	struct mei_cl *cl, *next;
+
+	list_for_each_entry_safe(cl, next, &dev->device_list, device_link) {
+		if (!uuid_le_cmp(uuid, cl->device_uuid))
+			return cl;
+	}
+
+	return NULL;
+}
+struct mei_cl_device *mei_cl_add_device(struct mei_device *dev,
+				  uuid_le uuid, char *name)
+{
+	struct mei_cl_device *device;
+	struct mei_cl *cl;
+	int status;
+
+	cl = mei_bus_find_mei_cl_by_uuid(dev, uuid);
+	if (cl == NULL)
+		return NULL;
+
+	device = kzalloc(sizeof(struct mei_cl_device), GFP_KERNEL);
+	if (!device)
+		return NULL;
+
+	device->cl = cl;
+
+	device->dev.parent = &dev->pdev->dev;
+	device->dev.bus = &mei_cl_bus_type;
+	device->dev.type = &mei_cl_device_type;
+
+	dev_set_name(&device->dev, "%s", name);
+
+	status = device_register(&device->dev);
+	if (status) {
+		dev_err(&dev->pdev->dev, "Failed to register MEI device\n");
+		kfree(device);
+		return NULL;
+	}
+
+	cl->device = device;
+
+	dev_dbg(&device->dev, "client %s registered\n", name);
+
+	return device;
+}
+EXPORT_SYMBOL_GPL(mei_cl_add_device);
+
+void mei_cl_remove_device(struct mei_cl_device *device)
+{
+	device_unregister(&device->dev);
+}
+EXPORT_SYMBOL_GPL(mei_cl_remove_device);
+
+int __mei_cl_driver_register(struct mei_cl_driver *driver, struct module *owner)
+{
+	int err;
+
+	driver->driver.name = driver->name;
+	driver->driver.owner = owner;
+	driver->driver.bus = &mei_cl_bus_type;
+
+	err = driver_register(&driver->driver);
+	if (err)
+		return err;
+
+	pr_debug("mei: driver [%s] registered\n", driver->driver.name);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(__mei_cl_driver_register);
+
+void mei_cl_driver_unregister(struct mei_cl_driver *driver)
+{
+	driver_unregister(&driver->driver);
+
+	pr_debug("mei: driver [%s] unregistered\n", driver->driver.name);
+}
+EXPORT_SYMBOL_GPL(mei_cl_driver_unregister);
+
+static int ___mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length,
+			bool blocking)
+{
+	struct mei_device *dev;
+	struct mei_msg_hdr mei_hdr;
+	struct mei_cl_cb *cb;
+	int me_cl_id, err;
+
+	if (WARN_ON(!cl || !cl->dev))
+		return -ENODEV;
+
+	if (cl->state != MEI_FILE_CONNECTED)
+		return -ENODEV;
+
+	cb = mei_io_cb_init(cl, NULL);
+	if (!cb)
+		return -ENOMEM;
+
+	err = mei_io_cb_alloc_req_buf(cb, length);
+	if (err < 0) {
+		mei_io_cb_free(cb);
+		return err;
+	}
+
+	memcpy(cb->request_buffer.data, buf, length);
+	cb->fop_type = MEI_FOP_WRITE;
+
+	dev = cl->dev;
+
+	mutex_lock(&dev->device_lock);
+
+	/* Check if we have an ME client device */
+	me_cl_id = mei_me_cl_by_id(dev, cl->me_client_id);
+	if (me_cl_id == dev->me_clients_num) {
+		err = -ENODEV;
+		goto out_err;
+	}
+
+	if (length > dev->me_clients[me_cl_id].props.max_msg_length) {
+		err = -EINVAL;
+		goto out_err;
+	}
+
+	err = mei_cl_flow_ctrl_creds(cl);
+	if (err < 0)
+		goto out_err;
+
+	/* Host buffer is not ready, we queue the request */
+	if (err == 0 || !dev->hbuf_is_ready) {
+		cb->buf_idx = 0;
+		mei_hdr.msg_complete = 0;
+		cl->writing_state = MEI_WRITING;
+
+		goto out;
+	}
+
+	dev->hbuf_is_ready = false;
+
+	/* Check for a maximum length */
+	if (length > mei_hbuf_max_len(dev)) {
+		mei_hdr.length = mei_hbuf_max_len(dev);
+		mei_hdr.msg_complete = 0;
+	} else {
+		mei_hdr.length = length;
+		mei_hdr.msg_complete = 1;
+	}
+
+	mei_hdr.host_addr = cl->host_client_id;
+	mei_hdr.me_addr = cl->me_client_id;
+	mei_hdr.reserved = 0;
+
+	if (mei_write_message(dev, &mei_hdr, buf)) {
+		err = -EIO;
+		goto out_err;
+	}
+
+	cl->writing_state = MEI_WRITING;
+	cb->buf_idx = mei_hdr.length;
+
+out:
+	if (mei_hdr.msg_complete) {
+		if (mei_cl_flow_ctrl_reduce(cl)) {
+			err = -ENODEV;
+			goto out_err;
+		}
+		list_add_tail(&cb->list, &dev->write_waiting_list.list);
+	} else {
+		list_add_tail(&cb->list, &dev->write_list.list);
+	}
+
+	mutex_unlock(&dev->device_lock);
+
+	if (blocking && cl->writing_state != MEI_WRITE_COMPLETE) {
+		if (wait_event_interruptible(cl->tx_wait,
+			cl->writing_state == MEI_WRITE_COMPLETE)) {
+				if (signal_pending(current))
+					err = -EINTR;
+			err = -ERESTARTSYS;
+			mutex_lock(&dev->device_lock);
+			goto out_err;
+		}
+	}
+
+	return mei_hdr.length;
+
+out_err:
+	mutex_unlock(&dev->device_lock);
+	mei_io_cb_free(cb);
+
+	return err;
+}
+
+int __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length)
+{
+	struct mei_device *dev;
+	struct mei_cl_cb *cb;
+	size_t r_length;
+	int err;
+
+	if (WARN_ON(!cl || !cl->dev))
+		return -ENODEV;
+
+	dev = cl->dev;
+
+	mutex_lock(&dev->device_lock);
+
+	if (!cl->read_cb) {
+		err = mei_cl_read_start(cl);
+		if (err < 0) {
+			mutex_unlock(&dev->device_lock);
+			return err;
+		}
+	}
+
+	if (cl->reading_state != MEI_READ_COMPLETE &&
+	    !waitqueue_active(&cl->rx_wait)) {
+		mutex_unlock(&dev->device_lock);
+
+		if (wait_event_interruptible(cl->rx_wait,
+				(MEI_READ_COMPLETE == cl->reading_state))) {
+			if (signal_pending(current))
+				return -EINTR;
+			return -ERESTARTSYS;
+		}
+
+		mutex_lock(&dev->device_lock);
+	}
+
+	cb = cl->read_cb;
+
+	if (cl->reading_state != MEI_READ_COMPLETE) {
+		r_length = 0;
+		goto out;
+	}
+
+	r_length = min_t(size_t, length, cb->buf_idx);
+
+	memcpy(buf, cb->response_buffer.data, r_length);
+
+	mei_io_cb_free(cb);
+	cl->reading_state = MEI_IDLE;
+	cl->read_cb = NULL;
+
+out:
+	mutex_unlock(&dev->device_lock);
+
+	return r_length;
+}
+
+inline int __mei_cl_async_send(struct mei_cl *cl, u8 *buf, size_t length)
+{
+	return ___mei_cl_send(cl, buf, length, 0);
+}
+
+inline int __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length)
+{
+	return ___mei_cl_send(cl, buf, length, 1);
+}
+
+int mei_cl_send(struct mei_cl_device *device, u8 *buf, size_t length)
+{
+	struct mei_cl *cl = device->cl;
+
+	if (cl == NULL)
+		return -ENODEV;
+
+	if (device->ops && device->ops->send)
+		return device->ops->send(device, buf, length);
+
+	return __mei_cl_send(cl, buf, length);
+}
+EXPORT_SYMBOL_GPL(mei_cl_send);
+
+int mei_cl_recv(struct mei_cl_device *device, u8 *buf, size_t length)
+{
+	struct mei_cl *cl =  device->cl;
+
+	if (cl == NULL)
+		return -ENODEV;
+
+	if (device->ops && device->ops->recv)
+		return device->ops->recv(device, buf, length);
+
+	return __mei_cl_recv(cl, buf, length);
+}
+EXPORT_SYMBOL_GPL(mei_cl_recv);
+
+static void mei_bus_event_work(struct work_struct *work)
+{
+	struct mei_cl_device *device;
+
+	device = container_of(work, struct mei_cl_device, event_work);
+
+	if (device->event_cb)
+		device->event_cb(device, device->events, device->event_context);
+
+	device->events = 0;
+
+	/* Prepare for the next read */
+	mei_cl_read_start(device->cl);
+}
+
+int mei_cl_register_event_cb(struct mei_cl_device *device,
+			  mei_cl_event_cb_t event_cb, void *context)
+{
+	if (device->event_cb)
+		return -EALREADY;
+
+	device->events = 0;
+	device->event_cb = event_cb;
+	device->event_context = context;
+	INIT_WORK(&device->event_work, mei_bus_event_work);
+
+	mei_cl_read_start(device->cl);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(mei_cl_register_event_cb);
+
+void *mei_cl_get_drvdata(const struct mei_cl_device *device)
+{
+	return dev_get_drvdata(&device->dev);
+}
+EXPORT_SYMBOL_GPL(mei_cl_get_drvdata);
+
+void mei_cl_set_drvdata(struct mei_cl_device *device, void *data)
+{
+	dev_set_drvdata(&device->dev, data);
+}
+EXPORT_SYMBOL_GPL(mei_cl_set_drvdata);
+
+void mei_cl_bus_rx_event(struct mei_cl *cl)
+{
+	struct mei_cl_device *device = cl->device;
+
+	if (!device || !device->event_cb)
+		return;
+
+	set_bit(MEI_CL_EVENT_RX, &device->events);
+
+	schedule_work(&device->event_work);
+}
+
+int __init mei_cl_bus_init(void)
+{
+	return bus_register(&mei_cl_bus_type);
+}
+
+void __exit mei_cl_bus_exit(void)
+{
+	bus_unregister(&mei_cl_bus_type);
+}
diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index 1569afe..e14397b 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -216,6 +216,7 @@ void mei_cl_init(struct mei_cl *cl, struct mei_device *dev)
 	init_waitqueue_head(&cl->rx_wait);
 	init_waitqueue_head(&cl->tx_wait);
 	INIT_LIST_HEAD(&cl->link);
+	INIT_LIST_HEAD(&cl->device_link);
 	cl->reading_state = MEI_IDLE;
 	cl->writing_state = MEI_IDLE;
 	cl->dev = dev;
diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c
index 642c622..5ad53eb 100644
--- a/drivers/misc/mei/hw-me.c
+++ b/drivers/misc/mei/hw-me.c
@@ -26,14 +26,14 @@
 
 
 /**
- * mei_reg_read - Reads 32bit data from the mei device
+ * mei_me_reg_read - Reads 32bit data from the mei device
  *
  * @dev: the device structure
  * @offset: offset from which to read the data
  *
  * returns register value (u32)
  */
-static inline u32 mei_reg_read(const struct mei_me_hw *hw,
+static inline u32 mei_me_reg_read(const struct mei_me_hw *hw,
 			       unsigned long offset)
 {
 	return ioread32(hw->mem_addr + offset);
@@ -41,20 +41,20 @@ static inline u32 mei_reg_read(const struct mei_me_hw *hw,
 
 
 /**
- * mei_reg_write - Writes 32bit data to the mei device
+ * mei_me_reg_write - Writes 32bit data to the mei device
  *
  * @dev: the device structure
  * @offset: offset from which to write the data
  * @value: register value to write (u32)
  */
-static inline void mei_reg_write(const struct mei_me_hw *hw,
+static inline void mei_me_reg_write(const struct mei_me_hw *hw,
 				 unsigned long offset, u32 value)
 {
 	iowrite32(value, hw->mem_addr + offset);
 }
 
 /**
- * mei_mecbrw_read - Reads 32bit data from ME circular buffer
+ * mei_me_mecbrw_read - Reads 32bit data from ME circular buffer
  *  read window register
  *
  * @dev: the device structure
@@ -63,18 +63,18 @@ static inline void mei_reg_write(const struct mei_me_hw *hw,
  */
 static u32 mei_me_mecbrw_read(const struct mei_device *dev)
 {
-	return mei_reg_read(to_me_hw(dev), ME_CB_RW);
+	return mei_me_reg_read(to_me_hw(dev), ME_CB_RW);
 }
 /**
- * mei_mecsr_read - Reads 32bit data from the ME CSR
+ * mei_me_mecsr_read - Reads 32bit data from the ME CSR
  *
  * @dev: the device structure
  *
  * returns ME_CSR_HA register value (u32)
  */
-static inline u32 mei_mecsr_read(const struct mei_me_hw *hw)
+static inline u32 mei_me_mecsr_read(const struct mei_me_hw *hw)
 {
-	return mei_reg_read(hw, ME_CSR_HA);
+	return mei_me_reg_read(hw, ME_CSR_HA);
 }
 
 /**
@@ -86,7 +86,7 @@ static inline u32 mei_mecsr_read(const struct mei_me_hw *hw)
  */
 static inline u32 mei_hcsr_read(const struct mei_me_hw *hw)
 {
-	return mei_reg_read(hw, H_CSR);
+	return mei_me_reg_read(hw, H_CSR);
 }
 
 /**
@@ -98,7 +98,7 @@ static inline u32 mei_hcsr_read(const struct mei_me_hw *hw)
 static inline void mei_hcsr_set(struct mei_me_hw *hw, u32 hcsr)
 {
 	hcsr &= ~H_IS;
-	mei_reg_write(hw, H_CSR, hcsr);
+	mei_me_reg_write(hw, H_CSR, hcsr);
 }
 
 
@@ -123,7 +123,7 @@ static void mei_me_intr_clear(struct mei_device *dev)
 	struct mei_me_hw *hw = to_me_hw(dev);
 	u32 hcsr = mei_hcsr_read(hw);
 	if ((hcsr & H_IS) == H_IS)
-		mei_reg_write(hw, H_CSR, hcsr);
+		mei_me_reg_write(hw, H_CSR, hcsr);
 }
 /**
  * mei_me_intr_enable - enables mei device interrupts
@@ -228,10 +228,42 @@ static bool mei_me_host_is_ready(struct mei_device *dev)
 static bool mei_me_hw_is_ready(struct mei_device *dev)
 {
 	struct mei_me_hw *hw = to_me_hw(dev);
-	hw->me_hw_state = mei_mecsr_read(hw);
+	hw->me_hw_state = mei_me_mecsr_read(hw);
 	return (hw->me_hw_state & ME_RDY_HRA) == ME_RDY_HRA;
 }
 
+static int mei_me_hw_ready_wait(struct mei_device *dev)
+{
+	int err;
+	if (mei_me_hw_is_ready(dev))
+		return 0;
+
+	mutex_unlock(&dev->device_lock);
+	err = wait_event_interruptible_timeout(dev->wait_hw_ready,
+			dev->recvd_hw_ready, MEI_INTEROP_TIMEOUT);
+	mutex_lock(&dev->device_lock);
+	if (!err && !dev->recvd_hw_ready) {
+		dev_err(&dev->pdev->dev,
+			"wait hw ready failed. status = 0x%x\n", err);
+		return -ETIMEDOUT;
+	}
+
+	dev->recvd_hw_ready = false;
+	return 0;
+}
+
+static int mei_me_hw_start(struct mei_device *dev)
+{
+	int ret = mei_me_hw_ready_wait(dev);
+	if (ret)
+		return ret;
+	dev_dbg(&dev->pdev->dev, "hw is ready\n");
+
+	mei_me_host_set_ready(dev);
+	return ret;
+}
+
+
 /**
  * mei_hbuf_filled_slots - gets number of device filled buffer slots
  *
@@ -305,10 +337,11 @@ static int mei_me_write_message(struct mei_device *dev,
 			unsigned char *buf)
 {
 	struct mei_me_hw *hw = to_me_hw(dev);
-	unsigned long rem, dw_cnt;
+	unsigned long rem;
 	unsigned long length = header->length;
 	u32 *reg_buf = (u32 *)buf;
 	u32 hcsr;
+	u32 dw_cnt;
 	int i;
 	int empty_slots;
 
@@ -321,16 +354,16 @@ static int mei_me_write_message(struct mei_device *dev,
 	if (empty_slots < 0 || dw_cnt > empty_slots)
 		return -EIO;
 
-	mei_reg_write(hw, H_CB_WW, *((u32 *) header));
+	mei_me_reg_write(hw, H_CB_WW, *((u32 *) header));
 
 	for (i = 0; i < length / 4; i++)
-		mei_reg_write(hw, H_CB_WW, reg_buf[i]);
+		mei_me_reg_write(hw, H_CB_WW, reg_buf[i]);
 
 	rem = length & 0x3;
 	if (rem > 0) {
 		u32 reg = 0;
 		memcpy(&reg, &buf[length - rem], rem);
-		mei_reg_write(hw, H_CB_WW, reg);
+		mei_me_reg_write(hw, H_CB_WW, reg);
 	}
 
 	hcsr = mei_hcsr_read(hw) | H_IG;
@@ -354,7 +387,7 @@ static int mei_me_count_full_read_slots(struct mei_device *dev)
 	char read_ptr, write_ptr;
 	unsigned char buffer_depth, filled_slots;
 
-	hw->me_hw_state = mei_mecsr_read(hw);
+	hw->me_hw_state = mei_me_mecsr_read(hw);
 	buffer_depth = (unsigned char)((hw->me_hw_state & ME_CBD_HRA) >> 24);
 	read_ptr = (char) ((hw->me_hw_state & ME_CBRP_HRA) >> 8);
 	write_ptr = (char) ((hw->me_hw_state & ME_CBWP_HRA) >> 16);
@@ -414,7 +447,7 @@ irqreturn_t mei_me_irq_quick_handler(int irq, void *dev_id)
 		return IRQ_NONE;
 
 	/* clear H_IS bit in H_CSR */
-	mei_reg_write(hw, H_CSR, csr_reg);
+	mei_me_reg_write(hw, H_CSR, csr_reg);
 
 	return IRQ_WAKE_THREAD;
 }
@@ -433,8 +466,6 @@ irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id)
 {
 	struct mei_device *dev = (struct mei_device *) dev_id;
 	struct mei_cl_cb complete_list;
-	struct mei_cl_cb *cb_pos = NULL, *cb_next = NULL;
-	struct mei_cl *cl;
 	s32 slots;
 	int rets;
 	bool  bus_message_received;
@@ -465,14 +496,9 @@ irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id)
 		if (mei_hw_is_ready(dev)) {
 			dev_dbg(&dev->pdev->dev, "we need to start the dev.\n");
 
-			mei_host_set_ready(dev);
-
-			dev_dbg(&dev->pdev->dev, "link is established start sending messages.\n");
-			/* link is established * start sending messages.  */
-
-			dev->dev_state = MEI_DEV_INIT_CLIENTS;
+			dev->recvd_hw_ready = true;
+			wake_up_interruptible(&dev->wait_hw_ready);
 
-			mei_hbm_start_req(dev);
 			mutex_unlock(&dev->device_lock);
 			return IRQ_HANDLED;
 		} else {
@@ -510,33 +536,19 @@ end:
 		wake_up_interruptible(&dev->wait_recvd_msg);
 		bus_message_received = false;
 	}
-	if (list_empty(&complete_list.list))
-		return IRQ_HANDLED;
 
+	mei_irq_compl_handler(dev, &complete_list);
 
-	list_for_each_entry_safe(cb_pos, cb_next, &complete_list.list, list) {
-		cl = cb_pos->cl;
-		list_del(&cb_pos->list);
-		if (cl) {
-			if (cl != &dev->iamthif_cl) {
-				dev_dbg(&dev->pdev->dev, "completing call back.\n");
-				mei_irq_complete_handler(cl, cb_pos);
-				cb_pos = NULL;
-			} else if (cl == &dev->iamthif_cl) {
-				mei_amthif_complete(dev, cb_pos);
-			}
-		}
-	}
 	return IRQ_HANDLED;
 }
 static const struct mei_hw_ops mei_me_hw_ops = {
 
-	.host_set_ready = mei_me_host_set_ready,
 	.host_is_ready = mei_me_host_is_ready,
 
 	.hw_is_ready = mei_me_hw_is_ready,
 	.hw_reset = mei_me_hw_reset,
-	.hw_config  = mei_me_hw_config,
+	.hw_config = mei_me_hw_config,
+	.hw_start = mei_me_hw_start,
 
 	.intr_clear = mei_me_intr_clear,
 	.intr_enable = mei_me_intr_enable,
@@ -571,14 +583,6 @@ struct mei_device *mei_me_dev_init(struct pci_dev *pdev)
 
 	mei_device_init(dev);
 
-	INIT_LIST_HEAD(&dev->wd_cl.link);
-	INIT_LIST_HEAD(&dev->iamthif_cl.link);
-	mei_io_list_init(&dev->amthif_cmd_list);
-	mei_io_list_init(&dev->amthif_rd_complete_list);
-
-	INIT_DELAYED_WORK(&dev->timer_work, mei_timer);
-	INIT_WORK(&dev->init_work, mei_host_client_init);
-
 	dev->ops = &mei_me_hw_ops;
 
 	dev->pdev = pdev;
diff --git a/drivers/misc/mei/hw-me.h b/drivers/misc/mei/hw-me.h
index 8518d3e..80bd829 100644
--- a/drivers/misc/mei/hw-me.h
+++ b/drivers/misc/mei/hw-me.h
@@ -36,12 +36,6 @@ struct mei_me_hw {
 
 struct mei_device *mei_me_dev_init(struct pci_dev *pdev);
 
-/* get slots (dwords) from a message length + header (bytes) */
-static inline unsigned char mei_data2slots(size_t length)
-{
-	return DIV_ROUND_UP(sizeof(struct mei_msg_hdr) + length, 4);
-}
-
 irqreturn_t mei_me_irq_quick_handler(int irq, void *dev_id);
 irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id);
 
diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c
index 3561799..54b51c0 100644
--- a/drivers/misc/mei/init.c
+++ b/drivers/misc/mei/init.c
@@ -14,6 +14,7 @@
  *
  */
 
+#include <linux/export.h>
 #include <linux/pci.h>
 #include <linux/sched.h>
 #include <linux/wait.h>
@@ -22,6 +23,7 @@
 #include <linux/mei.h>
 
 #include "mei_dev.h"
+#include "hbm.h"
 #include "client.h"
 
 const char *mei_dev_state_str(int state)
@@ -33,7 +35,6 @@ const char *mei_dev_state_str(int state)
 	MEI_DEV_STATE(ENABLED);
 	MEI_DEV_STATE(RESETING);
 	MEI_DEV_STATE(DISABLED);
-	MEI_DEV_STATE(RECOVERING_FROM_RESET);
 	MEI_DEV_STATE(POWER_DOWN);
 	MEI_DEV_STATE(POWER_UP);
 	default:
@@ -46,7 +47,9 @@ void mei_device_init(struct mei_device *dev)
 {
 	/* setup our list array */
 	INIT_LIST_HEAD(&dev->file_list);
+	INIT_LIST_HEAD(&dev->device_list);
 	mutex_init(&dev->device_lock);
+	init_waitqueue_head(&dev->wait_hw_ready);
 	init_waitqueue_head(&dev->wait_recvd_msg);
 	init_waitqueue_head(&dev->wait_stop_wd);
 	dev->dev_state = MEI_DEV_INITIALIZING;
@@ -56,16 +59,26 @@ void mei_device_init(struct mei_device *dev)
 	mei_io_list_init(&dev->write_waiting_list);
 	mei_io_list_init(&dev->ctrl_wr_list);
 	mei_io_list_init(&dev->ctrl_rd_list);
+
+	INIT_DELAYED_WORK(&dev->timer_work, mei_timer);
+	INIT_WORK(&dev->init_work, mei_host_client_init);
+
+	INIT_LIST_HEAD(&dev->wd_cl.link);
+	INIT_LIST_HEAD(&dev->iamthif_cl.link);
+	mei_io_list_init(&dev->amthif_cmd_list);
+	mei_io_list_init(&dev->amthif_rd_complete_list);
+
 }
+EXPORT_SYMBOL_GPL(mei_device_init);
 
 /**
- * mei_hw_init - initializes host and fw to start work.
+ * mei_start - initializes host and fw to start work.
  *
  * @dev: the device structure
  *
  * returns 0 on success, <0 on failure.
  */
-int mei_hw_init(struct mei_device *dev)
+int mei_start(struct mei_device *dev)
 {
 	int ret = 0;
 
@@ -126,6 +139,7 @@ err:
 	mutex_unlock(&dev->device_lock);
 	return -ENODEV;
 }
+EXPORT_SYMBOL_GPL(mei_start);
 
 /**
  * mei_reset - resets host and fw.
@@ -137,9 +151,6 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled)
 {
 	bool unexpected;
 
-	if (dev->dev_state == MEI_DEV_RECOVERING_FROM_RESET)
-		return;
-
 	unexpected = (dev->dev_state != MEI_DEV_INITIALIZING &&
 			dev->dev_state != MEI_DEV_DISABLED &&
 			dev->dev_state != MEI_DEV_POWER_DOWN &&
@@ -176,12 +187,27 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled)
 		dev_warn(&dev->pdev->dev, "unexpected reset: dev_state = %s\n",
 			 mei_dev_state_str(dev->dev_state));
 
+	if (!interrupts_enabled) {
+		dev_dbg(&dev->pdev->dev, "intr not enabled end of reset\n");
+		return;
+	}
+
+	mei_hw_start(dev);
+
+	dev_dbg(&dev->pdev->dev, "link is established start sending messages.\n");
+	/* link is established * start sending messages.  */
+
+	dev->dev_state = MEI_DEV_INIT_CLIENTS;
+
+	mei_hbm_start_req(dev);
+
 	/* wake up all readings so they can be interrupted */
 	mei_cl_all_read_wakeup(dev);
 
 	/* remove all waiting requests */
 	mei_cl_all_write_clear(dev);
 }
+EXPORT_SYMBOL_GPL(mei_reset);
 
 void mei_stop(struct mei_device *dev)
 {
@@ -199,8 +225,10 @@ void mei_stop(struct mei_device *dev)
 	mutex_unlock(&dev->device_lock);
 
 	flush_scheduled_work();
-}
 
+	mei_watchdog_unregister(dev);
+}
+EXPORT_SYMBOL_GPL(mei_stop);
 
 
 
diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c
index 3535b26..255e085 100644
--- a/drivers/misc/mei/interrupt.c
+++ b/drivers/misc/mei/interrupt.c
@@ -15,6 +15,7 @@
  */
 
 
+#include <linux/export.h>
 #include <linux/pci.h>
 #include <linux/kthread.h>
 #include <linux/interrupt.h>
@@ -30,30 +31,58 @@
 
 
 /**
- * mei_complete_handler - processes completed operation.
+ * mei_cl_complete_handler - processes completed operation for a client
  *
  * @cl: private data of the file object.
- * @cb_pos: callback block.
+ * @cb: callback block.
  */
-void mei_irq_complete_handler(struct mei_cl *cl, struct mei_cl_cb *cb_pos)
+static void mei_cl_complete_handler(struct mei_cl *cl, struct mei_cl_cb *cb)
 {
-	if (cb_pos->fop_type == MEI_FOP_WRITE) {
-		mei_io_cb_free(cb_pos);
-		cb_pos = NULL;
+	if (cb->fop_type == MEI_FOP_WRITE) {
+		mei_io_cb_free(cb);
+		cb = NULL;
 		cl->writing_state = MEI_WRITE_COMPLETE;
 		if (waitqueue_active(&cl->tx_wait))
 			wake_up_interruptible(&cl->tx_wait);
 
-	} else if (cb_pos->fop_type == MEI_FOP_READ &&
+	} else if (cb->fop_type == MEI_FOP_READ &&
 			MEI_READING == cl->reading_state) {
 		cl->reading_state = MEI_READ_COMPLETE;
 		if (waitqueue_active(&cl->rx_wait))
 			wake_up_interruptible(&cl->rx_wait);
+		else
+			mei_cl_bus_rx_event(cl);
 
 	}
 }
 
 /**
+ * mei_irq_compl_handler - dispatch complete handelers
+ *	for the completed callbacks
+ *
+ * @dev - mei device
+ * @compl_list - list of completed cbs
+ */
+void mei_irq_compl_handler(struct mei_device *dev, struct mei_cl_cb *compl_list)
+{
+	struct mei_cl_cb *cb, *next;
+	struct mei_cl *cl;
+
+	list_for_each_entry_safe(cb, next, &compl_list->list, list) {
+		cl = cb->cl;
+		list_del(&cb->list);
+		if (!cl)
+			continue;
+
+		dev_dbg(&dev->pdev->dev, "completing call back.\n");
+		if (cl == &dev->iamthif_cl)
+			mei_amthif_complete(dev, cb);
+		else
+			mei_cl_complete_handler(cl, cb);
+	}
+}
+EXPORT_SYMBOL_GPL(mei_irq_compl_handler);
+/**
  * _mei_irq_thread_state_ok - checks if mei header matches file private data
  *
  * @cl: private data of the file object
@@ -153,25 +182,27 @@ static int _mei_irq_thread_close(struct mei_device *dev, s32 *slots,
 				struct mei_cl *cl,
 				struct mei_cl_cb *cmpl_list)
 {
-	if ((*slots * sizeof(u32)) < (sizeof(struct mei_msg_hdr) +
-			sizeof(struct hbm_client_connect_request)))
-		return -EBADMSG;
+	u32 msg_slots =
+		mei_data2slots(sizeof(struct hbm_client_connect_request));
+
+	if (*slots < msg_slots)
+		return -EMSGSIZE;
 
-	*slots -= mei_data2slots(sizeof(struct hbm_client_connect_request));
+	*slots -= msg_slots;
 
 	if (mei_hbm_cl_disconnect_req(dev, cl)) {
 		cl->status = 0;
 		cb_pos->buf_idx = 0;
 		list_move_tail(&cb_pos->list, &cmpl_list->list);
-		return -EMSGSIZE;
-	} else {
-		cl->state = MEI_FILE_DISCONNECTING;
-		cl->status = 0;
-		cb_pos->buf_idx = 0;
-		list_move_tail(&cb_pos->list, &dev->ctrl_rd_list.list);
-		cl->timer_count = MEI_CONNECT_TIMEOUT;
+		return -EIO;
 	}
 
+	cl->state = MEI_FILE_DISCONNECTING;
+	cl->status = 0;
+	cb_pos->buf_idx = 0;
+	list_move_tail(&cb_pos->list, &dev->ctrl_rd_list.list);
+	cl->timer_count = MEI_CONNECT_TIMEOUT;
+
 	return 0;
 }
 
@@ -192,14 +223,15 @@ static int _mei_irq_thread_read(struct mei_device *dev,	s32 *slots,
 			struct mei_cl *cl,
 			struct mei_cl_cb *cmpl_list)
 {
-	if ((*slots * sizeof(u32)) < (sizeof(struct mei_msg_hdr) +
-			sizeof(struct hbm_flow_control))) {
+	u32 msg_slots = mei_data2slots(sizeof(struct hbm_flow_control));
+
+	if (*slots < msg_slots) {
 		/* return the cancel routine */
 		list_del(&cb_pos->list);
-		return -EBADMSG;
+		return -EMSGSIZE;
 	}
 
-	*slots -= mei_data2slots(sizeof(struct hbm_flow_control));
+	*slots -= msg_slots;
 
 	if (mei_hbm_cl_flow_control_req(dev, cl)) {
 		cl->status = -ENODEV;
@@ -229,15 +261,19 @@ static int _mei_irq_thread_ioctl(struct mei_device *dev, s32 *slots,
 			struct mei_cl *cl,
 			struct mei_cl_cb *cmpl_list)
 {
-	if ((*slots * sizeof(u32)) < (sizeof(struct mei_msg_hdr) +
-			sizeof(struct hbm_client_connect_request))) {
+	u32 msg_slots =
+		mei_data2slots(sizeof(struct hbm_client_connect_request));
+
+	if (*slots < msg_slots) {
 		/* return the cancel routine */
 		list_del(&cb_pos->list);
-		return -EBADMSG;
+		return -EMSGSIZE;
 	}
 
+	*slots -=  msg_slots;
+
 	cl->state = MEI_FILE_CONNECTING;
-	*slots -= mei_data2slots(sizeof(struct hbm_client_connect_request));
+
 	if (mei_hbm_cl_connect_req(dev, cl)) {
 		cl->status = -ENODEV;
 		cb_pos->buf_idx = 0;
@@ -266,7 +302,7 @@ static int mei_irq_thread_write_complete(struct mei_device *dev, s32 *slots,
 	struct mei_msg_hdr mei_hdr;
 	struct mei_cl *cl = cb->cl;
 	size_t len = cb->request_buffer.size - cb->buf_idx;
-	size_t msg_slots = mei_data2slots(len);
+	u32 msg_slots = mei_data2slots(len);
 
 	mei_hdr.host_addr = cl->host_client_id;
 	mei_hdr.me_addr = cl->me_client_id;
@@ -408,6 +444,7 @@ int mei_irq_read_handler(struct mei_device *dev,
 end:
 	return ret;
 }
+EXPORT_SYMBOL_GPL(mei_irq_read_handler);
 
 
 /**
@@ -419,8 +456,7 @@ end:
  *
  * returns 0 on success, <0 on failure.
  */
-int mei_irq_write_handler(struct mei_device *dev,
-				struct mei_cl_cb *cmpl_list)
+int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list)
 {
 
 	struct mei_cl *cl;
@@ -559,6 +595,7 @@ int mei_irq_write_handler(struct mei_device *dev,
 	}
 	return 0;
 }
+EXPORT_SYMBOL_GPL(mei_irq_write_handler);
 
 
 
diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c
index 903f809..872de9d 100644
--- a/drivers/misc/mei/main.c
+++ b/drivers/misc/mei/main.c
@@ -758,12 +758,29 @@ int mei_register(struct device *dev)
 	mei_misc_device.parent = dev;
 	return misc_register(&mei_misc_device);
 }
+EXPORT_SYMBOL_GPL(mei_register);
 
 void mei_deregister(void)
 {
 	misc_deregister(&mei_misc_device);
 	mei_misc_device.parent = NULL;
 }
+EXPORT_SYMBOL_GPL(mei_deregister);
 
+static int __init mei_init(void)
+{
+	return mei_cl_bus_init();
+}
+
+static void __exit mei_exit(void)
+{
+	mei_cl_bus_exit();
+}
+
+module_init(mei_init);
+module_exit(mei_exit);
+
+MODULE_AUTHOR("Intel Corporation");
+MODULE_DESCRIPTION("Intel(R) Management Engine Interface");
 MODULE_LICENSE("GPL v2");
 
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index 9787381..325f71a 100644
--- a/drivers/misc/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -21,6 +21,7 @@
 #include <linux/watchdog.h>
 #include <linux/poll.h>
 #include <linux/mei.h>
+#include <linux/mei_cl_bus.h>
 
 #include "hw.h"
 #include "hw-me-regs.h"
@@ -97,7 +98,6 @@ enum mei_dev_state {
 	MEI_DEV_ENABLED,
 	MEI_DEV_RESETING,
 	MEI_DEV_DISABLED,
-	MEI_DEV_RECOVERING_FROM_RESET,
 	MEI_DEV_POWER_DOWN,
 	MEI_DEV_POWER_UP
 };
@@ -209,15 +209,20 @@ struct mei_cl {
 	enum mei_file_transaction_states writing_state;
 	int sm_state;
 	struct mei_cl_cb *read_cb;
+
+	/* MEI CL bus data */
+	struct mei_cl_device *device;
+	struct list_head device_link;
+	uuid_le device_uuid;
 };
 
 /** struct mei_hw_ops
  *
- * @host_set_ready   - notify FW that host side is ready
  * @host_is_ready    - query for host readiness
 
  * @hw_is_ready      - query if hw is ready
  * @hw_reset         - reset hw
+ * @hw_start         - start hw after reset
  * @hw_config        - configure hw
 
  * @intr_clear       - clear pending interrupts
@@ -237,11 +242,11 @@ struct mei_cl {
  */
 struct mei_hw_ops {
 
-	void (*host_set_ready) (struct mei_device *dev);
 	bool (*host_is_ready) (struct mei_device *dev);
 
 	bool (*hw_is_ready) (struct mei_device *dev);
 	void (*hw_reset) (struct mei_device *dev, bool enable);
+	int  (*hw_start) (struct mei_device *dev);
 	void (*hw_config) (struct mei_device *dev);
 
 	void (*intr_clear) (struct mei_device *dev);
@@ -263,6 +268,67 @@ struct mei_hw_ops {
 		     unsigned char *buf, unsigned long len);
 };
 
+/* MEI bus API*/
+struct mei_cl_device *mei_cl_add_device(struct mei_device *dev,
+				  uuid_le uuid, char *name);
+void mei_cl_remove_device(struct mei_cl_device *device);
+
+int __mei_cl_async_send(struct mei_cl *cl, u8 *buf, size_t length);
+int __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length);
+int __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length);
+
+/**
+ * struct mei_cl_transport_ops - MEI CL device transport ops
+ * This structure allows ME host clients to implement technology
+ * specific transport layers.
+ *
+ * @send: Tx hook for the device. This allows ME host clients to trap
+ *	the device driver buffers before actually physically
+ *	pushing it to the ME.
+ * @recv: Rx hook for the device. This allows ME host clients to trap the
+ *	ME buffers before forwarding them to the device driver.
+ */
+struct mei_cl_transport_ops {
+	int (*send)(struct mei_cl_device *device, u8 *buf, size_t length);
+	int (*recv)(struct mei_cl_device *device, u8 *buf, size_t length);
+};
+
+void mei_cl_bus_rx_event(struct mei_cl *cl);
+int mei_cl_bus_init(void);
+void mei_cl_bus_exit(void);
+
+
+/**
+ * struct mei_cl_device - MEI device handle
+ * An mei_cl_device pointer is returned from mei_add_device()
+ * and links MEI bus clients to their actual ME host client pointer.
+ * Drivers for MEI devices will get an mei_cl_device pointer
+ * when being probed and shall use it for doing ME bus I/O.
+ *
+ * @dev: linux driver model device pointer
+ * @uuid: me client uuid
+ * @cl: mei client
+ * @ops: ME transport ops
+ * @event_cb: Drivers register this callback to get asynchronous ME
+ *	events (e.g. Rx buffer pending) notifications.
+ * @events: Events bitmask sent to the driver.
+ * @priv_data: client private data
+ */
+struct mei_cl_device {
+	struct device dev;
+
+	struct mei_cl *cl;
+
+	const struct mei_cl_transport_ops *ops;
+
+	struct work_struct event_work;
+	mei_cl_event_cb_t event_cb;
+	void *event_context;
+	unsigned long events;
+
+	void *priv_data;
+};
+
 /**
  * struct mei_device -  MEI private device struct
 
@@ -296,11 +362,14 @@ struct mei_device {
 	 */
 	struct mutex device_lock; /* device lock */
 	struct delayed_work timer_work;	/* MEI timer delayed work (timeouts) */
+
+	bool recvd_hw_ready;
 	bool recvd_msg;
 
 	/*
 	 * waiting queue for receive message from FW
 	 */
+	wait_queue_head_t wait_hw_ready;
 	wait_queue_head_t wait_recvd_msg;
 	wait_queue_head_t wait_stop_wd;
 
@@ -365,6 +434,9 @@ struct mei_device {
 
 	struct work_struct init_work;
 
+	/* List of bus devices */
+	struct list_head device_list;
+
 	const struct mei_hw_ops *ops;
 	char hw[0] __aligned(sizeof(void *));
 };
@@ -374,13 +446,23 @@ static inline unsigned long mei_secs_to_jiffies(unsigned long sec)
 	return msecs_to_jiffies(sec * MSEC_PER_SEC);
 }
 
+/**
+ * mei_data2slots - get slots - number of (dwords) from a message length
+ *	+ size of the mei header
+ * @length - size of the messages in bytes
+ * returns  - number of slots
+ */
+static inline u32 mei_data2slots(size_t length)
+{
+	return DIV_ROUND_UP(sizeof(struct mei_msg_hdr) + length, 4);
+}
 
 /*
  * mei init function prototypes
  */
 void mei_device_init(struct mei_device *dev);
 void mei_reset(struct mei_device *dev, int interrupts);
-int mei_hw_init(struct mei_device *dev);
+int mei_start(struct mei_device *dev);
 void mei_stop(struct mei_device *dev);
 
 /*
@@ -392,8 +474,7 @@ int mei_irq_read_handler(struct mei_device *dev,
 		struct mei_cl_cb *cmpl_list, s32 *slots);
 
 int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list);
-
-void mei_irq_complete_handler(struct mei_cl *cl, struct mei_cl_cb *cb_pos);
+void mei_irq_compl_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list);
 
 /*
  * AMTHIF - AMT Host Interface Functions
@@ -455,6 +536,11 @@ static inline void mei_hw_reset(struct mei_device *dev, bool enable)
 	dev->ops->hw_reset(dev, enable);
 }
 
+static inline void mei_hw_start(struct mei_device *dev)
+{
+	dev->ops->hw_start(dev);
+}
+
 static inline void mei_clear_interrupts(struct mei_device *dev)
 {
 	dev->ops->intr_clear(dev);
@@ -470,10 +556,6 @@ static inline void mei_disable_interrupts(struct mei_device *dev)
 	dev->ops->intr_disable(dev);
 }
 
-static inline void mei_host_set_ready(struct mei_device *dev)
-{
-	dev->ops->host_set_ready(dev);
-}
 static inline bool mei_host_is_ready(struct mei_device *dev)
 {
 	return dev->ops->host_is_ready(dev);
diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c
index b8b5c9c..a1a582b 100644
--- a/drivers/misc/mei/pci-me.c
+++ b/drivers/misc/mei/pci-me.c
@@ -47,7 +47,7 @@
 static struct pci_dev *mei_pdev;
 
 /* mei_pci_tbl - PCI Device ID Table */
-static DEFINE_PCI_DEVICE_TABLE(mei_pci_tbl) = {
+static DEFINE_PCI_DEVICE_TABLE(mei_me_pci_tbl) = {
 	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_82946GZ)},
 	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_82G35)},
 	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_82Q965)},
@@ -86,7 +86,7 @@ static DEFINE_PCI_DEVICE_TABLE(mei_pci_tbl) = {
 	{0, }
 };
 
-MODULE_DEVICE_TABLE(pci, mei_pci_tbl);
+MODULE_DEVICE_TABLE(pci, mei_me_pci_tbl);
 
 static DEFINE_MUTEX(mei_mutex);
 
@@ -97,7 +97,7 @@ static DEFINE_MUTEX(mei_mutex);
  *
  * returns true if ME Interface is valid, false otherwise
  */
-static bool mei_quirk_probe(struct pci_dev *pdev,
+static bool mei_me_quirk_probe(struct pci_dev *pdev,
 				const struct pci_device_id *ent)
 {
 	u32 reg;
@@ -119,7 +119,7 @@ static bool mei_quirk_probe(struct pci_dev *pdev,
  *
  * returns 0 on success, <0 on failure.
  */
-static int mei_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+static int mei_me_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	struct mei_device *dev;
 	struct mei_me_hw *hw;
@@ -127,7 +127,7 @@ static int mei_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	mutex_lock(&mei_mutex);
 
-	if (!mei_quirk_probe(pdev, ent)) {
+	if (!mei_me_quirk_probe(pdev, ent)) {
 		err = -ENODEV;
 		goto end;
 	}
@@ -184,7 +184,7 @@ static int mei_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 		goto disable_msi;
 	}
 
-	if (mei_hw_init(dev)) {
+	if (mei_start(dev)) {
 		dev_err(&pdev->dev, "init hw failure.\n");
 		err = -ENODEV;
 		goto release_irq;
@@ -197,7 +197,6 @@ static int mei_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	mei_pdev = pdev;
 	pci_set_drvdata(pdev, dev);
 
-
 	schedule_delayed_work(&dev->timer_work, HZ);
 
 	mutex_unlock(&mei_mutex);
@@ -233,7 +232,7 @@ end:
  * mei_remove is called by the PCI subsystem to alert the driver
  * that it should release a PCI device.
  */
-static void mei_remove(struct pci_dev *pdev)
+static void mei_me_remove(struct pci_dev *pdev)
 {
 	struct mei_device *dev;
 	struct mei_me_hw *hw;
@@ -253,8 +252,6 @@ static void mei_remove(struct pci_dev *pdev)
 
 	mei_pdev = NULL;
 
-	mei_watchdog_unregister(dev);
-
 	/* disable interrupts */
 	mei_disable_interrupts(dev);
 
@@ -274,7 +271,7 @@ static void mei_remove(struct pci_dev *pdev)
 
 }
 #ifdef CONFIG_PM
-static int mei_pci_suspend(struct device *device)
+static int mei_me_pci_suspend(struct device *device)
 {
 	struct pci_dev *pdev = to_pci_dev(device);
 	struct mei_device *dev = pci_get_drvdata(pdev);
@@ -294,7 +291,7 @@ static int mei_pci_suspend(struct device *device)
 	return 0;
 }
 
-static int mei_pci_resume(struct device *device)
+static int mei_me_pci_resume(struct device *device)
 {
 	struct pci_dev *pdev = to_pci_dev(device);
 	struct mei_device *dev;
@@ -334,24 +331,24 @@ static int mei_pci_resume(struct device *device)
 
 	return err;
 }
-static SIMPLE_DEV_PM_OPS(mei_pm_ops, mei_pci_suspend, mei_pci_resume);
-#define MEI_PM_OPS	(&mei_pm_ops)
+static SIMPLE_DEV_PM_OPS(mei_me_pm_ops, mei_me_pci_suspend, mei_me_pci_resume);
+#define MEI_ME_PM_OPS	(&mei_me_pm_ops)
 #else
-#define MEI_PM_OPS	NULL
+#define MEI_ME_PM_OPS	NULL
 #endif /* CONFIG_PM */
 /*
  *  PCI driver structure
  */
-static struct pci_driver mei_driver = {
+static struct pci_driver mei_me_driver = {
 	.name = KBUILD_MODNAME,
-	.id_table = mei_pci_tbl,
-	.probe = mei_probe,
-	.remove = mei_remove,
-	.shutdown = mei_remove,
-	.driver.pm = MEI_PM_OPS,
+	.id_table = mei_me_pci_tbl,
+	.probe = mei_me_probe,
+	.remove = mei_me_remove,
+	.shutdown = mei_me_remove,
+	.driver.pm = MEI_ME_PM_OPS,
 };
 
-module_pci_driver(mei_driver);
+module_pci_driver(mei_me_driver);
 
 MODULE_AUTHOR("Intel Corporation");
 MODULE_DESCRIPTION("Intel(R) Management Engine Interface");
diff --git a/drivers/misc/vmw_vmci/Kconfig b/drivers/misc/vmw_vmci/Kconfig
index 39c2eca..ea98f7e 100644
--- a/drivers/misc/vmw_vmci/Kconfig
+++ b/drivers/misc/vmw_vmci/Kconfig
@@ -4,7 +4,7 @@
 
 config VMWARE_VMCI
 	tristate "VMware VMCI Driver"
-	depends on X86 && PCI
+	depends on X86 && PCI && NET
 	help
 	  This is VMware's Virtual Machine Communication Interface.  It enables
 	  high-speed communication between host and guest in a virtual
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 5bab73b..e12a03c 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -1932,8 +1932,14 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
 	}
 
 out:
-	if (!req && !(mq->flags & MMC_QUEUE_NEW_REQUEST))
-		/* release host only when there are no more requests */
+	if ((!req && !(mq->flags & MMC_QUEUE_NEW_REQUEST)) ||
+	     (req && (req->cmd_flags & MMC_REQ_SPECIAL_MASK)))
+		/*
+		 * Release host when there are no more requests
+		 * and after special request(discard, flush) is done.
+		 * In case sepecial request, there is no reentry to
+		 * the 'mmc_blk_issue_rq' with 'mqrq_prev->req'.
+		 */
 		mmc_release_host(card->host);
 	return ret;
 }
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c
index fa4e44e..9447a0e 100644
--- a/drivers/mmc/card/queue.c
+++ b/drivers/mmc/card/queue.c
@@ -22,9 +22,6 @@
 
 #define MMC_QUEUE_BOUNCESZ	65536
 
-
-#define MMC_REQ_SPECIAL_MASK	(REQ_DISCARD | REQ_FLUSH)
-
 /*
  * Prepare a MMC request. This just filters out odd stuff.
  */
diff --git a/drivers/mmc/card/queue.h b/drivers/mmc/card/queue.h
index 031bf63..5752d50 100644
--- a/drivers/mmc/card/queue.h
+++ b/drivers/mmc/card/queue.h
@@ -1,6 +1,8 @@
 #ifndef MMC_QUEUE_H
 #define MMC_QUEUE_H
 
+#define MMC_REQ_SPECIAL_MASK	(REQ_DISCARD | REQ_FLUSH)
+
 struct request;
 struct task_struct;
 
diff --git a/drivers/mmc/card/sdio_uart.c b/drivers/mmc/card/sdio_uart.c
index c931dfe..f093cea 100644
--- a/drivers/mmc/card/sdio_uart.c
+++ b/drivers/mmc/card/sdio_uart.c
@@ -134,7 +134,6 @@ static void sdio_uart_port_put(struct sdio_uart_port *port)
 static void sdio_uart_port_remove(struct sdio_uart_port *port)
 {
 	struct sdio_func *func;
-	struct tty_struct *tty;
 
 	BUG_ON(sdio_uart_table[port->index] != port);
 
@@ -155,12 +154,8 @@ static void sdio_uart_port_remove(struct sdio_uart_port *port)
 	sdio_claim_host(func);
 	port->func = NULL;
 	mutex_unlock(&port->func_lock);
-	tty = tty_port_tty_get(&port->port);
 	/* tty_hangup is async so is this safe as is ?? */
-	if (tty) {
-		tty_hangup(tty);
-		tty_kref_put(tty);
-	}
+	tty_port_tty_hangup(&port->port, false);
 	mutex_unlock(&port->port.mutex);
 	sdio_release_irq(func);
 	sdio_disable_func(func);
@@ -492,11 +487,7 @@ static void sdio_uart_check_modem_status(struct sdio_uart_port *port)
 			wake_up_interruptible(&port->port.open_wait);
 		else {
 			/* DCD drop - hang up if tty attached */
-			tty = tty_port_tty_get(&port->port);
-			if (tty) {
-				tty_hangup(tty);
-				tty_kref_put(tty);
-			}
+			tty_port_tty_hangup(&port->port, false);
 		}
 	}
 	if (status & UART_MSR_DCTS) {
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 08a3cf2..7b435a3 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -120,8 +120,8 @@ static void mmc_should_fail_request(struct mmc_host *host,
 	    !should_fail(&host->fail_mmc_request, data->blksz * data->blocks))
 		return;
 
-	data->error = data_errors[random32() % ARRAY_SIZE(data_errors)];
-	data->bytes_xfered = (random32() % (data->bytes_xfered >> 9)) << 9;
+	data->error = data_errors[prandom_u32() % ARRAY_SIZE(data_errors)];
+	data->bytes_xfered = (prandom_u32() % (data->bytes_xfered >> 9)) << 9;
 }
 
 #else /* CONFIG_FAIL_MMC_REQUEST */
@@ -2289,6 +2289,19 @@ int _mmc_detect_card_removed(struct mmc_host *host)
 		return 1;
 
 	ret = host->bus_ops->alive(host);
+
+	/*
+	 * Card detect status and alive check may be out of sync if card is
+	 * removed slowly, when card detect switch changes while card/slot
+	 * pads are still contacted in hardware (refer to "SD Card Mechanical
+	 * Addendum, Appendix C: Card Detection Switch"). So reschedule a
+	 * detect work 200ms later for this case.
+	 */
+	if (!ret && host->ops->get_cd && !host->ops->get_cd(host)) {
+		mmc_detect_change(host, msecs_to_jiffies(200));
+		pr_debug("%s: card removed too slowly\n", mmc_hostname(host));
+	}
+
 	if (ret) {
 		mmc_card_set_removed(host->card);
 		pr_debug("%s: card remove detected\n", mmc_hostname(host));
@@ -2405,6 +2418,7 @@ void mmc_start_host(struct mmc_host *host)
 	host->rescan_disable = 0;
 	mmc_power_up(host);
 	mmc_detect_change(host, 0);
+	mmc_flush_scheduled_work();
 }
 
 void mmc_stop_host(struct mmc_host *host)
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index c8f3d6e..d584f7c 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -96,6 +96,7 @@ static int mmc_decode_cid(struct mmc_card *card)
 		card->cid.prod_name[3]	= UNSTUFF_BITS(resp, 72, 8);
 		card->cid.prod_name[4]	= UNSTUFF_BITS(resp, 64, 8);
 		card->cid.prod_name[5]	= UNSTUFF_BITS(resp, 56, 8);
+		card->cid.prv		= UNSTUFF_BITS(resp, 48, 8);
 		card->cid.serial	= UNSTUFF_BITS(resp, 16, 32);
 		card->cid.month		= UNSTUFF_BITS(resp, 12, 4);
 		card->cid.year		= UNSTUFF_BITS(resp, 8, 4) + 1997;
@@ -627,6 +628,7 @@ MMC_DEV_ATTR(hwrev, "0x%x\n", card->cid.hwrev);
 MMC_DEV_ATTR(manfid, "0x%06x\n", card->cid.manfid);
 MMC_DEV_ATTR(name, "%s\n", card->cid.prod_name);
 MMC_DEV_ATTR(oemid, "0x%04x\n", card->cid.oemid);
+MMC_DEV_ATTR(prv, "0x%x\n", card->cid.prv);
 MMC_DEV_ATTR(serial, "0x%08x\n", card->cid.serial);
 MMC_DEV_ATTR(enhanced_area_offset, "%llu\n",
 		card->ext_csd.enhanced_area_offset);
@@ -645,6 +647,7 @@ static struct attribute *mmc_std_attrs[] = {
 	&dev_attr_manfid.attr,
 	&dev_attr_name.attr,
 	&dev_attr_oemid.attr,
+	&dev_attr_prv.attr,
 	&dev_attr_serial.attr,
 	&dev_attr_enhanced_area_offset.attr,
 	&dev_attr_enhanced_area_size.attr,
diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c
index 5e57048..8d6bb18 100644
--- a/drivers/mmc/core/sdio_bus.c
+++ b/drivers/mmc/core/sdio_bus.c
@@ -16,6 +16,7 @@
 #include <linux/export.h>
 #include <linux/slab.h>
 #include <linux/pm_runtime.h>
+#include <linux/acpi.h>
 
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
@@ -299,6 +300,19 @@ struct sdio_func *sdio_alloc_func(struct mmc_card *card)
 	return func;
 }
 
+#ifdef CONFIG_ACPI
+static void sdio_acpi_set_handle(struct sdio_func *func)
+{
+	struct mmc_host *host = func->card->host;
+	u64 addr = (host->slotno << 16) | func->num;
+
+	ACPI_HANDLE_SET(&func->dev,
+			acpi_get_child(ACPI_HANDLE(host->parent), addr));
+}
+#else
+static inline void sdio_acpi_set_handle(struct sdio_func *func) {}
+#endif
+
 /*
  * Register a new SDIO function with the driver model.
  */
@@ -308,9 +322,12 @@ int sdio_add_func(struct sdio_func *func)
 
 	dev_set_name(&func->dev, "%s:%d", mmc_card_id(func->card), func->num);
 
+	sdio_acpi_set_handle(func);
 	ret = device_add(&func->dev);
-	if (ret == 0)
+	if (ret == 0) {
 		sdio_func_set_present(func);
+		acpi_dev_pm_attach(&func->dev, false);
+	}
 
 	return ret;
 }
@@ -326,6 +343,7 @@ void sdio_remove_func(struct sdio_func *func)
 	if (!sdio_func_present(func))
 		return;
 
+	acpi_dev_pm_detach(&func->dev, false);
 	device_del(&func->dev);
 	put_device(&func->dev);
 }
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index d88219e..f83f245 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -190,6 +190,17 @@ config MMC_SDHCI_S3C
 
 	  If unsure, say N.
 
+config MMC_SDHCI_SIRF
+	tristate "SDHCI support on CSR SiRFprimaII and SiRFmarco SoCs"
+	depends on ARCH_SIRF
+	depends on MMC_SDHCI_PLTFM
+	help
+	  This selects the SDHCI support for SiRF System-on-Chip devices.
+
+	  If you have a controller with this interface, say Y or M here.
+
+	  If unsure, say N.
+
 config MMC_SDHCI_PXAV3
 	tristate "Marvell MMP2 SD Host Controller support (PXAV3)"
 	depends on CLKDEV_LOOKUP
@@ -300,16 +311,6 @@ config MMC_ATMELMCI
 
 	  If unsure, say N.
 
-config MMC_ATMELMCI_DMA
-	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.
-
-	  If unsure, say N.
-
 config MMC_MSM
 	tristate "Qualcomm SDCC Controller Support"
 	depends on MMC && ARCH_MSM
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index c380e3c..cd32280 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_MMC_SDHCI_ACPI)	+= sdhci-acpi.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_SIRF)   	+= sdhci-sirf.o
 obj-$(CONFIG_MMC_SDHCI_SPEAR)	+= sdhci-spear.o
 obj-$(CONFIG_MMC_WBSD)		+= wbsd.o
 obj-$(CONFIG_MMC_AU1X)		+= au1xmmc.o
diff --git a/drivers/mmc/host/android-goldfish.c b/drivers/mmc/host/android-goldfish.c
index ef3aef0..7780c14 100644
--- a/drivers/mmc/host/android-goldfish.c
+++ b/drivers/mmc/host/android-goldfish.c
@@ -476,7 +476,7 @@ static int goldfish_mmc_probe(struct platform_device *pdev)
 	host->mmc = mmc;
 
 	pr_err("mmc: Mapping %lX to %lX\n", (long)res->start, (long)res->end);
-	host->reg_base = ioremap(res->start, res->end - res->start + 1);
+	host->reg_base = ioremap(res->start, resource_size(res));
 	if (host->reg_base == NULL) {
 		ret = -ENOMEM;
 		goto ioremap_failed;
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c
index 722af1d..10f8b73 100644
--- a/drivers/mmc/host/atmel-mci.c
+++ b/drivers/mmc/host/atmel-mci.c
@@ -2487,10 +2487,8 @@ static int __exit atmci_remove(struct platform_device *pdev)
 	atmci_readl(host, ATMCI_SR);
 	clk_disable(host->mck);
 
-#ifdef CONFIG_MMC_ATMELMCI_DMA
 	if (host->dma.chan)
 		dma_release_channel(host->dma.chan);
-#endif
 
 	free_irq(platform_get_irq(pdev, 0), host);
 	iounmap(host->regs);
diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c
index 2063677..4fdc159 100644
--- a/drivers/mmc/host/davinci_mmc.c
+++ b/drivers/mmc/host/davinci_mmc.c
@@ -1190,13 +1190,15 @@ static int __init davinci_mmcsd_probe(struct platform_device *pdev)
 
 	r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
 	if (!r)
-		goto out;
-	host->rxdma = r->start;
+		dev_warn(&pdev->dev, "RX DMA resource not specified\n");
+	else
+		host->rxdma = r->start;
 
 	r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
 	if (!r)
-		goto out;
-	host->txdma = r->start;
+		dev_warn(&pdev->dev, "TX DMA resource not specified\n");
+	else
+		host->txdma = r->start;
 
 	host->mem_res = mem;
 	host->base = ioremap(mem->start, mem_size);
@@ -1410,18 +1412,7 @@ static struct platform_driver davinci_mmcsd_driver = {
 	.remove		= __exit_p(davinci_mmcsd_remove),
 };
 
-static int __init davinci_mmcsd_init(void)
-{
-	return platform_driver_probe(&davinci_mmcsd_driver,
-				     davinci_mmcsd_probe);
-}
-module_init(davinci_mmcsd_init);
-
-static void __exit davinci_mmcsd_exit(void)
-{
-	platform_driver_unregister(&davinci_mmcsd_driver);
-}
-module_exit(davinci_mmcsd_exit);
+module_platform_driver_probe(davinci_mmcsd_driver, davinci_mmcsd_probe);
 
 MODULE_AUTHOR("Texas Instruments India");
 MODULE_LICENSE("GPL");
diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c
index 72fd0f2..c7f0976 100644
--- a/drivers/mmc/host/dw_mmc-exynos.c
+++ b/drivers/mmc/host/dw_mmc-exynos.c
@@ -189,8 +189,8 @@ static int dw_mci_exynos_setup_bus(struct dw_mci *host,
 	return 0;
 }
 
-/* Exynos5250 controller specific capabilities */
-static unsigned long exynos5250_dwmmc_caps[4] = {
+/* Common capabilities of Exynos4/Exynos5 SoC */
+static unsigned long exynos_dwmmc_caps[4] = {
 	MMC_CAP_UHS_DDR50 | MMC_CAP_1_8V_DDR |
 		MMC_CAP_8_BIT_DATA | MMC_CAP_CMD23,
 	MMC_CAP_CMD23,
@@ -198,8 +198,8 @@ static unsigned long exynos5250_dwmmc_caps[4] = {
 	MMC_CAP_CMD23,
 };
 
-static const struct dw_mci_drv_data exynos5250_drv_data = {
-	.caps			= exynos5250_dwmmc_caps,
+static const struct dw_mci_drv_data exynos_drv_data = {
+	.caps			= exynos_dwmmc_caps,
 	.init			= dw_mci_exynos_priv_init,
 	.setup_clock		= dw_mci_exynos_setup_clock,
 	.prepare_command	= dw_mci_exynos_prepare_command,
@@ -209,13 +209,15 @@ static const struct dw_mci_drv_data exynos5250_drv_data = {
 };
 
 static const struct of_device_id dw_mci_exynos_match[] = {
+	{ .compatible = "samsung,exynos4412-dw-mshc",
+			.data = &exynos_drv_data, },
 	{ .compatible = "samsung,exynos5250-dw-mshc",
-			.data = &exynos5250_drv_data, },
+			.data = &exynos_drv_data, },
 	{},
 };
 MODULE_DEVICE_TABLE(of, dw_mci_exynos_match);
 
-int dw_mci_exynos_probe(struct platform_device *pdev)
+static int dw_mci_exynos_probe(struct platform_device *pdev)
 {
 	const struct dw_mci_drv_data *drv_data;
 	const struct of_device_id *match;
@@ -230,7 +232,7 @@ static struct platform_driver dw_mci_exynos_pltfm_driver = {
 	.remove		= __exit_p(dw_mci_pltfm_remove),
 	.driver		= {
 		.name		= "dwmmc_exynos",
-		.of_match_table	= of_match_ptr(dw_mci_exynos_match),
+		.of_match_table	= dw_mci_exynos_match,
 		.pm		= &dw_mci_pltfm_pmops,
 	},
 };
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index 9834221..45d9216 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -795,9 +795,9 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 
 	/* DDR mode set */
 	if (ios->timing == MMC_TIMING_UHS_DDR50)
-		regs |= (0x1 << slot->id) << 16;
+		regs |= ((0x1 << slot->id) << 16);
 	else
-		regs &= ~(0x1 << slot->id) << 16;
+		regs &= ~((0x1 << slot->id) << 16);
 
 	mci_writel(slot->host, UHS_REG, regs);
 
@@ -818,6 +818,20 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 	switch (ios->power_mode) {
 	case MMC_POWER_UP:
 		set_bit(DW_MMC_CARD_NEED_INIT, &slot->flags);
+		/* Power up slot */
+		if (slot->host->pdata->setpower)
+			slot->host->pdata->setpower(slot->id, mmc->ocr_avail);
+		regs = mci_readl(slot->host, PWREN);
+		regs |= (1 << slot->id);
+		mci_writel(slot->host, PWREN, regs);
+		break;
+	case MMC_POWER_OFF:
+		/* Power down slot */
+		if (slot->host->pdata->setpower)
+			slot->host->pdata->setpower(slot->id, 0);
+		regs = mci_readl(slot->host, PWREN);
+		regs &= ~(1 << slot->id);
+		mci_writel(slot->host, PWREN, regs);
 		break;
 	default:
 		break;
@@ -1191,12 +1205,15 @@ static void dw_mci_pull_final_bytes(struct dw_mci *host, void *buf, int cnt)
 
 static void dw_mci_push_data16(struct dw_mci *host, void *buf, int cnt)
 {
+	struct mmc_data *data = host->data;
+	int init_cnt = 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) {
+		if (host->part_buf_count == 2) {
 			mci_writew(host, DATA(host->data_offset),
 					host->part_buf16);
 			host->part_buf_count = 0;
@@ -1229,9 +1246,11 @@ static void dw_mci_push_data16(struct dw_mci *host, void *buf, int cnt)
 	/* put anything remaining in the part_buf */
 	if (cnt) {
 		dw_mci_set_part_bytes(host, buf, cnt);
-		if (!sg_next(host->sg))
+		 /* Push data if we have reached the expected data length */
+		if ((data->bytes_xfered + init_cnt) ==
+		    (data->blksz * data->blocks))
 			mci_writew(host, DATA(host->data_offset),
-					host->part_buf16);
+				   host->part_buf16);
 	}
 }
 
@@ -1269,12 +1288,15 @@ static void dw_mci_pull_data16(struct dw_mci *host, void *buf, int cnt)
 
 static void dw_mci_push_data32(struct dw_mci *host, void *buf, int cnt)
 {
+	struct mmc_data *data = host->data;
+	int init_cnt = 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) {
+		if (host->part_buf_count == 4) {
 			mci_writel(host, DATA(host->data_offset),
 					host->part_buf32);
 			host->part_buf_count = 0;
@@ -1307,9 +1329,11 @@ static void dw_mci_push_data32(struct dw_mci *host, void *buf, int cnt)
 	/* put anything remaining in the part_buf */
 	if (cnt) {
 		dw_mci_set_part_bytes(host, buf, cnt);
-		if (!sg_next(host->sg))
+		 /* Push data if we have reached the expected data length */
+		if ((data->bytes_xfered + init_cnt) ==
+		    (data->blksz * data->blocks))
 			mci_writel(host, DATA(host->data_offset),
-						host->part_buf32);
+				   host->part_buf32);
 	}
 }
 
@@ -1347,13 +1371,17 @@ static void dw_mci_pull_data32(struct dw_mci *host, void *buf, int cnt)
 
 static void dw_mci_push_data64(struct dw_mci *host, void *buf, int cnt)
 {
+	struct mmc_data *data = host->data;
+	int init_cnt = 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->data_offset),
+
+		if (host->part_buf_count == 8) {
+			mci_writeq(host, DATA(host->data_offset),
 					host->part_buf);
 			host->part_buf_count = 0;
 		}
@@ -1385,9 +1413,11 @@ static void dw_mci_push_data64(struct dw_mci *host, void *buf, int cnt)
 	/* put anything remaining in the part_buf */
 	if (cnt) {
 		dw_mci_set_part_bytes(host, buf, cnt);
-		if (!sg_next(host->sg))
+		/* Push data if we have reached the expected data length */
+		if ((data->bytes_xfered + init_cnt) ==
+		    (data->blksz * data->blocks))
 			mci_writeq(host, DATA(host->data_offset),
-					host->part_buf);
+				   host->part_buf);
 	}
 }
 
@@ -1438,7 +1468,7 @@ static void dw_mci_pull_data(struct dw_mci *host, void *buf, int cnt)
 	host->pull_data(host, buf, cnt);
 }
 
-static void dw_mci_read_data_pio(struct dw_mci *host)
+static void dw_mci_read_data_pio(struct dw_mci *host, bool dto)
 {
 	struct sg_mapping_iter *sg_miter = &host->sg_miter;
 	void *buf;
@@ -1446,7 +1476,7 @@ static void dw_mci_read_data_pio(struct dw_mci *host)
 	struct mmc_data	*data = host->data;
 	int shift = host->data_shift;
 	u32 status;
-	unsigned int nbytes = 0, len;
+	unsigned int len;
 	unsigned int remain, fcnt;
 
 	do {
@@ -1465,16 +1495,17 @@ static void dw_mci_read_data_pio(struct dw_mci *host)
 			if (!len)
 				break;
 			dw_mci_pull_data(host, (void *)(buf + offset), len);
+			data->bytes_xfered += len;
 			offset += len;
-			nbytes += len;
 			remain -= len;
 		} while (remain);
 
 		sg_miter->consumed = offset;
 		status = mci_readl(host, MINTSTS);
 		mci_writel(host, RINTSTS, SDMMC_INT_RXDR);
-	} while (status & SDMMC_INT_RXDR); /*if the RXDR is ready read again*/
-	data->bytes_xfered += nbytes;
+	/* if the RXDR is ready read again */
+	} while ((status & SDMMC_INT_RXDR) ||
+		 (dto && SDMMC_GET_FCNT(mci_readl(host, STATUS))));
 
 	if (!remain) {
 		if (!sg_miter_next(sg_miter))
@@ -1485,7 +1516,6 @@ static void dw_mci_read_data_pio(struct dw_mci *host)
 	return;
 
 done:
-	data->bytes_xfered += nbytes;
 	sg_miter_stop(sg_miter);
 	host->sg = NULL;
 	smp_wmb();
@@ -1500,7 +1530,7 @@ static void dw_mci_write_data_pio(struct dw_mci *host)
 	struct mmc_data	*data = host->data;
 	int shift = host->data_shift;
 	u32 status;
-	unsigned int nbytes = 0, len;
+	unsigned int len;
 	unsigned int fifo_depth = host->fifo_depth;
 	unsigned int remain, fcnt;
 
@@ -1521,8 +1551,8 @@ static void dw_mci_write_data_pio(struct dw_mci *host)
 			if (!len)
 				break;
 			host->push_data(host, (void *)(buf + offset), len);
+			data->bytes_xfered += len;
 			offset += len;
-			nbytes += len;
 			remain -= len;
 		} while (remain);
 
@@ -1530,7 +1560,6 @@ static void dw_mci_write_data_pio(struct dw_mci *host)
 		status = mci_readl(host, MINTSTS);
 		mci_writel(host, RINTSTS, SDMMC_INT_TXDR);
 	} while (status & SDMMC_INT_TXDR); /* if TXDR write again */
-	data->bytes_xfered += nbytes;
 
 	if (!remain) {
 		if (!sg_miter_next(sg_miter))
@@ -1541,7 +1570,6 @@ static void dw_mci_write_data_pio(struct dw_mci *host)
 	return;
 
 done:
-	data->bytes_xfered += nbytes;
 	sg_miter_stop(sg_miter);
 	host->sg = NULL;
 	smp_wmb();
@@ -1563,11 +1591,11 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
 {
 	struct dw_mci *host = dev_id;
 	u32 pending;
-	unsigned int pass_count = 0;
 	int i;
 
-	do {
-		pending = mci_readl(host, MINTSTS); /* read-only mask reg */
+	pending = mci_readl(host, MINTSTS); /* read-only mask reg */
+
+	if (pending) {
 
 		/*
 		 * DTO fix - version 2.10a and below, and only if internal DMA
@@ -1579,9 +1607,6 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
 				pending |= SDMMC_INT_DATA_OVER;
 		}
 
-		if (!pending)
-			break;
-
 		if (pending & DW_MCI_CMD_ERROR_FLAGS) {
 			mci_writel(host, RINTSTS, DW_MCI_CMD_ERROR_FLAGS);
 			host->cmd_status = pending;
@@ -1605,7 +1630,7 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
 			smp_wmb();
 			if (host->dir_status == DW_MCI_RECV_STATUS) {
 				if (host->sg != NULL)
-					dw_mci_read_data_pio(host);
+					dw_mci_read_data_pio(host, true);
 			}
 			set_bit(EVENT_DATA_COMPLETE, &host->pending_events);
 			tasklet_schedule(&host->tasklet);
@@ -1614,7 +1639,7 @@ 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->dir_status == DW_MCI_RECV_STATUS && host->sg)
-				dw_mci_read_data_pio(host);
+				dw_mci_read_data_pio(host, false);
 		}
 
 		if (pending & SDMMC_INT_TXDR) {
@@ -1642,7 +1667,7 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
 			}
 		}
 
-	} while (pass_count++ < 5);
+	}
 
 #ifdef CONFIG_MMC_DW_IDMAC
 	/* Handle DMA interrupts */
@@ -1674,10 +1699,6 @@ static void dw_mci_work_routine_card(struct work_struct *work)
 			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 */
@@ -1760,10 +1781,6 @@ static void dw_mci_work_routine_card(struct work_struct *work)
 
 			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);
 		}
 
@@ -1980,8 +1997,14 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
 	if (IS_ERR(host->vmmc)) {
 		pr_info("%s: no vmmc regulator found\n", mmc_hostname(mmc));
 		host->vmmc = NULL;
-	} else
-		regulator_enable(host->vmmc);
+	} else {
+		ret = regulator_enable(host->vmmc);
+		if (ret) {
+			dev_err(host->dev,
+				"failed to enable regulator: %d\n", ret);
+			goto err_setup_bus;
+		}
+	}
 
 	if (dw_mci_get_cd(mmc))
 		set_bit(DW_MMC_CARD_PRESENT, &slot->flags);
@@ -1990,7 +2013,9 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
 
 	slot->wp_gpio = dw_mci_of_get_wp_gpio(host->dev, slot->id);
 
-	mmc_add_host(mmc);
+	ret = mmc_add_host(mmc);
+	if (ret)
+		goto err_setup_bus;
 
 #if defined(CONFIG_DEBUG_FS)
 	dw_mci_init_debugfs(slot);
@@ -2289,6 +2314,18 @@ int dw_mci_probe(struct dw_mci *host)
 	mci_writel(host, CLKENA, 0);
 	mci_writel(host, CLKSRC, 0);
 
+	/*
+	 * In 2.40a spec, Data offset is changed.
+	 * Need to check the version-id and set data-offset for DATA register.
+	 */
+	host->verid = SDMMC_GET_VERID(mci_readl(host, VERID));
+	dev_info(host->dev, "Version ID is %04x\n", host->verid);
+
+	if (host->verid < DW_MMC_240A)
+		host->data_offset = DATA_OFFSET;
+	else
+		host->data_offset = DATA_240A_OFFSET;
+
 	tasklet_init(&host->tasklet, dw_mci_tasklet_func, (unsigned long)host);
 	host->card_workqueue = alloc_workqueue("dw-mci-card",
 			WQ_MEM_RECLAIM | WQ_NON_REENTRANT, 1);
@@ -2337,18 +2374,6 @@ int dw_mci_probe(struct dw_mci *host)
 		goto err_workqueue;
 	}
 
-	/*
-	 * In 2.40a spec, Data offset is changed.
-	 * Need to check the version-id and set data-offset for DATA register.
-	 */
-	host->verid = SDMMC_GET_VERID(mci_readl(host, VERID));
-	dev_info(host->dev, "Version ID is %04x\n", host->verid);
-
-	if (host->verid < DW_MMC_240A)
-		host->data_offset = DATA_OFFSET;
-	else
-		host->data_offset = DATA_240A_OFFSET;
-
 	if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO)
 		dev_info(host->dev, "Internal DMAC interrupt fix enabled.\n");
 
@@ -2445,8 +2470,14 @@ int dw_mci_resume(struct dw_mci *host)
 {
 	int i, ret;
 
-	if (host->vmmc)
-		regulator_enable(host->vmmc);
+	if (host->vmmc) {
+		ret = regulator_enable(host->vmmc);
+		if (ret) {
+			dev_err(host->dev,
+				"failed to enable regulator: %d\n", ret);
+			return ret;
+		}
+	}
 
 	if (!mci_wait_reset(host->dev, host)) {
 		ret = -ENODEV;
@@ -2485,7 +2516,7 @@ EXPORT_SYMBOL(dw_mci_resume);
 
 static int __init dw_mci_init(void)
 {
-	printk(KERN_INFO "Synopsys Designware Multimedia Card Interface Driver");
+	pr_info("Synopsys Designware Multimedia Card Interface Driver\n");
 	return 0;
 }
 
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index 372e921..375c109 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -1141,6 +1141,11 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 	case MMC_POWER_OFF:
 		if (!IS_ERR(mmc->supply.vmmc))
 			mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0);
+
+		if (!IS_ERR(mmc->supply.vqmmc) &&
+		    regulator_is_enabled(mmc->supply.vqmmc))
+			regulator_disable(mmc->supply.vqmmc);
+
 		break;
 	case MMC_POWER_UP:
 		if (!IS_ERR(mmc->supply.vmmc))
@@ -1155,6 +1160,10 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 
 		break;
 	case MMC_POWER_ON:
+		if (!IS_ERR(mmc->supply.vqmmc) &&
+		    !regulator_is_enabled(mmc->supply.vqmmc))
+			regulator_enable(mmc->supply.vqmmc);
+
 		pwr |= MCI_PWR_ON;
 		break;
 	}
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index 7c0af0e..0ee4a57 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -43,7 +43,6 @@
 #include <asm/sizes.h>
 
 #include <linux/platform_data/mmc-msm_sdcc.h>
-#include <mach/msm_iomap.h>
 #include <mach/dma.h>
 #include <mach/clk.h>
 
diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c
index 145cdaf..8960fc8 100644
--- a/drivers/mmc/host/mvsdio.c
+++ b/drivers/mmc/host/mvsdio.c
@@ -119,10 +119,8 @@ static int mvsd_setup_data(struct mvsd_host *host, struct mmc_data *data)
 		host->pio_size = data->blocks * data->blksz;
 		host->pio_ptr = sg_virt(data->sg);
 		if (!nodma)
-			pr_debug("%s: fallback to PIO for data "
-					  "at 0x%p size %d\n",
-					  mmc_hostname(host->mmc),
-					  host->pio_ptr, host->pio_size);
+			dev_dbg(host->dev, "fallback to PIO for data at 0x%p size %d\n",
+				host->pio_ptr, host->pio_size);
 		return 1;
 	} else {
 		dma_addr_t phys_addr;
@@ -473,8 +471,8 @@ static irqreturn_t mvsd_irq(int irq, void *dev)
 		if (mrq->data)
 			err_status = mvsd_finish_data(host, mrq->data, err_status);
 		if (err_status) {
-			pr_err("%s: unhandled error status %#04x\n",
-					mmc_hostname(host->mmc), err_status);
+			dev_err(host->dev, "unhandled error status %#04x\n",
+				err_status);
 			cmd->error = -ENOMSG;
 		}
 
@@ -491,9 +489,8 @@ static irqreturn_t mvsd_irq(int irq, void *dev)
 	if (irq_handled)
 		return IRQ_HANDLED;
 
-	pr_err("%s: unhandled interrupt status=0x%04x en=0x%04x "
-			"pio=%d\n", mmc_hostname(host->mmc), intr_status,
-			host->intr_en, host->pio_size);
+	dev_err(host->dev, "unhandled interrupt status=0x%04x en=0x%04x pio=%d\n",
+		intr_status, host->intr_en, host->pio_size);
 	return IRQ_NONE;
 }
 
@@ -507,13 +504,11 @@ static void mvsd_timeout_timer(unsigned long data)
 	spin_lock_irqsave(&host->lock, flags);
 	mrq = host->mrq;
 	if (mrq) {
-		pr_err("%s: Timeout waiting for hardware interrupt.\n",
-				mmc_hostname(host->mmc));
-		pr_err("%s: hw_state=0x%04x, intr_status=0x%04x "
-				"intr_en=0x%04x\n", mmc_hostname(host->mmc),
-				mvsd_read(MVSD_HW_STATE),
-				mvsd_read(MVSD_NOR_INTR_STATUS),
-				mvsd_read(MVSD_NOR_INTR_EN));
+		dev_err(host->dev, "Timeout waiting for hardware interrupt.\n");
+		dev_err(host->dev, "hw_state=0x%04x, intr_status=0x%04x intr_en=0x%04x\n",
+			mvsd_read(MVSD_HW_STATE),
+			mvsd_read(MVSD_NOR_INTR_STATUS),
+			mvsd_read(MVSD_NOR_INTR_EN));
 
 		host->mrq = NULL;
 
@@ -741,8 +736,8 @@ static int __init mvsd_probe(struct platform_device *pdev)
 			goto out;
 		}
 		host->base_clock = mvsd_data->clock / 2;
-		gpio_card_detect = mvsd_data->gpio_card_detect;
-		gpio_write_protect = mvsd_data->gpio_write_protect;
+		gpio_card_detect = mvsd_data->gpio_card_detect ? : -EINVAL;
+		gpio_write_protect = mvsd_data->gpio_write_protect ? : -EINVAL;
 	}
 
 	mmc->ops = &mvsd_ops;
@@ -778,7 +773,7 @@ static int __init mvsd_probe(struct platform_device *pdev)
 
 	ret = devm_request_irq(&pdev->dev, irq, mvsd_irq, 0, DRIVER_NAME, host);
 	if (ret) {
-		pr_err("%s: cannot assign irq %d\n", DRIVER_NAME, irq);
+		dev_err(&pdev->dev, "cannot assign irq %d\n", irq);
 		goto out;
 	}
 
@@ -797,13 +792,11 @@ static int __init mvsd_probe(struct platform_device *pdev)
 	if (ret)
 		goto out;
 
-	pr_notice("%s: %s driver initialized, ",
-			   mmc_hostname(mmc), DRIVER_NAME);
 	if (!(mmc->caps & MMC_CAP_NEEDS_POLL))
-		printk("using GPIO %d for card detection\n",
-		       gpio_card_detect);
+		dev_notice(&pdev->dev, "using GPIO %d for card detection\n",
+			   gpio_card_detect);
 	else
-		printk("lacking card detect (fall back to polling)\n");
+		dev_notice(&pdev->dev, "lacking card detect (fall back to polling)\n");
 	return 0;
 
 out:
@@ -881,18 +874,7 @@ static struct platform_driver mvsd_driver = {
 	},
 };
 
-static int __init mvsd_init(void)
-{
-	return platform_driver_probe(&mvsd_driver, mvsd_probe);
-}
-
-static void __exit mvsd_exit(void)
-{
-	platform_driver_unregister(&mvsd_driver);
-}
-
-module_init(mvsd_init);
-module_exit(mvsd_exit);
+module_platform_driver_probe(mvsd_driver, mvsd_probe);
 
 /* maximum card clock frequency (default 50MHz) */
 module_param(maxfreq, int, 0);
diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c
index 4efe302..4fdc711 100644
--- a/drivers/mmc/host/mxs-mmc.c
+++ b/drivers/mmc/host/mxs-mmc.c
@@ -548,22 +548,6 @@ static const struct mmc_host_ops mxs_mmc_ops = {
 	.enable_sdio_irq = mxs_mmc_enable_sdio_irq,
 };
 
-static bool mxs_mmc_dma_filter(struct dma_chan *chan, void *param)
-{
-	struct mxs_mmc_host *host = param;
-	struct mxs_ssp *ssp = &host->ssp;
-
-	if (!mxs_dma_is_apbh(chan))
-		return false;
-
-	if (chan->chan_id != ssp->dma_channel)
-		return false;
-
-	chan->private = &ssp->dma_data;
-
-	return true;
-}
-
 static struct platform_device_id mxs_ssp_ids[] = {
 	{
 		.name = "imx23-mmc",
@@ -591,20 +575,17 @@ static int mxs_mmc_probe(struct platform_device *pdev)
 	struct device_node *np = pdev->dev.of_node;
 	struct mxs_mmc_host *host;
 	struct mmc_host *mmc;
-	struct resource *iores, *dmares;
+	struct resource *iores;
 	struct pinctrl *pinctrl;
-	int ret = 0, irq_err, irq_dma;
-	dma_cap_mask_t mask;
+	int ret = 0, irq_err;
 	struct regulator *reg_vmmc;
 	enum of_gpio_flags flags;
 	struct mxs_ssp *ssp;
 	u32 bus_width = 0;
 
 	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0);
 	irq_err = platform_get_irq(pdev, 0);
-	irq_dma = platform_get_irq(pdev, 1);
-	if (!iores || irq_err < 0 || irq_dma < 0)
+	if (!iores || irq_err < 0)
 		return -EINVAL;
 
 	mmc = mmc_alloc_host(sizeof(struct mxs_mmc_host), &pdev->dev);
@@ -620,23 +601,7 @@ static int mxs_mmc_probe(struct platform_device *pdev)
 		goto out_mmc_free;
 	}
 
-	if (np) {
-		ssp->devid = (enum mxs_ssp_id) of_id->data;
-		/*
-		 * TODO: This is a temporary solution and should be changed
-		 * to use generic DMA binding later when the helpers get in.
-		 */
-		ret = of_property_read_u32(np, "fsl,ssp-dma-channel",
-					   &ssp->dma_channel);
-		if (ret) {
-			dev_err(mmc_dev(host->mmc),
-				"failed to get dma channel\n");
-			goto out_mmc_free;
-		}
-	} else {
-		ssp->devid = pdev->id_entry->driver_data;
-		ssp->dma_channel = dmares->start;
-	}
+	ssp->devid = (enum mxs_ssp_id) of_id->data;
 
 	host->mmc = mmc;
 	host->sdio_irq_en = 0;
@@ -666,10 +631,7 @@ static int mxs_mmc_probe(struct platform_device *pdev)
 
 	mxs_mmc_reset(host);
 
-	dma_cap_zero(mask);
-	dma_cap_set(DMA_SLAVE, mask);
-	ssp->dma_data.chan_irq = irq_dma;
-	ssp->dmach = dma_request_channel(mask, mxs_mmc_dma_filter, host);
+	ssp->dmach = dma_request_slave_channel(&pdev->dev, "rx-tx");
 	if (!ssp->dmach) {
 		dev_err(mmc_dev(host->mmc),
 			"%s: failed to request dma\n", __func__);
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index bc58078..6e44025 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -1717,6 +1717,12 @@ static struct omap_mmc_platform_data *of_get_hsmmc_pdata(struct device *dev)
 	struct omap_mmc_platform_data *pdata;
 	struct device_node *np = dev->of_node;
 	u32 bus_width, max_freq;
+	int cd_gpio, wp_gpio;
+
+	cd_gpio = of_get_named_gpio(np, "cd-gpios", 0);
+	wp_gpio = of_get_named_gpio(np, "wp-gpios", 0);
+	if (cd_gpio == -EPROBE_DEFER || wp_gpio == -EPROBE_DEFER)
+		return ERR_PTR(-EPROBE_DEFER);
 
 	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
 	if (!pdata)
@@ -1727,8 +1733,8 @@ static struct omap_mmc_platform_data *of_get_hsmmc_pdata(struct device *dev)
 
 	/* This driver only supports 1 slot */
 	pdata->nr_slots = 1;
-	pdata->slots[0].switch_pin = of_get_named_gpio(np, "cd-gpios", 0);
-	pdata->slots[0].gpio_wp = of_get_named_gpio(np, "wp-gpios", 0);
+	pdata->slots[0].switch_pin = cd_gpio;
+	pdata->slots[0].gpio_wp = wp_gpio;
 
 	if (of_find_property(np, "ti,non-removable", NULL)) {
 		pdata->slots[0].nonremovable = true;
@@ -1774,6 +1780,10 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
 	match = of_match_device(of_match_ptr(omap_mmc_of_match), &pdev->dev);
 	if (match) {
 		pdata = of_get_hsmmc_pdata(&pdev->dev);
+
+		if (IS_ERR(pdata))
+			return PTR_ERR(pdata);
+
 		if (match->data) {
 			const u16 *offsetp = match->data;
 			pdata->reg_offset = *offsetp;
diff --git a/drivers/mmc/host/rtsx_pci_sdmmc.c b/drivers/mmc/host/rtsx_pci_sdmmc.c
index f981f7d..ad13f42 100644
--- a/drivers/mmc/host/rtsx_pci_sdmmc.c
+++ b/drivers/mmc/host/rtsx_pci_sdmmc.c
@@ -57,6 +57,9 @@ struct realtek_pci_sdmmc {
 	bool			eject;
 	bool			initial_mode;
 	bool			ddr_mode;
+	int			power_state;
+#define SDMMC_POWER_ON		1
+#define SDMMC_POWER_OFF		0
 };
 
 static inline struct device *sdmmc_dev(struct realtek_pci_sdmmc *host)
@@ -765,6 +768,9 @@ static int sd_power_on(struct realtek_pci_sdmmc *host)
 	struct rtsx_pcr *pcr = host->pcr;
 	int err;
 
+	if (host->power_state == SDMMC_POWER_ON)
+		return 0;
+
 	rtsx_pci_init_cmd(pcr);
 	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_SELECT, 0x07, SD_MOD_SEL);
 	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_SHARE_MODE,
@@ -787,6 +793,7 @@ static int sd_power_on(struct realtek_pci_sdmmc *host)
 	if (err < 0)
 		return err;
 
+	host->power_state = SDMMC_POWER_ON;
 	return 0;
 }
 
@@ -795,6 +802,8 @@ static int sd_power_off(struct realtek_pci_sdmmc *host)
 	struct rtsx_pcr *pcr = host->pcr;
 	int err;
 
+	host->power_state = SDMMC_POWER_OFF;
+
 	rtsx_pci_init_cmd(pcr);
 
 	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_CLK_EN, SD_CLK_EN, 0);
@@ -1260,6 +1269,7 @@ static int rtsx_pci_sdmmc_drv_probe(struct platform_device *pdev)
 	host->pcr = pcr;
 	host->mmc = mmc;
 	host->pdev = pdev;
+	host->power_state = SDMMC_POWER_OFF;
 	platform_set_drvdata(pdev, host);
 	pcr->slots[RTSX_SD_CARD].p_dev = pdev;
 	pcr->slots[RTSX_SD_CARD].card_event = rtsx_pci_sdmmc_card_event;
diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c
index 63fb265..8d6794c 100644
--- a/drivers/mmc/host/s3cmci.c
+++ b/drivers/mmc/host/s3cmci.c
@@ -25,14 +25,93 @@
 
 #include <mach/dma.h>
 
-#include <mach/regs-sdi.h>
-
 #include <linux/platform_data/mmc-s3cmci.h>
 
 #include "s3cmci.h"
 
 #define DRIVER_NAME "s3c-mci"
 
+#define S3C2410_SDICON			(0x00)
+#define S3C2410_SDIPRE			(0x04)
+#define S3C2410_SDICMDARG		(0x08)
+#define S3C2410_SDICMDCON		(0x0C)
+#define S3C2410_SDICMDSTAT		(0x10)
+#define S3C2410_SDIRSP0			(0x14)
+#define S3C2410_SDIRSP1			(0x18)
+#define S3C2410_SDIRSP2			(0x1C)
+#define S3C2410_SDIRSP3			(0x20)
+#define S3C2410_SDITIMER		(0x24)
+#define S3C2410_SDIBSIZE		(0x28)
+#define S3C2410_SDIDCON			(0x2C)
+#define S3C2410_SDIDCNT			(0x30)
+#define S3C2410_SDIDSTA			(0x34)
+#define S3C2410_SDIFSTA			(0x38)
+
+#define S3C2410_SDIDATA			(0x3C)
+#define S3C2410_SDIIMSK			(0x40)
+
+#define S3C2440_SDIDATA			(0x40)
+#define S3C2440_SDIIMSK			(0x3C)
+
+#define S3C2440_SDICON_SDRESET		(1 << 8)
+#define S3C2410_SDICON_SDIOIRQ		(1 << 3)
+#define S3C2410_SDICON_FIFORESET	(1 << 1)
+#define S3C2410_SDICON_CLOCKTYPE	(1 << 0)
+
+#define S3C2410_SDICMDCON_LONGRSP	(1 << 10)
+#define S3C2410_SDICMDCON_WAITRSP	(1 << 9)
+#define S3C2410_SDICMDCON_CMDSTART	(1 << 8)
+#define S3C2410_SDICMDCON_SENDERHOST	(1 << 6)
+#define S3C2410_SDICMDCON_INDEX		(0x3f)
+
+#define S3C2410_SDICMDSTAT_CRCFAIL	(1 << 12)
+#define S3C2410_SDICMDSTAT_CMDSENT	(1 << 11)
+#define S3C2410_SDICMDSTAT_CMDTIMEOUT	(1 << 10)
+#define S3C2410_SDICMDSTAT_RSPFIN	(1 << 9)
+
+#define S3C2440_SDIDCON_DS_WORD		(2 << 22)
+#define S3C2410_SDIDCON_TXAFTERRESP	(1 << 20)
+#define S3C2410_SDIDCON_RXAFTERCMD	(1 << 19)
+#define S3C2410_SDIDCON_BLOCKMODE	(1 << 17)
+#define S3C2410_SDIDCON_WIDEBUS		(1 << 16)
+#define S3C2410_SDIDCON_DMAEN		(1 << 15)
+#define S3C2410_SDIDCON_STOP		(1 << 14)
+#define S3C2440_SDIDCON_DATSTART	(1 << 14)
+
+#define S3C2410_SDIDCON_XFER_RXSTART	(2 << 12)
+#define S3C2410_SDIDCON_XFER_TXSTART	(3 << 12)
+
+#define S3C2410_SDIDCON_BLKNUM_MASK	(0xFFF)
+
+#define S3C2410_SDIDSTA_SDIOIRQDETECT	(1 << 9)
+#define S3C2410_SDIDSTA_FIFOFAIL	(1 << 8)
+#define S3C2410_SDIDSTA_CRCFAIL		(1 << 7)
+#define S3C2410_SDIDSTA_RXCRCFAIL	(1 << 6)
+#define S3C2410_SDIDSTA_DATATIMEOUT	(1 << 5)
+#define S3C2410_SDIDSTA_XFERFINISH	(1 << 4)
+#define S3C2410_SDIDSTA_TXDATAON	(1 << 1)
+#define S3C2410_SDIDSTA_RXDATAON	(1 << 0)
+
+#define S3C2440_SDIFSTA_FIFORESET	(1 << 16)
+#define S3C2440_SDIFSTA_FIFOFAIL	(3 << 14)
+#define S3C2410_SDIFSTA_TFDET		(1 << 13)
+#define S3C2410_SDIFSTA_RFDET		(1 << 12)
+#define S3C2410_SDIFSTA_COUNTMASK	(0x7f)
+
+#define S3C2410_SDIIMSK_RESPONSECRC	(1 << 17)
+#define S3C2410_SDIIMSK_CMDSENT		(1 << 16)
+#define S3C2410_SDIIMSK_CMDTIMEOUT	(1 << 15)
+#define S3C2410_SDIIMSK_RESPONSEND	(1 << 14)
+#define S3C2410_SDIIMSK_SDIOIRQ		(1 << 12)
+#define S3C2410_SDIIMSK_FIFOFAIL	(1 << 11)
+#define S3C2410_SDIIMSK_CRCSTATUS	(1 << 10)
+#define S3C2410_SDIIMSK_DATACRC		(1 << 9)
+#define S3C2410_SDIIMSK_DATATIMEOUT	(1 << 8)
+#define S3C2410_SDIIMSK_DATAFINISH	(1 << 7)
+#define S3C2410_SDIIMSK_TXFIFOHALF	(1 << 4)
+#define S3C2410_SDIIMSK_RXFIFOLAST	(1 << 2)
+#define S3C2410_SDIIMSK_RXFIFOHALF	(1 << 0)
+
 enum dbg_channels {
 	dbg_err   = (1 << 0),
 	dbg_debug = (1 << 1),
diff --git a/drivers/mmc/host/sdhci-bcm2835.c b/drivers/mmc/host/sdhci-bcm2835.c
index 8ffea05..d49bc95 100644
--- a/drivers/mmc/host/sdhci-bcm2835.c
+++ b/drivers/mmc/host/sdhci-bcm2835.c
@@ -124,7 +124,7 @@ unsigned int bcm2835_sdhci_get_min_clock(struct sdhci_host *host)
 	return MIN_FREQ;
 }
 
-static struct sdhci_ops bcm2835_sdhci_ops = {
+static const struct sdhci_ops bcm2835_sdhci_ops = {
 	.write_l = bcm2835_sdhci_writel,
 	.write_w = bcm2835_sdhci_writew,
 	.write_b = bcm2835_sdhci_writeb,
@@ -135,7 +135,7 @@ static struct sdhci_ops bcm2835_sdhci_ops = {
 	.get_min_clock = bcm2835_sdhci_get_min_clock,
 };
 
-static struct sdhci_pltfm_data bcm2835_sdhci_pdata = {
+static const struct sdhci_pltfm_data bcm2835_sdhci_pdata = {
 	.quirks = SDHCI_QUIRK_BROKEN_CARD_DETECTION |
 		  SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK,
 	.ops = &bcm2835_sdhci_ops,
diff --git a/drivers/mmc/host/sdhci-cns3xxx.c b/drivers/mmc/host/sdhci-cns3xxx.c
index 30bfdc4..8ebb6b6 100644
--- a/drivers/mmc/host/sdhci-cns3xxx.c
+++ b/drivers/mmc/host/sdhci-cns3xxx.c
@@ -16,7 +16,6 @@
 #include <linux/device.h>
 #include <linux/mmc/host.h>
 #include <linux/module.h>
-#include <mach/cns3xxx.h>
 #include "sdhci-pltfm.h"
 
 static unsigned int sdhci_cns3xxx_get_max_clk(struct sdhci_host *host)
@@ -80,12 +79,12 @@ out:
 	host->clock = clock;
 }
 
-static struct sdhci_ops sdhci_cns3xxx_ops = {
+static const struct sdhci_ops sdhci_cns3xxx_ops = {
 	.get_max_clock	= sdhci_cns3xxx_get_max_clk,
 	.set_clock	= sdhci_cns3xxx_set_clock,
 };
 
-static struct sdhci_pltfm_data sdhci_cns3xxx_pdata = {
+static const struct sdhci_pltfm_data sdhci_cns3xxx_pdata = {
 	.ops = &sdhci_cns3xxx_ops,
 	.quirks = SDHCI_QUIRK_BROKEN_DMA |
 		  SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
diff --git a/drivers/mmc/host/sdhci-dove.c b/drivers/mmc/host/sdhci-dove.c
index 169fab9..15e7803 100644
--- a/drivers/mmc/host/sdhci-dove.c
+++ b/drivers/mmc/host/sdhci-dove.c
@@ -83,12 +83,12 @@ static u32 sdhci_dove_readl(struct sdhci_host *host, int reg)
 	return ret;
 }
 
-static struct sdhci_ops sdhci_dove_ops = {
+static const struct sdhci_ops sdhci_dove_ops = {
 	.read_w	= sdhci_dove_readw,
 	.read_l	= sdhci_dove_readl,
 };
 
-static struct sdhci_pltfm_data sdhci_dove_pdata = {
+static const struct sdhci_pltfm_data sdhci_dove_pdata = {
 	.ops	= &sdhci_dove_ops,
 	.quirks	= SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER |
 		  SDHCI_QUIRK_NO_BUSY_IRQ |
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 78ac002..67d6dde 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -399,7 +399,7 @@ static int esdhc_pltfm_bus_width(struct sdhci_host *host, int width)
 	return 0;
 }
 
-static struct sdhci_ops sdhci_esdhc_ops = {
+static const struct sdhci_ops sdhci_esdhc_ops = {
 	.read_l = esdhc_readl_le,
 	.read_w = esdhc_readw_le,
 	.write_l = esdhc_writel_le,
@@ -412,7 +412,7 @@ static struct sdhci_ops sdhci_esdhc_ops = {
 	.platform_bus_width = esdhc_pltfm_bus_width,
 };
 
-static struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
+static const struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
 	.quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_NO_HISPD_BIT
 			| SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC
 			| SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
index f32526d..5e68adc 100644
--- a/drivers/mmc/host/sdhci-of-esdhc.c
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
@@ -230,7 +230,7 @@ static void esdhc_of_platform_init(struct sdhci_host *host)
 		host->quirks &= ~SDHCI_QUIRK_NO_BUSY_IRQ;
 }
 
-static struct sdhci_ops sdhci_esdhc_ops = {
+static const struct sdhci_ops sdhci_esdhc_ops = {
 	.read_l = esdhc_readl,
 	.read_w = esdhc_readw,
 	.read_b = esdhc_readb,
@@ -249,7 +249,7 @@ static struct sdhci_ops sdhci_esdhc_ops = {
 	.adma_workaround = esdhci_of_adma_workaround,
 };
 
-static struct sdhci_pltfm_data sdhci_esdhc_pdata = {
+static const struct sdhci_pltfm_data sdhci_esdhc_pdata = {
 	/*
 	 * card detection could be handled via GPIO
 	 * eSDHC cannot support End Attribute in NOP ADMA descriptor
diff --git a/drivers/mmc/host/sdhci-of-hlwd.c b/drivers/mmc/host/sdhci-of-hlwd.c
index c3d3715..200a6a9 100644
--- a/drivers/mmc/host/sdhci-of-hlwd.c
+++ b/drivers/mmc/host/sdhci-of-hlwd.c
@@ -51,7 +51,7 @@ static void sdhci_hlwd_writeb(struct sdhci_host *host, u8 val, int reg)
 	udelay(SDHCI_HLWD_WRITE_DELAY);
 }
 
-static struct sdhci_ops sdhci_hlwd_ops = {
+static const struct sdhci_ops sdhci_hlwd_ops = {
 	.read_l = sdhci_be32bs_readl,
 	.read_w = sdhci_be32bs_readw,
 	.read_b = sdhci_be32bs_readb,
@@ -60,7 +60,7 @@ static struct sdhci_ops sdhci_hlwd_ops = {
 	.write_b = sdhci_hlwd_writeb,
 };
 
-static struct sdhci_pltfm_data sdhci_hlwd_pdata = {
+static const struct sdhci_pltfm_data sdhci_hlwd_pdata = {
 	.quirks = SDHCI_QUIRK_32BIT_DMA_ADDR |
 		  SDHCI_QUIRK_32BIT_DMA_SIZE,
 	.ops = &sdhci_hlwd_ops,
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c
index c7ccf30..c1f0372 100644
--- a/drivers/mmc/host/sdhci-pci.c
+++ b/drivers/mmc/host/sdhci-pci.c
@@ -975,7 +975,7 @@ static void sdhci_pci_hw_reset(struct sdhci_host *host)
 	usleep_range(300, 1000);
 }
 
-static struct sdhci_ops sdhci_pci_ops = {
+static const struct sdhci_ops sdhci_pci_ops = {
 	.enable_dma	= sdhci_pci_enable_dma,
 	.platform_bus_width	= sdhci_pci_bus_width,
 	.hw_reset		= sdhci_pci_hw_reset,
@@ -1279,6 +1279,7 @@ static struct sdhci_pci_slot *sdhci_pci_probe_slot(
 	}
 
 	host->mmc->pm_caps = MMC_PM_KEEP_POWER | MMC_PM_WAKE_SDIO_IRQ;
+	host->mmc->slotno = slotno;
 
 	ret = sdhci_add_host(host);
 	if (ret)
diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c
index 3145a78..cd0f1f6 100644
--- a/drivers/mmc/host/sdhci-pltfm.c
+++ b/drivers/mmc/host/sdhci-pltfm.c
@@ -44,7 +44,7 @@ unsigned int sdhci_pltfm_clk_get_max_clock(struct sdhci_host *host)
 }
 EXPORT_SYMBOL_GPL(sdhci_pltfm_clk_get_max_clock);
 
-static struct sdhci_ops sdhci_pltfm_ops = {
+static const struct sdhci_ops sdhci_pltfm_ops = {
 };
 
 #ifdef CONFIG_OF
@@ -94,6 +94,7 @@ void sdhci_get_of_property(struct platform_device *pdev)
 
 		if (of_device_is_compatible(np, "fsl,p2020-esdhc") ||
 		    of_device_is_compatible(np, "fsl,p1010-esdhc") ||
+		    of_device_is_compatible(np, "fsl,t4240-esdhc") ||
 		    of_device_is_compatible(np, "fsl,mpc8536-esdhc"))
 			host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
 
@@ -114,7 +115,7 @@ void sdhci_get_of_property(struct platform_device *pdev) {}
 EXPORT_SYMBOL_GPL(sdhci_get_of_property);
 
 struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev,
-				    struct sdhci_pltfm_data *pdata)
+				    const struct sdhci_pltfm_data *pdata)
 {
 	struct sdhci_host *host;
 	struct sdhci_pltfm_host *pltfm_host;
@@ -201,7 +202,7 @@ void sdhci_pltfm_free(struct platform_device *pdev)
 EXPORT_SYMBOL_GPL(sdhci_pltfm_free);
 
 int sdhci_pltfm_register(struct platform_device *pdev,
-			 struct sdhci_pltfm_data *pdata)
+			 const struct sdhci_pltfm_data *pdata)
 {
 	struct sdhci_host *host;
 	int ret = 0;
diff --git a/drivers/mmc/host/sdhci-pltfm.h b/drivers/mmc/host/sdhci-pltfm.h
index 153b6c5..1210ed1 100644
--- a/drivers/mmc/host/sdhci-pltfm.h
+++ b/drivers/mmc/host/sdhci-pltfm.h
@@ -16,7 +16,7 @@
 #include "sdhci.h"
 
 struct sdhci_pltfm_data {
-	struct sdhci_ops *ops;
+	const struct sdhci_ops *ops;
 	unsigned int quirks;
 };
 
@@ -91,11 +91,11 @@ static inline void sdhci_be32bs_writeb(struct sdhci_host *host, u8 val, int reg)
 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);
+					  const 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);
+				const struct sdhci_pltfm_data *pdata);
 extern int sdhci_pltfm_unregister(struct platform_device *pdev);
 
 extern unsigned int sdhci_pltfm_clk_get_max_clock(struct sdhci_host *host);
diff --git a/drivers/mmc/host/sdhci-pxav2.c b/drivers/mmc/host/sdhci-pxav2.c
index eeb7d43..6a3f702 100644
--- a/drivers/mmc/host/sdhci-pxav2.c
+++ b/drivers/mmc/host/sdhci-pxav2.c
@@ -111,7 +111,7 @@ static int pxav2_mmc_set_width(struct sdhci_host *host, int width)
 	return 0;
 }
 
-static struct sdhci_ops pxav2_sdhci_ops = {
+static const struct sdhci_ops pxav2_sdhci_ops = {
 	.get_max_clock = sdhci_pltfm_clk_get_max_clock,
 	.platform_reset_exit = pxav2_set_private_registers,
 	.platform_bus_width = pxav2_mmc_set_width,
diff --git a/drivers/mmc/host/sdhci-pxav3.c b/drivers/mmc/host/sdhci-pxav3.c
index a0cdbc5..1ae358e 100644
--- a/drivers/mmc/host/sdhci-pxav3.c
+++ b/drivers/mmc/host/sdhci-pxav3.c
@@ -167,13 +167,21 @@ static int pxav3_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
 	return 0;
 }
 
-static struct sdhci_ops pxav3_sdhci_ops = {
+static const 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,
 	.get_max_clock = sdhci_pltfm_clk_get_max_clock,
 };
 
+static struct sdhci_pltfm_data sdhci_pxav3_pdata = {
+	.quirks = SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK
+		| SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC
+		| SDHCI_QUIRK_32BIT_ADMA_SIZE
+		| SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
+	.ops = &pxav3_sdhci_ops,
+};
+
 #ifdef CONFIG_OF
 static const struct of_device_id sdhci_pxav3_of_match[] = {
 	{
@@ -187,29 +195,16 @@ static struct sdhci_pxa_platdata *pxav3_get_mmc_pdata(struct device *dev)
 {
 	struct sdhci_pxa_platdata *pdata;
 	struct device_node *np = dev->of_node;
-	u32 bus_width;
 	u32 clk_delay_cycles;
-	enum of_gpio_flags gpio_flags;
 
 	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
 	if (!pdata)
 		return NULL;
 
-	if (of_find_property(np, "non-removable", NULL))
-		pdata->flags |= PXA_FLAG_CARD_PERMANENT;
-
-	of_property_read_u32(np, "bus-width", &bus_width);
-	if (bus_width == 8)
-		pdata->flags |= PXA_FLAG_SD_8_BIT_CAPABLE_SLOT;
-
 	of_property_read_u32(np, "mrvl,clk-delay-cycles", &clk_delay_cycles);
 	if (clk_delay_cycles > 0)
 		pdata->clk_delay_cycles = clk_delay_cycles;
 
-	pdata->ext_cd_gpio = of_get_named_gpio_flags(np, "cd-gpios", 0, &gpio_flags);
-	if (gpio_flags != OF_GPIO_ACTIVE_LOW)
-		pdata->host_caps2 |= MMC_CAP2_CD_ACTIVE_HIGH;
-
 	return pdata;
 }
 #else
@@ -235,7 +230,7 @@ static int sdhci_pxav3_probe(struct platform_device *pdev)
 	if (!pxa)
 		return -ENOMEM;
 
-	host = sdhci_pltfm_init(pdev, NULL);
+	host = sdhci_pltfm_init(pdev, &sdhci_pxav3_pdata);
 	if (IS_ERR(host)) {
 		kfree(pxa);
 		return PTR_ERR(host);
@@ -252,24 +247,18 @@ static int sdhci_pxav3_probe(struct platform_device *pdev)
 	pltfm_host->clk = clk;
 	clk_prepare_enable(clk);
 
-	host->quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL
-		| SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC
-		| SDHCI_QUIRK_32BIT_ADMA_SIZE
-		| SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN;
-
 	/* enable 1/8V DDR capable */
 	host->mmc->caps |= MMC_CAP_1_8V_DDR;
 
 	match = of_match_device(of_match_ptr(sdhci_pxav3_of_match), &pdev->dev);
-	if (match)
+	if (match) {
+		mmc_of_parse(host->mmc);
+		sdhci_get_of_property(pdev);
 		pdata = pxav3_get_mmc_pdata(dev);
-
-	if (pdata) {
-		if (pdata->flags & PXA_FLAG_CARD_PERMANENT) {
-			/* on-chip device */
-			host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION;
+	} else if (pdata) {
+		/* on-chip device */
+		if (pdata->flags & PXA_FLAG_CARD_PERMANENT)
 			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)
@@ -296,10 +285,6 @@ static int sdhci_pxav3_probe(struct platform_device *pdev)
 		}
 	}
 
-	host->ops = &pxav3_sdhci_ops;
-
-	sdhci_get_of_property(pdev);
-
 	pm_runtime_set_active(&pdev->dev);
 	pm_runtime_enable(&pdev->dev);
 	pm_runtime_set_autosuspend_delay(&pdev->dev, PXAV3_RPM_DELAY_MS);
@@ -317,7 +302,7 @@ static int sdhci_pxav3_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, host);
 
-	if (pdata->pm_caps & MMC_PM_KEEP_POWER) {
+	if (host->mmc->pm_caps & MMC_PM_KEEP_POWER) {
 		device_init_wakeup(&pdev->dev, 1);
 		host->mmc->pm_flags |= MMC_PM_WAKE_SDIO_IRQ;
 	} else {
diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c
index 7363efe..8cd966d 100644
--- a/drivers/mmc/host/sdhci-s3c.c
+++ b/drivers/mmc/host/sdhci-s3c.c
@@ -24,7 +24,6 @@
 #include <linux/of_gpio.h>
 #include <linux/pm.h>
 #include <linux/pm_runtime.h>
-#include <linux/pinctrl/consumer.h>
 
 #include <linux/mmc/host.h>
 
@@ -45,7 +44,6 @@
  * @ioarea: The resource created when we claimed the IO area.
  * @pdata: The platform data for this controller.
  * @cur_clk: The index of the current bus clock.
- * @gpios: List of gpio numbers parsed from device tree.
  * @clk_io: The clock for the internal bus interface.
  * @clk_bus: The clocks that are available for the SD/MMC bus clock.
  */
@@ -57,8 +55,6 @@ struct sdhci_s3c {
 	unsigned int		cur_clk;
 	int			ext_cd_irq;
 	int			ext_cd_gpio;
-	int			*gpios;
-	struct pinctrl          *pctrl;
 
 	struct clk		*clk_io;
 	struct clk		*clk_bus[MAX_BUS_CLK];
@@ -447,88 +443,39 @@ static int sdhci_s3c_parse_dt(struct device *dev,
 	struct device_node *node = dev->of_node;
 	struct sdhci_s3c *ourhost = to_s3c(host);
 	u32 max_width;
-	int gpio, cnt, ret;
+	int gpio;
 
 	/* if the bus-width property is not specified, assume width as 1 */
 	if (of_property_read_u32(node, "bus-width", &max_width))
 		max_width = 1;
 	pdata->max_width = max_width;
 
-	ourhost->gpios = devm_kzalloc(dev, NUM_GPIOS(pdata->max_width) *
-				sizeof(int), GFP_KERNEL);
-	if (!ourhost->gpios)
-		return -ENOMEM;
-
 	/* get the card detection method */
 	if (of_get_property(node, "broken-cd", NULL)) {
 		pdata->cd_type = S3C_SDHCI_CD_NONE;
-		goto setup_bus;
+		return 0;
 	}
 
 	if (of_get_property(node, "non-removable", NULL)) {
 		pdata->cd_type = S3C_SDHCI_CD_PERMANENT;
-		goto setup_bus;
+		return 0;
 	}
 
 	gpio = of_get_named_gpio(node, "cd-gpios", 0);
 	if (gpio_is_valid(gpio)) {
 		pdata->cd_type = S3C_SDHCI_CD_GPIO;
-		goto found_cd;
-	} else if (gpio != -ENOENT) {
-		dev_err(dev, "invalid card detect gpio specified\n");
-		return -EINVAL;
-	}
-
-	gpio = of_get_named_gpio(node, "samsung,cd-pinmux-gpio", 0);
-	if (gpio_is_valid(gpio)) {
-		pdata->cd_type = S3C_SDHCI_CD_INTERNAL;
-		goto found_cd;
-	} else if (gpio != -ENOENT) {
-		dev_err(dev, "invalid card detect gpio specified\n");
-		return -EINVAL;
-	}
-
-	/* assuming internal card detect that will be configured by pinctrl */
-	pdata->cd_type = S3C_SDHCI_CD_INTERNAL;
-	goto setup_bus;
-
- found_cd:
-	if (pdata->cd_type == S3C_SDHCI_CD_GPIO) {
 		pdata->ext_cd_gpio = gpio;
 		ourhost->ext_cd_gpio = -1;
 		if (of_get_property(node, "cd-inverted", NULL))
 			pdata->ext_cd_gpio_invert = 1;
-	} else if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
-		ret = devm_gpio_request(dev, gpio, "sdhci-cd");
-		if (ret) {
-			dev_err(dev, "card detect gpio request failed\n");
-			return -EINVAL;
-		}
-		ourhost->ext_cd_gpio = gpio;
-	}
-
- setup_bus:
-	if (!IS_ERR(ourhost->pctrl))
 		return 0;
-
-	/* get the gpios for command, clock and data lines */
-	for (cnt = 0; cnt < NUM_GPIOS(pdata->max_width); cnt++) {
-		gpio = of_get_gpio(node, cnt);
-		if (!gpio_is_valid(gpio)) {
-			dev_err(dev, "invalid gpio[%d]\n", cnt);
-			return -EINVAL;
-		}
-		ourhost->gpios[cnt] = gpio;
-	}
-
-	for (cnt = 0; cnt < NUM_GPIOS(pdata->max_width); cnt++) {
-		ret = devm_gpio_request(dev, ourhost->gpios[cnt], "sdhci-gpio");
-		if (ret) {
-			dev_err(dev, "gpio[%d] request failed\n", cnt);
-			return -EINVAL;
-		}
+	} else if (gpio != -ENOENT) {
+		dev_err(dev, "invalid card detect gpio specified\n");
+		return -EINVAL;
 	}
 
+	/* assuming internal card detect that will be configured by pinctrl */
+	pdata->cd_type = S3C_SDHCI_CD_INTERNAL;
 	return 0;
 }
 #else
@@ -589,8 +536,6 @@ static int sdhci_s3c_probe(struct platform_device *pdev)
 		goto err_pdata_io_clk;
 	}
 
-	sc->pctrl = devm_pinctrl_get_select_default(&pdev->dev);
-
 	if (pdev->dev.of_node) {
 		ret = sdhci_s3c_parse_dt(&pdev->dev, host, pdata);
 		if (ret)
@@ -608,7 +553,7 @@ static int sdhci_s3c_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, host);
 
-	sc->clk_io = clk_get(dev, "hsmmc");
+	sc->clk_io = devm_clk_get(dev, "hsmmc");
 	if (IS_ERR(sc->clk_io)) {
 		dev_err(dev, "failed to get io clock\n");
 		ret = PTR_ERR(sc->clk_io);
@@ -623,7 +568,7 @@ static int sdhci_s3c_probe(struct platform_device *pdev)
 		char name[14];
 
 		snprintf(name, 14, "mmc_busclk.%d", ptr);
-		clk = clk_get(dev, name);
+		clk = devm_clk_get(dev, name);
 		if (IS_ERR(clk))
 			continue;
 
@@ -764,15 +709,9 @@ static int sdhci_s3c_probe(struct platform_device *pdev)
 #ifndef CONFIG_PM_RUNTIME
 	clk_disable_unprepare(sc->clk_bus[sc->cur_clk]);
 #endif
-	for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) {
-		if (sc->clk_bus[ptr]) {
-			clk_put(sc->clk_bus[ptr]);
-		}
-	}
 
  err_no_busclks:
 	clk_disable_unprepare(sc->clk_io);
-	clk_put(sc->clk_io);
 
  err_pdata_io_clk:
 	sdhci_free_host(host);
@@ -785,7 +724,6 @@ static int sdhci_s3c_remove(struct platform_device *pdev)
 	struct sdhci_host *host =  platform_get_drvdata(pdev);
 	struct sdhci_s3c *sc = sdhci_priv(host);
 	struct s3c_sdhci_platdata *pdata = sc->pdata;
-	int ptr;
 
 	if (pdata->cd_type == S3C_SDHCI_CD_EXTERNAL && pdata->ext_cd_cleanup)
 		pdata->ext_cd_cleanup(&sdhci_s3c_notify_change);
@@ -805,13 +743,7 @@ static int sdhci_s3c_remove(struct platform_device *pdev)
 #ifndef CONFIG_PM_RUNTIME
 	clk_disable_unprepare(sc->clk_bus[sc->cur_clk]);
 #endif
-	for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) {
-		if (sc->clk_bus[ptr]) {
-			clk_put(sc->clk_bus[ptr]);
-		}
-	}
 	clk_disable_unprepare(sc->clk_io);
-	clk_put(sc->clk_io);
 
 	sdhci_free_host(host);
 	platform_set_drvdata(pdev, NULL);
diff --git a/drivers/mmc/host/sdhci-sirf.c b/drivers/mmc/host/sdhci-sirf.c
new file mode 100644
index 0000000..09805af
--- /dev/null
+++ b/drivers/mmc/host/sdhci-sirf.c
@@ -0,0 +1,193 @@
+/*
+ * SDHCI support for SiRF primaII and marco SoCs
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/mmc/host.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/mmc/slot-gpio.h>
+#include <linux/pinctrl/consumer.h>
+#include "sdhci-pltfm.h"
+
+struct sdhci_sirf_priv {
+	struct clk *clk;
+	int gpio_cd;
+};
+
+static unsigned int sdhci_sirf_get_max_clk(struct sdhci_host *host)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_sirf_priv *priv = pltfm_host->priv;
+	return clk_get_rate(priv->clk);
+}
+
+static struct sdhci_ops sdhci_sirf_ops = {
+	.get_max_clock	= sdhci_sirf_get_max_clk,
+};
+
+static struct sdhci_pltfm_data sdhci_sirf_pdata = {
+	.ops = &sdhci_sirf_ops,
+	.quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
+		SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
+		SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN |
+		SDHCI_QUIRK_INVERTED_WRITE_PROTECT |
+		SDHCI_QUIRK_DELAY_AFTER_POWER,
+};
+
+static int sdhci_sirf_probe(struct platform_device *pdev)
+{
+	struct sdhci_host *host;
+	struct sdhci_pltfm_host *pltfm_host;
+	struct sdhci_sirf_priv *priv;
+	struct pinctrl *pinctrl;
+	int ret;
+
+	pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+	if (IS_ERR(pinctrl)) {
+		dev_err(&pdev->dev, "unable to get pinmux");
+		return PTR_ERR(pinctrl);
+	}
+
+	priv = devm_kzalloc(&pdev->dev, sizeof(struct sdhci_sirf_priv),
+		GFP_KERNEL);
+	if (!priv) {
+		dev_err(&pdev->dev, "unable to allocate private data");
+		return -ENOMEM;
+	}
+
+	priv->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(priv->clk)) {
+		dev_err(&pdev->dev, "unable to get clock");
+		return PTR_ERR(priv->clk);
+	}
+
+	if (pdev->dev.of_node) {
+		priv->gpio_cd = of_get_named_gpio(pdev->dev.of_node,
+			"cd-gpios", 0);
+	} else {
+		priv->gpio_cd = -EINVAL;
+	}
+
+	host = sdhci_pltfm_init(pdev, &sdhci_sirf_pdata);
+	if (IS_ERR(host)) {
+		ret = PTR_ERR(host);
+		goto err_sdhci_pltfm_init;
+	}
+
+	pltfm_host = sdhci_priv(host);
+	pltfm_host->priv = priv;
+
+	sdhci_get_of_property(pdev);
+
+	clk_prepare_enable(priv->clk);
+
+	ret = sdhci_add_host(host);
+	if (ret)
+		goto err_sdhci_add;
+
+	/*
+	 * We must request the IRQ after sdhci_add_host(), as the tasklet only
+	 * gets setup in sdhci_add_host() and we oops.
+	 */
+	if (gpio_is_valid(priv->gpio_cd)) {
+		ret = mmc_gpio_request_cd(host->mmc, priv->gpio_cd);
+		if (ret) {
+			dev_err(&pdev->dev, "card detect irq request failed: %d\n",
+				ret);
+			goto err_request_cd;
+		}
+	}
+
+	return 0;
+
+err_request_cd:
+	sdhci_remove_host(host, 0);
+err_sdhci_add:
+	clk_disable_unprepare(priv->clk);
+	sdhci_pltfm_free(pdev);
+err_sdhci_pltfm_init:
+	return ret;
+}
+
+static int sdhci_sirf_remove(struct platform_device *pdev)
+{
+	struct sdhci_host *host = platform_get_drvdata(pdev);
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_sirf_priv *priv = pltfm_host->priv;
+
+	sdhci_pltfm_unregister(pdev);
+
+	if (gpio_is_valid(priv->gpio_cd))
+		mmc_gpio_free_cd(host->mmc);
+
+	clk_disable_unprepare(priv->clk);
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int sdhci_sirf_suspend(struct device *dev)
+{
+	struct sdhci_host *host = dev_get_drvdata(dev);
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_sirf_priv *priv = pltfm_host->priv;
+	int ret;
+
+	ret = sdhci_suspend_host(host);
+	if (ret)
+		return ret;
+
+	clk_disable(priv->clk);
+
+	return 0;
+}
+
+static int sdhci_sirf_resume(struct device *dev)
+{
+	struct sdhci_host *host = dev_get_drvdata(dev);
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_sirf_priv *priv = pltfm_host->priv;
+	int ret;
+
+	ret = clk_enable(priv->clk);
+	if (ret) {
+		dev_dbg(dev, "Resume: Error enabling clock\n");
+		return ret;
+	}
+
+	return sdhci_resume_host(host);
+}
+
+static SIMPLE_DEV_PM_OPS(sdhci_sirf_pm_ops, sdhci_sirf_suspend, sdhci_sirf_resume);
+#endif
+
+static const struct of_device_id sdhci_sirf_of_match[] = {
+	{ .compatible = "sirf,prima2-sdhc" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, sdhci_sirf_of_match);
+
+static struct platform_driver sdhci_sirf_driver = {
+	.driver		= {
+		.name	= "sdhci-sirf",
+		.owner	= THIS_MODULE,
+		.of_match_table = sdhci_sirf_of_match,
+#ifdef CONFIG_PM_SLEEP
+		.pm	= &sdhci_sirf_pm_ops,
+#endif
+	},
+	.probe		= sdhci_sirf_probe,
+	.remove		= sdhci_sirf_remove,
+};
+
+module_platform_driver(sdhci_sirf_driver);
+
+MODULE_DESCRIPTION("SDHCI driver for SiRFprimaII/SiRFmarco");
+MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/mmc/host/sdhci-spear.c b/drivers/mmc/host/sdhci-spear.c
index c6ece0b..7ae5b3a 100644
--- a/drivers/mmc/host/sdhci-spear.c
+++ b/drivers/mmc/host/sdhci-spear.c
@@ -36,7 +36,7 @@ struct spear_sdhci {
 };
 
 /* sdhci ops */
-static struct sdhci_ops sdhci_pltfm_ops = {
+static const struct sdhci_ops sdhci_pltfm_ops = {
 	/* Nothing to do for now. */
 };
 
@@ -291,7 +291,7 @@ static int sdhci_remove(struct platform_device *pdev)
 	return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int sdhci_suspend(struct device *dev)
 {
 	struct sdhci_host *host = dev_get_drvdata(dev);
diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index 08b06e9..45048d1 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -24,6 +24,7 @@
 #include <linux/gpio.h>
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
+#include <linux/mmc/slot-gpio.h>
 
 #include <asm/gpio.h>
 
@@ -38,16 +39,13 @@
 #define NVQUIRK_ENABLE_SDHCI_SPEC_300	BIT(2)
 
 struct sdhci_tegra_soc_data {
-	struct sdhci_pltfm_data *pdata;
+	const struct sdhci_pltfm_data *pdata;
 	u32 nvquirks;
 };
 
 struct sdhci_tegra {
 	const struct sdhci_tegra_soc_data *soc_data;
-	int cd_gpio;
-	int wp_gpio;
 	int power_gpio;
-	int is_8bit;
 };
 
 static u32 tegra_sdhci_readl(struct sdhci_host *host, int reg)
@@ -107,23 +105,9 @@ static void tegra_sdhci_writel(struct sdhci_host *host, u32 val, int reg)
 
 static unsigned int tegra_sdhci_get_ro(struct sdhci_host *host)
 {
-	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
-	struct sdhci_tegra *tegra_host = pltfm_host->priv;
-
-	if (!gpio_is_valid(tegra_host->wp_gpio))
-		return -1;
-
-	return gpio_get_value(tegra_host->wp_gpio);
+	return mmc_gpio_get_ro(host->mmc);
 }
 
-static irqreturn_t carddetect_irq(int irq, void *data)
-{
-	struct sdhci_host *sdhost = (struct sdhci_host *)data;
-
-	tasklet_schedule(&sdhost->card_tasklet);
-	return IRQ_HANDLED;
-};
-
 static void tegra_sdhci_reset_exit(struct sdhci_host *host, u8 mask)
 {
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@@ -145,12 +129,11 @@ static void tegra_sdhci_reset_exit(struct sdhci_host *host, u8 mask)
 
 static int tegra_sdhci_buswidth(struct sdhci_host *host, int bus_width)
 {
-	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
-	struct sdhci_tegra *tegra_host = pltfm_host->priv;
 	u32 ctrl;
 
 	ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
-	if (tegra_host->is_8bit && bus_width == MMC_BUS_WIDTH_8) {
+	if ((host->mmc->caps & MMC_CAP_8_BIT_DATA) &&
+	    (bus_width == MMC_BUS_WIDTH_8)) {
 		ctrl &= ~SDHCI_CTRL_4BITBUS;
 		ctrl |= SDHCI_CTRL_8BITBUS;
 	} else {
@@ -164,7 +147,7 @@ static int tegra_sdhci_buswidth(struct sdhci_host *host, int bus_width)
 	return 0;
 }
 
-static struct sdhci_ops tegra_sdhci_ops = {
+static const struct sdhci_ops tegra_sdhci_ops = {
 	.get_ro     = tegra_sdhci_get_ro,
 	.read_l     = tegra_sdhci_readl,
 	.read_w     = tegra_sdhci_readw,
@@ -173,8 +156,7 @@ static struct sdhci_ops tegra_sdhci_ops = {
 	.platform_reset_exit = tegra_sdhci_reset_exit,
 };
 
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
-static struct sdhci_pltfm_data sdhci_tegra20_pdata = {
+static const struct sdhci_pltfm_data sdhci_tegra20_pdata = {
 	.quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
 		  SDHCI_QUIRK_SINGLE_POWER_WRITE |
 		  SDHCI_QUIRK_NO_HISPD_BIT |
@@ -187,10 +169,8 @@ static struct sdhci_tegra_soc_data soc_data_tegra20 = {
 	.nvquirks = NVQUIRK_FORCE_SDHCI_SPEC_200 |
 		    NVQUIRK_ENABLE_BLOCK_GAP_DET,
 };
-#endif
 
-#ifdef CONFIG_ARCH_TEGRA_3x_SOC
-static struct sdhci_pltfm_data sdhci_tegra30_pdata = {
+static const struct sdhci_pltfm_data sdhci_tegra30_pdata = {
 	.quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
 		  SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
 		  SDHCI_QUIRK_SINGLE_POWER_WRITE |
@@ -203,32 +183,37 @@ static struct sdhci_tegra_soc_data soc_data_tegra30 = {
 	.pdata = &sdhci_tegra30_pdata,
 	.nvquirks = NVQUIRK_ENABLE_SDHCI_SPEC_300,
 };
-#endif
+
+static const struct sdhci_pltfm_data sdhci_tegra114_pdata = {
+	.quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
+		  SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
+		  SDHCI_QUIRK_SINGLE_POWER_WRITE |
+		  SDHCI_QUIRK_NO_HISPD_BIT |
+		  SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC,
+	.ops  = &tegra_sdhci_ops,
+};
+
+static struct sdhci_tegra_soc_data soc_data_tegra114 = {
+	.pdata = &sdhci_tegra114_pdata,
+};
 
 static const struct of_device_id sdhci_tegra_dt_match[] = {
-#ifdef CONFIG_ARCH_TEGRA_3x_SOC
+	{ .compatible = "nvidia,tegra114-sdhci", .data = &soc_data_tegra114 },
 	{ .compatible = "nvidia,tegra30-sdhci", .data = &soc_data_tegra30 },
-#endif
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
 	{ .compatible = "nvidia,tegra20-sdhci", .data = &soc_data_tegra20 },
-#endif
 	{}
 };
 MODULE_DEVICE_TABLE(of, sdhci_dt_ids);
 
-static void sdhci_tegra_parse_dt(struct device *dev,
-					struct sdhci_tegra *tegra_host)
+static void sdhci_tegra_parse_dt(struct device *dev)
 {
 	struct device_node *np = dev->of_node;
-	u32 bus_width;
+	struct sdhci_host *host = dev_get_drvdata(dev);
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_tegra *tegra_host = pltfm_host->priv;
 
-	tegra_host->cd_gpio = of_get_named_gpio(np, "cd-gpios", 0);
-	tegra_host->wp_gpio = of_get_named_gpio(np, "wp-gpios", 0);
 	tegra_host->power_gpio = of_get_named_gpio(np, "power-gpios", 0);
-
-	if (of_property_read_u32(np, "bus-width", &bus_width) == 0 &&
-	    bus_width == 8)
-		tegra_host->is_8bit = 1;
+	mmc_of_parse(host->mmc);
 }
 
 static int sdhci_tegra_probe(struct platform_device *pdev)
@@ -260,7 +245,7 @@ static int sdhci_tegra_probe(struct platform_device *pdev)
 	tegra_host->soc_data = soc_data;
 	pltfm_host->priv = tegra_host;
 
-	sdhci_tegra_parse_dt(&pdev->dev, tegra_host);
+	sdhci_tegra_parse_dt(&pdev->dev);
 
 	if (gpio_is_valid(tegra_host->power_gpio)) {
 		rc = gpio_request(tegra_host->power_gpio, "sdhci_power");
@@ -272,37 +257,6 @@ static int sdhci_tegra_probe(struct platform_device *pdev)
 		gpio_direction_output(tegra_host->power_gpio, 1);
 	}
 
-	if (gpio_is_valid(tegra_host->cd_gpio)) {
-		rc = gpio_request(tegra_host->cd_gpio, "sdhci_cd");
-		if (rc) {
-			dev_err(mmc_dev(host->mmc),
-				"failed to allocate cd gpio\n");
-			goto err_cd_req;
-		}
-		gpio_direction_input(tegra_host->cd_gpio);
-
-		rc = request_irq(gpio_to_irq(tegra_host->cd_gpio),
-				 carddetect_irq,
-				 IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
-				 mmc_hostname(host->mmc), host);
-
-		if (rc)	{
-			dev_err(mmc_dev(host->mmc), "request irq error\n");
-			goto err_cd_irq_req;
-		}
-
-	}
-
-	if (gpio_is_valid(tegra_host->wp_gpio)) {
-		rc = gpio_request(tegra_host->wp_gpio, "sdhci_wp");
-		if (rc) {
-			dev_err(mmc_dev(host->mmc),
-				"failed to allocate wp gpio\n");
-			goto err_wp_req;
-		}
-		gpio_direction_input(tegra_host->wp_gpio);
-	}
-
 	clk = clk_get(mmc_dev(host->mmc), NULL);
 	if (IS_ERR(clk)) {
 		dev_err(mmc_dev(host->mmc), "clk err\n");
@@ -312,9 +266,6 @@ static int sdhci_tegra_probe(struct platform_device *pdev)
 	clk_prepare_enable(clk);
 	pltfm_host->clk = clk;
 
-	if (tegra_host->is_8bit)
-		host->mmc->caps |= MMC_CAP_8_BIT_DATA;
-
 	rc = sdhci_add_host(host);
 	if (rc)
 		goto err_add_host;
@@ -325,15 +276,6 @@ err_add_host:
 	clk_disable_unprepare(pltfm_host->clk);
 	clk_put(pltfm_host->clk);
 err_clk_get:
-	if (gpio_is_valid(tegra_host->wp_gpio))
-		gpio_free(tegra_host->wp_gpio);
-err_wp_req:
-	if (gpio_is_valid(tegra_host->cd_gpio))
-		free_irq(gpio_to_irq(tegra_host->cd_gpio), host);
-err_cd_irq_req:
-	if (gpio_is_valid(tegra_host->cd_gpio))
-		gpio_free(tegra_host->cd_gpio);
-err_cd_req:
 	if (gpio_is_valid(tegra_host->power_gpio))
 		gpio_free(tegra_host->power_gpio);
 err_power_req:
@@ -351,14 +293,6 @@ static int sdhci_tegra_remove(struct platform_device *pdev)
 
 	sdhci_remove_host(host, dead);
 
-	if (gpio_is_valid(tegra_host->wp_gpio))
-		gpio_free(tegra_host->wp_gpio);
-
-	if (gpio_is_valid(tegra_host->cd_gpio)) {
-		free_irq(gpio_to_irq(tegra_host->cd_gpio), host);
-		gpio_free(tegra_host->cd_gpio);
-	}
-
 	if (gpio_is_valid(tegra_host->power_gpio))
 		gpio_free(tegra_host->power_gpio);
 
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 51bbba4..2ea429c 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1581,6 +1581,37 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 	sdhci_runtime_pm_put(host);
 }
 
+static int sdhci_do_get_cd(struct sdhci_host *host)
+{
+	int gpio_cd = mmc_gpio_get_cd(host->mmc);
+
+	if (host->flags & SDHCI_DEVICE_DEAD)
+		return 0;
+
+	/* If polling/nonremovable, assume that the card is always present. */
+	if ((host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) ||
+	    (host->mmc->caps & MMC_CAP_NONREMOVABLE))
+		return 1;
+
+	/* Try slot gpio detect */
+	if (!IS_ERR_VALUE(gpio_cd))
+		return !!gpio_cd;
+
+	/* Host native card detect */
+	return !!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT);
+}
+
+static int sdhci_get_cd(struct mmc_host *mmc)
+{
+	struct sdhci_host *host = mmc_priv(mmc);
+	int ret;
+
+	sdhci_runtime_pm_get(host);
+	ret = sdhci_do_get_cd(host);
+	sdhci_runtime_pm_put(host);
+	return ret;
+}
+
 static int sdhci_check_ro(struct sdhci_host *host)
 {
 	unsigned long flags;
@@ -2038,6 +2069,7 @@ static void sdhci_card_event(struct mmc_host *mmc)
 static const struct mmc_host_ops sdhci_ops = {
 	.request	= sdhci_request,
 	.set_ios	= sdhci_set_ios,
+	.get_cd		= sdhci_get_cd,
 	.get_ro		= sdhci_get_ro,
 	.hw_reset	= sdhci_hw_reset,
 	.enable_sdio_irq = sdhci_enable_sdio_irq,
@@ -2907,12 +2939,17 @@ int sdhci_add_host(struct sdhci_host *host)
 			host->vqmmc = NULL;
 		}
 	} else {
-		regulator_enable(host->vqmmc);
+		ret = regulator_enable(host->vqmmc);
 		if (!regulator_is_supported_voltage(host->vqmmc, 1700000,
 			1950000))
 			caps[1] &= ~(SDHCI_SUPPORT_SDR104 |
 					SDHCI_SUPPORT_SDR50 |
 					SDHCI_SUPPORT_DDR50);
+		if (ret) {
+			pr_warn("%s: Failed to enable vqmmc regulator: %d\n",
+				mmc_hostname(mmc), ret);
+			host->vqmmc = NULL;
+		}
 	}
 
 	if (host->quirks2 & SDHCI_QUIRK2_NO_1_8_V)
diff --git a/drivers/mmc/host/sdricoh_cs.c b/drivers/mmc/host/sdricoh_cs.c
index 7009f17..50adbd1 100644
--- a/drivers/mmc/host/sdricoh_cs.c
+++ b/drivers/mmc/host/sdricoh_cs.c
@@ -543,25 +543,7 @@ static struct pcmcia_driver sdricoh_driver = {
 	.suspend = sdricoh_pcmcia_suspend,
 	.resume = sdricoh_pcmcia_resume,
 };
-
-/*****************************************************************************\
- *                                                                           *
- * Driver init/exit                                                          *
- *                                                                           *
-\*****************************************************************************/
-
-static int __init sdricoh_drv_init(void)
-{
-	return pcmcia_register_driver(&sdricoh_driver);
-}
-
-static void __exit sdricoh_drv_exit(void)
-{
-	pcmcia_unregister_driver(&sdricoh_driver);
-}
-
-module_init(sdricoh_drv_init);
-module_exit(sdricoh_drv_exit);
+module_pcmcia_driver(sdricoh_driver);
 
 module_param(switchlocked, uint, 0444);
 
diff --git a/drivers/mmc/host/wmt-sdmmc.c b/drivers/mmc/host/wmt-sdmmc.c
index c6d0015..442f576 100644
--- a/drivers/mmc/host/wmt-sdmmc.c
+++ b/drivers/mmc/host/wmt-sdmmc.c
@@ -348,13 +348,11 @@ static void wmt_complete_data_request(struct wmt_mci_priv *priv)
 
 static irqreturn_t wmt_mci_dma_isr(int irq_num, void *data)
 {
-	struct mmc_host *mmc;
 	struct wmt_mci_priv *priv;
 
 	int status;
 
 	priv = (struct wmt_mci_priv *)data;
-	mmc = priv->mmc;
 
 	status = readl(priv->sdmmc_base + SDDMA_CCR) & 0x0F;
 
@@ -925,7 +923,7 @@ static int wmt_mci_remove(struct platform_device *pdev)
 	clk_put(priv->clk_sdmmc);
 
 	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));
 
 	mmc_free_host(mmc);
 
diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
index 557bec5..5fab4e6e 100644
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -157,19 +157,6 @@ config MTD_BCM47XX_PARTS
 
 comment "User Modules And Translation Layers"
 
-config MTD_CHAR
-	tristate "Direct char device access to MTD devices"
-	help
-	  This provides a character device for each MTD device present in
-	  the system, allowing the user to read and write directly to the
-	  memory chips, and also use ioctl() to obtain information about
-	  the device, or to erase parts of it.
-
-config HAVE_MTD_OTP
-	bool
-	help
-	  Enable access to OTP regions using MTD_CHAR.
-
 config MTD_BLKDEVS
 	tristate "Common interface to block layer for MTD 'translation layers'"
 	depends on BLOCK
diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile
index 18a38e5..4cfb31e 100644
--- a/drivers/mtd/Makefile
+++ b/drivers/mtd/Makefile
@@ -4,7 +4,7 @@
 
 # Core functionality.
 obj-$(CONFIG_MTD)		+= mtd.o
-mtd-y				:= mtdcore.o mtdsuper.o mtdconcat.o mtdpart.o
+mtd-y				:= mtdcore.o mtdsuper.o mtdconcat.o mtdpart.o mtdchar.o
 
 obj-$(CONFIG_MTD_OF_PARTS)	+= ofpart.o
 obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o
@@ -15,7 +15,6 @@ obj-$(CONFIG_MTD_BCM63XX_PARTS)	+= bcm63xxpart.o
 obj-$(CONFIG_MTD_BCM47XX_PARTS)	+= bcm47xxpart.o
 
 # 'Users' - code which presents functionality to userspace.
-obj-$(CONFIG_MTD_CHAR)		+= mtdchar.o
 obj-$(CONFIG_MTD_BLKDEVS)	+= mtd_blkdevs.o
 obj-$(CONFIG_MTD_BLOCK)		+= mtdblock.o
 obj-$(CONFIG_MTD_BLOCK_RO)	+= mtdblock_ro.o
diff --git a/drivers/mtd/chips/Kconfig b/drivers/mtd/chips/Kconfig
index c219e3d..e4696b3 100644
--- a/drivers/mtd/chips/Kconfig
+++ b/drivers/mtd/chips/Kconfig
@@ -146,7 +146,6 @@ config MTD_CFI_I8
 config MTD_OTP
 	bool "Protection Registers aka one-time programmable (OTP) bits"
 	depends on MTD_CFI_ADV_OPTIONS
-	select HAVE_MTD_OTP
 	default n
 	help
 	  This enables support for reading, writing and locking so called
diff --git a/drivers/mtd/chips/gen_probe.c b/drivers/mtd/chips/gen_probe.c
index 3b9a284..74dbb6b 100644
--- a/drivers/mtd/chips/gen_probe.c
+++ b/drivers/mtd/chips/gen_probe.c
@@ -204,14 +204,16 @@ static inline struct mtd_info *cfi_cmdset_unknown(struct map_info *map,
 	struct cfi_private *cfi = map->fldrv_priv;
 	__u16 type = primary?cfi->cfiq->P_ID:cfi->cfiq->A_ID;
 #ifdef CONFIG_MODULES
-	char probename[16+sizeof(MODULE_SYMBOL_PREFIX)];
+	char probename[sizeof(VMLINUX_SYMBOL_STR(cfi_cmdset_%4.4X))];
 	cfi_cmdset_fn_t *probe_function;
 
-	sprintf(probename, MODULE_SYMBOL_PREFIX "cfi_cmdset_%4.4X", type);
+	sprintf(probename, VMLINUX_SYMBOL_STR(cfi_cmdset_%4.4X), type);
 
 	probe_function = __symbol_get(probename);
 	if (!probe_function) {
-		request_module(probename + sizeof(MODULE_SYMBOL_PREFIX) - 1);
+		char modname[sizeof("cfi_cmdset_%4.4X")];
+		sprintf(modname, "cfi_cmdset_%4.4X", type);
+		request_module(modname);
 		probe_function = __symbol_get(probename);
 	}
 
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
index 12311f5..2a4d55e 100644
--- a/drivers/mtd/devices/Kconfig
+++ b/drivers/mtd/devices/Kconfig
@@ -71,7 +71,6 @@ config MTD_DATAFLASH_WRITE_VERIFY
 config MTD_DATAFLASH_OTP
 	bool "DataFlash OTP support (Security Register)"
 	depends on MTD_DATAFLASH
-	select HAVE_MTD_OTP
 	help
 	  Newer DataFlash chips (revisions C and D) support 128 bytes of
 	  one-time-programmable (OTP) data.  The first half may be written
@@ -205,69 +204,6 @@ config MTD_BLOCK2MTD
 
 comment "Disk-On-Chip Device Drivers"
 
-config MTD_DOC2000
-	tristate "M-Systems Disk-On-Chip 2000 and Millennium (DEPRECATED)"
-	depends on MTD_NAND
-	select MTD_DOCPROBE
-	select MTD_NAND_IDS
-	---help---
-	  This provides an MTD device driver for the M-Systems DiskOnChip
-	  2000 and Millennium devices.  Originally designed for the DiskOnChip
-	  2000, it also now includes support for the DiskOnChip Millennium.
-	  If you have problems with this driver and the DiskOnChip Millennium,
-	  you may wish to try the alternative Millennium driver below. To use
-	  the alternative driver, you will need to undefine DOC_SINGLE_DRIVER
-	  in the <file:drivers/mtd/devices/docprobe.c> source code.
-
-	  If you use this device, you probably also want to enable the NFTL
-	  'NAND Flash Translation Layer' option below, which is used to
-	  emulate a block device by using a kind of file system on the flash
-	  chips.
-
-	  NOTE: This driver is deprecated and will probably be removed soon.
-	  Please try the new DiskOnChip driver under "NAND Flash Device
-	  Drivers".
-
-config MTD_DOC2001
-	tristate "M-Systems Disk-On-Chip Millennium-only alternative driver (DEPRECATED)"
-	depends on MTD_NAND
-	select MTD_DOCPROBE
-	select MTD_NAND_IDS
-	---help---
-	  This provides an alternative MTD device driver for the M-Systems
-	  DiskOnChip Millennium devices.  Use this if you have problems with
-	  the combined DiskOnChip 2000 and Millennium driver above.  To get
-	  the DiskOnChip probe code to load and use this driver instead of
-	  the other one, you will need to undefine DOC_SINGLE_DRIVER near
-	  the beginning of <file:drivers/mtd/devices/docprobe.c>.
-
-	  If you use this device, you probably also want to enable the NFTL
-	  'NAND Flash Translation Layer' option below, which is used to
-	  emulate a block device by using a kind of file system on the flash
-	  chips.
-
-	  NOTE: This driver is deprecated and will probably be removed soon.
-	  Please try the new DiskOnChip driver under "NAND Flash Device
-	  Drivers".
-
-config MTD_DOC2001PLUS
-	tristate "M-Systems Disk-On-Chip Millennium Plus"
-	depends on MTD_NAND
-	select MTD_DOCPROBE
-	select MTD_NAND_IDS
-	---help---
-	  This provides an MTD device driver for the M-Systems DiskOnChip
-	  Millennium Plus devices.
-
-	  If you use this device, you probably also want to enable the INFTL
-	  'Inverse NAND Flash Translation Layer' option below, which is used
-	  to emulate a block device by using a kind of file system on the
-	  flash chips.
-
-	  NOTE: This driver will soon be replaced by the new DiskOnChip driver
-	  under "NAND Flash Device Drivers" (currently that driver does not
-	  support all Millennium Plus devices).
-
 config MTD_DOCG3
 	tristate "M-Systems Disk-On-Chip G3"
 	select BCH
diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile
index 369a194..d83bd73 100644
--- a/drivers/mtd/devices/Makefile
+++ b/drivers/mtd/devices/Makefile
@@ -2,12 +2,7 @@
 # linux/drivers/mtd/devices/Makefile
 #
 
-obj-$(CONFIG_MTD_DOC2000)	+= doc2000.o
-obj-$(CONFIG_MTD_DOC2001)	+= doc2001.o
-obj-$(CONFIG_MTD_DOC2001PLUS)	+= doc2001plus.o
 obj-$(CONFIG_MTD_DOCG3)		+= docg3.o
-obj-$(CONFIG_MTD_DOCPROBE)	+= docprobe.o
-obj-$(CONFIG_MTD_DOCECC)	+= docecc.o
 obj-$(CONFIG_MTD_SLRAM)		+= slram.o
 obj-$(CONFIG_MTD_PHRAM)		+= phram.o
 obj-$(CONFIG_MTD_PMC551)	+= pmc551.o
diff --git a/drivers/mtd/devices/bcm47xxsflash.c b/drivers/mtd/devices/bcm47xxsflash.c
index 9526628..18e7761 100644
--- a/drivers/mtd/devices/bcm47xxsflash.c
+++ b/drivers/mtd/devices/bcm47xxsflash.c
@@ -10,7 +10,7 @@
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Serial flash driver for BCMA bus");
 
-static const char *probes[] = { "bcm47xxpart", NULL };
+static const char * const probes[] = { "bcm47xxpart", NULL };
 
 static int bcm47xxsflash_read(struct mtd_info *mtd, loff_t from, size_t len,
 			      size_t *retlen, u_char *buf)
@@ -61,6 +61,17 @@ static int bcm47xxsflash_bcma_probe(struct platform_device *pdev)
 	}
 	sflash->priv = b47s;
 
+	b47s->bcma_cc = container_of(sflash, struct bcma_drv_cc, sflash);
+
+	switch (b47s->bcma_cc->capabilities & BCMA_CC_CAP_FLASHT) {
+	case BCMA_CC_FLASHT_STSER:
+		b47s->type = BCM47XXSFLASH_TYPE_ST;
+		break;
+	case BCMA_CC_FLASHT_ATSER:
+		b47s->type = BCM47XXSFLASH_TYPE_ATMEL;
+		break;
+	}
+
 	b47s->window = sflash->window;
 	b47s->blocksize = sflash->blocksize;
 	b47s->numblocks = sflash->numblocks;
diff --git a/drivers/mtd/devices/bcm47xxsflash.h b/drivers/mtd/devices/bcm47xxsflash.h
index ebf6f71..f22f8c4 100644
--- a/drivers/mtd/devices/bcm47xxsflash.h
+++ b/drivers/mtd/devices/bcm47xxsflash.h
@@ -3,7 +3,66 @@
 
 #include <linux/mtd/mtd.h>
 
+/* Used for ST flashes only. */
+#define OPCODE_ST_WREN		0x0006		/* Write Enable */
+#define OPCODE_ST_WRDIS		0x0004		/* Write Disable */
+#define OPCODE_ST_RDSR		0x0105		/* Read Status Register */
+#define OPCODE_ST_WRSR		0x0101		/* Write Status Register */
+#define OPCODE_ST_READ		0x0303		/* Read Data Bytes */
+#define OPCODE_ST_PP		0x0302		/* Page Program */
+#define OPCODE_ST_SE		0x02d8		/* Sector Erase */
+#define OPCODE_ST_BE		0x00c7		/* Bulk Erase */
+#define OPCODE_ST_DP		0x00b9		/* Deep Power-down */
+#define OPCODE_ST_RES		0x03ab		/* Read Electronic Signature */
+#define OPCODE_ST_CSA		0x1000		/* Keep chip select asserted */
+#define OPCODE_ST_SSE		0x0220		/* Sub-sector Erase */
+
+/* Used for Atmel flashes only. */
+#define OPCODE_AT_READ				0x07e8
+#define OPCODE_AT_PAGE_READ			0x07d2
+#define OPCODE_AT_STATUS			0x01d7
+#define OPCODE_AT_BUF1_WRITE			0x0384
+#define OPCODE_AT_BUF2_WRITE			0x0387
+#define OPCODE_AT_BUF1_ERASE_PROGRAM		0x0283
+#define OPCODE_AT_BUF2_ERASE_PROGRAM		0x0286
+#define OPCODE_AT_BUF1_PROGRAM			0x0288
+#define OPCODE_AT_BUF2_PROGRAM			0x0289
+#define OPCODE_AT_PAGE_ERASE			0x0281
+#define OPCODE_AT_BLOCK_ERASE			0x0250
+#define OPCODE_AT_BUF1_WRITE_ERASE_PROGRAM	0x0382
+#define OPCODE_AT_BUF2_WRITE_ERASE_PROGRAM	0x0385
+#define OPCODE_AT_BUF1_LOAD			0x0253
+#define OPCODE_AT_BUF2_LOAD			0x0255
+#define OPCODE_AT_BUF1_COMPARE			0x0260
+#define OPCODE_AT_BUF2_COMPARE			0x0261
+#define OPCODE_AT_BUF1_REPROGRAM		0x0258
+#define OPCODE_AT_BUF2_REPROGRAM		0x0259
+
+/* Status register bits for ST flashes */
+#define SR_ST_WIP		0x01		/* Write In Progress */
+#define SR_ST_WEL		0x02		/* Write Enable Latch */
+#define SR_ST_BP_MASK		0x1c		/* Block Protect */
+#define SR_ST_BP_SHIFT		2
+#define SR_ST_SRWD		0x80		/* Status Register Write Disable */
+
+/* Status register bits for Atmel flashes */
+#define SR_AT_READY		0x80
+#define SR_AT_MISMATCH		0x40
+#define SR_AT_ID_MASK		0x38
+#define SR_AT_ID_SHIFT		3
+
+struct bcma_drv_cc;
+
+enum bcm47xxsflash_type {
+	BCM47XXSFLASH_TYPE_ATMEL,
+	BCM47XXSFLASH_TYPE_ST,
+};
+
 struct bcm47xxsflash {
+	struct bcma_drv_cc *bcma_cc;
+
+	enum bcm47xxsflash_type type;
+
 	u32 window;
 	u32 blocksize;
 	u16 numblocks;
diff --git a/drivers/mtd/devices/doc2000.c b/drivers/mtd/devices/doc2000.c
deleted file mode 100644
index a4eb8b5..0000000
--- a/drivers/mtd/devices/doc2000.c
+++ /dev/null
@@ -1,1178 +0,0 @@
-
-/*
- * Linux driver for Disk-On-Chip 2000 and Millennium
- * (c) 1999 Machine Vision Holdings, Inc.
- * (c) 1999, 2000 David Woodhouse <dwmw2@infradead.org>
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <asm/errno.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/sched.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/bitops.h>
-#include <linux/mutex.h>
-
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
-#include <linux/mtd/doc2000.h>
-
-#define DOC_SUPPORT_2000
-#define DOC_SUPPORT_2000TSOP
-#define DOC_SUPPORT_MILLENNIUM
-
-#ifdef DOC_SUPPORT_2000
-#define DoC_is_2000(doc) (doc->ChipID == DOC_ChipID_Doc2k)
-#else
-#define DoC_is_2000(doc) (0)
-#endif
-
-#if defined(DOC_SUPPORT_2000TSOP) || defined(DOC_SUPPORT_MILLENNIUM)
-#define DoC_is_Millennium(doc) (doc->ChipID == DOC_ChipID_DocMil)
-#else
-#define DoC_is_Millennium(doc) (0)
-#endif
-
-/* #define ECC_DEBUG */
-
-/* I have no idea why some DoC chips can not use memcpy_from|to_io().
- * This may be due to the different revisions of the ASIC controller built-in or
- * simplily a QA/Bug issue. Who knows ?? If you have trouble, please uncomment
- * this:
- #undef USE_MEMCPY
-*/
-
-static int doc_read(struct mtd_info *mtd, loff_t from, size_t len,
-		    size_t *retlen, u_char *buf);
-static int doc_write(struct mtd_info *mtd, loff_t to, size_t len,
-		     size_t *retlen, const u_char *buf);
-static int doc_read_oob(struct mtd_info *mtd, loff_t ofs,
-			struct mtd_oob_ops *ops);
-static int doc_write_oob(struct mtd_info *mtd, loff_t ofs,
-			 struct mtd_oob_ops *ops);
-static int doc_write_oob_nolock(struct mtd_info *mtd, loff_t ofs, size_t len,
-			 size_t *retlen, const u_char *buf);
-static int doc_erase (struct mtd_info *mtd, struct erase_info *instr);
-
-static struct mtd_info *doc2klist = NULL;
-
-/* Perform the required delay cycles by reading from the appropriate register */
-static void DoC_Delay(struct DiskOnChip *doc, unsigned short cycles)
-{
-	volatile char dummy;
-	int i;
-
-	for (i = 0; i < cycles; i++) {
-		if (DoC_is_Millennium(doc))
-			dummy = ReadDOC(doc->virtadr, NOP);
-		else
-			dummy = ReadDOC(doc->virtadr, DOCStatus);
-	}
-
-}
-
-/* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */
-static int _DoC_WaitReady(struct DiskOnChip *doc)
-{
-	void __iomem *docptr = doc->virtadr;
-	unsigned long timeo = jiffies + (HZ * 10);
-
-	pr_debug("_DoC_WaitReady called for out-of-line wait\n");
-
-	/* Out-of-line routine to wait for chip response */
-	while (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B)) {
-		/* issue 2 read from NOP register after reading from CDSNControl register
-	   	see Software Requirement 11.4 item 2. */
-		DoC_Delay(doc, 2);
-
-		if (time_after(jiffies, timeo)) {
-			pr_debug("_DoC_WaitReady timed out.\n");
-			return -EIO;
-		}
-		udelay(1);
-		cond_resched();
-	}
-
-	return 0;
-}
-
-static inline int DoC_WaitReady(struct DiskOnChip *doc)
-{
-	void __iomem *docptr = doc->virtadr;
-
-	/* This is inline, to optimise the common case, where it's ready instantly */
-	int ret = 0;
-
-	/* 4 read form NOP register should be issued in prior to the read from CDSNControl
-	   see Software Requirement 11.4 item 2. */
-	DoC_Delay(doc, 4);
-
-	if (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B))
-		/* Call the out-of-line routine to wait */
-		ret = _DoC_WaitReady(doc);
-
-	/* issue 2 read from NOP register after reading from CDSNControl register
-	   see Software Requirement 11.4 item 2. */
-	DoC_Delay(doc, 2);
-
-	return ret;
-}
-
-/* DoC_Command: Send a flash command to the flash chip through the CDSN Slow IO register to
-   bypass the internal pipeline. Each of 4 delay cycles (read from the NOP register) is
-   required after writing to CDSN Control register, see Software Requirement 11.4 item 3. */
-
-static int DoC_Command(struct DiskOnChip *doc, unsigned char command,
-			      unsigned char xtraflags)
-{
-	void __iomem *docptr = doc->virtadr;
-
-	if (DoC_is_2000(doc))
-		xtraflags |= CDSN_CTRL_FLASH_IO;
-
-	/* Assert the CLE (Command Latch Enable) line to the flash chip */
-	WriteDOC(xtraflags | CDSN_CTRL_CLE | CDSN_CTRL_CE, docptr, CDSNControl);
-	DoC_Delay(doc, 4);	/* Software requirement 11.4.3 for Millennium */
-
-	if (DoC_is_Millennium(doc))
-		WriteDOC(command, docptr, CDSNSlowIO);
-
-	/* Send the command */
-	WriteDOC_(command, docptr, doc->ioreg);
-	if (DoC_is_Millennium(doc))
-		WriteDOC(command, docptr, WritePipeTerm);
-
-	/* Lower the CLE line */
-	WriteDOC(xtraflags | CDSN_CTRL_CE, docptr, CDSNControl);
-	DoC_Delay(doc, 4);	/* Software requirement 11.4.3 for Millennium */
-
-	/* Wait for the chip to respond - Software requirement 11.4.1 (extended for any command) */
-	return DoC_WaitReady(doc);
-}
-
-/* DoC_Address: Set the current address for the flash chip through the CDSN Slow IO register to
-   bypass the internal pipeline. Each of 4 delay cycles (read from the NOP register) is
-   required after writing to CDSN Control register, see Software Requirement 11.4 item 3. */
-
-static int DoC_Address(struct DiskOnChip *doc, int numbytes, unsigned long ofs,
-		       unsigned char xtraflags1, unsigned char xtraflags2)
-{
-	int i;
-	void __iomem *docptr = doc->virtadr;
-
-	if (DoC_is_2000(doc))
-		xtraflags1 |= CDSN_CTRL_FLASH_IO;
-
-	/* Assert the ALE (Address Latch Enable) line to the flash chip */
-	WriteDOC(xtraflags1 | CDSN_CTRL_ALE | CDSN_CTRL_CE, docptr, CDSNControl);
-
-	DoC_Delay(doc, 4);	/* Software requirement 11.4.3 for Millennium */
-
-	/* Send the address */
-	/* Devices with 256-byte page are addressed as:
-	   Column (bits 0-7), Page (bits 8-15, 16-23, 24-31)
-	   * there is no device on the market with page256
-	   and more than 24 bits.
-	   Devices with 512-byte page are addressed as:
-	   Column (bits 0-7), Page (bits 9-16, 17-24, 25-31)
-	   * 25-31 is sent only if the chip support it.
-	   * bit 8 changes the read command to be sent
-	   (NAND_CMD_READ0 or NAND_CMD_READ1).
-	 */
-
-	if (numbytes == ADDR_COLUMN || numbytes == ADDR_COLUMN_PAGE) {
-		if (DoC_is_Millennium(doc))
-			WriteDOC(ofs & 0xff, docptr, CDSNSlowIO);
-		WriteDOC_(ofs & 0xff, docptr, doc->ioreg);
-	}
-
-	if (doc->page256) {
-		ofs = ofs >> 8;
-	} else {
-		ofs = ofs >> 9;
-	}
-
-	if (numbytes == ADDR_PAGE || numbytes == ADDR_COLUMN_PAGE) {
-		for (i = 0; i < doc->pageadrlen; i++, ofs = ofs >> 8) {
-			if (DoC_is_Millennium(doc))
-				WriteDOC(ofs & 0xff, docptr, CDSNSlowIO);
-			WriteDOC_(ofs & 0xff, docptr, doc->ioreg);
-		}
-	}
-
-	if (DoC_is_Millennium(doc))
-		WriteDOC(ofs & 0xff, docptr, WritePipeTerm);
-
-	DoC_Delay(doc, 2);	/* Needed for some slow flash chips. mf. */
-
-	/* FIXME: The SlowIO's for millennium could be replaced by
-	   a single WritePipeTerm here. mf. */
-
-	/* Lower the ALE line */
-	WriteDOC(xtraflags1 | xtraflags2 | CDSN_CTRL_CE, docptr,
-		 CDSNControl);
-
-	DoC_Delay(doc, 4);	/* Software requirement 11.4.3 for Millennium */
-
-	/* Wait for the chip to respond - Software requirement 11.4.1 */
-	return DoC_WaitReady(doc);
-}
-
-/* Read a buffer from DoC, taking care of Millennium odditys */
-static void DoC_ReadBuf(struct DiskOnChip *doc, u_char * buf, int len)
-{
-	volatile int dummy;
-	int modulus = 0xffff;
-	void __iomem *docptr = doc->virtadr;
-	int i;
-
-	if (len <= 0)
-		return;
-
-	if (DoC_is_Millennium(doc)) {
-		/* Read the data via the internal pipeline through CDSN IO register,
-		   see Pipelined Read Operations 11.3 */
-		dummy = ReadDOC(docptr, ReadPipeInit);
-
-		/* Millennium should use the LastDataRead register - Pipeline Reads */
-		len--;
-
-		/* This is needed for correctly ECC calculation */
-		modulus = 0xff;
-	}
-
-	for (i = 0; i < len; i++)
-		buf[i] = ReadDOC_(docptr, doc->ioreg + (i & modulus));
-
-	if (DoC_is_Millennium(doc)) {
-		buf[i] = ReadDOC(docptr, LastDataRead);
-	}
-}
-
-/* Write a buffer to DoC, taking care of Millennium odditys */
-static void DoC_WriteBuf(struct DiskOnChip *doc, const u_char * buf, int len)
-{
-	void __iomem *docptr = doc->virtadr;
-	int i;
-
-	if (len <= 0)
-		return;
-
-	for (i = 0; i < len; i++)
-		WriteDOC_(buf[i], docptr, doc->ioreg + i);
-
-	if (DoC_is_Millennium(doc)) {
-		WriteDOC(0x00, docptr, WritePipeTerm);
-	}
-}
-
-
-/* DoC_SelectChip: Select a given flash chip within the current floor */
-
-static inline int DoC_SelectChip(struct DiskOnChip *doc, int chip)
-{
-	void __iomem *docptr = doc->virtadr;
-
-	/* Software requirement 11.4.4 before writing DeviceSelect */
-	/* Deassert the CE line to eliminate glitches on the FCE# outputs */
-	WriteDOC(CDSN_CTRL_WP, docptr, CDSNControl);
-	DoC_Delay(doc, 4);	/* Software requirement 11.4.3 for Millennium */
-
-	/* Select the individual flash chip requested */
-	WriteDOC(chip, docptr, CDSNDeviceSelect);
-	DoC_Delay(doc, 4);
-
-	/* Reassert the CE line */
-	WriteDOC(CDSN_CTRL_CE | CDSN_CTRL_FLASH_IO | CDSN_CTRL_WP, docptr,
-		 CDSNControl);
-	DoC_Delay(doc, 4);	/* Software requirement 11.4.3 for Millennium */
-
-	/* Wait for it to be ready */
-	return DoC_WaitReady(doc);
-}
-
-/* DoC_SelectFloor: Select a given floor (bank of flash chips) */
-
-static inline int DoC_SelectFloor(struct DiskOnChip *doc, int floor)
-{
-	void __iomem *docptr = doc->virtadr;
-
-	/* Select the floor (bank) of chips required */
-	WriteDOC(floor, docptr, FloorSelect);
-
-	/* Wait for the chip to be ready */
-	return DoC_WaitReady(doc);
-}
-
-/* DoC_IdentChip: Identify a given NAND chip given {floor,chip} */
-
-static int DoC_IdentChip(struct DiskOnChip *doc, int floor, int chip)
-{
-	int mfr, id, i, j;
-	volatile char dummy;
-
-	/* Page in the required floor/chip */
-	DoC_SelectFloor(doc, floor);
-	DoC_SelectChip(doc, chip);
-
-	/* Reset the chip */
-	if (DoC_Command(doc, NAND_CMD_RESET, CDSN_CTRL_WP)) {
-		pr_debug("DoC_Command (reset) for %d,%d returned true\n",
-		      floor, chip);
-		return 0;
-	}
-
-
-	/* Read the NAND chip ID: 1. Send ReadID command */
-	if (DoC_Command(doc, NAND_CMD_READID, CDSN_CTRL_WP)) {
-		pr_debug("DoC_Command (ReadID) for %d,%d returned true\n",
-		      floor, chip);
-		return 0;
-	}
-
-	/* Read the NAND chip ID: 2. Send address byte zero */
-	DoC_Address(doc, ADDR_COLUMN, 0, CDSN_CTRL_WP, 0);
-
-	/* Read the manufacturer and device id codes from the device */
-
-	if (DoC_is_Millennium(doc)) {
-		DoC_Delay(doc, 2);
-		dummy = ReadDOC(doc->virtadr, ReadPipeInit);
-		mfr = ReadDOC(doc->virtadr, LastDataRead);
-
-		DoC_Delay(doc, 2);
-		dummy = ReadDOC(doc->virtadr, ReadPipeInit);
-		id = ReadDOC(doc->virtadr, LastDataRead);
-	} else {
-		/* CDSN Slow IO register see Software Req 11.4 item 5. */
-		dummy = ReadDOC(doc->virtadr, CDSNSlowIO);
-		DoC_Delay(doc, 2);
-		mfr = ReadDOC_(doc->virtadr, doc->ioreg);
-
-		/* CDSN Slow IO register see Software Req 11.4 item 5. */
-		dummy = ReadDOC(doc->virtadr, CDSNSlowIO);
-		DoC_Delay(doc, 2);
-		id = ReadDOC_(doc->virtadr, doc->ioreg);
-	}
-
-	/* No response - return failure */
-	if (mfr == 0xff || mfr == 0)
-		return 0;
-
-	/* Check it's the same as the first chip we identified.
-	 * M-Systems say that any given DiskOnChip device should only
-	 * contain _one_ type of flash part, although that's not a
-	 * hardware restriction. */
-	if (doc->mfr) {
-		if (doc->mfr == mfr && doc->id == id)
-			return 1;	/* This is the same as the first */
-		else
-			printk(KERN_WARNING
-			       "Flash chip at floor %d, chip %d is different:\n",
-			       floor, chip);
-	}
-
-	/* Print and store the manufacturer and ID codes. */
-	for (i = 0; nand_flash_ids[i].name != NULL; i++) {
-		if (id == nand_flash_ids[i].id) {
-			/* Try to identify manufacturer */
-			for (j = 0; nand_manuf_ids[j].id != 0x0; j++) {
-				if (nand_manuf_ids[j].id == mfr)
-					break;
-			}
-			printk(KERN_INFO
-			       "Flash chip found: Manufacturer ID: %2.2X, "
-			       "Chip ID: %2.2X (%s:%s)\n", mfr, id,
-			       nand_manuf_ids[j].name, nand_flash_ids[i].name);
-			if (!doc->mfr) {
-				doc->mfr = mfr;
-				doc->id = id;
-				doc->chipshift =
-					ffs((nand_flash_ids[i].chipsize << 20)) - 1;
-				doc->page256 = (nand_flash_ids[i].pagesize == 256) ? 1 : 0;
-				doc->pageadrlen = doc->chipshift > 25 ? 3 : 2;
-				doc->erasesize =
-				    nand_flash_ids[i].erasesize;
-				return 1;
-			}
-			return 0;
-		}
-	}
-
-
-	/* We haven't fully identified the chip. Print as much as we know. */
-	printk(KERN_WARNING "Unknown flash chip found: %2.2X %2.2X\n",
-	       id, mfr);
-
-	printk(KERN_WARNING "Please report to dwmw2@infradead.org\n");
-	return 0;
-}
-
-/* DoC_ScanChips: Find all NAND chips present in a DiskOnChip, and identify them */
-
-static void DoC_ScanChips(struct DiskOnChip *this, int maxchips)
-{
-	int floor, chip;
-	int numchips[MAX_FLOORS];
-	int ret = 1;
-
-	this->numchips = 0;
-	this->mfr = 0;
-	this->id = 0;
-
-	/* For each floor, find the number of valid chips it contains */
-	for (floor = 0; floor < MAX_FLOORS; floor++) {
-		ret = 1;
-		numchips[floor] = 0;
-		for (chip = 0; chip < maxchips && ret != 0; chip++) {
-
-			ret = DoC_IdentChip(this, floor, chip);
-			if (ret) {
-				numchips[floor]++;
-				this->numchips++;
-			}
-		}
-	}
-
-	/* If there are none at all that we recognise, bail */
-	if (!this->numchips) {
-		printk(KERN_NOTICE "No flash chips recognised.\n");
-		return;
-	}
-
-	/* Allocate an array to hold the information for each chip */
-	this->chips = kmalloc(sizeof(struct Nand) * this->numchips, GFP_KERNEL);
-	if (!this->chips) {
-		printk(KERN_NOTICE "No memory for allocating chip info structures\n");
-		return;
-	}
-
-	ret = 0;
-
-	/* Fill out the chip array with {floor, chipno} for each
-	 * detected chip in the device. */
-	for (floor = 0; floor < MAX_FLOORS; floor++) {
-		for (chip = 0; chip < numchips[floor]; chip++) {
-			this->chips[ret].floor = floor;
-			this->chips[ret].chip = chip;
-			this->chips[ret].curadr = 0;
-			this->chips[ret].curmode = 0x50;
-			ret++;
-		}
-	}
-
-	/* Calculate and print the total size of the device */
-	this->totlen = this->numchips * (1 << this->chipshift);
-
-	printk(KERN_INFO "%d flash chips found. Total DiskOnChip size: %ld MiB\n",
-	       this->numchips, this->totlen >> 20);
-}
-
-static int DoC2k_is_alias(struct DiskOnChip *doc1, struct DiskOnChip *doc2)
-{
-	int tmp1, tmp2, retval;
-	if (doc1->physadr == doc2->physadr)
-		return 1;
-
-	/* Use the alias resolution register which was set aside for this
-	 * purpose. If it's value is the same on both chips, they might
-	 * be the same chip, and we write to one and check for a change in
-	 * the other. It's unclear if this register is usuable in the
-	 * DoC 2000 (it's in the Millennium docs), but it seems to work. */
-	tmp1 = ReadDOC(doc1->virtadr, AliasResolution);
-	tmp2 = ReadDOC(doc2->virtadr, AliasResolution);
-	if (tmp1 != tmp2)
-		return 0;
-
-	WriteDOC((tmp1 + 1) % 0xff, doc1->virtadr, AliasResolution);
-	tmp2 = ReadDOC(doc2->virtadr, AliasResolution);
-	if (tmp2 == (tmp1 + 1) % 0xff)
-		retval = 1;
-	else
-		retval = 0;
-
-	/* Restore register contents.  May not be necessary, but do it just to
-	 * be safe. */
-	WriteDOC(tmp1, doc1->virtadr, AliasResolution);
-
-	return retval;
-}
-
-/* This routine is found from the docprobe code by symbol_get(),
- * which will bump the use count of this module. */
-void DoC2k_init(struct mtd_info *mtd)
-{
-	struct DiskOnChip *this = mtd->priv;
-	struct DiskOnChip *old = NULL;
-	int maxchips;
-
-	/* We must avoid being called twice for the same device. */
-
-	if (doc2klist)
-		old = doc2klist->priv;
-
-	while (old) {
-		if (DoC2k_is_alias(old, this)) {
-			printk(KERN_NOTICE
-			       "Ignoring DiskOnChip 2000 at 0x%lX - already configured\n",
-			       this->physadr);
-			iounmap(this->virtadr);
-			kfree(mtd);
-			return;
-		}
-		if (old->nextdoc)
-			old = old->nextdoc->priv;
-		else
-			old = NULL;
-	}
-
-
-	switch (this->ChipID) {
-	case DOC_ChipID_Doc2kTSOP:
-		mtd->name = "DiskOnChip 2000 TSOP";
-		this->ioreg = DoC_Mil_CDSN_IO;
-		/* Pretend it's a Millennium */
-		this->ChipID = DOC_ChipID_DocMil;
-		maxchips = MAX_CHIPS;
-		break;
-	case DOC_ChipID_Doc2k:
-		mtd->name = "DiskOnChip 2000";
-		this->ioreg = DoC_2k_CDSN_IO;
-		maxchips = MAX_CHIPS;
-		break;
-	case DOC_ChipID_DocMil:
-		mtd->name = "DiskOnChip Millennium";
-		this->ioreg = DoC_Mil_CDSN_IO;
-		maxchips = MAX_CHIPS_MIL;
-		break;
-	default:
-		printk("Unknown ChipID 0x%02x\n", this->ChipID);
-		kfree(mtd);
-		iounmap(this->virtadr);
-		return;
-	}
-
-	printk(KERN_NOTICE "%s found at address 0x%lX\n", mtd->name,
-	       this->physadr);
-
-	mtd->type = MTD_NANDFLASH;
-	mtd->flags = MTD_CAP_NANDFLASH;
-	mtd->writebufsize = mtd->writesize = 512;
-	mtd->oobsize = 16;
-	mtd->ecc_strength = 2;
-	mtd->owner = THIS_MODULE;
-	mtd->_erase = doc_erase;
-	mtd->_read = doc_read;
-	mtd->_write = doc_write;
-	mtd->_read_oob = doc_read_oob;
-	mtd->_write_oob = doc_write_oob;
-	this->curfloor = -1;
-	this->curchip = -1;
-	mutex_init(&this->lock);
-
-	/* Ident all the chips present. */
-	DoC_ScanChips(this, maxchips);
-
-	if (!this->totlen) {
-		kfree(mtd);
-		iounmap(this->virtadr);
-	} else {
-		this->nextdoc = doc2klist;
-		doc2klist = mtd;
-		mtd->size = this->totlen;
-		mtd->erasesize = this->erasesize;
-		mtd_device_register(mtd, NULL, 0);
-		return;
-	}
-}
-EXPORT_SYMBOL_GPL(DoC2k_init);
-
-static int doc_read(struct mtd_info *mtd, loff_t from, size_t len,
-		    size_t * retlen, u_char * buf)
-{
-	struct DiskOnChip *this = mtd->priv;
-	void __iomem *docptr = this->virtadr;
-	struct Nand *mychip;
-	unsigned char syndrome[6], eccbuf[6];
-	volatile char dummy;
-	int i, len256 = 0, ret=0;
-	size_t left = len;
-
-	mutex_lock(&this->lock);
-	while (left) {
-		len = left;
-
-		/* Don't allow a single read to cross a 512-byte block boundary */
-		if (from + len > ((from | 0x1ff) + 1))
-			len = ((from | 0x1ff) + 1) - from;
-
-		/* The ECC will not be calculated correctly if less than 512 is read */
-		if (len != 0x200)
-			printk(KERN_WARNING
-			       "ECC needs a full sector read (adr: %lx size %lx)\n",
-			       (long) from, (long) len);
-
-		/* printk("DoC_Read (adr: %lx size %lx)\n", (long) from, (long) len); */
-
-
-		/* Find the chip which is to be used and select it */
-		mychip = &this->chips[from >> (this->chipshift)];
-
-		if (this->curfloor != mychip->floor) {
-			DoC_SelectFloor(this, mychip->floor);
-			DoC_SelectChip(this, mychip->chip);
-		} else if (this->curchip != mychip->chip) {
-			DoC_SelectChip(this, mychip->chip);
-		}
-
-		this->curfloor = mychip->floor;
-		this->curchip = mychip->chip;
-
-		DoC_Command(this,
-			    (!this->page256
-			     && (from & 0x100)) ? NAND_CMD_READ1 : NAND_CMD_READ0,
-			    CDSN_CTRL_WP);
-		DoC_Address(this, ADDR_COLUMN_PAGE, from, CDSN_CTRL_WP,
-			    CDSN_CTRL_ECC_IO);
-
-		/* Prime the ECC engine */
-		WriteDOC(DOC_ECC_RESET, docptr, ECCConf);
-		WriteDOC(DOC_ECC_EN, docptr, ECCConf);
-
-		/* treat crossing 256-byte sector for 2M x 8bits devices */
-		if (this->page256 && from + len > (from | 0xff) + 1) {
-			len256 = (from | 0xff) + 1 - from;
-			DoC_ReadBuf(this, buf, len256);
-
-			DoC_Command(this, NAND_CMD_READ0, CDSN_CTRL_WP);
-			DoC_Address(this, ADDR_COLUMN_PAGE, from + len256,
-				    CDSN_CTRL_WP, CDSN_CTRL_ECC_IO);
-		}
-
-		DoC_ReadBuf(this, &buf[len256], len - len256);
-
-		/* Let the caller know we completed it */
-		*retlen += len;
-
-		/* Read the ECC data through the DiskOnChip ECC logic */
-		/* Note: this will work even with 2M x 8bit devices as   */
-		/*       they have 8 bytes of OOB per 256 page. mf.      */
-		DoC_ReadBuf(this, eccbuf, 6);
-
-		/* Flush the pipeline */
-		if (DoC_is_Millennium(this)) {
-			dummy = ReadDOC(docptr, ECCConf);
-			dummy = ReadDOC(docptr, ECCConf);
-			i = ReadDOC(docptr, ECCConf);
-		} else {
-			dummy = ReadDOC(docptr, 2k_ECCStatus);
-			dummy = ReadDOC(docptr, 2k_ECCStatus);
-			i = ReadDOC(docptr, 2k_ECCStatus);
-		}
-
-		/* Check the ECC Status */
-		if (i & 0x80) {
-			int nb_errors;
-			/* There was an ECC error */
-#ifdef ECC_DEBUG
-			printk(KERN_ERR "DiskOnChip ECC Error: Read at %lx\n", (long)from);
-#endif
-			/* Read the ECC syndrome through the DiskOnChip ECC
-			   logic.  These syndrome will be all ZERO when there
-			   is no error */
-			for (i = 0; i < 6; i++) {
-				syndrome[i] =
-					ReadDOC(docptr, ECCSyndrome0 + i);
-			}
-			nb_errors = doc_decode_ecc(buf, syndrome);
-
-#ifdef ECC_DEBUG
-			printk(KERN_ERR "Errors corrected: %x\n", nb_errors);
-#endif
-			if (nb_errors < 0) {
-				/* We return error, but have actually done the
-				   read. Not that this can be told to
-				   user-space, via sys_read(), but at least
-				   MTD-aware stuff can know about it by
-				   checking *retlen */
-				ret = -EIO;
-			}
-		}
-
-#ifdef PSYCHO_DEBUG
-		printk(KERN_DEBUG "ECC DATA at %lxB: %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n",
-		       (long)from, eccbuf[0], eccbuf[1], eccbuf[2],
-		       eccbuf[3], eccbuf[4], eccbuf[5]);
-#endif
-
-		/* disable the ECC engine */
-		WriteDOC(DOC_ECC_DIS, docptr , ECCConf);
-
-		/* according to 11.4.1, we need to wait for the busy line
-	         * drop if we read to the end of the page.  */
-		if(0 == ((from + len) & 0x1ff))
-		{
-		    DoC_WaitReady(this);
-		}
-
-		from += len;
-		left -= len;
-		buf += len;
-	}
-
-	mutex_unlock(&this->lock);
-
-	return ret;
-}
-
-static int doc_write(struct mtd_info *mtd, loff_t to, size_t len,
-		     size_t * retlen, const u_char * buf)
-{
-	struct DiskOnChip *this = mtd->priv;
-	int di; /* Yes, DI is a hangover from when I was disassembling the binary driver */
-	void __iomem *docptr = this->virtadr;
-	unsigned char eccbuf[6];
-	volatile char dummy;
-	int len256 = 0;
-	struct Nand *mychip;
-	size_t left = len;
-	int status;
-
-	mutex_lock(&this->lock);
-	while (left) {
-		len = left;
-
-		/* Don't allow a single write to cross a 512-byte block boundary */
-		if (to + len > ((to | 0x1ff) + 1))
-			len = ((to | 0x1ff) + 1) - to;
-
-		/* The ECC will not be calculated correctly if less than 512 is written */
-/* DBB-
-		if (len != 0x200 && eccbuf)
-			printk(KERN_WARNING
-			       "ECC needs a full sector write (adr: %lx size %lx)\n",
-			       (long) to, (long) len);
-   -DBB */
-
-		/* printk("DoC_Write (adr: %lx size %lx)\n", (long) to, (long) len); */
-
-		/* Find the chip which is to be used and select it */
-		mychip = &this->chips[to >> (this->chipshift)];
-
-		if (this->curfloor != mychip->floor) {
-			DoC_SelectFloor(this, mychip->floor);
-			DoC_SelectChip(this, mychip->chip);
-		} else if (this->curchip != mychip->chip) {
-			DoC_SelectChip(this, mychip->chip);
-		}
-
-		this->curfloor = mychip->floor;
-		this->curchip = mychip->chip;
-
-		/* Set device to main plane of flash */
-		DoC_Command(this, NAND_CMD_RESET, CDSN_CTRL_WP);
-		DoC_Command(this,
-			    (!this->page256
-			     && (to & 0x100)) ? NAND_CMD_READ1 : NAND_CMD_READ0,
-			    CDSN_CTRL_WP);
-
-		DoC_Command(this, NAND_CMD_SEQIN, 0);
-		DoC_Address(this, ADDR_COLUMN_PAGE, to, 0, CDSN_CTRL_ECC_IO);
-
-		/* Prime the ECC engine */
-		WriteDOC(DOC_ECC_RESET, docptr, ECCConf);
-		WriteDOC(DOC_ECC_EN | DOC_ECC_RW, docptr, ECCConf);
-
-		/* treat crossing 256-byte sector for 2M x 8bits devices */
-		if (this->page256 && to + len > (to | 0xff) + 1) {
-			len256 = (to | 0xff) + 1 - to;
-			DoC_WriteBuf(this, buf, len256);
-
-			DoC_Command(this, NAND_CMD_PAGEPROG, 0);
-
-			DoC_Command(this, NAND_CMD_STATUS, CDSN_CTRL_WP);
-			/* There's an implicit DoC_WaitReady() in DoC_Command */
-
-			dummy = ReadDOC(docptr, CDSNSlowIO);
-			DoC_Delay(this, 2);
-
-			if (ReadDOC_(docptr, this->ioreg) & 1) {
-				printk(KERN_ERR "Error programming flash\n");
-				/* Error in programming */
-				*retlen = 0;
-				mutex_unlock(&this->lock);
-				return -EIO;
-			}
-
-			DoC_Command(this, NAND_CMD_SEQIN, 0);
-			DoC_Address(this, ADDR_COLUMN_PAGE, to + len256, 0,
-				    CDSN_CTRL_ECC_IO);
-		}
-
-		DoC_WriteBuf(this, &buf[len256], len - len256);
-
-		WriteDOC(CDSN_CTRL_ECC_IO | CDSN_CTRL_CE, docptr, CDSNControl);
-
-		if (DoC_is_Millennium(this)) {
-			WriteDOC(0, docptr, NOP);
-			WriteDOC(0, docptr, NOP);
-			WriteDOC(0, docptr, NOP);
-		} else {
-			WriteDOC_(0, docptr, this->ioreg);
-			WriteDOC_(0, docptr, this->ioreg);
-			WriteDOC_(0, docptr, this->ioreg);
-		}
-
-		WriteDOC(CDSN_CTRL_ECC_IO | CDSN_CTRL_FLASH_IO | CDSN_CTRL_CE, docptr,
-			 CDSNControl);
-
-		/* Read the ECC data through the DiskOnChip ECC logic */
-		for (di = 0; di < 6; di++) {
-			eccbuf[di] = ReadDOC(docptr, ECCSyndrome0 + di);
-		}
-
-		/* Reset the ECC engine */
-		WriteDOC(DOC_ECC_DIS, docptr, ECCConf);
-
-#ifdef PSYCHO_DEBUG
-		printk
-			("OOB data at %lx is %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n",
-			 (long) to, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3],
-			 eccbuf[4], eccbuf[5]);
-#endif
-		DoC_Command(this, NAND_CMD_PAGEPROG, 0);
-
-		DoC_Command(this, NAND_CMD_STATUS, CDSN_CTRL_WP);
-		/* There's an implicit DoC_WaitReady() in DoC_Command */
-
-		if (DoC_is_Millennium(this)) {
-			ReadDOC(docptr, ReadPipeInit);
-			status = ReadDOC(docptr, LastDataRead);
-		} else {
-			dummy = ReadDOC(docptr, CDSNSlowIO);
-			DoC_Delay(this, 2);
-			status = ReadDOC_(docptr, this->ioreg);
-		}
-
-		if (status & 1) {
-			printk(KERN_ERR "Error programming flash\n");
-			/* Error in programming */
-			*retlen = 0;
-			mutex_unlock(&this->lock);
-			return -EIO;
-		}
-
-		/* Let the caller know we completed it */
-		*retlen += len;
-
-		{
-			unsigned char x[8];
-			size_t dummy;
-			int ret;
-
-			/* Write the ECC data to flash */
-			for (di=0; di<6; di++)
-				x[di] = eccbuf[di];
-
-			x[6]=0x55;
-			x[7]=0x55;
-
-			ret = doc_write_oob_nolock(mtd, to, 8, &dummy, x);
-			if (ret) {
-				mutex_unlock(&this->lock);
-				return ret;
-			}
-		}
-
-		to += len;
-		left -= len;
-		buf += len;
-	}
-
-	mutex_unlock(&this->lock);
-	return 0;
-}
-
-static int doc_read_oob(struct mtd_info *mtd, loff_t ofs,
-			struct mtd_oob_ops *ops)
-{
-	struct DiskOnChip *this = mtd->priv;
-	int len256 = 0, ret;
-	struct Nand *mychip;
-	uint8_t *buf = ops->oobbuf;
-	size_t len = ops->len;
-
-	BUG_ON(ops->mode != MTD_OPS_PLACE_OOB);
-
-	ofs += ops->ooboffs;
-
-	mutex_lock(&this->lock);
-
-	mychip = &this->chips[ofs >> this->chipshift];
-
-	if (this->curfloor != mychip->floor) {
-		DoC_SelectFloor(this, mychip->floor);
-		DoC_SelectChip(this, mychip->chip);
-	} else if (this->curchip != mychip->chip) {
-		DoC_SelectChip(this, mychip->chip);
-	}
-	this->curfloor = mychip->floor;
-	this->curchip = mychip->chip;
-
-	/* update address for 2M x 8bit devices. OOB starts on the second */
-	/* page to maintain compatibility with doc_read_ecc. */
-	if (this->page256) {
-		if (!(ofs & 0x8))
-			ofs += 0x100;
-		else
-			ofs -= 0x8;
-	}
-
-	DoC_Command(this, NAND_CMD_READOOB, CDSN_CTRL_WP);
-	DoC_Address(this, ADDR_COLUMN_PAGE, ofs, CDSN_CTRL_WP, 0);
-
-	/* treat crossing 8-byte OOB data for 2M x 8bit devices */
-	/* Note: datasheet says it should automaticaly wrap to the */
-	/*       next OOB block, but it didn't work here. mf.      */
-	if (this->page256 && ofs + len > (ofs | 0x7) + 1) {
-		len256 = (ofs | 0x7) + 1 - ofs;
-		DoC_ReadBuf(this, buf, len256);
-
-		DoC_Command(this, NAND_CMD_READOOB, CDSN_CTRL_WP);
-		DoC_Address(this, ADDR_COLUMN_PAGE, ofs & (~0x1ff),
-			    CDSN_CTRL_WP, 0);
-	}
-
-	DoC_ReadBuf(this, &buf[len256], len - len256);
-
-	ops->retlen = len;
-	/* Reading the full OOB data drops us off of the end of the page,
-         * causing the flash device to go into busy mode, so we need
-         * to wait until ready 11.4.1 and Toshiba TC58256FT docs */
-
-	ret = DoC_WaitReady(this);
-
-	mutex_unlock(&this->lock);
-	return ret;
-
-}
-
-static int doc_write_oob_nolock(struct mtd_info *mtd, loff_t ofs, size_t len,
-				size_t * retlen, const u_char * buf)
-{
-	struct DiskOnChip *this = mtd->priv;
-	int len256 = 0;
-	void __iomem *docptr = this->virtadr;
-	struct Nand *mychip = &this->chips[ofs >> this->chipshift];
-	volatile int dummy;
-	int status;
-
-	//      printk("doc_write_oob(%lx, %d): %2.2X %2.2X %2.2X %2.2X ... %2.2X %2.2X .. %2.2X %2.2X\n",(long)ofs, len,
-	//   buf[0], buf[1], buf[2], buf[3], buf[8], buf[9], buf[14],buf[15]);
-
-	/* Find the chip which is to be used and select it */
-	if (this->curfloor != mychip->floor) {
-		DoC_SelectFloor(this, mychip->floor);
-		DoC_SelectChip(this, mychip->chip);
-	} else if (this->curchip != mychip->chip) {
-		DoC_SelectChip(this, mychip->chip);
-	}
-	this->curfloor = mychip->floor;
-	this->curchip = mychip->chip;
-
-	/* disable the ECC engine */
-	WriteDOC (DOC_ECC_RESET, docptr, ECCConf);
-	WriteDOC (DOC_ECC_DIS, docptr, ECCConf);
-
-	/* Reset the chip, see Software Requirement 11.4 item 1. */
-	DoC_Command(this, NAND_CMD_RESET, CDSN_CTRL_WP);
-
-	/* issue the Read2 command to set the pointer to the Spare Data Area. */
-	DoC_Command(this, NAND_CMD_READOOB, CDSN_CTRL_WP);
-
-	/* update address for 2M x 8bit devices. OOB starts on the second */
-	/* page to maintain compatibility with doc_read_ecc. */
-	if (this->page256) {
-		if (!(ofs & 0x8))
-			ofs += 0x100;
-		else
-			ofs -= 0x8;
-	}
-
-	/* issue the Serial Data In command to initial the Page Program process */
-	DoC_Command(this, NAND_CMD_SEQIN, 0);
-	DoC_Address(this, ADDR_COLUMN_PAGE, ofs, 0, 0);
-
-	/* treat crossing 8-byte OOB data for 2M x 8bit devices */
-	/* Note: datasheet says it should automaticaly wrap to the */
-	/*       next OOB block, but it didn't work here. mf.      */
-	if (this->page256 && ofs + len > (ofs | 0x7) + 1) {
-		len256 = (ofs | 0x7) + 1 - ofs;
-		DoC_WriteBuf(this, buf, len256);
-
-		DoC_Command(this, NAND_CMD_PAGEPROG, 0);
-		DoC_Command(this, NAND_CMD_STATUS, 0);
-		/* DoC_WaitReady() is implicit in DoC_Command */
-
-		if (DoC_is_Millennium(this)) {
-			ReadDOC(docptr, ReadPipeInit);
-			status = ReadDOC(docptr, LastDataRead);
-		} else {
-			dummy = ReadDOC(docptr, CDSNSlowIO);
-			DoC_Delay(this, 2);
-			status = ReadDOC_(docptr, this->ioreg);
-		}
-
-		if (status & 1) {
-			printk(KERN_ERR "Error programming oob data\n");
-			/* There was an error */
-			*retlen = 0;
-			return -EIO;
-		}
-		DoC_Command(this, NAND_CMD_SEQIN, 0);
-		DoC_Address(this, ADDR_COLUMN_PAGE, ofs & (~0x1ff), 0, 0);
-	}
-
-	DoC_WriteBuf(this, &buf[len256], len - len256);
-
-	DoC_Command(this, NAND_CMD_PAGEPROG, 0);
-	DoC_Command(this, NAND_CMD_STATUS, 0);
-	/* DoC_WaitReady() is implicit in DoC_Command */
-
-	if (DoC_is_Millennium(this)) {
-		ReadDOC(docptr, ReadPipeInit);
-		status = ReadDOC(docptr, LastDataRead);
-	} else {
-		dummy = ReadDOC(docptr, CDSNSlowIO);
-		DoC_Delay(this, 2);
-		status = ReadDOC_(docptr, this->ioreg);
-	}
-
-	if (status & 1) {
-		printk(KERN_ERR "Error programming oob data\n");
-		/* There was an error */
-		*retlen = 0;
-		return -EIO;
-	}
-
-	*retlen = len;
-	return 0;
-
-}
-
-static int doc_write_oob(struct mtd_info *mtd, loff_t ofs,
-			 struct mtd_oob_ops *ops)
-{
-	struct DiskOnChip *this = mtd->priv;
-	int ret;
-
-	BUG_ON(ops->mode != MTD_OPS_PLACE_OOB);
-
-	mutex_lock(&this->lock);
-	ret = doc_write_oob_nolock(mtd, ofs + ops->ooboffs, ops->len,
-				   &ops->retlen, ops->oobbuf);
-
-	mutex_unlock(&this->lock);
-	return ret;
-}
-
-static int doc_erase(struct mtd_info *mtd, struct erase_info *instr)
-{
-	struct DiskOnChip *this = mtd->priv;
-	__u32 ofs = instr->addr;
-	__u32 len = instr->len;
-	volatile int dummy;
-	void __iomem *docptr = this->virtadr;
-	struct Nand *mychip;
-	int status;
-
- 	mutex_lock(&this->lock);
-
-	if (ofs & (mtd->erasesize-1) || len & (mtd->erasesize-1)) {
-		mutex_unlock(&this->lock);
-		return -EINVAL;
-	}
-
-	instr->state = MTD_ERASING;
-
-	/* FIXME: Do this in the background. Use timers or schedule_task() */
-	while(len) {
-		mychip = &this->chips[ofs >> this->chipshift];
-
-		if (this->curfloor != mychip->floor) {
-			DoC_SelectFloor(this, mychip->floor);
-			DoC_SelectChip(this, mychip->chip);
-		} else if (this->curchip != mychip->chip) {
-			DoC_SelectChip(this, mychip->chip);
-		}
-		this->curfloor = mychip->floor;
-		this->curchip = mychip->chip;
-
-		DoC_Command(this, NAND_CMD_ERASE1, 0);
-		DoC_Address(this, ADDR_PAGE, ofs, 0, 0);
-		DoC_Command(this, NAND_CMD_ERASE2, 0);
-
-		DoC_Command(this, NAND_CMD_STATUS, CDSN_CTRL_WP);
-
-		if (DoC_is_Millennium(this)) {
-			ReadDOC(docptr, ReadPipeInit);
-			status = ReadDOC(docptr, LastDataRead);
-		} else {
-			dummy = ReadDOC(docptr, CDSNSlowIO);
-			DoC_Delay(this, 2);
-			status = ReadDOC_(docptr, this->ioreg);
-		}
-
-		if (status & 1) {
-			printk(KERN_ERR "Error erasing at 0x%x\n", ofs);
-			/* There was an error */
-			instr->state = MTD_ERASE_FAILED;
-			goto callback;
-		}
-		ofs += mtd->erasesize;
-		len -= mtd->erasesize;
-	}
-	instr->state = MTD_ERASE_DONE;
-
- callback:
-	mtd_erase_callback(instr);
-
-	mutex_unlock(&this->lock);
-	return 0;
-}
-
-
-/****************************************************************************
- *
- * Module stuff
- *
- ****************************************************************************/
-
-static void __exit cleanup_doc2000(void)
-{
-	struct mtd_info *mtd;
-	struct DiskOnChip *this;
-
-	while ((mtd = doc2klist)) {
-		this = mtd->priv;
-		doc2klist = this->nextdoc;
-
-		mtd_device_unregister(mtd);
-
-		iounmap(this->virtadr);
-		kfree(this->chips);
-		kfree(mtd);
-	}
-}
-
-module_exit(cleanup_doc2000);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org> et al.");
-MODULE_DESCRIPTION("MTD driver for DiskOnChip 2000 and Millennium");
-
diff --git a/drivers/mtd/devices/doc2001.c b/drivers/mtd/devices/doc2001.c
deleted file mode 100644
index f692795..0000000
--- a/drivers/mtd/devices/doc2001.c
+++ /dev/null
@@ -1,824 +0,0 @@
-
-/*
- * Linux driver for Disk-On-Chip Millennium
- * (c) 1999 Machine Vision Holdings, Inc.
- * (c) 1999, 2000 David Woodhouse <dwmw2@infradead.org>
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <asm/errno.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/bitops.h>
-
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
-#include <linux/mtd/doc2000.h>
-
-/* #define ECC_DEBUG */
-
-/* I have no idea why some DoC chips can not use memcop_form|to_io().
- * This may be due to the different revisions of the ASIC controller built-in or
- * simplily a QA/Bug issue. Who knows ?? If you have trouble, please uncomment
- * this:*/
-#undef USE_MEMCPY
-
-static int doc_read(struct mtd_info *mtd, loff_t from, size_t len,
-		    size_t *retlen, u_char *buf);
-static int doc_write(struct mtd_info *mtd, loff_t to, size_t len,
-		     size_t *retlen, const u_char *buf);
-static int doc_read_oob(struct mtd_info *mtd, loff_t ofs,
-			struct mtd_oob_ops *ops);
-static int doc_write_oob(struct mtd_info *mtd, loff_t ofs,
-			 struct mtd_oob_ops *ops);
-static int doc_erase (struct mtd_info *mtd, struct erase_info *instr);
-
-static struct mtd_info *docmillist = NULL;
-
-/* Perform the required delay cycles by reading from the NOP register */
-static void DoC_Delay(void __iomem * docptr, unsigned short cycles)
-{
-	volatile char dummy;
-	int i;
-
-	for (i = 0; i < cycles; i++)
-		dummy = ReadDOC(docptr, NOP);
-}
-
-/* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */
-static int _DoC_WaitReady(void __iomem * docptr)
-{
-	unsigned short c = 0xffff;
-
-	pr_debug("_DoC_WaitReady called for out-of-line wait\n");
-
-	/* Out-of-line routine to wait for chip response */
-	while (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B) && --c)
-		;
-
-	if (c == 0)
-		pr_debug("_DoC_WaitReady timed out.\n");
-
-	return (c == 0);
-}
-
-static inline int DoC_WaitReady(void __iomem * docptr)
-{
-	/* This is inline, to optimise the common case, where it's ready instantly */
-	int ret = 0;
-
-	/* 4 read form NOP register should be issued in prior to the read from CDSNControl
-	   see Software Requirement 11.4 item 2. */
-	DoC_Delay(docptr, 4);
-
-	if (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B))
-		/* Call the out-of-line routine to wait */
-		ret = _DoC_WaitReady(docptr);
-
-	/* issue 2 read from NOP register after reading from CDSNControl register
-	   see Software Requirement 11.4 item 2. */
-	DoC_Delay(docptr, 2);
-
-	return ret;
-}
-
-/* DoC_Command: Send a flash command to the flash chip through the CDSN IO register
-   with the internal pipeline. Each of 4 delay cycles (read from the NOP register) is
-   required after writing to CDSN Control register, see Software Requirement 11.4 item 3. */
-
-static void DoC_Command(void __iomem * docptr, unsigned char command,
-			       unsigned char xtraflags)
-{
-	/* Assert the CLE (Command Latch Enable) line to the flash chip */
-	WriteDOC(xtraflags | CDSN_CTRL_CLE | CDSN_CTRL_CE, docptr, CDSNControl);
-	DoC_Delay(docptr, 4);
-
-	/* Send the command */
-	WriteDOC(command, docptr, Mil_CDSN_IO);
-	WriteDOC(0x00, docptr, WritePipeTerm);
-
-	/* Lower the CLE line */
-	WriteDOC(xtraflags | CDSN_CTRL_CE, docptr, CDSNControl);
-	DoC_Delay(docptr, 4);
-}
-
-/* DoC_Address: Set the current address for the flash chip through the CDSN IO register
-   with the internal pipeline. Each of 4 delay cycles (read from the NOP register) is
-   required after writing to CDSN Control register, see Software Requirement 11.4 item 3. */
-
-static inline void DoC_Address(void __iomem * docptr, int numbytes, unsigned long ofs,
-			       unsigned char xtraflags1, unsigned char xtraflags2)
-{
-	/* Assert the ALE (Address Latch Enable) line to the flash chip */
-	WriteDOC(xtraflags1 | CDSN_CTRL_ALE | CDSN_CTRL_CE, docptr, CDSNControl);
-	DoC_Delay(docptr, 4);
-
-	/* Send the address */
-	switch (numbytes)
-	    {
-	    case 1:
-		    /* Send single byte, bits 0-7. */
-		    WriteDOC(ofs & 0xff, docptr, Mil_CDSN_IO);
-		    WriteDOC(0x00, docptr, WritePipeTerm);
-		    break;
-	    case 2:
-		    /* Send bits 9-16 followed by 17-23 */
-		    WriteDOC((ofs >> 9)  & 0xff, docptr, Mil_CDSN_IO);
-		    WriteDOC((ofs >> 17) & 0xff, docptr, Mil_CDSN_IO);
-		    WriteDOC(0x00, docptr, WritePipeTerm);
-		break;
-	    case 3:
-		    /* Send 0-7, 9-16, then 17-23 */
-		    WriteDOC(ofs & 0xff, docptr, Mil_CDSN_IO);
-		    WriteDOC((ofs >> 9)  & 0xff, docptr, Mil_CDSN_IO);
-		    WriteDOC((ofs >> 17) & 0xff, docptr, Mil_CDSN_IO);
-		    WriteDOC(0x00, docptr, WritePipeTerm);
-		break;
-	    default:
-		return;
-	    }
-
-	/* Lower the ALE line */
-	WriteDOC(xtraflags1 | xtraflags2 | CDSN_CTRL_CE, docptr, CDSNControl);
-	DoC_Delay(docptr, 4);
-}
-
-/* DoC_SelectChip: Select a given flash chip within the current floor */
-static int DoC_SelectChip(void __iomem * docptr, int chip)
-{
-	/* Select the individual flash chip requested */
-	WriteDOC(chip, docptr, CDSNDeviceSelect);
-	DoC_Delay(docptr, 4);
-
-	/* Wait for it to be ready */
-	return DoC_WaitReady(docptr);
-}
-
-/* DoC_SelectFloor: Select a given floor (bank of flash chips) */
-static int DoC_SelectFloor(void __iomem * docptr, int floor)
-{
-	/* Select the floor (bank) of chips required */
-	WriteDOC(floor, docptr, FloorSelect);
-
-	/* Wait for the chip to be ready */
-	return DoC_WaitReady(docptr);
-}
-
-/* DoC_IdentChip: Identify a given NAND chip given {floor,chip} */
-static int DoC_IdentChip(struct DiskOnChip *doc, int floor, int chip)
-{
-	int mfr, id, i, j;
-	volatile char dummy;
-
-	/* Page in the required floor/chip
-	   FIXME: is this supported by Millennium ?? */
-	DoC_SelectFloor(doc->virtadr, floor);
-	DoC_SelectChip(doc->virtadr, chip);
-
-	/* Reset the chip, see Software Requirement 11.4 item 1. */
-	DoC_Command(doc->virtadr, NAND_CMD_RESET, CDSN_CTRL_WP);
-	DoC_WaitReady(doc->virtadr);
-
-	/* Read the NAND chip ID: 1. Send ReadID command */
-	DoC_Command(doc->virtadr, NAND_CMD_READID, CDSN_CTRL_WP);
-
-	/* Read the NAND chip ID: 2. Send address byte zero */
-	DoC_Address(doc->virtadr, 1, 0x00, CDSN_CTRL_WP, 0x00);
-
-	/* Read the manufacturer and device id codes of the flash device through
-	   CDSN IO register see Software Requirement 11.4 item 5.*/
-	dummy = ReadDOC(doc->virtadr, ReadPipeInit);
-	DoC_Delay(doc->virtadr, 2);
-	mfr = ReadDOC(doc->virtadr, Mil_CDSN_IO);
-
-	DoC_Delay(doc->virtadr, 2);
-	id  = ReadDOC(doc->virtadr, Mil_CDSN_IO);
-	dummy = ReadDOC(doc->virtadr, LastDataRead);
-
-	/* No response - return failure */
-	if (mfr == 0xff || mfr == 0)
-		return 0;
-
-	/* FIXME: to deal with multi-flash on multi-Millennium case more carefully */
-	for (i = 0; nand_flash_ids[i].name != NULL; i++) {
-		if ( id == nand_flash_ids[i].id) {
-			/* Try to identify manufacturer */
-			for (j = 0; nand_manuf_ids[j].id != 0x0; j++) {
-				if (nand_manuf_ids[j].id == mfr)
-					break;
-			}
-			printk(KERN_INFO "Flash chip found: Manufacturer ID: %2.2X, "
-			       "Chip ID: %2.2X (%s:%s)\n",
-			       mfr, id, nand_manuf_ids[j].name, nand_flash_ids[i].name);
-			doc->mfr = mfr;
-			doc->id = id;
-			doc->chipshift = ffs((nand_flash_ids[i].chipsize << 20)) - 1;
-			break;
-		}
-	}
-
-	if (nand_flash_ids[i].name == NULL)
-		return 0;
-	else
-		return 1;
-}
-
-/* DoC_ScanChips: Find all NAND chips present in a DiskOnChip, and identify them */
-static void DoC_ScanChips(struct DiskOnChip *this)
-{
-	int floor, chip;
-	int numchips[MAX_FLOORS_MIL];
-	int ret;
-
-	this->numchips = 0;
-	this->mfr = 0;
-	this->id = 0;
-
-	/* For each floor, find the number of valid chips it contains */
-	for (floor = 0,ret = 1; floor < MAX_FLOORS_MIL; floor++) {
-		numchips[floor] = 0;
-		for (chip = 0; chip < MAX_CHIPS_MIL && ret != 0; chip++) {
-			ret = DoC_IdentChip(this, floor, chip);
-			if (ret) {
-				numchips[floor]++;
-				this->numchips++;
-			}
-		}
-	}
-	/* If there are none at all that we recognise, bail */
-	if (!this->numchips) {
-		printk("No flash chips recognised.\n");
-		return;
-	}
-
-	/* Allocate an array to hold the information for each chip */
-	this->chips = kmalloc(sizeof(struct Nand) * this->numchips, GFP_KERNEL);
-	if (!this->chips){
-		printk("No memory for allocating chip info structures\n");
-		return;
-	}
-
-	/* Fill out the chip array with {floor, chipno} for each
-	 * detected chip in the device. */
-	for (floor = 0, ret = 0; floor < MAX_FLOORS_MIL; floor++) {
-		for (chip = 0 ; chip < numchips[floor] ; chip++) {
-			this->chips[ret].floor = floor;
-			this->chips[ret].chip = chip;
-			this->chips[ret].curadr = 0;
-			this->chips[ret].curmode = 0x50;
-			ret++;
-		}
-	}
-
-	/* Calculate and print the total size of the device */
-	this->totlen = this->numchips * (1 << this->chipshift);
-	printk(KERN_INFO "%d flash chips found. Total DiskOnChip size: %ld MiB\n",
-	       this->numchips ,this->totlen >> 20);
-}
-
-static int DoCMil_is_alias(struct DiskOnChip *doc1, struct DiskOnChip *doc2)
-{
-	int tmp1, tmp2, retval;
-
-	if (doc1->physadr == doc2->physadr)
-		return 1;
-
-	/* Use the alias resolution register which was set aside for this
-	 * purpose. If it's value is the same on both chips, they might
-	 * be the same chip, and we write to one and check for a change in
-	 * the other. It's unclear if this register is usuable in the
-	 * DoC 2000 (it's in the Millenium docs), but it seems to work. */
-	tmp1 = ReadDOC(doc1->virtadr, AliasResolution);
-	tmp2 = ReadDOC(doc2->virtadr, AliasResolution);
-	if (tmp1 != tmp2)
-		return 0;
-
-	WriteDOC((tmp1+1) % 0xff, doc1->virtadr, AliasResolution);
-	tmp2 = ReadDOC(doc2->virtadr, AliasResolution);
-	if (tmp2 == (tmp1+1) % 0xff)
-		retval = 1;
-	else
-		retval = 0;
-
-	/* Restore register contents.  May not be necessary, but do it just to
-	 * be safe. */
-	WriteDOC(tmp1, doc1->virtadr, AliasResolution);
-
-	return retval;
-}
-
-/* This routine is found from the docprobe code by symbol_get(),
- * which will bump the use count of this module. */
-void DoCMil_init(struct mtd_info *mtd)
-{
-	struct DiskOnChip *this = mtd->priv;
-	struct DiskOnChip *old = NULL;
-
-	/* We must avoid being called twice for the same device. */
-	if (docmillist)
-		old = docmillist->priv;
-
-	while (old) {
-		if (DoCMil_is_alias(this, old)) {
-			printk(KERN_NOTICE "Ignoring DiskOnChip Millennium at "
-			       "0x%lX - already configured\n", this->physadr);
-			iounmap(this->virtadr);
-			kfree(mtd);
-			return;
-		}
-		if (old->nextdoc)
-			old = old->nextdoc->priv;
-		else
-			old = NULL;
-	}
-
-	mtd->name = "DiskOnChip Millennium";
-	printk(KERN_NOTICE "DiskOnChip Millennium found at address 0x%lX\n",
-	       this->physadr);
-
-	mtd->type = MTD_NANDFLASH;
-	mtd->flags = MTD_CAP_NANDFLASH;
-
-	/* FIXME: erase size is not always 8KiB */
-	mtd->erasesize = 0x2000;
-	mtd->writebufsize = mtd->writesize = 512;
-	mtd->oobsize = 16;
-	mtd->ecc_strength = 2;
-	mtd->owner = THIS_MODULE;
-	mtd->_erase = doc_erase;
-	mtd->_read = doc_read;
-	mtd->_write = doc_write;
-	mtd->_read_oob = doc_read_oob;
-	mtd->_write_oob = doc_write_oob;
-	this->curfloor = -1;
-	this->curchip = -1;
-
-	/* Ident all the chips present. */
-	DoC_ScanChips(this);
-
-	if (!this->totlen) {
-		kfree(mtd);
-		iounmap(this->virtadr);
-	} else {
-		this->nextdoc = docmillist;
-		docmillist = mtd;
-		mtd->size  = this->totlen;
-		mtd_device_register(mtd, NULL, 0);
-		return;
-	}
-}
-EXPORT_SYMBOL_GPL(DoCMil_init);
-
-static int doc_read (struct mtd_info *mtd, loff_t from, size_t len,
-		     size_t *retlen, u_char *buf)
-{
-	int i, ret;
-	volatile char dummy;
-	unsigned char syndrome[6], eccbuf[6];
-	struct DiskOnChip *this = mtd->priv;
-	void __iomem *docptr = this->virtadr;
-	struct Nand *mychip = &this->chips[from >> (this->chipshift)];
-
-	/* Don't allow a single read to cross a 512-byte block boundary */
-	if (from + len > ((from | 0x1ff) + 1))
-		len = ((from | 0x1ff) + 1) - from;
-
-	/* Find the chip which is to be used and select it */
-	if (this->curfloor != mychip->floor) {
-		DoC_SelectFloor(docptr, mychip->floor);
-		DoC_SelectChip(docptr, mychip->chip);
-	} else if (this->curchip != mychip->chip) {
-		DoC_SelectChip(docptr, mychip->chip);
-	}
-	this->curfloor = mychip->floor;
-	this->curchip = mychip->chip;
-
-	/* issue the Read0 or Read1 command depend on which half of the page
-	   we are accessing. Polling the Flash Ready bit after issue 3 bytes
-	   address in Sequence Read Mode, see Software Requirement 11.4 item 1.*/
-	DoC_Command(docptr, (from >> 8) & 1, CDSN_CTRL_WP);
-	DoC_Address(docptr, 3, from, CDSN_CTRL_WP, 0x00);
-	DoC_WaitReady(docptr);
-
-	/* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/
-	WriteDOC (DOC_ECC_RESET, docptr, ECCConf);
-	WriteDOC (DOC_ECC_EN, docptr, ECCConf);
-
-	/* Read the data via the internal pipeline through CDSN IO register,
-	   see Pipelined Read Operations 11.3 */
-	dummy = ReadDOC(docptr, ReadPipeInit);
-#ifndef USE_MEMCPY
-	for (i = 0; i < len-1; i++) {
-		/* N.B. you have to increase the source address in this way or the
-		   ECC logic will not work properly */
-		buf[i] = ReadDOC(docptr, Mil_CDSN_IO + (i & 0xff));
-	}
-#else
-	memcpy_fromio(buf, docptr + DoC_Mil_CDSN_IO, len - 1);
-#endif
-	buf[len - 1] = ReadDOC(docptr, LastDataRead);
-
-	/* Let the caller know we completed it */
-	*retlen = len;
-        ret = 0;
-
-	/* Read the ECC data from Spare Data Area,
-	   see Reed-Solomon EDC/ECC 11.1 */
-	dummy = ReadDOC(docptr, ReadPipeInit);
-#ifndef USE_MEMCPY
-	for (i = 0; i < 5; i++) {
-		/* N.B. you have to increase the source address in this way or the
-		   ECC logic will not work properly */
-		eccbuf[i] = ReadDOC(docptr, Mil_CDSN_IO + i);
-	}
-#else
-	memcpy_fromio(eccbuf, docptr + DoC_Mil_CDSN_IO, 5);
-#endif
-	eccbuf[5] = ReadDOC(docptr, LastDataRead);
-
-	/* Flush the pipeline */
-	dummy = ReadDOC(docptr, ECCConf);
-	dummy = ReadDOC(docptr, ECCConf);
-
-	/* Check the ECC Status */
-	if (ReadDOC(docptr, ECCConf) & 0x80) {
-		int nb_errors;
-		/* There was an ECC error */
-#ifdef ECC_DEBUG
-		printk("DiskOnChip ECC Error: Read at %lx\n", (long)from);
-#endif
-		/* Read the ECC syndrome through the DiskOnChip ECC logic.
-		   These syndrome will be all ZERO when there is no error */
-		for (i = 0; i < 6; i++) {
-			syndrome[i] = ReadDOC(docptr, ECCSyndrome0 + i);
-		}
-		nb_errors = doc_decode_ecc(buf, syndrome);
-#ifdef ECC_DEBUG
-		printk("ECC Errors corrected: %x\n", nb_errors);
-#endif
-		if (nb_errors < 0) {
-			/* We return error, but have actually done the read. Not that
-			   this can be told to user-space, via sys_read(), but at least
-			   MTD-aware stuff can know about it by checking *retlen */
-			ret = -EIO;
-		}
-	}
-
-#ifdef PSYCHO_DEBUG
-	printk("ECC DATA at %lx: %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n",
-	       (long)from, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3],
-	       eccbuf[4], eccbuf[5]);
-#endif
-
-	/* disable the ECC engine */
-	WriteDOC(DOC_ECC_DIS, docptr , ECCConf);
-
-	return ret;
-}
-
-static int doc_write (struct mtd_info *mtd, loff_t to, size_t len,
-		      size_t *retlen, const u_char *buf)
-{
-	int i,ret = 0;
-	char eccbuf[6];
-	volatile char dummy;
-	struct DiskOnChip *this = mtd->priv;
-	void __iomem *docptr = this->virtadr;
-	struct Nand *mychip = &this->chips[to >> (this->chipshift)];
-
-#if 0
-	/* Don't allow a single write to cross a 512-byte block boundary */
-	if (to + len > ( (to | 0x1ff) + 1))
-		len = ((to | 0x1ff) + 1) - to;
-#else
-	/* Don't allow writes which aren't exactly one block */
-	if (to & 0x1ff || len != 0x200)
-		return -EINVAL;
-#endif
-
-	/* Find the chip which is to be used and select it */
-	if (this->curfloor != mychip->floor) {
-		DoC_SelectFloor(docptr, mychip->floor);
-		DoC_SelectChip(docptr, mychip->chip);
-	} else if (this->curchip != mychip->chip) {
-		DoC_SelectChip(docptr, mychip->chip);
-	}
-	this->curfloor = mychip->floor;
-	this->curchip = mychip->chip;
-
-	/* Reset the chip, see Software Requirement 11.4 item 1. */
-	DoC_Command(docptr, NAND_CMD_RESET, 0x00);
-	DoC_WaitReady(docptr);
-	/* Set device to main plane of flash */
-	DoC_Command(docptr, NAND_CMD_READ0, 0x00);
-
-	/* issue the Serial Data In command to initial the Page Program process */
-	DoC_Command(docptr, NAND_CMD_SEQIN, 0x00);
-	DoC_Address(docptr, 3, to, 0x00, 0x00);
-	DoC_WaitReady(docptr);
-
-	/* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/
-	WriteDOC (DOC_ECC_RESET, docptr, ECCConf);
-	WriteDOC (DOC_ECC_EN | DOC_ECC_RW, docptr, ECCConf);
-
-	/* Write the data via the internal pipeline through CDSN IO register,
-	   see Pipelined Write Operations 11.2 */
-#ifndef USE_MEMCPY
-	for (i = 0; i < len; i++) {
-		/* N.B. you have to increase the source address in this way or the
-		   ECC logic will not work properly */
-		WriteDOC(buf[i], docptr, Mil_CDSN_IO + i);
-	}
-#else
-	memcpy_toio(docptr + DoC_Mil_CDSN_IO, buf, len);
-#endif
-	WriteDOC(0x00, docptr, WritePipeTerm);
-
-	/* Write ECC data to flash, the ECC info is generated by the DiskOnChip ECC logic
-	   see Reed-Solomon EDC/ECC 11.1 */
-	WriteDOC(0, docptr, NOP);
-	WriteDOC(0, docptr, NOP);
-	WriteDOC(0, docptr, NOP);
-
-	/* Read the ECC data through the DiskOnChip ECC logic */
-	for (i = 0; i < 6; i++) {
-		eccbuf[i] = ReadDOC(docptr, ECCSyndrome0 + i);
-	}
-
-	/* ignore the ECC engine */
-	WriteDOC(DOC_ECC_DIS, docptr , ECCConf);
-
-#ifndef USE_MEMCPY
-	/* Write the ECC data to flash */
-	for (i = 0; i < 6; i++) {
-		/* N.B. you have to increase the source address in this way or the
-		   ECC logic will not work properly */
-		WriteDOC(eccbuf[i], docptr, Mil_CDSN_IO + i);
-	}
-#else
-	memcpy_toio(docptr + DoC_Mil_CDSN_IO, eccbuf, 6);
-#endif
-
-	/* write the block status BLOCK_USED (0x5555) at the end of ECC data
-	   FIXME: this is only a hack for programming the IPL area for LinuxBIOS
-	   and should be replace with proper codes in user space utilities */
-	WriteDOC(0x55, docptr, Mil_CDSN_IO);
-	WriteDOC(0x55, docptr, Mil_CDSN_IO + 1);
-
-	WriteDOC(0x00, docptr, WritePipeTerm);
-
-#ifdef PSYCHO_DEBUG
-	printk("OOB data at %lx is %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n",
-	       (long) to, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3],
-	       eccbuf[4], eccbuf[5]);
-#endif
-
-	/* Commit the Page Program command and wait for ready
-	   see Software Requirement 11.4 item 1.*/
-	DoC_Command(docptr, NAND_CMD_PAGEPROG, 0x00);
-	DoC_WaitReady(docptr);
-
-	/* Read the status of the flash device through CDSN IO register
-	   see Software Requirement 11.4 item 5.*/
-	DoC_Command(docptr, NAND_CMD_STATUS, CDSN_CTRL_WP);
-	dummy = ReadDOC(docptr, ReadPipeInit);
-	DoC_Delay(docptr, 2);
-	if (ReadDOC(docptr, Mil_CDSN_IO) & 1) {
-		printk("Error programming flash\n");
-		/* Error in programming
-		   FIXME: implement Bad Block Replacement (in nftl.c ??) */
-		ret = -EIO;
-	}
-	dummy = ReadDOC(docptr, LastDataRead);
-
-	/* Let the caller know we completed it */
-	*retlen = len;
-
-	return ret;
-}
-
-static int doc_read_oob(struct mtd_info *mtd, loff_t ofs,
-			struct mtd_oob_ops *ops)
-{
-#ifndef USE_MEMCPY
-	int i;
-#endif
-	volatile char dummy;
-	struct DiskOnChip *this = mtd->priv;
-	void __iomem *docptr = this->virtadr;
-	struct Nand *mychip = &this->chips[ofs >> this->chipshift];
-	uint8_t *buf = ops->oobbuf;
-	size_t len = ops->len;
-
-	BUG_ON(ops->mode != MTD_OPS_PLACE_OOB);
-
-	ofs += ops->ooboffs;
-
-	/* Find the chip which is to be used and select it */
-	if (this->curfloor != mychip->floor) {
-		DoC_SelectFloor(docptr, mychip->floor);
-		DoC_SelectChip(docptr, mychip->chip);
-	} else if (this->curchip != mychip->chip) {
-		DoC_SelectChip(docptr, mychip->chip);
-	}
-	this->curfloor = mychip->floor;
-	this->curchip = mychip->chip;
-
-	/* disable the ECC engine */
-	WriteDOC (DOC_ECC_RESET, docptr, ECCConf);
-	WriteDOC (DOC_ECC_DIS, docptr, ECCConf);
-
-	/* issue the Read2 command to set the pointer to the Spare Data Area.
-	   Polling the Flash Ready bit after issue 3 bytes address in
-	   Sequence Read Mode, see Software Requirement 11.4 item 1.*/
-	DoC_Command(docptr, NAND_CMD_READOOB, CDSN_CTRL_WP);
-	DoC_Address(docptr, 3, ofs, CDSN_CTRL_WP, 0x00);
-	DoC_WaitReady(docptr);
-
-	/* Read the data out via the internal pipeline through CDSN IO register,
-	   see Pipelined Read Operations 11.3 */
-	dummy = ReadDOC(docptr, ReadPipeInit);
-#ifndef USE_MEMCPY
-	for (i = 0; i < len-1; i++) {
-		/* N.B. you have to increase the source address in this way or the
-		   ECC logic will not work properly */
-		buf[i] = ReadDOC(docptr, Mil_CDSN_IO + i);
-	}
-#else
-	memcpy_fromio(buf, docptr + DoC_Mil_CDSN_IO, len - 1);
-#endif
-	buf[len - 1] = ReadDOC(docptr, LastDataRead);
-
-	ops->retlen = len;
-
-	return 0;
-}
-
-static int doc_write_oob(struct mtd_info *mtd, loff_t ofs,
-			 struct mtd_oob_ops *ops)
-{
-#ifndef USE_MEMCPY
-	int i;
-#endif
-	volatile char dummy;
-	int ret = 0;
-	struct DiskOnChip *this = mtd->priv;
-	void __iomem *docptr = this->virtadr;
-	struct Nand *mychip = &this->chips[ofs >> this->chipshift];
-	uint8_t *buf = ops->oobbuf;
-	size_t len = ops->len;
-
-	BUG_ON(ops->mode != MTD_OPS_PLACE_OOB);
-
-	ofs += ops->ooboffs;
-
-	/* Find the chip which is to be used and select it */
-	if (this->curfloor != mychip->floor) {
-		DoC_SelectFloor(docptr, mychip->floor);
-		DoC_SelectChip(docptr, mychip->chip);
-	} else if (this->curchip != mychip->chip) {
-		DoC_SelectChip(docptr, mychip->chip);
-	}
-	this->curfloor = mychip->floor;
-	this->curchip = mychip->chip;
-
-	/* disable the ECC engine */
-	WriteDOC (DOC_ECC_RESET, docptr, ECCConf);
-	WriteDOC (DOC_ECC_DIS, docptr, ECCConf);
-
-	/* Reset the chip, see Software Requirement 11.4 item 1. */
-	DoC_Command(docptr, NAND_CMD_RESET, CDSN_CTRL_WP);
-	DoC_WaitReady(docptr);
-	/* issue the Read2 command to set the pointer to the Spare Data Area. */
-	DoC_Command(docptr, NAND_CMD_READOOB, CDSN_CTRL_WP);
-
-	/* issue the Serial Data In command to initial the Page Program process */
-	DoC_Command(docptr, NAND_CMD_SEQIN, 0x00);
-	DoC_Address(docptr, 3, ofs, 0x00, 0x00);
-
-	/* Write the data via the internal pipeline through CDSN IO register,
-	   see Pipelined Write Operations 11.2 */
-#ifndef USE_MEMCPY
-	for (i = 0; i < len; i++) {
-		/* N.B. you have to increase the source address in this way or the
-		   ECC logic will not work properly */
-		WriteDOC(buf[i], docptr, Mil_CDSN_IO + i);
-	}
-#else
-	memcpy_toio(docptr + DoC_Mil_CDSN_IO, buf, len);
-#endif
-	WriteDOC(0x00, docptr, WritePipeTerm);
-
-	/* Commit the Page Program command and wait for ready
-	   see Software Requirement 11.4 item 1.*/
-	DoC_Command(docptr, NAND_CMD_PAGEPROG, 0x00);
-	DoC_WaitReady(docptr);
-
-	/* Read the status of the flash device through CDSN IO register
-	   see Software Requirement 11.4 item 5.*/
-	DoC_Command(docptr, NAND_CMD_STATUS, 0x00);
-	dummy = ReadDOC(docptr, ReadPipeInit);
-	DoC_Delay(docptr, 2);
-	if (ReadDOC(docptr, Mil_CDSN_IO) & 1) {
-		printk("Error programming oob data\n");
-		/* FIXME: implement Bad Block Replacement (in nftl.c ??) */
-		ops->retlen = 0;
-		ret = -EIO;
-	}
-	dummy = ReadDOC(docptr, LastDataRead);
-
-	ops->retlen = len;
-
-	return ret;
-}
-
-int doc_erase (struct mtd_info *mtd, struct erase_info *instr)
-{
-	volatile char dummy;
-	struct DiskOnChip *this = mtd->priv;
-	__u32 ofs = instr->addr;
-	__u32 len = instr->len;
-	void __iomem *docptr = this->virtadr;
-	struct Nand *mychip = &this->chips[ofs >> this->chipshift];
-
-	if (len != mtd->erasesize)
-		printk(KERN_WARNING "Erase not right size (%x != %x)n",
-		       len, mtd->erasesize);
-
-	/* Find the chip which is to be used and select it */
-	if (this->curfloor != mychip->floor) {
-		DoC_SelectFloor(docptr, mychip->floor);
-		DoC_SelectChip(docptr, mychip->chip);
-	} else if (this->curchip != mychip->chip) {
-		DoC_SelectChip(docptr, mychip->chip);
-	}
-	this->curfloor = mychip->floor;
-	this->curchip = mychip->chip;
-
-	instr->state = MTD_ERASE_PENDING;
-
-	/* issue the Erase Setup command */
-	DoC_Command(docptr, NAND_CMD_ERASE1, 0x00);
-	DoC_Address(docptr, 2, ofs, 0x00, 0x00);
-
-	/* Commit the Erase Start command and wait for ready
-	   see Software Requirement 11.4 item 1.*/
-	DoC_Command(docptr, NAND_CMD_ERASE2, 0x00);
-	DoC_WaitReady(docptr);
-
-	instr->state = MTD_ERASING;
-
-	/* Read the status of the flash device through CDSN IO register
-	   see Software Requirement 11.4 item 5.
-	   FIXME: it seems that we are not wait long enough, some blocks are not
-	   erased fully */
-	DoC_Command(docptr, NAND_CMD_STATUS, CDSN_CTRL_WP);
-	dummy = ReadDOC(docptr, ReadPipeInit);
-	DoC_Delay(docptr, 2);
-	if (ReadDOC(docptr, Mil_CDSN_IO) & 1) {
-		printk("Error Erasing at 0x%x\n", ofs);
-		/* There was an error
-		   FIXME: implement Bad Block Replacement (in nftl.c ??) */
-		instr->state = MTD_ERASE_FAILED;
-	} else
-		instr->state = MTD_ERASE_DONE;
-	dummy = ReadDOC(docptr, LastDataRead);
-
-	mtd_erase_callback(instr);
-
-	return 0;
-}
-
-/****************************************************************************
- *
- * Module stuff
- *
- ****************************************************************************/
-
-static void __exit cleanup_doc2001(void)
-{
-	struct mtd_info *mtd;
-	struct DiskOnChip *this;
-
-	while ((mtd=docmillist)) {
-		this = mtd->priv;
-		docmillist = this->nextdoc;
-
-		mtd_device_unregister(mtd);
-
-		iounmap(this->virtadr);
-		kfree(this->chips);
-		kfree(mtd);
-	}
-}
-
-module_exit(cleanup_doc2001);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org> et al.");
-MODULE_DESCRIPTION("Alternative driver for DiskOnChip Millennium");
diff --git a/drivers/mtd/devices/doc2001plus.c b/drivers/mtd/devices/doc2001plus.c
deleted file mode 100644
index 4f2220a..0000000
--- a/drivers/mtd/devices/doc2001plus.c
+++ /dev/null
@@ -1,1080 +0,0 @@
-/*
- * Linux driver for Disk-On-Chip Millennium Plus
- *
- * (c) 2002-2003 Greg Ungerer <gerg@snapgear.com>
- * (c) 2002-2003 SnapGear Inc
- * (c) 1999 Machine Vision Holdings, Inc.
- * (c) 1999, 2000 David Woodhouse <dwmw2@infradead.org>
- *
- * Released under GPL
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <asm/errno.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/bitops.h>
-
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
-#include <linux/mtd/doc2000.h>
-
-/* #define ECC_DEBUG */
-
-/* I have no idea why some DoC chips can not use memcop_form|to_io().
- * This may be due to the different revisions of the ASIC controller built-in or
- * simplily a QA/Bug issue. Who knows ?? If you have trouble, please uncomment
- * this:*/
-#undef USE_MEMCPY
-
-static int doc_read(struct mtd_info *mtd, loff_t from, size_t len,
-		size_t *retlen, u_char *buf);
-static int doc_write(struct mtd_info *mtd, loff_t to, size_t len,
-		size_t *retlen, const u_char *buf);
-static int doc_read_oob(struct mtd_info *mtd, loff_t ofs,
-			struct mtd_oob_ops *ops);
-static int doc_write_oob(struct mtd_info *mtd, loff_t ofs,
-			 struct mtd_oob_ops *ops);
-static int doc_erase (struct mtd_info *mtd, struct erase_info *instr);
-
-static struct mtd_info *docmilpluslist = NULL;
-
-
-/* Perform the required delay cycles by writing to the NOP register */
-static void DoC_Delay(void __iomem * docptr, int cycles)
-{
-	int i;
-
-	for (i = 0; (i < cycles); i++)
-		WriteDOC(0, docptr, Mplus_NOP);
-}
-
-#define	CDSN_CTRL_FR_B_MASK	(CDSN_CTRL_FR_B0 | CDSN_CTRL_FR_B1)
-
-/* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */
-static int _DoC_WaitReady(void __iomem * docptr)
-{
-	unsigned int c = 0xffff;
-
-	pr_debug("_DoC_WaitReady called for out-of-line wait\n");
-
-	/* Out-of-line routine to wait for chip response */
-	while (((ReadDOC(docptr, Mplus_FlashControl) & CDSN_CTRL_FR_B_MASK) != CDSN_CTRL_FR_B_MASK) && --c)
-		;
-
-	if (c == 0)
-		pr_debug("_DoC_WaitReady timed out.\n");
-
-	return (c == 0);
-}
-
-static inline int DoC_WaitReady(void __iomem * docptr)
-{
-	/* This is inline, to optimise the common case, where it's ready instantly */
-	int ret = 0;
-
-	/* read form NOP register should be issued prior to the read from CDSNControl
-	   see Software Requirement 11.4 item 2. */
-	DoC_Delay(docptr, 4);
-
-	if ((ReadDOC(docptr, Mplus_FlashControl) & CDSN_CTRL_FR_B_MASK) != CDSN_CTRL_FR_B_MASK)
-		/* Call the out-of-line routine to wait */
-		ret = _DoC_WaitReady(docptr);
-
-	return ret;
-}
-
-/* For some reason the Millennium Plus seems to occasionally put itself
- * into reset mode. For me this happens randomly, with no pattern that I
- * can detect. M-systems suggest always check this on any block level
- * operation and setting to normal mode if in reset mode.
- */
-static inline void DoC_CheckASIC(void __iomem * docptr)
-{
-	/* Make sure the DoC is in normal mode */
-	if ((ReadDOC(docptr, Mplus_DOCControl) & DOC_MODE_NORMAL) == 0) {
-		WriteDOC((DOC_MODE_NORMAL | DOC_MODE_MDWREN), docptr, Mplus_DOCControl);
-		WriteDOC(~(DOC_MODE_NORMAL | DOC_MODE_MDWREN), docptr, Mplus_CtrlConfirm);
-	}
-}
-
-/* DoC_Command: Send a flash command to the flash chip through the Flash
- * command register. Need 2 Write Pipeline Terminates to complete send.
- */
-static void DoC_Command(void __iomem * docptr, unsigned char command,
-			       unsigned char xtraflags)
-{
-	WriteDOC(command, docptr, Mplus_FlashCmd);
-	WriteDOC(command, docptr, Mplus_WritePipeTerm);
-	WriteDOC(command, docptr, Mplus_WritePipeTerm);
-}
-
-/* DoC_Address: Set the current address for the flash chip through the Flash
- * Address register. Need 2 Write Pipeline Terminates to complete send.
- */
-static inline void DoC_Address(struct DiskOnChip *doc, int numbytes,
-			       unsigned long ofs, unsigned char xtraflags1,
-			       unsigned char xtraflags2)
-{
-	void __iomem * docptr = doc->virtadr;
-
-	/* Allow for possible Mill Plus internal flash interleaving */
-	ofs >>= doc->interleave;
-
-	switch (numbytes) {
-	case 1:
-		/* Send single byte, bits 0-7. */
-		WriteDOC(ofs & 0xff, docptr, Mplus_FlashAddress);
-		break;
-	case 2:
-		/* Send bits 9-16 followed by 17-23 */
-		WriteDOC((ofs >> 9)  & 0xff, docptr, Mplus_FlashAddress);
-		WriteDOC((ofs >> 17) & 0xff, docptr, Mplus_FlashAddress);
-		break;
-	case 3:
-		/* Send 0-7, 9-16, then 17-23 */
-		WriteDOC(ofs & 0xff, docptr, Mplus_FlashAddress);
-		WriteDOC((ofs >> 9)  & 0xff, docptr, Mplus_FlashAddress);
-		WriteDOC((ofs >> 17) & 0xff, docptr, Mplus_FlashAddress);
-		break;
-	default:
-		return;
-	}
-
-	WriteDOC(0x00, docptr, Mplus_WritePipeTerm);
-	WriteDOC(0x00, docptr, Mplus_WritePipeTerm);
-}
-
-/* DoC_SelectChip: Select a given flash chip within the current floor */
-static int DoC_SelectChip(void __iomem * docptr, int chip)
-{
-	/* No choice for flash chip on Millennium Plus */
-	return 0;
-}
-
-/* DoC_SelectFloor: Select a given floor (bank of flash chips) */
-static int DoC_SelectFloor(void __iomem * docptr, int floor)
-{
-	WriteDOC((floor & 0x3), docptr, Mplus_DeviceSelect);
-	return 0;
-}
-
-/*
- * Translate the given offset into the appropriate command and offset.
- * This does the mapping using the 16bit interleave layout defined by
- * M-Systems, and looks like this for a sector pair:
- *  +-----------+-------+-------+-------+--------------+---------+-----------+
- *  | 0 --- 511 |512-517|518-519|520-521| 522 --- 1033 |1034-1039|1040 - 1055|
- *  +-----------+-------+-------+-------+--------------+---------+-----------+
- *  | Data 0    | ECC 0 |Flags0 |Flags1 | Data 1       |ECC 1    | OOB 1 + 2 |
- *  +-----------+-------+-------+-------+--------------+---------+-----------+
- */
-/* FIXME: This lives in INFTL not here. Other users of flash devices
-   may not want it */
-static unsigned int DoC_GetDataOffset(struct mtd_info *mtd, loff_t *from)
-{
-	struct DiskOnChip *this = mtd->priv;
-
-	if (this->interleave) {
-		unsigned int ofs = *from & 0x3ff;
-		unsigned int cmd;
-
-		if (ofs < 512) {
-			cmd = NAND_CMD_READ0;
-			ofs &= 0x1ff;
-		} else if (ofs < 1014) {
-			cmd = NAND_CMD_READ1;
-			ofs = (ofs & 0x1ff) + 10;
-		} else {
-			cmd = NAND_CMD_READOOB;
-			ofs = ofs - 1014;
-		}
-
-		*from = (*from & ~0x3ff) | ofs;
-		return cmd;
-	} else {
-		/* No interleave */
-		if ((*from) & 0x100)
-			return NAND_CMD_READ1;
-		return NAND_CMD_READ0;
-	}
-}
-
-static unsigned int DoC_GetECCOffset(struct mtd_info *mtd, loff_t *from)
-{
-	unsigned int ofs, cmd;
-
-	if (*from & 0x200) {
-		cmd = NAND_CMD_READOOB;
-		ofs = 10 + (*from & 0xf);
-	} else {
-		cmd = NAND_CMD_READ1;
-		ofs = (*from & 0xf);
-	}
-
-	*from = (*from & ~0x3ff) | ofs;
-	return cmd;
-}
-
-static unsigned int DoC_GetFlagsOffset(struct mtd_info *mtd, loff_t *from)
-{
-	unsigned int ofs, cmd;
-
-	cmd = NAND_CMD_READ1;
-	ofs = (*from & 0x200) ? 8 : 6;
-	*from = (*from & ~0x3ff) | ofs;
-	return cmd;
-}
-
-static unsigned int DoC_GetHdrOffset(struct mtd_info *mtd, loff_t *from)
-{
-	unsigned int ofs, cmd;
-
-	cmd = NAND_CMD_READOOB;
-	ofs = (*from & 0x200) ? 24 : 16;
-	*from = (*from & ~0x3ff) | ofs;
-	return cmd;
-}
-
-static inline void MemReadDOC(void __iomem * docptr, unsigned char *buf, int len)
-{
-#ifndef USE_MEMCPY
-	int i;
-	for (i = 0; i < len; i++)
-		buf[i] = ReadDOC(docptr, Mil_CDSN_IO + i);
-#else
-	memcpy_fromio(buf, docptr + DoC_Mil_CDSN_IO, len);
-#endif
-}
-
-static inline void MemWriteDOC(void __iomem * docptr, unsigned char *buf, int len)
-{
-#ifndef USE_MEMCPY
-	int i;
-	for (i = 0; i < len; i++)
-		WriteDOC(buf[i], docptr, Mil_CDSN_IO + i);
-#else
-	memcpy_toio(docptr + DoC_Mil_CDSN_IO, buf, len);
-#endif
-}
-
-/* DoC_IdentChip: Identify a given NAND chip given {floor,chip} */
-static int DoC_IdentChip(struct DiskOnChip *doc, int floor, int chip)
-{
-	int mfr, id, i, j;
-	volatile char dummy;
-	void __iomem * docptr = doc->virtadr;
-
-	/* Page in the required floor/chip */
-	DoC_SelectFloor(docptr, floor);
-	DoC_SelectChip(docptr, chip);
-
-	/* Millennium Plus bus cycle sequence as per figure 2, section 2.4 */
-	WriteDOC((DOC_FLASH_CE | DOC_FLASH_WP), docptr, Mplus_FlashSelect);
-
-	/* Reset the chip, see Software Requirement 11.4 item 1. */
-	DoC_Command(docptr, NAND_CMD_RESET, 0);
-	DoC_WaitReady(docptr);
-
-	/* Read the NAND chip ID: 1. Send ReadID command */
-	DoC_Command(docptr, NAND_CMD_READID, 0);
-
-	/* Read the NAND chip ID: 2. Send address byte zero */
-	DoC_Address(doc, 1, 0x00, 0, 0x00);
-
-	WriteDOC(0, docptr, Mplus_FlashControl);
-	DoC_WaitReady(docptr);
-
-	/* Read the manufacturer and device id codes of the flash device through
-	   CDSN IO register see Software Requirement 11.4 item 5.*/
-	dummy = ReadDOC(docptr, Mplus_ReadPipeInit);
-	dummy = ReadDOC(docptr, Mplus_ReadPipeInit);
-
-	mfr = ReadDOC(docptr, Mil_CDSN_IO);
-	if (doc->interleave)
-		dummy = ReadDOC(docptr, Mil_CDSN_IO); /* 2 way interleave */
-
-	id  = ReadDOC(docptr, Mil_CDSN_IO);
-	if (doc->interleave)
-		dummy = ReadDOC(docptr, Mil_CDSN_IO); /* 2 way interleave */
-
-	dummy = ReadDOC(docptr, Mplus_LastDataRead);
-	dummy = ReadDOC(docptr, Mplus_LastDataRead);
-
-	/* Disable flash internally */
-	WriteDOC(0, docptr, Mplus_FlashSelect);
-
-	/* No response - return failure */
-	if (mfr == 0xff || mfr == 0)
-		return 0;
-
-	for (i = 0; nand_flash_ids[i].name != NULL; i++) {
-		if (id == nand_flash_ids[i].id) {
-			/* Try to identify manufacturer */
-			for (j = 0; nand_manuf_ids[j].id != 0x0; j++) {
-				if (nand_manuf_ids[j].id == mfr)
-					break;
-			}
-			printk(KERN_INFO "Flash chip found: Manufacturer ID: %2.2X, "
-			       "Chip ID: %2.2X (%s:%s)\n", mfr, id,
-			       nand_manuf_ids[j].name, nand_flash_ids[i].name);
-			doc->mfr = mfr;
-			doc->id = id;
-			doc->chipshift = ffs((nand_flash_ids[i].chipsize << 20)) - 1;
-			doc->erasesize = nand_flash_ids[i].erasesize << doc->interleave;
-			break;
-		}
-	}
-
-	if (nand_flash_ids[i].name == NULL)
-		return 0;
-	return 1;
-}
-
-/* DoC_ScanChips: Find all NAND chips present in a DiskOnChip, and identify them */
-static void DoC_ScanChips(struct DiskOnChip *this)
-{
-	int floor, chip;
-	int numchips[MAX_FLOORS_MPLUS];
-	int ret;
-
-	this->numchips = 0;
-	this->mfr = 0;
-	this->id = 0;
-
-	/* Work out the intended interleave setting */
-	this->interleave = 0;
-	if (this->ChipID == DOC_ChipID_DocMilPlus32)
-		this->interleave = 1;
-
-	/* Check the ASIC agrees */
-	if ( (this->interleave << 2) !=
-	     (ReadDOC(this->virtadr, Mplus_Configuration) & 4)) {
-		u_char conf = ReadDOC(this->virtadr, Mplus_Configuration);
-		printk(KERN_NOTICE "Setting DiskOnChip Millennium Plus interleave to %s\n",
-		       this->interleave?"on (16-bit)":"off (8-bit)");
-		conf ^= 4;
-		WriteDOC(conf, this->virtadr, Mplus_Configuration);
-	}
-
-	/* For each floor, find the number of valid chips it contains */
-	for (floor = 0,ret = 1; floor < MAX_FLOORS_MPLUS; floor++) {
-		numchips[floor] = 0;
-		for (chip = 0; chip < MAX_CHIPS_MPLUS && ret != 0; chip++) {
-			ret = DoC_IdentChip(this, floor, chip);
-			if (ret) {
-				numchips[floor]++;
-				this->numchips++;
-			}
-		}
-	}
-	/* If there are none at all that we recognise, bail */
-	if (!this->numchips) {
-		printk("No flash chips recognised.\n");
-		return;
-	}
-
-	/* Allocate an array to hold the information for each chip */
-	this->chips = kmalloc(sizeof(struct Nand) * this->numchips, GFP_KERNEL);
-	if (!this->chips){
-		printk("MTD: No memory for allocating chip info structures\n");
-		return;
-	}
-
-	/* Fill out the chip array with {floor, chipno} for each
-	 * detected chip in the device. */
-	for (floor = 0, ret = 0; floor < MAX_FLOORS_MPLUS; floor++) {
-		for (chip = 0 ; chip < numchips[floor] ; chip++) {
-			this->chips[ret].floor = floor;
-			this->chips[ret].chip = chip;
-			this->chips[ret].curadr = 0;
-			this->chips[ret].curmode = 0x50;
-			ret++;
-		}
-	}
-
-	/* Calculate and print the total size of the device */
-	this->totlen = this->numchips * (1 << this->chipshift);
-	printk(KERN_INFO "%d flash chips found. Total DiskOnChip size: %ld MiB\n",
-	       this->numchips ,this->totlen >> 20);
-}
-
-static int DoCMilPlus_is_alias(struct DiskOnChip *doc1, struct DiskOnChip *doc2)
-{
-	int tmp1, tmp2, retval;
-
-	if (doc1->physadr == doc2->physadr)
-		return 1;
-
-	/* Use the alias resolution register which was set aside for this
-	 * purpose. If it's value is the same on both chips, they might
-	 * be the same chip, and we write to one and check for a change in
-	 * the other. It's unclear if this register is usuable in the
-	 * DoC 2000 (it's in the Millennium docs), but it seems to work. */
-	tmp1 = ReadDOC(doc1->virtadr, Mplus_AliasResolution);
-	tmp2 = ReadDOC(doc2->virtadr, Mplus_AliasResolution);
-	if (tmp1 != tmp2)
-		return 0;
-
-	WriteDOC((tmp1+1) % 0xff, doc1->virtadr, Mplus_AliasResolution);
-	tmp2 = ReadDOC(doc2->virtadr, Mplus_AliasResolution);
-	if (tmp2 == (tmp1+1) % 0xff)
-		retval = 1;
-	else
-		retval = 0;
-
-	/* Restore register contents.  May not be necessary, but do it just to
-	 * be safe. */
-	WriteDOC(tmp1, doc1->virtadr, Mplus_AliasResolution);
-
-	return retval;
-}
-
-/* This routine is found from the docprobe code by symbol_get(),
- * which will bump the use count of this module. */
-void DoCMilPlus_init(struct mtd_info *mtd)
-{
-	struct DiskOnChip *this = mtd->priv;
-	struct DiskOnChip *old = NULL;
-
-	/* We must avoid being called twice for the same device. */
-	if (docmilpluslist)
-		old = docmilpluslist->priv;
-
-	while (old) {
-		if (DoCMilPlus_is_alias(this, old)) {
-			printk(KERN_NOTICE "Ignoring DiskOnChip Millennium "
-				"Plus at 0x%lX - already configured\n",
-				this->physadr);
-			iounmap(this->virtadr);
-			kfree(mtd);
-			return;
-		}
-		if (old->nextdoc)
-			old = old->nextdoc->priv;
-		else
-			old = NULL;
-	}
-
-	mtd->name = "DiskOnChip Millennium Plus";
-	printk(KERN_NOTICE "DiskOnChip Millennium Plus found at "
-		"address 0x%lX\n", this->physadr);
-
-	mtd->type = MTD_NANDFLASH;
-	mtd->flags = MTD_CAP_NANDFLASH;
-	mtd->writebufsize = mtd->writesize = 512;
-	mtd->oobsize = 16;
-	mtd->ecc_strength = 2;
-	mtd->owner = THIS_MODULE;
-	mtd->_erase = doc_erase;
-	mtd->_read = doc_read;
-	mtd->_write = doc_write;
-	mtd->_read_oob = doc_read_oob;
-	mtd->_write_oob = doc_write_oob;
-	this->curfloor = -1;
-	this->curchip = -1;
-
-	/* Ident all the chips present. */
-	DoC_ScanChips(this);
-
-	if (!this->totlen) {
-		kfree(mtd);
-		iounmap(this->virtadr);
-	} else {
-		this->nextdoc = docmilpluslist;
-		docmilpluslist = mtd;
-		mtd->size  = this->totlen;
-		mtd->erasesize = this->erasesize;
-		mtd_device_register(mtd, NULL, 0);
-		return;
-	}
-}
-EXPORT_SYMBOL_GPL(DoCMilPlus_init);
-
-#if 0
-static int doc_dumpblk(struct mtd_info *mtd, loff_t from)
-{
-	int i;
-	loff_t fofs;
-	struct DiskOnChip *this = mtd->priv;
-	void __iomem * docptr = this->virtadr;
-	struct Nand *mychip = &this->chips[from >> (this->chipshift)];
-	unsigned char *bp, buf[1056];
-	char c[32];
-
-	from &= ~0x3ff;
-
-	/* Don't allow read past end of device */
-	if (from >= this->totlen)
-		return -EINVAL;
-
-	DoC_CheckASIC(docptr);
-
-	/* Find the chip which is to be used and select it */
-	if (this->curfloor != mychip->floor) {
-		DoC_SelectFloor(docptr, mychip->floor);
-		DoC_SelectChip(docptr, mychip->chip);
-	} else if (this->curchip != mychip->chip) {
-		DoC_SelectChip(docptr, mychip->chip);
-	}
-	this->curfloor = mychip->floor;
-	this->curchip = mychip->chip;
-
-	/* Millennium Plus bus cycle sequence as per figure 2, section 2.4 */
-	WriteDOC((DOC_FLASH_CE | DOC_FLASH_WP), docptr, Mplus_FlashSelect);
-
-	/* Reset the chip, see Software Requirement 11.4 item 1. */
-	DoC_Command(docptr, NAND_CMD_RESET, 0);
-	DoC_WaitReady(docptr);
-
-	fofs = from;
-	DoC_Command(docptr, DoC_GetDataOffset(mtd, &fofs), 0);
-	DoC_Address(this, 3, fofs, 0, 0x00);
-	WriteDOC(0, docptr, Mplus_FlashControl);
-	DoC_WaitReady(docptr);
-
-	/* disable the ECC engine */
-	WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf);
-
-	ReadDOC(docptr, Mplus_ReadPipeInit);
-	ReadDOC(docptr, Mplus_ReadPipeInit);
-
-	/* Read the data via the internal pipeline through CDSN IO
-	   register, see Pipelined Read Operations 11.3 */
-	MemReadDOC(docptr, buf, 1054);
-	buf[1054] = ReadDOC(docptr, Mplus_LastDataRead);
-	buf[1055] = ReadDOC(docptr, Mplus_LastDataRead);
-
-	memset(&c[0], 0, sizeof(c));
-	printk("DUMP OFFSET=%x:\n", (int)from);
-
-        for (i = 0, bp = &buf[0]; (i < 1056); i++) {
-                if ((i % 16) == 0)
-                        printk("%08x: ", i);
-                printk(" %02x", *bp);
-                c[(i & 0xf)] = ((*bp >= 0x20) && (*bp <= 0x7f)) ? *bp : '.';
-                bp++;
-                if (((i + 1) % 16) == 0)
-                        printk("    %s\n", c);
-        }
-	printk("\n");
-
-	/* Disable flash internally */
-	WriteDOC(0, docptr, Mplus_FlashSelect);
-
-	return 0;
-}
-#endif
-
-static int doc_read(struct mtd_info *mtd, loff_t from, size_t len,
-		    size_t *retlen, u_char *buf)
-{
-	int ret, i;
-	volatile char dummy;
-	loff_t fofs;
-	unsigned char syndrome[6], eccbuf[6];
-	struct DiskOnChip *this = mtd->priv;
-	void __iomem * docptr = this->virtadr;
-	struct Nand *mychip = &this->chips[from >> (this->chipshift)];
-
-	/* Don't allow a single read to cross a 512-byte block boundary */
-	if (from + len > ((from | 0x1ff) + 1))
-		len = ((from | 0x1ff) + 1) - from;
-
-	DoC_CheckASIC(docptr);
-
-	/* Find the chip which is to be used and select it */
-	if (this->curfloor != mychip->floor) {
-		DoC_SelectFloor(docptr, mychip->floor);
-		DoC_SelectChip(docptr, mychip->chip);
-	} else if (this->curchip != mychip->chip) {
-		DoC_SelectChip(docptr, mychip->chip);
-	}
-	this->curfloor = mychip->floor;
-	this->curchip = mychip->chip;
-
-	/* Millennium Plus bus cycle sequence as per figure 2, section 2.4 */
-	WriteDOC((DOC_FLASH_CE | DOC_FLASH_WP), docptr, Mplus_FlashSelect);
-
-	/* Reset the chip, see Software Requirement 11.4 item 1. */
-	DoC_Command(docptr, NAND_CMD_RESET, 0);
-	DoC_WaitReady(docptr);
-
-	fofs = from;
-	DoC_Command(docptr, DoC_GetDataOffset(mtd, &fofs), 0);
-	DoC_Address(this, 3, fofs, 0, 0x00);
-	WriteDOC(0, docptr, Mplus_FlashControl);
-	DoC_WaitReady(docptr);
-
-	/* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/
-	WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf);
-	WriteDOC(DOC_ECC_EN, docptr, Mplus_ECCConf);
-
-	/* Let the caller know we completed it */
-	*retlen = len;
-	ret = 0;
-
-	ReadDOC(docptr, Mplus_ReadPipeInit);
-	ReadDOC(docptr, Mplus_ReadPipeInit);
-
-	/* Read the data via the internal pipeline through CDSN IO
-	   register, see Pipelined Read Operations 11.3 */
-	MemReadDOC(docptr, buf, len);
-
-	/* Read the ECC data following raw data */
-	MemReadDOC(docptr, eccbuf, 4);
-	eccbuf[4] = ReadDOC(docptr, Mplus_LastDataRead);
-	eccbuf[5] = ReadDOC(docptr, Mplus_LastDataRead);
-
-	/* Flush the pipeline */
-	dummy = ReadDOC(docptr, Mplus_ECCConf);
-	dummy = ReadDOC(docptr, Mplus_ECCConf);
-
-	/* Check the ECC Status */
-	if (ReadDOC(docptr, Mplus_ECCConf) & 0x80) {
-		int nb_errors;
-		/* There was an ECC error */
-#ifdef ECC_DEBUG
-		printk("DiskOnChip ECC Error: Read at %lx\n", (long)from);
-#endif
-		/* Read the ECC syndrome through the DiskOnChip ECC logic.
-		   These syndrome will be all ZERO when there is no error */
-		for (i = 0; i < 6; i++)
-			syndrome[i] = ReadDOC(docptr, Mplus_ECCSyndrome0 + i);
-
-		nb_errors = doc_decode_ecc(buf, syndrome);
-#ifdef ECC_DEBUG
-		printk("ECC Errors corrected: %x\n", nb_errors);
-#endif
-		if (nb_errors < 0) {
-			/* We return error, but have actually done the
-			   read. Not that this can be told to user-space, via
-			   sys_read(), but at least MTD-aware stuff can know
-			   about it by checking *retlen */
-#ifdef ECC_DEBUG
-			printk("%s(%d): Millennium Plus ECC error (from=0x%x:\n",
-				__FILE__, __LINE__, (int)from);
-			printk("        syndrome= %*phC\n", 6, syndrome);
-			printk("        eccbuf= %*phC\n", 6, eccbuf);
-#endif
-				ret = -EIO;
-		}
-	}
-
-#ifdef PSYCHO_DEBUG
-	printk("ECC DATA at %lx: %*ph\n", (long)from, 6, eccbuf);
-#endif
-	/* disable the ECC engine */
-	WriteDOC(DOC_ECC_DIS, docptr , Mplus_ECCConf);
-
-	/* Disable flash internally */
-	WriteDOC(0, docptr, Mplus_FlashSelect);
-
-	return ret;
-}
-
-static int doc_write(struct mtd_info *mtd, loff_t to, size_t len,
-		     size_t *retlen, const u_char *buf)
-{
-	int i, before, ret = 0;
-	loff_t fto;
-	volatile char dummy;
-	char eccbuf[6];
-	struct DiskOnChip *this = mtd->priv;
-	void __iomem * docptr = this->virtadr;
-	struct Nand *mychip = &this->chips[to >> (this->chipshift)];
-
-	/* Don't allow writes which aren't exactly one block (512 bytes) */
-	if ((to & 0x1ff) || (len != 0x200))
-		return -EINVAL;
-
-	/* Determine position of OOB flags, before or after data */
-	before = (this->interleave && (to & 0x200));
-
-	DoC_CheckASIC(docptr);
-
-	/* Find the chip which is to be used and select it */
-	if (this->curfloor != mychip->floor) {
-		DoC_SelectFloor(docptr, mychip->floor);
-		DoC_SelectChip(docptr, mychip->chip);
-	} else if (this->curchip != mychip->chip) {
-		DoC_SelectChip(docptr, mychip->chip);
-	}
-	this->curfloor = mychip->floor;
-	this->curchip = mychip->chip;
-
-	/* Millennium Plus bus cycle sequence as per figure 2, section 2.4 */
-	WriteDOC(DOC_FLASH_CE, docptr, Mplus_FlashSelect);
-
-	/* Reset the chip, see Software Requirement 11.4 item 1. */
-	DoC_Command(docptr, NAND_CMD_RESET, 0);
-	DoC_WaitReady(docptr);
-
-	/* Set device to appropriate plane of flash */
-	fto = to;
-	WriteDOC(DoC_GetDataOffset(mtd, &fto), docptr, Mplus_FlashCmd);
-
-	/* On interleaved devices the flags for 2nd half 512 are before data */
-	if (before)
-		fto -= 2;
-
-	/* issue the Serial Data In command to initial the Page Program process */
-	DoC_Command(docptr, NAND_CMD_SEQIN, 0x00);
-	DoC_Address(this, 3, fto, 0x00, 0x00);
-
-	/* Disable the ECC engine */
-	WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf);
-
-	if (before) {
-		/* Write the block status BLOCK_USED (0x5555) */
-		WriteDOC(0x55, docptr, Mil_CDSN_IO);
-		WriteDOC(0x55, docptr, Mil_CDSN_IO);
-	}
-
-	/* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/
-	WriteDOC(DOC_ECC_EN | DOC_ECC_RW, docptr, Mplus_ECCConf);
-
-	MemWriteDOC(docptr, (unsigned char *) buf, len);
-
-	/* Write ECC data to flash, the ECC info is generated by
-	   the DiskOnChip ECC logic see Reed-Solomon EDC/ECC 11.1 */
-	DoC_Delay(docptr, 3);
-
-	/* Read the ECC data through the DiskOnChip ECC logic */
-	for (i = 0; i < 6; i++)
-		eccbuf[i] = ReadDOC(docptr, Mplus_ECCSyndrome0 + i);
-
-	/* disable the ECC engine */
-	WriteDOC(DOC_ECC_DIS, docptr, Mplus_ECCConf);
-
-	/* Write the ECC data to flash */
-	MemWriteDOC(docptr, eccbuf, 6);
-
-	if (!before) {
-		/* Write the block status BLOCK_USED (0x5555) */
-		WriteDOC(0x55, docptr, Mil_CDSN_IO+6);
-		WriteDOC(0x55, docptr, Mil_CDSN_IO+7);
-	}
-
-#ifdef PSYCHO_DEBUG
-	printk("OOB data at %lx is %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n",
-	       (long) to, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3],
-	       eccbuf[4], eccbuf[5]);
-#endif
-
-	WriteDOC(0x00, docptr, Mplus_WritePipeTerm);
-	WriteDOC(0x00, docptr, Mplus_WritePipeTerm);
-
-	/* Commit the Page Program command and wait for ready
-	   see Software Requirement 11.4 item 1.*/
-	DoC_Command(docptr, NAND_CMD_PAGEPROG, 0x00);
-	DoC_WaitReady(docptr);
-
-	/* Read the status of the flash device through CDSN IO register
-	   see Software Requirement 11.4 item 5.*/
-	DoC_Command(docptr, NAND_CMD_STATUS, 0);
-	dummy = ReadDOC(docptr, Mplus_ReadPipeInit);
-	dummy = ReadDOC(docptr, Mplus_ReadPipeInit);
-	DoC_Delay(docptr, 2);
-	if ((dummy = ReadDOC(docptr, Mplus_LastDataRead)) & 1) {
-		printk("MTD: Error 0x%x programming at 0x%x\n", dummy, (int)to);
-		/* Error in programming
-		   FIXME: implement Bad Block Replacement (in nftl.c ??) */
-		ret = -EIO;
-	}
-	dummy = ReadDOC(docptr, Mplus_LastDataRead);
-
-	/* Disable flash internally */
-	WriteDOC(0, docptr, Mplus_FlashSelect);
-
-	/* Let the caller know we completed it */
-	*retlen = len;
-
-	return ret;
-}
-
-static int doc_read_oob(struct mtd_info *mtd, loff_t ofs,
-			struct mtd_oob_ops *ops)
-{
-	loff_t fofs, base;
-	struct DiskOnChip *this = mtd->priv;
-	void __iomem * docptr = this->virtadr;
-	struct Nand *mychip = &this->chips[ofs >> this->chipshift];
-	size_t i, size, got, want;
-	uint8_t *buf = ops->oobbuf;
-	size_t len = ops->len;
-
-	BUG_ON(ops->mode != MTD_OPS_PLACE_OOB);
-
-	ofs += ops->ooboffs;
-
-	DoC_CheckASIC(docptr);
-
-	/* Find the chip which is to be used and select it */
-	if (this->curfloor != mychip->floor) {
-		DoC_SelectFloor(docptr, mychip->floor);
-		DoC_SelectChip(docptr, mychip->chip);
-	} else if (this->curchip != mychip->chip) {
-		DoC_SelectChip(docptr, mychip->chip);
-	}
-	this->curfloor = mychip->floor;
-	this->curchip = mychip->chip;
-
-	/* Millennium Plus bus cycle sequence as per figure 2, section 2.4 */
-	WriteDOC((DOC_FLASH_CE | DOC_FLASH_WP), docptr, Mplus_FlashSelect);
-
-	/* disable the ECC engine */
-	WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf);
-	DoC_WaitReady(docptr);
-
-	/* Maximum of 16 bytes in the OOB region, so limit read to that */
-	if (len > 16)
-		len = 16;
-	got = 0;
-	want = len;
-
-	for (i = 0; ((i < 3) && (want > 0)); i++) {
-		/* Figure out which region we are accessing... */
-		fofs = ofs;
-		base = ofs & 0xf;
-		if (!this->interleave) {
-			DoC_Command(docptr, NAND_CMD_READOOB, 0);
-			size = 16 - base;
-		} else if (base < 6) {
-			DoC_Command(docptr, DoC_GetECCOffset(mtd, &fofs), 0);
-			size = 6 - base;
-		} else if (base < 8) {
-			DoC_Command(docptr, DoC_GetFlagsOffset(mtd, &fofs), 0);
-			size = 8 - base;
-		} else {
-			DoC_Command(docptr, DoC_GetHdrOffset(mtd, &fofs), 0);
-			size = 16 - base;
-		}
-		if (size > want)
-			size = want;
-
-		/* Issue read command */
-		DoC_Address(this, 3, fofs, 0, 0x00);
-		WriteDOC(0, docptr, Mplus_FlashControl);
-		DoC_WaitReady(docptr);
-
-		ReadDOC(docptr, Mplus_ReadPipeInit);
-		ReadDOC(docptr, Mplus_ReadPipeInit);
-		MemReadDOC(docptr, &buf[got], size - 2);
-		buf[got + size - 2] = ReadDOC(docptr, Mplus_LastDataRead);
-		buf[got + size - 1] = ReadDOC(docptr, Mplus_LastDataRead);
-
-		ofs += size;
-		got += size;
-		want -= size;
-	}
-
-	/* Disable flash internally */
-	WriteDOC(0, docptr, Mplus_FlashSelect);
-
-	ops->retlen = len;
-	return 0;
-}
-
-static int doc_write_oob(struct mtd_info *mtd, loff_t ofs,
-			 struct mtd_oob_ops *ops)
-{
-	volatile char dummy;
-	loff_t fofs, base;
-	struct DiskOnChip *this = mtd->priv;
-	void __iomem * docptr = this->virtadr;
-	struct Nand *mychip = &this->chips[ofs >> this->chipshift];
-	size_t i, size, got, want;
-	int ret = 0;
-	uint8_t *buf = ops->oobbuf;
-	size_t len = ops->len;
-
-	BUG_ON(ops->mode != MTD_OPS_PLACE_OOB);
-
-	ofs += ops->ooboffs;
-
-	DoC_CheckASIC(docptr);
-
-	/* Find the chip which is to be used and select it */
-	if (this->curfloor != mychip->floor) {
-		DoC_SelectFloor(docptr, mychip->floor);
-		DoC_SelectChip(docptr, mychip->chip);
-	} else if (this->curchip != mychip->chip) {
-		DoC_SelectChip(docptr, mychip->chip);
-	}
-	this->curfloor = mychip->floor;
-	this->curchip = mychip->chip;
-
-	/* Millennium Plus bus cycle sequence as per figure 2, section 2.4 */
-	WriteDOC(DOC_FLASH_CE, docptr, Mplus_FlashSelect);
-
-
-	/* Maximum of 16 bytes in the OOB region, so limit write to that */
-	if (len > 16)
-		len = 16;
-	got = 0;
-	want = len;
-
-	for (i = 0; ((i < 3) && (want > 0)); i++) {
-		/* Reset the chip, see Software Requirement 11.4 item 1. */
-		DoC_Command(docptr, NAND_CMD_RESET, 0);
-		DoC_WaitReady(docptr);
-
-		/* Figure out which region we are accessing... */
-		fofs = ofs;
-		base = ofs & 0x0f;
-		if (!this->interleave) {
-			WriteDOC(NAND_CMD_READOOB, docptr, Mplus_FlashCmd);
-			size = 16 - base;
-		} else if (base < 6) {
-			WriteDOC(DoC_GetECCOffset(mtd, &fofs), docptr, Mplus_FlashCmd);
-			size = 6 - base;
-		} else if (base < 8) {
-			WriteDOC(DoC_GetFlagsOffset(mtd, &fofs), docptr, Mplus_FlashCmd);
-			size = 8 - base;
-		} else {
-			WriteDOC(DoC_GetHdrOffset(mtd, &fofs), docptr, Mplus_FlashCmd);
-			size = 16 - base;
-		}
-		if (size > want)
-			size = want;
-
-		/* Issue the Serial Data In command to initial the Page Program process */
-		DoC_Command(docptr, NAND_CMD_SEQIN, 0x00);
-		DoC_Address(this, 3, fofs, 0, 0x00);
-
-		/* Disable the ECC engine */
-		WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf);
-
-		/* Write the data via the internal pipeline through CDSN IO
-		   register, see Pipelined Write Operations 11.2 */
-		MemWriteDOC(docptr, (unsigned char *) &buf[got], size);
-		WriteDOC(0x00, docptr, Mplus_WritePipeTerm);
-		WriteDOC(0x00, docptr, Mplus_WritePipeTerm);
-
-		/* Commit the Page Program command and wait for ready
-	 	   see Software Requirement 11.4 item 1.*/
-		DoC_Command(docptr, NAND_CMD_PAGEPROG, 0x00);
-		DoC_WaitReady(docptr);
-
-		/* Read the status of the flash device through CDSN IO register
-		   see Software Requirement 11.4 item 5.*/
-		DoC_Command(docptr, NAND_CMD_STATUS, 0x00);
-		dummy = ReadDOC(docptr, Mplus_ReadPipeInit);
-		dummy = ReadDOC(docptr, Mplus_ReadPipeInit);
-		DoC_Delay(docptr, 2);
-		if ((dummy = ReadDOC(docptr, Mplus_LastDataRead)) & 1) {
-			printk("MTD: Error 0x%x programming oob at 0x%x\n",
-				dummy, (int)ofs);
-			/* FIXME: implement Bad Block Replacement */
-			ops->retlen = 0;
-			ret = -EIO;
-		}
-		dummy = ReadDOC(docptr, Mplus_LastDataRead);
-
-		ofs += size;
-		got += size;
-		want -= size;
-	}
-
-	/* Disable flash internally */
-	WriteDOC(0, docptr, Mplus_FlashSelect);
-
-	ops->retlen = len;
-	return ret;
-}
-
-int doc_erase(struct mtd_info *mtd, struct erase_info *instr)
-{
-	volatile char dummy;
-	struct DiskOnChip *this = mtd->priv;
-	__u32 ofs = instr->addr;
-	__u32 len = instr->len;
-	void __iomem * docptr = this->virtadr;
-	struct Nand *mychip = &this->chips[ofs >> this->chipshift];
-
-	DoC_CheckASIC(docptr);
-
-	if (len != mtd->erasesize)
-		printk(KERN_WARNING "MTD: Erase not right size (%x != %x)n",
-		       len, mtd->erasesize);
-
-	/* Find the chip which is to be used and select it */
-	if (this->curfloor != mychip->floor) {
-		DoC_SelectFloor(docptr, mychip->floor);
-		DoC_SelectChip(docptr, mychip->chip);
-	} else if (this->curchip != mychip->chip) {
-		DoC_SelectChip(docptr, mychip->chip);
-	}
-	this->curfloor = mychip->floor;
-	this->curchip = mychip->chip;
-
-	instr->state = MTD_ERASE_PENDING;
-
-	/* Millennium Plus bus cycle sequence as per figure 2, section 2.4 */
-	WriteDOC(DOC_FLASH_CE, docptr, Mplus_FlashSelect);
-
-	DoC_Command(docptr, NAND_CMD_RESET, 0x00);
-	DoC_WaitReady(docptr);
-
-	DoC_Command(docptr, NAND_CMD_ERASE1, 0);
-	DoC_Address(this, 2, ofs, 0, 0x00);
-	DoC_Command(docptr, NAND_CMD_ERASE2, 0);
-	DoC_WaitReady(docptr);
-	instr->state = MTD_ERASING;
-
-	/* Read the status of the flash device through CDSN IO register
-	   see Software Requirement 11.4 item 5. */
-	DoC_Command(docptr, NAND_CMD_STATUS, 0);
-	dummy = ReadDOC(docptr, Mplus_ReadPipeInit);
-	dummy = ReadDOC(docptr, Mplus_ReadPipeInit);
-	if ((dummy = ReadDOC(docptr, Mplus_LastDataRead)) & 1) {
-		printk("MTD: Error 0x%x erasing at 0x%x\n", dummy, ofs);
-		/* FIXME: implement Bad Block Replacement (in nftl.c ??) */
-		instr->state = MTD_ERASE_FAILED;
-	} else {
-		instr->state = MTD_ERASE_DONE;
-	}
-	dummy = ReadDOC(docptr, Mplus_LastDataRead);
-
-	/* Disable flash internally */
-	WriteDOC(0, docptr, Mplus_FlashSelect);
-
-	mtd_erase_callback(instr);
-
-	return 0;
-}
-
-/****************************************************************************
- *
- * Module stuff
- *
- ****************************************************************************/
-
-static void __exit cleanup_doc2001plus(void)
-{
-	struct mtd_info *mtd;
-	struct DiskOnChip *this;
-
-	while ((mtd=docmilpluslist)) {
-		this = mtd->priv;
-		docmilpluslist = this->nextdoc;
-
-		mtd_device_unregister(mtd);
-
-		iounmap(this->virtadr);
-		kfree(this->chips);
-		kfree(mtd);
-	}
-}
-
-module_exit(cleanup_doc2001plus);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Greg Ungerer <gerg@snapgear.com> et al.");
-MODULE_DESCRIPTION("Driver for DiskOnChip Millennium Plus");
diff --git a/drivers/mtd/devices/docecc.c b/drivers/mtd/devices/docecc.c
deleted file mode 100644
index 4a1c39b..0000000
--- a/drivers/mtd/devices/docecc.c
+++ /dev/null
@@ -1,521 +0,0 @@
-/*
- * ECC algorithm for M-systems disk on chip. We use the excellent Reed
- * Solmon code of Phil Karn (karn@ka9q.ampr.org) available under the
- * GNU GPL License. The rest is simply to convert the disk on chip
- * syndrome into a standard syndome.
- *
- * Author: Fabrice Bellard (fabrice.bellard@netgem.com)
- * Copyright (C) 2000 Netgem S.A.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You 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 <asm/errno.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/types.h>
-
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/doc2000.h>
-
-#define DEBUG_ECC 0
-/* need to undef it (from asm/termbits.h) */
-#undef B0
-
-#define MM 10 /* Symbol size in bits */
-#define KK (1023-4) /* Number of data symbols per block */
-#define B0 510 /* First root of generator polynomial, alpha form */
-#define PRIM 1 /* power of alpha used to generate roots of generator poly */
-#define	NN ((1 << MM) - 1)
-
-typedef unsigned short dtype;
-
-/* 1+x^3+x^10 */
-static const int Pp[MM+1] = { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1 };
-
-/* This defines the type used to store an element of the Galois Field
- * used by the code. Make sure this is something larger than a char if
- * if anything larger than GF(256) is used.
- *
- * Note: unsigned char will work up to GF(256) but int seems to run
- * faster on the Pentium.
- */
-typedef int gf;
-
-/* No legal value in index form represents zero, so
- * we need a special value for this purpose
- */
-#define A0	(NN)
-
-/* Compute x % NN, where NN is 2**MM - 1,
- * without a slow divide
- */
-static inline gf
-modnn(int x)
-{
-  while (x >= NN) {
-    x -= NN;
-    x = (x >> MM) + (x & NN);
-  }
-  return x;
-}
-
-#define	CLEAR(a,n) {\
-int ci;\
-for(ci=(n)-1;ci >=0;ci--)\
-(a)[ci] = 0;\
-}
-
-#define	COPY(a,b,n) {\
-int ci;\
-for(ci=(n)-1;ci >=0;ci--)\
-(a)[ci] = (b)[ci];\
-}
-
-#define	COPYDOWN(a,b,n) {\
-int ci;\
-for(ci=(n)-1;ci >=0;ci--)\
-(a)[ci] = (b)[ci];\
-}
-
-#define Ldec 1
-
-/* generate GF(2**m) from the irreducible polynomial p(X) in Pp[0]..Pp[m]
-   lookup tables:  index->polynomial form   alpha_to[] contains j=alpha**i;
-                   polynomial form -> index form  index_of[j=alpha**i] = i
-   alpha=2 is the primitive element of GF(2**m)
-   HARI's COMMENT: (4/13/94) alpha_to[] can be used as follows:
-        Let @ represent the primitive element commonly called "alpha" that
-   is the root of the primitive polynomial p(x). Then in GF(2^m), for any
-   0 <= i <= 2^m-2,
-        @^i = a(0) + a(1) @ + a(2) @^2 + ... + a(m-1) @^(m-1)
-   where the binary vector (a(0),a(1),a(2),...,a(m-1)) is the representation
-   of the integer "alpha_to[i]" with a(0) being the LSB and a(m-1) the MSB. Thus for
-   example the polynomial representation of @^5 would be given by the binary
-   representation of the integer "alpha_to[5]".
-                   Similarly, index_of[] can be used as follows:
-        As above, let @ represent the primitive element of GF(2^m) that is
-   the root of the primitive polynomial p(x). In order to find the power
-   of @ (alpha) that has the polynomial representation
-        a(0) + a(1) @ + a(2) @^2 + ... + a(m-1) @^(m-1)
-   we consider the integer "i" whose binary representation with a(0) being LSB
-   and a(m-1) MSB is (a(0),a(1),...,a(m-1)) and locate the entry
-   "index_of[i]". Now, @^index_of[i] is that element whose polynomial
-    representation is (a(0),a(1),a(2),...,a(m-1)).
-   NOTE:
-        The element alpha_to[2^m-1] = 0 always signifying that the
-   representation of "@^infinity" = 0 is (0,0,0,...,0).
-        Similarly, the element index_of[0] = A0 always signifying
-   that the power of alpha which has the polynomial representation
-   (0,0,...,0) is "infinity".
-
-*/
-
-static void
-generate_gf(dtype Alpha_to[NN + 1], dtype Index_of[NN + 1])
-{
-  register int i, mask;
-
-  mask = 1;
-  Alpha_to[MM] = 0;
-  for (i = 0; i < MM; i++) {
-    Alpha_to[i] = mask;
-    Index_of[Alpha_to[i]] = i;
-    /* If Pp[i] == 1 then, term @^i occurs in poly-repr of @^MM */
-    if (Pp[i] != 0)
-      Alpha_to[MM] ^= mask;	/* Bit-wise EXOR operation */
-    mask <<= 1;	/* single left-shift */
-  }
-  Index_of[Alpha_to[MM]] = MM;
-  /*
-   * Have obtained poly-repr of @^MM. Poly-repr of @^(i+1) is given by
-   * poly-repr of @^i shifted left one-bit and accounting for any @^MM
-   * term that may occur when poly-repr of @^i is shifted.
-   */
-  mask >>= 1;
-  for (i = MM + 1; i < NN; i++) {
-    if (Alpha_to[i - 1] >= mask)
-      Alpha_to[i] = Alpha_to[MM] ^ ((Alpha_to[i - 1] ^ mask) << 1);
-    else
-      Alpha_to[i] = Alpha_to[i - 1] << 1;
-    Index_of[Alpha_to[i]] = i;
-  }
-  Index_of[0] = A0;
-  Alpha_to[NN] = 0;
-}
-
-/*
- * Performs ERRORS+ERASURES decoding of RS codes. bb[] is the content
- * of the feedback shift register after having processed the data and
- * the ECC.
- *
- * Return number of symbols corrected, or -1 if codeword is illegal
- * or uncorrectable. If eras_pos is non-null, the detected error locations
- * are written back. NOTE! This array must be at least NN-KK elements long.
- * The corrected data are written in eras_val[]. They must be xor with the data
- * to retrieve the correct data : data[erase_pos[i]] ^= erase_val[i] .
- *
- * First "no_eras" erasures are declared by the calling program. Then, the
- * maximum # of errors correctable is t_after_eras = floor((NN-KK-no_eras)/2).
- * If the number of channel errors is not greater than "t_after_eras" the
- * transmitted codeword will be recovered. Details of algorithm can be found
- * in R. Blahut's "Theory ... of Error-Correcting Codes".
-
- * Warning: the eras_pos[] array must not contain duplicate entries; decoder failure
- * will result. The decoder *could* check for this condition, but it would involve
- * extra time on every decoding operation.
- * */
-static int
-eras_dec_rs(dtype Alpha_to[NN + 1], dtype Index_of[NN + 1],
-            gf bb[NN - KK + 1], gf eras_val[NN-KK], int eras_pos[NN-KK],
-            int no_eras)
-{
-  int deg_lambda, el, deg_omega;
-  int i, j, r,k;
-  gf u,q,tmp,num1,num2,den,discr_r;
-  gf lambda[NN-KK + 1], s[NN-KK + 1];	/* Err+Eras Locator poly
-					 * and syndrome poly */
-  gf b[NN-KK + 1], t[NN-KK + 1], omega[NN-KK + 1];
-  gf root[NN-KK], reg[NN-KK + 1], loc[NN-KK];
-  int syn_error, count;
-
-  syn_error = 0;
-  for(i=0;i<NN-KK;i++)
-      syn_error |= bb[i];
-
-  if (!syn_error) {
-    /* if remainder is zero, data[] is a codeword and there are no
-     * errors to correct. So return data[] unmodified
-     */
-    count = 0;
-    goto finish;
-  }
-
-  for(i=1;i<=NN-KK;i++){
-    s[i] = bb[0];
-  }
-  for(j=1;j<NN-KK;j++){
-    if(bb[j] == 0)
-      continue;
-    tmp = Index_of[bb[j]];
-
-    for(i=1;i<=NN-KK;i++)
-      s[i] ^= Alpha_to[modnn(tmp + (B0+i-1)*PRIM*j)];
-  }
-
-  /* undo the feedback register implicit multiplication and convert
-     syndromes to index form */
-
-  for(i=1;i<=NN-KK;i++) {
-      tmp = Index_of[s[i]];
-      if (tmp != A0)
-          tmp = modnn(tmp + 2 * KK * (B0+i-1)*PRIM);
-      s[i] = tmp;
-  }
-
-  CLEAR(&lambda[1],NN-KK);
-  lambda[0] = 1;
-
-  if (no_eras > 0) {
-    /* Init lambda to be the erasure locator polynomial */
-    lambda[1] = Alpha_to[modnn(PRIM * eras_pos[0])];
-    for (i = 1; i < no_eras; i++) {
-      u = modnn(PRIM*eras_pos[i]);
-      for (j = i+1; j > 0; j--) {
-	tmp = Index_of[lambda[j - 1]];
-	if(tmp != A0)
-	  lambda[j] ^= Alpha_to[modnn(u + tmp)];
-      }
-    }
-#if DEBUG_ECC >= 1
-    /* Test code that verifies the erasure locator polynomial just constructed
-       Needed only for decoder debugging. */
-
-    /* find roots of the erasure location polynomial */
-    for(i=1;i<=no_eras;i++)
-      reg[i] = Index_of[lambda[i]];
-    count = 0;
-    for (i = 1,k=NN-Ldec; i <= NN; i++,k = modnn(NN+k-Ldec)) {
-      q = 1;
-      for (j = 1; j <= no_eras; j++)
-	if (reg[j] != A0) {
-	  reg[j] = modnn(reg[j] + j);
-	  q ^= Alpha_to[reg[j]];
-	}
-      if (q != 0)
-	continue;
-      /* store root and error location number indices */
-      root[count] = i;
-      loc[count] = k;
-      count++;
-    }
-    if (count != no_eras) {
-      printf("\n lambda(x) is WRONG\n");
-      count = -1;
-      goto finish;
-    }
-#if DEBUG_ECC >= 2
-    printf("\n Erasure positions as determined by roots of Eras Loc Poly:\n");
-    for (i = 0; i < count; i++)
-      printf("%d ", loc[i]);
-    printf("\n");
-#endif
-#endif
-  }
-  for(i=0;i<NN-KK+1;i++)
-    b[i] = Index_of[lambda[i]];
-
-  /*
-   * Begin Berlekamp-Massey algorithm to determine error+erasure
-   * locator polynomial
-   */
-  r = no_eras;
-  el = no_eras;
-  while (++r <= NN-KK) {	/* r is the step number */
-    /* Compute discrepancy at the r-th step in poly-form */
-    discr_r = 0;
-    for (i = 0; i < r; i++){
-      if ((lambda[i] != 0) && (s[r - i] != A0)) {
-	discr_r ^= Alpha_to[modnn(Index_of[lambda[i]] + s[r - i])];
-      }
-    }
-    discr_r = Index_of[discr_r];	/* Index form */
-    if (discr_r == A0) {
-      /* 2 lines below: B(x) <-- x*B(x) */
-      COPYDOWN(&b[1],b,NN-KK);
-      b[0] = A0;
-    } else {
-      /* 7 lines below: T(x) <-- lambda(x) - discr_r*x*b(x) */
-      t[0] = lambda[0];
-      for (i = 0 ; i < NN-KK; i++) {
-	if(b[i] != A0)
-	  t[i+1] = lambda[i+1] ^ Alpha_to[modnn(discr_r + b[i])];
-	else
-	  t[i+1] = lambda[i+1];
-      }
-      if (2 * el <= r + no_eras - 1) {
-	el = r + no_eras - el;
-	/*
-	 * 2 lines below: B(x) <-- inv(discr_r) *
-	 * lambda(x)
-	 */
-	for (i = 0; i <= NN-KK; i++)
-	  b[i] = (lambda[i] == 0) ? A0 : modnn(Index_of[lambda[i]] - discr_r + NN);
-      } else {
-	/* 2 lines below: B(x) <-- x*B(x) */
-	COPYDOWN(&b[1],b,NN-KK);
-	b[0] = A0;
-      }
-      COPY(lambda,t,NN-KK+1);
-    }
-  }
-
-  /* Convert lambda to index form and compute deg(lambda(x)) */
-  deg_lambda = 0;
-  for(i=0;i<NN-KK+1;i++){
-    lambda[i] = Index_of[lambda[i]];
-    if(lambda[i] != A0)
-      deg_lambda = i;
-  }
-  /*
-   * Find roots of the error+erasure locator polynomial by Chien
-   * Search
-   */
-  COPY(&reg[1],&lambda[1],NN-KK);
-  count = 0;		/* Number of roots of lambda(x) */
-  for (i = 1,k=NN-Ldec; i <= NN; i++,k = modnn(NN+k-Ldec)) {
-    q = 1;
-    for (j = deg_lambda; j > 0; j--){
-      if (reg[j] != A0) {
-	reg[j] = modnn(reg[j] + j);
-	q ^= Alpha_to[reg[j]];
-      }
-    }
-    if (q != 0)
-      continue;
-    /* store root (index-form) and error location number */
-    root[count] = i;
-    loc[count] = k;
-    /* If we've already found max possible roots,
-     * abort the search to save time
-     */
-    if(++count == deg_lambda)
-      break;
-  }
-  if (deg_lambda != count) {
-    /*
-     * deg(lambda) unequal to number of roots => uncorrectable
-     * error detected
-     */
-    count = -1;
-    goto finish;
-  }
-  /*
-   * Compute err+eras evaluator poly omega(x) = s(x)*lambda(x) (modulo
-   * x**(NN-KK)). in index form. Also find deg(omega).
-   */
-  deg_omega = 0;
-  for (i = 0; i < NN-KK;i++){
-    tmp = 0;
-    j = (deg_lambda < i) ? deg_lambda : i;
-    for(;j >= 0; j--){
-      if ((s[i + 1 - j] != A0) && (lambda[j] != A0))
-	tmp ^= Alpha_to[modnn(s[i + 1 - j] + lambda[j])];
-    }
-    if(tmp != 0)
-      deg_omega = i;
-    omega[i] = Index_of[tmp];
-  }
-  omega[NN-KK] = A0;
-
-  /*
-   * Compute error values in poly-form. num1 = omega(inv(X(l))), num2 =
-   * inv(X(l))**(B0-1) and den = lambda_pr(inv(X(l))) all in poly-form
-   */
-  for (j = count-1; j >=0; j--) {
-    num1 = 0;
-    for (i = deg_omega; i >= 0; i--) {
-      if (omega[i] != A0)
-	num1  ^= Alpha_to[modnn(omega[i] + i * root[j])];
-    }
-    num2 = Alpha_to[modnn(root[j] * (B0 - 1) + NN)];
-    den = 0;
-
-    /* lambda[i+1] for i even is the formal derivative lambda_pr of lambda[i] */
-    for (i = min(deg_lambda,NN-KK-1) & ~1; i >= 0; i -=2) {
-      if(lambda[i+1] != A0)
-	den ^= Alpha_to[modnn(lambda[i+1] + i * root[j])];
-    }
-    if (den == 0) {
-#if DEBUG_ECC >= 1
-      printf("\n ERROR: denominator = 0\n");
-#endif
-      /* Convert to dual- basis */
-      count = -1;
-      goto finish;
-    }
-    /* Apply error to data */
-    if (num1 != 0) {
-        eras_val[j] = Alpha_to[modnn(Index_of[num1] + Index_of[num2] + NN - Index_of[den])];
-    } else {
-        eras_val[j] = 0;
-    }
-  }
- finish:
-  for(i=0;i<count;i++)
-      eras_pos[i] = loc[i];
-  return count;
-}
-
-/***************************************************************************/
-/* The DOC specific code begins here */
-
-#define SECTOR_SIZE 512
-/* The sector bytes are packed into NB_DATA MM bits words */
-#define NB_DATA (((SECTOR_SIZE + 1) * 8 + 6) / MM)
-
-/*
- * Correct the errors in 'sector[]' by using 'ecc1[]' which is the
- * content of the feedback shift register applyied to the sector and
- * the ECC. Return the number of errors corrected (and correct them in
- * sector), or -1 if error
- */
-int doc_decode_ecc(unsigned char sector[SECTOR_SIZE], unsigned char ecc1[6])
-{
-    int parity, i, nb_errors;
-    gf bb[NN - KK + 1];
-    gf error_val[NN-KK];
-    int error_pos[NN-KK], pos, bitpos, index, val;
-    dtype *Alpha_to, *Index_of;
-
-    /* init log and exp tables here to save memory. However, it is slower */
-    Alpha_to = kmalloc((NN + 1) * sizeof(dtype), GFP_KERNEL);
-    if (!Alpha_to)
-        return -1;
-
-    Index_of = kmalloc((NN + 1) * sizeof(dtype), GFP_KERNEL);
-    if (!Index_of) {
-        kfree(Alpha_to);
-        return -1;
-    }
-
-    generate_gf(Alpha_to, Index_of);
-
-    parity = ecc1[1];
-
-    bb[0] =  (ecc1[4] & 0xff) | ((ecc1[5] & 0x03) << 8);
-    bb[1] = ((ecc1[5] & 0xfc) >> 2) | ((ecc1[2] & 0x0f) << 6);
-    bb[2] = ((ecc1[2] & 0xf0) >> 4) | ((ecc1[3] & 0x3f) << 4);
-    bb[3] = ((ecc1[3] & 0xc0) >> 6) | ((ecc1[0] & 0xff) << 2);
-
-    nb_errors = eras_dec_rs(Alpha_to, Index_of, bb,
-                            error_val, error_pos, 0);
-    if (nb_errors <= 0)
-        goto the_end;
-
-    /* correct the errors */
-    for(i=0;i<nb_errors;i++) {
-        pos = error_pos[i];
-        if (pos >= NB_DATA && pos < KK) {
-            nb_errors = -1;
-            goto the_end;
-        }
-        if (pos < NB_DATA) {
-            /* extract bit position (MSB first) */
-            pos = 10 * (NB_DATA - 1 - pos) - 6;
-            /* now correct the following 10 bits. At most two bytes
-               can be modified since pos is even */
-            index = (pos >> 3) ^ 1;
-            bitpos = pos & 7;
-            if ((index >= 0 && index < SECTOR_SIZE) ||
-                index == (SECTOR_SIZE + 1)) {
-                val = error_val[i] >> (2 + bitpos);
-                parity ^= val;
-                if (index < SECTOR_SIZE)
-                    sector[index] ^= val;
-            }
-            index = ((pos >> 3) + 1) ^ 1;
-            bitpos = (bitpos + 10) & 7;
-            if (bitpos == 0)
-                bitpos = 8;
-            if ((index >= 0 && index < SECTOR_SIZE) ||
-                index == (SECTOR_SIZE + 1)) {
-                val = error_val[i] << (8 - bitpos);
-                parity ^= val;
-                if (index < SECTOR_SIZE)
-                    sector[index] ^= val;
-            }
-        }
-    }
-
-    /* use parity to test extra errors */
-    if ((parity & 0xff) != 0)
-        nb_errors = -1;
-
- the_end:
-    kfree(Alpha_to);
-    kfree(Index_of);
-    return nb_errors;
-}
-
-EXPORT_SYMBOL_GPL(doc_decode_ecc);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Fabrice Bellard <fabrice.bellard@netgem.com>");
-MODULE_DESCRIPTION("ECC code for correcting errors detected by DiskOnChip 2000 and Millennium ECC hardware");
diff --git a/drivers/mtd/devices/docg3.c b/drivers/mtd/devices/docg3.c
index 8510ccb..3e1b0a0 100644
--- a/drivers/mtd/devices/docg3.c
+++ b/drivers/mtd/devices/docg3.c
@@ -123,7 +123,7 @@ static inline void doc_flash_address(struct docg3 *docg3, u8 addr)
 	doc_writeb(docg3, addr, DOC_FLASHADDRESS);
 }
 
-static char const *part_probes[] = { "cmdlinepart", "saftlpart", NULL };
+static char const * const part_probes[] = { "cmdlinepart", "saftlpart", NULL };
 
 static int doc_register_readb(struct docg3 *docg3, int reg)
 {
@@ -2144,18 +2144,7 @@ static struct platform_driver g3_driver = {
 	.remove		= __exit_p(docg3_release),
 };
 
-static int __init docg3_init(void)
-{
-	return platform_driver_probe(&g3_driver, docg3_probe);
-}
-module_init(docg3_init);
-
-
-static void __exit docg3_exit(void)
-{
-	platform_driver_unregister(&g3_driver);
-}
-module_exit(docg3_exit);
+module_platform_driver_probe(g3_driver, docg3_probe);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Robert Jarzmik <robert.jarzmik@free.fr>");
diff --git a/drivers/mtd/devices/docprobe.c b/drivers/mtd/devices/docprobe.c
deleted file mode 100644
index 88b3fd3..0000000
--- a/drivers/mtd/devices/docprobe.c
+++ /dev/null
@@ -1,325 +0,0 @@
-
-/* Linux driver for Disk-On-Chip devices			*/
-/* Probe routines common to all DoC devices			*/
-/* (C) 1999 Machine Vision Holdings, Inc.			*/
-/* (C) 1999-2003 David Woodhouse <dwmw2@infradead.org>		*/
-
-
-/* DOC_PASSIVE_PROBE:
-   In order to ensure that the BIOS checksum is correct at boot time, and
-   hence that the onboard BIOS extension gets executed, the DiskOnChip
-   goes into reset mode when it is read sequentially: all registers
-   return 0xff until the chip is woken up again by writing to the
-   DOCControl register.
-
-   Unfortunately, this means that the probe for the DiskOnChip is unsafe,
-   because one of the first things it does is write to where it thinks
-   the DOCControl register should be - which may well be shared memory
-   for another device. I've had machines which lock up when this is
-   attempted. Hence the possibility to do a passive probe, which will fail
-   to detect a chip in reset mode, but is at least guaranteed not to lock
-   the machine.
-
-   If you have this problem, uncomment the following line:
-#define DOC_PASSIVE_PROBE
-*/
-
-
-/* DOC_SINGLE_DRIVER:
-   Millennium driver has been merged into DOC2000 driver.
-
-   The old Millennium-only driver has been retained just in case there
-   are problems with the new code. If the combined driver doesn't work
-   for you, you can try the old one by undefining DOC_SINGLE_DRIVER
-   below and also enabling it in your configuration. If this fixes the
-   problems, please send a report to the MTD mailing list at
-   <linux-mtd@lists.infradead.org>.
-*/
-#define DOC_SINGLE_DRIVER
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <asm/errno.h>
-#include <asm/io.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/types.h>
-
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
-#include <linux/mtd/doc2000.h>
-
-
-static unsigned long doc_config_location = CONFIG_MTD_DOCPROBE_ADDRESS;
-module_param(doc_config_location, ulong, 0);
-MODULE_PARM_DESC(doc_config_location, "Physical memory address at which to probe for DiskOnChip");
-
-static unsigned long __initdata doc_locations[] = {
-#if defined (__alpha__) || defined(__i386__) || defined(__x86_64__)
-#ifdef CONFIG_MTD_DOCPROBE_HIGH
-	0xfffc8000, 0xfffca000, 0xfffcc000, 0xfffce000,
-	0xfffd0000, 0xfffd2000, 0xfffd4000, 0xfffd6000,
-	0xfffd8000, 0xfffda000, 0xfffdc000, 0xfffde000,
-	0xfffe0000, 0xfffe2000, 0xfffe4000, 0xfffe6000,
-	0xfffe8000, 0xfffea000, 0xfffec000, 0xfffee000,
-#else /*  CONFIG_MTD_DOCPROBE_HIGH */
-	0xc8000, 0xca000, 0xcc000, 0xce000,
-	0xd0000, 0xd2000, 0xd4000, 0xd6000,
-	0xd8000, 0xda000, 0xdc000, 0xde000,
-	0xe0000, 0xe2000, 0xe4000, 0xe6000,
-	0xe8000, 0xea000, 0xec000, 0xee000,
-#endif /*  CONFIG_MTD_DOCPROBE_HIGH */
-#endif
-	0xffffffff };
-
-/* doccheck: Probe a given memory window to see if there's a DiskOnChip present */
-
-static inline int __init doccheck(void __iomem *potential, unsigned long physadr)
-{
-	void __iomem *window=potential;
-	unsigned char tmp, tmpb, tmpc, ChipID;
-#ifndef DOC_PASSIVE_PROBE
-	unsigned char tmp2;
-#endif
-
-	/* Routine copied from the Linux DOC driver */
-
-#ifdef CONFIG_MTD_DOCPROBE_55AA
-	/* Check for 0x55 0xAA signature at beginning of window,
-	   this is no longer true once we remove the IPL (for Millennium */
-	if (ReadDOC(window, Sig1) != 0x55 || ReadDOC(window, Sig2) != 0xaa)
-		return 0;
-#endif /* CONFIG_MTD_DOCPROBE_55AA */
-
-#ifndef DOC_PASSIVE_PROBE
-	/* It's not possible to cleanly detect the DiskOnChip - the
-	 * bootup procedure will put the device into reset mode, and
-	 * it's not possible to talk to it without actually writing
-	 * to the DOCControl register. So we store the current contents
-	 * of the DOCControl register's location, in case we later decide
-	 * that it's not a DiskOnChip, and want to put it back how we
-	 * found it.
-	 */
-	tmp2 = ReadDOC(window, DOCControl);
-
-	/* Reset the DiskOnChip ASIC */
-	WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET,
-		 window, DOCControl);
-	WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET,
-		 window, DOCControl);
-
-	/* Enable the DiskOnChip ASIC */
-	WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL,
-		 window, DOCControl);
-	WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL,
-		 window, DOCControl);
-#endif /* !DOC_PASSIVE_PROBE */
-
-	/* We need to read the ChipID register four times. For some
-	   newer DiskOnChip 2000 units, the first three reads will
-	   return the DiskOnChip Millennium ident. Don't ask. */
-	ChipID = ReadDOC(window, ChipID);
-
-	switch (ChipID) {
-	case DOC_ChipID_Doc2k:
-		/* Check the TOGGLE bit in the ECC register */
-		tmp  = ReadDOC(window, 2k_ECCStatus) & DOC_TOGGLE_BIT;
-		tmpb = ReadDOC(window, 2k_ECCStatus) & DOC_TOGGLE_BIT;
-		tmpc = ReadDOC(window, 2k_ECCStatus) & DOC_TOGGLE_BIT;
-		if (tmp != tmpb && tmp == tmpc)
-				return ChipID;
-		break;
-
-	case DOC_ChipID_DocMil:
-		/* Check for the new 2000 with Millennium ASIC */
-		ReadDOC(window, ChipID);
-		ReadDOC(window, ChipID);
-		if (ReadDOC(window, ChipID) != DOC_ChipID_DocMil)
-			ChipID = DOC_ChipID_Doc2kTSOP;
-
-		/* Check the TOGGLE bit in the ECC register */
-		tmp  = ReadDOC(window, ECCConf) & DOC_TOGGLE_BIT;
-		tmpb = ReadDOC(window, ECCConf) & DOC_TOGGLE_BIT;
-		tmpc = ReadDOC(window, ECCConf) & DOC_TOGGLE_BIT;
-		if (tmp != tmpb && tmp == tmpc)
-				return ChipID;
-		break;
-
-	case DOC_ChipID_DocMilPlus16:
-	case DOC_ChipID_DocMilPlus32:
-	case 0:
-		/* Possible Millennium+, need to do more checks */
-#ifndef DOC_PASSIVE_PROBE
-		/* Possibly release from power down mode */
-		for (tmp = 0; (tmp < 4); tmp++)
-			ReadDOC(window, Mplus_Power);
-
-		/* Reset the DiskOnChip ASIC */
-		tmp = DOC_MODE_RESET | DOC_MODE_MDWREN | DOC_MODE_RST_LAT |
-			DOC_MODE_BDECT;
-		WriteDOC(tmp, window, Mplus_DOCControl);
-		WriteDOC(~tmp, window, Mplus_CtrlConfirm);
-
-		mdelay(1);
-		/* Enable the DiskOnChip ASIC */
-		tmp = DOC_MODE_NORMAL | DOC_MODE_MDWREN | DOC_MODE_RST_LAT |
-			DOC_MODE_BDECT;
-		WriteDOC(tmp, window, Mplus_DOCControl);
-		WriteDOC(~tmp, window, Mplus_CtrlConfirm);
-		mdelay(1);
-#endif /* !DOC_PASSIVE_PROBE */
-
-		ChipID = ReadDOC(window, ChipID);
-
-		switch (ChipID) {
-		case DOC_ChipID_DocMilPlus16:
-		case DOC_ChipID_DocMilPlus32:
-			/* Check the TOGGLE bit in the toggle register */
-			tmp  = ReadDOC(window, Mplus_Toggle) & DOC_TOGGLE_BIT;
-			tmpb = ReadDOC(window, Mplus_Toggle) & DOC_TOGGLE_BIT;
-			tmpc = ReadDOC(window, Mplus_Toggle) & DOC_TOGGLE_BIT;
-			if (tmp != tmpb && tmp == tmpc)
-					return ChipID;
-		default:
-			break;
-		}
-		/* FALL TRHU */
-
-	default:
-
-#ifdef CONFIG_MTD_DOCPROBE_55AA
-		printk(KERN_DEBUG "Possible DiskOnChip with unknown ChipID %2.2X found at 0x%lx\n",
-		       ChipID, physadr);
-#endif
-#ifndef DOC_PASSIVE_PROBE
-		/* Put back the contents of the DOCControl register, in case it's not
-		 * actually a DiskOnChip.
-		 */
-		WriteDOC(tmp2, window, DOCControl);
-#endif
-		return 0;
-	}
-
-	printk(KERN_WARNING "DiskOnChip failed TOGGLE test, dropping.\n");
-
-#ifndef DOC_PASSIVE_PROBE
-	/* Put back the contents of the DOCControl register: it's not a DiskOnChip */
-	WriteDOC(tmp2, window, DOCControl);
-#endif
-	return 0;
-}
-
-static int docfound;
-
-extern void DoC2k_init(struct mtd_info *);
-extern void DoCMil_init(struct mtd_info *);
-extern void DoCMilPlus_init(struct mtd_info *);
-
-static void __init DoC_Probe(unsigned long physadr)
-{
-	void __iomem *docptr;
-	struct DiskOnChip *this;
-	struct mtd_info *mtd;
-	int ChipID;
-	char namebuf[15];
-	char *name = namebuf;
-	void (*initroutine)(struct mtd_info *) = NULL;
-
-	docptr = ioremap(physadr, DOC_IOREMAP_LEN);
-
-	if (!docptr)
-		return;
-
-	if ((ChipID = doccheck(docptr, physadr))) {
-		if (ChipID == DOC_ChipID_Doc2kTSOP) {
-			/* Remove this at your own peril. The hardware driver works but nothing prevents you from erasing bad blocks */
-			printk(KERN_NOTICE "Refusing to drive DiskOnChip 2000 TSOP until Bad Block Table is correctly supported by INFTL\n");
-			iounmap(docptr);
-			return;
-		}
-		docfound = 1;
-		mtd = kzalloc(sizeof(struct DiskOnChip) + sizeof(struct mtd_info), GFP_KERNEL);
-		if (!mtd) {
-			printk(KERN_WARNING "Cannot allocate memory for data structures. Dropping.\n");
-			iounmap(docptr);
-			return;
-		}
-
-		this = (struct DiskOnChip *)(&mtd[1]);
-		mtd->priv = this;
-		this->virtadr = docptr;
-		this->physadr = physadr;
-		this->ChipID = ChipID;
-		sprintf(namebuf, "with ChipID %2.2X", ChipID);
-
-		switch(ChipID) {
-		case DOC_ChipID_Doc2kTSOP:
-			name="2000 TSOP";
-			initroutine = symbol_request(DoC2k_init);
-			break;
-
-		case DOC_ChipID_Doc2k:
-			name="2000";
-			initroutine = symbol_request(DoC2k_init);
-			break;
-
-		case DOC_ChipID_DocMil:
-			name="Millennium";
-#ifdef DOC_SINGLE_DRIVER
-			initroutine = symbol_request(DoC2k_init);
-#else
-			initroutine = symbol_request(DoCMil_init);
-#endif /* DOC_SINGLE_DRIVER */
-			break;
-
-		case DOC_ChipID_DocMilPlus16:
-		case DOC_ChipID_DocMilPlus32:
-			name="MillenniumPlus";
-			initroutine = symbol_request(DoCMilPlus_init);
-			break;
-		}
-
-		if (initroutine) {
-			(*initroutine)(mtd);
-			symbol_put_addr(initroutine);
-			return;
-		}
-		printk(KERN_NOTICE "Cannot find driver for DiskOnChip %s at 0x%lX\n", name, physadr);
-		kfree(mtd);
-	}
-	iounmap(docptr);
-}
-
-
-/****************************************************************************
- *
- * Module stuff
- *
- ****************************************************************************/
-
-static int __init init_doc(void)
-{
-	int i;
-
-	if (doc_config_location) {
-		printk(KERN_INFO "Using configured DiskOnChip probe address 0x%lx\n", doc_config_location);
-		DoC_Probe(doc_config_location);
-	} else {
-		for (i=0; (doc_locations[i] != 0xffffffff); i++) {
-			DoC_Probe(doc_locations[i]);
-		}
-	}
-	/* No banner message any more. Print a message if no DiskOnChip
-	   found, so the user knows we at least tried. */
-	if (!docfound)
-		printk(KERN_INFO "No recognised DiskOnChip devices found\n");
-	return -EAGAIN;
-}
-
-module_init(init_doc);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
-MODULE_DESCRIPTION("Probe code for DiskOnChip 2000 and Millennium devices");
-
diff --git a/drivers/mtd/devices/elm.c b/drivers/mtd/devices/elm.c
index 2ec5da9..dccef9f 100644
--- a/drivers/mtd/devices/elm.c
+++ b/drivers/mtd/devices/elm.c
@@ -81,14 +81,21 @@ static u32 elm_read_reg(struct elm_info *info, int offset)
  * @dev:	ELM device
  * @bch_type:	Type of BCH ecc
  */
-void elm_config(struct device *dev, enum bch_ecc bch_type)
+int elm_config(struct device *dev, enum bch_ecc bch_type)
 {
 	u32 reg_val;
 	struct elm_info *info = dev_get_drvdata(dev);
 
+	if (!info) {
+		dev_err(dev, "Unable to configure elm - device not probed?\n");
+		return -ENODEV;
+	}
+
 	reg_val = (bch_type & ECC_BCH_LEVEL_MASK) | (ELM_ECC_SIZE << 16);
 	elm_write_reg(info, ELM_LOCATION_CONFIG, reg_val);
 	info->bch_type = bch_type;
+
+	return 0;
 }
 EXPORT_SYMBOL(elm_config);
 
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index 5b6b072..2f3d2a5 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -681,6 +681,7 @@ struct flash_info {
 	u16		flags;
 #define	SECT_4K		0x01		/* OPCODE_BE_4K works uniformly */
 #define	M25P_NO_ERASE	0x02		/* No erase command needed */
+#define	SST_WRITE	0x04		/* use SST byte programming */
 };
 
 #define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags)	\
@@ -728,6 +729,7 @@ static const struct spi_device_id m25p_ids[] = {
 	{ "en25q32b", INFO(0x1c3016, 0, 64 * 1024,  64, 0) },
 	{ "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128, 0) },
 	{ "en25q64", INFO(0x1c3017, 0, 64 * 1024, 128, SECT_4K) },
+	{ "en25qh256", INFO(0x1c7019, 0, 64 * 1024, 512, 0) },
 
 	/* Everspin */
 	{ "mr25h256", CAT25_INFO(  32 * 1024, 1, 256, 2) },
@@ -740,7 +742,6 @@ static const struct spi_device_id m25p_ids[] = {
 	{ "160s33b",  INFO(0x898911, 0, 64 * 1024,  32, 0) },
 	{ "320s33b",  INFO(0x898912, 0, 64 * 1024,  64, 0) },
 	{ "640s33b",  INFO(0x898913, 0, 64 * 1024, 128, 0) },
-	{ "n25q064",  INFO(0x20ba17, 0, 64 * 1024, 128, 0) },
 
 	/* Macronix */
 	{ "mx25l2005a",  INFO(0xc22012, 0, 64 * 1024,   4, SECT_4K) },
@@ -753,8 +754,10 @@ static const struct spi_device_id m25p_ids[] = {
 	{ "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) },
 	{ "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, 0) },
 	{ "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) },
+	{ "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, 0) },
 
 	/* Micron */
+	{ "n25q064",  INFO(0x20ba17, 0, 64 * 1024, 128, 0) },
 	{ "n25q128a11",  INFO(0x20bb18, 0, 64 * 1024, 256, 0) },
 	{ "n25q128a13",  INFO(0x20ba18, 0, 64 * 1024, 256, 0) },
 	{ "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K) },
@@ -781,14 +784,15 @@ static const struct spi_device_id m25p_ids[] = {
 	{ "s25fl064k",  INFO(0xef4017,      0,  64 * 1024, 128, SECT_4K) },
 
 	/* SST -- large erase sizes are "overlays", "sectors" are 4K */
-	{ "sst25vf040b", INFO(0xbf258d, 0, 64 * 1024,  8, SECT_4K) },
-	{ "sst25vf080b", INFO(0xbf258e, 0, 64 * 1024, 16, SECT_4K) },
-	{ "sst25vf016b", INFO(0xbf2541, 0, 64 * 1024, 32, SECT_4K) },
-	{ "sst25vf032b", INFO(0xbf254a, 0, 64 * 1024, 64, SECT_4K) },
-	{ "sst25wf512",  INFO(0xbf2501, 0, 64 * 1024,  1, SECT_4K) },
-	{ "sst25wf010",  INFO(0xbf2502, 0, 64 * 1024,  2, SECT_4K) },
-	{ "sst25wf020",  INFO(0xbf2503, 0, 64 * 1024,  4, SECT_4K) },
-	{ "sst25wf040",  INFO(0xbf2504, 0, 64 * 1024,  8, SECT_4K) },
+	{ "sst25vf040b", INFO(0xbf258d, 0, 64 * 1024,  8, SECT_4K | SST_WRITE) },
+	{ "sst25vf080b", INFO(0xbf258e, 0, 64 * 1024, 16, SECT_4K | SST_WRITE) },
+	{ "sst25vf016b", INFO(0xbf2541, 0, 64 * 1024, 32, SECT_4K | SST_WRITE) },
+	{ "sst25vf032b", INFO(0xbf254a, 0, 64 * 1024, 64, SECT_4K | SST_WRITE) },
+	{ "sst25vf064c", INFO(0xbf254b, 0, 64 * 1024, 128, SECT_4K) },
+	{ "sst25wf512",  INFO(0xbf2501, 0, 64 * 1024,  1, SECT_4K | SST_WRITE) },
+	{ "sst25wf010",  INFO(0xbf2502, 0, 64 * 1024,  2, SECT_4K | SST_WRITE) },
+	{ "sst25wf020",  INFO(0xbf2503, 0, 64 * 1024,  4, SECT_4K | SST_WRITE) },
+	{ "sst25wf040",  INFO(0xbf2504, 0, 64 * 1024,  8, SECT_4K | SST_WRITE) },
 
 	/* ST Microelectronics -- newer production may have feature updates */
 	{ "m25p05",  INFO(0x202010,  0,  32 * 1024,   2, 0) },
@@ -838,6 +842,7 @@ static const struct spi_device_id m25p_ids[] = {
 	{ "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) },
 	{ "w25q80", INFO(0xef5014, 0, 64 * 1024,  16, SECT_4K) },
 	{ "w25q80bl", INFO(0xef4014, 0, 64 * 1024,  16, SECT_4K) },
+	{ "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, SECT_4K) },
 	{ "w25q256", INFO(0xef4019, 0, 64 * 1024, 512, SECT_4K) },
 
 	/* Catalyst / On Semiconductor -- non-JEDEC */
@@ -1000,7 +1005,7 @@ static int m25p_probe(struct spi_device *spi)
 	}
 
 	/* sst flash chips use AAI word program */
-	if (JEDEC_MFR(info->jedec_id) == CFI_MFR_SST)
+	if (info->flags & SST_WRITE)
 		flash->mtd._write = sst_write;
 	else
 		flash->mtd._write = m25p80_write;
diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c
index 945c9f76..28779b6 100644
--- a/drivers/mtd/devices/mtd_dataflash.c
+++ b/drivers/mtd/devices/mtd_dataflash.c
@@ -105,8 +105,6 @@ static const struct of_device_id dataflash_dt_ids[] = {
 	{ .compatible = "atmel,dataflash", },
 	{ /* sentinel */ }
 };
-#else
-#define dataflash_dt_ids NULL
 #endif
 
 /* ......................................................................... */
@@ -914,7 +912,7 @@ static struct spi_driver dataflash_driver = {
 	.driver = {
 		.name		= "mtd_dataflash",
 		.owner		= THIS_MODULE,
-		.of_match_table = dataflash_dt_ids,
+		.of_match_table = of_match_ptr(dataflash_dt_ids),
 	},
 
 	.probe		= dataflash_probe,
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
index 3ed17c4..bed9634 100644
--- a/drivers/mtd/maps/Kconfig
+++ b/drivers/mtd/maps/Kconfig
@@ -249,22 +249,6 @@ config MTD_LANTIQ
 	help
 	  Support for NOR flash attached to the Lantiq SoC's External Bus Unit.
 
-config MTD_DILNETPC
-	tristate "CFI Flash device mapped on DIL/Net PC"
-	depends on X86 && MTD_CFI_INTELEXT && BROKEN
-	help
-	  MTD map driver for SSV DIL/Net PC Boards "DNP" and "ADNP".
-	  For details, see <http://www.ssv-embedded.de/ssv/pc104/p169.htm>
- 	  and <http://www.ssv-embedded.de/ssv/pc104/p170.htm>
-
-config MTD_DILNETPC_BOOTSIZE
-	hex "Size of DIL/Net PC flash boot partition"
-	depends on MTD_DILNETPC
-	default "0x80000"
-	help
-	  The amount of space taken up by the kernel or Etherboot
-	  on the DIL/Net PC flash chips.
-
 config MTD_L440GX
 	tristate "BIOS flash chip on Intel L440GX boards"
 	depends on X86 && MTD_JEDECPROBE
@@ -274,42 +258,6 @@ config MTD_L440GX
 
 	  BE VERY CAREFUL.
 
-config MTD_TQM8XXL
-	tristate "CFI Flash device mapped on TQM8XXL"
-	depends on MTD_CFI && TQM8xxL
-	help
-	  The TQM8xxL PowerPC board has up to two banks of CFI-compliant
-	  chips, currently uses AMD one. This 'mapping' driver supports
-	  that arrangement, allowing the CFI probe and command set driver
-	  code to communicate with the chips on the TQM8xxL board. More at
-	  <http://www.denx.de/wiki/PPCEmbedded/>.
-
-config MTD_RPXLITE
-	tristate "CFI Flash device mapped on RPX Lite or CLLF"
-	depends on MTD_CFI && (RPXCLASSIC || RPXLITE)
-	help
-	  The RPXLite PowerPC board has CFI-compliant chips mapped in
-	  a strange sparse mapping. This 'mapping' driver supports that
-	  arrangement, allowing the CFI probe and command set driver code
-	  to communicate with the chips on the RPXLite board. More at
-	  <http://www.embeddedplanet.com/>.
-
-config MTD_MBX860
-	tristate "System flash on MBX860 board"
-	depends on MTD_CFI && MBX
-	help
-	  This enables access routines for the flash chips on the Motorola
-	  MBX860 board. If you have one of these boards and would like
-	  to use the flash chips on it, say 'Y'.
-
-config MTD_DBOX2
-	tristate "CFI Flash device mapped on D-Box2"
-	depends on DBOX2 && MTD_CFI_INTELSTD && MTD_CFI_INTELEXT && MTD_CFI_AMDSTD
-	help
-	  This enables access routines for the flash chips on the Nokia/Sagem
-	  D-Box 2 board. If you have one of these boards and would like to use
-	  the flash chips on it, say 'Y'.
-
 config MTD_CFI_FLAGADM
 	tristate "CFI Flash device mapping on FlagaDM"
 	depends on 8xx && MTD_CFI
@@ -349,15 +297,6 @@ config MTD_IXP4XX
 	  IXDP425 and Coyote. If you have an IXP4xx based board and
 	  would like to use the flash chips on it, say 'Y'.
 
-config MTD_IXP2000
-	tristate "CFI Flash device mapped on Intel IXP2000 based systems"
-	depends on MTD_CFI && MTD_COMPLEX_MAPPINGS && ARCH_IXP2000
-	help
-	  This enables MTD access to flash devices on platforms based
-	  on Intel's IXP2000 family of network processors. If you have an
-	  IXP2000 based board and would like to use the flash chips on it,
-	  say 'Y'.
-
 config MTD_AUTCPU12
 	bool "NV-RAM mapping AUTCPU12 board"
 	depends on ARCH_AUTCPU12
@@ -372,13 +311,6 @@ config MTD_IMPA7
 	  This enables access to the NOR Flash on the impA7 board of
 	  implementa GmbH. If you have such a board, say 'Y' here.
 
-config MTD_H720X
-	tristate "Hynix evaluation board mappings"
-	depends on MTD_CFI && ( ARCH_H7201 || ARCH_H7202 )
-	help
-	  This enables access to the flash chips on the Hynix evaluation boards.
-	  If you have such a board, say 'Y'.
-
 # This needs CFI or JEDEC, depending on the cards found.
 config MTD_PCI
 	tristate "PCI MTD driver"
@@ -433,15 +365,6 @@ config MTD_UCLINUX
 	help
 	  Map driver to support image based filesystems for uClinux.
 
-config MTD_DMV182
-        tristate "Map driver for Dy-4 SVME/DMV-182 board."
-        depends on DMV182
-	select MTD_MAP_BANK_WIDTH_32
-	select MTD_CFI_I8
-	select MTD_CFI_AMDSTD
-        help
-          Map driver for Dy-4 SVME/DMV-182 board.
-
 config MTD_INTEL_VR_NOR
 	tristate "NOR flash on Intel Vermilion Range Expansion Bus CS0"
 	depends on PCI
diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile
index 4ded287..395a124 100644
--- a/drivers/mtd/maps/Makefile
+++ b/drivers/mtd/maps/Makefile
@@ -9,7 +9,6 @@ endif
 # Chip mappings
 obj-$(CONFIG_MTD_CFI_FLAGADM)	+= cfi_flagadm.o
 obj-$(CONFIG_MTD_DC21285)	+= dc21285.o
-obj-$(CONFIG_MTD_DILNETPC)	+= dilnetpc.o
 obj-$(CONFIG_MTD_L440GX)	+= l440gx.o
 obj-$(CONFIG_MTD_AMD76XROM)	+= amd76xrom.o
 obj-$(CONFIG_MTD_ESB2ROM)	+= esb2rom.o
@@ -17,15 +16,12 @@ obj-$(CONFIG_MTD_ICHXROM)	+= ichxrom.o
 obj-$(CONFIG_MTD_CK804XROM)	+= ck804xrom.o
 obj-$(CONFIG_MTD_TSUNAMI)	+= tsunami_flash.o
 obj-$(CONFIG_MTD_PXA2XX)	+= pxa2xx-flash.o
-obj-$(CONFIG_MTD_MBX860)	+= mbx860.o
 obj-$(CONFIG_MTD_OCTAGON)	+= octagon-5066.o
 obj-$(CONFIG_MTD_PHYSMAP)	+= physmap.o
 obj-$(CONFIG_MTD_PHYSMAP_OF)	+= physmap_of.o
 obj-$(CONFIG_MTD_PISMO)		+= pismo.o
 obj-$(CONFIG_MTD_PMC_MSP_EVM)   += pmcmsp-flash.o
 obj-$(CONFIG_MTD_PCMCIA)	+= pcmciamtd.o
-obj-$(CONFIG_MTD_RPXLITE)	+= rpxlite.o
-obj-$(CONFIG_MTD_TQM8XXL)	+= tqm8xxl.o
 obj-$(CONFIG_MTD_SA1100)	+= sa1100-flash.o
 obj-$(CONFIG_MTD_SBC_GXX)	+= sbc_gxx.o
 obj-$(CONFIG_MTD_SC520CDP)	+= sc520cdp.o
@@ -34,7 +30,6 @@ obj-$(CONFIG_MTD_TS5500)	+= ts5500_flash.o
 obj-$(CONFIG_MTD_SUN_UFLASH)	+= sun_uflash.o
 obj-$(CONFIG_MTD_VMAX)		+= vmax301.o
 obj-$(CONFIG_MTD_SCx200_DOCFLASH)+= scx200_docflash.o
-obj-$(CONFIG_MTD_DBOX2)		+= dbox2-flash.o
 obj-$(CONFIG_MTD_SOLUTIONENGINE)+= solutionengine.o
 obj-$(CONFIG_MTD_PCI)		+= pci.o
 obj-$(CONFIG_MTD_AUTCPU12)	+= autcpu12-nvram.o
@@ -42,10 +37,7 @@ obj-$(CONFIG_MTD_IMPA7)		+= impa7.o
 obj-$(CONFIG_MTD_UCLINUX)	+= uclinux.o
 obj-$(CONFIG_MTD_NETtel)	+= nettel.o
 obj-$(CONFIG_MTD_SCB2_FLASH)	+= scb2_flash.o
-obj-$(CONFIG_MTD_H720X)		+= h720x-flash.o
 obj-$(CONFIG_MTD_IXP4XX)	+= ixp4xx.o
-obj-$(CONFIG_MTD_IXP2000)	+= ixp2000.o
-obj-$(CONFIG_MTD_DMV182)	+= dmv182.o
 obj-$(CONFIG_MTD_PLATRAM)	+= plat-ram.o
 obj-$(CONFIG_MTD_INTEL_VR_NOR)	+= intel_vr_nor.o
 obj-$(CONFIG_MTD_BFIN_ASYNC)	+= bfin-async-flash.o
diff --git a/drivers/mtd/maps/bfin-async-flash.c b/drivers/mtd/maps/bfin-async-flash.c
index f833edf..319b04a 100644
--- a/drivers/mtd/maps/bfin-async-flash.c
+++ b/drivers/mtd/maps/bfin-async-flash.c
@@ -122,7 +122,8 @@ static void bfin_flash_copy_to(struct map_info *map, unsigned long to, const voi
 	switch_back(state);
 }
 
-static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", NULL };
+static const char * const part_probe_types[] = {
+	"cmdlinepart", "RedBoot", NULL };
 
 static int bfin_flash_probe(struct platform_device *pdev)
 {
diff --git a/drivers/mtd/maps/ck804xrom.c b/drivers/mtd/maps/ck804xrom.c
index 586a1c7..0455166 100644
--- a/drivers/mtd/maps/ck804xrom.c
+++ b/drivers/mtd/maps/ck804xrom.c
@@ -308,8 +308,7 @@ static int ck804xrom_init_one(struct pci_dev *pdev,
 
  out:
 	/* Free any left over map structures */
-	if (map)
-		kfree(map);
+	kfree(map);
 
 	/* See if I have any map structures */
 	if (list_empty(&window->maps)) {
diff --git a/drivers/mtd/maps/dbox2-flash.c b/drivers/mtd/maps/dbox2-flash.c
deleted file mode 100644
index 85bdece..0000000
--- a/drivers/mtd/maps/dbox2-flash.c
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * D-Box 2 flash driver
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <asm/io.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
-#include <linux/mtd/partitions.h>
-#include <linux/errno.h>
-
-/* partition_info gives details on the logical partitions that the split the
- * single flash device into. If the size if zero we use up to the end of the
- * device. */
-static struct mtd_partition partition_info[]= {
-	{
-	.name		= "BR bootloader",
-	.size		= 128 * 1024,
-	.offset		= 0,
-	.mask_flags	= MTD_WRITEABLE
-	},
-	{
-	.name		= "FLFS (U-Boot)",
-	.size		= 128 * 1024,
-	.offset		= MTDPART_OFS_APPEND,
-	.mask_flags	= 0
-	},
-	{
-	.name		= "Root (SquashFS)",
-	.size		= 7040 * 1024,
-	.offset		= MTDPART_OFS_APPEND,
-	.mask_flags	= 0
-	},
-	{
-	.name		= "var (JFFS2)",
-	.size		= 896 * 1024,
-	.offset		= MTDPART_OFS_APPEND,
-	.mask_flags	= 0
-	},
-	{
-	.name		= "Flash without bootloader",
-	.size		= MTDPART_SIZ_FULL,
-	.offset		= 128 * 1024,
-	.mask_flags	= 0
-	},
-	{
-	.name		= "Complete Flash",
-	.size		= MTDPART_SIZ_FULL,
-	.offset		= 0,
-	.mask_flags	= MTD_WRITEABLE
-	}
-};
-
-#define NUM_PARTITIONS ARRAY_SIZE(partition_info)
-
-#define WINDOW_ADDR 0x10000000
-#define WINDOW_SIZE 0x800000
-
-static struct mtd_info *mymtd;
-
-
-struct map_info dbox2_flash_map = {
-	.name		= "D-Box 2 flash memory",
-	.size		= WINDOW_SIZE,
-	.bankwidth	= 4,
-	.phys		= WINDOW_ADDR,
-};
-
-static int __init init_dbox2_flash(void)
-{
-       	printk(KERN_NOTICE "D-Box 2 flash driver (size->0x%X mem->0x%X)\n", WINDOW_SIZE, WINDOW_ADDR);
-	dbox2_flash_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE);
-
-	if (!dbox2_flash_map.virt) {
-		printk("Failed to ioremap\n");
-		return -EIO;
-	}
-	simple_map_init(&dbox2_flash_map);
-
-	// Probe for dual Intel 28F320 or dual AMD
-	mymtd = do_map_probe("cfi_probe", &dbox2_flash_map);
-	if (!mymtd) {
-	    // Probe for single Intel 28F640
-	    dbox2_flash_map.bankwidth = 2;
-
-	    mymtd = do_map_probe("cfi_probe", &dbox2_flash_map);
-	}
-
-	if (mymtd) {
-		mymtd->owner = THIS_MODULE;
-
-                /* Create MTD devices for each partition. */
-		mtd_device_register(mymtd, partition_info, NUM_PARTITIONS);
-
-		return 0;
-	}
-
-	iounmap((void *)dbox2_flash_map.virt);
-	return -ENXIO;
-}
-
-static void __exit cleanup_dbox2_flash(void)
-{
-	if (mymtd) {
-		mtd_device_unregister(mymtd);
-		map_destroy(mymtd);
-	}
-	if (dbox2_flash_map.virt) {
-		iounmap((void *)dbox2_flash_map.virt);
-		dbox2_flash_map.virt = 0;
-	}
-}
-
-module_init(init_dbox2_flash);
-module_exit(cleanup_dbox2_flash);
-
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Kári Davíðsson <kd@flaga.is>, Bastian Blank <waldi@tuxbox.org>, Alexander Wild <wild@te-elektronik.com>");
-MODULE_DESCRIPTION("MTD map driver for D-Box 2 board");
diff --git a/drivers/mtd/maps/dc21285.c b/drivers/mtd/maps/dc21285.c
index 080f060..f8a7dd1 100644
--- a/drivers/mtd/maps/dc21285.c
+++ b/drivers/mtd/maps/dc21285.c
@@ -143,9 +143,8 @@ static struct map_info dc21285_map = {
 	.copy_from = dc21285_copy_from,
 };
 
-
 /* Partition stuff */
-static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
+static const char * const probes[] = { "RedBoot", "cmdlinepart", NULL };
 
 static int __init init_dc21285(void)
 {
diff --git a/drivers/mtd/maps/dilnetpc.c b/drivers/mtd/maps/dilnetpc.c
deleted file mode 100644
index 3e393f0..0000000
--- a/drivers/mtd/maps/dilnetpc.c
+++ /dev/null
@@ -1,496 +0,0 @@
-/* dilnetpc.c -- MTD map driver for SSV DIL/Net PC Boards "DNP" and "ADNP"
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- *
- * The DIL/Net PC is a tiny embedded PC board made by SSV Embedded Systems
- * featuring the AMD Elan SC410 processor. There are two variants of this
- * board: DNP/1486 and ADNP/1486. The DNP version has 2 megs of flash
- * ROM (Intel 28F016S3) and 8 megs of DRAM, the ADNP version has 4 megs
- * flash and 16 megs of RAM.
- * For details, see http://www.ssv-embedded.de/ssv/pc104/p169.htm
- * and http://www.ssv-embedded.de/ssv/pc104/p170.htm
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/string.h>
-
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
-#include <linux/mtd/partitions.h>
-#include <linux/mtd/concat.h>
-
-#include <asm/io.h>
-
-/*
-** The DIL/NetPC keeps its BIOS in two distinct flash blocks.
-** Destroying any of these blocks transforms the DNPC into
-** a paperweight (albeit not a very useful one, considering
-** it only weighs a few grams).
-**
-** Therefore, the BIOS blocks must never be erased or written to
-** except by people who know exactly what they are doing (e.g.
-** to install a BIOS update). These partitions are marked read-only
-** by default, but can be made read/write by undefining
-** DNPC_BIOS_BLOCKS_WRITEPROTECTED:
-*/
-#define DNPC_BIOS_BLOCKS_WRITEPROTECTED
-
-/*
-** The ID string (in ROM) is checked to determine whether we
-** are running on a DNP/1486 or ADNP/1486
-*/
-#define BIOSID_BASE	0x000fe100
-
-#define ID_DNPC	"DNP1486"
-#define ID_ADNP	"ADNP1486"
-
-/*
-** Address where the flash should appear in CPU space
-*/
-#define FLASH_BASE	0x2000000
-
-/*
-** Chip Setup and Control (CSC) indexed register space
-*/
-#define CSC_INDEX	0x22
-#define CSC_DATA	0x23
-
-#define CSC_MMSWAR	0x30	/* MMS window C-F attributes register */
-#define CSC_MMSWDSR	0x31	/* MMS window C-F device select register */
-
-#define CSC_RBWR	0xa7	/* GPIO Read-Back/Write Register B */
-
-#define CSC_CR		0xd0	/* internal I/O device disable/Echo */
-				/* Z-bus/configuration register */
-
-#define CSC_PCCMDCR	0xf1	/* PC card mode and DMA control register */
-
-
-/*
-** PC Card indexed register space:
-*/
-
-#define PCC_INDEX	0x3e0
-#define PCC_DATA	0x3e1
-
-#define PCC_AWER_B		0x46	/* Socket B Address Window enable register */
-#define PCC_MWSAR_1_Lo	0x58	/* memory window 1 start address low register */
-#define PCC_MWSAR_1_Hi	0x59	/* memory window 1 start address high register */
-#define PCC_MWEAR_1_Lo	0x5A	/* memory window 1 stop address low register */
-#define PCC_MWEAR_1_Hi	0x5B	/* memory window 1 stop address high register */
-#define PCC_MWAOR_1_Lo	0x5C	/* memory window 1 address offset low register */
-#define PCC_MWAOR_1_Hi	0x5D	/* memory window 1 address offset high register */
-
-
-/*
-** Access to SC4x0's Chip Setup and Control (CSC)
-** and PC Card (PCC) indexed registers:
-*/
-static inline void setcsc(int reg, unsigned char data)
-{
-	outb(reg, CSC_INDEX);
-	outb(data, CSC_DATA);
-}
-
-static inline unsigned char getcsc(int reg)
-{
-	outb(reg, CSC_INDEX);
-	return(inb(CSC_DATA));
-}
-
-static inline void setpcc(int reg, unsigned char data)
-{
-	outb(reg, PCC_INDEX);
-	outb(data, PCC_DATA);
-}
-
-static inline unsigned char getpcc(int reg)
-{
-	outb(reg, PCC_INDEX);
-	return(inb(PCC_DATA));
-}
-
-
-/*
-************************************************************
-** Enable access to DIL/NetPC's flash by mapping it into
-** the SC4x0's MMS Window C.
-************************************************************
-*/
-static void dnpc_map_flash(unsigned long flash_base, unsigned long flash_size)
-{
-	unsigned long flash_end = flash_base + flash_size - 1;
-
-	/*
-	** enable setup of MMS windows C-F:
-	*/
-	/* - enable PC Card indexed register space */
-	setcsc(CSC_CR, getcsc(CSC_CR) | 0x2);
-	/* - set PC Card controller to operate in standard mode */
-	setcsc(CSC_PCCMDCR, getcsc(CSC_PCCMDCR) & ~1);
-
-	/*
-	** Program base address and end address of window
-	** where the flash ROM should appear in CPU address space
-	*/
-	setpcc(PCC_MWSAR_1_Lo, (flash_base >> 12) & 0xff);
-	setpcc(PCC_MWSAR_1_Hi, (flash_base >> 20) & 0x3f);
-	setpcc(PCC_MWEAR_1_Lo, (flash_end >> 12) & 0xff);
-	setpcc(PCC_MWEAR_1_Hi, (flash_end >> 20) & 0x3f);
-
-	/* program offset of first flash location to appear in this window (0) */
-	setpcc(PCC_MWAOR_1_Lo, ((0 - flash_base) >> 12) & 0xff);
-	setpcc(PCC_MWAOR_1_Hi, ((0 - flash_base)>> 20) & 0x3f);
-
-	/* set attributes for MMS window C: non-cacheable, write-enabled */
-	setcsc(CSC_MMSWAR, getcsc(CSC_MMSWAR) & ~0x11);
-
-	/* select physical device ROMCS0 (i.e. flash) for MMS Window C */
-	setcsc(CSC_MMSWDSR, getcsc(CSC_MMSWDSR) & ~0x03);
-
-	/* enable memory window 1 */
-	setpcc(PCC_AWER_B, getpcc(PCC_AWER_B) | 0x02);
-
-	/* now disable PC Card indexed register space again */
-	setcsc(CSC_CR, getcsc(CSC_CR) & ~0x2);
-}
-
-
-/*
-************************************************************
-** Disable access to DIL/NetPC's flash by mapping it into
-** the SC4x0's MMS Window C.
-************************************************************
-*/
-static void dnpc_unmap_flash(void)
-{
-	/* - enable PC Card indexed register space */
-	setcsc(CSC_CR, getcsc(CSC_CR) | 0x2);
-
-	/* disable memory window 1 */
-	setpcc(PCC_AWER_B, getpcc(PCC_AWER_B) & ~0x02);
-
-	/* now disable PC Card indexed register space again */
-	setcsc(CSC_CR, getcsc(CSC_CR) & ~0x2);
-}
-
-
-
-/*
-************************************************************
-** Enable/Disable VPP to write to flash
-************************************************************
-*/
-
-static DEFINE_SPINLOCK(dnpc_spin);
-static int        vpp_counter = 0;
-/*
-** This is what has to be done for the DNP board ..
-*/
-static void dnp_set_vpp(struct map_info *not_used, int on)
-{
-	spin_lock_irq(&dnpc_spin);
-
-	if (on)
-	{
-		if(++vpp_counter == 1)
-			setcsc(CSC_RBWR, getcsc(CSC_RBWR) & ~0x4);
-	}
-	else
-	{
-		if(--vpp_counter == 0)
-			setcsc(CSC_RBWR, getcsc(CSC_RBWR) | 0x4);
-		else
-			BUG_ON(vpp_counter < 0);
-	}
-	spin_unlock_irq(&dnpc_spin);
-}
-
-/*
-** .. and this the ADNP version:
-*/
-static void adnp_set_vpp(struct map_info *not_used, int on)
-{
-	spin_lock_irq(&dnpc_spin);
-
-	if (on)
-	{
-		if(++vpp_counter == 1)
-			setcsc(CSC_RBWR, getcsc(CSC_RBWR) & ~0x8);
-	}
-	else
-	{
-		if(--vpp_counter == 0)
-			setcsc(CSC_RBWR, getcsc(CSC_RBWR) | 0x8);
-		else
-			BUG_ON(vpp_counter < 0);
-	}
-	spin_unlock_irq(&dnpc_spin);
-}
-
-
-
-#define DNP_WINDOW_SIZE		0x00200000	/*  DNP flash size is 2MiB  */
-#define ADNP_WINDOW_SIZE	0x00400000	/* ADNP flash size is 4MiB */
-#define WINDOW_ADDR		FLASH_BASE
-
-static struct map_info dnpc_map = {
-	.name = "ADNP Flash Bank",
-	.size = ADNP_WINDOW_SIZE,
-	.bankwidth = 1,
-	.set_vpp = adnp_set_vpp,
-	.phys = WINDOW_ADDR
-};
-
-/*
-** The layout of the flash is somewhat "strange":
-**
-** 1.  960 KiB (15 blocks) : Space for ROM Bootloader and user data
-** 2.   64 KiB (1 block)   : System BIOS
-** 3.  960 KiB (15 blocks) : User Data (DNP model) or
-** 3. 3008 KiB (47 blocks) : User Data (ADNP model)
-** 4.   64 KiB (1 block)   : System BIOS Entry
-*/
-
-static struct mtd_partition partition_info[]=
-{
-	{
-		.name =		"ADNP boot",
-		.offset =	0,
-		.size =		0xf0000,
-	},
-	{
-		.name =		"ADNP system BIOS",
-		.offset =	MTDPART_OFS_NXTBLK,
-		.size =		0x10000,
-#ifdef DNPC_BIOS_BLOCKS_WRITEPROTECTED
-		.mask_flags =	MTD_WRITEABLE,
-#endif
-	},
-	{
-		.name =		"ADNP file system",
-		.offset =	MTDPART_OFS_NXTBLK,
-		.size =		0x2f0000,
-	},
-	{
-		.name =		"ADNP system BIOS entry",
-		.offset =	MTDPART_OFS_NXTBLK,
-		.size =		MTDPART_SIZ_FULL,
-#ifdef DNPC_BIOS_BLOCKS_WRITEPROTECTED
-		.mask_flags =	MTD_WRITEABLE,
-#endif
-	},
-};
-
-#define NUM_PARTITIONS ARRAY_SIZE(partition_info)
-
-static struct mtd_info *mymtd;
-static struct mtd_info *lowlvl_parts[NUM_PARTITIONS];
-static struct mtd_info *merged_mtd;
-
-/*
-** "Highlevel" partition info:
-**
-** Using the MTD concat layer, we can re-arrange partitions to our
-** liking: we construct a virtual MTD device by concatenating the
-** partitions, specifying the sequence such that the boot block
-** is immediately followed by the filesystem block (i.e. the stupid
-** system BIOS block is mapped to a different place). When re-partitioning
-** this concatenated MTD device, we can set the boot block size to
-** an arbitrary (though erase block aligned) value i.e. not one that
-** is dictated by the flash's physical layout. We can thus set the
-** boot block to be e.g. 64 KB (which is fully sufficient if we want
-** to boot an etherboot image) or to -say- 1.5 MB if we want to boot
-** a large kernel image. In all cases, the remainder of the flash
-** is available as file system space.
-*/
-
-static struct mtd_partition higlvl_partition_info[]=
-{
-	{
-		.name =		"ADNP boot block",
-		.offset =	0,
-		.size =		CONFIG_MTD_DILNETPC_BOOTSIZE,
-	},
-	{
-		.name =		"ADNP file system space",
-		.offset =	MTDPART_OFS_NXTBLK,
-		.size =		ADNP_WINDOW_SIZE-CONFIG_MTD_DILNETPC_BOOTSIZE-0x20000,
-	},
-	{
-		.name =		"ADNP system BIOS + BIOS Entry",
-		.offset =	MTDPART_OFS_NXTBLK,
-		.size =		MTDPART_SIZ_FULL,
-#ifdef DNPC_BIOS_BLOCKS_WRITEPROTECTED
-		.mask_flags =	MTD_WRITEABLE,
-#endif
-	},
-};
-
-#define NUM_HIGHLVL_PARTITIONS ARRAY_SIZE(higlvl_partition_info)
-
-
-static int dnp_adnp_probe(void)
-{
-	char *biosid, rc = -1;
-
-	biosid = (char*)ioremap(BIOSID_BASE, 16);
-	if(biosid)
-	{
-		if(!strcmp(biosid, ID_DNPC))
-			rc = 1;		/* this is a DNPC  */
-		else if(!strcmp(biosid, ID_ADNP))
-			rc = 0;		/* this is a ADNPC */
-	}
-	iounmap((void *)biosid);
-	return(rc);
-}
-
-
-static int __init init_dnpc(void)
-{
-	int is_dnp;
-
-	/*
-	** determine hardware (DNP/ADNP/invalid)
-	*/
-	if((is_dnp = dnp_adnp_probe()) < 0)
-		return -ENXIO;
-
-	/*
-	** Things are set up for ADNP by default
-	** -> modify all that needs to be different for DNP
-	*/
-	if(is_dnp)
-	{	/*
-		** Adjust window size, select correct set_vpp function.
-		** The partitioning scheme is identical on both DNP
-		** and ADNP except for the size of the third partition.
-		*/
-		int i;
-		dnpc_map.size          = DNP_WINDOW_SIZE;
-		dnpc_map.set_vpp       = dnp_set_vpp;
-		partition_info[2].size = 0xf0000;
-
-		/*
-		** increment all string pointers so the leading 'A' gets skipped,
-		** thus turning all occurrences of "ADNP ..." into "DNP ..."
-		*/
-		++dnpc_map.name;
-		for(i = 0; i < NUM_PARTITIONS; i++)
-			++partition_info[i].name;
-		higlvl_partition_info[1].size = DNP_WINDOW_SIZE -
-			CONFIG_MTD_DILNETPC_BOOTSIZE - 0x20000;
-		for(i = 0; i < NUM_HIGHLVL_PARTITIONS; i++)
-			++higlvl_partition_info[i].name;
-	}
-
-	printk(KERN_NOTICE "DIL/Net %s flash: 0x%lx at 0x%llx\n",
-		is_dnp ? "DNPC" : "ADNP", dnpc_map.size, (unsigned long long)dnpc_map.phys);
-
-	dnpc_map.virt = ioremap_nocache(dnpc_map.phys, dnpc_map.size);
-
-	dnpc_map_flash(dnpc_map.phys, dnpc_map.size);
-
-	if (!dnpc_map.virt) {
-		printk("Failed to ioremap_nocache\n");
-		return -EIO;
-	}
-	simple_map_init(&dnpc_map);
-
-	printk("FLASH virtual address: 0x%p\n", dnpc_map.virt);
-
-	mymtd = do_map_probe("jedec_probe", &dnpc_map);
-
-	if (!mymtd)
-		mymtd = do_map_probe("cfi_probe", &dnpc_map);
-
-	/*
-	** If flash probes fail, try to make flashes accessible
-	** at least as ROM. Ajust erasesize in this case since
-	** the default one (128M) will break our partitioning
-	*/
-	if (!mymtd)
-		if((mymtd = do_map_probe("map_rom", &dnpc_map)))
-			mymtd->erasesize = 0x10000;
-
-	if (!mymtd) {
-		iounmap(dnpc_map.virt);
-		return -ENXIO;
-	}
-
-	mymtd->owner = THIS_MODULE;
-
-	/*
-	** Supply pointers to lowlvl_parts[] array to add_mtd_partitions()
-	** -> add_mtd_partitions() will _not_ register MTD devices for
-	** the partitions, but will instead store pointers to the MTD
-	** objects it creates into our lowlvl_parts[] array.
-	** NOTE: we arrange the pointers such that the sequence of the
-	**       partitions gets re-arranged: partition #2 follows
-	**       partition #0.
-	*/
-	partition_info[0].mtdp = &lowlvl_parts[0];
-	partition_info[1].mtdp = &lowlvl_parts[2];
-	partition_info[2].mtdp = &lowlvl_parts[1];
-	partition_info[3].mtdp = &lowlvl_parts[3];
-
-	mtd_device_register(mymtd, partition_info, NUM_PARTITIONS);
-
-	/*
-	** now create a virtual MTD device by concatenating the for partitions
-	** (in the sequence given by the lowlvl_parts[] array.
-	*/
-	merged_mtd = mtd_concat_create(lowlvl_parts, NUM_PARTITIONS, "(A)DNP Flash Concatenated");
-	if(merged_mtd)
-	{	/*
-		** now partition the new device the way we want it. This time,
-		** we do not supply mtd pointers in higlvl_partition_info, so
-		** add_mtd_partitions() will register the devices.
-		*/
-		mtd_device_register(merged_mtd, higlvl_partition_info,
-				    NUM_HIGHLVL_PARTITIONS);
-	}
-
-	return 0;
-}
-
-static void __exit cleanup_dnpc(void)
-{
-	if(merged_mtd) {
-		mtd_device_unregister(merged_mtd);
-		mtd_concat_destroy(merged_mtd);
-	}
-
-	if (mymtd) {
-		mtd_device_unregister(mymtd);
-		map_destroy(mymtd);
-	}
-	if (dnpc_map.virt) {
-		iounmap(dnpc_map.virt);
-		dnpc_unmap_flash();
-		dnpc_map.virt = NULL;
-	}
-}
-
-module_init(init_dnpc);
-module_exit(cleanup_dnpc);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Sysgo Real-Time Solutions GmbH");
-MODULE_DESCRIPTION("MTD map driver for SSV DIL/NetPC DNP & ADNP");
diff --git a/drivers/mtd/maps/dmv182.c b/drivers/mtd/maps/dmv182.c
deleted file mode 100644
index 6538ac6..0000000
--- a/drivers/mtd/maps/dmv182.c
+++ /dev/null
@@ -1,146 +0,0 @@
-
-/*
- * drivers/mtd/maps/dmv182.c
- *
- * Flash map driver for the Dy4 SVME182 board
- *
- * Copyright 2003-2004, TimeSys Corporation
- *
- * Based on the SVME181 flash map, by Tom Nelson, Dot4, Inc. for TimeSys 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/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <asm/io.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
-#include <linux/mtd/partitions.h>
-#include <linux/errno.h>
-
-/*
- * This driver currently handles only the 16MiB user flash bank 1 on the
- * board.  It does not provide access to bank 0 (contains the Dy4 FFW), bank 2
- * (VxWorks boot), or the optional 48MiB expansion flash.
- *
- * scott.wood@timesys.com: On the newer boards with 128MiB flash, it
- * now supports the first 96MiB (the boot flash bank containing FFW
- * is excluded).  The VxWorks loader is in partition 1.
- */
-
-#define FLASH_BASE_ADDR 0xf0000000
-#define FLASH_BANK_SIZE (128*1024*1024)
-
-MODULE_AUTHOR("Scott Wood, TimeSys Corporation <scott.wood@timesys.com>");
-MODULE_DESCRIPTION("User-programmable flash device on the Dy4 SVME182 board");
-MODULE_LICENSE("GPL");
-
-static struct map_info svme182_map = {
-	.name		= "Dy4 SVME182",
-	.bankwidth	= 32,
-	.size		=  128 * 1024 * 1024
-};
-
-#define BOOTIMAGE_PART_SIZE		((6*1024*1024)-RESERVED_PART_SIZE)
-
-// Allow 6MiB for the kernel
-#define NEW_BOOTIMAGE_PART_SIZE  (6 * 1024 * 1024)
-// Allow 1MiB for the bootloader
-#define NEW_BOOTLOADER_PART_SIZE (1024 * 1024)
-// Use the remaining 9MiB at the end of flash for the RFS
-#define NEW_RFS_PART_SIZE        (0x01000000 - NEW_BOOTLOADER_PART_SIZE - \
-                                  NEW_BOOTIMAGE_PART_SIZE)
-
-static struct mtd_partition svme182_partitions[] = {
-	// The Lower PABS is only 128KiB, but the partition code doesn't
-	// like partitions that don't end on the largest erase block
-	// size of the device, even if all of the erase blocks in the
-	// partition are small ones.  The hardware should prevent
-	// writes to the actual PABS areas.
-	{
-		name:       "Lower PABS and CPU 0 bootloader or kernel",
-		size:       6*1024*1024,
-		offset:     0,
-	},
-	{
-		name:       "Root Filesystem",
-		size:       10*1024*1024,
-		offset:     MTDPART_OFS_NXTBLK
-	},
-	{
-		name:       "CPU1 Bootloader",
-		size:       1024*1024,
-		offset:     MTDPART_OFS_NXTBLK,
-	},
-	{
-		name:       "Extra",
-		size:       110*1024*1024,
-		offset:     MTDPART_OFS_NXTBLK
-	},
-	{
-		name:       "Foundation Firmware and Upper PABS",
-		size:       1024*1024,
-		offset:     MTDPART_OFS_NXTBLK,
-		mask_flags: MTD_WRITEABLE // read-only
-	}
-};
-
-static struct mtd_info *this_mtd;
-
-static int __init init_svme182(void)
-{
-	struct mtd_partition *partitions;
-	int num_parts = ARRAY_SIZE(svme182_partitions);
-
-	partitions = svme182_partitions;
-
-	svme182_map.virt = ioremap(FLASH_BASE_ADDR, svme182_map.size);
-
-	if (svme182_map.virt == 0) {
-		printk("Failed to ioremap FLASH memory area.\n");
-		return -EIO;
-	}
-
-	simple_map_init(&svme182_map);
-
-	this_mtd = do_map_probe("cfi_probe", &svme182_map);
-	if (!this_mtd)
-	{
-		iounmap((void *)svme182_map.virt);
-		return -ENXIO;
-	}
-
-	printk(KERN_NOTICE "SVME182 flash device: %dMiB at 0x%08x\n",
-		   this_mtd->size >> 20, FLASH_BASE_ADDR);
-
-	this_mtd->owner = THIS_MODULE;
-	mtd_device_register(this_mtd, partitions, num_parts);
-
-	return 0;
-}
-
-static void __exit cleanup_svme182(void)
-{
-	if (this_mtd)
-	{
-		mtd_device_unregister(this_mtd);
-		map_destroy(this_mtd);
-	}
-
-	if (svme182_map.virt)
-	{
-		iounmap((void *)svme182_map.virt);
-		svme182_map.virt = 0;
-	}
-
-	return;
-}
-
-module_init(init_svme182);
-module_exit(cleanup_svme182);
diff --git a/drivers/mtd/maps/gpio-addr-flash.c b/drivers/mtd/maps/gpio-addr-flash.c
index 7b643de..5ede282 100644
--- a/drivers/mtd/maps/gpio-addr-flash.c
+++ b/drivers/mtd/maps/gpio-addr-flash.c
@@ -157,7 +157,8 @@ static void gf_copy_to(struct map_info *map, unsigned long to,
 	memcpy_toio(map->virt + (to % state->win_size), from, len);
 }
 
-static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", NULL };
+static const char * const part_probe_types[] = {
+	"cmdlinepart", "RedBoot", NULL };
 
 /**
  * gpio_flash_probe() - setup a mapping for a GPIO assisted flash
diff --git a/drivers/mtd/maps/h720x-flash.c b/drivers/mtd/maps/h720x-flash.c
deleted file mode 100644
index 8ed6cb4..0000000
--- a/drivers/mtd/maps/h720x-flash.c
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Flash memory access on Hynix GMS30C7201/HMS30C7202 based
- * evaluation boards
- *
- * (C) 2002 Jungjun Kim <jungjun.kim@hynix.com>
- *     2003 Thomas Gleixner <tglx@linutronix.de>
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
-#include <linux/mtd/partitions.h>
-#include <mach/hardware.h>
-#include <asm/io.h>
-
-static struct mtd_info *mymtd;
-
-static struct map_info h720x_map = {
-	.name =		"H720X",
-	.bankwidth =	4,
-	.size =		H720X_FLASH_SIZE,
-	.phys =		H720X_FLASH_PHYS,
-};
-
-static struct mtd_partition h720x_partitions[] = {
-        {
-                .name = "ArMon",
-                .size = 0x00080000,
-                .offset = 0,
-                .mask_flags = MTD_WRITEABLE
-        },{
-                .name = "Env",
-                .size = 0x00040000,
-                .offset = 0x00080000,
-                .mask_flags = MTD_WRITEABLE
-        },{
-                .name = "Kernel",
-                .size = 0x00180000,
-                .offset = 0x000c0000,
-                .mask_flags = MTD_WRITEABLE
-        },{
-                .name = "Ramdisk",
-                .size = 0x00400000,
-                .offset = 0x00240000,
-                .mask_flags = MTD_WRITEABLE
-        },{
-                .name = "jffs2",
-                .size = MTDPART_SIZ_FULL,
-                .offset = MTDPART_OFS_APPEND
-        }
-};
-
-#define NUM_PARTITIONS ARRAY_SIZE(h720x_partitions)
-
-/*
- * Initialize FLASH support
- */
-static int __init h720x_mtd_init(void)
-{
-	h720x_map.virt = ioremap(h720x_map.phys, h720x_map.size);
-
-	if (!h720x_map.virt) {
-		printk(KERN_ERR "H720x-MTD: ioremap failed\n");
-		return -EIO;
-	}
-
-	simple_map_init(&h720x_map);
-
-	// Probe for flash bankwidth 4
-	printk (KERN_INFO "H720x-MTD probing 32bit FLASH\n");
-	mymtd = do_map_probe("cfi_probe", &h720x_map);
-	if (!mymtd) {
-		printk (KERN_INFO "H720x-MTD probing 16bit FLASH\n");
-	    // Probe for bankwidth 2
-	    h720x_map.bankwidth = 2;
-	    mymtd = do_map_probe("cfi_probe", &h720x_map);
-	}
-
-	if (mymtd) {
-		mymtd->owner = THIS_MODULE;
-
-		mtd_device_parse_register(mymtd, NULL, NULL,
-					  h720x_partitions, NUM_PARTITIONS);
-		return 0;
-	}
-
-	iounmap((void *)h720x_map.virt);
-	return -ENXIO;
-}
-
-/*
- * Cleanup
- */
-static void __exit h720x_mtd_cleanup(void)
-{
-
-	if (mymtd) {
-		mtd_device_unregister(mymtd);
-		map_destroy(mymtd);
-	}
-
-	if (h720x_map.virt) {
-		iounmap((void *)h720x_map.virt);
-		h720x_map.virt = 0;
-	}
-}
-
-
-module_init(h720x_mtd_init);
-module_exit(h720x_mtd_cleanup);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Thomas Gleixner <tglx@linutronix.de>");
-MODULE_DESCRIPTION("MTD map driver for Hynix evaluation boards");
diff --git a/drivers/mtd/maps/impa7.c b/drivers/mtd/maps/impa7.c
index 834a06c..4968674 100644
--- a/drivers/mtd/maps/impa7.c
+++ b/drivers/mtd/maps/impa7.c
@@ -24,14 +24,12 @@
 #define NUM_FLASHBANKS 2
 #define BUSWIDTH     4
 
-/* can be { "cfi_probe", "jedec_probe", "map_rom", NULL } */
-#define PROBETYPES { "jedec_probe", NULL }
-
 #define MSG_PREFIX "impA7:"   /* prefix for our printk()'s */
 #define MTDID      "impa7-%d"  /* for mtdparts= partitioning */
 
 static struct mtd_info *impa7_mtd[NUM_FLASHBANKS];
 
+static const char * const rom_probe_types[] = { "jedec_probe", NULL };
 
 static struct map_info impa7_map[NUM_FLASHBANKS] = {
 	{
@@ -60,8 +58,7 @@ static struct mtd_partition partitions[] =
 
 static int __init init_impa7(void)
 {
-	static const char *rom_probe_types[] = PROBETYPES;
-	const char **type;
+	const char * const *type;
 	int i;
 	static struct { u_long addr; u_long size; } pt[NUM_FLASHBANKS] = {
 	  { WINDOW_ADDR0, WINDOW_SIZE0 },
diff --git a/drivers/mtd/maps/intel_vr_nor.c b/drivers/mtd/maps/intel_vr_nor.c
index b14053b..f581ac1 100644
--- a/drivers/mtd/maps/intel_vr_nor.c
+++ b/drivers/mtd/maps/intel_vr_nor.c
@@ -82,9 +82,9 @@ static void vr_nor_destroy_mtd_setup(struct vr_nor_mtd *p)
 
 static int vr_nor_mtd_setup(struct vr_nor_mtd *p)
 {
-	static const char *probe_types[] =
+	static const char * const probe_types[] =
 	    { "cfi_probe", "jedec_probe", NULL };
-	const char **type;
+	const char * const *type;
 
 	for (type = probe_types; !p->info && *type; type++)
 		p->info = do_map_probe(*type, &p->map);
diff --git a/drivers/mtd/maps/ixp2000.c b/drivers/mtd/maps/ixp2000.c
deleted file mode 100644
index 4a41ced..0000000
--- a/drivers/mtd/maps/ixp2000.c
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * drivers/mtd/maps/ixp2000.c
- *
- * Mapping for the Intel XScale IXP2000 based systems
- *
- * Copyright (C) 2002 Intel Corp.
- * Copyright (C) 2003-2004 MontaVista Software, Inc.
- *
- * Original Author: Naeem M Afzal <naeem.m.afzal@intel.com>
- * Maintainer: Deepak Saxena <dsaxena@plexity.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/ioport.h>
-#include <linux/device.h>
-#include <linux/platform_device.h>
-
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
-#include <linux/mtd/partitions.h>
-
-#include <asm/io.h>
-#include <mach/hardware.h>
-#include <asm/mach/flash.h>
-
-#include <linux/reboot.h>
-
-struct ixp2000_flash_info {
-	struct		mtd_info *mtd;
-	struct		map_info map;
-	struct		resource *res;
-};
-
-static inline unsigned long flash_bank_setup(struct map_info *map, unsigned long ofs)
-{
-	unsigned long (*set_bank)(unsigned long) =
-		(unsigned long(*)(unsigned long))map->map_priv_2;
-
-	return (set_bank ? set_bank(ofs) : ofs);
-}
-
-#ifdef __ARMEB__
-/*
- * Rev A0 and A1 of IXP2400 silicon have a broken addressing unit which
- * causes the lower address bits to be XORed with 0x11 on 8 bit accesses
- * and XORed with 0x10 on 16 bit accesses. See the spec update, erratum 44.
- */
-static int erratum44_workaround = 0;
-
-static inline unsigned long address_fix8_write(unsigned long addr)
-{
-	if (erratum44_workaround) {
-		return (addr ^ 3);
-	}
-	return addr;
-}
-#else
-
-#define address_fix8_write(x)	(x)
-#endif
-
-static map_word ixp2000_flash_read8(struct map_info *map, unsigned long ofs)
-{
-	map_word val;
-
-	val.x[0] =  *((u8 *)(map->map_priv_1 + flash_bank_setup(map, ofs)));
-	return val;
-}
-
-/*
- * We can't use the standard memcpy due to the broken SlowPort
- * address translation on rev A0 and A1 silicon and the fact that
- * we have banked flash.
- */
-static void ixp2000_flash_copy_from(struct map_info *map, void *to,
-			      unsigned long from, ssize_t len)
-{
-	from = flash_bank_setup(map, from);
-	while(len--)
-		*(__u8 *) to++ = *(__u8 *)(map->map_priv_1 + from++);
-}
-
-static void ixp2000_flash_write8(struct map_info *map, map_word d, unsigned long ofs)
-{
-	*(__u8 *) (address_fix8_write(map->map_priv_1 +
-				      flash_bank_setup(map, ofs))) = d.x[0];
-}
-
-static void ixp2000_flash_copy_to(struct map_info *map, unsigned long to,
-			    const void *from, ssize_t len)
-{
-	to = flash_bank_setup(map, to);
-	while(len--) {
-		unsigned long tmp = address_fix8_write(map->map_priv_1 + to++);
-		*(__u8 *)(tmp) = *(__u8 *)(from++);
-	}
-}
-
-
-static int ixp2000_flash_remove(struct platform_device *dev)
-{
-	struct flash_platform_data *plat = dev->dev.platform_data;
-	struct ixp2000_flash_info *info = platform_get_drvdata(dev);
-
-	platform_set_drvdata(dev, NULL);
-
-	if(!info)
-		return 0;
-
-	if (info->mtd) {
-		mtd_device_unregister(info->mtd);
-		map_destroy(info->mtd);
-	}
-	if (info->map.map_priv_1)
-		iounmap((void *) info->map.map_priv_1);
-
-	if (info->res) {
-		release_resource(info->res);
-		kfree(info->res);
-	}
-
-	if (plat->exit)
-		plat->exit();
-
-	return 0;
-}
-
-
-static int ixp2000_flash_probe(struct platform_device *dev)
-{
-	static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
-	struct ixp2000_flash_data *ixp_data = dev->dev.platform_data;
-	struct flash_platform_data *plat;
-	struct ixp2000_flash_info *info;
-	unsigned long window_size;
-	int err = -1;
-
-	if (!ixp_data)
-		return -ENODEV;
-
-	plat = ixp_data->platform_data;
-	if (!plat)
-		return -ENODEV;
-
-	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));
-
-	if (plat->width != 1) {
-		dev_err(&dev->dev, "IXP2000 MTD map only supports 8-bit mode, asking for %d\n",
-			plat->width * 8);
-		return -EIO;
-	}
-
-	info = kzalloc(sizeof(struct ixp2000_flash_info), GFP_KERNEL);
-	if(!info) {
-		err = -ENOMEM;
-		goto Error;
-	}
-
-	platform_set_drvdata(dev, info);
-
-	/*
-	 * Tell the MTD layer we're not 1:1 mapped so that it does
-	 * not attempt to do a direct access on us.
-	 */
-	info->map.phys = NO_XIP;
-
-	info->map.size = ixp_data->nr_banks * window_size;
-	info->map.bankwidth = 1;
-
-	/*
- 	 * map_priv_2 is used to store a ptr to the bank_setup routine
- 	 */
-	info->map.map_priv_2 = (unsigned long) ixp_data->bank_setup;
-
-	info->map.name = dev_name(&dev->dev);
-	info->map.read = ixp2000_flash_read8;
-	info->map.write = ixp2000_flash_write8;
-	info->map.copy_from = ixp2000_flash_copy_from;
-	info->map.copy_to = ixp2000_flash_copy_to;
-
-	info->res = request_mem_region(dev->resource->start,
-				       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,
-				       resource_size(dev->resource));
-	if (!info->map.map_priv_1) {
-		dev_err(&dev->dev, "Failed to ioremap flash region\n");
-		err = -EIO;
-		goto Error;
-	}
-
-#if defined(__ARMEB__)
-	/*
-	 * Enable erratum 44 workaround for NPUs with broken slowport
-	 */
-
-	erratum44_workaround = ixp2000_has_broken_slowport();
-	dev_info(&dev->dev, "Erratum 44 workaround %s\n",
-	       erratum44_workaround ? "enabled" : "disabled");
-#endif
-
-	info->mtd = do_map_probe(plat->map_name, &info->map);
-	if (!info->mtd) {
-		dev_err(&dev->dev, "map_probe failed\n");
-		err = -ENXIO;
-		goto Error;
-	}
-	info->mtd->owner = THIS_MODULE;
-
-	err = mtd_device_parse_register(info->mtd, probes, NULL, NULL, 0);
-	if (err)
-		goto Error;
-
-	return 0;
-
-Error:
-	ixp2000_flash_remove(dev);
-	return err;
-}
-
-static struct platform_driver ixp2000_flash_driver = {
-	.probe		= ixp2000_flash_probe,
-	.remove		= ixp2000_flash_remove,
-	.driver		= {
-		.name	= "IXP2000-Flash",
-		.owner	= THIS_MODULE,
-	},
-};
-
-module_platform_driver(ixp2000_flash_driver);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net>");
-MODULE_ALIAS("platform:IXP2000-Flash");
diff --git a/drivers/mtd/maps/ixp4xx.c b/drivers/mtd/maps/ixp4xx.c
index e864fc6..52b3410 100644
--- a/drivers/mtd/maps/ixp4xx.c
+++ b/drivers/mtd/maps/ixp4xx.c
@@ -148,7 +148,7 @@ struct ixp4xx_flash_info {
 	struct resource *res;
 };
 
-static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
+static const char * const probes[] = { "RedBoot", "cmdlinepart", NULL };
 
 static int ixp4xx_flash_remove(struct platform_device *dev)
 {
diff --git a/drivers/mtd/maps/lantiq-flash.c b/drivers/mtd/maps/lantiq-flash.c
index d1da6ed..d7ac65d 100644
--- a/drivers/mtd/maps/lantiq-flash.c
+++ b/drivers/mtd/maps/lantiq-flash.c
@@ -46,8 +46,7 @@ struct ltq_mtd {
 };
 
 static const char ltq_map_name[] = "ltq_nor";
-static const char *ltq_probe_types[] = {
-					"cmdlinepart", "ofpart", NULL };
+static const char * const ltq_probe_types[] = { "cmdlinepart", "ofpart", NULL };
 
 static map_word
 ltq_read16(struct map_info *map, unsigned long adr)
diff --git a/drivers/mtd/maps/mbx860.c b/drivers/mtd/maps/mbx860.c
deleted file mode 100644
index 93fa56c..0000000
--- a/drivers/mtd/maps/mbx860.c
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Handle mapping of the flash on MBX860 boards
- *
- * Author:	Anton Todorov
- * Copyright:	(C) 2001 Emness Technology
- *
- * This program is free software; you can 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/types.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <asm/io.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
-#include <linux/mtd/partitions.h>
-
-
-#define WINDOW_ADDR 0xfe000000
-#define WINDOW_SIZE 0x00200000
-
-/* Flash / Partition sizing */
-#define MAX_SIZE_KiB              8192
-#define BOOT_PARTITION_SIZE_KiB    512
-#define KERNEL_PARTITION_SIZE_KiB 5632
-#define APP_PARTITION_SIZE_KiB    2048
-
-#define NUM_PARTITIONS 3
-
-/* partition_info gives details on the logical partitions that the split the
- * single flash device into. If the size if zero we use up to the end of the
- * device. */
-static struct mtd_partition partition_info[]={
-	{ .name = "MBX flash BOOT partition",
-	.offset = 0,
-	.size =   BOOT_PARTITION_SIZE_KiB*1024 },
-	{ .name = "MBX flash DATA partition",
-	.offset = BOOT_PARTITION_SIZE_KiB*1024,
-	.size = (KERNEL_PARTITION_SIZE_KiB)*1024 },
-	{ .name = "MBX flash APPLICATION partition",
-	.offset = (BOOT_PARTITION_SIZE_KiB+KERNEL_PARTITION_SIZE_KiB)*1024 }
-};
-
-
-static struct mtd_info *mymtd;
-
-struct map_info mbx_map = {
-	.name = "MBX flash",
-	.size = WINDOW_SIZE,
-	.phys = WINDOW_ADDR,
-	.bankwidth = 4,
-};
-
-static int __init init_mbx(void)
-{
-	printk(KERN_NOTICE "Motorola MBX flash device: 0x%x at 0x%x\n", WINDOW_SIZE*4, WINDOW_ADDR);
-	mbx_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE * 4);
-
-	if (!mbx_map.virt) {
-		printk("Failed to ioremap\n");
-		return -EIO;
-	}
-	simple_map_init(&mbx_map);
-
-	mymtd = do_map_probe("jedec_probe", &mbx_map);
-	if (mymtd) {
-		mymtd->owner = THIS_MODULE;
-		mtd_device_register(mymtd, NULL, 0);
-		mtd_device_register(mymtd, partition_info, NUM_PARTITIONS);
-		return 0;
-	}
-
-	iounmap((void *)mbx_map.virt);
-	return -ENXIO;
-}
-
-static void __exit cleanup_mbx(void)
-{
-	if (mymtd) {
-		mtd_device_unregister(mymtd);
-		map_destroy(mymtd);
-	}
-	if (mbx_map.virt) {
-		iounmap((void *)mbx_map.virt);
-		mbx_map.virt = 0;
-	}
-}
-
-module_init(init_mbx);
-module_exit(cleanup_mbx);
-
-MODULE_AUTHOR("Anton Todorov <a.todorov@emness.com>");
-MODULE_DESCRIPTION("MTD map driver for Motorola MBX860 board");
-MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/maps/pci.c b/drivers/mtd/maps/pci.c
index c3aebd5..c2604f8 100644
--- a/drivers/mtd/maps/pci.c
+++ b/drivers/mtd/maps/pci.c
@@ -283,8 +283,7 @@ static int mtd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 	if (err)
 		goto release;
 
-	/* tsk - do_map_probe should take const char * */
-	mtd = do_map_probe((char *)info->map_name, &map->map);
+	mtd = do_map_probe(info->map_name, &map->map);
 	err = -ENODEV;
 	if (!mtd)
 		goto release;
diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c
index 21b0b71..e7a592c 100644
--- a/drivers/mtd/maps/physmap.c
+++ b/drivers/mtd/maps/physmap.c
@@ -87,21 +87,18 @@ static void physmap_set_vpp(struct map_info *map, int state)
 	spin_unlock_irqrestore(&info->vpp_lock, flags);
 }
 
-static const char *rom_probe_types[] = {
-					"cfi_probe",
-					"jedec_probe",
-					"qinfo_probe",
-					"map_rom",
-					NULL };
-static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", "afs",
-					  NULL };
+static const char * const rom_probe_types[] = {
+	"cfi_probe", "jedec_probe", "qinfo_probe", "map_rom", NULL };
+
+static const char * const part_probe_types[] = {
+	"cmdlinepart", "RedBoot", "afs", NULL };
 
 static int physmap_flash_probe(struct platform_device *dev)
 {
 	struct physmap_flash_data *physmap_data;
 	struct physmap_flash_info *info;
-	const char **probe_type;
-	const char **part_types;
+	const char * const *probe_type;
+	const char * const *part_types;
 	int err = 0;
 	int i;
 	int devices_found = 0;
diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c
index 363939d..d111097 100644
--- a/drivers/mtd/maps/physmap_of.c
+++ b/drivers/mtd/maps/physmap_of.c
@@ -71,6 +71,9 @@ static int of_flash_remove(struct platform_device *dev)
 	return 0;
 }
 
+static const char * const rom_probe_types[] = {
+	"cfi_probe", "jedec_probe", "map_rom" };
+
 /* Helper function to handle probing of the obsolete "direct-mapped"
  * compatible binding, which has an extra "probe-type" property
  * describing the type of flash probe necessary. */
@@ -80,8 +83,6 @@ static struct mtd_info *obsolete_probe(struct platform_device *dev,
 	struct device_node *dp = dev->dev.of_node;
 	const char *of_probe;
 	struct mtd_info *mtd;
-	static const char *rom_probe_types[]
-		= { "cfi_probe", "jedec_probe", "map_rom"};
 	int i;
 
 	dev_warn(&dev->dev, "Device tree uses obsolete \"direct-mapped\" "
@@ -111,9 +112,10 @@ static struct mtd_info *obsolete_probe(struct platform_device *dev,
    specifies the list of partition probers to use. If none is given then the
    default is use. These take precedence over other device tree
    information. */
-static const char *part_probe_types_def[] = { "cmdlinepart", "RedBoot",
-					"ofpart", "ofoldpart", NULL };
-static const char **of_get_probes(struct device_node *dp)
+static const char * const part_probe_types_def[] = {
+	"cmdlinepart", "RedBoot", "ofpart", "ofoldpart", NULL };
+
+static const char * const *of_get_probes(struct device_node *dp)
 {
 	const char *cp;
 	int cplen;
@@ -142,7 +144,7 @@ static const char **of_get_probes(struct device_node *dp)
 	return res;
 }
 
-static void of_free_probes(const char **probes)
+static void of_free_probes(const char * const *probes)
 {
 	if (probes != part_probe_types_def)
 		kfree(probes);
@@ -151,7 +153,7 @@ static void of_free_probes(const char **probes)
 static struct of_device_id of_flash_match[];
 static int of_flash_probe(struct platform_device *dev)
 {
-	const char **part_probe_types;
+	const char * const *part_probe_types;
 	const struct of_device_id *match;
 	struct device_node *dp = dev->dev.of_node;
 	struct resource res;
diff --git a/drivers/mtd/maps/plat-ram.c b/drivers/mtd/maps/plat-ram.c
index 2de66b0..71fdda2 100644
--- a/drivers/mtd/maps/plat-ram.c
+++ b/drivers/mtd/maps/plat-ram.c
@@ -199,7 +199,7 @@ static int platram_probe(struct platform_device *pdev)
 	 * supplied by the platform_data struct */
 
 	if (pdata->map_probes) {
-		const char **map_probes = pdata->map_probes;
+		const char * const *map_probes = pdata->map_probes;
 
 		for ( ; !info->mtd && *map_probes; map_probes++)
 			info->mtd = do_map_probe(*map_probes , &info->map);
diff --git a/drivers/mtd/maps/pxa2xx-flash.c b/drivers/mtd/maps/pxa2xx-flash.c
index 43e3dbb..acb1dbc 100644
--- a/drivers/mtd/maps/pxa2xx-flash.c
+++ b/drivers/mtd/maps/pxa2xx-flash.c
@@ -45,9 +45,7 @@ struct pxa2xx_flash_info {
 	struct map_info		map;
 };
 
-
-static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
-
+static const char * const probes[] = { "RedBoot", "cmdlinepart", NULL };
 
 static int pxa2xx_flash_probe(struct platform_device *pdev)
 {
diff --git a/drivers/mtd/maps/rbtx4939-flash.c b/drivers/mtd/maps/rbtx4939-flash.c
index 49c3fe7..ac02fbf 100644
--- a/drivers/mtd/maps/rbtx4939-flash.c
+++ b/drivers/mtd/maps/rbtx4939-flash.c
@@ -45,14 +45,15 @@ static int rbtx4939_flash_remove(struct platform_device *dev)
 	return 0;
 }
 
-static const char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL };
+static const char * const rom_probe_types[] = {
+	"cfi_probe", "jedec_probe", NULL };
 
 static int rbtx4939_flash_probe(struct platform_device *dev)
 {
 	struct rbtx4939_flash_data *pdata;
 	struct rbtx4939_flash_info *info;
 	struct resource *res;
-	const char **probe_type;
+	const char * const *probe_type;
 	int err = 0;
 	unsigned long size;
 
diff --git a/drivers/mtd/maps/rpxlite.c b/drivers/mtd/maps/rpxlite.c
deleted file mode 100644
index ed88225..0000000
--- a/drivers/mtd/maps/rpxlite.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Handle mapping of the flash on the RPX Lite and CLLF boards
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <asm/io.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
-
-
-#define WINDOW_ADDR 0xfe000000
-#define WINDOW_SIZE 0x800000
-
-static struct mtd_info *mymtd;
-
-static struct map_info rpxlite_map = {
-	.name = "RPX",
-	.size = WINDOW_SIZE,
-	.bankwidth = 4,
-	.phys = WINDOW_ADDR,
-};
-
-static int __init init_rpxlite(void)
-{
-	printk(KERN_NOTICE "RPX Lite or CLLF flash device: %x at %x\n", WINDOW_SIZE*4, WINDOW_ADDR);
-	rpxlite_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE * 4);
-
-	if (!rpxlite_map.virt) {
-		printk("Failed to ioremap\n");
-		return -EIO;
-	}
-	simple_map_init(&rpxlite_map);
-	mymtd = do_map_probe("cfi_probe", &rpxlite_map);
-	if (mymtd) {
-		mymtd->owner = THIS_MODULE;
-		mtd_device_register(mymtd, NULL, 0);
-		return 0;
-	}
-
-	iounmap((void *)rpxlite_map.virt);
-	return -ENXIO;
-}
-
-static void __exit cleanup_rpxlite(void)
-{
-	if (mymtd) {
-		mtd_device_unregister(mymtd);
-		map_destroy(mymtd);
-	}
-	if (rpxlite_map.virt) {
-		iounmap((void *)rpxlite_map.virt);
-		rpxlite_map.virt = 0;
-	}
-}
-
-module_init(init_rpxlite);
-module_exit(cleanup_rpxlite);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Arnold Christensen <AKC@pel.dk>");
-MODULE_DESCRIPTION("MTD map driver for RPX Lite and CLLF boards");
diff --git a/drivers/mtd/maps/sa1100-flash.c b/drivers/mtd/maps/sa1100-flash.c
index f694417..29e3dca 100644
--- a/drivers/mtd/maps/sa1100-flash.c
+++ b/drivers/mtd/maps/sa1100-flash.c
@@ -244,7 +244,7 @@ static struct sa_info *sa1100_setup_mtd(struct platform_device *pdev,
 	return ERR_PTR(ret);
 }
 
-static const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL };
+static const char * const part_probes[] = { "cmdlinepart", "RedBoot", NULL };
 
 static int sa1100_mtd_probe(struct platform_device *pdev)
 {
diff --git a/drivers/mtd/maps/solutionengine.c b/drivers/mtd/maps/solutionengine.c
index 9d900ad..83a7a70 100644
--- a/drivers/mtd/maps/solutionengine.c
+++ b/drivers/mtd/maps/solutionengine.c
@@ -31,7 +31,7 @@ struct map_info soleng_flash_map = {
 	.bankwidth = 4,
 };
 
-static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
+static const char * const probes[] = { "RedBoot", "cmdlinepart", NULL };
 
 #ifdef CONFIG_MTD_SUPERH_RESERVE
 static struct mtd_partition superh_se_partitions[] = {
diff --git a/drivers/mtd/maps/tqm8xxl.c b/drivers/mtd/maps/tqm8xxl.c
deleted file mode 100644
index d785879..0000000
--- a/drivers/mtd/maps/tqm8xxl.c
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- * Handle mapping of the flash memory access routines
- * on TQM8xxL based devices.
- *
- * based on rpxlite.c
- *
- * Copyright(C) 2001 Kirk Lee <kirk@hpc.ee.ntu.edu.tw>
- *
- * This code is GPLed
- *
- */
-
-/*
- * According to TQM8xxL hardware manual, TQM8xxL series have
- * following flash memory organisations:
- *	| capacity |	| chip type |	| bank0 |	| bank1 |
- *	    2MiB	   512Kx16	  2MiB		   0
- *	    4MiB	   1Mx16	  4MiB		   0
- *	    8MiB	   1Mx16	  4MiB		   4MiB
- * Thus, we choose CONFIG_MTD_CFI_I2 & CONFIG_MTD_CFI_B4 at
- * kernel configuration.
- */
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
-#include <linux/mtd/partitions.h>
-
-#include <asm/io.h>
-
-#define FLASH_ADDR 0x40000000
-#define FLASH_SIZE 0x00800000
-#define FLASH_BANK_MAX 4
-
-// trivial struct to describe partition information
-struct mtd_part_def
-{
-	int nums;
-	unsigned char *type;
-	struct mtd_partition* mtd_part;
-};
-
-//static struct mtd_info *mymtd;
-static struct mtd_info* mtd_banks[FLASH_BANK_MAX];
-static struct map_info* map_banks[FLASH_BANK_MAX];
-static struct mtd_part_def part_banks[FLASH_BANK_MAX];
-static unsigned long num_banks;
-static void __iomem *start_scan_addr;
-
-/*
- * Here are partition information for all known TQM8xxL series devices.
- * See include/linux/mtd/partitions.h for definition of the mtd_partition
- * structure.
- *
- * The *_max_flash_size is the maximum possible mapped flash size which
- * is not necessarily the actual flash size.  It must correspond to the
- * value specified in the mapping definition defined by the
- * "struct map_desc *_io_desc" for the corresponding machine.
- */
-
-/* Currently, TQM8xxL has up to 8MiB flash */
-static unsigned long tqm8xxl_max_flash_size = 0x00800000;
-
-/* partition definition for first flash bank
- * (cf. "drivers/char/flash_config.c")
- */
-static struct mtd_partition tqm8xxl_partitions[] = {
-	{
-	  .name = "ppcboot",
-	  .offset = 0x00000000,
-	  .size = 0x00020000,           /* 128KB           */
-	  .mask_flags = MTD_WRITEABLE,  /* force read-only */
-	},
-	{
-	  .name = "kernel",             /* default kernel image */
-	  .offset = 0x00020000,
-	  .size = 0x000e0000,
-	  .mask_flags = MTD_WRITEABLE,  /* force read-only */
-	},
-	{
-	  .name = "user",
-	  .offset = 0x00100000,
-	  .size = 0x00100000,
-	},
-	{
-	  .name = "initrd",
-	  .offset = 0x00200000,
-	  .size = 0x00200000,
-	}
-};
-/* partition definition for second flash bank */
-static struct mtd_partition tqm8xxl_fs_partitions[] = {
-	{
-	  .name = "cramfs",
-	  .offset = 0x00000000,
-	  .size = 0x00200000,
-	},
-	{
-	  .name = "jffs",
-	  .offset = 0x00200000,
-	  .size = 0x00200000,
-	  //.size = MTDPART_SIZ_FULL,
-	}
-};
-
-static int __init init_tqm_mtd(void)
-{
-	int idx = 0, ret = 0;
-	unsigned long flash_addr, flash_size, mtd_size = 0;
-	/* pointer to TQM8xxL board info data */
-	bd_t *bd = (bd_t *)__res;
-
-	flash_addr = bd->bi_flashstart;
-	flash_size = bd->bi_flashsize;
-
-	//request maximum flash size address space
-	start_scan_addr = ioremap(flash_addr, flash_size);
-	if (!start_scan_addr) {
-		printk(KERN_WARNING "%s:Failed to ioremap address:0x%x\n", __func__, flash_addr);
-		return -EIO;
-	}
-
-	for (idx = 0 ; idx < FLASH_BANK_MAX ; idx++) {
-		if(mtd_size >= flash_size)
-			break;
-
-		printk(KERN_INFO "%s: chip probing count %d\n", __func__, idx);
-
-		map_banks[idx] = kzalloc(sizeof(struct map_info), GFP_KERNEL);
-		if(map_banks[idx] == NULL) {
-			ret = -ENOMEM;
-			/* FIXME: What if some MTD devices were probed already? */
-			goto error_mem;
-		}
-
-		map_banks[idx]->name = kmalloc(16, GFP_KERNEL);
-
-		if (!map_banks[idx]->name) {
-			ret = -ENOMEM;
-			/* FIXME: What if some MTD devices were probed already? */
-			goto error_mem;
-		}
-		sprintf(map_banks[idx]->name, "TQM8xxL%d", idx);
-
-		map_banks[idx]->size = flash_size;
-		map_banks[idx]->bankwidth = 4;
-
-		simple_map_init(map_banks[idx]);
-
-		map_banks[idx]->virt = start_scan_addr;
-		map_banks[idx]->phys = flash_addr;
-		/* FIXME: This looks utterly bogus, but I'm trying to
-		   preserve the behaviour of the original (shown here)...
-
-		map_banks[idx]->map_priv_1 =
-		start_scan_addr + ((idx > 0) ?
-		(mtd_banks[idx-1] ? mtd_banks[idx-1]->size : 0) : 0);
-		*/
-
-		if (idx && mtd_banks[idx-1]) {
-			map_banks[idx]->virt += mtd_banks[idx-1]->size;
-			map_banks[idx]->phys += mtd_banks[idx-1]->size;
-		}
-
-		//start to probe flash chips
-		mtd_banks[idx] = do_map_probe("cfi_probe", map_banks[idx]);
-
-		if (mtd_banks[idx]) {
-			mtd_banks[idx]->owner = THIS_MODULE;
-			mtd_size += mtd_banks[idx]->size;
-			num_banks++;
-
-			printk(KERN_INFO "%s: bank%d, name:%s, size:%dbytes \n", __func__, num_banks,
-			mtd_banks[idx]->name, mtd_banks[idx]->size);
-		}
-	}
-
-	/* no supported flash chips found */
-	if (!num_banks) {
-		printk(KERN_NOTICE "TQM8xxL: No support flash chips found!\n");
-		ret = -ENXIO;
-		goto error_mem;
-	}
-
-	/*
-	 * Select Static partition definitions
-	 */
-	part_banks[0].mtd_part = tqm8xxl_partitions;
-	part_banks[0].type = "Static image";
-	part_banks[0].nums = ARRAY_SIZE(tqm8xxl_partitions);
-
-	part_banks[1].mtd_part = tqm8xxl_fs_partitions;
-	part_banks[1].type = "Static file system";
-	part_banks[1].nums = ARRAY_SIZE(tqm8xxl_fs_partitions);
-
-	for(idx = 0; idx < num_banks ; idx++) {
-		if (part_banks[idx].nums == 0)
-			printk(KERN_NOTICE "TQM flash%d: no partition info available, registering whole flash at once\n", idx);
-		else
-			printk(KERN_NOTICE "TQM flash%d: Using %s partition definition\n",
-					idx, part_banks[idx].type);
-		mtd_device_register(mtd_banks[idx], part_banks[idx].mtd_part,
-		part_banks[idx].nums);
-	}
-	return 0;
-error_mem:
-	for(idx = 0 ; idx < FLASH_BANK_MAX ; idx++) {
-		if(map_banks[idx] != NULL) {
-			kfree(map_banks[idx]->name);
-			map_banks[idx]->name = NULL;
-			kfree(map_banks[idx]);
-			map_banks[idx] = NULL;
-		}
-	}
-error:
-	iounmap(start_scan_addr);
-	return ret;
-}
-
-static void __exit cleanup_tqm_mtd(void)
-{
-	unsigned int idx = 0;
-	for(idx = 0 ; idx < num_banks ; idx++) {
-		/* destroy mtd_info previously allocated */
-		if (mtd_banks[idx]) {
-			mtd_device_unregister(mtd_banks[idx]);
-			map_destroy(mtd_banks[idx]);
-		}
-		/* release map_info not used anymore */
-		kfree(map_banks[idx]->name);
-		kfree(map_banks[idx]);
-	}
-
-	if (start_scan_addr) {
-		iounmap(start_scan_addr);
-		start_scan_addr = 0;
-	}
-}
-
-module_init(init_tqm_mtd);
-module_exit(cleanup_tqm_mtd);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Kirk Lee <kirk@hpc.ee.ntu.edu.tw>");
-MODULE_DESCRIPTION("MTD map driver for TQM8xxL boards");
diff --git a/drivers/mtd/maps/tsunami_flash.c b/drivers/mtd/maps/tsunami_flash.c
index 1de390e..da2cdb5 100644
--- a/drivers/mtd/maps/tsunami_flash.c
+++ b/drivers/mtd/maps/tsunami_flash.c
@@ -82,11 +82,12 @@ static void __exit  cleanup_tsunami_flash(void)
 	tsunami_flash_mtd = 0;
 }
 
+static const char * const rom_probe_types[] = {
+	"cfi_probe", "jedec_probe", "map_rom", NULL };
 
 static int __init init_tsunami_flash(void)
 {
-	static const char *rom_probe_types[] = { "cfi_probe", "jedec_probe", "map_rom", NULL };
-	char **type;
+	const char * const *type;
 
 	tsunami_tig_writeb(FLASH_ENABLE_BYTE, FLASH_ENABLE_PORT);
 
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index 92ab30a..e0e59bf 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -38,6 +38,8 @@
 
 #include <asm/uaccess.h>
 
+#include "mtdcore.h"
+
 static DEFINE_MUTEX(mtd_mutex);
 
 /*
@@ -365,37 +367,35 @@ static void mtdchar_erase_callback (struct erase_info *instr)
 	wake_up((wait_queue_head_t *)instr->priv);
 }
 
-#ifdef CONFIG_HAVE_MTD_OTP
 static int otp_select_filemode(struct mtd_file_info *mfi, int mode)
 {
 	struct mtd_info *mtd = mfi->mtd;
 	size_t retlen;
-	int ret = 0;
-
-	/*
-	 * Make a fake call to mtd_read_fact_prot_reg() to check if OTP
-	 * operations are supported.
-	 */
-	if (mtd_read_fact_prot_reg(mtd, -1, 0, &retlen, NULL) == -EOPNOTSUPP)
-		return -EOPNOTSUPP;
 
 	switch (mode) {
 	case MTD_OTP_FACTORY:
+		if (mtd_read_fact_prot_reg(mtd, -1, 0, &retlen, NULL) ==
+				-EOPNOTSUPP)
+			return -EOPNOTSUPP;
+
 		mfi->mode = MTD_FILE_MODE_OTP_FACTORY;
 		break;
 	case MTD_OTP_USER:
+		if (mtd_read_user_prot_reg(mtd, -1, 0, &retlen, NULL) ==
+				-EOPNOTSUPP)
+			return -EOPNOTSUPP;
+
 		mfi->mode = MTD_FILE_MODE_OTP_USER;
 		break;
-	default:
-		ret = -EINVAL;
 	case MTD_OTP_OFF:
+		mfi->mode = MTD_FILE_MODE_NORMAL;
 		break;
+	default:
+		return -EINVAL;
 	}
-	return ret;
+
+	return 0;
 }
-#else
-# define otp_select_filemode(f,m)	-EOPNOTSUPP
-#endif
 
 static int mtdchar_writeoob(struct file *file, struct mtd_info *mtd,
 	uint64_t start, uint32_t length, void __user *ptr,
@@ -888,7 +888,6 @@ static int mtdchar_ioctl(struct file *file, u_int cmd, u_long arg)
 		break;
 	}
 
-#ifdef CONFIG_HAVE_MTD_OTP
 	case OTPSELECT:
 	{
 		int mode;
@@ -944,7 +943,6 @@ static int mtdchar_ioctl(struct file *file, u_int cmd, u_long arg)
 		ret = mtd_lock_user_prot_reg(mtd, oinfo.start, oinfo.length);
 		break;
 	}
-#endif
 
 	/* This ioctl is being deprecated - it truncates the ECC layout */
 	case ECCGETLAYOUT:
@@ -1240,23 +1238,25 @@ static struct file_system_type mtd_inodefs_type = {
 };
 MODULE_ALIAS_FS("mtd_inodefs");
 
-static int __init init_mtdchar(void)
+int __init init_mtdchar(void)
 {
 	int ret;
 
 	ret = __register_chrdev(MTD_CHAR_MAJOR, 0, 1 << MINORBITS,
 				   "mtd", &mtd_fops);
 	if (ret < 0) {
-		pr_notice("Can't allocate major number %d for "
-				"Memory Technology Devices.\n", MTD_CHAR_MAJOR);
+		pr_err("Can't allocate major number %d for MTD\n",
+		       MTD_CHAR_MAJOR);
 		return ret;
 	}
 
 	ret = register_filesystem(&mtd_inodefs_type);
 	if (ret) {
-		pr_notice("Can't register mtd_inodefs filesystem: %d\n", ret);
+		pr_err("Can't register mtd_inodefs filesystem, error %d\n",
+		       ret);
 		goto err_unregister_chdev;
 	}
+
 	return ret;
 
 err_unregister_chdev:
@@ -1264,18 +1264,10 @@ err_unregister_chdev:
 	return ret;
 }
 
-static void __exit cleanup_mtdchar(void)
+void __exit cleanup_mtdchar(void)
 {
 	unregister_filesystem(&mtd_inodefs_type);
 	__unregister_chrdev(MTD_CHAR_MAJOR, 0, 1 << MINORBITS, "mtd");
 }
 
-module_init(init_mtdchar);
-module_exit(cleanup_mtdchar);
-
-MODULE_ALIAS_CHARDEV_MAJOR(MTD_CHAR_MAJOR);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
-MODULE_DESCRIPTION("Direct character-device access to MTD devices");
 MODULE_ALIAS_CHARDEV_MAJOR(MTD_CHAR_MAJOR);
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index 61d5f56..71877ff 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -41,6 +41,7 @@
 #include <linux/mtd/partitions.h>
 
 #include "mtdcore.h"
+
 /*
  * backing device capabilities for non-mappable devices (such as NAND flash)
  * - permits private mappings, copies are taken of the data
@@ -96,11 +97,7 @@ EXPORT_SYMBOL_GPL(__mtd_next_device);
 static LIST_HEAD(mtd_notifiers);
 
 
-#if defined(CONFIG_MTD_CHAR) || defined(CONFIG_MTD_CHAR_MODULE)
 #define MTD_DEVT(index) MKDEV(MTD_CHAR_MAJOR, (index)*2)
-#else
-#define MTD_DEVT(index) 0
-#endif
 
 /* REVISIT once MTD uses the driver model better, whoever allocates
  * the mtd_info will probably want to use the release() hook...
@@ -492,7 +489,7 @@ out_error:
  *
  * Returns zero in case of success and a negative error code in case of failure.
  */
-int mtd_device_parse_register(struct mtd_info *mtd, const char **types,
+int mtd_device_parse_register(struct mtd_info *mtd, const char * const *types,
 			      struct mtd_part_parser_data *parser_data,
 			      const struct mtd_partition *parts,
 			      int nr_parts)
@@ -1116,8 +1113,6 @@ EXPORT_SYMBOL_GPL(mtd_kmalloc_up_to);
 /*====================================================================*/
 /* Support for /proc/mtd */
 
-static struct proc_dir_entry *proc_mtd;
-
 static int mtd_proc_show(struct seq_file *m, void *v)
 {
 	struct mtd_info *mtd;
@@ -1163,6 +1158,8 @@ static int __init mtd_bdi_init(struct backing_dev_info *bdi, const char *name)
 	return ret;
 }
 
+static struct proc_dir_entry *proc_mtd;
+
 static int __init init_mtd(void)
 {
 	int ret;
@@ -1183,11 +1180,17 @@ static int __init init_mtd(void)
 	if (ret)
 		goto err_bdi3;
 
-#ifdef CONFIG_PROC_FS
 	proc_mtd = proc_create("mtd", 0, NULL, &mtd_proc_ops);
-#endif /* CONFIG_PROC_FS */
+
+	ret = init_mtdchar();
+	if (ret)
+		goto out_procfs;
+
 	return 0;
 
+out_procfs:
+	if (proc_mtd)
+		remove_proc_entry("mtd", NULL);
 err_bdi3:
 	bdi_destroy(&mtd_bdi_ro_mappable);
 err_bdi2:
@@ -1201,10 +1204,9 @@ err_reg:
 
 static void __exit cleanup_mtd(void)
 {
-#ifdef CONFIG_PROC_FS
+	cleanup_mtdchar();
 	if (proc_mtd)
-		remove_proc_entry( "mtd", NULL);
-#endif /* CONFIG_PROC_FS */
+		remove_proc_entry("mtd", NULL);
 	class_unregister(&mtd_class);
 	bdi_destroy(&mtd_bdi_unmappable);
 	bdi_destroy(&mtd_bdi_ro_mappable);
diff --git a/drivers/mtd/mtdcore.h b/drivers/mtd/mtdcore.h
index 961a384..7b03533 100644
--- a/drivers/mtd/mtdcore.h
+++ b/drivers/mtd/mtdcore.h
@@ -1,23 +1,21 @@
-/* linux/drivers/mtd/mtdcore.h
- *
- * Header file for driver private mtdcore exports
- *
+/*
+ * These are exported solely for the purpose of mtd_blkdevs.c and mtdchar.c.
+ * You should not use them for _anything_ else.
  */
 
-/* These are exported solely for the purpose of mtd_blkdevs.c. You
-   should not use them for _anything_ else */
-
 extern struct mutex mtd_table_mutex;
-extern struct mtd_info *__mtd_next_device(int i);
 
-extern int add_mtd_device(struct mtd_info *mtd);
-extern int del_mtd_device(struct mtd_info *mtd);
-extern int add_mtd_partitions(struct mtd_info *, const struct mtd_partition *,
-			      int);
-extern int del_mtd_partitions(struct mtd_info *);
-extern int parse_mtd_partitions(struct mtd_info *master, const char **types,
-				struct mtd_partition **pparts,
-				struct mtd_part_parser_data *data);
+struct mtd_info *__mtd_next_device(int i);
+int add_mtd_device(struct mtd_info *mtd);
+int del_mtd_device(struct mtd_info *mtd);
+int add_mtd_partitions(struct mtd_info *, const struct mtd_partition *, int);
+int del_mtd_partitions(struct mtd_info *);
+int parse_mtd_partitions(struct mtd_info *master, const char * const *types,
+			 struct mtd_partition **pparts,
+			 struct mtd_part_parser_data *data);
+
+int __init init_mtdchar(void);
+void __exit cleanup_mtdchar(void);
 
 #define mtd_for_each_device(mtd)			\
 	for ((mtd) = __mtd_next_device(0);		\
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index 70fa70a..3014933 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -694,7 +694,7 @@ EXPORT_SYMBOL_GPL(deregister_mtd_parser);
  * Do not forget to update 'parse_mtd_partitions()' kerneldoc comment if you
  * are changing this array!
  */
-static const char *default_mtd_part_types[] = {
+static const char * const default_mtd_part_types[] = {
 	"cmdlinepart",
 	"ofpart",
 	NULL
@@ -720,7 +720,7 @@ static const char *default_mtd_part_types[] = {
  * o a positive number of found partitions, in which case on exit @pparts will
  *   point to an array containing this number of &struct mtd_info objects.
  */
-int parse_mtd_partitions(struct mtd_info *master, const char **types,
+int parse_mtd_partitions(struct mtd_info *master, const char *const *types,
 			 struct mtd_partition **pparts,
 			 struct mtd_part_parser_data *data)
 {
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 81bf5e5..1cca712 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -41,14 +41,6 @@ config MTD_SM_COMMON
 	tristate
 	default n
 
-config MTD_NAND_MUSEUM_IDS
-	bool "Enable chip ids for obsolete ancient NAND devices"
-	default n
-	help
-	  Enable this option only when your board has first generation
-	  NAND chips (page size 256 byte, erase size 4-8KiB). The IDs
-	  of these chips were reused by later, larger chips.
-
 config MTD_NAND_DENALI
         tristate "Support Denali NAND controller"
         help
@@ -81,12 +73,6 @@ config MTD_NAND_DENALI_SCRATCH_REG_ADDR
           scratch register here to enable this feature. On Intel Moorestown
           boards, the scratch register is at 0xFF108018.
 
-config MTD_NAND_H1900
-	tristate "iPAQ H1900 flash"
-	depends on ARCH_PXA && BROKEN
-	help
-	  This enables the driver for the iPAQ h1900 flash.
-
 config MTD_NAND_GPIO
 	tristate "GPIO NAND Flash driver"
 	depends on GENERIC_GPIO && ARM
@@ -201,22 +187,6 @@ config MTD_NAND_BF5XX_BOOTROM_ECC
 
 	  If unsure, say N.
 
-config MTD_NAND_RTC_FROM4
-	tristate "Renesas Flash ROM 4-slot interface board (FROM_BOARD4)"
-	depends on SH_SOLUTION_ENGINE
-	select REED_SOLOMON
-	select REED_SOLOMON_DEC8
-	select BITREVERSE
-	help
-	  This enables the driver for the Renesas Technology AG-AND
-	  flash interface board (FROM_BOARD4)
-
-config MTD_NAND_PPCHAMELEONEVB
-	tristate "NAND Flash device on PPChameleonEVB board"
-	depends on PPCHAMELEONEVB && BROKEN
-	help
-	  This enables the NAND flash driver on the PPChameleon EVB Board.
-
 config MTD_NAND_S3C2410
 	tristate "NAND Flash support for Samsung S3C SoCs"
 	depends on ARCH_S3C24XX || ARCH_S3C64XX
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index d76d912..bb81891 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -15,14 +15,11 @@ obj-$(CONFIG_MTD_NAND_DENALI_PCI)	+= denali_pci.o
 obj-$(CONFIG_MTD_NAND_DENALI_DT)	+= denali_dt.o
 obj-$(CONFIG_MTD_NAND_AU1550)		+= au1550nd.o
 obj-$(CONFIG_MTD_NAND_BF5XX)		+= bf5xx_nand.o
-obj-$(CONFIG_MTD_NAND_PPCHAMELEONEVB)	+= ppchameleonevb.o
 obj-$(CONFIG_MTD_NAND_S3C2410)		+= s3c2410.o
 obj-$(CONFIG_MTD_NAND_DAVINCI)		+= davinci_nand.o
 obj-$(CONFIG_MTD_NAND_DISKONCHIP)	+= diskonchip.o
 obj-$(CONFIG_MTD_NAND_DOCG4)		+= docg4.o
 obj-$(CONFIG_MTD_NAND_FSMC)		+= fsmc_nand.o
-obj-$(CONFIG_MTD_NAND_H1900)		+= h1910.o
-obj-$(CONFIG_MTD_NAND_RTC_FROM4)	+= rtc_from4.o
 obj-$(CONFIG_MTD_NAND_SHARPSL)		+= sharpsl.o
 obj-$(CONFIG_MTD_NAND_NANDSIM)		+= nandsim.o
 obj-$(CONFIG_MTD_NAND_CS553X)		+= cs553x_nand.o
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
index ffcbcca..2d23d29 100644
--- a/drivers/mtd/nand/atmel_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -1737,20 +1737,7 @@ static struct platform_driver atmel_nand_driver = {
 	},
 };
 
-static int __init atmel_nand_init(void)
-{
-	return platform_driver_probe(&atmel_nand_driver, atmel_nand_probe);
-}
-
-
-static void __exit atmel_nand_exit(void)
-{
-	platform_driver_unregister(&atmel_nand_driver);
-}
-
-
-module_init(atmel_nand_init);
-module_exit(atmel_nand_exit);
+module_platform_driver_probe(atmel_nand_driver, atmel_nand_probe);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Rick Bronson");
diff --git a/drivers/mtd/nand/cafe_nand.c b/drivers/mtd/nand/cafe_nand.c
index 010d612..a01ccb9 100644
--- a/drivers/mtd/nand/cafe_nand.c
+++ b/drivers/mtd/nand/cafe_nand.c
@@ -303,13 +303,7 @@ static void cafe_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
 	case NAND_CMD_SEQIN:
 	case NAND_CMD_RNDIN:
 	case NAND_CMD_STATUS:
-	case NAND_CMD_DEPLETE1:
 	case NAND_CMD_RNDOUT:
-	case NAND_CMD_STATUS_ERROR:
-	case NAND_CMD_STATUS_ERROR0:
-	case NAND_CMD_STATUS_ERROR1:
-	case NAND_CMD_STATUS_ERROR2:
-	case NAND_CMD_STATUS_ERROR3:
 		cafe_writel(cafe, cafe->ctl2, NAND_CTRL2);
 		return;
 	}
diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c
index 94e17af..c3e15a5 100644
--- a/drivers/mtd/nand/davinci_nand.c
+++ b/drivers/mtd/nand/davinci_nand.c
@@ -34,6 +34,7 @@
 #include <linux/mtd/partitions.h>
 #include <linux/slab.h>
 #include <linux/of_device.h>
+#include <linux/of.h>
 
 #include <linux/platform_data/mtd-davinci.h>
 #include <linux/platform_data/mtd-davinci-aemif.h>
@@ -577,7 +578,6 @@ static struct davinci_nand_pdata
 	return pdev->dev.platform_data;
 }
 #else
-#define davinci_nand_of_match NULL
 static struct davinci_nand_pdata
 	*nand_davinci_get_pdata(struct platform_device *pdev)
 {
@@ -878,22 +878,12 @@ static struct platform_driver nand_davinci_driver = {
 	.driver		= {
 		.name	= "davinci_nand",
 		.owner	= THIS_MODULE,
-		.of_match_table = davinci_nand_of_match,
+		.of_match_table = of_match_ptr(davinci_nand_of_match),
 	},
 };
 MODULE_ALIAS("platform:davinci_nand");
 
-static int __init nand_davinci_init(void)
-{
-	return platform_driver_probe(&nand_davinci_driver, nand_davinci_probe);
-}
-module_init(nand_davinci_init);
-
-static void __exit nand_davinci_exit(void)
-{
-	platform_driver_unregister(&nand_davinci_driver);
-}
-module_exit(nand_davinci_exit);
+module_platform_driver_probe(nand_davinci_driver, nand_davinci_probe);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Texas Instruments");
diff --git a/drivers/mtd/nand/docg4.c b/drivers/mtd/nand/docg4.c
index 18fa448..fa25e7a 100644
--- a/drivers/mtd/nand/docg4.c
+++ b/drivers/mtd/nand/docg4.c
@@ -1397,18 +1397,7 @@ static struct platform_driver docg4_driver = {
 	.remove		= __exit_p(cleanup_docg4),
 };
 
-static int __init docg4_init(void)
-{
-	return platform_driver_probe(&docg4_driver, probe_docg4);
-}
-
-static void __exit docg4_exit(void)
-{
-	platform_driver_unregister(&docg4_driver);
-}
-
-module_init(docg4_init);
-module_exit(docg4_exit);
+module_platform_driver_probe(docg4_driver, probe_docg4);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Mike Dunn");
diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c
index 05ba3f0..911e243 100644
--- a/drivers/mtd/nand/fsmc_nand.c
+++ b/drivers/mtd/nand/fsmc_nand.c
@@ -1235,18 +1235,7 @@ static struct platform_driver fsmc_nand_driver = {
 	},
 };
 
-static int __init fsmc_nand_init(void)
-{
-	return platform_driver_probe(&fsmc_nand_driver,
-				     fsmc_nand_probe);
-}
-module_init(fsmc_nand_init);
-
-static void __exit fsmc_nand_exit(void)
-{
-	platform_driver_unregister(&fsmc_nand_driver);
-}
-module_exit(fsmc_nand_exit);
+module_platform_driver_probe(fsmc_nand_driver, fsmc_nand_probe);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Vipin Kumar <vipin.kumar@st.com>, Ashish Priyadarshi");
diff --git a/drivers/mtd/nand/gpio.c b/drivers/mtd/nand/gpio.c
index e789e3f..89065dd 100644
--- a/drivers/mtd/nand/gpio.c
+++ b/drivers/mtd/nand/gpio.c
@@ -190,7 +190,6 @@ static struct resource *gpio_nand_get_io_sync_of(struct platform_device *pdev)
 	return r;
 }
 #else /* CONFIG_OF */
-#define gpio_nand_id_table NULL
 static inline int gpio_nand_get_config_of(const struct device *dev,
 					  struct gpio_nand_platdata *plat)
 {
@@ -259,8 +258,6 @@ static int gpio_nand_remove(struct platform_device *dev)
 	if (gpio_is_valid(gpiomtd->plat.gpio_rdy))
 		gpio_free(gpiomtd->plat.gpio_rdy);
 
-	kfree(gpiomtd);
-
 	return 0;
 }
 
@@ -297,7 +294,7 @@ static int gpio_nand_probe(struct platform_device *dev)
 	if (!res0)
 		return -EINVAL;
 
-	gpiomtd = kzalloc(sizeof(*gpiomtd), GFP_KERNEL);
+	gpiomtd = devm_kzalloc(&dev->dev, sizeof(*gpiomtd), GFP_KERNEL);
 	if (gpiomtd == NULL) {
 		dev_err(&dev->dev, "failed to create NAND MTD\n");
 		return -ENOMEM;
@@ -412,7 +409,6 @@ err_sync:
 	iounmap(gpiomtd->nand_chip.IO_ADDR_R);
 	release_mem_region(res0->start, resource_size(res0));
 err_map:
-	kfree(gpiomtd);
 	return ret;
 }
 
@@ -421,7 +417,7 @@ static struct platform_driver gpio_nand_driver = {
 	.remove		= gpio_nand_remove,
 	.driver		= {
 		.name	= "gpio-nand",
-		.of_match_table = gpio_nand_id_table,
+		.of_match_table = of_match_ptr(gpio_nand_id_table),
 	},
 };
 
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
index 717881a..25ecfa1 100644
--- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
+++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
@@ -36,7 +36,6 @@
 #define GPMI_NAND_GPMI_REGS_ADDR_RES_NAME  "gpmi-nand"
 #define GPMI_NAND_BCH_REGS_ADDR_RES_NAME   "bch"
 #define GPMI_NAND_BCH_INTERRUPT_RES_NAME   "bch"
-#define GPMI_NAND_DMA_INTERRUPT_RES_NAME   "gpmi-dma"
 
 /* add our owner bbt descriptor */
 static uint8_t scan_ff_pattern[] = { 0xff };
@@ -420,28 +419,6 @@ static void release_bch_irq(struct gpmi_nand_data *this)
 		free_irq(i, this);
 }
 
-static bool gpmi_dma_filter(struct dma_chan *chan, void *param)
-{
-	struct gpmi_nand_data *this = param;
-	int dma_channel = (int)this->private;
-
-	if (!mxs_dma_is_apbh(chan))
-		return false;
-	/*
-	 * only catch the GPMI dma channels :
-	 *	for mx23 :	MX23_DMA_GPMI0 ~ MX23_DMA_GPMI3
-	 *		(These four channels share the same IRQ!)
-	 *
-	 *	for mx28 :	MX28_DMA_GPMI0 ~ MX28_DMA_GPMI7
-	 *		(These eight channels share the same IRQ!)
-	 */
-	if (dma_channel == chan->chan_id) {
-		chan->private = &this->dma_data;
-		return true;
-	}
-	return false;
-}
-
 static void release_dma_channels(struct gpmi_nand_data *this)
 {
 	unsigned int i;
@@ -455,36 +432,10 @@ static void release_dma_channels(struct gpmi_nand_data *this)
 static int acquire_dma_channels(struct gpmi_nand_data *this)
 {
 	struct platform_device *pdev = this->pdev;
-	struct resource *r_dma;
-	struct device_node *dn;
-	u32 dma_channel;
-	int ret;
 	struct dma_chan *dma_chan;
-	dma_cap_mask_t mask;
-
-	/* dma channel, we only use the first one. */
-	dn = pdev->dev.of_node;
-	ret = of_property_read_u32(dn, "fsl,gpmi-dma-channel", &dma_channel);
-	if (ret) {
-		pr_err("unable to get DMA channel from dt.\n");
-		goto acquire_err;
-	}
-	this->private = (void *)dma_channel;
-
-	/* gpmi dma interrupt */
-	r_dma = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
-					GPMI_NAND_DMA_INTERRUPT_RES_NAME);
-	if (!r_dma) {
-		pr_err("Can't get resource for DMA\n");
-		goto acquire_err;
-	}
-	this->dma_data.chan_irq = r_dma->start;
 
 	/* request dma channel */
-	dma_cap_zero(mask);
-	dma_cap_set(DMA_SLAVE, mask);
-
-	dma_chan = dma_request_channel(mask, gpmi_dma_filter, this);
+	dma_chan = dma_request_slave_channel(&pdev->dev, "rx-tx");
 	if (!dma_chan) {
 		pr_err("Failed to request DMA channel.\n");
 		goto acquire_err;
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.h b/drivers/mtd/nand/gpmi-nand/gpmi-nand.h
index 0729477..a7685e3 100644
--- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.h
+++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.h
@@ -20,7 +20,7 @@
 #include <linux/mtd/nand.h>
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
-#include <linux/fsl/mxs-dma.h>
+#include <linux/dmaengine.h>
 
 #define GPMI_CLK_MAX 5 /* MX6Q needs five clocks */
 struct resources {
@@ -180,7 +180,6 @@ struct gpmi_nand_data {
 	/* DMA channels */
 #define DMA_CHANS		8
 	struct dma_chan		*dma_chans[DMA_CHANS];
-	struct mxs_dma_data	dma_data;
 	enum dma_ops_type	last_dma_type;
 	enum dma_ops_type	dma_type;
 	struct completion	dma_done;
diff --git a/drivers/mtd/nand/h1910.c b/drivers/mtd/nand/h1910.c
deleted file mode 100644
index 50166e9..0000000
--- a/drivers/mtd/nand/h1910.c
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- *  drivers/mtd/nand/h1910.c
- *
- *  Copyright (C) 2003 Joshua Wise (joshua@joshuawise.com)
- *
- *  Derived from drivers/mtd/nand/edb7312.c
- *       Copyright (C) 2002 Marius Gröger (mag@sysgo.de)
- *       Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.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.
- *
- *  Overview:
- *   This is a device driver for the NAND flash device found on the
- *   iPAQ h1910 board which utilizes the Samsung K9F2808 part. This is
- *   a 128Mibit (16MiB x 8 bits) NAND flash device.
- */
-
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
-#include <linux/mtd/partitions.h>
-#include <asm/io.h>
-#include <mach/hardware.h>
-#include <asm/sizes.h>
-#include <mach/h1900-gpio.h>
-#include <mach/ipaq.h>
-
-/*
- * MTD structure for EDB7312 board
- */
-static struct mtd_info *h1910_nand_mtd = NULL;
-
-/*
- * Module stuff
- */
-
-/*
- * Define static partitions for flash device
- */
-static struct mtd_partition partition_info[] = {
-      {name:"h1910 NAND Flash",
-	      offset:0,
-      size:16 * 1024 * 1024}
-};
-
-#define NUM_PARTITIONS 1
-
-/*
- *	hardware specific access to control-lines
- *
- *	NAND_NCE: bit 0 - don't care
- *	NAND_CLE: bit 1 - address bit 2
- *	NAND_ALE: bit 2 - address bit 3
- */
-static void h1910_hwcontrol(struct mtd_info *mtd, int cmd,
-			    unsigned int ctrl)
-{
-	struct nand_chip *chip = mtd->priv;
-
-	if (cmd != NAND_CMD_NONE)
-		writeb(cmd, chip->IO_ADDR_W | ((ctrl & 0x6) << 1));
-}
-
-/*
- *	read device ready pin
- */
-#if 0
-static int h1910_device_ready(struct mtd_info *mtd)
-{
-	return (GPLR(55) & GPIO_bit(55));
-}
-#endif
-
-/*
- * Main initialization routine
- */
-static int __init h1910_init(void)
-{
-	struct nand_chip *this;
-	void __iomem *nandaddr;
-
-	if (!machine_is_h1900())
-		return -ENODEV;
-
-	nandaddr = ioremap(0x08000000, 0x1000);
-	if (!nandaddr) {
-		printk("Failed to ioremap nand flash.\n");
-		return -ENOMEM;
-	}
-
-	/* Allocate memory for MTD device structure and private data */
-	h1910_nand_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
-	if (!h1910_nand_mtd) {
-		printk("Unable to allocate h1910 NAND MTD device structure.\n");
-		iounmap((void *)nandaddr);
-		return -ENOMEM;
-	}
-
-	/* Get pointer to private data */
-	this = (struct nand_chip *)(&h1910_nand_mtd[1]);
-
-	/* Initialize structures */
-	memset(h1910_nand_mtd, 0, sizeof(struct mtd_info));
-	memset(this, 0, sizeof(struct nand_chip));
-
-	/* Link the private data with the MTD structure */
-	h1910_nand_mtd->priv = this;
-	h1910_nand_mtd->owner = THIS_MODULE;
-
-	/*
-	 * Enable VPEN
-	 */
-	GPSR(37) = GPIO_bit(37);
-
-	/* insert callbacks */
-	this->IO_ADDR_R = nandaddr;
-	this->IO_ADDR_W = nandaddr;
-	this->cmd_ctrl = h1910_hwcontrol;
-	this->dev_ready = NULL;	/* unknown whether that was correct or not so we will just do it like this */
-	/* 15 us command delay time */
-	this->chip_delay = 50;
-	this->ecc.mode = NAND_ECC_SOFT;
-
-	/* Scan to find existence of the device */
-	if (nand_scan(h1910_nand_mtd, 1)) {
-		printk(KERN_NOTICE "No NAND device - returning -ENXIO\n");
-		kfree(h1910_nand_mtd);
-		iounmap((void *)nandaddr);
-		return -ENXIO;
-	}
-
-	/* Register the partitions */
-	mtd_device_parse_register(h1910_nand_mtd, NULL, NULL, partition_info,
-				  NUM_PARTITIONS);
-
-	/* Return happy */
-	return 0;
-}
-
-module_init(h1910_init);
-
-/*
- * Clean up routine
- */
-static void __exit h1910_cleanup(void)
-{
-	struct nand_chip *this = (struct nand_chip *)&h1910_nand_mtd[1];
-
-	/* Release resources, unregister device */
-	nand_release(h1910_nand_mtd);
-
-	/* Release io resource */
-	iounmap((void *)this->IO_ADDR_W);
-
-	/* Free the MTD device structure */
-	kfree(h1910_nand_mtd);
-}
-
-module_exit(h1910_cleanup);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Joshua Wise <joshua at joshuawise dot com>");
-MODULE_DESCRIPTION("NAND flash driver for iPAQ h1910");
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 42c6392..383a5ac 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -4,7 +4,6 @@
  *  Overview:
  *   This is the generic MTD driver for NAND flash devices. It should be
  *   capable of working with almost all NAND chips currently available.
- *   Basic support for AG-AND chips is provided.
  *
  *	Additional technical information is available on
  *	http://www.linux-mtd.infradead.org/doc/nand.html
@@ -22,8 +21,6 @@
  *	Enable cached programming for 2k page size chips
  *	Check, if mtd->ecctype should be set to MTD_ECC_HW
  *	if we have HW ECC support.
- *	The AG-AND chips have nice features for speed improvement,
- *	which are not supported yet. Read / program 4 pages in one go.
  *	BBT table is not serialized, has to be fixed
  *
  * This program is free software; you can redistribute it and/or modify
@@ -205,6 +202,50 @@ static void nand_select_chip(struct mtd_info *mtd, int chipnr)
 }
 
 /**
+ * nand_write_byte - [DEFAULT] write single byte to chip
+ * @mtd: MTD device structure
+ * @byte: value to write
+ *
+ * Default function to write a byte to I/O[7:0]
+ */
+static void nand_write_byte(struct mtd_info *mtd, uint8_t byte)
+{
+	struct nand_chip *chip = mtd->priv;
+
+	chip->write_buf(mtd, &byte, 1);
+}
+
+/**
+ * nand_write_byte16 - [DEFAULT] write single byte to a chip with width 16
+ * @mtd: MTD device structure
+ * @byte: value to write
+ *
+ * Default function to write a byte to I/O[7:0] on a 16-bit wide chip.
+ */
+static void nand_write_byte16(struct mtd_info *mtd, uint8_t byte)
+{
+	struct nand_chip *chip = mtd->priv;
+
+	/*
+	 * It's not entirely clear what should happen to I/O[15:8] when writing
+	 * a byte. The ONFi spec (Revision 3.1; 2012-09-19, Section 2.16) reads:
+	 *
+	 *    When the host supports a 16-bit bus width, only data is
+	 *    transferred at the 16-bit width. All address and command line
+	 *    transfers shall use only the lower 8-bits of the data bus. During
+	 *    command transfers, the host may place any value on the upper
+	 *    8-bits of the data bus. During address transfers, the host shall
+	 *    set the upper 8-bits of the data bus to 00h.
+	 *
+	 * One user of the write_byte callback is nand_onfi_set_features. The
+	 * four parameters are specified to be written to I/O[7:0], but this is
+	 * neither an address nor a command transfer. Let's assume a 0 on the
+	 * upper I/O lines is OK.
+	 */
+	chip->write_buf(mtd, (uint8_t[]){ byte, 0 }, 2);
+}
+
+/**
  * nand_write_buf - [DEFAULT] write buffer to chip
  * @mtd: MTD device structure
  * @buf: data buffer
@@ -515,7 +556,7 @@ EXPORT_SYMBOL_GPL(nand_wait_ready);
  * @page_addr: the page address for this command, -1 if none
  *
  * Send command to NAND device. This function is used for small page devices
- * (256/512 Bytes per page).
+ * (512 Bytes per page).
  */
 static void nand_command(struct mtd_info *mtd, unsigned int command,
 			 int column, int page_addr)
@@ -631,8 +672,7 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
 	}
 
 	/* Command latch cycle */
-	chip->cmd_ctrl(mtd, command & 0xff,
-		       NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
+	chip->cmd_ctrl(mtd, command, NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
 
 	if (column != -1 || page_addr != -1) {
 		int ctrl = NAND_CTRL_CHANGE | NAND_NCE | NAND_ALE;
@@ -671,16 +711,6 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
 	case NAND_CMD_SEQIN:
 	case NAND_CMD_RNDIN:
 	case NAND_CMD_STATUS:
-	case NAND_CMD_DEPLETE1:
-		return;
-
-	case NAND_CMD_STATUS_ERROR:
-	case NAND_CMD_STATUS_ERROR0:
-	case NAND_CMD_STATUS_ERROR1:
-	case NAND_CMD_STATUS_ERROR2:
-	case NAND_CMD_STATUS_ERROR3:
-		/* Read error status commands require only a short delay */
-		udelay(chip->chip_delay);
 		return;
 
 	case NAND_CMD_RESET:
@@ -836,10 +866,7 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
 	 */
 	ndelay(100);
 
-	if ((state == FL_ERASING) && (chip->options & NAND_IS_AND))
-		chip->cmdfunc(mtd, NAND_CMD_STATUS_MULTI, -1, -1);
-	else
-		chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
+	chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
 
 	if (in_interrupt() || oops_in_progress)
 		panic_nand_wait(mtd, chip, timeo);
@@ -2075,7 +2102,7 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
 	 */
 	cached = 0;
 
-	if (!cached || !(chip->options & NAND_CACHEPRG)) {
+	if (!cached || !NAND_HAS_CACHEPROG(chip)) {
 
 		chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
 		status = chip->waitfunc(mtd, chip);
@@ -2481,24 +2508,6 @@ static void single_erase_cmd(struct mtd_info *mtd, int page)
 }
 
 /**
- * multi_erase_cmd - [GENERIC] AND specific block erase command function
- * @mtd: MTD device structure
- * @page: the page address of the block which will be erased
- *
- * AND multi block erase command function. Erase 4 consecutive blocks.
- */
-static void multi_erase_cmd(struct mtd_info *mtd, int page)
-{
-	struct nand_chip *chip = mtd->priv;
-	/* Send commands to erase a block */
-	chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page++);
-	chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page++);
-	chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page++);
-	chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page);
-	chip->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1);
-}
-
-/**
  * nand_erase - [MTD Interface] erase block(s)
  * @mtd: MTD device structure
  * @instr: erase instruction
@@ -2510,7 +2519,6 @@ static int nand_erase(struct mtd_info *mtd, struct erase_info *instr)
 	return nand_erase_nand(mtd, instr, 0);
 }
 
-#define BBT_PAGE_MASK	0xffffff3f
 /**
  * nand_erase_nand - [INTERN] erase block(s)
  * @mtd: MTD device structure
@@ -2524,8 +2532,6 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
 {
 	int page, status, pages_per_block, ret, chipnr;
 	struct nand_chip *chip = mtd->priv;
-	loff_t rewrite_bbt[NAND_MAX_CHIPS] = {0};
-	unsigned int bbt_masked_page = 0xffffffff;
 	loff_t len;
 
 	pr_debug("%s: start = 0x%012llx, len = %llu\n",
@@ -2556,15 +2562,6 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
 		goto erase_exit;
 	}
 
-	/*
-	 * If BBT requires refresh, set the BBT page mask to see if the BBT
-	 * should be rewritten. Otherwise the mask is set to 0xffffffff which
-	 * can not be matched. This is also done when the bbt is actually
-	 * erased to avoid recursive updates.
-	 */
-	if (chip->options & BBT_AUTO_REFRESH && !allowbbt)
-		bbt_masked_page = chip->bbt_td->pages[chipnr] & BBT_PAGE_MASK;
-
 	/* Loop through the pages */
 	len = instr->len;
 
@@ -2610,15 +2607,6 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
 			goto erase_exit;
 		}
 
-		/*
-		 * If BBT requires refresh, set the BBT rewrite flag to the
-		 * page being erased.
-		 */
-		if (bbt_masked_page != 0xffffffff &&
-		    (page & BBT_PAGE_MASK) == bbt_masked_page)
-			    rewrite_bbt[chipnr] =
-					((loff_t)page << chip->page_shift);
-
 		/* Increment page address and decrement length */
 		len -= (1 << chip->phys_erase_shift);
 		page += pages_per_block;
@@ -2628,15 +2616,6 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
 			chipnr++;
 			chip->select_chip(mtd, -1);
 			chip->select_chip(mtd, chipnr);
-
-			/*
-			 * If BBT requires refresh and BBT-PERCHIP, set the BBT
-			 * page mask to see if this BBT should be rewritten.
-			 */
-			if (bbt_masked_page != 0xffffffff &&
-			    (chip->bbt_td->options & NAND_BBT_PERCHIP))
-				bbt_masked_page = chip->bbt_td->pages[chipnr] &
-					BBT_PAGE_MASK;
 		}
 	}
 	instr->state = MTD_ERASE_DONE;
@@ -2653,23 +2632,6 @@ erase_exit:
 	if (!ret)
 		mtd_erase_callback(instr);
 
-	/*
-	 * If BBT requires refresh and erase was successful, rewrite any
-	 * selected bad block tables.
-	 */
-	if (bbt_masked_page == 0xffffffff || ret)
-		return ret;
-
-	for (chipnr = 0; chipnr < chip->numchips; chipnr++) {
-		if (!rewrite_bbt[chipnr])
-			continue;
-		/* Update the BBT for chip */
-		pr_debug("%s: nand_update_bbt (%d:0x%0llx 0x%0x)\n",
-				__func__, chipnr, rewrite_bbt[chipnr],
-				chip->bbt_td->pages[chipnr]);
-		nand_update_bbt(mtd, rewrite_bbt[chipnr]);
-	}
-
 	/* Return more or less happy */
 	return ret;
 }
@@ -2722,7 +2684,7 @@ static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs)
 }
 
 /**
- * nand_onfi_set_features- [REPLACEABLE] set features for ONFI nand
+ * nand_onfi_set_features - [REPLACEABLE] set features for ONFI nand
  * @mtd: MTD device structure
  * @chip: nand chip info structure
  * @addr: feature address.
@@ -2732,12 +2694,15 @@ static int nand_onfi_set_features(struct mtd_info *mtd, struct nand_chip *chip,
 			int addr, uint8_t *subfeature_param)
 {
 	int status;
+	int i;
 
 	if (!chip->onfi_version)
 		return -EINVAL;
 
 	chip->cmdfunc(mtd, NAND_CMD_SET_FEATURES, addr, -1);
-	chip->write_buf(mtd, subfeature_param, ONFI_SUBFEATURE_PARAM_LEN);
+	for (i = 0; i < ONFI_SUBFEATURE_PARAM_LEN; ++i)
+		chip->write_byte(mtd, subfeature_param[i]);
+
 	status = chip->waitfunc(mtd, chip);
 	if (status & NAND_STATUS_FAIL)
 		return -EIO;
@@ -2745,7 +2710,7 @@ static int nand_onfi_set_features(struct mtd_info *mtd, struct nand_chip *chip,
 }
 
 /**
- * nand_onfi_get_features- [REPLACEABLE] get features for ONFI nand
+ * nand_onfi_get_features - [REPLACEABLE] get features for ONFI nand
  * @mtd: MTD device structure
  * @chip: nand chip info structure
  * @addr: feature address.
@@ -2754,6 +2719,8 @@ static int nand_onfi_set_features(struct mtd_info *mtd, struct nand_chip *chip,
 static int nand_onfi_get_features(struct mtd_info *mtd, struct nand_chip *chip,
 			int addr, uint8_t *subfeature_param)
 {
+	int i;
+
 	if (!chip->onfi_version)
 		return -EINVAL;
 
@@ -2761,7 +2728,8 @@ static int nand_onfi_get_features(struct mtd_info *mtd, struct nand_chip *chip,
 	memset(subfeature_param, 0, ONFI_SUBFEATURE_PARAM_LEN);
 
 	chip->cmdfunc(mtd, NAND_CMD_GET_FEATURES, addr, -1);
-	chip->read_buf(mtd, subfeature_param, ONFI_SUBFEATURE_PARAM_LEN);
+	for (i = 0; i < ONFI_SUBFEATURE_PARAM_LEN; ++i)
+		*subfeature_param++ = chip->read_byte(mtd);
 	return 0;
 }
 
@@ -2816,6 +2784,8 @@ static void nand_set_defaults(struct nand_chip *chip, int busw)
 		chip->block_markbad = nand_default_block_markbad;
 	if (!chip->write_buf)
 		chip->write_buf = busw ? nand_write_buf16 : nand_write_buf;
+	if (!chip->write_byte)
+		chip->write_byte = busw ? nand_write_byte16 : nand_write_byte;
 	if (!chip->read_buf)
 		chip->read_buf = busw ? nand_read_buf16 : nand_read_buf;
 	if (!chip->scan_bbt)
@@ -2905,8 +2875,6 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
 		chip->onfi_version = 20;
 	else if (val & (1 << 1))
 		chip->onfi_version = 10;
-	else
-		chip->onfi_version = 0;
 
 	if (!chip->onfi_version) {
 		pr_info("%s: unsupported ONFI version: %d\n", __func__, val);
@@ -3171,6 +3139,30 @@ static void nand_decode_bbm_options(struct mtd_info *mtd,
 		chip->bbt_options |= NAND_BBT_SCAN2NDPAGE;
 }
 
+static inline bool is_full_id_nand(struct nand_flash_dev *type)
+{
+	return type->id_len;
+}
+
+static bool find_full_id_nand(struct mtd_info *mtd, struct nand_chip *chip,
+		   struct nand_flash_dev *type, u8 *id_data, int *busw)
+{
+	if (!strncmp(type->id, id_data, type->id_len)) {
+		mtd->writesize = type->pagesize;
+		mtd->erasesize = type->erasesize;
+		mtd->oobsize = type->oobsize;
+
+		chip->cellinfo = id_data[2];
+		chip->chipsize = (uint64_t)type->chipsize << 20;
+		chip->options |= type->options;
+
+		*busw = type->options & NAND_BUSWIDTH_16;
+
+		return true;
+	}
+	return false;
+}
+
 /*
  * Get the flash and manufacturer id and lookup if the type is supported.
  */
@@ -3222,9 +3214,14 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
 	if (!type)
 		type = nand_flash_ids;
 
-	for (; type->name != NULL; type++)
-		if (*dev_id == type->id)
-			break;
+	for (; type->name != NULL; type++) {
+		if (is_full_id_nand(type)) {
+			if (find_full_id_nand(mtd, chip, type, id_data, &busw))
+				goto ident_done;
+		} else if (*dev_id == type->dev_id) {
+				break;
+		}
+	}
 
 	chip->onfi_version = 0;
 	if (!type->name || !type->pagesize) {
@@ -3302,12 +3299,7 @@ ident_done:
 	}
 
 	chip->badblockbits = 8;
-
-	/* Check for AND chips with 4 page planes */
-	if (chip->options & NAND_4PAGE_ARRAY)
-		chip->erase_cmd = multi_erase_cmd;
-	else
-		chip->erase_cmd = single_erase_cmd;
+	chip->erase_cmd = single_erase_cmd;
 
 	/* Do not replace user supplied command function! */
 	if (mtd->writesize > 512 && chip->cmdfunc == nand_command)
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index 916d6e9..2672643 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -1240,15 +1240,6 @@ int nand_update_bbt(struct mtd_info *mtd, loff_t offs)
  */
 static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
 
-static uint8_t scan_agand_pattern[] = { 0x1C, 0x71, 0xC7, 0x1C, 0x71, 0xC7 };
-
-static struct nand_bbt_descr agand_flashbased = {
-	.options = NAND_BBT_SCANEMPTY | NAND_BBT_SCANALLPAGES,
-	.offs = 0x20,
-	.len = 6,
-	.pattern = scan_agand_pattern
-};
-
 /* Generic flash bbt descriptors */
 static uint8_t bbt_pattern[] = {'B', 'b', 't', '0' };
 static uint8_t mirror_pattern[] = {'1', 't', 'b', 'B' };
@@ -1333,22 +1324,6 @@ int nand_default_bbt(struct mtd_info *mtd)
 {
 	struct nand_chip *this = mtd->priv;
 
-	/*
-	 * Default for AG-AND. We must use a flash based bad block table as the
-	 * devices have factory marked _good_ blocks. Erasing those blocks
-	 * leads to loss of the good / bad information, so we _must_ store this
-	 * information in a good / bad table during startup.
-	 */
-	if (this->options & NAND_IS_AND) {
-		/* Use the default pattern descriptors */
-		if (!this->bbt_td) {
-			this->bbt_td = &bbt_main_descr;
-			this->bbt_md = &bbt_mirror_descr;
-		}
-		this->bbt_options |= NAND_BBT_USE_FLASH;
-		return nand_scan_bbt(mtd, &agand_flashbased);
-	}
-
 	/* Is a flash based bad block table requested? */
 	if (this->bbt_options & NAND_BBT_USE_FLASH) {
 		/* Use the default pattern descriptors */
diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c
index 9c61238..683813a 100644
--- a/drivers/mtd/nand/nand_ids.c
+++ b/drivers/mtd/nand/nand_ids.c
@@ -10,163 +10,153 @@
  */
 #include <linux/module.h>
 #include <linux/mtd/nand.h>
-/*
-*	Chip ID list
-*
-*	Name. ID code, pagesize, chipsize in MegaByte, eraseblock size,
-*	options
-*
-*	Pagesize; 0, 256, 512
-*	0	get this information from the extended chip ID
-+	256	256 Byte page size
-*	512	512 Byte page size
-*/
-struct nand_flash_dev nand_flash_ids[] = {
+#include <linux/sizes.h>
+
+#define LP_OPTIONS NAND_SAMSUNG_LP_OPTIONS
+#define LP_OPTIONS16 (LP_OPTIONS | NAND_BUSWIDTH_16)
+
 #define SP_OPTIONS NAND_NEED_READRDY
 #define SP_OPTIONS16 (SP_OPTIONS | NAND_BUSWIDTH_16)
 
-#ifdef CONFIG_MTD_NAND_MUSEUM_IDS
-	{"NAND 1MiB 5V 8-bit",		0x6e, 256, 1, 0x1000, SP_OPTIONS},
-	{"NAND 2MiB 5V 8-bit",		0x64, 256, 2, 0x1000, SP_OPTIONS},
-	{"NAND 4MiB 5V 8-bit",		0x6b, 512, 4, 0x2000, SP_OPTIONS},
-	{"NAND 1MiB 3,3V 8-bit",	0xe8, 256, 1, 0x1000, SP_OPTIONS},
-	{"NAND 1MiB 3,3V 8-bit",	0xec, 256, 1, 0x1000, SP_OPTIONS},
-	{"NAND 2MiB 3,3V 8-bit",	0xea, 256, 2, 0x1000, SP_OPTIONS},
-	{"NAND 4MiB 3,3V 8-bit",	0xd5, 512, 4, 0x2000, SP_OPTIONS},
-	{"NAND 4MiB 3,3V 8-bit",	0xe3, 512, 4, 0x2000, SP_OPTIONS},
-	{"NAND 4MiB 3,3V 8-bit",	0xe5, 512, 4, 0x2000, SP_OPTIONS},
-	{"NAND 8MiB 3,3V 8-bit",	0xd6, 512, 8, 0x2000, SP_OPTIONS},
-
-	{"NAND 8MiB 1,8V 8-bit",	0x39, 512, 8, 0x2000, SP_OPTIONS},
-	{"NAND 8MiB 3,3V 8-bit",	0xe6, 512, 8, 0x2000, SP_OPTIONS},
-	{"NAND 8MiB 1,8V 16-bit",	0x49, 512, 8, 0x2000, SP_OPTIONS16},
-	{"NAND 8MiB 3,3V 16-bit",	0x59, 512, 8, 0x2000, SP_OPTIONS16},
-#endif
-
-	{"NAND 16MiB 1,8V 8-bit",	0x33, 512, 16, 0x4000, SP_OPTIONS},
-	{"NAND 16MiB 3,3V 8-bit",	0x73, 512, 16, 0x4000, SP_OPTIONS},
-	{"NAND 16MiB 1,8V 16-bit",	0x43, 512, 16, 0x4000, SP_OPTIONS16},
-	{"NAND 16MiB 3,3V 16-bit",	0x53, 512, 16, 0x4000, SP_OPTIONS16},
-
-	{"NAND 32MiB 1,8V 8-bit",	0x35, 512, 32, 0x4000, SP_OPTIONS},
-	{"NAND 32MiB 3,3V 8-bit",	0x75, 512, 32, 0x4000, SP_OPTIONS},
-	{"NAND 32MiB 1,8V 16-bit",	0x45, 512, 32, 0x4000, SP_OPTIONS16},
-	{"NAND 32MiB 3,3V 16-bit",	0x55, 512, 32, 0x4000, SP_OPTIONS16},
-
-	{"NAND 64MiB 1,8V 8-bit",	0x36, 512, 64, 0x4000, SP_OPTIONS},
-	{"NAND 64MiB 3,3V 8-bit",	0x76, 512, 64, 0x4000, SP_OPTIONS},
-	{"NAND 64MiB 1,8V 16-bit",	0x46, 512, 64, 0x4000, SP_OPTIONS16},
-	{"NAND 64MiB 3,3V 16-bit",	0x56, 512, 64, 0x4000, SP_OPTIONS16},
-
-	{"NAND 128MiB 1,8V 8-bit",	0x78, 512, 128, 0x4000, SP_OPTIONS},
-	{"NAND 128MiB 1,8V 8-bit",	0x39, 512, 128, 0x4000, SP_OPTIONS},
-	{"NAND 128MiB 3,3V 8-bit",	0x79, 512, 128, 0x4000, SP_OPTIONS},
-	{"NAND 128MiB 1,8V 16-bit",	0x72, 512, 128, 0x4000, SP_OPTIONS16},
-	{"NAND 128MiB 1,8V 16-bit",	0x49, 512, 128, 0x4000, SP_OPTIONS16},
-	{"NAND 128MiB 3,3V 16-bit",	0x74, 512, 128, 0x4000, SP_OPTIONS16},
-	{"NAND 128MiB 3,3V 16-bit",	0x59, 512, 128, 0x4000, SP_OPTIONS16},
-
-	{"NAND 256MiB 3,3V 8-bit",	0x71, 512, 256, 0x4000, SP_OPTIONS},
+/*
+ * The chip ID list:
+ *    name, device ID, page size, chip size in MiB, eraseblock size, options
+ *
+ * If page size and eraseblock size are 0, the sizes are taken from the
+ * extended chip ID.
+ */
+struct nand_flash_dev nand_flash_ids[] = {
+	/*
+	 * Some incompatible NAND chips share device ID's and so must be
+	 * listed by full ID. We list them first so that we can easily identify
+	 * the most specific match.
+	 */
+	{"TC58NVG2S0F 4G 3.3V 8-bit",
+		{ .id = {0x98, 0xdc, 0x90, 0x26, 0x76, 0x15, 0x01, 0x08} },
+		  SZ_4K, SZ_512, SZ_256K, 0, 8, 224},
+	{"TC58NVG3S0F 8G 3.3V 8-bit",
+		{ .id = {0x98, 0xd3, 0x90, 0x26, 0x76, 0x15, 0x02, 0x08} },
+		  SZ_4K, SZ_1K, SZ_256K, 0, 8, 232},
+	{"TC58NVG5D2 32G 3.3V 8-bit",
+		{ .id = {0x98, 0xd7, 0x94, 0x32, 0x76, 0x56, 0x09, 0x00} },
+		  SZ_8K, SZ_4K, SZ_1M, 0, 8, 640},
+	{"TC58NVG6D2 64G 3.3V 8-bit",
+		{ .id = {0x98, 0xde, 0x94, 0x82, 0x76, 0x56, 0x04, 0x20} },
+		  SZ_8K, SZ_8K, SZ_2M, 0, 8, 640},
+
+	LEGACY_ID_NAND("NAND 4MiB 5V 8-bit",   0x6B, 4, SZ_8K, SP_OPTIONS),
+	LEGACY_ID_NAND("NAND 4MiB 3,3V 8-bit", 0xE3, 4, SZ_8K, SP_OPTIONS),
+	LEGACY_ID_NAND("NAND 4MiB 3,3V 8-bit", 0xE5, 4, SZ_8K, SP_OPTIONS),
+	LEGACY_ID_NAND("NAND 8MiB 3,3V 8-bit", 0xD6, 8, SZ_8K, SP_OPTIONS),
+	LEGACY_ID_NAND("NAND 8MiB 3,3V 8-bit", 0xE6, 8, SZ_8K, SP_OPTIONS),
+
+	LEGACY_ID_NAND("NAND 16MiB 1,8V 8-bit",  0x33, 16, SZ_16K, SP_OPTIONS),
+	LEGACY_ID_NAND("NAND 16MiB 3,3V 8-bit",  0x73, 16, SZ_16K, SP_OPTIONS),
+	LEGACY_ID_NAND("NAND 16MiB 1,8V 16-bit", 0x43, 16, SZ_16K, SP_OPTIONS16),
+	LEGACY_ID_NAND("NAND 16MiB 3,3V 16-bit", 0x53, 16, SZ_16K, SP_OPTIONS16),
+
+	LEGACY_ID_NAND("NAND 32MiB 1,8V 8-bit",  0x35, 32, SZ_16K, SP_OPTIONS),
+	LEGACY_ID_NAND("NAND 32MiB 3,3V 8-bit",  0x75, 32, SZ_16K, SP_OPTIONS),
+	LEGACY_ID_NAND("NAND 32MiB 1,8V 16-bit", 0x45, 32, SZ_16K, SP_OPTIONS16),
+	LEGACY_ID_NAND("NAND 32MiB 3,3V 16-bit", 0x55, 32, SZ_16K, SP_OPTIONS16),
+
+	LEGACY_ID_NAND("NAND 64MiB 1,8V 8-bit",  0x36, 64, SZ_16K, SP_OPTIONS),
+	LEGACY_ID_NAND("NAND 64MiB 3,3V 8-bit",  0x76, 64, SZ_16K, SP_OPTIONS),
+	LEGACY_ID_NAND("NAND 64MiB 1,8V 16-bit", 0x46, 64, SZ_16K, SP_OPTIONS16),
+	LEGACY_ID_NAND("NAND 64MiB 3,3V 16-bit", 0x56, 64, SZ_16K, SP_OPTIONS16),
+
+	LEGACY_ID_NAND("NAND 128MiB 1,8V 8-bit",  0x78, 128, SZ_16K, SP_OPTIONS),
+	LEGACY_ID_NAND("NAND 128MiB 1,8V 8-bit",  0x39, 128, SZ_16K, SP_OPTIONS),
+	LEGACY_ID_NAND("NAND 128MiB 3,3V 8-bit",  0x79, 128, SZ_16K, SP_OPTIONS),
+	LEGACY_ID_NAND("NAND 128MiB 1,8V 16-bit", 0x72, 128, SZ_16K, SP_OPTIONS16),
+	LEGACY_ID_NAND("NAND 128MiB 1,8V 16-bit", 0x49, 128, SZ_16K, SP_OPTIONS16),
+	LEGACY_ID_NAND("NAND 128MiB 3,3V 16-bit", 0x74, 128, SZ_16K, SP_OPTIONS16),
+	LEGACY_ID_NAND("NAND 128MiB 3,3V 16-bit", 0x59, 128, SZ_16K, SP_OPTIONS16),
+
+	LEGACY_ID_NAND("NAND 256MiB 3,3V 8-bit", 0x71, 256, SZ_16K, SP_OPTIONS),
 
 	/*
-	 * These are the new chips with large page size. The pagesize and the
-	 * erasesize is determined from the extended id bytes
+	 * These are the new chips with large page size. Their page size and
+	 * eraseblock size are determined from the extended ID bytes.
 	 */
-#define LP_OPTIONS NAND_SAMSUNG_LP_OPTIONS
-#define LP_OPTIONS16 (LP_OPTIONS | NAND_BUSWIDTH_16)
 
 	/* 512 Megabit */
-	{"NAND 64MiB 1,8V 8-bit",	0xA2, 0,  64, 0, LP_OPTIONS},
-	{"NAND 64MiB 1,8V 8-bit",	0xA0, 0,  64, 0, LP_OPTIONS},
-	{"NAND 64MiB 3,3V 8-bit",	0xF2, 0,  64, 0, LP_OPTIONS},
-	{"NAND 64MiB 3,3V 8-bit",	0xD0, 0,  64, 0, LP_OPTIONS},
-	{"NAND 64MiB 3,3V 8-bit",	0xF0, 0,  64, 0, LP_OPTIONS},
-	{"NAND 64MiB 1,8V 16-bit",	0xB2, 0,  64, 0, LP_OPTIONS16},
-	{"NAND 64MiB 1,8V 16-bit",	0xB0, 0,  64, 0, LP_OPTIONS16},
-	{"NAND 64MiB 3,3V 16-bit",	0xC2, 0,  64, 0, LP_OPTIONS16},
-	{"NAND 64MiB 3,3V 16-bit",	0xC0, 0,  64, 0, LP_OPTIONS16},
+	EXTENDED_ID_NAND("NAND 64MiB 1,8V 8-bit",  0xA2,  64, LP_OPTIONS),
+	EXTENDED_ID_NAND("NAND 64MiB 1,8V 8-bit",  0xA0,  64, LP_OPTIONS),
+	EXTENDED_ID_NAND("NAND 64MiB 3,3V 8-bit",  0xF2,  64, LP_OPTIONS),
+	EXTENDED_ID_NAND("NAND 64MiB 3,3V 8-bit",  0xD0,  64, LP_OPTIONS),
+	EXTENDED_ID_NAND("NAND 64MiB 3,3V 8-bit",  0xF0,  64, LP_OPTIONS),
+	EXTENDED_ID_NAND("NAND 64MiB 1,8V 16-bit", 0xB2,  64, LP_OPTIONS16),
+	EXTENDED_ID_NAND("NAND 64MiB 1,8V 16-bit", 0xB0,  64, LP_OPTIONS16),
+	EXTENDED_ID_NAND("NAND 64MiB 3,3V 16-bit", 0xC2,  64, LP_OPTIONS16),
+	EXTENDED_ID_NAND("NAND 64MiB 3,3V 16-bit", 0xC0,  64, LP_OPTIONS16),
 
 	/* 1 Gigabit */
-	{"NAND 128MiB 1,8V 8-bit",	0xA1, 0, 128, 0, LP_OPTIONS},
-	{"NAND 128MiB 3,3V 8-bit",	0xF1, 0, 128, 0, LP_OPTIONS},
-	{"NAND 128MiB 3,3V 8-bit",	0xD1, 0, 128, 0, LP_OPTIONS},
-	{"NAND 128MiB 1,8V 16-bit",	0xB1, 0, 128, 0, LP_OPTIONS16},
-	{"NAND 128MiB 3,3V 16-bit",	0xC1, 0, 128, 0, LP_OPTIONS16},
-	{"NAND 128MiB 1,8V 16-bit",     0xAD, 0, 128, 0, LP_OPTIONS16},
+	EXTENDED_ID_NAND("NAND 128MiB 1,8V 8-bit",  0xA1, 128, LP_OPTIONS),
+	EXTENDED_ID_NAND("NAND 128MiB 3,3V 8-bit",  0xF1, 128, LP_OPTIONS),
+	EXTENDED_ID_NAND("NAND 128MiB 3,3V 8-bit",  0xD1, 128, LP_OPTIONS),
+	EXTENDED_ID_NAND("NAND 128MiB 1,8V 16-bit", 0xB1, 128, LP_OPTIONS16),
+	EXTENDED_ID_NAND("NAND 128MiB 3,3V 16-bit", 0xC1, 128, LP_OPTIONS16),
+	EXTENDED_ID_NAND("NAND 128MiB 1,8V 16-bit", 0xAD, 128, LP_OPTIONS16),
 
 	/* 2 Gigabit */
-	{"NAND 256MiB 1,8V 8-bit",	0xAA, 0, 256, 0, LP_OPTIONS},
-	{"NAND 256MiB 3,3V 8-bit",	0xDA, 0, 256, 0, LP_OPTIONS},
-	{"NAND 256MiB 1,8V 16-bit",	0xBA, 0, 256, 0, LP_OPTIONS16},
-	{"NAND 256MiB 3,3V 16-bit",	0xCA, 0, 256, 0, LP_OPTIONS16},
+	EXTENDED_ID_NAND("NAND 256MiB 1,8V 8-bit",  0xAA, 256, LP_OPTIONS),
+	EXTENDED_ID_NAND("NAND 256MiB 3,3V 8-bit",  0xDA, 256, LP_OPTIONS),
+	EXTENDED_ID_NAND("NAND 256MiB 1,8V 16-bit", 0xBA, 256, LP_OPTIONS16),
+	EXTENDED_ID_NAND("NAND 256MiB 3,3V 16-bit", 0xCA, 256, LP_OPTIONS16),
 
 	/* 4 Gigabit */
-	{"NAND 512MiB 1,8V 8-bit",	0xAC, 0, 512, 0, LP_OPTIONS},
-	{"NAND 512MiB 3,3V 8-bit",	0xDC, 0, 512, 0, LP_OPTIONS},
-	{"NAND 512MiB 1,8V 16-bit",	0xBC, 0, 512, 0, LP_OPTIONS16},
-	{"NAND 512MiB 3,3V 16-bit",	0xCC, 0, 512, 0, LP_OPTIONS16},
+	EXTENDED_ID_NAND("NAND 512MiB 1,8V 8-bit",  0xAC, 512, LP_OPTIONS),
+	EXTENDED_ID_NAND("NAND 512MiB 3,3V 8-bit",  0xDC, 512, LP_OPTIONS),
+	EXTENDED_ID_NAND("NAND 512MiB 1,8V 16-bit", 0xBC, 512, LP_OPTIONS16),
+	EXTENDED_ID_NAND("NAND 512MiB 3,3V 16-bit", 0xCC, 512, LP_OPTIONS16),
 
 	/* 8 Gigabit */
-	{"NAND 1GiB 1,8V 8-bit",	0xA3, 0, 1024, 0, LP_OPTIONS},
-	{"NAND 1GiB 3,3V 8-bit",	0xD3, 0, 1024, 0, LP_OPTIONS},
-	{"NAND 1GiB 1,8V 16-bit",	0xB3, 0, 1024, 0, LP_OPTIONS16},
-	{"NAND 1GiB 3,3V 16-bit",	0xC3, 0, 1024, 0, LP_OPTIONS16},
+	EXTENDED_ID_NAND("NAND 1GiB 1,8V 8-bit",  0xA3, 1024, LP_OPTIONS),
+	EXTENDED_ID_NAND("NAND 1GiB 3,3V 8-bit",  0xD3, 1024, LP_OPTIONS),
+	EXTENDED_ID_NAND("NAND 1GiB 1,8V 16-bit", 0xB3, 1024, LP_OPTIONS16),
+	EXTENDED_ID_NAND("NAND 1GiB 3,3V 16-bit", 0xC3, 1024, LP_OPTIONS16),
 
 	/* 16 Gigabit */
-	{"NAND 2GiB 1,8V 8-bit",	0xA5, 0, 2048, 0, LP_OPTIONS},
-	{"NAND 2GiB 3,3V 8-bit",	0xD5, 0, 2048, 0, LP_OPTIONS},
-	{"NAND 2GiB 1,8V 16-bit",	0xB5, 0, 2048, 0, LP_OPTIONS16},
-	{"NAND 2GiB 3,3V 16-bit",	0xC5, 0, 2048, 0, LP_OPTIONS16},
+	EXTENDED_ID_NAND("NAND 2GiB 1,8V 8-bit",  0xA5, 2048, LP_OPTIONS),
+	EXTENDED_ID_NAND("NAND 2GiB 3,3V 8-bit",  0xD5, 2048, LP_OPTIONS),
+	EXTENDED_ID_NAND("NAND 2GiB 1,8V 16-bit", 0xB5, 2048, LP_OPTIONS16),
+	EXTENDED_ID_NAND("NAND 2GiB 3,3V 16-bit", 0xC5, 2048, LP_OPTIONS16),
 
 	/* 32 Gigabit */
-	{"NAND 4GiB 1,8V 8-bit",	0xA7, 0, 4096, 0, LP_OPTIONS},
-	{"NAND 4GiB 3,3V 8-bit",	0xD7, 0, 4096, 0, LP_OPTIONS},
-	{"NAND 4GiB 1,8V 16-bit",	0xB7, 0, 4096, 0, LP_OPTIONS16},
-	{"NAND 4GiB 3,3V 16-bit",	0xC7, 0, 4096, 0, LP_OPTIONS16},
+	EXTENDED_ID_NAND("NAND 4GiB 1,8V 8-bit",  0xA7, 4096, LP_OPTIONS),
+	EXTENDED_ID_NAND("NAND 4GiB 3,3V 8-bit",  0xD7, 4096, LP_OPTIONS),
+	EXTENDED_ID_NAND("NAND 4GiB 1,8V 16-bit", 0xB7, 4096, LP_OPTIONS16),
+	EXTENDED_ID_NAND("NAND 4GiB 3,3V 16-bit", 0xC7, 4096, LP_OPTIONS16),
 
 	/* 64 Gigabit */
-	{"NAND 8GiB 1,8V 8-bit",	0xAE, 0, 8192, 0, LP_OPTIONS},
-	{"NAND 8GiB 3,3V 8-bit",	0xDE, 0, 8192, 0, LP_OPTIONS},
-	{"NAND 8GiB 1,8V 16-bit",	0xBE, 0, 8192, 0, LP_OPTIONS16},
-	{"NAND 8GiB 3,3V 16-bit",	0xCE, 0, 8192, 0, LP_OPTIONS16},
+	EXTENDED_ID_NAND("NAND 8GiB 1,8V 8-bit",  0xAE, 8192, LP_OPTIONS),
+	EXTENDED_ID_NAND("NAND 8GiB 3,3V 8-bit",  0xDE, 8192, LP_OPTIONS),
+	EXTENDED_ID_NAND("NAND 8GiB 1,8V 16-bit", 0xBE, 8192, LP_OPTIONS16),
+	EXTENDED_ID_NAND("NAND 8GiB 3,3V 16-bit", 0xCE, 8192, LP_OPTIONS16),
 
 	/* 128 Gigabit */
-	{"NAND 16GiB 1,8V 8-bit",	0x1A, 0, 16384, 0, LP_OPTIONS},
-	{"NAND 16GiB 3,3V 8-bit",	0x3A, 0, 16384, 0, LP_OPTIONS},
-	{"NAND 16GiB 1,8V 16-bit",	0x2A, 0, 16384, 0, LP_OPTIONS16},
-	{"NAND 16GiB 3,3V 16-bit",	0x4A, 0, 16384, 0, LP_OPTIONS16},
+	EXTENDED_ID_NAND("NAND 16GiB 1,8V 8-bit",  0x1A, 16384, LP_OPTIONS),
+	EXTENDED_ID_NAND("NAND 16GiB 3,3V 8-bit",  0x3A, 16384, LP_OPTIONS),
+	EXTENDED_ID_NAND("NAND 16GiB 1,8V 16-bit", 0x2A, 16384, LP_OPTIONS16),
+	EXTENDED_ID_NAND("NAND 16GiB 3,3V 16-bit", 0x4A, 16384, LP_OPTIONS16),
 
 	/* 256 Gigabit */
-	{"NAND 32GiB 1,8V 8-bit",	0x1C, 0, 32768, 0, LP_OPTIONS},
-	{"NAND 32GiB 3,3V 8-bit",	0x3C, 0, 32768, 0, LP_OPTIONS},
-	{"NAND 32GiB 1,8V 16-bit",	0x2C, 0, 32768, 0, LP_OPTIONS16},
-	{"NAND 32GiB 3,3V 16-bit",	0x4C, 0, 32768, 0, LP_OPTIONS16},
+	EXTENDED_ID_NAND("NAND 32GiB 1,8V 8-bit",  0x1C, 32768, LP_OPTIONS),
+	EXTENDED_ID_NAND("NAND 32GiB 3,3V 8-bit",  0x3C, 32768, LP_OPTIONS),
+	EXTENDED_ID_NAND("NAND 32GiB 1,8V 16-bit", 0x2C, 32768, LP_OPTIONS16),
+	EXTENDED_ID_NAND("NAND 32GiB 3,3V 16-bit", 0x4C, 32768, LP_OPTIONS16),
 
 	/* 512 Gigabit */
-	{"NAND 64GiB 1,8V 8-bit",	0x1E, 0, 65536, 0, LP_OPTIONS},
-	{"NAND 64GiB 3,3V 8-bit",	0x3E, 0, 65536, 0, LP_OPTIONS},
-	{"NAND 64GiB 1,8V 16-bit",	0x2E, 0, 65536, 0, LP_OPTIONS16},
-	{"NAND 64GiB 3,3V 16-bit",	0x4E, 0, 65536, 0, LP_OPTIONS16},
+	EXTENDED_ID_NAND("NAND 64GiB 1,8V 8-bit",  0x1E, 65536, LP_OPTIONS),
+	EXTENDED_ID_NAND("NAND 64GiB 3,3V 8-bit",  0x3E, 65536, LP_OPTIONS),
+	EXTENDED_ID_NAND("NAND 64GiB 1,8V 16-bit", 0x2E, 65536, LP_OPTIONS16),
+	EXTENDED_ID_NAND("NAND 64GiB 3,3V 16-bit", 0x4E, 65536, LP_OPTIONS16),
 
-	/*
-	 * Renesas AND 1 Gigabit. Those chips do not support extended id and
-	 * have a strange page/block layout !  The chosen minimum erasesize is
-	 * 4 * 2 * 2048 = 16384 Byte, as those chips have an array of 4 page
-	 * planes 1 block = 2 pages, but due to plane arrangement the blocks
-	 * 0-3 consists of page 0 + 4,1 + 5, 2 + 6, 3 + 7 Anyway JFFS2 would
-	 * increase the eraseblock size so we chose a combined one which can be
-	 * erased in one go There are more speed improvements for reads and
-	 * writes possible, but not implemented now
-	 */
-	{"AND 128MiB 3,3V 8-bit",	0x01, 2048, 128, 0x4000,
-	 NAND_IS_AND | NAND_4PAGE_ARRAY | BBT_AUTO_REFRESH},
-
-	{NULL,}
+	{NULL}
 };
 
-/*
-*	Manufacturer ID list
-*/
+/* Manufacturer IDs */
 struct nand_manufacturers nand_manuf_ids[] = {
 	{NAND_MFR_TOSHIBA, "Toshiba"},
 	{NAND_MFR_SAMSUNG, "Samsung"},
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c
index 891c52a..cb38f3d 100644
--- a/drivers/mtd/nand/nandsim.c
+++ b/drivers/mtd/nand/nandsim.c
@@ -218,7 +218,6 @@ MODULE_PARM_DESC(bch,		 "Enable BCH ecc and set how many bits should "
 #define STATE_CMD_READOOB      0x00000005 /* read OOB area */
 #define STATE_CMD_ERASE1       0x00000006 /* sector erase first command */
 #define STATE_CMD_STATUS       0x00000007 /* read status */
-#define STATE_CMD_STATUS_M     0x00000008 /* read multi-plane status (isn't implemented) */
 #define STATE_CMD_SEQIN        0x00000009 /* sequential data input */
 #define STATE_CMD_READID       0x0000000A /* read ID */
 #define STATE_CMD_ERASE2       0x0000000B /* sector erase second command */
@@ -263,14 +262,13 @@ MODULE_PARM_DESC(bch,		 "Enable BCH ecc and set how many bits should "
 #define NS_OPER_STATES   6  /* Maximum number of states in operation */
 
 #define OPT_ANY          0xFFFFFFFF /* any chip supports this operation */
-#define OPT_PAGE256      0x00000001 /* 256-byte  page chips */
 #define OPT_PAGE512      0x00000002 /* 512-byte  page chips */
 #define OPT_PAGE2048     0x00000008 /* 2048-byte page chips */
 #define OPT_SMARTMEDIA   0x00000010 /* SmartMedia technology chips */
 #define OPT_PAGE512_8BIT 0x00000040 /* 512-byte page chips with 8-bit bus width */
 #define OPT_PAGE4096     0x00000080 /* 4096-byte page chips */
 #define OPT_LARGEPAGE    (OPT_PAGE2048 | OPT_PAGE4096) /* 2048 & 4096-byte page chips */
-#define OPT_SMALLPAGE    (OPT_PAGE256  | OPT_PAGE512)  /* 256 and 512-byte page chips */
+#define OPT_SMALLPAGE    (OPT_PAGE512) /* 512-byte page chips */
 
 /* Remove action bits from state */
 #define NS_STATE(x) ((x) & ~ACTION_MASK)
@@ -406,8 +404,6 @@ static struct nandsim_operations {
 	{OPT_ANY, {STATE_CMD_ERASE1, STATE_ADDR_SEC, STATE_CMD_ERASE2 | ACTION_SECERASE, STATE_READY}},
 	/* Read status */
 	{OPT_ANY, {STATE_CMD_STATUS, STATE_DATAOUT_STATUS, STATE_READY}},
-	/* Read multi-plane status */
-	{OPT_SMARTMEDIA, {STATE_CMD_STATUS_M, STATE_DATAOUT_STATUS_M, STATE_READY}},
 	/* Read ID */
 	{OPT_ANY, {STATE_CMD_READID, STATE_ADDR_ZERO, STATE_DATAOUT_ID, STATE_READY}},
 	/* Large page devices read page */
@@ -699,10 +695,7 @@ static int init_nandsim(struct mtd_info *mtd)
 	ns->geom.secszoob = ns->geom.secsz + ns->geom.oobsz * ns->geom.pgsec;
 	ns->options = 0;
 
-	if (ns->geom.pgsz == 256) {
-		ns->options |= OPT_PAGE256;
-	}
-	else if (ns->geom.pgsz == 512) {
+	if (ns->geom.pgsz == 512) {
 		ns->options |= OPT_PAGE512;
 		if (ns->busw == 8)
 			ns->options |= OPT_PAGE512_8BIT;
@@ -769,9 +762,9 @@ static int init_nandsim(struct mtd_info *mtd)
 	}
 
 	/* Detect how many ID bytes the NAND chip outputs */
-        for (i = 0; nand_flash_ids[i].name != NULL; i++) {
-                if (second_id_byte != nand_flash_ids[i].id)
-                        continue;
+	for (i = 0; nand_flash_ids[i].name != NULL; i++) {
+		if (second_id_byte != nand_flash_ids[i].dev_id)
+			continue;
 	}
 
 	if (ns->busw == 16)
@@ -1079,8 +1072,6 @@ static char *get_state_name(uint32_t state)
 			return "STATE_CMD_ERASE1";
 		case STATE_CMD_STATUS:
 			return "STATE_CMD_STATUS";
-		case STATE_CMD_STATUS_M:
-			return "STATE_CMD_STATUS_M";
 		case STATE_CMD_SEQIN:
 			return "STATE_CMD_SEQIN";
 		case STATE_CMD_READID:
@@ -1145,7 +1136,6 @@ static int check_command(int cmd)
 	case NAND_CMD_RNDOUTSTART:
 		return 0;
 
-	case NAND_CMD_STATUS_MULTI:
 	default:
 		return 1;
 	}
@@ -1171,8 +1161,6 @@ static uint32_t get_state_by_command(unsigned command)
 			return STATE_CMD_ERASE1;
 		case NAND_CMD_STATUS:
 			return STATE_CMD_STATUS;
-		case NAND_CMD_STATUS_MULTI:
-			return STATE_CMD_STATUS_M;
 		case NAND_CMD_SEQIN:
 			return STATE_CMD_SEQIN;
 		case NAND_CMD_READID:
@@ -2306,7 +2294,7 @@ static int __init ns_init_module(void)
 		nand->geom.idbytes = 2;
 	nand->regs.status = NS_STATUS_OK(nand);
 	nand->nxstate = STATE_UNKNOWN;
-	nand->options |= OPT_PAGE256; /* temporary value */
+	nand->options |= OPT_PAGE512; /* temporary value */
 	nand->ids[0] = first_id_byte;
 	nand->ids[1] = second_id_byte;
 	nand->ids[2] = third_id_byte;
diff --git a/drivers/mtd/nand/nuc900_nand.c b/drivers/mtd/nand/nuc900_nand.c
index a619119..cd6be2e 100644
--- a/drivers/mtd/nand/nuc900_nand.c
+++ b/drivers/mtd/nand/nuc900_nand.c
@@ -177,15 +177,6 @@ static void nuc900_nand_command_lp(struct mtd_info *mtd, unsigned int command,
 	case NAND_CMD_SEQIN:
 	case NAND_CMD_RNDIN:
 	case NAND_CMD_STATUS:
-	case NAND_CMD_DEPLETE1:
-		return;
-
-	case NAND_CMD_STATUS_ERROR:
-	case NAND_CMD_STATUS_ERROR0:
-	case NAND_CMD_STATUS_ERROR1:
-	case NAND_CMD_STATUS_ERROR2:
-	case NAND_CMD_STATUS_ERROR3:
-		udelay(chip->chip_delay);
 		return;
 
 	case NAND_CMD_RESET:
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 8e820dd..81b80af 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -1023,9 +1023,9 @@ static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip)
 	int status, state = this->state;
 
 	if (state == FL_ERASING)
-		timeo += (HZ * 400) / 1000;
+		timeo += msecs_to_jiffies(400);
 	else
-		timeo += (HZ * 20) / 1000;
+		timeo += msecs_to_jiffies(20);
 
 	writeb(NAND_CMD_STATUS & 0xFF, info->reg.gpmc_nand_command);
 	while (time_before(jiffies, timeo)) {
@@ -1701,8 +1701,9 @@ static int omap3_init_bch(struct mtd_info *mtd, int ecc_opt)
 		elm_node = of_find_node_by_phandle(be32_to_cpup(parp));
 		pdev = of_find_device_by_node(elm_node);
 		info->elm_dev = &pdev->dev;
-		elm_config(info->elm_dev, bch_type);
-		info->is_elm_used = true;
+
+		if (elm_config(info->elm_dev, bch_type) == 0)
+			info->is_elm_used = true;
 	}
 
 	if (info->is_elm_used && (mtd->writesize <= 4096)) {
diff --git a/drivers/mtd/nand/orion_nand.c b/drivers/mtd/nand/orion_nand.c
index cd72b92..8fbd002 100644
--- a/drivers/mtd/nand/orion_nand.c
+++ b/drivers/mtd/nand/orion_nand.c
@@ -231,18 +231,7 @@ static struct platform_driver orion_nand_driver = {
 	},
 };
 
-static int __init orion_nand_init(void)
-{
-	return platform_driver_probe(&orion_nand_driver, orion_nand_probe);
-}
-
-static void __exit orion_nand_exit(void)
-{
-	platform_driver_unregister(&orion_nand_driver);
-}
-
-module_init(orion_nand_init);
-module_exit(orion_nand_exit);
+module_platform_driver_probe(orion_nand_driver, orion_nand_probe);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Tzachi Perelstein");
diff --git a/drivers/mtd/nand/ppchameleonevb.c b/drivers/mtd/nand/ppchameleonevb.c
deleted file mode 100644
index 0ddd90e..0000000
--- a/drivers/mtd/nand/ppchameleonevb.c
+++ /dev/null
@@ -1,403 +0,0 @@
-/*
- *  drivers/mtd/nand/ppchameleonevb.c
- *
- *  Copyright (C) 2003 DAVE Srl (info@wawnet.biz)
- *
- *  Derived from drivers/mtd/nand/edb7312.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.
- *
- *  Overview:
- *   This is a device driver for the NAND flash devices found on the
- *   PPChameleon/PPChameleonEVB system.
- *   PPChameleon options (autodetected):
- *   - BA model: no NAND
- *   - ME model: 32MB (Samsung K9F5608U0B)
- *   - HI model: 128MB (Samsung K9F1G08UOM)
- *   PPChameleonEVB options:
- *   - 32MB (Samsung K9F5608U0B)
- */
-
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
-#include <linux/mtd/partitions.h>
-#include <asm/io.h>
-#include <platforms/PPChameleonEVB.h>
-
-#undef USE_READY_BUSY_PIN
-#define USE_READY_BUSY_PIN
-/* see datasheets (tR) */
-#define NAND_BIG_DELAY_US		25
-#define NAND_SMALL_DELAY_US		10
-
-/* handy sizes */
-#define SZ_4M                           0x00400000
-#define NAND_SMALL_SIZE                 0x02000000
-#define NAND_MTD_NAME		"ppchameleon-nand"
-#define NAND_EVB_MTD_NAME	"ppchameleonevb-nand"
-
-/* GPIO pins used to drive NAND chip mounted on processor module */
-#define NAND_nCE_GPIO_PIN 		(0x80000000 >> 1)
-#define NAND_CLE_GPIO_PIN 		(0x80000000 >> 2)
-#define NAND_ALE_GPIO_PIN 		(0x80000000 >> 3)
-#define NAND_RB_GPIO_PIN 		(0x80000000 >> 4)
-/* GPIO pins used to drive NAND chip mounted on EVB */
-#define NAND_EVB_nCE_GPIO_PIN 	(0x80000000 >> 14)
-#define NAND_EVB_CLE_GPIO_PIN 	(0x80000000 >> 15)
-#define NAND_EVB_ALE_GPIO_PIN 	(0x80000000 >> 16)
-#define NAND_EVB_RB_GPIO_PIN 	(0x80000000 >> 31)
-
-/*
- * MTD structure for PPChameleonEVB board
- */
-static struct mtd_info *ppchameleon_mtd = NULL;
-static struct mtd_info *ppchameleonevb_mtd = NULL;
-
-/*
- * Module stuff
- */
-static unsigned long ppchameleon_fio_pbase = CFG_NAND0_PADDR;
-static unsigned long ppchameleonevb_fio_pbase = CFG_NAND1_PADDR;
-
-#ifdef MODULE
-module_param(ppchameleon_fio_pbase, ulong, 0);
-module_param(ppchameleonevb_fio_pbase, ulong, 0);
-#else
-__setup("ppchameleon_fio_pbase=", ppchameleon_fio_pbase);
-__setup("ppchameleonevb_fio_pbase=", ppchameleonevb_fio_pbase);
-#endif
-
-/*
- * Define static partitions for flash devices
- */
-static struct mtd_partition partition_info_hi[] = {
-      { .name = "PPChameleon HI Nand Flash",
-	.offset = 0,
-	.size = 128 * 1024 * 1024
-      }
-};
-
-static struct mtd_partition partition_info_me[] = {
-      { .name = "PPChameleon ME Nand Flash",
-	.offset = 0,
-	.size = 32 * 1024 * 1024
-      }
-};
-
-static struct mtd_partition partition_info_evb[] = {
-      { .name = "PPChameleonEVB Nand Flash",
-	.offset = 0,
-	.size = 32 * 1024 * 1024
-      }
-};
-
-#define NUM_PARTITIONS 1
-
-/*
- *	hardware specific access to control-lines
- */
-static void ppchameleon_hwcontrol(struct mtd_info *mtdinfo, int cmd,
-				  unsigned int ctrl)
-{
-	struct nand_chip *chip = mtd->priv;
-
-	if (ctrl & NAND_CTRL_CHANGE) {
-#error Missing headerfiles. No way to fix this. -tglx
-		switch (cmd) {
-		case NAND_CTL_SETCLE:
-			MACRO_NAND_CTL_SETCLE((unsigned long)CFG_NAND0_PADDR);
-			break;
-		case NAND_CTL_CLRCLE:
-			MACRO_NAND_CTL_CLRCLE((unsigned long)CFG_NAND0_PADDR);
-			break;
-		case NAND_CTL_SETALE:
-			MACRO_NAND_CTL_SETALE((unsigned long)CFG_NAND0_PADDR);
-			break;
-		case NAND_CTL_CLRALE:
-			MACRO_NAND_CTL_CLRALE((unsigned long)CFG_NAND0_PADDR);
-			break;
-		case NAND_CTL_SETNCE:
-			MACRO_NAND_ENABLE_CE((unsigned long)CFG_NAND0_PADDR);
-			break;
-		case NAND_CTL_CLRNCE:
-			MACRO_NAND_DISABLE_CE((unsigned long)CFG_NAND0_PADDR);
-			break;
-		}
-	}
-	if (cmd != NAND_CMD_NONE)
-		writeb(cmd, chip->IO_ADDR_W);
-}
-
-static void ppchameleonevb_hwcontrol(struct mtd_info *mtdinfo, int cmd,
-				     unsigned int ctrl)
-{
-	struct nand_chip *chip = mtd->priv;
-
-	if (ctrl & NAND_CTRL_CHANGE) {
-#error Missing headerfiles. No way to fix this. -tglx
-		switch (cmd) {
-		case NAND_CTL_SETCLE:
-			MACRO_NAND_CTL_SETCLE((unsigned long)CFG_NAND1_PADDR);
-			break;
-		case NAND_CTL_CLRCLE:
-			MACRO_NAND_CTL_CLRCLE((unsigned long)CFG_NAND1_PADDR);
-			break;
-		case NAND_CTL_SETALE:
-			MACRO_NAND_CTL_SETALE((unsigned long)CFG_NAND1_PADDR);
-			break;
-		case NAND_CTL_CLRALE:
-			MACRO_NAND_CTL_CLRALE((unsigned long)CFG_NAND1_PADDR);
-			break;
-		case NAND_CTL_SETNCE:
-			MACRO_NAND_ENABLE_CE((unsigned long)CFG_NAND1_PADDR);
-			break;
-		case NAND_CTL_CLRNCE:
-			MACRO_NAND_DISABLE_CE((unsigned long)CFG_NAND1_PADDR);
-			break;
-		}
-	}
-	if (cmd != NAND_CMD_NONE)
-		writeb(cmd, chip->IO_ADDR_W);
-}
-
-#ifdef USE_READY_BUSY_PIN
-/*
- *	read device ready pin
- */
-static int ppchameleon_device_ready(struct mtd_info *minfo)
-{
-	if (in_be32((volatile unsigned *)GPIO0_IR) & NAND_RB_GPIO_PIN)
-		return 1;
-	return 0;
-}
-
-static int ppchameleonevb_device_ready(struct mtd_info *minfo)
-{
-	if (in_be32((volatile unsigned *)GPIO0_IR) & NAND_EVB_RB_GPIO_PIN)
-		return 1;
-	return 0;
-}
-#endif
-
-/*
- * Main initialization routine
- */
-static int __init ppchameleonevb_init(void)
-{
-	struct nand_chip *this;
-	void __iomem *ppchameleon_fio_base;
-	void __iomem *ppchameleonevb_fio_base;
-
-	/*********************************
-	* Processor module NAND (if any) *
-	*********************************/
-	/* Allocate memory for MTD device structure and private data */
-	ppchameleon_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
-	if (!ppchameleon_mtd) {
-		printk("Unable to allocate PPChameleon NAND MTD device structure.\n");
-		return -ENOMEM;
-	}
-
-	/* map physical address */
-	ppchameleon_fio_base = ioremap(ppchameleon_fio_pbase, SZ_4M);
-	if (!ppchameleon_fio_base) {
-		printk("ioremap PPChameleon NAND flash failed\n");
-		kfree(ppchameleon_mtd);
-		return -EIO;
-	}
-
-	/* Get pointer to private data */
-	this = (struct nand_chip *)(&ppchameleon_mtd[1]);
-
-	/* Initialize structures */
-	memset(ppchameleon_mtd, 0, sizeof(struct mtd_info));
-	memset(this, 0, sizeof(struct nand_chip));
-
-	/* Link the private data with the MTD structure */
-	ppchameleon_mtd->priv = this;
-	ppchameleon_mtd->owner = THIS_MODULE;
-
-	/* Initialize GPIOs */
-	/* Pin mapping for NAND chip */
-	/*
-	   CE   GPIO_01
-	   CLE  GPIO_02
-	   ALE  GPIO_03
-	   R/B  GPIO_04
-	 */
-	/* output select */
-	out_be32((volatile unsigned *)GPIO0_OSRH, in_be32((volatile unsigned *)GPIO0_OSRH) & 0xC0FFFFFF);
-	/* three-state select */
-	out_be32((volatile unsigned *)GPIO0_TSRH, in_be32((volatile unsigned *)GPIO0_TSRH) & 0xC0FFFFFF);
-	/* enable output driver */
-	out_be32((volatile unsigned *)GPIO0_TCR,
-		 in_be32((volatile unsigned *)GPIO0_TCR) | NAND_nCE_GPIO_PIN | NAND_CLE_GPIO_PIN | NAND_ALE_GPIO_PIN);
-#ifdef USE_READY_BUSY_PIN
-	/* three-state select */
-	out_be32((volatile unsigned *)GPIO0_TSRH, in_be32((volatile unsigned *)GPIO0_TSRH) & 0xFF3FFFFF);
-	/* high-impedecence */
-	out_be32((volatile unsigned *)GPIO0_TCR, in_be32((volatile unsigned *)GPIO0_TCR) & (~NAND_RB_GPIO_PIN));
-	/* input select */
-	out_be32((volatile unsigned *)GPIO0_ISR1H,
-		 (in_be32((volatile unsigned *)GPIO0_ISR1H) & 0xFF3FFFFF) | 0x00400000);
-#endif
-
-	/* insert callbacks */
-	this->IO_ADDR_R = ppchameleon_fio_base;
-	this->IO_ADDR_W = ppchameleon_fio_base;
-	this->cmd_ctrl = ppchameleon_hwcontrol;
-#ifdef USE_READY_BUSY_PIN
-	this->dev_ready = ppchameleon_device_ready;
-#endif
-	this->chip_delay = NAND_BIG_DELAY_US;
-	/* ECC mode */
-	this->ecc.mode = NAND_ECC_SOFT;
-
-	/* Scan to find existence of the device (it could not be mounted) */
-	if (nand_scan(ppchameleon_mtd, 1)) {
-		iounmap((void *)ppchameleon_fio_base);
-		ppchameleon_fio_base = NULL;
-		kfree(ppchameleon_mtd);
-		goto nand_evb_init;
-	}
-#ifndef USE_READY_BUSY_PIN
-	/* Adjust delay if necessary */
-	if (ppchameleon_mtd->size == NAND_SMALL_SIZE)
-		this->chip_delay = NAND_SMALL_DELAY_US;
-#endif
-
-	ppchameleon_mtd->name = "ppchameleon-nand";
-
-	/* Register the partitions */
-	mtd_device_parse_register(ppchameleon_mtd, NULL, NULL,
-				  ppchameleon_mtd->size == NAND_SMALL_SIZE ?
-					partition_info_me : partition_info_hi,
-				  NUM_PARTITIONS);
-
- nand_evb_init:
-	/****************************
-	* EVB NAND (always present) *
-	****************************/
-	/* Allocate memory for MTD device structure and private data */
-	ppchameleonevb_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
-	if (!ppchameleonevb_mtd) {
-		printk("Unable to allocate PPChameleonEVB NAND MTD device structure.\n");
-		if (ppchameleon_fio_base)
-			iounmap(ppchameleon_fio_base);
-		return -ENOMEM;
-	}
-
-	/* map physical address */
-	ppchameleonevb_fio_base = ioremap(ppchameleonevb_fio_pbase, SZ_4M);
-	if (!ppchameleonevb_fio_base) {
-		printk("ioremap PPChameleonEVB NAND flash failed\n");
-		kfree(ppchameleonevb_mtd);
-		if (ppchameleon_fio_base)
-			iounmap(ppchameleon_fio_base);
-		return -EIO;
-	}
-
-	/* Get pointer to private data */
-	this = (struct nand_chip *)(&ppchameleonevb_mtd[1]);
-
-	/* Initialize structures */
-	memset(ppchameleonevb_mtd, 0, sizeof(struct mtd_info));
-	memset(this, 0, sizeof(struct nand_chip));
-
-	/* Link the private data with the MTD structure */
-	ppchameleonevb_mtd->priv = this;
-
-	/* Initialize GPIOs */
-	/* Pin mapping for NAND chip */
-	/*
-	   CE   GPIO_14
-	   CLE  GPIO_15
-	   ALE  GPIO_16
-	   R/B  GPIO_31
-	 */
-	/* output select */
-	out_be32((volatile unsigned *)GPIO0_OSRH, in_be32((volatile unsigned *)GPIO0_OSRH) & 0xFFFFFFF0);
-	out_be32((volatile unsigned *)GPIO0_OSRL, in_be32((volatile unsigned *)GPIO0_OSRL) & 0x3FFFFFFF);
-	/* three-state select */
-	out_be32((volatile unsigned *)GPIO0_TSRH, in_be32((volatile unsigned *)GPIO0_TSRH) & 0xFFFFFFF0);
-	out_be32((volatile unsigned *)GPIO0_TSRL, in_be32((volatile unsigned *)GPIO0_TSRL) & 0x3FFFFFFF);
-	/* enable output driver */
-	out_be32((volatile unsigned *)GPIO0_TCR, in_be32((volatile unsigned *)GPIO0_TCR) | NAND_EVB_nCE_GPIO_PIN |
-		 NAND_EVB_CLE_GPIO_PIN | NAND_EVB_ALE_GPIO_PIN);
-#ifdef USE_READY_BUSY_PIN
-	/* three-state select */
-	out_be32((volatile unsigned *)GPIO0_TSRL, in_be32((volatile unsigned *)GPIO0_TSRL) & 0xFFFFFFFC);
-	/* high-impedecence */
-	out_be32((volatile unsigned *)GPIO0_TCR, in_be32((volatile unsigned *)GPIO0_TCR) & (~NAND_EVB_RB_GPIO_PIN));
-	/* input select */
-	out_be32((volatile unsigned *)GPIO0_ISR1L,
-		 (in_be32((volatile unsigned *)GPIO0_ISR1L) & 0xFFFFFFFC) | 0x00000001);
-#endif
-
-	/* insert callbacks */
-	this->IO_ADDR_R = ppchameleonevb_fio_base;
-	this->IO_ADDR_W = ppchameleonevb_fio_base;
-	this->cmd_ctrl = ppchameleonevb_hwcontrol;
-#ifdef USE_READY_BUSY_PIN
-	this->dev_ready = ppchameleonevb_device_ready;
-#endif
-	this->chip_delay = NAND_SMALL_DELAY_US;
-
-	/* ECC mode */
-	this->ecc.mode = NAND_ECC_SOFT;
-
-	/* Scan to find existence of the device */
-	if (nand_scan(ppchameleonevb_mtd, 1)) {
-		iounmap((void *)ppchameleonevb_fio_base);
-		kfree(ppchameleonevb_mtd);
-		if (ppchameleon_fio_base)
-			iounmap(ppchameleon_fio_base);
-		return -ENXIO;
-	}
-
-	ppchameleonevb_mtd->name = NAND_EVB_MTD_NAME;
-
-	/* Register the partitions */
-	mtd_device_parse_register(ppchameleonevb_mtd, NULL, NULL,
-				  ppchameleon_mtd->size == NAND_SMALL_SIZE ?
-				  partition_info_me : partition_info_hi,
-				  NUM_PARTITIONS);
-
-	/* Return happy */
-	return 0;
-}
-
-module_init(ppchameleonevb_init);
-
-/*
- * Clean up routine
- */
-static void __exit ppchameleonevb_cleanup(void)
-{
-	struct nand_chip *this;
-
-	/* Release resources, unregister device(s) */
-	nand_release(ppchameleon_mtd);
-	nand_release(ppchameleonevb_mtd);
-
-	/* Release iomaps */
-	this = (struct nand_chip *) &ppchameleon_mtd[1];
-	iounmap((void *) this->IO_ADDR_R);
-	this = (struct nand_chip *) &ppchameleonevb_mtd[1];
-	iounmap((void *) this->IO_ADDR_R);
-
-	/* Free the MTD device structure */
-	kfree (ppchameleon_mtd);
-	kfree (ppchameleonevb_mtd);
-}
-module_exit(ppchameleonevb_cleanup);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("DAVE Srl <support-ppchameleon@dave-tech.it>");
-MODULE_DESCRIPTION("MTD map driver for DAVE Srl PPChameleonEVB board");
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 37ee75c..dec80ca 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -989,7 +989,7 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
 	}
 
 	pxa3xx_flash_ids[0].name = f->name;
-	pxa3xx_flash_ids[0].id = (f->chip_id >> 8) & 0xffff;
+	pxa3xx_flash_ids[0].dev_id = (f->chip_id >> 8) & 0xffff;
 	pxa3xx_flash_ids[0].pagesize = f->page_size;
 	chipsize = (uint64_t)f->num_blocks * f->page_per_block * f->page_size;
 	pxa3xx_flash_ids[0].chipsize = chipsize >> 20;
diff --git a/drivers/mtd/nand/rtc_from4.c b/drivers/mtd/nand/rtc_from4.c
deleted file mode 100644
index e55b5cf..0000000
--- a/drivers/mtd/nand/rtc_from4.c
+++ /dev/null
@@ -1,624 +0,0 @@
-/*
- *  drivers/mtd/nand/rtc_from4.c
- *
- *  Copyright (C) 2004  Red Hat, Inc.
- *
- *  Derived from drivers/mtd/nand/spia.c
- *       Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.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.
- *
- * Overview:
- *   This is a device driver for the AG-AND flash device found on the
- *   Renesas Technology Corp. Flash ROM 4-slot interface board (FROM_BOARD4),
- *   which utilizes the Renesas HN29V1G91T-30 part.
- *   This chip is a 1 GBibit (128MiB x 8 bits) AG-AND flash device.
- */
-
-#include <linux/delay.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/rslib.h>
-#include <linux/bitrev.h>
-#include <linux/module.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
-#include <linux/mtd/partitions.h>
-#include <asm/io.h>
-
-/*
- * MTD structure for Renesas board
- */
-static struct mtd_info *rtc_from4_mtd = NULL;
-
-#define RTC_FROM4_MAX_CHIPS	2
-
-/* HS77x9 processor register defines */
-#define SH77X9_BCR1	((volatile unsigned short *)(0xFFFFFF60))
-#define SH77X9_BCR2	((volatile unsigned short *)(0xFFFFFF62))
-#define SH77X9_WCR1	((volatile unsigned short *)(0xFFFFFF64))
-#define SH77X9_WCR2	((volatile unsigned short *)(0xFFFFFF66))
-#define SH77X9_MCR	((volatile unsigned short *)(0xFFFFFF68))
-#define SH77X9_PCR	((volatile unsigned short *)(0xFFFFFF6C))
-#define SH77X9_FRQCR	((volatile unsigned short *)(0xFFFFFF80))
-
-/*
- * Values specific to the Renesas Technology Corp. FROM_BOARD4 (used with HS77x9 processor)
- */
-/* Address where flash is mapped */
-#define RTC_FROM4_FIO_BASE	0x14000000
-
-/* CLE and ALE are tied to address lines 5 & 4, respectively */
-#define RTC_FROM4_CLE		(1 << 5)
-#define RTC_FROM4_ALE		(1 << 4)
-
-/* address lines A24-A22 used for chip selection */
-#define RTC_FROM4_NAND_ADDR_SLOT3	(0x00800000)
-#define RTC_FROM4_NAND_ADDR_SLOT4	(0x00C00000)
-#define RTC_FROM4_NAND_ADDR_FPGA	(0x01000000)
-/* mask address lines A24-A22 used for chip selection */
-#define RTC_FROM4_NAND_ADDR_MASK	(RTC_FROM4_NAND_ADDR_SLOT3 | RTC_FROM4_NAND_ADDR_SLOT4 | RTC_FROM4_NAND_ADDR_FPGA)
-
-/* FPGA status register for checking device ready (bit zero) */
-#define RTC_FROM4_FPGA_SR		(RTC_FROM4_NAND_ADDR_FPGA | 0x00000002)
-#define RTC_FROM4_DEVICE_READY		0x0001
-
-/* FPGA Reed-Solomon ECC Control register */
-
-#define RTC_FROM4_RS_ECC_CTL		(RTC_FROM4_NAND_ADDR_FPGA | 0x00000050)
-#define RTC_FROM4_RS_ECC_CTL_CLR	(1 << 7)
-#define RTC_FROM4_RS_ECC_CTL_GEN	(1 << 6)
-#define RTC_FROM4_RS_ECC_CTL_FD_E	(1 << 5)
-
-/* FPGA Reed-Solomon ECC code base */
-#define RTC_FROM4_RS_ECC		(RTC_FROM4_NAND_ADDR_FPGA | 0x00000060)
-#define RTC_FROM4_RS_ECCN		(RTC_FROM4_NAND_ADDR_FPGA | 0x00000080)
-
-/* FPGA Reed-Solomon ECC check register */
-#define RTC_FROM4_RS_ECC_CHK		(RTC_FROM4_NAND_ADDR_FPGA | 0x00000070)
-#define RTC_FROM4_RS_ECC_CHK_ERROR	(1 << 7)
-
-#define ERR_STAT_ECC_AVAILABLE		0x20
-
-/* Undefine for software ECC */
-#define RTC_FROM4_HWECC	1
-
-/* Define as 1 for no virtual erase blocks (in JFFS2) */
-#define RTC_FROM4_NO_VIRTBLOCKS	0
-
-/*
- * Module stuff
- */
-static void __iomem *rtc_from4_fio_base = (void *)P2SEGADDR(RTC_FROM4_FIO_BASE);
-
-static const struct mtd_partition partition_info[] = {
-	{
-	 .name = "Renesas flash partition 1",
-	 .offset = 0,
-	 .size = MTDPART_SIZ_FULL},
-};
-
-#define NUM_PARTITIONS 1
-
-/*
- *	hardware specific flash bbt decriptors
- *	Note: this is to allow debugging by disabling
- *		NAND_BBT_CREATE and/or NAND_BBT_WRITE
- *
- */
-static uint8_t bbt_pattern[] = { 'B', 'b', 't', '0' };
-static uint8_t mirror_pattern[] = { '1', 't', 'b', 'B' };
-
-static struct nand_bbt_descr rtc_from4_bbt_main_descr = {
-	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
-		| NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
-	.offs = 40,
-	.len = 4,
-	.veroffs = 44,
-	.maxblocks = 4,
-	.pattern = bbt_pattern
-};
-
-static struct nand_bbt_descr rtc_from4_bbt_mirror_descr = {
-	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
-		| NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
-	.offs = 40,
-	.len = 4,
-	.veroffs = 44,
-	.maxblocks = 4,
-	.pattern = mirror_pattern
-};
-
-#ifdef RTC_FROM4_HWECC
-
-/* the Reed Solomon control structure */
-static struct rs_control *rs_decoder;
-
-/*
- *      hardware specific Out Of Band information
- */
-static struct nand_ecclayout rtc_from4_nand_oobinfo = {
-	.eccbytes = 32,
-	.eccpos = {
-		   0, 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},
-	.oobfree = {{32, 32}}
-};
-
-#endif
-
-/*
- * rtc_from4_hwcontrol - hardware specific access to control-lines
- * @mtd:	MTD device structure
- * @cmd:	hardware control command
- *
- * Address lines (A5 and A4) are used to control Command and Address Latch
- * Enable on this board, so set the read/write address appropriately.
- *
- * Chip Enable is also controlled by the Chip Select (CS5) and
- * Address lines (A24-A22), so no action is required here.
- *
- */
-static void rtc_from4_hwcontrol(struct mtd_info *mtd, int cmd,
-				unsigned int ctrl)
-{
-	struct nand_chip *chip = (mtd->priv);
-
-	if (cmd == NAND_CMD_NONE)
-		return;
-
-	if (ctrl & NAND_CLE)
-		writeb(cmd, chip->IO_ADDR_W | RTC_FROM4_CLE);
-	else
-		writeb(cmd, chip->IO_ADDR_W | RTC_FROM4_ALE);
-}
-
-/*
- * rtc_from4_nand_select_chip - hardware specific chip select
- * @mtd:	MTD device structure
- * @chip:	Chip to select (0 == slot 3, 1 == slot 4)
- *
- * The chip select is based on address lines A24-A22.
- * This driver uses flash slots 3 and 4 (A23-A22).
- *
- */
-static void rtc_from4_nand_select_chip(struct mtd_info *mtd, int chip)
-{
-	struct nand_chip *this = mtd->priv;
-
-	this->IO_ADDR_R = (void __iomem *)((unsigned long)this->IO_ADDR_R & ~RTC_FROM4_NAND_ADDR_MASK);
-	this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W & ~RTC_FROM4_NAND_ADDR_MASK);
-
-	switch (chip) {
-
-	case 0:		/* select slot 3 chip */
-		this->IO_ADDR_R = (void __iomem *)((unsigned long)this->IO_ADDR_R | RTC_FROM4_NAND_ADDR_SLOT3);
-		this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W | RTC_FROM4_NAND_ADDR_SLOT3);
-		break;
-	case 1:		/* select slot 4 chip */
-		this->IO_ADDR_R = (void __iomem *)((unsigned long)this->IO_ADDR_R | RTC_FROM4_NAND_ADDR_SLOT4);
-		this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W | RTC_FROM4_NAND_ADDR_SLOT4);
-		break;
-
-	}
-}
-
-/*
- * rtc_from4_nand_device_ready - hardware specific ready/busy check
- * @mtd:	MTD device structure
- *
- * This board provides the Ready/Busy state in the status register
- * of the FPGA.  Bit zero indicates the RDY(1)/BSY(0) signal.
- *
- */
-static int rtc_from4_nand_device_ready(struct mtd_info *mtd)
-{
-	unsigned short status;
-
-	status = *((volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_FPGA_SR));
-
-	return (status & RTC_FROM4_DEVICE_READY);
-
-}
-
-/*
- * deplete - code to perform device recovery in case there was a power loss
- * @mtd:	MTD device structure
- * @chip:	Chip to select (0 == slot 3, 1 == slot 4)
- *
- * If there was a sudden loss of power during an erase operation, a
- * "device recovery" operation must be performed when power is restored
- * to ensure correct operation.  This routine performs the required steps
- * for the requested chip.
- *
- * See page 86 of the data sheet for details.
- *
- */
-static void deplete(struct mtd_info *mtd, int chip)
-{
-	struct nand_chip *this = mtd->priv;
-
-	/* wait until device is ready */
-	while (!this->dev_ready(mtd)) ;
-
-	this->select_chip(mtd, chip);
-
-	/* Send the commands for device recovery, phase 1 */
-	this->cmdfunc(mtd, NAND_CMD_DEPLETE1, 0x0000, 0x0000);
-	this->cmdfunc(mtd, NAND_CMD_DEPLETE2, -1, -1);
-
-	/* Send the commands for device recovery, phase 2 */
-	this->cmdfunc(mtd, NAND_CMD_DEPLETE1, 0x0000, 0x0004);
-	this->cmdfunc(mtd, NAND_CMD_DEPLETE2, -1, -1);
-
-}
-
-#ifdef RTC_FROM4_HWECC
-/*
- * rtc_from4_enable_hwecc - hardware specific hardware ECC enable function
- * @mtd:	MTD device structure
- * @mode:	I/O mode; read or write
- *
- * enable hardware ECC for data read or write
- *
- */
-static void rtc_from4_enable_hwecc(struct mtd_info *mtd, int mode)
-{
-	volatile unsigned short *rs_ecc_ctl = (volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_RS_ECC_CTL);
-	unsigned short status;
-
-	switch (mode) {
-	case NAND_ECC_READ:
-		status = RTC_FROM4_RS_ECC_CTL_CLR | RTC_FROM4_RS_ECC_CTL_FD_E;
-
-		*rs_ecc_ctl = status;
-		break;
-
-	case NAND_ECC_READSYN:
-		status = 0x00;
-
-		*rs_ecc_ctl = status;
-		break;
-
-	case NAND_ECC_WRITE:
-		status = RTC_FROM4_RS_ECC_CTL_CLR | RTC_FROM4_RS_ECC_CTL_GEN | RTC_FROM4_RS_ECC_CTL_FD_E;
-
-		*rs_ecc_ctl = status;
-		break;
-
-	default:
-		BUG();
-		break;
-	}
-
-}
-
-/*
- * rtc_from4_calculate_ecc - hardware specific code to read ECC code
- * @mtd:	MTD device structure
- * @dat:	buffer containing the data to generate ECC codes
- * @ecc_code	ECC codes calculated
- *
- * The ECC code is calculated by the FPGA.  All we have to do is read the values
- * from the FPGA registers.
- *
- * Note: We read from the inverted registers, since data is inverted before
- * the code is calculated. So all 0xff data (blank page) results in all 0xff rs code
- *
- */
-static void rtc_from4_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)
-{
-	volatile unsigned short *rs_eccn = (volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_RS_ECCN);
-	unsigned short value;
-	int i;
-
-	for (i = 0; i < 8; i++) {
-		value = *rs_eccn;
-		ecc_code[i] = (unsigned char)value;
-		rs_eccn++;
-	}
-	ecc_code[7] |= 0x0f;	/* set the last four bits (not used) */
-}
-
-/*
- * rtc_from4_correct_data - hardware specific code to correct data using ECC code
- * @mtd:	MTD device structure
- * @buf:	buffer containing the data to generate ECC codes
- * @ecc1	ECC codes read
- * @ecc2	ECC codes calculated
- *
- * The FPGA tells us fast, if there's an error or not. If no, we go back happy
- * else we read the ecc results from the fpga and call the rs library to decode
- * and hopefully correct the error.
- *
- */
-static int rtc_from4_correct_data(struct mtd_info *mtd, const u_char *buf, u_char *ecc1, u_char *ecc2)
-{
-	int i, j, res;
-	unsigned short status;
-	uint16_t par[6], syn[6];
-	uint8_t ecc[8];
-	volatile unsigned short *rs_ecc;
-
-	status = *((volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_RS_ECC_CHK));
-
-	if (!(status & RTC_FROM4_RS_ECC_CHK_ERROR)) {
-		return 0;
-	}
-
-	/* Read the syndrome pattern from the FPGA and correct the bitorder */
-	rs_ecc = (volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_RS_ECC);
-	for (i = 0; i < 8; i++) {
-		ecc[i] = bitrev8(*rs_ecc);
-		rs_ecc++;
-	}
-
-	/* convert into 6 10bit syndrome fields */
-	par[5] = rs_decoder->index_of[(((uint16_t) ecc[0] >> 0) & 0x0ff) | (((uint16_t) ecc[1] << 8) & 0x300)];
-	par[4] = rs_decoder->index_of[(((uint16_t) ecc[1] >> 2) & 0x03f) | (((uint16_t) ecc[2] << 6) & 0x3c0)];
-	par[3] = rs_decoder->index_of[(((uint16_t) ecc[2] >> 4) & 0x00f) | (((uint16_t) ecc[3] << 4) & 0x3f0)];
-	par[2] = rs_decoder->index_of[(((uint16_t) ecc[3] >> 6) & 0x003) | (((uint16_t) ecc[4] << 2) & 0x3fc)];
-	par[1] = rs_decoder->index_of[(((uint16_t) ecc[5] >> 0) & 0x0ff) | (((uint16_t) ecc[6] << 8) & 0x300)];
-	par[0] = (((uint16_t) ecc[6] >> 2) & 0x03f) | (((uint16_t) ecc[7] << 6) & 0x3c0);
-
-	/* Convert to computable syndrome */
-	for (i = 0; i < 6; i++) {
-		syn[i] = par[0];
-		for (j = 1; j < 6; j++)
-			if (par[j] != rs_decoder->nn)
-				syn[i] ^= rs_decoder->alpha_to[rs_modnn(rs_decoder, par[j] + i * j)];
-
-		/* Convert to index form */
-		syn[i] = rs_decoder->index_of[syn[i]];
-	}
-
-	/* Let the library code do its magic. */
-	res = decode_rs8(rs_decoder, (uint8_t *) buf, par, 512, syn, 0, NULL, 0xff, NULL);
-	if (res > 0) {
-		pr_debug("rtc_from4_correct_data: " "ECC corrected %d errors on read\n", res);
-	}
-	return res;
-}
-
-/**
- * rtc_from4_errstat - perform additional error status checks
- * @mtd:	MTD device structure
- * @this:	NAND chip structure
- * @state:	state or the operation
- * @status:	status code returned from read status
- * @page:	startpage inside the chip, must be called with (page & this->pagemask)
- *
- * Perform additional error status checks on erase and write failures
- * to determine if errors are correctable.  For this device, correctable
- * 1-bit errors on erase and write are considered acceptable.
- *
- * note: see pages 34..37 of data sheet for details.
- *
- */
-static int rtc_from4_errstat(struct mtd_info *mtd, struct nand_chip *this,
-			     int state, int status, int page)
-{
-	int er_stat = 0;
-	int rtn, retlen;
-	size_t len;
-	uint8_t *buf;
-	int i;
-
-	this->cmdfunc(mtd, NAND_CMD_STATUS_CLEAR, -1, -1);
-
-	if (state == FL_ERASING) {
-
-		for (i = 0; i < 4; i++) {
-			if (!(status & 1 << (i + 1)))
-				continue;
-			this->cmdfunc(mtd, (NAND_CMD_STATUS_ERROR + i + 1),
-				      -1, -1);
-			rtn = this->read_byte(mtd);
-			this->cmdfunc(mtd, NAND_CMD_STATUS_RESET, -1, -1);
-
-			/* err_ecc_not_avail */
-			if (!(rtn & ERR_STAT_ECC_AVAILABLE))
-				er_stat |= 1 << (i + 1);
-		}
-
-	} else if (state == FL_WRITING) {
-
-		unsigned long corrected = mtd->ecc_stats.corrected;
-
-		/* single bank write logic */
-		this->cmdfunc(mtd, NAND_CMD_STATUS_ERROR, -1, -1);
-		rtn = this->read_byte(mtd);
-		this->cmdfunc(mtd, NAND_CMD_STATUS_RESET, -1, -1);
-
-		if (!(rtn & ERR_STAT_ECC_AVAILABLE)) {
-			/* err_ecc_not_avail */
-			er_stat |= 1 << 1;
-			goto out;
-		}
-
-		len = mtd->writesize;
-		buf = kmalloc(len, GFP_KERNEL);
-		if (!buf) {
-			er_stat = 1;
-			goto out;
-		}
-
-		/* recovery read */
-		rtn = nand_do_read(mtd, page, len, &retlen, buf);
-
-		/* if read failed or > 1-bit error corrected */
-		if (rtn || (mtd->ecc_stats.corrected - corrected) > 1)
-			er_stat |= 1 << 1;
-		kfree(buf);
-	}
-out:
-	rtn = status;
-	if (er_stat == 0) {	/* if ECC is available   */
-		rtn = (status & ~NAND_STATUS_FAIL);	/*   clear the error bit */
-	}
-
-	return rtn;
-}
-#endif
-
-/*
- * Main initialization routine
- */
-static int __init rtc_from4_init(void)
-{
-	struct nand_chip *this;
-	unsigned short bcr1, bcr2, wcr2;
-	int i;
-	int ret;
-
-	/* Allocate memory for MTD device structure and private data */
-	rtc_from4_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
-	if (!rtc_from4_mtd) {
-		printk("Unable to allocate Renesas NAND MTD device structure.\n");
-		return -ENOMEM;
-	}
-
-	/* Get pointer to private data */
-	this = (struct nand_chip *)(&rtc_from4_mtd[1]);
-
-	/* Initialize structures */
-	memset(rtc_from4_mtd, 0, sizeof(struct mtd_info));
-	memset(this, 0, sizeof(struct nand_chip));
-
-	/* Link the private data with the MTD structure */
-	rtc_from4_mtd->priv = this;
-	rtc_from4_mtd->owner = THIS_MODULE;
-
-	/* set area 5 as PCMCIA mode to clear the spec of tDH(Data hold time;9ns min) */
-	bcr1 = *SH77X9_BCR1 & ~0x0002;
-	bcr1 |= 0x0002;
-	*SH77X9_BCR1 = bcr1;
-
-	/* set */
-	bcr2 = *SH77X9_BCR2 & ~0x0c00;
-	bcr2 |= 0x0800;
-	*SH77X9_BCR2 = bcr2;
-
-	/* set area 5 wait states */
-	wcr2 = *SH77X9_WCR2 & ~0x1c00;
-	wcr2 |= 0x1c00;
-	*SH77X9_WCR2 = wcr2;
-
-	/* Set address of NAND IO lines */
-	this->IO_ADDR_R = rtc_from4_fio_base;
-	this->IO_ADDR_W = rtc_from4_fio_base;
-	/* Set address of hardware control function */
-	this->cmd_ctrl = rtc_from4_hwcontrol;
-	/* Set address of chip select function */
-	this->select_chip = rtc_from4_nand_select_chip;
-	/* command delay time (in us) */
-	this->chip_delay = 100;
-	/* return the status of the Ready/Busy line */
-	this->dev_ready = rtc_from4_nand_device_ready;
-
-#ifdef RTC_FROM4_HWECC
-	printk(KERN_INFO "rtc_from4_init: using hardware ECC detection.\n");
-
-	this->ecc.mode = NAND_ECC_HW_SYNDROME;
-	this->ecc.size = 512;
-	this->ecc.bytes = 8;
-	this->ecc.strength = 3;
-	/* return the status of extra status and ECC checks */
-	this->errstat = rtc_from4_errstat;
-	/* set the nand_oobinfo to support FPGA H/W error detection */
-	this->ecc.layout = &rtc_from4_nand_oobinfo;
-	this->ecc.hwctl = rtc_from4_enable_hwecc;
-	this->ecc.calculate = rtc_from4_calculate_ecc;
-	this->ecc.correct = rtc_from4_correct_data;
-
-	/* We could create the decoder on demand, if memory is a concern.
-	 * This way we have it handy, if an error happens
-	 *
-	 * Symbolsize is 10 (bits)
-	 * Primitve polynomial is x^10+x^3+1
-	 * first consecutive root is 0
-	 * primitve element to generate roots = 1
-	 * generator polinomial degree = 6
-	 */
-	rs_decoder = init_rs(10, 0x409, 0, 1, 6);
-	if (!rs_decoder) {
-		printk(KERN_ERR "Could not create a RS decoder\n");
-		ret = -ENOMEM;
-		goto err_1;
-	}
-#else
-	printk(KERN_INFO "rtc_from4_init: using software ECC detection.\n");
-
-	this->ecc.mode = NAND_ECC_SOFT;
-#endif
-
-	/* set the bad block tables to support debugging */
-	this->bbt_td = &rtc_from4_bbt_main_descr;
-	this->bbt_md = &rtc_from4_bbt_mirror_descr;
-
-	/* Scan to find existence of the device */
-	if (nand_scan(rtc_from4_mtd, RTC_FROM4_MAX_CHIPS)) {
-		ret = -ENXIO;
-		goto err_2;
-	}
-
-	/* Perform 'device recovery' for each chip in case there was a power loss. */
-	for (i = 0; i < this->numchips; i++) {
-		deplete(rtc_from4_mtd, i);
-	}
-
-#if RTC_FROM4_NO_VIRTBLOCKS
-	/* use a smaller erase block to minimize wasted space when a block is bad */
-	/* note: this uses eight times as much RAM as using the default and makes */
-	/*       mounts take four times as long. */
-	rtc_from4_mtd->flags |= MTD_NO_VIRTBLOCKS;
-#endif
-
-	/* Register the partitions */
-	ret = mtd_device_register(rtc_from4_mtd, partition_info,
-				  NUM_PARTITIONS);
-	if (ret)
-		goto err_3;
-
-	/* Return happy */
-	return 0;
-err_3:
-	nand_release(rtc_from4_mtd);
-err_2:
-	free_rs(rs_decoder);
-err_1:
-	kfree(rtc_from4_mtd);
-	return ret;
-}
-
-module_init(rtc_from4_init);
-
-/*
- * Clean up routine
- */
-static void __exit rtc_from4_cleanup(void)
-{
-	/* Release resource, unregister partitions */
-	nand_release(rtc_from4_mtd);
-
-	/* Free the MTD device structure */
-	kfree(rtc_from4_mtd);
-
-#ifdef RTC_FROM4_HWECC
-	/* Free the reed solomon resources */
-	if (rs_decoder) {
-		free_rs(rs_decoder);
-	}
-#endif
-}
-
-module_exit(rtc_from4_cleanup);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("d.marlin <dmarlin@redhat.com");
-MODULE_DESCRIPTION("Board-specific glue layer for AG-AND flash on Renesas FROM_BOARD4");
diff --git a/drivers/mtd/nand/sh_flctl.c b/drivers/mtd/nand/sh_flctl.c
index 57b3971..e57e18e 100644
--- a/drivers/mtd/nand/sh_flctl.c
+++ b/drivers/mtd/nand/sh_flctl.c
@@ -1081,7 +1081,6 @@ static struct sh_flctl_platform_data *flctl_parse_dt(struct device *dev)
 	return pdata;
 }
 #else /* CONFIG_OF */
-#define of_flctl_match NULL
 static struct sh_flctl_platform_data *flctl_parse_dt(struct device *dev)
 {
 	return NULL;
@@ -1219,22 +1218,11 @@ static struct platform_driver flctl_driver = {
 	.driver = {
 		.name	= "sh_flctl",
 		.owner	= THIS_MODULE,
-		.of_match_table = of_flctl_match,
+		.of_match_table = of_match_ptr(of_flctl_match),
 	},
 };
 
-static int __init flctl_nand_init(void)
-{
-	return platform_driver_probe(&flctl_driver, flctl_probe);
-}
-
-static void __exit flctl_nand_cleanup(void)
-{
-	platform_driver_unregister(&flctl_driver);
-}
-
-module_init(flctl_nand_init);
-module_exit(flctl_nand_cleanup);
+module_platform_driver_probe(flctl_driver, flctl_probe);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Yoshihiro Shimoda");
diff --git a/drivers/mtd/nand/sm_common.c b/drivers/mtd/nand/sm_common.c
index 082bcdc..e8181ed 100644
--- a/drivers/mtd/nand/sm_common.c
+++ b/drivers/mtd/nand/sm_common.c
@@ -9,6 +9,7 @@
 #include <linux/kernel.h>
 #include <linux/mtd/nand.h>
 #include <linux/module.h>
+#include <linux/sizes.h>
 #include "sm_common.h"
 
 static struct nand_ecclayout nand_oob_sm = {
@@ -67,44 +68,37 @@ static int sm_block_markbad(struct mtd_info *mtd, loff_t ofs)
 	return error;
 }
 
-
 static struct nand_flash_dev nand_smartmedia_flash_ids[] = {
-	{"SmartMedia 1MiB 5V",          0x6e, 256, 1, 0x1000, 0},
-	{"SmartMedia 1MiB 3,3V",        0xe8, 256, 1, 0x1000, 0},
-	{"SmartMedia 1MiB 3,3V",        0xec, 256, 1, 0x1000, 0},
-	{"SmartMedia 2MiB 3,3V",        0xea, 256, 2, 0x1000, 0},
-	{"SmartMedia 2MiB 5V",          0x64, 256, 2, 0x1000, 0},
-	{"SmartMedia 2MiB 3,3V ROM",    0x5d, 512, 2, 0x2000, NAND_ROM},
-	{"SmartMedia 4MiB 3,3V",        0xe3, 512, 4, 0x2000, 0},
-	{"SmartMedia 4MiB 3,3/5V",      0xe5, 512, 4, 0x2000, 0},
-	{"SmartMedia 4MiB 5V",          0x6b, 512, 4, 0x2000, 0},
-	{"SmartMedia 4MiB 3,3V ROM",    0xd5, 512, 4, 0x2000, NAND_ROM},
-	{"SmartMedia 8MiB 3,3V",        0xe6, 512, 8, 0x2000, 0},
-	{"SmartMedia 8MiB 3,3V ROM",    0xd6, 512, 8, 0x2000, NAND_ROM},
-	{"SmartMedia 16MiB 3,3V",       0x73, 512, 16, 0x4000, 0},
-	{"SmartMedia 16MiB 3,3V ROM",   0x57, 512, 16, 0x4000, NAND_ROM},
-	{"SmartMedia 32MiB 3,3V",       0x75, 512, 32, 0x4000, 0},
-	{"SmartMedia 32MiB 3,3V ROM",   0x58, 512, 32, 0x4000, NAND_ROM},
-	{"SmartMedia 64MiB 3,3V",       0x76, 512, 64, 0x4000, 0},
-	{"SmartMedia 64MiB 3,3V ROM",   0xd9, 512, 64, 0x4000, NAND_ROM},
-	{"SmartMedia 128MiB 3,3V",      0x79, 512, 128, 0x4000, 0},
-	{"SmartMedia 128MiB 3,3V ROM",  0xda, 512, 128, 0x4000, NAND_ROM},
-	{"SmartMedia 256MiB 3,3V",      0x71, 512, 256, 0x4000 },
-	{"SmartMedia 256MiB 3,3V ROM",  0x5b, 512, 256, 0x4000, NAND_ROM},
-	{NULL,}
+	LEGACY_ID_NAND("SmartMedia 2MiB 3,3V ROM",   0x5d, 2,   SZ_8K, NAND_ROM),
+	LEGACY_ID_NAND("SmartMedia 4MiB 3,3V",       0xe3, 4,   SZ_8K, 0),
+	LEGACY_ID_NAND("SmartMedia 4MiB 3,3/5V",     0xe5, 4,   SZ_8K, 0),
+	LEGACY_ID_NAND("SmartMedia 4MiB 5V",         0x6b, 4,   SZ_8K, 0),
+	LEGACY_ID_NAND("SmartMedia 4MiB 3,3V ROM",   0xd5, 4,   SZ_8K, NAND_ROM),
+	LEGACY_ID_NAND("SmartMedia 8MiB 3,3V",       0xe6, 8,   SZ_8K, 0),
+	LEGACY_ID_NAND("SmartMedia 8MiB 3,3V ROM",   0xd6, 8,   SZ_8K, NAND_ROM),
+	LEGACY_ID_NAND("SmartMedia 16MiB 3,3V",      0x73, 16,  SZ_16K, 0),
+	LEGACY_ID_NAND("SmartMedia 16MiB 3,3V ROM",  0x57, 16,  SZ_16K, NAND_ROM),
+	LEGACY_ID_NAND("SmartMedia 32MiB 3,3V",      0x75, 32,  SZ_16K, 0),
+	LEGACY_ID_NAND("SmartMedia 32MiB 3,3V ROM",  0x58, 32,  SZ_16K, NAND_ROM),
+	LEGACY_ID_NAND("SmartMedia 64MiB 3,3V",      0x76, 64,  SZ_16K, 0),
+	LEGACY_ID_NAND("SmartMedia 64MiB 3,3V ROM",  0xd9, 64,  SZ_16K, NAND_ROM),
+	LEGACY_ID_NAND("SmartMedia 128MiB 3,3V",     0x79, 128, SZ_16K, 0),
+	LEGACY_ID_NAND("SmartMedia 128MiB 3,3V ROM", 0xda, 128, SZ_16K, NAND_ROM),
+	LEGACY_ID_NAND("SmartMedia 256MiB 3, 3V",    0x71, 256, SZ_16K, 0),
+	LEGACY_ID_NAND("SmartMedia 256MiB 3,3V ROM", 0x5b, 256, SZ_16K, NAND_ROM),
+	{NULL}
 };
 
 static struct nand_flash_dev nand_xd_flash_ids[] = {
-
-	{"xD 16MiB 3,3V",    0x73, 512, 16, 0x4000, 0},
-	{"xD 32MiB 3,3V",    0x75, 512, 32, 0x4000, 0},
-	{"xD 64MiB 3,3V",    0x76, 512, 64, 0x4000, 0},
-	{"xD 128MiB 3,3V",   0x79, 512, 128, 0x4000, 0},
-	{"xD 256MiB 3,3V",   0x71, 512, 256, 0x4000, NAND_BROKEN_XD},
-	{"xD 512MiB 3,3V",   0xdc, 512, 512, 0x4000, NAND_BROKEN_XD},
-	{"xD 1GiB 3,3V",     0xd3, 512, 1024, 0x4000, NAND_BROKEN_XD},
-	{"xD 2GiB 3,3V",     0xd5, 512, 2048, 0x4000, NAND_BROKEN_XD},
-	{NULL,}
+	LEGACY_ID_NAND("xD 16MiB 3,3V",  0x73, 16,   SZ_16K, 0),
+	LEGACY_ID_NAND("xD 32MiB 3,3V",  0x75, 32,   SZ_16K, 0),
+	LEGACY_ID_NAND("xD 64MiB 3,3V",  0x76, 64,   SZ_16K, 0),
+	LEGACY_ID_NAND("xD 128MiB 3,3V", 0x79, 128,  SZ_16K, 0),
+	LEGACY_ID_NAND("xD 256MiB 3,3V", 0x71, 256,  SZ_16K, NAND_BROKEN_XD),
+	LEGACY_ID_NAND("xD 512MiB 3,3V", 0xdc, 512,  SZ_16K, NAND_BROKEN_XD),
+	LEGACY_ID_NAND("xD 1GiB 3,3V",   0xd3, 1024, SZ_16K, NAND_BROKEN_XD),
+	LEGACY_ID_NAND("xD 2GiB 3,3V",   0xd5, 2048, SZ_16K, NAND_BROKEN_XD),
+	{NULL}
 };
 
 int sm_register_device(struct mtd_info *mtd, int smartmedia)
diff --git a/drivers/mtd/nand/txx9ndfmc.c b/drivers/mtd/nand/txx9ndfmc.c
index e1e8748..7ed654c 100644
--- a/drivers/mtd/nand/txx9ndfmc.c
+++ b/drivers/mtd/nand/txx9ndfmc.c
@@ -427,18 +427,7 @@ static struct platform_driver txx9ndfmc_driver = {
 	},
 };
 
-static int __init txx9ndfmc_init(void)
-{
-	return platform_driver_probe(&txx9ndfmc_driver, txx9ndfmc_probe);
-}
-
-static void __exit txx9ndfmc_exit(void)
-{
-	platform_driver_unregister(&txx9ndfmc_driver);
-}
-
-module_init(txx9ndfmc_init);
-module_exit(txx9ndfmc_exit);
+module_platform_driver_probe(txx9ndfmc_driver, txx9ndfmc_probe);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("TXx9 SoC NAND flash controller driver");
diff --git a/drivers/mtd/ofpart.c b/drivers/mtd/ofpart.c
index 30bd907..553d6d6 100644
--- a/drivers/mtd/ofpart.c
+++ b/drivers/mtd/ofpart.c
@@ -55,6 +55,7 @@ static int parse_ofpart_partitions(struct mtd_info *master,
 	while ((pp = of_get_next_child(node, pp))) {
 		const __be32 *reg;
 		int len;
+		int a_cells, s_cells;
 
 		reg = of_get_property(pp, "reg", &len);
 		if (!reg) {
@@ -62,8 +63,10 @@ static int parse_ofpart_partitions(struct mtd_info *master,
 			continue;
 		}
 
-		(*pparts)[i].offset = be32_to_cpu(reg[0]);
-		(*pparts)[i].size = be32_to_cpu(reg[1]);
+		a_cells = of_n_addr_cells(pp);
+		s_cells = of_n_size_cells(pp);
+		(*pparts)[i].offset = of_read_number(reg, a_cells);
+		(*pparts)[i].size = of_read_number(reg + a_cells, s_cells);
 
 		partname = of_get_property(pp, "label", &len);
 		if (!partname)
diff --git a/drivers/mtd/onenand/Kconfig b/drivers/mtd/onenand/Kconfig
index 91467bb..ab26072 100644
--- a/drivers/mtd/onenand/Kconfig
+++ b/drivers/mtd/onenand/Kconfig
@@ -40,7 +40,6 @@ config MTD_ONENAND_SAMSUNG
 
 config MTD_ONENAND_OTP
 	bool "OneNAND OTP Support"
-	select HAVE_MTD_OTP
 	help
 	  One Block of the NAND Flash Array memory is reserved as
 	  a One-Time Programmable Block memory area.
@@ -68,10 +67,4 @@ config MTD_ONENAND_2X_PROGRAM
 
 	  And more recent chips
 
-config MTD_ONENAND_SIM
-	tristate "OneNAND simulator support"
-	help
-	  The simulator may simulate various OneNAND flash chips for the
-	  OneNAND MTD layer.
-
 endif # MTD_ONENAND
diff --git a/drivers/mtd/onenand/Makefile b/drivers/mtd/onenand/Makefile
index 2b7884c..9d6540e 100644
--- a/drivers/mtd/onenand/Makefile
+++ b/drivers/mtd/onenand/Makefile
@@ -10,7 +10,4 @@ obj-$(CONFIG_MTD_ONENAND_GENERIC)	+= generic.o
 obj-$(CONFIG_MTD_ONENAND_OMAP2)		+= omap2.o
 obj-$(CONFIG_MTD_ONENAND_SAMSUNG)       += samsung.o
 
-# Simulator
-obj-$(CONFIG_MTD_ONENAND_SIM)		+= onenand_sim.o
-
 onenand-objs = onenand_base.o onenand_bbt.o
diff --git a/drivers/mtd/onenand/onenand_sim.c b/drivers/mtd/onenand/onenand_sim.c
deleted file mode 100644
index 85399e3..0000000
--- a/drivers/mtd/onenand/onenand_sim.c
+++ /dev/null
@@ -1,564 +0,0 @@
-/*
- *  linux/drivers/mtd/onenand/onenand_sim.c
- *
- *  The OneNAND simulator
- *
- *  Copyright © 2005-2007 Samsung Electronics
- *  Kyungmin Park <kyungmin.park@samsung.com>
- *
- *  Vishak G <vishak.g at samsung.com>, Rohit Hagargundgi <h.rohit at samsung.com>
- *  Flex-OneNAND simulator support
- *  Copyright (C) Samsung Electronics, 2008
- *
- * This program is free software; you can 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/slab.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/vmalloc.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/partitions.h>
-#include <linux/mtd/onenand.h>
-
-#include <linux/io.h>
-
-#ifndef CONFIG_ONENAND_SIM_MANUFACTURER
-#define CONFIG_ONENAND_SIM_MANUFACTURER         0xec
-#endif
-
-#ifndef CONFIG_ONENAND_SIM_DEVICE_ID
-#define CONFIG_ONENAND_SIM_DEVICE_ID            0x04
-#endif
-
-#define CONFIG_FLEXONENAND ((CONFIG_ONENAND_SIM_DEVICE_ID >> 9) & 1)
-
-#ifndef CONFIG_ONENAND_SIM_VERSION_ID
-#define CONFIG_ONENAND_SIM_VERSION_ID           0x1e
-#endif
-
-#ifndef CONFIG_ONENAND_SIM_TECHNOLOGY_ID
-#define CONFIG_ONENAND_SIM_TECHNOLOGY_ID CONFIG_FLEXONENAND
-#endif
-
-/* Initial boundary values for Flex-OneNAND Simulator */
-#ifndef CONFIG_FLEXONENAND_SIM_DIE0_BOUNDARY
-#define CONFIG_FLEXONENAND_SIM_DIE0_BOUNDARY	0x01
-#endif
-
-#ifndef CONFIG_FLEXONENAND_SIM_DIE1_BOUNDARY
-#define CONFIG_FLEXONENAND_SIM_DIE1_BOUNDARY	0x01
-#endif
-
-static int manuf_id	= CONFIG_ONENAND_SIM_MANUFACTURER;
-static int device_id	= CONFIG_ONENAND_SIM_DEVICE_ID;
-static int version_id	= CONFIG_ONENAND_SIM_VERSION_ID;
-static int technology_id = CONFIG_ONENAND_SIM_TECHNOLOGY_ID;
-static int boundary[] = {
-	CONFIG_FLEXONENAND_SIM_DIE0_BOUNDARY,
-	CONFIG_FLEXONENAND_SIM_DIE1_BOUNDARY,
-};
-
-struct onenand_flash {
-	void __iomem *base;
-	void __iomem *data;
-};
-
-#define ONENAND_CORE(flash)		(flash->data)
-#define ONENAND_CORE_SPARE(flash, this, offset)				\
-	((flash->data) + (this->chipsize) + (offset >> 5))
-
-#define ONENAND_MAIN_AREA(this, offset)					\
-	(this->base + ONENAND_DATARAM + offset)
-
-#define ONENAND_SPARE_AREA(this, offset)				\
-	(this->base + ONENAND_SPARERAM + offset)
-
-#define ONENAND_GET_WP_STATUS(this)					\
-	(readw(this->base + ONENAND_REG_WP_STATUS))
-
-#define ONENAND_SET_WP_STATUS(v, this)					\
-	(writew(v, this->base + ONENAND_REG_WP_STATUS))
-
-/* It has all 0xff chars */
-#define MAX_ONENAND_PAGESIZE		(4096 + 128)
-static unsigned char *ffchars;
-
-#if CONFIG_FLEXONENAND
-#define PARTITION_NAME "Flex-OneNAND simulator partition"
-#else
-#define PARTITION_NAME "OneNAND simulator partition"
-#endif
-
-static struct mtd_partition os_partitions[] = {
-	{
-		.name		= PARTITION_NAME,
-		.offset		= 0,
-		.size		= MTDPART_SIZ_FULL,
-	},
-};
-
-/*
- * OneNAND simulator mtd
- */
-struct onenand_info {
-	struct mtd_info		mtd;
-	struct mtd_partition	*parts;
-	struct onenand_chip	onenand;
-	struct onenand_flash	flash;
-};
-
-static struct onenand_info *info;
-
-#define DPRINTK(format, args...)					\
-do {									\
-	printk(KERN_DEBUG "%s[%d]: " format "\n", __func__,		\
-			   __LINE__, ##args);				\
-} while (0)
-
-/**
- * onenand_lock_handle - Handle Lock scheme
- * @this:		OneNAND device structure
- * @cmd:		The command to be sent
- *
- * Send lock command to OneNAND device.
- * The lock scheme depends on chip type.
- */
-static void onenand_lock_handle(struct onenand_chip *this, int cmd)
-{
-	int block_lock_scheme;
-	int status;
-
-	status = ONENAND_GET_WP_STATUS(this);
-	block_lock_scheme = !(this->options & ONENAND_HAS_CONT_LOCK);
-
-	switch (cmd) {
-	case ONENAND_CMD_UNLOCK:
-	case ONENAND_CMD_UNLOCK_ALL:
-		if (block_lock_scheme)
-			ONENAND_SET_WP_STATUS(ONENAND_WP_US, this);
-		else
-			ONENAND_SET_WP_STATUS(status | ONENAND_WP_US, this);
-		break;
-
-	case ONENAND_CMD_LOCK:
-		if (block_lock_scheme)
-			ONENAND_SET_WP_STATUS(ONENAND_WP_LS, this);
-		else
-			ONENAND_SET_WP_STATUS(status | ONENAND_WP_LS, this);
-		break;
-
-	case ONENAND_CMD_LOCK_TIGHT:
-		if (block_lock_scheme)
-			ONENAND_SET_WP_STATUS(ONENAND_WP_LTS, this);
-		else
-			ONENAND_SET_WP_STATUS(status | ONENAND_WP_LTS, this);
-		break;
-
-	default:
-		break;
-	}
-}
-
-/**
- * onenand_bootram_handle - Handle BootRAM area
- * @this:		OneNAND device structure
- * @cmd:		The command to be sent
- *
- * Emulate BootRAM area. It is possible to do basic operation using BootRAM.
- */
-static void onenand_bootram_handle(struct onenand_chip *this, int cmd)
-{
-	switch (cmd) {
-	case ONENAND_CMD_READID:
-		writew(manuf_id, this->base);
-		writew(device_id, this->base + 2);
-		writew(version_id, this->base + 4);
-		break;
-
-	default:
-		/* REVIST: Handle other commands */
-		break;
-	}
-}
-
-/**
- * onenand_update_interrupt - Set interrupt register
- * @this:         OneNAND device structure
- * @cmd:          The command to be sent
- *
- * Update interrupt register. The status depends on command.
- */
-static void onenand_update_interrupt(struct onenand_chip *this, int cmd)
-{
-	int interrupt = ONENAND_INT_MASTER;
-
-	switch (cmd) {
-	case ONENAND_CMD_READ:
-	case ONENAND_CMD_READOOB:
-		interrupt |= ONENAND_INT_READ;
-		break;
-
-	case ONENAND_CMD_PROG:
-	case ONENAND_CMD_PROGOOB:
-		interrupt |= ONENAND_INT_WRITE;
-		break;
-
-	case ONENAND_CMD_ERASE:
-		interrupt |= ONENAND_INT_ERASE;
-		break;
-
-	case ONENAND_CMD_RESET:
-		interrupt |= ONENAND_INT_RESET;
-		break;
-
-	default:
-		break;
-	}
-
-	writew(interrupt, this->base + ONENAND_REG_INTERRUPT);
-}
-
-/**
- * onenand_check_overwrite - Check if over-write happened
- * @dest:		The destination pointer
- * @src:		The source pointer
- * @count:		The length to be check
- *
- * Returns:		0 on same, otherwise 1
- *
- * Compare the source with destination
- */
-static int onenand_check_overwrite(void *dest, void *src, size_t count)
-{
-	unsigned int *s = (unsigned int *) src;
-	unsigned int *d = (unsigned int *) dest;
-	int i;
-
-	count >>= 2;
-	for (i = 0; i < count; i++)
-		if ((*s++ ^ *d++) != 0)
-			return 1;
-
-	return 0;
-}
-
-/**
- * onenand_data_handle - Handle OneNAND Core and DataRAM
- * @this:		OneNAND device structure
- * @cmd:		The command to be sent
- * @dataram:		Which dataram used
- * @offset:		The offset to OneNAND Core
- *
- * Copy data from OneNAND Core to DataRAM (read)
- * Copy data from DataRAM to OneNAND Core (write)
- * Erase the OneNAND Core (erase)
- */
-static void onenand_data_handle(struct onenand_chip *this, int cmd,
-				int dataram, unsigned int offset)
-{
-	struct mtd_info *mtd = &info->mtd;
-	struct onenand_flash *flash = this->priv;
-	int main_offset, spare_offset, die = 0;
-	void __iomem *src;
-	void __iomem *dest;
-	unsigned int i;
-	static int pi_operation;
-	int erasesize, rgn;
-
-	if (dataram) {
-		main_offset = mtd->writesize;
-		spare_offset = mtd->oobsize;
-	} else {
-		main_offset = 0;
-		spare_offset = 0;
-	}
-
-	if (pi_operation) {
-		die = readw(this->base + ONENAND_REG_START_ADDRESS2);
-		die >>= ONENAND_DDP_SHIFT;
-	}
-
-	switch (cmd) {
-	case FLEXONENAND_CMD_PI_ACCESS:
-		pi_operation = 1;
-		break;
-
-	case ONENAND_CMD_RESET:
-		pi_operation = 0;
-		break;
-
-	case ONENAND_CMD_READ:
-		src = ONENAND_CORE(flash) + offset;
-		dest = ONENAND_MAIN_AREA(this, main_offset);
-		if (pi_operation) {
-			writew(boundary[die], this->base + ONENAND_DATARAM);
-			break;
-		}
-		memcpy(dest, src, mtd->writesize);
-		/* Fall through */
-
-	case ONENAND_CMD_READOOB:
-		src = ONENAND_CORE_SPARE(flash, this, offset);
-		dest = ONENAND_SPARE_AREA(this, spare_offset);
-		memcpy(dest, src, mtd->oobsize);
-		break;
-
-	case ONENAND_CMD_PROG:
-		src = ONENAND_MAIN_AREA(this, main_offset);
-		dest = ONENAND_CORE(flash) + offset;
-		if (pi_operation) {
-			boundary[die] = readw(this->base + ONENAND_DATARAM);
-			break;
-		}
-		/* To handle partial write */
-		for (i = 0; i < (1 << mtd->subpage_sft); i++) {
-			int off = i * this->subpagesize;
-			if (!memcmp(src + off, ffchars, this->subpagesize))
-				continue;
-			if (memcmp(dest + off, ffchars, this->subpagesize) &&
-			    onenand_check_overwrite(dest + off, src + off, this->subpagesize))
-				printk(KERN_ERR "over-write happened at 0x%08x\n", offset);
-			memcpy(dest + off, src + off, this->subpagesize);
-		}
-		/* Fall through */
-
-	case ONENAND_CMD_PROGOOB:
-		src = ONENAND_SPARE_AREA(this, spare_offset);
-		/* Check all data is 0xff chars */
-		if (!memcmp(src, ffchars, mtd->oobsize))
-			break;
-
-		dest = ONENAND_CORE_SPARE(flash, this, offset);
-		if (memcmp(dest, ffchars, mtd->oobsize) &&
-		    onenand_check_overwrite(dest, src, mtd->oobsize))
-			printk(KERN_ERR "OOB: over-write happened at 0x%08x\n",
-			       offset);
-		memcpy(dest, src, mtd->oobsize);
-		break;
-
-	case ONENAND_CMD_ERASE:
-		if (pi_operation)
-			break;
-
-		if (FLEXONENAND(this)) {
-			rgn = flexonenand_region(mtd, offset);
-			erasesize = mtd->eraseregions[rgn].erasesize;
-		} else
-			erasesize = mtd->erasesize;
-
-		memset(ONENAND_CORE(flash) + offset, 0xff, erasesize);
-		memset(ONENAND_CORE_SPARE(flash, this, offset), 0xff,
-		       (erasesize >> 5));
-		break;
-
-	default:
-		break;
-	}
-}
-
-/**
- * onenand_command_handle - Handle command
- * @this:		OneNAND device structure
- * @cmd:		The command to be sent
- *
- * Emulate OneNAND command.
- */
-static void onenand_command_handle(struct onenand_chip *this, int cmd)
-{
-	unsigned long offset = 0;
-	int block = -1, page = -1, bufferram = -1;
-	int dataram = 0;
-
-	switch (cmd) {
-	case ONENAND_CMD_UNLOCK:
-	case ONENAND_CMD_LOCK:
-	case ONENAND_CMD_LOCK_TIGHT:
-	case ONENAND_CMD_UNLOCK_ALL:
-		onenand_lock_handle(this, cmd);
-		break;
-
-	case ONENAND_CMD_BUFFERRAM:
-		/* Do nothing */
-		return;
-
-	default:
-		block = (int) readw(this->base + ONENAND_REG_START_ADDRESS1);
-		if (block & (1 << ONENAND_DDP_SHIFT)) {
-			block &= ~(1 << ONENAND_DDP_SHIFT);
-			/* The half of chip block */
-			block += this->chipsize >> (this->erase_shift + 1);
-		}
-		if (cmd == ONENAND_CMD_ERASE)
-			break;
-
-		page = (int) readw(this->base + ONENAND_REG_START_ADDRESS8);
-		page = (page >> ONENAND_FPA_SHIFT);
-		bufferram = (int) readw(this->base + ONENAND_REG_START_BUFFER);
-		bufferram >>= ONENAND_BSA_SHIFT;
-		bufferram &= ONENAND_BSA_DATARAM1;
-		dataram = (bufferram == ONENAND_BSA_DATARAM1) ? 1 : 0;
-		break;
-	}
-
-	if (block != -1)
-		offset = onenand_addr(this, block);
-
-	if (page != -1)
-		offset += page << this->page_shift;
-
-	onenand_data_handle(this, cmd, dataram, offset);
-
-	onenand_update_interrupt(this, cmd);
-}
-
-/**
- * onenand_writew - [OneNAND Interface] Emulate write operation
- * @value:		value to write
- * @addr:		address to write
- *
- * Write OneNAND register with value
- */
-static void onenand_writew(unsigned short value, void __iomem * addr)
-{
-	struct onenand_chip *this = info->mtd.priv;
-
-	/* BootRAM handling */
-	if (addr < this->base + ONENAND_DATARAM) {
-		onenand_bootram_handle(this, value);
-		return;
-	}
-	/* Command handling */
-	if (addr == this->base + ONENAND_REG_COMMAND)
-		onenand_command_handle(this, value);
-
-	writew(value, addr);
-}
-
-/**
- * flash_init - Initialize OneNAND simulator
- * @flash:		OneNAND simulator data strucutres
- *
- * Initialize OneNAND simulator.
- */
-static int __init flash_init(struct onenand_flash *flash)
-{
-	int density, size;
-	int buffer_size;
-
-	flash->base = kzalloc(131072, GFP_KERNEL);
-	if (!flash->base) {
-		printk(KERN_ERR "Unable to allocate base address.\n");
-		return -ENOMEM;
-	}
-
-	density = device_id >> ONENAND_DEVICE_DENSITY_SHIFT;
-	density &= ONENAND_DEVICE_DENSITY_MASK;
-	size = ((16 << 20) << density);
-
-	ONENAND_CORE(flash) = vmalloc(size + (size >> 5));
-	if (!ONENAND_CORE(flash)) {
-		printk(KERN_ERR "Unable to allocate nand core address.\n");
-		kfree(flash->base);
-		return -ENOMEM;
-	}
-
-	memset(ONENAND_CORE(flash), 0xff, size + (size >> 5));
-
-	/* Setup registers */
-	writew(manuf_id, flash->base + ONENAND_REG_MANUFACTURER_ID);
-	writew(device_id, flash->base + ONENAND_REG_DEVICE_ID);
-	writew(version_id, flash->base + ONENAND_REG_VERSION_ID);
-	writew(technology_id, flash->base + ONENAND_REG_TECHNOLOGY);
-
-	if (density < 2 && (!CONFIG_FLEXONENAND))
-		buffer_size = 0x0400;	/* 1KiB page */
-	else
-		buffer_size = 0x0800;	/* 2KiB page */
-	writew(buffer_size, flash->base + ONENAND_REG_DATA_BUFFER_SIZE);
-
-	return 0;
-}
-
-/**
- * flash_exit - Clean up OneNAND simulator
- * @flash:		OneNAND simulator data structures
- *
- * Clean up OneNAND simulator.
- */
-static void flash_exit(struct onenand_flash *flash)
-{
-	vfree(ONENAND_CORE(flash));
-	kfree(flash->base);
-}
-
-static int __init onenand_sim_init(void)
-{
-	/* Allocate all 0xff chars pointer */
-	ffchars = kmalloc(MAX_ONENAND_PAGESIZE, GFP_KERNEL);
-	if (!ffchars) {
-		printk(KERN_ERR "Unable to allocate ff chars.\n");
-		return -ENOMEM;
-	}
-	memset(ffchars, 0xff, MAX_ONENAND_PAGESIZE);
-
-	/* Allocate OneNAND simulator mtd pointer */
-	info = kzalloc(sizeof(struct onenand_info), GFP_KERNEL);
-	if (!info) {
-		printk(KERN_ERR "Unable to allocate core structures.\n");
-		kfree(ffchars);
-		return -ENOMEM;
-	}
-
-	/* Override write_word function */
-	info->onenand.write_word = onenand_writew;
-
-	if (flash_init(&info->flash)) {
-		printk(KERN_ERR "Unable to allocate flash.\n");
-		kfree(ffchars);
-		kfree(info);
-		return -ENOMEM;
-	}
-
-	info->parts = os_partitions;
-
-	info->onenand.base = info->flash.base;
-	info->onenand.priv = &info->flash;
-
-	info->mtd.name = "OneNAND simulator";
-	info->mtd.priv = &info->onenand;
-	info->mtd.owner = THIS_MODULE;
-
-	if (onenand_scan(&info->mtd, 1)) {
-		flash_exit(&info->flash);
-		kfree(ffchars);
-		kfree(info);
-		return -ENXIO;
-	}
-
-	mtd_device_register(&info->mtd, info->parts,
-			    ARRAY_SIZE(os_partitions));
-
-	return 0;
-}
-
-static void __exit onenand_sim_exit(void)
-{
-	struct onenand_chip *this = info->mtd.priv;
-	struct onenand_flash *flash = this->priv;
-
-	onenand_release(&info->mtd);
-	flash_exit(flash);
-	kfree(ffchars);
-	kfree(info);
-}
-
-module_init(onenand_sim_init);
-module_exit(onenand_sim_exit);
-
-MODULE_AUTHOR("Kyungmin Park <kyungmin.park@samsung.com>");
-MODULE_DESCRIPTION("The OneNAND flash simulator");
-MODULE_LICENSE("GPL");
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 87f1d39..3835321 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -151,6 +151,7 @@ config MACVTAP
 config VXLAN
        tristate "Virtual eXtensible Local Area Network (VXLAN)"
        depends on INET
+       select NET_IP_TUNNEL
        ---help---
 	  This allows one to create vxlan virtual interfaces that provide
 	  Layer 2 Networks over Layer 3 Networks. VXLAN is often used
diff --git a/drivers/net/appletalk/Kconfig b/drivers/net/appletalk/Kconfig
index f5a8916..4ce6ca5 100644
--- a/drivers/net/appletalk/Kconfig
+++ b/drivers/net/appletalk/Kconfig
@@ -106,20 +106,4 @@ config IPDDP_ENCAP
 	  IP packets inside AppleTalk frames; this is useful if your Linux box
 	  is stuck on an AppleTalk network (which hopefully contains a
 	  decapsulator somewhere). Please see
-	  <file:Documentation/networking/ipddp.txt> for more information. If
-	  you said Y to "AppleTalk-IP driver support" above and you say Y
-	  here, then you cannot say Y to "AppleTalk-IP to IP Decapsulation
-	  support", below.
-
-config IPDDP_DECAP
-	bool "Appletalk-IP to IP Decapsulation support"
-	depends on IPDDP
-	help
-	  If you say Y here, the AppleTalk-IP code will be able to decapsulate
-	  AppleTalk-IP frames to IP packets; this is useful if you want your
-	  Linux box to act as an Internet gateway for an AppleTalk network.
-	  Please see <file:Documentation/networking/ipddp.txt> for more
-	  information.  If you said Y to "AppleTalk-IP driver support" above
-	  and you say Y here, then you cannot say Y to "IP to AppleTalk-IP
-	  Encapsulation support", above.
-
+	  <file:Documentation/networking/ipddp.txt> for more information.
diff --git a/drivers/net/arcnet/com20020_cs.c b/drivers/net/arcnet/com20020_cs.c
index 5bed4c4..74dc187 100644
--- a/drivers/net/arcnet/com20020_cs.c
+++ b/drivers/net/arcnet/com20020_cs.c
@@ -333,16 +333,4 @@ static struct pcmcia_driver com20020_cs_driver = {
 	.suspend	= com20020_suspend,
 	.resume		= com20020_resume,
 };
-
-static int __init init_com20020_cs(void)
-{
-	return pcmcia_register_driver(&com20020_cs_driver);
-}
-
-static void __exit exit_com20020_cs(void)
-{
-	pcmcia_unregister_driver(&com20020_cs_driver);
-}
-
-module_init(init_com20020_cs);
-module_exit(exit_com20020_cs);
+module_pcmcia_driver(com20020_cs_driver);
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 6bbd90e..78c9e2d 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -796,9 +796,8 @@ static void bond_resend_igmp_join_requests_delayed(struct work_struct *work)
 {
 	struct bonding *bond = container_of(work, struct bonding,
 					    mcast_work.work);
-	rcu_read_lock();
+
 	bond_resend_igmp_join_requests(bond);
-	rcu_read_unlock();
 }
 
 /*
@@ -1976,12 +1975,11 @@ static int __bond_release_one(struct net_device *bond_dev,
 		return -EINVAL;
 	}
 
+	write_unlock_bh(&bond->lock);
 	/* unregister rx_handler early so bond_handle_frame wouldn't be called
 	 * for this slave anymore.
 	 */
 	netdev_rx_handler_unregister(slave_dev);
-	write_unlock_bh(&bond->lock);
-	synchronize_net();
 	write_lock_bh(&bond->lock);
 
 	if (!all && !bond->params.fail_over_mac) {
diff --git a/drivers/net/bonding/bond_procfs.c b/drivers/net/bonding/bond_procfs.c
index 3cea38d..94d06f1 100644
--- a/drivers/net/bonding/bond_procfs.c
+++ b/drivers/net/bonding/bond_procfs.c
@@ -218,15 +218,13 @@ static const struct seq_operations bond_info_seq_ops = {
 static int bond_info_open(struct inode *inode, struct file *file)
 {
 	struct seq_file *seq;
-	struct proc_dir_entry *proc;
 	int res;
 
 	res = seq_open(file, &bond_info_seq_ops);
 	if (!res) {
 		/* recover the pointer buried in proc_dir_entry data */
 		seq = file->private_data;
-		proc = PDE(inode);
-		seq->private = proc->data;
+		seq->private = PDE_DATA(inode);
 	}
 
 	return res;
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index db103e0..ea7a388 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -527,7 +527,7 @@ static ssize_t bonding_store_arp_interval(struct device *d,
 		goto out;
 	}
 	if (new_value < 0) {
-		pr_err("%s: Invalid arp_interval value %d not in range 1-%d; rejected.\n",
+		pr_err("%s: Invalid arp_interval value %d not in range 0-%d; rejected.\n",
 		       bond->dev->name, new_value, INT_MAX);
 		ret = -EINVAL;
 		goto out;
@@ -542,14 +542,15 @@ static ssize_t bonding_store_arp_interval(struct device *d,
 	pr_info("%s: Setting ARP monitoring interval to %d.\n",
 		bond->dev->name, new_value);
 	bond->params.arp_interval = new_value;
-	if (bond->params.miimon) {
-		pr_info("%s: ARP monitoring cannot be used with MII monitoring. %s Disabling MII monitoring.\n",
-			bond->dev->name, bond->dev->name);
-		bond->params.miimon = 0;
-	}
-	if (!bond->params.arp_targets[0]) {
-		pr_info("%s: ARP monitoring has been set up, but no ARP targets have been specified.\n",
-			bond->dev->name);
+	if (new_value) {
+		if (bond->params.miimon) {
+			pr_info("%s: ARP monitoring cannot be used with MII monitoring. %s Disabling MII monitoring.\n",
+				bond->dev->name, bond->dev->name);
+			bond->params.miimon = 0;
+		}
+		if (!bond->params.arp_targets[0])
+			pr_info("%s: ARP monitoring has been set up, but no ARP targets have been specified.\n",
+				bond->dev->name);
 	}
 	if (bond->dev->flags & IFF_UP) {
 		/* If the interface is up, we may need to fire off
@@ -557,10 +558,13 @@ static ssize_t bonding_store_arp_interval(struct device *d,
 		 * timer will get fired off when the open function
 		 * is called.
 		 */
-		cancel_delayed_work_sync(&bond->mii_work);
-		queue_delayed_work(bond->wq, &bond->arp_work, 0);
+		if (!new_value) {
+			cancel_delayed_work_sync(&bond->arp_work);
+		} else {
+			cancel_delayed_work_sync(&bond->mii_work);
+			queue_delayed_work(bond->wq, &bond->arp_work, 0);
+		}
 	}
-
 out:
 	rtnl_unlock();
 	return ret;
@@ -702,7 +706,7 @@ static ssize_t bonding_store_downdelay(struct device *d,
 	}
 	if (new_value < 0) {
 		pr_err("%s: Invalid down delay value %d not in range %d-%d; rejected.\n",
-		       bond->dev->name, new_value, 1, INT_MAX);
+		       bond->dev->name, new_value, 0, INT_MAX);
 		ret = -EINVAL;
 		goto out;
 	} else {
@@ -757,8 +761,8 @@ static ssize_t bonding_store_updelay(struct device *d,
 		goto out;
 	}
 	if (new_value < 0) {
-		pr_err("%s: Invalid down delay value %d not in range %d-%d; rejected.\n",
-		       bond->dev->name, new_value, 1, INT_MAX);
+		pr_err("%s: Invalid up delay value %d not in range %d-%d; rejected.\n",
+		       bond->dev->name, new_value, 0, INT_MAX);
 		ret = -EINVAL;
 		goto out;
 	} else {
@@ -968,37 +972,37 @@ static ssize_t bonding_store_miimon(struct device *d,
 	}
 	if (new_value < 0) {
 		pr_err("%s: Invalid miimon value %d not in range %d-%d; rejected.\n",
-		       bond->dev->name, new_value, 1, INT_MAX);
+		       bond->dev->name, new_value, 0, INT_MAX);
 		ret = -EINVAL;
 		goto out;
-	} else {
-		pr_info("%s: Setting MII monitoring interval to %d.\n",
-			bond->dev->name, new_value);
-		bond->params.miimon = new_value;
-		if (bond->params.updelay)
-			pr_info("%s: Note: Updating updelay (to %d) since it is a multiple of the miimon value.\n",
-				bond->dev->name,
-				bond->params.updelay * bond->params.miimon);
-		if (bond->params.downdelay)
-			pr_info("%s: Note: Updating downdelay (to %d) since it is a multiple of the miimon value.\n",
-				bond->dev->name,
-				bond->params.downdelay * bond->params.miimon);
-		if (bond->params.arp_interval) {
-			pr_info("%s: MII monitoring cannot be used with ARP monitoring. Disabling ARP monitoring...\n",
-				bond->dev->name);
-			bond->params.arp_interval = 0;
-			if (bond->params.arp_validate) {
-				bond->params.arp_validate =
-					BOND_ARP_VALIDATE_NONE;
-			}
-		}
-
-		if (bond->dev->flags & IFF_UP) {
-			/* If the interface is up, we may need to fire off
-			 * the MII timer. If the interface is down, the
-			 * timer will get fired off when the open function
-			 * is called.
-			 */
+	}
+	pr_info("%s: Setting MII monitoring interval to %d.\n",
+		bond->dev->name, new_value);
+	bond->params.miimon = new_value;
+	if (bond->params.updelay)
+		pr_info("%s: Note: Updating updelay (to %d) since it is a multiple of the miimon value.\n",
+			bond->dev->name,
+			bond->params.updelay * bond->params.miimon);
+	if (bond->params.downdelay)
+		pr_info("%s: Note: Updating downdelay (to %d) since it is a multiple of the miimon value.\n",
+			bond->dev->name,
+			bond->params.downdelay * bond->params.miimon);
+	if (new_value && bond->params.arp_interval) {
+		pr_info("%s: MII monitoring cannot be used with ARP monitoring. Disabling ARP monitoring...\n",
+			bond->dev->name);
+		bond->params.arp_interval = 0;
+		if (bond->params.arp_validate)
+			bond->params.arp_validate = BOND_ARP_VALIDATE_NONE;
+	}
+	if (bond->dev->flags & IFF_UP) {
+		/* If the interface is up, we may need to fire off
+		 * the MII timer. If the interface is down, the
+		 * timer will get fired off when the open function
+		 * is called.
+		 */
+		if (!new_value) {
+			cancel_delayed_work_sync(&bond->mii_work);
+		} else {
 			cancel_delayed_work_sync(&bond->arp_work);
 			queue_delayed_work(bond->wq, &bond->mii_work, 0);
 		}
diff --git a/drivers/net/caif/Kconfig b/drivers/net/caif/Kconfig
index 60c2142..7ffc756 100644
--- a/drivers/net/caif/Kconfig
+++ b/drivers/net/caif/Kconfig
@@ -32,13 +32,6 @@ config CAIF_SPI_SYNC
 	help to synchronize to the next transfer in case of over or under-runs.
 	This option also needs to be enabled on the modem.
 
-config CAIF_SHM
-	tristate "CAIF shared memory protocol driver"
-	depends on CAIF && U5500_MBOX
-	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
@@ -47,3 +40,17 @@ config CAIF_HSI
        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.
+
+config CAIF_VIRTIO
+	tristate "CAIF virtio transport driver"
+	depends on CAIF
+	select VHOST_RING
+	select VIRTIO
+	select GENERIC_ALLOCATOR
+	default n
+	---help---
+	The caif driver for CAIF over Virtio.
+
+if CAIF_VIRTIO
+source "drivers/vhost/Kconfig"
+endif
diff --git a/drivers/net/caif/Makefile b/drivers/net/caif/Makefile
index 91dff86..9bbd453 100644
--- a/drivers/net/caif/Makefile
+++ b/drivers/net/caif/Makefile
@@ -7,9 +7,8 @@ obj-$(CONFIG_CAIF_TTY) += caif_serial.o
 cfspi_slave-objs := caif_spi.o caif_spi_slave.o
 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
+
+# Virtio interface
+obj-$(CONFIG_CAIF_VIRTIO) += caif_virtio.o
diff --git a/drivers/net/caif/caif_serial.c b/drivers/net/caif/caif_serial.c
index 666891a..be90deb 100644
--- a/drivers/net/caif/caif_serial.c
+++ b/drivers/net/caif/caif_serial.c
@@ -88,11 +88,9 @@ static inline void update_tty_status(struct ser_device *ser)
 {
 	ser->tty_status =
 		ser->tty->stopped << 5 |
-		ser->tty->hw_stopped << 4 |
 		ser->tty->flow_stopped << 3 |
 		ser->tty->packet << 2 |
-		ser->tty->port->low_latency << 1 |
-		ser->tty->warned;
+		ser->tty->port->low_latency << 1;
 }
 static inline void debugfs_init(struct ser_device *ser, struct tty_struct *tty)
 {
diff --git a/drivers/net/caif/caif_shm_u5500.c b/drivers/net/caif/caif_shm_u5500.c
deleted file mode 100644
index 89d76b7..0000000
--- a/drivers/net/caif/caif_shm_u5500.c
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson AB 2010
- * Contact: Sjur Brendeland / sjur.brandeland@stericsson.com
- * Author:  Amarnath Revanna / amarnath.bangalore.revanna@stericsson.com
- * License terms: GNU General Public License (GPL) version 2
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ":" fmt
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/netdevice.h>
-#include <mach/mbox-db5500.h>
-#include <net/caif/caif_shm.h>
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("CAIF Shared Memory protocol driver");
-
-#define MAX_SHM_INSTANCES	1
-
-enum {
-	MBX_ACC0,
-	MBX_ACC1,
-	MBX_DSP
-};
-
-static struct shmdev_layer shmdev_lyr[MAX_SHM_INSTANCES];
-
-static unsigned int shm_start;
-static unsigned int shm_size;
-
-module_param(shm_size, uint  , 0440);
-MODULE_PARM_DESC(shm_total_size, "Start of SHM shared memory");
-
-module_param(shm_start, uint  , 0440);
-MODULE_PARM_DESC(shm_total_start, "Total Size of SHM shared memory");
-
-static int shmdev_send_msg(u32 dev_id, u32 mbx_msg)
-{
-	/* Always block until msg is written successfully */
-	mbox_send(shmdev_lyr[dev_id].hmbx, mbx_msg, true);
-	return 0;
-}
-
-static int shmdev_mbx_setup(void *pshmdrv_cb, struct shmdev_layer *pshm_dev,
-							 void *pshm_drv)
-{
-	/*
-	 * For UX5500, we have only 1 SHM instance which uses MBX0
-	 * for communication with the peer modem
-	 */
-	pshm_dev->hmbx = mbox_setup(MBX_ACC0, pshmdrv_cb, pshm_drv);
-
-	if (!pshm_dev->hmbx)
-		return -ENODEV;
-	else
-		return 0;
-}
-
-static int __init caif_shmdev_init(void)
-{
-	int i, result;
-
-	/* Loop is currently overkill, there is only one instance */
-	for (i = 0; i < MAX_SHM_INSTANCES; i++) {
-
-		shmdev_lyr[i].shm_base_addr = shm_start;
-		shmdev_lyr[i].shm_total_sz = shm_size;
-
-		if (((char *)shmdev_lyr[i].shm_base_addr == NULL)
-			       || (shmdev_lyr[i].shm_total_sz <= 0))	{
-			pr_warn("ERROR,"
-				"Shared memory Address and/or Size incorrect"
-				", Bailing out ...\n");
-			result = -EINVAL;
-			goto clean;
-		}
-
-		pr_info("SHM AREA (instance %d) STARTS"
-			" AT %p\n", i, (char *)shmdev_lyr[i].shm_base_addr);
-
-		shmdev_lyr[i].shm_id = i;
-		shmdev_lyr[i].pshmdev_mbxsend = shmdev_send_msg;
-		shmdev_lyr[i].pshmdev_mbxsetup = shmdev_mbx_setup;
-
-		/*
-		 * Finally, CAIF core module is called with details in place:
-		 * 1. SHM base address
-		 * 2. SHM size
-		 * 3. MBX handle
-		 */
-		result = caif_shmcore_probe(&shmdev_lyr[i]);
-		if (result) {
-			pr_warn("ERROR[%d],"
-				"Could not probe SHM core (instance %d)"
-				" Bailing out ...\n", result, i);
-			goto clean;
-		}
-	}
-
-	return 0;
-
-clean:
-	/*
-	 * For now, we assume that even if one instance of SHM fails, we bail
-	 * out of the driver support completely. For this, we need to release
-	 * any memory allocated and unregister any instance of SHM net device.
-	 */
-	for (i = 0; i < MAX_SHM_INSTANCES; i++) {
-		if (shmdev_lyr[i].pshm_netdev)
-			unregister_netdev(shmdev_lyr[i].pshm_netdev);
-	}
-	return result;
-}
-
-static void __exit caif_shmdev_exit(void)
-{
-	int i;
-
-	for (i = 0; i < MAX_SHM_INSTANCES; i++) {
-		caif_shmcore_remove(shmdev_lyr[i].pshm_netdev);
-		kfree((void *)shmdev_lyr[i].shm_base_addr);
-	}
-
-}
-
-module_init(caif_shmdev_init);
-module_exit(caif_shmdev_exit);
diff --git a/drivers/net/caif/caif_shmcore.c b/drivers/net/caif/caif_shmcore.c
deleted file mode 100644
index bce8bac..0000000
--- a/drivers/net/caif/caif_shmcore.c
+++ /dev/null
@@ -1,747 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson AB 2010
- * Contact: Sjur Brendeland / sjur.brandeland@stericsson.com
- * Authors:  Amarnath Revanna / amarnath.bangalore.revanna@stericsson.com,
- *           Daniel Martensson / daniel.martensson@stericsson.com
- * License terms: GNU General Public License (GPL) version 2
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ":" fmt
-
-#include <linux/spinlock.h>
-#include <linux/sched.h>
-#include <linux/list.h>
-#include <linux/netdevice.h>
-#include <linux/if_arp.h>
-#include <linux/io.h>
-
-#include <net/caif/caif_device.h>
-#include <net/caif/caif_shm.h>
-
-#define NR_TX_BUF		6
-#define NR_RX_BUF		6
-#define TX_BUF_SZ		0x2000
-#define RX_BUF_SZ		0x2000
-
-#define CAIF_NEEDED_HEADROOM	32
-
-#define CAIF_FLOW_ON		1
-#define CAIF_FLOW_OFF		0
-
-#define LOW_WATERMARK		3
-#define HIGH_WATERMARK		4
-
-/* Maximum number of CAIF buffers per shared memory buffer. */
-#define SHM_MAX_FRMS_PER_BUF	10
-
-/*
- * Size in bytes of the descriptor area
- * (With end of descriptor signalling)
- */
-#define SHM_CAIF_DESC_SIZE	((SHM_MAX_FRMS_PER_BUF + 1) * \
-					sizeof(struct shm_pck_desc))
-
-/*
- * Offset to the first CAIF frame within a shared memory buffer.
- * Aligned on 32 bytes.
- */
-#define SHM_CAIF_FRM_OFS	(SHM_CAIF_DESC_SIZE + (SHM_CAIF_DESC_SIZE % 32))
-
-/* Number of bytes for CAIF shared memory header. */
-#define SHM_HDR_LEN		1
-
-/* Number of padding bytes for the complete CAIF frame. */
-#define SHM_FRM_PAD_LEN		4
-
-#define CAIF_MAX_MTU		4096
-
-#define SHM_SET_FULL(x)	(((x+1) & 0x0F) << 0)
-#define SHM_GET_FULL(x)	(((x >> 0) & 0x0F) - 1)
-
-#define SHM_SET_EMPTY(x)	(((x+1) & 0x0F) << 4)
-#define SHM_GET_EMPTY(x)	(((x >> 4) & 0x0F) - 1)
-
-#define SHM_FULL_MASK		(0x0F << 0)
-#define SHM_EMPTY_MASK		(0x0F << 4)
-
-struct shm_pck_desc {
-	/*
-	 * Offset from start of shared memory area to start of
-	 * shared memory CAIF frame.
-	 */
-	u32 frm_ofs;
-	u32 frm_len;
-};
-
-struct buf_list {
-	unsigned char *desc_vptr;
-	u32 phy_addr;
-	u32 index;
-	u32 len;
-	u32 frames;
-	u32 frm_ofs;
-	struct list_head list;
-};
-
-struct shm_caif_frm {
-	/* Number of bytes of padding before the CAIF frame. */
-	u8 hdr_ofs;
-};
-
-struct shmdrv_layer {
-	/* caif_dev_common must always be first in the structure*/
-	struct caif_dev_common cfdev;
-
-	u32 shm_tx_addr;
-	u32 shm_rx_addr;
-	u32 shm_base_addr;
-	u32 tx_empty_available;
-	spinlock_t lock;
-
-	struct list_head tx_empty_list;
-	struct list_head tx_pend_list;
-	struct list_head tx_full_list;
-	struct list_head rx_empty_list;
-	struct list_head rx_pend_list;
-	struct list_head rx_full_list;
-
-	struct workqueue_struct *pshm_tx_workqueue;
-	struct workqueue_struct *pshm_rx_workqueue;
-
-	struct work_struct shm_tx_work;
-	struct work_struct shm_rx_work;
-
-	struct sk_buff_head sk_qhead;
-	struct shmdev_layer *pshm_dev;
-};
-
-static int shm_netdev_open(struct net_device *shm_netdev)
-{
-	netif_wake_queue(shm_netdev);
-	return 0;
-}
-
-static int shm_netdev_close(struct net_device *shm_netdev)
-{
-	netif_stop_queue(shm_netdev);
-	return 0;
-}
-
-int caif_shmdrv_rx_cb(u32 mbx_msg, void *priv)
-{
-	struct buf_list *pbuf;
-	struct shmdrv_layer *pshm_drv;
-	struct list_head *pos;
-	u32 avail_emptybuff = 0;
-	unsigned long flags = 0;
-
-	pshm_drv = priv;
-
-	/* Check for received buffers. */
-	if (mbx_msg & SHM_FULL_MASK) {
-		int idx;
-
-		spin_lock_irqsave(&pshm_drv->lock, flags);
-
-		/* Check whether we have any outstanding buffers. */
-		if (list_empty(&pshm_drv->rx_empty_list)) {
-
-			/* Release spin lock. */
-			spin_unlock_irqrestore(&pshm_drv->lock, flags);
-
-			/* We print even in IRQ context... */
-			pr_warn("No empty Rx buffers to fill: "
-					"mbx_msg:%x\n", mbx_msg);
-
-			/* Bail out. */
-			goto err_sync;
-		}
-
-		pbuf =
-			list_entry(pshm_drv->rx_empty_list.next,
-					struct buf_list, list);
-		idx = pbuf->index;
-
-		/* Check buffer synchronization. */
-		if (idx != SHM_GET_FULL(mbx_msg)) {
-
-			/* We print even in IRQ context... */
-			pr_warn(
-			"phyif_shm_mbx_msg_cb: RX full out of sync:"
-			" idx:%d, msg:%x SHM_GET_FULL(mbx_msg):%x\n",
-				idx, mbx_msg, SHM_GET_FULL(mbx_msg));
-
-			spin_unlock_irqrestore(&pshm_drv->lock, flags);
-
-			/* Bail out. */
-			goto err_sync;
-		}
-
-		list_del_init(&pbuf->list);
-		list_add_tail(&pbuf->list, &pshm_drv->rx_full_list);
-
-		spin_unlock_irqrestore(&pshm_drv->lock, flags);
-
-		/* Schedule RX work queue. */
-		if (!work_pending(&pshm_drv->shm_rx_work))
-			queue_work(pshm_drv->pshm_rx_workqueue,
-						&pshm_drv->shm_rx_work);
-	}
-
-	/* Check for emptied buffers. */
-	if (mbx_msg & SHM_EMPTY_MASK) {
-		int idx;
-
-		spin_lock_irqsave(&pshm_drv->lock, flags);
-
-		/* Check whether we have any outstanding buffers. */
-		if (list_empty(&pshm_drv->tx_full_list)) {
-
-			/* We print even in IRQ context... */
-			pr_warn("No TX to empty: msg:%x\n", mbx_msg);
-
-			spin_unlock_irqrestore(&pshm_drv->lock, flags);
-
-			/* Bail out. */
-			goto err_sync;
-		}
-
-		pbuf =
-			list_entry(pshm_drv->tx_full_list.next,
-					struct buf_list, list);
-		idx = pbuf->index;
-
-		/* Check buffer synchronization. */
-		if (idx != SHM_GET_EMPTY(mbx_msg)) {
-
-			spin_unlock_irqrestore(&pshm_drv->lock, flags);
-
-			/* We print even in IRQ context... */
-			pr_warn("TX empty "
-				"out of sync:idx:%d, msg:%x\n", idx, mbx_msg);
-
-			/* Bail out. */
-			goto err_sync;
-		}
-		list_del_init(&pbuf->list);
-
-		/* Reset buffer parameters. */
-		pbuf->frames = 0;
-		pbuf->frm_ofs = SHM_CAIF_FRM_OFS;
-
-		list_add_tail(&pbuf->list, &pshm_drv->tx_empty_list);
-
-		/* Check the available no. of buffers in the empty list */
-		list_for_each(pos, &pshm_drv->tx_empty_list)
-			avail_emptybuff++;
-
-		/* Check whether we have to wake up the transmitter. */
-		if ((avail_emptybuff > HIGH_WATERMARK) &&
-					(!pshm_drv->tx_empty_available)) {
-			pshm_drv->tx_empty_available = 1;
-			spin_unlock_irqrestore(&pshm_drv->lock, flags);
-			pshm_drv->cfdev.flowctrl
-					(pshm_drv->pshm_dev->pshm_netdev,
-								CAIF_FLOW_ON);
-
-
-			/* Schedule the work queue. if required */
-			if (!work_pending(&pshm_drv->shm_tx_work))
-				queue_work(pshm_drv->pshm_tx_workqueue,
-							&pshm_drv->shm_tx_work);
-		} else
-			spin_unlock_irqrestore(&pshm_drv->lock, flags);
-	}
-
-	return 0;
-
-err_sync:
-	return -EIO;
-}
-
-static void shm_rx_work_func(struct work_struct *rx_work)
-{
-	struct shmdrv_layer *pshm_drv;
-	struct buf_list *pbuf;
-	unsigned long flags = 0;
-	struct sk_buff *skb;
-	char *p;
-	int ret;
-
-	pshm_drv = container_of(rx_work, struct shmdrv_layer, shm_rx_work);
-
-	while (1) {
-
-		struct shm_pck_desc *pck_desc;
-
-		spin_lock_irqsave(&pshm_drv->lock, flags);
-
-		/* Check for received buffers. */
-		if (list_empty(&pshm_drv->rx_full_list)) {
-			spin_unlock_irqrestore(&pshm_drv->lock, flags);
-			break;
-		}
-
-		pbuf =
-			list_entry(pshm_drv->rx_full_list.next, struct buf_list,
-					list);
-		list_del_init(&pbuf->list);
-		spin_unlock_irqrestore(&pshm_drv->lock, flags);
-
-		/* Retrieve pointer to start of the packet descriptor area. */
-		pck_desc = (struct shm_pck_desc *) pbuf->desc_vptr;
-
-		/*
-		 * Check whether descriptor contains a CAIF shared memory
-		 * frame.
-		 */
-		while (pck_desc->frm_ofs) {
-			unsigned int frm_buf_ofs;
-			unsigned int frm_pck_ofs;
-			unsigned int frm_pck_len;
-			/*
-			 * Check whether offset is within buffer limits
-			 * (lower).
-			 */
-			if (pck_desc->frm_ofs <
-				(pbuf->phy_addr - pshm_drv->shm_base_addr))
-				break;
-			/*
-			 * Check whether offset is within buffer limits
-			 * (higher).
-			 */
-			if (pck_desc->frm_ofs >
-				((pbuf->phy_addr - pshm_drv->shm_base_addr) +
-					pbuf->len))
-				break;
-
-			/* Calculate offset from start of buffer. */
-			frm_buf_ofs =
-				pck_desc->frm_ofs - (pbuf->phy_addr -
-						pshm_drv->shm_base_addr);
-
-			/*
-			 * Calculate offset and length of CAIF packet while
-			 * taking care of the shared memory header.
-			 */
-			frm_pck_ofs =
-				frm_buf_ofs + SHM_HDR_LEN +
-				(*(pbuf->desc_vptr + frm_buf_ofs));
-			frm_pck_len =
-				(pck_desc->frm_len - SHM_HDR_LEN -
-				(*(pbuf->desc_vptr + frm_buf_ofs)));
-
-			/* Check whether CAIF packet is within buffer limits */
-			if ((frm_pck_ofs + pck_desc->frm_len) > pbuf->len)
-				break;
-
-			/* Get a suitable CAIF packet and copy in data. */
-			skb = netdev_alloc_skb(pshm_drv->pshm_dev->pshm_netdev,
-							frm_pck_len + 1);
-
-			if (skb == NULL) {
-				pr_info("OOM: Try next frame in descriptor\n");
-				break;
-			}
-
-			p = skb_put(skb, frm_pck_len);
-			memcpy(p, pbuf->desc_vptr + frm_pck_ofs, frm_pck_len);
-
-			skb->protocol = htons(ETH_P_CAIF);
-			skb_reset_mac_header(skb);
-			skb->dev = pshm_drv->pshm_dev->pshm_netdev;
-
-			/* Push received packet up the stack. */
-			ret = netif_rx_ni(skb);
-
-			if (!ret) {
-				pshm_drv->pshm_dev->pshm_netdev->stats.
-								rx_packets++;
-				pshm_drv->pshm_dev->pshm_netdev->stats.
-						rx_bytes += pck_desc->frm_len;
-			} else
-				++pshm_drv->pshm_dev->pshm_netdev->stats.
-								rx_dropped;
-			/* Move to next packet descriptor. */
-			pck_desc++;
-		}
-
-		spin_lock_irqsave(&pshm_drv->lock, flags);
-		list_add_tail(&pbuf->list, &pshm_drv->rx_pend_list);
-
-		spin_unlock_irqrestore(&pshm_drv->lock, flags);
-
-	}
-
-	/* Schedule the work queue. if required */
-	if (!work_pending(&pshm_drv->shm_tx_work))
-		queue_work(pshm_drv->pshm_tx_workqueue, &pshm_drv->shm_tx_work);
-
-}
-
-static void shm_tx_work_func(struct work_struct *tx_work)
-{
-	u32 mbox_msg;
-	unsigned int frmlen, avail_emptybuff, append = 0;
-	unsigned long flags = 0;
-	struct buf_list *pbuf = NULL;
-	struct shmdrv_layer *pshm_drv;
-	struct shm_caif_frm *frm;
-	struct sk_buff *skb;
-	struct shm_pck_desc *pck_desc;
-	struct list_head *pos;
-
-	pshm_drv = container_of(tx_work, struct shmdrv_layer, shm_tx_work);
-
-	do {
-		/* Initialize mailbox message. */
-		mbox_msg = 0x00;
-		avail_emptybuff = 0;
-
-		spin_lock_irqsave(&pshm_drv->lock, flags);
-
-		/* Check for pending receive buffers. */
-		if (!list_empty(&pshm_drv->rx_pend_list)) {
-
-			pbuf = list_entry(pshm_drv->rx_pend_list.next,
-						struct buf_list, list);
-
-			list_del_init(&pbuf->list);
-			list_add_tail(&pbuf->list, &pshm_drv->rx_empty_list);
-			/*
-			 * Value index is never changed,
-			 * so read access should be safe.
-			 */
-			mbox_msg |= SHM_SET_EMPTY(pbuf->index);
-		}
-
-		skb = skb_peek(&pshm_drv->sk_qhead);
-
-		if (skb == NULL)
-			goto send_msg;
-		/* Check the available no. of buffers in the empty list */
-		list_for_each(pos, &pshm_drv->tx_empty_list)
-			avail_emptybuff++;
-
-		if ((avail_emptybuff < LOW_WATERMARK) &&
-					pshm_drv->tx_empty_available) {
-			/* Update blocking condition. */
-			pshm_drv->tx_empty_available = 0;
-			spin_unlock_irqrestore(&pshm_drv->lock, flags);
-			pshm_drv->cfdev.flowctrl
-					(pshm_drv->pshm_dev->pshm_netdev,
-					CAIF_FLOW_OFF);
-			spin_lock_irqsave(&pshm_drv->lock, flags);
-		}
-		/*
-		 * We simply return back to the caller if we do not have space
-		 * either in Tx pending list or Tx empty list. In this case,
-		 * we hold the received skb in the skb list, waiting to
-		 * be transmitted once Tx buffers become available
-		 */
-		if (list_empty(&pshm_drv->tx_empty_list))
-			goto send_msg;
-
-		/* Get the first free Tx buffer. */
-		pbuf = list_entry(pshm_drv->tx_empty_list.next,
-						struct buf_list, list);
-		do {
-			if (append) {
-				skb = skb_peek(&pshm_drv->sk_qhead);
-				if (skb == NULL)
-					break;
-			}
-
-			frm = (struct shm_caif_frm *)
-					(pbuf->desc_vptr + pbuf->frm_ofs);
-
-			frm->hdr_ofs = 0;
-			frmlen = 0;
-			frmlen += SHM_HDR_LEN + frm->hdr_ofs + skb->len;
-
-			/* Add tail padding if needed. */
-			if (frmlen % SHM_FRM_PAD_LEN)
-				frmlen += SHM_FRM_PAD_LEN -
-						(frmlen % SHM_FRM_PAD_LEN);
-
-			/*
-			 * Verify that packet, header and additional padding
-			 * can fit within the buffer frame area.
-			 */
-			if (frmlen >= (pbuf->len - pbuf->frm_ofs))
-				break;
-
-			if (!append) {
-				list_del_init(&pbuf->list);
-				append = 1;
-			}
-
-			skb = skb_dequeue(&pshm_drv->sk_qhead);
-			if (skb == NULL)
-				break;
-			/* Copy in CAIF frame. */
-			skb_copy_bits(skb, 0, pbuf->desc_vptr +
-					pbuf->frm_ofs + SHM_HDR_LEN +
-						frm->hdr_ofs, skb->len);
-
-			pshm_drv->pshm_dev->pshm_netdev->stats.tx_packets++;
-			pshm_drv->pshm_dev->pshm_netdev->stats.tx_bytes +=
-									frmlen;
-			dev_kfree_skb_irq(skb);
-
-			/* Fill in the shared memory packet descriptor area. */
-			pck_desc = (struct shm_pck_desc *) (pbuf->desc_vptr);
-			/* Forward to current frame. */
-			pck_desc += pbuf->frames;
-			pck_desc->frm_ofs = (pbuf->phy_addr -
-						pshm_drv->shm_base_addr) +
-								pbuf->frm_ofs;
-			pck_desc->frm_len = frmlen;
-			/* Terminate packet descriptor area. */
-			pck_desc++;
-			pck_desc->frm_ofs = 0;
-			/* Update buffer parameters. */
-			pbuf->frames++;
-			pbuf->frm_ofs += frmlen + (frmlen % 32);
-
-		} while (pbuf->frames < SHM_MAX_FRMS_PER_BUF);
-
-		/* Assign buffer as full. */
-		list_add_tail(&pbuf->list, &pshm_drv->tx_full_list);
-		append = 0;
-		mbox_msg |= SHM_SET_FULL(pbuf->index);
-send_msg:
-		spin_unlock_irqrestore(&pshm_drv->lock, flags);
-
-		if (mbox_msg)
-			pshm_drv->pshm_dev->pshmdev_mbxsend
-					(pshm_drv->pshm_dev->shm_id, mbox_msg);
-	} while (mbox_msg);
-}
-
-static int shm_netdev_tx(struct sk_buff *skb, struct net_device *shm_netdev)
-{
-	struct shmdrv_layer *pshm_drv;
-
-	pshm_drv = netdev_priv(shm_netdev);
-
-	skb_queue_tail(&pshm_drv->sk_qhead, skb);
-
-	/* Schedule Tx work queue. for deferred processing of skbs*/
-	if (!work_pending(&pshm_drv->shm_tx_work))
-		queue_work(pshm_drv->pshm_tx_workqueue, &pshm_drv->shm_tx_work);
-
-	return 0;
-}
-
-static const struct net_device_ops netdev_ops = {
-	.ndo_open = shm_netdev_open,
-	.ndo_stop = shm_netdev_close,
-	.ndo_start_xmit = shm_netdev_tx,
-};
-
-static void shm_netdev_setup(struct net_device *pshm_netdev)
-{
-	struct shmdrv_layer *pshm_drv;
-	pshm_netdev->netdev_ops = &netdev_ops;
-
-	pshm_netdev->mtu = CAIF_MAX_MTU;
-	pshm_netdev->type = ARPHRD_CAIF;
-	pshm_netdev->hard_header_len = CAIF_NEEDED_HEADROOM;
-	pshm_netdev->tx_queue_len = 0;
-	pshm_netdev->destructor = free_netdev;
-
-	pshm_drv = netdev_priv(pshm_netdev);
-
-	/* Initialize structures in a clean state. */
-	memset(pshm_drv, 0, sizeof(struct shmdrv_layer));
-
-	pshm_drv->cfdev.link_select = CAIF_LINK_LOW_LATENCY;
-}
-
-int caif_shmcore_probe(struct shmdev_layer *pshm_dev)
-{
-	int result, j;
-	struct shmdrv_layer *pshm_drv = NULL;
-
-	pshm_dev->pshm_netdev = alloc_netdev(sizeof(struct shmdrv_layer),
-						"cfshm%d", shm_netdev_setup);
-	if (!pshm_dev->pshm_netdev)
-		return -ENOMEM;
-
-	pshm_drv = netdev_priv(pshm_dev->pshm_netdev);
-	pshm_drv->pshm_dev = pshm_dev;
-
-	/*
-	 * Initialization starts with the verification of the
-	 * availability of MBX driver by calling its setup function.
-	 * MBX driver must be available by this time for proper
-	 * functioning of SHM driver.
-	 */
-	if ((pshm_dev->pshmdev_mbxsetup
-				(caif_shmdrv_rx_cb, pshm_dev, pshm_drv)) != 0) {
-		pr_warn("Could not config. SHM Mailbox,"
-				" Bailing out.....\n");
-		free_netdev(pshm_dev->pshm_netdev);
-		return -ENODEV;
-	}
-
-	skb_queue_head_init(&pshm_drv->sk_qhead);
-
-	pr_info("SHM DEVICE[%d] PROBED BY DRIVER, NEW SHM DRIVER"
-			" INSTANCE AT pshm_drv =0x%p\n",
-			pshm_drv->pshm_dev->shm_id, pshm_drv);
-
-	if (pshm_dev->shm_total_sz <
-			(NR_TX_BUF * TX_BUF_SZ + NR_RX_BUF * RX_BUF_SZ)) {
-
-		pr_warn("ERROR, Amount of available"
-				" Phys. SHM cannot accommodate current SHM "
-				"driver configuration, Bailing out ...\n");
-		free_netdev(pshm_dev->pshm_netdev);
-		return -ENOMEM;
-	}
-
-	pshm_drv->shm_base_addr = pshm_dev->shm_base_addr;
-	pshm_drv->shm_tx_addr = pshm_drv->shm_base_addr;
-
-	if (pshm_dev->shm_loopback)
-		pshm_drv->shm_rx_addr = pshm_drv->shm_tx_addr;
-	else
-		pshm_drv->shm_rx_addr = pshm_dev->shm_base_addr +
-						(NR_TX_BUF * TX_BUF_SZ);
-
-	spin_lock_init(&pshm_drv->lock);
-	INIT_LIST_HEAD(&pshm_drv->tx_empty_list);
-	INIT_LIST_HEAD(&pshm_drv->tx_pend_list);
-	INIT_LIST_HEAD(&pshm_drv->tx_full_list);
-
-	INIT_LIST_HEAD(&pshm_drv->rx_empty_list);
-	INIT_LIST_HEAD(&pshm_drv->rx_pend_list);
-	INIT_LIST_HEAD(&pshm_drv->rx_full_list);
-
-	INIT_WORK(&pshm_drv->shm_tx_work, shm_tx_work_func);
-	INIT_WORK(&pshm_drv->shm_rx_work, shm_rx_work_func);
-
-	pshm_drv->pshm_tx_workqueue =
-				create_singlethread_workqueue("shm_tx_work");
-	pshm_drv->pshm_rx_workqueue =
-				create_singlethread_workqueue("shm_rx_work");
-
-	for (j = 0; j < NR_TX_BUF; j++) {
-		struct buf_list *tx_buf =
-				kmalloc(sizeof(struct buf_list), GFP_KERNEL);
-
-		if (tx_buf == NULL) {
-			free_netdev(pshm_dev->pshm_netdev);
-			return -ENOMEM;
-		}
-		tx_buf->index = j;
-		tx_buf->phy_addr = pshm_drv->shm_tx_addr + (TX_BUF_SZ * j);
-		tx_buf->len = TX_BUF_SZ;
-		tx_buf->frames = 0;
-		tx_buf->frm_ofs = SHM_CAIF_FRM_OFS;
-
-		if (pshm_dev->shm_loopback)
-			tx_buf->desc_vptr = (unsigned char *)tx_buf->phy_addr;
-		else
-			/*
-			 * FIXME: the result of ioremap is not a pointer - arnd
-			 */
-			tx_buf->desc_vptr =
-					ioremap(tx_buf->phy_addr, TX_BUF_SZ);
-
-		list_add_tail(&tx_buf->list, &pshm_drv->tx_empty_list);
-	}
-
-	for (j = 0; j < NR_RX_BUF; j++) {
-		struct buf_list *rx_buf =
-				kmalloc(sizeof(struct buf_list), GFP_KERNEL);
-
-		if (rx_buf == NULL) {
-			free_netdev(pshm_dev->pshm_netdev);
-			return -ENOMEM;
-		}
-		rx_buf->index = j;
-		rx_buf->phy_addr = pshm_drv->shm_rx_addr + (RX_BUF_SZ * j);
-		rx_buf->len = RX_BUF_SZ;
-
-		if (pshm_dev->shm_loopback)
-			rx_buf->desc_vptr = (unsigned char *)rx_buf->phy_addr;
-		else
-			rx_buf->desc_vptr =
-					ioremap(rx_buf->phy_addr, RX_BUF_SZ);
-		list_add_tail(&rx_buf->list, &pshm_drv->rx_empty_list);
-	}
-
-	pshm_drv->tx_empty_available = 1;
-	result = register_netdev(pshm_dev->pshm_netdev);
-	if (result)
-		pr_warn("ERROR[%d], SHM could not, "
-			"register with NW FRMWK Bailing out ...\n", result);
-
-	return result;
-}
-
-void caif_shmcore_remove(struct net_device *pshm_netdev)
-{
-	struct buf_list *pbuf;
-	struct shmdrv_layer *pshm_drv = NULL;
-
-	pshm_drv = netdev_priv(pshm_netdev);
-
-	while (!(list_empty(&pshm_drv->tx_pend_list))) {
-		pbuf =
-			list_entry(pshm_drv->tx_pend_list.next,
-					struct buf_list, list);
-
-		list_del(&pbuf->list);
-		kfree(pbuf);
-	}
-
-	while (!(list_empty(&pshm_drv->tx_full_list))) {
-		pbuf =
-			list_entry(pshm_drv->tx_full_list.next,
-					struct buf_list, list);
-		list_del(&pbuf->list);
-		kfree(pbuf);
-	}
-
-	while (!(list_empty(&pshm_drv->tx_empty_list))) {
-		pbuf =
-			list_entry(pshm_drv->tx_empty_list.next,
-					struct buf_list, list);
-		list_del(&pbuf->list);
-		kfree(pbuf);
-	}
-
-	while (!(list_empty(&pshm_drv->rx_full_list))) {
-		pbuf =
-			list_entry(pshm_drv->tx_full_list.next,
-				struct buf_list, list);
-		list_del(&pbuf->list);
-		kfree(pbuf);
-	}
-
-	while (!(list_empty(&pshm_drv->rx_pend_list))) {
-		pbuf =
-			list_entry(pshm_drv->tx_pend_list.next,
-				struct buf_list, list);
-		list_del(&pbuf->list);
-		kfree(pbuf);
-	}
-
-	while (!(list_empty(&pshm_drv->rx_empty_list))) {
-		pbuf =
-			list_entry(pshm_drv->rx_empty_list.next,
-				struct buf_list, list);
-		list_del(&pbuf->list);
-		kfree(pbuf);
-	}
-
-	/* Destroy work queues. */
-	destroy_workqueue(pshm_drv->pshm_tx_workqueue);
-	destroy_workqueue(pshm_drv->pshm_rx_workqueue);
-
-	unregister_netdev(pshm_netdev);
-}
diff --git a/drivers/net/caif/caif_virtio.c b/drivers/net/caif/caif_virtio.c
new file mode 100644
index 0000000..0e3bede
--- /dev/null
+++ b/drivers/net/caif/caif_virtio.c
@@ -0,0 +1,790 @@
+/*
+ * Copyright (C) ST-Ericsson AB 2013
+ * Authors: Vicram Arv / vikram.arv@stericsson.com,
+ *	    Dmitry Tarnyagin / dmitry.tarnyagin@stericsson.com
+ *	    Sjur Brendeland / sjur.brandeland@stericsson.com
+ * License terms: GNU General Public License (GPL) version 2
+ */
+#include <linux/module.h>
+#include <linux/if_arp.h>
+#include <linux/virtio.h>
+#include <linux/vringh.h>
+#include <linux/debugfs.h>
+#include <linux/spinlock.h>
+#include <linux/genalloc.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/rtnetlink.h>
+#include <linux/virtio_ids.h>
+#include <linux/virtio_caif.h>
+#include <linux/virtio_ring.h>
+#include <linux/dma-mapping.h>
+#include <net/caif/caif_dev.h>
+#include <linux/virtio_config.h>
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Vicram Arv <vikram.arv@stericsson.com>");
+MODULE_AUTHOR("Sjur Brendeland <sjur.brandeland@stericsson.com>");
+MODULE_DESCRIPTION("Virtio CAIF Driver");
+
+/* NAPI schedule quota */
+#define CFV_DEFAULT_QUOTA 32
+
+/* Defaults used if virtio config space is unavailable */
+#define CFV_DEF_MTU_SIZE 4096
+#define CFV_DEF_HEADROOM 32
+#define CFV_DEF_TAILROOM 32
+
+/* Required IP header alignment */
+#define IP_HDR_ALIGN 4
+
+/* struct cfv_napi_contxt - NAPI context info
+ * @riov: IOV holding data read from the ring. Note that riov may
+ *	  still hold data when cfv_rx_poll() returns.
+ * @head: Last descriptor ID we received from vringh_getdesc_kern.
+ *	  We use this to put descriptor back on the used ring. USHRT_MAX is
+ *	  used to indicate invalid head-id.
+ */
+struct cfv_napi_context {
+	struct vringh_kiov riov;
+	unsigned short head;
+};
+
+/* struct cfv_stats - statistics for debugfs
+ * @rx_napi_complete:	Number of NAPI completions (RX)
+ * @rx_napi_resched:	Number of calls where the full quota was used (RX)
+ * @rx_nomem:		Number of SKB alloc failures (RX)
+ * @rx_kicks:		Number of RX kicks
+ * @tx_full_ring:	Number times TX ring was full
+ * @tx_no_mem:		Number of times TX went out of memory
+ * @tx_flow_on:		Number of flow on (TX)
+ * @tx_kicks:		Number of TX kicks
+ */
+struct cfv_stats {
+	u32 rx_napi_complete;
+	u32 rx_napi_resched;
+	u32 rx_nomem;
+	u32 rx_kicks;
+	u32 tx_full_ring;
+	u32 tx_no_mem;
+	u32 tx_flow_on;
+	u32 tx_kicks;
+};
+
+/* struct cfv_info - Caif Virtio control structure
+ * @cfdev:	caif common header
+ * @vdev:	Associated virtio device
+ * @vr_rx:	rx/downlink host vring
+ * @vq_tx:	tx/uplink virtqueue
+ * @ndev:	CAIF link layer device
+ * @watermark_tx: indicates number of free descriptors we need
+ *		to reopen the tx-queues after overload.
+ * @tx_lock:	protects vq_tx from concurrent use
+ * @tx_release_tasklet: Tasklet for freeing consumed TX buffers
+ * @napi:       Napi context used in cfv_rx_poll()
+ * @ctx:        Context data used in cfv_rx_poll()
+ * @tx_hr:	transmit headroom
+ * @rx_hr:	receive headroom
+ * @tx_tr:	transmit tail room
+ * @rx_tr:	receive tail room
+ * @mtu:	transmit max size
+ * @mru:	receive max size
+ * @allocsz:    size of dma memory reserved for TX buffers
+ * @alloc_addr: virtual address to dma memory for TX buffers
+ * @alloc_dma:  dma address to dma memory for TX buffers
+ * @genpool:    Gen Pool used for allocating TX buffers
+ * @reserved_mem: Pointer to memory reserve allocated from genpool
+ * @reserved_size: Size of memory reserve allocated from genpool
+ * @stats:       Statistics exposed in sysfs
+ * @debugfs:    Debugfs dentry for statistic counters
+ */
+struct cfv_info {
+	struct caif_dev_common cfdev;
+	struct virtio_device *vdev;
+	struct vringh *vr_rx;
+	struct virtqueue *vq_tx;
+	struct net_device *ndev;
+	unsigned int watermark_tx;
+	/* Protect access to vq_tx */
+	spinlock_t tx_lock;
+	struct tasklet_struct tx_release_tasklet;
+	struct napi_struct napi;
+	struct cfv_napi_context ctx;
+	u16 tx_hr;
+	u16 rx_hr;
+	u16 tx_tr;
+	u16 rx_tr;
+	u32 mtu;
+	u32 mru;
+	size_t allocsz;
+	void *alloc_addr;
+	dma_addr_t alloc_dma;
+	struct gen_pool *genpool;
+	unsigned long reserved_mem;
+	size_t reserved_size;
+	struct cfv_stats stats;
+	struct dentry *debugfs;
+};
+
+/* struct buf_info - maintains transmit buffer data handle
+ * @size:	size of transmit buffer
+ * @dma_handle: handle to allocated dma device memory area
+ * @vaddr:	virtual address mapping to allocated memory area
+ */
+struct buf_info {
+	size_t size;
+	u8 *vaddr;
+};
+
+/* Called from virtio device, in IRQ context */
+static void cfv_release_cb(struct virtqueue *vq_tx)
+{
+	struct cfv_info *cfv = vq_tx->vdev->priv;
+
+	++cfv->stats.tx_kicks;
+	tasklet_schedule(&cfv->tx_release_tasklet);
+}
+
+static void free_buf_info(struct cfv_info *cfv, struct buf_info *buf_info)
+{
+	if (!buf_info)
+		return;
+	gen_pool_free(cfv->genpool, (unsigned long) buf_info->vaddr,
+		      buf_info->size);
+	kfree(buf_info);
+}
+
+/* This is invoked whenever the remote processor completed processing
+ * a TX msg we just sent, and the buffer is put back to the used ring.
+ */
+static void cfv_release_used_buf(struct virtqueue *vq_tx)
+{
+	struct cfv_info *cfv = vq_tx->vdev->priv;
+	unsigned long flags;
+
+	BUG_ON(vq_tx != cfv->vq_tx);
+
+	for (;;) {
+		unsigned int len;
+		struct buf_info *buf_info;
+
+		/* Get used buffer from used ring to recycle used descriptors */
+		spin_lock_irqsave(&cfv->tx_lock, flags);
+		buf_info = virtqueue_get_buf(vq_tx, &len);
+		spin_unlock_irqrestore(&cfv->tx_lock, flags);
+
+		/* Stop looping if there are no more buffers to free */
+		if (!buf_info)
+			break;
+
+		free_buf_info(cfv, buf_info);
+
+		/* watermark_tx indicates if we previously stopped the tx
+		 * queues. If we have enough free stots in the virtio ring,
+		 * re-establish memory reserved and open up tx queues.
+		 */
+		if (cfv->vq_tx->num_free <= cfv->watermark_tx)
+			continue;
+
+		/* Re-establish memory reserve */
+		if (cfv->reserved_mem == 0 && cfv->genpool)
+			cfv->reserved_mem =
+				gen_pool_alloc(cfv->genpool,
+					       cfv->reserved_size);
+
+		/* Open up the tx queues */
+		if (cfv->reserved_mem) {
+			cfv->watermark_tx =
+				virtqueue_get_vring_size(cfv->vq_tx);
+			netif_tx_wake_all_queues(cfv->ndev);
+			/* Buffers are recycled in cfv_netdev_tx, so
+			 * disable notifications when queues are opened.
+			 */
+			virtqueue_disable_cb(cfv->vq_tx);
+			++cfv->stats.tx_flow_on;
+		} else {
+			/* if no memory reserve, wait for more free slots */
+			WARN_ON(cfv->watermark_tx >
+			       virtqueue_get_vring_size(cfv->vq_tx));
+			cfv->watermark_tx +=
+				virtqueue_get_vring_size(cfv->vq_tx) / 4;
+		}
+	}
+}
+
+/* Allocate a SKB and copy packet data to it */
+static struct sk_buff *cfv_alloc_and_copy_skb(int *err,
+					      struct cfv_info *cfv,
+					      u8 *frm, u32 frm_len)
+{
+	struct sk_buff *skb;
+	u32 cfpkt_len, pad_len;
+
+	*err = 0;
+	/* Verify that packet size with down-link header and mtu size */
+	if (frm_len > cfv->mru || frm_len <= cfv->rx_hr + cfv->rx_tr) {
+		netdev_err(cfv->ndev,
+			   "Invalid frmlen:%u  mtu:%u hr:%d tr:%d\n",
+			   frm_len, cfv->mru,  cfv->rx_hr,
+			   cfv->rx_tr);
+		*err = -EPROTO;
+		return NULL;
+	}
+
+	cfpkt_len = frm_len - (cfv->rx_hr + cfv->rx_tr);
+	pad_len = (unsigned long)(frm + cfv->rx_hr) & (IP_HDR_ALIGN - 1);
+
+	skb = netdev_alloc_skb(cfv->ndev, frm_len + pad_len);
+	if (!skb) {
+		*err = -ENOMEM;
+		return NULL;
+	}
+
+	skb_reserve(skb, cfv->rx_hr + pad_len);
+
+	memcpy(skb_put(skb, cfpkt_len), frm + cfv->rx_hr, cfpkt_len);
+	return skb;
+}
+
+/* Get packets from the host vring */
+static int cfv_rx_poll(struct napi_struct *napi, int quota)
+{
+	struct cfv_info *cfv = container_of(napi, struct cfv_info, napi);
+	int rxcnt = 0;
+	int err = 0;
+	void *buf;
+	struct sk_buff *skb;
+	struct vringh_kiov *riov = &cfv->ctx.riov;
+	unsigned int skb_len;
+
+again:
+	do {
+		skb = NULL;
+
+		/* Put the previous iovec back on the used ring and
+		 * fetch a new iovec if we have processed all elements.
+		 */
+		if (riov->i == riov->used) {
+			if (cfv->ctx.head != USHRT_MAX) {
+				vringh_complete_kern(cfv->vr_rx,
+						     cfv->ctx.head,
+						     0);
+				cfv->ctx.head = USHRT_MAX;
+			}
+
+			err = vringh_getdesc_kern(
+				cfv->vr_rx,
+				riov,
+				NULL,
+				&cfv->ctx.head,
+				GFP_ATOMIC);
+
+			if (err <= 0)
+				goto exit;
+		}
+
+		buf = phys_to_virt((unsigned long) riov->iov[riov->i].iov_base);
+		/* TODO: Add check on valid buffer address */
+
+		skb = cfv_alloc_and_copy_skb(&err, cfv, buf,
+					     riov->iov[riov->i].iov_len);
+		if (unlikely(err))
+			goto exit;
+
+		/* Push received packet up the stack. */
+		skb_len = skb->len;
+		skb->protocol = htons(ETH_P_CAIF);
+		skb_reset_mac_header(skb);
+		skb->dev = cfv->ndev;
+		err = netif_receive_skb(skb);
+		if (unlikely(err)) {
+			++cfv->ndev->stats.rx_dropped;
+		} else {
+			++cfv->ndev->stats.rx_packets;
+			cfv->ndev->stats.rx_bytes += skb_len;
+		}
+
+		++riov->i;
+		++rxcnt;
+	} while (rxcnt < quota);
+
+	++cfv->stats.rx_napi_resched;
+	goto out;
+
+exit:
+	switch (err) {
+	case 0:
+		++cfv->stats.rx_napi_complete;
+
+		/* Really out of patckets? (stolen from virtio_net)*/
+		napi_complete(napi);
+		if (unlikely(!vringh_notify_enable_kern(cfv->vr_rx)) &&
+		    napi_schedule_prep(napi)) {
+			vringh_notify_disable_kern(cfv->vr_rx);
+			__napi_schedule(napi);
+			goto again;
+		}
+		break;
+
+	case -ENOMEM:
+		++cfv->stats.rx_nomem;
+		dev_kfree_skb(skb);
+		/* Stop NAPI poll on OOM, we hope to be polled later */
+		napi_complete(napi);
+		vringh_notify_enable_kern(cfv->vr_rx);
+		break;
+
+	default:
+		/* We're doomed, any modem fault is fatal */
+		netdev_warn(cfv->ndev, "Bad ring, disable device\n");
+		cfv->ndev->stats.rx_dropped = riov->used - riov->i;
+		napi_complete(napi);
+		vringh_notify_disable_kern(cfv->vr_rx);
+		netif_carrier_off(cfv->ndev);
+		break;
+	}
+out:
+	if (rxcnt && vringh_need_notify_kern(cfv->vr_rx) > 0)
+		vringh_notify(cfv->vr_rx);
+	return rxcnt;
+}
+
+static void cfv_recv(struct virtio_device *vdev, struct vringh *vr_rx)
+{
+	struct cfv_info *cfv = vdev->priv;
+
+	++cfv->stats.rx_kicks;
+	vringh_notify_disable_kern(cfv->vr_rx);
+	napi_schedule(&cfv->napi);
+}
+
+static void cfv_destroy_genpool(struct cfv_info *cfv)
+{
+	if (cfv->alloc_addr)
+		dma_free_coherent(cfv->vdev->dev.parent->parent,
+				  cfv->allocsz, cfv->alloc_addr,
+				  cfv->alloc_dma);
+
+	if (!cfv->genpool)
+		return;
+	gen_pool_free(cfv->genpool,  cfv->reserved_mem,
+		      cfv->reserved_size);
+	gen_pool_destroy(cfv->genpool);
+	cfv->genpool = NULL;
+}
+
+static int cfv_create_genpool(struct cfv_info *cfv)
+{
+	int err;
+
+	/* dma_alloc can only allocate whole pages, and we need a more
+	 * fine graned allocation so we use genpool. We ask for space needed
+	 * by IP and a full ring. If the dma allcoation fails we retry with a
+	 * smaller allocation size.
+	 */
+	err = -ENOMEM;
+	cfv->allocsz = (virtqueue_get_vring_size(cfv->vq_tx) *
+			(ETH_DATA_LEN + cfv->tx_hr + cfv->tx_tr) * 11)/10;
+	if (cfv->allocsz <= (num_possible_cpus() + 1) * cfv->ndev->mtu)
+		return -EINVAL;
+
+	for (;;) {
+		if (cfv->allocsz <= num_possible_cpus() * cfv->ndev->mtu) {
+			netdev_info(cfv->ndev, "Not enough device memory\n");
+			return -ENOMEM;
+		}
+
+		cfv->alloc_addr = dma_alloc_coherent(
+						cfv->vdev->dev.parent->parent,
+						cfv->allocsz, &cfv->alloc_dma,
+						GFP_ATOMIC);
+		if (cfv->alloc_addr)
+			break;
+
+		cfv->allocsz = (cfv->allocsz * 3) >> 2;
+	}
+
+	netdev_dbg(cfv->ndev, "Allocated %zd bytes from dma-memory\n",
+		   cfv->allocsz);
+
+	/* Allocate on 128 bytes boundaries (1 << 7)*/
+	cfv->genpool = gen_pool_create(7, -1);
+	if (!cfv->genpool)
+		goto err;
+
+	err = gen_pool_add_virt(cfv->genpool, (unsigned long)cfv->alloc_addr,
+				(phys_addr_t)virt_to_phys(cfv->alloc_addr),
+				cfv->allocsz, -1);
+	if (err)
+		goto err;
+
+	/* Reserve some memory for low memory situations. If we hit the roof
+	 * in the memory pool, we stop TX flow and release the reserve.
+	 */
+	cfv->reserved_size = num_possible_cpus() * cfv->ndev->mtu;
+	cfv->reserved_mem = gen_pool_alloc(cfv->genpool,
+					   cfv->reserved_size);
+	if (!cfv->reserved_mem) {
+		err = -ENOMEM;
+		goto err;
+	}
+
+	cfv->watermark_tx = virtqueue_get_vring_size(cfv->vq_tx);
+	return 0;
+err:
+	cfv_destroy_genpool(cfv);
+	return err;
+}
+
+/* Enable the CAIF interface and allocate the memory-pool */
+static int cfv_netdev_open(struct net_device *netdev)
+{
+	struct cfv_info *cfv = netdev_priv(netdev);
+
+	if (cfv_create_genpool(cfv))
+		return -ENOMEM;
+
+	netif_carrier_on(netdev);
+	napi_enable(&cfv->napi);
+
+	/* Schedule NAPI to read any pending packets */
+	napi_schedule(&cfv->napi);
+	return 0;
+}
+
+/* Disable the CAIF interface and free the memory-pool */
+static int cfv_netdev_close(struct net_device *netdev)
+{
+	struct cfv_info *cfv = netdev_priv(netdev);
+	unsigned long flags;
+	struct buf_info *buf_info;
+
+	/* Disable interrupts, queues and NAPI polling */
+	netif_carrier_off(netdev);
+	virtqueue_disable_cb(cfv->vq_tx);
+	vringh_notify_disable_kern(cfv->vr_rx);
+	napi_disable(&cfv->napi);
+
+	/* Release any TX buffers on both used and avilable rings */
+	cfv_release_used_buf(cfv->vq_tx);
+	spin_lock_irqsave(&cfv->tx_lock, flags);
+	while ((buf_info = virtqueue_detach_unused_buf(cfv->vq_tx)))
+		free_buf_info(cfv, buf_info);
+	spin_unlock_irqrestore(&cfv->tx_lock, flags);
+
+	/* Release all dma allocated memory and destroy the pool */
+	cfv_destroy_genpool(cfv);
+	return 0;
+}
+
+/* Allocate a buffer in dma-memory and copy skb to it */
+static struct buf_info *cfv_alloc_and_copy_to_shm(struct cfv_info *cfv,
+						       struct sk_buff *skb,
+						       struct scatterlist *sg)
+{
+	struct caif_payload_info *info = (void *)&skb->cb;
+	struct buf_info *buf_info = NULL;
+	u8 pad_len, hdr_ofs;
+
+	if (!cfv->genpool)
+		goto err;
+
+	if (unlikely(cfv->tx_hr + skb->len + cfv->tx_tr > cfv->mtu)) {
+		netdev_warn(cfv->ndev, "Invalid packet len (%d > %d)\n",
+			    cfv->tx_hr + skb->len + cfv->tx_tr, cfv->mtu);
+		goto err;
+	}
+
+	buf_info = kmalloc(sizeof(struct buf_info), GFP_ATOMIC);
+	if (unlikely(!buf_info))
+		goto err;
+
+	/* Make the IP header aligned in tbe buffer */
+	hdr_ofs = cfv->tx_hr + info->hdr_len;
+	pad_len = hdr_ofs & (IP_HDR_ALIGN - 1);
+	buf_info->size = cfv->tx_hr + skb->len + cfv->tx_tr + pad_len;
+
+	/* allocate dma memory buffer */
+	buf_info->vaddr = (void *)gen_pool_alloc(cfv->genpool, buf_info->size);
+	if (unlikely(!buf_info->vaddr))
+		goto err;
+
+	/* copy skbuf contents to send buffer */
+	skb_copy_bits(skb, 0, buf_info->vaddr + cfv->tx_hr + pad_len, skb->len);
+	sg_init_one(sg, buf_info->vaddr + pad_len,
+		    skb->len + cfv->tx_hr + cfv->rx_hr);
+
+	return buf_info;
+err:
+	kfree(buf_info);
+	return NULL;
+}
+
+/* Put the CAIF packet on the virtio ring and kick the receiver */
+static int cfv_netdev_tx(struct sk_buff *skb, struct net_device *netdev)
+{
+	struct cfv_info *cfv = netdev_priv(netdev);
+	struct buf_info *buf_info;
+	struct scatterlist sg;
+	unsigned long flags;
+	bool flow_off = false;
+	int ret;
+
+	/* garbage collect released buffers */
+	cfv_release_used_buf(cfv->vq_tx);
+	spin_lock_irqsave(&cfv->tx_lock, flags);
+
+	/* Flow-off check takes into account number of cpus to make sure
+	 * virtqueue will not be overfilled in any possible smp conditions.
+	 *
+	 * Flow-on is triggered when sufficient buffers are freed
+	 */
+	if (unlikely(cfv->vq_tx->num_free <= num_present_cpus())) {
+		flow_off = true;
+		cfv->stats.tx_full_ring++;
+	}
+
+	/* If we run out of memory, we release the memory reserve and retry
+	 * allocation.
+	 */
+	buf_info = cfv_alloc_and_copy_to_shm(cfv, skb, &sg);
+	if (unlikely(!buf_info)) {
+		cfv->stats.tx_no_mem++;
+		flow_off = true;
+
+		if (cfv->reserved_mem && cfv->genpool) {
+			gen_pool_free(cfv->genpool,  cfv->reserved_mem,
+				      cfv->reserved_size);
+			cfv->reserved_mem = 0;
+			buf_info = cfv_alloc_and_copy_to_shm(cfv, skb, &sg);
+		}
+	}
+
+	if (unlikely(flow_off)) {
+		/* Turn flow on when a 1/4 of the descriptors are released */
+		cfv->watermark_tx = virtqueue_get_vring_size(cfv->vq_tx) / 4;
+		/* Enable notifications of recycled TX buffers */
+		virtqueue_enable_cb(cfv->vq_tx);
+		netif_tx_stop_all_queues(netdev);
+	}
+
+	if (unlikely(!buf_info)) {
+		/* If the memory reserve does it's job, this shouldn't happen */
+		netdev_warn(cfv->ndev, "Out of gen_pool memory\n");
+		goto err;
+	}
+
+	ret = virtqueue_add_outbuf(cfv->vq_tx, &sg, 1, buf_info, GFP_ATOMIC);
+	if (unlikely((ret < 0))) {
+		/* If flow control works, this shouldn't happen */
+		netdev_warn(cfv->ndev, "Failed adding buffer to TX vring:%d\n",
+			    ret);
+		goto err;
+	}
+
+	/* update netdev statistics */
+	cfv->ndev->stats.tx_packets++;
+	cfv->ndev->stats.tx_bytes += skb->len;
+	spin_unlock_irqrestore(&cfv->tx_lock, flags);
+
+	/* tell the remote processor it has a pending message to read */
+	virtqueue_kick(cfv->vq_tx);
+
+	dev_kfree_skb(skb);
+	return NETDEV_TX_OK;
+err:
+	spin_unlock_irqrestore(&cfv->tx_lock, flags);
+	cfv->ndev->stats.tx_dropped++;
+	free_buf_info(cfv, buf_info);
+	dev_kfree_skb(skb);
+	return NETDEV_TX_OK;
+}
+
+static void cfv_tx_release_tasklet(unsigned long drv)
+{
+	struct cfv_info *cfv = (struct cfv_info *)drv;
+	cfv_release_used_buf(cfv->vq_tx);
+}
+
+static const struct net_device_ops cfv_netdev_ops = {
+	.ndo_open = cfv_netdev_open,
+	.ndo_stop = cfv_netdev_close,
+	.ndo_start_xmit = cfv_netdev_tx,
+};
+
+static void cfv_netdev_setup(struct net_device *netdev)
+{
+	netdev->netdev_ops = &cfv_netdev_ops;
+	netdev->type = ARPHRD_CAIF;
+	netdev->tx_queue_len = 100;
+	netdev->flags = IFF_POINTOPOINT | IFF_NOARP;
+	netdev->mtu = CFV_DEF_MTU_SIZE;
+	netdev->destructor = free_netdev;
+}
+
+/* Create debugfs counters for the device */
+static inline void debugfs_init(struct cfv_info *cfv)
+{
+	cfv->debugfs =
+		debugfs_create_dir(netdev_name(cfv->ndev), NULL);
+
+	if (IS_ERR(cfv->debugfs))
+		return;
+
+	debugfs_create_u32("rx-napi-complete", S_IRUSR, cfv->debugfs,
+			   &cfv->stats.rx_napi_complete);
+	debugfs_create_u32("rx-napi-resched", S_IRUSR, cfv->debugfs,
+			   &cfv->stats.rx_napi_resched);
+	debugfs_create_u32("rx-nomem", S_IRUSR, cfv->debugfs,
+			   &cfv->stats.rx_nomem);
+	debugfs_create_u32("rx-kicks", S_IRUSR, cfv->debugfs,
+			   &cfv->stats.rx_kicks);
+	debugfs_create_u32("tx-full-ring", S_IRUSR, cfv->debugfs,
+			   &cfv->stats.tx_full_ring);
+	debugfs_create_u32("tx-no-mem", S_IRUSR, cfv->debugfs,
+			   &cfv->stats.tx_no_mem);
+	debugfs_create_u32("tx-kicks", S_IRUSR, cfv->debugfs,
+			   &cfv->stats.tx_kicks);
+	debugfs_create_u32("tx-flow-on", S_IRUSR, cfv->debugfs,
+			   &cfv->stats.tx_flow_on);
+}
+
+/* Setup CAIF for the a virtio device */
+static int cfv_probe(struct virtio_device *vdev)
+{
+	vq_callback_t *vq_cbs = cfv_release_cb;
+	vrh_callback_t *vrh_cbs = cfv_recv;
+	const char *names =  "output";
+	const char *cfv_netdev_name = "cfvrt";
+	struct net_device *netdev;
+	struct cfv_info *cfv;
+	int err = -EINVAL;
+
+	netdev = alloc_netdev(sizeof(struct cfv_info), cfv_netdev_name,
+			      cfv_netdev_setup);
+	if (!netdev)
+		return -ENOMEM;
+
+	cfv = netdev_priv(netdev);
+	cfv->vdev = vdev;
+	cfv->ndev = netdev;
+
+	spin_lock_init(&cfv->tx_lock);
+
+	/* Get the RX virtio ring. This is a "host side vring". */
+	err = -ENODEV;
+	if (!vdev->vringh_config || !vdev->vringh_config->find_vrhs)
+		goto err;
+
+	err = vdev->vringh_config->find_vrhs(vdev, 1, &cfv->vr_rx, &vrh_cbs);
+	if (err)
+		goto err;
+
+	/* Get the TX virtio ring. This is a "guest side vring". */
+	err = vdev->config->find_vqs(vdev, 1, &cfv->vq_tx, &vq_cbs, &names);
+	if (err)
+		goto err;
+
+	/* Get the CAIF configuration from virtio config space, if available */
+#define GET_VIRTIO_CONFIG_OPS(_v, _var, _f) \
+	((_v)->config->get(_v, offsetof(struct virtio_caif_transf_config, _f), \
+			   &_var, \
+			   FIELD_SIZEOF(struct virtio_caif_transf_config, _f)))
+
+	if (vdev->config->get) {
+		GET_VIRTIO_CONFIG_OPS(vdev, cfv->tx_hr, headroom);
+		GET_VIRTIO_CONFIG_OPS(vdev, cfv->rx_hr, headroom);
+		GET_VIRTIO_CONFIG_OPS(vdev, cfv->tx_tr, tailroom);
+		GET_VIRTIO_CONFIG_OPS(vdev, cfv->rx_tr, tailroom);
+		GET_VIRTIO_CONFIG_OPS(vdev, cfv->mtu, mtu);
+		GET_VIRTIO_CONFIG_OPS(vdev, cfv->mru, mtu);
+	} else {
+		cfv->tx_hr = CFV_DEF_HEADROOM;
+		cfv->rx_hr = CFV_DEF_HEADROOM;
+		cfv->tx_tr = CFV_DEF_TAILROOM;
+		cfv->rx_tr = CFV_DEF_TAILROOM;
+		cfv->mtu = CFV_DEF_MTU_SIZE;
+		cfv->mru = CFV_DEF_MTU_SIZE;
+	}
+
+	netdev->needed_headroom = cfv->tx_hr;
+	netdev->needed_tailroom = cfv->tx_tr;
+
+	/* Disable buffer release interrupts unless we have stopped TX queues */
+	virtqueue_disable_cb(cfv->vq_tx);
+
+	netdev->mtu = cfv->mtu - cfv->tx_tr;
+	vdev->priv = cfv;
+
+	/* Initialize NAPI poll context data */
+	vringh_kiov_init(&cfv->ctx.riov, NULL, 0);
+	cfv->ctx.head = USHRT_MAX;
+	netif_napi_add(netdev, &cfv->napi, cfv_rx_poll, CFV_DEFAULT_QUOTA);
+
+	tasklet_init(&cfv->tx_release_tasklet,
+		     cfv_tx_release_tasklet,
+		     (unsigned long)cfv);
+
+	/* Carrier is off until netdevice is opened */
+	netif_carrier_off(netdev);
+
+	/* register Netdev */
+	err = register_netdev(netdev);
+	if (err) {
+		dev_err(&vdev->dev, "Unable to register netdev (%d)\n", err);
+		goto err;
+	}
+
+	debugfs_init(cfv);
+
+	return 0;
+err:
+	netdev_warn(cfv->ndev, "CAIF Virtio probe failed:%d\n", err);
+
+	if (cfv->vr_rx)
+		vdev->vringh_config->del_vrhs(cfv->vdev);
+	if (cfv->vdev)
+		vdev->config->del_vqs(cfv->vdev);
+	free_netdev(netdev);
+	return err;
+}
+
+static void cfv_remove(struct virtio_device *vdev)
+{
+	struct cfv_info *cfv = vdev->priv;
+
+	rtnl_lock();
+	dev_close(cfv->ndev);
+	rtnl_unlock();
+
+	tasklet_kill(&cfv->tx_release_tasklet);
+	debugfs_remove_recursive(cfv->debugfs);
+
+	vringh_kiov_cleanup(&cfv->ctx.riov);
+	vdev->config->reset(vdev);
+	vdev->vringh_config->del_vrhs(cfv->vdev);
+	cfv->vr_rx = NULL;
+	vdev->config->del_vqs(cfv->vdev);
+	unregister_netdev(cfv->ndev);
+}
+
+static struct virtio_device_id id_table[] = {
+	{ VIRTIO_ID_CAIF, VIRTIO_DEV_ANY_ID },
+	{ 0 },
+};
+
+static unsigned int features[] = {
+};
+
+static struct virtio_driver caif_virtio_driver = {
+	.feature_table		= features,
+	.feature_table_size	= ARRAY_SIZE(features),
+	.driver.name		= KBUILD_MODNAME,
+	.driver.owner		= THIS_MODULE,
+	.id_table		= id_table,
+	.probe			= cfv_probe,
+	.remove			= cfv_remove,
+};
+
+module_virtio_driver(caif_virtio_driver);
+MODULE_DEVICE_TABLE(virtio, id_table);
diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
index 9862b2e..e456b70 100644
--- a/drivers/net/can/Kconfig
+++ b/drivers/net/can/Kconfig
@@ -65,7 +65,7 @@ config CAN_LEDS
 
 config CAN_AT91
 	tristate "Atmel AT91 onchip CAN controller"
-	depends on ARCH_AT91SAM9263 || ARCH_AT91SAM9X5
+	depends on ARM
 	---help---
 	  This is a driver for the SoC CAN controller in Atmel's AT91SAM9263
 	  and AT91SAM9X5 processors.
diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c
index 44f3637..db52f441 100644
--- a/drivers/net/can/at91_can.c
+++ b/drivers/net/can/at91_can.c
@@ -27,6 +27,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/netdevice.h>
+#include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/rtnetlink.h>
 #include <linux/skbuff.h>
@@ -155,19 +156,20 @@ struct at91_priv {
 	canid_t mb0_id;
 };
 
-static const struct at91_devtype_data at91_devtype_data[] = {
-	[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 const struct at91_devtype_data at91_at91sam9263_data = {
+	.rx_first = 1,
+	.rx_split = 8,
+	.rx_last = 11,
+	.tx_shift = 2,
+	.type = AT91_DEVTYPE_SAM9263,
+};
+
+static const struct at91_devtype_data at91_at91sam9x5_data = {
+	.rx_first = 0,
+	.rx_split = 4,
+	.rx_last = 5,
+	.tx_shift = 1,
+	.type = AT91_DEVTYPE_SAM9X5,
 };
 
 static const struct can_bittiming_const at91_bittiming_const = {
@@ -1249,10 +1251,42 @@ static struct attribute_group at91_sysfs_attr_group = {
 	.attrs = at91_sysfs_attrs,
 };
 
+#if defined(CONFIG_OF)
+static const struct of_device_id at91_can_dt_ids[] = {
+	{
+		.compatible = "atmel,at91sam9x5-can",
+		.data = &at91_at91sam9x5_data,
+	}, {
+		.compatible = "atmel,at91sam9263-can",
+		.data = &at91_at91sam9263_data,
+	}, {
+		/* sentinel */
+	}
+};
+MODULE_DEVICE_TABLE(of, at91_can_dt_ids);
+#else
+#define at91_can_dt_ids NULL
+#endif
+
+static const struct at91_devtype_data *at91_can_get_driver_data(struct platform_device *pdev)
+{
+	if (pdev->dev.of_node) {
+		const struct of_device_id *match;
+
+		match = of_match_node(at91_can_dt_ids, pdev->dev.of_node);
+		if (!match) {
+			dev_err(&pdev->dev, "no matching node found in dtb\n");
+			return NULL;
+		}
+		return (const struct at91_devtype_data *)match->data;
+	}
+	return (const struct at91_devtype_data *)
+		platform_get_device_id(pdev)->driver_data;
+}
+
 static int 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;
@@ -1260,8 +1294,12 @@ static int 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];
+	devtype_data = at91_can_get_driver_data(pdev);
+	if (!devtype_data) {
+		dev_err(&pdev->dev, "no driver data\n");
+		err = -ENODEV;
+		goto exit;
+	}
 
 	clk = clk_get(&pdev->dev, "can_clk");
 	if (IS_ERR(clk)) {
@@ -1310,7 +1348,6 @@ static int at91_can_probe(struct platform_device *pdev)
 	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;
@@ -1373,10 +1410,10 @@ static int at91_can_remove(struct platform_device *pdev)
 static const struct platform_device_id at91_can_id_table[] = {
 	{
 		.name = "at91_can",
-		.driver_data = AT91_DEVTYPE_SAM9263,
+		.driver_data = (kernel_ulong_t)&at91_at91sam9x5_data,
 	}, {
 		.name = "at91sam9x5_can",
-		.driver_data = AT91_DEVTYPE_SAM9X5,
+		.driver_data = (kernel_ulong_t)&at91_at91sam9263_data,
 	}, {
 		/* sentinel */
 	}
@@ -1389,6 +1426,7 @@ static struct platform_driver at91_can_driver = {
 	.driver = {
 		.name = KBUILD_MODNAME,
 		.owner = THIS_MODULE,
+		.of_match_table = at91_can_dt_ids,
 	},
 	.id_table = at91_can_id_table,
 };
diff --git a/drivers/net/can/bfin_can.c b/drivers/net/can/bfin_can.c
index 6a05321..d4a15e8 100644
--- a/drivers/net/can/bfin_can.c
+++ b/drivers/net/can/bfin_can.c
@@ -412,7 +412,7 @@ static int bfin_can_err(struct net_device *dev, u16 isrc, u16 status)
 	return 0;
 }
 
-irqreturn_t bfin_can_interrupt(int irq, void *dev_id)
+static irqreturn_t bfin_can_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	struct bfin_can_priv *priv = netdev_priv(dev);
@@ -504,7 +504,7 @@ static int bfin_can_close(struct net_device *dev)
 	return 0;
 }
 
-struct net_device *alloc_bfin_candev(void)
+static struct net_device *alloc_bfin_candev(void)
 {
 	struct net_device *dev;
 	struct bfin_can_priv *priv;
diff --git a/drivers/net/can/mcp251x.c b/drivers/net/can/mcp251x.c
index f32b9fc..2b620c8 100644
--- a/drivers/net/can/mcp251x.c
+++ b/drivers/net/can/mcp251x.c
@@ -1138,9 +1138,11 @@ static int mcp251x_can_remove(struct spi_device *spi)
 	return 0;
 }
 
-#ifdef CONFIG_PM
-static int mcp251x_can_suspend(struct spi_device *spi, pm_message_t state)
+#ifdef CONFIG_PM_SLEEP
+
+static int mcp251x_can_suspend(struct device *dev)
 {
+	struct spi_device *spi = to_spi_device(dev);
 	struct mcp251x_platform_data *pdata = spi->dev.platform_data;
 	struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
 	struct net_device *net = priv->net;
@@ -1170,8 +1172,9 @@ static int mcp251x_can_suspend(struct spi_device *spi, pm_message_t state)
 	return 0;
 }
 
-static int mcp251x_can_resume(struct spi_device *spi)
+static int mcp251x_can_resume(struct device *dev)
 {
+	struct spi_device *spi = to_spi_device(dev);
 	struct mcp251x_platform_data *pdata = spi->dev.platform_data;
 	struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
 
@@ -1191,9 +1194,13 @@ static int mcp251x_can_resume(struct spi_device *spi)
 	enable_irq(spi->irq);
 	return 0;
 }
+
+static SIMPLE_DEV_PM_OPS(mcp251x_can_pm_ops, mcp251x_can_suspend,
+	mcp251x_can_resume);
+#define MCP251X_PM_OPS (&mcp251x_can_pm_ops)
+
 #else
-#define mcp251x_can_suspend NULL
-#define mcp251x_can_resume NULL
+#define MCP251X_PM_OPS NULL
 #endif
 
 static const struct spi_device_id mcp251x_id_table[] = {
@@ -1207,29 +1214,15 @@ MODULE_DEVICE_TABLE(spi, mcp251x_id_table);
 static struct spi_driver mcp251x_can_driver = {
 	.driver = {
 		.name = DEVICE_NAME,
-		.bus = &spi_bus_type,
 		.owner = THIS_MODULE,
+		.pm = MCP251X_PM_OPS,
 	},
 
 	.id_table = mcp251x_id_table,
 	.probe = mcp251x_can_probe,
 	.remove = mcp251x_can_remove,
-	.suspend = mcp251x_can_suspend,
-	.resume = mcp251x_can_resume,
 };
-
-static int __init mcp251x_can_init(void)
-{
-	return spi_register_driver(&mcp251x_can_driver);
-}
-
-static void __exit mcp251x_can_exit(void)
-{
-	spi_unregister_driver(&mcp251x_can_driver);
-}
-
-module_init(mcp251x_can_init);
-module_exit(mcp251x_can_exit);
+module_spi_driver(mcp251x_can_driver);
 
 MODULE_AUTHOR("Chris Elston <celston@katalix.com>, "
 	      "Christian Pellegrin <chripell@evolware.org>");
diff --git a/drivers/net/can/sja1000/Kconfig b/drivers/net/can/sja1000/Kconfig
index b39ca5b..ff2ba86 100644
--- a/drivers/net/can/sja1000/Kconfig
+++ b/drivers/net/can/sja1000/Kconfig
@@ -46,6 +46,7 @@ config CAN_EMS_PCI
 config CAN_PEAK_PCMCIA
 	tristate "PEAK PCAN-PC Card"
 	depends on PCMCIA
+	depends on HAS_IOPORT
 	---help---
 	  This driver is for the PCAN-PC Card PCMCIA adapter (1 or 2 channels)
 	  from PEAK-System (http://www.peak-system.com). To compile this
diff --git a/drivers/net/can/sja1000/ems_pcmcia.c b/drivers/net/can/sja1000/ems_pcmcia.c
index 5c2f3fb..321c27e 100644
--- a/drivers/net/can/sja1000/ems_pcmcia.c
+++ b/drivers/net/can/sja1000/ems_pcmcia.c
@@ -316,15 +316,4 @@ static struct pcmcia_driver ems_pcmcia_driver = {
 	.remove = ems_pcmcia_remove,
 	.id_table = ems_pcmcia_tbl,
 };
-
-static int __init ems_pcmcia_init(void)
-{
-	return pcmcia_register_driver(&ems_pcmcia_driver);
-}
-module_init(ems_pcmcia_init);
-
-static void __exit ems_pcmcia_exit(void)
-{
-	pcmcia_unregister_driver(&ems_pcmcia_driver);
-}
-module_exit(ems_pcmcia_exit);
+module_pcmcia_driver(ems_pcmcia_driver);
diff --git a/drivers/net/can/sja1000/peak_pcmcia.c b/drivers/net/can/sja1000/peak_pcmcia.c
index 1a7020b..0a707f7 100644
--- a/drivers/net/can/sja1000/peak_pcmcia.c
+++ b/drivers/net/can/sja1000/peak_pcmcia.c
@@ -740,15 +740,4 @@ static struct pcmcia_driver pcan_driver = {
 	.remove = pcan_remove,
 	.id_table = pcan_table,
 };
-
-static int __init pcan_init(void)
-{
-	return pcmcia_register_driver(&pcan_driver);
-}
-module_init(pcan_init);
-
-static void __exit pcan_exit(void)
-{
-	pcmcia_unregister_driver(&pcan_driver);
-}
-module_exit(pcan_exit);
+module_pcmcia_driver(pcan_driver);
diff --git a/drivers/net/can/sja1000/plx_pci.c b/drivers/net/can/sja1000/plx_pci.c
index a042cdc..3c18d7d 100644
--- a/drivers/net/can/sja1000/plx_pci.c
+++ b/drivers/net/can/sja1000/plx_pci.c
@@ -348,7 +348,7 @@ static inline int plx_pci_check_sja1000(const struct sja1000_priv *priv)
 	 */
 	if ((priv->read_reg(priv, REG_CR) & REG_CR_BASICCAN_INITIAL_MASK) ==
 	    REG_CR_BASICCAN_INITIAL &&
-	    (priv->read_reg(priv, REG_SR) == REG_SR_BASICCAN_INITIAL) &&
+	    (priv->read_reg(priv, SJA1000_REG_SR) == REG_SR_BASICCAN_INITIAL) &&
 	    (priv->read_reg(priv, REG_IR) == REG_IR_BASICCAN_INITIAL))
 		flag = 1;
 
@@ -360,7 +360,7 @@ static inline int plx_pci_check_sja1000(const struct sja1000_priv *priv)
 	 * See states on p. 23 of the Datasheet.
 	 */
 	if (priv->read_reg(priv, REG_MOD) == REG_MOD_PELICAN_INITIAL &&
-	    priv->read_reg(priv, REG_SR) == REG_SR_PELICAN_INITIAL &&
+	    priv->read_reg(priv, SJA1000_REG_SR) == REG_SR_PELICAN_INITIAL &&
 	    priv->read_reg(priv, REG_IR) == REG_IR_PELICAN_INITIAL)
 		return flag;
 
diff --git a/drivers/net/can/sja1000/sja1000.c b/drivers/net/can/sja1000/sja1000.c
index daf4013..e4df307 100644
--- a/drivers/net/can/sja1000/sja1000.c
+++ b/drivers/net/can/sja1000/sja1000.c
@@ -92,7 +92,7 @@ static void sja1000_write_cmdreg(struct sja1000_priv *priv, u8 val)
 	 */
 	spin_lock_irqsave(&priv->cmdreg_lock, flags);
 	priv->write_reg(priv, REG_CMR, val);
-	priv->read_reg(priv, REG_SR);
+	priv->read_reg(priv, SJA1000_REG_SR);
 	spin_unlock_irqrestore(&priv->cmdreg_lock, flags);
 }
 
@@ -502,7 +502,7 @@ irqreturn_t sja1000_interrupt(int irq, void *dev_id)
 
 	while ((isrc = priv->read_reg(priv, REG_IR)) && (n < SJA1000_MAX_IRQ)) {
 		n++;
-		status = priv->read_reg(priv, REG_SR);
+		status = priv->read_reg(priv, SJA1000_REG_SR);
 		/* check for absent controller due to hw unplug */
 		if (status == 0xFF && sja1000_is_absent(priv))
 			return IRQ_NONE;
@@ -530,7 +530,7 @@ irqreturn_t sja1000_interrupt(int irq, void *dev_id)
 			/* receive interrupt */
 			while (status & SR_RBS) {
 				sja1000_rx(dev);
-				status = priv->read_reg(priv, REG_SR);
+				status = priv->read_reg(priv, SJA1000_REG_SR);
 				/* check for absent controller */
 				if (status == 0xFF && sja1000_is_absent(priv))
 					return IRQ_NONE;
diff --git a/drivers/net/can/sja1000/sja1000.h b/drivers/net/can/sja1000/sja1000.h
index afa9984..aa48e05 100644
--- a/drivers/net/can/sja1000/sja1000.h
+++ b/drivers/net/can/sja1000/sja1000.h
@@ -56,7 +56,7 @@
 /* SJA1000 registers - manual section 6.4 (Pelican Mode) */
 #define REG_MOD		0x00
 #define REG_CMR		0x01
-#define REG_SR		0x02
+#define SJA1000_REG_SR		0x02
 #define REG_IR		0x03
 #define REG_IER		0x04
 #define REG_ALC		0x0B
diff --git a/drivers/net/can/softing/softing_cs.c b/drivers/net/can/softing/softing_cs.c
index c2c0a5b..498605f 100644
--- a/drivers/net/can/softing/softing_cs.c
+++ b/drivers/net/can/softing/softing_cs.c
@@ -27,7 +27,7 @@
 #include "softing_platform.h"
 
 static int softingcs_index;
-static spinlock_t softingcs_index_lock;
+static DEFINE_SPINLOCK(softingcs_index_lock);
 
 static int softingcs_reset(struct platform_device *pdev, int v);
 static int softingcs_enable_irq(struct platform_device *pdev, int v);
@@ -340,19 +340,7 @@ static struct pcmcia_driver softingcs_driver = {
 	.remove		= softingcs_remove,
 };
 
-static int __init softingcs_start(void)
-{
-	spin_lock_init(&softingcs_index_lock);
-	return pcmcia_register_driver(&softingcs_driver);
-}
-
-static void __exit softingcs_stop(void)
-{
-	pcmcia_unregister_driver(&softingcs_driver);
-}
-
-module_init(softingcs_start);
-module_exit(softingcs_stop);
+module_pcmcia_driver(softingcs_driver);
 
 MODULE_DESCRIPTION("softing CANcard driver"
 		", links PCMCIA card to softing driver");
diff --git a/drivers/net/ethernet/3com/3c574_cs.c b/drivers/net/ethernet/3com/3c574_cs.c
index ffd8de2..6fc994f 100644
--- a/drivers/net/ethernet/3com/3c574_cs.c
+++ b/drivers/net/ethernet/3com/3c574_cs.c
@@ -1165,16 +1165,4 @@ static struct pcmcia_driver tc574_driver = {
 	.suspend	= tc574_suspend,
 	.resume		= tc574_resume,
 };
-
-static int __init init_tc574(void)
-{
-	return pcmcia_register_driver(&tc574_driver);
-}
-
-static void __exit exit_tc574(void)
-{
-	pcmcia_unregister_driver(&tc574_driver);
-}
-
-module_init(init_tc574);
-module_exit(exit_tc574);
+module_pcmcia_driver(tc574_driver);
diff --git a/drivers/net/ethernet/3com/3c589_cs.c b/drivers/net/ethernet/3com/3c589_cs.c
index a556c01..078480a 100644
--- a/drivers/net/ethernet/3com/3c589_cs.c
+++ b/drivers/net/ethernet/3com/3c589_cs.c
@@ -928,16 +928,4 @@ static struct pcmcia_driver tc589_driver = {
 	.suspend	= tc589_suspend,
 	.resume		= tc589_resume,
 };
-
-static int __init init_tc589(void)
-{
-	return pcmcia_register_driver(&tc589_driver);
-}
-
-static void __exit exit_tc589(void)
-{
-	pcmcia_unregister_driver(&tc589_driver);
-}
-
-module_init(init_tc589);
-module_exit(exit_tc589);
+module_pcmcia_driver(tc589_driver);
diff --git a/drivers/net/ethernet/8390/axnet_cs.c b/drivers/net/ethernet/8390/axnet_cs.c
index e1b3941..d801c141 100644
--- a/drivers/net/ethernet/8390/axnet_cs.c
+++ b/drivers/net/ethernet/8390/axnet_cs.c
@@ -728,19 +728,7 @@ static struct pcmcia_driver axnet_cs_driver = {
 	.suspend	= axnet_suspend,
 	.resume		= axnet_resume,
 };
-
-static int __init init_axnet_cs(void)
-{
-	return pcmcia_register_driver(&axnet_cs_driver);
-}
-
-static void __exit exit_axnet_cs(void)
-{
-	pcmcia_unregister_driver(&axnet_cs_driver);
-}
-
-module_init(init_axnet_cs);
-module_exit(exit_axnet_cs);
+module_pcmcia_driver(axnet_cs_driver);
 
 /*====================================================================*/
 
diff --git a/drivers/net/ethernet/8390/pcnet_cs.c b/drivers/net/ethernet/8390/pcnet_cs.c
index de1af0b..46c5aad 100644
--- a/drivers/net/ethernet/8390/pcnet_cs.c
+++ b/drivers/net/ethernet/8390/pcnet_cs.c
@@ -1694,16 +1694,4 @@ static struct pcmcia_driver pcnet_driver = {
 	.suspend	= pcnet_suspend,
 	.resume		= pcnet_resume,
 };
-
-static int __init init_pcnet_cs(void)
-{
-    return pcmcia_register_driver(&pcnet_driver);
-}
-
-static void __exit exit_pcnet_cs(void)
-{
-    pcmcia_unregister_driver(&pcnet_driver);
-}
-
-module_init(init_pcnet_cs);
-module_exit(exit_pcnet_cs);
+module_pcmcia_driver(pcnet_driver);
diff --git a/drivers/net/ethernet/adi/bfin_mac.c b/drivers/net/ethernet/adi/bfin_mac.c
index a175d0b..ee70577 100644
--- a/drivers/net/ethernet/adi/bfin_mac.c
+++ b/drivers/net/ethernet/adi/bfin_mac.c
@@ -188,10 +188,9 @@ static int desc_list_init(struct net_device *dev)
 
 		/* allocate a new skb for next time receive */
 		new_skb = netdev_alloc_skb(dev, PKT_BUF_SZ + NET_IP_ALIGN);
-		if (!new_skb) {
-			pr_notice("init: low on mem - packet dropped\n");
+		if (!new_skb)
 			goto init_error;
-		}
+
 		skb_reserve(new_skb, NET_IP_ALIGN);
 		/* Invidate the data cache of skb->data range when it is write back
 		 * cache. It will prevent overwritting the new data from DMA
@@ -1236,7 +1235,6 @@ static void bfin_mac_rx(struct net_device *dev)
 
 	new_skb = netdev_alloc_skb(dev, PKT_BUF_SZ + NET_IP_ALIGN);
 	if (!new_skb) {
-		netdev_notice(dev, "rx: low on mem - packet dropped\n");
 		dev->stats.rx_dropped++;
 		goto out;
 	}
diff --git a/drivers/net/ethernet/aeroflex/greth.c b/drivers/net/ethernet/aeroflex/greth.c
index 0be2195..2692954 100644
--- a/drivers/net/ethernet/aeroflex/greth.c
+++ b/drivers/net/ethernet/aeroflex/greth.c
@@ -1464,35 +1464,23 @@ static int greth_of_probe(struct platform_device *ofdev)
 	}
 
 	/* Allocate TX descriptor ring in coherent memory */
-	greth->tx_bd_base = (struct greth_bd *) dma_alloc_coherent(greth->dev,
-								   1024,
-								   &greth->tx_bd_base_phys,
-								   GFP_KERNEL);
-
+	greth->tx_bd_base = dma_alloc_coherent(greth->dev, 1024,
+					       &greth->tx_bd_base_phys,
+					       GFP_KERNEL | __GFP_ZERO);
 	if (!greth->tx_bd_base) {
-		if (netif_msg_probe(greth))
-			dev_err(&dev->dev, "could not allocate descriptor memory.\n");
 		err = -ENOMEM;
 		goto error3;
 	}
 
-	memset(greth->tx_bd_base, 0, 1024);
-
 	/* Allocate RX descriptor ring in coherent memory */
-	greth->rx_bd_base = (struct greth_bd *) dma_alloc_coherent(greth->dev,
-								   1024,
-								   &greth->rx_bd_base_phys,
-								   GFP_KERNEL);
-
+	greth->rx_bd_base = dma_alloc_coherent(greth->dev, 1024,
+					       &greth->rx_bd_base_phys,
+					       GFP_KERNEL | __GFP_ZERO);
 	if (!greth->rx_bd_base) {
-		if (netif_msg_probe(greth))
-			dev_err(greth->dev, "could not allocate descriptor memory.\n");
 		err = -ENOMEM;
 		goto error4;
 	}
 
-	memset(greth->rx_bd_base, 0, 1024);
-
 	/* Get MAC address from: module param, OF property or ID prom */
 	for (i = 0; i < 6; i++) {
 		if (macaddr[i] != 0)
diff --git a/drivers/net/ethernet/amd/7990.c b/drivers/net/ethernet/amd/7990.c
index 6e722dc..65926a9 100644
--- a/drivers/net/ethernet/amd/7990.c
+++ b/drivers/net/ethernet/amd/7990.c
@@ -318,8 +318,6 @@ static int lance_rx (struct net_device *dev)
 			struct sk_buff *skb = netdev_alloc_skb(dev, len + 2);
 
                         if (!skb) {
-                                printk ("%s: Memory squeeze, deferring packet.\n",
-                                        dev->name);
                                 dev->stats.rx_dropped++;
                                 rd->mblength = 0;
                                 rd->rmd1_bits = LE_R1_OWN;
diff --git a/drivers/net/ethernet/amd/a2065.c b/drivers/net/ethernet/amd/a2065.c
index 3789aff..0866e76 100644
--- a/drivers/net/ethernet/amd/a2065.c
+++ b/drivers/net/ethernet/amd/a2065.c
@@ -293,7 +293,6 @@ static int lance_rx(struct net_device *dev)
 			struct sk_buff *skb = netdev_alloc_skb(dev, len + 2);
 
 			if (!skb) {
-				netdev_warn(dev, "Memory squeeze, deferring packet\n");
 				dev->stats.rx_dropped++;
 				rd->mblength = 0;
 				rd->rmd1_bits = LE_R1_OWN;
diff --git a/drivers/net/ethernet/amd/am79c961a.c b/drivers/net/ethernet/amd/am79c961a.c
index 60e2b70..9793767 100644
--- a/drivers/net/ethernet/amd/am79c961a.c
+++ b/drivers/net/ethernet/amd/am79c961a.c
@@ -528,7 +528,6 @@ am79c961_rx(struct net_device *dev, struct dev_priv *priv)
 			dev->stats.rx_packets++;
 		} else {
 			am_writeword (dev, hdraddr + 2, RMD_OWN);
-			printk (KERN_WARNING "%s: memory squeeze, dropping packet.\n", dev->name);
 			dev->stats.rx_dropped++;
 			break;
 		}
diff --git a/drivers/net/ethernet/amd/ariadne.c b/drivers/net/ethernet/amd/ariadne.c
index 98f4522..c178eb4 100644
--- a/drivers/net/ethernet/amd/ariadne.c
+++ b/drivers/net/ethernet/amd/ariadne.c
@@ -193,7 +193,6 @@ static int ariadne_rx(struct net_device *dev)
 
 			skb = netdev_alloc_skb(dev, 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;
diff --git a/drivers/net/ethernet/amd/atarilance.c b/drivers/net/ethernet/amd/atarilance.c
index 84219df..e8d0ef5 100644
--- a/drivers/net/ethernet/amd/atarilance.c
+++ b/drivers/net/ethernet/amd/atarilance.c
@@ -996,8 +996,6 @@ static int lance_rx( struct net_device *dev )
 			else {
 				skb = netdev_alloc_skb(dev, pkt_len + 2);
 				if (skb == NULL) {
-					DPRINTK( 1, ( "%s: Memory squeeze, deferring packet.\n",
-								  dev->name ));
 					for( i = 0; i < RX_RING_SIZE; i++ )
 						if (MEM->rx_head[(entry+i) & RX_RING_MOD_MASK].flag &
 							RMD1_OWN_CHIP)
@@ -1149,9 +1147,7 @@ static struct net_device *atarilance_dev;
 static int __init atarilance_module_init(void)
 {
 	atarilance_dev = atarilance_probe(-1);
-	if (IS_ERR(atarilance_dev))
-		return PTR_ERR(atarilance_dev);
-	return 0;
+	return PTR_RET(atarilance_dev);
 }
 
 static void __exit atarilance_module_exit(void)
diff --git a/drivers/net/ethernet/amd/au1000_eth.c b/drivers/net/ethernet/amd/au1000_eth.c
index de774d4..688aede 100644
--- a/drivers/net/ethernet/amd/au1000_eth.c
+++ b/drivers/net/ethernet/amd/au1000_eth.c
@@ -727,7 +727,6 @@ static int au1000_rx(struct net_device *dev)
 			frmlen -= 4; /* Remove FCS */
 			skb = netdev_alloc_skb(dev, frmlen + 2);
 			if (skb == NULL) {
-				netdev_err(dev, "Memory squeeze, dropping packet.\n");
 				dev->stats.rx_dropped++;
 				continue;
 			}
diff --git a/drivers/net/ethernet/amd/declance.c b/drivers/net/ethernet/amd/declance.c
index baca0bd..3d86ffe 100644
--- a/drivers/net/ethernet/amd/declance.c
+++ b/drivers/net/ethernet/amd/declance.c
@@ -607,8 +607,6 @@ static int lance_rx(struct net_device *dev)
 			skb = netdev_alloc_skb(dev, len + 2);
 
 			if (skb == 0) {
-				printk("%s: Memory squeeze, deferring packet.\n",
-				       dev->name);
 				dev->stats.rx_dropped++;
 				*rds_ptr(rd, mblength, lp->type) = 0;
 				*rds_ptr(rd, rmd1, lp->type) =
diff --git a/drivers/net/ethernet/amd/mvme147.c b/drivers/net/ethernet/amd/mvme147.c
index 9af3c30..a51497c 100644
--- a/drivers/net/ethernet/amd/mvme147.c
+++ b/drivers/net/ethernet/amd/mvme147.c
@@ -188,9 +188,7 @@ static struct net_device *dev_mvme147_lance;
 int __init init_module(void)
 {
 	dev_mvme147_lance = mvme147lance_probe(-1);
-	if (IS_ERR(dev_mvme147_lance))
-		return PTR_ERR(dev_mvme147_lance);
-	return 0;
+	return PTR_RET(dev_mvme147_lance);
 }
 
 void __exit cleanup_module(void)
diff --git a/drivers/net/ethernet/amd/ni65.c b/drivers/net/ethernet/amd/ni65.c
index 013b651..26fc0ce 100644
--- a/drivers/net/ethernet/amd/ni65.c
+++ b/drivers/net/ethernet/amd/ni65.c
@@ -1238,7 +1238,7 @@ MODULE_PARM_DESC(dma, "ni6510 ISA DMA channel (ignored for some cards)");
 int __init init_module(void)
 {
  	dev_ni65 = ni65_probe(-1);
-	return IS_ERR(dev_ni65) ? PTR_ERR(dev_ni65) : 0;
+	return PTR_RET(dev_ni65);
 }
 
 void __exit cleanup_module(void)
diff --git a/drivers/net/ethernet/amd/nmclan_cs.c b/drivers/net/ethernet/amd/nmclan_cs.c
index 9f59bf6..d4ed891 100644
--- a/drivers/net/ethernet/amd/nmclan_cs.c
+++ b/drivers/net/ethernet/amd/nmclan_cs.c
@@ -1508,16 +1508,4 @@ static struct pcmcia_driver nmclan_cs_driver = {
 	.suspend	= nmclan_suspend,
 	.resume		= nmclan_resume,
 };
-
-static int __init init_nmclan_cs(void)
-{
-	return pcmcia_register_driver(&nmclan_cs_driver);
-}
-
-static void __exit exit_nmclan_cs(void)
-{
-	pcmcia_unregister_driver(&nmclan_cs_driver);
-}
-
-module_init(init_nmclan_cs);
-module_exit(exit_nmclan_cs);
+module_pcmcia_driver(nmclan_cs_driver);
diff --git a/drivers/net/ethernet/amd/pcnet32.c b/drivers/net/ethernet/amd/pcnet32.c
index 797f847..ed21307 100644
--- a/drivers/net/ethernet/amd/pcnet32.c
+++ b/drivers/net/ethernet/amd/pcnet32.c
@@ -1166,7 +1166,6 @@ static void pcnet32_rx_entry(struct net_device *dev,
 		skb = netdev_alloc_skb(dev, pkt_len + NET_IP_ALIGN);
 
 	if (skb == NULL) {
-		netif_err(lp, drv, dev, "Memory squeeze, dropping packet\n");
 		dev->stats.rx_dropped++;
 		return;
 	}
diff --git a/drivers/net/ethernet/amd/sun3lance.c b/drivers/net/ethernet/amd/sun3lance.c
index 74b3891..4375abe 100644
--- a/drivers/net/ethernet/amd/sun3lance.c
+++ b/drivers/net/ethernet/amd/sun3lance.c
@@ -812,9 +812,6 @@ static int lance_rx( struct net_device *dev )
 			else {
 				skb = netdev_alloc_skb(dev, pkt_len + 2);
 				if (skb == NULL) {
-					DPRINTK( 1, ( "%s: Memory squeeze, deferring packet.\n",
-						      dev->name ));
-
 					dev->stats.rx_dropped++;
 					head->msg_length = 0;
 					head->flag |= RMD1_OWN_CHIP;
@@ -943,9 +940,7 @@ static struct net_device *sun3lance_dev;
 int __init init_module(void)
 {
 	sun3lance_dev = sun3lance_probe(-1);
-	if (IS_ERR(sun3lance_dev))
-		return PTR_ERR(sun3lance_dev);
-	return 0;
+	return PTR_RET(sun3lance_dev);
 }
 
 void __exit cleanup_module(void)
diff --git a/drivers/net/ethernet/amd/sunlance.c b/drivers/net/ethernet/amd/sunlance.c
index 6a40290..f47b780 100644
--- a/drivers/net/ethernet/amd/sunlance.c
+++ b/drivers/net/ethernet/amd/sunlance.c
@@ -536,8 +536,6 @@ static void lance_rx_dvma(struct net_device *dev)
 			skb = netdev_alloc_skb(dev, len + 2);
 
 			if (skb == NULL) {
-				printk(KERN_INFO "%s: Memory squeeze, deferring packet.\n",
-				       dev->name);
 				dev->stats.rx_dropped++;
 				rd->mblength = 0;
 				rd->rmd1_bits = LE_R1_OWN;
@@ -708,8 +706,6 @@ static void lance_rx_pio(struct net_device *dev)
 			skb = netdev_alloc_skb(dev, len + 2);
 
 			if (skb == NULL) {
-				printk(KERN_INFO "%s: Memory squeeze, deferring packet.\n",
-				       dev->name);
 				dev->stats.rx_dropped++;
 				sbus_writew(0, &rd->mblength);
 				sbus_writeb(LE_R1_OWN, &rd->rmd1_bits);
@@ -1377,10 +1373,9 @@ static int sparc_lance_probe_one(struct platform_device *op,
 			dma_alloc_coherent(&op->dev,
 					   sizeof(struct lance_init_block),
 					   &lp->init_block_dvma, GFP_ATOMIC);
-		if (!lp->init_block_mem) {
-			printk(KERN_ERR "SunLance: Cannot allocate consistent DMA memory.\n");
+		if (!lp->init_block_mem)
 			goto fail;
-		}
+
 		lp->pio_buffer = 0;
 		lp->init_ring = lance_init_ring_dvma;
 		lp->rx = lance_rx_dvma;
diff --git a/drivers/net/ethernet/apple/macmace.c b/drivers/net/ethernet/apple/macmace.c
index a206779..4ce8ceb 100644
--- a/drivers/net/ethernet/apple/macmace.c
+++ b/drivers/net/ethernet/apple/macmace.c
@@ -386,20 +386,16 @@ static int mace_open(struct net_device *dev)
 	/* Allocate the DMA ring buffers */
 
 	mp->tx_ring = dma_alloc_coherent(mp->device,
-			N_TX_RING * MACE_BUFF_SIZE,
-			&mp->tx_ring_phys, GFP_KERNEL);
-	if (mp->tx_ring == NULL) {
-		printk(KERN_ERR "%s: unable to allocate DMA tx buffers\n", dev->name);
+					 N_TX_RING * MACE_BUFF_SIZE,
+					 &mp->tx_ring_phys, GFP_KERNEL);
+	if (mp->tx_ring == NULL)
 		goto out1;
-	}
 
 	mp->rx_ring = dma_alloc_coherent(mp->device,
-			N_RX_RING * MACE_BUFF_SIZE,
-			&mp->rx_ring_phys, GFP_KERNEL);
-	if (mp->rx_ring == NULL) {
-		printk(KERN_ERR "%s: unable to allocate DMA rx buffers\n", dev->name);
+					 N_RX_RING * MACE_BUFF_SIZE,
+					 &mp->rx_ring_phys, GFP_KERNEL);
+	if (mp->rx_ring == NULL)
 		goto out2;
-	}
 
 	mace_dma_off(dev);
 
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c
index 21e261f..3ef7092 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c
@@ -810,7 +810,7 @@ int atl1c_power_saving(struct atl1c_hw *hw, u32 wufc)
 	if (wufc & AT_WUFC_LNKC) {
 		wol_ctrl |= WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN;
 		if (atl1c_write_phy_reg(hw, MII_IER, IER_LINK_UP) != 0) {
-			dev_dbg(&pdev->dev, "%s: write phy MII_IER faild.\n",
+			dev_dbg(&pdev->dev, "%s: write phy MII_IER failed.\n",
 				atl1c_driver_name);
 		}
 	}
diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e.h b/drivers/net/ethernet/atheros/atl1e/atl1e.h
index 829b5ad..edfdf6b 100644
--- a/drivers/net/ethernet/atheros/atl1e/atl1e.h
+++ b/drivers/net/ethernet/atheros/atl1e/atl1e.h
@@ -438,7 +438,6 @@ struct atl1e_adapter {
 	struct atl1e_hw        hw;
 	struct atl1e_hw_stats  hw_stats;
 
-	bool have_msi;
 	u32 wol;
 	u16 link_speed;
 	u16 link_duplex;
diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
index 92f4734..7e0a822 100644
--- a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
+++ b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
@@ -1420,11 +1420,9 @@ static void atl1e_clean_rx_irq(struct atl1e_adapter *adapter, u8 que,
 			packet_size = ((prrs->word1 >> RRS_PKT_SIZE_SHIFT) &
 					RRS_PKT_SIZE_MASK) - 4; /* CRC */
 			skb = netdev_alloc_skb_ip_align(netdev, packet_size);
-			if (skb == NULL) {
-				netdev_warn(netdev,
-					    "Memory squeeze, deferring packet\n");
+			if (skb == NULL)
 				goto skip_pkt;
-			}
+
 			memcpy(skb->data, (u8 *)(prrs + 1), packet_size);
 			skb_put(skb, packet_size);
 			skb->protocol = eth_type_trans(skb, netdev);
@@ -1849,34 +1847,19 @@ static void atl1e_free_irq(struct atl1e_adapter *adapter)
 	struct net_device *netdev = adapter->netdev;
 
 	free_irq(adapter->pdev->irq, netdev);
-
-	if (adapter->have_msi)
-		pci_disable_msi(adapter->pdev);
 }
 
 static int atl1e_request_irq(struct atl1e_adapter *adapter)
 {
 	struct pci_dev    *pdev   = adapter->pdev;
 	struct net_device *netdev = adapter->netdev;
-	int flags = 0;
 	int err = 0;
 
-	adapter->have_msi = true;
-	err = pci_enable_msi(pdev);
-	if (err) {
-		netdev_dbg(netdev,
-			   "Unable to allocate MSI interrupt Error: %d\n", err);
-		adapter->have_msi = false;
-	}
-
-	if (!adapter->have_msi)
-		flags |= IRQF_SHARED;
-	err = request_irq(pdev->irq, atl1e_intr, flags, netdev->name, netdev);
+	err = request_irq(pdev->irq, atl1e_intr, IRQF_SHARED, netdev->name,
+			  netdev);
 	if (err) {
 		netdev_dbg(adapter->netdev,
 			   "Unable to allocate interrupt Error: %d\n", err);
-		if (adapter->have_msi)
-			pci_disable_msi(pdev);
 		return err;
 	}
 	netdev_dbg(netdev, "atl1e_request_irq OK\n");
diff --git a/drivers/net/ethernet/atheros/atlx/atl1.c b/drivers/net/ethernet/atheros/atlx/atl1.c
index 5b0d993..9948fee 100644
--- a/drivers/net/ethernet/atheros/atlx/atl1.c
+++ b/drivers/net/ethernet/atheros/atlx/atl1.c
@@ -2774,7 +2774,7 @@ static int atl1_close(struct net_device *netdev)
 	return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int atl1_suspend(struct device *dev)
 {
 	struct pci_dev *pdev = to_pci_dev(dev);
diff --git a/drivers/net/ethernet/atheros/atlx/atl2.c b/drivers/net/ethernet/atheros/atlx/atl2.c
index 1278b47..a046b6f 100644
--- a/drivers/net/ethernet/atheros/atlx/atl2.c
+++ b/drivers/net/ethernet/atheros/atlx/atl2.c
@@ -437,9 +437,6 @@ static void atl2_intr_rx(struct atl2_adapter *adapter)
 			/* alloc new buffer */
 			skb = netdev_alloc_skb_ip_align(netdev, rx_size);
 			if (NULL == skb) {
-				printk(KERN_WARNING
-					"%s: Mem squeeze, deferring packet.\n",
-					netdev->name);
 				/*
 				 * Check that some rx space is free. If not,
 				 * free one and mark stats->rx_dropped++.
diff --git a/drivers/net/ethernet/broadcom/bcm63xx_enet.c b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
index 7d81e05..0b3e23e 100644
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
@@ -862,27 +862,25 @@ static int bcm_enet_open(struct net_device *dev)
 
 	/* allocate rx dma ring */
 	size = priv->rx_ring_size * sizeof(struct bcm_enet_desc);
-	p = dma_alloc_coherent(kdev, size, &priv->rx_desc_dma, GFP_KERNEL);
+	p = dma_alloc_coherent(kdev, size, &priv->rx_desc_dma,
+			       GFP_KERNEL | __GFP_ZERO);
 	if (!p) {
-		dev_err(kdev, "cannot allocate rx ring %u\n", size);
 		ret = -ENOMEM;
 		goto out_freeirq_tx;
 	}
 
-	memset(p, 0, size);
 	priv->rx_desc_alloc_size = size;
 	priv->rx_desc_cpu = p;
 
 	/* allocate tx dma ring */
 	size = priv->tx_ring_size * sizeof(struct bcm_enet_desc);
-	p = dma_alloc_coherent(kdev, size, &priv->tx_desc_dma, GFP_KERNEL);
+	p = dma_alloc_coherent(kdev, size, &priv->tx_desc_dma,
+			       GFP_KERNEL | __GFP_ZERO);
 	if (!p) {
-		dev_err(kdev, "cannot allocate tx ring\n");
 		ret = -ENOMEM;
 		goto out_free_rx_ring;
 	}
 
-	memset(p, 0, size);
 	priv->tx_desc_alloc_size = size;
 	priv->tx_desc_cpu = p;
 
@@ -1619,7 +1617,6 @@ static int bcm_enet_probe(struct platform_device *pdev)
 	struct resource *res_mem, *res_irq, *res_irq_rx, *res_irq_tx;
 	struct mii_bus *bus;
 	const char *clk_name;
-	unsigned int iomem_size;
 	int i, ret;
 
 	/* stop if shared driver failed, assume driver->probe will be
@@ -1644,17 +1641,12 @@ static int bcm_enet_probe(struct platform_device *pdev)
 	if (ret)
 		goto out;
 
-	iomem_size = resource_size(res_mem);
-	if (!request_mem_region(res_mem->start, iomem_size, "bcm63xx_enet")) {
-		ret = -EBUSY;
-		goto out;
-	}
-
-	priv->base = ioremap(res_mem->start, iomem_size);
+	priv->base = devm_request_and_ioremap(&pdev->dev, res_mem);
 	if (priv->base == NULL) {
 		ret = -ENOMEM;
-		goto out_release_mem;
+		goto out;
 	}
+
 	dev->irq = priv->irq = res_irq->start;
 	priv->irq_rx = res_irq_rx->start;
 	priv->irq_tx = res_irq_tx->start;
@@ -1674,9 +1666,9 @@ static int bcm_enet_probe(struct platform_device *pdev)
 	priv->mac_clk = clk_get(&pdev->dev, clk_name);
 	if (IS_ERR(priv->mac_clk)) {
 		ret = PTR_ERR(priv->mac_clk);
-		goto out_unmap;
+		goto out;
 	}
-	clk_enable(priv->mac_clk);
+	clk_prepare_enable(priv->mac_clk);
 
 	/* initialize default and fetch platform data */
 	priv->rx_ring_size = BCMENET_DEF_RX_DESC;
@@ -1705,7 +1697,7 @@ static int bcm_enet_probe(struct platform_device *pdev)
 			priv->phy_clk = NULL;
 			goto out_put_clk_mac;
 		}
-		clk_enable(priv->phy_clk);
+		clk_prepare_enable(priv->phy_clk);
 	}
 
 	/* do minimal hardware init to be able to probe mii bus */
@@ -1733,7 +1725,8 @@ static int bcm_enet_probe(struct platform_device *pdev)
 		 * if a slave is not present on hw */
 		bus->phy_mask = ~(1 << priv->phy_id);
 
-		bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
+		bus->irq = devm_kzalloc(&pdev->dev, sizeof(int) * PHY_MAX_ADDR,
+					GFP_KERNEL);
 		if (!bus->irq) {
 			ret = -ENOMEM;
 			goto out_free_mdio;
@@ -1794,10 +1787,8 @@ static int bcm_enet_probe(struct platform_device *pdev)
 	return 0;
 
 out_unregister_mdio:
-	if (priv->mii_bus) {
+	if (priv->mii_bus)
 		mdiobus_unregister(priv->mii_bus);
-		kfree(priv->mii_bus->irq);
-	}
 
 out_free_mdio:
 	if (priv->mii_bus)
@@ -1807,19 +1798,13 @@ out_uninit_hw:
 	/* turn off mdc clock */
 	enet_writel(priv, 0, ENET_MIISC_REG);
 	if (priv->phy_clk) {
-		clk_disable(priv->phy_clk);
+		clk_disable_unprepare(priv->phy_clk);
 		clk_put(priv->phy_clk);
 	}
 
 out_put_clk_mac:
-	clk_disable(priv->mac_clk);
+	clk_disable_unprepare(priv->mac_clk);
 	clk_put(priv->mac_clk);
-
-out_unmap:
-	iounmap(priv->base);
-
-out_release_mem:
-	release_mem_region(res_mem->start, iomem_size);
 out:
 	free_netdev(dev);
 	return ret;
@@ -1833,7 +1818,6 @@ static int bcm_enet_remove(struct platform_device *pdev)
 {
 	struct bcm_enet_priv *priv;
 	struct net_device *dev;
-	struct resource *res;
 
 	/* stop netdevice */
 	dev = platform_get_drvdata(pdev);
@@ -1845,7 +1829,6 @@ static int bcm_enet_remove(struct platform_device *pdev)
 
 	if (priv->has_phy) {
 		mdiobus_unregister(priv->mii_bus);
-		kfree(priv->mii_bus->irq);
 		mdiobus_free(priv->mii_bus);
 	} else {
 		struct bcm63xx_enet_platform_data *pd;
@@ -1856,17 +1839,12 @@ static int bcm_enet_remove(struct platform_device *pdev)
 				       bcm_enet_mdio_write_mii);
 	}
 
-	/* release device resources */
-	iounmap(priv->base);
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	release_mem_region(res->start, resource_size(res));
-
 	/* disable hw block clocks */
 	if (priv->phy_clk) {
-		clk_disable(priv->phy_clk);
+		clk_disable_unprepare(priv->phy_clk);
 		clk_put(priv->phy_clk);
 	}
-	clk_disable(priv->mac_clk);
+	clk_disable_unprepare(priv->mac_clk);
 	clk_put(priv->mac_clk);
 
 	platform_set_drvdata(pdev, NULL);
@@ -1889,31 +1867,20 @@ struct platform_driver bcm63xx_enet_driver = {
 static int bcm_enet_shared_probe(struct platform_device *pdev)
 {
 	struct resource *res;
-	unsigned int iomem_size;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res)
 		return -ENODEV;
 
-	iomem_size = resource_size(res);
-	if (!request_mem_region(res->start, iomem_size, "bcm63xx_enet_dma"))
-		return -EBUSY;
-
-	bcm_enet_shared_base = ioremap(res->start, iomem_size);
-	if (!bcm_enet_shared_base) {
-		release_mem_region(res->start, iomem_size);
+	bcm_enet_shared_base = devm_request_and_ioremap(&pdev->dev, res);
+	if (!bcm_enet_shared_base)
 		return -ENOMEM;
-	}
+
 	return 0;
 }
 
 static int bcm_enet_shared_remove(struct platform_device *pdev)
 {
-	struct resource *res;
-
-	iounmap(bcm_enet_shared_base);
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	release_mem_region(res->start, resource_size(res));
 	return 0;
 }
 
diff --git a/drivers/net/ethernet/broadcom/bgmac.c b/drivers/net/ethernet/broadcom/bgmac.c
index da5f439..eec0af4 100644
--- a/drivers/net/ethernet/broadcom/bgmac.c
+++ b/drivers/net/ethernet/broadcom/bgmac.c
@@ -13,6 +13,7 @@
 #include <linux/delay.h>
 #include <linux/etherdevice.h>
 #include <linux/mii.h>
+#include <linux/phy.h>
 #include <linux/interrupt.h>
 #include <linux/dma-mapping.h>
 #include <bcm47xx_nvram.h>
@@ -244,10 +245,8 @@ static int bgmac_dma_rx_skb_for_slot(struct bgmac *bgmac,
 
 	/* Alloc skb */
 	slot->skb = netdev_alloc_skb(bgmac->net_dev, BGMAC_RX_BUF_SIZE);
-	if (!slot->skb) {
-		bgmac_err(bgmac, "Allocation of skb failed!\n");
+	if (!slot->skb)
 		return -ENOMEM;
-	}
 
 	/* Poison - if everything goes fine, hardware will overwrite it */
 	rx = (struct bgmac_rx_header *)slot->skb->data;
@@ -1313,6 +1312,73 @@ static const struct ethtool_ops bgmac_ethtool_ops = {
 };
 
 /**************************************************
+ * MII
+ **************************************************/
+
+static int bgmac_mii_read(struct mii_bus *bus, int mii_id, int regnum)
+{
+	return bgmac_phy_read(bus->priv, mii_id, regnum);
+}
+
+static int bgmac_mii_write(struct mii_bus *bus, int mii_id, int regnum,
+			   u16 value)
+{
+	return bgmac_phy_write(bus->priv, mii_id, regnum, value);
+}
+
+static int bgmac_mii_register(struct bgmac *bgmac)
+{
+	struct mii_bus *mii_bus;
+	int i, err = 0;
+
+	mii_bus = mdiobus_alloc();
+	if (!mii_bus)
+		return -ENOMEM;
+
+	mii_bus->name = "bgmac mii bus";
+	sprintf(mii_bus->id, "%s-%d-%d", "bgmac", bgmac->core->bus->num,
+		bgmac->core->core_unit);
+	mii_bus->priv = bgmac;
+	mii_bus->read = bgmac_mii_read;
+	mii_bus->write = bgmac_mii_write;
+	mii_bus->parent = &bgmac->core->dev;
+	mii_bus->phy_mask = ~(1 << bgmac->phyaddr);
+
+	mii_bus->irq = kmalloc_array(PHY_MAX_ADDR, sizeof(int), GFP_KERNEL);
+	if (!mii_bus->irq) {
+		err = -ENOMEM;
+		goto err_free_bus;
+	}
+	for (i = 0; i < PHY_MAX_ADDR; i++)
+		mii_bus->irq[i] = PHY_POLL;
+
+	err = mdiobus_register(mii_bus);
+	if (err) {
+		bgmac_err(bgmac, "Registration of mii bus failed\n");
+		goto err_free_irq;
+	}
+
+	bgmac->mii_bus = mii_bus;
+
+	return err;
+
+err_free_irq:
+	kfree(mii_bus->irq);
+err_free_bus:
+	mdiobus_free(mii_bus);
+	return err;
+}
+
+static void bgmac_mii_unregister(struct bgmac *bgmac)
+{
+	struct mii_bus *mii_bus = bgmac->mii_bus;
+
+	mdiobus_unregister(mii_bus);
+	kfree(mii_bus->irq);
+	mdiobus_free(mii_bus);
+}
+
+/**************************************************
  * BCMA bus ops
  **************************************************/
 
@@ -1404,11 +1470,18 @@ static int bgmac_probe(struct bcma_device *core)
 	if (core->bus->sprom.boardflags_lo & BGMAC_BFL_ENETADM)
 		bgmac_warn(bgmac, "Support for ADMtek ethernet switch not implemented\n");
 
+	err = bgmac_mii_register(bgmac);
+	if (err) {
+		bgmac_err(bgmac, "Cannot register MDIO\n");
+		err = -ENOTSUPP;
+		goto err_dma_free;
+	}
+
 	err = register_netdev(bgmac->net_dev);
 	if (err) {
 		bgmac_err(bgmac, "Cannot register net device\n");
 		err = -ENOTSUPP;
-		goto err_dma_free;
+		goto err_mii_unregister;
 	}
 
 	netif_carrier_off(net_dev);
@@ -1417,6 +1490,8 @@ static int bgmac_probe(struct bcma_device *core)
 
 	return 0;
 
+err_mii_unregister:
+	bgmac_mii_unregister(bgmac);
 err_dma_free:
 	bgmac_dma_free(bgmac);
 
@@ -1433,6 +1508,7 @@ static void bgmac_remove(struct bcma_device *core)
 
 	netif_napi_del(&bgmac->napi);
 	unregister_netdev(bgmac->net_dev);
+	bgmac_mii_unregister(bgmac);
 	bgmac_dma_free(bgmac);
 	bcma_set_drvdata(core, NULL);
 	free_netdev(bgmac->net_dev);
diff --git a/drivers/net/ethernet/broadcom/bgmac.h b/drivers/net/ethernet/broadcom/bgmac.h
index 4ede614..98d4b5f 100644
--- a/drivers/net/ethernet/broadcom/bgmac.h
+++ b/drivers/net/ethernet/broadcom/bgmac.h
@@ -399,6 +399,7 @@ struct bgmac {
 	struct bcma_device *cmn; /* Reference to CMN core for BCM4706 */
 	struct net_device *net_dev;
 	struct napi_struct napi;
+	struct mii_bus *mii_bus;
 
 	/* DMA */
 	struct bgmac_dma_ring tx_ring[BGMAC_MAX_TX_RINGS];
diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c
index 2f0ba8f..e709296 100644
--- a/drivers/net/ethernet/broadcom/bnx2.c
+++ b/drivers/net/ethernet/broadcom/bnx2.c
@@ -854,12 +854,11 @@ bnx2_alloc_mem(struct bnx2 *bp)
 				sizeof(struct statistics_block);
 
 	status_blk = dma_alloc_coherent(&bp->pdev->dev, bp->status_stats_size,
-					&bp->status_blk_mapping, GFP_KERNEL);
+					&bp->status_blk_mapping,
+					GFP_KERNEL | __GFP_ZERO);
 	if (status_blk == NULL)
 		goto alloc_mem_err;
 
-	memset(status_blk, 0, bp->status_stats_size);
-
 	bnapi = &bp->bnx2_napi[0];
 	bnapi->status_blk.msi = status_blk;
 	bnapi->hw_tx_cons_ptr =
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
index e4605a9..c630342 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
@@ -492,7 +492,6 @@ enum bnx2x_tpa_mode_t {
 struct bnx2x_fastpath {
 	struct bnx2x		*bp; /* parent */
 
-#define BNX2X_NAPI_WEIGHT       128
 	struct napi_struct	napi;
 	union host_hc_status_block	status_blk;
 	/* chip independed shortcuts into sb structure */
@@ -613,9 +612,10 @@ struct bnx2x_fastpath {
  * START_BD		- describes packed
  * START_BD(splitted)	- includes unpaged data segment for GSO
  * PARSING_BD		- for TSO and CSUM data
+ * PARSING_BD2		- for encapsulation data
  * Frag BDs		- decribes pages for frags
  */
-#define BDS_PER_TX_PKT		3
+#define BDS_PER_TX_PKT		4
 #define MAX_BDS_PER_TX_PKT	(MAX_SKB_FRAGS + BDS_PER_TX_PKT)
 /* max BDs per tx packet including next pages */
 #define MAX_DESC_PER_TX_PKT	(MAX_BDS_PER_TX_PKT + \
@@ -730,18 +730,24 @@ struct bnx2x_fastpath {
 #define SKB_CS(skb)		(*(u16 *)(skb_transport_header(skb) + \
 					  skb->csum_offset))
 
-#define pbd_tcp_flags(skb)	(ntohl(tcp_flag_word(tcp_hdr(skb)))>>16 & 0xff)
+#define pbd_tcp_flags(tcp_hdr)	(ntohl(tcp_flag_word(tcp_hdr))>>16 & 0xff)
 
-#define XMIT_PLAIN			0
-#define XMIT_CSUM_V4			0x1
-#define XMIT_CSUM_V6			0x2
-#define XMIT_CSUM_TCP			0x4
-#define XMIT_GSO_V4			0x8
-#define XMIT_GSO_V6			0x10
+#define XMIT_PLAIN		0
+#define XMIT_CSUM_V4		(1 << 0)
+#define XMIT_CSUM_V6		(1 << 1)
+#define XMIT_CSUM_TCP		(1 << 2)
+#define XMIT_GSO_V4		(1 << 3)
+#define XMIT_GSO_V6		(1 << 4)
+#define XMIT_CSUM_ENC_V4	(1 << 5)
+#define XMIT_CSUM_ENC_V6	(1 << 6)
+#define XMIT_GSO_ENC_V4		(1 << 7)
+#define XMIT_GSO_ENC_V6		(1 << 8)
 
-#define XMIT_CSUM			(XMIT_CSUM_V4 | XMIT_CSUM_V6)
-#define XMIT_GSO			(XMIT_GSO_V4 | XMIT_GSO_V6)
+#define XMIT_CSUM_ENC		(XMIT_CSUM_ENC_V4 | XMIT_CSUM_ENC_V6)
+#define XMIT_GSO_ENC		(XMIT_GSO_ENC_V4 | XMIT_GSO_ENC_V6)
 
+#define XMIT_CSUM		(XMIT_CSUM_V4 | XMIT_CSUM_V6 | XMIT_CSUM_ENC)
+#define XMIT_GSO		(XMIT_GSO_V4 | XMIT_GSO_V6 | XMIT_GSO_ENC)
 
 /* stuff added to make the code fit 80Col */
 #define CQE_TYPE(cqe_fp_flags)	 ((cqe_fp_flags) & ETH_FAST_PATH_RX_CQE_TYPE)
@@ -1215,14 +1221,16 @@ enum {
 	BNX2X_SP_RTNL_ENABLE_SRIOV,
 	BNX2X_SP_RTNL_VFPF_MCAST,
 	BNX2X_SP_RTNL_VFPF_STORM_RX_MODE,
+	BNX2X_SP_RTNL_HYPERVISOR_VLAN,
 };
 
 
 struct bnx2x_prev_path_list {
+	struct list_head list;
 	u8 bus;
 	u8 slot;
 	u8 path;
-	struct list_head list;
+	u8 aer;
 	u8 undi;
 };
 
@@ -1269,6 +1277,8 @@ struct bnx2x {
 #define BP_FW_MB_IDX(bp)		BP_FW_MB_IDX_VN(bp, BP_VN(bp))
 
 #ifdef CONFIG_BNX2X_SRIOV
+	/* protects vf2pf mailbox from simultaneous access */
+	struct mutex		vf2pf_mutex;
 	/* vf pf channel mailbox contains request and response buffers */
 	struct bnx2x_vf_mbx_msg	*vf2pf_mbox;
 	dma_addr_t		vf2pf_mbox_mapping;
@@ -1281,6 +1291,8 @@ struct bnx2x {
 	dma_addr_t		pf2vf_bulletin_mapping;
 
 	struct pf_vf_bulletin_content	old_bulletin;
+
+	u16 requested_nr_virtfn;
 #endif /* CONFIG_BNX2X_SRIOV */
 
 	struct net_device	*dev;
@@ -1944,12 +1956,9 @@ static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms,
 void bnx2x_igu_clear_sb_gen(struct bnx2x *bp, u8 func, u8 idu_sb_id,
 			    bool is_pf);
 
-#define BNX2X_ILT_ZALLOC(x, y, size) \
-	do { \
-		x = dma_alloc_coherent(&bp->pdev->dev, size, y, GFP_KERNEL); \
-		if (x) \
-			memset(x, 0, size); \
-	} while (0)
+#define BNX2X_ILT_ZALLOC(x, y, size)				\
+	x = dma_alloc_coherent(&bp->pdev->dev, size, y,		\
+			       GFP_KERNEL | __GFP_ZERO)
 
 #define BNX2X_ILT_FREE(x, y, size) \
 	do { \
@@ -2286,7 +2295,7 @@ static const u32 dmae_reg_go_c[] = {
 	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_set_ethtool_ops(struct bnx2x *bp, struct net_device *netdev);
 void bnx2x_notify_link_changed(struct bnx2x *bp);
 
 #define BNX2X_MF_SD_PROTOCOL(bp) \
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
index 4046f97..352e58e 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
@@ -451,7 +451,8 @@ static void bnx2x_tpa_start(struct bnx2x_fastpath *fp, u16 queue,
  * Compute number of aggregated segments, and gso_type.
  */
 static void bnx2x_set_gro_params(struct sk_buff *skb, u16 parsing_flags,
-				 u16 len_on_bd, unsigned int pkt_len)
+				 u16 len_on_bd, unsigned int pkt_len,
+				 u16 num_of_coalesced_segs)
 {
 	/* TPA aggregation won't have either IP options or TCP options
 	 * other than timestamp or IPv6 extension headers.
@@ -480,8 +481,7 @@ static void bnx2x_set_gro_params(struct sk_buff *skb, u16 parsing_flags,
 	/* tcp_gro_complete() will copy NAPI_GRO_CB(skb)->count
 	 * to skb_shinfo(skb)->gso_segs
 	 */
-	NAPI_GRO_CB(skb)->count = DIV_ROUND_UP(pkt_len - hdrs_len,
-					       skb_shinfo(skb)->gso_size);
+	NAPI_GRO_CB(skb)->count = num_of_coalesced_segs;
 }
 
 static int bnx2x_alloc_rx_sge(struct bnx2x *bp,
@@ -537,7 +537,8 @@ static int bnx2x_fill_frag_skb(struct bnx2x *bp, struct bnx2x_fastpath *fp,
 	/* This is needed in order to enable forwarding support */
 	if (frag_size)
 		bnx2x_set_gro_params(skb, tpa_info->parsing_flags, len_on_bd,
-				     le16_to_cpu(cqe->pkt_len));
+				     le16_to_cpu(cqe->pkt_len),
+				     le16_to_cpu(cqe->num_of_coalesced_segs));
 
 #ifdef BNX2X_STOP_ON_ERROR
 	if (pages > min_t(u32, 8, MAX_SKB_FRAGS) * SGE_PAGES) {
@@ -2009,7 +2010,7 @@ static int bnx2x_init_hw(struct bnx2x *bp, u32 load_code)
  * 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)
+void bnx2x_squeeze_objects(struct bnx2x *bp)
 {
 	int rc;
 	unsigned long ramrod_flags = 0, vlan_mac_flags = 0;
@@ -2774,7 +2775,7 @@ load_error0:
 #endif /* ! BNX2X_STOP_ON_ERROR */
 }
 
-static int bnx2x_drain_tx_queues(struct bnx2x *bp)
+int bnx2x_drain_tx_queues(struct bnx2x *bp)
 {
 	u8 rc = 0, cos, i;
 
@@ -3086,11 +3087,11 @@ int bnx2x_poll(struct napi_struct *napi, int budget)
  * to ease the pain of our fellow microcode engineers
  * we use one mapping for both BDs
  */
-static noinline u16 bnx2x_tx_split(struct bnx2x *bp,
-				   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)
+static u16 bnx2x_tx_split(struct bnx2x *bp,
+			  struct bnx2x_fp_txdata *txdata,
+			  struct sw_tx_bd *tx_buf,
+			  struct eth_tx_start_bd **tx_bd, u16 hlen,
+			  u16 bd_prod)
 {
 	struct eth_tx_start_bd *h_tx_bd = *tx_bd;
 	struct eth_tx_bd *d_tx_bd;
@@ -3098,11 +3099,10 @@ static noinline u16 bnx2x_tx_split(struct bnx2x *bp,
 	int old_len = le16_to_cpu(h_tx_bd->nbytes);
 
 	/* first fix first BD */
-	h_tx_bd->nbd = cpu_to_le16(nbd);
 	h_tx_bd->nbytes = cpu_to_le16(hlen);
 
-	DP(NETIF_MSG_TX_QUEUED,	"TSO split header size is %d (%x:%x) nbd %d\n",
-	   h_tx_bd->nbytes, h_tx_bd->addr_hi, h_tx_bd->addr_lo, h_tx_bd->nbd);
+	DP(NETIF_MSG_TX_QUEUED,	"TSO split header size is %d (%x:%x)\n",
+	   h_tx_bd->nbytes, h_tx_bd->addr_hi, h_tx_bd->addr_lo);
 
 	/* now get a new data BD
 	 * (after the pbd) and fill it */
@@ -3131,7 +3131,7 @@ static noinline u16 bnx2x_tx_split(struct bnx2x *bp,
 
 #define bswab32(b32) ((__force __le32) swab32((__force __u32) (b32)))
 #define bswab16(b16) ((__force __le16) swab16((__force __u16) (b16)))
-static inline __le16 bnx2x_csum_fix(unsigned char *t_header, u16 csum, s8 fix)
+static __le16 bnx2x_csum_fix(unsigned char *t_header, u16 csum, s8 fix)
 {
 	__sum16 tsum = (__force __sum16) csum;
 
@@ -3146,30 +3146,47 @@ static inline __le16 bnx2x_csum_fix(unsigned char *t_header, u16 csum, s8 fix)
 	return bswab16(tsum);
 }
 
-static inline u32 bnx2x_xmit_type(struct bnx2x *bp, struct sk_buff *skb)
+static u32 bnx2x_xmit_type(struct bnx2x *bp, struct sk_buff *skb)
 {
 	u32 rc;
+	__u8 prot = 0;
+	__be16 protocol;
 
 	if (skb->ip_summed != CHECKSUM_PARTIAL)
-		rc = XMIT_PLAIN;
+		return XMIT_PLAIN;
 
-	else {
-		if (vlan_get_protocol(skb) == htons(ETH_P_IPV6)) {
-			rc = XMIT_CSUM_V6;
-			if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP)
-				rc |= XMIT_CSUM_TCP;
+	protocol = vlan_get_protocol(skb);
+	if (protocol == htons(ETH_P_IPV6)) {
+		rc = XMIT_CSUM_V6;
+		prot = ipv6_hdr(skb)->nexthdr;
+	} else {
+		rc = XMIT_CSUM_V4;
+		prot = ip_hdr(skb)->protocol;
+	}
 
+	if (!CHIP_IS_E1x(bp) && skb->encapsulation) {
+		if (inner_ip_hdr(skb)->version == 6) {
+			rc |= XMIT_CSUM_ENC_V6;
+			if (inner_ipv6_hdr(skb)->nexthdr == IPPROTO_TCP)
+				rc |= XMIT_CSUM_TCP;
 		} else {
-			rc = XMIT_CSUM_V4;
-			if (ip_hdr(skb)->protocol == IPPROTO_TCP)
+			rc |= XMIT_CSUM_ENC_V4;
+			if (inner_ip_hdr(skb)->protocol == IPPROTO_TCP)
 				rc |= XMIT_CSUM_TCP;
 		}
 	}
+	if (prot == IPPROTO_TCP)
+		rc |= XMIT_CSUM_TCP;
 
-	if (skb_is_gso_v6(skb))
-		rc |= XMIT_GSO_V6 | XMIT_CSUM_TCP | XMIT_CSUM_V6;
-	else if (skb_is_gso(skb))
-		rc |= XMIT_GSO_V4 | XMIT_CSUM_V4 | XMIT_CSUM_TCP;
+	if (skb_is_gso_v6(skb)) {
+		rc |= (XMIT_GSO_V6 | XMIT_CSUM_TCP | XMIT_CSUM_V6);
+		if (rc & XMIT_CSUM_ENC)
+			rc |= XMIT_GSO_ENC_V6;
+	} else if (skb_is_gso(skb)) {
+		rc |= (XMIT_GSO_V4 | XMIT_CSUM_V4 | XMIT_CSUM_TCP);
+		if (rc & XMIT_CSUM_ENC)
+			rc |= XMIT_GSO_ENC_V4;
+	}
 
 	return rc;
 }
@@ -3254,14 +3271,23 @@ exit_lbl:
 }
 #endif
 
-static inline void bnx2x_set_pbd_gso_e2(struct sk_buff *skb, u32 *parsing_data,
-					u32 xmit_type)
+static void bnx2x_set_pbd_gso_e2(struct sk_buff *skb, u32 *parsing_data,
+				 u32 xmit_type)
 {
+	struct ipv6hdr *ipv6;
+
 	*parsing_data |= (skb_shinfo(skb)->gso_size <<
 			      ETH_TX_PARSE_BD_E2_LSO_MSS_SHIFT) &
 			      ETH_TX_PARSE_BD_E2_LSO_MSS;
-	if ((xmit_type & XMIT_GSO_V6) &&
-	    (ipv6_hdr(skb)->nexthdr == NEXTHDR_IPV6))
+
+	if (xmit_type & XMIT_GSO_ENC_V6)
+		ipv6 = inner_ipv6_hdr(skb);
+	else if (xmit_type & XMIT_GSO_V6)
+		ipv6 = ipv6_hdr(skb);
+	else
+		ipv6 = NULL;
+
+	if (ipv6 && ipv6->nexthdr == NEXTHDR_IPV6)
 		*parsing_data |= ETH_TX_PARSE_BD_E2_IPV6_WITH_EXT_HDR;
 }
 
@@ -3272,13 +3298,13 @@ static inline void bnx2x_set_pbd_gso_e2(struct sk_buff *skb, u32 *parsing_data,
  * @pbd:	parse BD
  * @xmit_type:	xmit flags
  */
-static inline void bnx2x_set_pbd_gso(struct sk_buff *skb,
-				     struct eth_tx_parse_bd_e1x *pbd,
-				     u32 xmit_type)
+static void bnx2x_set_pbd_gso(struct sk_buff *skb,
+			      struct eth_tx_parse_bd_e1x *pbd,
+			      u32 xmit_type)
 {
 	pbd->lso_mss = cpu_to_le16(skb_shinfo(skb)->gso_size);
 	pbd->tcp_send_seq = bswab32(tcp_hdr(skb)->seq);
-	pbd->tcp_flags = pbd_tcp_flags(skb);
+	pbd->tcp_flags = pbd_tcp_flags(tcp_hdr(skb));
 
 	if (xmit_type & XMIT_GSO_V4) {
 		pbd->ip_id = bswab16(ip_hdr(skb)->id);
@@ -3298,6 +3324,40 @@ static inline void bnx2x_set_pbd_gso(struct sk_buff *skb,
 }
 
 /**
+ * bnx2x_set_pbd_csum_enc - update PBD with checksum and return header length
+ *
+ * @bp:			driver handle
+ * @skb:		packet skb
+ * @parsing_data:	data to be updated
+ * @xmit_type:		xmit flags
+ *
+ * 57712/578xx related, when skb has encapsulation
+ */
+static u8 bnx2x_set_pbd_csum_enc(struct bnx2x *bp, struct sk_buff *skb,
+				 u32 *parsing_data, u32 xmit_type)
+{
+	*parsing_data |=
+		((((u8 *)skb_inner_transport_header(skb) - skb->data) >> 1) <<
+		ETH_TX_PARSE_BD_E2_L4_HDR_START_OFFSET_W_SHIFT) &
+		ETH_TX_PARSE_BD_E2_L4_HDR_START_OFFSET_W;
+
+	if (xmit_type & XMIT_CSUM_TCP) {
+		*parsing_data |= ((inner_tcp_hdrlen(skb) / 4) <<
+			ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW_SHIFT) &
+			ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW;
+
+		return skb_inner_transport_header(skb) +
+			inner_tcp_hdrlen(skb) - skb->data;
+	}
+
+	/* We support checksum offload for TCP and UDP only.
+	 * No need to pass the UDP header length - it's a constant.
+	 */
+	return skb_inner_transport_header(skb) +
+		sizeof(struct udphdr) - skb->data;
+}
+
+/**
  * bnx2x_set_pbd_csum_e2 - update PBD with checksum and return header length
  *
  * @bp:			driver handle
@@ -3305,15 +3365,15 @@ static inline void bnx2x_set_pbd_gso(struct sk_buff *skb,
  * @parsing_data:	data to be updated
  * @xmit_type:		xmit flags
  *
- * 57712 related
+ * 57712/578xx related
  */
-static inline  u8 bnx2x_set_pbd_csum_e2(struct bnx2x *bp, struct sk_buff *skb,
-					u32 *parsing_data, u32 xmit_type)
+static u8 bnx2x_set_pbd_csum_e2(struct bnx2x *bp, struct sk_buff *skb,
+				u32 *parsing_data, u32 xmit_type)
 {
 	*parsing_data |=
 		((((u8 *)skb_transport_header(skb) - skb->data) >> 1) <<
-		ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W_SHIFT) &
-		ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W;
+		ETH_TX_PARSE_BD_E2_L4_HDR_START_OFFSET_W_SHIFT) &
+		ETH_TX_PARSE_BD_E2_L4_HDR_START_OFFSET_W;
 
 	if (xmit_type & XMIT_CSUM_TCP) {
 		*parsing_data |= ((tcp_hdrlen(skb) / 4) <<
@@ -3328,17 +3388,15 @@ static inline  u8 bnx2x_set_pbd_csum_e2(struct bnx2x *bp, struct sk_buff *skb,
 	return skb_transport_header(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)
+/* set FW indication according to inner or outer protocols if tunneled */
+static 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_ENC_V6 | XMIT_CSUM_V6))
+		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;
@@ -3352,9 +3410,9 @@ static inline void bnx2x_set_sbd_csum(struct bnx2x *bp, struct sk_buff *skb,
  * @pbd:	parse BD to be updated
  * @xmit_type:	xmit flags
  */
-static inline u8 bnx2x_set_pbd_csum(struct bnx2x *bp, struct sk_buff *skb,
-	struct eth_tx_parse_bd_e1x *pbd,
-	u32 xmit_type)
+static u8 bnx2x_set_pbd_csum(struct bnx2x *bp, struct sk_buff *skb,
+			     struct eth_tx_parse_bd_e1x *pbd,
+			     u32 xmit_type)
 {
 	u8 hlen = (skb_network_header(skb) - skb->data) >> 1;
 
@@ -3400,6 +3458,70 @@ static inline u8 bnx2x_set_pbd_csum(struct bnx2x *bp, struct sk_buff *skb,
 	return hlen;
 }
 
+static void bnx2x_update_pbds_gso_enc(struct sk_buff *skb,
+				      struct eth_tx_parse_bd_e2 *pbd_e2,
+				      struct eth_tx_parse_2nd_bd *pbd2,
+				      u16 *global_data,
+				      u32 xmit_type)
+{
+	u16 hlen_w = 0;
+	u8 outerip_off, outerip_len = 0;
+	/* from outer IP to transport */
+	hlen_w = (skb_inner_transport_header(skb) -
+		  skb_network_header(skb)) >> 1;
+
+	/* transport len */
+	if (xmit_type & XMIT_CSUM_TCP)
+		hlen_w += inner_tcp_hdrlen(skb) >> 1;
+	else
+		hlen_w += sizeof(struct udphdr) >> 1;
+
+	pbd2->fw_ip_hdr_to_payload_w = hlen_w;
+
+	if (xmit_type & XMIT_CSUM_ENC_V4) {
+		struct iphdr *iph = ip_hdr(skb);
+		pbd2->fw_ip_csum_wo_len_flags_frag =
+			bswab16(csum_fold((~iph->check) -
+					  iph->tot_len - iph->frag_off));
+	} else {
+		pbd2->fw_ip_hdr_to_payload_w =
+			hlen_w - ((sizeof(struct ipv6hdr)) >> 1);
+	}
+
+	pbd2->tcp_send_seq = bswab32(inner_tcp_hdr(skb)->seq);
+
+	pbd2->tcp_flags = pbd_tcp_flags(inner_tcp_hdr(skb));
+
+	if (xmit_type & XMIT_GSO_V4) {
+		pbd2->hw_ip_id = bswab16(inner_ip_hdr(skb)->id);
+
+		pbd_e2->data.tunnel_data.pseudo_csum =
+			bswab16(~csum_tcpudp_magic(
+					inner_ip_hdr(skb)->saddr,
+					inner_ip_hdr(skb)->daddr,
+					0, IPPROTO_TCP, 0));
+
+		outerip_len = ip_hdr(skb)->ihl << 1;
+	} else {
+		pbd_e2->data.tunnel_data.pseudo_csum =
+			bswab16(~csum_ipv6_magic(
+					&inner_ipv6_hdr(skb)->saddr,
+					&inner_ipv6_hdr(skb)->daddr,
+					0, IPPROTO_TCP, 0));
+	}
+
+	outerip_off = (skb_network_header(skb) - skb->data) >> 1;
+
+	*global_data |=
+		outerip_off |
+		(!!(xmit_type & XMIT_CSUM_V6) <<
+			ETH_TX_PARSE_2ND_BD_IP_HDR_TYPE_OUTER_SHIFT) |
+		(outerip_len <<
+			ETH_TX_PARSE_2ND_BD_IP_HDR_LEN_OUTER_W_SHIFT) |
+		((skb->protocol == cpu_to_be16(ETH_P_8021Q)) <<
+			ETH_TX_PARSE_2ND_BD_LLC_SNAP_EN_SHIFT);
+}
+
 /* called with netif_tx_lock
  * bnx2x_tx_int() runs without netif_tx_lock unless it needs to call
  * netif_wake_queue()
@@ -3415,6 +3537,7 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	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;
+	struct eth_tx_parse_2nd_bd *pbd2 = NULL;
 	u32 pbd_e2_parsing_data = 0;
 	u16 pkt_prod, bd_prod;
 	int nbd, txq_index;
@@ -3482,7 +3605,7 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
 			mac_type = MULTICAST_ADDRESS;
 	}
 
-#if (MAX_SKB_FRAGS >= MAX_FETCH_BD - 3)
+#if (MAX_SKB_FRAGS >= MAX_FETCH_BD - BDS_PER_TX_PKT)
 	/* First, check if we need to linearize the skb (due to FW
 	   restrictions). No need to check fragmentation if page size > 8K
 	   (there will be no violation to FW restrictions) */
@@ -3530,12 +3653,9 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	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_PARSE_NBDS,
-		 0);
 
-	/* header nbd */
-	SET_FLAG(tx_start_bd->general_data, ETH_TX_START_BD_HDR_NBDS, 1);
+	/* header nbd: indirectly zero other flags! */
+	tx_start_bd->general_data = 1 << ETH_TX_START_BD_HDR_NBDS_SHIFT;
 
 	/* remember the first BD of the packet */
 	tx_buf->first_bd = txdata->tx_bd_prod;
@@ -3555,19 +3675,16 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
 		/* when transmitting in a vf, start bd must hold the ethertype
 		 * for fw to enforce it
 		 */
-#ifndef BNX2X_STOP_ON_ERROR
-		if (IS_VF(bp)) {
-#endif
+		if (IS_VF(bp))
 			tx_start_bd->vlan_or_ethertype =
 				cpu_to_le16(ntohs(eth->h_proto));
-#ifndef BNX2X_STOP_ON_ERROR
-		} else {
+		else
 			/* used by FW for packet accounting */
 			tx_start_bd->vlan_or_ethertype = cpu_to_le16(pkt_prod);
-		}
-#endif
 	}
 
+	nbd = 2; /* start_bd + pbd + frags (updated when pages are mapped) */
+
 	/* turn on parsing and get a BD */
 	bd_prod = TX_BD(NEXT_TX_IDX(bd_prod));
 
@@ -3577,23 +3694,58 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	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)
+
+		if (xmit_type & XMIT_CSUM_ENC) {
+			u16 global_data = 0;
+
+			/* Set PBD in enc checksum offload case */
+			hlen = bnx2x_set_pbd_csum_enc(bp, skb,
+						      &pbd_e2_parsing_data,
+						      xmit_type);
+
+			/* turn on 2nd parsing and get a BD */
+			bd_prod = TX_BD(NEXT_TX_IDX(bd_prod));
+
+			pbd2 = &txdata->tx_desc_ring[bd_prod].parse_2nd_bd;
+
+			memset(pbd2, 0, sizeof(*pbd2));
+
+			pbd_e2->data.tunnel_data.ip_hdr_start_inner_w =
+				(skb_inner_network_header(skb) -
+				 skb->data) >> 1;
+
+			if (xmit_type & XMIT_GSO_ENC)
+				bnx2x_update_pbds_gso_enc(skb, pbd_e2, pbd2,
+							  &global_data,
+							  xmit_type);
+
+			pbd2->global_data = cpu_to_le16(global_data);
+
+			/* add addition parse BD indication to start BD */
+			SET_FLAG(tx_start_bd->general_data,
+				 ETH_TX_START_BD_PARSE_NBDS, 1);
+			/* set encapsulation flag in start BD */
+			SET_FLAG(tx_start_bd->general_data,
+				 ETH_TX_START_BD_TUNNEL_EXIST, 1);
+			nbd++;
+		} else if (xmit_type & XMIT_CSUM) {
+			/* Set PBD in checksum offload case w/o encapsulation */
 			hlen = bnx2x_set_pbd_csum_e2(bp, skb,
 						     &pbd_e2_parsing_data,
 						     xmit_type);
+		}
 
-		if (IS_MF_SI(bp) || IS_VF(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,
+		/* Add the macs to the parsing BD this is a vf */
+		if (IS_VF(bp)) {
+			/* override GRE parameters in BD */
+			bnx2x_set_fw_mac_addr(&pbd_e2->data.mac_addr.src_hi,
+					      &pbd_e2->data.mac_addr.src_mid,
+					      &pbd_e2->data.mac_addr.src_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,
+
+			bnx2x_set_fw_mac_addr(&pbd_e2->data.mac_addr.dst_hi,
+					      &pbd_e2->data.mac_addr.dst_mid,
+					      &pbd_e2->data.mac_addr.dst_lo,
 					      eth->h_dest);
 		}
 
@@ -3615,14 +3767,13 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	/* 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 = 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;
 
 	DP(NETIF_MSG_TX_QUEUED,
-	   "first bd @%p  addr (%x:%x)  nbd %d  nbytes %d  flags %x  vlan %x\n",
+	   "first bd @%p  addr (%x:%x)  nbytes %d  flags %x  vlan %x\n",
 	   tx_start_bd, tx_start_bd->addr_hi, tx_start_bd->addr_lo,
-	   le16_to_cpu(tx_start_bd->nbd), le16_to_cpu(tx_start_bd->nbytes),
+	   le16_to_cpu(tx_start_bd->nbytes),
 	   tx_start_bd->bd_flags.as_bitfield,
 	   le16_to_cpu(tx_start_bd->vlan_or_ethertype));
 
@@ -3635,10 +3786,12 @@ 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))
+		if (unlikely(skb_headlen(skb) > hlen)) {
+			nbd++;
 			bd_prod = bnx2x_tx_split(bp, txdata, tx_buf,
 						 &tx_start_bd, hlen,
-						 bd_prod, ++nbd);
+						 bd_prod);
+		}
 		if (!CHIP_IS_E1x(bp))
 			bnx2x_set_pbd_gso_e2(skb, &pbd_e2_parsing_data,
 					     xmit_type);
@@ -3728,9 +3881,13 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	if (pbd_e2)
 		DP(NETIF_MSG_TX_QUEUED,
 		   "PBD (E2) @%p  dst %x %x %x src %x %x %x parsing_data %x\n",
-		   pbd_e2, pbd_e2->dst_mac_addr_hi, pbd_e2->dst_mac_addr_mid,
-		   pbd_e2->dst_mac_addr_lo, pbd_e2->src_mac_addr_hi,
-		   pbd_e2->src_mac_addr_mid, pbd_e2->src_mac_addr_lo,
+		   pbd_e2,
+		   pbd_e2->data.mac_addr.dst_hi,
+		   pbd_e2->data.mac_addr.dst_mid,
+		   pbd_e2->data.mac_addr.dst_lo,
+		   pbd_e2->data.mac_addr.src_hi,
+		   pbd_e2->data.mac_addr.src_mid,
+		   pbd_e2->data.mac_addr.src_lo,
 		   pbd_e2->parsing_data);
 	DP(NETIF_MSG_TX_QUEUED, "doorbell: nbd %d  bd %u\n", nbd, bd_prod);
 
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
index aee7671..54e1b14 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
@@ -50,13 +50,13 @@ extern int int_mode;
 		} \
 	} while (0)
 
-#define BNX2X_PCI_ALLOC(x, y, size) \
-	do { \
-		x = dma_alloc_coherent(&bp->pdev->dev, size, y, GFP_KERNEL); \
-		if (x == NULL) \
-			goto alloc_mem_err; \
-		memset((void *)x, 0, size); \
-	} while (0)
+#define BNX2X_PCI_ALLOC(x, y, size)				\
+do {								\
+	x = dma_alloc_coherent(&bp->pdev->dev, size, y,		\
+			       GFP_KERNEL | __GFP_ZERO);	\
+	if (x == NULL)						\
+		goto alloc_mem_err;				\
+} while (0)
 
 #define BNX2X_ALLOC(x, size) \
 	do { \
@@ -496,7 +496,10 @@ 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);
 
+int bnx2x_get_vf_config(struct net_device *dev, int vf,
+			struct ifla_vf_info *ivi);
 int bnx2x_set_vf_mac(struct net_device *dev, int queue, u8 *mac);
+int bnx2x_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos);
 
 /* select_queue callback */
 u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb);
@@ -834,7 +837,7 @@ static inline void bnx2x_add_all_napi_cnic(struct bnx2x *bp)
 	/* Add NAPI objects */
 	for_each_rx_queue_cnic(bp, i)
 		netif_napi_add(bp->dev, &bnx2x_fp(bp, i, napi),
-			       bnx2x_poll, BNX2X_NAPI_WEIGHT);
+			       bnx2x_poll, NAPI_POLL_WEIGHT);
 }
 
 static inline void bnx2x_add_all_napi(struct bnx2x *bp)
@@ -844,7 +847,7 @@ static inline void bnx2x_add_all_napi(struct bnx2x *bp)
 	/* Add NAPI objects */
 	for_each_eth_queue(bp, i)
 		netif_napi_add(bp->dev, &bnx2x_fp(bp, i, napi),
-			       bnx2x_poll, BNX2X_NAPI_WEIGHT);
+			       bnx2x_poll, NAPI_POLL_WEIGHT);
 }
 
 static inline void bnx2x_del_all_napi_cnic(struct bnx2x *bp)
@@ -970,6 +973,9 @@ static inline int bnx2x_func_start(struct bnx2x *bp)
 	else /* CHIP_IS_E1X */
 		start_params->network_cos_mode = FW_WRR;
 
+	start_params->gre_tunnel_mode = IPGRE_TUNNEL;
+	start_params->gre_tunnel_rss = GRE_INNER_HEADERS_RSS;
+
 	return bnx2x_func_state_change(bp, &func_params);
 }
 
@@ -1396,4 +1402,8 @@ static inline bool bnx2x_is_valid_ether_addr(struct bnx2x *bp, u8 *addr)
  *
  */
 void bnx2x_fill_fw_str(struct bnx2x *bp, char *buf, size_t buf_len);
+
+int bnx2x_drain_tx_queues(struct bnx2x *bp);
+void bnx2x_squeeze_objects(struct bnx2x *bp);
+
 #endif /* BNX2X_CMN_H */
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
index edfa67a..129d6b2 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
@@ -1393,10 +1393,9 @@ static int bnx2x_get_module_eeprom(struct net_device *dev,
 				   u8 *data)
 {
 	struct bnx2x *bp = netdev_priv(dev);
-	int rc = 0, phy_idx;
+	int rc = -EINVAL, phy_idx;
 	u8 *user_data = data;
-	int remaining_len = ee->len, xfer_size;
-	unsigned int page_off = ee->offset;
+	unsigned int start_addr = ee->offset, xfer_size = 0;
 
 	if (!netif_running(dev)) {
 		DP(BNX2X_MSG_ETHTOOL | BNX2X_MSG_NVM,
@@ -1405,21 +1404,52 @@ static int bnx2x_get_module_eeprom(struct net_device *dev,
 	}
 
 	phy_idx = bnx2x_get_cur_phy_idx(bp);
-	bnx2x_acquire_phy_lock(bp);
-	while (!rc && remaining_len > 0) {
-		xfer_size = (remaining_len > SFP_EEPROM_PAGE_SIZE) ?
-			SFP_EEPROM_PAGE_SIZE : remaining_len;
+
+	/* Read A0 section */
+	if (start_addr < ETH_MODULE_SFF_8079_LEN) {
+		/* Limit transfer size to the A0 section boundary */
+		if (start_addr + ee->len > ETH_MODULE_SFF_8079_LEN)
+			xfer_size = ETH_MODULE_SFF_8079_LEN - start_addr;
+		else
+			xfer_size = ee->len;
+		bnx2x_acquire_phy_lock(bp);
 		rc = bnx2x_read_sfp_module_eeprom(&bp->link_params.phy[phy_idx],
 						  &bp->link_params,
-						  page_off,
+						  I2C_DEV_ADDR_A0,
+						  start_addr,
 						  xfer_size,
 						  user_data);
-		remaining_len -= xfer_size;
+		bnx2x_release_phy_lock(bp);
+		if (rc) {
+			DP(BNX2X_MSG_ETHTOOL, "Failed reading A0 section\n");
+
+			return -EINVAL;
+		}
 		user_data += xfer_size;
-		page_off += xfer_size;
+		start_addr += xfer_size;
 	}
 
-	bnx2x_release_phy_lock(bp);
+	/* Read A2 section */
+	if ((start_addr >= ETH_MODULE_SFF_8079_LEN) &&
+	    (start_addr < ETH_MODULE_SFF_8472_LEN)) {
+		xfer_size = ee->len - xfer_size;
+		/* Limit transfer size to the A2 section boundary */
+		if (start_addr + xfer_size > ETH_MODULE_SFF_8472_LEN)
+			xfer_size = ETH_MODULE_SFF_8472_LEN - start_addr;
+		start_addr -= ETH_MODULE_SFF_8079_LEN;
+		bnx2x_acquire_phy_lock(bp);
+		rc = bnx2x_read_sfp_module_eeprom(&bp->link_params.phy[phy_idx],
+						  &bp->link_params,
+						  I2C_DEV_ADDR_A2,
+						  start_addr,
+						  xfer_size,
+						  user_data);
+		bnx2x_release_phy_lock(bp);
+		if (rc) {
+			DP(BNX2X_MSG_ETHTOOL, "Failed reading A2 section\n");
+			return -EINVAL;
+		}
+	}
 	return rc;
 }
 
@@ -1427,24 +1457,50 @@ static int bnx2x_get_module_info(struct net_device *dev,
 				 struct ethtool_modinfo *modinfo)
 {
 	struct bnx2x *bp = netdev_priv(dev);
-	int phy_idx;
+	int phy_idx, rc;
+	u8 sff8472_comp, diag_type;
+
 	if (!netif_running(dev)) {
-		DP(BNX2X_MSG_ETHTOOL  | BNX2X_MSG_NVM,
+		DP(BNX2X_MSG_ETHTOOL | BNX2X_MSG_NVM,
 		   "cannot access eeprom when the interface is down\n");
 		return -EAGAIN;
 	}
-
 	phy_idx = bnx2x_get_cur_phy_idx(bp);
-	switch (bp->link_params.phy[phy_idx].media_type) {
-	case ETH_PHY_SFPP_10G_FIBER:
-	case ETH_PHY_SFP_1G_FIBER:
-	case ETH_PHY_DA_TWINAX:
+	bnx2x_acquire_phy_lock(bp);
+	rc = bnx2x_read_sfp_module_eeprom(&bp->link_params.phy[phy_idx],
+					  &bp->link_params,
+					  I2C_DEV_ADDR_A0,
+					  SFP_EEPROM_SFF_8472_COMP_ADDR,
+					  SFP_EEPROM_SFF_8472_COMP_SIZE,
+					  &sff8472_comp);
+	bnx2x_release_phy_lock(bp);
+	if (rc) {
+		DP(BNX2X_MSG_ETHTOOL, "Failed reading SFF-8472 comp field\n");
+		return -EINVAL;
+	}
+
+	bnx2x_acquire_phy_lock(bp);
+	rc = bnx2x_read_sfp_module_eeprom(&bp->link_params.phy[phy_idx],
+					  &bp->link_params,
+					  I2C_DEV_ADDR_A0,
+					  SFP_EEPROM_DIAG_TYPE_ADDR,
+					  SFP_EEPROM_DIAG_TYPE_SIZE,
+					  &diag_type);
+	bnx2x_release_phy_lock(bp);
+	if (rc) {
+		DP(BNX2X_MSG_ETHTOOL, "Failed reading Diag Type field\n");
+		return -EINVAL;
+	}
+
+	if (!sff8472_comp ||
+	    (diag_type & SFP_EEPROM_DIAG_ADDR_CHANGE_REQ)) {
 		modinfo->type = ETH_MODULE_SFF_8079;
 		modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN;
-		return 0;
-	default:
-		return -EOPNOTSUPP;
+	} else {
+		modinfo->type = ETH_MODULE_SFF_8472;
+		modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN;
 	}
+	return 0;
 }
 
 static int bnx2x_nvram_write_dword(struct bnx2x *bp, u32 offset, u32 val,
@@ -3232,7 +3288,32 @@ static const struct ethtool_ops bnx2x_ethtool_ops = {
 	.get_ts_info		= ethtool_op_get_ts_info,
 };
 
-void bnx2x_set_ethtool_ops(struct net_device *netdev)
+static const struct ethtool_ops bnx2x_vf_ethtool_ops = {
+	.get_settings		= bnx2x_get_settings,
+	.set_settings		= bnx2x_set_settings,
+	.get_drvinfo		= bnx2x_get_drvinfo,
+	.get_msglevel		= bnx2x_get_msglevel,
+	.set_msglevel		= bnx2x_set_msglevel,
+	.get_link		= bnx2x_get_link,
+	.get_coalesce		= bnx2x_get_coalesce,
+	.get_ringparam		= bnx2x_get_ringparam,
+	.set_ringparam		= bnx2x_set_ringparam,
+	.get_sset_count		= bnx2x_get_sset_count,
+	.get_strings		= bnx2x_get_strings,
+	.get_ethtool_stats	= bnx2x_get_ethtool_stats,
+	.get_rxnfc		= bnx2x_get_rxnfc,
+	.set_rxnfc		= bnx2x_set_rxnfc,
+	.get_rxfh_indir_size	= bnx2x_get_rxfh_indir_size,
+	.get_rxfh_indir		= bnx2x_get_rxfh_indir,
+	.set_rxfh_indir		= bnx2x_set_rxfh_indir,
+	.get_channels		= bnx2x_get_channels,
+	.set_channels		= bnx2x_set_channels,
+};
+
+void bnx2x_set_ethtool_ops(struct bnx2x *bp, struct net_device *netdev)
 {
-	SET_ETHTOOL_OPS(netdev, &bnx2x_ethtool_ops);
+	if (IS_PF(bp))
+		SET_ETHTOOL_OPS(netdev, &bnx2x_ethtool_ops);
+	else /* vf */
+		SET_ETHTOOL_OPS(netdev, &bnx2x_vf_ethtool_ops);
 }
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h
index e5f8083..40f22c6 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h
@@ -30,31 +30,31 @@
 	* IRO[138].m2) + ((sbId) * IRO[138].m3))
 #define CSTORM_IGU_MODE_OFFSET (IRO[157].base)
 #define CSTORM_ISCSI_CQ_SIZE_OFFSET(pfId) \
-	(IRO[316].base + ((pfId) * IRO[316].m1))
-#define CSTORM_ISCSI_CQ_SQN_SIZE_OFFSET(pfId) \
 	(IRO[317].base + ((pfId) * IRO[317].m1))
+#define CSTORM_ISCSI_CQ_SQN_SIZE_OFFSET(pfId) \
+	(IRO[318].base + ((pfId) * IRO[318].m1))
 #define CSTORM_ISCSI_EQ_CONS_OFFSET(pfId, iscsiEqId) \
-	(IRO[309].base + ((pfId) * IRO[309].m1) + ((iscsiEqId) * IRO[309].m2))
+	(IRO[310].base + ((pfId) * IRO[310].m1) + ((iscsiEqId) * IRO[310].m2))
 #define CSTORM_ISCSI_EQ_NEXT_EQE_ADDR_OFFSET(pfId, iscsiEqId) \
-	(IRO[311].base + ((pfId) * IRO[311].m1) + ((iscsiEqId) * IRO[311].m2))
+	(IRO[312].base + ((pfId) * IRO[312].m1) + ((iscsiEqId) * IRO[312].m2))
 #define CSTORM_ISCSI_EQ_NEXT_PAGE_ADDR_OFFSET(pfId, iscsiEqId) \
-	(IRO[310].base + ((pfId) * IRO[310].m1) + ((iscsiEqId) * IRO[310].m2))
+	(IRO[311].base + ((pfId) * IRO[311].m1) + ((iscsiEqId) * IRO[311].m2))
 #define CSTORM_ISCSI_EQ_NEXT_PAGE_ADDR_VALID_OFFSET(pfId, iscsiEqId) \
-	(IRO[312].base + ((pfId) * IRO[312].m1) + ((iscsiEqId) * IRO[312].m2))
+	(IRO[313].base + ((pfId) * IRO[313].m1) + ((iscsiEqId) * IRO[313].m2))
 #define CSTORM_ISCSI_EQ_PROD_OFFSET(pfId, iscsiEqId) \
-	(IRO[308].base + ((pfId) * IRO[308].m1) + ((iscsiEqId) * IRO[308].m2))
+	(IRO[309].base + ((pfId) * IRO[309].m1) + ((iscsiEqId) * IRO[309].m2))
 #define CSTORM_ISCSI_EQ_SB_INDEX_OFFSET(pfId, iscsiEqId) \
-	(IRO[314].base + ((pfId) * IRO[314].m1) + ((iscsiEqId) * IRO[314].m2))
+	(IRO[315].base + ((pfId) * IRO[315].m1) + ((iscsiEqId) * IRO[315].m2))
 #define CSTORM_ISCSI_EQ_SB_NUM_OFFSET(pfId, iscsiEqId) \
-	(IRO[313].base + ((pfId) * IRO[313].m1) + ((iscsiEqId) * IRO[313].m2))
+	(IRO[314].base + ((pfId) * IRO[314].m1) + ((iscsiEqId) * IRO[314].m2))
 #define CSTORM_ISCSI_HQ_SIZE_OFFSET(pfId) \
-	(IRO[315].base + ((pfId) * IRO[315].m1))
+	(IRO[316].base + ((pfId) * IRO[316].m1))
 #define CSTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfId) \
-	(IRO[307].base + ((pfId) * IRO[307].m1))
+	(IRO[308].base + ((pfId) * IRO[308].m1))
 #define CSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfId) \
-	(IRO[306].base + ((pfId) * IRO[306].m1))
+	(IRO[307].base + ((pfId) * IRO[307].m1))
 #define CSTORM_ISCSI_PAGE_SIZE_OFFSET(pfId) \
-	(IRO[305].base + ((pfId) * IRO[305].m1))
+	(IRO[306].base + ((pfId) * IRO[306].m1))
 #define CSTORM_RECORD_SLOW_PATH_OFFSET(funcId) \
 	(IRO[151].base + ((funcId) * IRO[151].m1))
 #define CSTORM_SP_STATUS_BLOCK_DATA_OFFSET(pfId) \
@@ -114,7 +114,7 @@
 #define TSTORM_ISCSI_RQ_SIZE_OFFSET(pfId) \
 	(IRO[268].base + ((pfId) * IRO[268].m1))
 #define TSTORM_ISCSI_TCP_LOCAL_ADV_WND_OFFSET(pfId) \
-	(IRO[277].base + ((pfId) * IRO[277].m1))
+	(IRO[278].base + ((pfId) * IRO[278].m1))
 #define TSTORM_ISCSI_TCP_VARS_FLAGS_OFFSET(pfId) \
 	(IRO[264].base + ((pfId) * IRO[264].m1))
 #define TSTORM_ISCSI_TCP_VARS_LSB_LOCAL_MAC_ADDR_OFFSET(pfId) \
@@ -136,35 +136,32 @@
 #define USTORM_ASSERT_LIST_INDEX_OFFSET	(IRO[177].base)
 #define USTORM_ASSERT_LIST_OFFSET(assertListEntry) \
 	(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[183].base + ((portId) * IRO[183].m1))
 #define USTORM_FCOE_EQ_PROD_OFFSET(pfId) \
-	(IRO[318].base + ((pfId) * IRO[318].m1))
+	(IRO[319].base + ((pfId) * IRO[319].m1))
 #define USTORM_FUNC_EN_OFFSET(funcId) \
 	(IRO[178].base + ((funcId) * IRO[178].m1))
 #define USTORM_ISCSI_CQ_SIZE_OFFSET(pfId) \
-	(IRO[282].base + ((pfId) * IRO[282].m1))
-#define USTORM_ISCSI_CQ_SQN_SIZE_OFFSET(pfId) \
 	(IRO[283].base + ((pfId) * IRO[283].m1))
+#define USTORM_ISCSI_CQ_SQN_SIZE_OFFSET(pfId) \
+	(IRO[284].base + ((pfId) * IRO[284].m1))
 #define USTORM_ISCSI_ERROR_BITMAP_OFFSET(pfId) \
-	(IRO[287].base + ((pfId) * IRO[287].m1))
+	(IRO[288].base + ((pfId) * IRO[288].m1))
 #define USTORM_ISCSI_GLOBAL_BUF_PHYS_ADDR_OFFSET(pfId) \
-	(IRO[284].base + ((pfId) * IRO[284].m1))
+	(IRO[285].base + ((pfId) * IRO[285].m1))
 #define USTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfId) \
-	(IRO[280].base + ((pfId) * IRO[280].m1))
+	(IRO[281].base + ((pfId) * IRO[281].m1))
 #define USTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfId) \
-	(IRO[279].base + ((pfId) * IRO[279].m1))
+	(IRO[280].base + ((pfId) * IRO[280].m1))
 #define USTORM_ISCSI_PAGE_SIZE_OFFSET(pfId) \
-	(IRO[278].base + ((pfId) * IRO[278].m1))
+	(IRO[279].base + ((pfId) * IRO[279].m1))
 #define USTORM_ISCSI_R2TQ_SIZE_OFFSET(pfId) \
-	(IRO[281].base + ((pfId) * IRO[281].m1))
+	(IRO[282].base + ((pfId) * IRO[282].m1))
 #define USTORM_ISCSI_RQ_BUFFER_SIZE_OFFSET(pfId) \
-	(IRO[285].base + ((pfId) * IRO[285].m1))
-#define USTORM_ISCSI_RQ_SIZE_OFFSET(pfId) \
 	(IRO[286].base + ((pfId) * IRO[286].m1))
+#define USTORM_ISCSI_RQ_SIZE_OFFSET(pfId) \
+	(IRO[287].base + ((pfId) * IRO[287].m1))
 #define USTORM_MEM_WORKAROUND_ADDRESS_OFFSET(pfId) \
 	(IRO[182].base + ((pfId) * IRO[182].m1))
 #define USTORM_RECORD_SLOW_PATH_OFFSET(funcId) \
@@ -190,39 +187,39 @@
 #define XSTORM_FUNC_EN_OFFSET(funcId) \
 	(IRO[47].base + ((funcId) * IRO[47].m1))
 #define XSTORM_ISCSI_HQ_SIZE_OFFSET(pfId) \
-	(IRO[295].base + ((pfId) * IRO[295].m1))
+	(IRO[296].base + ((pfId) * IRO[296].m1))
 #define XSTORM_ISCSI_LOCAL_MAC_ADDR0_OFFSET(pfId) \
-	(IRO[298].base + ((pfId) * IRO[298].m1))
-#define XSTORM_ISCSI_LOCAL_MAC_ADDR1_OFFSET(pfId) \
 	(IRO[299].base + ((pfId) * IRO[299].m1))
-#define XSTORM_ISCSI_LOCAL_MAC_ADDR2_OFFSET(pfId) \
+#define XSTORM_ISCSI_LOCAL_MAC_ADDR1_OFFSET(pfId) \
 	(IRO[300].base + ((pfId) * IRO[300].m1))
-#define XSTORM_ISCSI_LOCAL_MAC_ADDR3_OFFSET(pfId) \
+#define XSTORM_ISCSI_LOCAL_MAC_ADDR2_OFFSET(pfId) \
 	(IRO[301].base + ((pfId) * IRO[301].m1))
-#define XSTORM_ISCSI_LOCAL_MAC_ADDR4_OFFSET(pfId) \
+#define XSTORM_ISCSI_LOCAL_MAC_ADDR3_OFFSET(pfId) \
 	(IRO[302].base + ((pfId) * IRO[302].m1))
-#define XSTORM_ISCSI_LOCAL_MAC_ADDR5_OFFSET(pfId) \
+#define XSTORM_ISCSI_LOCAL_MAC_ADDR4_OFFSET(pfId) \
 	(IRO[303].base + ((pfId) * IRO[303].m1))
-#define XSTORM_ISCSI_LOCAL_VLAN_OFFSET(pfId) \
+#define XSTORM_ISCSI_LOCAL_MAC_ADDR5_OFFSET(pfId) \
 	(IRO[304].base + ((pfId) * IRO[304].m1))
+#define XSTORM_ISCSI_LOCAL_VLAN_OFFSET(pfId) \
+	(IRO[305].base + ((pfId) * IRO[305].m1))
 #define XSTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfId) \
-	(IRO[294].base + ((pfId) * IRO[294].m1))
+	(IRO[295].base + ((pfId) * IRO[295].m1))
 #define XSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfId) \
-	(IRO[293].base + ((pfId) * IRO[293].m1))
+	(IRO[294].base + ((pfId) * IRO[294].m1))
 #define XSTORM_ISCSI_PAGE_SIZE_OFFSET(pfId) \
-	(IRO[292].base + ((pfId) * IRO[292].m1))
+	(IRO[293].base + ((pfId) * IRO[293].m1))
 #define XSTORM_ISCSI_R2TQ_SIZE_OFFSET(pfId) \
-	(IRO[297].base + ((pfId) * IRO[297].m1))
+	(IRO[298].base + ((pfId) * IRO[298].m1))
 #define XSTORM_ISCSI_SQ_SIZE_OFFSET(pfId) \
-	(IRO[296].base + ((pfId) * IRO[296].m1))
+	(IRO[297].base + ((pfId) * IRO[297].m1))
 #define XSTORM_ISCSI_TCP_VARS_ADV_WND_SCL_OFFSET(pfId) \
-	(IRO[291].base + ((pfId) * IRO[291].m1))
+	(IRO[292].base + ((pfId) * IRO[292].m1))
 #define XSTORM_ISCSI_TCP_VARS_FLAGS_OFFSET(pfId) \
-	(IRO[290].base + ((pfId) * IRO[290].m1))
+	(IRO[291].base + ((pfId) * IRO[291].m1))
 #define XSTORM_ISCSI_TCP_VARS_TOS_OFFSET(pfId) \
-	(IRO[289].base + ((pfId) * IRO[289].m1))
+	(IRO[290].base + ((pfId) * IRO[290].m1))
 #define XSTORM_ISCSI_TCP_VARS_TTL_OFFSET(pfId) \
-	(IRO[288].base + ((pfId) * IRO[288].m1))
+	(IRO[289].base + ((pfId) * IRO[289].m1))
 #define XSTORM_RATE_SHAPING_PER_VN_VARS_OFFSET(pfId) \
 	(IRO[44].base + ((pfId) * IRO[44].m1))
 #define XSTORM_RECORD_SLOW_PATH_OFFSET(funcId) \
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h
index 037860e..12f00a4 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h
@@ -114,6 +114,10 @@ struct license_key {
 #define EPIO_CFG_EPIO30                     0x0000001f
 #define EPIO_CFG_EPIO31                     0x00000020
 
+struct mac_addr {
+	u32 upper;
+	u32 lower;
+};
 
 struct shared_hw_cfg {			 /* NVRAM Offset */
 	/* Up to 16 bytes of NULL-terminated string */
@@ -508,7 +512,22 @@ struct port_hw_cfg {		    /* port 0: 0x12c  port 1: 0x2bc */
 	#define PORT_HW_CFG_PAUSE_ON_HOST_RING_DISABLED               0x00000000
 	#define PORT_HW_CFG_PAUSE_ON_HOST_RING_ENABLED                0x00000001
 
-	u32 reserved0[6];				    /* 0x178 */
+	/* SFP+ Tx Equalization: NIC recommended and tested value is 0xBEB2
+	 * LOM recommended and tested value is 0xBEB2. Using a different
+	 * value means using a value not tested by BRCM
+	 */
+	u32 sfi_tap_values;                                 /* 0x178 */
+	#define PORT_HW_CFG_TX_EQUALIZATION_MASK                      0x0000FFFF
+	#define PORT_HW_CFG_TX_EQUALIZATION_SHIFT                     0
+
+	/* SFP+ Tx driver broadcast IDRIVER: NIC recommended and tested
+	 * value is 0x2. LOM recommended and tested value is 0x2. Using a
+	 * different value means using a value not tested by BRCM
+	 */
+	#define PORT_HW_CFG_TX_DRV_BROADCAST_MASK                     0x000F0000
+	#define PORT_HW_CFG_TX_DRV_BROADCAST_SHIFT                    16
+
+	u32 reserved0[5];				    /* 0x17c */
 
 	u32 aeu_int_mask;				    /* 0x190 */
 
@@ -2821,8 +2840,8 @@ struct afex_stats {
 
 #define BCM_5710_FW_MAJOR_VERSION			7
 #define BCM_5710_FW_MINOR_VERSION			8
-#define BCM_5710_FW_REVISION_VERSION		2
-#define BCM_5710_FW_ENGINEERING_VERSION			0
+#define BCM_5710_FW_REVISION_VERSION		17
+#define BCM_5710_FW_ENGINEERING_VERSION		0
 #define BCM_5710_FW_COMPILE_FLAGS			1
 
 
@@ -3513,11 +3532,14 @@ struct client_init_tx_data {
 #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
+#define CLIENT_INIT_TX_DATA_RESERVED0 (0xFFF<<4)
+#define CLIENT_INIT_TX_DATA_RESERVED0_SHIFT 4
 	u8 default_vlan_flg;
 	u8 force_default_pri_flg;
-	__le32 reserved3;
+	u8 tunnel_lso_inc_ip_id;
+	u8 refuse_outband_vlan_flg;
+	u8 tunnel_non_lso_pcsum_location;
+	u8 reserved1;
 };
 
 /*
@@ -3551,6 +3573,11 @@ struct client_update_ramrod_data {
 	__le16 silent_vlan_mask;
 	u8 silent_vlan_removal_flg;
 	u8 silent_vlan_change_flg;
+	u8 refuse_outband_vlan_flg;
+	u8 refuse_outband_vlan_change_flg;
+	u8 tx_switching_flg;
+	u8 tx_switching_change_flg;
+	__le32 reserved1;
 	__le32 echo;
 };
 
@@ -3620,7 +3647,8 @@ struct eth_classify_header {
  */
 struct eth_classify_mac_cmd {
 	struct eth_classify_cmd_header header;
-	__le32 reserved0;
+	__le16 reserved0;
+	__le16 inner_mac;
 	__le16 mac_lsb;
 	__le16 mac_mid;
 	__le16 mac_msb;
@@ -3633,7 +3661,8 @@ struct eth_classify_mac_cmd {
  */
 struct eth_classify_pair_cmd {
 	struct eth_classify_cmd_header header;
-	__le32 reserved0;
+	__le16 reserved0;
+	__le16 inner_mac;
 	__le16 mac_lsb;
 	__le16 mac_mid;
 	__le16 mac_msb;
@@ -3855,8 +3884,68 @@ struct eth_halt_ramrod_data {
 
 
 /*
- * Command for setting multicast classification for a client
+ * destination and source mac address.
+ */
+struct eth_mac_addresses {
+#if defined(__BIG_ENDIAN)
+	__le16 dst_mid;
+	__le16 dst_lo;
+#elif defined(__LITTLE_ENDIAN)
+	__le16 dst_lo;
+	__le16 dst_mid;
+#endif
+#if defined(__BIG_ENDIAN)
+	__le16 src_lo;
+	__le16 dst_hi;
+#elif defined(__LITTLE_ENDIAN)
+	__le16 dst_hi;
+	__le16 src_lo;
+#endif
+#if defined(__BIG_ENDIAN)
+	__le16 src_hi;
+	__le16 src_mid;
+#elif defined(__LITTLE_ENDIAN)
+	__le16 src_mid;
+	__le16 src_hi;
+#endif
+};
+
+/* tunneling related data */
+struct eth_tunnel_data {
+#if defined(__BIG_ENDIAN)
+	__le16 dst_mid;
+	__le16 dst_lo;
+#elif defined(__LITTLE_ENDIAN)
+	__le16 dst_lo;
+	__le16 dst_mid;
+#endif
+#if defined(__BIG_ENDIAN)
+	__le16 reserved0;
+	__le16 dst_hi;
+#elif defined(__LITTLE_ENDIAN)
+	__le16 dst_hi;
+	__le16 reserved0;
+#endif
+#if defined(__BIG_ENDIAN)
+	u8 reserved1;
+	u8 ip_hdr_start_inner_w;
+	__le16 pseudo_csum;
+#elif defined(__LITTLE_ENDIAN)
+	__le16 pseudo_csum;
+	u8 ip_hdr_start_inner_w;
+	u8 reserved1;
+#endif
+};
+
+/* union for mac addresses and for tunneling data.
+ * considered as tunneling data only if (tunnel_exist == 1).
  */
+union eth_mac_addr_or_tunnel_data {
+	struct eth_mac_addresses mac_addr;
+	struct eth_tunnel_data tunnel_data;
+};
+
+/*Command for setting multicast classification for a client */
 struct eth_multicast_rules_cmd {
 	u8 cmd_general_data;
 #define ETH_MULTICAST_RULES_CMD_RX_CMD (0x1<<0)
@@ -3874,7 +3963,6 @@ struct eth_multicast_rules_cmd {
 	struct regpair reserved3;
 };
 
-
 /*
  * parameters for multicast classification ramrod
  */
@@ -3883,7 +3971,6 @@ struct eth_multicast_rules_ramrod_data {
 	struct eth_multicast_rules_cmd rules[MULTICAST_RULES_COUNT];
 };
 
-
 /*
  * Place holder for ramrods protocol specific data
  */
@@ -3947,11 +4034,14 @@ struct eth_rss_update_ramrod_data {
 #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_EN_5_TUPLE_CAPABILITY (0x1<<6)
+#define ETH_RSS_UPDATE_RAMROD_DATA_EN_5_TUPLE_CAPABILITY_SHIFT 6
 #define ETH_RSS_UPDATE_RAMROD_DATA_UPDATE_RSS_KEY (0x1<<7)
 #define ETH_RSS_UPDATE_RAMROD_DATA_UPDATE_RSS_KEY_SHIFT 7
 	u8 rss_result_mask;
 	u8 rss_mode;
-	__le32 __reserved2;
+	__le16 udp_4tuple_dst_port_mask;
+	__le16 udp_4tuple_dst_port_value;
 	u8 indirection_table[T_ETH_INDIRECTION_TABLE_SIZE];
 	__le32 rss_key[T_ETH_RSS_KEY];
 	__le32 echo;
@@ -4115,6 +4205,23 @@ enum eth_tpa_update_command {
 	MAX_ETH_TPA_UPDATE_COMMAND
 };
 
+/* In case of LSO over IPv4 tunnel, whether to increment
+ * IP ID on external IP header or internal IP header
+ */
+enum eth_tunnel_lso_inc_ip_id {
+	EXT_HEADER,
+	INT_HEADER,
+	MAX_ETH_TUNNEL_LSO_INC_IP_ID
+};
+
+/* In case tunnel exist and L4 checksum offload,
+ * the pseudo checksum location, on packet or on BD.
+ */
+enum eth_tunnel_non_lso_pcsum_location {
+	PCSUM_ON_PKT,
+	PCSUM_ON_BD,
+	MAX_ETH_TUNNEL_NON_LSO_PCSUM_LOCATION
+};
 
 /*
  * Tx regular BD structure
@@ -4166,8 +4273,8 @@ struct eth_tx_start_bd {
 #define ETH_TX_START_BD_FORCE_VLAN_MODE_SHIFT 4
 #define ETH_TX_START_BD_PARSE_NBDS (0x3<<5)
 #define ETH_TX_START_BD_PARSE_NBDS_SHIFT 5
-#define ETH_TX_START_BD_RESREVED (0x1<<7)
-#define ETH_TX_START_BD_RESREVED_SHIFT 7
+#define ETH_TX_START_BD_TUNNEL_EXIST (0x1<<7)
+#define ETH_TX_START_BD_TUNNEL_EXIST_SHIFT 7
 };
 
 /*
@@ -4216,15 +4323,10 @@ struct eth_tx_parse_bd_e1x {
  * Tx parsing BD structure for ETH E2
  */
 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;
+	union eth_mac_addr_or_tunnel_data data;
 	__le32 parsing_data;
-#define ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W (0x7FF<<0)
-#define ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W_SHIFT 0
+#define ETH_TX_PARSE_BD_E2_L4_HDR_START_OFFSET_W (0x7FF<<0)
+#define ETH_TX_PARSE_BD_E2_L4_HDR_START_OFFSET_W_SHIFT 0
 #define ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW (0xF<<11)
 #define ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW_SHIFT 11
 #define ETH_TX_PARSE_BD_E2_IPV6_WITH_EXT_HDR (0x1<<15)
@@ -4236,8 +4338,51 @@ struct eth_tx_parse_bd_e2 {
 };
 
 /*
- * The last BD in the BD memory will hold a pointer to the next BD memory
+ * Tx 2nd parsing BD structure for ETH packet
  */
+struct eth_tx_parse_2nd_bd {
+	__le16 global_data;
+#define ETH_TX_PARSE_2ND_BD_IP_HDR_START_OUTER_W (0xF<<0)
+#define ETH_TX_PARSE_2ND_BD_IP_HDR_START_OUTER_W_SHIFT 0
+#define ETH_TX_PARSE_2ND_BD_IP_HDR_TYPE_OUTER (0x1<<4)
+#define ETH_TX_PARSE_2ND_BD_IP_HDR_TYPE_OUTER_SHIFT 4
+#define ETH_TX_PARSE_2ND_BD_LLC_SNAP_EN (0x1<<5)
+#define ETH_TX_PARSE_2ND_BD_LLC_SNAP_EN_SHIFT 5
+#define ETH_TX_PARSE_2ND_BD_NS_FLG (0x1<<6)
+#define ETH_TX_PARSE_2ND_BD_NS_FLG_SHIFT 6
+#define ETH_TX_PARSE_2ND_BD_TUNNEL_UDP_EXIST (0x1<<7)
+#define ETH_TX_PARSE_2ND_BD_TUNNEL_UDP_EXIST_SHIFT 7
+#define ETH_TX_PARSE_2ND_BD_IP_HDR_LEN_OUTER_W (0x1F<<8)
+#define ETH_TX_PARSE_2ND_BD_IP_HDR_LEN_OUTER_W_SHIFT 8
+#define ETH_TX_PARSE_2ND_BD_RESERVED0 (0x7<<13)
+#define ETH_TX_PARSE_2ND_BD_RESERVED0_SHIFT 13
+	__le16 reserved1;
+	u8 tcp_flags;
+#define ETH_TX_PARSE_2ND_BD_FIN_FLG (0x1<<0)
+#define ETH_TX_PARSE_2ND_BD_FIN_FLG_SHIFT 0
+#define ETH_TX_PARSE_2ND_BD_SYN_FLG (0x1<<1)
+#define ETH_TX_PARSE_2ND_BD_SYN_FLG_SHIFT 1
+#define ETH_TX_PARSE_2ND_BD_RST_FLG (0x1<<2)
+#define ETH_TX_PARSE_2ND_BD_RST_FLG_SHIFT 2
+#define ETH_TX_PARSE_2ND_BD_PSH_FLG (0x1<<3)
+#define ETH_TX_PARSE_2ND_BD_PSH_FLG_SHIFT 3
+#define ETH_TX_PARSE_2ND_BD_ACK_FLG (0x1<<4)
+#define ETH_TX_PARSE_2ND_BD_ACK_FLG_SHIFT 4
+#define ETH_TX_PARSE_2ND_BD_URG_FLG (0x1<<5)
+#define ETH_TX_PARSE_2ND_BD_URG_FLG_SHIFT 5
+#define ETH_TX_PARSE_2ND_BD_ECE_FLG (0x1<<6)
+#define ETH_TX_PARSE_2ND_BD_ECE_FLG_SHIFT 6
+#define ETH_TX_PARSE_2ND_BD_CWR_FLG (0x1<<7)
+#define ETH_TX_PARSE_2ND_BD_CWR_FLG_SHIFT 7
+	u8 reserved2;
+	u8 tunnel_udp_hdr_start_w;
+	u8 fw_ip_hdr_to_payload_w;
+	__le16 fw_ip_csum_wo_len_flags_frag;
+	__le16 hw_ip_id;
+	__le32 tcp_send_seq;
+};
+
+/* The last BD in the BD memory will hold a pointer to the next BD memory */
 struct eth_tx_next_bd {
 	__le32 addr_lo;
 	__le32 addr_hi;
@@ -4252,6 +4397,7 @@ union eth_tx_bd_types {
 	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_parse_2nd_bd parse_2nd_bd;
 	struct eth_tx_next_bd next_bd;
 };
 
@@ -4663,10 +4809,10 @@ enum common_spqe_cmd_id {
 	RAMROD_CMD_ID_COMMON_STOP_TRAFFIC,
 	RAMROD_CMD_ID_COMMON_START_TRAFFIC,
 	RAMROD_CMD_ID_COMMON_AFEX_VIF_LISTS,
+	RAMROD_CMD_ID_COMMON_SET_TIMESYNC,
 	MAX_COMMON_SPQE_CMD_ID
 };
 
-
 /*
  * Per-protocol connection types
  */
@@ -4863,7 +5009,7 @@ struct vf_flr_event_data {
  */
 struct malicious_vf_event_data {
 	u8 vf_id;
-	u8 reserved0;
+	u8 err_id;
 	u16 reserved1;
 	u32 reserved2;
 	u32 reserved3;
@@ -4969,10 +5115,10 @@ enum event_ring_opcode {
 	EVENT_RING_OPCODE_CLASSIFICATION_RULES,
 	EVENT_RING_OPCODE_FILTERS_RULES,
 	EVENT_RING_OPCODE_MULTICAST_RULES,
+	EVENT_RING_OPCODE_SET_TIMESYNC,
 	MAX_EVENT_RING_OPCODE
 };
 
-
 /*
  * Modes for fairness algorithm
  */
@@ -5010,14 +5156,18 @@ struct flow_control_configuration {
  */
 struct function_start_data {
 	u8 function_mode;
-	u8 reserved;
+	u8 allow_npar_tx_switching;
 	__le16 sd_vlan_tag;
 	__le16 vif_id;
 	u8 path_id;
 	u8 network_cos_mode;
+	u8 dmae_cmd_id;
+	u8 gre_tunnel_mode;
+	u8 gre_tunnel_rss;
+	u8 nvgre_clss_en;
+	__le16 reserved1[2];
 };
 
-
 struct function_update_data {
 	u8 vif_id_change_flg;
 	u8 afex_default_vlan_change_flg;
@@ -5027,14 +5177,19 @@ struct function_update_data {
 	__le16 afex_default_vlan;
 	u8 allowed_priorities;
 	u8 network_cos_mode;
+	u8 lb_mode_en_change_flg;
 	u8 lb_mode_en;
 	u8 tx_switch_suspend_change_flg;
 	u8 tx_switch_suspend;
 	u8 echo;
-	__le16 reserved1;
+	u8 reserved1;
+	u8 update_gre_cfg_flg;
+	u8 gre_tunnel_mode;
+	u8 gre_tunnel_rss;
+	u8 nvgre_clss_en;
+	u32 reserved3;
 };
 
-
 /*
  * FW version stored in the Xstorm RAM
  */
@@ -5061,6 +5216,22 @@ struct fw_version {
 #define __FW_VERSION_RESERVED_SHIFT 4
 };
 
+/* GRE RSS Mode */
+enum gre_rss_mode {
+	GRE_OUTER_HEADERS_RSS,
+	GRE_INNER_HEADERS_RSS,
+	NVGRE_KEY_ENTROPY_RSS,
+	MAX_GRE_RSS_MODE
+};
+
+/* GRE Tunnel Mode */
+enum gre_tunnel_type {
+	NO_GRE_TUNNEL,
+	NVGRE_TUNNEL,
+	L2GRE_TUNNEL,
+	IPGRE_TUNNEL,
+	MAX_GRE_TUNNEL_TYPE
+};
 
 /*
  * Dynamic Host-Coalescing - Driver(host) counters
@@ -5224,6 +5395,26 @@ enum ip_ver {
 	MAX_IP_VER
 };
 
+/*
+ * Malicious VF error ID
+ */
+enum malicious_vf_error_id {
+	VF_PF_CHANNEL_NOT_READY,
+	ETH_ILLEGAL_BD_LENGTHS,
+	ETH_PACKET_TOO_SHORT,
+	ETH_PAYLOAD_TOO_BIG,
+	ETH_ILLEGAL_ETH_TYPE,
+	ETH_ILLEGAL_LSO_HDR_LEN,
+	ETH_TOO_MANY_BDS,
+	ETH_ZERO_HDR_NBDS,
+	ETH_START_BD_NOT_SET,
+	ETH_ILLEGAL_PARSE_NBDS,
+	ETH_IPV6_AND_CHECKSUM,
+	ETH_VLAN_FLG_INCORRECT,
+	ETH_ILLEGAL_LSO_MSS,
+	ETH_TUNNEL_NOT_SUPPORTED,
+	MAX_MALICIOUS_VF_ERROR_ID
+};
 
 /*
  * Multi-function modes
@@ -5368,7 +5559,6 @@ struct protocol_common_spe {
 	union protocol_common_specific_data data;
 };
 
-
 /*
  * The send queue element
  */
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
index 77ebae0..6cc6c63 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
@@ -27,6 +27,10 @@
 #include "bnx2x.h"
 #include "bnx2x_cmn.h"
 
+typedef int (*read_sfp_module_eeprom_func_p)(struct bnx2x_phy *phy,
+					     struct link_params *params,
+					     u8 dev_addr, u16 addr, u8 byte_cnt,
+					     u8 *o_buf, u8);
 /********************************************************/
 #define ETH_HLEN			14
 /* L2 header size + 2*VLANs (8 bytes) + LLC SNAP (8 bytes) */
@@ -152,6 +156,7 @@
 #define SFP_EEPROM_CON_TYPE_ADDR		0x2
 	#define SFP_EEPROM_CON_TYPE_VAL_LC	0x7
 	#define SFP_EEPROM_CON_TYPE_VAL_COPPER	0x21
+	#define SFP_EEPROM_CON_TYPE_VAL_RJ45	0x22
 
 
 #define SFP_EEPROM_COMP_CODE_ADDR		0x3
@@ -3127,11 +3132,6 @@ static int bnx2x_bsc_read(struct link_params *params,
 	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);
@@ -3629,6 +3629,16 @@ static u8 bnx2x_ext_phy_resolve_fc(struct bnx2x_phy *phy,
  * init configuration, and set/clear SGMII flag. Internal
  * phy init is done purely in phy_init stage.
  */
+#define WC_TX_DRIVER(post2, idriver, ipre) \
+	((post2 << MDIO_WC_REG_TX0_TX_DRIVER_POST2_COEFF_OFFSET) | \
+	 (idriver << MDIO_WC_REG_TX0_TX_DRIVER_IDRIVER_OFFSET) | \
+	 (ipre << MDIO_WC_REG_TX0_TX_DRIVER_IPRE_DRIVER_OFFSET))
+
+#define WC_TX_FIR(post, main, pre) \
+	((post << MDIO_WC_REG_TX_FIR_TAP_POST_TAP_OFFSET) | \
+	 (main << MDIO_WC_REG_TX_FIR_TAP_MAIN_TAP_OFFSET) | \
+	 (pre << MDIO_WC_REG_TX_FIR_TAP_PRE_TAP_OFFSET))
+
 static void bnx2x_warpcore_enable_AN_KR2(struct bnx2x_phy *phy,
 					 struct link_params *params,
 					 struct link_vars *vars)
@@ -3728,7 +3738,7 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
 	if (((vars->line_speed == SPEED_AUTO_NEG) &&
 	     (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) ||
 	    (vars->line_speed == SPEED_1000)) {
-		u32 addr = MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2;
+		u16 addr = MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2;
 		an_adv |= (1<<5);
 
 		/* Enable CL37 1G Parallel Detect */
@@ -3753,20 +3763,13 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
 	/* 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)));
+			 MDIO_WC_REG_TX0_TX_DRIVER + 0x10*lane,
+			 WC_TX_DRIVER(0x02, 0x06, 0x09));
 	/* Configure the next lane if dual mode */
 	if (phy->flags & FLAGS_WC_DUAL_MODE)
 		bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
 				 MDIO_WC_REG_TX0_TX_DRIVER + 0x10*(lane+1),
-				 ((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)));
+				 WC_TX_DRIVER(0x02, 0x06, 0x09));
 	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
 			 MDIO_WC_REG_CL72_USERB0_CL72_OS_DEF_CTRL,
 			 0x03f0);
@@ -3909,6 +3912,8 @@ static void bnx2x_warpcore_set_10G_XFI(struct bnx2x_phy *phy,
 {
 	struct bnx2x *bp = params->bp;
 	u16 misc1_val, tap_val, tx_driver_val, lane, val;
+	u32 cfg_tap_val, tx_drv_brdct, tx_equal;
+
 	/* Hold rxSeqStart */
 	bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD,
 				 MDIO_WC_REG_DSC2B0_DSC_MISC_CTRL0, 0x8000);
@@ -3952,23 +3957,33 @@ static void bnx2x_warpcore_set_10G_XFI(struct bnx2x_phy *phy,
 
 	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));
-
+		tap_val = WC_TX_FIR(0x08, 0x37, 0x00);
+		tx_driver_val = WC_TX_DRIVER(0x00, 0x02, 0x03);
 	} else {
+		cfg_tap_val = REG_RD(bp, params->shmem_base +
+				     offsetof(struct shmem_region, dev_info.
+					      port_hw_config[params->port].
+					      sfi_tap_values));
+
+		tx_equal = cfg_tap_val & PORT_HW_CFG_TX_EQUALIZATION_MASK;
+
+		tx_drv_brdct = (cfg_tap_val &
+				PORT_HW_CFG_TX_DRV_BROADCAST_MASK) >>
+			       PORT_HW_CFG_TX_DRV_BROADCAST_SHIFT;
+
 		misc1_val |= 0x9;
-		tap_val = ((0x0f << MDIO_WC_REG_TX_FIR_TAP_POST_TAP_OFFSET) |
-			   (0x2b << MDIO_WC_REG_TX_FIR_TAP_MAIN_TAP_OFFSET) |
-			   (0x02 << MDIO_WC_REG_TX_FIR_TAP_PRE_TAP_OFFSET));
-		tx_driver_val =
-		      ((0x03 << MDIO_WC_REG_TX0_TX_DRIVER_POST2_COEFF_OFFSET) |
-		       (0x02 << MDIO_WC_REG_TX0_TX_DRIVER_IDRIVER_OFFSET) |
-		       (0x06 << MDIO_WC_REG_TX0_TX_DRIVER_IPRE_DRIVER_OFFSET));
+
+		/* TAP values are controlled by nvram, if value there isn't 0 */
+		if (tx_equal)
+			tap_val = (u16)tx_equal;
+		else
+			tap_val = WC_TX_FIR(0x0f, 0x2b, 0x02);
+
+		if (tx_drv_brdct)
+			tx_driver_val = WC_TX_DRIVER(0x03, (u16)tx_drv_brdct,
+						     0x06);
+		else
+			tx_driver_val = WC_TX_DRIVER(0x03, 0x02, 0x06);
 	}
 	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
 			 MDIO_WC_REG_SERDESDIGITAL_MISC1, misc1_val);
@@ -4105,15 +4120,11 @@ static void bnx2x_warpcore_set_20G_DXGXS(struct bnx2x *bp,
 	/* 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));
+			 (WC_TX_FIR(0x12, 0x2d, 0x00) |
+			  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)));
+			 MDIO_WC_REG_TX0_TX_DRIVER + 0x10*lane,
+			 WC_TX_DRIVER(0x02, 0x02, 0x02));
 }
 
 static void bnx2x_warpcore_set_sgmii_speed(struct bnx2x_phy *phy,
@@ -4750,8 +4761,8 @@ void bnx2x_link_status_update(struct link_params *params,
 					    port_mb[port].link_status));
 
 	/* Force link UP in non LOOPBACK_EXT loopback mode(s) */
-	if (bp->link_params.loopback_mode != LOOPBACK_NONE &&
-	    bp->link_params.loopback_mode != LOOPBACK_EXT)
+	if (params->loopback_mode != LOOPBACK_NONE &&
+	    params->loopback_mode != LOOPBACK_EXT)
 		vars->link_status |= LINK_STATUS_LINK_UP;
 
 	if (bnx2x_eee_has_cap(params))
@@ -7758,7 +7769,8 @@ static void bnx2x_sfp_set_transmitter(struct link_params *params,
 
 static int bnx2x_8726_read_sfp_module_eeprom(struct bnx2x_phy *phy,
 					     struct link_params *params,
-					     u16 addr, u8 byte_cnt, u8 *o_buf)
+					     u8 dev_addr, u16 addr, u8 byte_cnt,
+					     u8 *o_buf, u8 is_init)
 {
 	struct bnx2x *bp = params->bp;
 	u16 val = 0;
@@ -7771,7 +7783,7 @@ static int bnx2x_8726_read_sfp_module_eeprom(struct bnx2x_phy *phy,
 	/* Set the read command byte count */
 	bnx2x_cl45_write(bp, phy,
 			 MDIO_PMA_DEVAD, MDIO_PMA_REG_SFP_TWO_WIRE_BYTE_CNT,
-			 (byte_cnt | 0xa000));
+			 (byte_cnt | (dev_addr << 8)));
 
 	/* Set the read command address */
 	bnx2x_cl45_write(bp, phy,
@@ -7845,6 +7857,7 @@ static void bnx2x_warpcore_power_module(struct link_params *params,
 }
 static int bnx2x_warpcore_read_sfp_module_eeprom(struct bnx2x_phy *phy,
 						 struct link_params *params,
+						 u8 dev_addr,
 						 u16 addr, u8 byte_cnt,
 						 u8 *o_buf, u8 is_init)
 {
@@ -7869,7 +7882,7 @@ static int bnx2x_warpcore_read_sfp_module_eeprom(struct bnx2x_phy *phy,
 			usleep_range(1000, 2000);
 			bnx2x_warpcore_power_module(params, 1);
 		}
-		rc = bnx2x_bsc_read(params, phy, 0xa0, addr32, 0, byte_cnt,
+		rc = bnx2x_bsc_read(params, phy, dev_addr, addr32, 0, byte_cnt,
 				    data_array);
 	} while ((rc != 0) && (++cnt < I2C_WA_RETRY_CNT));
 
@@ -7885,7 +7898,8 @@ static int bnx2x_warpcore_read_sfp_module_eeprom(struct bnx2x_phy *phy,
 
 static int bnx2x_8727_read_sfp_module_eeprom(struct bnx2x_phy *phy,
 					     struct link_params *params,
-					     u16 addr, u8 byte_cnt, u8 *o_buf)
+					     u8 dev_addr, u16 addr, u8 byte_cnt,
+					     u8 *o_buf, u8 is_init)
 {
 	struct bnx2x *bp = params->bp;
 	u16 val, i;
@@ -7896,6 +7910,15 @@ static int bnx2x_8727_read_sfp_module_eeprom(struct bnx2x_phy *phy,
 		return -EINVAL;
 	}
 
+	/* Set 2-wire transfer rate of SFP+ module EEPROM
+	 * to 100Khz since some DACs(direct attached cables) do
+	 * not work at 400Khz.
+	 */
+	bnx2x_cl45_write(bp, phy,
+			 MDIO_PMA_DEVAD,
+			 MDIO_PMA_REG_8727_TWO_WIRE_SLAVE_ADDR,
+			 ((dev_addr << 8) | 1));
+
 	/* Need to read from 1.8000 to clear it */
 	bnx2x_cl45_read(bp, phy,
 			MDIO_PMA_DEVAD,
@@ -7968,26 +7991,44 @@ static int bnx2x_8727_read_sfp_module_eeprom(struct bnx2x_phy *phy,
 
 	return -EINVAL;
 }
-
 int bnx2x_read_sfp_module_eeprom(struct bnx2x_phy *phy,
-				 struct link_params *params, u16 addr,
-				 u8 byte_cnt, u8 *o_buf)
+				 struct link_params *params, u8 dev_addr,
+				 u16 addr, u16 byte_cnt, u8 *o_buf)
 {
-	int rc = -EOPNOTSUPP;
+	int rc = 0;
+	struct bnx2x *bp = params->bp;
+	u8 xfer_size;
+	u8 *user_data = o_buf;
+	read_sfp_module_eeprom_func_p read_func;
+
+	if ((dev_addr != 0xa0) && (dev_addr != 0xa2)) {
+		DP(NETIF_MSG_LINK, "invalid dev_addr 0x%x\n", dev_addr);
+		return -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;
+		read_func = bnx2x_8726_read_sfp_module_eeprom;
+		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;
+		read_func = bnx2x_8727_read_sfp_module_eeprom;
+		break;
 	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
-		rc = bnx2x_warpcore_read_sfp_module_eeprom(phy, params, addr,
-							   byte_cnt, o_buf, 0);
-	break;
+		read_func = bnx2x_warpcore_read_sfp_module_eeprom;
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	while (!rc && (byte_cnt > 0)) {
+		xfer_size = (byte_cnt > SFP_EEPROM_PAGE_SIZE) ?
+			SFP_EEPROM_PAGE_SIZE : byte_cnt;
+		rc = read_func(phy, params, dev_addr, addr, xfer_size,
+			       user_data, 0);
+		byte_cnt -= xfer_size;
+		user_data += xfer_size;
+		addr += xfer_size;
 	}
 	return rc;
 }
@@ -8004,6 +8045,7 @@ static int bnx2x_get_edc_mode(struct bnx2x_phy *phy,
 	/* First check for copper cable */
 	if (bnx2x_read_sfp_module_eeprom(phy,
 					 params,
+					 I2C_DEV_ADDR_A0,
 					 SFP_EEPROM_CON_TYPE_ADDR,
 					 2,
 					 (u8 *)val) != 0) {
@@ -8021,6 +8063,7 @@ static int bnx2x_get_edc_mode(struct bnx2x_phy *phy,
 		 */
 		if (bnx2x_read_sfp_module_eeprom(phy,
 					       params,
+					       I2C_DEV_ADDR_A0,
 					       SFP_EEPROM_FC_TX_TECH_ADDR,
 					       1,
 					       &copper_module_type) != 0) {
@@ -8049,20 +8092,24 @@ static int bnx2x_get_edc_mode(struct bnx2x_phy *phy,
 		break;
 	}
 	case SFP_EEPROM_CON_TYPE_VAL_LC:
+	case SFP_EEPROM_CON_TYPE_VAL_RJ45:
 		check_limiting_mode = 1;
 		if ((val[1] & (SFP_EEPROM_COMP_CODE_SR_MASK |
 			       SFP_EEPROM_COMP_CODE_LR_MASK |
 			       SFP_EEPROM_COMP_CODE_LRM_MASK)) == 0) {
-			DP(NETIF_MSG_LINK, "1G Optic module detected\n");
+			DP(NETIF_MSG_LINK, "1G SFP module detected\n");
 			gport = params->port;
 			phy->media_type = ETH_PHY_SFP_1G_FIBER;
-			phy->req_line_speed = SPEED_1000;
-			if (!CHIP_IS_E1x(bp))
-				gport = BP_PATH(bp) + (params->port << 1);
-			netdev_err(bp->dev, "Warning: Link speed was forced to 1000Mbps."
-			      " Current SFP module in port %d is not"
-			      " compliant with 10G Ethernet\n",
-			 gport);
+			if (phy->req_line_speed != SPEED_1000) {
+				phy->req_line_speed = SPEED_1000;
+				if (!CHIP_IS_E1x(bp)) {
+					gport = BP_PATH(bp) +
+					(params->port << 1);
+				}
+				netdev_err(bp->dev,
+					   "Warning: Link speed was forced to 1000Mbps. Current SFP module in port %d is not compliant with 10G Ethernet\n",
+					   gport);
+			}
 		} else {
 			int idx, cfg_idx = 0;
 			DP(NETIF_MSG_LINK, "10G Optic module detected\n");
@@ -8101,6 +8148,7 @@ static int bnx2x_get_edc_mode(struct bnx2x_phy *phy,
 		u8 options[SFP_EEPROM_OPTIONS_SIZE];
 		if (bnx2x_read_sfp_module_eeprom(phy,
 						 params,
+						 I2C_DEV_ADDR_A0,
 						 SFP_EEPROM_OPTIONS_ADDR,
 						 SFP_EEPROM_OPTIONS_SIZE,
 						 options) != 0) {
@@ -8167,6 +8215,7 @@ static int bnx2x_verify_sfp_module(struct bnx2x_phy *phy,
 	/* Format the warning message */
 	if (bnx2x_read_sfp_module_eeprom(phy,
 					 params,
+					 I2C_DEV_ADDR_A0,
 					 SFP_EEPROM_VENDOR_NAME_ADDR,
 					 SFP_EEPROM_VENDOR_NAME_SIZE,
 					 (u8 *)vendor_name))
@@ -8175,6 +8224,7 @@ static int bnx2x_verify_sfp_module(struct bnx2x_phy *phy,
 		vendor_name[SFP_EEPROM_VENDOR_NAME_SIZE] = '\0';
 	if (bnx2x_read_sfp_module_eeprom(phy,
 					 params,
+					 I2C_DEV_ADDR_A0,
 					 SFP_EEPROM_PART_NO_ADDR,
 					 SFP_EEPROM_PART_NO_SIZE,
 					 (u8 *)vendor_pn))
@@ -8205,12 +8255,13 @@ static int bnx2x_wait_for_sfp_module_initialized(struct bnx2x_phy *phy,
 
 	for (timeout = 0; timeout < 60; timeout++) {
 		if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT)
-			rc = bnx2x_warpcore_read_sfp_module_eeprom(phy,
-								   params, 1,
-								   1, &val, 1);
+			rc = bnx2x_warpcore_read_sfp_module_eeprom(
+				phy, params, I2C_DEV_ADDR_A0, 1, 1, &val,
+				1);
 		else
-			rc = bnx2x_read_sfp_module_eeprom(phy, params, 1, 1,
-							  &val);
+			rc = bnx2x_read_sfp_module_eeprom(phy, params,
+							  I2C_DEV_ADDR_A0,
+							  1, 1, &val);
 		if (rc == 0) {
 			DP(NETIF_MSG_LINK,
 			   "SFP+ module initialization took %d ms\n",
@@ -8219,7 +8270,8 @@ static int bnx2x_wait_for_sfp_module_initialized(struct bnx2x_phy *phy,
 		}
 		usleep_range(5000, 10000);
 	}
-	rc = bnx2x_read_sfp_module_eeprom(phy, params, 1, 1, &val);
+	rc = bnx2x_read_sfp_module_eeprom(phy, params, I2C_DEV_ADDR_A0,
+					  1, 1, &val);
 	return rc;
 }
 
@@ -8376,15 +8428,6 @@ static void bnx2x_8727_specific_func(struct bnx2x_phy *phy,
 		bnx2x_cl45_write(bp, phy,
 				 MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_PCS_OPT_CTRL,
 				 val);
-
-		/* Set 2-wire transfer rate of SFP+ module EEPROM
-		 * to 100Khz since some DACs(direct attached cables) do
-		 * not work at 400Khz.
-		 */
-		bnx2x_cl45_write(bp, phy,
-				 MDIO_PMA_DEVAD,
-				 MDIO_PMA_REG_8727_TWO_WIRE_SLAVE_ADDR,
-				 0xa001);
 		break;
 	default:
 		DP(NETIF_MSG_LINK, "Function 0x%x not supported by 8727\n",
@@ -9528,8 +9571,7 @@ static void bnx2x_save_848xx_spirom_version(struct bnx2x_phy *phy,
 	} else {
 		/* For 32-bit registers in 848xx, access via MDIO2ARM i/f. */
 		/* (1) set reg 0xc200_0014(SPI_BRIDGE_CTRL_2) to 0x03000000 */
-		for (i = 0; i < ARRAY_SIZE(reg_set);
-		      i++)
+		for (i = 0; i < ARRAY_SIZE(reg_set); i++)
 			bnx2x_cl45_write(bp, phy, reg_set[i].devad,
 					 reg_set[i].reg, reg_set[i].val);
 
@@ -10281,7 +10323,8 @@ static u8 bnx2x_848xx_read_status(struct bnx2x_phy *phy,
 				LINK_STATUS_LINK_PARTNER_10GXFD_CAPABLE;
 
 		/* Determine if EEE was negotiated */
-		if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833)
+		if ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) ||
+		    (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834))
 			bnx2x_eee_an_resolve(phy, params, vars);
 	}
 
@@ -12242,7 +12285,7 @@ static void bnx2x_init_bmac_loopback(struct link_params *params,
 
 		bnx2x_xgxs_deassert(params);
 
-		/* set bmac loopback */
+		/* Set bmac loopback */
 		bnx2x_bmac_enable(params, vars, 1, 1);
 
 		REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
@@ -12261,7 +12304,7 @@ static void bnx2x_init_emac_loopback(struct link_params *params,
 		vars->phy_flags = PHY_XGXS_FLAG;
 
 		bnx2x_xgxs_deassert(params);
-		/* set bmac loopback */
+		/* Set bmac loopback */
 		bnx2x_emac_enable(params, vars, 1);
 		bnx2x_emac_program(params, vars);
 		REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
@@ -12521,6 +12564,7 @@ int bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
 		   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]);
+	DP(NETIF_MSG_LINK, "req_adv_flow_ctrl 0x%x\n", params->req_fc_auto_adv);
 	vars->link_status = 0;
 	vars->phy_link_up = 0;
 	vars->link_up = 0;
@@ -13446,8 +13490,8 @@ static void bnx2x_check_kr2_wa(struct link_params *params,
 	}
 
 	/* Once KR2 was disabled, wait 5 seconds before checking KR2 recovery
-	 * since some switches tend to reinit the AN process and clear the
-	 * advertised BP/NP after ~2 seconds causing the KR2 to be disabled
+	 * Since some switches tend to reinit the AN process and clear the
+	 * the advertised BP/NP after ~2 seconds causing the KR2 to be disabled
 	 * and recovered many times
 	 */
 	if (vars->check_kr2_recovery_cnt > 0) {
@@ -13465,8 +13509,10 @@ static void bnx2x_check_kr2_wa(struct link_params *params,
 
 	/* CL73 has not begun yet */
 	if (base_page == 0) {
-		if (!(vars->link_attr_sync & LINK_ATTR_SYNC_KR2_ENABLE))
+		if (!(vars->link_attr_sync & LINK_ATTR_SYNC_KR2_ENABLE)) {
 			bnx2x_kr2_recovery(params, vars, phy);
+			DP(NETIF_MSG_LINK, "No BP\n");
+		}
 		return;
 	}
 
@@ -13482,7 +13528,7 @@ static void bnx2x_check_kr2_wa(struct link_params *params,
 	if (!(vars->link_attr_sync & LINK_ATTR_SYNC_KR2_ENABLE)) {
 		if (!not_kr2_device) {
 			DP(NETIF_MSG_LINK, "BP=0x%x, NP=0x%x\n", base_page,
-				       next_page);
+			   next_page);
 			bnx2x_kr2_recovery(params, vars, phy);
 		}
 		return;
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h
index 56c2aae..4df4523 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h
@@ -41,6 +41,9 @@
 #define SPEED_AUTO_NEG		0
 #define SPEED_20000		20000
 
+#define I2C_DEV_ADDR_A0			0xa0
+#define I2C_DEV_ADDR_A2			0xa2
+
 #define SFP_EEPROM_PAGE_SIZE			16
 #define SFP_EEPROM_VENDOR_NAME_ADDR		0x14
 #define SFP_EEPROM_VENDOR_NAME_SIZE		16
@@ -54,6 +57,15 @@
 #define SFP_EEPROM_SERIAL_SIZE			16
 #define SFP_EEPROM_DATE_ADDR			0x54 /* ASCII YYMMDD */
 #define SFP_EEPROM_DATE_SIZE			6
+#define SFP_EEPROM_DIAG_TYPE_ADDR		0x5c
+#define SFP_EEPROM_DIAG_TYPE_SIZE		1
+#define SFP_EEPROM_DIAG_ADDR_CHANGE_REQ		(1<<2)
+#define SFP_EEPROM_SFF_8472_COMP_ADDR		0x5e
+#define SFP_EEPROM_SFF_8472_COMP_SIZE		1
+
+#define SFP_EEPROM_A2_CHECKSUM_RANGE		0x5e
+#define SFP_EEPROM_A2_CC_DMI_ADDR		0x5f
+
 #define PWR_FLT_ERR_MSG_LEN			250
 
 #define XGXS_EXT_PHY_TYPE(ext_phy_config) \
@@ -420,8 +432,8 @@ void bnx2x_sfx7101_sp_sw_reset(struct bnx2x *bp, struct bnx2x_phy *phy);
 
 /* Read "byte_cnt" bytes from address "addr" from the SFP+ EEPROM */
 int bnx2x_read_sfp_module_eeprom(struct bnx2x_phy *phy,
-				 struct link_params *params, u16 addr,
-				 u8 byte_cnt, u8 *o_buf);
+				 struct link_params *params, u8 dev_addr,
+				 u16 addr, u16 byte_cnt, u8 *o_buf);
 
 void bnx2x_hw_reset_phy(struct link_params *params);
 
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index e81a747..fdfe33b 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -75,8 +75,6 @@
 #define FW_FILE_NAME_E1H	"bnx2x/bnx2x-e1h-" FW_FILE_VERSION ".fw"
 #define FW_FILE_NAME_E2		"bnx2x/bnx2x-e2-" FW_FILE_VERSION ".fw"
 
-#define MAC_LEADING_ZERO_CNT (ALIGN(ETH_ALEN, sizeof(u32)) - ETH_ALEN)
-
 /* Time in jiffies before concluding the transmitter is hung */
 #define TX_TIMEOUT		(5*HZ)
 
@@ -2955,14 +2953,16 @@ static unsigned long bnx2x_get_common_flags(struct bnx2x *bp,
 	__set_bit(BNX2X_Q_FLG_ACTIVE, &flags);
 
 	/* tx only connections collect statistics (on the same index as the
-	 *  parent connection). The statistics are zeroed when the parent
-	 *  connection is initialized.
+	 * parent connection). The statistics are zeroed when the parent
+	 * connection is initialized.
 	 */
 
 	__set_bit(BNX2X_Q_FLG_STATS, &flags);
 	if (zero_stats)
 		__set_bit(BNX2X_Q_FLG_ZERO_STATS, &flags);
 
+	__set_bit(BNX2X_Q_FLG_PCSUM_ON_PKT, &flags);
+	__set_bit(BNX2X_Q_FLG_TUN_INC_INNER_IP_ID, &flags);
 
 #ifdef BNX2X_STOP_ON_ERROR
 	__set_bit(BNX2X_Q_FLG_TX_SEC, &flags);
@@ -3227,16 +3227,29 @@ static void bnx2x_drv_info_ether_stat(struct bnx2x *bp)
 {
 	struct eth_stats_info *ether_stat =
 		&bp->slowpath->drv_info_to_mcp.ether_stat;
+	struct bnx2x_vlan_mac_obj *mac_obj =
+		&bp->sp_objs->mac_obj;
+	int i;
 
 	strlcpy(ether_stat->version, DRV_MODULE_VERSION,
 		ETH_STAT_INFO_VERSION_LEN);
 
-	bp->sp_objs[0].mac_obj.get_n_elements(bp, &bp->sp_objs[0].mac_obj,
-					DRV_INFO_ETH_STAT_NUM_MACS_REQUIRED,
-					ether_stat->mac_local);
-
+	/* get DRV_INFO_ETH_STAT_NUM_MACS_REQUIRED macs, placing them in the
+	 * mac_local field in ether_stat struct. The base address is offset by 2
+	 * bytes to account for the field being 8 bytes but a mac address is
+	 * only 6 bytes. Likewise, the stride for the get_n_elements function is
+	 * 2 bytes to compensate from the 6 bytes of a mac to the 8 bytes
+	 * allocated by the ether_stat struct, so the macs will land in their
+	 * proper positions.
+	 */
+	for (i = 0; i < DRV_INFO_ETH_STAT_NUM_MACS_REQUIRED; i++)
+		memset(ether_stat->mac_local + i, 0,
+		       sizeof(ether_stat->mac_local[0]));
+	mac_obj->get_n_elements(bp, &bp->sp_objs[0].mac_obj,
+				DRV_INFO_ETH_STAT_NUM_MACS_REQUIRED,
+				ether_stat->mac_local + MAC_PAD, MAC_PAD,
+				ETH_ALEN);
 	ether_stat->mtu_size = bp->dev->mtu;
-
 	if (bp->dev->features & NETIF_F_RXCSUM)
 		ether_stat->feature_flags |= FEATURE_ETH_CHKSUM_OFFLOAD_MASK;
 	if (bp->dev->features & NETIF_F_TSO)
@@ -3258,8 +3271,7 @@ static void bnx2x_drv_info_fcoe_stat(struct bnx2x *bp)
 	if (!CNIC_LOADED(bp))
 		return;
 
-	memcpy(fcoe_stat->mac_local + MAC_LEADING_ZERO_CNT,
-	       bp->fip_mac, ETH_ALEN);
+	memcpy(fcoe_stat->mac_local + MAC_PAD, bp->fip_mac, ETH_ALEN);
 
 	fcoe_stat->qos_priority =
 		app->traffic_type_priority[LLFC_TRAFFIC_TYPE_FCOE];
@@ -3361,8 +3373,8 @@ static void bnx2x_drv_info_iscsi_stat(struct bnx2x *bp)
 	if (!CNIC_LOADED(bp))
 		return;
 
-	memcpy(iscsi_stat->mac_local + MAC_LEADING_ZERO_CNT,
-	       bp->cnic_eth_dev.iscsi_mac, ETH_ALEN);
+	memcpy(iscsi_stat->mac_local + MAC_PAD, bp->cnic_eth_dev.iscsi_mac,
+	       ETH_ALEN);
 
 	iscsi_stat->qos_priority =
 		app->traffic_type_priority[LLFC_TRAFFIC_TYPE_ISCSI];
@@ -6029,9 +6041,10 @@ void bnx2x_nic_init(struct bnx2x *bp, u32 load_code)
 	rmb();
 	bnx2x_init_rx_rings(bp);
 	bnx2x_init_tx_rings(bp);
-
-	if (IS_VF(bp))
+	if (IS_VF(bp)) {
+		bnx2x_memset_stats(bp);
 		return;
+	}
 
 	/* Initialize MOD_ABS interrupts */
 	bnx2x_init_mod_abs_int(bp, &bp->link_vars, bp->common.chip_id,
@@ -9525,6 +9538,10 @@ sp_rtnl_not_reset:
 		bnx2x_vfpf_storm_rx_mode(bp);
 	}
 
+	if (test_and_clear_bit(BNX2X_SP_RTNL_HYPERVISOR_VLAN,
+			       &bp->sp_rtnl_state))
+		bnx2x_pf_set_vfs_vlan(bp);
+
 	/* work which needs rtnl lock not-taken (as it takes the lock itself and
 	 * can be called from other contexts as well)
 	 */
@@ -9532,8 +9549,10 @@ sp_rtnl_not_reset:
 
 	/* enable SR-IOV if applicable */
 	if (IS_SRIOV(bp) && test_and_clear_bit(BNX2X_SP_RTNL_ENABLE_SRIOV,
-					       &bp->sp_rtnl_state))
+					       &bp->sp_rtnl_state)) {
+		bnx2x_disable_sriov(bp);
 		bnx2x_enable_sriov(bp);
+	}
 }
 
 static void bnx2x_period_task(struct work_struct *work)
@@ -9701,6 +9720,31 @@ static struct bnx2x_prev_path_list *
 	return NULL;
 }
 
+static int bnx2x_prev_path_mark_eeh(struct bnx2x *bp)
+{
+	struct bnx2x_prev_path_list *tmp_list;
+	int rc;
+
+	rc = down_interruptible(&bnx2x_prev_sem);
+	if (rc) {
+		BNX2X_ERR("Received %d when tried to take lock\n", rc);
+		return rc;
+	}
+
+	tmp_list = bnx2x_prev_path_get_entry(bp);
+	if (tmp_list) {
+		tmp_list->aer = 1;
+		rc = 0;
+	} else {
+		BNX2X_ERR("path %d: Entry does not exist for eeh; Flow occurs before initial insmod is over ?\n",
+			  BP_PATH(bp));
+	}
+
+	up(&bnx2x_prev_sem);
+
+	return rc;
+}
+
 static bool bnx2x_prev_is_path_marked(struct bnx2x *bp)
 {
 	struct bnx2x_prev_path_list *tmp_list;
@@ -9709,14 +9753,15 @@ static bool bnx2x_prev_is_path_marked(struct bnx2x *bp)
 	if (down_trylock(&bnx2x_prev_sem))
 		return false;
 
-	list_for_each_entry(tmp_list, &bnx2x_prev_list, list) {
-		if (PCI_SLOT(bp->pdev->devfn) == tmp_list->slot &&
-		    bp->pdev->bus->number == tmp_list->bus &&
-		    BP_PATH(bp) == tmp_list->path) {
+	tmp_list = bnx2x_prev_path_get_entry(bp);
+	if (tmp_list) {
+		if (tmp_list->aer) {
+			DP(NETIF_MSG_HW, "Path %d was marked by AER\n",
+			   BP_PATH(bp));
+		} else {
 			rc = true;
 			BNX2X_DEV_INFO("Path %d was already cleaned from previous drivers\n",
 				       BP_PATH(bp));
-			break;
 		}
 	}
 
@@ -9730,6 +9775,28 @@ static int bnx2x_prev_mark_path(struct bnx2x *bp, bool after_undi)
 	struct bnx2x_prev_path_list *tmp_list;
 	int rc;
 
+	rc = down_interruptible(&bnx2x_prev_sem);
+	if (rc) {
+		BNX2X_ERR("Received %d when tried to take lock\n", rc);
+		return rc;
+	}
+
+	/* Check whether the entry for this path already exists */
+	tmp_list = bnx2x_prev_path_get_entry(bp);
+	if (tmp_list) {
+		if (!tmp_list->aer) {
+			BNX2X_ERR("Re-Marking the path.\n");
+		} else {
+			DP(NETIF_MSG_HW, "Removing AER indication from path %d\n",
+			   BP_PATH(bp));
+			tmp_list->aer = 0;
+		}
+		up(&bnx2x_prev_sem);
+		return 0;
+	}
+	up(&bnx2x_prev_sem);
+
+	/* Create an entry for this path and add it */
 	tmp_list = kmalloc(sizeof(struct bnx2x_prev_path_list), GFP_KERNEL);
 	if (!tmp_list) {
 		BNX2X_ERR("Failed to allocate 'bnx2x_prev_path_list'\n");
@@ -9739,6 +9806,7 @@ static int bnx2x_prev_mark_path(struct bnx2x *bp, bool after_undi)
 	tmp_list->bus = bp->pdev->bus->number;
 	tmp_list->slot = PCI_SLOT(bp->pdev->devfn);
 	tmp_list->path = BP_PATH(bp);
+	tmp_list->aer = 0;
 	tmp_list->undi = after_undi ? (1 << BP_PORT(bp)) : 0;
 
 	rc = down_interruptible(&bnx2x_prev_sem);
@@ -9746,8 +9814,8 @@ static int bnx2x_prev_mark_path(struct bnx2x *bp, bool after_undi)
 		BNX2X_ERR("Received %d when tried to take lock\n", rc);
 		kfree(tmp_list);
 	} else {
-		BNX2X_DEV_INFO("Marked path [%d] - finished previous unload\n",
-				BP_PATH(bp));
+		DP(NETIF_MSG_HW, "Marked path [%d] - finished previous unload\n",
+		   BP_PATH(bp));
 		list_add(&tmp_list->list, &bnx2x_prev_list);
 		up(&bnx2x_prev_sem);
 	}
@@ -9986,6 +10054,7 @@ static int bnx2x_prev_unload(struct bnx2x *bp)
 	}
 
 	do {
+		int aer = 0;
 		/* Lock MCP using an unload request */
 		fw = bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS, 0);
 		if (!fw) {
@@ -9994,7 +10063,18 @@ static int bnx2x_prev_unload(struct bnx2x *bp)
 			break;
 		}
 
-		if (fw == FW_MSG_CODE_DRV_UNLOAD_COMMON) {
+		rc = down_interruptible(&bnx2x_prev_sem);
+		if (rc) {
+			BNX2X_ERR("Cannot check for AER; Received %d when tried to take lock\n",
+				  rc);
+		} else {
+			/* If Path is marked by EEH, ignore unload status */
+			aer = !!(bnx2x_prev_path_get_entry(bp) &&
+				 bnx2x_prev_path_get_entry(bp)->aer);
+			up(&bnx2x_prev_sem);
+		}
+
+		if (fw == FW_MSG_CODE_DRV_UNLOAD_COMMON || aer) {
 			rc = bnx2x_prev_unload_common(bp);
 			break;
 		}
@@ -10034,8 +10114,12 @@ static void bnx2x_get_common_hwinfo(struct bnx2x *bp)
 	id = ((val & 0xffff) << 16);
 	val = REG_RD(bp, MISC_REG_CHIP_REV);
 	id |= ((val & 0xf) << 12);
-	val = REG_RD(bp, MISC_REG_CHIP_METAL);
-	id |= ((val & 0xff) << 4);
+
+	/* Metal is read from PCI regs, but we can't access >=0x400 from
+	 * the configuration space (so we need to reg_rd)
+	 */
+	val = REG_RD(bp, PCICFG_OFFSET + PCI_ID_VAL3);
+	id |= (((val >> 24) & 0xf) << 4);
 	val = REG_RD(bp, MISC_REG_BOND_ID);
 	id |= (val & 0xf);
 	bp->common.chip_id = id;
@@ -10812,14 +10896,12 @@ static void bnx2x_get_cnic_mac_hwinfo(struct bnx2x *bp)
 			}
 		}
 
-		if (IS_MF_STORAGE_SD(bp))
-			/* Zero primary MAC configuration */
-			memset(bp->dev->dev_addr, 0, ETH_ALEN);
-
-		if (IS_MF_FCOE_AFEX(bp) || IS_MF_FCOE_SD(bp))
-			/* use FIP MAC as primary MAC */
+		/* If this is a storage-only interface, use SAN mac as
+		 * primary MAC. Notice that for SD this is already the case,
+		 * as the SAN mac was copied from the primary MAC.
+		 */
+		if (IS_MF_FCOE_AFEX(bp))
 			memcpy(bp->dev->dev_addr, fip_mac, ETH_ALEN);
-
 	} else {
 		val2 = SHMEM_RD(bp, dev_info.port_hw_config[port].
 				iscsi_mac_upper);
@@ -11056,6 +11138,9 @@ static int bnx2x_get_hwinfo(struct bnx2x *bp)
 				} else
 					BNX2X_DEV_INFO("illegal OV for SD\n");
 				break;
+			case SHARED_FEAT_CFG_FORCE_SF_MODE_FORCED_SF:
+				bp->mf_config[vn] = 0;
+				break;
 			default:
 				/* Unknown configuration: reset mf_config */
 				bp->mf_config[vn] = 0;
@@ -11402,26 +11487,6 @@ static int bnx2x_init_bp(struct bnx2x *bp)
  * net_device service functions
  */
 
-static int bnx2x_open_epilog(struct bnx2x *bp)
-{
-	/* Enable sriov via delayed work. This must be done via delayed work
-	 * because it causes the probe of the vf devices to be run, which invoke
-	 * register_netdevice which must have rtnl lock taken. As we are holding
-	 * the lock right now, that could only work if the probe would not take
-	 * the lock. However, as the probe of the vf may be called from other
-	 * contexts as well (such as passthrough to vm failes) it can't assume
-	 * the lock is being held for it. Using delayed work here allows the
-	 * probe code to simply take the lock (i.e. wait for it to be released
-	 * if it is being held).
-	 */
-	smp_mb__before_clear_bit();
-	set_bit(BNX2X_SP_RTNL_ENABLE_SRIOV, &bp->sp_rtnl_state);
-	smp_mb__after_clear_bit();
-	schedule_delayed_work(&bp->sp_rtnl_task, 0);
-
-	return 0;
-}
-
 /* called with rtnl_lock */
 static int bnx2x_open(struct net_device *dev)
 {
@@ -11791,6 +11856,8 @@ static const struct net_device_ops bnx2x_netdev_ops = {
 	.ndo_setup_tc		= bnx2x_setup_tc,
 #ifdef CONFIG_BNX2X_SRIOV
 	.ndo_set_vf_mac		= bnx2x_set_vf_mac,
+	.ndo_set_vf_vlan        = bnx2x_set_vf_vlan,
+	.ndo_get_vf_config	= bnx2x_get_vf_config,
 #endif
 #ifdef NETDEV_FCOE_WWNN
 	.ndo_fcoe_get_wwn	= bnx2x_fcoe_get_wwn,
@@ -11953,7 +12020,7 @@ static int bnx2x_init_dev(struct bnx2x *bp, struct pci_dev *pdev,
 	dev->watchdog_timeo = TX_TIMEOUT;
 
 	dev->netdev_ops = &bnx2x_netdev_ops;
-	bnx2x_set_ethtool_ops(dev);
+	bnx2x_set_ethtool_ops(bp, dev);
 
 	dev->priv_flags |= IFF_UNICAST_FLT;
 
@@ -11961,6 +12028,13 @@ static int bnx2x_init_dev(struct bnx2x *bp, struct pci_dev *pdev,
 		NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6 |
 		NETIF_F_RXCSUM | NETIF_F_LRO | NETIF_F_GRO |
 		NETIF_F_RXHASH | NETIF_F_HW_VLAN_TX;
+	if (!CHIP_IS_E1x(bp)) {
+		dev->hw_features |= NETIF_F_GSO_GRE;
+		dev->hw_enc_features =
+			NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_SG |
+			NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6 |
+			NETIF_F_GSO_GRE;
+	}
 
 	dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
 		NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6 | NETIF_F_HIGHDMA;
@@ -12447,7 +12521,7 @@ static int bnx2x_init_one(struct pci_dev *pdev,
 	 * l2 connections.
 	 */
 	if (IS_VF(bp)) {
-		bnx2x_vf_map_doorbells(bp);
+		bp->doorbells = bnx2x_vf_doorbells(bp);
 		rc = bnx2x_vf_pci_alloc(bp);
 		if (rc)
 			goto init_one_exit;
@@ -12475,13 +12549,8 @@ static int bnx2x_init_one(struct pci_dev *pdev,
 			goto init_one_exit;
 	}
 
-	/* Enable SRIOV if capability found in configuration space.
-	 * Once the generic SR-IOV framework makes it in from the
-	 * pci tree this will be revised, to allow dynamic control
-	 * over the number of VFs. Right now, change the num of vfs
-	 * param below to enable SR-IOV.
-	 */
-	rc = bnx2x_iov_init_one(bp, int_mode, 0/*num vfs*/);
+	/* Enable SRIOV if capability found in configuration space */
+	rc = bnx2x_iov_init_one(bp, int_mode, BNX2X_MAX_NUM_OF_VFS);
 	if (rc)
 		goto init_one_exit;
 
@@ -12493,16 +12562,6 @@ static int bnx2x_init_one(struct pci_dev *pdev,
 	if (CHIP_IS_E1x(bp))
 		bp->flags |= NO_FCOE_FLAG;
 
-	/* disable FCOE for 57840 device, until FW supports it */
-	switch (ent->driver_data) {
-	case BCM57840_O:
-	case BCM57840_4_10:
-	case BCM57840_2_20:
-	case BCM57840_MFO:
-	case BCM57840_MF:
-		bp->flags |= NO_FCOE_FLAG;
-	}
-
 	/* Set bp->num_queues for MSI-X mode*/
 	bnx2x_set_num_queues(bp);
 
@@ -12636,9 +12695,7 @@ static void bnx2x_remove_one(struct pci_dev *pdev)
 
 static int bnx2x_eeh_nic_unload(struct bnx2x *bp)
 {
-	int i;
-
-	bp->state = BNX2X_STATE_ERROR;
+	bp->state = BNX2X_STATE_CLOSING_WAIT4_HALT;
 
 	bp->rx_mode = BNX2X_RX_MODE_NONE;
 
@@ -12647,29 +12704,21 @@ static int bnx2x_eeh_nic_unload(struct bnx2x *bp)
 
 	/* Stop Tx */
 	bnx2x_tx_disable(bp);
-
-	bnx2x_netif_stop(bp, 0);
 	/* Delete all NAPI objects */
 	bnx2x_del_all_napi(bp);
 	if (CNIC_LOADED(bp))
 		bnx2x_del_all_napi_cnic(bp);
+	netdev_reset_tc(bp->dev);
 
 	del_timer_sync(&bp->timer);
+	cancel_delayed_work(&bp->sp_task);
+	cancel_delayed_work(&bp->period_task);
 
-	bnx2x_stats_handle(bp, STATS_EVENT_STOP);
-
-	/* Release IRQs */
-	bnx2x_free_irq(bp);
-
-	/* Free SKBs, SGEs, TPA pool and driver internals */
-	bnx2x_free_skbs(bp);
-
-	for_each_rx_queue(bp, i)
-		bnx2x_free_rx_sge_range(bp, bp->fp + i, NUM_RX_SGE);
-
-	bnx2x_free_mem(bp);
+	spin_lock_bh(&bp->stats_lock);
+	bp->stats_state = STATS_STATE_DISABLED;
+	spin_unlock_bh(&bp->stats_lock);
 
-	bp->state = BNX2X_STATE_CLOSED;
+	bnx2x_save_statistics(bp);
 
 	netif_carrier_off(bp->dev);
 
@@ -12705,6 +12754,8 @@ static pci_ers_result_t bnx2x_io_error_detected(struct pci_dev *pdev,
 
 	rtnl_lock();
 
+	BNX2X_ERR("IO error detected\n");
+
 	netif_device_detach(dev);
 
 	if (state == pci_channel_io_perm_failure) {
@@ -12715,6 +12766,8 @@ static pci_ers_result_t bnx2x_io_error_detected(struct pci_dev *pdev,
 	if (netif_running(dev))
 		bnx2x_eeh_nic_unload(bp);
 
+	bnx2x_prev_path_mark_eeh(bp);
+
 	pci_disable_device(pdev);
 
 	rtnl_unlock();
@@ -12733,9 +12786,10 @@ static pci_ers_result_t bnx2x_io_slot_reset(struct pci_dev *pdev)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
 	struct bnx2x *bp = netdev_priv(dev);
+	int i;
 
 	rtnl_lock();
-
+	BNX2X_ERR("IO slot reset initializing...\n");
 	if (pci_enable_device(pdev)) {
 		dev_err(&pdev->dev,
 			"Cannot re-enable PCI device after reset\n");
@@ -12749,6 +12803,42 @@ static pci_ers_result_t bnx2x_io_slot_reset(struct pci_dev *pdev)
 	if (netif_running(dev))
 		bnx2x_set_power_state(bp, PCI_D0);
 
+	if (netif_running(dev)) {
+		BNX2X_ERR("IO slot reset --> driver unload\n");
+		if (IS_PF(bp) && SHMEM2_HAS(bp, drv_capabilities_flag)) {
+			u32 v;
+
+			v = SHMEM2_RD(bp,
+				      drv_capabilities_flag[BP_FW_MB_IDX(bp)]);
+			SHMEM2_WR(bp, drv_capabilities_flag[BP_FW_MB_IDX(bp)],
+				  v & ~DRV_FLAGS_CAPABILITIES_LOADED_L2);
+		}
+		bnx2x_drain_tx_queues(bp);
+		bnx2x_send_unload_req(bp, UNLOAD_RECOVERY);
+		bnx2x_netif_stop(bp, 1);
+		bnx2x_free_irq(bp);
+
+		/* Report UNLOAD_DONE to MCP */
+		bnx2x_send_unload_done(bp, true);
+
+		bp->sp_state = 0;
+		bp->port.pmf = 0;
+
+		bnx2x_prev_unload(bp);
+
+		/* We should have resetted the engine, so It's fair to
+		 * assume the FW will no longer write to the bnx2x driver.
+		 */
+		bnx2x_squeeze_objects(bp);
+		bnx2x_free_skbs(bp);
+		for_each_rx_queue(bp, i)
+			bnx2x_free_rx_sge_range(bp, bp->fp + i, NUM_RX_SGE);
+		bnx2x_free_fp_mem(bp);
+		bnx2x_free_mem(bp);
+
+		bp->state = BNX2X_STATE_CLOSED;
+	}
+
 	rtnl_unlock();
 
 	return PCI_ERS_RESULT_RECOVERED;
@@ -12775,6 +12865,9 @@ static void bnx2x_io_resume(struct pci_dev *pdev)
 
 	bnx2x_eeh_recover(bp);
 
+	bp->fw_seq = SHMEM_RD(bp, func_mb[BP_FW_MB_IDX(bp)].drv_mb_header) &
+							DRV_MSG_SEQ_NUMBER_MASK;
+
 	if (netif_running(dev))
 		bnx2x_nic_load(bp, LOAD_NORMAL);
 
@@ -12797,6 +12890,9 @@ static struct pci_driver bnx2x_pci_driver = {
 	.suspend     = bnx2x_suspend,
 	.resume      = bnx2x_resume,
 	.err_handler = &bnx2x_err_handler,
+#ifdef CONFIG_BNX2X_SRIOV
+	.sriov_configure = bnx2x_sriov_configure,
+#endif
 };
 
 static int __init bnx2x_init(void)
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h
index 791eb2d..d22bc40 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h
@@ -1491,10 +1491,6 @@
 /* [R 4] This field indicates the type of the device. '0' - 2 Ports; '1' - 1
    Port. */
 #define MISC_REG_BOND_ID					 0xa400
-/* [R 8] These bits indicate the metal revision of the chip. This value
-   starts at 0x00 for each all-layer tape-out and increments by one for each
-   tape-out. */
-#define MISC_REG_CHIP_METAL					 0xa404
 /* [R 16] These bits indicate the part number for the chip. */
 #define MISC_REG_CHIP_NUM					 0xa408
 /* [R 4] These bits indicate the base revision of the chip. This value
@@ -6331,6 +6327,8 @@
 #define PCI_PM_DATA_B					0x414
 #define PCI_ID_VAL1					0x434
 #define PCI_ID_VAL2					0x438
+#define PCI_ID_VAL3					0x43c
+
 #define GRC_CONFIG_REG_PF_INIT_VF		0x624
 #define GRC_CR_PF_INIT_VF_PF_FIRST_VF_NUM_MASK	0xf
 /* First VF_NUM for PF is encoded in this register.
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
index 7306416..32a9609 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
@@ -30,8 +30,6 @@
 
 #define BNX2X_MAX_EMUL_MULTI		16
 
-#define MAC_LEADING_ZERO_CNT (ALIGN(ETH_ALEN, sizeof(u32)) - ETH_ALEN)
-
 /**** Exe Queue interfaces ****/
 
 /**
@@ -444,30 +442,21 @@ static bool bnx2x_put_credit_vlan_mac(struct bnx2x_vlan_mac_obj *o)
 }
 
 static int bnx2x_get_n_elements(struct bnx2x *bp, struct bnx2x_vlan_mac_obj *o,
-				int n, u8 *buf)
+				int n, u8 *base, u8 stride, u8 size)
 {
 	struct bnx2x_vlan_mac_registry_elem *pos;
-	u8 *next = buf;
+	u8 *next = base;
 	int counter = 0;
 
 	/* traverse list */
 	list_for_each_entry(pos, &o->head, link) {
 		if (counter < n) {
-			/* place leading zeroes in buffer */
-			memset(next, 0, MAC_LEADING_ZERO_CNT);
-
-			/* place mac after leading zeroes*/
-			memcpy(next + MAC_LEADING_ZERO_CNT, pos->u.mac.mac,
-			       ETH_ALEN);
-
-			/* calculate address of next element and
-			 * advance counter
-			 */
+			memcpy(next, &pos->u, size);
 			counter++;
-			next = buf + counter * ALIGN(ETH_ALEN, sizeof(u32));
+			DP(BNX2X_MSG_SP, "copied element number %d to address %p element was:\n",
+			   counter, next);
+			next += stride + size;
 
-			DP(BNX2X_MSG_SP, "copied element number %d to address %p element was %pM\n",
-			   counter, next, pos->u.mac.mac);
 		}
 	}
 	return counter * ETH_ALEN;
@@ -487,7 +476,8 @@ static int bnx2x_check_mac_add(struct bnx2x *bp,
 
 	/* 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))
+		if (!memcmp(data->mac.mac, pos->u.mac.mac, ETH_ALEN) &&
+		    (data->mac.is_inner_mac == pos->u.mac.is_inner_mac))
 			return -EEXIST;
 
 	return 0;
@@ -520,7 +510,9 @@ static int bnx2x_check_vlan_mac_add(struct bnx2x *bp,
 	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)))
+				  ETH_ALEN)) &&
+		    (data->vlan_mac.is_inner_mac ==
+		     pos->u.vlan_mac.is_inner_mac))
 			return -EEXIST;
 
 	return 0;
@@ -538,7 +530,8 @@ static struct bnx2x_vlan_mac_registry_elem *
 	DP(BNX2X_MSG_SP, "Checking MAC %pM for DEL command\n", data->mac.mac);
 
 	list_for_each_entry(pos, &o->head, link)
-		if (!memcmp(data->mac.mac, pos->u.mac.mac, ETH_ALEN))
+		if ((!memcmp(data->mac.mac, pos->u.mac.mac, ETH_ALEN)) &&
+		    (data->mac.is_inner_mac == pos->u.mac.is_inner_mac))
 			return pos;
 
 	return NULL;
@@ -573,7 +566,9 @@ static struct bnx2x_vlan_mac_registry_elem *
 	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)))
+			     ETH_ALEN)) &&
+		    (data->vlan_mac.is_inner_mac ==
+		     pos->u.vlan_mac.is_inner_mac))
 			return pos;
 
 	return NULL;
@@ -770,6 +765,8 @@ static void bnx2x_set_one_mac_e2(struct bnx2x *bp,
 	bnx2x_set_fw_mac_addr(&rule_entry->mac.mac_msb,
 			      &rule_entry->mac.mac_mid,
 			      &rule_entry->mac.mac_lsb, mac);
+	rule_entry->mac.inner_mac =
+		cpu_to_le16(elem->cmd_data.vlan_mac.u.mac.is_inner_mac);
 
 	/* MOVE: Add a rule that will add this MAC to the target Queue */
 	if (cmd == BNX2X_VLAN_MAC_MOVE) {
@@ -786,6 +783,9 @@ static void bnx2x_set_one_mac_e2(struct bnx2x *bp,
 		bnx2x_set_fw_mac_addr(&rule_entry->mac.mac_msb,
 				      &rule_entry->mac.mac_mid,
 				      &rule_entry->mac.mac_lsb, mac);
+		rule_entry->mac.inner_mac =
+			cpu_to_le16(elem->cmd_data.vlan_mac.
+						u.mac.is_inner_mac);
 	}
 
 	/* Set the ramrod data header */
@@ -974,7 +974,8 @@ static void bnx2x_set_one_vlan_mac_e2(struct bnx2x *bp,
 	bnx2x_set_fw_mac_addr(&rule_entry->pair.mac_msb,
 			      &rule_entry->pair.mac_mid,
 			      &rule_entry->pair.mac_lsb, mac);
-
+	rule_entry->pair.inner_mac =
+		cpu_to_le16(elem->cmd_data.vlan_mac.u.vlan_mac.is_inner_mac);
 	/* MOVE: Add a rule that will add this MAC to the target Queue */
 	if (cmd == BNX2X_VLAN_MAC_MOVE) {
 		rule_entry++;
@@ -991,6 +992,9 @@ static void bnx2x_set_one_vlan_mac_e2(struct bnx2x *bp,
 		bnx2x_set_fw_mac_addr(&rule_entry->pair.mac_msb,
 				      &rule_entry->pair.mac_mid,
 				      &rule_entry->pair.mac_lsb, mac);
+		rule_entry->pair.inner_mac =
+			cpu_to_le16(elem->cmd_data.vlan_mac.u.
+						vlan_mac.is_inner_mac);
 	}
 
 	/* Set the ramrod data header */
@@ -1854,6 +1858,7 @@ static int bnx2x_vlan_mac_del_all(struct bnx2x *bp,
 				return rc;
 			}
 			list_del(&exeq_pos->link);
+			bnx2x_exe_queue_free_elem(bp, exeq_pos);
 		}
 	}
 
@@ -2012,6 +2017,7 @@ void bnx2x_init_vlan_obj(struct bnx2x *bp,
 		vlan_obj->check_move        = bnx2x_check_move;
 		vlan_obj->ramrod_cmd        =
 			RAMROD_CMD_ID_ETH_CLASSIFICATION_RULES;
+		vlan_obj->get_n_elements    = bnx2x_get_n_elements;
 
 		/* Exe Queue */
 		bnx2x_exe_queue_init(bp,
@@ -4426,6 +4432,12 @@ static void bnx2x_q_fill_init_tx_data(struct bnx2x_queue_sp_obj *o,
 	tx_data->force_default_pri_flg =
 		test_bit(BNX2X_Q_FLG_FORCE_DEFAULT_PRI, flags);
 
+	tx_data->tunnel_lso_inc_ip_id =
+		test_bit(BNX2X_Q_FLG_TUN_INC_INNER_IP_ID, flags);
+	tx_data->tunnel_non_lso_pcsum_location =
+		test_bit(BNX2X_Q_FLG_PCSUM_ON_PKT, flags) ? PCSUM_ON_PKT :
+								  PCSUM_ON_BD;
+
 	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;
@@ -5669,17 +5681,18 @@ static inline int bnx2x_func_send_start(struct bnx2x *bp,
 	memset(rdata, 0, sizeof(*rdata));
 
 	/* Fill the ramrod data with provided parameters */
-	rdata->function_mode    = (u8)start_params->mf_mode;
-	rdata->sd_vlan_tag      = cpu_to_le16(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()).
+	rdata->function_mode	= (u8)start_params->mf_mode;
+	rdata->sd_vlan_tag	= cpu_to_le16(start_params->sd_vlan_tag);
+	rdata->path_id		= BP_PATH(bp);
+	rdata->network_cos_mode	= start_params->network_cos_mode;
+	rdata->gre_tunnel_mode	= start_params->gre_tunnel_mode;
+	rdata->gre_tunnel_rss	= start_params->gre_tunnel_rss;
+
+	/* 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,
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h
index ff90760..43c00bc 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h
@@ -100,6 +100,7 @@ struct bnx2x_raw_obj {
 /************************* VLAN-MAC commands related parameters ***************/
 struct bnx2x_mac_ramrod_data {
 	u8 mac[ETH_ALEN];
+	u8 is_inner_mac;
 };
 
 struct bnx2x_vlan_ramrod_data {
@@ -108,6 +109,7 @@ struct bnx2x_vlan_ramrod_data {
 
 struct bnx2x_vlan_mac_ramrod_data {
 	u8 mac[ETH_ALEN];
+	u8 is_inner_mac;
 	u16 vlan;
 };
 
@@ -313,8 +315,9 @@ struct bnx2x_vlan_mac_obj {
 	 *
 	 * @return number of copied bytes
 	 */
-	int (*get_n_elements)(struct bnx2x *bp, struct bnx2x_vlan_mac_obj *o,
-			      int n, u8 *buf);
+	int (*get_n_elements)(struct bnx2x *bp,
+			      struct bnx2x_vlan_mac_obj *o, int n, u8 *base,
+			      u8 stride, u8 size);
 
 	/**
 	 * Checks if ADD-ramrod with the given params may be performed.
@@ -824,7 +827,9 @@ enum {
 	BNX2X_Q_FLG_TX_SEC,
 	BNX2X_Q_FLG_ANTI_SPOOF,
 	BNX2X_Q_FLG_SILENT_VLAN_REM,
-	BNX2X_Q_FLG_FORCE_DEFAULT_PRI
+	BNX2X_Q_FLG_FORCE_DEFAULT_PRI,
+	BNX2X_Q_FLG_PCSUM_ON_PKT,
+	BNX2X_Q_FLG_TUN_INC_INNER_IP_ID
 };
 
 /* Queue type options: queue type may be a compination of below. */
@@ -842,6 +847,7 @@ enum bnx2x_q_type {
 #define BNX2X_MULTI_TX_COS_E3B0			3
 #define BNX2X_MULTI_TX_COS			3 /* Maximum possible */
 
+#define MAC_PAD (ALIGN(ETH_ALEN, sizeof(u32)) - ETH_ALEN)
 
 struct bnx2x_queue_init_params {
 	struct {
@@ -1118,6 +1124,15 @@ struct bnx2x_func_start_params {
 
 	/* Function cos mode */
 	u8 network_cos_mode;
+
+	/* NVGRE classification enablement */
+	u8 nvgre_clss_en;
+
+	/* NO_GRE_TUNNEL/NVGRE_TUNNEL/L2GRE_TUNNEL/IPGRE_TUNNEL */
+	u8 gre_tunnel_mode;
+
+	/* GRE_OUTER_HEADERS_RSS/GRE_INNER_HEADERS_RSS/NVGRE_KEY_ENTROPY_RSS */
+	u8 gre_tunnel_rss;
 };
 
 struct bnx2x_func_switch_update_params {
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
index 6adfa20..2ce7c74 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
@@ -20,7 +20,9 @@
 #include "bnx2x.h"
 #include "bnx2x_init.h"
 #include "bnx2x_cmn.h"
+#include "bnx2x_sp.h"
 #include <linux/crc32.h>
+#include <linux/if_vlan.h>
 
 /* General service functions */
 static void storm_memset_vf_to_pf(struct bnx2x *bp, u16 abs_fid,
@@ -555,8 +557,7 @@ static int bnx2x_vfop_config_list(struct bnx2x *bp,
 		rc = bnx2x_config_vlan_mac(bp, vlan_mac);
 		if (rc >= 0) {
 			cnt += pos->add ? 1 : -1;
-			list_del(&pos->link);
-			list_add(&pos->link, &rollback_list);
+			list_move(&pos->link, &rollback_list);
 			rc = 0;
 		} else if (rc == -EEXIST) {
 			rc = 0;
@@ -958,6 +959,12 @@ op_err:
 	BNX2X_ERR("QSETUP[%d:%d] error: rc %d\n", vf->abs_vfid, qid, vfop->rc);
 op_done:
 	case BNX2X_VFOP_QSETUP_DONE:
+		vf->cfg_flags |= VF_CFG_VLAN;
+		smp_mb__before_clear_bit();
+		set_bit(BNX2X_SP_RTNL_HYPERVISOR_VLAN,
+			&bp->sp_rtnl_state);
+		smp_mb__after_clear_bit();
+		schedule_delayed_work(&bp->sp_rtnl_task, 0);
 		bnx2x_vfop_end(bp, vf, vfop);
 		return;
 	default:
@@ -1459,7 +1466,6 @@ static u8 bnx2x_vf_is_pcie_pending(struct bnx2x *bp, u8 abs_vfid)
 		return bnx2x_is_pcie_pending(dev);
 
 unknown_dev:
-	BNX2X_ERR("Unknown device\n");
 	return false;
 }
 
@@ -1926,20 +1932,22 @@ int bnx2x_iov_init_one(struct bnx2x *bp, int int_mode_param,
 
 	/* SRIOV can be enabled only with MSIX */
 	if (int_mode_param == BNX2X_INT_MODE_MSI ||
-	    int_mode_param == BNX2X_INT_MODE_INTX)
+	    int_mode_param == BNX2X_INT_MODE_INTX) {
 		BNX2X_ERR("Forced MSI/INTx mode is incompatible with SRIOV\n");
+		return 0;
+	}
 
 	err = -EIO;
 	/* verify ari is enabled */
 	if (!bnx2x_ari_enabled(bp->pdev)) {
-		BNX2X_ERR("ARI not supported, SRIOV can not be enabled\n");
-		return err;
+		BNX2X_ERR("ARI not supported (check pci bridge ARI forwarding), SRIOV can not be enabled\n");
+		return 0;
 	}
 
 	/* verify igu is in normal mode */
 	if (CHIP_INT_MODE_IS_BC(bp)) {
 		BNX2X_ERR("IGU not normal mode,  SRIOV can not be enabled\n");
-		return err;
+		return 0;
 	}
 
 	/* allocate the vfs database */
@@ -1964,8 +1972,10 @@ int bnx2x_iov_init_one(struct bnx2x *bp, int int_mode_param,
 	if (iov->total == 0)
 		goto failed;
 
-	/* calculate the actual number of VFs */
-	iov->nr_virtfn = min_t(u16, iov->total, (u16)num_vfs_param);
+	iov->nr_virtfn = min_t(u16, iov->total, num_vfs_param);
+
+	DP(BNX2X_MSG_IOV, "num_vfs_param was %d, nr_virtfn was %d\n",
+	   num_vfs_param, iov->nr_virtfn);
 
 	/* allocate the vf array */
 	bp->vfdb->vfs = kzalloc(sizeof(struct bnx2x_virtf) *
@@ -2378,8 +2388,8 @@ int bnx2x_iov_eq_sp_event(struct bnx2x *bp, union event_ring_elem *elem)
 		goto get_vf;
 	case EVENT_RING_OPCODE_MALICIOUS_VF:
 		abs_vfid = elem->message.data.malicious_vf_event.vf_id;
-		DP(BNX2X_MSG_IOV, "Got VF MALICIOUS notification abs_vfid=%d\n",
-		   abs_vfid);
+		DP(BNX2X_MSG_IOV, "Got VF MALICIOUS notification abs_vfid=%d err_id=0x%x\n",
+		   abs_vfid, elem->message.data.malicious_vf_event.err_id);
 		goto get_vf;
 	default:
 		return 1;
@@ -2436,8 +2446,8 @@ get_vf:
 		/* Do nothing for now */
 		break;
 	case EVENT_RING_OPCODE_MALICIOUS_VF:
-		DP(BNX2X_MSG_IOV, "got VF [%d] MALICIOUS notification\n",
-		   vf->abs_vfid);
+		DP(BNX2X_MSG_IOV, "Got VF MALICIOUS notification abs_vfid=%d error id %x\n",
+		   abs_vfid, elem->message.data.malicious_vf_event.err_id);
 		/* Do nothing for now */
 		break;
 	}
@@ -3012,21 +3022,138 @@ void bnx2x_unlock_vf_pf_channel(struct bnx2x *bp, struct bnx2x_virtf *vf,
 	vf->op_current = CHANNEL_TLV_NONE;
 }
 
-void bnx2x_enable_sriov(struct bnx2x *bp)
+int bnx2x_sriov_configure(struct pci_dev *dev, int num_vfs_param)
 {
-	int rc = 0;
 
-	/* disbale sriov in case it is still enabled */
+	struct bnx2x *bp = netdev_priv(pci_get_drvdata(dev));
+
+	DP(BNX2X_MSG_IOV, "bnx2x_sriov_configure called with %d, BNX2X_NR_VIRTFN(bp) was %d\n",
+	   num_vfs_param, BNX2X_NR_VIRTFN(bp));
+
+	/* HW channel is only operational when PF is up */
+	if (bp->state != BNX2X_STATE_OPEN) {
+		BNX2X_ERR("VF num configurtion via sysfs not supported while PF is down");
+		return -EINVAL;
+	}
+
+	/* we are always bound by the total_vfs in the configuration space */
+	if (num_vfs_param > BNX2X_NR_VIRTFN(bp)) {
+		BNX2X_ERR("truncating requested number of VFs (%d) down to maximum allowed (%d)\n",
+			  num_vfs_param, BNX2X_NR_VIRTFN(bp));
+		num_vfs_param = BNX2X_NR_VIRTFN(bp);
+	}
+
+	bp->requested_nr_virtfn = num_vfs_param;
+	if (num_vfs_param == 0) {
+		pci_disable_sriov(dev);
+		return 0;
+	} else {
+		return bnx2x_enable_sriov(bp);
+	}
+}
+
+int bnx2x_enable_sriov(struct bnx2x *bp)
+{
+	int rc = 0, req_vfs = bp->requested_nr_virtfn;
+
+	rc = pci_enable_sriov(bp->pdev, req_vfs);
+	if (rc) {
+		BNX2X_ERR("pci_enable_sriov failed with %d\n", rc);
+		return rc;
+	}
+	DP(BNX2X_MSG_IOV, "sriov enabled (%d vfs)\n", req_vfs);
+	return req_vfs;
+}
+
+void bnx2x_pf_set_vfs_vlan(struct bnx2x *bp)
+{
+	int vfidx;
+	struct pf_vf_bulletin_content *bulletin;
+
+	DP(BNX2X_MSG_IOV, "configuring vlan for VFs from sp-task\n");
+	for_each_vf(bp, vfidx) {
+	bulletin = BP_VF_BULLETIN(bp, vfidx);
+		if (BP_VF(bp, vfidx)->cfg_flags & VF_CFG_VLAN)
+			bnx2x_set_vf_vlan(bp->dev, vfidx, bulletin->vlan, 0);
+	}
+}
+
+void bnx2x_disable_sriov(struct bnx2x *bp)
+{
 	pci_disable_sriov(bp->pdev);
-	DP(BNX2X_MSG_IOV, "sriov disabled\n");
+}
+
+static int bnx2x_vf_ndo_sanity(struct bnx2x *bp, int vfidx,
+			       struct bnx2x_virtf *vf)
+{
+	if (!IS_SRIOV(bp)) {
+		BNX2X_ERR("vf ndo called though sriov is disabled\n");
+		return -EINVAL;
+	}
+
+	if (vfidx >= BNX2X_NR_VIRTFN(bp)) {
+		BNX2X_ERR("vf ndo called for uninitialized VF. vfidx was %d BNX2X_NR_VIRTFN was %d\n",
+			  vfidx, BNX2X_NR_VIRTFN(bp));
+		return -EINVAL;
+	}
+
+	if (!vf) {
+		BNX2X_ERR("vf ndo called but vf was null. vfidx was %d\n",
+			  vfidx);
+		return -EINVAL;
+	}
 
-	/* enable sriov */
-	DP(BNX2X_MSG_IOV, "vf num (%d)\n", (bp->vfdb->sriov.nr_virtfn));
-	rc = pci_enable_sriov(bp->pdev, (bp->vfdb->sriov.nr_virtfn));
+	return 0;
+}
+
+int bnx2x_get_vf_config(struct net_device *dev, int vfidx,
+			struct ifla_vf_info *ivi)
+{
+	struct bnx2x *bp = netdev_priv(dev);
+	struct bnx2x_virtf *vf = BP_VF(bp, vfidx);
+	struct bnx2x_vlan_mac_obj *mac_obj = &bnx2x_vfq(vf, 0, mac_obj);
+	struct bnx2x_vlan_mac_obj *vlan_obj = &bnx2x_vfq(vf, 0, vlan_obj);
+	struct pf_vf_bulletin_content *bulletin = BP_VF_BULLETIN(bp, vfidx);
+	int rc;
+
+	/* sanity */
+	rc = bnx2x_vf_ndo_sanity(bp, vfidx, vf);
 	if (rc)
-		BNX2X_ERR("pci_enable_sriov failed with %d\n", rc);
-	else
-		DP(BNX2X_MSG_IOV, "sriov enabled\n");
+		return rc;
+	if (!mac_obj || !vlan_obj || !bulletin) {
+		BNX2X_ERR("VF partially initialized\n");
+		return -EINVAL;
+	}
+
+	ivi->vf = vfidx;
+	ivi->qos = 0;
+	ivi->tx_rate = 10000; /* always 10G. TBA take from link struct */
+	ivi->spoofchk = 1; /*always enabled */
+	if (vf->state == VF_ENABLED) {
+		/* mac and vlan are in vlan_mac objects */
+		mac_obj->get_n_elements(bp, mac_obj, 1, (u8 *)&ivi->mac,
+					0, ETH_ALEN);
+		vlan_obj->get_n_elements(bp, vlan_obj, 1, (u8 *)&ivi->vlan,
+					 0, VLAN_HLEN);
+	} else {
+		/* mac */
+		if (bulletin->valid_bitmap & (1 << MAC_ADDR_VALID))
+			/* mac configured by ndo so its in bulletin board */
+			memcpy(&ivi->mac, bulletin->mac, ETH_ALEN);
+		else
+			/* funtion has not been loaded yet. Show mac as 0s */
+			memset(&ivi->mac, 0, ETH_ALEN);
+
+		/* vlan */
+		if (bulletin->valid_bitmap & (1 << VLAN_VALID))
+			/* vlan configured by ndo so its in bulletin board */
+			memcpy(&ivi->vlan, &bulletin->vlan, VLAN_HLEN);
+		else
+			/* funtion has not been loaded yet. Show vlans as 0s */
+			memset(&ivi->vlan, 0, VLAN_HLEN);
+	}
+
+	return 0;
 }
 
 /* New mac for VF. Consider these cases:
@@ -3044,23 +3171,19 @@ void bnx2x_enable_sriov(struct bnx2x *bp)
  * VF to configure any mac for itself except for this mac. In case of a race
  * where the VF fails to see the new post on its bulletin board before sending a
  * mac configuration request, the PF will simply fail the request and VF can try
- * again after consulting its bulletin board
+ * again after consulting its bulletin board.
  */
-int bnx2x_set_vf_mac(struct net_device *dev, int queue, u8 *mac)
+int bnx2x_set_vf_mac(struct net_device *dev, int vfidx, u8 *mac)
 {
 	struct bnx2x *bp = netdev_priv(dev);
-	int rc, q_logical_state, vfidx = queue;
+	int rc, q_logical_state;
 	struct bnx2x_virtf *vf = BP_VF(bp, vfidx);
 	struct pf_vf_bulletin_content *bulletin = BP_VF_BULLETIN(bp, vfidx);
 
-	/* if SRIOV is disabled there is nothing to do (and somewhere, someone
-	 * has erred).
-	 */
-	if (!IS_SRIOV(bp)) {
-		BNX2X_ERR("bnx2x_set_vf_mac called though sriov is disabled\n");
-		return -EINVAL;
-	}
-
+	/* sanity */
+	rc = bnx2x_vf_ndo_sanity(bp, vfidx, vf);
+	if (rc)
+		return rc;
 	if (!is_valid_ether_addr(mac)) {
 		BNX2X_ERR("mac address invalid\n");
 		return -EINVAL;
@@ -3085,7 +3208,7 @@ int bnx2x_set_vf_mac(struct net_device *dev, int queue, u8 *mac)
 	if (vf->state == VF_ENABLED &&
 	    q_logical_state == BNX2X_Q_LOGICAL_STATE_ACTIVE) {
 		/* configure the mac in device on this vf's queue */
-		unsigned long flags = 0;
+		unsigned long ramrod_flags = 0;
 		struct bnx2x_vlan_mac_obj *mac_obj = &bnx2x_vfq(vf, 0, mac_obj);
 
 		/* must lock vfpf channel to protect against vf flows */
@@ -3106,14 +3229,133 @@ int bnx2x_set_vf_mac(struct net_device *dev, int queue, u8 *mac)
 		}
 
 		/* configure the new mac to device */
-		__set_bit(RAMROD_COMP_WAIT, &flags);
+		__set_bit(RAMROD_COMP_WAIT, &ramrod_flags);
 		bnx2x_set_mac_one(bp, (u8 *)&bulletin->mac, mac_obj, true,
-				  BNX2X_ETH_MAC, &flags);
+				  BNX2X_ETH_MAC, &ramrod_flags);
 
 		bnx2x_unlock_vf_pf_channel(bp, vf, CHANNEL_TLV_PF_SET_MAC);
 	}
 
-	return rc;
+	return 0;
+}
+
+int bnx2x_set_vf_vlan(struct net_device *dev, int vfidx, u16 vlan, u8 qos)
+{
+	struct bnx2x *bp = netdev_priv(dev);
+	int rc, q_logical_state;
+	struct bnx2x_virtf *vf = BP_VF(bp, vfidx);
+	struct pf_vf_bulletin_content *bulletin = BP_VF_BULLETIN(bp, vfidx);
+
+	/* sanity */
+	rc = bnx2x_vf_ndo_sanity(bp, vfidx, vf);
+	if (rc)
+		return rc;
+
+	if (vlan > 4095) {
+		BNX2X_ERR("illegal vlan value %d\n", vlan);
+		return -EINVAL;
+	}
+
+	DP(BNX2X_MSG_IOV, "configuring VF %d with VLAN %d qos %d\n",
+	   vfidx, vlan, 0);
+
+	/* update PF's copy of the VF's bulletin. No point in posting the vlan
+	 * to the VF since it doesn't have anything to do with it. But it useful
+	 * to store it here in case the VF is not up yet and we can only
+	 * configure the vlan later when it does.
+	 */
+	bulletin->valid_bitmap |= 1 << VLAN_VALID;
+	bulletin->vlan = vlan;
+
+	/* is vf initialized and queue set up? */
+	q_logical_state =
+		bnx2x_get_q_logical_state(bp, &bnx2x_vfq(vf, 0, sp_obj));
+	if (vf->state == VF_ENABLED &&
+	    q_logical_state == BNX2X_Q_LOGICAL_STATE_ACTIVE) {
+		/* configure the vlan in device on this vf's queue */
+		unsigned long ramrod_flags = 0;
+		unsigned long vlan_mac_flags = 0;
+		struct bnx2x_vlan_mac_obj *vlan_obj =
+			&bnx2x_vfq(vf, 0, vlan_obj);
+		struct bnx2x_vlan_mac_ramrod_params ramrod_param;
+		struct bnx2x_queue_state_params q_params = {NULL};
+		struct bnx2x_queue_update_params *update_params;
+
+		memset(&ramrod_param, 0, sizeof(ramrod_param));
+
+		/* must lock vfpf channel to protect against vf flows */
+		bnx2x_lock_vf_pf_channel(bp, vf, CHANNEL_TLV_PF_SET_VLAN);
+
+		/* remove existing vlans */
+		__set_bit(RAMROD_COMP_WAIT, &ramrod_flags);
+		rc = vlan_obj->delete_all(bp, vlan_obj, &vlan_mac_flags,
+					  &ramrod_flags);
+		if (rc) {
+			BNX2X_ERR("failed to delete vlans\n");
+			return -EINVAL;
+		}
+
+		/* send queue update ramrod to configure default vlan and silent
+		 * vlan removal
+		 */
+		__set_bit(RAMROD_COMP_WAIT, &q_params.ramrod_flags);
+		q_params.cmd = BNX2X_Q_CMD_UPDATE;
+		q_params.q_obj = &bnx2x_vfq(vf, 0, sp_obj);
+		update_params = &q_params.params.update;
+		__set_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN_CHNG,
+			  &update_params->update_flags);
+		__set_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM_CHNG,
+			  &update_params->update_flags);
+
+		if (vlan == 0) {
+			/* if vlan is 0 then we want to leave the VF traffic
+			 * untagged, and leave the incoming traffic untouched
+			 * (i.e. do not remove any vlan tags).
+			 */
+			__clear_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN,
+				    &update_params->update_flags);
+			__clear_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM,
+				    &update_params->update_flags);
+		} else {
+			/* configure the new vlan to device */
+			__set_bit(RAMROD_COMP_WAIT, &ramrod_flags);
+			ramrod_param.vlan_mac_obj = vlan_obj;
+			ramrod_param.ramrod_flags = ramrod_flags;
+			ramrod_param.user_req.u.vlan.vlan = vlan;
+			ramrod_param.user_req.cmd = BNX2X_VLAN_MAC_ADD;
+			rc = bnx2x_config_vlan_mac(bp, &ramrod_param);
+			if (rc) {
+				BNX2X_ERR("failed to configure vlan\n");
+				return -EINVAL;
+			}
+
+			/* configure default vlan to vf queue and set silent
+			 * vlan removal (the vf remains unaware of this vlan).
+			 */
+			update_params = &q_params.params.update;
+			__set_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN,
+				  &update_params->update_flags);
+			__set_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM,
+				  &update_params->update_flags);
+			update_params->def_vlan = vlan;
+		}
+
+		/* Update the Queue state */
+		rc = bnx2x_queue_state_change(bp, &q_params);
+		if (rc) {
+			BNX2X_ERR("Failed to configure default VLAN\n");
+			return rc;
+		}
+
+		/* clear the flag indicating that this VF needs its vlan
+		 * (will only be set if the HV configured th Vlan before vf was
+		 * and we were called because the VF came up later
+		 */
+		vf->cfg_flags &= ~VF_CFG_VLAN;
+
+		bnx2x_unlock_vf_pf_channel(bp, vf, CHANNEL_TLV_PF_SET_VLAN);
+	}
+	return 0;
 }
 
 /* crc is the first field in the bulletin board. compute the crc over the
@@ -3165,20 +3407,26 @@ enum sample_bulletin_result bnx2x_sample_bulletin(struct bnx2x *bp)
 		memcpy(bp->dev->dev_addr, bulletin.mac, ETH_ALEN);
 	}
 
+	/* the vlan in bulletin board is valid and is new */
+	if (bulletin.valid_bitmap & 1 << VLAN_VALID)
+		memcpy(&bulletin.vlan, &bp->old_bulletin.vlan, VLAN_HLEN);
+
 	/* copy new bulletin board to bp */
 	bp->old_bulletin = bulletin;
 
 	return PFVF_BULLETIN_UPDATED;
 }
 
-void bnx2x_vf_map_doorbells(struct bnx2x *bp)
+void __iomem *bnx2x_vf_doorbells(struct bnx2x *bp)
 {
 	/* vf doorbells are embedded within the regview */
-	bp->doorbells = bp->regview + PXP_VF_ADDR_DB_START;
+	return bp->regview + PXP_VF_ADDR_DB_START;
 }
 
 int bnx2x_vf_pci_alloc(struct bnx2x *bp)
 {
+	mutex_init(&bp->vf2pf_mutex);
+
 	/* allocate vf2pf mailbox for vf to pf channel */
 	BNX2X_PCI_ALLOC(bp->vf2pf_mbox, &bp->vf2pf_mbox_mapping,
 			sizeof(struct bnx2x_vf_mbx_msg));
@@ -3196,3 +3444,26 @@ alloc_mem_err:
 		       sizeof(union pf_vf_bulletin));
 	return -ENOMEM;
 }
+
+int bnx2x_open_epilog(struct bnx2x *bp)
+{
+	/* Enable sriov via delayed work. This must be done via delayed work
+	 * because it causes the probe of the vf devices to be run, which invoke
+	 * register_netdevice which must have rtnl lock taken. As we are holding
+	 * the lock right now, that could only work if the probe would not take
+	 * the lock. However, as the probe of the vf may be called from other
+	 * contexts as well (such as passthrough to vm failes) it can't assume
+	 * the lock is being held for it. Using delayed work here allows the
+	 * probe code to simply take the lock (i.e. wait for it to be released
+	 * if it is being held). We only want to do this if the number of VFs
+	 * was set before PF driver was loaded.
+	 */
+	if (IS_SRIOV(bp) && BNX2X_NR_VIRTFN(bp)) {
+		smp_mb__before_clear_bit();
+		set_bit(BNX2X_SP_RTNL_ENABLE_SRIOV, &bp->sp_rtnl_state);
+		smp_mb__after_clear_bit();
+		schedule_delayed_work(&bp->sp_rtnl_task, 0);
+	}
+
+	return 0;
+}
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h
index b405017..d4b17b7 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h
@@ -193,6 +193,7 @@ struct bnx2x_virtf {
 #define VF_CFG_TPA		0x0004
 #define VF_CFG_INT_SIMD		0x0008
 #define VF_CACHE_LINE		0x0010
+#define VF_CFG_VLAN		0x0020
 
 	u8 state;
 #define VF_FREE		0	/* VF ready to be acquired holds no resc */
@@ -712,6 +713,7 @@ void bnx2x_add_tlv(struct bnx2x *bp, void *tlvs_list, u16 offset, u16 type,
 		   u16 length);
 void bnx2x_vfpf_prep(struct bnx2x *bp, struct vfpf_first_tlv *first_tlv,
 		     u16 type, u16 length);
+void bnx2x_vfpf_finalize(struct bnx2x *bp, struct vfpf_first_tlv *first_tlv);
 void bnx2x_dp_tlv_list(struct bnx2x *bp, void *tlvs_list);
 
 bool bnx2x_tlv_supported(u16 tlvtype);
@@ -750,13 +752,17 @@ static inline int bnx2x_vf_ustorm_prods_offset(struct bnx2x *bp,
 }
 
 enum sample_bulletin_result bnx2x_sample_bulletin(struct bnx2x *bp);
-void bnx2x_vf_map_doorbells(struct bnx2x *bp);
+void __iomem *bnx2x_vf_doorbells(struct bnx2x *bp);
 int bnx2x_vf_pci_alloc(struct bnx2x *bp);
-void bnx2x_enable_sriov(struct bnx2x *bp);
+int bnx2x_enable_sriov(struct bnx2x *bp);
+void bnx2x_disable_sriov(struct bnx2x *bp);
 static inline int bnx2x_vf_headroom(struct bnx2x *bp)
 {
 	return bp->vfdb->sriov.nr_virtfn * BNX2X_CLIENTS_PER_VF;
 }
+void bnx2x_pf_set_vfs_vlan(struct bnx2x *bp);
+int bnx2x_sriov_configure(struct pci_dev *dev, int num_vfs);
+int bnx2x_open_epilog(struct bnx2x *bp);
 
 #else /* CONFIG_BNX2X_SRIOV */
 
@@ -779,7 +785,8 @@ static inline void bnx2x_iov_init_dmae(struct bnx2x *bp) {}
 static inline int bnx2x_iov_init_one(struct bnx2x *bp, int int_mode_param,
 				     int num_vfs_param) {return 0; }
 static inline void bnx2x_iov_remove_one(struct bnx2x *bp) {}
-static inline void bnx2x_enable_sriov(struct bnx2x *bp) {}
+static inline int bnx2x_enable_sriov(struct bnx2x *bp) {return 0; }
+static inline void bnx2x_disable_sriov(struct bnx2x *bp) {}
 static inline int bnx2x_vfpf_acquire(struct bnx2x *bp,
 				     u8 tx_count, u8 rx_count) {return 0; }
 static inline int bnx2x_vfpf_release(struct bnx2x *bp) {return 0; }
@@ -802,8 +809,15 @@ static inline enum sample_bulletin_result bnx2x_sample_bulletin(struct bnx2x *bp
 	return PFVF_BULLETIN_UNCHANGED;
 }
 
-static inline int bnx2x_vf_map_doorbells(struct bnx2x *bp) {return 0; }
+static inline void __iomem *bnx2x_vf_doorbells(struct bnx2x *bp)
+{
+	return NULL;
+}
+
 static inline int bnx2x_vf_pci_alloc(struct bnx2x *bp) {return 0; }
+static inline void bnx2x_pf_set_vfs_vlan(struct bnx2x *bp) {}
+static inline int bnx2x_sriov_configure(struct pci_dev *dev, int num_vfs) {return 0; }
+static inline int bnx2x_open_epilog(struct bnx2x *bp) {return 0; }
 
 #endif /* CONFIG_BNX2X_SRIOV */
 #endif /* bnx2x_sriov.h */
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c
index 4397f8b..2ca3d94 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c
@@ -1547,11 +1547,51 @@ static void bnx2x_prep_fw_stats_req(struct bnx2x *bp)
 	}
 }
 
+void bnx2x_memset_stats(struct bnx2x *bp)
+{
+	int i;
+
+	/* function stats */
+	for_each_queue(bp, i) {
+		struct bnx2x_fp_stats *fp_stats = &bp->fp_stats[i];
+
+		memset(&fp_stats->old_tclient, 0,
+		       sizeof(fp_stats->old_tclient));
+		memset(&fp_stats->old_uclient, 0,
+		       sizeof(fp_stats->old_uclient));
+		memset(&fp_stats->old_xclient, 0,
+		       sizeof(fp_stats->old_xclient));
+		if (bp->stats_init) {
+			memset(&fp_stats->eth_q_stats, 0,
+			       sizeof(fp_stats->eth_q_stats));
+			memset(&fp_stats->eth_q_stats_old, 0,
+			       sizeof(fp_stats->eth_q_stats_old));
+		}
+	}
+
+	memset(&bp->dev->stats, 0, sizeof(bp->dev->stats));
+
+	if (bp->stats_init) {
+		memset(&bp->net_stats_old, 0, sizeof(bp->net_stats_old));
+		memset(&bp->fw_stats_old, 0, sizeof(bp->fw_stats_old));
+		memset(&bp->eth_stats_old, 0, sizeof(bp->eth_stats_old));
+		memset(&bp->eth_stats, 0, sizeof(bp->eth_stats));
+		memset(&bp->func_stats, 0, sizeof(bp->func_stats));
+	}
+
+	bp->stats_state = STATS_STATE_DISABLED;
+
+	if (bp->port.pmf && bp->port.port_stx)
+		bnx2x_port_stats_base_init(bp);
+
+	/* mark the end of statistics initializiation */
+	bp->stats_init = false;
+}
+
 void bnx2x_stats_init(struct bnx2x *bp)
 {
 	int /*abs*/port = BP_PORT(bp);
 	int mb_idx = BP_FW_MB_IDX(bp);
-	int i;
 
 	bp->stats_pending = 0;
 	bp->executer_idx = 0;
@@ -1587,36 +1627,11 @@ void bnx2x_stats_init(struct bnx2x *bp)
 			    &(bp->port.old_nig_stats.egress_mac_pkt1_lo), 2);
 	}
 
-	/* function stats */
-	for_each_queue(bp, i) {
-		struct bnx2x_fp_stats *fp_stats = &bp->fp_stats[i];
-
-		memset(&fp_stats->old_tclient, 0,
-		       sizeof(fp_stats->old_tclient));
-		memset(&fp_stats->old_uclient, 0,
-		       sizeof(fp_stats->old_uclient));
-		memset(&fp_stats->old_xclient, 0,
-		       sizeof(fp_stats->old_xclient));
-		if (bp->stats_init) {
-			memset(&fp_stats->eth_q_stats, 0,
-			       sizeof(fp_stats->eth_q_stats));
-			memset(&fp_stats->eth_q_stats_old, 0,
-			       sizeof(fp_stats->eth_q_stats_old));
-		}
-	}
-
 	/* Prepare statistics ramrod data */
 	bnx2x_prep_fw_stats_req(bp);
 
-	memset(&bp->dev->stats, 0, sizeof(bp->dev->stats));
+	/* Clean SP from previous statistics */
 	if (bp->stats_init) {
-		memset(&bp->net_stats_old, 0, sizeof(bp->net_stats_old));
-		memset(&bp->fw_stats_old, 0, sizeof(bp->fw_stats_old));
-		memset(&bp->eth_stats_old, 0, sizeof(bp->eth_stats_old));
-		memset(&bp->eth_stats, 0, sizeof(bp->eth_stats));
-		memset(&bp->func_stats, 0, sizeof(bp->func_stats));
-
-		/* Clean SP from previous statistics */
 		if (bp->func_stx) {
 			memset(bnx2x_sp(bp, func_stats), 0,
 			       sizeof(struct host_func_stats));
@@ -1626,13 +1641,7 @@ void bnx2x_stats_init(struct bnx2x *bp)
 		}
 	}
 
-	bp->stats_state = STATS_STATE_DISABLED;
-
-	if (bp->port.pmf && bp->port.port_stx)
-		bnx2x_port_stats_base_init(bp);
-
-	/* mark the end of statistics initializiation */
-	bp->stats_init = false;
+	bnx2x_memset_stats(bp);
 }
 
 void bnx2x_save_statistics(struct bnx2x *bp)
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h
index 198f6f1..d117f47 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h
@@ -540,8 +540,8 @@ struct bnx2x_fw_port_stats_old {
 /* forward */
 struct bnx2x;
 
+void bnx2x_memset_stats(struct bnx2x *bp);
 void bnx2x_stats_init(struct bnx2x *bp);
-
 void bnx2x_stats_handle(struct bnx2x *bp, enum bnx2x_stats_event event);
 
 /**
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
index 531eebf..90fbf9c 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
@@ -36,6 +36,8 @@ void bnx2x_add_tlv(struct bnx2x *bp, void *tlvs_list, u16 offset, u16 type,
 void bnx2x_vfpf_prep(struct bnx2x *bp, struct vfpf_first_tlv *first_tlv,
 		     u16 type, u16 length)
 {
+	mutex_lock(&bp->vf2pf_mutex);
+
 	DP(BNX2X_MSG_IOV, "preparing to send %d tlv over vf pf channel\n",
 	   type);
 
@@ -49,6 +51,15 @@ void bnx2x_vfpf_prep(struct bnx2x *bp, struct vfpf_first_tlv *first_tlv,
 	first_tlv->resp_msg_offset = sizeof(bp->vf2pf_mbox->req);
 }
 
+/* releases the mailbox */
+void bnx2x_vfpf_finalize(struct bnx2x *bp, struct vfpf_first_tlv *first_tlv)
+{
+	DP(BNX2X_MSG_IOV, "done sending [%d] tlv over vf pf channel\n",
+	   first_tlv->tl.type);
+
+	mutex_unlock(&bp->vf2pf_mutex);
+}
+
 /* list the types and lengths of the tlvs on the buffer */
 void bnx2x_dp_tlv_list(struct bnx2x *bp, void *tlvs_list)
 {
@@ -181,8 +192,10 @@ int bnx2x_vfpf_acquire(struct bnx2x *bp, u8 tx_count, u8 rx_count)
 	/* clear mailbox and prep first tlv */
 	bnx2x_vfpf_prep(bp, &req->first_tlv, CHANNEL_TLV_ACQUIRE, sizeof(*req));
 
-	if (bnx2x_get_vf_id(bp, &vf_id))
-		return -EAGAIN;
+	if (bnx2x_get_vf_id(bp, &vf_id)) {
+		rc = -EAGAIN;
+		goto out;
+	}
 
 	req->vfdev_info.vf_id = vf_id;
 	req->vfdev_info.vf_os = 0;
@@ -213,7 +226,7 @@ int bnx2x_vfpf_acquire(struct bnx2x *bp, u8 tx_count, u8 rx_count)
 
 		/* PF timeout */
 		if (rc)
-			return rc;
+			goto out;
 
 		/* copy acquire response from buffer to bp */
 		memcpy(&bp->acquire_resp, resp, sizeof(bp->acquire_resp));
@@ -253,7 +266,8 @@ int bnx2x_vfpf_acquire(struct bnx2x *bp, u8 tx_count, u8 rx_count)
 			/* PF reports error */
 			BNX2X_ERR("Failed to get the requested amount of resources: %d. Breaking...\n",
 				  bp->acquire_resp.hdr.status);
-			return -EAGAIN;
+			rc = -EAGAIN;
+			goto out;
 		}
 	}
 
@@ -279,20 +293,24 @@ int bnx2x_vfpf_acquire(struct bnx2x *bp, u8 tx_count, u8 rx_count)
 		       bp->acquire_resp.resc.current_mac_addr,
 		       ETH_ALEN);
 
-	return 0;
+out:
+	bnx2x_vfpf_finalize(bp, &req->first_tlv);
+	return rc;
 }
 
 int bnx2x_vfpf_release(struct bnx2x *bp)
 {
 	struct vfpf_release_tlv *req = &bp->vf2pf_mbox->req.release;
 	struct pfvf_general_resp_tlv *resp = &bp->vf2pf_mbox->resp.general_resp;
-	u32 rc = 0, vf_id;
+	u32 rc, vf_id;
 
 	/* clear mailbox and prep first tlv */
 	bnx2x_vfpf_prep(bp, &req->first_tlv, CHANNEL_TLV_RELEASE, sizeof(*req));
 
-	if (bnx2x_get_vf_id(bp, &vf_id))
-		return -EAGAIN;
+	if (bnx2x_get_vf_id(bp, &vf_id)) {
+		rc = -EAGAIN;
+		goto out;
+	}
 
 	req->vf_id = vf_id;
 
@@ -308,7 +326,8 @@ int bnx2x_vfpf_release(struct bnx2x *bp)
 
 	if (rc)
 		/* PF timeout */
-		return rc;
+		goto out;
+
 	if (resp->hdr.status == PFVF_STATUS_SUCCESS) {
 		/* PF released us */
 		DP(BNX2X_MSG_SP, "vf released\n");
@@ -316,10 +335,13 @@ int bnx2x_vfpf_release(struct bnx2x *bp)
 		/* PF reports error */
 		BNX2X_ERR("PF failed our release request - are we out of sync? response status: %d\n",
 			  resp->hdr.status);
-		return -EAGAIN;
+		rc = -EAGAIN;
+		goto out;
 	}
+out:
+	bnx2x_vfpf_finalize(bp, &req->first_tlv);
 
-	return 0;
+	return rc;
 }
 
 /* Tell PF about SB addresses */
@@ -350,16 +372,20 @@ int bnx2x_vfpf_init(struct bnx2x *bp)
 
 	rc = bnx2x_send_msg2pf(bp, &resp->hdr.status, bp->vf2pf_mbox_mapping);
 	if (rc)
-		return rc;
+		goto out;
 
 	if (resp->hdr.status != PFVF_STATUS_SUCCESS) {
 		BNX2X_ERR("INIT VF failed: %d. Breaking...\n",
 			  resp->hdr.status);
-		return -EAGAIN;
+		rc = -EAGAIN;
+		goto out;
 	}
 
 	DP(BNX2X_MSG_SP, "INIT VF Succeeded\n");
-	return 0;
+out:
+	bnx2x_vfpf_finalize(bp, &req->first_tlv);
+
+	return rc;
 }
 
 /* CLOSE VF - opposite to INIT_VF */
@@ -401,6 +427,8 @@ void bnx2x_vfpf_close_vf(struct bnx2x *bp)
 		BNX2X_ERR("Sending CLOSE failed: pf response was %d\n",
 			  resp->hdr.status);
 
+	bnx2x_vfpf_finalize(bp, &req->first_tlv);
+
 free_irq:
 	/* Disable HW interrupts, NAPI */
 	bnx2x_netif_stop(bp, 0);
@@ -435,7 +463,6 @@ int bnx2x_vfpf_setup_q(struct bnx2x *bp, int fp_idx)
 	/* calculate queue flags */
 	flags |= VFPF_QUEUE_FLG_STATS;
 	flags |= VFPF_QUEUE_FLG_CACHE_ALIGN;
-	flags |= IS_MF_SD(bp) ? VFPF_QUEUE_FLG_OV : 0;
 	flags |= VFPF_QUEUE_FLG_VLAN;
 	DP(NETIF_MSG_IFUP, "vlan removal enabled\n");
 
@@ -486,8 +513,11 @@ int bnx2x_vfpf_setup_q(struct bnx2x *bp, int fp_idx)
 	if (resp->hdr.status != PFVF_STATUS_SUCCESS) {
 		BNX2X_ERR("Status of SETUP_Q for queue[%d] is %d\n",
 			  fp_idx, resp->hdr.status);
-		return -EINVAL;
+		rc = -EINVAL;
 	}
+
+	bnx2x_vfpf_finalize(bp, &req->first_tlv);
+
 	return rc;
 }
 
@@ -515,17 +545,19 @@ int bnx2x_vfpf_teardown_queue(struct bnx2x *bp, int qidx)
 	if (rc) {
 		BNX2X_ERR("Sending TEARDOWN for queue %d failed: %d\n", qidx,
 			  rc);
-		return rc;
+		goto out;
 	}
 
 	/* PF failed the transaction */
 	if (resp->hdr.status != PFVF_STATUS_SUCCESS) {
 		BNX2X_ERR("TEARDOWN for queue %d failed: %d\n", qidx,
 			  resp->hdr.status);
-		return -EINVAL;
+		rc = -EINVAL;
 	}
 
-	return 0;
+out:
+	bnx2x_vfpf_finalize(bp, &req->first_tlv);
+	return rc;
 }
 
 /* request pf to add a mac for the vf */
@@ -533,7 +565,7 @@ int bnx2x_vfpf_set_mac(struct bnx2x *bp)
 {
 	struct vfpf_set_q_filters_tlv *req = &bp->vf2pf_mbox->req.set_q_filters;
 	struct pfvf_general_resp_tlv *resp = &bp->vf2pf_mbox->resp.general_resp;
-	int rc;
+	int rc = 0;
 
 	/* clear mailbox and prep first tlv */
 	bnx2x_vfpf_prep(bp, &req->first_tlv, CHANNEL_TLV_SET_Q_FILTERS,
@@ -562,7 +594,7 @@ int bnx2x_vfpf_set_mac(struct bnx2x *bp)
 	rc = bnx2x_send_msg2pf(bp, &resp->hdr.status, bp->vf2pf_mbox_mapping);
 	if (rc) {
 		BNX2X_ERR("failed to send message to pf. rc was %d\n", rc);
-		return rc;
+		goto out;
 	}
 
 	/* failure may mean PF was configured with a new mac for us */
@@ -587,8 +619,10 @@ int bnx2x_vfpf_set_mac(struct bnx2x *bp)
 
 	if (resp->hdr.status != PFVF_STATUS_SUCCESS) {
 		BNX2X_ERR("vfpf SET MAC failed: %d\n", resp->hdr.status);
-		return -EINVAL;
+		rc = -EINVAL;
 	}
+out:
+	bnx2x_vfpf_finalize(bp, &req->first_tlv);
 
 	return 0;
 }
@@ -643,14 +677,16 @@ int bnx2x_vfpf_set_mcast(struct net_device *dev)
 	rc = bnx2x_send_msg2pf(bp, &resp->hdr.status, bp->vf2pf_mbox_mapping);
 	if (rc) {
 		BNX2X_ERR("Sending a message failed: %d\n", rc);
-		return rc;
+		goto out;
 	}
 
 	if (resp->hdr.status != PFVF_STATUS_SUCCESS) {
 		BNX2X_ERR("Set Rx mode/multicast failed: %d\n",
 			  resp->hdr.status);
-		return -EINVAL;
+		rc = -EINVAL;
 	}
+out:
+	bnx2x_vfpf_finalize(bp, &req->first_tlv);
 
 	return 0;
 }
@@ -689,7 +725,8 @@ int bnx2x_vfpf_storm_rx_mode(struct bnx2x *bp)
 		break;
 	default:
 		BNX2X_ERR("BAD rx mode (%d)\n", mode);
-		return -EINVAL;
+		rc = -EINVAL;
+		goto out;
 	}
 
 	req->flags |= VFPF_SET_Q_FILTERS_RX_MASK_CHANGED;
@@ -708,8 +745,10 @@ int bnx2x_vfpf_storm_rx_mode(struct bnx2x *bp)
 
 	if (resp->hdr.status != PFVF_STATUS_SUCCESS) {
 		BNX2X_ERR("Set Rx mode failed: %d\n", resp->hdr.status);
-		return -EINVAL;
+		rc = -EINVAL;
 	}
+out:
+	bnx2x_vfpf_finalize(bp, &req->first_tlv);
 
 	return rc;
 }
@@ -1004,7 +1043,7 @@ static void bnx2x_vf_mbx_init_vf(struct bnx2x *bp, struct bnx2x_virtf *vf,
 }
 
 /* convert MBX queue-flags to standard SP queue-flags */
-static void bnx2x_vf_mbx_set_q_flags(u32 mbx_q_flags,
+static void bnx2x_vf_mbx_set_q_flags(struct bnx2x *bp, u32 mbx_q_flags,
 				     unsigned long *sp_q_flags)
 {
 	if (mbx_q_flags & VFPF_QUEUE_FLG_TPA)
@@ -1015,8 +1054,6 @@ static void bnx2x_vf_mbx_set_q_flags(u32 mbx_q_flags,
 		__set_bit(BNX2X_Q_FLG_TPA_GRO, sp_q_flags);
 	if (mbx_q_flags & VFPF_QUEUE_FLG_STATS)
 		__set_bit(BNX2X_Q_FLG_STATS, sp_q_flags);
-	if (mbx_q_flags & VFPF_QUEUE_FLG_OV)
-		__set_bit(BNX2X_Q_FLG_OV, sp_q_flags);
 	if (mbx_q_flags & VFPF_QUEUE_FLG_VLAN)
 		__set_bit(BNX2X_Q_FLG_VLAN, sp_q_flags);
 	if (mbx_q_flags & VFPF_QUEUE_FLG_COS)
@@ -1025,6 +1062,10 @@ static void bnx2x_vf_mbx_set_q_flags(u32 mbx_q_flags,
 		__set_bit(BNX2X_Q_FLG_HC, sp_q_flags);
 	if (mbx_q_flags & VFPF_QUEUE_FLG_DHC)
 		__set_bit(BNX2X_Q_FLG_DHC, sp_q_flags);
+
+	/* outer vlan removal is set according to the PF's multi fuction mode */
+	if (IS_MF_SD(bp))
+		__set_bit(BNX2X_Q_FLG_OV, sp_q_flags);
 }
 
 static void bnx2x_vf_mbx_setup_q(struct bnx2x *bp, struct bnx2x_virtf *vf,
@@ -1075,11 +1116,11 @@ static void bnx2x_vf_mbx_setup_q(struct bnx2x *bp, struct bnx2x_virtf *vf,
 			init_p->tx.hc_rate = setup_q->txq.hc_rate;
 			init_p->tx.sb_cq_index = setup_q->txq.sb_index;
 
-			bnx2x_vf_mbx_set_q_flags(setup_q->txq.flags,
+			bnx2x_vf_mbx_set_q_flags(bp, setup_q->txq.flags,
 						 &init_p->tx.flags);
 
 			/* tx setup - flags */
-			bnx2x_vf_mbx_set_q_flags(setup_q->txq.flags,
+			bnx2x_vf_mbx_set_q_flags(bp, setup_q->txq.flags,
 						 &setup_p->flags);
 
 			/* tx setup - general, nothing */
@@ -1107,11 +1148,11 @@ static void bnx2x_vf_mbx_setup_q(struct bnx2x *bp, struct bnx2x_virtf *vf,
 			/* rx init */
 			init_p->rx.hc_rate = setup_q->rxq.hc_rate;
 			init_p->rx.sb_cq_index = setup_q->rxq.sb_index;
-			bnx2x_vf_mbx_set_q_flags(setup_q->rxq.flags,
+			bnx2x_vf_mbx_set_q_flags(bp, setup_q->rxq.flags,
 						 &init_p->rx.flags);
 
 			/* rx setup - flags */
-			bnx2x_vf_mbx_set_q_flags(setup_q->rxq.flags,
+			bnx2x_vf_mbx_set_q_flags(bp, setup_q->rxq.flags,
 						 &setup_p->flags);
 
 			/* rx setup - general */
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h
index bfc80ba..41708fa 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h
@@ -328,9 +328,15 @@ struct pf_vf_bulletin_content {
 #define MAC_ADDR_VALID		0	/* alert the vf that a new mac address
 					 * is available for it
 					 */
+#define VLAN_VALID		1	/* when set, the vf should not access
+					 * the vfpf channel
+					 */
 
 	u8 mac[ETH_ALEN];
-	u8 padding[2];
+	u8 mac_padding[2];
+
+	u16 vlan;
+	u8 vlan_padding[6];
 };
 
 union pf_vf_bulletin {
@@ -353,6 +359,7 @@ enum channel_tlvs {
 	CHANNEL_TLV_LIST_END,
 	CHANNEL_TLV_FLR,
 	CHANNEL_TLV_PF_SET_MAC,
+	CHANNEL_TLV_PF_SET_VLAN,
 	CHANNEL_TLV_MAX
 };
 
diff --git a/drivers/net/ethernet/broadcom/cnic.c b/drivers/net/ethernet/broadcom/cnic.c
index 149a3a0..5abdd48 100644
--- a/drivers/net/ethernet/broadcom/cnic.c
+++ b/drivers/net/ethernet/broadcom/cnic.c
@@ -4085,7 +4085,7 @@ static int cnic_cm_alloc_mem(struct cnic_dev *dev)
 	if (!cp->csk_tbl)
 		return -ENOMEM;
 
-	port_id = random32();
+	port_id = prandom_u32();
 	port_id %= CNIC_LOCAL_PORT_RANGE;
 	if (cnic_init_id_tbl(&cp->csk_port_tbl, CNIC_LOCAL_PORT_RANGE,
 			     CNIC_LOCAL_PORT_MIN, port_id)) {
@@ -4145,7 +4145,7 @@ static int cnic_cm_init_bnx2_hw(struct cnic_dev *dev)
 {
 	u32 seed;
 
-	seed = random32();
+	seed = prandom_u32();
 	cnic_ctx_wr(dev, 45, 0, seed);
 	return 0;
 }
diff --git a/drivers/net/ethernet/broadcom/sb1250-mac.c b/drivers/net/ethernet/broadcom/sb1250-mac.c
index e9b35da..e80bfb6 100644
--- a/drivers/net/ethernet/broadcom/sb1250-mac.c
+++ b/drivers/net/ethernet/broadcom/sb1250-mac.c
@@ -831,11 +831,8 @@ static int sbdma_add_rcvbuffer(struct sbmac_softc *sc, struct sbmacdma *d,
 		sb_new = netdev_alloc_skb(dev, ENET_PACKET_SIZE +
 					       SMP_CACHE_BYTES * 2 +
 					       NET_IP_ALIGN);
-		if (sb_new == NULL) {
-			pr_info("%s: sk_buff allocation failed\n",
-			       d->sbdma_eth->sbm_dev->name);
+		if (sb_new == NULL)
 			return -ENOBUFS;
-		}
 
 		sbdma_align_skb(sb_new, SMP_CACHE_BYTES, NET_IP_ALIGN);
 	}
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index 67d2663..a4416b0 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -212,6 +212,7 @@ static inline void _tg3_flag_clear(enum TG3_FLAGS flag, unsigned long *bits)
 #define TG3_FW_UPDATE_FREQ_SEC		(TG3_FW_UPDATE_TIMEOUT_SEC / 2)
 
 #define FIRMWARE_TG3		"tigon/tg3.bin"
+#define FIRMWARE_TG357766	"tigon/tg357766.bin"
 #define FIRMWARE_TG3TSO		"tigon/tg3_tso.bin"
 #define FIRMWARE_TG3TSO5	"tigon/tg3_tso5.bin"
 
@@ -3448,11 +3449,58 @@ static int tg3_nvram_write_block(struct tg3 *tp, u32 offset, u32 len, u8 *buf)
 #define TX_CPU_SCRATCH_SIZE	0x04000
 
 /* tp->lock is held. */
-static int tg3_halt_cpu(struct tg3 *tp, u32 offset)
+static int tg3_pause_cpu(struct tg3 *tp, u32 cpu_base)
 {
 	int i;
+	const int iters = 10000;
 
-	BUG_ON(offset == TX_CPU_BASE && tg3_flag(tp, 5705_PLUS));
+	for (i = 0; i < iters; i++) {
+		tw32(cpu_base + CPU_STATE, 0xffffffff);
+		tw32(cpu_base + CPU_MODE,  CPU_MODE_HALT);
+		if (tr32(cpu_base + CPU_MODE) & CPU_MODE_HALT)
+			break;
+	}
+
+	return (i == iters) ? -EBUSY : 0;
+}
+
+/* tp->lock is held. */
+static int tg3_rxcpu_pause(struct tg3 *tp)
+{
+	int rc = tg3_pause_cpu(tp, RX_CPU_BASE);
+
+	tw32(RX_CPU_BASE + CPU_STATE, 0xffffffff);
+	tw32_f(RX_CPU_BASE + CPU_MODE,  CPU_MODE_HALT);
+	udelay(10);
+
+	return rc;
+}
+
+/* tp->lock is held. */
+static int tg3_txcpu_pause(struct tg3 *tp)
+{
+	return tg3_pause_cpu(tp, TX_CPU_BASE);
+}
+
+/* tp->lock is held. */
+static void tg3_resume_cpu(struct tg3 *tp, u32 cpu_base)
+{
+	tw32(cpu_base + CPU_STATE, 0xffffffff);
+	tw32_f(cpu_base + CPU_MODE,  0x00000000);
+}
+
+/* tp->lock is held. */
+static void tg3_rxcpu_resume(struct tg3 *tp)
+{
+	tg3_resume_cpu(tp, RX_CPU_BASE);
+}
+
+/* tp->lock is held. */
+static int tg3_halt_cpu(struct tg3 *tp, u32 cpu_base)
+{
+	int rc;
+
+	BUG_ON(cpu_base == TX_CPU_BASE && tg3_flag(tp, 5705_PLUS));
 
 	if (tg3_asic_rev(tp) == ASIC_REV_5906) {
 		u32 val = tr32(GRC_VCPU_EXT_CTRL);
@@ -3460,17 +3508,8 @@ static int tg3_halt_cpu(struct tg3 *tp, u32 offset)
 		tw32(GRC_VCPU_EXT_CTRL, val | GRC_VCPU_EXT_CTRL_HALT_CPU);
 		return 0;
 	}
-	if (offset == RX_CPU_BASE) {
-		for (i = 0; i < 10000; i++) {
-			tw32(offset + CPU_STATE, 0xffffffff);
-			tw32(offset + CPU_MODE,  CPU_MODE_HALT);
-			if (tr32(offset + CPU_MODE) & CPU_MODE_HALT)
-				break;
-		}
-
-		tw32(offset + CPU_STATE, 0xffffffff);
-		tw32_f(offset + CPU_MODE,  CPU_MODE_HALT);
-		udelay(10);
+	if (cpu_base == RX_CPU_BASE) {
+		rc = tg3_rxcpu_pause(tp);
 	} else {
 		/*
 		 * There is only an Rx CPU for the 5750 derivative in the
@@ -3479,17 +3518,12 @@ static int tg3_halt_cpu(struct tg3 *tp, u32 offset)
 		if (tg3_flag(tp, IS_SSB_CORE))
 			return 0;
 
-		for (i = 0; i < 10000; i++) {
-			tw32(offset + CPU_STATE, 0xffffffff);
-			tw32(offset + CPU_MODE,  CPU_MODE_HALT);
-			if (tr32(offset + CPU_MODE) & CPU_MODE_HALT)
-				break;
-		}
+		rc = tg3_txcpu_pause(tp);
 	}
 
-	if (i >= 10000) {
+	if (rc) {
 		netdev_err(tp->dev, "%s timed out, %s CPU\n",
-			   __func__, offset == RX_CPU_BASE ? "RX" : "TX");
+			   __func__, cpu_base == RX_CPU_BASE ? "RX" : "TX");
 		return -ENODEV;
 	}
 
@@ -3499,19 +3533,41 @@ static int tg3_halt_cpu(struct tg3 *tp, u32 offset)
 	return 0;
 }
 
-struct fw_info {
-	unsigned int fw_base;
-	unsigned int fw_len;
-	const __be32 *fw_data;
-};
+static int tg3_fw_data_len(struct tg3 *tp,
+			   const struct tg3_firmware_hdr *fw_hdr)
+{
+	int fw_len;
+
+	/* Non fragmented firmware have one firmware header followed by a
+	 * contiguous chunk of data to be written. The length field in that
+	 * header is not the length of data to be written but the complete
+	 * length of the bss. The data length is determined based on
+	 * tp->fw->size minus headers.
+	 *
+	 * Fragmented firmware have a main header followed by multiple
+	 * fragments. Each fragment is identical to non fragmented firmware
+	 * with a firmware header followed by a contiguous chunk of data. In
+	 * the main header, the length field is unused and set to 0xffffffff.
+	 * In each fragment header the length is the entire size of that
+	 * fragment i.e. fragment data + header length. Data length is
+	 * therefore length field in the header minus TG3_FW_HDR_LEN.
+	 */
+	if (tp->fw_len == 0xffffffff)
+		fw_len = be32_to_cpu(fw_hdr->len);
+	else
+		fw_len = tp->fw->size;
+
+	return (fw_len - TG3_FW_HDR_LEN) / sizeof(u32);
+}
 
 /* tp->lock is held. */
 static int tg3_load_firmware_cpu(struct tg3 *tp, u32 cpu_base,
 				 u32 cpu_scratch_base, int cpu_scratch_size,
-				 struct fw_info *info)
+				 const struct tg3_firmware_hdr *fw_hdr)
 {
-	int err, lock_err, i;
+	int err, i;
 	void (*write_op)(struct tg3 *, u32, u32);
+	int total_len = tp->fw->size;
 
 	if (cpu_base == TX_CPU_BASE && tg3_flag(tp, 5705_PLUS)) {
 		netdev_err(tp->dev,
@@ -3520,30 +3576,49 @@ static int tg3_load_firmware_cpu(struct tg3 *tp, u32 cpu_base,
 		return -EINVAL;
 	}
 
-	if (tg3_flag(tp, 5705_PLUS))
+	if (tg3_flag(tp, 5705_PLUS) && tg3_asic_rev(tp) != ASIC_REV_57766)
 		write_op = tg3_write_mem;
 	else
 		write_op = tg3_write_indirect_reg32;
 
-	/* It is possible that bootcode is still loading at this point.
-	 * Get the nvram lock first before halting the cpu.
-	 */
-	lock_err = tg3_nvram_lock(tp);
-	err = tg3_halt_cpu(tp, cpu_base);
-	if (!lock_err)
-		tg3_nvram_unlock(tp);
-	if (err)
-		goto out;
+	if (tg3_asic_rev(tp) != ASIC_REV_57766) {
+		/* It is possible that bootcode is still loading at this point.
+		 * Get the nvram lock first before halting the cpu.
+		 */
+		int lock_err = tg3_nvram_lock(tp);
+		err = tg3_halt_cpu(tp, cpu_base);
+		if (!lock_err)
+			tg3_nvram_unlock(tp);
+		if (err)
+			goto out;
 
-	for (i = 0; i < cpu_scratch_size; i += sizeof(u32))
-		write_op(tp, cpu_scratch_base + i, 0);
-	tw32(cpu_base + CPU_STATE, 0xffffffff);
-	tw32(cpu_base + CPU_MODE, tr32(cpu_base+CPU_MODE)|CPU_MODE_HALT);
-	for (i = 0; i < (info->fw_len / sizeof(u32)); i++)
-		write_op(tp, (cpu_scratch_base +
-			      (info->fw_base & 0xffff) +
-			      (i * sizeof(u32))),
-			      be32_to_cpu(info->fw_data[i]));
+		for (i = 0; i < cpu_scratch_size; i += sizeof(u32))
+			write_op(tp, cpu_scratch_base + i, 0);
+		tw32(cpu_base + CPU_STATE, 0xffffffff);
+		tw32(cpu_base + CPU_MODE,
+		     tr32(cpu_base + CPU_MODE) | CPU_MODE_HALT);
+	} else {
+		/* Subtract additional main header for fragmented firmware and
+		 * advance to the first fragment
+		 */
+		total_len -= TG3_FW_HDR_LEN;
+		fw_hdr++;
+	}
+
+	do {
+		u32 *fw_data = (u32 *)(fw_hdr + 1);
+		for (i = 0; i < tg3_fw_data_len(tp, fw_hdr); i++)
+			write_op(tp, cpu_scratch_base +
+				     (be32_to_cpu(fw_hdr->base_addr) & 0xffff) +
+				     (i * sizeof(u32)),
+				 be32_to_cpu(fw_data[i]));
+
+		total_len -= be32_to_cpu(fw_hdr->len);
+
+		/* Advance to next fragment */
+		fw_hdr = (struct tg3_firmware_hdr *)
+			 ((void *)fw_hdr + be32_to_cpu(fw_hdr->len));
+	} while (total_len > 0);
 
 	err = 0;
 
@@ -3552,13 +3627,33 @@ out:
 }
 
 /* tp->lock is held. */
+static int tg3_pause_cpu_and_set_pc(struct tg3 *tp, u32 cpu_base, u32 pc)
+{
+	int i;
+	const int iters = 5;
+
+	tw32(cpu_base + CPU_STATE, 0xffffffff);
+	tw32_f(cpu_base + CPU_PC, pc);
+
+	for (i = 0; i < iters; i++) {
+		if (tr32(cpu_base + CPU_PC) == pc)
+			break;
+		tw32(cpu_base + CPU_STATE, 0xffffffff);
+		tw32(cpu_base + CPU_MODE,  CPU_MODE_HALT);
+		tw32_f(cpu_base + CPU_PC, pc);
+		udelay(1000);
+	}
+
+	return (i == iters) ? -EBUSY : 0;
+}
+
+/* tp->lock is held. */
 static int tg3_load_5701_a0_firmware_fix(struct tg3 *tp)
 {
-	struct fw_info info;
-	const __be32 *fw_data;
-	int err, i;
+	const struct tg3_firmware_hdr *fw_hdr;
+	int err;
 
-	fw_data = (void *)tp->fw->data;
+	fw_hdr = (struct tg3_firmware_hdr *)tp->fw->data;
 
 	/* Firmware blob starts with version numbers, followed by
 	   start address and length. We are setting complete length.
@@ -3566,60 +3661,117 @@ static int tg3_load_5701_a0_firmware_fix(struct tg3 *tp)
 	   Remainder is the blob to be loaded contiguously
 	   from start address. */
 
-	info.fw_base = be32_to_cpu(fw_data[1]);
-	info.fw_len = tp->fw->size - 12;
-	info.fw_data = &fw_data[3];
-
 	err = tg3_load_firmware_cpu(tp, RX_CPU_BASE,
 				    RX_CPU_SCRATCH_BASE, RX_CPU_SCRATCH_SIZE,
-				    &info);
+				    fw_hdr);
 	if (err)
 		return err;
 
 	err = tg3_load_firmware_cpu(tp, TX_CPU_BASE,
 				    TX_CPU_SCRATCH_BASE, TX_CPU_SCRATCH_SIZE,
-				    &info);
+				    fw_hdr);
 	if (err)
 		return err;
 
 	/* Now startup only the RX cpu. */
-	tw32(RX_CPU_BASE + CPU_STATE, 0xffffffff);
-	tw32_f(RX_CPU_BASE + CPU_PC, info.fw_base);
-
-	for (i = 0; i < 5; i++) {
-		if (tr32(RX_CPU_BASE + CPU_PC) == info.fw_base)
-			break;
-		tw32(RX_CPU_BASE + CPU_STATE, 0xffffffff);
-		tw32(RX_CPU_BASE + CPU_MODE,  CPU_MODE_HALT);
-		tw32_f(RX_CPU_BASE + CPU_PC, info.fw_base);
-		udelay(1000);
-	}
-	if (i >= 5) {
+	err = tg3_pause_cpu_and_set_pc(tp, RX_CPU_BASE,
+				       be32_to_cpu(fw_hdr->base_addr));
+	if (err) {
 		netdev_err(tp->dev, "%s fails to set RX CPU PC, is %08x "
 			   "should be %08x\n", __func__,
-			   tr32(RX_CPU_BASE + CPU_PC), info.fw_base);
+			   tr32(RX_CPU_BASE + CPU_PC),
+				be32_to_cpu(fw_hdr->base_addr));
 		return -ENODEV;
 	}
-	tw32(RX_CPU_BASE + CPU_STATE, 0xffffffff);
-	tw32_f(RX_CPU_BASE + CPU_MODE,  0x00000000);
+
+	tg3_rxcpu_resume(tp);
+
+	return 0;
+}
+
+static int tg3_validate_rxcpu_state(struct tg3 *tp)
+{
+	const int iters = 1000;
+	int i;
+	u32 val;
+
+	/* Wait for boot code to complete initialization and enter service
+	 * loop. It is then safe to download service patches
+	 */
+	for (i = 0; i < iters; i++) {
+		if (tr32(RX_CPU_HWBKPT) == TG3_SBROM_IN_SERVICE_LOOP)
+			break;
+
+		udelay(10);
+	}
+
+	if (i == iters) {
+		netdev_err(tp->dev, "Boot code not ready for service patches\n");
+		return -EBUSY;
+	}
+
+	val = tg3_read_indirect_reg32(tp, TG3_57766_FW_HANDSHAKE);
+	if (val & 0xff) {
+		netdev_warn(tp->dev,
+			    "Other patches exist. Not downloading EEE patch\n");
+		return -EEXIST;
+	}
 
 	return 0;
 }
 
 /* tp->lock is held. */
+static void tg3_load_57766_firmware(struct tg3 *tp)
+{
+	struct tg3_firmware_hdr *fw_hdr;
+
+	if (!tg3_flag(tp, NO_NVRAM))
+		return;
+
+	if (tg3_validate_rxcpu_state(tp))
+		return;
+
+	if (!tp->fw)
+		return;
+
+	/* This firmware blob has a different format than older firmware
+	 * releases as given below. The main difference is we have fragmented
+	 * data to be written to non-contiguous locations.
+	 *
+	 * In the beginning we have a firmware header identical to other
+	 * firmware which consists of version, base addr and length. The length
+	 * here is unused and set to 0xffffffff.
+	 *
+	 * This is followed by a series of firmware fragments which are
+	 * individually identical to previous firmware. i.e. they have the
+	 * firmware header and followed by data for that fragment. The version
+	 * field of the individual fragment header is unused.
+	 */
+
+	fw_hdr = (struct tg3_firmware_hdr *)tp->fw->data;
+	if (be32_to_cpu(fw_hdr->base_addr) != TG3_57766_FW_BASE_ADDR)
+		return;
+
+	if (tg3_rxcpu_pause(tp))
+		return;
+
+	/* tg3_load_firmware_cpu() will always succeed for the 57766 */
+	tg3_load_firmware_cpu(tp, 0, TG3_57766_FW_BASE_ADDR, 0, fw_hdr);
+
+	tg3_rxcpu_resume(tp);
+}
+
+/* tp->lock is held. */
 static int tg3_load_tso_firmware(struct tg3 *tp)
 {
-	struct fw_info info;
-	const __be32 *fw_data;
+	const struct tg3_firmware_hdr *fw_hdr;
 	unsigned long cpu_base, cpu_scratch_base, cpu_scratch_size;
-	int err, i;
+	int err;
 
-	if (tg3_flag(tp, HW_TSO_1) ||
-	    tg3_flag(tp, HW_TSO_2) ||
-	    tg3_flag(tp, HW_TSO_3))
+	if (!tg3_flag(tp, FW_TSO))
 		return 0;
 
-	fw_data = (void *)tp->fw->data;
+	fw_hdr = (struct tg3_firmware_hdr *)tp->fw->data;
 
 	/* Firmware blob starts with version numbers, followed by
 	   start address and length. We are setting complete length.
@@ -3627,10 +3779,7 @@ static int tg3_load_tso_firmware(struct tg3 *tp)
 	   Remainder is the blob to be loaded contiguously
 	   from start address. */
 
-	info.fw_base = be32_to_cpu(fw_data[1]);
 	cpu_scratch_size = tp->fw_len;
-	info.fw_len = tp->fw->size - 12;
-	info.fw_data = &fw_data[3];
 
 	if (tg3_asic_rev(tp) == ASIC_REV_5705) {
 		cpu_base = RX_CPU_BASE;
@@ -3643,30 +3792,22 @@ static int tg3_load_tso_firmware(struct tg3 *tp)
 
 	err = tg3_load_firmware_cpu(tp, cpu_base,
 				    cpu_scratch_base, cpu_scratch_size,
-				    &info);
+				    fw_hdr);
 	if (err)
 		return err;
 
 	/* Now startup the cpu. */
-	tw32(cpu_base + CPU_STATE, 0xffffffff);
-	tw32_f(cpu_base + CPU_PC, info.fw_base);
-
-	for (i = 0; i < 5; i++) {
-		if (tr32(cpu_base + CPU_PC) == info.fw_base)
-			break;
-		tw32(cpu_base + CPU_STATE, 0xffffffff);
-		tw32(cpu_base + CPU_MODE,  CPU_MODE_HALT);
-		tw32_f(cpu_base + CPU_PC, info.fw_base);
-		udelay(1000);
-	}
-	if (i >= 5) {
+	err = tg3_pause_cpu_and_set_pc(tp, cpu_base,
+				       be32_to_cpu(fw_hdr->base_addr));
+	if (err) {
 		netdev_err(tp->dev,
 			   "%s fails to set CPU PC, is %08x should be %08x\n",
-			   __func__, tr32(cpu_base + CPU_PC), info.fw_base);
+			   __func__, tr32(cpu_base + CPU_PC),
+			   be32_to_cpu(fw_hdr->base_addr));
 		return -ENODEV;
 	}
-	tw32(cpu_base + CPU_STATE, 0xffffffff);
-	tw32_f(cpu_base + CPU_MODE,  0x00000000);
+
+	tg3_resume_cpu(tp, cpu_base);
 	return 0;
 }
 
@@ -8039,11 +8180,9 @@ static int tg3_mem_rx_acquire(struct tg3 *tp)
 		tnapi->rx_rcb = dma_alloc_coherent(&tp->pdev->dev,
 						   TG3_RX_RCB_RING_BYTES(tp),
 						   &tnapi->rx_rcb_mapping,
-						   GFP_KERNEL);
+						   GFP_KERNEL | __GFP_ZERO);
 		if (!tnapi->rx_rcb)
 			goto err_out;
-
-		memset(tnapi->rx_rcb, 0, TG3_RX_RCB_RING_BYTES(tp));
 	}
 
 	return 0;
@@ -8093,12 +8232,10 @@ static int tg3_alloc_consistent(struct tg3 *tp)
 	tp->hw_stats = dma_alloc_coherent(&tp->pdev->dev,
 					  sizeof(struct tg3_hw_stats),
 					  &tp->stats_mapping,
-					  GFP_KERNEL);
+					  GFP_KERNEL | __GFP_ZERO);
 	if (!tp->hw_stats)
 		goto err_out;
 
-	memset(tp->hw_stats, 0, sizeof(struct tg3_hw_stats));
-
 	for (i = 0; i < tp->irq_cnt; i++) {
 		struct tg3_napi *tnapi = &tp->napi[i];
 		struct tg3_hw_status *sblk;
@@ -8106,11 +8243,10 @@ static int tg3_alloc_consistent(struct tg3 *tp)
 		tnapi->hw_status = dma_alloc_coherent(&tp->pdev->dev,
 						      TG3_HW_STATUS_SIZE,
 						      &tnapi->status_mapping,
-						      GFP_KERNEL);
+						      GFP_KERNEL | __GFP_ZERO);
 		if (!tnapi->hw_status)
 			goto err_out;
 
-		memset(tnapi->hw_status, 0, TG3_HW_STATUS_SIZE);
 		sblk = tnapi->hw_status;
 
 		if (tg3_flag(tp, ENABLE_RSS)) {
@@ -9781,6 +9917,13 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
 			return err;
 	}
 
+	if (tg3_asic_rev(tp) == ASIC_REV_57766) {
+		/* Ignore any errors for the firmware download. If download
+		 * fails, the device will operate with EEE disabled
+		 */
+		tg3_load_57766_firmware(tp);
+	}
+
 	if (tg3_flag(tp, TSO_CAPABLE)) {
 		err = tg3_load_tso_firmware(tp);
 		if (err)
@@ -10570,7 +10713,7 @@ static int tg3_test_msi(struct tg3 *tp)
 
 static int tg3_request_firmware(struct tg3 *tp)
 {
-	const __be32 *fw_data;
+	const struct tg3_firmware_hdr *fw_hdr;
 
 	if (request_firmware(&tp->fw, tp->fw_needed, &tp->pdev->dev)) {
 		netdev_err(tp->dev, "Failed to load firmware \"%s\"\n",
@@ -10578,15 +10721,15 @@ static int tg3_request_firmware(struct tg3 *tp)
 		return -ENOENT;
 	}
 
-	fw_data = (void *)tp->fw->data;
+	fw_hdr = (struct tg3_firmware_hdr *)tp->fw->data;
 
 	/* Firmware blob starts with version numbers, followed by
 	 * start address and _full_ length including BSS sections
 	 * (which must be longer than the actual data, of course
 	 */
 
-	tp->fw_len = be32_to_cpu(fw_data[2]);	/* includes bss */
-	if (tp->fw_len < (tp->fw->size - 12)) {
+	tp->fw_len = be32_to_cpu(fw_hdr->len);	/* includes bss */
+	if (tp->fw_len < (tp->fw->size - TG3_FW_HDR_LEN)) {
 		netdev_err(tp->dev, "bogus length %d in \"%s\"\n",
 			   tp->fw_len, tp->fw_needed);
 		release_firmware(tp->fw);
@@ -10885,7 +11028,15 @@ static int tg3_open(struct net_device *dev)
 
 	if (tp->fw_needed) {
 		err = tg3_request_firmware(tp);
-		if (tg3_chip_rev_id(tp) == CHIPREV_ID_5701_A0) {
+		if (tg3_asic_rev(tp) == ASIC_REV_57766) {
+			if (err) {
+				netdev_warn(tp->dev, "EEE capability disabled\n");
+				tp->phy_flags &= ~TG3_PHYFLG_EEE_CAP;
+			} else if (!(tp->phy_flags & TG3_PHYFLG_EEE_CAP)) {
+				netdev_warn(tp->dev, "EEE capability restored\n");
+				tp->phy_flags |= TG3_PHYFLG_EEE_CAP;
+			}
+		} else if (tg3_chip_rev_id(tp) == CHIPREV_ID_5701_A0) {
 			if (err)
 				return err;
 		} else if (err) {
@@ -14515,6 +14666,7 @@ static int tg3_phy_probe(struct tg3 *tp)
 	if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES) &&
 	    (tg3_asic_rev(tp) == ASIC_REV_5719 ||
 	     tg3_asic_rev(tp) == ASIC_REV_5720 ||
+	     tg3_asic_rev(tp) == ASIC_REV_57766 ||
 	     tg3_asic_rev(tp) == ASIC_REV_5762 ||
 	     (tg3_asic_rev(tp) == ASIC_REV_5717 &&
 	      tg3_chip_rev_id(tp) != CHIPREV_ID_5717_A0) ||
@@ -14604,8 +14756,11 @@ static void tg3_read_vpd(struct tg3 *tp)
 		if (j + len > block_end)
 			goto partno;
 
-		memcpy(tp->fw_ver, &vpd_data[j], len);
-		strncat(tp->fw_ver, " bc ", vpdlen - len - 1);
+		if (len >= sizeof(tp->fw_ver))
+			len = sizeof(tp->fw_ver) - 1;
+		memset(tp->fw_ver, 0, sizeof(tp->fw_ver));
+		snprintf(tp->fw_ver, sizeof(tp->fw_ver), "%.*s bc ", len,
+			 &vpd_data[j]);
 	}
 
 partno:
@@ -15297,7 +15452,8 @@ static int tg3_get_invariants(struct tg3 *tp, const struct pci_device_id *ent)
 	} else if (tg3_asic_rev(tp) != ASIC_REV_5700 &&
 		   tg3_asic_rev(tp) != ASIC_REV_5701 &&
 		   tg3_chip_rev_id(tp) != CHIPREV_ID_5705_A0) {
-			tg3_flag_set(tp, TSO_BUG);
+		tg3_flag_set(tp, FW_TSO);
+		tg3_flag_set(tp, TSO_BUG);
 		if (tg3_asic_rev(tp) == ASIC_REV_5705)
 			tp->fw_needed = FIRMWARE_TG3TSO5;
 		else
@@ -15308,7 +15464,7 @@ static int tg3_get_invariants(struct tg3 *tp, const struct pci_device_id *ent)
 	if (tg3_flag(tp, HW_TSO_1) ||
 	    tg3_flag(tp, HW_TSO_2) ||
 	    tg3_flag(tp, HW_TSO_3) ||
-	    tp->fw_needed) {
+	    tg3_flag(tp, FW_TSO)) {
 		/* For firmware TSO, assume ASF is disabled.
 		 * We'll disable TSO later if we discover ASF
 		 * is enabled in tg3_get_eeprom_hw_cfg().
@@ -15323,6 +15479,9 @@ static int tg3_get_invariants(struct tg3 *tp, const struct pci_device_id *ent)
 	if (tg3_chip_rev_id(tp) == CHIPREV_ID_5701_A0)
 		tp->fw_needed = FIRMWARE_TG3;
 
+	if (tg3_asic_rev(tp) == ASIC_REV_57766)
+		tp->fw_needed = FIRMWARE_TG357766;
+
 	tp->irq_max = 1;
 
 	if (tg3_flag(tp, 5750_PLUS)) {
@@ -15595,7 +15754,7 @@ static int tg3_get_invariants(struct tg3 *tp, const struct pci_device_id *ent)
 	 */
 	tg3_get_eeprom_hw_cfg(tp);
 
-	if (tp->fw_needed && tg3_flag(tp, ENABLE_ASF)) {
+	if (tg3_flag(tp, FW_TSO) && tg3_flag(tp, ENABLE_ASF)) {
 		tg3_flag_clear(tp, TSO_CAPABLE);
 		tg3_flag_clear(tp, TSO_BUG);
 		tp->fw_needed = NULL;
@@ -15783,6 +15942,11 @@ static int tg3_get_invariants(struct tg3 *tp, const struct pci_device_id *ent)
 	udelay(50);
 	tg3_nvram_init(tp);
 
+	/* If the device has an NVRAM, no need to load patch firmware */
+	if (tg3_asic_rev(tp) == ASIC_REV_57766 &&
+	    !tg3_flag(tp, NO_NVRAM))
+		tp->fw_needed = NULL;
+
 	grc_misc_cfg = tr32(GRC_MISC_CFG);
 	grc_misc_cfg &= GRC_MISC_CFG_BOARD_ID_MASK;
 
diff --git a/drivers/net/ethernet/broadcom/tg3.h b/drivers/net/ethernet/broadcom/tg3.h
index 8d7d4c2..1cdc1b6 100644
--- a/drivers/net/ethernet/broadcom/tg3.h
+++ b/drivers/net/ethernet/broadcom/tg3.h
@@ -2222,6 +2222,12 @@
 #define  NIC_SRAM_MBUF_POOL_BASE5705	0x00010000
 #define  NIC_SRAM_MBUF_POOL_SIZE5705	0x0000e000
 
+#define TG3_SRAM_RXCPU_SCRATCH_BASE_57766	0x00030000
+#define  TG3_SRAM_RXCPU_SCRATCH_SIZE_57766	 0x00010000
+#define TG3_57766_FW_BASE_ADDR			0x00030000
+#define TG3_57766_FW_HANDSHAKE			0x0003fccc
+#define TG3_SBROM_IN_SERVICE_LOOP		0x51
+
 #define TG3_SRAM_RX_STD_BDCACHE_SIZE_5700	128
 #define TG3_SRAM_RX_STD_BDCACHE_SIZE_5755	64
 #define TG3_SRAM_RX_STD_BDCACHE_SIZE_5906	32
@@ -3009,17 +3015,18 @@ enum TG3_FLAGS {
 	TG3_FLAG_JUMBO_CAPABLE,
 	TG3_FLAG_CHIP_RESETTING,
 	TG3_FLAG_INIT_COMPLETE,
-	TG3_FLAG_TSO_BUG,
 	TG3_FLAG_MAX_RXPEND_64,
-	TG3_FLAG_TSO_CAPABLE,
 	TG3_FLAG_PCI_EXPRESS, /* BCM5785 + pci_is_pcie() */
 	TG3_FLAG_ASF_NEW_HANDSHAKE,
 	TG3_FLAG_HW_AUTONEG,
 	TG3_FLAG_IS_NIC,
 	TG3_FLAG_FLASH,
+	TG3_FLAG_FW_TSO,
 	TG3_FLAG_HW_TSO_1,
 	TG3_FLAG_HW_TSO_2,
 	TG3_FLAG_HW_TSO_3,
+	TG3_FLAG_TSO_CAPABLE,
+	TG3_FLAG_TSO_BUG,
 	TG3_FLAG_ICH_WORKAROUND,
 	TG3_FLAG_1SHOT_MSI,
 	TG3_FLAG_NO_FWARE_REPORTED,
@@ -3064,6 +3071,13 @@ enum TG3_FLAGS {
 	TG3_FLAG_NUMBER_OF_FLAGS,	/* Last entry in enum TG3_FLAGS */
 };
 
+struct tg3_firmware_hdr {
+	__be32 version; /* unused for fragments */
+	__be32 base_addr;
+	__be32 len;
+};
+#define TG3_FW_HDR_LEN         (sizeof(struct tg3_firmware_hdr))
+
 struct tg3 {
 	/* begin "general, frequently-used members" cacheline section */
 
diff --git a/drivers/net/ethernet/brocade/bna/bfa_ioc.c b/drivers/net/ethernet/brocade/bna/bfa_ioc.c
index 3227fdd..f2b73ff 100644
--- a/drivers/net/ethernet/brocade/bna/bfa_ioc.c
+++ b/drivers/net/ethernet/brocade/bna/bfa_ioc.c
@@ -76,7 +76,7 @@ static void bfa_ioc_pf_disabled(struct bfa_ioc *ioc);
 static void bfa_ioc_pf_failed(struct bfa_ioc *ioc);
 static void bfa_ioc_pf_hwfailed(struct bfa_ioc *ioc);
 static void bfa_ioc_pf_fwmismatch(struct bfa_ioc *ioc);
-static void bfa_ioc_boot(struct bfa_ioc *ioc, u32 boot_type,
+static void bfa_ioc_boot(struct bfa_ioc *ioc, enum bfi_fwboot_type boot_type,
 			 u32 boot_param);
 static u32 bfa_ioc_smem_pgnum(struct bfa_ioc *ioc, u32 fmaddr);
 static void bfa_ioc_get_adapter_serial_num(struct bfa_ioc *ioc,
diff --git a/drivers/net/ethernet/brocade/bna/bnad.c b/drivers/net/ethernet/brocade/bna/bnad.c
index 7cce42d..d588f84 100644
--- a/drivers/net/ethernet/brocade/bna/bnad.c
+++ b/drivers/net/ethernet/brocade/bna/bnad.c
@@ -1264,9 +1264,8 @@ bnad_mem_alloc(struct bnad *bnad,
 			mem_info->mdl[i].len = mem_info->len;
 			mem_info->mdl[i].kva =
 				dma_alloc_coherent(&bnad->pcidev->dev,
-						mem_info->len, &dma_pa,
-						GFP_KERNEL);
-
+						   mem_info->len, &dma_pa,
+						   GFP_KERNEL);
 			if (mem_info->mdl[i].kva == NULL)
 				goto err_return;
 
diff --git a/drivers/net/ethernet/cadence/at91_ether.c b/drivers/net/ethernet/cadence/at91_ether.c
index 3becdb2..a5f499f 100644
--- a/drivers/net/ethernet/cadence/at91_ether.c
+++ b/drivers/net/ethernet/cadence/at91_ether.c
@@ -47,22 +47,19 @@ static int at91ether_start(struct net_device *dev)
 	int i;
 
 	lp->rx_ring = dma_alloc_coherent(&lp->pdev->dev,
-					MAX_RX_DESCR * sizeof(struct macb_dma_desc),
-					&lp->rx_ring_dma, GFP_KERNEL);
-	if (!lp->rx_ring) {
-		netdev_err(dev, "unable to alloc rx ring DMA buffer\n");
+					 (MAX_RX_DESCR *
+					  sizeof(struct macb_dma_desc)),
+					 &lp->rx_ring_dma, GFP_KERNEL);
+	if (!lp->rx_ring)
 		return -ENOMEM;
-	}
 
 	lp->rx_buffers = dma_alloc_coherent(&lp->pdev->dev,
-					MAX_RX_DESCR * MAX_RBUFF_SZ,
-					&lp->rx_buffers_dma, GFP_KERNEL);
+					    MAX_RX_DESCR * MAX_RBUFF_SZ,
+					    &lp->rx_buffers_dma, GFP_KERNEL);
 	if (!lp->rx_buffers) {
-		netdev_err(dev, "unable to alloc rx data DMA buffer\n");
-
 		dma_free_coherent(&lp->pdev->dev,
-					MAX_RX_DESCR * sizeof(struct macb_dma_desc),
-					lp->rx_ring, lp->rx_ring_dma);
+				  MAX_RX_DESCR * sizeof(struct macb_dma_desc),
+				  lp->rx_ring, lp->rx_ring_dma);
 		lp->rx_ring = NULL;
 		return -ENOMEM;
 	}
@@ -209,7 +206,6 @@ static void at91ether_rx(struct net_device *dev)
 			netif_rx(skb);
 		} else {
 			lp->stats.rx_dropped++;
-			netdev_notice(dev, "Memory squeeze, dropping packet.\n");
 		}
 
 		if (lp->rx_ring[lp->rx_tail].ctrl & MACB_BIT(RX_MHASH_MATCH))
@@ -303,42 +299,7 @@ static const struct of_device_id at91ether_dt_ids[] = {
 	{ .compatible = "cdns,emac" },
 	{ /* sentinel */ }
 };
-
 MODULE_DEVICE_TABLE(of, at91ether_dt_ids);
-
-static int at91ether_get_phy_mode_dt(struct platform_device *pdev)
-{
-	struct device_node *np = pdev->dev.of_node;
-
-	if (np)
-		return of_get_phy_mode(np);
-
-	return -ENODEV;
-}
-
-static int at91ether_get_hwaddr_dt(struct macb *bp)
-{
-	struct device_node *np = bp->pdev->dev.of_node;
-
-	if (np) {
-		const char *mac = of_get_mac_address(np);
-		if (mac) {
-			memcpy(bp->dev->dev_addr, mac, ETH_ALEN);
-			return 0;
-		}
-	}
-
-	return -ENODEV;
-}
-#else
-static int at91ether_get_phy_mode_dt(struct platform_device *pdev)
-{
-	return -ENODEV;
-}
-static int at91ether_get_hwaddr_dt(struct macb *bp)
-{
-	return -ENODEV;
-}
 #endif
 
 /* Detect MAC & PHY and perform ethernet interface initialization */
@@ -352,6 +313,7 @@ static int __init at91ether_probe(struct platform_device *pdev)
 	struct macb *lp;
 	int res;
 	u32 reg;
+	const char *mac;
 
 	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!regs)
@@ -403,11 +365,13 @@ static int __init at91ether_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, dev);
 	SET_NETDEV_DEV(dev, &pdev->dev);
 
-	res = at91ether_get_hwaddr_dt(lp);
-	if (res < 0)
+	mac = of_get_mac_address(pdev->dev.of_node);
+	if (mac)
+		memcpy(lp->dev->dev_addr, mac, ETH_ALEN);
+	else
 		macb_get_hwaddr(lp);
 
-	res = at91ether_get_phy_mode_dt(pdev);
+	res = of_get_phy_mode(pdev->dev.of_node);
 	if (res < 0) {
 		if (board_data && board_data->is_rmii)
 			lp->phy_interface = PHY_INTERFACE_MODE_RMII;
@@ -519,18 +483,7 @@ static struct platform_driver at91ether_driver = {
 	},
 };
 
-static int __init at91ether_init(void)
-{
-	return platform_driver_probe(&at91ether_driver, at91ether_probe);
-}
-
-static void __exit at91ether_exit(void)
-{
-	platform_driver_unregister(&at91ether_driver);
-}
-
-module_init(at91ether_init)
-module_exit(at91ether_exit)
+module_platform_driver_probe(at91ether_driver, at91ether_probe);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("AT91RM9200 EMAC Ethernet driver");
diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c
index 7903943..7fd0e3e 100644
--- a/drivers/net/ethernet/cadence/macb.c
+++ b/drivers/net/ethernet/cadence/macb.c
@@ -485,6 +485,8 @@ static void macb_tx_interrupt(struct macb *bp)
 	status = macb_readl(bp, TSR);
 	macb_writel(bp, TSR, status);
 
+	macb_writel(bp, ISR, MACB_BIT(TCOMP));
+
 	netdev_vdbg(bp->dev, "macb_tx_interrupt status = 0x%03lx\n",
 		(unsigned long)status);
 
@@ -736,6 +738,7 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id)
 			 * now.
 			 */
 			macb_writel(bp, IDR, MACB_RX_INT_FLAGS);
+			macb_writel(bp, ISR, MACB_BIT(RCOMP));
 
 			if (napi_schedule_prep(&bp->napi)) {
 				netdev_vdbg(bp->dev, "scheduling RX softirq\n");
@@ -1054,6 +1057,7 @@ static void macb_configure_dma(struct macb *bp)
 		dmacfg |= GEM_BF(RXBS, RX_BUFFER_SIZE / 64);
 		dmacfg |= GEM_BF(FBLDO, 16);
 		dmacfg |= GEM_BIT(TXPBMS) | GEM_BF(RXBMS, -1L);
+		dmacfg &= ~GEM_BIT(ENDIA);
 		gem_writel(bp, DMACFG, dmacfg);
 	}
 }
@@ -1472,41 +1476,7 @@ static const struct of_device_id macb_dt_ids[] = {
 	{ .compatible = "cdns,gem" },
 	{ /* sentinel */ }
 };
-
 MODULE_DEVICE_TABLE(of, macb_dt_ids);
-
-static int macb_get_phy_mode_dt(struct platform_device *pdev)
-{
-	struct device_node *np = pdev->dev.of_node;
-
-	if (np)
-		return of_get_phy_mode(np);
-
-	return -ENODEV;
-}
-
-static int macb_get_hwaddr_dt(struct macb *bp)
-{
-	struct device_node *np = bp->pdev->dev.of_node;
-	if (np) {
-		const char *mac = of_get_mac_address(np);
-		if (mac) {
-			memcpy(bp->dev->dev_addr, mac, ETH_ALEN);
-			return 0;
-		}
-	}
-
-	return -ENODEV;
-}
-#else
-static int macb_get_phy_mode_dt(struct platform_device *pdev)
-{
-	return -ENODEV;
-}
-static int macb_get_hwaddr_dt(struct macb *bp)
-{
-	return -ENODEV;
-}
 #endif
 
 static int __init macb_probe(struct platform_device *pdev)
@@ -1519,6 +1489,7 @@ static int __init macb_probe(struct platform_device *pdev)
 	u32 config;
 	int err = -ENXIO;
 	struct pinctrl *pinctrl;
+	const char *mac;
 
 	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!regs) {
@@ -1557,14 +1528,14 @@ static int __init macb_probe(struct platform_device *pdev)
 		dev_err(&pdev->dev, "failed to get macb_clk\n");
 		goto err_out_free_dev;
 	}
-	clk_enable(bp->pclk);
+	clk_prepare_enable(bp->pclk);
 
 	bp->hclk = clk_get(&pdev->dev, "hclk");
 	if (IS_ERR(bp->hclk)) {
 		dev_err(&pdev->dev, "failed to get hclk\n");
 		goto err_out_put_pclk;
 	}
-	clk_enable(bp->hclk);
+	clk_prepare_enable(bp->hclk);
 
 	bp->regs = ioremap(regs->start, resource_size(regs));
 	if (!bp->regs) {
@@ -1592,11 +1563,13 @@ static int __init macb_probe(struct platform_device *pdev)
 	config |= macb_dbw(bp);
 	macb_writel(bp, NCFGR, config);
 
-	err = macb_get_hwaddr_dt(bp);
-	if (err < 0)
+	mac = of_get_mac_address(pdev->dev.of_node);
+	if (mac)
+		memcpy(bp->dev->dev_addr, mac, ETH_ALEN);
+	else
 		macb_get_hwaddr(bp);
 
-	err = macb_get_phy_mode_dt(pdev);
+	err = of_get_phy_mode(pdev->dev.of_node);
 	if (err < 0) {
 		pdata = pdev->dev.platform_data;
 		if (pdata && pdata->is_rmii)
@@ -1654,9 +1627,9 @@ err_out_free_irq:
 err_out_iounmap:
 	iounmap(bp->regs);
 err_out_disable_clocks:
-	clk_disable(bp->hclk);
+	clk_disable_unprepare(bp->hclk);
 	clk_put(bp->hclk);
-	clk_disable(bp->pclk);
+	clk_disable_unprepare(bp->pclk);
 err_out_put_pclk:
 	clk_put(bp->pclk);
 err_out_free_dev:
@@ -1683,9 +1656,9 @@ static int __exit macb_remove(struct platform_device *pdev)
 		unregister_netdev(dev);
 		free_irq(dev->irq, dev);
 		iounmap(bp->regs);
-		clk_disable(bp->hclk);
+		clk_disable_unprepare(bp->hclk);
 		clk_put(bp->hclk);
-		clk_disable(bp->pclk);
+		clk_disable_unprepare(bp->pclk);
 		clk_put(bp->pclk);
 		free_netdev(dev);
 		platform_set_drvdata(pdev, NULL);
@@ -1703,8 +1676,8 @@ static int macb_suspend(struct platform_device *pdev, pm_message_t state)
 	netif_carrier_off(netdev);
 	netif_device_detach(netdev);
 
-	clk_disable(bp->hclk);
-	clk_disable(bp->pclk);
+	clk_disable_unprepare(bp->hclk);
+	clk_disable_unprepare(bp->pclk);
 
 	return 0;
 }
@@ -1714,8 +1687,8 @@ static int macb_resume(struct platform_device *pdev)
 	struct net_device *netdev = platform_get_drvdata(pdev);
 	struct macb *bp = netdev_priv(netdev);
 
-	clk_enable(bp->pclk);
-	clk_enable(bp->hclk);
+	clk_prepare_enable(bp->pclk);
+	clk_prepare_enable(bp->hclk);
 
 	netif_device_attach(netdev);
 
@@ -1737,18 +1710,7 @@ static struct platform_driver macb_driver = {
 	},
 };
 
-static int __init macb_init(void)
-{
-	return platform_driver_probe(&macb_driver, macb_probe);
-}
-
-static void __exit macb_exit(void)
-{
-	platform_driver_unregister(&macb_driver);
-}
-
-module_init(macb_init);
-module_exit(macb_exit);
+module_platform_driver_probe(macb_driver, macb_probe);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Cadence MACB/GEM Ethernet driver");
diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h
index 570908b..993d703 100644
--- a/drivers/net/ethernet/cadence/macb.h
+++ b/drivers/net/ethernet/cadence/macb.h
@@ -173,6 +173,8 @@
 /* Bitfields in DMACFG. */
 #define GEM_FBLDO_OFFSET			0
 #define GEM_FBLDO_SIZE				5
+#define GEM_ENDIA_OFFSET			7
+#define GEM_ENDIA_SIZE				1
 #define GEM_RXBMS_OFFSET			8
 #define GEM_RXBMS_SIZE				2
 #define GEM_TXPBMS_OFFSET			10
diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c
index a170065..b0ebc9f 100644
--- a/drivers/net/ethernet/calxeda/xgmac.c
+++ b/drivers/net/ethernet/calxeda/xgmac.c
@@ -163,6 +163,7 @@
 #define XGMAC_FLOW_CTRL_FCB_BPA	0x00000001	/* Flow Control Busy ... */
 
 /* XGMAC_INT_STAT reg */
+#define XGMAC_INT_STAT_PMTIM	0x00800000	/* PMT Interrupt Mask */
 #define XGMAC_INT_STAT_PMT	0x0080		/* PMT Interrupt Status */
 #define XGMAC_INT_STAT_LPI	0x0040		/* LPI Interrupt Status */
 
@@ -960,6 +961,9 @@ static int xgmac_hw_init(struct net_device *dev)
 	writel(DMA_INTR_DEFAULT_MASK, ioaddr + XGMAC_DMA_STATUS);
 	writel(DMA_INTR_DEFAULT_MASK, ioaddr + XGMAC_DMA_INTR_ENA);
 
+	/* Mask power mgt interrupt */
+	writel(XGMAC_INT_STAT_PMTIM, ioaddr + XGMAC_INT_STAT);
+
 	/* XGMAC requires AXI bus init. This is a 'magic number' for now */
 	writel(0x0077000E, ioaddr + XGMAC_DMA_AXI_BUS);
 
@@ -1141,6 +1145,9 @@ static int xgmac_rx(struct xgmac_priv *priv, int limit)
 		struct sk_buff *skb;
 		int frame_len;
 
+		if (!dma_ring_cnt(priv->rx_head, priv->rx_tail, DMA_RX_RING_SZ))
+			break;
+
 		entry = priv->rx_tail;
 		p = priv->dma_rx + entry;
 		if (desc_get_owner(p))
@@ -1825,7 +1832,7 @@ static void xgmac_pmt(void __iomem *ioaddr, unsigned long mode)
 	unsigned int pmt = 0;
 
 	if (mode & WAKE_MAGIC)
-		pmt |= XGMAC_PMT_POWERDOWN | XGMAC_PMT_MAGIC_PKT;
+		pmt |= XGMAC_PMT_POWERDOWN | XGMAC_PMT_MAGIC_PKT_EN;
 	if (mode & WAKE_UCAST)
 		pmt |= XGMAC_PMT_POWERDOWN | XGMAC_PMT_GLBL_UNICAST;
 
diff --git a/drivers/net/ethernet/chelsio/cxgb/sge.c b/drivers/net/ethernet/chelsio/cxgb/sge.c
index 4829769..55fe8c9 100644
--- a/drivers/net/ethernet/chelsio/cxgb/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb/sge.c
@@ -835,7 +835,7 @@ static void refill_free_list(struct sge *sge, struct freelQ *q)
 		struct sk_buff *skb;
 		dma_addr_t mapping;
 
-		skb = alloc_skb(q->rx_buffer_size, GFP_ATOMIC);
+		skb = dev_alloc_skb(q->rx_buffer_size);
 		if (!skb)
 			break;
 
@@ -1046,11 +1046,10 @@ static inline struct sk_buff *get_packet(struct pci_dev *pdev,
 	const struct freelQ_ce *ce = &fl->centries[fl->cidx];
 
 	if (len < copybreak) {
-		skb = alloc_skb(len + 2, GFP_ATOMIC);
+		skb = netdev_alloc_skb_ip_align(NULL, len);
 		if (!skb)
 			goto use_orig_buf;
 
-		skb_reserve(skb, 2);	/* align IP header */
 		skb_put(skb, len);
 		pci_dma_sync_single_for_cpu(pdev,
 					    dma_unmap_addr(ce, dma_addr),
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
index 6db997c..681804b 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
@@ -54,6 +54,10 @@
 #define FW_VERSION_MINOR 1
 #define FW_VERSION_MICRO 0
 
+#define FW_VERSION_MAJOR_T5 0
+#define FW_VERSION_MINOR_T5 0
+#define FW_VERSION_MICRO_T5 0
+
 #define CH_WARN(adap, fmt, ...) dev_warn(adap->pdev_dev, fmt, ## __VA_ARGS__)
 
 enum {
@@ -66,7 +70,9 @@ enum {
 enum {
 	MEM_EDC0,
 	MEM_EDC1,
-	MEM_MC
+	MEM_MC,
+	MEM_MC0 = MEM_MC,
+	MEM_MC1
 };
 
 enum {
@@ -74,8 +80,10 @@ enum {
 	MEMWIN0_BASE     = 0x1b800,
 	MEMWIN1_APERTURE = 32768,
 	MEMWIN1_BASE     = 0x28000,
+	MEMWIN1_BASE_T5  = 0x52000,
 	MEMWIN2_APERTURE = 65536,
 	MEMWIN2_BASE     = 0x30000,
+	MEMWIN2_BASE_T5  = 0x54000,
 };
 
 enum dev_master {
@@ -431,6 +439,7 @@ struct sge_txq {
 	spinlock_t db_lock;
 	int db_disabled;
 	unsigned short db_pidx;
+	u64 udb;
 };
 
 struct sge_eth_txq {                /* state for an SGE Ethernet Tx queue */
@@ -504,13 +513,44 @@ struct sge {
 
 struct l2t_data;
 
+#define CHELSIO_CHIP_CODE(version, revision) (((version) << 4) | (revision))
+#define CHELSIO_CHIP_VERSION(code) ((code) >> 4)
+#define CHELSIO_CHIP_RELEASE(code) ((code) & 0xf)
+
+#define CHELSIO_T4		0x4
+#define CHELSIO_T5		0x5
+
+enum chip_type {
+	T4_A1 = CHELSIO_CHIP_CODE(CHELSIO_T4, 0),
+	T4_A2 = CHELSIO_CHIP_CODE(CHELSIO_T4, 1),
+	T4_A3 = CHELSIO_CHIP_CODE(CHELSIO_T4, 2),
+	T4_FIRST_REV	= T4_A1,
+	T4_LAST_REV	= T4_A3,
+
+	T5_A1 = CHELSIO_CHIP_CODE(CHELSIO_T5, 0),
+	T5_FIRST_REV	= T5_A1,
+	T5_LAST_REV	= T5_A1,
+};
+
+#ifdef CONFIG_PCI_IOV
+
+/* T4 supports SRIOV on PF0-3 and T5 on PF0-7.  However, the Serial
+ * Configuration initialization for T5 only has SR-IOV functionality enabled
+ * on PF0-3 in order to simplify everything.
+ */
+#define NUM_OF_PF_WITH_SRIOV 4
+
+#endif
+
 struct adapter {
 	void __iomem *regs;
+	void __iomem *bar2;
 	struct pci_dev *pdev;
 	struct device *pdev_dev;
 	unsigned int mbox;
 	unsigned int fn;
 	unsigned int flags;
+	enum chip_type chip;
 
 	int msg_enable;
 
@@ -673,6 +713,16 @@ enum {
 	VLAN_REWRITE
 };
 
+static inline int is_t5(enum chip_type chip)
+{
+	return (chip >= T5_FIRST_REV && chip <= T5_LAST_REV);
+}
+
+static inline int is_t4(enum chip_type chip)
+{
+	return (chip >= T4_FIRST_REV && chip <= T4_LAST_REV);
+}
+
 static inline u32 t4_read_reg(struct adapter *adap, u32 reg_addr)
 {
 	return readl(adap->regs + reg_addr);
@@ -858,7 +908,8 @@ int t4_config_rss_range(struct adapter *adapter, int mbox, unsigned int viid,
 			int start, int n, const u16 *rspq, unsigned int nrspq);
 int t4_config_glbl_rss(struct adapter *adapter, int mbox, unsigned int mode,
 		       unsigned int flags);
-int t4_mc_read(struct adapter *adap, u32 addr, __be32 *data, u64 *parity);
+int t4_mc_read(struct adapter *adap, int idx, u32 addr, __be32 *data,
+	       u64 *parity);
 int t4_edc_read(struct adapter *adap, int idx, u32 addr, __be32 *data,
 		u64 *parity);
 
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index e707e31..e76cf03 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -68,8 +68,8 @@
 #include "t4fw_api.h"
 #include "l2t.h"
 
-#define DRV_VERSION "1.3.0-ko"
-#define DRV_DESC "Chelsio T4 Network Driver"
+#define DRV_VERSION "2.0.0-ko"
+#define DRV_DESC "Chelsio T4/T5 Network Driver"
 
 /*
  * Max interrupt hold-off timer value in us.  Queues fall back to this value
@@ -229,11 +229,51 @@ static DEFINE_PCI_DEVICE_TABLE(cxgb4_pci_tbl) = {
 	CH_DEVICE(0x440a, 4),
 	CH_DEVICE(0x440d, 4),
 	CH_DEVICE(0x440e, 4),
+	CH_DEVICE(0x5001, 5),
+	CH_DEVICE(0x5002, 5),
+	CH_DEVICE(0x5003, 5),
+	CH_DEVICE(0x5004, 5),
+	CH_DEVICE(0x5005, 5),
+	CH_DEVICE(0x5006, 5),
+	CH_DEVICE(0x5007, 5),
+	CH_DEVICE(0x5008, 5),
+	CH_DEVICE(0x5009, 5),
+	CH_DEVICE(0x500A, 5),
+	CH_DEVICE(0x500B, 5),
+	CH_DEVICE(0x500C, 5),
+	CH_DEVICE(0x500D, 5),
+	CH_DEVICE(0x500E, 5),
+	CH_DEVICE(0x500F, 5),
+	CH_DEVICE(0x5010, 5),
+	CH_DEVICE(0x5011, 5),
+	CH_DEVICE(0x5012, 5),
+	CH_DEVICE(0x5013, 5),
+	CH_DEVICE(0x5401, 5),
+	CH_DEVICE(0x5402, 5),
+	CH_DEVICE(0x5403, 5),
+	CH_DEVICE(0x5404, 5),
+	CH_DEVICE(0x5405, 5),
+	CH_DEVICE(0x5406, 5),
+	CH_DEVICE(0x5407, 5),
+	CH_DEVICE(0x5408, 5),
+	CH_DEVICE(0x5409, 5),
+	CH_DEVICE(0x540A, 5),
+	CH_DEVICE(0x540B, 5),
+	CH_DEVICE(0x540C, 5),
+	CH_DEVICE(0x540D, 5),
+	CH_DEVICE(0x540E, 5),
+	CH_DEVICE(0x540F, 5),
+	CH_DEVICE(0x5410, 5),
+	CH_DEVICE(0x5411, 5),
+	CH_DEVICE(0x5412, 5),
+	CH_DEVICE(0x5413, 5),
 	{ 0, }
 };
 
 #define FW_FNAME "cxgb4/t4fw.bin"
+#define FW5_FNAME "cxgb4/t5fw.bin"
 #define FW_CFNAME "cxgb4/t4-config.txt"
+#define FW5_CFNAME "cxgb4/t5-config.txt"
 
 MODULE_DESCRIPTION(DRV_DESC);
 MODULE_AUTHOR("Chelsio Communications");
@@ -241,6 +281,7 @@ MODULE_LICENSE("Dual BSD/GPL");
 MODULE_VERSION(DRV_VERSION);
 MODULE_DEVICE_TABLE(pci, cxgb4_pci_tbl);
 MODULE_FIRMWARE(FW_FNAME);
+MODULE_FIRMWARE(FW5_FNAME);
 
 /*
  * Normally we're willing to become the firmware's Master PF but will be happy
@@ -319,7 +360,10 @@ static bool vf_acls;
 module_param(vf_acls, bool, 0644);
 MODULE_PARM_DESC(vf_acls, "if set enable virtualization L2 ACL enforcement");
 
-static unsigned int num_vf[4];
+/* Configure the number of PCI-E Virtual Function which are to be instantiated
+ * on SR-IOV Capable Physical Functions.
+ */
+static unsigned int num_vf[NUM_OF_PF_WITH_SRIOV];
 
 module_param_array(num_vf, uint, NULL, 0644);
 MODULE_PARM_DESC(num_vf, "number of VFs for each of PFs 0-3");
@@ -1002,21 +1046,36 @@ freeout:	t4_free_sge_resources(adap);
 static int upgrade_fw(struct adapter *adap)
 {
 	int ret;
-	u32 vers;
+	u32 vers, exp_major;
 	const struct fw_hdr *hdr;
 	const struct firmware *fw;
 	struct device *dev = adap->pdev_dev;
+	char *fw_file_name;
 
-	ret = request_firmware(&fw, FW_FNAME, dev);
+	switch (CHELSIO_CHIP_VERSION(adap->chip)) {
+	case CHELSIO_T4:
+		fw_file_name = FW_FNAME;
+		exp_major = FW_VERSION_MAJOR;
+		break;
+	case CHELSIO_T5:
+		fw_file_name = FW5_FNAME;
+		exp_major = FW_VERSION_MAJOR_T5;
+		break;
+	default:
+		dev_err(dev, "Unsupported chip type, %x\n", adap->chip);
+		return -EINVAL;
+	}
+
+	ret = request_firmware(&fw, fw_file_name, dev);
 	if (ret < 0) {
-		dev_err(dev, "unable to load firmware image " FW_FNAME
-			", error %d\n", ret);
+		dev_err(dev, "unable to load firmware image %s, error %d\n",
+			fw_file_name, ret);
 		return ret;
 	}
 
 	hdr = (const struct fw_hdr *)fw->data;
 	vers = ntohl(hdr->fw_ver);
-	if (FW_HDR_FW_VER_MAJOR_GET(vers) != FW_VERSION_MAJOR) {
+	if (FW_HDR_FW_VER_MAJOR_GET(vers) != exp_major) {
 		ret = -EINVAL;              /* wrong major version, won't do */
 		goto out;
 	}
@@ -1024,18 +1083,15 @@ static int upgrade_fw(struct adapter *adap)
 	/*
 	 * If the flash FW is unusable or we found something newer, load it.
 	 */
-	if (FW_HDR_FW_VER_MAJOR_GET(adap->params.fw_vers) != FW_VERSION_MAJOR ||
+	if (FW_HDR_FW_VER_MAJOR_GET(adap->params.fw_vers) != exp_major ||
 	    vers > adap->params.fw_vers) {
 		dev_info(dev, "upgrading firmware ...\n");
 		ret = t4_fw_upgrade(adap, adap->mbox, fw->data, fw->size,
 				    /*force=*/false);
 		if (!ret)
-			dev_info(dev, "firmware successfully upgraded to "
-				 FW_FNAME " (%d.%d.%d.%d)\n",
-				 FW_HDR_FW_VER_MAJOR_GET(vers),
-				 FW_HDR_FW_VER_MINOR_GET(vers),
-				 FW_HDR_FW_VER_MICRO_GET(vers),
-				 FW_HDR_FW_VER_BUILD_GET(vers));
+			dev_info(dev,
+				 "firmware upgraded to version %pI4 from %s\n",
+				 &hdr->fw_ver, fw_file_name);
 		else
 			dev_err(dev, "firmware upgrade failed! err=%d\n", -ret);
 	} else {
@@ -1308,6 +1364,8 @@ static char stats_strings[][ETH_GSTRING_LEN] = {
 	"VLANinsertions     ",
 	"GROpackets         ",
 	"GROmerged          ",
+	"WriteCoalSuccess   ",
+	"WriteCoalFail      ",
 };
 
 static int get_sset_count(struct net_device *dev, int sset)
@@ -1321,10 +1379,15 @@ static int get_sset_count(struct net_device *dev, int sset)
 }
 
 #define T4_REGMAP_SIZE (160 * 1024)
+#define T5_REGMAP_SIZE (332 * 1024)
 
 static int get_regs_len(struct net_device *dev)
 {
-	return T4_REGMAP_SIZE;
+	struct adapter *adap = netdev2adap(dev);
+	if (is_t4(adap->chip))
+		return T4_REGMAP_SIZE;
+	else
+		return T5_REGMAP_SIZE;
 }
 
 static int get_eeprom_len(struct net_device *dev)
@@ -1398,11 +1461,25 @@ static void get_stats(struct net_device *dev, struct ethtool_stats *stats,
 {
 	struct port_info *pi = netdev_priv(dev);
 	struct adapter *adapter = pi->adapter;
+	u32 val1, val2;
 
 	t4_get_port_stats(adapter, pi->tx_chan, (struct port_stats *)data);
 
 	data += sizeof(struct port_stats) / sizeof(u64);
 	collect_sge_port_stats(adapter, pi, (struct queue_port_stats *)data);
+	data += sizeof(struct queue_port_stats) / sizeof(u64);
+	if (!is_t4(adapter->chip)) {
+		t4_write_reg(adapter, SGE_STAT_CFG, STATSOURCE_T5(7));
+		val1 = t4_read_reg(adapter, SGE_STAT_TOTAL);
+		val2 = t4_read_reg(adapter, SGE_STAT_MATCH);
+		*data = val1 - val2;
+		data++;
+		*data = val2;
+		data++;
+	} else {
+		memset(data, 0, 2 * sizeof(u64));
+		*data += 2;
+	}
 }
 
 /*
@@ -1413,7 +1490,8 @@ static void get_stats(struct net_device *dev, struct ethtool_stats *stats,
  */
 static inline unsigned int mk_adap_vers(const struct adapter *ap)
 {
-	return 4 | (ap->params.rev << 10) | (1 << 16);
+	return CHELSIO_CHIP_VERSION(ap->chip) |
+		(CHELSIO_CHIP_RELEASE(ap->chip) << 10) | (1 << 16);
 }
 
 static void reg_block_dump(struct adapter *ap, void *buf, unsigned int start,
@@ -1428,7 +1506,7 @@ static void reg_block_dump(struct adapter *ap, void *buf, unsigned int start,
 static void get_regs(struct net_device *dev, struct ethtool_regs *regs,
 		     void *buf)
 {
-	static const unsigned int reg_ranges[] = {
+	static const unsigned int t4_reg_ranges[] = {
 		0x1008, 0x1108,
 		0x1180, 0x11b4,
 		0x11fc, 0x123c,
@@ -1648,13 +1726,452 @@ static void get_regs(struct net_device *dev, struct ethtool_regs *regs,
 		0x27e00, 0x27e04
 	};
 
+	static const unsigned int t5_reg_ranges[] = {
+		0x1008, 0x1148,
+		0x1180, 0x11b4,
+		0x11fc, 0x123c,
+		0x1280, 0x173c,
+		0x1800, 0x18fc,
+		0x3000, 0x3028,
+		0x3060, 0x30d8,
+		0x30e0, 0x30fc,
+		0x3140, 0x357c,
+		0x35a8, 0x35cc,
+		0x35ec, 0x35ec,
+		0x3600, 0x5624,
+		0x56cc, 0x575c,
+		0x580c, 0x5814,
+		0x5890, 0x58bc,
+		0x5940, 0x59dc,
+		0x59fc, 0x5a18,
+		0x5a60, 0x5a9c,
+		0x5b9c, 0x5bfc,
+		0x6000, 0x6040,
+		0x6058, 0x614c,
+		0x7700, 0x7798,
+		0x77c0, 0x78fc,
+		0x7b00, 0x7c54,
+		0x7d00, 0x7efc,
+		0x8dc0, 0x8de0,
+		0x8df8, 0x8e84,
+		0x8ea0, 0x8f84,
+		0x8fc0, 0x90f8,
+		0x9400, 0x9470,
+		0x9600, 0x96f4,
+		0x9800, 0x9808,
+		0x9820, 0x983c,
+		0x9850, 0x9864,
+		0x9c00, 0x9c6c,
+		0x9c80, 0x9cec,
+		0x9d00, 0x9d6c,
+		0x9d80, 0x9dec,
+		0x9e00, 0x9e6c,
+		0x9e80, 0x9eec,
+		0x9f00, 0x9f6c,
+		0x9f80, 0xa020,
+		0xd004, 0xd03c,
+		0xdfc0, 0xdfe0,
+		0xe000, 0x11088,
+		0x1109c, 0x1117c,
+		0x11190, 0x11204,
+		0x19040, 0x1906c,
+		0x19078, 0x19080,
+		0x1908c, 0x19124,
+		0x19150, 0x191b0,
+		0x191d0, 0x191e8,
+		0x19238, 0x19290,
+		0x193f8, 0x19474,
+		0x19490, 0x194cc,
+		0x194f0, 0x194f8,
+		0x19c00, 0x19c60,
+		0x19c94, 0x19e10,
+		0x19e50, 0x19f34,
+		0x19f40, 0x19f50,
+		0x19f90, 0x19fe4,
+		0x1a000, 0x1a06c,
+		0x1a0b0, 0x1a120,
+		0x1a128, 0x1a138,
+		0x1a190, 0x1a1c4,
+		0x1a1fc, 0x1a1fc,
+		0x1e008, 0x1e00c,
+		0x1e040, 0x1e04c,
+		0x1e284, 0x1e290,
+		0x1e2c0, 0x1e2c0,
+		0x1e2e0, 0x1e2e0,
+		0x1e300, 0x1e384,
+		0x1e3c0, 0x1e3c8,
+		0x1e408, 0x1e40c,
+		0x1e440, 0x1e44c,
+		0x1e684, 0x1e690,
+		0x1e6c0, 0x1e6c0,
+		0x1e6e0, 0x1e6e0,
+		0x1e700, 0x1e784,
+		0x1e7c0, 0x1e7c8,
+		0x1e808, 0x1e80c,
+		0x1e840, 0x1e84c,
+		0x1ea84, 0x1ea90,
+		0x1eac0, 0x1eac0,
+		0x1eae0, 0x1eae0,
+		0x1eb00, 0x1eb84,
+		0x1ebc0, 0x1ebc8,
+		0x1ec08, 0x1ec0c,
+		0x1ec40, 0x1ec4c,
+		0x1ee84, 0x1ee90,
+		0x1eec0, 0x1eec0,
+		0x1eee0, 0x1eee0,
+		0x1ef00, 0x1ef84,
+		0x1efc0, 0x1efc8,
+		0x1f008, 0x1f00c,
+		0x1f040, 0x1f04c,
+		0x1f284, 0x1f290,
+		0x1f2c0, 0x1f2c0,
+		0x1f2e0, 0x1f2e0,
+		0x1f300, 0x1f384,
+		0x1f3c0, 0x1f3c8,
+		0x1f408, 0x1f40c,
+		0x1f440, 0x1f44c,
+		0x1f684, 0x1f690,
+		0x1f6c0, 0x1f6c0,
+		0x1f6e0, 0x1f6e0,
+		0x1f700, 0x1f784,
+		0x1f7c0, 0x1f7c8,
+		0x1f808, 0x1f80c,
+		0x1f840, 0x1f84c,
+		0x1fa84, 0x1fa90,
+		0x1fac0, 0x1fac0,
+		0x1fae0, 0x1fae0,
+		0x1fb00, 0x1fb84,
+		0x1fbc0, 0x1fbc8,
+		0x1fc08, 0x1fc0c,
+		0x1fc40, 0x1fc4c,
+		0x1fe84, 0x1fe90,
+		0x1fec0, 0x1fec0,
+		0x1fee0, 0x1fee0,
+		0x1ff00, 0x1ff84,
+		0x1ffc0, 0x1ffc8,
+		0x30000, 0x30030,
+		0x30100, 0x30144,
+		0x30190, 0x301d0,
+		0x30200, 0x30318,
+		0x30400, 0x3052c,
+		0x30540, 0x3061c,
+		0x30800, 0x30834,
+		0x308c0, 0x30908,
+		0x30910, 0x309ac,
+		0x30a00, 0x30a04,
+		0x30a0c, 0x30a2c,
+		0x30a44, 0x30a50,
+		0x30a74, 0x30c24,
+		0x30d08, 0x30d14,
+		0x30d1c, 0x30d20,
+		0x30d3c, 0x30d50,
+		0x31200, 0x3120c,
+		0x31220, 0x31220,
+		0x31240, 0x31240,
+		0x31600, 0x31600,
+		0x31608, 0x3160c,
+		0x31a00, 0x31a1c,
+		0x31e04, 0x31e20,
+		0x31e38, 0x31e3c,
+		0x31e80, 0x31e80,
+		0x31e88, 0x31ea8,
+		0x31eb0, 0x31eb4,
+		0x31ec8, 0x31ed4,
+		0x31fb8, 0x32004,
+		0x32208, 0x3223c,
+		0x32600, 0x32630,
+		0x32a00, 0x32abc,
+		0x32b00, 0x32b70,
+		0x33000, 0x33048,
+		0x33060, 0x3309c,
+		0x330f0, 0x33148,
+		0x33160, 0x3319c,
+		0x331f0, 0x332e4,
+		0x332f8, 0x333e4,
+		0x333f8, 0x33448,
+		0x33460, 0x3349c,
+		0x334f0, 0x33548,
+		0x33560, 0x3359c,
+		0x335f0, 0x336e4,
+		0x336f8, 0x337e4,
+		0x337f8, 0x337fc,
+		0x33814, 0x33814,
+		0x3382c, 0x3382c,
+		0x33880, 0x3388c,
+		0x338e8, 0x338ec,
+		0x33900, 0x33948,
+		0x33960, 0x3399c,
+		0x339f0, 0x33ae4,
+		0x33af8, 0x33b10,
+		0x33b28, 0x33b28,
+		0x33b3c, 0x33b50,
+		0x33bf0, 0x33c10,
+		0x33c28, 0x33c28,
+		0x33c3c, 0x33c50,
+		0x33cf0, 0x33cfc,
+		0x34000, 0x34030,
+		0x34100, 0x34144,
+		0x34190, 0x341d0,
+		0x34200, 0x34318,
+		0x34400, 0x3452c,
+		0x34540, 0x3461c,
+		0x34800, 0x34834,
+		0x348c0, 0x34908,
+		0x34910, 0x349ac,
+		0x34a00, 0x34a04,
+		0x34a0c, 0x34a2c,
+		0x34a44, 0x34a50,
+		0x34a74, 0x34c24,
+		0x34d08, 0x34d14,
+		0x34d1c, 0x34d20,
+		0x34d3c, 0x34d50,
+		0x35200, 0x3520c,
+		0x35220, 0x35220,
+		0x35240, 0x35240,
+		0x35600, 0x35600,
+		0x35608, 0x3560c,
+		0x35a00, 0x35a1c,
+		0x35e04, 0x35e20,
+		0x35e38, 0x35e3c,
+		0x35e80, 0x35e80,
+		0x35e88, 0x35ea8,
+		0x35eb0, 0x35eb4,
+		0x35ec8, 0x35ed4,
+		0x35fb8, 0x36004,
+		0x36208, 0x3623c,
+		0x36600, 0x36630,
+		0x36a00, 0x36abc,
+		0x36b00, 0x36b70,
+		0x37000, 0x37048,
+		0x37060, 0x3709c,
+		0x370f0, 0x37148,
+		0x37160, 0x3719c,
+		0x371f0, 0x372e4,
+		0x372f8, 0x373e4,
+		0x373f8, 0x37448,
+		0x37460, 0x3749c,
+		0x374f0, 0x37548,
+		0x37560, 0x3759c,
+		0x375f0, 0x376e4,
+		0x376f8, 0x377e4,
+		0x377f8, 0x377fc,
+		0x37814, 0x37814,
+		0x3782c, 0x3782c,
+		0x37880, 0x3788c,
+		0x378e8, 0x378ec,
+		0x37900, 0x37948,
+		0x37960, 0x3799c,
+		0x379f0, 0x37ae4,
+		0x37af8, 0x37b10,
+		0x37b28, 0x37b28,
+		0x37b3c, 0x37b50,
+		0x37bf0, 0x37c10,
+		0x37c28, 0x37c28,
+		0x37c3c, 0x37c50,
+		0x37cf0, 0x37cfc,
+		0x38000, 0x38030,
+		0x38100, 0x38144,
+		0x38190, 0x381d0,
+		0x38200, 0x38318,
+		0x38400, 0x3852c,
+		0x38540, 0x3861c,
+		0x38800, 0x38834,
+		0x388c0, 0x38908,
+		0x38910, 0x389ac,
+		0x38a00, 0x38a04,
+		0x38a0c, 0x38a2c,
+		0x38a44, 0x38a50,
+		0x38a74, 0x38c24,
+		0x38d08, 0x38d14,
+		0x38d1c, 0x38d20,
+		0x38d3c, 0x38d50,
+		0x39200, 0x3920c,
+		0x39220, 0x39220,
+		0x39240, 0x39240,
+		0x39600, 0x39600,
+		0x39608, 0x3960c,
+		0x39a00, 0x39a1c,
+		0x39e04, 0x39e20,
+		0x39e38, 0x39e3c,
+		0x39e80, 0x39e80,
+		0x39e88, 0x39ea8,
+		0x39eb0, 0x39eb4,
+		0x39ec8, 0x39ed4,
+		0x39fb8, 0x3a004,
+		0x3a208, 0x3a23c,
+		0x3a600, 0x3a630,
+		0x3aa00, 0x3aabc,
+		0x3ab00, 0x3ab70,
+		0x3b000, 0x3b048,
+		0x3b060, 0x3b09c,
+		0x3b0f0, 0x3b148,
+		0x3b160, 0x3b19c,
+		0x3b1f0, 0x3b2e4,
+		0x3b2f8, 0x3b3e4,
+		0x3b3f8, 0x3b448,
+		0x3b460, 0x3b49c,
+		0x3b4f0, 0x3b548,
+		0x3b560, 0x3b59c,
+		0x3b5f0, 0x3b6e4,
+		0x3b6f8, 0x3b7e4,
+		0x3b7f8, 0x3b7fc,
+		0x3b814, 0x3b814,
+		0x3b82c, 0x3b82c,
+		0x3b880, 0x3b88c,
+		0x3b8e8, 0x3b8ec,
+		0x3b900, 0x3b948,
+		0x3b960, 0x3b99c,
+		0x3b9f0, 0x3bae4,
+		0x3baf8, 0x3bb10,
+		0x3bb28, 0x3bb28,
+		0x3bb3c, 0x3bb50,
+		0x3bbf0, 0x3bc10,
+		0x3bc28, 0x3bc28,
+		0x3bc3c, 0x3bc50,
+		0x3bcf0, 0x3bcfc,
+		0x3c000, 0x3c030,
+		0x3c100, 0x3c144,
+		0x3c190, 0x3c1d0,
+		0x3c200, 0x3c318,
+		0x3c400, 0x3c52c,
+		0x3c540, 0x3c61c,
+		0x3c800, 0x3c834,
+		0x3c8c0, 0x3c908,
+		0x3c910, 0x3c9ac,
+		0x3ca00, 0x3ca04,
+		0x3ca0c, 0x3ca2c,
+		0x3ca44, 0x3ca50,
+		0x3ca74, 0x3cc24,
+		0x3cd08, 0x3cd14,
+		0x3cd1c, 0x3cd20,
+		0x3cd3c, 0x3cd50,
+		0x3d200, 0x3d20c,
+		0x3d220, 0x3d220,
+		0x3d240, 0x3d240,
+		0x3d600, 0x3d600,
+		0x3d608, 0x3d60c,
+		0x3da00, 0x3da1c,
+		0x3de04, 0x3de20,
+		0x3de38, 0x3de3c,
+		0x3de80, 0x3de80,
+		0x3de88, 0x3dea8,
+		0x3deb0, 0x3deb4,
+		0x3dec8, 0x3ded4,
+		0x3dfb8, 0x3e004,
+		0x3e208, 0x3e23c,
+		0x3e600, 0x3e630,
+		0x3ea00, 0x3eabc,
+		0x3eb00, 0x3eb70,
+		0x3f000, 0x3f048,
+		0x3f060, 0x3f09c,
+		0x3f0f0, 0x3f148,
+		0x3f160, 0x3f19c,
+		0x3f1f0, 0x3f2e4,
+		0x3f2f8, 0x3f3e4,
+		0x3f3f8, 0x3f448,
+		0x3f460, 0x3f49c,
+		0x3f4f0, 0x3f548,
+		0x3f560, 0x3f59c,
+		0x3f5f0, 0x3f6e4,
+		0x3f6f8, 0x3f7e4,
+		0x3f7f8, 0x3f7fc,
+		0x3f814, 0x3f814,
+		0x3f82c, 0x3f82c,
+		0x3f880, 0x3f88c,
+		0x3f8e8, 0x3f8ec,
+		0x3f900, 0x3f948,
+		0x3f960, 0x3f99c,
+		0x3f9f0, 0x3fae4,
+		0x3faf8, 0x3fb10,
+		0x3fb28, 0x3fb28,
+		0x3fb3c, 0x3fb50,
+		0x3fbf0, 0x3fc10,
+		0x3fc28, 0x3fc28,
+		0x3fc3c, 0x3fc50,
+		0x3fcf0, 0x3fcfc,
+		0x40000, 0x4000c,
+		0x40040, 0x40068,
+		0x40080, 0x40144,
+		0x40180, 0x4018c,
+		0x40200, 0x40298,
+		0x402ac, 0x4033c,
+		0x403f8, 0x403fc,
+		0x41300, 0x413c4,
+		0x41400, 0x4141c,
+		0x41480, 0x414d0,
+		0x44000, 0x44078,
+		0x440c0, 0x44278,
+		0x442c0, 0x44478,
+		0x444c0, 0x44678,
+		0x446c0, 0x44878,
+		0x448c0, 0x449fc,
+		0x45000, 0x45068,
+		0x45080, 0x45084,
+		0x450a0, 0x450b0,
+		0x45200, 0x45268,
+		0x45280, 0x45284,
+		0x452a0, 0x452b0,
+		0x460c0, 0x460e4,
+		0x47000, 0x4708c,
+		0x47200, 0x47250,
+		0x47400, 0x47420,
+		0x47600, 0x47618,
+		0x47800, 0x47814,
+		0x48000, 0x4800c,
+		0x48040, 0x48068,
+		0x48080, 0x48144,
+		0x48180, 0x4818c,
+		0x48200, 0x48298,
+		0x482ac, 0x4833c,
+		0x483f8, 0x483fc,
+		0x49300, 0x493c4,
+		0x49400, 0x4941c,
+		0x49480, 0x494d0,
+		0x4c000, 0x4c078,
+		0x4c0c0, 0x4c278,
+		0x4c2c0, 0x4c478,
+		0x4c4c0, 0x4c678,
+		0x4c6c0, 0x4c878,
+		0x4c8c0, 0x4c9fc,
+		0x4d000, 0x4d068,
+		0x4d080, 0x4d084,
+		0x4d0a0, 0x4d0b0,
+		0x4d200, 0x4d268,
+		0x4d280, 0x4d284,
+		0x4d2a0, 0x4d2b0,
+		0x4e0c0, 0x4e0e4,
+		0x4f000, 0x4f08c,
+		0x4f200, 0x4f250,
+		0x4f400, 0x4f420,
+		0x4f600, 0x4f618,
+		0x4f800, 0x4f814,
+		0x50000, 0x500cc,
+		0x50400, 0x50400,
+		0x50800, 0x508cc,
+		0x50c00, 0x50c00,
+		0x51000, 0x5101c,
+		0x51300, 0x51308,
+	};
+
 	int i;
 	struct adapter *ap = netdev2adap(dev);
+	static const unsigned int *reg_ranges;
+	int arr_size = 0, buf_size = 0;
+
+	if (is_t4(ap->chip)) {
+		reg_ranges = &t4_reg_ranges[0];
+		arr_size = ARRAY_SIZE(t4_reg_ranges);
+		buf_size = T4_REGMAP_SIZE;
+	} else {
+		reg_ranges = &t5_reg_ranges[0];
+		arr_size = ARRAY_SIZE(t5_reg_ranges);
+		buf_size = T5_REGMAP_SIZE;
+	}
 
 	regs->version = mk_adap_vers(ap);
 
-	memset(buf, 0, T4_REGMAP_SIZE);
-	for (i = 0; i < ARRAY_SIZE(reg_ranges); i += 2)
+	memset(buf, 0, buf_size);
+	for (i = 0; i < arr_size; i += 2)
 		reg_block_dump(ap, buf, reg_ranges[i], reg_ranges[i + 1]);
 }
 
@@ -2363,8 +2880,8 @@ static ssize_t mem_read(struct file *file, char __user *buf, size_t count,
 		int ret, ofst;
 		__be32 data[16];
 
-		if (mem == MEM_MC)
-			ret = t4_mc_read(adap, pos, data, NULL);
+		if ((mem == MEM_MC) || (mem == MEM_MC1))
+			ret = t4_mc_read(adap, mem % MEM_MC, pos, data, NULL);
 		else
 			ret = t4_edc_read(adap, mem, pos, data, NULL);
 		if (ret)
@@ -2405,18 +2922,37 @@ static void add_debugfs_mem(struct adapter *adap, const char *name,
 static int setup_debugfs(struct adapter *adap)
 {
 	int i;
+	u32 size;
 
 	if (IS_ERR_OR_NULL(adap->debugfs_root))
 		return -1;
 
 	i = t4_read_reg(adap, MA_TARGET_MEM_ENABLE);
-	if (i & EDRAM0_ENABLE)
-		add_debugfs_mem(adap, "edc0", MEM_EDC0, 5);
-	if (i & EDRAM1_ENABLE)
-		add_debugfs_mem(adap, "edc1", MEM_EDC1, 5);
-	if (i & EXT_MEM_ENABLE)
-		add_debugfs_mem(adap, "mc", MEM_MC,
-			EXT_MEM_SIZE_GET(t4_read_reg(adap, MA_EXT_MEMORY_BAR)));
+	if (i & EDRAM0_ENABLE) {
+		size = t4_read_reg(adap, MA_EDRAM0_BAR);
+		add_debugfs_mem(adap, "edc0", MEM_EDC0,	EDRAM_SIZE_GET(size));
+	}
+	if (i & EDRAM1_ENABLE) {
+		size = t4_read_reg(adap, MA_EDRAM1_BAR);
+		add_debugfs_mem(adap, "edc1", MEM_EDC1, EDRAM_SIZE_GET(size));
+	}
+	if (is_t4(adap->chip)) {
+		size = t4_read_reg(adap, MA_EXT_MEMORY_BAR);
+		if (i & EXT_MEM_ENABLE)
+			add_debugfs_mem(adap, "mc", MEM_MC,
+					EXT_MEM_SIZE_GET(size));
+	} else {
+		if (i & EXT_MEM_ENABLE) {
+			size = t4_read_reg(adap, MA_EXT_MEMORY_BAR);
+			add_debugfs_mem(adap, "mc0", MEM_MC0,
+					EXT_MEM_SIZE_GET(size));
+		}
+		if (i & EXT_MEM1_ENABLE) {
+			size = t4_read_reg(adap, MA_EXT_MEMORY1_BAR);
+			add_debugfs_mem(adap, "mc1", MEM_MC1,
+					EXT_MEM_SIZE_GET(size));
+		}
+	}
 	if (adap->l2t)
 		debugfs_create_file("l2t", S_IRUSR, adap->debugfs_root, adap,
 				    &t4_l2t_fops);
@@ -2747,10 +3283,18 @@ EXPORT_SYMBOL(cxgb4_port_chan);
 unsigned int cxgb4_dbfifo_count(const struct net_device *dev, int lpfifo)
 {
 	struct adapter *adap = netdev2adap(dev);
-	u32 v;
+	u32 v1, v2, lp_count, hp_count;
 
-	v = t4_read_reg(adap, A_SGE_DBFIFO_STATUS);
-	return lpfifo ? G_LP_COUNT(v) : G_HP_COUNT(v);
+	v1 = t4_read_reg(adap, A_SGE_DBFIFO_STATUS);
+	v2 = t4_read_reg(adap, SGE_DBFIFO_STATUS2);
+	if (is_t4(adap->chip)) {
+		lp_count = G_LP_COUNT(v1);
+		hp_count = G_HP_COUNT(v1);
+	} else {
+		lp_count = G_LP_COUNT_T5(v1);
+		hp_count = G_HP_COUNT_T5(v2);
+	}
+	return lpfifo ? lp_count : hp_count;
 }
 EXPORT_SYMBOL(cxgb4_dbfifo_count);
 
@@ -2853,6 +3397,25 @@ out:
 }
 EXPORT_SYMBOL(cxgb4_sync_txq_pidx);
 
+void cxgb4_disable_db_coalescing(struct net_device *dev)
+{
+	struct adapter *adap;
+
+	adap = netdev2adap(dev);
+	t4_set_reg_field(adap, A_SGE_DOORBELL_CONTROL, F_NOCOALESCE,
+			 F_NOCOALESCE);
+}
+EXPORT_SYMBOL(cxgb4_disable_db_coalescing);
+
+void cxgb4_enable_db_coalescing(struct net_device *dev)
+{
+	struct adapter *adap;
+
+	adap = netdev2adap(dev);
+	t4_set_reg_field(adap, A_SGE_DOORBELL_CONTROL, F_NOCOALESCE, 0);
+}
+EXPORT_SYMBOL(cxgb4_enable_db_coalescing);
+
 static struct pci_driver cxgb4_driver;
 
 static void check_neigh_update(struct neighbour *neigh)
@@ -2888,14 +3451,23 @@ static struct notifier_block cxgb4_netevent_nb = {
 
 static void drain_db_fifo(struct adapter *adap, int usecs)
 {
-	u32 v;
+	u32 v1, v2, lp_count, hp_count;
 
 	do {
+		v1 = t4_read_reg(adap, A_SGE_DBFIFO_STATUS);
+		v2 = t4_read_reg(adap, SGE_DBFIFO_STATUS2);
+		if (is_t4(adap->chip)) {
+			lp_count = G_LP_COUNT(v1);
+			hp_count = G_HP_COUNT(v1);
+		} else {
+			lp_count = G_LP_COUNT_T5(v1);
+			hp_count = G_HP_COUNT_T5(v2);
+		}
+
+		if (lp_count == 0 && hp_count == 0)
+			break;
 		set_current_state(TASK_UNINTERRUPTIBLE);
 		schedule_timeout(usecs_to_jiffies(usecs));
-		v = t4_read_reg(adap, A_SGE_DBFIFO_STATUS);
-		if (G_LP_COUNT(v) == 0 && G_HP_COUNT(v) == 0)
-			break;
 	} while (1);
 }
 
@@ -3004,24 +3576,62 @@ static void process_db_drop(struct work_struct *work)
 
 	adap = container_of(work, struct adapter, db_drop_task);
 
+	if (is_t4(adap->chip)) {
+		disable_dbs(adap);
+		notify_rdma_uld(adap, CXGB4_CONTROL_DB_DROP);
+		drain_db_fifo(adap, 1);
+		recover_all_queues(adap);
+		enable_dbs(adap);
+	} else {
+		u32 dropped_db = t4_read_reg(adap, 0x010ac);
+		u16 qid = (dropped_db >> 15) & 0x1ffff;
+		u16 pidx_inc = dropped_db & 0x1fff;
+		unsigned int s_qpp;
+		unsigned short udb_density;
+		unsigned long qpshift;
+		int page;
+		u32 udb;
+
+		dev_warn(adap->pdev_dev,
+			 "Dropped DB 0x%x qid %d bar2 %d coalesce %d pidx %d\n",
+			 dropped_db, qid,
+			 (dropped_db >> 14) & 1,
+			 (dropped_db >> 13) & 1,
+			 pidx_inc);
+
+		drain_db_fifo(adap, 1);
+
+		s_qpp = QUEUESPERPAGEPF1 * adap->fn;
+		udb_density = 1 << QUEUESPERPAGEPF0_GET(t4_read_reg(adap,
+				SGE_EGRESS_QUEUES_PER_PAGE_PF) >> s_qpp);
+		qpshift = PAGE_SHIFT - ilog2(udb_density);
+		udb = qid << qpshift;
+		udb &= PAGE_MASK;
+		page = udb / PAGE_SIZE;
+		udb += (qid - (page * udb_density)) * 128;
+
+		writel(PIDX(pidx_inc),  adap->bar2 + udb + 8);
+
+		/* Re-enable BAR2 WC */
+		t4_set_reg_field(adap, 0x10b0, 1<<15, 1<<15);
+	}
+
 	t4_set_reg_field(adap, A_SGE_DOORBELL_CONTROL, F_DROPPED_DB, 0);
-	disable_dbs(adap);
-	notify_rdma_uld(adap, CXGB4_CONTROL_DB_DROP);
-	drain_db_fifo(adap, 1);
-	recover_all_queues(adap);
-	enable_dbs(adap);
 }
 
 void t4_db_full(struct adapter *adap)
 {
-	t4_set_reg_field(adap, SGE_INT_ENABLE3,
-			 DBFIFO_HP_INT | DBFIFO_LP_INT, 0);
-	queue_work(workq, &adap->db_full_task);
+	if (is_t4(adap->chip)) {
+		t4_set_reg_field(adap, SGE_INT_ENABLE3,
+				 DBFIFO_HP_INT | DBFIFO_LP_INT, 0);
+		queue_work(workq, &adap->db_full_task);
+	}
 }
 
 void t4_db_dropped(struct adapter *adap)
 {
-	queue_work(workq, &adap->db_drop_task);
+	if (is_t4(adap->chip))
+		queue_work(workq, &adap->db_drop_task);
 }
 
 static void uld_attach(struct adapter *adap, unsigned int uld)
@@ -3566,17 +4176,27 @@ void t4_fatal_err(struct adapter *adap)
 
 static void setup_memwin(struct adapter *adap)
 {
-	u32 bar0;
+	u32 bar0, mem_win0_base, mem_win1_base, mem_win2_base;
 
 	bar0 = pci_resource_start(adap->pdev, 0);  /* truncation intentional */
+	if (is_t4(adap->chip)) {
+		mem_win0_base = bar0 + MEMWIN0_BASE;
+		mem_win1_base = bar0 + MEMWIN1_BASE;
+		mem_win2_base = bar0 + MEMWIN2_BASE;
+	} else {
+		/* For T5, only relative offset inside the PCIe BAR is passed */
+		mem_win0_base = MEMWIN0_BASE;
+		mem_win1_base = MEMWIN1_BASE_T5;
+		mem_win2_base = MEMWIN2_BASE_T5;
+	}
 	t4_write_reg(adap, PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, 0),
-		     (bar0 + MEMWIN0_BASE) | BIR(0) |
+		     mem_win0_base | BIR(0) |
 		     WINDOW(ilog2(MEMWIN0_APERTURE) - 10));
 	t4_write_reg(adap, PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, 1),
-		     (bar0 + MEMWIN1_BASE) | BIR(0) |
+		     mem_win1_base | BIR(0) |
 		     WINDOW(ilog2(MEMWIN1_APERTURE) - 10));
 	t4_write_reg(adap, PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, 2),
-		     (bar0 + MEMWIN2_BASE) | BIR(0) |
+		     mem_win2_base | BIR(0) |
 		     WINDOW(ilog2(MEMWIN2_APERTURE) - 10));
 }
 
@@ -3745,6 +4365,7 @@ static int adap_init0_config(struct adapter *adapter, int reset)
 	unsigned long mtype = 0, maddr = 0;
 	u32 finiver, finicsum, cfcsum;
 	int ret, using_flash;
+	char *fw_config_file, fw_config_file_path[256];
 
 	/*
 	 * Reset device if necessary.
@@ -3761,7 +4382,21 @@ static int adap_init0_config(struct adapter *adapter, int reset)
 	 * then use that.  Otherwise, use the configuration file stored
 	 * in the adapter flash ...
 	 */
-	ret = request_firmware(&cf, FW_CFNAME, adapter->pdev_dev);
+	switch (CHELSIO_CHIP_VERSION(adapter->chip)) {
+	case CHELSIO_T4:
+		fw_config_file = FW_CFNAME;
+		break;
+	case CHELSIO_T5:
+		fw_config_file = FW5_CFNAME;
+		break;
+	default:
+		dev_err(adapter->pdev_dev, "Device %d is not supported\n",
+		       adapter->pdev->device);
+		ret = -EINVAL;
+		goto bye;
+	}
+
+	ret = request_firmware(&cf, fw_config_file, adapter->pdev_dev);
 	if (ret < 0) {
 		using_flash = 1;
 		mtype = FW_MEMTYPE_CF_FLASH;
@@ -3877,6 +4512,7 @@ static int adap_init0_config(struct adapter *adapter, int reset)
 	if (ret < 0)
 		goto bye;
 
+	sprintf(fw_config_file_path, "/lib/firmware/%s", fw_config_file);
 	/*
 	 * Return successfully and note that we're operating with parameters
 	 * not supplied by the driver, rather than from hard-wired
@@ -3887,7 +4523,7 @@ static int adap_init0_config(struct adapter *adapter, int reset)
 		 "Configuration File %s, version %#x, computed checksum %#x\n",
 		 (using_flash
 		  ? "in device FLASH"
-		  : "/lib/firmware/" FW_CFNAME),
+		  : fw_config_file_path),
 		 finiver, cfcsum);
 	return 0;
 
@@ -4814,7 +5450,8 @@ static void print_port_info(const struct net_device *dev)
 	sprintf(bufp, "BASE-%s", base[pi->port_type]);
 
 	netdev_info(dev, "Chelsio %s rev %d %s %sNIC PCIe x%d%s%s\n",
-		    adap->params.vpd.id, adap->params.rev, buf,
+		    adap->params.vpd.id,
+		    CHELSIO_CHIP_RELEASE(adap->params.rev), buf,
 		    is_offload(adap) ? "R" : "", adap->params.pci.width, spd,
 		    (adap->flags & USING_MSIX) ? " MSI-X" :
 		    (adap->flags & USING_MSI) ? " MSI" : "");
@@ -4854,10 +5491,11 @@ static void free_some_resources(struct adapter *adapter)
 #define TSO_FLAGS (NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_TSO_ECN)
 #define VLAN_FEAT (NETIF_F_SG | NETIF_F_IP_CSUM | TSO_FLAGS | \
 		   NETIF_F_IPV6_CSUM | NETIF_F_HIGHDMA)
+#define SEGMENT_SIZE 128
 
 static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
-	int func, i, err;
+	int func, i, err, s_qpp, qpp, num_seg;
 	struct port_info *pi;
 	bool highdma = false;
 	struct adapter *adapter = NULL;
@@ -4934,7 +5572,34 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	err = t4_prep_adapter(adapter);
 	if (err)
-		goto out_unmap_bar;
+		goto out_unmap_bar0;
+
+	if (!is_t4(adapter->chip)) {
+		s_qpp = QUEUESPERPAGEPF1 * adapter->fn;
+		qpp = 1 << QUEUESPERPAGEPF0_GET(t4_read_reg(adapter,
+		      SGE_EGRESS_QUEUES_PER_PAGE_PF) >> s_qpp);
+		num_seg = PAGE_SIZE / SEGMENT_SIZE;
+
+		/* Each segment size is 128B. Write coalescing is enabled only
+		 * when SGE_EGRESS_QUEUES_PER_PAGE_PF reg value for the
+		 * queue is less no of segments that can be accommodated in
+		 * a page size.
+		 */
+		if (qpp > num_seg) {
+			dev_err(&pdev->dev,
+				"Incorrect number of egress queues per page\n");
+			err = -EINVAL;
+			goto out_unmap_bar0;
+		}
+		adapter->bar2 = ioremap_wc(pci_resource_start(pdev, 2),
+		pci_resource_len(pdev, 2));
+		if (!adapter->bar2) {
+			dev_err(&pdev->dev, "cannot map device bar2 region\n");
+			err = -ENOMEM;
+			goto out_unmap_bar0;
+		}
+	}
+
 	setup_memwin(adapter);
 	err = adap_init0(adapter);
 	setup_memwin_rdma(adapter);
@@ -5063,6 +5728,9 @@ sriov:
  out_free_dev:
 	free_some_resources(adapter);
  out_unmap_bar:
+	if (!is_t4(adapter->chip))
+		iounmap(adapter->bar2);
+ out_unmap_bar0:
 	iounmap(adapter->regs);
  out_free_adapter:
 	kfree(adapter);
@@ -5113,6 +5781,8 @@ static void remove_one(struct pci_dev *pdev)
 
 		free_some_resources(adapter);
 		iounmap(adapter->regs);
+		if (!is_t4(adapter->chip))
+			iounmap(adapter->bar2);
 		kfree(adapter);
 		pci_disable_pcie_error_reporting(pdev);
 		pci_disable_device(pdev);
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
index e2bbc7f3e..4faf4d0 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
@@ -269,4 +269,7 @@ struct sk_buff *cxgb4_pktgl_to_skb(const struct pkt_gl *gl,
 				   unsigned int skb_len, unsigned int pull_len);
 int cxgb4_sync_txq_pidx(struct net_device *dev, u16 qid, u16 pidx, u16 size);
 int cxgb4_flush_eq_cache(struct net_device *dev);
+void cxgb4_disable_db_coalescing(struct net_device *dev);
+void cxgb4_enable_db_coalescing(struct net_device *dev);
+
 #endif  /* !__CXGB4_OFLD_H */
diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c
index fe9a2ea..8b47b25 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c
@@ -506,10 +506,14 @@ static void unmap_rx_buf(struct adapter *adap, struct sge_fl *q)
 
 static inline void ring_fl_db(struct adapter *adap, struct sge_fl *q)
 {
+	u32 val;
 	if (q->pend_cred >= 8) {
+		val = PIDX(q->pend_cred / 8);
+		if (!is_t4(adap->chip))
+			val |= DBTYPE(1);
 		wmb();
 		t4_write_reg(adap, MYPF_REG(SGE_PF_KDOORBELL), DBPRIO(1) |
-			     QID(q->cntxt_id) | PIDX(q->pend_cred / 8));
+			     QID(q->cntxt_id) | val);
 		q->pend_cred &= 7;
 	}
 }
@@ -812,6 +816,22 @@ static void write_sgl(const struct sk_buff *skb, struct sge_txq *q,
 		*end = 0;
 }
 
+/* This function copies 64 byte coalesced work request to
+ * memory mapped BAR2 space(user space writes).
+ * For coalesced WR SGE, fetches data from the FIFO instead of from Host.
+ */
+static void cxgb_pio_copy(u64 __iomem *dst, u64 *src)
+{
+	int count = 8;
+
+	while (count) {
+		writeq(*src, dst);
+		src++;
+		dst++;
+		count--;
+	}
+}
+
 /**
  *	ring_tx_db - check and potentially ring a Tx queue's doorbell
  *	@adap: the adapter
@@ -822,11 +842,25 @@ static void write_sgl(const struct sk_buff *skb, struct sge_txq *q,
  */
 static inline void ring_tx_db(struct adapter *adap, struct sge_txq *q, int n)
 {
+	unsigned int *wr, index;
+
 	wmb();            /* write descriptors before telling HW */
 	spin_lock(&q->db_lock);
 	if (!q->db_disabled) {
-		t4_write_reg(adap, MYPF_REG(SGE_PF_KDOORBELL),
-			     QID(q->cntxt_id) | PIDX(n));
+		if (is_t4(adap->chip)) {
+			t4_write_reg(adap, MYPF_REG(SGE_PF_KDOORBELL),
+				     QID(q->cntxt_id) | PIDX(n));
+		} else {
+			if (n == 1) {
+				index = q->pidx ? (q->pidx - 1) : (q->size - 1);
+				wr = (unsigned int *)&q->desc[index];
+				cxgb_pio_copy((u64 __iomem *)
+					      (adap->bar2 + q->udb + 64),
+					      (u64 *)wr);
+			} else
+				writel(n,  adap->bar2 + q->udb + 8);
+			wmb();
+		}
 	}
 	q->db_pidx = q->pidx;
 	spin_unlock(&q->db_lock);
@@ -1555,7 +1589,6 @@ static noinline int handle_trace_pkt(struct adapter *adap,
 				     const struct pkt_gl *gl)
 {
 	struct sk_buff *skb;
-	struct cpl_trace_pkt *p;
 
 	skb = cxgb4_pktgl_to_skb(gl, RX_PULL_LEN, RX_PULL_LEN);
 	if (unlikely(!skb)) {
@@ -1563,8 +1596,11 @@ static noinline int handle_trace_pkt(struct adapter *adap,
 		return 0;
 	}
 
-	p = (struct cpl_trace_pkt *)skb->data;
-	__skb_pull(skb, sizeof(*p));
+	if (is_t4(adap->chip))
+		__skb_pull(skb, sizeof(struct cpl_trace_pkt));
+	else
+		__skb_pull(skb, sizeof(struct cpl_t5_trace_pkt));
+
 	skb_reset_mac_header(skb);
 	skb->protocol = htons(0xffff);
 	skb->dev = adap->port[0];
@@ -1625,8 +1661,10 @@ int t4_ethrx_handler(struct sge_rspq *q, const __be64 *rsp,
 	const struct cpl_rx_pkt *pkt;
 	struct sge_eth_rxq *rxq = container_of(q, struct sge_eth_rxq, rspq);
 	struct sge *s = &q->adap->sge;
+	int cpl_trace_pkt = is_t4(q->adap->chip) ?
+			    CPL_TRACE_PKT : CPL_TRACE_PKT_T5;
 
-	if (unlikely(*(u8 *)rsp == CPL_TRACE_PKT))
+	if (unlikely(*(u8 *)rsp == cpl_trace_pkt))
 		return handle_trace_pkt(q->adap, si);
 
 	pkt = (const struct cpl_rx_pkt *)rsp;
@@ -2143,11 +2181,27 @@ err:
 
 static void init_txq(struct adapter *adap, struct sge_txq *q, unsigned int id)
 {
+	q->cntxt_id = id;
+	if (!is_t4(adap->chip)) {
+		unsigned int s_qpp;
+		unsigned short udb_density;
+		unsigned long qpshift;
+		int page;
+
+		s_qpp = QUEUESPERPAGEPF1 * adap->fn;
+		udb_density = 1 << QUEUESPERPAGEPF0_GET((t4_read_reg(adap,
+				SGE_EGRESS_QUEUES_PER_PAGE_PF) >> s_qpp));
+		qpshift = PAGE_SHIFT - ilog2(udb_density);
+		q->udb = q->cntxt_id << qpshift;
+		q->udb &= PAGE_MASK;
+		page = q->udb / PAGE_SIZE;
+		q->udb += (q->cntxt_id - (page * udb_density)) * 128;
+	}
+
 	q->in_use = 0;
 	q->cidx = q->pidx = 0;
 	q->stops = q->restarts = 0;
 	q->stat = (void *)&q->desc[q->size];
-	q->cntxt_id = id;
 	spin_lock_init(&q->db_lock);
 	adap->sge.egr_map[id - adap->sge.egr_start] = q;
 }
@@ -2587,11 +2641,20 @@ static int t4_sge_init_hard(struct adapter *adap)
 	 * Set up to drop DOORBELL writes when the DOORBELL FIFO overflows
 	 * and generate an interrupt when this occurs so we can recover.
 	 */
-	t4_set_reg_field(adap, A_SGE_DBFIFO_STATUS,
-			V_HP_INT_THRESH(M_HP_INT_THRESH) |
-			V_LP_INT_THRESH(M_LP_INT_THRESH),
-			V_HP_INT_THRESH(dbfifo_int_thresh) |
-			V_LP_INT_THRESH(dbfifo_int_thresh));
+	if (is_t4(adap->chip)) {
+		t4_set_reg_field(adap, A_SGE_DBFIFO_STATUS,
+				 V_HP_INT_THRESH(M_HP_INT_THRESH) |
+				 V_LP_INT_THRESH(M_LP_INT_THRESH),
+				 V_HP_INT_THRESH(dbfifo_int_thresh) |
+				 V_LP_INT_THRESH(dbfifo_int_thresh));
+	} else {
+		t4_set_reg_field(adap, A_SGE_DBFIFO_STATUS,
+				 V_LP_INT_THRESH_T5(M_LP_INT_THRESH_T5),
+				 V_LP_INT_THRESH_T5(dbfifo_int_thresh));
+		t4_set_reg_field(adap, SGE_DBFIFO_STATUS2,
+				 V_HP_INT_THRESH_T5(M_HP_INT_THRESH_T5),
+				 V_HP_INT_THRESH_T5(dbfifo_int_thresh));
+	}
 	t4_set_reg_field(adap, A_SGE_DOORBELL_CONTROL, F_ENABLE_DROP,
 			F_ENABLE_DROP);
 
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
index 8049268..d02d4e8 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
@@ -282,6 +282,7 @@ int t4_wr_mbox_meat(struct adapter *adap, int mbox, const void *cmd, int size,
  *	t4_mc_read - read from MC through backdoor accesses
  *	@adap: the adapter
  *	@addr: address of first byte requested
+ *	@idx: which MC to access
  *	@data: 64 bytes of data containing the requested address
  *	@ecc: where to store the corresponding 64-bit ECC word
  *
@@ -289,22 +290,38 @@ int t4_wr_mbox_meat(struct adapter *adap, int mbox, const void *cmd, int size,
  *	that covers the requested address @addr.  If @parity is not %NULL it
  *	is assigned the 64-bit ECC word for the read data.
  */
-int t4_mc_read(struct adapter *adap, u32 addr, __be32 *data, u64 *ecc)
+int t4_mc_read(struct adapter *adap, int idx, u32 addr, __be32 *data, u64 *ecc)
 {
 	int i;
+	u32 mc_bist_cmd, mc_bist_cmd_addr, mc_bist_cmd_len;
+	u32 mc_bist_status_rdata, mc_bist_data_pattern;
+
+	if (is_t4(adap->chip)) {
+		mc_bist_cmd = MC_BIST_CMD;
+		mc_bist_cmd_addr = MC_BIST_CMD_ADDR;
+		mc_bist_cmd_len = MC_BIST_CMD_LEN;
+		mc_bist_status_rdata = MC_BIST_STATUS_RDATA;
+		mc_bist_data_pattern = MC_BIST_DATA_PATTERN;
+	} else {
+		mc_bist_cmd = MC_REG(MC_P_BIST_CMD, idx);
+		mc_bist_cmd_addr = MC_REG(MC_P_BIST_CMD_ADDR, idx);
+		mc_bist_cmd_len = MC_REG(MC_P_BIST_CMD_LEN, idx);
+		mc_bist_status_rdata = MC_REG(MC_P_BIST_STATUS_RDATA, idx);
+		mc_bist_data_pattern = MC_REG(MC_P_BIST_DATA_PATTERN, idx);
+	}
 
-	if (t4_read_reg(adap, MC_BIST_CMD) & START_BIST)
+	if (t4_read_reg(adap, mc_bist_cmd) & START_BIST)
 		return -EBUSY;
-	t4_write_reg(adap, MC_BIST_CMD_ADDR, addr & ~0x3fU);
-	t4_write_reg(adap, MC_BIST_CMD_LEN, 64);
-	t4_write_reg(adap, MC_BIST_DATA_PATTERN, 0xc);
-	t4_write_reg(adap, MC_BIST_CMD, BIST_OPCODE(1) | START_BIST |
+	t4_write_reg(adap, mc_bist_cmd_addr, addr & ~0x3fU);
+	t4_write_reg(adap, mc_bist_cmd_len, 64);
+	t4_write_reg(adap, mc_bist_data_pattern, 0xc);
+	t4_write_reg(adap, mc_bist_cmd, BIST_OPCODE(1) | START_BIST |
 		     BIST_CMD_GAP(1));
-	i = t4_wait_op_done(adap, MC_BIST_CMD, START_BIST, 0, 10, 1);
+	i = t4_wait_op_done(adap, mc_bist_cmd, START_BIST, 0, 10, 1);
 	if (i)
 		return i;
 
-#define MC_DATA(i) MC_BIST_STATUS_REG(MC_BIST_STATUS_RDATA, i)
+#define MC_DATA(i) MC_BIST_STATUS_REG(mc_bist_status_rdata, i)
 
 	for (i = 15; i >= 0; i--)
 		*data++ = htonl(t4_read_reg(adap, MC_DATA(i)));
@@ -329,20 +346,39 @@ int t4_mc_read(struct adapter *adap, u32 addr, __be32 *data, u64 *ecc)
 int t4_edc_read(struct adapter *adap, int idx, u32 addr, __be32 *data, u64 *ecc)
 {
 	int i;
+	u32 edc_bist_cmd, edc_bist_cmd_addr, edc_bist_cmd_len;
+	u32 edc_bist_cmd_data_pattern, edc_bist_status_rdata;
+
+	if (is_t4(adap->chip)) {
+		edc_bist_cmd = EDC_REG(EDC_BIST_CMD, idx);
+		edc_bist_cmd_addr = EDC_REG(EDC_BIST_CMD_ADDR, idx);
+		edc_bist_cmd_len = EDC_REG(EDC_BIST_CMD_LEN, idx);
+		edc_bist_cmd_data_pattern = EDC_REG(EDC_BIST_DATA_PATTERN,
+						    idx);
+		edc_bist_status_rdata = EDC_REG(EDC_BIST_STATUS_RDATA,
+						    idx);
+	} else {
+		edc_bist_cmd = EDC_REG_T5(EDC_H_BIST_CMD, idx);
+		edc_bist_cmd_addr = EDC_REG_T5(EDC_H_BIST_CMD_ADDR, idx);
+		edc_bist_cmd_len = EDC_REG_T5(EDC_H_BIST_CMD_LEN, idx);
+		edc_bist_cmd_data_pattern =
+			EDC_REG_T5(EDC_H_BIST_DATA_PATTERN, idx);
+		edc_bist_status_rdata =
+			 EDC_REG_T5(EDC_H_BIST_STATUS_RDATA, idx);
+	}
 
-	idx *= EDC_STRIDE;
-	if (t4_read_reg(adap, EDC_BIST_CMD + idx) & START_BIST)
+	if (t4_read_reg(adap, edc_bist_cmd) & START_BIST)
 		return -EBUSY;
-	t4_write_reg(adap, EDC_BIST_CMD_ADDR + idx, addr & ~0x3fU);
-	t4_write_reg(adap, EDC_BIST_CMD_LEN + idx, 64);
-	t4_write_reg(adap, EDC_BIST_DATA_PATTERN + idx, 0xc);
-	t4_write_reg(adap, EDC_BIST_CMD + idx,
+	t4_write_reg(adap, edc_bist_cmd_addr, addr & ~0x3fU);
+	t4_write_reg(adap, edc_bist_cmd_len, 64);
+	t4_write_reg(adap, edc_bist_cmd_data_pattern, 0xc);
+	t4_write_reg(adap, edc_bist_cmd,
 		     BIST_OPCODE(1) | BIST_CMD_GAP(1) | START_BIST);
-	i = t4_wait_op_done(adap, EDC_BIST_CMD + idx, START_BIST, 0, 10, 1);
+	i = t4_wait_op_done(adap, edc_bist_cmd, START_BIST, 0, 10, 1);
 	if (i)
 		return i;
 
-#define EDC_DATA(i) (EDC_BIST_STATUS_REG(EDC_BIST_STATUS_RDATA, i) + idx)
+#define EDC_DATA(i) (EDC_BIST_STATUS_REG(edc_bist_status_rdata, i))
 
 	for (i = 15; i >= 0; i--)
 		*data++ = htonl(t4_read_reg(adap, EDC_DATA(i)));
@@ -366,6 +402,7 @@ int t4_edc_read(struct adapter *adap, int idx, u32 addr, __be32 *data, u64 *ecc)
 static int t4_mem_win_rw(struct adapter *adap, u32 addr, __be32 *data, int dir)
 {
 	int i;
+	u32 win_pf = is_t4(adap->chip) ? 0 : V_PFNUM(adap->fn);
 
 	/*
 	 * Setup offset into PCIE memory window.  Address must be a
@@ -374,7 +411,7 @@ static int t4_mem_win_rw(struct adapter *adap, u32 addr, __be32 *data, int dir)
 	 * values.)
 	 */
 	t4_write_reg(adap, PCIE_MEM_ACCESS_OFFSET,
-		     addr & ~(MEMWIN0_APERTURE - 1));
+		     (addr & ~(MEMWIN0_APERTURE - 1)) | win_pf);
 	t4_read_reg(adap, PCIE_MEM_ACCESS_OFFSET);
 
 	/* Collecting data 4 bytes at a time upto MEMWIN0_APERTURE */
@@ -410,6 +447,7 @@ static int t4_memory_rw(struct adapter *adap, int mtype, u32 addr, u32 len,
 			__be32 *buf, int dir)
 {
 	u32 pos, start, end, offset, memoffset;
+	u32 edc_size, mc_size;
 	int ret = 0;
 	__be32 *data;
 
@@ -423,13 +461,21 @@ static int t4_memory_rw(struct adapter *adap, int mtype, u32 addr, u32 len,
 	if (!data)
 		return -ENOMEM;
 
-	/*
-	 * Offset into the region of memory which is being accessed
+	/* Offset into the region of memory which is being accessed
 	 * MEM_EDC0 = 0
 	 * MEM_EDC1 = 1
-	 * MEM_MC   = 2
+	 * MEM_MC   = 2 -- T4
+	 * MEM_MC0  = 2 -- For T5
+	 * MEM_MC1  = 3 -- For T5
 	 */
-	memoffset = (mtype * (5 * 1024 * 1024));
+	edc_size  = EDRAM_SIZE_GET(t4_read_reg(adap, MA_EDRAM0_BAR));
+	if (mtype != MEM_MC1)
+		memoffset = (mtype * (edc_size * 1024 * 1024));
+	else {
+		mc_size = EXT_MEM_SIZE_GET(t4_read_reg(adap,
+						       MA_EXT_MEMORY_BAR));
+		memoffset = (MEM_MC0 * edc_size + mc_size) * 1024 * 1024;
+	}
 
 	/* Determine the PCIE_MEM_ACCESS_OFFSET */
 	addr = addr + memoffset;
@@ -497,9 +543,9 @@ int t4_memory_write(struct adapter *adap, int mtype, u32 addr, u32 len,
 }
 
 #define EEPROM_STAT_ADDR   0x7bfc
-#define VPD_LEN            512
 #define VPD_BASE           0x400
 #define VPD_BASE_OLD       0
+#define VPD_LEN            1024
 
 /**
  *	t4_seeprom_wp - enable/disable EEPROM write protection
@@ -856,6 +902,7 @@ int t4_check_fw_version(struct adapter *adapter)
 {
 	u32 api_vers[2];
 	int ret, major, minor, micro;
+	int exp_major, exp_minor, exp_micro;
 
 	ret = get_fw_version(adapter, &adapter->params.fw_vers);
 	if (!ret)
@@ -870,17 +917,35 @@ int t4_check_fw_version(struct adapter *adapter)
 	major = FW_HDR_FW_VER_MAJOR_GET(adapter->params.fw_vers);
 	minor = FW_HDR_FW_VER_MINOR_GET(adapter->params.fw_vers);
 	micro = FW_HDR_FW_VER_MICRO_GET(adapter->params.fw_vers);
+
+	switch (CHELSIO_CHIP_VERSION(adapter->chip)) {
+	case CHELSIO_T4:
+		exp_major = FW_VERSION_MAJOR;
+		exp_minor = FW_VERSION_MINOR;
+		exp_micro = FW_VERSION_MICRO;
+		break;
+	case CHELSIO_T5:
+		exp_major = FW_VERSION_MAJOR_T5;
+		exp_minor = FW_VERSION_MINOR_T5;
+		exp_micro = FW_VERSION_MICRO_T5;
+		break;
+	default:
+		dev_err(adapter->pdev_dev, "Unsupported chip type, %x\n",
+			adapter->chip);
+		return -EINVAL;
+	}
+
 	memcpy(adapter->params.api_vers, api_vers,
 	       sizeof(adapter->params.api_vers));
 
-	if (major != FW_VERSION_MAJOR) {            /* major mismatch - fail */
+	if (major != exp_major) {            /* major mismatch - fail */
 		dev_err(adapter->pdev_dev,
 			"card FW has major version %u, driver wants %u\n",
-			major, FW_VERSION_MAJOR);
+			major, exp_major);
 		return -EINVAL;
 	}
 
-	if (minor == FW_VERSION_MINOR && micro == FW_VERSION_MICRO)
+	if (minor == exp_minor && micro == exp_micro)
 		return 0;                                   /* perfect match */
 
 	/* Minor/micro version mismatch.  Report it but often it's OK. */
@@ -1246,6 +1311,45 @@ static void pcie_intr_handler(struct adapter *adapter)
 		{ 0 }
 	};
 
+	static struct intr_info t5_pcie_intr_info[] = {
+		{ MSTGRPPERR, "Master Response Read Queue parity error",
+		  -1, 1 },
+		{ MSTTIMEOUTPERR, "Master Timeout FIFO parity error", -1, 1 },
+		{ MSIXSTIPERR, "MSI-X STI SRAM parity error", -1, 1 },
+		{ MSIXADDRLPERR, "MSI-X AddrL parity error", -1, 1 },
+		{ MSIXADDRHPERR, "MSI-X AddrH parity error", -1, 1 },
+		{ MSIXDATAPERR, "MSI-X data parity error", -1, 1 },
+		{ MSIXDIPERR, "MSI-X DI parity error", -1, 1 },
+		{ PIOCPLGRPPERR, "PCI PIO completion Group FIFO parity error",
+		  -1, 1 },
+		{ PIOREQGRPPERR, "PCI PIO request Group FIFO parity error",
+		  -1, 1 },
+		{ TARTAGPERR, "PCI PCI target tag FIFO parity error", -1, 1 },
+		{ MSTTAGQPERR, "PCI master tag queue parity error", -1, 1 },
+		{ CREQPERR, "PCI CMD channel request parity error", -1, 1 },
+		{ CRSPPERR, "PCI CMD channel response parity error", -1, 1 },
+		{ DREQWRPERR, "PCI DMA channel write request parity error",
+		  -1, 1 },
+		{ DREQPERR, "PCI DMA channel request parity error", -1, 1 },
+		{ DRSPPERR, "PCI DMA channel response parity error", -1, 1 },
+		{ HREQWRPERR, "PCI HMA channel count parity error", -1, 1 },
+		{ HREQPERR, "PCI HMA channel request parity error", -1, 1 },
+		{ HRSPPERR, "PCI HMA channel response parity error", -1, 1 },
+		{ CFGSNPPERR, "PCI config snoop FIFO parity error", -1, 1 },
+		{ FIDPERR, "PCI FID parity error", -1, 1 },
+		{ VFIDPERR, "PCI INTx clear parity error", -1, 1 },
+		{ MAGRPPERR, "PCI MA group FIFO parity error", -1, 1 },
+		{ PIOTAGPERR, "PCI PIO tag parity error", -1, 1 },
+		{ IPRXHDRGRPPERR, "PCI IP Rx header group parity error",
+		  -1, 1 },
+		{ IPRXDATAGRPPERR, "PCI IP Rx data group parity error", -1, 1 },
+		{ RPLPERR, "PCI IP replay buffer parity error", -1, 1 },
+		{ IPSOTPERR, "PCI IP SOT buffer parity error", -1, 1 },
+		{ TRGT1GRPPERR, "PCI TRGT1 group FIFOs parity error", -1, 1 },
+		{ READRSPERR, "Outbound read error", -1, 0 },
+		{ 0 }
+	};
+
 	int fat;
 
 	fat = t4_handle_intr_status(adapter,
@@ -1254,7 +1358,10 @@ static void pcie_intr_handler(struct adapter *adapter)
 	      t4_handle_intr_status(adapter,
 				    PCIE_CORE_UTL_PCI_EXPRESS_PORT_STATUS,
 				    pcie_port_intr_info) +
-	      t4_handle_intr_status(adapter, PCIE_INT_CAUSE, pcie_intr_info);
+	      t4_handle_intr_status(adapter, PCIE_INT_CAUSE,
+				    is_t4(adapter->chip) ?
+				    pcie_intr_info : t5_pcie_intr_info);
+
 	if (fat)
 		t4_fatal_err(adapter);
 }
@@ -1664,7 +1771,14 @@ static void ncsi_intr_handler(struct adapter *adap)
  */
 static void xgmac_intr_handler(struct adapter *adap, int port)
 {
-	u32 v = t4_read_reg(adap, PORT_REG(port, XGMAC_PORT_INT_CAUSE));
+	u32 v, int_cause_reg;
+
+	if (is_t4(adap->chip))
+		int_cause_reg = PORT_REG(port, XGMAC_PORT_INT_CAUSE);
+	else
+		int_cause_reg = T5_PORT_REG(port, MAC_PORT_INT_CAUSE);
+
+	v = t4_read_reg(adap, int_cause_reg);
 
 	v &= TXFIFO_PRTY_ERR | RXFIFO_PRTY_ERR;
 	if (!v)
@@ -2126,7 +2240,9 @@ void t4_get_port_stats(struct adapter *adap, int idx, struct port_stats *p)
 	u32 bgmap = get_mps_bg_map(adap, idx);
 
 #define GET_STAT(name) \
-	t4_read_reg64(adap, PORT_REG(idx, MPS_PORT_STAT_##name##_L))
+	t4_read_reg64(adap, \
+	(is_t4(adap->chip) ? PORT_REG(idx, MPS_PORT_STAT_##name##_L) : \
+	T5_PORT_REG(idx, MPS_PORT_STAT_##name##_L)))
 #define GET_STAT_COM(name) t4_read_reg64(adap, MPS_STAT_##name##_L)
 
 	p->tx_octets           = GET_STAT(TX_PORT_BYTES);
@@ -2205,14 +2321,26 @@ void t4_get_port_stats(struct adapter *adap, int idx, struct port_stats *p)
 void t4_wol_magic_enable(struct adapter *adap, unsigned int port,
 			 const u8 *addr)
 {
+	u32 mag_id_reg_l, mag_id_reg_h, port_cfg_reg;
+
+	if (is_t4(adap->chip)) {
+		mag_id_reg_l = PORT_REG(port, XGMAC_PORT_MAGIC_MACID_LO);
+		mag_id_reg_h = PORT_REG(port, XGMAC_PORT_MAGIC_MACID_HI);
+		port_cfg_reg = PORT_REG(port, XGMAC_PORT_CFG2);
+	} else {
+		mag_id_reg_l = T5_PORT_REG(port, MAC_PORT_MAGIC_MACID_LO);
+		mag_id_reg_h = T5_PORT_REG(port, MAC_PORT_MAGIC_MACID_HI);
+		port_cfg_reg = T5_PORT_REG(port, MAC_PORT_CFG2);
+	}
+
 	if (addr) {
-		t4_write_reg(adap, PORT_REG(port, XGMAC_PORT_MAGIC_MACID_LO),
+		t4_write_reg(adap, mag_id_reg_l,
 			     (addr[2] << 24) | (addr[3] << 16) |
 			     (addr[4] << 8) | addr[5]);
-		t4_write_reg(adap, PORT_REG(port, XGMAC_PORT_MAGIC_MACID_HI),
+		t4_write_reg(adap, mag_id_reg_h,
 			     (addr[0] << 8) | addr[1]);
 	}
-	t4_set_reg_field(adap, PORT_REG(port, XGMAC_PORT_CFG2), MAGICEN,
+	t4_set_reg_field(adap, port_cfg_reg, MAGICEN,
 			 addr ? MAGICEN : 0);
 }
 
@@ -2235,16 +2363,23 @@ int t4_wol_pat_enable(struct adapter *adap, unsigned int port, unsigned int map,
 		      u64 mask0, u64 mask1, unsigned int crc, bool enable)
 {
 	int i;
+	u32 port_cfg_reg;
+
+	if (is_t4(adap->chip))
+		port_cfg_reg = PORT_REG(port, XGMAC_PORT_CFG2);
+	else
+		port_cfg_reg = T5_PORT_REG(port, MAC_PORT_CFG2);
 
 	if (!enable) {
-		t4_set_reg_field(adap, PORT_REG(port, XGMAC_PORT_CFG2),
-				 PATEN, 0);
+		t4_set_reg_field(adap, port_cfg_reg, PATEN, 0);
 		return 0;
 	}
 	if (map > 0xff)
 		return -EINVAL;
 
-#define EPIO_REG(name) PORT_REG(port, XGMAC_PORT_EPIO_##name)
+#define EPIO_REG(name) \
+	(is_t4(adap->chip) ? PORT_REG(port, XGMAC_PORT_EPIO_##name) : \
+	T5_PORT_REG(port, MAC_PORT_EPIO_##name))
 
 	t4_write_reg(adap, EPIO_REG(DATA1), mask0 >> 32);
 	t4_write_reg(adap, EPIO_REG(DATA2), mask1);
@@ -2322,24 +2457,24 @@ int t4_fwaddrspace_write(struct adapter *adap, unsigned int mbox,
  *     @addr: address of first byte requested aligned on 32b.
  *     @data: len bytes to hold the data read
  *     @len: amount of data to read from window.  Must be <=
- *            MEMWIN0_APERATURE after adjusting for 16B alignment
- *            requirements of the the memory window.
+ *            MEMWIN0_APERATURE after adjusting for 16B for T4 and
+ *            128B for T5 alignment requirements of the the memory window.
  *
  *     Read len bytes of data from MC starting at @addr.
  */
 int t4_mem_win_read_len(struct adapter *adap, u32 addr, __be32 *data, int len)
 {
-	int i;
-	int off;
+	int i, off;
+	u32 win_pf = is_t4(adap->chip) ? 0 : V_PFNUM(adap->fn);
 
-	/*
-	 * Align on a 16B boundary.
+	/* Align on a 2KB boundary.
 	 */
-	off = addr & 15;
+	off = addr & MEMWIN0_APERTURE;
 	if ((addr & 3) || (len + off) > MEMWIN0_APERTURE)
 		return -EINVAL;
 
-	t4_write_reg(adap, PCIE_MEM_ACCESS_OFFSET, addr & ~15);
+	t4_write_reg(adap, PCIE_MEM_ACCESS_OFFSET,
+		     (addr & ~MEMWIN0_APERTURE) | win_pf);
 	t4_read_reg(adap, PCIE_MEM_ACCESS_OFFSET);
 
 	for (i = 0; i < len; i += 4)
@@ -3162,6 +3297,9 @@ int t4_alloc_mac_filt(struct adapter *adap, unsigned int mbox,
 	int i, ret;
 	struct fw_vi_mac_cmd c;
 	struct fw_vi_mac_exact *p;
+	unsigned int max_naddr = is_t4(adap->chip) ?
+				       NUM_MPS_CLS_SRAM_L_INSTANCES :
+				       NUM_MPS_T5_CLS_SRAM_L_INSTANCES;
 
 	if (naddr > 7)
 		return -EINVAL;
@@ -3187,8 +3325,8 @@ int t4_alloc_mac_filt(struct adapter *adap, unsigned int mbox,
 		u16 index = FW_VI_MAC_CMD_IDX_GET(ntohs(p->valid_to_idx));
 
 		if (idx)
-			idx[i] = index >= NEXACT_MAC ? 0xffff : index;
-		if (index < NEXACT_MAC)
+			idx[i] = index >= max_naddr ? 0xffff : index;
+		if (index < max_naddr)
 			ret++;
 		else if (hash)
 			*hash |= (1ULL << hash_mac_addr(addr[i]));
@@ -3221,6 +3359,9 @@ int t4_change_mac(struct adapter *adap, unsigned int mbox, unsigned int viid,
 	int ret, mode;
 	struct fw_vi_mac_cmd c;
 	struct fw_vi_mac_exact *p = c.u.exact;
+	unsigned int max_mac_addr = is_t4(adap->chip) ?
+				    NUM_MPS_CLS_SRAM_L_INSTANCES :
+				    NUM_MPS_T5_CLS_SRAM_L_INSTANCES;
 
 	if (idx < 0)                             /* new allocation */
 		idx = persist ? FW_VI_MAC_ADD_PERSIST_MAC : FW_VI_MAC_ADD_MAC;
@@ -3238,7 +3379,7 @@ int t4_change_mac(struct adapter *adap, unsigned int mbox, unsigned int viid,
 	ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), &c);
 	if (ret == 0) {
 		ret = FW_VI_MAC_CMD_IDX_GET(ntohs(p->valid_to_idx));
-		if (ret >= NEXACT_MAC)
+		if (ret >= max_mac_addr)
 			ret = -ENOMEM;
 	}
 	return ret;
@@ -3547,7 +3688,8 @@ static int get_flash_params(struct adapter *adap)
  */
 int t4_prep_adapter(struct adapter *adapter)
 {
-	int ret;
+	int ret, ver;
+	uint16_t device_id;
 
 	ret = t4_wait_dev_ready(adapter);
 	if (ret < 0)
@@ -3562,6 +3704,28 @@ int t4_prep_adapter(struct adapter *adapter)
 		return ret;
 	}
 
+	/* Retrieve adapter's device ID
+	 */
+	pci_read_config_word(adapter->pdev, PCI_DEVICE_ID, &device_id);
+	ver = device_id >> 12;
+	switch (ver) {
+	case CHELSIO_T4:
+		adapter->chip = CHELSIO_CHIP_CODE(CHELSIO_T4,
+						  adapter->params.rev);
+		break;
+	case CHELSIO_T5:
+		adapter->chip = CHELSIO_CHIP_CODE(CHELSIO_T5,
+						  adapter->params.rev);
+		break;
+	default:
+		dev_err(adapter->pdev_dev, "Device %d is not supported\n",
+			device_id);
+		return -EINVAL;
+	}
+
+	/* Reassign the updated revision field */
+	adapter->params.rev = adapter->chip;
+
 	init_cong_ctrl(adapter->params.a_wnd, adapter->params.b_wnd);
 
 	/*
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h
index f534ed7..1d1623b 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h
@@ -47,7 +47,6 @@ enum {
 	TCB_SIZE       = 128,   /* TCB size */
 	NMTUS          = 16,    /* size of MTU table */
 	NCCTRL_WIN     = 32,    /* # of congestion control windows */
-	NEXACT_MAC     = 336,   /* # of exact MAC address filters */
 	L2T_SIZE       = 4096,  /* # of L2T entries */
 	MBOX_LEN       = 64,    /* mailbox size in bytes */
 	TRACE_LEN      = 112,   /* length of trace data and mask */
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h b/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h
index 261d177..47656ac 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h
@@ -74,6 +74,7 @@ enum {
 	CPL_PASS_ESTABLISH    = 0x41,
 	CPL_RX_DATA_DDP       = 0x42,
 	CPL_PASS_ACCEPT_REQ   = 0x44,
+	CPL_TRACE_PKT_T5      = 0x48,
 
 	CPL_RDMA_READ_REQ     = 0x60,
 
@@ -287,6 +288,23 @@ struct cpl_act_open_req {
 	__be32 opt2;
 };
 
+#define S_FILTER_TUPLE  24
+#define M_FILTER_TUPLE  0xFFFFFFFFFF
+#define V_FILTER_TUPLE(x) ((x) << S_FILTER_TUPLE)
+#define G_FILTER_TUPLE(x) (((x) >> S_FILTER_TUPLE) & M_FILTER_TUPLE)
+struct cpl_t5_act_open_req {
+	WR_HDR;
+	union opcode_tid ot;
+	__be16 local_port;
+	__be16 peer_port;
+	__be32 local_ip;
+	__be32 peer_ip;
+	__be64 opt0;
+	__be32 rsvd;
+	__be32 opt2;
+	__be64 params;
+};
+
 struct cpl_act_open_req6 {
 	WR_HDR;
 	union opcode_tid ot;
@@ -566,6 +584,11 @@ struct cpl_rx_pkt {
 #define V_RX_ETHHDR_LEN(x) ((x) << S_RX_ETHHDR_LEN)
 #define G_RX_ETHHDR_LEN(x) (((x) >> S_RX_ETHHDR_LEN) & M_RX_ETHHDR_LEN)
 
+#define S_RX_T5_ETHHDR_LEN    0
+#define M_RX_T5_ETHHDR_LEN    0x3F
+#define V_RX_T5_ETHHDR_LEN(x) ((x) << S_RX_T5_ETHHDR_LEN)
+#define G_RX_T5_ETHHDR_LEN(x) (((x) >> S_RX_T5_ETHHDR_LEN) & M_RX_T5_ETHHDR_LEN)
+
 #define S_RX_MACIDX    8
 #define M_RX_MACIDX    0x1FF
 #define V_RX_MACIDX(x) ((x) << S_RX_MACIDX)
@@ -612,6 +635,28 @@ struct cpl_trace_pkt {
 	__be64 tstamp;
 };
 
+struct cpl_t5_trace_pkt {
+	__u8 opcode;
+	__u8 intf;
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+	__u8 runt:4;
+	__u8 filter_hit:4;
+	__u8:6;
+	__u8 err:1;
+	__u8 trunc:1;
+#else
+	__u8 filter_hit:4;
+	__u8 runt:4;
+	__u8 trunc:1;
+	__u8 err:1;
+	__u8:6;
+#endif
+	__be16 rsvd;
+	__be16 len;
+	__be64 tstamp;
+	__be64 rsvd1;
+};
+
 struct cpl_l2t_write_req {
 	WR_HDR;
 	union opcode_tid ot;
@@ -742,4 +787,12 @@ struct ulp_mem_io {
 #define ULP_MEMIO_LOCK(x) ((x) << 31)
 };
 
+#define S_T5_ULP_MEMIO_IMM    23
+#define V_T5_ULP_MEMIO_IMM(x) ((x) << S_T5_ULP_MEMIO_IMM)
+#define F_T5_ULP_MEMIO_IMM    V_T5_ULP_MEMIO_IMM(1U)
+
+#define S_T5_ULP_MEMIO_ORDER    22
+#define V_T5_ULP_MEMIO_ORDER(x) ((x) << S_T5_ULP_MEMIO_ORDER)
+#define F_T5_ULP_MEMIO_ORDER    V_T5_ULP_MEMIO_ORDER(1U)
+
 #endif  /* __T4_MSG_H */
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
index 83ec5f7..ef146c0 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
@@ -68,9 +68,14 @@
 #define  QID_SHIFT   15
 #define  QID(x)      ((x) << QID_SHIFT)
 #define  DBPRIO(x)   ((x) << 14)
+#define  DBTYPE(x)   ((x) << 13)
 #define  PIDX_MASK   0x00003fffU
 #define  PIDX_SHIFT  0
 #define  PIDX(x)     ((x) << PIDX_SHIFT)
+#define  S_PIDX_T5   0
+#define  M_PIDX_T5   0x1fffU
+#define  PIDX_T5(x)  (((x) >> S_PIDX_T5) & M_PIDX_T5)
+
 
 #define SGE_PF_GTS 0x4
 #define  INGRESSQID_MASK   0xffff0000U
@@ -152,6 +157,8 @@
 #define  QUEUESPERPAGEPF0_MASK   0x0000000fU
 #define  QUEUESPERPAGEPF0_GET(x) ((x) & QUEUESPERPAGEPF0_MASK)
 
+#define QUEUESPERPAGEPF1    4
+
 #define SGE_INT_CAUSE1 0x1024
 #define SGE_INT_CAUSE2 0x1030
 #define SGE_INT_CAUSE3 0x103c
@@ -234,6 +241,10 @@
 #define SGE_DOORBELL_CONTROL 0x10a8
 #define  ENABLE_DROP        (1 << 13)
 
+#define S_NOCOALESCE    26
+#define V_NOCOALESCE(x) ((x) << S_NOCOALESCE)
+#define F_NOCOALESCE    V_NOCOALESCE(1U)
+
 #define SGE_TIMER_VALUE_0_AND_1 0x10b8
 #define  TIMERVALUE0_MASK   0xffff0000U
 #define  TIMERVALUE0_SHIFT  16
@@ -272,17 +283,36 @@
 #define S_HP_INT_THRESH    28
 #define M_HP_INT_THRESH 0xfU
 #define V_HP_INT_THRESH(x) ((x) << S_HP_INT_THRESH)
+#define S_LP_INT_THRESH_T5    18
+#define V_LP_INT_THRESH_T5(x) ((x) << S_LP_INT_THRESH_T5)
+#define M_LP_COUNT_T5    0x3ffffU
+#define G_LP_COUNT_T5(x) (((x) >> S_LP_COUNT) & M_LP_COUNT_T5)
 #define M_HP_COUNT 0x7ffU
 #define S_HP_COUNT 16
 #define G_HP_COUNT(x) (((x) >> S_HP_COUNT) & M_HP_COUNT)
 #define S_LP_INT_THRESH    12
 #define M_LP_INT_THRESH 0xfU
+#define M_LP_INT_THRESH_T5    0xfffU
 #define V_LP_INT_THRESH(x) ((x) << S_LP_INT_THRESH)
 #define M_LP_COUNT 0x7ffU
 #define S_LP_COUNT 0
 #define G_LP_COUNT(x) (((x) >> S_LP_COUNT) & M_LP_COUNT)
 #define A_SGE_DBFIFO_STATUS 0x10a4
 
+#define SGE_STAT_TOTAL 0x10e4
+#define SGE_STAT_MATCH 0x10e8
+
+#define SGE_STAT_CFG   0x10ec
+#define S_STATSOURCE_T5    9
+#define STATSOURCE_T5(x) ((x) << S_STATSOURCE_T5)
+
+#define SGE_DBFIFO_STATUS2 0x1118
+#define M_HP_COUNT_T5    0x3ffU
+#define G_HP_COUNT_T5(x) ((x)  & M_HP_COUNT_T5)
+#define S_HP_INT_THRESH_T5    10
+#define M_HP_INT_THRESH_T5    0xfU
+#define V_HP_INT_THRESH_T5(x) ((x) << S_HP_INT_THRESH_T5)
+
 #define S_ENABLE_DROP    13
 #define V_ENABLE_DROP(x) ((x) << S_ENABLE_DROP)
 #define F_ENABLE_DROP    V_ENABLE_DROP(1U)
@@ -331,8 +361,27 @@
 #define  MSIADDRHPERR  0x00000002U
 #define  MSIADDRLPERR  0x00000001U
 
+#define  READRSPERR      0x20000000U
+#define  TRGT1GRPPERR    0x10000000U
+#define  IPSOTPERR       0x08000000U
+#define  IPRXDATAGRPPERR 0x02000000U
+#define  IPRXHDRGRPPERR  0x01000000U
+#define  MAGRPPERR       0x00400000U
+#define  VFIDPERR        0x00200000U
+#define  HREQWRPERR      0x00010000U
+#define  DREQWRPERR      0x00002000U
+#define  MSTTAGQPERR     0x00000400U
+#define  PIOREQGRPPERR   0x00000100U
+#define  PIOCPLGRPPERR   0x00000080U
+#define  MSIXSTIPERR     0x00000004U
+#define  MSTTIMEOUTPERR  0x00000002U
+#define  MSTGRPPERR      0x00000001U
+
 #define PCIE_NONFAT_ERR 0x3010
 #define PCIE_MEM_ACCESS_BASE_WIN 0x3068
+#define S_PCIEOFST       10
+#define M_PCIEOFST       0x3fffffU
+#define GET_PCIEOFST(x)  (((x) >> S_PCIEOFST) & M_PCIEOFST)
 #define  PCIEOFST_MASK   0xfffffc00U
 #define  BIR_MASK        0x00000300U
 #define  BIR_SHIFT       8
@@ -342,6 +391,9 @@
 #define  WINDOW(x)       ((x) << WINDOW_SHIFT)
 #define PCIE_MEM_ACCESS_OFFSET 0x306c
 
+#define S_PFNUM    0
+#define V_PFNUM(x) ((x) << S_PFNUM)
+
 #define PCIE_FW 0x30b8
 #define  PCIE_FW_ERR		0x80000000U
 #define  PCIE_FW_INIT		0x40000000U
@@ -407,12 +459,18 @@
 
 #define MC_BIST_STATUS_RDATA 0x7688
 
+#define MA_EDRAM0_BAR 0x77c0
+#define MA_EDRAM1_BAR 0x77c4
+#define EDRAM_SIZE_MASK   0xfffU
+#define EDRAM_SIZE_GET(x) ((x) & EDRAM_SIZE_MASK)
+
 #define MA_EXT_MEMORY_BAR 0x77c8
 #define  EXT_MEM_SIZE_MASK   0x00000fffU
 #define  EXT_MEM_SIZE_SHIFT  0
 #define  EXT_MEM_SIZE_GET(x) (((x) & EXT_MEM_SIZE_MASK) >> EXT_MEM_SIZE_SHIFT)
 
 #define MA_TARGET_MEM_ENABLE 0x77d8
+#define  EXT_MEM1_ENABLE 0x00000010U
 #define  EXT_MEM_ENABLE 0x00000004U
 #define  EDRAM1_ENABLE  0x00000002U
 #define  EDRAM0_ENABLE  0x00000001U
@@ -431,6 +489,7 @@
 #define MA_PCIE_FW 0x30b8
 #define MA_PARITY_ERROR_STATUS 0x77f4
 
+#define MA_EXT_MEMORY1_BAR 0x7808
 #define EDC_0_BASE_ADDR 0x7900
 
 #define EDC_BIST_CMD 0x7904
@@ -801,6 +860,15 @@
 #define MPS_PORT_STAT_RX_PORT_PPP7_H 0x60c
 #define MPS_PORT_STAT_RX_PORT_LESS_64B_L 0x610
 #define MPS_PORT_STAT_RX_PORT_LESS_64B_H 0x614
+#define MAC_PORT_CFG2 0x818
+#define MAC_PORT_MAGIC_MACID_LO 0x824
+#define MAC_PORT_MAGIC_MACID_HI 0x828
+#define MAC_PORT_EPIO_DATA0 0x8c0
+#define MAC_PORT_EPIO_DATA1 0x8c4
+#define MAC_PORT_EPIO_DATA2 0x8c8
+#define MAC_PORT_EPIO_DATA3 0x8cc
+#define MAC_PORT_EPIO_OP 0x8d0
+
 #define MPS_CMN_CTL 0x9000
 #define  NUMPORTS_MASK   0x00000003U
 #define  NUMPORTS_SHIFT  0
@@ -1063,6 +1131,7 @@
 #define  ADDRESS_SHIFT  0
 #define  ADDRESS(x)     ((x) << ADDRESS_SHIFT)
 
+#define MAC_PORT_INT_CAUSE 0x8dc
 #define XGMAC_PORT_INT_CAUSE 0x10dc
 
 #define A_TP_TX_MOD_QUEUE_REQ_MAP 0x7e28
@@ -1101,4 +1170,33 @@
 #define V_PORT(x) ((x) << S_PORT)
 #define F_PORT    V_PORT(1U)
 
+#define NUM_MPS_CLS_SRAM_L_INSTANCES 336
+#define NUM_MPS_T5_CLS_SRAM_L_INSTANCES 512
+
+#define T5_PORT0_BASE 0x30000
+#define T5_PORT_STRIDE 0x4000
+#define T5_PORT_BASE(idx) (T5_PORT0_BASE + (idx) * T5_PORT_STRIDE)
+#define T5_PORT_REG(idx, reg) (T5_PORT_BASE(idx) + (reg))
+
+#define MC_0_BASE_ADDR 0x40000
+#define MC_1_BASE_ADDR 0x48000
+#define MC_STRIDE (MC_1_BASE_ADDR - MC_0_BASE_ADDR)
+#define MC_REG(reg, idx) (reg + MC_STRIDE * idx)
+
+#define MC_P_BIST_CMD 0x41400
+#define MC_P_BIST_CMD_ADDR 0x41404
+#define MC_P_BIST_CMD_LEN 0x41408
+#define MC_P_BIST_DATA_PATTERN 0x4140c
+#define MC_P_BIST_STATUS_RDATA 0x41488
+#define EDC_T50_BASE_ADDR 0x50000
+#define EDC_H_BIST_CMD 0x50004
+#define EDC_H_BIST_CMD_ADDR 0x50008
+#define EDC_H_BIST_CMD_LEN 0x5000c
+#define EDC_H_BIST_DATA_PATTERN 0x50010
+#define EDC_H_BIST_STATUS_RDATA 0x50028
+
+#define EDC_T51_BASE_ADDR 0x50800
+#define EDC_STRIDE_T5 (EDC_T51_BASE_ADDR - EDC_T50_BASE_ADDR)
+#define EDC_REG_T5(reg, idx) (reg + EDC_STRIDE_T5 * idx)
+
 #endif /* __T4_REGS_H */
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
index a0dcccd..9344432 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
@@ -574,7 +574,7 @@ struct fw_eth_tx_pkt_vm_wr {
 	__be16 vlantci;
 };
 
-#define FW_CMD_MAX_TIMEOUT 3000
+#define FW_CMD_MAX_TIMEOUT 10000
 
 /*
  * If a host driver does a HELLO and discovers that there's already a MASTER
diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/adapter.h b/drivers/net/ethernet/chelsio/cxgb4vf/adapter.h
index 68eaa9c..be5c7ef 100644
--- a/drivers/net/ethernet/chelsio/cxgb4vf/adapter.h
+++ b/drivers/net/ethernet/chelsio/cxgb4vf/adapter.h
@@ -344,6 +344,7 @@ struct adapter {
 	unsigned long registered_device_map;
 	unsigned long open_device_map;
 	unsigned long flags;
+	enum chip_type chip;
 	struct adapter_params params;
 
 	/* queue and interrupt resources */
diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
index 56b46ab..7fcac20 100644
--- a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
@@ -54,8 +54,8 @@
 /*
  * Generic information about the driver.
  */
-#define DRV_VERSION "1.0.0"
-#define DRV_DESC "Chelsio T4 Virtual Function (VF) Network Driver"
+#define DRV_VERSION "2.0.0-ko"
+#define DRV_DESC "Chelsio T4/T5 Virtual Function (VF) Network Driver"
 
 /*
  * Module Parameters.
@@ -1050,7 +1050,7 @@ static inline unsigned int mk_adap_vers(const struct adapter *adapter)
 	/*
 	 * Chip version 4, revision 0x3f (cxgb4vf).
 	 */
-	return 4 | (0x3f << 10);
+	return CHELSIO_CHIP_VERSION(adapter->chip) | (0x3f << 10);
 }
 
 /*
@@ -2099,6 +2099,15 @@ static int adap_init0(struct adapter *adapter)
 		return err;
 	}
 
+	switch (adapter->pdev->device >> 12) {
+	case CHELSIO_T4:
+		adapter->chip = CHELSIO_CHIP_CODE(CHELSIO_T4, 0);
+		break;
+	case CHELSIO_T5:
+		adapter->chip = CHELSIO_CHIP_CODE(CHELSIO_T5, 0);
+		break;
+	}
+
 	/*
 	 * Grab basic operational parameters.  These will predominantly have
 	 * been set up by the Physical Function Driver or will be hard coded
@@ -2888,6 +2897,26 @@ static struct pci_device_id cxgb4vf_pci_tbl[] = {
 	CH_DEVICE(0x480a, 0),   /* T404-bt */
 	CH_DEVICE(0x480d, 0),   /* T480-cr */
 	CH_DEVICE(0x480e, 0),   /* T440-lp-cr */
+	CH_DEVICE(0x5800, 0),	/* T580-dbg */
+	CH_DEVICE(0x5801, 0),	/* T520-cr */
+	CH_DEVICE(0x5802, 0),	/* T522-cr */
+	CH_DEVICE(0x5803, 0),	/* T540-cr */
+	CH_DEVICE(0x5804, 0),	/* T520-bch */
+	CH_DEVICE(0x5805, 0),   /* T540-bch */
+	CH_DEVICE(0x5806, 0),	/* T540-ch */
+	CH_DEVICE(0x5807, 0),	/* T520-so */
+	CH_DEVICE(0x5808, 0),	/* T520-cx */
+	CH_DEVICE(0x5809, 0),	/* T520-bt */
+	CH_DEVICE(0x580a, 0),   /* T504-bt */
+	CH_DEVICE(0x580b, 0),   /* T520-sr */
+	CH_DEVICE(0x580c, 0),   /* T504-bt */
+	CH_DEVICE(0x580d, 0),   /* T580-cr */
+	CH_DEVICE(0x580e, 0),   /* T540-lp-cr */
+	CH_DEVICE(0x580f, 0),   /* Amsterdam */
+	CH_DEVICE(0x5810, 0),   /* T580-lp-cr */
+	CH_DEVICE(0x5811, 0),   /* T520-lp-cr */
+	CH_DEVICE(0x5812, 0),   /* T560-cr */
+	CH_DEVICE(0x5813, 0),   /* T580-cr */
 	{ 0, }
 };
 
diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/sge.c b/drivers/net/ethernet/chelsio/cxgb4vf/sge.c
index 9488032..61dfb2a 100644
--- a/drivers/net/ethernet/chelsio/cxgb4vf/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb4vf/sge.c
@@ -528,17 +528,21 @@ static void unmap_rx_buf(struct adapter *adapter, struct sge_fl *fl)
  */
 static inline void ring_fl_db(struct adapter *adapter, struct sge_fl *fl)
 {
+	u32 val;
+
 	/*
 	 * The SGE keeps track of its Producer and Consumer Indices in terms
 	 * of Egress Queue Units so we can only tell it about integral numbers
 	 * of multiples of Free List Entries per Egress Queue Units ...
 	 */
 	if (fl->pend_cred >= FL_PER_EQ_UNIT) {
+		val = PIDX(fl->pend_cred / FL_PER_EQ_UNIT);
+		if (!is_t4(adapter->chip))
+			val |= DBTYPE(1);
 		wmb();
 		t4_write_reg(adapter, T4VF_SGE_BASE_ADDR + SGE_VF_KDOORBELL,
 			     DBPRIO(1) |
-			     QID(fl->cntxt_id) |
-			     PIDX(fl->pend_cred / FL_PER_EQ_UNIT));
+			     QID(fl->cntxt_id) | val);
 		fl->pend_cred %= FL_PER_EQ_UNIT;
 	}
 }
diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h b/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h
index 283f9d0..53cbfed 100644
--- a/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h
+++ b/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h
@@ -38,6 +38,25 @@
 
 #include "../cxgb4/t4fw_api.h"
 
+#define CHELSIO_CHIP_CODE(version, revision) (((version) << 4) | (revision))
+#define CHELSIO_CHIP_VERSION(code) ((code) >> 4)
+#define CHELSIO_CHIP_RELEASE(code) ((code) & 0xf)
+
+#define CHELSIO_T4		0x4
+#define CHELSIO_T5		0x5
+
+enum chip_type {
+	T4_A1 = CHELSIO_CHIP_CODE(CHELSIO_T4, 0),
+	T4_A2 = CHELSIO_CHIP_CODE(CHELSIO_T4, 1),
+	T4_A3 = CHELSIO_CHIP_CODE(CHELSIO_T4, 2),
+	T4_FIRST_REV	= T4_A1,
+	T4_LAST_REV	= T4_A3,
+
+	T5_A1 = CHELSIO_CHIP_CODE(CHELSIO_T5, 0),
+	T5_FIRST_REV	= T5_A1,
+	T5_LAST_REV	= T5_A1,
+};
+
 /*
  * The "len16" field of a Firmware Command Structure ...
  */
@@ -232,6 +251,11 @@ static inline int t4vf_wr_mbox_ns(struct adapter *adapter, const void *cmd,
 	return t4vf_wr_mbox_core(adapter, cmd, size, rpl, false);
 }
 
+static inline int is_t4(enum chip_type chip)
+{
+	return (chip >= T4_FIRST_REV && chip <= T4_LAST_REV);
+}
+
 int t4vf_wait_dev_ready(struct adapter *);
 int t4vf_port_init(struct adapter *, int);
 
diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c b/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c
index 7127c7b..9f96dc3 100644
--- a/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c
+++ b/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c
@@ -1027,8 +1027,11 @@ int t4vf_alloc_mac_filt(struct adapter *adapter, unsigned int viid, bool free,
 	unsigned nfilters = 0;
 	unsigned int rem = naddr;
 	struct fw_vi_mac_cmd cmd, rpl;
+	unsigned int max_naddr = is_t4(adapter->chip) ?
+				 NUM_MPS_CLS_SRAM_L_INSTANCES :
+				 NUM_MPS_T5_CLS_SRAM_L_INSTANCES;
 
-	if (naddr > FW_CLS_TCAM_NUM_ENTRIES)
+	if (naddr > max_naddr)
 		return -EINVAL;
 
 	for (offset = 0; offset < naddr; /**/) {
@@ -1069,10 +1072,10 @@ int t4vf_alloc_mac_filt(struct adapter *adapter, unsigned int viid, bool free,
 
 			if (idx)
 				idx[offset+i] =
-					(index >= FW_CLS_TCAM_NUM_ENTRIES
+					(index >= max_naddr
 					 ? 0xffff
 					 : index);
-			if (index < FW_CLS_TCAM_NUM_ENTRIES)
+			if (index < max_naddr)
 				nfilters++;
 			else if (hash)
 				*hash |= (1ULL << hash_mac_addr(addr[offset+i]));
@@ -1118,6 +1121,9 @@ int t4vf_change_mac(struct adapter *adapter, unsigned int viid,
 	struct fw_vi_mac_exact *p = &cmd.u.exact[0];
 	size_t len16 = DIV_ROUND_UP(offsetof(struct fw_vi_mac_cmd,
 					     u.exact[1]), 16);
+	unsigned int max_naddr = is_t4(adapter->chip) ?
+				 NUM_MPS_CLS_SRAM_L_INSTANCES :
+				 NUM_MPS_T5_CLS_SRAM_L_INSTANCES;
 
 	/*
 	 * If this is a new allocation, determine whether it should be
@@ -1140,7 +1146,7 @@ int t4vf_change_mac(struct adapter *adapter, unsigned int viid,
 	if (ret == 0) {
 		p = &rpl.u.exact[0];
 		ret = FW_VI_MAC_CMD_IDX_GET(be16_to_cpu(p->valid_to_idx));
-		if (ret >= FW_CLS_TCAM_NUM_ENTRIES)
+		if (ret >= max_naddr)
 			ret = -ENOMEM;
 	}
 	return ret;
diff --git a/drivers/net/ethernet/cirrus/cs89x0.c b/drivers/net/ethernet/cirrus/cs89x0.c
index 1384469..19f642a 100644
--- a/drivers/net/ethernet/cirrus/cs89x0.c
+++ b/drivers/net/ethernet/cirrus/cs89x0.c
@@ -101,23 +101,6 @@ static char version[] __initdata =
  * them to system IRQ numbers. This mapping is card specific and is set to
  * the configuration of the Cirrus Eval board for this chip.
  */
-#if defined(CONFIG_MACH_IXDP2351)
-#define CS89x0_NONISA_IRQ
-static unsigned int netcard_portlist[] __used __initdata = {
-	IXDP2351_VIRT_CS8900_BASE, 0
-};
-static unsigned int cs8900_irq_map[] = {
-	IRQ_IXDP2351_CS8900, 0, 0, 0
-};
-#elif defined(CONFIG_ARCH_IXDP2X01)
-#define CS89x0_NONISA_IRQ
-static unsigned int netcard_portlist[] __used __initdata = {
-	IXDP2X01_CS8900_VIRT_BASE, 0
-};
-static unsigned int cs8900_irq_map[] = {
-	IRQ_IXDP2X01_CS8900, 0, 0, 0
-};
-#else
 #ifndef CONFIG_CS89x0_PLATFORM
 static unsigned int netcard_portlist[] __used __initdata = {
 	0x300, 0x320, 0x340, 0x360, 0x200, 0x220, 0x240,
@@ -127,7 +110,6 @@ static unsigned int cs8900_irq_map[] = {
 	10, 11, 12, 5
 };
 #endif
-#endif
 
 #if DEBUGGING
 static unsigned int net_debug = DEBUGGING;
@@ -210,32 +192,6 @@ static int __init media_fn(char *str)
 __setup("cs89x0_media=", media_fn);
 #endif
 
-#if defined(CONFIG_MACH_IXDP2351)
-static u16
-readword(unsigned long base_addr, int portno)
-{
-	return __raw_readw(base_addr + (portno << 1));
-}
-
-static void
-writeword(unsigned long base_addr, int portno, u16 value)
-{
-	__raw_writew(value, base_addr + (portno << 1));
-}
-#elif defined(CONFIG_ARCH_IXDP2X01)
-static u16
-readword(unsigned long base_addr, int portno)
-{
-	return __raw_readl(base_addr + (portno << 1));
-}
-
-static void
-writeword(unsigned long base_addr, int portno, u16 value)
-{
-	__raw_writel(value, base_addr + (portno << 1));
-}
-#endif
-
 static void readwords(struct net_local *lp, int portno, void *buf, int length)
 {
 	u8 *buf8 = (u8 *)buf;
@@ -478,9 +434,6 @@ dma_rx(struct net_device *dev)
 	/* Malloc up new buffer. */
 	skb = netdev_alloc_skb(dev, length + 2);
 	if (skb == NULL) {
-		/* I don't think we want to do this to a stressed system */
-		cs89_dbg(0, err, "%s: Memory squeeze, dropping packet\n",
-			 dev->name);
 		dev->stats.rx_dropped++;
 
 		/* AKPM: advance bp to the next frame */
@@ -731,9 +684,6 @@ net_rx(struct net_device *dev)
 	/* Malloc up new buffer. */
 	skb = netdev_alloc_skb(dev, length + 2);
 	if (skb == NULL) {
-#if 0		/* Again, this seems a cruel thing to do */
-		pr_warn("%s: Memory squeeze, dropping packet\n", dev->name);
-#endif
 		dev->stats.rx_dropped++;
 		return;
 	}
@@ -908,7 +858,7 @@ net_open(struct net_device *dev)
 			goto bad_out;
 		}
 	} else {
-#if !defined(CS89x0_NONISA_IRQ) && !defined(CONFIG_CS89x0_PLATFORM)
+#if !defined(CONFIG_CS89x0_PLATFORM)
 		if (((1 << dev->irq) & lp->irq_map) == 0) {
 			pr_err("%s: IRQ %d is not in our map of allowable IRQs, which is %x\n",
 			       dev->name, dev->irq, lp->irq_map);
@@ -1321,9 +1271,7 @@ static const struct net_device_ops net_ops = {
 static void __init reset_chip(struct net_device *dev)
 {
 #if !defined(CONFIG_MACH_MX31ADS)
-#if !defined(CS89x0_NONISA_IRQ)
 	struct net_local *lp = netdev_priv(dev);
-#endif /* CS89x0_NONISA_IRQ */
 	int reset_start_time;
 
 	writereg(dev, PP_SelfCTL, readreg(dev, PP_SelfCTL) | POWER_ON_RESET);
@@ -1331,7 +1279,6 @@ static void __init reset_chip(struct net_device *dev)
 	/* wait 30 ms */
 	msleep(30);
 
-#if !defined(CS89x0_NONISA_IRQ)
 	if (lp->chip_type != CS8900) {
 		/* Hardware problem requires PNP registers to be reconfigured after a reset */
 		iowrite16(PP_CS8920_ISAINT, lp->virt_addr + ADD_PORT);
@@ -1344,7 +1291,6 @@ static void __init reset_chip(struct net_device *dev)
 		iowrite8((dev->mem_start >> 8) & 0xff,
 			 lp->virt_addr + DATA_PORT + 1);
 	}
-#endif /* CS89x0_NONISA_IRQ */
 
 	/* Wait until the chip is reset */
 	reset_start_time = jiffies;
@@ -1579,9 +1525,6 @@ cs89x0_probe1(struct net_device *dev, void __iomem *ioaddr, int modular)
 		i = lp->isa_config & INT_NO_MASK;
 #ifndef CONFIG_CS89x0_PLATFORM
 		if (lp->chip_type == CS8900) {
-#ifdef CS89x0_NONISA_IRQ
-			i = cs8900_irq_map[0];
-#else
 			/* Translate the IRQ using the IRQ mapping table. */
 			if (i >= ARRAY_SIZE(cs8900_irq_map))
 				pr_err("invalid ISA interrupt number %d\n", i);
@@ -1599,7 +1542,6 @@ cs89x0_probe1(struct net_device *dev, void __iomem *ioaddr, int modular)
 					lp->irq_map = ((irq_map_buff[0] >> 8) |
 						       (irq_map_buff[1] << 8));
 			}
-#endif
 		}
 #endif
 		if (!dev->irq)
@@ -1978,18 +1920,6 @@ static struct platform_driver cs89x0_driver = {
 	.remove	= cs89x0_platform_remove,
 };
 
-static int __init cs89x0_init(void)
-{
-	return platform_driver_probe(&cs89x0_driver, cs89x0_platform_probe);
-}
-
-module_init(cs89x0_init);
-
-static void __exit cs89x0_cleanup(void)
-{
-	platform_driver_unregister(&cs89x0_driver);
-}
-
-module_exit(cs89x0_cleanup);
+module_platform_driver_probe(cs89x0_driver, cs89x0_platform_probe);
 
 #endif /* CONFIG_CS89x0_PLATFORM */
diff --git a/drivers/net/ethernet/cirrus/ep93xx_eth.c b/drivers/net/ethernet/cirrus/ep93xx_eth.c
index 354cbb7..67b0388 100644
--- a/drivers/net/ethernet/cirrus/ep93xx_eth.c
+++ b/drivers/net/ethernet/cirrus/ep93xx_eth.c
@@ -887,18 +887,7 @@ static struct platform_driver ep93xx_eth_driver = {
 	},
 };
 
-static int __init ep93xx_eth_init_module(void)
-{
-	printk(KERN_INFO DRV_MODULE_NAME " version " DRV_MODULE_VERSION " loading\n");
-	return platform_driver_register(&ep93xx_eth_driver);
-}
-
-static void __exit ep93xx_eth_cleanup_module(void)
-{
-	platform_driver_unregister(&ep93xx_eth_driver);
-}
+module_platform_driver(ep93xx_eth_driver);
 
-module_init(ep93xx_eth_init_module);
-module_exit(ep93xx_eth_cleanup_module);
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:ep93xx-eth");
diff --git a/drivers/net/ethernet/davicom/dm9000.c b/drivers/net/ethernet/davicom/dm9000.c
index 8cdf025..9105465 100644
--- a/drivers/net/ethernet/davicom/dm9000.c
+++ b/drivers/net/ethernet/davicom/dm9000.c
@@ -257,6 +257,107 @@ static void dm9000_dumpblk_32bit(void __iomem *reg, int count)
 		tmp = readl(reg);
 }
 
+/*
+ * Sleep, either by using msleep() or if we are suspending, then
+ * use mdelay() to sleep.
+ */
+static void dm9000_msleep(board_info_t *db, unsigned int ms)
+{
+	if (db->in_suspend)
+		mdelay(ms);
+	else
+		msleep(ms);
+}
+
+/* Read a word from phyxcer */
+static int
+dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg)
+{
+	board_info_t *db = netdev_priv(dev);
+	unsigned long flags;
+	unsigned int reg_save;
+	int ret;
+
+	mutex_lock(&db->addr_lock);
+
+	spin_lock_irqsave(&db->lock, flags);
+
+	/* Save previous register address */
+	reg_save = readb(db->io_addr);
+
+	/* Fill the phyxcer register into REG_0C */
+	iow(db, DM9000_EPAR, DM9000_PHY | reg);
+
+	/* Issue phyxcer read command */
+	iow(db, DM9000_EPCR, EPCR_ERPRR | EPCR_EPOS);
+
+	writeb(reg_save, db->io_addr);
+	spin_unlock_irqrestore(&db->lock, flags);
+
+	dm9000_msleep(db, 1);		/* Wait read complete */
+
+	spin_lock_irqsave(&db->lock, flags);
+	reg_save = readb(db->io_addr);
+
+	iow(db, DM9000_EPCR, 0x0);	/* Clear phyxcer read command */
+
+	/* The read data keeps on REG_0D & REG_0E */
+	ret = (ior(db, DM9000_EPDRH) << 8) | ior(db, DM9000_EPDRL);
+
+	/* restore the previous address */
+	writeb(reg_save, db->io_addr);
+	spin_unlock_irqrestore(&db->lock, flags);
+
+	mutex_unlock(&db->addr_lock);
+
+	dm9000_dbg(db, 5, "phy_read[%02x] -> %04x\n", reg, ret);
+	return ret;
+}
+
+/* Write a word to phyxcer */
+static void
+dm9000_phy_write(struct net_device *dev,
+		 int phyaddr_unused, int reg, int value)
+{
+	board_info_t *db = netdev_priv(dev);
+	unsigned long flags;
+	unsigned long reg_save;
+
+	dm9000_dbg(db, 5, "phy_write[%02x] = %04x\n", reg, value);
+	mutex_lock(&db->addr_lock);
+
+	spin_lock_irqsave(&db->lock, flags);
+
+	/* Save previous register address */
+	reg_save = readb(db->io_addr);
+
+	/* Fill the phyxcer register into REG_0C */
+	iow(db, DM9000_EPAR, DM9000_PHY | reg);
+
+	/* Fill the written data into REG_0D & REG_0E */
+	iow(db, DM9000_EPDRL, value);
+	iow(db, DM9000_EPDRH, value >> 8);
+
+	/* Issue phyxcer write command */
+	iow(db, DM9000_EPCR, EPCR_EPOS | EPCR_ERPRW);
+
+	writeb(reg_save, db->io_addr);
+	spin_unlock_irqrestore(&db->lock, flags);
+
+	dm9000_msleep(db, 1);		/* Wait write complete */
+
+	spin_lock_irqsave(&db->lock, flags);
+	reg_save = readb(db->io_addr);
+
+	iow(db, DM9000_EPCR, 0x0);	/* Clear phyxcer write command */
+
+	/* restore the previous address */
+	writeb(reg_save, db->io_addr);
+
+	spin_unlock_irqrestore(&db->lock, flags);
+	mutex_unlock(&db->addr_lock);
+}
+
 /* dm9000_set_io
  *
  * select the specified set of io routines to use with the
@@ -795,6 +896,9 @@ dm9000_init_dm9000(struct net_device *dev)
 
 	iow(db, DM9000_GPCR, GPCR_GEP_CNTL);	/* Let GPIO0 output */
 
+	dm9000_phy_write(dev, 0, MII_BMCR, BMCR_RESET); /* PHY RESET */
+	dm9000_phy_write(dev, 0, MII_DM_DSPCR, DSPCR_INIT_PARAM); /* Init */
+
 	ncr = (db->flags & DM9000_PLATF_EXT_PHY) ? NCR_EXT_PHY : 0;
 
 	/* if wol is needed, then always set NCR_WAKEEN otherwise we end
@@ -1201,109 +1305,6 @@ dm9000_open(struct net_device *dev)
 	return 0;
 }
 
-/*
- * Sleep, either by using msleep() or if we are suspending, then
- * use mdelay() to sleep.
- */
-static void dm9000_msleep(board_info_t *db, unsigned int ms)
-{
-	if (db->in_suspend)
-		mdelay(ms);
-	else
-		msleep(ms);
-}
-
-/*
- *   Read a word from phyxcer
- */
-static int
-dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg)
-{
-	board_info_t *db = netdev_priv(dev);
-	unsigned long flags;
-	unsigned int reg_save;
-	int ret;
-
-	mutex_lock(&db->addr_lock);
-
-	spin_lock_irqsave(&db->lock,flags);
-
-	/* Save previous register address */
-	reg_save = readb(db->io_addr);
-
-	/* Fill the phyxcer register into REG_0C */
-	iow(db, DM9000_EPAR, DM9000_PHY | reg);
-
-	iow(db, DM9000_EPCR, EPCR_ERPRR | EPCR_EPOS);	/* Issue phyxcer read command */
-
-	writeb(reg_save, db->io_addr);
-	spin_unlock_irqrestore(&db->lock,flags);
-
-	dm9000_msleep(db, 1);		/* Wait read complete */
-
-	spin_lock_irqsave(&db->lock,flags);
-	reg_save = readb(db->io_addr);
-
-	iow(db, DM9000_EPCR, 0x0);	/* Clear phyxcer read command */
-
-	/* The read data keeps on REG_0D & REG_0E */
-	ret = (ior(db, DM9000_EPDRH) << 8) | ior(db, DM9000_EPDRL);
-
-	/* restore the previous address */
-	writeb(reg_save, db->io_addr);
-	spin_unlock_irqrestore(&db->lock,flags);
-
-	mutex_unlock(&db->addr_lock);
-
-	dm9000_dbg(db, 5, "phy_read[%02x] -> %04x\n", reg, ret);
-	return ret;
-}
-
-/*
- *   Write a word to phyxcer
- */
-static void
-dm9000_phy_write(struct net_device *dev,
-		 int phyaddr_unused, int reg, int value)
-{
-	board_info_t *db = netdev_priv(dev);
-	unsigned long flags;
-	unsigned long reg_save;
-
-	dm9000_dbg(db, 5, "phy_write[%02x] = %04x\n", reg, value);
-	mutex_lock(&db->addr_lock);
-
-	spin_lock_irqsave(&db->lock,flags);
-
-	/* Save previous register address */
-	reg_save = readb(db->io_addr);
-
-	/* Fill the phyxcer register into REG_0C */
-	iow(db, DM9000_EPAR, DM9000_PHY | reg);
-
-	/* Fill the written data into REG_0D & REG_0E */
-	iow(db, DM9000_EPDRL, value);
-	iow(db, DM9000_EPDRH, value >> 8);
-
-	iow(db, DM9000_EPCR, EPCR_EPOS | EPCR_ERPRW);	/* Issue phyxcer write command */
-
-	writeb(reg_save, db->io_addr);
-	spin_unlock_irqrestore(&db->lock, flags);
-
-	dm9000_msleep(db, 1);		/* Wait write complete */
-
-	spin_lock_irqsave(&db->lock,flags);
-	reg_save = readb(db->io_addr);
-
-	iow(db, DM9000_EPCR, 0x0);	/* Clear phyxcer write command */
-
-	/* restore the previous address */
-	writeb(reg_save, db->io_addr);
-
-	spin_unlock_irqrestore(&db->lock, flags);
-	mutex_unlock(&db->addr_lock);
-}
-
 static void
 dm9000_shutdown(struct net_device *dev)
 {
@@ -1502,7 +1503,12 @@ dm9000_probe(struct platform_device *pdev)
 	db->flags |= DM9000_PLATF_SIMPLE_PHY;
 #endif
 
-	dm9000_reset(db);
+	/* Fixing bug on dm9000_probe, takeover dm9000_reset(db),
+	 * Need 'NCR_MAC_LBK' bit to indeed stable our DM9000 fifo
+	 * while probe stage.
+	 */
+
+	iow(db, DM9000_NCR, NCR_MAC_LBK | NCR_RST);
 
 	/* try multiple times, DM9000 sometimes gets the read wrong */
 	for (i = 0; i < 8; i++) {
@@ -1687,22 +1693,7 @@ static struct platform_driver dm9000_driver = {
 	.remove  = dm9000_drv_remove,
 };
 
-static int __init
-dm9000_init(void)
-{
-	printk(KERN_INFO "%s Ethernet Driver, V%s\n", CARDNAME, DRV_VERSION);
-
-	return platform_driver_register(&dm9000_driver);
-}
-
-static void __exit
-dm9000_cleanup(void)
-{
-	platform_driver_unregister(&dm9000_driver);
-}
-
-module_init(dm9000_init);
-module_exit(dm9000_cleanup);
+module_platform_driver(dm9000_driver);
 
 MODULE_AUTHOR("Sascha Hauer, Ben Dooks");
 MODULE_DESCRIPTION("Davicom DM9000 network driver");
diff --git a/drivers/net/ethernet/davicom/dm9000.h b/drivers/net/ethernet/davicom/dm9000.h
index 55688bd..9ce058a 100644
--- a/drivers/net/ethernet/davicom/dm9000.h
+++ b/drivers/net/ethernet/davicom/dm9000.h
@@ -69,7 +69,9 @@
 #define NCR_WAKEEN          (1<<6)
 #define NCR_FCOL            (1<<4)
 #define NCR_FDX             (1<<3)
-#define NCR_LBK             (3<<1)
+
+#define NCR_RESERVED        (3<<1)
+#define NCR_MAC_LBK         (1<<1)
 #define NCR_RST	            (1<<0)
 
 #define NSR_SPEED           (1<<7)
@@ -167,5 +169,12 @@
 #define ISR_LNKCHNG		(1<<5)
 #define ISR_UNDERRUN		(1<<4)
 
+/* Davicom MII registers.
+ */
+
+#define MII_DM_DSPCR		0x1b    /* DSP Control Register */
+
+#define DSPCR_INIT_PARAM	0xE100	/* DSP init parameter */
+
 #endif /* _DM9000X_H_ */
 
diff --git a/drivers/net/ethernet/dec/tulip/xircom_cb.c b/drivers/net/ethernet/dec/tulip/xircom_cb.c
index 88feced..cdbcd16 100644
--- a/drivers/net/ethernet/dec/tulip/xircom_cb.c
+++ b/drivers/net/ethernet/dec/tulip/xircom_cb.c
@@ -236,17 +236,14 @@ static int xircom_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	private->rx_buffer = dma_alloc_coherent(d, 8192,
 						&private->rx_dma_handle,
 						GFP_KERNEL);
-	if (private->rx_buffer == NULL) {
-		pr_err("%s: no memory for rx buffer\n", __func__);
+	if (private->rx_buffer == NULL)
 		goto rx_buf_fail;
-	}
+
 	private->tx_buffer = dma_alloc_coherent(d, 8192,
 						&private->tx_dma_handle,
 						GFP_KERNEL);
-	if (private->tx_buffer == NULL) {
-		pr_err("%s: no memory for tx buffer\n", __func__);
+	if (private->tx_buffer == NULL)
 		goto tx_buf_fail;
-	}
 
 	SET_NETDEV_DEV(dev, &pdev->dev);
 
diff --git a/drivers/net/ethernet/dlink/dl2k.c b/drivers/net/ethernet/dlink/dl2k.c
index 110d26f..afa8e3a 100644
--- a/drivers/net/ethernet/dlink/dl2k.c
+++ b/drivers/net/ethernet/dlink/dl2k.c
@@ -580,12 +580,9 @@ alloc_list (struct net_device *dev)
 
 		skb = netdev_alloc_skb_ip_align(dev, np->rx_buf_sz);
 		np->rx_skbuff[i] = skb;
-		if (skb == NULL) {
-			printk (KERN_ERR
-				"%s: alloc_list: allocate Rx buffer error! ",
-				dev->name);
+		if (skb == NULL)
 			break;
-		}
+
 		/* Rubicon now supports 40 bits of addressing space. */
 		np->rx_ring[i].fraginfo =
 		    cpu_to_le64 ( pci_map_single (
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
index 29aff55..2e2700e 100644
--- a/drivers/net/ethernet/emulex/benet/be.h
+++ b/drivers/net/ethernet/emulex/benet/be.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005 - 2011 Emulex
+ * Copyright (C) 2005 - 2013 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c
index 3c9b4f1..f286ad2 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.c
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005 - 2011 Emulex
+ * Copyright (C) 2005 - 2013 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -2667,10 +2667,8 @@ int be_cmd_set_mac_list(struct be_adapter *adapter, u8 *mac_array,
 	cmd.size = sizeof(struct be_cmd_req_set_mac_list);
 	cmd.va = dma_alloc_coherent(&adapter->pdev->dev, cmd.size,
 			&cmd.dma, GFP_KERNEL);
-	if (!cmd.va) {
-		dev_err(&adapter->pdev->dev, "Memory alloc failure\n");
+	if (!cmd.va)
 		return -ENOMEM;
-	}
 
 	spin_lock_bh(&adapter->mcc_lock);
 
@@ -3202,6 +3200,31 @@ err:
 	return status;
 }
 
+int be_cmd_intr_set(struct be_adapter *adapter, bool intr_enable)
+{
+	struct be_mcc_wrb *wrb;
+	struct be_cmd_req_intr_set *req;
+	int status;
+
+	if (mutex_lock_interruptible(&adapter->mbox_lock))
+		return -1;
+
+	wrb = wrb_from_mbox(adapter);
+
+	req = embedded_payload(wrb);
+
+	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+			       OPCODE_COMMON_SET_INTERRUPT_ENABLE, sizeof(*req),
+			       wrb, NULL);
+
+	req->intr_enabled = intr_enable;
+
+	status = be_mbox_notify_wait(adapter);
+
+	mutex_unlock(&adapter->mbox_lock);
+	return status;
+}
+
 int be_roce_mcc_cmd(void *netdev_handle, void *wrb_payload,
 			int wrb_payload_size, u16 *cmd_status, u16 *ext_status)
 {
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h
index 9697086..f2af855 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.h
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005 - 2011 Emulex
+ * Copyright (C) 2005 - 2013 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -188,6 +188,7 @@ struct be_mcc_mailbox {
 #define OPCODE_COMMON_GET_BEACON_STATE			70
 #define OPCODE_COMMON_READ_TRANSRECV_DATA		73
 #define OPCODE_COMMON_GET_PORT_NAME			77
+#define OPCODE_COMMON_SET_INTERRUPT_ENABLE		89
 #define OPCODE_COMMON_GET_PHY_DETAILS			102
 #define OPCODE_COMMON_SET_DRIVER_FUNCTION_CAP		103
 #define OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES	121
@@ -1791,6 +1792,12 @@ struct be_cmd_enable_disable_vf {
 	u8 rsvd[3];
 };
 
+struct be_cmd_req_intr_set {
+	struct be_cmd_req_hdr hdr;
+	u8 intr_enabled;
+	u8 rsvd[3];
+};
+
 static inline bool check_privilege(struct be_adapter *adapter, u32 flags)
 {
 	return flags & adapter->cmd_privileges ? true : false;
@@ -1938,3 +1945,4 @@ extern int be_cmd_set_profile_config(struct be_adapter *adapter, u32 bps,
 extern int be_cmd_get_if_id(struct be_adapter *adapter,
 			    struct be_vf_cfg *vf_cfg, int vf_num);
 extern int be_cmd_enable_vf(struct be_adapter *adapter, u8 domain);
+extern int be_cmd_intr_set(struct be_adapter *adapter, bool intr_enable);
diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c
index 76b302f..07b7f27 100644
--- a/drivers/net/ethernet/emulex/benet/be_ethtool.c
+++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005 - 2011 Emulex
+ * Copyright (C) 2005 - 2013 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -719,10 +719,8 @@ be_test_ddr_dma(struct be_adapter *adapter)
 	ddrdma_cmd.size = sizeof(struct be_cmd_req_ddrdma_test);
 	ddrdma_cmd.va = dma_alloc_coherent(&adapter->pdev->dev, ddrdma_cmd.size,
 					   &ddrdma_cmd.dma, GFP_KERNEL);
-	if (!ddrdma_cmd.va) {
-		dev_err(&adapter->pdev->dev, "Memory allocation failure\n");
+	if (!ddrdma_cmd.va)
 		return -ENOMEM;
-	}
 
 	for (i = 0; i < 2; i++) {
 		ret = be_cmd_ddr_dma_test(adapter, pattern[i],
@@ -845,11 +843,8 @@ be_read_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom,
 	eeprom_cmd.va = dma_alloc_coherent(&adapter->pdev->dev, eeprom_cmd.size,
 					   &eeprom_cmd.dma, GFP_KERNEL);
 
-	if (!eeprom_cmd.va) {
-		dev_err(&adapter->pdev->dev,
-			"Memory allocation failure. Could not read eeprom\n");
+	if (!eeprom_cmd.va)
 		return -ENOMEM;
-	}
 
 	status = be_cmd_get_seeprom_data(adapter, &eeprom_cmd);
 
diff --git a/drivers/net/ethernet/emulex/benet/be_hw.h b/drivers/net/ethernet/emulex/benet/be_hw.h
index 62dc220..89e6d8c 100644
--- a/drivers/net/ethernet/emulex/benet/be_hw.h
+++ b/drivers/net/ethernet/emulex/benet/be_hw.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005 - 2011 Emulex
+ * Copyright (C) 2005 - 2013 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index 08e54f3..536afa2 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005 - 2011 Emulex
+ * Copyright (C) 2005 - 2013 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -146,20 +146,16 @@ static int be_queue_alloc(struct be_adapter *adapter, struct be_queue_info *q,
 	q->entry_size = entry_size;
 	mem->size = len * entry_size;
 	mem->va = dma_alloc_coherent(&adapter->pdev->dev, mem->size, &mem->dma,
-				     GFP_KERNEL);
+				     GFP_KERNEL | __GFP_ZERO);
 	if (!mem->va)
 		return -ENOMEM;
-	memset(mem->va, 0, mem->size);
 	return 0;
 }
 
-static void be_intr_set(struct be_adapter *adapter, bool enable)
+static void be_reg_intr_set(struct be_adapter *adapter, bool enable)
 {
 	u32 reg, enabled;
 
-	if (adapter->eeh_error)
-		return;
-
 	pci_read_config_dword(adapter->pdev, PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET,
 				&reg);
 	enabled = reg & MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK;
@@ -175,6 +171,22 @@ static void be_intr_set(struct be_adapter *adapter, bool enable)
 			PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET, reg);
 }
 
+static void be_intr_set(struct be_adapter *adapter, bool enable)
+{
+	int status = 0;
+
+	/* On lancer interrupts can't be controlled via this register */
+	if (lancer_chip(adapter))
+		return;
+
+	if (adapter->eeh_error)
+		return;
+
+	status = be_cmd_intr_set(adapter, enable);
+	if (status)
+		be_reg_intr_set(adapter, enable);
+}
+
 static void be_rxq_notify(struct be_adapter *adapter, u16 qid, u16 posted)
 {
 	u32 val = 0;
@@ -2435,9 +2447,6 @@ static int be_close(struct net_device *netdev)
 
 	be_roce_dev_close(adapter);
 
-	if (!lancer_chip(adapter))
-		be_intr_set(adapter, false);
-
 	for_all_evt_queues(adapter, eqo, i)
 		napi_disable(&eqo->napi);
 
@@ -2525,9 +2534,6 @@ static int be_open(struct net_device *netdev)
 
 	be_irq_register(adapter);
 
-	if (!lancer_chip(adapter))
-		be_intr_set(adapter, true);
-
 	for_all_rx_queues(adapter, rxo, i)
 		be_cq_notify(adapter, rxo->cq.id, true, 0);
 
@@ -2562,10 +2568,9 @@ static int be_setup_wol(struct be_adapter *adapter, bool enable)
 
 	cmd.size = sizeof(struct be_cmd_req_acpi_wol_magic_config);
 	cmd.va = dma_alloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
-				    GFP_KERNEL);
+				    GFP_KERNEL | __GFP_ZERO);
 	if (cmd.va == NULL)
 		return -1;
-	memset(cmd.va, 0, cmd.size);
 
 	if (enable) {
 		status = pci_write_config_dword(adapter->pdev,
@@ -3457,11 +3462,9 @@ static int lancer_fw_download(struct be_adapter *adapter,
 	flash_cmd.size = sizeof(struct lancer_cmd_req_write_object)
 				+ LANCER_FW_DOWNLOAD_CHUNK;
 	flash_cmd.va = dma_alloc_coherent(&adapter->pdev->dev, flash_cmd.size,
-						&flash_cmd.dma, GFP_KERNEL);
+					  &flash_cmd.dma, GFP_KERNEL);
 	if (!flash_cmd.va) {
 		status = -ENOMEM;
-		dev_err(&adapter->pdev->dev,
-			"Memory allocation failure while flashing\n");
 		goto lancer_fw_exit;
 	}
 
@@ -3563,8 +3566,6 @@ static int be_fw_download(struct be_adapter *adapter, const struct firmware* fw)
 					  &flash_cmd.dma, GFP_KERNEL);
 	if (!flash_cmd.va) {
 		status = -ENOMEM;
-		dev_err(&adapter->pdev->dev,
-			"Memory allocation failure while flashing\n");
 		goto be_fw_exit;
 	}
 
@@ -3791,12 +3792,13 @@ static int be_ctrl_init(struct be_adapter *adapter)
 
 	rx_filter->size = sizeof(struct be_cmd_req_rx_filter);
 	rx_filter->va = dma_alloc_coherent(&adapter->pdev->dev, rx_filter->size,
-					&rx_filter->dma, GFP_KERNEL);
+					   &rx_filter->dma,
+					   GFP_KERNEL | __GFP_ZERO);
 	if (rx_filter->va == NULL) {
 		status = -ENOMEM;
 		goto free_mbox;
 	}
-	memset(rx_filter->va, 0, rx_filter->size);
+
 	mutex_init(&adapter->mbox_lock);
 	spin_lock_init(&adapter->mcc_lock);
 	spin_lock_init(&adapter->mcc_cq_lock);
@@ -3838,10 +3840,9 @@ static int be_stats_init(struct be_adapter *adapter)
 		cmd->size = sizeof(struct be_cmd_req_get_stats_v1);
 
 	cmd->va = dma_alloc_coherent(&adapter->pdev->dev, cmd->size, &cmd->dma,
-				     GFP_KERNEL);
+				     GFP_KERNEL | __GFP_ZERO);
 	if (cmd->va == NULL)
 		return -1;
-	memset(cmd->va, 0, cmd->size);
 	return 0;
 }
 
@@ -3853,6 +3854,7 @@ static void be_remove(struct pci_dev *pdev)
 		return;
 
 	be_roce_dev_remove(adapter);
+	be_intr_set(adapter, false);
 
 	cancel_delayed_work_sync(&adapter->func_recovery_work);
 
@@ -4142,11 +4144,11 @@ static int be_probe(struct pci_dev *pdev, const struct pci_device_id *pdev_id)
 			goto ctrl_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);
+	/* Wait for interrupts to quiesce after an FLR */
+	msleep(100);
+
+	/* Allow interrupts for other ULPs running on NIC function */
+	be_intr_set(adapter, true);
 
 	status = be_stats_init(adapter);
 	if (status)
diff --git a/drivers/net/ethernet/emulex/benet/be_roce.c b/drivers/net/ethernet/emulex/benet/be_roce.c
index 55d32aa..f3d126d 100644
--- a/drivers/net/ethernet/emulex/benet/be_roce.c
+++ b/drivers/net/ethernet/emulex/benet/be_roce.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005 - 2011 Emulex
+ * Copyright (C) 2005 - 2013 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
diff --git a/drivers/net/ethernet/emulex/benet/be_roce.h b/drivers/net/ethernet/emulex/benet/be_roce.h
index db4ea80..2765729 100644
--- a/drivers/net/ethernet/emulex/benet/be_roce.h
+++ b/drivers/net/ethernet/emulex/benet/be_roce.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005 - 2011 Emulex
+ * Copyright (C) 2005 - 2013 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c
index 7c361d1..21b85fb 100644
--- a/drivers/net/ethernet/faraday/ftgmac100.c
+++ b/drivers/net/ethernet/faraday/ftgmac100.c
@@ -780,12 +780,11 @@ static int ftgmac100_alloc_buffers(struct ftgmac100 *priv)
 
 	priv->descs = dma_alloc_coherent(priv->dev,
 					 sizeof(struct ftgmac100_descs),
-					 &priv->descs_dma_addr, GFP_KERNEL);
+					 &priv->descs_dma_addr,
+					 GFP_KERNEL | __GFP_ZERO);
 	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]);
 
@@ -1350,22 +1349,7 @@ static struct platform_driver ftgmac100_driver = {
 	},
 };
 
-/******************************************************************************
- * 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_platform_driver(ftgmac100_driver);
 
 MODULE_AUTHOR("Po-Yu Chuang <ratbert@faraday-tech.com>");
 MODULE_DESCRIPTION("FTGMAC100 driver");
diff --git a/drivers/net/ethernet/faraday/ftmac100.c b/drivers/net/ethernet/faraday/ftmac100.c
index b5ea8fb..a6eda8d 100644
--- a/drivers/net/ethernet/faraday/ftmac100.c
+++ b/drivers/net/ethernet/faraday/ftmac100.c
@@ -732,13 +732,13 @@ static int ftmac100_alloc_buffers(struct ftmac100 *priv)
 {
 	int i;
 
-	priv->descs = dma_alloc_coherent(priv->dev, sizeof(struct ftmac100_descs),
-					 &priv->descs_dma_addr, GFP_KERNEL);
+	priv->descs = dma_alloc_coherent(priv->dev,
+					 sizeof(struct ftmac100_descs),
+					 &priv->descs_dma_addr,
+					 GFP_KERNEL | __GFP_ZERO);
 	if (!priv->descs)
 		return -ENOMEM;
 
-	memset(priv->descs, 0, sizeof(struct ftmac100_descs));
-
 	/* initialize RX ring */
 	ftmac100_rxdes_set_end_of_ring(&priv->descs->rxdes[RX_QUEUE_ENTRIES - 1]);
 
diff --git a/drivers/net/ethernet/freescale/Makefile b/drivers/net/ethernet/freescale/Makefile
index b7d58fe..549ce13 100644
--- a/drivers/net/ethernet/freescale/Makefile
+++ b/drivers/net/ethernet/freescale/Makefile
@@ -2,7 +2,8 @@
 # Makefile for the Freescale network device drivers.
 #
 
-obj-$(CONFIG_FEC) += fec.o fec_ptp.o
+obj-$(CONFIG_FEC) += fec.o
+fec-objs :=fec_main.o fec_ptp.o
 obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx.o
 ifeq ($(CONFIG_FEC_MPC52xx_MDIO),y)
 	obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx_phy.o
diff --git a/drivers/net/ethernet/freescale/fec.c b/drivers/net/ethernet/freescale/fec.c
deleted file mode 100644
index 911d025..0000000
--- a/drivers/net/ethernet/freescale/fec.c
+++ /dev/null
@@ -1,1986 +0,0 @@
-/*
- * Fast Ethernet Controller (FEC) driver for Motorola MPC8xx.
- * Copyright (c) 1997 Dan Malek (dmalek@jlc.net)
- *
- * Right now, I am very wasteful with the buffers.  I allocate memory
- * pages and then divide them into 2K frame buffers.  This way I know I
- * have buffers large enough to hold one frame within one buffer descriptor.
- * Once I get this working, I will use 64 or 128 byte CPM buffers, which
- * will be much more memory efficient and will easily handle lots of
- * small packets.
- *
- * Much better multiple PHY support by Magnus Damm.
- * Copyright (c) 2000 Ericsson Radio Systems AB.
- *
- * Support for FEC controller of ColdFire processors.
- * Copyright (c) 2001-2005 Greg Ungerer (gerg@snapgear.com)
- *
- * Bug fixes and cleanup by Philippe De Muyter (phdm@macqel.be)
- * Copyright (c) 2004-2006 Macq Electronique SA.
- *
- * Copyright (C) 2010-2011 Freescale Semiconductor, Inc.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/ptrace.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/spinlock.h>
-#include <linux/workqueue.h>
-#include <linux/bitops.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/clk.h>
-#include <linux/platform_device.h>
-#include <linux/phy.h>
-#include <linux/fec.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/of_gpio.h>
-#include <linux/of_net.h>
-#include <linux/pinctrl/consumer.h>
-#include <linux/regulator/consumer.h>
-
-#include <asm/cacheflush.h>
-
-#ifndef CONFIG_ARM
-#include <asm/coldfire.h>
-#include <asm/mcfsim.h>
-#endif
-
-#include "fec.h"
-
-#if defined(CONFIG_ARM)
-#define FEC_ALIGNMENT	0xf
-#else
-#define FEC_ALIGNMENT	0x3
-#endif
-
-#define DRIVER_NAME	"fec"
-#define FEC_NAPI_WEIGHT	64
-
-/* Pause frame feild and FIFO threshold */
-#define FEC_ENET_FCE	(1 << 5)
-#define FEC_ENET_RSEM_V	0x84
-#define FEC_ENET_RSFL_V	16
-#define FEC_ENET_RAEM_V	0x8
-#define FEC_ENET_RAFL_V	0x8
-#define FEC_ENET_OPD_V	0xFFF0
-
-/* Controller is ENET-MAC */
-#define FEC_QUIRK_ENET_MAC		(1 << 0)
-/* Controller needs driver to swap frame */
-#define FEC_QUIRK_SWAP_FRAME		(1 << 1)
-/* Controller uses gasket */
-#define FEC_QUIRK_USE_GASKET		(1 << 2)
-/* Controller has GBIT support */
-#define FEC_QUIRK_HAS_GBIT		(1 << 3)
-/* Controller has extend desc buffer */
-#define FEC_QUIRK_HAS_BUFDESC_EX	(1 << 4)
-
-static struct platform_device_id fec_devtype[] = {
-	{
-		/* keep it for coldfire */
-		.name = DRIVER_NAME,
-		.driver_data = 0,
-	}, {
-		.name = "imx25-fec",
-		.driver_data = FEC_QUIRK_USE_GASKET,
-	}, {
-		.name = "imx27-fec",
-		.driver_data = 0,
-	}, {
-		.name = "imx28-fec",
-		.driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_SWAP_FRAME,
-	}, {
-		.name = "imx6q-fec",
-		.driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT |
-				FEC_QUIRK_HAS_BUFDESC_EX,
-	}, {
-		/* sentinel */
-	}
-};
-MODULE_DEVICE_TABLE(platform, fec_devtype);
-
-enum imx_fec_type {
-	IMX25_FEC = 1,	/* runs on i.mx25/50/53 */
-	IMX27_FEC,	/* runs on i.mx27/35/51 */
-	IMX28_FEC,
-	IMX6Q_FEC,
-};
-
-static const struct of_device_id fec_dt_ids[] = {
-	{ .compatible = "fsl,imx25-fec", .data = &fec_devtype[IMX25_FEC], },
-	{ .compatible = "fsl,imx27-fec", .data = &fec_devtype[IMX27_FEC], },
-	{ .compatible = "fsl,imx28-fec", .data = &fec_devtype[IMX28_FEC], },
-	{ .compatible = "fsl,imx6q-fec", .data = &fec_devtype[IMX6Q_FEC], },
-	{ /* sentinel */ }
-};
-MODULE_DEVICE_TABLE(of, fec_dt_ids);
-
-static unsigned char macaddr[ETH_ALEN];
-module_param_array(macaddr, byte, NULL, 0);
-MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address");
-
-#if defined(CONFIG_M5272)
-/*
- * Some hardware gets it MAC address out of local flash memory.
- * if this is non-zero then assume it is the address to get MAC from.
- */
-#if defined(CONFIG_NETtel)
-#define	FEC_FLASHMAC	0xf0006006
-#elif defined(CONFIG_GILBARCONAP) || defined(CONFIG_SCALES)
-#define	FEC_FLASHMAC	0xf0006000
-#elif defined(CONFIG_CANCam)
-#define	FEC_FLASHMAC	0xf0020000
-#elif defined (CONFIG_M5272C3)
-#define	FEC_FLASHMAC	(0xffe04000 + 4)
-#elif defined(CONFIG_MOD5272)
-#define FEC_FLASHMAC	0xffc0406b
-#else
-#define	FEC_FLASHMAC	0
-#endif
-#endif /* CONFIG_M5272 */
-
-#if (((RX_RING_SIZE + TX_RING_SIZE) * 32) > PAGE_SIZE)
-#error "FEC: descriptor ring size constants too large"
-#endif
-
-/* Interrupt events/masks. */
-#define FEC_ENET_HBERR	((uint)0x80000000)	/* Heartbeat error */
-#define FEC_ENET_BABR	((uint)0x40000000)	/* Babbling receiver */
-#define FEC_ENET_BABT	((uint)0x20000000)	/* Babbling transmitter */
-#define FEC_ENET_GRA	((uint)0x10000000)	/* Graceful stop complete */
-#define FEC_ENET_TXF	((uint)0x08000000)	/* Full frame transmitted */
-#define FEC_ENET_TXB	((uint)0x04000000)	/* A buffer was transmitted */
-#define FEC_ENET_RXF	((uint)0x02000000)	/* Full frame received */
-#define FEC_ENET_RXB	((uint)0x01000000)	/* A buffer was received */
-#define FEC_ENET_MII	((uint)0x00800000)	/* MII interrupt */
-#define FEC_ENET_EBERR	((uint)0x00400000)	/* SDMA bus error */
-
-#define FEC_DEFAULT_IMASK (FEC_ENET_TXF | FEC_ENET_RXF | FEC_ENET_MII)
-#define FEC_RX_DISABLED_IMASK (FEC_DEFAULT_IMASK & (~FEC_ENET_RXF))
-
-/* The FEC stores dest/src/type, data, and checksum for receive packets.
- */
-#define PKT_MAXBUF_SIZE		1518
-#define PKT_MINBUF_SIZE		64
-#define PKT_MAXBLR_SIZE		1520
-
-/*
- * The 5270/5271/5280/5282/532x RX control register also contains maximum frame
- * size bits. Other FEC hardware does not, so we need to take that into
- * account when setting it.
- */
-#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
-    defined(CONFIG_M520x) || defined(CONFIG_M532x) || defined(CONFIG_ARM)
-#define	OPT_FRAME_SIZE	(PKT_MAXBUF_SIZE << 16)
-#else
-#define	OPT_FRAME_SIZE	0
-#endif
-
-/* FEC MII MMFR bits definition */
-#define FEC_MMFR_ST		(1 << 30)
-#define FEC_MMFR_OP_READ	(2 << 28)
-#define FEC_MMFR_OP_WRITE	(1 << 28)
-#define FEC_MMFR_PA(v)		((v & 0x1f) << 23)
-#define FEC_MMFR_RA(v)		((v & 0x1f) << 18)
-#define FEC_MMFR_TA		(2 << 16)
-#define FEC_MMFR_DATA(v)	(v & 0xffff)
-
-#define FEC_MII_TIMEOUT		30000 /* us */
-
-/* Transmitter timeout */
-#define TX_TIMEOUT (2 * HZ)
-
-#define FEC_PAUSE_FLAG_AUTONEG	0x1
-#define FEC_PAUSE_FLAG_ENABLE	0x2
-
-static int mii_cnt;
-
-static struct bufdesc *fec_enet_get_nextdesc(struct bufdesc *bdp, int is_ex)
-{
-	struct bufdesc_ex *ex = (struct bufdesc_ex *)bdp;
-	if (is_ex)
-		return (struct bufdesc *)(ex + 1);
-	else
-		return bdp + 1;
-}
-
-static struct bufdesc *fec_enet_get_prevdesc(struct bufdesc *bdp, int is_ex)
-{
-	struct bufdesc_ex *ex = (struct bufdesc_ex *)bdp;
-	if (is_ex)
-		return (struct bufdesc *)(ex - 1);
-	else
-		return bdp - 1;
-}
-
-static void *swap_buffer(void *bufaddr, int len)
-{
-	int i;
-	unsigned int *buf = bufaddr;
-
-	for (i = 0; i < (len + 3) / 4; i++, buf++)
-		*buf = cpu_to_be32(*buf);
-
-	return bufaddr;
-}
-
-static netdev_tx_t
-fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
-{
-	struct fec_enet_private *fep = netdev_priv(ndev);
-	const struct platform_device_id *id_entry =
-				platform_get_device_id(fep->pdev);
-	struct bufdesc *bdp;
-	void *bufaddr;
-	unsigned short	status;
-	unsigned int index;
-
-	if (!fep->link) {
-		/* Link is down or autonegotiation is in progress. */
-		return NETDEV_TX_BUSY;
-	}
-
-	/* Fill in a Tx ring entry */
-	bdp = fep->cur_tx;
-
-	status = bdp->cbd_sc;
-
-	if (status & BD_ENET_TX_READY) {
-		/* Ooops.  All transmit buffers are full.  Bail out.
-		 * This should not happen, since ndev->tbusy should be set.
-		 */
-		printk("%s: tx queue full!.\n", ndev->name);
-		return NETDEV_TX_BUSY;
-	}
-
-	/* Clear all of the status flags */
-	status &= ~BD_ENET_TX_STATS;
-
-	/* Set buffer length and buffer pointer */
-	bufaddr = skb->data;
-	bdp->cbd_datlen = skb->len;
-
-	/*
-	 * On some FEC implementations data must be aligned on
-	 * 4-byte boundaries. Use bounce buffers to copy data
-	 * and get it aligned. Ugh.
-	 */
-	if (fep->bufdesc_ex)
-		index = (struct bufdesc_ex *)bdp -
-			(struct bufdesc_ex *)fep->tx_bd_base;
-	else
-		index = bdp - fep->tx_bd_base;
-
-	if (((unsigned long) bufaddr) & FEC_ALIGNMENT) {
-		memcpy(fep->tx_bounce[index], skb->data, skb->len);
-		bufaddr = fep->tx_bounce[index];
-	}
-
-	/*
-	 * Some design made an incorrect assumption on endian mode of
-	 * the system that it's running on. As the result, driver has to
-	 * swap every frame going to and coming from the controller.
-	 */
-	if (id_entry->driver_data & FEC_QUIRK_SWAP_FRAME)
-		swap_buffer(bufaddr, skb->len);
-
-	/* Save skb pointer */
-	fep->tx_skbuff[index] = skb;
-
-	/* Push the data cache so the CPM does not get stale memory
-	 * data.
-	 */
-	bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, bufaddr,
-			FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE);
-
-	/* Send it on its way.  Tell FEC it's ready, interrupt when done,
-	 * it's the last BD of the frame, and to put the CRC on the end.
-	 */
-	status |= (BD_ENET_TX_READY | BD_ENET_TX_INTR
-			| BD_ENET_TX_LAST | BD_ENET_TX_TC);
-	bdp->cbd_sc = status;
-
-	if (fep->bufdesc_ex) {
-
-		struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp;
-		ebdp->cbd_bdu = 0;
-		if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP &&
-			fep->hwts_tx_en)) {
-			ebdp->cbd_esc = (BD_ENET_TX_TS | BD_ENET_TX_INT);
-			skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
-		} else {
-
-			ebdp->cbd_esc = BD_ENET_TX_INT;
-		}
-	}
-	/* If this was the last BD in the ring, start at the beginning again. */
-	if (status & BD_ENET_TX_WRAP)
-		bdp = fep->tx_bd_base;
-	else
-		bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
-
-	fep->cur_tx = bdp;
-
-	if (fep->cur_tx == fep->dirty_tx)
-		netif_stop_queue(ndev);
-
-	/* Trigger transmission start */
-	writel(0, fep->hwp + FEC_X_DES_ACTIVE);
-
-	skb_tx_timestamp(skb);
-
-	return NETDEV_TX_OK;
-}
-
-/* This function is called to start or restart the FEC during a link
- * change.  This only happens when switching between half and full
- * duplex.
- */
-static void
-fec_restart(struct net_device *ndev, int duplex)
-{
-	struct fec_enet_private *fep = netdev_priv(ndev);
-	const struct platform_device_id *id_entry =
-				platform_get_device_id(fep->pdev);
-	int i;
-	u32 temp_mac[2];
-	u32 rcntl = OPT_FRAME_SIZE | 0x04;
-	u32 ecntl = 0x2; /* ETHEREN */
-
-	/* Whack a reset.  We should wait for this. */
-	writel(1, fep->hwp + FEC_ECNTRL);
-	udelay(10);
-
-	/*
-	 * enet-mac reset will reset mac address registers too,
-	 * so need to reconfigure it.
-	 */
-	if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) {
-		memcpy(&temp_mac, ndev->dev_addr, ETH_ALEN);
-		writel(cpu_to_be32(temp_mac[0]), fep->hwp + FEC_ADDR_LOW);
-		writel(cpu_to_be32(temp_mac[1]), fep->hwp + FEC_ADDR_HIGH);
-	}
-
-	/* Clear any outstanding interrupt. */
-	writel(0xffc00000, fep->hwp + FEC_IEVENT);
-
-	/* Reset all multicast.	*/
-	writel(0, fep->hwp + FEC_GRP_HASH_TABLE_HIGH);
-	writel(0, fep->hwp + FEC_GRP_HASH_TABLE_LOW);
-#ifndef CONFIG_M5272
-	writel(0, fep->hwp + FEC_HASH_TABLE_HIGH);
-	writel(0, fep->hwp + FEC_HASH_TABLE_LOW);
-#endif
-
-	/* Set maximum receive buffer size. */
-	writel(PKT_MAXBLR_SIZE, fep->hwp + FEC_R_BUFF_SIZE);
-
-	/* Set receive and transmit descriptor base. */
-	writel(fep->bd_dma, fep->hwp + FEC_R_DES_START);
-	if (fep->bufdesc_ex)
-		writel((unsigned long)fep->bd_dma + sizeof(struct bufdesc_ex)
-			* RX_RING_SIZE, fep->hwp + FEC_X_DES_START);
-	else
-		writel((unsigned long)fep->bd_dma + sizeof(struct bufdesc)
-			* RX_RING_SIZE,	fep->hwp + FEC_X_DES_START);
-
-	fep->cur_rx = fep->rx_bd_base;
-
-	for (i = 0; i <= TX_RING_MOD_MASK; i++) {
-		if (fep->tx_skbuff[i]) {
-			dev_kfree_skb_any(fep->tx_skbuff[i]);
-			fep->tx_skbuff[i] = NULL;
-		}
-	}
-
-	/* Enable MII mode */
-	if (duplex) {
-		/* FD enable */
-		writel(0x04, fep->hwp + FEC_X_CNTRL);
-	} else {
-		/* No Rcv on Xmit */
-		rcntl |= 0x02;
-		writel(0x0, fep->hwp + FEC_X_CNTRL);
-	}
-
-	fep->full_duplex = duplex;
-
-	/* Set MII speed */
-	writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED);
-
-	/*
-	 * The phy interface and speed need to get configured
-	 * differently on enet-mac.
-	 */
-	if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) {
-		/* Enable flow control and length check */
-		rcntl |= 0x40000000 | 0x00000020;
-
-		/* RGMII, RMII or MII */
-		if (fep->phy_interface == PHY_INTERFACE_MODE_RGMII)
-			rcntl |= (1 << 6);
-		else if (fep->phy_interface == PHY_INTERFACE_MODE_RMII)
-			rcntl |= (1 << 8);
-		else
-			rcntl &= ~(1 << 8);
-
-		/* 1G, 100M or 10M */
-		if (fep->phy_dev) {
-			if (fep->phy_dev->speed == SPEED_1000)
-				ecntl |= (1 << 5);
-			else if (fep->phy_dev->speed == SPEED_100)
-				rcntl &= ~(1 << 9);
-			else
-				rcntl |= (1 << 9);
-		}
-	} else {
-#ifdef FEC_MIIGSK_ENR
-		if (id_entry->driver_data & FEC_QUIRK_USE_GASKET) {
-			u32 cfgr;
-			/* disable the gasket and wait */
-			writel(0, fep->hwp + FEC_MIIGSK_ENR);
-			while (readl(fep->hwp + FEC_MIIGSK_ENR) & 4)
-				udelay(1);
-
-			/*
-			 * configure the gasket:
-			 *   RMII, 50 MHz, no loopback, no echo
-			 *   MII, 25 MHz, no loopback, no echo
-			 */
-			cfgr = (fep->phy_interface == PHY_INTERFACE_MODE_RMII)
-				? BM_MIIGSK_CFGR_RMII : BM_MIIGSK_CFGR_MII;
-			if (fep->phy_dev && fep->phy_dev->speed == SPEED_10)
-				cfgr |= BM_MIIGSK_CFGR_FRCONT_10M;
-			writel(cfgr, fep->hwp + FEC_MIIGSK_CFGR);
-
-			/* re-enable the gasket */
-			writel(2, fep->hwp + FEC_MIIGSK_ENR);
-		}
-#endif
-	}
-
-	/* enable pause frame*/
-	if ((fep->pause_flag & FEC_PAUSE_FLAG_ENABLE) ||
-	    ((fep->pause_flag & FEC_PAUSE_FLAG_AUTONEG) &&
-	     fep->phy_dev && fep->phy_dev->pause)) {
-		rcntl |= FEC_ENET_FCE;
-
-		/* set FIFO thresh hold parameter to reduce overrun */
-		writel(FEC_ENET_RSEM_V, fep->hwp + FEC_R_FIFO_RSEM);
-		writel(FEC_ENET_RSFL_V, fep->hwp + FEC_R_FIFO_RSFL);
-		writel(FEC_ENET_RAEM_V, fep->hwp + FEC_R_FIFO_RAEM);
-		writel(FEC_ENET_RAFL_V, fep->hwp + FEC_R_FIFO_RAFL);
-
-		/* OPD */
-		writel(FEC_ENET_OPD_V, fep->hwp + FEC_OPD);
-	} else {
-		rcntl &= ~FEC_ENET_FCE;
-	}
-
-	writel(rcntl, fep->hwp + FEC_R_CNTRL);
-
-	if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) {
-		/* enable ENET endian swap */
-		ecntl |= (1 << 8);
-		/* enable ENET store and forward mode */
-		writel(1 << 8, fep->hwp + FEC_X_WMRK);
-	}
-
-	if (fep->bufdesc_ex)
-		ecntl |= (1 << 4);
-
-	/* And last, enable the transmit and receive processing */
-	writel(ecntl, fep->hwp + FEC_ECNTRL);
-	writel(0, fep->hwp + FEC_R_DES_ACTIVE);
-
-	if (fep->bufdesc_ex)
-		fec_ptp_start_cyclecounter(ndev);
-
-	/* Enable interrupts we wish to service */
-	writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
-}
-
-static void
-fec_stop(struct net_device *ndev)
-{
-	struct fec_enet_private *fep = netdev_priv(ndev);
-	const struct platform_device_id *id_entry =
-				platform_get_device_id(fep->pdev);
-	u32 rmii_mode = readl(fep->hwp + FEC_R_CNTRL) & (1 << 8);
-
-	/* We cannot expect a graceful transmit stop without link !!! */
-	if (fep->link) {
-		writel(1, fep->hwp + FEC_X_CNTRL); /* Graceful transmit stop */
-		udelay(10);
-		if (!(readl(fep->hwp + FEC_IEVENT) & FEC_ENET_GRA))
-			printk("fec_stop : Graceful transmit stop did not complete !\n");
-	}
-
-	/* Whack a reset.  We should wait for this. */
-	writel(1, fep->hwp + FEC_ECNTRL);
-	udelay(10);
-	writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED);
-	writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
-
-	/* We have to keep ENET enabled to have MII interrupt stay working */
-	if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) {
-		writel(2, fep->hwp + FEC_ECNTRL);
-		writel(rmii_mode, fep->hwp + FEC_R_CNTRL);
-	}
-}
-
-
-static void
-fec_timeout(struct net_device *ndev)
-{
-	struct fec_enet_private *fep = netdev_priv(ndev);
-
-	ndev->stats.tx_errors++;
-
-	fec_restart(ndev, fep->full_duplex);
-	netif_wake_queue(ndev);
-}
-
-static void
-fec_enet_tx(struct net_device *ndev)
-{
-	struct	fec_enet_private *fep;
-	struct bufdesc *bdp;
-	unsigned short status;
-	struct	sk_buff	*skb;
-	int	index = 0;
-
-	fep = netdev_priv(ndev);
-	bdp = fep->dirty_tx;
-
-	/* get next bdp of dirty_tx */
-	if (bdp->cbd_sc & BD_ENET_TX_WRAP)
-		bdp = fep->tx_bd_base;
-	else
-		bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
-
-	while (((status = bdp->cbd_sc) & BD_ENET_TX_READY) == 0) {
-
-		/* current queue is empty */
-		if (bdp == fep->cur_tx)
-			break;
-
-		if (fep->bufdesc_ex)
-			index = (struct bufdesc_ex *)bdp -
-				(struct bufdesc_ex *)fep->tx_bd_base;
-		else
-			index = bdp - fep->tx_bd_base;
-
-		dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr,
-				FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE);
-		bdp->cbd_bufaddr = 0;
-
-		skb = fep->tx_skbuff[index];
-
-		/* Check for errors. */
-		if (status & (BD_ENET_TX_HB | BD_ENET_TX_LC |
-				   BD_ENET_TX_RL | BD_ENET_TX_UN |
-				   BD_ENET_TX_CSL)) {
-			ndev->stats.tx_errors++;
-			if (status & BD_ENET_TX_HB)  /* No heartbeat */
-				ndev->stats.tx_heartbeat_errors++;
-			if (status & BD_ENET_TX_LC)  /* Late collision */
-				ndev->stats.tx_window_errors++;
-			if (status & BD_ENET_TX_RL)  /* Retrans limit */
-				ndev->stats.tx_aborted_errors++;
-			if (status & BD_ENET_TX_UN)  /* Underrun */
-				ndev->stats.tx_fifo_errors++;
-			if (status & BD_ENET_TX_CSL) /* Carrier lost */
-				ndev->stats.tx_carrier_errors++;
-		} else {
-			ndev->stats.tx_packets++;
-		}
-
-		if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS) &&
-			fep->bufdesc_ex) {
-			struct skb_shared_hwtstamps shhwtstamps;
-			unsigned long flags;
-			struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp;
-
-			memset(&shhwtstamps, 0, sizeof(shhwtstamps));
-			spin_lock_irqsave(&fep->tmreg_lock, flags);
-			shhwtstamps.hwtstamp = ns_to_ktime(
-				timecounter_cyc2time(&fep->tc, ebdp->ts));
-			spin_unlock_irqrestore(&fep->tmreg_lock, flags);
-			skb_tstamp_tx(skb, &shhwtstamps);
-		}
-
-		if (status & BD_ENET_TX_READY)
-			printk("HEY! Enet xmit interrupt and TX_READY.\n");
-
-		/* Deferred means some collisions occurred during transmit,
-		 * but we eventually sent the packet OK.
-		 */
-		if (status & BD_ENET_TX_DEF)
-			ndev->stats.collisions++;
-
-		/* Free the sk buffer associated with this last transmit */
-		dev_kfree_skb_any(skb);
-		fep->tx_skbuff[index] = NULL;
-
-		fep->dirty_tx = bdp;
-
-		/* Update pointer to next buffer descriptor to be transmitted */
-		if (status & BD_ENET_TX_WRAP)
-			bdp = fep->tx_bd_base;
-		else
-			bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
-
-		/* Since we have freed up a buffer, the ring is no longer full
-		 */
-		if (fep->dirty_tx != fep->cur_tx) {
-			if (netif_queue_stopped(ndev))
-				netif_wake_queue(ndev);
-		}
-	}
-	return;
-}
-
-
-/* During a receive, the cur_rx points to the current incoming buffer.
- * When we update through the ring, if the next incoming buffer has
- * not been given to the system, we just set the empty indicator,
- * effectively tossing the packet.
- */
-static int
-fec_enet_rx(struct net_device *ndev, int budget)
-{
-	struct fec_enet_private *fep = netdev_priv(ndev);
-	const struct platform_device_id *id_entry =
-				platform_get_device_id(fep->pdev);
-	struct bufdesc *bdp;
-	unsigned short status;
-	struct	sk_buff	*skb;
-	ushort	pkt_len;
-	__u8 *data;
-	int	pkt_received = 0;
-
-#ifdef CONFIG_M532x
-	flush_cache_all();
-#endif
-
-	/* First, grab all of the stats for the incoming packet.
-	 * These get messed up if we get called due to a busy condition.
-	 */
-	bdp = fep->cur_rx;
-
-	while (!((status = bdp->cbd_sc) & BD_ENET_RX_EMPTY)) {
-
-		if (pkt_received >= budget)
-			break;
-		pkt_received++;
-
-		/* Since we have allocated space to hold a complete frame,
-		 * the last indicator should be set.
-		 */
-		if ((status & BD_ENET_RX_LAST) == 0)
-			printk("FEC ENET: rcv is not +last\n");
-
-		if (!fep->opened)
-			goto rx_processing_done;
-
-		/* Check for errors. */
-		if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_NO |
-			   BD_ENET_RX_CR | BD_ENET_RX_OV)) {
-			ndev->stats.rx_errors++;
-			if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH)) {
-				/* Frame too long or too short. */
-				ndev->stats.rx_length_errors++;
-			}
-			if (status & BD_ENET_RX_NO)	/* Frame alignment */
-				ndev->stats.rx_frame_errors++;
-			if (status & BD_ENET_RX_CR)	/* CRC Error */
-				ndev->stats.rx_crc_errors++;
-			if (status & BD_ENET_RX_OV)	/* FIFO overrun */
-				ndev->stats.rx_fifo_errors++;
-		}
-
-		/* Report late collisions as a frame error.
-		 * On this error, the BD is closed, but we don't know what we
-		 * have in the buffer.  So, just drop this frame on the floor.
-		 */
-		if (status & BD_ENET_RX_CL) {
-			ndev->stats.rx_errors++;
-			ndev->stats.rx_frame_errors++;
-			goto rx_processing_done;
-		}
-
-		/* Process the incoming frame. */
-		ndev->stats.rx_packets++;
-		pkt_len = bdp->cbd_datlen;
-		ndev->stats.rx_bytes += pkt_len;
-		data = (__u8*)__va(bdp->cbd_bufaddr);
-
-		dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr,
-				FEC_ENET_TX_FRSIZE, DMA_FROM_DEVICE);
-
-		if (id_entry->driver_data & FEC_QUIRK_SWAP_FRAME)
-			swap_buffer(data, pkt_len);
-
-		/* This does 16 byte alignment, exactly what we need.
-		 * The packet length includes FCS, but we don't want to
-		 * include that when passing upstream as it messes up
-		 * bridging applications.
-		 */
-		skb = netdev_alloc_skb(ndev, pkt_len - 4 + NET_IP_ALIGN);
-
-		if (unlikely(!skb)) {
-			printk("%s: Memory squeeze, dropping packet.\n",
-					ndev->name);
-			ndev->stats.rx_dropped++;
-		} else {
-			skb_reserve(skb, NET_IP_ALIGN);
-			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);
-
-			/* Get receive timestamp from the skb */
-			if (fep->hwts_rx_en && fep->bufdesc_ex) {
-				struct skb_shared_hwtstamps *shhwtstamps =
-							    skb_hwtstamps(skb);
-				unsigned long flags;
-				struct bufdesc_ex *ebdp =
-					(struct bufdesc_ex *)bdp;
-
-				memset(shhwtstamps, 0, sizeof(*shhwtstamps));
-
-				spin_lock_irqsave(&fep->tmreg_lock, flags);
-				shhwtstamps->hwtstamp = ns_to_ktime(
-				    timecounter_cyc2time(&fep->tc, ebdp->ts));
-				spin_unlock_irqrestore(&fep->tmreg_lock, flags);
-			}
-
-			if (!skb_defer_rx_timestamp(skb))
-				napi_gro_receive(&fep->napi, skb);
-		}
-
-		bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, data,
-				FEC_ENET_TX_FRSIZE, DMA_FROM_DEVICE);
-rx_processing_done:
-		/* Clear the status flags for this buffer */
-		status &= ~BD_ENET_RX_STATS;
-
-		/* Mark the buffer empty */
-		status |= BD_ENET_RX_EMPTY;
-		bdp->cbd_sc = status;
-
-		if (fep->bufdesc_ex) {
-			struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp;
-
-			ebdp->cbd_esc = BD_ENET_RX_INT;
-			ebdp->cbd_prot = 0;
-			ebdp->cbd_bdu = 0;
-		}
-
-		/* Update BD pointer to next entry */
-		if (status & BD_ENET_RX_WRAP)
-			bdp = fep->rx_bd_base;
-		else
-			bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
-		/* Doing this here will keep the FEC running while we process
-		 * incoming frames.  On a heavily loaded network, we should be
-		 * able to keep up at the expense of system resources.
-		 */
-		writel(0, fep->hwp + FEC_R_DES_ACTIVE);
-	}
-	fep->cur_rx = bdp;
-
-	return pkt_received;
-}
-
-static irqreturn_t
-fec_enet_interrupt(int irq, void *dev_id)
-{
-	struct net_device *ndev = dev_id;
-	struct fec_enet_private *fep = netdev_priv(ndev);
-	uint int_events;
-	irqreturn_t ret = IRQ_NONE;
-
-	do {
-		int_events = readl(fep->hwp + FEC_IEVENT);
-		writel(int_events, fep->hwp + FEC_IEVENT);
-
-		if (int_events & (FEC_ENET_RXF | FEC_ENET_TXF)) {
-			ret = IRQ_HANDLED;
-
-			/* Disable the RX interrupt */
-			if (napi_schedule_prep(&fep->napi)) {
-				writel(FEC_RX_DISABLED_IMASK,
-					fep->hwp + FEC_IMASK);
-				__napi_schedule(&fep->napi);
-			}
-		}
-
-		if (int_events & FEC_ENET_MII) {
-			ret = IRQ_HANDLED;
-			complete(&fep->mdio_done);
-		}
-	} while (int_events);
-
-	return ret;
-}
-
-static int fec_enet_rx_napi(struct napi_struct *napi, int budget)
-{
-	struct net_device *ndev = napi->dev;
-	int pkts = fec_enet_rx(ndev, budget);
-	struct fec_enet_private *fep = netdev_priv(ndev);
-
-	fec_enet_tx(ndev);
-
-	if (pkts < budget) {
-		napi_complete(napi);
-		writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
-	}
-	return pkts;
-}
-
-/* ------------------------------------------------------------------------- */
-static void fec_get_mac(struct net_device *ndev)
-{
-	struct fec_enet_private *fep = netdev_priv(ndev);
-	struct fec_platform_data *pdata = fep->pdev->dev.platform_data;
-	unsigned char *iap, tmpaddr[ETH_ALEN];
-
-	/*
-	 * try to get mac address in following order:
-	 *
-	 * 1) module parameter via kernel command line in form
-	 *    fec.macaddr=0x00,0x04,0x9f,0x01,0x30,0xe0
-	 */
-	iap = macaddr;
-
-#ifdef CONFIG_OF
-	/*
-	 * 2) from device tree data
-	 */
-	if (!is_valid_ether_addr(iap)) {
-		struct device_node *np = fep->pdev->dev.of_node;
-		if (np) {
-			const char *mac = of_get_mac_address(np);
-			if (mac)
-				iap = (unsigned char *) mac;
-		}
-	}
-#endif
-
-	/*
-	 * 3) from flash or fuse (via platform data)
-	 */
-	if (!is_valid_ether_addr(iap)) {
-#ifdef CONFIG_M5272
-		if (FEC_FLASHMAC)
-			iap = (unsigned char *)FEC_FLASHMAC;
-#else
-		if (pdata)
-			iap = (unsigned char *)&pdata->mac;
-#endif
-	}
-
-	/*
-	 * 4) FEC mac registers set by bootloader
-	 */
-	if (!is_valid_ether_addr(iap)) {
-		*((unsigned long *) &tmpaddr[0]) =
-			be32_to_cpu(readl(fep->hwp + FEC_ADDR_LOW));
-		*((unsigned short *) &tmpaddr[4]) =
-			be16_to_cpu(readl(fep->hwp + FEC_ADDR_HIGH) >> 16);
-		iap = &tmpaddr[0];
-	}
-
-	memcpy(ndev->dev_addr, iap, ETH_ALEN);
-
-	/* Adjust MAC if using macaddr */
-	if (iap == macaddr)
-		 ndev->dev_addr[ETH_ALEN-1] = macaddr[ETH_ALEN-1] + fep->dev_id;
-}
-
-/* ------------------------------------------------------------------------- */
-
-/*
- * Phy section
- */
-static void fec_enet_adjust_link(struct net_device *ndev)
-{
-	struct fec_enet_private *fep = netdev_priv(ndev);
-	struct phy_device *phy_dev = fep->phy_dev;
-	unsigned long flags;
-
-	int status_change = 0;
-
-	spin_lock_irqsave(&fep->hw_lock, flags);
-
-	/* Prevent a state halted on mii error */
-	if (fep->mii_timeout && phy_dev->state == PHY_HALTED) {
-		phy_dev->state = PHY_RESUMING;
-		goto spin_unlock;
-	}
-
-	if (phy_dev->link) {
-		if (!fep->link) {
-			fep->link = phy_dev->link;
-			status_change = 1;
-		}
-
-		if (fep->full_duplex != phy_dev->duplex)
-			status_change = 1;
-
-		if (phy_dev->speed != fep->speed) {
-			fep->speed = phy_dev->speed;
-			status_change = 1;
-		}
-
-		/* if any of the above changed restart the FEC */
-		if (status_change)
-			fec_restart(ndev, phy_dev->duplex);
-	} else {
-		if (fep->link) {
-			fec_stop(ndev);
-			status_change = 1;
-		}
-	}
-
-spin_unlock:
-	spin_unlock_irqrestore(&fep->hw_lock, flags);
-
-	if (status_change)
-		phy_print_status(phy_dev);
-}
-
-static int fec_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
-{
-	struct fec_enet_private *fep = bus->priv;
-	unsigned long time_left;
-
-	fep->mii_timeout = 0;
-	init_completion(&fep->mdio_done);
-
-	/* start a read op */
-	writel(FEC_MMFR_ST | FEC_MMFR_OP_READ |
-		FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(regnum) |
-		FEC_MMFR_TA, fep->hwp + FEC_MII_DATA);
-
-	/* wait for end of transfer */
-	time_left = wait_for_completion_timeout(&fep->mdio_done,
-			usecs_to_jiffies(FEC_MII_TIMEOUT));
-	if (time_left == 0) {
-		fep->mii_timeout = 1;
-		printk(KERN_ERR "FEC: MDIO read timeout\n");
-		return -ETIMEDOUT;
-	}
-
-	/* return value */
-	return FEC_MMFR_DATA(readl(fep->hwp + FEC_MII_DATA));
-}
-
-static int fec_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
-			   u16 value)
-{
-	struct fec_enet_private *fep = bus->priv;
-	unsigned long time_left;
-
-	fep->mii_timeout = 0;
-	init_completion(&fep->mdio_done);
-
-	/* start a write op */
-	writel(FEC_MMFR_ST | FEC_MMFR_OP_WRITE |
-		FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(regnum) |
-		FEC_MMFR_TA | FEC_MMFR_DATA(value),
-		fep->hwp + FEC_MII_DATA);
-
-	/* wait for end of transfer */
-	time_left = wait_for_completion_timeout(&fep->mdio_done,
-			usecs_to_jiffies(FEC_MII_TIMEOUT));
-	if (time_left == 0) {
-		fep->mii_timeout = 1;
-		printk(KERN_ERR "FEC: MDIO write timeout\n");
-		return -ETIMEDOUT;
-	}
-
-	return 0;
-}
-
-static int fec_enet_mdio_reset(struct mii_bus *bus)
-{
-	return 0;
-}
-
-static int fec_enet_mii_probe(struct net_device *ndev)
-{
-	struct fec_enet_private *fep = netdev_priv(ndev);
-	const struct platform_device_id *id_entry =
-				platform_get_device_id(fep->pdev);
-	struct phy_device *phy_dev = NULL;
-	char mdio_bus_id[MII_BUS_ID_SIZE];
-	char phy_name[MII_BUS_ID_SIZE + 3];
-	int phy_id;
-	int dev_id = fep->dev_id;
-
-	fep->phy_dev = NULL;
-
-	/* check for attached phy */
-	for (phy_id = 0; (phy_id < PHY_MAX_ADDR); phy_id++) {
-		if ((fep->mii_bus->phy_mask & (1 << phy_id)))
-			continue;
-		if (fep->mii_bus->phy_map[phy_id] == NULL)
-			continue;
-		if (fep->mii_bus->phy_map[phy_id]->phy_id == 0)
-			continue;
-		if (dev_id--)
-			continue;
-		strncpy(mdio_bus_id, fep->mii_bus->id, MII_BUS_ID_SIZE);
-		break;
-	}
-
-	if (phy_id >= PHY_MAX_ADDR) {
-		printk(KERN_INFO
-			"%s: no PHY, assuming direct connection to switch\n",
-			ndev->name);
-		strncpy(mdio_bus_id, "fixed-0", MII_BUS_ID_SIZE);
-		phy_id = 0;
-	}
-
-	snprintf(phy_name, sizeof(phy_name), PHY_ID_FMT, mdio_bus_id, phy_id);
-	phy_dev = phy_connect(ndev, phy_name, &fec_enet_adjust_link,
-			      fep->phy_interface);
-	if (IS_ERR(phy_dev)) {
-		printk(KERN_ERR "%s: could not attach to PHY\n", ndev->name);
-		return PTR_ERR(phy_dev);
-	}
-
-	/* mask with MAC supported features */
-	if (id_entry->driver_data & FEC_QUIRK_HAS_GBIT) {
-		phy_dev->supported &= PHY_GBIT_FEATURES;
-		phy_dev->supported |= SUPPORTED_Pause;
-	}
-	else
-		phy_dev->supported &= PHY_BASIC_FEATURES;
-
-	phy_dev->advertising = phy_dev->supported;
-
-	fep->phy_dev = phy_dev;
-	fep->link = 0;
-	fep->full_duplex = 0;
-
-	printk(KERN_INFO
-		"%s: Freescale FEC PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n",
-		ndev->name,
-		fep->phy_dev->drv->name, dev_name(&fep->phy_dev->dev),
-		fep->phy_dev->irq);
-
-	return 0;
-}
-
-static int fec_enet_mii_init(struct platform_device *pdev)
-{
-	static struct mii_bus *fec0_mii_bus;
-	struct net_device *ndev = platform_get_drvdata(pdev);
-	struct fec_enet_private *fep = netdev_priv(ndev);
-	const struct platform_device_id *id_entry =
-				platform_get_device_id(fep->pdev);
-	int err = -ENXIO, i;
-
-	/*
-	 * The dual fec interfaces are not equivalent with enet-mac.
-	 * Here are the differences:
-	 *
-	 *  - fec0 supports MII & RMII modes while fec1 only supports RMII
-	 *  - fec0 acts as the 1588 time master while fec1 is slave
-	 *  - external phys can only be configured by fec0
-	 *
-	 * That is to say fec1 can not work independently. It only works
-	 * when fec0 is working. The reason behind this design is that the
-	 * second interface is added primarily for Switch mode.
-	 *
-	 * Because of the last point above, both phys are attached on fec0
-	 * mdio interface in board design, and need to be configured by
-	 * fec0 mii_bus.
-	 */
-	if ((id_entry->driver_data & FEC_QUIRK_ENET_MAC) && fep->dev_id > 0) {
-		/* fec1 uses fec0 mii_bus */
-		if (mii_cnt && fec0_mii_bus) {
-			fep->mii_bus = fec0_mii_bus;
-			mii_cnt++;
-			return 0;
-		}
-		return -ENOENT;
-	}
-
-	fep->mii_timeout = 0;
-
-	/*
-	 * Set MII speed to 2.5 MHz (= clk_get_rate() / 2 * phy_speed)
-	 *
-	 * The formula for FEC MDC is 'ref_freq / (MII_SPEED x 2)' while
-	 * for ENET-MAC is 'ref_freq / ((MII_SPEED + 1) x 2)'.  The i.MX28
-	 * Reference Manual has an error on this, and gets fixed on i.MX6Q
-	 * document.
-	 */
-	fep->phy_speed = DIV_ROUND_UP(clk_get_rate(fep->clk_ahb), 5000000);
-	if (id_entry->driver_data & FEC_QUIRK_ENET_MAC)
-		fep->phy_speed--;
-	fep->phy_speed <<= 1;
-	writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED);
-
-	fep->mii_bus = mdiobus_alloc();
-	if (fep->mii_bus == NULL) {
-		err = -ENOMEM;
-		goto err_out;
-	}
-
-	fep->mii_bus->name = "fec_enet_mii_bus";
-	fep->mii_bus->read = fec_enet_mdio_read;
-	fep->mii_bus->write = fec_enet_mdio_write;
-	fep->mii_bus->reset = fec_enet_mdio_reset;
-	snprintf(fep->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",
-		pdev->name, fep->dev_id + 1);
-	fep->mii_bus->priv = fep;
-	fep->mii_bus->parent = &pdev->dev;
-
-	fep->mii_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
-	if (!fep->mii_bus->irq) {
-		err = -ENOMEM;
-		goto err_out_free_mdiobus;
-	}
-
-	for (i = 0; i < PHY_MAX_ADDR; i++)
-		fep->mii_bus->irq[i] = PHY_POLL;
-
-	if (mdiobus_register(fep->mii_bus))
-		goto err_out_free_mdio_irq;
-
-	mii_cnt++;
-
-	/* save fec0 mii_bus */
-	if (id_entry->driver_data & FEC_QUIRK_ENET_MAC)
-		fec0_mii_bus = fep->mii_bus;
-
-	return 0;
-
-err_out_free_mdio_irq:
-	kfree(fep->mii_bus->irq);
-err_out_free_mdiobus:
-	mdiobus_free(fep->mii_bus);
-err_out:
-	return err;
-}
-
-static void fec_enet_mii_remove(struct fec_enet_private *fep)
-{
-	if (--mii_cnt == 0) {
-		mdiobus_unregister(fep->mii_bus);
-		kfree(fep->mii_bus->irq);
-		mdiobus_free(fep->mii_bus);
-	}
-}
-
-static int fec_enet_get_settings(struct net_device *ndev,
-				  struct ethtool_cmd *cmd)
-{
-	struct fec_enet_private *fep = netdev_priv(ndev);
-	struct phy_device *phydev = fep->phy_dev;
-
-	if (!phydev)
-		return -ENODEV;
-
-	return phy_ethtool_gset(phydev, cmd);
-}
-
-static int fec_enet_set_settings(struct net_device *ndev,
-				 struct ethtool_cmd *cmd)
-{
-	struct fec_enet_private *fep = netdev_priv(ndev);
-	struct phy_device *phydev = fep->phy_dev;
-
-	if (!phydev)
-		return -ENODEV;
-
-	return phy_ethtool_sset(phydev, cmd);
-}
-
-static void fec_enet_get_drvinfo(struct net_device *ndev,
-				 struct ethtool_drvinfo *info)
-{
-	struct fec_enet_private *fep = netdev_priv(ndev);
-
-	strlcpy(info->driver, fep->pdev->dev.driver->name,
-		sizeof(info->driver));
-	strlcpy(info->version, "Revision: 1.0", sizeof(info->version));
-	strlcpy(info->bus_info, dev_name(&ndev->dev), sizeof(info->bus_info));
-}
-
-static int fec_enet_get_ts_info(struct net_device *ndev,
-				struct ethtool_ts_info *info)
-{
-	struct fec_enet_private *fep = netdev_priv(ndev);
-
-	if (fep->bufdesc_ex) {
-
-		info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE |
-					SOF_TIMESTAMPING_RX_SOFTWARE |
-					SOF_TIMESTAMPING_SOFTWARE |
-					SOF_TIMESTAMPING_TX_HARDWARE |
-					SOF_TIMESTAMPING_RX_HARDWARE |
-					SOF_TIMESTAMPING_RAW_HARDWARE;
-		if (fep->ptp_clock)
-			info->phc_index = ptp_clock_index(fep->ptp_clock);
-		else
-			info->phc_index = -1;
-
-		info->tx_types = (1 << HWTSTAMP_TX_OFF) |
-				 (1 << HWTSTAMP_TX_ON);
-
-		info->rx_filters = (1 << HWTSTAMP_FILTER_NONE) |
-				   (1 << HWTSTAMP_FILTER_ALL);
-		return 0;
-	} else {
-		return ethtool_op_get_ts_info(ndev, info);
-	}
-}
-
-static void fec_enet_get_pauseparam(struct net_device *ndev,
-				    struct ethtool_pauseparam *pause)
-{
-	struct fec_enet_private *fep = netdev_priv(ndev);
-
-	pause->autoneg = (fep->pause_flag & FEC_PAUSE_FLAG_AUTONEG) != 0;
-	pause->tx_pause = (fep->pause_flag & FEC_PAUSE_FLAG_ENABLE) != 0;
-	pause->rx_pause = pause->tx_pause;
-}
-
-static int fec_enet_set_pauseparam(struct net_device *ndev,
-				   struct ethtool_pauseparam *pause)
-{
-	struct fec_enet_private *fep = netdev_priv(ndev);
-
-	if (pause->tx_pause != pause->rx_pause) {
-		netdev_info(ndev,
-			"hardware only support enable/disable both tx and rx");
-		return -EINVAL;
-	}
-
-	fep->pause_flag = 0;
-
-	/* tx pause must be same as rx pause */
-	fep->pause_flag |= pause->rx_pause ? FEC_PAUSE_FLAG_ENABLE : 0;
-	fep->pause_flag |= pause->autoneg ? FEC_PAUSE_FLAG_AUTONEG : 0;
-
-	if (pause->rx_pause || pause->autoneg) {
-		fep->phy_dev->supported |= ADVERTISED_Pause;
-		fep->phy_dev->advertising |= ADVERTISED_Pause;
-	} else {
-		fep->phy_dev->supported &= ~ADVERTISED_Pause;
-		fep->phy_dev->advertising &= ~ADVERTISED_Pause;
-	}
-
-	if (pause->autoneg) {
-		if (netif_running(ndev))
-			fec_stop(ndev);
-		phy_start_aneg(fep->phy_dev);
-	}
-	if (netif_running(ndev))
-		fec_restart(ndev, 0);
-
-	return 0;
-}
-
-static const struct ethtool_ops fec_enet_ethtool_ops = {
-	.get_pauseparam		= fec_enet_get_pauseparam,
-	.set_pauseparam		= fec_enet_set_pauseparam,
-	.get_settings		= fec_enet_get_settings,
-	.set_settings		= fec_enet_set_settings,
-	.get_drvinfo		= fec_enet_get_drvinfo,
-	.get_link		= ethtool_op_get_link,
-	.get_ts_info		= fec_enet_get_ts_info,
-};
-
-static int fec_enet_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
-{
-	struct fec_enet_private *fep = netdev_priv(ndev);
-	struct phy_device *phydev = fep->phy_dev;
-
-	if (!netif_running(ndev))
-		return -EINVAL;
-
-	if (!phydev)
-		return -ENODEV;
-
-	if (cmd == SIOCSHWTSTAMP && fep->bufdesc_ex)
-		return fec_ptp_ioctl(ndev, rq, cmd);
-
-	return phy_mii_ioctl(phydev, rq, cmd);
-}
-
-static void fec_enet_free_buffers(struct net_device *ndev)
-{
-	struct fec_enet_private *fep = netdev_priv(ndev);
-	unsigned int i;
-	struct sk_buff *skb;
-	struct bufdesc	*bdp;
-
-	bdp = fep->rx_bd_base;
-	for (i = 0; i < RX_RING_SIZE; i++) {
-		skb = fep->rx_skbuff[i];
-
-		if (bdp->cbd_bufaddr)
-			dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr,
-					FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE);
-		if (skb)
-			dev_kfree_skb(skb);
-		bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
-	}
-
-	bdp = fep->tx_bd_base;
-	for (i = 0; i < TX_RING_SIZE; i++)
-		kfree(fep->tx_bounce[i]);
-}
-
-static int fec_enet_alloc_buffers(struct net_device *ndev)
-{
-	struct fec_enet_private *fep = netdev_priv(ndev);
-	unsigned int i;
-	struct sk_buff *skb;
-	struct bufdesc	*bdp;
-
-	bdp = fep->rx_bd_base;
-	for (i = 0; i < RX_RING_SIZE; i++) {
-		skb = netdev_alloc_skb(ndev, FEC_ENET_RX_FRSIZE);
-		if (!skb) {
-			fec_enet_free_buffers(ndev);
-			return -ENOMEM;
-		}
-		fep->rx_skbuff[i] = skb;
-
-		bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, skb->data,
-				FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE);
-		bdp->cbd_sc = BD_ENET_RX_EMPTY;
-
-		if (fep->bufdesc_ex) {
-			struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp;
-			ebdp->cbd_esc = BD_ENET_RX_INT;
-		}
-
-		bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
-	}
-
-	/* Set the last buffer to wrap. */
-	bdp = fec_enet_get_prevdesc(bdp, fep->bufdesc_ex);
-	bdp->cbd_sc |= BD_SC_WRAP;
-
-	bdp = fep->tx_bd_base;
-	for (i = 0; i < TX_RING_SIZE; i++) {
-		fep->tx_bounce[i] = kmalloc(FEC_ENET_TX_FRSIZE, GFP_KERNEL);
-
-		bdp->cbd_sc = 0;
-		bdp->cbd_bufaddr = 0;
-
-		if (fep->bufdesc_ex) {
-			struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp;
-			ebdp->cbd_esc = BD_ENET_RX_INT;
-		}
-
-		bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
-	}
-
-	/* Set the last buffer to wrap. */
-	bdp = fec_enet_get_prevdesc(bdp, fep->bufdesc_ex);
-	bdp->cbd_sc |= BD_SC_WRAP;
-
-	return 0;
-}
-
-static int
-fec_enet_open(struct net_device *ndev)
-{
-	struct fec_enet_private *fep = netdev_priv(ndev);
-	int ret;
-
-	napi_enable(&fep->napi);
-
-	/* I should reset the ring buffers here, but I don't yet know
-	 * a simple way to do that.
-	 */
-
-	ret = fec_enet_alloc_buffers(ndev);
-	if (ret)
-		return ret;
-
-	/* Probe and connect to PHY when open the interface */
-	ret = fec_enet_mii_probe(ndev);
-	if (ret) {
-		fec_enet_free_buffers(ndev);
-		return ret;
-	}
-	phy_start(fep->phy_dev);
-	netif_start_queue(ndev);
-	fep->opened = 1;
-	return 0;
-}
-
-static int
-fec_enet_close(struct net_device *ndev)
-{
-	struct fec_enet_private *fep = netdev_priv(ndev);
-
-	/* Don't know what to do yet. */
-	napi_disable(&fep->napi);
-	fep->opened = 0;
-	netif_stop_queue(ndev);
-	fec_stop(ndev);
-
-	if (fep->phy_dev) {
-		phy_stop(fep->phy_dev);
-		phy_disconnect(fep->phy_dev);
-	}
-
-	fec_enet_free_buffers(ndev);
-
-	return 0;
-}
-
-/* Set or clear the multicast filter for this adaptor.
- * Skeleton taken from sunlance driver.
- * The CPM Ethernet implementation allows Multicast as well as individual
- * MAC address filtering.  Some of the drivers check to make sure it is
- * a group multicast address, and discard those that are not.  I guess I
- * will do the same for now, but just remove the test if you want
- * individual filtering as well (do the upper net layers want or support
- * this kind of feature?).
- */
-
-#define HASH_BITS	6		/* #bits in hash */
-#define CRC32_POLY	0xEDB88320
-
-static void set_multicast_list(struct net_device *ndev)
-{
-	struct fec_enet_private *fep = netdev_priv(ndev);
-	struct netdev_hw_addr *ha;
-	unsigned int i, bit, data, crc, tmp;
-	unsigned char hash;
-
-	if (ndev->flags & IFF_PROMISC) {
-		tmp = readl(fep->hwp + FEC_R_CNTRL);
-		tmp |= 0x8;
-		writel(tmp, fep->hwp + FEC_R_CNTRL);
-		return;
-	}
-
-	tmp = readl(fep->hwp + FEC_R_CNTRL);
-	tmp &= ~0x8;
-	writel(tmp, fep->hwp + FEC_R_CNTRL);
-
-	if (ndev->flags & IFF_ALLMULTI) {
-		/* Catch all multicast addresses, so set the
-		 * filter to all 1's
-		 */
-		writel(0xffffffff, fep->hwp + FEC_GRP_HASH_TABLE_HIGH);
-		writel(0xffffffff, fep->hwp + FEC_GRP_HASH_TABLE_LOW);
-
-		return;
-	}
-
-	/* Clear filter and add the addresses in hash register
-	 */
-	writel(0, fep->hwp + FEC_GRP_HASH_TABLE_HIGH);
-	writel(0, fep->hwp + FEC_GRP_HASH_TABLE_LOW);
-
-	netdev_for_each_mc_addr(ha, ndev) {
-		/* calculate crc32 value of mac address */
-		crc = 0xffffffff;
-
-		for (i = 0; i < ndev->addr_len; i++) {
-			data = ha->addr[i];
-			for (bit = 0; bit < 8; bit++, data >>= 1) {
-				crc = (crc >> 1) ^
-				(((crc ^ data) & 1) ? CRC32_POLY : 0);
-			}
-		}
-
-		/* only upper 6 bits (HASH_BITS) are used
-		 * which point to specific bit in he hash registers
-		 */
-		hash = (crc >> (32 - HASH_BITS)) & 0x3f;
-
-		if (hash > 31) {
-			tmp = readl(fep->hwp + FEC_GRP_HASH_TABLE_HIGH);
-			tmp |= 1 << (hash - 32);
-			writel(tmp, fep->hwp + FEC_GRP_HASH_TABLE_HIGH);
-		} else {
-			tmp = readl(fep->hwp + FEC_GRP_HASH_TABLE_LOW);
-			tmp |= 1 << hash;
-			writel(tmp, fep->hwp + FEC_GRP_HASH_TABLE_LOW);
-		}
-	}
-}
-
-/* Set a MAC change in hardware. */
-static int
-fec_set_mac_address(struct net_device *ndev, void *p)
-{
-	struct fec_enet_private *fep = netdev_priv(ndev);
-	struct sockaddr *addr = p;
-
-	if (!is_valid_ether_addr(addr->sa_data))
-		return -EADDRNOTAVAIL;
-
-	memcpy(ndev->dev_addr, addr->sa_data, ndev->addr_len);
-
-	writel(ndev->dev_addr[3] | (ndev->dev_addr[2] << 8) |
-		(ndev->dev_addr[1] << 16) | (ndev->dev_addr[0] << 24),
-		fep->hwp + FEC_ADDR_LOW);
-	writel((ndev->dev_addr[5] << 16) | (ndev->dev_addr[4] << 24),
-		fep->hwp + FEC_ADDR_HIGH);
-	return 0;
-}
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-/**
- * fec_poll_controller - FEC Poll controller function
- * @dev: The FEC network adapter
- *
- * Polled functionality used by netconsole and others in non interrupt mode
- *
- */
-void fec_poll_controller(struct net_device *dev)
-{
-	int i;
-	struct fec_enet_private *fep = netdev_priv(dev);
-
-	for (i = 0; i < FEC_IRQ_NUM; i++) {
-		if (fep->irq[i] > 0) {
-			disable_irq(fep->irq[i]);
-			fec_enet_interrupt(fep->irq[i], dev);
-			enable_irq(fep->irq[i]);
-		}
-	}
-}
-#endif
-
-static const struct net_device_ops fec_netdev_ops = {
-	.ndo_open		= fec_enet_open,
-	.ndo_stop		= fec_enet_close,
-	.ndo_start_xmit		= fec_enet_start_xmit,
-	.ndo_set_rx_mode	= set_multicast_list,
-	.ndo_change_mtu		= eth_change_mtu,
-	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_tx_timeout		= fec_timeout,
-	.ndo_set_mac_address	= fec_set_mac_address,
-	.ndo_do_ioctl		= fec_enet_ioctl,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	.ndo_poll_controller	= fec_poll_controller,
-#endif
-};
-
- /*
-  * XXX:  We need to clean up on failure exits here.
-  *
-  */
-static int fec_enet_init(struct net_device *ndev)
-{
-	struct fec_enet_private *fep = netdev_priv(ndev);
-	struct bufdesc *cbd_base;
-	struct bufdesc *bdp;
-	unsigned int i;
-
-	/* Allocate memory for buffer descriptors. */
-	cbd_base = dma_alloc_coherent(NULL, PAGE_SIZE, &fep->bd_dma,
-			GFP_KERNEL);
-	if (!cbd_base) {
-		printk("FEC: allocate descriptor memory failed?\n");
-		return -ENOMEM;
-	}
-
-	spin_lock_init(&fep->hw_lock);
-
-	fep->netdev = ndev;
-
-	/* Get the Ethernet address */
-	fec_get_mac(ndev);
-
-	/* Set receive and transmit descriptor base. */
-	fep->rx_bd_base = cbd_base;
-	if (fep->bufdesc_ex)
-		fep->tx_bd_base = (struct bufdesc *)
-			(((struct bufdesc_ex *)cbd_base) + RX_RING_SIZE);
-	else
-		fep->tx_bd_base = cbd_base + RX_RING_SIZE;
-
-	/* The FEC Ethernet specific entries in the device structure */
-	ndev->watchdog_timeo = TX_TIMEOUT;
-	ndev->netdev_ops = &fec_netdev_ops;
-	ndev->ethtool_ops = &fec_enet_ethtool_ops;
-
-	writel(FEC_RX_DISABLED_IMASK, fep->hwp + FEC_IMASK);
-	netif_napi_add(ndev, &fep->napi, fec_enet_rx_napi, FEC_NAPI_WEIGHT);
-
-	/* Initialize the receive buffer descriptors. */
-	bdp = fep->rx_bd_base;
-	for (i = 0; i < RX_RING_SIZE; i++) {
-
-		/* Initialize the BD for every fragment in the page. */
-		bdp->cbd_sc = 0;
-		bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
-	}
-
-	/* Set the last buffer to wrap */
-	bdp = fec_enet_get_prevdesc(bdp, fep->bufdesc_ex);
-	bdp->cbd_sc |= BD_SC_WRAP;
-
-	/* ...and the same for transmit */
-	bdp = fep->tx_bd_base;
-	fep->cur_tx = bdp;
-	for (i = 0; i < TX_RING_SIZE; i++) {
-
-		/* Initialize the BD for every fragment in the page. */
-		bdp->cbd_sc = 0;
-		bdp->cbd_bufaddr = 0;
-		bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
-	}
-
-	/* Set the last buffer to wrap */
-	bdp = fec_enet_get_prevdesc(bdp, fep->bufdesc_ex);
-	bdp->cbd_sc |= BD_SC_WRAP;
-	fep->dirty_tx = bdp;
-
-	fec_restart(ndev, 0);
-
-	return 0;
-}
-
-#ifdef CONFIG_OF
-static int fec_get_phy_mode_dt(struct platform_device *pdev)
-{
-	struct device_node *np = pdev->dev.of_node;
-
-	if (np)
-		return of_get_phy_mode(np);
-
-	return -ENODEV;
-}
-
-static void fec_reset_phy(struct platform_device *pdev)
-{
-	int err, phy_reset;
-	int msec = 1;
-	struct device_node *np = pdev->dev.of_node;
-
-	if (!np)
-		return;
-
-	of_property_read_u32(np, "phy-reset-duration", &msec);
-	/* A sane reset duration should not be longer than 1s */
-	if (msec > 1000)
-		msec = 1;
-
-	phy_reset = of_get_named_gpio(np, "phy-reset-gpios", 0);
-	if (!gpio_is_valid(phy_reset))
-		return;
-
-	err = devm_gpio_request_one(&pdev->dev, phy_reset,
-				    GPIOF_OUT_INIT_LOW, "phy-reset");
-	if (err) {
-		dev_err(&pdev->dev, "failed to get phy-reset-gpios: %d\n", err);
-		return;
-	}
-	msleep(msec);
-	gpio_set_value(phy_reset, 1);
-}
-#else /* CONFIG_OF */
-static int fec_get_phy_mode_dt(struct platform_device *pdev)
-{
-	return -ENODEV;
-}
-
-static void fec_reset_phy(struct platform_device *pdev)
-{
-	/*
-	 * In case of platform probe, the reset has been done
-	 * by machine code.
-	 */
-}
-#endif /* CONFIG_OF */
-
-static int
-fec_probe(struct platform_device *pdev)
-{
-	struct fec_enet_private *fep;
-	struct fec_platform_data *pdata;
-	struct net_device *ndev;
-	int i, irq, ret = 0;
-	struct resource *r;
-	const struct of_device_id *of_id;
-	static int dev_id;
-	struct pinctrl *pinctrl;
-	struct regulator *reg_phy;
-
-	of_id = of_match_device(fec_dt_ids, &pdev->dev);
-	if (of_id)
-		pdev->id_entry = of_id->data;
-
-	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!r)
-		return -ENXIO;
-
-	r = request_mem_region(r->start, resource_size(r), pdev->name);
-	if (!r)
-		return -EBUSY;
-
-	/* Init network device */
-	ndev = alloc_etherdev(sizeof(struct fec_enet_private));
-	if (!ndev) {
-		ret = -ENOMEM;
-		goto failed_alloc_etherdev;
-	}
-
-	SET_NETDEV_DEV(ndev, &pdev->dev);
-
-	/* setup board info structure */
-	fep = netdev_priv(ndev);
-
-	/* default enable pause frame auto negotiation */
-	if (pdev->id_entry &&
-	    (pdev->id_entry->driver_data & FEC_QUIRK_HAS_GBIT))
-		fep->pause_flag |= FEC_PAUSE_FLAG_AUTONEG;
-
-	fep->hwp = ioremap(r->start, resource_size(r));
-	fep->pdev = pdev;
-	fep->dev_id = dev_id++;
-
-	fep->bufdesc_ex = 0;
-
-	if (!fep->hwp) {
-		ret = -ENOMEM;
-		goto failed_ioremap;
-	}
-
-	platform_set_drvdata(pdev, ndev);
-
-	ret = fec_get_phy_mode_dt(pdev);
-	if (ret < 0) {
-		pdata = pdev->dev.platform_data;
-		if (pdata)
-			fep->phy_interface = pdata->phy;
-		else
-			fep->phy_interface = PHY_INTERFACE_MODE_MII;
-	} else {
-		fep->phy_interface = ret;
-	}
-
-	pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
-	if (IS_ERR(pinctrl)) {
-		ret = PTR_ERR(pinctrl);
-		goto failed_pin;
-	}
-
-	fep->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
-	if (IS_ERR(fep->clk_ipg)) {
-		ret = PTR_ERR(fep->clk_ipg);
-		goto failed_clk;
-	}
-
-	fep->clk_ahb = devm_clk_get(&pdev->dev, "ahb");
-	if (IS_ERR(fep->clk_ahb)) {
-		ret = PTR_ERR(fep->clk_ahb);
-		goto failed_clk;
-	}
-
-	fep->clk_ptp = devm_clk_get(&pdev->dev, "ptp");
-	fep->bufdesc_ex =
-		pdev->id_entry->driver_data & FEC_QUIRK_HAS_BUFDESC_EX;
-	if (IS_ERR(fep->clk_ptp)) {
-		ret = PTR_ERR(fep->clk_ptp);
-		fep->bufdesc_ex = 0;
-	}
-
-	clk_prepare_enable(fep->clk_ahb);
-	clk_prepare_enable(fep->clk_ipg);
-	if (!IS_ERR(fep->clk_ptp))
-		clk_prepare_enable(fep->clk_ptp);
-
-	reg_phy = devm_regulator_get(&pdev->dev, "phy");
-	if (!IS_ERR(reg_phy)) {
-		ret = regulator_enable(reg_phy);
-		if (ret) {
-			dev_err(&pdev->dev,
-				"Failed to enable phy regulator: %d\n", ret);
-			goto failed_regulator;
-		}
-	}
-
-	fec_reset_phy(pdev);
-
-	if (fep->bufdesc_ex)
-		fec_ptp_init(ndev, pdev);
-
-	ret = fec_enet_init(ndev);
-	if (ret)
-		goto failed_init;
-
-	for (i = 0; i < FEC_IRQ_NUM; i++) {
-		irq = platform_get_irq(pdev, i);
-		if (irq < 0) {
-			if (i)
-				break;
-			ret = irq;
-			goto failed_irq;
-		}
-		ret = request_irq(irq, fec_enet_interrupt, IRQF_DISABLED, pdev->name, ndev);
-		if (ret) {
-			while (--i >= 0) {
-				irq = platform_get_irq(pdev, i);
-				free_irq(irq, ndev);
-			}
-			goto failed_irq;
-		}
-	}
-
-	ret = fec_enet_mii_init(pdev);
-	if (ret)
-		goto failed_mii_init;
-
-	/* Carrier starts down, phylib will bring it up */
-	netif_carrier_off(ndev);
-
-	ret = register_netdev(ndev);
-	if (ret)
-		goto failed_register;
-
-	return 0;
-
-failed_register:
-	fec_enet_mii_remove(fep);
-failed_mii_init:
-failed_init:
-	for (i = 0; i < FEC_IRQ_NUM; i++) {
-		irq = platform_get_irq(pdev, i);
-		if (irq > 0)
-			free_irq(irq, ndev);
-	}
-failed_irq:
-failed_regulator:
-	clk_disable_unprepare(fep->clk_ahb);
-	clk_disable_unprepare(fep->clk_ipg);
-	if (!IS_ERR(fep->clk_ptp))
-		clk_disable_unprepare(fep->clk_ptp);
-failed_pin:
-failed_clk:
-	iounmap(fep->hwp);
-failed_ioremap:
-	free_netdev(ndev);
-failed_alloc_etherdev:
-	release_mem_region(r->start, resource_size(r));
-
-	return ret;
-}
-
-static int
-fec_drv_remove(struct platform_device *pdev)
-{
-	struct net_device *ndev = platform_get_drvdata(pdev);
-	struct fec_enet_private *fep = netdev_priv(ndev);
-	struct resource *r;
-	int i;
-
-	unregister_netdev(ndev);
-	fec_enet_mii_remove(fep);
-	del_timer_sync(&fep->time_keep);
-	clk_disable_unprepare(fep->clk_ptp);
-	if (fep->ptp_clock)
-		ptp_clock_unregister(fep->ptp_clock);
-	clk_disable_unprepare(fep->clk_ahb);
-	clk_disable_unprepare(fep->clk_ipg);
-	for (i = 0; i < FEC_IRQ_NUM; i++) {
-		int irq = platform_get_irq(pdev, i);
-		if (irq > 0)
-			free_irq(irq, ndev);
-	}
-	iounmap(fep->hwp);
-	free_netdev(ndev);
-
-	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	BUG_ON(!r);
-	release_mem_region(r->start, resource_size(r));
-
-	platform_set_drvdata(pdev, NULL);
-
-	return 0;
-}
-
-#ifdef CONFIG_PM
-static int
-fec_suspend(struct device *dev)
-{
-	struct net_device *ndev = dev_get_drvdata(dev);
-	struct fec_enet_private *fep = netdev_priv(ndev);
-
-	if (netif_running(ndev)) {
-		fec_stop(ndev);
-		netif_device_detach(ndev);
-	}
-	clk_disable_unprepare(fep->clk_ahb);
-	clk_disable_unprepare(fep->clk_ipg);
-
-	return 0;
-}
-
-static int
-fec_resume(struct device *dev)
-{
-	struct net_device *ndev = dev_get_drvdata(dev);
-	struct fec_enet_private *fep = netdev_priv(ndev);
-
-	clk_prepare_enable(fep->clk_ahb);
-	clk_prepare_enable(fep->clk_ipg);
-	if (netif_running(ndev)) {
-		fec_restart(ndev, fep->full_duplex);
-		netif_device_attach(ndev);
-	}
-
-	return 0;
-}
-
-static const struct dev_pm_ops fec_pm_ops = {
-	.suspend	= fec_suspend,
-	.resume		= fec_resume,
-	.freeze		= fec_suspend,
-	.thaw		= fec_resume,
-	.poweroff	= fec_suspend,
-	.restore	= fec_resume,
-};
-#endif
-
-static struct platform_driver fec_driver = {
-	.driver	= {
-		.name	= DRIVER_NAME,
-		.owner	= THIS_MODULE,
-#ifdef CONFIG_PM
-		.pm	= &fec_pm_ops,
-#endif
-		.of_match_table = fec_dt_ids,
-	},
-	.id_table = fec_devtype,
-	.probe	= fec_probe,
-	.remove	= fec_drv_remove,
-};
-
-module_platform_driver(fec_driver);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h
index eb43729..feabcb6 100644
--- a/drivers/net/ethernet/freescale/fec.h
+++ b/drivers/net/ethernet/freescale/fec.h
@@ -207,6 +207,7 @@ struct fec_enet_private {
 
 	struct clk *clk_ipg;
 	struct clk *clk_ahb;
+	struct clk *clk_enet_out;
 	struct clk *clk_ptp;
 
 	/* The saved address of a sent-in-place packet/buffer, for skfree(). */
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
new file mode 100644
index 0000000..806a56d
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -0,0 +1,1975 @@
+/*
+ * Fast Ethernet Controller (FEC) driver for Motorola MPC8xx.
+ * Copyright (c) 1997 Dan Malek (dmalek@jlc.net)
+ *
+ * Right now, I am very wasteful with the buffers.  I allocate memory
+ * pages and then divide them into 2K frame buffers.  This way I know I
+ * have buffers large enough to hold one frame within one buffer descriptor.
+ * Once I get this working, I will use 64 or 128 byte CPM buffers, which
+ * will be much more memory efficient and will easily handle lots of
+ * small packets.
+ *
+ * Much better multiple PHY support by Magnus Damm.
+ * Copyright (c) 2000 Ericsson Radio Systems AB.
+ *
+ * Support for FEC controller of ColdFire processors.
+ * Copyright (c) 2001-2005 Greg Ungerer (gerg@snapgear.com)
+ *
+ * Bug fixes and cleanup by Philippe De Muyter (phdm@macqel.be)
+ * Copyright (c) 2004-2006 Macq Electronique SA.
+ *
+ * Copyright (C) 2010-2011 Freescale Semiconductor, Inc.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/phy.h>
+#include <linux/fec.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/of_net.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/regulator/consumer.h>
+
+#include <asm/cacheflush.h>
+
+#ifndef CONFIG_ARM
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+#endif
+
+#include "fec.h"
+
+#if defined(CONFIG_ARM)
+#define FEC_ALIGNMENT	0xf
+#else
+#define FEC_ALIGNMENT	0x3
+#endif
+
+#define DRIVER_NAME	"fec"
+#define FEC_NAPI_WEIGHT	64
+
+/* Pause frame feild and FIFO threshold */
+#define FEC_ENET_FCE	(1 << 5)
+#define FEC_ENET_RSEM_V	0x84
+#define FEC_ENET_RSFL_V	16
+#define FEC_ENET_RAEM_V	0x8
+#define FEC_ENET_RAFL_V	0x8
+#define FEC_ENET_OPD_V	0xFFF0
+
+/* Controller is ENET-MAC */
+#define FEC_QUIRK_ENET_MAC		(1 << 0)
+/* Controller needs driver to swap frame */
+#define FEC_QUIRK_SWAP_FRAME		(1 << 1)
+/* Controller uses gasket */
+#define FEC_QUIRK_USE_GASKET		(1 << 2)
+/* Controller has GBIT support */
+#define FEC_QUIRK_HAS_GBIT		(1 << 3)
+/* Controller has extend desc buffer */
+#define FEC_QUIRK_HAS_BUFDESC_EX	(1 << 4)
+
+static struct platform_device_id fec_devtype[] = {
+	{
+		/* keep it for coldfire */
+		.name = DRIVER_NAME,
+		.driver_data = 0,
+	}, {
+		.name = "imx25-fec",
+		.driver_data = FEC_QUIRK_USE_GASKET,
+	}, {
+		.name = "imx27-fec",
+		.driver_data = 0,
+	}, {
+		.name = "imx28-fec",
+		.driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_SWAP_FRAME,
+	}, {
+		.name = "imx6q-fec",
+		.driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT |
+				FEC_QUIRK_HAS_BUFDESC_EX,
+	}, {
+		/* sentinel */
+	}
+};
+MODULE_DEVICE_TABLE(platform, fec_devtype);
+
+enum imx_fec_type {
+	IMX25_FEC = 1,	/* runs on i.mx25/50/53 */
+	IMX27_FEC,	/* runs on i.mx27/35/51 */
+	IMX28_FEC,
+	IMX6Q_FEC,
+};
+
+static const struct of_device_id fec_dt_ids[] = {
+	{ .compatible = "fsl,imx25-fec", .data = &fec_devtype[IMX25_FEC], },
+	{ .compatible = "fsl,imx27-fec", .data = &fec_devtype[IMX27_FEC], },
+	{ .compatible = "fsl,imx28-fec", .data = &fec_devtype[IMX28_FEC], },
+	{ .compatible = "fsl,imx6q-fec", .data = &fec_devtype[IMX6Q_FEC], },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, fec_dt_ids);
+
+static unsigned char macaddr[ETH_ALEN];
+module_param_array(macaddr, byte, NULL, 0);
+MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address");
+
+#if defined(CONFIG_M5272)
+/*
+ * Some hardware gets it MAC address out of local flash memory.
+ * if this is non-zero then assume it is the address to get MAC from.
+ */
+#if defined(CONFIG_NETtel)
+#define	FEC_FLASHMAC	0xf0006006
+#elif defined(CONFIG_GILBARCONAP) || defined(CONFIG_SCALES)
+#define	FEC_FLASHMAC	0xf0006000
+#elif defined(CONFIG_CANCam)
+#define	FEC_FLASHMAC	0xf0020000
+#elif defined (CONFIG_M5272C3)
+#define	FEC_FLASHMAC	(0xffe04000 + 4)
+#elif defined(CONFIG_MOD5272)
+#define FEC_FLASHMAC	0xffc0406b
+#else
+#define	FEC_FLASHMAC	0
+#endif
+#endif /* CONFIG_M5272 */
+
+#if (((RX_RING_SIZE + TX_RING_SIZE) * 32) > PAGE_SIZE)
+#error "FEC: descriptor ring size constants too large"
+#endif
+
+/* Interrupt events/masks. */
+#define FEC_ENET_HBERR	((uint)0x80000000)	/* Heartbeat error */
+#define FEC_ENET_BABR	((uint)0x40000000)	/* Babbling receiver */
+#define FEC_ENET_BABT	((uint)0x20000000)	/* Babbling transmitter */
+#define FEC_ENET_GRA	((uint)0x10000000)	/* Graceful stop complete */
+#define FEC_ENET_TXF	((uint)0x08000000)	/* Full frame transmitted */
+#define FEC_ENET_TXB	((uint)0x04000000)	/* A buffer was transmitted */
+#define FEC_ENET_RXF	((uint)0x02000000)	/* Full frame received */
+#define FEC_ENET_RXB	((uint)0x01000000)	/* A buffer was received */
+#define FEC_ENET_MII	((uint)0x00800000)	/* MII interrupt */
+#define FEC_ENET_EBERR	((uint)0x00400000)	/* SDMA bus error */
+
+#define FEC_DEFAULT_IMASK (FEC_ENET_TXF | FEC_ENET_RXF | FEC_ENET_MII)
+#define FEC_RX_DISABLED_IMASK (FEC_DEFAULT_IMASK & (~FEC_ENET_RXF))
+
+/* The FEC stores dest/src/type, data, and checksum for receive packets.
+ */
+#define PKT_MAXBUF_SIZE		1518
+#define PKT_MINBUF_SIZE		64
+#define PKT_MAXBLR_SIZE		1520
+
+/*
+ * The 5270/5271/5280/5282/532x RX control register also contains maximum frame
+ * size bits. Other FEC hardware does not, so we need to take that into
+ * account when setting it.
+ */
+#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
+    defined(CONFIG_M520x) || defined(CONFIG_M532x) || defined(CONFIG_ARM)
+#define	OPT_FRAME_SIZE	(PKT_MAXBUF_SIZE << 16)
+#else
+#define	OPT_FRAME_SIZE	0
+#endif
+
+/* FEC MII MMFR bits definition */
+#define FEC_MMFR_ST		(1 << 30)
+#define FEC_MMFR_OP_READ	(2 << 28)
+#define FEC_MMFR_OP_WRITE	(1 << 28)
+#define FEC_MMFR_PA(v)		((v & 0x1f) << 23)
+#define FEC_MMFR_RA(v)		((v & 0x1f) << 18)
+#define FEC_MMFR_TA		(2 << 16)
+#define FEC_MMFR_DATA(v)	(v & 0xffff)
+
+#define FEC_MII_TIMEOUT		30000 /* us */
+
+/* Transmitter timeout */
+#define TX_TIMEOUT (2 * HZ)
+
+#define FEC_PAUSE_FLAG_AUTONEG	0x1
+#define FEC_PAUSE_FLAG_ENABLE	0x2
+
+static int mii_cnt;
+
+static struct bufdesc *fec_enet_get_nextdesc(struct bufdesc *bdp, int is_ex)
+{
+	struct bufdesc_ex *ex = (struct bufdesc_ex *)bdp;
+	if (is_ex)
+		return (struct bufdesc *)(ex + 1);
+	else
+		return bdp + 1;
+}
+
+static struct bufdesc *fec_enet_get_prevdesc(struct bufdesc *bdp, int is_ex)
+{
+	struct bufdesc_ex *ex = (struct bufdesc_ex *)bdp;
+	if (is_ex)
+		return (struct bufdesc *)(ex - 1);
+	else
+		return bdp - 1;
+}
+
+static void *swap_buffer(void *bufaddr, int len)
+{
+	int i;
+	unsigned int *buf = bufaddr;
+
+	for (i = 0; i < (len + 3) / 4; i++, buf++)
+		*buf = cpu_to_be32(*buf);
+
+	return bufaddr;
+}
+
+static netdev_tx_t
+fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
+{
+	struct fec_enet_private *fep = netdev_priv(ndev);
+	const struct platform_device_id *id_entry =
+				platform_get_device_id(fep->pdev);
+	struct bufdesc *bdp;
+	void *bufaddr;
+	unsigned short	status;
+	unsigned int index;
+
+	if (!fep->link) {
+		/* Link is down or autonegotiation is in progress. */
+		return NETDEV_TX_BUSY;
+	}
+
+	/* Fill in a Tx ring entry */
+	bdp = fep->cur_tx;
+
+	status = bdp->cbd_sc;
+
+	if (status & BD_ENET_TX_READY) {
+		/* Ooops.  All transmit buffers are full.  Bail out.
+		 * This should not happen, since ndev->tbusy should be set.
+		 */
+		printk("%s: tx queue full!.\n", ndev->name);
+		return NETDEV_TX_BUSY;
+	}
+
+	/* Clear all of the status flags */
+	status &= ~BD_ENET_TX_STATS;
+
+	/* Set buffer length and buffer pointer */
+	bufaddr = skb->data;
+	bdp->cbd_datlen = skb->len;
+
+	/*
+	 * On some FEC implementations data must be aligned on
+	 * 4-byte boundaries. Use bounce buffers to copy data
+	 * and get it aligned. Ugh.
+	 */
+	if (fep->bufdesc_ex)
+		index = (struct bufdesc_ex *)bdp -
+			(struct bufdesc_ex *)fep->tx_bd_base;
+	else
+		index = bdp - fep->tx_bd_base;
+
+	if (((unsigned long) bufaddr) & FEC_ALIGNMENT) {
+		memcpy(fep->tx_bounce[index], skb->data, skb->len);
+		bufaddr = fep->tx_bounce[index];
+	}
+
+	/*
+	 * Some design made an incorrect assumption on endian mode of
+	 * the system that it's running on. As the result, driver has to
+	 * swap every frame going to and coming from the controller.
+	 */
+	if (id_entry->driver_data & FEC_QUIRK_SWAP_FRAME)
+		swap_buffer(bufaddr, skb->len);
+
+	/* Save skb pointer */
+	fep->tx_skbuff[index] = skb;
+
+	/* Push the data cache so the CPM does not get stale memory
+	 * data.
+	 */
+	bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, bufaddr,
+			FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE);
+
+	/* Send it on its way.  Tell FEC it's ready, interrupt when done,
+	 * it's the last BD of the frame, and to put the CRC on the end.
+	 */
+	status |= (BD_ENET_TX_READY | BD_ENET_TX_INTR
+			| BD_ENET_TX_LAST | BD_ENET_TX_TC);
+	bdp->cbd_sc = status;
+
+	if (fep->bufdesc_ex) {
+
+		struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp;
+		ebdp->cbd_bdu = 0;
+		if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP &&
+			fep->hwts_tx_en)) {
+			ebdp->cbd_esc = (BD_ENET_TX_TS | BD_ENET_TX_INT);
+			skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
+		} else {
+
+			ebdp->cbd_esc = BD_ENET_TX_INT;
+		}
+	}
+	/* If this was the last BD in the ring, start at the beginning again. */
+	if (status & BD_ENET_TX_WRAP)
+		bdp = fep->tx_bd_base;
+	else
+		bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
+
+	fep->cur_tx = bdp;
+
+	if (fep->cur_tx == fep->dirty_tx)
+		netif_stop_queue(ndev);
+
+	/* Trigger transmission start */
+	writel(0, fep->hwp + FEC_X_DES_ACTIVE);
+
+	skb_tx_timestamp(skb);
+
+	return NETDEV_TX_OK;
+}
+
+/* Init RX & TX buffer descriptors
+ */
+static void fec_enet_bd_init(struct net_device *dev)
+{
+	struct fec_enet_private *fep = netdev_priv(dev);
+	struct bufdesc *bdp;
+	unsigned int i;
+
+	/* Initialize the receive buffer descriptors. */
+	bdp = fep->rx_bd_base;
+	for (i = 0; i < RX_RING_SIZE; i++) {
+
+		/* Initialize the BD for every fragment in the page. */
+		if (bdp->cbd_bufaddr)
+			bdp->cbd_sc = BD_ENET_RX_EMPTY;
+		else
+			bdp->cbd_sc = 0;
+		bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
+	}
+
+	/* Set the last buffer to wrap */
+	bdp = fec_enet_get_prevdesc(bdp, fep->bufdesc_ex);
+	bdp->cbd_sc |= BD_SC_WRAP;
+
+	fep->cur_rx = fep->rx_bd_base;
+
+	/* ...and the same for transmit */
+	bdp = fep->tx_bd_base;
+	fep->cur_tx = bdp;
+	for (i = 0; i < TX_RING_SIZE; i++) {
+
+		/* Initialize the BD for every fragment in the page. */
+		bdp->cbd_sc = 0;
+		if (bdp->cbd_bufaddr && fep->tx_skbuff[i]) {
+			dev_kfree_skb_any(fep->tx_skbuff[i]);
+			fep->tx_skbuff[i] = NULL;
+		}
+		bdp->cbd_bufaddr = 0;
+		bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
+	}
+
+	/* Set the last buffer to wrap */
+	bdp = fec_enet_get_prevdesc(bdp, fep->bufdesc_ex);
+	bdp->cbd_sc |= BD_SC_WRAP;
+	fep->dirty_tx = bdp;
+}
+
+/* This function is called to start or restart the FEC during a link
+ * change.  This only happens when switching between half and full
+ * duplex.
+ */
+static void
+fec_restart(struct net_device *ndev, int duplex)
+{
+	struct fec_enet_private *fep = netdev_priv(ndev);
+	const struct platform_device_id *id_entry =
+				platform_get_device_id(fep->pdev);
+	int i;
+	u32 temp_mac[2];
+	u32 rcntl = OPT_FRAME_SIZE | 0x04;
+	u32 ecntl = 0x2; /* ETHEREN */
+
+	/* Whack a reset.  We should wait for this. */
+	writel(1, fep->hwp + FEC_ECNTRL);
+	udelay(10);
+
+	/*
+	 * enet-mac reset will reset mac address registers too,
+	 * so need to reconfigure it.
+	 */
+	if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) {
+		memcpy(&temp_mac, ndev->dev_addr, ETH_ALEN);
+		writel(cpu_to_be32(temp_mac[0]), fep->hwp + FEC_ADDR_LOW);
+		writel(cpu_to_be32(temp_mac[1]), fep->hwp + FEC_ADDR_HIGH);
+	}
+
+	/* Clear any outstanding interrupt. */
+	writel(0xffc00000, fep->hwp + FEC_IEVENT);
+
+	/* Reset all multicast.	*/
+	writel(0, fep->hwp + FEC_GRP_HASH_TABLE_HIGH);
+	writel(0, fep->hwp + FEC_GRP_HASH_TABLE_LOW);
+#ifndef CONFIG_M5272
+	writel(0, fep->hwp + FEC_HASH_TABLE_HIGH);
+	writel(0, fep->hwp + FEC_HASH_TABLE_LOW);
+#endif
+
+	/* Set maximum receive buffer size. */
+	writel(PKT_MAXBLR_SIZE, fep->hwp + FEC_R_BUFF_SIZE);
+
+	fec_enet_bd_init(ndev);
+
+	/* Set receive and transmit descriptor base. */
+	writel(fep->bd_dma, fep->hwp + FEC_R_DES_START);
+	if (fep->bufdesc_ex)
+		writel((unsigned long)fep->bd_dma + sizeof(struct bufdesc_ex)
+			* RX_RING_SIZE, fep->hwp + FEC_X_DES_START);
+	else
+		writel((unsigned long)fep->bd_dma + sizeof(struct bufdesc)
+			* RX_RING_SIZE,	fep->hwp + FEC_X_DES_START);
+
+
+	for (i = 0; i <= TX_RING_MOD_MASK; i++) {
+		if (fep->tx_skbuff[i]) {
+			dev_kfree_skb_any(fep->tx_skbuff[i]);
+			fep->tx_skbuff[i] = NULL;
+		}
+	}
+
+	/* Enable MII mode */
+	if (duplex) {
+		/* FD enable */
+		writel(0x04, fep->hwp + FEC_X_CNTRL);
+	} else {
+		/* No Rcv on Xmit */
+		rcntl |= 0x02;
+		writel(0x0, fep->hwp + FEC_X_CNTRL);
+	}
+
+	fep->full_duplex = duplex;
+
+	/* Set MII speed */
+	writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED);
+
+	/*
+	 * The phy interface and speed need to get configured
+	 * differently on enet-mac.
+	 */
+	if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) {
+		/* Enable flow control and length check */
+		rcntl |= 0x40000000 | 0x00000020;
+
+		/* RGMII, RMII or MII */
+		if (fep->phy_interface == PHY_INTERFACE_MODE_RGMII)
+			rcntl |= (1 << 6);
+		else if (fep->phy_interface == PHY_INTERFACE_MODE_RMII)
+			rcntl |= (1 << 8);
+		else
+			rcntl &= ~(1 << 8);
+
+		/* 1G, 100M or 10M */
+		if (fep->phy_dev) {
+			if (fep->phy_dev->speed == SPEED_1000)
+				ecntl |= (1 << 5);
+			else if (fep->phy_dev->speed == SPEED_100)
+				rcntl &= ~(1 << 9);
+			else
+				rcntl |= (1 << 9);
+		}
+	} else {
+#ifdef FEC_MIIGSK_ENR
+		if (id_entry->driver_data & FEC_QUIRK_USE_GASKET) {
+			u32 cfgr;
+			/* disable the gasket and wait */
+			writel(0, fep->hwp + FEC_MIIGSK_ENR);
+			while (readl(fep->hwp + FEC_MIIGSK_ENR) & 4)
+				udelay(1);
+
+			/*
+			 * configure the gasket:
+			 *   RMII, 50 MHz, no loopback, no echo
+			 *   MII, 25 MHz, no loopback, no echo
+			 */
+			cfgr = (fep->phy_interface == PHY_INTERFACE_MODE_RMII)
+				? BM_MIIGSK_CFGR_RMII : BM_MIIGSK_CFGR_MII;
+			if (fep->phy_dev && fep->phy_dev->speed == SPEED_10)
+				cfgr |= BM_MIIGSK_CFGR_FRCONT_10M;
+			writel(cfgr, fep->hwp + FEC_MIIGSK_CFGR);
+
+			/* re-enable the gasket */
+			writel(2, fep->hwp + FEC_MIIGSK_ENR);
+		}
+#endif
+	}
+
+	/* enable pause frame*/
+	if ((fep->pause_flag & FEC_PAUSE_FLAG_ENABLE) ||
+	    ((fep->pause_flag & FEC_PAUSE_FLAG_AUTONEG) &&
+	     fep->phy_dev && fep->phy_dev->pause)) {
+		rcntl |= FEC_ENET_FCE;
+
+		/* set FIFO thresh hold parameter to reduce overrun */
+		writel(FEC_ENET_RSEM_V, fep->hwp + FEC_R_FIFO_RSEM);
+		writel(FEC_ENET_RSFL_V, fep->hwp + FEC_R_FIFO_RSFL);
+		writel(FEC_ENET_RAEM_V, fep->hwp + FEC_R_FIFO_RAEM);
+		writel(FEC_ENET_RAFL_V, fep->hwp + FEC_R_FIFO_RAFL);
+
+		/* OPD */
+		writel(FEC_ENET_OPD_V, fep->hwp + FEC_OPD);
+	} else {
+		rcntl &= ~FEC_ENET_FCE;
+	}
+
+	writel(rcntl, fep->hwp + FEC_R_CNTRL);
+
+	if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) {
+		/* enable ENET endian swap */
+		ecntl |= (1 << 8);
+		/* enable ENET store and forward mode */
+		writel(1 << 8, fep->hwp + FEC_X_WMRK);
+	}
+
+	if (fep->bufdesc_ex)
+		ecntl |= (1 << 4);
+
+	/* And last, enable the transmit and receive processing */
+	writel(ecntl, fep->hwp + FEC_ECNTRL);
+	writel(0, fep->hwp + FEC_R_DES_ACTIVE);
+
+	if (fep->bufdesc_ex)
+		fec_ptp_start_cyclecounter(ndev);
+
+	/* Enable interrupts we wish to service */
+	writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
+}
+
+static void
+fec_stop(struct net_device *ndev)
+{
+	struct fec_enet_private *fep = netdev_priv(ndev);
+	const struct platform_device_id *id_entry =
+				platform_get_device_id(fep->pdev);
+	u32 rmii_mode = readl(fep->hwp + FEC_R_CNTRL) & (1 << 8);
+
+	/* We cannot expect a graceful transmit stop without link !!! */
+	if (fep->link) {
+		writel(1, fep->hwp + FEC_X_CNTRL); /* Graceful transmit stop */
+		udelay(10);
+		if (!(readl(fep->hwp + FEC_IEVENT) & FEC_ENET_GRA))
+			printk("fec_stop : Graceful transmit stop did not complete !\n");
+	}
+
+	/* Whack a reset.  We should wait for this. */
+	writel(1, fep->hwp + FEC_ECNTRL);
+	udelay(10);
+	writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED);
+	writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
+
+	/* We have to keep ENET enabled to have MII interrupt stay working */
+	if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) {
+		writel(2, fep->hwp + FEC_ECNTRL);
+		writel(rmii_mode, fep->hwp + FEC_R_CNTRL);
+	}
+}
+
+
+static void
+fec_timeout(struct net_device *ndev)
+{
+	struct fec_enet_private *fep = netdev_priv(ndev);
+
+	ndev->stats.tx_errors++;
+
+	fec_restart(ndev, fep->full_duplex);
+	netif_wake_queue(ndev);
+}
+
+static void
+fec_enet_tx(struct net_device *ndev)
+{
+	struct	fec_enet_private *fep;
+	struct bufdesc *bdp;
+	unsigned short status;
+	struct	sk_buff	*skb;
+	int	index = 0;
+
+	fep = netdev_priv(ndev);
+	bdp = fep->dirty_tx;
+
+	/* get next bdp of dirty_tx */
+	if (bdp->cbd_sc & BD_ENET_TX_WRAP)
+		bdp = fep->tx_bd_base;
+	else
+		bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
+
+	while (((status = bdp->cbd_sc) & BD_ENET_TX_READY) == 0) {
+
+		/* current queue is empty */
+		if (bdp == fep->cur_tx)
+			break;
+
+		if (fep->bufdesc_ex)
+			index = (struct bufdesc_ex *)bdp -
+				(struct bufdesc_ex *)fep->tx_bd_base;
+		else
+			index = bdp - fep->tx_bd_base;
+
+		dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr,
+				FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE);
+		bdp->cbd_bufaddr = 0;
+
+		skb = fep->tx_skbuff[index];
+
+		/* Check for errors. */
+		if (status & (BD_ENET_TX_HB | BD_ENET_TX_LC |
+				   BD_ENET_TX_RL | BD_ENET_TX_UN |
+				   BD_ENET_TX_CSL)) {
+			ndev->stats.tx_errors++;
+			if (status & BD_ENET_TX_HB)  /* No heartbeat */
+				ndev->stats.tx_heartbeat_errors++;
+			if (status & BD_ENET_TX_LC)  /* Late collision */
+				ndev->stats.tx_window_errors++;
+			if (status & BD_ENET_TX_RL)  /* Retrans limit */
+				ndev->stats.tx_aborted_errors++;
+			if (status & BD_ENET_TX_UN)  /* Underrun */
+				ndev->stats.tx_fifo_errors++;
+			if (status & BD_ENET_TX_CSL) /* Carrier lost */
+				ndev->stats.tx_carrier_errors++;
+		} else {
+			ndev->stats.tx_packets++;
+		}
+
+		if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS) &&
+			fep->bufdesc_ex) {
+			struct skb_shared_hwtstamps shhwtstamps;
+			unsigned long flags;
+			struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp;
+
+			memset(&shhwtstamps, 0, sizeof(shhwtstamps));
+			spin_lock_irqsave(&fep->tmreg_lock, flags);
+			shhwtstamps.hwtstamp = ns_to_ktime(
+				timecounter_cyc2time(&fep->tc, ebdp->ts));
+			spin_unlock_irqrestore(&fep->tmreg_lock, flags);
+			skb_tstamp_tx(skb, &shhwtstamps);
+		}
+
+		if (status & BD_ENET_TX_READY)
+			printk("HEY! Enet xmit interrupt and TX_READY.\n");
+
+		/* Deferred means some collisions occurred during transmit,
+		 * but we eventually sent the packet OK.
+		 */
+		if (status & BD_ENET_TX_DEF)
+			ndev->stats.collisions++;
+
+		/* Free the sk buffer associated with this last transmit */
+		dev_kfree_skb_any(skb);
+		fep->tx_skbuff[index] = NULL;
+
+		fep->dirty_tx = bdp;
+
+		/* Update pointer to next buffer descriptor to be transmitted */
+		if (status & BD_ENET_TX_WRAP)
+			bdp = fep->tx_bd_base;
+		else
+			bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
+
+		/* Since we have freed up a buffer, the ring is no longer full
+		 */
+		if (fep->dirty_tx != fep->cur_tx) {
+			if (netif_queue_stopped(ndev))
+				netif_wake_queue(ndev);
+		}
+	}
+	return;
+}
+
+
+/* During a receive, the cur_rx points to the current incoming buffer.
+ * When we update through the ring, if the next incoming buffer has
+ * not been given to the system, we just set the empty indicator,
+ * effectively tossing the packet.
+ */
+static int
+fec_enet_rx(struct net_device *ndev, int budget)
+{
+	struct fec_enet_private *fep = netdev_priv(ndev);
+	const struct platform_device_id *id_entry =
+				platform_get_device_id(fep->pdev);
+	struct bufdesc *bdp;
+	unsigned short status;
+	struct	sk_buff	*skb;
+	ushort	pkt_len;
+	__u8 *data;
+	int	pkt_received = 0;
+
+#ifdef CONFIG_M532x
+	flush_cache_all();
+#endif
+
+	/* First, grab all of the stats for the incoming packet.
+	 * These get messed up if we get called due to a busy condition.
+	 */
+	bdp = fep->cur_rx;
+
+	while (!((status = bdp->cbd_sc) & BD_ENET_RX_EMPTY)) {
+
+		if (pkt_received >= budget)
+			break;
+		pkt_received++;
+
+		/* Since we have allocated space to hold a complete frame,
+		 * the last indicator should be set.
+		 */
+		if ((status & BD_ENET_RX_LAST) == 0)
+			printk("FEC ENET: rcv is not +last\n");
+
+		if (!fep->opened)
+			goto rx_processing_done;
+
+		/* Check for errors. */
+		if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_NO |
+			   BD_ENET_RX_CR | BD_ENET_RX_OV)) {
+			ndev->stats.rx_errors++;
+			if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH)) {
+				/* Frame too long or too short. */
+				ndev->stats.rx_length_errors++;
+			}
+			if (status & BD_ENET_RX_NO)	/* Frame alignment */
+				ndev->stats.rx_frame_errors++;
+			if (status & BD_ENET_RX_CR)	/* CRC Error */
+				ndev->stats.rx_crc_errors++;
+			if (status & BD_ENET_RX_OV)	/* FIFO overrun */
+				ndev->stats.rx_fifo_errors++;
+		}
+
+		/* Report late collisions as a frame error.
+		 * On this error, the BD is closed, but we don't know what we
+		 * have in the buffer.  So, just drop this frame on the floor.
+		 */
+		if (status & BD_ENET_RX_CL) {
+			ndev->stats.rx_errors++;
+			ndev->stats.rx_frame_errors++;
+			goto rx_processing_done;
+		}
+
+		/* Process the incoming frame. */
+		ndev->stats.rx_packets++;
+		pkt_len = bdp->cbd_datlen;
+		ndev->stats.rx_bytes += pkt_len;
+		data = (__u8*)__va(bdp->cbd_bufaddr);
+
+		dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr,
+				FEC_ENET_TX_FRSIZE, DMA_FROM_DEVICE);
+
+		if (id_entry->driver_data & FEC_QUIRK_SWAP_FRAME)
+			swap_buffer(data, pkt_len);
+
+		/* This does 16 byte alignment, exactly what we need.
+		 * The packet length includes FCS, but we don't want to
+		 * include that when passing upstream as it messes up
+		 * bridging applications.
+		 */
+		skb = netdev_alloc_skb(ndev, pkt_len - 4 + NET_IP_ALIGN);
+
+		if (unlikely(!skb)) {
+			ndev->stats.rx_dropped++;
+		} else {
+			skb_reserve(skb, NET_IP_ALIGN);
+			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);
+
+			/* Get receive timestamp from the skb */
+			if (fep->hwts_rx_en && fep->bufdesc_ex) {
+				struct skb_shared_hwtstamps *shhwtstamps =
+							    skb_hwtstamps(skb);
+				unsigned long flags;
+				struct bufdesc_ex *ebdp =
+					(struct bufdesc_ex *)bdp;
+
+				memset(shhwtstamps, 0, sizeof(*shhwtstamps));
+
+				spin_lock_irqsave(&fep->tmreg_lock, flags);
+				shhwtstamps->hwtstamp = ns_to_ktime(
+				    timecounter_cyc2time(&fep->tc, ebdp->ts));
+				spin_unlock_irqrestore(&fep->tmreg_lock, flags);
+			}
+
+			if (!skb_defer_rx_timestamp(skb))
+				napi_gro_receive(&fep->napi, skb);
+		}
+
+		bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, data,
+				FEC_ENET_TX_FRSIZE, DMA_FROM_DEVICE);
+rx_processing_done:
+		/* Clear the status flags for this buffer */
+		status &= ~BD_ENET_RX_STATS;
+
+		/* Mark the buffer empty */
+		status |= BD_ENET_RX_EMPTY;
+		bdp->cbd_sc = status;
+
+		if (fep->bufdesc_ex) {
+			struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp;
+
+			ebdp->cbd_esc = BD_ENET_RX_INT;
+			ebdp->cbd_prot = 0;
+			ebdp->cbd_bdu = 0;
+		}
+
+		/* Update BD pointer to next entry */
+		if (status & BD_ENET_RX_WRAP)
+			bdp = fep->rx_bd_base;
+		else
+			bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
+		/* Doing this here will keep the FEC running while we process
+		 * incoming frames.  On a heavily loaded network, we should be
+		 * able to keep up at the expense of system resources.
+		 */
+		writel(0, fep->hwp + FEC_R_DES_ACTIVE);
+	}
+	fep->cur_rx = bdp;
+
+	return pkt_received;
+}
+
+static irqreturn_t
+fec_enet_interrupt(int irq, void *dev_id)
+{
+	struct net_device *ndev = dev_id;
+	struct fec_enet_private *fep = netdev_priv(ndev);
+	uint int_events;
+	irqreturn_t ret = IRQ_NONE;
+
+	do {
+		int_events = readl(fep->hwp + FEC_IEVENT);
+		writel(int_events, fep->hwp + FEC_IEVENT);
+
+		if (int_events & (FEC_ENET_RXF | FEC_ENET_TXF)) {
+			ret = IRQ_HANDLED;
+
+			/* Disable the RX interrupt */
+			if (napi_schedule_prep(&fep->napi)) {
+				writel(FEC_RX_DISABLED_IMASK,
+					fep->hwp + FEC_IMASK);
+				__napi_schedule(&fep->napi);
+			}
+		}
+
+		if (int_events & FEC_ENET_MII) {
+			ret = IRQ_HANDLED;
+			complete(&fep->mdio_done);
+		}
+	} while (int_events);
+
+	return ret;
+}
+
+static int fec_enet_rx_napi(struct napi_struct *napi, int budget)
+{
+	struct net_device *ndev = napi->dev;
+	int pkts = fec_enet_rx(ndev, budget);
+	struct fec_enet_private *fep = netdev_priv(ndev);
+
+	fec_enet_tx(ndev);
+
+	if (pkts < budget) {
+		napi_complete(napi);
+		writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
+	}
+	return pkts;
+}
+
+/* ------------------------------------------------------------------------- */
+static void fec_get_mac(struct net_device *ndev)
+{
+	struct fec_enet_private *fep = netdev_priv(ndev);
+	struct fec_platform_data *pdata = fep->pdev->dev.platform_data;
+	unsigned char *iap, tmpaddr[ETH_ALEN];
+
+	/*
+	 * try to get mac address in following order:
+	 *
+	 * 1) module parameter via kernel command line in form
+	 *    fec.macaddr=0x00,0x04,0x9f,0x01,0x30,0xe0
+	 */
+	iap = macaddr;
+
+	/*
+	 * 2) from device tree data
+	 */
+	if (!is_valid_ether_addr(iap)) {
+		struct device_node *np = fep->pdev->dev.of_node;
+		if (np) {
+			const char *mac = of_get_mac_address(np);
+			if (mac)
+				iap = (unsigned char *) mac;
+		}
+	}
+
+	/*
+	 * 3) from flash or fuse (via platform data)
+	 */
+	if (!is_valid_ether_addr(iap)) {
+#ifdef CONFIG_M5272
+		if (FEC_FLASHMAC)
+			iap = (unsigned char *)FEC_FLASHMAC;
+#else
+		if (pdata)
+			iap = (unsigned char *)&pdata->mac;
+#endif
+	}
+
+	/*
+	 * 4) FEC mac registers set by bootloader
+	 */
+	if (!is_valid_ether_addr(iap)) {
+		*((unsigned long *) &tmpaddr[0]) =
+			be32_to_cpu(readl(fep->hwp + FEC_ADDR_LOW));
+		*((unsigned short *) &tmpaddr[4]) =
+			be16_to_cpu(readl(fep->hwp + FEC_ADDR_HIGH) >> 16);
+		iap = &tmpaddr[0];
+	}
+
+	memcpy(ndev->dev_addr, iap, ETH_ALEN);
+
+	/* Adjust MAC if using macaddr */
+	if (iap == macaddr)
+		 ndev->dev_addr[ETH_ALEN-1] = macaddr[ETH_ALEN-1] + fep->dev_id;
+}
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * Phy section
+ */
+static void fec_enet_adjust_link(struct net_device *ndev)
+{
+	struct fec_enet_private *fep = netdev_priv(ndev);
+	struct phy_device *phy_dev = fep->phy_dev;
+	unsigned long flags;
+
+	int status_change = 0;
+
+	spin_lock_irqsave(&fep->hw_lock, flags);
+
+	/* Prevent a state halted on mii error */
+	if (fep->mii_timeout && phy_dev->state == PHY_HALTED) {
+		phy_dev->state = PHY_RESUMING;
+		goto spin_unlock;
+	}
+
+	if (phy_dev->link) {
+		if (!fep->link) {
+			fep->link = phy_dev->link;
+			status_change = 1;
+		}
+
+		if (fep->full_duplex != phy_dev->duplex)
+			status_change = 1;
+
+		if (phy_dev->speed != fep->speed) {
+			fep->speed = phy_dev->speed;
+			status_change = 1;
+		}
+
+		/* if any of the above changed restart the FEC */
+		if (status_change)
+			fec_restart(ndev, phy_dev->duplex);
+	} else {
+		if (fep->link) {
+			fec_stop(ndev);
+			status_change = 1;
+		}
+	}
+
+spin_unlock:
+	spin_unlock_irqrestore(&fep->hw_lock, flags);
+
+	if (status_change)
+		phy_print_status(phy_dev);
+}
+
+static int fec_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
+{
+	struct fec_enet_private *fep = bus->priv;
+	unsigned long time_left;
+
+	fep->mii_timeout = 0;
+	init_completion(&fep->mdio_done);
+
+	/* start a read op */
+	writel(FEC_MMFR_ST | FEC_MMFR_OP_READ |
+		FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(regnum) |
+		FEC_MMFR_TA, fep->hwp + FEC_MII_DATA);
+
+	/* wait for end of transfer */
+	time_left = wait_for_completion_timeout(&fep->mdio_done,
+			usecs_to_jiffies(FEC_MII_TIMEOUT));
+	if (time_left == 0) {
+		fep->mii_timeout = 1;
+		printk(KERN_ERR "FEC: MDIO read timeout\n");
+		return -ETIMEDOUT;
+	}
+
+	/* return value */
+	return FEC_MMFR_DATA(readl(fep->hwp + FEC_MII_DATA));
+}
+
+static int fec_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
+			   u16 value)
+{
+	struct fec_enet_private *fep = bus->priv;
+	unsigned long time_left;
+
+	fep->mii_timeout = 0;
+	init_completion(&fep->mdio_done);
+
+	/* start a write op */
+	writel(FEC_MMFR_ST | FEC_MMFR_OP_WRITE |
+		FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(regnum) |
+		FEC_MMFR_TA | FEC_MMFR_DATA(value),
+		fep->hwp + FEC_MII_DATA);
+
+	/* wait for end of transfer */
+	time_left = wait_for_completion_timeout(&fep->mdio_done,
+			usecs_to_jiffies(FEC_MII_TIMEOUT));
+	if (time_left == 0) {
+		fep->mii_timeout = 1;
+		printk(KERN_ERR "FEC: MDIO write timeout\n");
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
+static int fec_enet_mdio_reset(struct mii_bus *bus)
+{
+	return 0;
+}
+
+static int fec_enet_mii_probe(struct net_device *ndev)
+{
+	struct fec_enet_private *fep = netdev_priv(ndev);
+	const struct platform_device_id *id_entry =
+				platform_get_device_id(fep->pdev);
+	struct phy_device *phy_dev = NULL;
+	char mdio_bus_id[MII_BUS_ID_SIZE];
+	char phy_name[MII_BUS_ID_SIZE + 3];
+	int phy_id;
+	int dev_id = fep->dev_id;
+
+	fep->phy_dev = NULL;
+
+	/* check for attached phy */
+	for (phy_id = 0; (phy_id < PHY_MAX_ADDR); phy_id++) {
+		if ((fep->mii_bus->phy_mask & (1 << phy_id)))
+			continue;
+		if (fep->mii_bus->phy_map[phy_id] == NULL)
+			continue;
+		if (fep->mii_bus->phy_map[phy_id]->phy_id == 0)
+			continue;
+		if (dev_id--)
+			continue;
+		strncpy(mdio_bus_id, fep->mii_bus->id, MII_BUS_ID_SIZE);
+		break;
+	}
+
+	if (phy_id >= PHY_MAX_ADDR) {
+		printk(KERN_INFO
+			"%s: no PHY, assuming direct connection to switch\n",
+			ndev->name);
+		strncpy(mdio_bus_id, "fixed-0", MII_BUS_ID_SIZE);
+		phy_id = 0;
+	}
+
+	snprintf(phy_name, sizeof(phy_name), PHY_ID_FMT, mdio_bus_id, phy_id);
+	phy_dev = phy_connect(ndev, phy_name, &fec_enet_adjust_link,
+			      fep->phy_interface);
+	if (IS_ERR(phy_dev)) {
+		printk(KERN_ERR "%s: could not attach to PHY\n", ndev->name);
+		return PTR_ERR(phy_dev);
+	}
+
+	/* mask with MAC supported features */
+	if (id_entry->driver_data & FEC_QUIRK_HAS_GBIT) {
+		phy_dev->supported &= PHY_GBIT_FEATURES;
+		phy_dev->supported |= SUPPORTED_Pause;
+	}
+	else
+		phy_dev->supported &= PHY_BASIC_FEATURES;
+
+	phy_dev->advertising = phy_dev->supported;
+
+	fep->phy_dev = phy_dev;
+	fep->link = 0;
+	fep->full_duplex = 0;
+
+	printk(KERN_INFO
+		"%s: Freescale FEC PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n",
+		ndev->name,
+		fep->phy_dev->drv->name, dev_name(&fep->phy_dev->dev),
+		fep->phy_dev->irq);
+
+	return 0;
+}
+
+static int fec_enet_mii_init(struct platform_device *pdev)
+{
+	static struct mii_bus *fec0_mii_bus;
+	struct net_device *ndev = platform_get_drvdata(pdev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
+	const struct platform_device_id *id_entry =
+				platform_get_device_id(fep->pdev);
+	int err = -ENXIO, i;
+
+	/*
+	 * The dual fec interfaces are not equivalent with enet-mac.
+	 * Here are the differences:
+	 *
+	 *  - fec0 supports MII & RMII modes while fec1 only supports RMII
+	 *  - fec0 acts as the 1588 time master while fec1 is slave
+	 *  - external phys can only be configured by fec0
+	 *
+	 * That is to say fec1 can not work independently. It only works
+	 * when fec0 is working. The reason behind this design is that the
+	 * second interface is added primarily for Switch mode.
+	 *
+	 * Because of the last point above, both phys are attached on fec0
+	 * mdio interface in board design, and need to be configured by
+	 * fec0 mii_bus.
+	 */
+	if ((id_entry->driver_data & FEC_QUIRK_ENET_MAC) && fep->dev_id > 0) {
+		/* fec1 uses fec0 mii_bus */
+		if (mii_cnt && fec0_mii_bus) {
+			fep->mii_bus = fec0_mii_bus;
+			mii_cnt++;
+			return 0;
+		}
+		return -ENOENT;
+	}
+
+	fep->mii_timeout = 0;
+
+	/*
+	 * Set MII speed to 2.5 MHz (= clk_get_rate() / 2 * phy_speed)
+	 *
+	 * The formula for FEC MDC is 'ref_freq / (MII_SPEED x 2)' while
+	 * for ENET-MAC is 'ref_freq / ((MII_SPEED + 1) x 2)'.  The i.MX28
+	 * Reference Manual has an error on this, and gets fixed on i.MX6Q
+	 * document.
+	 */
+	fep->phy_speed = DIV_ROUND_UP(clk_get_rate(fep->clk_ahb), 5000000);
+	if (id_entry->driver_data & FEC_QUIRK_ENET_MAC)
+		fep->phy_speed--;
+	fep->phy_speed <<= 1;
+	writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED);
+
+	fep->mii_bus = mdiobus_alloc();
+	if (fep->mii_bus == NULL) {
+		err = -ENOMEM;
+		goto err_out;
+	}
+
+	fep->mii_bus->name = "fec_enet_mii_bus";
+	fep->mii_bus->read = fec_enet_mdio_read;
+	fep->mii_bus->write = fec_enet_mdio_write;
+	fep->mii_bus->reset = fec_enet_mdio_reset;
+	snprintf(fep->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",
+		pdev->name, fep->dev_id + 1);
+	fep->mii_bus->priv = fep;
+	fep->mii_bus->parent = &pdev->dev;
+
+	fep->mii_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
+	if (!fep->mii_bus->irq) {
+		err = -ENOMEM;
+		goto err_out_free_mdiobus;
+	}
+
+	for (i = 0; i < PHY_MAX_ADDR; i++)
+		fep->mii_bus->irq[i] = PHY_POLL;
+
+	if (mdiobus_register(fep->mii_bus))
+		goto err_out_free_mdio_irq;
+
+	mii_cnt++;
+
+	/* save fec0 mii_bus */
+	if (id_entry->driver_data & FEC_QUIRK_ENET_MAC)
+		fec0_mii_bus = fep->mii_bus;
+
+	return 0;
+
+err_out_free_mdio_irq:
+	kfree(fep->mii_bus->irq);
+err_out_free_mdiobus:
+	mdiobus_free(fep->mii_bus);
+err_out:
+	return err;
+}
+
+static void fec_enet_mii_remove(struct fec_enet_private *fep)
+{
+	if (--mii_cnt == 0) {
+		mdiobus_unregister(fep->mii_bus);
+		kfree(fep->mii_bus->irq);
+		mdiobus_free(fep->mii_bus);
+	}
+}
+
+static int fec_enet_get_settings(struct net_device *ndev,
+				  struct ethtool_cmd *cmd)
+{
+	struct fec_enet_private *fep = netdev_priv(ndev);
+	struct phy_device *phydev = fep->phy_dev;
+
+	if (!phydev)
+		return -ENODEV;
+
+	return phy_ethtool_gset(phydev, cmd);
+}
+
+static int fec_enet_set_settings(struct net_device *ndev,
+				 struct ethtool_cmd *cmd)
+{
+	struct fec_enet_private *fep = netdev_priv(ndev);
+	struct phy_device *phydev = fep->phy_dev;
+
+	if (!phydev)
+		return -ENODEV;
+
+	return phy_ethtool_sset(phydev, cmd);
+}
+
+static void fec_enet_get_drvinfo(struct net_device *ndev,
+				 struct ethtool_drvinfo *info)
+{
+	struct fec_enet_private *fep = netdev_priv(ndev);
+
+	strlcpy(info->driver, fep->pdev->dev.driver->name,
+		sizeof(info->driver));
+	strlcpy(info->version, "Revision: 1.0", sizeof(info->version));
+	strlcpy(info->bus_info, dev_name(&ndev->dev), sizeof(info->bus_info));
+}
+
+static int fec_enet_get_ts_info(struct net_device *ndev,
+				struct ethtool_ts_info *info)
+{
+	struct fec_enet_private *fep = netdev_priv(ndev);
+
+	if (fep->bufdesc_ex) {
+
+		info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE |
+					SOF_TIMESTAMPING_RX_SOFTWARE |
+					SOF_TIMESTAMPING_SOFTWARE |
+					SOF_TIMESTAMPING_TX_HARDWARE |
+					SOF_TIMESTAMPING_RX_HARDWARE |
+					SOF_TIMESTAMPING_RAW_HARDWARE;
+		if (fep->ptp_clock)
+			info->phc_index = ptp_clock_index(fep->ptp_clock);
+		else
+			info->phc_index = -1;
+
+		info->tx_types = (1 << HWTSTAMP_TX_OFF) |
+				 (1 << HWTSTAMP_TX_ON);
+
+		info->rx_filters = (1 << HWTSTAMP_FILTER_NONE) |
+				   (1 << HWTSTAMP_FILTER_ALL);
+		return 0;
+	} else {
+		return ethtool_op_get_ts_info(ndev, info);
+	}
+}
+
+static void fec_enet_get_pauseparam(struct net_device *ndev,
+				    struct ethtool_pauseparam *pause)
+{
+	struct fec_enet_private *fep = netdev_priv(ndev);
+
+	pause->autoneg = (fep->pause_flag & FEC_PAUSE_FLAG_AUTONEG) != 0;
+	pause->tx_pause = (fep->pause_flag & FEC_PAUSE_FLAG_ENABLE) != 0;
+	pause->rx_pause = pause->tx_pause;
+}
+
+static int fec_enet_set_pauseparam(struct net_device *ndev,
+				   struct ethtool_pauseparam *pause)
+{
+	struct fec_enet_private *fep = netdev_priv(ndev);
+
+	if (pause->tx_pause != pause->rx_pause) {
+		netdev_info(ndev,
+			"hardware only support enable/disable both tx and rx");
+		return -EINVAL;
+	}
+
+	fep->pause_flag = 0;
+
+	/* tx pause must be same as rx pause */
+	fep->pause_flag |= pause->rx_pause ? FEC_PAUSE_FLAG_ENABLE : 0;
+	fep->pause_flag |= pause->autoneg ? FEC_PAUSE_FLAG_AUTONEG : 0;
+
+	if (pause->rx_pause || pause->autoneg) {
+		fep->phy_dev->supported |= ADVERTISED_Pause;
+		fep->phy_dev->advertising |= ADVERTISED_Pause;
+	} else {
+		fep->phy_dev->supported &= ~ADVERTISED_Pause;
+		fep->phy_dev->advertising &= ~ADVERTISED_Pause;
+	}
+
+	if (pause->autoneg) {
+		if (netif_running(ndev))
+			fec_stop(ndev);
+		phy_start_aneg(fep->phy_dev);
+	}
+	if (netif_running(ndev))
+		fec_restart(ndev, 0);
+
+	return 0;
+}
+
+static const struct ethtool_ops fec_enet_ethtool_ops = {
+	.get_pauseparam		= fec_enet_get_pauseparam,
+	.set_pauseparam		= fec_enet_set_pauseparam,
+	.get_settings		= fec_enet_get_settings,
+	.set_settings		= fec_enet_set_settings,
+	.get_drvinfo		= fec_enet_get_drvinfo,
+	.get_link		= ethtool_op_get_link,
+	.get_ts_info		= fec_enet_get_ts_info,
+};
+
+static int fec_enet_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
+{
+	struct fec_enet_private *fep = netdev_priv(ndev);
+	struct phy_device *phydev = fep->phy_dev;
+
+	if (!netif_running(ndev))
+		return -EINVAL;
+
+	if (!phydev)
+		return -ENODEV;
+
+	if (cmd == SIOCSHWTSTAMP && fep->bufdesc_ex)
+		return fec_ptp_ioctl(ndev, rq, cmd);
+
+	return phy_mii_ioctl(phydev, rq, cmd);
+}
+
+static void fec_enet_free_buffers(struct net_device *ndev)
+{
+	struct fec_enet_private *fep = netdev_priv(ndev);
+	unsigned int i;
+	struct sk_buff *skb;
+	struct bufdesc	*bdp;
+
+	bdp = fep->rx_bd_base;
+	for (i = 0; i < RX_RING_SIZE; i++) {
+		skb = fep->rx_skbuff[i];
+
+		if (bdp->cbd_bufaddr)
+			dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr,
+					FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE);
+		if (skb)
+			dev_kfree_skb(skb);
+		bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
+	}
+
+	bdp = fep->tx_bd_base;
+	for (i = 0; i < TX_RING_SIZE; i++)
+		kfree(fep->tx_bounce[i]);
+}
+
+static int fec_enet_alloc_buffers(struct net_device *ndev)
+{
+	struct fec_enet_private *fep = netdev_priv(ndev);
+	unsigned int i;
+	struct sk_buff *skb;
+	struct bufdesc	*bdp;
+
+	bdp = fep->rx_bd_base;
+	for (i = 0; i < RX_RING_SIZE; i++) {
+		skb = netdev_alloc_skb(ndev, FEC_ENET_RX_FRSIZE);
+		if (!skb) {
+			fec_enet_free_buffers(ndev);
+			return -ENOMEM;
+		}
+		fep->rx_skbuff[i] = skb;
+
+		bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, skb->data,
+				FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE);
+		bdp->cbd_sc = BD_ENET_RX_EMPTY;
+
+		if (fep->bufdesc_ex) {
+			struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp;
+			ebdp->cbd_esc = BD_ENET_RX_INT;
+		}
+
+		bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
+	}
+
+	/* Set the last buffer to wrap. */
+	bdp = fec_enet_get_prevdesc(bdp, fep->bufdesc_ex);
+	bdp->cbd_sc |= BD_SC_WRAP;
+
+	bdp = fep->tx_bd_base;
+	for (i = 0; i < TX_RING_SIZE; i++) {
+		fep->tx_bounce[i] = kmalloc(FEC_ENET_TX_FRSIZE, GFP_KERNEL);
+
+		bdp->cbd_sc = 0;
+		bdp->cbd_bufaddr = 0;
+
+		if (fep->bufdesc_ex) {
+			struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp;
+			ebdp->cbd_esc = BD_ENET_TX_INT;
+		}
+
+		bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
+	}
+
+	/* Set the last buffer to wrap. */
+	bdp = fec_enet_get_prevdesc(bdp, fep->bufdesc_ex);
+	bdp->cbd_sc |= BD_SC_WRAP;
+
+	return 0;
+}
+
+static int
+fec_enet_open(struct net_device *ndev)
+{
+	struct fec_enet_private *fep = netdev_priv(ndev);
+	int ret;
+
+	napi_enable(&fep->napi);
+
+	/* I should reset the ring buffers here, but I don't yet know
+	 * a simple way to do that.
+	 */
+
+	ret = fec_enet_alloc_buffers(ndev);
+	if (ret)
+		return ret;
+
+	/* Probe and connect to PHY when open the interface */
+	ret = fec_enet_mii_probe(ndev);
+	if (ret) {
+		fec_enet_free_buffers(ndev);
+		return ret;
+	}
+	phy_start(fep->phy_dev);
+	netif_start_queue(ndev);
+	fep->opened = 1;
+	return 0;
+}
+
+static int
+fec_enet_close(struct net_device *ndev)
+{
+	struct fec_enet_private *fep = netdev_priv(ndev);
+
+	/* Don't know what to do yet. */
+	napi_disable(&fep->napi);
+	fep->opened = 0;
+	netif_stop_queue(ndev);
+	fec_stop(ndev);
+
+	if (fep->phy_dev) {
+		phy_stop(fep->phy_dev);
+		phy_disconnect(fep->phy_dev);
+	}
+
+	fec_enet_free_buffers(ndev);
+
+	return 0;
+}
+
+/* Set or clear the multicast filter for this adaptor.
+ * Skeleton taken from sunlance driver.
+ * The CPM Ethernet implementation allows Multicast as well as individual
+ * MAC address filtering.  Some of the drivers check to make sure it is
+ * a group multicast address, and discard those that are not.  I guess I
+ * will do the same for now, but just remove the test if you want
+ * individual filtering as well (do the upper net layers want or support
+ * this kind of feature?).
+ */
+
+#define HASH_BITS	6		/* #bits in hash */
+#define CRC32_POLY	0xEDB88320
+
+static void set_multicast_list(struct net_device *ndev)
+{
+	struct fec_enet_private *fep = netdev_priv(ndev);
+	struct netdev_hw_addr *ha;
+	unsigned int i, bit, data, crc, tmp;
+	unsigned char hash;
+
+	if (ndev->flags & IFF_PROMISC) {
+		tmp = readl(fep->hwp + FEC_R_CNTRL);
+		tmp |= 0x8;
+		writel(tmp, fep->hwp + FEC_R_CNTRL);
+		return;
+	}
+
+	tmp = readl(fep->hwp + FEC_R_CNTRL);
+	tmp &= ~0x8;
+	writel(tmp, fep->hwp + FEC_R_CNTRL);
+
+	if (ndev->flags & IFF_ALLMULTI) {
+		/* Catch all multicast addresses, so set the
+		 * filter to all 1's
+		 */
+		writel(0xffffffff, fep->hwp + FEC_GRP_HASH_TABLE_HIGH);
+		writel(0xffffffff, fep->hwp + FEC_GRP_HASH_TABLE_LOW);
+
+		return;
+	}
+
+	/* Clear filter and add the addresses in hash register
+	 */
+	writel(0, fep->hwp + FEC_GRP_HASH_TABLE_HIGH);
+	writel(0, fep->hwp + FEC_GRP_HASH_TABLE_LOW);
+
+	netdev_for_each_mc_addr(ha, ndev) {
+		/* calculate crc32 value of mac address */
+		crc = 0xffffffff;
+
+		for (i = 0; i < ndev->addr_len; i++) {
+			data = ha->addr[i];
+			for (bit = 0; bit < 8; bit++, data >>= 1) {
+				crc = (crc >> 1) ^
+				(((crc ^ data) & 1) ? CRC32_POLY : 0);
+			}
+		}
+
+		/* only upper 6 bits (HASH_BITS) are used
+		 * which point to specific bit in he hash registers
+		 */
+		hash = (crc >> (32 - HASH_BITS)) & 0x3f;
+
+		if (hash > 31) {
+			tmp = readl(fep->hwp + FEC_GRP_HASH_TABLE_HIGH);
+			tmp |= 1 << (hash - 32);
+			writel(tmp, fep->hwp + FEC_GRP_HASH_TABLE_HIGH);
+		} else {
+			tmp = readl(fep->hwp + FEC_GRP_HASH_TABLE_LOW);
+			tmp |= 1 << hash;
+			writel(tmp, fep->hwp + FEC_GRP_HASH_TABLE_LOW);
+		}
+	}
+}
+
+/* Set a MAC change in hardware. */
+static int
+fec_set_mac_address(struct net_device *ndev, void *p)
+{
+	struct fec_enet_private *fep = netdev_priv(ndev);
+	struct sockaddr *addr = p;
+
+	if (!is_valid_ether_addr(addr->sa_data))
+		return -EADDRNOTAVAIL;
+
+	memcpy(ndev->dev_addr, addr->sa_data, ndev->addr_len);
+
+	writel(ndev->dev_addr[3] | (ndev->dev_addr[2] << 8) |
+		(ndev->dev_addr[1] << 16) | (ndev->dev_addr[0] << 24),
+		fep->hwp + FEC_ADDR_LOW);
+	writel((ndev->dev_addr[5] << 16) | (ndev->dev_addr[4] << 24),
+		fep->hwp + FEC_ADDR_HIGH);
+	return 0;
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/**
+ * fec_poll_controller - FEC Poll controller function
+ * @dev: The FEC network adapter
+ *
+ * Polled functionality used by netconsole and others in non interrupt mode
+ *
+ */
+static void fec_poll_controller(struct net_device *dev)
+{
+	int i;
+	struct fec_enet_private *fep = netdev_priv(dev);
+
+	for (i = 0; i < FEC_IRQ_NUM; i++) {
+		if (fep->irq[i] > 0) {
+			disable_irq(fep->irq[i]);
+			fec_enet_interrupt(fep->irq[i], dev);
+			enable_irq(fep->irq[i]);
+		}
+	}
+}
+#endif
+
+static const struct net_device_ops fec_netdev_ops = {
+	.ndo_open		= fec_enet_open,
+	.ndo_stop		= fec_enet_close,
+	.ndo_start_xmit		= fec_enet_start_xmit,
+	.ndo_set_rx_mode	= set_multicast_list,
+	.ndo_change_mtu		= eth_change_mtu,
+	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_tx_timeout		= fec_timeout,
+	.ndo_set_mac_address	= fec_set_mac_address,
+	.ndo_do_ioctl		= fec_enet_ioctl,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	.ndo_poll_controller	= fec_poll_controller,
+#endif
+};
+
+ /*
+  * XXX:  We need to clean up on failure exits here.
+  *
+  */
+static int fec_enet_init(struct net_device *ndev)
+{
+	struct fec_enet_private *fep = netdev_priv(ndev);
+	struct bufdesc *cbd_base;
+
+	/* Allocate memory for buffer descriptors. */
+	cbd_base = dma_alloc_coherent(NULL, PAGE_SIZE, &fep->bd_dma,
+				      GFP_KERNEL);
+	if (!cbd_base)
+		return -ENOMEM;
+
+	memset(cbd_base, 0, PAGE_SIZE);
+	spin_lock_init(&fep->hw_lock);
+
+	fep->netdev = ndev;
+
+	/* Get the Ethernet address */
+	fec_get_mac(ndev);
+
+	/* Set receive and transmit descriptor base. */
+	fep->rx_bd_base = cbd_base;
+	if (fep->bufdesc_ex)
+		fep->tx_bd_base = (struct bufdesc *)
+			(((struct bufdesc_ex *)cbd_base) + RX_RING_SIZE);
+	else
+		fep->tx_bd_base = cbd_base + RX_RING_SIZE;
+
+	/* The FEC Ethernet specific entries in the device structure */
+	ndev->watchdog_timeo = TX_TIMEOUT;
+	ndev->netdev_ops = &fec_netdev_ops;
+	ndev->ethtool_ops = &fec_enet_ethtool_ops;
+
+	writel(FEC_RX_DISABLED_IMASK, fep->hwp + FEC_IMASK);
+	netif_napi_add(ndev, &fep->napi, fec_enet_rx_napi, FEC_NAPI_WEIGHT);
+
+	fec_restart(ndev, 0);
+
+	return 0;
+}
+
+#ifdef CONFIG_OF
+static void fec_reset_phy(struct platform_device *pdev)
+{
+	int err, phy_reset;
+	int msec = 1;
+	struct device_node *np = pdev->dev.of_node;
+
+	if (!np)
+		return;
+
+	of_property_read_u32(np, "phy-reset-duration", &msec);
+	/* A sane reset duration should not be longer than 1s */
+	if (msec > 1000)
+		msec = 1;
+
+	phy_reset = of_get_named_gpio(np, "phy-reset-gpios", 0);
+	if (!gpio_is_valid(phy_reset))
+		return;
+
+	err = devm_gpio_request_one(&pdev->dev, phy_reset,
+				    GPIOF_OUT_INIT_LOW, "phy-reset");
+	if (err) {
+		dev_err(&pdev->dev, "failed to get phy-reset-gpios: %d\n", err);
+		return;
+	}
+	msleep(msec);
+	gpio_set_value(phy_reset, 1);
+}
+#else /* CONFIG_OF */
+static void fec_reset_phy(struct platform_device *pdev)
+{
+	/*
+	 * In case of platform probe, the reset has been done
+	 * by machine code.
+	 */
+}
+#endif /* CONFIG_OF */
+
+static int
+fec_probe(struct platform_device *pdev)
+{
+	struct fec_enet_private *fep;
+	struct fec_platform_data *pdata;
+	struct net_device *ndev;
+	int i, irq, ret = 0;
+	struct resource *r;
+	const struct of_device_id *of_id;
+	static int dev_id;
+	struct pinctrl *pinctrl;
+	struct regulator *reg_phy;
+
+	of_id = of_match_device(fec_dt_ids, &pdev->dev);
+	if (of_id)
+		pdev->id_entry = of_id->data;
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!r)
+		return -ENXIO;
+
+	/* Init network device */
+	ndev = alloc_etherdev(sizeof(struct fec_enet_private));
+	if (!ndev)
+		return -ENOMEM;
+
+	SET_NETDEV_DEV(ndev, &pdev->dev);
+
+	/* setup board info structure */
+	fep = netdev_priv(ndev);
+
+	/* default enable pause frame auto negotiation */
+	if (pdev->id_entry &&
+	    (pdev->id_entry->driver_data & FEC_QUIRK_HAS_GBIT))
+		fep->pause_flag |= FEC_PAUSE_FLAG_AUTONEG;
+
+	fep->hwp = devm_request_and_ioremap(&pdev->dev, r);
+	fep->pdev = pdev;
+	fep->dev_id = dev_id++;
+
+	fep->bufdesc_ex = 0;
+
+	if (!fep->hwp) {
+		ret = -ENOMEM;
+		goto failed_ioremap;
+	}
+
+	platform_set_drvdata(pdev, ndev);
+
+	ret = of_get_phy_mode(pdev->dev.of_node);
+	if (ret < 0) {
+		pdata = pdev->dev.platform_data;
+		if (pdata)
+			fep->phy_interface = pdata->phy;
+		else
+			fep->phy_interface = PHY_INTERFACE_MODE_MII;
+	} else {
+		fep->phy_interface = ret;
+	}
+
+	pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+	if (IS_ERR(pinctrl)) {
+		ret = PTR_ERR(pinctrl);
+		goto failed_pin;
+	}
+
+	fep->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
+	if (IS_ERR(fep->clk_ipg)) {
+		ret = PTR_ERR(fep->clk_ipg);
+		goto failed_clk;
+	}
+
+	fep->clk_ahb = devm_clk_get(&pdev->dev, "ahb");
+	if (IS_ERR(fep->clk_ahb)) {
+		ret = PTR_ERR(fep->clk_ahb);
+		goto failed_clk;
+	}
+
+	/* enet_out is optional, depends on board */
+	fep->clk_enet_out = devm_clk_get(&pdev->dev, "enet_out");
+	if (IS_ERR(fep->clk_enet_out))
+		fep->clk_enet_out = NULL;
+
+	fep->clk_ptp = devm_clk_get(&pdev->dev, "ptp");
+	fep->bufdesc_ex =
+		pdev->id_entry->driver_data & FEC_QUIRK_HAS_BUFDESC_EX;
+	if (IS_ERR(fep->clk_ptp)) {
+		fep->clk_ptp = NULL;
+		fep->bufdesc_ex = 0;
+	}
+
+	clk_prepare_enable(fep->clk_ahb);
+	clk_prepare_enable(fep->clk_ipg);
+	clk_prepare_enable(fep->clk_enet_out);
+	clk_prepare_enable(fep->clk_ptp);
+
+	reg_phy = devm_regulator_get(&pdev->dev, "phy");
+	if (!IS_ERR(reg_phy)) {
+		ret = regulator_enable(reg_phy);
+		if (ret) {
+			dev_err(&pdev->dev,
+				"Failed to enable phy regulator: %d\n", ret);
+			goto failed_regulator;
+		}
+	}
+
+	fec_reset_phy(pdev);
+
+	if (fep->bufdesc_ex)
+		fec_ptp_init(ndev, pdev);
+
+	ret = fec_enet_init(ndev);
+	if (ret)
+		goto failed_init;
+
+	for (i = 0; i < FEC_IRQ_NUM; i++) {
+		irq = platform_get_irq(pdev, i);
+		if (irq < 0) {
+			if (i)
+				break;
+			ret = irq;
+			goto failed_irq;
+		}
+		ret = request_irq(irq, fec_enet_interrupt, IRQF_DISABLED, pdev->name, ndev);
+		if (ret) {
+			while (--i >= 0) {
+				irq = platform_get_irq(pdev, i);
+				free_irq(irq, ndev);
+			}
+			goto failed_irq;
+		}
+	}
+
+	ret = fec_enet_mii_init(pdev);
+	if (ret)
+		goto failed_mii_init;
+
+	/* Carrier starts down, phylib will bring it up */
+	netif_carrier_off(ndev);
+
+	ret = register_netdev(ndev);
+	if (ret)
+		goto failed_register;
+
+	return 0;
+
+failed_register:
+	fec_enet_mii_remove(fep);
+failed_mii_init:
+failed_init:
+	for (i = 0; i < FEC_IRQ_NUM; i++) {
+		irq = platform_get_irq(pdev, i);
+		if (irq > 0)
+			free_irq(irq, ndev);
+	}
+failed_irq:
+failed_regulator:
+	clk_disable_unprepare(fep->clk_ahb);
+	clk_disable_unprepare(fep->clk_ipg);
+	clk_disable_unprepare(fep->clk_enet_out);
+	clk_disable_unprepare(fep->clk_ptp);
+failed_pin:
+failed_clk:
+failed_ioremap:
+	free_netdev(ndev);
+
+	return ret;
+}
+
+static int
+fec_drv_remove(struct platform_device *pdev)
+{
+	struct net_device *ndev = platform_get_drvdata(pdev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
+	int i;
+
+	unregister_netdev(ndev);
+	fec_enet_mii_remove(fep);
+	del_timer_sync(&fep->time_keep);
+	clk_disable_unprepare(fep->clk_ptp);
+	if (fep->ptp_clock)
+		ptp_clock_unregister(fep->ptp_clock);
+	clk_disable_unprepare(fep->clk_enet_out);
+	clk_disable_unprepare(fep->clk_ahb);
+	clk_disable_unprepare(fep->clk_ipg);
+	for (i = 0; i < FEC_IRQ_NUM; i++) {
+		int irq = platform_get_irq(pdev, i);
+		if (irq > 0)
+			free_irq(irq, ndev);
+	}
+	free_netdev(ndev);
+
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int
+fec_suspend(struct device *dev)
+{
+	struct net_device *ndev = dev_get_drvdata(dev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
+
+	if (netif_running(ndev)) {
+		fec_stop(ndev);
+		netif_device_detach(ndev);
+	}
+	clk_disable_unprepare(fep->clk_enet_out);
+	clk_disable_unprepare(fep->clk_ahb);
+	clk_disable_unprepare(fep->clk_ipg);
+
+	return 0;
+}
+
+static int
+fec_resume(struct device *dev)
+{
+	struct net_device *ndev = dev_get_drvdata(dev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
+
+	clk_prepare_enable(fep->clk_enet_out);
+	clk_prepare_enable(fep->clk_ahb);
+	clk_prepare_enable(fep->clk_ipg);
+	if (netif_running(ndev)) {
+		fec_restart(ndev, fep->full_duplex);
+		netif_device_attach(ndev);
+	}
+
+	return 0;
+}
+
+static const struct dev_pm_ops fec_pm_ops = {
+	.suspend	= fec_suspend,
+	.resume		= fec_resume,
+	.freeze		= fec_suspend,
+	.thaw		= fec_resume,
+	.poweroff	= fec_suspend,
+	.restore	= fec_resume,
+};
+#endif
+
+static struct platform_driver fec_driver = {
+	.driver	= {
+		.name	= DRIVER_NAME,
+		.owner	= THIS_MODULE,
+#ifdef CONFIG_PM
+		.pm	= &fec_pm_ops,
+#endif
+		.of_match_table = fec_dt_ids,
+	},
+	.id_table = fec_devtype,
+	.probe	= fec_probe,
+	.remove	= fec_drv_remove,
+};
+
+module_platform_driver(fec_driver);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c
index 0d8df40..1f17ca0 100644
--- a/drivers/net/ethernet/freescale/fec_ptp.c
+++ b/drivers/net/ethernet/freescale/fec_ptp.c
@@ -128,7 +128,6 @@ void fec_ptp_start_cyclecounter(struct net_device *ndev)
 
 	spin_unlock_irqrestore(&fep->tmreg_lock, flags);
 }
-EXPORT_SYMBOL(fec_ptp_start_cyclecounter);
 
 /**
  * fec_ptp_adjfreq - adjust ptp cycle frequency
@@ -319,7 +318,6 @@ int fec_ptp_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd)
 	return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ?
 	    -EFAULT : 0;
 }
-EXPORT_SYMBOL(fec_ptp_ioctl);
 
 /**
  * fec_time_keep - call timecounter_read every second to avoid timer overrun
@@ -385,4 +383,3 @@ void fec_ptp_init(struct net_device *ndev, struct platform_device *pdev)
 		pr_info("registered PHC device on %s\n", ndev->name);
 	}
 }
-EXPORT_SYMBOL(fec_ptp_init);
diff --git a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
index 46df288..edc1200 100644
--- a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
+++ b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
@@ -177,8 +177,6 @@ static int fs_enet_rx_napi(struct napi_struct *napi, int budget)
 				received++;
 				netif_receive_skb(skb);
 			} else {
-				dev_warn(fep->dev,
-					 "Memory squeeze, dropping packet.\n");
 				fep->stats.rx_dropped++;
 				skbn = skb;
 			}
@@ -309,8 +307,6 @@ static int fs_enet_rx_non_napi(struct net_device *dev)
 				received++;
 				netif_rx(skb);
 			} else {
-				dev_warn(fep->dev,
-					 "Memory squeeze, dropping packet.\n");
 				fep->stats.rx_dropped++;
 				skbn = skb;
 			}
@@ -505,11 +501,9 @@ void fs_init_bds(struct net_device *dev)
 	 */
 	for (i = 0, bdp = fep->rx_bd_base; i < fep->rx_ring; i++, bdp++) {
 		skb = netdev_alloc_skb(dev, ENET_RX_FRSIZE);
-		if (skb == NULL) {
-			dev_warn(fep->dev,
-				 "Memory squeeze, unable to allocate skb\n");
+		if (skb == NULL)
 			break;
-		}
+
 		skb_align(skb, ENET_RX_ALIGN);
 		fep->rx_skbuff[i] = skb;
 		CBDW_BUFADDR(bdp,
@@ -593,13 +587,8 @@ static struct sk_buff *tx_skb_align_workaround(struct net_device *dev,
 
 	/* Alloc new skb */
 	new_skb = netdev_alloc_skb(dev, skb->len + 4);
-	if (!new_skb) {
-		if (net_ratelimit()) {
-			dev_warn(fep->dev,
-				 "Memory squeeze, dropping tx packet.\n");
-		}
+	if (!new_skb)
 		return NULL;
-	}
 
 	/* Make sure new skb is properly aligned */
 	skb_align(new_skb, 4);
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index d2c5441..96fbe35 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -132,7 +132,7 @@ static int gfar_poll(struct napi_struct *napi, int budget);
 static void gfar_netpoll(struct net_device *dev);
 #endif
 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 void gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue);
 static void gfar_process_frame(struct net_device *dev, struct sk_buff *skb,
 			       int amount_pull, struct napi_struct *napi);
 void gfar_halt(struct net_device *dev);
@@ -245,14 +245,13 @@ static int gfar_alloc_skb_resources(struct net_device *ndev)
 
 	/* Allocate memory for the buffer descriptors */
 	vaddr = dma_alloc_coherent(dev,
-			sizeof(struct txbd8) * priv->total_tx_ring_size +
-			sizeof(struct rxbd8) * priv->total_rx_ring_size,
-			&addr, GFP_KERNEL);
-	if (!vaddr) {
-		netif_err(priv, ifup, ndev,
-			  "Could not allocate buffer descriptors!\n");
+				   (priv->total_tx_ring_size *
+				    sizeof(struct txbd8)) +
+				   (priv->total_rx_ring_size *
+				    sizeof(struct rxbd8)),
+				   &addr, GFP_KERNEL);
+	if (!vaddr)
 		return -ENOMEM;
-	}
 
 	for (i = 0; i < priv->num_tx_queues; i++) {
 		tx_queue = priv->tx_queue[i];
@@ -342,7 +341,7 @@ static void gfar_init_mac(struct net_device *ndev)
 	gfar_init_tx_rx_base(priv);
 
 	/* Configure the coalescing support */
-	gfar_configure_coalescing(priv, 0xFF, 0xFF);
+	gfar_configure_coalescing_all(priv);
 
 	/* set this when rx hw offload (TOE) functions are being used */
 	priv->uses_rxfcb = 0;
@@ -691,7 +690,7 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev)
 	}
 
 	for (i = 0; i < priv->num_tx_queues; i++)
-	       priv->tx_queue[i] = NULL;
+		priv->tx_queue[i] = NULL;
 	for (i = 0; i < priv->num_rx_queues; i++)
 		priv->rx_queue[i] = NULL;
 
@@ -1817,25 +1816,15 @@ void gfar_start(struct net_device *dev)
 	dev->trans_start = jiffies; /* prevent tx timeout */
 }
 
-void gfar_configure_coalescing(struct gfar_private *priv,
+static void gfar_configure_coalescing(struct gfar_private *priv,
 			       unsigned long tx_mask, unsigned long rx_mask)
 {
 	struct gfar __iomem *regs = priv->gfargrp[0].regs;
 	u32 __iomem *baddr;
-	int i = 0;
-
-	/* Backward compatible case ---- even if we enable
-	 * multiple queues, there's only single reg to program
-	 */
-	gfar_write(&regs->txic, 0);
-	if (likely(priv->tx_queue[0]->txcoalescing))
-		gfar_write(&regs->txic, priv->tx_queue[0]->txic);
-
-	gfar_write(&regs->rxic, 0);
-	if (unlikely(priv->rx_queue[0]->rxcoalescing))
-		gfar_write(&regs->rxic, priv->rx_queue[0]->rxic);
 
 	if (priv->mode == MQ_MG_MODE) {
+		int i = 0;
+
 		baddr = &regs->txic0;
 		for_each_set_bit(i, &tx_mask, priv->num_tx_queues) {
 			gfar_write(baddr + i, 0);
@@ -1849,9 +1838,25 @@ void gfar_configure_coalescing(struct gfar_private *priv,
 			if (likely(priv->rx_queue[i]->rxcoalescing))
 				gfar_write(baddr + i, priv->rx_queue[i]->rxic);
 		}
+	} else {
+		/* Backward compatible case -- even if we enable
+		 * multiple queues, there's only single reg to program
+		 */
+		gfar_write(&regs->txic, 0);
+		if (likely(priv->tx_queue[0]->txcoalescing))
+			gfar_write(&regs->txic, priv->tx_queue[0]->txic);
+
+		gfar_write(&regs->rxic, 0);
+		if (unlikely(priv->rx_queue[0]->rxcoalescing))
+			gfar_write(&regs->rxic, priv->rx_queue[0]->rxic);
 	}
 }
 
+void gfar_configure_coalescing_all(struct gfar_private *priv)
+{
+	gfar_configure_coalescing(priv, 0xFF, 0xFF);
+}
+
 static int register_grp_irqs(struct gfar_priv_grp *grp)
 {
 	struct gfar_private *priv = grp->priv;
@@ -1941,7 +1946,7 @@ int startup_gfar(struct net_device *ndev)
 
 	phy_start(priv->phydev);
 
-	gfar_configure_coalescing(priv, 0xFF, 0xFF);
+	gfar_configure_coalescing_all(priv);
 
 	return 0;
 
@@ -2469,12 +2474,11 @@ static void gfar_align_skb(struct sk_buff *skb)
 }
 
 /* Interrupt Handler for Transmit complete */
-static int gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue)
+static void gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue)
 {
 	struct net_device *dev = tx_queue->dev;
 	struct netdev_queue *txq;
 	struct gfar_private *priv = netdev_priv(dev);
-	struct gfar_priv_rx_q *rx_queue = NULL;
 	struct txbd8 *bdp, *next = NULL;
 	struct txbd8 *lbdp = NULL;
 	struct txbd8 *base = tx_queue->tx_bd_base;
@@ -2489,7 +2493,6 @@ static int gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue)
 	u32 lstatus;
 	size_t buflen;
 
-	rx_queue = priv->rx_queue[tqi];
 	txq = netdev_get_tx_queue(dev, tqi);
 	bdp = tx_queue->dirty_tx;
 	skb_dirtytx = tx_queue->skb_dirtytx;
@@ -2571,8 +2574,6 @@ static int gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue)
 	tx_queue->dirty_tx = bdp;
 
 	netdev_tx_completed_queue(txq, howmany, bytes_sent);
-
-	return howmany;
 }
 
 static void gfar_schedule_cleanup(struct gfar_priv_grp *gfargrp)
@@ -2694,8 +2695,6 @@ static void gfar_process_frame(struct net_device *dev, struct sk_buff *skb,
 	struct gfar_private *priv = netdev_priv(dev);
 	struct rxfcb *fcb = NULL;
 
-	gro_result_t ret;
-
 	/* fcb is at the beginning if exists */
 	fcb = (struct rxfcb *)skb->data;
 
@@ -2734,10 +2733,8 @@ static void gfar_process_frame(struct net_device *dev, struct sk_buff *skb,
 		__vlan_hwaccel_put_tag(skb, fcb->vlctl);
 
 	/* Send the packet up the stack */
-	ret = napi_gro_receive(napi, skb);
+	napi_gro_receive(napi, skb);
 
-	if (unlikely(GRO_DROP == ret))
-		atomic64_inc(&priv->extra_stats.kernel_dropped);
 }
 
 /* gfar_clean_rx_ring() -- Processes each frame in the rx ring
@@ -2835,62 +2832,82 @@ static int gfar_poll(struct napi_struct *napi, int budget)
 	struct gfar __iomem *regs = gfargrp->regs;
 	struct gfar_priv_tx_q *tx_queue = NULL;
 	struct gfar_priv_rx_q *rx_queue = NULL;
-	int rx_cleaned = 0, budget_per_queue = 0, rx_cleaned_per_queue = 0;
-	int tx_cleaned = 0, i, left_over_budget = budget;
-	unsigned long serviced_queues = 0;
-	int num_queues = 0;
-
-	num_queues = gfargrp->num_rx_queues;
-	budget_per_queue = budget/num_queues;
+	int work_done = 0, work_done_per_q = 0;
+	int i, budget_per_q = 0;
+	int has_tx_work;
+	unsigned long rstat_rxf;
+	int num_act_queues;
 
 	/* Clear IEVENT, so interrupts aren't called again
 	 * because of the packets that have already arrived
 	 */
 	gfar_write(&regs->ievent, IEVENT_RTX_MASK);
 
-	while (num_queues && left_over_budget) {
-		budget_per_queue = left_over_budget/num_queues;
-		left_over_budget = 0;
+	rstat_rxf = gfar_read(&regs->rstat) & RSTAT_RXF_MASK;
+
+	num_act_queues = bitmap_weight(&rstat_rxf, MAX_RX_QS);
+	if (num_act_queues)
+		budget_per_q = budget/num_act_queues;
+
+	while (1) {
+		has_tx_work = 0;
+		for_each_set_bit(i, &gfargrp->tx_bit_map, priv->num_tx_queues) {
+			tx_queue = priv->tx_queue[i];
+			/* run Tx cleanup to completion */
+			if (tx_queue->tx_skbuff[tx_queue->skb_dirtytx]) {
+				gfar_clean_tx_ring(tx_queue);
+				has_tx_work = 1;
+			}
+		}
 
 		for_each_set_bit(i, &gfargrp->rx_bit_map, priv->num_rx_queues) {
-			if (test_bit(i, &serviced_queues))
+			/* skip queue if not active */
+			if (!(rstat_rxf & (RSTAT_CLEAR_RXF0 >> i)))
 				continue;
+
 			rx_queue = priv->rx_queue[i];
-			tx_queue = priv->tx_queue[rx_queue->qindex];
-
-			tx_cleaned += gfar_clean_tx_ring(tx_queue);
-			rx_cleaned_per_queue =
-				gfar_clean_rx_ring(rx_queue, budget_per_queue);
-			rx_cleaned += rx_cleaned_per_queue;
-			if (rx_cleaned_per_queue < budget_per_queue) {
-				left_over_budget = left_over_budget +
-					(budget_per_queue -
-					 rx_cleaned_per_queue);
-				set_bit(i, &serviced_queues);
-				num_queues--;
+			work_done_per_q =
+				gfar_clean_rx_ring(rx_queue, budget_per_q);
+			work_done += work_done_per_q;
+
+			/* finished processing this queue */
+			if (work_done_per_q < budget_per_q) {
+				/* clear active queue hw indication */
+				gfar_write(&regs->rstat,
+					   RSTAT_CLEAR_RXF0 >> i);
+				rstat_rxf &= ~(RSTAT_CLEAR_RXF0 >> i);
+				num_act_queues--;
+
+				if (!num_act_queues)
+					break;
+				/* recompute budget per Rx queue */
+				budget_per_q =
+					(budget - work_done) / num_act_queues;
 			}
 		}
-	}
 
-	if (tx_cleaned)
-		return budget;
+		if (work_done >= budget)
+			break;
 
-	if (rx_cleaned < budget) {
-		napi_complete(napi);
+		if (!num_act_queues && !has_tx_work) {
 
-		/* Clear the halt bit in RSTAT */
-		gfar_write(&regs->rstat, gfargrp->rstat);
+			napi_complete(napi);
 
-		gfar_write(&regs->imask, IMASK_DEFAULT);
+			/* Clear the halt bit in RSTAT */
+			gfar_write(&regs->rstat, gfargrp->rstat);
 
-		/* If we are coalescing interrupts, update the timer
-		 * Otherwise, clear it
-		 */
-		gfar_configure_coalescing(priv, gfargrp->rx_bit_map,
-					  gfargrp->tx_bit_map);
+			gfar_write(&regs->imask, IMASK_DEFAULT);
+
+			/* If we are coalescing interrupts, update the timer
+			 * Otherwise, clear it
+			 */
+			gfar_configure_coalescing(priv, gfargrp->rx_bit_map,
+						  gfargrp->tx_bit_map);
+			break;
+		}
 	}
 
-	return rx_cleaned;
+	return work_done;
 }
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
diff --git a/drivers/net/ethernet/freescale/gianfar.h b/drivers/net/ethernet/freescale/gianfar.h
index 63a28d2..04b552c 100644
--- a/drivers/net/ethernet/freescale/gianfar.h
+++ b/drivers/net/ethernet/freescale/gianfar.h
@@ -291,7 +291,9 @@ extern const char gfar_driver_version[];
 #define RCTRL_PADDING(x)	((x << 16) & RCTRL_PAL_MASK)
 
 
-#define RSTAT_CLEAR_RHALT       0x00800000
+#define RSTAT_CLEAR_RHALT	0x00800000
+#define RSTAT_CLEAR_RXF0	0x00000080
+#define RSTAT_RXF_MASK		0x000000ff
 
 #define TCTRL_IPCSEN		0x00004000
 #define TCTRL_TUCSEN		0x00002000
@@ -627,7 +629,6 @@ struct rmon_mib
 };
 
 struct gfar_extra_stats {
-	atomic64_t kernel_dropped;
 	atomic64_t rx_large;
 	atomic64_t rx_short;
 	atomic64_t rx_nonoctet;
@@ -1180,8 +1181,7 @@ extern void stop_gfar(struct net_device *dev);
 extern void gfar_halt(struct net_device *dev);
 extern void gfar_phy_test(struct mii_bus *bus, struct phy_device *phydev,
 		int enable, u32 regnum, u32 read);
-extern void gfar_configure_coalescing(struct gfar_private *priv,
-		unsigned long tx_mask, unsigned long rx_mask);
+extern void gfar_configure_coalescing_all(struct gfar_private *priv);
 void gfar_init_sysfs(struct net_device *dev);
 int gfar_set_features(struct net_device *dev, netdev_features_t features);
 extern void gfar_check_rx_parser_mode(struct gfar_private *priv);
diff --git a/drivers/net/ethernet/freescale/gianfar_ethtool.c b/drivers/net/ethernet/freescale/gianfar_ethtool.c
index 75e89ac..4e7118f 100644
--- a/drivers/net/ethernet/freescale/gianfar_ethtool.c
+++ b/drivers/net/ethernet/freescale/gianfar_ethtool.c
@@ -66,7 +66,6 @@ static void gfar_gdrvinfo(struct net_device *dev,
 			  struct ethtool_drvinfo *drvinfo);
 
 static const char stat_gstrings[][ETH_GSTRING_LEN] = {
-	"rx-dropped-by-kernel",
 	"rx-large-frame-errors",
 	"rx-short-frame-errors",
 	"rx-non-octet-errors",
@@ -436,7 +435,7 @@ static int gfar_scoalesce(struct net_device *dev,
 			gfar_usecs2ticks(priv, cvals->tx_coalesce_usecs));
 	}
 
-	gfar_configure_coalescing(priv, 0xFF, 0xFF);
+	gfar_configure_coalescing_all(priv);
 
 	return 0;
 }
diff --git a/drivers/net/ethernet/fujitsu/fmvj18x_cs.c b/drivers/net/ethernet/fujitsu/fmvj18x_cs.c
index 2418faf..ef46b58 100644
--- a/drivers/net/ethernet/fujitsu/fmvj18x_cs.c
+++ b/drivers/net/ethernet/fujitsu/fmvj18x_cs.c
@@ -705,19 +705,7 @@ static struct pcmcia_driver fmvj18x_cs_driver = {
 	.suspend	= fmvj18x_suspend,
 	.resume		= fmvj18x_resume,
 };
-
-static int __init init_fmvj18x_cs(void)
-{
-	return pcmcia_register_driver(&fmvj18x_cs_driver);
-}
-
-static void __exit exit_fmvj18x_cs(void)
-{
-	pcmcia_unregister_driver(&fmvj18x_cs_driver);
-}
-
-module_init(init_fmvj18x_cs);
-module_exit(exit_fmvj18x_cs);
+module_pcmcia_driver(fmvj18x_cs_driver);
 
 /*====================================================================*/
 
@@ -1003,8 +991,6 @@ static void fjn_rx(struct net_device *dev)
 	    }
 	    skb = netdev_alloc_skb(dev, pkt_len + 2);
 	    if (skb == NULL) {
-		netdev_notice(dev, "Memory squeeze, dropping packet (len %d)\n",
-			      pkt_len);
 		outb(F_SKP_PKT, ioaddr + RX_SKIP);
 		dev->stats.rx_dropped++;
 		break;
diff --git a/drivers/net/ethernet/i825xx/82596.c b/drivers/net/ethernet/i825xx/82596.c
index 1c54e22..e388161 100644
--- a/drivers/net/ethernet/i825xx/82596.c
+++ b/drivers/net/ethernet/i825xx/82596.c
@@ -798,16 +798,14 @@ static inline int i596_rx(struct net_device *dev)
 #ifdef __mc68000__
 				cache_clear(virt_to_phys(newskb->data), PKT_BUF_SZ);
 #endif
-			}
-			else
+			} else {
 				skb = netdev_alloc_skb(dev, pkt_len + 2);
+			}
 memory_squeeze:
 			if (skb == NULL) {
 				/* XXX tulip.c can defer packets here!! */
-				printk(KERN_WARNING "%s: i596_rx Memory squeeze, dropping packet.\n", dev->name);
 				dev->stats.rx_dropped++;
-			}
-			else {
+			} else {
 				if (!rx_in_place) {
 					/* 16 byte align the data fields */
 					skb_reserve(skb, 2);
diff --git a/drivers/net/ethernet/i825xx/lib82596.c b/drivers/net/ethernet/i825xx/lib82596.c
index f045ea4..d653bac 100644
--- a/drivers/net/ethernet/i825xx/lib82596.c
+++ b/drivers/net/ethernet/i825xx/lib82596.c
@@ -715,14 +715,12 @@ static inline int i596_rx(struct net_device *dev)
 				rbd->v_data = newskb->data;
 				rbd->b_data = SWAP32(dma_addr);
 				DMA_WBACK_INV(dev, rbd, sizeof(struct i596_rbd));
-			} else
+			} else {
 				skb = netdev_alloc_skb_ip_align(dev, pkt_len);
+			}
 memory_squeeze:
 			if (skb == NULL) {
 				/* XXX tulip.c can defer packets here!! */
-				printk(KERN_ERR
-				       "%s: i596_rx Memory squeeze, dropping packet.\n",
-				       dev->name);
 				dev->stats.rx_dropped++;
 			} else {
 				if (!rx_in_place) {
diff --git a/drivers/net/ethernet/ibm/ehea/ehea_main.c b/drivers/net/ethernet/ibm/ehea/ehea_main.c
index 328f47c..0296334 100644
--- a/drivers/net/ethernet/ibm/ehea/ehea_main.c
+++ b/drivers/net/ethernet/ibm/ehea/ehea_main.c
@@ -402,7 +402,6 @@ static void ehea_refill_rq1(struct ehea_port_res *pr, int index, int nr_of_wqes)
 			skb_arr_rq1[index] = netdev_alloc_skb(dev,
 							      EHEA_L_PKT_SIZE);
 			if (!skb_arr_rq1[index]) {
-				netdev_info(dev, "Unable to allocate enough skb in the array\n");
 				pr->rq1_skba.os_skbs = fill_wqes - i;
 				break;
 			}
@@ -432,10 +431,8 @@ static void ehea_init_fill_rq1(struct ehea_port_res *pr, int nr_rq1a)
 
 	for (i = 0; i < nr_rq1a; i++) {
 		skb_arr_rq1[i] = netdev_alloc_skb(dev, EHEA_L_PKT_SIZE);
-		if (!skb_arr_rq1[i]) {
-			netdev_info(dev, "Not enough memory to allocate skb array\n");
+		if (!skb_arr_rq1[i])
 			break;
-		}
 	}
 	/* Ring doorbell */
 	ehea_update_rq1a(pr->qp, i - 1);
@@ -695,10 +692,8 @@ static int ehea_proc_rwqes(struct net_device *dev,
 
 					skb = netdev_alloc_skb(dev,
 							       EHEA_L_PKT_SIZE);
-					if (!skb) {
-						netdev_err(dev, "Not enough memory to allocate skb\n");
+					if (!skb)
 						break;
-					}
 				}
 				skb_copy_to_linear_data(skb, ((char *)cqe) + 64,
 						 cqe->num_bytes_transfered - 4);
diff --git a/drivers/net/ethernet/ibm/emac/mal.c b/drivers/net/ethernet/ibm/emac/mal.c
index 1f7ecf5..610ed223 100644
--- a/drivers/net/ethernet/ibm/emac/mal.c
+++ b/drivers/net/ethernet/ibm/emac/mal.c
@@ -637,17 +637,12 @@ static int mal_probe(struct platform_device *ofdev)
 	bd_size = sizeof(struct mal_descriptor) *
 		(NUM_TX_BUFF * mal->num_tx_chans +
 		 NUM_RX_BUFF * mal->num_rx_chans);
-	mal->bd_virt =
-		dma_alloc_coherent(&ofdev->dev, bd_size, &mal->bd_dma,
-				   GFP_KERNEL);
+	mal->bd_virt = dma_alloc_coherent(&ofdev->dev, bd_size, &mal->bd_dma,
+					  GFP_KERNEL | __GFP_ZERO);
 	if (mal->bd_virt == NULL) {
-		printk(KERN_ERR
-		       "mal%d: out of memory allocating RX/TX descriptors!\n",
-		       index);
 		err = -ENOMEM;
 		goto fail_unmap;
 	}
-	memset(mal->bd_virt, 0, bd_size);
 
 	for (i = 0; i < mal->num_tx_chans; ++i)
 		set_mal_dcrn(mal, MAL_TXCTPR(i), mal->bd_dma +
diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c
index c859771..302d594 100644
--- a/drivers/net/ethernet/ibm/ibmveth.c
+++ b/drivers/net/ethernet/ibm/ibmveth.c
@@ -556,11 +556,9 @@ static int ibmveth_open(struct net_device *netdev)
 	adapter->rx_queue.queue_len = sizeof(struct ibmveth_rx_q_entry) *
 						rxq_entries;
 	adapter->rx_queue.queue_addr =
-	    dma_alloc_coherent(dev, adapter->rx_queue.queue_len,
-			       &adapter->rx_queue.queue_dma, GFP_KERNEL);
-
+		dma_alloc_coherent(dev, adapter->rx_queue.queue_len,
+				   &adapter->rx_queue.queue_dma, GFP_KERNEL);
 	if (!adapter->rx_queue.queue_addr) {
-		netdev_err(netdev, "unable to allocate rx queue pages\n");
 		rc = -ENOMEM;
 		goto err_out;
 	}
diff --git a/drivers/net/ethernet/intel/e1000/e1000_ethtool.c b/drivers/net/ethernet/intel/e1000/e1000_ethtool.c
index 43462d5..82a967c 100644
--- a/drivers/net/ethernet/intel/e1000/e1000_ethtool.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_ethtool.c
@@ -1020,12 +1020,11 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
 	txdr->size = txdr->count * sizeof(struct e1000_tx_desc);
 	txdr->size = ALIGN(txdr->size, 4096);
 	txdr->desc = dma_alloc_coherent(&pdev->dev, txdr->size, &txdr->dma,
-					GFP_KERNEL);
+					GFP_KERNEL | __GFP_ZERO);
 	if (!txdr->desc) {
 		ret_val = 2;
 		goto err_nomem;
 	}
-	memset(txdr->desc, 0, txdr->size);
 	txdr->next_to_use = txdr->next_to_clean = 0;
 
 	ew32(TDBAL, ((u64)txdr->dma & 0x00000000FFFFFFFF));
@@ -1053,6 +1052,10 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
 		txdr->buffer_info[i].dma =
 			dma_map_single(&pdev->dev, skb->data, skb->len,
 				       DMA_TO_DEVICE);
+		if (dma_mapping_error(&pdev->dev, txdr->buffer_info[i].dma)) {
+			ret_val = 4;
+			goto err_nomem;
+		}
 		tx_desc->buffer_addr = cpu_to_le64(txdr->buffer_info[i].dma);
 		tx_desc->lower.data = cpu_to_le32(skb->len);
 		tx_desc->lower.data |= cpu_to_le32(E1000_TXD_CMD_EOP |
@@ -1069,18 +1072,17 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
 	rxdr->buffer_info = kcalloc(rxdr->count, sizeof(struct e1000_buffer),
 				    GFP_KERNEL);
 	if (!rxdr->buffer_info) {
-		ret_val = 4;
+		ret_val = 5;
 		goto err_nomem;
 	}
 
 	rxdr->size = rxdr->count * sizeof(struct e1000_rx_desc);
 	rxdr->desc = dma_alloc_coherent(&pdev->dev, rxdr->size, &rxdr->dma,
-					GFP_KERNEL);
+					GFP_KERNEL | __GFP_ZERO);
 	if (!rxdr->desc) {
-		ret_val = 5;
+		ret_val = 6;
 		goto err_nomem;
 	}
-	memset(rxdr->desc, 0, rxdr->size);
 	rxdr->next_to_use = rxdr->next_to_clean = 0;
 
 	rctl = er32(RCTL);
@@ -1101,7 +1103,7 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
 
 		skb = alloc_skb(E1000_RXBUFFER_2048 + NET_IP_ALIGN, GFP_KERNEL);
 		if (!skb) {
-			ret_val = 6;
+			ret_val = 7;
 			goto err_nomem;
 		}
 		skb_reserve(skb, NET_IP_ALIGN);
@@ -1110,6 +1112,10 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
 		rxdr->buffer_info[i].dma =
 			dma_map_single(&pdev->dev, skb->data,
 				       E1000_RXBUFFER_2048, DMA_FROM_DEVICE);
+		if (dma_mapping_error(&pdev->dev, rxdr->buffer_info[i].dma)) {
+			ret_val = 8;
+			goto err_nomem;
+		}
 		rx_desc->buffer_addr = cpu_to_le64(rxdr->buffer_info[i].dma);
 		memset(skb->data, 0x00, skb->len);
 	}
diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c
index 8502c62..d98e1d09 100644
--- a/drivers/net/ethernet/intel/e1000/e1000_main.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_main.c
@@ -1516,8 +1516,6 @@ static int e1000_setup_tx_resources(struct e1000_adapter *adapter,
 	if (!txdr->desc) {
 setup_tx_desc_die:
 		vfree(txdr->buffer_info);
-		e_err(probe, "Unable to allocate memory for the Tx descriptor "
-		      "ring\n");
 		return -ENOMEM;
 	}
 
@@ -1707,10 +1705,7 @@ static int e1000_setup_rx_resources(struct e1000_adapter *adapter,
 
 	rxdr->desc = dma_alloc_coherent(&pdev->dev, rxdr->size, &rxdr->dma,
 					GFP_KERNEL);
-
 	if (!rxdr->desc) {
-		e_err(probe, "Unable to allocate memory for the Rx descriptor "
-		      "ring\n");
 setup_rx_desc_die:
 		vfree(rxdr->buffer_info);
 		return -ENOMEM;
@@ -1729,8 +1724,6 @@ setup_rx_desc_die:
 		if (!rxdr->desc) {
 			dma_free_coherent(&pdev->dev, rxdr->size, olddesc,
 					  olddma);
-			e_err(probe, "Unable to allocate memory for the Rx "
-			      "descriptor ring\n");
 			goto setup_rx_desc_die;
 		}
 
diff --git a/drivers/net/ethernet/intel/e1000e/80003es2lan.c b/drivers/net/ethernet/intel/e1000e/80003es2lan.c
index e099138..b71c850 100644
--- a/drivers/net/ethernet/intel/e1000e/80003es2lan.c
+++ b/drivers/net/ethernet/intel/e1000e/80003es2lan.c
@@ -37,7 +37,9 @@
  * "index + 5".
  */
 static const u16 e1000_gg82563_cable_length_table[] = {
-	 0, 60, 115, 150, 150, 60, 115, 150, 180, 180, 0xFF };
+	0, 60, 115, 150, 150, 60, 115, 150, 180, 180, 0xFF
+};
+
 #define GG82563_CABLE_LENGTH_TABLE_SIZE \
 		ARRAY_SIZE(e1000_gg82563_cable_length_table)
 
@@ -116,7 +118,7 @@ static s32 e1000_init_nvm_params_80003es2lan(struct e1000_hw *hw)
 	nvm->type = e1000_nvm_eeprom_spi;
 
 	size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >>
-			  E1000_EECD_SIZE_EX_SHIFT);
+		     E1000_EECD_SIZE_EX_SHIFT);
 
 	/* Added to a constant, "size" becomes the left-shift value
 	 * for setting word_size.
@@ -393,7 +395,7 @@ static s32 e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
 		 * before the device has completed the "Page Select" MDI
 		 * transaction.  So we wait 200us after each MDI command...
 		 */
-		udelay(200);
+		usleep_range(200, 400);
 
 		/* ...and verify the command was successful. */
 		ret_val = e1000e_read_phy_reg_mdic(hw, page_select, &temp);
@@ -403,17 +405,17 @@ static s32 e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
 			return -E1000_ERR_PHY;
 		}
 
-		udelay(200);
+		usleep_range(200, 400);
 
 		ret_val = e1000e_read_phy_reg_mdic(hw,
-		                                  MAX_PHY_REG_ADDRESS & offset,
-		                                  data);
+						   MAX_PHY_REG_ADDRESS & offset,
+						   data);
 
-		udelay(200);
+		usleep_range(200, 400);
 	} else {
 		ret_val = e1000e_read_phy_reg_mdic(hw,
-		                                  MAX_PHY_REG_ADDRESS & offset,
-		                                  data);
+						   MAX_PHY_REG_ADDRESS & offset,
+						   data);
 	}
 
 	e1000_release_phy_80003es2lan(hw);
@@ -462,7 +464,7 @@ static s32 e1000_write_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
 		 * before the device has completed the "Page Select" MDI
 		 * transaction.  So we wait 200us after each MDI command...
 		 */
-		udelay(200);
+		usleep_range(200, 400);
 
 		/* ...and verify the command was successful. */
 		ret_val = e1000e_read_phy_reg_mdic(hw, page_select, &temp);
@@ -472,17 +474,17 @@ static s32 e1000_write_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
 			return -E1000_ERR_PHY;
 		}
 
-		udelay(200);
+		usleep_range(200, 400);
 
 		ret_val = e1000e_write_phy_reg_mdic(hw,
-		                                  MAX_PHY_REG_ADDRESS & offset,
-		                                  data);
+						    MAX_PHY_REG_ADDRESS &
+						    offset, data);
 
-		udelay(200);
+		usleep_range(200, 400);
 	} else {
 		ret_val = e1000e_write_phy_reg_mdic(hw,
-		                                  MAX_PHY_REG_ADDRESS & offset,
-		                                  data);
+						    MAX_PHY_REG_ADDRESS &
+						    offset, data);
 	}
 
 	e1000_release_phy_80003es2lan(hw);
@@ -580,7 +582,7 @@ static s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw)
 		e_dbg("Waiting for forced speed/duplex link on GG82563 phy.\n");
 
 		ret_val = e1000e_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
-						     100000, &link);
+						      100000, &link);
 		if (ret_val)
 			return ret_val;
 
@@ -595,7 +597,7 @@ static s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw)
 
 		/* Try once more */
 		ret_val = e1000e_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
-						     100000, &link);
+						      100000, &link);
 		if (ret_val)
 			return ret_val;
 	}
@@ -666,14 +668,12 @@ static s32 e1000_get_link_up_info_80003es2lan(struct e1000_hw *hw, u16 *speed,
 	s32 ret_val;
 
 	if (hw->phy.media_type == e1000_media_type_copper) {
-		ret_val = e1000e_get_speed_and_duplex_copper(hw,
-								    speed,
-								    duplex);
+		ret_val = e1000e_get_speed_and_duplex_copper(hw, speed, duplex);
 		hw->phy.ops.cfg_on_link_up(hw);
 	} else {
 		ret_val = e1000e_get_speed_and_duplex_fiber_serdes(hw,
-								  speed,
-								  duplex);
+								   speed,
+								   duplex);
 	}
 
 	return ret_val;
@@ -754,9 +754,9 @@ static s32 e1000_init_hw_80003es2lan(struct e1000_hw *hw)
 
 	/* Initialize identification LED */
 	ret_val = mac->ops.id_led_init(hw);
+	/* An error is not fatal and we should not stop init due to this */
 	if (ret_val)
 		e_dbg("Error initializing identification LED\n");
-		/* This is not fatal and we should not stop init due to this */
 
 	/* Disabling VLAN filtering */
 	e_dbg("Initializing the IEEE VLAN\n");
@@ -784,14 +784,14 @@ static s32 e1000_init_hw_80003es2lan(struct e1000_hw *hw)
 
 	/* Set the transmit descriptor write-back policy */
 	reg_data = er32(TXDCTL(0));
-	reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) |
-		   E1000_TXDCTL_FULL_TX_DESC_WB | E1000_TXDCTL_COUNT_DESC;
+	reg_data = ((reg_data & ~E1000_TXDCTL_WTHRESH) |
+		    E1000_TXDCTL_FULL_TX_DESC_WB | E1000_TXDCTL_COUNT_DESC);
 	ew32(TXDCTL(0), reg_data);
 
 	/* ...for both queues. */
 	reg_data = er32(TXDCTL(1));
-	reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) |
-		   E1000_TXDCTL_FULL_TX_DESC_WB | E1000_TXDCTL_COUNT_DESC;
+	reg_data = ((reg_data & ~E1000_TXDCTL_WTHRESH) |
+		    E1000_TXDCTL_FULL_TX_DESC_WB | E1000_TXDCTL_COUNT_DESC);
 	ew32(TXDCTL(1), reg_data);
 
 	/* Enable retransmit on late collisions */
@@ -818,13 +818,12 @@ static s32 e1000_init_hw_80003es2lan(struct e1000_hw *hw)
 	/* default to true to enable the MDIC W/A */
 	hw->dev_spec.e80003es2lan.mdic_wa_enable = true;
 
-	ret_val = e1000_read_kmrn_reg_80003es2lan(hw,
-	                              E1000_KMRNCTRLSTA_OFFSET >>
-	                              E1000_KMRNCTRLSTA_OFFSET_SHIFT,
-	                              &i);
+	ret_val =
+	    e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_OFFSET >>
+					    E1000_KMRNCTRLSTA_OFFSET_SHIFT, &i);
 	if (!ret_val) {
 		if ((i & E1000_KMRNCTRLSTA_OPMODE_MASK) ==
-		     E1000_KMRNCTRLSTA_OPMODE_INBAND_MDIO)
+		    E1000_KMRNCTRLSTA_OPMODE_INBAND_MDIO)
 			hw->dev_spec.e80003es2lan.mdic_wa_enable = false;
 	}
 
@@ -891,7 +890,7 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw)
 {
 	struct e1000_phy_info *phy = &hw->phy;
 	s32 ret_val;
-	u32 ctrl_ext;
+	u32 reg;
 	u16 data;
 
 	ret_val = e1e_rphy(hw, GG82563_PHY_MAC_SPEC_CTRL, &data);
@@ -954,22 +953,19 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw)
 	}
 
 	/* Bypass Rx and Tx FIFO's */
-	ret_val = e1000_write_kmrn_reg_80003es2lan(hw,
-					E1000_KMRNCTRLSTA_OFFSET_FIFO_CTRL,
-					E1000_KMRNCTRLSTA_FIFO_CTRL_RX_BYPASS |
-					E1000_KMRNCTRLSTA_FIFO_CTRL_TX_BYPASS);
+	reg = E1000_KMRNCTRLSTA_OFFSET_FIFO_CTRL;
+	data = (E1000_KMRNCTRLSTA_FIFO_CTRL_RX_BYPASS |
+		E1000_KMRNCTRLSTA_FIFO_CTRL_TX_BYPASS);
+	ret_val = e1000_write_kmrn_reg_80003es2lan(hw, reg, data);
 	if (ret_val)
 		return ret_val;
 
-	ret_val = e1000_read_kmrn_reg_80003es2lan(hw,
-				       E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE,
-				       &data);
+	reg = E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE;
+	ret_val = e1000_read_kmrn_reg_80003es2lan(hw, reg, &data);
 	if (ret_val)
 		return ret_val;
 	data |= E1000_KMRNCTRLSTA_OPMODE_E_IDLE;
-	ret_val = e1000_write_kmrn_reg_80003es2lan(hw,
-					E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE,
-					data);
+	ret_val = e1000_write_kmrn_reg_80003es2lan(hw, reg, data);
 	if (ret_val)
 		return ret_val;
 
@@ -982,9 +978,9 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw)
 	if (ret_val)
 		return ret_val;
 
-	ctrl_ext = er32(CTRL_EXT);
-	ctrl_ext &= ~(E1000_CTRL_EXT_LINK_MODE_MASK);
-	ew32(CTRL_EXT, ctrl_ext);
+	reg = er32(CTRL_EXT);
+	reg &= ~E1000_CTRL_EXT_LINK_MODE_MASK;
+	ew32(CTRL_EXT, reg);
 
 	ret_val = e1e_rphy(hw, GG82563_PHY_PWR_MGMT_CTRL, &data);
 	if (ret_val)
@@ -1049,27 +1045,29 @@ static s32 e1000_setup_copper_link_80003es2lan(struct e1000_hw *hw)
 	 * polling the phy; this fixes erroneous timeouts at 10Mbps.
 	 */
 	ret_val = e1000_write_kmrn_reg_80003es2lan(hw, GG82563_REG(0x34, 4),
-	                                           0xFFFF);
+						   0xFFFF);
 	if (ret_val)
 		return ret_val;
 	ret_val = e1000_read_kmrn_reg_80003es2lan(hw, GG82563_REG(0x34, 9),
-	                                          &reg_data);
+						  &reg_data);
 	if (ret_val)
 		return ret_val;
 	reg_data |= 0x3F;
 	ret_val = e1000_write_kmrn_reg_80003es2lan(hw, GG82563_REG(0x34, 9),
-	                                           reg_data);
+						   reg_data);
 	if (ret_val)
 		return ret_val;
-	ret_val = e1000_read_kmrn_reg_80003es2lan(hw,
-				      E1000_KMRNCTRLSTA_OFFSET_INB_CTRL,
-				      &reg_data);
+	ret_val =
+	    e1000_read_kmrn_reg_80003es2lan(hw,
+					    E1000_KMRNCTRLSTA_OFFSET_INB_CTRL,
+					    &reg_data);
 	if (ret_val)
 		return ret_val;
 	reg_data |= E1000_KMRNCTRLSTA_INB_CTRL_DIS_PADDING;
-	ret_val = e1000_write_kmrn_reg_80003es2lan(hw,
-					E1000_KMRNCTRLSTA_OFFSET_INB_CTRL,
-					reg_data);
+	ret_val =
+	    e1000_write_kmrn_reg_80003es2lan(hw,
+					     E1000_KMRNCTRLSTA_OFFSET_INB_CTRL,
+					     reg_data);
 	if (ret_val)
 		return ret_val;
 
@@ -1096,7 +1094,7 @@ static s32 e1000_cfg_on_link_up_80003es2lan(struct e1000_hw *hw)
 
 	if (hw->phy.media_type == e1000_media_type_copper) {
 		ret_val = e1000e_get_speed_and_duplex_copper(hw, &speed,
-		                                             &duplex);
+							     &duplex);
 		if (ret_val)
 			return ret_val;
 
@@ -1125,9 +1123,10 @@ static s32 e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex)
 	u16 reg_data, reg_data2;
 
 	reg_data = E1000_KMRNCTRLSTA_HD_CTRL_10_100_DEFAULT;
-	ret_val = e1000_write_kmrn_reg_80003es2lan(hw,
-	                               E1000_KMRNCTRLSTA_OFFSET_HD_CTRL,
-	                               reg_data);
+	ret_val =
+	    e1000_write_kmrn_reg_80003es2lan(hw,
+					     E1000_KMRNCTRLSTA_OFFSET_HD_CTRL,
+					     reg_data);
 	if (ret_val)
 		return ret_val;
 
@@ -1171,9 +1170,10 @@ static s32 e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw)
 	u32 i = 0;
 
 	reg_data = E1000_KMRNCTRLSTA_HD_CTRL_1000_DEFAULT;
-	ret_val = e1000_write_kmrn_reg_80003es2lan(hw,
-	                               E1000_KMRNCTRLSTA_OFFSET_HD_CTRL,
-	                               reg_data);
+	ret_val =
+	    e1000_write_kmrn_reg_80003es2lan(hw,
+					     E1000_KMRNCTRLSTA_OFFSET_HD_CTRL,
+					     reg_data);
 	if (ret_val)
 		return ret_val;
 
@@ -1220,7 +1220,7 @@ static s32 e1000_read_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset,
 		return ret_val;
 
 	kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) &
-	               E1000_KMRNCTRLSTA_OFFSET) | E1000_KMRNCTRLSTA_REN;
+		       E1000_KMRNCTRLSTA_OFFSET) | E1000_KMRNCTRLSTA_REN;
 	ew32(KMRNCTRLSTA, kmrnctrlsta);
 	e1e_flush();
 
@@ -1255,7 +1255,7 @@ static s32 e1000_write_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset,
 		return ret_val;
 
 	kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) &
-	               E1000_KMRNCTRLSTA_OFFSET) | data;
+		       E1000_KMRNCTRLSTA_OFFSET) | data;
 	ew32(KMRNCTRLSTA, kmrnctrlsta);
 	e1e_flush();
 
@@ -1419,4 +1419,3 @@ const struct e1000_info e1000_es2_info = {
 	.phy_ops		= &es2_phy_ops,
 	.nvm_ops		= &es2_nvm_ops,
 };
-
diff --git a/drivers/net/ethernet/intel/e1000e/82571.c b/drivers/net/ethernet/intel/e1000e/82571.c
index 2faffbd..7380442 100644
--- a/drivers/net/ethernet/intel/e1000e/82571.c
+++ b/drivers/net/ethernet/intel/e1000e/82571.c
@@ -184,7 +184,7 @@ static s32 e1000_init_nvm_params_82571(struct e1000_hw *hw)
 	default:
 		nvm->type = e1000_nvm_eeprom_spi;
 		size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >>
-				  E1000_EECD_SIZE_EX_SHIFT);
+			     E1000_EECD_SIZE_EX_SHIFT);
 		/* Added to a constant, "size" becomes the left-shift value
 		 * for setting word_size.
 		 */
@@ -437,7 +437,7 @@ static s32 e1000_get_phy_id_82571(struct e1000_hw *hw)
 			return ret_val;
 
 		phy->id = (u32)(phy_id << 16);
-		udelay(20);
+		usleep_range(20, 40);
 		ret_val = e1e_rphy(hw, MII_PHYSID2, &phy_id);
 		if (ret_val)
 			return ret_val;
@@ -482,7 +482,7 @@ static s32 e1000_get_hw_semaphore_82571(struct e1000_hw *hw)
 		if (!(swsm & E1000_SWSM_SMBI))
 			break;
 
-		udelay(50);
+		usleep_range(50, 100);
 		i++;
 	}
 
@@ -499,7 +499,7 @@ static s32 e1000_get_hw_semaphore_82571(struct e1000_hw *hw)
 		if (er32(SWSM) & E1000_SWSM_SWESMBI)
 			break;
 
-		udelay(50);
+		usleep_range(50, 100);
 	}
 
 	if (i == fw_timeout) {
@@ -526,6 +526,7 @@ static void e1000_put_hw_semaphore_82571(struct e1000_hw *hw)
 	swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI);
 	ew32(SWSM, swsm);
 }
+
 /**
  *  e1000_get_hw_semaphore_82573 - Acquire hardware semaphore
  *  @hw: pointer to the HW structure
@@ -846,9 +847,9 @@ static s32 e1000_write_nvm_eewr_82571(struct e1000_hw *hw, u16 offset,
 	}
 
 	for (i = 0; i < words; i++) {
-		eewr = (data[i] << E1000_NVM_RW_REG_DATA) |
-		       ((offset+i) << E1000_NVM_RW_ADDR_SHIFT) |
-		       E1000_NVM_RW_REG_START;
+		eewr = ((data[i] << E1000_NVM_RW_REG_DATA) |
+			((offset + i) << E1000_NVM_RW_ADDR_SHIFT) |
+			E1000_NVM_RW_REG_START);
 
 		ret_val = e1000e_poll_eerd_eewr_done(hw, E1000_NVM_POLL_WRITE);
 		if (ret_val)
@@ -875,8 +876,7 @@ static s32 e1000_get_cfg_done_82571(struct e1000_hw *hw)
 	s32 timeout = PHY_CFG_TIMEOUT;
 
 	while (timeout) {
-		if (er32(EEMNGCTL) &
-		    E1000_NVM_CFG_DONE_PORT_0)
+		if (er32(EEMNGCTL) & E1000_NVM_CFG_DONE_PORT_0)
 			break;
 		usleep_range(1000, 2000);
 		timeout--;
@@ -1022,7 +1022,7 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw)
 	}
 
 	if (hw->nvm.type == e1000_nvm_flash_hw) {
-		udelay(10);
+		usleep_range(10, 20);
 		ctrl_ext = er32(CTRL_EXT);
 		ctrl_ext |= E1000_CTRL_EXT_EE_RST;
 		ew32(CTRL_EXT, ctrl_ext);
@@ -1095,9 +1095,9 @@ static s32 e1000_init_hw_82571(struct e1000_hw *hw)
 
 	/* Initialize identification LED */
 	ret_val = mac->ops.id_led_init(hw);
+	/* An error is not fatal and we should not stop init due to this */
 	if (ret_val)
 		e_dbg("Error initializing identification LED\n");
-		/* This is not fatal and we should not stop init due to this */
 
 	/* Disabling VLAN filtering */
 	e_dbg("Initializing the IEEE VLAN\n");
@@ -1122,9 +1122,8 @@ static s32 e1000_init_hw_82571(struct e1000_hw *hw)
 
 	/* Set the transmit descriptor write-back policy */
 	reg_data = er32(TXDCTL(0));
-	reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) |
-		   E1000_TXDCTL_FULL_TX_DESC_WB |
-		   E1000_TXDCTL_COUNT_DESC;
+	reg_data = ((reg_data & ~E1000_TXDCTL_WTHRESH) |
+		    E1000_TXDCTL_FULL_TX_DESC_WB | E1000_TXDCTL_COUNT_DESC);
 	ew32(TXDCTL(0), reg_data);
 
 	/* ...for both queues. */
@@ -1140,9 +1139,9 @@ static s32 e1000_init_hw_82571(struct e1000_hw *hw)
 		break;
 	default:
 		reg_data = er32(TXDCTL(1));
-		reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) |
-			   E1000_TXDCTL_FULL_TX_DESC_WB |
-			   E1000_TXDCTL_COUNT_DESC;
+		reg_data = ((reg_data & ~E1000_TXDCTL_WTHRESH) |
+			    E1000_TXDCTL_FULL_TX_DESC_WB |
+			    E1000_TXDCTL_COUNT_DESC);
 		ew32(TXDCTL(1), reg_data);
 		break;
 	}
@@ -1530,7 +1529,7 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw)
 	status = er32(STATUS);
 	er32(RXCW);
 	/* SYNCH bit and IV bit are sticky */
-	udelay(10);
+	usleep_range(10, 20);
 	rxcw = er32(RXCW);
 
 	if ((rxcw & E1000_RXCW_SYNCH) && !(rxcw & E1000_RXCW_IV)) {
@@ -1633,7 +1632,7 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw)
 			 * the IV bit and restart Autoneg
 			 */
 			for (i = 0; i < AN_RETRY_COUNT; i++) {
-				udelay(10);
+				usleep_range(10, 20);
 				rxcw = er32(RXCW);
 				if ((rxcw & E1000_RXCW_SYNCH) &&
 				    (rxcw & E1000_RXCW_C))
@@ -2066,4 +2065,3 @@ const struct e1000_info e1000_82583_info = {
 	.phy_ops		= &e82_phy_ops_bm,
 	.nvm_ops		= &e82571_nvm_ops,
 };
-
diff --git a/drivers/net/ethernet/intel/e1000e/82571.h b/drivers/net/ethernet/intel/e1000e/82571.h
index 85cb1a3..08e24dc 100644
--- a/drivers/net/ethernet/intel/e1000e/82571.h
+++ b/drivers/net/ethernet/intel/e1000e/82571.h
@@ -44,6 +44,8 @@
 #define E1000_EIAC_82574	0x000DC	/* Ext. Interrupt Auto Clear - RW */
 #define E1000_EIAC_MASK_82574	0x01F00000
 
+#define E1000_IVAR_INT_ALLOC_VALID	0x8
+
 /* Manageability Operation Mode mask */
 #define E1000_NVM_INIT_CTRL2_MNGM	0x6000
 
diff --git a/drivers/net/ethernet/intel/e1000e/defines.h b/drivers/net/ethernet/intel/e1000e/defines.h
index fc3a4fe..351c94a 100644
--- a/drivers/net/ethernet/intel/e1000e/defines.h
+++ b/drivers/net/ethernet/intel/e1000e/defines.h
@@ -66,7 +66,7 @@
 #define E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES  0x00C00000
 #define E1000_CTRL_EXT_EIAME          0x01000000
 #define E1000_CTRL_EXT_DRV_LOAD       0x10000000 /* Driver loaded bit for FW */
-#define E1000_CTRL_EXT_IAME           0x08000000 /* Interrupt acknowledge Auto-mask */
+#define E1000_CTRL_EXT_IAME		0x08000000 /* Int ACK Auto-mask */
 #define E1000_CTRL_EXT_PBA_CLR        0x80000000 /* PBA Clear */
 #define E1000_CTRL_EXT_LSECCK         0x00001000
 #define E1000_CTRL_EXT_PHYPDEN        0x00100000
@@ -216,6 +216,8 @@
 #define E1000_CTRL_MEHE     0x00080000  /* Memory Error Handling Enable */
 #define E1000_CTRL_SWDPIN0  0x00040000  /* SWDPIN 0 value */
 #define E1000_CTRL_SWDPIN1  0x00080000  /* SWDPIN 1 value */
+#define E1000_CTRL_ADVD3WUC 0x00100000  /* D3 WUC */
+#define E1000_CTRL_EN_PHY_PWR_MGMT 0x00200000 /* PHY PM enable */
 #define E1000_CTRL_SWDPIO0  0x00400000  /* SWDPIN 0 Input or output */
 #define E1000_CTRL_RST      0x04000000  /* Global reset */
 #define E1000_CTRL_RFCE     0x08000000  /* Receive Flow Control enable */
@@ -234,17 +236,17 @@
 #define E1000_STATUS_FUNC_SHIFT 2
 #define E1000_STATUS_FUNC_1     0x00000004      /* Function 1 */
 #define E1000_STATUS_TXOFF      0x00000010      /* transmission paused */
+#define E1000_STATUS_SPEED_MASK 0x000000C0
 #define E1000_STATUS_SPEED_10   0x00000000      /* Speed 10Mb/s */
 #define E1000_STATUS_SPEED_100  0x00000040      /* Speed 100Mb/s */
 #define E1000_STATUS_SPEED_1000 0x00000080      /* Speed 1000Mb/s */
 #define E1000_STATUS_LAN_INIT_DONE 0x00000200   /* Lan Init Completion by NVM */
 #define E1000_STATUS_PHYRA      0x00000400      /* PHY Reset Asserted */
-#define E1000_STATUS_GIO_MASTER_ENABLE 0x00080000 /* Status of Master requests. */
+#define E1000_STATUS_GIO_MASTER_ENABLE	0x00080000	/* Master Req status */
 
 #define HALF_DUPLEX 1
 #define FULL_DUPLEX 2
 
-
 #define ADVERTISE_10_HALF                 0x0001
 #define ADVERTISE_10_FULL                 0x0002
 #define ADVERTISE_100_HALF                0x0004
@@ -311,6 +313,7 @@
 
 /* SerDes Control */
 #define E1000_SCTL_DISABLE_SERDES_LOOPBACK 0x0400
+#define E1000_SCTL_ENABLE_SERDES_LOOPBACK	0x0410
 
 /* Receive Checksum Control */
 #define E1000_RXCSUM_TUOFL     0x00000200   /* TCP / UDP checksum offload */
@@ -400,7 +403,8 @@
 #define E1000_ICR_RXDMT0        0x00000010 /* Rx desc min. threshold (0) */
 #define E1000_ICR_RXT0          0x00000080 /* Rx timer intr (ring 0) */
 #define E1000_ICR_ECCER         0x00400000 /* Uncorrectable ECC Error */
-#define E1000_ICR_INT_ASSERTED  0x80000000 /* If this bit asserted, the driver should claim the interrupt */
+/* If this bit asserted, the driver should claim the interrupt */
+#define E1000_ICR_INT_ASSERTED	0x80000000
 #define E1000_ICR_RXQ0          0x00100000 /* Rx Queue 0 Interrupt */
 #define E1000_ICR_RXQ1          0x00200000 /* Rx Queue 1 Interrupt */
 #define E1000_ICR_TXQ0          0x00400000 /* Tx Queue 0 Interrupt */
@@ -583,13 +587,13 @@
 #define E1000_EECD_SEC1VAL   0x00400000 /* Sector One Valid */
 #define E1000_EECD_SEC1VAL_VALID_MASK (E1000_EECD_AUTO_RD | E1000_EECD_PRES)
 
-#define E1000_NVM_RW_REG_DATA   16   /* Offset to data in NVM read/write registers */
-#define E1000_NVM_RW_REG_DONE   2    /* Offset to READ/WRITE done bit */
-#define E1000_NVM_RW_REG_START  1    /* Start operation */
-#define E1000_NVM_RW_ADDR_SHIFT 2    /* Shift to the address bits */
-#define E1000_NVM_POLL_WRITE    1    /* Flag for polling for write complete */
-#define E1000_NVM_POLL_READ     0    /* Flag for polling for read complete */
-#define E1000_FLASH_UPDATES  2000
+#define E1000_NVM_RW_REG_DATA	16	/* Offset to data in NVM r/w regs */
+#define E1000_NVM_RW_REG_DONE	2	/* Offset to READ/WRITE done bit */
+#define E1000_NVM_RW_REG_START	1	/* Start operation */
+#define E1000_NVM_RW_ADDR_SHIFT	2	/* Shift to the address bits */
+#define E1000_NVM_POLL_WRITE	1	/* Flag for polling write complete */
+#define E1000_NVM_POLL_READ	0	/* Flag for polling read complete */
+#define E1000_FLASH_UPDATES	2000
 
 /* NVM Word Offsets */
 #define NVM_COMPAT                 0x0003
@@ -785,6 +789,7 @@
 	GG82563_REG(194, 18) /* Inband Control */
 
 /* MDI Control */
+#define E1000_MDIC_REG_MASK	0x001F0000
 #define E1000_MDIC_REG_SHIFT 16
 #define E1000_MDIC_PHY_SHIFT 21
 #define E1000_MDIC_OP_WRITE  0x04000000
diff --git a/drivers/net/ethernet/intel/e1000e/e1000.h b/drivers/net/ethernet/intel/e1000e/e1000.h
index fcc7581..82f1c84 100644
--- a/drivers/net/ethernet/intel/e1000e/e1000.h
+++ b/drivers/net/ethernet/intel/e1000e/e1000.h
@@ -46,6 +46,7 @@
 #include <linux/ptp_clock_kernel.h>
 #include <linux/ptp_classify.h>
 #include <linux/mii.h>
+#include <linux/mdio.h>
 #include "hw.h"
 
 struct e1000_info;
@@ -61,7 +62,6 @@ struct e1000_info;
 #define e_notice(format, arg...) \
 	netdev_notice(adapter->netdev, format, ## arg)
 
-
 /* Interrupt modes, as used by the IntMode parameter */
 #define E1000E_INT_MODE_LEGACY		0
 #define E1000E_INT_MODE_MSI		1
@@ -239,9 +239,8 @@ struct e1000_adapter {
 	u16 tx_itr;
 	u16 rx_itr;
 
-	/* Tx */
-	struct e1000_ring *tx_ring /* One per active queue */
-						____cacheline_aligned_in_smp;
+	/* Tx - one ring per active queue */
+	struct e1000_ring *tx_ring ____cacheline_aligned_in_smp;
 	u32 tx_fifo_limit;
 
 	struct napi_struct napi;
@@ -352,6 +351,8 @@ struct e1000_adapter {
 	struct timecounter tc;
 	struct ptp_clock *ptp_clock;
 	struct ptp_clock_info ptp_clock_info;
+
+	u16 eee_advert;
 };
 
 struct e1000_info {
@@ -487,8 +488,8 @@ extern int e1000e_setup_tx_resources(struct e1000_ring *ring);
 extern void e1000e_free_rx_resources(struct e1000_ring *ring);
 extern void e1000e_free_tx_resources(struct e1000_ring *ring);
 extern struct rtnl_link_stats64 *e1000e_get_stats64(struct net_device *netdev,
-                                                    struct rtnl_link_stats64
-                                                    *stats);
+						    struct rtnl_link_stats64
+						    *stats);
 extern void e1000e_set_interrupt_capability(struct e1000_adapter *adapter);
 extern void e1000e_reset_interrupt_capability(struct e1000_adapter *adapter);
 extern void e1000e_get_hw_control(struct e1000_adapter *adapter);
@@ -558,12 +559,14 @@ static inline s32 e1000e_update_nvm_checksum(struct e1000_hw *hw)
 	return hw->nvm.ops.update(hw);
 }
 
-static inline s32 e1000_read_nvm(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
+static inline s32 e1000_read_nvm(struct e1000_hw *hw, u16 offset, u16 words,
+				 u16 *data)
 {
 	return hw->nvm.ops.read(hw, offset, words, data);
 }
 
-static inline s32 e1000_write_nvm(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
+static inline s32 e1000_write_nvm(struct e1000_hw *hw, u16 offset, u16 words,
+				  u16 *data)
 {
 	return hw->nvm.ops.write(hw, offset, words, data);
 }
@@ -597,7 +600,7 @@ static inline s32 __ew32_prepare(struct e1000_hw *hw)
 	s32 i = E1000_ICH_FWSM_PCIM2PCI_COUNT;
 
 	while ((er32(FWSM) & E1000_ICH_FWSM_PCIM2PCI) && --i)
-		udelay(50);
+		usleep_range(50, 100);
 
 	return i;
 }
diff --git a/drivers/net/ethernet/intel/e1000e/ethtool.c b/drivers/net/ethernet/intel/e1000e/ethtool.c
index f91a8f3..7c8ca65 100644
--- a/drivers/net/ethernet/intel/e1000e/ethtool.c
+++ b/drivers/net/ethernet/intel/e1000e/ethtool.c
@@ -35,12 +35,11 @@
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/vmalloc.h>
-#include <linux/mdio.h>
 #include <linux/pm_runtime.h>
 
 #include "e1000.h"
 
-enum {NETDEV_STATS, E1000_STATS};
+enum { NETDEV_STATS, E1000_STATS };
 
 struct e1000_stats {
 	char stat_string[ETH_GSTRING_LEN];
@@ -121,6 +120,7 @@ static const char e1000_gstrings_test[][ETH_GSTRING_LEN] = {
 	"Interrupt test (offline)", "Loopback test  (offline)",
 	"Link test   (on/offline)"
 };
+
 #define E1000_TEST_LEN ARRAY_SIZE(e1000_gstrings_test)
 
 static int e1000_get_settings(struct net_device *netdev,
@@ -197,8 +197,7 @@ static int e1000_get_settings(struct net_device *netdev,
 	/* MDI-X => 2; MDI =>1; Invalid =>0 */
 	if ((hw->phy.media_type == e1000_media_type_copper) &&
 	    netif_carrier_ok(netdev))
-		ecmd->eth_tp_mdix = hw->phy.is_mdix ? ETH_TP_MDI_X :
-		                                      ETH_TP_MDI;
+		ecmd->eth_tp_mdix = hw->phy.is_mdix ? ETH_TP_MDI_X : ETH_TP_MDI;
 	else
 		ecmd->eth_tp_mdix = ETH_TP_MDI_INVALID;
 
@@ -224,8 +223,7 @@ static int e1000_set_spd_dplx(struct e1000_adapter *adapter, u32 spd, u8 dplx)
 
 	/* Fiber NICs only allow 1000 gbps Full duplex */
 	if ((adapter->hw.phy.media_type == e1000_media_type_fiber) &&
-	    spd != SPEED_1000 &&
-	    dplx != DUPLEX_FULL) {
+	    (spd != SPEED_1000) && (dplx != DUPLEX_FULL)) {
 		goto err_inval;
 	}
 
@@ -298,12 +296,10 @@ static int e1000_set_settings(struct net_device *netdev,
 		hw->mac.autoneg = 1;
 		if (hw->phy.media_type == e1000_media_type_fiber)
 			hw->phy.autoneg_advertised = ADVERTISED_1000baseT_Full |
-						     ADVERTISED_FIBRE |
-						     ADVERTISED_Autoneg;
+			    ADVERTISED_FIBRE | ADVERTISED_Autoneg;
 		else
 			hw->phy.autoneg_advertised = ecmd->advertising |
-						     ADVERTISED_TP |
-						     ADVERTISED_Autoneg;
+			    ADVERTISED_TP | ADVERTISED_Autoneg;
 		ecmd->advertising = hw->phy.autoneg_advertised;
 		if (adapter->fc_autoneg)
 			hw->fc.requested_mode = e1000_fc_default;
@@ -346,7 +342,7 @@ static void e1000_get_pauseparam(struct net_device *netdev,
 	struct e1000_hw *hw = &adapter->hw;
 
 	pause->autoneg =
-		(adapter->fc_autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE);
+	    (adapter->fc_autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE);
 
 	if (hw->fc.current_mode == e1000_fc_rx_pause) {
 		pause->rx_pause = 1;
@@ -435,7 +431,7 @@ static void e1000_get_regs(struct net_device *netdev,
 	memset(p, 0, E1000_REGS_LEN * sizeof(u32));
 
 	regs->version = (1 << 24) | (adapter->pdev->revision << 16) |
-			adapter->pdev->device;
+	    adapter->pdev->device;
 
 	regs_buff[0]  = er32(CTRL);
 	regs_buff[1]  = er32(STATUS);
@@ -503,8 +499,8 @@ static int e1000_get_eeprom(struct net_device *netdev,
 	first_word = eeprom->offset >> 1;
 	last_word = (eeprom->offset + eeprom->len - 1) >> 1;
 
-	eeprom_buff = kmalloc(sizeof(u16) *
-			(last_word - first_word + 1), GFP_KERNEL);
+	eeprom_buff = kmalloc(sizeof(u16) * (last_word - first_word + 1),
+			      GFP_KERNEL);
 	if (!eeprom_buff)
 		return -ENOMEM;
 
@@ -515,7 +511,7 @@ static int e1000_get_eeprom(struct net_device *netdev,
 	} else {
 		for (i = 0; i < last_word - first_word + 1; i++) {
 			ret_val = e1000_read_nvm(hw, first_word + i, 1,
-						      &eeprom_buff[i]);
+						 &eeprom_buff[i]);
 			if (ret_val)
 				break;
 		}
@@ -553,7 +549,8 @@ static int e1000_set_eeprom(struct net_device *netdev,
 	if (eeprom->len == 0)
 		return -EOPNOTSUPP;
 
-	if (eeprom->magic != (adapter->pdev->vendor | (adapter->pdev->device << 16)))
+	if (eeprom->magic !=
+	    (adapter->pdev->vendor | (adapter->pdev->device << 16)))
 		return -EFAULT;
 
 	if (adapter->flags & FLAG_READ_ONLY_NVM)
@@ -579,7 +576,7 @@ static int e1000_set_eeprom(struct net_device *netdev,
 		/* need read/modify/write of last changed EEPROM word */
 		/* only the first byte of the word is being modified */
 		ret_val = e1000_read_nvm(hw, last_word, 1,
-				  &eeprom_buff[last_word - first_word]);
+					 &eeprom_buff[last_word - first_word]);
 
 	if (ret_val)
 		goto out;
@@ -618,8 +615,7 @@ static void e1000_get_drvinfo(struct net_device *netdev,
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 
-	strlcpy(drvinfo->driver,  e1000e_driver_name,
-		sizeof(drvinfo->driver));
+	strlcpy(drvinfo->driver, e1000e_driver_name, sizeof(drvinfo->driver));
 	strlcpy(drvinfo->version, e1000e_driver_version,
 		sizeof(drvinfo->version));
 
@@ -627,10 +623,10 @@ static void e1000_get_drvinfo(struct net_device *netdev,
 	 * PCI-E controllers
 	 */
 	snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
-		"%d.%d-%d",
-		(adapter->eeprom_vers & 0xF000) >> 12,
-		(adapter->eeprom_vers & 0x0FF0) >> 4,
-		(adapter->eeprom_vers & 0x000F));
+		 "%d.%d-%d",
+		 (adapter->eeprom_vers & 0xF000) >> 12,
+		 (adapter->eeprom_vers & 0x0FF0) >> 4,
+		 (adapter->eeprom_vers & 0x000F));
 
 	strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
 		sizeof(drvinfo->bus_info));
@@ -756,7 +752,8 @@ static bool reg_pattern_test(struct e1000_adapter *adapter, u64 *data,
 {
 	u32 pat, val;
 	static const u32 test[] = {
-		0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF};
+		0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF
+	};
 	for (pat = 0; pat < ARRAY_SIZE(test); pat++) {
 		E1000_WRITE_REG_ARRAY(&adapter->hw, reg, offset,
 				      (test[pat] & write));
@@ -786,6 +783,7 @@ static bool reg_set_and_check(struct e1000_adapter *adapter, u64 *data,
 	}
 	return 0;
 }
+
 #define REG_PATTERN_TEST_ARRAY(reg, offset, mask, write)                       \
 	do {                                                                   \
 		if (reg_pattern_test(adapter, data, reg, offset, mask, write)) \
@@ -813,16 +811,16 @@ static int e1000_reg_test(struct e1000_adapter *adapter, u64 *data)
 	u32 wlock_mac = 0;
 
 	/* The status register is Read Only, so a write should fail.
-	 * Some bits that get toggled are ignored.
+	 * Some bits that get toggled are ignored.  There are several bits
+	 * on newer hardware that are r/w.
 	 */
 	switch (mac->type) {
-	/* there are several bits on newer hardware that are r/w */
 	case e1000_82571:
 	case e1000_82572:
 	case e1000_80003es2lan:
 		toggle = 0x7FFFF3FF;
 		break;
-        default:
+	default:
 		toggle = 0x7FFFF033;
 		break;
 	}
@@ -928,7 +926,7 @@ static int e1000_eeprom_test(struct e1000_adapter *adapter, u64 *data)
 	}
 
 	/* If Checksum is not Correct return error else test passed */
-	if ((checksum != (u16) NVM_SUM) && !(*data))
+	if ((checksum != (u16)NVM_SUM) && !(*data))
 		*data = 2;
 
 	return *data;
@@ -936,7 +934,7 @@ static int e1000_eeprom_test(struct e1000_adapter *adapter, u64 *data)
 
 static irqreturn_t e1000_test_intr(int __always_unused irq, void *data)
 {
-	struct net_device *netdev = (struct net_device *) data;
+	struct net_device *netdev = (struct net_device *)data;
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 	struct e1000_hw *hw = &adapter->hw;
 
@@ -969,8 +967,8 @@ static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data)
 	if (!request_irq(irq, e1000_test_intr, IRQF_PROBE_SHARED, netdev->name,
 			 netdev)) {
 		shared_int = 0;
-	} else if (request_irq(irq, e1000_test_intr, IRQF_SHARED,
-		 netdev->name, netdev)) {
+	} else if (request_irq(irq, e1000_test_intr, IRQF_SHARED, netdev->name,
+			       netdev)) {
 		*data = 1;
 		ret_val = -1;
 		goto out;
@@ -1080,28 +1078,33 @@ static void e1000_free_desc_rings(struct e1000_adapter *adapter)
 	struct e1000_ring *tx_ring = &adapter->test_tx_ring;
 	struct e1000_ring *rx_ring = &adapter->test_rx_ring;
 	struct pci_dev *pdev = adapter->pdev;
+	struct e1000_buffer *buffer_info;
 	int i;
 
 	if (tx_ring->desc && tx_ring->buffer_info) {
 		for (i = 0; i < tx_ring->count; i++) {
-			if (tx_ring->buffer_info[i].dma)
+			buffer_info = &tx_ring->buffer_info[i];
+
+			if (buffer_info->dma)
 				dma_unmap_single(&pdev->dev,
-					tx_ring->buffer_info[i].dma,
-					tx_ring->buffer_info[i].length,
-					DMA_TO_DEVICE);
-			if (tx_ring->buffer_info[i].skb)
-				dev_kfree_skb(tx_ring->buffer_info[i].skb);
+						 buffer_info->dma,
+						 buffer_info->length,
+						 DMA_TO_DEVICE);
+			if (buffer_info->skb)
+				dev_kfree_skb(buffer_info->skb);
 		}
 	}
 
 	if (rx_ring->desc && rx_ring->buffer_info) {
 		for (i = 0; i < rx_ring->count; i++) {
-			if (rx_ring->buffer_info[i].dma)
+			buffer_info = &rx_ring->buffer_info[i];
+
+			if (buffer_info->dma)
 				dma_unmap_single(&pdev->dev,
-					rx_ring->buffer_info[i].dma,
-					2048, DMA_FROM_DEVICE);
-			if (rx_ring->buffer_info[i].skb)
-				dev_kfree_skb(rx_ring->buffer_info[i].skb);
+						 buffer_info->dma,
+						 2048, DMA_FROM_DEVICE);
+			if (buffer_info->skb)
+				dev_kfree_skb(buffer_info->skb);
 		}
 	}
 
@@ -1138,8 +1141,7 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
 		tx_ring->count = E1000_DEFAULT_TXD;
 
 	tx_ring->buffer_info = kcalloc(tx_ring->count,
-				       sizeof(struct e1000_buffer),
-				       GFP_KERNEL);
+				       sizeof(struct e1000_buffer), GFP_KERNEL);
 	if (!tx_ring->buffer_info) {
 		ret_val = 1;
 		goto err_nomem;
@@ -1156,8 +1158,8 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
 	tx_ring->next_to_use = 0;
 	tx_ring->next_to_clean = 0;
 
-	ew32(TDBAL(0), ((u64) tx_ring->dma & 0x00000000FFFFFFFF));
-	ew32(TDBAH(0), ((u64) tx_ring->dma >> 32));
+	ew32(TDBAL(0), ((u64)tx_ring->dma & 0x00000000FFFFFFFF));
+	ew32(TDBAH(0), ((u64)tx_ring->dma >> 32));
 	ew32(TDLEN(0), tx_ring->count * sizeof(struct e1000_tx_desc));
 	ew32(TDH(0), 0);
 	ew32(TDT(0), 0);
@@ -1179,8 +1181,8 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
 		tx_ring->buffer_info[i].skb = skb;
 		tx_ring->buffer_info[i].length = skb->len;
 		tx_ring->buffer_info[i].dma =
-			dma_map_single(&pdev->dev, skb->data, skb->len,
-				       DMA_TO_DEVICE);
+		    dma_map_single(&pdev->dev, skb->data, skb->len,
+				   DMA_TO_DEVICE);
 		if (dma_mapping_error(&pdev->dev,
 				      tx_ring->buffer_info[i].dma)) {
 			ret_val = 4;
@@ -1200,8 +1202,7 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
 		rx_ring->count = E1000_DEFAULT_RXD;
 
 	rx_ring->buffer_info = kcalloc(rx_ring->count,
-				       sizeof(struct e1000_buffer),
-				       GFP_KERNEL);
+				       sizeof(struct e1000_buffer), GFP_KERNEL);
 	if (!rx_ring->buffer_info) {
 		ret_val = 5;
 		goto err_nomem;
@@ -1220,16 +1221,16 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
 	rctl = er32(RCTL);
 	if (!(adapter->flags2 & FLAG2_NO_DISABLE_RX))
 		ew32(RCTL, rctl & ~E1000_RCTL_EN);
-	ew32(RDBAL(0), ((u64) rx_ring->dma & 0xFFFFFFFF));
-	ew32(RDBAH(0), ((u64) rx_ring->dma >> 32));
+	ew32(RDBAL(0), ((u64)rx_ring->dma & 0xFFFFFFFF));
+	ew32(RDBAH(0), ((u64)rx_ring->dma >> 32));
 	ew32(RDLEN(0), rx_ring->size);
 	ew32(RDH(0), 0);
 	ew32(RDT(0), 0);
 	rctl = E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_SZ_2048 |
-		E1000_RCTL_UPE | E1000_RCTL_MPE | E1000_RCTL_LPE |
-		E1000_RCTL_SBP | E1000_RCTL_SECRC |
-		E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF |
-		(adapter->hw.mac.mc_filter_type << E1000_RCTL_MO_SHIFT);
+	    E1000_RCTL_UPE | E1000_RCTL_MPE | E1000_RCTL_LPE |
+	    E1000_RCTL_SBP | E1000_RCTL_SECRC |
+	    E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF |
+	    (adapter->hw.mac.mc_filter_type << E1000_RCTL_MO_SHIFT);
 	ew32(RCTL, rctl);
 
 	for (i = 0; i < rx_ring->count; i++) {
@@ -1244,8 +1245,8 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
 		skb_reserve(skb, NET_IP_ALIGN);
 		rx_ring->buffer_info[i].skb = skb;
 		rx_ring->buffer_info[i].dma =
-			dma_map_single(&pdev->dev, skb->data, 2048,
-				       DMA_FROM_DEVICE);
+		    dma_map_single(&pdev->dev, skb->data, 2048,
+				   DMA_FROM_DEVICE);
 		if (dma_mapping_error(&pdev->dev,
 				      rx_ring->buffer_info[i].dma)) {
 			ret_val = 8;
@@ -1296,7 +1297,7 @@ static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
 
 		ew32(CTRL, ctrl_reg);
 		e1e_flush();
-		udelay(500);
+		usleep_range(500, 1000);
 
 		return 0;
 	}
@@ -1322,7 +1323,7 @@ static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
 		e1e_wphy(hw, PHY_REG(2, 21), phy_reg);
 		/* Assert SW reset for above settings to take effect */
 		hw->phy.ops.commit(hw);
-		mdelay(1);
+		usleep_range(1000, 2000);
 		/* Force Full Duplex */
 		e1e_rphy(hw, PHY_REG(769, 16), &phy_reg);
 		e1e_wphy(hw, PHY_REG(769, 16), phy_reg | 0x000C);
@@ -1363,7 +1364,7 @@ static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
 
 	/* force 1000, set loopback */
 	e1e_wphy(hw, MII_BMCR, 0x4140);
-	mdelay(250);
+	msleep(250);
 
 	/* Now set up the MAC to the same speed/duplex as the PHY. */
 	ctrl_reg = er32(CTRL);
@@ -1395,7 +1396,7 @@ static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
 	if (hw->phy.type == e1000_phy_m88)
 		e1000_phy_disable_receiver(adapter);
 
-	udelay(500);
+	usleep_range(500, 1000);
 
 	return 0;
 }
@@ -1431,8 +1432,7 @@ static int e1000_set_82571_fiber_loopback(struct e1000_adapter *adapter)
 	/* special write to serdes control register to enable SerDes analog
 	 * loopback
 	 */
-#define E1000_SERDES_LB_ON 0x410
-	ew32(SCTL, E1000_SERDES_LB_ON);
+	ew32(SCTL, E1000_SCTL_ENABLE_SERDES_LOOPBACK);
 	e1e_flush();
 	usleep_range(10000, 20000);
 
@@ -1526,8 +1526,7 @@ static void e1000_loopback_cleanup(struct e1000_adapter *adapter)
 	case e1000_82572:
 		if (hw->phy.media_type == e1000_media_type_fiber ||
 		    hw->phy.media_type == e1000_media_type_internal_serdes) {
-#define E1000_SERDES_LB_OFF 0x400
-			ew32(SCTL, E1000_SERDES_LB_OFF);
+			ew32(SCTL, E1000_SCTL_DISABLE_SERDES_LOOPBACK);
 			e1e_flush();
 			usleep_range(10000, 20000);
 			break;
@@ -1564,7 +1563,7 @@ static int e1000_check_lbtest_frame(struct sk_buff *skb,
 	frame_size &= ~1;
 	if (*(skb->data + 3) == 0xFF)
 		if ((*(skb->data + frame_size / 2 + 10) == 0xBE) &&
-		   (*(skb->data + frame_size / 2 + 12) == 0xAF))
+		    (*(skb->data + frame_size / 2 + 12) == 0xAF))
 			return 0;
 	return 13;
 }
@@ -1575,6 +1574,7 @@ static int e1000_run_loopback_test(struct e1000_adapter *adapter)
 	struct e1000_ring *rx_ring = &adapter->test_rx_ring;
 	struct pci_dev *pdev = adapter->pdev;
 	struct e1000_hw *hw = &adapter->hw;
+	struct e1000_buffer *buffer_info;
 	int i, j, k, l;
 	int lc;
 	int good_cnt;
@@ -1595,14 +1595,17 @@ static int e1000_run_loopback_test(struct e1000_adapter *adapter)
 
 	k = 0;
 	l = 0;
-	for (j = 0; j <= lc; j++) { /* loop count loop */
-		for (i = 0; i < 64; i++) { /* send the packets */
-			e1000_create_lbtest_frame(tx_ring->buffer_info[k].skb,
-						  1024);
+	/* loop count loop */
+	for (j = 0; j <= lc; j++) {
+		/* send the packets */
+		for (i = 0; i < 64; i++) {
+			buffer_info = &tx_ring->buffer_info[k];
+
+			e1000_create_lbtest_frame(buffer_info->skb, 1024);
 			dma_sync_single_for_device(&pdev->dev,
-					tx_ring->buffer_info[k].dma,
-					tx_ring->buffer_info[k].length,
-					DMA_TO_DEVICE);
+						   buffer_info->dma,
+						   buffer_info->length,
+						   DMA_TO_DEVICE);
 			k++;
 			if (k == tx_ring->count)
 				k = 0;
@@ -1612,13 +1615,16 @@ static int e1000_run_loopback_test(struct e1000_adapter *adapter)
 		msleep(200);
 		time = jiffies; /* set the start time for the receive */
 		good_cnt = 0;
-		do { /* receive the sent packets */
+		/* receive the sent packets */
+		do {
+			buffer_info = &rx_ring->buffer_info[l];
+
 			dma_sync_single_for_cpu(&pdev->dev,
-					rx_ring->buffer_info[l].dma, 2048,
-					DMA_FROM_DEVICE);
+						buffer_info->dma, 2048,
+						DMA_FROM_DEVICE);
 
-			ret_val = e1000_check_lbtest_frame(
-					rx_ring->buffer_info[l].skb, 1024);
+			ret_val = e1000_check_lbtest_frame(buffer_info->skb,
+							   1024);
 			if (!ret_val)
 				good_cnt++;
 			l++;
@@ -1637,7 +1643,7 @@ static int e1000_run_loopback_test(struct e1000_adapter *adapter)
 			ret_val = 14; /* error code for time out error */
 			break;
 		}
-	} /* end loop count loop */
+	}
 	return ret_val;
 }
 
@@ -1696,7 +1702,7 @@ static int e1000_link_test(struct e1000_adapter *adapter, u64 *data)
 			/* On some Phy/switch combinations, link establishment
 			 * can take a few seconds more than expected.
 			 */
-			msleep(5000);
+			msleep_interruptible(5000);
 
 		if (!(er32(STATUS) & E1000_STATUS_LU))
 			*data = 1;
@@ -1980,12 +1986,12 @@ static void e1000_get_ethtool_stats(struct net_device *netdev,
 	for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++) {
 		switch (e1000_gstrings_stats[i].type) {
 		case NETDEV_STATS:
-			p = (char *) &net_stats +
-					e1000_gstrings_stats[i].stat_offset;
+			p = (char *)&net_stats +
+			    e1000_gstrings_stats[i].stat_offset;
 			break;
 		case E1000_STATS:
-			p = (char *) adapter +
-					e1000_gstrings_stats[i].stat_offset;
+			p = (char *)adapter +
+			    e1000_gstrings_stats[i].stat_offset;
 			break;
 		default:
 			data[i] = 0;
@@ -1993,7 +1999,7 @@ static void e1000_get_ethtool_stats(struct net_device *netdev,
 		}
 
 		data[i] = (e1000_gstrings_stats[i].sizeof_stat ==
-			sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
+			   sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
 	}
 }
 
@@ -2069,23 +2075,20 @@ static int e1000e_get_eee(struct net_device *netdev, struct ethtool_eee *edata)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 	struct e1000_hw *hw = &adapter->hw;
-	u16 cap_addr, adv_addr, lpa_addr, pcs_stat_addr, phy_data, lpi_ctrl;
-	u32 status, ret_val;
+	u16 cap_addr, lpa_addr, pcs_stat_addr, phy_data;
+	u32 ret_val;
 
-	if (!(adapter->flags & FLAG_IS_ICH) ||
-	    !(adapter->flags2 & FLAG2_HAS_EEE))
+	if (!(adapter->flags2 & FLAG2_HAS_EEE))
 		return -EOPNOTSUPP;
 
 	switch (hw->phy.type) {
 	case e1000_phy_82579:
 		cap_addr = I82579_EEE_CAPABILITY;
-		adv_addr = I82579_EEE_ADVERTISEMENT;
 		lpa_addr = I82579_EEE_LP_ABILITY;
 		pcs_stat_addr = I82579_EEE_PCS_STATUS;
 		break;
 	case e1000_phy_i217:
 		cap_addr = I217_EEE_CAPABILITY;
-		adv_addr = I217_EEE_ADVERTISEMENT;
 		lpa_addr = I217_EEE_LP_ABILITY;
 		pcs_stat_addr = I217_EEE_PCS_STATUS;
 		break;
@@ -2104,10 +2107,7 @@ static int e1000e_get_eee(struct net_device *netdev, struct ethtool_eee *edata)
 	edata->supported = mmd_eee_cap_to_ethtool_sup_t(phy_data);
 
 	/* EEE Advertised */
-	ret_val = e1000_read_emi_reg_locked(hw, adv_addr, &phy_data);
-	if (ret_val)
-		goto release;
-	edata->advertised = mmd_eee_adv_to_ethtool_adv_t(phy_data);
+	edata->advertised = mmd_eee_adv_to_ethtool_adv_t(adapter->eee_advert);
 
 	/* EEE Link Partner Advertised */
 	ret_val = e1000_read_emi_reg_locked(hw, lpa_addr, &phy_data);
@@ -2125,25 +2125,11 @@ release:
 	if (ret_val)
 		return -ENODATA;
 
-	e1e_rphy(hw, I82579_LPI_CTRL, &lpi_ctrl);
-	status = er32(STATUS);
-
 	/* Result of the EEE auto negotiation - there is no register that
 	 * has the status of the EEE negotiation so do a best-guess based
-	 * on whether both Tx and Rx LPI indications have been received or
-	 * base it on the link speed, the EEE advertised speeds on both ends
-	 * and the speeds on which EEE is enabled locally.
+	 * on whether Tx or Rx LPI indications have been received.
 	 */
-	if (((phy_data & E1000_EEE_TX_LPI_RCVD) &&
-	     (phy_data & E1000_EEE_RX_LPI_RCVD)) ||
-	    ((status & E1000_STATUS_SPEED_100) &&
-	     (edata->advertised & ADVERTISED_100baseT_Full) &&
-	     (edata->lp_advertised & ADVERTISED_100baseT_Full) &&
-	     (lpi_ctrl & I82579_LPI_CTRL_100_ENABLE)) ||
-	    ((status & E1000_STATUS_SPEED_1000) &&
-	     (edata->advertised & ADVERTISED_1000baseT_Full) &&
-	     (edata->lp_advertised & ADVERTISED_1000baseT_Full) &&
-	     (lpi_ctrl & I82579_LPI_CTRL_1000_ENABLE)))
+	if (phy_data & (E1000_EEE_TX_LPI_RCVD | E1000_EEE_RX_LPI_RCVD))
 		edata->eee_active = true;
 
 	edata->eee_enabled = !hw->dev_spec.ich8lan.eee_disable;
@@ -2160,19 +2146,10 @@ static int e1000e_set_eee(struct net_device *netdev, struct ethtool_eee *edata)
 	struct ethtool_eee eee_curr;
 	s32 ret_val;
 
-	if (!(adapter->flags & FLAG_IS_ICH) ||
-	    !(adapter->flags2 & FLAG2_HAS_EEE))
-		return -EOPNOTSUPP;
-
 	ret_val = e1000e_get_eee(netdev, &eee_curr);
 	if (ret_val)
 		return ret_val;
 
-	if (eee_curr.advertised != edata->advertised) {
-		e_err("Setting EEE advertisement is not supported\n");
-		return -EINVAL;
-	}
-
 	if (eee_curr.tx_lpi_enabled != edata->tx_lpi_enabled) {
 		e_err("Setting EEE tx-lpi is not supported\n");
 		return -EINVAL;
@@ -2183,16 +2160,21 @@ static int e1000e_set_eee(struct net_device *netdev, struct ethtool_eee *edata)
 		return -EINVAL;
 	}
 
-	if (hw->dev_spec.ich8lan.eee_disable != !edata->eee_enabled) {
-		hw->dev_spec.ich8lan.eee_disable = !edata->eee_enabled;
-
-		/* reset the link */
-		if (netif_running(netdev))
-			e1000e_reinit_locked(adapter);
-		else
-			e1000e_reset(adapter);
+	if (edata->advertised & ~(ADVERTISE_100_FULL | ADVERTISE_1000_FULL)) {
+		e_err("EEE advertisement supports only 100TX and/or 1000T full-duplex\n");
+		return -EINVAL;
 	}
 
+	adapter->eee_advert = ethtool_adv_to_mmd_eee_adv_t(edata->advertised);
+
+	hw->dev_spec.ich8lan.eee_disable = !edata->eee_enabled;
+
+	/* reset the link */
+	if (netif_running(netdev))
+		e1000e_reinit_locked(adapter);
+	else
+		e1000e_reset(adapter);
+
 	return 0;
 }
 
diff --git a/drivers/net/ethernet/intel/e1000e/hw.h b/drivers/net/ethernet/intel/e1000e/hw.h
index 1e6b889..84850f7 100644
--- a/drivers/net/ethernet/intel/e1000e/hw.h
+++ b/drivers/net/ethernet/intel/e1000e/hw.h
@@ -167,7 +167,7 @@ enum e1000_1000t_rx_status {
 	e1000_1000t_rx_status_undefined = 0xFF
 };
 
-enum e1000_rev_polarity{
+enum e1000_rev_polarity {
 	e1000_rev_polarity_normal = 0,
 	e1000_rev_polarity_reversed,
 	e1000_rev_polarity_undefined = 0xFF
@@ -545,7 +545,7 @@ struct e1000_mac_info {
 	u16 mta_reg_count;
 
 	/* Maximum size of the MTA register table in all supported adapters */
-	#define MAX_MTA_REG 128
+#define MAX_MTA_REG 128
 	u32 mta_shadow[MAX_MTA_REG];
 	u16 rar_entry_count;
 
diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.c b/drivers/net/ethernet/intel/e1000e/ich8lan.c
index 121a865..ad9d8f2 100644
--- a/drivers/net/ethernet/intel/e1000e/ich8lan.c
+++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c
@@ -61,15 +61,15 @@
 /* Offset 04h HSFSTS */
 union ich8_hws_flash_status {
 	struct ich8_hsfsts {
-		u16 flcdone    :1; /* bit 0 Flash Cycle Done */
-		u16 flcerr     :1; /* bit 1 Flash Cycle Error */
-		u16 dael       :1; /* bit 2 Direct Access error Log */
-		u16 berasesz   :2; /* bit 4:3 Sector Erase Size */
-		u16 flcinprog  :1; /* bit 5 flash cycle in Progress */
-		u16 reserved1  :2; /* bit 13:6 Reserved */
-		u16 reserved2  :6; /* bit 13:6 Reserved */
-		u16 fldesvalid :1; /* bit 14 Flash Descriptor Valid */
-		u16 flockdn    :1; /* bit 15 Flash Config Lock-Down */
+		u16 flcdone:1;	/* bit 0 Flash Cycle Done */
+		u16 flcerr:1;	/* bit 1 Flash Cycle Error */
+		u16 dael:1;	/* bit 2 Direct Access error Log */
+		u16 berasesz:2;	/* bit 4:3 Sector Erase Size */
+		u16 flcinprog:1;	/* bit 5 flash cycle in Progress */
+		u16 reserved1:2;	/* bit 13:6 Reserved */
+		u16 reserved2:6;	/* bit 13:6 Reserved */
+		u16 fldesvalid:1;	/* bit 14 Flash Descriptor Valid */
+		u16 flockdn:1;	/* bit 15 Flash Config Lock-Down */
 	} hsf_status;
 	u16 regval;
 };
@@ -78,11 +78,11 @@ union ich8_hws_flash_status {
 /* Offset 06h FLCTL */
 union ich8_hws_flash_ctrl {
 	struct ich8_hsflctl {
-		u16 flcgo      :1;   /* 0 Flash Cycle Go */
-		u16 flcycle    :2;   /* 2:1 Flash Cycle */
-		u16 reserved   :5;   /* 7:3 Reserved  */
-		u16 fldbcount  :2;   /* 9:8 Flash Data Byte Count */
-		u16 flockdn    :6;   /* 15:10 Reserved */
+		u16 flcgo:1;	/* 0 Flash Cycle Go */
+		u16 flcycle:2;	/* 2:1 Flash Cycle */
+		u16 reserved:5;	/* 7:3 Reserved  */
+		u16 fldbcount:2;	/* 9:8 Flash Data Byte Count */
+		u16 flockdn:6;	/* 15:10 Reserved */
 	} hsf_ctrl;
 	u16 regval;
 };
@@ -90,10 +90,10 @@ union ich8_hws_flash_ctrl {
 /* ICH Flash Region Access Permissions */
 union ich8_hws_flash_regacc {
 	struct ich8_flracc {
-		u32 grra      :8; /* 0:7 GbE region Read Access */
-		u32 grwa      :8; /* 8:15 GbE region Write Access */
-		u32 gmrag     :8; /* 23:16 GbE Master Read Access Grant */
-		u32 gmwag     :8; /* 31:24 GbE Master Write Access Grant */
+		u32 grra:8;	/* 0:7 GbE region Read Access */
+		u32 grwa:8;	/* 8:15 GbE region Write Access */
+		u32 gmrag:8;	/* 23:16 GbE Master Read Access Grant */
+		u32 gmwag:8;	/* 31:24 GbE Master Write Access Grant */
 	} hsf_flregacc;
 	u16 regval;
 };
@@ -142,6 +142,7 @@ static void e1000_rar_set_pch2lan(struct e1000_hw *hw, u8 *addr, u32 index);
 static void e1000_rar_set_pch_lpt(struct e1000_hw *hw, u8 *addr, u32 index);
 static s32 e1000_k1_workaround_lv(struct e1000_hw *hw);
 static void e1000_gate_hw_phy_config_ich8lan(struct e1000_hw *hw, bool gate);
+static s32 e1000_setup_copper_link_pch_lpt(struct e1000_hw *hw);
 
 static inline u16 __er16flash(struct e1000_hw *hw, unsigned long reg)
 {
@@ -312,7 +313,7 @@ static s32 e1000_init_phy_workarounds_pchlan(struct e1000_hw *hw)
 		mac_reg &= ~E1000_CTRL_LANPHYPC_VALUE;
 		ew32(CTRL, mac_reg);
 		e1e_flush();
-		udelay(10);
+		usleep_range(10, 20);
 		mac_reg &= ~E1000_CTRL_LANPHYPC_OVERRIDE;
 		ew32(CTRL, mac_reg);
 		e1e_flush();
@@ -548,8 +549,8 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw)
 	/* find total size of the NVM, then cut in half since the total
 	 * size represents two separate NVM banks.
 	 */
-	nvm->flash_bank_size = (sector_end_addr - sector_base_addr)
-				<< FLASH_SECTOR_ADDR_SHIFT;
+	nvm->flash_bank_size = ((sector_end_addr - sector_base_addr)
+				<< FLASH_SECTOR_ADDR_SHIFT);
 	nvm->flash_bank_size /= 2;
 	/* Adjust to word count */
 	nvm->flash_bank_size /= sizeof(u16);
@@ -636,6 +637,8 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw)
 	if (mac->type == e1000_pch_lpt) {
 		mac->rar_entry_count = E1000_PCH_LPT_RAR_ENTRIES;
 		mac->ops.rar_set = e1000_rar_set_pch_lpt;
+		mac->ops.setup_physical_interface =
+		    e1000_setup_copper_link_pch_lpt;
 	}
 
 	/* Enable PCS Lock-loss workaround for ICH8 */
@@ -692,7 +695,7 @@ s32 e1000_read_emi_reg_locked(struct e1000_hw *hw, u16 addr, u16 *data)
  *
  *  Assumes the SW/FW/HW Semaphore is already acquired.
  **/
-static s32 e1000_write_emi_reg_locked(struct e1000_hw *hw, u16 addr, u16 data)
+s32 e1000_write_emi_reg_locked(struct e1000_hw *hw, u16 addr, u16 data)
 {
 	return __e1000_access_emi_reg_locked(hw, addr, &data, false);
 }
@@ -709,11 +712,22 @@ static s32 e1000_set_eee_pchlan(struct e1000_hw *hw)
 {
 	struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
 	s32 ret_val;
-	u16 lpi_ctrl;
+	u16 lpa, pcs_status, adv, adv_addr, lpi_ctrl, data;
 
-	if ((hw->phy.type != e1000_phy_82579) &&
-	    (hw->phy.type != e1000_phy_i217))
+	switch (hw->phy.type) {
+	case e1000_phy_82579:
+		lpa = I82579_EEE_LP_ABILITY;
+		pcs_status = I82579_EEE_PCS_STATUS;
+		adv_addr = I82579_EEE_ADVERTISEMENT;
+		break;
+	case e1000_phy_i217:
+		lpa = I217_EEE_LP_ABILITY;
+		pcs_status = I217_EEE_PCS_STATUS;
+		adv_addr = I217_EEE_ADVERTISEMENT;
+		break;
+	default:
 		return 0;
+	}
 
 	ret_val = hw->phy.ops.acquire(hw);
 	if (ret_val)
@@ -728,34 +742,24 @@ static s32 e1000_set_eee_pchlan(struct e1000_hw *hw)
 
 	/* Enable EEE if not disabled by user */
 	if (!dev_spec->eee_disable) {
-		u16 lpa, pcs_status, data;
-
 		/* Save off link partner's EEE ability */
-		switch (hw->phy.type) {
-		case e1000_phy_82579:
-			lpa = I82579_EEE_LP_ABILITY;
-			pcs_status = I82579_EEE_PCS_STATUS;
-			break;
-		case e1000_phy_i217:
-			lpa = I217_EEE_LP_ABILITY;
-			pcs_status = I217_EEE_PCS_STATUS;
-			break;
-		default:
-			ret_val = -E1000_ERR_PHY;
-			goto release;
-		}
 		ret_val = e1000_read_emi_reg_locked(hw, lpa,
 						    &dev_spec->eee_lp_ability);
 		if (ret_val)
 			goto release;
 
+		/* Read EEE advertisement */
+		ret_val = e1000_read_emi_reg_locked(hw, adv_addr, &adv);
+		if (ret_val)
+			goto release;
+
 		/* Enable EEE only for speeds in which the link partner is
-		 * EEE capable.
+		 * EEE capable and for which we advertise EEE.
 		 */
-		if (dev_spec->eee_lp_ability & I82579_EEE_1000_SUPPORTED)
+		if (adv & dev_spec->eee_lp_ability & I82579_EEE_1000_SUPPORTED)
 			lpi_ctrl |= I82579_LPI_CTRL_1000_ENABLE;
 
-		if (dev_spec->eee_lp_ability & I82579_EEE_100_SUPPORTED) {
+		if (adv & dev_spec->eee_lp_ability & I82579_EEE_100_SUPPORTED) {
 			e1e_rphy_locked(hw, MII_LPA, &data);
 			if (data & LPA_100FULL)
 				lpi_ctrl |= I82579_LPI_CTRL_100_ENABLE;
@@ -767,13 +771,13 @@ static s32 e1000_set_eee_pchlan(struct e1000_hw *hw)
 				dev_spec->eee_lp_ability &=
 				    ~I82579_EEE_100_SUPPORTED;
 		}
-
-		/* R/Clr IEEE MMD 3.1 bits 11:10 - Tx/Rx LPI Received */
-		ret_val = e1000_read_emi_reg_locked(hw, pcs_status, &data);
-		if (ret_val)
-			goto release;
 	}
 
+	/* R/Clr IEEE MMD 3.1 bits 11:10 - Tx/Rx LPI Received */
+	ret_val = e1000_read_emi_reg_locked(hw, pcs_status, &data);
+	if (ret_val)
+		goto release;
+
 	ret_val = e1e_wphy_locked(hw, I82579_LPI_CTRL, lpi_ctrl);
 release:
 	hw->phy.ops.release(hw);
@@ -835,6 +839,94 @@ release:
 }
 
 /**
+ *  e1000_platform_pm_pch_lpt - Set platform power management values
+ *  @hw: pointer to the HW structure
+ *  @link: bool indicating link status
+ *
+ *  Set the Latency Tolerance Reporting (LTR) values for the "PCIe-like"
+ *  GbE MAC in the Lynx Point PCH based on Rx buffer size and link speed
+ *  when link is up (which must not exceed the maximum latency supported
+ *  by the platform), otherwise specify there is no LTR requirement.
+ *  Unlike true-PCIe devices which set the LTR maximum snoop/no-snoop
+ *  latencies in the LTR Extended Capability Structure in the PCIe Extended
+ *  Capability register set, on this device LTR is set by writing the
+ *  equivalent snoop/no-snoop latencies in the LTRV register in the MAC and
+ *  set the SEND bit to send an Intel On-chip System Fabric sideband (IOSF-SB)
+ *  message to the PMC.
+ **/
+static s32 e1000_platform_pm_pch_lpt(struct e1000_hw *hw, bool link)
+{
+	u32 reg = link << (E1000_LTRV_REQ_SHIFT + E1000_LTRV_NOSNOOP_SHIFT) |
+	    link << E1000_LTRV_REQ_SHIFT | E1000_LTRV_SEND;
+	u16 lat_enc = 0;	/* latency encoded */
+
+	if (link) {
+		u16 speed, duplex, scale = 0;
+		u16 max_snoop, max_nosnoop;
+		u16 max_ltr_enc;	/* max LTR latency encoded */
+		s64 lat_ns;	/* latency (ns) */
+		s64 value;
+		u32 rxa;
+
+		if (!hw->adapter->max_frame_size) {
+			e_dbg("max_frame_size not set.\n");
+			return -E1000_ERR_CONFIG;
+		}
+
+		hw->mac.ops.get_link_up_info(hw, &speed, &duplex);
+		if (!speed) {
+			e_dbg("Speed not set.\n");
+			return -E1000_ERR_CONFIG;
+		}
+
+		/* Rx Packet Buffer Allocation size (KB) */
+		rxa = er32(PBA) & E1000_PBA_RXA_MASK;
+
+		/* Determine the maximum latency tolerated by the device.
+		 *
+		 * Per the PCIe spec, the tolerated latencies are encoded as
+		 * a 3-bit encoded scale (only 0-5 are valid) multiplied by
+		 * a 10-bit value (0-1023) to provide a range from 1 ns to
+		 * 2^25*(2^10-1) ns.  The scale is encoded as 0=2^0ns,
+		 * 1=2^5ns, 2=2^10ns,...5=2^25ns.
+		 */
+		lat_ns = ((s64)rxa * 1024 -
+			  (2 * (s64)hw->adapter->max_frame_size)) * 8 * 1000;
+		if (lat_ns < 0)
+			lat_ns = 0;
+		else
+			do_div(lat_ns, speed);
+
+		value = lat_ns;
+		while (value > PCI_LTR_VALUE_MASK) {
+			scale++;
+			value = DIV_ROUND_UP(value, (1 << 5));
+		}
+		if (scale > E1000_LTRV_SCALE_MAX) {
+			e_dbg("Invalid LTR latency scale %d\n", scale);
+			return -E1000_ERR_CONFIG;
+		}
+		lat_enc = (u16)((scale << PCI_LTR_SCALE_SHIFT) | value);
+
+		/* Determine the maximum latency tolerated by the platform */
+		pci_read_config_word(hw->adapter->pdev, E1000_PCI_LTR_CAP_LPT,
+				     &max_snoop);
+		pci_read_config_word(hw->adapter->pdev,
+				     E1000_PCI_LTR_CAP_LPT + 2, &max_nosnoop);
+		max_ltr_enc = max_t(u16, max_snoop, max_nosnoop);
+
+		if (lat_enc > max_ltr_enc)
+			lat_enc = max_ltr_enc;
+	}
+
+	/* Set Snoop and No-Snoop latencies the same */
+	reg |= lat_enc | (lat_enc << E1000_LTRV_NOSNOOP_SHIFT);
+	ew32(LTRV, reg);
+
+	return 0;
+}
+
+/**
  *  e1000_check_for_copper_link_ich8lan - Check for link (Copper)
  *  @hw: pointer to the HW structure
  *
@@ -871,6 +963,34 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
 			return ret_val;
 	}
 
+	/* When connected at 10Mbps half-duplex, 82579 parts are excessively
+	 * aggressive resulting in many collisions. To avoid this, increase
+	 * the IPG and reduce Rx latency in the PHY.
+	 */
+	if ((hw->mac.type == e1000_pch2lan) && link) {
+		u32 reg;
+		reg = er32(STATUS);
+		if (!(reg & (E1000_STATUS_FD | E1000_STATUS_SPEED_MASK))) {
+			reg = er32(TIPG);
+			reg &= ~E1000_TIPG_IPGT_MASK;
+			reg |= 0xFF;
+			ew32(TIPG, reg);
+
+			/* Reduce Rx latency in analog PHY */
+			ret_val = hw->phy.ops.acquire(hw);
+			if (ret_val)
+				return ret_val;
+
+			ret_val =
+			    e1000_write_emi_reg_locked(hw, I82579_RX_CONFIG, 0);
+
+			hw->phy.ops.release(hw);
+
+			if (ret_val)
+				return ret_val;
+		}
+	}
+
 	/* Work-around I218 hang issue */
 	if ((hw->adapter->pdev->device == E1000_DEV_ID_PCH_LPTLP_I218_LM) ||
 	    (hw->adapter->pdev->device == E1000_DEV_ID_PCH_LPTLP_I218_V)) {
@@ -879,6 +999,15 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
 			return ret_val;
 	}
 
+	if (hw->mac.type == e1000_pch_lpt) {
+		/* Set platform power management values for
+		 * Latency Tolerance Reporting (LTR)
+		 */
+		ret_val = e1000_platform_pm_pch_lpt(hw, link);
+		if (ret_val)
+			return ret_val;
+	}
+
 	/* Clear link partner's EEE ability */
 	hw->dev_spec.ich8lan.eee_lp_ability = 0;
 
@@ -1002,10 +1131,6 @@ static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter)
 	    (er32(FWSM) & E1000_ICH_FWSM_FW_VALID))
 		adapter->flags2 |= FLAG2_PCIM2PCI_ARBITER_WA;
 
-	/* Disable EEE by default until IEEE802.3az spec is finalized */
-	if (adapter->flags2 & FLAG2_HAS_EEE)
-		adapter->hw.dev_spec.ich8lan.eee_disable = true;
-
 	return 0;
 }
 
@@ -1134,9 +1259,9 @@ static bool e1000_check_mng_mode_ich8lan(struct e1000_hw *hw)
 	u32 fwsm;
 
 	fwsm = er32(FWSM);
-	return (fwsm & E1000_ICH_FWSM_FW_VALID) &&
-	       ((fwsm & E1000_FWSM_MODE_MASK) ==
-		(E1000_ICH_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT));
+	return ((fwsm & E1000_ICH_FWSM_FW_VALID) &&
+		((fwsm & E1000_FWSM_MODE_MASK) ==
+		 (E1000_ICH_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT)));
 }
 
 /**
@@ -1153,7 +1278,7 @@ static bool e1000_check_mng_mode_pchlan(struct e1000_hw *hw)
 
 	fwsm = er32(FWSM);
 	return (fwsm & E1000_ICH_FWSM_FW_VALID) &&
-	       (fwsm & (E1000_ICH_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT));
+	    (fwsm & (E1000_ICH_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT));
 }
 
 /**
@@ -1440,8 +1565,7 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
 	word_addr = (u16)(cnf_base_addr << 1);
 
 	for (i = 0; i < cnf_size; i++) {
-		ret_val = e1000_read_nvm(hw, (word_addr + i * 2), 1,
-					 &reg_data);
+		ret_val = e1000_read_nvm(hw, (word_addr + i * 2), 1, &reg_data);
 		if (ret_val)
 			goto release;
 
@@ -1501,13 +1625,13 @@ static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link)
 			if (ret_val)
 				goto release;
 
-			status_reg &= BM_CS_STATUS_LINK_UP |
-			              BM_CS_STATUS_RESOLVED |
-			              BM_CS_STATUS_SPEED_MASK;
+			status_reg &= (BM_CS_STATUS_LINK_UP |
+				       BM_CS_STATUS_RESOLVED |
+				       BM_CS_STATUS_SPEED_MASK);
 
 			if (status_reg == (BM_CS_STATUS_LINK_UP |
-			                   BM_CS_STATUS_RESOLVED |
-			                   BM_CS_STATUS_SPEED_1000))
+					   BM_CS_STATUS_RESOLVED |
+					   BM_CS_STATUS_SPEED_1000))
 				k1_enable = false;
 		}
 
@@ -1516,13 +1640,13 @@ static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link)
 			if (ret_val)
 				goto release;
 
-			status_reg &= HV_M_STATUS_LINK_UP |
-			              HV_M_STATUS_AUTONEG_COMPLETE |
-			              HV_M_STATUS_SPEED_MASK;
+			status_reg &= (HV_M_STATUS_LINK_UP |
+				       HV_M_STATUS_AUTONEG_COMPLETE |
+				       HV_M_STATUS_SPEED_MASK);
 
 			if (status_reg == (HV_M_STATUS_LINK_UP |
-			                   HV_M_STATUS_AUTONEG_COMPLETE |
-			                   HV_M_STATUS_SPEED_1000))
+					   HV_M_STATUS_AUTONEG_COMPLETE |
+					   HV_M_STATUS_SPEED_1000))
 				k1_enable = false;
 		}
 
@@ -1579,7 +1703,7 @@ s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable)
 	if (ret_val)
 		return ret_val;
 
-	udelay(20);
+	usleep_range(20, 40);
 	ctrl_ext = er32(CTRL_EXT);
 	ctrl_reg = er32(CTRL);
 
@@ -1589,11 +1713,11 @@ s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable)
 
 	ew32(CTRL_EXT, ctrl_ext | E1000_CTRL_EXT_SPD_BYPS);
 	e1e_flush();
-	udelay(20);
+	usleep_range(20, 40);
 	ew32(CTRL, ctrl_reg);
 	ew32(CTRL_EXT, ctrl_ext);
 	e1e_flush();
-	udelay(20);
+	usleep_range(20, 40);
 
 	return 0;
 }
@@ -1667,7 +1791,6 @@ release:
 	return ret_val;
 }
 
-
 /**
  *  e1000_set_mdio_slow_mode_hv - Set slow MDIO access mode
  *  @hw:   pointer to the HW structure
@@ -1834,7 +1957,7 @@ s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable)
 		 * SHRAL/H) and initial CRC values to the MAC
 		 */
 		for (i = 0; i < (hw->mac.rar_entry_count + 4); i++) {
-			u8 mac_addr[ETH_ALEN] = {0};
+			u8 mac_addr[ETH_ALEN] = { 0 };
 			u32 addr_high, addr_low;
 
 			addr_high = er32(RAH(i));
@@ -1865,8 +1988,8 @@ s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable)
 		ew32(RCTL, mac_reg);
 
 		ret_val = e1000e_read_kmrn_reg(hw,
-						E1000_KMRNCTRLSTA_CTRL_OFFSET,
-						&data);
+					       E1000_KMRNCTRLSTA_CTRL_OFFSET,
+					       &data);
 		if (ret_val)
 			return ret_val;
 		ret_val = e1000e_write_kmrn_reg(hw,
@@ -1875,8 +1998,8 @@ s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable)
 		if (ret_val)
 			return ret_val;
 		ret_val = e1000e_read_kmrn_reg(hw,
-						E1000_KMRNCTRLSTA_HD_CTRL,
-						&data);
+					       E1000_KMRNCTRLSTA_HD_CTRL,
+					       &data);
 		if (ret_val)
 			return ret_val;
 		data &= ~(0xF << 8);
@@ -1923,8 +2046,8 @@ s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable)
 		ew32(RCTL, mac_reg);
 
 		ret_val = e1000e_read_kmrn_reg(hw,
-						E1000_KMRNCTRLSTA_CTRL_OFFSET,
-						&data);
+					       E1000_KMRNCTRLSTA_CTRL_OFFSET,
+					       &data);
 		if (ret_val)
 			return ret_val;
 		ret_val = e1000e_write_kmrn_reg(hw,
@@ -1933,8 +2056,8 @@ s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable)
 		if (ret_val)
 			return ret_val;
 		ret_val = e1000e_read_kmrn_reg(hw,
-						E1000_KMRNCTRLSTA_HD_CTRL,
-						&data);
+					       E1000_KMRNCTRLSTA_HD_CTRL,
+					       &data);
 		if (ret_val)
 			return ret_val;
 		data &= ~(0xF << 8);
@@ -2100,7 +2223,7 @@ static void e1000_lan_init_done_ich8lan(struct e1000_hw *hw)
 	do {
 		data = er32(STATUS);
 		data &= E1000_STATUS_LAN_INIT_DONE;
-		udelay(100);
+		usleep_range(100, 200);
 	} while ((!data) && --loop);
 
 	/* If basic configuration is incomplete before the above loop
@@ -2445,7 +2568,7 @@ static s32 e1000_valid_nvm_bank_detect_ich8lan(struct e1000_hw *hw, u32 *bank)
 
 		/* Check bank 0 */
 		ret_val = e1000_read_flash_byte_ich8lan(hw, act_offset,
-		                                        &sig_byte);
+							&sig_byte);
 		if (ret_val)
 			return ret_val;
 		if ((sig_byte & E1000_ICH_NVM_VALID_SIG_MASK) ==
@@ -2456,8 +2579,8 @@ static s32 e1000_valid_nvm_bank_detect_ich8lan(struct e1000_hw *hw, u32 *bank)
 
 		/* Check bank 1 */
 		ret_val = e1000_read_flash_byte_ich8lan(hw, act_offset +
-		                                        bank1_offset,
-		                                        &sig_byte);
+							bank1_offset,
+							&sig_byte);
 		if (ret_val)
 			return ret_val;
 		if ((sig_byte & E1000_ICH_NVM_VALID_SIG_MASK) ==
@@ -2510,8 +2633,8 @@ static s32 e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words,
 
 	ret_val = 0;
 	for (i = 0; i < words; i++) {
-		if (dev_spec->shadow_ram[offset+i].modified) {
-			data[i] = dev_spec->shadow_ram[offset+i].value;
+		if (dev_spec->shadow_ram[offset + i].modified) {
+			data[i] = dev_spec->shadow_ram[offset + i].value;
 		} else {
 			ret_val = e1000_read_flash_word_ich8lan(hw,
 								act_offset + i,
@@ -2696,8 +2819,8 @@ static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
 	if (size < 1  || size > 2 || offset > ICH_FLASH_LINEAR_ADDR_MASK)
 		return -E1000_ERR_NVM;
 
-	flash_linear_addr = (ICH_FLASH_LINEAR_ADDR_MASK & offset) +
-			    hw->nvm.flash_base_addr;
+	flash_linear_addr = ((ICH_FLASH_LINEAR_ADDR_MASK & offset) +
+			     hw->nvm.flash_base_addr);
 
 	do {
 		udelay(1);
@@ -2714,8 +2837,9 @@ static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
 
 		ew32flash(ICH_FLASH_FADDR, flash_linear_addr);
 
-		ret_val = e1000_flash_cycle_ich8lan(hw,
-						ICH_FLASH_READ_COMMAND_TIMEOUT);
+		ret_val =
+		    e1000_flash_cycle_ich8lan(hw,
+					      ICH_FLASH_READ_COMMAND_TIMEOUT);
 
 		/* Check if FCERR is set to 1, if set to 1, clear it
 		 * and try the whole sequence a few more times, else
@@ -2774,8 +2898,8 @@ static s32 e1000_write_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words,
 	nvm->ops.acquire(hw);
 
 	for (i = 0; i < words; i++) {
-		dev_spec->shadow_ram[offset+i].modified = true;
-		dev_spec->shadow_ram[offset+i].value = data[i];
+		dev_spec->shadow_ram[offset + i].modified = true;
+		dev_spec->shadow_ram[offset + i].value = data[i];
 	}
 
 	nvm->ops.release(hw);
@@ -2844,8 +2968,8 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
 			data = dev_spec->shadow_ram[i].value;
 		} else {
 			ret_val = e1000_read_flash_word_ich8lan(hw, i +
-			                                        old_bank_offset,
-			                                        &data);
+								old_bank_offset,
+								&data);
 			if (ret_val)
 				break;
 		}
@@ -2863,7 +2987,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
 		/* Convert offset to bytes. */
 		act_offset = (i + new_bank_offset) << 1;
 
-		udelay(100);
+		usleep_range(100, 200);
 		/* Write the bytes to the new bank. */
 		ret_val = e1000_retry_write_flash_byte_ich8lan(hw,
 							       act_offset,
@@ -2871,10 +2995,10 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
 		if (ret_val)
 			break;
 
-		udelay(100);
+		usleep_range(100, 200);
 		ret_val = e1000_retry_write_flash_byte_ich8lan(hw,
-							  act_offset + 1,
-							  (u8)(data >> 8));
+							       act_offset + 1,
+							       (u8)(data >> 8));
 		if (ret_val)
 			break;
 	}
@@ -3050,8 +3174,8 @@ static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
 	    offset > ICH_FLASH_LINEAR_ADDR_MASK)
 		return -E1000_ERR_NVM;
 
-	flash_linear_addr = (ICH_FLASH_LINEAR_ADDR_MASK & offset) +
-			    hw->nvm.flash_base_addr;
+	flash_linear_addr = ((ICH_FLASH_LINEAR_ADDR_MASK & offset) +
+			     hw->nvm.flash_base_addr);
 
 	do {
 		udelay(1);
@@ -3062,7 +3186,7 @@ static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
 
 		hsflctl.regval = er16flash(ICH_FLASH_HSFCTL);
 		/* 0b/1b corresponds to 1 or 2 byte size, respectively. */
-		hsflctl.hsf_ctrl.fldbcount = size -1;
+		hsflctl.hsf_ctrl.fldbcount = size - 1;
 		hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_WRITE;
 		ew16flash(ICH_FLASH_HSFCTL, hsflctl.regval);
 
@@ -3078,8 +3202,9 @@ static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
 		/* check if FCERR is set to 1 , if set to 1, clear it
 		 * and try the whole sequence a few more times else done
 		 */
-		ret_val = e1000_flash_cycle_ich8lan(hw,
-					       ICH_FLASH_WRITE_COMMAND_TIMEOUT);
+		ret_val =
+		    e1000_flash_cycle_ich8lan(hw,
+					      ICH_FLASH_WRITE_COMMAND_TIMEOUT);
 		if (!ret_val)
 			break;
 
@@ -3138,7 +3263,7 @@ static s32 e1000_retry_write_flash_byte_ich8lan(struct e1000_hw *hw,
 
 	for (program_retries = 0; program_retries < 100; program_retries++) {
 		e_dbg("Retrying Byte %2.2X at offset %u\n", byte, offset);
-		udelay(100);
+		usleep_range(100, 200);
 		ret_val = e1000_write_flash_byte_ich8lan(hw, offset, byte);
 		if (!ret_val)
 			break;
@@ -3209,8 +3334,10 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank)
 	flash_linear_addr = hw->nvm.flash_base_addr;
 	flash_linear_addr += (bank) ? flash_bank_size : 0;
 
-	for (j = 0; j < iteration ; j++) {
+	for (j = 0; j < iteration; j++) {
 		do {
+			u32 timeout = ICH_FLASH_ERASE_COMMAND_TIMEOUT;
+
 			/* Steps */
 			ret_val = e1000_flash_cycle_init_ich8lan(hw);
 			if (ret_val)
@@ -3230,8 +3357,7 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank)
 			flash_linear_addr += (j * sector_size);
 			ew32flash(ICH_FLASH_FADDR, flash_linear_addr);
 
-			ret_val = e1000_flash_cycle_ich8lan(hw,
-					       ICH_FLASH_ERASE_COMMAND_TIMEOUT);
+			ret_val = e1000_flash_cycle_ich8lan(hw, timeout);
 			if (!ret_val)
 				break;
 
@@ -3270,8 +3396,7 @@ static s32 e1000_valid_led_default_ich8lan(struct e1000_hw *hw, u16 *data)
 		return ret_val;
 	}
 
-	if (*data == ID_LED_RESERVED_0000 ||
-	    *data == ID_LED_RESERVED_FFFF)
+	if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF)
 		*data = ID_LED_DEFAULT_ICH8LAN;
 
 	return 0;
@@ -3511,9 +3636,9 @@ static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw)
 
 	/* Initialize identification LED */
 	ret_val = mac->ops.id_led_init(hw);
+	/* An error is not fatal and we should not stop init due to this */
 	if (ret_val)
 		e_dbg("Error initializing identification LED\n");
-		/* This is not fatal and we should not stop init due to this */
 
 	/* Setup the receive address. */
 	e1000e_init_rx_addrs(hw, mac->rar_entry_count);
@@ -3541,16 +3666,16 @@ static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw)
 
 	/* Set the transmit descriptor write-back policy for both queues */
 	txdctl = er32(TXDCTL(0));
-	txdctl = (txdctl & ~E1000_TXDCTL_WTHRESH) |
-		 E1000_TXDCTL_FULL_TX_DESC_WB;
-	txdctl = (txdctl & ~E1000_TXDCTL_PTHRESH) |
-		 E1000_TXDCTL_MAX_TX_DESC_PREFETCH;
+	txdctl = ((txdctl & ~E1000_TXDCTL_WTHRESH) |
+		  E1000_TXDCTL_FULL_TX_DESC_WB);
+	txdctl = ((txdctl & ~E1000_TXDCTL_PTHRESH) |
+		  E1000_TXDCTL_MAX_TX_DESC_PREFETCH);
 	ew32(TXDCTL(0), txdctl);
 	txdctl = er32(TXDCTL(1));
-	txdctl = (txdctl & ~E1000_TXDCTL_WTHRESH) |
-		 E1000_TXDCTL_FULL_TX_DESC_WB;
-	txdctl = (txdctl & ~E1000_TXDCTL_PTHRESH) |
-		 E1000_TXDCTL_MAX_TX_DESC_PREFETCH;
+	txdctl = ((txdctl & ~E1000_TXDCTL_WTHRESH) |
+		  E1000_TXDCTL_FULL_TX_DESC_WB);
+	txdctl = ((txdctl & ~E1000_TXDCTL_PTHRESH) |
+		  E1000_TXDCTL_MAX_TX_DESC_PREFETCH);
 	ew32(TXDCTL(1), txdctl);
 
 	/* ICH8 has opposite polarity of no_snoop bits.
@@ -3559,7 +3684,7 @@ static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw)
 	if (mac->type == e1000_ich8lan)
 		snoop = PCIE_ICH8_SNOOP_ALL;
 	else
-		snoop = (u32) ~(PCIE_NO_SNOOP_ALL);
+		snoop = (u32)~(PCIE_NO_SNOOP_ALL);
 	e1000e_set_pcie_no_snoop(hw, snoop);
 
 	ctrl_ext = er32(CTRL_EXT);
@@ -3575,6 +3700,7 @@ static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw)
 
 	return ret_val;
 }
+
 /**
  *  e1000_initialize_hw_bits_ich8lan - Initialize required hardware bits
  *  @hw: pointer to the HW structure
@@ -3686,8 +3812,7 @@ static s32 e1000_setup_link_ich8lan(struct e1000_hw *hw)
 	 */
 	hw->fc.current_mode = hw->fc.requested_mode;
 
-	e_dbg("After fix-ups FlowControl is now = %x\n",
-		hw->fc.current_mode);
+	e_dbg("After fix-ups FlowControl is now = %x\n", hw->fc.current_mode);
 
 	/* Continue to configure the copper link. */
 	ret_val = hw->mac.ops.setup_physical_interface(hw);
@@ -3737,12 +3862,12 @@ static s32 e1000_setup_copper_link_ich8lan(struct e1000_hw *hw)
 	if (ret_val)
 		return ret_val;
 	ret_val = e1000e_read_kmrn_reg(hw, E1000_KMRNCTRLSTA_INBAND_PARAM,
-	                               &reg_data);
+				       &reg_data);
 	if (ret_val)
 		return ret_val;
 	reg_data |= 0x3F;
 	ret_val = e1000e_write_kmrn_reg(hw, E1000_KMRNCTRLSTA_INBAND_PARAM,
-	                                reg_data);
+					reg_data);
 	if (ret_val)
 		return ret_val;
 
@@ -3760,7 +3885,6 @@ static s32 e1000_setup_copper_link_ich8lan(struct e1000_hw *hw)
 		break;
 	case e1000_phy_82577:
 	case e1000_phy_82579:
-	case e1000_phy_i217:
 		ret_val = e1000_copper_link_setup_82577(hw);
 		if (ret_val)
 			return ret_val;
@@ -3796,6 +3920,31 @@ static s32 e1000_setup_copper_link_ich8lan(struct e1000_hw *hw)
 }
 
 /**
+ *  e1000_setup_copper_link_pch_lpt - Configure MAC/PHY interface
+ *  @hw: pointer to the HW structure
+ *
+ *  Calls the PHY specific link setup function and then calls the
+ *  generic setup_copper_link to finish configuring the link for
+ *  Lynxpoint PCH devices
+ **/
+static s32 e1000_setup_copper_link_pch_lpt(struct e1000_hw *hw)
+{
+	u32 ctrl;
+	s32 ret_val;
+
+	ctrl = er32(CTRL);
+	ctrl |= E1000_CTRL_SLU;
+	ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
+	ew32(CTRL, ctrl);
+
+	ret_val = e1000_copper_link_setup_82577(hw);
+	if (ret_val)
+		return ret_val;
+
+	return e1000e_setup_copper_link(hw);
+}
+
+/**
  *  e1000_get_link_up_info_ich8lan - Get current link speed and duplex
  *  @hw: pointer to the HW structure
  *  @speed: pointer to store current link speed
@@ -3815,8 +3964,7 @@ static s32 e1000_get_link_up_info_ich8lan(struct e1000_hw *hw, u16 *speed,
 		return ret_val;
 
 	if ((hw->mac.type == e1000_ich8lan) &&
-	    (hw->phy.type == e1000_phy_igp_3) &&
-	    (*speed == SPEED_1000)) {
+	    (hw->phy.type == e1000_phy_igp_3) && (*speed == SPEED_1000)) {
 		ret_val = e1000_kmrn_lock_loss_workaround_ich8lan(hw);
 	}
 
@@ -3899,7 +4047,7 @@ static s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw)
  *  /disabled - false).
  **/
 void e1000e_set_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw,
-						 bool state)
+						  bool state)
 {
 	struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
 
@@ -3981,12 +4129,12 @@ void e1000e_gig_downshift_workaround_ich8lan(struct e1000_hw *hw)
 		return;
 
 	ret_val = e1000e_read_kmrn_reg(hw, E1000_KMRNCTRLSTA_DIAG_OFFSET,
-				      &reg_data);
+				       &reg_data);
 	if (ret_val)
 		return;
 	reg_data |= E1000_KMRNCTRLSTA_DIAG_NELPBK;
 	ret_val = e1000e_write_kmrn_reg(hw, E1000_KMRNCTRLSTA_DIAG_OFFSET,
-				       reg_data);
+					reg_data);
 	if (ret_val)
 		return;
 	reg_data &= ~E1000_KMRNCTRLSTA_DIAG_NELPBK;
diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.h b/drivers/net/ethernet/intel/e1000e/ich8lan.h
index 8bf4655..80034a2 100644
--- a/drivers/net/ethernet/intel/e1000e/ich8lan.h
+++ b/drivers/net/ethernet/intel/e1000e/ich8lan.h
@@ -211,7 +211,8 @@
 #define I82579_MSE_THRESHOLD	0x084F	/* 82579 Mean Square Error Threshold */
 #define I82577_MSE_THRESHOLD	0x0887	/* 82577 Mean Square Error Threshold */
 #define I82579_MSE_LINK_DOWN	0x2411	/* MSE count before dropping link */
-#define I82579_EEE_PCS_STATUS		0x182D	/* IEEE MMD Register 3.1 >> 8 */
+#define I82579_RX_CONFIG		0x3412	/* Receive configuration */
+#define I82579_EEE_PCS_STATUS		0x182E	/* IEEE MMD Register 3.1 >> 8 */
 #define I82579_EEE_CAPABILITY		0x0410	/* IEEE MMD Register 3.20 */
 #define I82579_EEE_ADVERTISEMENT	0x040E	/* IEEE MMD Register 7.60 */
 #define I82579_EEE_LP_ABILITY		0x040F	/* IEEE MMD Register 7.61 */
@@ -249,13 +250,6 @@
 /* Proprietary Latency Tolerance Reporting PCI Capability */
 #define E1000_PCI_LTR_CAP_LPT		0xA8
 
-/* OBFF Control & Threshold Defines */
-#define E1000_SVCR_OFF_EN		0x00000001
-#define E1000_SVCR_OFF_MASKINT		0x00001000
-#define E1000_SVCR_OFF_TIMER_MASK	0xFFFF0000
-#define E1000_SVCR_OFF_TIMER_SHIFT	16
-#define E1000_SVT_OFF_HWM_MASK		0x0000001F
-
 void e1000e_write_protect_nvm_ich8lan(struct e1000_hw *hw);
 void e1000e_set_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw,
 						  bool state);
@@ -267,4 +261,5 @@ s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable);
 void e1000_copy_rx_addrs_to_phy_ich8lan(struct e1000_hw *hw);
 s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable);
 s32 e1000_read_emi_reg_locked(struct e1000_hw *hw, u16 addr, u16 *data);
+s32 e1000_write_emi_reg_locked(struct e1000_hw *hw, u16 addr, u16 data);
 #endif /* _E1000E_ICH8LAN_H_ */
diff --git a/drivers/net/ethernet/intel/e1000e/mac.c b/drivers/net/ethernet/intel/e1000e/mac.c
index b78e021..2480c10 100644
--- a/drivers/net/ethernet/intel/e1000e/mac.c
+++ b/drivers/net/ethernet/intel/e1000e/mac.c
@@ -596,7 +596,7 @@ s32 e1000e_check_for_serdes_link(struct e1000_hw *hw)
 		 * serdes media type.
 		 */
 		/* SYNCH bit and IV bit are sticky. */
-		udelay(10);
+		usleep_range(10, 20);
 		rxcw = er32(RXCW);
 		if (rxcw & E1000_RXCW_SYNCH) {
 			if (!(rxcw & E1000_RXCW_IV)) {
@@ -613,7 +613,7 @@ s32 e1000e_check_for_serdes_link(struct e1000_hw *hw)
 		status = er32(STATUS);
 		if (status & E1000_STATUS_LU) {
 			/* SYNCH bit and IV bit are sticky, so reread rxcw. */
-			udelay(10);
+			usleep_range(10, 20);
 			rxcw = er32(RXCW);
 			if (rxcw & E1000_RXCW_SYNCH) {
 				if (!(rxcw & E1000_RXCW_IV)) {
@@ -1382,7 +1382,7 @@ s32 e1000e_get_hw_semaphore(struct e1000_hw *hw)
 		if (!(swsm & E1000_SWSM_SMBI))
 			break;
 
-		udelay(50);
+		usleep_range(50, 100);
 		i++;
 	}
 
@@ -1400,7 +1400,7 @@ s32 e1000e_get_hw_semaphore(struct e1000_hw *hw)
 		if (er32(SWSM) & E1000_SWSM_SWESMBI)
 			break;
 
-		udelay(50);
+		usleep_range(50, 100);
 	}
 
 	if (i == timeout) {
@@ -1600,15 +1600,28 @@ s32 e1000e_blink_led_generic(struct e1000_hw *hw)
 		ledctl_blink = E1000_LEDCTL_LED0_BLINK |
 		    (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED0_MODE_SHIFT);
 	} else {
-		/* set the blink bit for each LED that's "on" (0x0E)
-		 * in ledctl_mode2
+		/* Set the blink bit for each LED that's "on" (0x0E)
+		 * (or "off" if inverted) in ledctl_mode2.  The blink
+		 * logic in hardware only works when mode is set to "on"
+		 * so it must be changed accordingly when the mode is
+		 * "off" and inverted.
 		 */
 		ledctl_blink = hw->mac.ledctl_mode2;
-		for (i = 0; i < 4; i++)
-			if (((hw->mac.ledctl_mode2 >> (i * 8)) & 0xFF) ==
-			    E1000_LEDCTL_MODE_LED_ON)
-				ledctl_blink |= (E1000_LEDCTL_LED0_BLINK <<
-						 (i * 8));
+		for (i = 0; i < 32; i += 8) {
+			u32 mode = (hw->mac.ledctl_mode2 >> i) &
+			    E1000_LEDCTL_LED0_MODE_MASK;
+			u32 led_default = hw->mac.ledctl_default >> i;
+
+			if ((!(led_default & E1000_LEDCTL_LED0_IVRT) &&
+			     (mode == E1000_LEDCTL_MODE_LED_ON)) ||
+			    ((led_default & E1000_LEDCTL_LED0_IVRT) &&
+			     (mode == E1000_LEDCTL_MODE_LED_OFF))) {
+				ledctl_blink &=
+				    ~(E1000_LEDCTL_LED0_MODE_MASK << i);
+				ledctl_blink |= (E1000_LEDCTL_LED0_BLINK |
+						 E1000_LEDCTL_MODE_LED_ON) << i;
+			}
+		}
 	}
 
 	ew32(LEDCTL, ledctl_blink);
@@ -1712,7 +1725,7 @@ s32 e1000e_disable_pcie_master(struct e1000_hw *hw)
 	while (timeout) {
 		if (!(er32(STATUS) & E1000_STATUS_GIO_MASTER_ENABLE))
 			break;
-		udelay(100);
+		usleep_range(100, 200);
 		timeout--;
 	}
 
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
index 948b86ff..b18fad5 100644
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -55,7 +55,7 @@
 
 #define DRV_EXTRAVERSION "-k"
 
-#define DRV_VERSION "2.2.14" DRV_EXTRAVERSION
+#define DRV_VERSION "2.3.2" DRV_EXTRAVERSION
 char e1000e_driver_name[] = "e1000e";
 const char e1000e_driver_version[] = DRV_VERSION;
 
@@ -219,9 +219,8 @@ static void e1000e_dump(struct e1000_adapter *adapter)
 	if (netdev) {
 		dev_info(&adapter->pdev->dev, "Net device Info\n");
 		pr_info("Device Name     state            trans_start      last_rx\n");
-		pr_info("%-15s %016lX %016lX %016lX\n",
-			netdev->name, netdev->state, netdev->trans_start,
-			netdev->last_rx);
+		pr_info("%-15s %016lX %016lX %016lX\n", netdev->name,
+			netdev->state, netdev->trans_start, netdev->last_rx);
 	}
 
 	/* Print Registers */
@@ -755,8 +754,7 @@ static void e1000_alloc_rx_buffers_ps(struct e1000_ring *rx_ring,
 			    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) {
@@ -848,11 +846,16 @@ check_page:
 			}
 		}
 
-		if (!buffer_info->dma)
+		if (!buffer_info->dma) {
 			buffer_info->dma = dma_map_page(&pdev->dev,
-			                                buffer_info->page, 0,
-			                                PAGE_SIZE,
+							buffer_info->page, 0,
+							PAGE_SIZE,
 							DMA_FROM_DEVICE);
+			if (dma_mapping_error(&pdev->dev, buffer_info->dma)) {
+				adapter->alloc_rx_buff_failed++;
+				break;
+			}
+		}
 
 		rx_desc = E1000_RX_DESC_EXT(*rx_ring, i);
 		rx_desc->read.buffer_addr = cpu_to_le64(buffer_info->dma);
@@ -937,10 +940,8 @@ static bool e1000_clean_rx_irq(struct e1000_ring *rx_ring, int *work_done,
 
 		cleaned = true;
 		cleaned_count++;
-		dma_unmap_single(&pdev->dev,
-				 buffer_info->dma,
-				 adapter->rx_buffer_len,
-				 DMA_FROM_DEVICE);
+		dma_unmap_single(&pdev->dev, buffer_info->dma,
+				 adapter->rx_buffer_len, DMA_FROM_DEVICE);
 		buffer_info->dma = 0;
 
 		length = le16_to_cpu(rx_desc->wb.upper.length);
@@ -1068,8 +1069,8 @@ static void e1000_put_txbuf(struct e1000_ring *tx_ring,
 static void e1000_print_hw_hang(struct work_struct *work)
 {
 	struct e1000_adapter *adapter = container_of(work,
-	                                             struct e1000_adapter,
-	                                             print_hang_task);
+						     struct e1000_adapter,
+						     print_hang_task);
 	struct net_device *netdev = adapter->netdev;
 	struct e1000_ring *tx_ring = adapter->tx_ring;
 	unsigned int i = tx_ring->next_to_clean;
@@ -1082,8 +1083,7 @@ static void e1000_print_hw_hang(struct work_struct *work)
 	if (test_bit(__E1000_DOWN, &adapter->state))
 		return;
 
-	if (!adapter->tx_hang_recheck &&
-	    (adapter->flags2 & FLAG2_DMA_BURST)) {
+	if (!adapter->tx_hang_recheck && (adapter->flags2 & FLAG2_DMA_BURST)) {
 		/* May be block on write-back, flush and detect again
 		 * flush pending descriptor writebacks to memory
 		 */
@@ -1125,19 +1125,10 @@ static void e1000_print_hw_hang(struct work_struct *work)
 	      "PHY 1000BASE-T Status  <%x>\n"
 	      "PHY Extended Status    <%x>\n"
 	      "PCI Status             <%x>\n",
-	      readl(tx_ring->head),
-	      readl(tx_ring->tail),
-	      tx_ring->next_to_use,
-	      tx_ring->next_to_clean,
-	      tx_ring->buffer_info[eop].time_stamp,
-	      eop,
-	      jiffies,
-	      eop_desc->upper.fields.status,
-	      er32(STATUS),
-	      phy_status,
-	      phy_1000t_status,
-	      phy_ext_status,
-	      pci_status);
+	      readl(tx_ring->head), readl(tx_ring->tail), tx_ring->next_to_use,
+	      tx_ring->next_to_clean, tx_ring->buffer_info[eop].time_stamp,
+	      eop, jiffies, eop_desc->upper.fields.status, er32(STATUS),
+	      phy_status, phy_1000t_status, phy_ext_status, pci_status);
 
 	/* Suggest workaround for known h/w issue */
 	if ((hw->mac.type == e1000_pchlan) && (er32(CTRL) & E1000_CTRL_TFCE))
@@ -1430,7 +1421,7 @@ copydone:
 		e1000_rx_hash(netdev, rx_desc->wb.lower.hi_dword.rss, skb);
 
 		if (rx_desc->wb.upper.header_status &
-			   cpu_to_le16(E1000_RXDPS_HDRSTAT_HDRSP))
+		    cpu_to_le16(E1000_RXDPS_HDRSTAT_HDRSP))
 			adapter->rx_hdr_split++;
 
 		e1000_receive_skb(adapter, netdev, skb, staterr,
@@ -1468,7 +1459,7 @@ next_desc:
  * e1000_consume_page - helper function
  **/
 static void e1000_consume_page(struct e1000_buffer *bi, struct sk_buff *skb,
-                               u16 length)
+			       u16 length)
 {
 	bi->page = NULL;
 	skb->len += length;
@@ -1495,7 +1486,8 @@ static bool e1000_clean_jumbo_rx_irq(struct e1000_ring *rx_ring, int *work_done,
 	unsigned int i;
 	int cleaned_count = 0;
 	bool cleaned = false;
-	unsigned int total_rx_bytes=0, total_rx_packets=0;
+	unsigned int total_rx_bytes = 0, total_rx_packets = 0;
+	struct skb_shared_info *shinfo;
 
 	i = rx_ring->next_to_clean;
 	rx_desc = E1000_RX_DESC_EXT(*rx_ring, i);
@@ -1541,7 +1533,6 @@ static bool e1000_clean_jumbo_rx_irq(struct e1000_ring *rx_ring, int *work_done,
 			rx_ring->rx_skb_top = NULL;
 			goto next_desc;
 		}
-
 #define rxtop (rx_ring->rx_skb_top)
 		if (!(staterr & E1000_RXD_STAT_EOP)) {
 			/* this descriptor is only the beginning (or middle) */
@@ -1549,12 +1540,13 @@ static bool e1000_clean_jumbo_rx_irq(struct e1000_ring *rx_ring, int *work_done,
 				/* this is the beginning of a chain */
 				rxtop = skb;
 				skb_fill_page_desc(rxtop, 0, buffer_info->page,
-				                   0, length);
+						   0, length);
 			} else {
 				/* this is the middle of a chain */
-				skb_fill_page_desc(rxtop,
-				    skb_shinfo(rxtop)->nr_frags,
-				    buffer_info->page, 0, length);
+				shinfo = skb_shinfo(rxtop);
+				skb_fill_page_desc(rxtop, shinfo->nr_frags,
+						   buffer_info->page, 0,
+						   length);
 				/* re-use the skb, only consumed the page */
 				buffer_info->skb = skb;
 			}
@@ -1563,9 +1555,10 @@ static bool e1000_clean_jumbo_rx_irq(struct e1000_ring *rx_ring, int *work_done,
 		} else {
 			if (rxtop) {
 				/* end of the chain */
-				skb_fill_page_desc(rxtop,
-				    skb_shinfo(rxtop)->nr_frags,
-				    buffer_info->page, 0, length);
+				shinfo = skb_shinfo(rxtop);
+				skb_fill_page_desc(rxtop, shinfo->nr_frags,
+						   buffer_info->page, 0,
+						   length);
 				/* re-use the current skb, we only consumed the
 				 * page
 				 */
@@ -1590,10 +1583,10 @@ static bool e1000_clean_jumbo_rx_irq(struct e1000_ring *rx_ring, int *work_done,
 					skb_put(skb, length);
 				} else {
 					skb_fill_page_desc(skb, 0,
-					                   buffer_info->page, 0,
-				                           length);
+							   buffer_info->page, 0,
+							   length);
 					e1000_consume_page(buffer_info, skb,
-					                   length);
+							   length);
 				}
 			}
 		}
@@ -1666,8 +1659,7 @@ static void e1000_clean_rx_ring(struct e1000_ring *rx_ring)
 						 DMA_FROM_DEVICE);
 			else if (adapter->clean_rx == e1000_clean_jumbo_rx_irq)
 				dma_unmap_page(&pdev->dev, buffer_info->dma,
-				               PAGE_SIZE,
-					       DMA_FROM_DEVICE);
+					       PAGE_SIZE, DMA_FROM_DEVICE);
 			else if (adapter->clean_rx == e1000_clean_rx_irq_ps)
 				dma_unmap_single(&pdev->dev, buffer_info->dma,
 						 adapter->rx_ps_bsize0,
@@ -1720,7 +1712,8 @@ static void e1000_clean_rx_ring(struct e1000_ring *rx_ring)
 static void e1000e_downshift_workaround(struct work_struct *work)
 {
 	struct e1000_adapter *adapter = container_of(work,
-					struct e1000_adapter, downshift_task);
+						     struct e1000_adapter,
+						     downshift_task);
 
 	if (test_bit(__E1000_DOWN, &adapter->state))
 		return;
@@ -1913,7 +1906,6 @@ static irqreturn_t e1000_intr_msix_tx(int __always_unused irq, void *data)
 	struct e1000_hw *hw = &adapter->hw;
 	struct e1000_ring *tx_ring = adapter->tx_ring;
 
-
 	adapter->total_tx_bytes = 0;
 	adapter->total_tx_packets = 0;
 
@@ -1970,7 +1962,6 @@ static void e1000_configure_msix(struct e1000_adapter *adapter)
 		ew32(RFCTL, rfctl);
 	}
 
-#define E1000_IVAR_INT_ALLOC_VALID	0x8
 	/* Configure Rx vector */
 	rx_ring->ims_val = E1000_IMS_RXQ0;
 	adapter->eiac_mask |= rx_ring->ims_val;
@@ -2045,8 +2036,9 @@ void e1000e_set_interrupt_capability(struct e1000_adapter *adapter)
 		if (adapter->flags & FLAG_HAS_MSIX) {
 			adapter->num_vectors = 3; /* RxQ0, TxQ0 and other */
 			adapter->msix_entries = kcalloc(adapter->num_vectors,
-						      sizeof(struct msix_entry),
-						      GFP_KERNEL);
+							sizeof(struct
+							       msix_entry),
+							GFP_KERNEL);
 			if (adapter->msix_entries) {
 				for (i = 0; i < adapter->num_vectors; i++)
 					adapter->msix_entries[i].entry = i;
@@ -2490,7 +2482,7 @@ static unsigned int e1000_update_itr(u16 itr_setting, int packets, int bytes)
 	switch (itr_setting) {
 	case lowest_latency:
 		/* handle TSO and jumbo frames */
-		if (bytes/packets > 8000)
+		if (bytes / packets > 8000)
 			retval = bulk_latency;
 		else if ((packets < 5) && (bytes > 512))
 			retval = low_latency;
@@ -2498,13 +2490,13 @@ static unsigned int e1000_update_itr(u16 itr_setting, int packets, int bytes)
 	case low_latency:  /* 50 usec aka 20000 ints/s */
 		if (bytes > 10000) {
 			/* this if handles the TSO accounting */
-			if (bytes/packets > 8000)
+			if (bytes / packets > 8000)
 				retval = bulk_latency;
-			else if ((packets < 10) || ((bytes/packets) > 1200))
+			else if ((packets < 10) || ((bytes / packets) > 1200))
 				retval = bulk_latency;
 			else if ((packets > 35))
 				retval = lowest_latency;
-		} else if (bytes/packets > 2000) {
+		} else if (bytes / packets > 2000) {
 			retval = bulk_latency;
 		} else if (packets <= 2 && bytes < 512) {
 			retval = lowest_latency;
@@ -2556,8 +2548,8 @@ static void e1000_set_itr(struct e1000_adapter *adapter)
 
 	current_itr = max(adapter->rx_itr, adapter->tx_itr);
 
-	switch (current_itr) {
 	/* counts and packets in update_itr are dependent on these numbers */
+	switch (current_itr) {
 	case lowest_latency:
 		new_itr = 70000;
 		break;
@@ -2578,8 +2570,7 @@ set_itr_now:
 		 * increasing
 		 */
 		new_itr = new_itr > adapter->itr ?
-			     min(adapter->itr + (new_itr >> 2), new_itr) :
-			     new_itr;
+		    min(adapter->itr + (new_itr >> 2), new_itr) : new_itr;
 		adapter->itr = new_itr;
 		adapter->rx_ring->itr_val = new_itr;
 		if (adapter->msix_entries)
@@ -2810,8 +2801,7 @@ static void e1000_update_mng_vlan(struct e1000_adapter *adapter)
 	u16 vid = adapter->hw.mng_cookie.vlan_id;
 	u16 old_vid = adapter->mng_vlan_id;
 
-	if (adapter->hw.mng_cookie.status &
-	    E1000_MNG_DHCP_COOKIE_STATUS_VLAN) {
+	if (adapter->hw.mng_cookie.status & E1000_MNG_DHCP_COOKIE_STATUS_VLAN) {
 		e1000_vlan_rx_add_vid(netdev, vid);
 		adapter->mng_vlan_id = vid;
 	}
@@ -2827,7 +2817,7 @@ static void e1000_restore_vlan(struct e1000_adapter *adapter)
 	e1000_vlan_rx_add_vid(adapter->netdev, 0);
 
 	for_each_set_bit(vid, adapter->active_vlans, VLAN_N_VID)
-		e1000_vlan_rx_add_vid(adapter->netdev, vid);
+	    e1000_vlan_rx_add_vid(adapter->netdev, vid);
 }
 
 static void e1000_init_manageability_pt(struct e1000_adapter *adapter)
@@ -3002,8 +2992,8 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter)
 	rctl = er32(RCTL);
 	rctl &= ~(3 << E1000_RCTL_MO_SHIFT);
 	rctl |= E1000_RCTL_EN | E1000_RCTL_BAM |
-		E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF |
-		(adapter->hw.mac.mc_filter_type << E1000_RCTL_MO_SHIFT);
+	    E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF |
+	    (adapter->hw.mac.mc_filter_type << E1000_RCTL_MO_SHIFT);
 
 	/* Do not Store bad packets */
 	rctl &= ~E1000_RCTL_SBP;
@@ -3089,19 +3079,17 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter)
 		/* Enable Packet split descriptors */
 		rctl |= E1000_RCTL_DTYP_PS;
 
-		psrctl |= adapter->rx_ps_bsize0 >>
-			E1000_PSRCTL_BSIZE0_SHIFT;
+		psrctl |= adapter->rx_ps_bsize0 >> E1000_PSRCTL_BSIZE0_SHIFT;
 
 		switch (adapter->rx_ps_pages) {
 		case 3:
-			psrctl |= PAGE_SIZE <<
-				E1000_PSRCTL_BSIZE3_SHIFT;
+			psrctl |= PAGE_SIZE << E1000_PSRCTL_BSIZE3_SHIFT;
+			/* fall-through */
 		case 2:
-			psrctl |= PAGE_SIZE <<
-				E1000_PSRCTL_BSIZE2_SHIFT;
+			psrctl |= PAGE_SIZE << E1000_PSRCTL_BSIZE2_SHIFT;
+			/* fall-through */
 		case 1:
-			psrctl |= PAGE_SIZE >>
-				E1000_PSRCTL_BSIZE1_SHIFT;
+			psrctl |= PAGE_SIZE >> E1000_PSRCTL_BSIZE1_SHIFT;
 			break;
 		}
 
@@ -3275,7 +3263,7 @@ static int e1000e_write_mc_addr_list(struct net_device *netdev)
 	/* update_mc_addr_list expects a packed array of only addresses. */
 	i = 0;
 	netdev_for_each_mc_addr(ha, netdev)
-		memcpy(mta_list + (i++ * ETH_ALEN), ha->addr, ETH_ALEN);
+	    memcpy(mta_list + (i++ * ETH_ALEN), ha->addr, ETH_ALEN);
 
 	hw->mac.ops.update_mc_addr_list(hw, mta_list, i);
 	kfree(mta_list);
@@ -3752,8 +3740,7 @@ void e1000e_reset(struct e1000_adapter *adapter)
 		 * but don't include ethernet FCS because hardware appends it
 		 */
 		min_tx_space = (adapter->max_frame_size +
-				sizeof(struct e1000_tx_desc) -
-				ETH_FCS_LEN) * 2;
+				sizeof(struct e1000_tx_desc) - ETH_FCS_LEN) * 2;
 		min_tx_space = ALIGN(min_tx_space, 1024);
 		min_tx_space >>= 10;
 		/* software strips receive CRC, so leave room for it */
@@ -3856,13 +3843,13 @@ void e1000e_reset(struct e1000_adapter *adapter)
 		if ((adapter->max_frame_size * 2) > (pba << 10)) {
 			if (!(adapter->flags2 & FLAG2_DISABLE_AIM)) {
 				dev_info(&adapter->pdev->dev,
-					"Interrupt Throttle Rate turned off\n");
+					 "Interrupt Throttle Rate off\n");
 				adapter->flags2 |= FLAG2_DISABLE_AIM;
 				e1000e_write_itr(adapter, 0);
 			}
 		} else if (adapter->flags2 & FLAG2_DISABLE_AIM) {
 			dev_info(&adapter->pdev->dev,
-				 "Interrupt Throttle Rate turned on\n");
+				 "Interrupt Throttle Rate on\n");
 			adapter->flags2 &= ~FLAG2_DISABLE_AIM;
 			adapter->itr = 20000;
 			e1000e_write_itr(adapter, adapter->itr);
@@ -3893,6 +3880,38 @@ void e1000e_reset(struct e1000_adapter *adapter)
 	/* initialize systim and reset the ns time counter */
 	e1000e_config_hwtstamp(adapter);
 
+	/* Set EEE advertisement as appropriate */
+	if (adapter->flags2 & FLAG2_HAS_EEE) {
+		s32 ret_val;
+		u16 adv_addr;
+
+		switch (hw->phy.type) {
+		case e1000_phy_82579:
+			adv_addr = I82579_EEE_ADVERTISEMENT;
+			break;
+		case e1000_phy_i217:
+			adv_addr = I217_EEE_ADVERTISEMENT;
+			break;
+		default:
+			dev_err(&adapter->pdev->dev,
+				"Invalid PHY type setting EEE advertisement\n");
+			return;
+		}
+
+		ret_val = hw->phy.ops.acquire(hw);
+		if (ret_val) {
+			dev_err(&adapter->pdev->dev,
+				"EEE advertisement - unable to acquire PHY\n");
+			return;
+		}
+
+		e1000_write_emi_reg_locked(hw, adv_addr,
+					   hw->dev_spec.ich8lan.eee_disable ?
+					   0 : adapter->eee_advert);
+
+		hw->phy.ops.release(hw);
+	}
+
 	if (!netif_running(adapter->netdev) &&
 	    !test_bit(__E1000_TESTING, &adapter->state)) {
 		e1000_power_down_phy(adapter);
@@ -4261,8 +4280,7 @@ static int e1000_open(struct net_device *netdev)
 	e1000e_power_up_phy(adapter);
 
 	adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
-	if ((adapter->hw.mng_cookie.status &
-	     E1000_MNG_DHCP_COOKIE_STATUS_VLAN))
+	if ((adapter->hw.mng_cookie.status & E1000_MNG_DHCP_COOKIE_STATUS_VLAN))
 		e1000_update_mng_vlan(adapter);
 
 	/* DMA latency requirement to workaround jumbo issue */
@@ -4365,8 +4383,7 @@ static int e1000_close(struct net_device *netdev)
 	/* kill manageability vlan ID if supported, but not if a vlan with
 	 * the same ID is registered on the host OS (let 8021q kill it)
 	 */
-	if (adapter->hw.mng_cookie.status &
-	    E1000_MNG_DHCP_COOKIE_STATUS_VLAN)
+	if (adapter->hw.mng_cookie.status & E1000_MNG_DHCP_COOKIE_STATUS_VLAN)
 		e1000_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id);
 
 	/* If AMT is enabled, let the firmware know that the network
@@ -4382,6 +4399,7 @@ static int e1000_close(struct net_device *netdev)
 
 	return 0;
 }
+
 /**
  * e1000_set_mac - Change the Ethernet Address of the NIC
  * @netdev: network interface device structure
@@ -4432,7 +4450,8 @@ static int e1000_set_mac(struct net_device *netdev, void *p)
 static void e1000e_update_phy_task(struct work_struct *work)
 {
 	struct e1000_adapter *adapter = container_of(work,
-					struct e1000_adapter, update_phy_task);
+						     struct e1000_adapter,
+						     update_phy_task);
 
 	if (test_bit(__E1000_DOWN, &adapter->state))
 		return;
@@ -4449,7 +4468,7 @@ static void e1000e_update_phy_task(struct work_struct *work)
  **/
 static void e1000_update_phy_info(unsigned long data)
 {
-	struct e1000_adapter *adapter = (struct e1000_adapter *) data;
+	struct e1000_adapter *adapter = (struct e1000_adapter *)data;
 
 	if (test_bit(__E1000_DOWN, &adapter->state))
 		return;
@@ -4616,18 +4635,16 @@ static void e1000e_update_stats(struct e1000_adapter *adapter)
 	 * our own version based on RUC and ROC
 	 */
 	netdev->stats.rx_errors = adapter->stats.rxerrc +
-		adapter->stats.crcerrs + adapter->stats.algnerrc +
-		adapter->stats.ruc + adapter->stats.roc +
-		adapter->stats.cexterr;
+	    adapter->stats.crcerrs + adapter->stats.algnerrc +
+	    adapter->stats.ruc + adapter->stats.roc + adapter->stats.cexterr;
 	netdev->stats.rx_length_errors = adapter->stats.ruc +
-					      adapter->stats.roc;
+	    adapter->stats.roc;
 	netdev->stats.rx_crc_errors = adapter->stats.crcerrs;
 	netdev->stats.rx_frame_errors = adapter->stats.algnerrc;
 	netdev->stats.rx_missed_errors = adapter->stats.mpc;
 
 	/* Tx Errors */
-	netdev->stats.tx_errors = adapter->stats.ecol +
-				       adapter->stats.latecol;
+	netdev->stats.tx_errors = adapter->stats.ecol + adapter->stats.latecol;
 	netdev->stats.tx_aborted_errors = adapter->stats.ecol;
 	netdev->stats.tx_window_errors = adapter->stats.latecol;
 	netdev->stats.tx_carrier_errors = adapter->stats.tncrs;
@@ -4785,7 +4802,7 @@ static void e1000e_check_82574_phy_workaround(struct e1000_adapter *adapter)
  **/
 static void e1000_watchdog(unsigned long data)
 {
-	struct e1000_adapter *adapter = (struct e1000_adapter *) data;
+	struct e1000_adapter *adapter = (struct e1000_adapter *)data;
 
 	/* Do the rest outside of interrupt context */
 	schedule_work(&adapter->watchdog_task);
@@ -4796,7 +4813,8 @@ static void e1000_watchdog(unsigned long data)
 static void e1000_watchdog_task(struct work_struct *work)
 {
 	struct e1000_adapter *adapter = container_of(work,
-					struct e1000_adapter, watchdog_task);
+						     struct e1000_adapter,
+						     watchdog_task);
 	struct net_device *netdev = adapter->netdev;
 	struct e1000_mac_info *mac = &adapter->hw.mac;
 	struct e1000_phy_info *phy = &adapter->hw.phy;
@@ -4830,8 +4848,8 @@ static void e1000_watchdog_task(struct work_struct *work)
 			/* update snapshot of PHY registers on LSC */
 			e1000_phy_read_status(adapter);
 			mac->ops.get_link_up_info(&adapter->hw,
-						   &adapter->link_speed,
-						   &adapter->link_duplex);
+						  &adapter->link_speed,
+						  &adapter->link_duplex);
 			e1000_print_link_info(adapter);
 
 			/* check if SmartSpeed worked */
@@ -4944,7 +4962,7 @@ static void e1000_watchdog_task(struct work_struct *work)
 				adapter->flags |= FLAG_RESTART_NOW;
 			else
 				pm_schedule_suspend(netdev->dev.parent,
-							LINK_TIMEOUT);
+						    LINK_TIMEOUT);
 		}
 	}
 
@@ -4979,8 +4997,8 @@ link_up:
 		 */
 		u32 goc = (adapter->gotc + adapter->gorc) / 10000;
 		u32 dif = (adapter->gotc > adapter->gorc ?
-			    adapter->gotc - adapter->gorc :
-			    adapter->gorc - adapter->gotc) / 10000;
+			   adapter->gotc - adapter->gorc :
+			   adapter->gorc - adapter->gotc) / 10000;
 		u32 itr = goc > 0 ? (dif * 6000 / goc + 2000) : 8000;
 
 		e1000e_write_itr(adapter, itr);
@@ -5059,14 +5077,14 @@ static int e1000_tso(struct e1000_ring *tx_ring, struct sk_buff *skb)
 		iph->tot_len = 0;
 		iph->check = 0;
 		tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr,
-		                                         0, IPPROTO_TCP, 0);
+							 0, IPPROTO_TCP, 0);
 		cmd_length = E1000_TXD_CMD_IP;
 		ipcse = skb_transport_offset(skb) - 1;
 	} 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);
+						       &ipv6_hdr(skb)->daddr,
+						       0, IPPROTO_TCP, 0);
 		ipcse = 0;
 	}
 	ipcss = skb_network_offset(skb);
@@ -5075,7 +5093,7 @@ static int e1000_tso(struct e1000_ring *tx_ring, struct sk_buff *skb)
 	tucso = (void *)&(tcp_hdr(skb)->check) - (void *)skb->data;
 
 	cmd_length |= (E1000_TXD_CMD_DEXT | E1000_TXD_CMD_TSE |
-	               E1000_TXD_CMD_TCP | (skb->len - (hdr_len)));
+		       E1000_TXD_CMD_TCP | (skb->len - (hdr_len)));
 
 	i = tx_ring->next_to_use;
 	context_desc = E1000_CONTEXT_DESC(*tx_ring, i);
@@ -5145,8 +5163,7 @@ static bool e1000_tx_csum(struct e1000_ring *tx_ring, struct sk_buff *skb)
 
 	context_desc->lower_setup.ip_config = 0;
 	context_desc->upper_setup.tcp_fields.tucss = css;
-	context_desc->upper_setup.tcp_fields.tucso =
-				css + skb->csum_offset;
+	context_desc->upper_setup.tcp_fields.tucso = css + skb->csum_offset;
 	context_desc->upper_setup.tcp_fields.tucse = 0;
 	context_desc->tcp_seg_setup.data = 0;
 	context_desc->cmd_and_length = cpu_to_le32(cmd_len);
@@ -5219,7 +5236,8 @@ static int e1000_tx_map(struct e1000_ring *tx_ring, struct sk_buff *skb,
 			buffer_info->time_stamp = jiffies;
 			buffer_info->next_to_watch = i;
 			buffer_info->dma = skb_frag_dma_map(&pdev->dev, frag,
-						offset, size, DMA_TO_DEVICE);
+							    offset, size,
+							    DMA_TO_DEVICE);
 			buffer_info->mapped_as_page = true;
 			if (dma_mapping_error(&pdev->dev, buffer_info->dma))
 				goto dma_error;
@@ -5268,7 +5286,7 @@ static void e1000_tx_queue(struct e1000_ring *tx_ring, int tx_flags, int count)
 
 	if (tx_flags & E1000_TX_FLAGS_TSO) {
 		txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D |
-			     E1000_TXD_CMD_TSE;
+		    E1000_TXD_CMD_TSE;
 		txd_upper |= E1000_TXD_POPTS_TXSM << 8;
 
 		if (tx_flags & E1000_TX_FLAGS_IPV4)
@@ -5299,8 +5317,8 @@ static void e1000_tx_queue(struct e1000_ring *tx_ring, int tx_flags, int count)
 		buffer_info = &tx_ring->buffer_info[i];
 		tx_desc = E1000_TX_DESC(*tx_ring, i);
 		tx_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
-		tx_desc->lower.data =
-			cpu_to_le32(txd_lower | buffer_info->length);
+		tx_desc->lower.data = cpu_to_le32(txd_lower |
+						  buffer_info->length);
 		tx_desc->upper.data = cpu_to_le32(txd_upper);
 
 		i++;
@@ -5350,11 +5368,11 @@ static int e1000_transfer_dhcp_info(struct e1000_adapter *adapter,
 	if (skb->len <= MINIMUM_DHCP_PACKET_SIZE)
 		return 0;
 
-	if (((struct ethhdr *) skb->data)->h_proto != htons(ETH_P_IP))
+	if (((struct ethhdr *)skb->data)->h_proto != htons(ETH_P_IP))
 		return 0;
 
 	{
-		const struct iphdr *ip = (struct iphdr *)((u8 *)skb->data+14);
+		const struct iphdr *ip = (struct iphdr *)((u8 *)skb->data + 14);
 		struct udphdr *udp;
 
 		if (ip->protocol != IPPROTO_UDP)
@@ -5579,7 +5597,7 @@ static void e1000_reset_task(struct work_struct *work)
  * Returns the address of the device statistics structure.
  **/
 struct rtnl_link_stats64 *e1000e_get_stats64(struct net_device *netdev,
-                                             struct rtnl_link_stats64 *stats)
+					     struct rtnl_link_stats64 *stats)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 
@@ -5600,18 +5618,15 @@ struct rtnl_link_stats64 *e1000e_get_stats64(struct net_device *netdev,
 	 * our own version based on RUC and ROC
 	 */
 	stats->rx_errors = adapter->stats.rxerrc +
-		adapter->stats.crcerrs + adapter->stats.algnerrc +
-		adapter->stats.ruc + adapter->stats.roc +
-		adapter->stats.cexterr;
-	stats->rx_length_errors = adapter->stats.ruc +
-					      adapter->stats.roc;
+	    adapter->stats.crcerrs + adapter->stats.algnerrc +
+	    adapter->stats.ruc + adapter->stats.roc + adapter->stats.cexterr;
+	stats->rx_length_errors = adapter->stats.ruc + adapter->stats.roc;
 	stats->rx_crc_errors = adapter->stats.crcerrs;
 	stats->rx_frame_errors = adapter->stats.algnerrc;
 	stats->rx_missed_errors = adapter->stats.mpc;
 
 	/* Tx Errors */
-	stats->tx_errors = adapter->stats.ecol +
-				       adapter->stats.latecol;
+	stats->tx_errors = adapter->stats.ecol + adapter->stats.latecol;
 	stats->tx_aborted_errors = adapter->stats.ecol;
 	stats->tx_window_errors = adapter->stats.latecol;
 	stats->tx_carrier_errors = adapter->stats.tncrs;
@@ -5680,9 +5695,9 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu)
 
 	/* adjust allocation if LPE protects us, and we aren't using SBP */
 	if ((max_frame == ETH_FRAME_LEN + ETH_FCS_LEN) ||
-	     (max_frame == ETH_FRAME_LEN + VLAN_HLEN + ETH_FCS_LEN))
+	    (max_frame == ETH_FRAME_LEN + VLAN_HLEN + ETH_FCS_LEN))
 		adapter->rx_buffer_len = ETH_FRAME_LEN + VLAN_HLEN
-					 + ETH_FCS_LEN;
+		    + ETH_FCS_LEN;
 
 	if (netif_running(netdev))
 		e1000e_up(adapter);
@@ -5861,7 +5876,7 @@ static int e1000_init_phy_wakeup(struct e1000_adapter *adapter, u32 wufc)
 	phy_reg &= ~(BM_RCTL_MO_MASK);
 	if (mac_reg & E1000_RCTL_MO_3)
 		phy_reg |= (((mac_reg & E1000_RCTL_MO_3) >> E1000_RCTL_MO_SHIFT)
-				<< BM_RCTL_MO_SHIFT);
+			    << BM_RCTL_MO_SHIFT);
 	if (mac_reg & E1000_RCTL_BAM)
 		phy_reg |= BM_RCTL_BAM;
 	if (mac_reg & E1000_RCTL_PMCF)
@@ -5930,10 +5945,6 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool runtime)
 		}
 
 		ctrl = er32(CTRL);
-		/* advertise wake from D3Cold */
-		#define E1000_CTRL_ADVD3WUC 0x00100000
-		/* phy power management enable */
-		#define E1000_CTRL_EN_PHY_PWR_MGMT 0x00200000
 		ctrl |= E1000_CTRL_ADVD3WUC;
 		if (!(adapter->flags2 & FLAG2_HAS_PHY_WAKEUP))
 			ctrl |= E1000_CTRL_EN_PHY_PWR_MGMT;
@@ -5977,8 +5988,6 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool runtime)
 	 */
 	e1000e_release_hw_control(adapter);
 
-	pci_clear_master(pdev);
-
 	/* The pci-e switch on some quad port adapters will report a
 	 * correctable error when the MAC transitions from D0 to D3.  To
 	 * prevent this we need to mask off the correctable errors on the
@@ -6077,24 +6086,24 @@ static int __e1000_resume(struct pci_dev *pdev)
 		e1e_rphy(&adapter->hw, BM_WUS, &phy_data);
 		if (phy_data) {
 			e_info("PHY Wakeup cause - %s\n",
-				phy_data & E1000_WUS_EX ? "Unicast Packet" :
-				phy_data & E1000_WUS_MC ? "Multicast Packet" :
-				phy_data & E1000_WUS_BC ? "Broadcast Packet" :
-				phy_data & E1000_WUS_MAG ? "Magic Packet" :
-				phy_data & E1000_WUS_LNKC ?
-				"Link Status Change" : "other");
+			       phy_data & E1000_WUS_EX ? "Unicast Packet" :
+			       phy_data & E1000_WUS_MC ? "Multicast Packet" :
+			       phy_data & E1000_WUS_BC ? "Broadcast Packet" :
+			       phy_data & E1000_WUS_MAG ? "Magic Packet" :
+			       phy_data & E1000_WUS_LNKC ?
+			       "Link Status Change" : "other");
 		}
 		e1e_wphy(&adapter->hw, BM_WUS, ~0);
 	} else {
 		u32 wus = er32(WUS);
 		if (wus) {
 			e_info("MAC Wakeup cause - %s\n",
-				wus & E1000_WUS_EX ? "Unicast Packet" :
-				wus & E1000_WUS_MC ? "Multicast Packet" :
-				wus & E1000_WUS_BC ? "Broadcast Packet" :
-				wus & E1000_WUS_MAG ? "Magic Packet" :
-				wus & E1000_WUS_LNKC ? "Link Status Change" :
-				"other");
+			       wus & E1000_WUS_EX ? "Unicast Packet" :
+			       wus & E1000_WUS_MC ? "Multicast Packet" :
+			       wus & E1000_WUS_BC ? "Broadcast Packet" :
+			       wus & E1000_WUS_MAG ? "Magic Packet" :
+			       wus & E1000_WUS_LNKC ? "Link Status Change" :
+			       "other");
 		}
 		ew32(WUS, ~0);
 	}
@@ -6369,7 +6378,7 @@ static void e1000_print_device_info(struct e1000_adapter *adapter)
 	e_info("(PCI Express:2.5GT/s:%s) %pM\n",
 	       /* bus width */
 	       ((hw->bus.width == e1000_bus_width_pcie_x4) ? "Width x4" :
-	        "Width x1"),
+		"Width x1"),
 	       /* MAC address */
 	       netdev->dev_addr);
 	e_info("Intel(R) PRO/%s Network Connection\n",
@@ -6479,7 +6488,7 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	resource_size_t flash_start, flash_len;
 	static int cards_found;
 	u16 aspm_disable_flag = 0;
-	int i, err, pci_using_dac;
+	int bars, i, err, pci_using_dac;
 	u16 eeprom_data = 0;
 	u16 eeprom_apme_mask = E1000_EEPROM_APME;
 
@@ -6506,15 +6515,16 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 			err = dma_set_coherent_mask(&pdev->dev,
 						    DMA_BIT_MASK(32));
 			if (err) {
-				dev_err(&pdev->dev, "No usable DMA configuration, aborting\n");
+				dev_err(&pdev->dev,
+					"No usable DMA configuration, aborting\n");
 				goto err_dma;
 			}
 		}
 	}
 
-	err = pci_request_selected_regions_exclusive(pdev,
-					  pci_select_bars(pdev, IORESOURCE_MEM),
-					  e1000e_driver_name);
+	bars = pci_select_bars(pdev, IORESOURCE_MEM);
+	err = pci_request_selected_regions_exclusive(pdev, bars,
+						     e1000e_driver_name);
 	if (err)
 		goto err_pci_reg;
 
@@ -6567,6 +6577,10 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 			goto err_flashmap;
 	}
 
+	/* Set default EEE advertisement */
+	if (adapter->flags2 & FLAG2_HAS_EEE)
+		adapter->eee_advert = MDIO_EEE_100TX | MDIO_EEE_1000T;
+
 	/* construct the net_device struct */
 	netdev->netdev_ops		= &e1000e_netdev_ops;
 	e1000e_set_ethtool_ops(netdev);
@@ -6683,11 +6697,11 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	init_timer(&adapter->watchdog_timer);
 	adapter->watchdog_timer.function = e1000_watchdog;
-	adapter->watchdog_timer.data = (unsigned long) adapter;
+	adapter->watchdog_timer.data = (unsigned long)adapter;
 
 	init_timer(&adapter->phy_info_timer);
 	adapter->phy_info_timer.function = e1000_update_phy_info;
-	adapter->phy_info_timer.data = (unsigned long) adapter;
+	adapter->phy_info_timer.data = (unsigned long)adapter;
 
 	INIT_WORK(&adapter->reset_task, e1000_reset_task);
 	INIT_WORK(&adapter->watchdog_task, e1000_watchdog_task);
@@ -6795,7 +6809,7 @@ err_ioremap:
 	free_netdev(netdev);
 err_alloc_etherdev:
 	pci_release_selected_regions(pdev,
-	                             pci_select_bars(pdev, IORESOURCE_MEM));
+				     pci_select_bars(pdev, IORESOURCE_MEM));
 err_pci_reg:
 err_dma:
 	pci_disable_device(pdev);
@@ -6865,7 +6879,7 @@ static void e1000_remove(struct pci_dev *pdev)
 	if (adapter->hw.flash_address)
 		iounmap(adapter->hw.flash_address);
 	pci_release_selected_regions(pdev,
-	                             pci_select_bars(pdev, IORESOURCE_MEM));
+				     pci_select_bars(pdev, IORESOURCE_MEM));
 
 	free_netdev(netdev);
 
@@ -6886,7 +6900,8 @@ static DEFINE_PCI_DEVICE_TABLE(e1000_pci_tbl) = {
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_COPPER), board_82571 },
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_FIBER), board_82571 },
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_QUAD_COPPER), board_82571 },
-	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_QUAD_COPPER_LP), board_82571 },
+	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_QUAD_COPPER_LP),
+	  board_82571 },
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_QUAD_FIBER), board_82571 },
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_SERDES), board_82571 },
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_SERDES_DUAL), board_82571 },
@@ -6962,8 +6977,8 @@ MODULE_DEVICE_TABLE(pci, e1000_pci_tbl);
 #ifdef CONFIG_PM
 static const struct dev_pm_ops e1000_pm_ops = {
 	SET_SYSTEM_SLEEP_PM_OPS(e1000_suspend, e1000_resume)
-	SET_RUNTIME_PM_OPS(e1000_runtime_suspend,
-				e1000_runtime_resume, e1000_idle)
+	SET_RUNTIME_PM_OPS(e1000_runtime_suspend, e1000_runtime_resume,
+			   e1000_idle)
 };
 #endif
 
diff --git a/drivers/net/ethernet/intel/e1000e/nvm.c b/drivers/net/ethernet/intel/e1000e/nvm.c
index 84fecc2..44ddc0a 100644
--- a/drivers/net/ethernet/intel/e1000e/nvm.c
+++ b/drivers/net/ethernet/intel/e1000e/nvm.c
@@ -630,7 +630,7 @@ void e1000e_reload_nvm_generic(struct e1000_hw *hw)
 {
 	u32 ctrl_ext;
 
-	udelay(10);
+	usleep_range(10, 20);
 	ctrl_ext = er32(CTRL_EXT);
 	ctrl_ext |= E1000_CTRL_EXT_EE_RST;
 	ew32(CTRL_EXT, ctrl_ext);
diff --git a/drivers/net/ethernet/intel/e1000e/param.c b/drivers/net/ethernet/intel/e1000e/param.c
index 98da75d..c16bd75 100644
--- a/drivers/net/ethernet/intel/e1000e/param.c
+++ b/drivers/net/ethernet/intel/e1000e/param.c
@@ -45,7 +45,7 @@
 unsigned int copybreak = COPYBREAK_DEFAULT;
 module_param(copybreak, uint, 0644);
 MODULE_PARM_DESC(copybreak,
-	"Maximum size of packet that is copied to a new buffer on receive");
+		 "Maximum size of packet that is copied to a new buffer on receive");
 
 /* All parameters are treated the same, as an integer array of values.
  * This macro just reduces the need to repeat the same declaration code
@@ -143,7 +143,8 @@ E1000_PARAM(KumeranLockLoss, "Enable Kumeran lock loss workaround");
  *
  * Default Value: 1 (enabled)
  */
-E1000_PARAM(WriteProtectNVM, "Write-protect NVM [WARNING: disabling this can lead to corrupted NVM]");
+E1000_PARAM(WriteProtectNVM,
+	    "Write-protect NVM [WARNING: disabling this can lead to corrupted NVM]");
 
 /* Enable CRC Stripping
  *
@@ -160,13 +161,18 @@ struct e1000_option {
 	const char *err;
 	int def;
 	union {
-		struct { /* range_option info */
+		/* range_option info */
+		struct {
 			int min;
 			int max;
 		} r;
-		struct { /* list_option info */
+		/* list_option info */
+		struct {
 			int nr;
-			struct e1000_opt_list { int i; char *str; } *p;
+			struct e1000_opt_list {
+				int i;
+				char *str;
+			} *p;
 		} l;
 	} arg;
 };
@@ -246,7 +252,8 @@ void e1000e_check_options(struct e1000_adapter *adapter)
 			   "Using defaults for all values\n");
 	}
 
-	{ /* Transmit Interrupt Delay */
+	/* Transmit Interrupt Delay */
+	{
 		static const struct e1000_option opt = {
 			.type = range_option,
 			.name = "Transmit Interrupt Delay",
@@ -265,7 +272,8 @@ void e1000e_check_options(struct e1000_adapter *adapter)
 			adapter->tx_int_delay = opt.def;
 		}
 	}
-	{ /* Transmit Absolute Interrupt Delay */
+	/* Transmit Absolute Interrupt Delay */
+	{
 		static const struct e1000_option opt = {
 			.type = range_option,
 			.name = "Transmit Absolute Interrupt Delay",
@@ -284,7 +292,8 @@ void e1000e_check_options(struct e1000_adapter *adapter)
 			adapter->tx_abs_int_delay = opt.def;
 		}
 	}
-	{ /* Receive Interrupt Delay */
+	/* Receive Interrupt Delay */
+	{
 		static struct e1000_option opt = {
 			.type = range_option,
 			.name = "Receive Interrupt Delay",
@@ -303,7 +312,8 @@ void e1000e_check_options(struct e1000_adapter *adapter)
 			adapter->rx_int_delay = opt.def;
 		}
 	}
-	{ /* Receive Absolute Interrupt Delay */
+	/* Receive Absolute Interrupt Delay */
+	{
 		static const struct e1000_option opt = {
 			.type = range_option,
 			.name = "Receive Absolute Interrupt Delay",
@@ -322,7 +332,8 @@ void e1000e_check_options(struct e1000_adapter *adapter)
 			adapter->rx_abs_int_delay = opt.def;
 		}
 	}
-	{ /* Interrupt Throttling Rate */
+	/* Interrupt Throttling Rate */
+	{
 		static const struct e1000_option opt = {
 			.type = range_option,
 			.name = "Interrupt Throttling Rate (ints/sec)",
@@ -392,7 +403,8 @@ void e1000e_check_options(struct e1000_adapter *adapter)
 			break;
 		}
 	}
-	{ /* Interrupt Mode */
+	/* Interrupt Mode */
+	{
 		static struct e1000_option opt = {
 			.type = range_option,
 			.name = "Interrupt Mode",
@@ -435,7 +447,8 @@ void e1000e_check_options(struct e1000_adapter *adapter)
 		kfree(opt.err);
 #endif
 	}
-	{ /* Smart Power Down */
+	/* Smart Power Down */
+	{
 		static const struct e1000_option opt = {
 			.type = enable_option,
 			.name = "PHY Smart Power Down",
@@ -450,7 +463,8 @@ void e1000e_check_options(struct e1000_adapter *adapter)
 				adapter->flags |= FLAG_SMART_POWER_DOWN;
 		}
 	}
-	{ /* CRC Stripping */
+	/* CRC Stripping */
+	{
 		static const struct e1000_option opt = {
 			.type = enable_option,
 			.name = "CRC Stripping",
@@ -470,27 +484,28 @@ void e1000e_check_options(struct e1000_adapter *adapter)
 			adapter->flags2 |= FLAG2_DFLT_CRC_STRIPPING;
 		}
 	}
-	{ /* Kumeran Lock Loss Workaround */
+	/* Kumeran Lock Loss Workaround */
+	{
 		static const struct e1000_option opt = {
 			.type = enable_option,
 			.name = "Kumeran Lock Loss Workaround",
 			.err  = "defaulting to Enabled",
 			.def  = OPTION_ENABLED
 		};
+		bool enabled = opt.def;
 
 		if (num_KumeranLockLoss > bd) {
 			unsigned int kmrn_lock_loss = KumeranLockLoss[bd];
 			e1000_validate_option(&kmrn_lock_loss, &opt, adapter);
-			if (hw->mac.type == e1000_ich8lan)
-				e1000e_set_kmrn_lock_loss_workaround_ich8lan(hw,
-								kmrn_lock_loss);
-		} else {
-			if (hw->mac.type == e1000_ich8lan)
-				e1000e_set_kmrn_lock_loss_workaround_ich8lan(hw,
-								       opt.def);
+			enabled = kmrn_lock_loss;
 		}
+
+		if (hw->mac.type == e1000_ich8lan)
+			e1000e_set_kmrn_lock_loss_workaround_ich8lan(hw,
+								     enabled);
 	}
-	{ /* Write-protect NVM */
+	/* Write-protect NVM */
+	{
 		static const struct e1000_option opt = {
 			.type = enable_option,
 			.name = "Write-protect NVM",
@@ -500,7 +515,8 @@ void e1000e_check_options(struct e1000_adapter *adapter)
 
 		if (adapter->flags & FLAG_IS_ICH) {
 			if (num_WriteProtectNVM > bd) {
-				unsigned int write_protect_nvm = WriteProtectNVM[bd];
+				unsigned int write_protect_nvm =
+				    WriteProtectNVM[bd];
 				e1000_validate_option(&write_protect_nvm, &opt,
 						      adapter);
 				if (write_protect_nvm)
diff --git a/drivers/net/ethernet/intel/e1000e/phy.c b/drivers/net/ethernet/intel/e1000e/phy.c
index 0930c13..59c76a6 100644
--- a/drivers/net/ethernet/intel/e1000e/phy.c
+++ b/drivers/net/ethernet/intel/e1000e/phy.c
@@ -37,7 +37,9 @@ static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset,
 
 /* Cable length tables */
 static const u16 e1000_m88_cable_length_table[] = {
-	0, 50, 80, 110, 140, 140, E1000_CABLE_LENGTH_UNDEFINED };
+	0, 50, 80, 110, 140, 140, E1000_CABLE_LENGTH_UNDEFINED
+};
+
 #define M88E1000_CABLE_LENGTH_TABLE_SIZE \
 		ARRAY_SIZE(e1000_m88_cable_length_table)
 
@@ -49,7 +51,9 @@ static const u16 e1000_igp_2_cable_length_table[] = {
 	66, 70, 75, 79, 83, 87, 91, 94, 98, 101, 104, 60, 66, 72, 77, 82,
 	87, 92, 96, 100, 104, 108, 111, 114, 117, 119, 121, 83, 89, 95,
 	100, 105, 109, 113, 116, 119, 122, 124, 104, 109, 114, 118, 121,
-	124};
+	124
+};
+
 #define IGP02E1000_CABLE_LENGTH_TABLE_SIZE \
 		ARRAY_SIZE(e1000_igp_2_cable_length_table)
 
@@ -67,8 +71,7 @@ s32 e1000e_check_reset_block_generic(struct e1000_hw *hw)
 
 	manc = er32(MANC);
 
-	return (manc & E1000_MANC_BLK_PHY_RST_ON_IDE) ?
-	       E1000_BLK_PHY_RESET : 0;
+	return (manc & E1000_MANC_BLK_PHY_RST_ON_IDE) ? E1000_BLK_PHY_RESET : 0;
 }
 
 /**
@@ -94,7 +97,7 @@ s32 e1000e_get_phy_id(struct e1000_hw *hw)
 			return ret_val;
 
 		phy->id = (u32)(phy_id << 16);
-		udelay(20);
+		usleep_range(20, 40);
 		ret_val = e1e_rphy(hw, MII_PHYSID2, &phy_id);
 		if (ret_val)
 			return ret_val;
@@ -175,7 +178,13 @@ s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
 		e_dbg("MDI Error\n");
 		return -E1000_ERR_PHY;
 	}
-	*data = (u16) mdic;
+	if (((mdic & E1000_MDIC_REG_MASK) >> E1000_MDIC_REG_SHIFT) != offset) {
+		e_dbg("MDI Read offset error - requested %d, returned %d\n",
+		      offset,
+		      (mdic & E1000_MDIC_REG_MASK) >> E1000_MDIC_REG_SHIFT);
+		return -E1000_ERR_PHY;
+	}
+	*data = (u16)mdic;
 
 	/* Allow some time after each MDIC transaction to avoid
 	 * reading duplicate data in the next MDIC transaction.
@@ -233,6 +242,12 @@ s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
 		e_dbg("MDI Error\n");
 		return -E1000_ERR_PHY;
 	}
+	if (((mdic & E1000_MDIC_REG_MASK) >> E1000_MDIC_REG_SHIFT) != offset) {
+		e_dbg("MDI Write offset error - requested %d, returned %d\n",
+		      offset,
+		      (mdic & E1000_MDIC_REG_MASK) >> E1000_MDIC_REG_SHIFT);
+		return -E1000_ERR_PHY;
+	}
 
 	/* Allow some time after each MDIC transaction to avoid
 	 * reading duplicate data in the next MDIC transaction.
@@ -324,7 +339,7 @@ s32 e1000_set_page_igp(struct e1000_hw *hw, u16 page)
  *  semaphores before exiting.
  **/
 static s32 __e1000e_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data,
-                                    bool locked)
+				     bool locked)
 {
 	s32 ret_val = 0;
 
@@ -391,7 +406,7 @@ s32 e1000e_read_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 *data)
  *  at the offset.  Release any acquired semaphores before exiting.
  **/
 static s32 __e1000e_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data,
-                                     bool locked)
+				      bool locked)
 {
 	s32 ret_val = 0;
 
@@ -410,8 +425,7 @@ static s32 __e1000e_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data,
 						    (u16)offset);
 	if (!ret_val)
 		ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS &
-							offset,
-						    data);
+						    offset, data);
 	if (!locked)
 		hw->phy.ops.release(hw);
 
@@ -458,7 +472,7 @@ s32 e1000e_write_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 data)
  *  Release any acquired semaphores before exiting.
  **/
 static s32 __e1000_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data,
-                                 bool locked)
+				 bool locked)
 {
 	u32 kmrnctrlsta;
 
@@ -531,7 +545,7 @@ s32 e1000e_read_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 *data)
  *  before exiting.
  **/
 static s32 __e1000_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data,
-                                  bool locked)
+				  bool locked)
 {
 	u32 kmrnctrlsta;
 
@@ -772,8 +786,7 @@ s32 e1000e_copper_link_setup_m88(struct e1000_hw *hw)
 
 		phy_data |= M88E1000_EPSCR_TX_CLK_25;
 
-		if ((phy->revision == 2) &&
-		    (phy->id == M88E1111_I_PHY_ID)) {
+		if ((phy->revision == 2) && (phy->id == M88E1111_I_PHY_ID)) {
 			/* 82573L PHY - set the downshift counter to 5x. */
 			phy_data &= ~M88EC018_EPSCR_DOWNSHIFT_COUNTER_MASK;
 			phy_data |= M88EC018_EPSCR_DOWNSHIFT_COUNTER_5X;
@@ -1296,7 +1309,7 @@ s32 e1000e_phy_force_speed_duplex_m88(struct e1000_hw *hw)
 		e_dbg("Waiting for forced speed/duplex link on M88 phy.\n");
 
 		ret_val = e1000e_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
-						     100000, &link);
+						      100000, &link);
 		if (ret_val)
 			return ret_val;
 
@@ -1319,7 +1332,7 @@ s32 e1000e_phy_force_speed_duplex_m88(struct e1000_hw *hw)
 
 		/* Try once more */
 		ret_val = e1000e_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
-						     100000, &link);
+						      100000, &link);
 		if (ret_val)
 			return ret_val;
 	}
@@ -1609,9 +1622,9 @@ s32 e1000_check_polarity_m88(struct e1000_hw *hw)
 	ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_STATUS, &data);
 
 	if (!ret_val)
-		phy->cable_polarity = (data & M88E1000_PSSR_REV_POLARITY)
-				      ? e1000_rev_polarity_reversed
-				      : e1000_rev_polarity_normal;
+		phy->cable_polarity = ((data & M88E1000_PSSR_REV_POLARITY)
+				       ? e1000_rev_polarity_reversed
+				       : e1000_rev_polarity_normal);
 
 	return ret_val;
 }
@@ -1653,9 +1666,9 @@ s32 e1000_check_polarity_igp(struct e1000_hw *hw)
 	ret_val = e1e_rphy(hw, offset, &data);
 
 	if (!ret_val)
-		phy->cable_polarity = (data & mask)
-				      ? e1000_rev_polarity_reversed
-				      : e1000_rev_polarity_normal;
+		phy->cable_polarity = ((data & mask)
+				       ? e1000_rev_polarity_reversed
+				       : e1000_rev_polarity_normal);
 
 	return ret_val;
 }
@@ -1685,9 +1698,9 @@ s32 e1000_check_polarity_ife(struct e1000_hw *hw)
 	ret_val = e1e_rphy(hw, offset, &phy_data);
 
 	if (!ret_val)
-		phy->cable_polarity = (phy_data & mask)
-		                       ? e1000_rev_polarity_reversed
-		                       : e1000_rev_polarity_normal;
+		phy->cable_polarity = ((phy_data & mask)
+				       ? e1000_rev_polarity_reversed
+				       : e1000_rev_polarity_normal);
 
 	return ret_val;
 }
@@ -1733,7 +1746,7 @@ static s32 e1000_wait_autoneg(struct e1000_hw *hw)
  *  Polls the PHY status register for link, 'iterations' number of times.
  **/
 s32 e1000e_phy_has_link_generic(struct e1000_hw *hw, u32 iterations,
-			       u32 usec_interval, bool *success)
+				u32 usec_interval, bool *success)
 {
 	s32 ret_val = 0;
 	u16 i, phy_status;
@@ -1756,7 +1769,7 @@ s32 e1000e_phy_has_link_generic(struct e1000_hw *hw, u32 iterations,
 		if (phy_status & BMSR_LSTATUS)
 			break;
 		if (usec_interval >= 1000)
-			mdelay(usec_interval/1000);
+			mdelay(usec_interval / 1000);
 		else
 			udelay(usec_interval);
 	}
@@ -1791,8 +1804,8 @@ s32 e1000e_get_cable_length_m88(struct e1000_hw *hw)
 	if (ret_val)
 		return ret_val;
 
-	index = (phy_data & M88E1000_PSSR_CABLE_LENGTH) >>
-	        M88E1000_PSSR_CABLE_LENGTH_SHIFT;
+	index = ((phy_data & M88E1000_PSSR_CABLE_LENGTH) >>
+		 M88E1000_PSSR_CABLE_LENGTH_SHIFT);
 
 	if (index >= M88E1000_CABLE_LENGTH_TABLE_SIZE - 1)
 		return -E1000_ERR_PHY;
@@ -1824,10 +1837,10 @@ s32 e1000e_get_cable_length_igp_2(struct e1000_hw *hw)
 	u16 cur_agc_index, max_agc_index = 0;
 	u16 min_agc_index = IGP02E1000_CABLE_LENGTH_TABLE_SIZE - 1;
 	static const u16 agc_reg_array[IGP02E1000_PHY_CHANNEL_NUM] = {
-	       IGP02E1000_PHY_AGC_A,
-	       IGP02E1000_PHY_AGC_B,
-	       IGP02E1000_PHY_AGC_C,
-	       IGP02E1000_PHY_AGC_D
+		IGP02E1000_PHY_AGC_A,
+		IGP02E1000_PHY_AGC_B,
+		IGP02E1000_PHY_AGC_C,
+		IGP02E1000_PHY_AGC_D
 	};
 
 	/* Read the AGC registers for all channels */
@@ -1841,8 +1854,8 @@ s32 e1000e_get_cable_length_igp_2(struct e1000_hw *hw)
 		 * that can be put into the lookup table to obtain the
 		 * approximate cable length.
 		 */
-		cur_agc_index = (phy_data >> IGP02E1000_AGC_LENGTH_SHIFT) &
-				IGP02E1000_AGC_LENGTH_MASK;
+		cur_agc_index = ((phy_data >> IGP02E1000_AGC_LENGTH_SHIFT) &
+				 IGP02E1000_AGC_LENGTH_MASK);
 
 		/* Array index bound check. */
 		if ((cur_agc_index >= IGP02E1000_CABLE_LENGTH_TABLE_SIZE) ||
@@ -1865,8 +1878,8 @@ s32 e1000e_get_cable_length_igp_2(struct e1000_hw *hw)
 	agc_value /= (IGP02E1000_PHY_CHANNEL_NUM - 2);
 
 	/* Calculate cable length with the error range of +/- 10 meters. */
-	phy->min_cable_length = ((agc_value - IGP02E1000_AGC_RANGE) > 0) ?
-				 (agc_value - IGP02E1000_AGC_RANGE) : 0;
+	phy->min_cable_length = (((agc_value - IGP02E1000_AGC_RANGE) > 0) ?
+				 (agc_value - IGP02E1000_AGC_RANGE) : 0);
 	phy->max_cable_length = agc_value + IGP02E1000_AGC_RANGE;
 
 	phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2;
@@ -2040,9 +2053,9 @@ s32 e1000_get_phy_info_ife(struct e1000_hw *hw)
 			return ret_val;
 	} else {
 		/* Polarity is forced */
-		phy->cable_polarity = (data & IFE_PSC_FORCE_POLARITY)
-		                      ? e1000_rev_polarity_reversed
-		                      : e1000_rev_polarity_normal;
+		phy->cable_polarity = ((data & IFE_PSC_FORCE_POLARITY)
+				       ? e1000_rev_polarity_reversed
+				       : e1000_rev_polarity_normal);
 	}
 
 	ret_val = e1e_rphy(hw, IFE_PHY_MDIX_CONTROL, &data);
@@ -2119,7 +2132,7 @@ s32 e1000e_phy_hw_reset_generic(struct e1000_hw *hw)
 	ew32(CTRL, ctrl);
 	e1e_flush();
 
-	udelay(150);
+	usleep_range(150, 300);
 
 	phy->ops.release(hw);
 
@@ -2375,13 +2388,13 @@ s32 e1000e_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data)
 
 		/* Page is shifted left, PHY expects (page x 32) */
 		ret_val = e1000e_write_phy_reg_mdic(hw, page_select,
-		                                    (page << page_shift));
+						    (page << page_shift));
 		if (ret_val)
 			goto release;
 	}
 
 	ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
-	                                    data);
+					    data);
 
 release:
 	hw->phy.ops.release(hw);
@@ -2433,13 +2446,13 @@ s32 e1000e_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data)
 
 		/* Page is shifted left, PHY expects (page x 32) */
 		ret_val = e1000e_write_phy_reg_mdic(hw, page_select,
-		                                    (page << page_shift));
+						    (page << page_shift));
 		if (ret_val)
 			goto release;
 	}
 
 	ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
-	                                   data);
+					   data);
 release:
 	hw->phy.ops.release(hw);
 	return ret_val;
@@ -2674,7 +2687,7 @@ static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset,
 	if (read) {
 		/* Read the Wakeup register page value using opcode 0x12 */
 		ret_val = e1000e_read_phy_reg_mdic(hw, BM_WUC_DATA_OPCODE,
-		                                   data);
+						   data);
 	} else {
 		/* Write the Wakeup register page value using opcode 0x12 */
 		ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_DATA_OPCODE,
@@ -2763,7 +2776,7 @@ static s32 __e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data,
 
 	if (page > 0 && page < HV_INTC_FC_PAGE_START) {
 		ret_val = e1000_access_phy_debug_regs_hv(hw, offset,
-		                                         data, true);
+							 data, true);
 		goto out;
 	}
 
@@ -2786,8 +2799,7 @@ static s32 __e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data,
 	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);
+	ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg, data);
 out:
 	if (!locked)
 		hw->phy.ops.release(hw);
@@ -2871,7 +2883,7 @@ static s32 __e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data,
 
 	if (page > 0 && page < HV_INTC_FC_PAGE_START) {
 		ret_val = e1000_access_phy_debug_regs_hv(hw, offset,
-		                                         &data, false);
+							 &data, false);
 		goto out;
 	}
 
@@ -2910,7 +2922,7 @@ static s32 __e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data,
 	      page << IGP_PAGE_SHIFT, reg);
 
 	ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg,
-	                                  data);
+					    data);
 
 out:
 	if (!locked)
@@ -2988,15 +3000,15 @@ static u32 e1000_get_phy_addr_for_hv_page(u32 page)
  *  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)
+					  u16 *data, bool read)
 {
 	s32 ret_val;
 	u32 addr_reg;
 	u32 data_reg;
 
 	/* This takes care of the difference with desktop vs mobile phy */
-	addr_reg = (hw->phy.type == e1000_phy_82578) ?
-	           I82578_ADDR_REG : I82577_ADDR_REG;
+	addr_reg = ((hw->phy.type == e1000_phy_82578) ?
+		    I82578_ADDR_REG : I82577_ADDR_REG);
 	data_reg = addr_reg + 1;
 
 	/* All operations in this function are phy address 2 */
@@ -3050,8 +3062,8 @@ s32 e1000_link_stall_workaround_hv(struct e1000_hw *hw)
 	if (ret_val)
 		return ret_val;
 
-	data &= BM_CS_STATUS_LINK_UP | BM_CS_STATUS_RESOLVED |
-		BM_CS_STATUS_SPEED_MASK;
+	data &= (BM_CS_STATUS_LINK_UP | BM_CS_STATUS_RESOLVED |
+		 BM_CS_STATUS_SPEED_MASK);
 
 	if (data != (BM_CS_STATUS_LINK_UP | BM_CS_STATUS_RESOLVED |
 		     BM_CS_STATUS_SPEED_1000))
@@ -3086,9 +3098,9 @@ s32 e1000_check_polarity_82577(struct e1000_hw *hw)
 	ret_val = e1e_rphy(hw, I82577_PHY_STATUS_2, &data);
 
 	if (!ret_val)
-		phy->cable_polarity = (data & I82577_PHY_STATUS2_REV_POLARITY)
-		                      ? e1000_rev_polarity_reversed
-		                      : e1000_rev_polarity_normal;
+		phy->cable_polarity = ((data & I82577_PHY_STATUS2_REV_POLARITY)
+				       ? e1000_rev_polarity_reversed
+				       : e1000_rev_polarity_normal);
 
 	return ret_val;
 }
@@ -3215,8 +3227,8 @@ s32 e1000_get_cable_length_82577(struct e1000_hw *hw)
 	if (ret_val)
 		return ret_val;
 
-	length = (phy_data & I82577_DSTATUS_CABLE_LENGTH) >>
-	         I82577_DSTATUS_CABLE_LENGTH_SHIFT;
+	length = ((phy_data & I82577_DSTATUS_CABLE_LENGTH) >>
+		  I82577_DSTATUS_CABLE_LENGTH_SHIFT);
 
 	if (length == E1000_CABLE_LENGTH_UNDEFINED)
 		return -E1000_ERR_PHY;
diff --git a/drivers/net/ethernet/intel/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c
index d60cd43..bea46bb 100644
--- a/drivers/net/ethernet/intel/igbvf/netdev.c
+++ b/drivers/net/ethernet/intel/igbvf/netdev.c
@@ -447,7 +447,6 @@ int igbvf_setup_tx_resources(struct igbvf_adapter *adapter,
 
 	tx_ring->desc = dma_alloc_coherent(&pdev->dev, tx_ring->size,
 					   &tx_ring->dma, GFP_KERNEL);
-
 	if (!tx_ring->desc)
 		goto err;
 
@@ -488,7 +487,6 @@ int igbvf_setup_rx_resources(struct igbvf_adapter *adapter,
 
 	rx_ring->desc = dma_alloc_coherent(&pdev->dev, rx_ring->size,
 					   &rx_ring->dma, GFP_KERNEL);
-
 	if (!rx_ring->desc)
 		goto err;
 
diff --git a/drivers/net/ethernet/intel/ixgb/ixgb_main.c b/drivers/net/ethernet/intel/ixgb/ixgb_main.c
index ea48083..5dc119f 100644
--- a/drivers/net/ethernet/intel/ixgb/ixgb_main.c
+++ b/drivers/net/ethernet/intel/ixgb/ixgb_main.c
@@ -717,14 +717,11 @@ ixgb_setup_tx_resources(struct ixgb_adapter *adapter)
 	txdr->size = ALIGN(txdr->size, 4096);
 
 	txdr->desc = dma_alloc_coherent(&pdev->dev, txdr->size, &txdr->dma,
-					GFP_KERNEL);
+					GFP_KERNEL | __GFP_ZERO);
 	if (!txdr->desc) {
 		vfree(txdr->buffer_info);
-		netif_err(adapter, probe, adapter->netdev,
-			  "Unable to allocate transmit descriptor memory\n");
 		return -ENOMEM;
 	}
-	memset(txdr->desc, 0, txdr->size);
 
 	txdr->next_to_use = 0;
 	txdr->next_to_clean = 0;
@@ -807,8 +804,6 @@ ixgb_setup_rx_resources(struct ixgb_adapter *adapter)
 
 	if (!rxdr->desc) {
 		vfree(rxdr->buffer_info);
-		netif_err(adapter, probe, adapter->netdev,
-			  "Unable to allocate receive descriptors\n");
 		return -ENOMEM;
 	}
 	memset(rxdr->desc, 0, rxdr->size);
@@ -2159,6 +2154,10 @@ map_skb:
 		                                  skb->data,
 		                                  adapter->rx_buffer_len,
 						  DMA_FROM_DEVICE);
+		if (dma_mapping_error(&pdev->dev, buffer_info->dma)) {
+			adapter->alloc_rx_buff_failed++;
+			break;
+		}
 
 		rx_desc = IXGB_RX_DESC(*rx_ring, i);
 		rx_desc->buff_addr = cpu_to_le64(buffer_info->dma);
@@ -2168,7 +2167,8 @@ map_skb:
 		rx_desc->status = 0;
 
 
-		if (++i == rx_ring->count) i = 0;
+		if (++i == rx_ring->count)
+			i = 0;
 		buffer_info = &rx_ring->buffer_info[i];
 	}
 
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index db5611a..e56a3d1 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -7007,7 +7007,7 @@ static int ixgbe_ndo_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
 	int err;
 
 	if (!(adapter->flags & IXGBE_FLAG_SRIOV_ENABLED))
-		return -EOPNOTSUPP;
+		return ndo_dflt_fdb_add(ndm, tb, dev, addr, flags);
 
 	/* Hardware does not support aging addresses so if a
 	 * ndm_state is given only allow permanent addresses
@@ -7038,44 +7038,6 @@ static int ixgbe_ndo_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
 	return err;
 }
 
-static int ixgbe_ndo_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],
-			     struct net_device *dev,
-			     const unsigned char *addr)
-{
-	struct ixgbe_adapter *adapter = netdev_priv(dev);
-	int err = -EOPNOTSUPP;
-
-	if (ndm->ndm_state & NUD_PERMANENT) {
-		pr_info("%s: FDB only supports static addresses\n",
-			ixgbe_driver_name);
-		return -EINVAL;
-	}
-
-	if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) {
-		if (is_unicast_ether_addr(addr))
-			err = dev_uc_del(dev, addr);
-		else if (is_multicast_ether_addr(addr))
-			err = dev_mc_del(dev, addr);
-		else
-			err = -EINVAL;
-	}
-
-	return err;
-}
-
-static int ixgbe_ndo_fdb_dump(struct sk_buff *skb,
-			      struct netlink_callback *cb,
-			      struct net_device *dev,
-			      int idx)
-{
-	struct ixgbe_adapter *adapter = netdev_priv(dev);
-
-	if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)
-		idx = ndo_dflt_fdb_dump(skb, cb, dev, idx);
-
-	return idx;
-}
-
 static int ixgbe_ndo_bridge_setlink(struct net_device *dev,
 				    struct nlmsghdr *nlh)
 {
@@ -7171,8 +7133,6 @@ static const struct net_device_ops ixgbe_netdev_ops = {
 	.ndo_set_features = ixgbe_set_features,
 	.ndo_fix_features = ixgbe_fix_features,
 	.ndo_fdb_add		= ixgbe_ndo_fdb_add,
-	.ndo_fdb_del		= ixgbe_ndo_fdb_del,
-	.ndo_fdb_dump		= ixgbe_ndo_fdb_dump,
 	.ndo_bridge_setlink	= ixgbe_ndo_bridge_setlink,
 	.ndo_bridge_getlink	= ixgbe_ndo_bridge_getlink,
 };
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
index d44b4d2..b3e6530 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
@@ -661,13 +661,7 @@ int ixgbe_vf_configuration(struct pci_dev *pdev, unsigned int event_mask)
 	bool enable = ((event_mask & 0x10000000U) != 0);
 
 	if (enable) {
-		eth_random_addr(vf_mac_addr);
-		e_info(probe, "IOV: VF %d is enabled MAC %pM\n",
-		       vfn, vf_mac_addr);
-		/*
-		 * Store away the VF "permananet" MAC address, it will ask
-		 * for it later.
-		 */
+		eth_zero_addr(vf_mac_addr);
 		memcpy(adapter->vfinfo[vfn].vf_mac_addresses, vf_mac_addr, 6);
 	}
 
@@ -688,7 +682,8 @@ static int ixgbe_vf_reset_msg(struct ixgbe_adapter *adapter, u32 vf)
 	ixgbe_vf_reset_event(adapter, vf);
 
 	/* set vf mac address */
-	ixgbe_set_vf_mac(adapter, vf, vf_mac);
+	if (!is_zero_ether_addr(vf_mac))
+		ixgbe_set_vf_mac(adapter, vf, vf_mac);
 
 	vf_shift = vf % 32;
 	reg_offset = vf / 32;
@@ -729,8 +724,16 @@ static int ixgbe_vf_reset_msg(struct ixgbe_adapter *adapter, u32 vf)
 	IXGBE_WRITE_REG(hw, IXGBE_VMECM(reg_offset), reg);
 
 	/* reply to reset with ack and vf mac address */
-	msgbuf[0] = IXGBE_VF_RESET | IXGBE_VT_MSGTYPE_ACK;
-	memcpy(addr, vf_mac, ETH_ALEN);
+	msgbuf[0] = IXGBE_VF_RESET;
+	if (!is_zero_ether_addr(vf_mac)) {
+		msgbuf[0] |= IXGBE_VT_MSGTYPE_ACK;
+		memcpy(addr, vf_mac, ETH_ALEN);
+	} else {
+		msgbuf[0] |= IXGBE_VT_MSGTYPE_NACK;
+		dev_warn(&adapter->pdev->dev,
+			 "VF %d has no MAC address assigned, you may have to assign one manually\n",
+			 vf);
+	}
 
 	/*
 	 * Piggyback the multicast filter type so VF can compute the
diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
index fc0af9a..fff0d98 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
@@ -44,8 +44,8 @@ struct ixgbevf_tx_buffer {
 	struct sk_buff *skb;
 	dma_addr_t dma;
 	unsigned long time_stamp;
+	union ixgbe_adv_tx_desc *next_to_watch;
 	u16 length;
-	u16 next_to_watch;
 	u16 mapped_as_page;
 };
 
diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
index 2b6cb5c..eeae934 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
@@ -76,12 +76,9 @@ static const struct ixgbevf_info *ixgbevf_info_tbl[] = {
  * { Vendor ID, Device ID, SubVendor ID, SubDevice ID,
  *   Class, Class Mask, private data (not used) }
  */
-static struct pci_device_id ixgbevf_pci_tbl[] = {
-	{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_VF),
-	board_82599_vf},
-	{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X540_VF),
-	board_X540_vf},
-
+static DEFINE_PCI_DEVICE_TABLE(ixgbevf_pci_tbl) = {
+	{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_VF), board_82599_vf },
+	{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X540_VF), board_X540_vf },
 	/* required last entry */
 	{0, }
 };
@@ -190,28 +187,37 @@ static bool ixgbevf_clean_tx_irq(struct ixgbevf_q_vector *q_vector,
 	struct ixgbevf_adapter *adapter = q_vector->adapter;
 	union ixgbe_adv_tx_desc *tx_desc, *eop_desc;
 	struct ixgbevf_tx_buffer *tx_buffer_info;
-	unsigned int i, eop, count = 0;
+	unsigned int i, count = 0;
 	unsigned int total_bytes = 0, total_packets = 0;
 
 	if (test_bit(__IXGBEVF_DOWN, &adapter->state))
 		return true;
 
 	i = tx_ring->next_to_clean;
-	eop = tx_ring->tx_buffer_info[i].next_to_watch;
-	eop_desc = IXGBEVF_TX_DESC(tx_ring, eop);
+	tx_buffer_info = &tx_ring->tx_buffer_info[i];
+	eop_desc = tx_buffer_info->next_to_watch;
 
-	while ((eop_desc->wb.status & cpu_to_le32(IXGBE_TXD_STAT_DD)) &&
-	       (count < tx_ring->count)) {
+	do {
 		bool cleaned = false;
-		rmb(); /* read buffer_info after eop_desc */
-		/* eop could change between read and DD-check */
-		if (unlikely(eop != tx_ring->tx_buffer_info[i].next_to_watch))
-			goto cont_loop;
+
+		/* if next_to_watch is not set then there is no work pending */
+		if (!eop_desc)
+			break;
+
+		/* prevent any other reads prior to eop_desc */
+		read_barrier_depends();
+
+		/* if DD is not set pending work has not been completed */
+		if (!(eop_desc->wb.status & cpu_to_le32(IXGBE_TXD_STAT_DD)))
+			break;
+
+		/* clear next_to_watch to prevent false hangs */
+		tx_buffer_info->next_to_watch = NULL;
+
 		for ( ; !cleaned; count++) {
 			struct sk_buff *skb;
 			tx_desc = IXGBEVF_TX_DESC(tx_ring, i);
-			tx_buffer_info = &tx_ring->tx_buffer_info[i];
-			cleaned = (i == eop);
+			cleaned = (tx_desc == eop_desc);
 			skb = tx_buffer_info->skb;
 
 			if (cleaned && skb) {
@@ -234,12 +240,12 @@ static bool ixgbevf_clean_tx_irq(struct ixgbevf_q_vector *q_vector,
 			i++;
 			if (i == tx_ring->count)
 				i = 0;
+
+			tx_buffer_info = &tx_ring->tx_buffer_info[i];
 		}
 
-cont_loop:
-		eop = tx_ring->tx_buffer_info[i].next_to_watch;
-		eop_desc = IXGBEVF_TX_DESC(tx_ring, eop);
-	}
+		eop_desc = tx_buffer_info->next_to_watch;
+	} while (count < tx_ring->count);
 
 	tx_ring->next_to_clean = i;
 
@@ -2046,6 +2052,7 @@ static int ixgbevf_sw_init(struct ixgbevf_adapter *adapter)
 {
 	struct ixgbe_hw *hw = &adapter->hw;
 	struct pci_dev *pdev = adapter->pdev;
+	struct net_device *netdev = adapter->netdev;
 	int err;
 
 	/* PCI config space info */
@@ -2065,18 +2072,26 @@ static int ixgbevf_sw_init(struct ixgbevf_adapter *adapter)
 	err = hw->mac.ops.reset_hw(hw);
 	if (err) {
 		dev_info(&pdev->dev,
-		         "PF still in reset state, assigning new address\n");
-		eth_hw_addr_random(adapter->netdev);
-		memcpy(adapter->hw.mac.addr, adapter->netdev->dev_addr,
-			adapter->netdev->addr_len);
+			 "PF still in reset state.  Is the PF interface up?\n");
 	} else {
 		err = hw->mac.ops.init_hw(hw);
 		if (err) {
 			pr_err("init_shared_code failed: %d\n", err);
 			goto out;
 		}
-		memcpy(adapter->netdev->dev_addr, adapter->hw.mac.addr,
-		       adapter->netdev->addr_len);
+		err = hw->mac.ops.get_mac_addr(hw, hw->mac.addr);
+		if (err)
+			dev_info(&pdev->dev, "Error reading MAC address\n");
+		else if (is_zero_ether_addr(adapter->hw.mac.addr))
+			dev_info(&pdev->dev,
+				 "MAC address not assigned by administrator.\n");
+		memcpy(netdev->dev_addr, hw->mac.addr, netdev->addr_len);
+	}
+
+	if (!is_valid_ether_addr(netdev->dev_addr)) {
+		dev_info(&pdev->dev, "Assigning random MAC address\n");
+		eth_hw_addr_random(netdev);
+		memcpy(hw->mac.addr, netdev->dev_addr, netdev->addr_len);
 	}
 
 	/* lock to protect mailbox accesses */
@@ -2425,9 +2440,6 @@ int ixgbevf_setup_rx_resources(struct ixgbevf_adapter *adapter,
 					   &rx_ring->dma, GFP_KERNEL);
 
 	if (!rx_ring->desc) {
-		hw_dbg(&adapter->hw,
-		       "Unable to allocate memory for "
-		       "the receive descriptor ring\n");
 		vfree(rx_ring->rx_buffer_info);
 		rx_ring->rx_buffer_info = NULL;
 		goto alloc_failed;
@@ -2822,8 +2834,7 @@ static bool ixgbevf_tx_csum(struct ixgbevf_ring *tx_ring,
 }
 
 static int ixgbevf_tx_map(struct ixgbevf_ring *tx_ring,
-			  struct sk_buff *skb, u32 tx_flags,
-			  unsigned int first)
+			  struct sk_buff *skb, u32 tx_flags)
 {
 	struct ixgbevf_tx_buffer *tx_buffer_info;
 	unsigned int len;
@@ -2848,7 +2859,6 @@ static int ixgbevf_tx_map(struct ixgbevf_ring *tx_ring,
 						     size, DMA_TO_DEVICE);
 		if (dma_mapping_error(tx_ring->dev, tx_buffer_info->dma))
 			goto dma_error;
-		tx_buffer_info->next_to_watch = i;
 
 		len -= size;
 		total -= size;
@@ -2878,7 +2888,6 @@ static int ixgbevf_tx_map(struct ixgbevf_ring *tx_ring,
 					      tx_buffer_info->dma))
 				goto dma_error;
 			tx_buffer_info->mapped_as_page = true;
-			tx_buffer_info->next_to_watch = i;
 
 			len -= size;
 			total -= size;
@@ -2897,8 +2906,6 @@ static int ixgbevf_tx_map(struct ixgbevf_ring *tx_ring,
 	else
 		i = i - 1;
 	tx_ring->tx_buffer_info[i].skb = skb;
-	tx_ring->tx_buffer_info[first].next_to_watch = i;
-	tx_ring->tx_buffer_info[first].time_stamp = jiffies;
 
 	return count;
 
@@ -2907,7 +2914,6 @@ dma_error:
 
 	/* clear timestamp and dma mappings for failed tx_buffer_info map */
 	tx_buffer_info->dma = 0;
-	tx_buffer_info->next_to_watch = 0;
 	count--;
 
 	/* clear timestamp and dma mappings for remaining portion of packet */
@@ -2924,7 +2930,8 @@ dma_error:
 }
 
 static void ixgbevf_tx_queue(struct ixgbevf_ring *tx_ring, int tx_flags,
-			     int count, u32 paylen, u8 hdr_len)
+			     int count, unsigned int first, u32 paylen,
+			     u8 hdr_len)
 {
 	union ixgbe_adv_tx_desc *tx_desc = NULL;
 	struct ixgbevf_tx_buffer *tx_buffer_info;
@@ -2975,6 +2982,16 @@ static void ixgbevf_tx_queue(struct ixgbevf_ring *tx_ring, int tx_flags,
 
 	tx_desc->read.cmd_type_len |= cpu_to_le32(txd_cmd);
 
+	tx_ring->tx_buffer_info[first].time_stamp = jiffies;
+
+	/* Force memory writes to complete before letting h/w
+	 * know there are new descriptors to fetch.  (Only
+	 * applicable for weak-ordered memory model archs,
+	 * such as IA-64).
+	 */
+	wmb();
+
+	tx_ring->tx_buffer_info[first].next_to_watch = tx_desc;
 	tx_ring->next_to_use = i;
 }
 
@@ -3066,15 +3083,8 @@ static int ixgbevf_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 		tx_flags |= IXGBE_TX_FLAGS_CSUM;
 
 	ixgbevf_tx_queue(tx_ring, tx_flags,
-			 ixgbevf_tx_map(tx_ring, skb, tx_flags, first),
-			 skb->len, hdr_len);
-	/*
-	 * Force memory writes to complete before letting h/w
-	 * know there are new descriptors to fetch.  (Only
-	 * applicable for weak-ordered memory model archs,
-	 * such as IA-64).
-	 */
-	wmb();
+			 ixgbevf_tx_map(tx_ring, skb, tx_flags),
+			 first, skb->len, hdr_len);
 
 	writel(tx_ring->next_to_use, adapter->hw.hw_addr + tx_ring->tail);
 
diff --git a/drivers/net/ethernet/intel/ixgbevf/vf.c b/drivers/net/ethernet/intel/ixgbevf/vf.c
index 0c94557..387b526 100644
--- a/drivers/net/ethernet/intel/ixgbevf/vf.c
+++ b/drivers/net/ethernet/intel/ixgbevf/vf.c
@@ -109,7 +109,12 @@ static s32 ixgbevf_reset_hw_vf(struct ixgbe_hw *hw)
 	if (ret_val)
 		return ret_val;
 
-	if (msgbuf[0] != (IXGBE_VF_RESET | IXGBE_VT_MSGTYPE_ACK))
+	/* New versions of the PF may NACK the reset return message
+	 * to indicate that no MAC address has yet been assigned for
+	 * the VF.
+	 */
+	if (msgbuf[0] != (IXGBE_VF_RESET | IXGBE_VT_MSGTYPE_ACK) &&
+	    msgbuf[0] != (IXGBE_VF_RESET | IXGBE_VT_MSGTYPE_NACK))
 		return IXGBE_ERR_INVALID_MAC_ADDR;
 
 	memcpy(hw->mac.perm_addr, addr, ETH_ALEN);
diff --git a/drivers/net/ethernet/marvell/Kconfig b/drivers/net/ethernet/marvell/Kconfig
index edfba93..5170ecb 100644
--- a/drivers/net/ethernet/marvell/Kconfig
+++ b/drivers/net/ethernet/marvell/Kconfig
@@ -23,6 +23,7 @@ config MV643XX_ETH
 	depends on (MV64X60 || PPC32 || PLAT_ORION) && INET
 	select INET_LRO
 	select PHYLIB
+	select MVMDIO
 	---help---
 	  This driver supports the gigabit ethernet MACs in the
 	  Marvell Discovery PPC/MIPS chipset family (MV643XX) and
@@ -38,9 +39,7 @@ config MVMDIO
 	  interface units of the Marvell EBU SoCs (Kirkwood, Orion5x,
 	  Dove, Armada 370 and Armada XP).
 
-	  For now, this driver is only needed for the MVNETA driver
-	  (used on Armada 370 and XP), but it could be used in the
-	  future by the MV643XX_ETH driver.
+	  This driver is used by the MV643XX_ETH and MVNETA drivers.
 
 config MVNETA
 	tristate "Marvell Armada 370/XP network interface support"
diff --git a/drivers/net/ethernet/marvell/Makefile b/drivers/net/ethernet/marvell/Makefile
index 7f63b4a..5c4a776 100644
--- a/drivers/net/ethernet/marvell/Makefile
+++ b/drivers/net/ethernet/marvell/Makefile
@@ -2,8 +2,8 @@
 # Makefile for the Marvell device drivers.
 #
 
-obj-$(CONFIG_MV643XX_ETH) += mv643xx_eth.o
 obj-$(CONFIG_MVMDIO) += mvmdio.o
+obj-$(CONFIG_MV643XX_ETH) += mv643xx_eth.o
 obj-$(CONFIG_MVNETA) += mvneta.o
 obj-$(CONFIG_PXA168_ETH) += pxa168_eth.o
 obj-$(CONFIG_SKGE) += skge.o
diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c
index 6562c73..aedbd82 100644
--- a/drivers/net/ethernet/marvell/mv643xx_eth.c
+++ b/drivers/net/ethernet/marvell/mv643xx_eth.c
@@ -20,6 +20,8 @@
  * Copyright (C) 2007-2008 Marvell Semiconductor
  *			   Lennert Buytenhek <buytenh@marvell.com>
  *
+ * Copyright (C) 2013 Michael Stapelberg <michael@stapelberg.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
@@ -67,14 +69,6 @@ static char mv643xx_eth_driver_version[] = "1.4";
  * Registers shared between all ports.
  */
 #define PHY_ADDR			0x0000
-#define SMI_REG				0x0004
-#define  SMI_BUSY			0x10000000
-#define  SMI_READ_VALID			0x08000000
-#define  SMI_OPCODE_READ		0x04000000
-#define  SMI_OPCODE_WRITE		0x00000000
-#define ERR_INT_CAUSE			0x0080
-#define  ERR_INT_SMI_DONE		0x00000010
-#define ERR_INT_MASK			0x0084
 #define WINDOW_BASE(w)			(0x0200 + ((w) << 3))
 #define WINDOW_SIZE(w)			(0x0204 + ((w) << 3))
 #define WINDOW_REMAP_HIGH(w)		(0x0280 + ((w) << 2))
@@ -264,25 +258,6 @@ struct mv643xx_eth_shared_private {
 	void __iomem *base;
 
 	/*
-	 * Points at the right SMI instance to use.
-	 */
-	struct mv643xx_eth_shared_private *smi;
-
-	/*
-	 * Provides access to local SMI interface.
-	 */
-	struct mii_bus *smi_bus;
-
-	/*
-	 * If we have access to the error interrupt pin (which is
-	 * somewhat misnamed as it not only reflects internal errors
-	 * but also reflects SMI completion), use that to wait for
-	 * SMI access completion instead of polling the SMI busy bit.
-	 */
-	int err_interrupt;
-	wait_queue_head_t smi_busy_wait;
-
-	/*
 	 * Per-port MBUS window access register value.
 	 */
 	u32 win_protect;
@@ -1120,97 +1095,6 @@ out_write:
 	wrlp(mp, PORT_SERIAL_CONTROL, pscr);
 }
 
-static irqreturn_t mv643xx_eth_err_irq(int irq, void *dev_id)
-{
-	struct mv643xx_eth_shared_private *msp = dev_id;
-
-	if (readl(msp->base + ERR_INT_CAUSE) & ERR_INT_SMI_DONE) {
-		writel(~ERR_INT_SMI_DONE, msp->base + ERR_INT_CAUSE);
-		wake_up(&msp->smi_busy_wait);
-		return IRQ_HANDLED;
-	}
-
-	return IRQ_NONE;
-}
-
-static int smi_is_done(struct mv643xx_eth_shared_private *msp)
-{
-	return !(readl(msp->base + SMI_REG) & SMI_BUSY);
-}
-
-static int smi_wait_ready(struct mv643xx_eth_shared_private *msp)
-{
-	if (msp->err_interrupt == NO_IRQ) {
-		int i;
-
-		for (i = 0; !smi_is_done(msp); i++) {
-			if (i == 10)
-				return -ETIMEDOUT;
-			msleep(10);
-		}
-
-		return 0;
-	}
-
-	if (!smi_is_done(msp)) {
-		wait_event_timeout(msp->smi_busy_wait, smi_is_done(msp),
-				   msecs_to_jiffies(100));
-		if (!smi_is_done(msp))
-			return -ETIMEDOUT;
-	}
-
-	return 0;
-}
-
-static int smi_bus_read(struct mii_bus *bus, int addr, int reg)
-{
-	struct mv643xx_eth_shared_private *msp = bus->priv;
-	void __iomem *smi_reg = msp->base + SMI_REG;
-	int ret;
-
-	if (smi_wait_ready(msp)) {
-		pr_warn("SMI bus busy timeout\n");
-		return -ETIMEDOUT;
-	}
-
-	writel(SMI_OPCODE_READ | (reg << 21) | (addr << 16), smi_reg);
-
-	if (smi_wait_ready(msp)) {
-		pr_warn("SMI bus busy timeout\n");
-		return -ETIMEDOUT;
-	}
-
-	ret = readl(smi_reg);
-	if (!(ret & SMI_READ_VALID)) {
-		pr_warn("SMI bus read not valid\n");
-		return -ENODEV;
-	}
-
-	return ret & 0xffff;
-}
-
-static int smi_bus_write(struct mii_bus *bus, int addr, int reg, u16 val)
-{
-	struct mv643xx_eth_shared_private *msp = bus->priv;
-	void __iomem *smi_reg = msp->base + SMI_REG;
-
-	if (smi_wait_ready(msp)) {
-		pr_warn("SMI bus busy timeout\n");
-		return -ETIMEDOUT;
-	}
-
-	writel(SMI_OPCODE_WRITE | (reg << 21) |
-		(addr << 16) | (val & 0xffff), smi_reg);
-
-	if (smi_wait_ready(msp)) {
-		pr_warn("SMI bus busy timeout\n");
-		return -ETIMEDOUT;
-	}
-
-	return 0;
-}
-
-
 /* statistics ***************************************************************/
 static struct net_device_stats *mv643xx_eth_get_stats(struct net_device *dev)
 {
@@ -1523,6 +1407,34 @@ mv643xx_eth_get_settings_phyless(struct mv643xx_eth_private *mp,
 	return 0;
 }
 
+static void
+mv643xx_eth_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+	struct mv643xx_eth_private *mp = netdev_priv(dev);
+	wol->supported = 0;
+	wol->wolopts = 0;
+	if (mp->phy)
+		phy_ethtool_get_wol(mp->phy, wol);
+}
+
+static int
+mv643xx_eth_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+	struct mv643xx_eth_private *mp = netdev_priv(dev);
+	int err;
+
+	if (mp->phy == NULL)
+		return -EOPNOTSUPP;
+
+	err = phy_ethtool_set_wol(mp->phy, wol);
+	/* Given that mv643xx_eth works without the marvell-specific PHY driver,
+	 * this debugging hint is useful to have.
+	 */
+	if (err == -EOPNOTSUPP)
+		netdev_info(dev, "The PHY does not support set_wol, was CONFIG_MARVELL_PHY enabled?\n");
+	return err;
+}
+
 static int
 mv643xx_eth_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
@@ -1708,6 +1620,8 @@ static const struct ethtool_ops mv643xx_eth_ethtool_ops = {
 	.get_ethtool_stats	= mv643xx_eth_get_ethtool_stats,
 	.get_sset_count		= mv643xx_eth_get_sset_count,
 	.get_ts_info		= ethtool_op_get_ts_info,
+	.get_wol                = mv643xx_eth_get_wol,
+	.set_wol                = mv643xx_eth_set_wol,
 };
 
 
@@ -2656,47 +2570,6 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev)
 		goto out_free;
 
 	/*
-	 * Set up and register SMI bus.
-	 */
-	if (pd == NULL || pd->shared_smi == NULL) {
-		msp->smi_bus = mdiobus_alloc();
-		if (msp->smi_bus == NULL)
-			goto out_unmap;
-
-		msp->smi_bus->priv = msp;
-		msp->smi_bus->name = "mv643xx_eth smi";
-		msp->smi_bus->read = smi_bus_read;
-		msp->smi_bus->write = smi_bus_write,
-		snprintf(msp->smi_bus->id, MII_BUS_ID_SIZE, "%s-%d",
-			pdev->name, pdev->id);
-		msp->smi_bus->parent = &pdev->dev;
-		msp->smi_bus->phy_mask = 0xffffffff;
-		if (mdiobus_register(msp->smi_bus) < 0)
-			goto out_free_mii_bus;
-		msp->smi = msp;
-	} else {
-		msp->smi = platform_get_drvdata(pd->shared_smi);
-	}
-
-	msp->err_interrupt = NO_IRQ;
-	init_waitqueue_head(&msp->smi_busy_wait);
-
-	/*
-	 * Check whether the error interrupt is hooked up.
-	 */
-	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	if (res != NULL) {
-		int err;
-
-		err = request_irq(res->start, mv643xx_eth_err_irq,
-				  IRQF_SHARED, "mv643xx_eth", msp);
-		if (!err) {
-			writel(ERR_INT_SMI_DONE, msp->base + ERR_INT_MASK);
-			msp->err_interrupt = res->start;
-		}
-	}
-
-	/*
 	 * (Re-)program MBUS remapping windows if we are asked to.
 	 */
 	dram = mv_mbus_dram_info();
@@ -2711,10 +2584,6 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev)
 
 	return 0;
 
-out_free_mii_bus:
-	mdiobus_free(msp->smi_bus);
-out_unmap:
-	iounmap(msp->base);
 out_free:
 	kfree(msp);
 out:
@@ -2724,14 +2593,7 @@ out:
 static int mv643xx_eth_shared_remove(struct platform_device *pdev)
 {
 	struct mv643xx_eth_shared_private *msp = platform_get_drvdata(pdev);
-	struct mv643xx_eth_shared_platform_data *pd = pdev->dev.platform_data;
 
-	if (pd == NULL || pd->shared_smi == NULL) {
-		mdiobus_unregister(msp->smi_bus);
-		mdiobus_free(msp->smi_bus);
-	}
-	if (msp->err_interrupt != NO_IRQ)
-		free_irq(msp->err_interrupt, msp);
 	iounmap(msp->base);
 	kfree(msp);
 
@@ -2794,14 +2656,21 @@ static void set_params(struct mv643xx_eth_private *mp,
 	mp->txq_count = pd->tx_queue_count ? : 1;
 }
 
+static void mv643xx_eth_adjust_link(struct net_device *dev)
+{
+	struct mv643xx_eth_private *mp = netdev_priv(dev);
+
+	mv643xx_adjust_pscr(mp);
+}
+
 static struct phy_device *phy_scan(struct mv643xx_eth_private *mp,
 				   int phy_addr)
 {
-	struct mii_bus *bus = mp->shared->smi->smi_bus;
 	struct phy_device *phydev;
 	int start;
 	int num;
 	int i;
+	char phy_id[MII_BUS_ID_SIZE + 3];
 
 	if (phy_addr == MV643XX_ETH_PHY_ADDR_DEFAULT) {
 		start = phy_addr_get(mp) & 0x1f;
@@ -2811,17 +2680,19 @@ static struct phy_device *phy_scan(struct mv643xx_eth_private *mp,
 		num = 1;
 	}
 
-	phydev = NULL;
+	/* Attempt to connect to the PHY using orion-mdio */
+	phydev = ERR_PTR(-ENODEV);
 	for (i = 0; i < num; i++) {
 		int addr = (start + i) & 0x1f;
 
-		if (bus->phy_map[addr] == NULL)
-			mdiobus_scan(bus, addr);
+		snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT,
+				"orion-mdio-mii", addr);
 
-		if (phydev == NULL) {
-			phydev = bus->phy_map[addr];
-			if (phydev != NULL)
-				phy_addr_set(mp, addr);
+		phydev = phy_connect(mp->dev, phy_id, mv643xx_eth_adjust_link,
+				PHY_INTERFACE_MODE_GMII);
+		if (!IS_ERR(phydev)) {
+			phy_addr_set(mp, addr);
+			break;
 		}
 	}
 
@@ -2834,8 +2705,6 @@ static void phy_init(struct mv643xx_eth_private *mp, int speed, int duplex)
 
 	phy_reset(mp);
 
-	phy_attach(mp->dev, dev_name(&phy->dev), PHY_INTERFACE_MODE_GMII);
-
 	if (speed == 0) {
 		phy->autoneg = AUTONEG_ENABLE;
 		phy->speed = 0;
@@ -2943,11 +2812,17 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
 	netif_set_real_num_tx_queues(dev, mp->txq_count);
 	netif_set_real_num_rx_queues(dev, mp->rxq_count);
 
-	if (pd->phy_addr != MV643XX_ETH_PHY_NONE)
+	if (pd->phy_addr != MV643XX_ETH_PHY_NONE) {
 		mp->phy = phy_scan(mp, pd->phy_addr);
 
-	if (mp->phy != NULL)
+		if (IS_ERR(mp->phy)) {
+			err = PTR_ERR(mp->phy);
+			if (err == -ENODEV)
+				err = -EPROBE_DEFER;
+			goto out;
+		}
 		phy_init(mp, pd->speed, pd->duplex);
+	}
 
 	SET_ETHTOOL_OPS(dev, &mv643xx_eth_ethtool_ops);
 
diff --git a/drivers/net/ethernet/marvell/mvmdio.c b/drivers/net/ethernet/marvell/mvmdio.c
index 77b7c80..7b5158f 100644
--- a/drivers/net/ethernet/marvell/mvmdio.c
+++ b/drivers/net/ethernet/marvell/mvmdio.c
@@ -24,10 +24,13 @@
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/phy.h>
-#include <linux/of_address.h>
-#include <linux/of_mdio.h>
+#include <linux/interrupt.h>
 #include <linux/platform_device.h>
 #include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/of_mdio.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
 
 #define MVMDIO_SMI_DATA_SHIFT              0
 #define MVMDIO_SMI_PHY_ADDR_SHIFT          16
@@ -36,33 +39,58 @@
 #define MVMDIO_SMI_WRITE_OPERATION         0
 #define MVMDIO_SMI_READ_VALID              BIT(27)
 #define MVMDIO_SMI_BUSY                    BIT(28)
+#define MVMDIO_ERR_INT_CAUSE		   0x007C
+#define  MVMDIO_ERR_INT_SMI_DONE	   0x00000010
+#define MVMDIO_ERR_INT_MASK		   0x0080
 
 struct orion_mdio_dev {
 	struct mutex lock;
-	void __iomem *smireg;
+	void __iomem *regs;
+	/*
+	 * If we have access to the error interrupt pin (which is
+	 * somewhat misnamed as it not only reflects internal errors
+	 * but also reflects SMI completion), use that to wait for
+	 * SMI access completion instead of polling the SMI busy bit.
+	 */
+	int err_interrupt;
+	wait_queue_head_t smi_busy_wait;
 };
 
+static int orion_mdio_smi_is_done(struct orion_mdio_dev *dev)
+{
+	return !(readl(dev->regs) & MVMDIO_SMI_BUSY);
+}
+
 /* Wait for the SMI unit to be ready for another operation
  */
 static int orion_mdio_wait_ready(struct mii_bus *bus)
 {
 	struct orion_mdio_dev *dev = bus->priv;
 	int count;
-	u32 val;
 
-	count = 0;
-	while (1) {
-		val = readl(dev->smireg);
-		if (!(val & MVMDIO_SMI_BUSY))
-			break;
+	if (dev->err_interrupt <= 0) {
+		count = 0;
+		while (1) {
+			if (orion_mdio_smi_is_done(dev))
+				break;
 
-		if (count > 100) {
-			dev_err(bus->parent, "Timeout: SMI busy for too long\n");
-			return -ETIMEDOUT;
-		}
+			if (count > 100) {
+				dev_err(bus->parent,
+					"Timeout: SMI busy for too long\n");
+				return -ETIMEDOUT;
+			}
 
-		udelay(10);
-		count++;
+			udelay(10);
+			count++;
+		}
+	} else {
+		if (!orion_mdio_smi_is_done(dev)) {
+			wait_event_timeout(dev->smi_busy_wait,
+				orion_mdio_smi_is_done(dev),
+				msecs_to_jiffies(100));
+			if (!orion_mdio_smi_is_done(dev))
+				return -ETIMEDOUT;
+		}
 	}
 
 	return 0;
@@ -87,12 +115,12 @@ static int orion_mdio_read(struct mii_bus *bus, int mii_id,
 	writel(((mii_id << MVMDIO_SMI_PHY_ADDR_SHIFT) |
 		(regnum << MVMDIO_SMI_PHY_REG_SHIFT)  |
 		MVMDIO_SMI_READ_OPERATION),
-	       dev->smireg);
+	       dev->regs);
 
 	/* Wait for the value to become available */
 	count = 0;
 	while (1) {
-		val = readl(dev->smireg);
+		val = readl(dev->regs);
 		if (val & MVMDIO_SMI_READ_VALID)
 			break;
 
@@ -129,7 +157,7 @@ static int orion_mdio_write(struct mii_bus *bus, int mii_id,
 		(regnum << MVMDIO_SMI_PHY_REG_SHIFT)  |
 		MVMDIO_SMI_WRITE_OPERATION            |
 		(value << MVMDIO_SMI_DATA_SHIFT)),
-	       dev->smireg);
+	       dev->regs);
 
 	mutex_unlock(&dev->lock);
 
@@ -141,13 +169,34 @@ static int orion_mdio_reset(struct mii_bus *bus)
 	return 0;
 }
 
+static irqreturn_t orion_mdio_err_irq(int irq, void *dev_id)
+{
+	struct orion_mdio_dev *dev = dev_id;
+
+	if (readl(dev->regs + MVMDIO_ERR_INT_CAUSE) &
+			MVMDIO_ERR_INT_SMI_DONE) {
+		writel(~MVMDIO_ERR_INT_SMI_DONE,
+				dev->regs + MVMDIO_ERR_INT_CAUSE);
+		wake_up(&dev->smi_busy_wait);
+		return IRQ_HANDLED;
+	}
+
+	return IRQ_NONE;
+}
+
 static int orion_mdio_probe(struct platform_device *pdev)
 {
-	struct device_node *np = pdev->dev.of_node;
+	struct resource *r;
 	struct mii_bus *bus;
 	struct orion_mdio_dev *dev;
 	int i, ret;
 
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!r) {
+		dev_err(&pdev->dev, "No SMI register address given\n");
+		return -ENODEV;
+	}
+
 	bus = mdiobus_alloc_size(sizeof(struct orion_mdio_dev));
 	if (!bus) {
 		dev_err(&pdev->dev, "Cannot allocate MDIO bus\n");
@@ -172,33 +221,54 @@ static int orion_mdio_probe(struct platform_device *pdev)
 		bus->irq[i] = PHY_POLL;
 
 	dev = bus->priv;
-	dev->smireg = of_iomap(pdev->dev.of_node, 0);
-	if (!dev->smireg) {
-		dev_err(&pdev->dev, "No SMI register address given in DT\n");
-		kfree(bus->irq);
-		mdiobus_free(bus);
-		return -ENODEV;
+	dev->regs = devm_ioremap(&pdev->dev, r->start, resource_size(r));
+	if (!dev->regs) {
+		dev_err(&pdev->dev, "Unable to remap SMI register\n");
+		ret = -ENODEV;
+		goto out_mdio;
+	}
+
+	init_waitqueue_head(&dev->smi_busy_wait);
+
+	dev->err_interrupt = platform_get_irq(pdev, 0);
+	if (dev->err_interrupt != -ENXIO) {
+		ret = devm_request_irq(&pdev->dev, dev->err_interrupt,
+					orion_mdio_err_irq,
+					IRQF_SHARED, pdev->name, dev);
+		if (ret)
+			goto out_mdio;
+
+		writel(MVMDIO_ERR_INT_SMI_DONE,
+			dev->regs + MVMDIO_ERR_INT_MASK);
 	}
 
 	mutex_init(&dev->lock);
 
-	ret = of_mdiobus_register(bus, np);
+	if (pdev->dev.of_node)
+		ret = of_mdiobus_register(bus, pdev->dev.of_node);
+	else
+		ret = mdiobus_register(bus);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "Cannot register MDIO bus (%d)\n", ret);
-		iounmap(dev->smireg);
-		kfree(bus->irq);
-		mdiobus_free(bus);
-		return ret;
+		goto out_mdio;
 	}
 
 	platform_set_drvdata(pdev, bus);
 
 	return 0;
+
+out_mdio:
+	kfree(bus->irq);
+	mdiobus_free(bus);
+	return ret;
 }
 
 static int orion_mdio_remove(struct platform_device *pdev)
 {
 	struct mii_bus *bus = platform_get_drvdata(pdev);
+	struct orion_mdio_dev *dev = bus->priv;
+
+	writel(0, dev->regs + MVMDIO_ERR_INT_MASK);
 	mdiobus_unregister(bus);
 	kfree(bus->irq);
 	mdiobus_free(bus);
@@ -225,3 +295,4 @@ module_platform_driver(orion_mdio_driver);
 MODULE_DESCRIPTION("Marvell MDIO interface driver");
 MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:orion-mdio");
diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
index cd345b8..e48261e 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -1969,13 +1969,8 @@ static int mvneta_rxq_init(struct mvneta_port *pp,
 	rxq->descs = dma_alloc_coherent(pp->dev->dev.parent,
 					rxq->size * MVNETA_DESC_ALIGNED_SIZE,
 					&rxq->descs_phys, GFP_KERNEL);
-	if (rxq->descs == NULL) {
-		netdev_err(pp->dev,
-			   "rxq=%d: Can't allocate %d bytes for %d RX descr\n",
-			   rxq->id, rxq->size * MVNETA_DESC_ALIGNED_SIZE,
-			   rxq->size);
+	if (rxq->descs == NULL)
 		return -ENOMEM;
-	}
 
 	BUG_ON(rxq->descs !=
 	       PTR_ALIGN(rxq->descs, MVNETA_CPU_D_CACHE_LINE_SIZE));
@@ -2029,13 +2024,8 @@ static int mvneta_txq_init(struct mvneta_port *pp,
 	txq->descs = dma_alloc_coherent(pp->dev->dev.parent,
 					txq->size * MVNETA_DESC_ALIGNED_SIZE,
 					&txq->descs_phys, GFP_KERNEL);
-	if (txq->descs == NULL) {
-		netdev_err(pp->dev,
-			   "txQ=%d: Can't allocate %d bytes for %d TX descr\n",
-			   txq->id, txq->size * MVNETA_DESC_ALIGNED_SIZE,
-			   txq->size);
+	if (txq->descs == NULL)
 		return -ENOMEM;
-	}
 
 	/* Make sure descriptor address is cache line size aligned  */
 	BUG_ON(txq->descs !=
diff --git a/drivers/net/ethernet/marvell/pxa168_eth.c b/drivers/net/ethernet/marvell/pxa168_eth.c
index 037ed86..339bb32 100644
--- a/drivers/net/ethernet/marvell/pxa168_eth.c
+++ b/drivers/net/ethernet/marvell/pxa168_eth.c
@@ -584,12 +584,14 @@ static int init_hash_table(struct pxa168_eth_private *pep)
 	 */
 	if (pep->htpr == NULL) {
 		pep->htpr = dma_alloc_coherent(pep->dev->dev.parent,
-					      HASH_ADDR_TABLE_SIZE,
-					      &pep->htpr_dma, GFP_KERNEL);
+					       HASH_ADDR_TABLE_SIZE,
+					       &pep->htpr_dma,
+					       GFP_KERNEL | __GFP_ZERO);
 		if (pep->htpr == NULL)
 			return -ENOMEM;
+	} else {
+		memset(pep->htpr, 0, HASH_ADDR_TABLE_SIZE);
 	}
-	memset(pep->htpr, 0, HASH_ADDR_TABLE_SIZE);
 	wrl(pep, HTPR, pep->htpr_dma);
 	return 0;
 }
@@ -1023,13 +1025,11 @@ static int rxq_init(struct net_device *dev)
 	size = pep->rx_ring_size * sizeof(struct rx_desc);
 	pep->rx_desc_area_size = size;
 	pep->p_rx_desc_area = dma_alloc_coherent(pep->dev->dev.parent, size,
-						&pep->rx_desc_dma, GFP_KERNEL);
-	if (!pep->p_rx_desc_area) {
-		printk(KERN_ERR "%s: Cannot alloc RX ring (size %d bytes)\n",
-		       dev->name, size);
+						 &pep->rx_desc_dma,
+						 GFP_KERNEL | __GFP_ZERO);
+	if (!pep->p_rx_desc_area)
 		goto out;
-	}
-	memset((void *)pep->p_rx_desc_area, 0, size);
+
 	/* initialize the next_desc_ptr links in the Rx descriptors ring */
 	p_rx_desc = pep->p_rx_desc_area;
 	for (i = 0; i < rx_desc_num; i++) {
@@ -1086,13 +1086,10 @@ static int txq_init(struct net_device *dev)
 	size = pep->tx_ring_size * sizeof(struct tx_desc);
 	pep->tx_desc_area_size = size;
 	pep->p_tx_desc_area = dma_alloc_coherent(pep->dev->dev.parent, size,
-						&pep->tx_desc_dma, GFP_KERNEL);
-	if (!pep->p_tx_desc_area) {
-		printk(KERN_ERR "%s: Cannot allocate Tx Ring (size %d bytes)\n",
-		       dev->name, size);
+						 &pep->tx_desc_dma,
+						 GFP_KERNEL | __GFP_ZERO);
+	if (!pep->p_tx_desc_area)
 		goto out;
-	}
-	memset((void *)pep->p_tx_desc_area, 0, pep->tx_desc_area_size);
 	/* Initialize the next_desc_ptr links in the Tx descriptors ring */
 	p_tx_desc = pep->p_tx_desc_area;
 	for (i = 0; i < tx_desc_num; i++) {
diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c
index fc07ca3..6a0e671 100644
--- a/drivers/net/ethernet/marvell/sky2.c
+++ b/drivers/net/ethernet/marvell/sky2.c
@@ -1067,7 +1067,7 @@ static void sky2_ramset(struct sky2_hw *hw, u16 q, u32 start, u32 space)
 		sky2_write32(hw, RB_ADDR(q, RB_RX_UTHP), tp);
 		sky2_write32(hw, RB_ADDR(q, RB_RX_LTHP), space/2);
 
-		tp = space - 2048/8;
+		tp = space - 8192/8;
 		sky2_write32(hw, RB_ADDR(q, RB_RX_UTPP), tp);
 		sky2_write32(hw, RB_ADDR(q, RB_RX_LTPP), space/4);
 	} else {
diff --git a/drivers/net/ethernet/marvell/sky2.h b/drivers/net/ethernet/marvell/sky2.h
index 615ac63..ec6dcd8 100644
--- a/drivers/net/ethernet/marvell/sky2.h
+++ b/drivers/net/ethernet/marvell/sky2.h
@@ -2074,7 +2074,7 @@ enum {
 	GM_IS_RX_FF_OR	= 1<<1,	/* Receive FIFO Overrun */
 	GM_IS_RX_COMPL	= 1<<0,	/* Frame Reception Complete */
 
-#define GMAC_DEF_MSK     GM_IS_TX_FF_UR
+#define GMAC_DEF_MSK     (GM_IS_TX_FF_UR | GM_IS_RX_FF_OR)
 };
 
 /*	GMAC_LINK_CTRL	16 bit	GMAC Link Control Reg (YUKON only) */
diff --git a/drivers/net/ethernet/mellanox/mlx4/cmd.c b/drivers/net/ethernet/mellanox/mlx4/cmd.c
index fdc5f23..05267d7 100644
--- a/drivers/net/ethernet/mellanox/mlx4/cmd.c
+++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c
@@ -1837,10 +1837,8 @@ int mlx4_cmd_init(struct mlx4_dev *dev)
 		priv->mfunc.vhcr = dma_alloc_coherent(&(dev->pdev->dev), PAGE_SIZE,
 						      &priv->mfunc.vhcr_dma,
 						      GFP_KERNEL);
-		if (!priv->mfunc.vhcr) {
-			mlx4_err(dev, "Couldn't allocate VHCR.\n");
+		if (!priv->mfunc.vhcr)
 			goto err_hcr;
-		}
 	}
 
 	priv->cmd.pool = pci_pool_create("mlx4_cmd", dev->pdev,
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index f278b10..473c9d2 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -411,8 +411,8 @@ static int mlx4_en_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
 
 static void mlx4_en_u64_to_mac(unsigned char dst_mac[ETH_ALEN + 2], u64 src_mac)
 {
-	unsigned int i;
-	for (i = ETH_ALEN - 1; i; --i) {
+	int i;
+	for (i = ETH_ALEN - 1; i >= 0; --i) {
 		dst_mac[i] = src_mac & 0xff;
 		src_mac >>= 8;
 	}
@@ -1931,79 +1931,6 @@ static int mlx4_en_set_features(struct net_device *netdev,
 
 }
 
-static int mlx4_en_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
-			   struct net_device *dev,
-			   const unsigned char *addr, u16 flags)
-{
-	struct mlx4_en_priv *priv = netdev_priv(dev);
-	struct mlx4_dev *mdev = priv->mdev->dev;
-	int err;
-
-	if (!mlx4_is_mfunc(mdev))
-		return -EOPNOTSUPP;
-
-	/* Hardware does not support aging addresses, allow only
-	 * permanent addresses if ndm_state is given
-	 */
-	if (ndm->ndm_state && !(ndm->ndm_state & NUD_PERMANENT)) {
-		en_info(priv, "Add FDB only supports static addresses\n");
-		return -EINVAL;
-	}
-
-	if (is_unicast_ether_addr(addr) || is_link_local_ether_addr(addr))
-		err = dev_uc_add_excl(dev, addr);
-	else if (is_multicast_ether_addr(addr))
-		err = dev_mc_add_excl(dev, addr);
-	else
-		err = -EINVAL;
-
-	/* Only return duplicate errors if NLM_F_EXCL is set */
-	if (err == -EEXIST && !(flags & NLM_F_EXCL))
-		err = 0;
-
-	return err;
-}
-
-static int mlx4_en_fdb_del(struct ndmsg *ndm,
-			   struct nlattr *tb[],
-			   struct net_device *dev,
-			   const unsigned char *addr)
-{
-	struct mlx4_en_priv *priv = netdev_priv(dev);
-	struct mlx4_dev *mdev = priv->mdev->dev;
-	int err;
-
-	if (!mlx4_is_mfunc(mdev))
-		return -EOPNOTSUPP;
-
-	if (ndm->ndm_state && !(ndm->ndm_state & NUD_PERMANENT)) {
-		en_info(priv, "Del FDB only supports static addresses\n");
-		return -EINVAL;
-	}
-
-	if (is_unicast_ether_addr(addr) || is_link_local_ether_addr(addr))
-		err = dev_uc_del(dev, addr);
-	else if (is_multicast_ether_addr(addr))
-		err = dev_mc_del(dev, addr);
-	else
-		err = -EINVAL;
-
-	return err;
-}
-
-static int mlx4_en_fdb_dump(struct sk_buff *skb,
-			    struct netlink_callback *cb,
-			    struct net_device *dev, int idx)
-{
-	struct mlx4_en_priv *priv = netdev_priv(dev);
-	struct mlx4_dev *mdev = priv->mdev->dev;
-
-	if (mlx4_is_mfunc(mdev))
-		idx = ndo_dflt_fdb_dump(skb, cb, dev, idx);
-
-	return idx;
-}
-
 static const struct net_device_ops mlx4_netdev_ops = {
 	.ndo_open		= mlx4_en_open,
 	.ndo_stop		= mlx4_en_close,
@@ -2025,9 +1952,6 @@ static const struct net_device_ops mlx4_netdev_ops = {
 #ifdef CONFIG_RFS_ACCEL
 	.ndo_rx_flow_steer	= mlx4_en_filter_rfs,
 #endif
-	.ndo_fdb_add		= mlx4_en_fdb_add,
-	.ndo_fdb_del		= mlx4_en_fdb_del,
-	.ndo_fdb_dump		= mlx4_en_fdb_dump,
 };
 
 int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_selftest.c b/drivers/net/ethernet/mellanox/mlx4/en_selftest.c
index 3488c6d..2448f0d 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_selftest.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_selftest.c
@@ -58,10 +58,9 @@ static int mlx4_en_test_loopback_xmit(struct mlx4_en_priv *priv)
 
 	/* build the pkt before xmit */
 	skb = netdev_alloc_skb(priv->dev, MLX4_LOOPBACK_TEST_PAYLOAD + ETH_HLEN + NET_IP_ALIGN);
-	if (!skb) {
-		en_err(priv, "-LOOPBACK_TEST_XMIT- failed to create skb for xmit\n");
+	if (!skb)
 		return -ENOMEM;
-	}
+
 	skb_reserve(skb, NET_IP_ALIGN);
 
 	ethh = (struct ethhdr *)skb_put(skb, sizeof(struct ethhdr));
diff --git a/drivers/net/ethernet/micrel/ks8695net.c b/drivers/net/ethernet/micrel/ks8695net.c
index 07a6ebc..b6c60fd 100644
--- a/drivers/net/ethernet/micrel/ks8695net.c
+++ b/drivers/net/ethernet/micrel/ks8695net.c
@@ -1622,25 +1622,7 @@ static struct platform_driver ks8695_driver = {
 	.resume		= ks8695_drv_resume,
 };
 
-/* Module interface */
-
-static int __init
-ks8695_init(void)
-{
-	printk(KERN_INFO "%s Ethernet driver, V%s\n",
-	       MODULENAME, MODULEVERSION);
-
-	return platform_driver_register(&ks8695_driver);
-}
-
-static void __exit
-ks8695_cleanup(void)
-{
-	platform_driver_unregister(&ks8695_driver);
-}
-
-module_init(ks8695_init);
-module_exit(ks8695_cleanup);
+module_platform_driver(ks8695_driver);
 
 MODULE_AUTHOR("Simtec Electronics");
 MODULE_DESCRIPTION("Micrel KS8695 (Centaur) Ethernet driver");
diff --git a/drivers/net/ethernet/micrel/ks8851.c b/drivers/net/ethernet/micrel/ks8851.c
index 33bcb63..8fb4812 100644
--- a/drivers/net/ethernet/micrel/ks8851.c
+++ b/drivers/net/ethernet/micrel/ks8851.c
@@ -528,7 +528,7 @@ static void ks8851_rx_pkts(struct ks8851_net *ks)
 	for (; rxfc != 0; rxfc--) {
 		rxh = ks8851_rdreg32(ks, KS_RXFHSR);
 		rxstat = rxh & 0xffff;
-		rxlen = rxh >> 16;
+		rxlen = (rxh >> 16) & 0xfff;
 
 		netif_dbg(ks, rx_status, ks->netdev,
 			  "rx: stat 0x%04x, len 0x%04x\n", rxstat, rxlen);
diff --git a/drivers/net/ethernet/micrel/ks8851_mll.c b/drivers/net/ethernet/micrel/ks8851_mll.c
index a343066..ddaf138 100644
--- a/drivers/net/ethernet/micrel/ks8851_mll.c
+++ b/drivers/net/ethernet/micrel/ks8851_mll.c
@@ -792,20 +792,35 @@ static void ks_rcv(struct ks_net *ks, struct net_device *netdev)
 
 	frame_hdr = ks->frame_head_info;
 	while (ks->frame_cnt--) {
+		if (unlikely(!(frame_hdr->sts & RXFSHR_RXFV) ||
+			     frame_hdr->len >= RX_BUF_SIZE ||
+			     frame_hdr->len <= 0)) {
+
+			/* discard an invalid packet */
+			ks_wrreg16(ks, KS_RXQCR, (ks->rc_rxqcr | RXQCR_RRXEF));
+			netdev->stats.rx_dropped++;
+			if (!(frame_hdr->sts & RXFSHR_RXFV))
+				netdev->stats.rx_frame_errors++;
+			else
+				netdev->stats.rx_length_errors++;
+			frame_hdr++;
+			continue;
+		}
+
 		skb = netdev_alloc_skb(netdev, frame_hdr->len + 16);
-		if (likely(skb && (frame_hdr->sts & RXFSHR_RXFV) &&
-			(frame_hdr->len < RX_BUF_SIZE) && frame_hdr->len)) {
+		if (likely(skb)) {
 			skb_reserve(skb, 2);
 			/* read data block including CRC 4 bytes */
 			ks_read_qmu(ks, (u16 *)skb->data, frame_hdr->len);
-			skb_put(skb, frame_hdr->len);
+			skb_put(skb, frame_hdr->len - 4);
 			skb->protocol = eth_type_trans(skb, netdev);
 			netif_rx(skb);
+			/* exclude CRC size */
+			netdev->stats.rx_bytes += frame_hdr->len - 4;
+			netdev->stats.rx_packets++;
 		} else {
-			pr_err("%s: err:skb alloc\n", __func__);
 			ks_wrreg16(ks, KS_RXQCR, (ks->rc_rxqcr | RXQCR_RRXEF));
-			if (skb)
-				dev_kfree_skb_irq(skb);
+			netdev->stats.rx_dropped++;
 		}
 		frame_hdr++;
 	}
@@ -877,6 +892,8 @@ static irqreturn_t ks_irq(int irq, void *pw)
 		ks_wrreg16(ks, KS_PMECR, pmecr | PMECR_WKEVT_LINK);
 	}
 
+	if (unlikely(status & IRQ_RXOI))
+		ks->netdev->stats.rx_over_errors++;
 	/* this should be the last in IRQ handler*/
 	ks_restore_cmd_reg(ks);
 	return IRQ_HANDLED;
@@ -1015,6 +1032,9 @@ static int ks_start_xmit(struct sk_buff *skb, struct net_device *netdev)
 
 	if (likely(ks_tx_fifo_space(ks) >= skb->len + 12)) {
 		ks_write_qmu(ks, skb->data, skb->len);
+		/* add tx statistics */
+		netdev->stats.tx_bytes += skb->len;
+		netdev->stats.tx_packets++;
 		dev_kfree_skb(skb);
 	} else
 		retv = NETDEV_TX_BUSY;
diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
index 4f9937e..d5ffdc8 100644
--- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
+++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
@@ -3592,10 +3592,9 @@ static int myri10ge_alloc_slices(struct myri10ge_priv *mgp)
 		bytes = mgp->max_intr_slots * sizeof(*ss->rx_done.entry);
 		ss->rx_done.entry = dma_alloc_coherent(&pdev->dev, bytes,
 						       &ss->rx_done.bus,
-						       GFP_KERNEL);
+						       GFP_KERNEL | __GFP_ZERO);
 		if (ss->rx_done.entry == NULL)
 			goto abort;
-		memset(ss->rx_done.entry, 0, bytes);
 		bytes = sizeof(*ss->fw_stats);
 		ss->fw_stats = dma_alloc_coherent(&pdev->dev, bytes,
 						  &ss->fw_stats_bus,
diff --git a/drivers/net/ethernet/natsemi/jazzsonic.c b/drivers/net/ethernet/natsemi/jazzsonic.c
index b0b3615..c20766c 100644
--- a/drivers/net/ethernet/natsemi/jazzsonic.c
+++ b/drivers/net/ethernet/natsemi/jazzsonic.c
@@ -175,13 +175,13 @@ static int sonic_probe1(struct net_device *dev)
 
 	/* Allocate the entire chunk of memory for the descriptors.
            Note that this cannot cross a 64K boundary. */
-	if ((lp->descriptors = dma_alloc_coherent(lp->device,
-				SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode),
-				&lp->descriptors_laddr, GFP_KERNEL)) == NULL) {
-		printk(KERN_ERR "%s: couldn't alloc DMA memory for descriptors.\n",
-		       dev_name(lp->device));
+	lp->descriptors = dma_alloc_coherent(lp->device,
+					     SIZEOF_SONIC_DESC *
+					     SONIC_BUS_SCALE(lp->dma_bitmode),
+					     &lp->descriptors_laddr,
+					     GFP_KERNEL);
+	if (lp->descriptors == NULL)
 		goto out;
-	}
 
 	/* Now set up the pointers to point to the appropriate places */
 	lp->cda = lp->descriptors;
diff --git a/drivers/net/ethernet/natsemi/macsonic.c b/drivers/net/ethernet/natsemi/macsonic.c
index 0ffde69..346a4e0 100644
--- a/drivers/net/ethernet/natsemi/macsonic.c
+++ b/drivers/net/ethernet/natsemi/macsonic.c
@@ -202,13 +202,13 @@ static int macsonic_init(struct net_device *dev)
 
 	/* Allocate the entire chunk of memory for the descriptors.
            Note that this cannot cross a 64K boundary. */
-	if ((lp->descriptors = dma_alloc_coherent(lp->device,
-	            SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode),
-	            &lp->descriptors_laddr, GFP_KERNEL)) == NULL) {
-		printk(KERN_ERR "%s: couldn't alloc DMA memory for descriptors.\n",
-		       dev_name(lp->device));
+	lp->descriptors = dma_alloc_coherent(lp->device,
+					     SIZEOF_SONIC_DESC *
+					     SONIC_BUS_SCALE(lp->dma_bitmode),
+					     &lp->descriptors_laddr,
+					     GFP_KERNEL);
+	if (lp->descriptors == NULL)
 		return -ENOMEM;
-	}
 
 	/* Now set up the pointers to point to the appropriate places */
 	lp->cda = lp->descriptors;
diff --git a/drivers/net/ethernet/natsemi/sonic.c b/drivers/net/ethernet/natsemi/sonic.c
index 46795e4..1bd419d 100644
--- a/drivers/net/ethernet/natsemi/sonic.c
+++ b/drivers/net/ethernet/natsemi/sonic.c
@@ -424,7 +424,6 @@ static void sonic_rx(struct net_device *dev)
 			/* Malloc up new buffer. */
 			new_skb = netdev_alloc_skb(dev, SONIC_RBSIZE + 2);
 			if (new_skb == NULL) {
-				printk(KERN_ERR "%s: Memory squeeze, dropping packet.\n", dev->name);
 				lp->stats.rx_dropped++;
 				break;
 			}
diff --git a/drivers/net/ethernet/natsemi/xtsonic.c b/drivers/net/ethernet/natsemi/xtsonic.c
index 5e4748e..c2e0256 100644
--- a/drivers/net/ethernet/natsemi/xtsonic.c
+++ b/drivers/net/ethernet/natsemi/xtsonic.c
@@ -197,14 +197,12 @@ static int __init sonic_probe1(struct net_device *dev)
 	 *  We also allocate extra space for a pointer to allow freeing
 	 *  this structure later on (in xtsonic_cleanup_module()).
 	 */
-	lp->descriptors =
-		dma_alloc_coherent(lp->device,
-			SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode),
-			&lp->descriptors_laddr, GFP_KERNEL);
-
+	lp->descriptors = dma_alloc_coherent(lp->device,
+					     SIZEOF_SONIC_DESC *
+					     SONIC_BUS_SCALE(lp->dma_bitmode),
+					     &lp->descriptors_laddr,
+					     GFP_KERNEL);
 	if (lp->descriptors == NULL) {
-		printk(KERN_ERR "%s: couldn't alloc DMA memory for "
-				" descriptors.\n", dev_name(lp->device));
 		err = -ENOMEM;
 		goto out;
 	}
diff --git a/drivers/net/ethernet/neterion/s2io.c b/drivers/net/ethernet/neterion/s2io.c
index bfd8873..3371ff4 100644
--- a/drivers/net/ethernet/neterion/s2io.c
+++ b/drivers/net/ethernet/neterion/s2io.c
@@ -80,6 +80,7 @@
 #include <linux/slab.h>
 #include <linux/prefetch.h>
 #include <net/tcp.h>
+#include <net/checksum.h>
 
 #include <asm/div64.h>
 #include <asm/irq.h>
@@ -8337,16 +8338,13 @@ static void update_L3L4_header(struct s2io_nic *sp, struct lro *lro)
 {
 	struct iphdr *ip = lro->iph;
 	struct tcphdr *tcp = lro->tcph;
-	__sum16 nchk;
 	struct swStat *swstats = &sp->mac_control.stats_info->sw_stat;
 
 	DBG_PRINT(INFO_DBG, "%s: Been here...\n", __func__);
 
 	/* Update L3 header */
+	csum_replace2(&ip->check, ip->tot_len, htons(lro->total_len));
 	ip->tot_len = htons(lro->total_len);
-	ip->check = 0;
-	nchk = ip_fast_csum((u8 *)lro->iph, ip->ihl);
-	ip->check = nchk;
 
 	/* Update L4 header */
 	tcp->ack_seq = lro->tcp_ack;
diff --git a/drivers/net/ethernet/netx-eth.c b/drivers/net/ethernet/netx-eth.c
index 63e7af4..cb9e638 100644
--- a/drivers/net/ethernet/netx-eth.c
+++ b/drivers/net/ethernet/netx-eth.c
@@ -152,8 +152,6 @@ static void netx_eth_receive(struct net_device *ndev)
 
 	skb = netdev_alloc_skb(ndev, len);
 	if (unlikely(skb == NULL)) {
-		printk(KERN_NOTICE "%s: Low memory, packet dropped.\n",
-			ndev->name);
 		ndev->stats.rx_dropped++;
 		return;
 	}
diff --git a/drivers/net/ethernet/nuvoton/w90p910_ether.c b/drivers/net/ethernet/nuvoton/w90p910_ether.c
index 162da89..3df8287 100644
--- a/drivers/net/ethernet/nuvoton/w90p910_ether.c
+++ b/drivers/net/ethernet/nuvoton/w90p910_ether.c
@@ -287,23 +287,16 @@ static int w90p910_init_desc(struct net_device *dev)
 	ether = netdev_priv(dev);
 	pdev = ether->pdev;
 
-	ether->tdesc = (struct tran_pdesc *)
-		dma_alloc_coherent(&pdev->dev, sizeof(struct tran_pdesc),
-					&ether->tdesc_phys, GFP_KERNEL);
-
-	if (!ether->tdesc) {
-		dev_err(&pdev->dev, "Failed to allocate memory for tx desc\n");
+	ether->tdesc = dma_alloc_coherent(&pdev->dev, sizeof(struct tran_pdesc),
+					  &ether->tdesc_phys, GFP_KERNEL);
+	if (!ether->tdesc)
 		return -ENOMEM;
-	}
-
-	ether->rdesc = (struct recv_pdesc *)
-		dma_alloc_coherent(&pdev->dev, sizeof(struct recv_pdesc),
-					&ether->rdesc_phys, GFP_KERNEL);
 
+	ether->rdesc = dma_alloc_coherent(&pdev->dev, sizeof(struct recv_pdesc),
+					  &ether->rdesc_phys, GFP_KERNEL);
 	if (!ether->rdesc) {
-		dev_err(&pdev->dev, "Failed to allocate memory for rx desc\n");
 		dma_free_coherent(&pdev->dev, sizeof(struct tran_pdesc),
-					ether->tdesc, ether->tdesc_phys);
+				  ether->tdesc, ether->tdesc_phys);
 		return -ENOMEM;
 	}
 
@@ -737,7 +730,6 @@ static void netdev_rx(struct net_device *dev)
 			data = ether->rdesc->recv_buf[ether->cur_rx];
 			skb = netdev_alloc_skb(dev, length + 2);
 			if (!skb) {
-				dev_err(&pdev->dev, "get skb buffer error\n");
 				ether->stats.rx_dropped++;
 				return;
 			}
diff --git a/drivers/net/ethernet/nvidia/forcedeth.c b/drivers/net/ethernet/nvidia/forcedeth.c
index 0b8de12..5ae1247 100644
--- a/drivers/net/ethernet/nvidia/forcedeth.c
+++ b/drivers/net/ethernet/nvidia/forcedeth.c
@@ -2200,6 +2200,7 @@ static netdev_tx_t nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	struct ring_desc *start_tx;
 	struct ring_desc *prev_tx;
 	struct nv_skb_map *prev_tx_ctx;
+	struct nv_skb_map *tmp_tx_ctx = NULL, *start_tx_ctx = NULL;
 	unsigned long flags;
 
 	/* add fragments to entries count */
@@ -2261,12 +2262,31 @@ static netdev_tx_t nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
 		do {
 			prev_tx = put_tx;
 			prev_tx_ctx = np->put_tx_ctx;
+			if (!start_tx_ctx)
+				start_tx_ctx = tmp_tx_ctx = np->put_tx_ctx;
+
 			bcnt = (frag_size > NV_TX2_TSO_MAX_SIZE) ? NV_TX2_TSO_MAX_SIZE : frag_size;
 			np->put_tx_ctx->dma = skb_frag_dma_map(
 							&np->pci_dev->dev,
 							frag, offset,
 							bcnt,
 							DMA_TO_DEVICE);
+			if (dma_mapping_error(&np->pci_dev->dev, np->put_tx_ctx->dma)) {
+
+				/* Unwind the mapped fragments */
+				do {
+					nv_unmap_txskb(np, start_tx_ctx);
+					if (unlikely(tmp_tx_ctx++ == np->last_tx_ctx))
+						tmp_tx_ctx = np->first_tx_ctx;
+				} while (tmp_tx_ctx != np->put_tx_ctx);
+				kfree_skb(skb);
+				np->put_tx_ctx = start_tx_ctx;
+				u64_stats_update_begin(&np->swstats_tx_syncp);
+				np->stat_tx_dropped++;
+				u64_stats_update_end(&np->swstats_tx_syncp);
+				return NETDEV_TX_OK;
+			}
+
 			np->put_tx_ctx->dma_len = bcnt;
 			np->put_tx_ctx->dma_single = 0;
 			put_tx->buf = cpu_to_le32(np->put_tx_ctx->dma);
@@ -2327,7 +2347,8 @@ static netdev_tx_t nv_start_xmit_optimized(struct sk_buff *skb,
 	struct ring_desc_ex *start_tx;
 	struct ring_desc_ex *prev_tx;
 	struct nv_skb_map *prev_tx_ctx;
-	struct nv_skb_map *start_tx_ctx;
+	struct nv_skb_map *start_tx_ctx = NULL;
+	struct nv_skb_map *tmp_tx_ctx = NULL;
 	unsigned long flags;
 
 	/* add fragments to entries count */
@@ -2392,11 +2413,29 @@ static netdev_tx_t nv_start_xmit_optimized(struct sk_buff *skb,
 			prev_tx = put_tx;
 			prev_tx_ctx = np->put_tx_ctx;
 			bcnt = (frag_size > NV_TX2_TSO_MAX_SIZE) ? NV_TX2_TSO_MAX_SIZE : frag_size;
+			if (!start_tx_ctx)
+				start_tx_ctx = tmp_tx_ctx = np->put_tx_ctx;
 			np->put_tx_ctx->dma = skb_frag_dma_map(
 							&np->pci_dev->dev,
 							frag, offset,
 							bcnt,
 							DMA_TO_DEVICE);
+
+			if (dma_mapping_error(&np->pci_dev->dev, np->put_tx_ctx->dma)) {
+
+				/* Unwind the mapped fragments */
+				do {
+					nv_unmap_txskb(np, start_tx_ctx);
+					if (unlikely(tmp_tx_ctx++ == np->last_tx_ctx))
+						tmp_tx_ctx = np->first_tx_ctx;
+				} while (tmp_tx_ctx != np->put_tx_ctx);
+				kfree_skb(skb);
+				np->put_tx_ctx = start_tx_ctx;
+				u64_stats_update_begin(&np->swstats_tx_syncp);
+				np->stat_tx_dropped++;
+				u64_stats_update_end(&np->swstats_tx_syncp);
+				return NETDEV_TX_OK;
+			}
 			np->put_tx_ctx->dma_len = bcnt;
 			np->put_tx_ctx->dma_single = 0;
 			put_tx->bufhigh = cpu_to_le32(dma_high(np->put_tx_ctx->dma));
@@ -5025,7 +5064,6 @@ static int nv_loopback_test(struct net_device *dev)
 	pkt_len = ETH_DATA_LEN;
 	tx_skb = netdev_alloc_skb(dev, pkt_len);
 	if (!tx_skb) {
-		netdev_err(dev, "netdev_alloc_skb() failed during loopback test\n");
 		ret = 0;
 		goto out;
 	}
diff --git a/drivers/net/ethernet/nxp/lpc_eth.c b/drivers/net/ethernet/nxp/lpc_eth.c
index efa29b7..55a5548 100644
--- a/drivers/net/ethernet/nxp/lpc_eth.c
+++ b/drivers/net/ethernet/nxp/lpc_eth.c
@@ -1409,9 +1409,7 @@ static int lpc_eth_drv_probe(struct platform_device *pdev)
 			dma_alloc_coherent(&pldat->pdev->dev,
 					   pldat->dma_buff_size, &dma_handle,
 					   GFP_KERNEL);
-
 		if (pldat->dma_buff_base_v == NULL) {
-			dev_err(&pdev->dev, "error getting DMA region.\n");
 			ret = -ENOMEM;
 			goto err_out_free_irq;
 		}
@@ -1434,13 +1432,11 @@ static int lpc_eth_drv_probe(struct platform_device *pdev)
 	/* Get MAC address from current HW setting (POR state is all zeros) */
 	__lpc_get_mac(pldat, ndev->dev_addr);
 
-#ifdef CONFIG_OF_NET
 	if (!is_valid_ether_addr(ndev->dev_addr)) {
 		const char *macaddr = of_get_mac_address(pdev->dev.of_node);
 		if (macaddr)
 			memcpy(ndev->dev_addr, macaddr, ETH_ALEN);
 	}
-#endif
 	if (!is_valid_ether_addr(ndev->dev_addr))
 		eth_hw_addr_random(ndev);
 
diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
index 73ce7dd..60eb890 100644
--- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
@@ -1469,13 +1469,11 @@ pch_gbe_alloc_rx_buffers_pool(struct pch_gbe_adapter *adapter,
 
 	size = rx_ring->count * bufsz + PCH_GBE_RESERVE_MEMORY;
 	rx_ring->rx_buff_pool = dma_alloc_coherent(&pdev->dev, size,
-						&rx_ring->rx_buff_pool_logic,
-						GFP_KERNEL);
-	if (!rx_ring->rx_buff_pool) {
-		pr_err("Unable to allocate memory for the receive pool buffer\n");
+						   &rx_ring->rx_buff_pool_logic,
+						   GFP_KERNEL | __GFP_ZERO);
+	if (!rx_ring->rx_buff_pool)
 		return -ENOMEM;
-	}
-	memset(rx_ring->rx_buff_pool, 0, size);
+
 	rx_ring->rx_buff_pool_size = size;
 	for (i = 0; i < rx_ring->count; i++) {
 		buffer_info = &rx_ring->buffer_info[i];
@@ -1774,13 +1772,12 @@ int pch_gbe_setup_tx_resources(struct pch_gbe_adapter *adapter,
 	tx_ring->size = tx_ring->count * (int)sizeof(struct pch_gbe_tx_desc);
 
 	tx_ring->desc = dma_alloc_coherent(&pdev->dev, tx_ring->size,
-					   &tx_ring->dma, GFP_KERNEL);
+					   &tx_ring->dma,
+					   GFP_KERNEL | __GFP_ZERO);
 	if (!tx_ring->desc) {
 		vfree(tx_ring->buffer_info);
-		pr_err("Unable to allocate memory for the transmit descriptor ring\n");
 		return -ENOMEM;
 	}
-	memset(tx_ring->desc, 0, tx_ring->size);
 
 	tx_ring->next_to_use = 0;
 	tx_ring->next_to_clean = 0;
@@ -1820,14 +1817,12 @@ int pch_gbe_setup_rx_resources(struct pch_gbe_adapter *adapter,
 
 	rx_ring->size = rx_ring->count * (int)sizeof(struct pch_gbe_rx_desc);
 	rx_ring->desc =	dma_alloc_coherent(&pdev->dev, rx_ring->size,
-					   &rx_ring->dma, GFP_KERNEL);
-
+					   &rx_ring->dma,
+					   GFP_KERNEL | __GFP_ZERO);
 	if (!rx_ring->desc) {
-		pr_err("Unable to allocate memory for the receive descriptor ring\n");
 		vfree(rx_ring->buffer_info);
 		return -ENOMEM;
 	}
-	memset(rx_ring->desc, 0, rx_ring->size);
 	rx_ring->next_to_clean = 0;
 	rx_ring->next_to_use = 0;
 	for (desNo = 0; desNo < rx_ring->count; desNo++) {
diff --git a/drivers/net/ethernet/pasemi/pasemi_mac.c b/drivers/net/ethernet/pasemi/pasemi_mac.c
index b1cfbb7..a5f0b5d 100644
--- a/drivers/net/ethernet/pasemi/pasemi_mac.c
+++ b/drivers/net/ethernet/pasemi/pasemi_mac.c
@@ -441,12 +441,11 @@ static int pasemi_mac_setup_rx_resources(const struct net_device *dev)
 
 	ring->buffers = dma_alloc_coherent(&mac->dma_pdev->dev,
 					   RX_RING_SIZE * sizeof(u64),
-					   &ring->buf_dma, GFP_KERNEL);
+					   &ring->buf_dma,
+					   GFP_KERNEL | __GFP_ZERO);
 	if (!ring->buffers)
 		goto out_ring_desc;
 
-	memset(ring->buffers, 0, RX_RING_SIZE * sizeof(u64));
-
 	write_dma_reg(PAS_DMA_RXCHAN_BASEL(chno),
 		      PAS_DMA_RXCHAN_BASEL_BRBL(ring->chan.ring_dma));
 
diff --git a/drivers/net/ethernet/qlogic/Kconfig b/drivers/net/ethernet/qlogic/Kconfig
index a8669ad..0e17972 100644
--- a/drivers/net/ethernet/qlogic/Kconfig
+++ b/drivers/net/ethernet/qlogic/Kconfig
@@ -35,6 +35,16 @@ config QLCNIC
 	  This driver supports QLogic QLE8240 and QLE8242 Converged Ethernet
 	  devices.
 
+config QLCNIC_SRIOV
+	bool "QLOGIC QLCNIC 83XX family SR-IOV Support"
+	depends on QLCNIC && PCI_IOV
+	default y
+	---help---
+	  This configuration parameter enables Single Root Input Output
+	  Virtualization support for QLE83XX Converged Ethernet devices.
+	  This allows for virtual function acceleration in virtualized
+	  environments.
+
 config QLGE
 	tristate "QLogic QLGE 10Gb Ethernet Driver Support"
 	depends on PCI
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic.h b/drivers/net/ethernet/qlogic/netxen/netxen_nic.h
index eb3dfdb..322a36b 100644
--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic.h
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic.h
@@ -955,9 +955,10 @@ typedef struct nx_mac_list_s {
 	uint8_t mac_addr[ETH_ALEN+2];
 } nx_mac_list_t;
 
-struct nx_vlan_ip_list {
+struct nx_ip_list {
 	struct list_head list;
 	__be32 ip_addr;
+	bool master;
 };
 
 /*
@@ -1605,7 +1606,7 @@ struct netxen_adapter {
 	struct net_device *netdev;
 	struct pci_dev *pdev;
 	struct list_head mac_list;
-	struct list_head vlan_ip_list;
+	struct list_head ip_list;
 
 	spinlock_t tx_clean_lock;
 
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c
index 4782dcf..7692dfd 100644
--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c
@@ -27,6 +27,7 @@
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/if_vlan.h>
+#include <net/checksum.h>
 #include "netxen_nic.h"
 #include "netxen_nic_hw.h"
 
@@ -1641,9 +1642,8 @@ netxen_process_lro(struct netxen_adapter *adapter,
 	th = (struct tcphdr *)((skb->data + vhdr_len) + (iph->ihl << 2));
 
 	length = (iph->ihl << 2) + (th->doff << 2) + lro_length;
+	csum_replace2(&iph->check, iph->tot_len, htons(length));
 	iph->tot_len = htons(length);
-	iph->check = 0;
-	iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
 	th->psh = push;
 	th->seq = htonl(seq_number);
 
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
index 501f492..7867aeb 100644
--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
@@ -90,7 +90,7 @@ static irqreturn_t netxen_intr(int irq, void *data);
 static irqreturn_t netxen_msi_intr(int irq, void *data);
 static irqreturn_t netxen_msix_intr(int irq, void *data);
 
-static void netxen_free_vlan_ip_list(struct netxen_adapter *);
+static void netxen_free_ip_list(struct netxen_adapter *, bool);
 static void netxen_restore_indev_addr(struct net_device *dev, unsigned long);
 static struct rtnl_link_stats64 *netxen_nic_get_stats(struct net_device *dev,
 						      struct rtnl_link_stats64 *stats);
@@ -1450,7 +1450,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	spin_lock_init(&adapter->tx_clean_lock);
 	INIT_LIST_HEAD(&adapter->mac_list);
-	INIT_LIST_HEAD(&adapter->vlan_ip_list);
+	INIT_LIST_HEAD(&adapter->ip_list);
 
 	err = netxen_setup_pci_map(adapter);
 	if (err)
@@ -1585,7 +1585,7 @@ static void netxen_nic_remove(struct pci_dev *pdev)
 
 	cancel_work_sync(&adapter->tx_timeout_task);
 
-	netxen_free_vlan_ip_list(adapter);
+	netxen_free_ip_list(adapter, false);
 	netxen_nic_detach(adapter);
 
 	nx_decr_dev_ref_cnt(adapter);
@@ -3137,62 +3137,77 @@ netxen_destip_supported(struct netxen_adapter *adapter)
 }
 
 static void
-netxen_free_vlan_ip_list(struct netxen_adapter *adapter)
+netxen_free_ip_list(struct netxen_adapter *adapter, bool master)
 {
-	struct nx_vlan_ip_list  *cur;
-	struct list_head *head = &adapter->vlan_ip_list;
+	struct nx_ip_list  *cur, *tmp_cur;
 
-	while (!list_empty(head)) {
-		cur = list_entry(head->next, struct nx_vlan_ip_list, list);
-		netxen_config_ipaddr(adapter, cur->ip_addr, NX_IP_DOWN);
-		list_del(&cur->list);
-		kfree(cur);
+	list_for_each_entry_safe(cur, tmp_cur, &adapter->ip_list, list) {
+		if (master) {
+			if (cur->master) {
+				netxen_config_ipaddr(adapter, cur->ip_addr,
+						     NX_IP_DOWN);
+				list_del(&cur->list);
+				kfree(cur);
+			}
+		} else {
+			netxen_config_ipaddr(adapter, cur->ip_addr, NX_IP_DOWN);
+			list_del(&cur->list);
+			kfree(cur);
+		}
 	}
-
 }
-static void
-netxen_list_config_vlan_ip(struct netxen_adapter *adapter,
+
+static bool
+netxen_list_config_ip(struct netxen_adapter *adapter,
 		struct in_ifaddr *ifa, unsigned long event)
 {
 	struct net_device *dev;
-	struct nx_vlan_ip_list *cur, *tmp_cur;
+	struct nx_ip_list *cur, *tmp_cur;
 	struct list_head *head;
+	bool ret = false;
 
 	dev = ifa->ifa_dev ? ifa->ifa_dev->dev : NULL;
 
 	if (dev == NULL)
-		return;
-
-	if (!is_vlan_dev(dev))
-		return;
+		goto out;
 
 	switch (event) {
 	case NX_IP_UP:
-		list_for_each(head, &adapter->vlan_ip_list) {
-			cur = list_entry(head, struct nx_vlan_ip_list, list);
+		list_for_each(head, &adapter->ip_list) {
+			cur = list_entry(head, struct nx_ip_list, list);
 
 			if (cur->ip_addr == ifa->ifa_address)
-				return;
+				goto out;
 		}
 
-		cur = kzalloc(sizeof(struct nx_vlan_ip_list), GFP_ATOMIC);
+		cur = kzalloc(sizeof(struct nx_ip_list), GFP_ATOMIC);
 		if (cur == NULL)
-			return;
-
+			goto out;
+		if (dev->priv_flags & IFF_802_1Q_VLAN)
+			dev = vlan_dev_real_dev(dev);
+		cur->master = !!netif_is_bond_master(dev);
 		cur->ip_addr = ifa->ifa_address;
-		list_add_tail(&cur->list, &adapter->vlan_ip_list);
+		list_add_tail(&cur->list, &adapter->ip_list);
+		netxen_config_ipaddr(adapter, ifa->ifa_address, NX_IP_UP);
+		ret = true;
 		break;
 	case NX_IP_DOWN:
 		list_for_each_entry_safe(cur, tmp_cur,
-					&adapter->vlan_ip_list, list) {
+					&adapter->ip_list, list) {
 			if (cur->ip_addr == ifa->ifa_address) {
 				list_del(&cur->list);
 				kfree(cur);
+				netxen_config_ipaddr(adapter, ifa->ifa_address,
+						     NX_IP_DOWN);
+				ret = true;
 				break;
 			}
 		}
 	}
+out:
+	return ret;
 }
+
 static void
 netxen_config_indev_addr(struct netxen_adapter *adapter,
 		struct net_device *dev, unsigned long event)
@@ -3209,14 +3224,10 @@ netxen_config_indev_addr(struct netxen_adapter *adapter,
 	for_ifa(indev) {
 		switch (event) {
 		case NETDEV_UP:
-			netxen_config_ipaddr(adapter,
-					ifa->ifa_address, NX_IP_UP);
-			netxen_list_config_vlan_ip(adapter, ifa, NX_IP_UP);
+			netxen_list_config_ip(adapter, ifa, NX_IP_UP);
 			break;
 		case NETDEV_DOWN:
-			netxen_config_ipaddr(adapter,
-					ifa->ifa_address, NX_IP_DOWN);
-			netxen_list_config_vlan_ip(adapter, ifa, NX_IP_DOWN);
+			netxen_list_config_ip(adapter, ifa, NX_IP_DOWN);
 			break;
 		default:
 			break;
@@ -3231,23 +3242,78 @@ netxen_restore_indev_addr(struct net_device *netdev, unsigned long event)
 
 {
 	struct netxen_adapter *adapter = netdev_priv(netdev);
-	struct nx_vlan_ip_list *pos, *tmp_pos;
+	struct nx_ip_list *pos, *tmp_pos;
 	unsigned long ip_event;
 
 	ip_event = (event == NETDEV_UP) ? NX_IP_UP : NX_IP_DOWN;
 	netxen_config_indev_addr(adapter, netdev, event);
 
-	list_for_each_entry_safe(pos, tmp_pos, &adapter->vlan_ip_list, list) {
+	list_for_each_entry_safe(pos, tmp_pos, &adapter->ip_list, list) {
 		netxen_config_ipaddr(adapter, pos->ip_addr, ip_event);
 	}
 }
 
+static inline bool
+netxen_config_checkdev(struct net_device *dev)
+{
+	struct netxen_adapter *adapter;
+
+	if (!is_netxen_netdev(dev))
+		return false;
+	adapter = netdev_priv(dev);
+	if (!adapter)
+		return false;
+	if (!netxen_destip_supported(adapter))
+		return false;
+	if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC)
+		return false;
+
+	return true;
+}
+
+/**
+ * netxen_config_master - configure addresses based on master
+ * @dev: netxen device
+ * @event: netdev event
+ */
+static void netxen_config_master(struct net_device *dev, unsigned long event)
+{
+	struct net_device *master, *slave;
+	struct netxen_adapter *adapter = netdev_priv(dev);
+
+	rcu_read_lock();
+	master = netdev_master_upper_dev_get_rcu(dev);
+	/*
+	 * This is the case where the netxen nic is being
+	 * enslaved and is dev_open()ed in bond_enslave()
+	 * Now we should program the bond's (and its vlans')
+	 * addresses in the netxen NIC.
+	 */
+	if (master && netif_is_bond_master(master) &&
+	    !netif_is_bond_slave(dev)) {
+		netxen_config_indev_addr(adapter, master, event);
+		for_each_netdev_rcu(&init_net, slave)
+			if (slave->priv_flags & IFF_802_1Q_VLAN &&
+			    vlan_dev_real_dev(slave) == master)
+				netxen_config_indev_addr(adapter, slave, event);
+	}
+	rcu_read_unlock();
+	/*
+	 * This is the case where the netxen nic is being
+	 * released and is dev_close()ed in bond_release()
+	 * just before IFF_BONDING is stripped.
+	 */
+	if (!master && dev->priv_flags & IFF_BONDING)
+		netxen_free_ip_list(adapter, true);
+}
+
 static int netxen_netdev_event(struct notifier_block *this,
 				 unsigned long event, void *ptr)
 {
 	struct netxen_adapter *adapter;
 	struct net_device *dev = (struct net_device *)ptr;
 	struct net_device *orig_dev = dev;
+	struct net_device *slave;
 
 recheck:
 	if (dev == NULL)
@@ -3257,19 +3323,28 @@ recheck:
 		dev = vlan_dev_real_dev(dev);
 		goto recheck;
 	}
-
-	if (!is_netxen_netdev(dev))
-		goto done;
-
-	adapter = netdev_priv(dev);
-
-	if (!adapter)
-		goto done;
-
-	if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC)
-		goto done;
-
-	netxen_config_indev_addr(adapter, orig_dev, event);
+	if (event == NETDEV_UP || event == NETDEV_DOWN) {
+		/* If this is a bonding device, look for netxen-based slaves*/
+		if (netif_is_bond_master(dev)) {
+			rcu_read_lock();
+			for_each_netdev_in_bond_rcu(dev, slave) {
+				if (!netxen_config_checkdev(slave))
+					continue;
+				adapter = netdev_priv(slave);
+				netxen_config_indev_addr(adapter,
+							 orig_dev, event);
+			}
+			rcu_read_unlock();
+		} else {
+			if (!netxen_config_checkdev(dev))
+				goto done;
+			adapter = netdev_priv(dev);
+			/* Act only if the actual netxen is the target */
+			if (orig_dev == dev)
+				netxen_config_master(dev, event);
+			netxen_config_indev_addr(adapter, orig_dev, event);
+		}
+	}
 done:
 	return NOTIFY_DONE;
 }
@@ -3279,12 +3354,12 @@ netxen_inetaddr_event(struct notifier_block *this,
 		unsigned long event, void *ptr)
 {
 	struct netxen_adapter *adapter;
-	struct net_device *dev;
-
+	struct net_device *dev, *slave;
 	struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
+	unsigned long ip_event;
 
 	dev = ifa->ifa_dev ? ifa->ifa_dev->dev : NULL;
-
+	ip_event = (event == NETDEV_UP) ? NX_IP_UP : NX_IP_DOWN;
 recheck:
 	if (dev == NULL)
 		goto done;
@@ -3293,31 +3368,24 @@ recheck:
 		dev = vlan_dev_real_dev(dev);
 		goto recheck;
 	}
-
-	if (!is_netxen_netdev(dev))
-		goto done;
-
-	adapter = netdev_priv(dev);
-
-	if (!adapter || !netxen_destip_supported(adapter))
-		goto done;
-
-	if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC)
-		goto done;
-
-	switch (event) {
-	case NETDEV_UP:
-		netxen_config_ipaddr(adapter, ifa->ifa_address, NX_IP_UP);
-		netxen_list_config_vlan_ip(adapter, ifa, NX_IP_UP);
-		break;
-	case NETDEV_DOWN:
-		netxen_config_ipaddr(adapter, ifa->ifa_address, NX_IP_DOWN);
-		netxen_list_config_vlan_ip(adapter, ifa, NX_IP_DOWN);
-		break;
-	default:
-		break;
+	if (event == NETDEV_UP || event == NETDEV_DOWN) {
+		/* If this is a bonding device, look for netxen-based slaves*/
+		if (netif_is_bond_master(dev)) {
+			rcu_read_lock();
+			for_each_netdev_in_bond_rcu(dev, slave) {
+				if (!netxen_config_checkdev(slave))
+					continue;
+				adapter = netdev_priv(slave);
+				netxen_list_config_ip(adapter, ifa, ip_event);
+			}
+			rcu_read_unlock();
+		} else {
+			if (!netxen_config_checkdev(dev))
+				goto done;
+			adapter = netdev_priv(dev);
+			netxen_list_config_ip(adapter, ifa, ip_event);
+		}
 	}
-
 done:
 	return NOTIFY_DONE;
 }
@@ -3334,7 +3402,7 @@ static void
 netxen_restore_indev_addr(struct net_device *dev, unsigned long event)
 { }
 static void
-netxen_free_vlan_ip_list(struct netxen_adapter *adapter)
+netxen_free_ip_list(struct netxen_adapter *adapter, bool master)
 { }
 #endif
 
diff --git a/drivers/net/ethernet/qlogic/qla3xxx.c b/drivers/net/ethernet/qlogic/qla3xxx.c
index 8fd38cb6..91a8fcd 100644
--- a/drivers/net/ethernet/qlogic/qla3xxx.c
+++ b/drivers/net/ethernet/qlogic/qla3xxx.c
@@ -312,7 +312,6 @@ static void ql_release_to_lrg_buf_free_list(struct ql3_adapter *qdev,
 		lrg_buf_cb->skb = netdev_alloc_skb(qdev->ndev,
 						   qdev->lrg_buffer_len);
 		if (unlikely(!lrg_buf_cb->skb)) {
-			netdev_err(qdev->ndev, "failed netdev_alloc_skb()\n");
 			qdev->lrg_buf_skb_check++;
 		} else {
 			/*
diff --git a/drivers/net/ethernet/qlogic/qlcnic/Makefile b/drivers/net/ethernet/qlogic/qlcnic/Makefile
index 7722a20..4b1fb3f 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/Makefile
+++ b/drivers/net/ethernet/qlogic/qlcnic/Makefile
@@ -8,4 +8,6 @@ qlcnic-y := qlcnic_hw.o qlcnic_main.o qlcnic_init.o \
 	qlcnic_ethtool.o qlcnic_ctx.o qlcnic_io.o \
 	qlcnic_sysfs.o qlcnic_minidump.o qlcnic_83xx_hw.o \
 	qlcnic_83xx_init.o qlcnic_83xx_vnic.o \
-	qlcnic_minidump.o
+	qlcnic_minidump.o qlcnic_sriov_common.o
+
+qlcnic-$(CONFIG_QLCNIC_SRIOV) += qlcnic_sriov_pf.o
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
index ba3c72f..ef55718 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
@@ -37,9 +37,9 @@
 #include "qlcnic_83xx_hw.h"
 
 #define _QLCNIC_LINUX_MAJOR 5
-#define _QLCNIC_LINUX_MINOR 1
-#define _QLCNIC_LINUX_SUBVERSION 35
-#define QLCNIC_LINUX_VERSIONID  "5.1.35"
+#define _QLCNIC_LINUX_MINOR 2
+#define _QLCNIC_LINUX_SUBVERSION 40
+#define QLCNIC_LINUX_VERSIONID  "5.2.40"
 #define QLCNIC_DRV_IDC_VER  0x01
 #define QLCNIC_DRIVER_VERSION  ((_QLCNIC_LINUX_MAJOR << 16) |\
 		 (_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION))
@@ -449,6 +449,7 @@ struct qlcnic_hardware_context {
 	struct qlc_83xx_idc idc;
 	struct qlc_83xx_fw_info fw_info;
 	struct qlcnic_intrpt_config *intr_tbl;
+	struct qlcnic_sriov *sriov;
 	u32 *reg_tbl;
 	u32 *ext_reg_tbl;
 	u32 mbox_aen[QLC_83XX_MBX_AEN_CNT];
@@ -896,6 +897,7 @@ struct qlcnic_ipaddr {
 #define QLCNIC_FW_RESET_OWNER		0x2000
 #define QLCNIC_FW_HANG			0x4000
 #define QLCNIC_FW_LRO_MSS_CAP		0x8000
+#define QLCNIC_TX_INTR_SHARED		0x10000
 #define QLCNIC_IS_MSI_FAMILY(adapter) \
 	((adapter)->flags & (QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED))
 
@@ -914,7 +916,9 @@ struct qlcnic_ipaddr {
 #define __QLCNIC_AER			5
 #define __QLCNIC_DIAG_RES_ALLOC		6
 #define __QLCNIC_LED_ENABLE		7
-#define __QLCNIC_ELB_INPROGRESS	8
+#define __QLCNIC_ELB_INPROGRESS		8
+#define __QLCNIC_SRIOV_ENABLE		10
+#define __QLCNIC_SRIOV_CAPABLE		11
 
 #define QLCNIC_INTERRUPT_TEST		1
 #define QLCNIC_LOOPBACK_TEST		2
@@ -1009,6 +1013,7 @@ struct qlcnic_adapter {
 
 	struct qlcnic_filter_hash fhash;
 	struct qlcnic_filter_hash rx_fhash;
+	struct list_head vf_mc_list;
 
 	spinlock_t tx_clean_lock;
 	spinlock_t mac_learn_lock;
@@ -1051,7 +1056,11 @@ struct qlcnic_info_le {
 	u8      total_pf;
 	u8      total_rss_engines;
 	__le16  max_vports;
-	u8      reserved2[64];
+	__le16	linkstate_reg_offset;
+	__le16	bit_offsets;
+	__le16  max_local_ipv6_addrs;
+	__le16  max_remote_ipv6_addrs;
+	u8	reserved2[56];
 } __packed;
 
 struct qlcnic_info {
@@ -1083,6 +1092,10 @@ struct qlcnic_info {
 	u8      total_pf;
 	u8      total_rss_engines;
 	u16	max_vports;
+	u16	linkstate_reg_offset;
+	u16	bit_offsets;
+	u16	max_local_ipv6_addrs;
+	u16	max_remote_ipv6_addrs;
 };
 
 struct qlcnic_pci_info_le {
@@ -1348,6 +1361,7 @@ struct _cdrp_cmd {
 struct qlcnic_cmd_args {
 	struct _cdrp_cmd req;
 	struct _cdrp_cmd rsp;
+	int op_type;
 };
 
 int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter);
@@ -1430,6 +1444,7 @@ void qlcnic_post_rx_buffers(struct qlcnic_adapter *adapter,
 		struct qlcnic_host_rds_ring *rds_ring, u8 ring_id);
 int qlcnic_process_rcv_ring(struct qlcnic_host_sds_ring *sds_ring, int max);
 void qlcnic_set_multi(struct net_device *netdev);
+void __qlcnic_set_multi(struct net_device *netdev);
 int qlcnic_nic_add_mac(struct qlcnic_adapter *, const u8 *);
 int qlcnic_nic_del_mac(struct qlcnic_adapter *, const u8 *);
 void qlcnic_free_mac_list(struct qlcnic_adapter *adapter);
@@ -1511,6 +1526,12 @@ int qlcnic_reset_npar_config(struct qlcnic_adapter *);
 int qlcnic_set_eswitch_port_config(struct qlcnic_adapter *);
 void qlcnic_add_lb_filter(struct qlcnic_adapter *, struct sk_buff *, int,
 			  __le16);
+int qlcnic_83xx_configure_opmode(struct qlcnic_adapter *adapter);
+int qlcnic_read_mac_addr(struct qlcnic_adapter *);
+int qlcnic_setup_netdev(struct qlcnic_adapter *, struct net_device *, int);
+void qlcnic_sriov_vf_schedule_multi(struct net_device *);
+void qlcnic_vf_add_mc_list(struct net_device *);
+
 /*
  * QLOGIC Board information
  */
@@ -1567,6 +1588,9 @@ struct qlcnic_hardware_ops {
 	int (*create_rx_ctx) (struct qlcnic_adapter *);
 	int (*create_tx_ctx) (struct qlcnic_adapter *,
 	struct qlcnic_host_tx_ring *, int);
+	void (*del_rx_ctx) (struct qlcnic_adapter *);
+	void (*del_tx_ctx) (struct qlcnic_adapter *,
+			    struct qlcnic_host_tx_ring *);
 	int (*setup_link_event) (struct qlcnic_adapter *, int);
 	int (*get_nic_info) (struct qlcnic_adapter *, struct qlcnic_info *, u8);
 	int (*get_pci_info) (struct qlcnic_adapter *, struct qlcnic_pci_info *);
@@ -1635,7 +1659,10 @@ static inline int qlcnic_alloc_mbx_args(struct qlcnic_cmd_args *mbx,
 static inline int qlcnic_issue_cmd(struct qlcnic_adapter *adapter,
 				   struct qlcnic_cmd_args *cmd)
 {
-	return adapter->ahw->hw_ops->mbx_cmd(adapter, cmd);
+	if (adapter->ahw->hw_ops->mbx_cmd)
+		return adapter->ahw->hw_ops->mbx_cmd(adapter, cmd);
+
+	return -EIO;
 }
 
 static inline void qlcnic_get_func_no(struct qlcnic_adapter *adapter)
@@ -1655,12 +1682,14 @@ static inline void qlcnic_api_unlock(struct qlcnic_adapter *adapter)
 
 static inline void qlcnic_add_sysfs(struct qlcnic_adapter *adapter)
 {
-	adapter->ahw->hw_ops->add_sysfs(adapter);
+	if (adapter->ahw->hw_ops->add_sysfs)
+		adapter->ahw->hw_ops->add_sysfs(adapter);
 }
 
 static inline void qlcnic_remove_sysfs(struct qlcnic_adapter *adapter)
 {
-	adapter->ahw->hw_ops->remove_sysfs(adapter);
+	if (adapter->ahw->hw_ops->remove_sysfs)
+		adapter->ahw->hw_ops->remove_sysfs(adapter);
 }
 
 static inline void
@@ -1681,6 +1710,17 @@ static inline int qlcnic_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter,
 	return adapter->ahw->hw_ops->create_tx_ctx(adapter, ptr, ring);
 }
 
+static inline void qlcnic_fw_cmd_del_rx_ctx(struct qlcnic_adapter *adapter)
+{
+	return adapter->ahw->hw_ops->del_rx_ctx(adapter);
+}
+
+static inline void qlcnic_fw_cmd_del_tx_ctx(struct qlcnic_adapter *adapter,
+					    struct qlcnic_host_tx_ring *ptr)
+{
+	return adapter->ahw->hw_ops->del_tx_ctx(adapter, ptr);
+}
+
 static inline int qlcnic_linkevent_request(struct qlcnic_adapter *adapter,
 					   int enable)
 {
@@ -1778,12 +1818,14 @@ static inline int qlcnic_get_board_info(struct qlcnic_adapter *adapter)
 static inline void qlcnic_dev_request_reset(struct qlcnic_adapter *adapter,
 					    u32 key)
 {
-	adapter->nic_ops->request_reset(adapter, key);
+	if (adapter->nic_ops->request_reset)
+		adapter->nic_ops->request_reset(adapter, key);
 }
 
 static inline void qlcnic_cancel_idc_work(struct qlcnic_adapter *adapter)
 {
-	adapter->nic_ops->cancel_idc_work(adapter);
+	if (adapter->nic_ops->cancel_idc_work)
+		adapter->nic_ops->cancel_idc_work(adapter);
 }
 
 static inline irqreturn_t
@@ -1830,7 +1872,9 @@ extern const struct ethtool_ops qlcnic_ethtool_failed_ops;
 	} while (0)
 
 #define PCI_DEVICE_ID_QLOGIC_QLE834X    0x8030
+#define PCI_DEVICE_ID_QLOGIC_VF_QLE834X	0x8430
 #define PCI_DEVICE_ID_QLOGIC_QLE824X	0x8020
+
 static inline bool qlcnic_82xx_check(struct qlcnic_adapter *adapter)
 {
 	unsigned short device = adapter->pdev->device;
@@ -1840,8 +1884,23 @@ static inline bool qlcnic_82xx_check(struct qlcnic_adapter *adapter)
 static inline bool qlcnic_83xx_check(struct qlcnic_adapter *adapter)
 {
 	unsigned short device = adapter->pdev->device;
-	return (device == PCI_DEVICE_ID_QLOGIC_QLE834X) ? true : false;
+	bool status;
+
+	status = ((device == PCI_DEVICE_ID_QLOGIC_QLE834X) ||
+		  (device == PCI_DEVICE_ID_QLOGIC_VF_QLE834X)) ? true : false;
+
+	return status;
+}
+
+static inline bool qlcnic_sriov_pf_check(struct qlcnic_adapter *adapter)
+{
+	return (adapter->ahw->op_mode == QLCNIC_SRIOV_PF_FUNC) ? true : false;
 }
 
+static inline bool qlcnic_sriov_vf_check(struct qlcnic_adapter *adapter)
+{
+	unsigned short device = adapter->pdev->device;
 
+	return (device == PCI_DEVICE_ID_QLOGIC_VF_QLE834X) ? true : false;
+}
 #endif				/* __QLCNIC_H_ */
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
index cd5ae88..374fa8a 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
@@ -6,6 +6,7 @@
  */
 
 #include "qlcnic.h"
+#include "qlcnic_sriov.h"
 #include <linux/if_vlan.h>
 #include <linux/ipv6.h>
 #include <linux/ethtool.h>
@@ -13,100 +14,7 @@
 
 #define QLCNIC_MAX_TX_QUEUES		1
 #define RSS_HASHTYPE_IP_TCP		0x3
-
-/* status descriptor mailbox data
- * @phy_addr: physical address of buffer
- * @sds_ring_size: buffer size
- * @intrpt_id: interrupt id
- * @intrpt_val: source of interrupt
- */
-struct qlcnic_sds_mbx {
-	u64	phy_addr;
-	u8	rsvd1[16];
-	u16	sds_ring_size;
-	u16	rsvd2[3];
-	u16	intrpt_id;
-	u8	intrpt_val;
-	u8	rsvd3[5];
-} __packed;
-
-/* receive descriptor buffer data
- * phy_addr_reg: physical address of regular buffer
- * phy_addr_jmb: physical address of jumbo buffer
- * reg_ring_sz: size of regular buffer
- * reg_ring_len: no. of entries in regular buffer
- * jmb_ring_len: no. of entries in jumbo buffer
- * jmb_ring_sz: size of jumbo buffer
- */
-struct qlcnic_rds_mbx {
-	u64	phy_addr_reg;
-	u64	phy_addr_jmb;
-	u16	reg_ring_sz;
-	u16	reg_ring_len;
-	u16	jmb_ring_sz;
-	u16	jmb_ring_len;
-} __packed;
-
-/* host producers for regular and jumbo rings */
-struct __host_producer_mbx {
-	u32	reg_buf;
-	u32	jmb_buf;
-} __packed;
-
-/* Receive context mailbox data outbox registers
- * @state: state of the context
- * @vport_id: virtual port id
- * @context_id: receive context id
- * @num_pci_func: number of pci functions of the port
- * @phy_port: physical port id
- */
-struct qlcnic_rcv_mbx_out {
-	u8	rcv_num;
-	u8	sts_num;
-	u16	ctx_id;
-	u8	state;
-	u8	num_pci_func;
-	u8	phy_port;
-	u8	vport_id;
-	u32	host_csmr[QLCNIC_MAX_RING_SETS];
-	struct __host_producer_mbx host_prod[QLCNIC_MAX_RING_SETS];
-} __packed;
-
-struct qlcnic_add_rings_mbx_out {
-	u8      rcv_num;
-	u8      sts_num;
-	u16  ctx_id;
-	u32  host_csmr[QLCNIC_MAX_RING_SETS];
-	struct __host_producer_mbx host_prod[QLCNIC_MAX_RING_SETS];
-} __packed;
-
-/* Transmit context mailbox inbox registers
- * @phys_addr: DMA address of the transmit buffer
- * @cnsmr_index: host consumer index
- * @size: legth of transmit buffer ring
- * @intr_id: interrput id
- * @src: src of interrupt
- */
-struct qlcnic_tx_mbx {
-	u64	phys_addr;
-	u64	cnsmr_index;
-	u16	size;
-	u16	intr_id;
-	u8	src;
-	u8	rsvd[3];
-} __packed;
-
-/* Transmit context mailbox outbox registers
- * @host_prod: host producer index
- * @ctx_id: transmit context id
- * @state: state of the transmit context
- */
-struct qlcnic_tx_mbx_out {
-	u32	host_prod;
-	u16	ctx_id;
-	u8	state;
-	u8	rsvd;
-} __packed;
+#define QLC_83XX_FW_MBX_CMD		0
 
 static const struct qlcnic_mailbox_metadata qlcnic_83xx_mbx_tbl[] = {
 	{QLCNIC_CMD_CONFIGURE_IP_ADDR, 6, 1},
@@ -156,9 +64,11 @@ static const struct qlcnic_mailbox_metadata qlcnic_83xx_mbx_tbl[] = {
 	{QLCNIC_CMD_SET_LED_CONFIG, 5, 1},
 	{QLCNIC_CMD_GET_LED_CONFIG, 1, 5},
 	{QLCNIC_CMD_ADD_RCV_RINGS, 130, 26},
+	{QLCNIC_CMD_CONFIG_VPORT, 4, 4},
+	{QLCNIC_CMD_BC_EVENT_SETUP, 2, 1},
 };
 
-static const u32 qlcnic_83xx_ext_reg_tbl[] = {
+const u32 qlcnic_83xx_ext_reg_tbl[] = {
 	0x38CC,		/* Global Reset */
 	0x38F0,		/* Wildcard */
 	0x38FC,		/* Informant */
@@ -204,7 +114,7 @@ static const u32 qlcnic_83xx_ext_reg_tbl[] = {
 	0x34A4,		/* QLC_83XX_ASIC_TEMP */
 };
 
-static const u32 qlcnic_83xx_reg_tbl[] = {
+const u32 qlcnic_83xx_reg_tbl[] = {
 	0x34A8,		/* PEG_HALT_STAT1 */
 	0x34AC,		/* PEG_HALT_STAT2 */
 	0x34B0,		/* FW_HEARTBEAT */
@@ -247,6 +157,8 @@ static struct qlcnic_hardware_ops qlcnic_83xx_hw_ops = {
 	.process_lb_rcv_ring_diag	= qlcnic_83xx_process_rcv_ring_diag,
 	.create_rx_ctx			= qlcnic_83xx_create_rx_ctx,
 	.create_tx_ctx			= qlcnic_83xx_create_tx_ctx,
+	.del_rx_ctx			= qlcnic_83xx_del_rx_ctx,
+	.del_tx_ctx			= qlcnic_83xx_del_tx_ctx,
 	.setup_link_event		= qlcnic_83xx_setup_link_event,
 	.get_nic_info			= qlcnic_83xx_get_nic_info,
 	.get_pci_info			= qlcnic_83xx_get_pci_info,
@@ -355,14 +267,20 @@ int qlcnic_83xx_setup_intr(struct qlcnic_adapter *adapter, u8 num_intr)
 					      num_intr));
 	/* account for AEN interrupt MSI-X based interrupts */
 	num_msix += 1;
-	num_msix += adapter->max_drv_tx_rings;
+
+	if (!(adapter->flags & QLCNIC_TX_INTR_SHARED))
+		num_msix += adapter->max_drv_tx_rings;
+
 	err = qlcnic_enable_msix(adapter, num_msix);
 	if (err == -ENOMEM)
 		return err;
 	if (adapter->flags & QLCNIC_MSIX_ENABLED)
 		num_msix = adapter->ahw->num_msix;
-	else
+	else {
+		if (qlcnic_sriov_vf_check(adapter))
+			return -EINVAL;
 		num_msix = 1;
+	}
 	/* setup interrupt mapping table for fw */
 	ahw->intr_tbl = vzalloc(num_msix *
 				sizeof(struct qlcnic_intrpt_config));
@@ -595,7 +513,7 @@ int qlcnic_83xx_setup_mbx_intr(struct qlcnic_adapter *adapter)
 void qlcnic_83xx_get_func_no(struct qlcnic_adapter *adapter)
 {
 	u32 val = QLCRDX(adapter->ahw, QLCNIC_INFORMANT);
-	adapter->ahw->pci_func = val & 0xf;
+	adapter->ahw->pci_func = (val >> 24) & 0xff;
 }
 
 int qlcnic_83xx_cam_lock(struct qlcnic_adapter *adapter)
@@ -707,6 +625,11 @@ void qlcnic_83xx_check_vf(struct qlcnic_adapter *adapter,
 	ahw->fw_hal_version = 2;
 	qlcnic_get_func_no(adapter);
 
+	if (qlcnic_sriov_vf_check(adapter)) {
+		qlcnic_sriov_vf_set_ops(adapter);
+		return;
+	}
+
 	/* Determine function privilege level */
 	op_mode = QLCRDX(adapter->ahw, QLC_83XX_DRV_OP_MODE);
 	if (op_mode == QLC_83XX_DEFAULT_OPMODE)
@@ -722,6 +645,9 @@ void qlcnic_83xx_check_vf(struct qlcnic_adapter *adapter,
 			 ahw->fw_hal_version);
 		adapter->nic_ops = &qlcnic_vf_ops;
 	} else {
+		if (pci_find_ext_capability(adapter->pdev,
+					    PCI_EXT_CAP_ID_SRIOV))
+			set_bit(__QLCNIC_SRIOV_CAPABLE, &adapter->state);
 		adapter->nic_ops = &qlcnic_83xx_ops;
 	}
 }
@@ -755,7 +681,7 @@ static void qlcnic_dump_mbx(struct qlcnic_adapter *adapter,
 }
 
 /* Mailbox response for mac rcode */
-static u32 qlcnic_83xx_mac_rcode(struct qlcnic_adapter *adapter)
+u32 qlcnic_83xx_mac_rcode(struct qlcnic_adapter *adapter)
 {
 	u32 fw_data;
 	u8 mac_cmd_rcode;
@@ -769,7 +695,7 @@ static u32 qlcnic_83xx_mac_rcode(struct qlcnic_adapter *adapter)
 	return 1;
 }
 
-static u32 qlcnic_83xx_mbx_poll(struct qlcnic_adapter *adapter)
+u32 qlcnic_83xx_mbx_poll(struct qlcnic_adapter *adapter)
 {
 	u32 data;
 	unsigned long wait_time = 0;
@@ -884,6 +810,7 @@ int qlcnic_83xx_alloc_mbx_args(struct qlcnic_cmd_args *mbx,
 	size = ARRAY_SIZE(qlcnic_83xx_mbx_tbl);
 	for (i = 0; i < size; i++) {
 		if (type == mbx_tbl[i].cmd) {
+			mbx->op_type = QLC_83XX_FW_MBX_CMD;
 			mbx->req.num = mbx_tbl[i].in_args;
 			mbx->rsp.num = mbx_tbl[i].out_args;
 			mbx->req.arg = kcalloc(mbx->req.num, sizeof(u32),
@@ -901,10 +828,10 @@ int qlcnic_83xx_alloc_mbx_args(struct qlcnic_cmd_args *mbx,
 			memset(mbx->rsp.arg, 0, sizeof(u32) * mbx->rsp.num);
 			temp = adapter->ahw->fw_hal_version << 29;
 			mbx->req.arg[0] = (type | (mbx->req.num << 16) | temp);
-			break;
+			return 0;
 		}
 	}
-	return 0;
+	return -EINVAL;
 }
 
 void qlcnic_83xx_idc_aen_work(struct work_struct *work)
@@ -960,6 +887,9 @@ void qlcnic_83xx_process_aen(struct qlcnic_adapter *adapter)
 		break;
 	case QLCNIC_MBX_TIME_EXTEND_EVENT:
 		break;
+	case QLCNIC_MBX_BC_EVENT:
+		qlcnic_sriov_handle_bc_event(adapter, event[1]);
+		break;
 	case QLCNIC_MBX_SFP_INSERT_EVENT:
 		dev_info(&adapter->pdev->dev, "SFP+ Insert AEN:0x%x.\n",
 			 QLCNIC_MBX_RSP(event[0]));
@@ -1004,7 +934,8 @@ static int qlcnic_83xx_add_rings(struct qlcnic_adapter *adapter)
 		sds = &recv_ctx->sds_rings[i];
 		sds->consumer = 0;
 		memset(sds->desc_head, 0, STATUS_DESC_RINGSIZE(sds));
-		sds_mbx.phy_addr = sds->phys_addr;
+		sds_mbx.phy_addr_low = LSD(sds->phys_addr);
+		sds_mbx.phy_addr_high = MSD(sds->phys_addr);
 		sds_mbx.sds_ring_size = sds->num_desc;
 
 		if (adapter->flags & QLCNIC_MSIX_ENABLED)
@@ -1050,6 +981,32 @@ out:
 	return err;
 }
 
+void qlcnic_83xx_del_rx_ctx(struct qlcnic_adapter *adapter)
+{
+	int err;
+	u32 temp = 0;
+	struct qlcnic_cmd_args cmd;
+	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
+
+	if (qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_DESTROY_RX_CTX))
+		return;
+
+	if (qlcnic_sriov_pf_check(adapter) || qlcnic_sriov_vf_check(adapter))
+		cmd.req.arg[0] |= (0x3 << 29);
+
+	if (qlcnic_sriov_pf_check(adapter))
+		qlcnic_pf_set_interface_id_del_rx_ctx(adapter, &temp);
+
+	cmd.req.arg[1] = recv_ctx->context_id | temp;
+	err = qlcnic_issue_cmd(adapter, &cmd);
+	if (err)
+		dev_err(&adapter->pdev->dev,
+			"Failed to destroy rx ctx in firmware\n");
+
+	recv_ctx->state = QLCNIC_HOST_CTX_STATE_FREED;
+	qlcnic_free_mbx_args(&cmd);
+}
+
 int qlcnic_83xx_create_rx_ctx(struct qlcnic_adapter *adapter)
 {
 	int i, err, index, sds_mbx_size, rds_mbx_size;
@@ -1080,9 +1037,17 @@ int qlcnic_83xx_create_rx_ctx(struct qlcnic_adapter *adapter)
 	/* set mailbox hdr and capabilities */
 	qlcnic_alloc_mbx_args(&cmd, adapter,
 			      QLCNIC_CMD_CREATE_RX_CTX);
+
+	if (qlcnic_sriov_pf_check(adapter) || qlcnic_sriov_vf_check(adapter))
+		cmd.req.arg[0] |= (0x3 << 29);
+
 	cmd.req.arg[1] = cap;
 	cmd.req.arg[5] = 1 | (num_rds << 5) | (num_sds << 8) |
 			 (QLC_83XX_HOST_RDS_MODE_UNIQUE << 16);
+
+	if (qlcnic_sriov_pf_check(adapter))
+		qlcnic_pf_set_interface_id_create_rx_ctx(adapter,
+							 &cmd.req.arg[6]);
 	/* set up status rings, mbx 8-57/87 */
 	index = QLC_83XX_HOST_SDS_MBX_IDX;
 	for (i = 0; i < num_sds; i++) {
@@ -1090,7 +1055,8 @@ int qlcnic_83xx_create_rx_ctx(struct qlcnic_adapter *adapter)
 		sds = &recv_ctx->sds_rings[i];
 		sds->consumer = 0;
 		memset(sds->desc_head, 0, STATUS_DESC_RINGSIZE(sds));
-		sds_mbx.phy_addr = sds->phys_addr;
+		sds_mbx.phy_addr_low = LSD(sds->phys_addr);
+		sds_mbx.phy_addr_high = MSD(sds->phys_addr);
 		sds_mbx.sds_ring_size = sds->num_desc;
 		if (adapter->flags & QLCNIC_MSIX_ENABLED)
 			intrpt_id = ahw->intr_tbl[i].id;
@@ -1110,13 +1076,15 @@ int qlcnic_83xx_create_rx_ctx(struct qlcnic_adapter *adapter)
 	rds = &recv_ctx->rds_rings[0];
 	rds->producer = 0;
 	memset(&rds_mbx, 0, rds_mbx_size);
-	rds_mbx.phy_addr_reg = rds->phys_addr;
+	rds_mbx.phy_addr_reg_low = LSD(rds->phys_addr);
+	rds_mbx.phy_addr_reg_high = MSD(rds->phys_addr);
 	rds_mbx.reg_ring_sz = rds->dma_size;
 	rds_mbx.reg_ring_len = rds->num_desc;
 	/* Jumbo ring */
 	rds = &recv_ctx->rds_rings[1];
 	rds->producer = 0;
-	rds_mbx.phy_addr_jmb = rds->phys_addr;
+	rds_mbx.phy_addr_jmb_low = LSD(rds->phys_addr);
+	rds_mbx.phy_addr_jmb_high = MSD(rds->phys_addr);
 	rds_mbx.jmb_ring_sz = rds->dma_size;
 	rds_mbx.jmb_ring_len = rds->num_desc;
 	buf = &cmd.req.arg[index];
@@ -1163,16 +1131,39 @@ out:
 	return err;
 }
 
+void qlcnic_83xx_del_tx_ctx(struct qlcnic_adapter *adapter,
+			    struct qlcnic_host_tx_ring *tx_ring)
+{
+	struct qlcnic_cmd_args cmd;
+	u32 temp = 0;
+
+	if (qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_DESTROY_TX_CTX))
+		return;
+
+	if (qlcnic_sriov_pf_check(adapter) || qlcnic_sriov_vf_check(adapter))
+		cmd.req.arg[0] |= (0x3 << 29);
+
+	if (qlcnic_sriov_pf_check(adapter))
+		qlcnic_pf_set_interface_id_del_tx_ctx(adapter, &temp);
+
+	cmd.req.arg[1] = tx_ring->ctx_id | temp;
+	if (qlcnic_issue_cmd(adapter, &cmd))
+		dev_err(&adapter->pdev->dev,
+			"Failed to destroy tx ctx in firmware\n");
+	qlcnic_free_mbx_args(&cmd);
+}
+
 int qlcnic_83xx_create_tx_ctx(struct qlcnic_adapter *adapter,
 			      struct qlcnic_host_tx_ring *tx, int ring)
 {
 	int err;
 	u16 msix_id;
-	u32 *buf, intr_mask;
+	u32 *buf, intr_mask, temp = 0;
 	struct qlcnic_cmd_args cmd;
 	struct qlcnic_tx_mbx mbx;
 	struct qlcnic_tx_mbx_out *mbx_out;
 	struct qlcnic_hardware_context *ahw = adapter->ahw;
+	u32 msix_vector;
 
 	/* Reset host resources */
 	tx->producer = 0;
@@ -1182,13 +1173,21 @@ int qlcnic_83xx_create_tx_ctx(struct qlcnic_adapter *adapter,
 	memset(&mbx, 0, sizeof(struct qlcnic_tx_mbx));
 
 	/* setup mailbox inbox registerss */
-	mbx.phys_addr = tx->phys_addr;
-	mbx.cnsmr_index = tx->hw_cons_phys_addr;
+	mbx.phys_addr_low = LSD(tx->phys_addr);
+	mbx.phys_addr_high = MSD(tx->phys_addr);
+	mbx.cnsmr_index_low = LSD(tx->hw_cons_phys_addr);
+	mbx.cnsmr_index_high = MSD(tx->hw_cons_phys_addr);
 	mbx.size = tx->num_desc;
-	if (adapter->flags & QLCNIC_MSIX_ENABLED)
-		msix_id = ahw->intr_tbl[adapter->max_sds_rings + ring].id;
-	else
+	if (adapter->flags & QLCNIC_MSIX_ENABLED) {
+		if (!(adapter->flags & QLCNIC_TX_INTR_SHARED))
+			msix_vector = adapter->max_sds_rings + ring;
+		else
+			msix_vector = adapter->max_sds_rings - 1;
+		msix_id = ahw->intr_tbl[msix_vector].id;
+	} else {
 		msix_id = QLCRDX(ahw, QLCNIC_DEF_INT_ID);
+	}
+
 	if (adapter->ahw->diag_test != QLCNIC_LOOPBACK_TEST)
 		mbx.intr_id = msix_id;
 	else
@@ -1196,8 +1195,15 @@ int qlcnic_83xx_create_tx_ctx(struct qlcnic_adapter *adapter,
 	mbx.src = 0;
 
 	qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CREATE_TX_CTX);
+
+	if (qlcnic_sriov_pf_check(adapter) || qlcnic_sriov_vf_check(adapter))
+		cmd.req.arg[0] |= (0x3 << 29);
+
+	if (qlcnic_sriov_pf_check(adapter))
+		qlcnic_pf_set_interface_id_create_tx_ctx(adapter, &temp);
+
 	cmd.req.arg[1] = QLCNIC_CAP0_LEGACY_CONTEXT;
-	cmd.req.arg[5] = QLCNIC_MAX_TX_QUEUES;
+	cmd.req.arg[5] = QLCNIC_MAX_TX_QUEUES | temp;
 	buf = &cmd.req.arg[6];
 	memcpy(buf, &mbx, sizeof(struct qlcnic_tx_mbx));
 	/* send the mailbox command*/
@@ -1210,7 +1216,8 @@ int qlcnic_83xx_create_tx_ctx(struct qlcnic_adapter *adapter,
 	mbx_out = (struct qlcnic_tx_mbx_out *)&cmd.rsp.arg[2];
 	tx->crb_cmd_producer = ahw->pci_base0 + mbx_out->host_prod;
 	tx->ctx_id = mbx_out->ctx_id;
-	if (adapter->flags & QLCNIC_MSIX_ENABLED) {
+	if ((adapter->flags & QLCNIC_MSIX_ENABLED) &&
+	    !(adapter->flags & QLCNIC_TX_INTR_SHARED)) {
 		intr_mask = ahw->intr_tbl[adapter->max_sds_rings + ring].src;
 		tx->crb_intr_mask = ahw->pci_base0 + intr_mask;
 	}
@@ -1373,12 +1380,60 @@ mbx_err:
 	}
 }
 
+int  qlcnic_83xx_set_led(struct net_device *netdev,
+			 enum ethtool_phys_id_state state)
+{
+	struct qlcnic_adapter *adapter = netdev_priv(netdev);
+	int err = -EIO, active = 1;
+
+	if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC) {
+		netdev_warn(netdev,
+			    "LED test is not supported in non-privileged mode\n");
+		return -EOPNOTSUPP;
+	}
+
+	switch (state) {
+	case ETHTOOL_ID_ACTIVE:
+		if (test_and_set_bit(__QLCNIC_LED_ENABLE, &adapter->state))
+			return -EBUSY;
+
+		if (test_bit(__QLCNIC_RESETTING, &adapter->state))
+			break;
+
+		err = qlcnic_83xx_config_led(adapter, active, 0);
+		if (err)
+			netdev_err(netdev, "Failed to set LED blink state\n");
+		break;
+	case ETHTOOL_ID_INACTIVE:
+		active = 0;
+
+		if (test_bit(__QLCNIC_RESETTING, &adapter->state))
+			break;
+
+		err = qlcnic_83xx_config_led(adapter, active, 0);
+		if (err)
+			netdev_err(netdev, "Failed to reset LED blink state\n");
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	if (!active || err)
+		clear_bit(__QLCNIC_LED_ENABLE, &adapter->state);
+
+	return err;
+}
+
 void qlcnic_83xx_register_nic_idc_func(struct qlcnic_adapter *adapter,
 				       int enable)
 {
 	struct qlcnic_cmd_args cmd;
 	int status;
 
+	if (qlcnic_sriov_vf_check(adapter))
+		return;
+
 	if (enable) {
 		qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_INIT_NIC_FUNC);
 		cmd.req.arg[1] = BIT_0 | BIT_31;
@@ -1441,24 +1496,35 @@ int qlcnic_83xx_setup_link_event(struct qlcnic_adapter *adapter, int enable)
 	return err;
 }
 
+static void qlcnic_83xx_set_interface_id_promisc(struct qlcnic_adapter *adapter,
+						 u32 *interface_id)
+{
+	if (qlcnic_sriov_pf_check(adapter)) {
+		qlcnic_pf_set_interface_id_promisc(adapter, interface_id);
+	} else {
+		if (!qlcnic_sriov_vf_check(adapter))
+			*interface_id = adapter->recv_ctx->context_id << 16;
+	}
+}
+
 int qlcnic_83xx_nic_set_promisc(struct qlcnic_adapter *adapter, u32 mode)
 {
 	int err;
-	u32 temp;
+	u32 temp = 0;
 	struct qlcnic_cmd_args cmd;
 
 	if (adapter->recv_ctx->state == QLCNIC_HOST_CTX_STATE_FREED)
 		return -EIO;
 
 	qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIGURE_MAC_RX_MODE);
-	temp = adapter->recv_ctx->context_id << 16;
+	qlcnic_83xx_set_interface_id_promisc(adapter, &temp);
 	cmd.req.arg[1] = (mode ? 1 : 0) | temp;
 	err = qlcnic_issue_cmd(adapter, &cmd);
 	if (err)
 		dev_info(&adapter->pdev->dev,
 			 "Promiscous mode config failed\n");
-	qlcnic_free_mbx_args(&cmd);
 
+	qlcnic_free_mbx_args(&cmd);
 	return err;
 }
 
@@ -1598,21 +1664,31 @@ int qlcnic_83xx_clear_lb_mode(struct qlcnic_adapter *adapter, u8 mode)
 	return status;
 }
 
+static void qlcnic_83xx_set_interface_id_ipaddr(struct qlcnic_adapter *adapter,
+						u32 *interface_id)
+{
+	if (qlcnic_sriov_pf_check(adapter)) {
+		qlcnic_pf_set_interface_id_ipaddr(adapter, interface_id);
+	} else {
+		if (!qlcnic_sriov_vf_check(adapter))
+			*interface_id = adapter->recv_ctx->context_id << 16;
+	}
+}
+
 void qlcnic_83xx_config_ipaddr(struct qlcnic_adapter *adapter, __be32 ip,
 			       int mode)
 {
 	int err;
-	u32 temp, temp_ip;
+	u32 temp = 0, temp_ip;
 	struct qlcnic_cmd_args cmd;
 
 	qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIGURE_IP_ADDR);
-	if (mode == QLCNIC_IP_UP) {
-		temp = adapter->recv_ctx->context_id << 16;
+	qlcnic_83xx_set_interface_id_ipaddr(adapter, &temp);
+
+	if (mode == QLCNIC_IP_UP)
 		cmd.req.arg[1] = 1 | temp;
-	} else {
-		temp = adapter->recv_ctx->context_id << 16;
+	else
 		cmd.req.arg[1] = 2 | temp;
-	}
 
 	/*
 	 * Adapter needs IP address in network byte order.
@@ -1629,6 +1705,7 @@ void qlcnic_83xx_config_ipaddr(struct qlcnic_adapter *adapter, __be32 ip,
 		dev_err(&adapter->netdev->dev,
 			"could not notify %s IP 0x%x request\n",
 			(mode == QLCNIC_IP_UP) ? "Add" : "Remove", ip);
+
 	qlcnic_free_mbx_args(&cmd);
 }
 
@@ -1695,11 +1772,22 @@ int qlcnic_83xx_config_rss(struct qlcnic_adapter *adapter, int enable)
 
 }
 
+static void qlcnic_83xx_set_interface_id_macaddr(struct qlcnic_adapter *adapter,
+						 u32 *interface_id)
+{
+	if (qlcnic_sriov_pf_check(adapter)) {
+		qlcnic_pf_set_interface_id_macaddr(adapter, interface_id);
+	} else {
+		if (!qlcnic_sriov_vf_check(adapter))
+			*interface_id = adapter->recv_ctx->context_id << 16;
+	}
+}
+
 int qlcnic_83xx_sre_macaddr_change(struct qlcnic_adapter *adapter, u8 *addr,
 				   __le16 vlan_id, u8 op)
 {
 	int err;
-	u32 *buf;
+	u32 *buf, temp = 0;
 	struct qlcnic_cmd_args cmd;
 	struct qlcnic_macvlan_mbx mv;
 
@@ -1709,11 +1797,17 @@ int qlcnic_83xx_sre_macaddr_change(struct qlcnic_adapter *adapter, u8 *addr,
 	err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_MAC_VLAN);
 	if (err)
 		return err;
-	cmd.req.arg[1] = op | (1 << 8) |
-			(adapter->recv_ctx->context_id << 16);
 
+	cmd.req.arg[1] = op | (1 << 8);
+	qlcnic_83xx_set_interface_id_macaddr(adapter, &temp);
+	cmd.req.arg[1] |= temp;
 	mv.vlan = le16_to_cpu(vlan_id);
-	memcpy(&mv.mac, addr, ETH_ALEN);
+	mv.mac_addr0 = addr[0];
+	mv.mac_addr1 = addr[1];
+	mv.mac_addr2 = addr[2];
+	mv.mac_addr3 = addr[3];
+	mv.mac_addr4 = addr[4];
+	mv.mac_addr5 = addr[5];
 	buf = &cmd.req.arg[2];
 	memcpy(buf, &mv, sizeof(struct qlcnic_macvlan_mbx));
 	err = qlcnic_issue_cmd(adapter, &cmd);
@@ -2002,14 +2096,17 @@ int qlcnic_83xx_get_pci_info(struct qlcnic_adapter *adapter,
 int qlcnic_83xx_config_intrpt(struct qlcnic_adapter *adapter, bool op_type)
 {
 	int i, index, err;
-	bool type;
 	u8 max_ints;
-	u32 val, temp;
+	u32 val, temp, type;
 	struct qlcnic_cmd_args cmd;
 
 	max_ints = adapter->ahw->num_msix - 1;
 	qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_INTRPT);
 	cmd.req.arg[1] = max_ints;
+
+	if (qlcnic_sriov_vf_check(adapter))
+		cmd.req.arg[1] |= (adapter->ahw->pci_func << 8) | BIT_16;
+
 	for (i = 0, index = 2; i < max_ints; i++) {
 		type = op_type ? QLCNIC_INTRPT_ADD : QLCNIC_INTRPT_DEL;
 		val = type | (adapter->ahw->intr_tbl[i].type << 4);
@@ -2163,7 +2260,7 @@ static int qlcnic_83xx_poll_flash_status_reg(struct qlcnic_adapter *adapter)
 	return 0;
 }
 
-static int qlcnic_83xx_enable_flash_write_op(struct qlcnic_adapter *adapter)
+int qlcnic_83xx_enable_flash_write(struct qlcnic_adapter *adapter)
 {
 	int ret;
 	u32 cmd;
@@ -2181,7 +2278,7 @@ static int qlcnic_83xx_enable_flash_write_op(struct qlcnic_adapter *adapter)
 	return 0;
 }
 
-static int qlcnic_83xx_disable_flash_write_op(struct qlcnic_adapter *adapter)
+int qlcnic_83xx_disable_flash_write(struct qlcnic_adapter *adapter)
 {
 	int ret;
 
@@ -2255,7 +2352,7 @@ int qlcnic_83xx_erase_flash_sector(struct qlcnic_adapter *adapter,
 		return -EIO;
 
 	if (adapter->ahw->fdt.mfg_id == adapter->flash_mfg_id) {
-		ret = qlcnic_83xx_enable_flash_write_op(adapter);
+		ret = qlcnic_83xx_enable_flash_write(adapter);
 		if (ret) {
 			qlcnic_83xx_unlock_flash(adapter);
 			dev_err(&adapter->pdev->dev,
@@ -2297,7 +2394,7 @@ int qlcnic_83xx_erase_flash_sector(struct qlcnic_adapter *adapter,
 	}
 
 	if (adapter->ahw->fdt.mfg_id == adapter->flash_mfg_id) {
-		ret = qlcnic_83xx_disable_flash_write_op(adapter);
+		ret = qlcnic_83xx_disable_flash_write(adapter);
 		if (ret) {
 			qlcnic_83xx_unlock_flash(adapter);
 			dev_err(&adapter->pdev->dev,
@@ -2337,8 +2434,8 @@ int qlcnic_83xx_flash_bulk_write(struct qlcnic_adapter *adapter, u32 addr,
 	u32 temp;
 	int ret = -EIO;
 
-	if ((count < QLC_83XX_FLASH_BULK_WRITE_MIN) ||
-	    (count > QLC_83XX_FLASH_BULK_WRITE_MAX)) {
+	if ((count < QLC_83XX_FLASH_WRITE_MIN) ||
+	    (count > QLC_83XX_FLASH_WRITE_MAX)) {
 		dev_err(&adapter->pdev->dev,
 			"%s: Invalid word count\n", __func__);
 		return -EIO;
@@ -2616,13 +2713,19 @@ int qlcnic_83xx_flash_read32(struct qlcnic_adapter *adapter, u32 flash_addr,
 
 int qlcnic_83xx_test_link(struct qlcnic_adapter *adapter)
 {
+	u8 pci_func;
 	int err;
 	u32 config = 0, state;
 	struct qlcnic_cmd_args cmd;
 	struct qlcnic_hardware_context *ahw = adapter->ahw;
 
-	state = readl(ahw->pci_base0 + QLC_83XX_LINK_STATE(ahw->pci_func));
-	if (!QLC_83xx_FUNC_VAL(state, ahw->pci_func)) {
+	if (qlcnic_sriov_vf_check(adapter))
+		pci_func = adapter->portnum;
+	else
+		pci_func = ahw->pci_func;
+
+	state = readl(ahw->pci_base0 + QLC_83XX_LINK_STATE(pci_func));
+	if (!QLC_83xx_FUNC_VAL(state, pci_func)) {
 		dev_info(&adapter->pdev->dev, "link state down\n");
 		return config;
 	}
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
index 61f81f6..32ed4b4 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
@@ -12,6 +12,8 @@
 #include <linux/etherdevice.h>
 #include "qlcnic_hw.h"
 
+#define QLCNIC_83XX_BAR0_LENGTH 0x4000
+
 /* Directly mapped registers */
 #define QLC_83XX_CRB_WIN_BASE		0x3800
 #define QLC_83XX_CRB_WIN_FUNC(f)	(QLC_83XX_CRB_WIN_BASE+((f)*4))
@@ -86,6 +88,153 @@
 
 #define QLC_83XX_MAX_RESET_SEQ_ENTRIES	16
 
+/* status descriptor mailbox data
+ * @phy_addr_{low|high}: physical address of buffer
+ * @sds_ring_size: buffer size
+ * @intrpt_id: interrupt id
+ * @intrpt_val: source of interrupt
+ */
+struct qlcnic_sds_mbx {
+	u32	phy_addr_low;
+	u32	phy_addr_high;
+	u32	rsvd1[4];
+#if defined(__LITTLE_ENDIAN)
+	u16	sds_ring_size;
+	u16	rsvd2;
+	u16	rsvd3[2];
+	u16	intrpt_id;
+	u8	intrpt_val;
+	u8	rsvd4;
+#elif defined(__BIG_ENDIAN)
+	u16	rsvd2;
+	u16	sds_ring_size;
+	u16	rsvd3[2];
+	u8	rsvd4;
+	u8	intrpt_val;
+	u16	intrpt_id;
+#endif
+	u32	rsvd5;
+} __packed;
+
+/* receive descriptor buffer data
+ * phy_addr_reg_{low|high}: physical address of regular buffer
+ * phy_addr_jmb_{low|high}: physical address of jumbo buffer
+ * reg_ring_sz: size of regular buffer
+ * reg_ring_len: no. of entries in regular buffer
+ * jmb_ring_len: no. of entries in jumbo buffer
+ * jmb_ring_sz: size of jumbo buffer
+ */
+struct qlcnic_rds_mbx {
+	u32	phy_addr_reg_low;
+	u32	phy_addr_reg_high;
+	u32	phy_addr_jmb_low;
+	u32	phy_addr_jmb_high;
+#if defined(__LITTLE_ENDIAN)
+	u16	reg_ring_sz;
+	u16	reg_ring_len;
+	u16	jmb_ring_sz;
+	u16	jmb_ring_len;
+#elif defined(__BIG_ENDIAN)
+	u16	reg_ring_len;
+	u16	reg_ring_sz;
+	u16	jmb_ring_len;
+	u16	jmb_ring_sz;
+#endif
+} __packed;
+
+/* host producers for regular and jumbo rings */
+struct __host_producer_mbx {
+	u32	reg_buf;
+	u32	jmb_buf;
+} __packed;
+
+/* Receive context mailbox data outbox registers
+ * @state: state of the context
+ * @vport_id: virtual port id
+ * @context_id: receive context id
+ * @num_pci_func: number of pci functions of the port
+ * @phy_port: physical port id
+ */
+struct qlcnic_rcv_mbx_out {
+#if defined(__LITTLE_ENDIAN)
+	u8	rcv_num;
+	u8	sts_num;
+	u16	ctx_id;
+	u8	state;
+	u8	num_pci_func;
+	u8	phy_port;
+	u8	vport_id;
+#elif defined(__BIG_ENDIAN)
+	u16	ctx_id;
+	u8	sts_num;
+	u8	rcv_num;
+	u8	vport_id;
+	u8	phy_port;
+	u8	num_pci_func;
+	u8	state;
+#endif
+	u32	host_csmr[QLCNIC_MAX_RING_SETS];
+	struct __host_producer_mbx host_prod[QLCNIC_MAX_RING_SETS];
+} __packed;
+
+struct qlcnic_add_rings_mbx_out {
+#if defined(__LITTLE_ENDIAN)
+	u8      rcv_num;
+	u8      sts_num;
+	u16	ctx_id;
+#elif defined(__BIG_ENDIAN)
+	u16	ctx_id;
+	u8	sts_num;
+	u8	rcv_num;
+#endif
+	u32  host_csmr[QLCNIC_MAX_RING_SETS];
+	struct __host_producer_mbx host_prod[QLCNIC_MAX_RING_SETS];
+} __packed;
+
+/* Transmit context mailbox inbox registers
+ * @phys_addr_{low|high}: DMA address of the transmit buffer
+ * @cnsmr_index_{low|high}: host consumer index
+ * @size: legth of transmit buffer ring
+ * @intr_id: interrput id
+ * @src: src of interrupt
+ */
+struct qlcnic_tx_mbx {
+	u32	phys_addr_low;
+	u32	phys_addr_high;
+	u32	cnsmr_index_low;
+	u32	cnsmr_index_high;
+#if defined(__LITTLE_ENDIAN)
+	u16	size;
+	u16	intr_id;
+	u8	src;
+	u8	rsvd[3];
+#elif defined(__BIG_ENDIAN)
+	u16	intr_id;
+	u16	size;
+	u8	rsvd[3];
+	u8	src;
+#endif
+} __packed;
+
+/* Transmit context mailbox outbox registers
+ * @host_prod: host producer index
+ * @ctx_id: transmit context id
+ * @state: state of the transmit context
+ */
+
+struct qlcnic_tx_mbx_out {
+	u32	host_prod;
+#if defined(__LITTLE_ENDIAN)
+	u16	ctx_id;
+	u8	state;
+	u8	rsvd;
+#elif defined(__BIG_ENDIAN)
+	u8	rsvd;
+	u8	state;
+	u16	ctx_id;
+#endif
+} __packed;
+
 struct qlcnic_intrpt_config {
 	u8	type;
 	u8	enabled;
@@ -94,8 +243,23 @@ struct qlcnic_intrpt_config {
 };
 
 struct qlcnic_macvlan_mbx {
-	u8	mac[ETH_ALEN];
+#if defined(__LITTLE_ENDIAN)
+	u8	mac_addr0;
+	u8	mac_addr1;
+	u8	mac_addr2;
+	u8	mac_addr3;
+	u8	mac_addr4;
+	u8	mac_addr5;
 	u16	vlan;
+#elif defined(__BIG_ENDIAN)
+	u8	mac_addr3;
+	u8	mac_addr2;
+	u8	mac_addr1;
+	u8	mac_addr0;
+	u16	vlan;
+	u8	mac_addr5;
+	u8	mac_addr4;
+#endif
 };
 
 struct qlc_83xx_fw_info {
@@ -226,6 +390,7 @@ struct qlc_83xx_idc {
 #define QLC_83XX_GET_FW_LRO_MSS_CAPABILITY(val)	(val & 0x20000)
 #define QLC_83XX_VIRTUAL_NIC_MODE			0xFF
 #define QLC_83XX_DEFAULT_MODE				0x0
+#define QLC_83XX_SRIOV_MODE				0x1
 #define QLCNIC_BRDTYPE_83XX_10G			0x0083
 
 #define QLC_83XX_FLASH_SPI_STATUS		0x2808E010
@@ -242,8 +407,8 @@ struct qlc_83xx_idc {
 #define QLC_83XX_FLASH_BULK_WRITE_CMD		0xcadcadca
 #define QLC_83XX_FLASH_READ_RETRY_COUNT	5000
 #define QLC_83XX_FLASH_STATUS_READY		0x6
-#define QLC_83XX_FLASH_BULK_WRITE_MIN		2
-#define QLC_83XX_FLASH_BULK_WRITE_MAX		64
+#define QLC_83XX_FLASH_WRITE_MIN		2
+#define QLC_83XX_FLASH_WRITE_MAX		64
 #define QLC_83XX_FLASH_STATUS_REG_POLL_DELAY	1
 #define QLC_83XX_ERASE_MODE			1
 #define QLC_83XX_WRITE_MODE			2
@@ -351,6 +516,9 @@ int qlcnic_ind_rd(struct qlcnic_adapter *, u32);
 int qlcnic_83xx_create_rx_ctx(struct qlcnic_adapter *);
 int qlcnic_83xx_create_tx_ctx(struct qlcnic_adapter *,
 			      struct qlcnic_host_tx_ring *, int);
+void qlcnic_83xx_del_rx_ctx(struct qlcnic_adapter *);
+void qlcnic_83xx_del_tx_ctx(struct qlcnic_adapter *,
+			    struct qlcnic_host_tx_ring *);
 int qlcnic_83xx_get_nic_info(struct qlcnic_adapter *, struct qlcnic_info *, u8);
 int qlcnic_83xx_setup_link_event(struct qlcnic_adapter *, int);
 void qlcnic_83xx_process_rcv_ring_diag(struct qlcnic_host_sds_ring *);
@@ -401,7 +569,7 @@ int qlcnic_83xx_read_flash_descriptor_table(struct qlcnic_adapter *);
 int qlcnic_83xx_flash_read32(struct qlcnic_adapter *, u32, u8 *, int);
 int qlcnic_83xx_lockless_flash_read32(struct qlcnic_adapter *,
 				      u32, u8 *, int);
-int qlcnic_83xx_init(struct qlcnic_adapter *);
+int qlcnic_83xx_init(struct qlcnic_adapter *, int);
 int qlcnic_83xx_idc_ready_state_entry(struct qlcnic_adapter *);
 int qlcnic_83xx_check_hw_status(struct qlcnic_adapter *p_dev);
 void qlcnic_83xx_idc_poll_dev_state(struct work_struct *);
@@ -434,5 +602,10 @@ int qlcnic_83xx_get_regs_len(struct qlcnic_adapter *);
 int qlcnic_83xx_get_registers(struct qlcnic_adapter *, u32 *);
 int qlcnic_83xx_loopback_test(struct net_device *, u8);
 int qlcnic_83xx_interrupt_test(struct net_device *);
+int qlcnic_83xx_set_led(struct net_device *, enum ethtool_phys_id_state);
 int qlcnic_83xx_flash_test(struct qlcnic_adapter *);
+int qlcnic_83xx_enable_flash_write(struct qlcnic_adapter *);
+int qlcnic_83xx_disable_flash_write(struct qlcnic_adapter *);
+u32 qlcnic_83xx_mac_rcode(struct qlcnic_adapter *);
+u32 qlcnic_83xx_mbx_poll(struct qlcnic_adapter *);
 #endif
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
index 5c033f2..c302d11 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
@@ -5,6 +5,7 @@
  * See LICENSE.qlcnic for copyright and licensing details.
  */
 
+#include "qlcnic_sriov.h"
 #include "qlcnic.h"
 #include "qlcnic_hw.h"
 
@@ -25,12 +26,12 @@
 #define QLC_83XX_OPCODE_POLL_READ_LIST		0x0100
 
 static int qlcnic_83xx_init_default_driver(struct qlcnic_adapter *adapter);
-static int qlcnic_83xx_configure_opmode(struct qlcnic_adapter *adapter);
 static int qlcnic_83xx_check_heartbeat(struct qlcnic_adapter *p_dev);
 static int qlcnic_83xx_restart_hw(struct qlcnic_adapter *adapter);
 
 /* Template header */
 struct qlc_83xx_reset_hdr {
+#if defined(__LITTLE_ENDIAN)
 	u16	version;
 	u16	signature;
 	u16	size;
@@ -39,14 +40,31 @@ struct qlc_83xx_reset_hdr {
 	u16	checksum;
 	u16	init_offset;
 	u16	start_offset;
+#elif defined(__BIG_ENDIAN)
+	u16	signature;
+	u16	version;
+	u16	entries;
+	u16	size;
+	u16	checksum;
+	u16	hdr_size;
+	u16	start_offset;
+	u16	init_offset;
+#endif
 } __packed;
 
 /* Command entry header. */
 struct qlc_83xx_entry_hdr {
-	u16 cmd;
-	u16 size;
-	u16 count;
-	u16 delay;
+#if defined(__LITTLE_ENDIAN)
+	u16	cmd;
+	u16	size;
+	u16	count;
+	u16	delay;
+#elif defined(__BIG_ENDIAN)
+	u16	size;
+	u16	cmd;
+	u16	delay;
+	u16	count;
+#endif
 } __packed;
 
 /* Generic poll command */
@@ -60,10 +78,17 @@ struct qlc_83xx_rmw {
 	u32	mask;
 	u32	xor_value;
 	u32	or_value;
+#if defined(__LITTLE_ENDIAN)
 	u8	shl;
 	u8	shr;
 	u8	index_a;
 	u8	rsvd;
+#elif defined(__BIG_ENDIAN)
+	u8	rsvd;
+	u8	index_a;
+	u8	shr;
+	u8	shl;
+#endif
 } __packed;
 
 /* Generic command with 2 DWORD */
@@ -1893,6 +1918,9 @@ int qlcnic_83xx_config_default_opmode(struct qlcnic_adapter *adapter)
 	qlcnic_get_func_no(adapter);
 	op_mode = QLCRDX(ahw, QLC_83XX_DRV_OP_MODE);
 
+	if (test_bit(__QLCNIC_SRIOV_CAPABLE, &adapter->state))
+		op_mode = QLC_83XX_DEFAULT_OPMODE;
+
 	if (op_mode == QLC_83XX_DEFAULT_OPMODE) {
 		adapter->nic_ops->init_driver = qlcnic_83xx_init_default_driver;
 		ahw->idc.state_entry = qlcnic_83xx_idc_ready_state_entry;
@@ -1922,6 +1950,16 @@ int qlcnic_83xx_get_nic_configuration(struct qlcnic_adapter *adapter)
 	ahw->max_mac_filters = nic_info.max_mac_filters;
 	ahw->max_mtu = nic_info.max_mtu;
 
+	/* VNIC mode is detected by BIT_23 in capabilities. This bit is also
+	 * set in case device is SRIOV capable. VNIC and SRIOV are mutually
+	 * exclusive. So in case of sriov capable device load driver in
+	 * default mode
+	 */
+	if (test_bit(__QLCNIC_SRIOV_CAPABLE, &adapter->state)) {
+		ahw->nic_mode = QLC_83XX_DEFAULT_MODE;
+		return ahw->nic_mode;
+	}
+
 	if (ahw->capabilities & BIT_23)
 		ahw->nic_mode = QLC_83XX_VIRTUAL_NIC_MODE;
 	else
@@ -1930,7 +1968,7 @@ int qlcnic_83xx_get_nic_configuration(struct qlcnic_adapter *adapter)
 	return ahw->nic_mode;
 }
 
-static int qlcnic_83xx_configure_opmode(struct qlcnic_adapter *adapter)
+int qlcnic_83xx_configure_opmode(struct qlcnic_adapter *adapter)
 {
 	int ret;
 
@@ -2008,10 +2046,13 @@ static void qlcnic_83xx_clear_function_resources(struct qlcnic_adapter *adapter)
 	}
 }
 
-int qlcnic_83xx_init(struct qlcnic_adapter *adapter)
+int qlcnic_83xx_init(struct qlcnic_adapter *adapter, int pci_using_dac)
 {
 	struct qlcnic_hardware_context *ahw = adapter->ahw;
 
+	if (qlcnic_sriov_vf_check(adapter))
+		return qlcnic_sriov_vf_init(adapter, pci_using_dac);
+
 	if (qlcnic_83xx_check_hw_status(adapter))
 		return -EIO;
 
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
index a69097c..43562c2 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
@@ -382,8 +382,7 @@ out_free_rq:
 	return err;
 }
 
-static void
-qlcnic_fw_cmd_destroy_rx_ctx(struct qlcnic_adapter *adapter)
+void qlcnic_82xx_fw_cmd_del_rx_ctx(struct qlcnic_adapter *adapter)
 {
 	int err;
 	struct qlcnic_cmd_args cmd;
@@ -422,22 +421,20 @@ int qlcnic_82xx_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter,
 
 	rq_size = SIZEOF_HOSTRQ_TX(struct qlcnic_hostrq_tx_ctx);
 	rq_addr = dma_alloc_coherent(&adapter->pdev->dev, rq_size,
-			&rq_phys_addr, GFP_KERNEL);
+				     &rq_phys_addr, GFP_KERNEL | __GFP_ZERO);
 	if (!rq_addr)
 		return -ENOMEM;
 
 	rsp_size = SIZEOF_CARDRSP_TX(struct qlcnic_cardrsp_tx_ctx);
 	rsp_addr = dma_alloc_coherent(&adapter->pdev->dev, rsp_size,
-			&rsp_phys_addr, GFP_KERNEL);
+				      &rsp_phys_addr, GFP_KERNEL | __GFP_ZERO);
 	if (!rsp_addr) {
 		err = -ENOMEM;
 		goto out_free_rq;
 	}
 
-	memset(rq_addr, 0, rq_size);
 	prq = rq_addr;
 
-	memset(rsp_addr, 0, rsp_size);
 	prsp = rsp_addr;
 
 	prq->host_rsp_dma_addr = cpu_to_le64(rsp_phys_addr);
@@ -486,13 +483,13 @@ out_free_rq:
 	return err;
 }
 
-static void
-qlcnic_fw_cmd_destroy_tx_ctx(struct qlcnic_adapter *adapter,
-			     struct qlcnic_host_tx_ring *tx_ring)
+void qlcnic_82xx_fw_cmd_del_tx_ctx(struct qlcnic_adapter *adapter,
+				   struct qlcnic_host_tx_ring *tx_ring)
 {
 	struct qlcnic_cmd_args cmd;
 
 	qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_DESTROY_TX_CTX);
+
 	cmd.req.arg[1] = tx_ring->ctx_id;
 	if (qlcnic_issue_cmd(adapter, &cmd))
 		dev_err(&adapter->pdev->dev,
@@ -532,20 +529,15 @@ int qlcnic_alloc_hw_resources(struct qlcnic_adapter *adapter)
 		ptr = (__le32 *)dma_alloc_coherent(&pdev->dev, sizeof(u32),
 						   &tx_ring->hw_cons_phys_addr,
 						   GFP_KERNEL);
-
-		if (ptr == NULL) {
-			dev_err(&pdev->dev, "failed to allocate tx consumer\n");
+		if (ptr == NULL)
 			return -ENOMEM;
-		}
+
 		tx_ring->hw_consumer = ptr;
 		/* cmd desc ring */
 		addr = dma_alloc_coherent(&pdev->dev, TX_DESC_RINGSIZE(tx_ring),
 					  &tx_ring->phys_addr,
 					  GFP_KERNEL);
-
 		if (addr == NULL) {
-			dev_err(&pdev->dev,
-				"failed to allocate tx desc ring\n");
 			err = -ENOMEM;
 			goto err_out_free;
 		}
@@ -556,11 +548,9 @@ int qlcnic_alloc_hw_resources(struct qlcnic_adapter *adapter)
 	for (ring = 0; ring < adapter->max_rds_rings; ring++) {
 		rds_ring = &recv_ctx->rds_rings[ring];
 		addr = dma_alloc_coherent(&adapter->pdev->dev,
-				RCV_DESC_RINGSIZE(rds_ring),
-				&rds_ring->phys_addr, GFP_KERNEL);
+					  RCV_DESC_RINGSIZE(rds_ring),
+					  &rds_ring->phys_addr, GFP_KERNEL);
 		if (addr == NULL) {
-			dev_err(&pdev->dev,
-				"failed to allocate rds ring [%d]\n", ring);
 			err = -ENOMEM;
 			goto err_out_free;
 		}
@@ -572,11 +562,9 @@ int qlcnic_alloc_hw_resources(struct qlcnic_adapter *adapter)
 		sds_ring = &recv_ctx->sds_rings[ring];
 
 		addr = dma_alloc_coherent(&adapter->pdev->dev,
-				STATUS_DESC_RINGSIZE(sds_ring),
-				&sds_ring->phys_addr, GFP_KERNEL);
+					  STATUS_DESC_RINGSIZE(sds_ring),
+					  &sds_ring->phys_addr, GFP_KERNEL);
 		if (addr == NULL) {
-			dev_err(&pdev->dev,
-				"failed to allocate sds ring [%d]\n", ring);
 			err = -ENOMEM;
 			goto err_out_free;
 		}
@@ -616,13 +604,12 @@ int qlcnic_fw_create_ctx(struct qlcnic_adapter *dev)
 						  &dev->tx_ring[ring],
 						  ring);
 		if (err) {
-			qlcnic_fw_cmd_destroy_rx_ctx(dev);
+			qlcnic_fw_cmd_del_rx_ctx(dev);
 			if (ring == 0)
 				goto err_out;
 
 			for (i = 0; i < ring; i++)
-				qlcnic_fw_cmd_destroy_tx_ctx(dev,
-							     &dev->tx_ring[i]);
+				qlcnic_fw_cmd_del_tx_ctx(dev, &dev->tx_ring[i]);
 
 			goto err_out;
 		}
@@ -644,10 +631,10 @@ void qlcnic_fw_destroy_ctx(struct qlcnic_adapter *adapter)
 	int ring;
 
 	if (test_and_clear_bit(__QLCNIC_FW_ATTACHED, &adapter->state)) {
-		qlcnic_fw_cmd_destroy_rx_ctx(adapter);
+		qlcnic_fw_cmd_del_rx_ctx(adapter);
 		for (ring = 0; ring < adapter->max_drv_tx_rings; ring++)
-			qlcnic_fw_cmd_destroy_tx_ctx(adapter,
-						     &adapter->tx_ring[ring]);
+			qlcnic_fw_cmd_del_tx_ctx(adapter,
+						 &adapter->tx_ring[ring]);
 
 		if (qlcnic_83xx_check(adapter) &&
 		    (adapter->flags & QLCNIC_MSIX_ENABLED)) {
@@ -655,7 +642,7 @@ void qlcnic_fw_destroy_ctx(struct qlcnic_adapter *adapter)
 				qlcnic_83xx_config_intrpt(adapter, 0);
 		}
 		/* Allow dma queues to drain after context reset */
-		mdelay(20);
+		msleep(20);
 	}
 }
 
@@ -753,10 +740,9 @@ int qlcnic_82xx_get_nic_info(struct qlcnic_adapter *adapter,
 	size_t  nic_size = sizeof(struct qlcnic_info_le);
 
 	nic_info_addr = dma_alloc_coherent(&adapter->pdev->dev, nic_size,
-				&nic_dma_t, GFP_KERNEL);
+					   &nic_dma_t, GFP_KERNEL | __GFP_ZERO);
 	if (!nic_info_addr)
 		return -ENOMEM;
-	memset(nic_info_addr, 0, nic_size);
 
 	nic_info = nic_info_addr;
 
@@ -804,11 +790,10 @@ int qlcnic_82xx_set_nic_info(struct qlcnic_adapter *adapter,
 		return err;
 
 	nic_info_addr = dma_alloc_coherent(&adapter->pdev->dev, nic_size,
-			&nic_dma_t, GFP_KERNEL);
+					   &nic_dma_t, GFP_KERNEL | __GFP_ZERO);
 	if (!nic_info_addr)
 		return -ENOMEM;
 
-	memset(nic_info_addr, 0, nic_size);
 	nic_info = nic_info_addr;
 
 	nic_info->pci_func = cpu_to_le16(nic->pci_func);
@@ -854,10 +839,10 @@ int qlcnic_82xx_get_pci_info(struct qlcnic_adapter *adapter,
 	size_t pci_size = npar_size * QLCNIC_MAX_PCI_FUNC;
 
 	pci_info_addr = dma_alloc_coherent(&adapter->pdev->dev, pci_size,
-			&pci_info_dma_t, GFP_KERNEL);
+					   &pci_info_dma_t,
+					   GFP_KERNEL | __GFP_ZERO);
 	if (!pci_info_addr)
 		return -ENOMEM;
-	memset(pci_info_addr, 0, pci_size);
 
 	npar = pci_info_addr;
 	qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_PCI_INFO);
@@ -949,12 +934,9 @@ int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func,
 	}
 
 	stats_addr = dma_alloc_coherent(&adapter->pdev->dev, stats_size,
-			&stats_dma_t, GFP_KERNEL);
-	if (!stats_addr) {
-		dev_err(&adapter->pdev->dev, "Unable to allocate memory\n");
+					&stats_dma_t, GFP_KERNEL | __GFP_ZERO);
+	if (!stats_addr)
 		return -ENOMEM;
-	}
-	memset(stats_addr, 0, stats_size);
 
 	arg1 = func | QLCNIC_STATS_VERSION << 8 | QLCNIC_STATS_PORT << 12;
 	arg1 |= rx_tx << 15 | stats_size << 16;
@@ -1003,13 +985,10 @@ int qlcnic_get_mac_stats(struct qlcnic_adapter *adapter,
 		return -ENOMEM;
 
 	stats_addr = dma_alloc_coherent(&adapter->pdev->dev, stats_size,
-			&stats_dma_t, GFP_KERNEL);
-	if (!stats_addr) {
-		dev_err(&adapter->pdev->dev,
-			"%s: Unable to allocate memory.\n", __func__);
+					&stats_dma_t, GFP_KERNEL | __GFP_ZERO);
+	if (!stats_addr)
 		return -ENOMEM;
-	}
-	memset(stats_addr, 0, stats_size);
+
 	qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_MAC_STATS);
 	cmd.req.arg[1] = stats_size << 16;
 	cmd.req.arg[2] = MSD(stats_dma_t);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
index 5641f8e..f4f279d 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
@@ -149,7 +149,8 @@ static const char qlcnic_gstrings_test[][ETH_GSTRING_LEN] = {
 
 static inline int qlcnic_82xx_statistics(void)
 {
-	return QLCNIC_STATS_LEN + ARRAY_SIZE(qlcnic_83xx_mac_stats_strings);
+	return ARRAY_SIZE(qlcnic_device_gstrings_stats) +
+	       ARRAY_SIZE(qlcnic_83xx_mac_stats_strings);
 }
 
 static inline int qlcnic_83xx_statistics(void)
@@ -1070,8 +1071,7 @@ qlcnic_get_strings(struct net_device *dev, u32 stringset, u8 *data)
 	}
 }
 
-static void
-qlcnic_fill_stats(u64 *data, void *stats, int type)
+static u64 *qlcnic_fill_stats(u64 *data, void *stats, int type)
 {
 	if (type == QLCNIC_MAC_STATS) {
 		struct qlcnic_mac_statistics *mac_stats =
@@ -1120,6 +1120,7 @@ qlcnic_fill_stats(u64 *data, void *stats, int type)
 		*data++ = QLCNIC_FILL_STATS(esw_stats->local_frames);
 		*data++ = QLCNIC_FILL_STATS(esw_stats->numbytes);
 	}
+	return data;
 }
 
 static void qlcnic_get_ethtool_stats(struct net_device *dev,
@@ -1147,7 +1148,7 @@ static void qlcnic_get_ethtool_stats(struct net_device *dev,
 		/* Retrieve MAC statistics from firmware */
 		memset(&mac_stats, 0, sizeof(struct qlcnic_mac_statistics));
 		qlcnic_get_mac_stats(adapter, &mac_stats);
-		qlcnic_fill_stats(data, &mac_stats, QLCNIC_MAC_STATS);
+		data = qlcnic_fill_stats(data, &mac_stats, QLCNIC_MAC_STATS);
 	}
 
 	if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
@@ -1159,7 +1160,7 @@ static void qlcnic_get_ethtool_stats(struct net_device *dev,
 	if (ret)
 		return;
 
-	qlcnic_fill_stats(data, &port_stats.rx, QLCNIC_ESW_STATS);
+	data = qlcnic_fill_stats(data, &port_stats.rx, QLCNIC_ESW_STATS);
 	ret = qlcnic_get_port_stats(adapter, adapter->ahw->pci_func,
 			QLCNIC_QUERY_TX_COUNTER, &port_stats.tx);
 	if (ret)
@@ -1176,7 +1177,8 @@ static int qlcnic_set_led(struct net_device *dev,
 	int err = -EIO, active = 1;
 
 	if (qlcnic_83xx_check(adapter))
-		return -EOPNOTSUPP;
+		return qlcnic_83xx_set_led(dev, state);
+
 	if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC) {
 		netdev_warn(dev, "LED test not supported for non "
 				"privilege function\n");
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h
index 44197ca..1cebd89 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h
@@ -714,7 +714,9 @@ enum {
 	QLCNIC_MGMT_FUNC	= 0,
 	QLCNIC_PRIV_FUNC	= 1,
 	QLCNIC_NON_PRIV_FUNC	= 2,
-	QLCNIC_UNKNOWN_FUNC_MODE = 3
+	QLCNIC_SRIOV_PF_FUNC	= 3,
+	QLCNIC_SRIOV_VF_FUNC	= 4,
+	QLCNIC_UNKNOWN_FUNC_MODE = 5
 };
 
 enum {
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
index f89cc7a..253b3ac 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
@@ -496,7 +496,7 @@ int qlcnic_nic_add_mac(struct qlcnic_adapter *adapter, const u8 *addr)
 	return 0;
 }
 
-void qlcnic_set_multi(struct net_device *netdev)
+void __qlcnic_set_multi(struct net_device *netdev)
 {
 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
 	struct netdev_hw_addr *ha;
@@ -508,7 +508,8 @@ void qlcnic_set_multi(struct net_device *netdev)
 	if (!test_bit(__QLCNIC_FW_ATTACHED, &adapter->state))
 		return;
 
-	qlcnic_nic_add_mac(adapter, adapter->mac_addr);
+	if (!qlcnic_sriov_vf_check(adapter))
+		qlcnic_nic_add_mac(adapter, adapter->mac_addr);
 	qlcnic_nic_add_mac(adapter, bcast_addr);
 
 	if (netdev->flags & IFF_PROMISC) {
@@ -523,23 +524,55 @@ void qlcnic_set_multi(struct net_device *netdev)
 		goto send_fw_cmd;
 	}
 
-	if (!netdev_mc_empty(netdev)) {
+	if (!netdev_mc_empty(netdev) && !qlcnic_sriov_vf_check(adapter)) {
 		netdev_for_each_mc_addr(ha, netdev) {
 			qlcnic_nic_add_mac(adapter, ha->addr);
 		}
 	}
 
+	if (qlcnic_sriov_vf_check(adapter))
+		qlcnic_vf_add_mc_list(netdev);
+
 send_fw_cmd:
-	if (mode == VPORT_MISS_MODE_ACCEPT_ALL && !adapter->fdb_mac_learn) {
-		qlcnic_alloc_lb_filters_mem(adapter);
-		adapter->drv_mac_learn = true;
-	} else {
-		adapter->drv_mac_learn = false;
+	if (!qlcnic_sriov_vf_check(adapter)) {
+		if (mode == VPORT_MISS_MODE_ACCEPT_ALL &&
+		    !adapter->fdb_mac_learn) {
+			qlcnic_alloc_lb_filters_mem(adapter);
+			adapter->drv_mac_learn = true;
+		} else {
+			adapter->drv_mac_learn = false;
+		}
 	}
 
 	qlcnic_nic_set_promisc(adapter, mode);
 }
 
+void qlcnic_set_multi(struct net_device *netdev)
+{
+	struct qlcnic_adapter *adapter = netdev_priv(netdev);
+	struct netdev_hw_addr *ha;
+	struct qlcnic_mac_list_s *cur;
+
+	if (!test_bit(__QLCNIC_FW_ATTACHED, &adapter->state))
+		return;
+	if (qlcnic_sriov_vf_check(adapter)) {
+		if (!netdev_mc_empty(netdev)) {
+			netdev_for_each_mc_addr(ha, netdev) {
+				cur = kzalloc(sizeof(struct qlcnic_mac_list_s),
+					      GFP_ATOMIC);
+				if (cur == NULL)
+					break;
+				memcpy(cur->mac_addr,
+				       ha->addr, ETH_ALEN);
+				list_add_tail(&cur->list, &adapter->vf_mc_list);
+			}
+		}
+		qlcnic_sriov_vf_schedule_multi(adapter->netdev);
+		return;
+	}
+	__qlcnic_set_multi(netdev);
+}
+
 int qlcnic_82xx_nic_set_promisc(struct qlcnic_adapter *adapter, u32 mode)
 {
 	struct qlcnic_nic_req req;
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h
index 5b8749e..e862a77 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h
@@ -83,6 +83,8 @@ enum qlcnic_regs {
 #define QLCNIC_CMD_CONFIG_PORT			0x2e
 #define QLCNIC_CMD_TEMP_SIZE			0x2f
 #define QLCNIC_CMD_GET_TEMP_HDR			0x30
+#define QLCNIC_CMD_BC_EVENT_SETUP		0x31
+#define	QLCNIC_CMD_CONFIG_VPORT			0x32
 #define QLCNIC_CMD_GET_MAC_STATS		0x37
 #define QLCNIC_CMD_SET_DRV_VER			0x38
 #define QLCNIC_CMD_CONFIGURE_RSS		0x41
@@ -114,6 +116,7 @@ enum qlcnic_regs {
 #define QLCNIC_SET_FAC_DEF_MAC			5
 
 #define QLCNIC_MBX_LINK_EVENT		0x8001
+#define QLCNIC_MBX_BC_EVENT		0x8002
 #define QLCNIC_MBX_COMP_EVENT		0x8100
 #define QLCNIC_MBX_REQUEST_EVENT	0x8101
 #define QLCNIC_MBX_TIME_EXTEND_EVENT	0x8102
@@ -175,6 +178,9 @@ int qlcnic_82xx_issue_cmd(struct qlcnic_adapter *adapter,
 int qlcnic_82xx_fw_cmd_create_rx_ctx(struct qlcnic_adapter *);
 int qlcnic_82xx_fw_cmd_create_tx_ctx(struct qlcnic_adapter *,
 				     struct qlcnic_host_tx_ring *tx_ring, int);
+void qlcnic_82xx_fw_cmd_del_rx_ctx(struct qlcnic_adapter *);
+void qlcnic_82xx_fw_cmd_del_tx_ctx(struct qlcnic_adapter *,
+				   struct qlcnic_host_tx_ring *);
 int qlcnic_82xx_sre_macaddr_change(struct qlcnic_adapter *, u8 *, __le16, u8);
 int qlcnic_82xx_get_mac_address(struct qlcnic_adapter *, u8*);
 int qlcnic_82xx_get_nic_info(struct qlcnic_adapter *, struct qlcnic_info *, u8);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
index 0e63006..a85ca63a 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
@@ -9,6 +9,7 @@
 #include <linux/if_vlan.h>
 #include <net/ip.h>
 #include <linux/ipv6.h>
+#include <net/checksum.h>
 
 #include "qlcnic.h"
 
@@ -146,7 +147,10 @@ static inline u8 qlcnic_mac_hash(u64 mac)
 static inline u32 qlcnic_get_ref_handle(struct qlcnic_adapter *adapter,
 					u16 handle, u8 ring_id)
 {
-	if (adapter->pdev->device == PCI_DEVICE_ID_QLOGIC_QLE834X)
+	unsigned short device = adapter->pdev->device;
+
+	if ((device == PCI_DEVICE_ID_QLOGIC_QLE834X) ||
+	    (device == PCI_DEVICE_ID_QLOGIC_VF_QLE834X))
 		return handle | (ring_id << 15);
 	else
 		return handle;
@@ -1132,9 +1136,8 @@ qlcnic_process_lro(struct qlcnic_adapter *adapter,
 		iph = (struct iphdr *)skb->data;
 		th = (struct tcphdr *)(skb->data + (iph->ihl << 2));
 		length = (iph->ihl << 2) + (th->doff << 2) + lro_length;
+		csum_replace2(&iph->check, iph->tot_len, htons(length));
 		iph->tot_len = htons(length);
-		iph->check = 0;
-		iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
 	}
 
 	th->psh = push;
@@ -1595,9 +1598,8 @@ qlcnic_83xx_process_lro(struct qlcnic_adapter *adapter,
 		iph = (struct iphdr *)skb->data;
 		th = (struct tcphdr *)(skb->data + (iph->ihl << 2));
 		length = (iph->ihl << 2) + (th->doff << 2) + lro_length;
+		csum_replace2(&iph->check, iph->tot_len, htons(length));
 		iph->tot_len = htons(length);
-		iph->check = 0;
-		iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
 	}
 
 	th->psh = push;
@@ -1692,6 +1694,29 @@ skip:
 	return count;
 }
 
+static int qlcnic_83xx_msix_sriov_vf_poll(struct napi_struct *napi, int budget)
+{
+	int tx_complete;
+	int work_done;
+	struct qlcnic_host_sds_ring *sds_ring;
+	struct qlcnic_adapter *adapter;
+	struct qlcnic_host_tx_ring *tx_ring;
+
+	sds_ring = container_of(napi, struct qlcnic_host_sds_ring, napi);
+	adapter = sds_ring->adapter;
+	/* tx ring count = 1 */
+	tx_ring = adapter->tx_ring;
+
+	tx_complete = qlcnic_process_cmd_ring(adapter, tx_ring, budget);
+	work_done = qlcnic_83xx_process_rcv_ring(sds_ring, budget);
+	if ((work_done < budget) && tx_complete) {
+		napi_complete(&sds_ring->napi);
+		qlcnic_83xx_enable_intr(adapter, sds_ring);
+	}
+
+	return work_done;
+}
+
 static int qlcnic_83xx_poll(struct napi_struct *napi, int budget)
 {
 	int tx_complete;
@@ -1769,7 +1794,8 @@ void qlcnic_83xx_napi_enable(struct qlcnic_adapter *adapter)
 			qlcnic_83xx_enable_intr(adapter, sds_ring);
 	}
 
-	if (adapter->flags & QLCNIC_MSIX_ENABLED) {
+	if ((adapter->flags & QLCNIC_MSIX_ENABLED) &&
+	    !(adapter->flags & QLCNIC_TX_INTR_SHARED)) {
 		for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) {
 			tx_ring = &adapter->tx_ring[ring];
 			napi_enable(&tx_ring->napi);
@@ -1796,7 +1822,8 @@ void qlcnic_83xx_napi_disable(struct qlcnic_adapter *adapter)
 		napi_disable(&sds_ring->napi);
 	}
 
-	if (adapter->flags & QLCNIC_MSIX_ENABLED) {
+	if ((adapter->flags & QLCNIC_MSIX_ENABLED) &&
+	    !(adapter->flags & QLCNIC_TX_INTR_SHARED)) {
 		for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) {
 			tx_ring = &adapter->tx_ring[ring];
 			qlcnic_83xx_disable_tx_intr(adapter, tx_ring);
@@ -1809,7 +1836,7 @@ void qlcnic_83xx_napi_disable(struct qlcnic_adapter *adapter)
 int qlcnic_83xx_napi_add(struct qlcnic_adapter *adapter,
 			 struct net_device *netdev)
 {
-	int ring, max_sds_rings;
+	int ring, max_sds_rings, temp;
 	struct qlcnic_host_sds_ring *sds_ring;
 	struct qlcnic_host_tx_ring *tx_ring;
 	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
@@ -1820,14 +1847,23 @@ int qlcnic_83xx_napi_add(struct qlcnic_adapter *adapter,
 	max_sds_rings = adapter->max_sds_rings;
 	for (ring = 0; ring < adapter->max_sds_rings; ring++) {
 		sds_ring = &recv_ctx->sds_rings[ring];
-		if (adapter->flags & QLCNIC_MSIX_ENABLED)
-			netif_napi_add(netdev, &sds_ring->napi,
-				       qlcnic_83xx_rx_poll,
-				       QLCNIC_NETDEV_WEIGHT * 2);
-		else
+		if (adapter->flags & QLCNIC_MSIX_ENABLED) {
+			if (!(adapter->flags & QLCNIC_TX_INTR_SHARED)) {
+				netif_napi_add(netdev, &sds_ring->napi,
+					       qlcnic_83xx_rx_poll,
+					       QLCNIC_NETDEV_WEIGHT * 2);
+			} else {
+				temp = QLCNIC_NETDEV_WEIGHT / max_sds_rings;
+				netif_napi_add(netdev, &sds_ring->napi,
+					       qlcnic_83xx_msix_sriov_vf_poll,
+					       temp);
+			}
+
+		} else {
 			netif_napi_add(netdev, &sds_ring->napi,
 				       qlcnic_83xx_poll,
 				       QLCNIC_NETDEV_WEIGHT / max_sds_rings);
+		}
 	}
 
 	if (qlcnic_alloc_tx_rings(adapter, netdev)) {
@@ -1835,7 +1871,8 @@ int qlcnic_83xx_napi_add(struct qlcnic_adapter *adapter,
 		return -ENOMEM;
 	}
 
-	if (adapter->flags & QLCNIC_MSIX_ENABLED) {
+	if ((adapter->flags & QLCNIC_MSIX_ENABLED) &&
+	    !(adapter->flags & QLCNIC_TX_INTR_SHARED)) {
 		for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) {
 			tx_ring = &adapter->tx_ring[ring];
 			netif_napi_add(netdev, &tx_ring->napi,
@@ -1861,7 +1898,8 @@ void qlcnic_83xx_napi_del(struct qlcnic_adapter *adapter)
 
 	qlcnic_free_sds_rings(adapter->recv_ctx);
 
-	if ((adapter->flags & QLCNIC_MSIX_ENABLED)) {
+	if ((adapter->flags & QLCNIC_MSIX_ENABLED) &&
+	    !(adapter->flags & QLCNIC_TX_INTR_SHARED)) {
 		for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) {
 			tx_ring = &adapter->tx_ring[ring];
 			netif_napi_del(&tx_ring->napi);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index 28a6d48..0d00b2b 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -9,6 +9,7 @@
 #include <linux/interrupt.h>
 
 #include "qlcnic.h"
+#include "qlcnic_sriov.h"
 #include "qlcnic_hw.h"
 
 #include <linux/swab.h>
@@ -109,6 +110,7 @@ static u32 qlcnic_vlan_tx_check(struct qlcnic_adapter *adapter)
 static DEFINE_PCI_DEVICE_TABLE(qlcnic_pci_tbl) = {
 	ENTRY(PCI_DEVICE_ID_QLOGIC_QLE824X),
 	ENTRY(PCI_DEVICE_ID_QLOGIC_QLE834X),
+	ENTRY(PCI_DEVICE_ID_QLOGIC_VF_QLE834X),
 	{0,}
 };
 
@@ -198,8 +200,7 @@ void qlcnic_free_sds_rings(struct qlcnic_recv_context *recv_ctx)
 	recv_ctx->sds_rings = NULL;
 }
 
-static int
-qlcnic_read_mac_addr(struct qlcnic_adapter *adapter)
+int qlcnic_read_mac_addr(struct qlcnic_adapter *adapter)
 {
 	u8 mac_addr[ETH_ALEN];
 	struct net_device *netdev = adapter->netdev;
@@ -225,6 +226,9 @@ static int qlcnic_set_mac(struct net_device *netdev, void *p)
 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
 	struct sockaddr *addr = p;
 
+	if (qlcnic_sriov_vf_check(adapter))
+		return -EINVAL;
+
 	if ((adapter->flags & QLCNIC_MAC_OVERRIDE_DISABLED))
 		return -EOPNOTSUPP;
 
@@ -253,11 +257,8 @@ static int qlcnic_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],
 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
 	int err = -EOPNOTSUPP;
 
-	if (!adapter->fdb_mac_learn) {
-		pr_info("%s: Driver mac learn is enabled, FDB operation not allowed\n",
-			__func__);
-		return err;
-	}
+	if (!adapter->fdb_mac_learn)
+		return ndo_dflt_fdb_del(ndm, tb, netdev, addr);
 
 	if (adapter->flags & QLCNIC_ESWITCH_ENABLED) {
 		if (is_unicast_ether_addr(addr))
@@ -277,11 +278,8 @@ static int qlcnic_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
 	int err = 0;
 
-	if (!adapter->fdb_mac_learn) {
-		pr_info("%s: Driver mac learn is enabled, FDB operation not allowed\n",
-			__func__);
-		return -EOPNOTSUPP;
-	}
+	if (!adapter->fdb_mac_learn)
+		return ndo_dflt_fdb_add(ndm, tb, netdev, addr, flags);
 
 	if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED)) {
 		pr_info("%s: FDB e-switch is not enabled\n", __func__);
@@ -306,11 +304,8 @@ static int qlcnic_fdb_dump(struct sk_buff *skb, struct netlink_callback *ncb,
 {
 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
 
-	if (!adapter->fdb_mac_learn) {
-		pr_info("%s: Driver mac learn is enabled, FDB operation not allowed\n",
-			__func__);
-		return -EOPNOTSUPP;
-	}
+	if (!adapter->fdb_mac_learn)
+		return ndo_dflt_fdb_dump(skb, ncb, netdev, idx);
 
 	if (adapter->flags & QLCNIC_ESWITCH_ENABLED)
 		idx = ndo_dflt_fdb_dump(skb, ncb, netdev, idx);
@@ -387,6 +382,8 @@ static struct qlcnic_hardware_ops qlcnic_hw_ops = {
 	.process_lb_rcv_ring_diag	= qlcnic_82xx_process_rcv_ring_diag,
 	.create_rx_ctx			= qlcnic_82xx_fw_cmd_create_rx_ctx,
 	.create_tx_ctx			= qlcnic_82xx_fw_cmd_create_tx_ctx,
+	.del_rx_ctx			= qlcnic_82xx_fw_cmd_del_rx_ctx,
+	.del_tx_ctx			= qlcnic_82xx_fw_cmd_del_tx_ctx,
 	.setup_link_event		= qlcnic_82xx_linkevent_request,
 	.get_nic_info			= qlcnic_82xx_get_nic_info,
 	.get_pci_info			= qlcnic_82xx_get_pci_info,
@@ -408,7 +405,15 @@ int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix)
 {
 	struct pci_dev *pdev = adapter->pdev;
 	int err = -1, i;
-	int max_tx_rings;
+	int max_tx_rings, tx_vector;
+
+	if (adapter->flags & QLCNIC_TX_INTR_SHARED) {
+		max_tx_rings = 0;
+		tx_vector = 0;
+	} else {
+		max_tx_rings = adapter->max_drv_tx_rings;
+		tx_vector = 1;
+	}
 
 	if (!adapter->msix_entries) {
 		adapter->msix_entries = kcalloc(num_msix,
@@ -431,7 +436,6 @@ int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix)
 			if (qlcnic_83xx_check(adapter)) {
 				adapter->ahw->num_msix = num_msix;
 				/* subtract mail box and tx ring vectors */
-				max_tx_rings = adapter->max_drv_tx_rings;
 				adapter->max_sds_rings = num_msix -
 							 max_tx_rings - 1;
 			} else {
@@ -444,11 +448,11 @@ int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix)
 				 "Unable to allocate %d MSI-X interrupt vectors\n",
 				 num_msix);
 			if (qlcnic_83xx_check(adapter)) {
-				if (err < QLC_83XX_MINIMUM_VECTOR)
+				if (err < (QLC_83XX_MINIMUM_VECTOR - tx_vector))
 					return err;
-				err -= (adapter->max_drv_tx_rings + 1);
+				err -= (max_tx_rings + 1);
 				num_msix = rounddown_pow_of_two(err);
-				num_msix += (adapter->max_drv_tx_rings + 1);
+				num_msix += (max_tx_rings + 1);
 			} else {
 				num_msix = rounddown_pow_of_two(err);
 			}
@@ -542,11 +546,10 @@ void qlcnic_teardown_intr(struct qlcnic_adapter *adapter)
 	}
 }
 
-static void
-qlcnic_cleanup_pci_map(struct qlcnic_adapter *adapter)
+static void qlcnic_cleanup_pci_map(struct qlcnic_hardware_context *ahw)
 {
-	if (adapter->ahw->pci_base0 != NULL)
-		iounmap(adapter->ahw->pci_base0);
+	if (ahw->pci_base0 != NULL)
+		iounmap(ahw->pci_base0);
 }
 
 static int qlcnic_get_act_pci_func(struct qlcnic_adapter *adapter)
@@ -721,6 +724,7 @@ static void qlcnic_get_bar_length(u32 dev_id, ulong *bar)
 		*bar = QLCNIC_82XX_BAR0_LENGTH;
 		break;
 	case PCI_DEVICE_ID_QLOGIC_QLE834X:
+	case PCI_DEVICE_ID_QLOGIC_VF_QLE834X:
 		*bar = QLCNIC_83XX_BAR0_LENGTH;
 		break;
 	default:
@@ -751,7 +755,7 @@ static int qlcnic_setup_pci_map(struct pci_dev *pdev,
 		return -EIO;
 	}
 
-	dev_info(&pdev->dev, "%dMB memory map\n", (int)(mem_len>>20));
+	dev_info(&pdev->dev, "%dKB memory map\n", (int)(mem_len >> 10));
 
 	ahw->pci_base0 = mem_ptr0;
 	ahw->pci_len0 = pci_len0;
@@ -1292,7 +1296,8 @@ qlcnic_request_irq(struct qlcnic_adapter *adapter)
 			}
 		}
 		if (qlcnic_83xx_check(adapter) &&
-		    (adapter->flags & QLCNIC_MSIX_ENABLED)) {
+		    (adapter->flags & QLCNIC_MSIX_ENABLED) &&
+		    !(adapter->flags & QLCNIC_TX_INTR_SHARED)) {
 			handler = qlcnic_msix_tx_intr;
 			for (ring = 0; ring < adapter->max_drv_tx_rings;
 			     ring++) {
@@ -1328,7 +1333,8 @@ qlcnic_free_irq(struct qlcnic_adapter *adapter)
 				free_irq(sds_ring->irq, sds_ring);
 			}
 		}
-		if (qlcnic_83xx_check(adapter)) {
+		if (qlcnic_83xx_check(adapter) &&
+		    !(adapter->flags & QLCNIC_TX_INTR_SHARED)) {
 			for (ring = 0; ring < adapter->max_drv_tx_rings;
 			     ring++) {
 				tx_ring = &adapter->tx_ring[ring];
@@ -1418,9 +1424,12 @@ void __qlcnic_down(struct qlcnic_adapter *adapter, struct net_device *netdev)
 	if (!test_and_clear_bit(__QLCNIC_DEV_UP, &adapter->state))
 		return;
 
+	if (qlcnic_sriov_vf_check(adapter))
+		qlcnic_sriov_cleanup_async_list(&adapter->ahw->sriov->bc);
 	smp_mb();
 	spin_lock(&adapter->tx_clean_lock);
 	netif_carrier_off(netdev);
+	adapter->ahw->linkup = 0;
 	netif_tx_disable(netdev);
 
 	qlcnic_free_mac_list(adapter);
@@ -1685,7 +1694,7 @@ qlcnic_reset_context(struct qlcnic_adapter *adapter)
 	return err;
 }
 
-static int
+int
 qlcnic_setup_netdev(struct qlcnic_adapter *adapter, struct net_device *netdev,
 		    int pci_using_dac)
 {
@@ -1820,6 +1829,9 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	u32 capab2;
 	char board_name[QLCNIC_MAX_BOARD_NAME_LEN + 19]; /* MAC + ": " + name */
 
+	if (pdev->is_virtfn)
+		return -ENODEV;
+
 	err = pci_enable_device(pdev);
 	if (err)
 		return err;
@@ -1844,12 +1856,18 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	if (!ahw)
 		goto err_out_free_res;
 
-	if (ent->device == PCI_DEVICE_ID_QLOGIC_QLE824X) {
+	switch (ent->device) {
+	case PCI_DEVICE_ID_QLOGIC_QLE824X:
 		ahw->hw_ops = &qlcnic_hw_ops;
-		ahw->reg_tbl = (u32 *)qlcnic_reg_tbl;
-	} else if (ent->device == PCI_DEVICE_ID_QLOGIC_QLE834X) {
+		ahw->reg_tbl = (u32 *) qlcnic_reg_tbl;
+		break;
+	case PCI_DEVICE_ID_QLOGIC_QLE834X:
 		qlcnic_83xx_register_map(ahw);
-	} else {
+		break;
+	case PCI_DEVICE_ID_QLOGIC_VF_QLE834X:
+		qlcnic_sriov_vf_register_map(ahw);
+		break;
+	default:
 		goto err_out_free_hw_res;
 	}
 
@@ -1911,11 +1929,13 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	} else if (qlcnic_83xx_check(adapter)) {
 		qlcnic_83xx_check_vf(adapter, ent);
 		adapter->portnum = adapter->ahw->pci_func;
-		err = qlcnic_83xx_init(adapter);
+		err = qlcnic_83xx_init(adapter, pci_using_dac);
 		if (err) {
 			dev_err(&pdev->dev, "%s: failed\n", __func__);
 			goto err_out_free_hw;
 		}
+		if (qlcnic_sriov_vf_check(adapter))
+			return 0;
 	} else {
 		dev_err(&pdev->dev,
 			"%s: failed. Please Reboot\n", __func__);
@@ -1932,6 +1952,12 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 			module_name(THIS_MODULE),
 			board_name, adapter->ahw->revision_id);
 	}
+
+	if (qlcnic_83xx_check(adapter) && !qlcnic_use_msi_x &&
+	    !!qlcnic_use_msi)
+		dev_warn(&pdev->dev,
+			 "83xx adapter do not support MSI interrupts\n");
+
 	err = qlcnic_setup_intr(adapter, 0);
 	if (err) {
 		dev_err(&pdev->dev, "Failed to setup interrupt\n");
@@ -1999,7 +2025,7 @@ err_out_free_netdev:
 	free_netdev(netdev);
 
 err_out_iounmap:
-	qlcnic_cleanup_pci_map(adapter);
+	qlcnic_cleanup_pci_map(ahw);
 
 err_out_free_hw_res:
 	kfree(ahw);
@@ -2024,11 +2050,13 @@ static void qlcnic_remove(struct pci_dev *pdev)
 		return;
 
 	netdev = adapter->netdev;
+	qlcnic_sriov_pf_disable(adapter);
 
 	qlcnic_cancel_idc_work(adapter);
 	ahw = adapter->ahw;
 
 	unregister_netdev(netdev);
+	qlcnic_sriov_cleanup(adapter);
 
 	if (qlcnic_83xx_check(adapter)) {
 		qlcnic_83xx_free_mbx_intr(adapter);
@@ -2054,7 +2082,7 @@ static void qlcnic_remove(struct pci_dev *pdev)
 
 	qlcnic_remove_sysfs(adapter);
 
-	qlcnic_cleanup_pci_map(adapter);
+	qlcnic_cleanup_pci_map(adapter->ahw);
 
 	qlcnic_release_firmware(adapter);
 
@@ -3432,7 +3460,10 @@ static struct pci_driver qlcnic_driver = {
 	.resume = qlcnic_resume,
 #endif
 	.shutdown = qlcnic_shutdown,
-	.err_handler = &qlcnic_err_handler
+	.err_handler = &qlcnic_err_handler,
+#ifdef CONFIG_QLCNIC_SRIOV
+	.sriov_configure = qlcnic_pci_sriov_configure,
+#endif
 
 };
 
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c
index abbd22c..4b9bab1 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c
@@ -810,11 +810,8 @@ static int __qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter,
 
 	tmp_addr = dma_alloc_coherent(&adapter->pdev->dev, temp_size,
 				      &tmp_addr_t, GFP_KERNEL);
-	if (!tmp_addr) {
-		dev_err(&adapter->pdev->dev,
-			"Can't get memory for FW dump template\n");
+	if (!tmp_addr)
 		return -ENOMEM;
-	}
 
 	if (qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_TEMP_HDR)) {
 		err = -ENOMEM;
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h
new file mode 100644
index 0000000..b476eba
--- /dev/null
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h
@@ -0,0 +1,214 @@
+/*
+ * QLogic qlcnic NIC Driver
+ * Copyright (c) 2009-2013 QLogic Corporation
+ *
+ * See LICENSE.qlcnic for copyright and licensing details.
+ */
+
+#ifndef _QLCNIC_83XX_SRIOV_H_
+#define _QLCNIC_83XX_SRIOV_H_
+
+#include "qlcnic.h"
+#include <linux/types.h>
+#include <linux/pci.h>
+
+extern const u32 qlcnic_83xx_reg_tbl[];
+extern const u32 qlcnic_83xx_ext_reg_tbl[];
+
+struct qlcnic_bc_payload {
+	u64 payload[126];
+};
+
+struct qlcnic_bc_hdr {
+#if defined(__LITTLE_ENDIAN)
+	u8	version;
+	u8	msg_type:4;
+	u8	rsvd1:3;
+	u8	op_type:1;
+	u8	num_cmds;
+	u8	num_frags;
+	u8	frag_num;
+	u8	cmd_op;
+	u16	seq_id;
+	u64	rsvd3;
+#elif defined(__BIG_ENDIAN)
+	u8	num_frags;
+	u8	num_cmds;
+	u8	op_type:1;
+	u8	rsvd1:3;
+	u8	msg_type:4;
+	u8	version;
+	u16	seq_id;
+	u8	cmd_op;
+	u8	frag_num;
+	u64	rsvd3;
+#endif
+};
+
+enum qlcnic_bc_commands {
+	QLCNIC_BC_CMD_CHANNEL_INIT = 0x0,
+	QLCNIC_BC_CMD_CHANNEL_TERM = 0x1,
+};
+
+#define QLC_BC_CMD 1
+
+struct qlcnic_trans_list {
+	/* Lock for manipulating list */
+	spinlock_t		lock;
+	struct list_head	wait_list;
+	int			count;
+};
+
+enum qlcnic_trans_state {
+	QLC_INIT = 0,
+	QLC_WAIT_FOR_CHANNEL_FREE,
+	QLC_WAIT_FOR_RESP,
+	QLC_ABORT,
+	QLC_END,
+};
+
+struct qlcnic_bc_trans {
+	u8				func_id;
+	u8				active;
+	u8				curr_rsp_frag;
+	u8				curr_req_frag;
+	u16				cmd_id;
+	u16				req_pay_size;
+	u16				rsp_pay_size;
+	u32				trans_id;
+	enum qlcnic_trans_state		trans_state;
+	struct list_head		list;
+	struct qlcnic_bc_hdr		*req_hdr;
+	struct qlcnic_bc_hdr		*rsp_hdr;
+	struct qlcnic_bc_payload	*req_pay;
+	struct qlcnic_bc_payload	*rsp_pay;
+	struct completion		resp_cmpl;
+	struct qlcnic_vf_info		*vf;
+};
+
+enum qlcnic_vf_state {
+	QLC_BC_VF_SEND = 0,
+	QLC_BC_VF_RECV,
+	QLC_BC_VF_CHANNEL,
+	QLC_BC_VF_STATE,
+};
+
+struct qlcnic_resources {
+	u16 num_tx_mac_filters;
+	u16 num_rx_ucast_mac_filters;
+	u16 num_rx_mcast_mac_filters;
+
+	u16 num_txvlan_keys;
+
+	u16 num_rx_queues;
+	u16 num_tx_queues;
+
+	u16 num_rx_buf_rings;
+	u16 num_rx_status_rings;
+
+	u16 num_destip;
+	u32 num_lro_flows_supported;
+	u16 max_local_ipv6_addrs;
+	u16 max_remote_ipv6_addrs;
+};
+
+struct qlcnic_vport {
+	u16			handle;
+	u8			mac[6];
+};
+
+struct qlcnic_vf_info {
+	u8				pci_func;
+	u16				rx_ctx_id;
+	u16				tx_ctx_id;
+	unsigned long			state;
+	struct completion		ch_free_cmpl;
+	struct work_struct		trans_work;
+	/* It synchronizes commands sent from VF */
+	struct mutex			send_cmd_lock;
+	struct qlcnic_bc_trans		*send_cmd;
+	struct qlcnic_trans_list	rcv_act;
+	struct qlcnic_trans_list	rcv_pend;
+	struct qlcnic_adapter		*adapter;
+	struct qlcnic_vport		*vp;
+};
+
+struct qlcnic_async_work_list {
+	struct list_head	list;
+	struct work_struct	work;
+	void			*ptr;
+};
+
+struct qlcnic_back_channel {
+	u16			trans_counter;
+	struct workqueue_struct *bc_trans_wq;
+	struct workqueue_struct *bc_async_wq;
+	struct list_head	async_list;
+};
+
+struct qlcnic_sriov {
+	u16				vp_handle;
+	u8				num_vfs;
+	struct qlcnic_resources		ff_max;
+	struct qlcnic_back_channel	bc;
+	struct qlcnic_vf_info		*vf_info;
+};
+
+int qlcnic_sriov_init(struct qlcnic_adapter *, int);
+void qlcnic_sriov_cleanup(struct qlcnic_adapter *);
+void __qlcnic_sriov_cleanup(struct qlcnic_adapter *);
+void qlcnic_sriov_vf_register_map(struct qlcnic_hardware_context *);
+int qlcnic_sriov_vf_init(struct qlcnic_adapter *, int);
+void qlcnic_sriov_vf_set_ops(struct qlcnic_adapter *);
+int qlcnic_sriov_func_to_index(struct qlcnic_adapter *, u8);
+int qlcnic_sriov_channel_cfg_cmd(struct qlcnic_adapter *, u8);
+void qlcnic_sriov_handle_bc_event(struct qlcnic_adapter *, u32);
+int qlcnic_sriov_cfg_bc_intr(struct qlcnic_adapter *, u8);
+void qlcnic_sriov_cleanup_async_list(struct qlcnic_back_channel *);
+
+static inline bool qlcnic_sriov_enable_check(struct qlcnic_adapter *adapter)
+{
+	return test_bit(__QLCNIC_SRIOV_ENABLE, &adapter->state) ? true : false;
+}
+
+#ifdef CONFIG_QLCNIC_SRIOV
+void qlcnic_sriov_pf_process_bc_cmd(struct qlcnic_adapter *,
+				    struct qlcnic_bc_trans *,
+				    struct qlcnic_cmd_args *);
+void qlcnic_sriov_pf_disable(struct qlcnic_adapter *);
+void qlcnic_sriov_pf_cleanup(struct qlcnic_adapter *);
+int qlcnic_pci_sriov_configure(struct pci_dev *, int);
+void qlcnic_pf_set_interface_id_create_rx_ctx(struct qlcnic_adapter *, u32 *);
+void qlcnic_pf_set_interface_id_create_tx_ctx(struct qlcnic_adapter *, u32 *);
+void qlcnic_pf_set_interface_id_del_rx_ctx(struct qlcnic_adapter *, u32 *);
+void qlcnic_pf_set_interface_id_del_tx_ctx(struct qlcnic_adapter *, u32 *);
+void qlcnic_pf_set_interface_id_promisc(struct qlcnic_adapter *, u32 *);
+void qlcnic_pf_set_interface_id_ipaddr(struct qlcnic_adapter *, u32 *);
+void qlcnic_pf_set_interface_id_macaddr(struct qlcnic_adapter *, u32 *);
+#else
+static inline void qlcnic_sriov_pf_disable(struct qlcnic_adapter *adapter) {}
+static inline void qlcnic_sriov_pf_cleanup(struct qlcnic_adapter *adapter) {}
+static inline void
+qlcnic_pf_set_interface_id_create_rx_ctx(struct qlcnic_adapter *adapter,
+					 u32 *int_id) {}
+static inline void
+qlcnic_pf_set_interface_id_create_tx_ctx(struct qlcnic_adapter *adapter,
+					 u32 *int_id) {}
+static inline void
+qlcnic_pf_set_interface_id_del_rx_ctx(struct qlcnic_adapter *adapter,
+				      u32 *int_id) {}
+static inline void
+qlcnic_pf_set_interface_id_del_tx_ctx(struct qlcnic_adapter *adapter,
+				      u32 *int_id) {}
+static inline void
+qlcnic_pf_set_interface_id_ipaddr(struct qlcnic_adapter *adapter, u32 *int_id)
+{}
+static inline void
+qlcnic_pf_set_interface_id_macaddr(struct qlcnic_adapter *adapter, u32 *int_id)
+{}
+static inline void
+qlcnic_pf_set_interface_id_promisc(struct qlcnic_adapter *adapter, u32 *int_id)
+{}
+#endif
+
+#endif
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c
new file mode 100644
index 0000000..14e9ebd
--- /dev/null
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c
@@ -0,0 +1,1297 @@
+/*
+ * QLogic qlcnic NIC Driver
+ * Copyright (c) 2009-2013 QLogic Corporation
+ *
+ * See LICENSE.qlcnic for copyright and licensing details.
+ */
+
+#include "qlcnic_sriov.h"
+#include "qlcnic.h"
+#include "qlcnic_83xx_hw.h"
+#include <linux/types.h>
+
+#define QLC_BC_COMMAND	0
+#define QLC_BC_RESPONSE	1
+
+#define QLC_MBOX_RESP_TIMEOUT		(10 * HZ)
+#define QLC_MBOX_CH_FREE_TIMEOUT	(10 * HZ)
+
+#define QLC_BC_MSG		0
+#define QLC_BC_CFREE		1
+#define QLC_BC_HDR_SZ		16
+#define QLC_BC_PAYLOAD_SZ	(1024 - QLC_BC_HDR_SZ)
+
+#define QLC_DEFAULT_RCV_DESCRIPTORS_SRIOV_VF		2048
+#define QLC_DEFAULT_JUMBO_RCV_DESCRIPTORS_SRIOV_VF	512
+
+static int qlcnic_sriov_vf_mbx_op(struct qlcnic_adapter *,
+				  struct qlcnic_cmd_args *);
+
+static struct qlcnic_hardware_ops qlcnic_sriov_vf_hw_ops = {
+	.read_crb			= qlcnic_83xx_read_crb,
+	.write_crb			= qlcnic_83xx_write_crb,
+	.read_reg			= qlcnic_83xx_rd_reg_indirect,
+	.write_reg			= qlcnic_83xx_wrt_reg_indirect,
+	.get_mac_address		= qlcnic_83xx_get_mac_address,
+	.setup_intr			= qlcnic_83xx_setup_intr,
+	.alloc_mbx_args			= qlcnic_83xx_alloc_mbx_args,
+	.mbx_cmd			= qlcnic_sriov_vf_mbx_op,
+	.get_func_no			= qlcnic_83xx_get_func_no,
+	.api_lock			= qlcnic_83xx_cam_lock,
+	.api_unlock			= qlcnic_83xx_cam_unlock,
+	.process_lb_rcv_ring_diag	= qlcnic_83xx_process_rcv_ring_diag,
+	.create_rx_ctx			= qlcnic_83xx_create_rx_ctx,
+	.create_tx_ctx			= qlcnic_83xx_create_tx_ctx,
+	.del_rx_ctx			= qlcnic_83xx_del_rx_ctx,
+	.del_tx_ctx			= qlcnic_83xx_del_tx_ctx,
+	.setup_link_event		= qlcnic_83xx_setup_link_event,
+	.get_nic_info			= qlcnic_83xx_get_nic_info,
+	.get_pci_info			= qlcnic_83xx_get_pci_info,
+	.set_nic_info			= qlcnic_83xx_set_nic_info,
+	.change_macvlan			= qlcnic_83xx_sre_macaddr_change,
+	.napi_enable			= qlcnic_83xx_napi_enable,
+	.napi_disable			= qlcnic_83xx_napi_disable,
+	.config_intr_coal		= qlcnic_83xx_config_intr_coal,
+	.config_rss			= qlcnic_83xx_config_rss,
+	.config_hw_lro			= qlcnic_83xx_config_hw_lro,
+	.config_promisc_mode		= qlcnic_83xx_nic_set_promisc,
+	.change_l2_filter		= qlcnic_83xx_change_l2_filter,
+	.get_board_info			= qlcnic_83xx_get_port_info,
+};
+
+static struct qlcnic_nic_template qlcnic_sriov_vf_ops = {
+	.config_bridged_mode	= qlcnic_config_bridged_mode,
+	.config_led		= qlcnic_config_led,
+	.cancel_idc_work        = qlcnic_83xx_idc_exit,
+	.napi_add		= qlcnic_83xx_napi_add,
+	.napi_del		= qlcnic_83xx_napi_del,
+	.config_ipaddr		= qlcnic_83xx_config_ipaddr,
+	.clear_legacy_intr	= qlcnic_83xx_clear_legacy_intr,
+};
+
+static const struct qlcnic_mailbox_metadata qlcnic_sriov_bc_mbx_tbl[] = {
+	{QLCNIC_BC_CMD_CHANNEL_INIT, 2, 2},
+	{QLCNIC_BC_CMD_CHANNEL_TERM, 2, 2},
+};
+
+static inline bool qlcnic_sriov_bc_msg_check(u32 val)
+{
+	return (val & (1 << QLC_BC_MSG)) ? true : false;
+}
+
+static inline bool qlcnic_sriov_channel_free_check(u32 val)
+{
+	return (val & (1 << QLC_BC_CFREE)) ? true : false;
+}
+
+static inline u8 qlcnic_sriov_target_func_id(u32 val)
+{
+	return (val >> 4) & 0xff;
+}
+
+static int qlcnic_sriov_virtid_fn(struct qlcnic_adapter *adapter, int vf_id)
+{
+	struct pci_dev *dev = adapter->pdev;
+	int pos;
+	u16 stride, offset;
+
+	if (qlcnic_sriov_vf_check(adapter))
+		return 0;
+
+	pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_SRIOV);
+	pci_read_config_word(dev, pos + PCI_SRIOV_VF_OFFSET, &offset);
+	pci_read_config_word(dev, pos + PCI_SRIOV_VF_STRIDE, &stride);
+
+	return (dev->devfn + offset + stride * vf_id) & 0xff;
+}
+
+int qlcnic_sriov_init(struct qlcnic_adapter *adapter, int num_vfs)
+{
+	struct qlcnic_sriov *sriov;
+	struct qlcnic_back_channel *bc;
+	struct workqueue_struct *wq;
+	struct qlcnic_vport *vp;
+	struct qlcnic_vf_info *vf;
+	int err, i;
+
+	if (!qlcnic_sriov_enable_check(adapter))
+		return -EIO;
+
+	sriov  = kzalloc(sizeof(struct qlcnic_sriov), GFP_KERNEL);
+	if (!sriov)
+		return -ENOMEM;
+
+	adapter->ahw->sriov = sriov;
+	sriov->num_vfs = num_vfs;
+	bc = &sriov->bc;
+	sriov->vf_info = kzalloc(sizeof(struct qlcnic_vf_info) *
+				 num_vfs, GFP_KERNEL);
+	if (!sriov->vf_info) {
+		err = -ENOMEM;
+		goto qlcnic_free_sriov;
+	}
+
+	wq = create_singlethread_workqueue("bc-trans");
+	if (wq == NULL) {
+		err = -ENOMEM;
+		dev_err(&adapter->pdev->dev,
+			"Cannot create bc-trans workqueue\n");
+		goto qlcnic_free_vf_info;
+	}
+
+	bc->bc_trans_wq = wq;
+
+	wq = create_singlethread_workqueue("async");
+	if (wq == NULL) {
+		err = -ENOMEM;
+		dev_err(&adapter->pdev->dev, "Cannot create async workqueue\n");
+		goto qlcnic_destroy_trans_wq;
+	}
+
+	bc->bc_async_wq =  wq;
+	INIT_LIST_HEAD(&bc->async_list);
+
+	for (i = 0; i < num_vfs; i++) {
+		vf = &sriov->vf_info[i];
+		vf->adapter = adapter;
+		vf->pci_func = qlcnic_sriov_virtid_fn(adapter, i);
+		mutex_init(&vf->send_cmd_lock);
+		INIT_LIST_HEAD(&vf->rcv_act.wait_list);
+		INIT_LIST_HEAD(&vf->rcv_pend.wait_list);
+		spin_lock_init(&vf->rcv_act.lock);
+		spin_lock_init(&vf->rcv_pend.lock);
+		init_completion(&vf->ch_free_cmpl);
+
+		if (qlcnic_sriov_pf_check(adapter)) {
+			vp = kzalloc(sizeof(struct qlcnic_vport), GFP_KERNEL);
+			if (!vp) {
+				err = -ENOMEM;
+				goto qlcnic_destroy_async_wq;
+			}
+			sriov->vf_info[i].vp = vp;
+			random_ether_addr(vp->mac);
+			dev_info(&adapter->pdev->dev,
+				 "MAC Address %pM is configured for VF %d\n",
+				 vp->mac, i);
+		}
+	}
+
+	return 0;
+
+qlcnic_destroy_async_wq:
+	destroy_workqueue(bc->bc_async_wq);
+
+qlcnic_destroy_trans_wq:
+	destroy_workqueue(bc->bc_trans_wq);
+
+qlcnic_free_vf_info:
+	kfree(sriov->vf_info);
+
+qlcnic_free_sriov:
+	kfree(adapter->ahw->sriov);
+	return err;
+}
+
+void __qlcnic_sriov_cleanup(struct qlcnic_adapter *adapter)
+{
+	struct qlcnic_sriov *sriov = adapter->ahw->sriov;
+	struct qlcnic_back_channel *bc = &sriov->bc;
+	int i;
+
+	if (!qlcnic_sriov_enable_check(adapter))
+		return;
+
+	qlcnic_sriov_cleanup_async_list(bc);
+	destroy_workqueue(bc->bc_async_wq);
+	destroy_workqueue(bc->bc_trans_wq);
+
+	for (i = 0; i < sriov->num_vfs; i++)
+		kfree(sriov->vf_info[i].vp);
+
+	kfree(sriov->vf_info);
+	kfree(adapter->ahw->sriov);
+}
+
+static void qlcnic_sriov_vf_cleanup(struct qlcnic_adapter *adapter)
+{
+	qlcnic_sriov_channel_cfg_cmd(adapter, QLCNIC_BC_CMD_CHANNEL_TERM);
+	qlcnic_sriov_cfg_bc_intr(adapter, 0);
+	__qlcnic_sriov_cleanup(adapter);
+}
+
+void qlcnic_sriov_cleanup(struct qlcnic_adapter *adapter)
+{
+	if (qlcnic_sriov_pf_check(adapter))
+		qlcnic_sriov_pf_cleanup(adapter);
+
+	if (qlcnic_sriov_vf_check(adapter))
+		qlcnic_sriov_vf_cleanup(adapter);
+}
+
+static int qlcnic_sriov_post_bc_msg(struct qlcnic_adapter *adapter, u32 *hdr,
+				    u32 *pay, u8 pci_func, u8 size)
+{
+	struct qlcnic_hardware_context *ahw = adapter->ahw;
+	unsigned long flags;
+	u32 rsp, mbx_val, fw_data, rsp_num, mbx_cmd, val;
+	u16 opcode;
+	u8 mbx_err_code;
+	int i, j;
+
+	opcode = ((struct qlcnic_bc_hdr *)hdr)->cmd_op;
+
+	if (!test_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status)) {
+		dev_info(&adapter->pdev->dev,
+			 "Mailbox cmd attempted, 0x%x\n", opcode);
+		dev_info(&adapter->pdev->dev, "Mailbox detached\n");
+		return 0;
+	}
+
+	spin_lock_irqsave(&ahw->mbx_lock, flags);
+
+	mbx_val = QLCRDX(ahw, QLCNIC_HOST_MBX_CTRL);
+	if (mbx_val) {
+		QLCDB(adapter, DRV, "Mailbox cmd attempted, 0x%x\n", opcode);
+		spin_unlock_irqrestore(&ahw->mbx_lock, flags);
+		return QLCNIC_RCODE_TIMEOUT;
+	}
+	/* Fill in mailbox registers */
+	val = size + (sizeof(struct qlcnic_bc_hdr) / sizeof(u32));
+	mbx_cmd = 0x31 | (val << 16) | (adapter->ahw->fw_hal_version << 29);
+
+	writel(mbx_cmd, QLCNIC_MBX_HOST(ahw, 0));
+	mbx_cmd = 0x1 | (1 << 4);
+
+	if (qlcnic_sriov_pf_check(adapter))
+		mbx_cmd |= (pci_func << 5);
+
+	writel(mbx_cmd, QLCNIC_MBX_HOST(ahw, 1));
+	for (i = 2, j = 0; j < (sizeof(struct qlcnic_bc_hdr) / sizeof(u32));
+			i++, j++) {
+		writel(*(hdr++), QLCNIC_MBX_HOST(ahw, i));
+	}
+	for (j = 0; j < size; j++, i++)
+		writel(*(pay++), QLCNIC_MBX_HOST(ahw, i));
+
+	/* Signal FW about the impending command */
+	QLCWRX(ahw, QLCNIC_HOST_MBX_CTRL, QLCNIC_SET_OWNER);
+
+	/* Waiting for the mailbox cmd to complete and while waiting here
+	 * some AEN might arrive. If more than 5 seconds expire we can
+	 * assume something is wrong.
+	 */
+poll:
+	rsp = qlcnic_83xx_mbx_poll(adapter);
+	if (rsp != QLCNIC_RCODE_TIMEOUT) {
+		/* Get the FW response data */
+		fw_data = readl(QLCNIC_MBX_FW(ahw, 0));
+		if (fw_data &  QLCNIC_MBX_ASYNC_EVENT) {
+			qlcnic_83xx_process_aen(adapter);
+			mbx_val = QLCRDX(ahw, QLCNIC_HOST_MBX_CTRL);
+			if (mbx_val)
+				goto poll;
+		}
+		mbx_err_code = QLCNIC_MBX_STATUS(fw_data);
+		rsp_num = QLCNIC_MBX_NUM_REGS(fw_data);
+		opcode = QLCNIC_MBX_RSP(fw_data);
+
+		switch (mbx_err_code) {
+		case QLCNIC_MBX_RSP_OK:
+		case QLCNIC_MBX_PORT_RSP_OK:
+			rsp = QLCNIC_RCODE_SUCCESS;
+			break;
+		default:
+			if (opcode == QLCNIC_CMD_CONFIG_MAC_VLAN) {
+				rsp = qlcnic_83xx_mac_rcode(adapter);
+				if (!rsp)
+					goto out;
+			}
+			dev_err(&adapter->pdev->dev,
+				"MBX command 0x%x failed with err:0x%x\n",
+				opcode, mbx_err_code);
+			rsp = mbx_err_code;
+			break;
+		}
+		goto out;
+	}
+
+	dev_err(&adapter->pdev->dev, "MBX command 0x%x timed out\n",
+		QLCNIC_MBX_RSP(mbx_cmd));
+	rsp = QLCNIC_RCODE_TIMEOUT;
+out:
+	/* clear fw mbx control register */
+	QLCWRX(ahw, QLCNIC_FW_MBX_CTRL, QLCNIC_CLR_OWNER);
+	spin_unlock_irqrestore(&adapter->ahw->mbx_lock, flags);
+	return rsp;
+}
+
+static void qlcnic_sriov_vf_cfg_buff_desc(struct qlcnic_adapter *adapter)
+{
+	adapter->num_rxd = QLC_DEFAULT_RCV_DESCRIPTORS_SRIOV_VF;
+	adapter->max_rxd = MAX_RCV_DESCRIPTORS_10G;
+	adapter->num_jumbo_rxd = QLC_DEFAULT_JUMBO_RCV_DESCRIPTORS_SRIOV_VF;
+	adapter->max_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_10G;
+	adapter->num_txd = MAX_CMD_DESCRIPTORS;
+	adapter->max_rds_rings = MAX_RDS_RINGS;
+}
+
+static int qlcnic_sriov_vf_init_driver(struct qlcnic_adapter *adapter)
+{
+	struct qlcnic_info nic_info;
+	struct qlcnic_hardware_context *ahw = adapter->ahw;
+	int err;
+
+	err = qlcnic_get_nic_info(adapter, &nic_info, ahw->pci_func);
+	if (err)
+		return -EIO;
+
+	if (qlcnic_83xx_get_port_info(adapter))
+		return -EIO;
+
+	qlcnic_sriov_vf_cfg_buff_desc(adapter);
+	adapter->flags |= QLCNIC_ADAPTER_INITIALIZED;
+	dev_info(&adapter->pdev->dev, "HAL Version: %d\n",
+		 adapter->ahw->fw_hal_version);
+
+	ahw->physical_port = (u8) nic_info.phys_port;
+	ahw->switch_mode = nic_info.switch_mode;
+	ahw->max_mtu = nic_info.max_mtu;
+	ahw->op_mode = nic_info.op_mode;
+	ahw->capabilities = nic_info.capabilities;
+	return 0;
+}
+
+static int qlcnic_sriov_setup_vf(struct qlcnic_adapter *adapter,
+				 int pci_using_dac)
+{
+	int err;
+
+	INIT_LIST_HEAD(&adapter->vf_mc_list);
+	if (!qlcnic_use_msi_x && !!qlcnic_use_msi)
+		dev_warn(&adapter->pdev->dev,
+			 "83xx adapter do not support MSI interrupts\n");
+
+	err = qlcnic_setup_intr(adapter, 1);
+	if (err) {
+		dev_err(&adapter->pdev->dev, "Failed to setup interrupt\n");
+		goto err_out_disable_msi;
+	}
+
+	err = qlcnic_83xx_setup_mbx_intr(adapter);
+	if (err)
+		goto err_out_disable_msi;
+
+	err = qlcnic_sriov_init(adapter, 1);
+	if (err)
+		goto err_out_disable_mbx_intr;
+
+	err = qlcnic_sriov_cfg_bc_intr(adapter, 1);
+	if (err)
+		goto err_out_cleanup_sriov;
+
+	err = qlcnic_sriov_channel_cfg_cmd(adapter, QLCNIC_BC_CMD_CHANNEL_INIT);
+	if (err)
+		goto err_out_disable_bc_intr;
+
+	err = qlcnic_sriov_vf_init_driver(adapter);
+	if (err)
+		goto err_out_send_channel_term;
+
+	err = qlcnic_setup_netdev(adapter, adapter->netdev, pci_using_dac);
+	if (err)
+		goto err_out_send_channel_term;
+
+	pci_set_drvdata(adapter->pdev, adapter);
+	dev_info(&adapter->pdev->dev, "%s: XGbE port initialized\n",
+		 adapter->netdev->name);
+	return 0;
+
+err_out_send_channel_term:
+	qlcnic_sriov_channel_cfg_cmd(adapter, QLCNIC_BC_CMD_CHANNEL_TERM);
+
+err_out_disable_bc_intr:
+	qlcnic_sriov_cfg_bc_intr(adapter, 0);
+
+err_out_cleanup_sriov:
+	__qlcnic_sriov_cleanup(adapter);
+
+err_out_disable_mbx_intr:
+	qlcnic_83xx_free_mbx_intr(adapter);
+
+err_out_disable_msi:
+	qlcnic_teardown_intr(adapter);
+	return err;
+}
+
+int qlcnic_sriov_vf_init(struct qlcnic_adapter *adapter, int pci_using_dac)
+{
+	struct qlcnic_hardware_context *ahw = adapter->ahw;
+
+	spin_lock_init(&ahw->mbx_lock);
+	set_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status);
+	ahw->msix_supported = 1;
+	adapter->flags |= QLCNIC_TX_INTR_SHARED;
+
+	if (qlcnic_sriov_setup_vf(adapter, pci_using_dac))
+		return -EIO;
+
+	if (qlcnic_read_mac_addr(adapter))
+		dev_warn(&adapter->pdev->dev, "failed to read mac addr\n");
+
+	set_bit(QLC_83XX_MODULE_LOADED, &adapter->ahw->idc.status);
+	adapter->ahw->idc.delay = QLC_83XX_IDC_FW_POLL_DELAY;
+	adapter->ahw->reset_context = 0;
+	adapter->fw_fail_cnt = 0;
+	clear_bit(__QLCNIC_RESETTING, &adapter->state);
+	adapter->need_fw_reset = 0;
+	return 0;
+}
+
+void qlcnic_sriov_vf_set_ops(struct qlcnic_adapter *adapter)
+{
+	struct qlcnic_hardware_context *ahw = adapter->ahw;
+
+	ahw->op_mode = QLCNIC_SRIOV_VF_FUNC;
+	dev_info(&adapter->pdev->dev,
+		 "HAL Version: %d Non Privileged SRIOV function\n",
+		 ahw->fw_hal_version);
+	adapter->nic_ops = &qlcnic_sriov_vf_ops;
+	set_bit(__QLCNIC_SRIOV_ENABLE, &adapter->state);
+	return;
+}
+
+void qlcnic_sriov_vf_register_map(struct qlcnic_hardware_context *ahw)
+{
+	ahw->hw_ops		= &qlcnic_sriov_vf_hw_ops;
+	ahw->reg_tbl		= (u32 *)qlcnic_83xx_reg_tbl;
+	ahw->ext_reg_tbl	= (u32 *)qlcnic_83xx_ext_reg_tbl;
+}
+
+static u32 qlcnic_sriov_get_bc_paysize(u32 real_pay_size, u8 curr_frag)
+{
+	u32 pay_size;
+
+	pay_size = real_pay_size / ((curr_frag + 1) * QLC_BC_PAYLOAD_SZ);
+
+	if (pay_size)
+		pay_size = QLC_BC_PAYLOAD_SZ;
+	else
+		pay_size = real_pay_size % QLC_BC_PAYLOAD_SZ;
+
+	return pay_size;
+}
+
+int qlcnic_sriov_func_to_index(struct qlcnic_adapter *adapter, u8 pci_func)
+{
+	struct qlcnic_vf_info *vf_info = adapter->ahw->sriov->vf_info;
+	u8 i;
+
+	if (qlcnic_sriov_vf_check(adapter))
+		return 0;
+
+	for (i = 0; i < adapter->ahw->sriov->num_vfs; i++) {
+		if (vf_info[i].pci_func == pci_func)
+			return i;
+	}
+
+	return -EINVAL;
+}
+
+static inline int qlcnic_sriov_alloc_bc_trans(struct qlcnic_bc_trans **trans)
+{
+	*trans = kzalloc(sizeof(struct qlcnic_bc_trans), GFP_ATOMIC);
+	if (!*trans)
+		return -ENOMEM;
+
+	init_completion(&(*trans)->resp_cmpl);
+	return 0;
+}
+
+static inline int qlcnic_sriov_alloc_bc_msg(struct qlcnic_bc_hdr **hdr,
+					    u32 size)
+{
+	*hdr = kzalloc(sizeof(struct qlcnic_bc_hdr) * size, GFP_ATOMIC);
+	if (!*hdr)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static int qlcnic_sriov_alloc_bc_mbx_args(struct qlcnic_cmd_args *mbx, u32 type)
+{
+	const struct qlcnic_mailbox_metadata *mbx_tbl;
+	int i, size;
+
+	mbx_tbl = qlcnic_sriov_bc_mbx_tbl;
+	size = ARRAY_SIZE(qlcnic_sriov_bc_mbx_tbl);
+
+	for (i = 0; i < size; i++) {
+		if (type == mbx_tbl[i].cmd) {
+			mbx->op_type = QLC_BC_CMD;
+			mbx->req.num = mbx_tbl[i].in_args;
+			mbx->rsp.num = mbx_tbl[i].out_args;
+			mbx->req.arg = kcalloc(mbx->req.num, sizeof(u32),
+					       GFP_ATOMIC);
+			if (!mbx->req.arg)
+				return -ENOMEM;
+			mbx->rsp.arg = kcalloc(mbx->rsp.num, sizeof(u32),
+					       GFP_ATOMIC);
+			if (!mbx->rsp.arg) {
+				kfree(mbx->req.arg);
+				mbx->req.arg = NULL;
+				return -ENOMEM;
+			}
+			memset(mbx->req.arg, 0, sizeof(u32) * mbx->req.num);
+			memset(mbx->rsp.arg, 0, sizeof(u32) * mbx->rsp.num);
+			mbx->req.arg[0] = (type | (mbx->req.num << 16) |
+					   (3 << 29));
+			return 0;
+		}
+	}
+	return -EINVAL;
+}
+
+static int qlcnic_sriov_prepare_bc_hdr(struct qlcnic_bc_trans *trans,
+				       struct qlcnic_cmd_args *cmd,
+				       u16 seq, u8 msg_type)
+{
+	struct qlcnic_bc_hdr *hdr;
+	int i;
+	u32 num_regs, bc_pay_sz;
+	u16 remainder;
+	u8 cmd_op, num_frags, t_num_frags;
+
+	bc_pay_sz = QLC_BC_PAYLOAD_SZ;
+	if (msg_type == QLC_BC_COMMAND) {
+		trans->req_pay = (struct qlcnic_bc_payload *)cmd->req.arg;
+		trans->rsp_pay = (struct qlcnic_bc_payload *)cmd->rsp.arg;
+		num_regs = cmd->req.num;
+		trans->req_pay_size = (num_regs * 4);
+		num_regs = cmd->rsp.num;
+		trans->rsp_pay_size = (num_regs * 4);
+		cmd_op = cmd->req.arg[0] & 0xff;
+		remainder = (trans->req_pay_size) % (bc_pay_sz);
+		num_frags = (trans->req_pay_size) / (bc_pay_sz);
+		if (remainder)
+			num_frags++;
+		t_num_frags = num_frags;
+		if (qlcnic_sriov_alloc_bc_msg(&trans->req_hdr, num_frags))
+			return -ENOMEM;
+		remainder = (trans->rsp_pay_size) % (bc_pay_sz);
+		num_frags = (trans->rsp_pay_size) / (bc_pay_sz);
+		if (remainder)
+			num_frags++;
+		if (qlcnic_sriov_alloc_bc_msg(&trans->rsp_hdr, num_frags))
+			return -ENOMEM;
+		num_frags  = t_num_frags;
+		hdr = trans->req_hdr;
+	}  else {
+		cmd->req.arg = (u32 *)trans->req_pay;
+		cmd->rsp.arg = (u32 *)trans->rsp_pay;
+		cmd_op = cmd->req.arg[0] & 0xff;
+		remainder = (trans->rsp_pay_size) % (bc_pay_sz);
+		num_frags = (trans->rsp_pay_size) / (bc_pay_sz);
+		if (remainder)
+			num_frags++;
+		cmd->req.num = trans->req_pay_size / 4;
+		cmd->rsp.num = trans->rsp_pay_size / 4;
+		hdr = trans->rsp_hdr;
+	}
+
+	trans->trans_id = seq;
+	trans->cmd_id = cmd_op;
+	for (i = 0; i < num_frags; i++) {
+		hdr[i].version = 2;
+		hdr[i].msg_type = msg_type;
+		hdr[i].op_type = cmd->op_type;
+		hdr[i].num_cmds = 1;
+		hdr[i].num_frags = num_frags;
+		hdr[i].frag_num = i + 1;
+		hdr[i].cmd_op = cmd_op;
+		hdr[i].seq_id = seq;
+	}
+	return 0;
+}
+
+static void qlcnic_sriov_cleanup_transaction(struct qlcnic_bc_trans *trans)
+{
+	if (!trans)
+		return;
+	kfree(trans->req_hdr);
+	kfree(trans->rsp_hdr);
+	kfree(trans);
+}
+
+static int qlcnic_sriov_clear_trans(struct qlcnic_vf_info *vf,
+				    struct qlcnic_bc_trans *trans, u8 type)
+{
+	struct qlcnic_trans_list *t_list;
+	unsigned long flags;
+	int ret = 0;
+
+	if (type == QLC_BC_RESPONSE) {
+		t_list = &vf->rcv_act;
+		spin_lock_irqsave(&t_list->lock, flags);
+		t_list->count--;
+		list_del(&trans->list);
+		if (t_list->count > 0)
+			ret = 1;
+		spin_unlock_irqrestore(&t_list->lock, flags);
+	}
+	if (type == QLC_BC_COMMAND) {
+		while (test_and_set_bit(QLC_BC_VF_SEND, &vf->state))
+			msleep(100);
+		vf->send_cmd = NULL;
+		clear_bit(QLC_BC_VF_SEND, &vf->state);
+	}
+	return ret;
+}
+
+static void qlcnic_sriov_schedule_bc_cmd(struct qlcnic_sriov *sriov,
+					 struct qlcnic_vf_info *vf,
+					 work_func_t func)
+{
+	INIT_WORK(&vf->trans_work, func);
+	queue_work(sriov->bc.bc_trans_wq, &vf->trans_work);
+}
+
+static inline void qlcnic_sriov_wait_for_resp(struct qlcnic_bc_trans *trans)
+{
+	struct completion *cmpl = &trans->resp_cmpl;
+
+	if (wait_for_completion_timeout(cmpl, QLC_MBOX_RESP_TIMEOUT))
+		trans->trans_state = QLC_END;
+	else
+		trans->trans_state = QLC_ABORT;
+
+	return;
+}
+
+static void qlcnic_sriov_handle_multi_frags(struct qlcnic_bc_trans *trans,
+					    u8 type)
+{
+	if (type == QLC_BC_RESPONSE) {
+		trans->curr_rsp_frag++;
+		if (trans->curr_rsp_frag < trans->rsp_hdr->num_frags)
+			trans->trans_state = QLC_INIT;
+		else
+			trans->trans_state = QLC_END;
+	} else {
+		trans->curr_req_frag++;
+		if (trans->curr_req_frag < trans->req_hdr->num_frags)
+			trans->trans_state = QLC_INIT;
+		else
+			trans->trans_state = QLC_WAIT_FOR_RESP;
+	}
+}
+
+static void qlcnic_sriov_wait_for_channel_free(struct qlcnic_bc_trans *trans,
+					       u8 type)
+{
+	struct qlcnic_vf_info *vf = trans->vf;
+	struct completion *cmpl = &vf->ch_free_cmpl;
+
+	if (!wait_for_completion_timeout(cmpl, QLC_MBOX_CH_FREE_TIMEOUT)) {
+		trans->trans_state = QLC_ABORT;
+		return;
+	}
+
+	clear_bit(QLC_BC_VF_CHANNEL, &vf->state);
+	qlcnic_sriov_handle_multi_frags(trans, type);
+}
+
+static void qlcnic_sriov_pull_bc_msg(struct qlcnic_adapter *adapter,
+				     u32 *hdr, u32 *pay, u32 size)
+{
+	struct qlcnic_hardware_context *ahw = adapter->ahw;
+	u32 fw_mbx;
+	u8 i, max = 2, hdr_size, j;
+
+	hdr_size = (sizeof(struct qlcnic_bc_hdr) / sizeof(u32));
+	max = (size / sizeof(u32)) + hdr_size;
+
+	fw_mbx = readl(QLCNIC_MBX_FW(ahw, 0));
+	for (i = 2, j = 0; j < hdr_size; i++, j++)
+		*(hdr++) = readl(QLCNIC_MBX_FW(ahw, i));
+	for (; j < max; i++, j++)
+		*(pay++) = readl(QLCNIC_MBX_FW(ahw, i));
+}
+
+static int __qlcnic_sriov_issue_bc_post(struct qlcnic_vf_info *vf)
+{
+	int ret = -EBUSY;
+	u32 timeout = 10000;
+
+	do {
+		if (!test_and_set_bit(QLC_BC_VF_CHANNEL, &vf->state)) {
+			ret = 0;
+			break;
+		}
+		mdelay(1);
+	} while (--timeout);
+
+	return ret;
+}
+
+static int qlcnic_sriov_issue_bc_post(struct qlcnic_bc_trans *trans, u8 type)
+{
+	struct qlcnic_vf_info *vf = trans->vf;
+	u32 pay_size, hdr_size;
+	u32 *hdr, *pay;
+	int ret;
+	u8 pci_func = trans->func_id;
+
+	if (__qlcnic_sriov_issue_bc_post(vf))
+		return -EBUSY;
+
+	if (type == QLC_BC_COMMAND) {
+		hdr = (u32 *)(trans->req_hdr + trans->curr_req_frag);
+		pay = (u32 *)(trans->req_pay + trans->curr_req_frag);
+		hdr_size = (sizeof(struct qlcnic_bc_hdr) / sizeof(u32));
+		pay_size = qlcnic_sriov_get_bc_paysize(trans->req_pay_size,
+						       trans->curr_req_frag);
+		pay_size = (pay_size / sizeof(u32));
+	} else {
+		hdr = (u32 *)(trans->rsp_hdr + trans->curr_rsp_frag);
+		pay = (u32 *)(trans->rsp_pay + trans->curr_rsp_frag);
+		hdr_size = (sizeof(struct qlcnic_bc_hdr) / sizeof(u32));
+		pay_size = qlcnic_sriov_get_bc_paysize(trans->rsp_pay_size,
+						       trans->curr_rsp_frag);
+		pay_size = (pay_size / sizeof(u32));
+	}
+
+	ret = qlcnic_sriov_post_bc_msg(vf->adapter, hdr, pay,
+				       pci_func, pay_size);
+	return ret;
+}
+
+static int __qlcnic_sriov_send_bc_msg(struct qlcnic_bc_trans *trans,
+				      struct qlcnic_vf_info *vf, u8 type)
+{
+	int err;
+	bool flag = true;
+
+	while (flag) {
+		switch (trans->trans_state) {
+		case QLC_INIT:
+			trans->trans_state = QLC_WAIT_FOR_CHANNEL_FREE;
+			if (qlcnic_sriov_issue_bc_post(trans, type))
+				trans->trans_state = QLC_ABORT;
+			break;
+		case QLC_WAIT_FOR_CHANNEL_FREE:
+			qlcnic_sriov_wait_for_channel_free(trans, type);
+			break;
+		case QLC_WAIT_FOR_RESP:
+			qlcnic_sriov_wait_for_resp(trans);
+			break;
+		case QLC_END:
+			err = 0;
+			flag = false;
+			break;
+		case QLC_ABORT:
+			err = -EIO;
+			flag = false;
+			clear_bit(QLC_BC_VF_CHANNEL, &vf->state);
+			break;
+		default:
+			err = -EIO;
+			flag = false;
+		}
+	}
+	return err;
+}
+
+static int qlcnic_sriov_send_bc_cmd(struct qlcnic_adapter *adapter,
+				    struct qlcnic_bc_trans *trans, int pci_func)
+{
+	struct qlcnic_vf_info *vf;
+	int err, index = qlcnic_sriov_func_to_index(adapter, pci_func);
+
+	if (index < 0)
+		return -EIO;
+
+	vf = &adapter->ahw->sriov->vf_info[index];
+	trans->vf = vf;
+	trans->func_id = pci_func;
+
+	if (!test_bit(QLC_BC_VF_STATE, &vf->state)) {
+		if (qlcnic_sriov_pf_check(adapter))
+			return -EIO;
+		if (qlcnic_sriov_vf_check(adapter) &&
+		    trans->cmd_id != QLCNIC_BC_CMD_CHANNEL_INIT)
+			return -EIO;
+	}
+
+	mutex_lock(&vf->send_cmd_lock);
+	vf->send_cmd = trans;
+	err = __qlcnic_sriov_send_bc_msg(trans, vf, QLC_BC_COMMAND);
+	qlcnic_sriov_clear_trans(vf, trans, QLC_BC_COMMAND);
+	mutex_unlock(&vf->send_cmd_lock);
+	return err;
+}
+
+static void __qlcnic_sriov_process_bc_cmd(struct qlcnic_adapter *adapter,
+					  struct qlcnic_bc_trans *trans,
+					  struct qlcnic_cmd_args *cmd)
+{
+#ifdef CONFIG_QLCNIC_SRIOV
+	if (qlcnic_sriov_pf_check(adapter)) {
+		qlcnic_sriov_pf_process_bc_cmd(adapter, trans, cmd);
+		return;
+	}
+#endif
+	cmd->rsp.arg[0] |= (0x9 << 25);
+	return;
+}
+
+static void qlcnic_sriov_process_bc_cmd(struct work_struct *work)
+{
+	struct qlcnic_vf_info *vf = container_of(work, struct qlcnic_vf_info,
+						 trans_work);
+	struct qlcnic_bc_trans *trans = NULL;
+	struct qlcnic_adapter *adapter  = vf->adapter;
+	struct qlcnic_cmd_args cmd;
+	u8 req;
+
+	trans = list_first_entry(&vf->rcv_act.wait_list,
+				 struct qlcnic_bc_trans, list);
+	adapter = vf->adapter;
+
+	if (qlcnic_sriov_prepare_bc_hdr(trans, &cmd, trans->req_hdr->seq_id,
+					QLC_BC_RESPONSE))
+		goto cleanup_trans;
+
+	__qlcnic_sriov_process_bc_cmd(adapter, trans, &cmd);
+	trans->trans_state = QLC_INIT;
+	__qlcnic_sriov_send_bc_msg(trans, vf, QLC_BC_RESPONSE);
+
+cleanup_trans:
+	qlcnic_free_mbx_args(&cmd);
+	req = qlcnic_sriov_clear_trans(vf, trans, QLC_BC_RESPONSE);
+	qlcnic_sriov_cleanup_transaction(trans);
+	if (req)
+		qlcnic_sriov_schedule_bc_cmd(adapter->ahw->sriov, vf,
+					     qlcnic_sriov_process_bc_cmd);
+}
+
+static void qlcnic_sriov_handle_bc_resp(struct qlcnic_bc_hdr *hdr,
+					struct qlcnic_vf_info *vf)
+{
+	struct qlcnic_bc_trans *trans;
+	u32 pay_size;
+
+	if (test_and_set_bit(QLC_BC_VF_SEND, &vf->state))
+		return;
+
+	trans = vf->send_cmd;
+
+	if (trans == NULL)
+		goto clear_send;
+
+	if (trans->trans_id != hdr->seq_id)
+		goto clear_send;
+
+	pay_size = qlcnic_sriov_get_bc_paysize(trans->rsp_pay_size,
+					       trans->curr_rsp_frag);
+	qlcnic_sriov_pull_bc_msg(vf->adapter,
+				 (u32 *)(trans->rsp_hdr + trans->curr_rsp_frag),
+				 (u32 *)(trans->rsp_pay + trans->curr_rsp_frag),
+				 pay_size);
+	if (++trans->curr_rsp_frag < trans->rsp_hdr->num_frags)
+		goto clear_send;
+
+	complete(&trans->resp_cmpl);
+
+clear_send:
+	clear_bit(QLC_BC_VF_SEND, &vf->state);
+}
+
+static int qlcnic_sriov_add_act_list(struct qlcnic_sriov *sriov,
+				     struct qlcnic_vf_info *vf,
+				     struct qlcnic_bc_trans *trans)
+{
+	struct qlcnic_trans_list *t_list = &vf->rcv_act;
+
+	spin_lock(&t_list->lock);
+	t_list->count++;
+	list_add_tail(&trans->list, &t_list->wait_list);
+	if (t_list->count == 1)
+		qlcnic_sriov_schedule_bc_cmd(sriov, vf,
+					     qlcnic_sriov_process_bc_cmd);
+	spin_unlock(&t_list->lock);
+	return 0;
+}
+
+static void qlcnic_sriov_handle_pending_trans(struct qlcnic_sriov *sriov,
+					      struct qlcnic_vf_info *vf,
+					      struct qlcnic_bc_hdr *hdr)
+{
+	struct qlcnic_bc_trans *trans = NULL;
+	struct list_head *node;
+	u32 pay_size, curr_frag;
+	u8 found = 0, active = 0;
+
+	spin_lock(&vf->rcv_pend.lock);
+	if (vf->rcv_pend.count > 0) {
+		list_for_each(node, &vf->rcv_pend.wait_list) {
+			trans = list_entry(node, struct qlcnic_bc_trans, list);
+			if (trans->trans_id == hdr->seq_id) {
+				found = 1;
+				break;
+			}
+		}
+	}
+
+	if (found) {
+		curr_frag = trans->curr_req_frag;
+		pay_size = qlcnic_sriov_get_bc_paysize(trans->req_pay_size,
+						       curr_frag);
+		qlcnic_sriov_pull_bc_msg(vf->adapter,
+					 (u32 *)(trans->req_hdr + curr_frag),
+					 (u32 *)(trans->req_pay + curr_frag),
+					 pay_size);
+		trans->curr_req_frag++;
+		if (trans->curr_req_frag >= hdr->num_frags) {
+			vf->rcv_pend.count--;
+			list_del(&trans->list);
+			active = 1;
+		}
+	}
+	spin_unlock(&vf->rcv_pend.lock);
+
+	if (active)
+		if (qlcnic_sriov_add_act_list(sriov, vf, trans))
+			qlcnic_sriov_cleanup_transaction(trans);
+
+	return;
+}
+
+static void qlcnic_sriov_handle_bc_cmd(struct qlcnic_sriov *sriov,
+				       struct qlcnic_bc_hdr *hdr,
+				       struct qlcnic_vf_info *vf)
+{
+	struct qlcnic_bc_trans *trans;
+	struct qlcnic_adapter *adapter = vf->adapter;
+	struct qlcnic_cmd_args cmd;
+	u32 pay_size;
+	int err;
+	u8 cmd_op;
+
+	if (!test_bit(QLC_BC_VF_STATE, &vf->state) &&
+	    hdr->op_type != QLC_BC_CMD &&
+	    hdr->cmd_op != QLCNIC_BC_CMD_CHANNEL_INIT)
+		return;
+
+	if (hdr->frag_num > 1) {
+		qlcnic_sriov_handle_pending_trans(sriov, vf, hdr);
+		return;
+	}
+
+	cmd_op = hdr->cmd_op;
+	if (qlcnic_sriov_alloc_bc_trans(&trans))
+		return;
+
+	if (hdr->op_type == QLC_BC_CMD)
+		err = qlcnic_sriov_alloc_bc_mbx_args(&cmd, cmd_op);
+	else
+		err = qlcnic_alloc_mbx_args(&cmd, adapter, cmd_op);
+
+	if (err) {
+		qlcnic_sriov_cleanup_transaction(trans);
+		return;
+	}
+
+	cmd.op_type = hdr->op_type;
+	if (qlcnic_sriov_prepare_bc_hdr(trans, &cmd, hdr->seq_id,
+					QLC_BC_COMMAND)) {
+		qlcnic_free_mbx_args(&cmd);
+		qlcnic_sriov_cleanup_transaction(trans);
+		return;
+	}
+
+	pay_size = qlcnic_sriov_get_bc_paysize(trans->req_pay_size,
+					 trans->curr_req_frag);
+	qlcnic_sriov_pull_bc_msg(vf->adapter,
+				 (u32 *)(trans->req_hdr + trans->curr_req_frag),
+				 (u32 *)(trans->req_pay + trans->curr_req_frag),
+				 pay_size);
+	trans->func_id = vf->pci_func;
+	trans->vf = vf;
+	trans->trans_id = hdr->seq_id;
+	trans->curr_req_frag++;
+	if (trans->curr_req_frag == trans->req_hdr->num_frags) {
+		if (qlcnic_sriov_add_act_list(sriov, vf, trans)) {
+			qlcnic_free_mbx_args(&cmd);
+			qlcnic_sriov_cleanup_transaction(trans);
+		}
+	} else {
+		spin_lock(&vf->rcv_pend.lock);
+		list_add_tail(&trans->list, &vf->rcv_pend.wait_list);
+		vf->rcv_pend.count++;
+		spin_unlock(&vf->rcv_pend.lock);
+	}
+}
+
+static void qlcnic_sriov_handle_msg_event(struct qlcnic_sriov *sriov,
+					  struct qlcnic_vf_info *vf)
+{
+	struct qlcnic_bc_hdr hdr;
+	u32 *ptr = (u32 *)&hdr;
+	u8 msg_type, i;
+
+	for (i = 2; i < 6; i++)
+		ptr[i - 2] = readl(QLCNIC_MBX_FW(vf->adapter->ahw, i));
+	msg_type = hdr.msg_type;
+
+	switch (msg_type) {
+	case QLC_BC_COMMAND:
+		qlcnic_sriov_handle_bc_cmd(sriov, &hdr, vf);
+		break;
+	case QLC_BC_RESPONSE:
+		qlcnic_sriov_handle_bc_resp(&hdr, vf);
+		break;
+	}
+}
+
+void qlcnic_sriov_handle_bc_event(struct qlcnic_adapter *adapter, u32 event)
+{
+	struct qlcnic_vf_info *vf;
+	struct qlcnic_sriov *sriov;
+	int index;
+	u8 pci_func;
+
+	sriov = adapter->ahw->sriov;
+	pci_func = qlcnic_sriov_target_func_id(event);
+	index = qlcnic_sriov_func_to_index(adapter, pci_func);
+
+	if (index < 0)
+		return;
+
+	vf = &sriov->vf_info[index];
+	vf->pci_func = pci_func;
+
+	if (qlcnic_sriov_channel_free_check(event))
+		complete(&vf->ch_free_cmpl);
+
+	if (qlcnic_sriov_bc_msg_check(event))
+		qlcnic_sriov_handle_msg_event(sriov, vf);
+}
+
+int qlcnic_sriov_cfg_bc_intr(struct qlcnic_adapter *adapter, u8 enable)
+{
+	struct qlcnic_cmd_args cmd;
+	int err;
+
+	if (!test_bit(__QLCNIC_SRIOV_ENABLE, &adapter->state))
+		return 0;
+
+	if (qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_BC_EVENT_SETUP))
+		return -ENOMEM;
+
+	if (enable)
+		cmd.req.arg[1] = (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7);
+
+	err = qlcnic_83xx_mbx_op(adapter, &cmd);
+
+	if (err != QLCNIC_RCODE_SUCCESS) {
+		dev_err(&adapter->pdev->dev,
+			"Failed to %s bc events, err=%d\n",
+			(enable ? "enable" : "disable"), err);
+	}
+
+	qlcnic_free_mbx_args(&cmd);
+	return err;
+}
+
+static int qlcnic_sriov_vf_mbx_op(struct qlcnic_adapter *adapter,
+				  struct qlcnic_cmd_args *cmd)
+{
+	struct qlcnic_bc_trans *trans;
+	int err;
+	u32 rsp_data, opcode, mbx_err_code, rsp;
+	u16 seq = ++adapter->ahw->sriov->bc.trans_counter;
+
+	if (qlcnic_sriov_alloc_bc_trans(&trans))
+		return -ENOMEM;
+
+	if (qlcnic_sriov_prepare_bc_hdr(trans, cmd, seq, QLC_BC_COMMAND))
+		return -ENOMEM;
+
+	if (!test_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status)) {
+		rsp = -EIO;
+		QLCDB(adapter, DRV, "MBX not Ready!(cmd 0x%x) for VF 0x%x\n",
+		      QLCNIC_MBX_RSP(cmd->req.arg[0]), adapter->ahw->pci_func);
+		goto err_out;
+	}
+
+	err = qlcnic_sriov_send_bc_cmd(adapter, trans, adapter->ahw->pci_func);
+	if (err) {
+		dev_err(&adapter->pdev->dev,
+			"MBX command 0x%x timed out for VF %d\n",
+			(cmd->req.arg[0] & 0xffff), adapter->ahw->pci_func);
+		rsp = QLCNIC_RCODE_TIMEOUT;
+		goto err_out;
+	}
+
+	rsp_data = cmd->rsp.arg[0];
+	mbx_err_code = QLCNIC_MBX_STATUS(rsp_data);
+	opcode = QLCNIC_MBX_RSP(cmd->req.arg[0]);
+
+	if ((mbx_err_code == QLCNIC_MBX_RSP_OK) ||
+	    (mbx_err_code == QLCNIC_MBX_PORT_RSP_OK)) {
+		rsp = QLCNIC_RCODE_SUCCESS;
+	} else {
+		rsp = mbx_err_code;
+		if (!rsp)
+			rsp = 1;
+		dev_err(&adapter->pdev->dev,
+			"MBX command 0x%x failed with err:0x%x for VF %d\n",
+			opcode, mbx_err_code, adapter->ahw->pci_func);
+	}
+
+err_out:
+	qlcnic_sriov_cleanup_transaction(trans);
+	return rsp;
+}
+
+int qlcnic_sriov_channel_cfg_cmd(struct qlcnic_adapter *adapter, u8 cmd_op)
+{
+	struct qlcnic_cmd_args cmd;
+	struct qlcnic_vf_info *vf = &adapter->ahw->sriov->vf_info[0];
+	int ret;
+
+	if (qlcnic_sriov_alloc_bc_mbx_args(&cmd, cmd_op))
+		return -ENOMEM;
+
+	ret = qlcnic_issue_cmd(adapter, &cmd);
+	if (ret) {
+		dev_err(&adapter->pdev->dev,
+			"Failed bc channel %s %d\n", cmd_op ? "term" : "init",
+			ret);
+		goto out;
+	}
+
+	cmd_op = (cmd.rsp.arg[0] & 0xff);
+	if (cmd.rsp.arg[0] >> 25 == 2)
+		return 2;
+	if (cmd_op == QLCNIC_BC_CMD_CHANNEL_INIT)
+		set_bit(QLC_BC_VF_STATE, &vf->state);
+	else
+		clear_bit(QLC_BC_VF_STATE, &vf->state);
+
+out:
+	qlcnic_free_mbx_args(&cmd);
+	return ret;
+}
+
+void qlcnic_vf_add_mc_list(struct net_device *netdev)
+{
+	struct qlcnic_adapter *adapter = netdev_priv(netdev);
+	struct qlcnic_mac_list_s *cur;
+	struct list_head *head, tmp_list;
+
+	INIT_LIST_HEAD(&tmp_list);
+	head = &adapter->vf_mc_list;
+	netif_addr_lock_bh(netdev);
+
+	while (!list_empty(head)) {
+		cur = list_entry(head->next, struct qlcnic_mac_list_s, list);
+		list_move(&cur->list, &tmp_list);
+	}
+
+	netif_addr_unlock_bh(netdev);
+
+	while (!list_empty(&tmp_list)) {
+		cur = list_entry((&tmp_list)->next,
+				 struct qlcnic_mac_list_s, list);
+		qlcnic_nic_add_mac(adapter, cur->mac_addr);
+		list_del(&cur->list);
+		kfree(cur);
+	}
+}
+
+void qlcnic_sriov_cleanup_async_list(struct qlcnic_back_channel *bc)
+{
+	struct list_head *head = &bc->async_list;
+	struct qlcnic_async_work_list *entry;
+
+	while (!list_empty(head)) {
+		entry = list_entry(head->next, struct qlcnic_async_work_list,
+				   list);
+		cancel_work_sync(&entry->work);
+		list_del(&entry->list);
+		kfree(entry);
+	}
+}
+
+static void qlcnic_sriov_vf_set_multi(struct net_device *netdev)
+{
+	struct qlcnic_adapter *adapter = netdev_priv(netdev);
+
+	if (!test_bit(__QLCNIC_FW_ATTACHED, &adapter->state))
+		return;
+
+	__qlcnic_set_multi(netdev);
+}
+
+static void qlcnic_sriov_handle_async_multi(struct work_struct *work)
+{
+	struct qlcnic_async_work_list *entry;
+	struct net_device *netdev;
+
+	entry = container_of(work, struct qlcnic_async_work_list, work);
+	netdev = (struct net_device *)entry->ptr;
+
+	qlcnic_sriov_vf_set_multi(netdev);
+	return;
+}
+
+static struct qlcnic_async_work_list *
+qlcnic_sriov_get_free_node_async_work(struct qlcnic_back_channel *bc)
+{
+	struct list_head *node;
+	struct qlcnic_async_work_list *entry = NULL;
+	u8 empty = 0;
+
+	list_for_each(node, &bc->async_list) {
+		entry = list_entry(node, struct qlcnic_async_work_list, list);
+		if (!work_pending(&entry->work)) {
+			empty = 1;
+			break;
+		}
+	}
+
+	if (!empty) {
+		entry = kzalloc(sizeof(struct qlcnic_async_work_list),
+				GFP_ATOMIC);
+		if (entry == NULL)
+			return NULL;
+		list_add_tail(&entry->list, &bc->async_list);
+	}
+
+	return entry;
+}
+
+static void qlcnic_sriov_schedule_bc_async_work(struct qlcnic_back_channel *bc,
+						work_func_t func, void *data)
+{
+	struct qlcnic_async_work_list *entry = NULL;
+
+	entry = qlcnic_sriov_get_free_node_async_work(bc);
+	if (!entry)
+		return;
+
+	entry->ptr = data;
+	INIT_WORK(&entry->work, func);
+	queue_work(bc->bc_async_wq, &entry->work);
+}
+
+void qlcnic_sriov_vf_schedule_multi(struct net_device *netdev)
+{
+
+	struct qlcnic_adapter *adapter = netdev_priv(netdev);
+	struct qlcnic_back_channel *bc = &adapter->ahw->sriov->bc;
+
+	qlcnic_sriov_schedule_bc_async_work(bc, qlcnic_sriov_handle_async_multi,
+					    netdev);
+}
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c
new file mode 100644
index 0000000..bed5056
--- /dev/null
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c
@@ -0,0 +1,1175 @@
+/*
+ * QLogic qlcnic NIC Driver
+ * Copyright (c) 2009-2013 QLogic Corporation
+ *
+ * See LICENSE.qlcnic for copyright and licensing details.
+ */
+
+#include "qlcnic_sriov.h"
+#include "qlcnic.h"
+#include <linux/types.h>
+
+#define QLCNIC_SRIOV_VF_MAX_MAC 1
+
+static int qlcnic_sriov_pf_get_vport_handle(struct qlcnic_adapter *, u8);
+
+struct qlcnic_sriov_cmd_handler {
+	int (*fn) (struct qlcnic_bc_trans *, struct qlcnic_cmd_args *);
+};
+
+struct qlcnic_sriov_fw_cmd_handler {
+	u32 cmd;
+	int (*fn) (struct qlcnic_bc_trans *, struct qlcnic_cmd_args *);
+};
+
+static int qlcnic_sriov_pf_set_vport_info(struct qlcnic_adapter *adapter,
+					  struct qlcnic_info *npar_info,
+					  u16 vport_id)
+{
+	struct qlcnic_cmd_args cmd;
+	int err;
+
+	if (qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_SET_NIC_INFO))
+		return -ENOMEM;
+
+	cmd.req.arg[1] = (vport_id << 16) | 0x1;
+	cmd.req.arg[2] = npar_info->bit_offsets;
+	cmd.req.arg[2] |= npar_info->min_tx_bw << 16;
+	cmd.req.arg[3] = npar_info->max_tx_bw | (npar_info->max_tx_ques << 16);
+	cmd.req.arg[4] = npar_info->max_tx_mac_filters;
+	cmd.req.arg[4] |= npar_info->max_rx_mcast_mac_filters << 16;
+	cmd.req.arg[5] = npar_info->max_rx_ucast_mac_filters |
+			 (npar_info->max_rx_ip_addr << 16);
+	cmd.req.arg[6] = npar_info->max_rx_lro_flow |
+			 (npar_info->max_rx_status_rings << 16);
+	cmd.req.arg[7] = npar_info->max_rx_buf_rings |
+			 (npar_info->max_rx_ques << 16);
+	cmd.req.arg[8] = npar_info->max_tx_vlan_keys;
+	cmd.req.arg[8] |= npar_info->max_local_ipv6_addrs << 16;
+	cmd.req.arg[9] = npar_info->max_remote_ipv6_addrs;
+
+	err = qlcnic_issue_cmd(adapter, &cmd);
+	if (err)
+		dev_err(&adapter->pdev->dev,
+			"Failed to set vport info, err=%d\n", err);
+
+	qlcnic_free_mbx_args(&cmd);
+	return err;
+}
+
+static int qlcnic_sriov_pf_cal_res_limit(struct qlcnic_adapter *adapter,
+					 struct qlcnic_info *info, u16 func)
+{
+	struct qlcnic_sriov *sriov = adapter->ahw->sriov;
+	struct qlcnic_resources *res = &sriov->ff_max;
+	int ret = -EIO, vpid;
+	u32 temp, num_vf_macs, num_vfs, max;
+
+	vpid = qlcnic_sriov_pf_get_vport_handle(adapter, func);
+	if (vpid < 0)
+		return -EINVAL;
+
+	num_vfs = sriov->num_vfs;
+	max = num_vfs + 1;
+	info->bit_offsets = 0xffff;
+	info->min_tx_bw = 0;
+	info->max_tx_bw = MAX_BW;
+	info->max_tx_ques = res->num_tx_queues / max;
+	info->max_rx_mcast_mac_filters = res->num_rx_mcast_mac_filters;
+	num_vf_macs = QLCNIC_SRIOV_VF_MAX_MAC;
+
+	if (adapter->ahw->pci_func == func) {
+		temp = res->num_rx_mcast_mac_filters - (num_vfs * num_vf_macs);
+		info->max_rx_ucast_mac_filters = temp;
+		temp = res->num_tx_mac_filters - (num_vfs * num_vf_macs);
+		info->max_tx_mac_filters = temp;
+	} else {
+		info->max_rx_ucast_mac_filters = num_vf_macs;
+		info->max_tx_mac_filters = num_vf_macs;
+	}
+
+	info->max_rx_ip_addr = res->num_destip / max;
+	info->max_rx_status_rings = res->num_rx_status_rings / max;
+	info->max_rx_buf_rings = res->num_rx_buf_rings / max;
+	info->max_rx_ques = res->num_rx_queues / max;
+	info->max_rx_lro_flow = res->num_lro_flows_supported / max;
+	info->max_tx_vlan_keys = res->num_txvlan_keys;
+	info->max_local_ipv6_addrs = res->max_local_ipv6_addrs;
+	info->max_remote_ipv6_addrs = res->max_remote_ipv6_addrs;
+
+	ret = qlcnic_sriov_pf_set_vport_info(adapter, info, vpid);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static void qlcnic_sriov_pf_set_ff_max_res(struct qlcnic_adapter *adapter,
+					   struct qlcnic_info *info)
+{
+	struct qlcnic_resources *ff_max = &adapter->ahw->sriov->ff_max;
+
+	ff_max->num_tx_mac_filters = info->max_tx_mac_filters;
+	ff_max->num_rx_ucast_mac_filters = info->max_rx_ucast_mac_filters;
+	ff_max->num_rx_mcast_mac_filters = info->max_rx_mcast_mac_filters;
+	ff_max->num_txvlan_keys = info->max_tx_vlan_keys;
+	ff_max->num_rx_queues = info->max_rx_ques;
+	ff_max->num_tx_queues = info->max_tx_ques;
+	ff_max->num_lro_flows_supported = info->max_rx_lro_flow;
+	ff_max->num_destip = info->max_rx_ip_addr;
+	ff_max->num_rx_buf_rings = info->max_rx_buf_rings;
+	ff_max->num_rx_status_rings = info->max_rx_status_rings;
+	ff_max->max_remote_ipv6_addrs = info->max_remote_ipv6_addrs;
+	ff_max->max_local_ipv6_addrs = info->max_local_ipv6_addrs;
+}
+
+static int qlcnic_sriov_get_pf_info(struct qlcnic_adapter *adapter,
+				    struct qlcnic_info *npar_info)
+{
+	int err;
+	struct qlcnic_cmd_args cmd;
+
+	if (qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_NIC_INFO))
+		return -ENOMEM;
+
+	cmd.req.arg[1] = 0x2;
+	err = qlcnic_issue_cmd(adapter, &cmd);
+	if (err) {
+		dev_err(&adapter->pdev->dev,
+			"Failed to get PF info, err=%d\n", err);
+		goto out;
+	}
+
+	npar_info->total_pf = cmd.rsp.arg[2] & 0xff;
+	npar_info->total_rss_engines = (cmd.rsp.arg[2] >> 8) & 0xff;
+	npar_info->max_vports = MSW(cmd.rsp.arg[2]);
+	npar_info->max_tx_ques =  LSW(cmd.rsp.arg[3]);
+	npar_info->max_tx_mac_filters = MSW(cmd.rsp.arg[3]);
+	npar_info->max_rx_mcast_mac_filters = LSW(cmd.rsp.arg[4]);
+	npar_info->max_rx_ucast_mac_filters = MSW(cmd.rsp.arg[4]);
+	npar_info->max_rx_ip_addr = LSW(cmd.rsp.arg[5]);
+	npar_info->max_rx_lro_flow = MSW(cmd.rsp.arg[5]);
+	npar_info->max_rx_status_rings = LSW(cmd.rsp.arg[6]);
+	npar_info->max_rx_buf_rings = MSW(cmd.rsp.arg[6]);
+	npar_info->max_rx_ques = LSW(cmd.rsp.arg[7]);
+	npar_info->max_tx_vlan_keys = MSW(cmd.rsp.arg[7]);
+	npar_info->max_local_ipv6_addrs = LSW(cmd.rsp.arg[8]);
+	npar_info->max_remote_ipv6_addrs = MSW(cmd.rsp.arg[8]);
+
+	qlcnic_sriov_pf_set_ff_max_res(adapter, npar_info);
+	dev_info(&adapter->pdev->dev,
+		 "\n\ttotal_pf: %d,\n"
+		 "\n\ttotal_rss_engines: %d max_vports: %d max_tx_ques %d,\n"
+		 "\tmax_tx_mac_filters: %d max_rx_mcast_mac_filters: %d,\n"
+		 "\tmax_rx_ucast_mac_filters: 0x%x, max_rx_ip_addr: %d,\n"
+		 "\tmax_rx_lro_flow: %d max_rx_status_rings: %d,\n"
+		 "\tmax_rx_buf_rings: %d, max_rx_ques: %d, max_tx_vlan_keys %d\n"
+		 "\tmax_local_ipv6_addrs: %d, max_remote_ipv6_addrs: %d\n",
+		 npar_info->total_pf, npar_info->total_rss_engines,
+		 npar_info->max_vports, npar_info->max_tx_ques,
+		 npar_info->max_tx_mac_filters,
+		 npar_info->max_rx_mcast_mac_filters,
+		 npar_info->max_rx_ucast_mac_filters, npar_info->max_rx_ip_addr,
+		 npar_info->max_rx_lro_flow, npar_info->max_rx_status_rings,
+		 npar_info->max_rx_buf_rings, npar_info->max_rx_ques,
+		 npar_info->max_tx_vlan_keys, npar_info->max_local_ipv6_addrs,
+		 npar_info->max_remote_ipv6_addrs);
+
+out:
+	qlcnic_free_mbx_args(&cmd);
+	return err;
+}
+
+static void qlcnic_sriov_pf_reset_vport_handle(struct qlcnic_adapter *adapter,
+					       u8 func)
+{
+	struct qlcnic_sriov  *sriov = adapter->ahw->sriov;
+	struct qlcnic_vport *vp;
+	int index;
+
+	if (adapter->ahw->pci_func == func) {
+		sriov->vp_handle = 0;
+	} else {
+		index = qlcnic_sriov_func_to_index(adapter, func);
+		if (index < 0)
+			return;
+		vp = sriov->vf_info[index].vp;
+		vp->handle = 0;
+	}
+}
+
+static void qlcnic_sriov_pf_set_vport_handle(struct qlcnic_adapter *adapter,
+					     u16 vport_handle, u8 func)
+{
+	struct qlcnic_sriov  *sriov = adapter->ahw->sriov;
+	struct qlcnic_vport *vp;
+	int index;
+
+	if (adapter->ahw->pci_func == func) {
+		sriov->vp_handle = vport_handle;
+	} else {
+		index = qlcnic_sriov_func_to_index(adapter, func);
+		if (index < 0)
+			return;
+		vp = sriov->vf_info[index].vp;
+		vp->handle = vport_handle;
+	}
+}
+
+static int qlcnic_sriov_pf_get_vport_handle(struct qlcnic_adapter *adapter,
+					    u8 func)
+{
+	struct qlcnic_sriov  *sriov = adapter->ahw->sriov;
+	struct qlcnic_vf_info *vf_info;
+	int index;
+
+	if (adapter->ahw->pci_func == func) {
+		return sriov->vp_handle;
+	} else {
+		index = qlcnic_sriov_func_to_index(adapter, func);
+		if (index >= 0) {
+			vf_info = &sriov->vf_info[index];
+			return vf_info->vp->handle;
+		}
+	}
+
+	return -EINVAL;
+}
+
+static int qlcnic_sriov_pf_config_vport(struct qlcnic_adapter *adapter,
+					u8 flag, u16 func)
+{
+	struct qlcnic_cmd_args cmd;
+	int ret;
+	int vpid;
+
+	if (qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_VPORT))
+		return -ENOMEM;
+
+	if (flag) {
+		cmd.req.arg[3] = func << 8;
+	} else {
+		vpid = qlcnic_sriov_pf_get_vport_handle(adapter, func);
+		if (vpid < 0) {
+			ret = -EINVAL;
+			goto out;
+		}
+		cmd.req.arg[3] = ((vpid & 0xffff) << 8) | 1;
+	}
+
+	ret = qlcnic_issue_cmd(adapter, &cmd);
+	if (ret) {
+		dev_err(&adapter->pdev->dev,
+			"Failed %s vport, err %d for func 0x%x\n",
+			(flag ? "enable" : "disable"), ret, func);
+		goto out;
+	}
+
+	if (flag) {
+		vpid = cmd.rsp.arg[2] & 0xffff;
+		qlcnic_sriov_pf_set_vport_handle(adapter, vpid, func);
+	} else {
+		qlcnic_sriov_pf_reset_vport_handle(adapter, func);
+	}
+
+out:
+	qlcnic_free_mbx_args(&cmd);
+	return ret;
+}
+
+static int qlcnic_sriov_pf_cfg_eswitch(struct qlcnic_adapter *adapter,
+				       u8 func, u8 enable)
+{
+	struct qlcnic_cmd_args cmd;
+	int err = -EIO;
+
+	if (qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_TOGGLE_ESWITCH))
+		return -ENOMEM;
+
+	cmd.req.arg[0] |= (3 << 29);
+	cmd.req.arg[1] = ((func & 0xf) << 2) | BIT_6 | BIT_1;
+	if (enable)
+		cmd.req.arg[1] |= BIT_0;
+
+	err = qlcnic_issue_cmd(adapter, &cmd);
+
+	if (err != QLCNIC_RCODE_SUCCESS) {
+		dev_err(&adapter->pdev->dev,
+			"Failed to enable sriov eswitch%d\n", err);
+		err = -EIO;
+	}
+
+	qlcnic_free_mbx_args(&cmd);
+	return err;
+}
+
+void qlcnic_sriov_pf_cleanup(struct qlcnic_adapter *adapter)
+{
+	u8 func = adapter->ahw->pci_func;
+
+	if (!qlcnic_sriov_enable_check(adapter))
+		return;
+
+	qlcnic_sriov_cfg_bc_intr(adapter, 0);
+	qlcnic_sriov_pf_config_vport(adapter, 0, func);
+	qlcnic_sriov_pf_cfg_eswitch(adapter, func, 0);
+	__qlcnic_sriov_cleanup(adapter);
+	adapter->ahw->op_mode = QLCNIC_MGMT_FUNC;
+	clear_bit(__QLCNIC_SRIOV_ENABLE, &adapter->state);
+}
+
+void qlcnic_sriov_pf_disable(struct qlcnic_adapter *adapter)
+{
+	if (!qlcnic_sriov_pf_check(adapter))
+		return;
+
+	if (!qlcnic_sriov_enable_check(adapter))
+		return;
+
+	pci_disable_sriov(adapter->pdev);
+	netdev_info(adapter->netdev,
+		    "SR-IOV is disabled successfully on port %d\n",
+		    adapter->portnum);
+}
+
+static int qlcnic_pci_sriov_disable(struct qlcnic_adapter *adapter)
+{
+	struct net_device *netdev = adapter->netdev;
+
+	if (netif_running(netdev))
+		__qlcnic_down(adapter, netdev);
+
+	qlcnic_sriov_pf_disable(adapter);
+
+	qlcnic_sriov_pf_cleanup(adapter);
+
+	/* After disabling SRIOV re-init the driver in default mode
+	   configure opmode based on op_mode of function
+	 */
+	if (qlcnic_83xx_configure_opmode(adapter))
+		return -EIO;
+
+	if (netif_running(netdev))
+		__qlcnic_up(adapter, netdev);
+
+	return 0;
+}
+
+static int qlcnic_sriov_pf_init(struct qlcnic_adapter *adapter)
+{
+	struct qlcnic_hardware_context *ahw = adapter->ahw;
+	struct qlcnic_info nic_info, pf_info, vp_info;
+	int err;
+	u8 func = ahw->pci_func;
+
+	if (!qlcnic_sriov_enable_check(adapter))
+		return 0;
+
+	err = qlcnic_sriov_pf_cfg_eswitch(adapter, func, 1);
+	if (err)
+		goto clear_sriov_enable;
+
+	err = qlcnic_sriov_pf_config_vport(adapter, 1, func);
+	if (err)
+		goto disable_eswitch;
+
+	err = qlcnic_sriov_get_pf_info(adapter, &pf_info);
+	if (err)
+		goto delete_vport;
+
+	err = qlcnic_get_nic_info(adapter, &nic_info, func);
+	if (err)
+		goto delete_vport;
+
+	err = qlcnic_sriov_pf_cal_res_limit(adapter, &vp_info, func);
+	if (err)
+		goto delete_vport;
+
+	err = qlcnic_sriov_cfg_bc_intr(adapter, 1);
+	if (err)
+		goto delete_vport;
+
+	ahw->physical_port = (u8) nic_info.phys_port;
+	ahw->switch_mode = nic_info.switch_mode;
+	ahw->max_mtu = nic_info.max_mtu;
+	ahw->capabilities = nic_info.capabilities;
+	ahw->nic_mode = QLC_83XX_SRIOV_MODE;
+	return err;
+
+delete_vport:
+	qlcnic_sriov_pf_config_vport(adapter, 0, func);
+
+disable_eswitch:
+	qlcnic_sriov_pf_cfg_eswitch(adapter, func, 0);
+
+clear_sriov_enable:
+	__qlcnic_sriov_cleanup(adapter);
+	adapter->ahw->op_mode = QLCNIC_MGMT_FUNC;
+	clear_bit(__QLCNIC_SRIOV_ENABLE, &adapter->state);
+	return err;
+}
+
+static int qlcnic_sriov_pf_enable(struct qlcnic_adapter *adapter, int num_vfs)
+{
+	int err;
+
+	if (!qlcnic_sriov_enable_check(adapter))
+		return 0;
+
+	err = pci_enable_sriov(adapter->pdev, num_vfs);
+	if (err)
+		qlcnic_sriov_pf_cleanup(adapter);
+
+	return err;
+}
+
+static int __qlcnic_pci_sriov_enable(struct qlcnic_adapter *adapter,
+				     int num_vfs)
+{
+	int err = 0;
+
+	set_bit(__QLCNIC_SRIOV_ENABLE, &adapter->state);
+	adapter->ahw->op_mode = QLCNIC_SRIOV_PF_FUNC;
+
+	if (qlcnic_sriov_init(adapter, num_vfs)) {
+		clear_bit(__QLCNIC_SRIOV_ENABLE, &adapter->state);
+		adapter->ahw->op_mode = QLCNIC_MGMT_FUNC;
+		return -EIO;
+	}
+
+	if (qlcnic_sriov_pf_init(adapter))
+		return -EIO;
+
+	err = qlcnic_sriov_pf_enable(adapter, num_vfs);
+	return err;
+}
+
+static int qlcnic_pci_sriov_enable(struct qlcnic_adapter *adapter, int num_vfs)
+{
+	struct net_device *netdev = adapter->netdev;
+	int err;
+
+	if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) {
+		netdev_err(netdev,
+			   "SR-IOV cannot be enabled, when legacy interrupts are enabled\n");
+		return -EIO;
+	}
+
+	if (netif_running(netdev))
+		__qlcnic_down(adapter, netdev);
+
+	err = __qlcnic_pci_sriov_enable(adapter, num_vfs);
+	if (err) {
+		netdev_info(netdev, "Failed to enable SR-IOV on port %d\n",
+			    adapter->portnum);
+
+		if (qlcnic_83xx_configure_opmode(adapter))
+			goto error;
+	} else {
+		netdev_info(adapter->netdev,
+			    "SR-IOV is enabled successfully on port %d\n",
+			    adapter->portnum);
+	}
+	if (netif_running(netdev))
+		__qlcnic_up(adapter, netdev);
+
+error:
+	return err;
+}
+
+int qlcnic_pci_sriov_configure(struct pci_dev *dev, int num_vfs)
+{
+	struct qlcnic_adapter *adapter = pci_get_drvdata(dev);
+	int err;
+
+	if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
+		return -EBUSY;
+
+	if (num_vfs == 0)
+		err = qlcnic_pci_sriov_disable(adapter);
+	else
+		err = qlcnic_pci_sriov_enable(adapter, num_vfs);
+
+	clear_bit(__QLCNIC_RESETTING, &adapter->state);
+	return err;
+}
+
+static int qlcnic_sriov_set_vf_vport_info(struct qlcnic_adapter *adapter,
+					  u16 func)
+{
+	struct qlcnic_info defvp_info;
+	int err;
+
+	err = qlcnic_sriov_pf_cal_res_limit(adapter, &defvp_info, func);
+	if (err)
+		return -EIO;
+
+	return 0;
+}
+
+static int qlcnic_sriov_pf_channel_cfg_cmd(struct qlcnic_bc_trans *trans,
+					   struct qlcnic_cmd_args *cmd)
+{
+	struct qlcnic_vf_info *vf = trans->vf;
+	struct qlcnic_adapter *adapter = vf->adapter;
+	int err;
+	u16 func = vf->pci_func;
+
+	cmd->rsp.arg[0] = trans->req_hdr->cmd_op;
+	cmd->rsp.arg[0] |= (1 << 16);
+
+	if (trans->req_hdr->cmd_op == QLCNIC_BC_CMD_CHANNEL_INIT) {
+		err = qlcnic_sriov_pf_config_vport(adapter, 1, func);
+		if (!err) {
+			err = qlcnic_sriov_set_vf_vport_info(adapter, func);
+			if (err)
+				qlcnic_sriov_pf_config_vport(adapter, 0, func);
+		}
+	} else {
+		err = qlcnic_sriov_pf_config_vport(adapter, 0, func);
+	}
+
+	if (err)
+		goto err_out;
+
+	cmd->rsp.arg[0] |= (1 << 25);
+
+	if (trans->req_hdr->cmd_op == QLCNIC_BC_CMD_CHANNEL_INIT)
+		set_bit(QLC_BC_VF_STATE, &vf->state);
+	else
+		clear_bit(QLC_BC_VF_STATE, &vf->state);
+
+	return err;
+
+err_out:
+	cmd->rsp.arg[0] |= (2 << 25);
+	return err;
+}
+
+static int qlcnic_sriov_cfg_vf_def_mac(struct qlcnic_adapter *adapter,
+				       struct qlcnic_vport *vp,
+				       u16 func, __le16 vlan, u8 op)
+{
+	struct qlcnic_cmd_args cmd;
+	struct qlcnic_macvlan_mbx mv;
+	u8 *addr;
+	int err;
+	u32 *buf;
+	int vpid;
+
+	if (qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_MAC_VLAN))
+		return -ENOMEM;
+
+	vpid = qlcnic_sriov_pf_get_vport_handle(adapter, func);
+	if (vpid < 0) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	if (vlan)
+		op = ((op == QLCNIC_MAC_ADD || op == QLCNIC_MAC_VLAN_ADD) ?
+		      QLCNIC_MAC_VLAN_ADD : QLCNIC_MAC_VLAN_DEL);
+
+	cmd.req.arg[1] = op | (1 << 8) | (3 << 6);
+	cmd.req.arg[1] |= ((vpid & 0xffff) << 16) | BIT_31;
+
+	addr = vp->mac;
+	mv.vlan = le16_to_cpu(vlan);
+	mv.mac_addr0 = addr[0];
+	mv.mac_addr1 = addr[1];
+	mv.mac_addr2 = addr[2];
+	mv.mac_addr3 = addr[3];
+	mv.mac_addr4 = addr[4];
+	mv.mac_addr5 = addr[5];
+	buf = &cmd.req.arg[2];
+	memcpy(buf, &mv, sizeof(struct qlcnic_macvlan_mbx));
+
+	err = qlcnic_issue_cmd(adapter, &cmd);
+
+	if (err)
+		dev_err(&adapter->pdev->dev,
+			"MAC-VLAN %s to CAM failed, err=%d.\n",
+			((op == 1) ? "add " : "delete "), err);
+
+out:
+	qlcnic_free_mbx_args(&cmd);
+	return err;
+}
+
+static int qlcnic_sriov_validate_create_rx_ctx(struct qlcnic_cmd_args *cmd)
+{
+	if ((cmd->req.arg[0] >> 29) != 0x3)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int qlcnic_sriov_pf_create_rx_ctx_cmd(struct qlcnic_bc_trans *tran,
+					     struct qlcnic_cmd_args *cmd)
+{
+	struct qlcnic_vf_info *vf = tran->vf;
+	struct qlcnic_adapter *adapter = vf->adapter;
+	struct qlcnic_rcv_mbx_out *mbx_out;
+	int err;
+
+	err = qlcnic_sriov_validate_create_rx_ctx(cmd);
+	if (err) {
+		cmd->rsp.arg[0] |= (0x6 << 25);
+		return err;
+	}
+
+	cmd->req.arg[6] = vf->vp->handle;
+	err = qlcnic_issue_cmd(adapter, cmd);
+
+	if (!err) {
+		mbx_out = (struct qlcnic_rcv_mbx_out *)&cmd->rsp.arg[1];
+		vf->rx_ctx_id = mbx_out->ctx_id;
+		qlcnic_sriov_cfg_vf_def_mac(adapter, vf->vp, vf->pci_func,
+					    0, QLCNIC_MAC_ADD);
+	} else {
+		vf->rx_ctx_id = 0;
+	}
+
+	return err;
+}
+
+static int qlcnic_sriov_pf_mac_address_cmd(struct qlcnic_bc_trans *trans,
+					   struct qlcnic_cmd_args *cmd)
+{
+	struct qlcnic_vf_info *vf = trans->vf;
+	u8 type, *mac;
+
+	type = cmd->req.arg[1];
+	switch (type) {
+	case QLCNIC_SET_STATION_MAC:
+	case QLCNIC_SET_FAC_DEF_MAC:
+		cmd->rsp.arg[0] = (2 << 25);
+		break;
+	case QLCNIC_GET_CURRENT_MAC:
+		cmd->rsp.arg[0] = (1 << 25);
+		mac = vf->vp->mac;
+		cmd->rsp.arg[2] = mac[1] | ((mac[0] << 8) & 0xff00);
+		cmd->rsp.arg[1] = mac[5] | ((mac[4] << 8) & 0xff00) |
+				  ((mac[3]) << 16 & 0xff0000) |
+				  ((mac[2]) << 24 & 0xff000000);
+	}
+
+	return 0;
+}
+
+static int qlcnic_sriov_validate_create_tx_ctx(struct qlcnic_cmd_args *cmd)
+{
+	if ((cmd->req.arg[0] >> 29) != 0x3)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int qlcnic_sriov_pf_create_tx_ctx_cmd(struct qlcnic_bc_trans *trans,
+					     struct qlcnic_cmd_args *cmd)
+{
+	struct qlcnic_vf_info *vf = trans->vf;
+	struct qlcnic_adapter *adapter = vf->adapter;
+	struct qlcnic_tx_mbx_out *mbx_out;
+	int err;
+
+	err = qlcnic_sriov_validate_create_tx_ctx(cmd);
+	if (err) {
+		cmd->rsp.arg[0] |= (0x6 << 25);
+		return err;
+	}
+
+	cmd->req.arg[5] |= vf->vp->handle << 16;
+	err = qlcnic_issue_cmd(adapter, cmd);
+	if (!err) {
+		mbx_out = (struct qlcnic_tx_mbx_out *)&cmd->rsp.arg[2];
+		vf->tx_ctx_id = mbx_out->ctx_id;
+	} else {
+		vf->tx_ctx_id = 0;
+	}
+
+	return err;
+}
+
+static int qlcnic_sriov_validate_del_rx_ctx(struct qlcnic_vf_info *vf,
+					    struct qlcnic_cmd_args *cmd)
+{
+	if ((cmd->req.arg[0] >> 29) != 0x3)
+		return -EINVAL;
+
+	if ((cmd->req.arg[1] & 0xffff) != vf->rx_ctx_id)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int qlcnic_sriov_pf_del_rx_ctx_cmd(struct qlcnic_bc_trans *trans,
+					  struct qlcnic_cmd_args *cmd)
+{
+	struct qlcnic_vf_info *vf = trans->vf;
+	struct qlcnic_adapter *adapter = vf->adapter;
+	int err;
+
+	err = qlcnic_sriov_validate_del_rx_ctx(vf, cmd);
+	if (err) {
+		cmd->rsp.arg[0] |= (0x6 << 25);
+		return err;
+	}
+
+	qlcnic_sriov_cfg_vf_def_mac(adapter, vf->vp, vf->pci_func,
+				    0, QLCNIC_MAC_DEL);
+	cmd->req.arg[1] |= vf->vp->handle << 16;
+	err = qlcnic_issue_cmd(adapter, cmd);
+
+	if (!err)
+		vf->rx_ctx_id = 0;
+
+	return err;
+}
+
+static int qlcnic_sriov_validate_del_tx_ctx(struct qlcnic_vf_info *vf,
+					    struct qlcnic_cmd_args *cmd)
+{
+	if ((cmd->req.arg[0] >> 29) != 0x3)
+		return -EINVAL;
+
+	if ((cmd->req.arg[1] & 0xffff) != vf->tx_ctx_id)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int qlcnic_sriov_pf_del_tx_ctx_cmd(struct qlcnic_bc_trans *trans,
+					  struct qlcnic_cmd_args *cmd)
+{
+	struct qlcnic_vf_info *vf = trans->vf;
+	struct qlcnic_adapter *adapter = vf->adapter;
+	int err;
+
+	err = qlcnic_sriov_validate_del_tx_ctx(vf, cmd);
+	if (err) {
+		cmd->rsp.arg[0] |= (0x6 << 25);
+		return err;
+	}
+
+	cmd->req.arg[1] |= vf->vp->handle << 16;
+	err = qlcnic_issue_cmd(adapter, cmd);
+
+	if (!err)
+		vf->tx_ctx_id = 0;
+
+	return err;
+}
+
+static int qlcnic_sriov_validate_cfg_lro(struct qlcnic_vf_info *vf,
+					 struct qlcnic_cmd_args *cmd)
+{
+	if ((cmd->req.arg[1] >> 16) != vf->rx_ctx_id)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int qlcnic_sriov_pf_cfg_lro_cmd(struct qlcnic_bc_trans *trans,
+				       struct qlcnic_cmd_args *cmd)
+{
+	struct qlcnic_vf_info *vf = trans->vf;
+	struct qlcnic_adapter *adapter = vf->adapter;
+	int err;
+
+	err = qlcnic_sriov_validate_cfg_lro(vf, cmd);
+	if (err) {
+		cmd->rsp.arg[0] |= (0x6 << 25);
+		return err;
+	}
+
+	err = qlcnic_issue_cmd(adapter, cmd);
+	return err;
+}
+
+static int qlcnic_sriov_pf_cfg_ip_cmd(struct qlcnic_bc_trans *trans,
+				      struct qlcnic_cmd_args *cmd)
+{
+	struct qlcnic_vf_info *vf = trans->vf;
+	struct qlcnic_adapter *adapter = vf->adapter;
+	int err = -EIO;
+	u8 op;
+
+	op =  cmd->req.arg[1] & 0xff;
+
+	cmd->req.arg[1] |= vf->vp->handle << 16;
+	cmd->req.arg[1] |= BIT_31;
+
+	err = qlcnic_issue_cmd(adapter, cmd);
+	return err;
+}
+
+static int qlcnic_sriov_validate_cfg_intrpt(struct qlcnic_vf_info *vf,
+					    struct qlcnic_cmd_args *cmd)
+{
+	if (((cmd->req.arg[1] >> 8) & 0xff) != vf->pci_func)
+		return -EINVAL;
+
+	if (!(cmd->req.arg[1] & BIT_16))
+		return -EINVAL;
+
+	if ((cmd->req.arg[1] & 0xff) != 0x1)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int qlcnic_sriov_pf_cfg_intrpt_cmd(struct qlcnic_bc_trans *trans,
+					  struct qlcnic_cmd_args *cmd)
+{
+	struct qlcnic_vf_info *vf = trans->vf;
+	struct qlcnic_adapter *adapter = vf->adapter;
+	int err;
+
+	err = qlcnic_sriov_validate_cfg_intrpt(vf, cmd);
+	if (err)
+		cmd->rsp.arg[0] |= (0x6 << 25);
+	else
+		err = qlcnic_issue_cmd(adapter, cmd);
+
+	return err;
+}
+
+static int qlcnic_sriov_validate_mtu(struct qlcnic_adapter *adapter,
+				     struct qlcnic_vf_info *vf,
+				     struct qlcnic_cmd_args *cmd)
+{
+	if (cmd->req.arg[1] != vf->rx_ctx_id)
+		return -EINVAL;
+
+	if (cmd->req.arg[2] > adapter->ahw->max_mtu)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int qlcnic_sriov_pf_set_mtu_cmd(struct qlcnic_bc_trans *trans,
+				       struct qlcnic_cmd_args *cmd)
+{
+	struct qlcnic_vf_info *vf = trans->vf;
+	struct qlcnic_adapter *adapter = vf->adapter;
+	int err;
+
+	err = qlcnic_sriov_validate_mtu(adapter, vf, cmd);
+	if (err)
+		cmd->rsp.arg[0] |= (0x6 << 25);
+	else
+		err = qlcnic_issue_cmd(adapter, cmd);
+
+	return err;
+}
+
+static int qlcnic_sriov_validate_get_nic_info(struct qlcnic_vf_info *vf,
+					      struct qlcnic_cmd_args *cmd)
+{
+	if (cmd->req.arg[1] & BIT_31) {
+		if (((cmd->req.arg[1] >> 16) & 0x7fff) != vf->pci_func)
+			return -EINVAL;
+	} else {
+		cmd->req.arg[1] |= vf->vp->handle << 16;
+	}
+
+	return 0;
+}
+
+static int qlcnic_sriov_pf_get_nic_info_cmd(struct qlcnic_bc_trans *trans,
+					    struct qlcnic_cmd_args *cmd)
+{
+	struct qlcnic_vf_info *vf = trans->vf;
+	struct qlcnic_adapter *adapter = vf->adapter;
+	int err;
+
+	err = qlcnic_sriov_validate_get_nic_info(vf, cmd);
+	if (err) {
+		cmd->rsp.arg[0] |= (0x6 << 25);
+		return err;
+	}
+
+	err = qlcnic_issue_cmd(adapter, cmd);
+	return err;
+}
+
+static int qlcnic_sriov_validate_cfg_rss(struct qlcnic_vf_info *vf,
+					 struct qlcnic_cmd_args *cmd)
+{
+	if (cmd->req.arg[1] != vf->rx_ctx_id)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int qlcnic_sriov_pf_cfg_rss_cmd(struct qlcnic_bc_trans *trans,
+				       struct qlcnic_cmd_args *cmd)
+{
+	struct qlcnic_vf_info *vf = trans->vf;
+	struct qlcnic_adapter *adapter = vf->adapter;
+	int err;
+
+	err = qlcnic_sriov_validate_cfg_rss(vf, cmd);
+	if (err)
+		cmd->rsp.arg[0] |= (0x6 << 25);
+	else
+		err = qlcnic_issue_cmd(adapter, cmd);
+
+	return err;
+}
+
+static int qlcnic_sriov_validate_cfg_intrcoal(struct qlcnic_adapter *adapter,
+					      struct qlcnic_vf_info *vf,
+					      struct qlcnic_cmd_args *cmd)
+{
+	struct qlcnic_nic_intr_coalesce *coal = &adapter->ahw->coal;
+	u16 ctx_id, pkts, time;
+
+	ctx_id = cmd->req.arg[1] >> 16;
+	pkts = cmd->req.arg[2] & 0xffff;
+	time = cmd->req.arg[2] >> 16;
+
+	if (ctx_id != vf->rx_ctx_id)
+		return -EINVAL;
+	if (pkts > coal->rx_packets)
+		return -EINVAL;
+	if (time < coal->rx_time_us)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int qlcnic_sriov_pf_cfg_intrcoal_cmd(struct qlcnic_bc_trans *tran,
+					    struct qlcnic_cmd_args *cmd)
+{
+	struct qlcnic_vf_info *vf = tran->vf;
+	struct qlcnic_adapter *adapter = vf->adapter;
+	int err;
+
+	err = qlcnic_sriov_validate_cfg_intrcoal(adapter, vf, cmd);
+	if (err) {
+		cmd->rsp.arg[0] |= (0x6 << 25);
+		return err;
+	}
+
+	err = qlcnic_issue_cmd(adapter, cmd);
+	return err;
+}
+
+static int qlcnic_sriov_validate_cfg_macvlan(struct qlcnic_adapter *adapter,
+					     struct qlcnic_vf_info *vf,
+					     struct qlcnic_cmd_args *cmd)
+{
+	struct qlcnic_macvlan_mbx *macvlan;
+
+	if (!(cmd->req.arg[1] & BIT_8))
+		return -EINVAL;
+
+	cmd->req.arg[1] |= (vf->vp->handle << 16);
+	cmd->req.arg[1] |= BIT_31;
+
+	macvlan = (struct qlcnic_macvlan_mbx *)&cmd->req.arg[2];
+	if (!(macvlan->mac_addr0 & BIT_0)) {
+		dev_err(&adapter->pdev->dev,
+			"MAC address change is not allowed from VF %d",
+			vf->pci_func);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int qlcnic_sriov_pf_cfg_macvlan_cmd(struct qlcnic_bc_trans *trans,
+					   struct qlcnic_cmd_args *cmd)
+{
+	struct qlcnic_vf_info *vf = trans->vf;
+	struct qlcnic_adapter *adapter = vf->adapter;
+	int err;
+
+	err = qlcnic_sriov_validate_cfg_macvlan(adapter, vf, cmd);
+	if (err) {
+		cmd->rsp.arg[0] |= (0x6 << 25);
+		return err;
+	}
+
+	err = qlcnic_issue_cmd(adapter, cmd);
+	return err;
+}
+
+static int qlcnic_sriov_validate_linkevent(struct qlcnic_vf_info *vf,
+					   struct qlcnic_cmd_args *cmd)
+{
+	if ((cmd->req.arg[1] >> 16) != vf->rx_ctx_id)
+		return -EINVAL;
+
+	if (!(cmd->req.arg[1] & BIT_8))
+		return -EINVAL;
+
+	return 0;
+}
+
+static int qlcnic_sriov_pf_linkevent_cmd(struct qlcnic_bc_trans *trans,
+					 struct qlcnic_cmd_args *cmd)
+{
+	struct qlcnic_vf_info *vf = trans->vf;
+	struct qlcnic_adapter *adapter = vf->adapter;
+	int err;
+
+	err = qlcnic_sriov_validate_linkevent(vf, cmd);
+	if (err) {
+		cmd->rsp.arg[0] |= (0x6 << 25);
+		return err;
+	}
+
+	err = qlcnic_issue_cmd(adapter, cmd);
+	return err;
+}
+
+static int qlcnic_sriov_pf_cfg_promisc_cmd(struct qlcnic_bc_trans *trans,
+					   struct qlcnic_cmd_args *cmd)
+{
+	struct qlcnic_vf_info *vf = trans->vf;
+	struct qlcnic_adapter *adapter = vf->adapter;
+	int err;
+
+	cmd->req.arg[1] |= vf->vp->handle << 16;
+	cmd->req.arg[1] |= BIT_31;
+	err = qlcnic_issue_cmd(adapter, cmd);
+	return err;
+}
+
+static const int qlcnic_pf_passthru_supp_cmds[] = {
+	QLCNIC_CMD_GET_STATISTICS,
+	QLCNIC_CMD_GET_PORT_CONFIG,
+	QLCNIC_CMD_GET_LINK_STATUS,
+};
+
+static const struct qlcnic_sriov_cmd_handler qlcnic_pf_bc_cmd_hdlr[] = {
+	[QLCNIC_BC_CMD_CHANNEL_INIT] = {&qlcnic_sriov_pf_channel_cfg_cmd},
+	[QLCNIC_BC_CMD_CHANNEL_TERM] = {&qlcnic_sriov_pf_channel_cfg_cmd},
+};
+
+static const struct qlcnic_sriov_fw_cmd_handler qlcnic_pf_fw_cmd_hdlr[] = {
+	{QLCNIC_CMD_CREATE_RX_CTX, qlcnic_sriov_pf_create_rx_ctx_cmd},
+	{QLCNIC_CMD_CREATE_TX_CTX, qlcnic_sriov_pf_create_tx_ctx_cmd},
+	{QLCNIC_CMD_MAC_ADDRESS, qlcnic_sriov_pf_mac_address_cmd},
+	{QLCNIC_CMD_DESTROY_RX_CTX, qlcnic_sriov_pf_del_rx_ctx_cmd},
+	{QLCNIC_CMD_DESTROY_TX_CTX, qlcnic_sriov_pf_del_tx_ctx_cmd},
+	{QLCNIC_CMD_CONFIGURE_HW_LRO, qlcnic_sriov_pf_cfg_lro_cmd},
+	{QLCNIC_CMD_CONFIGURE_IP_ADDR, qlcnic_sriov_pf_cfg_ip_cmd},
+	{QLCNIC_CMD_CONFIG_INTRPT, qlcnic_sriov_pf_cfg_intrpt_cmd},
+	{QLCNIC_CMD_SET_MTU, qlcnic_sriov_pf_set_mtu_cmd},
+	{QLCNIC_CMD_GET_NIC_INFO, qlcnic_sriov_pf_get_nic_info_cmd},
+	{QLCNIC_CMD_CONFIGURE_RSS, qlcnic_sriov_pf_cfg_rss_cmd},
+	{QLCNIC_CMD_CONFIG_INTR_COAL, qlcnic_sriov_pf_cfg_intrcoal_cmd},
+	{QLCNIC_CMD_CONFIG_MAC_VLAN, qlcnic_sriov_pf_cfg_macvlan_cmd},
+	{QLCNIC_CMD_GET_LINK_EVENT, qlcnic_sriov_pf_linkevent_cmd},
+	{QLCNIC_CMD_CONFIGURE_MAC_RX_MODE, qlcnic_sriov_pf_cfg_promisc_cmd},
+};
+
+void qlcnic_sriov_pf_process_bc_cmd(struct qlcnic_adapter *adapter,
+				    struct qlcnic_bc_trans *trans,
+				    struct qlcnic_cmd_args *cmd)
+{
+	u8 size, cmd_op;
+
+	cmd_op = trans->req_hdr->cmd_op;
+
+	if (trans->req_hdr->op_type == QLC_BC_CMD) {
+		size = ARRAY_SIZE(qlcnic_pf_bc_cmd_hdlr);
+		if (cmd_op < size) {
+			qlcnic_pf_bc_cmd_hdlr[cmd_op].fn(trans, cmd);
+			return;
+		}
+	} else {
+		int i;
+		size = ARRAY_SIZE(qlcnic_pf_fw_cmd_hdlr);
+		for (i = 0; i < size; i++) {
+			if (cmd_op == qlcnic_pf_fw_cmd_hdlr[i].cmd) {
+				qlcnic_pf_fw_cmd_hdlr[i].fn(trans, cmd);
+				return;
+			}
+		}
+
+		size = ARRAY_SIZE(qlcnic_pf_passthru_supp_cmds);
+		for (i = 0; i < size; i++) {
+			if (cmd_op == qlcnic_pf_passthru_supp_cmds[i]) {
+				qlcnic_issue_cmd(adapter, cmd);
+				return;
+			}
+		}
+	}
+
+	cmd->rsp.arg[0] |= (0x9 << 25);
+}
+
+void qlcnic_pf_set_interface_id_create_rx_ctx(struct qlcnic_adapter *adapter,
+					     u32 *int_id)
+{
+	u16 vpid;
+
+	vpid = qlcnic_sriov_pf_get_vport_handle(adapter,
+						adapter->ahw->pci_func);
+	*int_id |= vpid;
+}
+
+void qlcnic_pf_set_interface_id_del_rx_ctx(struct qlcnic_adapter *adapter,
+					   u32 *int_id)
+{
+	u16 vpid;
+
+	vpid = qlcnic_sriov_pf_get_vport_handle(adapter,
+						adapter->ahw->pci_func);
+	*int_id |= vpid << 16;
+}
+
+void qlcnic_pf_set_interface_id_create_tx_ctx(struct qlcnic_adapter *adapter,
+					      u32 *int_id)
+{
+	int vpid;
+
+	vpid = qlcnic_sriov_pf_get_vport_handle(adapter,
+						adapter->ahw->pci_func);
+	*int_id |= vpid << 16;
+}
+
+void qlcnic_pf_set_interface_id_del_tx_ctx(struct qlcnic_adapter *adapter,
+					   u32 *int_id)
+{
+	u16 vpid;
+
+	vpid = qlcnic_sriov_pf_get_vport_handle(adapter,
+						adapter->ahw->pci_func);
+	*int_id |= vpid << 16;
+}
+
+void qlcnic_pf_set_interface_id_promisc(struct qlcnic_adapter *adapter,
+					u32 *int_id)
+{
+	u16 vpid;
+
+	vpid = qlcnic_sriov_pf_get_vport_handle(adapter,
+						adapter->ahw->pci_func);
+	*int_id |= (vpid << 16) | BIT_31;
+}
+
+void qlcnic_pf_set_interface_id_ipaddr(struct qlcnic_adapter *adapter,
+				       u32 *int_id)
+{
+	u16 vpid;
+
+	vpid = qlcnic_sriov_pf_get_vport_handle(adapter,
+						adapter->ahw->pci_func);
+	*int_id |= (vpid << 16) | BIT_31;
+}
+
+void qlcnic_pf_set_interface_id_macaddr(struct qlcnic_adapter *adapter,
+					u32 *int_id)
+{
+	u16 vpid;
+
+	vpid = qlcnic_sriov_pf_get_vport_handle(adapter,
+						adapter->ahw->pci_func);
+	*int_id |= (vpid << 16) | BIT_31;
+}
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c
index 987fb6f..c77675d 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c
@@ -21,8 +21,6 @@
 #include <linux/aer.h>
 #include <linux/log2.h>
 
-#include <linux/sysfs.h>
-
 #define QLC_STATUS_UNSUPPORTED_CMD	-2
 
 int qlcnicvf_config_bridged_mode(struct qlcnic_adapter *adapter, u32 enable)
@@ -886,6 +884,244 @@ static ssize_t qlcnic_sysfs_read_pci_config(struct file *file,
 	return size;
 }
 
+static ssize_t qlcnic_83xx_sysfs_flash_read_handler(struct file *filp,
+						    struct kobject *kobj,
+						    struct bin_attribute *attr,
+						    char *buf, loff_t offset,
+						    size_t size)
+{
+	unsigned char *p_read_buf;
+	int  ret, count;
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+
+	if (!size)
+		return QL_STATUS_INVALID_PARAM;
+	if (!buf)
+		return QL_STATUS_INVALID_PARAM;
+
+	count = size / sizeof(u32);
+
+	if (size % sizeof(u32))
+		count++;
+
+	p_read_buf = kcalloc(size, sizeof(unsigned char), GFP_KERNEL);
+	if (!p_read_buf)
+		return -ENOMEM;
+	if (qlcnic_83xx_lock_flash(adapter) != 0) {
+		kfree(p_read_buf);
+		return -EIO;
+	}
+
+	ret = qlcnic_83xx_lockless_flash_read32(adapter, offset, p_read_buf,
+						count);
+
+	if (ret) {
+		qlcnic_83xx_unlock_flash(adapter);
+		kfree(p_read_buf);
+		return ret;
+	}
+
+	qlcnic_83xx_unlock_flash(adapter);
+	memcpy(buf, p_read_buf, size);
+	kfree(p_read_buf);
+
+	return size;
+}
+
+static int qlcnic_83xx_sysfs_flash_bulk_write(struct qlcnic_adapter *adapter,
+					      char *buf, loff_t offset,
+					      size_t size)
+{
+	int  i, ret, count;
+	unsigned char *p_cache, *p_src;
+
+	p_cache = kcalloc(size, sizeof(unsigned char), GFP_KERNEL);
+	if (!p_cache)
+		return -ENOMEM;
+
+	memcpy(p_cache, buf, size);
+	p_src = p_cache;
+	count = size / sizeof(u32);
+
+	if (qlcnic_83xx_lock_flash(adapter) != 0) {
+		kfree(p_cache);
+		return -EIO;
+	}
+
+	if (adapter->ahw->fdt.mfg_id == adapter->flash_mfg_id) {
+		ret = qlcnic_83xx_enable_flash_write(adapter);
+		if (ret) {
+			kfree(p_cache);
+			qlcnic_83xx_unlock_flash(adapter);
+			return -EIO;
+		}
+	}
+
+	for (i = 0; i < count / QLC_83XX_FLASH_WRITE_MAX; i++) {
+		ret = qlcnic_83xx_flash_bulk_write(adapter, offset,
+						   (u32 *)p_src,
+						   QLC_83XX_FLASH_WRITE_MAX);
+
+		if (ret) {
+			if (adapter->ahw->fdt.mfg_id == adapter->flash_mfg_id) {
+				ret = qlcnic_83xx_disable_flash_write(adapter);
+				if (ret) {
+					kfree(p_cache);
+					qlcnic_83xx_unlock_flash(adapter);
+					return -EIO;
+				}
+			}
+
+			kfree(p_cache);
+			qlcnic_83xx_unlock_flash(adapter);
+			return -EIO;
+		}
+
+		p_src = p_src + sizeof(u32)*QLC_83XX_FLASH_WRITE_MAX;
+		offset = offset + sizeof(u32)*QLC_83XX_FLASH_WRITE_MAX;
+	}
+
+	if (adapter->ahw->fdt.mfg_id == adapter->flash_mfg_id) {
+		ret = qlcnic_83xx_disable_flash_write(adapter);
+		if (ret) {
+			kfree(p_cache);
+			qlcnic_83xx_unlock_flash(adapter);
+			return -EIO;
+		}
+	}
+
+	kfree(p_cache);
+	qlcnic_83xx_unlock_flash(adapter);
+
+	return 0;
+}
+
+static int qlcnic_83xx_sysfs_flash_write(struct qlcnic_adapter *adapter,
+					 char *buf, loff_t offset, size_t size)
+{
+	int  i, ret, count;
+	unsigned char *p_cache, *p_src;
+
+	p_cache = kcalloc(size, sizeof(unsigned char), GFP_KERNEL);
+	if (!p_cache)
+		return -ENOMEM;
+
+	memcpy(p_cache, buf, size);
+	p_src = p_cache;
+	count = size / sizeof(u32);
+
+	if (qlcnic_83xx_lock_flash(adapter) != 0) {
+		kfree(p_cache);
+		return -EIO;
+	}
+
+	if (adapter->ahw->fdt.mfg_id == adapter->flash_mfg_id) {
+		ret = qlcnic_83xx_enable_flash_write(adapter);
+		if (ret) {
+			kfree(p_cache);
+			qlcnic_83xx_unlock_flash(adapter);
+			return -EIO;
+		}
+	}
+
+	for (i = 0; i < count; i++) {
+		ret = qlcnic_83xx_flash_write32(adapter, offset, (u32 *)p_src);
+		if (ret) {
+			if (adapter->ahw->fdt.mfg_id == adapter->flash_mfg_id) {
+				ret = qlcnic_83xx_disable_flash_write(adapter);
+				if (ret) {
+					kfree(p_cache);
+					qlcnic_83xx_unlock_flash(adapter);
+					return -EIO;
+				}
+			}
+			kfree(p_cache);
+			qlcnic_83xx_unlock_flash(adapter);
+			return -EIO;
+		}
+
+		p_src = p_src + sizeof(u32);
+		offset = offset + sizeof(u32);
+	}
+
+	if (adapter->ahw->fdt.mfg_id == adapter->flash_mfg_id) {
+		ret = qlcnic_83xx_disable_flash_write(adapter);
+		if (ret) {
+			kfree(p_cache);
+			qlcnic_83xx_unlock_flash(adapter);
+			return -EIO;
+		}
+	}
+
+	kfree(p_cache);
+	qlcnic_83xx_unlock_flash(adapter);
+
+	return 0;
+}
+
+static ssize_t qlcnic_83xx_sysfs_flash_write_handler(struct file *filp,
+						     struct kobject *kobj,
+						     struct bin_attribute *attr,
+						     char *buf, loff_t offset,
+						     size_t size)
+{
+	int  ret;
+	static int flash_mode;
+	unsigned long data;
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+
+	if (!buf)
+		return QL_STATUS_INVALID_PARAM;
+
+	ret = kstrtoul(buf, 16, &data);
+
+	switch (data) {
+	case QLC_83XX_FLASH_SECTOR_ERASE_CMD:
+		flash_mode = QLC_83XX_ERASE_MODE;
+		ret = qlcnic_83xx_erase_flash_sector(adapter, offset);
+		if (ret) {
+			dev_err(&adapter->pdev->dev,
+				"%s failed at %d\n", __func__, __LINE__);
+			return -EIO;
+		}
+		break;
+
+	case QLC_83XX_FLASH_BULK_WRITE_CMD:
+		flash_mode = QLC_83XX_BULK_WRITE_MODE;
+		break;
+
+	case QLC_83XX_FLASH_WRITE_CMD:
+		flash_mode = QLC_83XX_WRITE_MODE;
+		break;
+	default:
+		if (flash_mode == QLC_83XX_BULK_WRITE_MODE) {
+			ret = qlcnic_83xx_sysfs_flash_bulk_write(adapter, buf,
+								 offset, size);
+			if (ret) {
+				dev_err(&adapter->pdev->dev,
+					"%s failed at %d\n",
+					__func__, __LINE__);
+				return -EIO;
+			}
+		}
+
+		if (flash_mode == QLC_83XX_WRITE_MODE) {
+			ret = qlcnic_83xx_sysfs_flash_write(adapter, buf,
+							    offset, size);
+			if (ret) {
+				dev_err(&adapter->pdev->dev,
+					"%s failed at %d\n", __func__,
+					__LINE__);
+				return -EIO;
+			}
+		}
+	}
+
+	return size;
+}
+
 static struct device_attribute dev_attr_bridged_mode = {
        .attr = {.name = "bridged_mode", .mode = (S_IRUGO | S_IWUSR)},
        .show = qlcnic_show_bridged_mode,
@@ -960,6 +1196,13 @@ static struct bin_attribute bin_attr_pm_config = {
 	.write = qlcnic_sysfs_write_pm_config,
 };
 
+static struct bin_attribute bin_attr_flash = {
+	.attr = {.name = "flash", .mode = (S_IRUGO | S_IWUSR)},
+	.size = 0,
+	.read = qlcnic_83xx_sysfs_flash_read_handler,
+	.write = qlcnic_83xx_sysfs_flash_write_handler,
+};
+
 void qlcnic_create_sysfs_entries(struct qlcnic_adapter *adapter)
 {
 	struct device *dev = &adapter->pdev->dev;
@@ -1048,10 +1291,18 @@ void qlcnic_82xx_remove_sysfs(struct qlcnic_adapter *adapter)
 
 void qlcnic_83xx_add_sysfs(struct qlcnic_adapter *adapter)
 {
+	struct device *dev = &adapter->pdev->dev;
+
 	qlcnic_create_diag_entries(adapter);
+
+	if (sysfs_create_bin_file(&dev->kobj, &bin_attr_flash))
+		dev_info(dev, "failed to create flash sysfs entry\n");
 }
 
 void qlcnic_83xx_remove_sysfs(struct qlcnic_adapter *adapter)
 {
+	struct device *dev = &adapter->pdev->dev;
+
 	qlcnic_remove_diag_entries(adapter);
+	sysfs_remove_bin_file(&dev->kobj, &bin_attr_flash);
 }
diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_main.c b/drivers/net/ethernet/qlogic/qlge/qlge_main.c
index b13ab54..1dd778a 100644
--- a/drivers/net/ethernet/qlogic/qlge/qlge_main.c
+++ b/drivers/net/ethernet/qlogic/qlge/qlge_main.c
@@ -1211,8 +1211,6 @@ static void ql_update_sbq(struct ql_adapter *qdev, struct rx_ring *rx_ring)
 				    netdev_alloc_skb(qdev->ndev,
 						     SMALL_BUFFER_SIZE);
 				if (sbq_desc->p.skb == NULL) {
-					netif_err(qdev, probe, qdev->ndev,
-						  "Couldn't get an skb.\n");
 					rx_ring->sbq_clean_idx = clean_idx;
 					return;
 				}
@@ -1519,8 +1517,6 @@ static void ql_process_mac_rx_page(struct ql_adapter *qdev,
 
 	skb = netdev_alloc_skb(ndev, length);
 	if (!skb) {
-		netif_err(qdev, drv, qdev->ndev,
-			  "Couldn't get an skb, need to unwind!.\n");
 		rx_ring->rx_dropped++;
 		put_page(lbq_desc->p.pg_chunk.page);
 		return;
@@ -1605,8 +1601,6 @@ static void ql_process_mac_rx_skb(struct ql_adapter *qdev,
 	/* Allocate new_skb and copy */
 	new_skb = netdev_alloc_skb(qdev->ndev, length + NET_IP_ALIGN);
 	if (new_skb == NULL) {
-		netif_err(qdev, probe, qdev->ndev,
-			  "No skb available, drop the packet.\n");
 		rx_ring->rx_dropped++;
 		return;
 	}
diff --git a/drivers/net/ethernet/rdc/r6040.c b/drivers/net/ethernet/rdc/r6040.c
index 5b4103d..e9dc849 100644
--- a/drivers/net/ethernet/rdc/r6040.c
+++ b/drivers/net/ethernet/rdc/r6040.c
@@ -224,11 +224,14 @@ static int r6040_phy_read(void __iomem *ioaddr, int phy_addr, int reg)
 			break;
 	}
 
+	if (limit < 0)
+		return -ETIMEDOUT;
+
 	return ioread16(ioaddr + MMRD);
 }
 
 /* Write a word data from PHY Chip */
-static void r6040_phy_write(void __iomem *ioaddr,
+static int r6040_phy_write(void __iomem *ioaddr,
 					int phy_addr, int reg, u16 val)
 {
 	int limit = MAC_DEF_TIMEOUT;
@@ -243,6 +246,8 @@ static void r6040_phy_write(void __iomem *ioaddr,
 		if (!(cmd & MDIO_WRITE))
 			break;
 	}
+
+	return (limit < 0) ? -ETIMEDOUT : 0;
 }
 
 static int r6040_mdiobus_read(struct mii_bus *bus, int phy_addr, int reg)
@@ -261,9 +266,7 @@ static int r6040_mdiobus_write(struct mii_bus *bus, int phy_addr,
 	struct r6040_private *lp = netdev_priv(dev);
 	void __iomem *ioaddr = lp->base;
 
-	r6040_phy_write(ioaddr, phy_addr, reg, value);
-
-	return 0;
+	return r6040_phy_write(ioaddr, phy_addr, reg, value);
 }
 
 static int r6040_mdiobus_reset(struct mii_bus *bus)
@@ -347,7 +350,6 @@ static int r6040_alloc_rxbufs(struct net_device *dev)
 	do {
 		skb = netdev_alloc_skb(dev, MAX_BUF_SIZE);
 		if (!skb) {
-			netdev_err(dev, "failed to alloc skb for rx\n");
 			rc = -ENOMEM;
 			goto err_exit;
 		}
diff --git a/drivers/net/ethernet/realtek/8139too.c b/drivers/net/ethernet/realtek/8139too.c
index 1276ac7..3ccedeb 100644
--- a/drivers/net/ethernet/realtek/8139too.c
+++ b/drivers/net/ethernet/realtek/8139too.c
@@ -2041,8 +2041,6 @@ keep_pkt:
 
 			netif_receive_skb (skb);
 		} else {
-			if (net_ratelimit())
-				netdev_warn(dev, "Memory squeeze, dropping packet\n");
 			dev->stats.rx_dropped++;
 		}
 		received++;
diff --git a/drivers/net/ethernet/realtek/atp.c b/drivers/net/ethernet/realtek/atp.c
index 9f2d416..d77d60e 100644
--- a/drivers/net/ethernet/realtek/atp.c
+++ b/drivers/net/ethernet/realtek/atp.c
@@ -782,8 +782,6 @@ static void net_rx(struct net_device *dev)
 
 		skb = netdev_alloc_skb(dev, pkt_len + 2);
 		if (skb == NULL) {
-			printk(KERN_ERR "%s: Memory squeeze, dropping packet.\n",
-				   dev->name);
 			dev->stats.rx_dropped++;
 			goto done;
 		}
diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
index 28fb50a..4ecbe64 100644
--- a/drivers/net/ethernet/realtek/r8169.c
+++ b/drivers/net/ethernet/realtek/r8169.c
@@ -3818,6 +3818,30 @@ static void rtl_init_mdio_ops(struct rtl8169_private *tp)
 	}
 }
 
+static void rtl_speed_down(struct rtl8169_private *tp)
+{
+	u32 adv;
+	int lpa;
+
+	rtl_writephy(tp, 0x1f, 0x0000);
+	lpa = rtl_readphy(tp, MII_LPA);
+
+	if (lpa & (LPA_10HALF | LPA_10FULL))
+		adv = ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full;
+	else if (lpa & (LPA_100HALF | LPA_100FULL))
+		adv = ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |
+		      ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full;
+	else
+		adv = ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |
+		      ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full |
+		      (tp->mii.supports_gmii ?
+		       ADVERTISED_1000baseT_Half |
+		       ADVERTISED_1000baseT_Full : 0);
+
+	rtl8169_set_speed(tp->dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL,
+			  adv);
+}
+
 static void rtl_wol_suspend_quirk(struct rtl8169_private *tp)
 {
 	void __iomem *ioaddr = tp->mmio_addr;
@@ -3848,9 +3872,7 @@ static bool rtl_wol_pll_power_down(struct rtl8169_private *tp)
 	if (!(__rtl8169_get_wol(tp) & WAKE_ANY))
 		return false;
 
-	rtl_writephy(tp, 0x1f, 0x0000);
-	rtl_writephy(tp, MII_BMCR, 0x0000);
-
+	rtl_speed_down(tp);
 	rtl_wol_suspend_quirk(tp);
 
 	return true;
diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
index bf5e3cf..a7499cb 100644
--- a/drivers/net/ethernet/renesas/sh_eth.c
+++ b/drivers/net/ethernet/renesas/sh_eth.c
@@ -2,7 +2,8 @@
  *  SuperH Ethernet device driver
  *
  *  Copyright (C) 2006-2012 Nobuhiro Iwamatsu
- *  Copyright (C) 2008-2012 Renesas Solutions Corp.
+ *  Copyright (C) 2008-2013 Renesas Solutions Corp.
+ *  Copyright (C) 2013 Cogent Embedded, Inc.
  *
  *  This program is free software; you can redistribute it and/or modify it
  *  under the terms and conditions of the GNU General Public License,
@@ -49,6 +50,269 @@
 		NETIF_MSG_RX_ERR| \
 		NETIF_MSG_TX_ERR)
 
+static const u16 sh_eth_offset_gigabit[SH_ETH_MAX_REGISTER_OFFSET] = {
+	[EDSR]		= 0x0000,
+	[EDMR]		= 0x0400,
+	[EDTRR]		= 0x0408,
+	[EDRRR]		= 0x0410,
+	[EESR]		= 0x0428,
+	[EESIPR]	= 0x0430,
+	[TDLAR]		= 0x0010,
+	[TDFAR]		= 0x0014,
+	[TDFXR]		= 0x0018,
+	[TDFFR]		= 0x001c,
+	[RDLAR]		= 0x0030,
+	[RDFAR]		= 0x0034,
+	[RDFXR]		= 0x0038,
+	[RDFFR]		= 0x003c,
+	[TRSCER]	= 0x0438,
+	[RMFCR]		= 0x0440,
+	[TFTR]		= 0x0448,
+	[FDR]		= 0x0450,
+	[RMCR]		= 0x0458,
+	[RPADIR]	= 0x0460,
+	[FCFTR]		= 0x0468,
+	[CSMR]		= 0x04E4,
+
+	[ECMR]		= 0x0500,
+	[ECSR]		= 0x0510,
+	[ECSIPR]	= 0x0518,
+	[PIR]		= 0x0520,
+	[PSR]		= 0x0528,
+	[PIPR]		= 0x052c,
+	[RFLR]		= 0x0508,
+	[APR]		= 0x0554,
+	[MPR]		= 0x0558,
+	[PFTCR]		= 0x055c,
+	[PFRCR]		= 0x0560,
+	[TPAUSER]	= 0x0564,
+	[GECMR]		= 0x05b0,
+	[BCULR]		= 0x05b4,
+	[MAHR]		= 0x05c0,
+	[MALR]		= 0x05c8,
+	[TROCR]		= 0x0700,
+	[CDCR]		= 0x0708,
+	[LCCR]		= 0x0710,
+	[CEFCR]		= 0x0740,
+	[FRECR]		= 0x0748,
+	[TSFRCR]	= 0x0750,
+	[TLFRCR]	= 0x0758,
+	[RFCR]		= 0x0760,
+	[CERCR]		= 0x0768,
+	[CEECR]		= 0x0770,
+	[MAFCR]		= 0x0778,
+	[RMII_MII]	= 0x0790,
+
+	[ARSTR]		= 0x0000,
+	[TSU_CTRST]	= 0x0004,
+	[TSU_FWEN0]	= 0x0010,
+	[TSU_FWEN1]	= 0x0014,
+	[TSU_FCM]	= 0x0018,
+	[TSU_BSYSL0]	= 0x0020,
+	[TSU_BSYSL1]	= 0x0024,
+	[TSU_PRISL0]	= 0x0028,
+	[TSU_PRISL1]	= 0x002c,
+	[TSU_FWSL0]	= 0x0030,
+	[TSU_FWSL1]	= 0x0034,
+	[TSU_FWSLC]	= 0x0038,
+	[TSU_QTAG0]	= 0x0040,
+	[TSU_QTAG1]	= 0x0044,
+	[TSU_FWSR]	= 0x0050,
+	[TSU_FWINMK]	= 0x0054,
+	[TSU_ADQT0]	= 0x0048,
+	[TSU_ADQT1]	= 0x004c,
+	[TSU_VTAG0]	= 0x0058,
+	[TSU_VTAG1]	= 0x005c,
+	[TSU_ADSBSY]	= 0x0060,
+	[TSU_TEN]	= 0x0064,
+	[TSU_POST1]	= 0x0070,
+	[TSU_POST2]	= 0x0074,
+	[TSU_POST3]	= 0x0078,
+	[TSU_POST4]	= 0x007c,
+	[TSU_ADRH0]	= 0x0100,
+	[TSU_ADRL0]	= 0x0104,
+	[TSU_ADRH31]	= 0x01f8,
+	[TSU_ADRL31]	= 0x01fc,
+
+	[TXNLCR0]	= 0x0080,
+	[TXALCR0]	= 0x0084,
+	[RXNLCR0]	= 0x0088,
+	[RXALCR0]	= 0x008c,
+	[FWNLCR0]	= 0x0090,
+	[FWALCR0]	= 0x0094,
+	[TXNLCR1]	= 0x00a0,
+	[TXALCR1]	= 0x00a0,
+	[RXNLCR1]	= 0x00a8,
+	[RXALCR1]	= 0x00ac,
+	[FWNLCR1]	= 0x00b0,
+	[FWALCR1]	= 0x00b4,
+};
+
+static const u16 sh_eth_offset_fast_rcar[SH_ETH_MAX_REGISTER_OFFSET] = {
+	[ECMR]		= 0x0300,
+	[RFLR]		= 0x0308,
+	[ECSR]		= 0x0310,
+	[ECSIPR]	= 0x0318,
+	[PIR]		= 0x0320,
+	[PSR]		= 0x0328,
+	[RDMLR]		= 0x0340,
+	[IPGR]		= 0x0350,
+	[APR]		= 0x0354,
+	[MPR]		= 0x0358,
+	[RFCF]		= 0x0360,
+	[TPAUSER]	= 0x0364,
+	[TPAUSECR]	= 0x0368,
+	[MAHR]		= 0x03c0,
+	[MALR]		= 0x03c8,
+	[TROCR]		= 0x03d0,
+	[CDCR]		= 0x03d4,
+	[LCCR]		= 0x03d8,
+	[CNDCR]		= 0x03dc,
+	[CEFCR]		= 0x03e4,
+	[FRECR]		= 0x03e8,
+	[TSFRCR]	= 0x03ec,
+	[TLFRCR]	= 0x03f0,
+	[RFCR]		= 0x03f4,
+	[MAFCR]		= 0x03f8,
+
+	[EDMR]		= 0x0200,
+	[EDTRR]		= 0x0208,
+	[EDRRR]		= 0x0210,
+	[TDLAR]		= 0x0218,
+	[RDLAR]		= 0x0220,
+	[EESR]		= 0x0228,
+	[EESIPR]	= 0x0230,
+	[TRSCER]	= 0x0238,
+	[RMFCR]		= 0x0240,
+	[TFTR]		= 0x0248,
+	[FDR]		= 0x0250,
+	[RMCR]		= 0x0258,
+	[TFUCR]		= 0x0264,
+	[RFOCR]		= 0x0268,
+	[FCFTR]		= 0x0270,
+	[TRIMD]		= 0x027c,
+};
+
+static const u16 sh_eth_offset_fast_sh4[SH_ETH_MAX_REGISTER_OFFSET] = {
+	[ECMR]		= 0x0100,
+	[RFLR]		= 0x0108,
+	[ECSR]		= 0x0110,
+	[ECSIPR]	= 0x0118,
+	[PIR]		= 0x0120,
+	[PSR]		= 0x0128,
+	[RDMLR]		= 0x0140,
+	[IPGR]		= 0x0150,
+	[APR]		= 0x0154,
+	[MPR]		= 0x0158,
+	[TPAUSER]	= 0x0164,
+	[RFCF]		= 0x0160,
+	[TPAUSECR]	= 0x0168,
+	[BCFRR]		= 0x016c,
+	[MAHR]		= 0x01c0,
+	[MALR]		= 0x01c8,
+	[TROCR]		= 0x01d0,
+	[CDCR]		= 0x01d4,
+	[LCCR]		= 0x01d8,
+	[CNDCR]		= 0x01dc,
+	[CEFCR]		= 0x01e4,
+	[FRECR]		= 0x01e8,
+	[TSFRCR]	= 0x01ec,
+	[TLFRCR]	= 0x01f0,
+	[RFCR]		= 0x01f4,
+	[MAFCR]		= 0x01f8,
+	[RTRATE]	= 0x01fc,
+
+	[EDMR]		= 0x0000,
+	[EDTRR]		= 0x0008,
+	[EDRRR]		= 0x0010,
+	[TDLAR]		= 0x0018,
+	[RDLAR]		= 0x0020,
+	[EESR]		= 0x0028,
+	[EESIPR]	= 0x0030,
+	[TRSCER]	= 0x0038,
+	[RMFCR]		= 0x0040,
+	[TFTR]		= 0x0048,
+	[FDR]		= 0x0050,
+	[RMCR]		= 0x0058,
+	[TFUCR]		= 0x0064,
+	[RFOCR]		= 0x0068,
+	[FCFTR]		= 0x0070,
+	[RPADIR]	= 0x0078,
+	[TRIMD]		= 0x007c,
+	[RBWAR]		= 0x00c8,
+	[RDFAR]		= 0x00cc,
+	[TBRAR]		= 0x00d4,
+	[TDFAR]		= 0x00d8,
+};
+
+static const u16 sh_eth_offset_fast_sh3_sh2[SH_ETH_MAX_REGISTER_OFFSET] = {
+	[ECMR]		= 0x0160,
+	[ECSR]		= 0x0164,
+	[ECSIPR]	= 0x0168,
+	[PIR]		= 0x016c,
+	[MAHR]		= 0x0170,
+	[MALR]		= 0x0174,
+	[RFLR]		= 0x0178,
+	[PSR]		= 0x017c,
+	[TROCR]		= 0x0180,
+	[CDCR]		= 0x0184,
+	[LCCR]		= 0x0188,
+	[CNDCR]		= 0x018c,
+	[CEFCR]		= 0x0194,
+	[FRECR]		= 0x0198,
+	[TSFRCR]	= 0x019c,
+	[TLFRCR]	= 0x01a0,
+	[RFCR]		= 0x01a4,
+	[MAFCR]		= 0x01a8,
+	[IPGR]		= 0x01b4,
+	[APR]		= 0x01b8,
+	[MPR]		= 0x01bc,
+	[TPAUSER]	= 0x01c4,
+	[BCFR]		= 0x01cc,
+
+	[ARSTR]		= 0x0000,
+	[TSU_CTRST]	= 0x0004,
+	[TSU_FWEN0]	= 0x0010,
+	[TSU_FWEN1]	= 0x0014,
+	[TSU_FCM]	= 0x0018,
+	[TSU_BSYSL0]	= 0x0020,
+	[TSU_BSYSL1]	= 0x0024,
+	[TSU_PRISL0]	= 0x0028,
+	[TSU_PRISL1]	= 0x002c,
+	[TSU_FWSL0]	= 0x0030,
+	[TSU_FWSL1]	= 0x0034,
+	[TSU_FWSLC]	= 0x0038,
+	[TSU_QTAGM0]	= 0x0040,
+	[TSU_QTAGM1]	= 0x0044,
+	[TSU_ADQT0]	= 0x0048,
+	[TSU_ADQT1]	= 0x004c,
+	[TSU_FWSR]	= 0x0050,
+	[TSU_FWINMK]	= 0x0054,
+	[TSU_ADSBSY]	= 0x0060,
+	[TSU_TEN]	= 0x0064,
+	[TSU_POST1]	= 0x0070,
+	[TSU_POST2]	= 0x0074,
+	[TSU_POST3]	= 0x0078,
+	[TSU_POST4]	= 0x007c,
+
+	[TXNLCR0]	= 0x0080,
+	[TXALCR0]	= 0x0084,
+	[RXNLCR0]	= 0x0088,
+	[RXALCR0]	= 0x008c,
+	[FWNLCR0]	= 0x0090,
+	[FWALCR0]	= 0x0094,
+	[TXNLCR1]	= 0x00a0,
+	[TXALCR1]	= 0x00a0,
+	[RXNLCR1]	= 0x00a8,
+	[RXALCR1]	= 0x00ac,
+	[FWNLCR1]	= 0x00b0,
+	[FWALCR1]	= 0x00b4,
+
+	[TSU_ADRH0]	= 0x0100,
+	[TSU_ADRL0]	= 0x0104,
+	[TSU_ADRL31]	= 0x01fc,
+};
+
 #if defined(CONFIG_CPU_SUBTYPE_SH7734) || \
 	defined(CONFIG_CPU_SUBTYPE_SH7763) || \
 	defined(CONFIG_ARCH_R8A7740)
@@ -78,7 +342,7 @@ static void sh_eth_select_mii(struct net_device *ndev)
 #endif
 
 /* There is CPU dependent code */
-#if defined(CONFIG_CPU_SUBTYPE_SH7724) || defined(CONFIG_ARCH_R8A7779)
+#if defined(CONFIG_ARCH_R8A7779)
 #define SH_ETH_RESET_DEFAULT	1
 static void sh_eth_set_duplex(struct net_device *ndev)
 {
@@ -93,18 +357,60 @@ static void sh_eth_set_duplex(struct net_device *ndev)
 static void sh_eth_set_rate(struct net_device *ndev)
 {
 	struct sh_eth_private *mdp = netdev_priv(ndev);
-	unsigned int bits = ECMR_RTM;
 
-#if defined(CONFIG_ARCH_R8A7779)
-	bits |= ECMR_ELB;
-#endif
+	switch (mdp->speed) {
+	case 10: /* 10BASE */
+		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_ELB, ECMR);
+		break;
+	case 100:/* 100BASE */
+		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_ELB, ECMR);
+		break;
+	default:
+		break;
+	}
+}
+
+/* R8A7779 */
+static struct sh_eth_cpu_data sh_eth_my_cpu_data = {
+	.set_duplex	= sh_eth_set_duplex,
+	.set_rate	= sh_eth_set_rate,
+
+	.ecsr_value	= ECSR_PSRTO | ECSR_LCHNG | ECSR_ICD,
+	.ecsipr_value	= ECSIPR_PSRTOIP | ECSIPR_LCHNGIP | ECSIPR_ICDIP,
+	.eesipr_value	= 0x01ff009f,
+
+	.tx_check	= EESR_FTC | EESR_CND | EESR_DLC | EESR_CD | EESR_RTO,
+	.eesr_err_check	= EESR_TWB | EESR_TABT | EESR_RABT | EESR_RDE |
+			  EESR_RFRMER | EESR_TFE | EESR_TDE | EESR_ECI,
+	.tx_error_check	= EESR_TWB | EESR_TABT | EESR_TDE | EESR_TFE,
+
+	.apr		= 1,
+	.mpr		= 1,
+	.tpauser	= 1,
+	.hw_swap	= 1,
+};
+#elif defined(CONFIG_CPU_SUBTYPE_SH7724)
+#define SH_ETH_RESET_DEFAULT	1
+static void sh_eth_set_duplex(struct net_device *ndev)
+{
+	struct sh_eth_private *mdp = netdev_priv(ndev);
+
+	if (mdp->duplex) /* Full */
+		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_DM, ECMR);
+	else		/* Half */
+		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_DM, ECMR);
+}
+
+static void sh_eth_set_rate(struct net_device *ndev)
+{
+	struct sh_eth_private *mdp = netdev_priv(ndev);
 
 	switch (mdp->speed) {
 	case 10: /* 10BASE */
-		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~bits, ECMR);
+		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_RTM, ECMR);
 		break;
 	case 100:/* 100BASE */
-		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | bits, ECMR);
+		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_RTM, ECMR);
 		break;
 	default:
 		break;
@@ -592,7 +898,7 @@ static int sh_eth_check_reset(struct net_device *ndev)
 		cnt--;
 	}
 	if (cnt < 0) {
-		printk(KERN_ERR "Device reset fail\n");
+		pr_err("Device reset fail\n");
 		ret = -ETIMEDOUT;
 	}
 	return ret;
@@ -908,11 +1214,8 @@ static int sh_eth_ring_init(struct net_device *ndev)
 	/* Allocate all Rx descriptors. */
 	rx_ringsize = sizeof(struct sh_eth_rxdesc) * mdp->num_rx_ring;
 	mdp->rx_ring = dma_alloc_coherent(NULL, rx_ringsize, &mdp->rx_desc_dma,
-			GFP_KERNEL);
-
+					  GFP_KERNEL);
 	if (!mdp->rx_ring) {
-		dev_err(&ndev->dev, "Cannot allocate Rx Ring (size %d bytes)\n",
-			rx_ringsize);
 		ret = -ENOMEM;
 		goto desc_ring_free;
 	}
@@ -922,10 +1225,8 @@ static int sh_eth_ring_init(struct net_device *ndev)
 	/* Allocate all Tx descriptors. */
 	tx_ringsize = sizeof(struct sh_eth_txdesc) * mdp->num_tx_ring;
 	mdp->tx_ring = dma_alloc_coherent(NULL, tx_ringsize, &mdp->tx_desc_dma,
-			GFP_KERNEL);
+					  GFP_KERNEL);
 	if (!mdp->tx_ring) {
-		dev_err(&ndev->dev, "Cannot allocate Tx Ring (size %d bytes)\n",
-			tx_ringsize);
 		ret = -ENOMEM;
 		goto desc_ring_free;
 	}
@@ -1216,10 +1517,7 @@ static void sh_eth_error(struct net_device *ndev, int intr_status)
 		if (felic_stat & ECSR_LCHNG) {
 			/* Link Changed */
 			if (mdp->cd->no_psr || mdp->no_ether_link) {
-				if (mdp->link == PHY_DOWN)
-					link_stat = 0;
-				else
-					link_stat = PHY_ST_LINK;
+				goto ignore_link;
 			} else {
 				link_stat = (sh_eth_read(ndev, PSR));
 				if (mdp->ether_link_active_low)
@@ -1242,6 +1540,7 @@ static void sh_eth_error(struct net_device *ndev, int intr_status)
 		}
 	}
 
+ignore_link:
 	if (intr_status & EESR_TWB) {
 		/* Write buck end. unused write back interrupt */
 		if (intr_status & EESR_TABT)	/* Transmit Abort int */
@@ -1326,12 +1625,18 @@ static irqreturn_t sh_eth_interrupt(int irq, void *netdev)
 	struct sh_eth_private *mdp = netdev_priv(ndev);
 	struct sh_eth_cpu_data *cd = mdp->cd;
 	irqreturn_t ret = IRQ_NONE;
-	u32 intr_status = 0;
+	unsigned long intr_status;
 
 	spin_lock(&mdp->lock);
 
-	/* Get interrpt stat */
+	/* Get interrupt status */
 	intr_status = sh_eth_read(ndev, EESR);
+	/* Mask it with the interrupt mask, forcing ECI interrupt to be always
+	 * enabled since it's the one that  comes thru regardless of the mask,
+	 * and we need to fully handle it in sh_eth_error() in order to quench
+	 * it as it doesn't get cleared by just writing 1 to the ECI bit...
+	 */
+	intr_status &= sh_eth_read(ndev, EESIPR) | DMAC_M_ECI;
 	/* Clear interrupt */
 	if (intr_status & (EESR_FRC | EESR_RMAF | EESR_RRF |
 			EESR_RTLF | EESR_RTSF | EESR_PRE | EESR_CERF |
@@ -1373,7 +1678,7 @@ static void sh_eth_adjust_link(struct net_device *ndev)
 	struct phy_device *phydev = mdp->phydev;
 	int new_state = 0;
 
-	if (phydev->link != PHY_DOWN) {
+	if (phydev->link) {
 		if (phydev->duplex != mdp->duplex) {
 			new_state = 1;
 			mdp->duplex = phydev->duplex;
@@ -1387,17 +1692,21 @@ static void sh_eth_adjust_link(struct net_device *ndev)
 			if (mdp->cd->set_rate)
 				mdp->cd->set_rate(ndev);
 		}
-		if (mdp->link == PHY_DOWN) {
+		if (!mdp->link) {
 			sh_eth_write(ndev,
 				(sh_eth_read(ndev, ECMR) & ~ECMR_TXF), ECMR);
 			new_state = 1;
 			mdp->link = phydev->link;
+			if (mdp->cd->no_psr || mdp->no_ether_link)
+				sh_eth_rcv_snd_enable(ndev);
 		}
 	} else if (mdp->link) {
 		new_state = 1;
-		mdp->link = PHY_DOWN;
+		mdp->link = 0;
 		mdp->speed = 0;
 		mdp->duplex = -1;
+		if (mdp->cd->no_psr || mdp->no_ether_link)
+			sh_eth_rcv_snd_disable(ndev);
 	}
 
 	if (new_state && netif_msg_link(mdp))
@@ -1414,7 +1723,7 @@ static int sh_eth_phy_init(struct net_device *ndev)
 	snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT,
 		mdp->mii_bus->id , mdp->phy_id);
 
-	mdp->link = PHY_DOWN;
+	mdp->link = 0;
 	mdp->speed = 0;
 	mdp->duplex = -1;
 
@@ -2220,7 +2529,6 @@ static void sh_eth_tsu_init(struct sh_eth_private *mdp)
 /* MDIO bus release function */
 static int sh_mdio_release(struct net_device *ndev)
 {
-	struct sh_eth_private *mdp = netdev_priv(ndev);
 	struct mii_bus *bus = dev_get_drvdata(&ndev->dev);
 
 	/* unregister mdio bus */
@@ -2229,15 +2537,9 @@ static int sh_mdio_release(struct net_device *ndev)
 	/* remove mdio bus info from net_device */
 	dev_set_drvdata(&ndev->dev, NULL);
 
-	/* free interrupts memory */
-	kfree(bus->irq);
-
 	/* free bitbang info */
 	free_mdio_bitbang(bus);
 
-	/* free bitbang memory */
-	kfree(mdp->bitbang);
-
 	return 0;
 }
 
@@ -2250,7 +2552,8 @@ static int sh_mdio_init(struct net_device *ndev, int id,
 	struct sh_eth_private *mdp = netdev_priv(ndev);
 
 	/* create bit control struct for PHY */
-	bitbang = kzalloc(sizeof(struct bb_info), GFP_KERNEL);
+	bitbang = devm_kzalloc(&ndev->dev, sizeof(struct bb_info),
+			       GFP_KERNEL);
 	if (!bitbang) {
 		ret = -ENOMEM;
 		goto out;
@@ -2259,18 +2562,17 @@ static int sh_mdio_init(struct net_device *ndev, int id,
 	/* bitbang init */
 	bitbang->addr = mdp->addr + mdp->reg_offset[PIR];
 	bitbang->set_gate = pd->set_mdio_gate;
-	bitbang->mdi_msk = 0x08;
-	bitbang->mdo_msk = 0x04;
-	bitbang->mmd_msk = 0x02;/* MMD */
-	bitbang->mdc_msk = 0x01;
+	bitbang->mdi_msk = PIR_MDI;
+	bitbang->mdo_msk = PIR_MDO;
+	bitbang->mmd_msk = PIR_MMD;
+	bitbang->mdc_msk = PIR_MDC;
 	bitbang->ctrl.ops = &bb_ops;
 
 	/* MII controller setting */
-	mdp->bitbang = bitbang;
 	mdp->mii_bus = alloc_mdio_bitbang(&bitbang->ctrl);
 	if (!mdp->mii_bus) {
 		ret = -ENOMEM;
-		goto out_free_bitbang;
+		goto out;
 	}
 
 	/* Hook up MII support for ethtool */
@@ -2280,7 +2582,9 @@ static int sh_mdio_init(struct net_device *ndev, int id,
 		mdp->pdev->name, id);
 
 	/* PHY IRQ */
-	mdp->mii_bus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
+	mdp->mii_bus->irq = devm_kzalloc(&ndev->dev,
+					 sizeof(int) * PHY_MAX_ADDR,
+					 GFP_KERNEL);
 	if (!mdp->mii_bus->irq) {
 		ret = -ENOMEM;
 		goto out_free_bus;
@@ -2292,21 +2596,15 @@ static int sh_mdio_init(struct net_device *ndev, int id,
 	/* register mdio bus */
 	ret = mdiobus_register(mdp->mii_bus);
 	if (ret)
-		goto out_free_irq;
+		goto out_free_bus;
 
 	dev_set_drvdata(&ndev->dev, mdp->mii_bus);
 
 	return 0;
 
-out_free_irq:
-	kfree(mdp->mii_bus->irq);
-
 out_free_bus:
 	free_mdio_bitbang(mdp->mii_bus);
 
-out_free_bitbang:
-	kfree(bitbang);
-
 out:
 	return ret;
 }
@@ -2319,6 +2617,9 @@ static const u16 *sh_eth_get_register_offset(int register_type)
 	case SH_ETH_REG_GIGABIT:
 		reg_offset = sh_eth_offset_gigabit;
 		break;
+	case SH_ETH_REG_FAST_RCAR:
+		reg_offset = sh_eth_offset_fast_rcar;
+		break;
 	case SH_ETH_REG_FAST_SH4:
 		reg_offset = sh_eth_offset_fast_sh4;
 		break;
@@ -2326,7 +2627,7 @@ static const u16 *sh_eth_get_register_offset(int register_type)
 		reg_offset = sh_eth_offset_fast_sh3_sh2;
 		break;
 	default:
-		printk(KERN_ERR "Unknown register type (%d)\n", register_type);
+		pr_err("Unknown register type (%d)\n", register_type);
 		break;
 	}
 
@@ -2356,7 +2657,7 @@ static int sh_eth_drv_probe(struct platform_device *pdev)
 	struct resource *res;
 	struct net_device *ndev = NULL;
 	struct sh_eth_private *mdp = NULL;
-	struct sh_eth_plat_data *pd;
+	struct sh_eth_plat_data *pd = pdev->dev.platform_data;
 
 	/* get base addr */
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -2394,10 +2695,9 @@ static int sh_eth_drv_probe(struct platform_device *pdev)
 	mdp = netdev_priv(ndev);
 	mdp->num_tx_ring = TX_RING_SIZE;
 	mdp->num_rx_ring = RX_RING_SIZE;
-	mdp->addr = ioremap(res->start, resource_size(res));
-	if (mdp->addr == NULL) {
-		ret = -ENOMEM;
-		dev_err(&pdev->dev, "ioremap failed.\n");
+	mdp->addr = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(mdp->addr)) {
+		ret = PTR_ERR(mdp->addr);
 		goto out_release;
 	}
 
@@ -2406,7 +2706,6 @@ static int sh_eth_drv_probe(struct platform_device *pdev)
 	pm_runtime_enable(&pdev->dev);
 	pm_runtime_resume(&pdev->dev);
 
-	pd = (struct sh_eth_plat_data *)(pdev->dev.platform_data);
 	/* get PHY ID */
 	mdp->phy_id = pd->phy;
 	mdp->phy_interface = pd->phy_interface;
@@ -2444,11 +2743,9 @@ static int sh_eth_drv_probe(struct platform_device *pdev)
 			ret = -ENODEV;
 			goto out_release;
 		}
-		mdp->tsu_addr = ioremap(rtsu->start,
-					resource_size(rtsu));
-		if (mdp->tsu_addr == NULL) {
-			ret = -ENOMEM;
-			dev_err(&pdev->dev, "TSU ioremap failed.\n");
+		mdp->tsu_addr = devm_ioremap_resource(&pdev->dev, rtsu);
+		if (IS_ERR(mdp->tsu_addr)) {
+			ret = PTR_ERR(mdp->tsu_addr);
 			goto out_release;
 		}
 		mdp->port = devno % 2;
@@ -2489,10 +2786,6 @@ out_unregister:
 
 out_release:
 	/* net_dev free */
-	if (mdp && mdp->addr)
-		iounmap(mdp->addr);
-	if (mdp && mdp->tsu_addr)
-		iounmap(mdp->tsu_addr);
 	if (ndev)
 		free_netdev(ndev);
 
@@ -2503,14 +2796,10 @@ out:
 static int sh_eth_drv_remove(struct platform_device *pdev)
 {
 	struct net_device *ndev = platform_get_drvdata(pdev);
-	struct sh_eth_private *mdp = netdev_priv(ndev);
 
-	if (mdp->cd->tsu)
-		iounmap(mdp->tsu_addr);
 	sh_mdio_release(ndev);
 	unregister_netdev(ndev);
 	pm_runtime_disable(&pdev->dev);
-	iounmap(mdp->addr);
 	free_netdev(ndev);
 	platform_set_drvdata(pdev, NULL);
 
diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h
index e665567..1ddc9f2 100644
--- a/drivers/net/ethernet/renesas/sh_eth.h
+++ b/drivers/net/ethernet/renesas/sh_eth.h
@@ -156,225 +156,6 @@ enum {
 	SH_ETH_MAX_REGISTER_OFFSET,
 };
 
-static const u16 sh_eth_offset_gigabit[SH_ETH_MAX_REGISTER_OFFSET] = {
-	[EDSR]	= 0x0000,
-	[EDMR]	= 0x0400,
-	[EDTRR]	= 0x0408,
-	[EDRRR]	= 0x0410,
-	[EESR]	= 0x0428,
-	[EESIPR]	= 0x0430,
-	[TDLAR]	= 0x0010,
-	[TDFAR]	= 0x0014,
-	[TDFXR]	= 0x0018,
-	[TDFFR]	= 0x001c,
-	[RDLAR]	= 0x0030,
-	[RDFAR]	= 0x0034,
-	[RDFXR]	= 0x0038,
-	[RDFFR]	= 0x003c,
-	[TRSCER]	= 0x0438,
-	[RMFCR]	= 0x0440,
-	[TFTR]	= 0x0448,
-	[FDR]	= 0x0450,
-	[RMCR]	= 0x0458,
-	[RPADIR]	= 0x0460,
-	[FCFTR]	= 0x0468,
-	[CSMR] = 0x04E4,
-
-	[ECMR]	= 0x0500,
-	[ECSR]	= 0x0510,
-	[ECSIPR]	= 0x0518,
-	[PIR]	= 0x0520,
-	[PSR]	= 0x0528,
-	[PIPR]	= 0x052c,
-	[RFLR]	= 0x0508,
-	[APR]	= 0x0554,
-	[MPR]	= 0x0558,
-	[PFTCR]	= 0x055c,
-	[PFRCR]	= 0x0560,
-	[TPAUSER]	= 0x0564,
-	[GECMR]	= 0x05b0,
-	[BCULR]	= 0x05b4,
-	[MAHR]	= 0x05c0,
-	[MALR]	= 0x05c8,
-	[TROCR]	= 0x0700,
-	[CDCR]	= 0x0708,
-	[LCCR]	= 0x0710,
-	[CEFCR]	= 0x0740,
-	[FRECR]	= 0x0748,
-	[TSFRCR]	= 0x0750,
-	[TLFRCR]	= 0x0758,
-	[RFCR]	= 0x0760,
-	[CERCR]	= 0x0768,
-	[CEECR]	= 0x0770,
-	[MAFCR]	= 0x0778,
-	[RMII_MII] =  0x0790,
-
-	[ARSTR]	= 0x0000,
-	[TSU_CTRST]	= 0x0004,
-	[TSU_FWEN0]	= 0x0010,
-	[TSU_FWEN1]	= 0x0014,
-	[TSU_FCM]	= 0x0018,
-	[TSU_BSYSL0]	= 0x0020,
-	[TSU_BSYSL1]	= 0x0024,
-	[TSU_PRISL0]	= 0x0028,
-	[TSU_PRISL1]	= 0x002c,
-	[TSU_FWSL0]	= 0x0030,
-	[TSU_FWSL1]	= 0x0034,
-	[TSU_FWSLC]	= 0x0038,
-	[TSU_QTAG0]	= 0x0040,
-	[TSU_QTAG1]	= 0x0044,
-	[TSU_FWSR]	= 0x0050,
-	[TSU_FWINMK]	= 0x0054,
-	[TSU_ADQT0]	= 0x0048,
-	[TSU_ADQT1]	= 0x004c,
-	[TSU_VTAG0]	= 0x0058,
-	[TSU_VTAG1]	= 0x005c,
-	[TSU_ADSBSY]	= 0x0060,
-	[TSU_TEN]	= 0x0064,
-	[TSU_POST1]	= 0x0070,
-	[TSU_POST2]	= 0x0074,
-	[TSU_POST3]	= 0x0078,
-	[TSU_POST4]	= 0x007c,
-	[TSU_ADRH0]	= 0x0100,
-	[TSU_ADRL0]	= 0x0104,
-	[TSU_ADRH31]	= 0x01f8,
-	[TSU_ADRL31]	= 0x01fc,
-
-	[TXNLCR0]	= 0x0080,
-	[TXALCR0]	= 0x0084,
-	[RXNLCR0]	= 0x0088,
-	[RXALCR0]	= 0x008c,
-	[FWNLCR0]	= 0x0090,
-	[FWALCR0]	= 0x0094,
-	[TXNLCR1]	= 0x00a0,
-	[TXALCR1]	= 0x00a0,
-	[RXNLCR1]	= 0x00a8,
-	[RXALCR1]	= 0x00ac,
-	[FWNLCR1]	= 0x00b0,
-	[FWALCR1]	= 0x00b4,
-};
-
-static const u16 sh_eth_offset_fast_sh4[SH_ETH_MAX_REGISTER_OFFSET] = {
-	[ECMR]	= 0x0100,
-	[RFLR]	= 0x0108,
-	[ECSR]	= 0x0110,
-	[ECSIPR]	= 0x0118,
-	[PIR]	= 0x0120,
-	[PSR]	= 0x0128,
-	[RDMLR]	= 0x0140,
-	[IPGR]	= 0x0150,
-	[APR]	= 0x0154,
-	[MPR]	= 0x0158,
-	[TPAUSER]	= 0x0164,
-	[RFCF]	= 0x0160,
-	[TPAUSECR]	= 0x0168,
-	[BCFRR]	= 0x016c,
-	[MAHR]	= 0x01c0,
-	[MALR]	= 0x01c8,
-	[TROCR]	= 0x01d0,
-	[CDCR]	= 0x01d4,
-	[LCCR]	= 0x01d8,
-	[CNDCR]	= 0x01dc,
-	[CEFCR]	= 0x01e4,
-	[FRECR]	= 0x01e8,
-	[TSFRCR]	= 0x01ec,
-	[TLFRCR]	= 0x01f0,
-	[RFCR]	= 0x01f4,
-	[MAFCR]	= 0x01f8,
-	[RTRATE]	= 0x01fc,
-
-	[EDMR]	= 0x0000,
-	[EDTRR]	= 0x0008,
-	[EDRRR]	= 0x0010,
-	[TDLAR]	= 0x0018,
-	[RDLAR]	= 0x0020,
-	[EESR]	= 0x0028,
-	[EESIPR]	= 0x0030,
-	[TRSCER]	= 0x0038,
-	[RMFCR]	= 0x0040,
-	[TFTR]	= 0x0048,
-	[FDR]	= 0x0050,
-	[RMCR]	= 0x0058,
-	[TFUCR]	= 0x0064,
-	[RFOCR]	= 0x0068,
-	[FCFTR]	= 0x0070,
-	[RPADIR]	= 0x0078,
-	[TRIMD]	= 0x007c,
-	[RBWAR]	= 0x00c8,
-	[RDFAR]	= 0x00cc,
-	[TBRAR]	= 0x00d4,
-	[TDFAR]	= 0x00d8,
-};
-
-static const u16 sh_eth_offset_fast_sh3_sh2[SH_ETH_MAX_REGISTER_OFFSET] = {
-	[ECMR]	= 0x0160,
-	[ECSR]	= 0x0164,
-	[ECSIPR]	= 0x0168,
-	[PIR]	= 0x016c,
-	[MAHR]	= 0x0170,
-	[MALR]	= 0x0174,
-	[RFLR]	= 0x0178,
-	[PSR]	= 0x017c,
-	[TROCR]	= 0x0180,
-	[CDCR]	= 0x0184,
-	[LCCR]	= 0x0188,
-	[CNDCR]	= 0x018c,
-	[CEFCR]	= 0x0194,
-	[FRECR]	= 0x0198,
-	[TSFRCR]	= 0x019c,
-	[TLFRCR]	= 0x01a0,
-	[RFCR]	= 0x01a4,
-	[MAFCR]	= 0x01a8,
-	[IPGR]	= 0x01b4,
-	[APR]	= 0x01b8,
-	[MPR]	= 0x01bc,
-	[TPAUSER]	= 0x01c4,
-	[BCFR]	= 0x01cc,
-
-	[ARSTR]	= 0x0000,
-	[TSU_CTRST]	= 0x0004,
-	[TSU_FWEN0]	= 0x0010,
-	[TSU_FWEN1]	= 0x0014,
-	[TSU_FCM]	= 0x0018,
-	[TSU_BSYSL0]	= 0x0020,
-	[TSU_BSYSL1]	= 0x0024,
-	[TSU_PRISL0]	= 0x0028,
-	[TSU_PRISL1]	= 0x002c,
-	[TSU_FWSL0]	= 0x0030,
-	[TSU_FWSL1]	= 0x0034,
-	[TSU_FWSLC]	= 0x0038,
-	[TSU_QTAGM0]	= 0x0040,
-	[TSU_QTAGM1]	= 0x0044,
-	[TSU_ADQT0]	= 0x0048,
-	[TSU_ADQT1]	= 0x004c,
-	[TSU_FWSR]	= 0x0050,
-	[TSU_FWINMK]	= 0x0054,
-	[TSU_ADSBSY]	= 0x0060,
-	[TSU_TEN]	= 0x0064,
-	[TSU_POST1]	= 0x0070,
-	[TSU_POST2]	= 0x0074,
-	[TSU_POST3]	= 0x0078,
-	[TSU_POST4]	= 0x007c,
-
-	[TXNLCR0]	= 0x0080,
-	[TXALCR0]	= 0x0084,
-	[RXNLCR0]	= 0x0088,
-	[RXALCR0]	= 0x008c,
-	[FWNLCR0]	= 0x0090,
-	[FWALCR0]	= 0x0094,
-	[TXNLCR1]	= 0x00a0,
-	[TXALCR1]	= 0x00a0,
-	[RXNLCR1]	= 0x00a8,
-	[RXALCR1]	= 0x00ac,
-	[FWNLCR1]	= 0x00b0,
-	[FWALCR1]	= 0x00b4,
-
-	[TSU_ADRH0]	= 0x0100,
-	[TSU_ADRL0]	= 0x0104,
-	[TSU_ADRL31]	= 0x01fc,
-
-};
-
 /* Driver's parameters */
 #if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE)
 #define SH4_SKB_RX_ALIGN	32
@@ -705,7 +486,6 @@ struct sh_eth_private {
 	const u16 *reg_offset;
 	void __iomem *addr;
 	void __iomem *tsu_addr;
-	struct bb_info *bitbang;
 	u32 num_rx_ring;
 	u32 num_tx_ring;
 	dma_addr_t rx_desc_dma;
@@ -723,7 +503,7 @@ struct sh_eth_private {
 	u32 phy_id;					/* PHY ID */
 	struct mii_bus *mii_bus;	/* MDIO bus control */
 	struct phy_device *phydev;	/* PHY device control */
-	enum phy_state link;
+	int link;
 	phy_interface_t phy_interface;
 	int msg_enable;
 	int speed;
diff --git a/drivers/net/ethernet/s6gmac.c b/drivers/net/ethernet/s6gmac.c
index 21683e2..b6739af 100644
--- a/drivers/net/ethernet/s6gmac.c
+++ b/drivers/net/ethernet/s6gmac.c
@@ -998,6 +998,7 @@ static int s6gmac_probe(struct platform_device *pdev)
 	mb = mdiobus_alloc();
 	if (!mb) {
 		printk(KERN_ERR DRV_PRMT "error allocating mii bus\n");
+		res = -ENOMEM;
 		goto errmii;
 	}
 	mb->name = "s6gmac_mii";
@@ -1053,20 +1054,7 @@ static struct platform_driver s6gmac_driver = {
 	},
 };
 
-static int __init s6gmac_init(void)
-{
-	printk(KERN_INFO DRV_PRMT "S6 GMAC ethernet driver\n");
-	return platform_driver_register(&s6gmac_driver);
-}
-
-
-static void __exit s6gmac_exit(void)
-{
-	platform_driver_unregister(&s6gmac_driver);
-}
-
-module_init(s6gmac_init);
-module_exit(s6gmac_exit);
+module_platform_driver(s6gmac_driver);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("S6105 on chip Ethernet driver");
diff --git a/drivers/net/ethernet/seeq/ether3.c b/drivers/net/ethernet/seeq/ether3.c
index 3aca578..bdac936 100644
--- a/drivers/net/ethernet/seeq/ether3.c
+++ b/drivers/net/ethernet/seeq/ether3.c
@@ -651,8 +651,11 @@ if (next_ptr < RX_START || next_ptr >= RX_END) {
 				skb->protocol = eth_type_trans(skb, dev);
 				netif_rx(skb);
 				received ++;
-			} else
-				goto dropping;
+			} else {
+				ether3_outw(next_ptr >> 8, REG_RECVEND);
+				dev->stats.rx_dropped++;
+				goto done;
+			}
 		} else {
 			struct net_device_stats *stats = &dev->stats;
 			ether3_outw(next_ptr >> 8, REG_RECVEND);
@@ -679,21 +682,6 @@ done:
 	}
 
 	return maxcnt;
-
-dropping:{
-	static unsigned long last_warned;
-
-	ether3_outw(next_ptr >> 8, REG_RECVEND);
-	/*
-	 * Don't print this message too many times...
-	 */
-	if (time_after(jiffies, last_warned + 10 * HZ)) {
-		last_warned = jiffies;
-		printk("%s: memory squeeze, dropping packet.\n", dev->name);
-	}
-	dev->stats.rx_dropped++;
-	goto done;
-	}
 }
 
 /*
diff --git a/drivers/net/ethernet/seeq/sgiseeq.c b/drivers/net/ethernet/seeq/sgiseeq.c
index 0fde9ca..0ad5694 100644
--- a/drivers/net/ethernet/seeq/sgiseeq.c
+++ b/drivers/net/ethernet/seeq/sgiseeq.c
@@ -381,8 +381,6 @@ memory_squeeze:
 					dev->stats.rx_packets++;
 					dev->stats.rx_bytes += len;
 				} else {
-					printk(KERN_NOTICE "%s: Memory squeeze, deferring packet.\n",
-						dev->name);
 					dev->stats.rx_dropped++;
 				}
 			} else {
diff --git a/drivers/net/ethernet/sfc/Kconfig b/drivers/net/ethernet/sfc/Kconfig
index 435b4f1..4136ccc 100644
--- a/drivers/net/ethernet/sfc/Kconfig
+++ b/drivers/net/ethernet/sfc/Kconfig
@@ -24,7 +24,7 @@ config SFC_MCDI_MON
 	bool "Solarflare SFC9000-family hwmon support"
 	depends on SFC && HWMON && !(SFC=y && HWMON=m)
 	default y
-	----help---
+	---help---
 	  This exposes the on-board firmware-managed sensors as a
 	  hardware monitor device.
 config SFC_SRIOV
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c
index 0bc0099..01b9920 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -22,6 +22,7 @@
 #include <linux/topology.h>
 #include <linux/gfp.h>
 #include <linux/cpu_rmap.h>
+#include <linux/aer.h>
 #include "net_driver.h"
 #include "efx.h"
 #include "nic.h"
@@ -71,21 +72,21 @@ const char *const efx_loopback_mode_names[] = {
 
 const unsigned int efx_reset_type_max = RESET_TYPE_MAX;
 const char *const efx_reset_type_names[] = {
-	[RESET_TYPE_INVISIBLE]     = "INVISIBLE",
-	[RESET_TYPE_ALL]           = "ALL",
-	[RESET_TYPE_WORLD]         = "WORLD",
-	[RESET_TYPE_DISABLE]       = "DISABLE",
-	[RESET_TYPE_TX_WATCHDOG]   = "TX_WATCHDOG",
-	[RESET_TYPE_INT_ERROR]     = "INT_ERROR",
-	[RESET_TYPE_RX_RECOVERY]   = "RX_RECOVERY",
-	[RESET_TYPE_RX_DESC_FETCH] = "RX_DESC_FETCH",
-	[RESET_TYPE_TX_DESC_FETCH] = "TX_DESC_FETCH",
-	[RESET_TYPE_TX_SKIP]       = "TX_SKIP",
-	[RESET_TYPE_MC_FAILURE]    = "MC_FAILURE",
+	[RESET_TYPE_INVISIBLE]          = "INVISIBLE",
+	[RESET_TYPE_ALL]                = "ALL",
+	[RESET_TYPE_RECOVER_OR_ALL]     = "RECOVER_OR_ALL",
+	[RESET_TYPE_WORLD]              = "WORLD",
+	[RESET_TYPE_RECOVER_OR_DISABLE] = "RECOVER_OR_DISABLE",
+	[RESET_TYPE_DISABLE]            = "DISABLE",
+	[RESET_TYPE_TX_WATCHDOG]        = "TX_WATCHDOG",
+	[RESET_TYPE_INT_ERROR]          = "INT_ERROR",
+	[RESET_TYPE_RX_RECOVERY]        = "RX_RECOVERY",
+	[RESET_TYPE_RX_DESC_FETCH]      = "RX_DESC_FETCH",
+	[RESET_TYPE_TX_DESC_FETCH]      = "TX_DESC_FETCH",
+	[RESET_TYPE_TX_SKIP]            = "TX_SKIP",
+	[RESET_TYPE_MC_FAILURE]         = "MC_FAILURE",
 };
 
-#define EFX_MAX_MTU (9 * 1024)
-
 /* Reset workqueue. If any NIC has a hardware failure then a reset will be
  * queued onto this work queue. This is not a per-nic work queue, because
  * efx_reset_work() acquires the rtnl lock, so resets are naturally serialised.
@@ -117,9 +118,12 @@ MODULE_PARM_DESC(separate_tx_channels,
 static int napi_weight = 64;
 
 /* This is the time (in jiffies) between invocations of the hardware
- * monitor.  On Falcon-based NICs, this will:
+ * monitor.
+ * On Falcon-based NICs, this will:
  * - Check the on-board hardware monitor;
  * - Poll the link state and reconfigure the hardware as necessary.
+ * On Siena-based NICs for power systems with EEH support, this will give EEH a
+ * chance to start.
  */
 static unsigned int efx_monitor_interval = 1 * HZ;
 
@@ -203,13 +207,14 @@ static void efx_stop_all(struct efx_nic *efx);
 #define EFX_ASSERT_RESET_SERIALISED(efx)		\
 	do {						\
 		if ((efx->state == STATE_READY) ||	\
+		    (efx->state == STATE_RECOVERY) ||	\
 		    (efx->state == STATE_DISABLED))	\
 			ASSERT_RTNL();			\
 	} while (0)
 
 static int efx_check_disabled(struct efx_nic *efx)
 {
-	if (efx->state == STATE_DISABLED) {
+	if (efx->state == STATE_DISABLED || efx->state == STATE_RECOVERY) {
 		netif_err(efx, drv, efx->net_dev,
 			  "device is disabled due to earlier errors\n");
 		return -EIO;
@@ -242,15 +247,9 @@ static int efx_process_channel(struct efx_channel *channel, int budget)
 		struct efx_rx_queue *rx_queue =
 			efx_channel_get_rx_queue(channel);
 
-		/* Deliver last RX packet. */
-		if (channel->rx_pkt) {
-			__efx_rx_packet(channel, channel->rx_pkt);
-			channel->rx_pkt = NULL;
-		}
-		if (rx_queue->enabled) {
-			efx_rx_strategy(channel);
+		efx_rx_flush_packet(channel);
+		if (rx_queue->enabled)
 			efx_fast_push_rx_descriptors(rx_queue);
-		}
 	}
 
 	return spent;
@@ -625,20 +624,51 @@ fail:
  */
 static void efx_start_datapath(struct efx_nic *efx)
 {
+	bool old_rx_scatter = efx->rx_scatter;
 	struct efx_tx_queue *tx_queue;
 	struct efx_rx_queue *rx_queue;
 	struct efx_channel *channel;
+	size_t rx_buf_len;
 
 	/* Calculate the rx buffer allocation parameters required to
 	 * support the current MTU, including padding for header
 	 * alignment and overruns.
 	 */
-	efx->rx_buffer_len = (max(EFX_PAGE_IP_ALIGN, NET_IP_ALIGN) +
-			      EFX_MAX_FRAME_LEN(efx->net_dev->mtu) +
-			      efx->type->rx_buffer_hash_size +
-			      efx->type->rx_buffer_padding);
-	efx->rx_buffer_order = get_order(efx->rx_buffer_len +
-					 sizeof(struct efx_rx_page_state));
+	efx->rx_dma_len = (efx->type->rx_buffer_hash_size +
+			   EFX_MAX_FRAME_LEN(efx->net_dev->mtu) +
+			   efx->type->rx_buffer_padding);
+	rx_buf_len = (sizeof(struct efx_rx_page_state) +
+		      EFX_PAGE_IP_ALIGN + efx->rx_dma_len);
+	if (rx_buf_len <= PAGE_SIZE) {
+		efx->rx_scatter = false;
+		efx->rx_buffer_order = 0;
+	} else if (efx->type->can_rx_scatter) {
+		BUILD_BUG_ON(sizeof(struct efx_rx_page_state) +
+			     EFX_PAGE_IP_ALIGN + EFX_RX_USR_BUF_SIZE >
+			     PAGE_SIZE / 2);
+		efx->rx_scatter = true;
+		efx->rx_dma_len = EFX_RX_USR_BUF_SIZE;
+		efx->rx_buffer_order = 0;
+	} else {
+		efx->rx_scatter = false;
+		efx->rx_buffer_order = get_order(rx_buf_len);
+	}
+
+	efx_rx_config_page_split(efx);
+	if (efx->rx_buffer_order)
+		netif_dbg(efx, drv, efx->net_dev,
+			  "RX buf len=%u; page order=%u batch=%u\n",
+			  efx->rx_dma_len, efx->rx_buffer_order,
+			  efx->rx_pages_per_batch);
+	else
+		netif_dbg(efx, drv, efx->net_dev,
+			  "RX buf len=%u step=%u bpp=%u; page batch=%u\n",
+			  efx->rx_dma_len, efx->rx_page_buf_step,
+			  efx->rx_bufs_per_page, efx->rx_pages_per_batch);
+
+	/* RX filters also have scatter-enabled flags */
+	if (efx->rx_scatter != old_rx_scatter)
+		efx_filter_update_rx_scatter(efx);
 
 	/* We must keep at least one descriptor in a TX ring empty.
 	 * We could avoid this when the queue size does not exactly
@@ -655,16 +685,12 @@ static void efx_start_datapath(struct efx_nic *efx)
 		efx_for_each_channel_tx_queue(tx_queue, channel)
 			efx_init_tx_queue(tx_queue);
 
-		/* The rx buffer allocation strategy is MTU dependent */
-		efx_rx_strategy(channel);
-
 		efx_for_each_channel_rx_queue(rx_queue, channel) {
 			efx_init_rx_queue(rx_queue);
 			efx_nic_generate_fill_event(rx_queue);
 		}
 
-		WARN_ON(channel->rx_pkt != NULL);
-		efx_rx_strategy(channel);
+		WARN_ON(channel->rx_pkt_n_frags);
 	}
 
 	if (netif_device_present(efx->net_dev))
@@ -683,7 +709,7 @@ static void efx_stop_datapath(struct efx_nic *efx)
 	BUG_ON(efx->port_enabled);
 
 	/* Only perform flush if dma is enabled */
-	if (dev->is_busmaster) {
+	if (dev->is_busmaster && efx->state != STATE_RECOVERY) {
 		rc = efx_nic_flush_queues(efx);
 
 		if (rc && EFX_WORKAROUND_7803(efx)) {
@@ -1596,13 +1622,15 @@ static void efx_start_all(struct efx_nic *efx)
 	efx_start_port(efx);
 	efx_start_datapath(efx);
 
-	/* Start the hardware monitor if there is one. Otherwise (we're link
-	 * event driven), we have to poll the PHY because after an event queue
-	 * flush, we could have a missed a link state change */
-	if (efx->type->monitor != NULL) {
+	/* Start the hardware monitor if there is one */
+	if (efx->type->monitor != NULL)
 		queue_delayed_work(efx->workqueue, &efx->monitor_work,
 				   efx_monitor_interval);
-	} else {
+
+	/* If link state detection is normally event-driven, we have
+	 * to poll now because we could have missed a change
+	 */
+	if (efx_nic_rev(efx) >= EFX_REV_SIENA_A0) {
 		mutex_lock(&efx->mac_lock);
 		if (efx->phy_op->poll(efx))
 			efx_link_status_changed(efx);
@@ -2309,7 +2337,9 @@ int efx_reset(struct efx_nic *efx, enum reset_type method)
 
 out:
 	/* Leave device stopped if necessary */
-	disabled = rc || method == RESET_TYPE_DISABLE;
+	disabled = rc ||
+		method == RESET_TYPE_DISABLE ||
+		method == RESET_TYPE_RECOVER_OR_DISABLE;
 	rc2 = efx_reset_up(efx, method, !disabled);
 	if (rc2) {
 		disabled = true;
@@ -2328,13 +2358,48 @@ out:
 	return rc;
 }
 
+/* Try recovery mechanisms.
+ * For now only EEH is supported.
+ * Returns 0 if the recovery mechanisms are unsuccessful.
+ * Returns a non-zero value otherwise.
+ */
+static int efx_try_recovery(struct efx_nic *efx)
+{
+#ifdef CONFIG_EEH
+	/* A PCI error can occur and not be seen by EEH because nothing
+	 * happens on the PCI bus. In this case the driver may fail and
+	 * schedule a 'recover or reset', leading to this recovery handler.
+	 * Manually call the eeh failure check function.
+	 */
+	struct eeh_dev *eehdev =
+		of_node_to_eeh_dev(pci_device_to_OF_node(efx->pci_dev));
+
+	if (eeh_dev_check_failure(eehdev)) {
+		/* The EEH mechanisms will handle the error and reset the
+		 * device if necessary.
+		 */
+		return 1;
+	}
+#endif
+	return 0;
+}
+
 /* The worker thread exists so that code that cannot sleep can
  * schedule a reset for later.
  */
 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);
+	unsigned long pending;
+	enum reset_type method;
+
+	pending = ACCESS_ONCE(efx->reset_pending);
+	method = fls(pending) - 1;
+
+	if ((method == RESET_TYPE_RECOVER_OR_DISABLE ||
+	     method == RESET_TYPE_RECOVER_OR_ALL) &&
+	    efx_try_recovery(efx))
+		return;
 
 	if (!pending)
 		return;
@@ -2346,7 +2411,7 @@ static void efx_reset_work(struct work_struct *data)
 	 * it cannot change again.
 	 */
 	if (efx->state == STATE_READY)
-		(void)efx_reset(efx, fls(pending) - 1);
+		(void)efx_reset(efx, method);
 
 	rtnl_unlock();
 }
@@ -2355,11 +2420,20 @@ void efx_schedule_reset(struct efx_nic *efx, enum reset_type type)
 {
 	enum reset_type method;
 
+	if (efx->state == STATE_RECOVERY) {
+		netif_dbg(efx, drv, efx->net_dev,
+			  "recovering: skip scheduling %s reset\n",
+			  RESET_TYPE(type));
+		return;
+	}
+
 	switch (type) {
 	case RESET_TYPE_INVISIBLE:
 	case RESET_TYPE_ALL:
+	case RESET_TYPE_RECOVER_OR_ALL:
 	case RESET_TYPE_WORLD:
 	case RESET_TYPE_DISABLE:
+	case RESET_TYPE_RECOVER_OR_DISABLE:
 		method = type;
 		netif_dbg(efx, drv, efx->net_dev, "scheduling %s reset\n",
 			  RESET_TYPE(method));
@@ -2569,6 +2643,8 @@ static void efx_pci_remove(struct pci_dev *pci_dev)
 	efx_fini_struct(efx);
 	pci_set_drvdata(pci_dev, NULL);
 	free_netdev(efx->net_dev);
+
+	pci_disable_pcie_error_reporting(pci_dev);
 };
 
 /* NIC VPD information
@@ -2741,6 +2817,11 @@ static int efx_pci_probe(struct pci_dev *pci_dev,
 		netif_warn(efx, probe, efx->net_dev,
 			   "failed to create MTDs (%d)\n", rc);
 
+	rc = pci_enable_pcie_error_reporting(pci_dev);
+	if (rc && rc != -EINVAL)
+		netif_warn(efx, probe, efx->net_dev,
+			   "pci_enable_pcie_error_reporting failed (%d)\n", rc);
+
 	return 0;
 
  fail4:
@@ -2865,12 +2946,112 @@ static const struct dev_pm_ops efx_pm_ops = {
 	.restore	= efx_pm_resume,
 };
 
+/* A PCI error affecting this device was detected.
+ * At this point MMIO and DMA may be disabled.
+ * Stop the software path and request a slot reset.
+ */
+static pci_ers_result_t efx_io_error_detected(struct pci_dev *pdev,
+					      enum pci_channel_state state)
+{
+	pci_ers_result_t status = PCI_ERS_RESULT_RECOVERED;
+	struct efx_nic *efx = pci_get_drvdata(pdev);
+
+	if (state == pci_channel_io_perm_failure)
+		return PCI_ERS_RESULT_DISCONNECT;
+
+	rtnl_lock();
+
+	if (efx->state != STATE_DISABLED) {
+		efx->state = STATE_RECOVERY;
+		efx->reset_pending = 0;
+
+		efx_device_detach_sync(efx);
+
+		efx_stop_all(efx);
+		efx_stop_interrupts(efx, false);
+
+		status = PCI_ERS_RESULT_NEED_RESET;
+	} else {
+		/* If the interface is disabled we don't want to do anything
+		 * with it.
+		 */
+		status = PCI_ERS_RESULT_RECOVERED;
+	}
+
+	rtnl_unlock();
+
+	pci_disable_device(pdev);
+
+	return status;
+}
+
+/* Fake a successfull reset, which will be performed later in efx_io_resume. */
+static pci_ers_result_t efx_io_slot_reset(struct pci_dev *pdev)
+{
+	struct efx_nic *efx = pci_get_drvdata(pdev);
+	pci_ers_result_t status = PCI_ERS_RESULT_RECOVERED;
+	int rc;
+
+	if (pci_enable_device(pdev)) {
+		netif_err(efx, hw, efx->net_dev,
+			  "Cannot re-enable PCI device after reset.\n");
+		status =  PCI_ERS_RESULT_DISCONNECT;
+	}
+
+	rc = pci_cleanup_aer_uncorrect_error_status(pdev);
+	if (rc) {
+		netif_err(efx, hw, efx->net_dev,
+		"pci_cleanup_aer_uncorrect_error_status failed (%d)\n", rc);
+		/* Non-fatal error. Continue. */
+	}
+
+	return status;
+}
+
+/* Perform the actual reset and resume I/O operations. */
+static void efx_io_resume(struct pci_dev *pdev)
+{
+	struct efx_nic *efx = pci_get_drvdata(pdev);
+	int rc;
+
+	rtnl_lock();
+
+	if (efx->state == STATE_DISABLED)
+		goto out;
+
+	rc = efx_reset(efx, RESET_TYPE_ALL);
+	if (rc) {
+		netif_err(efx, hw, efx->net_dev,
+			  "efx_reset failed after PCI error (%d)\n", rc);
+	} else {
+		efx->state = STATE_READY;
+		netif_dbg(efx, hw, efx->net_dev,
+			  "Done resetting and resuming IO after PCI error.\n");
+	}
+
+out:
+	rtnl_unlock();
+}
+
+/* For simplicity and reliability, we always require a slot reset and try to
+ * reset the hardware when a pci error affecting the device is detected.
+ * We leave both the link_reset and mmio_enabled callback unimplemented:
+ * with our request for slot reset the mmio_enabled callback will never be
+ * called, and the link_reset callback is not used by AER or EEH mechanisms.
+ */
+static struct pci_error_handlers efx_err_handlers = {
+	.error_detected = efx_io_error_detected,
+	.slot_reset	= efx_io_slot_reset,
+	.resume		= efx_io_resume,
+};
+
 static struct pci_driver efx_pci_driver = {
 	.name		= KBUILD_MODNAME,
 	.id_table	= efx_pci_table,
 	.probe		= efx_pci_probe,
 	.remove		= efx_pci_remove,
 	.driver.pm	= &efx_pm_ops,
+	.err_handler	= &efx_err_handlers,
 };
 
 /**************************************************************************
diff --git a/drivers/net/ethernet/sfc/efx.h b/drivers/net/ethernet/sfc/efx.h
index d2f790d..8372da2 100644
--- a/drivers/net/ethernet/sfc/efx.h
+++ b/drivers/net/ethernet/sfc/efx.h
@@ -33,17 +33,22 @@ extern int efx_setup_tc(struct net_device *net_dev, u8 num_tc);
 extern unsigned int efx_tx_max_skb_descs(struct efx_nic *efx);
 
 /* RX */
+extern void efx_rx_config_page_split(struct efx_nic *efx);
 extern int efx_probe_rx_queue(struct efx_rx_queue *rx_queue);
 extern void efx_remove_rx_queue(struct efx_rx_queue *rx_queue);
 extern void efx_init_rx_queue(struct efx_rx_queue *rx_queue);
 extern void efx_fini_rx_queue(struct efx_rx_queue *rx_queue);
-extern void efx_rx_strategy(struct efx_channel *channel);
 extern void efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue);
 extern void efx_rx_slow_fill(unsigned long context);
-extern void __efx_rx_packet(struct efx_channel *channel,
-			    struct efx_rx_buffer *rx_buf);
-extern void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index,
+extern void __efx_rx_packet(struct efx_channel *channel);
+extern void efx_rx_packet(struct efx_rx_queue *rx_queue,
+			  unsigned int index, unsigned int n_frags,
 			  unsigned int len, u16 flags);
+static inline void efx_rx_flush_packet(struct efx_channel *channel)
+{
+	if (channel->rx_pkt_n_frags)
+		__efx_rx_packet(channel);
+}
 extern void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue);
 
 #define EFX_MAX_DMAQ_SIZE 4096UL
@@ -67,6 +72,7 @@ extern void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue);
 extern int efx_probe_filters(struct efx_nic *efx);
 extern void efx_restore_filters(struct efx_nic *efx);
 extern void efx_remove_filters(struct efx_nic *efx);
+extern void efx_filter_update_rx_scatter(struct efx_nic *efx);
 extern s32 efx_filter_insert_filter(struct efx_nic *efx,
 				    struct efx_filter_spec *spec,
 				    bool replace);
diff --git a/drivers/net/ethernet/sfc/enum.h b/drivers/net/ethernet/sfc/enum.h
index 182dbe2..ab8fb58 100644
--- a/drivers/net/ethernet/sfc/enum.h
+++ b/drivers/net/ethernet/sfc/enum.h
@@ -137,8 +137,12 @@ enum efx_loopback_mode {
  * Reset methods are numbered in order of increasing scope.
  *
  * @RESET_TYPE_INVISIBLE: Reset datapath and MAC (Falcon only)
+ * @RESET_TYPE_RECOVER_OR_ALL: Try to recover. Apply RESET_TYPE_ALL
+ * if unsuccessful.
  * @RESET_TYPE_ALL: Reset datapath, MAC and PHY
  * @RESET_TYPE_WORLD: Reset as much as possible
+ * @RESET_TYPE_RECOVER_OR_DISABLE: Try to recover. Apply RESET_TYPE_DISABLE if
+ * unsuccessful.
  * @RESET_TYPE_DISABLE: Reset datapath, MAC and PHY; leave NIC disabled
  * @RESET_TYPE_TX_WATCHDOG: reset due to TX watchdog
  * @RESET_TYPE_INT_ERROR: reset due to internal error
@@ -150,9 +154,11 @@ enum efx_loopback_mode {
  */
 enum reset_type {
 	RESET_TYPE_INVISIBLE = 0,
-	RESET_TYPE_ALL = 1,
-	RESET_TYPE_WORLD = 2,
-	RESET_TYPE_DISABLE = 3,
+	RESET_TYPE_RECOVER_OR_ALL = 1,
+	RESET_TYPE_ALL = 2,
+	RESET_TYPE_WORLD = 3,
+	RESET_TYPE_RECOVER_OR_DISABLE = 4,
+	RESET_TYPE_DISABLE = 5,
 	RESET_TYPE_MAX_METHOD,
 	RESET_TYPE_TX_WATCHDOG,
 	RESET_TYPE_INT_ERROR,
diff --git a/drivers/net/ethernet/sfc/ethtool.c b/drivers/net/ethernet/sfc/ethtool.c
index 8e61cd0..6e76817 100644
--- a/drivers/net/ethernet/sfc/ethtool.c
+++ b/drivers/net/ethernet/sfc/ethtool.c
@@ -154,6 +154,7 @@ static const struct efx_ethtool_stat efx_ethtool_stats[] = {
 	EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_tcp_udp_chksum_err),
 	EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_mcast_mismatch),
 	EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_frm_trunc),
+	EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_nodesc_trunc),
 };
 
 /* Number of ethtool statistics */
@@ -978,7 +979,8 @@ static int efx_ethtool_set_class_rule(struct efx_nic *efx,
 	     rule->m_ext.data[1]))
 		return -EINVAL;
 
-	efx_filter_init_rx(&spec, EFX_FILTER_PRI_MANUAL, 0,
+	efx_filter_init_rx(&spec, EFX_FILTER_PRI_MANUAL,
+			   efx->rx_scatter ? EFX_FILTER_FLAG_RX_SCATTER : 0,
 			   (rule->ring_cookie == RX_CLS_FLOW_DISC) ?
 			   0xfff : rule->ring_cookie);
 
diff --git a/drivers/net/ethernet/sfc/falcon.c b/drivers/net/ethernet/sfc/falcon.c
index 49bcd19..71998e7 100644
--- a/drivers/net/ethernet/sfc/falcon.c
+++ b/drivers/net/ethernet/sfc/falcon.c
@@ -1528,7 +1528,7 @@ static int falcon_probe_nic(struct efx_nic *efx)
 	return 0;
 
  fail6:
-	BUG_ON(i2c_del_adapter(&board->i2c_adap));
+	i2c_del_adapter(&board->i2c_adap);
 	memset(&board->i2c_adap, 0, sizeof(board->i2c_adap));
  fail5:
 	efx_nic_free_buffer(efx, &efx->irq_status);
@@ -1546,10 +1546,6 @@ static int falcon_probe_nic(struct efx_nic *efx)
 
 static void falcon_init_rx_cfg(struct efx_nic *efx)
 {
-	/* Prior to Siena the RX DMA engine will split each frame at
-	 * intervals of RX_USR_BUF_SIZE (32-byte units). We set it to
-	 * be so large that that never happens. */
-	const unsigned huge_buf_size = (3 * 4096) >> 5;
 	/* RX control FIFO thresholds (32 entries) */
 	const unsigned ctrl_xon_thr = 20;
 	const unsigned ctrl_xoff_thr = 25;
@@ -1557,10 +1553,15 @@ static void falcon_init_rx_cfg(struct efx_nic *efx)
 
 	efx_reado(efx, &reg, FR_AZ_RX_CFG);
 	if (efx_nic_rev(efx) <= EFX_REV_FALCON_A1) {
-		/* Data FIFO size is 5.5K */
+		/* Data FIFO size is 5.5K.  The RX DMA engine only
+		 * supports scattering for user-mode queues, but will
+		 * split DMA writes at intervals of RX_USR_BUF_SIZE
+		 * (32-byte units) even for kernel-mode queues.  We
+		 * set it to be so large that that never happens.
+		 */
 		EFX_SET_OWORD_FIELD(reg, FRF_AA_RX_DESC_PUSH_EN, 0);
 		EFX_SET_OWORD_FIELD(reg, FRF_AA_RX_USR_BUF_SIZE,
-				    huge_buf_size);
+				    (3 * 4096) >> 5);
 		EFX_SET_OWORD_FIELD(reg, FRF_AA_RX_XON_MAC_TH, 512 >> 8);
 		EFX_SET_OWORD_FIELD(reg, FRF_AA_RX_XOFF_MAC_TH, 2048 >> 8);
 		EFX_SET_OWORD_FIELD(reg, FRF_AA_RX_XON_TX_TH, ctrl_xon_thr);
@@ -1569,7 +1570,7 @@ static void falcon_init_rx_cfg(struct efx_nic *efx)
 		/* Data FIFO size is 80K; register fields moved */
 		EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_DESC_PUSH_EN, 0);
 		EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_USR_BUF_SIZE,
-				    huge_buf_size);
+				    EFX_RX_USR_BUF_SIZE >> 5);
 		/* Send XON and XOFF at ~3 * max MTU away from empty/full */
 		EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_XON_MAC_TH, 27648 >> 8);
 		EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_XOFF_MAC_TH, 54272 >> 8);
@@ -1665,13 +1666,11 @@ static void falcon_remove_nic(struct efx_nic *efx)
 {
 	struct falcon_nic_data *nic_data = efx->nic_data;
 	struct falcon_board *board = falcon_board(efx);
-	int rc;
 
 	board->type->fini(efx);
 
 	/* Remove I2C adapter and clear it in preparation for a retry */
-	rc = i2c_del_adapter(&board->i2c_adap);
-	BUG_ON(rc);
+	i2c_del_adapter(&board->i2c_adap);
 	memset(&board->i2c_adap, 0, sizeof(board->i2c_adap));
 
 	efx_nic_free_buffer(efx, &efx->irq_status);
@@ -1815,6 +1814,7 @@ const struct efx_nic_type falcon_a1_nic_type = {
 	.evq_rptr_tbl_base = FR_AA_EVQ_RPTR_KER,
 	.max_dma_mask = DMA_BIT_MASK(FSF_AZ_TX_KER_BUF_ADDR_WIDTH),
 	.rx_buffer_padding = 0x24,
+	.can_rx_scatter = false,
 	.max_interrupt_mode = EFX_INT_MODE_MSI,
 	.phys_addr_channels = 4,
 	.timer_period_max =  1 << FRF_AB_TC_TIMER_VAL_WIDTH,
@@ -1865,6 +1865,7 @@ const struct efx_nic_type falcon_b0_nic_type = {
 	.max_dma_mask = DMA_BIT_MASK(FSF_AZ_TX_KER_BUF_ADDR_WIDTH),
 	.rx_buffer_hash_size = 0x10,
 	.rx_buffer_padding = 0,
+	.can_rx_scatter = true,
 	.max_interrupt_mode = EFX_INT_MODE_MSIX,
 	.phys_addr_channels = 32, /* Hardware limit is 64, but the legacy
 				   * interrupt handler only supports 32
diff --git a/drivers/net/ethernet/sfc/filter.c b/drivers/net/ethernet/sfc/filter.c
index 8af42cd..2397f0e 100644
--- a/drivers/net/ethernet/sfc/filter.c
+++ b/drivers/net/ethernet/sfc/filter.c
@@ -66,6 +66,10 @@ struct efx_filter_state {
 #endif
 };
 
+static void efx_filter_table_clear_entry(struct efx_nic *efx,
+					 struct efx_filter_table *table,
+					 unsigned int filter_idx);
+
 /* The filter hash function is LFSR polynomial x^16 + x^3 + 1 of a 32-bit
  * key derived from the n-tuple.  The initial LFSR state is 0xffff. */
 static u16 efx_filter_hash(u32 key)
@@ -168,6 +172,25 @@ static void efx_filter_push_rx_config(struct efx_nic *efx)
 			filter_ctl, FRF_CZ_MULTICAST_NOMATCH_RSS_ENABLED,
 			!!(table->spec[EFX_FILTER_INDEX_MC_DEF].flags &
 			   EFX_FILTER_FLAG_RX_RSS));
+
+		/* There is a single bit to enable RX scatter for all
+		 * unmatched packets.  Only set it if scatter is
+		 * enabled in both filter specs.
+		 */
+		EFX_SET_OWORD_FIELD(
+			filter_ctl, FRF_BZ_SCATTER_ENBL_NO_MATCH_Q,
+			!!(table->spec[EFX_FILTER_INDEX_UC_DEF].flags &
+			   table->spec[EFX_FILTER_INDEX_MC_DEF].flags &
+			   EFX_FILTER_FLAG_RX_SCATTER));
+	} else if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0) {
+		/* We don't expose 'default' filters because unmatched
+		 * packets always go to the queue number found in the
+		 * RSS table.  But we still need to set the RX scatter
+		 * bit here.
+		 */
+		EFX_SET_OWORD_FIELD(
+			filter_ctl, FRF_BZ_SCATTER_ENBL_NO_MATCH_Q,
+			efx->rx_scatter);
 	}
 
 	efx_writeo(efx, &filter_ctl, FR_BZ_RX_FILTER_CTL);
@@ -409,9 +432,18 @@ static void efx_filter_reset_rx_def(struct efx_nic *efx, unsigned filter_idx)
 	struct efx_filter_state *state = efx->filter_state;
 	struct efx_filter_table *table = &state->table[EFX_FILTER_TABLE_RX_DEF];
 	struct efx_filter_spec *spec = &table->spec[filter_idx];
+	enum efx_filter_flags flags = 0;
+
+	/* If there's only one channel then disable RSS for non VF
+	 * traffic, thereby allowing VFs to use RSS when the PF can't.
+	 */
+	if (efx->n_rx_channels > 1)
+		flags |= EFX_FILTER_FLAG_RX_RSS;
 
-	efx_filter_init_rx(spec, EFX_FILTER_PRI_MANUAL,
-			   EFX_FILTER_FLAG_RX_RSS, 0);
+	if (efx->rx_scatter)
+		flags |= EFX_FILTER_FLAG_RX_SCATTER;
+
+	efx_filter_init_rx(spec, EFX_FILTER_PRI_MANUAL, flags, 0);
 	spec->type = EFX_FILTER_UC_DEF + filter_idx;
 	table->used_bitmap[0] |= 1 << filter_idx;
 }
@@ -463,13 +495,6 @@ static u32 efx_filter_build(efx_oword_t *filter, struct efx_filter_spec *spec)
 		break;
 	}
 
-	case EFX_FILTER_TABLE_RX_DEF:
-		/* One filter spec per type */
-		BUILD_BUG_ON(EFX_FILTER_INDEX_UC_DEF != 0);
-		BUILD_BUG_ON(EFX_FILTER_INDEX_MC_DEF !=
-			     EFX_FILTER_MC_DEF - EFX_FILTER_UC_DEF);
-		return spec->type - EFX_FILTER_UC_DEF;
-
 	case EFX_FILTER_TABLE_RX_MAC: {
 		bool is_wild = spec->type == EFX_FILTER_MAC_WILD;
 		EFX_POPULATE_OWORD_7(
@@ -520,42 +545,6 @@ static bool efx_filter_equal(const struct efx_filter_spec *left,
 	return true;
 }
 
-static int efx_filter_search(struct efx_filter_table *table,
-			     struct efx_filter_spec *spec, u32 key,
-			     bool for_insert, unsigned int *depth_required)
-{
-	unsigned hash, incr, filter_idx, depth, depth_max;
-
-	hash = efx_filter_hash(key);
-	incr = efx_filter_increment(key);
-
-	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;
-	}
-}
-
 /*
  * Construct/deconstruct external filter IDs.  At least the RX filter
  * IDs must be ordered by matching priority, for RX NFC semantics.
@@ -650,44 +639,111 @@ u32 efx_filter_get_rx_id_limit(struct efx_nic *efx)
  * efx_filter_insert_filter - add or replace a filter
  * @efx: NIC in which to insert the filter
  * @spec: Specification for the filter
- * @replace: Flag for whether the specified filter may replace a filter
- *	with an identical match expression and equal or lower priority
+ * @replace_equal: Flag for whether the specified filter may replace an
+ *	existing filter with equal priority
  *
  * On success, return the filter ID.
  * On failure, return a negative error code.
+ *
+ * If an existing filter has equal match values to the new filter
+ * spec, then the new filter might replace it, depending on the
+ * relative priorities.  If the existing filter has lower priority, or
+ * if @replace_equal is set and it has equal priority, then it is
+ * replaced.  Otherwise the function fails, returning -%EPERM if
+ * the existing filter has higher priority or -%EEXIST if it has
+ * equal priority.
  */
 s32 efx_filter_insert_filter(struct efx_nic *efx, struct efx_filter_spec *spec,
-			     bool replace)
+			     bool replace_equal)
 {
 	struct efx_filter_state *state = efx->filter_state;
 	struct efx_filter_table *table = efx_filter_spec_table(state, spec);
-	struct efx_filter_spec *saved_spec;
 	efx_oword_t filter;
-	unsigned int filter_idx, depth = 0;
-	u32 key;
+	int rep_index, ins_index;
+	unsigned int depth = 0;
 	int rc;
 
 	if (!table || table->size == 0)
 		return -EINVAL;
 
-	key = efx_filter_build(&filter, spec);
-
 	netif_vdbg(efx, hw, efx->net_dev,
 		   "%s: type %d search_depth=%d", __func__, spec->type,
 		   table->search_depth[spec->type]);
 
-	spin_lock_bh(&state->lock);
+	if (table->id == EFX_FILTER_TABLE_RX_DEF) {
+		/* One filter spec per type */
+		BUILD_BUG_ON(EFX_FILTER_INDEX_UC_DEF != 0);
+		BUILD_BUG_ON(EFX_FILTER_INDEX_MC_DEF !=
+			     EFX_FILTER_MC_DEF - EFX_FILTER_UC_DEF);
+		rep_index = spec->type - EFX_FILTER_INDEX_UC_DEF;
+		ins_index = rep_index;
 
-	rc = efx_filter_search(table, spec, key, true, &depth);
-	if (rc < 0)
-		goto out;
-	filter_idx = rc;
-	BUG_ON(filter_idx >= table->size);
-	saved_spec = &table->spec[filter_idx];
-
-	if (test_bit(filter_idx, table->used_bitmap)) {
-		/* Should we replace the existing filter? */
-		if (!replace) {
+		spin_lock_bh(&state->lock);
+	} else {
+		/* Search concurrently for
+		 * (1) a filter to be replaced (rep_index): any filter
+		 *     with the same match values, up to the current
+		 *     search depth for this type, and
+		 * (2) the insertion point (ins_index): (1) or any
+		 *     free slot before it or up to the maximum search
+		 *     depth for this priority
+		 * We fail if we cannot find (2).
+		 *
+		 * We can stop once either
+		 * (a) we find (1), in which case we have definitely
+		 *     found (2) as well; or
+		 * (b) we have searched exhaustively for (1), and have
+		 *     either found (2) or searched exhaustively for it
+		 */
+		u32 key = efx_filter_build(&filter, spec);
+		unsigned int hash = efx_filter_hash(key);
+		unsigned int incr = efx_filter_increment(key);
+		unsigned int max_rep_depth = table->search_depth[spec->type];
+		unsigned int max_ins_depth =
+			spec->priority <= EFX_FILTER_PRI_HINT ?
+			FILTER_CTL_SRCH_HINT_MAX : FILTER_CTL_SRCH_MAX;
+		unsigned int i = hash & (table->size - 1);
+
+		ins_index = -1;
+		depth = 1;
+
+		spin_lock_bh(&state->lock);
+
+		for (;;) {
+			if (!test_bit(i, table->used_bitmap)) {
+				if (ins_index < 0)
+					ins_index = i;
+			} else if (efx_filter_equal(spec, &table->spec[i])) {
+				/* Case (a) */
+				if (ins_index < 0)
+					ins_index = i;
+				rep_index = i;
+				break;
+			}
+
+			if (depth >= max_rep_depth &&
+			    (ins_index >= 0 || depth >= max_ins_depth)) {
+				/* Case (b) */
+				if (ins_index < 0) {
+					rc = -EBUSY;
+					goto out;
+				}
+				rep_index = -1;
+				break;
+			}
+
+			i = (i + incr) & (table->size - 1);
+			++depth;
+		}
+	}
+
+	/* If we found a filter to be replaced, check whether we
+	 * should do so
+	 */
+	if (rep_index >= 0) {
+		struct efx_filter_spec *saved_spec = &table->spec[rep_index];
+
+		if (spec->priority == saved_spec->priority && !replace_equal) {
 			rc = -EEXIST;
 			goto out;
 		}
@@ -695,11 +751,14 @@ s32 efx_filter_insert_filter(struct efx_nic *efx, struct efx_filter_spec *spec,
 			rc = -EPERM;
 			goto out;
 		}
-	} else {
-		__set_bit(filter_idx, table->used_bitmap);
+	}
+
+	/* Insert the filter */
+	if (ins_index != rep_index) {
+		__set_bit(ins_index, table->used_bitmap);
 		++table->used;
 	}
-	*saved_spec = *spec;
+	table->spec[ins_index] = *spec;
 
 	if (table->id == EFX_FILTER_TABLE_RX_DEF) {
 		efx_filter_push_rx_config(efx);
@@ -713,13 +772,19 @@ s32 efx_filter_insert_filter(struct efx_nic *efx, struct efx_filter_spec *spec,
 		}
 
 		efx_writeo(efx, &filter,
-			   table->offset + table->step * filter_idx);
+			   table->offset + table->step * ins_index);
+
+		/* If we were able to replace a filter by inserting
+		 * at a lower depth, clear the replaced filter
+		 */
+		if (ins_index != rep_index && rep_index >= 0)
+			efx_filter_table_clear_entry(efx, table, rep_index);
 	}
 
 	netif_vdbg(efx, hw, efx->net_dev,
 		   "%s: filter type %d index %d rxq %u set",
-		   __func__, spec->type, filter_idx, spec->dmaq_id);
-	rc = efx_filter_make_id(spec, filter_idx);
+		   __func__, spec->type, ins_index, spec->dmaq_id);
+	rc = efx_filter_make_id(spec, ins_index);
 
 out:
 	spin_unlock_bh(&state->lock);
@@ -1060,6 +1125,50 @@ void efx_remove_filters(struct efx_nic *efx)
 	kfree(state);
 }
 
+/* Update scatter enable flags for filters pointing to our own RX queues */
+void efx_filter_update_rx_scatter(struct efx_nic *efx)
+{
+	struct efx_filter_state *state = efx->filter_state;
+	enum efx_filter_table_id table_id;
+	struct efx_filter_table *table;
+	efx_oword_t filter;
+	unsigned int filter_idx;
+
+	spin_lock_bh(&state->lock);
+
+	for (table_id = EFX_FILTER_TABLE_RX_IP;
+	     table_id <= EFX_FILTER_TABLE_RX_DEF;
+	     table_id++) {
+		table = &state->table[table_id];
+
+		for (filter_idx = 0; filter_idx < table->size; filter_idx++) {
+			if (!test_bit(filter_idx, table->used_bitmap) ||
+			    table->spec[filter_idx].dmaq_id >=
+			    efx->n_rx_channels)
+				continue;
+
+			if (efx->rx_scatter)
+				table->spec[filter_idx].flags |=
+					EFX_FILTER_FLAG_RX_SCATTER;
+			else
+				table->spec[filter_idx].flags &=
+					~EFX_FILTER_FLAG_RX_SCATTER;
+
+			if (table_id == EFX_FILTER_TABLE_RX_DEF)
+				/* Pushed by efx_filter_push_rx_config() */
+				continue;
+
+			efx_filter_build(&filter, &table->spec[filter_idx]);
+			efx_writeo(efx, &filter,
+				   table->offset + table->step * filter_idx);
+		}
+	}
+
+	efx_filter_push_rx_config(efx);
+
+	spin_unlock_bh(&state->lock);
+}
+
 #ifdef CONFIG_RFS_ACCEL
 
 int efx_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb,
diff --git a/drivers/net/ethernet/sfc/mcdi_pcol.h b/drivers/net/ethernet/sfc/mcdi_pcol.h
index 9d426d0..c5c9747 100644
--- a/drivers/net/ethernet/sfc/mcdi_pcol.h
+++ b/drivers/net/ethernet/sfc/mcdi_pcol.h
@@ -553,6 +553,7 @@
 #define          MC_CMD_PTP_MODE_V1_VLAN 0x1 /* enum */
 #define          MC_CMD_PTP_MODE_V2 0x2 /* enum */
 #define          MC_CMD_PTP_MODE_V2_VLAN 0x3 /* enum */
+#define          MC_CMD_PTP_MODE_V2_ENHANCED 0x4 /* enum */
 
 /* MC_CMD_PTP_IN_DISABLE msgrequest */
 #define    MC_CMD_PTP_IN_DISABLE_LEN 8
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
index 0a90abd..9bd433a 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -69,6 +69,12 @@
 #define EFX_TXQ_TYPES		4
 #define EFX_MAX_TX_QUEUES	(EFX_TXQ_TYPES * EFX_MAX_CHANNELS)
 
+/* Maximum possible MTU the driver supports */
+#define EFX_MAX_MTU (9 * 1024)
+
+/* Size of an RX scatter buffer.  Small enough to pack 2 into a 4K page. */
+#define EFX_RX_USR_BUF_SIZE 1824
+
 /* Forward declare Precision Time Protocol (PTP) support structure. */
 struct efx_ptp_data;
 
@@ -206,25 +212,23 @@ struct efx_tx_queue {
 /**
  * struct efx_rx_buffer - An Efx RX data buffer
  * @dma_addr: DMA base address of the buffer
- * @skb: The associated socket buffer. Valid iff !(@flags & %EFX_RX_BUF_PAGE).
- *	Will be %NULL if the buffer slot is currently free.
- * @page: The associated page buffer. Valif iff @flags & %EFX_RX_BUF_PAGE.
+ * @page: The associated page buffer.
  *	Will be %NULL if the buffer slot is currently free.
- * @page_offset: Offset within page. Valid iff @flags & %EFX_RX_BUF_PAGE.
- * @len: Buffer length, in bytes.
- * @flags: Flags for buffer and packet state.
+ * @page_offset: If pending: offset in @page of DMA base address.
+ *	If completed: offset in @page of Ethernet header.
+ * @len: If pending: length for DMA descriptor.
+ *	If completed: received length, excluding hash prefix.
+ * @flags: Flags for buffer and packet state.  These are only set on the
+ *	first buffer of a scattered packet.
  */
 struct efx_rx_buffer {
 	dma_addr_t dma_addr;
-	union {
-		struct sk_buff *skb;
-		struct page *page;
-	} u;
+	struct page *page;
 	u16 page_offset;
 	u16 len;
 	u16 flags;
 };
-#define EFX_RX_BUF_PAGE		0x0001
+#define EFX_RX_BUF_LAST_IN_PAGE	0x0001
 #define EFX_RX_PKT_CSUMMED	0x0002
 #define EFX_RX_PKT_DISCARD	0x0004
 
@@ -260,14 +264,23 @@ struct efx_rx_page_state {
  * @added_count: Number of buffers added to the receive queue.
  * @notified_count: Number of buffers given to NIC (<= @added_count).
  * @removed_count: Number of buffers removed from the receive queue.
+ * @scatter_n: Number of buffers used by current packet
+ * @page_ring: The ring to store DMA mapped pages for reuse.
+ * @page_add: Counter to calculate the write pointer for the recycle ring.
+ * @page_remove: Counter to calculate the read pointer for the recycle ring.
+ * @page_recycle_count: The number of pages that have been recycled.
+ * @page_recycle_failed: The number of pages that couldn't be recycled because
+ *      the kernel still held a reference to them.
+ * @page_recycle_full: The number of pages that were released because the
+ *      recycle ring was full.
+ * @page_ptr_mask: The number of pages in the RX recycle ring minus 1.
  * @max_fill: RX descriptor maximum fill level (<= ring size)
  * @fast_fill_trigger: RX descriptor fill level that will trigger a fast fill
  *	(<= @max_fill)
  * @min_fill: RX descriptor minimum non-zero fill level.
  *	This records the minimum fill level observed when a ring
  *	refill was triggered.
- * @alloc_page_count: RX allocation strategy counter.
- * @alloc_skb_count: RX allocation strategy counter.
+ * @recycle_count: RX buffer recycle counter.
  * @slow_fill: Timer used to defer efx_nic_generate_fill_event().
  */
 struct efx_rx_queue {
@@ -279,15 +292,22 @@ struct efx_rx_queue {
 	bool enabled;
 	bool flush_pending;
 
-	int added_count;
-	int notified_count;
-	int removed_count;
+	unsigned int added_count;
+	unsigned int notified_count;
+	unsigned int removed_count;
+	unsigned int scatter_n;
+	struct page **page_ring;
+	unsigned int page_add;
+	unsigned int page_remove;
+	unsigned int page_recycle_count;
+	unsigned int page_recycle_failed;
+	unsigned int page_recycle_full;
+	unsigned int page_ptr_mask;
 	unsigned int max_fill;
 	unsigned int fast_fill_trigger;
 	unsigned int min_fill;
 	unsigned int min_overfill;
-	unsigned int alloc_page_count;
-	unsigned int alloc_skb_count;
+	unsigned int recycle_count;
 	struct timer_list slow_fill;
 	unsigned int slow_fill_count;
 };
@@ -336,10 +356,6 @@ enum efx_rx_alloc_method {
  * @event_test_cpu: Last CPU to handle interrupt or test event for this channel
  * @irq_count: Number of IRQs since last adaptive moderation decision
  * @irq_mod_score: IRQ moderation score
- * @rx_alloc_level: Watermark based heuristic counter for pushing descriptors
- *	and diagnostic counters
- * @rx_alloc_push_pages: RX allocation method currently in use for pushing
- *	descriptors
  * @n_rx_tobe_disc: Count of RX_TOBE_DISC errors
  * @n_rx_ip_hdr_chksum_err: Count of RX IP header checksum errors
  * @n_rx_tcp_udp_chksum_err: Count of RX TCP and UDP checksum errors
@@ -347,6 +363,12 @@ enum efx_rx_alloc_method {
  * @n_rx_frm_trunc: Count of RX_FRM_TRUNC errors
  * @n_rx_overlength: Count of RX_OVERLENGTH errors
  * @n_skbuff_leaks: Count of skbuffs leaked due to RX overrun
+ * @n_rx_nodesc_trunc: Number of RX packets truncated and then dropped due to
+ *	lack of descriptors
+ * @rx_pkt_n_frags: Number of fragments in next packet to be delivered by
+ *	__efx_rx_packet(), or zero if there is none
+ * @rx_pkt_index: Ring index of first buffer for next packet to be delivered
+ *	by __efx_rx_packet(), if @rx_pkt_n_frags != 0
  * @rx_queue: RX queue for this channel
  * @tx_queue: TX queues for this channel
  */
@@ -371,9 +393,6 @@ struct efx_channel {
 	unsigned int rfs_filters_added;
 #endif
 
-	int rx_alloc_level;
-	int rx_alloc_push_pages;
-
 	unsigned n_rx_tobe_disc;
 	unsigned n_rx_ip_hdr_chksum_err;
 	unsigned n_rx_tcp_udp_chksum_err;
@@ -381,11 +400,10 @@ struct efx_channel {
 	unsigned n_rx_frm_trunc;
 	unsigned n_rx_overlength;
 	unsigned n_skbuff_leaks;
+	unsigned int n_rx_nodesc_trunc;
 
-	/* Used to pipeline received packets in order to optimise memory
-	 * access with prefetches.
-	 */
-	struct efx_rx_buffer *rx_pkt;
+	unsigned int rx_pkt_n_frags;
+	unsigned int rx_pkt_index;
 
 	struct efx_rx_queue rx_queue;
 	struct efx_tx_queue tx_queue[EFX_TXQ_TYPES];
@@ -410,7 +428,7 @@ struct efx_channel_type {
 	void (*post_remove)(struct efx_channel *);
 	void (*get_name)(struct efx_channel *, char *buf, size_t len);
 	struct efx_channel *(*copy)(const struct efx_channel *);
-	void (*receive_skb)(struct efx_channel *, struct sk_buff *);
+	bool (*receive_skb)(struct efx_channel *, struct sk_buff *);
 	bool keep_eventq;
 };
 
@@ -446,6 +464,7 @@ enum nic_state {
 	STATE_UNINIT = 0,	/* device being probed/removed or is frozen */
 	STATE_READY = 1,	/* hardware ready and netdev registered */
 	STATE_DISABLED = 2,	/* device disabled due to hardware errors */
+	STATE_RECOVERY = 3,	/* device recovering from PCI error */
 };
 
 /*
@@ -684,10 +703,13 @@ struct vfdi_status;
  * @n_channels: Number of channels in use
  * @n_rx_channels: Number of channels used for RX (= number of RX queues)
  * @n_tx_channels: Number of channels used for TX
- * @rx_buffer_len: RX buffer length
+ * @rx_dma_len: Current maximum RX DMA length
  * @rx_buffer_order: Order (log2) of number of pages for each RX buffer
+ * @rx_buffer_truesize: Amortised allocation size of an RX buffer,
+ *	for use in sk_buff::truesize
  * @rx_hash_key: Toeplitz hash key for RSS
  * @rx_indir_table: Indirection table for RSS
+ * @rx_scatter: Scatter mode enabled for receives
  * @int_error_count: Number of internal errors seen recently
  * @int_error_expire: Time at which error count will be expired
  * @irq_status: Interrupt status buffer
@@ -800,10 +822,15 @@ struct efx_nic {
 	unsigned rss_spread;
 	unsigned tx_channel_offset;
 	unsigned n_tx_channels;
-	unsigned int rx_buffer_len;
+	unsigned int rx_dma_len;
 	unsigned int rx_buffer_order;
+	unsigned int rx_buffer_truesize;
+	unsigned int rx_page_buf_step;
+	unsigned int rx_bufs_per_page;
+	unsigned int rx_pages_per_batch;
 	u8 rx_hash_key[40];
 	u32 rx_indir_table[128];
+	bool rx_scatter;
 
 	unsigned int_error_count;
 	unsigned long int_error_expire;
@@ -934,8 +961,9 @@ static inline unsigned int efx_port_num(struct efx_nic *efx)
  * @evq_ptr_tbl_base: Event queue pointer table base address
  * @evq_rptr_tbl_base: Event queue read-pointer table base address
  * @max_dma_mask: Maximum possible DMA mask
- * @rx_buffer_hash_size: Size of hash at start of RX buffer
- * @rx_buffer_padding: Size of padding at end of RX buffer
+ * @rx_buffer_hash_size: Size of hash at start of RX packet
+ * @rx_buffer_padding: Size of padding at end of RX packet
+ * @can_rx_scatter: NIC is able to scatter packet to multiple buffers
  * @max_interrupt_mode: Highest capability interrupt mode supported
  *	from &enum efx_init_mode.
  * @phys_addr_channels: Number of channels with physically addressed
@@ -983,6 +1011,7 @@ struct efx_nic_type {
 	u64 max_dma_mask;
 	unsigned int rx_buffer_hash_size;
 	unsigned int rx_buffer_padding;
+	bool can_rx_scatter;
 	unsigned int max_interrupt_mode;
 	unsigned int phys_addr_channels;
 	unsigned int timer_period_max;
diff --git a/drivers/net/ethernet/sfc/nic.c b/drivers/net/ethernet/sfc/nic.c
index eaa8e87..b0503cd 100644
--- a/drivers/net/ethernet/sfc/nic.c
+++ b/drivers/net/ethernet/sfc/nic.c
@@ -305,11 +305,11 @@ int efx_nic_alloc_buffer(struct efx_nic *efx, struct efx_buffer *buffer,
 			 unsigned int len)
 {
 	buffer->addr = dma_alloc_coherent(&efx->pci_dev->dev, len,
-					  &buffer->dma_addr, GFP_ATOMIC);
+					  &buffer->dma_addr,
+					  GFP_ATOMIC | __GFP_ZERO);
 	if (!buffer->addr)
 		return -ENOMEM;
 	buffer->len = len;
-	memset(buffer->addr, 0, len);
 	return 0;
 }
 
@@ -592,12 +592,22 @@ void efx_nic_init_rx(struct efx_rx_queue *rx_queue)
 	struct efx_nic *efx = rx_queue->efx;
 	bool is_b0 = efx_nic_rev(efx) >= EFX_REV_FALCON_B0;
 	bool iscsi_digest_en = is_b0;
+	bool jumbo_en;
+
+	/* For kernel-mode queues in Falcon A1, the JUMBO flag enables
+	 * DMA to continue after a PCIe page boundary (and scattering
+	 * is not possible).  In Falcon B0 and Siena, it enables
+	 * scatter.
+	 */
+	jumbo_en = !is_b0 || efx->rx_scatter;
 
 	netif_dbg(efx, hw, efx->net_dev,
 		  "RX queue %d ring in special buffers %d-%d\n",
 		  efx_rx_queue_index(rx_queue), rx_queue->rxd.index,
 		  rx_queue->rxd.index + rx_queue->rxd.entries - 1);
 
+	rx_queue->scatter_n = 0;
+
 	/* Pin RX descriptor ring */
 	efx_init_special_buffer(efx, &rx_queue->rxd);
 
@@ -614,8 +624,7 @@ void efx_nic_init_rx(struct efx_rx_queue *rx_queue)
 			      FRF_AZ_RX_DESCQ_SIZE,
 			      __ffs(rx_queue->rxd.entries),
 			      FRF_AZ_RX_DESCQ_TYPE, 0 /* kernel queue */ ,
-			      /* For >=B0 this is scatter so disable */
-			      FRF_AZ_RX_DESCQ_JUMBO, !is_b0,
+			      FRF_AZ_RX_DESCQ_JUMBO, jumbo_en,
 			      FRF_AZ_RX_DESCQ_EN, 1);
 	efx_writeo_table(efx, &rx_desc_ptr, efx->type->rxd_ptr_tbl_base,
 			 efx_rx_queue_index(rx_queue));
@@ -969,13 +978,24 @@ static u16 efx_handle_rx_not_ok(struct efx_rx_queue *rx_queue,
 		EFX_RX_PKT_DISCARD : 0;
 }
 
-/* Handle receive events that are not in-order. */
-static void
+/* Handle receive events that are not in-order. Return true if this
+ * can be handled as a partial packet discard, false if it's more
+ * serious.
+ */
+static bool
 efx_handle_rx_bad_index(struct efx_rx_queue *rx_queue, unsigned index)
 {
+	struct efx_channel *channel = efx_rx_queue_channel(rx_queue);
 	struct efx_nic *efx = rx_queue->efx;
 	unsigned expected, dropped;
 
+	if (rx_queue->scatter_n &&
+	    index == ((rx_queue->removed_count + rx_queue->scatter_n - 1) &
+		      rx_queue->ptr_mask)) {
+		++channel->n_rx_nodesc_trunc;
+		return true;
+	}
+
 	expected = rx_queue->removed_count & rx_queue->ptr_mask;
 	dropped = (index - expected) & rx_queue->ptr_mask;
 	netif_info(efx, rx_err, efx->net_dev,
@@ -984,6 +1004,7 @@ efx_handle_rx_bad_index(struct efx_rx_queue *rx_queue, unsigned index)
 
 	efx_schedule_reset(efx, EFX_WORKAROUND_5676(efx) ?
 			   RESET_TYPE_RX_RECOVERY : RESET_TYPE_DISABLE);
+	return false;
 }
 
 /* Handle a packet received event
@@ -999,7 +1020,7 @@ efx_handle_rx_event(struct efx_channel *channel, const efx_qword_t *event)
 	unsigned int rx_ev_desc_ptr, rx_ev_byte_cnt;
 	unsigned int rx_ev_hdr_type, rx_ev_mcast_pkt;
 	unsigned expected_ptr;
-	bool rx_ev_pkt_ok;
+	bool rx_ev_pkt_ok, rx_ev_sop, rx_ev_cont;
 	u16 flags;
 	struct efx_rx_queue *rx_queue;
 	struct efx_nic *efx = channel->efx;
@@ -1007,21 +1028,56 @@ efx_handle_rx_event(struct efx_channel *channel, const efx_qword_t *event)
 	if (unlikely(ACCESS_ONCE(efx->reset_pending)))
 		return;
 
-	/* Basic packet information */
-	rx_ev_byte_cnt = EFX_QWORD_FIELD(*event, FSF_AZ_RX_EV_BYTE_CNT);
-	rx_ev_pkt_ok = EFX_QWORD_FIELD(*event, FSF_AZ_RX_EV_PKT_OK);
-	rx_ev_hdr_type = EFX_QWORD_FIELD(*event, FSF_AZ_RX_EV_HDR_TYPE);
-	WARN_ON(EFX_QWORD_FIELD(*event, FSF_AZ_RX_EV_JUMBO_CONT));
-	WARN_ON(EFX_QWORD_FIELD(*event, FSF_AZ_RX_EV_SOP) != 1);
+	rx_ev_cont = EFX_QWORD_FIELD(*event, FSF_AZ_RX_EV_JUMBO_CONT);
+	rx_ev_sop = EFX_QWORD_FIELD(*event, FSF_AZ_RX_EV_SOP);
 	WARN_ON(EFX_QWORD_FIELD(*event, FSF_AZ_RX_EV_Q_LABEL) !=
 		channel->channel);
 
 	rx_queue = efx_channel_get_rx_queue(channel);
 
 	rx_ev_desc_ptr = EFX_QWORD_FIELD(*event, FSF_AZ_RX_EV_DESC_PTR);
-	expected_ptr = rx_queue->removed_count & rx_queue->ptr_mask;
-	if (unlikely(rx_ev_desc_ptr != expected_ptr))
-		efx_handle_rx_bad_index(rx_queue, rx_ev_desc_ptr);
+	expected_ptr = ((rx_queue->removed_count + rx_queue->scatter_n) &
+			rx_queue->ptr_mask);
+
+	/* Check for partial drops and other errors */
+	if (unlikely(rx_ev_desc_ptr != expected_ptr) ||
+	    unlikely(rx_ev_sop != (rx_queue->scatter_n == 0))) {
+		if (rx_ev_desc_ptr != expected_ptr &&
+		    !efx_handle_rx_bad_index(rx_queue, rx_ev_desc_ptr))
+			return;
+
+		/* Discard all pending fragments */
+		if (rx_queue->scatter_n) {
+			efx_rx_packet(
+				rx_queue,
+				rx_queue->removed_count & rx_queue->ptr_mask,
+				rx_queue->scatter_n, 0, EFX_RX_PKT_DISCARD);
+			rx_queue->removed_count += rx_queue->scatter_n;
+			rx_queue->scatter_n = 0;
+		}
+
+		/* Return if there is no new fragment */
+		if (rx_ev_desc_ptr != expected_ptr)
+			return;
+
+		/* Discard new fragment if not SOP */
+		if (!rx_ev_sop) {
+			efx_rx_packet(
+				rx_queue,
+				rx_queue->removed_count & rx_queue->ptr_mask,
+				1, 0, EFX_RX_PKT_DISCARD);
+			++rx_queue->removed_count;
+			return;
+		}
+	}
+
+	++rx_queue->scatter_n;
+	if (rx_ev_cont)
+		return;
+
+	rx_ev_byte_cnt = EFX_QWORD_FIELD(*event, FSF_AZ_RX_EV_BYTE_CNT);
+	rx_ev_pkt_ok = EFX_QWORD_FIELD(*event, FSF_AZ_RX_EV_PKT_OK);
+	rx_ev_hdr_type = EFX_QWORD_FIELD(*event, FSF_AZ_RX_EV_HDR_TYPE);
 
 	if (likely(rx_ev_pkt_ok)) {
 		/* If packet is marked as OK and packet type is TCP/IP or
@@ -1049,7 +1105,11 @@ efx_handle_rx_event(struct efx_channel *channel, const efx_qword_t *event)
 	channel->irq_mod_score += 2;
 
 	/* Handle received packet */
-	efx_rx_packet(rx_queue, rx_ev_desc_ptr, rx_ev_byte_cnt, flags);
+	efx_rx_packet(rx_queue,
+		      rx_queue->removed_count & rx_queue->ptr_mask,
+		      rx_queue->scatter_n, rx_ev_byte_cnt, flags);
+	rx_queue->removed_count += rx_queue->scatter_n;
+	rx_queue->scatter_n = 0;
 }
 
 /* If this flush done event corresponds to a &struct efx_tx_queue, then
diff --git a/drivers/net/ethernet/sfc/ptp.c b/drivers/net/ethernet/sfc/ptp.c
index 3f93624..07f6baa 100644
--- a/drivers/net/ethernet/sfc/ptp.c
+++ b/drivers/net/ethernet/sfc/ptp.c
@@ -99,6 +99,9 @@
 #define PTP_V2_VERSION_LENGTH	1
 #define PTP_V2_VERSION_OFFSET	29
 
+#define PTP_V2_UUID_LENGTH	8
+#define PTP_V2_UUID_OFFSET	48
+
 /* Although PTP V2 UUIDs are comprised a ClockIdentity (8) and PortNumber (2),
  * the MC only captures the last six bytes of the clock identity. These values
  * reflect those, not the ones used in the standard.  The standard permits
@@ -429,13 +432,10 @@ static int efx_ptp_process_times(struct efx_nic *efx, u8 *synch_buf,
 	unsigned number_readings = (response_length /
 			       MC_CMD_PTP_OUT_SYNCHRONIZE_TIMESET_LEN);
 	unsigned i;
-	unsigned min;
-	unsigned min_set = 0;
 	unsigned total;
 	unsigned ngood = 0;
 	unsigned last_good = 0;
 	struct efx_ptp_data *ptp = efx->ptp_data;
-	bool min_valid = false;
 	u32 last_sec;
 	u32 start_sec;
 	struct timespec delta;
@@ -443,35 +443,17 @@ static int efx_ptp_process_times(struct efx_nic *efx, u8 *synch_buf,
 	if (number_readings == 0)
 		return -EAGAIN;
 
-	/* Find minimum value in this set of results, discarding clearly
-	 * erroneous results.
+	/* Read the set of results and increment stats for any results that
+	 * appera to be erroneous.
 	 */
 	for (i = 0; i < number_readings; i++) {
 		efx_ptp_read_timeset(synch_buf, &ptp->timeset[i]);
 		synch_buf += MC_CMD_PTP_OUT_SYNCHRONIZE_TIMESET_LEN;
-		if (ptp->timeset[i].window > SYNCHRONISATION_GRANULARITY_NS) {
-			if (min_valid) {
-				if (ptp->timeset[i].window < min_set)
-					min_set = ptp->timeset[i].window;
-			} else {
-				min_valid = true;
-				min_set = ptp->timeset[i].window;
-			}
-		}
-	}
-
-	if (min_valid) {
-		if (ptp->base_sync_valid && (min_set > ptp->base_sync_ns))
-			min = ptp->base_sync_ns;
-		else
-			min = min_set;
-	} else {
-		min = SYNCHRONISATION_GRANULARITY_NS;
 	}
 
-	/* Discard excessively long synchronise durations.  The MC times
-	 * when it finishes reading the host time so the corrected window
-	 * time should be fairly constant for a given platform.
+	/* Find the last good host-MC synchronization result. The MC times
+	 * when it finishes reading the host time so the corrected window time
+	 * should be fairly constant for a given platform.
 	 */
 	total = 0;
 	for (i = 0; i < number_readings; i++)
@@ -489,8 +471,8 @@ static int efx_ptp_process_times(struct efx_nic *efx, u8 *synch_buf,
 
 	if (ngood == 0) {
 		netif_warn(efx, drv, efx->net_dev,
-			   "PTP no suitable synchronisations %dns %dns\n",
-			   ptp->base_sync_ns, min_set);
+			   "PTP no suitable synchronisations %dns\n",
+			   ptp->base_sync_ns);
 		return -EAGAIN;
 	}
 
@@ -1006,43 +988,53 @@ bool efx_ptp_is_ptp_tx(struct efx_nic *efx, struct sk_buff *skb)
  * the receive timestamp from the MC - this will probably occur after the
  * packet arrival because of the processing in the MC.
  */
-static void efx_ptp_rx(struct efx_channel *channel, struct sk_buff *skb)
+static bool efx_ptp_rx(struct efx_channel *channel, struct sk_buff *skb)
 {
 	struct efx_nic *efx = channel->efx;
 	struct efx_ptp_data *ptp = efx->ptp_data;
 	struct efx_ptp_match *match = (struct efx_ptp_match *)skb->cb;
-	u8 *data;
+	u8 *match_data_012, *match_data_345;
 	unsigned int version;
 
 	match->expiry = jiffies + msecs_to_jiffies(PKT_EVENT_LIFETIME_MS);
 
 	/* Correct version? */
 	if (ptp->mode == MC_CMD_PTP_MODE_V1) {
-		if (skb->len < PTP_V1_MIN_LENGTH) {
-			netif_receive_skb(skb);
-			return;
+		if (!pskb_may_pull(skb, PTP_V1_MIN_LENGTH)) {
+			return false;
 		}
 		version = ntohs(*(__be16 *)&skb->data[PTP_V1_VERSION_OFFSET]);
 		if (version != PTP_VERSION_V1) {
-			netif_receive_skb(skb);
-			return;
+			return false;
 		}
+
+		/* PTP V1 uses all six bytes of the UUID to match the packet
+		 * to the timestamp
+		 */
+		match_data_012 = skb->data + PTP_V1_UUID_OFFSET;
+		match_data_345 = skb->data + PTP_V1_UUID_OFFSET + 3;
 	} else {
-		if (skb->len < PTP_V2_MIN_LENGTH) {
-			netif_receive_skb(skb);
-			return;
+		if (!pskb_may_pull(skb, PTP_V2_MIN_LENGTH)) {
+			return false;
 		}
 		version = skb->data[PTP_V2_VERSION_OFFSET];
-
-		BUG_ON(ptp->mode != MC_CMD_PTP_MODE_V2);
-		BUILD_BUG_ON(PTP_V1_UUID_OFFSET != PTP_V2_MC_UUID_OFFSET);
-		BUILD_BUG_ON(PTP_V1_UUID_LENGTH != PTP_V2_MC_UUID_LENGTH);
-		BUILD_BUG_ON(PTP_V1_SEQUENCE_OFFSET != PTP_V2_SEQUENCE_OFFSET);
-		BUILD_BUG_ON(PTP_V1_SEQUENCE_LENGTH != PTP_V2_SEQUENCE_LENGTH);
-
 		if ((version & PTP_VERSION_V2_MASK) != PTP_VERSION_V2) {
-			netif_receive_skb(skb);
-			return;
+			return false;
+		}
+
+		/* The original V2 implementation uses bytes 2-7 of
+		 * the UUID to match the packet to the timestamp. This
+		 * discards two of the bytes of the MAC address used
+		 * to create the UUID (SF bug 33070).  The PTP V2
+		 * enhanced mode fixes this issue and uses bytes 0-2
+		 * and byte 5-7 of the UUID.
+		 */
+		match_data_345 = skb->data + PTP_V2_UUID_OFFSET + 5;
+		if (ptp->mode == MC_CMD_PTP_MODE_V2) {
+			match_data_012 = skb->data + PTP_V2_UUID_OFFSET + 2;
+		} else {
+			match_data_012 = skb->data + PTP_V2_UUID_OFFSET + 0;
+			BUG_ON(ptp->mode != MC_CMD_PTP_MODE_V2_ENHANCED);
 		}
 	}
 
@@ -1056,14 +1048,19 @@ static void efx_ptp_rx(struct efx_channel *channel, struct sk_buff *skb)
 		timestamps = skb_hwtstamps(skb);
 		memset(timestamps, 0, sizeof(*timestamps));
 
+		/* We expect the sequence number to be in the same position in
+		 * the packet for PTP V1 and V2
+		 */
+		BUILD_BUG_ON(PTP_V1_SEQUENCE_OFFSET != PTP_V2_SEQUENCE_OFFSET);
+		BUILD_BUG_ON(PTP_V1_SEQUENCE_LENGTH != PTP_V2_SEQUENCE_LENGTH);
+
 		/* Extract UUID/Sequence information */
-		data = skb->data + PTP_V1_UUID_OFFSET;
-		match->words[0] = (data[0]         |
-				   (data[1] << 8)  |
-				   (data[2] << 16) |
-				   (data[3] << 24));
-		match->words[1] = (data[4]         |
-				   (data[5] << 8)  |
+		match->words[0] = (match_data_012[0]         |
+				   (match_data_012[1] << 8)  |
+				   (match_data_012[2] << 16) |
+				   (match_data_345[0] << 24));
+		match->words[1] = (match_data_345[1]         |
+				   (match_data_345[2] << 8)  |
 				   (skb->data[PTP_V1_SEQUENCE_OFFSET +
 					      PTP_V1_SEQUENCE_LENGTH - 1] <<
 				    16));
@@ -1073,6 +1070,8 @@ static void efx_ptp_rx(struct efx_channel *channel, struct sk_buff *skb)
 
 	skb_queue_tail(&ptp->rxq, skb);
 	queue_work(ptp->workwq, &ptp->work);
+
+	return true;
 }
 
 /* Transmit a PTP packet.  This has to be transmitted by the MC
@@ -1167,7 +1166,7 @@ static int efx_ptp_ts_init(struct efx_nic *efx, struct hwtstamp_config *init)
 	 * timestamped
 	 */
 		init->rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_EVENT;
-		new_mode = MC_CMD_PTP_MODE_V2;
+		new_mode = MC_CMD_PTP_MODE_V2_ENHANCED;
 		enable_wanted = true;
 		break;
 	case HWTSTAMP_FILTER_PTP_V2_EVENT:
@@ -1186,7 +1185,14 @@ static int efx_ptp_ts_init(struct efx_nic *efx, struct hwtstamp_config *init)
 	if (init->tx_type != HWTSTAMP_TX_OFF)
 		enable_wanted = true;
 
+	/* Old versions of the firmware do not support the improved
+	 * UUID filtering option (SF bug 33070).  If the firmware does
+	 * not accept the enhanced mode, fall back to the standard PTP
+	 * v2 UUID filtering.
+	 */
 	rc = efx_ptp_change_mode(efx, enable_wanted, new_mode);
+	if ((rc != 0) && (new_mode == MC_CMD_PTP_MODE_V2_ENHANCED))
+		rc = efx_ptp_change_mode(efx, enable_wanted, MC_CMD_PTP_MODE_V2);
 	if (rc != 0)
 		return rc;
 
diff --git a/drivers/net/ethernet/sfc/rx.c b/drivers/net/ethernet/sfc/rx.c
index bb579a6..e73e30b 100644
--- a/drivers/net/ethernet/sfc/rx.c
+++ b/drivers/net/ethernet/sfc/rx.c
@@ -16,6 +16,7 @@
 #include <linux/udp.h>
 #include <linux/prefetch.h>
 #include <linux/moduleparam.h>
+#include <linux/iommu.h>
 #include <net/ip.h>
 #include <net/checksum.h>
 #include "net_driver.h"
@@ -24,85 +25,39 @@
 #include "selftest.h"
 #include "workarounds.h"
 
-/* Number of RX descriptors pushed at once. */
-#define EFX_RX_BATCH  8
+/* Preferred number of descriptors to fill at once */
+#define EFX_RX_PREFERRED_BATCH 8U
 
-/* Maximum size of a buffer sharing a page */
-#define EFX_RX_HALF_PAGE ((PAGE_SIZE >> 1) - sizeof(struct efx_rx_page_state))
+/* Number of RX buffers to recycle pages for.  When creating the RX page recycle
+ * ring, this number is divided by the number of buffers per page to calculate
+ * the number of pages to store in the RX page recycle ring.
+ */
+#define EFX_RECYCLE_RING_SIZE_IOMMU 4096
+#define EFX_RECYCLE_RING_SIZE_NOIOMMU (2 * EFX_RX_PREFERRED_BATCH)
 
 /* Size of buffer allocated for skb header area. */
 #define EFX_SKB_HEADERS  64u
 
-/*
- * rx_alloc_method - RX buffer allocation method
- *
- * This driver supports two methods for allocating and using RX buffers:
- * each RX buffer may be backed by an skb or by an order-n page.
- *
- * When GRO is in use then the second method has a lower overhead,
- * since we don't have to allocate then free skbs on reassembled frames.
- *
- * Values:
- *   - RX_ALLOC_METHOD_AUTO = 0
- *   - RX_ALLOC_METHOD_SKB  = 1
- *   - RX_ALLOC_METHOD_PAGE = 2
- *
- * The heuristic for %RX_ALLOC_METHOD_AUTO is a simple hysteresis count
- * controlled by the parameters below.
- *
- *   - Since pushing and popping descriptors are separated by the rx_queue
- *     size, so the watermarks should be ~rxd_size.
- *   - The performance win by using page-based allocation for GRO is less
- *     than the performance hit of using page-based allocation of non-GRO,
- *     so the watermarks should reflect this.
- *
- * Per channel we maintain a single variable, updated by each channel:
- *
- *   rx_alloc_level += (gro_performed ? RX_ALLOC_FACTOR_GRO :
- *                      RX_ALLOC_FACTOR_SKB)
- * Per NAPI poll interval, we constrain rx_alloc_level to 0..MAX (which
- * limits the hysteresis), and update the allocation strategy:
- *
- *   rx_alloc_method = (rx_alloc_level > RX_ALLOC_LEVEL_GRO ?
- *                      RX_ALLOC_METHOD_PAGE : RX_ALLOC_METHOD_SKB)
- */
-static int rx_alloc_method = RX_ALLOC_METHOD_AUTO;
-
-#define RX_ALLOC_LEVEL_GRO 0x2000
-#define RX_ALLOC_LEVEL_MAX 0x3000
-#define RX_ALLOC_FACTOR_GRO 1
-#define RX_ALLOC_FACTOR_SKB (-2)
-
 /* This is the percentage fill level below which new RX descriptors
  * will be added to the RX descriptor ring.
  */
 static unsigned int rx_refill_threshold;
 
+/* Each packet can consume up to ceil(max_frame_len / buffer_size) buffers */
+#define EFX_RX_MAX_FRAGS DIV_ROUND_UP(EFX_MAX_FRAME_LEN(EFX_MAX_MTU), \
+				      EFX_RX_USR_BUF_SIZE)
+
 /*
  * RX maximum head room required.
  *
- * This must be at least 1 to prevent overflow and at least 2 to allow
- * pipelined receives.
+ * This must be at least 1 to prevent overflow, plus one packet-worth
+ * to allow pipelined receives.
  */
-#define EFX_RXD_HEAD_ROOM 2
+#define EFX_RXD_HEAD_ROOM (1 + EFX_RX_MAX_FRAGS)
 
-/* Offset of ethernet header within page */
-static inline unsigned int efx_rx_buf_offset(struct efx_nic *efx,
-					     struct efx_rx_buffer *buf)
+static inline u8 *efx_rx_buf_va(struct efx_rx_buffer *buf)
 {
-	return buf->page_offset + efx->type->rx_buffer_hash_size;
-}
-static inline unsigned int efx_rx_buf_size(struct efx_nic *efx)
-{
-	return PAGE_SIZE << efx->rx_buffer_order;
-}
-
-static u8 *efx_rx_buf_eh(struct efx_nic *efx, struct efx_rx_buffer *buf)
-{
-	if (buf->flags & EFX_RX_BUF_PAGE)
-		return page_address(buf->u.page) + efx_rx_buf_offset(efx, buf);
-	else
-		return (u8 *)buf->u.skb->data + efx->type->rx_buffer_hash_size;
+	return page_address(buf->page) + buf->page_offset;
 }
 
 static inline u32 efx_rx_buf_hash(const u8 *eh)
@@ -119,66 +74,81 @@ static inline u32 efx_rx_buf_hash(const u8 *eh)
 #endif
 }
 
-/**
- * efx_init_rx_buffers_skb - create EFX_RX_BATCH skb-based RX buffers
- *
- * @rx_queue:		Efx RX queue
- *
- * This allocates EFX_RX_BATCH skbs, maps them for DMA, and populates a
- * struct efx_rx_buffer for each one. Return a negative error code or 0
- * on success. May fail having only inserted fewer than EFX_RX_BATCH
- * buffers.
- */
-static int efx_init_rx_buffers_skb(struct efx_rx_queue *rx_queue)
+static inline struct efx_rx_buffer *
+efx_rx_buf_next(struct efx_rx_queue *rx_queue, struct efx_rx_buffer *rx_buf)
+{
+	if (unlikely(rx_buf == efx_rx_buffer(rx_queue, rx_queue->ptr_mask)))
+		return efx_rx_buffer(rx_queue, 0);
+	else
+		return rx_buf + 1;
+}
+
+static inline void efx_sync_rx_buffer(struct efx_nic *efx,
+				      struct efx_rx_buffer *rx_buf,
+				      unsigned int len)
+{
+	dma_sync_single_for_cpu(&efx->pci_dev->dev, rx_buf->dma_addr, len,
+				DMA_FROM_DEVICE);
+}
+
+void efx_rx_config_page_split(struct efx_nic *efx)
+{
+	efx->rx_page_buf_step = ALIGN(efx->rx_dma_len + EFX_PAGE_IP_ALIGN,
+				      L1_CACHE_BYTES);
+	efx->rx_bufs_per_page = efx->rx_buffer_order ? 1 :
+		((PAGE_SIZE - sizeof(struct efx_rx_page_state)) /
+		 efx->rx_page_buf_step);
+	efx->rx_buffer_truesize = (PAGE_SIZE << efx->rx_buffer_order) /
+		efx->rx_bufs_per_page;
+	efx->rx_pages_per_batch = DIV_ROUND_UP(EFX_RX_PREFERRED_BATCH,
+					       efx->rx_bufs_per_page);
+}
+
+/* Check the RX page recycle ring for a page that can be reused. */
+static struct page *efx_reuse_page(struct efx_rx_queue *rx_queue)
 {
 	struct efx_nic *efx = rx_queue->efx;
-	struct net_device *net_dev = efx->net_dev;
-	struct efx_rx_buffer *rx_buf;
-	struct sk_buff *skb;
-	int skb_len = efx->rx_buffer_len;
-	unsigned index, count;
+	struct page *page;
+	struct efx_rx_page_state *state;
+	unsigned index;
 
-	for (count = 0; count < EFX_RX_BATCH; ++count) {
-		index = rx_queue->added_count & rx_queue->ptr_mask;
-		rx_buf = efx_rx_buffer(rx_queue, index);
-
-		rx_buf->u.skb = skb = netdev_alloc_skb(net_dev, skb_len);
-		if (unlikely(!skb))
-			return -ENOMEM;
-
-		/* Adjust the SKB for padding */
-		skb_reserve(skb, NET_IP_ALIGN);
-		rx_buf->len = skb_len - NET_IP_ALIGN;
-		rx_buf->flags = 0;
-
-		rx_buf->dma_addr = dma_map_single(&efx->pci_dev->dev,
-						  skb->data, rx_buf->len,
-						  DMA_FROM_DEVICE);
-		if (unlikely(dma_mapping_error(&efx->pci_dev->dev,
-					       rx_buf->dma_addr))) {
-			dev_kfree_skb_any(skb);
-			rx_buf->u.skb = NULL;
-			return -EIO;
-		}
+	index = rx_queue->page_remove & rx_queue->page_ptr_mask;
+	page = rx_queue->page_ring[index];
+	if (page == NULL)
+		return NULL;
+
+	rx_queue->page_ring[index] = NULL;
+	/* page_remove cannot exceed page_add. */
+	if (rx_queue->page_remove != rx_queue->page_add)
+		++rx_queue->page_remove;
 
-		++rx_queue->added_count;
-		++rx_queue->alloc_skb_count;
+	/* If page_count is 1 then we hold the only reference to this page. */
+	if (page_count(page) == 1) {
+		++rx_queue->page_recycle_count;
+		return page;
+	} else {
+		state = page_address(page);
+		dma_unmap_page(&efx->pci_dev->dev, state->dma_addr,
+			       PAGE_SIZE << efx->rx_buffer_order,
+			       DMA_FROM_DEVICE);
+		put_page(page);
+		++rx_queue->page_recycle_failed;
 	}
 
-	return 0;
+	return NULL;
 }
 
 /**
- * efx_init_rx_buffers_page - create EFX_RX_BATCH page-based RX buffers
+ * efx_init_rx_buffers - create EFX_RX_BATCH page-based RX buffers
  *
  * @rx_queue:		Efx RX queue
  *
- * This allocates memory for EFX_RX_BATCH receive buffers, maps them for DMA,
- * and populates struct efx_rx_buffers for each one. Return a negative error
- * code or 0 on success. If a single page can be split between two buffers,
- * then the page will either be inserted fully, or not at at all.
+ * This allocates a batch of pages, maps them for DMA, and populates
+ * struct efx_rx_buffers for each one. Return a negative error code or
+ * 0 on success. If a single page can be used for multiple buffers,
+ * then the page will either be inserted fully, or not at all.
  */
-static int efx_init_rx_buffers_page(struct efx_rx_queue *rx_queue)
+static int efx_init_rx_buffers(struct efx_rx_queue *rx_queue)
 {
 	struct efx_nic *efx = rx_queue->efx;
 	struct efx_rx_buffer *rx_buf;
@@ -188,150 +158,140 @@ static int efx_init_rx_buffers_page(struct efx_rx_queue *rx_queue)
 	dma_addr_t dma_addr;
 	unsigned index, count;
 
-	/* We can split a page between two buffers */
-	BUILD_BUG_ON(EFX_RX_BATCH & 1);
-
-	for (count = 0; count < EFX_RX_BATCH; ++count) {
-		page = alloc_pages(__GFP_COLD | __GFP_COMP | GFP_ATOMIC,
-				   efx->rx_buffer_order);
-		if (unlikely(page == NULL))
-			return -ENOMEM;
-		dma_addr = dma_map_page(&efx->pci_dev->dev, page, 0,
-					efx_rx_buf_size(efx),
-					DMA_FROM_DEVICE);
-		if (unlikely(dma_mapping_error(&efx->pci_dev->dev, dma_addr))) {
-			__free_pages(page, efx->rx_buffer_order);
-			return -EIO;
+	count = 0;
+	do {
+		page = efx_reuse_page(rx_queue);
+		if (page == NULL) {
+			page = alloc_pages(__GFP_COLD | __GFP_COMP | GFP_ATOMIC,
+					   efx->rx_buffer_order);
+			if (unlikely(page == NULL))
+				return -ENOMEM;
+			dma_addr =
+				dma_map_page(&efx->pci_dev->dev, page, 0,
+					     PAGE_SIZE << efx->rx_buffer_order,
+					     DMA_FROM_DEVICE);
+			if (unlikely(dma_mapping_error(&efx->pci_dev->dev,
+						       dma_addr))) {
+				__free_pages(page, efx->rx_buffer_order);
+				return -EIO;
+			}
+			state = page_address(page);
+			state->dma_addr = dma_addr;
+		} else {
+			state = page_address(page);
+			dma_addr = state->dma_addr;
 		}
-		state = page_address(page);
-		state->refcnt = 0;
-		state->dma_addr = dma_addr;
 
 		dma_addr += sizeof(struct efx_rx_page_state);
 		page_offset = sizeof(struct efx_rx_page_state);
 
-	split:
-		index = rx_queue->added_count & rx_queue->ptr_mask;
-		rx_buf = efx_rx_buffer(rx_queue, index);
-		rx_buf->dma_addr = dma_addr + EFX_PAGE_IP_ALIGN;
-		rx_buf->u.page = page;
-		rx_buf->page_offset = page_offset + EFX_PAGE_IP_ALIGN;
-		rx_buf->len = efx->rx_buffer_len - EFX_PAGE_IP_ALIGN;
-		rx_buf->flags = EFX_RX_BUF_PAGE;
-		++rx_queue->added_count;
-		++rx_queue->alloc_page_count;
-		++state->refcnt;
-
-		if ((~count & 1) && (efx->rx_buffer_len <= EFX_RX_HALF_PAGE)) {
-			/* Use the second half of the page */
+		do {
+			index = rx_queue->added_count & rx_queue->ptr_mask;
+			rx_buf = efx_rx_buffer(rx_queue, index);
+			rx_buf->dma_addr = dma_addr + EFX_PAGE_IP_ALIGN;
+			rx_buf->page = page;
+			rx_buf->page_offset = page_offset + EFX_PAGE_IP_ALIGN;
+			rx_buf->len = efx->rx_dma_len;
+			rx_buf->flags = 0;
+			++rx_queue->added_count;
 			get_page(page);
-			dma_addr += (PAGE_SIZE >> 1);
-			page_offset += (PAGE_SIZE >> 1);
-			++count;
-			goto split;
-		}
-	}
+			dma_addr += efx->rx_page_buf_step;
+			page_offset += efx->rx_page_buf_step;
+		} while (page_offset + efx->rx_page_buf_step <= PAGE_SIZE);
+
+		rx_buf->flags = EFX_RX_BUF_LAST_IN_PAGE;
+	} while (++count < efx->rx_pages_per_batch);
 
 	return 0;
 }
 
+/* Unmap a DMA-mapped page.  This function is only called for the final RX
+ * buffer in a page.
+ */
 static void efx_unmap_rx_buffer(struct efx_nic *efx,
-				struct efx_rx_buffer *rx_buf,
-				unsigned int used_len)
+				struct efx_rx_buffer *rx_buf)
 {
-	if ((rx_buf->flags & EFX_RX_BUF_PAGE) && rx_buf->u.page) {
-		struct efx_rx_page_state *state;
-
-		state = page_address(rx_buf->u.page);
-		if (--state->refcnt == 0) {
-			dma_unmap_page(&efx->pci_dev->dev,
-				       state->dma_addr,
-				       efx_rx_buf_size(efx),
-				       DMA_FROM_DEVICE);
-		} else if (used_len) {
-			dma_sync_single_for_cpu(&efx->pci_dev->dev,
-						rx_buf->dma_addr, used_len,
-						DMA_FROM_DEVICE);
-		}
-	} else if (!(rx_buf->flags & EFX_RX_BUF_PAGE) && rx_buf->u.skb) {
-		dma_unmap_single(&efx->pci_dev->dev, rx_buf->dma_addr,
-				 rx_buf->len, DMA_FROM_DEVICE);
+	struct page *page = rx_buf->page;
+
+	if (page) {
+		struct efx_rx_page_state *state = page_address(page);
+		dma_unmap_page(&efx->pci_dev->dev,
+			       state->dma_addr,
+			       PAGE_SIZE << efx->rx_buffer_order,
+			       DMA_FROM_DEVICE);
 	}
 }
 
-static void efx_free_rx_buffer(struct efx_nic *efx,
-			       struct efx_rx_buffer *rx_buf)
+static void efx_free_rx_buffer(struct efx_rx_buffer *rx_buf)
 {
-	if ((rx_buf->flags & EFX_RX_BUF_PAGE) && rx_buf->u.page) {
-		__free_pages(rx_buf->u.page, efx->rx_buffer_order);
-		rx_buf->u.page = NULL;
-	} else if (!(rx_buf->flags & EFX_RX_BUF_PAGE) && rx_buf->u.skb) {
-		dev_kfree_skb_any(rx_buf->u.skb);
-		rx_buf->u.skb = NULL;
+	if (rx_buf->page) {
+		put_page(rx_buf->page);
+		rx_buf->page = NULL;
 	}
 }
 
-static void efx_fini_rx_buffer(struct efx_rx_queue *rx_queue,
-			       struct efx_rx_buffer *rx_buf)
+/* Attempt to recycle the page if there is an RX recycle ring; the page can
+ * only be added if this is the final RX buffer, to prevent pages being used in
+ * the descriptor ring and appearing in the recycle ring simultaneously.
+ */
+static void efx_recycle_rx_page(struct efx_channel *channel,
+				struct efx_rx_buffer *rx_buf)
 {
-	efx_unmap_rx_buffer(rx_queue->efx, rx_buf, 0);
-	efx_free_rx_buffer(rx_queue->efx, rx_buf);
-}
+	struct page *page = rx_buf->page;
+	struct efx_rx_queue *rx_queue = efx_channel_get_rx_queue(channel);
+	struct efx_nic *efx = rx_queue->efx;
+	unsigned index;
 
-/* Attempt to resurrect the other receive buffer that used to share this page,
- * which had previously been passed up to the kernel and freed. */
-static void efx_resurrect_rx_buffer(struct efx_rx_queue *rx_queue,
-				    struct efx_rx_buffer *rx_buf)
-{
-	struct efx_rx_page_state *state = page_address(rx_buf->u.page);
-	struct efx_rx_buffer *new_buf;
-	unsigned fill_level, index;
-
-	/* +1 because efx_rx_packet() incremented removed_count. +1 because
-	 * we'd like to insert an additional descriptor whilst leaving
-	 * EFX_RXD_HEAD_ROOM for the non-recycle path */
-	fill_level = (rx_queue->added_count - rx_queue->removed_count + 2);
-	if (unlikely(fill_level > rx_queue->max_fill)) {
-		/* We could place "state" on a list, and drain the list in
-		 * efx_fast_push_rx_descriptors(). For now, this will do. */
+	/* Only recycle the page after processing the final buffer. */
+	if (!(rx_buf->flags & EFX_RX_BUF_LAST_IN_PAGE))
 		return;
-	}
 
-	++state->refcnt;
-	get_page(rx_buf->u.page);
+	index = rx_queue->page_add & rx_queue->page_ptr_mask;
+	if (rx_queue->page_ring[index] == NULL) {
+		unsigned read_index = rx_queue->page_remove &
+			rx_queue->page_ptr_mask;
 
-	index = rx_queue->added_count & rx_queue->ptr_mask;
-	new_buf = efx_rx_buffer(rx_queue, index);
-	new_buf->dma_addr = rx_buf->dma_addr ^ (PAGE_SIZE >> 1);
-	new_buf->u.page = rx_buf->u.page;
-	new_buf->len = rx_buf->len;
-	new_buf->flags = EFX_RX_BUF_PAGE;
-	++rx_queue->added_count;
+		/* The next slot in the recycle ring is available, but
+		 * increment page_remove if the read pointer currently
+		 * points here.
+		 */
+		if (read_index == index)
+			++rx_queue->page_remove;
+		rx_queue->page_ring[index] = page;
+		++rx_queue->page_add;
+		return;
+	}
+	++rx_queue->page_recycle_full;
+	efx_unmap_rx_buffer(efx, rx_buf);
+	put_page(rx_buf->page);
 }
 
-/* Recycle the given rx buffer directly back into the rx_queue. There is
- * always room to add this buffer, because we've just popped a buffer. */
-static void efx_recycle_rx_buffer(struct efx_channel *channel,
-				  struct efx_rx_buffer *rx_buf)
+static void efx_fini_rx_buffer(struct efx_rx_queue *rx_queue,
+			       struct efx_rx_buffer *rx_buf)
 {
-	struct efx_nic *efx = channel->efx;
-	struct efx_rx_queue *rx_queue = efx_channel_get_rx_queue(channel);
-	struct efx_rx_buffer *new_buf;
-	unsigned index;
-
-	rx_buf->flags &= EFX_RX_BUF_PAGE;
-
-	if ((rx_buf->flags & EFX_RX_BUF_PAGE) &&
-	    efx->rx_buffer_len <= EFX_RX_HALF_PAGE &&
-	    page_count(rx_buf->u.page) == 1)
-		efx_resurrect_rx_buffer(rx_queue, rx_buf);
+	/* Release the page reference we hold for the buffer. */
+	if (rx_buf->page)
+		put_page(rx_buf->page);
+
+	/* If this is the last buffer in a page, unmap and free it. */
+	if (rx_buf->flags & EFX_RX_BUF_LAST_IN_PAGE) {
+		efx_unmap_rx_buffer(rx_queue->efx, rx_buf);
+		efx_free_rx_buffer(rx_buf);
+	}
+	rx_buf->page = NULL;
+}
 
-	index = rx_queue->added_count & rx_queue->ptr_mask;
-	new_buf = efx_rx_buffer(rx_queue, index);
+/* Recycle the pages that are used by buffers that have just been received. */
+static void efx_recycle_rx_buffers(struct efx_channel *channel,
+				   struct efx_rx_buffer *rx_buf,
+				   unsigned int n_frags)
+{
+	struct efx_rx_queue *rx_queue = efx_channel_get_rx_queue(channel);
 
-	memcpy(new_buf, rx_buf, sizeof(*new_buf));
-	rx_buf->u.page = NULL;
-	++rx_queue->added_count;
+	do {
+		efx_recycle_rx_page(channel, rx_buf);
+		rx_buf = efx_rx_buf_next(rx_queue, rx_buf);
+	} while (--n_frags);
 }
 
 /**
@@ -348,8 +308,8 @@ static void efx_recycle_rx_buffer(struct efx_channel *channel,
  */
 void efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue)
 {
-	struct efx_channel *channel = efx_rx_queue_channel(rx_queue);
-	unsigned fill_level;
+	struct efx_nic *efx = rx_queue->efx;
+	unsigned int fill_level, batch_size;
 	int space, rc = 0;
 
 	/* Calculate current fill level, and exit if we don't need to fill */
@@ -364,28 +324,26 @@ void efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue)
 			rx_queue->min_fill = fill_level;
 	}
 
+	batch_size = efx->rx_pages_per_batch * efx->rx_bufs_per_page;
 	space = rx_queue->max_fill - fill_level;
-	EFX_BUG_ON_PARANOID(space < EFX_RX_BATCH);
+	EFX_BUG_ON_PARANOID(space < batch_size);
 
 	netif_vdbg(rx_queue->efx, rx_status, rx_queue->efx->net_dev,
 		   "RX queue %d fast-filling descriptor ring from"
-		   " level %d to level %d using %s allocation\n",
+		   " level %d to level %d\n",
 		   efx_rx_queue_index(rx_queue), fill_level,
-		   rx_queue->max_fill,
-		   channel->rx_alloc_push_pages ? "page" : "skb");
+		   rx_queue->max_fill);
+
 
 	do {
-		if (channel->rx_alloc_push_pages)
-			rc = efx_init_rx_buffers_page(rx_queue);
-		else
-			rc = efx_init_rx_buffers_skb(rx_queue);
+		rc = efx_init_rx_buffers(rx_queue);
 		if (unlikely(rc)) {
 			/* Ensure that we don't leave the rx queue empty */
 			if (rx_queue->added_count == rx_queue->removed_count)
 				efx_schedule_slow_fill(rx_queue);
 			goto out;
 		}
-	} while ((space -= EFX_RX_BATCH) >= EFX_RX_BATCH);
+	} while ((space -= batch_size) >= batch_size);
 
 	netif_vdbg(rx_queue->efx, rx_status, rx_queue->efx->net_dev,
 		   "RX queue %d fast-filled descriptor ring "
@@ -408,7 +366,7 @@ void efx_rx_slow_fill(unsigned long context)
 
 static void efx_rx_packet__check_len(struct efx_rx_queue *rx_queue,
 				     struct efx_rx_buffer *rx_buf,
-				     int len, bool *leak_packet)
+				     int len)
 {
 	struct efx_nic *efx = rx_queue->efx;
 	unsigned max_len = rx_buf->len - efx->type->rx_buffer_padding;
@@ -428,11 +386,6 @@ static void efx_rx_packet__check_len(struct efx_rx_queue *rx_queue,
 				  "RX event (0x%x > 0x%x+0x%x). Leaking\n",
 				  efx_rx_queue_index(rx_queue), len, max_len,
 				  efx->type->rx_buffer_padding);
-		/* If this buffer was skb-allocated, then the meta
-		 * data at the end of the skb will be trashed. So
-		 * we have no choice but to leak the fragment.
-		 */
-		*leak_packet = !(rx_buf->flags & EFX_RX_BUF_PAGE);
 		efx_schedule_reset(efx, RESET_TYPE_RX_RECOVERY);
 	} else {
 		if (net_ratelimit())
@@ -448,212 +401,238 @@ static void efx_rx_packet__check_len(struct efx_rx_queue *rx_queue,
 /* Pass a received packet up through GRO.  GRO can handle pages
  * regardless of checksum state and skbs with a good checksum.
  */
-static void efx_rx_packet_gro(struct efx_channel *channel,
-			      struct efx_rx_buffer *rx_buf,
-			      const u8 *eh)
+static void
+efx_rx_packet_gro(struct efx_channel *channel, struct efx_rx_buffer *rx_buf,
+		  unsigned int n_frags, u8 *eh)
 {
 	struct napi_struct *napi = &channel->napi_str;
 	gro_result_t gro_result;
+	struct efx_nic *efx = channel->efx;
+	struct sk_buff *skb;
 
-	if (rx_buf->flags & EFX_RX_BUF_PAGE) {
-		struct efx_nic *efx = channel->efx;
-		struct page *page = rx_buf->u.page;
-		struct sk_buff *skb;
+	skb = napi_get_frags(napi);
+	if (unlikely(!skb)) {
+		while (n_frags--) {
+			put_page(rx_buf->page);
+			rx_buf->page = NULL;
+			rx_buf = efx_rx_buf_next(&channel->rx_queue, rx_buf);
+		}
+		return;
+	}
 
-		rx_buf->u.page = NULL;
+	if (efx->net_dev->features & NETIF_F_RXHASH)
+		skb->rxhash = efx_rx_buf_hash(eh);
+	skb->ip_summed = ((rx_buf->flags & EFX_RX_PKT_CSUMMED) ?
+			  CHECKSUM_UNNECESSARY : CHECKSUM_NONE);
+
+	for (;;) {
+		skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags,
+				   rx_buf->page, rx_buf->page_offset,
+				   rx_buf->len);
+		rx_buf->page = NULL;
+		skb->len += rx_buf->len;
+		if (skb_shinfo(skb)->nr_frags == n_frags)
+			break;
+
+		rx_buf = efx_rx_buf_next(&channel->rx_queue, rx_buf);
+	}
 
-		skb = napi_get_frags(napi);
-		if (!skb) {
-			put_page(page);
-			return;
-		}
+	skb->data_len = skb->len;
+	skb->truesize += n_frags * efx->rx_buffer_truesize;
+
+	skb_record_rx_queue(skb, channel->rx_queue.core_index);
+
+	gro_result = napi_gro_frags(napi);
+	if (gro_result != GRO_DROP)
+		channel->irq_mod_score += 2;
+}
 
-		if (efx->net_dev->features & NETIF_F_RXHASH)
-			skb->rxhash = efx_rx_buf_hash(eh);
+/* Allocate and construct an SKB around page fragments */
+static struct sk_buff *efx_rx_mk_skb(struct efx_channel *channel,
+				     struct efx_rx_buffer *rx_buf,
+				     unsigned int n_frags,
+				     u8 *eh, int hdr_len)
+{
+	struct efx_nic *efx = channel->efx;
+	struct sk_buff *skb;
 
-		skb_fill_page_desc(skb, 0, page,
-				   efx_rx_buf_offset(efx, rx_buf), rx_buf->len);
+	/* Allocate an SKB to store the headers */
+	skb = netdev_alloc_skb(efx->net_dev, hdr_len + EFX_PAGE_SKB_ALIGN);
+	if (unlikely(skb == NULL))
+		return NULL;
 
-		skb->len = rx_buf->len;
-		skb->data_len = rx_buf->len;
-		skb->truesize += rx_buf->len;
-		skb->ip_summed = ((rx_buf->flags & EFX_RX_PKT_CSUMMED) ?
-				  CHECKSUM_UNNECESSARY : CHECKSUM_NONE);
+	EFX_BUG_ON_PARANOID(rx_buf->len < hdr_len);
 
-		skb_record_rx_queue(skb, channel->rx_queue.core_index);
+	skb_reserve(skb, EFX_PAGE_SKB_ALIGN);
+	memcpy(__skb_put(skb, hdr_len), eh, hdr_len);
 
-		gro_result = napi_gro_frags(napi);
-	} else {
-		struct sk_buff *skb = rx_buf->u.skb;
+	/* Append the remaining page(s) onto the frag list */
+	if (rx_buf->len > hdr_len) {
+		rx_buf->page_offset += hdr_len;
+		rx_buf->len -= hdr_len;
 
-		EFX_BUG_ON_PARANOID(!(rx_buf->flags & EFX_RX_PKT_CSUMMED));
-		rx_buf->u.skb = NULL;
-		skb->ip_summed = CHECKSUM_UNNECESSARY;
+		for (;;) {
+			skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags,
+					   rx_buf->page, rx_buf->page_offset,
+					   rx_buf->len);
+			rx_buf->page = NULL;
+			skb->len += rx_buf->len;
+			skb->data_len += rx_buf->len;
+			if (skb_shinfo(skb)->nr_frags == n_frags)
+				break;
 
-		gro_result = napi_gro_receive(napi, skb);
+			rx_buf = efx_rx_buf_next(&channel->rx_queue, rx_buf);
+		}
+	} else {
+		__free_pages(rx_buf->page, efx->rx_buffer_order);
+		rx_buf->page = NULL;
+		n_frags = 0;
 	}
 
-	if (gro_result == GRO_NORMAL) {
-		channel->rx_alloc_level += RX_ALLOC_FACTOR_SKB;
-	} else if (gro_result != GRO_DROP) {
-		channel->rx_alloc_level += RX_ALLOC_FACTOR_GRO;
-		channel->irq_mod_score += 2;
-	}
+	skb->truesize += n_frags * efx->rx_buffer_truesize;
+
+	/* Move past the ethernet header */
+	skb->protocol = eth_type_trans(skb, efx->net_dev);
+
+	return skb;
 }
 
 void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index,
-		   unsigned int len, u16 flags)
+		   unsigned int n_frags, unsigned int len, u16 flags)
 {
 	struct efx_nic *efx = rx_queue->efx;
 	struct efx_channel *channel = efx_rx_queue_channel(rx_queue);
 	struct efx_rx_buffer *rx_buf;
-	bool leak_packet = false;
 
 	rx_buf = efx_rx_buffer(rx_queue, index);
 	rx_buf->flags |= flags;
 
-	/* This allows the refill path to post another buffer.
-	 * EFX_RXD_HEAD_ROOM ensures that the slot we are using
-	 * isn't overwritten yet.
-	 */
-	rx_queue->removed_count++;
-
-	/* Validate the length encoded in the event vs the descriptor pushed */
-	efx_rx_packet__check_len(rx_queue, rx_buf, len, &leak_packet);
+	/* Validate the number of fragments and completed length */
+	if (n_frags == 1) {
+		efx_rx_packet__check_len(rx_queue, rx_buf, len);
+	} else if (unlikely(n_frags > EFX_RX_MAX_FRAGS) ||
+		   unlikely(len <= (n_frags - 1) * EFX_RX_USR_BUF_SIZE) ||
+		   unlikely(len > n_frags * EFX_RX_USR_BUF_SIZE) ||
+		   unlikely(!efx->rx_scatter)) {
+		/* If this isn't an explicit discard request, either
+		 * the hardware or the driver is broken.
+		 */
+		WARN_ON(!(len == 0 && rx_buf->flags & EFX_RX_PKT_DISCARD));
+		rx_buf->flags |= EFX_RX_PKT_DISCARD;
+	}
 
 	netif_vdbg(efx, rx_status, efx->net_dev,
-		   "RX queue %d received id %x at %llx+%x %s%s\n",
+		   "RX queue %d received ids %x-%x len %d %s%s\n",
 		   efx_rx_queue_index(rx_queue), index,
-		   (unsigned long long)rx_buf->dma_addr, len,
+		   (index + n_frags - 1) & rx_queue->ptr_mask, len,
 		   (rx_buf->flags & EFX_RX_PKT_CSUMMED) ? " [SUMMED]" : "",
 		   (rx_buf->flags & EFX_RX_PKT_DISCARD) ? " [DISCARD]" : "");
 
-	/* Discard packet, if instructed to do so */
+	/* Discard packet, if instructed to do so.  Process the
+	 * previous receive first.
+	 */
 	if (unlikely(rx_buf->flags & EFX_RX_PKT_DISCARD)) {
-		if (unlikely(leak_packet))
-			channel->n_skbuff_leaks++;
-		else
-			efx_recycle_rx_buffer(channel, rx_buf);
-
-		/* Don't hold off the previous receive */
-		rx_buf = NULL;
-		goto out;
+		efx_rx_flush_packet(channel);
+		put_page(rx_buf->page);
+		efx_recycle_rx_buffers(channel, rx_buf, n_frags);
+		return;
 	}
 
-	/* Release and/or sync DMA mapping - assumes all RX buffers
-	 * consumed in-order per RX queue
+	if (n_frags == 1)
+		rx_buf->len = len;
+
+	/* Release and/or sync the DMA mapping - assumes all RX buffers
+	 * consumed in-order per RX queue.
 	 */
-	efx_unmap_rx_buffer(efx, rx_buf, len);
+	efx_sync_rx_buffer(efx, rx_buf, rx_buf->len);
 
 	/* Prefetch nice and early so data will (hopefully) be in cache by
 	 * the time we look at it.
 	 */
-	prefetch(efx_rx_buf_eh(efx, rx_buf));
+	prefetch(efx_rx_buf_va(rx_buf));
+
+	rx_buf->page_offset += efx->type->rx_buffer_hash_size;
+	rx_buf->len -= efx->type->rx_buffer_hash_size;
+
+	if (n_frags > 1) {
+		/* Release/sync DMA mapping for additional fragments.
+		 * Fix length for last fragment.
+		 */
+		unsigned int tail_frags = n_frags - 1;
+
+		for (;;) {
+			rx_buf = efx_rx_buf_next(rx_queue, rx_buf);
+			if (--tail_frags == 0)
+				break;
+			efx_sync_rx_buffer(efx, rx_buf, EFX_RX_USR_BUF_SIZE);
+		}
+		rx_buf->len = len - (n_frags - 1) * EFX_RX_USR_BUF_SIZE;
+		efx_sync_rx_buffer(efx, rx_buf, rx_buf->len);
+	}
+
+	/* All fragments have been DMA-synced, so recycle buffers and pages. */
+	rx_buf = efx_rx_buffer(rx_queue, index);
+	efx_recycle_rx_buffers(channel, rx_buf, n_frags);
 
 	/* Pipeline receives so that we give time for packet headers to be
 	 * prefetched into cache.
 	 */
-	rx_buf->len = len - efx->type->rx_buffer_hash_size;
-out:
-	if (channel->rx_pkt)
-		__efx_rx_packet(channel, channel->rx_pkt);
-	channel->rx_pkt = rx_buf;
+	efx_rx_flush_packet(channel);
+	channel->rx_pkt_n_frags = n_frags;
+	channel->rx_pkt_index = index;
 }
 
-static void efx_rx_deliver(struct efx_channel *channel,
-			   struct efx_rx_buffer *rx_buf)
+static void efx_rx_deliver(struct efx_channel *channel, u8 *eh,
+			   struct efx_rx_buffer *rx_buf,
+			   unsigned int n_frags)
 {
 	struct sk_buff *skb;
+	u16 hdr_len = min_t(u16, rx_buf->len, EFX_SKB_HEADERS);
 
-	/* We now own the SKB */
-	skb = rx_buf->u.skb;
-	rx_buf->u.skb = NULL;
+	skb = efx_rx_mk_skb(channel, rx_buf, n_frags, eh, hdr_len);
+	if (unlikely(skb == NULL)) {
+		efx_free_rx_buffer(rx_buf);
+		return;
+	}
+	skb_record_rx_queue(skb, channel->rx_queue.core_index);
 
 	/* Set the SKB flags */
 	skb_checksum_none_assert(skb);
 
-	/* Record the rx_queue */
-	skb_record_rx_queue(skb, channel->rx_queue.core_index);
-
-	/* Pass the packet up */
 	if (channel->type->receive_skb)
-		channel->type->receive_skb(channel, skb);
-	else
-		netif_receive_skb(skb);
+		if (channel->type->receive_skb(channel, skb))
+			return;
 
-	/* Update allocation strategy method */
-	channel->rx_alloc_level += RX_ALLOC_FACTOR_SKB;
+	/* Pass the packet up */
+	netif_receive_skb(skb);
 }
 
 /* Handle a received packet.  Second half: Touches packet payload. */
-void __efx_rx_packet(struct efx_channel *channel, struct efx_rx_buffer *rx_buf)
+void __efx_rx_packet(struct efx_channel *channel)
 {
 	struct efx_nic *efx = channel->efx;
-	u8 *eh = efx_rx_buf_eh(efx, rx_buf);
+	struct efx_rx_buffer *rx_buf =
+		efx_rx_buffer(&channel->rx_queue, channel->rx_pkt_index);
+	u8 *eh = efx_rx_buf_va(rx_buf);
 
 	/* If we're in loopback test, then pass the packet directly to the
 	 * loopback layer, and free the rx_buf here
 	 */
 	if (unlikely(efx->loopback_selftest)) {
 		efx_loopback_rx_packet(efx, eh, rx_buf->len);
-		efx_free_rx_buffer(efx, rx_buf);
-		return;
-	}
-
-	if (!(rx_buf->flags & EFX_RX_BUF_PAGE)) {
-		struct sk_buff *skb = rx_buf->u.skb;
-
-		prefetch(skb_shinfo(skb));
-
-		skb_reserve(skb, efx->type->rx_buffer_hash_size);
-		skb_put(skb, rx_buf->len);
-
-		if (efx->net_dev->features & NETIF_F_RXHASH)
-			skb->rxhash = efx_rx_buf_hash(eh);
-
-		/* Move past the ethernet header. rx_buf->data still points
-		 * at the ethernet header */
-		skb->protocol = eth_type_trans(skb, efx->net_dev);
-
-		skb_record_rx_queue(skb, channel->rx_queue.core_index);
+		efx_free_rx_buffer(rx_buf);
+		goto out;
 	}
 
 	if (unlikely(!(efx->net_dev->features & NETIF_F_RXCSUM)))
 		rx_buf->flags &= ~EFX_RX_PKT_CSUMMED;
 
-	if (likely(rx_buf->flags & (EFX_RX_BUF_PAGE | EFX_RX_PKT_CSUMMED)) &&
-	    !channel->type->receive_skb)
-		efx_rx_packet_gro(channel, rx_buf, eh);
+	if (!channel->type->receive_skb)
+		efx_rx_packet_gro(channel, rx_buf, channel->rx_pkt_n_frags, eh);
 	else
-		efx_rx_deliver(channel, rx_buf);
-}
-
-void efx_rx_strategy(struct efx_channel *channel)
-{
-	enum efx_rx_alloc_method method = rx_alloc_method;
-
-	if (channel->type->receive_skb) {
-		channel->rx_alloc_push_pages = false;
-		return;
-	}
-
-	/* Only makes sense to use page based allocation if GRO is enabled */
-	if (!(channel->efx->net_dev->features & NETIF_F_GRO)) {
-		method = RX_ALLOC_METHOD_SKB;
-	} else if (method == RX_ALLOC_METHOD_AUTO) {
-		/* Constrain the rx_alloc_level */
-		if (channel->rx_alloc_level < 0)
-			channel->rx_alloc_level = 0;
-		else if (channel->rx_alloc_level > RX_ALLOC_LEVEL_MAX)
-			channel->rx_alloc_level = RX_ALLOC_LEVEL_MAX;
-
-		/* Decide on the allocation method */
-		method = ((channel->rx_alloc_level > RX_ALLOC_LEVEL_GRO) ?
-			  RX_ALLOC_METHOD_PAGE : RX_ALLOC_METHOD_SKB);
-	}
-
-	/* Push the option */
-	channel->rx_alloc_push_pages = (method == RX_ALLOC_METHOD_PAGE);
+		efx_rx_deliver(channel, eh, rx_buf, channel->rx_pkt_n_frags);
+out:
+	channel->rx_pkt_n_frags = 0;
 }
 
 int efx_probe_rx_queue(struct efx_rx_queue *rx_queue)
@@ -683,9 +662,32 @@ int efx_probe_rx_queue(struct efx_rx_queue *rx_queue)
 		kfree(rx_queue->buffer);
 		rx_queue->buffer = NULL;
 	}
+
 	return rc;
 }
 
+static void efx_init_rx_recycle_ring(struct efx_nic *efx,
+				     struct efx_rx_queue *rx_queue)
+{
+	unsigned int bufs_in_recycle_ring, page_ring_size;
+
+	/* Set the RX recycle ring size */
+#ifdef CONFIG_PPC64
+	bufs_in_recycle_ring = EFX_RECYCLE_RING_SIZE_IOMMU;
+#else
+	if (efx->pci_dev->dev.iommu_group)
+		bufs_in_recycle_ring = EFX_RECYCLE_RING_SIZE_IOMMU;
+	else
+		bufs_in_recycle_ring = EFX_RECYCLE_RING_SIZE_NOIOMMU;
+#endif /* CONFIG_PPC64 */
+
+	page_ring_size = roundup_pow_of_two(bufs_in_recycle_ring /
+					    efx->rx_bufs_per_page);
+	rx_queue->page_ring = kcalloc(page_ring_size,
+				      sizeof(*rx_queue->page_ring), GFP_KERNEL);
+	rx_queue->page_ptr_mask = page_ring_size - 1;
+}
+
 void efx_init_rx_queue(struct efx_rx_queue *rx_queue)
 {
 	struct efx_nic *efx = rx_queue->efx;
@@ -699,10 +701,18 @@ void efx_init_rx_queue(struct efx_rx_queue *rx_queue)
 	rx_queue->notified_count = 0;
 	rx_queue->removed_count = 0;
 	rx_queue->min_fill = -1U;
+	efx_init_rx_recycle_ring(efx, rx_queue);
+
+	rx_queue->page_remove = 0;
+	rx_queue->page_add = rx_queue->page_ptr_mask + 1;
+	rx_queue->page_recycle_count = 0;
+	rx_queue->page_recycle_failed = 0;
+	rx_queue->page_recycle_full = 0;
 
 	/* Initialise limit fields */
 	max_fill = efx->rxq_entries - EFX_RXD_HEAD_ROOM;
-	max_trigger = max_fill - EFX_RX_BATCH;
+	max_trigger =
+		max_fill - efx->rx_pages_per_batch * efx->rx_bufs_per_page;
 	if (rx_refill_threshold != 0) {
 		trigger = max_fill * min(rx_refill_threshold, 100U) / 100U;
 		if (trigger > max_trigger)
@@ -722,6 +732,7 @@ void efx_init_rx_queue(struct efx_rx_queue *rx_queue)
 void efx_fini_rx_queue(struct efx_rx_queue *rx_queue)
 {
 	int i;
+	struct efx_nic *efx = rx_queue->efx;
 	struct efx_rx_buffer *rx_buf;
 
 	netif_dbg(rx_queue->efx, drv, rx_queue->efx->net_dev,
@@ -733,13 +744,32 @@ void efx_fini_rx_queue(struct efx_rx_queue *rx_queue)
 	del_timer_sync(&rx_queue->slow_fill);
 	efx_nic_fini_rx(rx_queue);
 
-	/* Release RX buffers NB start at index 0 not current HW ptr */
+	/* Release RX buffers from the current read ptr to the write ptr */
 	if (rx_queue->buffer) {
-		for (i = 0; i <= rx_queue->ptr_mask; i++) {
-			rx_buf = efx_rx_buffer(rx_queue, i);
+		for (i = rx_queue->removed_count; i < rx_queue->added_count;
+		     i++) {
+			unsigned index = i & rx_queue->ptr_mask;
+			rx_buf = efx_rx_buffer(rx_queue, index);
 			efx_fini_rx_buffer(rx_queue, rx_buf);
 		}
 	}
+
+	/* Unmap and release the pages in the recycle ring. Remove the ring. */
+	for (i = 0; i <= rx_queue->page_ptr_mask; i++) {
+		struct page *page = rx_queue->page_ring[i];
+		struct efx_rx_page_state *state;
+
+		if (page == NULL)
+			continue;
+
+		state = page_address(page);
+		dma_unmap_page(&efx->pci_dev->dev, state->dma_addr,
+			       PAGE_SIZE << efx->rx_buffer_order,
+			       DMA_FROM_DEVICE);
+		put_page(page);
+	}
+	kfree(rx_queue->page_ring);
+	rx_queue->page_ring = NULL;
 }
 
 void efx_remove_rx_queue(struct efx_rx_queue *rx_queue)
@@ -754,9 +784,6 @@ void efx_remove_rx_queue(struct efx_rx_queue *rx_queue)
 }
 
 
-module_param(rx_alloc_method, int, 0644);
-MODULE_PARM_DESC(rx_alloc_method, "Allocation method used for RX buffers");
-
 module_param(rx_refill_threshold, uint, 0444);
 MODULE_PARM_DESC(rx_refill_threshold,
 		 "RX descriptor ring refill threshold (%)");
diff --git a/drivers/net/ethernet/sfc/siena.c b/drivers/net/ethernet/sfc/siena.c
index ba40f67..5166924 100644
--- a/drivers/net/ethernet/sfc/siena.c
+++ b/drivers/net/ethernet/sfc/siena.c
@@ -202,7 +202,7 @@ out:
 
 static enum reset_type siena_map_reset_reason(enum reset_type reason)
 {
-	return RESET_TYPE_ALL;
+	return RESET_TYPE_RECOVER_OR_ALL;
 }
 
 static int siena_map_reset_flags(u32 *flags)
@@ -245,6 +245,22 @@ static int siena_reset_hw(struct efx_nic *efx, enum reset_type method)
 		return efx_mcdi_reset_port(efx);
 }
 
+#ifdef CONFIG_EEH
+/* When a PCI device is isolated from the bus, a subsequent MMIO read is
+ * required for the kernel EEH mechanisms to notice. As the Solarflare driver
+ * was written to minimise MMIO read (for latency) then a periodic call to check
+ * the EEH status of the device is required so that device recovery can happen
+ * in a timely fashion.
+ */
+static void siena_monitor(struct efx_nic *efx)
+{
+	struct eeh_dev *eehdev =
+		of_node_to_eeh_dev(pci_device_to_OF_node(efx->pci_dev));
+
+	eeh_dev_check_failure(eehdev);
+}
+#endif
+
 static int siena_probe_nvconfig(struct efx_nic *efx)
 {
 	u32 caps = 0;
@@ -398,6 +414,8 @@ static int siena_init_nic(struct efx_nic *efx)
 	EFX_SET_OWORD_FIELD(temp, FRF_BZ_RX_HASH_INSRT_HDR, 1);
 	EFX_SET_OWORD_FIELD(temp, FRF_BZ_RX_HASH_ALG, 1);
 	EFX_SET_OWORD_FIELD(temp, FRF_BZ_RX_IP_HASH, 1);
+	EFX_SET_OWORD_FIELD(temp, FRF_BZ_RX_USR_BUF_SIZE,
+			    EFX_RX_USR_BUF_SIZE >> 5);
 	efx_writeo(efx, &temp, FR_AZ_RX_CFG);
 
 	/* Set hash key for IPv4 */
@@ -665,7 +683,11 @@ const struct efx_nic_type siena_a0_nic_type = {
 	.init = siena_init_nic,
 	.dimension_resources = siena_dimension_resources,
 	.fini = efx_port_dummy_op_void,
+#ifdef CONFIG_EEH
+	.monitor = siena_monitor,
+#else
 	.monitor = NULL,
+#endif
 	.map_reset_reason = siena_map_reset_reason,
 	.map_reset_flags = siena_map_reset_flags,
 	.reset = siena_reset_hw,
@@ -698,6 +720,7 @@ const struct efx_nic_type siena_a0_nic_type = {
 	.max_dma_mask = DMA_BIT_MASK(FSF_AZ_TX_KER_BUF_ADDR_WIDTH),
 	.rx_buffer_hash_size = 0x10,
 	.rx_buffer_padding = 0,
+	.can_rx_scatter = true,
 	.max_interrupt_mode = EFX_INT_MODE_MSIX,
 	.phys_addr_channels = 32, /* Hardware limit is 64, but the legacy
 				   * interrupt handler only supports 32
diff --git a/drivers/net/ethernet/sgi/meth.c b/drivers/net/ethernet/sgi/meth.c
index 79ad9c9..4bdbaad9 100644
--- a/drivers/net/ethernet/sgi/meth.c
+++ b/drivers/net/ethernet/sgi/meth.c
@@ -213,10 +213,11 @@ static int meth_init_tx_ring(struct meth_private *priv)
 {
 	/* Init TX ring */
 	priv->tx_ring = dma_alloc_coherent(NULL, TX_RING_BUFFER_SIZE,
-	                                   &priv->tx_ring_dma, GFP_ATOMIC);
+	                                   &priv->tx_ring_dma,
+					   GFP_ATOMIC | __GFP_ZERO);
 	if (!priv->tx_ring)
 		return -ENOMEM;
-	memset(priv->tx_ring, 0, TX_RING_BUFFER_SIZE);
+
 	priv->tx_count = priv->tx_read = priv->tx_write = 0;
 	mace->eth.tx_ring_base = priv->tx_ring_dma;
 	/* Now init skb save area */
diff --git a/drivers/net/ethernet/sis/sis900.c b/drivers/net/ethernet/sis/sis900.c
index efca14e..e458296 100644
--- a/drivers/net/ethernet/sis/sis900.c
+++ b/drivers/net/ethernet/sis/sis900.c
@@ -1841,15 +1841,12 @@ refill_rx_ring:
 		entry = sis_priv->dirty_rx % NUM_RX_DESC;
 
 		if (sis_priv->rx_skbuff[entry] == NULL) {
-			if ((skb = netdev_alloc_skb(net_dev, RX_BUF_SIZE)) == NULL) {
+			skb = netdev_alloc_skb(net_dev, RX_BUF_SIZE);
+			if (skb == NULL) {
 				/* not enough memory for skbuff, this makes a
 				 * "hole" on the buffer ring, it is not clear
 				 * how the hardware will react to this kind
 				 * of degenerated buffer */
-				if (netif_msg_rx_err(sis_priv))
-					printk(KERN_INFO "%s: Memory squeeze, "
-						"deferring packet.\n",
-						net_dev->name);
 				net_dev->stats.rx_dropped++;
 				break;
 			}
diff --git a/drivers/net/ethernet/smsc/smc9194.c b/drivers/net/ethernet/smsc/smc9194.c
index 50823da..e85c2e7 100644
--- a/drivers/net/ethernet/smsc/smc9194.c
+++ b/drivers/net/ethernet/smsc/smc9194.c
@@ -1223,9 +1223,7 @@ static void smc_rcv(struct net_device *dev)
 			dev->stats.multicast++;
 
 		skb = netdev_alloc_skb(dev, packet_length + 5);
-
 		if ( skb == NULL ) {
-			printk(KERN_NOTICE CARDNAME ": Low memory, packet dropped.\n");
 			dev->stats.rx_dropped++;
 			goto done;
 		}
diff --git a/drivers/net/ethernet/smsc/smc91c92_cs.c b/drivers/net/ethernet/smsc/smc91c92_cs.c
index 04393b5..656d2e2 100644
--- a/drivers/net/ethernet/smsc/smc91c92_cs.c
+++ b/drivers/net/ethernet/smsc/smc91c92_cs.c
@@ -2054,16 +2054,4 @@ static struct pcmcia_driver smc91c92_cs_driver = {
 	.suspend	= smc91c92_suspend,
 	.resume		= smc91c92_resume,
 };
-
-static int __init init_smc91c92_cs(void)
-{
-	return pcmcia_register_driver(&smc91c92_cs_driver);
-}
-
-static void __exit exit_smc91c92_cs(void)
-{
-	pcmcia_unregister_driver(&smc91c92_cs_driver);
-}
-
-module_init(init_smc91c92_cs);
-module_exit(exit_smc91c92_cs);
+module_pcmcia_driver(smc91c92_cs_driver);
diff --git a/drivers/net/ethernet/smsc/smc91x.c b/drivers/net/ethernet/smsc/smc91x.c
index 591650a..dfbf978 100644
--- a/drivers/net/ethernet/smsc/smc91x.c
+++ b/drivers/net/ethernet/smsc/smc91x.c
@@ -465,8 +465,6 @@ static inline void  smc_rcv(struct net_device *dev)
 		 */
 		skb = netdev_alloc_skb(dev, packet_len);
 		if (unlikely(skb == NULL)) {
-			printk(KERN_NOTICE "%s: Low memory, packet dropped.\n",
-				dev->name);
 			SMC_WAIT_MMU_BUSY(lp);
 			SMC_SET_MMU_CMD(lp, MC_RELEASE);
 			dev->stats.rx_dropped++;
diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c
index da5cc9a..3663b9e 100644
--- a/drivers/net/ethernet/smsc/smsc911x.c
+++ b/drivers/net/ethernet/smsc/smsc911x.c
@@ -33,6 +33,7 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/crc32.h>
+#include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/etherdevice.h>
@@ -144,6 +145,9 @@ struct smsc911x_data {
 
 	/* regulators */
 	struct regulator_bulk_data supplies[SMSC911X_NUM_SUPPLIES];
+
+	/* clock */
+	struct clk *clk;
 };
 
 /* Easy access to information */
@@ -369,7 +373,7 @@ out:
 }
 
 /*
- * enable resources, currently just regulators.
+ * enable regulator and clock resources.
  */
 static int smsc911x_enable_resources(struct platform_device *pdev)
 {
@@ -382,6 +386,13 @@ static int smsc911x_enable_resources(struct platform_device *pdev)
 	if (ret)
 		netdev_err(ndev, "failed to enable regulators %d\n",
 				ret);
+
+	if (!IS_ERR(pdata->clk)) {
+		ret = clk_prepare_enable(pdata->clk);
+		if (ret < 0)
+			netdev_err(ndev, "failed to enable clock %d\n", ret);
+	}
+
 	return ret;
 }
 
@@ -396,6 +407,10 @@ static int smsc911x_disable_resources(struct platform_device *pdev)
 
 	ret = regulator_bulk_disable(ARRAY_SIZE(pdata->supplies),
 			pdata->supplies);
+
+	if (!IS_ERR(pdata->clk))
+		clk_disable_unprepare(pdata->clk);
+
 	return ret;
 }
 
@@ -421,6 +436,12 @@ static int smsc911x_request_resources(struct platform_device *pdev)
 	if (ret)
 		netdev_err(ndev, "couldn't get regulators %d\n",
 				ret);
+
+	/* Request clock */
+	pdata->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(pdata->clk))
+		netdev_warn(ndev, "couldn't get clock %li\n", PTR_ERR(pdata->clk));
+
 	return ret;
 }
 
@@ -436,6 +457,12 @@ static void smsc911x_free_resources(struct platform_device *pdev)
 	/* Free regulators */
 	regulator_bulk_free(ARRAY_SIZE(pdata->supplies),
 			pdata->supplies);
+
+	/* Free clock */
+	if (!IS_ERR(pdata->clk)) {
+		clk_put(pdata->clk);
+		pdata->clk = NULL;
+	}
 }
 
 /* waits for MAC not busy, with timeout.  Only called by smsc911x_mac_read
@@ -2115,7 +2142,7 @@ static int smsc911x_init(struct net_device *dev)
 	spin_lock_init(&pdata->dev_lock);
 	spin_lock_init(&pdata->mac_lock);
 
-	if (pdata->ioaddr == 0) {
+	if (pdata->ioaddr == NULL) {
 		SMSC_WARN(pdata, probe, "pdata->ioaddr: 0x00000000");
 		return -ENODEV;
 	}
diff --git a/drivers/net/ethernet/smsc/smsc9420.c b/drivers/net/ethernet/smsc/smsc9420.c
index d457fa2..ffa5c4a 100644
--- a/drivers/net/ethernet/smsc/smsc9420.c
+++ b/drivers/net/ethernet/smsc/smsc9420.c
@@ -848,10 +848,8 @@ static int smsc9420_alloc_rx_buffer(struct smsc9420_pdata *pd, int index)
 	BUG_ON(pd->rx_buffers[index].skb);
 	BUG_ON(pd->rx_buffers[index].mapping);
 
-	if (unlikely(!skb)) {
-		smsc_warn(RX_ERR, "Failed to allocate new skb!");
+	if (unlikely(!skb))
 		return -ENOMEM;
-	}
 
 	mapping = pci_map_single(pd->pdev, skb_tail_pointer(skb),
 				 PKT_BUF_SZ, PCI_DMA_FROMDEVICE);
diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
index c0ea838..f695a50 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
+++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
@@ -5,6 +5,7 @@ config STMMAC_ETH
 	select MII
 	select PHYLIB
 	select CRC32
+	select PTP_1588_CLOCK
 	---help---
 	  This is the driver for the Ethernet IPs are built around a
 	  Synopsys IP Core and only tested on the STMicroelectronics
@@ -54,22 +55,4 @@ config STMMAC_DA
 	  By default, the DMA arbitration scheme is based on Round-robin
 	  (rx:tx priority is 1:1).
 
-choice
-	prompt "Select the DMA TX/RX descriptor operating modes"
-	depends on STMMAC_ETH
-	---help---
-	  This driver supports DMA descriptor to operate both in dual buffer
-	  (RING) and linked-list(CHAINED) mode. In RING mode each descriptor
-	  points to two data buffer pointers whereas in CHAINED mode they
-	  points to only one data buffer pointer.
-
-config STMMAC_RING
-	bool "Enable Descriptor Ring Mode"
-
-config STMMAC_CHAINED
-	bool "Enable Descriptor Chained Mode"
-
-endchoice
-
-
 endif
diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
index c8e8ea6..356a9dd 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Makefile
+++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
@@ -1,9 +1,7 @@
 obj-$(CONFIG_STMMAC_ETH) += stmmac.o
-stmmac-$(CONFIG_STMMAC_RING) += ring_mode.o
-stmmac-$(CONFIG_STMMAC_CHAINED) += chain_mode.o
 stmmac-$(CONFIG_STMMAC_PLATFORM) += stmmac_platform.o
 stmmac-$(CONFIG_STMMAC_PCI) += stmmac_pci.o
-stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o	\
-	      dwmac_lib.o dwmac1000_core.o  dwmac1000_dma.o	\
+stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o ring_mode.o	\
+	      chain_mode.o dwmac_lib.o dwmac1000_core.o  dwmac1000_dma.o \
 	      dwmac100_core.o dwmac100_dma.o enh_desc.o  norm_desc.o \
-	      mmc_core.o $(stmmac-y)
+	      mmc_core.o stmmac_hwtstamp.o stmmac_ptp.o $(stmmac-y)
diff --git a/drivers/net/ethernet/stmicro/stmmac/chain_mode.c b/drivers/net/ethernet/stmicro/stmmac/chain_mode.c
index 0668659..37a3f93 100644
--- a/drivers/net/ethernet/stmicro/stmmac/chain_mode.c
+++ b/drivers/net/ethernet/stmicro/stmmac/chain_mode.c
@@ -28,7 +28,7 @@
 
 #include "stmmac.h"
 
-unsigned int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
+static unsigned int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
 {
 	struct stmmac_priv *priv = (struct stmmac_priv *) p;
 	unsigned int txsize = priv->dma_tx_size;
@@ -47,7 +47,8 @@ unsigned int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
 
 	desc->des2 = dma_map_single(priv->device, skb->data,
 				    bmax, DMA_TO_DEVICE);
-	priv->hw->desc->prepare_tx_desc(desc, 1, bmax, csum);
+	priv->tx_skbuff_dma[entry] = desc->des2;
+	priv->hw->desc->prepare_tx_desc(desc, 1, bmax, csum, STMMAC_CHAIN_MODE);
 
 	while (len != 0) {
 		entry = (++priv->cur_tx) % txsize;
@@ -57,8 +58,9 @@ unsigned int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
 			desc->des2 = dma_map_single(priv->device,
 						    (skb->data + bmax * i),
 						    bmax, DMA_TO_DEVICE);
-			priv->hw->desc->prepare_tx_desc(desc, 0, bmax,
-							csum);
+			priv->tx_skbuff_dma[entry] = desc->des2;
+			priv->hw->desc->prepare_tx_desc(desc, 0, bmax, csum,
+							STMMAC_CHAIN_MODE);
 			priv->hw->desc->set_tx_owner(desc);
 			priv->tx_skbuff[entry] = NULL;
 			len -= bmax;
@@ -67,8 +69,9 @@ unsigned int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
 			desc->des2 = dma_map_single(priv->device,
 						    (skb->data + bmax * i), len,
 						    DMA_TO_DEVICE);
-			priv->hw->desc->prepare_tx_desc(desc, 0, len,
-							csum);
+			priv->tx_skbuff_dma[entry] = desc->des2;
+			priv->hw->desc->prepare_tx_desc(desc, 0, len, csum,
+							STMMAC_CHAIN_MODE);
 			priv->hw->desc->set_tx_owner(desc);
 			priv->tx_skbuff[entry] = NULL;
 			len = 0;
@@ -89,49 +92,70 @@ static unsigned int stmmac_is_jumbo_frm(int len, int enh_desc)
 	return ret;
 }
 
-static void stmmac_refill_desc3(int bfsize, struct dma_desc *p)
-{
-}
-
-static void stmmac_init_desc3(int des3_as_data_buf, struct dma_desc *p)
-{
-}
-
-static void stmmac_clean_desc3(struct dma_desc *p)
-{
-}
-
-static void stmmac_init_dma_chain(struct dma_desc *des, dma_addr_t phy_addr,
-				  unsigned int size)
+static void stmmac_init_dma_chain(void *des, dma_addr_t phy_addr,
+				  unsigned int size, unsigned int extend_desc)
 {
 	/*
 	 * In chained mode the des3 points to the next element in the ring.
 	 * The latest element has to point to the head.
 	 */
 	int i;
-	struct dma_desc *p = des;
 	dma_addr_t dma_phy = phy_addr;
 
-	for (i = 0; i < (size - 1); i++) {
-		dma_phy += sizeof(struct dma_desc);
-		p->des3 = (unsigned int)dma_phy;
-		p++;
+	if (extend_desc) {
+		struct dma_extended_desc *p = (struct dma_extended_desc *) des;
+		for (i = 0; i < (size - 1); i++) {
+			dma_phy += sizeof(struct dma_extended_desc);
+			p->basic.des3 = (unsigned int)dma_phy;
+			p++;
+		}
+		p->basic.des3 = (unsigned int)phy_addr;
+
+	} else {
+		struct dma_desc *p = (struct dma_desc *) des;
+		for (i = 0; i < (size - 1); i++) {
+			dma_phy += sizeof(struct dma_desc);
+			p->des3 = (unsigned int)dma_phy;
+			p++;
+		}
+		p->des3 = (unsigned int)phy_addr;
 	}
-	p->des3 = (unsigned int)phy_addr;
 }
 
-static int stmmac_set_16kib_bfsize(int mtu)
+static void stmmac_refill_desc3(void *priv_ptr, struct dma_desc *p)
+{
+	struct stmmac_priv *priv = (struct stmmac_priv *)priv_ptr;
+
+	if (priv->hwts_rx_en && !priv->extend_desc)
+		/* NOTE: Device will overwrite des3 with timestamp value if
+		 * 1588-2002 time stamping is enabled, hence reinitialize it
+		 * to keep explicit chaining in the descriptor.
+		 */
+		p->des3 = (unsigned int)(priv->dma_rx_phy +
+					 (((priv->dirty_rx) + 1) %
+					 priv->dma_rx_size) *
+					 sizeof(struct dma_desc));
+}
+
+static void stmmac_clean_desc3(void *priv_ptr, struct dma_desc *p)
 {
-	/* Not supported */
-	return 0;
+	struct stmmac_priv *priv = (struct stmmac_priv *)priv_ptr;
+
+	if (priv->hw->desc->get_tx_ls(p) && !priv->extend_desc)
+		/* NOTE: Device will overwrite des3 with timestamp value if
+		 * 1588-2002 time stamping is enabled, hence reinitialize it
+		 * to keep explicit chaining in the descriptor.
+		 */
+		p->des3 = (unsigned int)(priv->dma_tx_phy +
+					 (((priv->dirty_tx + 1) %
+					 priv->dma_tx_size) *
+					 sizeof(struct dma_desc)));
 }
 
-const struct stmmac_ring_mode_ops ring_mode_ops = {
+const struct stmmac_chain_mode_ops chain_mode_ops = {
+	.init = stmmac_init_dma_chain,
 	.is_jumbo_frm = stmmac_is_jumbo_frm,
 	.jumbo_frm = stmmac_jumbo_frm,
 	.refill_desc3 = stmmac_refill_desc3,
-	.init_desc3 = stmmac_init_desc3,
-	.init_dma_chain = stmmac_init_dma_chain,
 	.clean_desc3 = stmmac_clean_desc3,
-	.set_16kib_bfsize = stmmac_set_16kib_bfsize,
 };
diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index 186d148..ad7e20a 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -117,6 +117,36 @@ struct stmmac_extra_stats {
 	unsigned long irq_rx_path_in_lpi_mode_n;
 	unsigned long irq_rx_path_exit_lpi_mode_n;
 	unsigned long phy_eee_wakeup_error_n;
+	/* Extended RDES status */
+	unsigned long ip_hdr_err;
+	unsigned long ip_payload_err;
+	unsigned long ip_csum_bypassed;
+	unsigned long ipv4_pkt_rcvd;
+	unsigned long ipv6_pkt_rcvd;
+	unsigned long rx_msg_type_ext_no_ptp;
+	unsigned long rx_msg_type_sync;
+	unsigned long rx_msg_type_follow_up;
+	unsigned long rx_msg_type_delay_req;
+	unsigned long rx_msg_type_delay_resp;
+	unsigned long rx_msg_type_pdelay_req;
+	unsigned long rx_msg_type_pdelay_resp;
+	unsigned long rx_msg_type_pdelay_follow_up;
+	unsigned long ptp_frame_type;
+	unsigned long ptp_ver;
+	unsigned long timestamp_dropped;
+	unsigned long av_pkt_rcvd;
+	unsigned long av_tagged_pkt_rcvd;
+	unsigned long vlan_tag_priority_val;
+	unsigned long l3_filter_match;
+	unsigned long l4_filter_match;
+	unsigned long l3_l4_filter_no_match;
+	/* PCS */
+	unsigned long irq_pcs_ane_n;
+	unsigned long irq_pcs_link_n;
+	unsigned long irq_rgmii_n;
+	unsigned long pcs_link;
+	unsigned long pcs_duplex;
+	unsigned long pcs_speed;
 };
 
 /* CSR Frequency Access Defines*/
@@ -138,6 +168,12 @@ struct stmmac_extra_stats {
 #define FLOW_TX		2
 #define FLOW_AUTO	(FLOW_TX | FLOW_RX)
 
+/* PCS defines */
+#define STMMAC_PCS_RGMII	(1 << 0)
+#define STMMAC_PCS_SGMII	(1 << 1)
+#define STMMAC_PCS_TBI		(1 << 2)
+#define STMMAC_PCS_RTBI		(1 << 3)
+
 #define SF_DMA_MODE 1 /* DMA STORE-AND-FORWARD Operation Mode */
 
 /* DAM HW feature register fields */
@@ -194,17 +230,25 @@ enum dma_irq_status {
 	handle_tx = 0x8,
 };
 
-enum core_specific_irq_mask {
-	core_mmc_tx_irq = 1,
-	core_mmc_rx_irq = 2,
-	core_mmc_rx_csum_offload_irq = 4,
-	core_irq_receive_pmt_irq = 8,
-	core_irq_tx_path_in_lpi_mode = 16,
-	core_irq_tx_path_exit_lpi_mode = 32,
-	core_irq_rx_path_in_lpi_mode = 64,
-	core_irq_rx_path_exit_lpi_mode = 128,
+#define	CORE_IRQ_TX_PATH_IN_LPI_MODE	(1 << 1)
+#define	CORE_IRQ_TX_PATH_EXIT_LPI_MODE	(1 << 2)
+#define	CORE_IRQ_RX_PATH_IN_LPI_MODE	(1 << 3)
+#define	CORE_IRQ_RX_PATH_EXIT_LPI_MODE	(1 << 4)
+
+#define	CORE_PCS_ANE_COMPLETE		(1 << 5)
+#define	CORE_PCS_LINK_STATUS		(1 << 6)
+#define	CORE_RGMII_IRQ			(1 << 7)
+
+struct rgmii_adv {
+	unsigned int pause;
+	unsigned int duplex;
+	unsigned int lp_pause;
+	unsigned int lp_duplex;
 };
 
+#define STMMAC_PCS_PAUSE	1
+#define STMMAC_PCS_ASYM_PAUSE	2
+
 /* DMA HW capabilities */
 struct dma_features {
 	unsigned int mbps_10_100;
@@ -255,23 +299,26 @@ struct dma_features {
 #define STMMAC_DEFAULT_LIT_LS_TIMER	0x3E8
 #define STMMAC_DEFAULT_TWT_LS_TIMER	0x0
 
+#define STMMAC_CHAIN_MODE	0x1
+#define STMMAC_RING_MODE	0x2
+
 struct stmmac_desc_ops {
 	/* DMA RX descriptor ring initialization */
-	void (*init_rx_desc) (struct dma_desc *p, unsigned int ring_size,
-			      int disable_rx_ic);
+	void (*init_rx_desc) (struct dma_desc *p, int disable_rx_ic, int mode,
+			      int end);
 	/* DMA TX descriptor ring initialization */
-	void (*init_tx_desc) (struct dma_desc *p, unsigned int ring_size);
+	void (*init_tx_desc) (struct dma_desc *p, int mode, int end);
 
 	/* Invoked by the xmit function to prepare the tx descriptor */
 	void (*prepare_tx_desc) (struct dma_desc *p, int is_fs, int len,
-				 int csum_flag);
+				 int csum_flag, int mode);
 	/* Set/get the owner of the descriptor */
 	void (*set_tx_owner) (struct dma_desc *p);
 	int (*get_tx_owner) (struct dma_desc *p);
 	/* Invoked by the xmit function to close the tx descriptor */
 	void (*close_tx_desc) (struct dma_desc *p);
 	/* Clean the tx descriptor as soon as the tx irq is received */
-	void (*release_tx_desc) (struct dma_desc *p);
+	void (*release_tx_desc) (struct dma_desc *p, int mode);
 	/* Clear interrupt on tx frame completion. When this bit is
 	 * set an interrupt happens as soon as the frame is transmitted */
 	void (*clear_tx_ic) (struct dma_desc *p);
@@ -290,12 +337,22 @@ struct stmmac_desc_ops {
 	/* Return the reception status looking at the RDES1 */
 	int (*rx_status) (void *data, struct stmmac_extra_stats *x,
 			  struct dma_desc *p);
+	void (*rx_extended_status) (void *data, struct stmmac_extra_stats *x,
+				    struct dma_extended_desc *p);
+	/* Set tx timestamp enable bit */
+	void (*enable_tx_timestamp) (struct dma_desc *p);
+	/* get tx timestamp status */
+	int (*get_tx_timestamp_status) (struct dma_desc *p);
+	/* get timestamp value */
+	u64 (*get_timestamp) (void *desc, u32 ats);
+	/* get rx timestamp status */
+	int (*get_rx_timestamp_status) (void *desc, u32 ats);
 };
 
 struct stmmac_dma_ops {
 	/* DMA core initialization */
 	int (*init) (void __iomem *ioaddr, int pbl, int fb, int mb,
-		     int burst_len, u32 dma_tx, u32 dma_rx);
+		     int burst_len, u32 dma_tx, u32 dma_rx, int atds);
 	/* Dump DMA registers */
 	void (*dump_regs) (void __iomem *ioaddr);
 	/* Set tx/rx threshold in the csr6 register
@@ -327,7 +384,8 @@ struct stmmac_ops {
 	/* Dump MAC registers */
 	void (*dump_regs) (void __iomem *ioaddr);
 	/* Handle extra events on specific interrupts hw dependent */
-	int (*host_irq_status) (void __iomem *ioaddr);
+	int (*host_irq_status) (void __iomem *ioaddr,
+				struct stmmac_extra_stats *x);
 	/* Multicast filter setting */
 	void (*set_filter) (struct net_device *dev, int id);
 	/* Flow control setting */
@@ -344,6 +402,18 @@ struct stmmac_ops {
 	void (*reset_eee_mode) (void __iomem *ioaddr);
 	void (*set_eee_timer) (void __iomem *ioaddr, int ls, int tw);
 	void (*set_eee_pls) (void __iomem *ioaddr, int link);
+	void (*ctrl_ane) (void __iomem *ioaddr, bool restart);
+	void (*get_adv) (void __iomem *ioaddr, struct rgmii_adv *adv);
+};
+
+struct stmmac_hwtimestamp {
+	void (*config_hw_tstamping) (void __iomem *ioaddr, u32 data);
+	void (*config_sub_second_increment) (void __iomem *ioaddr);
+	int (*init_systime) (void __iomem *ioaddr, u32 sec, u32 nsec);
+	int (*config_addend)(void __iomem *ioaddr, u32 addend);
+	int (*adjust_systime)(void __iomem *ioaddr, u32 sec, u32 nsec,
+			      int add_sub);
+	u64 (*get_systime)(void __iomem *ioaddr);
 };
 
 struct mac_link {
@@ -360,19 +430,28 @@ struct mii_regs {
 struct stmmac_ring_mode_ops {
 	unsigned int (*is_jumbo_frm) (int len, int ehn_desc);
 	unsigned int (*jumbo_frm) (void *priv, struct sk_buff *skb, int csum);
-	void (*refill_desc3) (int bfsize, struct dma_desc *p);
-	void (*init_desc3) (int des3_as_data_buf, struct dma_desc *p);
-	void (*init_dma_chain) (struct dma_desc *des, dma_addr_t phy_addr,
-				unsigned int size);
-	void (*clean_desc3) (struct dma_desc *p);
+	void (*refill_desc3) (void *priv, struct dma_desc *p);
+	void (*init_desc3) (struct dma_desc *p);
+	void (*clean_desc3) (void *priv, struct dma_desc *p);
 	int (*set_16kib_bfsize) (int mtu);
 };
 
+struct stmmac_chain_mode_ops {
+	void (*init) (void *des, dma_addr_t phy_addr, unsigned int size,
+		      unsigned int extend_desc);
+	unsigned int (*is_jumbo_frm) (int len, int ehn_desc);
+	unsigned int (*jumbo_frm) (void *priv, struct sk_buff *skb, int csum);
+	void (*refill_desc3) (void *priv, struct dma_desc *p);
+	void (*clean_desc3) (void *priv, struct dma_desc *p);
+};
+
 struct mac_device_info {
 	const struct stmmac_ops		*mac;
 	const struct stmmac_desc_ops	*desc;
 	const struct stmmac_dma_ops	*dma;
 	const struct stmmac_ring_mode_ops	*ring;
+	const struct stmmac_chain_mode_ops	*chain;
+	const struct stmmac_hwtimestamp *ptp;
 	struct mii_regs mii;	/* MII register Addresses */
 	struct mac_link link;
 	unsigned int synopsys_uid;
@@ -390,5 +469,6 @@ extern void stmmac_set_mac(void __iomem *ioaddr, bool enable);
 
 extern void dwmac_dma_flush_tx_fifo(void __iomem *ioaddr);
 extern const struct stmmac_ring_mode_ops ring_mode_ops;
+extern const struct stmmac_chain_mode_ops chain_mode_ops;
 
 #endif /* __COMMON_H__ */
diff --git a/drivers/net/ethernet/stmicro/stmmac/descs.h b/drivers/net/ethernet/stmicro/stmmac/descs.h
index 223adf9..2eca0c0 100644
--- a/drivers/net/ethernet/stmicro/stmmac/descs.h
+++ b/drivers/net/ethernet/stmicro/stmmac/descs.h
@@ -24,6 +24,7 @@
 #ifndef __DESCS_H__
 #define __DESCS_H__
 
+/* Basic descriptor structure for normal and alternate descriptors */
 struct dma_desc {
 	/* Receive descriptor */
 	union {
@@ -60,7 +61,7 @@ struct dma_desc {
 		} rx;
 		struct {
 			/* RDES0 */
-			u32 payload_csum_error:1;
+			u32 rx_mac_addr:1;
 			u32 crc_error:1;
 			u32 dribbling:1;
 			u32 error_gmii:1;
@@ -162,13 +163,57 @@ struct dma_desc {
 	unsigned int des3;
 };
 
+/* Extended descriptor structure (supported by new SYNP GMAC generations) */
+struct dma_extended_desc {
+	struct dma_desc basic;
+	union {
+		struct {
+			u32 ip_payload_type:3;
+			u32 ip_hdr_err:1;
+			u32 ip_payload_err:1;
+			u32 ip_csum_bypassed:1;
+			u32 ipv4_pkt_rcvd:1;
+			u32 ipv6_pkt_rcvd:1;
+			u32 msg_type:4;
+			u32 ptp_frame_type:1;
+			u32 ptp_ver:1;
+			u32 timestamp_dropped:1;
+			u32 reserved:1;
+			u32 av_pkt_rcvd:1;
+			u32 av_tagged_pkt_rcvd:1;
+			u32 vlan_tag_priority_val:3;
+			u32 reserved3:3;
+			u32 l3_filter_match:1;
+			u32 l4_filter_match:1;
+			u32 l3_l4_filter_no_match:2;
+			u32 reserved4:4;
+		} erx;
+		struct {
+			u32 reserved;
+		} etx;
+	} des4;
+	unsigned int des5; /* Reserved */
+	unsigned int des6; /* Tx/Rx Timestamp Low */
+	unsigned int des7; /* Tx/Rx Timestamp High */
+};
+
 /* Transmit checksum insertion control */
 enum tdes_csum_insertion {
 	cic_disabled = 0,	/* Checksum Insertion Control */
 	cic_only_ip = 1,	/* Only IP header */
-	cic_no_pseudoheader = 2,	/* IP header but pseudoheader
-					 * is not calculated */
+	/* IP header but pseudoheader is not calculated */
+	cic_no_pseudoheader = 2,
 	cic_full = 3,		/* IP header and pseudoheader */
 };
 
+/* Extended RDES4 definitions */
+#define RDES_EXT_NO_PTP			0
+#define RDES_EXT_SYNC			0x1
+#define RDES_EXT_FOLLOW_UP		0x2
+#define RDES_EXT_DELAY_REQ		0x3
+#define RDES_EXT_DELAY_RESP		0x4
+#define RDES_EXT_PDELAY_REQ		0x5
+#define RDES_EXT_PDELAY_RESP		0x6
+#define RDES_EXT_PDELAY_FOLLOW_UP	0x7
+
 #endif /* __DESCS_H__ */
diff --git a/drivers/net/ethernet/stmicro/stmmac/descs_com.h b/drivers/net/ethernet/stmicro/stmmac/descs_com.h
index 7ee9499..20f83fc 100644
--- a/drivers/net/ethernet/stmicro/stmmac/descs_com.h
+++ b/drivers/net/ethernet/stmicro/stmmac/descs_com.h
@@ -30,26 +30,28 @@
 #ifndef __DESC_COM_H__
 #define __DESC_COM_H__
 
-#if defined(CONFIG_STMMAC_RING)
-static inline void ehn_desc_rx_set_on_ring_chain(struct dma_desc *p, int end)
+/* Specific functions used for Ring mode */
+
+/* Enhanced descriptors */
+static inline void ehn_desc_rx_set_on_ring(struct dma_desc *p, int end)
 {
 	p->des01.erx.buffer2_size = BUF_SIZE_8KiB - 1;
 	if (end)
 		p->des01.erx.end_ring = 1;
 }
 
-static inline void ehn_desc_tx_set_on_ring_chain(struct dma_desc *p, int end)
+static inline void ehn_desc_tx_set_on_ring(struct dma_desc *p, int end)
 {
 	if (end)
 		p->des01.etx.end_ring = 1;
 }
 
-static inline void enh_desc_end_tx_desc(struct dma_desc *p, int ter)
+static inline void enh_desc_end_tx_desc_on_ring(struct dma_desc *p, int ter)
 {
 	p->des01.etx.end_ring = ter;
 }
 
-static inline void enh_set_tx_desc_len(struct dma_desc *p, int len)
+static inline void enh_set_tx_desc_len_on_ring(struct dma_desc *p, int len)
 {
 	if (unlikely(len > BUF_SIZE_4KiB)) {
 		p->des01.etx.buffer1_size = BUF_SIZE_4KiB;
@@ -58,25 +60,26 @@ static inline void enh_set_tx_desc_len(struct dma_desc *p, int len)
 		p->des01.etx.buffer1_size = len;
 }
 
-static inline void ndesc_rx_set_on_ring_chain(struct dma_desc *p, int end)
+/* Normal descriptors */
+static inline void ndesc_rx_set_on_ring(struct dma_desc *p, int end)
 {
 	p->des01.rx.buffer2_size = BUF_SIZE_2KiB - 1;
 	if (end)
 		p->des01.rx.end_ring = 1;
 }
 
-static inline void ndesc_tx_set_on_ring_chain(struct dma_desc *p, int end)
+static inline void ndesc_tx_set_on_ring(struct dma_desc *p, int end)
 {
 	if (end)
 		p->des01.tx.end_ring = 1;
 }
 
-static inline void ndesc_end_tx_desc(struct dma_desc *p, int ter)
+static inline void ndesc_end_tx_desc_on_ring(struct dma_desc *p, int ter)
 {
 	p->des01.tx.end_ring = ter;
 }
 
-static inline void norm_set_tx_desc_len(struct dma_desc *p, int len)
+static inline void norm_set_tx_desc_len_on_ring(struct dma_desc *p, int len)
 {
 	if (unlikely(len > BUF_SIZE_2KiB)) {
 		p->des01.etx.buffer1_size = BUF_SIZE_2KiB - 1;
@@ -85,47 +88,48 @@ static inline void norm_set_tx_desc_len(struct dma_desc *p, int len)
 		p->des01.tx.buffer1_size = len;
 }
 
-#else
+/* Specific functions used for Chain mode */
 
-static inline void ehn_desc_rx_set_on_ring_chain(struct dma_desc *p, int end)
+/* Enhanced descriptors */
+static inline void ehn_desc_rx_set_on_chain(struct dma_desc *p, int end)
 {
 	p->des01.erx.second_address_chained = 1;
 }
 
-static inline void ehn_desc_tx_set_on_ring_chain(struct dma_desc *p, int end)
+static inline void ehn_desc_tx_set_on_chain(struct dma_desc *p, int end)
 {
 	p->des01.etx.second_address_chained = 1;
 }
 
-static inline void enh_desc_end_tx_desc(struct dma_desc *p, int ter)
+static inline void enh_desc_end_tx_desc_on_chain(struct dma_desc *p, int ter)
 {
 	p->des01.etx.second_address_chained = 1;
 }
 
-static inline void enh_set_tx_desc_len(struct dma_desc *p, int len)
+static inline void enh_set_tx_desc_len_on_chain(struct dma_desc *p, int len)
 {
 	p->des01.etx.buffer1_size = len;
 }
 
-static inline void ndesc_rx_set_on_ring_chain(struct dma_desc *p, int end)
+/* Normal descriptors */
+static inline void ndesc_rx_set_on_chain(struct dma_desc *p, int end)
 {
 	p->des01.rx.second_address_chained = 1;
 }
 
-static inline void ndesc_tx_set_on_ring_chain(struct dma_desc *p, int ring_size)
+static inline void ndesc_tx_set_on_chain(struct dma_desc *p, int
+						 ring_size)
 {
 	p->des01.tx.second_address_chained = 1;
 }
 
-static inline void ndesc_end_tx_desc(struct dma_desc *p, int ter)
+static inline void ndesc_end_tx_desc_on_chain(struct dma_desc *p, int ter)
 {
 	p->des01.tx.second_address_chained = 1;
 }
 
-static inline void norm_set_tx_desc_len(struct dma_desc *p, int len)
+static inline void norm_set_tx_desc_len_on_chain(struct dma_desc *p, int len)
 {
 	p->des01.tx.buffer1_size = len;
 }
-#endif
-
 #endif /* __DESC_COM_H__ */
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
index 7ad56af..57f4e8f 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
@@ -89,13 +89,46 @@ enum power_event {
 				(reg * 8))
 #define GMAC_MAX_PERFECT_ADDRESSES	32
 
+/* PCS registers (AN/TBI/SGMII/RGMII) offset */
 #define GMAC_AN_CTRL	0x000000c0	/* AN control */
 #define GMAC_AN_STATUS	0x000000c4	/* AN status */
 #define GMAC_ANE_ADV	0x000000c8	/* Auto-Neg. Advertisement */
-#define GMAC_ANE_LINK	0x000000cc	/* Auto-Neg. link partener ability */
+#define GMAC_ANE_LPA	0x000000cc	/* Auto-Neg. link partener ability */
 #define GMAC_ANE_EXP	0x000000d0	/* ANE expansion */
 #define GMAC_TBI	0x000000d4	/* TBI extend status */
-#define GMAC_GMII_STATUS 0x000000d8	/* S/R-GMII status */
+#define GMAC_S_R_GMII	0x000000d8	/* SGMII RGMII status */
+
+/* AN Configuration defines */
+#define GMAC_AN_CTRL_RAN	0x00000200 /* Restart Auto-Negotiation */
+#define GMAC_AN_CTRL_ANE	0x00001000 /* Auto-Negotiation Enable */
+#define GMAC_AN_CTRL_ELE	0x00004000 /* External Loopback Enable */
+#define GMAC_AN_CTRL_ECD	0x00010000 /* Enable Comma Detect */
+#define GMAC_AN_CTRL_LR	0x00020000 /* Lock to Reference */
+#define GMAC_AN_CTRL_SGMRAL	0x00040000 /* SGMII RAL Control */
+
+/* AN Status defines */
+#define GMAC_AN_STATUS_LS	0x00000004 /* Link Status 0:down 1:up */
+#define GMAC_AN_STATUS_ANA	0x00000008 /* Auto-Negotiation Ability */
+#define GMAC_AN_STATUS_ANC	0x00000020 /* Auto-Negotiation Complete */
+#define GMAC_AN_STATUS_ES	0x00000100 /* Extended Status */
+
+/* Register 54 (SGMII/RGMII status register) */
+#define GMAC_S_R_GMII_LINK		0x8
+#define GMAC_S_R_GMII_SPEED		0x5
+#define GMAC_S_R_GMII_SPEED_SHIFT	0x1
+#define GMAC_S_R_GMII_MODE		0x1
+#define GMAC_S_R_GMII_SPEED_125		2
+#define GMAC_S_R_GMII_SPEED_25		1
+
+/* Common ADV and LPA defines */
+#define GMAC_ANE_FD		(1 << 5)
+#define GMAC_ANE_HD		(1 << 6)
+#define GMAC_ANE_PSE		(3 << 7)
+#define GMAC_ANE_PSE_SHIFT	7
+
+ /* GMAC Configuration defines */
+#define GMAC_CONTROL_TC	0x01000000 /* Transmit Conf. in RGMII/SGMII */
+#define GMAC_CONTROL_WD	0x00800000 /* Disable Watchdog on receive */
 
 /* GMAC Configuration defines */
 #define GMAC_CONTROL_TC	0x01000000	/* Transmit Conf. in RGMII/SGMII */
@@ -155,6 +188,7 @@ enum inter_frame_gap {
 /* Programmable burst length (passed thorugh platform)*/
 #define DMA_BUS_MODE_PBL_MASK	0x00003f00	/* Programmable Burst Len */
 #define DMA_BUS_MODE_PBL_SHIFT	8
+#define DMA_BUS_MODE_ATDS	0x00000080	/* Alternate Descriptor Size */
 
 enum rx_tx_priority_ratio {
 	double_ratio = 0x00004000,	/*2:1 */
@@ -230,5 +264,7 @@ enum rtc_control {
 #define GMAC_MMC_TX_INTR   0x108
 #define GMAC_MMC_RX_CSUM_OFFLOAD   0x208
 
+
+
 extern const struct stmmac_dma_ops dwmac1000_dma_ops;
 #endif /* __DWMAC1000_H__ */
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
index bfe0226..29138da 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
@@ -28,6 +28,7 @@
 
 #include <linux/crc32.h>
 #include <linux/slab.h>
+#include <linux/ethtool.h>
 #include <asm/io.h>
 #include "dwmac1000.h"
 
@@ -193,59 +194,91 @@ static void dwmac1000_pmt(void __iomem *ioaddr, unsigned long mode)
 	writel(pmt, ioaddr + GMAC_PMT);
 }
 
-
-static int dwmac1000_irq_status(void __iomem *ioaddr)
+static int dwmac1000_irq_status(void __iomem *ioaddr,
+				struct stmmac_extra_stats *x)
 {
 	u32 intr_status = readl(ioaddr + GMAC_INT_STATUS);
-	int status = 0;
+	int ret = 0;
 
 	/* Not used events (e.g. MMC interrupts) are not handled. */
 	if ((intr_status & mmc_tx_irq)) {
 		CHIP_DBG(KERN_INFO "GMAC: MMC tx interrupt: 0x%08x\n",
 		    readl(ioaddr + GMAC_MMC_TX_INTR));
-		status |= core_mmc_tx_irq;
+		x->mmc_tx_irq_n++;
 	}
 	if (unlikely(intr_status & mmc_rx_irq)) {
 		CHIP_DBG(KERN_INFO "GMAC: MMC rx interrupt: 0x%08x\n",
 		    readl(ioaddr + GMAC_MMC_RX_INTR));
-		status |= core_mmc_rx_irq;
+		x->mmc_rx_irq_n++;
 	}
 	if (unlikely(intr_status & mmc_rx_csum_offload_irq)) {
 		CHIP_DBG(KERN_INFO "GMAC: MMC rx csum offload: 0x%08x\n",
 		    readl(ioaddr + GMAC_MMC_RX_CSUM_OFFLOAD));
-		status |= core_mmc_rx_csum_offload_irq;
+		x->mmc_rx_csum_offload_irq_n++;
 	}
 	if (unlikely(intr_status & pmt_irq)) {
 		CHIP_DBG(KERN_INFO "GMAC: received Magic frame\n");
 		/* clear the PMT bits 5 and 6 by reading the PMT
 		 * status register. */
 		readl(ioaddr + GMAC_PMT);
-		status |= core_irq_receive_pmt_irq;
+		x->irq_receive_pmt_irq_n++;
 	}
 	/* MAC trx/rx EEE LPI entry/exit interrupts */
 	if (intr_status & lpiis_irq) {
 		/* Clean LPI interrupt by reading the Reg 12 */
-		u32 lpi_status = readl(ioaddr + LPI_CTRL_STATUS);
+		ret = readl(ioaddr + LPI_CTRL_STATUS);
 
-		if (lpi_status & LPI_CTRL_STATUS_TLPIEN) {
+		if (ret & LPI_CTRL_STATUS_TLPIEN) {
 			CHIP_DBG(KERN_INFO "GMAC TX entered in LPI\n");
-			status |= core_irq_tx_path_in_lpi_mode;
+			x->irq_tx_path_in_lpi_mode_n++;
 		}
-		if (lpi_status & LPI_CTRL_STATUS_TLPIEX) {
+		if (ret & LPI_CTRL_STATUS_TLPIEX) {
 			CHIP_DBG(KERN_INFO "GMAC TX exit from LPI\n");
-			status |= core_irq_tx_path_exit_lpi_mode;
+			x->irq_tx_path_exit_lpi_mode_n++;
 		}
-		if (lpi_status & LPI_CTRL_STATUS_RLPIEN) {
+		if (ret & LPI_CTRL_STATUS_RLPIEN) {
 			CHIP_DBG(KERN_INFO "GMAC RX entered in LPI\n");
-			status |= core_irq_rx_path_in_lpi_mode;
+			x->irq_rx_path_in_lpi_mode_n++;
 		}
-		if (lpi_status & LPI_CTRL_STATUS_RLPIEX) {
+		if (ret & LPI_CTRL_STATUS_RLPIEX) {
 			CHIP_DBG(KERN_INFO "GMAC RX exit from LPI\n");
-			status |= core_irq_rx_path_exit_lpi_mode;
+			x->irq_rx_path_exit_lpi_mode_n++;
+		}
+	}
+
+	if ((intr_status & pcs_ane_irq) || (intr_status & pcs_link_irq)) {
+		CHIP_DBG(KERN_INFO "GMAC PCS ANE IRQ\n");
+		readl(ioaddr + GMAC_AN_STATUS);
+		x->irq_pcs_ane_n++;
+	}
+	if (intr_status & rgmii_irq) {
+		u32 status  = readl(ioaddr + GMAC_S_R_GMII);
+		CHIP_DBG(KERN_INFO "GMAC RGMII/SGMII interrupt\n");
+		x->irq_rgmii_n++;
+
+		/* Save and dump the link status. */
+		if (status & GMAC_S_R_GMII_LINK) {
+			int speed_value = (status & GMAC_S_R_GMII_SPEED) >>
+					  GMAC_S_R_GMII_SPEED_SHIFT;
+			x->pcs_duplex = (status & GMAC_S_R_GMII_MODE);
+
+			if (speed_value == GMAC_S_R_GMII_SPEED_125)
+				x->pcs_speed = SPEED_1000;
+			else if (speed_value == GMAC_S_R_GMII_SPEED_25)
+				x->pcs_speed = SPEED_100;
+			else
+				x->pcs_speed = SPEED_10;
+
+			x->pcs_link = 1;
+			pr_debug("Link is Up - %d/%s\n", (int) x->pcs_speed,
+				 x->pcs_duplex ? "Full" : "Half");
+		} else {
+			x->pcs_link = 0;
+			pr_debug("Link is Down\n");
 		}
 	}
 
-	return status;
+	return ret;
 }
 
 static void  dwmac1000_set_eee_mode(void __iomem *ioaddr)
@@ -297,6 +330,41 @@ static void  dwmac1000_set_eee_timer(void __iomem *ioaddr, int ls, int tw)
 	writel(value, ioaddr + LPI_TIMER_CTRL);
 }
 
+static void dwmac1000_ctrl_ane(void __iomem *ioaddr, bool restart)
+{
+	u32 value;
+
+	value = readl(ioaddr + GMAC_AN_CTRL);
+	/* auto negotiation enable and External Loopback enable */
+	value = GMAC_AN_CTRL_ANE | GMAC_AN_CTRL_ELE;
+
+	if (restart)
+		value |= GMAC_AN_CTRL_RAN;
+
+	writel(value, ioaddr + GMAC_AN_CTRL);
+}
+
+static void dwmac1000_get_adv(void __iomem *ioaddr, struct rgmii_adv *adv)
+{
+	u32 value = readl(ioaddr + GMAC_ANE_ADV);
+
+	if (value & GMAC_ANE_FD)
+		adv->duplex = DUPLEX_FULL;
+	if (value & GMAC_ANE_HD)
+		adv->duplex |= DUPLEX_HALF;
+
+	adv->pause = (value & GMAC_ANE_PSE) >> GMAC_ANE_PSE_SHIFT;
+
+	value = readl(ioaddr + GMAC_ANE_LPA);
+
+	if (value & GMAC_ANE_FD)
+		adv->lp_duplex = DUPLEX_FULL;
+	if (value & GMAC_ANE_HD)
+		adv->lp_duplex = DUPLEX_HALF;
+
+	adv->lp_pause = (value & GMAC_ANE_PSE) >> GMAC_ANE_PSE_SHIFT;
+}
+
 static const struct stmmac_ops dwmac1000_ops = {
 	.core_init = dwmac1000_core_init,
 	.rx_ipc = dwmac1000_rx_ipc_enable,
@@ -311,6 +379,8 @@ static const struct stmmac_ops dwmac1000_ops = {
 	.reset_eee_mode =  dwmac1000_reset_eee_mode,
 	.set_eee_timer =  dwmac1000_set_eee_timer,
 	.set_eee_pls =  dwmac1000_set_eee_pls,
+	.ctrl_ane = dwmac1000_ctrl_ane,
+	.get_adv = dwmac1000_get_adv,
 };
 
 struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
index bf83c03..f1c4b2c 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
@@ -30,8 +30,8 @@
 #include "dwmac1000.h"
 #include "dwmac_dma.h"
 
-static int dwmac1000_dma_init(void __iomem *ioaddr, int pbl, int fb,
-			      int mb, int burst_len, u32 dma_tx, u32 dma_rx)
+static int dwmac1000_dma_init(void __iomem *ioaddr, int pbl, int fb, int mb,
+			      int burst_len, u32 dma_tx, u32 dma_rx, int atds)
 {
 	u32 value = readl(ioaddr + DMA_BUS_MODE);
 	int limit;
@@ -73,6 +73,10 @@ static int dwmac1000_dma_init(void __iomem *ioaddr, int pbl, int fb,
 #ifdef CONFIG_STMMAC_DA
 	value |= DMA_BUS_MODE_DA;	/* Rx has priority over tx */
 #endif
+
+	if (atds)
+		value |= DMA_BUS_MODE_ATDS;
+
 	writel(value, ioaddr + DMA_BUS_MODE);
 
 	/* In case of GMAC AXI configuration, program the DMA_AXI_BUS_MODE
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
index f83210e..cb86a58 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
@@ -72,7 +72,8 @@ static int dwmac100_rx_ipc_enable(void __iomem *ioaddr)
 	return 0;
 }
 
-static int dwmac100_irq_status(void __iomem *ioaddr)
+static int dwmac100_irq_status(void __iomem *ioaddr,
+			       struct stmmac_extra_stats *x)
 {
 	return 0;
 }
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
index c2b4d55..e979a8b 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
@@ -32,8 +32,8 @@
 #include "dwmac100.h"
 #include "dwmac_dma.h"
 
-static int dwmac100_dma_init(void __iomem *ioaddr, int pbl, int fb,
-			     int mb, int burst_len, u32 dma_tx, u32 dma_rx)
+static int dwmac100_dma_init(void __iomem *ioaddr, int pbl, int fb, int mb,
+			     int burst_len, u32 dma_tx, u32 dma_rx, int atds)
 {
 	u32 value = readl(ioaddr + DMA_BUS_MODE);
 	int limit;
diff --git a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
index 2fc8ef9..0fbc8fa 100644
--- a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
+++ b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
@@ -150,6 +150,57 @@ static int enh_desc_coe_rdes0(int ipc_err, int type, int payload_err)
 	return ret;
 }
 
+static void enh_desc_get_ext_status(void *data, struct stmmac_extra_stats *x,
+				    struct dma_extended_desc *p)
+{
+	if (unlikely(p->basic.des01.erx.rx_mac_addr)) {
+		if (p->des4.erx.ip_hdr_err)
+			x->ip_hdr_err++;
+		if (p->des4.erx.ip_payload_err)
+			x->ip_payload_err++;
+		if (p->des4.erx.ip_csum_bypassed)
+			x->ip_csum_bypassed++;
+		if (p->des4.erx.ipv4_pkt_rcvd)
+			x->ipv4_pkt_rcvd++;
+		if (p->des4.erx.ipv6_pkt_rcvd)
+			x->ipv6_pkt_rcvd++;
+		if (p->des4.erx.msg_type == RDES_EXT_SYNC)
+			x->rx_msg_type_sync++;
+		else if (p->des4.erx.msg_type == RDES_EXT_FOLLOW_UP)
+			x->rx_msg_type_follow_up++;
+		else if (p->des4.erx.msg_type == RDES_EXT_DELAY_REQ)
+			x->rx_msg_type_delay_req++;
+		else if (p->des4.erx.msg_type == RDES_EXT_DELAY_RESP)
+			x->rx_msg_type_delay_resp++;
+		else if (p->des4.erx.msg_type == RDES_EXT_DELAY_REQ)
+			x->rx_msg_type_pdelay_req++;
+		else if (p->des4.erx.msg_type == RDES_EXT_PDELAY_RESP)
+			x->rx_msg_type_pdelay_resp++;
+		else if (p->des4.erx.msg_type == RDES_EXT_PDELAY_FOLLOW_UP)
+			x->rx_msg_type_pdelay_follow_up++;
+		else
+			x->rx_msg_type_ext_no_ptp++;
+		if (p->des4.erx.ptp_frame_type)
+			x->ptp_frame_type++;
+		if (p->des4.erx.ptp_ver)
+			x->ptp_ver++;
+		if (p->des4.erx.timestamp_dropped)
+			x->timestamp_dropped++;
+		if (p->des4.erx.av_pkt_rcvd)
+			x->av_pkt_rcvd++;
+		if (p->des4.erx.av_tagged_pkt_rcvd)
+			x->av_tagged_pkt_rcvd++;
+		if (p->des4.erx.vlan_tag_priority_val)
+			x->vlan_tag_priority_val++;
+		if (p->des4.erx.l3_filter_match)
+			x->l3_filter_match++;
+		if (p->des4.erx.l4_filter_match)
+			x->l4_filter_match++;
+		if (p->des4.erx.l3_l4_filter_no_match)
+			x->l3_l4_filter_no_match++;
+	}
+}
+
 static int enh_desc_get_rx_status(void *data, struct stmmac_extra_stats *x,
 				  struct dma_desc *p)
 {
@@ -198,7 +249,7 @@ static int enh_desc_get_rx_status(void *data, struct stmmac_extra_stats *x,
 	 * At any rate, we need to understand if the CSUM hw computation is ok
 	 * and report this info to the upper layers. */
 	ret = enh_desc_coe_rdes0(p->des01.erx.ipc_csum_error,
-		p->des01.erx.frame_type, p->des01.erx.payload_csum_error);
+		p->des01.erx.frame_type, p->des01.erx.rx_mac_addr);
 
 	if (unlikely(p->des01.erx.dribbling)) {
 		CHIP_DBG(KERN_ERR "GMAC RX: dribbling error\n");
@@ -225,34 +276,32 @@ static int enh_desc_get_rx_status(void *data, struct stmmac_extra_stats *x,
 		x->rx_vlan++;
 	}
 #endif
+
 	return ret;
 }
 
-static void enh_desc_init_rx_desc(struct dma_desc *p, unsigned int ring_size,
-				  int disable_rx_ic)
+static void enh_desc_init_rx_desc(struct dma_desc *p, int disable_rx_ic,
+				  int mode, int end)
 {
-	int i;
-	for (i = 0; i < ring_size; i++) {
-		p->des01.erx.own = 1;
-		p->des01.erx.buffer1_size = BUF_SIZE_8KiB - 1;
+	p->des01.erx.own = 1;
+	p->des01.erx.buffer1_size = BUF_SIZE_8KiB - 1;
 
-		ehn_desc_rx_set_on_ring_chain(p, (i == ring_size - 1));
+	if (mode == STMMAC_CHAIN_MODE)
+		ehn_desc_rx_set_on_chain(p, end);
+	else
+		ehn_desc_rx_set_on_ring(p, end);
 
-		if (disable_rx_ic)
-			p->des01.erx.disable_ic = 1;
-		p++;
-	}
+	if (disable_rx_ic)
+		p->des01.erx.disable_ic = 1;
 }
 
-static void enh_desc_init_tx_desc(struct dma_desc *p, unsigned int ring_size)
+static void enh_desc_init_tx_desc(struct dma_desc *p, int mode, int end)
 {
-	int i;
-
-	for (i = 0; i < ring_size; i++) {
-		p->des01.etx.own = 0;
-		ehn_desc_tx_set_on_ring_chain(p, (i == ring_size - 1));
-		p++;
-	}
+	p->des01.etx.own = 0;
+	if (mode == STMMAC_CHAIN_MODE)
+		ehn_desc_tx_set_on_chain(p, end);
+	else
+		ehn_desc_tx_set_on_ring(p, end);
 }
 
 static int enh_desc_get_tx_owner(struct dma_desc *p)
@@ -280,20 +329,26 @@ static int enh_desc_get_tx_ls(struct dma_desc *p)
 	return p->des01.etx.last_segment;
 }
 
-static void enh_desc_release_tx_desc(struct dma_desc *p)
+static void enh_desc_release_tx_desc(struct dma_desc *p, int mode)
 {
 	int ter = p->des01.etx.end_ring;
 
 	memset(p, 0, offsetof(struct dma_desc, des2));
-	enh_desc_end_tx_desc(p, ter);
+	if (mode == STMMAC_CHAIN_MODE)
+		enh_desc_end_tx_desc_on_chain(p, ter);
+	else
+		enh_desc_end_tx_desc_on_ring(p, ter);
 }
 
 static void enh_desc_prepare_tx_desc(struct dma_desc *p, int is_fs, int len,
-				     int csum_flag)
+				     int csum_flag, int mode)
 {
 	p->des01.etx.first_segment = is_fs;
 
-	enh_set_tx_desc_len(p, len);
+	if (mode == STMMAC_CHAIN_MODE)
+		enh_set_tx_desc_len_on_chain(p, len);
+	else
+		enh_set_tx_desc_len_on_ring(p, len);
 
 	if (likely(csum_flag))
 		p->des01.etx.checksum_insertion = cic_full;
@@ -323,6 +378,49 @@ static int enh_desc_get_rx_frame_len(struct dma_desc *p, int rx_coe_type)
 		return p->des01.erx.frame_length;
 }
 
+static void enh_desc_enable_tx_timestamp(struct dma_desc *p)
+{
+	p->des01.etx.time_stamp_enable = 1;
+}
+
+static int enh_desc_get_tx_timestamp_status(struct dma_desc *p)
+{
+	return p->des01.etx.time_stamp_status;
+}
+
+static u64 enh_desc_get_timestamp(void *desc, u32 ats)
+{
+	u64 ns;
+
+	if (ats) {
+		struct dma_extended_desc *p = (struct dma_extended_desc *)desc;
+		ns = p->des6;
+		/* convert high/sec time stamp value to nanosecond */
+		ns += p->des7 * 1000000000ULL;
+	} else {
+		struct dma_desc *p = (struct dma_desc *)desc;
+		ns = p->des2;
+		ns += p->des3 * 1000000000ULL;
+	}
+
+	return ns;
+}
+
+static int enh_desc_get_rx_timestamp_status(void *desc, u32 ats)
+{
+	if (ats) {
+		struct dma_extended_desc *p = (struct dma_extended_desc *)desc;
+		return p->basic.des01.erx.ipc_csum_error;
+	} else {
+		struct dma_desc *p = (struct dma_desc *)desc;
+		if ((p->des2 == 0xffffffff) && (p->des3 == 0xffffffff))
+			/* timestamp is corrupted, hence don't store it */
+			return 0;
+		else
+			return 1;
+	}
+}
+
 const struct stmmac_desc_ops enh_desc_ops = {
 	.tx_status = enh_desc_get_tx_status,
 	.rx_status = enh_desc_get_rx_status,
@@ -339,4 +437,9 @@ const struct stmmac_desc_ops enh_desc_ops = {
 	.set_tx_owner = enh_desc_set_tx_owner,
 	.set_rx_owner = enh_desc_set_rx_owner,
 	.get_rx_frame_len = enh_desc_get_rx_frame_len,
+	.rx_extended_status = enh_desc_get_ext_status,
+	.enable_tx_timestamp = enh_desc_enable_tx_timestamp,
+	.get_tx_timestamp_status = enh_desc_get_tx_timestamp_status,
+	.get_timestamp = enh_desc_get_timestamp,
+	.get_rx_timestamp_status = enh_desc_get_rx_timestamp_status,
 };
diff --git a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
index 68962c5..7cbcea3 100644
--- a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
+++ b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
@@ -122,30 +122,28 @@ static int ndesc_get_rx_status(void *data, struct stmmac_extra_stats *x,
 	return ret;
 }
 
-static void ndesc_init_rx_desc(struct dma_desc *p, unsigned int ring_size,
-			       int disable_rx_ic)
+static void ndesc_init_rx_desc(struct dma_desc *p, int disable_rx_ic, int mode,
+			       int end)
 {
-	int i;
-	for (i = 0; i < ring_size; i++) {
-		p->des01.rx.own = 1;
-		p->des01.rx.buffer1_size = BUF_SIZE_2KiB - 1;
+	p->des01.rx.own = 1;
+	p->des01.rx.buffer1_size = BUF_SIZE_2KiB - 1;
 
-		ndesc_rx_set_on_ring_chain(p, (i == ring_size - 1));
+	if (mode == STMMAC_CHAIN_MODE)
+		ndesc_rx_set_on_chain(p, end);
+	else
+		ndesc_rx_set_on_ring(p, end);
 
-		if (disable_rx_ic)
-			p->des01.rx.disable_ic = 1;
-		p++;
-	}
+	if (disable_rx_ic)
+		p->des01.rx.disable_ic = 1;
 }
 
-static void ndesc_init_tx_desc(struct dma_desc *p, unsigned int ring_size)
+static void ndesc_init_tx_desc(struct dma_desc *p, int mode, int end)
 {
-	int i;
-	for (i = 0; i < ring_size; i++) {
-		p->des01.tx.own = 0;
-		ndesc_tx_set_on_ring_chain(p, (i == (ring_size - 1)));
-		p++;
-	}
+	p->des01.tx.own = 0;
+	if (mode == STMMAC_CHAIN_MODE)
+		ndesc_tx_set_on_chain(p, end);
+	else
+		ndesc_tx_set_on_ring(p, end);
 }
 
 static int ndesc_get_tx_owner(struct dma_desc *p)
@@ -173,19 +171,25 @@ static int ndesc_get_tx_ls(struct dma_desc *p)
 	return p->des01.tx.last_segment;
 }
 
-static void ndesc_release_tx_desc(struct dma_desc *p)
+static void ndesc_release_tx_desc(struct dma_desc *p, int mode)
 {
 	int ter = p->des01.tx.end_ring;
 
 	memset(p, 0, offsetof(struct dma_desc, des2));
-	ndesc_end_tx_desc(p, ter);
+	if (mode == STMMAC_CHAIN_MODE)
+		ndesc_end_tx_desc_on_chain(p, ter);
+	else
+		ndesc_end_tx_desc_on_ring(p, ter);
 }
 
 static void ndesc_prepare_tx_desc(struct dma_desc *p, int is_fs, int len,
-				  int csum_flag)
+				  int csum_flag, int mode)
 {
 	p->des01.tx.first_segment = is_fs;
-	norm_set_tx_desc_len(p, len);
+	if (mode == STMMAC_CHAIN_MODE)
+		norm_set_tx_desc_len_on_chain(p, len);
+	else
+		norm_set_tx_desc_len_on_ring(p, len);
 
 	if (likely(csum_flag))
 		p->des01.tx.checksum_insertion = cic_full;
@@ -215,6 +219,39 @@ static int ndesc_get_rx_frame_len(struct dma_desc *p, int rx_coe_type)
 		return p->des01.rx.frame_length;
 }
 
+static void ndesc_enable_tx_timestamp(struct dma_desc *p)
+{
+	p->des01.tx.time_stamp_enable = 1;
+}
+
+static int ndesc_get_tx_timestamp_status(struct dma_desc *p)
+{
+	return p->des01.tx.time_stamp_status;
+}
+
+static u64 ndesc_get_timestamp(void *desc, u32 ats)
+{
+	struct dma_desc *p = (struct dma_desc *)desc;
+	u64 ns;
+
+	ns = p->des2;
+	/* convert high/sec time stamp value to nanosecond */
+	ns += p->des3 * 1000000000ULL;
+
+	return ns;
+}
+
+static int ndesc_get_rx_timestamp_status(void *desc, u32 ats)
+{
+	struct dma_desc *p = (struct dma_desc *)desc;
+
+	if ((p->des2 == 0xffffffff) && (p->des3 == 0xffffffff))
+		/* timestamp is corrupted, hence don't store it */
+		return 0;
+	else
+		return 1;
+}
+
 const struct stmmac_desc_ops ndesc_ops = {
 	.tx_status = ndesc_get_tx_status,
 	.rx_status = ndesc_get_rx_status,
@@ -231,4 +268,8 @@ const struct stmmac_desc_ops ndesc_ops = {
 	.set_tx_owner = ndesc_set_tx_owner,
 	.set_rx_owner = ndesc_set_rx_owner,
 	.get_rx_frame_len = ndesc_get_rx_frame_len,
+	.enable_tx_timestamp = ndesc_enable_tx_timestamp,
+	.get_tx_timestamp_status = ndesc_get_tx_timestamp_status,
+	.get_timestamp = ndesc_get_timestamp,
+	.get_rx_timestamp_status = ndesc_get_rx_timestamp_status,
 };
diff --git a/drivers/net/ethernet/stmicro/stmmac/ring_mode.c b/drivers/net/ethernet/stmicro/stmmac/ring_mode.c
index 4b785e1..d0265a7 100644
--- a/drivers/net/ethernet/stmicro/stmmac/ring_mode.c
+++ b/drivers/net/ethernet/stmicro/stmmac/ring_mode.c
@@ -48,25 +48,30 @@ static unsigned int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
 
 		desc->des2 = dma_map_single(priv->device, skb->data,
 					    bmax, DMA_TO_DEVICE);
+		priv->tx_skbuff_dma[entry] = desc->des2;
 		desc->des3 = desc->des2 + BUF_SIZE_4KiB;
-		priv->hw->desc->prepare_tx_desc(desc, 1, bmax,
-						csum);
+		priv->hw->desc->prepare_tx_desc(desc, 1, bmax, csum,
+						STMMAC_RING_MODE);
 		wmb();
 		entry = (++priv->cur_tx) % txsize;
 		desc = priv->dma_tx + entry;
 
 		desc->des2 = dma_map_single(priv->device, skb->data + bmax,
 					    len, DMA_TO_DEVICE);
+		priv->tx_skbuff_dma[entry] = desc->des2;
 		desc->des3 = desc->des2 + BUF_SIZE_4KiB;
-		priv->hw->desc->prepare_tx_desc(desc, 0, len, csum);
+		priv->hw->desc->prepare_tx_desc(desc, 0, len, csum,
+						STMMAC_RING_MODE);
 		wmb();
 		priv->hw->desc->set_tx_owner(desc);
 		priv->tx_skbuff[entry] = NULL;
 	} else {
 		desc->des2 = dma_map_single(priv->device, skb->data,
 					    nopaged_len, DMA_TO_DEVICE);
+		priv->tx_skbuff_dma[entry] = desc->des2;
 		desc->des3 = desc->des2 + BUF_SIZE_4KiB;
-		priv->hw->desc->prepare_tx_desc(desc, 1, nopaged_len, csum);
+		priv->hw->desc->prepare_tx_desc(desc, 1, nopaged_len, csum,
+						STMMAC_RING_MODE);
 	}
 
 	return entry;
@@ -82,27 +87,23 @@ static unsigned int stmmac_is_jumbo_frm(int len, int enh_desc)
 	return ret;
 }
 
-static void stmmac_refill_desc3(int bfsize, struct dma_desc *p)
+static void stmmac_refill_desc3(void *priv_ptr, struct dma_desc *p)
 {
-	/* Fill DES3 in case of RING mode */
-	if (bfsize >= BUF_SIZE_8KiB)
-		p->des3 = p->des2 + BUF_SIZE_8KiB;
-}
+	struct stmmac_priv *priv = (struct stmmac_priv *)priv_ptr;
 
-/* In ring mode we need to fill the desc3 because it is used
- * as buffer */
-static void stmmac_init_desc3(int des3_as_data_buf, struct dma_desc *p)
-{
-	if (unlikely(des3_as_data_buf))
-		p->des3 = p->des2 + BUF_SIZE_8KiB;
+	if (unlikely(priv->plat->has_gmac))
+		/* Fill DES3 in case of RING mode */
+		if (priv->dma_buf_sz >= BUF_SIZE_8KiB)
+			p->des3 = p->des2 + BUF_SIZE_8KiB;
 }
 
-static void stmmac_init_dma_chain(struct dma_desc *des, dma_addr_t phy_addr,
-				  unsigned int size)
+/* In ring mode we need to fill the desc3 because it is used as buffer */
+static void stmmac_init_desc3(struct dma_desc *p)
 {
+	p->des3 = p->des2 + BUF_SIZE_8KiB;
 }
 
-static void stmmac_clean_desc3(struct dma_desc *p)
+static void stmmac_clean_desc3(void *priv_ptr, struct dma_desc *p)
 {
 	if (unlikely(p->des3))
 		p->des3 = 0;
@@ -121,7 +122,6 @@ const struct stmmac_ring_mode_ops ring_mode_ops = {
 	.jumbo_frm = stmmac_jumbo_frm,
 	.refill_desc3 = stmmac_refill_desc3,
 	.init_desc3 = stmmac_init_desc3,
-	.init_dma_chain = stmmac_init_dma_chain,
 	.clean_desc3 = stmmac_clean_desc3,
 	.set_16kib_bfsize = stmmac_set_16kib_bfsize,
 };
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index b05df89..75f997b 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -24,25 +24,29 @@
 #define __STMMAC_H__
 
 #define STMMAC_RESOURCE_NAME   "stmmaceth"
-#define DRV_MODULE_VERSION	"Nov_2012"
+#define DRV_MODULE_VERSION	"March_2013"
 
 #include <linux/clk.h>
 #include <linux/stmmac.h>
 #include <linux/phy.h>
 #include <linux/pci.h>
 #include "common.h"
+#include <linux/ptp_clock_kernel.h>
 
 struct stmmac_priv {
 	/* Frequently used values are kept adjacent for cache effect */
-	struct dma_desc *dma_tx ____cacheline_aligned;
+	struct dma_desc *dma_tx ____cacheline_aligned;	/* Basic TX desc */
+	struct dma_extended_desc *dma_etx;	/* Extended TX descriptor */
 	dma_addr_t dma_tx_phy;
 	struct sk_buff **tx_skbuff;
+	dma_addr_t *tx_skbuff_dma;
 	unsigned int cur_tx;
 	unsigned int dirty_tx;
 	unsigned int dma_tx_size;
 	int tx_coalesce;
 
-	struct dma_desc *dma_rx ;
+	struct dma_desc *dma_rx;		/* Basic RX descriptor */
+	struct dma_extended_desc *dma_erx;	/* Extended RX descriptor */
 	unsigned int cur_rx;
 	unsigned int dirty_rx;
 	struct sk_buff **rx_skbuff;
@@ -93,6 +97,16 @@ struct stmmac_priv {
 	u32 tx_coal_timer;
 	int use_riwt;
 	u32 rx_riwt;
+	unsigned int mode;
+	int extend_desc;
+	int pcs;
+	int hwts_tx_en;
+	int hwts_rx_en;
+	unsigned int default_addend;
+	u32 adv_ts;
+	struct ptp_clock *ptp_clock;
+	struct ptp_clock_info ptp_clock_ops;
+	spinlock_t ptp_lock;
 };
 
 extern int phyaddr;
@@ -102,6 +116,9 @@ extern int stmmac_mdio_register(struct net_device *ndev);
 extern void stmmac_set_ethtool_ops(struct net_device *netdev);
 extern const struct stmmac_desc_ops enh_desc_ops;
 extern const struct stmmac_desc_ops ndesc_ops;
+extern const struct stmmac_hwtimestamp stmmac_ptp;
+extern int stmmac_ptp_register(struct stmmac_priv *priv);
+extern void stmmac_ptp_unregister(struct stmmac_priv *priv);
 int stmmac_freeze(struct net_device *ndev);
 int stmmac_restore(struct net_device *ndev);
 int stmmac_resume(struct net_device *ndev);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
index d1ac39c..c5f9cb8 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
@@ -27,6 +27,7 @@
 #include <linux/interrupt.h>
 #include <linux/mii.h>
 #include <linux/phy.h>
+#include <linux/net_tstamp.h>
 #include <asm/io.h>
 
 #include "stmmac.h"
@@ -108,6 +109,33 @@ static const struct stmmac_stats stmmac_gstrings_stats[] = {
 	STMMAC_STAT(irq_rx_path_in_lpi_mode_n),
 	STMMAC_STAT(irq_rx_path_exit_lpi_mode_n),
 	STMMAC_STAT(phy_eee_wakeup_error_n),
+	/* Extended RDES status */
+	STMMAC_STAT(ip_hdr_err),
+	STMMAC_STAT(ip_payload_err),
+	STMMAC_STAT(ip_csum_bypassed),
+	STMMAC_STAT(ipv4_pkt_rcvd),
+	STMMAC_STAT(ipv6_pkt_rcvd),
+	STMMAC_STAT(rx_msg_type_ext_no_ptp),
+	STMMAC_STAT(rx_msg_type_sync),
+	STMMAC_STAT(rx_msg_type_follow_up),
+	STMMAC_STAT(rx_msg_type_delay_req),
+	STMMAC_STAT(rx_msg_type_delay_resp),
+	STMMAC_STAT(rx_msg_type_pdelay_req),
+	STMMAC_STAT(rx_msg_type_pdelay_resp),
+	STMMAC_STAT(rx_msg_type_pdelay_follow_up),
+	STMMAC_STAT(ptp_frame_type),
+	STMMAC_STAT(ptp_ver),
+	STMMAC_STAT(timestamp_dropped),
+	STMMAC_STAT(av_pkt_rcvd),
+	STMMAC_STAT(av_tagged_pkt_rcvd),
+	STMMAC_STAT(vlan_tag_priority_val),
+	STMMAC_STAT(l3_filter_match),
+	STMMAC_STAT(l4_filter_match),
+	STMMAC_STAT(l3_l4_filter_no_match),
+	/* PCS */
+	STMMAC_STAT(irq_pcs_ane_n),
+	STMMAC_STAT(irq_pcs_link_n),
+	STMMAC_STAT(irq_rgmii_n),
 };
 #define STMMAC_STATS_LEN ARRAY_SIZE(stmmac_gstrings_stats)
 
@@ -219,6 +247,70 @@ static int stmmac_ethtool_getsettings(struct net_device *dev,
 	struct stmmac_priv *priv = netdev_priv(dev);
 	struct phy_device *phy = priv->phydev;
 	int rc;
+
+	if ((priv->pcs & STMMAC_PCS_RGMII) || (priv->pcs & STMMAC_PCS_SGMII)) {
+		struct rgmii_adv adv;
+
+		if (!priv->xstats.pcs_link) {
+			ethtool_cmd_speed_set(cmd, SPEED_UNKNOWN);
+			cmd->duplex = DUPLEX_UNKNOWN;
+			return 0;
+		}
+		cmd->duplex = priv->xstats.pcs_duplex;
+
+		ethtool_cmd_speed_set(cmd, priv->xstats.pcs_speed);
+
+		/* Get and convert ADV/LP_ADV from the HW AN registers */
+		if (priv->hw->mac->get_adv)
+			priv->hw->mac->get_adv(priv->ioaddr, &adv);
+		else
+			return -EOPNOTSUPP;	/* should never happen indeed */
+
+		/* Encoding of PSE bits is defined in 802.3z, 37.2.1.4 */
+
+		if (adv.pause & STMMAC_PCS_PAUSE)
+			cmd->advertising |= ADVERTISED_Pause;
+		if (adv.pause & STMMAC_PCS_ASYM_PAUSE)
+			cmd->advertising |= ADVERTISED_Asym_Pause;
+		if (adv.lp_pause & STMMAC_PCS_PAUSE)
+			cmd->lp_advertising |= ADVERTISED_Pause;
+		if (adv.lp_pause & STMMAC_PCS_ASYM_PAUSE)
+			cmd->lp_advertising |= ADVERTISED_Asym_Pause;
+
+		/* Reg49[3] always set because ANE is always supported */
+		cmd->autoneg = ADVERTISED_Autoneg;
+		cmd->supported |= SUPPORTED_Autoneg;
+		cmd->advertising |= ADVERTISED_Autoneg;
+		cmd->lp_advertising |= ADVERTISED_Autoneg;
+
+		if (adv.duplex) {
+			cmd->supported |= (SUPPORTED_1000baseT_Full |
+					   SUPPORTED_100baseT_Full |
+					   SUPPORTED_10baseT_Full);
+			cmd->advertising |= (ADVERTISED_1000baseT_Full |
+					     ADVERTISED_100baseT_Full |
+					     ADVERTISED_10baseT_Full);
+		} else {
+			cmd->supported |= (SUPPORTED_1000baseT_Half |
+					   SUPPORTED_100baseT_Half |
+					   SUPPORTED_10baseT_Half);
+			cmd->advertising |= (ADVERTISED_1000baseT_Half |
+					     ADVERTISED_100baseT_Half |
+					     ADVERTISED_10baseT_Half);
+		}
+		if (adv.lp_duplex)
+			cmd->lp_advertising |= (ADVERTISED_1000baseT_Full |
+						ADVERTISED_100baseT_Full |
+						ADVERTISED_10baseT_Full);
+		else
+			cmd->lp_advertising |= (ADVERTISED_1000baseT_Half |
+						ADVERTISED_100baseT_Half |
+						ADVERTISED_10baseT_Half);
+		cmd->port = PORT_OTHER;
+
+		return 0;
+	}
+
 	if (phy == NULL) {
 		pr_err("%s: %s: PHY is not registered\n",
 		       __func__, dev->name);
@@ -243,6 +335,30 @@ static int stmmac_ethtool_setsettings(struct net_device *dev,
 	struct phy_device *phy = priv->phydev;
 	int rc;
 
+	if ((priv->pcs & STMMAC_PCS_RGMII) || (priv->pcs & STMMAC_PCS_SGMII)) {
+		u32 mask = ADVERTISED_Autoneg | ADVERTISED_Pause;
+
+		/* Only support ANE */
+		if (cmd->autoneg != AUTONEG_ENABLE)
+			return -EINVAL;
+
+		if (cmd->autoneg == AUTONEG_ENABLE) {
+			mask &= (ADVERTISED_1000baseT_Half |
+			ADVERTISED_1000baseT_Full |
+			ADVERTISED_100baseT_Half |
+			ADVERTISED_100baseT_Full |
+			ADVERTISED_10baseT_Half |
+			ADVERTISED_10baseT_Full);
+
+			spin_lock(&priv->lock);
+			if (priv->hw->mac->ctrl_ane)
+				priv->hw->mac->ctrl_ane(priv->ioaddr, 1);
+			spin_unlock(&priv->lock);
+		}
+
+		return 0;
+	}
+
 	spin_lock(&priv->lock);
 	rc = phy_ethtool_sset(phy, cmd);
 	spin_unlock(&priv->lock);
@@ -312,6 +428,9 @@ stmmac_get_pauseparam(struct net_device *netdev,
 {
 	struct stmmac_priv *priv = netdev_priv(netdev);
 
+	if (priv->pcs)	/* FIXME */
+		return;
+
 	spin_lock(&priv->lock);
 
 	pause->rx_pause = 0;
@@ -335,6 +454,9 @@ stmmac_set_pauseparam(struct net_device *netdev,
 	int new_pause = FLOW_OFF;
 	int ret = 0;
 
+	if (priv->pcs)	/* FIXME */
+		return -EOPNOTSUPP;
+
 	spin_lock(&priv->lock);
 
 	if (pause->rx_pause)
@@ -604,6 +726,38 @@ static int stmmac_set_coalesce(struct net_device *dev,
 	return 0;
 }
 
+static int stmmac_get_ts_info(struct net_device *dev,
+			      struct ethtool_ts_info *info)
+{
+	struct stmmac_priv *priv = netdev_priv(dev);
+
+	if ((priv->hwts_tx_en) && (priv->hwts_rx_en)) {
+
+		info->so_timestamping = SOF_TIMESTAMPING_TX_HARDWARE |
+					SOF_TIMESTAMPING_RX_HARDWARE |
+					SOF_TIMESTAMPING_RAW_HARDWARE;
+
+		if (priv->ptp_clock)
+			info->phc_index = ptp_clock_index(priv->ptp_clock);
+
+		info->tx_types = (1 << HWTSTAMP_TX_OFF) | (1 << HWTSTAMP_TX_ON);
+
+		info->rx_filters = ((1 << HWTSTAMP_FILTER_NONE) |
+				    (1 << HWTSTAMP_FILTER_PTP_V1_L4_EVENT) |
+				    (1 << HWTSTAMP_FILTER_PTP_V1_L4_SYNC) |
+				    (1 << HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ) |
+				    (1 << HWTSTAMP_FILTER_PTP_V2_L4_EVENT) |
+				    (1 << HWTSTAMP_FILTER_PTP_V2_L4_SYNC) |
+				    (1 << HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ) |
+				    (1 << HWTSTAMP_FILTER_PTP_V2_EVENT) |
+				    (1 << HWTSTAMP_FILTER_PTP_V2_SYNC) |
+				    (1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ) |
+				    (1 << HWTSTAMP_FILTER_ALL));
+		return 0;
+	} else
+		return ethtool_op_get_ts_info(dev, info);
+}
+
 static const struct ethtool_ops stmmac_ethtool_ops = {
 	.begin = stmmac_check_if_running,
 	.get_drvinfo = stmmac_ethtool_getdrvinfo,
@@ -623,7 +777,7 @@ static const struct ethtool_ops stmmac_ethtool_ops = {
 	.get_eee = stmmac_ethtool_op_get_eee,
 	.set_eee = stmmac_ethtool_op_set_eee,
 	.get_sset_count	= stmmac_get_sset_count,
-	.get_ts_info = ethtool_op_get_ts_info,
+	.get_ts_info = stmmac_get_ts_info,
 	.get_coalesce = stmmac_get_coalesce,
 	.set_coalesce = stmmac_set_coalesce,
 };
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c
new file mode 100644
index 0000000..def7e75
--- /dev/null
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c
@@ -0,0 +1,148 @@
+/*******************************************************************************
+  Copyright (C) 2013  Vayavya Labs Pvt Ltd
+
+  This implements all the API for managing HW timestamp & PTP.
+
+  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.
+
+  The full GNU General Public License is included in this distribution in
+  the file called "COPYING".
+
+  Author: Rayagond Kokatanur <rayagond@vayavyalabs.com>
+  Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
+*******************************************************************************/
+
+#include <linux/io.h>
+#include <linux/delay.h>
+#include "common.h"
+#include "stmmac_ptp.h"
+
+static void stmmac_config_hw_tstamping(void __iomem *ioaddr, u32 data)
+{
+	writel(data, ioaddr + PTP_TCR);
+}
+
+static void stmmac_config_sub_second_increment(void __iomem *ioaddr)
+{
+	u32 value = readl(ioaddr + PTP_TCR);
+	unsigned long data;
+
+	/* Convert the ptp_clock to nano second
+	 * formula = (1/ptp_clock) * 1000000000
+	 * where, ptp_clock = 50MHz.
+	 */
+	data = (1000000000ULL / 50000000);
+
+	/* 0.465ns accuracy */
+	if (value & PTP_TCR_TSCTRLSSR)
+		data = (data * 100) / 465;
+
+	writel(data, ioaddr + PTP_SSIR);
+}
+
+static int stmmac_init_systime(void __iomem *ioaddr, u32 sec, u32 nsec)
+{
+	int limit;
+	u32 value;
+
+	writel(sec, ioaddr + PTP_STSUR);
+	writel(nsec, ioaddr + PTP_STNSUR);
+	/* issue command to initialize the system time value */
+	value = readl(ioaddr + PTP_TCR);
+	value |= PTP_TCR_TSINIT;
+	writel(value, ioaddr + PTP_TCR);
+
+	/* wait for present system time initialize to complete */
+	limit = 10;
+	while (limit--) {
+		if (!(readl(ioaddr + PTP_TCR) & PTP_TCR_TSINIT))
+			break;
+		mdelay(10);
+	}
+	if (limit < 0)
+		return -EBUSY;
+
+	return 0;
+}
+
+static int stmmac_config_addend(void __iomem *ioaddr, u32 addend)
+{
+	u32 value;
+	int limit;
+
+	writel(addend, ioaddr + PTP_TAR);
+	/* issue command to update the addend value */
+	value = readl(ioaddr + PTP_TCR);
+	value |= PTP_TCR_TSADDREG;
+	writel(value, ioaddr + PTP_TCR);
+
+	/* wait for present addend update to complete */
+	limit = 10;
+	while (limit--) {
+		if (!(readl(ioaddr + PTP_TCR) & PTP_TCR_TSADDREG))
+			break;
+		mdelay(10);
+	}
+	if (limit < 0)
+		return -EBUSY;
+
+	return 0;
+}
+
+static int stmmac_adjust_systime(void __iomem *ioaddr, u32 sec, u32 nsec,
+				 int add_sub)
+{
+	u32 value;
+	int limit;
+
+	writel(sec, ioaddr + PTP_STSUR);
+	writel(((add_sub << PTP_STNSUR_ADDSUB_SHIFT) | nsec),
+		ioaddr + PTP_STNSUR);
+	/* issue command to initialize the system time value */
+	value = readl(ioaddr + PTP_TCR);
+	value |= PTP_TCR_TSUPDT;
+	writel(value, ioaddr + PTP_TCR);
+
+	/* wait for present system time adjust/update to complete */
+	limit = 10;
+	while (limit--) {
+		if (!(readl(ioaddr + PTP_TCR) & PTP_TCR_TSUPDT))
+			break;
+		mdelay(10);
+	}
+	if (limit < 0)
+		return -EBUSY;
+
+	return 0;
+}
+
+static u64 stmmac_get_systime(void __iomem *ioaddr)
+{
+	u64 ns;
+
+	ns = readl(ioaddr + PTP_STNSR);
+	/* convert sec time value to nanosecond */
+	ns += readl(ioaddr + PTP_STSR) * 1000000000ULL;
+
+	return ns;
+}
+
+const struct stmmac_hwtimestamp stmmac_ptp = {
+	.config_hw_tstamping = stmmac_config_hw_tstamping,
+	.init_systime = stmmac_init_systime,
+	.config_sub_second_increment = stmmac_config_sub_second_increment,
+	.config_addend = stmmac_config_addend,
+	.adjust_systime = stmmac_adjust_systime,
+	.get_systime = stmmac_get_systime,
+};
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 39c6c55..6b26d31 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -47,6 +47,8 @@
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
 #endif
+#include <linux/net_tstamp.h>
+#include "stmmac_ptp.h"
 #include "stmmac.h"
 
 #undef STMMAC_DEBUG
@@ -130,6 +132,13 @@ module_param(eee_timer, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(eee_timer, "LPI tx expiration time in msec");
 #define STMMAC_LPI_TIMER(x) (jiffies + msecs_to_jiffies(x))
 
+/* By default the driver will use the ring mode to manage tx and rx descriptors
+ * but passing this value so user can force to use the chain instead of the ring
+ */
+static unsigned int chain_mode;
+module_param(chain_mode, int, S_IRUGO);
+MODULE_PARM_DESC(chain_mode, "To use chain instead of ring mode");
+
 static irqreturn_t stmmac_interrupt(int irq, void *dev_id);
 
 #ifdef CONFIG_STMMAC_DEBUG_FS
@@ -304,6 +313,339 @@ static void stmmac_eee_adjust(struct stmmac_priv *priv)
 		priv->hw->mac->set_eee_pls(priv->ioaddr, priv->phydev->link);
 }
 
+/* stmmac_get_tx_hwtstamp:
+ * @priv : pointer to private device structure.
+ * @entry : descriptor index to be used.
+ * @skb : the socket buffer
+ * Description :
+ * This function will read timestamp from the descriptor & pass it to stack.
+ * and also perform some sanity checks.
+ */
+static void stmmac_get_tx_hwtstamp(struct stmmac_priv *priv,
+				   unsigned int entry,
+				   struct sk_buff *skb)
+{
+	struct skb_shared_hwtstamps shhwtstamp;
+	u64 ns;
+	void *desc = NULL;
+
+	if (!priv->hwts_tx_en)
+		return;
+
+	/* if skb doesn't support hw tstamp */
+	if (likely(!(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)))
+		return;
+
+	if (priv->adv_ts)
+		desc = (priv->dma_etx + entry);
+	else
+		desc = (priv->dma_tx + entry);
+
+	/* check tx tstamp status */
+	if (!priv->hw->desc->get_tx_timestamp_status((struct dma_desc *)desc))
+		return;
+
+	/* get the valid tstamp */
+	ns = priv->hw->desc->get_timestamp(desc, priv->adv_ts);
+
+	memset(&shhwtstamp, 0, sizeof(struct skb_shared_hwtstamps));
+	shhwtstamp.hwtstamp = ns_to_ktime(ns);
+	/* pass tstamp to stack */
+	skb_tstamp_tx(skb, &shhwtstamp);
+
+	return;
+}
+
+/* stmmac_get_rx_hwtstamp:
+ * @priv : pointer to private device structure.
+ * @entry : descriptor index to be used.
+ * @skb : the socket buffer
+ * Description :
+ * This function will read received packet's timestamp from the descriptor
+ * and pass it to stack. It also perform some sanity checks.
+ */
+static void stmmac_get_rx_hwtstamp(struct stmmac_priv *priv,
+				   unsigned int entry,
+				   struct sk_buff *skb)
+{
+	struct skb_shared_hwtstamps *shhwtstamp = NULL;
+	u64 ns;
+	void *desc = NULL;
+
+	if (!priv->hwts_rx_en)
+		return;
+
+	if (priv->adv_ts)
+		desc = (priv->dma_erx + entry);
+	else
+		desc = (priv->dma_rx + entry);
+
+	/* if rx tstamp is not valid */
+	if (!priv->hw->desc->get_rx_timestamp_status(desc, priv->adv_ts))
+		return;
+
+	/* get valid tstamp */
+	ns = priv->hw->desc->get_timestamp(desc, priv->adv_ts);
+	shhwtstamp = skb_hwtstamps(skb);
+	memset(shhwtstamp, 0, sizeof(struct skb_shared_hwtstamps));
+	shhwtstamp->hwtstamp = ns_to_ktime(ns);
+}
+
+/**
+ *  stmmac_hwtstamp_ioctl - control hardware timestamping.
+ *  @dev: device pointer.
+ *  @ifr: An IOCTL specefic structure, that can contain a pointer to
+ *  a proprietary structure used to pass information to the driver.
+ *  Description:
+ *  This function configures the MAC to enable/disable both outgoing(TX)
+ *  and incoming(RX) packets time stamping based on user input.
+ *  Return Value:
+ *  0 on success and an appropriate -ve integer on failure.
+ */
+static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)
+{
+	struct stmmac_priv *priv = netdev_priv(dev);
+	struct hwtstamp_config config;
+	struct timespec now;
+	u64 temp = 0;
+	u32 ptp_v2 = 0;
+	u32 tstamp_all = 0;
+	u32 ptp_over_ipv4_udp = 0;
+	u32 ptp_over_ipv6_udp = 0;
+	u32 ptp_over_ethernet = 0;
+	u32 snap_type_sel = 0;
+	u32 ts_master_en = 0;
+	u32 ts_event_en = 0;
+	u32 value = 0;
+
+	if (!(priv->dma_cap.time_stamp || priv->adv_ts)) {
+		netdev_alert(priv->dev, "No support for HW time stamping\n");
+		priv->hwts_tx_en = 0;
+		priv->hwts_rx_en = 0;
+
+		return -EOPNOTSUPP;
+	}
+
+	if (copy_from_user(&config, ifr->ifr_data,
+		sizeof(struct hwtstamp_config)))
+		return -EFAULT;
+
+	pr_debug("%s config flags:0x%x, tx_type:0x%x, rx_filter:0x%x\n",
+		 __func__, config.flags, config.tx_type, config.rx_filter);
+
+	/* reserved for future extensions */
+	if (config.flags)
+		return -EINVAL;
+
+	switch (config.tx_type) {
+	case HWTSTAMP_TX_OFF:
+		priv->hwts_tx_en = 0;
+		break;
+	case HWTSTAMP_TX_ON:
+		priv->hwts_tx_en = 1;
+		break;
+	default:
+		return -ERANGE;
+	}
+
+	if (priv->adv_ts) {
+		switch (config.rx_filter) {
+		/* time stamp no incoming packet at all */
+		case HWTSTAMP_FILTER_NONE:
+			config.rx_filter = HWTSTAMP_FILTER_NONE;
+			break;
+
+		/* PTP v1, UDP, any kind of event packet */
+		case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
+			config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT;
+			/* take time stamp for all event messages */
+			snap_type_sel = PTP_TCR_SNAPTYPSEL_1;
+
+			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
+			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
+			break;
+
+		/* PTP v1, UDP, Sync packet */
+		case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
+			config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_SYNC;
+			/* take time stamp for SYNC messages only */
+			ts_event_en = PTP_TCR_TSEVNTENA;
+
+			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
+			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
+			break;
+
+		/* PTP v1, UDP, Delay_req packet */
+		case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
+			config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ;
+			/* take time stamp for Delay_Req messages only */
+			ts_master_en = PTP_TCR_TSMSTRENA;
+			ts_event_en = PTP_TCR_TSEVNTENA;
+
+			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
+			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
+			break;
+
+		/* PTP v2, UDP, any kind of event packet */
+		case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
+			config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_EVENT;
+			ptp_v2 = PTP_TCR_TSVER2ENA;
+			/* take time stamp for all event messages */
+			snap_type_sel = PTP_TCR_SNAPTYPSEL_1;
+
+			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
+			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
+			break;
+
+		/* PTP v2, UDP, Sync packet */
+		case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
+			config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_SYNC;
+			ptp_v2 = PTP_TCR_TSVER2ENA;
+			/* take time stamp for SYNC messages only */
+			ts_event_en = PTP_TCR_TSEVNTENA;
+
+			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
+			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
+			break;
+
+		/* PTP v2, UDP, Delay_req packet */
+		case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
+			config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ;
+			ptp_v2 = PTP_TCR_TSVER2ENA;
+			/* take time stamp for Delay_Req messages only */
+			ts_master_en = PTP_TCR_TSMSTRENA;
+			ts_event_en = PTP_TCR_TSEVNTENA;
+
+			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
+			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
+			break;
+
+		/* PTP v2/802.AS1, any layer, any kind of event packet */
+		case HWTSTAMP_FILTER_PTP_V2_EVENT:
+			config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
+			ptp_v2 = PTP_TCR_TSVER2ENA;
+			/* take time stamp for all event messages */
+			snap_type_sel = PTP_TCR_SNAPTYPSEL_1;
+
+			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
+			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
+			ptp_over_ethernet = PTP_TCR_TSIPENA;
+			break;
+
+		/* PTP v2/802.AS1, any layer, Sync packet */
+		case HWTSTAMP_FILTER_PTP_V2_SYNC:
+			config.rx_filter = HWTSTAMP_FILTER_PTP_V2_SYNC;
+			ptp_v2 = PTP_TCR_TSVER2ENA;
+			/* take time stamp for SYNC messages only */
+			ts_event_en = PTP_TCR_TSEVNTENA;
+
+			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
+			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
+			ptp_over_ethernet = PTP_TCR_TSIPENA;
+			break;
+
+		/* PTP v2/802.AS1, any layer, Delay_req packet */
+		case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
+			config.rx_filter = HWTSTAMP_FILTER_PTP_V2_DELAY_REQ;
+			ptp_v2 = PTP_TCR_TSVER2ENA;
+			/* take time stamp for Delay_Req messages only */
+			ts_master_en = PTP_TCR_TSMSTRENA;
+			ts_event_en = PTP_TCR_TSEVNTENA;
+
+			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
+			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
+			ptp_over_ethernet = PTP_TCR_TSIPENA;
+			break;
+
+		/* time stamp any incoming packet */
+		case HWTSTAMP_FILTER_ALL:
+			config.rx_filter = HWTSTAMP_FILTER_ALL;
+			tstamp_all = PTP_TCR_TSENALL;
+			break;
+
+		default:
+			return -ERANGE;
+		}
+	} else {
+		switch (config.rx_filter) {
+		case HWTSTAMP_FILTER_NONE:
+			config.rx_filter = HWTSTAMP_FILTER_NONE;
+			break;
+		default:
+			/* PTP v1, UDP, any kind of event packet */
+			config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT;
+			break;
+		}
+	}
+	priv->hwts_rx_en = ((config.rx_filter == HWTSTAMP_FILTER_NONE) ? 0 : 1);
+
+	if (!priv->hwts_tx_en && !priv->hwts_rx_en)
+		priv->hw->ptp->config_hw_tstamping(priv->ioaddr, 0);
+	else {
+		value = (PTP_TCR_TSENA | PTP_TCR_TSCFUPDT | PTP_TCR_TSCTRLSSR |
+			tstamp_all | ptp_v2 | ptp_over_ethernet |
+			ptp_over_ipv6_udp | ptp_over_ipv4_udp | ts_event_en |
+			ts_master_en | snap_type_sel);
+
+		priv->hw->ptp->config_hw_tstamping(priv->ioaddr, value);
+
+		/* program Sub Second Increment reg */
+		priv->hw->ptp->config_sub_second_increment(priv->ioaddr);
+
+		/* calculate default added value:
+		 * formula is :
+		 * addend = (2^32)/freq_div_ratio;
+		 * where, freq_div_ratio = STMMAC_SYSCLOCK/50MHz
+		 * hence, addend = ((2^32) * 50MHz)/STMMAC_SYSCLOCK;
+		 * NOTE: STMMAC_SYSCLOCK should be >= 50MHz to
+		 *       achive 20ns accuracy.
+		 *
+		 * 2^x * y == (y << x), hence
+		 * 2^32 * 50000000 ==> (50000000 << 32)
+		 */
+		temp = (u64)(50000000ULL << 32);
+		priv->default_addend = div_u64(temp, STMMAC_SYSCLOCK);
+		priv->hw->ptp->config_addend(priv->ioaddr,
+					     priv->default_addend);
+
+		/* initialize system time */
+		getnstimeofday(&now);
+		priv->hw->ptp->init_systime(priv->ioaddr, now.tv_sec,
+					    now.tv_nsec);
+	}
+
+	return copy_to_user(ifr->ifr_data, &config,
+			    sizeof(struct hwtstamp_config)) ? -EFAULT : 0;
+}
+
+static int stmmac_init_ptp(struct stmmac_priv *priv)
+{
+	if (!(priv->dma_cap.time_stamp || priv->dma_cap.atime_stamp))
+		return -EOPNOTSUPP;
+
+	if (netif_msg_hw(priv)) {
+		if (priv->dma_cap.time_stamp) {
+			pr_debug("IEEE 1588-2002 Time Stamp supported\n");
+			priv->adv_ts = 0;
+		}
+		if (priv->dma_cap.atime_stamp && priv->extend_desc) {
+			pr_debug("IEEE 1588-2008 Advanced Time Stamp supported\n");
+			priv->adv_ts = 1;
+		}
+	}
+
+	priv->hw->ptp = &stmmac_ptp;
+	priv->hwts_tx_en = 0;
+	priv->hwts_rx_en = 0;
+
+	return stmmac_ptp_register(priv);
+}
+
+static void stmmac_release_ptp(struct stmmac_priv *priv)
+{
+	stmmac_ptp_unregister(priv);
+}
+
 /**
  * stmmac_adjust_link
  * @dev: net device structure
@@ -398,6 +740,24 @@ static void stmmac_adjust_link(struct net_device *dev)
 	DBG(probe, DEBUG, "stmmac_adjust_link: exiting\n");
 }
 
+static void stmmac_check_pcs_mode(struct stmmac_priv *priv)
+{
+	int interface = priv->plat->interface;
+
+	if (priv->dma_cap.pcs) {
+		if ((interface & PHY_INTERFACE_MODE_RGMII) ||
+		    (interface & PHY_INTERFACE_MODE_RGMII_ID) ||
+		    (interface & PHY_INTERFACE_MODE_RGMII_RXID) ||
+		    (interface & PHY_INTERFACE_MODE_RGMII_TXID)) {
+			pr_debug("STMMAC: PCS RGMII support enable\n");
+			priv->pcs = STMMAC_PCS_RGMII;
+		} else if (interface & PHY_INTERFACE_MODE_SGMII) {
+			pr_debug("STMMAC: PCS SGMII support enable\n");
+			priv->pcs = STMMAC_PCS_SGMII;
+		}
+	}
+}
+
 /**
  * stmmac_init_phy - PHY initialization
  * @dev: net device structure
@@ -461,29 +821,56 @@ static int stmmac_init_phy(struct net_device *dev)
 }
 
 /**
- * display_ring
+ * stmmac_display_ring
  * @p: pointer to the ring.
  * @size: size of the ring.
- * Description: display all the descriptors within the ring.
+ * Description: display the control/status and buffer descriptors.
  */
-static void display_ring(struct dma_desc *p, int size)
+static void stmmac_display_ring(void *head, int size, int extend_desc)
 {
-	struct tmp_s {
-		u64 a;
-		unsigned int b;
-		unsigned int c;
-	};
 	int i;
+	struct dma_extended_desc *ep = (struct dma_extended_desc *) head;
+	struct dma_desc *p = (struct dma_desc *) head;
+
 	for (i = 0; i < size; i++) {
-		struct tmp_s *x = (struct tmp_s *)(p + i);
-		pr_info("\t%d [0x%x]: DES0=0x%x DES1=0x%x BUF1=0x%x BUF2=0x%x",
-		       i, (unsigned int)virt_to_phys(&p[i]),
-		       (unsigned int)(x->a), (unsigned int)((x->a) >> 32),
-		       x->b, x->c);
+		u64 x;
+		if (extend_desc) {
+			x = *(u64 *) ep;
+			pr_info("%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n",
+				i, (unsigned int) virt_to_phys(ep),
+				(unsigned int) x, (unsigned int) (x >> 32),
+				ep->basic.des2, ep->basic.des3);
+			ep++;
+		} else {
+			x = *(u64 *) p;
+			pr_info("%d [0x%x]: 0x%x 0x%x 0x%x 0x%x",
+				i, (unsigned int) virt_to_phys(p),
+				(unsigned int) x, (unsigned int) (x >> 32),
+				p->des2, p->des3);
+			p++;
+		}
 		pr_info("\n");
 	}
 }
 
+static void stmmac_display_rings(struct stmmac_priv *priv)
+{
+	unsigned int txsize = priv->dma_tx_size;
+	unsigned int rxsize = priv->dma_rx_size;
+
+	if (priv->extend_desc) {
+		pr_info("Extended RX descriptor ring:\n");
+		stmmac_display_ring((void *) priv->dma_erx, rxsize, 1);
+		pr_info("Extended TX descriptor ring:\n");
+		stmmac_display_ring((void *) priv->dma_etx, txsize, 1);
+	} else {
+		pr_info("RX descriptor ring:\n");
+		stmmac_display_ring((void *)priv->dma_rx, rxsize, 0);
+		pr_info("TX descriptor ring:\n");
+		stmmac_display_ring((void *)priv->dma_tx, txsize, 0);
+	}
+}
+
 static int stmmac_set_bfsize(int mtu, int bufsize)
 {
 	int ret = bufsize;
@@ -500,6 +887,59 @@ static int stmmac_set_bfsize(int mtu, int bufsize)
 	return ret;
 }
 
+static void stmmac_clear_descriptors(struct stmmac_priv *priv)
+{
+	int i;
+	unsigned int txsize = priv->dma_tx_size;
+	unsigned int rxsize = priv->dma_rx_size;
+
+	/* Clear the Rx/Tx descriptors */
+	for (i = 0; i < rxsize; i++)
+		if (priv->extend_desc)
+			priv->hw->desc->init_rx_desc(&priv->dma_erx[i].basic,
+						     priv->use_riwt, priv->mode,
+						     (i == rxsize - 1));
+		else
+			priv->hw->desc->init_rx_desc(&priv->dma_rx[i],
+						     priv->use_riwt, priv->mode,
+						     (i == rxsize - 1));
+	for (i = 0; i < txsize; i++)
+		if (priv->extend_desc)
+			priv->hw->desc->init_tx_desc(&priv->dma_etx[i].basic,
+						     priv->mode,
+						     (i == txsize - 1));
+		else
+			priv->hw->desc->init_tx_desc(&priv->dma_tx[i],
+						     priv->mode,
+						     (i == txsize - 1));
+}
+
+static int stmmac_init_rx_buffers(struct stmmac_priv *priv, struct dma_desc *p,
+				  int i)
+{
+	struct sk_buff *skb;
+
+	skb = __netdev_alloc_skb(priv->dev, priv->dma_buf_sz + NET_IP_ALIGN,
+				 GFP_KERNEL);
+	if (unlikely(skb == NULL)) {
+		pr_err("%s: Rx init fails; skb is NULL\n", __func__);
+		return 1;
+	}
+	skb_reserve(skb, NET_IP_ALIGN);
+	priv->rx_skbuff[i] = skb;
+	priv->rx_skbuff_dma[i] = dma_map_single(priv->device, skb->data,
+						priv->dma_buf_sz,
+						DMA_FROM_DEVICE);
+
+	p->des2 = priv->rx_skbuff_dma[i];
+
+	if ((priv->mode == STMMAC_RING_MODE) &&
+	    (priv->dma_buf_sz == BUF_SIZE_16KiB))
+		priv->hw->ring->init_desc3(p);
+
+	return 0;
+}
+
 /**
  * init_dma_desc_rings - init the RX/TX descriptor rings
  * @dev: net device structure
@@ -511,75 +951,70 @@ static void init_dma_desc_rings(struct net_device *dev)
 {
 	int i;
 	struct stmmac_priv *priv = netdev_priv(dev);
-	struct sk_buff *skb;
 	unsigned int txsize = priv->dma_tx_size;
 	unsigned int rxsize = priv->dma_rx_size;
-	unsigned int bfsize;
-	int dis_ic = 0;
-	int des3_as_data_buf = 0;
+	unsigned int bfsize = 0;
 
 	/* Set the max buffer size according to the DESC mode
 	 * and the MTU. Note that RING mode allows 16KiB bsize. */
-	bfsize = priv->hw->ring->set_16kib_bfsize(dev->mtu);
+	if (priv->mode == STMMAC_RING_MODE)
+		bfsize = priv->hw->ring->set_16kib_bfsize(dev->mtu);
 
-	if (bfsize == BUF_SIZE_16KiB)
-		des3_as_data_buf = 1;
-	else
+	if (bfsize < BUF_SIZE_16KiB)
 		bfsize = stmmac_set_bfsize(dev->mtu, priv->dma_buf_sz);
 
 	DBG(probe, INFO, "stmmac: txsize %d, rxsize %d, bfsize %d\n",
 	    txsize, rxsize, bfsize);
 
-	priv->rx_skbuff_dma = kmalloc_array(rxsize, sizeof(dma_addr_t),
-					    GFP_KERNEL);
-	priv->rx_skbuff = kmalloc_array(rxsize, sizeof(struct sk_buff *),
-					GFP_KERNEL);
-	priv->dma_rx =
-	    (struct dma_desc *)dma_alloc_coherent(priv->device,
-						  rxsize *
+	if (priv->extend_desc) {
+		priv->dma_erx = dma_alloc_coherent(priv->device, rxsize *
+						   sizeof(struct
+							  dma_extended_desc),
+						   &priv->dma_rx_phy,
+						   GFP_KERNEL);
+		priv->dma_etx = dma_alloc_coherent(priv->device, txsize *
+						   sizeof(struct
+							  dma_extended_desc),
+						   &priv->dma_tx_phy,
+						   GFP_KERNEL);
+		if ((!priv->dma_erx) || (!priv->dma_etx))
+			return;
+	} else {
+		priv->dma_rx = dma_alloc_coherent(priv->device, rxsize *
 						  sizeof(struct dma_desc),
 						  &priv->dma_rx_phy,
 						  GFP_KERNEL);
-	priv->tx_skbuff = kmalloc_array(txsize, sizeof(struct sk_buff *),
-					GFP_KERNEL);
-	priv->dma_tx =
-	    (struct dma_desc *)dma_alloc_coherent(priv->device,
-						  txsize *
+		priv->dma_tx = dma_alloc_coherent(priv->device, txsize *
 						  sizeof(struct dma_desc),
 						  &priv->dma_tx_phy,
 						  GFP_KERNEL);
-
-	if ((priv->dma_rx == NULL) || (priv->dma_tx == NULL)) {
-		pr_err("%s:ERROR allocating the DMA Tx/Rx desc\n", __func__);
-		return;
+		if ((!priv->dma_rx) || (!priv->dma_tx))
+			return;
 	}
 
-	DBG(probe, INFO, "stmmac (%s) DMA desc: virt addr (Rx %p, "
-	    "Tx %p)\n\tDMA phy addr (Rx 0x%08x, Tx 0x%08x)\n",
-	    dev->name, priv->dma_rx, priv->dma_tx,
-	    (unsigned int)priv->dma_rx_phy, (unsigned int)priv->dma_tx_phy);
+	priv->rx_skbuff_dma = kmalloc_array(rxsize, sizeof(dma_addr_t),
+					    GFP_KERNEL);
+	priv->rx_skbuff = kmalloc_array(rxsize, sizeof(struct sk_buff *),
+					GFP_KERNEL);
+	priv->tx_skbuff_dma = kmalloc_array(txsize, sizeof(dma_addr_t),
+					GFP_KERNEL);
+	priv->tx_skbuff = kmalloc_array(txsize, sizeof(struct sk_buff *),
+					GFP_KERNEL);
+	if (netif_msg_drv(priv))
+		pr_debug("(%s) dma_rx_phy=0x%08x dma_tx_phy=0x%08x\n", __func__,
+			 (u32) priv->dma_rx_phy, (u32) priv->dma_tx_phy);
 
 	/* RX INITIALIZATION */
-	DBG(probe, INFO, "stmmac: SKB addresses:\n"
-			 "skb\t\tskb data\tdma data\n");
-
+	DBG(probe, INFO, "stmmac: SKB addresses:\nskb\t\tskb data\tdma data\n");
 	for (i = 0; i < rxsize; i++) {
-		struct dma_desc *p = priv->dma_rx + i;
+		struct dma_desc *p;
+		if (priv->extend_desc)
+			p = &((priv->dma_erx + i)->basic);
+		else
+			p = priv->dma_rx + i;
 
-		skb = __netdev_alloc_skb(dev, bfsize + NET_IP_ALIGN,
-					 GFP_KERNEL);
-		if (unlikely(skb == NULL)) {
-			pr_err("%s: Rx init fails; skb is NULL\n", __func__);
+		if (stmmac_init_rx_buffers(priv, p, i))
 			break;
-		}
-		skb_reserve(skb, NET_IP_ALIGN);
-		priv->rx_skbuff[i] = skb;
-		priv->rx_skbuff_dma[i] = dma_map_single(priv->device, skb->data,
-						bfsize, DMA_FROM_DEVICE);
-
-		p->des2 = priv->rx_skbuff_dma[i];
-
-		priv->hw->ring->init_desc3(des3_as_data_buf, p);
 
 		DBG(probe, INFO, "[%p]\t[%p]\t[%x]\n", priv->rx_skbuff[i],
 			priv->rx_skbuff[i]->data, priv->rx_skbuff_dma[i]);
@@ -589,32 +1024,40 @@ static void init_dma_desc_rings(struct net_device *dev)
 	priv->dma_buf_sz = bfsize;
 	buf_sz = bfsize;
 
+	/* Setup the chained descriptor addresses */
+	if (priv->mode == STMMAC_CHAIN_MODE) {
+		if (priv->extend_desc) {
+			priv->hw->chain->init(priv->dma_erx, priv->dma_rx_phy,
+					      rxsize, 1);
+			priv->hw->chain->init(priv->dma_etx, priv->dma_tx_phy,
+					      txsize, 1);
+		} else {
+			priv->hw->chain->init(priv->dma_rx, priv->dma_rx_phy,
+					      rxsize, 0);
+			priv->hw->chain->init(priv->dma_tx, priv->dma_tx_phy,
+					      txsize, 0);
+		}
+	}
+
 	/* TX INITIALIZATION */
 	for (i = 0; i < txsize; i++) {
+		struct dma_desc *p;
+		if (priv->extend_desc)
+			p = &((priv->dma_etx + i)->basic);
+		else
+			p = priv->dma_tx + i;
+		p->des2 = 0;
+		priv->tx_skbuff_dma[i] = 0;
 		priv->tx_skbuff[i] = NULL;
-		priv->dma_tx[i].des2 = 0;
 	}
 
-	/* In case of Chained mode this sets the des3 to the next
-	 * element in the chain */
-	priv->hw->ring->init_dma_chain(priv->dma_rx, priv->dma_rx_phy, rxsize);
-	priv->hw->ring->init_dma_chain(priv->dma_tx, priv->dma_tx_phy, txsize);
-
 	priv->dirty_tx = 0;
 	priv->cur_tx = 0;
 
-	if (priv->use_riwt)
-		dis_ic = 1;
-	/* Clear the Rx/Tx descriptors */
-	priv->hw->desc->init_rx_desc(priv->dma_rx, rxsize, dis_ic);
-	priv->hw->desc->init_tx_desc(priv->dma_tx, txsize);
+	stmmac_clear_descriptors(priv);
 
-	if (netif_msg_hw(priv)) {
-		pr_info("RX descriptor ring:\n");
-		display_ring(priv->dma_rx, rxsize);
-		pr_info("TX descriptor ring:\n");
-		display_ring(priv->dma_tx, txsize);
-	}
+	if (netif_msg_hw(priv))
+		stmmac_display_rings(priv);
 }
 
 static void dma_free_rx_skbufs(struct stmmac_priv *priv)
@@ -637,13 +1080,20 @@ static void dma_free_tx_skbufs(struct stmmac_priv *priv)
 
 	for (i = 0; i < priv->dma_tx_size; i++) {
 		if (priv->tx_skbuff[i] != NULL) {
-			struct dma_desc *p = priv->dma_tx + i;
-			if (p->des2)
-				dma_unmap_single(priv->device, p->des2,
+			struct dma_desc *p;
+			if (priv->extend_desc)
+				p = &((priv->dma_etx + i)->basic);
+			else
+				p = priv->dma_tx + i;
+
+			if (priv->tx_skbuff_dma[i])
+				dma_unmap_single(priv->device,
+						 priv->tx_skbuff_dma[i],
 						 priv->hw->desc->get_tx_len(p),
 						 DMA_TO_DEVICE);
 			dev_kfree_skb_any(priv->tx_skbuff[i]);
 			priv->tx_skbuff[i] = NULL;
+			priv->tx_skbuff_dma[i] = 0;
 		}
 	}
 }
@@ -656,14 +1106,24 @@ static void free_dma_desc_resources(struct stmmac_priv *priv)
 
 	/* Free the region of consistent memory previously allocated for
 	 * the DMA */
-	dma_free_coherent(priv->device,
-			  priv->dma_tx_size * sizeof(struct dma_desc),
-			  priv->dma_tx, priv->dma_tx_phy);
-	dma_free_coherent(priv->device,
-			  priv->dma_rx_size * sizeof(struct dma_desc),
-			  priv->dma_rx, priv->dma_rx_phy);
+	if (!priv->extend_desc) {
+		dma_free_coherent(priv->device,
+				  priv->dma_tx_size * sizeof(struct dma_desc),
+				  priv->dma_tx, priv->dma_tx_phy);
+		dma_free_coherent(priv->device,
+				  priv->dma_rx_size * sizeof(struct dma_desc),
+				  priv->dma_rx, priv->dma_rx_phy);
+	} else {
+		dma_free_coherent(priv->device, priv->dma_tx_size *
+				  sizeof(struct dma_extended_desc),
+				  priv->dma_etx, priv->dma_tx_phy);
+		dma_free_coherent(priv->device, priv->dma_rx_size *
+				  sizeof(struct dma_extended_desc),
+				  priv->dma_erx, priv->dma_rx_phy);
+	}
 	kfree(priv->rx_skbuff_dma);
 	kfree(priv->rx_skbuff);
+	kfree(priv->tx_skbuff_dma);
 	kfree(priv->tx_skbuff);
 }
 
@@ -708,13 +1168,18 @@ static void stmmac_tx_clean(struct stmmac_priv *priv)
 		int last;
 		unsigned int entry = priv->dirty_tx % txsize;
 		struct sk_buff *skb = priv->tx_skbuff[entry];
-		struct dma_desc *p = priv->dma_tx + entry;
+		struct dma_desc *p;
+
+		if (priv->extend_desc)
+			p = (struct dma_desc *) (priv->dma_etx + entry);
+		else
+			p = priv->dma_tx + entry;
 
 		/* Check if the descriptor is owned by the DMA. */
 		if (priv->hw->desc->get_tx_owner(p))
 			break;
 
-		/* Verify tx error by looking at the last segment */
+		/* Verify tx error by looking at the last segment. */
 		last = priv->hw->desc->get_tx_ls(p);
 		if (likely(last)) {
 			int tx_error =
@@ -726,22 +1191,27 @@ static void stmmac_tx_clean(struct stmmac_priv *priv)
 				priv->xstats.tx_pkt_n++;
 			} else
 				priv->dev->stats.tx_errors++;
+
+			stmmac_get_tx_hwtstamp(priv, entry, skb);
 		}
 		TX_DBG("%s: curr %d, dirty %d\n", __func__,
 			priv->cur_tx, priv->dirty_tx);
 
-		if (likely(p->des2))
-			dma_unmap_single(priv->device, p->des2,
+		if (likely(priv->tx_skbuff_dma[entry])) {
+			dma_unmap_single(priv->device,
+					 priv->tx_skbuff_dma[entry],
 					 priv->hw->desc->get_tx_len(p),
 					 DMA_TO_DEVICE);
-		priv->hw->ring->clean_desc3(p);
+			priv->tx_skbuff_dma[entry] = 0;
+		}
+		priv->hw->ring->clean_desc3(priv, p);
 
 		if (likely(skb != NULL)) {
 			dev_kfree_skb(skb);
 			priv->tx_skbuff[entry] = NULL;
 		}
 
-		priv->hw->desc->release_tx_desc(p);
+		priv->hw->desc->release_tx_desc(p, priv->mode);
 
 		priv->dirty_tx++;
 	}
@@ -782,11 +1252,21 @@ static inline void stmmac_disable_dma_irq(struct stmmac_priv *priv)
  */
 static void stmmac_tx_err(struct stmmac_priv *priv)
 {
+	int i;
+	int txsize = priv->dma_tx_size;
 	netif_stop_queue(priv->dev);
 
 	priv->hw->dma->stop_tx(priv->ioaddr);
 	dma_free_tx_skbufs(priv);
-	priv->hw->desc->init_tx_desc(priv->dma_tx, priv->dma_tx_size);
+	for (i = 0; i < txsize; i++)
+		if (priv->extend_desc)
+			priv->hw->desc->init_tx_desc(&priv->dma_etx[i].basic,
+						     priv->mode,
+						     (i == txsize - 1));
+		else
+			priv->hw->desc->init_tx_desc(&priv->dma_tx[i],
+						     priv->mode,
+						     (i == txsize - 1));
 	priv->dirty_tx = 0;
 	priv->cur_tx = 0;
 	priv->hw->dma->start_tx(priv->ioaddr);
@@ -860,6 +1340,14 @@ static void stmmac_selec_desc_mode(struct stmmac_priv *priv)
 {
 	if (priv->plat->enh_desc) {
 		pr_info(" Enhanced/Alternate descriptors\n");
+
+		/* GMAC older than 3.50 has no extended descriptors */
+		if (priv->synopsys_id >= DWMAC_CORE_3_50) {
+			pr_info("\tEnabled extended descriptors\n");
+			priv->extend_desc = 1;
+		} else
+			pr_warn("Extended descriptors not supported\n");
+
 		priv->hw->desc = &enh_desc_ops;
 	} else {
 		pr_info(" Normal descriptors\n");
@@ -946,6 +1434,7 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv)
 {
 	int pbl = DEFAULT_DMA_PBL, fixed_burst = 0, burst_len = 0;
 	int mixed_burst = 0;
+	int atds = 0;
 
 	/* Some DMA parameters can be passed from the platform;
 	 * in case of these are not passed we keep a default
@@ -957,9 +1446,12 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv)
 		burst_len = priv->plat->dma_cfg->burst_len;
 	}
 
+	if (priv->extend_desc && (priv->mode == STMMAC_RING_MODE))
+		atds = 1;
+
 	return priv->hw->dma->init(priv->ioaddr, pbl, fixed_burst, mixed_burst,
 				   burst_len, priv->dma_tx_phy,
-				   priv->dma_rx_phy);
+				   priv->dma_rx_phy, atds);
 }
 
 /**
@@ -1012,10 +1504,13 @@ static int stmmac_open(struct net_device *dev)
 
 	stmmac_check_ether_addr(priv);
 
-	ret = stmmac_init_phy(dev);
-	if (unlikely(ret)) {
-		pr_err("%s: Cannot attach to PHY (error: %d)\n", __func__, ret);
-		goto open_error;
+	if (!priv->pcs) {
+		ret = stmmac_init_phy(dev);
+		if (ret) {
+			pr_err("%s: Cannot attach to PHY (error: %d)\n",
+			       __func__, ret);
+			goto open_error;
+		}
 	}
 
 	/* Create and initialize the TX/RX descriptors chains. */
@@ -1084,6 +1579,10 @@ static int stmmac_open(struct net_device *dev)
 
 	stmmac_mmc_setup(priv);
 
+	ret = stmmac_init_ptp(priv);
+	if (ret)
+		pr_warn("%s: failed PTP initialisation\n", __func__);
+
 #ifdef CONFIG_STMMAC_DEBUG_FS
 	ret = stmmac_init_fs(dev);
 	if (ret < 0)
@@ -1104,7 +1603,12 @@ static int stmmac_open(struct net_device *dev)
 		phy_start(priv->phydev);
 
 	priv->tx_lpi_timer = STMMAC_DEFAULT_TWT_LS_TIMER;
-	priv->eee_enabled = stmmac_eee_init(priv);
+
+	/* Using PCS we cannot dial with the phy registers at this stage
+	 * so we do not support extra feature like EEE.
+	 */
+	if (!priv->pcs)
+		priv->eee_enabled = stmmac_eee_init(priv);
 
 	stmmac_init_tx_coalesce(priv);
 
@@ -1113,6 +1617,9 @@ static int stmmac_open(struct net_device *dev)
 		priv->hw->dma->rx_watchdog(priv->ioaddr, MAX_DMA_RIWT);
 	}
 
+	if (priv->pcs && priv->hw->mac->ctrl_ane)
+		priv->hw->mac->ctrl_ane(priv->ioaddr, 0);
+
 	napi_enable(&priv->napi);
 	netif_start_queue(dev);
 
@@ -1184,6 +1691,8 @@ static int stmmac_release(struct net_device *dev)
 #endif
 	clk_disable_unprepare(priv->stmmac_clk);
 
+	stmmac_release_ptp(priv);
+
 	return 0;
 }
 
@@ -1198,7 +1707,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
 	struct stmmac_priv *priv = netdev_priv(dev);
 	unsigned int txsize = priv->dma_tx_size;
 	unsigned int entry;
-	int i, csum_insertion = 0;
+	int i, csum_insertion = 0, is_jumbo = 0;
 	int nfrags = skb_shinfo(skb)->nr_frags;
 	struct dma_desc *desc, *first;
 	unsigned int nopaged_len = skb_headlen(skb);
@@ -1233,7 +1742,11 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
 
 	csum_insertion = (skb->ip_summed == CHECKSUM_PARTIAL);
 
-	desc = priv->dma_tx + entry;
+	if (priv->extend_desc)
+		desc = (struct dma_desc *) (priv->dma_etx + entry);
+	else
+		desc = priv->dma_tx + entry;
+
 	first = desc;
 
 #ifdef STMMAC_XMIT_DEBUG
@@ -1244,28 +1757,46 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
 #endif
 	priv->tx_skbuff[entry] = skb;
 
-	if (priv->hw->ring->is_jumbo_frm(skb->len, priv->plat->enh_desc)) {
-		entry = priv->hw->ring->jumbo_frm(priv, skb, csum_insertion);
-		desc = priv->dma_tx + entry;
+	/* To program the descriptors according to the size of the frame */
+	if (priv->mode == STMMAC_RING_MODE) {
+		is_jumbo = priv->hw->ring->is_jumbo_frm(skb->len,
+							priv->plat->enh_desc);
+		if (unlikely(is_jumbo))
+			entry = priv->hw->ring->jumbo_frm(priv, skb,
+							  csum_insertion);
 	} else {
+		is_jumbo = priv->hw->chain->is_jumbo_frm(skb->len,
+							priv->plat->enh_desc);
+		if (unlikely(is_jumbo))
+			entry = priv->hw->chain->jumbo_frm(priv, skb,
+							   csum_insertion);
+	}
+	if (likely(!is_jumbo)) {
 		desc->des2 = dma_map_single(priv->device, skb->data,
 					nopaged_len, DMA_TO_DEVICE);
+		priv->tx_skbuff_dma[entry] = desc->des2;
 		priv->hw->desc->prepare_tx_desc(desc, 1, nopaged_len,
-						csum_insertion);
-	}
+						csum_insertion, priv->mode);
+	} else
+		desc = first;
 
 	for (i = 0; i < nfrags; i++) {
 		const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
 		int len = skb_frag_size(frag);
 
 		entry = (++priv->cur_tx) % txsize;
-		desc = priv->dma_tx + entry;
+		if (priv->extend_desc)
+			desc = (struct dma_desc *) (priv->dma_etx + entry);
+		else
+			desc = priv->dma_tx + entry;
 
 		TX_DBG("\t[entry %d] segment len: %d\n", entry, len);
 		desc->des2 = skb_frag_dma_map(priv->device, frag, 0, len,
 					      DMA_TO_DEVICE);
+		priv->tx_skbuff_dma[entry] = desc->des2;
 		priv->tx_skbuff[entry] = NULL;
-		priv->hw->desc->prepare_tx_desc(desc, 0, len, csum_insertion);
+		priv->hw->desc->prepare_tx_desc(desc, 0, len, csum_insertion,
+						priv->mode);
 		wmb();
 		priv->hw->desc->set_tx_owner(desc);
 		wmb();
@@ -1302,7 +1833,11 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
 		       "first=%p, nfrags=%d\n",
 		       (priv->cur_tx % txsize), (priv->dirty_tx % txsize),
 		       entry, first, nfrags);
-		display_ring(priv->dma_tx, txsize);
+		if (priv->extend_desc)
+			stmmac_display_ring((void *)priv->dma_etx, txsize, 1);
+		else
+			stmmac_display_ring((void *)priv->dma_tx, txsize, 0);
+
 		pr_info(">>> frame to be transmitted: ");
 		print_pkt(skb->data, skb->len);
 	}
@@ -1314,7 +1849,15 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
 
 	dev->stats.tx_bytes += skb->len;
 
-	skb_tx_timestamp(skb);
+	if (unlikely((skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) &&
+		     priv->hwts_tx_en)) {
+		/* declare that device is doing timestamping */
+		skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
+		priv->hw->desc->enable_tx_timestamp(first);
+	}
+
+	if (!priv->hwts_tx_en)
+		skb_tx_timestamp(skb);
 
 	priv->hw->dma->enable_dma_transmission(priv->ioaddr);
 
@@ -1327,10 +1870,16 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv)
 {
 	unsigned int rxsize = priv->dma_rx_size;
 	int bfsize = priv->dma_buf_sz;
-	struct dma_desc *p = priv->dma_rx;
 
 	for (; priv->cur_rx - priv->dirty_rx > 0; priv->dirty_rx++) {
 		unsigned int entry = priv->dirty_rx % rxsize;
+		struct dma_desc *p;
+
+		if (priv->extend_desc)
+			p = (struct dma_desc *) (priv->dma_erx + entry);
+		else
+			p = priv->dma_rx + entry;
+
 		if (likely(priv->rx_skbuff[entry] == NULL)) {
 			struct sk_buff *skb;
 
@@ -1344,15 +1893,14 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv)
 			    dma_map_single(priv->device, skb->data, bfsize,
 					   DMA_FROM_DEVICE);
 
-			(p + entry)->des2 = priv->rx_skbuff_dma[entry];
+			p->des2 = priv->rx_skbuff_dma[entry];
 
-			if (unlikely(priv->plat->has_gmac))
-				priv->hw->ring->refill_desc3(bfsize, p + entry);
+			priv->hw->ring->refill_desc3(priv, p);
 
 			RX_DBG(KERN_INFO "\trefill entry #%d\n", entry);
 		}
 		wmb();
-		priv->hw->desc->set_rx_owner(p + entry);
+		priv->hw->desc->set_rx_owner(p);
 		wmb();
 	}
 }
@@ -1363,33 +1911,61 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit)
 	unsigned int entry = priv->cur_rx % rxsize;
 	unsigned int next_entry;
 	unsigned int count = 0;
-	struct dma_desc *p = priv->dma_rx + entry;
-	struct dma_desc *p_next;
 
 #ifdef STMMAC_RX_DEBUG
 	if (netif_msg_hw(priv)) {
 		pr_debug(">>> stmmac_rx: descriptor ring:\n");
-		display_ring(priv->dma_rx, rxsize);
+		if (priv->extend_desc)
+			stmmac_display_ring((void *) priv->dma_erx, rxsize, 1);
+		else
+			stmmac_display_ring((void *)priv->dma_rx, rxsize, 0);
 	}
 #endif
-	while (!priv->hw->desc->get_rx_owner(p)) {
+	while (count < limit) {
 		int status;
+		struct dma_desc *p, *p_next;
+
+		if (priv->extend_desc)
+			p = (struct dma_desc *) (priv->dma_erx + entry);
+		else
+			p = priv->dma_rx + entry ;
 
-		if (count >= limit)
+		if (priv->hw->desc->get_rx_owner(p))
 			break;
 
 		count++;
 
 		next_entry = (++priv->cur_rx) % rxsize;
-		p_next = priv->dma_rx + next_entry;
+		if (priv->extend_desc)
+			p_next = (struct dma_desc *) (priv->dma_erx +
+						      next_entry);
+		else
+			p_next = priv->dma_rx + next_entry;
+
 		prefetch(p_next);
 
 		/* read the status of the incoming frame */
-		status = (priv->hw->desc->rx_status(&priv->dev->stats,
-						    &priv->xstats, p));
-		if (unlikely(status == discard_frame))
+		status = priv->hw->desc->rx_status(&priv->dev->stats,
+						   &priv->xstats, p);
+		if ((priv->extend_desc) && (priv->hw->desc->rx_extended_status))
+			priv->hw->desc->rx_extended_status(&priv->dev->stats,
+							   &priv->xstats,
+							   priv->dma_erx +
+							   entry);
+		if (unlikely(status == discard_frame)) {
 			priv->dev->stats.rx_errors++;
-		else {
+			if (priv->hwts_rx_en && !priv->extend_desc) {
+				/* DESC2 & DESC3 will be overwitten by device
+				 * with timestamp value, hence reinitialize
+				 * them in stmmac_rx_refill() function so that
+				 * device can reuse it.
+				 */
+				priv->rx_skbuff[entry] = NULL;
+				dma_unmap_single(priv->device,
+					priv->rx_skbuff_dma[entry],
+					priv->dma_buf_sz, DMA_FROM_DEVICE);
+			}
+		} else {
 			struct sk_buff *skb;
 			int frame_len;
 
@@ -1418,6 +1994,8 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit)
 			prefetch(skb->data - NET_IP_ALIGN);
 			priv->rx_skbuff[entry] = NULL;
 
+			stmmac_get_rx_hwtstamp(priv, entry, skb);
+
 			skb_put(skb, frame_len);
 			dma_unmap_single(priv->device,
 					 priv->rx_skbuff_dma[entry],
@@ -1441,7 +2019,6 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit)
 			priv->dev->stats.rx_bytes += frame_len;
 		}
 		entry = next_entry;
-		p = p_next;	/* use prefetched values */
 	}
 
 	stmmac_rx_refill(priv);
@@ -1604,30 +2181,14 @@ static irqreturn_t stmmac_interrupt(int irq, void *dev_id)
 	/* To handle GMAC own interrupts */
 	if (priv->plat->has_gmac) {
 		int status = priv->hw->mac->host_irq_status((void __iomem *)
-							    dev->base_addr);
+							    dev->base_addr,
+							    &priv->xstats);
 		if (unlikely(status)) {
-			if (status & core_mmc_tx_irq)
-				priv->xstats.mmc_tx_irq_n++;
-			if (status & core_mmc_rx_irq)
-				priv->xstats.mmc_rx_irq_n++;
-			if (status & core_mmc_rx_csum_offload_irq)
-				priv->xstats.mmc_rx_csum_offload_irq_n++;
-			if (status & core_irq_receive_pmt_irq)
-				priv->xstats.irq_receive_pmt_irq_n++;
-
 			/* For LPI we need to save the tx status */
-			if (status & core_irq_tx_path_in_lpi_mode) {
-				priv->xstats.irq_tx_path_in_lpi_mode_n++;
+			if (status & CORE_IRQ_TX_PATH_IN_LPI_MODE)
 				priv->tx_path_in_lpi_mode = true;
-			}
-			if (status & core_irq_tx_path_exit_lpi_mode) {
-				priv->xstats.irq_tx_path_exit_lpi_mode_n++;
+			if (status & CORE_IRQ_TX_PATH_EXIT_LPI_MODE)
 				priv->tx_path_in_lpi_mode = false;
-			}
-			if (status & core_irq_rx_path_in_lpi_mode)
-				priv->xstats.irq_rx_path_in_lpi_mode_n++;
-			if (status & core_irq_rx_path_exit_lpi_mode)
-				priv->xstats.irq_rx_path_exit_lpi_mode_n++;
 		}
 	}
 
@@ -1655,21 +2216,30 @@ static void stmmac_poll_controller(struct net_device *dev)
  *  a proprietary structure used to pass information to the driver.
  *  @cmd: IOCTL command
  *  Description:
- *  Currently there are no special functionality supported in IOCTL, just the
- *  phy_mii_ioctl(...) can be invoked.
+ *  Currently it supports just the phy_mii_ioctl(...) and HW time stamping.
  */
 static int stmmac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
 	struct stmmac_priv *priv = netdev_priv(dev);
-	int ret;
+	int ret = -EOPNOTSUPP;
 
 	if (!netif_running(dev))
 		return -EINVAL;
 
-	if (!priv->phydev)
-		return -EINVAL;
-
-	ret = phy_mii_ioctl(priv->phydev, rq, cmd);
+	switch (cmd) {
+	case SIOCGMIIPHY:
+	case SIOCGMIIREG:
+	case SIOCSMIIREG:
+		if (!priv->phydev)
+			return -EINVAL;
+		ret = phy_mii_ioctl(priv->phydev, rq, cmd);
+		break;
+	case SIOCSHWTSTAMP:
+		ret = stmmac_hwtstamp_ioctl(dev, rq);
+		break;
+	default:
+		break;
+	}
 
 	return ret;
 }
@@ -1679,40 +2249,51 @@ static struct dentry *stmmac_fs_dir;
 static struct dentry *stmmac_rings_status;
 static struct dentry *stmmac_dma_cap;
 
-static int stmmac_sysfs_ring_read(struct seq_file *seq, void *v)
+static void sysfs_display_ring(void *head, int size, int extend_desc,
+				struct seq_file *seq)
 {
-	struct tmp_s {
-		u64 a;
-		unsigned int b;
-		unsigned int c;
-	};
 	int i;
-	struct net_device *dev = seq->private;
-	struct stmmac_priv *priv = netdev_priv(dev);
-
-	seq_printf(seq, "=======================\n");
-	seq_printf(seq, " RX descriptor ring\n");
-	seq_printf(seq, "=======================\n");
+	struct dma_extended_desc *ep = (struct dma_extended_desc *) head;
+	struct dma_desc *p = (struct dma_desc *) head;
 
-	for (i = 0; i < priv->dma_rx_size; i++) {
-		struct tmp_s *x = (struct tmp_s *)(priv->dma_rx + i);
-		seq_printf(seq, "[%d] DES0=0x%x DES1=0x%x BUF1=0x%x BUF2=0x%x",
-			   i, (unsigned int)(x->a),
-			   (unsigned int)((x->a) >> 32), x->b, x->c);
+	for (i = 0; i < size; i++) {
+		u64 x;
+		if (extend_desc) {
+			x = *(u64 *) ep;
+			seq_printf(seq, "%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n",
+				   i, (unsigned int) virt_to_phys(ep),
+				   (unsigned int) x, (unsigned int) (x >> 32),
+				   ep->basic.des2, ep->basic.des3);
+			ep++;
+		} else {
+			x = *(u64 *) p;
+			seq_printf(seq, "%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n",
+				   i, (unsigned int) virt_to_phys(ep),
+				   (unsigned int) x, (unsigned int) (x >> 32),
+				   p->des2, p->des3);
+			p++;
+		}
 		seq_printf(seq, "\n");
 	}
+}
 
-	seq_printf(seq, "\n");
-	seq_printf(seq, "=======================\n");
-	seq_printf(seq, "  TX descriptor ring\n");
-	seq_printf(seq, "=======================\n");
+static int stmmac_sysfs_ring_read(struct seq_file *seq, void *v)
+{
+	struct net_device *dev = seq->private;
+	struct stmmac_priv *priv = netdev_priv(dev);
+	unsigned int txsize = priv->dma_tx_size;
+	unsigned int rxsize = priv->dma_rx_size;
 
-	for (i = 0; i < priv->dma_tx_size; i++) {
-		struct tmp_s *x = (struct tmp_s *)(priv->dma_tx + i);
-		seq_printf(seq, "[%d] DES0=0x%x DES1=0x%x BUF1=0x%x BUF2=0x%x",
-			   i, (unsigned int)(x->a),
-			   (unsigned int)((x->a) >> 32), x->b, x->c);
-		seq_printf(seq, "\n");
+	if (priv->extend_desc) {
+		seq_printf(seq, "Extended RX descriptor ring:\n");
+		sysfs_display_ring((void *) priv->dma_erx, rxsize, 1, seq);
+		seq_printf(seq, "Extended TX descriptor ring:\n");
+		sysfs_display_ring((void *) priv->dma_etx, txsize, 1, seq);
+	} else {
+		seq_printf(seq, "RX descriptor ring:\n");
+		sysfs_display_ring((void *)priv->dma_rx, rxsize, 0, seq);
+		seq_printf(seq, "TX descriptor ring:\n");
+		sysfs_display_ring((void *)priv->dma_tx, txsize, 0, seq);
 	}
 
 	return 0;
@@ -1877,7 +2458,7 @@ static const struct net_device_ops stmmac_netdev_ops = {
  */
 static int stmmac_hw_init(struct stmmac_priv *priv)
 {
-	int ret = 0;
+	int ret;
 	struct mac_device_info *mac;
 
 	/* Identify the MAC HW device */
@@ -1892,12 +2473,23 @@ static int stmmac_hw_init(struct stmmac_priv *priv)
 
 	priv->hw = mac;
 
-	/* To use the chained or ring mode */
-	priv->hw->ring = &ring_mode_ops;
-
 	/* Get and dump the chip ID */
 	priv->synopsys_id = stmmac_get_synopsys_id(priv);
 
+	/* To use alternate (extended) or normal descriptor structures */
+	stmmac_selec_desc_mode(priv);
+
+	/* To use the chained or ring mode */
+	if (chain_mode)	{
+		priv->hw->chain = &chain_mode_ops;
+		pr_info(" Chain mode enabled\n");
+		priv->mode = STMMAC_CHAIN_MODE;
+	} else {
+		priv->hw->ring = &ring_mode_ops;
+		pr_info(" Ring mode enabled\n");
+		priv->mode = STMMAC_RING_MODE;
+	}
+
 	/* Get the HW capability (new GMAC newer than 3.50a) */
 	priv->hw_cap_support = stmmac_get_hw_features(priv);
 	if (priv->hw_cap_support) {
@@ -1921,9 +2513,6 @@ static int stmmac_hw_init(struct stmmac_priv *priv)
 	} else
 		pr_info(" No HW DMA feature register supported");
 
-	/* Select the enhnaced/normal descriptor structures */
-	stmmac_selec_desc_mode(priv);
-
 	/* Enable the IPC (Checksum Offload) and check if the feature has been
 	 * enabled during the core configuration. */
 	ret = priv->hw->mac->rx_ipc(priv->ioaddr);
@@ -1943,7 +2532,7 @@ static int stmmac_hw_init(struct stmmac_priv *priv)
 		device_set_wakeup_capable(priv->device, 1);
 	}
 
-	return ret;
+	return 0;
 }
 
 /**
@@ -1989,7 +2578,9 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device,
 		priv->plat->phy_addr = phyaddr;
 
 	/* Init MAC and get the capabilities */
-	stmmac_hw_init(priv);
+	ret = stmmac_hw_init(priv);
+	if (ret)
+		goto error_free_netdev;
 
 	ndev->netdev_ops = &stmmac_netdev_ops;
 
@@ -2044,12 +2635,16 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device,
 	else
 		priv->clk_csr = priv->plat->clk_csr;
 
-	/* MDIO bus Registration */
-	ret = stmmac_mdio_register(ndev);
-	if (ret < 0) {
-		pr_debug("%s: MDIO bus (id: %d) registration failed",
-			 __func__, priv->plat->bus_id);
-		goto error_mdio_register;
+	stmmac_check_pcs_mode(priv);
+
+	if (!priv->pcs) {
+		/* MDIO bus Registration */
+		ret = stmmac_mdio_register(ndev);
+		if (ret < 0) {
+			pr_debug("%s: MDIO bus (id: %d) registration failed",
+				 __func__, priv->plat->bus_id);
+			goto error_mdio_register;
+		}
 	}
 
 	return priv;
@@ -2060,6 +2655,7 @@ error_clk_get:
 	unregister_netdev(ndev);
 error_netdev_register:
 	netif_napi_del(&priv->napi);
+error_free_netdev:
 	free_netdev(ndev);
 
 	return NULL;
@@ -2081,7 +2677,8 @@ int stmmac_dvr_remove(struct net_device *ndev)
 	priv->hw->dma->stop_tx(priv->ioaddr);
 
 	stmmac_set_mac(priv->ioaddr, false);
-	stmmac_mdio_unregister(ndev);
+	if (!priv->pcs)
+		stmmac_mdio_unregister(ndev);
 	netif_carrier_off(ndev);
 	unregister_netdev(ndev);
 	free_netdev(ndev);
@@ -2093,7 +2690,6 @@ int stmmac_dvr_remove(struct net_device *ndev)
 int stmmac_suspend(struct net_device *ndev)
 {
 	struct stmmac_priv *priv = netdev_priv(ndev);
-	int dis_ic = 0;
 	unsigned long flags;
 
 	if (!ndev || !netif_running(ndev))
@@ -2107,18 +2703,13 @@ int stmmac_suspend(struct net_device *ndev)
 	netif_device_detach(ndev);
 	netif_stop_queue(ndev);
 
-	if (priv->use_riwt)
-		dis_ic = 1;
-
 	napi_disable(&priv->napi);
 
 	/* Stop TX/RX DMA */
 	priv->hw->dma->stop_tx(priv->ioaddr);
 	priv->hw->dma->stop_rx(priv->ioaddr);
-	/* Clear the Rx/Tx descriptors */
-	priv->hw->desc->init_rx_desc(priv->dma_rx, priv->dma_rx_size,
-				     dis_ic);
-	priv->hw->desc->init_tx_desc(priv->dma_tx, priv->dma_tx_size);
+
+	stmmac_clear_descriptors(priv);
 
 	/* Enable Power down mode by programming the PMT regs */
 	if (device_may_wakeup(priv->device))
@@ -2257,6 +2848,9 @@ static int __init stmmac_cmdline_opt(char *str)
 		} else if (!strncmp(opt, "eee_timer:", 10)) {
 			if (kstrtoint(opt + 10, 0, &eee_timer))
 				goto err;
+		} else if (!strncmp(opt, "chain_mode:", 11)) {
+			if (kstrtoint(opt + 11, 0, &chain_mode))
+				goto err;
 		}
 	}
 	return 0;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c
new file mode 100644
index 0000000..93d4bef
--- /dev/null
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c
@@ -0,0 +1,215 @@
+/*******************************************************************************
+  PTP 1588 clock using the STMMAC.
+
+  Copyright (C) 2013  Vayavya Labs Pvt Ltd
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms and conditions of the GNU General Public License,
+  version 2, as published by the Free Software Foundation.
+
+  This program is distributed in the hope it will be useful, but WITHOUT
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+  more details.
+
+  You should have received a copy of the GNU General Public License along with
+  this program; if not, write to the Free Software Foundation, Inc.,
+  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+
+  The full GNU General Public License is included in this distribution in
+  the file called "COPYING".
+
+  Author: Rayagond Kokatanur <rayagond@vayavyalabs.com>
+*******************************************************************************/
+#include "stmmac.h"
+#include "stmmac_ptp.h"
+
+/**
+ * stmmac_adjust_freq
+ *
+ * @ptp: pointer to ptp_clock_info structure
+ * @ppb: desired period change in parts ber billion
+ *
+ * Description: this function will adjust the frequency of hardware clock.
+ */
+static int stmmac_adjust_freq(struct ptp_clock_info *ptp, s32 ppb)
+{
+	struct stmmac_priv *priv =
+	    container_of(ptp, struct stmmac_priv, ptp_clock_ops);
+	unsigned long flags;
+	u32 diff, addend;
+	int neg_adj = 0;
+	u64 adj;
+
+	if (ppb < 0) {
+		neg_adj = 1;
+		ppb = -ppb;
+	}
+
+	addend = priv->default_addend;
+	adj = addend;
+	adj *= ppb;
+	diff = div_u64(adj, 1000000000ULL);
+	addend = neg_adj ? (addend - diff) : (addend + diff);
+
+	spin_lock_irqsave(&priv->ptp_lock, flags);
+
+	priv->hw->ptp->config_addend(priv->ioaddr, addend);
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	return 0;
+}
+
+/**
+ * stmmac_adjust_time
+ *
+ * @ptp: pointer to ptp_clock_info structure
+ * @delta: desired change in nanoseconds
+ *
+ * Description: this function will shift/adjust the hardware clock time.
+ */
+static int stmmac_adjust_time(struct ptp_clock_info *ptp, s64 delta)
+{
+	struct stmmac_priv *priv =
+	    container_of(ptp, struct stmmac_priv, ptp_clock_ops);
+	unsigned long flags;
+	u32 sec, nsec;
+	u32 quotient, reminder;
+	int neg_adj = 0;
+
+	if (delta < 0) {
+		neg_adj = 1;
+		delta = -delta;
+	}
+
+	quotient = div_u64_rem(delta, 1000000000ULL, &reminder);
+	sec = quotient;
+	nsec = reminder;
+
+	spin_lock_irqsave(&priv->ptp_lock, flags);
+
+	priv->hw->ptp->adjust_systime(priv->ioaddr, sec, nsec, neg_adj);
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	return 0;
+}
+
+/**
+ * stmmac_get_time
+ *
+ * @ptp: pointer to ptp_clock_info structure
+ * @ts: pointer to hold time/result
+ *
+ * Description: this function will read the current time from the
+ * hardware clock and store it in @ts.
+ */
+static int stmmac_get_time(struct ptp_clock_info *ptp, struct timespec *ts)
+{
+	struct stmmac_priv *priv =
+	    container_of(ptp, struct stmmac_priv, ptp_clock_ops);
+	unsigned long flags;
+	u64 ns;
+	u32 reminder;
+
+	spin_lock_irqsave(&priv->ptp_lock, flags);
+
+	ns = priv->hw->ptp->get_systime(priv->ioaddr);
+
+	spin_unlock_irqrestore(&priv->ptp_lock, flags);
+
+	ts->tv_sec = div_u64_rem(ns, 1000000000ULL, &reminder);
+	ts->tv_nsec = reminder;
+
+	return 0;
+}
+
+/**
+ * stmmac_set_time
+ *
+ * @ptp: pointer to ptp_clock_info structure
+ * @ts: time value to set
+ *
+ * Description: this function will set the current time on the
+ * hardware clock.
+ */
+static int stmmac_set_time(struct ptp_clock_info *ptp,
+			   const struct timespec *ts)
+{
+	struct stmmac_priv *priv =
+	    container_of(ptp, struct stmmac_priv, ptp_clock_ops);
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->ptp_lock, flags);
+
+	priv->hw->ptp->init_systime(priv->ioaddr, ts->tv_sec, ts->tv_nsec);
+
+	spin_unlock_irqrestore(&priv->ptp_lock, flags);
+
+	return 0;
+}
+
+static int stmmac_enable(struct ptp_clock_info *ptp,
+			 struct ptp_clock_request *rq, int on)
+{
+	return -EOPNOTSUPP;
+}
+
+/* structure describing a PTP hardware clock */
+static struct ptp_clock_info stmmac_ptp_clock_ops = {
+	.owner = THIS_MODULE,
+	.name = "stmmac_ptp_clock",
+	.max_adj = 62500000,
+	.n_alarm = 0,
+	.n_ext_ts = 0,
+	.n_per_out = 0,
+	.pps = 0,
+	.adjfreq = stmmac_adjust_freq,
+	.adjtime = stmmac_adjust_time,
+	.gettime = stmmac_get_time,
+	.settime = stmmac_set_time,
+	.enable = stmmac_enable,
+};
+
+/**
+ * stmmac_ptp_register
+ *
+ * @ndev: net device pointer
+ *
+ * Description: this function will register the ptp clock driver
+ * to kernel. It also does some house keeping work.
+ */
+int stmmac_ptp_register(struct stmmac_priv *priv)
+{
+	spin_lock_init(&priv->ptp_lock);
+	priv->ptp_clock_ops = stmmac_ptp_clock_ops;
+
+	priv->ptp_clock = ptp_clock_register(&priv->ptp_clock_ops,
+					     priv->device);
+	if (IS_ERR(priv->ptp_clock)) {
+		priv->ptp_clock = NULL;
+		pr_err("ptp_clock_register() failed on %s\n", priv->dev->name);
+	} else
+		pr_debug("Added PTP HW clock successfully on %s\n",
+			 priv->dev->name);
+
+	return 0;
+}
+
+/**
+ * stmmac_ptp_unregister
+ *
+ * @ndev: net device pointer
+ *
+ * Description: this function will remove/unregister the ptp clock driver
+ * from the kernel.
+ */
+void stmmac_ptp_unregister(struct stmmac_priv *priv)
+{
+	if (priv->ptp_clock) {
+		ptp_clock_unregister(priv->ptp_clock);
+		pr_debug("Removed PTP HW clock successfully on %s\n",
+			 priv->dev->name);
+	}
+}
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h
new file mode 100644
index 0000000..3dbc047
--- /dev/null
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h
@@ -0,0 +1,74 @@
+/******************************************************************************
+  PTP Header file
+
+  Copyright (C) 2013  Vayavya Labs Pvt Ltd
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms and conditions of the GNU General Public License,
+  version 2, as published by the Free Software Foundation.
+
+  This program is distributed in the hope it will be useful, but WITHOUT
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+  more details.
+
+  You should have received a copy of the GNU General Public License along with
+  this program; if not, write to the Free Software Foundation, Inc.,
+  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+
+  The full GNU General Public License is included in this distribution in
+  the file called "COPYING".
+
+  Author: Rayagond Kokatanur <rayagond@vayavyalabs.com>
+******************************************************************************/
+
+#ifndef __STMMAC_PTP_H__
+#define __STMMAC_PTP_H__
+
+#define STMMAC_SYSCLOCK 62500000
+
+/* IEEE 1588 PTP register offsets */
+#define PTP_TCR		0x0700	/* Timestamp Control Reg */
+#define PTP_SSIR	0x0704	/* Sub-Second Increment Reg */
+#define PTP_STSR	0x0708	/* System Time – Seconds Regr */
+#define PTP_STNSR	0x070C	/* System Time – Nanoseconds Reg */
+#define PTP_STSUR	0x0710	/* System Time – Seconds Update Reg */
+#define PTP_STNSUR	0x0714	/* System Time – Nanoseconds Update Reg */
+#define PTP_TAR		0x0718	/* Timestamp Addend Reg */
+#define PTP_TTSR	0x071C	/* Target Time Seconds Reg */
+#define PTP_TTNSR	0x0720	/* Target Time Nanoseconds Reg */
+#define	PTP_STHWSR	0x0724	/* System Time - Higher Word Seconds Reg */
+#define PTP_TSR		0x0728	/* Timestamp Status */
+
+#define PTP_STNSUR_ADDSUB_SHIFT 31
+
+/* PTP TCR defines */
+#define PTP_TCR_TSENA		0x00000001 /* Timestamp Enable */
+#define PTP_TCR_TSCFUPDT	0x00000002 /* Timestamp Fine/Coarse Update */
+#define PTP_TCR_TSINIT		0x00000004 /* Timestamp Initialize */
+#define PTP_TCR_TSUPDT		0x00000008 /* Timestamp Update */
+/* Timestamp Interrupt Trigger Enable */
+#define PTP_TCR_TSTRIG		0x00000010
+#define PTP_TCR_TSADDREG	0x00000020 /* Addend Reg Update */
+#define PTP_TCR_TSENALL		0x00000100 /* Enable Timestamp for All Frames */
+/* Timestamp Digital or Binary Rollover Control */
+#define PTP_TCR_TSCTRLSSR	0x00000200
+
+/* Enable PTP packet Processing for Version 2 Format */
+#define PTP_TCR_TSVER2ENA	0x00000400
+/* Enable Processing of PTP over Ethernet Frames */
+#define PTP_TCR_TSIPENA		0x00000800
+/* Enable Processing of PTP Frames Sent over IPv6-UDP */
+#define PTP_TCR_TSIPV6ENA	0x00001000
+/* Enable Processing of PTP Frames Sent over IPv4-UDP */
+#define PTP_TCR_TSIPV4ENA	0x00002000
+/* Enable Timestamp Snapshot for Event Messages */
+#define PTP_TCR_TSEVNTENA	0x00004000
+/* Enable Snapshot for Messages Relevant to Master */
+#define PTP_TCR_TSMSTRENA	0x00008000
+/* Select PTP packets for Taking Snapshots */
+#define PTP_TCR_SNAPTYPSEL_1	0x00010000
+/* Enable MAC address for PTP Frame Filtering */
+#define PTP_TCR_TSENMACADDR	0x00040000
+
+#endif /* __STMMAC_PTP_H__ */
diff --git a/drivers/net/ethernet/sun/niu.c b/drivers/net/ethernet/sun/niu.c
index e4c1c88..95cff98 100644
--- a/drivers/net/ethernet/sun/niu.c
+++ b/drivers/net/ethernet/sun/niu.c
@@ -6618,7 +6618,7 @@ static u64 niu_compute_tx_flags(struct sk_buff *skb, struct ethhdr *ehdr,
 	       (len << TXHDR_LEN_SHIFT) |
 	       ((l3off / 2) << TXHDR_L3START_SHIFT) |
 	       (ihl << TXHDR_IHL_SHIFT) |
-	       ((eth_proto_inner < 1536) ? TXHDR_LLC : 0) |
+	       ((eth_proto_inner < ETH_P_802_3_MIN) ? TXHDR_LLC : 0) |
 	       ((eth_proto == ETH_P_8021Q) ? TXHDR_VLAN : 0) |
 	       (ipv6 ? TXHDR_IP_VER : 0) |
 	       csum_bits);
diff --git a/drivers/net/ethernet/sun/sunbmac.c b/drivers/net/ethernet/sun/sunbmac.c
index 5fafca0..0549759 100644
--- a/drivers/net/ethernet/sun/sunbmac.c
+++ b/drivers/net/ethernet/sun/sunbmac.c
@@ -1169,10 +1169,8 @@ static int bigmac_ether_init(struct platform_device *op,
 	bp->bmac_block = dma_alloc_coherent(&bp->bigmac_op->dev,
 					    PAGE_SIZE,
 					    &bp->bblock_dvma, GFP_ATOMIC);
-	if (bp->bmac_block == NULL || bp->bblock_dvma == 0) {
-		printk(KERN_ERR "BIGMAC: Cannot allocate consistent DMA.\n");
+	if (bp->bmac_block == NULL || bp->bblock_dvma == 0)
 		goto fail_and_cleanup;
-	}
 
 	/* Get the board revision of this BigMAC. */
 	bp->board_rev = of_getintprop_default(bp->bigmac_op->dev.of_node,
diff --git a/drivers/net/ethernet/sun/sunhme.c b/drivers/net/ethernet/sun/sunhme.c
index a1bff49..436fa9d 100644
--- a/drivers/net/ethernet/sun/sunhme.c
+++ b/drivers/net/ethernet/sun/sunhme.c
@@ -2752,10 +2752,8 @@ static int happy_meal_sbus_probe_one(struct platform_device *op, int is_qfe)
 					     &hp->hblock_dvma,
 					     GFP_ATOMIC);
 	err = -ENOMEM;
-	if (!hp->happy_block) {
-		printk(KERN_ERR "happymeal: Cannot allocate descriptors.\n");
+	if (!hp->happy_block)
 		goto err_out_iounmap;
-	}
 
 	/* Force check of the link first time we are brought up. */
 	hp->linkcheck = 0;
@@ -3068,14 +3066,11 @@ static int happy_meal_pci_probe(struct pci_dev *pdev,
 	hp->happy_bursts = DMA_BURSTBITS;
 #endif
 
-	hp->happy_block = (struct hmeal_init_block *)
-		dma_alloc_coherent(&pdev->dev, PAGE_SIZE, &hp->hblock_dvma, GFP_KERNEL);
-
+	hp->happy_block = dma_alloc_coherent(&pdev->dev, PAGE_SIZE,
+					     &hp->hblock_dvma, GFP_KERNEL);
 	err = -ENODEV;
-	if (!hp->happy_block) {
-		printk(KERN_ERR "happymeal(PCI): Cannot get hme init block.\n");
+	if (!hp->happy_block)
 		goto err_out_iounmap;
-	}
 
 	hp->linkcheck = 0;
 	hp->timer_state = asleep;
diff --git a/drivers/net/ethernet/sun/sunqe.c b/drivers/net/ethernet/sun/sunqe.c
index 49bf3e2..8182591b 100644
--- a/drivers/net/ethernet/sun/sunqe.c
+++ b/drivers/net/ethernet/sun/sunqe.c
@@ -414,7 +414,7 @@ static void qe_rx(struct sunqe *qep)
 	struct qe_rxd *this;
 	struct sunqe_buffers *qbufs = qep->buffers;
 	__u32 qbufs_dvma = qep->buffers_dvma;
-	int elem = qep->rx_new, drops = 0;
+	int elem = qep->rx_new;
 	u32 flags;
 
 	this = &rxbase[elem];
@@ -436,7 +436,6 @@ static void qe_rx(struct sunqe *qep)
 		} else {
 			skb = netdev_alloc_skb(dev, len + 2);
 			if (skb == NULL) {
-				drops++;
 				dev->stats.rx_dropped++;
 			} else {
 				skb_reserve(skb, 2);
@@ -456,8 +455,6 @@ static void qe_rx(struct sunqe *qep)
 		this = &rxbase[elem];
 	}
 	qep->rx_new = elem;
-	if (drops)
-		printk(KERN_NOTICE "%s: Memory squeeze, deferring packet.\n", qep->dev->name);
 }
 
 static void qe_tx_reclaim(struct sunqe *qep);
diff --git a/drivers/net/ethernet/tehuti/tehuti.c b/drivers/net/ethernet/tehuti/tehuti.c
index e15cc71..e8824ce 100644
--- a/drivers/net/ethernet/tehuti/tehuti.c
+++ b/drivers/net/ethernet/tehuti/tehuti.c
@@ -1102,10 +1102,9 @@ static void bdx_rx_alloc_skbs(struct bdx_priv *priv, struct rxf_fifo *f)
 	dno = bdx_rxdb_available(db) - 1;
 	while (dno > 0) {
 		skb = netdev_alloc_skb(priv->ndev, f->m.pktsz + NET_IP_ALIGN);
-		if (!skb) {
-			pr_err("NO MEM: netdev_alloc_skb failed\n");
+		if (!skb)
 			break;
-		}
+
 		skb_reserve(skb, NET_IP_ALIGN);
 
 		idx = bdx_rxdb_alloc_elem(db);
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index df32a09..1d74042 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -126,6 +126,13 @@ do {								\
 #define CPSW_FIFO_DUAL_MAC_MODE		(1 << 15)
 #define CPSW_FIFO_RATE_LIMIT_MODE	(2 << 15)
 
+#define CPSW_INTPACEEN		(0x3f << 16)
+#define CPSW_INTPRESCALE_MASK	(0x7FF << 0)
+#define CPSW_CMINTMAX_CNT	63
+#define CPSW_CMINTMIN_CNT	2
+#define CPSW_CMINTMAX_INTVL	(1000 / CPSW_CMINTMIN_CNT)
+#define CPSW_CMINTMIN_INTVL	((1000 / CPSW_CMINTMAX_CNT) + 1)
+
 #define cpsw_enable_irq(priv)	\
 	do {			\
 		u32 i;		\
@@ -139,6 +146,10 @@ do {								\
 			disable_irq_nosync(priv->irqs_table[i]); \
 	} while (0);
 
+#define cpsw_slave_index(priv)				\
+		((priv->data.dual_emac) ? priv->emac_port :	\
+		priv->data.active_slave)
+
 static int debug_level;
 module_param(debug_level, int, 0);
 MODULE_PARM_DESC(debug_level, "cpsw debug level (NETIF_MSG bits)");
@@ -160,6 +171,15 @@ struct cpsw_wr_regs {
 	u32	rx_en;
 	u32	tx_en;
 	u32	misc_en;
+	u32	mem_allign1[8];
+	u32	rx_thresh_stat;
+	u32	rx_stat;
+	u32	tx_stat;
+	u32	misc_stat;
+	u32	mem_allign2[8];
+	u32	rx_imax;
+	u32	tx_imax;
+
 };
 
 struct cpsw_ss_regs {
@@ -314,6 +334,8 @@ struct cpsw_priv {
 	struct cpsw_host_regs __iomem	*host_port_regs;
 	u32				msg_enable;
 	u32				version;
+	u32				coal_intvl;
+	u32				bus_freq_mhz;
 	struct net_device_stats		stats;
 	int				rx_packet_max;
 	int				host_port;
@@ -436,7 +458,7 @@ void cpsw_tx_handler(void *token, int len, int status)
 	 * queue is stopped then start the queue as we have free desc for tx
 	 */
 	if (unlikely(netif_queue_stopped(ndev)))
-		netif_start_queue(ndev);
+		netif_wake_queue(ndev);
 	cpts_tx_timestamp(priv->cpts, skb);
 	priv->stats.tx_packets++;
 	priv->stats.tx_bytes += len;
@@ -612,6 +634,77 @@ static void cpsw_adjust_link(struct net_device *ndev)
 	}
 }
 
+static int cpsw_get_coalesce(struct net_device *ndev,
+				struct ethtool_coalesce *coal)
+{
+	struct cpsw_priv *priv = netdev_priv(ndev);
+
+	coal->rx_coalesce_usecs = priv->coal_intvl;
+	return 0;
+}
+
+static int cpsw_set_coalesce(struct net_device *ndev,
+				struct ethtool_coalesce *coal)
+{
+	struct cpsw_priv *priv = netdev_priv(ndev);
+	u32 int_ctrl;
+	u32 num_interrupts = 0;
+	u32 prescale = 0;
+	u32 addnl_dvdr = 1;
+	u32 coal_intvl = 0;
+
+	if (!coal->rx_coalesce_usecs)
+		return -EINVAL;
+
+	coal_intvl = coal->rx_coalesce_usecs;
+
+	int_ctrl =  readl(&priv->wr_regs->int_control);
+	prescale = priv->bus_freq_mhz * 4;
+
+	if (coal_intvl < CPSW_CMINTMIN_INTVL)
+		coal_intvl = CPSW_CMINTMIN_INTVL;
+
+	if (coal_intvl > CPSW_CMINTMAX_INTVL) {
+		/* Interrupt pacer works with 4us Pulse, we can
+		 * throttle further by dilating the 4us pulse.
+		 */
+		addnl_dvdr = CPSW_INTPRESCALE_MASK / prescale;
+
+		if (addnl_dvdr > 1) {
+			prescale *= addnl_dvdr;
+			if (coal_intvl > (CPSW_CMINTMAX_INTVL * addnl_dvdr))
+				coal_intvl = (CPSW_CMINTMAX_INTVL
+						* addnl_dvdr);
+		} else {
+			addnl_dvdr = 1;
+			coal_intvl = CPSW_CMINTMAX_INTVL;
+		}
+	}
+
+	num_interrupts = (1000 * addnl_dvdr) / coal_intvl;
+	writel(num_interrupts, &priv->wr_regs->rx_imax);
+	writel(num_interrupts, &priv->wr_regs->tx_imax);
+
+	int_ctrl |= CPSW_INTPACEEN;
+	int_ctrl &= (~CPSW_INTPRESCALE_MASK);
+	int_ctrl |= (prescale & CPSW_INTPRESCALE_MASK);
+	writel(int_ctrl, &priv->wr_regs->int_control);
+
+	cpsw_notice(priv, timer, "Set coalesce to %d usecs.\n", coal_intvl);
+	if (priv->data.dual_emac) {
+		int i;
+
+		for (i = 0; i < priv->data.slaves; i++) {
+			priv = netdev_priv(priv->slaves[i].ndev);
+			priv->coal_intvl = coal_intvl;
+		}
+	} else {
+		priv->coal_intvl = coal_intvl;
+	}
+
+	return 0;
+}
+
 static inline int __show_stat(char *buf, int maxlen, const char *name, u32 val)
 {
 	static char *leader = "........................................";
@@ -834,6 +927,14 @@ static int cpsw_ndo_open(struct net_device *ndev)
 		cpsw_info(priv, ifup, "submitted %d rx descriptors\n", i);
 	}
 
+	/* Enable Interrupt pacing if configured */
+	if (priv->coal_intvl != 0) {
+		struct ethtool_coalesce coal;
+
+		coal.rx_coalesce_usecs = (priv->coal_intvl << 4);
+		cpsw_set_coalesce(ndev, &coal);
+	}
+
 	cpdma_ctlr_start(priv->dma);
 	cpsw_intr_enable(priv);
 	napi_enable(&priv->napi);
@@ -942,7 +1043,7 @@ static void cpsw_ndo_change_rx_flags(struct net_device *ndev, int flags)
 
 static void cpsw_hwtstamp_v1(struct cpsw_priv *priv)
 {
-	struct cpsw_slave *slave = &priv->slaves[priv->data.cpts_active_slave];
+	struct cpsw_slave *slave = &priv->slaves[priv->data.active_slave];
 	u32 ts_en, seq_id;
 
 	if (!priv->cpts->tx_enable && !priv->cpts->rx_enable) {
@@ -971,7 +1072,7 @@ static void cpsw_hwtstamp_v2(struct cpsw_priv *priv)
 	if (priv->data.dual_emac)
 		slave = &priv->slaves[priv->emac_port];
 	else
-		slave = &priv->slaves[priv->data.cpts_active_slave];
+		slave = &priv->slaves[priv->data.active_slave];
 
 	ctrl = slave_read(slave, CPSW2_CONTROL);
 	ctrl &= ~CTRL_ALL_TS_MASK;
@@ -1056,14 +1157,26 @@ static int cpsw_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)
 
 static int cpsw_ndo_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
 {
+	struct cpsw_priv *priv = netdev_priv(dev);
+	struct mii_ioctl_data *data = if_mii(req);
+	int slave_no = cpsw_slave_index(priv);
+
 	if (!netif_running(dev))
 		return -EINVAL;
 
+	switch (cmd) {
 #ifdef CONFIG_TI_CPTS
-	if (cmd == SIOCSHWTSTAMP)
+	case SIOCSHWTSTAMP:
 		return cpsw_hwtstamp_ioctl(dev, req);
 #endif
-	return -ENOTSUPP;
+	case SIOCGMIIPHY:
+		data->phy_id = priv->slaves[slave_no].phy->addr;
+		break;
+	default:
+		return -ENOTSUPP;
+	}
+
+	return 0;
 }
 
 static void cpsw_ndo_tx_timeout(struct net_device *ndev)
@@ -1244,12 +1357,39 @@ static int cpsw_get_ts_info(struct net_device *ndev,
 	return 0;
 }
 
+static int cpsw_get_settings(struct net_device *ndev,
+			     struct ethtool_cmd *ecmd)
+{
+	struct cpsw_priv *priv = netdev_priv(ndev);
+	int slave_no = cpsw_slave_index(priv);
+
+	if (priv->slaves[slave_no].phy)
+		return phy_ethtool_gset(priv->slaves[slave_no].phy, ecmd);
+	else
+		return -EOPNOTSUPP;
+}
+
+static int cpsw_set_settings(struct net_device *ndev, struct ethtool_cmd *ecmd)
+{
+	struct cpsw_priv *priv = netdev_priv(ndev);
+	int slave_no = cpsw_slave_index(priv);
+
+	if (priv->slaves[slave_no].phy)
+		return phy_ethtool_sset(priv->slaves[slave_no].phy, ecmd);
+	else
+		return -EOPNOTSUPP;
+}
+
 static const struct ethtool_ops cpsw_ethtool_ops = {
 	.get_drvinfo	= cpsw_get_drvinfo,
 	.get_msglevel	= cpsw_get_msglevel,
 	.set_msglevel	= cpsw_set_msglevel,
 	.get_link	= ethtool_op_get_link,
 	.get_ts_info	= cpsw_get_ts_info,
+	.get_settings	= cpsw_get_settings,
+	.set_settings	= cpsw_set_settings,
+	.get_coalesce	= cpsw_get_coalesce,
+	.set_coalesce	= cpsw_set_coalesce,
 };
 
 static void cpsw_slave_init(struct cpsw_slave *slave, struct cpsw_priv *priv,
@@ -1282,12 +1422,12 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
 	}
 	data->slaves = prop;
 
-	if (of_property_read_u32(node, "cpts_active_slave", &prop)) {
-		pr_err("Missing cpts_active_slave property in the DT.\n");
+	if (of_property_read_u32(node, "active_slave", &prop)) {
+		pr_err("Missing active_slave property in the DT.\n");
 		ret = -EINVAL;
 		goto error_ret;
 	}
-	data->cpts_active_slave = prop;
+	data->active_slave = prop;
 
 	if (of_property_read_u32(node, "cpts_clock_mult", &prop)) {
 		pr_err("Missing cpts_clock_mult property in the DT.\n");
@@ -1437,6 +1577,9 @@ static int cpsw_probe_dual_emac(struct platform_device *pdev,
 	priv_sl2->slaves = priv->slaves;
 	priv_sl2->clk = priv->clk;
 
+	priv_sl2->coal_intvl = 0;
+	priv_sl2->bus_freq_mhz = priv->bus_freq_mhz;
+
 	priv_sl2->cpsw_res = priv->cpsw_res;
 	priv_sl2->regs = priv->regs;
 	priv_sl2->host_port = priv->host_port;
@@ -1546,6 +1689,8 @@ static int cpsw_probe(struct platform_device *pdev)
 		ret = -ENODEV;
 		goto clean_slave_ret;
 	}
+	priv->coal_intvl = 0;
+	priv->bus_freq_mhz = clk_get_rate(priv->clk) / 1000000;
 
 	priv->cpsw_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!priv->cpsw_res) {
diff --git a/drivers/net/ethernet/ti/cpts.c b/drivers/net/ethernet/ti/cpts.c
index 463597f..8c351f1 100644
--- a/drivers/net/ethernet/ti/cpts.c
+++ b/drivers/net/ethernet/ti/cpts.c
@@ -94,7 +94,7 @@ static int cpts_fifo_read(struct cpts *cpts, int match)
 		case CPTS_EV_HW:
 			break;
 		default:
-			pr_err("cpts: unkown event type\n");
+			pr_err("cpts: unknown event type\n");
 			break;
 		}
 		if (type == match)
diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c
index ae1b77a..6a0b477 100644
--- a/drivers/net/ethernet/ti/davinci_emac.c
+++ b/drivers/net/ethernet/ti/davinci_emac.c
@@ -1053,7 +1053,7 @@ static void emac_tx_handler(void *token, int len, int status)
 	 * queue is stopped then start the queue as we have free desc for tx
 	 */
 	if (unlikely(netif_queue_stopped(ndev)))
-		netif_start_queue(ndev);
+		netif_wake_queue(ndev);
 	ndev->stats.tx_packets++;
 	ndev->stats.tx_bytes += len;
 	dev_kfree_skb_any(skb);
@@ -1438,7 +1438,7 @@ static int emac_poll(struct napi_struct *napi, int budget)
  * Polled functionality used by netconsole and others in non interrupt mode
  *
  */
-void emac_poll_controller(struct net_device *ndev)
+static void emac_poll_controller(struct net_device *ndev)
 {
 	struct emac_priv *priv = netdev_priv(ndev);
 
@@ -1865,21 +1865,18 @@ static int davinci_emac_probe(struct platform_device *pdev)
 
 
 	/* obtain emac clock from kernel */
-	emac_clk = clk_get(&pdev->dev, NULL);
+	emac_clk = devm_clk_get(&pdev->dev, NULL);
 	if (IS_ERR(emac_clk)) {
 		dev_err(&pdev->dev, "failed to get EMAC clock\n");
 		return -EBUSY;
 	}
 	emac_bus_frequency = clk_get_rate(emac_clk);
-	clk_put(emac_clk);
 
 	/* TODO: Probe PHY here if possible */
 
 	ndev = alloc_etherdev(sizeof(struct emac_priv));
-	if (!ndev) {
-		rc = -ENOMEM;
-		goto no_ndev;
-	}
+	if (!ndev)
+		return -ENOMEM;
 
 	platform_set_drvdata(pdev, ndev);
 	priv = netdev_priv(ndev);
@@ -1893,7 +1890,7 @@ static int davinci_emac_probe(struct platform_device *pdev)
 	if (!pdata) {
 		dev_err(&pdev->dev, "no platform data\n");
 		rc = -ENODEV;
-		goto probe_quit;
+		goto no_pdata;
 	}
 
 	/* MAC addr and PHY mask , RMII enable info from platform_data */
@@ -1913,23 +1910,23 @@ static int davinci_emac_probe(struct platform_device *pdev)
 	if (!res) {
 		dev_err(&pdev->dev,"error getting res\n");
 		rc = -ENOENT;
-		goto probe_quit;
+		goto no_pdata;
 	}
 
 	priv->emac_base_phys = res->start + pdata->ctrl_reg_offset;
 	size = resource_size(res);
-	if (!request_mem_region(res->start, size, ndev->name)) {
+	if (!devm_request_mem_region(&pdev->dev, res->start,
+				     size, ndev->name)) {
 		dev_err(&pdev->dev, "failed request_mem_region() for regs\n");
 		rc = -ENXIO;
-		goto probe_quit;
+		goto no_pdata;
 	}
 
-	priv->remap_addr = ioremap(res->start, size);
+	priv->remap_addr = devm_ioremap(&pdev->dev, res->start, size);
 	if (!priv->remap_addr) {
 		dev_err(&pdev->dev, "unable to map IO\n");
 		rc = -ENOMEM;
-		release_mem_region(res->start, size);
-		goto probe_quit;
+		goto no_pdata;
 	}
 	priv->emac_base = priv->remap_addr + pdata->ctrl_reg_offset;
 	ndev->base_addr = (unsigned long)priv->remap_addr;
@@ -1962,7 +1959,7 @@ static int davinci_emac_probe(struct platform_device *pdev)
 	if (!priv->dma) {
 		dev_err(&pdev->dev, "error initializing DMA\n");
 		rc = -ENOMEM;
-		goto no_dma;
+		goto no_pdata;
 	}
 
 	priv->txchan = cpdma_chan_create(priv->dma, tx_chan_num(EMAC_DEF_TX_CH),
@@ -1971,14 +1968,14 @@ static int davinci_emac_probe(struct platform_device *pdev)
 				       emac_rx_handler);
 	if (WARN_ON(!priv->txchan || !priv->rxchan)) {
 		rc = -ENOMEM;
-		goto no_irq_res;
+		goto no_cpdma_chan;
 	}
 
 	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 	if (!res) {
 		dev_err(&pdev->dev, "error getting irq res\n");
 		rc = -ENOENT;
-		goto no_irq_res;
+		goto no_cpdma_chan;
 	}
 	ndev->irq = res->start;
 
@@ -2000,7 +1997,7 @@ static int davinci_emac_probe(struct platform_device *pdev)
 	if (rc) {
 		dev_err(&pdev->dev, "error in register_netdev\n");
 		rc = -ENODEV;
-		goto no_irq_res;
+		goto no_cpdma_chan;
 	}
 
 
@@ -2015,20 +2012,14 @@ static int davinci_emac_probe(struct platform_device *pdev)
 
 	return 0;
 
-no_irq_res:
+no_cpdma_chan:
 	if (priv->txchan)
 		cpdma_chan_destroy(priv->txchan);
 	if (priv->rxchan)
 		cpdma_chan_destroy(priv->rxchan);
 	cpdma_ctlr_destroy(priv->dma);
-no_dma:
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	release_mem_region(res->start, resource_size(res));
-	iounmap(priv->remap_addr);
-
-probe_quit:
+no_pdata:
 	free_netdev(ndev);
-no_ndev:
 	return rc;
 }
 
@@ -2041,14 +2032,12 @@ no_ndev:
  */
 static int davinci_emac_remove(struct platform_device *pdev)
 {
-	struct resource *res;
 	struct net_device *ndev = platform_get_drvdata(pdev);
 	struct emac_priv *priv = netdev_priv(ndev);
 
 	dev_notice(&ndev->dev, "DaVinci EMAC: davinci_emac_remove()\n");
 
 	platform_set_drvdata(pdev, NULL);
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
 	if (priv->txchan)
 		cpdma_chan_destroy(priv->txchan);
@@ -2056,10 +2045,7 @@ static int davinci_emac_remove(struct platform_device *pdev)
 		cpdma_chan_destroy(priv->rxchan);
 	cpdma_ctlr_destroy(priv->dma);
 
-	release_mem_region(res->start, resource_size(res));
-
 	unregister_netdev(ndev);
-	iounmap(priv->remap_addr);
 	free_netdev(ndev);
 
 	return 0;
diff --git a/drivers/net/ethernet/ti/tlan.c b/drivers/net/ethernet/ti/tlan.c
index 2272538..bdda36f 100644
--- a/drivers/net/ethernet/ti/tlan.c
+++ b/drivers/net/ethernet/ti/tlan.c
@@ -1911,10 +1911,8 @@ static void tlan_reset_lists(struct net_device *dev)
 		list->frame_size = TLAN_MAX_FRAME_SIZE;
 		list->buffer[0].count = TLAN_MAX_FRAME_SIZE | TLAN_LAST_BUFFER;
 		skb = netdev_alloc_skb_ip_align(dev, TLAN_MAX_FRAME_SIZE + 5);
-		if (!skb) {
-			netdev_err(dev, "Out of memory for received data\n");
+		if (!skb)
 			break;
-		}
 
 		list->buffer[0].address = pci_map_single(priv->pci_dev,
 							 skb->data,
diff --git a/drivers/net/ethernet/toshiba/ps3_gelic_net.c b/drivers/net/ethernet/toshiba/ps3_gelic_net.c
index 445c059..ad32af6 100644
--- a/drivers/net/ethernet/toshiba/ps3_gelic_net.c
+++ b/drivers/net/ethernet/toshiba/ps3_gelic_net.c
@@ -58,13 +58,6 @@ MODULE_DESCRIPTION("Gelic Network driver");
 MODULE_LICENSE("GPL");
 
 
-static inline void gelic_card_enable_rxdmac(struct gelic_card *card);
-static inline void gelic_card_disable_rxdmac(struct gelic_card *card);
-static inline void gelic_card_disable_txdmac(struct gelic_card *card);
-static inline void gelic_card_reset_chain(struct gelic_card *card,
-					  struct gelic_descr_chain *chain,
-					  struct gelic_descr *start_descr);
-
 /* set irq_mask */
 int gelic_card_set_irq_mask(struct gelic_card *card, u64 mask)
 {
@@ -78,12 +71,12 @@ int gelic_card_set_irq_mask(struct gelic_card *card, u64 mask)
 	return status;
 }
 
-static inline void gelic_card_rx_irq_on(struct gelic_card *card)
+static void gelic_card_rx_irq_on(struct gelic_card *card)
 {
 	card->irq_mask |= GELIC_CARD_RXINT;
 	gelic_card_set_irq_mask(card, card->irq_mask);
 }
-static inline void gelic_card_rx_irq_off(struct gelic_card *card)
+static void gelic_card_rx_irq_off(struct gelic_card *card)
 {
 	card->irq_mask &= ~GELIC_CARD_RXINT;
 	gelic_card_set_irq_mask(card, card->irq_mask);
@@ -127,6 +120,120 @@ static int gelic_card_set_link_mode(struct gelic_card *card, int mode)
 	return 0;
 }
 
+/**
+ * gelic_card_disable_txdmac - disables the transmit DMA controller
+ * @card: card structure
+ *
+ * gelic_card_disable_txdmac terminates processing on the DMA controller by
+ * turing off DMA and issuing a force end
+ */
+static void gelic_card_disable_txdmac(struct gelic_card *card)
+{
+	int status;
+
+	/* this hvc blocks until the DMA in progress really stopped */
+	status = lv1_net_stop_tx_dma(bus_id(card), dev_id(card));
+	if (status)
+		dev_err(ctodev(card),
+			"lv1_net_stop_tx_dma failed, status=%d\n", status);
+}
+
+/**
+ * gelic_card_enable_rxdmac - enables the receive DMA controller
+ * @card: card structure
+ *
+ * gelic_card_enable_rxdmac enables the DMA controller by setting RX_DMA_EN
+ * in the GDADMACCNTR register
+ */
+static void gelic_card_enable_rxdmac(struct gelic_card *card)
+{
+	int status;
+
+#ifdef DEBUG
+	if (gelic_descr_get_status(card->rx_chain.head) !=
+	    GELIC_DESCR_DMA_CARDOWNED) {
+		printk(KERN_ERR "%s: status=%x\n", __func__,
+		       be32_to_cpu(card->rx_chain.head->dmac_cmd_status));
+		printk(KERN_ERR "%s: nextphy=%x\n", __func__,
+		       be32_to_cpu(card->rx_chain.head->next_descr_addr));
+		printk(KERN_ERR "%s: head=%p\n", __func__,
+		       card->rx_chain.head);
+	}
+#endif
+	status = lv1_net_start_rx_dma(bus_id(card), dev_id(card),
+				card->rx_chain.head->bus_addr, 0);
+	if (status)
+		dev_info(ctodev(card),
+			 "lv1_net_start_rx_dma failed, status=%d\n", status);
+}
+
+/**
+ * gelic_card_disable_rxdmac - disables the receive DMA controller
+ * @card: card structure
+ *
+ * gelic_card_disable_rxdmac terminates processing on the DMA controller by
+ * turing off DMA and issuing a force end
+ */
+static void gelic_card_disable_rxdmac(struct gelic_card *card)
+{
+	int status;
+
+	/* this hvc blocks until the DMA in progress really stopped */
+	status = lv1_net_stop_rx_dma(bus_id(card), dev_id(card));
+	if (status)
+		dev_err(ctodev(card),
+			"lv1_net_stop_rx_dma failed, %d\n", status);
+}
+
+/**
+ * gelic_descr_set_status -- sets the status of a descriptor
+ * @descr: descriptor to change
+ * @status: status to set in the descriptor
+ *
+ * changes the status to the specified value. Doesn't change other bits
+ * in the status
+ */
+static void gelic_descr_set_status(struct gelic_descr *descr,
+				   enum gelic_descr_dma_status status)
+{
+	descr->dmac_cmd_status = cpu_to_be32(status |
+			(be32_to_cpu(descr->dmac_cmd_status) &
+			 ~GELIC_DESCR_DMA_STAT_MASK));
+	/*
+	 * dma_cmd_status field is used to indicate whether the descriptor
+	 * is valid or not.
+	 * Usually caller of this function wants to inform that to the
+	 * hardware, so we assure here the hardware sees the change.
+	 */
+	wmb();
+}
+
+/**
+ * gelic_card_reset_chain - reset status of a descriptor chain
+ * @card: card structure
+ * @chain: address of chain
+ * @start_descr: address of descriptor array
+ *
+ * Reset the status of dma descriptors to ready state
+ * and re-initialize the hardware chain for later use
+ */
+static void gelic_card_reset_chain(struct gelic_card *card,
+				   struct gelic_descr_chain *chain,
+				   struct gelic_descr *start_descr)
+{
+	struct gelic_descr *descr;
+
+	for (descr = start_descr; start_descr != descr->next; descr++) {
+		gelic_descr_set_status(descr, GELIC_DESCR_DMA_CARDOWNED);
+		descr->next_descr_addr = cpu_to_be32(descr->next->bus_addr);
+	}
+
+	chain->head = start_descr;
+	chain->tail = (descr - 1);
+
+	(descr - 1)->next_descr_addr = 0;
+}
+
 void gelic_card_up(struct gelic_card *card)
 {
 	pr_debug("%s: called\n", __func__);
@@ -183,29 +290,6 @@ gelic_descr_get_status(struct gelic_descr *descr)
 }
 
 /**
- * gelic_descr_set_status -- sets the status of a descriptor
- * @descr: descriptor to change
- * @status: status to set in the descriptor
- *
- * changes the status to the specified value. Doesn't change other bits
- * in the status
- */
-static void gelic_descr_set_status(struct gelic_descr *descr,
-				   enum gelic_descr_dma_status status)
-{
-	descr->dmac_cmd_status = cpu_to_be32(status |
-			(be32_to_cpu(descr->dmac_cmd_status) &
-			 ~GELIC_DESCR_DMA_STAT_MASK));
-	/*
-	 * dma_cmd_status field is used to indicate whether the descriptor
-	 * is valid or not.
-	 * Usually caller of this function wants to inform that to the
-	 * hardware, so we assure here the hardware sees the change.
-	 */
-	wmb();
-}
-
-/**
  * gelic_card_free_chain - free descriptor chain
  * @card: card structure
  * @descr_in: address of desc
@@ -286,31 +370,6 @@ iommu_error:
 }
 
 /**
- * gelic_card_reset_chain - reset status of a descriptor chain
- * @card: card structure
- * @chain: address of chain
- * @start_descr: address of descriptor array
- *
- * Reset the status of dma descriptors to ready state
- * and re-initialize the hardware chain for later use
- */
-static void gelic_card_reset_chain(struct gelic_card *card,
-				   struct gelic_descr_chain *chain,
-				   struct gelic_descr *start_descr)
-{
-	struct gelic_descr *descr;
-
-	for (descr = start_descr; start_descr != descr->next; descr++) {
-		gelic_descr_set_status(descr, GELIC_DESCR_DMA_CARDOWNED);
-		descr->next_descr_addr = cpu_to_be32(descr->next->bus_addr);
-	}
-
-	chain->head = start_descr;
-	chain->tail = (descr - 1);
-
-	(descr - 1)->next_descr_addr = 0;
-}
-/**
  * gelic_descr_prepare_rx - reinitializes a rx descriptor
  * @card: card structure
  * @descr: descriptor to re-init
@@ -599,71 +658,6 @@ void gelic_net_set_multi(struct net_device *netdev)
 }
 
 /**
- * gelic_card_enable_rxdmac - enables the receive DMA controller
- * @card: card structure
- *
- * gelic_card_enable_rxdmac enables the DMA controller by setting RX_DMA_EN
- * in the GDADMACCNTR register
- */
-static inline void gelic_card_enable_rxdmac(struct gelic_card *card)
-{
-	int status;
-
-#ifdef DEBUG
-	if (gelic_descr_get_status(card->rx_chain.head) !=
-	    GELIC_DESCR_DMA_CARDOWNED) {
-		printk(KERN_ERR "%s: status=%x\n", __func__,
-		       be32_to_cpu(card->rx_chain.head->dmac_cmd_status));
-		printk(KERN_ERR "%s: nextphy=%x\n", __func__,
-		       be32_to_cpu(card->rx_chain.head->next_descr_addr));
-		printk(KERN_ERR "%s: head=%p\n", __func__,
-		       card->rx_chain.head);
-	}
-#endif
-	status = lv1_net_start_rx_dma(bus_id(card), dev_id(card),
-				card->rx_chain.head->bus_addr, 0);
-	if (status)
-		dev_info(ctodev(card),
-			 "lv1_net_start_rx_dma failed, status=%d\n", status);
-}
-
-/**
- * gelic_card_disable_rxdmac - disables the receive DMA controller
- * @card: card structure
- *
- * gelic_card_disable_rxdmac terminates processing on the DMA controller by
- * turing off DMA and issuing a force end
- */
-static inline void gelic_card_disable_rxdmac(struct gelic_card *card)
-{
-	int status;
-
-	/* this hvc blocks until the DMA in progress really stopped */
-	status = lv1_net_stop_rx_dma(bus_id(card), dev_id(card));
-	if (status)
-		dev_err(ctodev(card),
-			"lv1_net_stop_rx_dma failed, %d\n", status);
-}
-
-/**
- * gelic_card_disable_txdmac - disables the transmit DMA controller
- * @card: card structure
- *
- * gelic_card_disable_txdmac terminates processing on the DMA controller by
- * turing off DMA and issuing a force end
- */
-static inline void gelic_card_disable_txdmac(struct gelic_card *card)
-{
-	int status;
-
-	/* this hvc blocks until the DMA in progress really stopped */
-	status = lv1_net_stop_tx_dma(bus_id(card), dev_id(card));
-	if (status)
-		dev_err(ctodev(card),
-			"lv1_net_stop_tx_dma failed, status=%d\n", status);
-}
-
-/**
  * gelic_net_stop - called upon ifconfig down
  * @netdev: interface device structure
  *
@@ -746,7 +740,7 @@ static void gelic_descr_set_tx_cmdstat(struct gelic_descr *descr,
 	}
 }
 
-static inline struct sk_buff *gelic_put_vlan_tag(struct sk_buff *skb,
+static struct sk_buff *gelic_put_vlan_tag(struct sk_buff *skb,
 						 unsigned short tag)
 {
 	struct vlan_ethhdr *veth;
diff --git a/drivers/net/ethernet/toshiba/spider_net.c b/drivers/net/ethernet/toshiba/spider_net.c
index f1b91fd..fef6b59 100644
--- a/drivers/net/ethernet/toshiba/spider_net.c
+++ b/drivers/net/ethernet/toshiba/spider_net.c
@@ -352,8 +352,7 @@ spider_net_init_chain(struct spider_net_card *card,
 	alloc_size = chain->num_desc * sizeof(struct spider_net_hw_descr);
 
 	chain->hwring = dma_alloc_coherent(&card->pdev->dev, alloc_size,
-		&chain->dma_addr, GFP_KERNEL);
-
+					   &chain->dma_addr, GFP_KERNEL);
 	if (!chain->hwring)
 		return -ENOMEM;
 
diff --git a/drivers/net/ethernet/tundra/tsi108_eth.c b/drivers/net/ethernet/tundra/tsi108_eth.c
index 8fa947a..3c69a04 100644
--- a/drivers/net/ethernet/tundra/tsi108_eth.c
+++ b/drivers/net/ethernet/tundra/tsi108_eth.c
@@ -1308,27 +1308,16 @@ static int tsi108_open(struct net_device *dev)
 		       data->id, dev->irq, dev->name);
 	}
 
-	data->rxring = dma_alloc_coherent(NULL, rxring_size,
-			&data->rxdma, GFP_KERNEL);
-
-	if (!data->rxring) {
-		printk(KERN_DEBUG
-		       "TSI108_ETH: failed to allocate memory for rxring!\n");
+	data->rxring = dma_alloc_coherent(NULL, rxring_size, &data->rxdma,
+					  GFP_KERNEL | __GFP_ZERO);
+	if (!data->rxring)
 		return -ENOMEM;
-	} else {
-		memset(data->rxring, 0, rxring_size);
-	}
-
-	data->txring = dma_alloc_coherent(NULL, txring_size,
-			&data->txdma, GFP_KERNEL);
 
+	data->txring = dma_alloc_coherent(NULL, txring_size, &data->txdma,
+					  GFP_KERNEL | __GFP_ZERO);
 	if (!data->txring) {
-		printk(KERN_DEBUG
-		       "TSI108_ETH: failed to allocate memory for txring!\n");
 		pci_free_consistent(0, rxring_size, data->rxring, data->rxdma);
 		return -ENOMEM;
-	} else {
-		memset(data->txring, 0, txring_size);
 	}
 
 	for (i = 0; i < TSI108_RXRING_LEN; i++) {
diff --git a/drivers/net/ethernet/wiznet/w5100.c b/drivers/net/ethernet/wiznet/w5100.c
index 545043c..a518dca 100644
--- a/drivers/net/ethernet/wiznet/w5100.c
+++ b/drivers/net/ethernet/wiznet/w5100.c
@@ -754,7 +754,7 @@ static int w5100_remove(struct platform_device *pdev)
 	return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int w5100_suspend(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
@@ -787,7 +787,7 @@ static int w5100_resume(struct device *dev)
 	}
 	return 0;
 }
-#endif /* CONFIG_PM */
+#endif /* CONFIG_PM_SLEEP */
 
 static SIMPLE_DEV_PM_OPS(w5100_pm_ops, w5100_suspend, w5100_resume);
 
diff --git a/drivers/net/ethernet/wiznet/w5300.c b/drivers/net/ethernet/wiznet/w5300.c
index 7cbd0e6..6e00e3f 100644
--- a/drivers/net/ethernet/wiznet/w5300.c
+++ b/drivers/net/ethernet/wiznet/w5300.c
@@ -666,7 +666,7 @@ static int w5300_remove(struct platform_device *pdev)
 	return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int w5300_suspend(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
@@ -699,7 +699,7 @@ static int w5300_resume(struct device *dev)
 	}
 	return 0;
 }
-#endif /* CONFIG_PM */
+#endif /* CONFIG_PM_SLEEP */
 
 static SIMPLE_DEV_PM_OPS(w5300_pm_ops, w5300_suspend, w5300_resume);
 
diff --git a/drivers/net/ethernet/xilinx/ll_temac_main.c b/drivers/net/ethernet/xilinx/ll_temac_main.c
index 9fc2ada..4a7c60f 100644
--- a/drivers/net/ethernet/xilinx/ll_temac_main.c
+++ b/drivers/net/ethernet/xilinx/ll_temac_main.c
@@ -245,39 +245,30 @@ static int temac_dma_bd_init(struct net_device *ndev)
 	/* returns a virtual address and a physical address. */
 	lp->tx_bd_v = dma_alloc_coherent(ndev->dev.parent,
 					 sizeof(*lp->tx_bd_v) * TX_BD_NUM,
-					 &lp->tx_bd_p, GFP_KERNEL);
-	if (!lp->tx_bd_v) {
-		dev_err(&ndev->dev,
-				"unable to allocate DMA TX buffer descriptors");
+					 &lp->tx_bd_p, GFP_KERNEL | __GFP_ZERO);
+	if (!lp->tx_bd_v)
 		goto out;
-	}
+
 	lp->rx_bd_v = dma_alloc_coherent(ndev->dev.parent,
 					 sizeof(*lp->rx_bd_v) * RX_BD_NUM,
-					 &lp->rx_bd_p, GFP_KERNEL);
-	if (!lp->rx_bd_v) {
-		dev_err(&ndev->dev,
-				"unable to allocate DMA RX buffer descriptors");
+					 &lp->rx_bd_p, GFP_KERNEL | __GFP_ZERO);
+	if (!lp->rx_bd_v)
 		goto out;
-	}
 
-	memset(lp->tx_bd_v, 0, sizeof(*lp->tx_bd_v) * TX_BD_NUM);
 	for (i = 0; i < TX_BD_NUM; i++) {
 		lp->tx_bd_v[i].next = lp->tx_bd_p +
 				sizeof(*lp->tx_bd_v) * ((i + 1) % TX_BD_NUM);
 	}
 
-	memset(lp->rx_bd_v, 0, sizeof(*lp->rx_bd_v) * RX_BD_NUM);
 	for (i = 0; i < RX_BD_NUM; i++) {
 		lp->rx_bd_v[i].next = lp->rx_bd_p +
 				sizeof(*lp->rx_bd_v) * ((i + 1) % RX_BD_NUM);
 
 		skb = netdev_alloc_skb_ip_align(ndev,
 						XTE_MAX_JUMBO_FRAME_SIZE);
-
-		if (skb == 0) {
-			dev_err(&ndev->dev, "alloc_skb error %d\n", i);
+		if (!skb)
 			goto out;
-		}
+
 		lp->rx_skb[i] = skb;
 		/* returns physical address of skb->data */
 		lp->rx_bd_v[i].phys = dma_map_single(ndev->dev.parent,
@@ -789,9 +780,7 @@ static void ll_temac_recv(struct net_device *ndev)
 
 		new_skb = netdev_alloc_skb_ip_align(ndev,
 						XTE_MAX_JUMBO_FRAME_SIZE);
-
-		if (new_skb == 0) {
-			dev_err(&ndev->dev, "no memory for new sk_buff\n");
+		if (!new_skb) {
 			spin_unlock_irqrestore(&lp->rx_lock, flags);
 			return;
 		}
diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
index 278c9db..24748e8 100644
--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
@@ -204,41 +204,31 @@ static int axienet_dma_bd_init(struct net_device *ndev)
 	lp->tx_bd_v = dma_alloc_coherent(ndev->dev.parent,
 					 sizeof(*lp->tx_bd_v) * TX_BD_NUM,
 					 &lp->tx_bd_p,
-					 GFP_KERNEL);
-	if (!lp->tx_bd_v) {
-		dev_err(&ndev->dev, "unable to allocate DMA Tx buffer "
-			"descriptors");
+					 GFP_KERNEL | __GFP_ZERO);
+	if (!lp->tx_bd_v)
 		goto out;
-	}
 
 	lp->rx_bd_v = dma_alloc_coherent(ndev->dev.parent,
 					 sizeof(*lp->rx_bd_v) * RX_BD_NUM,
 					 &lp->rx_bd_p,
-					 GFP_KERNEL);
-	if (!lp->rx_bd_v) {
-		dev_err(&ndev->dev, "unable to allocate DMA Rx buffer "
-			"descriptors");
+					 GFP_KERNEL | __GFP_ZERO);
+	if (!lp->rx_bd_v)
 		goto out;
-	}
 
-	memset(lp->tx_bd_v, 0, sizeof(*lp->tx_bd_v) * TX_BD_NUM);
 	for (i = 0; i < TX_BD_NUM; i++) {
 		lp->tx_bd_v[i].next = lp->tx_bd_p +
 				      sizeof(*lp->tx_bd_v) *
 				      ((i + 1) % TX_BD_NUM);
 	}
 
-	memset(lp->rx_bd_v, 0, sizeof(*lp->rx_bd_v) * RX_BD_NUM);
 	for (i = 0; i < RX_BD_NUM; i++) {
 		lp->rx_bd_v[i].next = lp->rx_bd_p +
 				      sizeof(*lp->rx_bd_v) *
 				      ((i + 1) % RX_BD_NUM);
 
 		skb = netdev_alloc_skb_ip_align(ndev, lp->max_frm_size);
-		if (!skb) {
-			dev_err(&ndev->dev, "alloc_skb error %d\n", i);
+		if (!skb)
 			goto out;
-		}
 
 		lp->rx_bd_v[i].sw_id_offset = (u32) skb;
 		lp->rx_bd_v[i].phys = dma_map_single(ndev->dev.parent,
@@ -777,10 +767,9 @@ static void axienet_recv(struct net_device *ndev)
 		packets++;
 
 		new_skb = netdev_alloc_skb_ip_align(ndev, lp->max_frm_size);
-		if (!new_skb) {
-			dev_err(&ndev->dev, "no memory for new sk_buff\n");
+		if (!new_skb)
 			return;
-		}
+
 		cur_p->phys = dma_map_single(ndev->dev.parent, new_skb->data,
 					     lp->max_frm_size,
 					     DMA_FROM_DEVICE);
diff --git a/drivers/net/ethernet/xircom/xirc2ps_cs.c b/drivers/net/ethernet/xircom/xirc2ps_cs.c
index 98e09d0..bdd20b8 100644
--- a/drivers/net/ethernet/xircom/xirc2ps_cs.c
+++ b/drivers/net/ethernet/xircom/xirc2ps_cs.c
@@ -1041,7 +1041,6 @@ xirc2ps_interrupt(int irq, void *dev_id)
 	    /* 1 extra so we can use insw */
 	    skb = netdev_alloc_skb(dev, pktlen + 3);
 	    if (!skb) {
-		pr_notice("low memory, packet dropped (size=%u)\n", pktlen);
 		dev->stats.rx_dropped++;
 	    } else { /* okay get the packet */
 		skb_reserve(skb, 2);
@@ -1775,21 +1774,7 @@ static struct pcmcia_driver xirc2ps_cs_driver = {
 	.suspend	= xirc2ps_suspend,
 	.resume		= xirc2ps_resume,
 };
-
-static int __init
-init_xirc2ps_cs(void)
-{
-	return pcmcia_register_driver(&xirc2ps_cs_driver);
-}
-
-static void __exit
-exit_xirc2ps_cs(void)
-{
-	pcmcia_unregister_driver(&xirc2ps_cs_driver);
-}
-
-module_init(init_xirc2ps_cs);
-module_exit(exit_xirc2ps_cs);
+module_pcmcia_driver(xirc2ps_cs_driver);
 
 #ifndef MODULE
 static int __init setup_xirc2ps_cs(char *str)
diff --git a/drivers/net/fddi/defxx.c b/drivers/net/fddi/defxx.c
index 502c8ff..4c8ddc9 100644
--- a/drivers/net/fddi/defxx.c
+++ b/drivers/net/fddi/defxx.c
@@ -1070,13 +1070,10 @@ static int dfx_driver_init(struct net_device *dev, const char *print_name,
 					(PI_ALIGN_K_DESC_BLK - 1);
 	bp->kmalloced = top_v = dma_alloc_coherent(bp->bus_dev, alloc_size,
 						   &bp->kmalloced_dma,
-						   GFP_ATOMIC);
-	if (top_v == NULL) {
-		printk("%s: Could not allocate memory for host buffers "
-		       "and structures!\n", print_name);
+						   GFP_ATOMIC | __GFP_ZERO);
+	if (top_v == NULL)
 		return DFX_K_FAILURE;
-	}
-	memset(top_v, 0, alloc_size);	/* zero out memory before continuing */
+
 	top_p = bp->kmalloced_dma;	/* get physical address of buffer */
 
 	/*
diff --git a/drivers/net/hamradio/baycom_epp.c b/drivers/net/hamradio/baycom_epp.c
index 49b8b58..484f77e 100644
--- a/drivers/net/hamradio/baycom_epp.c
+++ b/drivers/net/hamradio/baycom_epp.c
@@ -449,7 +449,7 @@ static int transmit(struct baycom_state *bc, int cnt, unsigned char stat)
 			if ((--bc->hdlctx.slotcnt) > 0)
 				return 0;
 			bc->hdlctx.slotcnt = bc->ch_params.slottime;
-			if ((random32() % 256) > bc->ch_params.ppersist)
+			if ((prandom_u32() % 256) > bc->ch_params.ppersist)
 				return 0;
 		}
 	}
diff --git a/drivers/net/hamradio/hdlcdrv.c b/drivers/net/hamradio/hdlcdrv.c
index a4a3516..3169252 100644
--- a/drivers/net/hamradio/hdlcdrv.c
+++ b/drivers/net/hamradio/hdlcdrv.c
@@ -389,7 +389,7 @@ void hdlcdrv_arbitrate(struct net_device *dev, struct hdlcdrv_state *s)
 	if ((--s->hdlctx.slotcnt) > 0)
 		return;
 	s->hdlctx.slotcnt = s->ch_params.slottime;
-	if ((random32() % 256) > s->ch_params.ppersist)
+	if ((prandom_u32() % 256) > s->ch_params.ppersist)
 		return;
 	start_tx(dev, s);
 }
diff --git a/drivers/net/hamradio/yam.c b/drivers/net/hamradio/yam.c
index 4cf8f10..0721e72 100644
--- a/drivers/net/hamradio/yam.c
+++ b/drivers/net/hamradio/yam.c
@@ -638,7 +638,7 @@ static void yam_arbitrate(struct net_device *dev)
 	yp->slotcnt = yp->slot / 10;
 
 	/* is random > persist ? */
-	if ((random32() % 256) > yp->pers)
+	if ((prandom_u32() % 256) > yp->pers)
 		return;
 
 	yam_start_tx(dev, yp);
@@ -866,7 +866,7 @@ static int yam_open(struct net_device *dev)
 
 	printk(KERN_INFO "Trying %s at iobase 0x%lx irq %u\n", dev->name, dev->base_addr, dev->irq);
 
-	if (!dev || !yp->bitrate)
+	if (!yp->bitrate)
 		return -ENXIO;
 	if (!dev->base_addr || dev->base_addr > 0x1000 - YAM_EXTENT ||
 		dev->irq < 2 || dev->irq > 15) {
diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c
index fc1687e..6e88eab 100644
--- a/drivers/net/ieee802154/at86rf230.c
+++ b/drivers/net/ieee802154/at86rf230.c
@@ -233,8 +233,8 @@ struct at86rf230_local {
 #define STATE_SLEEP		0x0F
 #define STATE_BUSY_RX_AACK	0x11
 #define STATE_BUSY_TX_ARET	0x12
-#define STATE_BUSY_RX_AACK_ON	0x16
-#define STATE_BUSY_TX_ARET_ON	0x19
+#define STATE_RX_AACK_ON	0x16
+#define STATE_TX_ARET_ON	0x19
 #define STATE_RX_ON_NOCLK	0x1C
 #define STATE_RX_AACK_ON_NOCLK	0x1D
 #define STATE_BUSY_RX_AACK_NOCLK 0x1E
@@ -619,6 +619,52 @@ err:
 	return -EINVAL;
 }
 
+static int
+at86rf230_set_hw_addr_filt(struct ieee802154_dev *dev,
+			   struct ieee802154_hw_addr_filt *filt,
+			   unsigned long changed)
+{
+	struct at86rf230_local *lp = dev->priv;
+
+	if (changed & IEEE802515_AFILT_SADDR_CHANGED) {
+		dev_vdbg(&lp->spi->dev,
+			"at86rf230_set_hw_addr_filt called for saddr\n");
+		__at86rf230_write(lp, RG_SHORT_ADDR_0, filt->short_addr);
+		__at86rf230_write(lp, RG_SHORT_ADDR_1, filt->short_addr >> 8);
+	}
+
+	if (changed & IEEE802515_AFILT_PANID_CHANGED) {
+		dev_vdbg(&lp->spi->dev,
+			"at86rf230_set_hw_addr_filt called for pan id\n");
+		__at86rf230_write(lp, RG_PAN_ID_0, filt->pan_id);
+		__at86rf230_write(lp, RG_PAN_ID_1, filt->pan_id >> 8);
+	}
+
+	if (changed & IEEE802515_AFILT_IEEEADDR_CHANGED) {
+		dev_vdbg(&lp->spi->dev,
+			"at86rf230_set_hw_addr_filt called for IEEE addr\n");
+		at86rf230_write_subreg(lp, SR_IEEE_ADDR_0, filt->ieee_addr[7]);
+		at86rf230_write_subreg(lp, SR_IEEE_ADDR_1, filt->ieee_addr[6]);
+		at86rf230_write_subreg(lp, SR_IEEE_ADDR_2, filt->ieee_addr[5]);
+		at86rf230_write_subreg(lp, SR_IEEE_ADDR_3, filt->ieee_addr[4]);
+		at86rf230_write_subreg(lp, SR_IEEE_ADDR_4, filt->ieee_addr[3]);
+		at86rf230_write_subreg(lp, SR_IEEE_ADDR_5, filt->ieee_addr[2]);
+		at86rf230_write_subreg(lp, SR_IEEE_ADDR_6, filt->ieee_addr[1]);
+		at86rf230_write_subreg(lp, SR_IEEE_ADDR_7, filt->ieee_addr[0]);
+	}
+
+	if (changed & IEEE802515_AFILT_PANC_CHANGED) {
+		dev_vdbg(&lp->spi->dev,
+			"at86rf230_set_hw_addr_filt called for panc change\n");
+		if (filt->pan_coord)
+			at86rf230_write_subreg(lp, SR_AACK_I_AM_COORD, 1);
+		else
+			at86rf230_write_subreg(lp, SR_AACK_I_AM_COORD, 0);
+	}
+
+	return 0;
+}
+
 static struct ieee802154_ops at86rf230_ops = {
 	.owner = THIS_MODULE,
 	.xmit = at86rf230_xmit,
@@ -626,6 +672,7 @@ static struct ieee802154_ops at86rf230_ops = {
 	.set_channel = at86rf230_channel,
 	.start = at86rf230_start,
 	.stop = at86rf230_stop,
+	.set_hw_addr_filt = at86rf230_set_hw_addr_filt,
 };
 
 static void at86rf230_irqwork(struct work_struct *work)
diff --git a/drivers/net/ieee802154/mrf24j40.c b/drivers/net/ieee802154/mrf24j40.c
index 3f2c7aa..0ca8f88 100644
--- a/drivers/net/ieee802154/mrf24j40.c
+++ b/drivers/net/ieee802154/mrf24j40.c
@@ -22,6 +22,7 @@
 #include <linux/spi/spi.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
+#include <linux/pinctrl/consumer.h>
 #include <net/wpan-phy.h>
 #include <net/mac802154.h>
 
@@ -91,9 +92,8 @@ struct mrf24j40 {
 #define MRF24J40_READLONG(reg) (1 << 15 | (reg) << 5)
 #define MRF24J40_WRITELONG(reg) (1 << 15 | (reg) << 5 | 1 << 4)
 
-/* Maximum speed to run the device at. TODO: Get the real max value from
- * someone at Microchip since it isn't in the datasheet. */
-#define MAX_SPI_SPEED_HZ 1000000
+/* The datasheet indicates the theoretical maximum for SCK to be 10MHz */
+#define MAX_SPI_SPEED_HZ 10000000
 
 #define printdev(X) (&X->spi->dev)
 
@@ -361,6 +361,7 @@ static int mrf24j40_tx(struct ieee802154_dev *dev, struct sk_buff *skb)
 	if (ret == -ERESTARTSYS)
 		goto err;
 	if (ret == 0) {
+		dev_warn(printdev(devrec), "Timeout waiting for TX interrupt\n");
 		ret = -ETIMEDOUT;
 		goto err;
 	}
@@ -477,7 +478,7 @@ static int mrf24j40_filter(struct ieee802154_dev *dev,
 		int i;
 		for (i = 0; i < 8; i++)
 			write_short_reg(devrec, REG_EADR0+i,
-					filt->ieee_addr[i]);
+					filt->ieee_addr[7-i]);
 
 #ifdef DEBUG
 		printk(KERN_DEBUG "Set long addr to: ");
@@ -623,6 +624,7 @@ static int mrf24j40_probe(struct spi_device *spi)
 	int ret = -ENOMEM;
 	u8 val;
 	struct mrf24j40 *devrec;
+	struct pinctrl *pinctrl;
 
 	printk(KERN_INFO "mrf24j40: probe(). IRQ: %d\n", spi->irq);
 
@@ -633,6 +635,11 @@ static int mrf24j40_probe(struct spi_device *spi)
 	if (!devrec->buf)
 		goto err_buf;
 
+	pinctrl = devm_pinctrl_get_select_default(&spi->dev);
+	if (IS_ERR(pinctrl))
+		dev_warn(&spi->dev,
+			"pinctrl pins are not configured from the driver");
+
 	spi->mode = SPI_MODE_0; /* TODO: Is this appropriate for right here? */
 	if (spi->max_speed_hz > MAX_SPI_SPEED_HZ)
 		spi->max_speed_hz = MAX_SPI_SPEED_HZ;
diff --git a/drivers/net/irda/ali-ircc.c b/drivers/net/irda/ali-ircc.c
index 9cea451..3adb43c 100644
--- a/drivers/net/irda/ali-ircc.c
+++ b/drivers/net/irda/ali-ircc.c
@@ -352,21 +352,19 @@ static int ali_ircc_open(int i, chipio_t *info)
 	/* Allocate memory if needed */
 	self->rx_buff.head =
 		dma_alloc_coherent(NULL, self->rx_buff.truesize,
-				   &self->rx_buff_dma, GFP_KERNEL);
+				   &self->rx_buff_dma, GFP_KERNEL | __GFP_ZERO);
 	if (self->rx_buff.head == NULL) {
 		err = -ENOMEM;
 		goto err_out2;
 	}
-	memset(self->rx_buff.head, 0, self->rx_buff.truesize);
 	
 	self->tx_buff.head =
 		dma_alloc_coherent(NULL, self->tx_buff.truesize,
-				   &self->tx_buff_dma, GFP_KERNEL);
+				   &self->tx_buff_dma, GFP_KERNEL | __GFP_ZERO);
 	if (self->tx_buff.head == NULL) {
 		err = -ENOMEM;
 		goto err_out3;
 	}
-	memset(self->tx_buff.head, 0, self->tx_buff.truesize);
 
 	self->rx_buff.in_frame = FALSE;
 	self->rx_buff.state = OUTSIDE_FRAME;
diff --git a/drivers/net/irda/au1k_ir.c b/drivers/net/irda/au1k_ir.c
index b5151e4..7a1f684 100644
--- a/drivers/net/irda/au1k_ir.c
+++ b/drivers/net/irda/au1k_ir.c
@@ -27,6 +27,7 @@
 #include <linux/slab.h>
 #include <linux/time.h>
 #include <linux/types.h>
+#include <linux/ioport.h>
 
 #include <net/irda/irda.h>
 #include <net/irda/irmod.h>
@@ -882,12 +883,12 @@ static int au1k_irda_probe(struct platform_device *pdev)
 		goto out;
 
 	err = -EBUSY;
-	aup->ioarea = request_mem_region(r->start, r->end - r->start + 1,
+	aup->ioarea = request_mem_region(r->start, resource_size(r),
 					 pdev->name);
 	if (!aup->ioarea)
 		goto out;
 
-	aup->iobase = ioremap_nocache(r->start, r->end - r->start + 1);
+	aup->iobase = ioremap_nocache(r->start, resource_size(r));
 	if (!aup->iobase)
 		goto out2;
 
@@ -952,18 +953,7 @@ static struct platform_driver au1k_irda_driver = {
 	.remove		= au1k_irda_remove,
 };
 
-static int __init au1k_irda_load(void)
-{
-	return platform_driver_register(&au1k_irda_driver);
-}
-
-static void __exit au1k_irda_unload(void)
-{
-	return platform_driver_unregister(&au1k_irda_driver);
-}
+module_platform_driver(au1k_irda_driver);
 
 MODULE_AUTHOR("Pete Popov <ppopov@mvista.com>");
 MODULE_DESCRIPTION("Au1000 IrDA Device Driver");
-
-module_init(au1k_irda_load);
-module_exit(au1k_irda_unload);
diff --git a/drivers/net/irda/bfin_sir.c b/drivers/net/irda/bfin_sir.c
index fed4a05..a06fca6 100644
--- a/drivers/net/irda/bfin_sir.c
+++ b/drivers/net/irda/bfin_sir.c
@@ -389,7 +389,8 @@ static int bfin_sir_startup(struct bfin_sir_port *port, struct net_device *dev)
 	set_dma_callback(port->rx_dma_channel, bfin_sir_dma_rx_int, dev);
 	set_dma_callback(port->tx_dma_channel, bfin_sir_dma_tx_int, dev);
 
-	port->rx_dma_buf.buf = (unsigned char *)dma_alloc_coherent(NULL, PAGE_SIZE, &dma_handle, GFP_DMA);
+	port->rx_dma_buf.buf = dma_alloc_coherent(NULL, PAGE_SIZE,
+						  &dma_handle, GFP_DMA);
 	port->rx_dma_buf.head = 0;
 	port->rx_dma_buf.tail = 0;
 	port->rx_dma_nrows = 0;
diff --git a/drivers/net/irda/nsc-ircc.c b/drivers/net/irda/nsc-ircc.c
index 2a4f2f1..9cf836b 100644
--- a/drivers/net/irda/nsc-ircc.c
+++ b/drivers/net/irda/nsc-ircc.c
@@ -431,22 +431,20 @@ static int __init nsc_ircc_open(chipio_t *info)
 	/* Allocate memory if needed */
 	self->rx_buff.head =
 		dma_alloc_coherent(NULL, self->rx_buff.truesize,
-				   &self->rx_buff_dma, GFP_KERNEL);
+				   &self->rx_buff_dma, GFP_KERNEL | __GFP_ZERO);
 	if (self->rx_buff.head == NULL) {
 		err = -ENOMEM;
 		goto out2;
 
 	}
-	memset(self->rx_buff.head, 0, self->rx_buff.truesize);
 	
 	self->tx_buff.head =
 		dma_alloc_coherent(NULL, self->tx_buff.truesize,
-				   &self->tx_buff_dma, GFP_KERNEL);
+				   &self->tx_buff_dma, GFP_KERNEL | __GFP_ZERO);
 	if (self->tx_buff.head == NULL) {
 		err = -ENOMEM;
 		goto out3;
 	}
-	memset(self->tx_buff.head, 0, self->tx_buff.truesize);
 
 	self->rx_buff.in_frame = FALSE;
 	self->rx_buff.state = OUTSIDE_FRAME;
diff --git a/drivers/net/irda/pxaficp_ir.c b/drivers/net/irda/pxaficp_ir.c
index 858de05..964b116 100644
--- a/drivers/net/irda/pxaficp_ir.c
+++ b/drivers/net/irda/pxaficp_ir.c
@@ -700,12 +700,12 @@ static int pxa_irda_start(struct net_device *dev)
 
 	err = -ENOMEM;
 	si->dma_rx_buff = dma_alloc_coherent(si->dev, IRDA_FRAME_SIZE_LIMIT,
-					     &si->dma_rx_buff_phy, GFP_KERNEL );
+					     &si->dma_rx_buff_phy, GFP_KERNEL);
 	if (!si->dma_rx_buff)
 		goto err_dma_rx_buff;
 
 	si->dma_tx_buff = dma_alloc_coherent(si->dev, IRDA_FRAME_SIZE_LIMIT,
-					     &si->dma_tx_buff_phy, GFP_KERNEL );
+					     &si->dma_tx_buff_phy, GFP_KERNEL);
 	if (!si->dma_tx_buff)
 		goto err_dma_tx_buff;
 
diff --git a/drivers/net/irda/smsc-ircc2.c b/drivers/net/irda/smsc-ircc2.c
index 5290952..aa05dad 100644
--- a/drivers/net/irda/smsc-ircc2.c
+++ b/drivers/net/irda/smsc-ircc2.c
@@ -563,24 +563,15 @@ static int smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u8 dma,
 
 	self->rx_buff.head =
 		dma_alloc_coherent(NULL, self->rx_buff.truesize,
-				   &self->rx_buff_dma, GFP_KERNEL);
-	if (self->rx_buff.head == NULL) {
-		IRDA_ERROR("%s, Can't allocate memory for receive buffer!\n",
-			   driver_name);
+				   &self->rx_buff_dma, GFP_KERNEL | __GFP_ZERO);
+	if (self->rx_buff.head == NULL)
 		goto err_out2;
-	}
 
 	self->tx_buff.head =
 		dma_alloc_coherent(NULL, self->tx_buff.truesize,
-				   &self->tx_buff_dma, GFP_KERNEL);
-	if (self->tx_buff.head == NULL) {
-		IRDA_ERROR("%s, Can't allocate memory for transmit buffer!\n",
-			   driver_name);
+				   &self->tx_buff_dma, GFP_KERNEL | __GFP_ZERO);
+	if (self->tx_buff.head == NULL)
 		goto err_out3;
-	}
-
-	memset(self->rx_buff.head, 0, self->rx_buff.truesize);
-	memset(self->tx_buff.head, 0, self->tx_buff.truesize);
 
 	self->rx_buff.in_frame = FALSE;
 	self->rx_buff.state = OUTSIDE_FRAME;
diff --git a/drivers/net/irda/via-ircc.c b/drivers/net/irda/via-ircc.c
index f9033c6..51f2bc3 100644
--- a/drivers/net/irda/via-ircc.c
+++ b/drivers/net/irda/via-ircc.c
@@ -364,21 +364,19 @@ static int via_ircc_open(struct pci_dev *pdev, chipio_t *info, unsigned int id)
 	/* Allocate memory if needed */
 	self->rx_buff.head =
 		dma_alloc_coherent(&pdev->dev, self->rx_buff.truesize,
-				   &self->rx_buff_dma, GFP_KERNEL);
+				   &self->rx_buff_dma, GFP_KERNEL | __GFP_ZERO);
 	if (self->rx_buff.head == NULL) {
 		err = -ENOMEM;
 		goto err_out2;
 	}
-	memset(self->rx_buff.head, 0, self->rx_buff.truesize);
 
 	self->tx_buff.head =
 		dma_alloc_coherent(&pdev->dev, self->tx_buff.truesize,
-				   &self->tx_buff_dma, GFP_KERNEL);
+				   &self->tx_buff_dma, GFP_KERNEL | __GFP_ZERO);
 	if (self->tx_buff.head == NULL) {
 		err = -ENOMEM;
 		goto err_out3;
 	}
-	memset(self->tx_buff.head, 0, self->tx_buff.truesize);
 
 	self->rx_buff.in_frame = FALSE;
 	self->rx_buff.state = OUTSIDE_FRAME;
diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c
index 2f99f88..e22cd4e 100644
--- a/drivers/net/irda/vlsi_ir.c
+++ b/drivers/net/irda/vlsi_ir.c
@@ -383,7 +383,7 @@ static int vlsi_seq_show(struct seq_file *seq, void *v)
 
 static int vlsi_seq_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, vlsi_seq_show, PDE(inode)->data);
+	return single_open(file, vlsi_seq_show, PDE_DATA(inode));
 }
 
 static const struct file_operations vlsi_proc_fops = {
diff --git a/drivers/net/irda/w83977af_ir.c b/drivers/net/irda/w83977af_ir.c
index f5bb92f..bb8857a 100644
--- a/drivers/net/irda/w83977af_ir.c
+++ b/drivers/net/irda/w83977af_ir.c
@@ -216,22 +216,19 @@ static int w83977af_open(int i, unsigned int iobase, unsigned int irq,
 	/* Allocate memory if needed */
 	self->rx_buff.head =
 		dma_alloc_coherent(NULL, self->rx_buff.truesize,
-				   &self->rx_buff_dma, GFP_KERNEL);
+				   &self->rx_buff_dma, GFP_KERNEL | __GFP_ZERO);
 	if (self->rx_buff.head == NULL) {
 		err = -ENOMEM;
 		goto err_out1;
 	}
 
-	memset(self->rx_buff.head, 0, self->rx_buff.truesize);
-	
 	self->tx_buff.head =
 		dma_alloc_coherent(NULL, self->tx_buff.truesize,
-				   &self->tx_buff_dma, GFP_KERNEL);
+				   &self->tx_buff_dma, GFP_KERNEL | __GFP_ZERO);
 	if (self->tx_buff.head == NULL) {
 		err = -ENOMEM;
 		goto err_out2;
 	}
-	memset(self->tx_buff.head, 0, self->tx_buff.truesize);
 
 	self->rx_buff.in_frame = FALSE;
 	self->rx_buff.state = OUTSIDE_FRAME;
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index 73abbc1..70af6dc 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -46,9 +46,16 @@ struct macvlan_port {
 
 static void macvlan_port_destroy(struct net_device *dev);
 
-#define macvlan_port_get_rcu(dev) \
-	((struct macvlan_port *) rcu_dereference(dev->rx_handler_data))
-#define macvlan_port_get(dev) ((struct macvlan_port *) dev->rx_handler_data)
+static struct macvlan_port *macvlan_port_get_rcu(const struct net_device *dev)
+{
+	return rcu_dereference(dev->rx_handler_data);
+}
+
+static struct macvlan_port *macvlan_port_get_rtnl(const struct net_device *dev)
+{
+	return rtnl_dereference(dev->rx_handler_data);
+}
+
 #define macvlan_port_exists(dev) (dev->priv_flags & IFF_MACVLAN_PORT)
 
 static struct macvlan_dev *macvlan_hash_lookup(const struct macvlan_port *port,
@@ -703,7 +710,7 @@ static int macvlan_port_create(struct net_device *dev)
 
 static void macvlan_port_destroy(struct net_device *dev)
 {
-	struct macvlan_port *port = macvlan_port_get(dev);
+	struct macvlan_port *port = macvlan_port_get_rtnl(dev);
 
 	dev->priv_flags &= ~IFF_MACVLAN_PORT;
 	netdev_rx_handler_unregister(dev);
@@ -772,7 +779,7 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
 		if (err < 0)
 			return err;
 	}
-	port = macvlan_port_get(lowerdev);
+	port = macvlan_port_get_rtnl(lowerdev);
 
 	/* Only 1 macvlan device can be created in passthru mode */
 	if (port->passthru)
@@ -921,7 +928,7 @@ static int macvlan_device_event(struct notifier_block *unused,
 	if (!macvlan_port_exists(dev))
 		return NOTIFY_DONE;
 
-	port = macvlan_port_get(dev);
+	port = macvlan_port_get_rtnl(dev);
 
 	switch (event) {
 	case NETDEV_CHANGE:
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
index a449439..59e9605 100644
--- a/drivers/net/macvtap.c
+++ b/drivers/net/macvtap.c
@@ -725,6 +725,8 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m,
 			goto err_kfree;
 	}
 
+	skb_probe_transport_header(skb, ETH_HLEN);
+
 	rcu_read_lock_bh();
 	vlan = rcu_dereference_bh(q->vlan);
 	/* copy skb_ubuf_info for callback when skb has no error */
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index 59ac143..855541f 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -757,7 +757,7 @@ static void write_msg(struct console *con, const char *msg, unsigned int len)
 
 static struct console netconsole = {
 	.name	= "netcon",
-	.flags	= CON_ENABLED,
+	.flags	= CON_ENABLED | CON_ALLDATA,
 	.write	= write_msg,
 };
 
diff --git a/drivers/net/phy/lxt.c b/drivers/net/phy/lxt.c
index ec40ba8..ff2e45e 100644
--- a/drivers/net/phy/lxt.c
+++ b/drivers/net/phy/lxt.c
@@ -159,7 +159,7 @@ static int lxt973a2_update_link(struct phy_device *phydev)
 	return 0;
 }
 
-int lxt973a2_read_status(struct phy_device *phydev)
+static int lxt973a2_read_status(struct phy_device *phydev)
 {
 	int adv;
 	int err;
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index 22dec9c..202fe1f 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -7,6 +7,8 @@
  *
  * Copyright (c) 2004 Freescale Semiconductor, Inc.
  *
+ * Copyright (c) 2013 Michael Stapelberg <michael@stapelberg.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
@@ -80,6 +82,28 @@
 #define MII_88E1318S_PHY_MSCR1_REG	16
 #define MII_88E1318S_PHY_MSCR1_PAD_ODD	BIT(6)
 
+/* Copper Specific Interrupt Enable Register */
+#define MII_88E1318S_PHY_CSIER                              0x12
+/* WOL Event Interrupt Enable */
+#define MII_88E1318S_PHY_CSIER_WOL_EIE                      BIT(7)
+
+/* LED Timer Control Register */
+#define MII_88E1318S_PHY_LED_PAGE                           0x03
+#define MII_88E1318S_PHY_LED_TCR                            0x12
+#define MII_88E1318S_PHY_LED_TCR_FORCE_INT                  BIT(15)
+#define MII_88E1318S_PHY_LED_TCR_INTn_ENABLE                BIT(7)
+#define MII_88E1318S_PHY_LED_TCR_INT_ACTIVE_LOW             BIT(11)
+
+/* Magic Packet MAC address registers */
+#define MII_88E1318S_PHY_MAGIC_PACKET_WORD2                 0x17
+#define MII_88E1318S_PHY_MAGIC_PACKET_WORD1                 0x18
+#define MII_88E1318S_PHY_MAGIC_PACKET_WORD0                 0x19
+
+#define MII_88E1318S_PHY_WOL_PAGE                           0x11
+#define MII_88E1318S_PHY_WOL_CTRL                           0x10
+#define MII_88E1318S_PHY_WOL_CTRL_CLEAR_WOL_STATUS          BIT(12)
+#define MII_88E1318S_PHY_WOL_CTRL_MAGIC_PACKET_MATCH_ENABLE BIT(14)
+
 #define MII_88E1121_PHY_LED_CTRL	16
 #define MII_88E1121_PHY_LED_PAGE	3
 #define MII_88E1121_PHY_LED_DEF		0x0030
@@ -696,6 +720,107 @@ static int m88e1121_did_interrupt(struct phy_device *phydev)
 	return 0;
 }
 
+static void m88e1318_get_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol)
+{
+	wol->supported = WAKE_MAGIC;
+	wol->wolopts = 0;
+
+	if (phy_write(phydev, MII_MARVELL_PHY_PAGE,
+		      MII_88E1318S_PHY_WOL_PAGE) < 0)
+		return;
+
+	if (phy_read(phydev, MII_88E1318S_PHY_WOL_CTRL) &
+	    MII_88E1318S_PHY_WOL_CTRL_MAGIC_PACKET_MATCH_ENABLE)
+		wol->wolopts |= WAKE_MAGIC;
+
+	if (phy_write(phydev, MII_MARVELL_PHY_PAGE, 0x00) < 0)
+		return;
+}
+
+static int m88e1318_set_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol)
+{
+	int err, oldpage, temp;
+
+	oldpage = phy_read(phydev, MII_MARVELL_PHY_PAGE);
+
+	if (wol->wolopts & WAKE_MAGIC) {
+		/* Explicitly switch to page 0x00, just to be sure */
+		err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 0x00);
+		if (err < 0)
+			return err;
+
+		/* Enable the WOL interrupt */
+		temp = phy_read(phydev, MII_88E1318S_PHY_CSIER);
+		temp |= MII_88E1318S_PHY_CSIER_WOL_EIE;
+		err = phy_write(phydev, MII_88E1318S_PHY_CSIER, temp);
+		if (err < 0)
+			return err;
+
+		err = phy_write(phydev, MII_MARVELL_PHY_PAGE,
+				MII_88E1318S_PHY_LED_PAGE);
+		if (err < 0)
+			return err;
+
+		/* Setup LED[2] as interrupt pin (active low) */
+		temp = phy_read(phydev, MII_88E1318S_PHY_LED_TCR);
+		temp &= ~MII_88E1318S_PHY_LED_TCR_FORCE_INT;
+		temp |= MII_88E1318S_PHY_LED_TCR_INTn_ENABLE;
+		temp |= MII_88E1318S_PHY_LED_TCR_INT_ACTIVE_LOW;
+		err = phy_write(phydev, MII_88E1318S_PHY_LED_TCR, temp);
+		if (err < 0)
+			return err;
+
+		err = phy_write(phydev, MII_MARVELL_PHY_PAGE,
+				MII_88E1318S_PHY_WOL_PAGE);
+		if (err < 0)
+			return err;
+
+		/* Store the device address for the magic packet */
+		err = phy_write(phydev, MII_88E1318S_PHY_MAGIC_PACKET_WORD2,
+				((phydev->attached_dev->dev_addr[5] << 8) |
+				 phydev->attached_dev->dev_addr[4]));
+		if (err < 0)
+			return err;
+		err = phy_write(phydev, MII_88E1318S_PHY_MAGIC_PACKET_WORD1,
+				((phydev->attached_dev->dev_addr[3] << 8) |
+				 phydev->attached_dev->dev_addr[2]));
+		if (err < 0)
+			return err;
+		err = phy_write(phydev, MII_88E1318S_PHY_MAGIC_PACKET_WORD0,
+				((phydev->attached_dev->dev_addr[1] << 8) |
+				 phydev->attached_dev->dev_addr[0]));
+		if (err < 0)
+			return err;
+
+		/* Clear WOL status and enable magic packet matching */
+		temp = phy_read(phydev, MII_88E1318S_PHY_WOL_CTRL);
+		temp |= MII_88E1318S_PHY_WOL_CTRL_CLEAR_WOL_STATUS;
+		temp |= MII_88E1318S_PHY_WOL_CTRL_MAGIC_PACKET_MATCH_ENABLE;
+		err = phy_write(phydev, MII_88E1318S_PHY_WOL_CTRL, temp);
+		if (err < 0)
+			return err;
+	} else {
+		err = phy_write(phydev, MII_MARVELL_PHY_PAGE,
+				MII_88E1318S_PHY_WOL_PAGE);
+		if (err < 0)
+			return err;
+
+		/* Clear WOL status and disable magic packet matching */
+		temp = phy_read(phydev, MII_88E1318S_PHY_WOL_CTRL);
+		temp |= MII_88E1318S_PHY_WOL_CTRL_CLEAR_WOL_STATUS;
+		temp &= ~MII_88E1318S_PHY_WOL_CTRL_MAGIC_PACKET_MATCH_ENABLE;
+		err = phy_write(phydev, MII_88E1318S_PHY_WOL_CTRL, temp);
+		if (err < 0)
+			return err;
+	}
+
+	err = phy_write(phydev, MII_MARVELL_PHY_PAGE, oldpage);
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
 static struct phy_driver marvell_drivers[] = {
 	{
 		.phy_id = MARVELL_PHY_ID_88E1101,
@@ -772,6 +897,8 @@ static struct phy_driver marvell_drivers[] = {
 		.ack_interrupt = &marvell_ack_interrupt,
 		.config_intr = &marvell_config_intr,
 		.did_interrupt = &m88e1121_did_interrupt,
+		.get_wol = &m88e1318_get_wol,
+		.set_wol = &m88e1318_set_wol,
 		.driver = { .owner = THIS_MODULE },
 	},
 	{
diff --git a/drivers/net/phy/mdio-gpio.c b/drivers/net/phy/mdio-gpio.c
index 2727498..a47f923 100644
--- a/drivers/net/phy/mdio-gpio.c
+++ b/drivers/net/phy/mdio-gpio.c
@@ -235,17 +235,7 @@ static struct platform_driver mdio_gpio_driver = {
 	},
 };
 
-static int __init mdio_gpio_init(void)
-{
-	return platform_driver_register(&mdio_gpio_driver);
-}
-module_init(mdio_gpio_init);
-
-static void __exit mdio_gpio_exit(void)
-{
-	platform_driver_unregister(&mdio_gpio_driver);
-}
-module_exit(mdio_gpio_exit);
+module_platform_driver(mdio_gpio_driver);
 
 MODULE_ALIAS("platform:mdio-gpio");
 MODULE_AUTHOR("Laurent Pinchart, Paulius Zaleckas");
diff --git a/drivers/net/phy/mdio-octeon.c b/drivers/net/phy/mdio-octeon.c
index 09297fe..c2c878d 100644
--- a/drivers/net/phy/mdio-octeon.c
+++ b/drivers/net/phy/mdio-octeon.c
@@ -197,18 +197,7 @@ void octeon_mdiobus_force_mod_depencency(void)
 }
 EXPORT_SYMBOL(octeon_mdiobus_force_mod_depencency);
 
-static int __init octeon_mdiobus_mod_init(void)
-{
-	return platform_driver_register(&octeon_mdiobus_driver);
-}
-
-static void __exit octeon_mdiobus_mod_exit(void)
-{
-	platform_driver_unregister(&octeon_mdiobus_driver);
-}
-
-module_init(octeon_mdiobus_mod_init);
-module_exit(octeon_mdiobus_mod_exit);
+module_platform_driver(octeon_mdiobus_driver);
 
 MODULE_DESCRIPTION(DRV_DESCRIPTION);
 MODULE_VERSION(DRV_VERSION);
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index abf7b61..2510435 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -53,6 +53,18 @@
 #define KS8737_CTRL_INT_ACTIVE_HIGH		(1 << 14)
 #define KSZ8051_RMII_50MHZ_CLK			(1 << 7)
 
+static int ksz_config_flags(struct phy_device *phydev)
+{
+	int regval;
+
+	if (phydev->dev_flags & MICREL_PHY_50MHZ_CLK) {
+		regval = phy_read(phydev, MII_KSZPHY_CTRL);
+		regval |= KSZ8051_RMII_50MHZ_CLK;
+		return phy_write(phydev, MII_KSZPHY_CTRL, regval);
+	}
+	return 0;
+}
+
 static int kszphy_ack_interrupt(struct phy_device *phydev)
 {
 	/* bit[7..0] int status, which is a read and clear register. */
@@ -114,22 +126,19 @@ static int kszphy_config_init(struct phy_device *phydev)
 
 static int ksz8021_config_init(struct phy_device *phydev)
 {
+	int rc;
 	const u16 val = KSZPHY_OMSO_B_CAST_OFF | KSZPHY_OMSO_RMII_OVERRIDE;
 	phy_write(phydev, MII_KSZPHY_OMSO, val);
-	return 0;
+	rc = ksz_config_flags(phydev);
+	return rc < 0 ? rc : 0;
 }
 
 static int ks8051_config_init(struct phy_device *phydev)
 {
-	int regval;
-
-	if (phydev->dev_flags & MICREL_PHY_50MHZ_CLK) {
-		regval = phy_read(phydev, MII_KSZPHY_CTRL);
-		regval |= KSZ8051_RMII_50MHZ_CLK;
-		phy_write(phydev, MII_KSZPHY_CTRL, regval);
-	}
+	int rc;
 
-	return 0;
+	rc = ksz_config_flags(phydev);
+	return rc < 0 ? rc : 0;
 }
 
 #define KSZ8873MLL_GLOBAL_CONTROL_4	0x06
@@ -192,6 +201,19 @@ static struct phy_driver ksphy_driver[] = {
 	.config_intr	= kszphy_config_intr,
 	.driver		= { .owner = THIS_MODULE,},
 }, {
+	.phy_id		= PHY_ID_KSZ8031,
+	.phy_id_mask	= 0x00ffffff,
+	.name		= "Micrel KSZ8031",
+	.features	= (PHY_BASIC_FEATURES | SUPPORTED_Pause |
+			   SUPPORTED_Asym_Pause),
+	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
+	.config_init	= ksz8021_config_init,
+	.config_aneg	= genphy_config_aneg,
+	.read_status	= genphy_read_status,
+	.ack_interrupt	= kszphy_ack_interrupt,
+	.config_intr	= kszphy_config_intr,
+	.driver		= { .owner = THIS_MODULE,},
+}, {
 	.phy_id		= PHY_ID_KSZ8041,
 	.phy_id_mask	= 0x00fffff0,
 	.name		= "Micrel KSZ8041",
@@ -325,6 +347,7 @@ static struct mdio_device_id __maybe_unused micrel_tbl[] = {
 	{ PHY_ID_KSZ8001, 0x00ffffff },
 	{ PHY_ID_KS8737, 0x00fffff0 },
 	{ PHY_ID_KSZ8021, 0x00ffffff },
+	{ PHY_ID_KSZ8031, 0x00ffffff },
 	{ PHY_ID_KSZ8041, 0x00fffff0 },
 	{ PHY_ID_KSZ8051, 0x00fffff0 },
 	{ PHY_ID_KSZ8061, 0x00fffff0 },
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index ef9ea92..c14f147 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -463,33 +463,6 @@ void phy_stop_machine(struct phy_device *phydev)
 }
 
 /**
- * phy_force_reduction - reduce PHY speed/duplex settings by one step
- * @phydev: target phy_device struct
- *
- * Description: Reduces the speed/duplex settings by one notch,
- *   in this order--
- *   1000/FULL, 1000/HALF, 100/FULL, 100/HALF, 10/FULL, 10/HALF.
- *   The function bottoms out at 10/HALF.
- */
-static void phy_force_reduction(struct phy_device *phydev)
-{
-	int idx;
-
-	idx = phy_find_setting(phydev->speed, phydev->duplex);
-	
-	idx++;
-
-	idx = phy_find_valid(idx, phydev->supported);
-
-	phydev->speed = settings[idx].speed;
-	phydev->duplex = settings[idx].duplex;
-
-	pr_info("Trying %d/%s\n",
-		phydev->speed, DUPLEX_FULL == phydev->duplex ? "FULL" : "HALF");
-}
-
-
-/**
  * phy_error - enter HALTED state for this PHY device
  * @phydev: target phy_device struct
  *
@@ -818,30 +791,11 @@ void phy_state_machine(struct work_struct *work)
 				phydev->adjust_link(phydev->attached_dev);
 
 			} else if (0 == phydev->link_timeout--) {
-				int idx;
-
 				needs_aneg = 1;
 				/* If we have the magic_aneg bit,
 				 * we try again */
 				if (phydev->drv->flags & PHY_HAS_MAGICANEG)
 					break;
-
-				/* The timer expired, and we still
-				 * don't have a setting, so we try
-				 * forcing it until we find one that
-				 * works, starting from the fastest speed,
-				 * and working our way down */
-				idx = phy_find_valid(0, phydev->supported);
-
-				phydev->speed = settings[idx].speed;
-				phydev->duplex = settings[idx].duplex;
-
-				phydev->autoneg = AUTONEG_DISABLE;
-
-				pr_info("Trying %d/%s\n",
-					phydev->speed,
-					DUPLEX_FULL == phydev->duplex ?
-					"FULL" : "HALF");
 			}
 			break;
 		case PHY_NOLINK:
@@ -866,10 +820,8 @@ void phy_state_machine(struct work_struct *work)
 				phydev->state = PHY_RUNNING;
 				netif_carrier_on(phydev->attached_dev);
 			} else {
-				if (0 == phydev->link_timeout--) {
-					phy_force_reduction(phydev);
+				if (0 == phydev->link_timeout--)
 					needs_aneg = 1;
-				}
 			}
 
 			phydev->adjust_link(phydev->attached_dev);
@@ -1188,3 +1140,19 @@ int phy_ethtool_set_eee(struct phy_device *phydev, struct ethtool_eee *data)
 	return 0;
 }
 EXPORT_SYMBOL(phy_ethtool_set_eee);
+
+int phy_ethtool_set_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol)
+{
+	if (phydev->drv->set_wol)
+		return phydev->drv->set_wol(phydev, wol);
+
+	return -EOPNOTSUPP;
+}
+EXPORT_SYMBOL(phy_ethtool_set_wol);
+
+void phy_ethtool_get_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol)
+{
+	if (phydev->drv->get_wol)
+		phydev->drv->get_wol(phydev, wol);
+}
+EXPORT_SYMBOL(phy_ethtool_get_wol);
diff --git a/drivers/net/phy/vitesse.c b/drivers/net/phy/vitesse.c
index 2585c38..3492b53 100644
--- a/drivers/net/phy/vitesse.c
+++ b/drivers/net/phy/vitesse.c
@@ -61,7 +61,7 @@ MODULE_DESCRIPTION("Vitesse PHY driver");
 MODULE_AUTHOR("Kriston Carson");
 MODULE_LICENSE("GPL");
 
-int vsc824x_add_skew(struct phy_device *phydev)
+static int vsc824x_add_skew(struct phy_device *phydev)
 {
 	int err;
 	int extcon;
@@ -81,7 +81,6 @@ int vsc824x_add_skew(struct phy_device *phydev)
 
 	return err;
 }
-EXPORT_SYMBOL(vsc824x_add_skew);
 
 static int vsc824x_config_init(struct phy_device *phydev)
 {
diff --git a/drivers/net/plip/plip.c b/drivers/net/plip/plip.c
index bed62d9..1f7bef9 100644
--- a/drivers/net/plip/plip.c
+++ b/drivers/net/plip/plip.c
@@ -560,7 +560,7 @@ static __be16 plip_type_trans(struct sk_buff *skb, struct net_device *dev)
 	 *	so don't forget to remove it.
 	 */
 
-	if (ntohs(eth->h_proto) >= 1536)
+	if (ntohs(eth->h_proto) >= ETH_P_802_3_MIN)
 		return eth->h_proto;
 
 	rawp = skb->data;
diff --git a/drivers/net/ppp/ppp_async.c b/drivers/net/ppp/ppp_async.c
index a031f6b..9c889e0 100644
--- a/drivers/net/ppp/ppp_async.c
+++ b/drivers/net/ppp/ppp_async.c
@@ -314,7 +314,7 @@ ppp_asynctty_ioctl(struct tty_struct *tty, struct file *file,
 		/* flush our buffers and the serial port's buffer */
 		if (arg == TCIOFLUSH || arg == TCOFLUSH)
 			ppp_async_flush_output(ap);
-		err = tty_perform_flush(tty, arg);
+		err = n_tty_ioctl_helper(tty, file, cmd, arg);
 		break;
 
 	case FIONREAD:
diff --git a/drivers/net/ppp/ppp_synctty.c b/drivers/net/ppp/ppp_synctty.c
index 1a12033..925d3e2 100644
--- a/drivers/net/ppp/ppp_synctty.c
+++ b/drivers/net/ppp/ppp_synctty.c
@@ -105,64 +105,15 @@ static const struct ppp_channel_ops sync_ops = {
 };
 
 /*
- * Utility procedures to print a buffer in hex/ascii
+ * Utility procedure to print a buffer in hex/ascii
  */
 static void
-ppp_print_hex (register __u8 * out, const __u8 * in, int count)
-{
-	register __u8 next_ch;
-	static const char hex[] = "0123456789ABCDEF";
-
-	while (count-- > 0) {
-		next_ch = *in++;
-		*out++ = hex[(next_ch >> 4) & 0x0F];
-		*out++ = hex[next_ch & 0x0F];
-		++out;
-	}
-}
-
-static void
-ppp_print_char (register __u8 * out, const __u8 * in, int count)
-{
-	register __u8 next_ch;
-
-	while (count-- > 0) {
-		next_ch = *in++;
-
-		if (next_ch < 0x20 || next_ch > 0x7e)
-			*out++ = '.';
-		else {
-			*out++ = next_ch;
-			if (next_ch == '%')   /* printk/syslogd has a bug !! */
-				*out++ = '%';
-		}
-	}
-	*out = '\0';
-}
-
-static void
 ppp_print_buffer (const char *name, const __u8 *buf, int count)
 {
-	__u8 line[44];
-
 	if (name != NULL)
 		printk(KERN_DEBUG "ppp_synctty: %s, count = %d\n", name, count);
 
-	while (count > 8) {
-		memset (line, 32, 44);
-		ppp_print_hex (line, buf, 8);
-		ppp_print_char (&line[8 * 3], buf, 8);
-		printk(KERN_DEBUG "%s\n", line);
-		count -= 8;
-		buf += 8;
-	}
-
-	if (count > 0) {
-		memset (line, 32, 44);
-		ppp_print_hex (line, buf, count);
-		ppp_print_char (&line[8 * 3], buf, count);
-		printk(KERN_DEBUG "%s\n", line);
-	}
+	print_hex_dump_bytes("", DUMP_PREFIX_NONE, buf, count);
 }
 
 
@@ -355,7 +306,7 @@ ppp_synctty_ioctl(struct tty_struct *tty, struct file *file,
 		/* flush our buffers and the serial port's buffer */
 		if (arg == TCIOFLUSH || arg == TCOFLUSH)
 			ppp_sync_flush_output(ap);
-		err = tty_perform_flush(tty, arg);
+		err = n_tty_ioctl_helper(tty, file, cmd, arg);
 		break;
 
 	case FIONREAD:
diff --git a/drivers/net/team/Kconfig b/drivers/net/team/Kconfig
index c3011af..c853d84 100644
--- a/drivers/net/team/Kconfig
+++ b/drivers/net/team/Kconfig
@@ -37,6 +37,18 @@ config NET_TEAM_MODE_ROUNDROBIN
 	  To compile this team mode as a module, choose M here: the module
 	  will be called team_mode_roundrobin.
 
+config NET_TEAM_MODE_RANDOM
+	tristate "Random mode support"
+	depends on NET_TEAM
+	---help---
+	  Basic mode where port used for transmitting packets is selected
+	  randomly.
+
+	  All added ports are setup to have team's device address.
+
+	  To compile this team mode as a module, choose M here: the module
+	  will be called team_mode_random.
+
 config NET_TEAM_MODE_ACTIVEBACKUP
 	tristate "Active-backup mode support"
 	depends on NET_TEAM
diff --git a/drivers/net/team/Makefile b/drivers/net/team/Makefile
index 9757630..c57e858 100644
--- a/drivers/net/team/Makefile
+++ b/drivers/net/team/Makefile
@@ -5,5 +5,6 @@
 obj-$(CONFIG_NET_TEAM) += team.o
 obj-$(CONFIG_NET_TEAM_MODE_BROADCAST) += team_mode_broadcast.o
 obj-$(CONFIG_NET_TEAM_MODE_ROUNDROBIN) += team_mode_roundrobin.o
+obj-$(CONFIG_NET_TEAM_MODE_RANDOM) += team_mode_random.o
 obj-$(CONFIG_NET_TEAM_MODE_ACTIVEBACKUP) += team_mode_activebackup.o
 obj-$(CONFIG_NET_TEAM_MODE_LOADBALANCE) += team_mode_loadbalance.o
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index bf34192..621c1bd 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -73,11 +73,24 @@ static int team_port_set_orig_dev_addr(struct team_port *port)
 	return __set_port_dev_addr(port->dev, port->orig.dev_addr);
 }
 
-int team_port_set_team_dev_addr(struct team_port *port)
+static int team_port_set_team_dev_addr(struct team *team,
+				       struct team_port *port)
+{
+	return __set_port_dev_addr(port->dev, team->dev->dev_addr);
+}
+
+int team_modeop_port_enter(struct team *team, struct team_port *port)
+{
+	return team_port_set_team_dev_addr(team, port);
+}
+EXPORT_SYMBOL(team_modeop_port_enter);
+
+void team_modeop_port_change_dev_addr(struct team *team,
+				      struct team_port *port)
 {
-	return __set_port_dev_addr(port->dev, port->team->dev->dev_addr);
+	team_port_set_team_dev_addr(team, port);
 }
-EXPORT_SYMBOL(team_port_set_team_dev_addr);
+EXPORT_SYMBOL(team_modeop_port_change_dev_addr);
 
 static void team_refresh_port_linkup(struct team_port *port)
 {
@@ -490,9 +503,9 @@ static bool team_dummy_transmit(struct team *team, struct sk_buff *skb)
 	return false;
 }
 
-rx_handler_result_t team_dummy_receive(struct team *team,
-				       struct team_port *port,
-				       struct sk_buff *skb)
+static rx_handler_result_t team_dummy_receive(struct team *team,
+					      struct team_port *port,
+					      struct sk_buff *skb)
 {
 	return RX_HANDLER_ANOTHER;
 }
diff --git a/drivers/net/team/team_mode_broadcast.c b/drivers/net/team/team_mode_broadcast.c
index c5db428..c366cd2 100644
--- a/drivers/net/team/team_mode_broadcast.c
+++ b/drivers/net/team/team_mode_broadcast.c
@@ -46,20 +46,10 @@ static bool bc_transmit(struct team *team, struct sk_buff *skb)
 	return sum_ret;
 }
 
-static int bc_port_enter(struct team *team, struct team_port *port)
-{
-	return team_port_set_team_dev_addr(port);
-}
-
-static void bc_port_change_dev_addr(struct team *team, struct team_port *port)
-{
-	team_port_set_team_dev_addr(port);
-}
-
 static const struct team_mode_ops bc_mode_ops = {
 	.transmit		= bc_transmit,
-	.port_enter		= bc_port_enter,
-	.port_change_dev_addr	= bc_port_change_dev_addr,
+	.port_enter		= team_modeop_port_enter,
+	.port_change_dev_addr	= team_modeop_port_change_dev_addr,
 };
 
 static const struct team_mode bc_mode = {
diff --git a/drivers/net/team/team_mode_random.c b/drivers/net/team/team_mode_random.c
new file mode 100644
index 0000000..5ca14d4
--- /dev/null
+++ b/drivers/net/team/team_mode_random.c
@@ -0,0 +1,71 @@
+/*
+ * drivers/net/team/team_mode_random.c - Random mode for team
+ * Copyright (c) 2013 Jiri Pirko <jiri@resnulli.us>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/types.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/skbuff.h>
+#include <linux/reciprocal_div.h>
+#include <linux/if_team.h>
+
+static u32 random_N(unsigned int N)
+{
+	return reciprocal_divide(prandom_u32(), N);
+}
+
+static bool rnd_transmit(struct team *team, struct sk_buff *skb)
+{
+	struct team_port *port;
+	int port_index;
+
+	port_index = random_N(team->en_port_count);
+	port = team_get_port_by_index_rcu(team, port_index);
+	port = team_get_first_port_txable_rcu(team, port);
+	if (unlikely(!port))
+		goto drop;
+	if (team_dev_queue_xmit(team, port, skb))
+		return false;
+	return true;
+
+drop:
+	dev_kfree_skb_any(skb);
+	return false;
+}
+
+static const struct team_mode_ops rnd_mode_ops = {
+	.transmit		= rnd_transmit,
+	.port_enter		= team_modeop_port_enter,
+	.port_change_dev_addr	= team_modeop_port_change_dev_addr,
+};
+
+static const struct team_mode rnd_mode = {
+	.kind		= "random",
+	.owner		= THIS_MODULE,
+	.ops		= &rnd_mode_ops,
+};
+
+static int __init rnd_init_module(void)
+{
+	return team_mode_register(&rnd_mode);
+}
+
+static void __exit rnd_cleanup_module(void)
+{
+	team_mode_unregister(&rnd_mode);
+}
+
+module_init(rnd_init_module);
+module_exit(rnd_cleanup_module);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Jiri Pirko <jiri@resnulli.us>");
+MODULE_DESCRIPTION("Random mode for team");
+MODULE_ALIAS("team-mode-random");
diff --git a/drivers/net/team/team_mode_roundrobin.c b/drivers/net/team/team_mode_roundrobin.c
index 105135a..d268e4d 100644
--- a/drivers/net/team/team_mode_roundrobin.c
+++ b/drivers/net/team/team_mode_roundrobin.c
@@ -25,26 +25,6 @@ static struct rr_priv *rr_priv(struct team *team)
 	return (struct rr_priv *) &team->mode_priv;
 }
 
-static struct team_port *__get_first_port_up(struct team *team,
-					     struct team_port *port)
-{
-	struct team_port *cur;
-
-	if (team_port_txable(port))
-		return port;
-	cur = port;
-	list_for_each_entry_continue_rcu(cur, &team->port_list, list)
-		if (team_port_txable(port))
-			return cur;
-	list_for_each_entry_rcu(cur, &team->port_list, list) {
-		if (cur == port)
-			break;
-		if (team_port_txable(port))
-			return cur;
-	}
-	return NULL;
-}
-
 static bool rr_transmit(struct team *team, struct sk_buff *skb)
 {
 	struct team_port *port;
@@ -52,7 +32,7 @@ static bool rr_transmit(struct team *team, struct sk_buff *skb)
 
 	port_index = rr_priv(team)->sent_packets++ % team->en_port_count;
 	port = team_get_port_by_index_rcu(team, port_index);
-	port = __get_first_port_up(team, port);
+	port = team_get_first_port_txable_rcu(team, port);
 	if (unlikely(!port))
 		goto drop;
 	if (team_dev_queue_xmit(team, port, skb))
@@ -64,20 +44,10 @@ drop:
 	return false;
 }
 
-static int rr_port_enter(struct team *team, struct team_port *port)
-{
-	return team_port_set_team_dev_addr(port);
-}
-
-static void rr_port_change_dev_addr(struct team *team, struct team_port *port)
-{
-	team_port_set_team_dev_addr(port);
-}
-
 static const struct team_mode_ops rr_mode_ops = {
 	.transmit		= rr_transmit,
-	.port_enter		= rr_port_enter,
-	.port_change_dev_addr	= rr_port_change_dev_addr,
+	.port_enter		= team_modeop_port_enter,
+	.port_change_dev_addr	= team_modeop_port_change_dev_addr,
 };
 
 static const struct team_mode rr_mode = {
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index b7c457a..29538e6 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -409,14 +409,12 @@ static void __tun_detach(struct tun_file *tfile, bool clean)
 {
 	struct tun_file *ntfile;
 	struct tun_struct *tun;
-	struct net_device *dev;
 
 	tun = rtnl_dereference(tfile->tun);
 
 	if (tun && !tfile->detached) {
 		u16 index = tfile->queue_index;
 		BUG_ON(index >= tun->numqueues);
-		dev = tun->dev;
 
 		rcu_assign_pointer(tun->tfiles[index],
 				   tun->tfiles[tun->numqueues - 1]);
@@ -1205,6 +1203,8 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
 	}
 
 	skb_reset_network_header(skb);
+	skb_probe_transport_header(skb, 0);
+
 	rxhash = skb_get_rxhash(skb);
 	netif_rx_ni(skb);
 
diff --git a/drivers/net/usb/cdc_mbim.c b/drivers/net/usb/cdc_mbim.c
index 16c8429..673e362 100644
--- a/drivers/net/usb/cdc_mbim.c
+++ b/drivers/net/usb/cdc_mbim.c
@@ -323,6 +323,11 @@ static int cdc_mbim_suspend(struct usb_interface *intf, pm_message_t message)
 		goto error;
 	}
 
+	/*
+	 * Both usbnet_suspend() and subdriver->suspend() MUST return 0
+	 * in system sleep context, otherwise, the resume callback has
+	 * to recover device from previous suspend failure.
+	 */
 	ret = usbnet_suspend(intf, message);
 	if (ret < 0)
 		goto error;
diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c
index 4709fa3..44a989c 100644
--- a/drivers/net/usb/cdc_ncm.c
+++ b/drivers/net/usb/cdc_ncm.c
@@ -362,8 +362,8 @@ int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_
 	u8 iface_no;
 
 	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
-	if (ctx == NULL)
-		return -ENODEV;
+	if (!ctx)
+		return -ENOMEM;
 
 	hrtimer_init(&ctx->tx_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
 	ctx->tx_timer.function = &cdc_ncm_tx_timer_cb;
diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c
index e2dd324..cba1d46 100644
--- a/drivers/net/usb/hso.c
+++ b/drivers/net/usb/hso.c
@@ -1925,7 +1925,6 @@ static void hso_std_serial_write_bulk_callback(struct urb *urb)
 {
 	struct hso_serial *serial = urb->context;
 	int status = urb->status;
-	struct tty_struct *tty;
 
 	/* sanity check */
 	if (!serial) {
@@ -1941,11 +1940,7 @@ static void hso_std_serial_write_bulk_callback(struct urb *urb)
 		return;
 	}
 	hso_put_activity(serial->parent);
-	tty = tty_port_tty_get(&serial->port);
-	if (tty) {
-		tty_wakeup(tty);
-		tty_kref_put(tty);
-	}
+	tty_port_tty_wakeup(&serial->port);
 	hso_kick_transmit(serial);
 
 	D1(" ");
@@ -2008,12 +2003,8 @@ static void ctrl_callback(struct urb *urb)
 		put_rxbuf_data_and_resubmit_ctrl_urb(serial);
 		spin_unlock(&serial->serial_lock);
 	} else {
-		struct tty_struct *tty = tty_port_tty_get(&serial->port);
 		hso_put_activity(serial->parent);
-		if (tty) {
-			tty_wakeup(tty);
-			tty_kref_put(tty);
-		}
+		tty_port_tty_wakeup(&serial->port);
 		/* response to a write command */
 		hso_kick_transmit(serial);
 	}
@@ -3133,18 +3124,13 @@ static void hso_serial_ref_free(struct kref *ref)
 static void hso_free_interface(struct usb_interface *interface)
 {
 	struct hso_serial *hso_dev;
-	struct tty_struct *tty;
 	int i;
 
 	for (i = 0; i < HSO_SERIAL_TTY_MINORS; i++) {
 		if (serial_table[i] &&
 		    (serial_table[i]->interface == interface)) {
 			hso_dev = dev2ser(serial_table[i]);
-			tty = tty_port_tty_get(&hso_dev->port);
-			if (tty) {
-				tty_hangup(tty);
-				tty_kref_put(tty);
-			}
+			tty_port_tty_hangup(&hso_dev->port, false);
 			mutex_lock(&hso_dev->parent->mutex);
 			hso_dev->parent->usb_gone = 1;
 			mutex_unlock(&hso_dev->parent->mutex);
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
index 968d5d5..bdceb74 100644
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -271,6 +271,11 @@ static int qmi_wwan_suspend(struct usb_interface *intf, pm_message_t message)
 	struct qmi_wwan_state *info = (void *)&dev->data;
 	int ret;
 
+	/*
+	 * Both usbnet_suspend() and subdriver->suspend() MUST return 0
+	 * in system sleep context, otherwise, the resume callback has
+	 * to recover device from previous suspend failure.
+	 */
 	ret = usbnet_suspend(intf, message);
 	if (ret < 0)
 		goto err;
diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c
index 9abe517..7540974 100644
--- a/drivers/net/usb/smsc75xx.c
+++ b/drivers/net/usb/smsc75xx.c
@@ -914,8 +914,12 @@ static int smsc75xx_set_rx_max_frame_length(struct usbnet *dev, int size)
 static int smsc75xx_change_mtu(struct net_device *netdev, int new_mtu)
 {
 	struct usbnet *dev = netdev_priv(netdev);
+	int ret;
+
+	if (new_mtu > MAX_SINGLE_PACKET_SIZE)
+		return -EINVAL;
 
-	int ret = smsc75xx_set_rx_max_frame_length(dev, new_mtu);
+	ret = smsc75xx_set_rx_max_frame_length(dev, new_mtu + ETH_HLEN);
 	if (ret < 0) {
 		netdev_warn(dev->net, "Failed to set mac rx frame length\n");
 		return ret;
@@ -1324,7 +1328,7 @@ static int smsc75xx_reset(struct usbnet *dev)
 
 	netif_dbg(dev, ifup, dev->net, "FCT_TX_CTL set to 0x%08x\n", buf);
 
-	ret = smsc75xx_set_rx_max_frame_length(dev, 1514);
+	ret = smsc75xx_set_rx_max_frame_length(dev, dev->net->mtu + ETH_HLEN);
 	if (ret < 0) {
 		netdev_warn(dev->net, "Failed to set max rx frame length\n");
 		return ret;
@@ -2011,7 +2015,11 @@ static int smsc75xx_suspend(struct usb_interface *intf, pm_message_t message)
 	ret = smsc75xx_enter_suspend0(dev);
 
 done:
-	if (ret)
+	/*
+	 * TODO: resume() might need to handle the suspend failure
+	 * in system sleep
+	 */
+	if (ret && PMSG_IS_AUTO(message))
 		usbnet_resume(intf);
 	return ret;
 }
@@ -2134,8 +2142,8 @@ static int smsc75xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 			else if (rx_cmd_a & (RX_CMD_A_LONG | RX_CMD_A_RUNT))
 				dev->net->stats.rx_frame_errors++;
 		} else {
-			/* ETH_FRAME_LEN + 4(CRC) + 2(COE) + 4(Vlan) */
-			if (unlikely(size > (ETH_FRAME_LEN + 12))) {
+			/* MAX_SINGLE_PACKET_SIZE + 4(CRC) + 2(COE) + 4(Vlan) */
+			if (unlikely(size > (MAX_SINGLE_PACKET_SIZE + ETH_HLEN + 12))) {
 				netif_dbg(dev, rx_err, dev->net,
 					  "size err rx_cmd_a=0x%08x\n",
 					  rx_cmd_a);
diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c
index e6d2dea..3f38ba8 100644
--- a/drivers/net/usb/smsc95xx.c
+++ b/drivers/net/usb/smsc95xx.c
@@ -1660,7 +1660,11 @@ static int smsc95xx_suspend(struct usb_interface *intf, pm_message_t message)
 	ret = smsc95xx_enter_suspend0(dev);
 
 done:
-	if (ret)
+	/*
+	 * TODO: resume() might need to handle the suspend failure
+	 * in system sleep
+	 */
+	if (ret && PMSG_IS_AUTO(message))
 		usbnet_resume(intf);
 	return ret;
 }
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 57ac4b0..24fc9f5 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -39,7 +39,6 @@ module_param(gso, bool, 0444);
 #define MAX_PACKET_LEN (ETH_HLEN + VLAN_HLEN + ETH_DATA_LEN)
 #define GOOD_COPY_LEN	128
 
-#define VIRTNET_SEND_COMMAND_SG_MAX    2
 #define VIRTNET_DRIVER_VERSION "1.0.0"
 
 struct virtnet_stats {
@@ -154,7 +153,7 @@ struct padded_vnet_hdr {
  */
 static int vq2txq(struct virtqueue *vq)
 {
-	return (virtqueue_get_queue_index(vq) - 1) / 2;
+	return (vq->index - 1) / 2;
 }
 
 static int txq2vq(int txq)
@@ -164,7 +163,7 @@ static int txq2vq(int txq)
 
 static int vq2rxq(struct virtqueue *vq)
 {
-	return virtqueue_get_queue_index(vq) / 2;
+	return vq->index / 2;
 }
 
 static int rxq2vq(int rxq)
@@ -444,7 +443,7 @@ static int add_recvbuf_small(struct receive_queue *rq, gfp_t gfp)
 
 	skb_to_sgvec(skb, rq->sg + 1, 0, skb->len);
 
-	err = virtqueue_add_buf(rq->vq, rq->sg, 0, 2, skb, gfp);
+	err = virtqueue_add_inbuf(rq->vq, rq->sg, 2, skb, gfp);
 	if (err < 0)
 		dev_kfree_skb(skb);
 
@@ -489,8 +488,8 @@ static int add_recvbuf_big(struct receive_queue *rq, gfp_t gfp)
 
 	/* chain first in list head */
 	first->private = (unsigned long)list;
-	err = virtqueue_add_buf(rq->vq, rq->sg, 0, MAX_SKB_FRAGS + 2,
-				first, gfp);
+	err = virtqueue_add_inbuf(rq->vq, rq->sg, MAX_SKB_FRAGS + 2,
+				  first, gfp);
 	if (err < 0)
 		give_pages(rq, first);
 
@@ -508,7 +507,7 @@ static int add_recvbuf_mergeable(struct receive_queue *rq, gfp_t gfp)
 
 	sg_init_one(rq->sg, page_address(page), PAGE_SIZE);
 
-	err = virtqueue_add_buf(rq->vq, rq->sg, 0, 1, page, gfp);
+	err = virtqueue_add_inbuf(rq->vq, rq->sg, 1, page, gfp);
 	if (err < 0)
 		give_pages(rq, page);
 
@@ -711,8 +710,7 @@ static int xmit_skb(struct send_queue *sq, struct sk_buff *skb)
 		sg_set_buf(sq->sg, &hdr->hdr, sizeof hdr->hdr);
 
 	num_sg = skb_to_sgvec(skb, sq->sg + 1, 0, skb->len) + 1;
-	return virtqueue_add_buf(sq->vq, sq->sg, num_sg,
-				 0, skb, GFP_ATOMIC);
+	return virtqueue_add_outbuf(sq->vq, sq->sg, num_sg, skb, GFP_ATOMIC);
 }
 
 static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
@@ -767,32 +765,35 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
  * never fail unless improperly formated.
  */
 static bool virtnet_send_command(struct virtnet_info *vi, u8 class, u8 cmd,
-				 struct scatterlist *data, int out, int in)
+				 struct scatterlist *out,
+				 struct scatterlist *in)
 {
-	struct scatterlist *s, sg[VIRTNET_SEND_COMMAND_SG_MAX + 2];
+	struct scatterlist *sgs[4], hdr, stat;
 	struct virtio_net_ctrl_hdr ctrl;
 	virtio_net_ctrl_ack status = ~0;
-	unsigned int tmp;
-	int i;
+	unsigned out_num = 0, in_num = 0, tmp;
 
 	/* Caller should know better */
-	BUG_ON(!virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ) ||
-		(out + in > VIRTNET_SEND_COMMAND_SG_MAX));
-
-	out++; /* Add header */
-	in++; /* Add return status */
+	BUG_ON(!virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ));
 
 	ctrl.class = class;
 	ctrl.cmd = cmd;
+	/* Add header */
+	sg_init_one(&hdr, &ctrl, sizeof(ctrl));
+	sgs[out_num++] = &hdr;
 
-	sg_init_table(sg, out + in);
+	if (out)
+		sgs[out_num++] = out;
+	if (in)
+		sgs[out_num + in_num++] = in;
 
-	sg_set_buf(&sg[0], &ctrl, sizeof(ctrl));
-	for_each_sg(data, s, out + in - 2, i)
-		sg_set_buf(&sg[i + 1], sg_virt(s), s->length);
-	sg_set_buf(&sg[out + in - 1], &status, sizeof(status));
+	/* Add return status. */
+	sg_init_one(&stat, &status, sizeof(status));
+	sgs[out_num + in_num++] = &stat;
 
-	BUG_ON(virtqueue_add_buf(vi->cvq, sg, out, in, vi, GFP_ATOMIC) < 0);
+	BUG_ON(out_num + in_num > ARRAY_SIZE(sgs));
+	BUG_ON(virtqueue_add_sgs(vi->cvq, sgs, out_num, in_num, vi, GFP_ATOMIC)
+	       < 0);
 
 	virtqueue_kick(vi->cvq);
 
@@ -821,7 +822,7 @@ static int virtnet_set_mac_address(struct net_device *dev, void *p)
 		sg_init_one(&sg, addr->sa_data, dev->addr_len);
 		if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_MAC,
 					  VIRTIO_NET_CTRL_MAC_ADDR_SET,
-					  &sg, 1, 0)) {
+					  &sg, NULL)) {
 			dev_warn(&vdev->dev,
 				 "Failed to set mac address by vq command.\n");
 			return -EINVAL;
@@ -889,8 +890,7 @@ static void virtnet_ack_link_announce(struct virtnet_info *vi)
 {
 	rtnl_lock();
 	if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_ANNOUNCE,
-				  VIRTIO_NET_CTRL_ANNOUNCE_ACK, NULL,
-				  0, 0))
+				  VIRTIO_NET_CTRL_ANNOUNCE_ACK, NULL, NULL))
 		dev_warn(&vi->dev->dev, "Failed to ack link announce.\n");
 	rtnl_unlock();
 }
@@ -908,7 +908,7 @@ static int virtnet_set_queues(struct virtnet_info *vi, u16 queue_pairs)
 	sg_init_one(&sg, &s, sizeof(s));
 
 	if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_MQ,
-				  VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET, &sg, 1, 0)){
+				  VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET, &sg, NULL)) {
 		dev_warn(&dev->dev, "Fail to set num of queue pairs to %d\n",
 			 queue_pairs);
 		return -EINVAL;
@@ -955,7 +955,7 @@ static void virtnet_set_rx_mode(struct net_device *dev)
 
 	if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_RX,
 				  VIRTIO_NET_CTRL_RX_PROMISC,
-				  sg, 1, 0))
+				  sg, NULL))
 		dev_warn(&dev->dev, "Failed to %sable promisc mode.\n",
 			 promisc ? "en" : "dis");
 
@@ -963,7 +963,7 @@ static void virtnet_set_rx_mode(struct net_device *dev)
 
 	if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_RX,
 				  VIRTIO_NET_CTRL_RX_ALLMULTI,
-				  sg, 1, 0))
+				  sg, NULL))
 		dev_warn(&dev->dev, "Failed to %sable allmulti mode.\n",
 			 allmulti ? "en" : "dis");
 
@@ -1000,7 +1000,7 @@ static void virtnet_set_rx_mode(struct net_device *dev)
 
 	if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_MAC,
 				  VIRTIO_NET_CTRL_MAC_TABLE_SET,
-				  sg, 2, 0))
+				  sg, NULL))
 		dev_warn(&dev->dev, "Failed to set MAC fitler table.\n");
 
 	kfree(buf);
@@ -1014,7 +1014,7 @@ static int virtnet_vlan_rx_add_vid(struct net_device *dev, u16 vid)
 	sg_init_one(&sg, &vid, sizeof(vid));
 
 	if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_VLAN,
-				  VIRTIO_NET_CTRL_VLAN_ADD, &sg, 1, 0))
+				  VIRTIO_NET_CTRL_VLAN_ADD, &sg, NULL))
 		dev_warn(&dev->dev, "Failed to add VLAN ID %d.\n", vid);
 	return 0;
 }
@@ -1027,7 +1027,7 @@ static int virtnet_vlan_rx_kill_vid(struct net_device *dev, u16 vid)
 	sg_init_one(&sg, &vid, sizeof(vid));
 
 	if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_VLAN,
-				  VIRTIO_NET_CTRL_VLAN_DEL, &sg, 1, 0))
+				  VIRTIO_NET_CTRL_VLAN_DEL, &sg, NULL))
 		dev_warn(&dev->dev, "Failed to kill VLAN ID %d.\n", vid);
 	return 0;
 }
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index 7cee7a3..62a4438 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -33,7 +33,7 @@
 #include <net/arp.h>
 #include <net/ndisc.h>
 #include <net/ip.h>
-#include <net/ipip.h>
+#include <net/ip_tunnels.h>
 #include <net/icmp.h>
 #include <net/udp.h>
 #include <net/rtnetlink.h>
@@ -81,31 +81,30 @@ struct vxlan_net {
 	struct hlist_head vni_list[VNI_HASH_SIZE];
 };
 
+struct vxlan_rdst {
+	struct rcu_head		 rcu;
+	__be32			 remote_ip;
+	__be16			 remote_port;
+	u32			 remote_vni;
+	u32			 remote_ifindex;
+	struct vxlan_rdst	*remote_next;
+};
+
 /* Forwarding table entry */
 struct vxlan_fdb {
 	struct hlist_node hlist;	/* linked list of entries */
 	struct rcu_head	  rcu;
 	unsigned long	  updated;	/* jiffies */
 	unsigned long	  used;
-	__be32		  remote_ip;
+	struct vxlan_rdst remote;
 	u16		  state;	/* see ndm_state */
 	u8		  eth_addr[ETH_ALEN];
 };
 
-/* Per-cpu network traffic stats */
-struct vxlan_stats {
-	u64			rx_packets;
-	u64			rx_bytes;
-	u64			tx_packets;
-	u64			tx_bytes;
-	struct u64_stats_sync	syncp;
-};
-
 /* Pseudo network device */
 struct vxlan_dev {
 	struct hlist_node hlist;
 	struct net_device *dev;
-	struct vxlan_stats __percpu *stats;
 	__u32		  vni;		/* virtual network id */
 	__be32	          gaddr;	/* multicast group */
 	__be32		  saddr;	/* source address */
@@ -157,7 +156,8 @@ static struct vxlan_dev *vxlan_find_vni(struct net *net, u32 id)
 /* Fill in neighbour message in skbuff. */
 static int vxlan_fdb_info(struct sk_buff *skb, struct vxlan_dev *vxlan,
 			   const struct vxlan_fdb *fdb,
-			   u32 portid, u32 seq, int type, unsigned int flags)
+			   u32 portid, u32 seq, int type, unsigned int flags,
+			   const struct vxlan_rdst *rdst)
 {
 	unsigned long now = jiffies;
 	struct nda_cacheinfo ci;
@@ -176,7 +176,7 @@ static int vxlan_fdb_info(struct sk_buff *skb, struct vxlan_dev *vxlan,
 
 	if (type == RTM_GETNEIGH) {
 		ndm->ndm_family	= AF_INET;
-		send_ip = fdb->remote_ip != 0;
+		send_ip = rdst->remote_ip != htonl(INADDR_ANY);
 		send_eth = !is_zero_ether_addr(fdb->eth_addr);
 	} else
 		ndm->ndm_family	= AF_BRIDGE;
@@ -188,7 +188,17 @@ static int vxlan_fdb_info(struct sk_buff *skb, struct vxlan_dev *vxlan,
 	if (send_eth && nla_put(skb, NDA_LLADDR, ETH_ALEN, &fdb->eth_addr))
 		goto nla_put_failure;
 
-	if (send_ip && nla_put_be32(skb, NDA_DST, fdb->remote_ip))
+	if (send_ip && nla_put_be32(skb, NDA_DST, rdst->remote_ip))
+		goto nla_put_failure;
+
+	if (rdst->remote_port && rdst->remote_port != vxlan_port &&
+	    nla_put_be16(skb, NDA_PORT, rdst->remote_port))
+		goto nla_put_failure;
+	if (rdst->remote_vni != vxlan->vni &&
+	    nla_put_be32(skb, NDA_VNI, rdst->remote_vni))
+		goto nla_put_failure;
+	if (rdst->remote_ifindex &&
+	    nla_put_u32(skb, NDA_IFINDEX, rdst->remote_ifindex))
 		goto nla_put_failure;
 
 	ci.ndm_used	 = jiffies_to_clock_t(now - fdb->used);
@@ -211,6 +221,9 @@ static inline size_t vxlan_nlmsg_size(void)
 	return NLMSG_ALIGN(sizeof(struct ndmsg))
 		+ nla_total_size(ETH_ALEN) /* NDA_LLADDR */
 		+ nla_total_size(sizeof(__be32)) /* NDA_DST */
+		+ nla_total_size(sizeof(__be32)) /* NDA_PORT */
+		+ nla_total_size(sizeof(__be32)) /* NDA_VNI */
+		+ nla_total_size(sizeof(__u32)) /* NDA_IFINDEX */
 		+ nla_total_size(sizeof(struct nda_cacheinfo));
 }
 
@@ -225,7 +238,7 @@ static void vxlan_fdb_notify(struct vxlan_dev *vxlan,
 	if (skb == NULL)
 		goto errout;
 
-	err = vxlan_fdb_info(skb, vxlan, fdb, 0, 0, type, 0);
+	err = vxlan_fdb_info(skb, vxlan, fdb, 0, 0, type, 0, &fdb->remote);
 	if (err < 0) {
 		/* -EMSGSIZE implies BUG in vxlan_nlmsg_size() */
 		WARN_ON(err == -EMSGSIZE);
@@ -247,7 +260,8 @@ static void vxlan_ip_miss(struct net_device *dev, __be32 ipa)
 
 	memset(&f, 0, sizeof f);
 	f.state = NUD_STALE;
-	f.remote_ip = ipa; /* goes to NDA_DST */
+	f.remote.remote_ip = ipa; /* goes to NDA_DST */
+	f.remote.remote_vni = VXLAN_N_VID;
 
 	vxlan_fdb_notify(vxlan, &f, RTM_GETNEIGH);
 }
@@ -300,10 +314,38 @@ static struct vxlan_fdb *vxlan_find_mac(struct vxlan_dev *vxlan,
 	return NULL;
 }
 
+/* Add/update destinations for multicast */
+static int vxlan_fdb_append(struct vxlan_fdb *f,
+			    __be32 ip, __u32 port, __u32 vni, __u32 ifindex)
+{
+	struct vxlan_rdst *rd_prev, *rd;
+
+	rd_prev = NULL;
+	for (rd = &f->remote; rd; rd = rd->remote_next) {
+		if (rd->remote_ip == ip &&
+		    rd->remote_port == port &&
+		    rd->remote_vni == vni &&
+		    rd->remote_ifindex == ifindex)
+			return 0;
+		rd_prev = rd;
+	}
+	rd = kmalloc(sizeof(*rd), GFP_ATOMIC);
+	if (rd == NULL)
+		return -ENOBUFS;
+	rd->remote_ip = ip;
+	rd->remote_port = port;
+	rd->remote_vni = vni;
+	rd->remote_ifindex = ifindex;
+	rd->remote_next = NULL;
+	rd_prev->remote_next = rd;
+	return 1;
+}
+
 /* Add new entry to forwarding table -- assumes lock held */
 static int vxlan_fdb_create(struct vxlan_dev *vxlan,
 			    const u8 *mac, __be32 ip,
-			    __u16 state, __u16 flags)
+			    __u16 state, __u16 flags,
+			    __u32 port, __u32 vni, __u32 ifindex)
 {
 	struct vxlan_fdb *f;
 	int notify = 0;
@@ -320,6 +362,14 @@ static int vxlan_fdb_create(struct vxlan_dev *vxlan,
 			f->updated = jiffies;
 			notify = 1;
 		}
+		if ((flags & NLM_F_APPEND) &&
+		    is_multicast_ether_addr(f->eth_addr)) {
+			int rc = vxlan_fdb_append(f, ip, port, vni, ifindex);
+
+			if (rc < 0)
+				return rc;
+			notify |= rc;
+		}
 	} else {
 		if (!(flags & NLM_F_CREATE))
 			return -ENOENT;
@@ -333,7 +383,11 @@ static int vxlan_fdb_create(struct vxlan_dev *vxlan,
 			return -ENOMEM;
 
 		notify = 1;
-		f->remote_ip = ip;
+		f->remote.remote_ip = ip;
+		f->remote.remote_port = port;
+		f->remote.remote_vni = vni;
+		f->remote.remote_ifindex = ifindex;
+		f->remote.remote_next = NULL;
 		f->state = state;
 		f->updated = f->used = jiffies;
 		memcpy(f->eth_addr, mac, ETH_ALEN);
@@ -349,6 +403,19 @@ static int vxlan_fdb_create(struct vxlan_dev *vxlan,
 	return 0;
 }
 
+void vxlan_fdb_free(struct rcu_head *head)
+{
+	struct vxlan_fdb *f = container_of(head, struct vxlan_fdb, rcu);
+
+	while (f->remote.remote_next) {
+		struct vxlan_rdst *rd = f->remote.remote_next;
+
+		f->remote.remote_next = rd->remote_next;
+		kfree(rd);
+	}
+	kfree(f);
+}
+
 static void vxlan_fdb_destroy(struct vxlan_dev *vxlan, struct vxlan_fdb *f)
 {
 	netdev_dbg(vxlan->dev,
@@ -358,7 +425,7 @@ static void vxlan_fdb_destroy(struct vxlan_dev *vxlan, struct vxlan_fdb *f)
 	vxlan_fdb_notify(vxlan, f, RTM_DELNEIGH);
 
 	hlist_del_rcu(&f->hlist);
-	kfree_rcu(f, rcu);
+	call_rcu(&f->rcu, vxlan_fdb_free);
 }
 
 /* Add static entry (via netlink) */
@@ -367,7 +434,9 @@ static int vxlan_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
 			 const unsigned char *addr, u16 flags)
 {
 	struct vxlan_dev *vxlan = netdev_priv(dev);
+	struct net *net = dev_net(vxlan->dev);
 	__be32 ip;
+	u32 port, vni, ifindex;
 	int err;
 
 	if (!(ndm->ndm_state & (NUD_PERMANENT|NUD_REACHABLE))) {
@@ -384,8 +453,36 @@ static int vxlan_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
 
 	ip = nla_get_be32(tb[NDA_DST]);
 
+	if (tb[NDA_PORT]) {
+		if (nla_len(tb[NDA_PORT]) != sizeof(u32))
+			return -EINVAL;
+		port = nla_get_u32(tb[NDA_PORT]);
+	} else
+		port = vxlan_port;
+
+	if (tb[NDA_VNI]) {
+		if (nla_len(tb[NDA_VNI]) != sizeof(u32))
+			return -EINVAL;
+		vni = nla_get_u32(tb[NDA_VNI]);
+	} else
+		vni = vxlan->vni;
+
+	if (tb[NDA_IFINDEX]) {
+		struct net_device *tdev;
+
+		if (nla_len(tb[NDA_IFINDEX]) != sizeof(u32))
+			return -EINVAL;
+		ifindex = nla_get_u32(tb[NDA_IFINDEX]);
+		tdev = dev_get_by_index(net, ifindex);
+		if (!tdev)
+			return -EADDRNOTAVAIL;
+		dev_put(tdev);
+	} else
+		ifindex = 0;
+
 	spin_lock_bh(&vxlan->hash_lock);
-	err = vxlan_fdb_create(vxlan, addr, ip, ndm->ndm_state, flags);
+	err = vxlan_fdb_create(vxlan, addr, ip, ndm->ndm_state, flags, port,
+		vni, ifindex);
 	spin_unlock_bh(&vxlan->hash_lock);
 
 	return err;
@@ -423,18 +520,21 @@ static int vxlan_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb,
 		int err;
 
 		hlist_for_each_entry_rcu(f, &vxlan->fdb_head[h], hlist) {
-			if (idx < cb->args[0])
-				goto skip;
-
-			err = vxlan_fdb_info(skb, vxlan, f,
-					     NETLINK_CB(cb->skb).portid,
-					     cb->nlh->nlmsg_seq,
-					     RTM_NEWNEIGH,
-					     NLM_F_MULTI);
-			if (err < 0)
-				break;
+			struct vxlan_rdst *rd;
+			for (rd = &f->remote; rd; rd = rd->remote_next) {
+				if (idx < cb->args[0])
+					goto skip;
+
+				err = vxlan_fdb_info(skb, vxlan, f,
+						     NETLINK_CB(cb->skb).portid,
+						     cb->nlh->nlmsg_seq,
+						     RTM_NEWNEIGH,
+						     NLM_F_MULTI, rd);
+				if (err < 0)
+					break;
 skip:
-			++idx;
+				++idx;
+			}
 		}
 	}
 
@@ -454,22 +554,23 @@ static void vxlan_snoop(struct net_device *dev,
 	f = vxlan_find_mac(vxlan, src_mac);
 	if (likely(f)) {
 		f->used = jiffies;
-		if (likely(f->remote_ip == src_ip))
+		if (likely(f->remote.remote_ip == src_ip))
 			return;
 
 		if (net_ratelimit())
 			netdev_info(dev,
 				    "%pM migrated from %pI4 to %pI4\n",
-				    src_mac, &f->remote_ip, &src_ip);
+				    src_mac, &f->remote.remote_ip, &src_ip);
 
-		f->remote_ip = src_ip;
+		f->remote.remote_ip = src_ip;
 		f->updated = jiffies;
 	} else {
 		/* learned new entry */
 		spin_lock(&vxlan->hash_lock);
 		err = vxlan_fdb_create(vxlan, src_mac, src_ip,
 				       NUD_REACHABLE,
-				       NLM_F_EXCL|NLM_F_CREATE);
+				       NLM_F_EXCL|NLM_F_CREATE,
+				       vxlan_port, vxlan->vni, 0);
 		spin_unlock(&vxlan->hash_lock);
 	}
 }
@@ -556,7 +657,7 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
 	struct iphdr *oip;
 	struct vxlanhdr *vxh;
 	struct vxlan_dev *vxlan;
-	struct vxlan_stats *stats;
+	struct pcpu_tstats *stats;
 	__u32 vni;
 	int err;
 
@@ -632,7 +733,7 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
 		}
 	}
 
-	stats = this_cpu_ptr(vxlan->stats);
+	stats = this_cpu_ptr(vxlan->dev->tstats);
 	u64_stats_update_begin(&stats->syncp);
 	stats->rx_packets++;
 	stats->rx_bytes += skb->len;
@@ -691,7 +792,6 @@ static int arp_reduce(struct net_device *dev, struct sk_buff *skb)
 	n = neigh_lookup(&arp_tbl, &tip, dev);
 
 	if (n) {
-		struct vxlan_dev *vxlan = netdev_priv(dev);
 		struct vxlan_fdb *f;
 		struct sk_buff	*reply;
 
@@ -701,7 +801,7 @@ static int arp_reduce(struct net_device *dev, struct sk_buff *skb)
 		}
 
 		f = vxlan_find_mac(vxlan, n->ha);
-		if (f && f->remote_ip == 0) {
+		if (f && f->remote.remote_ip == htonl(INADDR_ANY)) {
 			/* bridge-local neighbor */
 			neigh_release(n);
 			goto out;
@@ -763,28 +863,6 @@ static bool route_shortcircuit(struct net_device *dev, struct sk_buff *skb)
 	return false;
 }
 
-/* Extract dsfield from inner protocol */
-static inline u8 vxlan_get_dsfield(const struct iphdr *iph,
-				   const struct sk_buff *skb)
-{
-	if (skb->protocol == htons(ETH_P_IP))
-		return iph->tos;
-	else if (skb->protocol == htons(ETH_P_IPV6))
-		return ipv6_get_dsfield((const struct ipv6hdr *)iph);
-	else
-		return 0;
-}
-
-/* Propogate ECN bits out */
-static inline u8 vxlan_ecn_encap(u8 tos,
-				 const struct iphdr *iph,
-				 const struct sk_buff *skb)
-{
-	u8 inner = vxlan_get_dsfield(iph, skb);
-
-	return INET_ECN_encapsulate(tos, inner);
-}
-
 static void vxlan_sock_free(struct sk_buff *skb)
 {
 	sock_put(skb->sk);
@@ -820,48 +898,40 @@ static u16 vxlan_src_port(const struct vxlan_dev *vxlan, struct sk_buff *skb)
 	return (((u64) hash * range) >> 32) + vxlan->port_min;
 }
 
-/* Transmit local packets over Vxlan
- *
- * Outer IP header inherits ECN and DF from inner header.
- * Outer UDP destination is the VXLAN assigned port.
- *           source port is based on hash of flow
- */
-static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
+static int handle_offloads(struct sk_buff *skb)
+{
+	if (skb_is_gso(skb)) {
+		int err = skb_unclone(skb, GFP_ATOMIC);
+		if (unlikely(err))
+			return err;
+
+		skb_shinfo(skb)->gso_type |= (SKB_GSO_UDP_TUNNEL | SKB_GSO_UDP);
+	} else if (skb->ip_summed != CHECKSUM_PARTIAL)
+		skb->ip_summed = CHECKSUM_NONE;
+
+	return 0;
+}
+
+static netdev_tx_t vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
+				  struct vxlan_rdst *rdst, bool did_rsc)
 {
 	struct vxlan_dev *vxlan = netdev_priv(dev);
 	struct rtable *rt;
 	const struct iphdr *old_iph;
-	struct ethhdr *eth;
 	struct iphdr *iph;
 	struct vxlanhdr *vxh;
 	struct udphdr *uh;
 	struct flowi4 fl4;
 	unsigned int pkt_len = skb->len;
 	__be32 dst;
-	__u16 src_port;
+	__u16 src_port, dst_port;
+        u32 vni;
 	__be16 df = 0;
 	__u8 tos, ttl;
-	int err;
-	bool did_rsc = false;
-	const struct vxlan_fdb *f;
-
-	skb_reset_mac_header(skb);
-	eth = eth_hdr(skb);
 
-	if ((vxlan->flags & VXLAN_F_PROXY) && ntohs(eth->h_proto) == ETH_P_ARP)
-		return arp_reduce(dev, skb);
-	else if ((vxlan->flags&VXLAN_F_RSC) && ntohs(eth->h_proto) == ETH_P_IP)
-		did_rsc = route_shortcircuit(dev, skb);
-
-	f = vxlan_find_mac(vxlan, eth->h_dest);
-	if (f == NULL) {
-		did_rsc = false;
-		dst = vxlan->gaddr;
-		if (!dst && (vxlan->flags & VXLAN_F_L2MISS) &&
-		    !is_multicast_ether_addr(eth->h_dest))
-			vxlan_fdb_miss(vxlan, eth->h_dest);
-	} else
-		dst = f->remote_ip;
+	dst_port = rdst->remote_port ? rdst->remote_port : vxlan_port;
+	vni = rdst->remote_vni;
+	dst = rdst->remote_ip;
 
 	if (!dst) {
 		if (did_rsc) {
@@ -871,8 +941,7 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
 
 			/* short-circuited back to local bridge */
 			if (netif_rx(skb) == NET_RX_SUCCESS) {
-				struct vxlan_stats *stats =
-						this_cpu_ptr(vxlan->stats);
+				struct pcpu_tstats *stats = this_cpu_ptr(dev->tstats);
 
 				u64_stats_update_begin(&stats->syncp);
 				stats->tx_packets++;
@@ -904,12 +973,12 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
 
 	tos = vxlan->tos;
 	if (tos == 1)
-		tos = vxlan_get_dsfield(old_iph, skb);
+		tos = ip_tunnel_get_dsfield(old_iph, skb);
 
 	src_port = vxlan_src_port(vxlan, skb);
 
 	memset(&fl4, 0, sizeof(fl4));
-	fl4.flowi4_oif = vxlan->link;
+	fl4.flowi4_oif = rdst->remote_ifindex;
 	fl4.flowi4_tos = RT_TOS(tos);
 	fl4.daddr = dst;
 	fl4.saddr = vxlan->saddr;
@@ -936,13 +1005,13 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
 
 	vxh = (struct vxlanhdr *) __skb_push(skb, sizeof(*vxh));
 	vxh->vx_flags = htonl(VXLAN_FLAGS);
-	vxh->vx_vni = htonl(vxlan->vni << 8);
+	vxh->vx_vni = htonl(vni << 8);
 
 	__skb_push(skb, sizeof(*uh));
 	skb_reset_transport_header(skb);
 	uh = udp_hdr(skb);
 
-	uh->dest = htons(vxlan_port);
+	uh->dest = htons(dst_port);
 	uh->source = htons(src_port);
 
 	uh->len = htons(skb->len);
@@ -955,7 +1024,7 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
 	iph->ihl	= sizeof(struct iphdr) >> 2;
 	iph->frag_off	= df;
 	iph->protocol	= IPPROTO_UDP;
-	iph->tos	= vxlan_ecn_encap(tos, old_iph, skb);
+	iph->tos	= ip_tunnel_ecn_encap(tos, old_iph, skb);
 	iph->daddr	= dst;
 	iph->saddr	= fl4.saddr;
 	iph->ttl	= ttl ? : ip4_dst_hoplimit(&rt->dst);
@@ -965,22 +1034,10 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
 
 	vxlan_set_owner(dev, skb);
 
-	/* See iptunnel_xmit() */
-	if (skb->ip_summed != CHECKSUM_PARTIAL)
-		skb->ip_summed = CHECKSUM_NONE;
-
-	err = ip_local_out(skb);
-	if (likely(net_xmit_eval(err) == 0)) {
-		struct vxlan_stats *stats = this_cpu_ptr(vxlan->stats);
+	if (handle_offloads(skb))
+		goto drop;
 
-		u64_stats_update_begin(&stats->syncp);
-		stats->tx_packets++;
-		stats->tx_bytes += pkt_len;
-		u64_stats_update_end(&stats->syncp);
-	} else {
-		dev->stats.tx_errors++;
-		dev->stats.tx_aborted_errors++;
-	}
+	iptunnel_xmit(skb, dev);
 	return NETDEV_TX_OK;
 
 drop:
@@ -994,6 +1051,64 @@ tx_free:
 	return NETDEV_TX_OK;
 }
 
+/* Transmit local packets over Vxlan
+ *
+ * Outer IP header inherits ECN and DF from inner header.
+ * Outer UDP destination is the VXLAN assigned port.
+ *           source port is based on hash of flow
+ */
+static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct vxlan_dev *vxlan = netdev_priv(dev);
+	struct ethhdr *eth;
+	bool did_rsc = false;
+	struct vxlan_rdst group, *rdst0, *rdst;
+	struct vxlan_fdb *f;
+	int rc1, rc;
+
+	skb_reset_mac_header(skb);
+	eth = eth_hdr(skb);
+
+	if ((vxlan->flags & VXLAN_F_PROXY) && ntohs(eth->h_proto) == ETH_P_ARP)
+		return arp_reduce(dev, skb);
+	else if ((vxlan->flags&VXLAN_F_RSC) && ntohs(eth->h_proto) == ETH_P_IP)
+		did_rsc = route_shortcircuit(dev, skb);
+
+	f = vxlan_find_mac(vxlan, eth->h_dest);
+	if (f == NULL) {
+		did_rsc = false;
+		group.remote_port = vxlan_port;
+		group.remote_vni = vxlan->vni;
+		group.remote_ip = vxlan->gaddr;
+		group.remote_ifindex = vxlan->link;
+		group.remote_next = 0;
+		rdst0 = &group;
+
+		if (group.remote_ip == htonl(INADDR_ANY) &&
+		    (vxlan->flags & VXLAN_F_L2MISS) &&
+		    !is_multicast_ether_addr(eth->h_dest))
+			vxlan_fdb_miss(vxlan, eth->h_dest);
+	} else
+		rdst0 = &f->remote;
+
+	rc = NETDEV_TX_OK;
+
+	/* if there are multiple destinations, send copies */
+	for (rdst = rdst0->remote_next; rdst; rdst = rdst->remote_next) {
+		struct sk_buff *skb1;
+
+		skb1 = skb_clone(skb, GFP_ATOMIC);
+		rc1 = vxlan_xmit_one(skb1, dev, rdst, did_rsc);
+		if (rc == NETDEV_TX_OK)
+			rc = rc1;
+	}
+
+	rc1 = vxlan_xmit_one(skb, dev, rdst0, did_rsc);
+	if (rc == NETDEV_TX_OK)
+		rc = rc1;
+	return rc;
+}
+
 /* Walk the forwarding table and purge stale entries */
 static void vxlan_cleanup(unsigned long arg)
 {
@@ -1034,10 +1149,8 @@ static void vxlan_cleanup(unsigned long arg)
 /* Setup stats when device is created */
 static int vxlan_init(struct net_device *dev)
 {
-	struct vxlan_dev *vxlan = netdev_priv(dev);
-
-	vxlan->stats = alloc_percpu(struct vxlan_stats);
-	if (!vxlan->stats)
+	dev->tstats = alloc_percpu(struct pcpu_tstats);
+	if (!dev->tstats)
 		return -ENOMEM;
 
 	return 0;
@@ -1093,49 +1206,6 @@ static int vxlan_stop(struct net_device *dev)
 	return 0;
 }
 
-/* Merge per-cpu statistics */
-static struct rtnl_link_stats64 *vxlan_stats64(struct net_device *dev,
-					       struct rtnl_link_stats64 *stats)
-{
-	struct vxlan_dev *vxlan = netdev_priv(dev);
-	struct vxlan_stats tmp, sum = { 0 };
-	unsigned int cpu;
-
-	for_each_possible_cpu(cpu) {
-		unsigned int start;
-		const struct vxlan_stats *stats
-			= per_cpu_ptr(vxlan->stats, cpu);
-
-		do {
-			start = u64_stats_fetch_begin_bh(&stats->syncp);
-			memcpy(&tmp, stats, sizeof(tmp));
-		} while (u64_stats_fetch_retry_bh(&stats->syncp, start));
-
-		sum.tx_bytes   += tmp.tx_bytes;
-		sum.tx_packets += tmp.tx_packets;
-		sum.rx_bytes   += tmp.rx_bytes;
-		sum.rx_packets += tmp.rx_packets;
-	}
-
-	stats->tx_bytes   = sum.tx_bytes;
-	stats->tx_packets = sum.tx_packets;
-	stats->rx_bytes   = sum.rx_bytes;
-	stats->rx_packets = sum.rx_packets;
-
-	stats->multicast = dev->stats.multicast;
-	stats->rx_length_errors = dev->stats.rx_length_errors;
-	stats->rx_frame_errors = dev->stats.rx_frame_errors;
-	stats->rx_errors = dev->stats.rx_errors;
-
-	stats->tx_dropped = dev->stats.tx_dropped;
-	stats->tx_carrier_errors  = dev->stats.tx_carrier_errors;
-	stats->tx_aborted_errors  = dev->stats.tx_aborted_errors;
-	stats->collisions  = dev->stats.collisions;
-	stats->tx_errors = dev->stats.tx_errors;
-
-	return stats;
-}
-
 /* Stub, nothing needs to be done. */
 static void vxlan_set_multicast_list(struct net_device *dev)
 {
@@ -1146,7 +1216,7 @@ static const struct net_device_ops vxlan_netdev_ops = {
 	.ndo_open		= vxlan_open,
 	.ndo_stop		= vxlan_stop,
 	.ndo_start_xmit		= vxlan_xmit,
-	.ndo_get_stats64	= vxlan_stats64,
+	.ndo_get_stats64	= ip_tunnel_get_stats64,
 	.ndo_set_rx_mode	= vxlan_set_multicast_list,
 	.ndo_change_mtu		= eth_change_mtu,
 	.ndo_validate_addr	= eth_validate_addr,
@@ -1163,9 +1233,7 @@ static struct device_type vxlan_type = {
 
 static void vxlan_free(struct net_device *dev)
 {
-	struct vxlan_dev *vxlan = netdev_priv(dev);
-
-	free_percpu(vxlan->stats);
+	free_percpu(dev->tstats);
 	free_netdev(dev);
 }
 
@@ -1189,8 +1257,10 @@ static void vxlan_setup(struct net_device *dev)
 	dev->features	|= NETIF_F_NETNS_LOCAL;
 	dev->features	|= NETIF_F_SG | NETIF_F_HW_CSUM;
 	dev->features   |= NETIF_F_RXCSUM;
+	dev->features   |= NETIF_F_GSO_SOFTWARE;
 
 	dev->hw_features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_RXCSUM;
+	dev->hw_features |= NETIF_F_GSO_SOFTWARE;
 	dev->priv_flags	&= ~IFF_XMIT_DST_RELEASE;
 	dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
 
@@ -1555,6 +1625,7 @@ static void __exit vxlan_cleanup_module(void)
 {
 	rtnl_link_unregister(&vxlan_link_ops);
 	unregister_pernet_device(&vxlan_net_ops);
+	rcu_barrier();
 }
 module_exit(vxlan_cleanup_module);
 
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index 5329541..66e398d 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -4663,8 +4663,7 @@ static ssize_t proc_write( struct file *file,
 static int proc_status_open(struct inode *inode, struct file *file)
 {
 	struct proc_data *data;
-	struct proc_dir_entry *dp = PDE(inode);
-	struct net_device *dev = dp->data;
+	struct net_device *dev = PDE_DATA(inode);
 	struct airo_info *apriv = dev->ml_priv;
 	CapabilityRid cap_rid;
 	StatusRid status_rid;
@@ -4746,8 +4745,7 @@ static int proc_stats_rid_open( struct inode *inode,
 				u16 rid )
 {
 	struct proc_data *data;
-	struct proc_dir_entry *dp = PDE(inode);
-	struct net_device *dev = dp->data;
+	struct net_device *dev = PDE_DATA(inode);
 	struct airo_info *apriv = dev->ml_priv;
 	StatsRid stats;
 	int i, j;
@@ -4809,8 +4807,7 @@ static inline int sniffing_mode(struct airo_info *ai)
 static void proc_config_on_close(struct inode *inode, struct file *file)
 {
 	struct proc_data *data = file->private_data;
-	struct proc_dir_entry *dp = PDE(inode);
-	struct net_device *dev = dp->data;
+	struct net_device *dev = PDE_DATA(inode);
 	struct airo_info *ai = dev->ml_priv;
 	char *line;
 
@@ -5021,8 +5018,7 @@ static const char *get_rmode(__le16 mode)
 static int proc_config_open(struct inode *inode, struct file *file)
 {
 	struct proc_data *data;
-	struct proc_dir_entry *dp = PDE(inode);
-	struct net_device *dev = dp->data;
+	struct net_device *dev = PDE_DATA(inode);
 	struct airo_info *ai = dev->ml_priv;
 	int i;
 	__le16 mode;
@@ -5112,8 +5108,7 @@ static int proc_config_open(struct inode *inode, struct file *file)
 static void proc_SSID_on_close(struct inode *inode, struct file *file)
 {
 	struct proc_data *data = file->private_data;
-	struct proc_dir_entry *dp = PDE(inode);
-	struct net_device *dev = dp->data;
+	struct net_device *dev = PDE_DATA(inode);
 	struct airo_info *ai = dev->ml_priv;
 	SsidRid SSID_rid;
 	int i;
@@ -5148,8 +5143,7 @@ static void proc_SSID_on_close(struct inode *inode, struct file *file)
 
 static void proc_APList_on_close( struct inode *inode, struct file *file ) {
 	struct proc_data *data = file->private_data;
-	struct proc_dir_entry *dp = PDE(inode);
-	struct net_device *dev = dp->data;
+	struct net_device *dev = PDE_DATA(inode);
 	struct airo_info *ai = dev->ml_priv;
 	APListRid APList_rid;
 	int i;
@@ -5283,8 +5277,7 @@ static int set_wep_tx_idx(struct airo_info *ai, u16 index, int perm, int lock)
 
 static void proc_wepkey_on_close( struct inode *inode, struct file *file ) {
 	struct proc_data *data;
-	struct proc_dir_entry *dp = PDE(inode);
-	struct net_device *dev = dp->data;
+	struct net_device *dev = PDE_DATA(inode);
 	struct airo_info *ai = dev->ml_priv;
 	int i, rc;
 	char key[16];
@@ -5335,8 +5328,7 @@ static void proc_wepkey_on_close( struct inode *inode, struct file *file ) {
 static int proc_wepkey_open( struct inode *inode, struct file *file )
 {
 	struct proc_data *data;
-	struct proc_dir_entry *dp = PDE(inode);
-	struct net_device *dev = dp->data;
+	struct net_device *dev = PDE_DATA(inode);
 	struct airo_info *ai = dev->ml_priv;
 	char *ptr;
 	WepKeyRid wkr;
@@ -5384,8 +5376,7 @@ static int proc_wepkey_open( struct inode *inode, struct file *file )
 static int proc_SSID_open(struct inode *inode, struct file *file)
 {
 	struct proc_data *data;
-	struct proc_dir_entry *dp = PDE(inode);
-	struct net_device *dev = dp->data;
+	struct net_device *dev = PDE_DATA(inode);
 	struct airo_info *ai = dev->ml_priv;
 	int i;
 	char *ptr;
@@ -5428,8 +5419,7 @@ static int proc_SSID_open(struct inode *inode, struct file *file)
 
 static int proc_APList_open( struct inode *inode, struct file *file ) {
 	struct proc_data *data;
-	struct proc_dir_entry *dp = PDE(inode);
-	struct net_device *dev = dp->data;
+	struct net_device *dev = PDE_DATA(inode);
 	struct airo_info *ai = dev->ml_priv;
 	int i;
 	char *ptr;
@@ -5468,8 +5458,7 @@ static int proc_APList_open( struct inode *inode, struct file *file ) {
 
 static int proc_BSSList_open( struct inode *inode, struct file *file ) {
 	struct proc_data *data;
-	struct proc_dir_entry *dp = PDE(inode);
-	struct net_device *dev = dp->data;
+	struct net_device *dev = PDE_DATA(inode);
 	struct airo_info *ai = dev->ml_priv;
 	char *ptr;
 	BSSListRid BSSList_rid;
diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c
index 956024a..14128fd 100644
--- a/drivers/net/wireless/airo_cs.c
+++ b/drivers/net/wireless/airo_cs.c
@@ -180,16 +180,7 @@ static struct pcmcia_driver airo_driver = {
 	.suspend	= airo_suspend,
 	.resume		= airo_resume,
 };
-
-static int __init airo_cs_init(void)
-{
-	return pcmcia_register_driver(&airo_driver);
-}
-
-static void __exit airo_cs_cleanup(void)
-{
-	pcmcia_unregister_driver(&airo_driver);
-}
+module_pcmcia_driver(airo_driver);
 
 /*
     This program is free software; you can redistribute it and/or
@@ -229,6 +220,3 @@ static void __exit airo_cs_cleanup(void)
     IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     POSSIBILITY OF SUCH DAMAGE.
 */
-
-module_init(airo_cs_init);
-module_exit(airo_cs_cleanup);
diff --git a/drivers/net/wireless/ath/ar5523/ar5523.c b/drivers/net/wireless/ath/ar5523/ar5523.c
index 7157f7d..afd1e36 100644
--- a/drivers/net/wireless/ath/ar5523/ar5523.c
+++ b/drivers/net/wireless/ath/ar5523/ar5523.c
@@ -1091,7 +1091,7 @@ static int ar5523_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
 	return ret;
 }
 
-static void ar5523_flush(struct ieee80211_hw *hw, bool drop)
+static void ar5523_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
 {
 	struct ar5523 *ar = hw->priv;
 
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h
index 3150def..2d691b8 100644
--- a/drivers/net/wireless/ath/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath/ath5k/ath5k.h
@@ -1523,7 +1523,8 @@ int ath5k_hw_dma_stop(struct ath5k_hw *ah);
 /* EEPROM access functions */
 int ath5k_eeprom_init(struct ath5k_hw *ah);
 void ath5k_eeprom_detach(struct ath5k_hw *ah);
-
+int ath5k_eeprom_mode_from_channel(struct ath5k_hw *ah,
+		struct ieee80211_channel *channel);
 
 /* Protocol Control Unit Functions */
 /* Helpers */
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c
index b7e0258..94d34ee 100644
--- a/drivers/net/wireless/ath/ath5k/eeprom.c
+++ b/drivers/net/wireless/ath/ath5k/eeprom.c
@@ -1779,7 +1779,8 @@ ath5k_eeprom_detach(struct ath5k_hw *ah)
 }
 
 int
-ath5k_eeprom_mode_from_channel(struct ieee80211_channel *channel)
+ath5k_eeprom_mode_from_channel(struct ath5k_hw *ah,
+		struct ieee80211_channel *channel)
 {
 	switch (channel->hw_value) {
 	case AR5K_MODE_11A:
@@ -1789,6 +1790,7 @@ ath5k_eeprom_mode_from_channel(struct ieee80211_channel *channel)
 	case AR5K_MODE_11B:
 		return AR5K_EEPROM_MODE_11B;
 	default:
-		return -1;
+		ATH5K_WARN(ah, "channel is not A/B/G!");
+		return AR5K_EEPROM_MODE_11A;
 	}
 }
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.h b/drivers/net/wireless/ath/ath5k/eeprom.h
index 94a9bbe..693296e 100644
--- a/drivers/net/wireless/ath/ath5k/eeprom.h
+++ b/drivers/net/wireless/ath/ath5k/eeprom.h
@@ -493,6 +493,3 @@ struct ath5k_eeprom_info {
 	/* Antenna raw switch tables */
 	u32	ee_antenna[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX];
 };
-
-int
-ath5k_eeprom_mode_from_channel(struct ieee80211_channel *channel);
diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c
index a78afa9..d6bc7cb 100644
--- a/drivers/net/wireless/ath/ath5k/phy.c
+++ b/drivers/net/wireless/ath/ath5k/phy.c
@@ -1612,11 +1612,7 @@ ath5k_hw_update_noise_floor(struct ath5k_hw *ah)
 
 	ah->ah_cal_mask |= AR5K_CALIBRATION_NF;
 
-	ee_mode = ath5k_eeprom_mode_from_channel(ah->ah_current_channel);
-	if (WARN_ON(ee_mode < 0)) {
-		ah->ah_cal_mask &= ~AR5K_CALIBRATION_NF;
-		return;
-	}
+	ee_mode = ath5k_eeprom_mode_from_channel(ah, ah->ah_current_channel);
 
 	/* completed NF calibration, test threshold */
 	nf = ath5k_hw_read_measured_noise_floor(ah);
@@ -2317,12 +2313,7 @@ ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode)
 
 	def_ant = ah->ah_def_ant;
 
-	ee_mode = ath5k_eeprom_mode_from_channel(channel);
-	if (ee_mode < 0) {
-		ATH5K_ERR(ah,
-			"invalid channel: %d\n", channel->center_freq);
-		return;
-	}
+	ee_mode = ath5k_eeprom_mode_from_channel(ah, channel);
 
 	switch (ant_mode) {
 	case AR5K_ANTMODE_DEFAULT:
@@ -3622,12 +3613,7 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel,
 		return -EINVAL;
 	}
 
-	ee_mode = ath5k_eeprom_mode_from_channel(channel);
-	if (ee_mode < 0) {
-		ATH5K_ERR(ah,
-			"invalid channel: %d\n", channel->center_freq);
-		return -EINVAL;
-	}
+	ee_mode = ath5k_eeprom_mode_from_channel(ah, channel);
 
 	/* Initialize TX power table */
 	switch (ah->ah_radio) {
diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c
index e2d8b2c..a3399c4 100644
--- a/drivers/net/wireless/ath/ath5k/reset.c
+++ b/drivers/net/wireless/ath/ath5k/reset.c
@@ -984,9 +984,7 @@ ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah,
 	if (ah->ah_version == AR5K_AR5210)
 		return;
 
-	ee_mode = ath5k_eeprom_mode_from_channel(channel);
-	if (WARN_ON(ee_mode < 0))
-		return;
+	ee_mode = ath5k_eeprom_mode_from_channel(ah, channel);
 
 	/* Adjust power delta for channel 14 */
 	if (channel->center_freq == 2484)
diff --git a/drivers/net/wireless/ath/ath6kl/Kconfig b/drivers/net/wireless/ath/ath6kl/Kconfig
index 630c83d..e39e586 100644
--- a/drivers/net/wireless/ath/ath6kl/Kconfig
+++ b/drivers/net/wireless/ath/ath6kl/Kconfig
@@ -30,6 +30,15 @@ config ATH6KL_DEBUG
 	---help---
 	  Enables debug support
 
+config ATH6KL_TRACING
+	bool "Atheros ath6kl tracing support"
+	depends on ATH6KL
+	depends on EVENT_TRACING
+	---help---
+	  Select this to ath6kl use tracing infrastructure.
+
+	  If unsure, say Y to make it easier to debug problems.
+
 config ATH6KL_REGDOMAIN
 	bool "Atheros ath6kl regdomain support"
 	depends on ATH6KL
diff --git a/drivers/net/wireless/ath/ath6kl/Makefile b/drivers/net/wireless/ath/ath6kl/Makefile
index cab0ec0..dc2b3b4 100644
--- a/drivers/net/wireless/ath/ath6kl/Makefile
+++ b/drivers/net/wireless/ath/ath6kl/Makefile
@@ -35,10 +35,15 @@ ath6kl_core-y += txrx.o
 ath6kl_core-y += wmi.o
 ath6kl_core-y += core.o
 ath6kl_core-y += recovery.o
+
 ath6kl_core-$(CONFIG_NL80211_TESTMODE) += testmode.o
+ath6kl_core-$(CONFIG_ATH6KL_TRACING) += trace.o
 
 obj-$(CONFIG_ATH6KL_SDIO) += ath6kl_sdio.o
 ath6kl_sdio-y += sdio.o
 
 obj-$(CONFIG_ATH6KL_USB) += ath6kl_usb.o
 ath6kl_usb-y += usb.o
+
+# for tracing framework to find trace.h
+CFLAGS_trace.o := -I$(src)
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c
index 752ffc4..5c9736a 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
@@ -402,7 +402,7 @@ static bool ath6kl_is_valid_iftype(struct ath6kl *ar, enum nl80211_iftype type,
 	if (type == NL80211_IFTYPE_STATION ||
 	    type == NL80211_IFTYPE_AP || type == NL80211_IFTYPE_ADHOC) {
 		for (i = 0; i < ar->vif_max; i++) {
-			if ((ar->avail_idx_map >> i) & BIT(0)) {
+			if ((ar->avail_idx_map) & BIT(i)) {
 				*if_idx = i;
 				return true;
 			}
@@ -412,7 +412,7 @@ static bool ath6kl_is_valid_iftype(struct ath6kl *ar, enum nl80211_iftype type,
 	if (type == NL80211_IFTYPE_P2P_CLIENT ||
 	    type == NL80211_IFTYPE_P2P_GO) {
 		for (i = ar->max_norm_iface; i < ar->vif_max; i++) {
-			if ((ar->avail_idx_map >> i) & BIT(0)) {
+			if ((ar->avail_idx_map) & BIT(i)) {
 				*if_idx = i;
 				return true;
 			}
@@ -1535,7 +1535,9 @@ static int ath6kl_cfg80211_del_iface(struct wiphy *wiphy,
 
 	ath6kl_cfg80211_vif_stop(vif, test_bit(WMI_READY, &ar->flag));
 
+	rtnl_lock();
 	ath6kl_cfg80211_vif_cleanup(vif);
+	rtnl_unlock();
 
 	return 0;
 }
@@ -2990,13 +2992,15 @@ static int ath6kl_change_station(struct wiphy *wiphy, struct net_device *dev,
 {
 	struct ath6kl *ar = ath6kl_priv(dev);
 	struct ath6kl_vif *vif = netdev_priv(dev);
+	int err;
 
 	if (vif->nw_type != AP_NETWORK)
 		return -EOPNOTSUPP;
 
-	/* Use this only for authorizing/unauthorizing a station */
-	if (!(params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED)))
-		return -EOPNOTSUPP;
+	err = cfg80211_check_station_change(wiphy, params,
+					    CFG80211_STA_AP_MLME_CLIENT);
+	if (err)
+		return err;
 
 	if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED))
 		return ath6kl_wmi_ap_set_mlme(ar->wmi, vif->fw_vif_idx,
@@ -3659,7 +3663,6 @@ struct wireless_dev *ath6kl_interface_add(struct ath6kl *ar, const char *name,
 	vif->sme_state = SME_DISCONNECTED;
 	set_bit(WLAN_ENABLED, &vif->flags);
 	ar->wlan_pwr_state = WLAN_POWER_STATE_ON;
-	set_bit(NETDEV_REGISTERED, &vif->flags);
 
 	if (type == NL80211_IFTYPE_ADHOC)
 		ar->ibss_if_active = true;
diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h
index 61b2f98..26b0f92 100644
--- a/drivers/net/wireless/ath/ath6kl/core.h
+++ b/drivers/net/wireless/ath/ath6kl/core.h
@@ -560,7 +560,6 @@ enum ath6kl_vif_state {
 	WMM_ENABLED,
 	NETQ_STOPPED,
 	DTIM_EXPIRED,
-	NETDEV_REGISTERED,
 	CLEAR_BSSFILTER_ON_BEACON,
 	DTIM_PERIOD_AVAIL,
 	WLAN_ENABLED,
@@ -936,8 +935,6 @@ void aggr_recv_addba_req_evt(struct ath6kl_vif *vif, u8 tid, u16 seq_no,
 			     u8 win_sz);
 void ath6kl_wakeup_event(void *dev);
 
-void ath6kl_reset_device(struct ath6kl *ar, u32 target_type,
-			 bool wait_fot_compltn, bool cold_reset);
 void ath6kl_init_control_info(struct ath6kl_vif *vif);
 struct ath6kl_vif *ath6kl_vif_first(struct ath6kl *ar);
 void ath6kl_cfg80211_vif_stop(struct ath6kl_vif *vif, bool wmi_ready);
diff --git a/drivers/net/wireless/ath/ath6kl/debug.c b/drivers/net/wireless/ath/ath6kl/debug.c
index 15cfe30..fe38b83 100644
--- a/drivers/net/wireless/ath/ath6kl/debug.c
+++ b/drivers/net/wireless/ath/ath6kl/debug.c
@@ -56,6 +56,60 @@ int ath6kl_printk(const char *level, const char *fmt, ...)
 }
 EXPORT_SYMBOL(ath6kl_printk);
 
+int ath6kl_info(const char *fmt, ...)
+{
+	struct va_format vaf = {
+		.fmt = fmt,
+	};
+	va_list args;
+	int ret;
+
+	va_start(args, fmt);
+	vaf.va = &args;
+	ret = ath6kl_printk(KERN_INFO, "%pV", &vaf);
+	trace_ath6kl_log_info(&vaf);
+	va_end(args);
+
+	return ret;
+}
+EXPORT_SYMBOL(ath6kl_info);
+
+int ath6kl_err(const char *fmt, ...)
+{
+	struct va_format vaf = {
+		.fmt = fmt,
+	};
+	va_list args;
+	int ret;
+
+	va_start(args, fmt);
+	vaf.va = &args;
+	ret = ath6kl_printk(KERN_ERR, "%pV", &vaf);
+	trace_ath6kl_log_err(&vaf);
+	va_end(args);
+
+	return ret;
+}
+EXPORT_SYMBOL(ath6kl_err);
+
+int ath6kl_warn(const char *fmt, ...)
+{
+	struct va_format vaf = {
+		.fmt = fmt,
+	};
+	va_list args;
+	int ret;
+
+	va_start(args, fmt);
+	vaf.va = &args;
+	ret = ath6kl_printk(KERN_WARNING, "%pV", &vaf);
+	trace_ath6kl_log_warn(&vaf);
+	va_end(args);
+
+	return ret;
+}
+EXPORT_SYMBOL(ath6kl_warn);
+
 #ifdef CONFIG_ATH6KL_DEBUG
 
 void ath6kl_dbg(enum ATH6K_DEBUG_MASK mask, const char *fmt, ...)
@@ -63,15 +117,15 @@ void ath6kl_dbg(enum ATH6K_DEBUG_MASK mask, const char *fmt, ...)
 	struct va_format vaf;
 	va_list args;
 
-	if (!(debug_mask & mask))
-		return;
-
 	va_start(args, fmt);
 
 	vaf.fmt = fmt;
 	vaf.va = &args;
 
-	ath6kl_printk(KERN_DEBUG, "%pV", &vaf);
+	if (debug_mask & mask)
+		ath6kl_printk(KERN_DEBUG, "%pV", &vaf);
+
+	trace_ath6kl_log_dbg(mask, &vaf);
 
 	va_end(args);
 }
@@ -87,6 +141,10 @@ void ath6kl_dbg_dump(enum ATH6K_DEBUG_MASK mask,
 
 		print_hex_dump_bytes(prefix, DUMP_PREFIX_OFFSET, buf, len);
 	}
+
+	/* tracing code doesn't like null strings :/ */
+	trace_ath6kl_log_dbg_dump(msg ? msg : "", prefix ? prefix : "",
+				  buf, len);
 }
 EXPORT_SYMBOL(ath6kl_dbg_dump);
 
@@ -1752,8 +1810,10 @@ int ath6kl_debug_init_fs(struct ath6kl *ar)
 	debugfs_create_file("tgt_stats", S_IRUSR, ar->debugfs_phy, ar,
 			    &fops_tgt_stats);
 
-	debugfs_create_file("credit_dist_stats", S_IRUSR, ar->debugfs_phy, ar,
-			    &fops_credit_dist_stats);
+	if (ar->hif_type == ATH6KL_HIF_TYPE_SDIO)
+		debugfs_create_file("credit_dist_stats", S_IRUSR,
+				    ar->debugfs_phy, ar,
+				    &fops_credit_dist_stats);
 
 	debugfs_create_file("endpoint_stats", S_IRUSR | S_IWUSR,
 			    ar->debugfs_phy, ar, &fops_endpoint_stats);
diff --git a/drivers/net/wireless/ath/ath6kl/debug.h b/drivers/net/wireless/ath/ath6kl/debug.h
index f97cd4e..74369de 100644
--- a/drivers/net/wireless/ath/ath6kl/debug.h
+++ b/drivers/net/wireless/ath/ath6kl/debug.h
@@ -19,6 +19,7 @@
 #define DEBUG_H
 
 #include "hif.h"
+#include "trace.h"
 
 enum ATH6K_DEBUG_MASK {
 	ATH6KL_DBG_CREDIT	= BIT(0),
@@ -51,13 +52,9 @@ enum ATH6K_DEBUG_MASK {
 extern unsigned int debug_mask;
 extern __printf(2, 3)
 int ath6kl_printk(const char *level, const char *fmt, ...);
-
-#define ath6kl_info(fmt, ...)				\
-	ath6kl_printk(KERN_INFO, fmt, ##__VA_ARGS__)
-#define ath6kl_err(fmt, ...)					\
-	ath6kl_printk(KERN_ERR, fmt, ##__VA_ARGS__)
-#define ath6kl_warn(fmt, ...)					\
-	ath6kl_printk(KERN_WARNING, fmt, ##__VA_ARGS__)
+extern __printf(1, 2) int ath6kl_info(const char *fmt, ...);
+extern __printf(1, 2) int ath6kl_err(const char *fmt, ...);
+extern __printf(1, 2) int ath6kl_warn(const char *fmt, ...);
 
 enum ath6kl_war {
 	ATH6KL_WAR_INVALID_RATE,
diff --git a/drivers/net/wireless/ath/ath6kl/hif.c b/drivers/net/wireless/ath/ath6kl/hif.c
index a6b6144..fea7709 100644
--- a/drivers/net/wireless/ath/ath6kl/hif.c
+++ b/drivers/net/wireless/ath/ath6kl/hif.c
@@ -22,6 +22,7 @@
 #include "target.h"
 #include "hif-ops.h"
 #include "debug.h"
+#include "trace.h"
 
 #define MAILBOX_FOR_BLOCK_SIZE          1
 
@@ -436,6 +437,8 @@ static int proc_pending_irqs(struct ath6kl_device *dev, bool *done)
 
 		ath6kl_dump_registers(dev, &dev->irq_proc_reg,
 				      &dev->irq_en_reg);
+		trace_ath6kl_sdio_irq(&dev->irq_en_reg,
+				      sizeof(dev->irq_en_reg));
 
 		/* Update only those registers that are enabled */
 		host_int_status = dev->irq_proc_reg.host_int_status &
diff --git a/drivers/net/wireless/ath/ath6kl/htc_mbox.c b/drivers/net/wireless/ath/ath6kl/htc_mbox.c
index fbb78df..65e5b71 100644
--- a/drivers/net/wireless/ath/ath6kl/htc_mbox.c
+++ b/drivers/net/wireless/ath/ath6kl/htc_mbox.c
@@ -19,6 +19,8 @@
 #include "hif.h"
 #include "debug.h"
 #include "hif-ops.h"
+#include "trace.h"
+
 #include <asm/unaligned.h>
 
 #define CALC_TXRX_PADDED_LEN(dev, len)  (__ALIGN_MASK((len), (dev)->block_mask))
@@ -537,6 +539,8 @@ static int ath6kl_htc_tx_issue(struct htc_target *target,
 				packet->buf, padded_len,
 				HIF_WR_ASYNC_BLOCK_INC, packet);
 
+	trace_ath6kl_htc_tx(status, packet->endpoint, packet->buf, send_len);
+
 	return status;
 }
 
@@ -757,7 +761,8 @@ static void ath6kl_htc_tx_bundle(struct htc_endpoint *endpoint,
 {
 	struct htc_target *target = endpoint->target;
 	struct hif_scatter_req *scat_req = NULL;
-	int n_scat, n_sent_bundle = 0, tot_pkts_bundle = 0;
+	int n_scat, n_sent_bundle = 0, tot_pkts_bundle = 0, i;
+	struct htc_packet *packet;
 	int status;
 	u32 txb_mask;
 	u8 ac = WMM_NUM_AC;
@@ -832,6 +837,13 @@ static void ath6kl_htc_tx_bundle(struct htc_endpoint *endpoint,
 		ath6kl_dbg(ATH6KL_DBG_HTC,
 			   "htc tx scatter bytes %d entries %d\n",
 			   scat_req->len, scat_req->scat_entries);
+
+		for (i = 0; i < scat_req->scat_entries; i++) {
+			packet = scat_req->scat_list[i].packet;
+			trace_ath6kl_htc_tx(packet->status, packet->endpoint,
+					    packet->buf, packet->act_len);
+		}
+
 		ath6kl_hif_submit_scat_req(target->dev, scat_req, false);
 
 		if (status)
@@ -1903,6 +1915,7 @@ static void ath6kl_htc_rx_complete(struct htc_endpoint *endpoint,
 		ath6kl_dbg(ATH6KL_DBG_HTC,
 			   "htc rx complete ep %d packet 0x%p\n",
 			   endpoint->eid, packet);
+
 		endpoint->ep_cb.rx(endpoint->target, packet);
 }
 
@@ -2011,6 +2024,9 @@ static int ath6kl_htc_rx_process_packets(struct htc_target *target,
 	list_for_each_entry_safe(packet, tmp_pkt, comp_pktq, list) {
 		ep = &target->endpoint[packet->endpoint];
 
+		trace_ath6kl_htc_rx(packet->status, packet->endpoint,
+				    packet->buf, packet->act_len);
+
 		/* process header for each of the recv packet */
 		status = ath6kl_htc_rx_process_hdr(target, packet, lk_ahds,
 						   n_lk_ahd);
@@ -2291,6 +2307,9 @@ static struct htc_packet *htc_wait_for_ctrl_msg(struct htc_target *target)
 	if (ath6kl_htc_rx_packet(target, packet, packet->act_len))
 		goto fail_ctrl_rx;
 
+	trace_ath6kl_htc_rx(packet->status, packet->endpoint,
+			    packet->buf, packet->act_len);
+
 	/* process receive header */
 	packet->status = ath6kl_htc_rx_process_hdr(target, packet, NULL, NULL);
 
diff --git a/drivers/net/wireless/ath/ath6kl/htc_pipe.c b/drivers/net/wireless/ath/ath6kl/htc_pipe.c
index 2813901..67aa924 100644
--- a/drivers/net/wireless/ath/ath6kl/htc_pipe.c
+++ b/drivers/net/wireless/ath/ath6kl/htc_pipe.c
@@ -988,8 +988,6 @@ static int ath6kl_htc_pipe_rx_complete(struct ath6kl *ar, struct sk_buff *skb,
 
 	htc_hdr = (struct htc_frame_hdr *) netdata;
 
-	ep = &target->endpoint[htc_hdr->eid];
-
 	if (htc_hdr->eid >= ENDPOINT_MAX) {
 		ath6kl_dbg(ATH6KL_DBG_HTC,
 			   "HTC Rx: invalid EndpointID=%d\n",
@@ -997,6 +995,7 @@ static int ath6kl_htc_pipe_rx_complete(struct ath6kl *ar, struct sk_buff *skb,
 		status = -EINVAL;
 		goto free_skb;
 	}
+	ep = &target->endpoint[htc_hdr->eid];
 
 	payload_len = le16_to_cpu(get_unaligned(&htc_hdr->payld_len));
 
@@ -1168,8 +1167,8 @@ static int htc_wait_recv_ctrl_message(struct htc_target *target)
 	}
 
 	if (count <= 0) {
-		ath6kl_dbg(ATH6KL_DBG_HTC, "%s: Timeout!\n", __func__);
-		return -ECOMM;
+		ath6kl_warn("htc pipe control receive timeout!\n");
+		return -ETIMEDOUT;
 	}
 
 	return 0;
@@ -1582,16 +1581,16 @@ static int ath6kl_htc_pipe_wait_target(struct htc_target *target)
 		return status;
 
 	if (target->pipe.ctrl_response_len < sizeof(*ready_msg)) {
-		ath6kl_dbg(ATH6KL_DBG_HTC, "invalid htc ready msg len:%d!\n",
-			   target->pipe.ctrl_response_len);
+		ath6kl_warn("invalid htc pipe ready msg len: %d\n",
+			    target->pipe.ctrl_response_len);
 		return -ECOMM;
 	}
 
 	ready_msg = (struct htc_ready_ext_msg *) target->pipe.ctrl_response_buf;
 
 	if (ready_msg->ver2_0_info.msg_id != cpu_to_le16(HTC_MSG_READY_ID)) {
-		ath6kl_dbg(ATH6KL_DBG_HTC, "invalid htc ready msg : 0x%X !\n",
-			   ready_msg->ver2_0_info.msg_id);
+		ath6kl_warn("invalid htc pipe ready msg: 0x%x\n",
+			    ready_msg->ver2_0_info.msg_id);
 		return -ECOMM;
 	}
 
diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c
index 5d434cf..40ffee6 100644
--- a/drivers/net/wireless/ath/ath6kl/init.c
+++ b/drivers/net/wireless/ath/ath6kl/init.c
@@ -201,8 +201,8 @@ struct sk_buff *ath6kl_buf_alloc(int size)
 	u16 reserved;
 
 	/* Add chacheline space at front and back of buffer */
-	reserved = (2 * L1_CACHE_BYTES) + ATH6KL_DATA_OFFSET +
-		   sizeof(struct htc_packet) + ATH6KL_HTC_ALIGN_BYTES;
+	reserved = roundup((2 * L1_CACHE_BYTES) + ATH6KL_DATA_OFFSET +
+		   sizeof(struct htc_packet) + ATH6KL_HTC_ALIGN_BYTES, 4);
 	skb = dev_alloc_skb(size + reserved);
 
 	if (skb)
@@ -1549,10 +1549,89 @@ static const char *ath6kl_init_get_hif_name(enum ath6kl_hif_type type)
 	return NULL;
 }
 
+
+static const struct fw_capa_str_map {
+	int id;
+	const char *name;
+} fw_capa_map[] = {
+	{ ATH6KL_FW_CAPABILITY_HOST_P2P, "host-p2p" },
+	{ ATH6KL_FW_CAPABILITY_SCHED_SCAN, "sched-scan" },
+	{ ATH6KL_FW_CAPABILITY_STA_P2PDEV_DUPLEX, "sta-p2pdev-duplex" },
+	{ ATH6KL_FW_CAPABILITY_INACTIVITY_TIMEOUT, "inactivity-timeout" },
+	{ ATH6KL_FW_CAPABILITY_RSN_CAP_OVERRIDE, "rsn-cap-override" },
+	{ ATH6KL_FW_CAPABILITY_WOW_MULTICAST_FILTER, "wow-mc-filter" },
+	{ ATH6KL_FW_CAPABILITY_BMISS_ENHANCE, "bmiss-enhance" },
+	{ ATH6KL_FW_CAPABILITY_SCHED_SCAN_MATCH_LIST, "sscan-match-list" },
+	{ ATH6KL_FW_CAPABILITY_RSSI_SCAN_THOLD, "rssi-scan-thold" },
+	{ ATH6KL_FW_CAPABILITY_CUSTOM_MAC_ADDR, "custom-mac-addr" },
+	{ ATH6KL_FW_CAPABILITY_TX_ERR_NOTIFY, "tx-err-notify" },
+	{ ATH6KL_FW_CAPABILITY_REGDOMAIN, "regdomain" },
+	{ ATH6KL_FW_CAPABILITY_SCHED_SCAN_V2, "sched-scan-v2" },
+	{ ATH6KL_FW_CAPABILITY_HEART_BEAT_POLL, "hb-poll" },
+};
+
+static const char *ath6kl_init_get_fw_capa_name(unsigned int id)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(fw_capa_map); i++) {
+		if (fw_capa_map[i].id == id)
+			return fw_capa_map[i].name;
+	}
+
+	return "<unknown>";
+}
+
+static void ath6kl_init_get_fwcaps(struct ath6kl *ar, char *buf, size_t buf_len)
+{
+	u8 *data = (u8 *) ar->fw_capabilities;
+	size_t trunc_len, len = 0;
+	int i, index, bit;
+	char *trunc = "...";
+
+	for (i = 0; i < ATH6KL_FW_CAPABILITY_MAX; i++) {
+		index = i / 8;
+		bit = i % 8;
+
+		if (index >= sizeof(ar->fw_capabilities) * 4)
+			break;
+
+		if (buf_len - len < 4) {
+			ath6kl_warn("firmware capability buffer too small!\n");
+
+			/* add "..." to the end of string */
+			trunc_len = strlen(trunc) + 1;
+			strncpy(buf + buf_len - trunc_len, trunc, trunc_len);
+
+			return;
+		}
+
+		if (data[index] & (1 << bit)) {
+			len += scnprintf(buf + len, buf_len - len, "%s,",
+					    ath6kl_init_get_fw_capa_name(i));
+		}
+	}
+
+	/* overwrite the last comma */
+	if (len > 0)
+		len--;
+
+	buf[len] = '\0';
+}
+
+static int ath6kl_init_hw_reset(struct ath6kl *ar)
+{
+	ath6kl_dbg(ATH6KL_DBG_BOOT, "cold resetting the device");
+
+	return ath6kl_diag_write32(ar, RESET_CONTROL_ADDRESS,
+				   cpu_to_le32(RESET_CONTROL_COLD_RST));
+}
+
 static int __ath6kl_init_hw_start(struct ath6kl *ar)
 {
 	long timeleft;
 	int ret, i;
+	char buf[200];
 
 	ath6kl_dbg(ATH6KL_DBG_BOOT, "hw start\n");
 
@@ -1569,24 +1648,35 @@ static int __ath6kl_init_hw_start(struct ath6kl *ar)
 		goto err_power_off;
 
 	/* Do we need to finish the BMI phase */
-	/* FIXME: return error from ath6kl_bmi_done() */
-	if (ath6kl_bmi_done(ar)) {
-		ret = -EIO;
+	ret = ath6kl_bmi_done(ar);
+	if (ret)
 		goto err_power_off;
-	}
 
 	/*
 	 * The reason we have to wait for the target here is that the
 	 * driver layer has to init BMI in order to set the host block
 	 * size.
 	 */
-	if (ath6kl_htc_wait_target(ar->htc_target)) {
-		ret = -EIO;
+	ret = ath6kl_htc_wait_target(ar->htc_target);
+
+	if (ret == -ETIMEDOUT) {
+		/*
+		 * Most likely USB target is in odd state after reboot and
+		 * needs a reset. A cold reset makes the whole device
+		 * disappear from USB bus and initialisation starts from
+		 * beginning.
+		 */
+		ath6kl_warn("htc wait target timed out, resetting device\n");
+		ath6kl_init_hw_reset(ar);
+		goto err_power_off;
+	} else if (ret) {
+		ath6kl_err("htc wait target failed: %d\n", ret);
 		goto err_power_off;
 	}
 
-	if (ath6kl_init_service_ep(ar)) {
-		ret = -EIO;
+	ret = ath6kl_init_service_ep(ar);
+	if (ret) {
+		ath6kl_err("Endpoint service initilisation failed: %d\n", ret);
 		goto err_cleanup_scatter;
 	}
 
@@ -1617,6 +1707,8 @@ static int __ath6kl_init_hw_start(struct ath6kl *ar)
 			    ar->wiphy->fw_version,
 			    ar->fw_api,
 			    test_bit(TESTMODE, &ar->flag) ? " testmode" : "");
+		ath6kl_init_get_fwcaps(ar, buf, sizeof(buf));
+		ath6kl_info("firmware supports: %s\n", buf);
 	}
 
 	if (ar->version.abi_ver != ATH6KL_ABI_VERSION) {
@@ -1765,9 +1857,7 @@ void ath6kl_stop_txrx(struct ath6kl *ar)
 	 * Try to reset the device if we can. The driver may have been
 	 * configure NOT to reset the target during a debug session.
 	 */
-	ath6kl_dbg(ATH6KL_DBG_TRC,
-		   "attempting to reset target on instance destroy\n");
-	ath6kl_reset_device(ar, ar->target_type, true, true);
+	ath6kl_init_hw_reset(ar);
 
 	up(&ar->sem);
 }
diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c
index bd50b6b..d4fcfca 100644
--- a/drivers/net/wireless/ath/ath6kl/main.c
+++ b/drivers/net/wireless/ath/ath6kl/main.c
@@ -345,39 +345,6 @@ out:
 	return ret;
 }
 
-/* FIXME: move to a better place, target.h? */
-#define AR6003_RESET_CONTROL_ADDRESS 0x00004000
-#define AR6004_RESET_CONTROL_ADDRESS 0x00004000
-
-void ath6kl_reset_device(struct ath6kl *ar, u32 target_type,
-			 bool wait_fot_compltn, bool cold_reset)
-{
-	int status = 0;
-	u32 address;
-	__le32 data;
-
-	if (target_type != TARGET_TYPE_AR6003 &&
-	    target_type != TARGET_TYPE_AR6004)
-		return;
-
-	data = cold_reset ? cpu_to_le32(RESET_CONTROL_COLD_RST) :
-			    cpu_to_le32(RESET_CONTROL_MBOX_RST);
-
-	switch (target_type) {
-	case TARGET_TYPE_AR6003:
-		address = AR6003_RESET_CONTROL_ADDRESS;
-		break;
-	case TARGET_TYPE_AR6004:
-		address = AR6004_RESET_CONTROL_ADDRESS;
-		break;
-	}
-
-	status = ath6kl_diag_write32(ar, address, data);
-
-	if (status)
-		ath6kl_err("failed to reset target\n");
-}
-
 static void ath6kl_install_static_wep_keys(struct ath6kl_vif *vif)
 {
 	u8 index;
@@ -1327,9 +1294,11 @@ void init_netdev(struct net_device *dev)
 	dev->watchdog_timeo = ATH6KL_TX_TIMEOUT;
 
 	dev->needed_headroom = ETH_HLEN;
-	dev->needed_headroom += sizeof(struct ath6kl_llc_snap_hdr) +
-				sizeof(struct wmi_data_hdr) + HTC_HDR_LENGTH
-				+ WMI_MAX_TX_META_SZ + ATH6KL_HTC_ALIGN_BYTES;
+	dev->needed_headroom += roundup(sizeof(struct ath6kl_llc_snap_hdr) +
+					sizeof(struct wmi_data_hdr) +
+					HTC_HDR_LENGTH +
+					WMI_MAX_TX_META_SZ +
+					ATH6KL_HTC_ALIGN_BYTES, 4);
 
 	dev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_RXCSUM;
 
diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c
index d111980..fb14145 100644
--- a/drivers/net/wireless/ath/ath6kl/sdio.c
+++ b/drivers/net/wireless/ath/ath6kl/sdio.c
@@ -28,6 +28,7 @@
 #include "target.h"
 #include "debug.h"
 #include "cfg80211.h"
+#include "trace.h"
 
 struct ath6kl_sdio {
 	struct sdio_func *func;
@@ -179,6 +180,8 @@ static int ath6kl_sdio_io(struct sdio_func *func, u32 request, u32 addr,
 		   request & HIF_FIXED_ADDRESS ? " (fixed)" : "", buf, len);
 	ath6kl_dbg_dump(ATH6KL_DBG_SDIO_DUMP, NULL, "sdio ", buf, len);
 
+	trace_ath6kl_sdio(addr, request, buf, len);
+
 	return ret;
 }
 
@@ -309,6 +312,13 @@ static int ath6kl_sdio_scat_rw(struct ath6kl_sdio *ar_sdio,
 	sdio_claim_host(ar_sdio->func);
 
 	mmc_set_data_timeout(&data, ar_sdio->func->card);
+
+	trace_ath6kl_sdio_scat(scat_req->addr,
+			       scat_req->req,
+			       scat_req->len,
+			       scat_req->scat_entries,
+			       scat_req->scat_list);
+
 	/* synchronous call to process request */
 	mmc_wait_for_req(ar_sdio->func->card->host, &mmc_req);
 
@@ -1123,10 +1133,12 @@ static int ath6kl_sdio_bmi_write(struct ath6kl *ar, u8 *buf, u32 len)
 
 	ret = ath6kl_sdio_read_write_sync(ar, addr, buf, len,
 					  HIF_WR_SYNC_BYTE_INC);
-	if (ret)
+	if (ret) {
 		ath6kl_err("unable to send the bmi data to the device\n");
+		return ret;
+	}
 
-	return ret;
+	return 0;
 }
 
 static int ath6kl_sdio_bmi_read(struct ath6kl *ar, u8 *buf, u32 len)
diff --git a/drivers/net/wireless/ath/ath6kl/target.h b/drivers/net/wireless/ath/ath6kl/target.h
index a98c12b..a580a62 100644
--- a/drivers/net/wireless/ath/ath6kl/target.h
+++ b/drivers/net/wireless/ath/ath6kl/target.h
@@ -25,7 +25,7 @@
 #define AR6004_BOARD_DATA_SZ     6144
 #define AR6004_BOARD_EXT_DATA_SZ 0
 
-#define RESET_CONTROL_ADDRESS		0x00000000
+#define RESET_CONTROL_ADDRESS		0x00004000
 #define RESET_CONTROL_COLD_RST		0x00000100
 #define RESET_CONTROL_MBOX_RST		0x00000004
 
diff --git a/drivers/net/wireless/ath/ath6kl/trace.c b/drivers/net/wireless/ath/ath6kl/trace.c
new file mode 100644
index 0000000..e7d64b1
--- /dev/null
+++ b/drivers/net/wireless/ath/ath6kl/trace.c
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2012 Qualcomm Atheros, 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.
+ */
+
+#include <linux/module.h>
+
+#define CREATE_TRACE_POINTS
+#include "trace.h"
+
+EXPORT_TRACEPOINT_SYMBOL(ath6kl_sdio);
+EXPORT_TRACEPOINT_SYMBOL(ath6kl_sdio_scat);
diff --git a/drivers/net/wireless/ath/ath6kl/trace.h b/drivers/net/wireless/ath/ath6kl/trace.h
new file mode 100644
index 0000000..1a1ea78
--- /dev/null
+++ b/drivers/net/wireless/ath/ath6kl/trace.h
@@ -0,0 +1,332 @@
+#if !defined(_ATH6KL_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
+
+#include <net/cfg80211.h>
+#include <linux/skbuff.h>
+#include <linux/tracepoint.h>
+#include "wmi.h"
+#include "hif.h"
+
+#if !defined(_ATH6KL_TRACE_H)
+static inline unsigned int ath6kl_get_wmi_id(void *buf, size_t buf_len)
+{
+	struct wmi_cmd_hdr *hdr = buf;
+
+	if (buf_len < sizeof(*hdr))
+		return 0;
+
+	return le16_to_cpu(hdr->cmd_id);
+}
+#endif /* __ATH6KL_TRACE_H */
+
+#define _ATH6KL_TRACE_H
+
+/* create empty functions when tracing is disabled */
+#if !defined(CONFIG_ATH6KL_TRACING)
+#undef TRACE_EVENT
+#define TRACE_EVENT(name, proto, ...) \
+static inline void trace_ ## name(proto) {}
+#undef DECLARE_EVENT_CLASS
+#define DECLARE_EVENT_CLASS(...)
+#undef DEFINE_EVENT
+#define DEFINE_EVENT(evt_class, name, proto, ...) \
+static inline void trace_ ## name(proto) {}
+#endif /* !CONFIG_ATH6KL_TRACING || __CHECKER__ */
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM ath6kl
+
+TRACE_EVENT(ath6kl_wmi_cmd,
+	TP_PROTO(void *buf, size_t buf_len),
+
+	TP_ARGS(buf, buf_len),
+
+	TP_STRUCT__entry(
+		__field(unsigned int, id)
+		__field(size_t, buf_len)
+		__dynamic_array(u8, buf, buf_len)
+	),
+
+	TP_fast_assign(
+		__entry->id = ath6kl_get_wmi_id(buf, buf_len);
+		__entry->buf_len = buf_len;
+		memcpy(__get_dynamic_array(buf), buf, buf_len);
+	),
+
+	TP_printk(
+		"id %d len %zd",
+		__entry->id, __entry->buf_len
+	)
+);
+
+TRACE_EVENT(ath6kl_wmi_event,
+	TP_PROTO(void *buf, size_t buf_len),
+
+	TP_ARGS(buf, buf_len),
+
+	TP_STRUCT__entry(
+		__field(unsigned int, id)
+		__field(size_t, buf_len)
+		__dynamic_array(u8, buf, buf_len)
+	),
+
+	TP_fast_assign(
+		__entry->id = ath6kl_get_wmi_id(buf, buf_len);
+		__entry->buf_len = buf_len;
+		memcpy(__get_dynamic_array(buf), buf, buf_len);
+	),
+
+	TP_printk(
+		"id %d len %zd",
+		__entry->id, __entry->buf_len
+	)
+);
+
+TRACE_EVENT(ath6kl_sdio,
+	TP_PROTO(unsigned int addr, int flags,
+		 void *buf, size_t buf_len),
+
+	TP_ARGS(addr, flags, buf, buf_len),
+
+	TP_STRUCT__entry(
+		__field(unsigned int, tx)
+		__field(unsigned int, addr)
+		__field(int, flags)
+		__field(size_t, buf_len)
+		__dynamic_array(u8, buf, buf_len)
+	),
+
+	TP_fast_assign(
+		__entry->addr = addr;
+		__entry->flags = flags;
+		__entry->buf_len = buf_len;
+		memcpy(__get_dynamic_array(buf), buf, buf_len);
+
+		if (flags & HIF_WRITE)
+			__entry->tx = 1;
+		else
+			__entry->tx = 0;
+	),
+
+	TP_printk(
+		"%s addr 0x%x flags 0x%x len %zd\n",
+		__entry->tx ? "tx" : "rx",
+		__entry->addr,
+		__entry->flags,
+		__entry->buf_len
+	)
+);
+
+TRACE_EVENT(ath6kl_sdio_scat,
+	TP_PROTO(unsigned int addr, int flags, unsigned int total_len,
+		 unsigned int entries, struct hif_scatter_item *list),
+
+	TP_ARGS(addr, flags, total_len, entries, list),
+
+	TP_STRUCT__entry(
+		__field(unsigned int, tx)
+		__field(unsigned int, addr)
+		__field(int, flags)
+		__field(unsigned int, entries)
+		__field(size_t, total_len)
+		__dynamic_array(unsigned int, len_array, entries)
+		__dynamic_array(u8, data, total_len)
+	),
+
+	TP_fast_assign(
+		unsigned int *len_array;
+		int i, offset = 0;
+		size_t len;
+
+		__entry->addr = addr;
+		__entry->flags = flags;
+		__entry->entries = entries;
+		__entry->total_len = total_len;
+
+		if (flags & HIF_WRITE)
+			__entry->tx = 1;
+		else
+			__entry->tx = 0;
+
+		len_array = __get_dynamic_array(len_array);
+
+		for (i = 0; i < entries; i++) {
+			len = list[i].len;
+
+			memcpy((u8 *) __get_dynamic_array(data) + offset,
+			       list[i].buf, len);
+
+			len_array[i] = len;
+			offset += len;
+		}
+	),
+
+	TP_printk(
+		"%s addr 0x%x flags 0x%x entries %d total_len %zd\n",
+		__entry->tx ? "tx" : "rx",
+		__entry->addr,
+		__entry->flags,
+		__entry->entries,
+		__entry->total_len
+	)
+);
+
+TRACE_EVENT(ath6kl_sdio_irq,
+	TP_PROTO(void *buf, size_t buf_len),
+
+	TP_ARGS(buf, buf_len),
+
+	TP_STRUCT__entry(
+		__field(size_t, buf_len)
+		__dynamic_array(u8, buf, buf_len)
+	),
+
+	TP_fast_assign(
+		__entry->buf_len = buf_len;
+		memcpy(__get_dynamic_array(buf), buf, buf_len);
+	),
+
+	TP_printk(
+		"irq len %zd\n", __entry->buf_len
+	)
+);
+
+TRACE_EVENT(ath6kl_htc_rx,
+	TP_PROTO(int status, int endpoint, void *buf,
+		 size_t buf_len),
+
+	TP_ARGS(status, endpoint, buf, buf_len),
+
+	TP_STRUCT__entry(
+		__field(int, status)
+		__field(int, endpoint)
+		__field(size_t, buf_len)
+		__dynamic_array(u8, buf, buf_len)
+	),
+
+	TP_fast_assign(
+		__entry->status = status;
+		__entry->endpoint = endpoint;
+		__entry->buf_len = buf_len;
+		memcpy(__get_dynamic_array(buf), buf, buf_len);
+	),
+
+	TP_printk(
+		"status %d endpoint %d len %zd\n",
+		__entry->status,
+		__entry->endpoint,
+		__entry->buf_len
+	)
+);
+
+TRACE_EVENT(ath6kl_htc_tx,
+	TP_PROTO(int status, int endpoint, void *buf,
+		 size_t buf_len),
+
+	TP_ARGS(status, endpoint, buf, buf_len),
+
+	TP_STRUCT__entry(
+		__field(int, status)
+		__field(int, endpoint)
+		__field(size_t, buf_len)
+		__dynamic_array(u8, buf, buf_len)
+	),
+
+	TP_fast_assign(
+		__entry->status = status;
+		__entry->endpoint = endpoint;
+		__entry->buf_len = buf_len;
+		memcpy(__get_dynamic_array(buf), buf, buf_len);
+	),
+
+	TP_printk(
+		"status %d endpoint %d len %zd\n",
+		__entry->status,
+		__entry->endpoint,
+		__entry->buf_len
+	)
+);
+
+#define ATH6KL_MSG_MAX 200
+
+DECLARE_EVENT_CLASS(ath6kl_log_event,
+	TP_PROTO(struct va_format *vaf),
+	TP_ARGS(vaf),
+	TP_STRUCT__entry(
+		__dynamic_array(char, msg, ATH6KL_MSG_MAX)
+	),
+	TP_fast_assign(
+		WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg),
+				       ATH6KL_MSG_MAX,
+				       vaf->fmt,
+				       *vaf->va) >= ATH6KL_MSG_MAX);
+	),
+	TP_printk("%s", __get_str(msg))
+);
+
+DEFINE_EVENT(ath6kl_log_event, ath6kl_log_err,
+	     TP_PROTO(struct va_format *vaf),
+	     TP_ARGS(vaf)
+);
+
+DEFINE_EVENT(ath6kl_log_event, ath6kl_log_warn,
+	     TP_PROTO(struct va_format *vaf),
+	     TP_ARGS(vaf)
+);
+
+DEFINE_EVENT(ath6kl_log_event, ath6kl_log_info,
+	     TP_PROTO(struct va_format *vaf),
+	     TP_ARGS(vaf)
+);
+
+TRACE_EVENT(ath6kl_log_dbg,
+	TP_PROTO(unsigned int level, struct va_format *vaf),
+	TP_ARGS(level, vaf),
+	TP_STRUCT__entry(
+		__field(unsigned int, level)
+		__dynamic_array(char, msg, ATH6KL_MSG_MAX)
+	),
+	TP_fast_assign(
+		__entry->level = level;
+		WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg),
+				       ATH6KL_MSG_MAX,
+				       vaf->fmt,
+				       *vaf->va) >= ATH6KL_MSG_MAX);
+	),
+	TP_printk("%s", __get_str(msg))
+);
+
+TRACE_EVENT(ath6kl_log_dbg_dump,
+	TP_PROTO(const char *msg, const char *prefix,
+		 const void *buf, size_t buf_len),
+
+	TP_ARGS(msg, prefix, buf, buf_len),
+
+	TP_STRUCT__entry(
+		__string(msg, msg)
+		__string(prefix, prefix)
+		__field(size_t, buf_len)
+		__dynamic_array(u8, buf, buf_len)
+	),
+
+	TP_fast_assign(
+		__assign_str(msg, msg);
+		__assign_str(prefix, prefix);
+		__entry->buf_len = buf_len;
+		memcpy(__get_dynamic_array(buf), buf, buf_len);
+	),
+
+	TP_printk(
+		"%s/%s\n", __get_str(prefix), __get_str(msg)
+	)
+);
+
+#endif /* _ ATH6KL_TRACE_H || TRACE_HEADER_MULTI_READ*/
+
+/* we don't want to use include/trace/events */
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE trace
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/drivers/net/wireless/ath/ath6kl/txrx.c b/drivers/net/wireless/ath/ath6kl/txrx.c
index 78b3692..ebb2404 100644
--- a/drivers/net/wireless/ath/ath6kl/txrx.c
+++ b/drivers/net/wireless/ath/ath6kl/txrx.c
@@ -20,6 +20,7 @@
 #include "core.h"
 #include "debug.h"
 #include "htc-ops.h"
+#include "trace.h"
 
 /*
  * tid - tid_mux0..tid_mux3
@@ -288,6 +289,8 @@ int ath6kl_control_tx(void *devt, struct sk_buff *skb,
 	int status = 0;
 	struct ath6kl_cookie *cookie = NULL;
 
+	trace_ath6kl_wmi_cmd(skb->data, skb->len);
+
 	if (WARN_ON_ONCE(ar->state == ATH6KL_STATE_WOW)) {
 		dev_kfree_skb(skb);
 		return -EACCES;
@@ -1324,7 +1327,7 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet)
 		   __func__, ar, ept, skb, packet->buf,
 		   packet->act_len, status);
 
-	if (status || !(skb->data + HTC_HDR_LENGTH)) {
+	if (status || packet->act_len < HTC_HDR_LENGTH) {
 		dev_kfree_skb(skb);
 		return;
 	}
diff --git a/drivers/net/wireless/ath/ath6kl/usb.c b/drivers/net/wireless/ath/ath6kl/usb.c
index 5fcd342..bed0d33 100644
--- a/drivers/net/wireless/ath/ath6kl/usb.c
+++ b/drivers/net/wireless/ath/ath6kl/usb.c
@@ -856,11 +856,9 @@ static int ath6kl_usb_submit_ctrl_out(struct ath6kl_usb *ar_usb,
 	int ret;
 
 	if (size > 0) {
-		buf = kmalloc(size, GFP_KERNEL);
+		buf = kmemdup(data, size, GFP_KERNEL);
 		if (buf == NULL)
 			return -ENOMEM;
-
-		memcpy(buf, data, size);
 	}
 
 	/* note: if successful returns number of bytes transfered */
@@ -872,8 +870,9 @@ static int ath6kl_usb_submit_ctrl_out(struct ath6kl_usb *ar_usb,
 			      size, 1000);
 
 	if (ret < 0) {
-		ath6kl_dbg(ATH6KL_DBG_USB, "%s failed,result = %d\n",
-			   __func__, ret);
+		ath6kl_warn("Failed to submit usb control message: %d\n", ret);
+		kfree(buf);
+		return ret;
 	}
 
 	kfree(buf);
@@ -903,8 +902,9 @@ static int ath6kl_usb_submit_ctrl_in(struct ath6kl_usb *ar_usb,
 				 size, 2 * HZ);
 
 	if (ret < 0) {
-		ath6kl_dbg(ATH6KL_DBG_USB, "%s failed,result = %d\n",
-			   __func__, ret);
+		ath6kl_warn("Failed to read usb control message: %d\n", ret);
+		kfree(buf);
+		return ret;
 	}
 
 	memcpy((u8 *) data, buf, size);
@@ -961,8 +961,10 @@ static int ath6kl_usb_diag_read32(struct ath6kl *ar, u32 address, u32 *data)
 				ATH6KL_USB_CONTROL_REQ_DIAG_RESP,
 				ar_usb->diag_resp_buffer, &resp_len);
 
-	if (ret)
+	if (ret) {
+		ath6kl_warn("diag read32 failed: %d\n", ret);
 		return ret;
+	}
 
 	resp = (struct ath6kl_usb_ctrl_diag_resp_read *)
 		ar_usb->diag_resp_buffer;
@@ -976,6 +978,7 @@ static int ath6kl_usb_diag_write32(struct ath6kl *ar, u32 address, __le32 data)
 {
 	struct ath6kl_usb *ar_usb = ar->hif_priv;
 	struct ath6kl_usb_ctrl_diag_cmd_write *cmd;
+	int ret;
 
 	cmd = (struct ath6kl_usb_ctrl_diag_cmd_write *) ar_usb->diag_cmd_buffer;
 
@@ -984,12 +987,17 @@ static int ath6kl_usb_diag_write32(struct ath6kl *ar, u32 address, __le32 data)
 	cmd->address = cpu_to_le32(address);
 	cmd->value = data;
 
-	return ath6kl_usb_ctrl_msg_exchange(ar_usb,
-					    ATH6KL_USB_CONTROL_REQ_DIAG_CMD,
-					    (u8 *) cmd,
-					    sizeof(*cmd),
-					    0, NULL, NULL);
+	ret = ath6kl_usb_ctrl_msg_exchange(ar_usb,
+					   ATH6KL_USB_CONTROL_REQ_DIAG_CMD,
+					   (u8 *) cmd,
+					   sizeof(*cmd),
+					   0, NULL, NULL);
+	if (ret) {
+		ath6kl_warn("diag_write32 failed: %d\n", ret);
+		return ret;
+	}
 
+	return 0;
 }
 
 static int ath6kl_usb_bmi_read(struct ath6kl *ar, u8 *buf, u32 len)
@@ -1001,7 +1009,7 @@ static int ath6kl_usb_bmi_read(struct ath6kl *ar, u8 *buf, u32 len)
 	ret = ath6kl_usb_submit_ctrl_in(ar_usb,
 					ATH6KL_USB_CONTROL_REQ_RECV_BMI_RESP,
 					0, 0, buf, len);
-	if (ret != 0) {
+	if (ret) {
 		ath6kl_err("Unable to read the bmi data from the device: %d\n",
 			   ret);
 		return ret;
@@ -1019,7 +1027,7 @@ static int ath6kl_usb_bmi_write(struct ath6kl *ar, u8 *buf, u32 len)
 	ret = ath6kl_usb_submit_ctrl_out(ar_usb,
 					 ATH6KL_USB_CONTROL_REQ_SEND_BMI_CMD,
 					 0, 0, buf, len);
-	if (ret != 0) {
+	if (ret) {
 		ath6kl_err("unable to send the bmi data to the device: %d\n",
 			   ret);
 		return ret;
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c
index d76b5bd..87aefb4 100644
--- a/drivers/net/wireless/ath/ath6kl/wmi.c
+++ b/drivers/net/wireless/ath/ath6kl/wmi.c
@@ -20,6 +20,7 @@
 #include "core.h"
 #include "debug.h"
 #include "testmode.h"
+#include "trace.h"
 #include "../regd.h"
 #include "../regd_common.h"
 
@@ -2028,6 +2029,9 @@ int ath6kl_wmi_beginscan_cmd(struct wmi *wmi, u8 if_idx,
 		if (!sband)
 			continue;
 
+		if (WARN_ON(band >= ATH6KL_NUM_BANDS))
+			break;
+
 		ratemask = rates[band];
 		supp_rates = sc->supp_rates[band].rates;
 		num_rates = 0;
@@ -4086,6 +4090,8 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb)
 		return -EINVAL;
 	}
 
+	trace_ath6kl_wmi_event(skb->data, skb->len);
+
 	return ath6kl_wmi_proc_events(wmi, skb);
 }
 
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_calib.c b/drivers/net/wireless/ath/ath9k/ar9002_calib.c
index c55e5bb..9f58974 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c
@@ -731,7 +731,8 @@ static bool ar9285_hw_cl_cal(struct ath_hw *ah, struct ath9k_channel *chan)
 		if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
 				  AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT)) {
 			ath_dbg(common, CALIBRATE,
-				"offset calibration failed to complete in 1ms; noisy environment?\n");
+				"offset calibration failed to complete in %d ms; noisy environment?\n",
+				AH_WAIT_TIMEOUT / 1000);
 			return false;
 		}
 		REG_CLR_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN);
@@ -745,7 +746,8 @@ static bool ar9285_hw_cl_cal(struct ath_hw *ah, struct ath9k_channel *chan)
 	if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL,
 			  0, AH_WAIT_TIMEOUT)) {
 		ath_dbg(common, CALIBRATE,
-			"offset calibration failed to complete in 1ms; noisy environment?\n");
+			"offset calibration failed to complete in %d ms; noisy environment?\n",
+			AH_WAIT_TIMEOUT / 1000);
 		return false;
 	}
 
@@ -841,7 +843,8 @@ static bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan)
 				   AR_PHY_AGC_CONTROL_CAL,
 				   0, AH_WAIT_TIMEOUT)) {
 			ath_dbg(common, CALIBRATE,
-				"offset calibration failed to complete in 1ms; noisy environment?\n");
+				"offset calibration failed to complete in %d ms; noisy environment?\n",
+				AH_WAIT_TIMEOUT / 1000);
 			return false;
 		}
 
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
index f76c3ca..639ba7d 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
@@ -1126,7 +1126,8 @@ skip_tx_iqcal:
 			ar9003_hw_rtt_disable(ah);
 
 		ath_dbg(common, CALIBRATE,
-			"offset calibration failed to complete in 1ms; noisy environment?\n");
+			"offset calibration failed to complete in %d ms; noisy environment?\n",
+			AH_WAIT_TIMEOUT / 1000);
 		return false;
 	}
 
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
index 881e989..e6b92ff 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
@@ -3606,6 +3606,12 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz)
 	value = ar9003_hw_ant_ctrl_common_2_get(ah, is2ghz);
 	REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2, AR_SWITCH_TABLE_COM2_ALL, value);
 
+	if ((AR_SREV_9462(ah)) && (ah->rxchainmask == 0x2)) {
+		value = ar9003_hw_ant_ctrl_chain_get(ah, 1, is2ghz);
+		REG_RMW_FIELD(ah, switch_chain_reg[0],
+			      AR_SWITCH_TABLE_ALL, value);
+	}
+
 	for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
 		if ((ah->rxchainmask & BIT(chain)) ||
 		    (ah->txchainmask & BIT(chain))) {
@@ -3772,6 +3778,17 @@ static void ar9003_hw_atten_apply(struct ath_hw *ah, struct ath9k_channel *chan)
 					  AR_PHY_EXT_ATTEN_CTL_2,
 					 };
 
+	if ((AR_SREV_9462(ah)) && (ah->rxchainmask == 0x2)) {
+		value = ar9003_hw_atten_chain_get(ah, 1, chan);
+		REG_RMW_FIELD(ah, ext_atten_reg[0],
+			      AR_PHY_EXT_ATTEN_CTL_XATTEN1_DB, value);
+
+		value = ar9003_hw_atten_chain_get_margin(ah, 1, chan);
+		REG_RMW_FIELD(ah, ext_atten_reg[0],
+			      AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN,
+			      value);
+	}
+
 	/* Test value. if 0 then attenuation is unused. Don't load anything. */
 	for (i = 0; i < 3; i++) {
 		if (ah->txchainmask & BIT(i)) {
diff --git a/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h
index ccc42a7..999ab08 100644
--- a/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h
+++ b/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h
@@ -37,28 +37,28 @@ static const u32 ar9462_pciephy_clkreq_enable_L1_2p0[][2] = {
 	/* Addr      allmodes  */
 	{0x00018c00, 0x18253ede},
 	{0x00018c04, 0x000801d8},
-	{0x00018c08, 0x0003580c},
+	{0x00018c08, 0x0003780c},
 };
 
 static const u32 ar9462_2p0_baseband_postamble[][5] = {
 	/* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
 	{0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a800d},
 	{0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a01ae},
-	{0x00009824, 0x5ac640de, 0x5ac640d0, 0x5ac640d0, 0x63c640da},
+	{0x00009824, 0x63c640de, 0x5ac640d0, 0x5ac640d0, 0x63c640da},
 	{0x00009828, 0x0796be89, 0x0696b081, 0x0696b881, 0x09143e81},
 	{0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
 	{0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c},
 	{0x00009c00, 0x000000c4, 0x000000c4, 0x000000c4, 0x000000c4},
-	{0x00009e00, 0x0372111a, 0x0372111a, 0x037216a0, 0x037216a0},
+	{0x00009e00, 0x0372111a, 0x0372111a, 0x037216a0, 0x037216a2},
 	{0x00009e04, 0x001c2020, 0x001c2020, 0x001c2020, 0x001c2020},
 	{0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000d8},
 	{0x00009e10, 0x92c88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec86d2e},
-	{0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3376605e, 0x32395d5e},
+	{0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3236605e, 0x32365a5e},
 	{0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
 	{0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
 	{0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
 	{0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
-	{0x00009e3c, 0xcf946222, 0xcf946222, 0xcfd5c782, 0xcfd5c282},
+	{0x00009e3c, 0xcf946220, 0xcf946220, 0xcfd5c782, 0xcfd5c282},
 	{0x00009e44, 0x62321e27, 0x62321e27, 0xfe291e27, 0xfe291e27},
 	{0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
 	{0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
@@ -82,9 +82,9 @@ static const u32 ar9462_2p0_baseband_postamble[][5] = {
 	{0x0000a2d0, 0x00041981, 0x00041981, 0x00041981, 0x00041982},
 	{0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b},
 	{0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-	{0x0000a3a4, 0x00000010, 0x00000010, 0x00000000, 0x00000000},
+	{0x0000a3a4, 0x00000050, 0x00000050, 0x00000000, 0x00000000},
 	{0x0000a3a8, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa},
-	{0x0000a3ac, 0xaaaaaa00, 0xaaaaaa30, 0xaaaaaa00, 0xaaaaaa00},
+	{0x0000a3ac, 0xaaaaaa00, 0xaa30aa30, 0xaaaaaa00, 0xaaaaaa00},
 	{0x0000a41c, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce},
 	{0x0000a420, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce},
 	{0x0000a424, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce},
@@ -363,14 +363,14 @@ static const u32 ar9462_pciephy_clkreq_disable_L1_2p0[][2] = {
 	/* Addr      allmodes  */
 	{0x00018c00, 0x18213ede},
 	{0x00018c04, 0x000801d8},
-	{0x00018c08, 0x0003580c},
+	{0x00018c08, 0x0003780c},
 };
 
 static const u32 ar9462_pciephy_pll_on_clkreq_disable_L1_2p0[][2] = {
 	/* Addr      allmodes  */
 	{0x00018c00, 0x18212ede},
 	{0x00018c04, 0x000801d8},
-	{0x00018c08, 0x0003580c},
+	{0x00018c08, 0x0003780c},
 };
 
 static const u32 ar9462_2p0_radio_postamble_sys2ant[][5] = {
@@ -775,7 +775,7 @@ static const u32 ar9462_2p0_baseband_core[][2] = {
 	{0x00009fc0, 0x803e4788},
 	{0x00009fc4, 0x0001efb5},
 	{0x00009fcc, 0x40000014},
-	{0x00009fd0, 0x01193b93},
+	{0x00009fd0, 0x0a193b93},
 	{0x0000a20c, 0x00000000},
 	{0x0000a220, 0x00000000},
 	{0x0000a224, 0x00000000},
@@ -850,7 +850,7 @@ static const u32 ar9462_2p0_baseband_core[][2] = {
 	{0x0000a7cc, 0x00000000},
 	{0x0000a7d0, 0x00000000},
 	{0x0000a7d4, 0x00000004},
-	{0x0000a7dc, 0x00000001},
+	{0x0000a7dc, 0x00000000},
 	{0x0000a7f0, 0x80000000},
 	{0x0000a8d0, 0x004b6a8e},
 	{0x0000a8d4, 0x00000820},
@@ -886,7 +886,7 @@ static const u32 ar9462_modes_high_ob_db_tx_gain_table_2p0[][5] = {
 	{0x0000a2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584},
 	{0x0000a2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800},
 	{0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
-	{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
+	{0x0000a410, 0x000050da, 0x000050da, 0x000050de, 0x000050de},
 	{0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
 	{0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
 	{0x0000a504, 0x06002223, 0x06002223, 0x04000002, 0x04000002},
@@ -906,20 +906,20 @@ static const u32 ar9462_modes_high_ob_db_tx_gain_table_2p0[][5] = {
 	{0x0000a53c, 0x41025e4a, 0x41025e4a, 0x34001640, 0x34001640},
 	{0x0000a540, 0x48025e6c, 0x48025e6c, 0x38001660, 0x38001660},
 	{0x0000a544, 0x4e025e8e, 0x4e025e8e, 0x3b001861, 0x3b001861},
-	{0x0000a548, 0x53025eb2, 0x53025eb2, 0x3e001a81, 0x3e001a81},
-	{0x0000a54c, 0x59025eb6, 0x59025eb6, 0x42001a83, 0x42001a83},
-	{0x0000a550, 0x5d025ef6, 0x5d025ef6, 0x44001c84, 0x44001c84},
+	{0x0000a548, 0x55025eb3, 0x55025eb3, 0x3e001a81, 0x3e001a81},
+	{0x0000a54c, 0x58025ef3, 0x58025ef3, 0x42001a83, 0x42001a83},
+	{0x0000a550, 0x5d025ef6, 0x5d025ef6, 0x44001a84, 0x44001a84},
 	{0x0000a554, 0x62025f56, 0x62025f56, 0x48001ce3, 0x48001ce3},
 	{0x0000a558, 0x66027f56, 0x66027f56, 0x4c001ce5, 0x4c001ce5},
 	{0x0000a55c, 0x6a029f56, 0x6a029f56, 0x50001ce9, 0x50001ce9},
 	{0x0000a560, 0x70049f56, 0x70049f56, 0x54001ceb, 0x54001ceb},
-	{0x0000a564, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
-	{0x0000a568, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
-	{0x0000a56c, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
-	{0x0000a570, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
-	{0x0000a574, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
-	{0x0000a578, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
-	{0x0000a57c, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
+	{0x0000a564, 0x751ffff6, 0x751ffff6, 0x56001eec, 0x56001eec},
+	{0x0000a568, 0x751ffff6, 0x751ffff6, 0x58001ef0, 0x58001ef0},
+	{0x0000a56c, 0x751ffff6, 0x751ffff6, 0x5a001ef4, 0x5a001ef4},
+	{0x0000a570, 0x751ffff6, 0x751ffff6, 0x5c001ff6, 0x5c001ff6},
+	{0x0000a574, 0x751ffff6, 0x751ffff6, 0x5c001ff6, 0x5c001ff6},
+	{0x0000a578, 0x751ffff6, 0x751ffff6, 0x5c001ff6, 0x5c001ff6},
+	{0x0000a57c, 0x751ffff6, 0x751ffff6, 0x5c001ff6, 0x5c001ff6},
 	{0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
 	{0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
 	{0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
@@ -1053,7 +1053,6 @@ static const u32 ar9462_2p0_mac_core[][2] = {
 	{0x00008044, 0x00000000},
 	{0x00008048, 0x00000000},
 	{0x0000804c, 0xffffffff},
-	{0x00008050, 0xffffffff},
 	{0x00008054, 0x00000000},
 	{0x00008058, 0x00000000},
 	{0x0000805c, 0x000fc78f},
@@ -1117,9 +1116,9 @@ static const u32 ar9462_2p0_mac_core[][2] = {
 	{0x000081f8, 0x00000000},
 	{0x000081fc, 0x00000000},
 	{0x00008240, 0x00100000},
-	{0x00008244, 0x0010f424},
+	{0x00008244, 0x0010f400},
 	{0x00008248, 0x00000800},
-	{0x0000824c, 0x0001e848},
+	{0x0000824c, 0x0001e800},
 	{0x00008250, 0x00000000},
 	{0x00008254, 0x00000000},
 	{0x00008258, 0x00000000},
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c
index 1e85085..7bdd726 100644
--- a/drivers/net/wireless/ath/ath9k/calib.c
+++ b/drivers/net/wireless/ath/ath9k/calib.c
@@ -369,7 +369,6 @@ bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan)
 	struct ieee80211_channel *c = chan->chan;
 	struct ath9k_hw_cal_data *caldata = ah->caldata;
 
-	chan->channelFlags &= (~CHANNEL_CW_INT);
 	if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) {
 		ath_dbg(common, CALIBRATE,
 			"NF did not complete in calibration window\n");
@@ -384,7 +383,6 @@ bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan)
 		ath_dbg(common, CALIBRATE,
 			"noise floor failed detected; detected %d, threshold %d\n",
 			nf, nfThresh);
-		chan->channelFlags |= CHANNEL_CW_INT;
 	}
 
 	if (!caldata) {
@@ -410,7 +408,7 @@ void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah,
 	int i, j;
 
 	ah->caldata->channel = chan->channel;
-	ah->caldata->channelFlags = chan->channelFlags & ~CHANNEL_CW_INT;
+	ah->caldata->channelFlags = chan->channelFlags;
 	ah->caldata->chanmode = chan->chanmode;
 	h = ah->caldata->nfCalHist;
 	default_nf = ath9k_hw_get_default_nf(ah, chan);
diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h
index 050ca4a..6102476 100644
--- a/drivers/net/wireless/ath/ath9k/common.h
+++ b/drivers/net/wireless/ath/ath9k/common.h
@@ -40,7 +40,7 @@
 	x = ATH_LPF_RSSI((x), ATH_RSSI_IN((y)), ATH_RSSI_LPF_LEN);  	\
 } while (0)
 #define ATH_EP_RND(x, mul) 						\
-	((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul))
+	(((x) + ((mul)/2)) / (mul))
 
 int ath9k_cmn_padpos(__le16 frame_control);
 int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb);
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
index 3714b97..e6307b8 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -537,6 +537,7 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
 	PR("AMPDUs Completed:", a_completed);
 	PR("AMPDUs Retried:  ", a_retries);
 	PR("AMPDUs XRetried: ", a_xretries);
+	PR("TXERR Filtered:  ", txerr_filtered);
 	PR("FIFO Underrun:   ", fifo_underrun);
 	PR("TXOP Exceeded:   ", xtxop);
 	PR("TXTIMER Expiry:  ", timer_exp);
@@ -756,6 +757,8 @@ void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
 			TX_STAT_INC(qnum, completed);
 	}
 
+	if (ts->ts_status & ATH9K_TXERR_FILT)
+		TX_STAT_INC(qnum, txerr_filtered);
 	if (ts->ts_status & ATH9K_TXERR_FIFO)
 		TX_STAT_INC(qnum, fifo_underrun);
 	if (ts->ts_status & ATH9K_TXERR_XTXOP)
@@ -1909,6 +1912,7 @@ static const char ath9k_gstrings_stats[][ETH_GSTRING_LEN] = {
 	AMKSTR(d_tx_desc_cfg_err),
 	AMKSTR(d_tx_data_underrun),
 	AMKSTR(d_tx_delim_underrun),
+	"d_rx_crc_err",
 	"d_rx_decrypt_crc_err",
 	"d_rx_phy_err",
 	"d_rx_mic_err",
@@ -1989,6 +1993,7 @@ void ath9k_get_et_stats(struct ieee80211_hw *hw,
 	AWDATA(data_underrun);
 	AWDATA(delim_underrun);
 
+	AWDATA_RX(crc_err);
 	AWDATA_RX(decrypt_crc_err);
 	AWDATA_RX(phy_err);
 	AWDATA_RX(mic_err);
@@ -2067,7 +2072,7 @@ int ath9k_init_debug(struct ath_hw *ah)
 			    &fops_modal_eeprom);
 	sc->rfs_chan_spec_scan = relay_open("spectral_scan",
 					    sc->debug.debugfs_phy,
-					    262144, 4, &rfs_spec_scan_cb,
+					    1024, 256, &rfs_spec_scan_cb,
 					    NULL);
 	debugfs_create_file("spectral_scan_ctl", S_IRUSR | S_IWUSR,
 			    sc->debug.debugfs_phy, sc,
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h
index 410d6d8..794a7ec 100644
--- a/drivers/net/wireless/ath/ath9k/debug.h
+++ b/drivers/net/wireless/ath/ath9k/debug.h
@@ -142,6 +142,7 @@ struct ath_interrupt_stats {
  * @a_completed: Total AMPDUs completed
  * @a_retries: No. of AMPDUs retried (SW)
  * @a_xretries: No. of AMPDUs dropped due to xretries
+ * @txerr_filtered: No. of frames with TXERR_FILT flag set.
  * @fifo_underrun: FIFO underrun occurrences
 	Valid only for:
 		- non-aggregate condition.
@@ -168,6 +169,7 @@ struct ath_tx_stats {
 	u32 a_completed;
 	u32 a_retries;
 	u32 a_xretries;
+	u32 txerr_filtered;
 	u32 fifo_underrun;
 	u32 xtxop;
 	u32 timer_exp;
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 07e2526..4fa2bb1 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -1669,6 +1669,104 @@ bool ath9k_hw_check_alive(struct ath_hw *ah)
 }
 EXPORT_SYMBOL(ath9k_hw_check_alive);
 
+static void ath9k_hw_init_mfp(struct ath_hw *ah)
+{
+	/* Setup MFP options for CCMP */
+	if (AR_SREV_9280_20_OR_LATER(ah)) {
+		/* Mask Retry(b11), PwrMgt(b12), MoreData(b13) to 0 in mgmt
+		 * frames when constructing CCMP AAD. */
+		REG_RMW_FIELD(ah, AR_AES_MUTE_MASK1, AR_AES_MUTE_MASK1_FC_MGMT,
+			      0xc7ff);
+		ah->sw_mgmt_crypto = false;
+	} else if (AR_SREV_9160_10_OR_LATER(ah)) {
+		/* Disable hardware crypto for management frames */
+		REG_CLR_BIT(ah, AR_PCU_MISC_MODE2,
+			    AR_PCU_MISC_MODE2_MGMT_CRYPTO_ENABLE);
+		REG_SET_BIT(ah, AR_PCU_MISC_MODE2,
+			    AR_PCU_MISC_MODE2_NO_CRYPTO_FOR_NON_DATA_PKT);
+		ah->sw_mgmt_crypto = true;
+	} else {
+		ah->sw_mgmt_crypto = true;
+	}
+}
+
+static void ath9k_hw_reset_opmode(struct ath_hw *ah,
+				  u32 macStaId1, u32 saveDefAntenna)
+{
+	struct ath_common *common = ath9k_hw_common(ah);
+
+	ENABLE_REGWRITE_BUFFER(ah);
+
+	REG_WRITE(ah, AR_STA_ID0, get_unaligned_le32(common->macaddr));
+	REG_WRITE(ah, AR_STA_ID1, get_unaligned_le16(common->macaddr + 4)
+		  | macStaId1
+		  | AR_STA_ID1_RTS_USE_DEF
+		  | (ah->config.ack_6mb ? AR_STA_ID1_ACKCTS_6MB : 0)
+		  | ah->sta_id1_defaults);
+	ath_hw_setbssidmask(common);
+	REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna);
+	ath9k_hw_write_associd(ah);
+	REG_WRITE(ah, AR_ISR, ~0);
+	REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR);
+
+	REGWRITE_BUFFER_FLUSH(ah);
+
+	ath9k_hw_set_operating_mode(ah, ah->opmode);
+}
+
+static void ath9k_hw_init_queues(struct ath_hw *ah)
+{
+	int i;
+
+	ENABLE_REGWRITE_BUFFER(ah);
+
+	for (i = 0; i < AR_NUM_DCU; i++)
+		REG_WRITE(ah, AR_DQCUMASK(i), 1 << i);
+
+	REGWRITE_BUFFER_FLUSH(ah);
+
+	ah->intr_txqs = 0;
+	for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
+		ath9k_hw_resettxqueue(ah, i);
+}
+
+/*
+ * For big endian systems turn on swapping for descriptors
+ */
+static void ath9k_hw_init_desc(struct ath_hw *ah)
+{
+	struct ath_common *common = ath9k_hw_common(ah);
+
+	if (AR_SREV_9100(ah)) {
+		u32 mask;
+		mask = REG_READ(ah, AR_CFG);
+		if (mask & (AR_CFG_SWRB | AR_CFG_SWTB | AR_CFG_SWRG)) {
+			ath_dbg(common, RESET, "CFG Byte Swap Set 0x%x\n",
+				mask);
+		} else {
+			mask = INIT_CONFIG_STATUS | AR_CFG_SWRB | AR_CFG_SWTB;
+			REG_WRITE(ah, AR_CFG, mask);
+			ath_dbg(common, RESET, "Setting CFG 0x%x\n",
+				REG_READ(ah, AR_CFG));
+		}
+	} else {
+		if (common->bus_ops->ath_bus_type == ATH_USB) {
+			/* Configure AR9271 target WLAN */
+			if (AR_SREV_9271(ah))
+				REG_WRITE(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB);
+			else
+				REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD);
+		}
+#ifdef __BIG_ENDIAN
+		else if (AR_SREV_9330(ah) || AR_SREV_9340(ah) ||
+			 AR_SREV_9550(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);
+#endif
+	}
+}
+
 /*
  * Fast channel change:
  * (Change synthesizer based on channel freq without resetting chip)
@@ -1746,7 +1844,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
 	u32 saveDefAntenna;
 	u32 macStaId1;
 	u64 tsf = 0;
-	int i, r;
+	int r;
 	bool start_mci_reset = false;
 	bool save_fullsleep = ah->chip_fullsleep;
 
@@ -1763,10 +1861,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
 		ath9k_hw_getnf(ah, ah->curchan);
 
 	ah->caldata = caldata;
-	if (caldata &&
-	    (chan->channel != caldata->channel ||
-	     (chan->channelFlags & ~CHANNEL_CW_INT) !=
-	     (caldata->channelFlags & ~CHANNEL_CW_INT))) {
+	if (caldata && (chan->channel != caldata->channel ||
+			chan->channelFlags != caldata->channelFlags)) {
 		/* Operating channel changed, reset channel calibration data */
 		memset(caldata, 0, sizeof(*caldata));
 		ath9k_init_nfcal_hist_buffer(ah, chan);
@@ -1853,22 +1949,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
 		ath9k_hw_settsf64(ah, tsf);
 	}
 
-	/* Setup MFP options for CCMP */
-	if (AR_SREV_9280_20_OR_LATER(ah)) {
-		/* Mask Retry(b11), PwrMgt(b12), MoreData(b13) to 0 in mgmt
-		 * frames when constructing CCMP AAD. */
-		REG_RMW_FIELD(ah, AR_AES_MUTE_MASK1, AR_AES_MUTE_MASK1_FC_MGMT,
-			      0xc7ff);
-		ah->sw_mgmt_crypto = false;
-	} else if (AR_SREV_9160_10_OR_LATER(ah)) {
-		/* Disable hardware crypto for management frames */
-		REG_CLR_BIT(ah, AR_PCU_MISC_MODE2,
-			    AR_PCU_MISC_MODE2_MGMT_CRYPTO_ENABLE);
-		REG_SET_BIT(ah, AR_PCU_MISC_MODE2,
-			    AR_PCU_MISC_MODE2_NO_CRYPTO_FOR_NON_DATA_PKT);
-		ah->sw_mgmt_crypto = true;
-	} else
-		ah->sw_mgmt_crypto = true;
+	ath9k_hw_init_mfp(ah);
 
 	if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan))
 		ath9k_hw_set_delta_slope(ah, chan);
@@ -1876,24 +1957,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
 	ath9k_hw_spur_mitigate_freq(ah, chan);
 	ah->eep_ops->set_board_values(ah, chan);
 
-	ENABLE_REGWRITE_BUFFER(ah);
-
-	REG_WRITE(ah, AR_STA_ID0, get_unaligned_le32(common->macaddr));
-	REG_WRITE(ah, AR_STA_ID1, get_unaligned_le16(common->macaddr + 4)
-		  | macStaId1
-		  | AR_STA_ID1_RTS_USE_DEF
-		  | (ah->config.
-		     ack_6mb ? AR_STA_ID1_ACKCTS_6MB : 0)
-		  | ah->sta_id1_defaults);
-	ath_hw_setbssidmask(common);
-	REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna);
-	ath9k_hw_write_associd(ah);
-	REG_WRITE(ah, AR_ISR, ~0);
-	REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR);
-
-	REGWRITE_BUFFER_FLUSH(ah);
-
-	ath9k_hw_set_operating_mode(ah, ah->opmode);
+	ath9k_hw_reset_opmode(ah, macStaId1, saveDefAntenna);
 
 	r = ath9k_hw_rf_set_freq(ah, chan);
 	if (r)
@@ -1901,17 +1965,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
 
 	ath9k_hw_set_clockrate(ah);
 
-	ENABLE_REGWRITE_BUFFER(ah);
-
-	for (i = 0; i < AR_NUM_DCU; i++)
-		REG_WRITE(ah, AR_DQCUMASK(i), 1 << i);
-
-	REGWRITE_BUFFER_FLUSH(ah);
-
-	ah->intr_txqs = 0;
-	for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
-		ath9k_hw_resettxqueue(ah, i);
-
+	ath9k_hw_init_queues(ah);
 	ath9k_hw_init_interrupt_masks(ah, ah->opmode);
 	ath9k_hw_ani_cache_ini_regs(ah);
 	ath9k_hw_init_qos(ah);
@@ -1966,38 +2020,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
 
 	REGWRITE_BUFFER_FLUSH(ah);
 
-	/*
-	 * For big endian systems turn on swapping for descriptors
-	 */
-	if (AR_SREV_9100(ah)) {
-		u32 mask;
-		mask = REG_READ(ah, AR_CFG);
-		if (mask & (AR_CFG_SWRB | AR_CFG_SWTB | AR_CFG_SWRG)) {
-			ath_dbg(common, RESET, "CFG Byte Swap Set 0x%x\n",
-				mask);
-		} else {
-			mask =
-				INIT_CONFIG_STATUS | AR_CFG_SWRB | AR_CFG_SWTB;
-			REG_WRITE(ah, AR_CFG, mask);
-			ath_dbg(common, RESET, "Setting CFG 0x%x\n",
-				REG_READ(ah, AR_CFG));
-		}
-	} else {
-		if (common->bus_ops->ath_bus_type == ATH_USB) {
-			/* Configure AR9271 target WLAN */
-			if (AR_SREV_9271(ah))
-				REG_WRITE(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB);
-			else
-				REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD);
-		}
-#ifdef __BIG_ENDIAN
-		else if (AR_SREV_9330(ah) || AR_SREV_9340(ah) ||
-			 AR_SREV_9550(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);
-#endif
-	}
+	ath9k_hw_init_desc(ah);
 
 	if (ath9k_hw_btcoex_is_enabled(ah))
 		ath9k_hw_btcoex_enable(ah);
@@ -2010,7 +2033,6 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
 
 	if (AR_SREV_9300_20_OR_LATER(ah)) {
 		ar9003_hw_bb_watchdog_config(ah);
-
 		ar9003_hw_disable_phy_restart(ah);
 	}
 
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index 784e81c..30e62d9 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -363,7 +363,6 @@ enum ath9k_int {
 	ATH9K_INT_NOCARD = 0xffffffff
 };
 
-#define CHANNEL_CW_INT    0x00002
 #define CHANNEL_CCK       0x00020
 #define CHANNEL_OFDM      0x00040
 #define CHANNEL_2GHZ      0x00080
diff --git a/drivers/net/wireless/ath/ath9k/link.c b/drivers/net/wireless/ath/ath9k/link.c
index 39c84ec..7fdac6c 100644
--- a/drivers/net/wireless/ath/ath9k/link.c
+++ b/drivers/net/wireless/ath/ath9k/link.c
@@ -170,7 +170,8 @@ void ath_rx_poll(unsigned long data)
 {
 	struct ath_softc *sc = (struct ath_softc *)data;
 
-	ieee80211_queue_work(sc->hw, &sc->hw_check_work);
+	if (!test_bit(SC_OP_INVALID, &sc->sc_flags))
+		ieee80211_queue_work(sc->hw, &sc->hw_check_work);
 }
 
 /*
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 6e66f9c..83608be 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -280,6 +280,10 @@ static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan)
 	if (r) {
 		ath_err(common,
 			"Unable to reset channel, reset status %d\n", r);
+
+		ath9k_hw_enable_interrupts(ah);
+		ath9k_queue_reset(sc, RESET_TYPE_BB_HANG);
+
 		goto out;
 	}
 
@@ -1745,7 +1749,7 @@ static void ath9k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class)
 	mutex_unlock(&sc->mutex);
 }
 
-static void ath9k_flush(struct ieee80211_hw *hw, bool drop)
+static void ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
 {
 	struct ath_softc *sc = hw->priv;
 	struct ath_hw *ah = sc->sc_ah;
diff --git a/drivers/net/wireless/ath/carl9170/carl9170.h b/drivers/net/wireless/ath/carl9170/carl9170.h
index 2559974..9dce106 100644
--- a/drivers/net/wireless/ath/carl9170/carl9170.h
+++ b/drivers/net/wireless/ath/carl9170/carl9170.h
@@ -70,12 +70,6 @@
 
 static const u8 ar9170_qmap[__AR9170_NUM_TXQ] = { 3, 2, 1, 0 };
 
-enum carl9170_rf_init_mode {
-	CARL9170_RFI_NONE,
-	CARL9170_RFI_WARM,
-	CARL9170_RFI_COLD,
-};
-
 #define CARL9170_MAX_RX_BUFFER_SIZE		8192
 
 enum carl9170_device_state {
@@ -599,7 +593,7 @@ int carl9170_led_set_state(struct ar9170 *ar, const u32 led_state);
 
 /* PHY / RF */
 int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
-	enum nl80211_channel_type bw, enum carl9170_rf_init_mode rfi);
+			 enum nl80211_channel_type bw);
 int carl9170_get_noisefloor(struct ar9170 *ar);
 
 /* FW */
diff --git a/drivers/net/wireless/ath/carl9170/debug.c b/drivers/net/wireless/ath/carl9170/debug.c
index 93fe600..40109be 100644
--- a/drivers/net/wireless/ath/carl9170/debug.c
+++ b/drivers/net/wireless/ath/carl9170/debug.c
@@ -655,7 +655,7 @@ static ssize_t carl9170_debugfs_bug_write(struct ar9170 *ar, const char *buf,
 
 	case 'P':
 		err = carl9170_set_channel(ar, ar->hw->conf.channel,
-			ar->hw->conf.channel_type, CARL9170_RFI_COLD);
+					   ar->hw->conf.channel_type);
 		if (err < 0)
 			count = err;
 
diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c
index f293b3f..699c557 100644
--- a/drivers/net/wireless/ath/carl9170/main.c
+++ b/drivers/net/wireless/ath/carl9170/main.c
@@ -939,7 +939,7 @@ static int carl9170_op_config(struct ieee80211_hw *hw, u32 changed)
 			goto out;
 
 		err = carl9170_set_channel(ar, hw->conf.channel,
-			hw->conf.channel_type, CARL9170_RFI_NONE);
+					   hw->conf.channel_type);
 		if (err)
 			goto out;
 
@@ -1703,7 +1703,7 @@ found:
 	return 0;
 }
 
-static void carl9170_op_flush(struct ieee80211_hw *hw, bool drop)
+static void carl9170_op_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
 {
 	struct ar9170 *ar = hw->priv;
 	unsigned int vid;
diff --git a/drivers/net/wireless/ath/carl9170/phy.c b/drivers/net/wireless/ath/carl9170/phy.c
index b72c09c..07f8223 100644
--- a/drivers/net/wireless/ath/carl9170/phy.c
+++ b/drivers/net/wireless/ath/carl9170/phy.c
@@ -1569,16 +1569,14 @@ static enum carl9170_bw nl80211_to_carl(enum nl80211_channel_type type)
 }
 
 int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
-			 enum nl80211_channel_type _bw,
-			 enum carl9170_rf_init_mode rfi)
+			 enum nl80211_channel_type _bw)
 {
 	const struct carl9170_phy_freq_params *freqpar;
 	struct carl9170_rf_init_result rf_res;
 	struct carl9170_rf_init rf;
-	u32 cmd, tmp, offs = 0, new_ht = 0;
+	u32 tmp, offs = 0, new_ht = 0;
 	int err;
 	enum carl9170_bw bw;
-	bool warm_reset;
 	struct ieee80211_channel *old_channel = NULL;
 
 	bw = nl80211_to_carl(_bw);
@@ -1592,51 +1590,27 @@ int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
 	/* may be NULL at first setup */
 	if (ar->channel) {
 		old_channel = ar->channel;
-		warm_reset = (old_channel->band != channel->band) ||
-			     (old_channel->center_freq ==
-			      channel->center_freq) ||
-			     (ar->ht_settings != new_ht);
-
 		ar->channel = NULL;
-	} else {
-		warm_reset = true;
 	}
 
-	/* HW workaround */
-	if (!ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] &&
-	    channel->center_freq <= 2417)
-		warm_reset = true;
-
-	if (rfi != CARL9170_RFI_NONE || warm_reset) {
-		u32 val;
-
-		if (rfi == CARL9170_RFI_COLD)
-			val = AR9170_PWR_RESET_BB_COLD_RESET;
-		else
-			val = AR9170_PWR_RESET_BB_WARM_RESET;
-
-		/* warm/cold reset BB/ADDA */
-		err = carl9170_write_reg(ar, AR9170_PWR_REG_RESET, val);
-		if (err)
-			return err;
-
-		err = carl9170_write_reg(ar, AR9170_PWR_REG_RESET, 0x0);
-		if (err)
-			return err;
+	/* cold reset BB/ADDA */
+	err = carl9170_write_reg(ar, AR9170_PWR_REG_RESET,
+				 AR9170_PWR_RESET_BB_COLD_RESET);
+	if (err)
+		return err;
 
-		err = carl9170_init_phy(ar, channel->band);
-		if (err)
-			return err;
+	err = carl9170_write_reg(ar, AR9170_PWR_REG_RESET, 0x0);
+	if (err)
+		return err;
 
-		err = carl9170_init_rf_banks_0_7(ar,
-			channel->band == IEEE80211_BAND_5GHZ);
-		if (err)
-			return err;
+	err = carl9170_init_phy(ar, channel->band);
+	if (err)
+		return err;
 
-		cmd = CARL9170_CMD_RF_INIT;
-	} else {
-		cmd = CARL9170_CMD_FREQUENCY;
-	}
+	err = carl9170_init_rf_banks_0_7(ar,
+					 channel->band == IEEE80211_BAND_5GHZ);
+	if (err)
+		return err;
 
 	err = carl9170_exec_cmd(ar, CARL9170_CMD_FREQ_START, 0, NULL, 0, NULL);
 	if (err)
@@ -1648,8 +1622,8 @@ int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
 		return err;
 
 	err = carl9170_init_rf_bank4_pwr(ar,
-		channel->band == IEEE80211_BAND_5GHZ,
-		channel->center_freq, bw);
+					 channel->band == IEEE80211_BAND_5GHZ,
+					 channel->center_freq, bw);
 	if (err)
 		return err;
 
@@ -1703,13 +1677,8 @@ int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
 	rf.delta_slope_coeff_man = cpu_to_le32(freqpar->coeff_man);
 	rf.delta_slope_coeff_exp_shgi = cpu_to_le32(freqpar->coeff_exp_shgi);
 	rf.delta_slope_coeff_man_shgi = cpu_to_le32(freqpar->coeff_man_shgi);
-
-	if (rfi != CARL9170_RFI_NONE)
-		rf.finiteLoopCount = cpu_to_le32(2000);
-	else
-		rf.finiteLoopCount = cpu_to_le32(1000);
-
-	err = carl9170_exec_cmd(ar, cmd, sizeof(rf), &rf,
+	rf.finiteLoopCount = cpu_to_le32(2000);
+	err = carl9170_exec_cmd(ar, CARL9170_CMD_RF_INIT, sizeof(rf), &rf,
 				sizeof(rf_res), &rf_res);
 	if (err)
 		return err;
@@ -1724,9 +1693,8 @@ int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
 			  old_channel->center_freq : -1, channel->center_freq,
 			  err);
 
-		if ((rfi == CARL9170_RFI_COLD) || (ar->chan_fail > 3)) {
-			/*
-			 * We have tried very hard to change to _another_
+		if (ar->chan_fail > 3) {
+			/* We have tried very hard to change to _another_
 			 * channel and we've failed to do so!
 			 * Chances are that the PHY/RF is no longer
 			 * operable (due to corruptions/fatal events/bugs?)
@@ -1736,8 +1704,7 @@ int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
 			return 0;
 		}
 
-		err = carl9170_set_channel(ar, channel, _bw,
-					   CARL9170_RFI_COLD);
+		err = carl9170_set_channel(ar, channel, _bw);
 		if (err)
 			return err;
 	} else {
diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c
index 9c0b150..c61cafa 100644
--- a/drivers/net/wireless/ath/carl9170/tx.c
+++ b/drivers/net/wireless/ath/carl9170/tx.c
@@ -387,8 +387,7 @@ static void carl9170_tx_status_process_ampdu(struct ar9170 *ar,
 	u8 tid;
 
 	if (!(txinfo->flags & IEEE80211_TX_CTL_AMPDU) ||
-	    txinfo->flags & IEEE80211_TX_CTL_INJECTED ||
-	   (!(super->f.mac_control & cpu_to_le16(AR9170_TX_MAC_AGGR))))
+	    txinfo->flags & IEEE80211_TX_CTL_INJECTED)
 		return;
 
 	rcu_read_lock();
@@ -981,30 +980,6 @@ static int carl9170_tx_prepare(struct ar9170 *ar,
 
 		SET_VAL(CARL9170_TX_SUPER_AMPDU_FACTOR,
 			txc->s.ampdu_settings, factor);
-
-		for (i = 0; i < CARL9170_TX_MAX_RATES; i++) {
-			txrate = &info->control.rates[i];
-			if (txrate->idx >= 0) {
-				txc->s.ri[i] =
-					CARL9170_TX_SUPER_RI_AMPDU;
-
-				if (WARN_ON(!(txrate->flags &
-					      IEEE80211_TX_RC_MCS))) {
-					/*
-					 * Not sure if it's even possible
-					 * to aggregate non-ht rates with
-					 * this HW.
-					 */
-					goto err_out;
-				}
-				continue;
-			}
-
-			txrate->idx = 0;
-			txrate->count = ar->hw->max_rate_tries;
-		}
-
-		mac_tmp |= cpu_to_le16(AR9170_TX_MAC_AGGR);
 	}
 
 	/*
@@ -1012,11 +987,31 @@ static int carl9170_tx_prepare(struct ar9170 *ar,
 	 * taken from mac_control. For all fallback rate, the firmware
 	 * updates the mac_control flags from the rate info field.
 	 */
-	for (i = 1; i < CARL9170_TX_MAX_RATES; i++) {
+	for (i = 0; i < CARL9170_TX_MAX_RATES; i++) {
+		__le32 phy_set;
 		txrate = &info->control.rates[i];
 		if (txrate->idx < 0)
 			break;
 
+		phy_set = carl9170_tx_physet(ar, info, txrate);
+		if (i == 0) {
+			/* first rate - part of the hw's frame header */
+			txc->f.phy_control = phy_set;
+
+			if (ampdu && txrate->flags & IEEE80211_TX_RC_MCS)
+				mac_tmp |= cpu_to_le16(AR9170_TX_MAC_AGGR);
+			if (carl9170_tx_rts_check(ar, txrate, ampdu, no_ack))
+				mac_tmp |= cpu_to_le16(AR9170_TX_MAC_PROT_RTS);
+			else if (carl9170_tx_cts_check(ar, txrate))
+				mac_tmp |= cpu_to_le16(AR9170_TX_MAC_PROT_CTS);
+
+		} else {
+			/* fallback rates are stored in the firmware's
+			 * retry rate set array.
+			 */
+			txc->s.rr[i - 1] = phy_set;
+		}
+
 		SET_VAL(CARL9170_TX_SUPER_RI_TRIES, txc->s.ri[i],
 			txrate->count);
 
@@ -1027,21 +1022,13 @@ static int carl9170_tx_prepare(struct ar9170 *ar,
 			txc->s.ri[i] |= (AR9170_TX_MAC_PROT_CTS <<
 				CARL9170_TX_SUPER_RI_ERP_PROT_S);
 
-		txc->s.rr[i - 1] = carl9170_tx_physet(ar, info, txrate);
+		if (ampdu && (txrate->flags & IEEE80211_TX_RC_MCS))
+			txc->s.ri[i] |= CARL9170_TX_SUPER_RI_AMPDU;
 	}
 
-	txrate = &info->control.rates[0];
-	SET_VAL(CARL9170_TX_SUPER_RI_TRIES, txc->s.ri[0], txrate->count);
-
-	if (carl9170_tx_rts_check(ar, txrate, ampdu, no_ack))
-		mac_tmp |= cpu_to_le16(AR9170_TX_MAC_PROT_RTS);
-	else if (carl9170_tx_cts_check(ar, txrate))
-		mac_tmp |= cpu_to_le16(AR9170_TX_MAC_PROT_CTS);
-
 	txc->s.len = cpu_to_le16(skb->len);
 	txc->f.length = cpu_to_le16(len + FCS_LEN);
 	txc->f.mac_control = mac_tmp;
-	txc->f.phy_control = carl9170_tx_physet(ar, info, txrate);
 
 	arinfo = (void *)info->rate_driver_data;
 	arinfo->timeout = jiffies;
@@ -1381,9 +1368,9 @@ static void carl9170_tx(struct ar9170 *ar)
 }
 
 static bool carl9170_tx_ampdu_queue(struct ar9170 *ar,
-	struct ieee80211_sta *sta, struct sk_buff *skb)
+	struct ieee80211_sta *sta, struct sk_buff *skb,
+	struct ieee80211_tx_info *txinfo)
 {
-	struct _carl9170_tx_superframe *super = (void *) skb->data;
 	struct carl9170_sta_info *sta_info;
 	struct carl9170_sta_tid *agg;
 	struct sk_buff *iter;
@@ -1450,7 +1437,7 @@ err_unlock:
 
 err_unlock_rcu:
 	rcu_read_unlock();
-	super->f.mac_control &= ~cpu_to_le16(AR9170_TX_MAC_AGGR);
+	txinfo->flags &= ~IEEE80211_TX_CTL_AMPDU;
 	carl9170_tx_status(ar, skb, false);
 	ar->tx_dropped++;
 	return false;
@@ -1492,7 +1479,7 @@ void carl9170_op_tx(struct ieee80211_hw *hw,
 		 * sta == NULL checks are redundant in this
 		 * special case.
 		 */
-		run = carl9170_tx_ampdu_queue(ar, sta, skb);
+		run = carl9170_tx_ampdu_queue(ar, sta, skb, info);
 		if (run)
 			carl9170_tx_ampdu(ar);
 
diff --git a/drivers/net/wireless/ath/wil6210/Makefile b/drivers/net/wireless/ath/wil6210/Makefile
index 9396dc9..d288eea 100644
--- a/drivers/net/wireless/ath/wil6210/Makefile
+++ b/drivers/net/wireless/ath/wil6210/Makefile
@@ -9,5 +9,7 @@ wil6210-objs += wmi.o
 wil6210-objs += interrupt.o
 wil6210-objs += txrx.o
 
-subdir-ccflags-y += -Werror
+ifeq (, $(findstring -W,$(EXTRA_CFLAGS)))
+	subdir-ccflags-y += -Werror
+endif
 subdir-ccflags-y += -D__CHECK_ENDIAN__
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c
index 9ecc196..c5d4a87 100644
--- a/drivers/net/wireless/ath/wil6210/cfg80211.c
+++ b/drivers/net/wireless/ath/wil6210/cfg80211.c
@@ -14,16 +14,6 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <linux/kernel.h>
-#include <linux/netdevice.h>
-#include <linux/sched.h>
-#include <linux/etherdevice.h>
-#include <linux/wireless.h>
-#include <linux/ieee80211.h>
-#include <linux/slab.h>
-#include <linux/version.h>
-#include <net/cfg80211.h>
-
 #include "wil6210.h"
 #include "wmi.h"
 
@@ -292,7 +282,7 @@ static int wil_cfg80211_connect(struct wiphy *wiphy,
 
 	/* WMI_CONNECT_CMD */
 	memset(&conn, 0, sizeof(conn));
-	switch (bss->capability & 0x03) {
+	switch (bss->capability & WLAN_CAPABILITY_DMG_TYPE_MASK) {
 	case WLAN_CAPABILITY_DMG_TYPE_AP:
 		conn.network_type = WMI_NETTYPE_INFRA;
 		break;
@@ -437,17 +427,18 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy,
 	if (rc)
 		return rc;
 
-	rc = wmi_set_channel(wil, channel->hw_value);
-	if (rc)
-		return rc;
-
 	/* MAC address - pre-requisite for other commands */
 	wmi_set_mac_address(wil, ndev->dev_addr);
 
 	/* IE's */
 	/* bcon 'head IE's are not relevant for 60g band */
-	wmi_set_ie(wil, WMI_FRAME_BEACON, bcon->beacon_ies_len,
-		   bcon->beacon_ies);
+	/*
+	 * FW do not form regular beacon, so bcon IE's are not set
+	 * For the DMG bcon, when it will be supported, bcon IE's will
+	 * be reused; add something like:
+	 * wmi_set_ie(wil, WMI_FRAME_BEACON, bcon->beacon_ies_len,
+	 * bcon->beacon_ies);
+	 */
 	wmi_set_ie(wil, WMI_FRAME_PROBE_RESP, bcon->proberesp_ies_len,
 		   bcon->proberesp_ies);
 	wmi_set_ie(wil, WMI_FRAME_ASSOC_RESP, bcon->assocresp_ies_len,
@@ -455,7 +446,8 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy,
 
 	wil->secure_pcp = info->privacy;
 
-	rc = wmi_set_bcon(wil, info->beacon_interval, wmi_nettype);
+	rc = wmi_pcp_start(wil, info->beacon_interval, wmi_nettype,
+			   channel->hw_value);
 	if (rc)
 		return rc;
 
@@ -472,11 +464,8 @@ static int wil_cfg80211_stop_ap(struct wiphy *wiphy,
 {
 	int rc = 0;
 	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
-	struct wireless_dev *wdev = ndev->ieee80211_ptr;
-	u8 wmi_nettype = wil_iftype_nl2wmi(wdev->iftype);
 
-	/* To stop beaconing, set BI to 0 */
-	rc = wmi_set_bcon(wil, 0, wmi_nettype);
+	rc = wmi_pcp_stop(wil);
 
 	return rc;
 }
diff --git a/drivers/net/wireless/ath/wil6210/dbg_hexdump.h b/drivers/net/wireless/ath/wil6210/dbg_hexdump.h
deleted file mode 100644
index e5712f0..0000000
--- a/drivers/net/wireless/ath/wil6210/dbg_hexdump.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef WIL_DBG_HEXDUMP_H_
-#define WIL_DBG_HEXDUMP_H_
-
-#include <linux/printk.h>
-#include <linux/dynamic_debug.h>
-
-#if defined(CONFIG_DYNAMIC_DEBUG)
-#define wil_print_hex_dump_debug(prefix_str, prefix_type, rowsize,	\
-				 groupsize, buf, len, ascii)		\
-	dynamic_hex_dump(prefix_str, prefix_type, rowsize,		\
-			     groupsize, buf, len, ascii)
-
-#else /* defined(CONFIG_DYNAMIC_DEBUG) */
-#define wil_print_hex_dump_debug(prefix_str, prefix_type, rowsize,	\
-				 groupsize, buf, len, ascii)		\
-	print_hex_dump(KERN_DEBUG, prefix_str, prefix_type, rowsize,	\
-		       groupsize, buf, len, ascii)
-#endif /* defined(CONFIG_DYNAMIC_DEBUG) */
-
-#endif /* WIL_DBG_HEXDUMP_H_ */
diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c
index 65fc968..727b1f5 100644
--- a/drivers/net/wireless/ath/wil6210/debugfs.c
+++ b/drivers/net/wireless/ath/wil6210/debugfs.c
@@ -216,7 +216,7 @@ DEFINE_SIMPLE_ATTRIBUTE(fops_iomem_x32, wil_debugfs_iomem_x32_get,
 			wil_debugfs_iomem_x32_set, "0x%08llx\n");
 
 static struct dentry *wil_debugfs_create_iomem_x32(const char *name,
-						   mode_t mode,
+						   umode_t mode,
 						   struct dentry *parent,
 						   void __iomem *value)
 {
@@ -312,14 +312,6 @@ static const struct file_operations fops_memread = {
 	.llseek		= seq_lseek,
 };
 
-static int wil_default_open(struct inode *inode, struct file *file)
-{
-	if (inode->i_private)
-		file->private_data = inode->i_private;
-
-	return 0;
-}
-
 static ssize_t wil_read_file_ioblob(struct file *file, char __user *user_buf,
 				size_t count, loff_t *ppos)
 {
@@ -361,13 +353,13 @@ static ssize_t wil_read_file_ioblob(struct file *file, char __user *user_buf,
 
 static const struct file_operations fops_ioblob = {
 	.read =		wil_read_file_ioblob,
-	.open =		wil_default_open,
+	.open =		simple_open,
 	.llseek =	default_llseek,
 };
 
 static
 struct dentry *wil_debugfs_create_ioblob(const char *name,
-					 mode_t mode,
+					 umode_t mode,
 					 struct dentry *parent,
 					 struct debugfs_blob_wrapper *blob)
 {
@@ -396,7 +388,7 @@ static ssize_t wil_write_file_reset(struct file *file, const char __user *buf,
 
 static const struct file_operations fops_reset = {
 	.write = wil_write_file_reset,
-	.open  = wil_default_open,
+	.open  = simple_open,
 };
 /*---------Tx descriptor------------*/
 
@@ -526,7 +518,50 @@ static ssize_t wil_write_file_ssid(struct file *file, const char __user *buf,
 static const struct file_operations fops_ssid = {
 	.read = wil_read_file_ssid,
 	.write = wil_write_file_ssid,
-	.open  = wil_default_open,
+	.open  = simple_open,
+};
+
+/*---------temp------------*/
+static void print_temp(struct seq_file *s, const char *prefix, u32 t)
+{
+	switch (t) {
+	case 0:
+	case ~(u32)0:
+		seq_printf(s, "%s N/A\n", prefix);
+	break;
+	default:
+		seq_printf(s, "%s %d.%03d\n", prefix, t / 1000, t % 1000);
+		break;
+	}
+}
+
+static int wil_temp_debugfs_show(struct seq_file *s, void *data)
+{
+	struct wil6210_priv *wil = s->private;
+	u32 t_m, t_r;
+
+	int rc = wmi_get_temperature(wil, &t_m, &t_r);
+	if (rc) {
+		seq_printf(s, "Failed\n");
+		return 0;
+	}
+
+	print_temp(s, "MAC temperature   :", t_m);
+	print_temp(s, "Radio temperature :", t_r);
+
+	return 0;
+}
+
+static int wil_temp_seq_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, wil_temp_debugfs_show, inode->i_private);
+}
+
+static const struct file_operations fops_temp = {
+	.open		= wil_temp_seq_open,
+	.release	= single_release,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
 };
 
 /*----------------*/
@@ -563,6 +598,7 @@ int wil6210_debugfs_init(struct wil6210_priv *wil)
 	debugfs_create_file("mem_val", S_IRUGO, dbg, wil, &fops_memread);
 
 	debugfs_create_file("reset", S_IWUSR, dbg, wil, &fops_reset);
+	debugfs_create_file("temp", S_IRUGO, dbg, wil, &fops_temp);
 
 	wil->rgf_blob.data = (void * __force)wil->csr + 0;
 	wil->rgf_blob.size = 0xa000;
diff --git a/drivers/net/wireless/ath/wil6210/interrupt.c b/drivers/net/wireless/ath/wil6210/interrupt.c
index dc97e7b..e3c1e76 100644
--- a/drivers/net/wireless/ath/wil6210/interrupt.c
+++ b/drivers/net/wireless/ath/wil6210/interrupt.c
@@ -240,6 +240,15 @@ static void wil_notify_fw_error(struct wil6210_priv *wil)
 	kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
 }
 
+static void wil_cache_mbox_regs(struct wil6210_priv *wil)
+{
+	/* make shadow copy of registers that should not change on run time */
+	wil_memcpy_fromio_32(&wil->mbox_ctl, wil->csr + HOST_MBOX,
+			     sizeof(struct wil6210_mbox_ctl));
+	wil_mbox_ring_le2cpus(&wil->mbox_ctl.rx);
+	wil_mbox_ring_le2cpus(&wil->mbox_ctl.tx);
+}
+
 static irqreturn_t wil6210_irq_misc(int irq, void *cookie)
 {
 	struct wil6210_priv *wil = cookie;
@@ -257,14 +266,19 @@ static irqreturn_t wil6210_irq_misc(int irq, void *cookie)
 	wil6210_mask_irq_misc(wil);
 
 	if (isr & ISR_MISC_FW_ERROR) {
-		wil_dbg_irq(wil, "IRQ: Firmware error\n");
+		wil_err(wil, "Firmware error detected\n");
 		clear_bit(wil_status_fwready, &wil->status);
-		wil_notify_fw_error(wil);
-		isr &= ~ISR_MISC_FW_ERROR;
+		/*
+		 * do not clear @isr here - we do 2-nd part in thread
+		 * there, user space get notified, and it should be done
+		 * in non-atomic context
+		 */
 	}
 
 	if (isr & ISR_MISC_FW_READY) {
 		wil_dbg_irq(wil, "IRQ: FW ready\n");
+		wil_cache_mbox_regs(wil);
+		set_bit(wil_status_reset_done, &wil->status);
 		/**
 		 * Actual FW ready indicated by the
 		 * WMI_FW_READY_EVENTID
@@ -289,6 +303,11 @@ static irqreturn_t wil6210_irq_misc_thread(int irq, void *cookie)
 
 	wil_dbg_irq(wil, "Thread ISR MISC 0x%08x\n", isr);
 
+	if (isr & ISR_MISC_FW_ERROR) {
+		wil_notify_fw_error(wil);
+		isr &= ~ISR_MISC_FW_ERROR;
+	}
+
 	if (isr & ISR_MISC_MBOX_EVT) {
 		wil_dbg_irq(wil, "MBOX event\n");
 		wmi_recv_cmd(wil);
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c
index 761c389..a0478e2 100644
--- a/drivers/net/wireless/ath/wil6210/main.c
+++ b/drivers/net/wireless/ath/wil6210/main.c
@@ -14,12 +14,6 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <linux/kernel.h>
-#include <linux/netdevice.h>
-#include <linux/sched.h>
-#include <linux/ieee80211.h>
-#include <linux/wireless.h>
-#include <linux/slab.h>
 #include <linux/moduleparam.h>
 #include <linux/if_arp.h>
 
@@ -109,13 +103,24 @@ static void wil_connect_timer_fn(ulong x)
 	schedule_work(&wil->disconnect_worker);
 }
 
-static void wil_cache_mbox_regs(struct wil6210_priv *wil)
+static void wil_connect_worker(struct work_struct *work)
 {
-	/* make shadow copy of registers that should not change on run time */
-	wil_memcpy_fromio_32(&wil->mbox_ctl, wil->csr + HOST_MBOX,
-			     sizeof(struct wil6210_mbox_ctl));
-	wil_mbox_ring_le2cpus(&wil->mbox_ctl.rx);
-	wil_mbox_ring_le2cpus(&wil->mbox_ctl.tx);
+	int rc;
+	struct wil6210_priv *wil = container_of(work, struct wil6210_priv,
+						connect_worker);
+	int cid = wil->pending_connect_cid;
+
+	if (cid < 0) {
+		wil_err(wil, "No connection pending\n");
+		return;
+	}
+
+	wil_dbg_wmi(wil, "Configure for connection CID %d\n", cid);
+
+	rc = wil_vring_init_tx(wil, 0, WIL6210_TX_RING_SIZE, cid, 0);
+	wil->pending_connect_cid = -1;
+	if (rc == 0)
+		wil_link_on(wil);
 }
 
 int wil_priv_init(struct wil6210_priv *wil)
@@ -130,7 +135,7 @@ int wil_priv_init(struct wil6210_priv *wil)
 	wil->pending_connect_cid = -1;
 	setup_timer(&wil->connect_timer, wil_connect_timer_fn, (ulong)wil);
 
-	INIT_WORK(&wil->wmi_connect_worker, wmi_connect_worker);
+	INIT_WORK(&wil->connect_worker, wil_connect_worker);
 	INIT_WORK(&wil->disconnect_worker, wil_disconnect_worker);
 	INIT_WORK(&wil->wmi_event_worker, wmi_event_worker);
 
@@ -147,8 +152,6 @@ int wil_priv_init(struct wil6210_priv *wil)
 		return -EAGAIN;
 	}
 
-	wil_cache_mbox_regs(wil);
-
 	return 0;
 }
 
@@ -185,15 +188,11 @@ static void wil_target_reset(struct wil6210_priv *wil)
 	W(RGF_USER_MAC_CPU_0,  BIT(1)); /* mac_cpu_man_rst */
 	W(RGF_USER_USER_CPU_0, BIT(1)); /* user_cpu_man_rst */
 
-	msleep(100);
-
 	W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0xFE000000);
 	W(RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0x0000003F);
 	W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000170);
 	W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0xFFE7FC00);
 
-	msleep(100);
-
 	W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0);
 	W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0);
 	W(RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0);
@@ -203,12 +202,6 @@ static void wil_target_reset(struct wil6210_priv *wil)
 	W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00000080);
 	W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0);
 
-	msleep(2000);
-
-	W(RGF_USER_USER_CPU_0, BIT(0)); /* user_cpu_man_de_rst */
-
-	msleep(2000);
-
 	wil_dbg_misc(wil, "Reset completed\n");
 
 #undef W
@@ -265,8 +258,6 @@ int wil_reset(struct wil6210_priv *wil)
 	wil->pending_connect_cid = -1;
 	INIT_COMPLETION(wil->wmi_ready);
 
-	wil_cache_mbox_regs(wil);
-
 	/* TODO: release MAC reset */
 	wil6210_enable_irq(wil);
 
@@ -352,9 +343,9 @@ static int __wil_up(struct wil6210_priv *wil)
 			wil_err(wil, "SSID not set\n");
 			return -EINVAL;
 		}
-		wmi_set_ssid(wil, wdev->ssid_len, wdev->ssid);
-		if (channel)
-			wmi_set_channel(wil, channel->hw_value);
+		rc = wmi_set_ssid(wil, wdev->ssid_len, wdev->ssid);
+		if (rc)
+			return rc;
 		break;
 	default:
 		break;
@@ -364,9 +355,12 @@ static int __wil_up(struct wil6210_priv *wil)
 	wmi_set_mac_address(wil, ndev->dev_addr);
 
 	/* Set up beaconing if required. */
-	rc = wmi_set_bcon(wil, bi, wmi_nettype);
-	if (rc)
-		return rc;
+	if (bi > 0) {
+		rc = wmi_pcp_start(wil, bi, wmi_nettype,
+				   (channel ? channel->hw_value : 0));
+		if (rc)
+			return rc;
+	}
 
 	/* Rx VRING. After MAC and beacon */
 	wil_rx_init(wil);
diff --git a/drivers/net/wireless/ath/wil6210/netdev.c b/drivers/net/wireless/ath/wil6210/netdev.c
index 8ce2e33..098a8ec 100644
--- a/drivers/net/wireless/ath/wil6210/netdev.c
+++ b/drivers/net/wireless/ath/wil6210/netdev.c
@@ -14,10 +14,7 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <linux/module.h>
-#include <linux/netdevice.h>
 #include <linux/etherdevice.h>
-#include <linux/slab.h>
 
 #include "wil6210.h"
 
diff --git a/drivers/net/wireless/ath/wil6210/pcie_bus.c b/drivers/net/wireless/ath/wil6210/pcie_bus.c
index 81c35c6..eb1dc7a 100644
--- a/drivers/net/wireless/ath/wil6210/pcie_bus.c
+++ b/drivers/net/wireless/ath/wil6210/pcie_bus.c
@@ -14,10 +14,7 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/netdevice.h>
 #include <linux/debugfs.h>
 #include <linux/pci.h>
 #include <linux/moduleparam.h>
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c
index d1315b4..79d4e327 100644
--- a/drivers/net/wireless/ath/wil6210/txrx.c
+++ b/drivers/net/wireless/ath/wil6210/txrx.c
@@ -14,10 +14,7 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <linux/kernel.h>
-#include <linux/netdevice.h>
 #include <linux/etherdevice.h>
-#include <linux/hardirq.h>
 #include <net/ieee80211_radiotap.h>
 #include <linux/if_arp.h>
 #include <linux/moduleparam.h>
@@ -83,8 +80,6 @@ static int wil_vring_alloc(struct wil6210_priv *wil, struct vring *vring)
 	 */
 	vring->va = dma_alloc_coherent(dev, sz, &vring->pa, GFP_KERNEL);
 	if (!vring->va) {
-		wil_err(wil, "vring_alloc [%d] failed to alloc DMA mem\n",
-			vring->size);
 		kfree(vring->ctx);
 		vring->ctx = NULL;
 		return -ENOMEM;
@@ -560,7 +555,7 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size,
 	if (rc)
 		goto out_free;
 
-	if (reply.cmd.status != WMI_VRING_CFG_SUCCESS) {
+	if (reply.cmd.status != WMI_FW_STATUS_SUCCESS) {
 		wil_err(wil, "Tx config failed, status 0x%02x\n",
 			reply.cmd.status);
 		rc = -EINVAL;
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h
index aea961f..8f76ecd 100644
--- a/drivers/net/wireless/ath/wil6210/wil6210.h
+++ b/drivers/net/wireless/ath/wil6210/wil6210.h
@@ -21,8 +21,6 @@
 #include <linux/wireless.h>
 #include <net/cfg80211.h>
 
-#include "dbg_hexdump.h"
-
 #define WIL_NAME "wil6210"
 
 /**
@@ -188,6 +186,7 @@ enum { /* for wil6210_priv.status */
 	wil_status_fwready = 0,
 	wil_status_fwconnected,
 	wil_status_dontscan,
+	wil_status_reset_done,
 	wil_status_irqen, /* FIXME: interrupts enabled - for debug */
 };
 
@@ -210,6 +209,8 @@ struct wil6210_priv {
 	struct wireless_dev *wdev;
 	void __iomem *csr;
 	ulong status;
+	u32 fw_version;
+	u8 n_mids; /* number of additional MIDs as reported by FW */
 	/* profile */
 	u32 monitor_flags;
 	u32 secure_pcp; /* create secure PCP? */
@@ -227,7 +228,7 @@ struct wil6210_priv {
 	struct workqueue_struct *wmi_wq; /* for deferred calls */
 	struct work_struct wmi_event_worker;
 	struct workqueue_struct *wmi_wq_conn; /* for connect worker */
-	struct work_struct wmi_connect_worker;
+	struct work_struct connect_worker;
 	struct work_struct disconnect_worker;
 	struct timer_list connect_timer;
 	int pending_connect_cid;
@@ -277,13 +278,13 @@ struct wil6210_priv {
 
 #define wil_hex_dump_txrx(prefix_str, prefix_type, rowsize,	\
 			  groupsize, buf, len, ascii)		\
-			  wil_print_hex_dump_debug("DBG[TXRX]" prefix_str,\
+			  print_hex_dump_debug("DBG[TXRX]" prefix_str,\
 					 prefix_type, rowsize,	\
 					 groupsize, buf, len, ascii)
 
 #define wil_hex_dump_wmi(prefix_str, prefix_type, rowsize,	\
 			 groupsize, buf, len, ascii)		\
-			 wil_print_hex_dump_debug("DBG[ WMI]" prefix_str,\
+			 print_hex_dump_debug("DBG[ WMI]" prefix_str,\
 					prefix_type, rowsize,	\
 					groupsize, buf, len, ascii)
 
@@ -313,7 +314,6 @@ int wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len);
 void wmi_recv_cmd(struct wil6210_priv *wil);
 int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len,
 	     u16 reply_id, void *reply, u8 reply_size, int to_msec);
-void wmi_connect_worker(struct work_struct *work);
 void wmi_event_worker(struct work_struct *work);
 void wmi_event_flush(struct wil6210_priv *wil);
 int wmi_set_ssid(struct wil6210_priv *wil, u8 ssid_len, const void *ssid);
@@ -328,6 +328,8 @@ int wmi_add_cipher_key(struct wil6210_priv *wil, u8 key_index,
 int wmi_echo(struct wil6210_priv *wil);
 int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie);
 int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring);
+int wmi_p2p_cfg(struct wil6210_priv *wil, int channel);
+int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_m, u32 *t_r);
 
 int wil6210_init_irq(struct wil6210_priv *wil, int irq);
 void wil6210_fini_irq(struct wil6210_priv *wil, int irq);
@@ -341,7 +343,8 @@ struct wireless_dev *wil_cfg80211_init(struct device *dev);
 void wil_wdev_free(struct wil6210_priv *wil);
 
 int wmi_set_mac_address(struct wil6210_priv *wil, void *addr);
-int wmi_set_bcon(struct wil6210_priv *wil, int bi, u8 wmi_nettype);
+int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, u8 chan);
+int wmi_pcp_stop(struct wil6210_priv *wil);
 void wil6210_disconnect(struct wil6210_priv *wil, void *bssid);
 
 int wil_rx_init(struct wil6210_priv *wil);
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c
index 0bb3b76..45b04e3 100644
--- a/drivers/net/wireless/ath/wil6210/wmi.c
+++ b/drivers/net/wireless/ath/wil6210/wmi.c
@@ -14,9 +14,6 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <linux/pci.h>
-#include <linux/io.h>
-#include <linux/list.h>
 #include <linux/etherdevice.h>
 #include <linux/if_arp.h>
 
@@ -272,16 +269,18 @@ static void wmi_evt_ready(struct wil6210_priv *wil, int id, void *d, int len)
 	struct net_device *ndev = wil_to_ndev(wil);
 	struct wireless_dev *wdev = wil->wdev;
 	struct wmi_ready_event *evt = d;
-	u32 ver = le32_to_cpu(evt->sw_version);
+	wil->fw_version = le32_to_cpu(evt->sw_version);
+	wil->n_mids = evt->numof_additional_mids;
 
-	wil_dbg_wmi(wil, "FW ver. %d; MAC %pM\n", ver, evt->mac);
+	wil_dbg_wmi(wil, "FW ver. %d; MAC %pM; %d MID's\n", wil->fw_version,
+		    evt->mac, wil->n_mids);
 
 	if (!is_valid_ether_addr(ndev->dev_addr)) {
 		memcpy(ndev->dev_addr, evt->mac, ETH_ALEN);
 		memcpy(ndev->perm_addr, evt->mac, ETH_ALEN);
 	}
 	snprintf(wdev->wiphy->fw_version, sizeof(wdev->wiphy->fw_version),
-		 "%d", ver);
+		 "%d", wil->fw_version);
 }
 
 static void wmi_evt_fw_ready(struct wil6210_priv *wil, int id, void *d,
@@ -324,17 +323,9 @@ static void wmi_evt_rx_mgmt(struct wil6210_priv *wil, int id, void *d, int len)
 
 	if (ieee80211_is_beacon(fc) || ieee80211_is_probe_resp(fc)) {
 		struct cfg80211_bss *bss;
-		u64 tsf = le64_to_cpu(rx_mgmt_frame->u.beacon.timestamp);
-		u16 cap = le16_to_cpu(rx_mgmt_frame->u.beacon.capab_info);
-		u16 bi = le16_to_cpu(rx_mgmt_frame->u.beacon.beacon_int);
-		const u8 *ie_buf = rx_mgmt_frame->u.beacon.variable;
-		size_t ie_len = d_len - offsetof(struct ieee80211_mgmt,
-						 u.beacon.variable);
-		wil_dbg_wmi(wil, "Capability info : 0x%04x\n", cap);
-
-		bss = cfg80211_inform_bss(wiphy, channel, rx_mgmt_frame->bssid,
-					  tsf, cap, bi, ie_buf, ie_len,
-					  signal, GFP_KERNEL);
+
+		bss = cfg80211_inform_bss_frame(wiphy, channel, rx_mgmt_frame,
+						d_len, signal, GFP_KERNEL);
 		if (bss) {
 			wil_dbg_wmi(wil, "Added BSS %pM\n",
 				    rx_mgmt_frame->bssid);
@@ -342,6 +333,9 @@ static void wmi_evt_rx_mgmt(struct wil6210_priv *wil, int id, void *d, int len)
 		} else {
 			wil_err(wil, "cfg80211_inform_bss() failed\n");
 		}
+	} else {
+		cfg80211_rx_mgmt(wil->wdev, freq, signal,
+				 (void *)rx_mgmt_frame, d_len, GFP_KERNEL);
 	}
 }
 
@@ -443,7 +437,7 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len)
 	memcpy(wil->dst_addr[0], evt->bssid, ETH_ALEN);
 
 	wil->pending_connect_cid = evt->cid;
-	queue_work(wil->wmi_wq_conn, &wil->wmi_connect_worker);
+	queue_work(wil->wmi_wq_conn, &wil->connect_worker);
 }
 
 static void wmi_evt_disconnect(struct wil6210_priv *wil, int id,
@@ -528,6 +522,37 @@ static void wmi_evt_eapol_rx(struct wil6210_priv *wil, int id,
 	}
 }
 
+static void wmi_evt_linkup(struct wil6210_priv *wil, int id, void *d, int len)
+{
+	struct net_device *ndev = wil_to_ndev(wil);
+	struct wmi_data_port_open_event *evt = d;
+
+	wil_dbg_wmi(wil, "Link UP for CID %d\n", evt->cid);
+
+	netif_carrier_on(ndev);
+}
+
+static void wmi_evt_linkdown(struct wil6210_priv *wil, int id, void *d, int len)
+{
+	struct net_device *ndev = wil_to_ndev(wil);
+	struct wmi_wbe_link_down_event *evt = d;
+
+	wil_dbg_wmi(wil, "Link DOWN for CID %d, reason %d\n",
+		    evt->cid, le32_to_cpu(evt->reason));
+
+	netif_carrier_off(ndev);
+}
+
+static void wmi_evt_ba_status(struct wil6210_priv *wil, int id, void *d,
+			      int len)
+{
+	struct wmi_vring_ba_status_event *evt = d;
+
+	wil_dbg_wmi(wil, "BACK[%d] %s {%d} timeout %d\n",
+		    evt->ringid, evt->status ? "N/A" : "OK", evt->agg_wsize,
+		    __le16_to_cpu(evt->ba_timeout));
+}
+
 static const struct {
 	int eventid;
 	void (*handler)(struct wil6210_priv *wil, int eventid,
@@ -541,6 +566,9 @@ static const struct {
 	{WMI_DISCONNECT_EVENTID,	wmi_evt_disconnect},
 	{WMI_NOTIFY_REQ_DONE_EVENTID,	wmi_evt_notify},
 	{WMI_EAPOL_RX_EVENTID,		wmi_evt_eapol_rx},
+	{WMI_DATA_PORT_OPEN_EVENTID,	wmi_evt_linkup},
+	{WMI_WBE_LINKDOWN_EVENTID,	wmi_evt_linkdown},
+	{WMI_BA_STATUS_EVENTID,		wmi_evt_ba_status},
 };
 
 /*
@@ -559,6 +587,11 @@ void wmi_recv_cmd(struct wil6210_priv *wil)
 	void __iomem *src;
 	ulong flags;
 
+	if (!test_bit(wil_status_reset_done, &wil->status)) {
+		wil_err(wil, "Reset not completed\n");
+		return;
+	}
+
 	for (;;) {
 		u16 len;
 
@@ -683,18 +716,39 @@ int wmi_set_mac_address(struct wil6210_priv *wil, void *addr)
 	return wmi_send(wil, WMI_SET_MAC_ADDRESS_CMDID, &cmd, sizeof(cmd));
 }
 
-int wmi_set_bcon(struct wil6210_priv *wil, int bi, u8 wmi_nettype)
+int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, u8 chan)
 {
-	struct wmi_bcon_ctrl_cmd cmd = {
+	int rc;
+
+	struct wmi_pcp_start_cmd cmd = {
 		.bcon_interval = cpu_to_le16(bi),
 		.network_type = wmi_nettype,
 		.disable_sec_offload = 1,
+		.channel = chan,
 	};
+	struct {
+		struct wil6210_mbox_hdr_wmi wmi;
+		struct wmi_pcp_started_event evt;
+	} __packed reply;
 
 	if (!wil->secure_pcp)
 		cmd.disable_sec = 1;
 
-	return wmi_send(wil, WMI_BCON_CTRL_CMDID, &cmd, sizeof(cmd));
+	rc = wmi_call(wil, WMI_PCP_START_CMDID, &cmd, sizeof(cmd),
+		      WMI_PCP_STARTED_EVENTID, &reply, sizeof(reply), 100);
+	if (rc)
+		return rc;
+
+	if (reply.evt.status != WMI_FW_STATUS_SUCCESS)
+		rc = -EINVAL;
+
+	return rc;
+}
+
+int wmi_pcp_stop(struct wil6210_priv *wil)
+{
+	return wmi_call(wil, WMI_PCP_STOP_CMDID, NULL, 0,
+			WMI_PCP_STOPPED_EVENTID, NULL, 0, 20);
 }
 
 int wmi_set_ssid(struct wil6210_priv *wil, u8 ssid_len, const void *ssid)
@@ -765,6 +819,16 @@ int wmi_get_channel(struct wil6210_priv *wil, int *channel)
 	return 0;
 }
 
+int wmi_p2p_cfg(struct wil6210_priv *wil, int channel)
+{
+	struct wmi_p2p_cfg_cmd cmd = {
+		.discovery_mode = WMI_DISCOVERY_MODE_NON_OFFLOAD,
+		.channel = channel - 1,
+	};
+
+	return wmi_send(wil, WMI_P2P_CFG_CMDID, &cmd, sizeof(cmd));
+}
+
 int wmi_tx_eapol(struct wil6210_priv *wil, struct sk_buff *skb)
 {
 	struct wmi_eapol_tx_cmd *cmd;
@@ -843,7 +907,7 @@ int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie)
 	/* BUG: FW API define ieLen as u8. Will fix FW */
 	cmd->ie_len = cpu_to_le16(ie_len);
 	memcpy(cmd->ie_info, ie, ie_len);
-	rc = wmi_send(wil, WMI_SET_APPIE_CMDID, &cmd, len);
+	rc = wmi_send(wil, WMI_SET_APPIE_CMDID, cmd, len);
 	kfree(cmd);
 
 	return rc;
@@ -898,6 +962,31 @@ int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring)
 	return rc;
 }
 
+int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_m, u32 *t_r)
+{
+	int rc;
+	struct wmi_temp_sense_cmd cmd = {
+		.measure_marlon_m_en = cpu_to_le32(!!t_m),
+		.measure_marlon_r_en = cpu_to_le32(!!t_r),
+	};
+	struct {
+		struct wil6210_mbox_hdr_wmi wmi;
+		struct wmi_temp_sense_done_event evt;
+	} __packed reply;
+
+	rc = wmi_call(wil, WMI_TEMP_SENSE_CMDID, &cmd, sizeof(cmd),
+		      WMI_TEMP_SENSE_DONE_EVENTID, &reply, sizeof(reply), 100);
+	if (rc)
+		return rc;
+
+	if (t_m)
+		*t_m = le32_to_cpu(reply.evt.marlon_m_t1000);
+	if (t_r)
+		*t_r = le32_to_cpu(reply.evt.marlon_r_t1000);
+
+	return 0;
+}
+
 void wmi_event_flush(struct wil6210_priv *wil)
 {
 	struct pending_wmi_event *evt, *t;
@@ -997,24 +1086,3 @@ void wmi_event_worker(struct work_struct *work)
 		kfree(evt);
 	}
 }
-
-void wmi_connect_worker(struct work_struct *work)
-{
-	int rc;
-	struct wil6210_priv *wil = container_of(work, struct wil6210_priv,
-						wmi_connect_worker);
-
-	if (wil->pending_connect_cid < 0) {
-		wil_err(wil, "No connection pending\n");
-		return;
-	}
-
-	wil_dbg_wmi(wil, "Configure for connection CID %d\n",
-		    wil->pending_connect_cid);
-
-	rc = wil_vring_init_tx(wil, 0, WIL6210_TX_RING_SIZE,
-			       wil->pending_connect_cid, 0);
-	wil->pending_connect_cid = -1;
-	if (rc == 0)
-		wil_link_on(wil);
-}
diff --git a/drivers/net/wireless/ath/wil6210/wmi.h b/drivers/net/wireless/ath/wil6210/wmi.h
index 3bbf875..50b8528 100644
--- a/drivers/net/wireless/ath/wil6210/wmi.h
+++ b/drivers/net/wireless/ath/wil6210/wmi.h
@@ -36,6 +36,7 @@
 enum wmi_command_id {
 	WMI_CONNECT_CMDID		= 0x0001,
 	WMI_DISCONNECT_CMDID		= 0x0003,
+	WMI_DISCONNECT_STA_CMDID	= 0x0004,
 	WMI_START_SCAN_CMDID		= 0x0007,
 	WMI_SET_BSS_FILTER_CMDID	= 0x0009,
 	WMI_SET_PROBED_SSID_CMDID	= 0x000a,
@@ -44,7 +45,6 @@ enum wmi_command_id {
 	WMI_ADD_CIPHER_KEY_CMDID	= 0x0016,
 	WMI_DELETE_CIPHER_KEY_CMDID	= 0x0017,
 	WMI_SET_APPIE_CMDID		= 0x003f,
-	WMI_GET_APPIE_CMDID		= 0x0040,
 	WMI_SET_WSC_STATUS_CMDID	= 0x0041,
 	WMI_PXMT_RANGE_CFG_CMDID	= 0x0042,
 	WMI_PXMT_SNR2_RANGE_CFG_CMDID	= 0x0043,
@@ -55,11 +55,11 @@ enum wmi_command_id {
 	WMI_DEEP_ECHO_CMDID		= 0x0804,
 	WMI_CONFIG_MAC_CMDID		= 0x0805,
 	WMI_CONFIG_PHY_DEBUG_CMDID	= 0x0806,
-	WMI_ADD_STATION_CMDID		= 0x0807,
 	WMI_ADD_DEBUG_TX_PCKT_CMDID	= 0x0808,
 	WMI_PHY_GET_STATISTICS_CMDID	= 0x0809,
 	WMI_FS_TUNE_CMDID		= 0x080a,
 	WMI_CORR_MEASURE_CMDID		= 0x080b,
+	WMI_READ_RSSI_CMDID		= 0x080c,
 	WMI_TEMP_SENSE_CMDID		= 0x080e,
 	WMI_DC_CALIB_CMDID		= 0x080f,
 	WMI_SEND_TONE_CMDID		= 0x0810,
@@ -75,9 +75,9 @@ enum wmi_command_id {
 	MAC_IO_STATIC_PARAMS_CMDID	= 0x081b,
 	MAC_IO_DYNAMIC_PARAMS_CMDID	= 0x081c,
 	WMI_SILENT_RSSI_CALIB_CMDID	= 0x081d,
+	WMI_RF_RX_TEST_CMDID		= 0x081e,
 	WMI_CFG_RX_CHAIN_CMDID		= 0x0820,
 	WMI_VRING_CFG_CMDID		= 0x0821,
-	WMI_RX_ON_CMDID			= 0x0822,
 	WMI_VRING_BA_EN_CMDID		= 0x0823,
 	WMI_VRING_BA_DIS_CMDID		= 0x0824,
 	WMI_RCP_ADDBA_RESP_CMDID	= 0x0825,
@@ -87,7 +87,6 @@ enum wmi_command_id {
 	WMI_SET_PCP_CHANNEL_CMDID	= 0x0829,
 	WMI_GET_PCP_CHANNEL_CMDID	= 0x082a,
 	WMI_SW_TX_REQ_CMDID		= 0x082b,
-	WMI_RX_OFF_CMDID		= 0x082c,
 	WMI_READ_MAC_RXQ_CMDID		= 0x0830,
 	WMI_READ_MAC_TXQ_CMDID		= 0x0831,
 	WMI_WRITE_MAC_RXQ_CMDID		= 0x0832,
@@ -112,6 +111,18 @@ enum wmi_command_id {
 	WMI_FLASH_READ_CMDID		= 0x0902,
 	WMI_FLASH_WRITE_CMDID		= 0x0903,
 	WMI_SECURITY_UNIT_TEST_CMDID	= 0x0904,
+	/*P2P*/
+	WMI_P2P_CFG_CMDID		= 0x0910,
+	WMI_PORT_ALLOCATE_CMDID		= 0x0911,
+	WMI_PORT_DELETE_CMDID		= 0x0912,
+	WMI_POWER_MGMT_CFG_CMDID	= 0x0913,
+	WMI_START_LISTEN_CMDID		= 0x0914,
+	WMI_START_SEARCH_CMDID		= 0x0915,
+	WMI_DISCOVERY_START_CMDID	= 0x0916,
+	WMI_DISCOVERY_STOP_CMDID	= 0x0917,
+	WMI_PCP_START_CMDID		= 0x0918,
+	WMI_PCP_STOP_CMDID		= 0x0919,
+	WMI_GET_PCP_FACTOR_CMDID	= 0x091b,
 
 	WMI_SET_MAC_ADDRESS_CMDID	= 0xf003,
 	WMI_ABORT_SCAN_CMDID		= 0xf007,
@@ -132,18 +143,6 @@ enum wmi_command_id {
  */
 
 /*
- * Frame Types
- */
-enum wmi_mgmt_frame_type {
-	WMI_FRAME_BEACON	= 0,
-	WMI_FRAME_PROBE_REQ	= 1,
-	WMI_FRAME_PROBE_RESP	= 2,
-	WMI_FRAME_ASSOC_REQ	= 3,
-	WMI_FRAME_ASSOC_RESP	= 4,
-	WMI_NUM_MGMT_FRAME,
-};
-
-/*
  * WMI_CONNECT_CMDID
  */
 enum wmi_network_type {
@@ -184,7 +183,7 @@ enum wmi_crypto_type {
 enum wmi_connect_ctrl_flag_bits {
 	WMI_CONNECT_ASSOC_POLICY_USER		= 0x0001,
 	WMI_CONNECT_SEND_REASSOC		= 0x0002,
-	WMI_CONNECT_IGNORE_WPAx_GROUP_CIPHER	= 0x0004,
+	WMI_CONNECT_IGNORE_WPA_GROUP_CIPHER	= 0x0004,
 	WMI_CONNECT_PROFILE_MATCH_DONE		= 0x0008,
 	WMI_CONNECT_IGNORE_AAC_BEACON		= 0x0010,
 	WMI_CONNECT_CSA_FOLLOW_BSS		= 0x0020,
@@ -212,6 +211,13 @@ struct wmi_connect_cmd {
 	u8 reserved1[2];
 } __packed;
 
+/*
+ * WMI_DISCONNECT_STA_CMDID
+ */
+struct wmi_disconnect_sta_cmd {
+	u8 dst_mac[WMI_MAC_LEN];
+	__le16 disconnect_reason;
+} __packed;
 
 /*
  * WMI_RECONNECT_CMDID
@@ -289,10 +295,12 @@ struct wmi_delete_cipher_key_cmd {
 enum wmi_scan_type {
 	WMI_LONG_SCAN		= 0,
 	WMI_SHORT_SCAN		= 1,
+	WMI_PBC_SCAN		= 2,
 };
 
 struct wmi_start_scan_cmd {
 	u8 reserved[8];
+
 	__le32 home_dwell_time;	/* Max duration in the home channel(ms) */
 	__le32 force_scan_interval;	/* Time interval between scans (ms)*/
 	u8 scan_type;		/* wmi_scan_type */
@@ -309,7 +317,7 @@ struct wmi_start_scan_cmd {
 /*
  * WMI_SET_PROBED_SSID_CMDID
  */
-#define MAX_PROBED_SSID_INDEX   (15)
+#define MAX_PROBED_SSID_INDEX	(3)
 
 enum wmi_ssid_flag {
 	WMI_SSID_FLAG_DISABLE	= 0,	/* disables entry */
@@ -328,6 +336,20 @@ struct wmi_probed_ssid_cmd {
  * WMI_SET_APPIE_CMDID
  * Add Application specified IE to a management frame
  */
+#define WMI_MAX_IE_LEN		(1024)
+
+/*
+ * Frame Types
+ */
+enum wmi_mgmt_frame_type {
+	WMI_FRAME_BEACON	= 0,
+	WMI_FRAME_PROBE_REQ	= 1,
+	WMI_FRAME_PROBE_RESP	= 2,
+	WMI_FRAME_ASSOC_REQ	= 3,
+	WMI_FRAME_ASSOC_RESP	= 4,
+	WMI_NUM_MGMT_FRAME,
+};
+
 struct wmi_set_appie_cmd {
 	u8 mgmt_frm_type;	/* enum wmi_mgmt_frame_type */
 	u8 reserved;
@@ -335,13 +357,18 @@ struct wmi_set_appie_cmd {
 	u8 ie_info[0];
 } __packed;
 
-#define WMI_MAX_IE_LEN (1024)
 
+/*
+ * WMI_PXMT_RANGE_CFG_CMDID
+ */
 struct wmi_pxmt_range_cfg_cmd {
 	u8 dst_mac[WMI_MAC_LEN];
 	__le16 range;
 } __packed;
 
+/*
+ * WMI_PXMT_SNR2_RANGE_CFG_CMDID
+ */
 struct wmi_pxmt_snr2_range_cfg_cmd {
 	s8 snr2range_arr[WMI_PROX_RANGE_NUM-1];
 } __packed;
@@ -359,6 +386,23 @@ struct wmi_rf_mgmt_cmd {
 	__le32 rf_mgmt_type;
 } __packed;
 
+
+/*
+ * WMI_RF_RX_TEST_CMDID
+ */
+struct wmi_rf_rx_test_cmd {
+	__le32 sector;
+} __packed;
+
+/*
+ * WMI_CORR_MEASURE_CMDID
+ */
+struct wmi_corr_measure_cmd {
+	s32 freq_mhz;
+	__le32 length_samples;
+	__le32 iterations;
+} __packed;
+
 /*
  * WMI_SET_SSID_CMDID
  */
@@ -388,6 +432,74 @@ struct wmi_bcon_ctrl_cmd {
 	u8 disable_sec;
 } __packed;
 
+
+/******* P2P ***********/
+
+/*
+ * WMI_PORT_ALLOCATE_CMDID
+ */
+enum wmi_port_role {
+	WMI_PORT_STA		= 0,
+	WMI_PORT_PCP		= 1,
+	WMI_PORT_AP		= 2,
+	WMI_PORT_P2P_DEV	= 3,
+	WMI_PORT_P2P_CLIENT	= 4,
+	WMI_PORT_P2P_GO		= 5,
+};
+
+struct wmi_port_allocate_cmd {
+	u8 mac[WMI_MAC_LEN];
+	u8 port_role;
+	u8 midid;
+} __packed;
+
+/*
+ * WMI_PORT_DELETE_CMDID
+ */
+struct wmi_delete_port_cmd {
+	u8 mid;
+	u8 reserved[3];
+} __packed;
+
+/*
+ * WMI_P2P_CFG_CMDID
+ */
+enum wmi_discovery_mode {
+	WMI_DISCOVERY_MODE_NON_OFFLOAD	= 0,
+	WMI_DISCOVERY_MODE_OFFLOAD	= 1,
+};
+
+struct wmi_p2p_cfg_cmd {
+	u8 discovery_mode;	/* wmi_discovery_mode */
+	u8 channel;
+	__le16 bcon_interval; /* base to listen/search duration calculation */
+} __packed;
+
+/*
+ * WMI_POWER_MGMT_CFG_CMDID
+ */
+enum wmi_power_source_type {
+	WMI_POWER_SOURCE_BATTERY	= 0,
+	WMI_POWER_SOURCE_OTHER		= 1,
+};
+
+struct wmi_power_mgmt_cfg_cmd {
+	u8 power_source;	/* wmi_power_source_type */
+	u8 reserved[3];
+} __packed;
+
+/*
+ * WMI_PCP_START_CMDID
+ */
+struct wmi_pcp_start_cmd {
+	__le16 bcon_interval;
+	u8 reserved0[10];
+	u8 network_type;
+	u8 channel;
+	u8 disable_sec_offload;
+	u8 disable_sec;
+} __packed;
+
 /*
  * WMI_SW_TX_REQ_CMDID
  */
@@ -435,16 +547,17 @@ enum wmi_vring_cfg_schd_params_priority {
 	WMI_SCH_PRIO_HIGH			= 1,
 };
 
+#define CIDXTID_CID_POS (0)
+#define CIDXTID_CID_LEN (4)
+#define CIDXTID_CID_MSK (0xF)
+#define CIDXTID_TID_POS (4)
+#define CIDXTID_TID_LEN (4)
+#define CIDXTID_TID_MSK (0xF0)
+
 struct wmi_vring_cfg {
 	struct wmi_sw_ring_cfg tx_sw_ring;
 	u8 ringid;				/* 0-23 vrings */
 
-	#define CIDXTID_CID_POS (0)
-	#define CIDXTID_CID_LEN (4)
-	#define CIDXTID_CID_MSK (0xF)
-	#define CIDXTID_TID_POS (4)
-	#define CIDXTID_TID_LEN (4)
-	#define CIDXTID_TID_MSK (0xF0)
 	u8 cidxtid;
 
 	u8 encap_trans_type;
@@ -501,8 +614,14 @@ struct wmi_vring_ba_dis_cmd {
  */
 struct wmi_notify_req_cmd {
 	u8 cid;
-	u8 reserved[3];
+	u8 year;
+	u8 month;
+	u8 day;
 	__le32 interval_usec;
+	u8 hour;
+	u8 minute;
+	u8 second;
+	u8 miliseconds;
 } __packed;
 
 /*
@@ -548,6 +667,11 @@ enum wmi_cfg_rx_chain_cmd_nwifi_ds_trans_type {
 	WMI_NWIFI_RX_TRANS_MODE_PBSS2STA	= 2,
 };
 
+enum wmi_cfg_rx_chain_cmd_reorder_type {
+	WMI_RX_HW_REORDER = 0,
+	WMI_RX_SW_REORDER = 1,
+};
+
 struct wmi_cfg_rx_chain_cmd {
 	__le32 action;
 	struct wmi_sw_ring_cfg rx_sw_ring;
@@ -596,7 +720,8 @@ struct wmi_cfg_rx_chain_cmd {
 	__le16 wb_thrsh;
 	__le32 itr_value;
 	__le16 host_thrsh;
-	u8 reserved[2];
+	u8 reorder_type;
+	u8 reserved;
 	struct wmi_sniffer_cfg sniffer_cfg;
 } __packed;
 
@@ -604,15 +729,7 @@ struct wmi_cfg_rx_chain_cmd {
  * WMI_RCP_ADDBA_RESP_CMDID
  */
 struct wmi_rcp_addba_resp_cmd {
-
-	#define CIDXTID_CID_POS (0)
-	#define CIDXTID_CID_LEN (4)
-	#define CIDXTID_CID_MSK (0xF)
-	#define CIDXTID_TID_POS (4)
-	#define CIDXTID_TID_LEN (4)
-	#define CIDXTID_TID_MSK (0xF0)
 	u8 cidxtid;
-
 	u8 dialog_token;
 	__le16 status_code;
 	__le16 ba_param_set;	/* ieee80211_ba_parameterset field to send */
@@ -623,15 +740,7 @@ struct wmi_rcp_addba_resp_cmd {
  * WMI_RCP_DELBA_CMDID
  */
 struct wmi_rcp_delba_cmd {
-
-	#define CIDXTID_CID_POS (0)
-	#define CIDXTID_CID_LEN (4)
-	#define CIDXTID_CID_MSK (0xF)
-	#define CIDXTID_TID_POS (4)
-	#define CIDXTID_TID_LEN (4)
-	#define CIDXTID_TID_MSK (0xF0)
 	u8 cidxtid;
-
 	u8 reserved;
 	__le16 reason;
 } __packed;
@@ -640,15 +749,7 @@ struct wmi_rcp_delba_cmd {
  * WMI_RCP_ADDBA_REQ_CMDID
  */
 struct wmi_rcp_addba_req_cmd {
-
-	#define CIDXTID_CID_POS (0)
-	#define CIDXTID_CID_LEN (4)
-	#define CIDXTID_CID_MSK (0xF)
-	#define CIDXTID_TID_POS (4)
-	#define CIDXTID_TID_LEN (4)
-	#define CIDXTID_TID_MSK (0xF0)
 	u8 cidxtid;
-
 	u8 dialog_token;
 	/* ieee80211_ba_parameterset field as it received */
 	__le16 ba_param_set;
@@ -665,7 +766,6 @@ struct wmi_set_mac_address_cmd {
 	u8 reserved[2];
 } __packed;
 
-
 /*
 * WMI_EAPOL_TX_CMDID
 */
@@ -692,6 +792,17 @@ struct wmi_echo_cmd {
 } __packed;
 
 /*
+ * WMI_TEMP_SENSE_CMDID
+ *
+ * Measure MAC and radio temperatures
+ */
+struct wmi_temp_sense_cmd {
+	__le32 measure_marlon_m_en;
+	__le32 measure_marlon_r_en;
+} __packed;
+
+
+/*
  * WMI Events
  */
 
@@ -699,7 +810,6 @@ struct wmi_echo_cmd {
  * List of Events (target to host)
  */
 enum wmi_event_id {
-	WMI_IMM_RSP_EVENTID			= 0x0000,
 	WMI_READY_EVENTID			= 0x1001,
 	WMI_CONNECT_EVENTID			= 0x1002,
 	WMI_DISCONNECT_EVENTID			= 0x1003,
@@ -709,13 +819,9 @@ enum wmi_event_id {
 	WMI_FW_READY_EVENTID			= 0x1801,
 	WMI_EXIT_FAST_MEM_ACC_MODE_EVENTID	= 0x0200,
 	WMI_ECHO_RSP_EVENTID			= 0x1803,
-	WMI_CONFIG_MAC_DONE_EVENTID		= 0x1805,
-	WMI_CONFIG_PHY_DEBUG_DONE_EVENTID	= 0x1806,
-	WMI_ADD_STATION_DONE_EVENTID		= 0x1807,
-	WMI_ADD_DEBUG_TX_PCKT_DONE_EVENTID	= 0x1808,
-	WMI_PHY_GET_STATISTICS_EVENTID		= 0x1809,
 	WMI_FS_TUNE_DONE_EVENTID		= 0x180a,
-	WMI_CORR_MEASURE_DONE_EVENTID		= 0x180b,
+	WMI_CORR_MEASURE_EVENTID		= 0x180b,
+	WMI_READ_RSSI_EVENTID			= 0x180c,
 	WMI_TEMP_SENSE_DONE_EVENTID		= 0x180e,
 	WMI_DC_CALIB_DONE_EVENTID		= 0x180f,
 	WMI_IQ_TX_CALIB_DONE_EVENTID		= 0x1811,
@@ -727,10 +833,9 @@ enum wmi_event_id {
 	WMI_MARLON_R_WRITE_DONE_EVENTID		= 0x1819,
 	WMI_MARLON_R_TXRX_SEL_DONE_EVENTID	= 0x181a,
 	WMI_SILENT_RSSI_CALIB_DONE_EVENTID	= 0x181d,
-
+	WMI_RF_RX_TEST_DONE_EVENTID		= 0x181e,
 	WMI_CFG_RX_CHAIN_DONE_EVENTID		= 0x1820,
 	WMI_VRING_CFG_DONE_EVENTID		= 0x1821,
-	WMI_RX_ON_DONE_EVENTID			= 0x1822,
 	WMI_BA_STATUS_EVENTID			= 0x1823,
 	WMI_RCP_ADDBA_REQ_EVENTID		= 0x1824,
 	WMI_ADDBA_RESP_SENT_EVENTID		= 0x1825,
@@ -738,7 +843,6 @@ enum wmi_event_id {
 	WMI_GET_SSID_EVENTID			= 0x1828,
 	WMI_GET_PCP_CHANNEL_EVENTID		= 0x182a,
 	WMI_SW_TX_COMPLETE_EVENTID		= 0x182b,
-	WMI_RX_OFF_DONE_EVENTID			= 0x182c,
 
 	WMI_READ_MAC_RXQ_EVENTID		= 0x1830,
 	WMI_READ_MAC_TXQ_EVENTID		= 0x1831,
@@ -765,7 +869,16 @@ enum wmi_event_id {
 	WMI_UNIT_TEST_EVENTID			= 0x1900,
 	WMI_FLASH_READ_DONE_EVENTID		= 0x1902,
 	WMI_FLASH_WRITE_DONE_EVENTID		= 0x1903,
-
+	/*P2P*/
+	WMI_PORT_ALLOCATED_EVENTID		= 0x1911,
+	WMI_PORT_DELETED_EVENTID		= 0x1912,
+	WMI_LISTEN_STARTED_EVENTID		= 0x1914,
+	WMI_SEARCH_STARTED_EVENTID		= 0x1915,
+	WMI_DISCOVERY_STARTED_EVENTID		= 0x1916,
+	WMI_DISCOVERY_STOPPED_EVENTID		= 0x1917,
+	WMI_PCP_STARTED_EVENTID			= 0x1918,
+	WMI_PCP_STOPPED_EVENTID			= 0x1919,
+	WMI_PCP_FACTOR_EVENTID			= 0x191a,
 	WMI_SET_CHANNEL_EVENTID			= 0x9000,
 	WMI_ASSOC_REQ_EVENTID			= 0x9001,
 	WMI_EAPOL_RX_EVENTID			= 0x9002,
@@ -777,6 +890,12 @@ enum wmi_event_id {
  * Events data structures
  */
 
+
+enum wmi_fw_status {
+	WMI_FW_STATUS_SUCCESS,
+	WMI_FW_STATUS_FAILURE,
+};
+
 /*
  * WMI_RF_MGMT_STATUS_EVENTID
  */
@@ -857,7 +976,7 @@ struct wmi_ready_event {
 	__le32 abi_version;
 	u8 mac[WMI_MAC_LEN];
 	u8 phy_capability;		/* enum wmi_phy_capability */
-	u8 reserved;
+	u8 numof_additional_mids;
 } __packed;
 
 /*
@@ -876,6 +995,8 @@ struct wmi_notify_req_done_event {
 	__le16 other_rx_sector;
 	__le16 other_tx_sector;
 	__le16 range;
+	u8 sqi;
+	u8 reserved[3];
 } __packed;
 
 /*
@@ -951,27 +1072,15 @@ struct wmi_vring_ba_status_event {
  * WMI_DELBA_EVENTID
  */
 struct wmi_delba_event {
-
-	#define CIDXTID_CID_POS (0)
-	#define CIDXTID_CID_LEN (4)
-	#define CIDXTID_CID_MSK (0xF)
-	#define CIDXTID_TID_POS (4)
-	#define CIDXTID_TID_LEN (4)
-	#define CIDXTID_TID_MSK (0xF0)
 	u8 cidxtid;
-
 	u8 from_initiator;
 	__le16 reason;
 } __packed;
 
+
 /*
  * WMI_VRING_CFG_DONE_EVENTID
  */
-enum wmi_vring_cfg_done_event_status {
-	WMI_VRING_CFG_SUCCESS		= 0,
-	WMI_VRING_CFG_FAILURE		= 1,
-};
-
 struct wmi_vring_cfg_done_event {
 	u8 ringid;
 	u8 status;
@@ -982,21 +1091,8 @@ struct wmi_vring_cfg_done_event {
 /*
  * WMI_ADDBA_RESP_SENT_EVENTID
  */
-enum wmi_rcp_addba_resp_sent_event_status {
-	WMI_ADDBA_SUCCESS		= 0,
-	WMI_ADDBA_FAIL			= 1,
-};
-
 struct wmi_rcp_addba_resp_sent_event {
-
-	#define CIDXTID_CID_POS (0)
-	#define CIDXTID_CID_LEN (4)
-	#define CIDXTID_CID_MSK (0xF)
-	#define CIDXTID_TID_POS (4)
-	#define CIDXTID_TID_LEN (4)
-	#define CIDXTID_TID_MSK (0xF0)
 	u8 cidxtid;
-
 	u8 reserved;
 	__le16 status;
 } __packed;
@@ -1005,15 +1101,7 @@ struct wmi_rcp_addba_resp_sent_event {
  * WMI_RCP_ADDBA_REQ_EVENTID
  */
 struct wmi_rcp_addba_req_event {
-
-	#define CIDXTID_CID_POS (0)
-	#define CIDXTID_CID_LEN (4)
-	#define CIDXTID_CID_MSK (0xF)
-	#define CIDXTID_TID_POS (4)
-	#define CIDXTID_TID_LEN (4)
-	#define CIDXTID_TID_MSK (0xF0)
 	u8 cidxtid;
-
 	u8 dialog_token;
 	__le16 ba_param_set;	/* ieee80211_ba_parameterset as it received */
 	__le16 ba_timeout;
@@ -1055,6 +1143,7 @@ struct wmi_data_port_open_event {
 	u8 reserved[3];
 } __packed;
 
+
 /*
  * WMI_GET_PCP_CHANNEL_EVENTID
  */
@@ -1063,6 +1152,54 @@ struct wmi_get_pcp_channel_event {
 	u8 reserved[3];
 } __packed;
 
+
+/*
+* WMI_PORT_ALLOCATED_EVENTID
+*/
+struct wmi_port_allocated_event {
+	u8 status;	/* wmi_fw_status */
+	u8 reserved[3];
+} __packed;
+
+/*
+* WMI_PORT_DELETED_EVENTID
+*/
+struct wmi_port_deleted_event {
+	u8 status;	/* wmi_fw_status */
+	u8 reserved[3];
+} __packed;
+
+/*
+ * WMI_LISTEN_STARTED_EVENTID
+ */
+struct wmi_listen_started_event {
+	u8 status;	/* wmi_fw_status */
+	u8 reserved[3];
+} __packed;
+
+/*
+ * WMI_SEARCH_STARTED_EVENTID
+ */
+struct wmi_search_started_event {
+	u8 status;	/* wmi_fw_status */
+	u8 reserved[3];
+} __packed;
+
+/*
+ * WMI_PCP_STARTED_EVENTID
+ */
+struct wmi_pcp_started_event {
+	u8 status;	/* wmi_fw_status */
+	u8 reserved[3];
+} __packed;
+
+/*
+ * WMI_PCP_FACTOR_EVENTID
+ */
+struct wmi_pcp_factor_event {
+	__le32 pcp_factor;
+} __packed;
+
 /*
  * WMI_SW_TX_COMPLETE_EVENTID
  */
@@ -1078,6 +1215,23 @@ struct wmi_sw_tx_complete_event {
 } __packed;
 
 /*
+ * WMI_CORR_MEASURE_EVENTID
+ */
+struct wmi_corr_measure_event {
+	s32 i;
+	s32 q;
+	s32 image_i;
+	s32 image_q;
+} __packed;
+
+/*
+ * WMI_READ_RSSI_EVENTID
+ */
+struct wmi_read_rssi_event {
+	__le32 ina_rssi_adc_dbm;
+} __packed;
+
+/*
  * WMI_GET_SSID_EVENTID
  */
 struct wmi_get_ssid_event {
@@ -1091,7 +1245,8 @@ struct wmi_get_ssid_event {
 struct wmi_rx_mgmt_info {
 	u8 mcs;
 	s8 snr;
-	__le16 range;
+	u8 range;
+	u8 sqi;
 	__le16 stype;
 	__le16 status;
 	__le32 len;
@@ -1113,4 +1268,14 @@ struct wmi_echo_event {
 	__le32 echoed_value;
 } __packed;
 
+/*
+ * WMI_TEMP_SENSE_DONE_EVENTID
+ *
+ * Measure MAC and radio temperatures
+ */
+struct wmi_temp_sense_done_event {
+	__le32 marlon_m_t1000;
+	__le32 marlon_r_t1000;
+} __packed;
+
 #endif /* __WILOCITY_WMI_H__ */
diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c
index b42930f..5225722 100644
--- a/drivers/net/wireless/atmel_cs.c
+++ b/drivers/net/wireless/atmel_cs.c
@@ -245,16 +245,7 @@ static struct pcmcia_driver atmel_driver = {
 	.suspend	= atmel_suspend,
 	.resume		= atmel_resume,
 };
-
-static int __init atmel_cs_init(void)
-{
-        return pcmcia_register_driver(&atmel_driver);
-}
-
-static void __exit atmel_cs_cleanup(void)
-{
-        pcmcia_unregister_driver(&atmel_driver);
-}
+module_pcmcia_driver(atmel_driver);
 
 /*
     This program is free software; you can redistribute it and/or
@@ -294,6 +285,3 @@ static void __exit atmel_cs_cleanup(void)
     IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     POSSIBILITY OF SUCH DAMAGE.
 */
-
-module_init(atmel_cs_init);
-module_exit(atmel_cs_cleanup);
diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig
index 287c6b6..078e6f3 100644
--- a/drivers/net/wireless/b43/Kconfig
+++ b/drivers/net/wireless/b43/Kconfig
@@ -131,7 +131,7 @@ config B43_PHY_LP
 
 config B43_PHY_HT
 	bool "Support for HT-PHY (high throughput) devices"
-	depends on B43
+	depends on B43 && B43_BCMA
 	---help---
 	  Support for the HT-PHY.
 
@@ -166,8 +166,8 @@ config B43_DEBUG
 	  Broadcom 43xx debugging.
 
 	  This adds additional runtime sanity checks and statistics to the driver.
-	  These checks and statistics might me expensive and hurt runtime performance
-	  of your system.
+	  These checks and statistics might be expensive and hurt the runtime
+	  performance of your system.
 	  This also adds the b43 debugfs interface.
 
 	  Do not enable this, unless you are debugging the driver.
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h
index 10e288d..f5e8401 100644
--- a/drivers/net/wireless/b43/b43.h
+++ b/drivers/net/wireless/b43/b43.h
@@ -285,7 +285,9 @@ enum {
 #define B43_SHM_SH_DTIMPER		0x0012	/* DTIM period */
 #define B43_SHM_SH_NOSLPZNATDTIM	0x004C	/* NOSLPZNAT DTIM */
 /* SHM_SHARED beacon/AP variables */
+#define B43_SHM_SH_BT_BASE0		0x0068	/* Beacon template base 0 */
 #define B43_SHM_SH_BTL0			0x0018	/* Beacon template length 0 */
+#define B43_SHM_SH_BT_BASE1		0x0468	/* Beacon template base 1 */
 #define B43_SHM_SH_BTL1			0x001A	/* Beacon template length 1 */
 #define B43_SHM_SH_BTSFOFF		0x001C	/* Beacon TSF offset */
 #define B43_SHM_SH_TIMBPOS		0x001E	/* TIM B position in beacon */
@@ -473,6 +475,12 @@ enum {
 #define B43_MACCMD_CCA			0x00000008	/* Clear channel assessment */
 #define B43_MACCMD_BGNOISE		0x00000010	/* Background noise */
 
+/* See BCMA_CLKCTLST_EXTRESREQ and BCMA_CLKCTLST_EXTRESST */
+#define B43_BCMA_CLKCTLST_80211_PLL_REQ	0x00000100
+#define B43_BCMA_CLKCTLST_PHY_PLL_REQ	0x00000200
+#define B43_BCMA_CLKCTLST_80211_PLL_ST	0x01000000
+#define B43_BCMA_CLKCTLST_PHY_PLL_ST	0x02000000
+
 /* 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 */
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c
index 38bc5a7..523355b 100644
--- a/drivers/net/wireless/b43/dma.c
+++ b/drivers/net/wireless/b43/dma.c
@@ -419,8 +419,6 @@ static inline
 
 static int alloc_ringmemory(struct b43_dmaring *ring)
 {
-	gfp_t flags = GFP_KERNEL;
-
 	/* The specs call for 4K buffers for 30- and 32-bit DMA with 4K
 	 * alignment and 8K buffers for 64-bit DMA with 8K alignment.
 	 * In practice we could use smaller buffers for the latter, but the
@@ -435,12 +433,9 @@ static int alloc_ringmemory(struct b43_dmaring *ring)
 
 	ring->descbase = dma_alloc_coherent(ring->dev->dev->dma_dev,
 					    ring_mem_size, &(ring->dmabase),
-					    flags);
-	if (!ring->descbase) {
-		b43err(ring->dev->wl, "DMA ringmemory allocation failed\n");
+					    GFP_KERNEL | __GFP_ZERO);
+	if (!ring->descbase)
 		return -ENOMEM;
-	}
-	memset(ring->descbase, 0, ring_mem_size);
 
 	return 0;
 }
@@ -1487,8 +1482,12 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
 	const struct b43_dma_ops *ops;
 	struct b43_dmaring *ring;
 	struct b43_dmadesc_meta *meta;
+	static const struct b43_txstatus fake; /* filled with 0 */
+	const struct b43_txstatus *txstat;
 	int slot, firstused;
 	bool frame_succeed;
+	int skip;
+	static u8 err_out1, err_out2;
 
 	ring = parse_cookie(dev, status->cookie, &slot);
 	if (unlikely(!ring))
@@ -1501,13 +1500,36 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
 	firstused = ring->current_slot - ring->used_slots + 1;
 	if (firstused < 0)
 		firstused = ring->nr_slots + firstused;
+
+	skip = 0;
 	if (unlikely(slot != firstused)) {
 		/* This possibly is a firmware bug and will result in
-		 * malfunction, memory leaks and/or stall of DMA functionality. */
-		b43dbg(dev->wl, "Out of order TX status report on DMA ring %d. "
-		       "Expected %d, but got %d\n",
-		       ring->index, firstused, slot);
-		return;
+		 * malfunction, memory leaks and/or stall of DMA functionality.
+		 */
+		if (slot == next_slot(ring, next_slot(ring, firstused))) {
+			/* If a single header/data pair was missed, skip over
+			 * the first two slots in an attempt to recover.
+			 */
+			slot = firstused;
+			skip = 2;
+			if (!err_out1) {
+				/* Report the error once. */
+				b43dbg(dev->wl,
+				       "Skip on DMA ring %d slot %d.\n",
+				       ring->index, slot);
+				err_out1 = 1;
+			}
+		} else {
+			/* More than a single header/data pair were missed.
+			 * Report this error once.
+			 */
+			if (!err_out2)
+				b43dbg(dev->wl,
+				       "Out of order TX status report on DMA ring %d. Expected %d, but got %d\n",
+				       ring->index, firstused, slot);
+			err_out2 = 1;
+			return;
+		}
 	}
 
 	ops = ring->ops;
@@ -1522,11 +1544,13 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
 			       slot, firstused, ring->index);
 			break;
 		}
+
 		if (meta->skb) {
 			struct b43_private_tx_info *priv_info =
-				b43_get_priv_tx_info(IEEE80211_SKB_CB(meta->skb));
+			     b43_get_priv_tx_info(IEEE80211_SKB_CB(meta->skb));
 
-			unmap_descbuffer(ring, meta->dmaaddr, meta->skb->len, 1);
+			unmap_descbuffer(ring, meta->dmaaddr,
+					 meta->skb->len, 1);
 			kfree(priv_info->bouncebuffer);
 			priv_info->bouncebuffer = NULL;
 		} else {
@@ -1538,8 +1562,9 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
 			struct ieee80211_tx_info *info;
 
 			if (unlikely(!meta->skb)) {
-				/* This is a scatter-gather fragment of a frame, so
-				 * the skb pointer must not be NULL. */
+				/* This is a scatter-gather fragment of a frame,
+				 * so the skb pointer must not be NULL.
+				 */
 				b43dbg(dev->wl, "TX status unexpected NULL skb "
 				       "at slot %d (first=%d) on ring %d\n",
 				       slot, firstused, ring->index);
@@ -1550,9 +1575,18 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
 
 			/*
 			 * Call back to inform the ieee80211 subsystem about
-			 * the status of the transmission.
+			 * the status of the transmission. When skipping over
+			 * a missed TX status report, use a status structure
+			 * filled with zeros to indicate that the frame was not
+			 * sent (frame_count 0) and not acknowledged
 			 */
-			frame_succeed = b43_fill_txstatus_report(dev, info, status);
+			if (unlikely(skip))
+				txstat = &fake;
+			else
+				txstat = status;
+
+			frame_succeed = b43_fill_txstatus_report(dev, info,
+								 txstat);
 #ifdef CONFIG_B43_DEBUG
 			if (frame_succeed)
 				ring->nr_succeed_tx_packets++;
@@ -1580,12 +1614,14 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
 		/* Everything unmapped and free'd. So it's not used anymore. */
 		ring->used_slots--;
 
-		if (meta->is_last_fragment) {
+		if (meta->is_last_fragment && !skip) {
 			/* This is the last scatter-gather
 			 * fragment of the frame. We are done. */
 			break;
 		}
 		slot = next_slot(ring, slot);
+		if (skip > 0)
+			--skip;
 	}
 	if (ring->stopped) {
 		B43_WARN_ON(free_slots(ring) < TX_SLOTS_PER_FRAME);
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 0568273..4ac73d2 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -1189,10 +1189,15 @@ static void b43_bcma_phy_reset(struct b43_wldev *dev)
 
 static void b43_bcma_wireless_core_reset(struct b43_wldev *dev, bool gmode)
 {
+	u32 req = B43_BCMA_CLKCTLST_80211_PLL_REQ |
+		  B43_BCMA_CLKCTLST_PHY_PLL_REQ;
+	u32 status = B43_BCMA_CLKCTLST_80211_PLL_ST |
+		     B43_BCMA_CLKCTLST_PHY_PLL_ST;
+
 	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);
+	bcma_core_pll_ctl(dev->dev->bdev, req, status, true);
 }
 #endif
 
@@ -1305,17 +1310,19 @@ static u32 b43_jssi_read(struct b43_wldev *dev)
 {
 	u32 val = 0;
 
-	val = b43_shm_read16(dev, B43_SHM_SHARED, 0x08A);
+	val = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_JSSI1);
 	val <<= 16;
-	val |= b43_shm_read16(dev, B43_SHM_SHARED, 0x088);
+	val |= b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_JSSI0);
 
 	return val;
 }
 
 static void b43_jssi_write(struct b43_wldev *dev, u32 jssi)
 {
-	b43_shm_write16(dev, B43_SHM_SHARED, 0x088, (jssi & 0x0000FFFF));
-	b43_shm_write16(dev, B43_SHM_SHARED, 0x08A, (jssi & 0xFFFF0000) >> 16);
+	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_JSSI0,
+			(jssi & 0x0000FFFF));
+	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_JSSI1,
+			(jssi & 0xFFFF0000) >> 16);
 }
 
 static void b43_generate_noise_sample(struct b43_wldev *dev)
@@ -1618,7 +1625,7 @@ static void b43_upload_beacon0(struct b43_wldev *dev)
 
 	if (wl->beacon0_uploaded)
 		return;
-	b43_write_beacon_template(dev, 0x68, 0x18);
+	b43_write_beacon_template(dev, B43_SHM_SH_BT_BASE0, B43_SHM_SH_BTL0);
 	wl->beacon0_uploaded = true;
 }
 
@@ -1628,7 +1635,7 @@ static void b43_upload_beacon1(struct b43_wldev *dev)
 
 	if (wl->beacon1_uploaded)
 		return;
-	b43_write_beacon_template(dev, 0x468, 0x1A);
+	b43_write_beacon_template(dev, B43_SHM_SH_BT_BASE1, B43_SHM_SH_BTL1);
 	wl->beacon1_uploaded = true;
 }
 
@@ -2775,9 +2782,7 @@ static int b43_gpio_init(struct b43_wldev *dev)
 	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);
+		bcma_chipco_gpio_control(&dev->dev->bdev->bus->drv_cc, mask, set);
 		break;
 #endif
 #ifdef CONFIG_B43_SSB
@@ -2802,8 +2807,7 @@ static void b43_gpio_cleanup(struct b43_wldev *dev)
 	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);
+		bcma_chipco_gpio_control(&dev->dev->bdev->bus->drv_cc, ~0, 0);
 		break;
 #endif
 #ifdef CONFIG_B43_SSB
@@ -3111,7 +3115,7 @@ static int b43_chip_init(struct b43_wldev *dev)
 
 	/* Probe Response Timeout value */
 	/* FIXME: Default to 0, has to be set by ioctl probably... :-/ */
-	b43_shm_write16(dev, B43_SHM_SHARED, 0x0074, 0x0000);
+	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_PRMAXTIME, 0);
 
 	/* Initially set the wireless operation mode. */
 	b43_adjust_opmode(dev);
diff --git a/drivers/net/wireless/b43/pcmcia.c b/drivers/net/wireless/b43/pcmcia.c
index f2ea2ce..55f2bd7 100644
--- a/drivers/net/wireless/b43/pcmcia.c
+++ b/drivers/net/wireless/b43/pcmcia.c
@@ -130,6 +130,10 @@ static struct pcmcia_driver b43_pcmcia_driver = {
 	.resume		= b43_pcmcia_resume,
 };
 
+/*
+ * These are not module init/exit functions!
+ * The module_pcmcia_driver() helper cannot be used here.
+ */
 int b43_pcmcia_init(void)
 {
 	return pcmcia_register_driver(&b43_pcmcia_driver);
diff --git a/drivers/net/wireless/b43/phy_ht.c b/drivers/net/wireless/b43/phy_ht.c
index 7416c5e..b866770 100644
--- a/drivers/net/wireless/b43/phy_ht.c
+++ b/drivers/net/wireless/b43/phy_ht.c
@@ -154,9 +154,84 @@ static void b43_radio_2059_init(struct b43_wldev *dev)
 }
 
 /**************************************************
+ * RF
+ **************************************************/
+
+static void b43_phy_ht_force_rf_sequence(struct b43_wldev *dev, u16 rf_seq)
+{
+	u8 i;
+
+	u16 save_seq_mode = b43_phy_read(dev, B43_PHY_HT_RF_SEQ_MODE);
+	b43_phy_set(dev, B43_PHY_HT_RF_SEQ_MODE, 0x3);
+
+	b43_phy_set(dev, B43_PHY_HT_RF_SEQ_TRIG, rf_seq);
+	for (i = 0; i < 200; i++) {
+		if (!(b43_phy_read(dev, B43_PHY_HT_RF_SEQ_STATUS) & rf_seq)) {
+			i = 0;
+			break;
+		}
+		msleep(1);
+	}
+	if (i)
+		b43err(dev->wl, "Forcing RF sequence timeout\n");
+
+	b43_phy_write(dev, B43_PHY_HT_RF_SEQ_MODE, save_seq_mode);
+}
+
+static void b43_phy_ht_pa_override(struct b43_wldev *dev, bool enable)
+{
+	struct b43_phy_ht *htphy = dev->phy.ht;
+	static const u16 regs[3] = { B43_PHY_HT_RF_CTL_INT_C1,
+				     B43_PHY_HT_RF_CTL_INT_C2,
+				     B43_PHY_HT_RF_CTL_INT_C3 };
+	int i;
+
+	if (enable) {
+		for (i = 0; i < 3; i++)
+			b43_phy_write(dev, regs[i], htphy->rf_ctl_int_save[i]);
+	} else {
+		for (i = 0; i < 3; i++)
+			htphy->rf_ctl_int_save[i] = b43_phy_read(dev, regs[i]);
+		/* TODO: Does 5GHz band use different value (not 0x0400)? */
+		for (i = 0; i < 3; i++)
+			b43_phy_write(dev, regs[i], 0x0400);
+	}
+}
+
+/**************************************************
  * Various PHY ops
  **************************************************/
 
+static u16 b43_phy_ht_classifier(struct b43_wldev *dev, u16 mask, u16 val)
+{
+	u16 tmp;
+	u16 allowed = B43_PHY_HT_CLASS_CTL_CCK_EN |
+		      B43_PHY_HT_CLASS_CTL_OFDM_EN |
+		      B43_PHY_HT_CLASS_CTL_WAITED_EN;
+
+	tmp = b43_phy_read(dev, B43_PHY_HT_CLASS_CTL);
+	tmp &= allowed;
+	tmp &= ~mask;
+	tmp |= (val & mask);
+	b43_phy_maskset(dev, B43_PHY_HT_CLASS_CTL, ~allowed, tmp);
+
+	return tmp;
+}
+
+static void b43_phy_ht_reset_cca(struct b43_wldev *dev)
+{
+	u16 bbcfg;
+
+	b43_phy_force_clock(dev, true);
+	bbcfg = b43_phy_read(dev, B43_PHY_HT_BBCFG);
+	b43_phy_write(dev, B43_PHY_HT_BBCFG, bbcfg | B43_PHY_HT_BBCFG_RSTCCA);
+	udelay(1);
+	b43_phy_write(dev, B43_PHY_HT_BBCFG, bbcfg & ~B43_PHY_HT_BBCFG_RSTCCA);
+	b43_phy_force_clock(dev, false);
+
+	b43_phy_ht_force_rf_sequence(dev, B43_PHY_HT_RF_SEQ_TRIG_RST2RX);
+}
+
 static void b43_phy_ht_zero_extg(struct b43_wldev *dev)
 {
 	u8 i, j;
@@ -176,10 +251,10 @@ static void b43_phy_ht_afe_unk1(struct b43_wldev *dev)
 {
 	u8 i;
 
-	const u16 ctl_regs[3][2] = {
-		{ B43_PHY_HT_AFE_CTL1, B43_PHY_HT_AFE_CTL2 },
-		{ B43_PHY_HT_AFE_CTL3, B43_PHY_HT_AFE_CTL4 },
-		{ B43_PHY_HT_AFE_CTL5, B43_PHY_HT_AFE_CTL6},
+	static const u16 ctl_regs[3][2] = {
+		{ B43_PHY_HT_AFE_C1_OVER, B43_PHY_HT_AFE_C1 },
+		{ B43_PHY_HT_AFE_C2_OVER, B43_PHY_HT_AFE_C2 },
+		{ B43_PHY_HT_AFE_C3_OVER, B43_PHY_HT_AFE_C3},
 	};
 
 	for (i = 0; i < 3; i++) {
@@ -193,27 +268,6 @@ static void b43_phy_ht_afe_unk1(struct b43_wldev *dev)
 	}
 }
 
-static void b43_phy_ht_force_rf_sequence(struct b43_wldev *dev, u16 rf_seq)
-{
-	u8 i;
-
-	u16 save_seq_mode = b43_phy_read(dev, B43_PHY_HT_RF_SEQ_MODE);
-	b43_phy_set(dev, B43_PHY_HT_RF_SEQ_MODE, 0x3);
-
-	b43_phy_set(dev, B43_PHY_HT_RF_SEQ_TRIG, rf_seq);
-	for (i = 0; i < 200; i++) {
-		if (!(b43_phy_read(dev, B43_PHY_HT_RF_SEQ_STATUS) & rf_seq)) {
-			i = 0;
-			break;
-		}
-		msleep(1);
-	}
-	if (i)
-		b43err(dev->wl, "Forcing RF sequence timeout\n");
-
-	b43_phy_write(dev, B43_PHY_HT_RF_SEQ_MODE, save_seq_mode);
-}
-
 static void b43_phy_ht_read_clip_detection(struct b43_wldev *dev, u16 *clip_st)
 {
 	clip_st[0] = b43_phy_read(dev, B43_PHY_HT_C1_CLIP1THRES);
@@ -240,15 +294,426 @@ static void b43_phy_ht_bphy_init(struct b43_wldev *dev)
 }
 
 /**************************************************
+ * Samples
+ **************************************************/
+
+static void b43_phy_ht_stop_playback(struct b43_wldev *dev)
+{
+	struct b43_phy_ht *phy_ht = dev->phy.ht;
+	u16 tmp;
+	int i;
+
+	tmp = b43_phy_read(dev, B43_PHY_HT_SAMP_STAT);
+	if (tmp & 0x1)
+		b43_phy_set(dev, B43_PHY_HT_SAMP_CMD, B43_PHY_HT_SAMP_CMD_STOP);
+	else if (tmp & 0x2)
+		b43_phy_mask(dev, B43_PHY_HT_IQLOCAL_CMDGCTL, 0x7FFF);
+
+	b43_phy_mask(dev, B43_PHY_HT_SAMP_CMD, ~0x0004);
+
+	for (i = 0; i < 3; i++) {
+		if (phy_ht->bb_mult_save[i] >= 0) {
+			b43_httab_write(dev, B43_HTTAB16(13, 0x63 + i * 4),
+					phy_ht->bb_mult_save[i]);
+			b43_httab_write(dev, B43_HTTAB16(13, 0x67 + i * 4),
+					phy_ht->bb_mult_save[i]);
+		}
+	}
+}
+
+static u16 b43_phy_ht_load_samples(struct b43_wldev *dev)
+{
+	int i;
+	u16 len = 20 << 3;
+
+	b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, 0x4400);
+
+	for (i = 0; i < len; i++) {
+		b43_phy_write(dev, B43_PHY_HT_TABLE_DATAHI, 0);
+		b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, 0);
+	}
+
+	return len;
+}
+
+static void b43_phy_ht_run_samples(struct b43_wldev *dev, u16 samps, u16 loops,
+				   u16 wait)
+{
+	struct b43_phy_ht *phy_ht = dev->phy.ht;
+	u16 save_seq_mode;
+	int i;
+
+	for (i = 0; i < 3; i++) {
+		if (phy_ht->bb_mult_save[i] < 0)
+			phy_ht->bb_mult_save[i] = b43_httab_read(dev, B43_HTTAB16(13, 0x63 + i * 4));
+	}
+
+	b43_phy_write(dev, B43_PHY_HT_SAMP_DEP_CNT, samps - 1);
+	if (loops != 0xFFFF)
+		loops--;
+	b43_phy_write(dev, B43_PHY_HT_SAMP_LOOP_CNT, loops);
+	b43_phy_write(dev, B43_PHY_HT_SAMP_WAIT_CNT, wait);
+
+	save_seq_mode = b43_phy_read(dev, B43_PHY_HT_RF_SEQ_MODE);
+	b43_phy_set(dev, B43_PHY_HT_RF_SEQ_MODE,
+		    B43_PHY_HT_RF_SEQ_MODE_CA_OVER);
+
+	/* TODO: find out mask bits! Do we need more function arguments? */
+	b43_phy_mask(dev, B43_PHY_HT_SAMP_CMD, ~0);
+	b43_phy_mask(dev, B43_PHY_HT_SAMP_CMD, ~0);
+	b43_phy_mask(dev, B43_PHY_HT_IQLOCAL_CMDGCTL, ~0);
+	b43_phy_set(dev, B43_PHY_HT_SAMP_CMD, 0x1);
+
+	for (i = 0; i < 100; i++) {
+		if (!(b43_phy_read(dev, B43_PHY_HT_RF_SEQ_STATUS) & 1)) {
+			i = 0;
+			break;
+		}
+		udelay(10);
+	}
+	if (i)
+		b43err(dev->wl, "run samples timeout\n");
+
+	b43_phy_write(dev, B43_PHY_HT_RF_SEQ_MODE, save_seq_mode);
+}
+
+static void b43_phy_ht_tx_tone(struct b43_wldev *dev)
+{
+	u16 samp;
+
+	samp = b43_phy_ht_load_samples(dev);
+	b43_phy_ht_run_samples(dev, samp, 0xFFFF, 0);
+}
+
+/**************************************************
+ * RSSI
+ **************************************************/
+
+static void b43_phy_ht_rssi_select(struct b43_wldev *dev, u8 core_sel,
+				   u8 rssi_type)
+{
+	static const u16 ctl_regs[3][2] = {
+		{ B43_PHY_HT_AFE_C1, B43_PHY_HT_AFE_C1_OVER, },
+		{ B43_PHY_HT_AFE_C2, B43_PHY_HT_AFE_C2_OVER, },
+		{ B43_PHY_HT_AFE_C3, B43_PHY_HT_AFE_C3_OVER, },
+	};
+	static const u16 radio_r[] = { R2059_SYN, R2059_TXRX0, R2059_RXRX1, };
+	int core;
+
+	if (core_sel == 0) {
+		b43err(dev->wl, "RSSI selection for core off not implemented yet\n");
+	} else {
+		for (core = 0; core < 3; core++) {
+			/* Check if caller requested a one specific core */
+			if ((core_sel == 1 && core != 0) ||
+			    (core_sel == 2 && core != 1) ||
+			    (core_sel == 3 && core != 2))
+				continue;
+
+			switch (rssi_type) {
+			case 4:
+				b43_phy_set(dev, ctl_regs[core][0], 0x3 << 8);
+				b43_phy_set(dev, ctl_regs[core][0], 0x3 << 10);
+				b43_phy_set(dev, ctl_regs[core][1], 0x1 << 9);
+				b43_phy_set(dev, ctl_regs[core][1], 0x1 << 10);
+
+				b43_radio_set(dev, R2059_RXRX1 | 0xbf, 0x1);
+				b43_radio_write(dev, radio_r[core] | 0x159,
+						0x11);
+				break;
+			default:
+				b43err(dev->wl, "RSSI selection for type %d not implemented yet\n",
+				       rssi_type);
+			}
+		}
+	}
+}
+
+static void b43_phy_ht_poll_rssi(struct b43_wldev *dev, u8 type, s32 *buf,
+				 u8 nsamp)
+{
+	u16 phy_regs_values[12];
+	static const u16 phy_regs_to_save[] = {
+		B43_PHY_HT_AFE_C1, B43_PHY_HT_AFE_C1_OVER,
+		0x848, 0x841,
+		B43_PHY_HT_AFE_C2, B43_PHY_HT_AFE_C2_OVER,
+		0x868, 0x861,
+		B43_PHY_HT_AFE_C3, B43_PHY_HT_AFE_C3_OVER,
+		0x888, 0x881,
+	};
+	u16 tmp[3];
+	int i;
+
+	for (i = 0; i < 12; i++)
+		phy_regs_values[i] = b43_phy_read(dev, phy_regs_to_save[i]);
+
+	b43_phy_ht_rssi_select(dev, 5, type);
+
+	for (i = 0; i < 6; i++)
+		buf[i] = 0;
+
+	for (i = 0; i < nsamp; i++) {
+		tmp[0] = b43_phy_read(dev, B43_PHY_HT_RSSI_C1);
+		tmp[1] = b43_phy_read(dev, B43_PHY_HT_RSSI_C2);
+		tmp[2] = b43_phy_read(dev, B43_PHY_HT_RSSI_C3);
+
+		buf[0] += ((s8)((tmp[0] & 0x3F) << 2)) >> 2;
+		buf[1] += ((s8)(((tmp[0] >> 8) & 0x3F) << 2)) >> 2;
+		buf[2] += ((s8)((tmp[1] & 0x3F) << 2)) >> 2;
+		buf[3] += ((s8)(((tmp[1] >> 8) & 0x3F) << 2)) >> 2;
+		buf[4] += ((s8)((tmp[2] & 0x3F) << 2)) >> 2;
+		buf[5] += ((s8)(((tmp[2] >> 8) & 0x3F) << 2)) >> 2;
+	}
+
+	for (i = 0; i < 12; i++)
+		b43_phy_write(dev, phy_regs_to_save[i], phy_regs_values[i]);
+}
+
+/**************************************************
+ * Tx/Rx
+ **************************************************/
+
+static void b43_phy_ht_tx_power_fix(struct b43_wldev *dev)
+{
+	int i;
+
+	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);
+	}
+}
+
+static void b43_phy_ht_tx_power_ctl(struct b43_wldev *dev, bool enable)
+{
+	struct b43_phy_ht *phy_ht = dev->phy.ht;
+	u16 en_bits = B43_PHY_HT_TXPCTL_CMD_C1_COEFF |
+		      B43_PHY_HT_TXPCTL_CMD_C1_HWPCTLEN |
+		      B43_PHY_HT_TXPCTL_CMD_C1_PCTLEN;
+	static const u16 cmd_regs[3] = { B43_PHY_HT_TXPCTL_CMD_C1,
+					 B43_PHY_HT_TXPCTL_CMD_C2,
+					 B43_PHY_HT_TXPCTL_CMD_C3 };
+	int i;
+
+	if (!enable) {
+		if (b43_phy_read(dev, B43_PHY_HT_TXPCTL_CMD_C1) & en_bits) {
+			/* We disable enabled TX pwr ctl, save it's state */
+			/*
+			 * TODO: find the registers. On N-PHY they were 0x1ed
+			 * and 0x1ee, we need 3 such a registers for HT-PHY
+			 */
+		}
+		b43_phy_mask(dev, B43_PHY_HT_TXPCTL_CMD_C1, ~en_bits);
+	} else {
+		b43_phy_set(dev, B43_PHY_HT_TXPCTL_CMD_C1, en_bits);
+
+		if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
+			for (i = 0; i < 3; i++)
+				b43_phy_write(dev, cmd_regs[i], 0x32);
+		}
+
+		for (i = 0; i < 3; i++)
+			if (phy_ht->tx_pwr_idx[i] <=
+			    B43_PHY_HT_TXPCTL_CMD_C1_INIT)
+				b43_phy_write(dev, cmd_regs[i],
+					      phy_ht->tx_pwr_idx[i]);
+	}
+
+	phy_ht->tx_pwr_ctl = enable;
+}
+
+static void b43_phy_ht_tx_power_ctl_idle_tssi(struct b43_wldev *dev)
+{
+	struct b43_phy_ht *phy_ht = dev->phy.ht;
+	s32 rssi_buf[6];
+
+	/* TODO */
+
+	b43_phy_ht_tx_tone(dev);
+	udelay(20);
+	b43_phy_ht_poll_rssi(dev, 4, rssi_buf, 1);
+	b43_phy_ht_stop_playback(dev);
+	b43_phy_ht_reset_cca(dev);
+
+	phy_ht->idle_tssi[0] = rssi_buf[0] & 0xff;
+	phy_ht->idle_tssi[1] = rssi_buf[2] & 0xff;
+	phy_ht->idle_tssi[2] = rssi_buf[4] & 0xff;
+
+	/* TODO */
+}
+
+static void b43_phy_ht_tx_power_ctl_setup(struct b43_wldev *dev)
+{
+	struct b43_phy_ht *phy_ht = dev->phy.ht;
+	struct ssb_sprom *sprom = dev->dev->bus_sprom;
+
+	u8 *idle = phy_ht->idle_tssi;
+	u8 target[3];
+	s16 a1[3], b0[3], b1[3];
+
+	u16 freq = dev->phy.channel_freq;
+	int i, c;
+
+	if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
+		for (c = 0; c < 3; c++) {
+			target[c] = sprom->core_pwr_info[c].maxpwr_2g;
+			a1[c] = sprom->core_pwr_info[c].pa_2g[0];
+			b0[c] = sprom->core_pwr_info[c].pa_2g[1];
+			b1[c] = sprom->core_pwr_info[c].pa_2g[2];
+		}
+	} else if (freq >= 4900 && freq < 5100) {
+		for (c = 0; c < 3; c++) {
+			target[c] = sprom->core_pwr_info[c].maxpwr_5gl;
+			a1[c] = sprom->core_pwr_info[c].pa_5gl[0];
+			b0[c] = sprom->core_pwr_info[c].pa_5gl[1];
+			b1[c] = sprom->core_pwr_info[c].pa_5gl[2];
+		}
+	} else if (freq >= 5100 && freq < 5500) {
+		for (c = 0; c < 3; c++) {
+			target[c] = sprom->core_pwr_info[c].maxpwr_5g;
+			a1[c] = sprom->core_pwr_info[c].pa_5g[0];
+			b0[c] = sprom->core_pwr_info[c].pa_5g[1];
+			b1[c] = sprom->core_pwr_info[c].pa_5g[2];
+		}
+	} else if (freq >= 5500) {
+		for (c = 0; c < 3; c++) {
+			target[c] = sprom->core_pwr_info[c].maxpwr_5gh;
+			a1[c] = sprom->core_pwr_info[c].pa_5gh[0];
+			b0[c] = sprom->core_pwr_info[c].pa_5gh[1];
+			b1[c] = sprom->core_pwr_info[c].pa_5gh[2];
+		}
+	} else {
+		target[0] = target[1] = target[2] = 52;
+		a1[0] = a1[1] = a1[2] = -424;
+		b0[0] = b0[1] = b0[2] = 5612;
+		b1[0] = b1[1] = b1[2] = -1393;
+	}
+
+	b43_phy_set(dev, B43_PHY_HT_TSSIMODE, B43_PHY_HT_TSSIMODE_EN);
+	b43_phy_mask(dev, B43_PHY_HT_TXPCTL_CMD_C1,
+		     ~B43_PHY_HT_TXPCTL_CMD_C1_PCTLEN & 0xFFFF);
+
+	/* TODO: Does it depend on sprom->fem.ghz2.tssipos? */
+	b43_phy_set(dev, B43_PHY_HT_TXPCTL_IDLE_TSSI, 0x4000);
+
+	b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_CMD_C1,
+			~B43_PHY_HT_TXPCTL_CMD_C1_INIT, 0x19);
+	b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_CMD_C2,
+			~B43_PHY_HT_TXPCTL_CMD_C2_INIT, 0x19);
+	b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_CMD_C3,
+			~B43_PHY_HT_TXPCTL_CMD_C3_INIT, 0x19);
+
+	b43_phy_set(dev, B43_PHY_HT_TXPCTL_IDLE_TSSI,
+		    B43_PHY_HT_TXPCTL_IDLE_TSSI_BINF);
+
+	b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_IDLE_TSSI,
+			~B43_PHY_HT_TXPCTL_IDLE_TSSI_C1,
+			idle[0] << B43_PHY_HT_TXPCTL_IDLE_TSSI_C1_SHIFT);
+	b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_IDLE_TSSI,
+			~B43_PHY_HT_TXPCTL_IDLE_TSSI_C2,
+			idle[1] << B43_PHY_HT_TXPCTL_IDLE_TSSI_C2_SHIFT);
+	b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_IDLE_TSSI2,
+			~B43_PHY_HT_TXPCTL_IDLE_TSSI2_C3,
+			idle[2] << B43_PHY_HT_TXPCTL_IDLE_TSSI2_C3_SHIFT);
+
+	b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_N, ~B43_PHY_HT_TXPCTL_N_TSSID,
+			0xf0);
+	b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_N, ~B43_PHY_HT_TXPCTL_N_NPTIL2,
+			0x3 << B43_PHY_HT_TXPCTL_N_NPTIL2_SHIFT);
+#if 0
+	/* TODO: what to mask/set? */
+	b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_CMD_C1, 0x800, 0)
+	b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_CMD_C1, 0x400, 0)
+#endif
+
+	b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_TARG_PWR,
+			~B43_PHY_HT_TXPCTL_TARG_PWR_C1,
+			target[0] << B43_PHY_HT_TXPCTL_TARG_PWR_C1_SHIFT);
+	b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_TARG_PWR,
+			~B43_PHY_HT_TXPCTL_TARG_PWR_C2 & 0xFFFF,
+			target[1] << B43_PHY_HT_TXPCTL_TARG_PWR_C2_SHIFT);
+	b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_TARG_PWR2,
+			~B43_PHY_HT_TXPCTL_TARG_PWR2_C3,
+			target[2] << B43_PHY_HT_TXPCTL_TARG_PWR2_C3_SHIFT);
+
+	for (c = 0; c < 3; c++) {
+		s32 num, den, pwr;
+		u32 regval[64];
+
+		for (i = 0; i < 64; i++) {
+			num = 8 * (16 * b0[c] + b1[c] * i);
+			den = 32768 + a1[c] * i;
+			pwr = max((4 * num + den / 2) / den, -8);
+			regval[i] = pwr;
+		}
+		b43_httab_write_bulk(dev, B43_HTTAB16(26 + c, 0), 64, regval);
+	}
+}
+
+/**************************************************
  * Channel switching ops.
  **************************************************/
 
+static void b43_phy_ht_spur_avoid(struct b43_wldev *dev,
+				  struct ieee80211_channel *new_channel)
+{
+	struct bcma_device *core = dev->dev->bdev;
+	int spuravoid = 0;
+	u16 tmp;
+
+	/* Check for 13 and 14 is just a guess, we don't have enough logs. */
+	if (new_channel->hw_value == 13 || new_channel->hw_value == 14)
+		spuravoid = 1;
+	bcma_core_pll_ctl(core, B43_BCMA_CLKCTLST_PHY_PLL_REQ, 0, false);
+	bcma_pmu_spuravoid_pllupdate(&core->bus->drv_cc, spuravoid);
+	bcma_core_pll_ctl(core,
+			  B43_BCMA_CLKCTLST_80211_PLL_REQ |
+			  B43_BCMA_CLKCTLST_PHY_PLL_REQ,
+			  B43_BCMA_CLKCTLST_80211_PLL_ST |
+			  B43_BCMA_CLKCTLST_PHY_PLL_ST, false);
+
+	/* Values has been taken from wlc_bmac_switch_macfreq comments */
+	switch (spuravoid) {
+	case 2: /* 126MHz */
+		tmp = 0x2082;
+		break;
+	case 1: /* 123MHz */
+		tmp = 0x5341;
+		break;
+	default: /* 120MHz */
+		tmp = 0x8889;
+	}
+
+	b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, tmp);
+	b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8);
+
+	/* TODO: reset PLL */
+
+	if (spuravoid)
+		b43_phy_set(dev, B43_PHY_HT_BBCFG, B43_PHY_HT_BBCFG_RSTRX);
+	else
+		b43_phy_mask(dev, B43_PHY_HT_BBCFG,
+				~B43_PHY_HT_BBCFG_RSTRX & 0xFFFF);
+
+	b43_phy_ht_reset_cca(dev);
+}
+
 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) {
@@ -264,25 +729,20 @@ static void b43_phy_ht_channel_setup(struct b43_wldev *dev,
 	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 */
+	if (new_channel->hw_value == 14) {
+		b43_phy_ht_classifier(dev, B43_PHY_HT_CLASS_CTL_OFDM_EN, 0);
+		b43_phy_set(dev, B43_PHY_HT_TEST, 0x0800);
+	} else {
+		b43_phy_ht_classifier(dev, B43_PHY_HT_CLASS_CTL_OFDM_EN,
+				      B43_PHY_HT_CLASS_CTL_OFDM_EN);
+		if (new_channel->band == IEEE80211_BAND_2GHZ)
+			b43_phy_mask(dev, B43_PHY_HT_TEST, ~0x840);
+	}
 
-	/* TODO: separated function? */
-	for (i = 0; i < 3; i++) {
-		u16 mask;
-		u32 tmp = b43_httab_read(dev, B43_HTTAB32(26, 0xE8));
+	if (1) /* TODO: On N it's for early devices only, what about HT? */
+		b43_phy_ht_tx_power_fix(dev);
 
-		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_ht_spur_avoid(dev, new_channel);
 
 	b43_phy_write(dev, 0x017e, 0x3830);
 }
@@ -337,14 +797,29 @@ 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;
+	int i;
 
 	memset(phy_ht, 0, sizeof(*phy_ht));
+
+	phy_ht->tx_pwr_ctl = true;
+	for (i = 0; i < 3; i++)
+		phy_ht->tx_pwr_idx[i] = B43_PHY_HT_TXPCTL_CMD_C1_INIT + 1;
+
+	for (i = 0; i < 3; i++)
+		phy_ht->bb_mult_save[i] = -1;
 }
 
 static int b43_phy_ht_op_init(struct b43_wldev *dev)
 {
+	struct b43_phy_ht *phy_ht = dev->phy.ht;
 	u16 tmp;
 	u16 clip_state[3];
+	bool saved_tx_pwr_ctl;
+
+	if (dev->dev->bus_type != B43_BUS_BCMA) {
+		b43err(dev->wl, "HT-PHY is supported only on BCMA bus!\n");
+		return -EOPNOTSUPP;
+	}
 
 	b43_phy_ht_tables_init(dev);
 
@@ -357,9 +832,9 @@ static int b43_phy_ht_op_init(struct b43_wldev *dev)
 
 	b43_phy_mask(dev, B43_PHY_EXTG(0), ~0x3);
 
-	b43_phy_write(dev, B43_PHY_HT_AFE_CTL1, 0);
-	b43_phy_write(dev, B43_PHY_HT_AFE_CTL3, 0);
-	b43_phy_write(dev, B43_PHY_HT_AFE_CTL5, 0);
+	b43_phy_write(dev, B43_PHY_HT_AFE_C1_OVER, 0);
+	b43_phy_write(dev, B43_PHY_HT_AFE_C2_OVER, 0);
+	b43_phy_write(dev, B43_PHY_HT_AFE_C3_OVER, 0);
 
 	b43_phy_write(dev, B43_PHY_EXTG(0x103), 0x20);
 	b43_phy_write(dev, B43_PHY_EXTG(0x101), 0x20);
@@ -371,8 +846,11 @@ static int b43_phy_ht_op_init(struct b43_wldev *dev)
 	if (0) /* TODO: condition */
 		; /* TODO: PHY op on reg 0x217 */
 
-	b43_phy_read(dev, 0xb0); /* TODO: what for? */
-	b43_phy_set(dev, 0xb0, 0x1);
+	if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ)
+		b43_phy_ht_classifier(dev, B43_PHY_HT_CLASS_CTL_CCK_EN, 0);
+	else
+		b43_phy_ht_classifier(dev, B43_PHY_HT_CLASS_CTL_CCK_EN,
+				      B43_PHY_HT_CLASS_CTL_CCK_EN);
 
 	b43_phy_set(dev, 0xb1, 0x91);
 	b43_phy_write(dev, 0x32f, 0x0003);
@@ -448,12 +926,13 @@ static int b43_phy_ht_op_init(struct b43_wldev *dev)
 
 	b43_mac_phy_clock_set(dev, true);
 
+	b43_phy_ht_pa_override(dev, false);
 	b43_phy_ht_force_rf_sequence(dev, B43_PHY_HT_RF_SEQ_TRIG_RX2TX);
 	b43_phy_ht_force_rf_sequence(dev, B43_PHY_HT_RF_SEQ_TRIG_RST2RX);
-
-	/* TODO: PHY op on reg 0xb0 */
+	b43_phy_ht_pa_override(dev, true);
 
 	/* TODO: Should we restore it? Or store it in global PHY info? */
+	b43_phy_ht_classifier(dev, 0, 0);
 	b43_phy_ht_read_clip_detection(dev, clip_state);
 
 	if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
@@ -462,6 +941,13 @@ static int b43_phy_ht_op_init(struct b43_wldev *dev)
 	b43_httab_write_bulk(dev, B43_HTTAB32(0x1a, 0xc0),
 			B43_HTTAB_1A_C0_LATE_SIZE, b43_httab_0x1a_0xc0_late);
 
+	saved_tx_pwr_ctl = phy_ht->tx_pwr_ctl;
+	b43_phy_ht_tx_power_fix(dev);
+	b43_phy_ht_tx_power_ctl(dev, false);
+	b43_phy_ht_tx_power_ctl_idle_tssi(dev);
+	b43_phy_ht_tx_power_ctl_setup(dev);
+	b43_phy_ht_tx_power_ctl(dev, saved_tx_pwr_ctl);
+
 	return 0;
 }
 
@@ -506,19 +992,19 @@ static void b43_phy_ht_op_software_rfkill(struct b43_wldev *dev,
 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);
+		b43_phy_write(dev, B43_PHY_HT_AFE_C1, 0x00cd);
+		b43_phy_write(dev, B43_PHY_HT_AFE_C1_OVER, 0x0000);
+		b43_phy_write(dev, B43_PHY_HT_AFE_C2, 0x00cd);
+		b43_phy_write(dev, B43_PHY_HT_AFE_C2_OVER, 0x0000);
+		b43_phy_write(dev, B43_PHY_HT_AFE_C3, 0x00cd);
+		b43_phy_write(dev, B43_PHY_HT_AFE_C3_OVER, 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);
+		b43_phy_write(dev, B43_PHY_HT_AFE_C1_OVER, 0x07ff);
+		b43_phy_write(dev, B43_PHY_HT_AFE_C1, 0x00fd);
+		b43_phy_write(dev, B43_PHY_HT_AFE_C2_OVER, 0x07ff);
+		b43_phy_write(dev, B43_PHY_HT_AFE_C2, 0x00fd);
+		b43_phy_write(dev, B43_PHY_HT_AFE_C3_OVER, 0x07ff);
+		b43_phy_write(dev, B43_PHY_HT_AFE_C3, 0x00fd);
 	}
 }
 
diff --git a/drivers/net/wireless/b43/phy_ht.h b/drivers/net/wireless/b43/phy_ht.h
index 6544c42..9b2408e 100644
--- a/drivers/net/wireless/b43/phy_ht.h
+++ b/drivers/net/wireless/b43/phy_ht.h
@@ -12,18 +12,60 @@
 #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_CLASS_CTL			0x0B0 /* Classifier control */
+#define  B43_PHY_HT_CLASS_CTL_CCK_EN		0x0001 /* CCK enable */
+#define  B43_PHY_HT_CLASS_CTL_OFDM_EN		0x0002 /* OFDM enable */
+#define  B43_PHY_HT_CLASS_CTL_WAITED_EN		0x0004 /* Waited enable */
+#define B43_PHY_HT_IQLOCAL_CMDGCTL		0x0C2	/* I/Q LO cal command G control */
+#define B43_PHY_HT_SAMP_CMD			0x0C3	/* Sample command */
+#define  B43_PHY_HT_SAMP_CMD_STOP		0x0002	/* Stop */
+#define B43_PHY_HT_SAMP_LOOP_CNT		0x0C4	/* Sample loop count */
+#define B43_PHY_HT_SAMP_WAIT_CNT		0x0C5	/* Sample wait count */
+#define B43_PHY_HT_SAMP_DEP_CNT			0x0C6	/* Sample depth count */
+#define B43_PHY_HT_SAMP_STAT			0x0C7	/* Sample status */
+#define B43_PHY_HT_TSSIMODE			0x122	/* TSSI mode */
+#define  B43_PHY_HT_TSSIMODE_EN			0x0001	/* TSSI enable */
+#define  B43_PHY_HT_TSSIMODE_PDEN		0x0002	/* Power det enable */
 #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_TXPCTL_CMD_C1		0x1E7	/* TX power control command */
+#define  B43_PHY_HT_TXPCTL_CMD_C1_INIT		0x007F	/* Init */
+#define  B43_PHY_HT_TXPCTL_CMD_C1_COEFF		0x2000	/* Power control coefficients */
+#define  B43_PHY_HT_TXPCTL_CMD_C1_HWPCTLEN	0x4000	/* Hardware TX power control enable */
+#define  B43_PHY_HT_TXPCTL_CMD_C1_PCTLEN	0x8000	/* TX power control enable */
+#define B43_PHY_HT_TXPCTL_N			0x1E8	/* TX power control N num */
+#define  B43_PHY_HT_TXPCTL_N_TSSID		0x00FF	/* N TSSI delay */
+#define  B43_PHY_HT_TXPCTL_N_TSSID_SHIFT	0
+#define  B43_PHY_HT_TXPCTL_N_NPTIL2		0x0700	/* N PT integer log2 */
+#define  B43_PHY_HT_TXPCTL_N_NPTIL2_SHIFT	8
+#define B43_PHY_HT_TXPCTL_IDLE_TSSI		0x1E9	/* TX power control idle TSSI */
+#define  B43_PHY_HT_TXPCTL_IDLE_TSSI_C1		0x003F
+#define  B43_PHY_HT_TXPCTL_IDLE_TSSI_C1_SHIFT	0
+#define  B43_PHY_HT_TXPCTL_IDLE_TSSI_C2		0x3F00
+#define  B43_PHY_HT_TXPCTL_IDLE_TSSI_C2_SHIFT	8
+#define  B43_PHY_HT_TXPCTL_IDLE_TSSI_BINF	0x8000	/* Raw TSSI offset bin format */
+#define B43_PHY_HT_TXPCTL_TARG_PWR		0x1EA	/* TX power control target power */
+#define  B43_PHY_HT_TXPCTL_TARG_PWR_C1		0x00FF	/* Power 0 */
+#define  B43_PHY_HT_TXPCTL_TARG_PWR_C1_SHIFT	0
+#define  B43_PHY_HT_TXPCTL_TARG_PWR_C2		0xFF00	/* Power 1 */
+#define  B43_PHY_HT_TXPCTL_TARG_PWR_C2_SHIFT	8
+#define B43_PHY_HT_TXPCTL_CMD_C2		0x222
+#define  B43_PHY_HT_TXPCTL_CMD_C2_INIT		0x007F
+#define B43_PHY_HT_RSSI_C1			0x219
+#define B43_PHY_HT_RSSI_C2			0x21A
+#define B43_PHY_HT_RSSI_C3			0x21B
 
 #define B43_PHY_HT_C1_CLIP1THRES		B43_PHY_OFDM(0x00E)
 #define B43_PHY_HT_C2_CLIP1THRES		B43_PHY_OFDM(0x04E)
 #define B43_PHY_HT_C3_CLIP1THRES		B43_PHY_OFDM(0x08E)
 
 #define B43_PHY_HT_RF_SEQ_MODE			B43_PHY_EXTG(0x000)
+#define  B43_PHY_HT_RF_SEQ_MODE_CA_OVER		0x0001	/* Core active override */
+#define  B43_PHY_HT_RF_SEQ_MODE_TR_OVER		0x0002	/* Trigger override */
 #define B43_PHY_HT_RF_SEQ_TRIG			B43_PHY_EXTG(0x003)
 #define  B43_PHY_HT_RF_SEQ_TRIG_RX2TX		0x0001 /* RX2TX */
 #define  B43_PHY_HT_RF_SEQ_TRIG_TX2RX		0x0002 /* TX2RX */
@@ -36,12 +78,27 @@
 
 #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)
+#define B43_PHY_HT_RF_CTL_INT_C1		B43_PHY_EXTG(0x04c)
+#define B43_PHY_HT_RF_CTL_INT_C2		B43_PHY_EXTG(0x06c)
+#define B43_PHY_HT_RF_CTL_INT_C3		B43_PHY_EXTG(0x08c)
+
+#define B43_PHY_HT_AFE_C1_OVER			B43_PHY_EXTG(0x110)
+#define B43_PHY_HT_AFE_C1			B43_PHY_EXTG(0x111)
+#define B43_PHY_HT_AFE_C2_OVER			B43_PHY_EXTG(0x114)
+#define B43_PHY_HT_AFE_C2			B43_PHY_EXTG(0x115)
+#define B43_PHY_HT_AFE_C3_OVER			B43_PHY_EXTG(0x118)
+#define B43_PHY_HT_AFE_C3			B43_PHY_EXTG(0x119)
+
+#define B43_PHY_HT_TXPCTL_CMD_C3		B43_PHY_EXTG(0x164)
+#define  B43_PHY_HT_TXPCTL_CMD_C3_INIT		0x007F
+#define B43_PHY_HT_TXPCTL_IDLE_TSSI2		B43_PHY_EXTG(0x165)	/* TX power control idle TSSI */
+#define  B43_PHY_HT_TXPCTL_IDLE_TSSI2_C3	0x003F
+#define  B43_PHY_HT_TXPCTL_IDLE_TSSI2_C3_SHIFT	0
+#define B43_PHY_HT_TXPCTL_TARG_PWR2		B43_PHY_EXTG(0x166)	/* TX power control target power */
+#define  B43_PHY_HT_TXPCTL_TARG_PWR2_C3		0x00FF
+#define  B43_PHY_HT_TXPCTL_TARG_PWR2_C3_SHIFT	0
+
+#define B43_PHY_HT_TEST				B43_PHY_N_BMODE(0x00A)
 
 
 /* Values for PHY registers used on channel switching */
@@ -56,6 +113,14 @@ struct b43_phy_ht_channeltab_e_phy {
 
 
 struct b43_phy_ht {
+	u16 rf_ctl_int_save[3];
+
+	bool tx_pwr_ctl;
+	u8 tx_pwr_idx[3];
+
+	s32 bb_mult_save[3];
+
+	u8 idle_tssi[3];
 };
 
 
diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c
index 3ae2856..5ed352d 100644
--- a/drivers/net/wireless/b43/phy_lp.c
+++ b/drivers/net/wireless/b43/phy_lp.c
@@ -104,14 +104,8 @@ static void lpphy_read_band_sprom(struct b43_wldev *dev)
 		maxpwr = sprom->maxpwr_bg;
 		lpphy->max_tx_pwr_med_band = maxpwr;
 		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(sprom->revision < 8);
-		ofdmpo = sprom->ofdm2gpo;
 		if (cckpo) {
+			ofdmpo = sprom->ofdm2gpo;
 			for (i = 0; i < 4; i++) {
 				lpphy->tx_max_rate[i] =
 					maxpwr - (ofdmpo & 0xF) * 2;
@@ -124,11 +118,11 @@ static void lpphy_read_band_sprom(struct b43_wldev *dev)
 				ofdmpo >>= 4;
 			}
 		} else {
-			ofdmpo &= 0xFF;
+			u8 opo = sprom->opo;
 			for (i = 0; i < 4; i++)
 				lpphy->tx_max_rate[i] = maxpwr;
 			for (i = 4; i < 15; i++)
-				lpphy->tx_max_rate[i] = maxpwr - ofdmpo;
+				lpphy->tx_max_rate[i] = maxpwr - opo;
 		}
 	} else { /* 5GHz */
 		lpphy->tx_isolation_low_band = sprom->tri5gl;
diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c
index 3c35382..f9339e7 100644
--- a/drivers/net/wireless/b43/phy_n.c
+++ b/drivers/net/wireless/b43/phy_n.c
@@ -1564,7 +1564,7 @@ static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev)
 	u16 clip_off[2] = { 0xFFFF, 0xFFFF };
 
 	u8 vcm_final = 0;
-	s8 offset[4];
+	s32 offset[4];
 	s32 results[8][4] = { };
 	s32 results_min[4] = { };
 	s32 poll_results[4] = { };
@@ -1615,7 +1615,7 @@ static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev)
 		}
 		for (i = 0; i < 4; i += 2) {
 			s32 curr;
-			s32 mind = 40;
+			s32 mind = 0x100000;
 			s32 minpoll = 249;
 			u8 minvcm = 0;
 			if (2 * core != i)
@@ -1732,7 +1732,7 @@ static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type)
 	u8 regs_save_radio[2];
 	u16 regs_save_phy[2];
 
-	s8 offset[4];
+	s32 offset[4];
 	u8 core;
 	u8 rail;
 
@@ -1799,7 +1799,7 @@ static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type)
 	}
 
 	for (i = 0; i < 4; i++) {
-		s32 mind = 40;
+		s32 mind = 0x100000;
 		u8 minvcm = 0;
 		s32 minpoll = 249;
 		s32 curr;
@@ -2789,10 +2789,6 @@ static void b43_nphy_iq_cal_gain_params(struct b43_wldev *dev, u16 core,
  * Tx and Rx
  **************************************************/
 
-void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna)
-{//TODO
-}
-
 static void b43_nphy_op_adjust_txpower(struct b43_wldev *dev)
 {//TODO
 }
@@ -4892,7 +4888,7 @@ static void b43_nphy_superswitch_init(struct b43_wldev *dev, bool init)
 }
 
 /* http://bcm-v4.sipsolutions.net/802.11/PHY/Init/N */
-int b43_phy_initn(struct b43_wldev *dev)
+static int b43_phy_initn(struct b43_wldev *dev)
 {
 	struct ssb_sprom *sprom = dev->dev->bus_sprom;
 	struct b43_phy *phy = &dev->phy;
diff --git a/drivers/net/wireless/b43/radio_2056.c b/drivers/net/wireless/b43/radio_2056.c
index ce037fb..b4fd934 100644
--- a/drivers/net/wireless/b43/radio_2056.c
+++ b/drivers/net/wireless/b43/radio_2056.c
@@ -2980,7 +2980,7 @@ static const struct b2056_inittab_entry b2056_inittab_rev8_rx[] = {
 	.rx		= prefix##_rx,			\
 	.rx_length	= ARRAY_SIZE(prefix##_rx)
 
-struct b2056_inittabs_pts b2056_inittabs[] = {
+static const struct b2056_inittabs_pts b2056_inittabs[] = {
 	[3] = { INITTABSPTS(b2056_inittab_rev3) },
 	[4] = { INITTABSPTS(b2056_inittab_rev4) },
 	[5] = { INITTABSPTS(b2056_inittab_rev5) },
@@ -9035,7 +9035,7 @@ static void b2056_upload_inittab(struct b43_wldev *dev, bool ghz5,
 void b2056_upload_inittabs(struct b43_wldev *dev,
 			   bool ghz5, bool ignore_uploadflag)
 {
-	struct b2056_inittabs_pts *pts;
+	const struct b2056_inittabs_pts *pts;
 
 	if (dev->phy.rev >= ARRAY_SIZE(b2056_inittabs)) {
 		B43_WARN_ON(1);
@@ -9057,7 +9057,7 @@ void b2056_upload_inittabs(struct b43_wldev *dev,
 
 void b2056_upload_syn_pll_cp2(struct b43_wldev *dev, bool ghz5)
 {
-	struct b2056_inittabs_pts *pts;
+	const struct b2056_inittabs_pts *pts;
 	const struct b2056_inittab_entry *e;
 
 	if (dev->phy.rev >= ARRAY_SIZE(b2056_inittabs)) {
diff --git a/drivers/net/wireless/b43/sdio.h b/drivers/net/wireless/b43/sdio.h
index fb63309..1e93926 100644
--- a/drivers/net/wireless/b43/sdio.h
+++ b/drivers/net/wireless/b43/sdio.h
@@ -25,12 +25,12 @@ void b43_sdio_exit(void);
 #else /* CONFIG_B43_SDIO */
 
 
-int b43_sdio_request_irq(struct b43_wldev *dev,
+static inline int b43_sdio_request_irq(struct b43_wldev *dev,
 			 void (*handler)(struct b43_wldev *dev))
 {
 	return -ENODEV;
 }
-void b43_sdio_free_irq(struct b43_wldev *dev)
+static inline void b43_sdio_free_irq(struct b43_wldev *dev)
 {
 }
 static inline int b43_sdio_init(void)
diff --git a/drivers/net/wireless/b43/tables_nphy.c b/drivers/net/wireless/b43/tables_nphy.c
index aaca60c..110510d 100644
--- a/drivers/net/wireless/b43/tables_nphy.c
+++ b/drivers/net/wireless/b43/tables_nphy.c
@@ -2800,7 +2800,7 @@ static const struct nphy_rf_control_override_rev7
 	{ 0x0010, 0x344, 0x345, 0x0010, 4 },
 };
 
-struct nphy_gain_ctl_workaround_entry nphy_gain_ctl_wa_phy6_radio11_ghz2 = {
+static struct nphy_gain_ctl_workaround_entry nphy_gain_ctl_wa_phy6_radio11_ghz2 = {
 	{ 10, 14, 19, 27 },
 	{ -5, 6, 10, 15 },
 	{ 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA },
@@ -2811,7 +2811,7 @@ struct nphy_gain_ctl_workaround_entry nphy_gain_ctl_wa_phy6_radio11_ghz2 = {
 	0x18, 0x18, 0x18,
 	0x01D0, 0x5,
 };
-struct nphy_gain_ctl_workaround_entry nphy_gain_ctl_workaround[2][4] = {
+static struct nphy_gain_ctl_workaround_entry nphy_gain_ctl_workaround[2][4] = {
 	{ /* 2GHz */
 		{ /* PHY rev 3 */
 			{ 7, 11, 16, 23 },
diff --git a/drivers/net/wireless/b43/tables_phy_lcn.c b/drivers/net/wireless/b43/tables_phy_lcn.c
index 5176363..e347b8d 100644
--- a/drivers/net/wireless/b43/tables_phy_lcn.c
+++ b/drivers/net/wireless/b43/tables_phy_lcn.c
@@ -313,7 +313,7 @@ static const u32 b43_lcntab_0x18[] = {
  * TX gain.
  **************************************************/
 
-const struct b43_lcntab_tx_gain_tbl_entry
+static const struct b43_lcntab_tx_gain_tbl_entry
 	b43_lcntab_tx_gain_tbl_2ghz_ext_pa_rev0[B43_LCNTAB_TX_GAIN_SIZE] = {
 	{ 0x03, 0x00, 0x1f, 0x0, 0x48 },
 	{ 0x03, 0x00, 0x1f, 0x0, 0x46 },
@@ -449,7 +449,7 @@ const struct b43_lcntab_tx_gain_tbl_entry
  * SW control.
  **************************************************/
 
-const u16 b43_lcntab_sw_ctl_4313_epa_rev0[] = {
+static const u16 b43_lcntab_sw_ctl_4313_epa_rev0[] = {
 	0x0002, 0x0008, 0x0004, 0x0001, 0x0002, 0x0008,
 	0x0004, 0x0001, 0x0002, 0x0008, 0x0004, 0x0001,
 	0x0002, 0x0008, 0x0004, 0x0001, 0x0002, 0x0008,
@@ -631,7 +631,7 @@ static void b43_phy_lcn_upload_static_tables(struct b43_wldev *dev)
 	lcntab_upload(dev, B43_LCNTAB32(0x18, 0), b43_lcntab_0x18);
 }
 
-void b43_phy_lcn_load_tx_gain_tab(struct b43_wldev *dev,
+static void b43_phy_lcn_load_tx_gain_tab(struct b43_wldev *dev,
 			const struct b43_lcntab_tx_gain_tbl_entry *gain_table)
 {
 	u32 i;
diff --git a/drivers/net/wireless/b43legacy/dma.c b/drivers/net/wireless/b43legacy/dma.c
index 2d3c664..faeafe2 100644
--- a/drivers/net/wireless/b43legacy/dma.c
+++ b/drivers/net/wireless/b43legacy/dma.c
@@ -334,13 +334,9 @@ static int alloc_ringmemory(struct b43legacy_dmaring *ring)
 	ring->descbase = dma_alloc_coherent(ring->dev->dev->dma_dev,
 					    B43legacy_DMA_RINGMEMSIZE,
 					    &(ring->dmabase),
-					    GFP_KERNEL);
-	if (!ring->descbase) {
-		b43legacyerr(ring->dev->wl, "DMA ringmemory allocation"
-			     " failed\n");
+					    GFP_KERNEL | __GFP_ZERO);
+	if (!ring->descbase)
 		return -ENOMEM;
-	}
-	memset(ring->descbase, 0, B43legacy_DMA_RINGMEMSIZE);
 
 	return 0;
 }
diff --git a/drivers/net/wireless/brcm80211/Kconfig b/drivers/net/wireless/brcm80211/Kconfig
index 1d92d87..747e931 100644
--- a/drivers/net/wireless/brcm80211/Kconfig
+++ b/drivers/net/wireless/brcm80211/Kconfig
@@ -12,8 +12,9 @@ config BRCMSMAC
 	select CORDIC
 	---help---
 	  This module adds support for PCIe wireless adapters based on Broadcom
-	  IEEE802.11n SoftMAC chipsets.  If you choose to build a module, it'll
-	  be called brcmsmac.ko.
+	  IEEE802.11n SoftMAC chipsets. It also has WLAN led support, which will
+	  be available if you select BCMA_DRIVER_GPIO. If you choose to build a
+	  module, the driver will be called brcmsmac.ko.
 
 config BRCMFMAC
 	tristate "Broadcom IEEE802.11n embedded FullMAC WLAN driver"
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/Makefile b/drivers/net/wireless/brcm80211/brcmfmac/Makefile
index 756e19f..598c8e2 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/Makefile
+++ b/drivers/net/wireless/brcm80211/brcmfmac/Makefile
@@ -26,6 +26,7 @@ brcmfmac-objs += \
 		wl_cfg80211.o \
 		fwil.o \
 		fweh.o \
+		fwsignal.o \
 		p2p.o \
 		dhd_cdc.o \
 		dhd_common.o \
@@ -39,3 +40,5 @@ brcmfmac-$(CONFIG_BRCMFMAC_USB) += \
 		usb.o
 brcmfmac-$(CONFIG_BRCMDBG) += \
 		dhd_dbg.o
+brcmfmac-$(CONFIG_BRCM_TRACING) += \
+		tracepoint.o
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
index 11fd1c7..f3149de 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
@@ -65,7 +65,7 @@ int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev)
 	u8 data;
 	unsigned long flags;
 
-	brcmf_dbg(TRACE, "Entering: irq %d\n", sdiodev->irq);
+	brcmf_dbg(SDIO, "Entering: irq %d\n", sdiodev->irq);
 
 	ret = request_irq(sdiodev->irq, brcmf_sdio_irqhandler,
 			  sdiodev->irq_flags, "brcmf_oob_intr",
@@ -102,7 +102,7 @@ int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev)
 
 int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev)
 {
-	brcmf_dbg(TRACE, "Entering\n");
+	brcmf_dbg(SDIO, "Entering\n");
 
 	sdio_claim_host(sdiodev->func[1]);
 	brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, 0, NULL);
@@ -136,7 +136,7 @@ static void brcmf_sdio_dummy_irqhandler(struct sdio_func *func)
 
 int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev)
 {
-	brcmf_dbg(TRACE, "Entering\n");
+	brcmf_dbg(SDIO, "Entering\n");
 
 	sdio_claim_host(sdiodev->func[1]);
 	sdio_claim_irq(sdiodev->func[1], brcmf_sdio_irqhandler);
@@ -148,7 +148,7 @@ int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev)
 
 int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev)
 {
-	brcmf_dbg(TRACE, "Entering\n");
+	brcmf_dbg(SDIO, "Entering\n");
 
 	sdio_claim_host(sdiodev->func[1]);
 	sdio_release_irq(sdiodev->func[2]);
@@ -253,9 +253,9 @@ u8 brcmf_sdio_regrb(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret)
 	u8 data;
 	int retval;
 
-	brcmf_dbg(INFO, "addr:0x%08x\n", addr);
+	brcmf_dbg(SDIO, "addr:0x%08x\n", addr);
 	retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, false);
-	brcmf_dbg(INFO, "data:0x%02x\n", data);
+	brcmf_dbg(SDIO, "data:0x%02x\n", data);
 
 	if (ret)
 		*ret = retval;
@@ -268,9 +268,9 @@ u32 brcmf_sdio_regrl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret)
 	u32 data;
 	int retval;
 
-	brcmf_dbg(INFO, "addr:0x%08x\n", addr);
+	brcmf_dbg(SDIO, "addr:0x%08x\n", addr);
 	retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, false);
-	brcmf_dbg(INFO, "data:0x%08x\n", data);
+	brcmf_dbg(SDIO, "data:0x%08x\n", data);
 
 	if (ret)
 		*ret = retval;
@@ -283,7 +283,7 @@ void brcmf_sdio_regwb(struct brcmf_sdio_dev *sdiodev, u32 addr,
 {
 	int retval;
 
-	brcmf_dbg(INFO, "addr:0x%08x, data:0x%02x\n", addr, data);
+	brcmf_dbg(SDIO, "addr:0x%08x, data:0x%02x\n", addr, data);
 	retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, true);
 
 	if (ret)
@@ -295,7 +295,7 @@ void brcmf_sdio_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr,
 {
 	int retval;
 
-	brcmf_dbg(INFO, "addr:0x%08x, data:0x%08x\n", addr, data);
+	brcmf_dbg(SDIO, "addr:0x%08x, data:0x%08x\n", addr, data);
 	retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, true);
 
 	if (ret)
@@ -358,7 +358,7 @@ brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
 	uint width;
 	int err = 0;
 
-	brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n",
+	brcmf_dbg(SDIO, "fun = %d, addr = 0x%x, size = %d\n",
 		  fn, addr, pkt->len);
 
 	width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
@@ -381,7 +381,7 @@ int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
 	uint width;
 	int err = 0;
 
-	brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n",
+	brcmf_dbg(SDIO, "fun = %d, addr = 0x%x, size = %d\n",
 		  fn, addr, pktq->qlen);
 
 	width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
@@ -428,7 +428,7 @@ brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
 	uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
 	int err = 0;
 
-	brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n",
+	brcmf_dbg(SDIO, "fun = %d, addr = 0x%x, size = %d\n",
 		  fn, addr, pkt->len);
 
 	/* Async not implemented yet */
@@ -492,13 +492,13 @@ int brcmf_sdcard_rwdata(struct brcmf_sdio_dev *sdiodev, uint rw, u32 addr,
 int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn)
 {
 	char t_func = (char)fn;
-	brcmf_dbg(TRACE, "Enter\n");
+	brcmf_dbg(SDIO, "Enter\n");
 
 	/* issue abort cmd52 command through F0 */
 	brcmf_sdioh_request_byte(sdiodev, SDIOH_WRITE, SDIO_FUNC_0,
 				 SDIO_CCCR_ABORT, &t_func);
 
-	brcmf_dbg(TRACE, "Exit\n");
+	brcmf_dbg(SDIO, "Exit\n");
 	return 0;
 }
 
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
index d92d373..7165489 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
@@ -139,7 +139,7 @@ int brcmf_sdioh_request_byte(struct brcmf_sdio_dev *sdiodev, uint rw, uint func,
 {
 	int err_ret;
 
-	brcmf_dbg(INFO, "rw=%d, func=%d, addr=0x%05x\n", rw, func, regaddr);
+	brcmf_dbg(SDIO, "rw=%d, func=%d, addr=0x%05x\n", rw, func, regaddr);
 
 	brcmf_pm_resume_wait(sdiodev, &sdiodev->request_byte_wait);
 	if (brcmf_pm_resume_error(sdiodev))
@@ -179,7 +179,7 @@ int brcmf_sdioh_request_word(struct brcmf_sdio_dev *sdiodev,
 		return -EINVAL;
 	}
 
-	brcmf_dbg(INFO, "rw=%d, func=%d, addr=0x%05x, nbytes=%d\n",
+	brcmf_dbg(SDIO, "rw=%d, func=%d, addr=0x%05x, nbytes=%d\n",
 		  rw, func, addr, nbytes);
 
 	brcmf_pm_resume_wait(sdiodev, &sdiodev->request_word_wait);
@@ -252,7 +252,7 @@ brcmf_sdioh_request_chain(struct brcmf_sdio_dev *sdiodev, uint fix_inc,
 
 	struct sk_buff *pkt;
 
-	brcmf_dbg(TRACE, "Enter\n");
+	brcmf_dbg(SDIO, "Enter\n");
 
 	brcmf_pm_resume_wait(sdiodev, &sdiodev->request_chain_wait);
 	if (brcmf_pm_resume_error(sdiodev))
@@ -270,7 +270,7 @@ brcmf_sdioh_request_chain(struct brcmf_sdio_dev *sdiodev, uint fix_inc,
 				  write ? "TX" : "RX", pkt, SGCount, addr,
 				  pkt_len, err_ret);
 		} else {
-			brcmf_dbg(TRACE, "%s xfr'd %p[%d], addr=0x%05x, len=%d\n",
+			brcmf_dbg(SDIO, "%s xfr'd %p[%d], addr=0x%05x, len=%d\n",
 				  write ? "TX" : "RX", pkt, SGCount, addr,
 				  pkt_len);
 		}
@@ -280,7 +280,7 @@ brcmf_sdioh_request_chain(struct brcmf_sdio_dev *sdiodev, uint fix_inc,
 		SGCount++;
 	}
 
-	brcmf_dbg(TRACE, "Exit\n");
+	brcmf_dbg(SDIO, "Exit\n");
 	return err_ret;
 }
 
@@ -295,7 +295,7 @@ int brcmf_sdioh_request_buffer(struct brcmf_sdio_dev *sdiodev,
 	uint pkt_len;
 	bool fifo = (fix_inc == SDIOH_DATA_FIX);
 
-	brcmf_dbg(TRACE, "Enter\n");
+	brcmf_dbg(SDIO, "Enter\n");
 
 	if (pkt == NULL)
 		return -EINVAL;
@@ -314,7 +314,7 @@ int brcmf_sdioh_request_buffer(struct brcmf_sdio_dev *sdiodev,
 		brcmf_err("%s FAILED %p, addr=0x%05x, pkt_len=%d, ERR=0x%08x\n",
 			  write ? "TX" : "RX", pkt, addr, pkt_len, status);
 	} else {
-		brcmf_dbg(TRACE, "%s xfr'd %p, addr=0x%05x, len=%d\n",
+		brcmf_dbg(SDIO, "%s xfr'd %p, addr=0x%05x, len=%d\n",
 			  write ? "TX" : "RX", pkt, addr, pkt_len);
 	}
 
@@ -350,12 +350,12 @@ static int brcmf_sdioh_enablefuncs(struct brcmf_sdio_dev *sdiodev)
 	u32 fbraddr;
 	u8 func;
 
-	brcmf_dbg(TRACE, "\n");
+	brcmf_dbg(SDIO, "\n");
 
 	/* Get the Card's common CIS address */
 	sdiodev->func_cis_ptr[0] = brcmf_sdioh_get_cisaddr(sdiodev,
 							   SDIO_CCCR_CIS);
-	brcmf_dbg(INFO, "Card's Common CIS Ptr = 0x%x\n",
+	brcmf_dbg(SDIO, "Card's Common CIS Ptr = 0x%x\n",
 		  sdiodev->func_cis_ptr[0]);
 
 	/* Get the Card's function CIS (for each function) */
@@ -363,7 +363,7 @@ static int brcmf_sdioh_enablefuncs(struct brcmf_sdio_dev *sdiodev)
 	     func <= sdiodev->num_funcs; func++, fbraddr += SDIOD_FBR_SIZE) {
 		sdiodev->func_cis_ptr[func] =
 		    brcmf_sdioh_get_cisaddr(sdiodev, SDIO_FBR_CIS + fbraddr);
-		brcmf_dbg(INFO, "Function %d CIS Ptr = 0x%x\n",
+		brcmf_dbg(SDIO, "Function %d CIS Ptr = 0x%x\n",
 			  func, sdiodev->func_cis_ptr[func]);
 	}
 
@@ -382,7 +382,7 @@ int brcmf_sdioh_attach(struct brcmf_sdio_dev *sdiodev)
 {
 	int err_ret = 0;
 
-	brcmf_dbg(TRACE, "\n");
+	brcmf_dbg(SDIO, "\n");
 
 	sdiodev->num_funcs = 2;
 
@@ -404,13 +404,13 @@ int brcmf_sdioh_attach(struct brcmf_sdio_dev *sdiodev)
 
 out:
 	sdio_release_host(sdiodev->func[1]);
-	brcmf_dbg(TRACE, "Done\n");
+	brcmf_dbg(SDIO, "Done\n");
 	return err_ret;
 }
 
 void brcmf_sdioh_detach(struct brcmf_sdio_dev *sdiodev)
 {
-	brcmf_dbg(TRACE, "\n");
+	brcmf_dbg(SDIO, "\n");
 
 	/* Disable Function 2 */
 	sdio_claim_host(sdiodev->func[2]);
@@ -458,11 +458,11 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
 	struct brcmf_sdio_dev *sdiodev;
 	struct brcmf_bus *bus_if;
 
-	brcmf_dbg(TRACE, "Enter\n");
-	brcmf_dbg(TRACE, "Class=%x\n", func->class);
-	brcmf_dbg(TRACE, "sdio vendor ID: 0x%04x\n", func->vendor);
-	brcmf_dbg(TRACE, "sdio device ID: 0x%04x\n", func->device);
-	brcmf_dbg(TRACE, "Function#: %d\n", func->num);
+	brcmf_dbg(SDIO, "Enter\n");
+	brcmf_dbg(SDIO, "Class=%x\n", func->class);
+	brcmf_dbg(SDIO, "sdio vendor ID: 0x%04x\n", func->vendor);
+	brcmf_dbg(SDIO, "sdio device ID: 0x%04x\n", func->device);
+	brcmf_dbg(SDIO, "Function#: %d\n", func->num);
 
 	/* Consume func num 1 but dont do anything with it. */
 	if (func->num == 1)
@@ -501,13 +501,13 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
 	if (err)
 		goto fail;
 
-	brcmf_dbg(TRACE, "F2 found, calling brcmf_sdio_probe...\n");
+	brcmf_dbg(SDIO, "F2 found, calling brcmf_sdio_probe...\n");
 	err = brcmf_sdio_probe(sdiodev);
 	if (err) {
 		brcmf_err("F2 error, probe failed %d...\n", err);
 		goto fail;
 	}
-	brcmf_dbg(TRACE, "F2 init completed...\n");
+	brcmf_dbg(SDIO, "F2 init completed...\n");
 	return 0;
 
 fail:
@@ -523,10 +523,10 @@ static void brcmf_ops_sdio_remove(struct sdio_func *func)
 	struct brcmf_bus *bus_if;
 	struct brcmf_sdio_dev *sdiodev;
 
-	brcmf_dbg(TRACE, "Enter\n");
-	brcmf_dbg(TRACE, "sdio vendor ID: 0x%04x\n", func->vendor);
-	brcmf_dbg(TRACE, "sdio device ID: 0x%04x\n", func->device);
-	brcmf_dbg(TRACE, "Function: %d\n", func->num);
+	brcmf_dbg(SDIO, "Enter\n");
+	brcmf_dbg(SDIO, "sdio vendor ID: 0x%04x\n", func->vendor);
+	brcmf_dbg(SDIO, "sdio device ID: 0x%04x\n", func->device);
+	brcmf_dbg(SDIO, "Function: %d\n", func->num);
 
 	if (func->num != 1 && func->num != 2)
 		return;
@@ -543,7 +543,7 @@ static void brcmf_ops_sdio_remove(struct sdio_func *func)
 		kfree(sdiodev);
 	}
 
-	brcmf_dbg(TRACE, "Exit\n");
+	brcmf_dbg(SDIO, "Exit\n");
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -554,7 +554,7 @@ static int brcmf_sdio_suspend(struct device *dev)
 	struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
 	int ret = 0;
 
-	brcmf_dbg(TRACE, "\n");
+	brcmf_dbg(SDIO, "\n");
 
 	atomic_set(&sdiodev->suspend, true);
 
@@ -645,7 +645,7 @@ static struct platform_driver brcmf_sdio_pd = {
 
 void brcmf_sdio_exit(void)
 {
-	brcmf_dbg(TRACE, "Enter\n");
+	brcmf_dbg(SDIO, "Enter\n");
 
 	sdio_unregister_driver(&brcmf_sdmmc_driver);
 
@@ -656,7 +656,7 @@ void brcmf_sdio_init(void)
 {
 	int ret;
 
-	brcmf_dbg(TRACE, "Enter\n");
+	brcmf_dbg(SDIO, "Enter\n");
 
 	ret = platform_driver_register(&brcmf_sdio_pd);
 
@@ -666,7 +666,7 @@ void brcmf_sdio_init(void)
 #else
 void brcmf_sdio_exit(void)
 {
-	brcmf_dbg(TRACE, "Enter\n");
+	brcmf_dbg(SDIO, "Enter\n");
 
 	sdio_unregister_driver(&brcmf_sdmmc_driver);
 }
@@ -675,7 +675,7 @@ void brcmf_sdio_init(void)
 {
 	int ret;
 
-	brcmf_dbg(TRACE, "Enter\n");
+	brcmf_dbg(SDIO, "Enter\n");
 
 	ret = sdio_register_driver(&brcmf_sdmmc_driver);
 
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
index ef6f23b..ef5e3a9 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
@@ -72,6 +72,7 @@
 #define BRCMF_C_SET_WSEC			134
 #define BRCMF_C_GET_PHY_NOISE			135
 #define BRCMF_C_GET_BSS_INFO			136
+#define BRCMF_C_GET_BANDLIST			140
 #define BRCMF_C_SET_SCB_TIMEOUT			158
 #define BRCMF_C_GET_PHYLIST			180
 #define BRCMF_C_SET_SCAN_CHANNEL_TIME		185
@@ -475,6 +476,11 @@ struct brcmf_sta_info_le {
 	__le32	rx_decrypt_failures;	/* # of packet decrypted failed */
 };
 
+struct brcmf_chanspec_list {
+	__le32	count;		/* # of entries */
+	__le32	element[1];	/* variable length uint32 list */
+};
+
 /*
  * WLC_E_PROBRESP_MSG
  * WLC_E_P2P_PROBREQ_MSG
@@ -501,6 +507,7 @@ struct brcmf_dcmd {
 /* Forward decls for struct brcmf_pub (see below) */
 struct brcmf_proto;	/* device communication protocol info */
 struct brcmf_cfg80211_dev; /* cfg80211 device info */
+struct brcmf_fws_info; /* firmware signalling info */
 
 /* Common structure for module and instance linkage */
 struct brcmf_pub {
@@ -527,6 +534,10 @@ struct brcmf_pub {
 	unsigned char proto_buf[BRCMF_DCMD_MAXLEN];
 
 	struct brcmf_fweh_info fweh;
+
+	bool fw_signals;
+	struct brcmf_fws_info *fws;
+	spinlock_t fws_spinlock;
 #ifdef DEBUG
 	struct dentry *dbgfs_dir;
 #endif
@@ -539,8 +550,22 @@ struct brcmf_if_event {
 	u8 bssidx;
 };
 
-/* forward declaration */
+/* forward declarations */
 struct brcmf_cfg80211_vif;
+struct brcmf_fws_mac_descriptor;
+
+/**
+ * enum brcmf_netif_stop_reason - reason for stopping netif queue.
+ *
+ * @BRCMF_NETIF_STOP_REASON_FWS_FC:
+ *	netif stopped due to firmware signalling flow control.
+ * @BRCMF_NETIF_STOP_REASON_BLOCK_BUS:
+ *	netif stopped due to bus blocking.
+ */
+enum brcmf_netif_stop_reason {
+	BRCMF_NETIF_STOP_REASON_FWS_FC = 1,
+	BRCMF_NETIF_STOP_REASON_BLOCK_BUS = 2
+};
 
 /**
  * struct brcmf_if - interface control information.
@@ -549,9 +574,13 @@ struct brcmf_cfg80211_vif;
  * @vif: points to cfg80211 specific interface information.
  * @ndev: associated network device.
  * @stats: interface specific network statistics.
+ * @setmacaddr_work: worker object for setting mac address.
+ * @multicast_work: worker object for multicast provisioning.
+ * @fws_desc: interface specific firmware-signalling descriptor.
  * @ifidx: interface index in device firmware.
  * @bssidx: index of bss associated with this interface.
  * @mac_addr: assigned mac address.
+ * @netif_stop: bitmap indicates reason why netif queues are stopped.
  * @pend_8021x_cnt: tracks outstanding number of 802.1x frames.
  * @pend_8021x_wait: used for signalling change in count.
  */
@@ -562,9 +591,11 @@ struct brcmf_if {
 	struct net_device_stats stats;
 	struct work_struct setmacaddr_work;
 	struct work_struct multicast_work;
+	struct brcmf_fws_mac_descriptor *fws_desc;
 	int ifidx;
 	s32 bssidx;
 	u8 mac_addr[ETH_ALEN];
+	u8 netif_stop;
 	atomic_t pend_8021x_cnt;
 	wait_queue_head_t pend_8021x_wait;
 };
@@ -582,13 +613,17 @@ extern int brcmf_proto_cdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd,
 				    void *buf, uint len);
 
 /* Remove any protocol-specific data header. */
-extern int brcmf_proto_hdrpull(struct brcmf_pub *drvr, u8 *ifidx,
+extern int brcmf_proto_hdrpull(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx,
 			       struct sk_buff *rxp);
 
 extern int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked);
 extern struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx,
 				     s32 ifidx, char *name, u8 *mac_addr);
 extern void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx);
+void brcmf_txflowblock_if(struct brcmf_if *ifp,
+			  enum brcmf_netif_stop_reason reason, bool state);
 extern u32 brcmf_get_chip_info(struct brcmf_if *ifp);
+extern void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp,
+			     bool success);
 
 #endif				/* _BRCMF_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
index ad25c34..080395f 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
@@ -39,10 +39,12 @@ struct brcmf_bus_dcmd {
  * @txdata: send a data frame to the dongle (callee disposes skb).
  * @txctl: transmit a control request message to dongle.
  * @rxctl: receive a control response message from dongle.
+ * @gettxq: obtain a reference of bus transmit queue (optional).
  *
  * This structure provides an abstract interface towards the
  * bus specific driver. For control messages to common driver
- * will assure there is only one active transaction.
+ * will assure there is only one active transaction. Unless
+ * indicated otherwise these callbacks are mandatory.
  */
 struct brcmf_bus_ops {
 	int (*init)(struct device *dev);
@@ -50,6 +52,7 @@ struct brcmf_bus_ops {
 	int (*txdata)(struct device *dev, struct sk_buff *skb);
 	int (*txctl)(struct device *dev, unsigned char *msg, uint len);
 	int (*rxctl)(struct device *dev, unsigned char *msg, uint len);
+	struct pktq * (*gettxq)(struct device *dev);
 };
 
 /**
@@ -115,6 +118,14 @@ int brcmf_bus_rxctl(struct brcmf_bus *bus, unsigned char *msg, uint len)
 	return bus->ops->rxctl(bus->dev, msg, len);
 }
 
+static inline
+struct pktq *brcmf_bus_gettxq(struct brcmf_bus *bus)
+{
+	if (!bus->ops->gettxq)
+		return ERR_PTR(-ENOENT);
+
+	return bus->ops->gettxq(bus->dev);
+}
 /*
  * interface functions from common layer
  */
@@ -134,7 +145,7 @@ extern void brcmf_dev_reset(struct device *dev);
 /* Indication from bus module to change flow-control state */
 extern void brcmf_txflowblock(struct device *dev, bool state);
 
-/* Notify tx completion */
+/* Notify the bus has transferred the tx packet to firmware */
 extern void brcmf_txcomplete(struct device *dev, struct sk_buff *txp,
 			     bool success);
 
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c
index a2354d9..59c77aa 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c
@@ -28,6 +28,7 @@
 #include "dhd.h"
 #include "dhd_proto.h"
 #include "dhd_bus.h"
+#include "fwsignal.h"
 #include "dhd_dbg.h"
 
 struct brcmf_proto_cdc_dcmd {
@@ -71,13 +72,26 @@ struct brcmf_proto_cdc_dcmd {
 	((hdr)->flags2 = (((hdr)->flags2 & ~BDC_FLAG2_IF_MASK) | \
 	((idx) << BDC_FLAG2_IF_SHIFT)))
 
+/**
+ * struct brcmf_proto_bdc_header - BDC header format
+ *
+ * @flags: flags contain protocol and checksum info.
+ * @priority: 802.1d priority and USB flow control info (bit 4:7).
+ * @flags2: additional flags containing dongle interface index.
+ * @data_offset: start of packet data. header is following by firmware signals.
+ */
 struct brcmf_proto_bdc_header {
 	u8 flags;
-	u8 priority;	/* 802.1d Priority, 4:7 flow control info for usb */
+	u8 priority;
 	u8 flags2;
 	u8 data_offset;
 };
 
+/*
+ * maximum length of firmware signal data between
+ * the BDC header and packet data in the tx path.
+ */
+#define BRCMF_PROT_FW_SIGNAL_MAX_TXBYTES	12
 
 #define RETRIES 2 /* # of retries to retrieve matching dcmd response */
 #define BUS_HEADER_LEN	(16+64)		/* Must be atleast SDPCM_RESERVE
@@ -258,7 +272,7 @@ static void pkt_set_sum_good(struct sk_buff *skb, bool x)
 	skb->ip_summed = (x ? CHECKSUM_UNNECESSARY : CHECKSUM_NONE);
 }
 
-void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx,
+void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx, u8 offset,
 			 struct sk_buff *pktbuf)
 {
 	struct brcmf_proto_bdc_header *h;
@@ -266,7 +280,6 @@ void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx,
 	brcmf_dbg(CDC, "Enter\n");
 
 	/* Push BDC header used to convey priority for buses that don't */
-
 	skb_push(pktbuf, BDC_HEADER_LEN);
 
 	h = (struct brcmf_proto_bdc_header *)(pktbuf->data);
@@ -277,11 +290,11 @@ void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx,
 
 	h->priority = (pktbuf->priority & BDC_PRIORITY_MASK);
 	h->flags2 = 0;
-	h->data_offset = 0;
+	h->data_offset = offset;
 	BDC_SET_IF_IDX(h, ifidx);
 }
 
-int brcmf_proto_hdrpull(struct brcmf_pub *drvr, u8 *ifidx,
+int brcmf_proto_hdrpull(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx,
 			struct sk_buff *pktbuf)
 {
 	struct brcmf_proto_bdc_header *h;
@@ -290,8 +303,8 @@ int brcmf_proto_hdrpull(struct brcmf_pub *drvr, u8 *ifidx,
 
 	/* Pop BDC header used to convey priority for buses that don't */
 
-	if (pktbuf->len < BDC_HEADER_LEN) {
-		brcmf_err("rx data too short (%d < %d)\n",
+	if (pktbuf->len <= BDC_HEADER_LEN) {
+		brcmf_dbg(INFO, "rx data too short (%d <= %d)\n",
 			  pktbuf->len, BDC_HEADER_LEN);
 		return -EBADE;
 	}
@@ -328,7 +341,10 @@ int brcmf_proto_hdrpull(struct brcmf_pub *drvr, u8 *ifidx,
 	pktbuf->priority = h->priority & BDC_PRIORITY_MASK;
 
 	skb_pull(pktbuf, BDC_HEADER_LEN);
-	skb_pull(pktbuf, h->data_offset << 2);
+	if (do_fws)
+		brcmf_fws_hdrpull(drvr, *ifidx, h->data_offset << 2, pktbuf);
+	else
+		skb_pull(pktbuf, h->data_offset << 2);
 
 	if (pktbuf->len == 0)
 		return -ENODATA;
@@ -350,7 +366,7 @@ int brcmf_proto_attach(struct brcmf_pub *drvr)
 	}
 
 	drvr->prot = cdc;
-	drvr->hdrlen += BDC_HEADER_LEN;
+	drvr->hdrlen += BDC_HEADER_LEN + BRCMF_PROT_FW_SIGNAL_MAX_TXBYTES;
 	drvr->bus_if->maxctl = BRCMF_DCMD_MAXLEN +
 			sizeof(struct brcmf_proto_cdc_dcmd) + ROUND_UP_MARGIN;
 	return 0;
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c
index 4544342..be0787c 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c
@@ -24,6 +24,7 @@
 #include "dhd_proto.h"
 #include "dhd_dbg.h"
 #include "fwil.h"
+#include "tracepoint.h"
 
 #define PKTFILTER_BUF_SIZE		128
 #define BRCMF_ARPOL_MODE		0xb	/* agent|snoop|peer_autoreply */
@@ -373,3 +374,35 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
 done:
 	return err;
 }
+
+#ifdef CONFIG_BRCM_TRACING
+void __brcmf_err(const char *func, const char *fmt, ...)
+{
+	struct va_format vaf = {
+		.fmt = fmt,
+	};
+	va_list args;
+
+	va_start(args, fmt);
+	vaf.va = &args;
+	pr_err("%s: %pV", func, &vaf);
+	trace_brcmf_err(func, &vaf);
+	va_end(args);
+}
+#endif
+#if defined(CONFIG_BRCM_TRACING) || defined(CONFIG_BRCMDBG)
+void __brcmf_dbg(u32 level, const char *func, const char *fmt, ...)
+{
+	struct va_format vaf = {
+		.fmt = fmt,
+	};
+	va_list args;
+
+	va_start(args, fmt);
+	vaf.va = &args;
+	if (brcmf_msg_level & level)
+		pr_debug("%s %pV", func, &vaf);
+	trace_brcmf_dbg(level, func, &vaf);
+	va_end(args);
+}
+#endif
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c
index 57671ed..bd16f0b 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c
@@ -22,6 +22,7 @@
 #include "dhd.h"
 #include "dhd_bus.h"
 #include "dhd_dbg.h"
+#include "tracepoint.h"
 
 static struct dentry *root_folder;
 
@@ -123,3 +124,78 @@ void brcmf_debugfs_create_sdio_count(struct brcmf_pub *drvr,
 		debugfs_create_file("counters", S_IRUGO, dentry,
 				    sdcnt, &brcmf_debugfs_sdio_counter_ops);
 }
+
+static
+ssize_t brcmf_debugfs_fws_stats_read(struct file *f, char __user *data,
+				     size_t count, loff_t *ppos)
+{
+	struct brcmf_fws_stats *fwstats = f->private_data;
+	char buf[650];
+	int res;
+
+	/* only allow read from start */
+	if (*ppos > 0)
+		return 0;
+
+	res = scnprintf(buf, sizeof(buf),
+			"header_pulls:      %u\n"
+			"header_only_pkt:   %u\n"
+			"tlv_parse_failed:  %u\n"
+			"tlv_invalid_type:  %u\n"
+			"mac_update_fails:  %u\n"
+			"pkt2bus:           %u\n"
+			"generic_error:     %u\n"
+			"rollback_success:  %u\n"
+			"rollback_failed:   %u\n"
+			"delayq_full:       %u\n"
+			"supprq_full:       %u\n"
+			"txs_indicate:      %u\n"
+			"txs_discard:       %u\n"
+			"txs_suppr_core:    %u\n"
+			"txs_suppr_ps:      %u\n"
+			"txs_tossed:        %u\n"
+			"send_pkts:         BK:%u BE:%u VO:%u VI:%u BCMC:%u\n"
+			"fifo_credits_sent: BK:%u BE:%u VO:%u VI:%u BCMC:%u\n",
+			fwstats->header_pulls,
+			fwstats->header_only_pkt,
+			fwstats->tlv_parse_failed,
+			fwstats->tlv_invalid_type,
+			fwstats->mac_update_failed,
+			fwstats->pkt2bus,
+			fwstats->generic_error,
+			fwstats->rollback_success,
+			fwstats->rollback_failed,
+			fwstats->delayq_full_error,
+			fwstats->supprq_full_error,
+			fwstats->txs_indicate,
+			fwstats->txs_discard,
+			fwstats->txs_supp_core,
+			fwstats->txs_supp_ps,
+			fwstats->txs_tossed,
+			fwstats->send_pkts[0], fwstats->send_pkts[1],
+			fwstats->send_pkts[2], fwstats->send_pkts[3],
+			fwstats->send_pkts[4],
+			fwstats->fifo_credits_sent[0],
+			fwstats->fifo_credits_sent[1],
+			fwstats->fifo_credits_sent[2],
+			fwstats->fifo_credits_sent[3],
+			fwstats->fifo_credits_sent[4]);
+
+	return simple_read_from_buffer(data, count, ppos, buf, res);
+}
+
+static const struct file_operations brcmf_debugfs_fws_stats_ops = {
+	.owner = THIS_MODULE,
+	.open = simple_open,
+	.read = brcmf_debugfs_fws_stats_read
+};
+
+void brcmf_debugfs_create_fws_stats(struct brcmf_pub *drvr,
+				    struct brcmf_fws_stats *stats)
+{
+	struct dentry *dentry =  drvr->dbgfs_dir;
+
+	if (!IS_ERR_OR_NULL(dentry))
+		debugfs_create_file("fws_stats", S_IRUGO, dentry,
+				    stats, &brcmf_debugfs_fws_stats_ops);
+}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h
index bc013cb..a6b16a1 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h
@@ -34,6 +34,7 @@
 #define BRCMF_SCAN_VAL	0x00004000
 #define BRCMF_CONN_VAL	0x00008000
 #define BRCMF_CDC_VAL	0x00010000
+#define BRCMF_SDIO_VAL	0x00020000
 
 /* set default print format */
 #undef pr_fmt
@@ -43,6 +44,7 @@
  * debugging is not selected. When debugging the driver error
  * messages are as important as other tracing or even more so.
  */
+#ifndef CONFIG_BRCM_TRACING
 #ifdef CONFIG_BRCMDBG
 #define brcmf_err(fmt, ...)	pr_err("%s: " fmt, __func__, ##__VA_ARGS__)
 #else
@@ -52,15 +54,21 @@
 			pr_err("%s: " fmt, __func__, ##__VA_ARGS__);	\
 	} while (0)
 #endif
+#else
+__printf(2, 3)
+void __brcmf_err(const char *func, const char *fmt, ...);
+#define brcmf_err(fmt, ...) \
+	__brcmf_err(__func__, fmt, ##__VA_ARGS__)
+#endif
 
-#if defined(DEBUG)
-
+#if defined(DEBUG) || defined(CONFIG_BRCM_TRACING)
+__printf(3, 4)
+void __brcmf_dbg(u32 level, const char *func, const char *fmt, ...);
 #define brcmf_dbg(level, fmt, ...)				\
 do {								\
-	if (brcmf_msg_level & BRCMF_##level##_VAL)		\
-		pr_debug("%s: " fmt, __func__, ##__VA_ARGS__);	\
+	__brcmf_dbg(BRCMF_##level##_VAL, __func__,		\
+		    fmt, ##__VA_ARGS__);			\
 } while (0)
-
 #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)
@@ -69,7 +77,7 @@ do {								\
 #define BRCMF_EVENT_ON()	(brcmf_msg_level & BRCMF_EVENT_VAL)
 #define BRCMF_FIL_ON()		(brcmf_msg_level & BRCMF_FIL_VAL)
 
-#else	/* (defined DEBUG) || (defined DEBUG) */
+#else /* defined(DEBUG) || defined(CONFIG_BRCM_TRACING) */
 
 #define brcmf_dbg(level, fmt, ...) no_printk(fmt, ##__VA_ARGS__)
 
@@ -81,7 +89,7 @@ do {								\
 #define BRCMF_EVENT_ON()	0
 #define BRCMF_FIL_ON()		0
 
-#endif				/* defined(DEBUG) */
+#endif /* defined(DEBUG) || defined(CONFIG_BRCM_TRACING) */
 
 #define brcmf_dbg_hex_dump(test, data, len, fmt, ...)			\
 do {									\
@@ -125,6 +133,28 @@ struct brcmf_sdio_count {
 	ulong rx_readahead_cnt;	/* packets where header read-ahead was used */
 };
 
+struct brcmf_fws_stats {
+	u32 tlv_parse_failed;
+	u32 tlv_invalid_type;
+	u32 header_only_pkt;
+	u32 header_pulls;
+	u32 pkt2bus;
+	u32 send_pkts[5];
+	u32 fifo_credits_sent[5];
+	u32 fifo_credits_back[6];
+	u32 generic_error;
+	u32 mac_update_failed;
+	u32 rollback_success;
+	u32 rollback_failed;
+	u32 delayq_full_error;
+	u32 supprq_full_error;
+	u32 txs_indicate;
+	u32 txs_discard;
+	u32 txs_supp_core;
+	u32 txs_supp_ps;
+	u32 txs_tossed;
+};
+
 struct brcmf_pub;
 #ifdef DEBUG
 void brcmf_debugfs_init(void);
@@ -134,6 +164,8 @@ void brcmf_debugfs_detach(struct brcmf_pub *drvr);
 struct dentry *brcmf_debugfs_get_devdir(struct brcmf_pub *drvr);
 void brcmf_debugfs_create_sdio_count(struct brcmf_pub *drvr,
 				     struct brcmf_sdio_count *sdcnt);
+void brcmf_debugfs_create_fws_stats(struct brcmf_pub *drvr,
+				    struct brcmf_fws_stats *stats);
 #else
 static inline void brcmf_debugfs_init(void)
 {
@@ -148,6 +180,10 @@ static inline int brcmf_debugfs_attach(struct brcmf_pub *drvr)
 static inline void brcmf_debugfs_detach(struct brcmf_pub *drvr)
 {
 }
+static inline void brcmf_debugfs_create_fws_stats(struct brcmf_pub *drvr,
+						  struct brcmf_fws_stats *stats)
+{
+}
 #endif
 
 #endif				/* _BRCMF_DBG_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
index c06cea8..c82f3e0 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
@@ -30,17 +30,18 @@
 #include "p2p.h"
 #include "wl_cfg80211.h"
 #include "fwil.h"
+#include "fwsignal.h"
 
 MODULE_AUTHOR("Broadcom Corporation");
 MODULE_DESCRIPTION("Broadcom 802.11 wireless LAN fullmac driver.");
-MODULE_SUPPORTED_DEVICE("Broadcom 802.11 WLAN fullmac cards");
 MODULE_LICENSE("Dual BSD/GPL");
 
 #define MAX_WAIT_FOR_8021X_TX		50	/* msecs */
 
 /* Error bits */
 int brcmf_msg_level;
-module_param(brcmf_msg_level, int, 0);
+module_param_named(debug, brcmf_msg_level, int, S_IRUSR | S_IWUSR);
+MODULE_PARM_DESC(debug, "level of debug output");
 
 /* P2P0 enable */
 static int brcmf_p2p_enable;
@@ -222,18 +223,7 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb,
 		goto done;
 	}
 
-	/* handle ethernet header */
-	eh = (struct ethhdr *)(skb->data);
-	if (is_multicast_ether_addr(eh->h_dest))
-		drvr->tx_multicast++;
-	if (ntohs(eh->h_proto) == ETH_P_PAE)
-		atomic_inc(&ifp->pend_8021x_cnt);
-
-	/* If the protocol uses a data header, apply it */
-	brcmf_proto_hdrpush(drvr, ifp->ifidx, skb);
-
-	/* Use bus module to send data frame */
-	ret =  brcmf_bus_txdata(drvr->bus_if, skb);
+	ret = brcmf_fws_process_skb(ifp, skb);
 
 done:
 	if (ret) {
@@ -247,9 +237,27 @@ done:
 	return NETDEV_TX_OK;
 }
 
+void brcmf_txflowblock_if(struct brcmf_if *ifp,
+			  enum brcmf_netif_stop_reason reason, bool state)
+{
+	if (!ifp)
+		return;
+
+	brcmf_dbg(TRACE, "enter: idx=%d stop=0x%X reason=%d state=%d\n",
+		  ifp->bssidx, ifp->netif_stop, reason, state);
+	if (state) {
+		if (!ifp->netif_stop)
+			netif_stop_queue(ifp->ndev);
+		ifp->netif_stop |= reason;
+	} else {
+		ifp->netif_stop &= ~reason;
+		if (!ifp->netif_stop)
+			netif_wake_queue(ifp->ndev);
+	}
+}
+
 void brcmf_txflowblock(struct device *dev, bool state)
 {
-	struct net_device *ndev;
 	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
 	struct brcmf_pub *drvr = bus_if->drvr;
 	int i;
@@ -257,13 +265,8 @@ void brcmf_txflowblock(struct device *dev, bool state)
 	brcmf_dbg(TRACE, "Enter\n");
 
 	for (i = 0; i < BRCMF_MAX_IFS; i++)
-		if (drvr->iflist[i]) {
-			ndev = drvr->iflist[i]->ndev;
-			if (state)
-				netif_stop_queue(ndev);
-			else
-				netif_wake_queue(ndev);
-		}
+		brcmf_txflowblock_if(drvr->iflist[i],
+				     BRCMF_NETIF_STOP_REASON_BLOCK_BUS, state);
 }
 
 void brcmf_rx_frames(struct device *dev, struct sk_buff_head *skb_list)
@@ -283,7 +286,7 @@ void brcmf_rx_frames(struct device *dev, struct sk_buff_head *skb_list)
 		skb_unlink(skb, skb_list);
 
 		/* process and remove protocol-specific header */
-		ret = brcmf_proto_hdrpull(drvr, &ifidx, skb);
+		ret = brcmf_proto_hdrpull(drvr, drvr->fw_signals, &ifidx, skb);
 		ifp = drvr->iflist[ifidx];
 
 		if (ret || !ifp || !ifp->ndev) {
@@ -349,31 +352,49 @@ void brcmf_rx_frames(struct device *dev, struct sk_buff_head *skb_list)
 	}
 }
 
-void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success)
+void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp,
+		      bool success)
 {
-	u8 ifidx;
+	struct brcmf_if *ifp;
 	struct ethhdr *eh;
+	u8 ifidx;
 	u16 type;
-	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
-	struct brcmf_pub *drvr = bus_if->drvr;
-	struct brcmf_if *ifp;
+	int res;
 
-	brcmf_proto_hdrpull(drvr, &ifidx, txp);
+	res = brcmf_proto_hdrpull(drvr, false, &ifidx, txp);
 
 	ifp = drvr->iflist[ifidx];
 	if (!ifp)
-		return;
+		goto done;
 
-	eh = (struct ethhdr *)(txp->data);
-	type = ntohs(eh->h_proto);
+	if (res == 0) {
+		eh = (struct ethhdr *)(txp->data);
+		type = ntohs(eh->h_proto);
 
-	if (type == ETH_P_PAE) {
-		atomic_dec(&ifp->pend_8021x_cnt);
-		if (waitqueue_active(&ifp->pend_8021x_wait))
-			wake_up(&ifp->pend_8021x_wait);
+		if (type == ETH_P_PAE) {
+			atomic_dec(&ifp->pend_8021x_cnt);
+			if (waitqueue_active(&ifp->pend_8021x_wait))
+				wake_up(&ifp->pend_8021x_wait);
+		}
 	}
 	if (!success)
 		ifp->stats.tx_errors++;
+done:
+	brcmu_pkt_buf_free_skb(txp);
+}
+
+void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success)
+{
+	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+	struct brcmf_pub *drvr = bus_if->drvr;
+
+	/* await txstatus signal for firmware if active */
+	if (brcmf_fws_fc_active(drvr->fws)) {
+		if (!success)
+			brcmf_fws_bustxfail(drvr->fws, txp);
+	} else {
+		brcmf_txfinalize(drvr, txp, success);
+	}
 }
 
 static struct net_device_stats *brcmf_netdev_get_stats(struct net_device *ndev)
@@ -748,7 +769,6 @@ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx,
 	ifp->ifidx = ifidx;
 	ifp->bssidx = bssidx;
 
-
 	init_waitqueue_head(&ifp->pend_8021x_wait);
 
 	if (mac_addr != NULL)
@@ -873,6 +893,10 @@ int brcmf_bus_start(struct device *dev)
 	if (ret < 0)
 		goto fail;
 
+	drvr->fw_signals = true;
+	(void)brcmf_fws_init(drvr);
+	brcmf_fws_add_interface(ifp);
+
 	drvr->config = brcmf_cfg80211_attach(drvr, bus_if->dev);
 	if (drvr->config == NULL) {
 		ret = -ENOMEM;
@@ -889,6 +913,10 @@ fail:
 		brcmf_err("failed: %d\n", ret);
 		if (drvr->config)
 			brcmf_cfg80211_detach(drvr->config);
+		if (drvr->fws) {
+			brcmf_fws_del_interface(ifp);
+			brcmf_fws_deinit(drvr);
+		}
 		free_netdev(ifp->ndev);
 		drvr->iflist[0] = NULL;
 		if (p2p_ifp) {
@@ -944,14 +972,18 @@ void brcmf_detach(struct device *dev)
 
 	/* make sure primary interface removed last */
 	for (i = BRCMF_MAX_IFS-1; i > -1; i--)
-		if (drvr->iflist[i])
+		if (drvr->iflist[i]) {
+			brcmf_fws_del_interface(drvr->iflist[i]);
 			brcmf_del_if(drvr, i);
+		}
 
 	brcmf_bus_detach(drvr);
 
 	if (drvr->prot)
 		brcmf_proto_detach(drvr);
 
+	brcmf_fws_deinit(drvr);
+
 	brcmf_debugfs_detach(drvr);
 	bus_if->drvr = NULL;
 	kfree(drvr);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h
index 48fa703..ef91798 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h
@@ -33,7 +33,7 @@ extern void brcmf_proto_stop(struct brcmf_pub *drvr);
 /* Add any protocol-specific data header.
  * Caller must reserve prot_hdrlen prepend space.
  */
-extern void brcmf_proto_hdrpush(struct brcmf_pub *, int ifidx,
+extern void brcmf_proto_hdrpush(struct brcmf_pub *, int ifidx, u8 offset,
 				struct sk_buff *txp);
 
 /* Sets dongle media info (drv_version, mac address). */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
index 4469321..b1b0302 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
@@ -675,7 +675,7 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok)
 	u8 clkctl, clkreq, devctl;
 	unsigned long timeout;
 
-	brcmf_dbg(TRACE, "Enter\n");
+	brcmf_dbg(SDIO, "Enter\n");
 
 	clkctl = 0;
 
@@ -713,7 +713,7 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok)
 			devctl |= SBSDIO_DEVCTL_CA_INT_ONLY;
 			brcmf_sdio_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL,
 					 devctl, &err);
-			brcmf_dbg(INFO, "CLKCTL: set PENDING\n");
+			brcmf_dbg(SDIO, "CLKCTL: set PENDING\n");
 			bus->clkstate = CLK_PENDING;
 
 			return 0;
@@ -750,7 +750,7 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok)
 
 		/* Mark clock available */
 		bus->clkstate = CLK_AVAIL;
-		brcmf_dbg(INFO, "CLKCTL: turned ON\n");
+		brcmf_dbg(SDIO, "CLKCTL: turned ON\n");
 
 #if defined(DEBUG)
 		if (!bus->alp_only) {
@@ -775,7 +775,7 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok)
 		bus->clkstate = CLK_SDONLY;
 		brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
 				 clkreq, &err);
-		brcmf_dbg(INFO, "CLKCTL: turned OFF\n");
+		brcmf_dbg(SDIO, "CLKCTL: turned OFF\n");
 		if (err) {
 			brcmf_err("Failed access turning clock off: %d\n",
 				  err);
@@ -788,7 +788,7 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok)
 /* Change idle/active SD state */
 static int brcmf_sdbrcm_sdclk(struct brcmf_sdio *bus, bool on)
 {
-	brcmf_dbg(TRACE, "Enter\n");
+	brcmf_dbg(SDIO, "Enter\n");
 
 	if (on)
 		bus->clkstate = CLK_SDONLY;
@@ -805,7 +805,7 @@ static int brcmf_sdbrcm_clkctl(struct brcmf_sdio *bus, uint target, bool pendok)
 	uint oldstate = bus->clkstate;
 #endif				/* DEBUG */
 
-	brcmf_dbg(TRACE, "Enter\n");
+	brcmf_dbg(SDIO, "Enter\n");
 
 	/* Early exit if we're already there */
 	if (bus->clkstate == target) {
@@ -849,7 +849,7 @@ static int brcmf_sdbrcm_clkctl(struct brcmf_sdio *bus, uint target, bool pendok)
 		break;
 	}
 #ifdef DEBUG
-	brcmf_dbg(INFO, "%d -> %d\n", oldstate, bus->clkstate);
+	brcmf_dbg(SDIO, "%d -> %d\n", oldstate, bus->clkstate);
 #endif				/* DEBUG */
 
 	return 0;
@@ -862,7 +862,7 @@ static u32 brcmf_sdbrcm_hostmail(struct brcmf_sdio *bus)
 	u8 fcbits;
 	int ret;
 
-	brcmf_dbg(TRACE, "Enter\n");
+	brcmf_dbg(SDIO, "Enter\n");
 
 	/* Read mailbox data and ack that we did so */
 	ret = r_sdreg32(bus, &hmb_data,
@@ -875,7 +875,7 @@ static u32 brcmf_sdbrcm_hostmail(struct brcmf_sdio *bus)
 
 	/* Dongle recomposed rx frames, accept them again */
 	if (hmb_data & HMB_DATA_NAKHANDLED) {
-		brcmf_dbg(INFO, "Dongle reports NAK handled, expect rtx of %d\n",
+		brcmf_dbg(SDIO, "Dongle reports NAK handled, expect rtx of %d\n",
 			  bus->rx_seq);
 		if (!bus->rxskip)
 			brcmf_err("unexpected NAKHANDLED!\n");
@@ -896,7 +896,7 @@ static u32 brcmf_sdbrcm_hostmail(struct brcmf_sdio *bus)
 				  "expecting %d\n",
 				  bus->sdpcm_ver, SDPCM_PROT_VERSION);
 		else
-			brcmf_dbg(INFO, "Dongle ready, protocol version %d\n",
+			brcmf_dbg(SDIO, "Dongle ready, protocol version %d\n",
 				  bus->sdpcm_ver);
 	}
 
@@ -970,7 +970,7 @@ static void brcmf_sdbrcm_rxfail(struct brcmf_sdio *bus, bool abort, bool rtx)
 	if (!retries)
 		brcmf_err("count never zeroed: last 0x%04x\n", lastrbc);
 	else
-		brcmf_dbg(INFO, "flush took %d iterations\n", 0xffff - retries);
+		brcmf_dbg(SDIO, "flush took %d iterations\n", 0xffff - retries);
 
 	if (rtx) {
 		bus->sdcnt.rxrtx++;
@@ -1173,7 +1173,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
 	/* If packets, issue read(s) and send up packet chain */
 	/* Return sequence numbers consumed? */
 
-	brcmf_dbg(TRACE, "start: glomd %p glom %p\n",
+	brcmf_dbg(SDIO, "start: glomd %p glom %p\n",
 		  bus->glomd, skb_peek(&bus->glom));
 
 	/* If there's a descriptor, generate the packet chain */
@@ -1546,7 +1546,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
 	struct sk_buff_head pktlist;	/* needed for bus interface */
 	u16 pad;		/* Number of pad bytes to read */
 	uint rxleft = 0;	/* Remaining number of frames allowed */
-	int sdret;		/* Return code from calls */
+	int ret;		/* Return code from calls */
 	uint rxcount = 0;	/* Total frames read */
 	struct brcmf_sdio_read *rd = &bus->cur_read, rd_new;
 	u8 head_read = 0;
@@ -1577,15 +1577,15 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
 		/* read header first for unknow frame length */
 		sdio_claim_host(bus->sdiodev->func[1]);
 		if (!rd->len) {
-			sdret = brcmf_sdcard_recv_buf(bus->sdiodev,
+			ret = brcmf_sdcard_recv_buf(bus->sdiodev,
 						      bus->sdiodev->sbwad,
 						      SDIO_FUNC_2, F2SYNC,
 						      bus->rxhdr,
 						      BRCMF_FIRSTREAD);
 			bus->sdcnt.f2rxhdrs++;
-			if (sdret < 0) {
+			if (ret < 0) {
 				brcmf_err("RXHEADER FAILED: %d\n",
-					  sdret);
+					  ret);
 				bus->sdcnt.rx_hdrfail++;
 				brcmf_sdbrcm_rxfail(bus, true, true);
 				sdio_release_host(bus->sdiodev->func[1]);
@@ -1637,14 +1637,14 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
 		skb_pull(pkt, head_read);
 		pkt_align(pkt, rd->len_left, BRCMF_SDALIGN);
 
-		sdret = brcmf_sdcard_recv_pkt(bus->sdiodev, bus->sdiodev->sbwad,
+		ret = brcmf_sdcard_recv_pkt(bus->sdiodev, bus->sdiodev->sbwad,
 					      SDIO_FUNC_2, F2SYNC, pkt);
 		bus->sdcnt.f2rxdata++;
 		sdio_release_host(bus->sdiodev->func[1]);
 
-		if (sdret < 0) {
+		if (ret < 0) {
 			brcmf_err("read %d bytes from channel %d failed: %d\n",
-				  rd->len, rd->channel, sdret);
+				  rd->len, rd->channel, ret);
 			brcmu_pkt_buf_free_skb(pkt);
 			sdio_claim_host(bus->sdiodev->func[1]);
 			brcmf_sdbrcm_rxfail(bus, true,
@@ -1775,13 +1775,12 @@ brcmf_sdbrcm_wait_event_wakeup(struct brcmf_sdio *bus)
 /* Writes a HW/SW header into the packet and sends it. */
 /* Assumes: (a) header space already there, (b) caller holds lock */
 static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt,
-			      uint chan, bool free_pkt)
+			      uint chan)
 {
 	int ret;
 	u8 *frame;
 	u16 len, pad = 0;
 	u32 swheader;
-	struct sk_buff *new;
 	int i;
 
 	brcmf_dbg(TRACE, "Enter\n");
@@ -1795,30 +1794,14 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt,
 			brcmf_dbg(INFO, "insufficient headroom %d for %d pad\n",
 				  skb_headroom(pkt), pad);
 			bus->sdiodev->bus_if->tx_realloc++;
-			new = brcmu_pkt_buf_get_skb(pkt->len + BRCMF_SDALIGN);
-			if (!new) {
-				brcmf_err("couldn't allocate new %d-byte packet\n",
-					  pkt->len + BRCMF_SDALIGN);
-				ret = -ENOMEM;
+			ret = skb_cow(pkt, BRCMF_SDALIGN);
+			if (ret)
 				goto done;
-			}
-
-			pkt_align(new, pkt->len, BRCMF_SDALIGN);
-			memcpy(new->data, pkt->data, pkt->len);
-			if (free_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);
-			/* precondition: (frame % BRCMF_SDALIGN) == 0) */
-			pad = 0;
-		} else {
-			skb_push(pkt, pad);
-			frame = (u8 *) (pkt->data);
-			/* precondition: pad + SDPCM_HDRLEN <= pkt->len */
-			memset(frame, 0, pad + SDPCM_HDRLEN);
+			pad = ((unsigned long)frame % BRCMF_SDALIGN);
 		}
+		skb_push(pkt, pad);
+		frame = (u8 *) (pkt->data);
+		memset(frame, 0, pad + SDPCM_HDRLEN);
 	}
 	/* precondition: pad < BRCMF_SDALIGN */
 
@@ -1833,8 +1816,8 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt,
 	    (((pad +
 	       SDPCM_HDRLEN) << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK);
 
-	put_unaligned_le32(swheader, frame + SDPCM_FRAMETAG_LEN);
-	put_unaligned_le32(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader));
+	*(((__le32 *) frame) + 1) = cpu_to_le32(swheader);
+	*(((__le32 *) frame) + 2) = 0;
 
 #ifdef DEBUG
 	tx_packets[pkt->priority]++;
@@ -1900,11 +1883,7 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt,
 done:
 	/* restore pkt buffer pointer before calling tx complete routine */
 	skb_pull(pkt, SDPCM_HDRLEN + pad);
-	brcmf_txcomplete(bus->sdiodev->dev, pkt, ret != 0);
-
-	if (free_pkt)
-		brcmu_pkt_buf_free_skb(pkt);
-
+	brcmf_txcomplete(bus->sdiodev->dev, pkt, ret == 0);
 	return ret;
 }
 
@@ -1932,7 +1911,7 @@ static uint brcmf_sdbrcm_sendfromq(struct brcmf_sdio *bus, uint maxframes)
 		spin_unlock_bh(&bus->txqlock);
 		datalen = pkt->len - SDPCM_HDRLEN;
 
-		ret = brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_DATA_CHANNEL, true);
+		ret = brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_DATA_CHANNEL);
 
 		/* In poll mode, need to check for other events */
 		if (!bus->intr && cnt) {
@@ -2138,7 +2117,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
 			bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN;
 		}
 
-		brcmf_dbg(INFO, "DPC: PENDING, devctl 0x%02x clkctl 0x%02x\n",
+		brcmf_dbg(SDIO, "DPC: PENDING, devctl 0x%02x clkctl 0x%02x\n",
 			  devctl, clkctl);
 
 		if (SBSDIO_HTAV(clkctl)) {
@@ -2314,6 +2293,15 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
 	}
 }
 
+static struct pktq *brcmf_sdbrcm_bus_gettxq(struct device *dev)
+{
+	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+	struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
+	struct brcmf_sdio *bus = sdiodev->bus;
+
+	return &bus->txq;
+}
+
 static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt)
 {
 	int ret = -EBADE;
@@ -2343,7 +2331,6 @@ static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt)
 	if (!brcmf_c_prec_enq(bus->sdiodev->dev, &bus->txq, pkt, prec)) {
 		skb_pull(pkt, SDPCM_HDRLEN);
 		brcmf_txcomplete(bus->sdiodev->dev, pkt, false);
-		brcmu_pkt_buf_free_skb(pkt);
 		brcmf_err("out of bus->txq !!!\n");
 		ret = -ENOSR;
 	} else {
@@ -2400,7 +2387,7 @@ brcmf_sdbrcm_membytes(struct brcmf_sdio *bus, bool write, u32 address, u8 *data,
 
 	/* Do the transfer(s) */
 	while (size) {
-		brcmf_dbg(INFO, "%s %d bytes at offset 0x%08x in window 0x%08x\n",
+		brcmf_dbg(SDIO, "%s %d bytes at offset 0x%08x in window 0x%08x\n",
 			  write ? "write" : "read", dsize,
 			  sdaddr, address & SBSDIO_SBWINDOW_MASK);
 		bcmerror = brcmf_sdcard_rwdata(bus->sdiodev, write,
@@ -2633,10 +2620,10 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
 						 msecs_to_jiffies(2000));
 
 		if (!bus->ctrl_frame_stat) {
-			brcmf_dbg(INFO, "ctrl_frame_stat == false\n");
+			brcmf_dbg(SDIO, "ctrl_frame_stat == false\n");
 			ret = 0;
 		} else {
-			brcmf_dbg(INFO, "ctrl_frame_stat == true\n");
+			brcmf_dbg(SDIO, "ctrl_frame_stat == true\n");
 			ret = -1;
 		}
 	}
@@ -2707,7 +2694,7 @@ static int brcmf_sdio_readshared(struct brcmf_sdio *bus,
 
 	addr = le32_to_cpu(addr_le);
 
-	brcmf_dbg(INFO, "sdpcm_shared address 0x%08X\n", addr);
+	brcmf_dbg(SDIO, "sdpcm_shared address 0x%08X\n", addr);
 
 	/*
 	 * Check if addr is valid.
@@ -3317,15 +3304,15 @@ static int _brcmf_sdbrcm_download_firmware(struct brcmf_sdio *bus)
 		goto err;
 	}
 
-	/* External image takes precedence if specified */
 	if (brcmf_sdbrcm_download_code_file(bus)) {
 		brcmf_err("dongle image file download failed\n");
 		goto err;
 	}
 
-	/* External nvram takes precedence if specified */
-	if (brcmf_sdbrcm_download_nvram(bus))
+	if (brcmf_sdbrcm_download_nvram(bus)) {
 		brcmf_err("dongle nvram file download failed\n");
+		goto err;
+	}
 
 	/* Take arm out of reset */
 	if (brcmf_sdbrcm_download_state(bus, false)) {
@@ -3856,6 +3843,7 @@ static struct brcmf_bus_ops brcmf_sdio_bus_ops = {
 	.txdata = brcmf_sdbrcm_bus_txdata,
 	.txctl = brcmf_sdbrcm_bus_txctl,
 	.rxctl = brcmf_sdbrcm_bus_rxctl,
+	.gettxq = brcmf_sdbrcm_bus_gettxq,
 };
 
 void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev)
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c
index e9d6f91..dad9414 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c
@@ -20,6 +20,7 @@
 
 #include "dhd.h"
 #include "dhd_dbg.h"
+#include "fwsignal.h"
 #include "fweh.h"
 #include "fwil.h"
 
@@ -198,15 +199,20 @@ static void brcmf_fweh_handle_if_event(struct brcmf_pub *drvr,
 				   emsg->ifname, emsg->addr);
 		if (IS_ERR(ifp))
 			return;
-
+		brcmf_fws_add_interface(ifp);
 		if (!drvr->fweh.evt_handler[BRCMF_E_IF])
 			err = brcmf_net_attach(ifp, false);
 	}
 
+	if (ifevent->action == BRCMF_E_IF_CHANGE)
+		brcmf_fws_reset_interface(ifp);
+
 	err = brcmf_fweh_call_event_handler(ifp, emsg->event_code, emsg, data);
 
-	if (ifevent->action == BRCMF_E_IF_DEL)
+	if (ifevent->action == BRCMF_E_IF_DEL) {
+		brcmf_fws_del_interface(ifp);
 		brcmf_del_if(drvr, ifevent->bssidx);
+	}
 }
 
 /**
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
new file mode 100644
index 0000000..8ce79af
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
@@ -0,0 +1,1858 @@
+/*
+ * 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/module.h>
+#include <linux/if_ether.h>
+#include <linux/spinlock.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/err.h>
+#include <uapi/linux/nl80211.h>
+#include <net/cfg80211.h>
+
+#include <brcmu_utils.h>
+#include <brcmu_wifi.h>
+#include "dhd.h"
+#include "dhd_proto.h"
+#include "dhd_dbg.h"
+#include "dhd_bus.h"
+#include "fwil.h"
+#include "fweh.h"
+#include "fwsignal.h"
+
+/**
+ * DOC: Firmware Signalling
+ *
+ * Firmware can send signals to host and vice versa, which are passed in the
+ * data packets using TLV based header. This signalling layer is on top of the
+ * BDC bus protocol layer.
+ */
+
+/*
+ * single definition for firmware-driver flow control tlv's.
+ *
+ * each tlv is specified by BRCMF_FWS_TLV_DEF(name, ID, length).
+ * A length value 0 indicates variable length tlv.
+ */
+#define BRCMF_FWS_TLV_DEFLIST \
+	BRCMF_FWS_TLV_DEF(MAC_OPEN, 1, 1) \
+	BRCMF_FWS_TLV_DEF(MAC_CLOSE, 2, 1) \
+	BRCMF_FWS_TLV_DEF(MAC_REQUEST_CREDIT, 3, 2) \
+	BRCMF_FWS_TLV_DEF(TXSTATUS, 4, 4) \
+	BRCMF_FWS_TLV_DEF(PKTTAG, 5, 4) \
+	BRCMF_FWS_TLV_DEF(MACDESC_ADD,	6, 8) \
+	BRCMF_FWS_TLV_DEF(MACDESC_DEL, 7, 8) \
+	BRCMF_FWS_TLV_DEF(RSSI, 8, 1) \
+	BRCMF_FWS_TLV_DEF(INTERFACE_OPEN, 9, 1) \
+	BRCMF_FWS_TLV_DEF(INTERFACE_CLOSE, 10, 1) \
+	BRCMF_FWS_TLV_DEF(FIFO_CREDITBACK, 11, 6) \
+	BRCMF_FWS_TLV_DEF(PENDING_TRAFFIC_BMP, 12, 2) \
+	BRCMF_FWS_TLV_DEF(MAC_REQUEST_PACKET, 13, 3) \
+	BRCMF_FWS_TLV_DEF(HOST_REORDER_RXPKTS, 14, 10) \
+	BRCMF_FWS_TLV_DEF(TRANS_ID, 18, 6) \
+	BRCMF_FWS_TLV_DEF(COMP_TXSTATUS, 19, 1) \
+	BRCMF_FWS_TLV_DEF(FILLER, 255, 0)
+
+/*
+ * enum brcmf_fws_tlv_type - definition of tlv identifiers.
+ */
+#define BRCMF_FWS_TLV_DEF(name, id, len) \
+	BRCMF_FWS_TYPE_ ## name =  id,
+enum brcmf_fws_tlv_type {
+	BRCMF_FWS_TLV_DEFLIST
+	BRCMF_FWS_TYPE_INVALID
+};
+#undef BRCMF_FWS_TLV_DEF
+
+/*
+ * enum brcmf_fws_tlv_len - definition of tlv lengths.
+ */
+#define BRCMF_FWS_TLV_DEF(name, id, len) \
+	BRCMF_FWS_TYPE_ ## name ## _LEN = (len),
+enum brcmf_fws_tlv_len {
+	BRCMF_FWS_TLV_DEFLIST
+};
+#undef BRCMF_FWS_TLV_DEF
+
+#ifdef DEBUG
+/*
+ * brcmf_fws_tlv_names - array of tlv names.
+ */
+#define BRCMF_FWS_TLV_DEF(name, id, len) \
+	{ id, #name },
+static struct {
+	enum brcmf_fws_tlv_type id;
+	const char *name;
+} brcmf_fws_tlv_names[] = {
+	BRCMF_FWS_TLV_DEFLIST
+};
+#undef BRCMF_FWS_TLV_DEF
+
+static const char *brcmf_fws_get_tlv_name(enum brcmf_fws_tlv_type id)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(brcmf_fws_tlv_names); i++)
+		if (brcmf_fws_tlv_names[i].id == id)
+			return brcmf_fws_tlv_names[i].name;
+
+	return "INVALID";
+}
+#else
+static const char *brcmf_fws_get_tlv_name(enum brcmf_fws_tlv_type id)
+{
+	return "NODEBUG";
+}
+#endif /* DEBUG */
+
+/*
+ * flags used to enable tlv signalling from firmware.
+ */
+#define BRCMF_FWS_FLAGS_RSSI_SIGNALS			0x0001
+#define BRCMF_FWS_FLAGS_XONXOFF_SIGNALS			0x0002
+#define BRCMF_FWS_FLAGS_CREDIT_STATUS_SIGNALS		0x0004
+#define BRCMF_FWS_FLAGS_HOST_PROPTXSTATUS_ACTIVE	0x0008
+#define BRCMF_FWS_FLAGS_PSQ_GENERATIONFSM_ENABLE	0x0010
+#define BRCMF_FWS_FLAGS_PSQ_ZERO_BUFFER_ENABLE		0x0020
+#define BRCMF_FWS_FLAGS_HOST_RXREORDER_ACTIVE		0x0040
+
+#define BRCMF_FWS_MAC_DESC_TABLE_SIZE			32
+#define BRCMF_FWS_MAC_DESC_ID_INVALID			0xff
+
+#define BRCMF_FWS_HOSTIF_FLOWSTATE_OFF			0
+#define BRCMF_FWS_HOSTIF_FLOWSTATE_ON			1
+#define BRCMF_FWS_FLOWCONTROL_HIWATER			128
+#define BRCMF_FWS_FLOWCONTROL_LOWATER			64
+
+#define BRCMF_FWS_PSQ_PREC_COUNT		((NL80211_NUM_ACS + 1) * 2)
+#define BRCMF_FWS_PSQ_LEN				256
+
+#define BRCMF_FWS_HTOD_FLAG_PKTFROMHOST			0x01
+#define BRCMF_FWS_HTOD_FLAG_PKT_REQUESTED		0x02
+
+/**
+ * enum brcmf_fws_skb_state - indicates processing state of skb.
+ *
+ * @BRCMF_FWS_SKBSTATE_NEW: sk_buff is newly arrived in the driver.
+ * @BRCMF_FWS_SKBSTATE_DELAYED: sk_buff had to wait on queue.
+ * @BRCMF_FWS_SKBSTATE_SUPPRESSED: sk_buff has been suppressed by firmware.
+ */
+enum brcmf_fws_skb_state {
+	BRCMF_FWS_SKBSTATE_NEW,
+	BRCMF_FWS_SKBSTATE_DELAYED,
+	BRCMF_FWS_SKBSTATE_SUPPRESSED
+};
+
+/**
+ * struct brcmf_skbuff_cb - control buffer associated with skbuff.
+ *
+ * @if_flags: holds interface index and packet related flags.
+ * @htod: host to device packet identifier (used in PKTTAG tlv).
+ * @state: transmit state of the packet.
+ * @mac: descriptor related to destination for this packet.
+ *
+ * This information is stored in control buffer struct sk_buff::cb, which
+ * provides 48 bytes of storage so this structure should not exceed that.
+ */
+struct brcmf_skbuff_cb {
+	u16 if_flags;
+	u32 htod;
+	enum brcmf_fws_skb_state state;
+	struct brcmf_fws_mac_descriptor *mac;
+};
+
+/*
+ * macro casting skbuff control buffer to struct brcmf_skbuff_cb.
+ */
+#define brcmf_skbcb(skb)	((struct brcmf_skbuff_cb *)((skb)->cb))
+
+/*
+ * sk_buff control if flags
+ *
+ *	b[11]  - packet sent upon firmware request.
+ *	b[10]  - packet only contains signalling data.
+ *	b[9]   - packet is a tx packet.
+ *	b[8]   - packet uses FIFO credit (non-pspoll).
+ *	b[7]   - interface in AP mode.
+ *	b[6:4] - AC FIFO number.
+ *	b[3:0] - interface index.
+ */
+#define BRCMF_SKB_IF_FLAGS_REQUESTED_MASK	0x0800
+#define BRCMF_SKB_IF_FLAGS_REQUESTED_SHIFT	11
+#define BRCMF_SKB_IF_FLAGS_SIGNAL_ONLY_MASK	0x0400
+#define BRCMF_SKB_IF_FLAGS_SIGNAL_ONLY_SHIFT	10
+#define BRCMF_SKB_IF_FLAGS_TRANSMIT_MASK        0x0200
+#define BRCMF_SKB_IF_FLAGS_TRANSMIT_SHIFT	9
+#define BRCMF_SKB_IF_FLAGS_CREDITCHECK_MASK	0x0100
+#define BRCMF_SKB_IF_FLAGS_CREDITCHECK_SHIFT	8
+#define BRCMF_SKB_IF_FLAGS_IF_AP_MASK		0x0080
+#define BRCMF_SKB_IF_FLAGS_IF_AP_SHIFT		7
+#define BRCMF_SKB_IF_FLAGS_FIFO_MASK		0x0070
+#define BRCMF_SKB_IF_FLAGS_FIFO_SHIFT		4
+#define BRCMF_SKB_IF_FLAGS_INDEX_MASK		0x000f
+#define BRCMF_SKB_IF_FLAGS_INDEX_SHIFT		0
+
+#define brcmf_skb_if_flags_set_field(skb, field, value) \
+	brcmu_maskset16(&(brcmf_skbcb(skb)->if_flags), \
+			BRCMF_SKB_IF_FLAGS_ ## field ## _MASK, \
+			BRCMF_SKB_IF_FLAGS_ ## field ## _SHIFT, (value))
+#define brcmf_skb_if_flags_get_field(skb, field) \
+	brcmu_maskget16(brcmf_skbcb(skb)->if_flags, \
+			BRCMF_SKB_IF_FLAGS_ ## field ## _MASK, \
+			BRCMF_SKB_IF_FLAGS_ ## field ## _SHIFT)
+
+/*
+ * sk_buff control packet identifier
+ *
+ * 32-bit packet identifier used in PKTTAG tlv from host to dongle.
+ *
+ * - Generated at the host (e.g. dhd)
+ * - Seen as a generic sequence number by firmware except for the flags field.
+ *
+ * Generation	: b[31]	=> generation number for this packet [host->fw]
+ *			   OR, current generation number [fw->host]
+ * Flags	: b[30:27] => command, status flags
+ * FIFO-AC	: b[26:24] => AC-FIFO id
+ * h-slot	: b[23:8] => hanger-slot
+ * freerun	: b[7:0] => A free running counter
+ */
+#define BRCMF_SKB_HTOD_TAG_GENERATION_MASK		0x80000000
+#define BRCMF_SKB_HTOD_TAG_GENERATION_SHIFT		31
+#define BRCMF_SKB_HTOD_TAG_FLAGS_MASK			0x78000000
+#define BRCMF_SKB_HTOD_TAG_FLAGS_SHIFT			27
+#define BRCMF_SKB_HTOD_TAG_FIFO_MASK			0x07000000
+#define BRCMF_SKB_HTOD_TAG_FIFO_SHIFT			24
+#define BRCMF_SKB_HTOD_TAG_HSLOT_MASK			0x00ffff00
+#define BRCMF_SKB_HTOD_TAG_HSLOT_SHIFT			8
+#define BRCMF_SKB_HTOD_TAG_FREERUN_MASK			0x000000ff
+#define BRCMF_SKB_HTOD_TAG_FREERUN_SHIFT			0
+
+#define brcmf_skb_htod_tag_set_field(skb, field, value) \
+	brcmu_maskset32(&(brcmf_skbcb(skb)->htod), \
+			BRCMF_SKB_HTOD_TAG_ ## field ## _MASK, \
+			BRCMF_SKB_HTOD_TAG_ ## field ## _SHIFT, (value))
+#define brcmf_skb_htod_tag_get_field(skb, field) \
+	brcmu_maskget32(brcmf_skbcb(skb)->htod, \
+			BRCMF_SKB_HTOD_TAG_ ## field ## _MASK, \
+			BRCMF_SKB_HTOD_TAG_ ## field ## _SHIFT)
+
+#define BRCMF_FWS_TXSTAT_GENERATION_MASK	0x80000000
+#define BRCMF_FWS_TXSTAT_GENERATION_SHIFT	31
+#define BRCMF_FWS_TXSTAT_FLAGS_MASK		0x78000000
+#define BRCMF_FWS_TXSTAT_FLAGS_SHIFT		27
+#define BRCMF_FWS_TXSTAT_FIFO_MASK		0x07000000
+#define BRCMF_FWS_TXSTAT_FIFO_SHIFT		24
+#define BRCMF_FWS_TXSTAT_HSLOT_MASK		0x00FFFF00
+#define BRCMF_FWS_TXSTAT_HSLOT_SHIFT		8
+#define BRCMF_FWS_TXSTAT_PKTID_MASK		0x00FFFFFF
+#define BRCMF_FWS_TXSTAT_PKTID_SHIFT		0
+
+#define brcmf_txstatus_get_field(txs, field) \
+	brcmu_maskget32(txs, BRCMF_FWS_TXSTAT_ ## field ## _MASK, \
+			BRCMF_FWS_TXSTAT_ ## field ## _SHIFT)
+
+/**
+ * enum brcmf_fws_fifo - fifo indices used by dongle firmware.
+ *
+ * @BRCMF_FWS_FIFO_AC_BK: fifo for background traffic.
+ * @BRCMF_FWS_FIFO_AC_BE: fifo for best-effort traffic.
+ * @BRCMF_FWS_FIFO_AC_VI: fifo for video traffic.
+ * @BRCMF_FWS_FIFO_AC_VO: fifo for voice traffic.
+ * @BRCMF_FWS_FIFO_BCMC: fifo for broadcast/multicast (AP only).
+ * @BRCMF_FWS_FIFO_ATIM: fifo for ATIM (AP only).
+ * @BRCMF_FWS_FIFO_COUNT: number of fifos.
+ */
+enum brcmf_fws_fifo {
+	BRCMF_FWS_FIFO_AC_BK,
+	BRCMF_FWS_FIFO_AC_BE,
+	BRCMF_FWS_FIFO_AC_VI,
+	BRCMF_FWS_FIFO_AC_VO,
+	BRCMF_FWS_FIFO_BCMC,
+	BRCMF_FWS_FIFO_ATIM,
+	BRCMF_FWS_FIFO_COUNT
+};
+
+/**
+ * enum brcmf_fws_txstatus - txstatus flag values.
+ *
+ * @BRCMF_FWS_TXSTATUS_DISCARD:
+ *	host is free to discard the packet.
+ * @BRCMF_FWS_TXSTATUS_CORE_SUPPRESS:
+ *	802.11 core suppressed the packet.
+ * @BRCMF_FWS_TXSTATUS_FW_PS_SUPPRESS:
+ *	firmware suppress the packet as device is already in PS mode.
+ * @BRCMF_FWS_TXSTATUS_FW_TOSSED:
+ *	firmware tossed the packet.
+ */
+enum brcmf_fws_txstatus {
+	BRCMF_FWS_TXSTATUS_DISCARD,
+	BRCMF_FWS_TXSTATUS_CORE_SUPPRESS,
+	BRCMF_FWS_TXSTATUS_FW_PS_SUPPRESS,
+	BRCMF_FWS_TXSTATUS_FW_TOSSED
+};
+
+enum brcmf_fws_fcmode {
+	BRCMF_FWS_FCMODE_NONE,
+	BRCMF_FWS_FCMODE_IMPLIED_CREDIT,
+	BRCMF_FWS_FCMODE_EXPLICIT_CREDIT
+};
+
+enum brcmf_fws_mac_desc_state {
+	BRCMF_FWS_STATE_OPEN = 1,
+	BRCMF_FWS_STATE_CLOSE
+};
+
+/**
+ * struct brcmf_fws_mac_descriptor - firmware signalling data per node/interface
+ *
+ * @occupied: slot is in use.
+ * @mac_handle: handle for mac entry determined by firmware.
+ * @interface_id: interface index.
+ * @state: current state.
+ * @suppressed: mac entry is suppressed.
+ * @generation: generation bit.
+ * @ac_bitmap: ac queue bitmap.
+ * @requested_credit: credits requested by firmware.
+ * @ea: ethernet address.
+ * @seq: per-node free-running sequence.
+ * @psq: power-save queue.
+ * @transit_count: packet in transit to firmware.
+ */
+struct brcmf_fws_mac_descriptor {
+	u8 occupied;
+	u8 mac_handle;
+	u8 interface_id;
+	u8 state;
+	bool suppressed;
+	u8 generation;
+	u8 ac_bitmap;
+	u8 requested_credit;
+	u8 requested_packet;
+	u8 ea[ETH_ALEN];
+	u8 seq[BRCMF_FWS_FIFO_COUNT];
+	struct pktq psq;
+	int transit_count;
+	int suppress_count;
+	int suppr_transit_count;
+	bool send_tim_signal;
+	u8 traffic_pending_bmp;
+	u8 traffic_lastreported_bmp;
+};
+
+#define BRCMF_FWS_HANGER_MAXITEMS	1024
+
+/**
+ * enum brcmf_fws_hanger_item_state - state of hanger item.
+ *
+ * @BRCMF_FWS_HANGER_ITEM_STATE_FREE: item is free for use.
+ * @BRCMF_FWS_HANGER_ITEM_STATE_INUSE: item is in use.
+ * @BRCMF_FWS_HANGER_ITEM_STATE_INUSE_SUPPRESSED: item was suppressed.
+ */
+enum brcmf_fws_hanger_item_state {
+	BRCMF_FWS_HANGER_ITEM_STATE_FREE = 1,
+	BRCMF_FWS_HANGER_ITEM_STATE_INUSE,
+	BRCMF_FWS_HANGER_ITEM_STATE_INUSE_SUPPRESSED
+};
+
+
+/**
+ * struct brcmf_fws_hanger_item - single entry for tx pending packet.
+ *
+ * @state: entry is either free or occupied.
+ * @gen: generation.
+ * @pkt: packet itself.
+ */
+struct brcmf_fws_hanger_item {
+	enum brcmf_fws_hanger_item_state state;
+	u8 gen;
+	struct sk_buff *pkt;
+};
+
+/**
+ * struct brcmf_fws_hanger - holds packets awaiting firmware txstatus.
+ *
+ * @pushed: packets pushed to await txstatus.
+ * @popped: packets popped upon handling txstatus.
+ * @failed_to_push: packets that could not be pushed.
+ * @failed_to_pop: packets that could not be popped.
+ * @failed_slotfind: packets for which failed to find an entry.
+ * @slot_pos: last returned item index for a free entry.
+ * @items: array of hanger items.
+ */
+struct brcmf_fws_hanger {
+	u32 pushed;
+	u32 popped;
+	u32 failed_to_push;
+	u32 failed_to_pop;
+	u32 failed_slotfind;
+	u32 slot_pos;
+	struct brcmf_fws_hanger_item items[BRCMF_FWS_HANGER_MAXITEMS];
+};
+
+struct brcmf_fws_macdesc_table {
+	struct brcmf_fws_mac_descriptor nodes[BRCMF_FWS_MAC_DESC_TABLE_SIZE];
+	struct brcmf_fws_mac_descriptor iface[BRCMF_MAX_IFS];
+	struct brcmf_fws_mac_descriptor other;
+};
+
+struct brcmf_fws_info {
+	struct brcmf_pub *drvr;
+	struct brcmf_fws_stats stats;
+	struct brcmf_fws_hanger hanger;
+	enum brcmf_fws_fcmode fcmode;
+	struct brcmf_fws_macdesc_table desc;
+	struct workqueue_struct *fws_wq;
+	struct work_struct fws_dequeue_work;
+	u32 fifo_enqpkt[BRCMF_FWS_FIFO_COUNT];
+	int fifo_credit[BRCMF_FWS_FIFO_COUNT];
+	int deq_node_pos[BRCMF_FWS_FIFO_COUNT];
+	u32 fifo_credit_map;
+	u32 fifo_delay_map;
+};
+
+/*
+ * brcmf_fws_prio2fifo - mapping from 802.1d priority to firmware fifo index.
+ */
+static const int brcmf_fws_prio2fifo[] = {
+	BRCMF_FWS_FIFO_AC_BE,
+	BRCMF_FWS_FIFO_AC_BK,
+	BRCMF_FWS_FIFO_AC_BK,
+	BRCMF_FWS_FIFO_AC_BE,
+	BRCMF_FWS_FIFO_AC_VI,
+	BRCMF_FWS_FIFO_AC_VI,
+	BRCMF_FWS_FIFO_AC_VO,
+	BRCMF_FWS_FIFO_AC_VO
+};
+
+static int fcmode;
+module_param(fcmode, int, S_IRUSR);
+MODULE_PARM_DESC(fcmode, "mode of firmware signalled flow control");
+
+#define BRCMF_FWS_TLV_DEF(name, id, len) \
+	case BRCMF_FWS_TYPE_ ## name: \
+		return len;
+
+/**
+ * brcmf_fws_get_tlv_len() - returns defined length for given tlv id.
+ *
+ * @fws: firmware-signalling information.
+ * @id: identifier of the TLV.
+ *
+ * Return: the specified length for the given TLV; Otherwise -EINVAL.
+ */
+static int brcmf_fws_get_tlv_len(struct brcmf_fws_info *fws,
+				 enum brcmf_fws_tlv_type id)
+{
+	switch (id) {
+	BRCMF_FWS_TLV_DEFLIST
+	default:
+		fws->stats.tlv_invalid_type++;
+		break;
+	}
+	return -EINVAL;
+}
+#undef BRCMF_FWS_TLV_DEF
+
+static bool brcmf_fws_ifidx_match(struct sk_buff *skb, void *arg)
+{
+	u32 ifidx = brcmf_skb_if_flags_get_field(skb, INDEX);
+	return ifidx == *(int *)arg;
+}
+
+static void brcmf_fws_psq_flush(struct brcmf_fws_info *fws, struct pktq *q,
+				int ifidx)
+{
+	bool (*matchfn)(struct sk_buff *, void *) = NULL;
+	struct sk_buff *skb;
+	int prec;
+
+	if (ifidx != -1)
+		matchfn = brcmf_fws_ifidx_match;
+	for (prec = 0; prec < q->num_prec; prec++) {
+		skb = brcmu_pktq_pdeq_match(q, prec, matchfn, &ifidx);
+		while (skb) {
+			brcmu_pkt_buf_free_skb(skb);
+			skb = brcmu_pktq_pdeq_match(q, prec, matchfn, &ifidx);
+		}
+	}
+}
+
+static void brcmf_fws_hanger_init(struct brcmf_fws_hanger *hanger)
+{
+	int i;
+
+	brcmf_dbg(TRACE, "enter\n");
+	memset(hanger, 0, sizeof(*hanger));
+	for (i = 0; i < ARRAY_SIZE(hanger->items); i++)
+		hanger->items[i].state = BRCMF_FWS_HANGER_ITEM_STATE_FREE;
+}
+
+static u32 brcmf_fws_hanger_get_free_slot(struct brcmf_fws_hanger *h)
+{
+	u32 i;
+
+	brcmf_dbg(TRACE, "enter\n");
+	i = (h->slot_pos + 1) % BRCMF_FWS_HANGER_MAXITEMS;
+
+	while (i != h->slot_pos) {
+		if (h->items[i].state == BRCMF_FWS_HANGER_ITEM_STATE_FREE) {
+			h->slot_pos = i;
+			goto done;
+		}
+		i++;
+		if (i == BRCMF_FWS_HANGER_MAXITEMS)
+			i = 0;
+	}
+	brcmf_err("all slots occupied\n");
+	h->failed_slotfind++;
+	i = BRCMF_FWS_HANGER_MAXITEMS;
+done:
+	brcmf_dbg(TRACE, "exit: %d\n", i);
+	return i;
+}
+
+static int brcmf_fws_hanger_pushpkt(struct brcmf_fws_hanger *h,
+					   struct sk_buff *pkt, u32 slot_id)
+{
+	brcmf_dbg(TRACE, "enter\n");
+	if (slot_id >= BRCMF_FWS_HANGER_MAXITEMS)
+		return -ENOENT;
+
+	if (h->items[slot_id].state != BRCMF_FWS_HANGER_ITEM_STATE_FREE) {
+		brcmf_err("slot is not free\n");
+		h->failed_to_push++;
+		return -EINVAL;
+	}
+
+	h->items[slot_id].state = BRCMF_FWS_HANGER_ITEM_STATE_INUSE;
+	h->items[slot_id].pkt = pkt;
+	h->pushed++;
+	return 0;
+}
+
+static int brcmf_fws_hanger_poppkt(struct brcmf_fws_hanger *h,
+					  u32 slot_id, struct sk_buff **pktout,
+					  bool remove_item)
+{
+	brcmf_dbg(TRACE, "enter\n");
+	if (slot_id >= BRCMF_FWS_HANGER_MAXITEMS)
+		return -ENOENT;
+
+	if (h->items[slot_id].state == BRCMF_FWS_HANGER_ITEM_STATE_FREE) {
+		brcmf_err("entry not in use\n");
+		h->failed_to_pop++;
+		return -EINVAL;
+	}
+
+	*pktout = h->items[slot_id].pkt;
+	if (remove_item) {
+		h->items[slot_id].state = BRCMF_FWS_HANGER_ITEM_STATE_FREE;
+		h->items[slot_id].pkt = NULL;
+		h->items[slot_id].gen = 0xff;
+		h->popped++;
+	}
+	return 0;
+}
+
+static int brcmf_fws_hanger_mark_suppressed(struct brcmf_fws_hanger *h,
+						   u32 slot_id, u8 gen)
+{
+	brcmf_dbg(TRACE, "enter\n");
+
+	if (slot_id >= BRCMF_FWS_HANGER_MAXITEMS)
+		return -ENOENT;
+
+	h->items[slot_id].gen = gen;
+
+	if (h->items[slot_id].state != BRCMF_FWS_HANGER_ITEM_STATE_INUSE) {
+		brcmf_err("entry not in use\n");
+		return -EINVAL;
+	}
+
+	h->items[slot_id].state = BRCMF_FWS_HANGER_ITEM_STATE_INUSE_SUPPRESSED;
+	return 0;
+}
+
+static int brcmf_fws_hanger_get_genbit(struct brcmf_fws_hanger *hanger,
+					      struct sk_buff *pkt, u32 slot_id,
+					      int *gen)
+{
+	brcmf_dbg(TRACE, "enter\n");
+	*gen = 0xff;
+
+	if (slot_id >= BRCMF_FWS_HANGER_MAXITEMS)
+		return -ENOENT;
+
+	if (hanger->items[slot_id].state == BRCMF_FWS_HANGER_ITEM_STATE_FREE) {
+		brcmf_err("slot not in use\n");
+		return -EINVAL;
+	}
+
+	*gen = hanger->items[slot_id].gen;
+	return 0;
+}
+
+static void brcmf_fws_hanger_cleanup(struct brcmf_fws_info *fws,
+				     bool (*fn)(struct sk_buff *, void *),
+				     int ifidx)
+{
+	struct brcmf_fws_hanger *h = &fws->hanger;
+	struct sk_buff *skb;
+	int i;
+	enum brcmf_fws_hanger_item_state s;
+
+	brcmf_dbg(TRACE, "enter: ifidx=%d\n", ifidx);
+	for (i = 0; i < ARRAY_SIZE(h->items); i++) {
+		s = h->items[i].state;
+		if (s == BRCMF_FWS_HANGER_ITEM_STATE_INUSE ||
+		    s == BRCMF_FWS_HANGER_ITEM_STATE_INUSE_SUPPRESSED) {
+			skb = h->items[i].pkt;
+			if (fn == NULL || fn(skb, &ifidx)) {
+				/* suppress packets freed from psq */
+				if (s == BRCMF_FWS_HANGER_ITEM_STATE_INUSE)
+					brcmu_pkt_buf_free_skb(skb);
+				h->items[i].state =
+					BRCMF_FWS_HANGER_ITEM_STATE_FREE;
+			}
+		}
+	}
+}
+
+static void brcmf_fws_init_mac_descriptor(struct brcmf_fws_mac_descriptor *desc,
+					  u8 *addr, u8 ifidx)
+{
+	brcmf_dbg(TRACE,
+		  "enter: desc %p ea=%pM, ifidx=%u\n", desc, addr, ifidx);
+	desc->occupied = 1;
+	desc->state = BRCMF_FWS_STATE_OPEN;
+	desc->requested_credit = 0;
+	/* depending on use may need ifp->bssidx instead */
+	desc->interface_id = ifidx;
+	desc->ac_bitmap = 0xff; /* update this when handling APSD */
+	if (addr)
+		memcpy(&desc->ea[0], addr, ETH_ALEN);
+}
+
+static
+void brcmf_fws_clear_mac_descriptor(struct brcmf_fws_mac_descriptor *desc)
+{
+	brcmf_dbg(TRACE,
+		  "enter: ea=%pM, ifidx=%u\n", desc->ea, desc->interface_id);
+	desc->occupied = 0;
+	desc->state = BRCMF_FWS_STATE_CLOSE;
+	desc->requested_credit = 0;
+}
+
+static struct brcmf_fws_mac_descriptor *
+brcmf_fws_mac_descriptor_lookup(struct brcmf_fws_info *fws, u8 *ea)
+{
+	struct brcmf_fws_mac_descriptor *entry;
+	int i;
+
+	brcmf_dbg(TRACE, "enter: ea=%pM\n", ea);
+	if (ea == NULL)
+		return ERR_PTR(-EINVAL);
+
+	entry = &fws->desc.nodes[0];
+	for (i = 0; i < ARRAY_SIZE(fws->desc.nodes); i++) {
+		if (entry->occupied && !memcmp(entry->ea, ea, ETH_ALEN))
+			return entry;
+		entry++;
+	}
+
+	return ERR_PTR(-ENOENT);
+}
+
+static struct brcmf_fws_mac_descriptor*
+brcmf_fws_find_mac_desc(struct brcmf_fws_info *fws, int ifidx, u8 *da)
+{
+	struct brcmf_fws_mac_descriptor *entry = &fws->desc.other;
+	struct brcmf_if *ifp;
+	bool multicast;
+
+	brcmf_dbg(TRACE, "enter: ifidx=%d\n", ifidx);
+
+	multicast = is_multicast_ether_addr(da);
+	ifp = fws->drvr->iflist[ifidx ? ifidx + 1 : 0];
+	if (WARN_ON(!ifp))
+		goto done;
+
+	/* Multicast destination and P2P clients get the interface entry.
+	 * STA gets the interface entry if there is no exact match. For
+	 * example, TDLS destinations have their own entry.
+	 */
+	entry = NULL;
+	if (multicast && ifp->fws_desc)
+		entry = ifp->fws_desc;
+
+	if (entry != NULL && multicast)
+		goto done;
+
+	entry = brcmf_fws_mac_descriptor_lookup(fws, da);
+	if (IS_ERR(entry))
+		entry = &fws->desc.other;
+
+done:
+	brcmf_dbg(TRACE, "exit: entry=%p\n", entry);
+	return entry;
+}
+
+static bool brcmf_fws_mac_desc_ready(struct brcmf_fws_mac_descriptor *entry,
+				     int fifo)
+{
+	bool ready;
+
+	/*
+	 * destination entry is ready when firmware says it is OPEN
+	 * and there are no packets enqueued for it.
+	 */
+	ready = entry->state == BRCMF_FWS_STATE_OPEN &&
+		!entry->suppressed &&
+		brcmu_pktq_mlen(&entry->psq, 3 << (fifo * 2)) == 0;
+
+	/*
+	 * Or when the destination entry is CLOSED, but firmware has
+	 * specifically requested packets for this entry.
+	 */
+	ready = ready || (entry->state == BRCMF_FWS_STATE_CLOSE &&
+		(entry->requested_credit + entry->requested_packet));
+	return ready;
+}
+
+static void brcmf_fws_mac_desc_cleanup(struct brcmf_fws_info *fws,
+				       struct brcmf_fws_mac_descriptor *entry,
+				       int ifidx)
+{
+	brcmf_dbg(TRACE, "enter: entry=(ea=%pM, ifid=%d), ifidx=%d\n",
+		  entry->ea, entry->interface_id, ifidx);
+	if (entry->occupied && (ifidx == -1 || ifidx == entry->interface_id)) {
+		brcmf_dbg(TRACE, "flush psq: ifidx=%d, qlen=%d\n",
+			  ifidx, entry->psq.len);
+		brcmf_fws_psq_flush(fws, &entry->psq, ifidx);
+		entry->occupied = !!(entry->psq.len);
+	}
+}
+
+static void brcmf_fws_bus_txq_cleanup(struct brcmf_fws_info *fws,
+				      bool (*fn)(struct sk_buff *, void *),
+				      int ifidx)
+{
+	struct brcmf_fws_hanger_item *hi;
+	struct pktq *txq;
+	struct sk_buff *skb;
+	int prec;
+	u32 hslot;
+
+	brcmf_dbg(TRACE, "enter: ifidx=%d\n", ifidx);
+	txq = brcmf_bus_gettxq(fws->drvr->bus_if);
+	if (IS_ERR(txq)) {
+		brcmf_dbg(TRACE, "no txq to clean up\n");
+		return;
+	}
+
+	for (prec = 0; prec < txq->num_prec; prec++) {
+		skb = brcmu_pktq_pdeq_match(txq, prec, fn, &ifidx);
+		while (skb) {
+			hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT);
+			hi = &fws->hanger.items[hslot];
+			WARN_ON(skb != hi->pkt);
+			hi->state = BRCMF_FWS_HANGER_ITEM_STATE_FREE;
+			brcmu_pkt_buf_free_skb(skb);
+			skb = brcmu_pktq_pdeq_match(txq, prec, fn, &ifidx);
+		}
+	}
+}
+
+static void brcmf_fws_cleanup(struct brcmf_fws_info *fws, int ifidx)
+{
+	int i;
+	struct brcmf_fws_mac_descriptor *table;
+	bool (*matchfn)(struct sk_buff *, void *) = NULL;
+
+	brcmf_dbg(TRACE, "enter: ifidx=%d\n", ifidx);
+	if (fws == NULL)
+		return;
+
+	if (ifidx != -1)
+		matchfn = brcmf_fws_ifidx_match;
+
+	/* cleanup individual nodes */
+	table = &fws->desc.nodes[0];
+	for (i = 0; i < ARRAY_SIZE(fws->desc.nodes); i++)
+		brcmf_fws_mac_desc_cleanup(fws, &table[i], ifidx);
+
+	brcmf_fws_mac_desc_cleanup(fws, &fws->desc.other, ifidx);
+	brcmf_fws_bus_txq_cleanup(fws, matchfn, ifidx);
+	brcmf_fws_hanger_cleanup(fws, matchfn, ifidx);
+}
+
+static void brcmf_fws_tim_update(struct brcmf_fws_info *ctx,
+				 struct brcmf_fws_mac_descriptor *entry,
+				 int prec)
+{
+	brcmf_dbg(TRACE, "enter: ea=%pM\n", entry->ea);
+	if (entry->state == BRCMF_FWS_STATE_CLOSE) {
+		/* check delayedQ and suppressQ in one call using bitmap */
+		if (brcmu_pktq_mlen(&entry->psq, 3 << (prec * 2)) == 0)
+			entry->traffic_pending_bmp =
+				entry->traffic_pending_bmp & ~NBITVAL(prec);
+		else
+			entry->traffic_pending_bmp =
+				entry->traffic_pending_bmp | NBITVAL(prec);
+	}
+	/* request a TIM update to firmware at the next piggyback opportunity */
+	if (entry->traffic_lastreported_bmp != entry->traffic_pending_bmp)
+		entry->send_tim_signal = true;
+}
+
+static void
+brcmf_fws_flow_control_check(struct brcmf_fws_info *fws, struct pktq *pq,
+			     u8 if_id)
+{
+	struct brcmf_if *ifp = fws->drvr->iflist[if_id];
+
+	brcmf_dbg(TRACE,
+		  "enter: bssidx=%d, ifidx=%d\n", ifp->bssidx, ifp->ifidx);
+	if (WARN_ON(!ifp))
+		return;
+
+	if ((ifp->netif_stop & BRCMF_NETIF_STOP_REASON_FWS_FC) &&
+	    pq->len <= BRCMF_FWS_FLOWCONTROL_LOWATER)
+		brcmf_txflowblock_if(ifp,
+				     BRCMF_NETIF_STOP_REASON_FWS_FC, false);
+	if (!(ifp->netif_stop & BRCMF_NETIF_STOP_REASON_FWS_FC) &&
+	    pq->len >= BRCMF_FWS_FLOWCONTROL_HIWATER)
+		brcmf_txflowblock_if(ifp, BRCMF_NETIF_STOP_REASON_FWS_FC, true);
+	return;
+}
+
+static int brcmf_fws_rssi_indicate(struct brcmf_fws_info *fws, s8 rssi)
+{
+	brcmf_dbg(CTL, "rssi %d\n", rssi);
+	return 0;
+}
+
+static
+int brcmf_fws_macdesc_indicate(struct brcmf_fws_info *fws, u8 type, u8 *data)
+{
+	struct brcmf_fws_mac_descriptor *entry, *existing;
+	u8 mac_handle;
+	u8 ifidx;
+	u8 *addr;
+
+	mac_handle = *data++;
+	ifidx = *data++;
+	addr = data;
+
+	entry = &fws->desc.nodes[mac_handle & 0x1F];
+	if (type == BRCMF_FWS_TYPE_MACDESC_DEL) {
+		brcmf_dbg(TRACE, "deleting mac %pM idx %d\n", addr, ifidx);
+		if (entry->occupied)
+			brcmf_fws_clear_mac_descriptor(entry);
+		else
+			fws->stats.mac_update_failed++;
+		return 0;
+	}
+
+	brcmf_dbg(TRACE,
+		  "add mac %pM handle %u idx %d\n", addr, mac_handle, ifidx);
+	existing = brcmf_fws_mac_descriptor_lookup(fws, addr);
+	if (IS_ERR(existing)) {
+		if (!entry->occupied) {
+			entry->mac_handle = mac_handle;
+			brcmf_fws_init_mac_descriptor(entry, addr, ifidx);
+			brcmu_pktq_init(&entry->psq, BRCMF_FWS_PSQ_PREC_COUNT,
+					BRCMF_FWS_PSQ_LEN);
+		} else {
+			fws->stats.mac_update_failed++;
+		}
+	} else {
+		if (entry != existing) {
+			brcmf_dbg(TRACE, "relocate mac\n");
+			memcpy(entry, existing,
+			       offsetof(struct brcmf_fws_mac_descriptor, psq));
+			entry->mac_handle = mac_handle;
+			brcmf_fws_clear_mac_descriptor(existing);
+		} else {
+			brcmf_dbg(TRACE, "use existing\n");
+			WARN_ON(entry->mac_handle != mac_handle);
+			/* TODO: what should we do here: continue, reinit, .. */
+		}
+	}
+	return 0;
+}
+
+static void brcmf_fws_return_credits(struct brcmf_fws_info *fws,
+				     u8 fifo, u8 credits)
+{
+	if (!credits)
+		return;
+
+	fws->fifo_credit_map |= 1 << fifo;
+	fws->fifo_credit[fifo] += credits;
+}
+
+static void brcmf_fws_schedule_deq(struct brcmf_fws_info *fws)
+{
+	/* only schedule dequeue when there are credits for delayed traffic */
+	if (fws->fifo_credit_map & fws->fifo_delay_map)
+		queue_work(fws->fws_wq, &fws->fws_dequeue_work);
+}
+
+static void brcmf_skb_pick_up_credit(struct brcmf_fws_info *fws, int fifo,
+				     struct sk_buff *p)
+{
+	struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(p)->mac;
+
+	if (brcmf_skbcb(p)->if_flags & BRCMF_SKB_IF_FLAGS_CREDITCHECK_MASK) {
+		if (fws->fcmode != BRCMF_FWS_FCMODE_IMPLIED_CREDIT)
+			return;
+		brcmf_fws_return_credits(fws, fifo, 1);
+	} else {
+		/*
+		 * if this packet did not count against FIFO credit, it
+		 * must have taken a requested_credit from the destination
+		 * entry (for pspoll etc.)
+		 */
+		if (!brcmf_skb_if_flags_get_field(p, REQUESTED))
+			entry->requested_credit++;
+	}
+	brcmf_fws_schedule_deq(fws);
+}
+
+static int brcmf_fws_enq(struct brcmf_fws_info *fws,
+			 enum brcmf_fws_skb_state state, int fifo,
+			 struct sk_buff *p)
+{
+	int prec = 2 * fifo;
+	u32 *qfull_stat = &fws->stats.delayq_full_error;
+
+	struct brcmf_fws_mac_descriptor *entry;
+
+	entry = brcmf_skbcb(p)->mac;
+	if (entry == NULL) {
+		brcmf_err("no mac descriptor found for skb %p\n", p);
+		return -ENOENT;
+	}
+
+	brcmf_dbg(TRACE, "enter: ea=%pM, qlen=%d\n", entry->ea, entry->psq.len);
+	if (state == BRCMF_FWS_SKBSTATE_SUPPRESSED) {
+		prec += 1;
+		qfull_stat = &fws->stats.supprq_full_error;
+	}
+
+	if (brcmu_pktq_penq(&entry->psq, prec, p) == NULL) {
+		*qfull_stat += 1;
+		return -ENFILE;
+	}
+
+	/* increment total enqueued packet count */
+	fws->fifo_delay_map |= 1 << fifo;
+	fws->fifo_enqpkt[fifo]++;
+
+	/* update the sk_buff state */
+	brcmf_skbcb(p)->state = state;
+	if (state == BRCMF_FWS_SKBSTATE_SUPPRESSED)
+		entry->suppress_count++;
+
+	/*
+	 * A packet has been pushed so update traffic
+	 * availability bitmap, if applicable
+	 */
+	brcmf_fws_tim_update(fws, entry, fifo);
+	brcmf_fws_flow_control_check(fws, &entry->psq,
+				     brcmf_skb_if_flags_get_field(p, INDEX));
+	return 0;
+}
+
+static struct sk_buff *brcmf_fws_deq(struct brcmf_fws_info *fws, int fifo)
+{
+	struct brcmf_fws_mac_descriptor *table;
+	struct brcmf_fws_mac_descriptor *entry;
+	struct sk_buff *p;
+	int use_credit = 1;
+	int num_nodes;
+	int node_pos;
+	int prec_out;
+	int pmsk = 3;
+	int i;
+
+	table = (struct brcmf_fws_mac_descriptor *)&fws->desc;
+	num_nodes = sizeof(fws->desc) / sizeof(struct brcmf_fws_mac_descriptor);
+	node_pos = fws->deq_node_pos[fifo];
+
+	for (i = 0; i < num_nodes; i++) {
+		entry = &table[(node_pos + i) % num_nodes];
+		if (!entry->occupied)
+			continue;
+
+		if (entry->suppressed)
+			pmsk = 2;
+		p = brcmu_pktq_mdeq(&entry->psq, pmsk << (fifo * 2), &prec_out);
+		if (p == NULL) {
+			if (entry->suppressed) {
+				if (entry->suppr_transit_count >
+				    entry->suppress_count)
+					return NULL;
+				entry->suppressed = false;
+				p = brcmu_pktq_mdeq(&entry->psq,
+						    1 << (fifo * 2), &prec_out);
+			}
+		}
+		if  (p == NULL)
+			continue;
+
+		/* did the packet come from suppress sub-queue? */
+		if (entry->requested_credit > 0) {
+			entry->requested_credit--;
+			/*
+			 * if the packet was pulled out while destination is in
+			 * closed state but had a non-zero packets requested,
+			 * then this should not count against the FIFO credit.
+			 * That is due to the fact that the firmware will
+			 * most likely hold onto this packet until a suitable
+			 * time later to push it to the appropriate AC FIFO.
+			 */
+			if (entry->state == BRCMF_FWS_STATE_CLOSE)
+				use_credit = 0;
+		} else if (entry->requested_packet > 0) {
+			entry->requested_packet--;
+			brcmf_skb_if_flags_set_field(p, REQUESTED, 1);
+			if (entry->state == BRCMF_FWS_STATE_CLOSE)
+				use_credit = 0;
+		}
+		brcmf_skb_if_flags_set_field(p, CREDITCHECK, use_credit);
+
+		/* move dequeue position to ensure fair round-robin */
+		fws->deq_node_pos[fifo] = (node_pos + i + 1) % num_nodes;
+		brcmf_fws_flow_control_check(fws, &entry->psq,
+					     brcmf_skb_if_flags_get_field(p,
+									  INDEX)
+					     );
+		/*
+		 * A packet has been picked up, update traffic
+		 * availability bitmap, if applicable
+		 */
+		brcmf_fws_tim_update(fws, entry, fifo);
+
+		/*
+		 * decrement total enqueued fifo packets and
+		 * clear delay bitmap if done.
+		 */
+		fws->fifo_enqpkt[fifo]--;
+		if (fws->fifo_enqpkt[fifo] == 0)
+			fws->fifo_delay_map &= ~(1 << fifo);
+		goto done;
+	}
+	p = NULL;
+done:
+	brcmf_dbg(TRACE, "exit: fifo %d skb %p\n", fifo, p);
+	return p;
+}
+
+static int brcmf_fws_txstatus_suppressed(struct brcmf_fws_info *fws, int fifo,
+					 struct sk_buff *skb, u32 genbit)
+{
+	struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(skb)->mac;
+	u32 hslot;
+	int ret;
+
+	hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT);
+
+	/* this packet was suppressed */
+	if (!entry->suppressed || entry->generation != genbit) {
+		entry->suppressed = true;
+		entry->suppress_count = brcmu_pktq_mlen(&entry->psq,
+							1 << (fifo * 2 + 1));
+		entry->suppr_transit_count = entry->transit_count;
+	}
+
+	entry->generation = genbit;
+
+	ret = brcmf_fws_enq(fws, BRCMF_FWS_SKBSTATE_SUPPRESSED, fifo, skb);
+	if (ret != 0) {
+		/* suppress q is full, drop this packet */
+		brcmf_fws_hanger_poppkt(&fws->hanger, hslot, &skb,
+					true);
+	} else {
+		/*
+		 * Mark suppressed to avoid a double free during
+		 * wlfc cleanup
+		 */
+		brcmf_fws_hanger_mark_suppressed(&fws->hanger, hslot,
+						 genbit);
+		entry->suppress_count++;
+	}
+
+	return ret;
+}
+
+static int
+brcmf_fws_txstatus_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot,
+			   u32 genbit)
+{
+	u32 fifo;
+	int ret;
+	bool remove_from_hanger = true;
+	struct sk_buff *skb;
+	struct brcmf_fws_mac_descriptor *entry = NULL;
+
+	fws->stats.txs_indicate++;
+
+	brcmf_dbg(TRACE, "status: flags=0x%X, hslot=%d\n",
+		  flags, hslot);
+
+	if (flags == BRCMF_FWS_TXSTATUS_DISCARD)
+		fws->stats.txs_discard++;
+	else if (flags == BRCMF_FWS_TXSTATUS_CORE_SUPPRESS) {
+		fws->stats.txs_supp_core++;
+		remove_from_hanger = false;
+	} else if (flags == BRCMF_FWS_TXSTATUS_FW_PS_SUPPRESS) {
+		fws->stats.txs_supp_ps++;
+		remove_from_hanger = false;
+	} else if (flags == BRCMF_FWS_TXSTATUS_FW_TOSSED)
+		fws->stats.txs_tossed++;
+	else
+		brcmf_err("unexpected txstatus\n");
+
+	ret = brcmf_fws_hanger_poppkt(&fws->hanger, hslot, &skb,
+				      remove_from_hanger);
+	if (ret != 0) {
+		brcmf_err("no packet in hanger slot: hslot=%d\n", hslot);
+		return ret;
+	}
+
+	entry = brcmf_skbcb(skb)->mac;
+	if (WARN_ON(!entry)) {
+		brcmu_pkt_buf_free_skb(skb);
+		return -EINVAL;
+	}
+
+	/* pick up the implicit credit from this packet */
+	fifo = brcmf_skb_htod_tag_get_field(skb, FIFO);
+	brcmf_skb_pick_up_credit(fws, fifo, skb);
+
+	if (!remove_from_hanger)
+		ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb, genbit);
+
+	if (remove_from_hanger || ret) {
+		entry->transit_count--;
+		if (entry->suppressed)
+			entry->suppr_transit_count--;
+
+		brcmf_txfinalize(fws->drvr, skb, true);
+	}
+	return 0;
+}
+
+static int brcmf_fws_fifocreditback_indicate(struct brcmf_fws_info *fws,
+					     u8 *data)
+{
+	int i;
+
+	if (fws->fcmode != BRCMF_FWS_FCMODE_EXPLICIT_CREDIT) {
+		brcmf_dbg(INFO, "ignored\n");
+		return 0;
+	}
+
+	brcmf_dbg(TRACE, "enter: data %pM\n", data);
+	for (i = 0; i < BRCMF_FWS_FIFO_COUNT; i++)
+		brcmf_fws_return_credits(fws, i, data[i]);
+
+	brcmf_dbg(INFO, "map: credit %x delay %x\n", fws->fifo_credit_map,
+		  fws->fifo_delay_map);
+	brcmf_fws_schedule_deq(fws);
+	return 0;
+}
+
+static int brcmf_fws_txstatus_indicate(struct brcmf_fws_info *fws, u8 *data)
+{
+	u32 status;
+	u32 hslot;
+	u32 genbit;
+	u8 flags;
+
+	fws->stats.txs_indicate++;
+	status = le32_to_cpu(*(__le32 *)data);
+	flags = brcmf_txstatus_get_field(status, FLAGS);
+	hslot = brcmf_txstatus_get_field(status, HSLOT);
+	genbit = brcmf_txstatus_get_field(status, GENERATION);
+
+	return brcmf_fws_txstatus_process(fws, flags, hslot, genbit);
+}
+
+static int brcmf_fws_dbg_seqnum_check(struct brcmf_fws_info *fws, u8 *data)
+{
+	__le32 timestamp;
+
+	memcpy(&timestamp, &data[2], sizeof(timestamp));
+	brcmf_dbg(INFO, "received: seq %d, timestamp %d\n", data[1],
+		  le32_to_cpu(timestamp));
+	return 0;
+}
+
+/* using macro so sparse checking does not complain
+ * about locking imbalance.
+ */
+#define brcmf_fws_lock(drvr, flags)				\
+do {								\
+	flags = 0;						\
+	spin_lock_irqsave(&((drvr)->fws_spinlock), (flags));	\
+} while (0)
+
+/* using macro so sparse checking does not complain
+ * about locking imbalance.
+ */
+#define brcmf_fws_unlock(drvr, flags) \
+	spin_unlock_irqrestore(&((drvr)->fws_spinlock), (flags))
+
+static int brcmf_fws_notify_credit_map(struct brcmf_if *ifp,
+				       const struct brcmf_event_msg *e,
+				       void *data)
+{
+	struct brcmf_fws_info *fws = ifp->drvr->fws;
+	int i;
+	ulong flags;
+	u8 *credits = data;
+
+	if (e->datalen < BRCMF_FWS_FIFO_COUNT) {
+		brcmf_err("event payload too small (%d)\n", e->datalen);
+		return -EINVAL;
+	}
+
+	brcmf_dbg(TRACE, "enter: credits %pM\n", credits);
+	brcmf_fws_lock(ifp->drvr, flags);
+	for (i = 0; i < ARRAY_SIZE(fws->fifo_credit); i++) {
+		if (*credits)
+			fws->fifo_credit_map |= 1 << i;
+		else
+			fws->fifo_credit_map &= ~(1 << i);
+		fws->fifo_credit[i] = *credits++;
+	}
+	brcmf_fws_schedule_deq(fws);
+	brcmf_fws_unlock(ifp->drvr, flags);
+	return 0;
+}
+
+int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
+		      struct sk_buff *skb)
+{
+	struct brcmf_fws_info *fws = drvr->fws;
+	ulong flags;
+	u8 *signal_data;
+	s16 data_len;
+	u8 type;
+	u8 len;
+	u8 *data;
+
+	brcmf_dbg(TRACE, "enter: ifidx %d, skblen %u, sig %d\n",
+		  ifidx, skb->len, signal_len);
+
+	WARN_ON(signal_len > skb->len);
+
+	/* if flow control disabled, skip to packet data and leave */
+	if (!signal_len || !drvr->fw_signals) {
+		skb_pull(skb, signal_len);
+		return 0;
+	}
+
+	/* lock during tlv parsing */
+	brcmf_fws_lock(drvr, flags);
+
+	fws->stats.header_pulls++;
+	data_len = signal_len;
+	signal_data = skb->data;
+
+	while (data_len > 0) {
+		/* extract tlv info */
+		type = signal_data[0];
+
+		/* FILLER type is actually not a TLV, but
+		 * a single byte that can be skipped.
+		 */
+		if (type == BRCMF_FWS_TYPE_FILLER) {
+			signal_data += 1;
+			data_len -= 1;
+			continue;
+		}
+		len = signal_data[1];
+		data = signal_data + 2;
+
+		brcmf_dbg(INFO, "tlv type=%d (%s), len=%d, data[0]=%d\n", type,
+			  brcmf_fws_get_tlv_name(type), len, *data);
+
+		/* abort parsing when length invalid */
+		if (data_len < len + 2)
+			break;
+
+		if (len != brcmf_fws_get_tlv_len(fws, type))
+			break;
+
+		switch (type) {
+		case BRCMF_FWS_TYPE_MAC_OPEN:
+		case BRCMF_FWS_TYPE_MAC_CLOSE:
+		case BRCMF_FWS_TYPE_MAC_REQUEST_CREDIT:
+		case BRCMF_FWS_TYPE_INTERFACE_OPEN:
+		case BRCMF_FWS_TYPE_INTERFACE_CLOSE:
+		case BRCMF_FWS_TYPE_MAC_REQUEST_PACKET:
+		case BRCMF_FWS_TYPE_HOST_REORDER_RXPKTS:
+		case BRCMF_FWS_TYPE_COMP_TXSTATUS:
+			break;
+		case BRCMF_FWS_TYPE_MACDESC_ADD:
+		case BRCMF_FWS_TYPE_MACDESC_DEL:
+			brcmf_fws_macdesc_indicate(fws, type, data);
+			break;
+		case BRCMF_FWS_TYPE_TXSTATUS:
+			brcmf_fws_txstatus_indicate(fws, data);
+			break;
+		case BRCMF_FWS_TYPE_FIFO_CREDITBACK:
+			brcmf_fws_fifocreditback_indicate(fws, data);
+			break;
+		case BRCMF_FWS_TYPE_RSSI:
+			brcmf_fws_rssi_indicate(fws, *data);
+			break;
+		case BRCMF_FWS_TYPE_TRANS_ID:
+			brcmf_fws_dbg_seqnum_check(fws, data);
+			break;
+		case BRCMF_FWS_TYPE_PKTTAG:
+		case BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP:
+		default:
+			fws->stats.tlv_invalid_type++;
+			break;
+		}
+
+		signal_data += len + 2;
+		data_len -= len + 2;
+	}
+
+	if (data_len != 0)
+		fws->stats.tlv_parse_failed++;
+
+	/* signalling processing result does
+	 * not affect the actual ethernet packet.
+	 */
+	skb_pull(skb, signal_len);
+
+	/* this may be a signal-only packet
+	 */
+	if (skb->len == 0)
+		fws->stats.header_only_pkt++;
+
+	brcmf_fws_unlock(drvr, flags);
+	return 0;
+}
+
+static int brcmf_fws_hdrpush(struct brcmf_fws_info *fws, struct sk_buff *skb)
+{
+	struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(skb)->mac;
+	u8 *wlh;
+	u16 data_offset = 0;
+	u8 fillers;
+	__le32 pkttag = cpu_to_le32(brcmf_skbcb(skb)->htod);
+
+	brcmf_dbg(TRACE, "enter: ea=%pM, ifidx=%u, pkttag=0x%08X\n",
+		  entry->ea, entry->interface_id, le32_to_cpu(pkttag));
+	if (entry->send_tim_signal)
+		data_offset += 2 + BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP_LEN;
+
+	/* +2 is for Type[1] and Len[1] in TLV, plus TIM signal */
+	data_offset += 2 + BRCMF_FWS_TYPE_PKTTAG_LEN;
+	fillers = round_up(data_offset, 4) - data_offset;
+	data_offset += fillers;
+
+	skb_push(skb, data_offset);
+	wlh = skb->data;
+
+	wlh[0] = BRCMF_FWS_TYPE_PKTTAG;
+	wlh[1] = BRCMF_FWS_TYPE_PKTTAG_LEN;
+	memcpy(&wlh[2], &pkttag, sizeof(pkttag));
+	wlh += BRCMF_FWS_TYPE_PKTTAG_LEN + 2;
+
+	if (entry->send_tim_signal) {
+		entry->send_tim_signal = 0;
+		wlh[0] = BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP;
+		wlh[1] = BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP_LEN;
+		wlh[2] = entry->mac_handle;
+		wlh[3] = entry->traffic_pending_bmp;
+		wlh += BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP_LEN + 2;
+		entry->traffic_lastreported_bmp = entry->traffic_pending_bmp;
+	}
+	if (fillers)
+		memset(wlh, BRCMF_FWS_TYPE_FILLER, fillers);
+
+	brcmf_proto_hdrpush(fws->drvr, brcmf_skb_if_flags_get_field(skb, INDEX),
+			    data_offset >> 2, skb);
+	return 0;
+}
+
+static int brcmf_fws_precommit_skb(struct brcmf_fws_info *fws, int fifo,
+				   struct sk_buff *p)
+{
+	struct brcmf_skbuff_cb *skcb = brcmf_skbcb(p);
+	struct brcmf_fws_mac_descriptor *entry = skcb->mac;
+	int rc = 0;
+	bool header_needed;
+	int hslot = BRCMF_FWS_HANGER_MAXITEMS;
+	u8 free_ctr;
+	u8 ifidx;
+	u8 flags;
+
+	header_needed = skcb->state != BRCMF_FWS_SKBSTATE_SUPPRESSED;
+
+	if (header_needed) {
+		/* obtaining free slot may fail, but that will be caught
+		 * by the hanger push. This assures the packet has a BDC
+		 * header upon return.
+		 */
+		hslot = brcmf_fws_hanger_get_free_slot(&fws->hanger);
+		free_ctr = entry->seq[fifo];
+		brcmf_skb_htod_tag_set_field(p, HSLOT, hslot);
+		brcmf_skb_htod_tag_set_field(p, FREERUN, free_ctr);
+		brcmf_skb_htod_tag_set_field(p, GENERATION, 1);
+		entry->transit_count++;
+	}
+	brcmf_skb_if_flags_set_field(p, TRANSMIT, 1);
+	brcmf_skb_htod_tag_set_field(p, FIFO, fifo);
+
+	flags = BRCMF_FWS_HTOD_FLAG_PKTFROMHOST;
+	if (!(skcb->if_flags & BRCMF_SKB_IF_FLAGS_CREDITCHECK_MASK)) {
+		/*
+		Indicate that this packet is being sent in response to an
+		explicit request from the firmware side.
+		*/
+		flags |= BRCMF_FWS_HTOD_FLAG_PKT_REQUESTED;
+	}
+	brcmf_skb_htod_tag_set_field(p, FLAGS, flags);
+	if (header_needed) {
+		brcmf_fws_hdrpush(fws, p);
+		rc = brcmf_fws_hanger_pushpkt(&fws->hanger, p, hslot);
+		if (rc)
+			brcmf_err("hanger push failed: rc=%d\n", rc);
+	} else {
+		int gen;
+
+		/* remove old header */
+		rc = brcmf_proto_hdrpull(fws->drvr, false, &ifidx, p);
+		if (rc == 0) {
+			hslot = brcmf_skb_htod_tag_get_field(p, HSLOT);
+			brcmf_fws_hanger_get_genbit(&fws->hanger, p,
+						    hslot, &gen);
+			brcmf_skb_htod_tag_set_field(p, GENERATION, gen);
+
+			/* push new header */
+			brcmf_fws_hdrpush(fws, p);
+		}
+	}
+
+	return rc;
+}
+
+static int
+brcmf_fws_rollback_toq(struct brcmf_fws_info *fws, struct sk_buff *skb)
+{
+	/*
+	put the packet back to the head of queue
+
+	- suppressed packet goes back to suppress sub-queue
+	- pull out the header, if new or delayed packet
+
+	Note: hslot is used only when header removal is done.
+	*/
+	struct brcmf_fws_mac_descriptor *entry;
+	enum brcmf_fws_skb_state state;
+	struct sk_buff *pktout;
+	int rc = 0;
+	int fifo;
+	int hslot;
+	u8 ifidx;
+
+	fifo = brcmf_skb_if_flags_get_field(skb, FIFO);
+	state = brcmf_skbcb(skb)->state;
+	entry = brcmf_skbcb(skb)->mac;
+
+	if (entry != NULL) {
+		if (state == BRCMF_FWS_SKBSTATE_SUPPRESSED) {
+			/* wl-header is saved for suppressed packets */
+			pktout = brcmu_pktq_penq_head(&entry->psq, 2 * fifo + 1,
+						      skb);
+			if (pktout == NULL) {
+				brcmf_err("suppress queue full\n");
+				rc = -ENOSPC;
+			}
+		} else {
+			hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT);
+
+			/* remove header first */
+			rc = brcmf_proto_hdrpull(fws->drvr, false, &ifidx, skb);
+			if (rc) {
+				brcmf_err("header removal failed\n");
+				/* free the hanger slot */
+				brcmf_fws_hanger_poppkt(&fws->hanger, hslot,
+							&pktout, true);
+				brcmf_txfinalize(fws->drvr, skb, false);
+				rc = -EINVAL;
+				goto fail;
+			}
+
+			/* delay-q packets are going to delay-q */
+			pktout = brcmu_pktq_penq_head(&entry->psq,
+						      2 * fifo, skb);
+			if (pktout == NULL) {
+				brcmf_err("delay queue full\n");
+				rc = -ENOSPC;
+			}
+
+			/* free the hanger slot */
+			brcmf_fws_hanger_poppkt(&fws->hanger, hslot, &pktout,
+						true);
+
+			/* decrement sequence count */
+			entry->seq[fifo]--;
+		}
+		/*
+		if this packet did not count against FIFO credit, it must have
+		taken a requested_credit from the firmware (for pspoll etc.)
+		*/
+		if (!(brcmf_skbcb(skb)->if_flags &
+		      BRCMF_SKB_IF_FLAGS_CREDITCHECK_MASK))
+			entry->requested_credit++;
+	} else {
+		brcmf_err("no mac entry linked\n");
+		rc = -ENOENT;
+	}
+
+
+fail:
+	if (rc)
+		fws->stats.rollback_failed++;
+	else
+		fws->stats.rollback_success++;
+	return rc;
+}
+
+static int brcmf_fws_consume_credit(struct brcmf_fws_info *fws, int fifo,
+				    struct sk_buff *skb)
+{
+	struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(skb)->mac;
+	int *credit = &fws->fifo_credit[fifo];
+	int use_credit = 1;
+
+	brcmf_dbg(TRACE, "enter: ac=%d, credits=%d\n", fifo, *credit);
+
+	if (entry->requested_credit > 0) {
+		/*
+		 * if the packet was pulled out while destination is in
+		 * closed state but had a non-zero packets requested,
+		 * then this should not count against the FIFO credit.
+		 * That is due to the fact that the firmware will
+		 * most likely hold onto this packet until a suitable
+		 * time later to push it to the appropriate AC FIFO.
+		 */
+		entry->requested_credit--;
+		if (entry->state == BRCMF_FWS_STATE_CLOSE)
+			use_credit = 0;
+	} else if (entry->requested_packet > 0) {
+		entry->requested_packet--;
+		brcmf_skb_if_flags_set_field(skb, REQUESTED, 1);
+		if (entry->state == BRCMF_FWS_STATE_CLOSE)
+			use_credit = 0;
+	}
+	brcmf_skb_if_flags_set_field(skb, CREDITCHECK, use_credit);
+	if (!use_credit) {
+		brcmf_dbg(TRACE, "exit: no creditcheck set\n");
+		return 0;
+	}
+
+	if (!(*credit)) {
+		brcmf_dbg(TRACE, "exit: credits depleted\n");
+		return -ENAVAIL;
+	}
+	(*credit)--;
+	if (!(*credit))
+		fws->fifo_credit_map &= ~(1 << fifo);
+	brcmf_dbg(TRACE, "exit: ac=%d, credits=%d\n", fifo, *credit);
+	return 0;
+}
+
+static int brcmf_fws_commit_skb(struct brcmf_fws_info *fws, int fifo,
+				struct sk_buff *skb)
+{
+	struct brcmf_skbuff_cb *skcb = brcmf_skbcb(skb);
+	struct brcmf_fws_mac_descriptor *entry;
+	struct brcmf_bus *bus = fws->drvr->bus_if;
+	int rc;
+
+	entry = skcb->mac;
+	if (IS_ERR(entry))
+		return PTR_ERR(entry);
+
+	rc = brcmf_fws_precommit_skb(fws, fifo, skb);
+	if (rc < 0) {
+		fws->stats.generic_error++;
+		goto rollback;
+	}
+
+	rc = brcmf_bus_txdata(bus, skb);
+	if (rc < 0)
+		goto rollback;
+
+	entry->seq[fifo]++;
+	fws->stats.pkt2bus++;
+	if (brcmf_skbcb(skb)->if_flags & BRCMF_SKB_IF_FLAGS_CREDITCHECK_MASK) {
+		fws->stats.send_pkts[fifo]++;
+		fws->stats.fifo_credits_sent[fifo]++;
+	}
+
+	return rc;
+
+rollback:
+	rc = brcmf_fws_rollback_toq(fws, skb);
+	return rc;
+}
+
+int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)
+{
+	struct brcmf_pub *drvr = ifp->drvr;
+	struct brcmf_skbuff_cb *skcb = brcmf_skbcb(skb);
+	struct ethhdr *eh = (struct ethhdr *)(skb->data);
+	ulong flags;
+	u8 ifidx = ifp->ifidx;
+	int fifo = BRCMF_FWS_FIFO_BCMC;
+	bool multicast = is_multicast_ether_addr(eh->h_dest);
+
+	/* determine the priority */
+	if (!skb->priority)
+		skb->priority = cfg80211_classify8021d(skb);
+
+	drvr->tx_multicast += !!multicast;
+	if (ntohs(eh->h_proto) == ETH_P_PAE)
+		atomic_inc(&ifp->pend_8021x_cnt);
+
+	if (!brcmf_fws_fc_active(drvr->fws)) {
+		/* If the protocol uses a data header, apply it */
+		brcmf_proto_hdrpush(drvr, ifidx, 0, skb);
+
+		/* Use bus module to send data frame */
+		return brcmf_bus_txdata(drvr->bus_if, skb);
+	}
+
+	/* set control buffer information */
+	skcb->if_flags = 0;
+	skcb->mac = brcmf_fws_find_mac_desc(drvr->fws, ifidx, eh->h_dest);
+	skcb->state = BRCMF_FWS_SKBSTATE_NEW;
+	brcmf_skb_if_flags_set_field(skb, INDEX, ifidx);
+	if (!multicast)
+		fifo = brcmf_fws_prio2fifo[skb->priority];
+	brcmf_skb_if_flags_set_field(skb, FIFO, fifo);
+
+	brcmf_dbg(TRACE, "ea=%pM, multi=%d, fifo=%d\n", eh->h_dest,
+		  multicast, fifo);
+
+	brcmf_fws_lock(drvr, flags);
+	if (!brcmf_fws_mac_desc_ready(skcb->mac, fifo) ||
+	    (!multicast &&
+	     brcmf_fws_consume_credit(drvr->fws, fifo, skb) < 0)) {
+		/* enqueue the packet in delayQ */
+		drvr->fws->fifo_delay_map |= 1 << fifo;
+		brcmf_fws_enq(drvr->fws, BRCMF_FWS_SKBSTATE_DELAYED, fifo, skb);
+	} else {
+		brcmf_fws_commit_skb(drvr->fws, fifo, skb);
+	}
+	brcmf_fws_unlock(drvr, flags);
+	return 0;
+}
+
+void brcmf_fws_reset_interface(struct brcmf_if *ifp)
+{
+	struct brcmf_fws_mac_descriptor *entry = ifp->fws_desc;
+
+	brcmf_dbg(TRACE, "enter: idx=%d\n", ifp->bssidx);
+	if (!entry)
+		return;
+
+	brcmf_fws_init_mac_descriptor(entry, ifp->mac_addr, ifp->ifidx);
+}
+
+void brcmf_fws_add_interface(struct brcmf_if *ifp)
+{
+	struct brcmf_fws_info *fws = ifp->drvr->fws;
+	struct brcmf_fws_mac_descriptor *entry;
+
+	brcmf_dbg(TRACE, "enter: idx=%d, mac=%pM\n",
+		  ifp->bssidx, ifp->mac_addr);
+	if (!ifp->drvr->fw_signals)
+		return;
+
+	entry = &fws->desc.iface[ifp->ifidx];
+	ifp->fws_desc = entry;
+	brcmf_fws_init_mac_descriptor(entry, ifp->mac_addr, ifp->ifidx);
+	brcmu_pktq_init(&entry->psq, BRCMF_FWS_PSQ_PREC_COUNT,
+			BRCMF_FWS_PSQ_LEN);
+}
+
+void brcmf_fws_del_interface(struct brcmf_if *ifp)
+{
+	struct brcmf_fws_mac_descriptor *entry = ifp->fws_desc;
+
+	brcmf_dbg(TRACE, "enter: idx=%d\n", ifp->bssidx);
+	if (!entry)
+		return;
+
+	ifp->fws_desc = NULL;
+	brcmf_fws_clear_mac_descriptor(entry);
+	brcmf_fws_cleanup(ifp->drvr->fws, ifp->ifidx);
+}
+
+static void brcmf_fws_dequeue_worker(struct work_struct *worker)
+{
+	struct brcmf_fws_info *fws;
+	struct sk_buff *skb;
+	ulong flags;
+	int fifo;
+	int credit;
+
+	fws = container_of(worker, struct brcmf_fws_info, fws_dequeue_work);
+
+	brcmf_dbg(TRACE, "enter: fws=%p\n", fws);
+	brcmf_fws_lock(fws->drvr, flags);
+	for (fifo = NL80211_NUM_ACS; fifo >= 0; fifo--) {
+		brcmf_dbg(TRACE, "fifo %d credit %d\n", fifo,
+			  fws->fifo_credit[fifo]);
+		for (credit = 0; credit < fws->fifo_credit[fifo]; /* nop */) {
+			skb = brcmf_fws_deq(fws, fifo);
+			if (!skb)
+				break;
+			if (!brcmf_fws_commit_skb(fws, fifo, skb) &&
+			    brcmf_skbcb(skb)->if_flags &
+			    BRCMF_SKB_IF_FLAGS_CREDITCHECK_MASK)
+				credit++;
+		}
+		fws->fifo_credit[fifo] -= credit;
+	}
+	brcmf_fws_unlock(fws->drvr, flags);
+}
+
+int brcmf_fws_init(struct brcmf_pub *drvr)
+{
+	u32 tlv = BRCMF_FWS_FLAGS_RSSI_SIGNALS;
+	int rc;
+
+	if (!drvr->fw_signals)
+		return 0;
+
+	spin_lock_init(&drvr->fws_spinlock);
+
+	drvr->fws = kzalloc(sizeof(*(drvr->fws)), GFP_KERNEL);
+	if (!drvr->fws) {
+		rc = -ENOMEM;
+		goto fail;
+	}
+
+	/* set linkage back */
+	drvr->fws->drvr = drvr;
+	drvr->fws->fcmode = fcmode;
+
+	drvr->fws->fws_wq = create_singlethread_workqueue("brcmf_fws_wq");
+	if (drvr->fws->fws_wq == NULL) {
+		brcmf_err("workqueue creation failed\n");
+		rc = -EBADF;
+		goto fail;
+	}
+	INIT_WORK(&drvr->fws->fws_dequeue_work, brcmf_fws_dequeue_worker);
+
+	/* enable firmware signalling if fcmode active */
+	if (drvr->fws->fcmode != BRCMF_FWS_FCMODE_NONE)
+		tlv |= BRCMF_FWS_FLAGS_XONXOFF_SIGNALS |
+		       BRCMF_FWS_FLAGS_CREDIT_STATUS_SIGNALS;
+
+	rc = brcmf_fil_iovar_int_set(drvr->iflist[0], "tlv", tlv);
+	if (rc < 0) {
+		brcmf_err("failed to set bdcv2 tlv signaling\n");
+		goto fail;
+	}
+
+	if (brcmf_fweh_register(drvr, BRCMF_E_FIFO_CREDIT_MAP,
+				brcmf_fws_notify_credit_map)) {
+		brcmf_err("register credit map handler failed\n");
+		goto fail;
+	}
+
+	brcmf_fws_hanger_init(&drvr->fws->hanger);
+	brcmf_fws_init_mac_descriptor(&drvr->fws->desc.other, NULL, 0);
+	brcmu_pktq_init(&drvr->fws->desc.other.psq, BRCMF_FWS_PSQ_PREC_COUNT,
+			BRCMF_FWS_PSQ_LEN);
+
+	/* create debugfs file for statistics */
+	brcmf_debugfs_create_fws_stats(drvr, &drvr->fws->stats);
+
+	/* TODO: remove upon feature delivery */
+	brcmf_err("%s bdcv2 tlv signaling [%x]\n",
+		  drvr->fw_signals ? "enabled" : "disabled", tlv);
+	return 0;
+
+fail:
+	/* disable flow control entirely */
+	drvr->fw_signals = false;
+	brcmf_fws_deinit(drvr);
+	return rc;
+}
+
+void brcmf_fws_deinit(struct brcmf_pub *drvr)
+{
+	struct brcmf_fws_info *fws = drvr->fws;
+	ulong flags;
+
+	if (!fws)
+		return;
+
+	/* cleanup */
+	brcmf_fws_lock(drvr, flags);
+	brcmf_fws_cleanup(fws, -1);
+	drvr->fws = NULL;
+	brcmf_fws_unlock(drvr, flags);
+
+	/* free top structure */
+	kfree(fws);
+}
+
+bool brcmf_fws_fc_active(struct brcmf_fws_info *fws)
+{
+	if (!fws)
+		return false;
+
+	brcmf_dbg(TRACE, "enter: mode=%d\n", fws->fcmode);
+	return fws->fcmode != BRCMF_FWS_FCMODE_NONE;
+}
+
+void brcmf_fws_bustxfail(struct brcmf_fws_info *fws, struct sk_buff *skb)
+{
+	ulong flags;
+
+	brcmf_fws_lock(fws->drvr, flags);
+	brcmf_fws_txstatus_process(fws, BRCMF_FWS_TXSTATUS_FW_TOSSED,
+				   brcmf_skb_htod_tag_get_field(skb, HSLOT), 0);
+	/* the packet never reached firmware so reclaim credit */
+	if (fws->fcmode == BRCMF_FWS_FCMODE_EXPLICIT_CREDIT &&
+	    brcmf_skbcb(skb)->if_flags & BRCMF_SKB_IF_FLAGS_CREDITCHECK_MASK) {
+		brcmf_fws_return_credits(fws,
+					 brcmf_skb_htod_tag_get_field(skb,
+								      FIFO),
+					 1);
+		brcmf_fws_schedule_deq(fws);
+	}
+	brcmf_fws_unlock(fws->drvr, flags);
+}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h
new file mode 100644
index 0000000..fbe483d
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2012 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 FWSIGNAL_H_
+#define FWSIGNAL_H_
+
+int brcmf_fws_init(struct brcmf_pub *drvr);
+void brcmf_fws_deinit(struct brcmf_pub *drvr);
+bool brcmf_fws_fc_active(struct brcmf_fws_info *fws);
+int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
+		      struct sk_buff *skb);
+int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb);
+
+void brcmf_fws_reset_interface(struct brcmf_if *ifp);
+void brcmf_fws_add_interface(struct brcmf_if *ifp);
+void brcmf_fws_del_interface(struct brcmf_if *ifp);
+void brcmf_fws_bustxfail(struct brcmf_fws_info *fws, struct sk_buff *skb);
+
+#endif /* FWSIGNAL_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
index 4166e64..bca31a8 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
@@ -1118,7 +1118,7 @@ static void brcmf_p2p_afx_handler(struct work_struct *work)
 	if (afx_hdl->is_listen && afx_hdl->my_listen_chan)
 		/* 100ms ~ 300ms */
 		err = brcmf_p2p_discover_listen(p2p, afx_hdl->my_listen_chan,
-						100 * (1 + (random32() % 3)));
+					100 * (1 + (prandom_u32() % 3)));
 	else
 		err = brcmf_p2p_act_frm_search(p2p, afx_hdl->peer_listen_chan);
 
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.c b/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.c
new file mode 100644
index 0000000..b505db4
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.c
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2012 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> /* bug in tracepoint.h, it should include this */
+
+#ifndef __CHECKER__
+#define CREATE_TRACE_POINTS
+#include "tracepoint.h"
+#endif
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h b/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h
new file mode 100644
index 0000000..35efc7a
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2013 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.
+ */
+#if !defined(BRCMF_TRACEPOINT_H_) || defined(TRACE_HEADER_MULTI_READ)
+#define BRCMF_TRACEPOINT_H_
+
+#include <linux/types.h>
+#include <linux/tracepoint.h>
+
+#ifndef CONFIG_BRCM_TRACING
+
+#undef TRACE_EVENT
+#define TRACE_EVENT(name, proto, ...) \
+static inline void trace_ ## name(proto) {}
+
+#undef DECLARE_EVENT_CLASS
+#define DECLARE_EVENT_CLASS(...)
+
+#undef DEFINE_EVENT
+#define DEFINE_EVENT(evt_class, name, proto, ...) \
+static inline void trace_ ## name(proto) {}
+
+#endif /* CONFIG_BRCM_TRACING */
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM	brcmfmac
+
+#define MAX_MSG_LEN		100
+
+TRACE_EVENT(brcmf_err,
+	TP_PROTO(const char *func, struct va_format *vaf),
+	TP_ARGS(func, vaf),
+	TP_STRUCT__entry(
+		__string(func, func)
+		__dynamic_array(char, msg, MAX_MSG_LEN)
+	),
+	TP_fast_assign(
+		__assign_str(func, func);
+		WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg),
+				       MAX_MSG_LEN, vaf->fmt,
+				       *vaf->va) >= MAX_MSG_LEN);
+	),
+	TP_printk("%s: %s", __get_str(func), __get_str(msg))
+);
+
+TRACE_EVENT(brcmf_dbg,
+	TP_PROTO(u32 level, const char *func, struct va_format *vaf),
+	TP_ARGS(level, func, vaf),
+	TP_STRUCT__entry(
+		__field(u32, level)
+		__string(func, func)
+		__dynamic_array(char, msg, MAX_MSG_LEN)
+	),
+	TP_fast_assign(
+		__entry->level = level;
+		__assign_str(func, func);
+		WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg),
+				       MAX_MSG_LEN, vaf->fmt,
+				       *vaf->va) >= MAX_MSG_LEN);
+	),
+	TP_printk("%s: %s", __get_str(func), __get_str(msg))
+);
+
+#ifdef CONFIG_BRCM_TRACING
+
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE tracepoint
+
+#include <trace/define_trace.h>
+
+#endif /* CONFIG_BRCM_TRACING */
+
+#endif /* BRCMF_TRACEPOINT_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
index 42289e9..01aed7a 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
@@ -112,11 +112,6 @@ struct brcmf_usbdev_info {
 static void brcmf_usb_rx_refill(struct brcmf_usbdev_info *devinfo,
 				struct brcmf_usbreq  *req);
 
-MODULE_AUTHOR("Broadcom Corporation");
-MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN fullmac usb driver.");
-MODULE_SUPPORTED_DEVICE("Broadcom 802.11n WLAN fullmac usb cards");
-MODULE_LICENSE("Dual BSD/GPL");
-
 static struct brcmf_usbdev *brcmf_usb_get_buspub(struct device *dev)
 {
 	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
@@ -422,8 +417,6 @@ static void brcmf_usb_tx_complete(struct urb *urb)
 	brcmf_usb_del_fromq(devinfo, req);
 
 	brcmf_txcomplete(devinfo->dev, req->skb, urb->status == 0);
-
-	brcmu_pkt_buf_free_skb(req->skb);
 	req->skb = NULL;
 	brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req, &devinfo->tx_freecount);
 	if (devinfo->tx_freecount > devinfo->tx_high_watermark &&
@@ -577,15 +570,17 @@ static int brcmf_usb_tx(struct device *dev, struct sk_buff *skb)
 	int ret;
 
 	brcmf_dbg(USB, "Enter, skb=%p\n", skb);
-	if (devinfo->bus_pub.state != BRCMFMAC_USB_STATE_UP)
-		return -EIO;
+	if (devinfo->bus_pub.state != BRCMFMAC_USB_STATE_UP) {
+		ret = -EIO;
+		goto fail;
+	}
 
 	req = brcmf_usb_deq(devinfo, &devinfo->tx_freeq,
 					&devinfo->tx_freecount);
 	if (!req) {
-		brcmu_pkt_buf_free_skb(skb);
 		brcmf_err("no req to send\n");
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto fail;
 	}
 
 	req->skb = skb;
@@ -598,18 +593,21 @@ static int brcmf_usb_tx(struct device *dev, struct sk_buff *skb)
 	if (ret) {
 		brcmf_err("brcmf_usb_tx usb_submit_urb FAILED\n");
 		brcmf_usb_del_fromq(devinfo, req);
-		brcmu_pkt_buf_free_skb(req->skb);
 		req->skb = NULL;
 		brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req,
-						&devinfo->tx_freecount);
-	} else {
-		if (devinfo->tx_freecount < devinfo->tx_low_watermark &&
-			!devinfo->tx_flowblock) {
-			brcmf_txflowblock(dev, true);
-			devinfo->tx_flowblock = true;
-		}
+			      &devinfo->tx_freecount);
+		goto fail;
 	}
 
+	if (devinfo->tx_freecount < devinfo->tx_low_watermark &&
+	    !devinfo->tx_flowblock) {
+		brcmf_txflowblock(dev, true);
+		devinfo->tx_flowblock = true;
+	}
+	return 0;
+
+fail:
+	brcmf_txcomplete(dev, skb, false);
 	return ret;
 }
 
@@ -1485,6 +1483,7 @@ static struct usb_device_id brcmf_usb_devid_table[] = {
 	{ USB_DEVICE(BRCMF_USB_VENDOR_ID_BROADCOM, BRCMF_USB_DEVICE_ID_BCMFW) },
 	{ }
 };
+
 MODULE_DEVICE_TABLE(usb, brcmf_usb_devid_table);
 MODULE_FIRMWARE(BRCMF_USB_43143_FW_NAME);
 MODULE_FIRMWARE(BRCMF_USB_43236_FW_NAME);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
index 2af9c0f..5368ad2 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
@@ -182,64 +182,6 @@ static struct ieee80211_channel __wl_5ghz_a_channels[] = {
 	CHAN5G(216, 0),
 };
 
-static struct ieee80211_channel __wl_5ghz_n_channels[] = {
-	CHAN5G(32, 0), CHAN5G(34, 0),
-	CHAN5G(36, 0), CHAN5G(38, 0),
-	CHAN5G(40, 0), CHAN5G(42, 0),
-	CHAN5G(44, 0), CHAN5G(46, 0),
-	CHAN5G(48, 0), CHAN5G(50, 0),
-	CHAN5G(52, 0), CHAN5G(54, 0),
-	CHAN5G(56, 0), CHAN5G(58, 0),
-	CHAN5G(60, 0), CHAN5G(62, 0),
-	CHAN5G(64, 0), CHAN5G(66, 0),
-	CHAN5G(68, 0), CHAN5G(70, 0),
-	CHAN5G(72, 0), CHAN5G(74, 0),
-	CHAN5G(76, 0), CHAN5G(78, 0),
-	CHAN5G(80, 0), CHAN5G(82, 0),
-	CHAN5G(84, 0), CHAN5G(86, 0),
-	CHAN5G(88, 0), CHAN5G(90, 0),
-	CHAN5G(92, 0), CHAN5G(94, 0),
-	CHAN5G(96, 0), CHAN5G(98, 0),
-	CHAN5G(100, 0), CHAN5G(102, 0),
-	CHAN5G(104, 0), CHAN5G(106, 0),
-	CHAN5G(108, 0), CHAN5G(110, 0),
-	CHAN5G(112, 0), CHAN5G(114, 0),
-	CHAN5G(116, 0), CHAN5G(118, 0),
-	CHAN5G(120, 0), CHAN5G(122, 0),
-	CHAN5G(124, 0), CHAN5G(126, 0),
-	CHAN5G(128, 0), CHAN5G(130, 0),
-	CHAN5G(132, 0), CHAN5G(134, 0),
-	CHAN5G(136, 0), CHAN5G(138, 0),
-	CHAN5G(140, 0), CHAN5G(142, 0),
-	CHAN5G(144, 0), CHAN5G(145, 0),
-	CHAN5G(146, 0), CHAN5G(147, 0),
-	CHAN5G(148, 0), CHAN5G(149, 0),
-	CHAN5G(150, 0), CHAN5G(151, 0),
-	CHAN5G(152, 0), CHAN5G(153, 0),
-	CHAN5G(154, 0), CHAN5G(155, 0),
-	CHAN5G(156, 0), CHAN5G(157, 0),
-	CHAN5G(158, 0), CHAN5G(159, 0),
-	CHAN5G(160, 0), CHAN5G(161, 0),
-	CHAN5G(162, 0), CHAN5G(163, 0),
-	CHAN5G(164, 0), CHAN5G(165, 0),
-	CHAN5G(166, 0), CHAN5G(168, 0),
-	CHAN5G(170, 0), CHAN5G(172, 0),
-	CHAN5G(174, 0), CHAN5G(176, 0),
-	CHAN5G(178, 0), CHAN5G(180, 0),
-	CHAN5G(182, 0), CHAN5G(184, 0),
-	CHAN5G(186, 0), CHAN5G(188, 0),
-	CHAN5G(190, 0), CHAN5G(192, 0),
-	CHAN5G(194, 0), CHAN5G(196, 0),
-	CHAN5G(198, 0), CHAN5G(200, 0),
-	CHAN5G(202, 0), CHAN5G(204, 0),
-	CHAN5G(206, 0), CHAN5G(208, 0),
-	CHAN5G(210, 0), CHAN5G(212, 0),
-	CHAN5G(214, 0), CHAN5G(216, 0),
-	CHAN5G(218, 0), CHAN5G(220, 0),
-	CHAN5G(222, 0), CHAN5G(224, 0),
-	CHAN5G(226, 0), CHAN5G(228, 0),
-};
-
 static struct ieee80211_supported_band __wl_band_2ghz = {
 	.band = IEEE80211_BAND_2GHZ,
 	.channels = __wl_2ghz_channels,
@@ -256,12 +198,28 @@ static struct ieee80211_supported_band __wl_band_5ghz_a = {
 	.n_bitrates = wl_a_rates_size,
 };
 
-static struct ieee80211_supported_band __wl_band_5ghz_n = {
-	.band = IEEE80211_BAND_5GHZ,
-	.channels = __wl_5ghz_n_channels,
-	.n_channels = ARRAY_SIZE(__wl_5ghz_n_channels),
-	.bitrates = wl_a_rates,
-	.n_bitrates = wl_a_rates_size,
+/* This is to override regulatory domains defined in cfg80211 module (reg.c)
+ * By default world regulatory domain defined in reg.c puts the flags
+ * NL80211_RRF_PASSIVE_SCAN and NL80211_RRF_NO_IBSS for 5GHz channels (for
+ * 36..48 and 149..165). With respect to these flags, wpa_supplicant doesn't
+ * start p2p operations on 5GHz channels. All the changes in world regulatory
+ * domain are to be done here.
+ */
+static const struct ieee80211_regdomain brcmf_regdom = {
+	.n_reg_rules = 4,
+	.alpha2 =  "99",
+	.reg_rules = {
+		/* IEEE 802.11b/g, channels 1..11 */
+		REG_RULE(2412-10, 2472+10, 40, 6, 20, 0),
+		/* If any */
+		/* IEEE 802.11 channel 14 - Only JP enables
+		 * this and for 802.11b only
+		 */
+		REG_RULE(2484-10, 2484+10, 20, 6, 20, 0),
+		/* IEEE 802.11a, channel 36..64 */
+		REG_RULE(5150-10, 5350+10, 40, 6, 20, 0),
+		/* IEEE 802.11a, channel 100..165 */
+		REG_RULE(5470-10, 5850+10, 40, 6, 20, 0), }
 };
 
 static const u32 __wl_cipher_suites[] = {
@@ -1891,8 +1849,10 @@ static s32
 brcmf_add_keyext(struct wiphy *wiphy, struct net_device *ndev,
 	      u8 key_idx, const u8 *mac_addr, struct key_params *params)
 {
+	struct brcmf_if *ifp = netdev_priv(ndev);
 	struct brcmf_wsec_key key;
 	s32 err = 0;
+	u8 keybuf[8];
 
 	memset(&key, 0, sizeof(key));
 	key.index = (u32) key_idx;
@@ -1916,8 +1876,9 @@ brcmf_add_keyext(struct wiphy *wiphy, struct net_device *ndev,
 		brcmf_dbg(CONN, "Setting the key index %d\n", key.index);
 		memcpy(key.data, params->key, key.len);
 
-		if (params->cipher == WLAN_CIPHER_SUITE_TKIP) {
-			u8 keybuf[8];
+		if ((ifp->vif->mode != WL_MODE_AP) &&
+		    (params->cipher == WLAN_CIPHER_SUITE_TKIP)) {
+			brcmf_dbg(CONN, "Swapping RX/TX MIC key\n");
 			memcpy(keybuf, &key.data[24], sizeof(keybuf));
 			memcpy(&key.data[24], &key.data[16], sizeof(keybuf));
 			memcpy(&key.data[16], keybuf, sizeof(keybuf));
@@ -2013,7 +1974,7 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
 		break;
 	case WLAN_CIPHER_SUITE_TKIP:
 		if (ifp->vif->mode != WL_MODE_AP) {
-			brcmf_dbg(CONN, "Swapping key\n");
+			brcmf_dbg(CONN, "Swapping RX/TX MIC key\n");
 			memcpy(keybuf, &key.data[24], sizeof(keybuf));
 			memcpy(&key.data[24], &key.data[16], sizeof(keybuf));
 			memcpy(&key.data[16], keybuf, sizeof(keybuf));
@@ -2118,8 +2079,7 @@ brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev,
 		err = -EAGAIN;
 		goto done;
 	}
-	switch (wsec & ~SES_OW_ENABLED) {
-	case WEP_ENABLED:
+	if (wsec & WEP_ENABLED) {
 		sec = &profile->sec;
 		if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP40) {
 			params.cipher = WLAN_CIPHER_SUITE_WEP40;
@@ -2128,16 +2088,13 @@ brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev,
 			params.cipher = WLAN_CIPHER_SUITE_WEP104;
 			brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_WEP104\n");
 		}
-		break;
-	case TKIP_ENABLED:
+	} else if (wsec & TKIP_ENABLED) {
 		params.cipher = WLAN_CIPHER_SUITE_TKIP;
 		brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_TKIP\n");
-		break;
-	case AES_ENABLED:
+	} else if (wsec & AES_ENABLED) {
 		params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
 		brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_AES_CMAC\n");
-		break;
-	default:
+	} else  {
 		brcmf_err("Invalid algo (0x%x)\n", wsec);
 		err = -EINVAL;
 		goto done;
@@ -3052,16 +3009,16 @@ brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy,
 	int i;
 	int ret = 0;
 
-	brcmf_dbg(SCAN, "Enter n_match_sets:%d   n_ssids:%d\n",
+	brcmf_dbg(SCAN, "Enter n_match_sets:%d n_ssids:%d\n",
 		  request->n_match_sets, request->n_ssids);
 	if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {
 		brcmf_err("Scanning already: status (%lu)\n", cfg->scan_status);
 		return -EAGAIN;
 	}
 
-	if (!request || !request->n_ssids || !request->n_match_sets) {
+	if (!request->n_ssids || !request->n_match_sets) {
 		brcmf_err("Invalid sched scan req!! n_ssids:%d\n",
-			  request ? request->n_ssids : 0);
+			  request->n_ssids);
 		return -EINVAL;
 	}
 
@@ -3824,8 +3781,9 @@ exit:
 static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev)
 {
 	struct brcmf_if *ifp = netdev_priv(ndev);
-	s32 err = -EPERM;
+	s32 err;
 	struct brcmf_fil_bss_enable_le bss_enable;
+	struct brcmf_join_params join_params;
 
 	brcmf_dbg(TRACE, "Enter\n");
 
@@ -3833,16 +3791,21 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev)
 		/* Due to most likely deauths outstanding we sleep */
 		/* first to make sure they get processed by fw. */
 		msleep(400);
-		err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_AP, 0);
-		if (err < 0) {
-			brcmf_err("setting AP mode failed %d\n", err);
-			goto exit;
-		}
+
+		memset(&join_params, 0, sizeof(join_params));
+		err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID,
+					     &join_params, sizeof(join_params));
+		if (err < 0)
+			brcmf_err("SET SSID error (%d)\n", err);
 		err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 0);
-		if (err < 0) {
+		if (err < 0)
 			brcmf_err("BRCMF_C_UP error %d\n", err);
-			goto exit;
-		}
+		err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_AP, 0);
+		if (err < 0)
+			brcmf_err("setting AP mode failed %d\n", err);
+		err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_INFRA, 0);
+		if (err < 0)
+			brcmf_err("setting INFRA mode failed %d\n", err);
 	} else {
 		bss_enable.bsscfg_idx = cpu_to_le32(ifp->bssidx);
 		bss_enable.enable = cpu_to_le32(0);
@@ -3855,7 +3818,6 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev)
 	set_bit(BRCMF_VIF_STATUS_AP_CREATING, &ifp->vif->sme_state);
 	clear_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state);
 
-exit:
 	return err;
 }
 
@@ -4188,13 +4150,6 @@ static struct wiphy *brcmf_setup_wiphy(struct device *phydev)
 	wiphy->iface_combinations = brcmf_iface_combos;
 	wiphy->n_iface_combinations = ARRAY_SIZE(brcmf_iface_combos);
 	wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
-	wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a;	/* Set
-						* it as 11a by default.
-						* This will be updated with
-						* 11n phy tables in
-						* "ifconfig up"
-						* if phy has 11n capability
-						*/
 	wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
 	wiphy->cipher_suites = __wl_cipher_suites;
 	wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
@@ -4204,6 +4159,9 @@ static struct wiphy *brcmf_setup_wiphy(struct device *phydev)
 	wiphy->mgmt_stypes = brcmf_txrx_stypes;
 	wiphy->max_remain_on_channel_duration = 5000;
 	brcmf_wiphy_pno_params(wiphy);
+	brcmf_dbg(INFO, "Registering custom regulatory\n");
+	wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
+	wiphy_apply_custom_regulatory(wiphy, &brcmf_regdom);
 	err = wiphy_register(wiphy);
 	if (err < 0) {
 		brcmf_err("Could not register wiphy device (%d)\n", err);
@@ -4927,34 +4885,248 @@ dongle_scantime_out:
 	return err;
 }
 
-static s32 wl_update_wiphybands(struct brcmf_cfg80211_info *cfg)
+
+static s32 brcmf_construct_reginfo(struct brcmf_cfg80211_info *cfg, u32 bw_cap)
+{
+	struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
+	struct ieee80211_channel *band_chan_arr;
+	struct brcmf_chanspec_list *list;
+	s32 err;
+	u8 *pbuf;
+	u32 i, j;
+	u32 total;
+	u16 chanspec;
+	enum ieee80211_band band;
+	u32 channel;
+	u32 *n_cnt;
+	bool ht40_allowed;
+	u32 index;
+	u32 ht40_flag;
+	bool update;
+	u32 array_size;
+
+	pbuf = kzalloc(BRCMF_DCMD_MEDLEN, GFP_KERNEL);
+
+	if (pbuf == NULL)
+		return -ENOMEM;
+
+	list = (struct brcmf_chanspec_list *)pbuf;
+
+	err = brcmf_fil_iovar_data_get(ifp, "chanspecs", pbuf,
+				       BRCMF_DCMD_MEDLEN);
+	if (err) {
+		brcmf_err("get chanspecs error (%d)\n", err);
+		goto exit;
+	}
+
+	__wl_band_2ghz.n_channels = 0;
+	__wl_band_5ghz_a.n_channels = 0;
+
+	total = le32_to_cpu(list->count);
+	for (i = 0; i < total; i++) {
+		chanspec = (u16)le32_to_cpu(list->element[i]);
+		channel = CHSPEC_CHANNEL(chanspec);
+
+		if (CHSPEC_IS40(chanspec)) {
+			if (CHSPEC_SB_UPPER(chanspec))
+				channel += CH_10MHZ_APART;
+			else
+				channel -= CH_10MHZ_APART;
+		} else if (CHSPEC_IS80(chanspec)) {
+			brcmf_dbg(INFO, "HT80 center channel : %d\n",
+				  channel);
+			continue;
+		}
+		if (CHSPEC_IS2G(chanspec) && (channel >= CH_MIN_2G_CHANNEL) &&
+		    (channel <= CH_MAX_2G_CHANNEL)) {
+			band_chan_arr = __wl_2ghz_channels;
+			array_size = ARRAY_SIZE(__wl_2ghz_channels);
+			n_cnt = &__wl_band_2ghz.n_channels;
+			band = IEEE80211_BAND_2GHZ;
+			ht40_allowed = (bw_cap == WLC_N_BW_40ALL);
+		} else if (CHSPEC_IS5G(chanspec) &&
+			   channel >= CH_MIN_5G_CHANNEL) {
+			band_chan_arr = __wl_5ghz_a_channels;
+			array_size = ARRAY_SIZE(__wl_5ghz_a_channels);
+			n_cnt = &__wl_band_5ghz_a.n_channels;
+			band = IEEE80211_BAND_5GHZ;
+			ht40_allowed = !(bw_cap == WLC_N_BW_20ALL);
+		} else {
+			brcmf_err("Invalid channel Sepc. 0x%x.\n", chanspec);
+			continue;
+		}
+		if (!ht40_allowed && CHSPEC_IS40(chanspec))
+			continue;
+		update = false;
+		for (j = 0; (j < *n_cnt && (*n_cnt < array_size)); j++) {
+			if (band_chan_arr[j].hw_value == channel) {
+				update = true;
+				break;
+			}
+		}
+		if (update)
+			index = j;
+		else
+			index = *n_cnt;
+		if (index <  array_size) {
+			band_chan_arr[index].center_freq =
+				ieee80211_channel_to_frequency(channel, band);
+			band_chan_arr[index].hw_value = channel;
+
+			if (CHSPEC_IS40(chanspec) && ht40_allowed) {
+				/* assuming the order is HT20, HT40 Upper,
+				 * HT40 lower from chanspecs
+				 */
+				ht40_flag = band_chan_arr[index].flags &
+					    IEEE80211_CHAN_NO_HT40;
+				if (CHSPEC_SB_UPPER(chanspec)) {
+					if (ht40_flag == IEEE80211_CHAN_NO_HT40)
+						band_chan_arr[index].flags &=
+							~IEEE80211_CHAN_NO_HT40;
+					band_chan_arr[index].flags |=
+						IEEE80211_CHAN_NO_HT40PLUS;
+				} else {
+					/* It should be one of
+					 * IEEE80211_CHAN_NO_HT40 or
+					 * IEEE80211_CHAN_NO_HT40PLUS
+					 */
+					band_chan_arr[index].flags &=
+							~IEEE80211_CHAN_NO_HT40;
+					if (ht40_flag == IEEE80211_CHAN_NO_HT40)
+						band_chan_arr[index].flags |=
+						    IEEE80211_CHAN_NO_HT40MINUS;
+				}
+			} else {
+				band_chan_arr[index].flags =
+							IEEE80211_CHAN_NO_HT40;
+				if (band == IEEE80211_BAND_2GHZ)
+					channel |= WL_CHANSPEC_BAND_2G;
+				else
+					channel |= WL_CHANSPEC_BAND_5G;
+				channel |= WL_CHANSPEC_BW_20;
+				err = brcmf_fil_bsscfg_int_get(ifp,
+							       "per_chan_info",
+							       &channel);
+				if (!err) {
+					if (channel & WL_CHAN_RADAR)
+						band_chan_arr[index].flags |=
+							(IEEE80211_CHAN_RADAR |
+							IEEE80211_CHAN_NO_IBSS);
+					if (channel & WL_CHAN_PASSIVE)
+						band_chan_arr[index].flags |=
+						    IEEE80211_CHAN_PASSIVE_SCAN;
+				}
+			}
+			if (!update)
+				(*n_cnt)++;
+		}
+	}
+exit:
+	kfree(pbuf);
+	return err;
+}
+
+
+static s32 brcmf_update_wiphybands(struct brcmf_cfg80211_info *cfg)
 {
 	struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
 	struct wiphy *wiphy;
 	s32 phy_list;
+	u32 band_list[3];
+	u32 nmode;
+	u32 bw_cap = 0;
 	s8 phy;
-	s32 err = 0;
+	s32 err;
+	u32 nband;
+	s32 i;
+	struct ieee80211_supported_band *bands[IEEE80211_NUM_BANDS];
+	s32 index;
 
 	err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_PHYLIST,
 				     &phy_list, sizeof(phy_list));
 	if (err) {
-		brcmf_err("error (%d)\n", err);
+		brcmf_err("BRCMF_C_GET_PHYLIST error (%d)\n", err);
 		return err;
 	}
 
 	phy = ((char *)&phy_list)[0];
-	brcmf_dbg(INFO, "%c phy\n", phy);
-	if (phy == 'n' || phy == 'a') {
-		wiphy = cfg_to_wiphy(cfg);
-		wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_n;
+	brcmf_dbg(INFO, "BRCMF_C_GET_PHYLIST reported: %c phy\n", phy);
+
+
+	err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BANDLIST,
+				     &band_list, sizeof(band_list));
+	if (err) {
+		brcmf_err("BRCMF_C_GET_BANDLIST error (%d)\n", err);
+		return err;
+	}
+	brcmf_dbg(INFO, "BRCMF_C_GET_BANDLIST reported: 0x%08x 0x%08x 0x%08x phy\n",
+		  band_list[0], band_list[1], band_list[2]);
+
+	err = brcmf_fil_iovar_int_get(ifp, "nmode", &nmode);
+	if (err) {
+		brcmf_err("nmode error (%d)\n", err);
+	} else {
+		err = brcmf_fil_iovar_int_get(ifp, "mimo_bw_cap", &bw_cap);
+		if (err)
+			brcmf_err("mimo_bw_cap error (%d)\n", err);
 	}
+	brcmf_dbg(INFO, "nmode=%d, mimo_bw_cap=%d\n", nmode, bw_cap);
+
+	err = brcmf_construct_reginfo(cfg, bw_cap);
+	if (err) {
+		brcmf_err("brcmf_construct_reginfo failed (%d)\n", err);
+		return err;
+	}
+
+	nband = band_list[0];
+	memset(bands, 0, sizeof(bands));
+
+	for (i = 1; i <= nband && i < ARRAY_SIZE(band_list); i++) {
+		index = -1;
+		if ((band_list[i] == WLC_BAND_5G) &&
+		    (__wl_band_5ghz_a.n_channels > 0)) {
+			index = IEEE80211_BAND_5GHZ;
+			bands[index] = &__wl_band_5ghz_a;
+			if ((bw_cap == WLC_N_BW_40ALL) ||
+			    (bw_cap == WLC_N_BW_20IN2G_40IN5G))
+				bands[index]->ht_cap.cap |=
+							IEEE80211_HT_CAP_SGI_40;
+		} else if ((band_list[i] == WLC_BAND_2G) &&
+			   (__wl_band_2ghz.n_channels > 0)) {
+			index = IEEE80211_BAND_2GHZ;
+			bands[index] = &__wl_band_2ghz;
+			if (bw_cap == WLC_N_BW_40ALL)
+				bands[index]->ht_cap.cap |=
+							IEEE80211_HT_CAP_SGI_40;
+		}
+
+		if ((index >= 0) && nmode) {
+			bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_20;
+			bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_DSSSCCK40;
+			bands[index]->ht_cap.ht_supported = true;
+			bands[index]->ht_cap.ampdu_factor =
+						IEEE80211_HT_MAX_AMPDU_64K;
+			bands[index]->ht_cap.ampdu_density =
+						IEEE80211_HT_MPDU_DENSITY_16;
+			/* An HT shall support all EQM rates for one spatial
+			 * stream
+			 */
+			bands[index]->ht_cap.mcs.rx_mask[0] = 0xff;
+		}
+	}
+
+	wiphy = cfg_to_wiphy(cfg);
+	wiphy->bands[IEEE80211_BAND_2GHZ] = bands[IEEE80211_BAND_2GHZ];
+	wiphy->bands[IEEE80211_BAND_5GHZ] = bands[IEEE80211_BAND_5GHZ];
+	wiphy_apply_custom_regulatory(wiphy, &brcmf_regdom);
 
 	return err;
 }
 
+
 static s32 brcmf_dongle_probecap(struct brcmf_cfg80211_info *cfg)
 {
-	return wl_update_wiphybands(cfg);
+	return brcmf_update_wiphybands(cfg);
 }
 
 static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg)
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/Makefile b/drivers/net/wireless/brcm80211/brcmsmac/Makefile
index d3d4151..cba19d8 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/Makefile
+++ b/drivers/net/wireless/brcm80211/brcmsmac/Makefile
@@ -43,6 +43,10 @@ BRCMSMAC_OFILES := \
 	brcms_trace_events.o \
 	debug.o
 
+ifdef CONFIG_BCMA_DRIVER_GPIO
+BRCMSMAC_OFILES += led.o
+endif
+
 MODULEPFX := brcmsmac
 
 obj-$(CONFIG_BRCMSMAC)	+= $(MODULEPFX).o
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c b/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c
index f0888a9..e4fd1ee 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c
@@ -318,12 +318,6 @@
 #define	IS_SIM(chippkg)	\
 	((chippkg == HDLSIM_PKG_ID) || (chippkg == HWSIM_PKG_ID))
 
-#ifdef DEBUG
-#define	SI_MSG(fmt, ...)	pr_debug(fmt, ##__VA_ARGS__)
-#else
-#define	SI_MSG(fmt, ...)	no_printk(fmt, ##__VA_ARGS__)
-#endif				/* DEBUG */
-
 #define	GOODCOREADDR(x, b) \
 	(((x) >= (b)) && ((x) < ((b) + SI_MAXCORES * SI_CORE_SIZE)) && \
 		IS_ALIGNED((x), SI_CORE_SIZE))
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/d11.h b/drivers/net/wireless/brcm80211/brcmsmac/d11.h
index 3f659e0..9035cc4 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/d11.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/d11.h
@@ -457,6 +457,7 @@ struct d11regs {
 /*== maccontrol register ==*/
 #define	MCTL_GMODE		(1U << 31)
 #define	MCTL_DISCARD_PMQ	(1 << 30)
+#define	MCTL_TBTTHOLD		(1 << 28)
 #define	MCTL_WAKE		(1 << 26)
 #define	MCTL_HPS		(1 << 25)
 #define	MCTL_PROMISC		(1 << 24)
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/led.c b/drivers/net/wireless/brcm80211/brcmsmac/led.c
new file mode 100644
index 0000000..74b17ce
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmsmac/led.c
@@ -0,0 +1,126 @@
+#include <net/mac80211.h>
+#include <linux/bcma/bcma_driver_chipcommon.h>
+#include <linux/gpio.h>
+
+#include "mac80211_if.h"
+#include "pub.h"
+#include "main.h"
+#include "led.h"
+
+	/* number of leds */
+#define  BRCMS_LED_NO		4
+	/* behavior mask */
+#define  BRCMS_LED_BEH_MASK	0x7f
+	/* activelow (polarity) bit */
+#define  BRCMS_LED_AL_MASK	0x80
+	/* radio enabled */
+#define  BRCMS_LED_RADIO	3
+
+static void brcms_radio_led_ctrl(struct brcms_info *wl, bool state)
+{
+	if (wl->radio_led.gpio == -1)
+		return;
+
+	if (wl->radio_led.active_low)
+		state = !state;
+
+	if (state)
+		gpio_set_value(wl->radio_led.gpio, 1);
+	else
+		gpio_set_value(wl->radio_led.gpio, 0);
+}
+
+
+/* Callback from the LED subsystem. */
+static void brcms_led_brightness_set(struct led_classdev *led_dev,
+				   enum led_brightness brightness)
+{
+	struct brcms_info *wl = container_of(led_dev,
+		struct brcms_info, led_dev);
+	brcms_radio_led_ctrl(wl, brightness);
+}
+
+void brcms_led_unregister(struct brcms_info *wl)
+{
+	if (wl->led_dev.dev)
+		led_classdev_unregister(&wl->led_dev);
+	if (wl->radio_led.gpio != -1)
+		gpio_free(wl->radio_led.gpio);
+}
+
+int brcms_led_register(struct brcms_info *wl)
+{
+	int i, err;
+	struct brcms_led *radio_led = &wl->radio_led;
+	/* get CC core */
+	struct bcma_drv_cc *cc_drv  = &wl->wlc->hw->d11core->bus->drv_cc;
+	struct gpio_chip *bcma_gpio = &cc_drv->gpio;
+	struct ssb_sprom *sprom = &wl->wlc->hw->d11core->bus->sprom;
+	u8 *leds[] = { &sprom->gpio0,
+		&sprom->gpio1,
+		&sprom->gpio2,
+		&sprom->gpio3 };
+	unsigned gpio = -1;
+	bool active_low = false;
+
+	/* none by default */
+	radio_led->gpio = -1;
+	radio_led->active_low = false;
+
+	if (!bcma_gpio || !gpio_is_valid(bcma_gpio->base))
+		return -ENODEV;
+
+	/* find radio enabled LED */
+	for (i = 0; i < BRCMS_LED_NO; i++) {
+		u8 led = *leds[i];
+		if ((led & BRCMS_LED_BEH_MASK) == BRCMS_LED_RADIO) {
+			gpio = bcma_gpio->base + i;
+			if (led & BRCMS_LED_AL_MASK)
+				active_low = true;
+			break;
+		}
+	}
+
+	if (gpio == -1 || !gpio_is_valid(gpio))
+		return -ENODEV;
+
+	/* request and configure LED gpio */
+	err = gpio_request_one(gpio,
+				active_low ? GPIOF_OUT_INIT_HIGH
+					: GPIOF_OUT_INIT_LOW,
+				"radio on");
+	if (err) {
+		wiphy_err(wl->wiphy, "requesting led gpio %d failed (err: %d)\n",
+			  gpio, err);
+		return err;
+	}
+	err = gpio_direction_output(gpio, 1);
+	if (err) {
+		wiphy_err(wl->wiphy, "cannot set led gpio %d to output (err: %d)\n",
+			  gpio, err);
+		return err;
+	}
+
+	snprintf(wl->radio_led.name, sizeof(wl->radio_led.name),
+		 "brcmsmac-%s:radio", wiphy_name(wl->wiphy));
+
+	wl->led_dev.name = wl->radio_led.name;
+	wl->led_dev.default_trigger =
+		ieee80211_get_radio_led_name(wl->pub->ieee_hw);
+	wl->led_dev.brightness_set = brcms_led_brightness_set;
+	err = led_classdev_register(wiphy_dev(wl->wiphy), &wl->led_dev);
+
+	if (err) {
+		wiphy_err(wl->wiphy, "cannot register led device: %s (err: %d)\n",
+			  wl->radio_led.name, err);
+		return err;
+	}
+
+	wiphy_info(wl->wiphy, "registered radio enabled led device: %s gpio: %d\n",
+		   wl->radio_led.name,
+		   gpio);
+	radio_led->gpio = gpio;
+	radio_led->active_low = active_low;
+
+	return 0;
+}
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/led.h b/drivers/net/wireless/brcm80211/brcmsmac/led.h
new file mode 100644
index 0000000..17a0b1f
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmsmac/led.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2012 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_LED_H_
+#define _BRCM_LED_H_
+struct brcms_led {
+	char name[32];
+	unsigned gpio;
+	bool active_low;
+};
+
+#ifdef CONFIG_BCMA_DRIVER_GPIO
+void brcms_led_unregister(struct brcms_info *wl);
+int brcms_led_register(struct brcms_info *wl);
+#else
+static inline void brcms_led_unregister(struct brcms_info *wl) {};
+static inline int brcms_led_register(struct brcms_info *wl)
+{
+	return -ENOTSUPP;
+};
+#endif
+
+#endif /* _BRCM_LED_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
index c6451c6..cd83786 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2010 Broadcom Corporation
+ * Copyright (c) 2013 Hauke Mehrtens <hauke@hauke-m.de>
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -34,6 +35,7 @@
 #include "mac80211_if.h"
 #include "main.h"
 #include "debug.h"
+#include "led.h"
 
 #define N_TX_QUEUES	4 /* #tx queues on mac80211<->driver interface */
 #define BRCMS_FLUSH_TIMEOUT	500 /* msec */
@@ -355,18 +357,26 @@ brcms_ops_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 {
 	struct brcms_info *wl = hw->priv;
 
-	/* Just STA for now */
-	if (vif->type != NL80211_IFTYPE_STATION) {
+	/* Just STA, AP and ADHOC for now */
+	if (vif->type != NL80211_IFTYPE_STATION &&
+	    vif->type != NL80211_IFTYPE_AP &&
+	    vif->type != NL80211_IFTYPE_ADHOC) {
 		brcms_err(wl->wlc->hw->d11core,
-			  "%s: Attempt to add type %d, only STA for now\n",
+			  "%s: Attempt to add type %d, only STA, AP and AdHoc for now\n",
 			  __func__, vif->type);
 		return -EOPNOTSUPP;
 	}
 
 	spin_lock_bh(&wl->lock);
-	memcpy(wl->pub->cur_etheraddr, vif->addr, sizeof(vif->addr));
 	wl->mute_tx = false;
 	brcms_c_mute(wl->wlc, false);
+	if (vif->type == NL80211_IFTYPE_STATION)
+		brcms_c_start_station(wl->wlc, vif->addr);
+	else if (vif->type == NL80211_IFTYPE_AP)
+		brcms_c_start_ap(wl->wlc, vif->addr, vif->bss_conf.bssid,
+				 vif->bss_conf.ssid, vif->bss_conf.ssid_len);
+	else if (vif->type == NL80211_IFTYPE_ADHOC)
+		brcms_c_start_adhoc(wl->wlc, vif->addr);
 	spin_unlock_bh(&wl->lock);
 
 	return 0;
@@ -518,14 +528,43 @@ brcms_ops_bss_info_changed(struct ieee80211_hw *hw,
 		brcms_c_set_addrmatch(wl->wlc, RCM_BSSID_OFFSET, info->bssid);
 		spin_unlock_bh(&wl->lock);
 	}
-	if (changed & BSS_CHANGED_BEACON)
+	if (changed & BSS_CHANGED_SSID) {
+		/* BSSID changed, for whatever reason (IBSS and managed mode) */
+		spin_lock_bh(&wl->lock);
+		brcms_c_set_ssid(wl->wlc, info->ssid, info->ssid_len);
+		spin_unlock_bh(&wl->lock);
+	}
+	if (changed & BSS_CHANGED_BEACON) {
 		/* Beacon data changed, retrieve new beacon (beaconing modes) */
-		brcms_err(core, "%s: beacon changed\n", __func__);
+		struct sk_buff *beacon;
+		u16 tim_offset = 0;
+
+		spin_lock_bh(&wl->lock);
+		beacon = ieee80211_beacon_get_tim(hw, vif, &tim_offset, NULL);
+		brcms_c_set_new_beacon(wl->wlc, beacon, tim_offset,
+				       info->dtim_period);
+		spin_unlock_bh(&wl->lock);
+	}
+
+	if (changed & BSS_CHANGED_AP_PROBE_RESP) {
+		struct sk_buff *probe_resp;
+
+		spin_lock_bh(&wl->lock);
+		probe_resp = ieee80211_proberesp_get(hw, vif);
+		brcms_c_set_new_probe_resp(wl->wlc, probe_resp);
+		spin_unlock_bh(&wl->lock);
+	}
 
 	if (changed & BSS_CHANGED_BEACON_ENABLED) {
 		/* Beaconing should be enabled/disabled (beaconing modes) */
 		brcms_err(core, "%s: Beacon enabled: %s\n", __func__,
 			  info->enable_beacon ? "true" : "false");
+		if (info->enable_beacon &&
+		    hw->wiphy->flags & WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD) {
+			brcms_c_enable_probe_resp(wl->wlc, true);
+		} else {
+			brcms_c_enable_probe_resp(wl->wlc, false);
+		}
 	}
 
 	if (changed & BSS_CHANGED_CQM) {
@@ -723,7 +762,7 @@ static bool brcms_tx_flush_completed(struct brcms_info *wl)
 	return result;
 }
 
-static void brcms_ops_flush(struct ieee80211_hw *hw, bool drop)
+static void brcms_ops_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
 {
 	struct brcms_info *wl = hw->priv;
 	int ret;
@@ -738,6 +777,28 @@ static void brcms_ops_flush(struct ieee80211_hw *hw, bool drop)
 			   "ret=%d\n", jiffies_to_msecs(ret));
 }
 
+static u64 brcms_ops_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
+{
+	struct brcms_info *wl = hw->priv;
+	u64 tsf;
+
+	spin_lock_bh(&wl->lock);
+	tsf = brcms_c_tsf_get(wl->wlc);
+	spin_unlock_bh(&wl->lock);
+
+	return tsf;
+}
+
+static void brcms_ops_set_tsf(struct ieee80211_hw *hw,
+			   struct ieee80211_vif *vif, u64 tsf)
+{
+	struct brcms_info *wl = hw->priv;
+
+	spin_lock_bh(&wl->lock);
+	brcms_c_tsf_set(wl->wlc, tsf);
+	spin_unlock_bh(&wl->lock);
+}
+
 static const struct ieee80211_ops brcms_ops = {
 	.tx = brcms_ops_tx,
 	.start = brcms_ops_start,
@@ -754,6 +815,8 @@ static const struct ieee80211_ops brcms_ops = {
 	.ampdu_action = brcms_ops_ampdu_action,
 	.rfkill_poll = brcms_ops_rfkill_poll,
 	.flush = brcms_ops_flush,
+	.get_tsf = brcms_ops_get_tsf,
+	.set_tsf = brcms_ops_set_tsf,
 };
 
 void brcms_dpc(unsigned long data)
@@ -904,6 +967,7 @@ static void brcms_remove(struct bcma_device *pdev)
 	struct brcms_info *wl = hw->priv;
 
 	if (wl->wlc) {
+		brcms_led_unregister(wl);
 		wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, false);
 		wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy);
 		ieee80211_unregister_hw(hw);
@@ -994,7 +1058,16 @@ static int ieee_hw_init(struct ieee80211_hw *hw)
 
 	/* channel change time is dependent on chip and band  */
 	hw->channel_change_time = 7 * 1000;
-	hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
+	hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
+				     BIT(NL80211_IFTYPE_AP) |
+				     BIT(NL80211_IFTYPE_ADHOC);
+
+	/*
+	 * deactivate sending probe responses by ucude, because this will
+	 * cause problems when WPS is used.
+	 *
+	 * hw->wiphy->flags |= WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD;
+	 */
 
 	hw->rate_control_algorithm = "minstrel_ht";
 
@@ -1151,6 +1224,8 @@ static int brcms_bcma_probe(struct bcma_device *pdev)
 		pr_err("%s: brcms_attach failed!\n", __func__);
 		return -ENODEV;
 	}
+	brcms_led_register(wl);
+
 	return 0;
 }
 
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h
index 947ccac..4090032 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h
@@ -20,8 +20,10 @@
 #include <linux/timer.h>
 #include <linux/interrupt.h>
 #include <linux/workqueue.h>
+#include <linux/leds.h>
 
 #include "ucode_loader.h"
+#include "led.h"
 /*
  * Starting index for 5G rates in the
  * legacy rate table.
@@ -81,6 +83,8 @@ struct brcms_info {
 	struct wiphy *wiphy;
 	struct brcms_ucode ucode;
 	bool mute_tx;
+	struct brcms_led radio_led;
+	struct led_classdev led_dev;
 };
 
 /* misc callbacks */
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c
index 8ef02dc..59d4384 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2010 Broadcom Corporation
+ * Copyright (c) 2013 Hauke Mehrtens <hauke@hauke-m.de>
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -448,6 +449,10 @@ static void brcms_c_detach_mfree(struct brcms_c_info *wlc)
 	kfree(wlc->corestate);
 	kfree(wlc->hw->bandstate[0]);
 	kfree(wlc->hw);
+	if (wlc->beacon)
+		dev_kfree_skb_any(wlc->beacon);
+	if (wlc->probe_resp)
+		dev_kfree_skb_any(wlc->probe_resp);
 
 	/* free the wlc */
 	kfree(wlc);
@@ -1069,7 +1074,7 @@ brcms_b_txstatus(struct brcms_hardware *wlc_hw, bool bound, bool *fatal)
 
 static void brcms_c_tbtt(struct brcms_c_info *wlc)
 {
-	if (!wlc->bsscfg->BSS)
+	if (wlc->bsscfg->type == BRCMS_TYPE_ADHOC)
 		/*
 		 * DirFrmQ is now valid...defer setting until end
 		 * of ATIM window
@@ -2163,6 +2168,32 @@ void brcms_b_switch_macfreq(struct brcms_hardware *wlc_hw, u8 spurmode)
 	}
 }
 
+void brcms_c_start_station(struct brcms_c_info *wlc, u8 *addr)
+{
+	memcpy(wlc->pub->cur_etheraddr, addr, sizeof(wlc->pub->cur_etheraddr));
+	wlc->bsscfg->type = BRCMS_TYPE_STATION;
+}
+
+void brcms_c_start_ap(struct brcms_c_info *wlc, u8 *addr, const u8 *bssid,
+		      u8 *ssid, size_t ssid_len)
+{
+	brcms_c_set_ssid(wlc, ssid, ssid_len);
+
+	memcpy(wlc->pub->cur_etheraddr, addr, sizeof(wlc->pub->cur_etheraddr));
+	memcpy(wlc->bsscfg->BSSID, bssid, sizeof(wlc->bsscfg->BSSID));
+	wlc->bsscfg->type = BRCMS_TYPE_AP;
+
+	brcms_b_mctrl(wlc->hw, MCTL_AP | MCTL_INFRA, MCTL_AP | MCTL_INFRA);
+}
+
+void brcms_c_start_adhoc(struct brcms_c_info *wlc, u8 *addr)
+{
+	memcpy(wlc->pub->cur_etheraddr, addr, sizeof(wlc->pub->cur_etheraddr));
+	wlc->bsscfg->type = BRCMS_TYPE_ADHOC;
+
+	brcms_b_mctrl(wlc->hw, MCTL_AP | MCTL_INFRA, 0);
+}
+
 /* Initialize GPIOs that are controlled by D11 core */
 static void brcms_c_gpio_init(struct brcms_c_info *wlc)
 {
@@ -3043,8 +3074,6 @@ static void brcms_b_antsel_set(struct brcms_hardware *wlc_hw, u32 antsel_avail)
  */
 static bool brcms_c_ps_allowed(struct brcms_c_info *wlc)
 {
-	struct brcms_bss_cfg *cfg = wlc->bsscfg;
-
 	/* disallow PS when one of the following global conditions meets */
 	if (!wlc->pub->associated)
 		return false;
@@ -3053,16 +3082,11 @@ static bool brcms_c_ps_allowed(struct brcms_c_info *wlc)
 	if (wlc->filter_flags & FIF_PROMISC_IN_BSS)
 		return false;
 
-	if (cfg->associated) {
-		/*
-		 * disallow PS when one of the following
-		 * bsscfg specific conditions meets
-		 */
-		if (!cfg->BSS)
-			return false;
+	if (wlc->bsscfg->type == BRCMS_TYPE_AP)
+		return false;
 
+	if (wlc->bsscfg->type == BRCMS_TYPE_ADHOC)
 		return false;
-	}
 
 	return true;
 }
@@ -3771,7 +3795,7 @@ static int brcms_c_set_mac(struct brcms_bss_cfg *bsscfg)
 	struct brcms_c_info *wlc = bsscfg->wlc;
 
 	/* enter the MAC addr into the RXE match registers */
-	brcms_c_set_addrmatch(wlc, RCM_MAC_OFFSET, bsscfg->cur_etheraddr);
+	brcms_c_set_addrmatch(wlc, RCM_MAC_OFFSET, wlc->pub->cur_etheraddr);
 
 	brcms_c_ampdu_macaddr_upd(wlc);
 
@@ -3787,6 +3811,15 @@ static void brcms_c_set_bssid(struct brcms_bss_cfg *bsscfg)
 	brcms_c_set_addrmatch(bsscfg->wlc, RCM_BSSID_OFFSET, bsscfg->BSSID);
 }
 
+void brcms_c_set_ssid(struct brcms_c_info *wlc, u8 *ssid, size_t ssid_len)
+{
+	u8 len = min_t(u8, sizeof(wlc->bsscfg->SSID), ssid_len);
+	memset(wlc->bsscfg->SSID, 0, sizeof(wlc->bsscfg->SSID));
+
+	memcpy(wlc->bsscfg->SSID, ssid, len);
+	wlc->bsscfg->SSID_len = len;
+}
+
 static void brcms_b_set_shortslot(struct brcms_hardware *wlc_hw, bool shortslot)
 {
 	wlc_hw->shortslot = shortslot;
@@ -3821,7 +3854,7 @@ static void brcms_c_set_home_chanspec(struct brcms_c_info *wlc, u16 chanspec)
 	if (wlc->home_chanspec != chanspec) {
 		wlc->home_chanspec = chanspec;
 
-		if (wlc->bsscfg->associated)
+		if (wlc->pub->associated)
 			wlc->bsscfg->current_bss->chanspec = chanspec;
 	}
 }
@@ -4091,10 +4124,14 @@ void brcms_c_wme_setparams(struct brcms_c_info *wlc, u16 aci,
 					  *shm_entry++);
 	}
 
-	if (suspend) {
+	if (suspend)
 		brcms_c_suspend_mac_and_wait(wlc);
+
+	brcms_c_update_beacon(wlc);
+	brcms_c_update_probe_resp(wlc, false);
+
+	if (suspend)
 		brcms_c_enable_mac(wlc);
-	}
 }
 
 static void brcms_c_edcf_setparams(struct brcms_c_info *wlc, bool suspend)
@@ -4332,7 +4369,6 @@ static void brcms_c_info_init(struct brcms_c_info *wlc, int unit)
 
 	/* WME QoS mode is Auto by default */
 	wlc->pub->_ampdu = AMPDU_AGG_HOST;
-	wlc->pub->bcmerror = 0;
 }
 
 static uint brcms_c_attach_module(struct brcms_c_info *wlc)
@@ -5072,8 +5108,8 @@ int brcms_c_up(struct brcms_c_info *wlc)
 				struct brcms_bss_cfg *bsscfg = wlc->bsscfg;
 				mboolset(wlc->pub->radio_disabled,
 					 WL_RADIO_HW_DISABLE);
-
-				if (bsscfg->enable && bsscfg->BSS)
+				if (bsscfg->type == BRCMS_TYPE_STATION ||
+				    bsscfg->type == BRCMS_TYPE_ADHOC)
 					brcms_err(wlc->hw->d11core,
 						  "wl%d: up: rfdisable -> "
 						  "bsscfg_disable()\n",
@@ -5434,7 +5470,7 @@ static void brcms_c_ofdm_rateset_war(struct brcms_c_info *wlc)
 	u8 r;
 	bool war = false;
 
-	if (wlc->bsscfg->associated)
+	if (wlc->pub->associated)
 		r = wlc->bsscfg->current_bss->rateset.rates[0];
 	else
 		r = wlc->default_bss->rateset.rates[0];
@@ -5528,7 +5564,7 @@ int brcms_c_set_rateset(struct brcms_c_info *wlc, struct brcm_rateset *rs)
 	/* merge rateset coming in with the current mcsset */
 	if (wlc->pub->_n_enab & SUPPORT_11N) {
 		struct brcms_bss_info *mcsset_bss;
-		if (wlc->bsscfg->associated)
+		if (wlc->pub->associated)
 			mcsset_bss = wlc->bsscfg->current_bss;
 		else
 			mcsset_bss = wlc->default_bss;
@@ -5543,12 +5579,36 @@ int brcms_c_set_rateset(struct brcms_c_info *wlc, struct brcm_rateset *rs)
 	return bcmerror;
 }
 
+static void brcms_c_time_lock(struct brcms_c_info *wlc)
+{
+	bcma_set32(wlc->hw->d11core, D11REGOFFS(maccontrol), MCTL_TBTTHOLD);
+	/* Commit the write */
+	bcma_read32(wlc->hw->d11core, D11REGOFFS(maccontrol));
+}
+
+static void brcms_c_time_unlock(struct brcms_c_info *wlc)
+{
+	bcma_mask32(wlc->hw->d11core, D11REGOFFS(maccontrol), ~MCTL_TBTTHOLD);
+	/* Commit the write */
+	bcma_read32(wlc->hw->d11core, D11REGOFFS(maccontrol));
+}
+
 int brcms_c_set_beacon_period(struct brcms_c_info *wlc, u16 period)
 {
+	u32 bcnint_us;
+
 	if (period == 0)
 		return -EINVAL;
 
 	wlc->default_bss->beacon_period = period;
+
+	bcnint_us = period << 10;
+	brcms_c_time_lock(wlc);
+	bcma_write32(wlc->hw->d11core, D11REGOFFS(tsf_cfprep),
+		     (bcnint_us << CFPREP_CBI_SHIFT));
+	bcma_write32(wlc->hw->d11core, D11REGOFFS(tsf_cfpstart), bcnint_us);
+	brcms_c_time_unlock(wlc);
+
 	return 0;
 }
 
@@ -7291,72 +7351,110 @@ brcms_c_mod_prb_rsp_rate_table(struct brcms_c_info *wlc, uint frame_len)
 	}
 }
 
-/*	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,
-			 u32 bcn_rspec,
-			 struct brcms_bss_cfg *cfg, u16 *buf, int *len)
+int brcms_c_get_header_len(void)
 {
-	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;
-
-	hdr_len = D11_PHY_HDR_LEN + DOT11_MAC_HDR_LEN;
+	return TXOFF;
+}
 
-	/* calc buffer size provided for frame body */
-	body_len = *len - hdr_len;
-	/* return actual size */
-	*len = hdr_len + body_len;
+static void brcms_c_beacon_write(struct brcms_c_info *wlc,
+				 struct sk_buff *beacon, u16 tim_offset,
+				 u16 dtim_period, bool bcn0, bool bcn1)
+{
+	size_t len;
+	struct ieee80211_tx_info *tx_info;
+	struct brcms_hardware *wlc_hw = wlc->hw;
+	struct ieee80211_hw *ieee_hw = brcms_c_pub(wlc)->ieee_hw;
 
-	/* format PHY and MAC headers */
-	memset(buf, 0, hdr_len);
+	/* Get tx_info */
+	tx_info = IEEE80211_SKB_CB(beacon);
 
-	plcp = (struct cck_phy_hdr *) buf;
+	len = min_t(size_t, beacon->len, BCN_TMPL_LEN);
+	wlc->bcn_rspec = ieee80211_get_tx_rate(ieee_hw, tx_info)->hw_value;
 
-	/*
-	 * PLCP for Probe Response frames are filled in from
-	 * core's rate table
-	 */
-	if (type == IEEE80211_STYPE_BEACON)
-		/* fill in PLCP */
-		brcms_c_compute_plcp(wlc, bcn_rspec,
-				 (DOT11_MAC_HDR_LEN + body_len + FCS_LEN),
-				 (u8 *) plcp);
+	brcms_c_compute_plcp(wlc, wlc->bcn_rspec,
+			     len + FCS_LEN - D11_PHY_HDR_LEN, beacon->data);
 
 	/* "Regular" and 16 MBSS but not for 4 MBSS */
 	/* Update the phytxctl for the beacon based on the rspec */
-	brcms_c_beacon_phytxctl_txant_upd(wlc, bcn_rspec);
+	brcms_c_beacon_phytxctl_txant_upd(wlc, wlc->bcn_rspec);
 
-	h = (struct ieee80211_mgmt *)&plcp[1];
+	if (bcn0) {
+		/* write the probe response into the template region */
+		brcms_b_write_template_ram(wlc_hw, T_BCN0_TPL_BASE,
+					    (len + 3) & ~3, beacon->data);
 
-	/* fill in 802.11 header */
-	h->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | type);
+		/* write beacon length to SCR */
+		brcms_b_write_shm(wlc_hw, M_BCN0_FRM_BYTESZ, (u16) len);
+	}
+	if (bcn1) {
+		/* write the probe response into the template region */
+		brcms_b_write_template_ram(wlc_hw, T_BCN1_TPL_BASE,
+					    (len + 3) & ~3, beacon->data);
 
-	/* 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);
+		/* write beacon length to SCR */
+		brcms_b_write_shm(wlc_hw, M_BCN1_FRM_BYTESZ, (u16) len);
+	}
 
-	/* SEQ filled in by MAC */
+	if (tim_offset != 0) {
+		brcms_b_write_shm(wlc_hw, M_TIMBPOS_INBEACON,
+				  tim_offset + D11B_PHY_HDR_LEN);
+		brcms_b_write_shm(wlc_hw, M_DOT11_DTIMPERIOD, dtim_period);
+	} else {
+		brcms_b_write_shm(wlc_hw, M_TIMBPOS_INBEACON,
+				  len + D11B_PHY_HDR_LEN);
+		brcms_b_write_shm(wlc_hw, M_DOT11_DTIMPERIOD, 0);
+	}
 }
 
-int brcms_c_get_header_len(void)
+static void brcms_c_update_beacon_hw(struct brcms_c_info *wlc,
+				     struct sk_buff *beacon, u16 tim_offset,
+				     u16 dtim_period)
 {
-	return TXOFF;
+	struct brcms_hardware *wlc_hw = wlc->hw;
+	struct bcma_device *core = wlc_hw->d11core;
+
+	/* Hardware beaconing for this config */
+	u32 both_valid = MCMD_BCN0VLD | MCMD_BCN1VLD;
+
+	/* Check if both templates are in use, if so sched. an interrupt
+	 *      that will call back into this routine
+	 */
+	if ((bcma_read32(core, D11REGOFFS(maccommand)) & both_valid) == both_valid)
+		/* clear any previous status */
+		bcma_write32(core, D11REGOFFS(macintstatus), MI_BCNTPL);
+
+	if (wlc->beacon_template_virgin) {
+		wlc->beacon_template_virgin = false;
+		brcms_c_beacon_write(wlc, beacon, tim_offset, dtim_period, true,
+				     true);
+		/* mark beacon0 valid */
+		bcma_set32(core, D11REGOFFS(maccommand), MCMD_BCN0VLD);
+		return;
+	}
+
+	/* Check that after scheduling the interrupt both of the
+	 *      templates are still busy. if not clear the int. & remask
+	 */
+	if ((bcma_read32(core, D11REGOFFS(maccommand)) & both_valid) == both_valid) {
+		wlc->defmacintmask |= MI_BCNTPL;
+		return;
+	}
+
+	if (!(bcma_read32(core, D11REGOFFS(maccommand)) & MCMD_BCN0VLD)) {
+		brcms_c_beacon_write(wlc, beacon, tim_offset, dtim_period, true,
+				     false);
+		/* mark beacon0 valid */
+		bcma_set32(core, D11REGOFFS(maccommand), MCMD_BCN0VLD);
+		return;
+	}
+	if (!(bcma_read32(core, D11REGOFFS(maccommand)) & MCMD_BCN1VLD)) {
+		brcms_c_beacon_write(wlc, beacon, tim_offset, dtim_period,
+				     false, true);
+		/* mark beacon0 valid */
+		bcma_set32(core, D11REGOFFS(maccommand), MCMD_BCN1VLD);
+		return;
+	}
+	return;
 }
 
 /*
@@ -7366,9 +7464,57 @@ void brcms_c_update_beacon(struct brcms_c_info *wlc)
 {
 	struct brcms_bss_cfg *bsscfg = wlc->bsscfg;
 
-	if (bsscfg->up && !bsscfg->BSS)
+	if (wlc->pub->up && (bsscfg->type == BRCMS_TYPE_AP ||
+			     bsscfg->type == BRCMS_TYPE_ADHOC)) {
 		/* Clear the soft intmask */
 		wlc->defmacintmask &= ~MI_BCNTPL;
+		if (!wlc->beacon)
+			return;
+		brcms_c_update_beacon_hw(wlc, wlc->beacon,
+					 wlc->beacon_tim_offset,
+					 wlc->beacon_dtim_period);
+	}
+}
+
+void brcms_c_set_new_beacon(struct brcms_c_info *wlc, struct sk_buff *beacon,
+			    u16 tim_offset, u16 dtim_period)
+{
+	if (!beacon)
+		return;
+	if (wlc->beacon)
+		dev_kfree_skb_any(wlc->beacon);
+	wlc->beacon = beacon;
+
+	/* add PLCP */
+	skb_push(wlc->beacon, D11_PHY_HDR_LEN);
+	wlc->beacon_tim_offset = tim_offset;
+	wlc->beacon_dtim_period = dtim_period;
+	brcms_c_update_beacon(wlc);
+}
+
+void brcms_c_set_new_probe_resp(struct brcms_c_info *wlc,
+				struct sk_buff *probe_resp)
+{
+	if (!probe_resp)
+		return;
+	if (wlc->probe_resp)
+		dev_kfree_skb_any(wlc->probe_resp);
+	wlc->probe_resp = probe_resp;
+
+	/* add PLCP */
+	skb_push(wlc->probe_resp, D11_PHY_HDR_LEN);
+	brcms_c_update_probe_resp(wlc, false);
+}
+
+void brcms_c_enable_probe_resp(struct brcms_c_info *wlc, bool enable)
+{
+	/*
+	 * prevent ucode from sending probe responses by setting the timeout
+	 * to 1, it can not send it in that time frame.
+	 */
+	wlc->prb_resp_timeout = enable ? BRCMS_PRB_RESP_TIMEOUT : 1;
+	brcms_b_write_shm(wlc->hw, M_PRS_MAXTIME, wlc->prb_resp_timeout);
+	/* TODO: if (enable) => also deactivate receiving of probe request */
 }
 
 /* Write ssid into shared memory */
@@ -7390,30 +7536,19 @@ brcms_c_shm_ssid_upd(struct brcms_c_info *wlc, struct brcms_bss_cfg *cfg)
 static void
 brcms_c_bss_update_probe_resp(struct brcms_c_info *wlc,
 			      struct brcms_bss_cfg *cfg,
+			      struct sk_buff *probe_resp,
 			      bool suspend)
 {
-	u16 *prb_resp;
-	int len = BCN_TMPL_LEN;
-
-	prb_resp = kmalloc(BCN_TMPL_LEN, GFP_ATOMIC);
-	if (!prb_resp)
-		return;
-
-	/*
-	 * write the probe response to hardware, or save in
-	 * the config structure
-	 */
+	int len;
 
-	/* create the probe response template */
-	brcms_c_bcn_prb_template(wlc, IEEE80211_STYPE_PROBE_RESP, 0,
-				 cfg, prb_resp, &len);
+	len = min_t(size_t, probe_resp->len, BCN_TMPL_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);
+				    (len + 3) & ~3, probe_resp->data);
 
 	/* write the length of the probe response frame (+PLCP/-FCS) */
 	brcms_b_write_shm(wlc->hw, M_PRB_RESP_FRM_LEN, (u16) len);
@@ -7427,13 +7562,11 @@ brcms_c_bss_update_probe_resp(struct brcms_c_info *wlc,
 	 * 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);
+	brcms_c_mod_prb_rsp_rate_table(wlc,
+				      (u16)len + FCS_LEN - D11_PHY_HDR_LEN);
 
 	if (suspend)
 		brcms_c_enable_mac(wlc);
-
-	kfree(prb_resp);
 }
 
 void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend)
@@ -7441,8 +7574,13 @@ void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend)
 	struct brcms_bss_cfg *bsscfg = wlc->bsscfg;
 
 	/* update AP or IBSS probe responses */
-	if (bsscfg->up && !bsscfg->BSS)
-		brcms_c_bss_update_probe_resp(wlc, bsscfg, suspend);
+	if (wlc->pub->up && (bsscfg->type == BRCMS_TYPE_AP ||
+			     bsscfg->type == BRCMS_TYPE_ADHOC)) {
+		if (!wlc->probe_resp)
+			return;
+		brcms_c_bss_update_probe_resp(wlc, bsscfg, wlc->probe_resp,
+					      suspend);
+	}
 }
 
 int brcms_b_xmtfifo_sz_get(struct brcms_hardware *wlc_hw, uint fifo,
@@ -7481,7 +7619,6 @@ void brcms_c_scan_stop(struct brcms_c_info *wlc)
 void brcms_c_associate_upd(struct brcms_c_info *wlc, bool state)
 {
 	wlc->pub->associated = state;
-	wlc->bsscfg->associated = state;
 }
 
 /*
@@ -7526,6 +7663,36 @@ void brcms_c_set_beacon_listen_interval(struct brcms_c_info *wlc, u8 interval)
 		brcms_c_bcn_li_upd(wlc);
 }
 
+u64 brcms_c_tsf_get(struct brcms_c_info *wlc)
+{
+	u32 tsf_h, tsf_l;
+	u64 tsf;
+
+	brcms_b_read_tsf(wlc->hw, &tsf_l, &tsf_h);
+
+	tsf = tsf_h;
+	tsf <<= 32;
+	tsf |= tsf_l;
+
+	return tsf;
+}
+
+void brcms_c_tsf_set(struct brcms_c_info *wlc, u64 tsf)
+{
+	u32 tsf_h, tsf_l;
+
+	brcms_c_time_lock(wlc);
+
+	tsf_l = tsf;
+	tsf_h = (tsf >> 32);
+
+	/* read the tsf timer low, then high to get an atomic read */
+	bcma_write32(wlc->hw->d11core, D11REGOFFS(tsf_timerlow), tsf_l);
+	bcma_write32(wlc->hw->d11core, D11REGOFFS(tsf_timerhigh), tsf_h);
+
+	brcms_c_time_unlock(wlc);
+}
+
 int brcms_c_set_tx_power(struct brcms_c_info *wlc, int txpwr)
 {
 	uint qdbm;
@@ -7737,6 +7904,10 @@ bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded)
 		brcms_rfkill_set_hw_state(wlc->wl);
 	}
 
+	/* BCN template is available */
+	if (macintstatus & MI_BCNTPL)
+		brcms_c_update_beacon(wlc);
+
 	/* it isn't done and needs to be resched if macintstatus is non-zero */
 	return wlc->macintstatus != 0;
 
@@ -7765,7 +7936,7 @@ void brcms_c_init(struct brcms_c_info *wlc, bool mute_tx)
 	brcms_c_set_bssid(wlc->bsscfg);
 
 	/* Update tsf_cfprep if associated and up */
-	if (wlc->pub->associated && wlc->bsscfg->up) {
+	if (wlc->pub->associated && wlc->pub->up) {
 		u32 bi;
 
 		/* get beacon period and convert to uS */
@@ -7810,9 +7981,14 @@ void brcms_c_init(struct brcms_c_info *wlc, bool mute_tx)
 
 	/* read the ucode version if we have not yet done so */
 	if (wlc->ucode_rev == 0) {
-		wlc->ucode_rev =
-		    brcms_b_read_shm(wlc->hw, M_BOM_REV_MAJOR) << NBITS(u16);
-		wlc->ucode_rev |= brcms_b_read_shm(wlc->hw, M_BOM_REV_MINOR);
+		u16 rev;
+		u16 patch;
+
+		rev = brcms_b_read_shm(wlc->hw, M_BOM_REV_MAJOR);
+		patch = brcms_b_read_shm(wlc->hw, M_BOM_REV_MINOR);
+		wlc->ucode_rev = (rev << NBITS(u16)) | patch;
+		snprintf(wlc->wiphy->fw_version,
+			 sizeof(wlc->wiphy->fw_version), "%u.%u", rev, patch);
 	}
 
 	/* ..now really unleash hell (allow the MAC out of suspend) */
@@ -7868,6 +8044,7 @@ brcms_c_attach(struct brcms_info *wl, struct bcma_device *core, uint unit,
 	pub->unit = unit;
 	pub->_piomode = piomode;
 	wlc->bandinit_pending = false;
+	wlc->beacon_template_virgin = true;
 
 	/* populate struct brcms_c_info with default values  */
 	brcms_c_info_init(wlc, unit);
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.h b/drivers/net/wireless/brcm80211/brcmsmac/main.h
index fb44774..b5d7a38 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.h
@@ -492,6 +492,8 @@ struct brcms_c_info {
 	bool radio_monitor;
 	bool going_down;
 
+	bool beacon_template_virgin;
+
 	struct brcms_timer *wdtimer;
 	struct brcms_timer *radio_timer;
 
@@ -561,6 +563,11 @@ struct brcms_c_info {
 
 	struct wiphy *wiphy;
 	struct scb pri_scb;
+
+	struct sk_buff *beacon;
+	u16 beacon_tim_offset;
+	u16 beacon_dtim_period;
+	struct sk_buff *probe_resp;
 };
 
 /* antsel module specific state */
@@ -576,14 +583,17 @@ struct antsel_info {
 	struct brcms_antselcfg antcfg_cur; /* current antenna config (auto) */
 };
 
+enum brcms_bss_type {
+	BRCMS_TYPE_STATION,
+	BRCMS_TYPE_AP,
+	BRCMS_TYPE_ADHOC,
+};
+
 /*
  * BSS configuration state
  *
  * wlc: wlc to which this bsscfg belongs to.
- * up: is this configuration up operational
- * enable: is this configuration enabled
- * associated: is BSS in ASSOCIATED state
- * BSS: infraustructure or adhoc
+ * type: interface type
  * SSID_len: the length of SSID
  * SSID: SSID string
  *
@@ -599,14 +609,10 @@ struct antsel_info {
  */
 struct brcms_bss_cfg {
 	struct brcms_c_info *wlc;
-	bool up;
-	bool enable;
-	bool associated;
-	bool BSS;
+	enum brcms_bss_type type;
 	u8 SSID_len;
 	u8 SSID[IEEE80211_MAX_SSID_LEN];
 	u8 BSSID[ETH_ALEN];
-	u8 cur_etheraddr[ETH_ALEN];
 	struct brcms_bss_info *current_bss;
 };
 
@@ -631,7 +637,6 @@ extern u16 brcms_c_compute_rtscts_dur(struct brcms_c_info *wlc, bool cts_only,
 extern void brcms_c_inval_dma_pkts(struct brcms_hardware *hw,
 			       struct ieee80211_sta *sta,
 			       void (*dma_callback_fn));
-extern void brcms_c_update_beacon(struct brcms_c_info *wlc);
 extern void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend);
 extern int brcms_c_set_nmode(struct brcms_c_info *wlc);
 extern void brcms_c_beacon_phytxctl_txant_upd(struct brcms_c_info *wlc,
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c
index 91937c5..b0fd807 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c
@@ -198,8 +198,6 @@ u16 read_radio_reg(struct brcms_phy *pi, u16 addr)
 
 void write_radio_reg(struct brcms_phy *pi, u16 addr, u16 val)
 {
-	struct si_info *sii = container_of(pi->sh->sih, struct si_info, pub);
-
 	if ((D11REV_GE(pi->sh->corerev, 24)) ||
 	    (D11REV_IS(pi->sh->corerev, 22)
 	     && (pi->pubpi.phy_type != PHY_TYPE_SSN))) {
@@ -211,7 +209,7 @@ void write_radio_reg(struct brcms_phy *pi, u16 addr, u16 val)
 		bcma_write16(pi->d11core, D11REGOFFS(phy4wdatalo), val);
 	}
 
-	if ((sii->icbus->hosttype == BCMA_HOSTTYPE_PCI) &&
+	if ((pi->d11core->bus->hosttype == BCMA_HOSTTYPE_PCI) &&
 	    (++pi->phy_wreg >= pi->phy_wreg_limit)) {
 		(void)bcma_read32(pi->d11core, D11REGOFFS(maccontrol));
 		pi->phy_wreg = 0;
@@ -297,10 +295,8 @@ void write_phy_reg(struct brcms_phy *pi, u16 addr, u16 val)
 	if (addr == 0x72)
 		(void)bcma_read16(pi->d11core, D11REGOFFS(phyregdata));
 #else
-	struct si_info *sii = container_of(pi->sh->sih, struct si_info, pub);
-
 	bcma_write32(pi->d11core, D11REGOFFS(phyregaddr), addr | (val << 16));
-	if ((sii->icbus->hosttype == BCMA_HOSTTYPE_PCI) &&
+	if ((pi->d11core->bus->hosttype == BCMA_HOSTTYPE_PCI) &&
 	    (++pi->phy_wreg >= pi->phy_wreg_limit)) {
 		pi->phy_wreg = 0;
 		(void)bcma_read16(pi->d11core, D11REGOFFS(phyversion));
@@ -374,7 +370,6 @@ struct shared_phy *wlc_phy_shared_attach(struct shared_phy_params *shp)
 	if (sh == NULL)
 		return NULL;
 
-	sh->sih = shp->sih;
 	sh->physhim = shp->physhim;
 	sh->unit = shp->unit;
 	sh->corerev = shp->corerev;
@@ -2911,29 +2906,24 @@ void wlc_lcnphy_epa_switch(struct brcms_phy *pi, bool mode)
 				mod_phy_reg(pi, 0x44c, (0x1 << 2), (1) << 2);
 
 			}
-			ai_cc_reg(pi->sh->sih,
-				  offsetof(struct chipcregs, gpiocontrol),
-				  ~0x0, 0x0);
-			ai_cc_reg(pi->sh->sih,
-				  offsetof(struct chipcregs, gpioout),
-				  0x40, 0x40);
-			ai_cc_reg(pi->sh->sih,
-				  offsetof(struct chipcregs, gpioouten),
-				  0x40, 0x40);
+
+			bcma_chipco_gpio_control(&pi->d11core->bus->drv_cc,
+						 0x0, 0x0);
+			bcma_chipco_gpio_out(&pi->d11core->bus->drv_cc,
+					     ~0x40, 0x40);
+			bcma_chipco_gpio_outen(&pi->d11core->bus->drv_cc,
+					       ~0x40, 0x40);
 		} else {
 			mod_phy_reg(pi, 0x44c, (0x1 << 2), (0) << 2);
 
 			mod_phy_reg(pi, 0x44d, (0x1 << 2), (0) << 2);
 
-			ai_cc_reg(pi->sh->sih,
-				  offsetof(struct chipcregs, gpioout),
-				  0x40, 0x00);
-			ai_cc_reg(pi->sh->sih,
-				  offsetof(struct chipcregs, gpioouten),
-				  0x40, 0x0);
-			ai_cc_reg(pi->sh->sih,
-				  offsetof(struct chipcregs, gpiocontrol),
-				  ~0x0, 0x40);
+			bcma_chipco_gpio_out(&pi->d11core->bus->drv_cc,
+					     ~0x40, 0x00);
+			bcma_chipco_gpio_outen(&pi->d11core->bus->drv_cc,
+					       ~0x40, 0x00);
+			bcma_chipco_gpio_control(&pi->d11core->bus->drv_cc,
+						 0x0, 0x40);
 		}
 	}
 }
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_int.h b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_int.h
index af00e2c..1dc767c 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_int.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_int.h
@@ -488,7 +488,6 @@ struct lcnphy_cal_results {
 struct shared_phy {
 	struct brcms_phy *phy_head;
 	uint unit;
-	struct si_pub *sih;
 	struct phy_shim_info *physhim;
 	uint corerev;
 	u32 machwcap;
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c
index 21a8242..3d6b16c 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c
@@ -1137,9 +1137,8 @@ wlc_lcnphy_set_rx_gain_by_distribution(struct brcms_phy *pi,
 	gain0_15 = ((biq1 & 0xf) << 12) |
 		   ((tia & 0xf) << 8) |
 		   ((lna2 & 0x3) << 6) |
-		   ((lna2 & 0x3) << 4) |
-		   ((lna1 & 0x3) << 2) |
-		   ((lna1 & 0x3) << 0);
+		   ((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);
@@ -1157,8 +1156,6 @@ wlc_lcnphy_set_rx_gain_by_distribution(struct brcms_phy *pi,
 	}
 
 	mod_phy_reg(pi, 0x44d, (0x1 << 0), (!trsw) << 0);
-	mod_phy_reg(pi, 0x4b1, (0x3 << 11), lna1 << 11);
-	mod_phy_reg(pi, 0x4e6, (0x3 << 3), lna1 << 3);
 
 }
 
@@ -1331,43 +1328,6 @@ static u32 wlc_lcnphy_measure_digital_power(struct brcms_phy *pi, u16 nsamples)
 	return (iq_est.i_pwr + iq_est.q_pwr) / nsamples;
 }
 
-static bool wlc_lcnphy_rx_iq_cal_gain(struct brcms_phy *pi, u16 biq1_gain,
-				      u16 tia_gain, u16 lna2_gain)
-{
-	u32 i_thresh_l, q_thresh_l;
-	u32 i_thresh_h, q_thresh_h;
-	struct lcnphy_iq_est iq_est_h, iq_est_l;
-
-	wlc_lcnphy_set_rx_gain_by_distribution(pi, 0, 0, 0, biq1_gain, tia_gain,
-					       lna2_gain, 0);
-
-	wlc_lcnphy_rx_gain_override_enable(pi, true);
-	wlc_lcnphy_start_tx_tone(pi, 2000, (40 >> 1), 0);
-	udelay(500);
-	write_radio_reg(pi, RADIO_2064_REG112, 0);
-	if (!wlc_lcnphy_rx_iq_est(pi, 1024, 32, &iq_est_l))
-		return false;
-
-	wlc_lcnphy_start_tx_tone(pi, 2000, 40, 0);
-	udelay(500);
-	write_radio_reg(pi, RADIO_2064_REG112, 0);
-	if (!wlc_lcnphy_rx_iq_est(pi, 1024, 32, &iq_est_h))
-		return false;
-
-	i_thresh_l = (iq_est_l.i_pwr << 1);
-	i_thresh_h = (iq_est_l.i_pwr << 2) + iq_est_l.i_pwr;
-
-	q_thresh_l = (iq_est_l.q_pwr << 1);
-	q_thresh_h = (iq_est_l.q_pwr << 2) + iq_est_l.q_pwr;
-	if ((iq_est_h.i_pwr > i_thresh_l) &&
-	    (iq_est_h.i_pwr < i_thresh_h) &&
-	    (iq_est_h.q_pwr > q_thresh_l) &&
-	    (iq_est_h.q_pwr < q_thresh_h))
-		return true;
-
-	return false;
-}
-
 static bool
 wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi,
 		     const struct lcnphy_rx_iqcomp *iqcomp,
@@ -1382,8 +1342,8 @@ wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi,
 	    RFOverrideVal0_old, rfoverride2_old, rfoverride2val_old,
 	    rfoverride3_old, rfoverride3val_old, rfoverride4_old,
 	    rfoverride4val_old, afectrlovr_old, afectrlovrval_old;
-	int tia_gain, lna2_gain, biq1_gain;
-	bool set_gain;
+	int tia_gain;
+	u32 received_power, rx_pwr_threshold;
 	u16 old_sslpnCalibClkEnCtrl, old_sslpnRxFeClkEnCtrl;
 	u16 values_to_save[11];
 	s16 *ptr;
@@ -1408,134 +1368,126 @@ wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi,
 		goto cal_done;
 	}
 
-	WARN_ON(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);
+	if (module == 1) {
 
-	mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0);
-	mod_phy_reg(pi, 0x4fa, (0x1 << 0), 0 << 0);
+		tx_pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
+		wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
 
-	mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1);
-	mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1);
+		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;
+		}
 
-	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);
+		wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_idx);
 
-	mod_phy_reg(pi, 0x43b, (0x1 << 0), 1 << 0);
-	mod_phy_reg(pi, 0x43c, (0x1 << 0), 0 << 0);
+		mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0);
+		mod_phy_reg(pi, 0x4fa, (0x1 << 0), 0 << 0);
 
-	write_phy_reg(pi, 0x6da, 0xffff);
-	or_phy_reg(pi, 0x6db, 0x3);
+		mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1);
+		mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1);
 
-	wlc_lcnphy_set_trsw_override(pi, tx_switch, rx_switch);
-	set_gain = false;
-
-	lna2_gain = 3;
-	while ((lna2_gain >= 0) && !set_gain) {
-		tia_gain = 4;
-
-		while ((tia_gain >= 0) && !set_gain) {
-			biq1_gain = 6;
-
-			while ((biq1_gain >= 0) && !set_gain) {
-				set_gain = wlc_lcnphy_rx_iq_cal_gain(pi,
-								     (u16)
-								     biq1_gain,
-								     (u16)
-								     tia_gain,
-								     (u16)
-								     lna2_gain);
-				biq1_gain -= 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;
 		}
-		lna2_gain -= 1;
-	}
+		result = wlc_lcnphy_calc_rx_iq_comp(pi, 0xffff);
 
-	if (set_gain)
-		result = wlc_lcnphy_calc_rx_iq_comp(pi, 1024);
-	else
-		result = false;
+		wlc_lcnphy_stop_tx_tone(pi);
 
-	wlc_lcnphy_stop_tx_tone(pi);
+		write_phy_reg(pi, 0x631, Core1TxControl_old);
 
-	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);
+		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);
+		wlc_lcnphy_clear_trsw_override(pi);
 
-	mod_phy_reg(pi, 0x44c, (0x1 << 2), 0 << 2);
+		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]);
+		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);
+		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);
+		wlc_lcnphy_set_tx_pwr_ctrl(pi, tx_pwr_ctrl);
+		wlc_lcnphy_rx_gain_override_enable(pi, false);
+	}
 
 cal_done:
 	kfree(ptr);
@@ -1643,11 +1595,15 @@ wlc_lcnphy_set_chanspec_tweaks(struct brcms_phy *pi, u16 chanspec)
 	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);
+		bcma_chipco_pll_write(&pi->d11core->bus->drv_cc, 0x2,
+				      0x03000c04);
+		bcma_chipco_pll_maskset(&pi->d11core->bus->drv_cc, 0x3,
+					~0x00ffffff, 0x0);
+		bcma_chipco_pll_write(&pi->d11core->bus->drv_cc, 0x4,
+				      0x200005c0);
+
+		bcma_cc_set32(&pi->d11core->bus->drv_cc, BCMA_CC_PMU_CTL,
+			      BCMA_CC_PMU_CTL_PLL_UPD);
 		write_phy_reg(pi, 0x942, 0);
 		wlc_lcnphy_txrx_spur_avoidance_mode(pi, false);
 		pi_lcn->lcnphy_spurmod = false;
@@ -1655,11 +1611,15 @@ wlc_lcnphy_set_chanspec_tweaks(struct brcms_phy *pi, u16 chanspec)
 
 		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);
+		bcma_chipco_pll_write(&pi->d11core->bus->drv_cc, 0x2,
+				      0x03140c04);
+		bcma_chipco_pll_maskset(&pi->d11core->bus->drv_cc, 0x3,
+					~0x00ffffff, 0x333333);
+		bcma_chipco_pll_write(&pi->d11core->bus->drv_cc, 0x4,
+				      0x202c2820);
+
+		bcma_cc_set32(&pi->d11core->bus->drv_cc, BCMA_CC_PMU_CTL,
+			      BCMA_CC_PMU_CTL_PLL_UPD);
 		write_phy_reg(pi, 0x942, 0);
 		wlc_lcnphy_txrx_spur_avoidance_mode(pi, true);
 
@@ -1829,17 +1789,6 @@ wlc_lcnphy_radio_2064_channel_tune_4313(struct brcms_phy *pi, u8 channel)
 		write_radio_reg(pi, RADIO_2064_REG038, 3);
 		write_radio_reg(pi, RADIO_2064_REG091, 7);
 	}
-
-	if (!(pi->sh->boardflags & BFL_FEM)) {
-		u8 reg038[14] = {0xd, 0xe, 0xd, 0xd, 0xd, 0xc,
-			0xa, 0xb, 0xb, 0x3, 0x3, 0x2, 0x0, 0x0};
-
-		write_radio_reg(pi, RADIO_2064_REG02A, 0xf);
-		write_radio_reg(pi, RADIO_2064_REG091, 0x3);
-		write_radio_reg(pi, RADIO_2064_REG038, 0x3);
-
-		write_radio_reg(pi, RADIO_2064_REG038, reg038[channel - 1]);
-	}
 }
 
 static int
@@ -2034,16 +1983,6 @@ wlc_lcnphy_set_tssi_mux(struct brcms_phy *pi, enum lcnphy_tssi_mode pos)
 		} else {
 			mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0x1);
 			mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8);
-			mod_radio_reg(pi, RADIO_2064_REG028, 0x1, 0x0);
-			mod_radio_reg(pi, RADIO_2064_REG11A, 0x4, 1<<2);
-			mod_radio_reg(pi, RADIO_2064_REG036, 0x10, 0x0);
-			mod_radio_reg(pi, RADIO_2064_REG11A, 0x10, 1<<4);
-			mod_radio_reg(pi, RADIO_2064_REG036, 0x3, 0x0);
-			mod_radio_reg(pi, RADIO_2064_REG035, 0xff, 0x77);
-			mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, 0xe<<1);
-			mod_radio_reg(pi, RADIO_2064_REG112, 0x80, 1<<7);
-			mod_radio_reg(pi, RADIO_2064_REG005, 0x7, 1<<1);
-			mod_radio_reg(pi, RADIO_2064_REG029, 0xf0, 0<<4);
 		}
 	} else {
 		mod_phy_reg(pi, 0x4d9, (0x1 << 2), (0x1) << 2);
@@ -2130,14 +2069,12 @@ static void wlc_lcnphy_pwrctrl_rssiparams(struct brcms_phy *pi)
 		    (auxpga_vmid_temp << 0) | (auxpga_gain_temp << 12));
 
 	mod_radio_reg(pi, RADIO_2064_REG082, (1 << 5), (1 << 5));
-	mod_radio_reg(pi, RADIO_2064_REG07C, (1 << 0), (1 << 0));
 }
 
 static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi)
 {
 	struct phytbl_info tab;
 	u32 rfseq, ind;
-	u8 tssi_sel;
 
 	tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
 	tab.tbl_width = 32;
@@ -2159,13 +2096,7 @@ static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi)
 
 	mod_phy_reg(pi, 0x503, (0x1 << 4), (1) << 4);
 
-	if (pi->sh->boardflags & BFL_FEM) {
-		tssi_sel = 0x1;
-		wlc_lcnphy_set_tssi_mux(pi, LCNPHY_TSSI_EXT);
-	} else {
-		tssi_sel = 0xe;
-		wlc_lcnphy_set_tssi_mux(pi, LCNPHY_TSSI_POST_PA);
-	}
+	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);
@@ -2201,10 +2132,9 @@ static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi)
 	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, tssi_sel);
+		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_REG028, 0x1e, tssi_sel << 1);
 		mod_radio_reg(pi, RADIO_2064_REG03A, 0x1, 1);
 		mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 1 << 3);
 	}
@@ -2251,10 +2181,6 @@ static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi)
 
 	mod_phy_reg(pi, 0x4d7, (0xf << 8), (0) << 8);
 
-	mod_radio_reg(pi, RADIO_2064_REG035, 0xff, 0x0);
-	mod_radio_reg(pi, RADIO_2064_REG036, 0x3, 0x0);
-	mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8);
-
 	wlc_lcnphy_pwrctrl_rssiparams(pi);
 }
 
@@ -2873,8 +2799,6 @@ static void wlc_lcnphy_idle_tssi_est(struct brcms_phy_pub *ppi)
 		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;
-	u8 SAVE_bbmult = wlc_lcnphy_get_bbmult(pi);
-
 	idleTssi = read_phy_reg(pi, 0x4ab);
 	suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) &
 			 MCTL_EN_MAC));
@@ -2892,12 +2816,6 @@ static void wlc_lcnphy_idle_tssi_est(struct brcms_phy_pub *ppi)
 	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);
-
-	mod_phy_reg(pi, 0x4d7, (0x1 << 0), (1 << 0));
-	mod_phy_reg(pi, 0x4d7, (0x1 << 6), (1 << 6));
-
-	wlc_lcnphy_set_bbmult(pi, 0x0);
-
 	wlc_phy_do_dummy_tx(pi, true, OFF);
 	idleTssi = ((read_phy_reg(pi, 0x4ab) & (0x1ff << 0))
 		    >> 0);
@@ -2919,7 +2837,6 @@ static void wlc_lcnphy_idle_tssi_est(struct brcms_phy_pub *ppi)
 
 	mod_phy_reg(pi, 0x44c, (0x1 << 12), (0) << 12);
 
-	wlc_lcnphy_set_bbmult(pi, SAVE_bbmult);
 	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);
@@ -3133,11 +3050,6 @@ static void wlc_lcnphy_tx_pwr_ctrl_init(struct brcms_phy_pub *ppi)
 			wlc_lcnphy_write_table(pi, &tab);
 			tab.tbl_offset++;
 		}
-		mod_phy_reg(pi, 0x4d0, (0x1 << 0), (0) << 0);
-		mod_phy_reg(pi, 0x4d3, (0xff << 0), (0) << 0);
-		mod_phy_reg(pi, 0x4d3, (0xff << 8), (0) << 8);
-		mod_phy_reg(pi, 0x4d0, (0x1 << 4), (0) << 4);
-		mod_phy_reg(pi, 0x4d0, (0x1 << 2), (0) << 2);
 
 		mod_phy_reg(pi, 0x410, (0x1 << 7), (0) << 7);
 
@@ -3939,6 +3851,7 @@ static void wlc_lcnphy_txpwrtbl_iqlo_cal(struct brcms_phy *pi)
 	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) {
 
@@ -3949,7 +3862,6 @@ static void wlc_lcnphy_txpwrtbl_iqlo_cal(struct brcms_phy *pi)
 					lcnphy_recal ? LCNPHY_CAL_RECAL :
 					LCNPHY_CAL_FULL), false);
 	} else {
-		wlc_lcnphy_set_tx_pwr_by_index(pi, 16);
 		wlc_lcnphy_tx_iqlo_soft_cal_full(pi);
 	}
 
@@ -4374,22 +4286,17 @@ wlc_lcnphy_load_tx_gain_table(struct brcms_phy *pi,
 	if (CHSPEC_IS5G(pi->radio_chanspec))
 		pa_gain = 0x70;
 	else
-		pa_gain = 0x60;
+		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++) {
-		if (pi->sh->boardflags & BFL_FEM)
-			gm_gain = gain_table[j].gm;
-		else
-			gm_gain = 15;
-
+		gm_gain = gain_table[j].gm;
 		val = (((u32) pa_gain << 24) |
 		       (gain_table[j].pad << 16) |
 		       (gain_table[j].pga << 8) | gm_gain);
@@ -4600,10 +4507,7 @@ static void wlc_radio_2064_init(struct brcms_phy *pi)
 
 	write_phy_reg(pi, 0x4ea, 0x4688);
 
-	if (pi->sh->boardflags & BFL_FEM)
-		mod_phy_reg(pi, 0x4eb, (0x7 << 0), 2 << 0);
-	else
-		mod_phy_reg(pi, 0x4eb, (0x7 << 0), 3 << 0);
+	mod_phy_reg(pi, 0x4eb, (0x7 << 0), 2 << 0);
 
 	mod_phy_reg(pi, 0x4eb, (0x7 << 6), 0 << 6);
 
@@ -4614,13 +4518,6 @@ static void wlc_radio_2064_init(struct brcms_phy *pi)
 	wlc_lcnphy_rcal(pi);
 
 	wlc_lcnphy_rc_cal(pi);
-
-	if (!(pi->sh->boardflags & BFL_FEM)) {
-		write_radio_reg(pi, RADIO_2064_REG032, 0x6f);
-		write_radio_reg(pi, RADIO_2064_REG033, 0x19);
-		write_radio_reg(pi, RADIO_2064_REG039, 0xe);
-	}
-
 }
 
 static void wlc_lcnphy_radio_init(struct brcms_phy *pi)
@@ -4650,20 +4547,22 @@ static void wlc_lcnphy_tbl_init(struct brcms_phy *pi)
 		wlc_lcnphy_write_table(pi, &tab);
 	}
 
-	if (!(pi->sh->boardflags & BFL_FEM)) {
-		tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
-		tab.tbl_width = 16;
-		tab.tbl_ptr = &val;
-		tab.tbl_len = 1;
+	tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
+	tab.tbl_width = 16;
+	tab.tbl_ptr = &val;
+	tab.tbl_len = 1;
 
-		val = 150;
-		tab.tbl_offset = 0;
-		wlc_lcnphy_write_table(pi, &tab);
+	val = 114;
+	tab.tbl_offset = 0;
+	wlc_lcnphy_write_table(pi, &tab);
 
-		val = 220;
-		tab.tbl_offset = 1;
-		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)
@@ -4864,9 +4763,10 @@ void wlc_phy_init_lcnphy(struct brcms_phy *pi)
 
 	wlc_phy_chanspec_set((struct brcms_phy_pub *) pi, pi->radio_chanspec);
 
-	si_pmu_regcontrol(pi->sh->sih, 0, 0xf, 0x9);
+	bcma_chipco_regctl_maskset(&pi->d11core->bus->drv_cc, 0, ~0xf, 0x9);
 
-	si_pmu_chipcontrol(pi->sh->sih, 0, 0xffffffff, 0x03CDDDDD);
+	bcma_chipco_chipctl_maskset(&pi->d11core->bus->drv_cc, 0, 0x0,
+				    0x03CDDDDD);
 
 	if ((pi->sh->boardflags & BFL_FEM)
 	    && wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
@@ -5055,7 +4955,6 @@ void wlc_phy_chanspec_set_lcnphy(struct brcms_phy *pi, u16 chanspec)
 		wlc_lcnphy_load_tx_iir_filter(pi, true, 3);
 
 	mod_phy_reg(pi, 0x4eb, (0x7 << 3), (1) << 3);
-	wlc_lcnphy_tssi_setup(pi);
 }
 
 void wlc_phy_detach_lcnphy(struct brcms_phy *pi)
@@ -5078,7 +4977,7 @@ bool wlc_phy_attach_lcnphy(struct brcms_phy *pi)
 		pi->hwpwrctrl_capable = true;
 	}
 
-	pi->xtalfreq = si_pmu_alp_clock(pi->sh->sih);
+	pi->xtalfreq = bcma_chipco_get_alp_clock(&pi->d11core->bus->drv_cc);
 	pi_lcn->lcnphy_papd_rxGnCtrl_init = 0;
 
 	pi->pi_fptr.init = wlc_phy_init_lcnphy;
@@ -5094,7 +4993,8 @@ bool wlc_phy_attach_lcnphy(struct brcms_phy *pi)
 	if (!wlc_phy_txpwr_srom_read_lcnphy(pi))
 		return false;
 
-	if (LCNREV_IS(pi->pubpi.phy_rev, 1)) {
+	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;
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c
index 65db9b7..3e9f5b2 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c
@@ -19321,14 +19321,13 @@ void wlc_phy_init_nphy(struct brcms_phy *pi)
 	     (pi->sh->chippkg == BCMA_PKG_ID_BCM4718))) {
 		if ((pi->sh->boardflags & BFL_EXTLNA) &&
 		    (CHSPEC_IS2G(pi->radio_chanspec)))
-			ai_cc_reg(pi->sh->sih,
-				  offsetof(struct chipcregs, chipcontrol),
-				  0x40, 0x40);
+			bcma_cc_set32(&pi->d11core->bus->drv_cc,
+				      BCMA_CC_CHIPCTL, 0x40);
 	}
 
 	if ((!PHY_IPA(pi)) && (pi->sh->chip == BCMA_CHIP_ID_BCM5357))
-		si_pmu_chipcontrol(pi->sh->sih, 1, CCTRL5357_EXTPA,
-				   CCTRL5357_EXTPA);
+		bcma_chipco_chipctl_maskset(&pi->d11core->bus->drv_cc, 1,
+					    ~CCTRL5357_EXTPA, CCTRL5357_EXTPA);
 
 	if ((pi->nphy_gband_spurwar2_en) && CHSPEC_IS2G(pi->radio_chanspec) &&
 	    CHSPEC_IS40(pi->radio_chanspec)) {
@@ -21133,7 +21132,6 @@ wlc_phy_chanspec_nphy_setup(struct brcms_phy *pi, u16 chanspec,
 			    const struct nphy_sfo_cfg *ci)
 {
 	u16 val;
-	struct si_info *sii = container_of(pi->sh->sih, struct si_info, pub);
 
 	val = read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand;
 	if (CHSPEC_IS5G(chanspec) && !val) {
@@ -21221,11 +21219,11 @@ wlc_phy_chanspec_nphy_setup(struct brcms_phy *pi, u16 chanspec,
 
 		if ((pi->sh->chip == BCMA_CHIP_ID_BCM4716) ||
 		    (pi->sh->chip == BCMA_CHIP_ID_BCM43225)) {
-			bcma_pmu_spuravoid_pllupdate(&sii->icbus->drv_cc,
+			bcma_pmu_spuravoid_pllupdate(&pi->d11core->bus->drv_cc,
 						     spuravoid);
 		} else {
 			wlapi_bmac_core_phypll_ctl(pi->sh->physhim, false);
-			bcma_pmu_spuravoid_pllupdate(&sii->icbus->drv_cc,
+			bcma_pmu_spuravoid_pllupdate(&pi->d11core->bus->drv_cc,
 						     spuravoid);
 			wlapi_bmac_core_phypll_ctl(pi->sh->physhim, true);
 		}
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c b/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c
index b7e95ac..622c01c 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c
@@ -1992,70 +1992,70 @@ static const u16 dot11lcn_sw_ctrl_tbl_4313_epa_rev0[] = {
 };
 
 static const u16 dot11lcn_sw_ctrl_tbl_4313_rev0[] = {
-	0x0009,
 	0x000a,
-	0x0005,
-	0x0006,
 	0x0009,
-	0x000a,
-	0x0005,
 	0x0006,
-	0x0009,
-	0x000a,
 	0x0005,
-	0x0006,
-	0x0009,
 	0x000a,
-	0x0005,
-	0x0006,
 	0x0009,
-	0x000a,
-	0x0005,
 	0x0006,
-	0x0009,
-	0x000a,
 	0x0005,
-	0x0006,
-	0x0009,
 	0x000a,
-	0x0005,
-	0x0006,
 	0x0009,
-	0x000a,
-	0x0005,
 	0x0006,
-	0x0009,
-	0x000a,
 	0x0005,
-	0x0006,
-	0x0009,
 	0x000a,
-	0x0005,
-	0x0006,
 	0x0009,
-	0x000a,
-	0x0005,
 	0x0006,
-	0x0009,
-	0x000a,
 	0x0005,
-	0x0006,
+	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,
 };
 
 static const u16 dot11lcn_sw_ctrl_tbl_rev0[] = {
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/pmu.c b/drivers/net/wireless/brcm80211/brcmsmac/pmu.c
index 7e9df56..71b8038 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/pmu.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/pmu.c
@@ -115,60 +115,6 @@ u16 si_pmu_fast_pwrup_delay(struct si_pub *sih)
 	return (u16) delay;
 }
 
-/* Read/write a chipcontrol reg */
-u32 si_pmu_chipcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val)
-{
-	ai_cc_reg(sih, offsetof(struct chipcregs, chipcontrol_addr), ~0, reg);
-	return ai_cc_reg(sih, offsetof(struct chipcregs, chipcontrol_data),
-			 mask, val);
-}
-
-/* Read/write a regcontrol reg */
-u32 si_pmu_regcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val)
-{
-	ai_cc_reg(sih, offsetof(struct chipcregs, regcontrol_addr), ~0, reg);
-	return ai_cc_reg(sih, offsetof(struct chipcregs, regcontrol_data),
-			 mask, val);
-}
-
-/* Read/write a pllcontrol reg */
-u32 si_pmu_pllcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val)
-{
-	ai_cc_reg(sih, offsetof(struct chipcregs, pllcontrol_addr), ~0, reg);
-	return ai_cc_reg(sih, offsetof(struct chipcregs, pllcontrol_data),
-			 mask, val);
-}
-
-/* PMU PLL update */
-void si_pmu_pllupd(struct si_pub *sih)
-{
-	ai_cc_reg(sih, offsetof(struct chipcregs, 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 (!(ai_get_cccaps(sih) & CC_CAP_PMU))
-		return clock;
-
-	switch (ai_get_chip_id(sih)) {
-	case BCMA_CHIP_ID_BCM43224:
-	case BCMA_CHIP_ID_BCM43225:
-	case BCMA_CHIP_ID_BCM4313:
-		/* always 20Mhz */
-		clock = 20000 * 1000;
-		break;
-	default:
-		break;
-	}
-
-	return clock;
-}
-
 u32 si_pmu_measure_alpclk(struct si_pub *sih)
 {
 	struct si_info *sii = container_of(sih, struct si_info, pub);
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/pmu.h b/drivers/net/wireless/brcm80211/brcmsmac/pmu.h
index f7cff87..20e2012 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/pmu.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/pmu.h
@@ -21,12 +21,6 @@
 #include "types.h"
 
 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_alp_clock(struct si_pub *sih);
-extern void si_pmu_pllupd(struct si_pub *sih);
-extern u32 si_pmu_pllcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val);
 extern u32 si_pmu_measure_alpclk(struct si_pub *sih);
 
 #endif /* _BRCM_PMU_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/pub.h b/drivers/net/wireless/brcm80211/brcmsmac/pub.h
index b0f14b7..d36ea5e 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/pub.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/pub.h
@@ -164,8 +164,6 @@ struct brcms_pub {
 
 	u8 cur_etheraddr[ETH_ALEN];	/* our local ethernet address */
 
-	int bcmerror;		/* last bcm error */
-
 	u32 radio_disabled;	/* bit vector for radio disabled reasons */
 
 	u16 boardrev;	/* version # of particular board */
@@ -326,10 +324,25 @@ extern void brcms_c_set_shortslot_override(struct brcms_c_info *wlc,
 				    s8 sslot_override);
 extern void brcms_c_set_beacon_listen_interval(struct brcms_c_info *wlc,
 					u8 interval);
+extern u64 brcms_c_tsf_get(struct brcms_c_info *wlc);
+extern void brcms_c_tsf_set(struct brcms_c_info *wlc, u64 tsf);
 extern int brcms_c_set_tx_power(struct brcms_c_info *wlc, int txpwr);
 extern int brcms_c_get_tx_power(struct brcms_c_info *wlc);
 extern bool brcms_c_check_radio_disabled(struct brcms_c_info *wlc);
 extern void brcms_c_mute(struct brcms_c_info *wlc, bool on);
 extern bool brcms_c_tx_flush_completed(struct brcms_c_info *wlc);
+extern void brcms_c_start_station(struct brcms_c_info *wlc, u8 *addr);
+extern void brcms_c_start_ap(struct brcms_c_info *wlc, u8 *addr,
+			     const u8 *bssid, u8 *ssid, size_t ssid_len);
+extern void brcms_c_start_adhoc(struct brcms_c_info *wlc, u8 *addr);
+extern void brcms_c_update_beacon(struct brcms_c_info *wlc);
+extern void brcms_c_set_new_beacon(struct brcms_c_info *wlc,
+				   struct sk_buff *beacon, u16 tim_offset,
+				   u16 dtim_period);
+extern void brcms_c_set_new_probe_resp(struct brcms_c_info *wlc,
+				       struct sk_buff *probe_resp);
+extern void brcms_c_enable_probe_resp(struct brcms_c_info *wlc, bool enable);
+extern void brcms_c_set_ssid(struct brcms_c_info *wlc, u8 *ssid,
+			     size_t ssid_len);
 
 #endif				/* _BRCM_PUB_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmutil/utils.c b/drivers/net/wireless/brcm80211/brcmutil/utils.c
index 3e6405e..bf5e50f 100644
--- a/drivers/net/wireless/brcm80211/brcmutil/utils.c
+++ b/drivers/net/wireless/brcm80211/brcmutil/utils.c
@@ -116,6 +116,31 @@ struct sk_buff *brcmu_pktq_pdeq(struct pktq *pq, int prec)
 }
 EXPORT_SYMBOL(brcmu_pktq_pdeq);
 
+/*
+ * precedence based dequeue with match function. Passing a NULL pointer
+ * for the match function parameter is considered to be a wildcard so
+ * any packet on the queue is returned. In that case it is no different
+ * from brcmu_pktq_pdeq() above.
+ */
+struct sk_buff *brcmu_pktq_pdeq_match(struct pktq *pq, int prec,
+				      bool (*match_fn)(struct sk_buff *skb,
+						       void *arg), void *arg)
+{
+	struct sk_buff_head *q;
+	struct sk_buff *p, *next;
+
+	q = &pq->q[prec].skblist;
+	skb_queue_walk_safe(q, p, next) {
+		if (match_fn == NULL || match_fn(p, arg)) {
+			skb_unlink(p, q);
+			pq->len--;
+			return p;
+		}
+	}
+	return NULL;
+}
+EXPORT_SYMBOL(brcmu_pktq_pdeq_match);
+
 struct sk_buff *brcmu_pktq_pdeq_tail(struct pktq *pq, int prec)
 {
 	struct sk_buff_head *q;
diff --git a/drivers/net/wireless/brcm80211/include/brcmu_utils.h b/drivers/net/wireless/brcm80211/include/brcmu_utils.h
index 477b92a..898cacb 100644
--- a/drivers/net/wireless/brcm80211/include/brcmu_utils.h
+++ b/drivers/net/wireless/brcm80211/include/brcmu_utils.h
@@ -120,6 +120,10 @@ 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);
+extern struct sk_buff *brcmu_pktq_pdeq_match(struct pktq *pq, int prec,
+					     bool (*match_fn)(struct sk_buff *p,
+							      void *arg),
+					     void *arg);
 
 /* packet primitives */
 extern struct sk_buff *brcmu_pkt_buf_get_skb(uint len);
@@ -173,6 +177,29 @@ extern void brcmu_pktq_flush(struct pktq *pq, bool dir,
 /* ip address */
 struct ipv4_addr;
 
+/*
+ * bitfield macros using masking and shift
+ *
+ * remark: the mask parameter should be a shifted mask.
+ */
+static inline void brcmu_maskset32(u32 *var, u32 mask, u8 shift, u32 value)
+{
+	value = (value << shift) & mask;
+	*var = (*var & ~mask) | value;
+}
+static inline u32 brcmu_maskget32(u32 var, u32 mask, u8 shift)
+{
+	return (var & mask) >> shift;
+}
+static inline void brcmu_maskset16(u16 *var, u16 mask, u8 shift, u16 value)
+{
+	value = (value << shift) & mask;
+	*var = (*var & ~mask) | value;
+}
+static inline u16 brcmu_maskget16(u16 var, u16 mask, u8 shift)
+{
+	return (var & mask) >> shift;
+}
 
 /* externs */
 /* format/print */
diff --git a/drivers/net/wireless/brcm80211/include/brcmu_wifi.h b/drivers/net/wireless/brcm80211/include/brcmu_wifi.h
index c11a290..0505cc0 100644
--- a/drivers/net/wireless/brcm80211/include/brcmu_wifi.h
+++ b/drivers/net/wireless/brcm80211/include/brcmu_wifi.h
@@ -32,8 +32,9 @@
 #define CH_20MHZ_APART			4
 #define CH_10MHZ_APART			2
 #define CH_5MHZ_APART			1 /* 2G band channels are 5 Mhz apart */
+#define CH_MIN_2G_CHANNEL		1
 #define CH_MAX_2G_CHANNEL		14	/* Max channel in 2G band */
-#define BRCM_MAX_2G_CHANNEL	CH_MAX_2G_CHANNEL	/* legacy define */
+#define CH_MIN_5G_CHANNEL		34
 
 /* bandstate array indices */
 #define BAND_2G_INDEX		0	/* wlc->bandstate[x] index */
@@ -60,6 +61,7 @@
 #define WL_CHANSPEC_BW_10		0x0400
 #define WL_CHANSPEC_BW_20		0x0800
 #define WL_CHANSPEC_BW_40		0x0C00
+#define WL_CHANSPEC_BW_80		0x2000
 
 #define WL_CHANSPEC_BAND_MASK		0xf000
 #define WL_CHANSPEC_BAND_SHIFT		12
@@ -67,6 +69,25 @@
 #define WL_CHANSPEC_BAND_2G		0x2000
 #define INVCHANSPEC			255
 
+#define WL_CHAN_VALID_HW		(1 << 0) /* valid with current HW */
+#define WL_CHAN_VALID_SW		(1 << 1) /* valid with country sett. */
+#define WL_CHAN_BAND_5G			(1 << 2) /* 5GHz-band channel */
+#define WL_CHAN_RADAR			(1 << 3) /* radar sensitive  channel */
+#define WL_CHAN_INACTIVE		(1 << 4) /* inactive due to radar */
+#define WL_CHAN_PASSIVE			(1 << 5) /* channel in passive mode */
+#define WL_CHAN_RESTRICTED		(1 << 6) /* restricted use channel */
+
+/* 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
+
+/* 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 */
+
 #define CHSPEC_CHANNEL(chspec)	((u8)((chspec) & WL_CHANSPEC_CHAN_MASK))
 #define CHSPEC_BAND(chspec)	((chspec) & WL_CHANSPEC_BAND_MASK)
 
@@ -79,10 +100,11 @@
 #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
+
+#define CHSPEC_IS80(chspec) \
+	(((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_80)
 
 #define CHSPEC_IS5G(chspec) \
 	(((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_5G)
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c
index 89e9d3a..56cd01c 100644
--- a/drivers/net/wireless/hostap/hostap_cs.c
+++ b/drivers/net/wireless/hostap/hostap_cs.c
@@ -709,17 +709,4 @@ static struct pcmcia_driver hostap_driver = {
 	.suspend	= hostap_cs_suspend,
 	.resume		= hostap_cs_resume,
 };
-
-static int __init init_prism2_pccard(void)
-{
-	return pcmcia_register_driver(&hostap_driver);
-}
-
-static void __exit exit_prism2_pccard(void)
-{
-	pcmcia_unregister_driver(&hostap_driver);
-}
-
-
-module_init(init_prism2_pccard);
-module_exit(exit_prism2_pccard);
+module_pcmcia_driver(hostap_driver);
diff --git a/drivers/net/wireless/iwlegacy/3945-mac.c b/drivers/net/wireless/iwlegacy/3945-mac.c
index c353b5f..b37a582 100644
--- a/drivers/net/wireless/iwlegacy/3945-mac.c
+++ b/drivers/net/wireless/iwlegacy/3945-mac.c
@@ -3477,7 +3477,7 @@ static struct attribute_group il3945_attribute_group = {
 	.attrs = il3945_sysfs_entries,
 };
 
-struct ieee80211_ops il3945_mac_ops = {
+static struct ieee80211_ops il3945_mac_ops __read_mostly = {
 	.tx = il3945_mac_tx,
 	.start = il3945_mac_start,
 	.stop = il3945_mac_stop,
diff --git a/drivers/net/wireless/iwlegacy/3945.c b/drivers/net/wireless/iwlegacy/3945.c
index e0b9d7f..dc1e6da 100644
--- a/drivers/net/wireless/iwlegacy/3945.c
+++ b/drivers/net/wireless/iwlegacy/3945.c
@@ -2379,10 +2379,8 @@ il3945_hw_set_hw_params(struct il_priv *il)
 	il->_3945.shared_virt =
 	    dma_alloc_coherent(&il->pci_dev->dev, sizeof(struct il3945_shared),
 			       &il->_3945.shared_phys, GFP_KERNEL);
-	if (!il->_3945.shared_virt) {
-		IL_ERR("failed to allocate pci memory\n");
+	if (!il->_3945.shared_virt)
 		return -ENOMEM;
-	}
 
 	il->hw_params.bcast_id = IL3945_BROADCAST_ID;
 
diff --git a/drivers/net/wireless/iwlegacy/3945.h b/drivers/net/wireless/iwlegacy/3945.h
index 1d45075..9a8703d 100644
--- a/drivers/net/wireless/iwlegacy/3945.h
+++ b/drivers/net/wireless/iwlegacy/3945.h
@@ -150,10 +150,6 @@ struct il3945_frame {
 	struct list_head list;
 };
 
-#define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4)
-#define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ)
-#define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4)
-
 #define SUP_RATE_11A_MAX_NUM_CHANNELS  8
 #define SUP_RATE_11B_MAX_NUM_CHANNELS  4
 #define SUP_RATE_11G_MAX_NUM_CHANNELS  12
diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c
index 7941eb3..6affa7e 100644
--- a/drivers/net/wireless/iwlegacy/4965-mac.c
+++ b/drivers/net/wireless/iwlegacy/4965-mac.c
@@ -612,7 +612,7 @@ il4965_pass_packet_to_mac80211(struct il_priv *il, struct ieee80211_hdr *hdr,
 
 /* Called for N_RX (legacy ABG frames), or
  * N_RX_MPDU (HT high-throughput N frames). */
-void
+static void
 il4965_hdl_rx(struct il_priv *il, struct il_rx_buf *rxb)
 {
 	struct ieee80211_hdr *header;
@@ -744,7 +744,7 @@ il4965_hdl_rx(struct il_priv *il, struct il_rx_buf *rxb)
 
 /* Cache phy data (Rx signal strength, etc) for HT frame (N_RX_PHY).
  * This will be used later in il_hdl_rx() for N_RX_MPDU. */
-void
+static void
 il4965_hdl_rx_phy(struct il_priv *il, struct il_rx_buf *rxb)
 {
 	struct il_rx_pkt *pkt = rxb_addr(rxb);
@@ -1250,7 +1250,7 @@ il4965_dump_fh(struct il_priv *il, char **buf, bool display)
 	return 0;
 }
 
-void
+static void
 il4965_hdl_missed_beacon(struct il_priv *il, struct il_rx_buf *rxb)
 {
 	struct il_rx_pkt *pkt = rxb_addr(rxb);
@@ -1357,7 +1357,7 @@ il4965_accumulative_stats(struct il_priv *il, __le32 * stats)
 }
 #endif
 
-void
+static void
 il4965_hdl_stats(struct il_priv *il, struct il_rx_buf *rxb)
 {
 	const int recalib_seconds = 60;
@@ -1399,7 +1399,7 @@ il4965_hdl_stats(struct il_priv *il, struct il_rx_buf *rxb)
 		il4965_temperature_calib(il);
 }
 
-void
+static void
 il4965_hdl_c_stats(struct il_priv *il, struct il_rx_buf *rxb)
 {
 	struct il_rx_pkt *pkt = rxb_addr(rxb);
@@ -1921,8 +1921,8 @@ drop_unlock:
 static inline int
 il4965_alloc_dma_ptr(struct il_priv *il, struct il_dma_ptr *ptr, size_t size)
 {
-	ptr->addr =
-	    dma_alloc_coherent(&il->pci_dev->dev, size, &ptr->dma, GFP_KERNEL);
+	ptr->addr = dma_alloc_coherent(&il->pci_dev->dev, size, &ptr->dma,
+				       GFP_KERNEL);
 	if (!ptr->addr)
 		return -ENOMEM;
 	ptr->size = size;
@@ -2050,7 +2050,7 @@ il4965_txq_ctx_reset(struct il_priv *il)
 		il_tx_queue_reset(il, txq_id);
 }
 
-void
+static void
 il4965_txq_ctx_unmap(struct il_priv *il)
 {
 	int txq_id;
@@ -2258,7 +2258,7 @@ il4965_tx_agg_start(struct il_priv *il, struct ieee80211_vif *vif,
 
 	spin_lock_irqsave(&il->sta_lock, flags);
 	tid_data = &il->stations[sta_id].tid[tid];
-	*ssn = SEQ_TO_SN(tid_data->seq_number);
+	*ssn = IEEE80211_SEQ_TO_SN(tid_data->seq_number);
 	tid_data->agg.txq_id = txq_id;
 	il_set_swq_id(&il->txq[txq_id], il4965_get_ac_from_tid(tid), txq_id);
 	spin_unlock_irqrestore(&il->sta_lock, flags);
@@ -2408,7 +2408,7 @@ il4965_txq_check_empty(struct il_priv *il, int sta_id, u8 tid, int txq_id)
 		/* aggregated HW queue */
 		if (txq_id == tid_data->agg.txq_id &&
 		    q->read_ptr == q->write_ptr) {
-			u16 ssn = SEQ_TO_SN(tid_data->seq_number);
+			u16 ssn = IEEE80211_SEQ_TO_SN(tid_data->seq_number);
 			int tx_fifo = il4965_get_fifo_from_tid(tid);
 			D_HT("HW queue empty: continue DELBA flow\n");
 			il4965_txq_agg_disable(il, txq_id, ssn, tx_fifo);
@@ -2627,7 +2627,8 @@ il4965_get_ra_sta_id(struct il_priv *il, struct ieee80211_hdr *hdr)
 static inline u32
 il4965_get_scd_ssn(struct il4965_tx_resp *tx_resp)
 {
-	return le32_to_cpup(&tx_resp->u.status + tx_resp->frame_count) & MAX_SN;
+	return le32_to_cpup(&tx_resp->u.status +
+			    tx_resp->frame_count) & IEEE80211_MAX_SN;
 }
 
 static inline u32
@@ -2717,15 +2718,15 @@ il4965_tx_status_reply_tx(struct il_priv *il, struct il_ht_agg *agg,
 			hdr = (struct ieee80211_hdr *) skb->data;
 
 			sc = le16_to_cpu(hdr->seq_ctrl);
-			if (idx != (SEQ_TO_SN(sc) & 0xff)) {
+			if (idx != (IEEE80211_SEQ_TO_SN(sc) & 0xff)) {
 				IL_ERR("BUG_ON idx doesn't match seq control"
 				       " idx=%d, seq_idx=%d, seq=%d\n", idx,
-				       SEQ_TO_SN(sc), hdr->seq_ctrl);
+				       IEEE80211_SEQ_TO_SN(sc), hdr->seq_ctrl);
 				return -1;
 			}
 
 			D_TX_REPLY("AGG Frame i=%d idx %d seq=%d\n", i, idx,
-				   SEQ_TO_SN(sc));
+				   IEEE80211_SEQ_TO_SN(sc));
 
 			sh = idx - start;
 			if (sh > 64) {
@@ -2895,7 +2896,7 @@ il4965_hwrate_to_tx_control(struct il_priv *il, u32 rate_n_flags,
  * Handles block-acknowledge notification from device, which reports success
  * of frames sent via aggregation.
  */
-void
+static void
 il4965_hdl_compressed_ba(struct il_priv *il, struct il_rx_buf *rxb)
 {
 	struct il_rx_pkt *pkt = rxb_addr(rxb);
@@ -6316,7 +6317,7 @@ il4965_tx_queue_set_status(struct il_priv *il, struct il_tx_queue *txq,
 	       scd_retry ? "BA" : "AC", txq_id, tx_fifo_id);
 }
 
-const struct ieee80211_ops il4965_mac_ops = {
+static const struct ieee80211_ops il4965_mac_ops = {
 	.tx = il4965_mac_tx,
 	.start = il4965_mac_start,
 	.stop = il4965_mac_stop,
diff --git a/drivers/net/wireless/iwlegacy/4965-rs.c b/drivers/net/wireless/iwlegacy/4965-rs.c
index e8324b5..6c7493c 100644
--- a/drivers/net/wireless/iwlegacy/4965-rs.c
+++ b/drivers/net/wireless/iwlegacy/4965-rs.c
@@ -2152,7 +2152,7 @@ il4965_rs_initialize_lq(struct il_priv *il, struct ieee80211_conf *conf,
 	int rate_idx;
 	int i;
 	u32 rate;
-	u8 use_green = il4965_rs_use_green(il, sta);
+	u8 use_green;
 	u8 active_tbl = 0;
 	u8 valid_tx_ant;
 	struct il_station_priv *sta_priv;
@@ -2160,6 +2160,7 @@ il4965_rs_initialize_lq(struct il_priv *il, struct ieee80211_conf *conf,
 	if (!sta || !lq_sta)
 		return;
 
+	use_green = il4965_rs_use_green(il, sta);
 	sta_priv = (void *)sta->drv_priv;
 
 	i = lq_sta->last_txrate_idx;
diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c
index e006ea8..3613b3a 100644
--- a/drivers/net/wireless/iwlegacy/common.c
+++ b/drivers/net/wireless/iwlegacy/common.c
@@ -1122,7 +1122,7 @@ il_set_power(struct il_priv *il, struct il_powertable_cmd *cmd)
 			       sizeof(struct il_powertable_cmd), cmd);
 }
 
-int
+static int
 il_power_set_mode(struct il_priv *il, struct il_powertable_cmd *cmd, bool force)
 {
 	int ret;
@@ -2566,15 +2566,13 @@ il_rx_queue_alloc(struct il_priv *il)
 	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);
+	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 il_rb_status),
-			       &rxq->rb_stts_dma, GFP_KERNEL);
+	rxq->rb_stts = dma_alloc_coherent(dev, sizeof(struct il_rb_status),
+					  &rxq->rb_stts_dma, GFP_KERNEL);
 	if (!rxq->rb_stts)
 		goto err_rb;
 
@@ -2941,10 +2939,9 @@ il_tx_queue_alloc(struct il_priv *il, struct il_tx_queue *txq, u32 id)
 	 * shared with device */
 	txq->tfds =
 	    dma_alloc_coherent(dev, tfd_sz, &txq->q.dma_addr, GFP_KERNEL);
-	if (!txq->tfds) {
-		IL_ERR("Fail to alloc TFDs\n");
+	if (!txq->tfds)
 		goto error;
-	}
+
 	txq->q.id = id;
 
 	return 0;
@@ -4704,8 +4701,7 @@ out:
 }
 EXPORT_SYMBOL(il_mac_change_interface);
 
-void
-il_mac_flush(struct ieee80211_hw *hw, bool drop)
+void il_mac_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
 {
 	struct il_priv *il = hw->priv;
 	unsigned long timeout = jiffies + msecs_to_jiffies(500);
@@ -4891,7 +4887,7 @@ il_add_beacon_time(struct il_priv *il, u32 base, u32 addon,
 }
 EXPORT_SYMBOL(il_add_beacon_time);
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 
 static int
 il_pci_suspend(struct device *device)
@@ -4942,7 +4938,7 @@ il_pci_resume(struct device *device)
 SIMPLE_DEV_PM_OPS(il_pm_ops, il_pci_suspend, il_pci_resume);
 EXPORT_SYMBOL(il_pm_ops);
 
-#endif /* CONFIG_PM */
+#endif /* CONFIG_PM_SLEEP */
 
 static void
 il_update_qos(struct il_priv *il)
diff --git a/drivers/net/wireless/iwlegacy/common.h b/drivers/net/wireless/iwlegacy/common.h
index 96f2025..f8246f2 100644
--- a/drivers/net/wireless/iwlegacy/common.h
+++ b/drivers/net/wireless/iwlegacy/common.h
@@ -541,10 +541,6 @@ struct il_frame {
 	struct list_head list;
 };
 
-#define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4)
-#define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ)
-#define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4)
-
 enum {
 	CMD_SYNC = 0,
 	CMD_SIZE_NORMAL = 0,
@@ -1724,7 +1720,7 @@ void il_mac_remove_interface(struct ieee80211_hw *hw,
 			     struct ieee80211_vif *vif);
 int il_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 			    enum nl80211_iftype newtype, bool newp2p);
-void il_mac_flush(struct ieee80211_hw *hw, bool drop);
+void il_mac_flush(struct ieee80211_hw *hw, u32 queues, bool drop);
 int il_alloc_txq_mem(struct il_priv *il);
 void il_free_txq_mem(struct il_priv *il);
 
@@ -2235,9 +2231,8 @@ il_alloc_fw_desc(struct pci_dev *pci_dev, struct fw_desc *desc)
 		return -EINVAL;
 	}
 
-	desc->v_addr =
-	    dma_alloc_coherent(&pci_dev->dev, desc->len, &desc->p_addr,
-			       GFP_KERNEL);
+	desc->v_addr = dma_alloc_coherent(&pci_dev->dev, desc->len,
+					  &desc->p_addr, GFP_KERNEL);
 	return (desc->v_addr != NULL) ? 0 : -ENOMEM;
 }
 
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig
index ba319cb..56c2040 100644
--- a/drivers/net/wireless/iwlwifi/Kconfig
+++ b/drivers/net/wireless/iwlwifi/Kconfig
@@ -6,7 +6,6 @@ config IWLWIFI
 	select LEDS_CLASS
 	select LEDS_TRIGGERS
 	select MAC80211_LEDS
-	select IWLDVM
 	---help---
 	  Select to build the driver supporting the:
 
@@ -45,6 +44,7 @@ config IWLWIFI
 config IWLDVM
 	tristate "Intel Wireless WiFi DVM Firmware support"
 	depends on IWLWIFI
+	default IWLWIFI
 	help
 	  This is the driver supporting the DVM firmware which is
 	  currently the only firmware available for existing devices.
@@ -58,6 +58,15 @@ config IWLMVM
 
 	  Say yes if you have such a device.
 
+# don't call it _MODULE -- will confuse Kconfig/fixdep/...
+config IWLWIFI_OPMODE_MODULAR
+	bool
+	default y if IWLDVM=m
+	default y if IWLMVM=m
+
+comment "WARNING: iwlwifi is useless without IWLDVM or IWLMVM"
+	depends on IWLWIFI && IWLDVM=n && IWLMVM=n
+
 menu "Debugging Options"
 	depends on IWLWIFI
 
diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile
index 6c78000..3b5613e 100644
--- a/drivers/net/wireless/iwlwifi/Makefile
+++ b/drivers/net/wireless/iwlwifi/Makefile
@@ -7,8 +7,7 @@ iwlwifi-objs		+= iwl-notif-wait.o
 iwlwifi-objs		+= iwl-eeprom-read.o iwl-eeprom-parse.o
 iwlwifi-objs		+= iwl-phy-db.o iwl-nvm-parse.o
 iwlwifi-objs		+= pcie/drv.o pcie/rx.o pcie/tx.o pcie/trans.o
-iwlwifi-objs		+= pcie/1000.o pcie/2000.o pcie/5000.o pcie/6000.o
-iwlwifi-objs		+= pcie/7000.o
+iwlwifi-objs		+= iwl-1000.o iwl-2000.o iwl-5000.o iwl-6000.o iwl-7000.o
 
 iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o
 iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TESTMODE) += iwl-test.o
diff --git a/drivers/net/wireless/iwlwifi/dvm/agn.h b/drivers/net/wireless/iwlwifi/dvm/agn.h
index 41ec27c..019d433 100644
--- a/drivers/net/wireless/iwlwifi/dvm/agn.h
+++ b/drivers/net/wireless/iwlwifi/dvm/agn.h
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
diff --git a/drivers/net/wireless/iwlwifi/dvm/calib.c b/drivers/net/wireless/iwlwifi/dvm/calib.c
index 6468de8..d6c4cf2 100644
--- a/drivers/net/wireless/iwlwifi/dvm/calib.c
+++ b/drivers/net/wireless/iwlwifi/dvm/calib.c
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
diff --git a/drivers/net/wireless/iwlwifi/dvm/calib.h b/drivers/net/wireless/iwlwifi/dvm/calib.h
index 65e920c..cfddde1 100644
--- a/drivers/net/wireless/iwlwifi/dvm/calib.h
+++ b/drivers/net/wireless/iwlwifi/dvm/calib.h
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
diff --git a/drivers/net/wireless/iwlwifi/dvm/commands.h b/drivers/net/wireless/iwlwifi/dvm/commands.h
index 84e2c0f..95ca026 100644
--- a/drivers/net/wireless/iwlwifi/dvm/commands.h
+++ b/drivers/net/wireless/iwlwifi/dvm/commands.h
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
@@ -1526,6 +1526,7 @@ struct iwl_compressed_ba_resp {
 	__le16 scd_ssn;
 	u8 txed;	/* number of frames sent */
 	u8 txed_2_done; /* number of frames acked */
+	__le16 reserved1;
 } __packed;
 
 /*
diff --git a/drivers/net/wireless/iwlwifi/dvm/debugfs.c b/drivers/net/wireless/iwlwifi/dvm/debugfs.c
index 20806ca..7b8178b 100644
--- a/drivers/net/wireless/iwlwifi/dvm/debugfs.c
+++ b/drivers/net/wireless/iwlwifi/dvm/debugfs.c
@@ -19,7 +19,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
@@ -2324,6 +2324,28 @@ static ssize_t iwl_dbgfs_calib_disabled_write(struct file *file,
 	return count;
 }
 
+static ssize_t iwl_dbgfs_fw_restart_write(struct file *file,
+					  const char __user *user_buf,
+					  size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = file->private_data;
+	bool restart_fw = iwlwifi_mod_params.restart_fw;
+	int ret;
+
+	iwlwifi_mod_params.restart_fw = true;
+
+	mutex_lock(&priv->mutex);
+
+	/* take the return value to make compiler happy - it will fail anyway */
+	ret = iwl_dvm_send_cmd_pdu(priv, REPLY_ERROR, CMD_SYNC, 0, NULL);
+
+	mutex_unlock(&priv->mutex);
+
+	iwlwifi_mod_params.restart_fw = restart_fw;
+
+	return count;
+}
+
 DEBUGFS_READ_FILE_OPS(ucode_rx_stats);
 DEBUGFS_READ_FILE_OPS(ucode_tx_stats);
 DEBUGFS_READ_FILE_OPS(ucode_general_stats);
@@ -2343,6 +2365,7 @@ DEBUGFS_READ_FILE_OPS(bt_traffic);
 DEBUGFS_READ_WRITE_FILE_OPS(protection_mode);
 DEBUGFS_READ_FILE_OPS(reply_tx_error);
 DEBUGFS_WRITE_FILE_OPS(echo_test);
+DEBUGFS_WRITE_FILE_OPS(fw_restart);
 #ifdef CONFIG_IWLWIFI_DEBUG
 DEBUGFS_READ_WRITE_FILE_OPS(log_event);
 #endif
@@ -2400,6 +2423,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, struct dentry *dbgfs_dir)
 	DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR);
 	DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR);
 	DEBUGFS_ADD_FILE(echo_test, dir_debug, S_IWUSR);
+	DEBUGFS_ADD_FILE(fw_restart, dir_debug, S_IWUSR);
 #ifdef CONFIG_IWLWIFI_DEBUG
 	DEBUGFS_ADD_FILE(log_event, dir_debug, S_IWUSR | S_IRUSR);
 #endif
diff --git a/drivers/net/wireless/iwlwifi/dvm/lib.c b/drivers/net/wireless/iwlwifi/dvm/lib.c
index 86ea5f4..87c006c 100644
--- a/drivers/net/wireless/iwlwifi/dvm/lib.c
+++ b/drivers/net/wireless/iwlwifi/dvm/lib.c
@@ -19,7 +19,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
@@ -1262,6 +1262,15 @@ int iwl_dvm_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
 	}
 
 	/*
+	 * This can happen upon FW ASSERT: we clear the STATUS_FW_ERROR flag
+	 * in iwl_down but cancel the workers only later.
+	 */
+	if (!priv->ucode_loaded) {
+		IWL_ERR(priv, "Fw not loaded - dropping CMD: %x\n", cmd->id);
+		return -EIO;
+	}
+
+	/*
 	 * Synchronous commands from this op-mode must hold
 	 * the mutex, this ensures we don't try to send two
 	 * (or more) synchronous commands at a time.
diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
index 323e4a3..a7294fa 100644
--- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
@@ -1100,7 +1100,7 @@ static void iwlagn_configure_filter(struct ieee80211_hw *hw,
 			FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL;
 }
 
-static void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop)
+static void iwlagn_mac_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
 {
 	struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
 
@@ -1137,7 +1137,8 @@ done:
 static int iwlagn_mac_remain_on_channel(struct ieee80211_hw *hw,
 				     struct ieee80211_vif *vif,
 				     struct ieee80211_channel *channel,
-				     int duration)
+				     int duration,
+				     enum ieee80211_roc_type type)
 {
 	struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
 	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_PAN];
diff --git a/drivers/net/wireless/iwlwifi/dvm/rxon.c b/drivers/net/wireless/iwlwifi/dvm/rxon.c
index 23be948..a82b6b3 100644
--- a/drivers/net/wireless/iwlwifi/dvm/rxon.c
+++ b/drivers/net/wireless/iwlwifi/dvm/rxon.c
@@ -1419,6 +1419,14 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
 
 	mutex_lock(&priv->mutex);
 
+	if (changes & BSS_CHANGED_IDLE && bss_conf->idle) {
+		/*
+		 * If we go idle, then clearly no "passive-no-rx"
+		 * workaround is needed any more, this is a reset.
+		 */
+		iwlagn_lift_passive_no_rx(priv);
+	}
+
 	if (unlikely(!iwl_is_ready(priv))) {
 		IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
 		mutex_unlock(&priv->mutex);
@@ -1450,16 +1458,6 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
 			priv->timestamp = bss_conf->sync_tsf;
 			ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
 		} else {
-			/*
-			 * If we disassociate while there are pending
-			 * frames, just wake up the queues and let the
-			 * frames "escape" ... This shouldn't really
-			 * be happening to start with, but we should
-			 * not get stuck in this case either since it
-			 * can happen if userspace gets confused.
-			 */
-			iwlagn_lift_passive_no_rx(priv);
-
 			ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
 
 			if (ctx->ctxid == IWL_RXON_CTX_BSS)
diff --git a/drivers/net/wireless/iwlwifi/dvm/scan.c b/drivers/net/wireless/iwlwifi/dvm/scan.c
index 3a4aa52..d69b558 100644
--- a/drivers/net/wireless/iwlwifi/dvm/scan.c
+++ b/drivers/net/wireless/iwlwifi/dvm/scan.c
@@ -19,7 +19,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
diff --git a/drivers/net/wireless/iwlwifi/dvm/testmode.c b/drivers/net/wireless/iwlwifi/dvm/testmode.c
index dc6f965..b89b9d9 100644
--- a/drivers/net/wireless/iwlwifi/dvm/testmode.c
+++ b/drivers/net/wireless/iwlwifi/dvm/testmode.c
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
diff --git a/drivers/net/wireless/iwlwifi/dvm/tx.c b/drivers/net/wireless/iwlwifi/dvm/tx.c
index 6aec2df..70b7f68 100644
--- a/drivers/net/wireless/iwlwifi/dvm/tx.c
+++ b/drivers/net/wireless/iwlwifi/dvm/tx.c
@@ -19,7 +19,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
@@ -418,7 +418,8 @@ int iwlagn_tx_skb(struct iwl_priv *priv,
 				" Tx flags = 0x%08x, agg.state = %d",
 				info->flags, tid_data->agg.state);
 			IWL_ERR(priv, "sta_id = %d, tid = %d seq_num = %d",
-				sta_id, tid, SEQ_TO_SN(tid_data->seq_number));
+				sta_id, tid,
+				IEEE80211_SEQ_TO_SN(tid_data->seq_number));
 			goto drop_unlock_sta;
 		}
 
@@ -569,7 +570,7 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
 		return 0;
 	}
 
-	tid_data->agg.ssn = SEQ_TO_SN(tid_data->seq_number);
+	tid_data->agg.ssn = IEEE80211_SEQ_TO_SN(tid_data->seq_number);
 
 	/* There are still packets for this RA / TID in the HW */
 	if (!test_bit(txq_id, priv->agg_q_alloc)) {
@@ -651,7 +652,7 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
 
 	spin_lock_bh(&priv->sta_lock);
 	tid_data = &priv->tid_data[sta_id][tid];
-	tid_data->agg.ssn = SEQ_TO_SN(tid_data->seq_number);
+	tid_data->agg.ssn = IEEE80211_SEQ_TO_SN(tid_data->seq_number);
 	tid_data->agg.txq_id = txq_id;
 
 	*ssn = tid_data->agg.ssn;
@@ -911,7 +912,7 @@ static void iwlagn_count_agg_tx_err_status(struct iwl_priv *priv, u16 status)
 static inline u32 iwlagn_get_scd_ssn(struct iwlagn_tx_resp *tx_resp)
 {
 	return le32_to_cpup((__le32 *)&tx_resp->status +
-			    tx_resp->frame_count) & MAX_SN;
+			    tx_resp->frame_count) & IEEE80211_MAX_SN;
 }
 
 static void iwl_rx_reply_tx_agg(struct iwl_priv *priv,
@@ -1148,7 +1149,7 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
 
 	if (tx_resp->frame_count == 1) {
 		u16 next_reclaimed = le16_to_cpu(tx_resp->seq_ctl);
-		next_reclaimed = SEQ_TO_SN(next_reclaimed + 0x10);
+		next_reclaimed = IEEE80211_SEQ_TO_SN(next_reclaimed + 0x10);
 
 		if (is_agg) {
 			/* If this is an aggregation queue, we can rely on the
@@ -1192,7 +1193,7 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
 			memset(&info->status, 0, sizeof(info->status));
 
 			if (status == TX_STATUS_FAIL_PASSIVE_NO_RX &&
-			    iwl_is_associated_ctx(ctx) && ctx->vif &&
+			    ctx->vif &&
 			    ctx->vif->type == NL80211_IFTYPE_STATION) {
 				/* block and stop all queues */
 				priv->passive_no_rx = true;
diff --git a/drivers/net/wireless/iwlwifi/dvm/ucode.c b/drivers/net/wireless/iwlwifi/dvm/ucode.c
index 736fe9b..0a1cdc5 100644
--- a/drivers/net/wireless/iwlwifi/dvm/ucode.c
+++ b/drivers/net/wireless/iwlwifi/dvm/ucode.c
@@ -19,7 +19,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
@@ -367,6 +367,8 @@ int iwl_load_ucode_wait_alive(struct iwl_priv *priv,
 		return -EIO;
 	}
 
+	priv->ucode_loaded = true;
+
 	if (ucode_type != IWL_UCODE_WOWLAN) {
 		/* delay a bit to give rfkill time to run */
 		msleep(5);
@@ -380,8 +382,6 @@ int iwl_load_ucode_wait_alive(struct iwl_priv *priv,
 		return ret;
 	}
 
-	priv->ucode_loaded = true;
-
 	return 0;
 }
 
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c
new file mode 100644
index 0000000..c080ae3
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-1000.c
@@ -0,0 +1,140 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2008 - 2013 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.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+
+#include <linux/module.h>
+#include <linux/stringify.h>
+#include "iwl-config.h"
+#include "iwl-csr.h"
+#include "iwl-agn-hw.h"
+
+/* Highest firmware API version supported */
+#define IWL1000_UCODE_API_MAX 5
+#define IWL100_UCODE_API_MAX 5
+
+/* Oldest version we won't warn about */
+#define IWL1000_UCODE_API_OK 5
+#define IWL100_UCODE_API_OK 5
+
+/* Lowest firmware API version supported */
+#define IWL1000_UCODE_API_MIN 1
+#define IWL100_UCODE_API_MIN 5
+
+/* EEPROM version */
+#define EEPROM_1000_TX_POWER_VERSION	(4)
+#define EEPROM_1000_EEPROM_VERSION	(0x15C)
+
+#define IWL1000_FW_PRE "iwlwifi-1000-"
+#define IWL1000_MODULE_FIRMWARE(api) IWL1000_FW_PRE __stringify(api) ".ucode"
+
+#define IWL100_FW_PRE "iwlwifi-100-"
+#define IWL100_MODULE_FIRMWARE(api) IWL100_FW_PRE __stringify(api) ".ucode"
+
+
+static const struct iwl_base_params iwl1000_base_params = {
+	.num_of_queues = IWLAGN_NUM_QUEUES,
+	.eeprom_size = OTP_LOW_IMAGE_SIZE,
+	.pll_cfg_val = CSR50_ANA_PLL_CFG_VAL,
+	.max_ll_items = OTP_MAX_LL_ITEMS_1000,
+	.shadow_ram_support = false,
+	.led_compensation = 51,
+	.support_ct_kill_exit = true,
+	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF,
+	.chain_noise_scale = 1000,
+	.wd_timeout = IWL_WATCHDOG_DISABLED,
+	.max_event_log_size = 128,
+};
+
+static const struct iwl_ht_params iwl1000_ht_params = {
+	.ht_greenfield_support = true,
+	.use_rts_for_aggregation = true, /* use rts/cts protection */
+	.ht40_bands = BIT(IEEE80211_BAND_2GHZ),
+};
+
+static const struct iwl_eeprom_params iwl1000_eeprom_params = {
+	.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_REG_BAND_24_HT40_CHANNELS,
+		EEPROM_REGULATORY_BAND_NO_HT40,
+	}
+};
+
+#define IWL_DEVICE_1000						\
+	.fw_name_pre = IWL1000_FW_PRE,				\
+	.ucode_api_max = IWL1000_UCODE_API_MAX,			\
+	.ucode_api_ok = IWL1000_UCODE_API_OK,			\
+	.ucode_api_min = IWL1000_UCODE_API_MIN,			\
+	.device_family = IWL_DEVICE_FAMILY_1000,		\
+	.max_inst_size = IWLAGN_RTC_INST_SIZE,			\
+	.max_data_size = IWLAGN_RTC_DATA_SIZE,			\
+	.nvm_ver = EEPROM_1000_EEPROM_VERSION,		\
+	.nvm_calib_ver = EEPROM_1000_TX_POWER_VERSION,	\
+	.base_params = &iwl1000_base_params,			\
+	.eeprom_params = &iwl1000_eeprom_params,		\
+	.led_mode = IWL_LED_BLINK
+
+const struct iwl_cfg iwl1000_bgn_cfg = {
+	.name = "Intel(R) Centrino(R) Wireless-N 1000 BGN",
+	IWL_DEVICE_1000,
+	.ht_params = &iwl1000_ht_params,
+};
+
+const struct iwl_cfg iwl1000_bg_cfg = {
+	.name = "Intel(R) Centrino(R) Wireless-N 1000 BG",
+	IWL_DEVICE_1000,
+};
+
+#define IWL_DEVICE_100						\
+	.fw_name_pre = IWL100_FW_PRE,				\
+	.ucode_api_max = IWL100_UCODE_API_MAX,			\
+	.ucode_api_ok = IWL100_UCODE_API_OK,			\
+	.ucode_api_min = IWL100_UCODE_API_MIN,			\
+	.device_family = IWL_DEVICE_FAMILY_100,			\
+	.max_inst_size = IWLAGN_RTC_INST_SIZE,			\
+	.max_data_size = IWLAGN_RTC_DATA_SIZE,			\
+	.nvm_ver = EEPROM_1000_EEPROM_VERSION,		\
+	.nvm_calib_ver = EEPROM_1000_TX_POWER_VERSION,	\
+	.base_params = &iwl1000_base_params,			\
+	.eeprom_params = &iwl1000_eeprom_params,		\
+	.led_mode = IWL_LED_RF_STATE,				\
+	.rx_with_siso_diversity = true
+
+const struct iwl_cfg iwl100_bgn_cfg = {
+	.name = "Intel(R) Centrino(R) Wireless-N 100 BGN",
+	IWL_DEVICE_100,
+	.ht_params = &iwl1000_ht_params,
+};
+
+const struct iwl_cfg iwl100_bg_cfg = {
+	.name = "Intel(R) Centrino(R) Wireless-N 100 BG",
+	IWL_DEVICE_100,
+};
+
+MODULE_FIRMWARE(IWL1000_MODULE_FIRMWARE(IWL1000_UCODE_API_OK));
+MODULE_FIRMWARE(IWL100_MODULE_FIRMWARE(IWL100_UCODE_API_OK));
diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c
new file mode 100644
index 0000000..a6ddd2f
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-2000.c
@@ -0,0 +1,242 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2008 - 2013 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.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+
+#include <linux/module.h>
+#include <linux/stringify.h>
+#include "iwl-config.h"
+#include "iwl-agn-hw.h"
+#include "dvm/commands.h" /* needed for BT for now */
+
+/* Highest firmware API version supported */
+#define IWL2030_UCODE_API_MAX 6
+#define IWL2000_UCODE_API_MAX 6
+#define IWL105_UCODE_API_MAX 6
+#define IWL135_UCODE_API_MAX 6
+
+/* Oldest version we won't warn about */
+#define IWL2030_UCODE_API_OK 6
+#define IWL2000_UCODE_API_OK 6
+#define IWL105_UCODE_API_OK 6
+#define IWL135_UCODE_API_OK 6
+
+/* 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
+
+/* EEPROM version */
+#define EEPROM_2000_TX_POWER_VERSION	(6)
+#define EEPROM_2000_EEPROM_VERSION	(0x805)
+
+
+#define IWL2030_FW_PRE "iwlwifi-2030-"
+#define IWL2030_MODULE_FIRMWARE(api) IWL2030_FW_PRE __stringify(api) ".ucode"
+
+#define IWL2000_FW_PRE "iwlwifi-2000-"
+#define IWL2000_MODULE_FIRMWARE(api) IWL2000_FW_PRE __stringify(api) ".ucode"
+
+#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 __stringify(api) ".ucode"
+
+static const struct iwl_base_params iwl2000_base_params = {
+	.eeprom_size = OTP_LOW_IMAGE_SIZE,
+	.num_of_queues = IWLAGN_NUM_QUEUES,
+	.pll_cfg_val = 0,
+	.max_ll_items = OTP_MAX_LL_ITEMS_2x00,
+	.shadow_ram_support = true,
+	.led_compensation = 51,
+	.adv_thermal_throttle = true,
+	.support_ct_kill_exit = true,
+	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
+	.chain_noise_scale = 1000,
+	.wd_timeout = IWL_DEF_WD_TIMEOUT,
+	.max_event_log_size = 512,
+	.shadow_reg_enable = false, /* TODO: fix bugs using this feature */
+	.hd_v2 = true,
+};
+
+
+static const struct iwl_base_params iwl2030_base_params = {
+	.eeprom_size = OTP_LOW_IMAGE_SIZE,
+	.num_of_queues = IWLAGN_NUM_QUEUES,
+	.pll_cfg_val = 0,
+	.max_ll_items = OTP_MAX_LL_ITEMS_2x00,
+	.shadow_ram_support = true,
+	.led_compensation = 57,
+	.adv_thermal_throttle = true,
+	.support_ct_kill_exit = true,
+	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
+	.chain_noise_scale = 1000,
+	.wd_timeout = IWL_LONG_WD_TIMEOUT,
+	.max_event_log_size = 512,
+	.shadow_reg_enable = false, /* TODO: fix bugs using this feature */
+	.hd_v2 = true,
+};
+
+static const struct iwl_ht_params iwl2000_ht_params = {
+	.ht_greenfield_support = true,
+	.use_rts_for_aggregation = true, /* use rts/cts protection */
+	.ht40_bands = BIT(IEEE80211_BAND_2GHZ),
+};
+
+static const struct iwl_bt_params iwl2030_bt_params = {
+	/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
+	.advanced_bt_coexist = true,
+	.agg_time_limit = BT_AGG_THRESHOLD_DEF,
+	.bt_init_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_NONE,
+	.bt_prio_boost = IWLAGN_BT_PRIO_BOOST_DEFAULT32,
+	.bt_sco_disable = true,
+	.bt_session_2 = true,
+};
+
+static const struct iwl_eeprom_params iwl20x0_eeprom_params = {
+	.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,
+	},
+	.enhanced_txpower = true,
+};
+
+#define IWL_DEVICE_2000						\
+	.fw_name_pre = IWL2000_FW_PRE,				\
+	.ucode_api_max = IWL2000_UCODE_API_MAX,			\
+	.ucode_api_ok = IWL2000_UCODE_API_OK,			\
+	.ucode_api_min = IWL2000_UCODE_API_MIN,			\
+	.device_family = IWL_DEVICE_FAMILY_2000,		\
+	.max_inst_size = IWL60_RTC_INST_SIZE,			\
+	.max_data_size = IWL60_RTC_DATA_SIZE,			\
+	.nvm_ver = EEPROM_2000_EEPROM_VERSION,		\
+	.nvm_calib_ver = EEPROM_2000_TX_POWER_VERSION,	\
+	.base_params = &iwl2000_base_params,			\
+	.eeprom_params = &iwl20x0_eeprom_params,		\
+	.need_temp_offset_calib = true,				\
+	.temp_offset_v2 = true,					\
+	.led_mode = IWL_LED_RF_STATE
+
+const struct iwl_cfg iwl2000_2bgn_cfg = {
+	.name = "Intel(R) Centrino(R) Wireless-N 2200 BGN",
+	IWL_DEVICE_2000,
+	.ht_params = &iwl2000_ht_params,
+};
+
+const struct iwl_cfg iwl2000_2bgn_d_cfg = {
+	.name = "Intel(R) Centrino(R) Wireless-N 2200D BGN",
+	IWL_DEVICE_2000,
+	.ht_params = &iwl2000_ht_params,
+};
+
+#define IWL_DEVICE_2030						\
+	.fw_name_pre = IWL2030_FW_PRE,				\
+	.ucode_api_max = IWL2030_UCODE_API_MAX,			\
+	.ucode_api_ok = IWL2030_UCODE_API_OK,			\
+	.ucode_api_min = IWL2030_UCODE_API_MIN,			\
+	.device_family = IWL_DEVICE_FAMILY_2030,		\
+	.max_inst_size = IWL60_RTC_INST_SIZE,			\
+	.max_data_size = IWL60_RTC_DATA_SIZE,			\
+	.nvm_ver = EEPROM_2000_EEPROM_VERSION,		\
+	.nvm_calib_ver = EEPROM_2000_TX_POWER_VERSION,	\
+	.base_params = &iwl2030_base_params,			\
+	.bt_params = &iwl2030_bt_params,			\
+	.eeprom_params = &iwl20x0_eeprom_params,		\
+	.need_temp_offset_calib = true,				\
+	.temp_offset_v2 = true,					\
+	.led_mode = IWL_LED_RF_STATE,				\
+	.adv_pm = true
+
+const struct iwl_cfg iwl2030_2bgn_cfg = {
+	.name = "Intel(R) Centrino(R) Wireless-N 2230 BGN",
+	IWL_DEVICE_2030,
+	.ht_params = &iwl2000_ht_params,
+};
+
+#define IWL_DEVICE_105						\
+	.fw_name_pre = IWL105_FW_PRE,				\
+	.ucode_api_max = IWL105_UCODE_API_MAX,			\
+	.ucode_api_ok = IWL105_UCODE_API_OK,			\
+	.ucode_api_min = IWL105_UCODE_API_MIN,			\
+	.device_family = IWL_DEVICE_FAMILY_105,			\
+	.max_inst_size = IWL60_RTC_INST_SIZE,			\
+	.max_data_size = IWL60_RTC_DATA_SIZE,			\
+	.nvm_ver = EEPROM_2000_EEPROM_VERSION,		\
+	.nvm_calib_ver = EEPROM_2000_TX_POWER_VERSION,	\
+	.base_params = &iwl2000_base_params,			\
+	.eeprom_params = &iwl20x0_eeprom_params,		\
+	.need_temp_offset_calib = true,				\
+	.temp_offset_v2 = true,					\
+	.led_mode = IWL_LED_RF_STATE,				\
+	.adv_pm = true,						\
+	.rx_with_siso_diversity = true
+
+const struct iwl_cfg iwl105_bgn_cfg = {
+	.name = "Intel(R) Centrino(R) Wireless-N 105 BGN",
+	IWL_DEVICE_105,
+	.ht_params = &iwl2000_ht_params,
+};
+
+const struct iwl_cfg iwl105_bgn_d_cfg = {
+	.name = "Intel(R) Centrino(R) Wireless-N 105D BGN",
+	IWL_DEVICE_105,
+	.ht_params = &iwl2000_ht_params,
+};
+
+#define IWL_DEVICE_135						\
+	.fw_name_pre = IWL135_FW_PRE,				\
+	.ucode_api_max = IWL135_UCODE_API_MAX,			\
+	.ucode_api_ok = IWL135_UCODE_API_OK,			\
+	.ucode_api_min = IWL135_UCODE_API_MIN,			\
+	.device_family = IWL_DEVICE_FAMILY_135,			\
+	.max_inst_size = IWL60_RTC_INST_SIZE,			\
+	.max_data_size = IWL60_RTC_DATA_SIZE,			\
+	.nvm_ver = EEPROM_2000_EEPROM_VERSION,		\
+	.nvm_calib_ver = EEPROM_2000_TX_POWER_VERSION,	\
+	.base_params = &iwl2030_base_params,			\
+	.bt_params = &iwl2030_bt_params,			\
+	.eeprom_params = &iwl20x0_eeprom_params,		\
+	.need_temp_offset_calib = true,				\
+	.temp_offset_v2 = true,					\
+	.led_mode = IWL_LED_RF_STATE,				\
+	.adv_pm = true,						\
+	.rx_with_siso_diversity = true
+
+const struct iwl_cfg iwl135_bgn_cfg = {
+	.name = "Intel(R) Centrino(R) Wireless-N 135 BGN",
+	IWL_DEVICE_135,
+	.ht_params = &iwl2000_ht_params,
+};
+
+MODULE_FIRMWARE(IWL2000_MODULE_FIRMWARE(IWL2000_UCODE_API_OK));
+MODULE_FIRMWARE(IWL2030_MODULE_FIRMWARE(IWL2030_UCODE_API_OK));
+MODULE_FIRMWARE(IWL105_MODULE_FIRMWARE(IWL105_UCODE_API_OK));
+MODULE_FIRMWARE(IWL135_MODULE_FIRMWARE(IWL135_UCODE_API_OK));
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
new file mode 100644
index 0000000..403f3f2
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -0,0 +1,179 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2013 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.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+
+#include <linux/module.h>
+#include <linux/stringify.h>
+#include "iwl-config.h"
+#include "iwl-agn-hw.h"
+#include "iwl-csr.h"
+
+/* Highest firmware API version supported */
+#define IWL5000_UCODE_API_MAX 5
+#define IWL5150_UCODE_API_MAX 2
+
+/* Oldest version we won't warn about */
+#define IWL5000_UCODE_API_OK 5
+#define IWL5150_UCODE_API_OK 2
+
+/* Lowest firmware API version supported */
+#define IWL5000_UCODE_API_MIN 1
+#define IWL5150_UCODE_API_MIN 1
+
+/* EEPROM versions */
+#define EEPROM_5000_TX_POWER_VERSION	(4)
+#define EEPROM_5000_EEPROM_VERSION	(0x11A)
+#define EEPROM_5050_TX_POWER_VERSION	(4)
+#define EEPROM_5050_EEPROM_VERSION	(0x21E)
+
+#define IWL5000_FW_PRE "iwlwifi-5000-"
+#define IWL5000_MODULE_FIRMWARE(api) IWL5000_FW_PRE __stringify(api) ".ucode"
+
+#define IWL5150_FW_PRE "iwlwifi-5150-"
+#define IWL5150_MODULE_FIRMWARE(api) IWL5150_FW_PRE __stringify(api) ".ucode"
+
+static const struct iwl_base_params iwl5000_base_params = {
+	.eeprom_size = IWLAGN_EEPROM_IMG_SIZE,
+	.num_of_queues = IWLAGN_NUM_QUEUES,
+	.pll_cfg_val = CSR50_ANA_PLL_CFG_VAL,
+	.led_compensation = 51,
+	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
+	.chain_noise_scale = 1000,
+	.wd_timeout = IWL_WATCHDOG_DISABLED,
+	.max_event_log_size = 512,
+	.no_idle_support = true,
+};
+
+static const struct iwl_ht_params iwl5000_ht_params = {
+	.ht_greenfield_support = true,
+	.ht40_bands = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ),
+};
+
+static const struct iwl_eeprom_params iwl5000_eeprom_params = {
+	.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_REG_BAND_24_HT40_CHANNELS,
+		EEPROM_REG_BAND_52_HT40_CHANNELS
+	},
+};
+
+#define IWL_DEVICE_5000						\
+	.fw_name_pre = IWL5000_FW_PRE,				\
+	.ucode_api_max = IWL5000_UCODE_API_MAX,			\
+	.ucode_api_ok = IWL5000_UCODE_API_OK,			\
+	.ucode_api_min = IWL5000_UCODE_API_MIN,			\
+	.device_family = IWL_DEVICE_FAMILY_5000,		\
+	.max_inst_size = IWLAGN_RTC_INST_SIZE,			\
+	.max_data_size = IWLAGN_RTC_DATA_SIZE,			\
+	.nvm_ver = EEPROM_5000_EEPROM_VERSION,		\
+	.nvm_calib_ver = EEPROM_5000_TX_POWER_VERSION,	\
+	.base_params = &iwl5000_base_params,			\
+	.eeprom_params = &iwl5000_eeprom_params,		\
+	.led_mode = IWL_LED_BLINK
+
+const struct iwl_cfg iwl5300_agn_cfg = {
+	.name = "Intel(R) Ultimate N WiFi Link 5300 AGN",
+	IWL_DEVICE_5000,
+	/* at least EEPROM 0x11A has wrong info */
+	.valid_tx_ant = ANT_ABC,	/* .cfg overwrite */
+	.valid_rx_ant = ANT_ABC,	/* .cfg overwrite */
+	.ht_params = &iwl5000_ht_params,
+};
+
+const struct iwl_cfg iwl5100_bgn_cfg = {
+	.name = "Intel(R) WiFi Link 5100 BGN",
+	IWL_DEVICE_5000,
+	.valid_tx_ant = ANT_B,		/* .cfg overwrite */
+	.valid_rx_ant = ANT_AB,		/* .cfg overwrite */
+	.ht_params = &iwl5000_ht_params,
+};
+
+const struct iwl_cfg iwl5100_abg_cfg = {
+	.name = "Intel(R) WiFi Link 5100 ABG",
+	IWL_DEVICE_5000,
+	.valid_tx_ant = ANT_B,		/* .cfg overwrite */
+	.valid_rx_ant = ANT_AB,		/* .cfg overwrite */
+};
+
+const struct iwl_cfg iwl5100_agn_cfg = {
+	.name = "Intel(R) WiFi Link 5100 AGN",
+	IWL_DEVICE_5000,
+	.valid_tx_ant = ANT_B,		/* .cfg overwrite */
+	.valid_rx_ant = ANT_AB,		/* .cfg overwrite */
+	.ht_params = &iwl5000_ht_params,
+};
+
+const struct iwl_cfg iwl5350_agn_cfg = {
+	.name = "Intel(R) WiMAX/WiFi Link 5350 AGN",
+	.fw_name_pre = IWL5000_FW_PRE,
+	.ucode_api_max = IWL5000_UCODE_API_MAX,
+	.ucode_api_ok = IWL5000_UCODE_API_OK,
+	.ucode_api_min = IWL5000_UCODE_API_MIN,
+	.device_family = IWL_DEVICE_FAMILY_5000,
+	.max_inst_size = IWLAGN_RTC_INST_SIZE,
+	.max_data_size = IWLAGN_RTC_DATA_SIZE,
+	.nvm_ver = EEPROM_5050_EEPROM_VERSION,
+	.nvm_calib_ver = EEPROM_5050_TX_POWER_VERSION,
+	.base_params = &iwl5000_base_params,
+	.eeprom_params = &iwl5000_eeprom_params,
+	.ht_params = &iwl5000_ht_params,
+	.led_mode = IWL_LED_BLINK,
+	.internal_wimax_coex = true,
+};
+
+#define IWL_DEVICE_5150						\
+	.fw_name_pre = IWL5150_FW_PRE,				\
+	.ucode_api_max = IWL5150_UCODE_API_MAX,			\
+	.ucode_api_ok = IWL5150_UCODE_API_OK,			\
+	.ucode_api_min = IWL5150_UCODE_API_MIN,			\
+	.device_family = IWL_DEVICE_FAMILY_5150,		\
+	.max_inst_size = IWLAGN_RTC_INST_SIZE,			\
+	.max_data_size = IWLAGN_RTC_DATA_SIZE,			\
+	.nvm_ver = EEPROM_5050_EEPROM_VERSION,		\
+	.nvm_calib_ver = EEPROM_5050_TX_POWER_VERSION,	\
+	.base_params = &iwl5000_base_params,			\
+	.eeprom_params = &iwl5000_eeprom_params,		\
+	.no_xtal_calib = true,					\
+	.led_mode = IWL_LED_BLINK,				\
+	.internal_wimax_coex = true
+
+const struct iwl_cfg iwl5150_agn_cfg = {
+	.name = "Intel(R) WiMAX/WiFi Link 5150 AGN",
+	IWL_DEVICE_5150,
+	.ht_params = &iwl5000_ht_params,
+
+};
+
+const struct iwl_cfg iwl5150_abg_cfg = {
+	.name = "Intel(R) WiMAX/WiFi Link 5150 ABG",
+	IWL_DEVICE_5150,
+};
+
+MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_OK));
+MODULE_FIRMWARE(IWL5150_MODULE_FIRMWARE(IWL5150_UCODE_API_OK));
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c
new file mode 100644
index 0000000..b5ab8d1
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-6000.c
@@ -0,0 +1,402 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2008 - 2013 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.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+
+#include <linux/module.h>
+#include <linux/stringify.h>
+#include "iwl-config.h"
+#include "iwl-agn-hw.h"
+#include "dvm/commands.h" /* needed for BT for now */
+
+/* Highest firmware API version supported */
+#define IWL6000_UCODE_API_MAX 6
+#define IWL6050_UCODE_API_MAX 5
+#define IWL6000G2_UCODE_API_MAX 6
+#define IWL6035_UCODE_API_MAX 6
+
+/* Oldest version we won't warn about */
+#define IWL6000_UCODE_API_OK 4
+#define IWL6000G2_UCODE_API_OK 5
+#define IWL6050_UCODE_API_OK 5
+#define IWL6000G2B_UCODE_API_OK 6
+#define IWL6035_UCODE_API_OK 6
+
+/* Lowest firmware API version supported */
+#define IWL6000_UCODE_API_MIN 4
+#define IWL6050_UCODE_API_MIN 4
+#define IWL6000G2_UCODE_API_MIN 5
+#define IWL6035_UCODE_API_MIN 6
+
+/* EEPROM versions */
+#define EEPROM_6000_TX_POWER_VERSION	(4)
+#define EEPROM_6000_EEPROM_VERSION	(0x423)
+#define EEPROM_6050_TX_POWER_VERSION	(4)
+#define EEPROM_6050_EEPROM_VERSION	(0x532)
+#define EEPROM_6150_TX_POWER_VERSION	(6)
+#define EEPROM_6150_EEPROM_VERSION	(0x553)
+#define EEPROM_6005_TX_POWER_VERSION	(6)
+#define EEPROM_6005_EEPROM_VERSION	(0x709)
+#define EEPROM_6030_TX_POWER_VERSION	(6)
+#define EEPROM_6030_EEPROM_VERSION	(0x709)
+#define EEPROM_6035_TX_POWER_VERSION	(6)
+#define EEPROM_6035_EEPROM_VERSION	(0x753)
+
+#define IWL6000_FW_PRE "iwlwifi-6000-"
+#define IWL6000_MODULE_FIRMWARE(api) IWL6000_FW_PRE __stringify(api) ".ucode"
+
+#define IWL6050_FW_PRE "iwlwifi-6050-"
+#define IWL6050_MODULE_FIRMWARE(api) IWL6050_FW_PRE __stringify(api) ".ucode"
+
+#define IWL6005_FW_PRE "iwlwifi-6000g2a-"
+#define IWL6005_MODULE_FIRMWARE(api) IWL6005_FW_PRE __stringify(api) ".ucode"
+
+#define IWL6030_FW_PRE "iwlwifi-6000g2b-"
+#define IWL6030_MODULE_FIRMWARE(api) IWL6030_FW_PRE __stringify(api) ".ucode"
+
+static const struct iwl_base_params iwl6000_base_params = {
+	.eeprom_size = OTP_LOW_IMAGE_SIZE,
+	.num_of_queues = IWLAGN_NUM_QUEUES,
+	.pll_cfg_val = 0,
+	.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
+	.shadow_ram_support = true,
+	.led_compensation = 51,
+	.adv_thermal_throttle = true,
+	.support_ct_kill_exit = true,
+	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
+	.chain_noise_scale = 1000,
+	.wd_timeout = IWL_DEF_WD_TIMEOUT,
+	.max_event_log_size = 512,
+	.shadow_reg_enable = false, /* TODO: fix bugs using this feature */
+};
+
+static const struct iwl_base_params iwl6050_base_params = {
+	.eeprom_size = OTP_LOW_IMAGE_SIZE,
+	.num_of_queues = IWLAGN_NUM_QUEUES,
+	.pll_cfg_val = 0,
+	.max_ll_items = OTP_MAX_LL_ITEMS_6x50,
+	.shadow_ram_support = true,
+	.led_compensation = 51,
+	.adv_thermal_throttle = true,
+	.support_ct_kill_exit = true,
+	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
+	.chain_noise_scale = 1500,
+	.wd_timeout = IWL_DEF_WD_TIMEOUT,
+	.max_event_log_size = 1024,
+	.shadow_reg_enable = false, /* TODO: fix bugs using this feature */
+};
+
+static const struct iwl_base_params iwl6000_g2_base_params = {
+	.eeprom_size = OTP_LOW_IMAGE_SIZE,
+	.num_of_queues = IWLAGN_NUM_QUEUES,
+	.pll_cfg_val = 0,
+	.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
+	.shadow_ram_support = true,
+	.led_compensation = 57,
+	.adv_thermal_throttle = true,
+	.support_ct_kill_exit = true,
+	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
+	.chain_noise_scale = 1000,
+	.wd_timeout = IWL_LONG_WD_TIMEOUT,
+	.max_event_log_size = 512,
+	.shadow_reg_enable = false, /* TODO: fix bugs using this feature */
+};
+
+static const struct iwl_ht_params iwl6000_ht_params = {
+	.ht_greenfield_support = true,
+	.use_rts_for_aggregation = true, /* use rts/cts protection */
+	.ht40_bands = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ),
+};
+
+static const struct iwl_bt_params iwl6000_bt_params = {
+	/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
+	.advanced_bt_coexist = true,
+	.agg_time_limit = BT_AGG_THRESHOLD_DEF,
+	.bt_init_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_NONE,
+	.bt_prio_boost = IWLAGN_BT_PRIO_BOOST_DEFAULT,
+	.bt_sco_disable = true,
+};
+
+static const struct iwl_eeprom_params iwl6000_eeprom_params = {
+	.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_REG_BAND_52_HT40_CHANNELS
+	},
+	.enhanced_txpower = true,
+};
+
+#define IWL_DEVICE_6005						\
+	.fw_name_pre = IWL6005_FW_PRE,				\
+	.ucode_api_max = IWL6000G2_UCODE_API_MAX,		\
+	.ucode_api_ok = IWL6000G2_UCODE_API_OK,			\
+	.ucode_api_min = IWL6000G2_UCODE_API_MIN,		\
+	.device_family = IWL_DEVICE_FAMILY_6005,		\
+	.max_inst_size = IWL60_RTC_INST_SIZE,			\
+	.max_data_size = IWL60_RTC_DATA_SIZE,			\
+	.nvm_ver = EEPROM_6005_EEPROM_VERSION,		\
+	.nvm_calib_ver = EEPROM_6005_TX_POWER_VERSION,	\
+	.base_params = &iwl6000_g2_base_params,			\
+	.eeprom_params = &iwl6000_eeprom_params,		\
+	.need_temp_offset_calib = true,				\
+	.led_mode = IWL_LED_RF_STATE
+
+const struct iwl_cfg iwl6005_2agn_cfg = {
+	.name = "Intel(R) Centrino(R) Advanced-N 6205 AGN",
+	IWL_DEVICE_6005,
+	.ht_params = &iwl6000_ht_params,
+};
+
+const struct iwl_cfg iwl6005_2abg_cfg = {
+	.name = "Intel(R) Centrino(R) Advanced-N 6205 ABG",
+	IWL_DEVICE_6005,
+};
+
+const struct iwl_cfg iwl6005_2bg_cfg = {
+	.name = "Intel(R) Centrino(R) Advanced-N 6205 BG",
+	IWL_DEVICE_6005,
+};
+
+const struct iwl_cfg iwl6005_2agn_sff_cfg = {
+	.name = "Intel(R) Centrino(R) Advanced-N 6205S AGN",
+	IWL_DEVICE_6005,
+	.ht_params = &iwl6000_ht_params,
+};
+
+const struct iwl_cfg iwl6005_2agn_d_cfg = {
+	.name = "Intel(R) Centrino(R) Advanced-N 6205D AGN",
+	IWL_DEVICE_6005,
+	.ht_params = &iwl6000_ht_params,
+};
+
+const struct iwl_cfg iwl6005_2agn_mow1_cfg = {
+	.name = "Intel(R) Centrino(R) Advanced-N 6206 AGN",
+	IWL_DEVICE_6005,
+	.ht_params = &iwl6000_ht_params,
+};
+
+const struct iwl_cfg iwl6005_2agn_mow2_cfg = {
+	.name = "Intel(R) Centrino(R) Advanced-N 6207 AGN",
+	IWL_DEVICE_6005,
+	.ht_params = &iwl6000_ht_params,
+};
+
+#define IWL_DEVICE_6030						\
+	.fw_name_pre = IWL6030_FW_PRE,				\
+	.ucode_api_max = IWL6000G2_UCODE_API_MAX,		\
+	.ucode_api_ok = IWL6000G2B_UCODE_API_OK,		\
+	.ucode_api_min = IWL6000G2_UCODE_API_MIN,		\
+	.device_family = IWL_DEVICE_FAMILY_6030,		\
+	.max_inst_size = IWL60_RTC_INST_SIZE,			\
+	.max_data_size = IWL60_RTC_DATA_SIZE,			\
+	.nvm_ver = EEPROM_6030_EEPROM_VERSION,		\
+	.nvm_calib_ver = EEPROM_6030_TX_POWER_VERSION,	\
+	.base_params = &iwl6000_g2_base_params,			\
+	.bt_params = &iwl6000_bt_params,			\
+	.eeprom_params = &iwl6000_eeprom_params,		\
+	.need_temp_offset_calib = true,				\
+	.led_mode = IWL_LED_RF_STATE,				\
+	.adv_pm = true						\
+
+const struct iwl_cfg iwl6030_2agn_cfg = {
+	.name = "Intel(R) Centrino(R) Advanced-N 6230 AGN",
+	IWL_DEVICE_6030,
+	.ht_params = &iwl6000_ht_params,
+};
+
+const struct iwl_cfg iwl6030_2abg_cfg = {
+	.name = "Intel(R) Centrino(R) Advanced-N 6230 ABG",
+	IWL_DEVICE_6030,
+};
+
+const struct iwl_cfg iwl6030_2bgn_cfg = {
+	.name = "Intel(R) Centrino(R) Advanced-N 6230 BGN",
+	IWL_DEVICE_6030,
+	.ht_params = &iwl6000_ht_params,
+};
+
+const struct iwl_cfg iwl6030_2bg_cfg = {
+	.name = "Intel(R) Centrino(R) Advanced-N 6230 BG",
+	IWL_DEVICE_6030,
+};
+
+#define IWL_DEVICE_6035						\
+	.fw_name_pre = IWL6030_FW_PRE,				\
+	.ucode_api_max = IWL6035_UCODE_API_MAX,			\
+	.ucode_api_ok = IWL6035_UCODE_API_OK,			\
+	.ucode_api_min = IWL6035_UCODE_API_MIN,			\
+	.device_family = IWL_DEVICE_FAMILY_6030,		\
+	.max_inst_size = IWL60_RTC_INST_SIZE,			\
+	.max_data_size = IWL60_RTC_DATA_SIZE,			\
+	.nvm_ver = EEPROM_6030_EEPROM_VERSION,		\
+	.nvm_calib_ver = EEPROM_6030_TX_POWER_VERSION,	\
+	.base_params = &iwl6000_g2_base_params,			\
+	.bt_params = &iwl6000_bt_params,			\
+	.eeprom_params = &iwl6000_eeprom_params,		\
+	.need_temp_offset_calib = true,				\
+	.led_mode = IWL_LED_RF_STATE,				\
+	.adv_pm = true
+
+const struct iwl_cfg iwl6035_2agn_cfg = {
+	.name = "Intel(R) Centrino(R) Advanced-N 6235 AGN",
+	IWL_DEVICE_6035,
+	.ht_params = &iwl6000_ht_params,
+};
+
+const struct iwl_cfg iwl1030_bgn_cfg = {
+	.name = "Intel(R) Centrino(R) Wireless-N 1030 BGN",
+	IWL_DEVICE_6030,
+	.ht_params = &iwl6000_ht_params,
+};
+
+const struct iwl_cfg iwl1030_bg_cfg = {
+	.name = "Intel(R) Centrino(R) Wireless-N 1030 BG",
+	IWL_DEVICE_6030,
+};
+
+const struct iwl_cfg iwl130_bgn_cfg = {
+	.name = "Intel(R) Centrino(R) Wireless-N 130 BGN",
+	IWL_DEVICE_6030,
+	.ht_params = &iwl6000_ht_params,
+	.rx_with_siso_diversity = true,
+};
+
+const struct iwl_cfg iwl130_bg_cfg = {
+	.name = "Intel(R) Centrino(R) Wireless-N 130 BG",
+	IWL_DEVICE_6030,
+	.rx_with_siso_diversity = true,
+};
+
+/*
+ * "i": Internal configuration, use internal Power Amplifier
+ */
+#define IWL_DEVICE_6000i					\
+	.fw_name_pre = IWL6000_FW_PRE,				\
+	.ucode_api_max = IWL6000_UCODE_API_MAX,			\
+	.ucode_api_ok = IWL6000_UCODE_API_OK,			\
+	.ucode_api_min = IWL6000_UCODE_API_MIN,			\
+	.device_family = IWL_DEVICE_FAMILY_6000i,		\
+	.max_inst_size = IWL60_RTC_INST_SIZE,			\
+	.max_data_size = IWL60_RTC_DATA_SIZE,			\
+	.valid_tx_ant = ANT_BC,		/* .cfg overwrite */	\
+	.valid_rx_ant = ANT_BC,		/* .cfg overwrite */	\
+	.nvm_ver = EEPROM_6000_EEPROM_VERSION,		\
+	.nvm_calib_ver = EEPROM_6000_TX_POWER_VERSION,	\
+	.base_params = &iwl6000_base_params,			\
+	.eeprom_params = &iwl6000_eeprom_params,		\
+	.led_mode = IWL_LED_BLINK
+
+const struct iwl_cfg iwl6000i_2agn_cfg = {
+	.name = "Intel(R) Centrino(R) Advanced-N 6200 AGN",
+	IWL_DEVICE_6000i,
+	.ht_params = &iwl6000_ht_params,
+};
+
+const struct iwl_cfg iwl6000i_2abg_cfg = {
+	.name = "Intel(R) Centrino(R) Advanced-N 6200 ABG",
+	IWL_DEVICE_6000i,
+};
+
+const struct iwl_cfg iwl6000i_2bg_cfg = {
+	.name = "Intel(R) Centrino(R) Advanced-N 6200 BG",
+	IWL_DEVICE_6000i,
+};
+
+#define IWL_DEVICE_6050						\
+	.fw_name_pre = IWL6050_FW_PRE,				\
+	.ucode_api_max = IWL6050_UCODE_API_MAX,			\
+	.ucode_api_min = IWL6050_UCODE_API_MIN,			\
+	.device_family = IWL_DEVICE_FAMILY_6050,		\
+	.max_inst_size = IWL60_RTC_INST_SIZE,			\
+	.max_data_size = IWL60_RTC_DATA_SIZE,			\
+	.valid_tx_ant = ANT_AB,		/* .cfg overwrite */	\
+	.valid_rx_ant = ANT_AB,		/* .cfg overwrite */	\
+	.nvm_ver = EEPROM_6050_EEPROM_VERSION,		\
+	.nvm_calib_ver = EEPROM_6050_TX_POWER_VERSION,	\
+	.base_params = &iwl6050_base_params,			\
+	.eeprom_params = &iwl6000_eeprom_params,		\
+	.led_mode = IWL_LED_BLINK,				\
+	.internal_wimax_coex = true
+
+const struct iwl_cfg iwl6050_2agn_cfg = {
+	.name = "Intel(R) Centrino(R) Advanced-N + WiMAX 6250 AGN",
+	IWL_DEVICE_6050,
+	.ht_params = &iwl6000_ht_params,
+};
+
+const struct iwl_cfg iwl6050_2abg_cfg = {
+	.name = "Intel(R) Centrino(R) Advanced-N + WiMAX 6250 ABG",
+	IWL_DEVICE_6050,
+};
+
+#define IWL_DEVICE_6150						\
+	.fw_name_pre = IWL6050_FW_PRE,				\
+	.ucode_api_max = IWL6050_UCODE_API_MAX,			\
+	.ucode_api_min = IWL6050_UCODE_API_MIN,			\
+	.device_family = IWL_DEVICE_FAMILY_6150,		\
+	.max_inst_size = IWL60_RTC_INST_SIZE,			\
+	.max_data_size = IWL60_RTC_DATA_SIZE,			\
+	.nvm_ver = EEPROM_6150_EEPROM_VERSION,		\
+	.nvm_calib_ver = EEPROM_6150_TX_POWER_VERSION,	\
+	.base_params = &iwl6050_base_params,			\
+	.eeprom_params = &iwl6000_eeprom_params,		\
+	.led_mode = IWL_LED_BLINK,				\
+	.internal_wimax_coex = true
+
+const struct iwl_cfg iwl6150_bgn_cfg = {
+	.name = "Intel(R) Centrino(R) Wireless-N + WiMAX 6150 BGN",
+	IWL_DEVICE_6150,
+	.ht_params = &iwl6000_ht_params,
+};
+
+const struct iwl_cfg iwl6150_bg_cfg = {
+	.name = "Intel(R) Centrino(R) Wireless-N + WiMAX 6150 BG",
+	IWL_DEVICE_6150,
+};
+
+const struct iwl_cfg iwl6000_3agn_cfg = {
+	.name = "Intel(R) Centrino(R) Ultimate-N 6300 AGN",
+	.fw_name_pre = IWL6000_FW_PRE,
+	.ucode_api_max = IWL6000_UCODE_API_MAX,
+	.ucode_api_ok = IWL6000_UCODE_API_OK,
+	.ucode_api_min = IWL6000_UCODE_API_MIN,
+	.device_family = IWL_DEVICE_FAMILY_6000,
+	.max_inst_size = IWL60_RTC_INST_SIZE,
+	.max_data_size = IWL60_RTC_DATA_SIZE,
+	.nvm_ver = EEPROM_6000_EEPROM_VERSION,
+	.nvm_calib_ver = EEPROM_6000_TX_POWER_VERSION,
+	.base_params = &iwl6000_base_params,
+	.eeprom_params = &iwl6000_eeprom_params,
+	.ht_params = &iwl6000_ht_params,
+	.led_mode = IWL_LED_BLINK,
+};
+
+MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_OK));
+MODULE_FIRMWARE(IWL6050_MODULE_FIRMWARE(IWL6050_UCODE_API_OK));
+MODULE_FIRMWARE(IWL6005_MODULE_FIRMWARE(IWL6000G2_UCODE_API_OK));
+MODULE_FIRMWARE(IWL6030_MODULE_FIRMWARE(IWL6000G2B_UCODE_API_OK));
diff --git a/drivers/net/wireless/iwlwifi/iwl-7000.c b/drivers/net/wireless/iwlwifi/iwl-7000.c
new file mode 100644
index 0000000..50263e8
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-7000.c
@@ -0,0 +1,146 @@
+/******************************************************************************
+ *
+ * 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) 2012 - 2013 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 COPYING.
+ *
+ * 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) 2012 - 2013 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/module.h>
+#include <linux/stringify.h>
+#include "iwl-config.h"
+#include "iwl-agn-hw.h"
+
+/* Highest firmware API version supported */
+#define IWL7260_UCODE_API_MAX	6
+#define IWL3160_UCODE_API_MAX	6
+
+/* Oldest version we won't warn about */
+#define IWL7260_UCODE_API_OK	6
+#define IWL3160_UCODE_API_OK	6
+
+/* Lowest firmware API version supported */
+#define IWL7260_UCODE_API_MIN	6
+#define IWL3160_UCODE_API_MIN	6
+
+/* NVM versions */
+#define IWL7260_NVM_VERSION		0x0a1d
+#define IWL7260_TX_POWER_VERSION	0xffff /* meaningless */
+#define IWL3160_NVM_VERSION		0x709
+#define IWL3160_TX_POWER_VERSION	0xffff /* meaningless */
+
+#define IWL7260_FW_PRE "iwlwifi-7260-"
+#define IWL7260_MODULE_FIRMWARE(api) IWL7260_FW_PRE __stringify(api) ".ucode"
+
+#define IWL3160_FW_PRE "iwlwifi-3160-"
+#define IWL3160_MODULE_FIRMWARE(api) IWL3160_FW_PRE __stringify(api) ".ucode"
+
+static const struct iwl_base_params iwl7000_base_params = {
+	.eeprom_size = OTP_LOW_IMAGE_SIZE,
+	.num_of_queues = IWLAGN_NUM_QUEUES,
+	.pll_cfg_val = 0,
+	.shadow_ram_support = true,
+	.led_compensation = 57,
+	.adv_thermal_throttle = true,
+	.support_ct_kill_exit = true,
+	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
+	.chain_noise_scale = 1000,
+	.wd_timeout = IWL_LONG_WD_TIMEOUT,
+	.max_event_log_size = 512,
+	.shadow_reg_enable = false, /* TODO: fix bugs using this feature */
+};
+
+static const struct iwl_ht_params iwl7000_ht_params = {
+	.use_rts_for_aggregation = true, /* use rts/cts protection */
+	.ht40_bands = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ),
+};
+
+#define IWL_DEVICE_7000						\
+	.ucode_api_max = IWL7260_UCODE_API_MAX,			\
+	.ucode_api_ok = IWL7260_UCODE_API_OK,			\
+	.ucode_api_min = IWL7260_UCODE_API_MIN,			\
+	.device_family = IWL_DEVICE_FAMILY_7000,		\
+	.max_inst_size = IWL60_RTC_INST_SIZE,			\
+	.max_data_size = IWL60_RTC_DATA_SIZE,			\
+	.base_params = &iwl7000_base_params,			\
+	/* TODO: .bt_params? */					\
+	.need_temp_offset_calib = true,				\
+	.led_mode = IWL_LED_RF_STATE,				\
+	.adv_pm = true						\
+
+
+const struct iwl_cfg iwl7260_2ac_cfg = {
+	.name = "Intel(R) Dual Band Wireless AC7260",
+	.fw_name_pre = IWL7260_FW_PRE,
+	IWL_DEVICE_7000,
+	.ht_params = &iwl7000_ht_params,
+	.nvm_ver = IWL7260_NVM_VERSION,
+	.nvm_calib_ver = IWL7260_TX_POWER_VERSION,
+};
+
+const struct iwl_cfg iwl3160_ac_cfg = {
+	.name = "Intel(R) Dual Band Wireless AC3160",
+	.fw_name_pre = IWL3160_FW_PRE,
+	IWL_DEVICE_7000,
+	.ht_params = &iwl7000_ht_params,
+	.nvm_ver = IWL3160_NVM_VERSION,
+	.nvm_calib_ver = IWL3160_TX_POWER_VERSION,
+};
+
+MODULE_FIRMWARE(IWL7260_MODULE_FIRMWARE(IWL7260_UCODE_API_OK));
+MODULE_FIRMWARE(IWL3160_MODULE_FIRMWARE(IWL3160_UCODE_API_OK));
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hw.h b/drivers/net/wireless/iwlwifi/iwl-agn-hw.h
index e9975c5..6d73f94 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-hw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-hw.h
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
diff --git a/drivers/net/wireless/iwlwifi/iwl-config.h b/drivers/net/wireless/iwlwifi/iwl-config.h
index 743b483..c38aa8f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-config.h
+++ b/drivers/net/wireless/iwlwifi/iwl-config.h
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
@@ -275,4 +275,51 @@ struct iwl_cfg {
 	const bool temp_offset_v2;
 };
 
+/*
+ * This list declares the config structures for all devices.
+ */
+extern const struct iwl_cfg iwl5300_agn_cfg;
+extern const struct iwl_cfg iwl5100_agn_cfg;
+extern const struct iwl_cfg iwl5350_agn_cfg;
+extern const struct iwl_cfg iwl5100_bgn_cfg;
+extern const struct iwl_cfg iwl5100_abg_cfg;
+extern const struct iwl_cfg iwl5150_agn_cfg;
+extern const struct iwl_cfg iwl5150_abg_cfg;
+extern const struct iwl_cfg iwl6005_2agn_cfg;
+extern const struct iwl_cfg iwl6005_2abg_cfg;
+extern const struct iwl_cfg iwl6005_2bg_cfg;
+extern const struct iwl_cfg iwl6005_2agn_sff_cfg;
+extern const struct iwl_cfg iwl6005_2agn_d_cfg;
+extern const struct iwl_cfg iwl6005_2agn_mow1_cfg;
+extern const struct iwl_cfg iwl6005_2agn_mow2_cfg;
+extern const struct iwl_cfg iwl1030_bgn_cfg;
+extern const struct iwl_cfg iwl1030_bg_cfg;
+extern const struct iwl_cfg iwl6030_2agn_cfg;
+extern const struct iwl_cfg iwl6030_2abg_cfg;
+extern const struct iwl_cfg iwl6030_2bgn_cfg;
+extern const struct iwl_cfg iwl6030_2bg_cfg;
+extern const struct iwl_cfg iwl6000i_2agn_cfg;
+extern const struct iwl_cfg iwl6000i_2abg_cfg;
+extern const struct iwl_cfg iwl6000i_2bg_cfg;
+extern const struct iwl_cfg iwl6000_3agn_cfg;
+extern const struct iwl_cfg iwl6050_2agn_cfg;
+extern const struct iwl_cfg iwl6050_2abg_cfg;
+extern const struct iwl_cfg iwl6150_bgn_cfg;
+extern const struct iwl_cfg iwl6150_bg_cfg;
+extern const struct iwl_cfg iwl1000_bgn_cfg;
+extern const struct iwl_cfg iwl1000_bg_cfg;
+extern const struct iwl_cfg iwl100_bgn_cfg;
+extern const struct iwl_cfg iwl100_bg_cfg;
+extern const struct iwl_cfg iwl130_bgn_cfg;
+extern const struct iwl_cfg iwl130_bg_cfg;
+extern const struct iwl_cfg iwl2000_2bgn_cfg;
+extern const struct iwl_cfg iwl2000_2bgn_d_cfg;
+extern const struct iwl_cfg iwl2030_2bgn_cfg;
+extern const struct iwl_cfg iwl6035_2agn_cfg;
+extern const struct iwl_cfg iwl105_bgn_cfg;
+extern const struct iwl_cfg iwl105_bgn_d_cfg;
+extern const struct iwl_cfg iwl135_bgn_cfg;
+extern const struct iwl_cfg iwl7260_2ac_cfg;
+extern const struct iwl_cfg iwl3160_ac_cfg;
+
 #endif /* __IWL_CONFIG_H__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h
index df3463a..20e845d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-csr.h
+++ b/drivers/net/wireless/iwlwifi/iwl-csr.h
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.c b/drivers/net/wireless/iwlwifi/iwl-debug.c
index 87535a6..8a44f59 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debug.c
+++ b/drivers/net/wireless/iwlwifi/iwl-debug.c
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
@@ -66,6 +66,7 @@
 #include <linux/device.h>
 #include <linux/interrupt.h>
 #include <linux/export.h>
+#include "iwl-drv.h"
 #include "iwl-debug.h"
 #include "iwl-devtrace.h"
 
@@ -85,11 +86,11 @@ void __iwl_ ##fn(struct device *dev, const char *fmt, ...)	\
 }
 
 __iwl_fn(warn)
-EXPORT_SYMBOL_GPL(__iwl_warn);
+IWL_EXPORT_SYMBOL(__iwl_warn);
 __iwl_fn(info)
-EXPORT_SYMBOL_GPL(__iwl_info);
+IWL_EXPORT_SYMBOL(__iwl_info);
 __iwl_fn(crit)
-EXPORT_SYMBOL_GPL(__iwl_crit);
+IWL_EXPORT_SYMBOL(__iwl_crit);
 
 void __iwl_err(struct device *dev, bool rfkill_prefix, bool trace_only,
 		const char *fmt, ...)
@@ -110,7 +111,7 @@ void __iwl_err(struct device *dev, bool rfkill_prefix, bool trace_only,
 	trace_iwlwifi_err(&vaf);
 	va_end(args);
 }
-EXPORT_SYMBOL_GPL(__iwl_err);
+IWL_EXPORT_SYMBOL(__iwl_err);
 
 #if defined(CONFIG_IWLWIFI_DEBUG) || defined(CONFIG_IWLWIFI_DEVICE_TRACING)
 void __iwl_dbg(struct device *dev,
@@ -133,5 +134,5 @@ void __iwl_dbg(struct device *dev,
 	trace_iwlwifi_dbg(level, in_interrupt(), function, &vaf);
 	va_end(args);
 }
-EXPORT_SYMBOL_GPL(__iwl_dbg);
+IWL_EXPORT_SYMBOL(__iwl_dbg);
 #endif
diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.h b/drivers/net/wireless/iwlwifi/iwl-devtrace.h
index 81aa91f..4491c1c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-devtrace.h
+++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.h
@@ -298,7 +298,7 @@ TRACE_EVENT(iwlwifi_dbg,
 				       MAX_MSG_LEN, vaf->fmt,
 				       *vaf->va) >= MAX_MSG_LEN);
 	),
-	TP_printk("%s", (char *)__get_dynamic_array(msg))
+	TP_printk("%s", __get_str(msg))
 );
 
 #undef TRACE_SYSTEM
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c
index fbfd2d1..4983005 100644
--- a/drivers/net/wireless/iwlwifi/iwl-drv.c
+++ b/drivers/net/wireless/iwlwifi/iwl-drv.c
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
@@ -1102,7 +1102,7 @@ void iwl_drv_stop(struct iwl_drv *drv)
 
 /* shared module parameters */
 struct iwl_mod_params iwlwifi_mod_params = {
-	.restart_fw = 1,
+	.restart_fw = true,
 	.plcp_check = true,
 	.bt_coex_active = true,
 	.power_level = IWL_POWER_INDEX_1,
@@ -1111,7 +1111,7 @@ struct iwl_mod_params iwlwifi_mod_params = {
 	.wd_disable = true,
 	/* the rest are 0 by default */
 };
-EXPORT_SYMBOL_GPL(iwlwifi_mod_params);
+IWL_EXPORT_SYMBOL(iwlwifi_mod_params);
 
 int iwl_opmode_register(const char *name, const struct iwl_op_mode_ops *ops)
 {
@@ -1135,7 +1135,7 @@ int iwl_opmode_register(const char *name, const struct iwl_op_mode_ops *ops)
 	mutex_unlock(&iwlwifi_opmode_table_mtx);
 	return -EIO;
 }
-EXPORT_SYMBOL_GPL(iwl_opmode_register);
+IWL_EXPORT_SYMBOL(iwl_opmode_register);
 
 void iwl_opmode_deregister(const char *name)
 {
@@ -1157,7 +1157,7 @@ void iwl_opmode_deregister(const char *name)
 	}
 	mutex_unlock(&iwlwifi_opmode_table_mtx);
 }
-EXPORT_SYMBOL_GPL(iwl_opmode_deregister);
+IWL_EXPORT_SYMBOL(iwl_opmode_deregister);
 
 static int __init iwl_drv_init(void)
 {
@@ -1207,8 +1207,8 @@ MODULE_PARM_DESC(11n_disable,
 module_param_named(amsdu_size_8K, iwlwifi_mod_params.amsdu_size_8K,
 		   int, S_IRUGO);
 MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size (default 0)");
-module_param_named(fw_restart, iwlwifi_mod_params.restart_fw, int, S_IRUGO);
-MODULE_PARM_DESC(fw_restart, "restart firmware in case of error");
+module_param_named(fw_restart, iwlwifi_mod_params.restart_fw, bool, S_IRUGO);
+MODULE_PARM_DESC(fw_restart, "restart firmware in case of error (default true)");
 
 module_param_named(antenna_coupling, iwlwifi_mod_params.ant_coupling,
 		   int, S_IRUGO);
@@ -1266,7 +1266,3 @@ module_param_named(auto_agg, iwlwifi_mod_params.auto_agg,
 		bool, S_IRUGO);
 MODULE_PARM_DESC(auto_agg,
 		 "enable agg w/o check traffic load (default: enable)");
-
-module_param_named(5ghz_disable, iwlwifi_mod_params.disable_5ghz,
-		bool, S_IRUGO);
-MODULE_PARM_DESC(5ghz_disable, "disable 5GHz band (default: 0 [enabled])");
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.h b/drivers/net/wireless/iwlwifi/iwl-drv.h
index 594a5c7..7d14509 100644
--- a/drivers/net/wireless/iwlwifi/iwl-drv.h
+++ b/drivers/net/wireless/iwlwifi/iwl-drv.h
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
@@ -63,6 +63,8 @@
 #ifndef __iwl_drv_h__
 #define __iwl_drv_h__
 
+#include <linux/module.h>
+
 /* for all modules */
 #define DRV_NAME        "iwlwifi"
 #define IWLWIFI_VERSION "in-tree:"
@@ -123,4 +125,17 @@ struct iwl_drv *iwl_drv_start(struct iwl_trans *trans,
  */
 void iwl_drv_stop(struct iwl_drv *drv);
 
+/*
+ * exported symbol management
+ *
+ * The driver can be split into multiple modules, in which case some symbols
+ * must be exported for the sub-modules. However, if it's not split and
+ * everything is built-in, then we can avoid that.
+ */
+#ifdef CONFIG_IWLWIFI_OPMODE_MODULAR
+#define IWL_EXPORT_SYMBOL(sym)	EXPORT_SYMBOL_GPL(sym)
+#else
+#define IWL_EXPORT_SYMBOL(sym)
+#endif
+
 #endif /* __iwl_drv_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c
index 034f2ff..600c9fd 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
@@ -62,6 +62,7 @@
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/export.h>
+#include "iwl-drv.h"
 #include "iwl-modparams.h"
 #include "iwl-eeprom-parse.h"
 
@@ -749,7 +750,7 @@ void iwl_init_ht_hw_capab(const struct iwl_cfg *cfg,
 	}
 
 	ht_info->ht_supported = true;
-	ht_info->cap = 0;
+	ht_info->cap = IEEE80211_HT_CAP_DSSSCCK40;
 
 	if (iwlwifi_mod_params.amsdu_size_8K)
 		ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU;
@@ -909,7 +910,7 @@ iwl_parse_eeprom_data(struct device *dev, const struct iwl_cfg *cfg,
 	kfree(data);
 	return NULL;
 }
-EXPORT_SYMBOL_GPL(iwl_parse_eeprom_data);
+IWL_EXPORT_SYMBOL(iwl_parse_eeprom_data);
 
 /* helper functions */
 int iwl_nvm_check_version(struct iwl_nvm_data *data,
@@ -928,4 +929,4 @@ int iwl_nvm_check_version(struct iwl_nvm_data *data,
 		data->calib_version,  trans->cfg->nvm_calib_ver);
 	return -EINVAL;
 }
-EXPORT_SYMBOL_GPL(iwl_nvm_check_version);
+IWL_EXPORT_SYMBOL(iwl_nvm_check_version);
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h
index 683fe6a..37f1153 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom-read.c b/drivers/net/wireless/iwlwifi/iwl-eeprom-read.c
index ef4806f..e5f2e36 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom-read.c
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom-read.c
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
@@ -63,6 +63,7 @@
 #include <linux/slab.h>
 #include <linux/export.h>
 
+#include "iwl-drv.h"
 #include "iwl-debug.h"
 #include "iwl-eeprom-read.h"
 #include "iwl-io.h"
@@ -460,4 +461,4 @@ int iwl_read_eeprom(struct iwl_trans *trans, u8 **eeprom, size_t *eeprom_size)
 
 	return ret;
 }
-EXPORT_SYMBOL_GPL(iwl_read_eeprom);
+IWL_EXPORT_SYMBOL(iwl_read_eeprom);
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom-read.h b/drivers/net/wireless/iwlwifi/iwl-eeprom-read.h
index b2588c5..8e941f8 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom-read.h
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom-read.h
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
diff --git a/drivers/net/wireless/iwlwifi/iwl-fh.h b/drivers/net/wireless/iwlwifi/iwl-fh.h
index f5592fb..484d318 100644
--- a/drivers/net/wireless/iwlwifi/iwl-fh.h
+++ b/drivers/net/wireless/iwlwifi/iwl-fh.h
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/iwlwifi/iwl-fw-file.h
index 90873ec..8b6c6fd 100644
--- a/drivers/net/wireless/iwlwifi/iwl-fw-file.h
+++ b/drivers/net/wireless/iwlwifi/iwl-fw-file.h
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw.h b/drivers/net/wireless/iwlwifi/iwl-fw.h
index b545178..c4c446d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-fw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-fw.h
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
@@ -73,12 +73,14 @@
  *	treats good CRC threshold as a boolean
  * @IWL_UCODE_TLV_FLAGS_MFP: This uCode image supports MFP (802.11w).
  * @IWL_UCODE_TLV_FLAGS_P2P: This uCode image supports P2P.
+ * @IWL_UCODE_TLV_FLAGS_DW_BC_TABLE: The SCD byte count table is in DWORDS
  */
 enum iwl_ucode_tlv_flag {
 	IWL_UCODE_TLV_FLAGS_PAN		= BIT(0),
 	IWL_UCODE_TLV_FLAGS_NEWSCAN	= BIT(1),
 	IWL_UCODE_TLV_FLAGS_MFP		= BIT(2),
 	IWL_UCODE_TLV_FLAGS_P2P		= BIT(3),
+	IWL_UCODE_TLV_FLAGS_DW_BC_TABLE	= BIT(4),
 };
 
 /* The default calibrate table size if not specified by firmware file */
@@ -152,6 +154,19 @@ struct iwl_tlv_calib_ctrl {
 	__le32 event_trigger;
 } __packed;
 
+enum iwl_fw_phy_cfg {
+	FW_PHY_CFG_RADIO_TYPE_POS = 0,
+	FW_PHY_CFG_RADIO_TYPE = 0x3 << FW_PHY_CFG_RADIO_TYPE_POS,
+	FW_PHY_CFG_RADIO_STEP_POS = 2,
+	FW_PHY_CFG_RADIO_STEP = 0x3 << FW_PHY_CFG_RADIO_STEP_POS,
+	FW_PHY_CFG_RADIO_DASH_POS = 4,
+	FW_PHY_CFG_RADIO_DASH = 0x3 << FW_PHY_CFG_RADIO_DASH_POS,
+	FW_PHY_CFG_TX_CHAIN_POS = 16,
+	FW_PHY_CFG_TX_CHAIN = 0xf << FW_PHY_CFG_TX_CHAIN_POS,
+	FW_PHY_CFG_RX_CHAIN_POS = 20,
+	FW_PHY_CFG_RX_CHAIN = 0xf << FW_PHY_CFG_RX_CHAIN_POS,
+};
+
 /**
  * struct iwl_fw - variables associated with the firmware
  *
@@ -188,4 +203,16 @@ struct iwl_fw {
 	bool mvm_fw;
 };
 
+static inline u8 iwl_fw_valid_tx_ant(const struct iwl_fw *fw)
+{
+	return (fw->phy_config & FW_PHY_CFG_TX_CHAIN) >>
+		FW_PHY_CFG_TX_CHAIN_POS;
+}
+
+static inline u8 iwl_fw_valid_rx_ant(const struct iwl_fw *fw)
+{
+	return (fw->phy_config & FW_PHY_CFG_RX_CHAIN) >>
+		FW_PHY_CFG_RX_CHAIN_POS;
+}
+
 #endif  /* __iwl_fw_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.c b/drivers/net/wireless/iwlwifi/iwl-io.c
index 276410d..305c81f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-io.c
+++ b/drivers/net/wireless/iwlwifi/iwl-io.c
@@ -29,6 +29,7 @@
 #include <linux/device.h>
 #include <linux/export.h>
 
+#include "iwl-drv.h"
 #include "iwl-io.h"
 #include "iwl-csr.h"
 #include "iwl-debug.h"
@@ -49,7 +50,7 @@ int iwl_poll_bit(struct iwl_trans *trans, u32 addr,
 
 	return -ETIMEDOUT;
 }
-EXPORT_SYMBOL_GPL(iwl_poll_bit);
+IWL_EXPORT_SYMBOL(iwl_poll_bit);
 
 u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg)
 {
@@ -62,7 +63,7 @@ u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg)
 
 	return value;
 }
-EXPORT_SYMBOL_GPL(iwl_read_direct32);
+IWL_EXPORT_SYMBOL(iwl_read_direct32);
 
 void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value)
 {
@@ -73,7 +74,7 @@ void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value)
 		iwl_trans_release_nic_access(trans, &flags);
 	}
 }
-EXPORT_SYMBOL_GPL(iwl_write_direct32);
+IWL_EXPORT_SYMBOL(iwl_write_direct32);
 
 int iwl_poll_direct_bit(struct iwl_trans *trans, u32 addr, u32 mask,
 			int timeout)
@@ -89,7 +90,7 @@ int iwl_poll_direct_bit(struct iwl_trans *trans, u32 addr, u32 mask,
 
 	return -ETIMEDOUT;
 }
-EXPORT_SYMBOL_GPL(iwl_poll_direct_bit);
+IWL_EXPORT_SYMBOL(iwl_poll_direct_bit);
 
 static inline u32 __iwl_read_prph(struct iwl_trans *trans, u32 ofs)
 {
@@ -115,7 +116,7 @@ u32 iwl_read_prph(struct iwl_trans *trans, u32 ofs)
 	}
 	return val;
 }
-EXPORT_SYMBOL_GPL(iwl_read_prph);
+IWL_EXPORT_SYMBOL(iwl_read_prph);
 
 void iwl_write_prph(struct iwl_trans *trans, u32 ofs, u32 val)
 {
@@ -126,7 +127,7 @@ void iwl_write_prph(struct iwl_trans *trans, u32 ofs, u32 val)
 		iwl_trans_release_nic_access(trans, &flags);
 	}
 }
-EXPORT_SYMBOL_GPL(iwl_write_prph);
+IWL_EXPORT_SYMBOL(iwl_write_prph);
 
 void iwl_set_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask)
 {
@@ -138,7 +139,7 @@ void iwl_set_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask)
 		iwl_trans_release_nic_access(trans, &flags);
 	}
 }
-EXPORT_SYMBOL_GPL(iwl_set_bits_prph);
+IWL_EXPORT_SYMBOL(iwl_set_bits_prph);
 
 void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs,
 			    u32 bits, u32 mask)
@@ -151,7 +152,7 @@ void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs,
 		iwl_trans_release_nic_access(trans, &flags);
 	}
 }
-EXPORT_SYMBOL_GPL(iwl_set_bits_mask_prph);
+IWL_EXPORT_SYMBOL(iwl_set_bits_mask_prph);
 
 void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask)
 {
@@ -164,4 +165,4 @@ void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask)
 		iwl_trans_release_nic_access(trans, &flags);
 	}
 }
-EXPORT_SYMBOL_GPL(iwl_clear_bits_prph);
+IWL_EXPORT_SYMBOL(iwl_clear_bits_prph);
diff --git a/drivers/net/wireless/iwlwifi/iwl-modparams.h b/drivers/net/wireless/iwlwifi/iwl-modparams.h
index 2c2a729..d6f6c37 100644
--- a/drivers/net/wireless/iwlwifi/iwl-modparams.h
+++ b/drivers/net/wireless/iwlwifi/iwl-modparams.h
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
@@ -103,13 +103,12 @@ enum iwl_power_level {
  * @ant_coupling: antenna coupling in dB, default = 0
  * @bt_ch_announce: BT channel inhibition, default = enable
  * @auto_agg: enable agg. without check, default = true
- * @disable_5ghz: disable 5GHz capability, default = false
  */
 struct iwl_mod_params {
 	int sw_crypto;
 	unsigned int disable_11n;
 	int amsdu_size_8K;
-	int restart_fw;
+	bool restart_fw;
 	bool plcp_check;
 	int  wd_disable;
 	bool bt_coex_active;
@@ -120,7 +119,6 @@ struct iwl_mod_params {
 	int ant_coupling;
 	bool bt_ch_announce;
 	bool auto_agg;
-	bool disable_5ghz;
 };
 
 #endif /* #__iwl_modparams_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-notif-wait.c b/drivers/net/wireless/iwlwifi/iwl-notif-wait.c
index c3affbc..940b8a9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-notif-wait.c
+++ b/drivers/net/wireless/iwlwifi/iwl-notif-wait.c
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
@@ -63,6 +63,7 @@
 #include <linux/sched.h>
 #include <linux/export.h>
 
+#include "iwl-drv.h"
 #include "iwl-notif-wait.h"
 
 
@@ -72,7 +73,7 @@ void iwl_notification_wait_init(struct iwl_notif_wait_data *notif_wait)
 	INIT_LIST_HEAD(&notif_wait->notif_waits);
 	init_waitqueue_head(&notif_wait->notif_waitq);
 }
-EXPORT_SYMBOL_GPL(iwl_notification_wait_init);
+IWL_EXPORT_SYMBOL(iwl_notification_wait_init);
 
 void iwl_notification_wait_notify(struct iwl_notif_wait_data *notif_wait,
 				  struct iwl_rx_packet *pkt)
@@ -117,7 +118,7 @@ void iwl_notification_wait_notify(struct iwl_notif_wait_data *notif_wait,
 	if (triggered)
 		wake_up_all(&notif_wait->notif_waitq);
 }
-EXPORT_SYMBOL_GPL(iwl_notification_wait_notify);
+IWL_EXPORT_SYMBOL(iwl_notification_wait_notify);
 
 void iwl_abort_notification_waits(struct iwl_notif_wait_data *notif_wait)
 {
@@ -130,7 +131,7 @@ void iwl_abort_notification_waits(struct iwl_notif_wait_data *notif_wait)
 
 	wake_up_all(&notif_wait->notif_waitq);
 }
-EXPORT_SYMBOL_GPL(iwl_abort_notification_waits);
+IWL_EXPORT_SYMBOL(iwl_abort_notification_waits);
 
 void
 iwl_init_notification_wait(struct iwl_notif_wait_data *notif_wait,
@@ -154,7 +155,7 @@ iwl_init_notification_wait(struct iwl_notif_wait_data *notif_wait,
 	list_add(&wait_entry->list, &notif_wait->notif_waits);
 	spin_unlock_bh(&notif_wait->notif_wait_lock);
 }
-EXPORT_SYMBOL_GPL(iwl_init_notification_wait);
+IWL_EXPORT_SYMBOL(iwl_init_notification_wait);
 
 int iwl_wait_notification(struct iwl_notif_wait_data *notif_wait,
 			  struct iwl_notification_wait *wait_entry,
@@ -178,7 +179,7 @@ int iwl_wait_notification(struct iwl_notif_wait_data *notif_wait,
 		return -ETIMEDOUT;
 	return 0;
 }
-EXPORT_SYMBOL_GPL(iwl_wait_notification);
+IWL_EXPORT_SYMBOL(iwl_wait_notification);
 
 void iwl_remove_notification(struct iwl_notif_wait_data *notif_wait,
 			     struct iwl_notification_wait *wait_entry)
@@ -187,4 +188,4 @@ void iwl_remove_notification(struct iwl_notif_wait_data *notif_wait,
 	list_del(&wait_entry->list);
 	spin_unlock_bh(&notif_wait->notif_wait_lock);
 }
-EXPORT_SYMBOL_GPL(iwl_remove_notification);
+IWL_EXPORT_SYMBOL(iwl_remove_notification);
diff --git a/drivers/net/wireless/iwlwifi/iwl-notif-wait.h b/drivers/net/wireless/iwlwifi/iwl-notif-wait.h
index c2ce764..2e2f1c8 100644
--- a/drivers/net/wireless/iwlwifi/iwl-notif-wait.h
+++ b/drivers/net/wireless/iwlwifi/iwl-notif-wait.h
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
diff --git a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c
index a70213b..6199a0a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c
+++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
@@ -62,6 +62,7 @@
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/export.h>
+#include "iwl-drv.h"
 #include "iwl-modparams.h"
 #include "iwl-nvm-parse.h"
 
@@ -149,6 +150,8 @@ static struct ieee80211_rate iwl_cfg80211_rates[] = {
  * @NVM_CHANNEL_DFS: dynamic freq selection candidate
  * @NVM_CHANNEL_WIDE: 20 MHz channel okay (?)
  * @NVM_CHANNEL_40MHZ: 40 MHz channel okay (?)
+ * @NVM_CHANNEL_80MHZ: 80 MHz channel okay (?)
+ * @NVM_CHANNEL_160MHZ: 160 MHz channel okay (?)
  */
 enum iwl_nvm_channel_flags {
 	NVM_CHANNEL_VALID = BIT(0),
@@ -158,6 +161,8 @@ enum iwl_nvm_channel_flags {
 	NVM_CHANNEL_DFS = BIT(7),
 	NVM_CHANNEL_WIDE = BIT(8),
 	NVM_CHANNEL_40MHZ = BIT(9),
+	NVM_CHANNEL_80MHZ = BIT(10),
+	NVM_CHANNEL_160MHZ = BIT(11),
 };
 
 #define CHECK_AND_PRINT_I(x)	\
@@ -210,6 +215,10 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
 			else
 				channel->flags &= ~IEEE80211_CHAN_NO_HT40MINUS;
 		}
+		if (!(ch_flags & NVM_CHANNEL_80MHZ))
+			channel->flags |= IEEE80211_CHAN_NO_80MHZ;
+		if (!(ch_flags & NVM_CHANNEL_160MHZ))
+			channel->flags |= IEEE80211_CHAN_NO_160MHZ;
 
 		if (!(ch_flags & NVM_CHANNEL_IBSS))
 			channel->flags |= IEEE80211_CHAN_NO_IBSS;
@@ -245,6 +254,43 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
 	return n_channels;
 }
 
+static void iwl_init_vht_hw_capab(const struct iwl_cfg *cfg,
+				  struct iwl_nvm_data *data,
+				  struct ieee80211_sta_vht_cap *vht_cap)
+{
+	/* For now, assume new devices with NVM are VHT capable */
+
+	vht_cap->vht_supported = true;
+
+	vht_cap->cap = IEEE80211_VHT_CAP_SHORT_GI_80 |
+		       IEEE80211_VHT_CAP_RXSTBC_1 |
+		       IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
+		       7 << IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT;
+
+	if (iwlwifi_mod_params.amsdu_size_8K)
+		vht_cap->cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991;
+
+	vht_cap->vht_mcs.rx_mcs_map =
+		cpu_to_le16(IEEE80211_VHT_MCS_SUPPORT_0_9 << 0 |
+			    IEEE80211_VHT_MCS_SUPPORT_0_9 << 2 |
+			    IEEE80211_VHT_MCS_NOT_SUPPORTED << 4 |
+			    IEEE80211_VHT_MCS_NOT_SUPPORTED << 6 |
+			    IEEE80211_VHT_MCS_NOT_SUPPORTED << 8 |
+			    IEEE80211_VHT_MCS_NOT_SUPPORTED << 10 |
+			    IEEE80211_VHT_MCS_NOT_SUPPORTED << 12 |
+			    IEEE80211_VHT_MCS_NOT_SUPPORTED << 14);
+
+	if (data->valid_rx_ant == 1 || cfg->rx_with_siso_diversity) {
+		vht_cap->cap |= IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN |
+				IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN;
+		/* this works because NOT_SUPPORTED == 3 */
+		vht_cap->vht_mcs.rx_mcs_map |=
+			cpu_to_le16(IEEE80211_VHT_MCS_NOT_SUPPORTED << 2);
+	}
+
+	vht_cap->vht_mcs.tx_mcs_map = vht_cap->vht_mcs.rx_mcs_map;
+}
+
 static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg,
 			    struct iwl_nvm_data *data, const __le16 *nvm_sw)
 {
@@ -268,6 +314,7 @@ static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg,
 	n_used += iwl_init_sband_channels(data, sband, n_channels,
 					  IEEE80211_BAND_5GHZ);
 	iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_5GHZ);
+	iwl_init_vht_hw_capab(cfg, data, &sband->vht_cap);
 
 	if (n_channels != n_used)
 		IWL_ERR_DEV(dev, "NVM: used only %d of %d channels\n",
@@ -343,4 +390,4 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg,
 
 	return data;
 }
-EXPORT_SYMBOL_GPL(iwl_parse_nvm_data);
+IWL_EXPORT_SYMBOL(iwl_parse_nvm_data);
diff --git a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.h b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.h
index b2692bd..e57fb98 100644
--- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.h
+++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.h
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
diff --git a/drivers/net/wireless/iwlwifi/iwl-op-mode.h b/drivers/net/wireless/iwlwifi/iwl-op-mode.h
index 4a68001..98c7aa7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-op-mode.h
+++ b/drivers/net/wireless/iwlwifi/iwl-op-mode.h
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
diff --git a/drivers/net/wireless/iwlwifi/iwl-phy-db.c b/drivers/net/wireless/iwlwifi/iwl-phy-db.c
index 3392011..25745da 100644
--- a/drivers/net/wireless/iwlwifi/iwl-phy-db.c
+++ b/drivers/net/wireless/iwlwifi/iwl-phy-db.c
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
@@ -65,6 +65,7 @@
 #include <linux/string.h>
 #include <linux/export.h>
 
+#include "iwl-drv.h"
 #include "iwl-phy-db.h"
 #include "iwl-debug.h"
 #include "iwl-op-mode.h"
@@ -149,7 +150,7 @@ struct iwl_phy_db *iwl_phy_db_init(struct iwl_trans *trans)
 	/* TODO: add default values of the phy db. */
 	return phy_db;
 }
-EXPORT_SYMBOL(iwl_phy_db_init);
+IWL_EXPORT_SYMBOL(iwl_phy_db_init);
 
 /*
  * get phy db section: returns a pointer to a phy db section specified by
@@ -215,7 +216,7 @@ void iwl_phy_db_free(struct iwl_phy_db *phy_db)
 
 	kfree(phy_db);
 }
-EXPORT_SYMBOL(iwl_phy_db_free);
+IWL_EXPORT_SYMBOL(iwl_phy_db_free);
 
 int iwl_phy_db_set_section(struct iwl_phy_db *phy_db, struct iwl_rx_packet *pkt,
 			   gfp_t alloc_ctx)
@@ -260,7 +261,7 @@ int iwl_phy_db_set_section(struct iwl_phy_db *phy_db, struct iwl_rx_packet *pkt,
 
 	return 0;
 }
-EXPORT_SYMBOL(iwl_phy_db_set_section);
+IWL_EXPORT_SYMBOL(iwl_phy_db_set_section);
 
 static int is_valid_channel(u16 ch_id)
 {
@@ -495,4 +496,4 @@ int iwl_send_phy_db_data(struct iwl_phy_db *phy_db)
 		       "Finished sending phy db non channel data\n");
 	return 0;
 }
-EXPORT_SYMBOL(iwl_send_phy_db_data);
+IWL_EXPORT_SYMBOL(iwl_send_phy_db_data);
diff --git a/drivers/net/wireless/iwlwifi/iwl-phy-db.h b/drivers/net/wireless/iwlwifi/iwl-phy-db.h
index d0e43d9..ce983af 100644
--- a/drivers/net/wireless/iwlwifi/iwl-phy-db.h
+++ b/drivers/net/wireless/iwlwifi/iwl-phy-db.h
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h
index f76e9ca..386f2a7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-prph.h
+++ b/drivers/net/wireless/iwlwifi/iwl-prph.h
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
diff --git a/drivers/net/wireless/iwlwifi/iwl-test.c b/drivers/net/wireless/iwlwifi/iwl-test.c
index ce0c67b..5cfd55b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-test.c
+++ b/drivers/net/wireless/iwlwifi/iwl-test.c
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
@@ -64,6 +64,7 @@
 #include <linux/export.h>
 #include <net/netlink.h>
 
+#include "iwl-drv.h"
 #include "iwl-io.h"
 #include "iwl-fh.h"
 #include "iwl-prph.h"
@@ -271,7 +272,7 @@ static int iwl_test_fw_cmd(struct iwl_test *tst, struct nlattr **tb)
 
 	reply_len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
 	skb = iwl_test_alloc_reply(tst, reply_len + 20);
-	reply_buf = kmalloc(reply_len, GFP_KERNEL);
+	reply_buf = kmemdup(&pkt->hdr, reply_len, GFP_KERNEL);
 	if (!skb || !reply_buf) {
 		kfree_skb(skb);
 		kfree(reply_buf);
@@ -279,7 +280,6 @@ static int iwl_test_fw_cmd(struct iwl_test *tst, struct nlattr **tb)
 	}
 
 	/* The reply is in a page, that we cannot send to user space. */
-	memcpy(reply_buf, &(pkt->hdr), reply_len);
 	iwl_free_resp(&cmd);
 
 	if (nla_put_u32(skb, IWL_TM_ATTR_COMMAND,
@@ -653,7 +653,7 @@ int iwl_test_parse(struct iwl_test *tst, struct nlattr **tb,
 	}
 	return 0;
 }
-EXPORT_SYMBOL_GPL(iwl_test_parse);
+IWL_EXPORT_SYMBOL(iwl_test_parse);
 
 /*
  * Handle test commands.
@@ -715,7 +715,7 @@ int iwl_test_handle_cmd(struct iwl_test *tst, struct nlattr **tb)
 	}
 	return result;
 }
-EXPORT_SYMBOL_GPL(iwl_test_handle_cmd);
+IWL_EXPORT_SYMBOL(iwl_test_handle_cmd);
 
 static int iwl_test_trace_dump(struct iwl_test *tst, struct sk_buff *skb,
 			       struct netlink_callback *cb)
@@ -803,7 +803,7 @@ int iwl_test_dump(struct iwl_test *tst, u32 cmd, struct sk_buff *skb,
 	}
 	return result;
 }
-EXPORT_SYMBOL_GPL(iwl_test_dump);
+IWL_EXPORT_SYMBOL(iwl_test_dump);
 
 /*
  * Multicast a spontaneous messages from the device to the user space.
@@ -849,4 +849,4 @@ void iwl_test_rx(struct iwl_test *tst, struct iwl_rx_cmd_buffer *rxb)
 	if (tst->notify)
 		iwl_test_send_rx(tst, rxb);
 }
-EXPORT_SYMBOL_GPL(iwl_test_rx);
+IWL_EXPORT_SYMBOL(iwl_test_rx);
diff --git a/drivers/net/wireless/iwlwifi/iwl-test.h b/drivers/net/wireless/iwlwifi/iwl-test.h
index 7fbf4d7..8fbd217 100644
--- a/drivers/net/wireless/iwlwifi/iwl-test.h
+++ b/drivers/net/wireless/iwlwifi/iwl-test.h
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.h b/drivers/net/wireless/iwlwifi/iwl-testmode.h
index a963f45..98f48a9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-testmode.h
+++ b/drivers/net/wireless/iwlwifi/iwl-testmode.h
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h
index 0cac2b7..7f9c254 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/iwlwifi/iwl-trans.h
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
@@ -114,9 +114,6 @@
  * completely agnostic to these differences.
  * The transport does provide helper functionnality (i.e. SYNC / ASYNC mode),
  */
-#define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4)
-#define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ)
-#define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4)
 #define SEQ_TO_QUEUE(s)	(((s) >> 8) & 0x1f)
 #define QUEUE_TO_SEQ(q)	(((q) & 0x1f) << 8)
 #define SEQ_TO_INDEX(s)	((s) & 0xff)
diff --git a/drivers/net/wireless/iwlwifi/mvm/Makefile b/drivers/net/wireless/iwlwifi/mvm/Makefile
index 807b250..2acc44b 100644
--- a/drivers/net/wireless/iwlwifi/mvm/Makefile
+++ b/drivers/net/wireless/iwlwifi/mvm/Makefile
@@ -2,7 +2,7 @@ obj-$(CONFIG_IWLMVM)   += iwlmvm.o
 iwlmvm-y += fw.o mac80211.o nvm.o ops.o phy-ctxt.o mac-ctxt.o
 iwlmvm-y += utils.o rx.o tx.o binding.o quota.o sta.o
 iwlmvm-y += scan.o time-event.o rs.o
-iwlmvm-y += power.o
+iwlmvm-y += power.o bt-coex.o
 iwlmvm-y += led.o
 iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o
 iwlmvm-$(CONFIG_PM_SLEEP) += d3.o
diff --git a/drivers/net/wireless/iwlwifi/mvm/binding.c b/drivers/net/wireless/iwlwifi/mvm/binding.c
index 73d24aa..93fd145 100644
--- a/drivers/net/wireless/iwlwifi/mvm/binding.c
+++ b/drivers/net/wireless/iwlwifi/mvm/binding.c
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
diff --git a/drivers/net/wireless/iwlwifi/mvm/bt-coex.c b/drivers/net/wireless/iwlwifi/mvm/bt-coex.c
new file mode 100644
index 0000000..1700232
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/mvm/bt-coex.c
@@ -0,0 +1,348 @@
+/******************************************************************************
+ *
+ * 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) 2013 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 COPYING.
+ *
+ * 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) 2013 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 "fw-api-bt-coex.h"
+#include "iwl-modparams.h"
+#include "mvm.h"
+#include "iwl-debug.h"
+
+#define EVENT_PRIO_ANT(_evt, _prio, _shrd_ant)			\
+	[(_evt)] = (((_prio) << BT_COEX_PRIO_TBL_PRIO_POS) |	\
+		   ((_shrd_ant) << BT_COEX_PRIO_TBL_SHRD_ANT_POS))
+
+static const u8 iwl_bt_prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX] = {
+	EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_INIT_CALIB1,
+		       BT_COEX_PRIO_TBL_PRIO_BYPASS, 0),
+	EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_INIT_CALIB2,
+		       BT_COEX_PRIO_TBL_PRIO_BYPASS, 1),
+	EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_LOW1,
+		       BT_COEX_PRIO_TBL_PRIO_LOW, 0),
+	EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_LOW2,
+		       BT_COEX_PRIO_TBL_PRIO_LOW, 1),
+	EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_HIGH1,
+		       BT_COEX_PRIO_TBL_PRIO_HIGH, 0),
+	EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_HIGH2,
+		       BT_COEX_PRIO_TBL_PRIO_HIGH, 1),
+	EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_DTIM,
+		       BT_COEX_PRIO_TBL_DISABLED, 0),
+	EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_SCAN52,
+		       BT_COEX_PRIO_TBL_PRIO_COEX_OFF, 0),
+	EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_SCAN24,
+		       BT_COEX_PRIO_TBL_PRIO_COEX_ON, 0),
+	EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_IDLE,
+		       BT_COEX_PRIO_TBL_PRIO_COEX_IDLE, 0),
+	0, 0, 0, 0, 0, 0,
+};
+
+#undef EVENT_PRIO_ANT
+
+int iwl_send_bt_prio_tbl(struct iwl_mvm *mvm)
+{
+	return iwl_mvm_send_cmd_pdu(mvm, BT_COEX_PRIO_TABLE, CMD_SYNC,
+				    sizeof(struct iwl_bt_coex_prio_tbl_cmd),
+				    &iwl_bt_prio_tbl);
+}
+
+static int iwl_send_bt_env(struct iwl_mvm *mvm, u8 action, u8 type)
+{
+	struct iwl_bt_coex_prot_env_cmd env_cmd;
+	int ret;
+
+	env_cmd.action = action;
+	env_cmd.type = type;
+	ret = iwl_mvm_send_cmd_pdu(mvm, BT_COEX_PROT_ENV, CMD_SYNC,
+				   sizeof(env_cmd), &env_cmd);
+	if (ret)
+		IWL_ERR(mvm, "failed to send BT env command\n");
+	return ret;
+}
+
+enum iwl_bt_kill_msk {
+	BT_KILL_MSK_DEFAULT,
+	BT_KILL_MSK_SCO_HID_A2DP,
+	BT_KILL_MSK_REDUCED_TXPOW,
+	BT_KILL_MSK_MAX,
+};
+
+static const u32 iwl_bt_ack_kill_msk[BT_KILL_MSK_MAX] = {
+	[BT_KILL_MSK_DEFAULT] = 0xffff0000,
+	[BT_KILL_MSK_SCO_HID_A2DP] = 0xffffffff,
+	[BT_KILL_MSK_REDUCED_TXPOW] = 0,
+};
+
+static const u32 iwl_bt_cts_kill_msk[BT_KILL_MSK_MAX] = {
+	[BT_KILL_MSK_DEFAULT] = 0xffff0000,
+	[BT_KILL_MSK_SCO_HID_A2DP] = 0xffffffff,
+	[BT_KILL_MSK_REDUCED_TXPOW] = 0,
+};
+
+#define IWL_BT_DEFAULT_BOOST (0xf0f0f0f0)
+
+/* Tight Coex */
+static const __le32 iwl_tight_lookup[BT_COEX_LUT_SIZE] = {
+	cpu_to_le32(0xaaaaaaaa),
+	cpu_to_le32(0xaaaaaaaa),
+	cpu_to_le32(0xaeaaaaaa),
+	cpu_to_le32(0xaaaaaaaa),
+	cpu_to_le32(0xcc00ff28),
+	cpu_to_le32(0x0000aaaa),
+	cpu_to_le32(0xcc00aaaa),
+	cpu_to_le32(0x0000aaaa),
+	cpu_to_le32(0xc0004000),
+	cpu_to_le32(0x00000000),
+	cpu_to_le32(0xf0005000),
+	cpu_to_le32(0xf0005000),
+};
+
+/* Loose Coex */
+static const __le32 iwl_loose_lookup[BT_COEX_LUT_SIZE] = {
+	cpu_to_le32(0xaaaaaaaa),
+	cpu_to_le32(0xaaaaaaaa),
+	cpu_to_le32(0xaeaaaaaa),
+	cpu_to_le32(0xaaaaaaaa),
+	cpu_to_le32(0xcc00ff28),
+	cpu_to_le32(0x0000aaaa),
+	cpu_to_le32(0xcc00aaaa),
+	cpu_to_le32(0x0000aaaa),
+	cpu_to_le32(0x00000000),
+	cpu_to_le32(0x00000000),
+	cpu_to_le32(0xf0005000),
+	cpu_to_le32(0xf0005000),
+};
+
+/* Full concurrency */
+static const __le32 iwl_concurrent_lookup[BT_COEX_LUT_SIZE] = {
+	cpu_to_le32(0xaaaaaaaa),
+	cpu_to_le32(0xaaaaaaaa),
+	cpu_to_le32(0xaaaaaaaa),
+	cpu_to_le32(0xaaaaaaaa),
+	cpu_to_le32(0xaaaaaaaa),
+	cpu_to_le32(0xaaaaaaaa),
+	cpu_to_le32(0xaaaaaaaa),
+	cpu_to_le32(0xaaaaaaaa),
+	cpu_to_le32(0x00000000),
+	cpu_to_le32(0x00000000),
+	cpu_to_le32(0x00000000),
+	cpu_to_le32(0x00000000),
+};
+
+/* BT Antenna Coupling Threshold (dB) */
+#define IWL_BT_ANTENNA_COUPLING_THRESHOLD	(35)
+#define IWL_BT_LOAD_FORCE_SISO_THRESHOLD	(3)
+
+
+int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
+{
+	struct iwl_bt_coex_cmd cmd = {
+		.max_kill = 5,
+		.bt3_time_t7_value = 1,
+		.bt3_prio_sample_time = 2,
+		.bt3_timer_t2_value = 0xc,
+	};
+	int ret;
+
+	cmd.flags = iwlwifi_mod_params.bt_coex_active ?
+			BT_COEX_NW : BT_COEX_DISABLE;
+	cmd.flags |= iwlwifi_mod_params.bt_ch_announce ? BT_CH_PRIMARY_EN : 0;
+	cmd.flags |= BT_SYNC_2_BT_DISABLE;
+
+	cmd.valid_bit_msk = cpu_to_le16(BT_VALID_ENABLE |
+					BT_VALID_BT_PRIO_BOOST |
+					BT_VALID_MAX_KILL |
+					BT_VALID_3W_TMRS |
+					BT_VALID_KILL_ACK |
+					BT_VALID_KILL_CTS |
+					BT_VALID_REDUCED_TX_POWER |
+					BT_VALID_LUT);
+
+	if (iwlwifi_mod_params.ant_coupling > IWL_BT_ANTENNA_COUPLING_THRESHOLD)
+		memcpy(&cmd.decision_lut, iwl_loose_lookup,
+		       sizeof(iwl_tight_lookup));
+	else
+		memcpy(&cmd.decision_lut, iwl_tight_lookup,
+		       sizeof(iwl_tight_lookup));
+
+	cmd.bt_prio_boost = cpu_to_le32(IWL_BT_DEFAULT_BOOST);
+	cmd.kill_ack_msk =
+		cpu_to_le32(iwl_bt_ack_kill_msk[BT_KILL_MSK_DEFAULT]);
+	cmd.kill_cts_msk =
+		cpu_to_le32(iwl_bt_cts_kill_msk[BT_KILL_MSK_DEFAULT]);
+
+	/* go to CALIB state in internal BT-Coex state machine */
+	ret = iwl_send_bt_env(mvm, BT_COEX_ENV_OPEN,
+			      BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
+	if (ret)
+		return ret;
+
+	ret  = iwl_send_bt_env(mvm, BT_COEX_ENV_CLOSE,
+			       BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
+	if (ret)
+		return ret;
+
+	return iwl_mvm_send_cmd_pdu(mvm, BT_CONFIG, CMD_SYNC,
+				    sizeof(cmd), &cmd);
+}
+
+struct iwl_bt_notif_iterator_data {
+	struct iwl_mvm *mvm;
+	struct iwl_bt_coex_profile_notif *notif;
+};
+
+static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
+				      struct ieee80211_vif *vif)
+{
+	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+	struct iwl_bt_notif_iterator_data *data = _data;
+	struct ieee80211_chanctx_conf *chanctx_conf;
+	enum ieee80211_smps_mode smps_mode;
+	enum ieee80211_band band;
+
+	if (vif->type != NL80211_IFTYPE_STATION)
+		return;
+
+	rcu_read_lock();
+	chanctx_conf = rcu_dereference(vif->chanctx_conf);
+	if (chanctx_conf && chanctx_conf->def.chan)
+		band = chanctx_conf->def.chan->band;
+	else
+		band = -1;
+	rcu_read_unlock();
+
+	if (band != IEEE80211_BAND_2GHZ)
+		return;
+
+	smps_mode = IEEE80211_SMPS_AUTOMATIC;
+
+	if (data->notif->bt_status)
+		smps_mode = IEEE80211_SMPS_DYNAMIC;
+
+	if (data->notif->bt_traffic_load >= IWL_BT_LOAD_FORCE_SISO_THRESHOLD)
+		smps_mode = IEEE80211_SMPS_STATIC;
+
+	IWL_DEBUG_COEX(data->mvm,
+		       "mac %d: bt_status %d traffic_load %d smps_req %d\n",
+		       mvmvif->id,  data->notif->bt_status,
+		       data->notif->bt_traffic_load, smps_mode);
+
+	ieee80211_request_smps(vif, smps_mode);
+}
+
+int iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm,
+			     struct iwl_rx_cmd_buffer *rxb,
+			     struct iwl_device_cmd *dev_cmd)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	struct iwl_bt_coex_profile_notif *notif = (void *)pkt->data;
+	struct iwl_bt_notif_iterator_data data = {
+		.mvm = mvm,
+		.notif = notif,
+	};
+	struct iwl_bt_coex_cmd cmd = {};
+	enum iwl_bt_kill_msk bt_kill_msk;
+
+	IWL_DEBUG_COEX(mvm, "BT Coex Notification received\n");
+	IWL_DEBUG_COEX(mvm, "\tBT %salive\n", notif->bt_status ? "" : "not ");
+	IWL_DEBUG_COEX(mvm, "\tBT open conn %d\n", notif->bt_open_conn);
+	IWL_DEBUG_COEX(mvm, "\tBT traffic load %d\n", notif->bt_traffic_load);
+	IWL_DEBUG_COEX(mvm, "\tBT agg traffic load %d\n",
+		       notif->bt_agg_traffic_load);
+	IWL_DEBUG_COEX(mvm, "\tBT ci compliance %d\n", notif->bt_ci_compliance);
+
+	/* remember this notification for future use: rssi fluctuations */
+	memcpy(&mvm->last_bt_notif, notif, sizeof(mvm->last_bt_notif));
+
+	ieee80211_iterate_active_interfaces_atomic(
+					mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
+					iwl_mvm_bt_notif_iterator, &data);
+
+	/* Low latency BT profile is active: give higher prio to BT */
+	if (BT_MBOX_MSG(notif, 3, SCO_STATE)  ||
+	    BT_MBOX_MSG(notif, 3, A2DP_STATE) ||
+	    BT_MBOX_MSG(notif, 3, SNIFF_STATE))
+		bt_kill_msk = BT_KILL_MSK_SCO_HID_A2DP;
+	else
+		bt_kill_msk = BT_KILL_MSK_DEFAULT;
+
+	/* Don't send HCMD if there is no update */
+	if (bt_kill_msk == mvm->bt_kill_msk)
+		return 0;
+
+	IWL_DEBUG_COEX(mvm,
+		       "Update kill_msk: %d - SCO %sactive A2DP %sactive SNIFF %sactive\n",
+		       bt_kill_msk,
+		       BT_MBOX_MSG(notif, 3, SCO_STATE) ? "" : "in",
+		       BT_MBOX_MSG(notif, 3, A2DP_STATE) ? "" : "in",
+		       BT_MBOX_MSG(notif, 3, SNIFF_STATE) ? "" : "in");
+
+	mvm->bt_kill_msk = bt_kill_msk;
+	cmd.kill_ack_msk = cpu_to_le32(iwl_bt_ack_kill_msk[bt_kill_msk]);
+	cmd.kill_cts_msk = cpu_to_le32(iwl_bt_cts_kill_msk[bt_kill_msk]);
+
+	cmd.valid_bit_msk = cpu_to_le16(BT_VALID_KILL_ACK | BT_VALID_KILL_CTS);
+
+	if (iwl_mvm_send_cmd_pdu(mvm, BT_CONFIG, CMD_SYNC, sizeof(cmd), &cmd))
+		IWL_ERR(mvm, "Failed to sent BT Coex CMD\n");
+
+	/* This handler is ASYNC */
+	return 0;
+}
diff --git a/drivers/net/wireless/iwlwifi/mvm/d3.c b/drivers/net/wireless/iwlwifi/mvm/d3.c
index 994c8c2..bf087ab 100644
--- a/drivers/net/wireless/iwlwifi/mvm/d3.c
+++ b/drivers/net/wireless/iwlwifi/mvm/d3.c
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
@@ -62,8 +62,10 @@
  *****************************************************************************/
 
 #include <linux/etherdevice.h>
+#include <linux/ip.h>
 #include <net/cfg80211.h>
 #include <net/ipv6.h>
+#include <net/tcp.h>
 #include "iwl-modparams.h"
 #include "fw-api.h"
 #include "mvm.h"
@@ -402,6 +404,233 @@ static int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm,
 				    sizeof(cmd), &cmd);
 }
 
+enum iwl_mvm_tcp_packet_type {
+	MVM_TCP_TX_SYN,
+	MVM_TCP_RX_SYNACK,
+	MVM_TCP_TX_DATA,
+	MVM_TCP_RX_ACK,
+	MVM_TCP_RX_WAKE,
+	MVM_TCP_TX_FIN,
+};
+
+static __le16 pseudo_hdr_check(int len, __be32 saddr, __be32 daddr)
+{
+	__sum16 check = tcp_v4_check(len, saddr, daddr, 0);
+	return cpu_to_le16(be16_to_cpu((__force __be16)check));
+}
+
+static void iwl_mvm_build_tcp_packet(struct iwl_mvm *mvm,
+				     struct ieee80211_vif *vif,
+				     struct cfg80211_wowlan_tcp *tcp,
+				     void *_pkt, u8 *mask,
+				     __le16 *pseudo_hdr_csum,
+				     enum iwl_mvm_tcp_packet_type ptype)
+{
+	struct {
+		struct ethhdr eth;
+		struct iphdr ip;
+		struct tcphdr tcp;
+		u8 data[];
+	} __packed *pkt = _pkt;
+	u16 ip_tot_len = sizeof(struct iphdr) + sizeof(struct tcphdr);
+	int i;
+
+	pkt->eth.h_proto = cpu_to_be16(ETH_P_IP),
+	pkt->ip.version = 4;
+	pkt->ip.ihl = 5;
+	pkt->ip.protocol = IPPROTO_TCP;
+
+	switch (ptype) {
+	case MVM_TCP_TX_SYN:
+	case MVM_TCP_TX_DATA:
+	case MVM_TCP_TX_FIN:
+		memcpy(pkt->eth.h_dest, tcp->dst_mac, ETH_ALEN);
+		memcpy(pkt->eth.h_source, vif->addr, ETH_ALEN);
+		pkt->ip.ttl = 128;
+		pkt->ip.saddr = tcp->src;
+		pkt->ip.daddr = tcp->dst;
+		pkt->tcp.source = cpu_to_be16(tcp->src_port);
+		pkt->tcp.dest = cpu_to_be16(tcp->dst_port);
+		/* overwritten for TX SYN later */
+		pkt->tcp.doff = sizeof(struct tcphdr) / 4;
+		pkt->tcp.window = cpu_to_be16(65000);
+		break;
+	case MVM_TCP_RX_SYNACK:
+	case MVM_TCP_RX_ACK:
+	case MVM_TCP_RX_WAKE:
+		memcpy(pkt->eth.h_dest, vif->addr, ETH_ALEN);
+		memcpy(pkt->eth.h_source, tcp->dst_mac, ETH_ALEN);
+		pkt->ip.saddr = tcp->dst;
+		pkt->ip.daddr = tcp->src;
+		pkt->tcp.source = cpu_to_be16(tcp->dst_port);
+		pkt->tcp.dest = cpu_to_be16(tcp->src_port);
+		break;
+	default:
+		WARN_ON(1);
+		return;
+	}
+
+	switch (ptype) {
+	case MVM_TCP_TX_SYN:
+		/* firmware assumes 8 option bytes - 8 NOPs for now */
+		memset(pkt->data, 0x01, 8);
+		ip_tot_len += 8;
+		pkt->tcp.doff = (sizeof(struct tcphdr) + 8) / 4;
+		pkt->tcp.syn = 1;
+		break;
+	case MVM_TCP_TX_DATA:
+		ip_tot_len += tcp->payload_len;
+		memcpy(pkt->data, tcp->payload, tcp->payload_len);
+		pkt->tcp.psh = 1;
+		pkt->tcp.ack = 1;
+		break;
+	case MVM_TCP_TX_FIN:
+		pkt->tcp.fin = 1;
+		pkt->tcp.ack = 1;
+		break;
+	case MVM_TCP_RX_SYNACK:
+		pkt->tcp.syn = 1;
+		pkt->tcp.ack = 1;
+		break;
+	case MVM_TCP_RX_ACK:
+		pkt->tcp.ack = 1;
+		break;
+	case MVM_TCP_RX_WAKE:
+		ip_tot_len += tcp->wake_len;
+		pkt->tcp.psh = 1;
+		pkt->tcp.ack = 1;
+		memcpy(pkt->data, tcp->wake_data, tcp->wake_len);
+		break;
+	}
+
+	switch (ptype) {
+	case MVM_TCP_TX_SYN:
+	case MVM_TCP_TX_DATA:
+	case MVM_TCP_TX_FIN:
+		pkt->ip.tot_len = cpu_to_be16(ip_tot_len);
+		pkt->ip.check = ip_fast_csum(&pkt->ip, pkt->ip.ihl);
+		break;
+	case MVM_TCP_RX_WAKE:
+		for (i = 0; i < DIV_ROUND_UP(tcp->wake_len, 8); i++) {
+			u8 tmp = tcp->wake_mask[i];
+			mask[i + 6] |= tmp << 6;
+			if (i + 1 < DIV_ROUND_UP(tcp->wake_len, 8))
+				mask[i + 7] = tmp >> 2;
+		}
+		/* fall through for ethernet/IP/TCP headers mask */
+	case MVM_TCP_RX_SYNACK:
+	case MVM_TCP_RX_ACK:
+		mask[0] = 0xff; /* match ethernet */
+		/*
+		 * match ethernet, ip.version, ip.ihl
+		 * the ip.ihl half byte is really masked out by firmware
+		 */
+		mask[1] = 0x7f;
+		mask[2] = 0x80; /* match ip.protocol */
+		mask[3] = 0xfc; /* match ip.saddr, ip.daddr */
+		mask[4] = 0x3f; /* match ip.daddr, tcp.source, tcp.dest */
+		mask[5] = 0x80; /* match tcp flags */
+		/* leave rest (0 or set for MVM_TCP_RX_WAKE) */
+		break;
+	};
+
+	*pseudo_hdr_csum = pseudo_hdr_check(ip_tot_len - sizeof(struct iphdr),
+					    pkt->ip.saddr, pkt->ip.daddr);
+}
+
+static int iwl_mvm_send_remote_wake_cfg(struct iwl_mvm *mvm,
+					struct ieee80211_vif *vif,
+					struct cfg80211_wowlan_tcp *tcp)
+{
+	struct iwl_wowlan_remote_wake_config *cfg;
+	struct iwl_host_cmd cmd = {
+		.id = REMOTE_WAKE_CONFIG_CMD,
+		.len = { sizeof(*cfg), },
+		.dataflags = { IWL_HCMD_DFL_NOCOPY, },
+		.flags = CMD_SYNC,
+	};
+	int ret;
+
+	if (!tcp)
+		return 0;
+
+	cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
+	if (!cfg)
+		return -ENOMEM;
+	cmd.data[0] = cfg;
+
+	cfg->max_syn_retries = 10;
+	cfg->max_data_retries = 10;
+	cfg->tcp_syn_ack_timeout = 1; /* seconds */
+	cfg->tcp_ack_timeout = 1; /* seconds */
+
+	/* SYN (TX) */
+	iwl_mvm_build_tcp_packet(
+		mvm, vif, tcp, cfg->syn_tx.data, NULL,
+		&cfg->syn_tx.info.tcp_pseudo_header_checksum,
+		MVM_TCP_TX_SYN);
+	cfg->syn_tx.info.tcp_payload_length = 0;
+
+	/* SYN/ACK (RX) */
+	iwl_mvm_build_tcp_packet(
+		mvm, vif, tcp, cfg->synack_rx.data, cfg->synack_rx.rx_mask,
+		&cfg->synack_rx.info.tcp_pseudo_header_checksum,
+		MVM_TCP_RX_SYNACK);
+	cfg->synack_rx.info.tcp_payload_length = 0;
+
+	/* KEEPALIVE/ACK (TX) */
+	iwl_mvm_build_tcp_packet(
+		mvm, vif, tcp, cfg->keepalive_tx.data, NULL,
+		&cfg->keepalive_tx.info.tcp_pseudo_header_checksum,
+		MVM_TCP_TX_DATA);
+	cfg->keepalive_tx.info.tcp_payload_length =
+		cpu_to_le16(tcp->payload_len);
+	cfg->sequence_number_offset = tcp->payload_seq.offset;
+	/* length must be 0..4, the field is little endian */
+	cfg->sequence_number_length = tcp->payload_seq.len;
+	cfg->initial_sequence_number = cpu_to_le32(tcp->payload_seq.start);
+	cfg->keepalive_interval = cpu_to_le16(tcp->data_interval);
+	if (tcp->payload_tok.len) {
+		cfg->token_offset = tcp->payload_tok.offset;
+		cfg->token_length = tcp->payload_tok.len;
+		cfg->num_tokens =
+			cpu_to_le16(tcp->tokens_size % tcp->payload_tok.len);
+		memcpy(cfg->tokens, tcp->payload_tok.token_stream,
+		       tcp->tokens_size);
+	} else {
+		/* set tokens to max value to almost never run out */
+		cfg->num_tokens = cpu_to_le16(65535);
+	}
+
+	/* ACK (RX) */
+	iwl_mvm_build_tcp_packet(
+		mvm, vif, tcp, cfg->keepalive_ack_rx.data,
+		cfg->keepalive_ack_rx.rx_mask,
+		&cfg->keepalive_ack_rx.info.tcp_pseudo_header_checksum,
+		MVM_TCP_RX_ACK);
+	cfg->keepalive_ack_rx.info.tcp_payload_length = 0;
+
+	/* WAKEUP (RX) */
+	iwl_mvm_build_tcp_packet(
+		mvm, vif, tcp, cfg->wake_rx.data, cfg->wake_rx.rx_mask,
+		&cfg->wake_rx.info.tcp_pseudo_header_checksum,
+		MVM_TCP_RX_WAKE);
+	cfg->wake_rx.info.tcp_payload_length =
+		cpu_to_le16(tcp->wake_len);
+
+	/* FIN */
+	iwl_mvm_build_tcp_packet(
+		mvm, vif, tcp, cfg->fin_tx.data, NULL,
+		&cfg->fin_tx.info.tcp_pseudo_header_checksum,
+		MVM_TCP_TX_FIN);
+	cfg->fin_tx.info.tcp_payload_length = 0;
+
+	ret = iwl_mvm_send_cmd(mvm, &cmd);
+	kfree(cfg);
+
+	return ret;
+}
+
 struct iwl_d3_iter_data {
 	struct iwl_mvm *mvm;
 	struct ieee80211_vif *vif;
@@ -637,9 +866,21 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
 			cpu_to_le32(IWL_WOWLAN_WAKEUP_PATTERN_MATCH);
 
 	if (wowlan->rfkill_release)
-		d3_cfg_cmd.wakeup_flags |=
+		wowlan_config_cmd.wakeup_filter |=
 			cpu_to_le32(IWL_WOWLAN_WAKEUP_RF_KILL_DEASSERT);
 
+	if (wowlan->tcp) {
+		/*
+		 * Set the "link change" (really "link lost") flag as well
+		 * since that implies losing the TCP connection.
+		 */
+		wowlan_config_cmd.wakeup_filter |=
+			cpu_to_le32(IWL_WOWLAN_WAKEUP_REMOTE_LINK_LOSS |
+				    IWL_WOWLAN_WAKEUP_REMOTE_SIGNATURE_TABLE |
+				    IWL_WOWLAN_WAKEUP_REMOTE_WAKEUP_PACKET |
+				    IWL_WOWLAN_WAKEUP_LINK_CHANGE);
+	}
+
 	iwl_mvm_cancel_scan(mvm);
 
 	iwl_trans_stop_device(mvm->trans);
@@ -755,6 +996,10 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
 	if (ret)
 		goto out;
 
+	ret = iwl_mvm_send_remote_wake_cfg(mvm, vif, wowlan->tcp);
+	if (ret)
+		goto out;
+
 	/* must be last -- this switches firmware state */
 	ret = iwl_mvm_send_cmd_pdu(mvm, D3_CONFIG_CMD, CMD_SYNC,
 				   sizeof(d3_cfg_cmd), &d3_cfg_cmd);
@@ -874,6 +1119,15 @@ static void iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm,
 	if (reasons & IWL_WOWLAN_WAKEUP_BY_FOUR_WAY_HANDSHAKE)
 		wakeup.four_way_handshake = true;
 
+	if (reasons & IWL_WOWLAN_WAKEUP_BY_REM_WAKE_LINK_LOSS)
+		wakeup.tcp_connlost = true;
+
+	if (reasons & IWL_WOWLAN_WAKEUP_BY_REM_WAKE_SIGNATURE_TABLE)
+		wakeup.tcp_nomoretokens = true;
+
+	if (reasons & IWL_WOWLAN_WAKEUP_BY_REM_WAKE_WAKEUP_PACKET)
+		wakeup.tcp_match = true;
+
 	if (status->wake_packet_bufsize) {
 		int pktsize = le32_to_cpu(status->wake_packet_bufsize);
 		int pktlen = le32_to_cpu(status->wake_packet_length);
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c
index c1bdb55..b080b4b 100644
--- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c
+++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
@@ -69,12 +69,6 @@ struct iwl_dbgfs_mvm_ctx {
 	struct ieee80211_vif *vif;
 };
 
-static int iwl_dbgfs_open_file_generic(struct inode *inode, struct file *file)
-{
-	file->private_data = inode->i_private;
-	return 0;
-}
-
 static ssize_t iwl_dbgfs_tx_flush_write(struct file *file,
 					const char __user *user_buf,
 					size_t count, loff_t *ppos)
@@ -306,10 +300,130 @@ static ssize_t iwl_dbgfs_power_down_d3_allow_write(struct file *file,
 	return count;
 }
 
+#define BT_MBOX_MSG(_notif, _num, _field)				     \
+	((le32_to_cpu((_notif)->mbox_msg[(_num)]) & BT_MBOX##_num##_##_field)\
+	>> BT_MBOX##_num##_##_field##_POS)
+
+
+#define BT_MBOX_PRINT(_num, _field, _end)				    \
+			pos += scnprintf(buf + pos, bufsz - pos,	    \
+					 "\t%s: %d%s",			    \
+					 #_field,			    \
+					 BT_MBOX_MSG(notif, _num, _field),  \
+					 true ? "\n" : ", ");
+
+static ssize_t iwl_dbgfs_bt_notif_read(struct file *file, char __user *user_buf,
+				       size_t count, loff_t *ppos)
+{
+	struct iwl_mvm *mvm = file->private_data;
+	struct iwl_bt_coex_profile_notif *notif = &mvm->last_bt_notif;
+	char *buf;
+	int ret, pos = 0, bufsz = sizeof(char) * 1024;
+
+	buf = kmalloc(bufsz, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	mutex_lock(&mvm->mutex);
+
+	pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw0:\n");
+
+	BT_MBOX_PRINT(0, LE_SLAVE_LAT, false);
+	BT_MBOX_PRINT(0, LE_PROF1, false);
+	BT_MBOX_PRINT(0, LE_PROF2, false);
+	BT_MBOX_PRINT(0, LE_PROF_OTHER, false);
+	BT_MBOX_PRINT(0, CHL_SEQ_N, false);
+	BT_MBOX_PRINT(0, INBAND_S, false);
+	BT_MBOX_PRINT(0, LE_MIN_RSSI, false);
+	BT_MBOX_PRINT(0, LE_SCAN, false);
+	BT_MBOX_PRINT(0, LE_ADV, false);
+	BT_MBOX_PRINT(0, LE_MAX_TX_POWER, false);
+	BT_MBOX_PRINT(0, OPEN_CON_1, true);
+
+	pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw1:\n");
+
+	BT_MBOX_PRINT(1, BR_MAX_TX_POWER, false);
+	BT_MBOX_PRINT(1, IP_SR, false);
+	BT_MBOX_PRINT(1, LE_MSTR, false);
+	BT_MBOX_PRINT(1, AGGR_TRFC_LD, false);
+	BT_MBOX_PRINT(1, MSG_TYPE, false);
+	BT_MBOX_PRINT(1, SSN, true);
+
+	pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw2:\n");
+
+	BT_MBOX_PRINT(2, SNIFF_ACT, false);
+	BT_MBOX_PRINT(2, PAG, false);
+	BT_MBOX_PRINT(2, INQUIRY, false);
+	BT_MBOX_PRINT(2, CONN, false);
+	BT_MBOX_PRINT(2, SNIFF_INTERVAL, false);
+	BT_MBOX_PRINT(2, DISC, false);
+	BT_MBOX_PRINT(2, SCO_TX_ACT, false);
+	BT_MBOX_PRINT(2, SCO_RX_ACT, false);
+	BT_MBOX_PRINT(2, ESCO_RE_TX, false);
+	BT_MBOX_PRINT(2, SCO_DURATION, true);
+
+	pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw3:\n");
+
+	BT_MBOX_PRINT(3, SCO_STATE, false);
+	BT_MBOX_PRINT(3, SNIFF_STATE, false);
+	BT_MBOX_PRINT(3, A2DP_STATE, false);
+	BT_MBOX_PRINT(3, ACL_STATE, false);
+	BT_MBOX_PRINT(3, MSTR_STATE, false);
+	BT_MBOX_PRINT(3, OBX_STATE, false);
+	BT_MBOX_PRINT(3, OPEN_CON_2, false);
+	BT_MBOX_PRINT(3, TRAFFIC_LOAD, false);
+	BT_MBOX_PRINT(3, CHL_SEQN_LSB, false);
+	BT_MBOX_PRINT(3, INBAND_P, false);
+	BT_MBOX_PRINT(3, MSG_TYPE_2, false);
+	BT_MBOX_PRINT(3, SSN_2, false);
+	BT_MBOX_PRINT(3, UPDATE_REQUEST, true);
+
+	pos += scnprintf(buf+pos, bufsz-pos, "bt_status = %d\n",
+					 notif->bt_status);
+	pos += scnprintf(buf+pos, bufsz-pos, "bt_open_conn = %d\n",
+					 notif->bt_open_conn);
+	pos += scnprintf(buf+pos, bufsz-pos, "bt_traffic_load = %d\n",
+					 notif->bt_traffic_load);
+	pos += scnprintf(buf+pos, bufsz-pos, "bt_agg_traffic_load = %d\n",
+					 notif->bt_agg_traffic_load);
+	pos += scnprintf(buf+pos, bufsz-pos, "bt_ci_compliance = %d\n",
+					 notif->bt_ci_compliance);
+
+	mutex_unlock(&mvm->mutex);
+
+	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+	kfree(buf);
+
+	return ret;
+}
+#undef BT_MBOX_PRINT
+
+static ssize_t iwl_dbgfs_fw_restart_write(struct file *file,
+					  const char __user *user_buf,
+					  size_t count, loff_t *ppos)
+{
+	struct iwl_mvm *mvm = file->private_data;
+	bool restart_fw = iwlwifi_mod_params.restart_fw;
+	int ret;
+
+	iwlwifi_mod_params.restart_fw = true;
+
+	mutex_lock(&mvm->mutex);
+
+	/* take the return value to make compiler happy - it will fail anyway */
+	ret = iwl_mvm_send_cmd_pdu(mvm, REPLY_ERROR, CMD_SYNC, 0, NULL);
+
+	mutex_unlock(&mvm->mutex);
+
+	iwlwifi_mod_params.restart_fw = restart_fw;
+
+	return count;
+}
+
 #define MVM_DEBUGFS_READ_FILE_OPS(name)					\
 static const struct file_operations iwl_dbgfs_##name##_ops = {	\
 	.read = iwl_dbgfs_##name##_read,				\
-	.open = iwl_dbgfs_open_file_generic,				\
+	.open = simple_open,						\
 	.llseek = generic_file_llseek,					\
 }
 
@@ -317,14 +431,14 @@ static const struct file_operations iwl_dbgfs_##name##_ops = {	\
 static const struct file_operations iwl_dbgfs_##name##_ops = {	\
 	.write = iwl_dbgfs_##name##_write,				\
 	.read = iwl_dbgfs_##name##_read,				\
-	.open = iwl_dbgfs_open_file_generic,				\
+	.open = simple_open,						\
 	.llseek = generic_file_llseek,					\
 };
 
 #define MVM_DEBUGFS_WRITE_FILE_OPS(name)				\
 static const struct file_operations iwl_dbgfs_##name##_ops = {	\
 	.write = iwl_dbgfs_##name##_write,				\
-	.open = iwl_dbgfs_open_file_generic,				\
+	.open = simple_open,						\
 	.llseek = generic_file_llseek,					\
 };
 
@@ -345,8 +459,10 @@ MVM_DEBUGFS_WRITE_FILE_OPS(tx_flush);
 MVM_DEBUGFS_WRITE_FILE_OPS(sta_drain);
 MVM_DEBUGFS_READ_WRITE_FILE_OPS(sram);
 MVM_DEBUGFS_READ_FILE_OPS(stations);
+MVM_DEBUGFS_READ_FILE_OPS(bt_notif);
 MVM_DEBUGFS_WRITE_FILE_OPS(power_down_allow);
 MVM_DEBUGFS_WRITE_FILE_OPS(power_down_d3_allow);
+MVM_DEBUGFS_WRITE_FILE_OPS(fw_restart);
 
 int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
 {
@@ -358,8 +474,10 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
 	MVM_DEBUGFS_ADD_FILE(sta_drain, mvm->debugfs_dir, S_IWUSR);
 	MVM_DEBUGFS_ADD_FILE(sram, mvm->debugfs_dir, S_IWUSR | S_IRUSR);
 	MVM_DEBUGFS_ADD_FILE(stations, dbgfs_dir, S_IRUSR);
+	MVM_DEBUGFS_ADD_FILE(bt_notif, dbgfs_dir, S_IRUSR);
 	MVM_DEBUGFS_ADD_FILE(power_down_allow, mvm->debugfs_dir, S_IWUSR);
 	MVM_DEBUGFS_ADD_FILE(power_down_d3_allow, mvm->debugfs_dir, S_IWUSR);
+	MVM_DEBUGFS_ADD_FILE(fw_restart, mvm->debugfs_dir, S_IWUSR);
 
 	/*
 	 * Create a symlink with mac80211. It will be removed when mac80211
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-bt-coex.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-bt-coex.h
new file mode 100644
index 0000000..05c61d6
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-bt-coex.h
@@ -0,0 +1,319 @@
+/******************************************************************************
+ *
+ * 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) 2013 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 COPYING.
+ *
+ * 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) 2013 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 __fw_api_bt_coex_h__
+#define __fw_api_bt_coex_h__
+
+#include <linux/types.h>
+#include <linux/bitops.h>
+
+#define BITS(nb) (BIT(nb) - 1)
+
+/**
+ * enum iwl_bt_coex_flags - flags for BT_COEX command
+ * @BT_CH_PRIMARY_EN:
+ * @BT_CH_SECONDARY_EN:
+ * @BT_NOTIF_COEX_OFF:
+ * @BT_COEX_MODE_POS:
+ * @BT_COEX_MODE_MSK:
+ * @BT_COEX_DISABLE:
+ * @BT_COEX_2W:
+ * @BT_COEX_3W:
+ * @BT_COEX_NW:
+ * @BT_USE_DEFAULTS:
+ * @BT_SYNC_2_BT_DISABLE:
+ * @BT_COEX_CORUNNING_TBL_EN:
+ */
+enum iwl_bt_coex_flags {
+	BT_CH_PRIMARY_EN		= BIT(0),
+	BT_CH_SECONDARY_EN		= BIT(1),
+	BT_NOTIF_COEX_OFF		= BIT(2),
+	BT_COEX_MODE_POS		= 3,
+	BT_COEX_MODE_MSK		= BITS(3) << BT_COEX_MODE_POS,
+	BT_COEX_DISABLE			= 0x0 << BT_COEX_MODE_POS,
+	BT_COEX_2W			= 0x1 << BT_COEX_MODE_POS,
+	BT_COEX_3W			= 0x2 << BT_COEX_MODE_POS,
+	BT_COEX_NW			= 0x3 << BT_COEX_MODE_POS,
+	BT_USE_DEFAULTS			= BIT(6),
+	BT_SYNC_2_BT_DISABLE		= BIT(7),
+	/*
+	 * For future use - when the flags will be enlarged
+	 * BT_COEX_CORUNNING_TBL_EN	= BIT(8),
+	 */
+};
+
+/*
+ * indicates what has changed in the BT_COEX command.
+ */
+enum iwl_bt_coex_valid_bit_msk {
+	BT_VALID_ENABLE			= BIT(0),
+	BT_VALID_BT_PRIO_BOOST		= BIT(1),
+	BT_VALID_MAX_KILL		= BIT(2),
+	BT_VALID_3W_TMRS		= BIT(3),
+	BT_VALID_KILL_ACK		= BIT(4),
+	BT_VALID_KILL_CTS		= BIT(5),
+	BT_VALID_REDUCED_TX_POWER	= BIT(6),
+	BT_VALID_LUT			= BIT(7),
+	BT_VALID_WIFI_RX_SW_PRIO_BOOST	= BIT(8),
+	BT_VALID_WIFI_TX_SW_PRIO_BOOST	= BIT(9),
+	BT_VALID_MULTI_PRIO_LUT		= BIT(10),
+	BT_VALID_TRM_KICK_FILTER	= BIT(11),
+	BT_VALID_CORUN_LUT_20		= BIT(12),
+	BT_VALID_CORUN_LUT_40		= BIT(13),
+	BT_VALID_ANT_ISOLATION		= BIT(14),
+	BT_VALID_ANT_ISOLATION_THRS	= BIT(15),
+	/*
+	 * For future use - when the valid flags will be enlarged
+	 * BT_VALID_TXTX_DELTA_FREQ_THRS	= BIT(16),
+	 * BT_VALID_TXRX_MAX_FREQ_0	= BIT(17),
+	 */
+};
+
+/**
+ * enum iwl_bt_reduced_tx_power - allows to reduce txpower for WiFi frames.
+ * @BT_REDUCED_TX_POWER_CTL: reduce Tx power for control frames
+ * @BT_REDUCED_TX_POWER_DATA: reduce Tx power for data frames
+ *
+ * This mechanism allows to have BT and WiFi run concurrently. Since WiFi
+ * reduces its Tx power, it can work along with BT, hence reducing the amount
+ * of WiFi frames being killed by BT.
+ */
+enum iwl_bt_reduced_tx_power {
+	BT_REDUCED_TX_POWER_CTL		= BIT(0),
+	BT_REDUCED_TX_POWER_DATA	= BIT(1),
+};
+
+#define BT_COEX_LUT_SIZE (12)
+
+/**
+ * struct iwl_bt_coex_cmd - bt coex configuration command
+ * @flags:&enum iwl_bt_coex_flags
+ * @lead_time:
+ * @max_kill:
+ * @bt3_time_t7_value:
+ * @kill_ack_msk:
+ * @kill_cts_msk:
+ * @bt3_prio_sample_time:
+ * @bt3_timer_t2_value:
+ * @bt4_reaction_time:
+ * @decision_lut[12]:
+ * @bt_reduced_tx_power: enum %iwl_bt_reduced_tx_power
+ * @valid_bit_msk: enum %iwl_bt_coex_valid_bit_msk
+ * @bt_prio_boost: values for PTA boost register
+ * @wifi_tx_prio_boost: SW boost of wifi tx priority
+ * @wifi_rx_prio_boost: SW boost of wifi rx priority
+ *
+ * The structure is used for the BT_COEX command.
+ */
+struct iwl_bt_coex_cmd {
+	u8 flags;
+	u8 lead_time;
+	u8 max_kill;
+	u8 bt3_time_t7_value;
+	__le32 kill_ack_msk;
+	__le32 kill_cts_msk;
+	u8 bt3_prio_sample_time;
+	u8 bt3_timer_t2_value;
+	__le16 bt4_reaction_time;
+	__le32 decision_lut[BT_COEX_LUT_SIZE];
+	u8 bt_reduced_tx_power;
+	u8 reserved;
+	__le16 valid_bit_msk;
+	__le32 bt_prio_boost;
+	u8 reserved2;
+	u8 wifi_tx_prio_boost;
+	__le16 wifi_rx_prio_boost;
+} __packed; /* BT_COEX_CMD_API_S_VER_3 */
+
+#define BT_MBOX(n_dw, _msg, _pos, _nbits)	\
+	BT_MBOX##n_dw##_##_msg##_POS = (_pos),	\
+	BT_MBOX##n_dw##_##_msg = BITS(_nbits) << BT_MBOX##n_dw##_##_msg##_POS
+
+enum iwl_bt_mxbox_dw0 {
+	BT_MBOX(0, LE_SLAVE_LAT, 0, 3),
+	BT_MBOX(0, LE_PROF1, 3, 1),
+	BT_MBOX(0, LE_PROF2, 4, 1),
+	BT_MBOX(0, LE_PROF_OTHER, 5, 1),
+	BT_MBOX(0, CHL_SEQ_N, 8, 4),
+	BT_MBOX(0, INBAND_S, 13, 1),
+	BT_MBOX(0, LE_MIN_RSSI, 16, 4),
+	BT_MBOX(0, LE_SCAN, 20, 1),
+	BT_MBOX(0, LE_ADV, 21, 1),
+	BT_MBOX(0, LE_MAX_TX_POWER, 24, 4),
+	BT_MBOX(0, OPEN_CON_1, 28, 2),
+};
+
+enum iwl_bt_mxbox_dw1 {
+	BT_MBOX(1, BR_MAX_TX_POWER, 0, 4),
+	BT_MBOX(1, IP_SR, 4, 1),
+	BT_MBOX(1, LE_MSTR, 5, 1),
+	BT_MBOX(1, AGGR_TRFC_LD, 8, 6),
+	BT_MBOX(1, MSG_TYPE, 16, 3),
+	BT_MBOX(1, SSN, 19, 2),
+};
+
+enum iwl_bt_mxbox_dw2 {
+	BT_MBOX(2, SNIFF_ACT, 0, 3),
+	BT_MBOX(2, PAG, 3, 1),
+	BT_MBOX(2, INQUIRY, 4, 1),
+	BT_MBOX(2, CONN, 5, 1),
+	BT_MBOX(2, SNIFF_INTERVAL, 8, 5),
+	BT_MBOX(2, DISC, 13, 1),
+	BT_MBOX(2, SCO_TX_ACT, 16, 2),
+	BT_MBOX(2, SCO_RX_ACT, 18, 2),
+	BT_MBOX(2, ESCO_RE_TX, 20, 2),
+	BT_MBOX(2, SCO_DURATION, 24, 6),
+};
+
+enum iwl_bt_mxbox_dw3 {
+	BT_MBOX(3, SCO_STATE, 0, 1),
+	BT_MBOX(3, SNIFF_STATE, 1, 1),
+	BT_MBOX(3, A2DP_STATE, 2, 1),
+	BT_MBOX(3, ACL_STATE, 3, 1),
+	BT_MBOX(3, MSTR_STATE, 4, 1),
+	BT_MBOX(3, OBX_STATE, 5, 1),
+	BT_MBOX(3, OPEN_CON_2, 8, 2),
+	BT_MBOX(3, TRAFFIC_LOAD, 10, 2),
+	BT_MBOX(3, CHL_SEQN_LSB, 12, 1),
+	BT_MBOX(3, INBAND_P, 13, 1),
+	BT_MBOX(3, MSG_TYPE_2, 16, 3),
+	BT_MBOX(3, SSN_2, 19, 2),
+	BT_MBOX(3, UPDATE_REQUEST, 21, 1),
+};
+
+#define BT_MBOX_MSG(_notif, _num, _field)				     \
+	((le32_to_cpu((_notif)->mbox_msg[(_num)]) & BT_MBOX##_num##_##_field)\
+	>> BT_MBOX##_num##_##_field##_POS)
+
+/**
+ * struct iwl_bt_coex_profile_notif - notification about BT coex
+ * @mbox_msg: message from BT to WiFi
+ * @:bt_status: 0 - off, 1 - on
+ * @:bt_open_conn: number of BT connections open
+ * @:bt_traffic_load: load of BT traffic
+ * @:bt_agg_traffic_load: aggregated load of BT traffic
+ * @:bt_ci_compliance: 0 - no CI compliance, 1 - CI compliant
+ */
+struct iwl_bt_coex_profile_notif {
+	__le32 mbox_msg[4];
+	u8 bt_status;
+	u8 bt_open_conn;
+	u8 bt_traffic_load;
+	u8 bt_agg_traffic_load;
+	u8 bt_ci_compliance;
+	u8 reserved[3];
+} __packed; /* BT_COEX_PROFILE_NTFY_API_S_VER_2 */
+
+enum iwl_bt_coex_prio_table_event {
+	BT_COEX_PRIO_TBL_EVT_INIT_CALIB1		= 0,
+	BT_COEX_PRIO_TBL_EVT_INIT_CALIB2		= 1,
+	BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_LOW1	= 2,
+	BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_LOW2	= 3,
+	BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_HIGH1	= 4,
+	BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_HIGH2	= 5,
+	BT_COEX_PRIO_TBL_EVT_DTIM			= 6,
+	BT_COEX_PRIO_TBL_EVT_SCAN52			= 7,
+	BT_COEX_PRIO_TBL_EVT_SCAN24			= 8,
+	BT_COEX_PRIO_TBL_EVT_IDLE			= 9,
+	BT_COEX_PRIO_TBL_EVT_MAX			= 16,
+}; /* BT_COEX_PRIO_TABLE_EVENTS_API_E_VER_1 */
+
+enum iwl_bt_coex_prio_table_prio {
+	BT_COEX_PRIO_TBL_DISABLED	= 0,
+	BT_COEX_PRIO_TBL_PRIO_LOW	= 1,
+	BT_COEX_PRIO_TBL_PRIO_HIGH	= 2,
+	BT_COEX_PRIO_TBL_PRIO_BYPASS	= 3,
+	BT_COEX_PRIO_TBL_PRIO_COEX_OFF	= 4,
+	BT_COEX_PRIO_TBL_PRIO_COEX_ON	= 5,
+	BT_COEX_PRIO_TBL_PRIO_COEX_IDLE = 6,
+	BT_COEX_PRIO_TBL_MAX		= 8,
+}; /* BT_COEX_PRIO_TABLE_PRIORITIES_API_E_VER_1 */
+
+#define BT_COEX_PRIO_TBL_SHRD_ANT_POS     (0)
+#define BT_COEX_PRIO_TBL_PRIO_POS         (1)
+#define BT_COEX_PRIO_TBL_RESERVED_POS     (4)
+
+/**
+ * struct iwl_bt_coex_prio_tbl_cmd - priority table for BT coex
+ * @prio_tbl:
+ */
+struct iwl_bt_coex_prio_tbl_cmd {
+	u8 prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX];
+} __packed;
+
+enum iwl_bt_coex_env_action {
+	BT_COEX_ENV_CLOSE	 = 0,
+	BT_COEX_ENV_OPEN	 = 1,
+}; /* BT_COEX_PROT_ENV_ACTION_API_E_VER_1 */
+
+/**
+ * struct iwl_bt_coex_prot_env_cmd - BT Protection Envelope
+ * @action: enum %iwl_bt_coex_env_action
+ * @type: enum %iwl_bt_coex_prio_table_event
+ */
+struct iwl_bt_coex_prot_env_cmd {
+	u8 action; /* 0 = closed, 1 = open */
+	u8 type; /* 0 .. 15 */
+	u8 reserved[2];
+} __packed;
+
+#endif /* __fw_api_bt_coex_h__ */
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h
index cf6f9a0..51e015d 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
@@ -258,7 +258,7 @@ enum iwl_wowlan_wakeup_reason {
 	IWL_WOWLAN_WAKEUP_BY_FOUR_WAY_HANDSHAKE			= BIT(8),
 	IWL_WOWLAN_WAKEUP_BY_REM_WAKE_LINK_LOSS			= BIT(9),
 	IWL_WOWLAN_WAKEUP_BY_REM_WAKE_SIGNATURE_TABLE		= BIT(10),
-	IWL_WOWLAN_WAKEUP_BY_REM_WAKE_TCP_EXTERNAL		= BIT(11),
+	/* BIT(11) reserved */
 	IWL_WOWLAN_WAKEUP_BY_REM_WAKE_WAKEUP_PACKET		= BIT(12),
 }; /* WOWLAN_WAKE_UP_REASON_API_E_VER_2 */
 
@@ -277,6 +277,55 @@ struct iwl_wowlan_status {
 	u8 wake_packet[]; /* can be truncated from _length to _bufsize */
 } __packed; /* WOWLAN_STATUSES_API_S_VER_4 */
 
+#define IWL_WOWLAN_TCP_MAX_PACKET_LEN		64
+#define IWL_WOWLAN_REMOTE_WAKE_MAX_PACKET_LEN	128
+#define IWL_WOWLAN_REMOTE_WAKE_MAX_TOKENS	2048
+
+struct iwl_tcp_packet_info {
+	__le16 tcp_pseudo_header_checksum;
+	__le16 tcp_payload_length;
+} __packed; /* TCP_PACKET_INFO_API_S_VER_2 */
+
+struct iwl_tcp_packet {
+	struct iwl_tcp_packet_info info;
+	u8 rx_mask[IWL_WOWLAN_MAX_PATTERN_LEN / 8];
+	u8 data[IWL_WOWLAN_TCP_MAX_PACKET_LEN];
+} __packed; /* TCP_PROTOCOL_PACKET_API_S_VER_1 */
+
+struct iwl_remote_wake_packet {
+	struct iwl_tcp_packet_info info;
+	u8 rx_mask[IWL_WOWLAN_MAX_PATTERN_LEN / 8];
+	u8 data[IWL_WOWLAN_REMOTE_WAKE_MAX_PACKET_LEN];
+} __packed; /* TCP_PROTOCOL_PACKET_API_S_VER_1 */
+
+struct iwl_wowlan_remote_wake_config {
+	__le32 connection_max_time; /* unused */
+	/* TCP_PROTOCOL_CONFIG_API_S_VER_1 */
+	u8 max_syn_retries;
+	u8 max_data_retries;
+	u8 tcp_syn_ack_timeout;
+	u8 tcp_ack_timeout;
+
+	struct iwl_tcp_packet syn_tx;
+	struct iwl_tcp_packet synack_rx;
+	struct iwl_tcp_packet keepalive_ack_rx;
+	struct iwl_tcp_packet fin_tx;
+
+	struct iwl_remote_wake_packet keepalive_tx;
+	struct iwl_remote_wake_packet wake_rx;
+
+	/* REMOTE_WAKE_OFFSET_INFO_API_S_VER_1 */
+	u8 sequence_number_offset;
+	u8 sequence_number_length;
+	u8 token_offset;
+	u8 token_length;
+	/* REMOTE_WAKE_PROTOCOL_PARAMS_API_S_VER_1 */
+	__le32 initial_sequence_number;
+	__le16 keepalive_interval;
+	__le16 num_tokens;
+	u8 tokens[IWL_WOWLAN_REMOTE_WAKE_MAX_TOKENS];
+} __packed; /* REMOTE_WAKE_CONFIG_API_S_VER_2 */
+
 /* TODO: NetDetect API */
 
 #endif /* __fw_api_d3_h__ */
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-mac.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-mac.h
index ae39b7d..d68640e 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-mac.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-mac.h
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
index be36b76..1270518 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h
index aa3474d..fdd33bc 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h
index 670ac8f..b60d141 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h
index 0acb53d..a30691a8 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h
index 2677914..007a93b 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
@@ -537,6 +537,12 @@ struct iwl_mac_beacon_cmd {
 	struct ieee80211_hdr frame[0];
 } __packed;
 
+struct iwl_beacon_notif {
+	struct iwl_mvm_tx_resp beacon_notify_hdr;
+	__le64 tsf;
+	__le32 ibss_mgr_status;
+} __packed;
+
 /**
  * enum iwl_dump_control - dump (flush) control flags
  * @DUMP_TX_FIFO_FLUSH: Dump MSDUs until the the FIFO is empty
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h
index 2adb61f..1073f26 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
@@ -70,6 +70,7 @@
 #include "fw-api-mac.h"
 #include "fw-api-power.h"
 #include "fw-api-d3.h"
+#include "fw-api-bt-coex.h"
 
 /* queue and FIFO numbers by usage */
 enum {
@@ -150,8 +151,10 @@ enum {
 
 	SET_CALIB_DEFAULT_CMD = 0x8e,
 
+	BEACON_NOTIFICATION = 0x90,
 	BEACON_TEMPLATE_CMD = 0x91,
 	TX_ANT_CONFIGURATION_CMD = 0x98,
+	BT_CONFIG = 0x9b,
 	STATISTICS_NOTIFICATION = 0x9d,
 
 	/* RF-KILL commands and notifications */
@@ -162,6 +165,11 @@ enum {
 	REPLY_RX_MPDU_CMD = 0xc1,
 	BA_NOTIF = 0xc5,
 
+	/* BT Coex */
+	BT_COEX_PRIO_TABLE = 0xcc,
+	BT_COEX_PROT_ENV = 0xcd,
+	BT_PROFILE_NOTIFICATION = 0xce,
+
 	REPLY_DEBUG_CMD = 0xf0,
 	DEBUG_LOG_MSG = 0xf7,
 
@@ -271,38 +279,7 @@ enum {
 	NVM_ACCESS_TARGET_EEPROM = 2,
 };
 
-/**
- * struct iwl_nvm_access_cmd_ver1 - Request the device to send the NVM.
- * @op_code: 0 - read, 1 - write.
- * @target: NVM_ACCESS_TARGET_*. should be 0 for read.
- * @cache_refresh: 0 - None, 1- NVM.
- * @offset: offset in the nvm data.
- * @length: of the chunk.
- * @data: empty on read, the NVM chunk on write
- */
-struct iwl_nvm_access_cmd_ver1 {
-	u8 op_code;
-	u8 target;
-	u8 cache_refresh;
-	u8 reserved;
-	__le16 offset;
-	__le16 length;
-	u8 data[];
-} __packed; /* NVM_ACCESS_CMD_API_S_VER_1 */
-
-/**
- * struct iwl_nvm_access_resp_ver1 - response to NVM_ACCESS_CMD
- * @offset: the offset in the nvm data
- * @length: of the chunk
- * @data: the nvm chunk on when NVM_ACCESS_CMD was read, nothing on write
- */
-struct iwl_nvm_access_resp_ver1 {
-	__le16 offset;
-	__le16 length;
-	u8 data[];
-} __packed; /* NVM_ACCESS_CMD_RESP_API_S_VER_1 */
-
-/* Section types for NVM_ACCESS_CMD version 2 */
+/* Section types for NVM_ACCESS_CMD */
 enum {
 	NVM_SECTION_TYPE_HW = 0,
 	NVM_SECTION_TYPE_SW,
@@ -323,7 +300,7 @@ enum {
  * @length: in bytes, to read/write
  * @data: if write operation, the data to write. On read its empty
  */
-struct iwl_nvm_access_cmd_ver2 {
+struct iwl_nvm_access_cmd {
 	u8 op_code;
 	u8 target;
 	__le16 type;
@@ -340,7 +317,7 @@ struct iwl_nvm_access_cmd_ver2 {
  * @status: 0 for success, fail otherwise
  * @data: if read operation, the data returned. Empty on write.
  */
-struct iwl_nvm_access_resp_ver2 {
+struct iwl_nvm_access_resp {
 	__le16 offset;
 	__le16 length;
 	__le16 type;
@@ -794,6 +771,7 @@ struct iwl_phy_context_cmd {
  * @byte_count: frame's byte-count
  * @frame_time: frame's time on the air, based on byte count and frame rate
  *	calculation
+ * @mac_active_msk: what MACs were active when the frame was received
  *
  * Before each Rx, the device sends this data. It contains PHY information
  * about the reception of the packet.
@@ -811,7 +789,7 @@ struct iwl_rx_phy_info {
 	__le32 non_cfg_phy[IWL_RX_INFO_PHY_CNT];
 	__le32 rate_n_flags;
 	__le32 byte_count;
-	__le16 reserved2;
+	__le16 mac_active_msk;
 	__le16 frame_time;
 } __packed;
 
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw.c b/drivers/net/wireless/iwlwifi/mvm/fw.c
index 500f818..e18c92d 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw.c
+++ b/drivers/net/wireless/iwlwifi/mvm/fw.c
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
@@ -114,7 +114,7 @@ static int iwl_send_tx_ant_cfg(struct iwl_mvm *mvm, u8 valid_tx_ant)
 		.valid = cpu_to_le32(valid_tx_ant),
 	};
 
-	IWL_DEBUG_HC(mvm, "select valid tx ant: %u\n", valid_tx_ant);
+	IWL_DEBUG_FW(mvm, "select valid tx ant: %u\n", valid_tx_ant);
 	return iwl_mvm_send_cmd_pdu(mvm, TX_ANT_CONFIGURATION_CMD, CMD_SYNC,
 				    sizeof(tx_ant_cmd), &tx_ant_cmd);
 }
@@ -134,9 +134,10 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait,
 	alive_data->scd_base_addr = le32_to_cpu(palive->scd_base_ptr);
 
 	alive_data->valid = le16_to_cpu(palive->status) == IWL_ALIVE_STATUS_OK;
-	IWL_DEBUG_FW(mvm, "Alive ucode status 0x%04x revision 0x%01X 0x%01X\n",
+	IWL_DEBUG_FW(mvm,
+		     "Alive ucode status 0x%04x revision 0x%01X 0x%01X flags 0x%01X\n",
 		     le16_to_cpu(palive->status), palive->ver_type,
-		     palive->ver_subtype);
+		     palive->ver_subtype, palive->flags);
 
 	return true;
 }
@@ -309,6 +310,10 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
 		goto error;
 	}
 
+	ret = iwl_send_bt_prio_tbl(mvm);
+	if (ret)
+		goto error;
+
 	if (read_nvm) {
 		/* Read nvm */
 		ret = iwl_nvm_init(mvm);
@@ -322,16 +327,14 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
 	WARN_ON(ret);
 
 	/* Send TX valid antennas before triggering calibrations */
-	ret = iwl_send_tx_ant_cfg(mvm, mvm->nvm_data->valid_tx_ant);
+	ret = iwl_send_tx_ant_cfg(mvm, iwl_fw_valid_tx_ant(mvm->fw));
 	if (ret)
 		goto error;
 
-	/* WkP doesn't have all calibrations, need to set default values */
-	if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) {
-		ret = iwl_set_default_calibrations(mvm);
-		if (ret)
-			goto error;
-	}
+	/* need to set default values */
+	ret = iwl_set_default_calibrations(mvm);
+	if (ret)
+		goto error;
 
 	/*
 	 * Send phy configurations command to init uCode
@@ -410,7 +413,15 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
 		goto error;
 	}
 
-	ret = iwl_send_tx_ant_cfg(mvm, mvm->nvm_data->valid_tx_ant);
+	ret = iwl_send_tx_ant_cfg(mvm, iwl_fw_valid_tx_ant(mvm->fw));
+	if (ret)
+		goto error;
+
+	ret = iwl_send_bt_prio_tbl(mvm);
+	if (ret)
+		goto error;
+
+	ret = iwl_send_bt_init_conf(mvm);
 	if (ret)
 		goto error;
 
@@ -456,7 +467,7 @@ int iwl_mvm_load_d3_fw(struct iwl_mvm *mvm)
 		goto error;
 	}
 
-	ret = iwl_send_tx_ant_cfg(mvm, mvm->nvm_data->valid_tx_ant);
+	ret = iwl_send_tx_ant_cfg(mvm, iwl_fw_valid_tx_ant(mvm->fw));
 	if (ret)
 		goto error;
 
diff --git a/drivers/net/wireless/iwlwifi/mvm/led.c b/drivers/net/wireless/iwlwifi/mvm/led.c
index 011906e..2269a9e 100644
--- a/drivers/net/wireless/iwlwifi/mvm/led.c
+++ b/drivers/net/wireless/iwlwifi/mvm/led.c
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
index 341dbc0..86e312a 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
@@ -196,7 +196,7 @@ u32 iwl_mvm_mac_get_queues_mask(struct iwl_mvm *mvm,
 	u32 qmask, ac;
 
 	if (vif->type == NL80211_IFTYPE_P2P_DEVICE)
-		return BIT(IWL_OFFCHANNEL_QUEUE);
+		return BIT(IWL_MVM_OFFCHANNEL_QUEUE);
 
 	qmask = (vif->cab_queue != IEEE80211_INVAL_HW_QUEUE) ?
 		BIT(vif->cab_queue) : 0;
@@ -553,9 +553,9 @@ static void iwl_mvm_mac_ctxt_cmd_common(struct iwl_mvm *mvm,
 	if (vif->bss_conf.qos)
 		cmd->qos_flags |= cpu_to_le32(MAC_QOS_FLG_UPDATE_EDCA);
 
+	/* Don't use cts to self as the fw doesn't support it currently. */
 	if (vif->bss_conf.use_cts_prot)
-		cmd->protection_flags |= cpu_to_le32(MAC_PROT_FLG_TGG_PROTECT |
-						     MAC_PROT_FLG_SELF_CTS_EN);
+		cmd->protection_flags |= cpu_to_le32(MAC_PROT_FLG_TGG_PROTECT);
 
 	/*
 	 * I think that we should enable these 2 flags regardless the HT PROT
@@ -651,6 +651,13 @@ static int iwl_mvm_mac_ctxt_cmd_station(struct iwl_mvm *mvm,
 	/* Fill the common data for all mac context types */
 	iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action);
 
+	/* Allow beacons to pass through as long as we are not associated,or we
+	 * do not have dtim period information */
+	if (!vif->bss_conf.assoc || !vif->bss_conf.dtim_period)
+		cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_BEACON);
+	else
+		cmd.filter_flags &= ~cpu_to_le32(MAC_FILTER_IN_BEACON);
+
 	/* Fill the data specific for station mode */
 	iwl_mvm_mac_ctxt_cmd_fill_sta(mvm, vif, &cmd.sta);
 
@@ -685,7 +692,12 @@ static int iwl_mvm_mac_ctxt_cmd_listener(struct iwl_mvm *mvm,
 	WARN_ON(vif->type != NL80211_IFTYPE_MONITOR);
 
 	iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action);
-	/* No other data to be filled */
+
+	cmd.filter_flags = cpu_to_le32(MAC_FILTER_IN_PROMISC |
+				       MAC_FILTER_IN_CONTROL_AND_MGMT |
+				       MAC_FILTER_IN_BEACON |
+				       MAC_FILTER_IN_PROBE_REQUEST);
+
 	return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
 }
 
@@ -714,7 +726,9 @@ static int iwl_mvm_mac_ctxt_cmd_p2p_device(struct iwl_mvm *mvm,
 	iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action);
 
 	cmd.protection_flags |= cpu_to_le32(MAC_PROT_FLG_TGG_PROTECT);
-	cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROMISC);
+
+	/* Override the filter flags to accept only probe requests */
+	cmd.filter_flags = cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST);
 
 	/*
 	 * This flag should be set to true when the P2P Device is
@@ -789,7 +803,7 @@ static int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm,
 					     TX_CMD_FLG_TSF);
 
 	mvm->mgmt_last_antenna_idx =
-		iwl_mvm_next_antenna(mvm, mvm->nvm_data->valid_tx_ant,
+		iwl_mvm_next_antenna(mvm, iwl_fw_valid_tx_ant(mvm->fw),
 				     mvm->mgmt_last_antenna_idx);
 
 	beacon_cmd.tx.rate_n_flags =
@@ -846,10 +860,10 @@ int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm,
  */
 static void iwl_mvm_mac_ctxt_cmd_fill_ap(struct iwl_mvm *mvm,
 					 struct ieee80211_vif *vif,
-					 struct iwl_mac_data_ap *ctxt_ap)
+					 struct iwl_mac_data_ap *ctxt_ap,
+					 bool add)
 {
 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
-	u32 curr_dev_time;
 
 	ctxt_ap->bi = cpu_to_le32(vif->bss_conf.beacon_int);
 	ctxt_ap->bi_reciprocal =
@@ -861,10 +875,19 @@ static void iwl_mvm_mac_ctxt_cmd_fill_ap(struct iwl_mvm *mvm,
 					       vif->bss_conf.dtim_period));
 
 	ctxt_ap->mcast_qid = cpu_to_le32(vif->cab_queue);
-	curr_dev_time = iwl_read_prph(mvm->trans, DEVICE_SYSTEM_TIME_REG);
-	ctxt_ap->beacon_time = cpu_to_le32(curr_dev_time);
 
-	ctxt_ap->beacon_tsf = cpu_to_le64(curr_dev_time);
+	/*
+	 * Only read the system time when the MAC is being added, when we
+	 * just modify the MAC then we should keep the time -- the firmware
+	 * can otherwise have a "jumping" TBTT.
+	 */
+	if (add)
+		mvmvif->ap_beacon_time =
+			iwl_read_prph(mvm->trans, DEVICE_SYSTEM_TIME_REG);
+
+	ctxt_ap->beacon_time = cpu_to_le32(mvmvif->ap_beacon_time);
+
+	ctxt_ap->beacon_tsf = 0; /* unused */
 
 	/* TODO: Assume that the beacon id == mac context id */
 	ctxt_ap->beacon_template = cpu_to_le32(mvmvif->id);
@@ -881,8 +904,12 @@ static int iwl_mvm_mac_ctxt_cmd_ap(struct iwl_mvm *mvm,
 	/* Fill the common data for all mac context types */
 	iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action);
 
+	/* Also enable probe requests to pass */
+	cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST);
+
 	/* Fill the data specific for ap mode */
-	iwl_mvm_mac_ctxt_cmd_fill_ap(mvm, vif, &cmd.ap);
+	iwl_mvm_mac_ctxt_cmd_fill_ap(mvm, vif, &cmd.ap,
+				     action == FW_CTXT_ACTION_ADD);
 
 	return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
 }
@@ -899,7 +926,8 @@ static int iwl_mvm_mac_ctxt_cmd_go(struct iwl_mvm *mvm,
 	iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action);
 
 	/* Fill the data specific for GO mode */
-	iwl_mvm_mac_ctxt_cmd_fill_ap(mvm, vif, &cmd.go.ap);
+	iwl_mvm_mac_ctxt_cmd_fill_ap(mvm, vif, &cmd.go.ap,
+				     action == FW_CTXT_ACTION_ADD);
 
 	cmd.go.ctwin = cpu_to_le32(vif->bss_conf.p2p_ctwindow);
 	cmd.go.opp_ps_enabled = cpu_to_le32(!!vif->bss_conf.p2p_oppps);
@@ -990,3 +1018,22 @@ int iwl_mvm_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
 	mvmvif->uploaded = false;
 	return 0;
 }
+
+int iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm,
+			    struct iwl_rx_cmd_buffer *rxb,
+			    struct iwl_device_cmd *cmd)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	struct iwl_beacon_notif *beacon = (void *)pkt->data;
+	u16 status __maybe_unused =
+		le16_to_cpu(beacon->beacon_notify_hdr.status.status);
+	u32 rate __maybe_unused =
+		le32_to_cpu(beacon->beacon_notify_hdr.initial_rate);
+
+	IWL_DEBUG_RX(mvm, "beacon status %#x retries:%d tsf:0x%16llX rate:%d\n",
+		     status & TX_STATUS_MSK,
+		     beacon->beacon_notify_hdr.failure_frame,
+		     le64_to_cpu(beacon->tsf),
+		     rate);
+	return 0;
+}
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
index 7e169b0..3d193f8 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
@@ -65,7 +65,9 @@
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
+#include <linux/ip.h>
 #include <net/mac80211.h>
+#include <net/tcp.h>
 
 #include "iwl-op-mode.h"
 #include "iwl-io.h"
@@ -102,10 +104,33 @@ static const struct ieee80211_iface_combination iwl_mvm_iface_combinations[] = {
 	},
 };
 
+#ifdef CONFIG_PM_SLEEP
+static const struct nl80211_wowlan_tcp_data_token_feature
+iwl_mvm_wowlan_tcp_token_feature = {
+	.min_len = 0,
+	.max_len = 255,
+	.bufsize = IWL_WOWLAN_REMOTE_WAKE_MAX_TOKENS,
+};
+
+static const struct wiphy_wowlan_tcp_support iwl_mvm_wowlan_tcp_support = {
+	.tok = &iwl_mvm_wowlan_tcp_token_feature,
+	.data_payload_max = IWL_WOWLAN_TCP_MAX_PACKET_LEN -
+			    sizeof(struct ethhdr) -
+			    sizeof(struct iphdr) -
+			    sizeof(struct tcphdr),
+	.data_interval_max = 65535, /* __le16 in API */
+	.wake_payload_max = IWL_WOWLAN_REMOTE_WAKE_MAX_PACKET_LEN -
+			    sizeof(struct ethhdr) -
+			    sizeof(struct iphdr) -
+			    sizeof(struct tcphdr),
+	.seq = true,
+};
+#endif
+
 int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
 {
 	struct ieee80211_hw *hw = mvm->hw;
-	int num_mac, ret;
+	int num_mac, ret, i;
 
 	/* Tell mac80211 our characteristics */
 	hw->flags = IEEE80211_HW_SIGNAL_DBM |
@@ -118,8 +143,8 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
 		    IEEE80211_HW_AMPDU_AGGREGATION |
 		    IEEE80211_HW_TIMING_BEACON_ONLY;
 
-	hw->queues = IWL_FIRST_AMPDU_QUEUE;
-	hw->offchannel_tx_hw_queue = IWL_OFFCHANNEL_QUEUE;
+	hw->queues = IWL_MVM_FIRST_AGG_QUEUE;
+	hw->offchannel_tx_hw_queue = IWL_MVM_OFFCHANNEL_QUEUE;
 	hw->rate_control_algorithm = "iwl-mvm-rs";
 
 	/*
@@ -149,18 +174,22 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
 	hw->wiphy->n_iface_combinations =
 		ARRAY_SIZE(iwl_mvm_iface_combinations);
 
-	hw->wiphy->max_remain_on_channel_duration = 500;
+	hw->wiphy->max_remain_on_channel_duration = 10000;
 	hw->max_listen_interval = IWL_CONN_MAX_LISTEN_INTERVAL;
 
 	/* Extract MAC address */
 	memcpy(mvm->addresses[0].addr, mvm->nvm_data->hw_addr, ETH_ALEN);
 	hw->wiphy->addresses = mvm->addresses;
 	hw->wiphy->n_addresses = 1;
-	num_mac = mvm->nvm_data->n_hw_addrs;
-	if (num_mac > 1) {
-		memcpy(mvm->addresses[1].addr, mvm->addresses[0].addr,
+
+	/* Extract additional MAC addresses if available */
+	num_mac = (mvm->nvm_data->n_hw_addrs > 1) ?
+		min(IWL_MVM_MAX_ADDRESSES, mvm->nvm_data->n_hw_addrs) : 1;
+
+	for (i = 1; i < num_mac; i++) {
+		memcpy(mvm->addresses[i].addr, mvm->addresses[i-1].addr,
 		       ETH_ALEN);
-		mvm->addresses[1].addr[5]++;
+		mvm->addresses[i].addr[5]++;
 		hw->wiphy->n_addresses++;
 	}
 
@@ -206,6 +235,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
 		hw->wiphy->wowlan.n_patterns = IWL_WOWLAN_MAX_PATTERNS;
 		hw->wiphy->wowlan.pattern_min_len = IWL_WOWLAN_MIN_PATTERN_LEN;
 		hw->wiphy->wowlan.pattern_max_len = IWL_WOWLAN_MAX_PATTERN_LEN;
+		hw->wiphy->wowlan.tcp = &iwl_mvm_wowlan_tcp_support;
 	}
 #endif
 
@@ -227,7 +257,7 @@ static void iwl_mvm_mac_tx(struct ieee80211_hw *hw,
 		goto drop;
 	}
 
-	if (IEEE80211_SKB_CB(skb)->hw_queue == IWL_OFFCHANNEL_QUEUE &&
+	if (IEEE80211_SKB_CB(skb)->hw_queue == IWL_MVM_OFFCHANNEL_QUEUE &&
 	    !test_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status))
 		goto drop;
 
@@ -273,12 +303,18 @@ static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw,
 		ret = iwl_mvm_sta_rx_agg(mvm, sta, tid, 0, false);
 		break;
 	case IEEE80211_AMPDU_TX_START:
+		if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_TXAGG) {
+			ret = -EINVAL;
+			break;
+		}
 		ret = iwl_mvm_sta_tx_agg_start(mvm, vif, sta, tid, ssn);
 		break;
 	case IEEE80211_AMPDU_TX_STOP_CONT:
+		ret = iwl_mvm_sta_tx_agg_stop(mvm, vif, sta, tid);
+		break;
 	case IEEE80211_AMPDU_TX_STOP_FLUSH:
 	case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
-		ret = iwl_mvm_sta_tx_agg_stop(mvm, vif, sta, tid);
+		ret = iwl_mvm_sta_tx_agg_flush(mvm, vif, sta, tid);
 		break;
 	case IEEE80211_AMPDU_TX_OPERATIONAL:
 		ret = iwl_mvm_sta_tx_agg_oper(mvm, vif, sta, tid, buf_size);
@@ -1051,6 +1087,13 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
 
 	switch (cmd) {
 	case SET_KEY:
+		if (vif->type == NL80211_IFTYPE_AP && !sta) {
+			/* GTK on AP interface is a TX-only key, return 0 */
+			ret = 0;
+			key->hw_key_idx = STA_KEY_IDX_INVALID;
+			break;
+		}
+
 		IWL_DEBUG_MAC80211(mvm, "set hwcrypto key\n");
 		ret = iwl_mvm_set_sta_key(mvm, vif, sta, key, false);
 		if (ret) {
@@ -1059,11 +1102,17 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
 			 * can't add key for RX, but we don't need it
 			 * in the device for TX so still return 0
 			 */
+			key->hw_key_idx = STA_KEY_IDX_INVALID;
 			ret = 0;
 		}
 
 		break;
 	case DISABLE_KEY:
+		if (key->hw_key_idx == STA_KEY_IDX_INVALID) {
+			ret = 0;
+			break;
+		}
+
 		IWL_DEBUG_MAC80211(mvm, "disable hwcrypto key\n");
 		ret = iwl_mvm_remove_sta_key(mvm, vif, sta, key);
 		break;
@@ -1090,7 +1139,8 @@ static void iwl_mvm_mac_update_tkip_key(struct ieee80211_hw *hw,
 static int iwl_mvm_roc(struct ieee80211_hw *hw,
 		       struct ieee80211_vif *vif,
 		       struct ieee80211_channel *channel,
-		       int duration)
+		       int duration,
+		       enum ieee80211_roc_type type)
 {
 	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
 	struct cfg80211_chan_def chandef;
@@ -1101,8 +1151,8 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw,
 		return -EINVAL;
 	}
 
-	IWL_DEBUG_MAC80211(mvm, "enter (%d, %d)\n", channel->hw_value,
-			   duration);
+	IWL_DEBUG_MAC80211(mvm, "enter (%d, %d, %d)\n", channel->hw_value,
+			   duration, type);
 
 	mutex_lock(&mvm->mutex);
 
@@ -1111,7 +1161,7 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw,
 				       &chandef, 1, 1);
 
 	/* Schedule the time events */
-	ret = iwl_mvm_start_p2p_roc(mvm, vif, duration);
+	ret = iwl_mvm_start_p2p_roc(mvm, vif, duration, type);
 
 	mutex_unlock(&mvm->mutex);
 	IWL_DEBUG_MAC80211(mvm, "leave\n");
@@ -1215,6 +1265,7 @@ static int iwl_mvm_assign_vif_chanctx(struct ieee80211_hw *hw,
 	 * will handle quota settings.
 	 */
 	if (vif->type == NL80211_IFTYPE_MONITOR) {
+		mvmvif->monitor_active = true;
 		ret = iwl_mvm_update_quotas(mvm, vif);
 		if (ret)
 			goto out_remove_binding;
@@ -1245,15 +1296,16 @@ static void iwl_mvm_unassign_vif_chanctx(struct ieee80211_hw *hw,
 	if (vif->type == NL80211_IFTYPE_AP)
 		goto out_unlock;
 
-	iwl_mvm_binding_remove_vif(mvm, vif);
 	switch (vif->type) {
 	case NL80211_IFTYPE_MONITOR:
-		iwl_mvm_update_quotas(mvm, vif);
+		mvmvif->monitor_active = false;
+		iwl_mvm_update_quotas(mvm, NULL);
 		break;
 	default:
 		break;
 	}
 
+	iwl_mvm_binding_remove_vif(mvm, vif);
 out_unlock:
 	mvmvif->phy_ctxt = NULL;
 	mutex_unlock(&mvm->mutex);
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h
index bdae700..53d5896 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
@@ -79,7 +79,7 @@
 #include "fw-api.h"
 
 #define IWL_INVALID_MAC80211_QUEUE	0xff
-#define IWL_MVM_MAX_ADDRESSES		2
+#define IWL_MVM_MAX_ADDRESSES		5
 /* RSSI offset for WkP */
 #define IWL_RSSI_OFFSET 50
 
@@ -90,10 +90,6 @@ enum iwl_mvm_tx_fifo {
 	IWL_MVM_TX_FIFO_VO,
 };
 
-/* Placeholder */
-#define IWL_OFFCHANNEL_QUEUE 8
-#define IWL_FIRST_AMPDU_QUEUE 11
-
 extern struct ieee80211_ops iwl_mvm_hw_ops;
 /**
  * struct iwl_mvm_mod_params - module parameters for iwlmvm
@@ -161,6 +157,8 @@ enum iwl_power_scheme {
  * @uploaded: indicates the MAC context has been added to the device
  * @ap_active: indicates that ap context is configured, and that the interface
  *  should get quota etc.
+ * @monitor_active: indicates that monitor context is configured, and that the
+ * interface should get quota etc.
  * @queue_params: QoS params for this MAC
  * @bcast_sta: station used for broadcast packets. Used by the following
  *  vifs: P2P_DEVICE, GO and AP.
@@ -173,6 +171,9 @@ struct iwl_mvm_vif {
 
 	bool uploaded;
 	bool ap_active;
+	bool monitor_active;
+
+	u32 ap_beacon_time;
 
 	enum iwl_tsf_id tsf_id;
 
@@ -279,10 +280,7 @@ struct iwl_mvm {
 	atomic_t queue_stop_count[IWL_MAX_HW_QUEUES];
 
 	struct iwl_nvm_data *nvm_data;
-	/* eeprom blob for debugfs/testmode */
-	u8 *eeprom_blob;
-	size_t eeprom_blob_size;
-	/* NVM sections for 7000 family */
+	/* NVM sections */
 	struct iwl_nvm_section nvm_sections[NVM_NUM_OF_SECTIONS];
 
 	/* EEPROM MAC addresses */
@@ -332,6 +330,10 @@ struct iwl_mvm {
 #ifdef CONFIG_PM_SLEEP
 	int gtk_ivlen, gtk_icvlen, ptk_ivlen, ptk_icvlen;
 #endif
+
+	/* BT-Coex */
+	u8 bt_kill_msk;
+	struct iwl_bt_coex_profile_notif last_bt_notif;
 };
 
 /* Extract MVM priv from op_mode and _hw */
@@ -445,6 +447,9 @@ u32 iwl_mvm_mac_get_queues_mask(struct iwl_mvm *mvm,
 				struct ieee80211_vif *vif);
 int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm,
 				    struct ieee80211_vif *vif);
+int iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm,
+			    struct iwl_rx_cmd_buffer *rxb,
+			    struct iwl_device_cmd *cmd);
 
 /* Bindings */
 int iwl_mvm_binding_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
@@ -502,4 +507,11 @@ void iwl_mvm_ipv6_addr_change(struct ieee80211_hw *hw,
 void iwl_mvm_set_default_unicast_key(struct ieee80211_hw *hw,
 				     struct ieee80211_vif *vif, int idx);
 
+/* BT Coex */
+int iwl_send_bt_prio_tbl(struct iwl_mvm *mvm);
+int iwl_send_bt_init_conf(struct iwl_mvm *mvm);
+int iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm,
+			     struct iwl_rx_cmd_buffer *rxb,
+			     struct iwl_device_cmd *cmd);
+
 #endif /* __IWL_MVM_H__ */
diff --git a/drivers/net/wireless/iwlwifi/mvm/nvm.c b/drivers/net/wireless/iwlwifi/mvm/nvm.c
index 20016bc..b8ec02f 100644
--- a/drivers/net/wireless/iwlwifi/mvm/nvm.c
+++ b/drivers/net/wireless/iwlwifi/mvm/nvm.c
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
@@ -74,26 +74,11 @@ static const int nvm_to_read[] = {
 	NVM_SECTION_TYPE_PRODUCTION,
 };
 
-/* used to simplify the shared operations on NCM_ACCESS_CMD versions */
-union iwl_nvm_access_cmd {
-	struct iwl_nvm_access_cmd_ver1 ver1;
-	struct iwl_nvm_access_cmd_ver2 ver2;
-};
-union iwl_nvm_access_resp {
-	struct iwl_nvm_access_resp_ver1 ver1;
-	struct iwl_nvm_access_resp_ver2 ver2;
-};
-
-static inline void iwl_nvm_fill_read_ver1(struct iwl_nvm_access_cmd_ver1 *cmd,
-					  u16 offset, u16 length)
-{
-	cmd->offset = cpu_to_le16(offset);
-	cmd->length = cpu_to_le16(length);
-	cmd->cache_refresh = 1;
-}
+/* Default NVM size to read */
+#define IWL_NVM_DEFAULT_CHUNK_SIZE (2*1024);
 
-static inline void iwl_nvm_fill_read_ver2(struct iwl_nvm_access_cmd_ver2 *cmd,
-					  u16 offset, u16 length, u16 section)
+static inline void iwl_nvm_fill_read(struct iwl_nvm_access_cmd *cmd,
+				     u16 offset, u16 length, u16 section)
 {
 	cmd->offset = cpu_to_le16(offset);
 	cmd->length = cpu_to_le16(length);
@@ -103,8 +88,8 @@ static inline void iwl_nvm_fill_read_ver2(struct iwl_nvm_access_cmd_ver2 *cmd,
 static int iwl_nvm_read_chunk(struct iwl_mvm *mvm, u16 section,
 			      u16 offset, u16 length, u8 *data)
 {
-	union iwl_nvm_access_cmd nvm_access_cmd;
-	union iwl_nvm_access_resp *nvm_resp;
+	struct iwl_nvm_access_cmd nvm_access_cmd = {};
+	struct iwl_nvm_access_resp *nvm_resp;
 	struct iwl_rx_packet *pkt;
 	struct iwl_host_cmd cmd = {
 		.id = NVM_ACCESS_CMD,
@@ -114,18 +99,8 @@ static int iwl_nvm_read_chunk(struct iwl_mvm *mvm, u16 section,
 	int ret, bytes_read, offset_read;
 	u8 *resp_data;
 
-	memset(&nvm_access_cmd, 0, sizeof(nvm_access_cmd));
-
-	/* TODO: not sure family should be the decider, maybe FW version? */
-	if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) {
-		iwl_nvm_fill_read_ver2(&(nvm_access_cmd.ver2),
-				       offset, length, section);
-		cmd.len[0] = sizeof(struct iwl_nvm_access_cmd_ver2);
-	} else {
-		iwl_nvm_fill_read_ver1(&(nvm_access_cmd.ver1),
-				       offset, length);
-		cmd.len[0] = sizeof(struct iwl_nvm_access_cmd_ver1);
-	}
+	iwl_nvm_fill_read(&nvm_access_cmd, offset, length, section);
+	cmd.len[0] = sizeof(struct iwl_nvm_access_cmd);
 
 	ret = iwl_mvm_send_cmd(mvm, &cmd);
 	if (ret)
@@ -141,17 +116,10 @@ static int iwl_nvm_read_chunk(struct iwl_mvm *mvm, u16 section,
 
 	/* Extract NVM response */
 	nvm_resp = (void *)pkt->data;
-	if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) {
-		ret = le16_to_cpu(nvm_resp->ver2.status);
-		bytes_read = le16_to_cpu(nvm_resp->ver2.length);
-		offset_read = le16_to_cpu(nvm_resp->ver2.offset);
-		resp_data = nvm_resp->ver2.data;
-	} else {
-		ret = le16_to_cpu(nvm_resp->ver1.length) <= 0;
-		bytes_read = le16_to_cpu(nvm_resp->ver1.length);
-		offset_read = le16_to_cpu(nvm_resp->ver1.offset);
-		resp_data = nvm_resp->ver1.data;
-	}
+	ret = le16_to_cpu(nvm_resp->status);
+	bytes_read = le16_to_cpu(nvm_resp->length);
+	offset_read = le16_to_cpu(nvm_resp->offset);
+	resp_data = nvm_resp->data;
 	if (ret) {
 		IWL_ERR(mvm,
 			"NVM access command failed with status %d (device: %s)\n",
@@ -191,17 +159,10 @@ static int iwl_nvm_read_section(struct iwl_mvm *mvm, u16 section,
 {
 	u16 length, offset = 0;
 	int ret;
-	bool old_eeprom = mvm->cfg->device_family != IWL_DEVICE_FAMILY_7000;
 
-	length = (iwlwifi_mod_params.amsdu_size_8K ? (8 * 1024) : (4 * 1024))
-		- sizeof(union iwl_nvm_access_cmd)
-		- sizeof(struct iwl_rx_packet);
-	/*
-	 * if length is greater than EEPROM size, truncate it because uCode
-	 * doesn't check it by itself, and exit the loop when reached.
-	 */
-	if (old_eeprom && length > mvm->cfg->base_params->eeprom_size)
-		length = mvm->cfg->base_params->eeprom_size;
+	/* Set nvm section read length */
+	length = IWL_NVM_DEFAULT_CHUNK_SIZE;
+
 	ret = length;
 
 	/* Read the NVM until exhausted (reading less than requested) */
@@ -214,8 +175,6 @@ static int iwl_nvm_read_section(struct iwl_mvm *mvm, u16 section,
 			return ret;
 		}
 		offset += ret;
-		if (old_eeprom && offset == mvm->cfg->base_params->eeprom_size)
-			break;
 	}
 
 	IWL_INFO(mvm, "NVM section %d read completed\n", section);
@@ -249,63 +208,31 @@ int iwl_nvm_init(struct iwl_mvm *mvm)
 	int ret, i, section;
 	u8 *nvm_buffer, *temp;
 
-	if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) {
-		/* TODO: find correct NVM max size for a section */
-		nvm_buffer = kmalloc(mvm->cfg->base_params->eeprom_size,
-				     GFP_KERNEL);
-		if (!nvm_buffer)
-			return -ENOMEM;
-		for (i = 0; i < ARRAY_SIZE(nvm_to_read); i++) {
-			section = nvm_to_read[i];
-			/* we override the constness for initial read */
-			ret = iwl_nvm_read_section(mvm, section, nvm_buffer);
-			if (ret < 0)
-				break;
-			temp = kmemdup(nvm_buffer, ret, GFP_KERNEL);
-			if (!temp) {
-				ret = -ENOMEM;
-				break;
-			}
-			mvm->nvm_sections[section].data = temp;
-			mvm->nvm_sections[section].length = ret;
-		}
-		kfree(nvm_buffer);
+	/* TODO: find correct NVM max size for a section */
+	nvm_buffer = kmalloc(mvm->cfg->base_params->eeprom_size,
+			     GFP_KERNEL);
+	if (!nvm_buffer)
+		return -ENOMEM;
+	for (i = 0; i < ARRAY_SIZE(nvm_to_read); i++) {
+		section = nvm_to_read[i];
+		/* we override the constness for initial read */
+		ret = iwl_nvm_read_section(mvm, section, nvm_buffer);
 		if (ret < 0)
-			return ret;
-	} else {
-		/* allocate eeprom */
-		mvm->eeprom_blob_size = mvm->cfg->base_params->eeprom_size;
-		IWL_DEBUG_EEPROM(mvm->trans->dev, "NVM size = %zd\n",
-				 mvm->eeprom_blob_size);
-		mvm->eeprom_blob = kzalloc(mvm->eeprom_blob_size, GFP_KERNEL);
-		if (!mvm->eeprom_blob)
-			return -ENOMEM;
-
-		ret = iwl_nvm_read_section(mvm, 0, mvm->eeprom_blob);
-		if (ret != mvm->eeprom_blob_size) {
-			IWL_ERR(mvm, "Read partial NVM %d/%zd\n",
-				ret, mvm->eeprom_blob_size);
-			kfree(mvm->eeprom_blob);
-			mvm->eeprom_blob = NULL;
-			return -EINVAL;
+			break;
+		temp = kmemdup(nvm_buffer, ret, GFP_KERNEL);
+		if (!temp) {
+			ret = -ENOMEM;
+			break;
 		}
+		mvm->nvm_sections[section].data = temp;
+		mvm->nvm_sections[section].length = ret;
 	}
+	kfree(nvm_buffer);
+	if (ret < 0)
+		return ret;
 
 	ret = 0;
-	if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000)
-		mvm->nvm_data = iwl_parse_nvm_sections(mvm);
-	else
-		mvm->nvm_data =
-			iwl_parse_eeprom_data(mvm->trans->dev,
-					      mvm->cfg,
-					      mvm->eeprom_blob,
-					      mvm->eeprom_blob_size);
-
-	if (!mvm->nvm_data) {
-		kfree(mvm->eeprom_blob);
-		mvm->eeprom_blob = NULL;
-		ret = -ENOMEM;
-	}
+	mvm->nvm_data = iwl_parse_nvm_sections(mvm);
 
 	return ret;
 }
diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c
index d0f9c1e..fe031d3 100644
--- a/drivers/net/wireless/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/iwlwifi/mvm/ops.c
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
@@ -143,21 +143,12 @@ static void iwl_mvm_nic_config(struct iwl_op_mode *op_mode)
 	u8 radio_cfg_type, radio_cfg_step, radio_cfg_dash;
 	u32 reg_val = 0;
 
-	/*
-	 * We can't upload the correct value to the INIT image
-	 * as we don't have nvm_data by that time.
-	 *
-	 * TODO: Figure out what we should do here
-	 */
-	if (mvm->nvm_data) {
-		radio_cfg_type = mvm->nvm_data->radio_cfg_type;
-		radio_cfg_step = mvm->nvm_data->radio_cfg_step;
-		radio_cfg_dash = mvm->nvm_data->radio_cfg_dash;
-	} else {
-		radio_cfg_type = 0;
-		radio_cfg_step = 0;
-		radio_cfg_dash = 0;
-	}
+	radio_cfg_type = (mvm->fw->phy_config & FW_PHY_CFG_RADIO_TYPE) >>
+			  FW_PHY_CFG_RADIO_TYPE_POS;
+	radio_cfg_step = (mvm->fw->phy_config & FW_PHY_CFG_RADIO_STEP) >>
+			  FW_PHY_CFG_RADIO_STEP_POS;
+	radio_cfg_dash = (mvm->fw->phy_config & FW_PHY_CFG_RADIO_DASH) >>
+			  FW_PHY_CFG_RADIO_DASH_POS;
 
 	/* SKU control */
 	reg_val |= CSR_HW_REV_STEP(mvm->trans->hw_rev) <<
@@ -175,7 +166,6 @@ static void iwl_mvm_nic_config(struct iwl_op_mode *op_mode)
 
 	/* silicon bits */
 	reg_val |= CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI;
-	reg_val |= CSR_HW_IF_CONFIG_REG_BIT_MAC_SI;
 
 	iwl_trans_set_bits_mask(mvm->trans, CSR_HW_IF_CONFIG_REG,
 				CSR_HW_IF_CONFIG_REG_MSK_MAC_DASH |
@@ -230,6 +220,9 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = {
 	RX_HANDLER(SCAN_REQUEST_CMD, iwl_mvm_rx_scan_response, false),
 	RX_HANDLER(SCAN_COMPLETE_NOTIFICATION, iwl_mvm_rx_scan_complete, false),
 
+	RX_HANDLER(BT_PROFILE_NOTIFICATION, iwl_mvm_rx_bt_coex_notif, true),
+	RX_HANDLER(BEACON_NOTIFICATION, iwl_mvm_rx_beacon_notif, false),
+
 	RX_HANDLER(RADIO_VERSION_NOTIFICATION, iwl_mvm_rx_radio_ver, false),
 	RX_HANDLER(CARD_STATE_NOTIFICATION, iwl_mvm_rx_card_state_notif, false),
 
@@ -274,6 +267,7 @@ static const char *iwl_mvm_cmd_strings[REPLY_MAX] = {
 	CMD(WEP_KEY),
 	CMD(REPLY_RX_PHY_CMD),
 	CMD(REPLY_RX_MPDU_CMD),
+	CMD(BEACON_NOTIFICATION),
 	CMD(BEACON_TEMPLATE_CMD),
 	CMD(STATISTICS_NOTIFICATION),
 	CMD(TX_ANT_CONFIGURATION_CMD),
@@ -293,6 +287,11 @@ static const char *iwl_mvm_cmd_strings[REPLY_MAX] = {
 	CMD(NET_DETECT_PROFILES_CMD),
 	CMD(NET_DETECT_HOTSPOTS_CMD),
 	CMD(NET_DETECT_HOTSPOTS_QUERY_CMD),
+	CMD(CARD_STATE_NOTIFICATION),
+	CMD(BT_COEX_PRIO_TABLE),
+	CMD(BT_COEX_PROT_ENV),
+	CMD(BT_PROFILE_NOTIFICATION),
+	CMD(BT_CONFIG),
 };
 #undef CMD
 
@@ -312,16 +311,6 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
 	};
 	int err, scan_size;
 
-	switch (cfg->device_family) {
-	case IWL_DEVICE_FAMILY_6030:
-	case IWL_DEVICE_FAMILY_6005:
-	case IWL_DEVICE_FAMILY_7000:
-		break;
-	default:
-		IWL_ERR(trans, "Trying to load mvm on an unsupported device\n");
-		return NULL;
-	}
-
 	/********************************
 	 * 1. Allocating and configuring HW data
 	 ********************************/
@@ -363,8 +352,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
 	trans_cfg.n_no_reclaim_cmds = ARRAY_SIZE(no_reclaim_cmds);
 	trans_cfg.rx_buf_size_8k = iwlwifi_mod_params.amsdu_size_8K;
 
-	/* TODO: this should really be a TLV */
-	if (cfg->device_family == IWL_DEVICE_FAMILY_7000)
+	if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_DW_BC_TABLE)
 		trans_cfg.bc_table_dword = true;
 
 	if (!iwlwifi_mod_params.wd_disable)
@@ -438,7 +426,6 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
  out_free:
 	iwl_phy_db_free(mvm->phy_db);
 	kfree(mvm->scan_cmd);
-	kfree(mvm->eeprom_blob);
 	iwl_trans_stop_hw(trans, true);
 	ieee80211_free_hw(mvm->hw);
 	return NULL;
@@ -460,7 +447,6 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode)
 	iwl_phy_db_free(mvm->phy_db);
 	mvm->phy_db = NULL;
 
-	kfree(mvm->eeprom_blob);
 	iwl_free_nvm_data(mvm->nvm_data);
 	for (i = 0; i < NVM_NUM_OF_SECTIONS; i++)
 		kfree(mvm->nvm_sections[i].data);
diff --git a/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c
index b428448..0f0b44e 100644
--- a/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c
+++ b/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
@@ -142,7 +142,7 @@ static void iwl_mvm_phy_ctxt_cmd_data(struct iwl_mvm *mvm,
 				      struct cfg80211_chan_def *chandef,
 				      u8 chains_static, u8 chains_dynamic)
 {
-	u8 valid_rx_chains, active_cnt, idle_cnt;
+	u8 active_cnt, idle_cnt;
 
 	/* Set the channel info data */
 	cmd->ci.band = (chandef->chan->band == IEEE80211_BAND_2GHZ ?
@@ -158,17 +158,16 @@ static void iwl_mvm_phy_ctxt_cmd_data(struct iwl_mvm *mvm,
 	 * Need to add on chain noise calibration limitations, and
 	 * BT coex considerations.
 	 */
-	valid_rx_chains = mvm->nvm_data->valid_rx_ant;
 	idle_cnt = chains_static;
 	active_cnt = chains_dynamic;
 
-	cmd->rxchain_info = cpu_to_le32(valid_rx_chains <<
+	cmd->rxchain_info = cpu_to_le32(iwl_fw_valid_rx_ant(mvm->fw) <<
 					PHY_RX_CHAIN_VALID_POS);
 	cmd->rxchain_info |= cpu_to_le32(idle_cnt << PHY_RX_CHAIN_CNT_POS);
 	cmd->rxchain_info |= cpu_to_le32(active_cnt <<
 					 PHY_RX_CHAIN_MIMO_CNT_POS);
 
-	cmd->txchain_info = cpu_to_le32(mvm->nvm_data->valid_tx_ant);
+	cmd->txchain_info = cpu_to_le32(iwl_fw_valid_tx_ant(mvm->fw));
 }
 
 /*
diff --git a/drivers/net/wireless/iwlwifi/mvm/power.c b/drivers/net/wireless/iwlwifi/mvm/power.c
index 5a92a49..efb9a6f 100644
--- a/drivers/net/wireless/iwlwifi/mvm/power.c
+++ b/drivers/net/wireless/iwlwifi/mvm/power.c
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
diff --git a/drivers/net/wireless/iwlwifi/mvm/quota.c b/drivers/net/wireless/iwlwifi/mvm/quota.c
index 9256284..a1e3e92 100644
--- a/drivers/net/wireless/iwlwifi/mvm/quota.c
+++ b/drivers/net/wireless/iwlwifi/mvm/quota.c
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
@@ -114,7 +114,8 @@ static void iwl_mvm_quota_iterator(void *_data, u8 *mac,
 			data->n_interfaces[id]++;
 		break;
 	case NL80211_IFTYPE_MONITOR:
-		data->n_interfaces[id]++;
+		if (mvmvif->monitor_active)
+			data->n_interfaces[id]++;
 		break;
 	case NL80211_IFTYPE_P2P_DEVICE:
 		break;
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c
index 56b636d..a01a661 100644
--- a/drivers/net/wireless/iwlwifi/mvm/rs.c
+++ b/drivers/net/wireless/iwlwifi/mvm/rs.c
@@ -680,12 +680,14 @@ static int rs_toggle_antenna(u32 valid_ant, u32 *rate_n_flags,
  */
 static bool rs_use_green(struct ieee80211_sta *sta)
 {
-	struct iwl_mvm_sta *sta_priv = (void *)sta->drv_priv;
-
-	bool use_green = !(sta_priv->vif->bss_conf.ht_operation_mode &
-				IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
-
-	return (sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD) && use_green;
+	/*
+	 * There's a bug somewhere in this code that causes the
+	 * scaling to get stuck because GF+SGI can't be combined
+	 * in SISO rates. Until we find that bug, disable GF, it
+	 * has only limited benefit and we still interoperate with
+	 * GF APs since we can always receive GF transmissions.
+	 */
+	return false;
 }
 
 /**
diff --git a/drivers/net/wireless/iwlwifi/mvm/rx.c b/drivers/net/wireless/iwlwifi/mvm/rx.c
index b0b190d..4dfc21a 100644
--- a/drivers/net/wireless/iwlwifi/mvm/rx.c
+++ b/drivers/net/wireless/iwlwifi/mvm/rx.c
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c
index 9b21b92..2157b0f 100644
--- a/drivers/net/wireless/iwlwifi/mvm/scan.c
+++ b/drivers/net/wireless/iwlwifi/mvm/scan.c
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
@@ -74,7 +74,7 @@
 static inline __le16 iwl_mvm_scan_rx_chain(struct iwl_mvm *mvm)
 {
 	u16 rx_chain;
-	u8 rx_ant = mvm->nvm_data->valid_rx_ant;
+	u8 rx_ant = iwl_fw_valid_rx_ant(mvm->fw);
 
 	rx_chain = rx_ant << PHY_RX_CHAIN_VALID_POS;
 	rx_chain |= rx_ant << PHY_RX_CHAIN_FORCE_MIMO_SEL_POS;
@@ -115,7 +115,7 @@ iwl_mvm_scan_rate_n_flags(struct iwl_mvm *mvm, enum ieee80211_band band,
 	u32 tx_ant;
 
 	mvm->scan_last_antenna_idx =
-		iwl_mvm_next_antenna(mvm, mvm->nvm_data->valid_tx_ant,
+		iwl_mvm_next_antenna(mvm, iwl_fw_valid_tx_ant(mvm->fw),
 				     mvm->scan_last_antenna_idx);
 	tx_ant = BIT(mvm->scan_last_antenna_idx) << RATE_MCS_ANT_POS;
 
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c
index 274f44e..4d872d6 100644
--- a/drivers/net/wireless/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/iwlwifi/mvm/sta.c
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
@@ -101,8 +101,55 @@ int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
 	}
 	add_sta_cmd.add_modify = update ? 1 : 0;
 
-	/* STA_FLG_FAT_EN_MSK ? */
-	/* STA_FLG_MIMO_EN_MSK ? */
+	add_sta_cmd.station_flags_msk |= cpu_to_le32(STA_FLG_FAT_EN_MSK |
+						     STA_FLG_MIMO_EN_MSK);
+
+	switch (sta->bandwidth) {
+	case IEEE80211_STA_RX_BW_160:
+		add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_FAT_EN_160MHZ);
+		/* fall through */
+	case IEEE80211_STA_RX_BW_80:
+		add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_FAT_EN_80MHZ);
+		/* fall through */
+	case IEEE80211_STA_RX_BW_40:
+		add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_FAT_EN_40MHZ);
+		/* fall through */
+	case IEEE80211_STA_RX_BW_20:
+		if (sta->ht_cap.ht_supported)
+			add_sta_cmd.station_flags |=
+				cpu_to_le32(STA_FLG_FAT_EN_20MHZ);
+		break;
+	}
+
+	switch (sta->rx_nss) {
+	case 1:
+		add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_MIMO_EN_SISO);
+		break;
+	case 2:
+		add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_MIMO_EN_MIMO2);
+		break;
+	case 3 ... 8:
+		add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_MIMO_EN_MIMO3);
+		break;
+	}
+
+	switch (sta->smps_mode) {
+	case IEEE80211_SMPS_AUTOMATIC:
+	case IEEE80211_SMPS_NUM_MODES:
+		WARN_ON(1);
+		break;
+	case IEEE80211_SMPS_STATIC:
+		/* override NSS */
+		add_sta_cmd.station_flags &= ~cpu_to_le32(STA_FLG_MIMO_EN_MSK);
+		add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_MIMO_EN_SISO);
+		break;
+	case IEEE80211_SMPS_DYNAMIC:
+		add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_RTS_MIMO_PROT);
+		break;
+	case IEEE80211_SMPS_OFF:
+		/* nothing */
+		break;
+	}
 
 	if (sta->ht_cap.ht_supported) {
 		add_sta_cmd.station_flags_msk |=
@@ -340,6 +387,9 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
 
 	if (vif->type == NL80211_IFTYPE_STATION &&
 	    mvmvif->ap_sta_id == mvm_sta->sta_id) {
+		/* flush its queues here since we are freeing mvm_sta */
+		ret = iwl_mvm_flush_tx_path(mvm, mvm_sta->tfd_queue_msk, true);
+
 		/*
 		 * Put a non-NULL since the fw station isn't removed.
 		 * It will be removed after the MAC will be set as
@@ -348,9 +398,6 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
 		rcu_assign_pointer(mvm->fw_id_to_mac_id[mvm_sta->sta_id],
 				   ERR_PTR(-EINVAL));
 
-		/* flush its queues here since we are freeing mvm_sta */
-		ret = iwl_mvm_flush_tx_path(mvm, mvm_sta->tfd_queue_msk, true);
-
 		/* if we are associated - we can't remove the AP STA now */
 		if (vif->bss_conf.assoc)
 			return ret;
@@ -686,7 +733,7 @@ int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 
 	spin_lock_bh(&mvmsta->lock);
 	tid_data = &mvmsta->tid_data[tid];
-	tid_data->ssn = SEQ_TO_SN(tid_data->seq_number);
+	tid_data->ssn = IEEE80211_SEQ_TO_SN(tid_data->seq_number);
 	tid_data->txq_id = txq_id;
 	*ssn = tid_data->ssn;
 
@@ -789,7 +836,7 @@ int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 
 	switch (tid_data->state) {
 	case IWL_AGG_ON:
-		tid_data->ssn = SEQ_TO_SN(tid_data->seq_number);
+		tid_data->ssn = IEEE80211_SEQ_TO_SN(tid_data->seq_number);
 
 		IWL_DEBUG_TX_QUEUES(mvm,
 				    "ssn = %d, next_recl = %d\n",
@@ -834,6 +881,34 @@ int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 	return err;
 }
 
+int iwl_mvm_sta_tx_agg_flush(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+			    struct ieee80211_sta *sta, u16 tid)
+{
+	struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv;
+	struct iwl_mvm_tid_data *tid_data = &mvmsta->tid_data[tid];
+	u16 txq_id;
+
+	/*
+	 * First set the agg state to OFF to avoid calling
+	 * ieee80211_stop_tx_ba_cb in iwl_mvm_check_ratid_empty.
+	 */
+	spin_lock_bh(&mvmsta->lock);
+	txq_id = tid_data->txq_id;
+	IWL_DEBUG_TX_QUEUES(mvm, "Flush AGG: sta %d tid %d q %d state %d\n",
+			    mvmsta->sta_id, tid, txq_id, tid_data->state);
+	tid_data->state = IWL_AGG_OFF;
+	spin_unlock_bh(&mvmsta->lock);
+
+	if (iwl_mvm_flush_tx_path(mvm, BIT(txq_id), true))
+		IWL_ERR(mvm, "Couldn't flush the AGG queue\n");
+
+	iwl_trans_txq_disable(mvm->trans, tid_data->txq_id);
+	mvm->queue_to_mac80211[tid_data->txq_id] =
+				IWL_INVALID_MAC80211_QUEUE;
+
+	return 0;
+}
+
 static int iwl_mvm_set_fw_key_idx(struct iwl_mvm *mvm)
 {
 	int i;
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.h b/drivers/net/wireless/iwlwifi/mvm/sta.h
index 896f88a..b0352df 100644
--- a/drivers/net/wireless/iwlwifi/mvm/sta.h
+++ b/drivers/net/wireless/iwlwifi/mvm/sta.h
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
@@ -348,6 +348,8 @@ int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 			struct ieee80211_sta *sta, u16 tid, u8 buf_size);
 int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 			    struct ieee80211_sta *sta, u16 tid);
+int iwl_mvm_sta_tx_agg_flush(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+			    struct ieee80211_sta *sta, u16 tid);
 
 int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm);
 int iwl_mvm_allocate_int_sta(struct iwl_mvm *mvm, struct iwl_mvm_int_sta *sta,
diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.c b/drivers/net/wireless/iwlwifi/mvm/time-event.c
index e437e02..4dc934b 100644
--- a/drivers/net/wireless/iwlwifi/mvm/time-event.c
+++ b/drivers/net/wireless/iwlwifi/mvm/time-event.c
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
@@ -76,14 +76,12 @@
 #define TU_TO_JIFFIES(_tu)	(usecs_to_jiffies((_tu) * 1024))
 #define MSEC_TO_TU(_msec)	(_msec*1000/1024)
 
-/* For ROC use a TE type which has priority high enough to be scheduled when
- * there is a concurrent BSS or GO/AP. Currently, use a TE type that has
- * priority similar to the TE priority used for action scans by the FW.
- * TODO: This needs to be changed, based on the reason for the ROC, i.e., use
- * TE_P2P_DEVICE_DISCOVERABLE for remain on channel without mgmt skb, and use
- * TE_P2P_DEVICE_ACTION_SCAN
+/*
+ * For the high priority TE use a time event type that has similar priority to
+ * the FW's action scan priority.
  */
-#define IWL_MVM_ROC_TE_TYPE TE_P2P_DEVICE_ACTION_SCAN
+#define IWL_MVM_ROC_TE_TYPE_NORMAL TE_P2P_DEVICE_DISCOVERABLE
+#define IWL_MVM_ROC_TE_TYPE_MGMT_TX TE_P2P_CLIENT_ASSOC
 
 void iwl_mvm_te_clear_data(struct iwl_mvm *mvm,
 			   struct iwl_mvm_time_event_data *te_data)
@@ -116,7 +114,7 @@ void iwl_mvm_roc_done_wk(struct work_struct *wk)
 	 * issue as it will have to complete before the next command is
 	 * executed, and a new time event means a new command.
 	 */
-	iwl_mvm_flush_tx_path(mvm, BIT(IWL_OFFCHANNEL_QUEUE), false);
+	iwl_mvm_flush_tx_path(mvm, BIT(IWL_MVM_OFFCHANNEL_QUEUE), false);
 }
 
 static void iwl_mvm_roc_finished(struct iwl_mvm *mvm)
@@ -438,7 +436,7 @@ void iwl_mvm_stop_session_protection(struct iwl_mvm *mvm,
 }
 
 int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
-			  int duration)
+			  int duration, enum ieee80211_roc_type type)
 {
 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 	struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data;
@@ -459,21 +457,29 @@ int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 	time_cmd.action = cpu_to_le32(FW_CTXT_ACTION_ADD);
 	time_cmd.id_and_color =
 		cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color));
-	time_cmd.id = cpu_to_le32(IWL_MVM_ROC_TE_TYPE);
+
+	switch (type) {
+	case IEEE80211_ROC_TYPE_NORMAL:
+		time_cmd.id = cpu_to_le32(IWL_MVM_ROC_TE_TYPE_NORMAL);
+		break;
+	case IEEE80211_ROC_TYPE_MGMT_TX:
+		time_cmd.id = cpu_to_le32(IWL_MVM_ROC_TE_TYPE_MGMT_TX);
+		break;
+	default:
+		WARN_ONCE(1, "Got an invalid ROC type\n");
+		return -EINVAL;
+	}
 
 	time_cmd.apply_time = cpu_to_le32(0);
 	time_cmd.dep_policy = cpu_to_le32(TE_INDEPENDENT);
 	time_cmd.is_present = cpu_to_le32(1);
-
 	time_cmd.interval = cpu_to_le32(1);
 
 	/*
-	 * IWL_MVM_ROC_TE_TYPE can have lower priority than other events
+	 * The P2P Device TEs can have lower priority than other events
 	 * that are being scheduled by the driver/fw, and thus it might not be
-	 * scheduled. To improve the chances of it being scheduled, allow it to
-	 * be fragmented.
-	 * In addition, for the same reasons, allow to delay the scheduling of
-	 * the time event.
+	 * scheduled. To improve the chances of it being scheduled, allow them
+	 * to be fragmented, and in addition allow them to be delayed.
 	 */
 	time_cmd.max_frags = cpu_to_le32(MSEC_TO_TU(duration)/20);
 	time_cmd.max_delay = cpu_to_le32(MSEC_TO_TU(duration/2));
diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.h b/drivers/net/wireless/iwlwifi/mvm/time-event.h
index 64fb57a..f86c510 100644
--- a/drivers/net/wireless/iwlwifi/mvm/time-event.h
+++ b/drivers/net/wireless/iwlwifi/mvm/time-event.h
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
@@ -162,6 +162,7 @@ int iwl_mvm_rx_time_event_notif(struct iwl_mvm *mvm,
  * that the vif type is NL80211_IFTYPE_P2P_DEVICE
  * @duration: the requested duration in millisecond for the fw to be on the
  * channel that is bound to the vif.
+ * @type: the remain on channel request type
  *
  * This function can be used to issue a remain on channel session,
  * which means that the fw will stay in the channel for the request %duration
@@ -172,7 +173,7 @@ int iwl_mvm_rx_time_event_notif(struct iwl_mvm *mvm,
  * another notification to the driver.
  */
 int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
-			  int duration);
+			  int duration, enum ieee80211_roc_type type);
 
 /**
  * iwl_mvm_stop_p2p_roc - stop remain on channel for p2p device functionlity
diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c
index 6645efe..0acc0bf 100644
--- a/drivers/net/wireless/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/iwlwifi/mvm/tx.c
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
@@ -417,7 +417,7 @@ int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb,
 	spin_unlock(&mvmsta->lock);
 
 	if (mvmsta->vif->type == NL80211_IFTYPE_AP &&
-	    txq_id < IWL_FIRST_AMPDU_QUEUE)
+	    txq_id < IWL_MVM_FIRST_AGG_QUEUE)
 		atomic_inc(&mvmsta->pending_frames);
 
 	return 0;
@@ -606,7 +606,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
 					     info);
 
 		/* Single frame failure in an AMPDU queue => send BAR */
-		if (txq_id >= IWL_FIRST_AMPDU_QUEUE &&
+		if (txq_id >= IWL_MVM_FIRST_AGG_QUEUE &&
 		    !(info->flags & IEEE80211_TX_STAT_ACK))
 			info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
 
@@ -619,7 +619,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
 		ieee80211_tx_status_ni(mvm->hw, skb);
 	}
 
-	if (txq_id >= IWL_FIRST_AMPDU_QUEUE) {
+	if (txq_id >= IWL_MVM_FIRST_AGG_QUEUE) {
 		/* If this is an aggregation queue, we use the ssn since:
 		 * ssn = wifi seq_num % 256.
 		 * The seq_ctl is the sequence control of the packet to which
@@ -637,7 +637,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
 		next_reclaimed = ssn;
 	} else {
 		/* The next packet to be reclaimed is the one after this one */
-		next_reclaimed = SEQ_TO_SN(seq_ctl + 0x10);
+		next_reclaimed = IEEE80211_SEQ_TO_SN(seq_ctl + 0x10);
 	}
 
 	IWL_DEBUG_TX_REPLY(mvm,
@@ -681,7 +681,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
 	 * If there are no pending frames for this STA, notify mac80211 that
 	 * this station can go to sleep in its STA table.
 	 */
-	if (txq_id < IWL_FIRST_AMPDU_QUEUE && mvmsta &&
+	if (txq_id < IWL_MVM_FIRST_AGG_QUEUE && mvmsta &&
 	    !WARN_ON(skb_freed > 1) &&
 	    mvmsta->vif->type == NL80211_IFTYPE_AP &&
 	    atomic_sub_and_test(skb_freed, &mvmsta->pending_frames)) {
@@ -750,7 +750,7 @@ static void iwl_mvm_rx_tx_cmd_agg(struct iwl_mvm *mvm,
 	u16 sequence = le16_to_cpu(pkt->hdr.sequence);
 	struct ieee80211_sta *sta;
 
-	if (WARN_ON_ONCE(SEQ_TO_QUEUE(sequence) < IWL_FIRST_AMPDU_QUEUE))
+	if (WARN_ON_ONCE(SEQ_TO_QUEUE(sequence) < IWL_MVM_FIRST_AGG_QUEUE))
 		return;
 
 	if (WARN_ON_ONCE(tid == IWL_TID_NON_QOS))
diff --git a/drivers/net/wireless/iwlwifi/mvm/utils.c b/drivers/net/wireless/iwlwifi/mvm/utils.c
index 000e842..e308ad9 100644
--- a/drivers/net/wireless/iwlwifi/mvm/utils.c
+++ b/drivers/net/wireless/iwlwifi/mvm/utils.c
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
diff --git a/drivers/net/wireless/iwlwifi/pcie/1000.c b/drivers/net/wireless/iwlwifi/pcie/1000.c
deleted file mode 100644
index ff33897..0000000
--- a/drivers/net/wireless/iwlwifi/pcie/1000.c
+++ /dev/null
@@ -1,141 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2008 - 2013 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.
- *
- * Contact Information:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- *****************************************************************************/
-
-#include <linux/module.h>
-#include <linux/stringify.h>
-#include "iwl-config.h"
-#include "iwl-csr.h"
-#include "iwl-agn-hw.h"
-#include "cfg.h"
-
-/* Highest firmware API version supported */
-#define IWL1000_UCODE_API_MAX 5
-#define IWL100_UCODE_API_MAX 5
-
-/* Oldest version we won't warn about */
-#define IWL1000_UCODE_API_OK 5
-#define IWL100_UCODE_API_OK 5
-
-/* Lowest firmware API version supported */
-#define IWL1000_UCODE_API_MIN 1
-#define IWL100_UCODE_API_MIN 5
-
-/* EEPROM version */
-#define EEPROM_1000_TX_POWER_VERSION	(4)
-#define EEPROM_1000_EEPROM_VERSION	(0x15C)
-
-#define IWL1000_FW_PRE "iwlwifi-1000-"
-#define IWL1000_MODULE_FIRMWARE(api) IWL1000_FW_PRE __stringify(api) ".ucode"
-
-#define IWL100_FW_PRE "iwlwifi-100-"
-#define IWL100_MODULE_FIRMWARE(api) IWL100_FW_PRE __stringify(api) ".ucode"
-
-
-static const struct iwl_base_params iwl1000_base_params = {
-	.num_of_queues = IWLAGN_NUM_QUEUES,
-	.eeprom_size = OTP_LOW_IMAGE_SIZE,
-	.pll_cfg_val = CSR50_ANA_PLL_CFG_VAL,
-	.max_ll_items = OTP_MAX_LL_ITEMS_1000,
-	.shadow_ram_support = false,
-	.led_compensation = 51,
-	.support_ct_kill_exit = true,
-	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF,
-	.chain_noise_scale = 1000,
-	.wd_timeout = IWL_WATCHDOG_DISABLED,
-	.max_event_log_size = 128,
-};
-
-static const struct iwl_ht_params iwl1000_ht_params = {
-	.ht_greenfield_support = true,
-	.use_rts_for_aggregation = true, /* use rts/cts protection */
-	.ht40_bands = BIT(IEEE80211_BAND_2GHZ),
-};
-
-static const struct iwl_eeprom_params iwl1000_eeprom_params = {
-	.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_REG_BAND_24_HT40_CHANNELS,
-		EEPROM_REGULATORY_BAND_NO_HT40,
-	}
-};
-
-#define IWL_DEVICE_1000						\
-	.fw_name_pre = IWL1000_FW_PRE,				\
-	.ucode_api_max = IWL1000_UCODE_API_MAX,			\
-	.ucode_api_ok = IWL1000_UCODE_API_OK,			\
-	.ucode_api_min = IWL1000_UCODE_API_MIN,			\
-	.device_family = IWL_DEVICE_FAMILY_1000,		\
-	.max_inst_size = IWLAGN_RTC_INST_SIZE,			\
-	.max_data_size = IWLAGN_RTC_DATA_SIZE,			\
-	.nvm_ver = EEPROM_1000_EEPROM_VERSION,		\
-	.nvm_calib_ver = EEPROM_1000_TX_POWER_VERSION,	\
-	.base_params = &iwl1000_base_params,			\
-	.eeprom_params = &iwl1000_eeprom_params,		\
-	.led_mode = IWL_LED_BLINK
-
-const struct iwl_cfg iwl1000_bgn_cfg = {
-	.name = "Intel(R) Centrino(R) Wireless-N 1000 BGN",
-	IWL_DEVICE_1000,
-	.ht_params = &iwl1000_ht_params,
-};
-
-const struct iwl_cfg iwl1000_bg_cfg = {
-	.name = "Intel(R) Centrino(R) Wireless-N 1000 BG",
-	IWL_DEVICE_1000,
-};
-
-#define IWL_DEVICE_100						\
-	.fw_name_pre = IWL100_FW_PRE,				\
-	.ucode_api_max = IWL100_UCODE_API_MAX,			\
-	.ucode_api_ok = IWL100_UCODE_API_OK,			\
-	.ucode_api_min = IWL100_UCODE_API_MIN,			\
-	.device_family = IWL_DEVICE_FAMILY_100,			\
-	.max_inst_size = IWLAGN_RTC_INST_SIZE,			\
-	.max_data_size = IWLAGN_RTC_DATA_SIZE,			\
-	.nvm_ver = EEPROM_1000_EEPROM_VERSION,		\
-	.nvm_calib_ver = EEPROM_1000_TX_POWER_VERSION,	\
-	.base_params = &iwl1000_base_params,			\
-	.eeprom_params = &iwl1000_eeprom_params,		\
-	.led_mode = IWL_LED_RF_STATE,				\
-	.rx_with_siso_diversity = true
-
-const struct iwl_cfg iwl100_bgn_cfg = {
-	.name = "Intel(R) Centrino(R) Wireless-N 100 BGN",
-	IWL_DEVICE_100,
-	.ht_params = &iwl1000_ht_params,
-};
-
-const struct iwl_cfg iwl100_bg_cfg = {
-	.name = "Intel(R) Centrino(R) Wireless-N 100 BG",
-	IWL_DEVICE_100,
-};
-
-MODULE_FIRMWARE(IWL1000_MODULE_FIRMWARE(IWL1000_UCODE_API_OK));
-MODULE_FIRMWARE(IWL100_MODULE_FIRMWARE(IWL100_UCODE_API_OK));
diff --git a/drivers/net/wireless/iwlwifi/pcie/2000.c b/drivers/net/wireless/iwlwifi/pcie/2000.c
deleted file mode 100644
index e7de331..0000000
--- a/drivers/net/wireless/iwlwifi/pcie/2000.c
+++ /dev/null
@@ -1,243 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2008 - 2013 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.
- *
- * Contact Information:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- *****************************************************************************/
-
-#include <linux/module.h>
-#include <linux/stringify.h>
-#include "iwl-config.h"
-#include "iwl-agn-hw.h"
-#include "cfg.h"
-#include "dvm/commands.h" /* needed for BT for now */
-
-/* Highest firmware API version supported */
-#define IWL2030_UCODE_API_MAX 6
-#define IWL2000_UCODE_API_MAX 6
-#define IWL105_UCODE_API_MAX 6
-#define IWL135_UCODE_API_MAX 6
-
-/* Oldest version we won't warn about */
-#define IWL2030_UCODE_API_OK 6
-#define IWL2000_UCODE_API_OK 6
-#define IWL105_UCODE_API_OK 6
-#define IWL135_UCODE_API_OK 6
-
-/* 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
-
-/* EEPROM version */
-#define EEPROM_2000_TX_POWER_VERSION	(6)
-#define EEPROM_2000_EEPROM_VERSION	(0x805)
-
-
-#define IWL2030_FW_PRE "iwlwifi-2030-"
-#define IWL2030_MODULE_FIRMWARE(api) IWL2030_FW_PRE __stringify(api) ".ucode"
-
-#define IWL2000_FW_PRE "iwlwifi-2000-"
-#define IWL2000_MODULE_FIRMWARE(api) IWL2000_FW_PRE __stringify(api) ".ucode"
-
-#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 __stringify(api) ".ucode"
-
-static const struct iwl_base_params iwl2000_base_params = {
-	.eeprom_size = OTP_LOW_IMAGE_SIZE,
-	.num_of_queues = IWLAGN_NUM_QUEUES,
-	.pll_cfg_val = 0,
-	.max_ll_items = OTP_MAX_LL_ITEMS_2x00,
-	.shadow_ram_support = true,
-	.led_compensation = 51,
-	.adv_thermal_throttle = true,
-	.support_ct_kill_exit = true,
-	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
-	.chain_noise_scale = 1000,
-	.wd_timeout = IWL_DEF_WD_TIMEOUT,
-	.max_event_log_size = 512,
-	.shadow_reg_enable = false, /* TODO: fix bugs using this feature */
-	.hd_v2 = true,
-};
-
-
-static const struct iwl_base_params iwl2030_base_params = {
-	.eeprom_size = OTP_LOW_IMAGE_SIZE,
-	.num_of_queues = IWLAGN_NUM_QUEUES,
-	.pll_cfg_val = 0,
-	.max_ll_items = OTP_MAX_LL_ITEMS_2x00,
-	.shadow_ram_support = true,
-	.led_compensation = 57,
-	.adv_thermal_throttle = true,
-	.support_ct_kill_exit = true,
-	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
-	.chain_noise_scale = 1000,
-	.wd_timeout = IWL_LONG_WD_TIMEOUT,
-	.max_event_log_size = 512,
-	.shadow_reg_enable = false, /* TODO: fix bugs using this feature */
-	.hd_v2 = true,
-};
-
-static const struct iwl_ht_params iwl2000_ht_params = {
-	.ht_greenfield_support = true,
-	.use_rts_for_aggregation = true, /* use rts/cts protection */
-	.ht40_bands = BIT(IEEE80211_BAND_2GHZ),
-};
-
-static const struct iwl_bt_params iwl2030_bt_params = {
-	/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
-	.advanced_bt_coexist = true,
-	.agg_time_limit = BT_AGG_THRESHOLD_DEF,
-	.bt_init_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_NONE,
-	.bt_prio_boost = IWLAGN_BT_PRIO_BOOST_DEFAULT32,
-	.bt_sco_disable = true,
-	.bt_session_2 = true,
-};
-
-static const struct iwl_eeprom_params iwl20x0_eeprom_params = {
-	.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,
-	},
-	.enhanced_txpower = true,
-};
-
-#define IWL_DEVICE_2000						\
-	.fw_name_pre = IWL2000_FW_PRE,				\
-	.ucode_api_max = IWL2000_UCODE_API_MAX,			\
-	.ucode_api_ok = IWL2000_UCODE_API_OK,			\
-	.ucode_api_min = IWL2000_UCODE_API_MIN,			\
-	.device_family = IWL_DEVICE_FAMILY_2000,		\
-	.max_inst_size = IWL60_RTC_INST_SIZE,			\
-	.max_data_size = IWL60_RTC_DATA_SIZE,			\
-	.nvm_ver = EEPROM_2000_EEPROM_VERSION,		\
-	.nvm_calib_ver = EEPROM_2000_TX_POWER_VERSION,	\
-	.base_params = &iwl2000_base_params,			\
-	.eeprom_params = &iwl20x0_eeprom_params,		\
-	.need_temp_offset_calib = true,				\
-	.temp_offset_v2 = true,					\
-	.led_mode = IWL_LED_RF_STATE
-
-const struct iwl_cfg iwl2000_2bgn_cfg = {
-	.name = "Intel(R) Centrino(R) Wireless-N 2200 BGN",
-	IWL_DEVICE_2000,
-	.ht_params = &iwl2000_ht_params,
-};
-
-const struct iwl_cfg iwl2000_2bgn_d_cfg = {
-	.name = "Intel(R) Centrino(R) Wireless-N 2200D BGN",
-	IWL_DEVICE_2000,
-	.ht_params = &iwl2000_ht_params,
-};
-
-#define IWL_DEVICE_2030						\
-	.fw_name_pre = IWL2030_FW_PRE,				\
-	.ucode_api_max = IWL2030_UCODE_API_MAX,			\
-	.ucode_api_ok = IWL2030_UCODE_API_OK,			\
-	.ucode_api_min = IWL2030_UCODE_API_MIN,			\
-	.device_family = IWL_DEVICE_FAMILY_2030,		\
-	.max_inst_size = IWL60_RTC_INST_SIZE,			\
-	.max_data_size = IWL60_RTC_DATA_SIZE,			\
-	.nvm_ver = EEPROM_2000_EEPROM_VERSION,		\
-	.nvm_calib_ver = EEPROM_2000_TX_POWER_VERSION,	\
-	.base_params = &iwl2030_base_params,			\
-	.bt_params = &iwl2030_bt_params,			\
-	.eeprom_params = &iwl20x0_eeprom_params,		\
-	.need_temp_offset_calib = true,				\
-	.temp_offset_v2 = true,					\
-	.led_mode = IWL_LED_RF_STATE,				\
-	.adv_pm = true
-
-const struct iwl_cfg iwl2030_2bgn_cfg = {
-	.name = "Intel(R) Centrino(R) Wireless-N 2230 BGN",
-	IWL_DEVICE_2030,
-	.ht_params = &iwl2000_ht_params,
-};
-
-#define IWL_DEVICE_105						\
-	.fw_name_pre = IWL105_FW_PRE,				\
-	.ucode_api_max = IWL105_UCODE_API_MAX,			\
-	.ucode_api_ok = IWL105_UCODE_API_OK,			\
-	.ucode_api_min = IWL105_UCODE_API_MIN,			\
-	.device_family = IWL_DEVICE_FAMILY_105,			\
-	.max_inst_size = IWL60_RTC_INST_SIZE,			\
-	.max_data_size = IWL60_RTC_DATA_SIZE,			\
-	.nvm_ver = EEPROM_2000_EEPROM_VERSION,		\
-	.nvm_calib_ver = EEPROM_2000_TX_POWER_VERSION,	\
-	.base_params = &iwl2000_base_params,			\
-	.eeprom_params = &iwl20x0_eeprom_params,		\
-	.need_temp_offset_calib = true,				\
-	.temp_offset_v2 = true,					\
-	.led_mode = IWL_LED_RF_STATE,				\
-	.adv_pm = true,						\
-	.rx_with_siso_diversity = true
-
-const struct iwl_cfg iwl105_bgn_cfg = {
-	.name = "Intel(R) Centrino(R) Wireless-N 105 BGN",
-	IWL_DEVICE_105,
-	.ht_params = &iwl2000_ht_params,
-};
-
-const struct iwl_cfg iwl105_bgn_d_cfg = {
-	.name = "Intel(R) Centrino(R) Wireless-N 105D BGN",
-	IWL_DEVICE_105,
-	.ht_params = &iwl2000_ht_params,
-};
-
-#define IWL_DEVICE_135						\
-	.fw_name_pre = IWL135_FW_PRE,				\
-	.ucode_api_max = IWL135_UCODE_API_MAX,			\
-	.ucode_api_ok = IWL135_UCODE_API_OK,			\
-	.ucode_api_min = IWL135_UCODE_API_MIN,			\
-	.device_family = IWL_DEVICE_FAMILY_135,			\
-	.max_inst_size = IWL60_RTC_INST_SIZE,			\
-	.max_data_size = IWL60_RTC_DATA_SIZE,			\
-	.nvm_ver = EEPROM_2000_EEPROM_VERSION,		\
-	.nvm_calib_ver = EEPROM_2000_TX_POWER_VERSION,	\
-	.base_params = &iwl2030_base_params,			\
-	.bt_params = &iwl2030_bt_params,			\
-	.eeprom_params = &iwl20x0_eeprom_params,		\
-	.need_temp_offset_calib = true,				\
-	.temp_offset_v2 = true,					\
-	.led_mode = IWL_LED_RF_STATE,				\
-	.adv_pm = true,						\
-	.rx_with_siso_diversity = true
-
-const struct iwl_cfg iwl135_bgn_cfg = {
-	.name = "Intel(R) Centrino(R) Wireless-N 135 BGN",
-	IWL_DEVICE_135,
-	.ht_params = &iwl2000_ht_params,
-};
-
-MODULE_FIRMWARE(IWL2000_MODULE_FIRMWARE(IWL2000_UCODE_API_OK));
-MODULE_FIRMWARE(IWL2030_MODULE_FIRMWARE(IWL2030_UCODE_API_OK));
-MODULE_FIRMWARE(IWL105_MODULE_FIRMWARE(IWL105_UCODE_API_OK));
-MODULE_FIRMWARE(IWL135_MODULE_FIRMWARE(IWL135_UCODE_API_OK));
diff --git a/drivers/net/wireless/iwlwifi/pcie/5000.c b/drivers/net/wireless/iwlwifi/pcie/5000.c
deleted file mode 100644
index 5096f7c..0000000
--- a/drivers/net/wireless/iwlwifi/pcie/5000.c
+++ /dev/null
@@ -1,180 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2013 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.
- *
- * Contact Information:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- *****************************************************************************/
-
-#include <linux/module.h>
-#include <linux/stringify.h>
-#include "iwl-config.h"
-#include "iwl-agn-hw.h"
-#include "iwl-csr.h"
-#include "cfg.h"
-
-/* Highest firmware API version supported */
-#define IWL5000_UCODE_API_MAX 5
-#define IWL5150_UCODE_API_MAX 2
-
-/* Oldest version we won't warn about */
-#define IWL5000_UCODE_API_OK 5
-#define IWL5150_UCODE_API_OK 2
-
-/* Lowest firmware API version supported */
-#define IWL5000_UCODE_API_MIN 1
-#define IWL5150_UCODE_API_MIN 1
-
-/* EEPROM versions */
-#define EEPROM_5000_TX_POWER_VERSION	(4)
-#define EEPROM_5000_EEPROM_VERSION	(0x11A)
-#define EEPROM_5050_TX_POWER_VERSION	(4)
-#define EEPROM_5050_EEPROM_VERSION	(0x21E)
-
-#define IWL5000_FW_PRE "iwlwifi-5000-"
-#define IWL5000_MODULE_FIRMWARE(api) IWL5000_FW_PRE __stringify(api) ".ucode"
-
-#define IWL5150_FW_PRE "iwlwifi-5150-"
-#define IWL5150_MODULE_FIRMWARE(api) IWL5150_FW_PRE __stringify(api) ".ucode"
-
-static const struct iwl_base_params iwl5000_base_params = {
-	.eeprom_size = IWLAGN_EEPROM_IMG_SIZE,
-	.num_of_queues = IWLAGN_NUM_QUEUES,
-	.pll_cfg_val = CSR50_ANA_PLL_CFG_VAL,
-	.led_compensation = 51,
-	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
-	.chain_noise_scale = 1000,
-	.wd_timeout = IWL_WATCHDOG_DISABLED,
-	.max_event_log_size = 512,
-	.no_idle_support = true,
-};
-
-static const struct iwl_ht_params iwl5000_ht_params = {
-	.ht_greenfield_support = true,
-	.ht40_bands = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ),
-};
-
-static const struct iwl_eeprom_params iwl5000_eeprom_params = {
-	.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_REG_BAND_24_HT40_CHANNELS,
-		EEPROM_REG_BAND_52_HT40_CHANNELS
-	},
-};
-
-#define IWL_DEVICE_5000						\
-	.fw_name_pre = IWL5000_FW_PRE,				\
-	.ucode_api_max = IWL5000_UCODE_API_MAX,			\
-	.ucode_api_ok = IWL5000_UCODE_API_OK,			\
-	.ucode_api_min = IWL5000_UCODE_API_MIN,			\
-	.device_family = IWL_DEVICE_FAMILY_5000,		\
-	.max_inst_size = IWLAGN_RTC_INST_SIZE,			\
-	.max_data_size = IWLAGN_RTC_DATA_SIZE,			\
-	.nvm_ver = EEPROM_5000_EEPROM_VERSION,		\
-	.nvm_calib_ver = EEPROM_5000_TX_POWER_VERSION,	\
-	.base_params = &iwl5000_base_params,			\
-	.eeprom_params = &iwl5000_eeprom_params,		\
-	.led_mode = IWL_LED_BLINK
-
-const struct iwl_cfg iwl5300_agn_cfg = {
-	.name = "Intel(R) Ultimate N WiFi Link 5300 AGN",
-	IWL_DEVICE_5000,
-	/* at least EEPROM 0x11A has wrong info */
-	.valid_tx_ant = ANT_ABC,	/* .cfg overwrite */
-	.valid_rx_ant = ANT_ABC,	/* .cfg overwrite */
-	.ht_params = &iwl5000_ht_params,
-};
-
-const struct iwl_cfg iwl5100_bgn_cfg = {
-	.name = "Intel(R) WiFi Link 5100 BGN",
-	IWL_DEVICE_5000,
-	.valid_tx_ant = ANT_B,		/* .cfg overwrite */
-	.valid_rx_ant = ANT_AB,		/* .cfg overwrite */
-	.ht_params = &iwl5000_ht_params,
-};
-
-const struct iwl_cfg iwl5100_abg_cfg = {
-	.name = "Intel(R) WiFi Link 5100 ABG",
-	IWL_DEVICE_5000,
-	.valid_tx_ant = ANT_B,		/* .cfg overwrite */
-	.valid_rx_ant = ANT_AB,		/* .cfg overwrite */
-};
-
-const struct iwl_cfg iwl5100_agn_cfg = {
-	.name = "Intel(R) WiFi Link 5100 AGN",
-	IWL_DEVICE_5000,
-	.valid_tx_ant = ANT_B,		/* .cfg overwrite */
-	.valid_rx_ant = ANT_AB,		/* .cfg overwrite */
-	.ht_params = &iwl5000_ht_params,
-};
-
-const struct iwl_cfg iwl5350_agn_cfg = {
-	.name = "Intel(R) WiMAX/WiFi Link 5350 AGN",
-	.fw_name_pre = IWL5000_FW_PRE,
-	.ucode_api_max = IWL5000_UCODE_API_MAX,
-	.ucode_api_ok = IWL5000_UCODE_API_OK,
-	.ucode_api_min = IWL5000_UCODE_API_MIN,
-	.device_family = IWL_DEVICE_FAMILY_5000,
-	.max_inst_size = IWLAGN_RTC_INST_SIZE,
-	.max_data_size = IWLAGN_RTC_DATA_SIZE,
-	.nvm_ver = EEPROM_5050_EEPROM_VERSION,
-	.nvm_calib_ver = EEPROM_5050_TX_POWER_VERSION,
-	.base_params = &iwl5000_base_params,
-	.eeprom_params = &iwl5000_eeprom_params,
-	.ht_params = &iwl5000_ht_params,
-	.led_mode = IWL_LED_BLINK,
-	.internal_wimax_coex = true,
-};
-
-#define IWL_DEVICE_5150						\
-	.fw_name_pre = IWL5150_FW_PRE,				\
-	.ucode_api_max = IWL5150_UCODE_API_MAX,			\
-	.ucode_api_ok = IWL5150_UCODE_API_OK,			\
-	.ucode_api_min = IWL5150_UCODE_API_MIN,			\
-	.device_family = IWL_DEVICE_FAMILY_5150,		\
-	.max_inst_size = IWLAGN_RTC_INST_SIZE,			\
-	.max_data_size = IWLAGN_RTC_DATA_SIZE,			\
-	.nvm_ver = EEPROM_5050_EEPROM_VERSION,		\
-	.nvm_calib_ver = EEPROM_5050_TX_POWER_VERSION,	\
-	.base_params = &iwl5000_base_params,			\
-	.eeprom_params = &iwl5000_eeprom_params,		\
-	.no_xtal_calib = true,					\
-	.led_mode = IWL_LED_BLINK,				\
-	.internal_wimax_coex = true
-
-const struct iwl_cfg iwl5150_agn_cfg = {
-	.name = "Intel(R) WiMAX/WiFi Link 5150 AGN",
-	IWL_DEVICE_5150,
-	.ht_params = &iwl5000_ht_params,
-
-};
-
-const struct iwl_cfg iwl5150_abg_cfg = {
-	.name = "Intel(R) WiMAX/WiFi Link 5150 ABG",
-	IWL_DEVICE_5150,
-};
-
-MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_OK));
-MODULE_FIRMWARE(IWL5150_MODULE_FIRMWARE(IWL5150_UCODE_API_OK));
diff --git a/drivers/net/wireless/iwlwifi/pcie/6000.c b/drivers/net/wireless/iwlwifi/pcie/6000.c
deleted file mode 100644
index 801ff49..0000000
--- a/drivers/net/wireless/iwlwifi/pcie/6000.c
+++ /dev/null
@@ -1,403 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2008 - 2013 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.
- *
- * Contact Information:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- *****************************************************************************/
-
-#include <linux/module.h>
-#include <linux/stringify.h>
-#include "iwl-config.h"
-#include "iwl-agn-hw.h"
-#include "cfg.h"
-#include "dvm/commands.h" /* needed for BT for now */
-
-/* Highest firmware API version supported */
-#define IWL6000_UCODE_API_MAX 6
-#define IWL6050_UCODE_API_MAX 5
-#define IWL6000G2_UCODE_API_MAX 6
-#define IWL6035_UCODE_API_MAX 6
-
-/* Oldest version we won't warn about */
-#define IWL6000_UCODE_API_OK 4
-#define IWL6000G2_UCODE_API_OK 5
-#define IWL6050_UCODE_API_OK 5
-#define IWL6000G2B_UCODE_API_OK 6
-#define IWL6035_UCODE_API_OK 6
-
-/* Lowest firmware API version supported */
-#define IWL6000_UCODE_API_MIN 4
-#define IWL6050_UCODE_API_MIN 4
-#define IWL6000G2_UCODE_API_MIN 5
-#define IWL6035_UCODE_API_MIN 6
-
-/* EEPROM versions */
-#define EEPROM_6000_TX_POWER_VERSION	(4)
-#define EEPROM_6000_EEPROM_VERSION	(0x423)
-#define EEPROM_6050_TX_POWER_VERSION	(4)
-#define EEPROM_6050_EEPROM_VERSION	(0x532)
-#define EEPROM_6150_TX_POWER_VERSION	(6)
-#define EEPROM_6150_EEPROM_VERSION	(0x553)
-#define EEPROM_6005_TX_POWER_VERSION	(6)
-#define EEPROM_6005_EEPROM_VERSION	(0x709)
-#define EEPROM_6030_TX_POWER_VERSION	(6)
-#define EEPROM_6030_EEPROM_VERSION	(0x709)
-#define EEPROM_6035_TX_POWER_VERSION	(6)
-#define EEPROM_6035_EEPROM_VERSION	(0x753)
-
-#define IWL6000_FW_PRE "iwlwifi-6000-"
-#define IWL6000_MODULE_FIRMWARE(api) IWL6000_FW_PRE __stringify(api) ".ucode"
-
-#define IWL6050_FW_PRE "iwlwifi-6050-"
-#define IWL6050_MODULE_FIRMWARE(api) IWL6050_FW_PRE __stringify(api) ".ucode"
-
-#define IWL6005_FW_PRE "iwlwifi-6000g2a-"
-#define IWL6005_MODULE_FIRMWARE(api) IWL6005_FW_PRE __stringify(api) ".ucode"
-
-#define IWL6030_FW_PRE "iwlwifi-6000g2b-"
-#define IWL6030_MODULE_FIRMWARE(api) IWL6030_FW_PRE __stringify(api) ".ucode"
-
-static const struct iwl_base_params iwl6000_base_params = {
-	.eeprom_size = OTP_LOW_IMAGE_SIZE,
-	.num_of_queues = IWLAGN_NUM_QUEUES,
-	.pll_cfg_val = 0,
-	.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
-	.shadow_ram_support = true,
-	.led_compensation = 51,
-	.adv_thermal_throttle = true,
-	.support_ct_kill_exit = true,
-	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
-	.chain_noise_scale = 1000,
-	.wd_timeout = IWL_DEF_WD_TIMEOUT,
-	.max_event_log_size = 512,
-	.shadow_reg_enable = false, /* TODO: fix bugs using this feature */
-};
-
-static const struct iwl_base_params iwl6050_base_params = {
-	.eeprom_size = OTP_LOW_IMAGE_SIZE,
-	.num_of_queues = IWLAGN_NUM_QUEUES,
-	.pll_cfg_val = 0,
-	.max_ll_items = OTP_MAX_LL_ITEMS_6x50,
-	.shadow_ram_support = true,
-	.led_compensation = 51,
-	.adv_thermal_throttle = true,
-	.support_ct_kill_exit = true,
-	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
-	.chain_noise_scale = 1500,
-	.wd_timeout = IWL_DEF_WD_TIMEOUT,
-	.max_event_log_size = 1024,
-	.shadow_reg_enable = false, /* TODO: fix bugs using this feature */
-};
-
-static const struct iwl_base_params iwl6000_g2_base_params = {
-	.eeprom_size = OTP_LOW_IMAGE_SIZE,
-	.num_of_queues = IWLAGN_NUM_QUEUES,
-	.pll_cfg_val = 0,
-	.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
-	.shadow_ram_support = true,
-	.led_compensation = 57,
-	.adv_thermal_throttle = true,
-	.support_ct_kill_exit = true,
-	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
-	.chain_noise_scale = 1000,
-	.wd_timeout = IWL_LONG_WD_TIMEOUT,
-	.max_event_log_size = 512,
-	.shadow_reg_enable = false, /* TODO: fix bugs using this feature */
-};
-
-static const struct iwl_ht_params iwl6000_ht_params = {
-	.ht_greenfield_support = true,
-	.use_rts_for_aggregation = true, /* use rts/cts protection */
-	.ht40_bands = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ),
-};
-
-static const struct iwl_bt_params iwl6000_bt_params = {
-	/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
-	.advanced_bt_coexist = true,
-	.agg_time_limit = BT_AGG_THRESHOLD_DEF,
-	.bt_init_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_NONE,
-	.bt_prio_boost = IWLAGN_BT_PRIO_BOOST_DEFAULT,
-	.bt_sco_disable = true,
-};
-
-static const struct iwl_eeprom_params iwl6000_eeprom_params = {
-	.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_REG_BAND_52_HT40_CHANNELS
-	},
-	.enhanced_txpower = true,
-};
-
-#define IWL_DEVICE_6005						\
-	.fw_name_pre = IWL6005_FW_PRE,				\
-	.ucode_api_max = IWL6000G2_UCODE_API_MAX,		\
-	.ucode_api_ok = IWL6000G2_UCODE_API_OK,			\
-	.ucode_api_min = IWL6000G2_UCODE_API_MIN,		\
-	.device_family = IWL_DEVICE_FAMILY_6005,		\
-	.max_inst_size = IWL60_RTC_INST_SIZE,			\
-	.max_data_size = IWL60_RTC_DATA_SIZE,			\
-	.nvm_ver = EEPROM_6005_EEPROM_VERSION,		\
-	.nvm_calib_ver = EEPROM_6005_TX_POWER_VERSION,	\
-	.base_params = &iwl6000_g2_base_params,			\
-	.eeprom_params = &iwl6000_eeprom_params,		\
-	.need_temp_offset_calib = true,				\
-	.led_mode = IWL_LED_RF_STATE
-
-const struct iwl_cfg iwl6005_2agn_cfg = {
-	.name = "Intel(R) Centrino(R) Advanced-N 6205 AGN",
-	IWL_DEVICE_6005,
-	.ht_params = &iwl6000_ht_params,
-};
-
-const struct iwl_cfg iwl6005_2abg_cfg = {
-	.name = "Intel(R) Centrino(R) Advanced-N 6205 ABG",
-	IWL_DEVICE_6005,
-};
-
-const struct iwl_cfg iwl6005_2bg_cfg = {
-	.name = "Intel(R) Centrino(R) Advanced-N 6205 BG",
-	IWL_DEVICE_6005,
-};
-
-const struct iwl_cfg iwl6005_2agn_sff_cfg = {
-	.name = "Intel(R) Centrino(R) Advanced-N 6205S AGN",
-	IWL_DEVICE_6005,
-	.ht_params = &iwl6000_ht_params,
-};
-
-const struct iwl_cfg iwl6005_2agn_d_cfg = {
-	.name = "Intel(R) Centrino(R) Advanced-N 6205D AGN",
-	IWL_DEVICE_6005,
-	.ht_params = &iwl6000_ht_params,
-};
-
-const struct iwl_cfg iwl6005_2agn_mow1_cfg = {
-	.name = "Intel(R) Centrino(R) Advanced-N 6206 AGN",
-	IWL_DEVICE_6005,
-	.ht_params = &iwl6000_ht_params,
-};
-
-const struct iwl_cfg iwl6005_2agn_mow2_cfg = {
-	.name = "Intel(R) Centrino(R) Advanced-N 6207 AGN",
-	IWL_DEVICE_6005,
-	.ht_params = &iwl6000_ht_params,
-};
-
-#define IWL_DEVICE_6030						\
-	.fw_name_pre = IWL6030_FW_PRE,				\
-	.ucode_api_max = IWL6000G2_UCODE_API_MAX,		\
-	.ucode_api_ok = IWL6000G2B_UCODE_API_OK,		\
-	.ucode_api_min = IWL6000G2_UCODE_API_MIN,		\
-	.device_family = IWL_DEVICE_FAMILY_6030,		\
-	.max_inst_size = IWL60_RTC_INST_SIZE,			\
-	.max_data_size = IWL60_RTC_DATA_SIZE,			\
-	.nvm_ver = EEPROM_6030_EEPROM_VERSION,		\
-	.nvm_calib_ver = EEPROM_6030_TX_POWER_VERSION,	\
-	.base_params = &iwl6000_g2_base_params,			\
-	.bt_params = &iwl6000_bt_params,			\
-	.eeprom_params = &iwl6000_eeprom_params,		\
-	.need_temp_offset_calib = true,				\
-	.led_mode = IWL_LED_RF_STATE,				\
-	.adv_pm = true						\
-
-const struct iwl_cfg iwl6030_2agn_cfg = {
-	.name = "Intel(R) Centrino(R) Advanced-N 6230 AGN",
-	IWL_DEVICE_6030,
-	.ht_params = &iwl6000_ht_params,
-};
-
-const struct iwl_cfg iwl6030_2abg_cfg = {
-	.name = "Intel(R) Centrino(R) Advanced-N 6230 ABG",
-	IWL_DEVICE_6030,
-};
-
-const struct iwl_cfg iwl6030_2bgn_cfg = {
-	.name = "Intel(R) Centrino(R) Advanced-N 6230 BGN",
-	IWL_DEVICE_6030,
-	.ht_params = &iwl6000_ht_params,
-};
-
-const struct iwl_cfg iwl6030_2bg_cfg = {
-	.name = "Intel(R) Centrino(R) Advanced-N 6230 BG",
-	IWL_DEVICE_6030,
-};
-
-#define IWL_DEVICE_6035						\
-	.fw_name_pre = IWL6030_FW_PRE,				\
-	.ucode_api_max = IWL6035_UCODE_API_MAX,			\
-	.ucode_api_ok = IWL6035_UCODE_API_OK,			\
-	.ucode_api_min = IWL6035_UCODE_API_MIN,			\
-	.device_family = IWL_DEVICE_FAMILY_6030,		\
-	.max_inst_size = IWL60_RTC_INST_SIZE,			\
-	.max_data_size = IWL60_RTC_DATA_SIZE,			\
-	.nvm_ver = EEPROM_6030_EEPROM_VERSION,		\
-	.nvm_calib_ver = EEPROM_6030_TX_POWER_VERSION,	\
-	.base_params = &iwl6000_g2_base_params,			\
-	.bt_params = &iwl6000_bt_params,			\
-	.eeprom_params = &iwl6000_eeprom_params,		\
-	.need_temp_offset_calib = true,				\
-	.led_mode = IWL_LED_RF_STATE,				\
-	.adv_pm = true
-
-const struct iwl_cfg iwl6035_2agn_cfg = {
-	.name = "Intel(R) Centrino(R) Advanced-N 6235 AGN",
-	IWL_DEVICE_6035,
-	.ht_params = &iwl6000_ht_params,
-};
-
-const struct iwl_cfg iwl1030_bgn_cfg = {
-	.name = "Intel(R) Centrino(R) Wireless-N 1030 BGN",
-	IWL_DEVICE_6030,
-	.ht_params = &iwl6000_ht_params,
-};
-
-const struct iwl_cfg iwl1030_bg_cfg = {
-	.name = "Intel(R) Centrino(R) Wireless-N 1030 BG",
-	IWL_DEVICE_6030,
-};
-
-const struct iwl_cfg iwl130_bgn_cfg = {
-	.name = "Intel(R) Centrino(R) Wireless-N 130 BGN",
-	IWL_DEVICE_6030,
-	.ht_params = &iwl6000_ht_params,
-	.rx_with_siso_diversity = true,
-};
-
-const struct iwl_cfg iwl130_bg_cfg = {
-	.name = "Intel(R) Centrino(R) Wireless-N 130 BG",
-	IWL_DEVICE_6030,
-	.rx_with_siso_diversity = true,
-};
-
-/*
- * "i": Internal configuration, use internal Power Amplifier
- */
-#define IWL_DEVICE_6000i					\
-	.fw_name_pre = IWL6000_FW_PRE,				\
-	.ucode_api_max = IWL6000_UCODE_API_MAX,			\
-	.ucode_api_ok = IWL6000_UCODE_API_OK,			\
-	.ucode_api_min = IWL6000_UCODE_API_MIN,			\
-	.device_family = IWL_DEVICE_FAMILY_6000i,		\
-	.max_inst_size = IWL60_RTC_INST_SIZE,			\
-	.max_data_size = IWL60_RTC_DATA_SIZE,			\
-	.valid_tx_ant = ANT_BC,		/* .cfg overwrite */	\
-	.valid_rx_ant = ANT_BC,		/* .cfg overwrite */	\
-	.nvm_ver = EEPROM_6000_EEPROM_VERSION,		\
-	.nvm_calib_ver = EEPROM_6000_TX_POWER_VERSION,	\
-	.base_params = &iwl6000_base_params,			\
-	.eeprom_params = &iwl6000_eeprom_params,		\
-	.led_mode = IWL_LED_BLINK
-
-const struct iwl_cfg iwl6000i_2agn_cfg = {
-	.name = "Intel(R) Centrino(R) Advanced-N 6200 AGN",
-	IWL_DEVICE_6000i,
-	.ht_params = &iwl6000_ht_params,
-};
-
-const struct iwl_cfg iwl6000i_2abg_cfg = {
-	.name = "Intel(R) Centrino(R) Advanced-N 6200 ABG",
-	IWL_DEVICE_6000i,
-};
-
-const struct iwl_cfg iwl6000i_2bg_cfg = {
-	.name = "Intel(R) Centrino(R) Advanced-N 6200 BG",
-	IWL_DEVICE_6000i,
-};
-
-#define IWL_DEVICE_6050						\
-	.fw_name_pre = IWL6050_FW_PRE,				\
-	.ucode_api_max = IWL6050_UCODE_API_MAX,			\
-	.ucode_api_min = IWL6050_UCODE_API_MIN,			\
-	.device_family = IWL_DEVICE_FAMILY_6050,		\
-	.max_inst_size = IWL60_RTC_INST_SIZE,			\
-	.max_data_size = IWL60_RTC_DATA_SIZE,			\
-	.valid_tx_ant = ANT_AB,		/* .cfg overwrite */	\
-	.valid_rx_ant = ANT_AB,		/* .cfg overwrite */	\
-	.nvm_ver = EEPROM_6050_EEPROM_VERSION,		\
-	.nvm_calib_ver = EEPROM_6050_TX_POWER_VERSION,	\
-	.base_params = &iwl6050_base_params,			\
-	.eeprom_params = &iwl6000_eeprom_params,		\
-	.led_mode = IWL_LED_BLINK,				\
-	.internal_wimax_coex = true
-
-const struct iwl_cfg iwl6050_2agn_cfg = {
-	.name = "Intel(R) Centrino(R) Advanced-N + WiMAX 6250 AGN",
-	IWL_DEVICE_6050,
-	.ht_params = &iwl6000_ht_params,
-};
-
-const struct iwl_cfg iwl6050_2abg_cfg = {
-	.name = "Intel(R) Centrino(R) Advanced-N + WiMAX 6250 ABG",
-	IWL_DEVICE_6050,
-};
-
-#define IWL_DEVICE_6150						\
-	.fw_name_pre = IWL6050_FW_PRE,				\
-	.ucode_api_max = IWL6050_UCODE_API_MAX,			\
-	.ucode_api_min = IWL6050_UCODE_API_MIN,			\
-	.device_family = IWL_DEVICE_FAMILY_6150,		\
-	.max_inst_size = IWL60_RTC_INST_SIZE,			\
-	.max_data_size = IWL60_RTC_DATA_SIZE,			\
-	.nvm_ver = EEPROM_6150_EEPROM_VERSION,		\
-	.nvm_calib_ver = EEPROM_6150_TX_POWER_VERSION,	\
-	.base_params = &iwl6050_base_params,			\
-	.eeprom_params = &iwl6000_eeprom_params,		\
-	.led_mode = IWL_LED_BLINK,				\
-	.internal_wimax_coex = true
-
-const struct iwl_cfg iwl6150_bgn_cfg = {
-	.name = "Intel(R) Centrino(R) Wireless-N + WiMAX 6150 BGN",
-	IWL_DEVICE_6150,
-	.ht_params = &iwl6000_ht_params,
-};
-
-const struct iwl_cfg iwl6150_bg_cfg = {
-	.name = "Intel(R) Centrino(R) Wireless-N + WiMAX 6150 BG",
-	IWL_DEVICE_6150,
-};
-
-const struct iwl_cfg iwl6000_3agn_cfg = {
-	.name = "Intel(R) Centrino(R) Ultimate-N 6300 AGN",
-	.fw_name_pre = IWL6000_FW_PRE,
-	.ucode_api_max = IWL6000_UCODE_API_MAX,
-	.ucode_api_ok = IWL6000_UCODE_API_OK,
-	.ucode_api_min = IWL6000_UCODE_API_MIN,
-	.device_family = IWL_DEVICE_FAMILY_6000,
-	.max_inst_size = IWL60_RTC_INST_SIZE,
-	.max_data_size = IWL60_RTC_DATA_SIZE,
-	.nvm_ver = EEPROM_6000_EEPROM_VERSION,
-	.nvm_calib_ver = EEPROM_6000_TX_POWER_VERSION,
-	.base_params = &iwl6000_base_params,
-	.eeprom_params = &iwl6000_eeprom_params,
-	.ht_params = &iwl6000_ht_params,
-	.led_mode = IWL_LED_BLINK,
-};
-
-MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_OK));
-MODULE_FIRMWARE(IWL6050_MODULE_FIRMWARE(IWL6050_UCODE_API_OK));
-MODULE_FIRMWARE(IWL6005_MODULE_FIRMWARE(IWL6000G2_UCODE_API_OK));
-MODULE_FIRMWARE(IWL6030_MODULE_FIRMWARE(IWL6000G2B_UCODE_API_OK));
diff --git a/drivers/net/wireless/iwlwifi/pcie/7000.c b/drivers/net/wireless/iwlwifi/pcie/7000.c
deleted file mode 100644
index 6e35b2b..0000000
--- a/drivers/net/wireless/iwlwifi/pcie/7000.c
+++ /dev/null
@@ -1,111 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2008 - 2013 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.
- *
- * Contact Information:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- *****************************************************************************/
-
-#include <linux/module.h>
-#include <linux/stringify.h>
-#include "iwl-config.h"
-#include "iwl-agn-hw.h"
-#include "cfg.h"
-
-/* Highest firmware API version supported */
-#define IWL7260_UCODE_API_MAX	6
-#define IWL3160_UCODE_API_MAX	6
-
-/* Oldest version we won't warn about */
-#define IWL7260_UCODE_API_OK	6
-#define IWL3160_UCODE_API_OK	6
-
-/* Lowest firmware API version supported */
-#define IWL7260_UCODE_API_MIN	6
-#define IWL3160_UCODE_API_MIN	6
-
-/* NVM versions */
-#define IWL7260_NVM_VERSION		0x0a1d
-#define IWL7260_TX_POWER_VERSION	0xffff /* meaningless */
-#define IWL3160_NVM_VERSION		0x709
-#define IWL3160_TX_POWER_VERSION	0xffff /* meaningless */
-
-#define IWL7260_FW_PRE "iwlwifi-7260-"
-#define IWL7260_MODULE_FIRMWARE(api) IWL7260_FW_PRE __stringify(api) ".ucode"
-
-#define IWL3160_FW_PRE "iwlwifi-3160-"
-#define IWL3160_MODULE_FIRMWARE(api) IWL3160_FW_PRE __stringify(api) ".ucode"
-
-static const struct iwl_base_params iwl7000_base_params = {
-	.eeprom_size = OTP_LOW_IMAGE_SIZE,
-	.num_of_queues = IWLAGN_NUM_QUEUES,
-	.pll_cfg_val = 0,
-	.shadow_ram_support = true,
-	.led_compensation = 57,
-	.adv_thermal_throttle = true,
-	.support_ct_kill_exit = true,
-	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
-	.chain_noise_scale = 1000,
-	.wd_timeout = IWL_LONG_WD_TIMEOUT,
-	.max_event_log_size = 512,
-	.shadow_reg_enable = false, /* TODO: fix bugs using this feature */
-};
-
-static const struct iwl_ht_params iwl7000_ht_params = {
-	.ht_greenfield_support = true,
-	.use_rts_for_aggregation = true, /* use rts/cts protection */
-	.ht40_bands = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ),
-};
-
-#define IWL_DEVICE_7000						\
-	.ucode_api_max = IWL7260_UCODE_API_MAX,			\
-	.ucode_api_ok = IWL7260_UCODE_API_OK,			\
-	.ucode_api_min = IWL7260_UCODE_API_MIN,			\
-	.device_family = IWL_DEVICE_FAMILY_7000,		\
-	.max_inst_size = IWL60_RTC_INST_SIZE,			\
-	.max_data_size = IWL60_RTC_DATA_SIZE,			\
-	.base_params = &iwl7000_base_params,			\
-	/* TODO: .bt_params? */					\
-	.need_temp_offset_calib = true,				\
-	.led_mode = IWL_LED_RF_STATE,				\
-	.adv_pm = true						\
-
-
-const struct iwl_cfg iwl7260_2ac_cfg = {
-	.name = "Intel(R) Dual Band Wireless AC7260",
-	.fw_name_pre = IWL7260_FW_PRE,
-	IWL_DEVICE_7000,
-	.ht_params = &iwl7000_ht_params,
-	.nvm_ver = IWL7260_NVM_VERSION,
-	.nvm_calib_ver = IWL7260_TX_POWER_VERSION,
-};
-
-const struct iwl_cfg iwl3160_ac_cfg = {
-	.name = "Intel(R) Dual Band Wireless AC3160",
-	.fw_name_pre = IWL3160_FW_PRE,
-	IWL_DEVICE_7000,
-	.ht_params = &iwl7000_ht_params,
-	.nvm_ver = IWL3160_NVM_VERSION,
-	.nvm_calib_ver = IWL3160_TX_POWER_VERSION,
-};
-
-MODULE_FIRMWARE(IWL7260_MODULE_FIRMWARE(IWL7260_UCODE_API_OK));
-MODULE_FIRMWARE(IWL3160_MODULE_FIRMWARE(IWL3160_UCODE_API_OK));
diff --git a/drivers/net/wireless/iwlwifi/pcie/cfg.h b/drivers/net/wireless/iwlwifi/pcie/cfg.h
deleted file mode 100644
index c6f8e83..0000000
--- a/drivers/net/wireless/iwlwifi/pcie/cfg.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/******************************************************************************
- *
- * 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 - 2013 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 - 2013 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__
-
-
-/*
- * This file declares the config structures for all devices.
- */
-
-extern const struct iwl_cfg iwl5300_agn_cfg;
-extern const struct iwl_cfg iwl5100_agn_cfg;
-extern const struct iwl_cfg iwl5350_agn_cfg;
-extern const struct iwl_cfg iwl5100_bgn_cfg;
-extern const struct iwl_cfg iwl5100_abg_cfg;
-extern const struct iwl_cfg iwl5150_agn_cfg;
-extern const struct iwl_cfg iwl5150_abg_cfg;
-extern const struct iwl_cfg iwl6005_2agn_cfg;
-extern const struct iwl_cfg iwl6005_2abg_cfg;
-extern const struct iwl_cfg iwl6005_2bg_cfg;
-extern const struct iwl_cfg iwl6005_2agn_sff_cfg;
-extern const struct iwl_cfg iwl6005_2agn_d_cfg;
-extern const struct iwl_cfg iwl6005_2agn_mow1_cfg;
-extern const struct iwl_cfg iwl6005_2agn_mow2_cfg;
-extern const struct iwl_cfg iwl1030_bgn_cfg;
-extern const struct iwl_cfg iwl1030_bg_cfg;
-extern const struct iwl_cfg iwl6030_2agn_cfg;
-extern const struct iwl_cfg iwl6030_2abg_cfg;
-extern const struct iwl_cfg iwl6030_2bgn_cfg;
-extern const struct iwl_cfg iwl6030_2bg_cfg;
-extern const struct iwl_cfg iwl6000i_2agn_cfg;
-extern const struct iwl_cfg iwl6000i_2abg_cfg;
-extern const struct iwl_cfg iwl6000i_2bg_cfg;
-extern const struct iwl_cfg iwl6000_3agn_cfg;
-extern const struct iwl_cfg iwl6050_2agn_cfg;
-extern const struct iwl_cfg iwl6050_2abg_cfg;
-extern const struct iwl_cfg iwl6150_bgn_cfg;
-extern const struct iwl_cfg iwl6150_bg_cfg;
-extern const struct iwl_cfg iwl1000_bgn_cfg;
-extern const struct iwl_cfg iwl1000_bg_cfg;
-extern const struct iwl_cfg iwl100_bgn_cfg;
-extern const struct iwl_cfg iwl100_bg_cfg;
-extern const struct iwl_cfg iwl130_bgn_cfg;
-extern const struct iwl_cfg iwl130_bg_cfg;
-extern const struct iwl_cfg iwl2000_2bgn_cfg;
-extern const struct iwl_cfg iwl2000_2bgn_d_cfg;
-extern const struct iwl_cfg iwl2030_2bgn_cfg;
-extern const struct iwl_cfg iwl6035_2agn_cfg;
-extern const struct iwl_cfg iwl105_bgn_cfg;
-extern const struct iwl_cfg iwl105_bgn_d_cfg;
-extern const struct iwl_cfg iwl135_bgn_cfg;
-extern const struct iwl_cfg iwl7260_2ac_cfg;
-extern const struct iwl_cfg iwl3160_ac_cfg;
-
-#endif /* __iwl_pci_h__ */
diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c
index 7bc0fb9..46ca91f 100644
--- a/drivers/net/wireless/iwlwifi/pcie/drv.c
+++ b/drivers/net/wireless/iwlwifi/pcie/drv.c
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
@@ -69,8 +69,6 @@
 
 #include "iwl-trans.h"
 #include "iwl-drv.h"
-
-#include "cfg.h"
 #include "internal.h"
 
 #define IWL_PCI_DEVICE(dev, subdev, cfg) \
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c
index 17bedc5..50ba0a4 100644
--- a/drivers/net/wireless/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/iwlwifi/pcie/trans.c
@@ -22,7 +22,7 @@
  * USA
  *
  * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
+ * in the file called COPYING.
  *
  * Contact Information:
  *  Intel Linux Wireless <ilw@linux.intel.com>
@@ -475,6 +475,10 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans,
 
 	/* If platform's RF_KILL switch is NOT set to KILL */
 	hw_rfkill = iwl_is_rfkill_set(trans);
+	if (hw_rfkill)
+		set_bit(STATUS_RFKILL, &trans_pcie->status);
+	else
+		clear_bit(STATUS_RFKILL, &trans_pcie->status);
 	iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill);
 	if (hw_rfkill && !run_in_rfkill)
 		return -ERFKILL;
@@ -641,6 +645,7 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans,
 
 static int iwl_trans_pcie_start_hw(struct iwl_trans *trans)
 {
+	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 	bool hw_rfkill;
 	int err;
 
@@ -656,6 +661,10 @@ static int iwl_trans_pcie_start_hw(struct iwl_trans *trans)
 	iwl_enable_rfkill_int(trans);
 
 	hw_rfkill = iwl_is_rfkill_set(trans);
+	if (hw_rfkill)
+		set_bit(STATUS_RFKILL, &trans_pcie->status);
+	else
+		clear_bit(STATUS_RFKILL, &trans_pcie->status);
 	iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill);
 
 	return 0;
@@ -694,6 +703,10 @@ static void iwl_trans_pcie_stop_hw(struct iwl_trans *trans,
 		 * op_mode.
 		 */
 		hw_rfkill = iwl_is_rfkill_set(trans);
+		if (hw_rfkill)
+			set_bit(STATUS_RFKILL, &trans_pcie->status);
+		else
+			clear_bit(STATUS_RFKILL, &trans_pcie->status);
 		iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill);
 	}
 }
@@ -715,7 +728,8 @@ static u32 iwl_trans_pcie_read32(struct iwl_trans *trans, u32 ofs)
 
 static u32 iwl_trans_pcie_read_prph(struct iwl_trans *trans, u32 reg)
 {
-	iwl_trans_pcie_write32(trans, HBUS_TARG_PRPH_RADDR, reg | (3 << 24));
+	iwl_trans_pcie_write32(trans, HBUS_TARG_PRPH_RADDR,
+			       ((reg & 0x000FFFFF) | (3 << 24)));
 	return iwl_trans_pcie_read32(trans, HBUS_TARG_PRPH_RDAT);
 }
 
@@ -723,7 +737,7 @@ static void iwl_trans_pcie_write_prph(struct iwl_trans *trans, u32 addr,
 				      u32 val)
 {
 	iwl_trans_pcie_write32(trans, HBUS_TARG_PRPH_WADDR,
-			       ((addr & 0x0000FFFF) | (3 << 24)));
+			       ((addr & 0x000FFFFF) | (3 << 24)));
 	iwl_trans_pcie_write32(trans, HBUS_TARG_PRPH_WDAT, val);
 }
 
@@ -1370,28 +1384,11 @@ static ssize_t iwl_dbgfs_fh_reg_read(struct file *file,
 	return ret;
 }
 
-static ssize_t iwl_dbgfs_fw_restart_write(struct file *file,
-					  const char __user *user_buf,
-					  size_t count, loff_t *ppos)
-{
-	struct iwl_trans *trans = file->private_data;
-
-	if (!trans->op_mode)
-		return -EAGAIN;
-
-	local_bh_disable();
-	iwl_op_mode_nic_error(trans->op_mode);
-	local_bh_enable();
-
-	return count;
-}
-
 DEBUGFS_READ_WRITE_FILE_OPS(interrupt);
 DEBUGFS_READ_FILE_OPS(fh_reg);
 DEBUGFS_READ_FILE_OPS(rx_queue);
 DEBUGFS_READ_FILE_OPS(tx_queue);
 DEBUGFS_WRITE_FILE_OPS(csr);
-DEBUGFS_WRITE_FILE_OPS(fw_restart);
 
 /*
  * Create the debugfs files and directories
@@ -1405,7 +1402,6 @@ static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans,
 	DEBUGFS_ADD_FILE(interrupt, dir, S_IWUSR | S_IRUSR);
 	DEBUGFS_ADD_FILE(csr, dir, S_IWUSR);
 	DEBUGFS_ADD_FILE(fh_reg, dir, S_IRUSR);
-	DEBUGFS_ADD_FILE(fw_restart, dir, S_IWUSR);
 	return 0;
 
 err:
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c
index 8595c16..68466ca 100644
--- a/drivers/net/wireless/iwlwifi/pcie/tx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/tx.c
@@ -501,10 +501,8 @@ static int iwl_pcie_txq_alloc(struct iwl_trans *trans,
 	 * shared with device */
 	txq->tfds = dma_alloc_coherent(trans->dev, tfd_sz,
 				       &txq->q.dma_addr, GFP_KERNEL);
-	if (!txq->tfds) {
-		IWL_ERR(trans, "dma_alloc_coherent(%zd) failed\n", tfd_sz);
+	if (!txq->tfds)
 		goto error;
-	}
 
 	BUILD_BUG_ON(IWL_HCMD_SCRATCHBUF_SIZE != sizeof(*txq->scratchbufs));
 	BUILD_BUG_ON(offsetof(struct iwl_pcie_txq_scratch_buf, scratch) !=
@@ -1264,7 +1262,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
 	for (i = 0; i < IWL_MAX_CMD_TBS_PER_TFD; i++) {
 		int copy = 0;
 
-		if (!cmd->len)
+		if (!cmd->len[i])
 			continue;
 
 		/* need at least IWL_HCMD_SCRATCHBUF_SIZE copied */
@@ -1566,8 +1564,11 @@ int iwl_trans_pcie_send_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
 	if (test_bit(STATUS_FW_ERROR, &trans_pcie->status))
 		return -EIO;
 
-	if (test_bit(STATUS_RFKILL, &trans_pcie->status))
+	if (test_bit(STATUS_RFKILL, &trans_pcie->status)) {
+		IWL_DEBUG_RF_KILL(trans, "Dropping CMD 0x%x: RF KILL\n",
+				  cmd->id);
 		return -ERFKILL;
+	}
 
 	if (cmd->flags & CMD_ASYNC)
 		return iwl_pcie_send_hcmd_async(trans, cmd);
@@ -1609,7 +1610,7 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
 	 * Check here that the packets are in the right place on the ring.
 	 */
 #ifdef CONFIG_IWLWIFI_DEBUG
-	wifi_seq = SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl));
+	wifi_seq = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl));
 	WARN_ONCE((iwl_read_prph(trans, SCD_AGGR_SEL) & BIT(txq_id)) &&
 		  ((wifi_seq & 0xff) != q->write_ptr),
 		  "Q: %d WiFi Seq %d tfdNum %d",
diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c
index 16beaf3..c94dd68 100644
--- a/drivers/net/wireless/libertas/if_cs.c
+++ b/drivers/net/wireless/libertas/if_cs.c
@@ -999,7 +999,6 @@ static const struct pcmcia_device_id if_cs_ids[] = {
 };
 MODULE_DEVICE_TABLE(pcmcia, if_cs_ids);
 
-
 static struct pcmcia_driver lbs_driver = {
 	.owner		= THIS_MODULE,
 	.name		= DRV_NAME,
@@ -1007,26 +1006,4 @@ static struct pcmcia_driver lbs_driver = {
 	.remove		= if_cs_detach,
 	.id_table       = if_cs_ids,
 };
-
-
-static int __init if_cs_init(void)
-{
-	int ret;
-
-	lbs_deb_enter(LBS_DEB_CS);
-	ret = pcmcia_register_driver(&lbs_driver);
-	lbs_deb_leave(LBS_DEB_CS);
-	return ret;
-}
-
-
-static void __exit if_cs_exit(void)
-{
-	lbs_deb_enter(LBS_DEB_CS);
-	pcmcia_unregister_driver(&lbs_driver);
-	lbs_deb_leave(LBS_DEB_CS);
-}
-
-
-module_init(if_cs_init);
-module_exit(if_cs_exit);
+module_pcmcia_driver(lbs_driver);
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index cffdf4f..0064d38 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -964,6 +964,12 @@ static int mac80211_hwsim_change_interface(struct ieee80211_hw *hw,
 		    newtype, vif->addr);
 	hwsim_check_magic(vif);
 
+	/*
+	 * interface may change from non-AP to AP in
+	 * which case this needs to be set up again
+	 */
+	vif->cab_queue = 0;
+
 	return 0;
 }
 
@@ -1389,7 +1395,7 @@ static int mac80211_hwsim_ampdu_action(struct ieee80211_hw *hw,
 	return 0;
 }
 
-static void mac80211_hwsim_flush(struct ieee80211_hw *hw, bool drop)
+static void mac80211_hwsim_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
 {
 	/* Not implemented, queues only on kernel side */
 }
@@ -1535,7 +1541,8 @@ static void hw_roc_done(struct work_struct *work)
 static int mac80211_hwsim_roc(struct ieee80211_hw *hw,
 			      struct ieee80211_vif *vif,
 			      struct ieee80211_channel *chan,
-			      int duration)
+			      int duration,
+			      enum ieee80211_roc_type type)
 {
 	struct mac80211_hwsim_data *hwsim = hw->priv;
 
diff --git a/drivers/net/wireless/mwifiex/11ac.c b/drivers/net/wireless/mwifiex/11ac.c
index cf43b3c..966a78f 100644
--- a/drivers/net/wireless/mwifiex/11ac.c
+++ b/drivers/net/wireless/mwifiex/11ac.c
@@ -259,3 +259,44 @@ int mwifiex_cmd_append_11ac_tlv(struct mwifiex_private *priv,
 
 	return ret_len;
 }
+
+int mwifiex_cmd_11ac_cfg(struct mwifiex_private *priv,
+			 struct host_cmd_ds_command *cmd, u16 cmd_action,
+			 struct mwifiex_11ac_vht_cfg *cfg)
+{
+	struct host_cmd_11ac_vht_cfg *vhtcfg = &cmd->params.vht_cfg;
+
+	cmd->command = cpu_to_le16(HostCmd_CMD_11AC_CFG);
+	cmd->size = cpu_to_le16(sizeof(struct host_cmd_11ac_vht_cfg) +
+				S_DS_GEN);
+	vhtcfg->action = cpu_to_le16(cmd_action);
+	vhtcfg->band_config = cfg->band_config;
+	vhtcfg->misc_config = cfg->misc_config;
+	vhtcfg->cap_info = cpu_to_le32(cfg->cap_info);
+	vhtcfg->mcs_tx_set = cpu_to_le32(cfg->mcs_tx_set);
+	vhtcfg->mcs_rx_set = cpu_to_le32(cfg->mcs_rx_set);
+
+	return 0;
+}
+
+/* This function initializes the BlockACK setup information for given
+ * mwifiex_private structure for 11ac enabled networks.
+ */
+void mwifiex_set_11ac_ba_params(struct mwifiex_private *priv)
+{
+	priv->add_ba_param.timeout = MWIFIEX_DEFAULT_BLOCK_ACK_TIMEOUT;
+
+	if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) {
+		priv->add_ba_param.tx_win_size =
+					   MWIFIEX_11AC_UAP_AMPDU_DEF_TXWINSIZE;
+		priv->add_ba_param.rx_win_size =
+					   MWIFIEX_11AC_UAP_AMPDU_DEF_RXWINSIZE;
+	} else {
+		priv->add_ba_param.tx_win_size =
+					   MWIFIEX_11AC_STA_AMPDU_DEF_TXWINSIZE;
+		priv->add_ba_param.rx_win_size =
+					   MWIFIEX_11AC_STA_AMPDU_DEF_RXWINSIZE;
+	}
+
+	return;
+}
diff --git a/drivers/net/wireless/mwifiex/11ac.h b/drivers/net/wireless/mwifiex/11ac.h
index 80fd1ba..7c2c69b 100644
--- a/drivers/net/wireless/mwifiex/11ac.h
+++ b/drivers/net/wireless/mwifiex/11ac.h
@@ -20,7 +20,24 @@
 #ifndef _MWIFIEX_11AC_H_
 #define _MWIFIEX_11AC_H_
 
+#define VHT_CFG_2GHZ BIT(0)
+#define VHT_CFG_5GHZ BIT(1)
+
+enum vht_cfg_misc_config {
+	VHT_CAP_TX_OPERATION = 1,
+	VHT_CAP_ASSOCIATION,
+	VHT_CAP_UAP_ONLY
+};
+
+#define DEFAULT_VHT_MCS_SET 0xfffa
+#define DISABLE_VHT_MCS_SET 0xffff
+
+#define VHT_BW_80_160_80P80 BIT(2)
+
 int mwifiex_cmd_append_11ac_tlv(struct mwifiex_private *priv,
 				struct mwifiex_bssdescriptor *bss_desc,
 				u8 **buffer);
+int mwifiex_cmd_11ac_cfg(struct mwifiex_private *priv,
+			 struct host_cmd_ds_command *cmd, u16 cmd_action,
+			 struct mwifiex_11ac_vht_cfg *cfg);
 #endif /* _MWIFIEX_11AC_H_ */
diff --git a/drivers/net/wireless/mwifiex/11n.c b/drivers/net/wireless/mwifiex/11n.c
index 45f1971..41e9d25 100644
--- a/drivers/net/wireless/mwifiex/11n.c
+++ b/drivers/net/wireless/mwifiex/11n.c
@@ -679,3 +679,25 @@ void mwifiex_del_tx_ba_stream_tbl_by_ra(struct mwifiex_private *priv, u8 *ra)
 
 	return;
 }
+
+/* This function initializes the BlockACK setup information for given
+ * mwifiex_private structure.
+ */
+void mwifiex_set_ba_params(struct mwifiex_private *priv)
+{
+	priv->add_ba_param.timeout = MWIFIEX_DEFAULT_BLOCK_ACK_TIMEOUT;
+
+	if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) {
+		priv->add_ba_param.tx_win_size =
+						MWIFIEX_UAP_AMPDU_DEF_TXWINSIZE;
+		priv->add_ba_param.rx_win_size =
+						MWIFIEX_UAP_AMPDU_DEF_RXWINSIZE;
+	} else {
+		priv->add_ba_param.tx_win_size =
+						MWIFIEX_STA_AMPDU_DEF_TXWINSIZE;
+		priv->add_ba_param.rx_win_size =
+						MWIFIEX_STA_AMPDU_DEF_RXWINSIZE;
+	}
+
+	return;
+}
diff --git a/drivers/net/wireless/mwifiex/Makefile b/drivers/net/wireless/mwifiex/Makefile
index 97b245c..ecf2846 100644
--- a/drivers/net/wireless/mwifiex/Makefile
+++ b/drivers/net/wireless/mwifiex/Makefile
@@ -39,6 +39,7 @@ mwifiex-y += sta_tx.o
 mwifiex-y += sta_rx.o
 mwifiex-y += uap_txrx.o
 mwifiex-y += cfg80211.o
+mwifiex-y += ethtool.o
 mwifiex-$(CONFIG_DEBUG_FS) += debugfs.o
 obj-$(CONFIG_MWIFIEX) += mwifiex.o
 
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c
index a44023a..8fc311f 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -216,7 +216,7 @@ mwifiex_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
 	mwifiex_form_mgmt_frame(skb, buf, len);
 	mwifiex_queue_tx_pkt(priv, skb);
 
-	*cookie = random32() | 1;
+	*cookie = prandom_u32() | 1;
 	cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, true, GFP_ATOMIC);
 
 	wiphy_dbg(wiphy, "info: management frame transmitted\n");
@@ -271,7 +271,7 @@ mwifiex_cfg80211_remain_on_channel(struct wiphy *wiphy,
 					 duration);
 
 	if (!ret) {
-		*cookie = random32() | 1;
+		*cookie = prandom_u32() | 1;
 		priv->roc_cfg.cookie = *cookie;
 		priv->roc_cfg.chan = *chan;
 
@@ -1374,6 +1374,18 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,
 	}
 
 	mwifiex_set_ht_params(priv, bss_cfg, params);
+
+	if (priv->adapter->is_hw_11ac_capable) {
+		mwifiex_set_vht_params(priv, bss_cfg, params);
+		mwifiex_set_vht_width(priv, params->chandef.width,
+				      priv->ap_11ac_enabled);
+	}
+
+	if (priv->ap_11ac_enabled)
+		mwifiex_set_11ac_ba_params(priv);
+	else
+		mwifiex_set_ba_params(priv);
+
 	mwifiex_set_wmm_params(priv, bss_cfg, params);
 
 	if (params->inactivity_timeout > 0) {
@@ -1892,7 +1904,8 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy,
 		}
 	}
 
-	for (i = 0; i < request->n_channels; i++) {
+	for (i = 0; i < min_t(u32, request->n_channels,
+			      MWIFIEX_USER_SCAN_CHAN_MAX); i++) {
 		chan = request->channels[i];
 		priv->user_scan_cfg->chan_list[i].chan_number = chan->hw_value;
 		priv->user_scan_cfg->chan_list[i].radio_type = chan->band;
@@ -1932,66 +1945,10 @@ static void mwifiex_setup_vht_caps(struct ieee80211_sta_vht_cap *vht_info,
 				   struct mwifiex_private *priv)
 {
 	struct mwifiex_adapter *adapter = priv->adapter;
-	u32 vht_cap = 0, cap = adapter->hw_dot_11ac_dev_cap;
 
 	vht_info->vht_supported = true;
 
-	switch (GET_VHTCAP_MAXMPDULEN(cap)) {
-	case 0x00:
-		vht_cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895;
-		break;
-	case 0x01:
-		vht_cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991;
-		break;
-	case 0x10:
-		vht_cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454;
-	    break;
-	default:
-	    dev_err(adapter->dev, "unsupported MAX MPDU len\n");
-	    break;
-	}
-
-	if (ISSUPP_11ACVHTHTCVHT(cap))
-		vht_cap |= IEEE80211_VHT_CAP_HTC_VHT;
-
-	if (ISSUPP_11ACVHTTXOPPS(cap))
-		vht_cap |= IEEE80211_VHT_CAP_VHT_TXOP_PS;
-
-	if (ISSUPP_11ACMURXBEAMFORMEE(cap))
-		vht_cap |= IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE;
-
-	if (ISSUPP_11ACMUTXBEAMFORMEE(cap))
-		vht_cap |= IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE;
-
-	if (ISSUPP_11ACSUBEAMFORMER(cap))
-		vht_cap |= IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE;
-
-	if (ISSUPP_11ACSUBEAMFORMEE(cap))
-		vht_cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE;
-
-	if (ISSUPP_11ACRXSTBC(cap))
-		vht_cap |= IEEE80211_VHT_CAP_RXSTBC_1;
-
-	if (ISSUPP_11ACTXSTBC(cap))
-		vht_cap |= IEEE80211_VHT_CAP_TXSTBC;
-
-	if (ISSUPP_11ACSGI160(cap))
-		vht_cap |= IEEE80211_VHT_CAP_SHORT_GI_160;
-
-	if (ISSUPP_11ACSGI80(cap))
-		vht_cap |= IEEE80211_VHT_CAP_SHORT_GI_80;
-
-	if (ISSUPP_11ACLDPC(cap))
-		vht_cap |= IEEE80211_VHT_CAP_RXLDPC;
-
-	if (ISSUPP_11ACBW8080(cap))
-		vht_cap |= IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
-
-	if (ISSUPP_11ACBW160(cap))
-		vht_cap |= IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
-
-	vht_info->cap = vht_cap;
-
+	vht_info->cap = adapter->hw_dot_11ac_dev_cap;
 	/* Update MCS support for VHT */
 	vht_info->vht_mcs.rx_mcs_map = cpu_to_le16(
 				adapter->hw_dot_11ac_mcs_support & 0xFFFF);
@@ -2235,6 +2192,7 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
 	dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
 	dev->watchdog_timeo = MWIFIEX_DEFAULT_WATCHDOG_TIMEOUT;
 	dev->hard_header_len += MWIFIEX_MIN_DATA_HEADER_LEN;
+	dev->ethtool_ops = &mwifiex_ethtool_ops;
 
 	mdev_priv = netdev_priv(dev);
 	*((unsigned long *) mdev_priv) = (unsigned long) priv;
@@ -2293,6 +2251,152 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
 }
 EXPORT_SYMBOL_GPL(mwifiex_del_virtual_intf);
 
+#ifdef CONFIG_PM
+static bool
+mwifiex_is_pattern_supported(struct cfg80211_wowlan_trig_pkt_pattern *pat,
+			     s8 *byte_seq)
+{
+	int j, k, valid_byte_cnt = 0;
+	bool dont_care_byte = false;
+
+	for (j = 0; j < DIV_ROUND_UP(pat->pattern_len, 8); j++) {
+		for (k = 0; k < 8; k++) {
+			if (pat->mask[j] & 1 << k) {
+				memcpy(byte_seq + valid_byte_cnt,
+				       &pat->pattern[j * 8 + k], 1);
+				valid_byte_cnt++;
+				if (dont_care_byte)
+					return false;
+			} else {
+				if (valid_byte_cnt)
+					dont_care_byte = true;
+			}
+
+			if (valid_byte_cnt > MAX_BYTESEQ)
+				return false;
+		}
+	}
+
+	byte_seq[MAX_BYTESEQ] = valid_byte_cnt;
+
+	return true;
+}
+
+static int mwifiex_cfg80211_suspend(struct wiphy *wiphy,
+				    struct cfg80211_wowlan *wowlan)
+{
+	struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
+	struct mwifiex_ds_mef_cfg mef_cfg;
+	struct mwifiex_mef_entry *mef_entry;
+	int i, filt_num = 0, ret;
+	bool first_pat = true;
+	u8 byte_seq[MAX_BYTESEQ + 1];
+	const u8 ipv4_mc_mac[] = {0x33, 0x33};
+	const u8 ipv6_mc_mac[] = {0x01, 0x00, 0x5e};
+	struct mwifiex_private *priv =
+			mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA);
+
+	if (!wowlan) {
+		dev_warn(adapter->dev, "None of the WOWLAN triggers enabled\n");
+		return 0;
+	}
+
+	if (!priv->media_connected) {
+		dev_warn(adapter->dev,
+			 "Can not configure WOWLAN in disconnected state\n");
+		return 0;
+	}
+
+	mef_entry = kzalloc(sizeof(*mef_entry), GFP_KERNEL);
+	if (!mef_entry)
+		return -ENOMEM;
+
+	memset(&mef_cfg, 0, sizeof(mef_cfg));
+	mef_cfg.num_entries = 1;
+	mef_cfg.mef_entry = mef_entry;
+	mef_entry->mode = MEF_MODE_HOST_SLEEP;
+	mef_entry->action = MEF_ACTION_ALLOW_AND_WAKEUP_HOST;
+
+	for (i = 0; i < wowlan->n_patterns; i++) {
+		memset(byte_seq, 0, sizeof(byte_seq));
+		if (!mwifiex_is_pattern_supported(&wowlan->patterns[i],
+						  byte_seq)) {
+			wiphy_err(wiphy, "Pattern not supported\n");
+			kfree(mef_entry);
+			return -EOPNOTSUPP;
+		}
+
+		if (!wowlan->patterns[i].pkt_offset) {
+			if (!(byte_seq[0] & 0x01) &&
+			    (byte_seq[MAX_BYTESEQ] == 1)) {
+				mef_cfg.criteria |= MWIFIEX_CRITERIA_UNICAST;
+				continue;
+			} else if (is_broadcast_ether_addr(byte_seq)) {
+				mef_cfg.criteria |= MWIFIEX_CRITERIA_BROADCAST;
+				continue;
+			} else if ((!memcmp(byte_seq, ipv4_mc_mac, 2) &&
+				    (byte_seq[MAX_BYTESEQ] == 2)) ||
+				   (!memcmp(byte_seq, ipv6_mc_mac, 3) &&
+				    (byte_seq[MAX_BYTESEQ] == 3))) {
+				mef_cfg.criteria |= MWIFIEX_CRITERIA_MULTICAST;
+				continue;
+			}
+		}
+
+		mef_entry->filter[filt_num].repeat = 1;
+		mef_entry->filter[filt_num].offset =
+						wowlan->patterns[i].pkt_offset;
+		memcpy(mef_entry->filter[filt_num].byte_seq, byte_seq,
+		       sizeof(byte_seq));
+		mef_entry->filter[filt_num].filt_type = TYPE_EQ;
+
+		if (first_pat)
+			first_pat = false;
+		else
+			mef_entry->filter[filt_num].filt_action = TYPE_AND;
+
+		filt_num++;
+	}
+
+	if (wowlan->magic_pkt) {
+		mef_cfg.criteria |= MWIFIEX_CRITERIA_UNICAST;
+		mef_entry->filter[filt_num].repeat = 16;
+		memcpy(mef_entry->filter[filt_num].byte_seq, priv->curr_addr,
+		       ETH_ALEN);
+		mef_entry->filter[filt_num].byte_seq[MAX_BYTESEQ] = ETH_ALEN;
+		mef_entry->filter[filt_num].offset = 14;
+		mef_entry->filter[filt_num].filt_type = TYPE_EQ;
+		if (filt_num)
+			mef_entry->filter[filt_num].filt_action = TYPE_OR;
+	}
+
+	if (!mef_cfg.criteria)
+		mef_cfg.criteria = MWIFIEX_CRITERIA_BROADCAST |
+				   MWIFIEX_CRITERIA_UNICAST |
+				   MWIFIEX_CRITERIA_MULTICAST;
+
+	ret =  mwifiex_send_cmd_sync(priv, HostCmd_CMD_MEF_CFG,
+				     HostCmd_ACT_GEN_SET, 0,
+				     &mef_cfg);
+
+	kfree(mef_entry);
+	return ret;
+}
+
+static int mwifiex_cfg80211_resume(struct wiphy *wiphy)
+{
+	return 0;
+}
+
+static void mwifiex_cfg80211_set_wakeup(struct wiphy *wiphy,
+				       bool enabled)
+{
+	struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
+
+	device_set_wakeup_enable(adapter->dev, enabled);
+}
+#endif
+
 /* station cfg80211 operations */
 static struct cfg80211_ops mwifiex_cfg80211_ops = {
 	.add_virtual_intf = mwifiex_add_virtual_intf,
@@ -2321,6 +2425,11 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = {
 	.change_beacon = mwifiex_cfg80211_change_beacon,
 	.set_cqm_rssi_config = mwifiex_cfg80211_set_cqm_rssi_config,
 	.set_antenna = mwifiex_cfg80211_set_antenna,
+#ifdef CONFIG_PM
+	.suspend = mwifiex_cfg80211_suspend,
+	.resume = mwifiex_cfg80211_resume,
+	.set_wakeup = mwifiex_cfg80211_set_wakeup,
+#endif
 };
 
 /*
@@ -2379,6 +2488,14 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
 
 	wiphy_apply_custom_regulatory(wiphy, &mwifiex_world_regdom_custom);
 
+#ifdef CONFIG_PM
+	wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
+	wiphy->wowlan.n_patterns = MWIFIEX_MAX_FILTERS;
+	wiphy->wowlan.pattern_min_len = 1;
+	wiphy->wowlan.pattern_max_len = MWIFIEX_MAX_PATTERN_LEN;
+	wiphy->wowlan.max_pkt_offset = MWIFIEX_MAX_OFFSET_LEN;
+#endif
+
 	wiphy->probe_resp_offload = NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS |
 				    NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 |
 				    NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P;
diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c
index b5c8b96..9a1302b 100644
--- a/drivers/net/wireless/mwifiex/cmdevt.c
+++ b/drivers/net/wireless/mwifiex/cmdevt.c
@@ -1149,7 +1149,7 @@ int mwifiex_ret_802_11_hs_cfg(struct mwifiex_private *priv,
 			phs_cfg->params.hs_config.gpio,
 			phs_cfg->params.hs_config.gap);
 	}
-	if (conditions != HOST_SLEEP_CFG_CANCEL) {
+	if (conditions != HS_CFG_CANCEL) {
 		adapter->is_hs_configured = true;
 		if (adapter->iface_type == MWIFIEX_USB ||
 		    adapter->iface_type == MWIFIEX_PCIE)
diff --git a/drivers/net/wireless/mwifiex/decl.h b/drivers/net/wireless/mwifiex/decl.h
index e8a569a..94cc09d 100644
--- a/drivers/net/wireless/mwifiex/decl.h
+++ b/drivers/net/wireless/mwifiex/decl.h
@@ -41,8 +41,15 @@
 #define MWIFIEX_MAX_TX_BASTREAM_SUPPORTED	2
 #define MWIFIEX_MAX_RX_BASTREAM_SUPPORTED	16
 
-#define MWIFIEX_AMPDU_DEF_TXWINSIZE        32
-#define MWIFIEX_AMPDU_DEF_RXWINSIZE        16
+#define MWIFIEX_STA_AMPDU_DEF_TXWINSIZE        16
+#define MWIFIEX_STA_AMPDU_DEF_RXWINSIZE        32
+#define MWIFIEX_UAP_AMPDU_DEF_TXWINSIZE        32
+#define MWIFIEX_UAP_AMPDU_DEF_RXWINSIZE        16
+#define MWIFIEX_11AC_STA_AMPDU_DEF_TXWINSIZE   32
+#define MWIFIEX_11AC_STA_AMPDU_DEF_RXWINSIZE   48
+#define MWIFIEX_11AC_UAP_AMPDU_DEF_TXWINSIZE   48
+#define MWIFIEX_11AC_UAP_AMPDU_DEF_RXWINSIZE   32
+
 #define MWIFIEX_DEFAULT_BLOCK_ACK_TIMEOUT  0xffff
 
 #define MWIFIEX_RATE_BITMAP_MCS0   32
diff --git a/drivers/net/wireless/mwifiex/ethtool.c b/drivers/net/wireless/mwifiex/ethtool.c
new file mode 100644
index 0000000..bfb3990
--- /dev/null
+++ b/drivers/net/wireless/mwifiex/ethtool.c
@@ -0,0 +1,70 @@
+/*
+ * Marvell Wireless LAN device driver: ethtool
+ *
+ * Copyright (C) 2013, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+#include "main.h"
+
+static void mwifiex_ethtool_get_wol(struct net_device *dev,
+				    struct ethtool_wolinfo *wol)
+{
+	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+	u32 conditions = le32_to_cpu(priv->adapter->hs_cfg.conditions);
+
+	wol->supported = WAKE_UCAST|WAKE_MCAST|WAKE_BCAST|WAKE_PHY;
+
+	if (conditions == HS_CFG_COND_DEF)
+		return;
+
+	if (conditions & HS_CFG_COND_UNICAST_DATA)
+		wol->wolopts |= WAKE_UCAST;
+	if (conditions & HS_CFG_COND_MULTICAST_DATA)
+		wol->wolopts |= WAKE_MCAST;
+	if (conditions & HS_CFG_COND_BROADCAST_DATA)
+		wol->wolopts |= WAKE_BCAST;
+	if (conditions & HS_CFG_COND_MAC_EVENT)
+		wol->wolopts |= WAKE_PHY;
+}
+
+static int mwifiex_ethtool_set_wol(struct net_device *dev,
+				   struct ethtool_wolinfo *wol)
+{
+	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+	u32 conditions = 0;
+
+	if (wol->wolopts & ~(WAKE_UCAST|WAKE_MCAST|WAKE_BCAST|WAKE_PHY))
+		return -EOPNOTSUPP;
+
+	if (wol->wolopts & WAKE_UCAST)
+		conditions |= HS_CFG_COND_UNICAST_DATA;
+	if (wol->wolopts & WAKE_MCAST)
+		conditions |= HS_CFG_COND_MULTICAST_DATA;
+	if (wol->wolopts & WAKE_BCAST)
+		conditions |= HS_CFG_COND_BROADCAST_DATA;
+	if (wol->wolopts & WAKE_PHY)
+		conditions |= HS_CFG_COND_MAC_EVENT;
+	if (wol->wolopts == 0)
+		conditions |= HS_CFG_COND_DEF;
+	priv->adapter->hs_cfg.conditions = cpu_to_le32(conditions);
+
+	return 0;
+}
+
+const struct ethtool_ops mwifiex_ethtool_ops = {
+	.get_wol = mwifiex_ethtool_get_wol,
+	.set_wol = mwifiex_ethtool_set_wol,
+};
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h
index 25acb06..1f7578d 100644
--- a/drivers/net/wireless/mwifiex/fw.h
+++ b/drivers/net/wireless/mwifiex/fw.h
@@ -230,40 +230,12 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
 
 #define ISSUPP_11ACENABLED(fw_cap_info) (fw_cap_info & (BIT(13)|BIT(14)))
 
-#define GET_VHTCAP_MAXMPDULEN(vht_cap_info) (vht_cap_info & 0x3)
 #define GET_VHTCAP_CHWDSET(vht_cap_info)    ((vht_cap_info >> 2) & 0x3)
 #define GET_VHTNSSMCS(mcs_mapset, nss) ((mcs_mapset >> (2 * (nss - 1))) & 0x3)
 #define SET_VHTNSSMCS(mcs_mapset, nss, value) (mcs_mapset |= (value & 0x3) << \
 					      (2 * (nss - 1)))
 #define NO_NSS_SUPPORT		0x3
 
-/* HW_SPEC: HTC-VHT supported */
-#define ISSUPP_11ACVHTHTCVHT(Dot11acDevCap) (Dot11acDevCap & BIT(22))
-/* HW_SPEC: VHT TXOP PS support */
-#define ISSUPP_11ACVHTTXOPPS(Dot11acDevCap) (Dot11acDevCap & BIT(21))
-/* HW_SPEC: MU RX beamformee support */
-#define ISSUPP_11ACMURXBEAMFORMEE(Dot11acDevCap) (Dot11acDevCap & BIT(20))
-/* HW_SPEC: MU TX beamformee support */
-#define ISSUPP_11ACMUTXBEAMFORMEE(Dot11acDevCap) (Dot11acDevCap & BIT(19))
-/* HW_SPEC: SU Beamformee support */
-#define ISSUPP_11ACSUBEAMFORMEE(Dot11acDevCap) (Dot11acDevCap & BIT(10))
-/* HW_SPEC: SU Beamformer support */
-#define ISSUPP_11ACSUBEAMFORMER(Dot11acDevCap) (Dot11acDevCap & BIT(9))
-/* HW_SPEC: Rx STBC support */
-#define ISSUPP_11ACRXSTBC(Dot11acDevCap) (Dot11acDevCap & BIT(8))
-/* HW_SPEC: Tx STBC support */
-#define ISSUPP_11ACTXSTBC(Dot11acDevCap) (Dot11acDevCap & BIT(7))
-/* HW_SPEC: Short GI support for 160MHz BW */
-#define ISSUPP_11ACSGI160(Dot11acDevCap) (Dot11acDevCap & BIT(6))
-/* HW_SPEC: Short GI support for 80MHz BW */
-#define ISSUPP_11ACSGI80(Dot11acDevCap) (Dot11acDevCap & BIT(5))
-/* HW_SPEC: LDPC coding support */
-#define ISSUPP_11ACLDPC(Dot11acDevCap) (Dot11acDevCap & BIT(4))
-/* HW_SPEC: Channel BW 20/40/80/160/80+80 MHz support */
-#define ISSUPP_11ACBW8080(Dot11acDevCap) (Dot11acDevCap & BIT(3))
-/* HW_SPEC: Channel BW 20/40/80/160 MHz support */
-#define ISSUPP_11ACBW160(Dot11acDevCap) (Dot11acDevCap & BIT(2))
-
 #define GET_DEVTXMCSMAP(dev_mcs_map)      (dev_mcs_map >> 16)
 #define GET_DEVRXMCSMAP(dev_mcs_map)      (dev_mcs_map & 0xFFFF)
 
@@ -300,6 +272,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
 #define HostCmd_CMD_802_11_TX_RATE_QUERY              0x007f
 #define HostCmd_CMD_802_11_IBSS_COALESCING_STATUS     0x0083
 #define HostCmd_CMD_VERSION_EXT                       0x0097
+#define HostCmd_CMD_MEF_CFG                           0x009a
 #define HostCmd_CMD_RSSI_INFO                         0x00a4
 #define HostCmd_CMD_FUNC_INIT                         0x00a9
 #define HostCmd_CMD_FUNC_SHUTDOWN                     0x00aa
@@ -322,6 +295,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
 #define HostCmd_CMD_PCIE_DESC_DETAILS                 0x00fa
 #define HostCmd_CMD_MGMT_FRAME_REG                    0x010c
 #define HostCmd_CMD_REMAIN_ON_CHAN                    0x010d
+#define HostCmd_CMD_11AC_CFG			      0x0112
 
 #define PROTOCOL_NO_SECURITY        0x01
 #define PROTOCOL_STATIC_WEP         0x02
@@ -376,10 +350,14 @@ enum P2P_MODES {
 #define HostCmd_SCAN_RADIO_TYPE_BG          0
 #define HostCmd_SCAN_RADIO_TYPE_A           1
 
-#define HOST_SLEEP_CFG_CANCEL		0xffffffff
-#define HOST_SLEEP_CFG_COND_DEF		0x00000000
-#define HOST_SLEEP_CFG_GPIO_DEF		0xff
-#define HOST_SLEEP_CFG_GAP_DEF		0
+#define HS_CFG_CANCEL			0xffffffff
+#define HS_CFG_COND_DEF			0x00000000
+#define HS_CFG_GPIO_DEF			0xff
+#define HS_CFG_GAP_DEF			0
+#define HS_CFG_COND_BROADCAST_DATA	0x00000001
+#define HS_CFG_COND_UNICAST_DATA	0x00000002
+#define HS_CFG_COND_MAC_EVENT		0x00000004
+#define HS_CFG_COND_MULTICAST_DATA	0x00000008
 
 #define MWIFIEX_TIMEOUT_FOR_AP_RESP		0xfffc
 #define MWIFIEX_STATUS_CODE_AUTH_TIMEOUT	2
@@ -469,6 +447,23 @@ enum P2P_MODES {
 #define EVENT_GET_BSS_TYPE(event_cause)         \
 	(((event_cause) >> 24) & 0x00ff)
 
+#define MWIFIEX_MAX_PATTERN_LEN		20
+#define MWIFIEX_MAX_OFFSET_LEN		50
+#define STACK_NBYTES			100
+#define TYPE_DNUM			1
+#define TYPE_BYTESEQ			2
+#define MAX_OPERAND			0x40
+#define TYPE_EQ				(MAX_OPERAND+1)
+#define TYPE_EQ_DNUM			(MAX_OPERAND+2)
+#define TYPE_EQ_BIT			(MAX_OPERAND+3)
+#define TYPE_AND			(MAX_OPERAND+4)
+#define TYPE_OR				(MAX_OPERAND+5)
+#define MEF_MODE_HOST_SLEEP			1
+#define MEF_ACTION_ALLOW_AND_WAKEUP_HOST	3
+#define MWIFIEX_CRITERIA_BROADCAST	BIT(0)
+#define MWIFIEX_CRITERIA_UNICAST	BIT(1)
+#define MWIFIEX_CRITERIA_MULTICAST	BIT(3)
+
 struct mwifiex_ie_types_header {
 	__le16 type;
 	__le16 len;
@@ -1369,6 +1364,15 @@ struct host_cmd_ds_sys_config {
 	u8 tlv[0];
 };
 
+struct host_cmd_11ac_vht_cfg {
+	__le16 action;
+	u8 band_config;
+	u8 misc_config;
+	__le32 cap_info;
+	__le32 mcs_tx_set;
+	__le32 mcs_rx_set;
+} __packed;
+
 struct host_cmd_tlv_akmp {
 	struct host_cmd_tlv tlv;
 	__le16 key_mgmt;
@@ -1499,6 +1503,19 @@ struct host_cmd_ds_802_11_ibss_status {
 	__le16 use_g_rate_protect;
 } __packed;
 
+struct mwifiex_fw_mef_entry {
+	u8 mode;
+	u8 action;
+	__le16 exprsize;
+	u8 expr[0];
+} __packed;
+
+struct host_cmd_ds_mef_cfg {
+	__le32 criteria;
+	__le16 num_entries;
+	struct mwifiex_fw_mef_entry mef_entry[0];
+} __packed;
+
 #define CONNECTION_TYPE_INFRA   0
 #define CONNECTION_TYPE_ADHOC   1
 #define CONNECTION_TYPE_AP      2
@@ -1603,6 +1620,7 @@ struct host_cmd_ds_command {
 		struct host_cmd_ds_remain_on_chan roc_cfg;
 		struct host_cmd_ds_p2p_mode_cfg mode_cfg;
 		struct host_cmd_ds_802_11_ibss_status ibss_coalescing;
+		struct host_cmd_ds_mef_cfg mef_cfg;
 		struct host_cmd_ds_mac_reg_access mac_reg;
 		struct host_cmd_ds_bbp_reg_access bbp_reg;
 		struct host_cmd_ds_rf_reg_access rf_reg;
@@ -1612,6 +1630,7 @@ struct host_cmd_ds_command {
 		struct host_cmd_ds_802_11_eeprom_access eeprom;
 		struct host_cmd_ds_802_11_subsc_evt subsc_evt;
 		struct host_cmd_ds_sys_config uap_sys_config;
+		struct host_cmd_11ac_vht_cfg vht_cfg;
 	} params;
 } __packed;
 
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c
index 0ff4c37..daf8801 100644
--- a/drivers/net/wireless/mwifiex/init.c
+++ b/drivers/net/wireless/mwifiex/init.c
@@ -318,9 +318,9 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter)
 	adapter->curr_tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K;
 
 	adapter->is_hs_configured = false;
-	adapter->hs_cfg.conditions = cpu_to_le32(HOST_SLEEP_CFG_COND_DEF);
-	adapter->hs_cfg.gpio = HOST_SLEEP_CFG_GPIO_DEF;
-	adapter->hs_cfg.gap = HOST_SLEEP_CFG_GAP_DEF;
+	adapter->hs_cfg.conditions = cpu_to_le32(HS_CFG_COND_DEF);
+	adapter->hs_cfg.gpio = HS_CFG_GPIO_DEF;
+	adapter->hs_cfg.gap = HS_CFG_GAP_DEF;
 	adapter->hs_activated = false;
 
 	memset(adapter->event_body, 0, sizeof(adapter->event_body));
diff --git a/drivers/net/wireless/mwifiex/ioctl.h b/drivers/net/wireless/mwifiex/ioctl.h
index d85e6eb..7f27e45 100644
--- a/drivers/net/wireless/mwifiex/ioctl.h
+++ b/drivers/net/wireless/mwifiex/ioctl.h
@@ -272,6 +272,14 @@ struct mwifiex_ds_pm_cfg {
 	} param;
 };
 
+struct mwifiex_11ac_vht_cfg {
+	u8 band_config;
+	u8 misc_config;
+	u32 cap_info;
+	u32 mcs_tx_set;
+	u32 mcs_rx_set;
+};
+
 struct mwifiex_ds_11n_tx_cfg {
 	u16 tx_htcap;
 	u16 tx_htinfo;
@@ -354,6 +362,29 @@ struct mwifiex_ds_misc_subsc_evt {
 	struct subsc_evt_cfg bcn_h_rssi_cfg;
 };
 
+#define MAX_BYTESEQ		6	/* non-adjustable */
+#define MWIFIEX_MAX_FILTERS	10
+
+struct mwifiex_mef_filter {
+	u16 repeat;
+	u16 offset;
+	s8 byte_seq[MAX_BYTESEQ + 1];
+	u8 filt_type;
+	u8 filt_action;
+};
+
+struct mwifiex_mef_entry {
+	u8 mode;
+	u8 action;
+	struct mwifiex_mef_filter filter[MWIFIEX_MAX_FILTERS];
+};
+
+struct mwifiex_ds_mef_cfg {
+	u32 criteria;
+	u16 num_entries;
+	struct mwifiex_mef_entry *mef_entry;
+};
+
 #define MWIFIEX_MAX_VSIE_LEN       (256)
 #define MWIFIEX_MAX_VSIE_NUM       (8)
 #define MWIFIEX_VSIE_MASK_CLEAR    0x00
diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c
index 2fe0ceb..6bcb66e 100644
--- a/drivers/net/wireless/mwifiex/join.c
+++ b/drivers/net/wireless/mwifiex/join.c
@@ -1295,6 +1295,14 @@ int mwifiex_associate(struct mwifiex_private *priv,
 	    (bss_desc->bss_mode != NL80211_IFTYPE_STATION))
 		return -1;
 
+	if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info) &&
+	    !bss_desc->disable_11n && !bss_desc->disable_11ac &&
+	    (priv->adapter->config_bands & BAND_GAC ||
+	     priv->adapter->config_bands & BAND_AAC))
+		mwifiex_set_11ac_ba_params(priv);
+	else
+		mwifiex_set_ba_params(priv);
+
 	memcpy(&current_bssid,
 	       &priv->curr_bss_params.bss_descriptor.mac_address,
 	       sizeof(current_bssid));
@@ -1323,6 +1331,13 @@ mwifiex_adhoc_start(struct mwifiex_private *priv,
 	dev_dbg(priv->adapter->dev, "info: curr_bss_params.band = %d\n",
 		priv->curr_bss_params.band);
 
+	if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info) &&
+	    (priv->adapter->config_bands & BAND_GAC ||
+	     priv->adapter->config_bands & BAND_AAC))
+		mwifiex_set_11ac_ba_params(priv);
+	else
+		mwifiex_set_ba_params(priv);
+
 	return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_AD_HOC_START,
 				    HostCmd_ACT_GEN_SET, 0, adhoc_ssid);
 }
@@ -1356,6 +1371,14 @@ int mwifiex_adhoc_join(struct mwifiex_private *priv,
 		return -1;
 	}
 
+	if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info) &&
+	    !bss_desc->disable_11n && !bss_desc->disable_11ac &&
+	    (priv->adapter->config_bands & BAND_GAC ||
+	     priv->adapter->config_bands & BAND_AAC))
+		mwifiex_set_11ac_ba_params(priv);
+	else
+		mwifiex_set_ba_params(priv);
+
 	dev_dbg(priv->adapter->dev, "info: curr_bss_params.channel = %d\n",
 		priv->curr_bss_params.bss_descriptor.channel);
 	dev_dbg(priv->adapter->dev, "info: curr_bss_params.band = %c\n",
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c
index 9c802ed..121443a 100644
--- a/drivers/net/wireless/mwifiex/main.c
+++ b/drivers/net/wireless/mwifiex/main.c
@@ -588,10 +588,19 @@ mwifiex_tx_timeout(struct net_device *dev)
 {
 	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
 
-	dev_err(priv->adapter->dev, "%lu : Tx timeout, bss_type-num = %d-%d\n",
-		jiffies, priv->bss_type, priv->bss_num);
-	mwifiex_set_trans_start(dev);
 	priv->num_tx_timeout++;
+	priv->tx_timeout_cnt++;
+	dev_err(priv->adapter->dev,
+		"%lu : Tx timeout(#%d), bss_type-num = %d-%d\n",
+		jiffies, priv->tx_timeout_cnt, priv->bss_type, priv->bss_num);
+	mwifiex_set_trans_start(dev);
+
+	if (priv->tx_timeout_cnt > TX_TIMEOUT_THRESHOLD &&
+	    priv->adapter->if_ops.card_reset) {
+		dev_err(priv->adapter->dev,
+			"tx_timeout_cnt exceeds threshold. Triggering card reset!\n");
+		priv->adapter->if_ops.card_reset(priv->adapter);
+	}
 }
 
 /*
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index 7035ade..cab8a85 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -130,6 +130,9 @@ enum {
 #define MWIFIEX_USB_TYPE_DATA			0xBEADC0DE
 #define MWIFIEX_USB_TYPE_EVENT			0xBEEFFACE
 
+/* Threshold for tx_timeout_cnt before we trigger a card reset */
+#define TX_TIMEOUT_THRESHOLD	6
+
 struct mwifiex_dbg {
 	u32 num_cmd_host_to_card_failure;
 	u32 num_cmd_sleep_cfm_host_to_card_failure;
@@ -394,6 +397,8 @@ struct mwifiex_private {
 	u8 curr_addr[ETH_ALEN];
 	u8 media_connected;
 	u32 num_tx_timeout;
+	/* track consecutive timeout */
+	u8 tx_timeout_cnt;
 	struct net_device *netdev;
 	struct net_device_stats stats;
 	u16 curr_pkt_filter;
@@ -907,12 +912,20 @@ int mwifiex_set_secure_params(struct mwifiex_private *priv,
 void mwifiex_set_ht_params(struct mwifiex_private *priv,
 			   struct mwifiex_uap_bss_param *bss_cfg,
 			   struct cfg80211_ap_settings *params);
+void mwifiex_set_vht_params(struct mwifiex_private *priv,
+			    struct mwifiex_uap_bss_param *bss_cfg,
+			    struct cfg80211_ap_settings *params);
 void mwifiex_set_uap_rates(struct mwifiex_uap_bss_param *bss_cfg,
 			   struct cfg80211_ap_settings *params);
+void mwifiex_set_vht_width(struct mwifiex_private *priv,
+			   enum nl80211_chan_width width,
+			   bool ap_11ac_disable);
 void
 mwifiex_set_wmm_params(struct mwifiex_private *priv,
 		       struct mwifiex_uap_bss_param *bss_cfg,
 		       struct cfg80211_ap_settings *params);
+void mwifiex_set_ba_params(struct mwifiex_private *priv);
+void mwifiex_set_11ac_ba_params(struct mwifiex_private *priv);
 
 /*
  * This function checks if the queuing is RA based or not.
@@ -1098,11 +1111,15 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev);
 
 void mwifiex_set_sys_config_invalid_data(struct mwifiex_uap_bss_param *config);
 
+int mwifiex_add_wowlan_magic_pkt_filter(struct mwifiex_adapter *adapter);
+
 int mwifiex_set_mgmt_ies(struct mwifiex_private *priv,
 			 struct cfg80211_beacon_data *data);
 int mwifiex_del_mgmt_ies(struct mwifiex_private *priv);
 u8 *mwifiex_11d_code_2_region(u8 code);
 
+extern const struct ethtool_ops mwifiex_ethtool_ops;
+
 #ifdef CONFIG_DEBUG_FS
 void mwifiex_debugfs_init(void);
 void mwifiex_debugfs_remove(void);
diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c
index 5c395e2..856959b 100644
--- a/drivers/net/wireless/mwifiex/pcie.c
+++ b/drivers/net/wireless/mwifiex/pcie.c
@@ -36,8 +36,6 @@ static u8 user_rmmod;
 static struct mwifiex_if_ops pcie_ops;
 
 static struct semaphore add_remove_card_sem;
-static int mwifiex_pcie_enable_host_int(struct mwifiex_adapter *adapter);
-static int mwifiex_pcie_resume(struct pci_dev *pdev);
 
 static int
 mwifiex_map_pci_memory(struct mwifiex_adapter *adapter, struct sk_buff *skb,
@@ -78,6 +76,82 @@ static bool mwifiex_pcie_ok_to_access_hw(struct mwifiex_adapter *adapter)
 	return false;
 }
 
+#ifdef CONFIG_PM
+/*
+ * Kernel needs to suspend all functions separately. Therefore all
+ * registered functions must have drivers with suspend and resume
+ * methods. Failing that the kernel simply removes the whole card.
+ *
+ * If already not suspended, this function allocates and sends a host
+ * sleep activate request to the firmware and turns off the traffic.
+ */
+static int mwifiex_pcie_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	struct mwifiex_adapter *adapter;
+	struct pcie_service_card *card;
+	int hs_actived;
+
+	if (pdev) {
+		card = (struct pcie_service_card *) pci_get_drvdata(pdev);
+		if (!card || !card->adapter) {
+			pr_err("Card or adapter structure is not valid\n");
+			return 0;
+		}
+	} else {
+		pr_err("PCIE device is not specified\n");
+		return 0;
+	}
+
+	adapter = card->adapter;
+
+	hs_actived = mwifiex_enable_hs(adapter);
+
+	/* Indicate device suspended */
+	adapter->is_suspended = true;
+
+	return 0;
+}
+
+/*
+ * Kernel needs to suspend all functions separately. Therefore all
+ * registered functions must have drivers with suspend and resume
+ * methods. Failing that the kernel simply removes the whole card.
+ *
+ * If already not resumed, this function turns on the traffic and
+ * sends a host sleep cancel request to the firmware.
+ */
+static int mwifiex_pcie_resume(struct pci_dev *pdev)
+{
+	struct mwifiex_adapter *adapter;
+	struct pcie_service_card *card;
+
+	if (pdev) {
+		card = (struct pcie_service_card *) pci_get_drvdata(pdev);
+		if (!card || !card->adapter) {
+			pr_err("Card or adapter structure is not valid\n");
+			return 0;
+		}
+	} else {
+		pr_err("PCIE device is not specified\n");
+		return 0;
+	}
+
+	adapter = card->adapter;
+
+	if (!adapter->is_suspended) {
+		dev_warn(adapter->dev, "Device already resumed\n");
+		return 0;
+	}
+
+	adapter->is_suspended = false;
+
+	mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA),
+			  MWIFIEX_ASYNC_CMD);
+
+	return 0;
+}
+#endif
+
 /*
  * This function probes an mwifiex device and registers it. It allocates
  * the card structure, enables PCIE function number and initiates the
@@ -159,80 +233,6 @@ static void mwifiex_pcie_remove(struct pci_dev *pdev)
 	kfree(card);
 }
 
-/*
- * Kernel needs to suspend all functions separately. Therefore all
- * registered functions must have drivers with suspend and resume
- * methods. Failing that the kernel simply removes the whole card.
- *
- * If already not suspended, this function allocates and sends a host
- * sleep activate request to the firmware and turns off the traffic.
- */
-static int mwifiex_pcie_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-	struct mwifiex_adapter *adapter;
-	struct pcie_service_card *card;
-	int hs_actived;
-
-	if (pdev) {
-		card = (struct pcie_service_card *) pci_get_drvdata(pdev);
-		if (!card || !card->adapter) {
-			pr_err("Card or adapter structure is not valid\n");
-			return 0;
-		}
-	} else {
-		pr_err("PCIE device is not specified\n");
-		return 0;
-	}
-
-	adapter = card->adapter;
-
-	hs_actived = mwifiex_enable_hs(adapter);
-
-	/* Indicate device suspended */
-	adapter->is_suspended = true;
-
-	return 0;
-}
-
-/*
- * Kernel needs to suspend all functions separately. Therefore all
- * registered functions must have drivers with suspend and resume
- * methods. Failing that the kernel simply removes the whole card.
- *
- * If already not resumed, this function turns on the traffic and
- * sends a host sleep cancel request to the firmware.
- */
-static int mwifiex_pcie_resume(struct pci_dev *pdev)
-{
-	struct mwifiex_adapter *adapter;
-	struct pcie_service_card *card;
-
-	if (pdev) {
-		card = (struct pcie_service_card *) pci_get_drvdata(pdev);
-		if (!card || !card->adapter) {
-			pr_err("Card or adapter structure is not valid\n");
-			return 0;
-		}
-	} else {
-		pr_err("PCIE device is not specified\n");
-		return 0;
-	}
-
-	adapter = card->adapter;
-
-	if (!adapter->is_suspended) {
-		dev_warn(adapter->dev, "Device already resumed\n");
-		return 0;
-	}
-
-	adapter->is_suspended = false;
-
-	mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA),
-			  MWIFIEX_ASYNC_CMD);
-
-	return 0;
-}
-
 static DEFINE_PCI_DEVICE_TABLE(mwifiex_ids) = {
 	{
 		PCIE_VENDOR_ID_MARVELL, PCIE_DEVICE_ID_MARVELL_88W8766P,
@@ -287,18 +287,13 @@ static int mwifiex_read_reg(struct mwifiex_adapter *adapter, int reg, u32 *data)
 }
 
 /*
- * This function wakes up the card.
- *
- * A host power up command is written to the card configuration
- * register to wake up the card.
+ * This function adds delay loop to ensure FW is awake before proceeding.
  */
-static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter)
+static void mwifiex_pcie_dev_wakeup_delay(struct mwifiex_adapter *adapter)
 {
 	int i = 0;
-	struct pcie_service_card *card = adapter->card;
-	const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
 
-	while (reg->sleep_cookie && mwifiex_pcie_ok_to_access_hw(adapter)) {
+	while (mwifiex_pcie_ok_to_access_hw(adapter)) {
 		i++;
 		usleep_range(10, 20);
 		/* 50ms max wait */
@@ -306,16 +301,32 @@ static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter)
 			break;
 	}
 
+	return;
+}
+
+/* This function wakes up the card by reading fw_status register. */
+static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter)
+{
+	u32 fw_status;
+	struct pcie_service_card *card = adapter->card;
+	const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
+
 	dev_dbg(adapter->dev, "event: Wakeup device...\n");
 
-	/* Enable interrupts or any chip access will wakeup device */
-	if (mwifiex_write_reg(adapter, PCIE_HOST_INT_MASK, HOST_INTR_MASK)) {
-		dev_warn(adapter->dev, "Enable host interrupt failed\n");
+	if (reg->sleep_cookie)
+		mwifiex_pcie_dev_wakeup_delay(adapter);
+
+	/* Reading fw_status register will wakeup device */
+	if (mwifiex_read_reg(adapter, reg->fw_status, &fw_status)) {
+		dev_warn(adapter->dev, "Reading fw_status register failed\n");
 		return -1;
 	}
 
-	dev_dbg(adapter->dev, "PCIE wakeup: Setting PS_STATE_AWAKE\n");
-	adapter->ps_state = PS_STATE_AWAKE;
+	if (reg->sleep_cookie) {
+		mwifiex_pcie_dev_wakeup_delay(adapter);
+		dev_dbg(adapter->dev, "PCIE wakeup: Setting PS_STATE_AWAKE\n");
+		adapter->ps_state = PS_STATE_AWAKE;
+	}
 
 	return 0;
 }
@@ -1030,8 +1041,8 @@ mwifiex_pcie_send_data(struct mwifiex_adapter *adapter, struct sk_buff *skb,
 	u32 wrindx, num_tx_buffs, rx_val;
 	int ret;
 	dma_addr_t buf_pa;
-	struct mwifiex_pcie_buf_desc *desc;
-	struct mwifiex_pfu_buf_desc *desc2;
+	struct mwifiex_pcie_buf_desc *desc = NULL;
+	struct mwifiex_pfu_buf_desc *desc2 = NULL;
 	__le16 *tmp;
 
 	if (!(skb->data && skb->len)) {
@@ -1508,6 +1519,7 @@ static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter)
 		}
 		memcpy(adapter->upld_buf, skb->data,
 		       min_t(u32, MWIFIEX_SIZE_OF_CMD_BUFFER, skb->len));
+		skb_push(skb, INTF_HEADER_LEN);
 		if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE,
 					   PCI_DMA_FROMDEVICE))
 			return -1;
@@ -1983,12 +1995,13 @@ static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter)
 				}
 			}
 		} else if (!adapter->pps_uapsd_mode &&
-			   adapter->ps_state == PS_STATE_SLEEP) {
+			   adapter->ps_state == PS_STATE_SLEEP &&
+			   mwifiex_pcie_ok_to_access_hw(adapter)) {
 				/* Potentially for PCIe we could get other
 				 * interrupts like shared. Don't change power
 				 * state until cookie is set */
-				if (mwifiex_pcie_ok_to_access_hw(adapter))
-					adapter->ps_state = PS_STATE_AWAKE;
+				adapter->ps_state = PS_STATE_AWAKE;
+				adapter->pm_wakeup_fw_try = false;
 		}
 	}
 }
@@ -2111,7 +2124,8 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter)
 	}
 	dev_dbg(adapter->dev, "info: cmd_sent=%d data_sent=%d\n",
 		adapter->cmd_sent, adapter->data_sent);
-	mwifiex_pcie_enable_host_int(adapter);
+	if (adapter->ps_state != PS_STATE_SLEEP)
+		mwifiex_pcie_enable_host_int(adapter);
 
 	return 0;
 }
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c
index d215b4d..e7f6dea 100644
--- a/drivers/net/wireless/mwifiex/scan.c
+++ b/drivers/net/wireless/mwifiex/scan.c
@@ -1393,8 +1393,10 @@ int mwifiex_scan_networks(struct mwifiex_private *priv,
 			queue_work(adapter->workqueue, &adapter->main_work);
 
 			/* Perform internal scan synchronously */
-			if (!priv->scan_request)
+			if (!priv->scan_request) {
+				dev_dbg(adapter->dev, "wait internal scan\n");
 				mwifiex_wait_queue_complete(adapter, cmd_node);
+			}
 		} else {
 			spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
 					       flags);
@@ -1793,7 +1795,12 @@ check_next_scan:
 		/* Need to indicate IOCTL complete */
 		if (adapter->curr_cmd->wait_q_enabled) {
 			adapter->cmd_wait_q.status = 0;
-			mwifiex_complete_cmd(adapter, adapter->curr_cmd);
+			if (!priv->scan_request) {
+				dev_dbg(adapter->dev,
+					"complete internal scan\n");
+				mwifiex_complete_cmd(adapter,
+						     adapter->curr_cmd);
+			}
 		}
 		if (priv->report_scan_result)
 			priv->report_scan_result = false;
diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c
index c55c5bb..b193e25 100644
--- a/drivers/net/wireless/mwifiex/sta_cmd.c
+++ b/drivers/net/wireless/mwifiex/sta_cmd.c
@@ -24,6 +24,7 @@
 #include "main.h"
 #include "wmm.h"
 #include "11n.h"
+#include "11ac.h"
 
 /*
  * This function prepares command to set/get RSSI information.
@@ -334,7 +335,7 @@ mwifiex_cmd_802_11_hs_cfg(struct mwifiex_private *priv,
 	cmd->command = cpu_to_le16(HostCmd_CMD_802_11_HS_CFG_ENH);
 
 	if (!hs_activate &&
-	    (hscfg_param->conditions != cpu_to_le32(HOST_SLEEP_CFG_CANCEL)) &&
+	    (hscfg_param->conditions != cpu_to_le32(HS_CFG_CANCEL)) &&
 	    ((adapter->arp_filter_size > 0) &&
 	     (adapter->arp_filter_size <= ARP_FILTER_MAX_BUF_SIZE))) {
 		dev_dbg(adapter->dev,
@@ -1059,6 +1060,80 @@ mwifiex_cmd_802_11_subsc_evt(struct mwifiex_private *priv,
 	return 0;
 }
 
+static int
+mwifiex_cmd_append_rpn_expression(struct mwifiex_private *priv,
+				  struct mwifiex_mef_entry *mef_entry,
+				  u8 **buffer)
+{
+	struct mwifiex_mef_filter *filter = mef_entry->filter;
+	int i, byte_len;
+	u8 *stack_ptr = *buffer;
+
+	for (i = 0; i < MWIFIEX_MAX_FILTERS; i++) {
+		filter = &mef_entry->filter[i];
+		if (!filter->filt_type)
+			break;
+		*(__le32 *)stack_ptr = cpu_to_le32((u32)filter->repeat);
+		stack_ptr += 4;
+		*stack_ptr = TYPE_DNUM;
+		stack_ptr += 1;
+
+		byte_len = filter->byte_seq[MAX_BYTESEQ];
+		memcpy(stack_ptr, filter->byte_seq, byte_len);
+		stack_ptr += byte_len;
+		*stack_ptr = byte_len;
+		stack_ptr += 1;
+		*stack_ptr = TYPE_BYTESEQ;
+		stack_ptr += 1;
+
+		*(__le32 *)stack_ptr = cpu_to_le32((u32)filter->offset);
+		stack_ptr += 4;
+		*stack_ptr = TYPE_DNUM;
+		stack_ptr += 1;
+
+		*stack_ptr = filter->filt_type;
+		stack_ptr += 1;
+
+		if (filter->filt_action) {
+			*stack_ptr = filter->filt_action;
+			stack_ptr += 1;
+		}
+
+		if (stack_ptr - *buffer > STACK_NBYTES)
+			return -1;
+	}
+
+	*buffer = stack_ptr;
+	return 0;
+}
+
+static int
+mwifiex_cmd_mef_cfg(struct mwifiex_private *priv,
+		    struct host_cmd_ds_command *cmd,
+		    struct mwifiex_ds_mef_cfg *mef)
+{
+	struct host_cmd_ds_mef_cfg *mef_cfg = &cmd->params.mef_cfg;
+	u8 *pos = (u8 *)mef_cfg;
+
+	cmd->command = cpu_to_le16(HostCmd_CMD_MEF_CFG);
+
+	mef_cfg->criteria = cpu_to_le32(mef->criteria);
+	mef_cfg->num_entries = cpu_to_le16(mef->num_entries);
+	pos += sizeof(*mef_cfg);
+	mef_cfg->mef_entry->mode = mef->mef_entry->mode;
+	mef_cfg->mef_entry->action = mef->mef_entry->action;
+	pos += sizeof(*(mef_cfg->mef_entry));
+
+	if (mwifiex_cmd_append_rpn_expression(priv, mef->mef_entry, &pos))
+		return -1;
+
+	mef_cfg->mef_entry->exprsize =
+			cpu_to_le16(pos - mef_cfg->mef_entry->expr);
+	cmd->size = cpu_to_le16((u16) (pos - (u8 *)mef_cfg) + S_DS_GEN);
+
+	return 0;
+}
+
 /*
  * This function prepares the commands before sending them to the firmware.
  *
@@ -1184,6 +1259,9 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
 		      cpu_to_le16(sizeof(struct host_cmd_ds_remain_on_chan) +
 				  S_DS_GEN);
 		break;
+	case HostCmd_CMD_11AC_CFG:
+		ret = mwifiex_cmd_11ac_cfg(priv, cmd_ptr, cmd_action, data_buf);
+		break;
 	case HostCmd_CMD_P2P_MODE_CFG:
 		cmd_ptr->command = cpu_to_le16(cmd_no);
 		cmd_ptr->params.mode_cfg.action = cpu_to_le16(cmd_action);
@@ -1273,6 +1351,9 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
 	case HostCmd_CMD_802_11_SUBSCRIBE_EVENT:
 		ret = mwifiex_cmd_802_11_subsc_evt(priv, cmd_ptr, data_buf);
 		break;
+	case HostCmd_CMD_MEF_CFG:
+		ret = mwifiex_cmd_mef_cfg(priv, cmd_ptr, data_buf);
+		break;
 	default:
 		dev_err(priv->adapter->dev,
 			"PREP_CMD: unknown cmd- %#x\n", cmd_no);
diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c
index 4669f8d..c7dc450 100644
--- a/drivers/net/wireless/mwifiex/sta_cmdresp.c
+++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c
@@ -907,6 +907,8 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no,
 	case HostCmd_CMD_REMAIN_ON_CHAN:
 		ret = mwifiex_ret_remain_on_chan(priv, resp, data_buf);
 		break;
+	case HostCmd_CMD_11AC_CFG:
+		break;
 	case HostCmd_CMD_P2P_MODE_CFG:
 		ret = mwifiex_ret_p2p_mode_cfg(priv, resp, data_buf);
 		break;
@@ -976,6 +978,8 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no,
 	case HostCmd_CMD_UAP_BSS_STOP:
 		priv->bss_started = 0;
 		break;
+	case HostCmd_CMD_MEF_CFG:
+		break;
 	default:
 		dev_err(adapter->dev, "CMD_RESP: unknown cmd response %#x\n",
 			resp->command);
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c
index 13100f8..8c943b6 100644
--- a/drivers/net/wireless/mwifiex/sta_ioctl.c
+++ b/drivers/net/wireless/mwifiex/sta_ioctl.c
@@ -382,7 +382,7 @@ static int mwifiex_set_hs_params(struct mwifiex_private *priv, u16 action,
 			break;
 		}
 		if (hs_cfg->is_invoke_hostcmd) {
-			if (hs_cfg->conditions == HOST_SLEEP_CFG_CANCEL) {
+			if (hs_cfg->conditions == HS_CFG_CANCEL) {
 				if (!adapter->is_hs_configured)
 					/* Already cancelled */
 					break;
@@ -397,8 +397,8 @@ static int mwifiex_set_hs_params(struct mwifiex_private *priv, u16 action,
 				adapter->hs_cfg.gpio = (u8)hs_cfg->gpio;
 				if (hs_cfg->gap)
 					adapter->hs_cfg.gap = (u8)hs_cfg->gap;
-			} else if (adapter->hs_cfg.conditions
-				   == cpu_to_le32(HOST_SLEEP_CFG_CANCEL)) {
+			} else if (adapter->hs_cfg.conditions ==
+				   cpu_to_le32(HS_CFG_CANCEL)) {
 				/* Return failure if no parameters for HS
 				   enable */
 				status = -1;
@@ -414,7 +414,7 @@ static int mwifiex_set_hs_params(struct mwifiex_private *priv, u16 action,
 						HostCmd_CMD_802_11_HS_CFG_ENH,
 						HostCmd_ACT_GEN_SET, 0,
 						&adapter->hs_cfg);
-			if (hs_cfg->conditions == HOST_SLEEP_CFG_CANCEL)
+			if (hs_cfg->conditions == HS_CFG_CANCEL)
 				/* Restore previous condition */
 				adapter->hs_cfg.conditions =
 						cpu_to_le32(prev_cond);
@@ -448,7 +448,7 @@ int mwifiex_cancel_hs(struct mwifiex_private *priv, int cmd_type)
 {
 	struct mwifiex_ds_hs_cfg hscfg;
 
-	hscfg.conditions = HOST_SLEEP_CFG_CANCEL;
+	hscfg.conditions = HS_CFG_CANCEL;
 	hscfg.is_invoke_hostcmd = true;
 
 	return mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_SET,
diff --git a/drivers/net/wireless/mwifiex/txrx.c b/drivers/net/wireless/mwifiex/txrx.c
index 296faec..8f923d0 100644
--- a/drivers/net/wireless/mwifiex/txrx.c
+++ b/drivers/net/wireless/mwifiex/txrx.c
@@ -169,6 +169,8 @@ int mwifiex_write_data_complete(struct mwifiex_adapter *adapter,
 	if (!status) {
 		priv->stats.tx_packets++;
 		priv->stats.tx_bytes += skb->len;
+		if (priv->tx_timeout_cnt)
+			priv->tx_timeout_cnt = 0;
 	} else {
 		priv->stats.tx_errors++;
 	}
diff --git a/drivers/net/wireless/mwifiex/uap_cmd.c b/drivers/net/wireless/mwifiex/uap_cmd.c
index 6e76a15..b04b1db 100644
--- a/drivers/net/wireless/mwifiex/uap_cmd.c
+++ b/drivers/net/wireless/mwifiex/uap_cmd.c
@@ -18,6 +18,7 @@
  */
 
 #include "main.h"
+#include "11ac.h"
 
 /* This function parses security related parameters from cfg80211_ap_settings
  * and sets into FW understandable bss_config structure.
@@ -177,6 +178,60 @@ mwifiex_set_ht_params(struct mwifiex_private *priv,
 	return;
 }
 
+/* This function updates 11ac related parameters from IE
+ * and sets them into bss_config structure.
+ */
+void mwifiex_set_vht_params(struct mwifiex_private *priv,
+			    struct mwifiex_uap_bss_param *bss_cfg,
+			    struct cfg80211_ap_settings *params)
+{
+	const u8 *vht_ie;
+
+	vht_ie = cfg80211_find_ie(WLAN_EID_VHT_CAPABILITY, params->beacon.tail,
+				  params->beacon.tail_len);
+	if (vht_ie) {
+		memcpy(&bss_cfg->vht_cap, vht_ie + 2,
+		       sizeof(struct ieee80211_vht_cap));
+		priv->ap_11ac_enabled = 1;
+	} else {
+		priv->ap_11ac_enabled = 0;
+	}
+
+	return;
+}
+
+/* Enable VHT only when cfg80211_ap_settings has VHT IE.
+ * Otherwise disable VHT.
+ */
+void mwifiex_set_vht_width(struct mwifiex_private *priv,
+			   enum nl80211_chan_width width,
+			   bool ap_11ac_enable)
+{
+	struct mwifiex_adapter *adapter = priv->adapter;
+	struct mwifiex_11ac_vht_cfg vht_cfg;
+
+	vht_cfg.band_config = VHT_CFG_5GHZ;
+	vht_cfg.cap_info = adapter->hw_dot_11ac_dev_cap;
+
+	if (!ap_11ac_enable) {
+		vht_cfg.mcs_tx_set = DISABLE_VHT_MCS_SET;
+		vht_cfg.mcs_rx_set = DISABLE_VHT_MCS_SET;
+	} else {
+		vht_cfg.mcs_tx_set = DEFAULT_VHT_MCS_SET;
+		vht_cfg.mcs_rx_set = DEFAULT_VHT_MCS_SET;
+	}
+
+	vht_cfg.misc_config  = VHT_CAP_UAP_ONLY;
+
+	if (ap_11ac_enable && width >= NL80211_CHAN_WIDTH_80)
+		vht_cfg.misc_config |= VHT_BW_80_160_80P80;
+
+	mwifiex_send_cmd_sync(priv, HostCmd_CMD_11AC_CFG,
+			      HostCmd_ACT_GEN_SET, 0, &vht_cfg);
+
+	return;
+}
+
 /* This function finds supported rates IE from beacon parameter and sets
  * these rates into bss_config structure.
  */
diff --git a/drivers/net/wireless/mwifiex/util.c b/drivers/net/wireless/mwifiex/util.c
index 2155397..54667e6 100644
--- a/drivers/net/wireless/mwifiex/util.c
+++ b/drivers/net/wireless/mwifiex/util.c
@@ -195,7 +195,7 @@ int mwifiex_recv_packet(struct mwifiex_private *priv, struct sk_buff *skb)
 	skb->protocol = eth_type_trans(skb, priv->netdev);
 	skb->ip_summed = CHECKSUM_NONE;
 
-	/* This is required only in case of 11n and USB as we alloc
+	/* This is required only in case of 11n and USB/PCIE as we alloc
 	 * a buffer of 4K only if its 11N (to be able to receive 4K
 	 * AMSDU packets). In case of SD we allocate buffers based
 	 * on the size of packet and hence this is not needed.
@@ -212,7 +212,8 @@ int mwifiex_recv_packet(struct mwifiex_private *priv, struct sk_buff *skb)
 	 * fragments. Currently we fail the Filesndl-ht.scr script
 	 * for UDP, hence this fix
 	 */
-	if ((priv->adapter->iface_type == MWIFIEX_USB) &&
+	if ((priv->adapter->iface_type == MWIFIEX_USB ||
+	     priv->adapter->iface_type == MWIFIEX_PCIE) &&
 	    (skb->truesize > MWIFIEX_RX_DATA_BUF_SIZE))
 		skb->truesize += (skb->len - MWIFIEX_RX_DATA_BUF_SIZE);
 
diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c
index 32adc87..3ddae52 100644
--- a/drivers/net/wireless/mwifiex/wmm.c
+++ b/drivers/net/wireless/mwifiex/wmm.c
@@ -436,10 +436,7 @@ mwifiex_wmm_init(struct mwifiex_adapter *adapter)
 					= priv->aggr_prio_tbl[7].ampdu_user
 					= BA_STREAM_NOT_ALLOWED;
 
-		priv->add_ba_param.timeout = MWIFIEX_DEFAULT_BLOCK_ACK_TIMEOUT;
-		priv->add_ba_param.tx_win_size = MWIFIEX_AMPDU_DEF_TXWINSIZE;
-		priv->add_ba_param.rx_win_size = MWIFIEX_AMPDU_DEF_RXWINSIZE;
-
+		mwifiex_set_ba_params(priv);
 		mwifiex_reset_11n_rx_seq_num(priv);
 
 		atomic_set(&priv->wmm.tx_pkts_queued, 0);
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index 091d9a6..956c108 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -232,6 +232,7 @@ struct mwl8k_priv {
 	u16 num_mcaddrs;
 	u8 hw_rev;
 	u32 fw_rev;
+	u32 caps;
 
 	/*
 	 * Running count of TX packets in flight, to avoid
@@ -284,6 +285,7 @@ struct mwl8k_priv {
 	unsigned fw_state;
 	char *fw_pref;
 	char *fw_alt;
+	bool is_8764;
 	struct completion firmware_loading_complete;
 
 	/* bitmap of running BSSes */
@@ -600,13 +602,18 @@ mwl8k_send_fw_load_cmd(struct mwl8k_priv *priv, void *data, int length)
 	loops = 1000;
 	do {
 		u32 int_code;
-
-		int_code = ioread32(regs + MWL8K_HIU_INT_CODE);
-		if (int_code == MWL8K_INT_CODE_CMD_FINISHED) {
-			iowrite32(0, regs + MWL8K_HIU_INT_CODE);
-			break;
+		if (priv->is_8764) {
+			int_code = ioread32(regs +
+					    MWL8K_HIU_H2A_INTERRUPT_STATUS);
+			if (int_code == 0)
+				break;
+		} else {
+			int_code = ioread32(regs + MWL8K_HIU_INT_CODE);
+			if (int_code == MWL8K_INT_CODE_CMD_FINISHED) {
+				iowrite32(0, regs + MWL8K_HIU_INT_CODE);
+				break;
+			}
 		}
-
 		cond_resched();
 		udelay(1);
 	} while (--loops);
@@ -724,7 +731,7 @@ static int mwl8k_load_firmware(struct ieee80211_hw *hw)
 	int rc;
 	int loops;
 
-	if (!memcmp(fw->data, "\x01\x00\x00\x00", 4)) {
+	if (!memcmp(fw->data, "\x01\x00\x00\x00", 4) && !priv->is_8764) {
 		const struct firmware *helper = priv->fw_helper;
 
 		if (helper == NULL) {
@@ -743,7 +750,10 @@ static int mwl8k_load_firmware(struct ieee80211_hw *hw)
 
 		rc = mwl8k_feed_fw_image(priv, fw->data, fw->size);
 	} else {
-		rc = mwl8k_load_fw_image(priv, fw->data, fw->size);
+		if (priv->is_8764)
+			rc = mwl8k_feed_fw_image(priv, fw->data, fw->size);
+		else
+			rc = mwl8k_load_fw_image(priv, fw->data, fw->size);
 	}
 
 	if (rc) {
@@ -908,9 +918,9 @@ static void mwl8k_encapsulate_tx_frame(struct mwl8k_priv *priv,
 }
 
 /*
- * Packet reception for 88w8366 AP firmware.
+ * Packet reception for 88w8366/88w8764 AP firmware.
  */
-struct mwl8k_rxd_8366_ap {
+struct mwl8k_rxd_ap {
 	__le16 pkt_len;
 	__u8 sq2;
 	__u8 rate;
@@ -928,30 +938,30 @@ struct mwl8k_rxd_8366_ap {
 	__u8 rx_ctrl;
 } __packed;
 
-#define MWL8K_8366_AP_RATE_INFO_MCS_FORMAT	0x80
-#define MWL8K_8366_AP_RATE_INFO_40MHZ		0x40
-#define MWL8K_8366_AP_RATE_INFO_RATEID(x)	((x) & 0x3f)
+#define MWL8K_AP_RATE_INFO_MCS_FORMAT		0x80
+#define MWL8K_AP_RATE_INFO_40MHZ		0x40
+#define MWL8K_AP_RATE_INFO_RATEID(x)		((x) & 0x3f)
 
-#define MWL8K_8366_AP_RX_CTRL_OWNED_BY_HOST	0x80
+#define MWL8K_AP_RX_CTRL_OWNED_BY_HOST		0x80
 
-/* 8366 AP rx_status bits */
-#define MWL8K_8366_AP_RXSTAT_DECRYPT_ERR_MASK		0x80
-#define MWL8K_8366_AP_RXSTAT_GENERAL_DECRYPT_ERR	0xFF
-#define MWL8K_8366_AP_RXSTAT_TKIP_DECRYPT_MIC_ERR	0x02
-#define MWL8K_8366_AP_RXSTAT_WEP_DECRYPT_ICV_ERR	0x04
-#define MWL8K_8366_AP_RXSTAT_TKIP_DECRYPT_ICV_ERR	0x08
+/* 8366/8764 AP rx_status bits */
+#define MWL8K_AP_RXSTAT_DECRYPT_ERR_MASK		0x80
+#define MWL8K_AP_RXSTAT_GENERAL_DECRYPT_ERR		0xFF
+#define MWL8K_AP_RXSTAT_TKIP_DECRYPT_MIC_ERR		0x02
+#define MWL8K_AP_RXSTAT_WEP_DECRYPT_ICV_ERR		0x04
+#define MWL8K_AP_RXSTAT_TKIP_DECRYPT_ICV_ERR		0x08
 
-static void mwl8k_rxd_8366_ap_init(void *_rxd, dma_addr_t next_dma_addr)
+static void mwl8k_rxd_ap_init(void *_rxd, dma_addr_t next_dma_addr)
 {
-	struct mwl8k_rxd_8366_ap *rxd = _rxd;
+	struct mwl8k_rxd_ap *rxd = _rxd;
 
 	rxd->next_rxd_phys_addr = cpu_to_le32(next_dma_addr);
-	rxd->rx_ctrl = MWL8K_8366_AP_RX_CTRL_OWNED_BY_HOST;
+	rxd->rx_ctrl = MWL8K_AP_RX_CTRL_OWNED_BY_HOST;
 }
 
-static void mwl8k_rxd_8366_ap_refill(void *_rxd, dma_addr_t addr, int len)
+static void mwl8k_rxd_ap_refill(void *_rxd, dma_addr_t addr, int len)
 {
-	struct mwl8k_rxd_8366_ap *rxd = _rxd;
+	struct mwl8k_rxd_ap *rxd = _rxd;
 
 	rxd->pkt_len = cpu_to_le16(len);
 	rxd->pkt_phys_addr = cpu_to_le32(addr);
@@ -960,12 +970,12 @@ static void mwl8k_rxd_8366_ap_refill(void *_rxd, dma_addr_t addr, int len)
 }
 
 static int
-mwl8k_rxd_8366_ap_process(void *_rxd, struct ieee80211_rx_status *status,
-			  __le16 *qos, s8 *noise)
+mwl8k_rxd_ap_process(void *_rxd, struct ieee80211_rx_status *status,
+		     __le16 *qos, s8 *noise)
 {
-	struct mwl8k_rxd_8366_ap *rxd = _rxd;
+	struct mwl8k_rxd_ap *rxd = _rxd;
 
-	if (!(rxd->rx_ctrl & MWL8K_8366_AP_RX_CTRL_OWNED_BY_HOST))
+	if (!(rxd->rx_ctrl & MWL8K_AP_RX_CTRL_OWNED_BY_HOST))
 		return -1;
 	rmb();
 
@@ -974,11 +984,11 @@ mwl8k_rxd_8366_ap_process(void *_rxd, struct ieee80211_rx_status *status,
 	status->signal = -rxd->rssi;
 	*noise = -rxd->noise_floor;
 
-	if (rxd->rate & MWL8K_8366_AP_RATE_INFO_MCS_FORMAT) {
+	if (rxd->rate & MWL8K_AP_RATE_INFO_MCS_FORMAT) {
 		status->flag |= RX_FLAG_HT;
-		if (rxd->rate & MWL8K_8366_AP_RATE_INFO_40MHZ)
+		if (rxd->rate & MWL8K_AP_RATE_INFO_40MHZ)
 			status->flag |= RX_FLAG_40MHZ;
-		status->rate_idx = MWL8K_8366_AP_RATE_INFO_RATEID(rxd->rate);
+		status->rate_idx = MWL8K_AP_RATE_INFO_RATEID(rxd->rate);
 	} else {
 		int i;
 
@@ -1002,19 +1012,19 @@ mwl8k_rxd_8366_ap_process(void *_rxd, struct ieee80211_rx_status *status,
 
 	*qos = rxd->qos_control;
 
-	if ((rxd->rx_status != MWL8K_8366_AP_RXSTAT_GENERAL_DECRYPT_ERR) &&
-	    (rxd->rx_status & MWL8K_8366_AP_RXSTAT_DECRYPT_ERR_MASK) &&
-	    (rxd->rx_status & MWL8K_8366_AP_RXSTAT_TKIP_DECRYPT_MIC_ERR))
+	if ((rxd->rx_status != MWL8K_AP_RXSTAT_GENERAL_DECRYPT_ERR) &&
+	    (rxd->rx_status & MWL8K_AP_RXSTAT_DECRYPT_ERR_MASK) &&
+	    (rxd->rx_status & MWL8K_AP_RXSTAT_TKIP_DECRYPT_MIC_ERR))
 		status->flag |= RX_FLAG_MMIC_ERROR;
 
 	return le16_to_cpu(rxd->pkt_len);
 }
 
-static struct rxd_ops rxd_8366_ap_ops = {
-	.rxd_size	= sizeof(struct mwl8k_rxd_8366_ap),
-	.rxd_init	= mwl8k_rxd_8366_ap_init,
-	.rxd_refill	= mwl8k_rxd_8366_ap_refill,
-	.rxd_process	= mwl8k_rxd_8366_ap_process,
+static struct rxd_ops rxd_ap_ops = {
+	.rxd_size	= sizeof(struct mwl8k_rxd_ap),
+	.rxd_init	= mwl8k_rxd_ap_init,
+	.rxd_refill	= mwl8k_rxd_ap_refill,
+	.rxd_process	= mwl8k_rxd_ap_process,
 };
 
 /*
@@ -2401,6 +2411,9 @@ mwl8k_set_caps(struct ieee80211_hw *hw, u32 caps)
 {
 	struct mwl8k_priv *priv = hw->priv;
 
+	if (priv->caps)
+		return;
+
 	if ((caps & MWL8K_CAP_2GHZ4) || !(caps & MWL8K_CAP_BAND_MASK)) {
 		mwl8k_setup_2ghz_band(hw);
 		if (caps & MWL8K_CAP_MIMO)
@@ -2412,6 +2425,8 @@ mwl8k_set_caps(struct ieee80211_hw *hw, u32 caps)
 		if (caps & MWL8K_CAP_MIMO)
 			mwl8k_set_ht_caps(hw, &priv->band_50, caps);
 	}
+
+	priv->caps = caps;
 }
 
 static int mwl8k_cmd_get_hw_spec_sta(struct ieee80211_hw *hw)
@@ -4792,16 +4807,14 @@ static int mwl8k_config(struct ieee80211_hw *hw, u32 changed)
 	struct mwl8k_priv *priv = hw->priv;
 	int rc;
 
-	if (conf->flags & IEEE80211_CONF_IDLE) {
-		mwl8k_cmd_radio_disable(hw);
-		return 0;
-	}
-
 	rc = mwl8k_fw_lock(hw);
 	if (rc)
 		return rc;
 
-	rc = mwl8k_cmd_radio_enable(hw);
+	if (conf->flags & IEEE80211_CONF_IDLE)
+		rc = mwl8k_cmd_radio_disable(hw);
+	else
+		rc = mwl8k_cmd_radio_enable(hw);
 	if (rc)
 		goto out;
 
@@ -5429,12 +5442,17 @@ enum {
 	MWL8363 = 0,
 	MWL8687,
 	MWL8366,
+	MWL8764,
 };
 
 #define MWL8K_8366_AP_FW_API 3
 #define _MWL8K_8366_AP_FW(api) "mwl8k/fmimage_8366_ap-" #api ".fw"
 #define MWL8K_8366_AP_FW(api) _MWL8K_8366_AP_FW(api)
 
+#define MWL8K_8764_AP_FW_API 1
+#define _MWL8K_8764_AP_FW(api) "mwl8k/fmimage_8764_ap-" #api ".fw"
+#define MWL8K_8764_AP_FW(api) _MWL8K_8764_AP_FW(api)
+
 static struct mwl8k_device_info mwl8k_info_tbl[] = {
 	[MWL8363] = {
 		.part_name	= "88w8363",
@@ -5452,7 +5470,13 @@ static struct mwl8k_device_info mwl8k_info_tbl[] = {
 		.fw_image_sta	= "mwl8k/fmimage_8366.fw",
 		.fw_image_ap	= MWL8K_8366_AP_FW(MWL8K_8366_AP_FW_API),
 		.fw_api_ap	= MWL8K_8366_AP_FW_API,
-		.ap_rxd_ops	= &rxd_8366_ap_ops,
+		.ap_rxd_ops	= &rxd_ap_ops,
+	},
+	[MWL8764] = {
+		.part_name	= "88w8764",
+		.fw_image_ap	= MWL8K_8764_AP_FW(MWL8K_8764_AP_FW_API),
+		.fw_api_ap	= MWL8K_8764_AP_FW_API,
+		.ap_rxd_ops	= &rxd_ap_ops,
 	},
 };
 
@@ -5474,6 +5498,7 @@ static DEFINE_PCI_DEVICE_TABLE(mwl8k_pci_id_table) = {
 	{ PCI_VDEVICE(MARVELL, 0x2a41), .driver_data = MWL8366, },
 	{ PCI_VDEVICE(MARVELL, 0x2a42), .driver_data = MWL8366, },
 	{ PCI_VDEVICE(MARVELL, 0x2a43), .driver_data = MWL8366, },
+	{ PCI_VDEVICE(MARVELL, 0x2b36), .driver_data = MWL8764, },
 	{ },
 };
 MODULE_DEVICE_TABLE(pci, mwl8k_pci_id_table);
@@ -5995,6 +6020,8 @@ static int mwl8k_probe(struct pci_dev *pdev,
 	priv->pdev = pdev;
 	priv->device_info = &mwl8k_info_tbl[id->driver_data];
 
+	if (id->driver_data == MWL8764)
+		priv->is_8764 = true;
 
 	priv->sram = pci_iomap(pdev, 0, 0x10000);
 	if (priv->sram == NULL) {
diff --git a/drivers/net/wireless/orinoco/orinoco_cs.c b/drivers/net/wireless/orinoco/orinoco_cs.c
index d7dbc00..d21d959 100644
--- a/drivers/net/wireless/orinoco/orinoco_cs.c
+++ b/drivers/net/wireless/orinoco/orinoco_cs.c
@@ -338,18 +338,4 @@ static struct pcmcia_driver orinoco_driver = {
 	.suspend	= orinoco_cs_suspend,
 	.resume		= orinoco_cs_resume,
 };
-
-static int __init
-init_orinoco_cs(void)
-{
-	return pcmcia_register_driver(&orinoco_driver);
-}
-
-static void __exit
-exit_orinoco_cs(void)
-{
-	pcmcia_unregister_driver(&orinoco_driver);
-}
-
-module_init(init_orinoco_cs);
-module_exit(exit_orinoco_cs);
+module_pcmcia_driver(orinoco_driver);
diff --git a/drivers/net/wireless/orinoco/orinoco_usb.c b/drivers/net/wireless/orinoco/orinoco_usb.c
index 7744f42..1f9cb55 100644
--- a/drivers/net/wireless/orinoco/orinoco_usb.c
+++ b/drivers/net/wireless/orinoco/orinoco_usb.c
@@ -1584,7 +1584,7 @@ static int ezusb_probe(struct usb_interface *interface,
 	struct ezusb_priv *upriv = NULL;
 	struct usb_interface_descriptor *iface_desc;
 	struct usb_endpoint_descriptor *ep;
-	const struct firmware *fw_entry;
+	const struct firmware *fw_entry = NULL;
 	int retval = 0;
 	int i;
 
diff --git a/drivers/net/wireless/orinoco/spectrum_cs.c b/drivers/net/wireless/orinoco/spectrum_cs.c
index 6e28ee4..e2264bc 100644
--- a/drivers/net/wireless/orinoco/spectrum_cs.c
+++ b/drivers/net/wireless/orinoco/spectrum_cs.c
@@ -318,18 +318,4 @@ static struct pcmcia_driver orinoco_driver = {
 	.resume		= spectrum_cs_resume,
 	.id_table       = spectrum_cs_ids,
 };
-
-static int __init
-init_spectrum_cs(void)
-{
-	return pcmcia_register_driver(&orinoco_driver);
-}
-
-static void __exit
-exit_spectrum_cs(void)
-{
-	pcmcia_unregister_driver(&orinoco_driver);
-}
-
-module_init(init_spectrum_cs);
-module_exit(exit_spectrum_cs);
+module_pcmcia_driver(orinoco_driver);
diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c
index aadda99..ee654a6 100644
--- a/drivers/net/wireless/p54/main.c
+++ b/drivers/net/wireless/p54/main.c
@@ -670,7 +670,7 @@ static unsigned int p54_flush_count(struct p54_common *priv)
 	return total;
 }
 
-static void p54_flush(struct ieee80211_hw *dev, bool drop)
+static void p54_flush(struct ieee80211_hw *dev, u32 queues, bool drop)
 {
 	struct p54_common *priv = dev->priv;
 	unsigned int total, i;
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
index 3109c0d..9b557a1 100644
--- a/drivers/net/wireless/ray_cs.c
+++ b/drivers/net/wireless/ray_cs.c
@@ -144,7 +144,7 @@ static int psm;
 static char *essid;
 
 /* Default to encapsulation unless translation requested */
-static int translate = 1;
+static bool translate = 1;
 
 static int country = USA;
 
@@ -178,7 +178,7 @@ module_param(hop_dwell, int, 0);
 module_param(beacon_period, int, 0);
 module_param(psm, int, 0);
 module_param(essid, charp, 0);
-module_param(translate, int, 0);
+module_param(translate, bool, 0);
 module_param(country, int, 0);
 module_param(sniffer, int, 0);
 module_param(bc, int, 0);
@@ -953,7 +953,7 @@ static int translate_frame(ray_dev_t *local, struct tx_msg __iomem *ptx,
 			   unsigned char *data, int len)
 {
 	__be16 proto = ((struct ethhdr *)data)->h_proto;
-	if (ntohs(proto) >= 1536) { /* DIX II ethernet frame */
+	if (ntohs(proto) >= ETH_P_802_3_MIN) { /* DIX II ethernet frame */
 		pr_debug("ray_cs translate_frame DIX II\n");
 		/* Copy LLC header to card buffer */
 		memcpy_toio(&ptx->var, eth2_llc, sizeof(eth2_llc));
@@ -1353,7 +1353,7 @@ static int ray_get_range(struct net_device *dev, struct iw_request_info *info,
 static int ray_set_framing(struct net_device *dev, struct iw_request_info *info,
 			   union iwreq_data *wrqu, char *extra)
 {
-	translate = *(extra);	/* Set framing mode */
+	translate = !!*(extra);	/* Set framing mode */
 
 	return 0;
 }
@@ -2778,7 +2778,7 @@ static ssize_t int_proc_write(struct file *file, const char __user *buffer,
 		nr = nr * 10 + c;
 		p++;
 	} while (--len);
-	*(int *)PDE(file_inode(file))->data = nr;
+	*(int *)PDE_DATA(file_inode(file)) = nr;
 	return count;
 }
 
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index 525fd75..8169a85 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -2,7 +2,7 @@
  * Driver for RNDIS based wireless USB devices.
  *
  * Copyright (C) 2007 by Bjorge Dijkstra <bjd@jooz.net>
- * Copyright (C) 2008-2009 by Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
+ * Copyright (C) 2008-2009 by Jussi Kivilinna <jussi.kivilinna@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
@@ -2839,8 +2839,7 @@ static void rndis_wlan_do_link_up_work(struct usbnet *usbdev)
 	} else if (priv->infra_mode == NDIS_80211_INFRA_ADHOC)
 		cfg80211_ibss_joined(usbdev->net, bssid, GFP_KERNEL);
 
-	if (info != NULL)
-		kfree(info);
+	kfree(info);
 
 	priv->connected = true;
 	memcpy(priv->bssid, bssid, ETH_ALEN);
diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig
index 2bf4efa..9b915d3 100644
--- a/drivers/net/wireless/rt2x00/Kconfig
+++ b/drivers/net/wireless/rt2x00/Kconfig
@@ -20,6 +20,7 @@ if RT2X00
 config RT2400PCI
 	tristate "Ralink rt2400 (PCI/PCMCIA) support"
 	depends on PCI
+	select RT2X00_LIB_MMIO
 	select RT2X00_LIB_PCI
 	select EEPROM_93CX6
 	---help---
@@ -31,6 +32,7 @@ config RT2400PCI
 config RT2500PCI
 	tristate "Ralink rt2500 (PCI/PCMCIA) support"
 	depends on PCI
+	select RT2X00_LIB_MMIO
 	select RT2X00_LIB_PCI
 	select EEPROM_93CX6
 	---help---
@@ -43,6 +45,7 @@ config RT61PCI
 	tristate "Ralink rt2501/rt61 (PCI/PCMCIA) support"
 	depends on PCI
 	select RT2X00_LIB_PCI
+	select RT2X00_LIB_MMIO
 	select RT2X00_LIB_FIRMWARE
 	select RT2X00_LIB_CRYPTO
 	select CRC_ITU_T
@@ -57,6 +60,7 @@ config RT2800PCI
 	tristate "Ralink rt27xx/rt28xx/rt30xx (PCI/PCIe/PCMCIA) support"
 	depends on PCI || SOC_RT288X || SOC_RT305X
 	select RT2800_LIB
+	select RT2X00_LIB_MMIO
 	select RT2X00_LIB_PCI if PCI
 	select RT2X00_LIB_SOC if SOC_RT288X || SOC_RT305X
 	select RT2X00_LIB_FIRMWARE
@@ -169,6 +173,13 @@ config RT2800USB_RT53XX
          rt2800usb driver.
          Supported chips: RT5370
 
+config RT2800USB_RT55XX
+       bool "rt2800usb - Include support for rt55xx devices (EXPERIMENTAL)"
+       ---help---
+         This adds support for rt55xx wireless chipset family to the
+         rt2800usb driver.
+         Supported chips: RT5572
+
 config RT2800USB_UNKNOWN
 	bool "rt2800usb - Include support for unknown (USB) devices"
 	default n
@@ -185,6 +196,9 @@ endif
 config RT2800_LIB
 	tristate
 
+config RT2X00_LIB_MMIO
+	tristate
+
 config RT2X00_LIB_PCI
 	tristate
 	select RT2X00_LIB
diff --git a/drivers/net/wireless/rt2x00/Makefile b/drivers/net/wireless/rt2x00/Makefile
index 349d5b8..f069d8b 100644
--- a/drivers/net/wireless/rt2x00/Makefile
+++ b/drivers/net/wireless/rt2x00/Makefile
@@ -9,6 +9,7 @@ rt2x00lib-$(CONFIG_RT2X00_LIB_FIRMWARE)	+= rt2x00firmware.o
 rt2x00lib-$(CONFIG_RT2X00_LIB_LEDS)	+= rt2x00leds.o
 
 obj-$(CONFIG_RT2X00_LIB)		+= rt2x00lib.o
+obj-$(CONFIG_RT2X00_LIB_MMIO)		+= rt2x00mmio.o
 obj-$(CONFIG_RT2X00_LIB_PCI)		+= rt2x00pci.o
 obj-$(CONFIG_RT2X00_LIB_SOC)		+= rt2x00soc.o
 obj-$(CONFIG_RT2X00_LIB_USB)		+= rt2x00usb.o
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index 221beaa..dcfb54e 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -34,6 +34,7 @@
 #include <linux/slab.h>
 
 #include "rt2x00.h"
+#include "rt2x00mmio.h"
 #include "rt2x00pci.h"
 #include "rt2400pci.h"
 
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index 39edc59e..e1d2dc9 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -34,6 +34,7 @@
 #include <linux/slab.h>
 
 #include "rt2x00.h"
+#include "rt2x00mmio.h"
 #include "rt2x00pci.h"
 #include "rt2500pci.h"
 
diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h
index 4db1088..a7630d5 100644
--- a/drivers/net/wireless/rt2x00/rt2800.h
+++ b/drivers/net/wireless/rt2x00/rt2800.h
@@ -51,6 +51,7 @@
  * RF3320 2.4G 1T1R(RT3350/RT3370/RT3390)
  * RF3322 2.4G 2T2R(RT3352/RT3371/RT3372/RT3391/RT3392)
  * RF3053 2.4G/5G 3T3R(RT3883/RT3563/RT3573/RT3593/RT3662)
+ * RF5592 2.4G/5G 2T2R
  * RF5360 2.4G 1T1R
  * RF5370 2.4G 1T1R
  * RF5390 2.4G 1T1R
@@ -68,6 +69,7 @@
 #define RF3320				0x000b
 #define RF3322				0x000c
 #define RF3053				0x000d
+#define RF5592				0x000f
 #define RF3290				0x3290
 #define RF5360				0x5360
 #define RF5370				0x5370
@@ -88,11 +90,8 @@
 #define REV_RT3390E			0x0211
 #define REV_RT5390F			0x0502
 #define REV_RT5390R			0x1502
+#define REV_RT5592C			0x0221
 
-/*
- * Signal information.
- * Default offset is required for RSSI <-> dBm conversion.
- */
 #define DEFAULT_RSSI_OFFSET		120
 
 /*
@@ -690,6 +689,12 @@
 #define GPIO_SWITCH_7			FIELD32(0x00000080)
 
 /*
+ * FIXME: where the DEBUG_INDEX name come from?
+ */
+#define MAC_DEBUG_INDEX			0x05e8
+#define MAC_DEBUG_INDEX_XTAL		FIELD32(0x80000000)
+
+/*
  * MAC Control/Status Registers(CSR).
  * Some values are set in TU, whereas 1 TU == 1024 us.
  */
@@ -1934,6 +1939,9 @@ struct mac_iveiv_entry {
 #define BBP4_BANDWIDTH			FIELD8(0x18)
 #define BBP4_MAC_IF_CTRL		FIELD8(0x40)
 
+/* BBP27 */
+#define BBP27_RX_CHAIN_SEL		FIELD8(0x60)
+
 /*
  * BBP 47: Bandwidth
  */
@@ -1948,6 +1956,20 @@ struct mac_iveiv_entry {
 #define BBP49_UPDATE_FLAG		FIELD8(0x01)
 
 /*
+ * BBP 105:
+ * - bit0: detect SIG on primary channel only (on 40MHz bandwidth)
+ * - bit1: FEQ (Feed Forward Compensation) for independend streams
+ * - bit2: MLD (Maximum Likehood Detection) for 2 streams (reserved on single
+ *	   stream)
+ * - bit4: channel estimation updates based on remodulation of
+ *	   L-SIG and HT-SIG symbols
+ */
+#define BBP105_DETECT_SIG_ON_PRIMARY	FIELD8(0x01)
+#define BBP105_FEQ			FIELD8(0x02)
+#define BBP105_MLD			FIELD8(0x04)
+#define BBP105_SIG_REMODULATION		FIELD8(0x08)
+
+/*
  * BBP 109
  */
 #define BBP109_TX0_POWER		FIELD8(0x0f)
@@ -1967,6 +1989,11 @@ struct mac_iveiv_entry {
 #define BBP152_RX_DEFAULT_ANT		FIELD8(0x80)
 
 /*
+ * BBP 254: unknown
+ */
+#define BBP254_BIT7			FIELD8(0x80)
+
+/*
  * RFCSR registers
  * The wordsize of the RFCSR is 8 bits.
  */
@@ -2022,9 +2049,18 @@ struct mac_iveiv_entry {
 #define RFCSR7_BITS67			FIELD8(0xc0)
 
 /*
+ * RFCSR 9:
+ */
+#define RFCSR9_K			FIELD8(0x0f)
+#define RFCSR9_N			FIELD8(0x10)
+#define RFCSR9_UNKNOWN			FIELD8(0x60)
+#define RFCSR9_MOD			FIELD8(0x80)
+
+/*
  * RFCSR 11:
  */
 #define RFCSR11_R			FIELD8(0x03)
+#define RFCSR11_MOD			FIELD8(0xc0)
 
 /*
  * RFCSR 12:
@@ -2130,11 +2166,13 @@ struct mac_iveiv_entry {
  * RFCSR 49:
  */
 #define RFCSR49_TX			FIELD8(0x3f)
+#define RFCSR49_EP			FIELD8(0xc0)
 
 /*
  * RFCSR 50:
  */
 #define RFCSR50_TX			FIELD8(0x3f)
+#define RFCSR50_EP			FIELD8(0xc0)
 
 /*
  * RF registers
@@ -2497,6 +2535,61 @@ struct mac_iveiv_entry {
 #define EEPROM_BBP_REG_ID		FIELD16(0xff00)
 
 /*
+ * EEPROM IQ Calibration, unlike other entries those are byte addresses.
+ */
+
+#define EEPROM_IQ_GAIN_CAL_TX0_2G			0x130
+#define EEPROM_IQ_PHASE_CAL_TX0_2G			0x131
+#define EEPROM_IQ_GROUPDELAY_CAL_TX0_2G			0x132
+#define EEPROM_IQ_GAIN_CAL_TX1_2G			0x133
+#define EEPROM_IQ_PHASE_CAL_TX1_2G			0x134
+#define EEPROM_IQ_GROUPDELAY_CAL_TX1_2G			0x135
+#define EEPROM_IQ_GAIN_CAL_RX0_2G			0x136
+#define EEPROM_IQ_PHASE_CAL_RX0_2G			0x137
+#define EEPROM_IQ_GROUPDELAY_CAL_RX0_2G			0x138
+#define EEPROM_IQ_GAIN_CAL_RX1_2G			0x139
+#define EEPROM_IQ_PHASE_CAL_RX1_2G			0x13A
+#define EEPROM_IQ_GROUPDELAY_CAL_RX1_2G			0x13B
+#define EEPROM_RF_IQ_COMPENSATION_CONTROL		0x13C
+#define EEPROM_RF_IQ_IMBALANCE_COMPENSATION_CONTROL	0x13D
+#define EEPROM_IQ_GAIN_CAL_TX0_CH36_TO_CH64_5G		0x144
+#define EEPROM_IQ_PHASE_CAL_TX0_CH36_TO_CH64_5G		0x145
+#define EEPROM_IQ_GAIN_CAL_TX0_CH100_TO_CH138_5G	0X146
+#define EEPROM_IQ_PHASE_CAL_TX0_CH100_TO_CH138_5G	0x147
+#define EEPROM_IQ_GAIN_CAL_TX0_CH140_TO_CH165_5G	0x148
+#define EEPROM_IQ_PHASE_CAL_TX0_CH140_TO_CH165_5G	0x149
+#define EEPROM_IQ_GAIN_CAL_TX1_CH36_TO_CH64_5G		0x14A
+#define EEPROM_IQ_PHASE_CAL_TX1_CH36_TO_CH64_5G		0x14B
+#define EEPROM_IQ_GAIN_CAL_TX1_CH100_TO_CH138_5G	0X14C
+#define EEPROM_IQ_PHASE_CAL_TX1_CH100_TO_CH138_5G	0x14D
+#define EEPROM_IQ_GAIN_CAL_TX1_CH140_TO_CH165_5G	0x14E
+#define EEPROM_IQ_PHASE_CAL_TX1_CH140_TO_CH165_5G	0x14F
+#define EEPROM_IQ_GROUPDELAY_CAL_TX0_CH36_TO_CH64_5G	0x150
+#define EEPROM_IQ_GROUPDELAY_CAL_TX1_CH36_TO_CH64_5G	0x151
+#define EEPROM_IQ_GROUPDELAY_CAL_TX0_CH100_TO_CH138_5G	0x152
+#define EEPROM_IQ_GROUPDELAY_CAL_TX1_CH100_TO_CH138_5G	0x153
+#define EEPROM_IQ_GROUPDELAY_CAL_TX0_CH140_TO_CH165_5G	0x154
+#define EEPROM_IQ_GROUPDELAY_CAL_TX1_CH140_TO_CH165_5G	0x155
+#define EEPROM_IQ_GAIN_CAL_RX0_CH36_TO_CH64_5G		0x156
+#define EEPROM_IQ_PHASE_CAL_RX0_CH36_TO_CH64_5G		0x157
+#define EEPROM_IQ_GAIN_CAL_RX0_CH100_TO_CH138_5G	0X158
+#define EEPROM_IQ_PHASE_CAL_RX0_CH100_TO_CH138_5G	0x159
+#define EEPROM_IQ_GAIN_CAL_RX0_CH140_TO_CH165_5G	0x15A
+#define EEPROM_IQ_PHASE_CAL_RX0_CH140_TO_CH165_5G	0x15B
+#define EEPROM_IQ_GAIN_CAL_RX1_CH36_TO_CH64_5G		0x15C
+#define EEPROM_IQ_PHASE_CAL_RX1_CH36_TO_CH64_5G		0x15D
+#define EEPROM_IQ_GAIN_CAL_RX1_CH100_TO_CH138_5G	0X15E
+#define EEPROM_IQ_PHASE_CAL_RX1_CH100_TO_CH138_5G	0x15F
+#define EEPROM_IQ_GAIN_CAL_RX1_CH140_TO_CH165_5G	0x160
+#define EEPROM_IQ_PHASE_CAL_RX1_CH140_TO_CH165_5G	0x161
+#define EEPROM_IQ_GROUPDELAY_CAL_RX0_CH36_TO_CH64_5G	0x162
+#define EEPROM_IQ_GROUPDELAY_CAL_RX1_CH36_TO_CH64_5G	0x163
+#define EEPROM_IQ_GROUPDELAY_CAL_RX0_CH100_TO_CH138_5G	0x164
+#define EEPROM_IQ_GROUPDELAY_CAL_RX1_CH100_TO_CH138_5G	0x165
+#define EEPROM_IQ_GROUPDELAY_CAL_RX0_CH140_TO_CH165_5G	0x166
+#define EEPROM_IQ_GROUPDELAY_CAL_RX1_CH140_TO_CH165_5G	0x167
+
+/*
  * MCU mailbox commands.
  * MCU_SLEEP - go to power-save mode.
  *             arg1: 1: save as much power as possible, 0: save less power.
@@ -2535,6 +2628,8 @@ struct mac_iveiv_entry {
 #define TXWI_DESC_SIZE			(4 * sizeof(__le32))
 #define RXWI_DESC_SIZE			(4 * sizeof(__le32))
 
+#define TXWI_DESC_SIZE_5592		(5 * sizeof(__le32))
+#define RXWI_DESC_SIZE_5592		(6 * sizeof(__le32))
 /*
  * TX WI structure
  */
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index a658b4b..7deac4d 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -527,8 +527,10 @@ int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev,
 	 */
 	rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
 	rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
-	if (rt2x00_is_usb(rt2x00dev))
+	if (rt2x00_is_usb(rt2x00dev)) {
 		rt2800_register_write(rt2x00dev, H2M_INT_SRC, 0);
+		rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0);
+	}
 	msleep(1);
 
 	return 0;
@@ -674,11 +676,6 @@ void rt2800_process_rxwi(struct queue_entry *entry,
 	 * Convert descriptor AGC value to RSSI value.
 	 */
 	rxdesc->rssi = rt2800_agc_to_rssi(entry->queue->rt2x00dev, word);
-
-	/*
-	 * Remove RXWI descriptor from start of buffer.
-	 */
-	skb_pull(entry->skb, RXWI_DESC_SIZE);
 }
 EXPORT_SYMBOL_GPL(rt2800_process_rxwi);
 
@@ -1988,8 +1985,21 @@ static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev,
 }
 
 #define POWER_BOUND		0x27
+#define POWER_BOUND_5G		0x2b
 #define FREQ_OFFSET_BOUND	0x5f
 
+static void rt2800_adjust_freq_offset(struct rt2x00_dev *rt2x00dev)
+{
+	u8 rfcsr;
+
+	rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr);
+	if (rt2x00dev->freq_offset > FREQ_OFFSET_BOUND)
+		rt2x00_set_field8(&rfcsr, RFCSR17_CODE, FREQ_OFFSET_BOUND);
+	else
+		rt2x00_set_field8(&rfcsr, RFCSR17_CODE, rt2x00dev->freq_offset);
+	rt2800_rfcsr_write(rt2x00dev, 17, rfcsr);
+}
+
 static void rt2800_config_channel_rf3290(struct rt2x00_dev *rt2x00dev,
 					 struct ieee80211_conf *conf,
 					 struct rf_channel *rf,
@@ -2010,12 +2020,7 @@ static void rt2800_config_channel_rf3290(struct rt2x00_dev *rt2x00dev,
 		rt2x00_set_field8(&rfcsr, RFCSR49_TX, info->default_power1);
 	rt2800_rfcsr_write(rt2x00dev, 49, rfcsr);
 
-	rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr);
-	if (rt2x00dev->freq_offset > FREQ_OFFSET_BOUND)
-		rt2x00_set_field8(&rfcsr, RFCSR17_CODE, FREQ_OFFSET_BOUND);
-	else
-		rt2x00_set_field8(&rfcsr, RFCSR17_CODE, rt2x00dev->freq_offset);
-	rt2800_rfcsr_write(rt2x00dev, 17, rfcsr);
+	rt2800_adjust_freq_offset(rt2x00dev);
 
 	if (rf->channel <= 14) {
 		if (rf->channel == 6)
@@ -2056,13 +2061,7 @@ static void rt2800_config_channel_rf3322(struct rt2x00_dev *rt2x00dev,
 	else
 		rt2800_rfcsr_write(rt2x00dev, 48, info->default_power2);
 
-	rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr);
-	if (rt2x00dev->freq_offset > FREQ_OFFSET_BOUND)
-		rt2x00_set_field8(&rfcsr, RFCSR17_CODE, FREQ_OFFSET_BOUND);
-	else
-		rt2x00_set_field8(&rfcsr, RFCSR17_CODE, rt2x00dev->freq_offset);
-
-	rt2800_rfcsr_write(rt2x00dev, 17, rfcsr);
+	rt2800_adjust_freq_offset(rt2x00dev);
 
 	rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);
 	rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 1);
@@ -2127,12 +2126,7 @@ static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev,
 	rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 1);
 	rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);
 
-	rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr);
-	if (rt2x00dev->freq_offset > FREQ_OFFSET_BOUND)
-		rt2x00_set_field8(&rfcsr, RFCSR17_CODE, FREQ_OFFSET_BOUND);
-	else
-		rt2x00_set_field8(&rfcsr, RFCSR17_CODE, rt2x00dev->freq_offset);
-	rt2800_rfcsr_write(rt2x00dev, 17, rfcsr);
+	rt2800_adjust_freq_offset(rt2x00dev);
 
 	if (rf->channel <= 14) {
 		int idx = rf->channel-1;
@@ -2184,6 +2178,382 @@ static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev,
 	}
 }
 
+static void rt2800_config_channel_rf55xx(struct rt2x00_dev *rt2x00dev,
+					 struct ieee80211_conf *conf,
+					 struct rf_channel *rf,
+					 struct channel_info *info)
+{
+	u8 rfcsr, ep_reg;
+	u32 reg;
+	int power_bound;
+
+	/* TODO */
+	const bool is_11b = false;
+	const bool is_type_ep = false;
+
+	rt2800_register_read(rt2x00dev, LDO_CFG0, &reg);
+	rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL,
+			   (rf->channel > 14 || conf_is_ht40(conf)) ? 5 : 0);
+	rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
+
+	/* Order of values on rf_channel entry: N, K, mod, R */
+	rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1 & 0xff);
+
+	rt2800_rfcsr_read(rt2x00dev,  9, &rfcsr);
+	rt2x00_set_field8(&rfcsr, RFCSR9_K, rf->rf2 & 0xf);
+	rt2x00_set_field8(&rfcsr, RFCSR9_N, (rf->rf1 & 0x100) >> 8);
+	rt2x00_set_field8(&rfcsr, RFCSR9_MOD, ((rf->rf3 - 8) & 0x4) >> 2);
+	rt2800_rfcsr_write(rt2x00dev, 9, rfcsr);
+
+	rt2800_rfcsr_read(rt2x00dev, 11, &rfcsr);
+	rt2x00_set_field8(&rfcsr, RFCSR11_R, rf->rf4 - 1);
+	rt2x00_set_field8(&rfcsr, RFCSR11_MOD, (rf->rf3 - 8) & 0x3);
+	rt2800_rfcsr_write(rt2x00dev, 11, rfcsr);
+
+	if (rf->channel <= 14) {
+		rt2800_rfcsr_write(rt2x00dev, 10, 0x90);
+		/* FIXME: RF11 owerwrite ? */
+		rt2800_rfcsr_write(rt2x00dev, 11, 0x4A);
+		rt2800_rfcsr_write(rt2x00dev, 12, 0x52);
+		rt2800_rfcsr_write(rt2x00dev, 13, 0x42);
+		rt2800_rfcsr_write(rt2x00dev, 22, 0x40);
+		rt2800_rfcsr_write(rt2x00dev, 24, 0x4A);
+		rt2800_rfcsr_write(rt2x00dev, 25, 0x80);
+		rt2800_rfcsr_write(rt2x00dev, 27, 0x42);
+		rt2800_rfcsr_write(rt2x00dev, 36, 0x80);
+		rt2800_rfcsr_write(rt2x00dev, 37, 0x08);
+		rt2800_rfcsr_write(rt2x00dev, 38, 0x89);
+		rt2800_rfcsr_write(rt2x00dev, 39, 0x1B);
+		rt2800_rfcsr_write(rt2x00dev, 40, 0x0D);
+		rt2800_rfcsr_write(rt2x00dev, 41, 0x9B);
+		rt2800_rfcsr_write(rt2x00dev, 42, 0xD5);
+		rt2800_rfcsr_write(rt2x00dev, 43, 0x72);
+		rt2800_rfcsr_write(rt2x00dev, 44, 0x0E);
+		rt2800_rfcsr_write(rt2x00dev, 45, 0xA2);
+		rt2800_rfcsr_write(rt2x00dev, 46, 0x6B);
+		rt2800_rfcsr_write(rt2x00dev, 48, 0x10);
+		rt2800_rfcsr_write(rt2x00dev, 51, 0x3E);
+		rt2800_rfcsr_write(rt2x00dev, 52, 0x48);
+		rt2800_rfcsr_write(rt2x00dev, 54, 0x38);
+		rt2800_rfcsr_write(rt2x00dev, 56, 0xA1);
+		rt2800_rfcsr_write(rt2x00dev, 57, 0x00);
+		rt2800_rfcsr_write(rt2x00dev, 58, 0x39);
+		rt2800_rfcsr_write(rt2x00dev, 60, 0x45);
+		rt2800_rfcsr_write(rt2x00dev, 61, 0x91);
+		rt2800_rfcsr_write(rt2x00dev, 62, 0x39);
+
+		/* TODO RF27 <- tssi */
+
+		rfcsr = rf->channel <= 10 ? 0x07 : 0x06;
+		rt2800_rfcsr_write(rt2x00dev, 23, rfcsr);
+		rt2800_rfcsr_write(rt2x00dev, 59, rfcsr);
+
+		if (is_11b) {
+			/* CCK */
+			rt2800_rfcsr_write(rt2x00dev, 31, 0xF8);
+			rt2800_rfcsr_write(rt2x00dev, 32, 0xC0);
+			if (is_type_ep)
+				rt2800_rfcsr_write(rt2x00dev, 55, 0x06);
+			else
+				rt2800_rfcsr_write(rt2x00dev, 55, 0x47);
+		} else {
+			/* OFDM */
+			if (is_type_ep)
+				rt2800_rfcsr_write(rt2x00dev, 55, 0x03);
+			else
+				rt2800_rfcsr_write(rt2x00dev, 55, 0x43);
+		}
+
+		power_bound = POWER_BOUND;
+		ep_reg = 0x2;
+	} else {
+		rt2800_rfcsr_write(rt2x00dev, 10, 0x97);
+		/* FIMXE: RF11 overwrite */
+		rt2800_rfcsr_write(rt2x00dev, 11, 0x40);
+		rt2800_rfcsr_write(rt2x00dev, 25, 0xBF);
+		rt2800_rfcsr_write(rt2x00dev, 27, 0x42);
+		rt2800_rfcsr_write(rt2x00dev, 36, 0x00);
+		rt2800_rfcsr_write(rt2x00dev, 37, 0x04);
+		rt2800_rfcsr_write(rt2x00dev, 38, 0x85);
+		rt2800_rfcsr_write(rt2x00dev, 40, 0x42);
+		rt2800_rfcsr_write(rt2x00dev, 41, 0xBB);
+		rt2800_rfcsr_write(rt2x00dev, 42, 0xD7);
+		rt2800_rfcsr_write(rt2x00dev, 45, 0x41);
+		rt2800_rfcsr_write(rt2x00dev, 48, 0x00);
+		rt2800_rfcsr_write(rt2x00dev, 57, 0x77);
+		rt2800_rfcsr_write(rt2x00dev, 60, 0x05);
+		rt2800_rfcsr_write(rt2x00dev, 61, 0x01);
+
+		/* TODO RF27 <- tssi */
+
+		if (rf->channel >= 36 && rf->channel <= 64) {
+
+			rt2800_rfcsr_write(rt2x00dev, 12, 0x2E);
+			rt2800_rfcsr_write(rt2x00dev, 13, 0x22);
+			rt2800_rfcsr_write(rt2x00dev, 22, 0x60);
+			rt2800_rfcsr_write(rt2x00dev, 23, 0x7F);
+			if (rf->channel <= 50)
+				rt2800_rfcsr_write(rt2x00dev, 24, 0x09);
+			else if (rf->channel >= 52)
+				rt2800_rfcsr_write(rt2x00dev, 24, 0x07);
+			rt2800_rfcsr_write(rt2x00dev, 39, 0x1C);
+			rt2800_rfcsr_write(rt2x00dev, 43, 0x5B);
+			rt2800_rfcsr_write(rt2x00dev, 44, 0X40);
+			rt2800_rfcsr_write(rt2x00dev, 46, 0X00);
+			rt2800_rfcsr_write(rt2x00dev, 51, 0xFE);
+			rt2800_rfcsr_write(rt2x00dev, 52, 0x0C);
+			rt2800_rfcsr_write(rt2x00dev, 54, 0xF8);
+			if (rf->channel <= 50) {
+				rt2800_rfcsr_write(rt2x00dev, 55, 0x06),
+				rt2800_rfcsr_write(rt2x00dev, 56, 0xD3);
+			} else if (rf->channel >= 52) {
+				rt2800_rfcsr_write(rt2x00dev, 55, 0x04);
+				rt2800_rfcsr_write(rt2x00dev, 56, 0xBB);
+			}
+
+			rt2800_rfcsr_write(rt2x00dev, 58, 0x15);
+			rt2800_rfcsr_write(rt2x00dev, 59, 0x7F);
+			rt2800_rfcsr_write(rt2x00dev, 62, 0x15);
+
+		} else if (rf->channel >= 100 && rf->channel <= 165) {
+
+			rt2800_rfcsr_write(rt2x00dev, 12, 0x0E);
+			rt2800_rfcsr_write(rt2x00dev, 13, 0x42);
+			rt2800_rfcsr_write(rt2x00dev, 22, 0x40);
+			if (rf->channel <= 153) {
+				rt2800_rfcsr_write(rt2x00dev, 23, 0x3C);
+				rt2800_rfcsr_write(rt2x00dev, 24, 0x06);
+			} else if (rf->channel >= 155) {
+				rt2800_rfcsr_write(rt2x00dev, 23, 0x38);
+				rt2800_rfcsr_write(rt2x00dev, 24, 0x05);
+			}
+			if (rf->channel <= 138) {
+				rt2800_rfcsr_write(rt2x00dev, 39, 0x1A);
+				rt2800_rfcsr_write(rt2x00dev, 43, 0x3B);
+				rt2800_rfcsr_write(rt2x00dev, 44, 0x20);
+				rt2800_rfcsr_write(rt2x00dev, 46, 0x18);
+			} else if (rf->channel >= 140) {
+				rt2800_rfcsr_write(rt2x00dev, 39, 0x18);
+				rt2800_rfcsr_write(rt2x00dev, 43, 0x1B);
+				rt2800_rfcsr_write(rt2x00dev, 44, 0x10);
+				rt2800_rfcsr_write(rt2x00dev, 46, 0X08);
+			}
+			if (rf->channel <= 124)
+				rt2800_rfcsr_write(rt2x00dev, 51, 0xFC);
+			else if (rf->channel >= 126)
+				rt2800_rfcsr_write(rt2x00dev, 51, 0xEC);
+			if (rf->channel <= 138)
+				rt2800_rfcsr_write(rt2x00dev, 52, 0x06);
+			else if (rf->channel >= 140)
+				rt2800_rfcsr_write(rt2x00dev, 52, 0x06);
+			rt2800_rfcsr_write(rt2x00dev, 54, 0xEB);
+			if (rf->channel <= 138)
+				rt2800_rfcsr_write(rt2x00dev, 55, 0x01);
+			else if (rf->channel >= 140)
+				rt2800_rfcsr_write(rt2x00dev, 55, 0x00);
+			if (rf->channel <= 128)
+				rt2800_rfcsr_write(rt2x00dev, 56, 0xBB);
+			else if (rf->channel >= 130)
+				rt2800_rfcsr_write(rt2x00dev, 56, 0xAB);
+			if (rf->channel <= 116)
+				rt2800_rfcsr_write(rt2x00dev, 58, 0x1D);
+			else if (rf->channel >= 118)
+				rt2800_rfcsr_write(rt2x00dev, 58, 0x15);
+			if (rf->channel <= 138)
+				rt2800_rfcsr_write(rt2x00dev, 59, 0x3F);
+			else if (rf->channel >= 140)
+				rt2800_rfcsr_write(rt2x00dev, 59, 0x7C);
+			if (rf->channel <= 116)
+				rt2800_rfcsr_write(rt2x00dev, 62, 0x1D);
+			else if (rf->channel >= 118)
+				rt2800_rfcsr_write(rt2x00dev, 62, 0x15);
+		}
+
+		power_bound = POWER_BOUND_5G;
+		ep_reg = 0x3;
+	}
+
+	rt2800_rfcsr_read(rt2x00dev, 49, &rfcsr);
+	if (info->default_power1 > power_bound)
+		rt2x00_set_field8(&rfcsr, RFCSR49_TX, power_bound);
+	else
+		rt2x00_set_field8(&rfcsr, RFCSR49_TX, info->default_power1);
+	if (is_type_ep)
+		rt2x00_set_field8(&rfcsr, RFCSR49_EP, ep_reg);
+	rt2800_rfcsr_write(rt2x00dev, 49, rfcsr);
+
+	rt2800_rfcsr_read(rt2x00dev, 50, &rfcsr);
+	if (info->default_power1 > power_bound)
+		rt2x00_set_field8(&rfcsr, RFCSR50_TX, power_bound);
+	else
+		rt2x00_set_field8(&rfcsr, RFCSR50_TX, info->default_power2);
+	if (is_type_ep)
+		rt2x00_set_field8(&rfcsr, RFCSR50_EP, ep_reg);
+	rt2800_rfcsr_write(rt2x00dev, 50, rfcsr);
+
+	rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);
+	rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1);
+	rt2x00_set_field8(&rfcsr, RFCSR1_PLL_PD, 1);
+
+	rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD,
+			  rt2x00dev->default_ant.tx_chain_num >= 1);
+	rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD,
+			  rt2x00dev->default_ant.tx_chain_num == 2);
+	rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 0);
+
+	rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD,
+			  rt2x00dev->default_ant.rx_chain_num >= 1);
+	rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD,
+			  rt2x00dev->default_ant.rx_chain_num == 2);
+	rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 0);
+
+	rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);
+	rt2800_rfcsr_write(rt2x00dev, 6, 0xe4);
+
+	if (conf_is_ht40(conf))
+		rt2800_rfcsr_write(rt2x00dev, 30, 0x16);
+	else
+		rt2800_rfcsr_write(rt2x00dev, 30, 0x10);
+
+	if (!is_11b) {
+		rt2800_rfcsr_write(rt2x00dev, 31, 0x80);
+		rt2800_rfcsr_write(rt2x00dev, 32, 0x80);
+	}
+
+	/* TODO proper frequency adjustment */
+	rt2800_adjust_freq_offset(rt2x00dev);
+
+	/* TODO merge with others */
+	rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr);
+	rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1);
+	rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
+
+	/* BBP settings */
+	rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain);
+	rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain);
+	rt2800_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain);
+
+	rt2800_bbp_write(rt2x00dev, 79, (rf->channel <= 14) ? 0x1C : 0x18);
+	rt2800_bbp_write(rt2x00dev, 80, (rf->channel <= 14) ? 0x0E : 0x08);
+	rt2800_bbp_write(rt2x00dev, 81, (rf->channel <= 14) ? 0x3A : 0x38);
+	rt2800_bbp_write(rt2x00dev, 82, (rf->channel <= 14) ? 0x62 : 0x92);
+
+	/* GLRT band configuration */
+	rt2800_bbp_write(rt2x00dev, 195, 128);
+	rt2800_bbp_write(rt2x00dev, 196, (rf->channel <= 14) ? 0xE0 : 0xF0);
+	rt2800_bbp_write(rt2x00dev, 195, 129);
+	rt2800_bbp_write(rt2x00dev, 196, (rf->channel <= 14) ? 0x1F : 0x1E);
+	rt2800_bbp_write(rt2x00dev, 195, 130);
+	rt2800_bbp_write(rt2x00dev, 196, (rf->channel <= 14) ? 0x38 : 0x28);
+	rt2800_bbp_write(rt2x00dev, 195, 131);
+	rt2800_bbp_write(rt2x00dev, 196, (rf->channel <= 14) ? 0x32 : 0x20);
+	rt2800_bbp_write(rt2x00dev, 195, 133);
+	rt2800_bbp_write(rt2x00dev, 196, (rf->channel <= 14) ? 0x28 : 0x7F);
+	rt2800_bbp_write(rt2x00dev, 195, 124);
+	rt2800_bbp_write(rt2x00dev, 196, (rf->channel <= 14) ? 0x19 : 0x7F);
+}
+
+static void rt2800_bbp_write_with_rx_chain(struct rt2x00_dev *rt2x00dev,
+					   const unsigned int word,
+					   const u8 value)
+{
+	u8 chain, reg;
+
+	for (chain = 0; chain < rt2x00dev->default_ant.rx_chain_num; chain++) {
+		rt2800_bbp_read(rt2x00dev, 27, &reg);
+		rt2x00_set_field8(&reg,  BBP27_RX_CHAIN_SEL, chain);
+		rt2800_bbp_write(rt2x00dev, 27, reg);
+
+		rt2800_bbp_write(rt2x00dev, word, value);
+	}
+}
+
+static void rt2800_iq_calibrate(struct rt2x00_dev *rt2x00dev, int channel)
+{
+	u8 cal;
+
+	/* TX0 IQ Gain */
+	rt2800_bbp_write(rt2x00dev, 158, 0x2c);
+	if (channel <= 14)
+		cal = rt2x00_eeprom_byte(rt2x00dev, EEPROM_IQ_GAIN_CAL_TX0_2G);
+	else if (channel >= 36 && channel <= 64)
+		cal = rt2x00_eeprom_byte(rt2x00dev,
+					 EEPROM_IQ_GAIN_CAL_TX0_CH36_TO_CH64_5G);
+	else if (channel >= 100 && channel <= 138)
+		cal = rt2x00_eeprom_byte(rt2x00dev,
+					 EEPROM_IQ_GAIN_CAL_TX0_CH100_TO_CH138_5G);
+	else if (channel >= 140 && channel <= 165)
+		cal = rt2x00_eeprom_byte(rt2x00dev,
+					 EEPROM_IQ_GAIN_CAL_TX0_CH140_TO_CH165_5G);
+	else
+		cal = 0;
+	rt2800_bbp_write(rt2x00dev, 159, cal);
+
+	/* TX0 IQ Phase */
+	rt2800_bbp_write(rt2x00dev, 158, 0x2d);
+	if (channel <= 14)
+		cal = rt2x00_eeprom_byte(rt2x00dev, EEPROM_IQ_PHASE_CAL_TX0_2G);
+	else if (channel >= 36 && channel <= 64)
+		cal = rt2x00_eeprom_byte(rt2x00dev,
+					 EEPROM_IQ_PHASE_CAL_TX0_CH36_TO_CH64_5G);
+	else if (channel >= 100 && channel <= 138)
+		cal = rt2x00_eeprom_byte(rt2x00dev,
+					 EEPROM_IQ_PHASE_CAL_TX0_CH100_TO_CH138_5G);
+	else if (channel >= 140 && channel <= 165)
+		cal = rt2x00_eeprom_byte(rt2x00dev,
+					 EEPROM_IQ_PHASE_CAL_TX0_CH140_TO_CH165_5G);
+	else
+		cal = 0;
+	rt2800_bbp_write(rt2x00dev, 159, cal);
+
+	/* TX1 IQ Gain */
+	rt2800_bbp_write(rt2x00dev, 158, 0x4a);
+	if (channel <= 14)
+		cal = rt2x00_eeprom_byte(rt2x00dev, EEPROM_IQ_GAIN_CAL_TX1_2G);
+	else if (channel >= 36 && channel <= 64)
+		cal = rt2x00_eeprom_byte(rt2x00dev,
+					 EEPROM_IQ_GAIN_CAL_TX1_CH36_TO_CH64_5G);
+	else if (channel >= 100 && channel <= 138)
+		cal = rt2x00_eeprom_byte(rt2x00dev,
+					 EEPROM_IQ_GAIN_CAL_TX1_CH100_TO_CH138_5G);
+	else if (channel >= 140 && channel <= 165)
+		cal = rt2x00_eeprom_byte(rt2x00dev,
+					 EEPROM_IQ_GAIN_CAL_TX1_CH140_TO_CH165_5G);
+	else
+		cal = 0;
+	rt2800_bbp_write(rt2x00dev, 159, cal);
+
+	/* TX1 IQ Phase */
+	rt2800_bbp_write(rt2x00dev, 158, 0x4b);
+	if (channel <= 14)
+		cal = rt2x00_eeprom_byte(rt2x00dev, EEPROM_IQ_PHASE_CAL_TX1_2G);
+	else if (channel >= 36 && channel <= 64)
+		cal = rt2x00_eeprom_byte(rt2x00dev,
+					 EEPROM_IQ_PHASE_CAL_TX1_CH36_TO_CH64_5G);
+	else if (channel >= 100 && channel <= 138)
+		cal = rt2x00_eeprom_byte(rt2x00dev,
+					 EEPROM_IQ_PHASE_CAL_TX1_CH100_TO_CH138_5G);
+	else if (channel >= 140 && channel <= 165)
+		cal = rt2x00_eeprom_byte(rt2x00dev,
+					 EEPROM_IQ_PHASE_CAL_TX1_CH140_TO_CH165_5G);
+	else
+		cal = 0;
+	rt2800_bbp_write(rt2x00dev, 159, cal);
+
+	/* FIXME: possible RX0, RX1 callibration ? */
+
+	/* RF IQ compensation control */
+	rt2800_bbp_write(rt2x00dev, 158, 0x04);
+	cal = rt2x00_eeprom_byte(rt2x00dev, EEPROM_RF_IQ_COMPENSATION_CONTROL);
+	rt2800_bbp_write(rt2x00dev, 159, cal != 0xff ? cal : 0);
+
+	/* RF IQ imbalance compensation control */
+	rt2800_bbp_write(rt2x00dev, 158, 0x03);
+	cal = rt2x00_eeprom_byte(rt2x00dev,
+				 EEPROM_RF_IQ_IMBALANCE_COMPENSATION_CONTROL);
+	rt2800_bbp_write(rt2x00dev, 159, cal != 0xff ? cal : 0);
+}
+
 static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
 				  struct ieee80211_conf *conf,
 				  struct rf_channel *rf,
@@ -2225,6 +2595,9 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
 	case RF5392:
 		rt2800_config_channel_rf53xx(rt2x00dev, conf, rf, info);
 		break;
+	case RF5592:
+		rt2800_config_channel_rf55xx(rt2x00dev, conf, rf, info);
+		break;
 	default:
 		rt2800_config_channel_rf2xxx(rt2x00dev, conf, rf, info);
 	}
@@ -2326,6 +2699,17 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
 	if (rt2x00_rt(rt2x00dev, RT3572))
 		rt2800_rfcsr_write(rt2x00dev, 8, 0x80);
 
+	if (rt2x00_rt(rt2x00dev, RT5592)) {
+		rt2800_bbp_write(rt2x00dev, 195, 141);
+		rt2800_bbp_write(rt2x00dev, 196, conf_is_ht40(conf) ? 0x10 : 0x1a);
+
+		/* AGC init */
+		reg = (rf->channel <= 14 ? 0x1c : 0x24) + 2 * rt2x00dev->lna_gain;
+		rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, reg);
+
+		rt2800_iq_calibrate(rt2x00dev, rf->channel);
+	}
+
 	rt2800_bbp_read(rt2x00dev, 4, &bbp);
 	rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * conf_is_ht40(conf));
 	rt2800_bbp_write(rt2x00dev, 4, bbp);
@@ -2938,13 +3322,16 @@ static u8 rt2800_get_default_vgc(struct rt2x00_dev *rt2x00dev)
 		    rt2x00_rt(rt2x00dev, RT3390) ||
 		    rt2x00_rt(rt2x00dev, RT3572) ||
 		    rt2x00_rt(rt2x00dev, RT5390) ||
-		    rt2x00_rt(rt2x00dev, RT5392))
+		    rt2x00_rt(rt2x00dev, RT5392) ||
+		    rt2x00_rt(rt2x00dev, RT5592))
 			vgc = 0x1c + (2 * rt2x00dev->lna_gain);
 		else
 			vgc = 0x2e + rt2x00dev->lna_gain;
 	} else { /* 5GHZ band */
 		if (rt2x00_rt(rt2x00dev, RT3572))
 			vgc = 0x22 + (rt2x00dev->lna_gain * 5) / 3;
+		else if (rt2x00_rt(rt2x00dev, RT5592))
+			vgc = 0x24 + (2 * rt2x00dev->lna_gain);
 		else {
 			if (!test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags))
 				vgc = 0x32 + (rt2x00dev->lna_gain * 5) / 3;
@@ -2960,7 +3347,11 @@ static inline void rt2800_set_vgc(struct rt2x00_dev *rt2x00dev,
 				  struct link_qual *qual, u8 vgc_level)
 {
 	if (qual->vgc_level != vgc_level) {
-		rt2800_bbp_write(rt2x00dev, 66, vgc_level);
+		if (rt2x00_rt(rt2x00dev, RT5592)) {
+			rt2800_bbp_write(rt2x00dev, 83, qual->rssi > -65 ? 0x4a : 0x7a);
+			rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, vgc_level);
+		} else
+			rt2800_bbp_write(rt2x00dev, 66, vgc_level);
 		qual->vgc_level = vgc_level;
 		qual->vgc_level_reg = vgc_level;
 	}
@@ -2975,15 +3366,23 @@ EXPORT_SYMBOL_GPL(rt2800_reset_tuner);
 void rt2800_link_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual,
 		       const u32 count)
 {
+	u8 vgc;
+
 	if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C))
 		return;
-
 	/*
-	 * When RSSI is better then -80 increase VGC level with 0x10
+	 * When RSSI is better then -80 increase VGC level with 0x10, except
+	 * for rt5592 chip.
 	 */
-	rt2800_set_vgc(rt2x00dev, qual,
-		       rt2800_get_default_vgc(rt2x00dev) +
-		       ((qual->rssi > -80) * 0x10));
+
+	vgc = rt2800_get_default_vgc(rt2x00dev);
+
+	if (rt2x00_rt(rt2x00dev, RT5592) && qual->rssi > -65)
+		vgc += 0x20;
+	else if (qual->rssi > -80)
+		vgc += 0x10;
+
+	rt2800_set_vgc(rt2x00dev, qual, vgc);
 }
 EXPORT_SYMBOL_GPL(rt2800_link_tuner);
 
@@ -3122,7 +3521,8 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
 		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400);
 		rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
 	} else if (rt2x00_rt(rt2x00dev, RT5390) ||
-		   rt2x00_rt(rt2x00dev, RT5392)) {
+		   rt2x00_rt(rt2x00dev, RT5392) ||
+		   rt2x00_rt(rt2x00dev, RT5592)) {
 		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404);
 		rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
 		rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000);
@@ -3302,7 +3702,8 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
 	rt2x00_set_field32(&reg, TXOP_CTRL_CFG_EXT_CWMIN, 0);
 	rt2800_register_write(rt2x00dev, TXOP_CTRL_CFG, reg);
 
-	rt2800_register_write(rt2x00dev, TXOP_HLDR_ET, 0x00000002);
+	reg = rt2x00_rt(rt2x00dev, RT5592) ? 0x00000082 : 0x00000002;
+	rt2800_register_write(rt2x00dev, TXOP_HLDR_ET, reg);
 
 	rt2800_register_read(rt2x00dev, TX_RTS_CFG, &reg);
 	rt2x00_set_field32(&reg, TX_RTS_CFG_AUTO_RTS_RETRY_LIMIT, 32);
@@ -3487,6 +3888,136 @@ static int rt2800_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)
 	return -EACCES;
 }
 
+static void rt2800_bbp4_mac_if_ctrl(struct rt2x00_dev *rt2x00dev)
+{
+	u8 value;
+
+	rt2800_bbp_read(rt2x00dev, 4, &value);
+	rt2x00_set_field8(&value, BBP4_MAC_IF_CTRL, 1);
+	rt2800_bbp_write(rt2x00dev, 4, value);
+}
+
+static void rt2800_init_freq_calibration(struct rt2x00_dev *rt2x00dev)
+{
+	rt2800_bbp_write(rt2x00dev, 142, 1);
+	rt2800_bbp_write(rt2x00dev, 143, 57);
+}
+
+static void rt2800_init_bbp_5592_glrt(struct rt2x00_dev *rt2x00dev)
+{
+	const u8 glrt_table[] = {
+		0xE0, 0x1F, 0X38, 0x32, 0x08, 0x28, 0x19, 0x0A, 0xFF, 0x00, /* 128 ~ 137 */
+		0x16, 0x10, 0x10, 0x0B, 0x36, 0x2C, 0x26, 0x24, 0x42, 0x36, /* 138 ~ 147 */
+		0x30, 0x2D, 0x4C, 0x46, 0x3D, 0x40, 0x3E, 0x42, 0x3D, 0x40, /* 148 ~ 157 */
+		0X3C, 0x34, 0x2C, 0x2F, 0x3C, 0x35, 0x2E, 0x2A, 0x49, 0x41, /* 158 ~ 167 */
+		0x36, 0x31, 0x30, 0x30, 0x0E, 0x0D, 0x28, 0x21, 0x1C, 0x16, /* 168 ~ 177 */
+		0x50, 0x4A, 0x43, 0x40, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, /* 178 ~ 187 */
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 188 ~ 197 */
+		0x00, 0x00, 0x7D, 0x14, 0x32, 0x2C, 0x36, 0x4C, 0x43, 0x2C, /* 198 ~ 207 */
+		0x2E, 0x36, 0x30, 0x6E,					    /* 208 ~ 211 */
+	};
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(glrt_table); i++) {
+		rt2800_bbp_write(rt2x00dev, 195, 128 + i);
+		rt2800_bbp_write(rt2x00dev, 196, glrt_table[i]);
+	}
+};
+
+static void rt2800_init_bbb_early(struct rt2x00_dev *rt2x00dev)
+{
+	rt2800_bbp_write(rt2x00dev, 65, 0x2C);
+	rt2800_bbp_write(rt2x00dev, 66, 0x38);
+	rt2800_bbp_write(rt2x00dev, 68, 0x0B);
+	rt2800_bbp_write(rt2x00dev, 69, 0x12);
+	rt2800_bbp_write(rt2x00dev, 70, 0x0a);
+	rt2800_bbp_write(rt2x00dev, 73, 0x10);
+	rt2800_bbp_write(rt2x00dev, 81, 0x37);
+	rt2800_bbp_write(rt2x00dev, 82, 0x62);
+	rt2800_bbp_write(rt2x00dev, 83, 0x6A);
+	rt2800_bbp_write(rt2x00dev, 84, 0x99);
+	rt2800_bbp_write(rt2x00dev, 86, 0x00);
+	rt2800_bbp_write(rt2x00dev, 91, 0x04);
+	rt2800_bbp_write(rt2x00dev, 92, 0x00);
+	rt2800_bbp_write(rt2x00dev, 103, 0x00);
+	rt2800_bbp_write(rt2x00dev, 105, 0x05);
+	rt2800_bbp_write(rt2x00dev, 106, 0x35);
+}
+
+static void rt2800_init_bbp_5592(struct rt2x00_dev *rt2x00dev)
+{
+	int ant, div_mode;
+	u16 eeprom;
+	u8 value;
+
+	rt2800_init_bbb_early(rt2x00dev);
+
+	rt2800_bbp_read(rt2x00dev, 105, &value);
+	rt2x00_set_field8(&value, BBP105_MLD,
+			  rt2x00dev->default_ant.rx_chain_num == 2);
+	rt2800_bbp_write(rt2x00dev, 105, value);
+
+	rt2800_bbp4_mac_if_ctrl(rt2x00dev);
+
+	rt2800_bbp_write(rt2x00dev, 20, 0x06);
+	rt2800_bbp_write(rt2x00dev, 31, 0x08);
+	rt2800_bbp_write(rt2x00dev, 65, 0x2C);
+	rt2800_bbp_write(rt2x00dev, 68, 0xDD);
+	rt2800_bbp_write(rt2x00dev, 69, 0x1A);
+	rt2800_bbp_write(rt2x00dev, 70, 0x05);
+	rt2800_bbp_write(rt2x00dev, 73, 0x13);
+	rt2800_bbp_write(rt2x00dev, 74, 0x0F);
+	rt2800_bbp_write(rt2x00dev, 75, 0x4F);
+	rt2800_bbp_write(rt2x00dev, 76, 0x28);
+	rt2800_bbp_write(rt2x00dev, 77, 0x59);
+	rt2800_bbp_write(rt2x00dev, 84, 0x9A);
+	rt2800_bbp_write(rt2x00dev, 86, 0x38);
+	rt2800_bbp_write(rt2x00dev, 88, 0x90);
+	rt2800_bbp_write(rt2x00dev, 91, 0x04);
+	rt2800_bbp_write(rt2x00dev, 92, 0x02);
+	rt2800_bbp_write(rt2x00dev, 95, 0x9a);
+	rt2800_bbp_write(rt2x00dev, 98, 0x12);
+	rt2800_bbp_write(rt2x00dev, 103, 0xC0);
+	rt2800_bbp_write(rt2x00dev, 104, 0x92);
+	/* FIXME BBP105 owerwrite */
+	rt2800_bbp_write(rt2x00dev, 105, 0x3C);
+	rt2800_bbp_write(rt2x00dev, 106, 0x35);
+	rt2800_bbp_write(rt2x00dev, 128, 0x12);
+	rt2800_bbp_write(rt2x00dev, 134, 0xD0);
+	rt2800_bbp_write(rt2x00dev, 135, 0xF6);
+	rt2800_bbp_write(rt2x00dev, 137, 0x0F);
+
+	/* Initialize GLRT (Generalized Likehood Radio Test) */
+	rt2800_init_bbp_5592_glrt(rt2x00dev);
+
+	rt2800_bbp4_mac_if_ctrl(rt2x00dev);
+
+	rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);
+	div_mode = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_ANT_DIVERSITY);
+	ant = (div_mode == 3) ? 1 : 0;
+	rt2800_bbp_read(rt2x00dev, 152, &value);
+	if (ant == 0) {
+		/* Main antenna */
+		rt2x00_set_field8(&value, BBP152_RX_DEFAULT_ANT, 1);
+	} else {
+		/* Auxiliary antenna */
+		rt2x00_set_field8(&value, BBP152_RX_DEFAULT_ANT, 0);
+	}
+	rt2800_bbp_write(rt2x00dev, 152, value);
+
+	if (rt2x00_rt_rev_gte(rt2x00dev, RT5592, REV_RT5592C)) {
+		rt2800_bbp_read(rt2x00dev, 254, &value);
+		rt2x00_set_field8(&value, BBP254_BIT7, 1);
+		rt2800_bbp_write(rt2x00dev, 254, value);
+	}
+
+	rt2800_init_freq_calibration(rt2x00dev);
+
+	rt2800_bbp_write(rt2x00dev, 84, 0x19);
+	if (rt2x00_rt_rev_gte(rt2x00dev, RT5592, REV_RT5592C))
+		rt2800_bbp_write(rt2x00dev, 103, 0xc0);
+}
+
 static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
 {
 	unsigned int i;
@@ -3498,6 +4029,11 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
 		     rt2800_wait_bbp_ready(rt2x00dev)))
 		return -EACCES;
 
+	if (rt2x00_rt(rt2x00dev, RT5592)) {
+		rt2800_init_bbp_5592(rt2x00dev);
+		return 0;
+	}
+
 	if (rt2x00_rt(rt2x00dev, RT3352)) {
 		rt2800_bbp_write(rt2x00dev, 3, 0x00);
 		rt2800_bbp_write(rt2x00dev, 4, 0x50);
@@ -3505,11 +4041,8 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
 
 	if (rt2x00_rt(rt2x00dev, RT3290) ||
 	    rt2x00_rt(rt2x00dev, RT5390) ||
-	    rt2x00_rt(rt2x00dev, RT5392)) {
-		rt2800_bbp_read(rt2x00dev, 4, &value);
-		rt2x00_set_field8(&value, BBP4_MAC_IF_CTRL, 1);
-		rt2800_bbp_write(rt2x00dev, 4, value);
-	}
+	    rt2x00_rt(rt2x00dev, RT5392))
+		rt2800_bbp4_mac_if_ctrl(rt2x00dev);
 
 	if (rt2800_is_305x_soc(rt2x00dev) ||
 	    rt2x00_rt(rt2x00dev, RT3290) ||
@@ -3783,9 +4316,7 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
 			rt2x00_set_field8(&value, BBP152_RX_DEFAULT_ANT, 0);
 		rt2800_bbp_write(rt2x00dev, 152, value);
 
-		/* Init frequency calibration */
-		rt2800_bbp_write(rt2x00dev, 142, 1);
-		rt2800_bbp_write(rt2x00dev, 143, 57);
+		rt2800_init_freq_calibration(rt2x00dev);
 	}
 
 	for (i = 0; i < EEPROM_BBP_SIZE; i++) {
@@ -4259,6 +4790,69 @@ static void rt2800_init_rfcsr_5392(struct rt2x00_dev *rt2x00dev)
 	rt2800_rfcsr_write(rt2x00dev, 63, 0x07);
 }
 
+static void rt2800_init_rfcsr_5592(struct rt2x00_dev *rt2x00dev)
+{
+	u8 reg;
+	u16 eeprom;
+
+	rt2800_rfcsr_write(rt2x00dev, 1, 0x3F);
+	rt2800_rfcsr_write(rt2x00dev, 3, 0x08);
+	rt2800_rfcsr_write(rt2x00dev, 3, 0x08);
+	rt2800_rfcsr_write(rt2x00dev, 5, 0x10);
+	rt2800_rfcsr_write(rt2x00dev, 6, 0xE4);
+	rt2800_rfcsr_write(rt2x00dev, 7, 0x00);
+	rt2800_rfcsr_write(rt2x00dev, 14, 0x00);
+	rt2800_rfcsr_write(rt2x00dev, 15, 0x00);
+	rt2800_rfcsr_write(rt2x00dev, 16, 0x00);
+	rt2800_rfcsr_write(rt2x00dev, 18, 0x03);
+	rt2800_rfcsr_write(rt2x00dev, 19, 0x4D);
+	rt2800_rfcsr_write(rt2x00dev, 20, 0x10);
+	rt2800_rfcsr_write(rt2x00dev, 21, 0x8D);
+	rt2800_rfcsr_write(rt2x00dev, 26, 0x82);
+	rt2800_rfcsr_write(rt2x00dev, 28, 0x00);
+	rt2800_rfcsr_write(rt2x00dev, 29, 0x10);
+	rt2800_rfcsr_write(rt2x00dev, 33, 0xC0);
+	rt2800_rfcsr_write(rt2x00dev, 34, 0x07);
+	rt2800_rfcsr_write(rt2x00dev, 35, 0x12);
+	rt2800_rfcsr_write(rt2x00dev, 47, 0x0C);
+	rt2800_rfcsr_write(rt2x00dev, 53, 0x22);
+	rt2800_rfcsr_write(rt2x00dev, 63, 0x07);
+
+	rt2800_rfcsr_write(rt2x00dev, 2, 0x80);
+	msleep(1);
+
+	rt2800_adjust_freq_offset(rt2x00dev);
+
+	rt2800_bbp_read(rt2x00dev, 138, &reg);
+
+	/*  Turn off unused DAC1 and ADC1 to reduce power consumption */
+	rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom);
+	if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH) == 1)
+		rt2x00_set_field8(&reg, BBP138_RX_ADC1, 0);
+	if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH) == 1)
+		rt2x00_set_field8(&reg, BBP138_TX_DAC1, 1);
+
+	rt2800_bbp_write(rt2x00dev, 138, reg);
+
+	/* Enable DC filter */
+	if (rt2x00_rt_rev_gte(rt2x00dev, RT5592, REV_RT5592C))
+		rt2800_bbp_write(rt2x00dev, 103, 0xc0);
+
+	rt2800_rfcsr_read(rt2x00dev, 38, &reg);
+	rt2x00_set_field8(&reg, RFCSR38_RX_LO1_EN, 0);
+	rt2800_rfcsr_write(rt2x00dev, 38, reg);
+
+	rt2800_rfcsr_read(rt2x00dev, 39, &reg);
+	rt2x00_set_field8(&reg, RFCSR39_RX_LO2_EN, 0);
+	rt2800_rfcsr_write(rt2x00dev, 39, reg);
+
+	rt2800_bbp4_mac_if_ctrl(rt2x00dev);
+
+	rt2800_rfcsr_read(rt2x00dev, 30, &reg);
+	rt2x00_set_field8(&reg, RFCSR30_RX_VCM, 2);
+	rt2800_rfcsr_write(rt2x00dev, 30, reg);
+}
+
 static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
 {
 	struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
@@ -4276,6 +4870,8 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
 	    !rt2x00_rt(rt2x00dev, RT3572) &&
 	    !rt2x00_rt(rt2x00dev, RT5390) &&
 	    !rt2x00_rt(rt2x00dev, RT5392) &&
+	    !rt2x00_rt(rt2x00dev, RT5392) &&
+	    !rt2x00_rt(rt2x00dev, RT5592) &&
 	    !rt2800_is_305x_soc(rt2x00dev))
 		return 0;
 
@@ -4330,6 +4926,9 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
 	case RT5392:
 		rt2800_init_rfcsr_5392(rt2x00dev);
 		break;
+	case RT5592:
+		rt2800_init_rfcsr_5592(rt2x00dev);
+		return 0;
 	}
 
 	if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) {
@@ -4427,7 +5026,8 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
 	if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F) ||
 	    rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||
 	    rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) ||
-	    rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E))
+	    rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E) ||
+	    rt2x00_rt_rev_lt(rt2x00dev, RT5592, REV_RT5592C))
 		rt2800_rfcsr_write(rt2x00dev, 27, 0x03);
 
 	rt2800_register_read(rt2x00dev, OPT_14_CSR, &reg);
@@ -4451,7 +5051,8 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
 		rt2800_rfcsr_write(rt2x00dev, 17, rfcsr);
 	}
 
-	if (rt2x00_rt(rt2x00dev, RT3090)) {
+	if (rt2x00_rt(rt2x00dev, RT3090) ||
+	    rt2x00_rt(rt2x00dev, RT5592)) {
 		rt2800_bbp_read(rt2x00dev, 138, &bbp);
 
 		/*  Turn off unused DAC1 and ADC1 to reduce power consumption */
@@ -4507,7 +5108,8 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
 	}
 
 	if (rt2x00_rt(rt2x00dev, RT5390) ||
-	    rt2x00_rt(rt2x00dev, RT5392)) {
+	    rt2x00_rt(rt2x00dev, RT5392) ||
+	    rt2x00_rt(rt2x00dev, RT5592)) {
 		rt2800_rfcsr_read(rt2x00dev, 38, &rfcsr);
 		rt2x00_set_field8(&rfcsr, RFCSR38_RX_LO1_EN, 0);
 		rt2800_rfcsr_write(rt2x00dev, 38, rfcsr);
@@ -4533,15 +5135,23 @@ int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev)
 	 * Initialize all registers.
 	 */
 	if (unlikely(rt2800_wait_wpdma_ready(rt2x00dev) ||
-		     rt2800_init_registers(rt2x00dev) ||
-		     rt2800_init_bbp(rt2x00dev) ||
-		     rt2800_init_rfcsr(rt2x00dev)))
+		     rt2800_init_registers(rt2x00dev)))
 		return -EIO;
 
 	/*
 	 * Send signal to firmware during boot time.
 	 */
-	rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0);
+	rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
+	rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
+	if (rt2x00_is_usb(rt2x00dev)) {
+		rt2800_register_write(rt2x00dev, H2M_INT_SRC, 0);
+		rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0);
+	}
+	msleep(1);
+
+	if (unlikely(rt2800_init_bbp(rt2x00dev) ||
+		     rt2800_init_rfcsr(rt2x00dev)))
+		return -EIO;
 
 	if (rt2x00_is_usb(rt2x00dev) &&
 	    (rt2x00_rt(rt2x00dev, RT3070) ||
@@ -4821,9 +5431,9 @@ static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
 
 static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
 {
-	u32 reg;
 	u16 value;
 	u16 eeprom;
+	u16 rf;
 
 	/*
 	 * Read EEPROM word for configuration.
@@ -4835,41 +5445,14 @@ static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
 	 * RT28xx/RT30xx: defined in "EEPROM_NIC_CONF0_RF_TYPE" field
 	 * RT53xx: defined in "EEPROM_CHIP_ID" field
 	 */
-	if (rt2x00_rt(rt2x00dev, RT3290))
-		rt2800_register_read(rt2x00dev, MAC_CSR0_3290, &reg);
-	else
-		rt2800_register_read(rt2x00dev, MAC_CSR0, &reg);
-
-	if (rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT3290 ||
-	    rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT5390 ||
-	    rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT5392)
-		rt2x00_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &value);
+	if (rt2x00_rt(rt2x00dev, RT3290) ||
+	    rt2x00_rt(rt2x00dev, RT5390) ||
+	    rt2x00_rt(rt2x00dev, RT5392))
+		rt2x00_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &rf);
 	else
-		value = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RF_TYPE);
-
-	rt2x00_set_chip(rt2x00dev, rt2x00_get_field32(reg, MAC_CSR0_CHIPSET),
-			value, rt2x00_get_field32(reg, MAC_CSR0_REVISION));
-
-	switch (rt2x00dev->chip.rt) {
-	case RT2860:
-	case RT2872:
-	case RT2883:
-	case RT3070:
-	case RT3071:
-	case RT3090:
-	case RT3290:
-	case RT3352:
-	case RT3390:
-	case RT3572:
-	case RT5390:
-	case RT5392:
-		break;
-	default:
-		ERROR(rt2x00dev, "Invalid RT chipset 0x%04x detected.\n", rt2x00dev->chip.rt);
-		return -ENODEV;
-	}
+		rf = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RF_TYPE);
 
-	switch (rt2x00dev->chip.rf) {
+	switch (rf) {
 	case RF2820:
 	case RF2850:
 	case RF2720:
@@ -4887,13 +5470,15 @@ static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
 	case RF5372:
 	case RF5390:
 	case RF5392:
+	case RF5592:
 		break;
 	default:
-		ERROR(rt2x00dev, "Invalid RF chipset 0x%04x detected.\n",
-		      rt2x00dev->chip.rf);
+		ERROR(rt2x00dev, "Invalid RF chipset 0x%04x detected.\n", rf);
 		return -ENODEV;
 	}
 
+	rt2x00_set_rf(rt2x00dev, rf);
+
 	/*
 	 * Identify default antenna configuration.
 	 */
@@ -5122,6 +5707,138 @@ static const struct rf_channel rf_vals_3x[] = {
 	{173, 0x61, 0, 9},
 };
 
+static const struct rf_channel rf_vals_5592_xtal20[] = {
+	/* Channel, N, K, mod, R */
+	{1, 482, 4, 10, 3},
+	{2, 483, 4, 10, 3},
+	{3, 484, 4, 10, 3},
+	{4, 485, 4, 10, 3},
+	{5, 486, 4, 10, 3},
+	{6, 487, 4, 10, 3},
+	{7, 488, 4, 10, 3},
+	{8, 489, 4, 10, 3},
+	{9, 490, 4, 10, 3},
+	{10, 491, 4, 10, 3},
+	{11, 492, 4, 10, 3},
+	{12, 493, 4, 10, 3},
+	{13, 494, 4, 10, 3},
+	{14, 496, 8, 10, 3},
+	{36, 172, 8, 12, 1},
+	{38, 173, 0, 12, 1},
+	{40, 173, 4, 12, 1},
+	{42, 173, 8, 12, 1},
+	{44, 174, 0, 12, 1},
+	{46, 174, 4, 12, 1},
+	{48, 174, 8, 12, 1},
+	{50, 175, 0, 12, 1},
+	{52, 175, 4, 12, 1},
+	{54, 175, 8, 12, 1},
+	{56, 176, 0, 12, 1},
+	{58, 176, 4, 12, 1},
+	{60, 176, 8, 12, 1},
+	{62, 177, 0, 12, 1},
+	{64, 177, 4, 12, 1},
+	{100, 183, 4, 12, 1},
+	{102, 183, 8, 12, 1},
+	{104, 184, 0, 12, 1},
+	{106, 184, 4, 12, 1},
+	{108, 184, 8, 12, 1},
+	{110, 185, 0, 12, 1},
+	{112, 185, 4, 12, 1},
+	{114, 185, 8, 12, 1},
+	{116, 186, 0, 12, 1},
+	{118, 186, 4, 12, 1},
+	{120, 186, 8, 12, 1},
+	{122, 187, 0, 12, 1},
+	{124, 187, 4, 12, 1},
+	{126, 187, 8, 12, 1},
+	{128, 188, 0, 12, 1},
+	{130, 188, 4, 12, 1},
+	{132, 188, 8, 12, 1},
+	{134, 189, 0, 12, 1},
+	{136, 189, 4, 12, 1},
+	{138, 189, 8, 12, 1},
+	{140, 190, 0, 12, 1},
+	{149, 191, 6, 12, 1},
+	{151, 191, 10, 12, 1},
+	{153, 192, 2, 12, 1},
+	{155, 192, 6, 12, 1},
+	{157, 192, 10, 12, 1},
+	{159, 193, 2, 12, 1},
+	{161, 193, 6, 12, 1},
+	{165, 194, 2, 12, 1},
+	{184, 164, 0, 12, 1},
+	{188, 164, 4, 12, 1},
+	{192, 165, 8, 12, 1},
+	{196, 166, 0, 12, 1},
+};
+
+static const struct rf_channel rf_vals_5592_xtal40[] = {
+	/* Channel, N, K, mod, R */
+	{1, 241, 2, 10, 3},
+	{2, 241, 7, 10, 3},
+	{3, 242, 2, 10, 3},
+	{4, 242, 7, 10, 3},
+	{5, 243, 2, 10, 3},
+	{6, 243, 7, 10, 3},
+	{7, 244, 2, 10, 3},
+	{8, 244, 7, 10, 3},
+	{9, 245, 2, 10, 3},
+	{10, 245, 7, 10, 3},
+	{11, 246, 2, 10, 3},
+	{12, 246, 7, 10, 3},
+	{13, 247, 2, 10, 3},
+	{14, 248, 4, 10, 3},
+	{36, 86, 4, 12, 1},
+	{38, 86, 6, 12, 1},
+	{40, 86, 8, 12, 1},
+	{42, 86, 10, 12, 1},
+	{44, 87, 0, 12, 1},
+	{46, 87, 2, 12, 1},
+	{48, 87, 4, 12, 1},
+	{50, 87, 6, 12, 1},
+	{52, 87, 8, 12, 1},
+	{54, 87, 10, 12, 1},
+	{56, 88, 0, 12, 1},
+	{58, 88, 2, 12, 1},
+	{60, 88, 4, 12, 1},
+	{62, 88, 6, 12, 1},
+	{64, 88, 8, 12, 1},
+	{100, 91, 8, 12, 1},
+	{102, 91, 10, 12, 1},
+	{104, 92, 0, 12, 1},
+	{106, 92, 2, 12, 1},
+	{108, 92, 4, 12, 1},
+	{110, 92, 6, 12, 1},
+	{112, 92, 8, 12, 1},
+	{114, 92, 10, 12, 1},
+	{116, 93, 0, 12, 1},
+	{118, 93, 2, 12, 1},
+	{120, 93, 4, 12, 1},
+	{122, 93, 6, 12, 1},
+	{124, 93, 8, 12, 1},
+	{126, 93, 10, 12, 1},
+	{128, 94, 0, 12, 1},
+	{130, 94, 2, 12, 1},
+	{132, 94, 4, 12, 1},
+	{134, 94, 6, 12, 1},
+	{136, 94, 8, 12, 1},
+	{138, 94, 10, 12, 1},
+	{140, 95, 0, 12, 1},
+	{149, 95, 9, 12, 1},
+	{151, 95, 11, 12, 1},
+	{153, 96, 1, 12, 1},
+	{155, 96, 3, 12, 1},
+	{157, 96, 5, 12, 1},
+	{159, 96, 7, 12, 1},
+	{161, 96, 9, 12, 1},
+	{165, 97, 1, 12, 1},
+	{184, 82, 0, 12, 1},
+	{188, 82, 4, 12, 1},
+	{192, 82, 8, 12, 1},
+	{196, 83, 0, 12, 1},
+};
+
 static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
 {
 	struct hw_mode_spec *spec = &rt2x00dev->spec;
@@ -5130,6 +5847,7 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
 	char *default_power2;
 	unsigned int i;
 	u16 eeprom;
+	u32 reg;
 
 	/*
 	 * Disable powersaving as default on PCI devices.
@@ -5211,8 +5929,22 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
 		spec->supported_bands |= SUPPORT_BAND_5GHZ;
 		spec->num_channels = ARRAY_SIZE(rf_vals_3x);
 		spec->channels = rf_vals_3x;
+	} else if (rt2x00_rf(rt2x00dev, RF5592)) {
+		spec->supported_bands |= SUPPORT_BAND_5GHZ;
+
+		rt2800_register_read(rt2x00dev, MAC_DEBUG_INDEX, &reg);
+		if (rt2x00_get_field32(reg, MAC_DEBUG_INDEX_XTAL)) {
+			spec->num_channels = ARRAY_SIZE(rf_vals_5592_xtal40);
+			spec->channels = rf_vals_5592_xtal40;
+		} else {
+			spec->num_channels = ARRAY_SIZE(rf_vals_5592_xtal20);
+			spec->channels = rf_vals_5592_xtal20;
+		}
 	}
 
+	if (WARN_ON_ONCE(!spec->channels))
+		return -ENODEV;
+
 	/*
 	 * Initialize HT information.
 	 */
@@ -5300,11 +6032,56 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
 	return 0;
 }
 
+static int rt2800_probe_rt(struct rt2x00_dev *rt2x00dev)
+{
+	u32 reg;
+	u32 rt;
+	u32 rev;
+
+	if (rt2x00_rt(rt2x00dev, RT3290))
+		rt2800_register_read(rt2x00dev, MAC_CSR0_3290, &reg);
+	else
+		rt2800_register_read(rt2x00dev, MAC_CSR0, &reg);
+
+	rt = rt2x00_get_field32(reg, MAC_CSR0_CHIPSET);
+	rev = rt2x00_get_field32(reg, MAC_CSR0_REVISION);
+
+	switch (rt) {
+	case RT2860:
+	case RT2872:
+	case RT2883:
+	case RT3070:
+	case RT3071:
+	case RT3090:
+	case RT3290:
+	case RT3352:
+	case RT3390:
+	case RT3572:
+	case RT5390:
+	case RT5392:
+	case RT5592:
+		break;
+	default:
+		ERROR(rt2x00dev,
+		      "Invalid RT chipset 0x%04x, rev %04x detected.\n",
+		      rt, rev);
+		return -ENODEV;
+	}
+
+	rt2x00_set_rt(rt2x00dev, rt, rev);
+
+	return 0;
+}
+
 int rt2800_probe_hw(struct rt2x00_dev *rt2x00dev)
 {
 	int retval;
 	u32 reg;
 
+	retval = rt2800_probe_rt(rt2x00dev);
+	if (retval)
+		return retval;
+
 	/*
 	 * Allocate eeprom data.
 	 */
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index ded73da..565a80d 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -41,6 +41,7 @@
 #include <linux/eeprom_93cx6.h>
 
 #include "rt2x00.h"
+#include "rt2x00mmio.h"
 #include "rt2x00pci.h"
 #include "rt2x00soc.h"
 #include "rt2800lib.h"
@@ -729,6 +730,11 @@ static void rt2800pci_fill_rxdone(struct queue_entry *entry,
 	 * Process the RXWI structure that is at the start of the buffer.
 	 */
 	rt2800_process_rxwi(entry, rxdesc);
+
+	/*
+	 * Remove RXWI descriptor from start of buffer.
+	 */
+	skb_pull(entry->skb, RXWI_DESC_SIZE);
 }
 
 /*
@@ -742,10 +748,90 @@ static void rt2800pci_wakeup(struct rt2x00_dev *rt2x00dev)
 	rt2800_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS);
 }
 
+static bool rt2800pci_txdone_entry_check(struct queue_entry *entry, u32 status)
+{
+	__le32 *txwi;
+	u32 word;
+	int wcid, tx_wcid;
+
+	wcid = rt2x00_get_field32(status, TX_STA_FIFO_WCID);
+
+	txwi = rt2800_drv_get_txwi(entry);
+	rt2x00_desc_read(txwi, 1, &word);
+	tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID);
+
+	return (tx_wcid == wcid);
+}
+
+static bool rt2800pci_txdone_find_entry(struct queue_entry *entry, void *data)
+{
+	u32 status = *(u32 *)data;
+
+	/*
+	 * rt2800pci hardware might reorder frames when exchanging traffic
+	 * with multiple BA enabled STAs.
+	 *
+	 * For example, a tx queue
+	 *    [ STA1 | STA2 | STA1 | STA2 ]
+	 * can result in tx status reports
+	 *    [ STA1 | STA1 | STA2 | STA2 ]
+	 * when the hw decides to aggregate the frames for STA1 into one AMPDU.
+	 *
+	 * To mitigate this effect, associate the tx status to the first frame
+	 * in the tx queue with a matching wcid.
+	 */
+	if (rt2800pci_txdone_entry_check(entry, status) &&
+	    !test_bit(ENTRY_DATA_STATUS_SET, &entry->flags)) {
+		/*
+		 * Got a matching frame, associate the tx status with
+		 * the frame
+		 */
+		entry->status = status;
+		set_bit(ENTRY_DATA_STATUS_SET, &entry->flags);
+		return true;
+	}
+
+	/* Check the next frame */
+	return false;
+}
+
+static bool rt2800pci_txdone_match_first(struct queue_entry *entry, void *data)
+{
+	u32 status = *(u32 *)data;
+
+	/*
+	 * Find the first frame without tx status and assign this status to it
+	 * regardless if it matches or not.
+	 */
+	if (!test_bit(ENTRY_DATA_STATUS_SET, &entry->flags)) {
+		/*
+		 * Got a matching frame, associate the tx status with
+		 * the frame
+		 */
+		entry->status = status;
+		set_bit(ENTRY_DATA_STATUS_SET, &entry->flags);
+		return true;
+	}
+
+	/* Check the next frame */
+	return false;
+}
+static bool rt2800pci_txdone_release_entries(struct queue_entry *entry,
+					     void *data)
+{
+	if (test_bit(ENTRY_DATA_STATUS_SET, &entry->flags)) {
+		rt2800_txdone_entry(entry, entry->status,
+				    rt2800pci_get_txwi(entry));
+		return false;
+	}
+
+	/* No more frames to release */
+	return true;
+}
+
 static bool rt2800pci_txdone(struct rt2x00_dev *rt2x00dev)
 {
 	struct data_queue *queue;
-	struct queue_entry *entry;
 	u32 status;
 	u8 qid;
 	int max_tx_done = 16;
@@ -783,8 +869,33 @@ static bool rt2800pci_txdone(struct rt2x00_dev *rt2x00dev)
 			break;
 		}
 
-		entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
-		rt2800_txdone_entry(entry, status, rt2800pci_get_txwi(entry));
+		/*
+		 * Let's associate this tx status with the first
+		 * matching frame.
+		 */
+		if (!rt2x00queue_for_each_entry(queue, Q_INDEX_DONE,
+						Q_INDEX, &status,
+						rt2800pci_txdone_find_entry)) {
+			/*
+			 * We cannot match the tx status to any frame, so just
+			 * use the first one.
+			 */
+			if (!rt2x00queue_for_each_entry(queue, Q_INDEX_DONE,
+							Q_INDEX, &status,
+							rt2800pci_txdone_match_first)) {
+				WARNING(rt2x00dev, "No frame found for TX "
+						   "status on queue %u, dropping\n",
+						   qid);
+				break;
+			}
+		}
+
+		/*
+		 * Release all frames with a valid tx status.
+		 */
+		rt2x00queue_for_each_entry(queue, Q_INDEX_DONE,
+					   Q_INDEX, NULL,
+					   rt2800pci_txdone_release_entries);
 
 		if (--max_tx_done == 0)
 			break;
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 098613e..f322820 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -485,7 +485,7 @@ static void rt2800usb_write_tx_desc(struct queue_entry *entry,
 	 */
 	skbdesc->flags |= SKBDESC_DESC_IN_SKB;
 	skbdesc->desc = txi;
-	skbdesc->desc_len = TXINFO_DESC_SIZE + TXWI_DESC_SIZE;
+	skbdesc->desc_len = entry->queue->desc_size;
 }
 
 /*
@@ -730,6 +730,11 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry,
 	 * Process the RXWI structure.
 	 */
 	rt2800_process_rxwi(entry, rxdesc);
+
+	/*
+	 * Remove RXWI descriptor from start of buffer.
+	 */
+	skb_pull(entry->skb, entry->queue->desc_size - RXINFO_DESC_SIZE);
 }
 
 /*
@@ -890,6 +895,47 @@ static const struct rt2x00_ops rt2800usb_ops = {
 #endif /* CONFIG_RT2X00_LIB_DEBUGFS */
 };
 
+static const struct data_queue_desc rt2800usb_queue_rx_5592 = {
+	.entry_num		= 128,
+	.data_size		= AGGREGATION_SIZE,
+	.desc_size		= RXINFO_DESC_SIZE + RXWI_DESC_SIZE_5592,
+	.priv_size		= sizeof(struct queue_entry_priv_usb),
+};
+
+static const struct data_queue_desc rt2800usb_queue_tx_5592 = {
+	.entry_num		= 16,
+	.data_size		= AGGREGATION_SIZE,
+	.desc_size		= TXINFO_DESC_SIZE + TXWI_DESC_SIZE_5592,
+	.priv_size		= sizeof(struct queue_entry_priv_usb),
+};
+
+static const struct data_queue_desc rt2800usb_queue_bcn_5592 = {
+	.entry_num		= 8,
+	.data_size		= MGMT_FRAME_SIZE,
+	.desc_size		= TXINFO_DESC_SIZE + TXWI_DESC_SIZE_5592,
+	.priv_size		= sizeof(struct queue_entry_priv_usb),
+};
+
+
+static const struct rt2x00_ops rt2800usb_ops_5592 = {
+	.name			= KBUILD_MODNAME,
+	.drv_data_size		= sizeof(struct rt2800_drv_data),
+	.max_ap_intf		= 8,
+	.eeprom_size		= EEPROM_SIZE,
+	.rf_size		= RF_SIZE,
+	.tx_queues		= NUM_TX_QUEUES,
+	.extra_tx_headroom	= TXINFO_DESC_SIZE + TXWI_DESC_SIZE_5592,
+	.rx			= &rt2800usb_queue_rx_5592,
+	.tx			= &rt2800usb_queue_tx_5592,
+	.bcn			= &rt2800usb_queue_bcn_5592,
+	.lib			= &rt2800usb_rt2x00_ops,
+	.drv			= &rt2800usb_rt2800_ops,
+	.hw			= &rt2800usb_mac80211_ops,
+#ifdef CONFIG_RT2X00_LIB_DEBUGFS
+	.debugfs		= &rt2800_rt2x00debug,
+#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
+};
+
 /*
  * rt2800usb module information.
  */
@@ -1200,6 +1246,18 @@ static struct usb_device_id rt2800usb_device_table[] = {
 	{ USB_DEVICE(0x148f, 0x5370) },
 	{ USB_DEVICE(0x148f, 0x5372) },
 #endif
+#ifdef CONFIG_RT2800USB_RT55XX
+	/* Arcadyan */
+	{ USB_DEVICE(0x043e, 0x7a32), .driver_info = 5592 },
+	/* AVM GmbH */
+	{ USB_DEVICE(0x057c, 0x8501), .driver_info = 5592 },
+	/* D-Link DWA-160-B2 */
+	{ USB_DEVICE(0x2001, 0x3c1a), .driver_info = 5592 },
+	/* Proware */
+	{ USB_DEVICE(0x043e, 0x7a13), .driver_info = 5592 },
+	/* Ralink */
+	{ USB_DEVICE(0x148f, 0x5572), .driver_info = 5592 },
+#endif
 #ifdef CONFIG_RT2800USB_UNKNOWN
 	/*
 	 * Unclear what kind of devices these are (they aren't supported by the
@@ -1303,6 +1361,9 @@ MODULE_LICENSE("GPL");
 static int rt2800usb_probe(struct usb_interface *usb_intf,
 			   const struct usb_device_id *id)
 {
+	if (id->driver_info == 5592)
+		return rt2x00usb_probe(usb_intf, &rt2800usb_ops_5592);
+
 	return rt2x00usb_probe(usb_intf, &rt2800usb_ops);
 }
 
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index 086abb4..0d02d16 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -193,6 +193,7 @@ struct rt2x00_chip {
 #define RT3883		0x3883	/* WSOC */
 #define RT5390		0x5390  /* 2.4GHz */
 #define RT5392		0x5392  /* 2.4GHz */
+#define RT5592		0x5592
 
 	u16 rf;
 	u16 rev;
@@ -1064,8 +1065,7 @@ static inline void rt2x00_rf_write(struct rt2x00_dev *rt2x00dev,
 }
 
 /*
- *  Generic EEPROM access.
- * The EEPROM is being accessed by word index.
+ * Generic EEPROM access. The EEPROM is being accessed by word or byte index.
  */
 static inline void *rt2x00_eeprom_addr(struct rt2x00_dev *rt2x00dev,
 				       const unsigned int word)
@@ -1085,6 +1085,12 @@ static inline void rt2x00_eeprom_write(struct rt2x00_dev *rt2x00dev,
 	rt2x00dev->eeprom[word] = cpu_to_le16(data);
 }
 
+static inline u8 rt2x00_eeprom_byte(struct rt2x00_dev *rt2x00dev,
+				    const unsigned int byte)
+{
+	return *(((u8 *)rt2x00dev->eeprom) + byte);
+}
+
 /*
  * Chipset handlers
  */
@@ -1100,6 +1106,23 @@ static inline void rt2x00_set_chip(struct rt2x00_dev *rt2x00dev,
 	     rt2x00dev->chip.rt, rt2x00dev->chip.rf, rt2x00dev->chip.rev);
 }
 
+static inline void rt2x00_set_rt(struct rt2x00_dev *rt2x00dev,
+				 const u16 rt, const u16 rev)
+{
+	rt2x00dev->chip.rt = rt;
+	rt2x00dev->chip.rev = rev;
+
+	INFO(rt2x00dev, "RT chipset %04x, rev %04x detected\n",
+	     rt2x00dev->chip.rt, rt2x00dev->chip.rev);
+}
+
+static inline void rt2x00_set_rf(struct rt2x00_dev *rt2x00dev, const u16 rf)
+{
+	rt2x00dev->chip.rf = rf;
+
+	INFO(rt2x00dev, "RF chipset %04x detected\n", rt2x00dev->chip.rf);
+}
+
 static inline bool rt2x00_rt(struct rt2x00_dev *rt2x00dev, const u16 rt)
 {
 	return (rt2x00dev->chip.rt == rt);
@@ -1360,7 +1383,7 @@ int rt2x00mac_conf_tx(struct ieee80211_hw *hw,
 		      struct ieee80211_vif *vif, u16 queue,
 		      const struct ieee80211_tx_queue_params *params);
 void rt2x00mac_rfkill_poll(struct ieee80211_hw *hw);
-void rt2x00mac_flush(struct ieee80211_hw *hw, bool drop);
+void rt2x00mac_flush(struct ieee80211_hw *hw, u32 queues, bool drop);
 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,
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index 20c6ecc..9161c02 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -748,7 +748,7 @@ void rt2x00mac_rfkill_poll(struct ieee80211_hw *hw)
 }
 EXPORT_SYMBOL_GPL(rt2x00mac_rfkill_poll);
 
-void rt2x00mac_flush(struct ieee80211_hw *hw, bool drop)
+void rt2x00mac_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
 {
 	struct rt2x00_dev *rt2x00dev = hw->priv;
 	struct data_queue *queue;
diff --git a/drivers/net/wireless/rt2x00/rt2x00mmio.c b/drivers/net/wireless/rt2x00/rt2x00mmio.c
new file mode 100644
index 0000000..9fe9a36
--- /dev/null
+++ b/drivers/net/wireless/rt2x00/rt2x00mmio.c
@@ -0,0 +1,214 @@
+/*
+	Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
+	<http://rt2x00.serialmonkey.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.
+ */
+
+/*
+	Module: rt2x00mmio
+	Abstract: rt2x00 generic mmio device routines.
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include "rt2x00.h"
+#include "rt2x00mmio.h"
+
+/*
+ * Register access.
+ */
+int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev,
+			   const unsigned int offset,
+			   const struct rt2x00_field32 field,
+			   u32 *reg)
+{
+	unsigned int i;
+
+	if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
+		return 0;
+
+	for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
+		rt2x00pci_register_read(rt2x00dev, offset, reg);
+		if (!rt2x00_get_field32(*reg, field))
+			return 1;
+		udelay(REGISTER_BUSY_DELAY);
+	}
+
+	printk_once(KERN_ERR "%s() Indirect register access failed: "
+	      "offset=0x%.08x, value=0x%.08x\n", __func__, offset, *reg);
+	*reg = ~0;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(rt2x00pci_regbusy_read);
+
+bool rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
+{
+	struct data_queue *queue = rt2x00dev->rx;
+	struct queue_entry *entry;
+	struct queue_entry_priv_pci *entry_priv;
+	struct skb_frame_desc *skbdesc;
+	int max_rx = 16;
+
+	while (--max_rx) {
+		entry = rt2x00queue_get_entry(queue, Q_INDEX);
+		entry_priv = entry->priv_data;
+
+		if (rt2x00dev->ops->lib->get_entry_state(entry))
+			break;
+
+		/*
+		 * Fill in desc fields of the skb descriptor
+		 */
+		skbdesc = get_skb_frame_desc(entry->skb);
+		skbdesc->desc = entry_priv->desc;
+		skbdesc->desc_len = entry->queue->desc_size;
+
+		/*
+		 * DMA is already done, notify rt2x00lib that
+		 * it finished successfully.
+		 */
+		rt2x00lib_dmastart(entry);
+		rt2x00lib_dmadone(entry);
+
+		/*
+		 * Send the frame to rt2x00lib for further processing.
+		 */
+		rt2x00lib_rxdone(entry, GFP_ATOMIC);
+	}
+
+	return !max_rx;
+}
+EXPORT_SYMBOL_GPL(rt2x00pci_rxdone);
+
+void rt2x00pci_flush_queue(struct data_queue *queue, bool drop)
+{
+	unsigned int i;
+
+	for (i = 0; !rt2x00queue_empty(queue) && i < 10; i++)
+		msleep(10);
+}
+EXPORT_SYMBOL_GPL(rt2x00pci_flush_queue);
+
+/*
+ * Device initialization handlers.
+ */
+static int rt2x00pci_alloc_queue_dma(struct rt2x00_dev *rt2x00dev,
+				     struct data_queue *queue)
+{
+	struct queue_entry_priv_pci *entry_priv;
+	void *addr;
+	dma_addr_t dma;
+	unsigned int i;
+
+	/*
+	 * Allocate DMA memory for descriptor and buffer.
+	 */
+	addr = dma_alloc_coherent(rt2x00dev->dev,
+				  queue->limit * queue->desc_size,
+				  &dma, GFP_KERNEL | __GFP_ZERO);
+	if (!addr)
+		return -ENOMEM;
+
+	/*
+	 * Initialize all queue entries to contain valid addresses.
+	 */
+	for (i = 0; i < queue->limit; i++) {
+		entry_priv = queue->entries[i].priv_data;
+		entry_priv->desc = addr + i * queue->desc_size;
+		entry_priv->desc_dma = dma + i * queue->desc_size;
+	}
+
+	return 0;
+}
+
+static void rt2x00pci_free_queue_dma(struct rt2x00_dev *rt2x00dev,
+				     struct data_queue *queue)
+{
+	struct queue_entry_priv_pci *entry_priv =
+	    queue->entries[0].priv_data;
+
+	if (entry_priv->desc)
+		dma_free_coherent(rt2x00dev->dev,
+				  queue->limit * queue->desc_size,
+				  entry_priv->desc, entry_priv->desc_dma);
+	entry_priv->desc = NULL;
+}
+
+int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev)
+{
+	struct data_queue *queue;
+	int status;
+
+	/*
+	 * Allocate DMA
+	 */
+	queue_for_each(rt2x00dev, queue) {
+		status = rt2x00pci_alloc_queue_dma(rt2x00dev, queue);
+		if (status)
+			goto exit;
+	}
+
+	/*
+	 * Register interrupt handler.
+	 */
+	status = request_irq(rt2x00dev->irq,
+			     rt2x00dev->ops->lib->irq_handler,
+			     IRQF_SHARED, rt2x00dev->name, rt2x00dev);
+	if (status) {
+		ERROR(rt2x00dev, "IRQ %d allocation failed (error %d).\n",
+		      rt2x00dev->irq, status);
+		goto exit;
+	}
+
+	return 0;
+
+exit:
+	queue_for_each(rt2x00dev, queue)
+		rt2x00pci_free_queue_dma(rt2x00dev, queue);
+
+	return status;
+}
+EXPORT_SYMBOL_GPL(rt2x00pci_initialize);
+
+void rt2x00pci_uninitialize(struct rt2x00_dev *rt2x00dev)
+{
+	struct data_queue *queue;
+
+	/*
+	 * Free irq line.
+	 */
+	free_irq(rt2x00dev->irq, rt2x00dev);
+
+	/*
+	 * Free DMA
+	 */
+	queue_for_each(rt2x00dev, queue)
+		rt2x00pci_free_queue_dma(rt2x00dev, queue);
+}
+EXPORT_SYMBOL_GPL(rt2x00pci_uninitialize);
+
+/*
+ * rt2x00mmio module information.
+ */
+MODULE_AUTHOR(DRV_PROJECT);
+MODULE_VERSION(DRV_VERSION);
+MODULE_DESCRIPTION("rt2x00 mmio library");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/wireless/rt2x00/rt2x00mmio.h b/drivers/net/wireless/rt2x00/rt2x00mmio.h
new file mode 100644
index 0000000..4ecaf60
--- /dev/null
+++ b/drivers/net/wireless/rt2x00/rt2x00mmio.h
@@ -0,0 +1,119 @@
+/*
+	Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
+	<http://rt2x00.serialmonkey.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.
+ */
+
+/*
+	Module: rt2x00mmio
+	Abstract: Data structures for the rt2x00mmio module.
+ */
+
+#ifndef RT2X00MMIO_H
+#define RT2X00MMIO_H
+
+#include <linux/io.h>
+
+/*
+ * Register access.
+ */
+static inline void rt2x00pci_register_read(struct rt2x00_dev *rt2x00dev,
+					   const unsigned int offset,
+					   u32 *value)
+{
+	*value = readl(rt2x00dev->csr.base + offset);
+}
+
+static inline void rt2x00pci_register_multiread(struct rt2x00_dev *rt2x00dev,
+						const unsigned int offset,
+						void *value, const u32 length)
+{
+	memcpy_fromio(value, rt2x00dev->csr.base + offset, length);
+}
+
+static inline void rt2x00pci_register_write(struct rt2x00_dev *rt2x00dev,
+					    const unsigned int offset,
+					    u32 value)
+{
+	writel(value, rt2x00dev->csr.base + offset);
+}
+
+static inline void rt2x00pci_register_multiwrite(struct rt2x00_dev *rt2x00dev,
+						 const unsigned int offset,
+						 const void *value,
+						 const u32 length)
+{
+	__iowrite32_copy(rt2x00dev->csr.base + offset, value, length >> 2);
+}
+
+/**
+ * rt2x00pci_regbusy_read - Read from register with busy check
+ * @rt2x00dev: Device pointer, see &struct rt2x00_dev.
+ * @offset: Register offset
+ * @field: Field to check if register is busy
+ * @reg: Pointer to where register contents should be stored
+ *
+ * This function will read the given register, and checks if the
+ * register is busy. If it is, it will sleep for a couple of
+ * microseconds before reading the register again. If the register
+ * is not read after a certain timeout, this function will return
+ * FALSE.
+ */
+int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev,
+			   const unsigned int offset,
+			   const struct rt2x00_field32 field,
+			   u32 *reg);
+
+/**
+ * struct queue_entry_priv_pci: Per entry PCI specific information
+ *
+ * @desc: Pointer to device descriptor
+ * @desc_dma: DMA pointer to &desc.
+ * @data: Pointer to device's entry memory.
+ * @data_dma: DMA pointer to &data.
+ */
+struct queue_entry_priv_pci {
+	__le32 *desc;
+	dma_addr_t desc_dma;
+};
+
+/**
+ * rt2x00pci_rxdone - Handle RX done events
+ * @rt2x00dev: Device pointer, see &struct rt2x00_dev.
+ *
+ * Returns true if there are still rx frames pending and false if all
+ * pending rx frames were processed.
+ */
+bool rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev);
+
+/**
+ * rt2x00pci_flush_queue - Flush data queue
+ * @queue: Data queue to stop
+ * @drop: True to drop all pending frames.
+ *
+ * This will wait for a maximum of 100ms, waiting for the queues
+ * to become empty.
+ */
+void rt2x00pci_flush_queue(struct data_queue *queue, bool drop);
+
+/*
+ * Device initialization handlers.
+ */
+int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev);
+void rt2x00pci_uninitialize(struct rt2x00_dev *rt2x00dev);
+
+#endif /* RT2X00MMIO_H */
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c
index a0c8cae..e87865e 100644
--- a/drivers/net/wireless/rt2x00/rt2x00pci.c
+++ b/drivers/net/wireless/rt2x00/rt2x00pci.c
@@ -33,182 +33,6 @@
 #include "rt2x00pci.h"
 
 /*
- * Register access.
- */
-int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev,
-			   const unsigned int offset,
-			   const struct rt2x00_field32 field,
-			   u32 *reg)
-{
-	unsigned int i;
-
-	if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
-		return 0;
-
-	for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
-		rt2x00pci_register_read(rt2x00dev, offset, reg);
-		if (!rt2x00_get_field32(*reg, field))
-			return 1;
-		udelay(REGISTER_BUSY_DELAY);
-	}
-
-	ERROR(rt2x00dev, "Indirect register access failed: "
-	      "offset=0x%.08x, value=0x%.08x\n", offset, *reg);
-	*reg = ~0;
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(rt2x00pci_regbusy_read);
-
-bool rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
-{
-	struct data_queue *queue = rt2x00dev->rx;
-	struct queue_entry *entry;
-	struct queue_entry_priv_pci *entry_priv;
-	struct skb_frame_desc *skbdesc;
-	int max_rx = 16;
-
-	while (--max_rx) {
-		entry = rt2x00queue_get_entry(queue, Q_INDEX);
-		entry_priv = entry->priv_data;
-
-		if (rt2x00dev->ops->lib->get_entry_state(entry))
-			break;
-
-		/*
-		 * Fill in desc fields of the skb descriptor
-		 */
-		skbdesc = get_skb_frame_desc(entry->skb);
-		skbdesc->desc = entry_priv->desc;
-		skbdesc->desc_len = entry->queue->desc_size;
-
-		/*
-		 * DMA is already done, notify rt2x00lib that
-		 * it finished successfully.
-		 */
-		rt2x00lib_dmastart(entry);
-		rt2x00lib_dmadone(entry);
-
-		/*
-		 * Send the frame to rt2x00lib for further processing.
-		 */
-		rt2x00lib_rxdone(entry, GFP_ATOMIC);
-	}
-
-	return !max_rx;
-}
-EXPORT_SYMBOL_GPL(rt2x00pci_rxdone);
-
-void rt2x00pci_flush_queue(struct data_queue *queue, bool drop)
-{
-	unsigned int i;
-
-	for (i = 0; !rt2x00queue_empty(queue) && i < 10; i++)
-		msleep(10);
-}
-EXPORT_SYMBOL_GPL(rt2x00pci_flush_queue);
-
-/*
- * Device initialization handlers.
- */
-static int rt2x00pci_alloc_queue_dma(struct rt2x00_dev *rt2x00dev,
-				     struct data_queue *queue)
-{
-	struct queue_entry_priv_pci *entry_priv;
-	void *addr;
-	dma_addr_t dma;
-	unsigned int i;
-
-	/*
-	 * Allocate DMA memory for descriptor and buffer.
-	 */
-	addr = dma_alloc_coherent(rt2x00dev->dev,
-				  queue->limit * queue->desc_size,
-				  &dma, GFP_KERNEL);
-	if (!addr)
-		return -ENOMEM;
-
-	memset(addr, 0, queue->limit * queue->desc_size);
-
-	/*
-	 * Initialize all queue entries to contain valid addresses.
-	 */
-	for (i = 0; i < queue->limit; i++) {
-		entry_priv = queue->entries[i].priv_data;
-		entry_priv->desc = addr + i * queue->desc_size;
-		entry_priv->desc_dma = dma + i * queue->desc_size;
-	}
-
-	return 0;
-}
-
-static void rt2x00pci_free_queue_dma(struct rt2x00_dev *rt2x00dev,
-				     struct data_queue *queue)
-{
-	struct queue_entry_priv_pci *entry_priv =
-	    queue->entries[0].priv_data;
-
-	if (entry_priv->desc)
-		dma_free_coherent(rt2x00dev->dev,
-				  queue->limit * queue->desc_size,
-				  entry_priv->desc, entry_priv->desc_dma);
-	entry_priv->desc = NULL;
-}
-
-int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev)
-{
-	struct data_queue *queue;
-	int status;
-
-	/*
-	 * Allocate DMA
-	 */
-	queue_for_each(rt2x00dev, queue) {
-		status = rt2x00pci_alloc_queue_dma(rt2x00dev, queue);
-		if (status)
-			goto exit;
-	}
-
-	/*
-	 * Register interrupt handler.
-	 */
-	status = request_irq(rt2x00dev->irq,
-			     rt2x00dev->ops->lib->irq_handler,
-			     IRQF_SHARED, rt2x00dev->name, rt2x00dev);
-	if (status) {
-		ERROR(rt2x00dev, "IRQ %d allocation failed (error %d).\n",
-		      rt2x00dev->irq, status);
-		goto exit;
-	}
-
-	return 0;
-
-exit:
-	queue_for_each(rt2x00dev, queue)
-		rt2x00pci_free_queue_dma(rt2x00dev, queue);
-
-	return status;
-}
-EXPORT_SYMBOL_GPL(rt2x00pci_initialize);
-
-void rt2x00pci_uninitialize(struct rt2x00_dev *rt2x00dev)
-{
-	struct data_queue *queue;
-
-	/*
-	 * Free irq line.
-	 */
-	free_irq(rt2x00dev->irq, rt2x00dev);
-
-	/*
-	 * Free DMA
-	 */
-	queue_for_each(rt2x00dev, queue)
-		rt2x00pci_free_queue_dma(rt2x00dev, queue);
-}
-EXPORT_SYMBOL_GPL(rt2x00pci_uninitialize);
-
-/*
  * PCI driver handlers.
  */
 static void rt2x00pci_free_reg(struct rt2x00_dev *rt2x00dev)
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.h b/drivers/net/wireless/rt2x00/rt2x00pci.h
index e2c99f2..60d90b2 100644
--- a/drivers/net/wireless/rt2x00/rt2x00pci.h
+++ b/drivers/net/wireless/rt2x00/rt2x00pci.h
@@ -36,94 +36,6 @@
 #define PCI_DEVICE_DATA(__ops)	.driver_data = (kernel_ulong_t)(__ops)
 
 /*
- * Register access.
- */
-static inline void rt2x00pci_register_read(struct rt2x00_dev *rt2x00dev,
-					   const unsigned int offset,
-					   u32 *value)
-{
-	*value = readl(rt2x00dev->csr.base + offset);
-}
-
-static inline void rt2x00pci_register_multiread(struct rt2x00_dev *rt2x00dev,
-						const unsigned int offset,
-						void *value, const u32 length)
-{
-	memcpy_fromio(value, rt2x00dev->csr.base + offset, length);
-}
-
-static inline void rt2x00pci_register_write(struct rt2x00_dev *rt2x00dev,
-					    const unsigned int offset,
-					    u32 value)
-{
-	writel(value, rt2x00dev->csr.base + offset);
-}
-
-static inline void rt2x00pci_register_multiwrite(struct rt2x00_dev *rt2x00dev,
-						 const unsigned int offset,
-						 const void *value,
-						 const u32 length)
-{
-	__iowrite32_copy(rt2x00dev->csr.base + offset, value, length >> 2);
-}
-
-/**
- * rt2x00pci_regbusy_read - Read from register with busy check
- * @rt2x00dev: Device pointer, see &struct rt2x00_dev.
- * @offset: Register offset
- * @field: Field to check if register is busy
- * @reg: Pointer to where register contents should be stored
- *
- * This function will read the given register, and checks if the
- * register is busy. If it is, it will sleep for a couple of
- * microseconds before reading the register again. If the register
- * is not read after a certain timeout, this function will return
- * FALSE.
- */
-int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev,
-			   const unsigned int offset,
-			   const struct rt2x00_field32 field,
-			   u32 *reg);
-
-/**
- * struct queue_entry_priv_pci: Per entry PCI specific information
- *
- * @desc: Pointer to device descriptor
- * @desc_dma: DMA pointer to &desc.
- * @data: Pointer to device's entry memory.
- * @data_dma: DMA pointer to &data.
- */
-struct queue_entry_priv_pci {
-	__le32 *desc;
-	dma_addr_t desc_dma;
-};
-
-/**
- * rt2x00pci_rxdone - Handle RX done events
- * @rt2x00dev: Device pointer, see &struct rt2x00_dev.
- *
- * Returns true if there are still rx frames pending and false if all
- * pending rx frames were processed.
- */
-bool rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev);
-
-/**
- * rt2x00pci_flush_queue - Flush data queue
- * @queue: Data queue to stop
- * @drop: True to drop all pending frames.
- *
- * This will wait for a maximum of 100ms, waiting for the queues
- * to become empty.
- */
-void rt2x00pci_flush_queue(struct data_queue *queue, bool drop);
-
-/*
- * Device initialization handlers.
- */
-int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev);
-void rt2x00pci_uninitialize(struct rt2x00_dev *rt2x00dev);
-
-/*
  * PCI driver handlers.
  */
 int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops);
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index 4d91795..952a049 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -832,7 +832,9 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
 bool rt2x00queue_for_each_entry(struct data_queue *queue,
 				enum queue_index start,
 				enum queue_index end,
-				bool (*fn)(struct queue_entry *entry))
+				void *data,
+				bool (*fn)(struct queue_entry *entry,
+					   void *data))
 {
 	unsigned long irqflags;
 	unsigned int index_start;
@@ -863,17 +865,17 @@ bool rt2x00queue_for_each_entry(struct data_queue *queue,
 	 */
 	if (index_start < index_end) {
 		for (i = index_start; i < index_end; i++) {
-			if (fn(&queue->entries[i]))
+			if (fn(&queue->entries[i], data))
 				return true;
 		}
 	} else {
 		for (i = index_start; i < queue->limit; i++) {
-			if (fn(&queue->entries[i]))
+			if (fn(&queue->entries[i], data))
 				return true;
 		}
 
 		for (i = 0; i < index_end; i++) {
-			if (fn(&queue->entries[i]))
+			if (fn(&queue->entries[i], data))
 				return true;
 		}
 	}
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h
index 9b8c10a..3d01371 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.h
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.h
@@ -359,6 +359,7 @@ enum queue_entry_flags {
 	ENTRY_DATA_PENDING,
 	ENTRY_DATA_IO_FAILED,
 	ENTRY_DATA_STATUS_PENDING,
+	ENTRY_DATA_STATUS_SET,
 };
 
 /**
@@ -372,6 +373,7 @@ enum queue_entry_flags {
  * @entry_idx: The entry index number.
  * @priv_data: Private data belonging to this queue entry. The pointer
  *	points to data specific to a particular driver and queue type.
+ * @status: Device specific status
  */
 struct queue_entry {
 	unsigned long flags;
@@ -383,6 +385,8 @@ struct queue_entry {
 
 	unsigned int entry_idx;
 
+	u32 status;
+
 	void *priv_data;
 };
 
@@ -584,6 +588,7 @@ struct data_queue_desc {
  * @queue: Pointer to @data_queue
  * @start: &enum queue_index Pointer to start index
  * @end: &enum queue_index Pointer to end index
+ * @data: Data to pass to the callback function
  * @fn: The function to call for each &struct queue_entry
  *
  * This will walk through all entries in the queue, in chronological
@@ -596,7 +601,9 @@ struct data_queue_desc {
 bool rt2x00queue_for_each_entry(struct data_queue *queue,
 				enum queue_index start,
 				enum queue_index end,
-				bool (*fn)(struct queue_entry *entry));
+				void *data,
+				bool (*fn)(struct queue_entry *entry,
+					   void *data));
 
 /**
  * rt2x00queue_empty - Check if the queue is empty.
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index 40ea807..5e50d4f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -285,7 +285,7 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb)
 		queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
 }
 
-static bool rt2x00usb_kick_tx_entry(struct queue_entry *entry)
+static bool rt2x00usb_kick_tx_entry(struct queue_entry *entry, void *data)
 {
 	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
 	struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev);
@@ -390,7 +390,7 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb)
 	queue_work(rt2x00dev->workqueue, &rt2x00dev->rxdone_work);
 }
 
-static bool rt2x00usb_kick_rx_entry(struct queue_entry *entry)
+static bool rt2x00usb_kick_rx_entry(struct queue_entry *entry, void *data)
 {
 	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
 	struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev);
@@ -427,12 +427,18 @@ void rt2x00usb_kick_queue(struct data_queue *queue)
 	case QID_AC_BE:
 	case QID_AC_BK:
 		if (!rt2x00queue_empty(queue))
-			rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX,
+			rt2x00queue_for_each_entry(queue,
+						   Q_INDEX_DONE,
+						   Q_INDEX,
+						   NULL,
 						   rt2x00usb_kick_tx_entry);
 		break;
 	case QID_RX:
 		if (!rt2x00queue_full(queue))
-			rt2x00queue_for_each_entry(queue, Q_INDEX, Q_INDEX_DONE,
+			rt2x00queue_for_each_entry(queue,
+						   Q_INDEX,
+						   Q_INDEX_DONE,
+						   NULL,
 						   rt2x00usb_kick_rx_entry);
 		break;
 	default:
@@ -441,7 +447,7 @@ void rt2x00usb_kick_queue(struct data_queue *queue)
 }
 EXPORT_SYMBOL_GPL(rt2x00usb_kick_queue);
 
-static bool rt2x00usb_flush_entry(struct queue_entry *entry)
+static bool rt2x00usb_flush_entry(struct queue_entry *entry, void *data)
 {
 	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
 	struct queue_entry_priv_usb *entry_priv = entry->priv_data;
@@ -468,7 +474,7 @@ void rt2x00usb_flush_queue(struct data_queue *queue, bool drop)
 	unsigned int i;
 
 	if (drop)
-		rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX,
+		rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, NULL,
 					   rt2x00usb_flush_entry);
 
 	/*
@@ -559,7 +565,7 @@ void rt2x00usb_clear_entry(struct queue_entry *entry)
 	entry->flags = 0;
 
 	if (entry->queue->qid == QID_RX)
-		rt2x00usb_kick_rx_entry(entry);
+		rt2x00usb_kick_rx_entry(entry, NULL);
 }
 EXPORT_SYMBOL_GPL(rt2x00usb_clear_entry);
 
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index f95792c..9e3c8ff 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -35,6 +35,7 @@
 #include <linux/eeprom_93cx6.h>
 
 #include "rt2x00.h"
+#include "rt2x00mmio.h"
 #include "rt2x00pci.h"
 #include "rt61pci.h"
 
diff --git a/drivers/net/wireless/rtlwifi/Kconfig b/drivers/net/wireless/rtlwifi/Kconfig
index b6aa0c4..7253de3 100644
--- a/drivers/net/wireless/rtlwifi/Kconfig
+++ b/drivers/net/wireless/rtlwifi/Kconfig
@@ -55,6 +55,15 @@ config RTL8723AE
 
 	If you choose to build it as a module, it will be called rtl8723ae
 
+config RTL8188EE
+	tristate "Realtek RTL8188EE Wireless Network Adapter"
+	depends on RTLWIFI && PCI
+	---help---
+	This is the driver for Realtek RTL8188EE 802.11n PCIe
+	wireless network adapters.
+
+	If you choose to build it as a module, it will be called rtl8188ee
+
 config RTL8192CU
 	tristate "Realtek RTL8192CU/RTL8188CU USB Wireless Network Adapter"
 	depends on RTLWIFI && USB
diff --git a/drivers/net/wireless/rtlwifi/Makefile b/drivers/net/wireless/rtlwifi/Makefile
index 3b1cbac..ff02b87 100644
--- a/drivers/net/wireless/rtlwifi/Makefile
+++ b/drivers/net/wireless/rtlwifi/Makefile
@@ -26,5 +26,6 @@ obj-$(CONFIG_RTL8192CU)		+= rtl8192cu/
 obj-$(CONFIG_RTL8192SE)		+= rtl8192se/
 obj-$(CONFIG_RTL8192DE)		+= rtl8192de/
 obj-$(CONFIG_RTL8723AE)		+= rtl8723ae/
+obj-$(CONFIG_RTL8188EE)		+= rtl8188ee/
 
 ccflags-y += -D__CHECK_ENDIAN__
diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/rtlwifi/base.c
index 99c5cea..cac1fa9 100644
--- a/drivers/net/wireless/rtlwifi/base.c
+++ b/drivers/net/wireless/rtlwifi/base.c
@@ -54,7 +54,8 @@
  *5) frame process functions
  *6) IOT functions
  *7) sysfs functions
- *8) ...
+ *8) vif functions
+ *9) ...
  */
 
 /*********************************************************
@@ -198,34 +199,46 @@ static void _rtl_init_hw_ht_capab(struct ieee80211_hw *hw,
 
 	ht_cap->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
 
-	/*
-	 *hw->wiphy->bands[IEEE80211_BAND_2GHZ]
+	/*hw->wiphy->bands[IEEE80211_BAND_2GHZ]
 	 *base on ant_num
 	 *rx_mask: RX mask
-	 *if rx_ant =1 rx_mask[0]=0xff;==>MCS0-MCS7
-	 *if rx_ant =2 rx_mask[1]=0xff;==>MCS8-MCS15
-	 *if rx_ant >=3 rx_mask[2]=0xff;
-	 *if BW_40 rx_mask[4]=0x01;
+	 *if rx_ant = 1 rx_mask[0]= 0xff;==>MCS0-MCS7
+	 *if rx_ant = 2 rx_mask[1]= 0xff;==>MCS8-MCS15
+	 *if rx_ant >= 3 rx_mask[2]= 0xff;
+	 *if BW_40 rx_mask[4]= 0x01;
 	 *highest supported RX rate
 	 */
-	if (get_rf_type(rtlphy) == RF_1T2R || get_rf_type(rtlphy) == RF_2T2R) {
+	if (rtlpriv->dm.supp_phymode_switch) {
 
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "1T2R or 2T2R\n");
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG,
+			 "Support phy mode switch\n");
 
 		ht_cap->mcs.rx_mask[0] = 0xFF;
 		ht_cap->mcs.rx_mask[1] = 0xFF;
 		ht_cap->mcs.rx_mask[4] = 0x01;
 
 		ht_cap->mcs.rx_highest = cpu_to_le16(MAX_BIT_RATE_40MHZ_MCS15);
-	} else if (get_rf_type(rtlphy) == RF_1T1R) {
-
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "1T1R\n");
-
-		ht_cap->mcs.rx_mask[0] = 0xFF;
-		ht_cap->mcs.rx_mask[1] = 0x00;
-		ht_cap->mcs.rx_mask[4] = 0x01;
-
-		ht_cap->mcs.rx_highest = cpu_to_le16(MAX_BIT_RATE_40MHZ_MCS7);
+	} else {
+		if (get_rf_type(rtlphy) == RF_1T2R ||
+		    get_rf_type(rtlphy) == RF_2T2R) {
+			RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+				 "1T2R or 2T2R\n");
+			ht_cap->mcs.rx_mask[0] = 0xFF;
+			ht_cap->mcs.rx_mask[1] = 0xFF;
+			ht_cap->mcs.rx_mask[4] = 0x01;
+
+			ht_cap->mcs.rx_highest =
+				 cpu_to_le16(MAX_BIT_RATE_40MHZ_MCS15);
+		} else if (get_rf_type(rtlphy) == RF_1T1R) {
+			RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "1T1R\n");
+
+			ht_cap->mcs.rx_mask[0] = 0xFF;
+			ht_cap->mcs.rx_mask[1] = 0x00;
+			ht_cap->mcs.rx_mask[4] = 0x01;
+
+			ht_cap->mcs.rx_highest =
+				 cpu_to_le16(MAX_BIT_RATE_40MHZ_MCS7);
+		}
 	}
 }
 
@@ -311,6 +324,8 @@ static void _rtl_init_mac80211(struct ieee80211_hw *hw)
 	    IEEE80211_HW_AMPDU_AGGREGATION |
 	    IEEE80211_HW_CONNECTION_MONITOR |
 	    /* IEEE80211_HW_SUPPORTS_CQM_RSSI | */
+	    IEEE80211_HW_CONNECTION_MONITOR |
+	    IEEE80211_HW_MFP_CAPABLE |
 	    IEEE80211_HW_REPORTS_TX_ACK_STATUS | 0;
 
 	/* swlps or hwlps has been set in diff chip in init_sw_vars */
@@ -323,8 +338,12 @@ static void _rtl_init_mac80211(struct ieee80211_hw *hw)
 	hw->wiphy->interface_modes =
 	    BIT(NL80211_IFTYPE_AP) |
 	    BIT(NL80211_IFTYPE_STATION) |
-	    BIT(NL80211_IFTYPE_ADHOC);
+	    BIT(NL80211_IFTYPE_ADHOC) |
+	    BIT(NL80211_IFTYPE_MESH_POINT) |
+	    BIT(NL80211_IFTYPE_P2P_CLIENT) |
+	    BIT(NL80211_IFTYPE_P2P_GO);
 
+	hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
 	hw->wiphy->rts_threshold = 2347;
 
 	hw->queues = AC_MAX;
@@ -354,9 +373,10 @@ static void _rtl_init_deferred_work(struct ieee80211_hw *hw)
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 
 	/* <1> timer */
-	init_timer(&rtlpriv->works.watchdog_timer);
 	setup_timer(&rtlpriv->works.watchdog_timer,
 		    rtl_watch_dog_timer_callback, (unsigned long)hw);
+	setup_timer(&rtlpriv->works.dualmac_easyconcurrent_retrytimer,
+		    rtl_easy_concurrent_retrytimer_callback, (unsigned long)hw);
 
 	/* <2> work queue */
 	rtlpriv->works.hw = hw;
@@ -369,6 +389,8 @@ static void _rtl_init_deferred_work(struct ieee80211_hw *hw)
 			  (void *)rtl_swlps_wq_callback);
 	INIT_DELAYED_WORK(&rtlpriv->works.ps_rfon_wq,
 			  (void *)rtl_swlps_rfon_wq_callback);
+	INIT_DELAYED_WORK(&rtlpriv->works.fwevt_wq,
+			  (void *)rtl_fwevt_wq_callback);
 
 }
 
@@ -382,6 +404,7 @@ void rtl_deinit_deferred_work(struct ieee80211_hw *hw)
 	cancel_delayed_work(&rtlpriv->works.ips_nic_off_wq);
 	cancel_delayed_work(&rtlpriv->works.ps_work);
 	cancel_delayed_work(&rtlpriv->works.ps_rfon_wq);
+	cancel_delayed_work(&rtlpriv->works.fwevt_wq);
 }
 
 void rtl_init_rfkill(struct ieee80211_hw *hw)
@@ -436,12 +459,6 @@ int rtl_init_core(struct ieee80211_hw *hw)
 	if (rtl_regd_init(hw, rtl_reg_notifier)) {
 		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "REGD init failed\n");
 		return 1;
-	} else {
-		/* CRDA regd hint must after init CRDA */
-		if (regulatory_hint(hw->wiphy, rtlpriv->regd.alpha2)) {
-			RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
-				 "regulatory_hint fail\n");
-		}
 	}
 
 	/* <4> locks */
@@ -449,15 +466,25 @@ int rtl_init_core(struct ieee80211_hw *hw)
 	mutex_init(&rtlpriv->locks.ps_mutex);
 	spin_lock_init(&rtlpriv->locks.ips_lock);
 	spin_lock_init(&rtlpriv->locks.irq_th_lock);
+	spin_lock_init(&rtlpriv->locks.irq_pci_lock);
+	spin_lock_init(&rtlpriv->locks.tx_lock);
 	spin_lock_init(&rtlpriv->locks.h2c_lock);
 	spin_lock_init(&rtlpriv->locks.rf_ps_lock);
 	spin_lock_init(&rtlpriv->locks.rf_lock);
 	spin_lock_init(&rtlpriv->locks.waitq_lock);
+	spin_lock_init(&rtlpriv->locks.entry_list_lock);
+	spin_lock_init(&rtlpriv->locks.fw_ps_lock);
 	spin_lock_init(&rtlpriv->locks.cck_and_rw_pagea_lock);
+	spin_lock_init(&rtlpriv->locks.check_sendpkt_lock);
+	spin_lock_init(&rtlpriv->locks.fw_ps_lock);
+	spin_lock_init(&rtlpriv->locks.lps_lock);
+
+	/* <5> init list */
+	INIT_LIST_HEAD(&rtlpriv->entry_list);
 
 	rtlmac->link_state = MAC80211_NOLINK;
 
-	/* <5> init deferred work */
+	/* <6> init deferred work */
 	_rtl_init_deferred_work(hw);
 
 	return 0;
@@ -523,7 +550,8 @@ static void _rtl_query_shortgi(struct ieee80211_hw *hw,
 	if (mac->opmode == NL80211_IFTYPE_STATION)
 		bw_40 = mac->bw_40;
 	else if (mac->opmode == NL80211_IFTYPE_AP ||
-		 mac->opmode == NL80211_IFTYPE_ADHOC)
+		 mac->opmode == NL80211_IFTYPE_ADHOC ||
+		 mac->opmode == NL80211_IFTYPE_MESH_POINT)
 		bw_40 = sta->bandwidth >= IEEE80211_STA_RX_BW_40;
 
 	if (bw_40 && sgi_40)
@@ -578,23 +606,26 @@ static void _rtl_txrate_selectmode(struct ieee80211_hw *hw,
 	if (!tcb_desc->disable_ratefallback || !tcb_desc->use_driver_rate) {
 		if (mac->opmode == NL80211_IFTYPE_STATION) {
 			tcb_desc->ratr_index = 0;
-		} else if (mac->opmode == NL80211_IFTYPE_ADHOC) {
+		} else if (mac->opmode == NL80211_IFTYPE_ADHOC ||
+			   mac->opmode == NL80211_IFTYPE_MESH_POINT) {
 			if (tcb_desc->multicast || tcb_desc->broadcast) {
 				tcb_desc->hw_rate =
 				    rtlpriv->cfg->maps[RTL_RC_CCK_RATE2M];
 				tcb_desc->use_driver_rate = 1;
+				tcb_desc->ratr_index = RATR_INX_WIRELESS_MC;
 			} else {
-				/* TODO */
+				tcb_desc->ratr_index = ratr_index;
 			}
-			tcb_desc->ratr_index = ratr_index;
 		} else if (mac->opmode == NL80211_IFTYPE_AP) {
 			tcb_desc->ratr_index = ratr_index;
 		}
 	}
 
 	if (rtlpriv->dm.useramask) {
-		/* TODO we will differentiate adhoc and station futrue  */
-		if (mac->opmode == NL80211_IFTYPE_STATION) {
+		tcb_desc->ratr_index = ratr_index;
+		/* TODO we will differentiate adhoc and station future  */
+		if (mac->opmode == NL80211_IFTYPE_STATION ||
+		    mac->opmode == NL80211_IFTYPE_MESH_POINT) {
 			tcb_desc->mac_id = 0;
 
 			if (mac->mode == WIRELESS_MODE_N_24G)
@@ -608,7 +639,7 @@ static void _rtl_txrate_selectmode(struct ieee80211_hw *hw,
 			else if (mac->mode & WIRELESS_MODE_A)
 				tcb_desc->ratr_index = RATR_INX_WIRELESS_G;
 		} else if (mac->opmode == NL80211_IFTYPE_AP ||
-			mac->opmode == NL80211_IFTYPE_ADHOC) {
+			   mac->opmode == NL80211_IFTYPE_ADHOC) {
 			if (NULL != sta) {
 				if (sta->aid > 0)
 					tcb_desc->mac_id = sta->aid + 1;
@@ -619,7 +650,6 @@ static void _rtl_txrate_selectmode(struct ieee80211_hw *hw,
 			}
 		}
 	}
-
 }
 
 static void _rtl_query_bandwidth_mode(struct ieee80211_hw *hw,
@@ -633,7 +663,8 @@ static void _rtl_query_bandwidth_mode(struct ieee80211_hw *hw,
 	if (!sta)
 		return;
 	if (mac->opmode == NL80211_IFTYPE_AP ||
-	    mac->opmode == NL80211_IFTYPE_ADHOC) {
+	    mac->opmode == NL80211_IFTYPE_ADHOC ||
+	    mac->opmode == NL80211_IFTYPE_MESH_POINT) {
 		if (sta->bandwidth == IEEE80211_STA_RX_BW_20)
 			return;
 	} else if (mac->opmode == NL80211_IFTYPE_STATION) {
@@ -834,8 +865,8 @@ bool rtl_tx_mgmt_proc(struct ieee80211_hw *hw, struct sk_buff *skb)
 	if (rtlpriv->dm.supp_phymode_switch &&
 	    mac->link_state < MAC80211_LINKED &&
 	    (ieee80211_is_auth(fc) || ieee80211_is_probe_req(fc))) {
-		if (rtlpriv->cfg->ops->check_switch_to_dmdp)
-			rtlpriv->cfg->ops->check_switch_to_dmdp(hw);
+		if (rtlpriv->cfg->ops->chk_switch_dmdp)
+			rtlpriv->cfg->ops->chk_switch_dmdp(hw);
 	}
 	if (ieee80211_is_auth(fc)) {
 		RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, "MAC80211_LINKING\n");
@@ -924,6 +955,56 @@ void rtl_get_tcb_desc(struct ieee80211_hw *hw,
 }
 EXPORT_SYMBOL(rtl_get_tcb_desc);
 
+static bool addbareq_rx(struct ieee80211_hw *hw, struct sk_buff *skb)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct ieee80211_sta *sta = NULL;
+	struct ieee80211_hdr *hdr = rtl_get_hdr(skb);
+	struct rtl_sta_info *sta_entry = NULL;
+	struct ieee80211_mgmt *mgmt = (void *)skb->data;
+	u16 capab = 0, tid = 0;
+	struct rtl_tid_data *tid_data;
+	struct sk_buff *skb_delba = NULL;
+	struct ieee80211_rx_status rx_status = { 0 };
+
+	rcu_read_lock();
+	sta = rtl_find_sta(hw, hdr->addr3);
+	if (sta == NULL) {
+		RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_EMERG,
+			 "sta is NULL\n");
+		rcu_read_unlock();
+		return true;
+	}
+
+	sta_entry = (struct rtl_sta_info *)sta->drv_priv;
+	if (!sta_entry) {
+		rcu_read_unlock();
+		return true;
+	}
+	capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab);
+	tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2;
+	tid_data = &sta_entry->tids[tid];
+	if (tid_data->agg.rx_agg_state == RTL_RX_AGG_START) {
+		skb_delba = rtl_make_del_ba(hw, hdr->addr2, hdr->addr3, tid);
+		if (skb_delba) {
+			rx_status.freq = hw->conf.channel->center_freq;
+			rx_status.band = hw->conf.channel->band;
+			rx_status.flag |= RX_FLAG_DECRYPTED;
+			rx_status.flag |= RX_FLAG_MACTIME_END;
+			rx_status.rate_idx = 0;
+			rx_status.signal = 50 + 10;
+			memcpy(IEEE80211_SKB_RXCB(skb_delba), &rx_status,
+			       sizeof(rx_status));
+			RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_DMESG,
+				      "fake del\n", skb_delba->data,
+				      skb_delba->len);
+			ieee80211_rx_irqsafe(hw, skb_delba);
+		}
+	}
+	rcu_read_unlock();
+	return false;
+}
+
 bool rtl_action_proc(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx)
 {
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
@@ -948,6 +1029,11 @@ bool rtl_action_proc(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx)
 			RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG,
 				 "%s ACT_ADDBAREQ From :%pM\n",
 				 is_tx ? "Tx" : "Rx", hdr->addr2);
+			RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_DMESG, "req\n",
+				      skb->data, skb->len);
+			if (!is_tx)
+				if (addbareq_rx(hw, skb))
+					return true;
 			break;
 		case ACT_ADDBARSP:
 			RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG,
@@ -1003,8 +1089,9 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx)
 					 is_tx ? "Tx" : "Rx");
 
 				if (is_tx) {
+					rtlpriv->enter_ps = false;
 					schedule_work(&rtlpriv->
-						      works.lps_leave_work);
+						      works.lps_change_work);
 					ppsc->last_delaylps_stamp_jiffies =
 					    jiffies;
 				}
@@ -1014,7 +1101,8 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx)
 		}
 	} else if (ETH_P_ARP == ether_type) {
 		if (is_tx) {
-			schedule_work(&rtlpriv->works.lps_leave_work);
+			rtlpriv->enter_ps = false;
+			schedule_work(&rtlpriv->works.lps_change_work);
 			ppsc->last_delaylps_stamp_jiffies = jiffies;
 		}
 
@@ -1024,7 +1112,8 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx)
 			 "802.1X %s EAPOL pkt!!\n", is_tx ? "Tx" : "Rx");
 
 		if (is_tx) {
-			schedule_work(&rtlpriv->works.lps_leave_work);
+			rtlpriv->enter_ps = false;
+			schedule_work(&rtlpriv->works.lps_change_work);
 			ppsc->last_delaylps_stamp_jiffies = jiffies;
 		}
 
@@ -1101,6 +1190,58 @@ int rtl_tx_agg_stop(struct ieee80211_hw *hw,
 	return 0;
 }
 
+int rtl_rx_agg_start(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)
+		return -EINVAL;
+
+	if (unlikely(tid >= MAX_TID_COUNT))
+		return -EINVAL;
+
+	sta_entry = (struct rtl_sta_info *)sta->drv_priv;
+	if (!sta_entry)
+		return -ENXIO;
+	tid_data = &sta_entry->tids[tid];
+
+	RT_TRACE(rtlpriv, COMP_RECV, DBG_DMESG,
+		 "on ra = %pM tid = %d seq:%d\n", sta->addr, tid,
+		 tid_data->seq_number);
+
+	tid_data->agg.rx_agg_state = RTL_RX_AGG_START;
+	return 0;
+}
+
+int rtl_rx_agg_stop(struct ieee80211_hw *hw,
+		    struct ieee80211_sta *sta, u16 tid)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_sta_info *sta_entry = NULL;
+
+	if (sta == NULL)
+		return -EINVAL;
+
+	if (!sta->addr) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "ra = NULL\n");
+		return -EINVAL;
+	}
+
+	RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG,
+		 "on ra = %pM tid = %d\n", sta->addr, tid);
+
+	if (unlikely(tid >= MAX_TID_COUNT))
+		return -EINVAL;
+
+	sta_entry = (struct rtl_sta_info *)sta->drv_priv;
+	sta_entry->tids[tid].agg.rx_agg_state = RTL_RX_AGG_STOP;
+
+	return 0;
+}
+
 int rtl_tx_agg_oper(struct ieee80211_hw *hw,
 		struct ieee80211_sta *sta, u16 tid)
 {
@@ -1132,6 +1273,34 @@ int rtl_tx_agg_oper(struct ieee80211_hw *hw,
  * wq & timer callback functions
  *
  *********************************************************/
+/* this function is used for roaming */
+void rtl_beacon_statistic(struct ieee80211_hw *hw, struct sk_buff *skb)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+
+	if (rtlpriv->mac80211.opmode != NL80211_IFTYPE_STATION)
+		return;
+
+	if (rtlpriv->mac80211.link_state < MAC80211_LINKED)
+		return;
+
+	/* check if this really is a beacon */
+	if (!ieee80211_is_beacon(hdr->frame_control) &&
+	    !ieee80211_is_probe_resp(hdr->frame_control))
+		return;
+
+	/* min. beacon length + FCS_LEN */
+	if (skb->len <= 40 + FCS_LEN)
+		return;
+
+	/* and only beacons from the associated BSSID, please */
+	if (compare_ether_addr(hdr->addr3, rtlpriv->mac80211.bssid))
+		return;
+
+	rtlpriv->link_info.bcn_rx_inperiod++;
+}
+
 void rtl_watchdog_wq_callback(void *data)
 {
 	struct rtl_works *rtlworks = container_of_dwork_rtl(data,
@@ -1142,6 +1311,8 @@ void rtl_watchdog_wq_callback(void *data)
 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 	bool busytraffic = false;
+	bool tx_busy_traffic = false;
+	bool rx_busy_traffic = false;
 	bool higher_busytraffic = false;
 	bool higher_busyrxtraffic = false;
 	u8 idx, tid;
@@ -1151,7 +1322,6 @@ void rtl_watchdog_wq_callback(void *data)
 	u32 aver_tx_cnt_inperiod = 0;
 	u32 aver_tidtx_inperiod[MAX_TID_COUNT] = {0};
 	u32 tidtx_inp4eriod[MAX_TID_COUNT] = {0};
-	bool enter_ps = false;
 
 	if (is_hal_stop(rtlhal))
 		return;
@@ -1191,8 +1361,13 @@ void rtl_watchdog_wq_callback(void *data)
 		aver_tx_cnt_inperiod = tx_cnt_inp4eriod / 4;
 
 		/* (2) check traffic busy */
-		if (aver_rx_cnt_inperiod > 100 || aver_tx_cnt_inperiod > 100)
+		if (aver_rx_cnt_inperiod > 100 || aver_tx_cnt_inperiod > 100) {
 			busytraffic = true;
+			if (aver_rx_cnt_inperiod > aver_tx_cnt_inperiod)
+				rx_busy_traffic = true;
+			else
+				tx_busy_traffic = false;
+		}
 
 		/* Higher Tx/Rx data. */
 		if (aver_rx_cnt_inperiod > 4000 ||
@@ -1228,15 +1403,12 @@ void rtl_watchdog_wq_callback(void *data)
 		if (((rtlpriv->link_info.num_rx_inperiod +
 		      rtlpriv->link_info.num_tx_inperiod) > 8) ||
 		    (rtlpriv->link_info.num_rx_inperiod > 2))
-			enter_ps = false;
+			rtlpriv->enter_ps = true;
 		else
-			enter_ps = true;
+			rtlpriv->enter_ps = false;
 
 		/* LeisurePS only work in infra mode. */
-		if (enter_ps)
-			rtl_lps_enter(hw);
-		else
-			rtl_lps_leave(hw);
+		schedule_work(&rtlpriv->works.lps_change_work);
 	}
 
 	rtlpriv->link_info.num_rx_inperiod = 0;
@@ -1246,10 +1418,37 @@ void rtl_watchdog_wq_callback(void *data)
 
 	rtlpriv->link_info.busytraffic = busytraffic;
 	rtlpriv->link_info.higher_busytraffic = higher_busytraffic;
+	rtlpriv->link_info.rx_busy_traffic = rx_busy_traffic;
+	rtlpriv->link_info.tx_busy_traffic = tx_busy_traffic;
 	rtlpriv->link_info.higher_busyrxtraffic = higher_busyrxtraffic;
 
 	/* <3> DM */
 	rtlpriv->cfg->ops->dm_watchdog(hw);
+
+	/* <4> roaming */
+	if (mac->link_state == MAC80211_LINKED &&
+	    mac->opmode == NL80211_IFTYPE_STATION) {
+		if ((rtlpriv->link_info.bcn_rx_inperiod +
+		     rtlpriv->link_info.num_rx_inperiod) == 0) {
+			rtlpriv->link_info.roam_times++;
+			RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG,
+				 "AP off for %d s\n",
+				 (rtlpriv->link_info.roam_times * 2));
+
+			/* if we can't recv beacon for 6s, we should
+			 * reconnect this AP
+			 */
+			if (rtlpriv->link_info.roam_times >= 3) {
+				RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+					 "AP off, try to reconnect now\n");
+				rtlpriv->link_info.roam_times = 0;
+				ieee80211_connection_loss(rtlpriv->mac80211.vif);
+			}
+		} else {
+			rtlpriv->link_info.roam_times = 0;
+		}
+	}
+	rtlpriv->link_info.bcn_rx_inperiod = 0;
 }
 
 void rtl_watch_dog_timer_callback(unsigned long data)
@@ -1264,6 +1463,28 @@ void rtl_watch_dog_timer_callback(unsigned long data)
 		  jiffies + MSECS(RTL_WATCH_DOG_TIME));
 }
 
+void rtl_fwevt_wq_callback(void *data)
+{
+	struct rtl_works *rtlworks =
+		container_of_dwork_rtl(data, struct rtl_works, fwevt_wq);
+	struct ieee80211_hw *hw = rtlworks->hw;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	rtlpriv->cfg->ops->c2h_command_handle(hw);
+}
+
+void rtl_easy_concurrent_retrytimer_callback(unsigned long data)
+{
+	struct ieee80211_hw *hw = (struct ieee80211_hw *)data;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_priv *buddy_priv = rtlpriv->buddy_priv;
+
+	if (buddy_priv == NULL)
+		return;
+
+	rtlpriv->cfg->ops->dualmac_easy_concurrent(hw);
+}
+
 /*********************************************************
  *
  * frame process functions
@@ -1334,14 +1555,16 @@ static struct sk_buff *rtl_make_smps_action(struct ieee80211_hw *hw,
 }
 
 int rtl_send_smps_action(struct ieee80211_hw *hw,
-		struct ieee80211_sta *sta, u8 *da, u8 *bssid,
+		struct ieee80211_sta *sta,
 		enum ieee80211_smps_mode smps)
 {
 	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));
-	struct sk_buff *skb = rtl_make_smps_action(hw, smps, da, bssid);
+	struct sk_buff *skb = NULL;
 	struct rtl_tcb_desc tcb_desc;
+	u8 bssid[ETH_ALEN] = {0};
+
 	memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc));
 
 	if (rtlpriv->mac80211.act_scanning)
@@ -1356,21 +1579,67 @@ int rtl_send_smps_action(struct ieee80211_hw *hw,
 	if (!test_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status))
 		goto err_free;
 
+	if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP)
+		memcpy(bssid, rtlpriv->efuse.dev_addr, ETH_ALEN);
+	else
+		memcpy(bssid, rtlpriv->mac80211.bssid, ETH_ALEN);
+
+	skb = rtl_make_smps_action(hw, smps, sta->addr, bssid);
 	/* this is a type = mgmt * stype = action frame */
 	if (skb) {
 		struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 		struct rtl_sta_info *sta_entry =
 			(struct rtl_sta_info *) sta->drv_priv;
 		sta_entry->mimo_ps = smps;
-		rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0);
 
 		info->control.rates[0].idx = 0;
 		info->band = hw->conf.channel->band;
 		rtlpriv->intf_ops->adapter_tx(hw, sta, skb, &tcb_desc);
 	}
+	return 1;
+
 err_free:
 	return 0;
 }
+EXPORT_SYMBOL(rtl_send_smps_action);
+
+/* There seem to be issues in mac80211 regarding when del ba frames can be
+ * received. As a work around, we make a fake del_ba if we receive a ba_req;
+ * however, rx_agg was opened to let mac80211 release some ba related
+ * resources. This del_ba is for tx only.
+ */
+struct sk_buff *rtl_make_del_ba(struct ieee80211_hw *hw,
+				u8 *sa, u8 *bssid, u16 tid)
+{
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	struct sk_buff *skb;
+	struct ieee80211_mgmt *action_frame;
+	u16 params;
+
+	/* 27 = header + category + action + smps mode */
+	skb = dev_alloc_skb(34 + hw->extra_tx_headroom);
+	if (!skb)
+		return NULL;
+
+	skb_reserve(skb, hw->extra_tx_headroom);
+	action_frame = (void *)skb_put(skb, 34);
+	memset(action_frame, 0, 34);
+	memcpy(action_frame->sa, sa, ETH_ALEN);
+	memcpy(action_frame->da, rtlefuse->dev_addr, ETH_ALEN);
+	memcpy(action_frame->bssid, bssid, ETH_ALEN);
+	action_frame->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
+						  IEEE80211_STYPE_ACTION);
+	action_frame->u.action.category = WLAN_CATEGORY_BACK;
+	action_frame->u.action.u.delba.action_code = WLAN_ACTION_DELBA;
+	params = (u16)(1 << 11);	/* bit 11 initiator */
+	params |= (u16)(tid << 12);		/* bit 15:12 TID number */
+
+	action_frame->u.action.u.delba.params = cpu_to_le16(params);
+	action_frame->u.action.u.delba.reason_code =
+		cpu_to_le16(WLAN_REASON_QSTA_TIMEOUT);
+
+	return skb;
+}
 
 /*********************************************************
  *
@@ -1587,11 +1856,17 @@ MODULE_AUTHOR("Larry Finger	<Larry.FInger@lwfinger.net>");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Realtek 802.11n PCI wireless core");
 
+struct rtl_global_var global_var = {};
+
 static int __init rtl_core_module_init(void)
 {
 	if (rtl_rate_control_register())
 		pr_err("Unable to register rtl_rc, use default RC !!\n");
 
+	/* init some global vars */
+	INIT_LIST_HEAD(&global_var.glb_priv_list);
+	spin_lock_init(&global_var.glb_list_lock);
+
 	return 0;
 }
 
diff --git a/drivers/net/wireless/rtlwifi/base.h b/drivers/net/wireless/rtlwifi/base.h
index 5a8c80e..8576bc3 100644
--- a/drivers/net/wireless/rtlwifi/base.h
+++ b/drivers/net/wireless/rtlwifi/base.h
@@ -113,6 +113,7 @@ void rtl_init_rx_config(struct ieee80211_hw *hw);
 void rtl_init_rfkill(struct ieee80211_hw *hw);
 void rtl_deinit_rfkill(struct ieee80211_hw *hw);
 
+void rtl_beacon_statistic(struct ieee80211_hw *hw, struct sk_buff *skb);
 void rtl_watch_dog_timer_callback(unsigned long data);
 void rtl_deinit_deferred_work(struct ieee80211_hw *hw);
 
@@ -126,7 +127,12 @@ int rtl_tx_agg_stop(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
 		    u16 tid);
 int rtl_tx_agg_oper(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
 		    u16 tid);
+int rtl_rx_agg_start(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
+		     u16 tid);
+int rtl_rx_agg_stop(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
+		    u16 tid);
 void rtl_watchdog_wq_callback(void *data);
+void rtl_fwevt_wq_callback(void *data);
 
 void rtl_get_tcb_desc(struct ieee80211_hw *hw,
 		      struct ieee80211_tx_info *info,
@@ -134,14 +140,18 @@ void rtl_get_tcb_desc(struct ieee80211_hw *hw,
 		      struct sk_buff *skb, struct rtl_tcb_desc *tcb_desc);
 
 int rtl_send_smps_action(struct ieee80211_hw *hw,
-		struct ieee80211_sta *sta, u8 *da, u8 *bssid,
-		enum ieee80211_smps_mode smps);
+			 struct ieee80211_sta *sta,
+			 enum ieee80211_smps_mode smps);
 u8 *rtl_find_ie(u8 *data, unsigned int len, u8 ie);
 void rtl_recognize_peer(struct ieee80211_hw *hw, u8 *data, unsigned int len);
 u8 rtl_tid_to_ac(u8 tid);
 extern struct attribute_group rtl_attribute_group;
+void rtl_easy_concurrent_retrytimer_callback(unsigned long data);
+extern struct rtl_global_var global_var;
 int rtlwifi_rate_mapping(struct ieee80211_hw *hw,
 			 bool isht, u8 desc_rate, bool first_ampdu);
 bool rtl_tx_mgmt_proc(struct ieee80211_hw *hw, struct sk_buff *skb);
+struct sk_buff *rtl_make_del_ba(struct ieee80211_hw *hw,
+				u8 *sa, u8 *bssid, u16 tid);
 
 #endif
diff --git a/drivers/net/wireless/rtlwifi/core.c b/drivers/net/wireless/rtlwifi/core.c
index d3ce9fb..2201b5c 100644
--- a/drivers/net/wireless/rtlwifi/core.c
+++ b/drivers/net/wireless/rtlwifi/core.c
@@ -104,9 +104,12 @@ static void rtl_op_stop(struct ieee80211_hw *hw)
 	if (is_hal_stop(rtlhal))
 		return;
 
+	/* here is must, because adhoc do stop and start,
+	 * but stop with RFOFF may cause something wrong,
+	 * like adhoc TP
+	 */
 	if (unlikely(ppsc->rfpwr_state == ERFOFF)) {
 		rtl_ips_nic_on(hw);
-		mdelay(1);
 	}
 
 	mutex_lock(&rtlpriv->locks.conf_mutex);
@@ -167,7 +170,11 @@ static int rtl_op_add_interface(struct ieee80211_hw *hw,
 	rtl_ips_nic_on(hw);
 
 	mutex_lock(&rtlpriv->locks.conf_mutex);
-	switch (vif->type) {
+
+	switch (ieee80211_vif_type_p2p(vif)) {
+	case NL80211_IFTYPE_P2P_CLIENT:
+		mac->p2p = P2P_ROLE_CLIENT;
+		/*fall through*/
 	case NL80211_IFTYPE_STATION:
 		if (mac->beacon_enabled == 1) {
 			RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
@@ -192,6 +199,9 @@ static int rtl_op_add_interface(struct ieee80211_hw *hw,
 				(u8 *) (&mac->basic_rates));
 
 		break;
+	case NL80211_IFTYPE_P2P_GO:
+		mac->p2p = P2P_ROLE_GO;
+		/*fall through*/
 	case NL80211_IFTYPE_AP:
 		RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
 			 "NL80211_IFTYPE_AP\n");
@@ -205,6 +215,19 @@ static int rtl_op_add_interface(struct ieee80211_hw *hw,
 		rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE,
 				(u8 *) (&mac->basic_rates));
 		break;
+	case NL80211_IFTYPE_MESH_POINT:
+		RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
+			 "NL80211_IFTYPE_MESH_POINT\n");
+
+		mac->link_state = MAC80211_LINKED;
+		rtlpriv->cfg->ops->set_bcn_reg(hw);
+		if (rtlpriv->rtlhal.current_bandtype == BAND_ON_2_4G)
+			mac->basic_rates = 0xfff;
+		else
+			mac->basic_rates = 0xff0;
+		rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE,
+				(u8 *)(&mac->basic_rates));
+		break;
 	default:
 		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
 			 "operation mode %d is not supported!\n", vif->type);
@@ -212,6 +235,13 @@ static int rtl_op_add_interface(struct ieee80211_hw *hw,
 		goto out;
 	}
 
+	if (mac->p2p) {
+		RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
+			 "p2p role %x\n", vif->type);
+		mac->basic_rates = 0xff0;/*disable cck rate for p2p*/
+		rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE,
+				(u8 *)(&mac->basic_rates));
+	}
 	mac->vif = vif;
 	mac->opmode = vif->type;
 	rtlpriv->cfg->ops->set_network_type(hw, vif->type);
@@ -232,9 +262,9 @@ static void rtl_op_remove_interface(struct ieee80211_hw *hw,
 	mutex_lock(&rtlpriv->locks.conf_mutex);
 
 	/* Free beacon resources */
-	if ((mac->opmode == NL80211_IFTYPE_AP) ||
-	    (mac->opmode == NL80211_IFTYPE_ADHOC) ||
-	    (mac->opmode == NL80211_IFTYPE_MESH_POINT)) {
+	if ((vif->type == NL80211_IFTYPE_AP) ||
+	    (vif->type == NL80211_IFTYPE_ADHOC) ||
+	    (vif->type == NL80211_IFTYPE_MESH_POINT)) {
 		if (mac->beacon_enabled == 1) {
 			mac->beacon_enabled = 0;
 			rtlpriv->cfg->ops->update_interrupt_mask(hw, 0,
@@ -247,6 +277,7 @@ static void rtl_op_remove_interface(struct ieee80211_hw *hw,
 	 *Note: We assume NL80211_IFTYPE_UNSPECIFIED as
 	 *NO LINK for our hardware.
 	 */
+	mac->p2p = 0;
 	mac->vif = NULL;
 	mac->link_state = MAC80211_NOLINK;
 	memset(mac->bssid, 0, 6);
@@ -256,6 +287,22 @@ static void rtl_op_remove_interface(struct ieee80211_hw *hw,
 	mutex_unlock(&rtlpriv->locks.conf_mutex);
 }
 
+static int rtl_op_change_interface(struct ieee80211_hw *hw,
+				      struct ieee80211_vif *vif,
+				      enum nl80211_iftype new_type, bool p2p)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	int ret;
+	rtl_op_remove_interface(hw, vif);
+
+	vif->type = new_type;
+	vif->p2p = p2p;
+	ret = rtl_op_add_interface(hw, vif);
+	RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
+		 "p2p %x\n", p2p);
+	return ret;
+}
+
 static int rtl_op_config(struct ieee80211_hw *hw, u32 changed)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
@@ -264,6 +311,9 @@ static int rtl_op_config(struct ieee80211_hw *hw, u32 changed)
 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
 	struct ieee80211_conf *conf = &hw->conf;
 
+	if (mac->skip_scan)
+		return 1;
+
 	mutex_lock(&rtlpriv->locks.conf_mutex);
 	if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) {	/*BIT(2)*/
 		RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
@@ -323,6 +373,16 @@ static int rtl_op_config(struct ieee80211_hw *hw, u32 changed)
 		struct ieee80211_channel *channel = hw->conf.channel;
 		u8 wide_chan = (u8) channel->hw_value;
 
+		if (mac->act_scanning)
+			mac->n_channels++;
+
+		if (rtlpriv->dm.supp_phymode_switch &&
+		    mac->link_state < MAC80211_LINKED &&
+		    !mac->act_scanning) {
+			if (rtlpriv->cfg->ops->chk_switch_dmdp)
+				rtlpriv->cfg->ops->chk_switch_dmdp(hw);
+		}
+
 		/*
 		 *because we should back channel to
 		 *current_network.chan in in scanning,
@@ -373,13 +433,13 @@ static int rtl_op_config(struct ieee80211_hw *hw, u32 changed)
 		if (wide_chan <= 0)
 			wide_chan = 1;
 
-		/* In scanning, before we go offchannel we may send a ps=1 null
-		 * to AP, and then we may send a ps = 0 null to AP quickly, but
-		 * first null may have caused AP to put lots of packet to hw tx
-		 * buffer. These packets must be tx'd before we go off channel
-		 * so we must delay more time to let AP flush these packets
-		 * before going offchannel, or dis-association or delete BA will
-		 * happen by AP
+		/* In scanning, before we go offchannel we may send a ps = 1
+		 * null to AP, and then we may send a ps = 0 null to AP quickly,
+		 * but first null may have caused AP to put lots of packet to
+		 * hw tx buffer. These packets must be tx'd before we go off
+		 * channel so we must delay more time to let AP flush these
+		 * packets before going offchannel, or dis-association or
+		 * delete BA will be caused by AP
 		 */
 		if (rtlpriv->mac80211.offchan_delay) {
 			rtlpriv->mac80211.offchan_delay = false;
@@ -441,7 +501,8 @@ static void rtl_op_configure_filter(struct ieee80211_hw *hw,
 	 * and nolink check bssid is set in set network_type */
 	if ((changed_flags & FIF_BCN_PRBRESP_PROMISC) &&
 		(mac->link_state >= MAC80211_LINKED)) {
-		if (mac->opmode != NL80211_IFTYPE_AP) {
+		if (mac->opmode != NL80211_IFTYPE_AP &&
+		    mac->opmode != NL80211_IFTYPE_MESH_POINT) {
 			if (*new_flags & FIF_BCN_PRBRESP_PROMISC) {
 				rtlpriv->cfg->ops->set_chk_bssid(hw, false);
 			} else {
@@ -481,32 +542,43 @@ static int rtl_op_sta_add(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_sta_info *sta_entry;
 
 	if (sta) {
 		sta_entry = (struct rtl_sta_info *) sta->drv_priv;
+		spin_lock_bh(&rtlpriv->locks.entry_list_lock);
+		list_add_tail(&sta_entry->list, &rtlpriv->entry_list);
+		spin_unlock_bh(&rtlpriv->locks.entry_list_lock);
 		if (rtlhal->current_bandtype == BAND_ON_2_4G) {
 			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)
+			if (sta->ht_cap.ht_supported == true)
 				sta_entry->wireless_mode = WIRELESS_MODE_N_24G;
+
+			if (vif->type == NL80211_IFTYPE_ADHOC)
+				sta_entry->wireless_mode = WIRELESS_MODE_G;
 		} else if (rtlhal->current_bandtype == BAND_ON_5G) {
 			sta_entry->wireless_mode = WIRELESS_MODE_A;
-			if (sta->ht_cap.ht_supported)
+			if (sta->ht_cap.ht_supported == true)
 				sta_entry->wireless_mode = WIRELESS_MODE_N_24G;
-		}
 
-		/* I found some times mac80211 give wrong supp_rates for adhoc*/
-		if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC)
-			sta_entry->wireless_mode = WIRELESS_MODE_G;
+			if (vif->type == NL80211_IFTYPE_ADHOC)
+				sta_entry->wireless_mode = WIRELESS_MODE_A;
+		}
+		/*disable cck rate for p2p*/
+		if (mac->p2p)
+			sta->supp_rates[0] &= 0xfffffff0;
 
+		memcpy(sta_entry->mac_addr, sta->addr, ETH_ALEN);
 		RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG,
 			 "Add sta addr is %pM\n", sta->addr);
 		rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0);
 	}
 	return 0;
 }
+
 static int rtl_op_sta_remove(struct ieee80211_hw *hw,
 				struct ieee80211_vif *vif,
 				struct ieee80211_sta *sta)
@@ -519,9 +591,14 @@ static int rtl_op_sta_remove(struct ieee80211_hw *hw,
 		sta_entry = (struct rtl_sta_info *) sta->drv_priv;
 		sta_entry->wireless_mode = 0;
 		sta_entry->ratr_index = 0;
+
+		spin_lock_bh(&rtlpriv->locks.entry_list_lock);
+		list_del(&sta_entry->list);
+		spin_unlock_bh(&rtlpriv->locks.entry_list_lock);
 	}
 	return 0;
 }
+
 static int _rtl_get_hal_qnum(u16 queue)
 {
 	int qnum;
@@ -547,8 +624,8 @@ static int _rtl_get_hal_qnum(u16 queue)
 }
 
 /*
- *for mac80211 VO=0, VI=1, BE=2, BK=3
- *for rtl819x  BE=0, BK=1, VI=2, VO=3
+ *for mac80211 VO = 0, VI = 1, BE = 2, BK = 3
+ *for rtl819x  BE = 0, BK = 1, VI = 2, VO = 3
  */
 static int rtl_op_conf_tx(struct ieee80211_hw *hw,
 		   struct ieee80211_vif *vif, u16 queue,
@@ -630,6 +707,7 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw,
 	/*TODO: reference to enum ieee80211_bss_change */
 	if (changed & BSS_CHANGED_ASSOC) {
 		if (bss_conf->assoc) {
+			struct ieee80211_sta *sta = NULL;
 			/* we should reset all sec info & cam
 			 * before set cam after linked, we should not
 			 * reset in disassoc, that will cause tkip->wep
@@ -647,23 +725,39 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw,
 
 			if (rtlpriv->cfg->ops->linked_set_reg)
 				rtlpriv->cfg->ops->linked_set_reg(hw);
-			if (mac->opmode == NL80211_IFTYPE_STATION && sta)
+			rcu_read_lock();
+			sta = ieee80211_find_sta(vif, (u8 *)bss_conf->bssid);
+
+			if (vif->type == NL80211_IFTYPE_STATION && sta)
 				rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0);
+			RT_TRACE(rtlpriv, COMP_EASY_CONCURRENT, DBG_LOUD,
+				 "send PS STATIC frame\n");
+			if (rtlpriv->dm.supp_phymode_switch) {
+				if (sta->ht_cap.ht_supported)
+					rtl_send_smps_action(hw, sta,
+						 IEEE80211_SMPS_STATIC);
+			}
+			rcu_read_unlock();
+
 			RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG,
 				 "BSS_CHANGED_ASSOC\n");
 		} else {
-			if (mac->link_state == MAC80211_LINKED)
-				rtl_lps_leave(hw);
+			if (mac->link_state == MAC80211_LINKED) {
+				rtlpriv->enter_ps = false;
+				schedule_work(&rtlpriv->works.lps_change_work);
+			}
 
+			if (ppsc->p2p_ps_info.p2p_ps_mode > P2P_PS_NONE)
+				rtl_p2p_ps_cmd(hw, P2P_PS_DISABLE);
 			mac->link_state = MAC80211_NOLINK;
 			memset(mac->bssid, 0, 6);
-
-			/* reset sec info */
-			rtl_cam_reset_sec_info(hw);
-
-			rtl_cam_reset_all_entry(hw);
 			mac->vendor = PEER_UNKNOWN;
 
+			if (rtlpriv->dm.supp_phymode_switch) {
+				if (rtlpriv->cfg->ops->chk_switch_dmdp)
+					rtlpriv->cfg->ops->chk_switch_dmdp(hw);
+			}
+
 			RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG,
 				 "BSS_CHANGED_UN_ASSOC\n");
 		}
@@ -778,7 +872,7 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw,
 		}
 
 		if (changed & BSS_CHANGED_BASIC_RATES) {
-			/* for 5G must << RATE_6M_INDEX=4,
+			/* for 5G must << RATE_6M_INDEX = 4,
 			 * because 5G have no cck rate*/
 			if (rtlhal->current_bandtype == BAND_ON_5G)
 				basic_rates = sta->supp_rates[1] << 4;
@@ -815,6 +909,9 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw,
 				ppsc->report_linked = false;
 			}
 		}
+		if (rtlpriv->cfg->ops->bt_wifi_media_status_notify)
+			rtlpriv->cfg->ops->bt_wifi_media_status_notify(hw,
+							 ppsc->report_linked);
 	}
 
 out:
@@ -885,7 +982,6 @@ static int rtl_op_ampdu_action(struct ieee80211_hw *hw,
 		RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
 			 "IEEE80211_AMPDU_TX_STOP: TID:%d\n", tid);
 		return rtl_tx_agg_stop(hw, sta, tid);
-		break;
 	case IEEE80211_AMPDU_TX_OPERATIONAL:
 		RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
 			 "IEEE80211_AMPDU_TX_OPERATIONAL:TID:%d\n", tid);
@@ -894,11 +990,11 @@ static int rtl_op_ampdu_action(struct ieee80211_hw *hw,
 	case IEEE80211_AMPDU_RX_START:
 		RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
 			 "IEEE80211_AMPDU_RX_START:TID:%d\n", tid);
-		break;
+		return rtl_rx_agg_start(hw, sta, tid);
 	case IEEE80211_AMPDU_RX_STOP:
 		RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
 			 "IEEE80211_AMPDU_RX_STOP:TID:%d\n", tid);
-		break;
+		return rtl_rx_agg_stop(hw, sta, tid);
 	default:
 		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
 			 "IEEE80211_AMPDU_ERR!!!!:\n");
@@ -912,12 +1008,20 @@ static void rtl_op_sw_scan_start(struct ieee80211_hw *hw)
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 
-	mac->act_scanning = true;
-
 	RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "\n");
+	mac->act_scanning = true;
+	if (rtlpriv->link_info.higher_busytraffic) {
+		mac->skip_scan = true;
+		return;
+	}
 
+	if (rtlpriv->dm.supp_phymode_switch) {
+		if (rtlpriv->cfg->ops->chk_switch_dmdp)
+			rtlpriv->cfg->ops->chk_switch_dmdp(hw);
+	}
 	if (mac->link_state == MAC80211_LINKED) {
-		rtl_lps_leave(hw);
+		rtlpriv->enter_ps = false;
+		schedule_work(&rtlpriv->works.lps_change_work);
 		mac->link_state = MAC80211_LINKED_SCANNING;
 	} else {
 		rtl_ips_nic_on(hw);
@@ -937,6 +1041,16 @@ static void rtl_op_sw_scan_complete(struct ieee80211_hw *hw)
 
 	RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "\n");
 	mac->act_scanning = false;
+	mac->skip_scan = false;
+	if (rtlpriv->link_info.higher_busytraffic)
+		return;
+
+	/*p2p will use 1/6/11 to scan */
+	if (mac->n_channels == 3)
+		mac->p2p_in_use = true;
+	else
+		mac->p2p_in_use = false;
+	mac->n_channels = 0;
 	/* Dual mac */
 	rtlpriv->rtlhal.load_imrandiqk_setting_for2g = false;
 
@@ -970,6 +1084,11 @@ static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 			 "not open hw encryption\n");
 		return -ENOSPC;	/*User disabled HW-crypto */
 	}
+	/* To support IBSS, use sw-crypto for GTK */
+	if (((vif->type == NL80211_IFTYPE_ADHOC) ||
+	     (vif->type == NL80211_IFTYPE_MESH_POINT)) &&
+	      !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
+		return -ENOSPC;
 	RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
 		 "%s hardware based encryption for keyidx: %d, mac: %pM\n",
 		 cmd == SET_KEY ? "Using" : "Disabling", key->keyidx,
@@ -996,6 +1115,14 @@ static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 		key_type = AESCCMP_ENCRYPTION;
 		RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "alg:CCMP\n");
 		break;
+	case WLAN_CIPHER_SUITE_AES_CMAC:
+		/*HW doesn't support CMAC encryption, use software CMAC */
+		key_type = AESCMAC_ENCRYPTION;
+		RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "alg:CMAC\n");
+		RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
+			 "HW don't support CMAC encryption, use software CMAC\n");
+		err = -EOPNOTSUPP;
+		goto out_unlock;
 	default:
 		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "alg_err:%x!!!!\n",
 			 key->cipher);
@@ -1017,13 +1144,14 @@ static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 	 * 1) wep only: is just for wep enc, in this condition
 	 * rtlpriv->sec.pairwise_enc_algorithm == NO_ENCRYPTION
 	 * will be true & enable_hw_sec will be set when wep
-	 * ke setting.
+	 * key setting.
 	 * 2) wep(group) + AES(pairwise): some AP like cisco
 	 * may use it, in this condition enable_hw_sec will not
 	 * be set when wep key setting */
 	/* we must reset sec_info after lingked before set key,
 	 * or some flag will be wrong*/
-	if (mac->opmode == NL80211_IFTYPE_AP) {
+	if (vif->type == NL80211_IFTYPE_AP ||
+	    vif->type == NL80211_IFTYPE_MESH_POINT) {
 		if (!group_key || key_type == WEP40_ENCRYPTION ||
 			key_type == WEP104_ENCRYPTION) {
 			if (group_key)
@@ -1098,12 +1226,16 @@ static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 		key->hw_key_idx = key_idx;
 		if (key_type == TKIP_ENCRYPTION)
 			key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
+		/*use software CCMP encryption for management frames (MFP) */
+		if (key_type == AESCCMP_ENCRYPTION)
+			key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX;
 		break;
 	case DISABLE_KEY:
 		RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
 			 "disable key delete one entry\n");
 		/*set local buf about wep key. */
-		if (mac->opmode == NL80211_IFTYPE_AP) {
+		if (vif->type == NL80211_IFTYPE_AP ||
+		    vif->type == NL80211_IFTYPE_MESH_POINT) {
 			if (sta)
 				rtl_cam_del_entry(hw, sta->addr);
 		}
@@ -1163,10 +1295,10 @@ static void rtl_op_rfkill_poll(struct ieee80211_hw *hw)
 }
 
 /* this function is called by mac80211 to flush tx buffer
- * before switch channle or power save, or tx buffer packet
+ * before switch channel or power save, or tx buffer packet
  * maybe send after offchannel or rf sleep, this may cause
  * dis-association by AP */
-static void rtl_op_flush(struct ieee80211_hw *hw, bool drop)
+static void rtl_op_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 
@@ -1180,6 +1312,7 @@ const struct ieee80211_ops rtl_ops = {
 	.tx = rtl_op_tx,
 	.add_interface = rtl_op_add_interface,
 	.remove_interface = rtl_op_remove_interface,
+	.change_interface = rtl_op_change_interface,
 	.config = rtl_op_config,
 	.configure_filter = rtl_op_configure_filter,
 	.sta_add = rtl_op_sta_add,
diff --git a/drivers/net/wireless/rtlwifi/debug.c b/drivers/net/wireless/rtlwifi/debug.c
index bdda9b2..7d52d3d 100644
--- a/drivers/net/wireless/rtlwifi/debug.c
+++ b/drivers/net/wireless/rtlwifi/debug.c
@@ -41,7 +41,10 @@ void rtl_dbgp_flag_init(struct ieee80211_hw *hw)
 	    COMP_BEACON | COMP_RATE | COMP_RXDESC | COMP_DIG | COMP_TXAGC |
 	    COMP_POWER | COMP_POWER_TRACKING | COMP_BB_POWERSAVING | COMP_SWAS |
 	    COMP_RF | COMP_TURBO | COMP_RATR | COMP_CMD |
-	    COMP_EFUSE | COMP_QOS | COMP_MAC80211 | COMP_REGD | COMP_CHAN;
+	    COMP_EFUSE | COMP_QOS | COMP_MAC80211 | COMP_REGD | COMP_CHAN |
+	    COMP_EASY_CONCURRENT | COMP_EFUSE | COMP_QOS | COMP_MAC80211 |
+	    COMP_REGD | COMP_CHAN | COMP_BT_COEXIST;
+
 
 	for (i = 0; i < DBGP_TYPE_MAX; i++)
 		rtlpriv->dbg.dbgp_type[i] = 0;
diff --git a/drivers/net/wireless/rtlwifi/debug.h b/drivers/net/wireless/rtlwifi/debug.h
index fd3269f..6d66936 100644
--- a/drivers/net/wireless/rtlwifi/debug.h
+++ b/drivers/net/wireless/rtlwifi/debug.h
@@ -115,11 +115,11 @@
 /* Define EEPROM and EFUSE  check module bit*/
 #define EEPROM_W			BIT(0)
 #define EFUSE_PG			BIT(1)
-#define EFUSE_READ_ALL		BIT(2)
+#define EFUSE_READ_ALL			BIT(2)
 
 /* Define init check for module bit*/
 #define	INIT_EEPROM			BIT(0)
-#define	INIT_TxPower		BIT(1)
+#define	INIT_TXPOWER			BIT(1)
 #define	INIT_IQK			BIT(2)
 #define	INIT_RF				BIT(3)
 
@@ -135,6 +135,15 @@
 #define	PHY_TXPWR			BIT(8)
 #define	PHY_PWRDIFF			BIT(9)
 
+/* Define Dynamic Mechanism check module bit --> FDM */
+#define WA_IOT				BIT(0)
+#define DM_PWDB				BIT(1)
+#define DM_MONITOR			BIT(2)
+#define DM_DIG				BIT(3)
+#define DM_EDCA_TURBO			BIT(4)
+
+#define DM_PWDB				BIT(1)
+
 enum dbgp_flag_e {
 	FQOS = 0,
 	FTX = 1,
diff --git a/drivers/net/wireless/rtlwifi/efuse.c b/drivers/net/wireless/rtlwifi/efuse.c
index 8e2f9af..9e38941 100644
--- a/drivers/net/wireless/rtlwifi/efuse.c
+++ b/drivers/net/wireless/rtlwifi/efuse.c
@@ -35,8 +35,6 @@ static const u8 MAX_PGPKT_SIZE = 9;
 static const u8 PGPKT_DATA_SIZE = 8;
 static const int EFUSE_MAX_SIZE = 512;
 
-static const u8 EFUSE_OOB_PROTECT_BYTES = 15;
-
 static const struct efuse_map RTL8712_SDIO_EFUSE_TABLE[] = {
 	{0, 0, 0, 2},
 	{0, 1, 0, 2},
@@ -240,6 +238,7 @@ void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf)
 	u8 rtemp8[1];
 	u16 efuse_addr = 0;
 	u8 offset, wren;
+	u8 u1temp = 0;
 	u16 i;
 	u16 j;
 	const u16 efuse_max_section =
@@ -285,10 +284,31 @@ void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf)
 	}
 
 	while ((*rtemp8 != 0xFF) && (efuse_addr < efuse_len)) {
-		offset = ((*rtemp8 >> 4) & 0x0f);
+		/*  Check PG header for section num.  */
+		if ((*rtemp8 & 0x1F) == 0x0F) {/* extended header */
+			u1temp = ((*rtemp8 & 0xE0) >> 5);
+			read_efuse_byte(hw, efuse_addr, rtemp8);
 
-		if (offset < efuse_max_section) {
+			if ((*rtemp8 & 0x0F) == 0x0F) {
+				efuse_addr++;
+				read_efuse_byte(hw, efuse_addr, rtemp8);
+
+				if (*rtemp8 != 0xFF &&
+				    (efuse_addr < efuse_len)) {
+					efuse_addr++;
+				}
+				continue;
+			} else {
+				offset = ((*rtemp8 & 0xF0) >> 1) | u1temp;
+				wren = (*rtemp8 & 0x0F);
+				efuse_addr++;
+			}
+		} else {
+			offset = ((*rtemp8 >> 4) & 0x0f);
 			wren = (*rtemp8 & 0x0f);
+		}
+
+		if (offset < efuse_max_section) {
 			RTPRINT(rtlpriv, FEEPROM, EFUSE_READ_ALL,
 				"offset-%d Worden=%x\n", offset, wren);
 
@@ -391,7 +411,8 @@ bool efuse_shadow_update_chk(struct ieee80211_hw *hw)
 	efuse_used = rtlefuse->efuse_usedbytes;
 
 	if ((totalbytes + efuse_used) >=
-	    (EFUSE_MAX_SIZE - EFUSE_OOB_PROTECT_BYTES))
+	    (EFUSE_MAX_SIZE -
+	     rtlpriv->cfg->maps[EFUSE_OOB_PROTECT_BYTES_LEN]))
 		result = false;
 
 	RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD,
@@ -932,8 +953,8 @@ static int efuse_pg_packet_write(struct ieee80211_hw *hw,
 	u8 badworden = 0x0F;
 	static int repeat_times;
 
-	if (efuse_get_current_size(hw) >=
-	    (EFUSE_MAX_SIZE - EFUSE_OOB_PROTECT_BYTES)) {
+	if (efuse_get_current_size(hw) >= (EFUSE_MAX_SIZE -
+	    rtlpriv->cfg->maps[EFUSE_OOB_PROTECT_BYTES_LEN])) {
 		RTPRINT(rtlpriv, FEEPROM, EFUSE_PG,
 			"efuse_pg_packet_write error\n");
 		return false;
@@ -949,8 +970,8 @@ static int efuse_pg_packet_write(struct ieee80211_hw *hw,
 
 	RTPRINT(rtlpriv, FEEPROM, EFUSE_PG,  "efuse Power ON\n");
 
-	while (continual && (efuse_addr <
-	       (EFUSE_MAX_SIZE - EFUSE_OOB_PROTECT_BYTES))) {
+	while (continual && (efuse_addr < (EFUSE_MAX_SIZE -
+	       rtlpriv->cfg->maps[EFUSE_OOB_PROTECT_BYTES_LEN]))) {
 
 		if (write_state == PG_STATE_HEADER) {
 			badworden = 0x0F;
@@ -1003,7 +1024,8 @@ static int efuse_pg_packet_write(struct ieee80211_hw *hw,
 		}
 	}
 
-	if (efuse_addr >= (EFUSE_MAX_SIZE - EFUSE_OOB_PROTECT_BYTES)) {
+	if (efuse_addr >= (EFUSE_MAX_SIZE -
+	    rtlpriv->cfg->maps[EFUSE_OOB_PROTECT_BYTES_LEN])) {
 		RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD,
 			 "efuse_addr(%#x) Out of size!!\n", efuse_addr);
 	}
@@ -1102,8 +1124,11 @@ static void efuse_power_switch(struct ieee80211_hw *hw, u8 write, u8 pwrstate)
 	u8 tempval;
 	u16 tmpV16;
 
-	if (pwrstate && (rtlhal->hw_type !=
-		HARDWARE_TYPE_RTL8192SE)) {
+	if (pwrstate && (rtlhal->hw_type != HARDWARE_TYPE_RTL8192SE)) {
+		if (rtlhal->hw_type == HARDWARE_TYPE_RTL8188EE)
+			rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_ACCESS],
+				       0x69);
+
 		tmpV16 = rtl_read_word(rtlpriv,
 				       rtlpriv->cfg->maps[SYS_ISO_CTRL]);
 		if (!(tmpV16 & rtlpriv->cfg->maps[EFUSE_PWC_EV12V])) {
@@ -1153,6 +1178,10 @@ static void efuse_power_switch(struct ieee80211_hw *hw, u8 write, u8 pwrstate)
 		}
 
 	} else {
+		if (rtlhal->hw_type == HARDWARE_TYPE_RTL8188EE)
+			rtl_write_byte(rtlpriv,
+				       rtlpriv->cfg->maps[EFUSE_ACCESS], 0);
+
 		if (write) {
 			tempval = rtl_read_byte(rtlpriv,
 						rtlpriv->cfg->maps[EFUSE_TEST] +
diff --git a/drivers/net/wireless/rtlwifi/efuse.h b/drivers/net/wireless/rtlwifi/efuse.h
index 2bdea9a..395a326 100644
--- a/drivers/net/wireless/rtlwifi/efuse.h
+++ b/drivers/net/wireless/rtlwifi/efuse.h
@@ -32,7 +32,6 @@
 
 #define EFUSE_IC_ID_OFFSET		506
 
-#define EFUSE_REAL_CONTENT_LEN		512
 #define EFUSE_MAP_LEN			128
 #define EFUSE_MAX_WORD_UNIT		4
 
diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c
index 4261e8e..999ffc1 100644
--- a/drivers/net/wireless/rtlwifi/pci.c
+++ b/drivers/net/wireless/rtlwifi/pci.c
@@ -59,7 +59,7 @@ static u8 _rtl_mac_to_hwqueue(struct ieee80211_hw *hw,
 
 	if (unlikely(ieee80211_is_beacon(fc)))
 		return BEACON_QUEUE;
-	if (ieee80211_is_mgmt(fc))
+	if (ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc))
 		return MGNT_QUEUE;
 	if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192SE)
 		if (ieee80211_is_nullfunc(fc))
@@ -271,9 +271,6 @@ static void rtl_pci_enable_aspm(struct ieee80211_hw *hw)
 	struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
 	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
-	u8 pcibridge_busnum = pcipriv->ndis_adapter.pcibridge_busnum;
-	u8 pcibridge_devnum = pcipriv->ndis_adapter.pcibridge_devnum;
-	u8 pcibridge_funcnum = pcipriv->ndis_adapter.pcibridge_funcnum;
 	u8 pcibridge_vendor = pcipriv->ndis_adapter.pcibridge_vendor;
 	u8 num4bytes = pcipriv->ndis_adapter.num4bytes;
 	u16 aspmlevel;
@@ -302,8 +299,7 @@ static void rtl_pci_enable_aspm(struct ieee80211_hw *hw)
 			      u_pcibridge_aspmsetting);
 
 	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
-		 "PlatformEnableASPM():PciBridge busnumber[%x], DevNumbe[%x], funcnumber[%x], Write reg[%x] = %x\n",
-		 pcibridge_busnum, pcibridge_devnum, pcibridge_funcnum,
+		 "PlatformEnableASPM(): Write reg[%x] = %x\n",
 		 (pcipriv->ndis_adapter.pcibridge_pciehdr_offset + 0x10),
 		 u_pcibridge_aspmsetting);
 
@@ -349,6 +345,49 @@ static bool rtl_pci_get_amd_l1_patch(struct ieee80211_hw *hw)
 	return status;
 }
 
+static bool rtl_pci_check_buddy_priv(struct ieee80211_hw *hw,
+				     struct rtl_priv **buddy_priv)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
+	bool find_buddy_priv = false;
+	struct rtl_priv *tpriv = NULL;
+	struct rtl_pci_priv *tpcipriv = NULL;
+
+	if (!list_empty(&rtlpriv->glb_var->glb_priv_list)) {
+		list_for_each_entry(tpriv, &rtlpriv->glb_var->glb_priv_list,
+				    list) {
+			if (tpriv) {
+				tpcipriv = (struct rtl_pci_priv *)tpriv->priv;
+				RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+					 "pcipriv->ndis_adapter.funcnumber %x\n",
+					pcipriv->ndis_adapter.funcnumber);
+				RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+					 "tpcipriv->ndis_adapter.funcnumber %x\n",
+					tpcipriv->ndis_adapter.funcnumber);
+
+				if ((pcipriv->ndis_adapter.busnumber ==
+				     tpcipriv->ndis_adapter.busnumber) &&
+				    (pcipriv->ndis_adapter.devnumber ==
+				    tpcipriv->ndis_adapter.devnumber) &&
+				    (pcipriv->ndis_adapter.funcnumber !=
+				    tpcipriv->ndis_adapter.funcnumber)) {
+					find_buddy_priv = true;
+					break;
+				}
+			}
+		}
+	}
+
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+		 "find_buddy_priv %d\n", find_buddy_priv);
+
+	if (find_buddy_priv)
+		*buddy_priv = tpriv;
+
+	return find_buddy_priv;
+}
+
 static void rtl_pci_get_linkcontrol_field(struct ieee80211_hw *hw)
 {
 	struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
@@ -420,17 +459,14 @@ static void _rtl_pci_io_handler_init(struct device *dev,
 
 }
 
-static void _rtl_pci_io_handler_release(struct ieee80211_hw *hw)
-{
-}
-
 static bool _rtl_update_earlymode_info(struct ieee80211_hw *hw,
 		struct sk_buff *skb, struct rtl_tcb_desc *tcb_desc, u8 tid)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-	u8 additionlen = FCS_LEN;
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 	struct sk_buff *next_skb;
+	u8 additionlen = FCS_LEN;
 
 	/* here open is 4, wep/tkip is 8, aes is 12*/
 	if (info->control.hw_key)
@@ -455,7 +491,7 @@ static bool _rtl_update_earlymode_info(struct ieee80211_hw *hw,
 				      next_skb))
 			break;
 
-		if (tcb_desc->empkt_num >= 5)
+		if (tcb_desc->empkt_num >= rtlhal->max_earlymode_num)
 			break;
 	}
 	spin_unlock_bh(&rtlpriv->locks.waitq_lock);
@@ -471,11 +507,17 @@ static void _rtl_pci_tx_chk_waitq(struct ieee80211_hw *hw)
 	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
 	struct sk_buff *skb = NULL;
 	struct ieee80211_tx_info *info = NULL;
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 	int tid;
 
 	if (!rtlpriv->rtlhal.earlymode_enable)
 		return;
 
+	if (rtlpriv->dm.supp_phymode_switch &&
+	    (rtlpriv->easy_concurrent_ctl.switch_in_process ||
+	    (rtlpriv->buddy_priv &&
+	    rtlpriv->buddy_priv->easy_concurrent_ctl.switch_in_process)))
+		return;
 	/* we juse use em for BE/BK/VI/VO */
 	for (tid = 7; tid >= 0; tid--) {
 		u8 hw_queue = ac_to_hwq[rtl_tid_to_ac(tid)];
@@ -487,7 +529,8 @@ static void _rtl_pci_tx_chk_waitq(struct ieee80211_hw *hw)
 
 			spin_lock_bh(&rtlpriv->locks.waitq_lock);
 			if (!skb_queue_empty(&mac->skb_waitq[tid]) &&
-			   (ring->entries - skb_queue_len(&ring->queue) > 5)) {
+			    (ring->entries - skb_queue_len(&ring->queue) >
+			     rtlhal->max_earlymode_num)) {
 				skb = skb_dequeue(&mac->skb_waitq[tid]);
 			} else {
 				spin_unlock_bh(&rtlpriv->locks.waitq_lock);
@@ -525,9 +568,8 @@ static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio)
 		u8 own = (u8) rtlpriv->cfg->ops->get_desc((u8 *) entry, true,
 							  HW_DESC_OWN);
 
-		/*
-		 *beacon packet will only use the first
-		 *descriptor defautly,and the own may not
+		/*beacon packet will only use the first
+		 *descriptor by defaut, and the own may not
 		 *be cleared by the hardware
 		 */
 		if (own)
@@ -558,8 +600,9 @@ static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio)
 		}
 
 		/* for sw LPS, just after NULL skb send out, we can
-		 * sure AP kown we are sleeped, our we should not let
-		 * rf to sleep*/
+		 * sure AP knows we are sleeping, we should not let
+		 * rf sleep
+		 */
 		fc = rtl_get_fc(skb);
 		if (ieee80211_is_nullfunc(fc)) {
 			if (ieee80211_has_pm(fc)) {
@@ -569,6 +612,15 @@ static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio)
 				rtlpriv->psc.state_inap = false;
 			}
 		}
+		if (ieee80211_is_action(fc)) {
+			struct ieee80211_mgmt *action_frame =
+				(struct ieee80211_mgmt *)skb->data;
+			if (action_frame->u.action.u.ht_smps.action ==
+			    WLAN_HT_ACTION_SMPS) {
+				dev_kfree_skb(skb);
+				goto tx_status_ok;
+			}
+		}
 
 		/* update tid tx pkt num */
 		tid = rtl_get_tid(skb);
@@ -602,7 +654,8 @@ tx_status_ok:
 	if (((rtlpriv->link_info.num_rx_inperiod +
 		rtlpriv->link_info.num_tx_inperiod) > 8) ||
 		(rtlpriv->link_info.num_rx_inperiod > 2)) {
-		schedule_work(&rtlpriv->works.lps_leave_work);
+		rtlpriv->enter_ps = false;
+		schedule_work(&rtlpriv->works.lps_change_work);
 	}
 }
 
@@ -637,6 +690,10 @@ static void _rtl_receive_one(struct ieee80211_hw *hw, struct sk_buff *skb,
 			rtlpriv->link_info.num_rx_inperiod++;
 	}
 
+	/* static bcn for roaming */
+	rtl_beacon_statistic(hw, skb);
+	rtl_p2p_info(hw, (void *)skb->data, skb->len);
+
 	/* for sw lps */
 	rtl_swlps_beacon(hw, (void *)skb->data, skb->len);
 	rtl_recognize_peer(hw, (void *)skb->data, skb->len);
@@ -727,9 +784,10 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)
 		_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)) {
-			schedule_work(&rtlpriv->works.lps_leave_work);
+		      rtlpriv->link_info.num_tx_inperiod) > 8) ||
+		      (rtlpriv->link_info.num_rx_inperiod > 2)) {
+			rtlpriv->enter_ps = false;
+			schedule_work(&rtlpriv->works.lps_change_work);
 		}
 
 		dev_kfree_skb_any(skb);
@@ -803,7 +861,7 @@ static irqreturn_t _rtl_pci_interrupt(int irq, void *dev_id)
 		RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, "beacon interrupt!\n");
 	}
 
-	if (inta & rtlpriv->cfg->maps[RTL_IMR_BcnInt]) {
+	if (inta & rtlpriv->cfg->maps[RTL_IMR_BCNINT]) {
 		RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE,
 			 "prepare beacon for interrupt!\n");
 		tasklet_schedule(&rtlpriv->works.irq_prepare_bcn_tasklet);
@@ -884,6 +942,16 @@ static irqreturn_t _rtl_pci_interrupt(int irq, void *dev_id)
 		_rtl_pci_rx_interrupt(hw);
 	}
 
+	/*fw related*/
+	if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723AE) {
+		if (inta & rtlpriv->cfg->maps[RTL_IMR_C2HCMD]) {
+			RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE,
+				 "firmware interrupt!\n");
+			queue_delayed_work(rtlpriv->works.rtl_wq,
+					   &rtlpriv->works.fwevt_wq, 0);
+		}
+	}
+
 	if (rtlpriv->rtlhal.earlymode_enable)
 		tasklet_schedule(&rtlpriv->works.irq_tasklet);
 
@@ -939,13 +1007,17 @@ static void _rtl_pci_prepare_bcn_tasklet(struct ieee80211_hw *hw)
 	return;
 }
 
-static void rtl_lps_leave_work_callback(struct work_struct *work)
+static void rtl_lps_change_work_callback(struct work_struct *work)
 {
 	struct rtl_works *rtlworks =
-	    container_of(work, struct rtl_works, lps_leave_work);
+	    container_of(work, struct rtl_works, lps_change_work);
 	struct ieee80211_hw *hw = rtlworks->hw;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
 
-	rtl_lps_leave(hw);
+	if (rtlpriv->enter_ps)
+		rtl_lps_enter(hw);
+	else
+		rtl_lps_leave(hw);
 }
 
 static void _rtl_pci_init_trx_var(struct ieee80211_hw *hw)
@@ -1009,7 +1081,8 @@ 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);
-	INIT_WORK(&rtlpriv->works.lps_leave_work, rtl_lps_leave_work_callback);
+	INIT_WORK(&rtlpriv->works.lps_change_work,
+		  rtl_lps_change_work_callback);
 }
 
 static int _rtl_pci_init_tx_ring(struct ieee80211_hw *hw,
@@ -1458,10 +1531,14 @@ static void rtl_pci_flush(struct ieee80211_hw *hw, bool drop)
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 	u16 i = 0;
 	int queue_id;
 	struct rtl8192_tx_ring *ring;
 
+	if (mac->skip_scan)
+		return;
+
 	for (queue_id = RTL_PCI_MAX_TX_QUEUE_COUNT - 1; queue_id >= 0;) {
 		u32 queue_len;
 		ring = &pcipriv->dev.tx_ring[queue_id];
@@ -1491,7 +1568,7 @@ static void rtl_pci_deinit(struct ieee80211_hw *hw)
 
 	synchronize_irq(rtlpci->pdev->irq);
 	tasklet_kill(&rtlpriv->works.irq_tasklet);
-	cancel_work_sync(&rtlpriv->works.lps_leave_work);
+	cancel_work_sync(&rtlpriv->works.lps_change_work);
 
 	flush_workqueue(rtlpriv->works.rtl_wq);
 	destroy_workqueue(rtlpriv->works.rtl_wq);
@@ -1566,7 +1643,7 @@ static void rtl_pci_stop(struct ieee80211_hw *hw)
 	set_hal_stop(rtlhal);
 
 	rtlpriv->cfg->ops->disable_interrupt(hw);
-	cancel_work_sync(&rtlpriv->works.lps_leave_work);
+	cancel_work_sync(&rtlpriv->works.lps_change_work);
 
 	spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flags);
 	while (ppsc->rfchange_inprogress) {
@@ -1673,6 +1750,10 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev,
 		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
 			 "8192D PCI-E is found - vid/did=%x/%x\n",
 			 venderid, deviceid);
+	} else if (deviceid == RTL_PCI_8188EE_DID) {
+		rtlhal->hw_type = HARDWARE_TYPE_RTL8188EE;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+			 "Find adapter, Hardware type is 8188EE\n");
 	} else {
 		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
 			 "Err: Unknown device - vid/did=%x/%x\n",
@@ -1704,6 +1785,9 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev,
 	pcipriv->ndis_adapter.devnumber = PCI_SLOT(pdev->devfn);
 	pcipriv->ndis_adapter.funcnumber = PCI_FUNC(pdev->devfn);
 
+	/* some ARM have no bridge_pdev and will crash here
+	 * so we should check if bridge_pdev is NULL
+	 */
 	if (bridge_pdev) {
 		/*find bridge info if available */
 		pcipriv->ndis_adapter.pcibridge_vendorid = bridge_pdev->vendor;
@@ -1758,6 +1842,7 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev,
 		 pcipriv->ndis_adapter.amd_l1_patch);
 
 	rtl_pci_parse_configuration(pdev, hw);
+	list_add_tail(&rtlpriv->list, &rtlpriv->glb_var->glb_priv_list);
 
 	return true;
 }
@@ -1804,6 +1889,7 @@ int rtl_pci_probe(struct pci_dev *pdev,
 	pci_set_drvdata(pdev, hw);
 
 	rtlpriv = hw->priv;
+	rtlpriv->hw = hw;
 	pcipriv = (void *)rtlpriv->priv;
 	pcipriv->dev.pdev = pdev;
 	init_completion(&rtlpriv->firmware_loading_complete);
@@ -1812,6 +1898,7 @@ int rtl_pci_probe(struct pci_dev *pdev,
 	rtlpriv->rtlhal.interface = INTF_PCI;
 	rtlpriv->cfg = (struct rtl_hal_cfg *)(id->driver_data);
 	rtlpriv->intf_ops = &rtl_pci_ops;
+	rtlpriv->glb_var = &global_var;
 
 	/*
 	 *init dbgp flags before all
@@ -1916,7 +2003,6 @@ int rtl_pci_probe(struct pci_dev *pdev,
 
 fail3:
 	rtl_deinit_core(hw);
-	_rtl_pci_io_handler_release(hw);
 
 	if (rtlpriv->io.pci_mem_start != 0)
 		pci_iounmap(pdev, (void __iomem *)rtlpriv->io.pci_mem_start);
@@ -1965,14 +2051,15 @@ void rtl_pci_disconnect(struct pci_dev *pdev)
 
 	rtl_pci_deinit(hw);
 	rtl_deinit_core(hw);
-	_rtl_pci_io_handler_release(hw);
 	rtlpriv->cfg->ops->deinit_sw_vars(hw);
 
 	if (rtlpci->irq_alloc) {
+		synchronize_irq(rtlpci->pdev->irq);
 		free_irq(rtlpci->pdev->irq, hw);
 		rtlpci->irq_alloc = 0;
 	}
 
+	list_del(&rtlpriv->list);
 	if (rtlpriv->io.pci_mem_start != 0) {
 		pci_iounmap(pdev, (void __iomem *)rtlpriv->io.pci_mem_start);
 		pci_release_regions(pdev);
@@ -2034,6 +2121,7 @@ struct rtl_intf_ops rtl_pci_ops = {
 	.read_efuse_byte = read_efuse_byte,
 	.adapter_start = rtl_pci_start,
 	.adapter_stop = rtl_pci_stop,
+	.check_buddy_priv = rtl_pci_check_buddy_priv,
 	.adapter_tx = rtl_pci_tx,
 	.flush = rtl_pci_flush,
 	.reset_trx_ring = rtl_pci_reset_trx_ring,
diff --git a/drivers/net/wireless/rtlwifi/pci.h b/drivers/net/wireless/rtlwifi/pci.h
index 65b08f5..d3262ec 100644
--- a/drivers/net/wireless/rtlwifi/pci.h
+++ b/drivers/net/wireless/rtlwifi/pci.h
@@ -94,6 +94,7 @@
 #define RTL_PCI_8192CU_DID	0x8191	/*8192ce */
 #define RTL_PCI_8192DE_DID	0x8193	/*8192de */
 #define RTL_PCI_8192DE_DID2	0x002B	/*92DE*/
+#define RTL_PCI_8188EE_DID	0x8179  /*8188ee*/
 
 /*8192 support 16 pages of IO registers*/
 #define RTL_MEM_MAPPED_IO_RANGE_8190PCI		0x1000
@@ -175,6 +176,7 @@ struct rtl_pci {
 	/*irq */
 	u8 irq_alloc;
 	u32 irq_mask[2];
+	u32 sys_irq_mask;
 
 	/*Bcn control register setting */
 	u32 reg_bcn_ctrl_val;
diff --git a/drivers/net/wireless/rtlwifi/ps.c b/drivers/net/wireless/rtlwifi/ps.c
index 13ad33e..884bcea 100644
--- a/drivers/net/wireless/rtlwifi/ps.c
+++ b/drivers/net/wireless/rtlwifi/ps.c
@@ -180,6 +180,9 @@ void rtl_ips_nic_off_wq_callback(void *data)
 		return;
 	}
 
+	if (mac->p2p_in_use)
+		return;
+
 	if (mac->link_state > MAC80211_NOLINK)
 		return;
 
@@ -189,6 +192,9 @@ void rtl_ips_nic_off_wq_callback(void *data)
 	if (rtlpriv->sec.being_setkey)
 		return;
 
+	if (rtlpriv->cfg->ops->bt_coex_off_before_lps)
+		rtlpriv->cfg->ops->bt_coex_off_before_lps(hw);
+
 	if (ppsc->inactiveps) {
 		rtstate = ppsc->rfpwr_state;
 
@@ -231,6 +237,9 @@ void rtl_ips_nic_off(struct ieee80211_hw *hw)
 			   &rtlpriv->works.ips_nic_off_wq, MSECS(100));
 }
 
+/* NOTICE: any opmode should exc nic_on, or disable without
+ * nic_on may something wrong, like adhoc TP
+ */
 void rtl_ips_nic_on(struct ieee80211_hw *hw)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
@@ -299,7 +308,7 @@ static void rtl_lps_set_psmode(struct ieee80211_hw *hw, u8 rt_psmode)
 	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));
-	u8 rpwm_val, fw_pwrmode;
+	bool enter_fwlps;
 
 	if (mac->opmode == NL80211_IFTYPE_ADHOC)
 		return;
@@ -324,43 +333,31 @@ static void rtl_lps_set_psmode(struct ieee80211_hw *hw, u8 rt_psmode)
 	 */
 
 	if ((ppsc->fwctrl_lps) && ppsc->report_linked) {
-		bool fw_current_inps;
 		if (ppsc->dot11_psmode == EACTIVE) {
 			RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
 				 "FW LPS leave ps_mode:%x\n",
 				 FW_PS_ACTIVE_MODE);
-
-			rpwm_val = 0x0C;	/* RF on */
-			fw_pwrmode = FW_PS_ACTIVE_MODE;
-			rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM,
-					&rpwm_val);
+			enter_fwlps = false;
+			ppsc->pwr_mode = FW_PS_ACTIVE_MODE;
+			ppsc->smart_ps = 0;
 			rtlpriv->cfg->ops->set_hw_reg(hw,
-					HW_VAR_H2C_FW_PWRMODE,
-					&fw_pwrmode);
-			fw_current_inps = false;
-
-			rtlpriv->cfg->ops->set_hw_reg(hw,
-					HW_VAR_FW_PSMODE_STATUS,
-					(u8 *) (&fw_current_inps));
+						HW_VAR_FW_LPS_ACTION,
+						(u8 *)(&enter_fwlps));
+			if (ppsc->p2p_ps_info.opp_ps)
+				rtl_p2p_ps_cmd(hw, P2P_PS_ENABLE);
 
 		} else {
 			if (rtl_get_fwlps_doze(hw)) {
 				RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
 					 "FW LPS enter ps_mode:%x\n",
 					 ppsc->fwctrl_psmode);
-
-				rpwm_val = 0x02;	/* RF off */
-				fw_current_inps = true;
+				enter_fwlps = true;
+				ppsc->pwr_mode = ppsc->fwctrl_psmode;
+				ppsc->smart_ps = 2;
 				rtlpriv->cfg->ops->set_hw_reg(hw,
-						HW_VAR_FW_PSMODE_STATUS,
-						(u8 *) (&fw_current_inps));
-				rtlpriv->cfg->ops->set_hw_reg(hw,
-						HW_VAR_H2C_FW_PWRMODE,
-						&ppsc->fwctrl_psmode);
+							HW_VAR_FW_LPS_ACTION,
+							(u8 *)(&enter_fwlps));
 
-				rtlpriv->cfg->ops->set_hw_reg(hw,
-						HW_VAR_SET_RPWM,
-						&rpwm_val);
 			} else {
 				/* Reset the power save related parameters. */
 				ppsc->dot11_psmode = EACTIVE;
@@ -642,3 +639,286 @@ void rtl_swlps_wq_callback(void *data)
 		rtlpriv->psc.state = ps;
 	}
 }
+
+static void rtl_p2p_noa_ie(struct ieee80211_hw *hw, void *data,
+			   unsigned int len)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct ieee80211_mgmt *mgmt = (void *)data;
+	struct rtl_p2p_ps_info *p2pinfo = &(rtlpriv->psc.p2p_ps_info);
+	u8 *pos, *end, *ie;
+	u16 noa_len;
+	static u8 p2p_oui_ie_type[4] = {0x50, 0x6f, 0x9a, 0x09};
+	u8 noa_num, index, i, noa_index = 0;
+	bool find_p2p_ie = false , find_p2p_ps_ie = false;
+	pos = (u8 *)mgmt->u.beacon.variable;
+	end = data + len;
+	ie = NULL;
+
+	while (pos + 1 < end) {
+		if (pos + 2 + pos[1] > end)
+			return;
+
+		if (pos[0] == 221 && pos[1] > 4) {
+			if (memcmp(&pos[2], p2p_oui_ie_type, 4) == 0) {
+				ie = pos + 2+4;
+				break;
+			}
+		}
+		pos += 2 + pos[1];
+	}
+
+	if (ie == NULL)
+		return;
+	find_p2p_ie = true;
+	/*to find noa ie*/
+	while (ie + 1 < end) {
+		noa_len = READEF2BYTE(&ie[1]);
+		if (ie + 3 + ie[1] > end)
+			return;
+
+		if (ie[0] == 12) {
+			find_p2p_ps_ie = true;
+			if ((noa_len - 2) % 13 != 0) {
+				RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+					 "P2P notice of absence: invalid length.%d\n",
+					 noa_len);
+				return;
+			} else {
+				noa_num = (noa_len - 2) / 13;
+			}
+			noa_index = ie[3];
+			if (rtlpriv->psc.p2p_ps_info.p2p_ps_mode ==
+			    P2P_PS_NONE || noa_index != p2pinfo->noa_index) {
+				RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD,
+					 "update NOA ie.\n");
+				p2pinfo->noa_index = noa_index;
+				p2pinfo->opp_ps = (ie[4] >> 7);
+				p2pinfo->ctwindow = ie[4] & 0x7F;
+				p2pinfo->noa_num = noa_num;
+				index = 5;
+				for (i = 0; i < noa_num; i++) {
+					p2pinfo->noa_count_type[i] =
+						 READEF1BYTE(ie+index);
+					index += 1;
+					p2pinfo->noa_duration[i] =
+						 READEF4BYTE(ie+index);
+					index += 4;
+					p2pinfo->noa_interval[i] =
+						 READEF4BYTE(ie+index);
+					index += 4;
+					p2pinfo->noa_start_time[i] =
+						 READEF4BYTE(ie+index);
+					index += 4;
+				}
+
+				if (p2pinfo->opp_ps == 1) {
+					p2pinfo->p2p_ps_mode = P2P_PS_CTWINDOW;
+					/* Driver should wait LPS entering
+					 * CTWindow
+					 */
+					if (rtlpriv->psc.fw_current_inpsmode)
+						rtl_p2p_ps_cmd(hw,
+							       P2P_PS_ENABLE);
+				} else if (p2pinfo->noa_num > 0) {
+					p2pinfo->p2p_ps_mode = P2P_PS_NOA;
+					rtl_p2p_ps_cmd(hw, P2P_PS_ENABLE);
+				} else if (p2pinfo->p2p_ps_mode > P2P_PS_NONE) {
+					rtl_p2p_ps_cmd(hw, P2P_PS_DISABLE);
+				}
+			}
+		break;
+		}
+		ie += 3 + noa_len;
+	}
+
+	if (find_p2p_ie == true) {
+		if ((p2pinfo->p2p_ps_mode > P2P_PS_NONE) &&
+		    (find_p2p_ps_ie == false))
+			rtl_p2p_ps_cmd(hw, P2P_PS_DISABLE);
+	}
+}
+
+static void rtl_p2p_action_ie(struct ieee80211_hw *hw, void *data,
+			      unsigned int len)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct ieee80211_mgmt *mgmt = (void *)data;
+	struct rtl_p2p_ps_info *p2pinfo = &(rtlpriv->psc.p2p_ps_info);
+	u8 noa_num, index, i, noa_index = 0;
+	u8 *pos, *end, *ie;
+	u16 noa_len;
+	static u8 p2p_oui_ie_type[4] = {0x50, 0x6f, 0x9a, 0x09};
+
+	pos = (u8 *)&mgmt->u.action.category;
+	end = data + len;
+	ie = NULL;
+
+	if (pos[0] == 0x7f) {
+		if (memcmp(&pos[1], p2p_oui_ie_type, 4) == 0)
+			ie = pos + 3+4;
+	}
+
+	if (ie == NULL)
+		return;
+
+	RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "action frame find P2P IE.\n");
+	/*to find noa ie*/
+	while (ie + 1 < end) {
+		noa_len = READEF2BYTE(&ie[1]);
+		if (ie + 3 + ie[1] > end)
+			return;
+
+		if (ie[0] == 12) {
+			RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "find NOA IE.\n");
+			RT_PRINT_DATA(rtlpriv, COMP_FW, DBG_LOUD, "noa ie ",
+				      ie, noa_len);
+			if ((noa_len - 2) % 13 != 0) {
+				RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD,
+					 "P2P notice of absence: invalid length.%d\n",
+					 noa_len);
+				return;
+			} else {
+				noa_num = (noa_len - 2) / 13;
+			}
+			noa_index = ie[3];
+			if (rtlpriv->psc.p2p_ps_info.p2p_ps_mode ==
+			    P2P_PS_NONE || noa_index != p2pinfo->noa_index) {
+				p2pinfo->noa_index = noa_index;
+				p2pinfo->opp_ps = (ie[4] >> 7);
+				p2pinfo->ctwindow = ie[4] & 0x7F;
+				p2pinfo->noa_num = noa_num;
+				index = 5;
+				for (i = 0; i < noa_num; i++) {
+					p2pinfo->noa_count_type[i] =
+							 READEF1BYTE(ie+index);
+					index += 1;
+					p2pinfo->noa_duration[i] =
+							 READEF4BYTE(ie+index);
+					index += 4;
+					p2pinfo->noa_interval[i] =
+							 READEF4BYTE(ie+index);
+					index += 4;
+					p2pinfo->noa_start_time[i] =
+							 READEF4BYTE(ie+index);
+					index += 4;
+				}
+
+				if (p2pinfo->opp_ps == 1) {
+					p2pinfo->p2p_ps_mode = P2P_PS_CTWINDOW;
+					/* Driver should wait LPS entering
+					 * CTWindow
+					 */
+					if (rtlpriv->psc.fw_current_inpsmode)
+						rtl_p2p_ps_cmd(hw,
+							       P2P_PS_ENABLE);
+				} else if (p2pinfo->noa_num > 0) {
+					p2pinfo->p2p_ps_mode = P2P_PS_NOA;
+					rtl_p2p_ps_cmd(hw, P2P_PS_ENABLE);
+				} else if (p2pinfo->p2p_ps_mode > P2P_PS_NONE) {
+					rtl_p2p_ps_cmd(hw, P2P_PS_DISABLE);
+				}
+			}
+		break;
+		}
+		ie += 3 + noa_len;
+	}
+}
+
+void rtl_p2p_ps_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw));
+	struct rtl_p2p_ps_info  *p2pinfo = &(rtlpriv->psc.p2p_ps_info);
+
+	RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, " p2p state %x\n", p2p_ps_state);
+	switch (p2p_ps_state) {
+	case P2P_PS_DISABLE:
+		p2pinfo->p2p_ps_state = p2p_ps_state;
+		rtlpriv->cfg->ops->set_hw_reg(hw,
+				 HW_VAR_H2C_FW_P2P_PS_OFFLOAD,
+				 (u8 *)(&p2p_ps_state));
+
+		p2pinfo->noa_index = 0;
+		p2pinfo->ctwindow = 0;
+		p2pinfo->opp_ps = 0;
+		p2pinfo->noa_num = 0;
+		p2pinfo->p2p_ps_mode = P2P_PS_NONE;
+		if (rtlps->fw_current_inpsmode == true) {
+			if (rtlps->smart_ps == 0) {
+				rtlps->smart_ps = 2;
+				rtlpriv->cfg->ops->set_hw_reg(hw,
+					 HW_VAR_H2C_FW_PWRMODE,
+					 (u8 *)(&rtlps->pwr_mode));
+			}
+		}
+		break;
+	case P2P_PS_ENABLE:
+		if (p2pinfo->p2p_ps_mode > P2P_PS_NONE) {
+			p2pinfo->p2p_ps_state = p2p_ps_state;
+
+			if (p2pinfo->ctwindow > 0) {
+				if (rtlps->smart_ps != 0) {
+					rtlps->smart_ps = 0;
+					rtlpriv->cfg->ops->set_hw_reg(hw,
+						 HW_VAR_H2C_FW_PWRMODE,
+						 (u8 *)(&rtlps->pwr_mode));
+				}
+			}
+			rtlpriv->cfg->ops->set_hw_reg(hw,
+				 HW_VAR_H2C_FW_P2P_PS_OFFLOAD,
+				 (u8 *)(&p2p_ps_state));
+		}
+		break;
+	case P2P_PS_SCAN:
+	case P2P_PS_SCAN_DONE:
+	case P2P_PS_ALLSTASLEEP:
+		if (p2pinfo->p2p_ps_mode > P2P_PS_NONE) {
+			p2pinfo->p2p_ps_state = p2p_ps_state;
+			rtlpriv->cfg->ops->set_hw_reg(hw,
+				 HW_VAR_H2C_FW_P2P_PS_OFFLOAD,
+				 (u8 *)(&p2p_ps_state));
+		}
+		break;
+	default:
+		break;
+	}
+	RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD,
+		 "ctwindow %x oppps %x\n", p2pinfo->ctwindow, p2pinfo->opp_ps);
+	RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD,
+		 "count %x duration %x index %x interval %x start time %x noa num %x\n",
+		 p2pinfo->noa_count_type[0], p2pinfo->noa_duration[0],
+		 p2pinfo->noa_index, p2pinfo->noa_interval[0],
+		 p2pinfo->noa_start_time[0], p2pinfo->noa_num);
+	RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "end\n");
+}
+
+void rtl_p2p_info(struct ieee80211_hw *hw, void *data, unsigned int len)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	struct ieee80211_hdr *hdr = (void *)data;
+
+	if (!mac->p2p)
+		return;
+	if (mac->link_state != MAC80211_LINKED)
+		return;
+	/* min. beacon length + FCS_LEN */
+	if (len <= 40 + FCS_LEN)
+		return;
+
+	/* and only beacons from the associated BSSID, please */
+	if (compare_ether_addr(hdr->addr3, rtlpriv->mac80211.bssid))
+		return;
+
+	/* check if this really is a beacon */
+	if (!(ieee80211_is_beacon(hdr->frame_control) ||
+	      ieee80211_is_probe_resp(hdr->frame_control) ||
+	      ieee80211_is_action(hdr->frame_control)))
+		return;
+
+	if (ieee80211_is_action(hdr->frame_control))
+		rtl_p2p_action_ie(hw, data, len - FCS_LEN);
+	else
+		rtl_p2p_noa_ie(hw, data, len - FCS_LEN);
+}
diff --git a/drivers/net/wireless/rtlwifi/ps.h b/drivers/net/wireless/rtlwifi/ps.h
index 1357856..4d682b7 100644
--- a/drivers/net/wireless/rtlwifi/ps.h
+++ b/drivers/net/wireless/rtlwifi/ps.h
@@ -47,5 +47,7 @@ void rtl_swlps_wq_callback(void *data);
 void rtl_swlps_rfon_wq_callback(void *data);
 void rtl_swlps_rf_awake(struct ieee80211_hw *hw);
 void rtl_swlps_rf_sleep(struct ieee80211_hw *hw);
+void rtl_p2p_ps_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state);
+void rtl_p2p_info(struct ieee80211_hw *hw, void *data, unsigned int len);
 
 #endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/Makefile b/drivers/net/wireless/rtlwifi/rtl8188ee/Makefile
new file mode 100644
index 0000000..01173a2
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8188ee/Makefile
@@ -0,0 +1,16 @@
+rtl8188ee-objs :=		\
+		dm.o		\
+		fw.o		\
+		hw.o		\
+		led.o		\
+		phy.o		\
+		pwrseq.o	\
+		pwrseqcmd.o	\
+		rf.o		\
+		sw.o		\
+		table.o		\
+		trx.o
+
+obj-$(CONFIG_RTL8188EE) += rtl8188ee.o
+
+ccflags-y += -I drivers/net/wireless/rtlwifi -D__CHECK_ENDIAN__
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/def.h b/drivers/net/wireless/rtlwifi/rtl8188ee/def.h
new file mode 100644
index 0000000..c764fff
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8188ee/def.h
@@ -0,0 +1,324 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2013  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_DEF_H__
+#define __RTL92C_DEF_H__
+
+#define HAL_RETRY_LIMIT_INFRA				48
+#define HAL_RETRY_LIMIT_AP_ADHOC			7
+
+#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 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 AC2QUEUEID(_AC)					(_AC)
+
+#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)
+
+#define CHIP_BONDING_IDENTIFIER(_value)	(((_value)>>22)&0x3)
+
+
+/* [15:12] IC version(CUT): A-cut=0, B-cut=1, C-cut=2, D-cut=3
+ * [7] Manufacturer: TSMC=0, UMC=1
+ * [6:4] RF type: 1T1R=0, 1T2R=1, 2T2R=2
+ * [3] Chip type: TEST=0, NORMAL=1
+ * [2:0] IC type: 81xxC=0, 8723=1, 92D=2
+ */
+#define CHIP_8723			BIT(0)
+#define CHIP_92D			BIT(1)
+#define NORMAL_CHIP			BIT(3)
+#define RF_TYPE_1T1R			(~(BIT(4)|BIT(5)|BIT(6)))
+#define RF_TYPE_1T2R			BIT(4)
+#define RF_TYPE_2T2R			BIT(5)
+#define CHIP_VENDOR_UMC			BIT(7)
+#define B_CUT_VERSION			BIT(12)
+#define C_CUT_VERSION			BIT(13)
+#define D_CUT_VERSION			((BIT(12)|BIT(13)))
+#define E_CUT_VERSION			BIT(14)
+
+
+/* MASK */
+#define IC_TYPE_MASK			(BIT(0)|BIT(1)|BIT(2))
+#define CHIP_TYPE_MASK			BIT(3)
+#define RF_TYPE_MASK			(BIT(4)|BIT(5)|BIT(6))
+#define MANUFACTUER_MASK		BIT(7)
+#define ROM_VERSION_MASK		(BIT(11)|BIT(10)|BIT(9)|BIT(8))
+#define CUT_VERSION_MASK		(BIT(15)|BIT(14)|BIT(13)|BIT(12))
+
+/* Get element */
+#define GET_CVID_IC_TYPE(version)	((version) & IC_TYPE_MASK)
+#define GET_CVID_CHIP_TYPE(version)	((version) & CHIP_TYPE_MASK)
+#define GET_CVID_RF_TYPE(version)	((version) & RF_TYPE_MASK)
+#define GET_CVID_MANUFACTUER(version)	((version) & MANUFACTUER_MASK)
+#define GET_CVID_ROM_VERSION(version)	((version) & ROM_VERSION_MASK)
+#define GET_CVID_CUT_VERSION(version)	((version) & CUT_VERSION_MASK)
+
+
+#define IS_81XXC(version)						\
+	((GET_CVID_IC_TYPE(version) == 0) ? true : false)
+#define IS_8723_SERIES(version)						\
+	((GET_CVID_IC_TYPE(version) == CHIP_8723) ? true : false)
+#define IS_92D(version)							\
+	((GET_CVID_IC_TYPE(version) == CHIP_92D) ? true : false)
+
+#define IS_NORMAL_CHIP(version)						\
+	((GET_CVID_CHIP_TYPE(version)) ? true : false)
+#define IS_NORMAL_CHIP92D(version)					\
+	((GET_CVID_CHIP_TYPE(version)) ? true : false)
+
+#define IS_1T1R(version)						\
+	((GET_CVID_RF_TYPE(version)) ? false : true)
+#define IS_1T2R(version)						\
+	((GET_CVID_RF_TYPE(version) == RF_TYPE_1T2R) ? true : false)
+#define IS_2T2R(version)						\
+	((GET_CVID_RF_TYPE(version) == RF_TYPE_2T2R) ? true : false)
+#define IS_CHIP_VENDOR_UMC(version)					\
+	((GET_CVID_MANUFACTUER(version)) ? true : false)
+
+#define IS_92C_SERIAL(version)						\
+	((IS_81XXC(version) && IS_2T2R(version)) ? true : false)
+#define IS_81xxC_VENDOR_UMC_A_CUT(version)				\
+	(IS_81XXC(version) ? ((IS_CHIP_VENDOR_UMC(version)) ?		\
+	 ((GET_CVID_CUT_VERSION(version)) ? false : true) : false) : false)
+#define IS_81xxC_VENDOR_UMC_B_CUT(version)				\
+	(IS_81XXC(version) ? (IS_CHIP_VENDOR_UMC(version) ?		\
+	((GET_CVID_CUT_VERSION(version) == B_CUT_VERSION) ? true	\
+	: false) : false) : false)
+
+enum version_8188e {
+	VERSION_TEST_CHIP_88E = 0x00,
+	VERSION_NORMAL_CHIP_88E = 0x01,
+	VERSION_UNKNOWN = 0xFF,
+};
+
+enum rx_packet_type {
+	NORMAL_RX,
+	TX_REPORT1,
+	TX_REPORT2,
+	HIS_REPORT,
+};
+
+enum rtl819x_loopback_e {
+	RTL819X_NO_LOOPBACK = 0,
+	RTL819X_MAC_LOOPBACK = 1,
+	RTL819X_DMA_LOOPBACK = 2,
+	RTL819X_CCK_LOOPBACK = 3,
+};
+
+enum rf_optype {
+	RF_OP_BY_SW_3WIRE = 0,
+	RF_OP_BY_FW,
+	RF_OP_MAX
+};
+
+enum rf_power_state {
+	RF_ON,
+	RF_OFF,
+	RF_SLEEP,
+	RF_SHUT_DOWN,
+};
+
+enum power_save_mode {
+	POWER_SAVE_MODE_ACTIVE,
+	POWER_SAVE_MODE_SAVE,
+};
+
+enum power_polocy_config {
+	POWERCFG_MAX_POWER_SAVINGS,
+	POWERCFG_GLOBAL_POWER_SAVINGS,
+	POWERCFG_LOCAL_POWER_SAVINGS,
+	POWERCFG_LENOVO,
+};
+
+enum interface_select_pci {
+	INTF_SEL1_MINICARD,
+	INTF_SEL0_PCIE,
+	INTF_SEL2_RSV,
+	INTF_SEL3_RSV,
+};
+
+enum hal_fw_c2h_cmd_id {
+	HAL_FW_C2H_CMD_Read_MACREG,
+	HAL_FW_C2H_CMD_Read_BBREG,
+	HAL_FW_C2H_CMD_Read_RFREG,
+	HAL_FW_C2H_CMD_Read_EEPROM,
+	HAL_FW_C2H_CMD_Read_EFUSE,
+	HAL_FW_C2H_CMD_Read_CAM,
+	HAL_FW_C2H_CMD_Get_BasicRate,
+	HAL_FW_C2H_CMD_Get_DataRate,
+	HAL_FW_C2H_CMD_Survey,
+	HAL_FW_C2H_CMD_SurveyDone,
+	HAL_FW_C2H_CMD_JoinBss,
+	HAL_FW_C2H_CMD_AddSTA,
+	HAL_FW_C2H_CMD_DelSTA,
+	HAL_FW_C2H_CMD_AtimDone,
+	HAL_FW_C2H_CMD_TX_Report,
+	HAL_FW_C2H_CMD_CCX_Report,
+	HAL_FW_C2H_CMD_DTM_Report,
+	HAL_FW_C2H_CMD_TX_Rate_Statistics,
+	HAL_FW_C2H_CMD_C2HLBK,
+	HAL_FW_C2H_CMD_C2HDBG,
+	HAL_FW_C2H_CMD_C2HFEEDBACK,
+	HAL_FW_C2H_CMD_MAX
+};
+
+enum wake_on_wlan_mode {
+	ewowlandisable,
+	ewakeonmagicpacketonly,
+	ewakeonpatternmatchonly,
+	ewakeonbothtypepacket
+};
+
+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_desc92c_rate {
+	DESC92C_RATE1M = 0x00,
+	DESC92C_RATE2M = 0x01,
+	DESC92C_RATE5_5M = 0x02,
+	DESC92C_RATE11M = 0x03,
+
+	DESC92C_RATE6M = 0x04,
+	DESC92C_RATE9M = 0x05,
+	DESC92C_RATE12M = 0x06,
+	DESC92C_RATE18M = 0x07,
+	DESC92C_RATE24M = 0x08,
+	DESC92C_RATE36M = 0x09,
+	DESC92C_RATE48M = 0x0a,
+	DESC92C_RATE54M = 0x0b,
+
+	DESC92C_RATEMCS0 = 0x0c,
+	DESC92C_RATEMCS1 = 0x0d,
+	DESC92C_RATEMCS2 = 0x0e,
+	DESC92C_RATEMCS3 = 0x0f,
+	DESC92C_RATEMCS4 = 0x10,
+	DESC92C_RATEMCS5 = 0x11,
+	DESC92C_RATEMCS6 = 0x12,
+	DESC92C_RATEMCS7 = 0x13,
+	DESC92C_RATEMCS8 = 0x14,
+	DESC92C_RATEMCS9 = 0x15,
+	DESC92C_RATEMCS10 = 0x16,
+	DESC92C_RATEMCS11 = 0x17,
+	DESC92C_RATEMCS12 = 0x18,
+	DESC92C_RATEMCS13 = 0x19,
+	DESC92C_RATEMCS14 = 0x1a,
+	DESC92C_RATEMCS15 = 0x1b,
+	DESC92C_RATEMCS15_SG = 0x1c,
+	DESC92C_RATEMCS32 = 0x20,
+};
+
+struct phy_sts_cck_8192s_t {
+	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;
+};
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/dm.c b/drivers/net/wireless/rtlwifi/rtl8188ee/dm.c
new file mode 100644
index 0000000..21a5cf0
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8188ee/dm.c
@@ -0,0 +1,1794 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2013  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 "../pci.h"
+#include "reg.h"
+#include "def.h"
+#include "phy.h"
+#include "dm.h"
+#include "fw.h"
+#include "trx.h"
+
+static const u32 ofdmswing_table[OFDM_TABLE_SIZE] = {
+	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 cck_tbl_ch1_13[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 cck_tbl_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*/
+};
+
+#define	CAL_SWING_OFF(_off, _dir, _size, _del)				\
+	do {								\
+		for (_off = 0; _off < _size; _off++) {			\
+			if (_del < thermal_threshold[_dir][_off]) {	\
+				if (_off != 0)				\
+					_off--;				\
+				break;					\
+			}						\
+		}							\
+		if (_off >= _size)					\
+			_off = _size - 1;				\
+	} while (0)
+
+static void rtl88e_set_iqk_matrix(struct ieee80211_hw *hw,
+				  u8 ofdm_index, u8 rfpath,
+				  long iqk_result_x, long iqk_result_y)
+{
+	long ele_a = 0, ele_d, ele_c = 0, value32;
+
+	ele_d = (ofdmswing_table[ofdm_index] & 0xFFC00000)>>22;
+
+	if (iqk_result_x != 0) {
+		if ((iqk_result_x & 0x00000200) != 0)
+			iqk_result_x = iqk_result_x | 0xFFFFFC00;
+		ele_a = ((iqk_result_x * ele_d)>>8)&0x000003FF;
+
+		if ((iqk_result_y & 0x00000200) != 0)
+			iqk_result_y = iqk_result_y | 0xFFFFFC00;
+		ele_c = ((iqk_result_y * ele_d)>>8)&0x000003FF;
+
+		switch (rfpath) {
+		case RF90_PATH_A:
+			value32 = (ele_d << 22)|((ele_c & 0x3F)<<16) | ele_a;
+			rtl_set_bbreg(hw, ROFDM0_XATXIQIMBAL, MASKDWORD,
+				      value32);
+			value32 = (ele_c & 0x000003C0) >> 6;
+			rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS, value32);
+			value32 = ((iqk_result_x * ele_d) >> 7) & 0x01;
+			rtl_set_bbreg(hw, ROFDM0_ECCATHRES, BIT(24), value32);
+			break;
+		case RF90_PATH_B:
+			value32 = (ele_d << 22)|((ele_c & 0x3F)<<16) | ele_a;
+			rtl_set_bbreg(hw, ROFDM0_XBTXIQIMBAL,
+				      MASKDWORD, value32);
+			value32 = (ele_c & 0x000003C0) >> 6;
+			rtl_set_bbreg(hw, ROFDM0_XDTXAFE, MASKH4BITS, value32);
+			value32 = ((iqk_result_x * ele_d) >> 7) & 0x01;
+			rtl_set_bbreg(hw, ROFDM0_ECCATHRES, BIT(28), value32);
+			break;
+		default:
+			break;
+		}
+	} else {
+		switch (rfpath) {
+		case RF90_PATH_A:
+			rtl_set_bbreg(hw, ROFDM0_XATXIQIMBAL, MASKDWORD,
+				      ofdmswing_table[ofdm_index]);
+			rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS, 0x00);
+			rtl_set_bbreg(hw, ROFDM0_ECCATHRES, BIT(24), 0x00);
+			break;
+		case RF90_PATH_B:
+			rtl_set_bbreg(hw, ROFDM0_XBTXIQIMBAL, MASKDWORD,
+				      ofdmswing_table[ofdm_index]);
+			rtl_set_bbreg(hw, ROFDM0_XDTXAFE, MASKH4BITS, 0x00);
+			rtl_set_bbreg(hw, ROFDM0_ECCATHRES, BIT(28), 0x00);
+			break;
+		default:
+			break;
+		}
+	}
+}
+
+void rtl88e_dm_txpower_track_adjust(struct ieee80211_hw *hw,
+	u8 type, u8 *pdirection, u32 *poutwrite_val)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
+	u8 pwr_val = 0;
+	u8 cck_base = rtldm->swing_idx_cck_base;
+	u8 cck_val = rtldm->swing_idx_cck;
+	u8 ofdm_base = rtldm->swing_idx_ofdm_base;
+	u8 ofdm_val = rtlpriv->dm.swing_idx_ofdm[RF90_PATH_A];
+
+	if (type == 0) {
+		if (ofdm_val <= ofdm_base) {
+			*pdirection = 1;
+			pwr_val = ofdm_base - ofdm_val;
+		} else {
+			*pdirection = 2;
+			pwr_val = ofdm_val - ofdm_base;
+		}
+	} else if (type == 1) {
+		if (cck_val <= cck_base) {
+			*pdirection = 1;
+			pwr_val = cck_base - cck_val;
+		} else {
+			*pdirection = 2;
+			pwr_val = cck_val - cck_base;
+		}
+	}
+
+	if (pwr_val >= TXPWRTRACK_MAX_IDX && (*pdirection == 1))
+		pwr_val = TXPWRTRACK_MAX_IDX;
+
+	*poutwrite_val = pwr_val | (pwr_val << 8) | (pwr_val << 16) |
+			 (pwr_val << 24);
+}
+
+
+static void rtl88e_chk_tx_track(struct ieee80211_hw *hw,
+				enum pwr_track_control_method method,
+				u8 rfpath, u8 index)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
+	int jj = rtldm->swing_idx_cck;
+	int i;
+
+	if (method == TXAGC) {
+		if (rtldm->swing_flag_ofdm == true ||
+		    rtldm->swing_flag_cck == true) {
+			u8 chan = rtlphy->current_channel;
+			rtl88e_phy_set_txpower_level(hw, chan);
+			rtldm->swing_flag_ofdm = false;
+			rtldm->swing_flag_cck = false;
+		}
+	} else if (method == BBSWING) {
+		if (!rtldm->cck_inch14) {
+			for (i = 0; i < 8; i++)
+				rtl_write_byte(rtlpriv, 0xa22 + i,
+					       cck_tbl_ch1_13[jj][i]);
+		} else {
+			for (i = 0; i < 8; i++)
+				rtl_write_byte(rtlpriv, 0xa22 + i,
+					       cck_tbl_ch14[jj][i]);
+		}
+
+		if (rfpath == RF90_PATH_A) {
+			long x = rtlphy->iqk_matrix[index].value[0][0];
+			long y = rtlphy->iqk_matrix[index].value[0][1];
+			u8 indx = rtldm->swing_idx_ofdm[rfpath];
+			rtl88e_set_iqk_matrix(hw, indx, rfpath, x, y);
+		} else if (rfpath == RF90_PATH_B) {
+			u8 indx = rtldm->swing_idx_ofdm[rfpath];
+			long x = rtlphy->iqk_matrix[indx].value[0][4];
+			long y = rtlphy->iqk_matrix[indx].value[0][5];
+			rtl88e_set_iqk_matrix(hw, indx, rfpath, x, y);
+		}
+	} else {
+		return;
+	}
+}
+
+static void rtl88e_dm_diginit(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct dig_t *dm_dig = &rtlpriv->dm_digtable;
+
+	dm_dig->dig_enable_flag = true;
+	dm_dig->cur_igvalue = rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f);
+	dm_dig->pre_igvalue = 0;
+	dm_dig->cursta_cstate = DIG_STA_DISCONNECT;
+	dm_dig->presta_cstate = DIG_STA_DISCONNECT;
+	dm_dig->curmultista_cstate = DIG_MULTISTA_DISCONNECT;
+	dm_dig->rssi_lowthresh = DM_DIG_THRESH_LOW;
+	dm_dig->rssi_highthresh = DM_DIG_THRESH_HIGH;
+	dm_dig->fa_lowthresh = DM_FALSEALARM_THRESH_LOW;
+	dm_dig->fa_highthresh = DM_FALSEALARM_THRESH_HIGH;
+	dm_dig->rx_gain_max = DM_DIG_MAX;
+	dm_dig->rx_gain_min = DM_DIG_MIN;
+	dm_dig->back_val = DM_DIG_BACKOFF_DEFAULT;
+	dm_dig->back_range_max = DM_DIG_BACKOFF_MAX;
+	dm_dig->back_range_min = DM_DIG_BACKOFF_MIN;
+	dm_dig->pre_cck_cca_thres = 0xff;
+	dm_dig->cur_cck_cca_thres = 0x83;
+	dm_dig->forbidden_igi = DM_DIG_MIN;
+	dm_dig->large_fa_hit = 0;
+	dm_dig->recover_cnt = 0;
+	dm_dig->dig_min_0 = 0x25;
+	dm_dig->dig_min_1 = 0x25;
+	dm_dig->media_connect_0 = false;
+	dm_dig->media_connect_1 = false;
+	rtlpriv->dm.dm_initialgain_enable = true;
+}
+
+static u8 rtl88e_dm_initial_gain_min_pwdb(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct dig_t *dm_dig = &rtlpriv->dm_digtable;
+	long rssi_val_min = 0;
+
+	if ((dm_dig->curmultista_cstate == DIG_MULTISTA_CONNECT) &&
+	    (dm_dig->cursta_cstate == DIG_STA_CONNECT)) {
+		if (rtlpriv->dm.entry_min_undec_sm_pwdb != 0)
+			rssi_val_min =
+			    (rtlpriv->dm.entry_min_undec_sm_pwdb >
+			    rtlpriv->dm.undec_sm_pwdb) ?
+			    rtlpriv->dm.undec_sm_pwdb :
+			    rtlpriv->dm.entry_min_undec_sm_pwdb;
+		else
+			rssi_val_min = rtlpriv->dm.undec_sm_pwdb;
+	} else if (dm_dig->cursta_cstate == DIG_STA_CONNECT ||
+		   dm_dig->cursta_cstate == DIG_STA_BEFORE_CONNECT) {
+		rssi_val_min = rtlpriv->dm.undec_sm_pwdb;
+	} else if (dm_dig->curmultista_cstate ==
+		DIG_MULTISTA_CONNECT) {
+		rssi_val_min = rtlpriv->dm.entry_min_undec_sm_pwdb;
+	}
+	return (u8)rssi_val_min;
+}
+
+static void rtl88e_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw)
+{
+	u32 ret_value;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct false_alarm_statistics *alm_cnt = &(rtlpriv->falsealm_cnt);
+
+	rtl_set_bbreg(hw, ROFDM0_LSTF, BIT(31), 1);
+	rtl_set_bbreg(hw, ROFDM1_LSTF, BIT(31), 1);
+
+	ret_value = rtl_get_bbreg(hw, ROFDM0_FRAMESYNC, MASKDWORD);
+	alm_cnt->cnt_fast_fsync_fail = (ret_value&0xffff);
+	alm_cnt->cnt_sb_search_fail = ((ret_value&0xffff0000)>>16);
+
+	ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER1, MASKDWORD);
+	alm_cnt->cnt_ofdm_cca = (ret_value&0xffff);
+	alm_cnt->cnt_parity_fail = ((ret_value & 0xffff0000) >> 16);
+
+	ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER2, MASKDWORD);
+	alm_cnt->cnt_rate_illegal = (ret_value & 0xffff);
+	alm_cnt->cnt_crc8_fail = ((ret_value & 0xffff0000) >> 16);
+
+	ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER3, MASKDWORD);
+	alm_cnt->cnt_mcs_fail = (ret_value & 0xffff);
+	alm_cnt->cnt_ofdm_fail = alm_cnt->cnt_parity_fail +
+				 alm_cnt->cnt_rate_illegal +
+				 alm_cnt->cnt_crc8_fail +
+				 alm_cnt->cnt_mcs_fail +
+				 alm_cnt->cnt_fast_fsync_fail +
+				 alm_cnt->cnt_sb_search_fail;
+
+	ret_value = rtl_get_bbreg(hw, REG_SC_CNT, MASKDWORD);
+	alm_cnt->cnt_bw_lsc = (ret_value & 0xffff);
+	alm_cnt->cnt_bw_usc = ((ret_value & 0xffff0000) >> 16);
+
+	rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(12), 1);
+	rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(14), 1);
+
+	ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERLOWER, MASKBYTE0);
+	alm_cnt->cnt_cck_fail = ret_value;
+
+	ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERUPPER, MASKBYTE3);
+	alm_cnt->cnt_cck_fail += (ret_value & 0xff) << 8;
+
+	ret_value = rtl_get_bbreg(hw, RCCK0_CCA_CNT, MASKDWORD);
+	alm_cnt->cnt_cck_cca = ((ret_value & 0xff) << 8) |
+				((ret_value&0xFF00)>>8);
+
+	alm_cnt->cnt_all = alm_cnt->cnt_fast_fsync_fail +
+			   alm_cnt->cnt_sb_search_fail +
+			   alm_cnt->cnt_parity_fail +
+			   alm_cnt->cnt_rate_illegal +
+			   alm_cnt->cnt_crc8_fail +
+			   alm_cnt->cnt_mcs_fail +
+			   alm_cnt->cnt_cck_fail;
+	alm_cnt->cnt_cca_all = alm_cnt->cnt_ofdm_cca + alm_cnt->cnt_cck_cca;
+
+	rtl_set_bbreg(hw, ROFDM0_TRSWISOLATION, BIT(31), 1);
+	rtl_set_bbreg(hw, ROFDM0_TRSWISOLATION, BIT(31), 0);
+	rtl_set_bbreg(hw, ROFDM1_LSTF, BIT(27), 1);
+	rtl_set_bbreg(hw, ROFDM1_LSTF, BIT(27), 0);
+	rtl_set_bbreg(hw, ROFDM0_LSTF, BIT(31), 0);
+	rtl_set_bbreg(hw, ROFDM1_LSTF, BIT(31), 0);
+	rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(13)|BIT(12), 0);
+	rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(13)|BIT(12), 2);
+	rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(15)|BIT(14), 0);
+	rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(15)|BIT(14), 2);
+
+	RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
+		 "cnt_parity_fail = %d, cnt_rate_illegal = %d, "
+		 "cnt_crc8_fail = %d, cnt_mcs_fail = %d\n",
+		 alm_cnt->cnt_parity_fail,
+		 alm_cnt->cnt_rate_illegal,
+		 alm_cnt->cnt_crc8_fail, alm_cnt->cnt_mcs_fail);
+
+	RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
+		 "cnt_ofdm_fail = %x, cnt_cck_fail = %x, cnt_all = %x\n",
+		 alm_cnt->cnt_ofdm_fail,
+		 alm_cnt->cnt_cck_fail, alm_cnt->cnt_all);
+}
+
+static void rtl88e_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct dig_t *dm_dig = &rtlpriv->dm_digtable;
+	u8 cur_cck_cca_thresh;
+
+	if (dm_dig->cursta_cstate == DIG_STA_CONNECT) {
+		dm_dig->rssi_val_min = rtl88e_dm_initial_gain_min_pwdb(hw);
+		if (dm_dig->rssi_val_min > 25) {
+			cur_cck_cca_thresh = 0xcd;
+		} else if ((dm_dig->rssi_val_min <= 25) &&
+			   (dm_dig->rssi_val_min > 10)) {
+			cur_cck_cca_thresh = 0x83;
+		} else {
+			if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000)
+				cur_cck_cca_thresh = 0x83;
+			else
+				cur_cck_cca_thresh = 0x40;
+		}
+
+	} else {
+		if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000)
+			cur_cck_cca_thresh = 0x83;
+		else
+			cur_cck_cca_thresh = 0x40;
+	}
+
+	if (dm_dig->cur_cck_cca_thres != cur_cck_cca_thresh)
+		rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, cur_cck_cca_thresh);
+
+	dm_dig->cur_cck_cca_thres = cur_cck_cca_thresh;
+	dm_dig->pre_cck_cca_thres = dm_dig->cur_cck_cca_thres;
+	RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
+		 "CCK cca thresh hold =%x\n", dm_dig->cur_cck_cca_thres);
+}
+
+static void rtl88e_dm_dig(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct dig_t *dm_dig = &rtlpriv->dm_digtable;
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	u8 dig_min, dig_maxofmin;
+	bool bfirstconnect;
+	u8 dm_dig_max, dm_dig_min;
+	u8 current_igi = dm_dig->cur_igvalue;
+
+	if (rtlpriv->dm.dm_initialgain_enable == false)
+		return;
+	if (dm_dig->dig_enable_flag == false)
+		return;
+	if (mac->act_scanning == true)
+		return;
+
+	if (mac->link_state >= MAC80211_LINKED)
+		dm_dig->cursta_cstate = DIG_STA_CONNECT;
+	else
+		dm_dig->cursta_cstate = DIG_STA_DISCONNECT;
+	if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP ||
+	    rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC)
+		dm_dig->cursta_cstate = DIG_STA_DISCONNECT;
+
+	dm_dig_max = DM_DIG_MAX;
+	dm_dig_min = DM_DIG_MIN;
+	dig_maxofmin = DM_DIG_MAX_AP;
+	dig_min = dm_dig->dig_min_0;
+	bfirstconnect = ((mac->link_state >= MAC80211_LINKED) ? true : false) &&
+			 (dm_dig->media_connect_0 == false);
+
+	dm_dig->rssi_val_min =
+		rtl88e_dm_initial_gain_min_pwdb(hw);
+
+	if (mac->link_state >= MAC80211_LINKED) {
+		if ((dm_dig->rssi_val_min + 20) > dm_dig_max)
+			dm_dig->rx_gain_max = dm_dig_max;
+		else if ((dm_dig->rssi_val_min + 20) < dm_dig_min)
+			dm_dig->rx_gain_max = dm_dig_min;
+		else
+			dm_dig->rx_gain_max = dm_dig->rssi_val_min + 20;
+
+		if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) {
+			dig_min  = dm_dig->antdiv_rssi_max;
+		} else {
+			if (dm_dig->rssi_val_min < dm_dig_min)
+				dig_min = dm_dig_min;
+			else if (dm_dig->rssi_val_min < dig_maxofmin)
+				dig_min = dig_maxofmin;
+			else
+				dig_min = dm_dig->rssi_val_min;
+		}
+	} else {
+		dm_dig->rx_gain_max = dm_dig_max;
+		dig_min = dm_dig_min;
+		RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "no link\n");
+	}
+
+	if (rtlpriv->falsealm_cnt.cnt_all > 10000) {
+		dm_dig->large_fa_hit++;
+		if (dm_dig->forbidden_igi < current_igi) {
+			dm_dig->forbidden_igi = current_igi;
+			dm_dig->large_fa_hit = 1;
+		}
+
+		if (dm_dig->large_fa_hit >= 3) {
+			if ((dm_dig->forbidden_igi + 1) > dm_dig->rx_gain_max)
+				dm_dig->rx_gain_min = dm_dig->rx_gain_max;
+			else
+				dm_dig->rx_gain_min = dm_dig->forbidden_igi + 1;
+			dm_dig->recover_cnt = 3600;
+		}
+	} else {
+		if (dm_dig->recover_cnt != 0) {
+			dm_dig->recover_cnt--;
+		} else {
+			if (dm_dig->large_fa_hit == 0) {
+				if ((dm_dig->forbidden_igi - 1) < dig_min) {
+					dm_dig->forbidden_igi = dig_min;
+					dm_dig->rx_gain_min = dig_min;
+				} else {
+					dm_dig->forbidden_igi--;
+					dm_dig->rx_gain_min =
+						 dm_dig->forbidden_igi + 1;
+				}
+			} else if (dm_dig->large_fa_hit == 3) {
+				dm_dig->large_fa_hit = 0;
+			}
+		}
+	}
+
+	if (dm_dig->cursta_cstate == DIG_STA_CONNECT) {
+		if (bfirstconnect) {
+			current_igi = dm_dig->rssi_val_min;
+		} else {
+			if (rtlpriv->falsealm_cnt.cnt_all > DM_DIG_FA_TH2)
+				current_igi += 2;
+			else if (rtlpriv->falsealm_cnt.cnt_all > DM_DIG_FA_TH1)
+				current_igi++;
+			else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH0)
+				current_igi--;
+		}
+	} else {
+		if (rtlpriv->falsealm_cnt.cnt_all > 10000)
+			current_igi += 2;
+		else if (rtlpriv->falsealm_cnt.cnt_all > 8000)
+			current_igi++;
+		else if (rtlpriv->falsealm_cnt.cnt_all < 500)
+			current_igi--;
+	}
+
+	if (current_igi > DM_DIG_FA_UPPER)
+		current_igi = DM_DIG_FA_UPPER;
+	else if (current_igi < DM_DIG_FA_LOWER)
+		current_igi = DM_DIG_FA_LOWER;
+
+	if (rtlpriv->falsealm_cnt.cnt_all > 10000)
+		current_igi = DM_DIG_FA_UPPER;
+
+	dm_dig->cur_igvalue = current_igi;
+	rtl88e_dm_write_dig(hw);
+	dm_dig->media_connect_0 = ((mac->link_state >= MAC80211_LINKED) ?
+				    true : false);
+	dm_dig->dig_min_0 = dig_min;
+
+	rtl88e_dm_cck_packet_detection_thresh(hw);
+}
+
+static void rtl88e_dm_init_dynamic_txpower(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	rtlpriv->dm.dynamic_txpower_enable = false;
+
+	rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL;
+	rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
+}
+
+static void rtl92c_dm_dynamic_txpower(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	long undec_sm_pwdb;
+
+	if (!rtlpriv->dm.dynamic_txpower_enable)
+		return;
+
+	if (rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) {
+		rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
+		return;
+	}
+
+	if ((mac->link_state < MAC80211_LINKED) &&
+	    (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) {
+		RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE,
+			 "Not connected\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) {
+			undec_sm_pwdb =
+			    rtlpriv->dm.entry_min_undec_sm_pwdb;
+			RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+				 "AP Client PWDB = 0x%lx\n",
+				  undec_sm_pwdb);
+		} else {
+			undec_sm_pwdb =
+			    rtlpriv->dm.undec_sm_pwdb;
+			RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+				 "STA Default Port PWDB = 0x%lx\n",
+				  undec_sm_pwdb);
+		}
+	} else {
+		undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb;
+
+		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+			 "AP Ext Port PWDB = 0x%lx\n", undec_sm_pwdb);
+	}
+
+	if (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL2) {
+		rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1;
+		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+			 "TXHIGHPWRLEVEL_LEVEL1 (TxPwr = 0x0)\n");
+	} else if ((undec_sm_pwdb <
+		    (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3)) &&
+		   (undec_sm_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 (undec_sm_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);
+		rtl88e_phy_set_txpower_level(hw, rtlphy->current_channel);
+	}
+
+	rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl;
+}
+
+void rtl88e_dm_write_dig(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct dig_t *dm_dig = &rtlpriv->dm_digtable;
+
+	RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
+		 "cur_igvalue = 0x%x, "
+		  "pre_igvalue = 0x%x, back_val = %d\n",
+		  dm_dig->cur_igvalue, dm_dig->pre_igvalue,
+		  dm_dig->back_val);
+
+	if (dm_dig->cur_igvalue > 0x3f)
+		dm_dig->cur_igvalue = 0x3f;
+	if (dm_dig->pre_igvalue != dm_dig->cur_igvalue) {
+		rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f,
+			      dm_dig->cur_igvalue);
+
+		dm_dig->pre_igvalue = dm_dig->cur_igvalue;
+	}
+}
+
+static void rtl88e_dm_pwdb_monitor(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	struct rtl_sta_info *drv_priv;
+	static u64 last_txok;
+	static u64 last_rx;
+	long tmp_entry_max_pwdb = 0, tmp_entry_min_pwdb = 0xff;
+
+	if (rtlhal->oem_id == RT_CID_819x_HP) {
+		u64 cur_txok_cnt = 0;
+		u64 cur_rxok_cnt = 0;
+		cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok;
+		cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rx;
+		last_txok = cur_txok_cnt;
+		last_rx = cur_rxok_cnt;
+
+		if (cur_rxok_cnt > (cur_txok_cnt * 6))
+			rtl_write_dword(rtlpriv, REG_ARFR0, 0x8f015);
+		else
+			rtl_write_dword(rtlpriv, REG_ARFR0, 0xff015);
+	}
+
+	/* AP & ADHOC & MESH */
+	spin_lock_bh(&rtlpriv->locks.entry_list_lock);
+	list_for_each_entry(drv_priv, &rtlpriv->entry_list, list) {
+		if (drv_priv->rssi_stat.undec_sm_pwdb < tmp_entry_min_pwdb)
+			tmp_entry_min_pwdb = drv_priv->rssi_stat.undec_sm_pwdb;
+		if (drv_priv->rssi_stat.undec_sm_pwdb > tmp_entry_max_pwdb)
+			tmp_entry_max_pwdb = drv_priv->rssi_stat.undec_sm_pwdb;
+	}
+	spin_unlock_bh(&rtlpriv->locks.entry_list_lock);
+
+	/* If associated entry is found */
+	if (tmp_entry_max_pwdb != 0) {
+		rtlpriv->dm.entry_max_undec_sm_pwdb = tmp_entry_max_pwdb;
+		RTPRINT(rtlpriv, FDM, DM_PWDB, "EntryMaxPWDB = 0x%lx(%ld)\n",
+			tmp_entry_max_pwdb, tmp_entry_max_pwdb);
+	} else {
+		rtlpriv->dm.entry_max_undec_sm_pwdb = 0;
+	}
+	/* If associated entry is found */
+	if (tmp_entry_min_pwdb != 0xff) {
+		rtlpriv->dm.entry_min_undec_sm_pwdb = tmp_entry_min_pwdb;
+		RTPRINT(rtlpriv, FDM, DM_PWDB, "EntryMinPWDB = 0x%lx(%ld)\n",
+			tmp_entry_min_pwdb, tmp_entry_min_pwdb);
+	} else {
+		rtlpriv->dm.entry_min_undec_sm_pwdb = 0;
+	}
+	/* Indicate Rx signal strength to FW. */
+	if (!rtlpriv->dm.useramask)
+		rtl_write_byte(rtlpriv, 0x4fe, rtlpriv->dm.undec_sm_pwdb);
+}
+
+void rtl88e_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 rtl88e_dm_check_edca_turbo(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	static u64 last_txok_cnt;
+	static u64 last_rxok_cnt;
+	static u32 last_bt_edca_ul;
+	static u32 last_bt_edca_dl;
+	u64 cur_txok_cnt = 0;
+	u64 cur_rxok_cnt = 0;
+	u32 edca_be_ul = 0x5ea42b;
+	u32 edca_be_dl = 0x5ea42b;
+	bool change_edca = false;
+
+	if ((last_bt_edca_ul != rtlpcipriv->bt_coexist.bt_edca_ul) ||
+	    (last_bt_edca_dl != rtlpcipriv->bt_coexist.bt_edca_dl)) {
+		rtlpriv->dm.current_turbo_edca = false;
+		last_bt_edca_ul = rtlpcipriv->bt_coexist.bt_edca_ul;
+		last_bt_edca_dl = rtlpcipriv->bt_coexist.bt_edca_dl;
+	}
+
+	if (rtlpcipriv->bt_coexist.bt_edca_ul != 0) {
+		edca_be_ul = rtlpcipriv->bt_coexist.bt_edca_ul;
+		change_edca = true;
+	}
+
+	if (rtlpcipriv->bt_coexist.bt_edca_dl != 0) {
+		edca_be_ul = rtlpcipriv->bt_coexist.bt_edca_dl;
+		change_edca = true;
+	}
+
+	if (mac->link_state != MAC80211_LINKED) {
+		rtlpriv->dm.current_turbo_edca = false;
+		return;
+	}
+
+	if ((!mac->ht_enable) && (!rtlpcipriv->bt_coexist.bt_coexistence)) {
+		if (!(edca_be_ul & 0xffff0000))
+			edca_be_ul |= 0x005e0000;
+
+		if (!(edca_be_dl & 0xffff0000))
+			edca_be_dl |= 0x005e0000;
+	}
+
+	if ((change_edca) || ((!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;
+		}
+	}
+
+	rtlpriv->dm.is_any_nonbepkts = false;
+	last_txok_cnt = rtlpriv->stats.txbytesunicast;
+	last_rxok_cnt = rtlpriv->stats.rxbytesunicast;
+}
+
+static void rtl88e_dm_txpower_tracking_callback_thermalmeter(struct ieee80211_hw
+							     *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	struct rtl_dm	*rtldm = rtl_dm(rtl_priv(hw));
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	u8 thermalvalue = 0, delta, delta_lck, delta_iqk, off;
+	u8 th_avg_cnt = 0;
+	u32 thermalvalue_avg = 0;
+	long  ele_d, temp_cck;
+	char ofdm_index[2], cck_index = 0, ofdm_old[2] = {0, 0}, cck_old = 0;
+	int i = 0;
+	bool is2t = false;
+
+	u8 ofdm_min_index = 6, rf = (is2t) ? 2 : 1;
+	u8 index_for_channel;
+	enum _dec_inc {dec, power_inc};
+
+	/* 0.1 the following TWO tables decide the final index of
+	 * OFDM/CCK swing table
+	 */
+	char del_tbl_idx[2][15] = {
+		{0, 0, 2, 3, 4, 4, 5, 6, 7, 7, 8, 9, 10, 10, 11},
+		{0, 0, -1, -2, -3, -4, -4, -4, -4, -5, -7, -8, -9, -9, -10}
+	};
+	u8 thermal_threshold[2][15] = {
+		{0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 27},
+		{0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 25, 25, 25}
+	};
+
+	/*Initilization (7 steps in total) */
+	rtlpriv->dm.txpower_trackinginit = true;
+	RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+		 "rtl88e_dm_txpower_tracking_callback_thermalmeter\n");
+
+	thermalvalue = (u8) rtl_get_rfreg(hw, RF90_PATH_A, RF_T_METER, 0xfc00);
+	if (!thermalvalue)
+		return;
+	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);
+
+	/*1. Query OFDM Default Setting: Path A*/
+	ele_d = rtl_get_bbreg(hw, ROFDM0_XATXIQIMBAL, MASKDWORD) & MASKOFDM_D;
+	for (i = 0; i < OFDM_TABLE_LENGTH; i++) {
+		if (ele_d == (ofdmswing_table[i] & MASKOFDM_D)) {
+			ofdm_old[0] = (u8) i;
+			rtldm->swing_idx_ofdm_base = (u8)i;
+			RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+				 "Initial pathA ele_d reg0x%x = 0x%lx, ofdm_index = 0x%x\n",
+				 ROFDM0_XATXIQIMBAL,
+				 ele_d, ofdm_old[0]);
+			break;
+		}
+	}
+
+	if (is2t) {
+		ele_d = rtl_get_bbreg(hw, ROFDM0_XBTXIQIMBAL,
+				      MASKDWORD) & MASKOFDM_D;
+		for (i = 0; i < OFDM_TABLE_LENGTH; i++) {
+			if (ele_d == (ofdmswing_table[i] & MASKOFDM_D)) {
+				ofdm_old[1] = (u8)i;
+
+				RT_TRACE(rtlpriv, COMP_POWER_TRACKING,
+					 DBG_LOUD,
+					 "Initial pathB ele_d reg0x%x = 0x%lx, ofdm_index = 0x%x\n",
+					 ROFDM0_XBTXIQIMBAL, ele_d,
+					 ofdm_old[1]);
+				break;
+			}
+		}
+	}
+	/*2.Query CCK default setting From 0xa24*/
+	temp_cck = rtl_get_bbreg(hw, RCCK0_TXFILTER2, MASKDWORD) & MASKCCK;
+	for (i = 0; i < CCK_TABLE_LENGTH; i++) {
+		if (rtlpriv->dm.cck_inch14) {
+			if (memcmp(&temp_cck, &cck_tbl_ch14[i][2], 4) == 0) {
+				cck_old = (u8)i;
+				rtldm->swing_idx_cck_base = (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_old,
+					 rtlpriv->dm.cck_inch14);
+				break;
+			}
+		} else {
+			if (memcmp(&temp_cck, &cck_tbl_ch1_13[i][2], 4) == 0) {
+				cck_old = (u8)i;
+				rtldm->swing_idx_cck_base = (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_old,
+					 rtlpriv->dm.cck_inch14);
+				break;
+			}
+		}
+	}
+
+	/*3 Initialize ThermalValues of RFCalibrateInfo*/
+	if (!rtldm->thermalvalue) {
+		rtlpriv->dm.thermalvalue = rtlefuse->eeprom_thermalmeter;
+		rtlpriv->dm.thermalvalue_lck = thermalvalue;
+		rtlpriv->dm.thermalvalue_iqk = thermalvalue;
+		for (i = 0; i < rf; i++)
+			rtlpriv->dm.ofdm_index[i] = ofdm_old[i];
+		rtlpriv->dm.cck_index = cck_old;
+	}
+
+	/*4 Calculate average thermal meter*/
+	rtldm->thermalvalue_avg[rtldm->thermalvalue_avg_index] = thermalvalue;
+	rtldm->thermalvalue_avg_index++;
+	if (rtldm->thermalvalue_avg_index == AVG_THERMAL_NUM_88E)
+		rtldm->thermalvalue_avg_index = 0;
+
+	for (i = 0; i < AVG_THERMAL_NUM_88E; i++) {
+		if (rtldm->thermalvalue_avg[i]) {
+			thermalvalue_avg += rtldm->thermalvalue_avg[i];
+			th_avg_cnt++;
+		}
+	}
+
+	if (th_avg_cnt)
+		thermalvalue = (u8)(thermalvalue_avg / th_avg_cnt);
+
+	/* 5 Calculate delta, delta_LCK, delta_IQK.*/
+	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);
+
+	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);
+	/* 6 If necessary, do LCK.*/
+	if (delta_lck >= 8) {
+		rtlpriv->dm.thermalvalue_lck = thermalvalue;
+		rtl88e_phy_lc_calibrate(hw);
+	}
+
+	/* 7 If necessary, move the index of swing table to adjust Tx power. */
+	if (delta > 0 && rtlpriv->dm.txpower_track_control) {
+		delta = (thermalvalue > rtlefuse->eeprom_thermalmeter) ?
+			(thermalvalue - rtlefuse->eeprom_thermalmeter) :
+			(rtlefuse->eeprom_thermalmeter - thermalvalue);
+
+		/* 7.1 Get the final CCK_index and OFDM_index for each
+		 * swing table.
+		 */
+		if (thermalvalue > rtlefuse->eeprom_thermalmeter) {
+			CAL_SWING_OFF(off, power_inc, IDX_MAP, delta);
+			for (i = 0; i < rf; i++)
+				ofdm_index[i] = rtldm->ofdm_index[i] +
+						del_tbl_idx[power_inc][off];
+			cck_index = rtldm->cck_index +
+				    del_tbl_idx[power_inc][off];
+		} else {
+			CAL_SWING_OFF(off, dec, IDX_MAP, delta);
+			for (i = 0; i < rf; i++)
+				ofdm_index[i] = rtldm->ofdm_index[i] +
+						del_tbl_idx[dec][off];
+			cck_index = rtldm->cck_index + del_tbl_idx[dec][off];
+		}
+
+		/* 7.2 Handle boundary conditions of index.*/
+		for (i = 0; i < rf; i++) {
+			if (ofdm_index[i] > OFDM_TABLE_SIZE-1)
+				ofdm_index[i] = OFDM_TABLE_SIZE-1;
+			else if (rtldm->ofdm_index[i] < ofdm_min_index)
+				ofdm_index[i] = ofdm_min_index;
+		}
+
+		if (cck_index > CCK_TABLE_SIZE - 1)
+			cck_index = CCK_TABLE_SIZE - 1;
+		else if (cck_index < 0)
+			cck_index = 0;
+
+		/*7.3Configure the Swing Table to adjust Tx Power.*/
+		if (rtlpriv->dm.txpower_track_control) {
+			rtldm->done_txpower = true;
+			rtldm->swing_idx_ofdm[RF90_PATH_A] =
+				 (u8)ofdm_index[RF90_PATH_A];
+			if (is2t)
+				rtldm->swing_idx_ofdm[RF90_PATH_B] =
+					 (u8)ofdm_index[RF90_PATH_B];
+			rtldm->swing_idx_cck = cck_index;
+			if (rtldm->swing_idx_ofdm_cur !=
+			    rtldm->swing_idx_ofdm[0]) {
+				rtldm->swing_idx_ofdm_cur =
+					 rtldm->swing_idx_ofdm[0];
+				rtldm->swing_flag_ofdm = true;
+			}
+
+			if (rtldm->swing_idx_cck != rtldm->swing_idx_cck) {
+				rtldm->swing_idx_cck_cur = rtldm->swing_idx_cck;
+				rtldm->swing_flag_cck = true;
+			}
+
+			rtl88e_chk_tx_track(hw, TXAGC, 0, 0);
+
+			if (is2t)
+				rtl88e_chk_tx_track(hw, BBSWING,
+						    RF90_PATH_B,
+						    index_for_channel);
+		}
+	}
+
+	if (delta_iqk >= 8) {
+		rtlpriv->dm.thermalvalue_iqk = thermalvalue;
+		rtl88e_phy_iq_calibrate(hw, false);
+	}
+
+	if (rtldm->txpower_track_control)
+		rtldm->thermalvalue = thermalvalue;
+	rtldm->txpowercount = 0;
+	RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, "end\n");
+}
+
+static void rtl88e_dm_init_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.txpowercount = 0;
+	rtlpriv->dm.txpower_track_control = true;
+
+	rtlpriv->dm.swing_idx_ofdm[RF90_PATH_A] = 12;
+	rtlpriv->dm.swing_idx_ofdm_cur = 12;
+	rtlpriv->dm.swing_flag_ofdm = false;
+	RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+		 "  rtlpriv->dm.txpower_tracking = %d\n",
+		 rtlpriv->dm.txpower_tracking);
+}
+
+void rtl88e_dm_check_txpower_tracking(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 88E Thermal Meter!!\n");
+		tm_trigger = 1;
+		return;
+	} else {
+		RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+			 "Schedule TxPowerTracking !!\n");
+		rtl88e_dm_txpower_tracking_callback_thermalmeter(hw);
+		tm_trigger = 0;
+	}
+}
+
+void rtl88e_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rate_adaptive *p_ra = &(rtlpriv->ra);
+
+	p_ra->ratr_state = DM_RATR_STA_INIT;
+	p_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;
+}
+
+static void rtl88e_dm_refresh_rate_adaptive_mask(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 rate_adaptive *p_ra = &(rtlpriv->ra);
+	struct ieee80211_sta *sta = NULL;
+	u32 low_rssi, hi_rssi;
+
+	if (is_hal_stop(rtlhal)) {
+		RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
+			 "driver is going to unload\n");
+		return;
+	}
+
+	if (!rtlpriv->dm.useramask) {
+		RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
+			 "driver does not control rate adaptive mask\n");
+		return;
+	}
+
+	if (mac->link_state == MAC80211_LINKED &&
+	    mac->opmode == NL80211_IFTYPE_STATION) {
+		switch (p_ra->pre_ratr_state) {
+		case DM_RATR_STA_HIGH:
+			hi_rssi = 50;
+			low_rssi = 20;
+			break;
+		case DM_RATR_STA_MIDDLE:
+			hi_rssi = 55;
+			low_rssi = 20;
+			break;
+		case DM_RATR_STA_LOW:
+			hi_rssi = 50;
+			low_rssi = 25;
+			break;
+		default:
+			hi_rssi = 50;
+			low_rssi = 20;
+			break;
+		}
+
+		if (rtlpriv->dm.undec_sm_pwdb > (long)hi_rssi)
+			p_ra->ratr_state = DM_RATR_STA_HIGH;
+		else if (rtlpriv->dm.undec_sm_pwdb > (long)low_rssi)
+			p_ra->ratr_state = DM_RATR_STA_MIDDLE;
+		else
+			p_ra->ratr_state = DM_RATR_STA_LOW;
+
+		if (p_ra->pre_ratr_state != p_ra->ratr_state) {
+			RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
+				 "RSSI = %ld\n",
+				 rtlpriv->dm.undec_sm_pwdb);
+			RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
+				 "RSSI_LEVEL = %d\n", p_ra->ratr_state);
+			RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
+				 "PreState = %d, CurState = %d\n",
+				  p_ra->pre_ratr_state, p_ra->ratr_state);
+
+			rcu_read_lock();
+			sta = rtl_find_sta(hw, mac->bssid);
+			if (sta)
+				rtlpriv->cfg->ops->update_rate_tbl(hw, sta,
+						   p_ra->ratr_state);
+			rcu_read_unlock();
+
+			p_ra->pre_ratr_state = p_ra->ratr_state;
+		}
+	}
+}
+
+static void rtl92c_dm_init_dynamic_bb_powersaving(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct ps_t *dm_pstable = &rtlpriv->dm_pstable;
+
+	dm_pstable->pre_ccastate = CCA_MAX;
+	dm_pstable->cur_ccasate = CCA_MAX;
+	dm_pstable->pre_rfstate = RF_MAX;
+	dm_pstable->cur_rfstate = RF_MAX;
+	dm_pstable->rssi_val_min = 0;
+}
+
+static void rtl88e_dm_update_rx_idle_ant(struct ieee80211_hw *hw, u8 ant)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
+	struct fast_ant_training *fat_tbl = &(rtldm->fat_table);
+	u32 def_ant, opt_ant;
+
+	if (fat_tbl->rx_idle_ant != ant) {
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+			 "need to update rx idle ant\n");
+		if (ant == MAIN_ANT) {
+			def_ant = (fat_tbl->rx_idle_ant == CG_TRX_HW_ANTDIV) ?
+				   MAIN_ANT_CG_TRX : MAIN_ANT_CGCS_RX;
+			opt_ant = (fat_tbl->rx_idle_ant == CG_TRX_HW_ANTDIV) ?
+				   AUX_ANT_CG_TRX : AUX_ANT_CGCS_RX;
+		} else {
+			def_ant = (fat_tbl->rx_idle_ant == CG_TRX_HW_ANTDIV) ?
+				   AUX_ANT_CG_TRX : AUX_ANT_CGCS_RX;
+			opt_ant = (fat_tbl->rx_idle_ant == CG_TRX_HW_ANTDIV) ?
+				   MAIN_ANT_CG_TRX : MAIN_ANT_CGCS_RX;
+		}
+
+		if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) {
+			rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(5) |
+				      BIT(4) | BIT(3), def_ant);
+			rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(8) |
+				      BIT(7) | BIT(6), opt_ant);
+			rtl_set_bbreg(hw, DM_REG_ANTSEL_CTRL_11N, BIT(14) |
+				      BIT(13) | BIT(12), def_ant);
+			rtl_set_bbreg(hw, DM_REG_RESP_TX_11N, BIT(6) | BIT(7),
+				      def_ant);
+		} else if (rtlefuse->antenna_div_type == CGCS_RX_HW_ANTDIV) {
+			rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(5) |
+				      BIT(4) | BIT(3), def_ant);
+			rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(8) |
+				      BIT(7) | BIT(6), opt_ant);
+		}
+	}
+	fat_tbl->rx_idle_ant = ant;
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "RxIdleAnt %s\n",
+		 ((ant == MAIN_ANT) ? ("MAIN_ANT") : ("AUX_ANT")));
+}
+
+static void rtl88e_dm_update_tx_ant(struct ieee80211_hw *hw,
+	u8 ant, u32 mac_id)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
+	struct fast_ant_training *fat_tbl = &(rtldm->fat_table);
+	u8 target_ant;
+
+	if (ant == MAIN_ANT)
+		target_ant = MAIN_ANT_CG_TRX;
+	else
+		target_ant = AUX_ANT_CG_TRX;
+
+	fat_tbl->antsel_a[mac_id] = target_ant & BIT(0);
+	fat_tbl->antsel_b[mac_id] = (target_ant & BIT(1)) >> 1;
+	fat_tbl->antsel_c[mac_id] = (target_ant & BIT(2)) >> 2;
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "txfrominfo target ant %s\n",
+		 ((ant == MAIN_ANT) ? ("MAIN_ANT") : ("AUX_ANT")));
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "antsel_tr_mux = 3'b%d%d%d\n",
+		 fat_tbl->antsel_c[mac_id],
+		 fat_tbl->antsel_b[mac_id], fat_tbl->antsel_a[mac_id]);
+}
+
+static void rtl88e_dm_rx_hw_antena_div_init(struct ieee80211_hw *hw)
+{
+	u32  value32;
+	/*MAC Setting*/
+	value32 = rtl_get_bbreg(hw, DM_REG_ANTSEL_PIN_11N, MASKDWORD);
+	rtl_set_bbreg(hw, DM_REG_ANTSEL_PIN_11N, MASKDWORD, value32 |
+		     (BIT(23) | BIT(25)));
+	/*Pin Setting*/
+	rtl_set_bbreg(hw, DM_REG_PIN_CTRL_11N, BIT(9) | BIT(8), 0);
+	rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(10), 0);
+	rtl_set_bbreg(hw, DM_REG_LNA_SWITCH_11N, BIT(22), 1);
+	rtl_set_bbreg(hw, DM_REG_LNA_SWITCH_11N, BIT(31), 1);
+	/*OFDM Setting*/
+	rtl_set_bbreg(hw, DM_REG_ANTDIV_PARA1_11N, MASKDWORD, 0x000000a0);
+	/*CCK Setting*/
+	rtl_set_bbreg(hw, DM_REG_BB_PWR_SAV4_11N, BIT(7), 1);
+	rtl_set_bbreg(hw, DM_REG_CCK_ANTDIV_PARA2_11N, BIT(4), 1);
+	rtl88e_dm_update_rx_idle_ant(hw, MAIN_ANT);
+	rtl_set_bbreg(hw, DM_REG_ANT_MAPPING1_11N, MASKLWORD, 0x0201);
+}
+
+static void rtl88e_dm_trx_hw_antenna_div_init(struct ieee80211_hw *hw)
+{
+	u32  value32;
+
+	/*MAC Setting*/
+	value32 = rtl_get_bbreg(hw, DM_REG_ANTSEL_PIN_11N, MASKDWORD);
+	rtl_set_bbreg(hw, DM_REG_ANTSEL_PIN_11N, MASKDWORD, value32 |
+		     (BIT(23) | BIT(25)));
+	/*Pin Setting*/
+	rtl_set_bbreg(hw, DM_REG_PIN_CTRL_11N, BIT(9) | BIT(8), 0);
+	rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(10), 0);
+	rtl_set_bbreg(hw, DM_REG_LNA_SWITCH_11N, BIT(22), 0);
+	rtl_set_bbreg(hw, DM_REG_LNA_SWITCH_11N, BIT(31), 1);
+	/*OFDM Setting*/
+	rtl_set_bbreg(hw, DM_REG_ANTDIV_PARA1_11N, MASKDWORD, 0x000000a0);
+	/*CCK Setting*/
+	rtl_set_bbreg(hw, DM_REG_BB_PWR_SAV4_11N, BIT(7), 1);
+	rtl_set_bbreg(hw, DM_REG_CCK_ANTDIV_PARA2_11N, BIT(4), 1);
+	/*TX Setting*/
+	rtl_set_bbreg(hw, DM_REG_TX_ANT_CTRL_11N, BIT(21), 0);
+	rtl88e_dm_update_rx_idle_ant(hw, MAIN_ANT);
+	rtl_set_bbreg(hw, DM_REG_ANT_MAPPING1_11N, MASKLWORD, 0x0201);
+}
+
+static void rtl88e_dm_fast_training_init(struct ieee80211_hw *hw)
+{
+	struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
+	struct fast_ant_training *fat_tbl = &(rtldm->fat_table);
+	u32 ant_combo = 2;
+	u32 value32, i;
+
+	for (i = 0; i < 6; i++) {
+		fat_tbl->bssid[i] = 0;
+		fat_tbl->ant_sum[i] = 0;
+		fat_tbl->ant_cnt[i] = 0;
+		fat_tbl->ant_ave[i] = 0;
+	}
+	fat_tbl->train_idx = 0;
+	fat_tbl->fat_state = FAT_NORMAL_STATE;
+
+	/*MAC Setting*/
+	value32 = rtl_get_bbreg(hw, DM_REG_ANTSEL_PIN_11N, MASKDWORD);
+	rtl_set_bbreg(hw, DM_REG_ANTSEL_PIN_11N, MASKDWORD, value32 | (BIT(23) |
+		      BIT(25)));
+	value32 = rtl_get_bbreg(hw, DM_REG_ANT_TRAIN_2, MASKDWORD);
+	rtl_set_bbreg(hw, DM_REG_ANT_TRAIN_2, MASKDWORD, value32 | (BIT(16) |
+		      BIT(17)));
+	rtl_set_bbreg(hw, DM_REG_ANT_TRAIN_2, MASKLWORD, 0);
+	rtl_set_bbreg(hw, DM_REG_ANT_TRAIN_1, MASKDWORD, 0);
+
+	/*Pin Setting*/
+	rtl_set_bbreg(hw, DM_REG_PIN_CTRL_11N, BIT(9) | BIT(8), 0);
+	rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(10), 0);
+	rtl_set_bbreg(hw, DM_REG_LNA_SWITCH_11N, BIT(22), 0);
+	rtl_set_bbreg(hw, DM_REG_LNA_SWITCH_11N, BIT(31), 1);
+
+	/*OFDM Setting*/
+	rtl_set_bbreg(hw, DM_REG_ANTDIV_PARA1_11N, MASKDWORD, 0x000000a0);
+	/*antenna mapping table*/
+	if (ant_combo == 2) {
+		rtl_set_bbreg(hw, DM_REG_ANT_MAPPING1_11N, MASKBYTE0, 1);
+		rtl_set_bbreg(hw, DM_REG_ANT_MAPPING1_11N, MASKBYTE1, 2);
+	} else if (ant_combo == 7) {
+		rtl_set_bbreg(hw, DM_REG_ANT_MAPPING1_11N, MASKBYTE0, 1);
+		rtl_set_bbreg(hw, DM_REG_ANT_MAPPING1_11N, MASKBYTE1, 2);
+		rtl_set_bbreg(hw, DM_REG_ANT_MAPPING1_11N, MASKBYTE2, 2);
+		rtl_set_bbreg(hw, DM_REG_ANT_MAPPING1_11N, MASKBYTE3, 3);
+		rtl_set_bbreg(hw, DM_REG_ANT_MAPPING2_11N, MASKBYTE0, 4);
+		rtl_set_bbreg(hw, DM_REG_ANT_MAPPING2_11N, MASKBYTE1, 5);
+		rtl_set_bbreg(hw, DM_REG_ANT_MAPPING2_11N, MASKBYTE2, 6);
+		rtl_set_bbreg(hw, DM_REG_ANT_MAPPING2_11N, MASKBYTE3, 7);
+	}
+
+	/*TX Setting*/
+	rtl_set_bbreg(hw, DM_REG_TX_ANT_CTRL_11N, BIT(21), 1);
+	rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(5) | BIT(4) | BIT(3), 0);
+	rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(8) | BIT(7) | BIT(6), 1);
+	rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(2) | BIT(1) | BIT(0),
+		      (ant_combo - 1));
+
+	rtl_set_bbreg(hw, DM_REG_IGI_A_11N, BIT(7), 1);
+}
+
+static void rtl88e_dm_antenna_div_init(struct ieee80211_hw *hw)
+{
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+
+	if (rtlefuse->antenna_div_type == CGCS_RX_HW_ANTDIV)
+		rtl88e_dm_rx_hw_antena_div_init(hw);
+	else if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV)
+		rtl88e_dm_trx_hw_antenna_div_init(hw);
+	else if (rtlefuse->antenna_div_type == CG_TRX_SMART_ANTDIV)
+		rtl88e_dm_fast_training_init(hw);
+}
+
+void rtl88e_dm_set_tx_ant_by_tx_info(struct ieee80211_hw *hw,
+				     u8 *pdesc, u32 mac_id)
+{
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
+	struct fast_ant_training *fat_tbl = &(rtldm->fat_table);
+
+	if ((rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) ||
+	    (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV)) {
+		SET_TX_DESC_ANTSEL_A(pdesc, fat_tbl->antsel_a[mac_id]);
+		SET_TX_DESC_ANTSEL_B(pdesc, fat_tbl->antsel_b[mac_id]);
+		SET_TX_DESC_ANTSEL_C(pdesc, fat_tbl->antsel_c[mac_id]);
+	}
+}
+
+void rtl88e_dm_ant_sel_statistics(struct ieee80211_hw *hw,
+				  u8 antsel_tr_mux, u32 mac_id, u32 rx_pwdb_all)
+{
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
+	struct fast_ant_training *fat_tbl = &(rtldm->fat_table);
+
+	if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) {
+		if (antsel_tr_mux == MAIN_ANT_CG_TRX) {
+			fat_tbl->main_ant_sum[mac_id] += rx_pwdb_all;
+			fat_tbl->main_ant_cnt[mac_id]++;
+		} else {
+			fat_tbl->aux_ant_sum[mac_id] += rx_pwdb_all;
+			fat_tbl->aux_ant_cnt[mac_id]++;
+		}
+	} else if (rtlefuse->antenna_div_type == CGCS_RX_HW_ANTDIV) {
+		if (antsel_tr_mux == MAIN_ANT_CGCS_RX) {
+			fat_tbl->main_ant_sum[mac_id] += rx_pwdb_all;
+			fat_tbl->main_ant_cnt[mac_id]++;
+		} else {
+			fat_tbl->aux_ant_sum[mac_id] += rx_pwdb_all;
+			fat_tbl->aux_ant_cnt[mac_id]++;
+		}
+	}
+}
+
+static void rtl88e_dm_hw_ant_div(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct dig_t *dm_dig = &rtlpriv->dm_digtable;
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
+	struct rtl_sta_info *drv_priv;
+	struct fast_ant_training *fat_tbl = &(rtldm->fat_table);
+	u32 i, min_rssi = 0xff, ant_div_max_rssi = 0, max_rssi = 0;
+	u32 local_min_rssi, local_max_rssi;
+	u32 main_rssi, aux_rssi;
+	u8 rx_idle_ant = 0, target_ant = 7;
+
+	i = 0;
+	main_rssi = (fat_tbl->main_ant_cnt[i] != 0) ?
+		    (fat_tbl->main_ant_sum[i] /
+		     fat_tbl->main_ant_cnt[i]) : 0;
+	aux_rssi = (fat_tbl->aux_ant_cnt[i] != 0) ?
+		(fat_tbl->aux_ant_sum[i] / fat_tbl->aux_ant_cnt[i]) : 0;
+	target_ant = (main_rssi == aux_rssi) ?
+		     fat_tbl->rx_idle_ant : ((main_rssi >= aux_rssi) ?
+		     MAIN_ANT : AUX_ANT);
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+		 "main_ant_sum %d main_ant_cnt %d\n",
+		 fat_tbl->main_ant_sum[i], fat_tbl->main_ant_cnt[i]);
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+		 "aux_ant_sum %d aux_ant_cnt %d\n",
+		 fat_tbl->aux_ant_sum[i],
+		 fat_tbl->aux_ant_cnt[i]);
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+		 "main_rssi %d aux_rssi%d\n", main_rssi, aux_rssi);
+	local_max_rssi = (main_rssi > aux_rssi) ? main_rssi : aux_rssi;
+	if ((local_max_rssi > ant_div_max_rssi) && (local_max_rssi < 40))
+		ant_div_max_rssi = local_max_rssi;
+	if (local_max_rssi > max_rssi)
+		max_rssi = local_max_rssi;
+
+	if ((fat_tbl->rx_idle_ant == MAIN_ANT) && (main_rssi == 0))
+		main_rssi = aux_rssi;
+	else if ((fat_tbl->rx_idle_ant == AUX_ANT) && (aux_rssi == 0))
+		aux_rssi = main_rssi;
+
+	local_min_rssi = (main_rssi > aux_rssi) ? aux_rssi : main_rssi;
+	if (local_min_rssi < min_rssi) {
+		min_rssi = local_min_rssi;
+		rx_idle_ant = target_ant;
+	}
+	if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV)
+		rtl88e_dm_update_tx_ant(hw, target_ant, i);
+
+	if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP ||
+	    rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC) {
+		spin_lock_bh(&rtlpriv->locks.entry_list_lock);
+		list_for_each_entry(drv_priv, &rtlpriv->entry_list, list) {
+			i++;
+			main_rssi = (fat_tbl->main_ant_cnt[i] != 0) ?
+				(fat_tbl->main_ant_sum[i] /
+				 fat_tbl->main_ant_cnt[i]) : 0;
+			aux_rssi = (fat_tbl->aux_ant_cnt[i] != 0) ?
+				   (fat_tbl->aux_ant_sum[i] /
+				    fat_tbl->aux_ant_cnt[i]) : 0;
+			target_ant = (main_rssi == aux_rssi) ?
+				      fat_tbl->rx_idle_ant : ((main_rssi >=
+				      aux_rssi) ? MAIN_ANT : AUX_ANT);
+
+
+			local_max_rssi = max_t(u32, main_rssi, aux_rssi);
+			if ((local_max_rssi > ant_div_max_rssi) &&
+			    (local_max_rssi < 40))
+				ant_div_max_rssi = local_max_rssi;
+			if (local_max_rssi > max_rssi)
+				max_rssi = local_max_rssi;
+
+			if ((fat_tbl->rx_idle_ant == MAIN_ANT) && !main_rssi)
+				main_rssi = aux_rssi;
+			else if ((fat_tbl->rx_idle_ant == AUX_ANT) &&
+				 (aux_rssi == 0))
+				aux_rssi = main_rssi;
+
+			local_min_rssi = (main_rssi > aux_rssi) ?
+					  aux_rssi : main_rssi;
+			if (local_min_rssi < min_rssi) {
+				min_rssi = local_min_rssi;
+				rx_idle_ant = target_ant;
+			}
+			if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV)
+				rtl88e_dm_update_tx_ant(hw, target_ant, i);
+		}
+		spin_unlock_bh(&rtlpriv->locks.entry_list_lock);
+	}
+
+	for (i = 0; i < ASSOCIATE_ENTRY_NUM; i++) {
+		fat_tbl->main_ant_sum[i] = 0;
+		fat_tbl->aux_ant_sum[i] = 0;
+		fat_tbl->main_ant_cnt[i] = 0;
+		fat_tbl->aux_ant_cnt[i] = 0;
+	}
+
+	rtl88e_dm_update_rx_idle_ant(hw, rx_idle_ant);
+
+	dm_dig->antdiv_rssi_max = ant_div_max_rssi;
+	dm_dig->rssi_max = max_rssi;
+}
+
+static void rtl88e_set_next_mac_address_target(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
+	struct rtl_sta_info *drv_priv;
+	struct fast_ant_training *fat_tbl = &(rtldm->fat_table);
+	u32 value32, i, j = 0;
+
+	if (mac->link_state >= MAC80211_LINKED) {
+		for (i = 0; i < ASSOCIATE_ENTRY_NUM; i++) {
+			if ((fat_tbl->train_idx + 1) == ASSOCIATE_ENTRY_NUM)
+				fat_tbl->train_idx = 0;
+			else
+				fat_tbl->train_idx++;
+
+			if (fat_tbl->train_idx == 0) {
+				value32 = (mac->mac_addr[5] << 8) |
+					   mac->mac_addr[4];
+				rtl_set_bbreg(hw, DM_REG_ANT_TRAIN_2,
+					      MASKLWORD, value32);
+
+				value32 = (mac->mac_addr[3] << 24) |
+					  (mac->mac_addr[2] << 16) |
+					  (mac->mac_addr[1] << 8) |
+					   mac->mac_addr[0];
+				rtl_set_bbreg(hw, DM_REG_ANT_TRAIN_1,
+					      MASKDWORD, value32);
+				break;
+			}
+
+			if (rtlpriv->mac80211.opmode !=
+			    NL80211_IFTYPE_STATION) {
+				spin_lock_bh(&rtlpriv->locks.entry_list_lock);
+				list_for_each_entry(drv_priv,
+						    &rtlpriv->entry_list,
+						    list) {
+					j++;
+					if (j != fat_tbl->train_idx)
+						continue;
+
+					value32 = (drv_priv->mac_addr[5] << 8) |
+						   drv_priv->mac_addr[4];
+					rtl_set_bbreg(hw, DM_REG_ANT_TRAIN_2,
+						      MASKLWORD, value32);
+
+					value32 = (drv_priv->mac_addr[3]<<24) |
+						  (drv_priv->mac_addr[2]<<16) |
+						  (drv_priv->mac_addr[1]<<8) |
+						   drv_priv->mac_addr[0];
+					rtl_set_bbreg(hw, DM_REG_ANT_TRAIN_1,
+						      MASKDWORD, value32);
+					break;
+				}
+				spin_unlock_bh(&rtlpriv->locks.entry_list_lock);
+				/*find entry, break*/
+				if (j == fat_tbl->train_idx)
+					break;
+			}
+		}
+	}
+}
+
+static void rtl88e_dm_fast_ant_training(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
+	struct fast_ant_training *fat_tbl = &(rtldm->fat_table);
+	u32 i, max_rssi = 0;
+	u8 target_ant = 2;
+	bool bpkt_filter_match = false;
+
+	if (fat_tbl->fat_state == FAT_TRAINING_STATE) {
+		for (i = 0; i < 7; i++) {
+			if (fat_tbl->ant_cnt[i] == 0) {
+				fat_tbl->ant_ave[i] = 0;
+			} else {
+				fat_tbl->ant_ave[i] = fat_tbl->ant_sum[i] /
+					fat_tbl->ant_cnt[i];
+				bpkt_filter_match = true;
+			}
+
+			if (fat_tbl->ant_ave[i] > max_rssi) {
+				max_rssi = fat_tbl->ant_ave[i];
+				target_ant = (u8) i;
+			}
+		}
+
+		if (bpkt_filter_match == false) {
+			rtl_set_bbreg(hw, DM_REG_TXAGC_A_1_MCS32_11N,
+				      BIT(16), 0);
+			rtl_set_bbreg(hw, DM_REG_IGI_A_11N, BIT(7), 0);
+		} else {
+			rtl_set_bbreg(hw, DM_REG_TXAGC_A_1_MCS32_11N,
+				      BIT(16), 0);
+			rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(8) |
+				      BIT(7) | BIT(6), target_ant);
+			rtl_set_bbreg(hw, DM_REG_TX_ANT_CTRL_11N, BIT(21), 1);
+
+			fat_tbl->antsel_a[fat_tbl->train_idx] =
+				  target_ant & BIT(0);
+			fat_tbl->antsel_b[fat_tbl->train_idx] =
+				 (target_ant & BIT(1)) >> 1;
+			fat_tbl->antsel_c[fat_tbl->train_idx] =
+				 (target_ant & BIT(2)) >> 2;
+
+			if (target_ant == 0)
+				rtl_set_bbreg(hw, DM_REG_IGI_A_11N, BIT(7), 0);
+		}
+
+		for (i = 0; i < 7; i++) {
+			fat_tbl->ant_sum[i] = 0;
+			fat_tbl->ant_cnt[i] = 0;
+		}
+
+		fat_tbl->fat_state = FAT_NORMAL_STATE;
+		return;
+	}
+
+	if (fat_tbl->fat_state == FAT_NORMAL_STATE) {
+		rtl88e_set_next_mac_address_target(hw);
+
+		fat_tbl->fat_state = FAT_TRAINING_STATE;
+		rtl_set_bbreg(hw, DM_REG_TXAGC_A_1_MCS32_11N, BIT(16), 1);
+		rtl_set_bbreg(hw, DM_REG_IGI_A_11N, BIT(7), 1);
+
+		mod_timer(&rtlpriv->works.fast_antenna_training_timer,
+			  jiffies + MSECS(RTL_WATCH_DOG_TIME));
+	}
+}
+
+void rtl88e_dm_fast_antenna_training_callback(unsigned long data)
+{
+	struct ieee80211_hw *hw = (struct ieee80211_hw *)data;
+
+	rtl88e_dm_fast_ant_training(hw);
+}
+
+static void rtl88e_dm_antenna_diversity(struct ieee80211_hw *hw)
+{
+	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));
+	struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
+	struct fast_ant_training *fat_tbl = &(rtldm->fat_table);
+
+	if (mac->link_state < MAC80211_LINKED) {
+		RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "No Link\n");
+		if (fat_tbl->becomelinked == true) {
+			RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
+				 "need to turn off HW AntDiv\n");
+			rtl_set_bbreg(hw, DM_REG_IGI_A_11N, BIT(7), 0);
+			rtl_set_bbreg(hw, DM_REG_CCK_ANTDIV_PARA1_11N,
+				      BIT(15), 0);
+			if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV)
+				rtl_set_bbreg(hw, DM_REG_TX_ANT_CTRL_11N,
+					      BIT(21), 0);
+			fat_tbl->becomelinked =
+			  (mac->link_state == MAC80211_LINKED) ? true : false;
+		}
+		return;
+	} else {
+		if (fat_tbl->becomelinked == false) {
+			RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
+				 "Need to turn on HW AntDiv\n");
+			rtl_set_bbreg(hw, DM_REG_IGI_A_11N, BIT(7), 1);
+			rtl_set_bbreg(hw, DM_REG_CCK_ANTDIV_PARA1_11N,
+				      BIT(15), 1);
+			if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV)
+				rtl_set_bbreg(hw, DM_REG_TX_ANT_CTRL_11N,
+					      BIT(21), 1);
+			fat_tbl->becomelinked =
+			   (mac->link_state >= MAC80211_LINKED) ? true : false;
+		}
+	}
+
+	if ((rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) ||
+	    (rtlefuse->antenna_div_type == CGCS_RX_HW_ANTDIV))
+		rtl88e_dm_hw_ant_div(hw);
+	else if (rtlefuse->antenna_div_type == CG_TRX_SMART_ANTDIV)
+		rtl88e_dm_fast_ant_training(hw);
+}
+
+void rtl88e_dm_init(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER;
+	rtl88e_dm_diginit(hw);
+	rtl88e_dm_init_dynamic_txpower(hw);
+	rtl88e_dm_init_edca_turbo(hw);
+	rtl88e_dm_init_rate_adaptive_mask(hw);
+	rtl88e_dm_init_txpower_tracking(hw);
+	rtl92c_dm_init_dynamic_bb_powersaving(hw);
+	rtl88e_dm_antenna_div_init(hw);
+}
+
+void rtl88e_dm_watchdog(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+	bool fw_current_inpsmode = false;
+	bool fw_ps_awake = true;
+
+	rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
+				      (u8 *)(&fw_current_inpsmode));
+	rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON,
+				      (u8 *)(&fw_ps_awake));
+	if (ppsc->p2p_ps_info.p2p_ps_mode)
+		fw_ps_awake = false;
+
+	if ((ppsc->rfpwr_state == ERFON) &&
+	    ((!fw_current_inpsmode) && fw_ps_awake) &&
+	    (!ppsc->rfchange_inprogress)) {
+		rtl88e_dm_pwdb_monitor(hw);
+		rtl88e_dm_dig(hw);
+		rtl88e_dm_false_alarm_counter_statistics(hw);
+		rtl92c_dm_dynamic_txpower(hw);
+		rtl88e_dm_check_txpower_tracking(hw);
+		rtl88e_dm_refresh_rate_adaptive_mask(hw);
+		rtl88e_dm_check_edca_turbo(hw);
+		rtl88e_dm_antenna_diversity(hw);
+	}
+}
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/dm.h b/drivers/net/wireless/rtlwifi/rtl8188ee/dm.h
new file mode 100644
index 0000000..0e07f72
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8188ee/dm.h
@@ -0,0 +1,326 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2013  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	__RTL88E_DM_H__
+#define __RTL88E_DM_H__
+
+#define	MAIN_ANT					0
+#define	AUX_ANT						1
+#define	MAIN_ANT_CG_TRX					1
+#define	AUX_ANT_CG_TRX					0
+#define	MAIN_ANT_CGCS_RX				0
+#define	AUX_ANT_CGCS_RX					1
+
+/*RF REG LIST*/
+#define	DM_REG_RF_MODE_11N				0x00
+#define	DM_REG_RF_0B_11N				0x0B
+#define	DM_REG_CHNBW_11N				0x18
+#define	DM_REG_T_METER_11N				0x24
+#define	DM_REG_RF_25_11N				0x25
+#define	DM_REG_RF_26_11N				0x26
+#define	DM_REG_RF_27_11N				0x27
+#define	DM_REG_RF_2B_11N				0x2B
+#define	DM_REG_RF_2C_11N				0x2C
+#define	DM_REG_RXRF_A3_11N				0x3C
+#define	DM_REG_T_METER_92D_11N				0x42
+#define	DM_REG_T_METER_88E_11N				0x42
+
+/*BB REG LIST*/
+/*PAGE 8 */
+#define	DM_REG_BB_CTRL_11N				0x800
+#define	DM_REG_RF_PIN_11N				0x804
+#define	DM_REG_PSD_CTRL_11N				0x808
+#define	DM_REG_TX_ANT_CTRL_11N				0x80C
+#define	DM_REG_BB_PWR_SAV5_11N				0x818
+#define	DM_REG_CCK_RPT_FORMAT_11N			0x824
+#define	DM_REG_RX_DEFAULT_A_11N				0x858
+#define	DM_REG_RX_DEFAULT_B_11N				0x85A
+#define	DM_REG_BB_PWR_SAV3_11N				0x85C
+#define	DM_REG_ANTSEL_CTRL_11N				0x860
+#define	DM_REG_RX_ANT_CTRL_11N				0x864
+#define	DM_REG_PIN_CTRL_11N				0x870
+#define	DM_REG_BB_PWR_SAV1_11N				0x874
+#define	DM_REG_ANTSEL_PATH_11N				0x878
+#define	DM_REG_BB_3WIRE_11N				0x88C
+#define	DM_REG_SC_CNT_11N				0x8C4
+#define	DM_REG_PSD_DATA_11N				0x8B4
+/*PAGE 9*/
+#define	DM_REG_ANT_MAPPING1_11N				0x914
+#define	DM_REG_ANT_MAPPING2_11N				0x918
+/*PAGE A*/
+#define	DM_REG_CCK_ANTDIV_PARA1_11N			0xA00
+#define	DM_REG_CCK_CCA_11N				0xA0A
+#define	DM_REG_CCK_ANTDIV_PARA2_11N			0xA0C
+#define	DM_REG_CCK_ANTDIV_PARA3_11N			0xA10
+#define	DM_REG_CCK_ANTDIV_PARA4_11N			0xA14
+#define	DM_REG_CCK_FILTER_PARA1_11N			0xA22
+#define	DM_REG_CCK_FILTER_PARA2_11N			0xA23
+#define	DM_REG_CCK_FILTER_PARA3_11N			0xA24
+#define	DM_REG_CCK_FILTER_PARA4_11N			0xA25
+#define	DM_REG_CCK_FILTER_PARA5_11N			0xA26
+#define	DM_REG_CCK_FILTER_PARA6_11N			0xA27
+#define	DM_REG_CCK_FILTER_PARA7_11N			0xA28
+#define	DM_REG_CCK_FILTER_PARA8_11N			0xA29
+#define	DM_REG_CCK_FA_RST_11N				0xA2C
+#define	DM_REG_CCK_FA_MSB_11N				0xA58
+#define	DM_REG_CCK_FA_LSB_11N				0xA5C
+#define	DM_REG_CCK_CCA_CNT_11N				0xA60
+#define	DM_REG_BB_PWR_SAV4_11N				0xA74
+/*PAGE B */
+#define	DM_REG_LNA_SWITCH_11N				0xB2C
+#define	DM_REG_PATH_SWITCH_11N				0xB30
+#define	DM_REG_RSSI_CTRL_11N				0xB38
+#define	DM_REG_CONFIG_ANTA_11N				0xB68
+#define	DM_REG_RSSI_BT_11N				0xB9C
+/*PAGE C */
+#define	DM_REG_OFDM_FA_HOLDC_11N			0xC00
+#define	DM_REG_RX_PATH_11N				0xC04
+#define	DM_REG_TRMUX_11N				0xC08
+#define	DM_REG_OFDM_FA_RSTC_11N				0xC0C
+#define	DM_REG_RXIQI_MATRIX_11N				0xC14
+#define	DM_REG_TXIQK_MATRIX_LSB1_11N			0xC4C
+#define	DM_REG_IGI_A_11N				0xC50
+#define	DM_REG_ANTDIV_PARA2_11N				0xC54
+#define	DM_REG_IGI_B_11N				0xC58
+#define	DM_REG_ANTDIV_PARA3_11N				0xC5C
+#define	DM_REG_BB_PWR_SAV2_11N				0xC70
+#define	DM_REG_RX_OFF_11N				0xC7C
+#define	DM_REG_TXIQK_MATRIXA_11N			0xC80
+#define	DM_REG_TXIQK_MATRIXB_11N			0xC88
+#define	DM_REG_TXIQK_MATRIXA_LSB2_11N			0xC94
+#define	DM_REG_TXIQK_MATRIXB_LSB2_11N			0xC9C
+#define	DM_REG_RXIQK_MATRIX_LSB_11N			0xCA0
+#define	DM_REG_ANTDIV_PARA1_11N				0xCA4
+#define	DM_REG_OFDM_FA_TYPE1_11N			0xCF0
+/*PAGE D */
+#define	DM_REG_OFDM_FA_RSTD_11N				0xD00
+#define	DM_REG_OFDM_FA_TYPE2_11N			0xDA0
+#define	DM_REG_OFDM_FA_TYPE3_11N			0xDA4
+#define	DM_REG_OFDM_FA_TYPE4_11N			0xDA8
+/*PAGE E */
+#define	DM_REG_TXAGC_A_6_18_11N				0xE00
+#define	DM_REG_TXAGC_A_24_54_11N			0xE04
+#define	DM_REG_TXAGC_A_1_MCS32_11N			0xE08
+#define	DM_REG_TXAGC_A_MCS0_3_11N			0xE10
+#define	DM_REG_TXAGC_A_MCS4_7_11N			0xE14
+#define	DM_REG_TXAGC_A_MCS8_11_11N			0xE18
+#define	DM_REG_TXAGC_A_MCS12_15_11N			0xE1C
+#define	DM_REG_FPGA0_IQK_11N				0xE28
+#define	DM_REG_TXIQK_TONE_A_11N				0xE30
+#define	DM_REG_RXIQK_TONE_A_11N				0xE34
+#define	DM_REG_TXIQK_PI_A_11N				0xE38
+#define	DM_REG_RXIQK_PI_A_11N				0xE3C
+#define	DM_REG_TXIQK_11N				0xE40
+#define	DM_REG_RXIQK_11N				0xE44
+#define	DM_REG_IQK_AGC_PTS_11N				0xE48
+#define	DM_REG_IQK_AGC_RSP_11N				0xE4C
+#define	DM_REG_BLUETOOTH_11N				0xE6C
+#define	DM_REG_RX_WAIT_CCA_11N				0xE70
+#define	DM_REG_TX_CCK_RFON_11N				0xE74
+#define	DM_REG_TX_CCK_BBON_11N				0xE78
+#define	DM_REG_OFDM_RFON_11N				0xE7C
+#define	DM_REG_OFDM_BBON_11N				0xE80
+#define DM_REG_TX2RX_11N				0xE84
+#define	DM_REG_TX2TX_11N				0xE88
+#define	DM_REG_RX_CCK_11N				0xE8C
+#define	DM_REG_RX_OFDM_11N				0xED0
+#define	DM_REG_RX_WAIT_RIFS_11N				0xED4
+#define	DM_REG_RX2RX_11N				0xED8
+#define	DM_REG_STANDBY_11N				0xEDC
+#define	DM_REG_SLEEP_11N				0xEE0
+#define	DM_REG_PMPD_ANAEN_11N				0xEEC
+
+
+/*MAC REG LIST*/
+#define	DM_REG_BB_RST_11N				0x02
+#define	DM_REG_ANTSEL_PIN_11N				0x4C
+#define	DM_REG_EARLY_MODE_11N				0x4D0
+#define	DM_REG_RSSI_MONITOR_11N				0x4FE
+#define	DM_REG_EDCA_VO_11N				0x500
+#define	DM_REG_EDCA_VI_11N				0x504
+#define	DM_REG_EDCA_BE_11N				0x508
+#define	DM_REG_EDCA_BK_11N				0x50C
+#define	DM_REG_TXPAUSE_11N				0x522
+#define	DM_REG_RESP_TX_11N				0x6D8
+#define	DM_REG_ANT_TRAIN_1				0x7b0
+#define	DM_REG_ANT_TRAIN_2				0x7b4
+
+/*DIG Related*/
+#define	DM_BIT_IGI_11N					0x0000007F
+
+#define HAL_DM_DIG_DISABLE				BIT(0)
+#define HAL_DM_HIPWR_DISABLE				BIT(1)
+
+#define OFDM_TABLE_LENGTH				43
+#define CCK_TABLE_LENGTH				33
+
+#define OFDM_TABLE_SIZE					43
+#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					0x1e
+
+#define DM_DIG_MAX_AP					0x32
+#define DM_DIG_MIN_AP					0x20
+
+#define DM_DIG_FA_UPPER					0x3e
+#define DM_DIG_FA_LOWER					0x1e
+#define DM_DIG_FA_TH0					0x200
+#define DM_DIG_FA_TH1					0x300
+#define DM_DIG_FA_TH2					0x400
+
+#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 TXPWRTRACK_MAX_IDX				6
+
+struct swat_t {
+	u8 failure_cnt;
+	u8 try_flag;
+	u8 stop_trying;
+	long pre_rssi;
+	long trying_threshold;
+	u8 cur_antenna;
+	u8 pre_antenna;
+};
+
+enum FAT_STATE {
+	FAT_NORMAL_STATE	= 0,
+	FAT_TRAINING_STATE = 1,
+};
+
+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_e {
+	CCA_1R = 0,
+	CCA_2R = 1,
+	CCA_MAX = 2,
+};
+
+enum dm_rf_e {
+	RF_SAVE = 0,
+	RF_NORMAL = 1,
+	RF_MAX = 2,
+};
+
+enum dm_sw_ant_switch_e {
+	ANS_ANTENNA_B = 1,
+	ANS_ANTENNA_A = 2,
+	ANS_ANTENNA_MAX = 3,
+};
+
+enum dm_dig_ext_port_alg_e {
+	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_e {
+	DIG_STA_DISCONNECT = 0,
+	DIG_STA_CONNECT = 1,
+	DIG_STA_BEFORE_CONNECT = 2,
+	DIG_MULTISTA_DISCONNECT = 3,
+	DIG_MULTISTA_CONNECT = 4,
+	DIG_CONNECT_MAX
+};
+
+enum pwr_track_control_method {
+	BBSWING,
+	TXAGC
+};
+
+void rtl88e_dm_set_tx_ant_by_tx_info(struct ieee80211_hw *hw,
+				     u8 *pdesc, u32 mac_id);
+void rtl88e_dm_ant_sel_statistics(struct ieee80211_hw *hw, u8 antsel_tr_mux,
+				  u32 mac_id, u32 rx_pwdb_all);
+void rtl88e_dm_fast_antenna_training_callback(unsigned long data);
+void rtl88e_dm_init(struct ieee80211_hw *hw);
+void rtl88e_dm_watchdog(struct ieee80211_hw *hw);
+void rtl88e_dm_write_dig(struct ieee80211_hw *hw);
+void rtl88e_dm_init_edca_turbo(struct ieee80211_hw *hw);
+void rtl88e_dm_check_txpower_tracking(struct ieee80211_hw *hw);
+void rtl88e_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw);
+void rtl88e_dm_txpower_track_adjust(struct ieee80211_hw *hw,
+				    u8 type, u8 *pdirection,
+				    u32 *poutwrite_val);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/fw.c b/drivers/net/wireless/rtlwifi/rtl8188ee/fw.c
new file mode 100644
index 0000000..57e4cc5
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8188ee/fw.c
@@ -0,0 +1,830 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2013  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 <linux/kmemleak.h>
+
+static void _rtl88e_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);
+
+		rtl_write_byte(rtlpriv, REG_MCUFWDL + 1, 0x00);
+	}
+}
+
+static void _rtl88e_fw_block_write(struct ieee80211_hw *hw,
+				   const u8 *buffer, u32 size)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u32 blk_sz = sizeof(u32);
+	u8 *buf_ptr = (u8 *)buffer;
+	u32 *pu4BytePtr = (u32 *)buffer;
+	u32 i, offset, blk_cnt, remain;
+
+	blk_cnt = size / blk_sz;
+	remain = size % blk_sz;
+
+	for (i = 0; i < blk_cnt; i++) {
+		offset = i * blk_sz;
+		rtl_write_dword(rtlpriv, (FW_8192C_START_ADDRESS + offset),
+				*(pu4BytePtr + i));
+	}
+
+	if (remain) {
+		offset = blk_cnt * blk_sz;
+		buf_ptr += offset;
+		for (i = 0; i < remain; i++) {
+			rtl_write_byte(rtlpriv, (FW_8192C_START_ADDRESS +
+						 offset + i), *(buf_ptr + i));
+		}
+	}
+}
+
+static void _rtl88e_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);
+	_rtl88e_fw_block_write(hw, buffer, size);
+}
+
+static void _rtl88e_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 _rtl88e_write_fw(struct ieee80211_hw *hw,
+			     enum version_8188e version, u8 *buffer, u32 size)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u8 *buf_ptr = (u8 *)buffer;
+	u32 page_no, remain;
+	u32 page, offset;
+
+	RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "FW size is %d bytes,\n", size);
+
+	_rtl88e_fill_dummy(buf_ptr, &size);
+
+	page_no = size / FW_8192C_PAGE_SIZE;
+	remain = size % FW_8192C_PAGE_SIZE;
+
+	if (page_no > 8) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 "Page numbers should not greater then 8\n");
+	}
+
+	for (page = 0; page < page_no; page++) {
+		offset = page * FW_8192C_PAGE_SIZE;
+		_rtl88e_fw_page_write(hw, page, (buf_ptr + offset),
+				      FW_8192C_PAGE_SIZE);
+	}
+
+	if (remain) {
+		offset = page_no * FW_8192C_PAGE_SIZE;
+		page = page_no;
+		_rtl88e_fw_page_write(hw, page, (buf_ptr + offset), remain);
+	}
+}
+
+static int _rtl88e_fw_free_to_go(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	int err = -EIO;
+	u32 counter = 0;
+	u32 value32;
+
+	do {
+		value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
+	} while ((counter++ < FW_8192C_POLLING_TIMEOUT_COUNT) &&
+		 (!(value32 & FWDL_CHKSUM_RPT)));
+
+	if (counter >= FW_8192C_POLLING_TIMEOUT_COUNT) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 "chksum report faill ! REG_MCUFWDL:0x%08x .\n",
+			  value32);
+		goto exit;
+	}
+
+	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;
+	value32 &= ~WINTINI_RDY;
+	rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
+
+	rtl88e_firmware_selfreset(hw);
+	counter = 0;
+
+	do {
+		value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
+		if (value32 & WINTINI_RDY) {
+			RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
+				 "Polling FW ready success!! REG_MCUFWDL:0x%08x.\n",
+				  value32);
+			err = 0;
+			goto exit;
+		}
+
+		udelay(FW_8192C_POLLING_DELAY);
+
+	} while (counter++ < FW_8192C_POLLING_TIMEOUT_COUNT);
+
+	RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+		 "Polling FW ready fail!! REG_MCUFWDL:0x%08x .\n", value32);
+
+exit:
+	return err;
+}
+
+int rtl88e_download_fw(struct ieee80211_hw *hw, bool buse_wake_on_wlan_fw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	struct rtl92c_firmware_header *pfwheader;
+	u8 *pfwdata;
+	u32 fwsize;
+	int err;
+	enum version_8188e version = rtlhal->version;
+
+	if (!rtlhal->pfirmware)
+		return 1;
+
+	pfwheader = (struct rtl92c_firmware_header *)rtlhal->pfirmware;
+	pfwdata = (u8 *)rtlhal->pfirmware;
+	fwsize = rtlhal->fwsize;
+	RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
+		 "normal Firmware SIZE %d\n", fwsize);
+
+	if (IS_FW_HEADER_EXIST(pfwheader)) {
+		RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
+			 "Firmware Version(%d), Signature(%#x), Size(%d)\n",
+			 pfwheader->version, pfwheader->signature,
+			 (int)sizeof(struct rtl92c_firmware_header));
+
+		pfwdata = pfwdata + sizeof(struct rtl92c_firmware_header);
+		fwsize = fwsize - sizeof(struct rtl92c_firmware_header);
+	}
+
+	if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) {
+		rtl_write_byte(rtlpriv, REG_MCUFWDL, 0);
+		rtl88e_firmware_selfreset(hw);
+	}
+	_rtl88e_enable_fw_download(hw, true);
+	_rtl88e_write_fw(hw, version, pfwdata, fwsize);
+	_rtl88e_enable_fw_download(hw, false);
+
+	err = _rtl88e_fw_free_to_go(hw);
+
+	RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
+		 "Firmware is%s ready to run!\n", err ? " not" : "");
+	return 0;
+}
+
+static bool _rtl88e_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u8 val_hmetfr;
+
+	val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR);
+	if (((val_hmetfr >> boxnum) & BIT(0)) == 0)
+		return true;
+	return false;
+}
+
+static void _rtl88e_fill_h2c_command(struct ieee80211_hw *hw,
+				     u8 element_id, u32 cmd_len,
+				     u8 *cmd_b)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	u8 boxnum;
+	u16 box_reg = 0, box_extreg = 0;
+	u8 u1b_tmp;
+	bool isfw_read = false;
+	u8 buf_index = 0;
+	bool write_sucess = false;
+	u8 wait_h2c_limit = 100;
+	u8 wait_writeh2c_limit = 100;
+	u8 boxc[4], boxext[2];
+	u32 h2c_waitcounter = 0;
+	unsigned long flag;
+	u8 idx;
+
+	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 (!write_sucess) {
+		wait_writeh2c_limit--;
+		if (wait_writeh2c_limit == 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 processed\n");
+			break;
+		}
+
+		isfw_read = _rtl88e_check_fw_read_last_h2c(hw, boxnum);
+		while (!isfw_read) {
+			wait_h2c_limit--;
+			if (wait_h2c_limit == 0) {
+				RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+					 "Wating too long for FW read "
+					 "clear HMEBox(%d)!\n", boxnum);
+				break;
+			}
+
+			udelay(10);
+
+			isfw_read = _rtl88e_check_fw_read_last_h2c(hw, boxnum);
+			u1b_tmp = rtl_read_byte(rtlpriv, 0x130);
+			RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+				 "Wating for FW read clear HMEBox(%d)!!! "
+				 "0x130 = %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(boxc, 0, sizeof(boxc));
+		memset(boxext, 0, sizeof(boxext));
+		boxc[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:
+		case 2:
+		case 3:
+			/*boxc[0] &= ~(BIT(7));*/
+			memcpy((u8 *)(boxc) + 1, cmd_b + buf_index, cmd_len);
+
+			for (idx = 0; idx < 4; idx++)
+				rtl_write_byte(rtlpriv, box_reg+idx, boxc[idx]);
+			break;
+		case 4:
+		case 5:
+		case 6:
+		case 7:
+			/*boxc[0] |= (BIT(7));*/
+			memcpy((u8 *)(boxext), cmd_b + buf_index+3, cmd_len-3);
+			memcpy((u8 *)(boxc) + 1, cmd_b + buf_index, 3);
+
+			for (idx = 0; idx < 2; idx++) {
+				rtl_write_byte(rtlpriv, box_extreg + idx,
+					       boxext[idx]);
+			}
+
+			for (idx = 0; idx < 4; idx++) {
+				rtl_write_byte(rtlpriv, box_reg + idx,
+					       boxc[idx]);
+			}
+			break;
+		default:
+			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+				 "switch case not processed\n");
+			break;
+		}
+
+		write_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 rtl88e_fill_h2c_cmd(struct ieee80211_hw *hw,
+			 u8 element_id, u32 cmd_len, u8 *cmd_b)
+{
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	u32 tmp_cmdbuf[2];
+
+	if (rtlhal->fw_ready == false) {
+		RT_ASSERT(false, "fail H2C cmd - Fw download fail!!!\n");
+		return;
+	}
+
+	memset(tmp_cmdbuf, 0, 8);
+	memcpy(tmp_cmdbuf, cmd_b, cmd_len);
+	_rtl88e_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf);
+
+	return;
+}
+
+void rtl88e_firmware_selfreset(struct ieee80211_hw *hw)
+{
+	u8 u1b_tmp;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN+1);
+	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN+1, (u1b_tmp & (~BIT(2))));
+	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN+1, (u1b_tmp | BIT(2)));
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+		 "8051Reset88E(): 8051 reset success.\n");
+}
+
+void rtl88e_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u8 u1_h2c_set_pwrmode[H2C_88E_PWEMODE_LENGTH] = { 0 };
+	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+	u8 power_state = 0;
+
+	RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode);
+	SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0));
+	SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, 0);
+	SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode,
+					 (rtlpriv->mac80211.p2p) ?
+					 ppsc->smart_ps : 1);
+	SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode,
+					       ppsc->reg_max_lps_awakeintvl);
+	SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0);
+	if (mode == FW_PS_ACTIVE_MODE)
+		power_state |= FW_PWR_STATE_ACTIVE;
+	else
+		power_state |= FW_PWR_STATE_RF_OFF;
+	SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state);
+
+	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
+		      "rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n",
+		      u1_h2c_set_pwrmode, H2C_88E_PWEMODE_LENGTH);
+	rtl88e_fill_h2c_cmd(hw, H2C_88E_SETPWRMODE, H2C_88E_PWEMODE_LENGTH,
+			    u1_h2c_set_pwrmode);
+}
+
+void rtl88e_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);
+
+	rtl88e_fill_h2c_cmd(hw, H2C_88E_JOINBSSRPT, 1, u1_joinbssrpt_parm);
+}
+
+void rtl88e_set_fw_ap_off_load_cmd(struct ieee80211_hw *hw,
+				   u8 ap_offload_enable)
+{
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	u8 u1_apoffload_parm[H2C_88E_AP_OFFLOAD_LENGTH] = { 0 };
+
+	SET_H2CCMD_AP_OFFLOAD_ON(u1_apoffload_parm, ap_offload_enable);
+	SET_H2CCMD_AP_OFFLOAD_HIDDEN(u1_apoffload_parm, mac->hiddenssid);
+	SET_H2CCMD_AP_OFFLOAD_DENYANY(u1_apoffload_parm, 0);
+
+	rtl88e_fill_h2c_cmd(hw, H2C_88E_AP_OFFLOAD, H2C_88E_AP_OFFLOAD_LENGTH,
+			    u1_apoffload_parm);
+}
+
+static bool _rtl88e_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;
+	struct sk_buff *pskb = NULL;
+	unsigned long flags;
+
+	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[0];
+
+	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 rtl88e_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_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;
+	u8 u1RsvdPageLoc[5] = { 0 };
+
+	u8 *beacon;
+	u8 *pspoll;
+	u8 *nullfunc;
+	u8 *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
+	 *--------------------------------------------------------
+	 */
+	pspoll = &reserved_page_packet[PSPOLL_PG * 128];
+	SET_80211_PS_POLL_AID(pspoll, (mac->assoc_id | 0xc000));
+	SET_80211_PS_POLL_BSSID(pspoll, mac->bssid);
+	SET_80211_PS_POLL_TA(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
+	 *----------------------------------------------------------
+	 */
+	probersp = &reserved_page_packet[PROBERSP_PG * 128];
+	SET_80211_HDR_ADDRESS1(probersp, mac->bssid);
+	SET_80211_HDR_ADDRESS2(probersp, mac->mac_addr);
+	SET_80211_HDR_ADDRESS3(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,
+		      "rtl88e_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
+		      &reserved_page_packet[0], totalpacketlen);
+	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
+		      "rtl88e_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
+		      u1RsvdPageLoc, 3);
+
+	skb = dev_alloc_skb(totalpacketlen);
+	if (!skb)
+		return;
+	kmemleak_not_leak(skb);
+	memcpy(skb_put(skb, totalpacketlen),
+	       &reserved_page_packet, totalpacketlen);
+
+	if (_rtl88e_cmd_send_packet(hw, skb)) {
+		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);
+		rtl88e_fill_h2c_cmd(hw, H2C_88E_RSVDPAGE,
+				    sizeof(u1RsvdPageLoc), u1RsvdPageLoc);
+	} else
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+			 "Set RSVD page location to Fw FAIL!!!!!!.\n");
+}
+
+/*Shoud check FW support p2p or not.*/
+static void rtl88e_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, u8 ctwindow)
+{
+	u8 u1_ctwindow_period[1] = {ctwindow};
+
+	rtl88e_fill_h2c_cmd(hw, H2C_88E_P2P_PS_CTW_CMD, 1, u1_ctwindow_period);
+}
+
+void rtl88e_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw));
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	struct rtl_p2p_ps_info *p2pinfo = &(rtlps->p2p_ps_info);
+	struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload;
+	u8	i;
+	u16	ctwindow;
+	u32	start_time, tsf_low;
+
+	switch (p2p_ps_state) {
+	case P2P_PS_DISABLE:
+		RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_DISABLE\n");
+		memset(p2p_ps_offload, 0, sizeof(struct p2p_ps_offload_t));
+		break;
+	case P2P_PS_ENABLE:
+		RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_ENABLE\n");
+		/* update CTWindow value. */
+		if (p2pinfo->ctwindow > 0) {
+			p2p_ps_offload->ctwindow_en = 1;
+			ctwindow = p2pinfo->ctwindow;
+			rtl88e_set_p2p_ctw_period_cmd(hw, ctwindow);
+		}
+		/* hw only support 2 set of NoA */
+		for (i = 0; i < p2pinfo->noa_num; i++) {
+			/* To control the register setting for which NOA*/
+			rtl_write_byte(rtlpriv, 0x5cf, (i << 4));
+			if (i == 0)
+				p2p_ps_offload->noa0_en = 1;
+			else
+				p2p_ps_offload->noa1_en = 1;
+
+			/* config P2P NoA Descriptor Register */
+			rtl_write_dword(rtlpriv, 0x5E0,
+					p2pinfo->noa_duration[i]);
+			rtl_write_dword(rtlpriv, 0x5E4,
+					p2pinfo->noa_interval[i]);
+
+			/*Get Current TSF value */
+			tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR);
+
+			start_time = p2pinfo->noa_start_time[i];
+			if (p2pinfo->noa_count_type[i] != 1) {
+				while (start_time <= (tsf_low + (50 * 1024))) {
+					start_time += p2pinfo->noa_interval[i];
+					if (p2pinfo->noa_count_type[i] != 255)
+						p2pinfo->noa_count_type[i]--;
+				}
+			}
+			rtl_write_dword(rtlpriv, 0x5E8, start_time);
+			rtl_write_dword(rtlpriv, 0x5EC,
+					p2pinfo->noa_count_type[i]);
+		}
+
+		if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) {
+			/* rst p2p circuit */
+			rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4));
+
+			p2p_ps_offload->offload_en = 1;
+
+			if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) {
+				p2p_ps_offload->role = 1;
+				p2p_ps_offload->allstasleep = 0;
+			} else {
+				p2p_ps_offload->role = 0;
+			}
+
+			p2p_ps_offload->discovery = 0;
+		}
+		break;
+	case P2P_PS_SCAN:
+		RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n");
+		p2p_ps_offload->discovery = 1;
+		break;
+	case P2P_PS_SCAN_DONE:
+		RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN_DONE\n");
+		p2p_ps_offload->discovery = 0;
+		p2pinfo->p2p_ps_state = P2P_PS_ENABLE;
+		break;
+	default:
+		break;
+	}
+
+	rtl88e_fill_h2c_cmd(hw, H2C_88E_P2P_PS_OFFLOAD, 1,
+			    (u8 *)p2p_ps_offload);
+}
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/fw.h b/drivers/net/wireless/rtlwifi/rtl8188ee/fw.h
new file mode 100644
index 0000000..854a987
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8188ee/fw.h
@@ -0,0 +1,301 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2013  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__FW__H__
+#define __RTL92C__FW__H__
+
+#define FW_8192C_SIZE				0x8000
+#define FW_8192C_START_ADDRESS			0x1000
+#define FW_8192C_END_ADDRESS			0x5FFF
+#define FW_8192C_PAGE_SIZE			4096
+#define FW_8192C_POLLING_DELAY			5
+#define FW_8192C_POLLING_TIMEOUT_COUNT		3000
+
+#define IS_FW_HEADER_EXIST(_pfwhdr)		\
+	((_pfwhdr->signature&0xFFFF) == 0x88E1)
+#define USE_OLD_WOWLAN_DEBUG_FW			0
+
+#define H2C_88E_RSVDPAGE_LOC_LEN		5
+#define H2C_88E_PWEMODE_LENGTH			5
+#define H2C_88E_JOINBSSRPT_LENGTH		1
+#define H2C_88E_AP_OFFLOAD_LENGTH		3
+#define H2C_88E_WOWLAN_LENGTH			3
+#define H2C_88E_KEEP_ALIVE_CTRL_LENGTH		3
+#if (USE_OLD_WOWLAN_DEBUG_FW == 0)
+#define H2C_88E_REMOTE_WAKE_CTRL_LEN		1
+#else
+#define H2C_88E_REMOTE_WAKE_CTRL_LEN		3
+#endif
+#define H2C_88E_AOAC_GLOBAL_INFO_LEN		2
+#define H2C_88E_AOAC_RSVDPAGE_LOC_LEN		7
+
+/* Fw PS state for RPWM.
+ * BIT[2:0] = HW state
+ * BIT[3] = Protocol PS state, 1: register active state, 0: register sleep state
+ * BIT[4] = sub-state
+ */
+#define	FW_PS_GO_ON			BIT(0)
+#define	FW_PS_TX_NULL			BIT(1)
+#define	FW_PS_RF_ON			BIT(2)
+#define	FW_PS_REGISTER_ACTIVE		BIT(3)
+
+#define	FW_PS_DPS			BIT(0)
+#define	FW_PS_LCLK			(FW_PS_DPS)
+#define	FW_PS_RF_OFF			BIT(1)
+#define	FW_PS_ALL_ON			BIT(2)
+#define	FW_PS_ST_ACTIVE			BIT(3)
+#define	FW_PS_ISR_ENABLE		BIT(4)
+#define	FW_PS_IMR_ENABLE		BIT(5)
+
+
+#define	FW_PS_ACK			BIT(6)
+#define	FW_PS_TOGGLE			BIT(7)
+
+ /* 88E RPWM value*/
+ /* BIT[0] = 1: 32k, 0: 40M*/
+#define	FW_PS_CLOCK_OFF			BIT(0)		/* 32k*/
+#define	FW_PS_CLOCK_ON			0		/*40M*/
+
+#define	FW_PS_STATE_MASK		(0x0F)
+#define	FW_PS_STATE_HW_MASK		(0x07)
+/*ISR_ENABLE, IMR_ENABLE, and PS mode should be inherited.*/
+#define	FW_PS_STATE_INT_MASK		(0x3F)
+
+#define	FW_PS_STATE(x)			(FW_PS_STATE_MASK & (x))
+#define	FW_PS_STATE_HW(x)		(FW_PS_STATE_HW_MASK & (x))
+#define	FW_PS_STATE_INT(x)		(FW_PS_STATE_INT_MASK & (x))
+#define	FW_PS_ISR_VAL(x)		((x) & 0x70)
+#define	FW_PS_IMR_MASK(x)		((x) & 0xDF)
+#define	FW_PS_KEEP_IMR(x)		((x) & 0x20)
+
+#define	FW_PS_STATE_S0			(FW_PS_DPS)
+#define	FW_PS_STATE_S1			(FW_PS_LCLK)
+#define	FW_PS_STATE_S2			(FW_PS_RF_OFF)
+#define	FW_PS_STATE_S3			(FW_PS_ALL_ON)
+#define	FW_PS_STATE_S4			((FW_PS_ST_ACTIVE) | (FW_PS_ALL_ON))
+
+#define	FW_PS_STATE_ALL_ON_88E		(FW_PS_CLOCK_ON)
+#define	FW_PS_STATE_RF_ON_88E		(FW_PS_CLOCK_ON)
+#define	FW_PS_STATE_RF_OFF_88E		(FW_PS_CLOCK_ON)
+#define	FW_PS_STATE_RF_OFF_LOW_PWR_88E	(FW_PS_CLOCK_OFF)
+
+#define	FW_PS_STATE_ALL_ON_92C		(FW_PS_STATE_S4)
+#define	FW_PS_STATE_RF_ON_92C		(FW_PS_STATE_S3)
+#define	FW_PS_STATE_RF_OFF_92C		(FW_PS_STATE_S2)
+#define	FW_PS_STATE_RF_OFF_LOW_PWR_92C	(FW_PS_STATE_S1)
+
+/* For 88E H2C PwrMode Cmd ID 5.*/
+#define	FW_PWR_STATE_ACTIVE	((FW_PS_RF_ON) | (FW_PS_REGISTER_ACTIVE))
+#define	FW_PWR_STATE_RF_OFF		0
+
+#define	FW_PS_IS_ACK(x)			((x) & FW_PS_ACK)
+#define	FW_PS_IS_CLK_ON(x)		((x) & (FW_PS_RF_OFF | FW_PS_ALL_ON))
+#define	FW_PS_IS_RF_ON(x)		((x) & (FW_PS_ALL_ON))
+#define	FW_PS_IS_ACTIVE(x)		((x) & (FW_PS_ST_ACTIVE))
+#define	FW_PS_IS_CPWM_INT(x)		((x) & 0x40)
+
+#define	FW_CLR_PS_STATE(x)		((x) = ((x) & (0xF0)))
+
+#define	IS_IN_LOW_POWER_STATE_88E(fwpsstate)		\
+	(FW_PS_STATE(fwpsstate) == FW_PS_CLOCK_OFF)
+
+#define	FW_PWR_STATE_ACTIVE	((FW_PS_RF_ON) | (FW_PS_REGISTER_ACTIVE))
+#define	FW_PWR_STATE_RF_OFF		0
+
+struct rtl92c_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 rtl8192c_h2c_cmd {
+	H2C_88E_RSVDPAGE = 0,
+	H2C_88E_JOINBSSRPT = 1,
+	H2C_88E_SCAN = 2,
+	H2C_88E_KEEP_ALIVE_CTRL = 3,
+	H2C_88E_DISCONNECT_DECISION = 4,
+#if (USE_OLD_WOWLAN_DEBUG_FW == 1)
+	H2C_88E_WO_WLAN = 5,
+#endif
+	H2C_88E_INIT_OFFLOAD = 6,
+#if (USE_OLD_WOWLAN_DEBUG_FW == 1)
+	H2C_88E_REMOTE_WAKE_CTRL = 7,
+#endif
+	H2C_88E_AP_OFFLOAD = 8,
+	H2C_88E_BCN_RSVDPAGE = 9,
+	H2C_88E_PROBERSP_RSVDPAGE = 10,
+
+	H2C_88E_SETPWRMODE = 0x20,
+	H2C_88E_PS_TUNING_PARA = 0x21,
+	H2C_88E_PS_TUNING_PARA2 = 0x22,
+	H2C_88E_PS_LPS_PARA = 0x23,
+	H2C_88E_P2P_PS_OFFLOAD = 024,
+
+#if (USE_OLD_WOWLAN_DEBUG_FW == 0)
+	H2C_88E_WO_WLAN = 0x80,
+	H2C_88E_REMOTE_WAKE_CTRL = 0x81,
+	H2C_88E_AOAC_GLOBAL_INFO = 0x82,
+	H2C_88E_AOAC_RSVDPAGE = 0x83,
+#endif
+	/* Not defined in new 88E H2C CMD Format */
+	H2C_88E_RA_MASK,
+	H2C_88E_SELECTIVE_SUSPEND_ROF_CMD,
+	H2C_88E_P2P_PS_MODE,
+	H2C_88E_PSD_RESULT,
+	/*Not defined CTW CMD for P2P yet*/
+	H2C_88E_P2P_PS_CTW_CMD,
+	MAX_88E_H2CCMD
+};
+
+#define pagenum_128(_len)	(u32)(((_len)>>7) + ((_len)&0x7F ? 1 : 0))
+
+#define SET_88E_H2CCMD_WOWLAN_FUNC_ENABLE(__cmd, __value)		\
+	SET_BITS_TO_LE_1BYTE(__cmd, 0, 1, __value)
+#define SET_88E_H2CCMD_WOWLAN_PATTERN_MATCH_ENABLE(__cmd, __value)	\
+	SET_BITS_TO_LE_1BYTE(__cmd, 1, 1, __value)
+#define SET_88E_H2CCMD_WOWLAN_MAGIC_PKT_ENABLE(__cmd, __value)	\
+	SET_BITS_TO_LE_1BYTE(__cmd, 2, 1, __value)
+#define SET_88E_H2CCMD_WOWLAN_UNICAST_PKT_ENABLE(__cmd, __value)	\
+	SET_BITS_TO_LE_1BYTE(__cmd, 3, 1, __value)
+#define SET_88E_H2CCMD_WOWLAN_ALL_PKT_DROP(__cmd, __value)		\
+	SET_BITS_TO_LE_1BYTE(__cmd, 4, 1, __value)
+#define SET_88E_H2CCMD_WOWLAN_GPIO_ACTIVE(__cmd, __value)		\
+	SET_BITS_TO_LE_1BYTE(__cmd, 5, 1, __value)
+#define SET_88E_H2CCMD_WOWLAN_REKEY_WAKE_UP(__cmd, __value)		\
+	SET_BITS_TO_LE_1BYTE(__cmd, 6, 1, __value)
+#define SET_88E_H2CCMD_WOWLAN_DISCONNECT_WAKE_UP(__cmd, __value)	\
+	SET_BITS_TO_LE_1BYTE(__cmd, 7, 1, __value)
+#define SET_88E_H2CCMD_WOWLAN_GPIONUM(__cmd, __value)		\
+	SET_BITS_TO_LE_1BYTE((__cmd)+1, 0, 8, __value)
+#define SET_88E_H2CCMD_WOWLAN_GPIO_DURATION(__cmd, __value)		\
+	SET_BITS_TO_LE_1BYTE((__cmd)+2, 0, 8, __value)
+
+
+#define SET_H2CCMD_PWRMODE_PARM_MODE(__ph2ccmd, __val)			\
+	SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val)
+#define SET_H2CCMD_PWRMODE_PARM_RLBM(__cmd, __value)		\
+	SET_BITS_TO_LE_1BYTE((__cmd)+1, 0, 4, __value)
+#define SET_H2CCMD_PWRMODE_PARM_SMART_PS(__cmd, __value)		\
+	SET_BITS_TO_LE_1BYTE((__cmd)+1, 4, 4, __value)
+#define SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(__cmd, __value)	\
+	SET_BITS_TO_LE_1BYTE((__cmd)+2, 0, 8, __value)
+#define SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(__cmd, __value)	\
+	SET_BITS_TO_LE_1BYTE((__cmd)+3, 0, 8, __value)
+#define SET_H2CCMD_PWRMODE_PARM_PWR_STATE(__cmd, __value)		\
+	SET_BITS_TO_LE_1BYTE((__cmd)+4, 0, 8, __value)
+#define GET_88E_H2CCMD_PWRMODE_PARM_MODE(__cmd)			\
+	LE_BITS_TO_1BYTE(__cmd, 0, 8)
+
+#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)
+
+/* AP_OFFLOAD */
+#define SET_H2CCMD_AP_OFFLOAD_ON(__cmd, __value)			\
+	SET_BITS_TO_LE_1BYTE(__cmd, 0, 8, __value)
+#define SET_H2CCMD_AP_OFFLOAD_HIDDEN(__cmd, __value)		\
+	SET_BITS_TO_LE_1BYTE((__cmd)+1, 0, 8, __value)
+#define SET_H2CCMD_AP_OFFLOAD_DENYANY(__cmd, __value)		\
+	SET_BITS_TO_LE_1BYTE((__cmd)+2, 0, 8, __value)
+#define SET_H2CCMD_AP_OFFLOAD_WAKEUP_EVT_RPT(__cmd, __value)	\
+	SET_BITS_TO_LE_1BYTE((__cmd)+3, 0, 8, __value)
+
+/* Keep Alive Control*/
+#define SET_88E_H2CCMD_KEEP_ALIVE_ENABLE(__cmd, __value)		\
+	SET_BITS_TO_LE_1BYTE(__cmd, 0, 1, __value)
+#define SET_88E_H2CCMD_KEEP_ALIVE_ACCPEPT_USER_DEFINED(__cmd, __value) \
+	SET_BITS_TO_LE_1BYTE(__cmd, 1, 1, __value)
+#define SET_88E_H2CCMD_KEEP_ALIVE_PERIOD(__cmd, __value)		\
+	SET_BITS_TO_LE_1BYTE((__cmd)+1, 0, 8, __value)
+
+/*REMOTE_WAKE_CTRL */
+#define SET_88E_H2CCMD_REMOTE_WAKE_CTRL_EN(__cmd, __value)		\
+	SET_BITS_TO_LE_1BYTE(__cmd, 0, 1, __value)
+#if (USE_OLD_WOWLAN_DEBUG_FW == 0)
+#define SET_88E_H2CCMD_REMOTE_WAKE_CTRL_ARP_OFFLOAD_EN(__cmd, __value) \
+	SET_BITS_TO_LE_1BYTE(__cmd, 1, 1, __value)
+#define SET_88E_H2CCMD_REMOTE_WAKE_CTRL_NDP_OFFLOAD_EN(__cmd, __value) \
+	SET_BITS_TO_LE_1BYTE(__cmd, 2, 1, __value)
+#define SET_88E_H2CCMD_REMOTE_WAKE_CTRL_GTK_OFFLOAD_EN(__cmd, __value) \
+	SET_BITS_TO_LE_1BYTE(__cmd, 3, 1, __value)
+#else
+#define SET_88E_H2_REM_WAKE_ENC_ALG(__cmd, __value)		\
+	SET_BITS_TO_LE_1BYTE((__cmd)+1, 0, 8, __value)
+#define SET_88E_H2CCMD_REMOTE_WAKE_CTRL_GROUP_ENC_ALG(__cmd, __value) \
+	SET_BITS_TO_LE_1BYTE((__cmd)+2, 0, 8, __value)
+#endif
+
+/* GTK_OFFLOAD */
+#define SET_88E_H2CCMD_AOAC_GLOBAL_INFO_PAIRWISE_ENC_ALG(__cmd, __value) \
+	SET_BITS_TO_LE_1BYTE(__cmd, 0, 8, __value)
+#define SET_88E_H2CCMD_AOAC_GLOBAL_INFO_GROUP_ENC_ALG(__cmd, __value) \
+	SET_BITS_TO_LE_1BYTE((__cmd)+1, 0, 8, __value)
+
+/* AOAC_RSVDPAGE_LOC */
+#define SET_88E_H2CCMD_AOAC_RSVD_LOC_REM_WAKE_CTRL_INFO(__cmd, __value) \
+	SET_BITS_TO_LE_1BYTE((__cmd), 0, 8, __value)
+#define SET_88E_H2CCMD_AOAC_RSVDPAGE_LOC_ARP_RSP(__cmd, __value)	\
+	SET_BITS_TO_LE_1BYTE((__cmd)+1, 0, 8, __value)
+#define SET_88E_H2CCMD_AOAC_RSVDPAGE_LOC_NEIGHBOR_ADV(__cmd, __value) \
+	SET_BITS_TO_LE_1BYTE((__cmd)+2, 0, 8, __value)
+#define SET_88E_H2CCMD_AOAC_RSVDPAGE_LOC_GTK_RSP(__cmd, __value)	\
+	SET_BITS_TO_LE_1BYTE((__cmd)+3, 0, 8, __value)
+#define SET_88E_H2CCMD_AOAC_RSVDPAGE_LOC_GTK_INFO(__cmd, __value)	\
+	SET_BITS_TO_LE_1BYTE((__cmd)+4, 0, 8, __value)
+
+int rtl88e_download_fw(struct ieee80211_hw *hw,
+		       bool buse_wake_on_wlan_fw);
+void rtl88e_fill_h2c_cmd(struct ieee80211_hw *hw, u8 element_id,
+			 u32 cmd_len, u8 *p_cmdbuffer);
+void rtl88e_firmware_selfreset(struct ieee80211_hw *hw);
+void rtl88e_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode);
+void rtl88e_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw,
+				      u8 mstatus);
+void rtl88e_set_fw_ap_off_load_cmd(struct ieee80211_hw *hw,  u8 enable);
+void rtl88e_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished);
+void rtl88e_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c b/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c
new file mode 100644
index 0000000..bcff497
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c
@@ -0,0 +1,2530 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2013  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 "hw.h"
+#include "pwrseqcmd.h"
+#include "pwrseq.h"
+
+#define LLT_CONFIG		5
+
+static void _rtl88ee_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 _rtl88ee_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_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 _rtl88ee_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_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 _rtl88ee_enable_bcn_sub_func(struct ieee80211_hw *hw)
+{
+	_rtl88ee_set_bcn_ctrl_reg(hw, 0, BIT(1));
+}
+
+static void _rtl88ee_return_beacon_queue_skb(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+	struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[BEACON_QUEUE];
+
+	while (skb_queue_len(&ring->queue)) {
+		struct rtl_tx_desc *entry = &ring->desc[ring->idx];
+		struct sk_buff *skb = __skb_dequeue(&ring->queue);
+
+		pci_unmap_single(rtlpci->pdev,
+				 rtlpriv->cfg->ops->get_desc(
+				 (u8 *)entry, true, HW_DESC_TXBUFF_ADDR),
+				 skb->len, PCI_DMA_TODEVICE);
+		kfree_skb(skb);
+		ring->idx = (ring->idx + 1) % ring->entries;
+	}
+}
+
+static void _rtl88ee_disable_bcn_sub_func(struct ieee80211_hw *hw)
+{
+	_rtl88ee_set_bcn_ctrl_reg(hw, BIT(1), 0);
+}
+
+static void _rtl88ee_set_fw_clock_on(struct ieee80211_hw *hw,
+				     u8 rpwm_val, bool need_turn_off_ckk)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	bool support_remote_wake_up;
+	u32 count = 0, isr_regaddr, content;
+	bool schedule_timer = need_turn_off_ckk;
+
+	rtlpriv->cfg->ops->get_hw_reg(hw, HAL_DEF_WOWLAN,
+				      (u8 *)(&support_remote_wake_up));
+	if (!rtlhal->fw_ready)
+		return;
+	if (!rtlpriv->psc.fw_current_inpsmode)
+		return;
+
+	while (1) {
+		spin_lock_bh(&rtlpriv->locks.fw_ps_lock);
+		if (rtlhal->fw_clk_change_in_progress) {
+			while (rtlhal->fw_clk_change_in_progress) {
+				spin_unlock_bh(&rtlpriv->locks.fw_ps_lock);
+				udelay(100);
+				if (++count > 1000)
+					return;
+				spin_lock_bh(&rtlpriv->locks.fw_ps_lock);
+			}
+			spin_unlock_bh(&rtlpriv->locks.fw_ps_lock);
+		} else {
+			rtlhal->fw_clk_change_in_progress = false;
+			spin_unlock_bh(&rtlpriv->locks.fw_ps_lock);
+		}
+	}
+
+	if (IS_IN_LOW_POWER_STATE_88E(rtlhal->fw_ps_state)) {
+		rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_SET_RPWM,
+					      (u8 *)(&rpwm_val));
+		if (FW_PS_IS_ACK(rpwm_val)) {
+			isr_regaddr = REG_HISR;
+			content = rtl_read_dword(rtlpriv, isr_regaddr);
+			while (!(content & IMR_CPWM) && (count < 500)) {
+				udelay(50);
+				count++;
+				content = rtl_read_dword(rtlpriv, isr_regaddr);
+			}
+
+			if (content & IMR_CPWM) {
+				rtl_write_word(rtlpriv, isr_regaddr, 0x0100);
+				rtlhal->fw_ps_state = FW_PS_STATE_RF_ON_88E;
+				RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+					 "Receive CPWM INT!!! Set pHalData->FwPSState = %X\n",
+					 rtlhal->fw_ps_state);
+			}
+		}
+
+		spin_lock_bh(&rtlpriv->locks.fw_ps_lock);
+		rtlhal->fw_clk_change_in_progress = false;
+		spin_unlock_bh(&rtlpriv->locks.fw_ps_lock);
+		if (schedule_timer) {
+			mod_timer(&rtlpriv->works.fw_clockoff_timer,
+				  jiffies + MSECS(10));
+		}
+	} else  {
+		spin_lock_bh(&rtlpriv->locks.fw_ps_lock);
+		rtlhal->fw_clk_change_in_progress = false;
+		spin_unlock_bh(&rtlpriv->locks.fw_ps_lock);
+	}
+}
+
+static void _rtl88ee_set_fw_clock_off(struct ieee80211_hw *hw,
+				      u8 rpwm_val)
+{
+	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 rtl8192_tx_ring *ring;
+	enum rf_pwrstate rtstate;
+	bool schedule_timer = false;
+	u8 queue;
+
+	if (!rtlhal->fw_ready)
+		return;
+	if (!rtlpriv->psc.fw_current_inpsmode)
+		return;
+	if (!rtlhal->allow_sw_to_change_hwclc)
+		return;
+	rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RF_STATE, (u8 *)(&rtstate));
+	if (rtstate == ERFOFF || rtlpriv->psc.inactive_pwrstate == ERFOFF)
+		return;
+
+	for (queue = 0; queue < RTL_PCI_MAX_TX_QUEUE_COUNT; queue++) {
+		ring = &rtlpci->tx_ring[queue];
+		if (skb_queue_len(&ring->queue)) {
+			schedule_timer = true;
+			break;
+		}
+	}
+
+	if (schedule_timer) {
+		mod_timer(&rtlpriv->works.fw_clockoff_timer,
+			  jiffies + MSECS(10));
+		return;
+	}
+
+	if (FW_PS_STATE(rtlhal->fw_ps_state) !=
+	    FW_PS_STATE_RF_OFF_LOW_PWR_88E) {
+		spin_lock_bh(&rtlpriv->locks.fw_ps_lock);
+		if (!rtlhal->fw_clk_change_in_progress) {
+			rtlhal->fw_clk_change_in_progress = true;
+			spin_unlock_bh(&rtlpriv->locks.fw_ps_lock);
+			rtlhal->fw_ps_state = FW_PS_STATE(rpwm_val);
+			rtl_write_word(rtlpriv, REG_HISR, 0x0100);
+			rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM,
+						      (u8 *)(&rpwm_val));
+			spin_lock_bh(&rtlpriv->locks.fw_ps_lock);
+			rtlhal->fw_clk_change_in_progress = false;
+			spin_unlock_bh(&rtlpriv->locks.fw_ps_lock);
+		} else {
+			spin_unlock_bh(&rtlpriv->locks.fw_ps_lock);
+			mod_timer(&rtlpriv->works.fw_clockoff_timer,
+				  jiffies + MSECS(10));
+		}
+	}
+}
+
+static void _rtl88ee_set_fw_ps_rf_on(struct ieee80211_hw *hw)
+{
+	u8 rpwm_val = 0;
+
+	rpwm_val |= (FW_PS_STATE_RF_OFF_88E | FW_PS_ACK);
+	_rtl88ee_set_fw_clock_on(hw, rpwm_val, true);
+}
+
+static void _rtl88ee_set_fw_ps_rf_off_low_power(struct ieee80211_hw *hw)
+{
+	u8 rpwm_val = 0;
+
+	rpwm_val |= FW_PS_STATE_RF_OFF_LOW_PWR_88E;
+	_rtl88ee_set_fw_clock_off(hw, rpwm_val);
+}
+
+void rtl88ee_fw_clk_off_timer_callback(unsigned long data)
+{
+	struct ieee80211_hw *hw = (struct ieee80211_hw *)data;
+
+	_rtl88ee_set_fw_ps_rf_off_low_power(hw);
+}
+
+static void _rtl88ee_fwlps_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));
+	bool fw_current_inps = false;
+	u8 rpwm_val = 0, fw_pwrmode = FW_PS_ACTIVE_MODE;
+
+	if (ppsc->low_power_enable) {
+		rpwm_val = (FW_PS_STATE_ALL_ON_88E|FW_PS_ACK);/* RF on */
+		_rtl88ee_set_fw_clock_on(hw, rpwm_val, false);
+		rtlhal->allow_sw_to_change_hwclc = false;
+		rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE,
+					      (u8 *)(&fw_pwrmode));
+		rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
+					      (u8 *)(&fw_current_inps));
+	} else {
+		rpwm_val = FW_PS_STATE_ALL_ON_88E;	/* RF on */
+		rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM,
+					      (u8 *)(&rpwm_val));
+		rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE,
+					      (u8 *)(&fw_pwrmode));
+		rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
+					      (u8 *)(&fw_current_inps));
+	}
+}
+
+static void _rtl88ee_fwlps_enter(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));
+	bool fw_current_inps = true;
+	u8 rpwm_val;
+
+	if (ppsc->low_power_enable) {
+		rpwm_val = FW_PS_STATE_RF_OFF_LOW_PWR_88E;	/* RF off */
+		rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
+					      (u8 *)(&fw_current_inps));
+		rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE,
+					      (u8 *)(&ppsc->fwctrl_psmode));
+		rtlhal->allow_sw_to_change_hwclc = true;
+		_rtl88ee_set_fw_clock_off(hw, rpwm_val);
+	} else {
+		rpwm_val = FW_PS_STATE_RF_OFF_88E;	/* RF off */
+		rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
+					      (u8 *)(&fw_current_inps));
+		rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE,
+					      (u8 *)(&ppsc->fwctrl_psmode));
+		rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM,
+					      (u8 *)(&rpwm_val));
+	}
+}
+
+void rtl88ee_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; }
+	default:
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 "switch case not process %x\n", variable);
+		break;
+	}
+}
+
+void rtl88ee_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_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;
+		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++;
+		}
+		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 = rtl_read_byte(rtlpriv, REG_TRXPTCL_CTL+2);
+		if (short_preamble) {
+			reg_tmp |= 0x02;
+			rtl_write_byte(rtlpriv, REG_TRXPTCL_CTL + 2, reg_tmp);
+		} else {
+			reg_tmp |= 0xFD;
+			rtl_write_byte(rtlpriv, REG_TRXPTCL_CTL + 2, reg_tmp);
+		}
+		break; }
+	case HW_VAR_WPA_CONFIG:
+		rtl_write_byte(rtlpriv, REG_SECCFG, *((u8 *)val));
+		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 |= (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 regtoset_normal[4] = { 0x41, 0xa8, 0x72, 0xb9 };
+		u8 factor;
+		u8 *reg = NULL;
+		u8 id = 0;
+
+		reg = regtoset_normal;
+
+		factor = *((u8 *)val);
+		if (factor <= 3) {
+			factor = (1 << (factor + 2));
+			if (factor > 0xf)
+				factor = 0xf;
+
+			for (id = 0; id < 4; id++) {
+				if ((reg[id] & 0xf0) > (factor << 4))
+					reg[id] = (reg[id] & 0x0f) |
+						  (factor << 4);
+
+				if ((reg[id] & 0x0f) > factor)
+					reg[id] = (reg[id] & 0xf0) | (factor);
+
+				rtl_write_byte(rtlpriv, (REG_AGGLEN_LMT + id),
+					       reg[id]);
+			}
+
+			RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD,
+				 "Set HW_VAR_AMPDU_FACTOR: %#x\n", factor);
+		}
+		break; }
+	case HW_VAR_AC_PARAM:{
+		u8 e_aci = *((u8 *)val);
+		rtl88e_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_BEQEN);
+				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:
+		rtl88e_phy_set_io_cmd(hw, (*(enum io_type *)val));
+		break;
+	case HW_VAR_SET_RPWM:{
+		u8 rpwm_val;
+
+		rpwm_val = rtl_read_byte(rtlpriv, REG_PCIE_HRPWM);
+		udelay(1);
+
+		if (rpwm_val & BIT(7)) {
+			rtl_write_byte(rtlpriv, REG_PCIE_HRPWM,
+				       (*(u8 *)val));
+		} else {
+			rtl_write_byte(rtlpriv, REG_PCIE_HRPWM,
+				       ((*(u8 *)val) | BIT(7)));
+		}
+		break; }
+	case HW_VAR_H2C_FW_PWRMODE:
+		rtl88e_set_fw_pwrmode_cmd(hw, (*(u8 *)val));
+		break;
+	case HW_VAR_FW_PSMODE_STATUS:
+		ppsc->fw_current_inpsmode = *((bool *)val);
+		break;
+	case HW_VAR_RESUME_CLK_ON:
+		_rtl88ee_set_fw_ps_rf_on(hw);
+		break;
+	case HW_VAR_FW_LPS_ACTION:{
+		bool enter_fwlps = *((bool *)val);
+
+		if (enter_fwlps)
+			_rtl88ee_fwlps_enter(hw);
+		 else
+			_rtl88ee_fwlps_leave(hw);
+		 break; }
+	case HW_VAR_H2C_FW_JOINBSSRPT:{
+		u8 mstatus = (*(u8 *)val);
+		u8 tmp, tmp_reg422, uval;
+		u8 count = 0, dlbcn_count = 0;
+		bool recover = false;
+
+		if (mstatus == RT_MEDIA_CONNECT) {
+			rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AID, NULL);
+
+			tmp = rtl_read_byte(rtlpriv, REG_CR + 1);
+			rtl_write_byte(rtlpriv, REG_CR + 1, (tmp | BIT(0)));
+
+			_rtl88ee_set_bcn_ctrl_reg(hw, 0, BIT(3));
+			_rtl88ee_set_bcn_ctrl_reg(hw, BIT(4), 0);
+
+			tmp_reg422 = rtl_read_byte(rtlpriv,
+						   REG_FWHW_TXQ_CTRL + 2);
+			rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2,
+				       tmp_reg422 & (~BIT(6)));
+			if (tmp_reg422 & BIT(6))
+				recover = true;
+
+			do {
+				uval = rtl_read_byte(rtlpriv, REG_TDECTRL+2);
+				rtl_write_byte(rtlpriv, REG_TDECTRL+2,
+					       (uval | BIT(0)));
+				_rtl88ee_return_beacon_queue_skb(hw);
+
+				rtl88e_set_fw_rsvdpagepkt(hw, 0);
+				uval = rtl_read_byte(rtlpriv, REG_TDECTRL+2);
+				count = 0;
+				while (!(uval & BIT(0)) && count < 20) {
+					count++;
+					udelay(10);
+					uval = rtl_read_byte(rtlpriv,
+							     REG_TDECTRL+2);
+				}
+				dlbcn_count++;
+			} while (!(uval & BIT(0)) && dlbcn_count < 5);
+
+			if (uval & BIT(0))
+				rtl_write_byte(rtlpriv, REG_TDECTRL+2, BIT(0));
+
+			_rtl88ee_set_bcn_ctrl_reg(hw, BIT(3), 0);
+			_rtl88ee_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 & ~(BIT(0))));
+		}
+		rtl88e_set_fw_joinbss_report_cmd(hw, (*(u8 *)val));
+		break; }
+	case HW_VAR_H2C_FW_P2P_PS_OFFLOAD:
+		rtl88e_set_p2p_ps_offload_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 == true)
+			_rtl88ee_stop_tx_beacon(hw);
+
+		_rtl88ee_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));
+
+		_rtl88ee_set_bcn_ctrl_reg(hw, BIT(3), 0);
+
+		if (btype_ibss == true)
+			_rtl88ee_resume_tx_beacon(hw);
+		break; }
+	default:
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 "switch case not process %x\n", variable);
+		break;
+	}
+}
+
+static bool _rtl88ee_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 _rtl88ee_llt_table_init(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	unsigned short i;
+	u8 txpktbuf_bndy;
+	u8 maxpage;
+	bool status;
+
+	maxpage = 0xAF;
+	txpktbuf_bndy = 0xAB;
+
+	rtl_write_byte(rtlpriv, REG_RQPN_NPQ, 0x01);
+	rtl_write_dword(rtlpriv, REG_RQPN, 0x80730d29);
+
+
+	rtl_write_dword(rtlpriv, REG_TRXFF_BNDY, (0x25FF0000 | txpktbuf_bndy));
+	rtl_write_byte(rtlpriv, REG_TDECTRL + 1, txpktbuf_bndy);
+
+	rtl_write_byte(rtlpriv, REG_TXPKTBUF_BCNQ_BDNY, txpktbuf_bndy);
+	rtl_write_byte(rtlpriv, REG_TXPKTBUF_MGQ_BDNY, txpktbuf_bndy);
+
+	rtl_write_byte(rtlpriv, 0x45D, txpktbuf_bndy);
+	rtl_write_byte(rtlpriv, REG_PBP, 0x11);
+	rtl_write_byte(rtlpriv, REG_RX_DRVINFO_SZ, 0x4);
+
+	for (i = 0; i < (txpktbuf_bndy - 1); i++) {
+		status = _rtl88ee_llt_write(hw, i, i + 1);
+		if (true != status)
+			return status;
+	}
+
+	status = _rtl88ee_llt_write(hw, (txpktbuf_bndy - 1), 0xFF);
+	if (true != status)
+		return status;
+
+	for (i = txpktbuf_bndy; i < maxpage; i++) {
+		status = _rtl88ee_llt_write(hw, i, (i + 1));
+		if (true != status)
+			return status;
+	}
+
+	status = _rtl88ee_llt_write(hw, maxpage, txpktbuf_bndy);
+	if (true != status)
+		return status;
+
+	return true;
+}
+
+static void _rtl88ee_gen_refresh_led_state(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
+	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+	struct rtl_led *pLed0 = &(pcipriv->ledctl.sw_led0);
+
+	if (rtlpriv->rtlhal.up_first_time)
+		return;
+
+	if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS)
+		rtl88ee_sw_led_on(hw, pLed0);
+	else if (ppsc->rfoff_reason == RF_CHANGE_BY_INIT)
+		rtl88ee_sw_led_on(hw, pLed0);
+	else
+		rtl88ee_sw_led_off(hw, pLed0);
+}
+
+static bool _rtl88ee_init_mac(struct ieee80211_hw *hw)
+{
+	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));
+	u8 bytetmp;
+	u16 wordtmp;
+
+	/*Disable XTAL OUTPUT for power saving. YJ, add, 111206. */
+	bytetmp = rtl_read_byte(rtlpriv, REG_XCK_OUT_CTRL) & (~BIT(0));
+	rtl_write_byte(rtlpriv, REG_XCK_OUT_CTRL, bytetmp);
+	/*Auto Power Down to CHIP-off State*/
+	bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO + 1) & (~BIT(7));
+	rtl_write_byte(rtlpriv, REG_APS_FSMCO + 1, bytetmp);
+
+	rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x00);
+	/* HW Power on sequence */
+	if (!rtl88_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK,
+					PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK,
+					Rtl8188E_NIC_ENABLE_FLOW)) {
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+			 "init MAC Fail as rtl88_hal_pwrseqcmdparsing\n");
+		return false;
+	}
+
+	bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO) | BIT(4);
+	rtl_write_byte(rtlpriv, REG_APS_FSMCO, bytetmp);
+
+	bytetmp = rtl_read_byte(rtlpriv, REG_PCIE_CTRL_REG+2);
+	rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG+2, bytetmp|BIT(2));
+
+	bytetmp = rtl_read_byte(rtlpriv, REG_WATCH_DOG+1);
+	rtl_write_byte(rtlpriv, REG_WATCH_DOG+1, bytetmp|BIT(7));
+
+	bytetmp = rtl_read_byte(rtlpriv, REG_AFE_XTAL_CTRL_EXT+1);
+	rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL_EXT+1, bytetmp|BIT(1));
+
+	bytetmp = rtl_read_byte(rtlpriv, REG_TX_RPT_CTRL);
+	rtl_write_byte(rtlpriv, REG_TX_RPT_CTRL, bytetmp|BIT(1)|BIT(0));
+	rtl_write_byte(rtlpriv, REG_TX_RPT_CTRL+1, 2);
+	rtl_write_word(rtlpriv, REG_TX_RPT_TIME, 0xcdf0);
+
+	/*Add for wake up online*/
+	bytetmp = rtl_read_byte(rtlpriv, REG_SYS_CLKR);
+
+	rtl_write_byte(rtlpriv, REG_SYS_CLKR, bytetmp|BIT(3));
+	bytetmp = rtl_read_byte(rtlpriv, REG_GPIO_MUXCFG+1);
+	rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG+1, (bytetmp & (~BIT(4))));
+	rtl_write_byte(rtlpriv, 0x367, 0x80);
+
+	rtl_write_word(rtlpriv, REG_CR, 0x2ff);
+	rtl_write_byte(rtlpriv, REG_CR+1, 0x06);
+	rtl_write_byte(rtlpriv, REG_CR+2, 0x00);
+
+	if (!rtlhal->mac_func_enable) {
+		if (_rtl88ee_llt_table_init(hw) == false) {
+			RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+				 "LLT table init fail\n");
+			return false;
+		}
+	}
+
+
+	rtl_write_dword(rtlpriv, REG_HISR, 0xffffffff);
+	rtl_write_dword(rtlpriv, REG_HISRE, 0xffffffff);
+
+	wordtmp = rtl_read_word(rtlpriv, REG_TRXDMA_CTRL);
+	wordtmp &= 0xf;
+	wordtmp |= 0xE771;
+	rtl_write_word(rtlpriv, REG_TRXDMA_CTRL, wordtmp);
+
+	rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config);
+	rtl_write_word(rtlpriv, REG_RXFLTMAP2, 0xffff);
+	rtl_write_dword(rtlpriv, REG_TCR, rtlpci->transmit_config);
+
+	rtl_write_dword(rtlpriv, REG_BCNQ_DESA,
+			((u64) rtlpci->tx_ring[BEACON_QUEUE].dma) &
+			DMA_BIT_MASK(32));
+	rtl_write_dword(rtlpriv, REG_MGQ_DESA,
+			(u64) rtlpci->tx_ring[MGNT_QUEUE].dma &
+			DMA_BIT_MASK(32));
+	rtl_write_dword(rtlpriv, REG_VOQ_DESA,
+			(u64) rtlpci->tx_ring[VO_QUEUE].dma & DMA_BIT_MASK(32));
+	rtl_write_dword(rtlpriv, REG_VIQ_DESA,
+			(u64) rtlpci->tx_ring[VI_QUEUE].dma & DMA_BIT_MASK(32));
+	rtl_write_dword(rtlpriv, REG_BEQ_DESA,
+			(u64) rtlpci->tx_ring[BE_QUEUE].dma & DMA_BIT_MASK(32));
+	rtl_write_dword(rtlpriv, REG_BKQ_DESA,
+			(u64) rtlpci->tx_ring[BK_QUEUE].dma & DMA_BIT_MASK(32));
+	rtl_write_dword(rtlpriv, REG_HQ_DESA,
+			(u64) rtlpci->tx_ring[HIGH_QUEUE].dma &
+			DMA_BIT_MASK(32));
+	rtl_write_dword(rtlpriv, REG_RX_DESA,
+			(u64) rtlpci->rx_ring[RX_MPDU_QUEUE].dma &
+			DMA_BIT_MASK(32));
+
+	/* if we want to support 64 bit DMA, we should set it here,
+	 * but at the moment we do not support 64 bit DMA
+	 */
+
+	rtl_write_dword(rtlpriv, REG_INT_MIG, 0);
+
+	rtl_write_dword(rtlpriv, REG_MCUTST_1, 0x0);
+	rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG+1, 0);/*Enable RX DMA */
+
+	if (rtlhal->earlymode_enable) {/*Early mode enable*/
+		bytetmp = rtl_read_byte(rtlpriv, REG_EARLY_MODE_CONTROL);
+		bytetmp |= 0x1f;
+		rtl_write_byte(rtlpriv, REG_EARLY_MODE_CONTROL, bytetmp);
+		rtl_write_byte(rtlpriv, REG_EARLY_MODE_CONTROL+3, 0x81);
+	}
+	_rtl88ee_gen_refresh_led_state(hw);
+	return true;
+}
+
+static void _rtl88ee_hw_configure(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u32 reg_prsr;
+
+	reg_prsr = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
+
+	rtl_write_dword(rtlpriv, REG_RRSR, reg_prsr);
+	rtl_write_byte(rtlpriv, REG_HWSEQ_CTRL, 0xFF);
+}
+
+static void _rtl88ee_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));
+	u8 tmp1byte = 0;
+	u32 tmp4Byte = 0, count;
+
+	rtl_write_word(rtlpriv, 0x354, 0x8104);
+	rtl_write_word(rtlpriv, 0x358, 0x24);
+
+	rtl_write_word(rtlpriv, 0x350, 0x70c);
+	rtl_write_byte(rtlpriv, 0x352, 0x2);
+	tmp1byte = rtl_read_byte(rtlpriv, 0x352);
+	count = 0;
+	while (tmp1byte && count < 20) {
+		udelay(10);
+		tmp1byte = rtl_read_byte(rtlpriv, 0x352);
+		count++;
+	}
+	if (0 == tmp1byte) {
+		tmp4Byte = rtl_read_dword(rtlpriv, 0x34c);
+		rtl_write_dword(rtlpriv, 0x348, tmp4Byte|BIT(31));
+		rtl_write_word(rtlpriv, 0x350, 0xf70c);
+		rtl_write_byte(rtlpriv, 0x352, 0x1);
+	}
+
+	tmp1byte = rtl_read_byte(rtlpriv, 0x352);
+	count = 0;
+	while (tmp1byte && count < 20) {
+		udelay(10);
+		tmp1byte = rtl_read_byte(rtlpriv, 0x352);
+		count++;
+	}
+
+	rtl_write_word(rtlpriv, 0x350, 0x718);
+	rtl_write_byte(rtlpriv, 0x352, 0x2);
+	tmp1byte = rtl_read_byte(rtlpriv, 0x352);
+	count = 0;
+	while (tmp1byte && count < 20) {
+		udelay(10);
+		tmp1byte = rtl_read_byte(rtlpriv, 0x352);
+		count++;
+	}
+	if (ppsc->support_backdoor || (0 == tmp1byte)) {
+		tmp4Byte = rtl_read_dword(rtlpriv, 0x34c);
+		rtl_write_dword(rtlpriv, 0x348, tmp4Byte|BIT(11)|BIT(12));
+		rtl_write_word(rtlpriv, 0x350, 0xf718);
+		rtl_write_byte(rtlpriv, 0x352, 0x1);
+	}
+	tmp1byte = rtl_read_byte(rtlpriv, 0x352);
+	count = 0;
+	while (tmp1byte && count < 20) {
+		udelay(10);
+		tmp1byte = rtl_read_byte(rtlpriv, 0x352);
+		count++;
+	}
+}
+
+void rtl88ee_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_DMESG,
+		 "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_RXDECENABLE;
+
+	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_DMESG,
+		 "The SECR-value %x\n", sec_reg_value);
+	rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_WPA_CONFIG, &sec_reg_value);
+}
+
+int rtl88ee_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_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	bool rtstatus = true;
+	int err = 0;
+	u8 tmp_u1b, u1byte;
+
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Rtl8188EE hw init\n");
+	rtlpriv->rtlhal.being_init_adapter = true;
+	rtlpriv->intf_ops->disable_aspm(hw);
+
+	tmp_u1b = rtl_read_byte(rtlpriv, REG_SYS_CLKR+1);
+	u1byte = rtl_read_byte(rtlpriv, REG_CR);
+	if ((tmp_u1b & BIT(3)) && (u1byte != 0 && u1byte != 0xEA)) {
+		rtlhal->mac_func_enable = true;
+	} else {
+		rtlhal->mac_func_enable = false;
+		rtlhal->fw_ps_state = FW_PS_STATE_ALL_ON_88E;
+	}
+
+	rtstatus = _rtl88ee_init_mac(hw);
+	if (rtstatus != true) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Init MAC failed\n");
+		err = 1;
+		return err;
+	}
+
+	err = rtl88e_download_fw(hw, false);
+	if (err) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+			 "Failed to download FW. Init HW without FW now..\n");
+		err = 1;
+		rtlhal->fw_ready = false;
+		return err;
+	} else {
+		rtlhal->fw_ready = true;
+	}
+	/*fw related variable initialize */
+	rtlhal->last_hmeboxnum = 0;
+	rtlhal->fw_ps_state = FW_PS_STATE_ALL_ON_88E;
+	rtlhal->fw_clk_change_in_progress = false;
+	rtlhal->allow_sw_to_change_hwclc = false;
+	ppsc->fw_current_inpsmode = false;
+
+	rtl88e_phy_mac_config(hw);
+	/* because last function modifies RCR, we update
+	 * rcr var here, or TP will be unstable for receive_config
+	 * is wrong, RX RCR_ACRC32 will cause TP unstable & Rx
+	 * RCR_APP_ICV will cause mac80211 disassoc for cisco 1252
+	 */
+	rtlpci->receive_config &= ~(RCR_ACRC32 | RCR_AICV);
+	rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config);
+
+	rtl88e_phy_bb_config(hw);
+	rtl_set_bbreg(hw, RFPGA0_RFMOD, BCCKEN, 0x1);
+	rtl_set_bbreg(hw, RFPGA0_RFMOD, BOFDMEN, 0x1);
+
+	rtlphy->rf_mode = RF_OP_BY_SW_3WIRE;
+	rtl88e_phy_rf_config(hw);
+
+	rtlphy->rfreg_chnlval[0] = rtl_get_rfreg(hw, (enum radio_path)0,
+						 RF_CHNLBW, RFREG_OFFSET_MASK);
+	rtlphy->rfreg_chnlval[0] = rtlphy->rfreg_chnlval[0] & 0xfff00fff;
+
+	_rtl88ee_hw_configure(hw);
+	rtl_cam_reset_all_entry(hw);
+	rtl88ee_enable_hw_security_config(hw);
+
+	rtlhal->mac_func_enable = true;
+	ppsc->rfpwr_state = ERFON;
+
+	rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR, mac->mac_addr);
+	_rtl88ee_enable_aspm_back_door(hw);
+	rtlpriv->intf_ops->enable_aspm(hw);
+
+	if (ppsc->rfpwr_state == ERFON) {
+		if ((rtlefuse->antenna_div_type == CGCS_RX_HW_ANTDIV) ||
+		    ((rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) &&
+		    (rtlhal->oem_id == RT_CID_819x_HP))) {
+			rtl88e_phy_set_rfpath_switch(hw, true);
+			rtlpriv->dm.fat_table.rx_idle_ant = MAIN_ANT;
+		} else {
+			rtl88e_phy_set_rfpath_switch(hw, false);
+			rtlpriv->dm.fat_table.rx_idle_ant = AUX_ANT;
+		}
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+			 "rx idle ant %s\n",
+			 (rtlpriv->dm.fat_table.rx_idle_ant == MAIN_ANT) ?
+			 ("MAIN_ANT") : ("AUX_ANT"));
+
+		if (rtlphy->iqk_initialized) {
+			rtl88e_phy_iq_calibrate(hw, true);
+		} else {
+			rtl88e_phy_iq_calibrate(hw, false);
+			rtlphy->iqk_initialized = true;
+		}
+		rtl88e_dm_check_txpower_tracking(hw);
+		rtl88e_phy_lc_calibrate(hw);
+	}
+
+	tmp_u1b = efuse_read_1byte(hw, 0x1FA);
+	if (!(tmp_u1b & BIT(0))) {
+		rtl_set_rfreg(hw, RF90_PATH_A, 0x15, 0x0F, 0x05);
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "PA BIAS path A\n");
+	}
+
+	if (!(tmp_u1b & BIT(4))) {
+		tmp_u1b = rtl_read_byte(rtlpriv, 0x16);
+		tmp_u1b &= 0x0F;
+		rtl_write_byte(rtlpriv, 0x16, tmp_u1b | 0x80);
+		udelay(10);
+		rtl_write_byte(rtlpriv, 0x16, tmp_u1b | 0x90);
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "under 1.5V\n");
+	}
+	rtl_write_byte(rtlpriv, REG_NAV_CTRL+2,  ((30000+127)/128));
+	rtl88e_dm_init(hw);
+	rtlpriv->rtlhal.being_init_adapter = false;
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "end of Rtl8188EE hw init %x\n",
+		 err);
+	return 0;
+}
+
+static enum version_8188e _rtl88ee_read_chip_version(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	enum version_8188e version = VERSION_UNKNOWN;
+	u32 value32;
+
+	value32 = rtl_read_dword(rtlpriv, REG_SYS_CFG);
+	if (value32 & TRP_VAUX_EN) {
+		version = (enum version_8188e) VERSION_TEST_CHIP_88E;
+	} else {
+		version = NORMAL_CHIP;
+		version = version | ((value32 & TYPE_ID) ? RF_TYPE_2T2R : 0);
+		version = version | ((value32 & VENDOR_ID) ?
+			  CHIP_VENDOR_UMC : 0);
+	}
+
+	rtlphy->rf_type = RF_1T1R;
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+		 "Chip RF Type: %s\n", (rtlphy->rf_type == RF_2T2R) ?
+		 "RF_2T2R" : "RF_1T1R");
+
+	return version;
+}
+
+static int _rtl88ee_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;
+	bt_msr &= 0xfc;
+
+	if (type == NL80211_IFTYPE_UNSPECIFIED ||
+	    type == NL80211_IFTYPE_STATION) {
+		_rtl88ee_stop_tx_beacon(hw);
+		_rtl88ee_enable_bcn_sub_func(hw);
+	} else if (type == NL80211_IFTYPE_ADHOC ||
+		type == NL80211_IFTYPE_AP ||
+		type == NL80211_IFTYPE_MESH_POINT) {
+		_rtl88ee_resume_tx_beacon(hw);
+		_rtl88ee_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);
+	}
+
+	switch (type) {
+	case NL80211_IFTYPE_UNSPECIFIED:
+		bt_msr |= MSR_NOLINK;
+		ledaction = LED_CTL_LINK;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 "Set Network type to NO LINK!\n");
+		break;
+	case NL80211_IFTYPE_ADHOC:
+		bt_msr |= MSR_ADHOC;
+		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;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 "Set Network type to STA!\n");
+		break;
+	case NL80211_IFTYPE_AP:
+		bt_msr |= MSR_AP;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 "Set Network type to AP!\n");
+		break;
+	case NL80211_IFTYPE_MESH_POINT:
+		bt_msr |= MSR_ADHOC;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 "Set Network type to Mesh Point!\n");
+		break;
+	default:
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 "Network type %d not support!\n", type);
+		return 1;
+	}
+
+	rtl_write_byte(rtlpriv, (MSR), 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 rtl88ee_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 == true) {
+		reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN);
+		rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR,
+					      (u8 *)(&reg_rcr));
+		_rtl88ee_set_bcn_ctrl_reg(hw, 0, BIT(4));
+	} else if (check_bssid == false) {
+		reg_rcr &= (~(RCR_CBSSID_DATA | RCR_CBSSID_BCN));
+		_rtl88ee_set_bcn_ctrl_reg(hw, BIT(4), 0);
+		rtlpriv->cfg->ops->set_hw_reg(hw,
+			HW_VAR_RCR, (u8 *)(&reg_rcr));
+	}
+}
+
+int rtl88ee_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	if (_rtl88ee_set_media_status(hw, type))
+		return -EOPNOTSUPP;
+
+	if (rtlpriv->mac80211.link_state == MAC80211_LINKED) {
+		if (type != NL80211_IFTYPE_AP &&
+		    type != NL80211_IFTYPE_MESH_POINT)
+			rtl88ee_set_check_bssid(hw, true);
+	} else {
+		rtl88ee_set_check_bssid(hw, false);
+	}
+
+	return 0;
+}
+
+/* don't set REG_EDCA_BE_PARAM here because mac80211 will send pkt when scan */
+void rtl88ee_set_qos(struct ieee80211_hw *hw, int aci)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	rtl88e_dm_init_edca_turbo(hw);
+	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 rtl88ee_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);
+	rtlpci->irq_enabled = true;
+	/* there are some C2H CMDs have been sent before system interrupt
+	 * is enabled, e.g., C2H, CPWM.
+	 * So we need to clear all C2H events that FW has notified, otherwise
+	 * FW won't schedule any commands anymore.
+	 */
+	rtl_write_byte(rtlpriv, REG_C2HEVT_CLEAR, 0);
+	/*enable system interrupt*/
+	rtl_write_dword(rtlpriv, REG_HSIMR, rtlpci->sys_irq_mask & 0xFFFFFFFF);
+}
+
+void rtl88ee_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, IMR_DISABLED);
+	rtl_write_dword(rtlpriv, REG_HIMRE, IMR_DISABLED);
+	rtlpci->irq_enabled = false;
+	synchronize_irq(rtlpci->pdev->irq);
+}
+
+static void _rtl88ee_poweroff_adapter(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	u8 u1b_tmp;
+	u32 count = 0;
+	rtlhal->mac_func_enable = false;
+	rtlpriv->intf_ops->enable_aspm(hw);
+
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "POWER OFF adapter\n");
+	u1b_tmp = rtl_read_byte(rtlpriv, REG_TX_RPT_CTRL);
+	rtl_write_byte(rtlpriv, REG_TX_RPT_CTRL, u1b_tmp & (~BIT(1)));
+
+	u1b_tmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL);
+	while (!(u1b_tmp & BIT(1)) && (count++ < 100)) {
+		udelay(10);
+		u1b_tmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL);
+		count++;
+	}
+	rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG+1, 0xFF);
+
+	rtl88_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK,
+				   PWR_INTF_PCI_MSK,
+				   Rtl8188E_NIC_LPS_ENTER_FLOW);
+
+	rtl_write_byte(rtlpriv, REG_RF_CTRL, 0x00);
+
+	if ((rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) && rtlhal->fw_ready)
+		rtl88e_firmware_selfreset(hw);
+
+	u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN+1);
+	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp & (~BIT(2))));
+	rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00);
+
+	u1b_tmp = rtl_read_byte(rtlpriv, REG_32K_CTRL);
+	rtl_write_byte(rtlpriv, REG_32K_CTRL, (u1b_tmp & (~BIT(0))));
+
+	rtl88_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK,
+				   PWR_INTF_PCI_MSK, Rtl8188E_NIC_DISABLE_FLOW);
+
+	u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL+1);
+	rtl_write_byte(rtlpriv, REG_RSV_CTRL+1, (u1b_tmp & (~BIT(3))));
+	u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL+1);
+	rtl_write_byte(rtlpriv, REG_RSV_CTRL+1, (u1b_tmp | BIT(3)));
+
+	rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x0E);
+
+	u1b_tmp = rtl_read_byte(rtlpriv, GPIO_IN);
+	rtl_write_byte(rtlpriv, GPIO_OUT, u1b_tmp);
+	rtl_write_byte(rtlpriv, GPIO_IO_SEL, 0x7F);
+
+	u1b_tmp = rtl_read_byte(rtlpriv, REG_GPIO_IO_SEL);
+	rtl_write_byte(rtlpriv, REG_GPIO_IO_SEL, (u1b_tmp << 4) | u1b_tmp);
+	u1b_tmp = rtl_read_byte(rtlpriv, REG_GPIO_IO_SEL+1);
+	rtl_write_byte(rtlpriv, REG_GPIO_IO_SEL+1, u1b_tmp | 0x0F);
+
+	rtl_write_dword(rtlpriv, REG_GPIO_IO_SEL_2+2, 0x00080808);
+}
+
+void rtl88ee_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_mac *mac = rtl_mac(rtl_priv(hw));
+	enum nl80211_iftype opmode;
+
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "RTL8188ee card disable\n");
+
+	mac->link_state = MAC80211_NOLINK;
+	opmode = NL80211_IFTYPE_UNSPECIFIED;
+
+	_rtl88ee_set_media_status(hw, opmode);
+
+	if (rtlpriv->rtlhal.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);
+	_rtl88ee_poweroff_adapter(hw);
+
+	/* after power off we should do iqk again */
+	rtlpriv->phy.iqk_initialized = false;
+}
+
+void rtl88ee_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, REG_HISRE, *p_intb);
+}
+
+void rtl88ee_set_beacon_related_registers(struct ieee80211_hw *hw)
+{
+	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));
+	u16 bcn_interval, atim_window;
+
+	bcn_interval = mac->beacon_interval;
+	atim_window = 2;	/*FIX MERGE */
+	rtl88ee_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, 0x18);
+	rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_OFDM, 0x18);
+	rtl_write_byte(rtlpriv, 0x606, 0x30);
+	rtlpci->reg_bcn_ctrl_val |= BIT(3);
+	rtl_write_byte(rtlpriv, REG_BCN_CTRL, (u8) rtlpci->reg_bcn_ctrl_val);
+	/*rtl88ee_enable_interrupt(hw);*/
+}
+
+void rtl88ee_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);
+	/*rtl88ee_disable_interrupt(hw);*/
+	rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval);
+	/*rtl88ee_enable_interrupt(hw);*/
+}
+
+void rtl88ee_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);
+
+	rtl88ee_disable_interrupt(hw);
+	if (add_msr)
+		rtlpci->irq_mask[0] |= add_msr;
+	if (rm_msr)
+		rtlpci->irq_mask[0] &= (~rm_msr);
+	rtl88ee_enable_interrupt(hw);
+}
+
+static inline u8 get_chnl_group(u8 chnl)
+{
+	u8 group;
+
+	group = chnl / 3;
+	if (chnl == 14)
+		group = 5;
+
+	return group;
+}
+
+static void set_diff0_2g(struct txpower_info_2g *pwr2g, u8 *hwinfo, u32 path,
+			 u32 i, u32 eadr)
+{
+	pwr2g->bw40_diff[path][i] = 0;
+	if (hwinfo[eadr] == 0xFF) {
+		pwr2g->bw20_diff[path][i] = 0x02;
+	} else {
+		pwr2g->bw20_diff[path][i] = (hwinfo[eadr]&0xf0)>>4;
+		/*bit sign number to 8 bit sign number*/
+		if (pwr2g->bw20_diff[path][i] & BIT(3))
+			pwr2g->bw20_diff[path][i] |= 0xF0;
+	}
+
+	if (hwinfo[eadr] == 0xFF) {
+		pwr2g->ofdm_diff[path][i] = 0x04;
+	} else {
+		pwr2g->ofdm_diff[path][i] = (hwinfo[eadr] & 0x0f);
+		/*bit sign number to 8 bit sign number*/
+		if (pwr2g->ofdm_diff[path][i] & BIT(3))
+			pwr2g->ofdm_diff[path][i] |= 0xF0;
+	}
+	pwr2g->cck_diff[path][i] = 0;
+}
+
+static void set_diff0_5g(struct txpower_info_5g *pwr5g, u8 *hwinfo, u32 path,
+			 u32 i, u32 eadr)
+{
+	pwr5g->bw40_diff[path][i] = 0;
+	if (hwinfo[eadr] == 0xFF) {
+		pwr5g->bw20_diff[path][i] = 0;
+	} else {
+		pwr5g->bw20_diff[path][i] = (hwinfo[eadr]&0xf0)>>4;
+		/*bit sign number to 8 bit sign number*/
+		if (pwr5g->bw20_diff[path][i] & BIT(3))
+			pwr5g->bw20_diff[path][i] |= 0xF0;
+	}
+
+	if (hwinfo[eadr] == 0xFF) {
+		pwr5g->ofdm_diff[path][i] = 0x04;
+	} else {
+		pwr5g->ofdm_diff[path][i] = (hwinfo[eadr] & 0x0f);
+		/*bit sign number to 8 bit sign number*/
+		if (pwr5g->ofdm_diff[path][i] & BIT(3))
+			pwr5g->ofdm_diff[path][i] |= 0xF0;
+	}
+}
+
+static void set_diff1_2g(struct txpower_info_2g *pwr2g, u8 *hwinfo, u32 path,
+			 u32 i, u32 eadr)
+{
+	if (hwinfo[eadr] == 0xFF) {
+		pwr2g->bw40_diff[path][i] = 0xFE;
+	} else {
+		pwr2g->bw40_diff[path][i] = (hwinfo[eadr]&0xf0)>>4;
+		if (pwr2g->bw40_diff[path][i] & BIT(3))
+			pwr2g->bw40_diff[path][i] |= 0xF0;
+	}
+
+	if (hwinfo[eadr] == 0xFF) {
+		pwr2g->bw20_diff[path][i] = 0xFE;
+	} else {
+		pwr2g->bw20_diff[path][i] = (hwinfo[eadr]&0x0f);
+		if (pwr2g->bw20_diff[path][i] & BIT(3))
+			pwr2g->bw20_diff[path][i] |= 0xF0;
+	}
+}
+
+static void set_diff1_5g(struct txpower_info_5g *pwr5g, u8 *hwinfo, u32 path,
+			 u32 i, u32 eadr)
+{
+	if (hwinfo[eadr] == 0xFF) {
+		pwr5g->bw40_diff[path][i] = 0xFE;
+	} else {
+		pwr5g->bw40_diff[path][i] = (hwinfo[eadr]&0xf0)>>4;
+		if (pwr5g->bw40_diff[path][i] & BIT(3))
+			pwr5g->bw40_diff[path][i] |= 0xF0;
+	}
+
+	if (hwinfo[eadr] == 0xFF) {
+		pwr5g->bw20_diff[path][i] = 0xFE;
+	} else {
+		pwr5g->bw20_diff[path][i] = (hwinfo[eadr] & 0x0f);
+		if (pwr5g->bw20_diff[path][i] & BIT(3))
+			pwr5g->bw20_diff[path][i] |= 0xF0;
+	}
+}
+
+static void set_diff2_2g(struct txpower_info_2g *pwr2g, u8 *hwinfo, u32 path,
+			 u32 i, u32 eadr)
+{
+	if (hwinfo[eadr] == 0xFF) {
+		pwr2g->ofdm_diff[path][i] = 0xFE;
+	} else {
+		pwr2g->ofdm_diff[path][i] = (hwinfo[eadr]&0xf0)>>4;
+		if (pwr2g->ofdm_diff[path][i] & BIT(3))
+			pwr2g->ofdm_diff[path][i] |= 0xF0;
+	}
+
+	if (hwinfo[eadr] == 0xFF) {
+		pwr2g->cck_diff[path][i] = 0xFE;
+	} else {
+		pwr2g->cck_diff[path][i] = (hwinfo[eadr]&0x0f);
+		if (pwr2g->cck_diff[path][i] & BIT(3))
+			pwr2g->cck_diff[path][i] |= 0xF0;
+	}
+}
+
+static void _rtl8188e_read_power_value_fromprom(struct ieee80211_hw *hw,
+						struct txpower_info_2g *pwr2g,
+						struct txpower_info_5g *pwr5g,
+						bool autoload_fail,
+						u8 *hwinfo)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u32 path, eadr = EEPROM_TX_PWR_INX, i;
+
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+		 "hal_ReadPowerValueFromPROM88E(): PROMContent[0x%x]= 0x%x\n",
+		 (eadr+1), hwinfo[eadr+1]);
+	if (0xFF == hwinfo[eadr+1])
+		autoload_fail = true;
+
+	if (autoload_fail) {
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+			 "auto load fail : Use Default value!\n");
+		for (path = 0; path < MAX_RF_PATH; path++) {
+			/* 2.4G default value */
+			for (i = 0; i < MAX_CHNL_GROUP_24G; i++) {
+				pwr2g->index_cck_base[path][i] = 0x2D;
+				pwr2g->index_bw40_base[path][i] = 0x2D;
+			}
+			for (i = 0; i < MAX_TX_COUNT; i++) {
+				if (i == 0) {
+					pwr2g->bw20_diff[path][0] = 0x02;
+					pwr2g->ofdm_diff[path][0] = 0x04;
+				} else {
+					pwr2g->bw20_diff[path][i] = 0xFE;
+					pwr2g->bw40_diff[path][i] = 0xFE;
+					pwr2g->cck_diff[path][i] = 0xFE;
+					pwr2g->ofdm_diff[path][i] = 0xFE;
+				}
+			}
+		}
+		return;
+	}
+
+	for (path = 0; path < MAX_RF_PATH; path++) {
+		/*2.4G default value*/
+		for (i = 0; i < MAX_CHNL_GROUP_24G; i++) {
+			pwr2g->index_cck_base[path][i] = hwinfo[eadr++];
+			if (pwr2g->index_cck_base[path][i] == 0xFF)
+				pwr2g->index_cck_base[path][i] = 0x2D;
+		}
+		for (i = 0; i < MAX_CHNL_GROUP_24G-1; i++) {
+			pwr2g->index_bw40_base[path][i] = hwinfo[eadr++];
+			if (pwr2g->index_bw40_base[path][i] == 0xFF)
+				pwr2g->index_bw40_base[path][i] = 0x2D;
+		}
+		for (i = 0; i < MAX_TX_COUNT; i++) {
+			if (i == 0) {
+				set_diff0_2g(pwr2g, hwinfo, path, i, eadr);
+				eadr++;
+			} else {
+				set_diff1_2g(pwr2g, hwinfo, path, i, eadr);
+				eadr++;
+
+				set_diff2_2g(pwr2g, hwinfo, path, i, eadr);
+				eadr++;
+			}
+		}
+
+		/*5G default value*/
+		for (i = 0; i < MAX_CHNL_GROUP_5G; i++) {
+			pwr5g->index_bw40_base[path][i] = hwinfo[eadr++];
+			if (pwr5g->index_bw40_base[path][i] == 0xFF)
+				pwr5g->index_bw40_base[path][i] = 0xFE;
+		}
+
+		for (i = 0; i < MAX_TX_COUNT; i++) {
+			if (i == 0) {
+				set_diff0_5g(pwr5g, hwinfo, path, i, eadr);
+				eadr++;
+			} else {
+				set_diff1_5g(pwr5g, hwinfo, path, i, eadr);
+				eadr++;
+			}
+		}
+
+		if (hwinfo[eadr] == 0xFF) {
+			pwr5g->ofdm_diff[path][1] = 0xFE;
+			pwr5g->ofdm_diff[path][2] = 0xFE;
+		} else {
+			pwr5g->ofdm_diff[path][1] = (hwinfo[eadr] & 0xf0) >> 4;
+			pwr5g->ofdm_diff[path][2] = (hwinfo[eadr] & 0x0f);
+		}
+		eadr++;
+
+		if (hwinfo[eadr] == 0xFF)
+			pwr5g->ofdm_diff[path][3] = 0xFE;
+		else
+			pwr5g->ofdm_diff[path][3] = (hwinfo[eadr]&0x0f);
+		eadr++;
+
+		for (i = 1; i < MAX_TX_COUNT; i++) {
+			if (pwr5g->ofdm_diff[path][i] == 0xFF)
+				pwr5g->ofdm_diff[path][i] = 0xFE;
+			else if (pwr5g->ofdm_diff[path][i] & BIT(3))
+				pwr5g->ofdm_diff[path][i] |= 0xF0;
+		}
+	}
+}
+
+static void _rtl88ee_read_txpower_info_from_hwpg(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_2g pwrinfo24g;
+	struct txpower_info_5g pwrinfo5g;
+	u8 rf_path, index;
+	u8 i;
+	int jj = EEPROM_RF_BOARD_OPTION_88E;
+	int kk = EEPROM_THERMAL_METER_88E;
+
+	_rtl8188e_read_power_value_fromprom(hw, &pwrinfo24g, &pwrinfo5g,
+					    autoload_fail, hwinfo);
+
+	for (rf_path = 0; rf_path < 2; rf_path++) {
+		for (i = 0; i < 14; i++) {
+			index = get_chnl_group(i+1);
+
+			rtlefuse->txpwrlevel_cck[rf_path][i] =
+				 pwrinfo24g.index_cck_base[rf_path][index];
+			if (i == 13)
+				rtlefuse->txpwrlevel_ht40_1s[rf_path][i] =
+				     pwrinfo24g.index_bw40_base[rf_path][4];
+			else
+				rtlefuse->txpwrlevel_ht40_1s[rf_path][i] =
+				     pwrinfo24g.index_bw40_base[rf_path][index];
+			rtlefuse->txpwr_ht20diff[rf_path][i] =
+				 pwrinfo24g.bw20_diff[rf_path][0];
+			rtlefuse->txpwr_legacyhtdiff[rf_path][i] =
+				 pwrinfo24g.ofdm_diff[rf_path][0];
+		}
+
+		for (i = 0; i < 14; i++) {
+			RTPRINT(rtlpriv, FINIT, INIT_TXPOWER,
+				"RF(%d)-Ch(%d) [CCK / HT40_1S ] = "
+				"[0x%x / 0x%x ]\n", rf_path, i,
+				rtlefuse->txpwrlevel_cck[rf_path][i],
+				rtlefuse->txpwrlevel_ht40_1s[rf_path][i]);
+		}
+	}
+
+	if (!autoload_fail)
+		rtlefuse->eeprom_thermalmeter = hwinfo[kk];
+	else
+		rtlefuse->eeprom_thermalmeter = EEPROM_DEFAULT_THERMALMETER;
+
+	if (rtlefuse->eeprom_thermalmeter == 0xff || autoload_fail) {
+		rtlefuse->apk_thermalmeterignore = true;
+		rtlefuse->eeprom_thermalmeter = EEPROM_DEFAULT_THERMALMETER;
+	}
+
+	rtlefuse->thermalmeter[0] = rtlefuse->eeprom_thermalmeter;
+	RTPRINT(rtlpriv, FINIT, INIT_TXPOWER,
+		"thermalmeter = 0x%x\n", rtlefuse->eeprom_thermalmeter);
+
+	if (!autoload_fail) {
+		rtlefuse->eeprom_regulatory = hwinfo[jj] & 0x07;/*bit0~2*/
+		if (hwinfo[jj] == 0xFF)
+			rtlefuse->eeprom_regulatory = 0;
+	} else {
+		rtlefuse->eeprom_regulatory = 0;
+	}
+	RTPRINT(rtlpriv, FINIT, INIT_TXPOWER,
+		"eeprom_regulatory = 0x%x\n", rtlefuse->eeprom_regulatory);
+}
+
+static void _rtl88ee_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));
+	struct rtl_pci_priv *rppriv = rtl_pcipriv(hw);
+	u16 i, usvalue;
+	u8 hwinfo[HWSET_MAX_SIZE];
+	u16 eeprom_id;
+	int jj = EEPROM_RF_BOARD_OPTION_88E;
+	int kk = EEPROM_RF_FEATURE_OPTION_88E;
+
+	if (rtlefuse->epromtype == EEPROM_BOOT_EFUSE) {
+		rtl_efuse_shadow_map_update(hw);
+
+		memcpy(hwinfo, &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 != RTL8188E_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 == true)
+		return;
+	/*VID DID SVID SDID*/
+	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);
+	/*customer ID*/
+	rtlefuse->eeprom_oemid = *(u8 *)&hwinfo[EEPROM_CUSTOMER_ID];
+	if (rtlefuse->eeprom_oemid == 0xFF)
+		rtlefuse->eeprom_oemid = 0;
+
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+		 "EEPROM Customer ID: 0x%2x\n", rtlefuse->eeprom_oemid);
+	/*EEPROM version*/
+	rtlefuse->eeprom_version = *(u16 *)&hwinfo[EEPROM_VERSION];
+	/*mac address*/
+	for (i = 0; i < 6; i += 2) {
+		usvalue = *(u16 *)&hwinfo[EEPROM_MAC_ADDR + i];
+		*((u16 *)(&rtlefuse->dev_addr[i])) = usvalue;
+	}
+
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+		 "dev_addr: %pM\n", rtlefuse->dev_addr);
+	/*channel plan */
+	rtlefuse->eeprom_channelplan = *(u8 *)&hwinfo[EEPROM_CHANNELPLAN];
+	/* set channel paln to world wide 13 */
+	rtlefuse->channel_plan = COUNTRY_CODE_WORLD_WIDE_13;
+	/*tx power*/
+	_rtl88ee_read_txpower_info_from_hwpg(hw, rtlefuse->autoload_failflag,
+					     hwinfo);
+	rtlefuse->txpwr_fromeprom = true;
+
+	rtl8188ee_read_bt_coexist_info_from_hwpg(hw,
+						 rtlefuse->autoload_failflag,
+						 hwinfo);
+	/*board type*/
+	rtlefuse->board_type = (((*(u8 *)&hwinfo[jj]) & 0xE0) >> 5);
+	/*Wake on wlan*/
+	rtlefuse->wowlan_enable = ((hwinfo[kk] & 0x40) >> 6);
+	/*parse xtal*/
+	rtlefuse->crystalcap = hwinfo[EEPROM_XTAL_88E];
+	if (hwinfo[EEPROM_XTAL_88E])
+		rtlefuse->crystalcap = 0x20;
+	/*antenna diversity*/
+	rtlefuse->antenna_div_cfg = (hwinfo[jj] & 0x18) >> 3;
+	if (hwinfo[jj] == 0xFF)
+		rtlefuse->antenna_div_cfg = 0;
+	if (rppriv->bt_coexist.eeprom_bt_coexist != 0 &&
+	    rppriv->bt_coexist.eeprom_bt_ant_num == ANT_X1)
+		rtlefuse->antenna_div_cfg = 0;
+
+	rtlefuse->antenna_div_type = hwinfo[EEPROM_RF_ANTENNA_OPT_88E];
+	if (rtlefuse->antenna_div_type == 0xFF)
+		rtlefuse->antenna_div_type = 0x01;
+	if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV ||
+	    rtlefuse->antenna_div_type == CGCS_RX_HW_ANTDIV)
+		rtlefuse->antenna_div_cfg = 1;
+
+	if (rtlhal->oem_id == RT_CID_DEFAULT) {
+		switch (rtlefuse->eeprom_oemid) {
+		case EEPROM_CID_DEFAULT:
+			if (rtlefuse->eeprom_did == 0x8179) {
+				if (rtlefuse->eeprom_svid == 0x1025) {
+					rtlhal->oem_id = RT_CID_819x_Acer;
+				} else if ((rtlefuse->eeprom_svid == 0x10EC &&
+					    rtlefuse->eeprom_smid == 0x0179) ||
+					    (rtlefuse->eeprom_svid == 0x17AA &&
+					    rtlefuse->eeprom_smid == 0x0179)) {
+					rtlhal->oem_id = RT_CID_819x_Lenovo;
+				} else if (rtlefuse->eeprom_svid == 0x103c &&
+					 rtlefuse->eeprom_smid == 0x197d) {
+					rtlhal->oem_id = RT_CID_819x_HP;
+				} else {
+					rtlhal->oem_id = RT_CID_DEFAULT;
+				}
+			} else {
+				rtlhal->oem_id = RT_CID_DEFAULT;
+			}
+			break;
+		case EEPROM_CID_TOSHIBA:
+			rtlhal->oem_id = RT_CID_TOSHIBA;
+			break;
+		case EEPROM_CID_QMI:
+			rtlhal->oem_id = RT_CID_819x_QMI;
+			break;
+		case EEPROM_CID_WHQL:
+		default:
+			rtlhal->oem_id = RT_CID_DEFAULT;
+			break;
+		}
+	}
+}
+
+static void _rtl88ee_hal_customized_behavior(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+
+	pcipriv->ledctl.led_opendrain = true;
+
+	switch (rtlhal->oem_id) {
+	case RT_CID_819x_HP:
+		pcipriv->ledctl.led_opendrain = true;
+		break;
+	case RT_CID_819x_Lenovo:
+	case RT_CID_DEFAULT:
+	case RT_CID_TOSHIBA:
+	case RT_CID_CCX:
+	case RT_CID_819x_Acer:
+	case RT_CID_WHQL:
+	default:
+		break;
+	}
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+		 "RT Customized ID: 0x%02X\n", rtlhal->oem_id);
+}
+
+void rtl88ee_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_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	u8 tmp_u1b;
+
+	rtlhal->version = _rtl88ee_read_chip_version(hw);
+	if (get_rf_type(rtlphy) == RF_1T1R) {
+		rtlpriv->dm.rfpath_rxenable[0] = true;
+	} else {
+		rtlpriv->dm.rfpath_rxenable[0] = true;
+		rtlpriv->dm.rfpath_rxenable[1] = true;
+	}
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "VersionID = 0x%4x\n",
+		 rtlhal->version);
+	tmp_u1b = rtl_read_byte(rtlpriv, REG_9346CR);
+	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;
+		_rtl88ee_read_adapter_info(hw);
+	} else {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Autoload ERR!!\n");
+	}
+	_rtl88ee_hal_customized_behavior(hw);
+}
+
+static void rtl88ee_update_hal_rate_table(struct ieee80211_hw *hw,
+					  struct ieee80211_sta *sta)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci_priv *rppriv = rtl_pcipriv(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 ctx40 = mac->bw_40;
+	u16 cap = sta->ht_cap.cap;
+	u8 short40 = (cap & IEEE80211_HT_CAP_SGI_40) ?  1 : 0;
+	u8 short20 = (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];
+	if (mac->opmode == NL80211_IFTYPE_ADHOC)
+		ratr_value = 0xfff;
+	ratr_value |= (sta->ht_cap.mcs.rx_mask[1] << 20 |
+			sta->ht_cap.mcs.rx_mask[0] << 12);
+	switch (wirelessmode) {
+	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;
+	}
+
+	if ((rppriv->bt_coexist.bt_coexistence) &&
+	    (rppriv->bt_coexist.bt_coexist_type == BT_CSR_BC4) &&
+	    (rppriv->bt_coexist.bt_cur_state) &&
+	    (rppriv->bt_coexist.bt_ant_isolation) &&
+	    ((rppriv->bt_coexist.bt_service == BT_SCO) ||
+	    (rppriv->bt_coexist.bt_service == BT_BUSY)))
+		ratr_value &= 0x0fffcfc0;
+	else
+		ratr_value &= 0x0FFFFFFF;
+
+	if (nmode && ((ctx40 && short40) ||
+		      (!ctx40 && short20))) {
+		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 rtl88ee_update_hal_rate_mask(struct ieee80211_hw *hw,
+					 struct ieee80211_sta *sta, u8 rssi)
+{
+	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;
+	u16 cap = sta->ht_cap.cap;
+	u8 ctx40 = (cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) ? 1 : 0;
+	u8 short40 = (cap & IEEE80211_HT_CAP_SGI_40) ?  1 : 0;
+	u8 short20 = (cap & IEEE80211_HT_CAP_SGI_20) ?  1 : 0;
+	enum wireless_mode wirelessmode = 0;
+	bool shortgi = false;
+	u8 rate_mask[5];
+	u8 macid = 0;
+	u8 mimo_ps = IEEE80211_SMPS_OFF;
+
+	sta_entry = (struct rtl_sta_info *)sta->drv_priv;
+	wirelessmode = sta_entry->wireless_mode;
+	if (mac->opmode == NL80211_IFTYPE_STATION ||
+	    mac->opmode == NL80211_IFTYPE_MESH_POINT)
+		ctx40 = 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];
+	if (mac->opmode == NL80211_IFTYPE_ADHOC)
+		ratr_bitmap = 0xfff;
+	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 == 1)
+			ratr_bitmap &= 0x00000f00;
+		else if (rssi == 2)
+			ratr_bitmap &= 0x00000ff0;
+		else
+			ratr_bitmap &= 0x00000ff5;
+		break;
+	case WIRELESS_MODE_A:
+		ratr_index = RATR_INX_WIRELESS_A;
+		ratr_bitmap &= 0x00000ff0;
+		break;
+	case WIRELESS_MODE_N_24G:
+	case WIRELESS_MODE_N_5G:
+		ratr_index = RATR_INX_WIRELESS_NGB;
+
+		if (mimo_ps == IEEE80211_SMPS_STATIC) {
+			if (rssi == 1)
+				ratr_bitmap &= 0x00070000;
+			else if (rssi == 2)
+				ratr_bitmap &= 0x0007f000;
+			else
+				ratr_bitmap &= 0x0007f005;
+		} else {
+			if (rtlphy->rf_type == RF_1T2R ||
+			    rtlphy->rf_type == RF_1T1R) {
+				if (ctx40) {
+					if (rssi == 1)
+						ratr_bitmap &= 0x000f0000;
+					else if (rssi == 2)
+						ratr_bitmap &= 0x000ff000;
+					else
+						ratr_bitmap &= 0x000ff015;
+				} else {
+					if (rssi == 1)
+						ratr_bitmap &= 0x000f0000;
+					else if (rssi == 2)
+						ratr_bitmap &= 0x000ff000;
+					else
+						ratr_bitmap &= 0x000ff005;
+				}
+			} else {
+				if (ctx40) {
+					if (rssi == 1)
+						ratr_bitmap &= 0x0f8f0000;
+					else if (rssi == 2)
+						ratr_bitmap &= 0x0f8ff000;
+					else
+						ratr_bitmap &= 0x0f8ff015;
+				} else {
+					if (rssi == 1)
+						ratr_bitmap &= 0x0f8f0000;
+					else if (rssi == 2)
+						ratr_bitmap &= 0x0f8ff000;
+					else
+						ratr_bitmap &= 0x0f8ff005;
+				}
+			}
+		}
+
+		if ((ctx40 && short40) || (!ctx40 && short20)) {
+			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;
+	}
+	sta_entry->ratr_index = ratr_index;
+
+	RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG,
+		 "ratr_bitmap :%x\n", ratr_bitmap);
+	*(u32 *)&rate_mask = (ratr_bitmap & 0x0fffffff) |
+			     (ratr_index << 28);
+	rate_mask[4] = macid | (shortgi ? 0x20 : 0x00) | 0x80;
+	RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG,
+		 "Rate_index:%x, ratr_val:%x, %x:%x:%x:%x:%x\n",
+		 ratr_index, ratr_bitmap, rate_mask[0], rate_mask[1],
+		 rate_mask[2], rate_mask[3], rate_mask[4]);
+	rtl88e_fill_h2c_cmd(hw, H2C_88E_RA_MASK, 5, rate_mask);
+	_rtl88ee_set_bcn_ctrl_reg(hw, BIT(3), 0);
+}
+
+void rtl88ee_update_hal_rate_tbl(struct ieee80211_hw *hw,
+		struct ieee80211_sta *sta, u8 rssi)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	if (rtlpriv->dm.useramask)
+		rtl88ee_update_hal_rate_mask(hw, sta, rssi);
+	else
+		rtl88ee_update_hal_rate_table(hw, sta);
+}
+
+void rtl88ee_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 = 0x0e0e;
+	rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SIFS, (u8 *)&sifs_timer);
+}
+
+bool rtl88ee_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));
+	enum rf_pwrstate state_toset;
+	u32 u4tmp;
+	bool actuallyset = false;
+
+	if (rtlpriv->rtlhal.being_init_adapter)
+		return false;
+
+	if (ppsc->swrf_processing)
+		return false;
+
+	spin_lock(&rtlpriv->locks.rf_ps_lock);
+	if (ppsc->rfchange_inprogress) {
+		spin_unlock(&rtlpriv->locks.rf_ps_lock);
+		return false;
+	} else {
+		ppsc->rfchange_inprogress = true;
+		spin_unlock(&rtlpriv->locks.rf_ps_lock);
+	}
+
+	u4tmp = rtl_read_dword(rtlpriv, REG_GPIO_OUTPUT);
+	state_toset = (u4tmp & BIT(31)) ? ERFON : ERFOFF;
+
+
+	if ((ppsc->hwradiooff == true) && (state_toset == ERFON)) {
+		RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
+			 "GPIOChangeRF  - HW Radio ON, RF ON\n");
+
+		state_toset = ERFON;
+		ppsc->hwradiooff = false;
+		actuallyset = true;
+	} else if ((ppsc->hwradiooff == false) && (state_toset == ERFOFF)) {
+		RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
+			 "GPIOChangeRF  - HW Radio OFF, RF OFF\n");
+
+		state_toset = ERFOFF;
+		ppsc->hwradiooff = true;
+		actuallyset = true;
+	}
+
+	if (actuallyset) {
+		spin_lock(&rtlpriv->locks.rf_ps_lock);
+		ppsc->rfchange_inprogress = false;
+		spin_unlock(&rtlpriv->locks.rf_ps_lock);
+	} 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(&rtlpriv->locks.rf_ps_lock);
+		ppsc->rfchange_inprogress = false;
+		spin_unlock(&rtlpriv->locks.rf_ps_lock);
+	}
+
+	*valid = 1;
+	return !ppsc->hwradiooff;
+}
+
+static void add_one_key(struct ieee80211_hw *hw, u8 *macaddr,
+			struct rtl_mac *mac, u32 key, u32 id,
+			u8 enc_algo, bool is_pairwise)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+
+	RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "add one entry\n");
+	if (is_pairwise) {
+		RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "set Pairwise key\n");
+
+		rtl_cam_add_one_entry(hw, macaddr, key, id, enc_algo,
+				      CAM_CONFIG_NO_USEDK,
+				      rtlpriv->sec.key_buf[key]);
+	} 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[id]);
+		}
+
+		rtl_cam_add_one_entry(hw, macaddr, key, id, enc_algo,
+				      CAM_CONFIG_NO_USEDK,
+				      rtlpriv->sec.key_buf[id]);
+	}
+}
+
+void rtl88ee_set_key(struct ieee80211_hw *hw, u32 key,
+		     u8 *mac_ad, 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));
+	u8 *macaddr = mac_ad;
+	u32 id = 0;
+	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 = 0;
+		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 processed\n");
+			enc_algo = CAM_TKIP;
+			break;
+		}
+
+		if (is_wepkey || rtlpriv->sec.use_defaultkey) {
+			macaddr = cam_const_addr[key];
+			id = key;
+		} else {
+			if (is_group) {
+				macaddr = cam_const_broad;
+				id = key;
+			} else {
+				if (mac->opmode == NL80211_IFTYPE_AP ||
+				    mac->opmode == NL80211_IFTYPE_MESH_POINT) {
+					id = rtl_cam_get_free_entry(hw, mac_ad);
+					if (id >=  TOTAL_CAM_ENTRY) {
+						RT_TRACE(rtlpriv, COMP_SEC,
+							 DBG_EMERG,
+							 "Can not find free hw security cam entry\n");
+						return;
+					}
+				} else {
+					id = CAM_PAIRWISE_KEY_POSITION;
+				}
+
+				key = PAIRWISE_KEYIDX;
+				is_pairwise = true;
+			}
+		}
+
+		if (rtlpriv->sec.key_len[key] == 0) {
+			RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
+				 "delete one entry, id is %d\n", id);
+			if (mac->opmode == NL80211_IFTYPE_AP ||
+			    mac->opmode == NL80211_IFTYPE_MESH_POINT)
+				rtl_cam_del_entry(hw, mac_ad);
+			rtl_cam_delete_one_entry(hw, mac_ad, id);
+		} else {
+			add_one_key(hw, macaddr, mac, key, id, enc_algo,
+				    is_pairwise);
+		}
+	}
+}
+
+static void rtl8188ee_bt_var_init(struct ieee80211_hw *hw)
+{
+	struct rtl_pci_priv *rppriv = rtl_pcipriv(hw);
+	struct bt_coexist_info coexist = rppriv->bt_coexist;
+
+	coexist.bt_coexistence = rppriv->bt_coexist.eeprom_bt_coexist;
+	coexist.bt_ant_num = coexist.eeprom_bt_ant_num;
+	coexist.bt_coexist_type = coexist.eeprom_bt_type;
+
+	if (coexist.reg_bt_iso == 2)
+		coexist.bt_ant_isolation = coexist.eeprom_bt_ant_isol;
+	else
+		coexist.bt_ant_isolation = coexist.reg_bt_iso;
+
+	coexist.bt_radio_shared_type = coexist.eeprom_bt_radio_shared;
+
+	if (coexist.bt_coexistence) {
+		if (coexist.reg_bt_sco == 1)
+			coexist.bt_service = BT_OTHER_ACTION;
+		else if (coexist.reg_bt_sco == 2)
+			coexist.bt_service = BT_SCO;
+		else if (coexist.reg_bt_sco == 4)
+			coexist.bt_service = BT_BUSY;
+		else if (coexist.reg_bt_sco == 5)
+			coexist.bt_service = BT_OTHERBUSY;
+		else
+			coexist.bt_service = BT_IDLE;
+
+		coexist.bt_edca_ul = 0;
+		coexist.bt_edca_dl = 0;
+		coexist.bt_rssi_state = 0xff;
+	}
+}
+
+void rtl8188ee_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw,
+					      bool auto_load_fail, u8 *hwinfo)
+{
+	rtl8188ee_bt_var_init(hw);
+}
+
+void rtl8188ee_bt_reg_init(struct ieee80211_hw *hw)
+{
+	struct rtl_pci_priv *rppriv = rtl_pcipriv(hw);
+
+	/* 0:Low, 1:High, 2:From Efuse. */
+	rppriv->bt_coexist.reg_bt_iso = 2;
+	/* 0:Idle, 1:None-SCO, 2:SCO, 3:From Counter. */
+	rppriv->bt_coexist.reg_bt_sco = 3;
+	/* 0:Disable BT control A-MPDU, 1:Enable BT control A-MPDU. */
+	rppriv->bt_coexist.reg_bt_sco = 0;
+}
+
+void rtl8188ee_bt_hw_init(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_pci_priv *rppriv = rtl_pcipriv(hw);
+	struct bt_coexist_info coexist = rppriv->bt_coexist;
+	u8 u1_tmp;
+
+	if (coexist.bt_coexistence &&
+	    ((coexist.bt_coexist_type == BT_CSR_BC4) ||
+	      coexist.bt_coexist_type == BT_CSR_BC8)) {
+		if (coexist.bt_ant_isolation)
+			rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0xa0);
+
+		u1_tmp = rtl_read_byte(rtlpriv, 0x4fd) &
+				       BIT_OFFSET_LEN_MASK_32(0, 1);
+		u1_tmp = u1_tmp | ((coexist.bt_ant_isolation == 1) ?
+			 0 : BIT_OFFSET_LEN_MASK_32(1, 1)) |
+			 ((coexist.bt_service == BT_SCO) ?
+			 0 : BIT_OFFSET_LEN_MASK_32(2, 1));
+		rtl_write_byte(rtlpriv, 0x4fd, u1_tmp);
+
+		rtl_write_dword(rtlpriv, REG_BT_COEX_TABLE+4, 0xaaaa9aaa);
+		rtl_write_dword(rtlpriv, REG_BT_COEX_TABLE+8, 0xffbd0040);
+		rtl_write_dword(rtlpriv, REG_BT_COEX_TABLE+0xc, 0x40000010);
+
+		/* Config to 1T1R. */
+		if (rtlphy->rf_type == RF_1T1R) {
+			u1_tmp = rtl_read_byte(rtlpriv, ROFDM0_TRXPATHENABLE);
+			u1_tmp &= ~(BIT_OFFSET_LEN_MASK_32(1, 1));
+			rtl_write_byte(rtlpriv, ROFDM0_TRXPATHENABLE, u1_tmp);
+
+			u1_tmp = rtl_read_byte(rtlpriv, ROFDM1_TRXPATHENABLE);
+			u1_tmp &= ~(BIT_OFFSET_LEN_MASK_32(1, 1));
+			rtl_write_byte(rtlpriv, ROFDM1_TRXPATHENABLE, u1_tmp);
+		}
+	}
+}
+
+void rtl88ee_suspend(struct ieee80211_hw *hw)
+{
+}
+
+void rtl88ee_resume(struct ieee80211_hw *hw)
+{
+}
+
+/* Turn on AAP (RCR:bit 0) for promicuous mode. */
+void rtl88ee_allow_all_destaddr(struct ieee80211_hw *hw,
+				bool allow_all_da, bool write_into_reg)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+
+	if (allow_all_da) /* Set BIT0 */
+		rtlpci->receive_config |= RCR_AAP;
+	 else /* Clear BIT0 */
+		rtlpci->receive_config &= ~RCR_AAP;
+
+	if (write_into_reg)
+		rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config);
+
+	RT_TRACE(rtlpriv, COMP_TURBO | COMP_INIT, DBG_LOUD,
+		 "receive_config = 0x%08X, write_into_reg =%d\n",
+		 rtlpci->receive_config, write_into_reg);
+}
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/hw.h b/drivers/net/wireless/rtlwifi/rtl8188ee/hw.h
new file mode 100644
index 0000000..b4460a4
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8188ee/hw.h
@@ -0,0 +1,68 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2013  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_HW_H__
+#define __RTL92CE_HW_H__
+
+void rtl88ee_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val);
+void rtl88ee_read_eeprom_info(struct ieee80211_hw *hw);
+void rtl88ee_interrupt_recognized(struct ieee80211_hw *hw,
+				  u32 *p_inta, u32 *p_intb);
+int rtl88ee_hw_init(struct ieee80211_hw *hw);
+void rtl88ee_card_disable(struct ieee80211_hw *hw);
+void rtl88ee_enable_interrupt(struct ieee80211_hw *hw);
+void rtl88ee_disable_interrupt(struct ieee80211_hw *hw);
+int rtl88ee_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type);
+void rtl88ee_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid);
+void rtl88ee_set_qos(struct ieee80211_hw *hw, int aci);
+void rtl88ee_set_beacon_related_registers(struct ieee80211_hw *hw);
+void rtl88ee_set_beacon_interval(struct ieee80211_hw *hw);
+void rtl88ee_update_interrupt_mask(struct ieee80211_hw *hw,
+				   u32 add_msr, u32 rm_msr);
+void rtl88ee_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val);
+void rtl88ee_update_hal_rate_tbl(struct ieee80211_hw *hw,
+				 struct ieee80211_sta *sta, u8 rssi_level);
+void rtl88ee_update_channel_access_setting(struct ieee80211_hw *hw);
+bool rtl88ee_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid);
+void rtl88ee_enable_hw_security_config(struct ieee80211_hw *hw);
+void rtl88ee_set_key(struct ieee80211_hw *hw, u32 key_index,
+		     u8 *p_macaddr, bool is_group, u8 enc_algo,
+		     bool is_wepkey, bool clear_all);
+
+void rtl8188ee_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw,
+					      bool autoload_fail, u8 *hwinfo);
+void rtl8188ee_bt_reg_init(struct ieee80211_hw *hw);
+void rtl8188ee_bt_hw_init(struct ieee80211_hw *hw);
+void rtl88ee_suspend(struct ieee80211_hw *hw);
+void rtl88ee_resume(struct ieee80211_hw *hw);
+void rtl88ee_allow_all_destaddr(struct ieee80211_hw *hw,
+				bool allow_all_da, bool write_into_reg);
+void rtl88ee_fw_clk_off_timer_callback(unsigned long data);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/led.c b/drivers/net/wireless/rtlwifi/rtl8188ee/led.c
new file mode 100644
index 0000000..c81a9cb
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8188ee/led.c
@@ -0,0 +1,157 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2013  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 rtl88ee_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 rtl88ee_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);
+		rtl_write_byte(rtlpriv, REG_LEDCFG2,
+			       (ledcfg & 0xf0) | BIT(5) | BIT(6));
+		break;
+	case LED_PIN_LED1:
+		ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG1);
+		rtl_write_byte(rtlpriv, REG_LEDCFG1, ledcfg & 0x10);
+		break;
+	default:
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 "switch case not processed\n");
+		break;
+	}
+	pled->ledon = true;
+}
+
+void rtl88ee_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;
+	u8 val;
+
+	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);
+		ledcfg &= 0xf0;
+		val = ledcfg | BIT(3) | BIT(5) | BIT(6);
+		if (pcipriv->ledctl.led_opendrain == true) {
+			rtl_write_byte(rtlpriv, REG_LEDCFG2, val);
+			ledcfg = rtl_read_byte(rtlpriv, REG_MAC_PINMUX_CFG);
+			val = ledcfg & 0xFE;
+			rtl_write_byte(rtlpriv, REG_MAC_PINMUX_CFG, val);
+		} else {
+			rtl_write_byte(rtlpriv, REG_LEDCFG2, val);
+		}
+		break;
+	case LED_PIN_LED1:
+		ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG1);
+		ledcfg &= 0x10;
+		rtl_write_byte(rtlpriv, REG_LEDCFG1, (ledcfg | BIT(3)));
+		break;
+	default:
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 "switch case not processed\n");
+		break;
+	}
+	pled->ledon = false;
+}
+
+void rtl88ee_init_sw_leds(struct ieee80211_hw *hw)
+{
+	struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
+
+	rtl88ee_init_led(hw, &(pcipriv->ledctl.sw_led0), LED_PIN_LED0);
+	rtl88ee_init_led(hw, &(pcipriv->ledctl.sw_led1), LED_PIN_LED1);
+}
+
+static void rtl88ee_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:
+		rtl88ee_sw_led_on(hw, pLed0);
+		break;
+	case LED_CTL_POWER_OFF:
+		rtl88ee_sw_led_off(hw, pLed0);
+		break;
+	default:
+		break;
+	}
+}
+
+void rtl88ee_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_TRACE, "ledaction %d,\n",
+		 ledaction);
+	rtl88ee_sw_led_control(hw, ledaction);
+}
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/led.h b/drivers/net/wireless/rtlwifi/rtl8188ee/led.h
new file mode 100644
index 0000000..4073f6f
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8188ee/led.h
@@ -0,0 +1,38 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2013  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 rtl88ee_init_sw_leds(struct ieee80211_hw *hw);
+void rtl88ee_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled);
+void rtl88ee_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled);
+void rtl88ee_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/phy.c b/drivers/net/wireless/rtlwifi/rtl8188ee/phy.c
new file mode 100644
index 0000000..e655c04
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8188ee/phy.c
@@ -0,0 +1,2202 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2013  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"
+
+static void set_baseband_phy_config(struct ieee80211_hw *hw);
+static void set_baseband_agc_config(struct ieee80211_hw *hw);
+static void store_pwrindex_offset(struct ieee80211_hw *hw,
+				  u32 regaddr, u32 bitmask,
+				  u32 data);
+static bool check_cond(struct ieee80211_hw *hw, const u32  condition);
+
+static u32 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 *phreg = &rtlphy->phyreg_def[rfpath];
+	u32 newoffset;
+	u32 tmplong, tmplong2;
+	u8 rfpi_enable = 0;
+	u32 ret;
+	int jj = RF90_PATH_A;
+	int kk = RF90_PATH_B;
+
+	offset &= 0xff;
+	newoffset = offset;
+	if (RT_CANNOT_IO(hw)) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "return all one\n");
+		return 0xFFFFFFFF;
+	}
+	tmplong = rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD);
+	if (rfpath == jj)
+		tmplong2 = tmplong;
+	else
+		tmplong2 = rtl_get_bbreg(hw, phreg->rfhssi_para2, MASKDWORD);
+	tmplong2 = (tmplong2 & (~BLSSIREADADDRESS)) |
+	    (newoffset << 23) | BLSSIREADEDGE;
+	rtl_set_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD,
+		      tmplong & (~BLSSIREADEDGE));
+	mdelay(1);
+	rtl_set_bbreg(hw, phreg->rfhssi_para2, MASKDWORD, tmplong2);
+	mdelay(2);
+	if (rfpath == jj)
+		rfpi_enable = (u8) rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER1,
+						 BIT(8));
+	else if (rfpath == kk)
+		rfpi_enable = (u8) rtl_get_bbreg(hw, RFPGA0_XB_HSSIPARAMETER1,
+						 BIT(8));
+	if (rfpi_enable)
+		ret = rtl_get_bbreg(hw, phreg->rf_rbpi, BLSSIREADBACKDATA);
+	else
+		ret = rtl_get_bbreg(hw, phreg->rf_rb, BLSSIREADBACKDATA);
+	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, "RFR-%d Addr[0x%x]= 0x%x\n",
+		 rfpath, phreg->rf_rb, ret);
+	return ret;
+}
+
+static void 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 *phreg = &rtlphy->phyreg_def[rfpath];
+
+	if (RT_CANNOT_IO(hw)) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "stop\n");
+		return;
+	}
+	offset &= 0xff;
+	newoffset = offset;
+	data_and_addr = ((newoffset << 20) | (data & 0x000fffff)) & 0x0fffffff;
+	rtl_set_bbreg(hw, phreg->rf3wire_offset, MASKDWORD, data_and_addr);
+	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, "RFW-%d Addr[0x%x]= 0x%x\n",
+		 rfpath, phreg->rf3wire_offset, data_and_addr);
+}
+
+static u32 cal_bit_shift(u32 bitmask)
+{
+	u32 i;
+
+	for (i = 0; i <= 31; i++) {
+		if (((bitmask >> i) & 0x1) == 1)
+			break;
+	}
+	return i;
+}
+
+static bool config_bb_with_header(struct ieee80211_hw *hw,
+				  u8 configtype)
+{
+	if (configtype == BASEBAND_CONFIG_PHY_REG)
+		set_baseband_phy_config(hw);
+	else if (configtype == BASEBAND_CONFIG_AGC_TAB)
+		set_baseband_agc_config(hw);
+	return true;
+}
+
+static bool config_bb_with_pgheader(struct ieee80211_hw *hw,
+				    u8 configtype)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	int i;
+	u32 *table_pg;
+	u16 tbl_page_len;
+	u32 v1 = 0, v2 = 0;
+
+	tbl_page_len = RTL8188EEPHY_REG_ARRAY_PGLEN;
+	table_pg = RTL8188EEPHY_REG_ARRAY_PG;
+
+	if (configtype == BASEBAND_CONFIG_PHY_REG) {
+		for (i = 0; i < tbl_page_len; i = i + 3) {
+			v1 = table_pg[i];
+			v2 = table_pg[i + 1];
+
+			if (v1 < 0xcdcdcdcd) {
+				if (table_pg[i] == 0xfe)
+					mdelay(50);
+				else if (table_pg[i] == 0xfd)
+					mdelay(5);
+				else if (table_pg[i] == 0xfc)
+					mdelay(1);
+				else if (table_pg[i] == 0xfb)
+					udelay(50);
+				else if (table_pg[i] == 0xfa)
+					udelay(5);
+				else if (table_pg[i] == 0xf9)
+					udelay(1);
+
+				store_pwrindex_offset(hw, table_pg[i],
+						      table_pg[i + 1],
+						      table_pg[i + 2]);
+				continue;
+			} else {
+				if (!check_cond(hw, table_pg[i])) {
+					/*don't need the hw_body*/
+					i += 2; /* skip the pair of expression*/
+					v1 = table_pg[i];
+					v2 = table_pg[i + 1];
+					while (v2 != 0xDEAD) {
+						i += 3;
+						v1 = table_pg[i];
+						v2 = table_pg[i + 1];
+					}
+				}
+			}
+		}
+	} else {
+		RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE,
+			 "configtype != BaseBand_Config_PHY_REG\n");
+	}
+	return true;
+}
+
+static bool config_parafile(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_efuse *fuse = rtl_efuse(rtl_priv(hw));
+	bool rtstatus;
+
+	rtstatus = config_bb_with_header(hw, BASEBAND_CONFIG_PHY_REG);
+	if (rtstatus != true) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Write BB Reg Fail!!");
+		return false;
+	}
+
+	if (fuse->autoload_failflag == false) {
+		rtlphy->pwrgroup_cnt = 0;
+		rtstatus = config_bb_with_pgheader(hw, BASEBAND_CONFIG_PHY_REG);
+	}
+	if (rtstatus != true) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "BB_PG Reg Fail!!");
+		return false;
+	}
+	rtstatus = config_bb_with_header(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;
+}
+
+static void rtl88e_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	int jj = RF90_PATH_A;
+	int kk = RF90_PATH_B;
+
+	rtlphy->phyreg_def[jj].rfintfs = RFPGA0_XAB_RFINTERFACESW;
+	rtlphy->phyreg_def[kk].rfintfs = RFPGA0_XAB_RFINTERFACESW;
+	rtlphy->phyreg_def[RF90_PATH_C].rfintfs = RFPGA0_XCD_RFINTERFACESW;
+	rtlphy->phyreg_def[RF90_PATH_D].rfintfs = RFPGA0_XCD_RFINTERFACESW;
+
+	rtlphy->phyreg_def[jj].rfintfi = RFPGA0_XAB_RFINTERFACERB;
+	rtlphy->phyreg_def[kk].rfintfi = RFPGA0_XAB_RFINTERFACERB;
+	rtlphy->phyreg_def[RF90_PATH_C].rfintfi = RFPGA0_XCD_RFINTERFACERB;
+	rtlphy->phyreg_def[RF90_PATH_D].rfintfi = RFPGA0_XCD_RFINTERFACERB;
+
+	rtlphy->phyreg_def[jj].rfintfo = RFPGA0_XA_RFINTERFACEOE;
+	rtlphy->phyreg_def[kk].rfintfo = RFPGA0_XB_RFINTERFACEOE;
+
+	rtlphy->phyreg_def[jj].rfintfe = RFPGA0_XA_RFINTERFACEOE;
+	rtlphy->phyreg_def[kk].rfintfe = RFPGA0_XB_RFINTERFACEOE;
+
+	rtlphy->phyreg_def[jj].rf3wire_offset = RFPGA0_XA_LSSIPARAMETER;
+	rtlphy->phyreg_def[kk].rf3wire_offset = RFPGA0_XB_LSSIPARAMETER;
+
+	rtlphy->phyreg_def[jj].rflssi_select = rFPGA0_XAB_RFPARAMETER;
+	rtlphy->phyreg_def[kk].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;
+
+	rtlphy->phyreg_def[jj].rftxgain_stage = RFPGA0_TXGAINSTAGE;
+	rtlphy->phyreg_def[kk].rftxgain_stage = RFPGA0_TXGAINSTAGE;
+	rtlphy->phyreg_def[RF90_PATH_C].rftxgain_stage = RFPGA0_TXGAINSTAGE;
+	rtlphy->phyreg_def[RF90_PATH_D].rftxgain_stage = RFPGA0_TXGAINSTAGE;
+
+	rtlphy->phyreg_def[jj].rfhssi_para1 = RFPGA0_XA_HSSIPARAMETER1;
+	rtlphy->phyreg_def[kk].rfhssi_para1 = RFPGA0_XB_HSSIPARAMETER1;
+
+	rtlphy->phyreg_def[jj].rfhssi_para2 = RFPGA0_XA_HSSIPARAMETER2;
+	rtlphy->phyreg_def[kk].rfhssi_para2 = RFPGA0_XB_HSSIPARAMETER2;
+
+	rtlphy->phyreg_def[jj].rfsw_ctrl = RFPGA0_XAB_SWITCHCONTROL;
+	rtlphy->phyreg_def[kk].rfsw_ctrl = RFPGA0_XAB_SWITCHCONTROL;
+	rtlphy->phyreg_def[RF90_PATH_C].rfsw_ctrl = RFPGA0_XCD_SWITCHCONTROL;
+	rtlphy->phyreg_def[RF90_PATH_D].rfsw_ctrl = RFPGA0_XCD_SWITCHCONTROL;
+
+	rtlphy->phyreg_def[jj].rfagc_control1 = ROFDM0_XAAGCCORE1;
+	rtlphy->phyreg_def[kk].rfagc_control1 = ROFDM0_XBAGCCORE1;
+	rtlphy->phyreg_def[RF90_PATH_C].rfagc_control1 = ROFDM0_XCAGCCORE1;
+	rtlphy->phyreg_def[RF90_PATH_D].rfagc_control1 = ROFDM0_XDAGCCORE1;
+
+	rtlphy->phyreg_def[jj].rfagc_control2 = ROFDM0_XAAGCCORE2;
+	rtlphy->phyreg_def[kk].rfagc_control2 = ROFDM0_XBAGCCORE2;
+	rtlphy->phyreg_def[RF90_PATH_C].rfagc_control2 = ROFDM0_XCAGCCORE2;
+	rtlphy->phyreg_def[RF90_PATH_D].rfagc_control2 = ROFDM0_XDAGCCORE2;
+
+	rtlphy->phyreg_def[jj].rfrxiq_imbal = ROFDM0_XARXIQIMBAL;
+	rtlphy->phyreg_def[kk].rfrxiq_imbal = ROFDM0_XBRXIQIMBAL;
+	rtlphy->phyreg_def[RF90_PATH_C].rfrxiq_imbal = ROFDM0_XCRXIQIMBAL;
+	rtlphy->phyreg_def[RF90_PATH_D].rfrxiq_imbal = ROFDM0_XDRXIQIMBAL;
+
+	rtlphy->phyreg_def[jj].rfrx_afe = ROFDM0_XARXAFE;
+	rtlphy->phyreg_def[kk].rfrx_afe = ROFDM0_XBRXAFE;
+	rtlphy->phyreg_def[RF90_PATH_C].rfrx_afe = ROFDM0_XCRXAFE;
+	rtlphy->phyreg_def[RF90_PATH_D].rfrx_afe = ROFDM0_XDRXAFE;
+
+	rtlphy->phyreg_def[jj].rftxiq_imbal = ROFDM0_XATXIQIMBAL;
+	rtlphy->phyreg_def[kk].rftxiq_imbal = ROFDM0_XBTXIQIMBAL;
+	rtlphy->phyreg_def[RF90_PATH_C].rftxiq_imbal = ROFDM0_XCTXIQIMBAL;
+	rtlphy->phyreg_def[RF90_PATH_D].rftxiq_imbal = ROFDM0_XDTXIQIMBAL;
+
+	rtlphy->phyreg_def[jj].rftx_afe = ROFDM0_XATXAFE;
+	rtlphy->phyreg_def[kk].rftx_afe = ROFDM0_XBTXAFE;
+
+	rtlphy->phyreg_def[jj].rf_rb = RFPGA0_XA_LSSIREADBACK;
+	rtlphy->phyreg_def[kk].rf_rb = RFPGA0_XB_LSSIREADBACK;
+
+	rtlphy->phyreg_def[jj].rf_rbpi = TRANSCEIVEA_HSPI_READBACK;
+	rtlphy->phyreg_def[kk].rf_rbpi = TRANSCEIVEB_HSPI_READBACK;
+}
+
+static bool rtl88e_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;
+}
+
+static bool 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;
+	rtl88e_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++,
+					MAX_PRECMD_CNT,
+					CMDID_SET_TXPOWEROWER_LEVEL, 0, 0, 0);
+	rtl88e_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++,
+					MAX_PRECMD_CNT, CMDID_END, 0, 0, 0);
+
+	postcommoncmdcnt = 0;
+
+	rtl88e_phy_set_sw_chnl_cmdarray(postcommoncmd, postcommoncmdcnt++,
+					MAX_POSTCMD_CNT, CMDID_END, 0, 0, 0);
+
+	rfdependcmdcnt = 0;
+
+	RT_ASSERT((channel >= 1 && channel <= 14),
+		  "illegal channel for Zebra: %d\n", channel);
+
+	rtl88e_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++,
+					MAX_RFDEPENDCMD_CNT, CMDID_RF_WRITEREG,
+					RF_CHNLBW, channel, 10);
+
+	rtl88e_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:
+			rtl88e_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] &
+				      0xfffffc00) | currentcmd->para2);
+
+				rtl_set_rfreg(hw, (enum radio_path)rfpath,
+					      currentcmd->para1,
+					      RFREG_OFFSET_MASK,
+					      rtlphy->rfreg_chnlval[rfpath]);
+			}
+			break;
+		default:
+			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+				 "switch case not processed\n");
+			break;
+		}
+
+		break;
+	} while (true);
+
+	(*delay) = currentcmd->msdelay;
+	(*step)++;
+	return false;
+}
+
+static long rtl88e_pwr_idx_dbm(struct ieee80211_hw *hw,
+			       enum wireless_mode wirelessmode,
+			       u8 txpwridx)
+{
+	long offset;
+	long pwrout_dbm;
+
+	switch (wirelessmode) {
+	case WIRELESS_MODE_B:
+		offset = -7;
+		break;
+	case WIRELESS_MODE_G:
+	case WIRELESS_MODE_N_24G:
+		offset = -8;
+		break;
+	default:
+		offset = -8;
+		break;
+	}
+	pwrout_dbm = txpwridx / 2 + offset;
+	return pwrout_dbm;
+}
+
+static void rtl88e_phy_set_io(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
+
+	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:
+		dm_digtable->cur_igvalue = rtlphy->initgain_backup.xaagccore1;
+		/*rtl92c_dm_write_dig(hw);*/
+		rtl88e_phy_set_txpower_level(hw, rtlphy->current_channel);
+		rtl_set_bbreg(hw, RCCK0_CCA, 0xff0000, 0x83);
+		break;
+	case IO_CMD_PAUSE_DM_BY_SCAN:
+		rtlphy->initgain_backup.xaagccore1 = dm_digtable->cur_igvalue;
+		dm_digtable->cur_igvalue = 0x17;
+		rtl_set_bbreg(hw, RCCK0_CCA, 0xff0000, 0x40);
+		break;
+	default:
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 "switch case not processed\n");
+		break;
+	}
+	rtlphy->set_io_inprogress = false;
+	RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE,
+		 "(%#x)\n", rtlphy->current_io_type);
+}
+
+u32 rtl88e_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u32 returnvalue, originalvalue, bitshift;
+
+	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
+		 "regaddr(%#x), bitmask(%#x)\n", regaddr, bitmask);
+	originalvalue = rtl_read_dword(rtlpriv, regaddr);
+	bitshift = cal_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 rtl88e_phy_set_bb_reg(struct ieee80211_hw *hw,
+			   u32 regaddr, u32 bitmask, u32 data)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u32 originalvalue, bitshift;
+
+	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
+		 "regaddr(%#x), bitmask(%#x),data(%#x)\n",
+		 regaddr, bitmask, data);
+
+	if (bitmask != MASKDWORD) {
+		originalvalue = rtl_read_dword(rtlpriv, regaddr);
+		bitshift = cal_bit_shift(bitmask);
+		data = ((originalvalue & (~bitmask)) | (data << bitshift));
+	}
+
+	rtl_write_dword(rtlpriv, regaddr, data);
+
+	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
+		 "regaddr(%#x), bitmask(%#x), data(%#x)\n",
+		 regaddr, bitmask, data);
+}
+
+u32 rtl88e_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 = rf_serial_read(hw, rfpath, regaddr);
+	bitshift = cal_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 rtl88e_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);
+	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);
+
+	if (bitmask != RFREG_OFFSET_MASK) {
+			original_value = rf_serial_read(hw, rfpath, regaddr);
+			bitshift = cal_bit_shift(bitmask);
+			data = ((original_value & (~bitmask)) |
+				(data << bitshift));
+		}
+
+	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);
+}
+
+static bool config_mac_with_header(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 Rtl8188EMACPHY_Array\n");
+	arraylength = RTL8188EEMAC_1T_ARRAYLEN;
+	ptrarray = RTL8188EEMAC_1T_ARRAY;
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+		 "Img:RTL8188EEMAC_1T_ARRAY LEN %d\n", arraylength);
+	for (i = 0; i < arraylength; i = i + 2)
+		rtl_write_byte(rtlpriv, ptrarray[i], (u8) ptrarray[i + 1]);
+	return true;
+}
+
+bool rtl88e_phy_mac_config(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	bool rtstatus = config_mac_with_header(hw);
+
+	rtl_write_byte(rtlpriv, 0x04CA, 0x0B);
+	return rtstatus;
+}
+
+bool rtl88e_phy_bb_config(struct ieee80211_hw *hw)
+{
+	bool rtstatus = true;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u16 regval;
+	u8 reg_hwparafile = 1;
+	u32 tmp;
+	rtl88e_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_RF_CTRL, 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);
+	tmp = rtl_read_dword(rtlpriv, 0x4c);
+	rtl_write_dword(rtlpriv, 0x4c, tmp | BIT(23));
+	if (reg_hwparafile == 1)
+		rtstatus = config_parafile(hw);
+	return rtstatus;
+}
+
+bool rtl88e_phy_rf_config(struct ieee80211_hw *hw)
+{
+	return rtl88e_phy_rf6052_config(hw);
+}
+
+static bool check_cond(struct ieee80211_hw *hw,
+				    const u32  condition)
+{
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	struct rtl_efuse *fuse = rtl_efuse(rtl_priv(hw));
+	u32 _board = fuse->board_type; /*need efuse define*/
+	u32 _interface = rtlhal->interface;
+	u32 _platform = 0x08;/*SupportPlatform */
+	u32 cond = condition;
+
+	if (condition == 0xCDCDCDCD)
+		return true;
+
+	cond = condition & 0xFF;
+	if ((_board & cond) == 0 && cond != 0x1F)
+		return false;
+
+	cond = condition & 0xFF00;
+	cond = cond >> 8;
+	if ((_interface & cond) == 0 && cond != 0x07)
+		return false;
+
+	cond = condition & 0xFF0000;
+	cond = cond >> 16;
+	if ((_platform & cond) == 0 && cond != 0x0F)
+		return false;
+	return true;
+}
+
+static void _rtl8188e_config_rf_reg(struct ieee80211_hw *hw,
+				    u32 addr, u32 data, enum radio_path rfpath,
+				    u32 regaddr)
+{
+	if (addr == 0xffe) {
+		mdelay(50);
+	} else if (addr == 0xfd) {
+		mdelay(5);
+	} else if (addr == 0xfc) {
+		mdelay(1);
+	} else if (addr == 0xfb) {
+		udelay(50);
+	} else if (addr == 0xfa) {
+		udelay(5);
+	} else if (addr == 0xf9) {
+		udelay(1);
+	} else {
+		rtl_set_rfreg(hw, rfpath, regaddr,
+			      RFREG_OFFSET_MASK,
+			      data);
+		udelay(1);
+	}
+}
+
+static void rtl88_config_s(struct ieee80211_hw *hw,
+	u32 addr, u32 data)
+{
+	u32 content = 0x1000; /*RF Content: radio_a_txt*/
+	u32 maskforphyset = (u32)(content & 0xE000);
+
+	_rtl8188e_config_rf_reg(hw, addr, data, RF90_PATH_A,
+				addr | maskforphyset);
+}
+
+static void _rtl8188e_config_bb_reg(struct ieee80211_hw *hw,
+				    u32 addr, u32 data)
+{
+	if (addr == 0xfe) {
+		mdelay(50);
+	} else if (addr == 0xfd) {
+		mdelay(5);
+	} else if (addr == 0xfc) {
+		mdelay(1);
+	} else if (addr == 0xfb) {
+		udelay(50);
+	} else if (addr == 0xfa) {
+		udelay(5);
+	} else if (addr == 0xf9) {
+		udelay(1);
+	} else {
+		rtl_set_bbreg(hw, addr, MASKDWORD, data);
+		udelay(1);
+	}
+}
+
+
+#define NEXT_PAIR(v1, v2, i)				\
+	do {						\
+		i += 2; v1 = array_table[i];		\
+		v2 = array_table[i + 1];		\
+	} while (0)
+
+static void set_baseband_agc_config(struct ieee80211_hw *hw)
+{
+	int i;
+	u32 *array_table;
+	u16 arraylen;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u32 v1 = 0, v2 = 0;
+
+	arraylen = RTL8188EEAGCTAB_1TARRAYLEN;
+	array_table = RTL8188EEAGCTAB_1TARRAY;
+
+	for (i = 0; i < arraylen; i += 2) {
+		v1 = array_table[i];
+		v2 = array_table[i + 1];
+		if (v1 < 0xCDCDCDCD) {
+			rtl_set_bbreg(hw, array_table[i], MASKDWORD,
+				      array_table[i + 1]);
+			udelay(1);
+			continue;
+		} else {/*This line is the start line of branch.*/
+			if (!check_cond(hw, array_table[i])) {
+				/*Discard the following (offset, data) pairs*/
+				NEXT_PAIR(v1, v2, i);
+				while (v2 != 0xDEAD && v2 != 0xCDEF &&
+				       v2 != 0xCDCD && i < arraylen - 2) {
+					NEXT_PAIR(v1, v2, i);
+				}
+				i -= 2; /* compensate for loop's += 2*/
+			} else {
+				/* Configure matched pairs and skip to end */
+				NEXT_PAIR(v1, v2, i);
+				while (v2 != 0xDEAD && v2 != 0xCDEF &&
+				       v2 != 0xCDCD && i < arraylen - 2) {
+					rtl_set_bbreg(hw, array_table[i],
+						      MASKDWORD,
+						      array_table[i + 1]);
+					udelay(1);
+					NEXT_PAIR(v1, v2, i);
+				}
+
+				while (v2 != 0xDEAD && i < arraylen - 2)
+					NEXT_PAIR(v1, v2, i);
+			}
+		}
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 "The agctab_array_table[0] is %x Rtl818EEPHY_REGArray[1] is %x\n",
+			 array_table[i],
+			 array_table[i + 1]);
+	}
+}
+
+static void set_baseband_phy_config(struct ieee80211_hw *hw)
+{
+	int i;
+	u32 *array_table;
+	u16 arraylen;
+	u32 v1 = 0, v2 = 0;
+
+	arraylen = RTL8188EEPHY_REG_1TARRAYLEN;
+	array_table = RTL8188EEPHY_REG_1TARRAY;
+
+	for (i = 0; i < arraylen; i += 2) {
+		v1 = array_table[i];
+		v2 = array_table[i + 1];
+		if (v1 < 0xcdcdcdcd) {
+			_rtl8188e_config_bb_reg(hw, v1, v2);
+		} else {/*This line is the start line of branch.*/
+			if (!check_cond(hw, array_table[i])) {
+				/*Discard the following (offset, data) pairs*/
+				NEXT_PAIR(v1, v2, i);
+				while (v2 != 0xDEAD &&
+				       v2 != 0xCDEF &&
+				       v2 != 0xCDCD && i < arraylen - 2)
+					NEXT_PAIR(v1, v2, i);
+				i -= 2; /* prevent from for-loop += 2*/
+			} else {
+				/* Configure matched pairs and skip to end */
+				NEXT_PAIR(v1, v2, i);
+				while (v2 != 0xDEAD &&
+				       v2 != 0xCDEF &&
+				       v2 != 0xCDCD && i < arraylen - 2) {
+					_rtl8188e_config_bb_reg(hw, v1, v2);
+					NEXT_PAIR(v1, v2, i);
+				}
+
+				while (v2 != 0xDEAD && i < arraylen - 2)
+					NEXT_PAIR(v1, v2, i);
+			}
+		}
+	}
+}
+
+static void store_pwrindex_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_offset[rtlphy->pwrgroup_cnt][0] = data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 "MCSTxPowerLevelOriginalOffset[%d][0] = 0x%x\n",
+			 rtlphy->pwrgroup_cnt,
+			 rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][0]);
+	}
+	if (regaddr == RTXAGC_A_RATE54_24) {
+		rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][1] = data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 "MCSTxPowerLevelOriginalOffset[%d][1] = 0x%x\n",
+			 rtlphy->pwrgroup_cnt,
+			 rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][1]);
+	}
+	if (regaddr == RTXAGC_A_CCK1_MCS32) {
+		rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][6] = data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 "MCSTxPowerLevelOriginalOffset[%d][6] = 0x%x\n",
+			 rtlphy->pwrgroup_cnt,
+			 rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][6]);
+	}
+	if (regaddr == RTXAGC_B_CCK11_A_CCK2_11 && bitmask == 0xffffff00) {
+		rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][7] = data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 "MCSTxPowerLevelOriginalOffset[%d][7] = 0x%x\n",
+			 rtlphy->pwrgroup_cnt,
+			 rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][7]);
+	}
+	if (regaddr == RTXAGC_A_MCS03_MCS00) {
+		rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][2] = data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 "MCSTxPowerLevelOriginalOffset[%d][2] = 0x%x\n",
+			 rtlphy->pwrgroup_cnt,
+			 rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][2]);
+	}
+	if (regaddr == RTXAGC_A_MCS07_MCS04) {
+		rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][3] = data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 "MCSTxPowerLevelOriginalOffset[%d][3] = 0x%x\n",
+			 rtlphy->pwrgroup_cnt,
+			 rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][3]);
+	}
+	if (regaddr == RTXAGC_A_MCS11_MCS08) {
+		rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][4] = data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 "MCSTxPowerLevelOriginalOffset[%d][4] = 0x%x\n",
+			 rtlphy->pwrgroup_cnt,
+			 rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][4]);
+	}
+	if (regaddr == RTXAGC_A_MCS15_MCS12) {
+		rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][5] = data;
+		if (get_rf_type(rtlphy) == RF_1T1R)
+			rtlphy->pwrgroup_cnt++;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 "MCSTxPowerLevelOriginalOffset[%d][5] = 0x%x\n",
+			 rtlphy->pwrgroup_cnt,
+			 rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][5]);
+	}
+	if (regaddr == RTXAGC_B_RATE18_06) {
+		rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][8] = data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 "MCSTxPowerLevelOriginalOffset[%d][8] = 0x%x\n",
+			 rtlphy->pwrgroup_cnt,
+			 rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][8]);
+	}
+	if (regaddr == RTXAGC_B_RATE54_24) {
+		rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][9] = data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 "MCSTxPowerLevelOriginalOffset[%d][9] = 0x%x\n",
+			 rtlphy->pwrgroup_cnt,
+			 rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][9]);
+	}
+	if (regaddr == RTXAGC_B_CCK1_55_MCS32) {
+		rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][14] = data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 "MCSTxPowerLevelOriginalOffset[%d][14] = 0x%x\n",
+			 rtlphy->pwrgroup_cnt,
+			 rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][14]);
+	}
+	if (regaddr == RTXAGC_B_CCK11_A_CCK2_11 && bitmask == 0x000000ff) {
+		rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][15] = data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 "MCSTxPowerLevelOriginalOffset[%d][15] = 0x%x\n",
+			 rtlphy->pwrgroup_cnt,
+			 rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][15]);
+	}
+	if (regaddr == RTXAGC_B_MCS03_MCS00) {
+		rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][10] = data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 "MCSTxPowerLevelOriginalOffset[%d][10] = 0x%x\n",
+			 rtlphy->pwrgroup_cnt,
+			 rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][10]);
+	}
+	if (regaddr == RTXAGC_B_MCS07_MCS04) {
+		rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][11] = data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 "MCSTxPowerLevelOriginalOffset[%d][11] = 0x%x\n",
+			 rtlphy->pwrgroup_cnt,
+			 rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][11]);
+	}
+	if (regaddr == RTXAGC_B_MCS11_MCS08) {
+		rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][12] = data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 "MCSTxPowerLevelOriginalOffset[%d][12] = 0x%x\n",
+			 rtlphy->pwrgroup_cnt,
+			 rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][12]);
+	}
+	if (regaddr == RTXAGC_B_MCS15_MCS12) {
+		rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][13] = data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 "MCSTxPowerLevelOriginalOffset[%d][13] = 0x%x\n",
+			 rtlphy->pwrgroup_cnt,
+			 rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][13]);
+		if (get_rf_type(rtlphy) != RF_1T1R)
+			rtlphy->pwrgroup_cnt++;
+	}
+}
+
+#define READ_NEXT_RF_PAIR(v1, v2, i)		\
+	do {					\
+		i += 2; v1 = a_table[i];	\
+		v2 = a_table[i + 1];		\
+	} while (0)
+
+bool rtl88e_phy_config_rf_with_headerfile(struct ieee80211_hw *hw,
+					  enum radio_path rfpath)
+{
+	int i;
+	u32 *a_table;
+	u16 a_len;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	u32 v1 = 0, v2 = 0;
+
+	a_len = RTL8188EE_RADIOA_1TARRAYLEN;
+	a_table = RTL8188EE_RADIOA_1TARRAY;
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+		 "Radio_A:RTL8188EE_RADIOA_1TARRAY %d\n", a_len);
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Radio No %x\n", rfpath);
+	switch (rfpath) {
+	case RF90_PATH_A:
+		for (i = 0; i < a_len; i = i + 2) {
+			v1 = a_table[i];
+			v2 = a_table[i + 1];
+			if (v1 < 0xcdcdcdcd) {
+				rtl88_config_s(hw, v1, v2);
+			} else {/*This line is the start line of branch.*/
+				if (!check_cond(hw, a_table[i])) {
+					/* Discard the following (offset, data)
+					 * pairs
+					 */
+					READ_NEXT_RF_PAIR(v1, v2, i);
+					while (v2 != 0xDEAD && v2 != 0xCDEF &&
+					       v2 != 0xCDCD && i < a_len - 2)
+						READ_NEXT_RF_PAIR(v1, v2, i);
+					i -= 2; /* prevent from for-loop += 2*/
+				} else {
+					/* Configure matched pairs and skip to
+					 * end of if-else.
+					 */
+					READ_NEXT_RF_PAIR(v1, v2, i);
+					while (v2 != 0xDEAD && v2 != 0xCDEF &&
+					       v2 != 0xCDCD && i < a_len - 2) {
+						rtl88_config_s(hw, v1, v2);
+						READ_NEXT_RF_PAIR(v1, v2, i);
+					}
+
+					while (v2 != 0xDEAD && i < a_len - 2)
+						READ_NEXT_RF_PAIR(v1, v2, i);
+				}
+			}
+		}
+
+		if (rtlhal->oem_id == RT_CID_819x_HP)
+			rtl88_config_s(hw, 0x52, 0x7E4BD);
+
+		break;
+
+	case RF90_PATH_B:
+	case RF90_PATH_C:
+	case RF90_PATH_D:
+	default:
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 "switch case not processed\n");
+		break;
+	}
+	return true;
+}
+
+void rtl88e_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] = rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1,
+						       MASKBYTE0);
+	rtlphy->default_initialgain[1] = rtl_get_bbreg(hw, ROFDM0_XBAGCCORE1,
+						       MASKBYTE0);
+	rtlphy->default_initialgain[2] = rtl_get_bbreg(hw, ROFDM0_XCAGCCORE1,
+						       MASKBYTE0);
+	rtlphy->default_initialgain[3] = rtl_get_bbreg(hw, ROFDM0_XDAGCCORE1,
+						       MASKBYTE0);
+
+	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 = rtl_get_bbreg(hw, ROFDM0_RXDETECTOR3,
+					  MASKBYTE0);
+	rtlphy->framesync_c34 = rtl_get_bbreg(hw, ROFDM0_RXDETECTOR2,
+					      MASKDWORD);
+
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+		 "Default framesync (0x%x) = 0x%x\n",
+		 ROFDM0_RXDETECTOR3, rtlphy->framesync);
+}
+
+void rtl88e_phy_get_txpower_level(struct ieee80211_hw *hw, long *powerlevel)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	u8 level;
+	long dbm;
+
+	level = rtlphy->cur_cck_txpwridx;
+	dbm = rtl88e_pwr_idx_dbm(hw, WIRELESS_MODE_B, level);
+	level = rtlphy->cur_ofdm24g_txpwridx;
+	if (rtl88e_pwr_idx_dbm(hw, WIRELESS_MODE_G, level) > dbm)
+		dbm = rtl88e_pwr_idx_dbm(hw, WIRELESS_MODE_G, level);
+	level = rtlphy->cur_ofdm24g_txpwridx;
+	if (rtl88e_pwr_idx_dbm(hw, WIRELESS_MODE_N_24G, level) > dbm)
+		dbm = rtl88e_pwr_idx_dbm(hw, WIRELESS_MODE_N_24G, level);
+	*powerlevel = dbm;
+}
+
+static void _rtl88e_get_txpower_index(struct ieee80211_hw *hw, u8 channel,
+				      u8 *cckpower, u8 *ofdm, u8 *bw20_pwr,
+				      u8 *bw40_pwr)
+{
+	struct rtl_efuse *fuse = rtl_efuse(rtl_priv(hw));
+	u8 i = (channel - 1);
+	u8 rf_path = 0;
+	int jj = RF90_PATH_A;
+	int kk = RF90_PATH_B;
+
+	for (rf_path = 0; rf_path < 2; rf_path++) {
+		if (rf_path == jj) {
+			cckpower[jj] = fuse->txpwrlevel_cck[jj][i];
+			if (fuse->txpwr_ht20diff[jj][i] > 0x0f) /*-8~7 */
+				bw20_pwr[jj] = fuse->txpwrlevel_ht40_1s[jj][i] -
+					(~(fuse->txpwr_ht20diff[jj][i]) + 1);
+			else
+				bw20_pwr[jj] = fuse->txpwrlevel_ht40_1s[jj][i] +
+					 fuse->txpwr_ht20diff[jj][i];
+			if (fuse->txpwr_legacyhtdiff[jj][i] > 0xf)
+				ofdm[jj] = fuse->txpwrlevel_ht40_1s[jj][i] -
+					(~(fuse->txpwr_legacyhtdiff[jj][i])+1);
+			else
+				ofdm[jj] = fuse->txpwrlevel_ht40_1s[jj][i] +
+					   fuse->txpwr_legacyhtdiff[jj][i];
+			bw40_pwr[jj] = fuse->txpwrlevel_ht40_1s[jj][i];
+
+		} else if (rf_path == kk) {
+			cckpower[kk] = fuse->txpwrlevel_cck[kk][i];
+			bw20_pwr[kk] = fuse->txpwrlevel_ht40_1s[kk][i] +
+				       fuse->txpwr_ht20diff[kk][i];
+			ofdm[kk] = fuse->txpwrlevel_ht40_1s[kk][i] +
+					fuse->txpwr_legacyhtdiff[kk][i];
+			bw40_pwr[kk] = fuse->txpwrlevel_ht40_1s[kk][i];
+		}
+	}
+}
+
+static void _rtl88e_ccxpower_index_check(struct ieee80211_hw *hw,
+					 u8 channel, u8 *cckpower,
+					 u8 *ofdm, u8 *bw20_pwr,
+					 u8 *bw40_pwr)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+
+	rtlphy->cur_cck_txpwridx = cckpower[0];
+	rtlphy->cur_ofdm24g_txpwridx = ofdm[0];
+	rtlphy->cur_bw20_txpwridx = bw20_pwr[0];
+	rtlphy->cur_bw40_txpwridx = bw40_pwr[0];
+}
+
+void rtl88e_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel)
+{
+	struct rtl_efuse *fuse = rtl_efuse(rtl_priv(hw));
+	u8 cckpower[MAX_TX_COUNT]  = {0}, ofdm[MAX_TX_COUNT] = {0};
+	u8 bw20_pwr[MAX_TX_COUNT] = {0}, bw40_pwr[MAX_TX_COUNT] = {0};
+
+	if (fuse->txpwr_fromeprom == false)
+		return;
+	_rtl88e_get_txpower_index(hw, channel, &cckpower[0], &ofdm[0],
+				  &bw20_pwr[0], &bw40_pwr[0]);
+	_rtl88e_ccxpower_index_check(hw, channel, &cckpower[0], &ofdm[0],
+				     &bw20_pwr[0], &bw40_pwr[0]);
+	rtl88e_phy_rf6052_set_cck_txpower(hw, &cckpower[0]);
+	rtl88e_phy_rf6052_set_ofdm_txpower(hw, &ofdm[0], &bw20_pwr[0],
+					   &bw40_pwr[0], channel);
+}
+
+void rtl88e_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:
+			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 rtl88e_phy_set_bw_mode_callback(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_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 ?
+		 "20MHz" : "40MHz");
+
+	if (is_hal_stop(rtlhal)) {
+		rtlphy->set_bwmode_inprogress = false;
+		return;
+	}
+
+	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);
+	/*	rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 1);*/
+		break;
+	case HT_CHANNEL_WIDTH_20_40:
+		rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x1);
+		rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x1);
+
+		rtl_set_bbreg(hw, RCCK0_SYSTEM, BCCK_SIDEBAND,
+			      (mac->cur_40_prime_sc >> 1));
+		rtl_set_bbreg(hw, ROFDM1_LSTF, 0xC00, mac->cur_40_prime_sc);
+		/*rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 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;
+	}
+	rtl88e_phy_rf6052_set_bandwidth(hw, rtlphy->current_chan_bw);
+	rtlphy->set_bwmode_inprogress = false;
+	RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD, "\n");
+}
+
+void rtl88e_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));
+	u8 tmp_bw = rtlphy->current_chan_bw;
+
+	if (rtlphy->set_bwmode_inprogress)
+		return;
+	rtlphy->set_bwmode_inprogress = true;
+	if ((!is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) {
+		rtl88e_phy_set_bw_mode_callback(hw);
+	} else {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+			 "FALSE driver sleep or unload\n");
+		rtlphy->set_bwmode_inprogress = false;
+		rtlphy->current_chan_bw = tmp_bw;
+	}
+}
+
+void rtl88e_phy_sw_chnl_callback(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);
+	u32 delay;
+
+	RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE,
+		 "switch to channel%d\n", rtlphy->current_channel);
+	if (is_hal_stop(rtlhal))
+		return;
+	do {
+		if (!rtlphy->sw_chnl_inprogress)
+			break;
+		if (!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");
+}
+
+u8 rtl88e_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));
+
+	if (rtlphy->sw_chnl_inprogress)
+		return 0;
+	if (rtlphy->set_bwmode_inprogress)
+		return 0;
+	RT_ASSERT((rtlphy->current_channel <= 14),
+		  "WIRELESS_MODE_G but channel>14");
+	rtlphy->sw_chnl_inprogress = true;
+	rtlphy->sw_chnl_stage = 0;
+	rtlphy->sw_chnl_step = 0;
+	if (!(is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) {
+		rtl88e_phy_sw_chnl_callback(hw);
+		RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD,
+			 "sw_chnl_inprogress false schdule workitem current channel %d\n",
+			 rtlphy->current_channel);
+		rtlphy->sw_chnl_inprogress = false;
+	} else {
+		RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD,
+			 "sw_chnl_inprogress false driver sleep or unload\n");
+		rtlphy->sw_chnl_inprogress = false;
+	}
+	return 1;
+}
+
+static u8 _rtl88e_phy_path_a_iqk(struct ieee80211_hw *hw, bool config_pathb)
+{
+	u32 reg_eac, reg_e94, reg_e9c;
+	u8 result = 0x00;
+
+	rtl_set_bbreg(hw, 0xe30, MASKDWORD, 0x10008c1c);
+	rtl_set_bbreg(hw, 0xe34, MASKDWORD, 0x30008c1c);
+	rtl_set_bbreg(hw, 0xe38, MASKDWORD, 0x8214032a);
+	rtl_set_bbreg(hw, 0xe3c, MASKDWORD, 0x28160000);
+
+	rtl_set_bbreg(hw, 0xe4c, MASKDWORD, 0x00462911);
+	rtl_set_bbreg(hw, 0xe48, MASKDWORD, 0xf9000000);
+	rtl_set_bbreg(hw, 0xe48, MASKDWORD, 0xf8000000);
+
+	mdelay(IQK_DELAY_TIME);
+
+	reg_eac = rtl_get_bbreg(hw, 0xeac, MASKDWORD);
+	reg_e94 = rtl_get_bbreg(hw, 0xe94, MASKDWORD);
+	reg_e9c = rtl_get_bbreg(hw, 0xe9c, MASKDWORD);
+
+	if (!(reg_eac & BIT(28)) &&
+	    (((reg_e94 & 0x03FF0000) >> 16) != 0x142) &&
+	    (((reg_e9c & 0x03FF0000) >> 16) != 0x42))
+		result |= 0x01;
+	return result;
+}
+
+static u8 _rtl88e_phy_path_b_iqk(struct ieee80211_hw *hw)
+{
+	u32 reg_eac, reg_eb4, reg_ebc, reg_ec4, reg_ecc;
+	u8 result = 0x00;
+
+	rtl_set_bbreg(hw, 0xe60, MASKDWORD, 0x00000002);
+	rtl_set_bbreg(hw, 0xe60, MASKDWORD, 0x00000000);
+	mdelay(IQK_DELAY_TIME);
+	reg_eac = rtl_get_bbreg(hw, 0xeac, MASKDWORD);
+	reg_eb4 = rtl_get_bbreg(hw, 0xeb4, MASKDWORD);
+	reg_ebc = rtl_get_bbreg(hw, 0xebc, MASKDWORD);
+	reg_ec4 = rtl_get_bbreg(hw, 0xec4, MASKDWORD);
+	reg_ecc = rtl_get_bbreg(hw, 0xecc, MASKDWORD);
+
+	if (!(reg_eac & BIT(31)) &&
+	    (((reg_eb4 & 0x03FF0000) >> 16) != 0x142) &&
+	    (((reg_ebc & 0x03FF0000) >> 16) != 0x42))
+		result |= 0x01;
+	else
+		return result;
+	if (!(reg_eac & BIT(30)) &&
+	    (((reg_ec4 & 0x03FF0000) >> 16) != 0x132) &&
+	    (((reg_ecc & 0x03FF0000) >> 16) != 0x36))
+		result |= 0x02;
+	return result;
+}
+
+static u8 _rtl88e_phy_path_a_rx_iqk(struct ieee80211_hw *hw, bool config_pathb)
+{
+	u32 reg_eac, reg_e94, reg_e9c, reg_ea4, u32temp;
+	u8 result = 0x00;
+	int jj = RF90_PATH_A;
+
+	/*Get TXIMR Setting*/
+	/*Modify RX IQK mode table*/
+	rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000);
+	rtl_set_rfreg(hw, jj, RF_WE_LUT, RFREG_OFFSET_MASK, 0x800a0);
+	rtl_set_rfreg(hw, jj, RF_RCK_OS, RFREG_OFFSET_MASK, 0x30000);
+	rtl_set_rfreg(hw, jj, RF_TXPA_G1, RFREG_OFFSET_MASK, 0x0000f);
+	rtl_set_rfreg(hw, jj, RF_TXPA_G2, RFREG_OFFSET_MASK, 0xf117b);
+	rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x80800000);
+
+	/*IQK Setting*/
+	rtl_set_bbreg(hw, RTX_IQK, MASKDWORD, 0x01007c00);
+	rtl_set_bbreg(hw, RRX_IQK, MASKDWORD, 0x81004800);
+
+	/*path a IQK setting*/
+	rtl_set_bbreg(hw, RTX_IQK_TONE_A, MASKDWORD, 0x10008c1c);
+	rtl_set_bbreg(hw, RRX_IQK_TONE_A, MASKDWORD, 0x30008c1c);
+	rtl_set_bbreg(hw, RTX_IQK_PI_A, MASKDWORD, 0x82160804);
+	rtl_set_bbreg(hw, RRX_IQK_PI_A, MASKDWORD, 0x28160000);
+
+	/*LO calibration Setting*/
+	rtl_set_bbreg(hw, RIQK_AGC_RSP, MASKDWORD, 0x0046a911);
+	/*one shot, path A LOK & iqk*/
+	rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf9000000);
+	rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf8000000);
+
+	mdelay(IQK_DELAY_TIME);
+
+	reg_eac = rtl_get_bbreg(hw, RRX_POWER_AFTER_IQK_A_2, MASKDWORD);
+	reg_e94 = rtl_get_bbreg(hw, RTX_POWER_BEFORE_IQK_A, MASKDWORD);
+	reg_e9c = rtl_get_bbreg(hw, RTX_POWER_AFTER_IQK_A, MASKDWORD);
+
+
+	if (!(reg_eac & BIT(28)) &&
+	    (((reg_e94 & 0x03FF0000) >> 16) != 0x142) &&
+	    (((reg_e9c & 0x03FF0000) >> 16) != 0x42))
+		result |= 0x01;
+	else
+		return result;
+
+	u32temp = 0x80007C00 | (reg_e94&0x3FF0000)  |
+		  ((reg_e9c&0x3FF0000) >> 16);
+	rtl_set_bbreg(hw, RTX_IQK, MASKDWORD, u32temp);
+	/*RX IQK*/
+	/*Modify RX IQK mode table*/
+	rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000);
+	rtl_set_rfreg(hw, jj, RF_WE_LUT, RFREG_OFFSET_MASK, 0x800a0);
+	rtl_set_rfreg(hw, jj, RF_RCK_OS, RFREG_OFFSET_MASK, 0x30000);
+	rtl_set_rfreg(hw, jj, RF_TXPA_G1, RFREG_OFFSET_MASK, 0x0000f);
+	rtl_set_rfreg(hw, jj, RF_TXPA_G2, RFREG_OFFSET_MASK, 0xf7ffa);
+	rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x80800000);
+
+	/*IQK Setting*/
+	rtl_set_bbreg(hw, RRX_IQK, MASKDWORD, 0x01004800);
+
+	/*path a IQK setting*/
+	rtl_set_bbreg(hw, RTX_IQK_TONE_A, MASKDWORD, 0x30008c1c);
+	rtl_set_bbreg(hw, RRX_IQK_TONE_A, MASKDWORD, 0x10008c1c);
+	rtl_set_bbreg(hw, RTX_IQK_PI_A, MASKDWORD, 0x82160c05);
+	rtl_set_bbreg(hw, RRX_IQK_PI_A, MASKDWORD, 0x28160c05);
+
+	/*LO calibration Setting*/
+	rtl_set_bbreg(hw, RIQK_AGC_RSP, MASKDWORD, 0x0046a911);
+	/*one shot, path A LOK & iqk*/
+	rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf9000000);
+	rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf8000000);
+
+	mdelay(IQK_DELAY_TIME);
+
+	reg_eac = rtl_get_bbreg(hw, RRX_POWER_AFTER_IQK_A_2, MASKDWORD);
+	reg_e94 = rtl_get_bbreg(hw, RTX_POWER_BEFORE_IQK_A, MASKDWORD);
+	reg_e9c = rtl_get_bbreg(hw, RTX_POWER_AFTER_IQK_A, MASKDWORD);
+	reg_ea4 = rtl_get_bbreg(hw, RRX_POWER_BEFORE_IQK_A_2, MASKDWORD);
+
+	if (!(reg_eac & BIT(27)) &&
+	    (((reg_ea4 & 0x03FF0000) >> 16) != 0x132) &&
+	    (((reg_eac & 0x03FF0000) >> 16) != 0x36))
+		result |= 0x02;
+	return result;
+}
+
+static void fill_iqk(struct ieee80211_hw *hw, bool iqk_ok, long result[][8],
+		     u8 final, bool btxonly)
+{
+	u32 oldval_0, x, tx0_a, reg;
+	long y, tx0_c;
+
+	if (final == 0xFF) {
+		return;
+	} else if (iqk_ok) {
+		oldval_0 = (rtl_get_bbreg(hw, ROFDM0_XATXIQIMBAL,
+					  MASKDWORD) >> 22) & 0x3FF;
+		x = result[final][0];
+		if ((x & 0x00000200) != 0)
+			x = x | 0xFFFFFC00;
+		tx0_a = (x * oldval_0) >> 8;
+		rtl_set_bbreg(hw, ROFDM0_XATXIQIMBAL, 0x3FF, tx0_a);
+		rtl_set_bbreg(hw, ROFDM0_ECCATHRES, BIT(31),
+			      ((x * oldval_0 >> 7) & 0x1));
+		y = result[final][1];
+		if ((y & 0x00000200) != 0)
+			y |= 0xFFFFFC00;
+		tx0_c = (y * oldval_0) >> 8;
+		rtl_set_bbreg(hw, ROFDM0_XCTXAFE, 0xF0000000,
+			      ((tx0_c & 0x3C0) >> 6));
+		rtl_set_bbreg(hw, ROFDM0_XATXIQIMBAL, 0x003F0000,
+			      (tx0_c & 0x3F));
+		rtl_set_bbreg(hw, ROFDM0_ECCATHRES, BIT(29),
+			      ((y * oldval_0 >> 7) & 0x1));
+		if (btxonly)
+			return;
+		reg = result[final][2];
+		rtl_set_bbreg(hw, ROFDM0_XARXIQIMBAL, 0x3FF, reg);
+		reg = result[final][3] & 0x3F;
+		rtl_set_bbreg(hw, ROFDM0_XARXIQIMBAL, 0xFC00, reg);
+		reg = (result[final][3] >> 6) & 0xF;
+		rtl_set_bbreg(hw, 0xca0, 0xF0000000, reg);
+	}
+}
+
+static void save_adda_reg(struct ieee80211_hw *hw,
+			  const u32 *addareg, u32 *backup,
+			  u32 registernum)
+{
+	u32 i;
+
+	for (i = 0; i < registernum; i++)
+		backup[i] = rtl_get_bbreg(hw, addareg[i], MASKDWORD);
+}
+
+static void save_mac_reg(struct ieee80211_hw *hw, const u32 *macreg,
+			 u32 *macbackup)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u32 i;
+
+	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 reload_adda(struct ieee80211_hw *hw, const u32 *addareg,
+		        u32 *backup, u32 reg_num)
+{
+	u32 i;
+
+	for (i = 0; i < reg_num; i++)
+		rtl_set_bbreg(hw, addareg[i], MASKDWORD, backup[i]);
+}
+
+static void reload_mac(struct ieee80211_hw *hw, const u32 *macreg,
+		       u32 *macbackup)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u32 i;
+
+	for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++)
+		rtl_write_byte(rtlpriv, macreg[i], (u8) macbackup[i]);
+	rtl_write_dword(rtlpriv, macreg[i], macbackup[i]);
+}
+
+static void _rtl88e_phy_path_adda_on(struct ieee80211_hw *hw,
+				     const u32 *addareg, bool is_patha_on,
+				     bool is2t)
+{
+	u32 pathon;
+	u32 i;
+
+	pathon = is_patha_on ? 0x04db25a4 : 0x0b1b25a4;
+	if (false == is2t) {
+		pathon = 0x0bdb25a0;
+		rtl_set_bbreg(hw, addareg[0], MASKDWORD, 0x0b1b25a0);
+	} else {
+		rtl_set_bbreg(hw, addareg[0], MASKDWORD, pathon);
+	}
+
+	for (i = 1; i < IQK_ADDA_REG_NUM; i++)
+		rtl_set_bbreg(hw, addareg[i], MASKDWORD, pathon);
+}
+
+static void _rtl88e_phy_mac_setting_calibration(struct ieee80211_hw *hw,
+						const u32 *macreg,
+						u32 *macbackup)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u32 i = 0;
+
+	rtl_write_byte(rtlpriv, macreg[i], 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 _rtl88e_phy_path_a_standby(struct ieee80211_hw *hw)
+{
+	rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x0);
+	rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00010000);
+	rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x80800000);
+}
+
+static void _rtl88e_phy_pi_mode_switch(struct ieee80211_hw *hw, bool pi_mode)
+{
+	u32 mode;
+
+	mode = pi_mode ? 0x01000100 : 0x01000000;
+	rtl_set_bbreg(hw, 0x820, MASKDWORD, mode);
+	rtl_set_bbreg(hw, 0x828, MASKDWORD, mode);
+}
+
+static bool sim_comp(struct ieee80211_hw *hw, long result[][8], u8 c1, u8 c2)
+{
+	u32 i, j, diff, bitmap, bound;
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+
+	u8 final[2] = {0xFF, 0xFF};
+	bool bresult = true, is2t = IS_92C_SERIAL(rtlhal->version);
+
+	if (is2t)
+		bound = 8;
+	else
+		bound = 4;
+
+	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) {
+			if ((i == 2 || i == 6) && !bitmap) {
+				if (result[c1][i] + result[c1][i + 1] == 0)
+					final[(i / 4)] = c2;
+				else if (result[c2][i] + result[c2][i + 1] == 0)
+					final[(i / 4)] = c1;
+				else
+					bitmap = bitmap | (1 << i);
+			} else {
+				bitmap = bitmap | (1 << i);
+			}
+		}
+	}
+
+	if (bitmap == 0) {
+		for (i = 0; i < (bound / 4); i++) {
+			if (final[i] != 0xFF) {
+				for (j = i * 4; j < (i + 1) * 4 - 2; j++)
+					result[3][j] = result[final[i]][j];
+				bresult = false;
+			}
+		}
+		return bresult;
+	} else if (!(bitmap & 0x0F)) {
+		for (i = 0; i < 4; i++)
+			result[3][i] = result[c1][i];
+		return false;
+	} else if (!(bitmap & 0xF0) && is2t) {
+		for (i = 4; i < 8; i++)
+			result[3][i] = result[c1][i];
+		return false;
+	} else {
+		return false;
+	}
+}
+
+static void _rtl88e_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;
+	const u32 adda_reg[IQK_ADDA_REG_NUM] = {
+		0x85c, 0xe6c, 0xe70, 0xe74,
+		0xe78, 0xe7c, 0xe80, 0xe84,
+		0xe88, 0xe8c, 0xed0, 0xed4,
+		0xed8, 0xedc, 0xee0, 0xeec
+	};
+	const u32 iqk_mac_reg[IQK_MAC_REG_NUM] = {
+		0x522, 0x550, 0x551, 0x040
+	};
+	const u32 iqk_bb_reg[IQK_BB_REG_NUM] = {
+		ROFDM0_TRXPATHENABLE, ROFDM0_TRMUXPAR, RFPGA0_XCD_RFINTERFACESW,
+		0xb68, 0xb6c, 0x870, 0x860, 0x864, 0x800
+	};
+	const u32 retrycount = 2;
+
+	if (t == 0) {
+		save_adda_reg(hw, adda_reg, rtlphy->adda_backup, 16);
+		save_mac_reg(hw, iqk_mac_reg, rtlphy->iqk_mac_backup);
+		save_adda_reg(hw, iqk_bb_reg, rtlphy->iqk_bb_backup,
+			      IQK_BB_REG_NUM);
+	}
+	_rtl88e_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));
+	}
+
+	if (!rtlphy->rfpi_enable)
+		_rtl88e_phy_pi_mode_switch(hw, true);
+	/*BB Setting*/
+	rtl_set_bbreg(hw, 0x800, BIT(24), 0x00);
+	rtl_set_bbreg(hw, 0xc04, MASKDWORD, 0x03a05600);
+	rtl_set_bbreg(hw, 0xc08, MASKDWORD, 0x000800e4);
+	rtl_set_bbreg(hw, 0x874, MASKDWORD, 0x22204000);
+
+	rtl_set_bbreg(hw, 0x870, BIT(10), 0x01);
+	rtl_set_bbreg(hw, 0x870, BIT(26), 0x01);
+	rtl_set_bbreg(hw, 0x860, BIT(10), 0x00);
+	rtl_set_bbreg(hw, 0x864, BIT(10), 0x00);
+
+	if (is2t) {
+		rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00010000);
+		rtl_set_bbreg(hw, 0x844, MASKDWORD, 0x00010000);
+	}
+	_rtl88e_phy_mac_setting_calibration(hw, iqk_mac_reg,
+					    rtlphy->iqk_mac_backup);
+	rtl_set_bbreg(hw, 0xb68, MASKDWORD, 0x0f600000);
+	if (is2t)
+		rtl_set_bbreg(hw, 0xb6c, MASKDWORD, 0x0f600000);
+
+	rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x80800000);
+	rtl_set_bbreg(hw, 0xe40, MASKDWORD, 0x01007c00);
+	rtl_set_bbreg(hw, 0xe44, MASKDWORD, 0x81004800);
+	for (i = 0; i < retrycount; i++) {
+		patha_ok = _rtl88e_phy_path_a_iqk(hw, is2t);
+		if (patha_ok == 0x01) {
+			RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+				 "Path A Tx IQK Success!!\n");
+			result[t][0] = (rtl_get_bbreg(hw, 0xe94, MASKDWORD) &
+					0x3FF0000) >> 16;
+			result[t][1] = (rtl_get_bbreg(hw, 0xe9c, MASKDWORD) &
+					0x3FF0000) >> 16;
+			break;
+		}
+	}
+
+	for (i = 0; i < retrycount; i++) {
+		patha_ok = _rtl88e_phy_path_a_rx_iqk(hw, is2t);
+		if (patha_ok == 0x03) {
+			RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+				 "Path A Rx IQK Success!!\n");
+			result[t][2] = (rtl_get_bbreg(hw, 0xea4, MASKDWORD) &
+					0x3FF0000) >> 16;
+			result[t][3] = (rtl_get_bbreg(hw, 0xeac, MASKDWORD) &
+					0x3FF0000) >> 16;
+			break;
+		} else {
+			RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+				 "Path a RX iqk fail!!!\n");
+		}
+	}
+
+	if (0 == patha_ok) {
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+			 "Path A IQK Success!!\n");
+	}
+	if (is2t) {
+		_rtl88e_phy_path_a_standby(hw);
+		_rtl88e_phy_path_adda_on(hw, adda_reg, false, is2t);
+		for (i = 0; i < retrycount; i++) {
+			pathb_ok = _rtl88e_phy_path_b_iqk(hw);
+			if (pathb_ok == 0x03) {
+				result[t][4] = (rtl_get_bbreg(hw,
+						0xeb4, MASKDWORD) &
+						0x3FF0000) >> 16;
+				result[t][5] =
+				    (rtl_get_bbreg(hw, 0xebc, MASKDWORD) &
+						   0x3FF0000) >> 16;
+				result[t][6] =
+				    (rtl_get_bbreg(hw, 0xec4, MASKDWORD) &
+						   0x3FF0000) >> 16;
+				result[t][7] =
+				    (rtl_get_bbreg(hw, 0xecc, MASKDWORD) &
+						   0x3FF0000) >> 16;
+				break;
+			} else if (i == (retrycount - 1) && pathb_ok == 0x01) {
+				result[t][4] = (rtl_get_bbreg(hw,
+						0xeb4, MASKDWORD) &
+						0x3FF0000) >> 16;
+			}
+			result[t][5] = (rtl_get_bbreg(hw, 0xebc, MASKDWORD) &
+					0x3FF0000) >> 16;
+		}
+	}
+
+	rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0);
+
+	if (t != 0) {
+		if (!rtlphy->rfpi_enable)
+			_rtl88e_phy_pi_mode_switch(hw, false);
+		reload_adda(hw, adda_reg, rtlphy->adda_backup, 16);
+		reload_mac(hw, iqk_mac_reg, rtlphy->iqk_mac_backup);
+		reload_adda(hw, iqk_bb_reg, rtlphy->iqk_bb_backup,
+			    IQK_BB_REG_NUM);
+
+		rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00032ed3);
+		if (is2t)
+			rtl_set_bbreg(hw, 0x844, MASKDWORD, 0x00032ed3);
+		rtl_set_bbreg(hw, 0xe30, MASKDWORD, 0x01008c00);
+		rtl_set_bbreg(hw, 0xe34, MASKDWORD, 0x01008c00);
+	}
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "88ee IQK Finish!!\n");
+}
+
+static void _rtl88e_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t)
+{
+	u8 tmpreg;
+	u32 rf_a_mode = 0, rf_b_mode = 0, lc_cal;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	int jj = RF90_PATH_A;
+	int kk = RF90_PATH_B;
+
+	tmpreg = rtl_read_byte(rtlpriv, 0xd03);
+
+	if ((tmpreg & 0x70) != 0)
+		rtl_write_byte(rtlpriv, 0xd03, tmpreg & 0x8F);
+	else
+		rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF);
+
+	if ((tmpreg & 0x70) != 0) {
+		rf_a_mode = rtl_get_rfreg(hw, jj, 0x00, MASK12BITS);
+
+		if (is2t)
+			rf_b_mode = rtl_get_rfreg(hw, kk, 0x00,
+						  MASK12BITS);
+
+		rtl_set_rfreg(hw, jj, 0x00, MASK12BITS,
+			      (rf_a_mode & 0x8FFFF) | 0x10000);
+
+		if (is2t)
+			rtl_set_rfreg(hw, kk, 0x00, MASK12BITS,
+				      (rf_b_mode & 0x8FFFF) | 0x10000);
+	}
+	lc_cal = rtl_get_rfreg(hw, jj, 0x18, MASK12BITS);
+
+	rtl_set_rfreg(hw, jj, 0x18, MASK12BITS, lc_cal | 0x08000);
+
+	mdelay(100);
+
+	if ((tmpreg & 0x70) != 0) {
+		rtl_write_byte(rtlpriv, 0xd03, tmpreg);
+		rtl_set_rfreg(hw, jj, 0x00, MASK12BITS, rf_a_mode);
+
+		if (is2t)
+			rtl_set_rfreg(hw, kk, 0x00, MASK12BITS,
+				      rf_b_mode);
+	} else {
+		rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00);
+	}
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "\n");
+}
+
+static void rfpath_switch(struct ieee80211_hw *hw,
+			  bool bmain, bool is2t)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	struct rtl_efuse *fuse = rtl_efuse(rtl_priv(hw));
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "\n");
+
+	if (is_hal_stop(rtlhal)) {
+		u8 u1btmp;
+		u1btmp = rtl_read_byte(rtlpriv, REG_LEDCFG0);
+		rtl_write_byte(rtlpriv, REG_LEDCFG0, u1btmp | BIT(7));
+		rtl_set_bbreg(hw, rFPGA0_XAB_RFPARAMETER, BIT(13), 0x01);
+	}
+	if (is2t) {
+		if (bmain)
+			rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE,
+				      BIT(5) | BIT(6), 0x1);
+		else
+			rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE,
+				      BIT(5) | BIT(6), 0x2);
+	} else {
+		rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW, BIT(8) | BIT(9), 0);
+		rtl_set_bbreg(hw, 0x914, MASKLWORD, 0x0201);
+
+		/* We use the RF definition of MAIN and AUX, left antenna and
+		 * right antenna repectively.
+		 * Default output at AUX.
+		 */
+		if (bmain) {
+			rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, BIT(14) |
+				      BIT(13) | BIT(12), 0);
+			rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, BIT(5) |
+				      BIT(4) | BIT(3), 0);
+			if (fuse->antenna_div_type == CGCS_RX_HW_ANTDIV)
+				rtl_set_bbreg(hw, RCONFIG_RAM64X16, BIT(31), 0);
+		} else {
+			rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, BIT(14) |
+				      BIT(13) | BIT(12), 1);
+			rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, BIT(5) |
+				      BIT(4) | BIT(3), 1);
+			if (fuse->antenna_div_type == CGCS_RX_HW_ANTDIV)
+				rtl_set_bbreg(hw, RCONFIG_RAM64X16, BIT(31), 1);
+		}
+	}
+}
+
+#undef IQK_ADDA_REG_NUM
+#undef IQK_DELAY_TIME
+
+void rtl88e_phy_iq_calibrate(struct ieee80211_hw *hw, bool recovery)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	long result[4][8];
+	u8 i, final;
+	bool patha_ok;
+	long reg_e94, reg_e9c, reg_ea4, reg_eb4, reg_ebc, reg_tmp = 0;
+	bool is12simular, is13simular, is23simular;
+	u32 iqk_bb_reg[9] = {
+		ROFDM0_XARXIQIMBAL,
+		ROFDM0_XBRXIQIMBAL,
+		ROFDM0_ECCATHRES,
+		ROFDM0_AGCRSSITABLE,
+		ROFDM0_XATXIQIMBAL,
+		ROFDM0_XBTXIQIMBAL,
+		ROFDM0_XCTXAFE,
+		ROFDM0_XDTXAFE,
+		ROFDM0_RXIQEXTANTA
+	};
+
+	if (recovery) {
+		reload_adda(hw, iqk_bb_reg, rtlphy->iqk_bb_backup, 9);
+		return;
+	}
+
+	memset(result, 0, 32 * sizeof(long));
+	final = 0xff;
+	patha_ok = false;
+	is12simular = false;
+	is23simular = false;
+	is13simular = false;
+	for (i = 0; i < 3; i++) {
+		if (get_rf_type(rtlphy) == RF_2T2R)
+			_rtl88e_phy_iq_calibrate(hw, result, i, true);
+		else
+			_rtl88e_phy_iq_calibrate(hw, result, i, false);
+		if (i == 1) {
+			is12simular = sim_comp(hw, result, 0, 1);
+			if (is12simular) {
+				final = 0;
+				break;
+			}
+		}
+		if (i == 2) {
+			is13simular = sim_comp(hw, result, 0, 2);
+			if (is13simular) {
+				final = 0;
+				break;
+			}
+			is23simular = sim_comp(hw, result, 1, 2);
+			if (is23simular) {
+				final = 1;
+			} else {
+				for (i = 0; i < 8; i++)
+					reg_tmp += result[3][i];
+
+				if (reg_tmp != 0)
+					final = 3;
+				else
+					final = 0xFF;
+			}
+		}
+	}
+	for (i = 0; i < 4; i++) {
+		reg_e94 = result[i][0];
+		reg_e9c = result[i][1];
+		reg_ea4 = result[i][2];
+		reg_eb4 = result[i][4];
+		reg_ebc = result[i][5];
+	}
+	if (final != 0xff) {
+		reg_e94 = result[final][0];
+		rtlphy->reg_e94 = reg_e94;
+		reg_e9c = result[final][1];
+		rtlphy->reg_e9c = reg_e9c;
+		reg_ea4 = result[final][2];
+		reg_eb4 = result[final][4];
+		rtlphy->reg_eb4 = reg_eb4;
+		reg_ebc = result[final][5];
+		rtlphy->reg_ebc = reg_ebc;
+		patha_ok = true;
+	} else {
+		rtlphy->reg_e94 = 0x100;
+		rtlphy->reg_eb4 = 0x100;
+		rtlphy->reg_ebc = 0x0;
+		rtlphy->reg_e9c = 0x0;
+	}
+	if (reg_e94 != 0) /*&&(reg_ea4 != 0) */
+		fill_iqk(hw, patha_ok, result, final, (reg_ea4 == 0));
+	if (final != 0xFF) {
+		for (i = 0; i < IQK_MATRIX_REG_NUM; i++)
+			rtlphy->iqk_matrix[0].value[0][i] = result[final][i];
+		rtlphy->iqk_matrix[0].iqk_done = true;
+	}
+	save_adda_reg(hw, iqk_bb_reg, rtlphy->iqk_bb_backup, 9);
+}
+
+void rtl88e_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);
+	bool start_conttx = false, singletone = false;
+	u32 timeout = 2000, timecount = 0;
+
+	if (start_conttx || singletone)
+		return;
+
+	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);
+
+	_rtl88e_phy_lc_calibrate(hw, false);
+
+	rtlphy->lck_inprogress = false;
+}
+
+void rtl88e_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain)
+{
+	rfpath_switch(hw, bmain, false);
+}
+
+bool rtl88e_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 processed\n");
+			break;
+		}
+	} while (false);
+	if (postprocessing && !rtlphy->set_io_inprogress) {
+		rtlphy->set_io_inprogress = true;
+		rtlphy->current_io_type = iotype;
+	} else {
+		return false;
+	}
+	rtl88e_phy_set_io(hw);
+	RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, "IO Type(%#x)\n", iotype);
+	return true;
+}
+
+static void rtl88ee_phy_set_rf_on(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x2b);
+	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3);
+	/*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);
+}
+
+static void _rtl88ee_phy_set_rf_sleep(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	int jj = RF90_PATH_A;
+
+	rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF);
+	rtl_set_rfreg(hw, jj, 0x00, RFREG_OFFSET_MASK, 0x00);
+	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2);
+	rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x22);
+}
+
+static bool _rtl88ee_phy_set_rf_power_state(struct ieee80211_hw *hw,
+					    enum rf_pwrstate rfpwr_state)
+{
+	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 rtl8192_tx_ring *ring = NULL;
+	bool bresult = true;
+	u8 i, queue_id;
+
+	switch (rfpwr_state) {
+	case ERFON:{
+		if ((ppsc->rfpwr_state == ERFOFF) &&
+		    RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) {
+			bool rtstatus;
+			u32 init = 0;
+			do {
+				init++;
+				RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
+					 "IPS Set eRf nic enable\n");
+				rtstatus = rtl_ps_enable_nic(hw);
+			} while ((rtstatus != true) && (init < 10));
+			RT_CLEAR_PS_LEVEL(ppsc,
+					  RT_RF_OFF_LEVL_HALT_NIC);
+		} else {
+			RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
+				 "Set ERFON sleeped:%d ms\n",
+				 jiffies_to_msecs(jiffies - ppsc->
+						  last_sleep_jiffies));
+			ppsc->last_awake_jiffies = jiffies;
+			rtl88ee_phy_set_rf_on(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:{
+		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++;
+				continue;
+			} else {
+				RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+					 "eRf Off/Sleep: %d times TcbBusyQueue[%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,
+					 "\n ERFSLEEP: %d times TcbBusyQueue[%d] = %d !\n",
+					  MAX_DOZE_WAITING_TIMES_9x,
+					  queue_id,
+					  skb_queue_len(&ring->queue));
+				break;
+			}
+		}
+		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++;
+				continue;
+			} else {
+				RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+					 "eRf Off/Sleep: %d times TcbBusyQueue[%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,
+					 "\n ERFSLEEP: %d times TcbBusyQueue[%d] = %d !\n",
+					 MAX_DOZE_WAITING_TIMES_9x,
+					 queue_id,
+					 skb_queue_len(&ring->queue));
+				break;
+			}
+		}
+		RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
+			 "Set ERFSLEEP awaked:%d ms\n",
+			 jiffies_to_msecs(jiffies - ppsc->last_awake_jiffies));
+		ppsc->last_sleep_jiffies = jiffies;
+		_rtl88ee_phy_set_rf_sleep(hw);
+		break; }
+	default:
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 "switch case not processed\n");
+		bresult = false;
+		break;
+	}
+	if (bresult)
+		ppsc->rfpwr_state = rfpwr_state;
+	return bresult;
+}
+
+bool rtl88e_phy_set_rf_power_state(struct ieee80211_hw *hw,
+				   enum rf_pwrstate rfpwr_state)
+{
+	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+	bool bresult;
+
+	if (rfpwr_state == ppsc->rfpwr_state)
+		return false;
+	bresult = _rtl88ee_phy_set_rf_power_state(hw, rfpwr_state);
+	return bresult;
+}
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/phy.h b/drivers/net/wireless/rtlwifi/rtl8188ee/phy.h
new file mode 100644
index 0000000..f1acd6d
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8188ee/phy.h
@@ -0,0 +1,236 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2013  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_PHY_H__
+#define __RTL92C_PHY_H__
+
+/*It must always set to 4, otherwise read efuse table secquence will be wrong.*/
+#define	MAX_TX_COUNT				4
+
+#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 IQK_BB_REG_NUM				9
+#define MAX_TOLERANCE				5
+#define	IQK_DELAY_TIME				10
+#define	IDX_MAP					15
+
+#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 ANTENNADIVERSITYVALUE			0x80
+#define MAX_TXPWR_IDX_NMODE_92S			63
+#define RESET_CNT_LIMIT				3
+
+#define IQK_ADDA_REG_NUM			16
+#define IQK_MAC_REG_NUM				4
+
+#define RF6052_MAX_PATH				2
+
+#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
+
+#define RTL92C_MAX_PATH_NUM			2
+
+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 hw90_block_e {
+	HW90_BLOCK_MAC = 0,
+	HW90_BLOCK_PHY0 = 1,
+	HW90_BLOCK_PHY1 = 2,
+	HW90_BLOCK_RF = 3,
+	HW90_BLOCK_MAXIMUM = 4,
+};
+
+enum baseband_config_type {
+	BASEBAND_CONFIG_PHY_REG = 0,
+	BASEBAND_CONFIG_AGC_TAB = 1,
+};
+
+enum ra_offset_area {
+	RA_OFFSET_LEGACY_OFDM1,
+	RA_OFFSET_LEGACY_OFDM2,
+	RA_OFFSET_HT_OFDM1,
+	RA_OFFSET_HT_OFDM2,
+	RA_OFFSET_HT_OFDM3,
+	RA_OFFSET_HT_OFDM4,
+	RA_OFFSET_HT_CCK,
+};
+
+enum antenna_path {
+	ANTENNA_NONE,
+	ANTENNA_D,
+	ANTENNA_C,
+	ANTENNA_CD,
+	ANTENNA_B,
+	ANTENNA_BD,
+	ANTENNA_BC,
+	ANTENNA_BCD,
+	ANTENNA_A,
+	ANTENNA_AD,
+	ANTENNA_AC,
+	ANTENNA_ACD,
+	ANTENNA_AB,
+	ANTENNA_ABD,
+	ANTENNA_ABC,
+	ANTENNA_ABCD
+};
+
+struct r_antenna_select_ofdm {
+	u32 r_tx_antenna:4;
+	u32 r_ant_l:4;
+	u32 r_ant_non_ht:4;
+	u32 r_ant_ht1:4;
+	u32 r_ant_ht2:4;
+	u32 r_ant_ht_s1:4;
+	u32 r_ant_non_ht_s1:4;
+	u32 ofdm_txsc:2;
+	u32 reserved:2;
+};
+
+struct r_antenna_select_cck {
+	u8 r_cckrx_enable_2:2;
+	u8 r_cckrx_enable:2;
+	u8 r_ccktx_enable:4;
+};
+
+
+struct efuse_contents {
+	u8 mac_addr[ETH_ALEN];
+	u8 cck_tx_power_idx[6];
+	u8 ht40_1s_tx_power_idx[6];
+	u8 ht40_2s_tx_power_idx_diff[3];
+	u8 ht20_tx_power_idx_diff[3];
+	u8 ofdm_tx_power_idx_diff[3];
+	u8 ht40_max_power_offset[3];
+	u8 ht20_max_power_offset[3];
+	u8 channel_plan;
+	u8 thermal_meter;
+	u8 rf_option[5];
+	u8 version;
+	u8 oem_id;
+	u8 regulatory;
+};
+
+struct tx_power_struct {
+	u8 cck[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER];
+	u8 ht40_1s[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER];
+	u8 ht40_2s[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER];
+	u8 ht20_diff[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER];
+	u8 legacy_ht_diff[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER];
+	u8 legacy_ht_txpowerdiff;
+	u8 groupht20[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER];
+	u8 groupht40[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER];
+	u8 pwrgroup_cnt;
+	u32 mcs_original_offset[4][16];
+};
+
+enum _ANT_DIV_TYPE {
+	NO_ANTDIV			= 0xFF,
+	CG_TRX_HW_ANTDIV		= 0x01,
+	CGCS_RX_HW_ANTDIV		= 0x02,
+	FIXED_HW_ANTDIV			= 0x03,
+	CG_TRX_SMART_ANTDIV		= 0x04,
+	CGCS_RX_SW_ANTDIV		= 0x05,
+};
+
+extern u32 rtl88e_phy_query_bb_reg(struct ieee80211_hw *hw,
+				   u32 regaddr, u32 bitmask);
+extern void rtl88e_phy_set_bb_reg(struct ieee80211_hw *hw,
+				  u32 regaddr, u32 bitmask, u32 data);
+extern u32 rtl88e_phy_query_rf_reg(struct ieee80211_hw *hw,
+				   enum radio_path rfpath, u32 regaddr,
+				   u32 bitmask);
+extern void rtl88e_phy_set_rf_reg(struct ieee80211_hw *hw,
+				  enum radio_path rfpath, u32 regaddr,
+				  u32 bitmask, u32 data);
+extern bool rtl88e_phy_mac_config(struct ieee80211_hw *hw);
+extern bool rtl88e_phy_bb_config(struct ieee80211_hw *hw);
+extern bool rtl88e_phy_rf_config(struct ieee80211_hw *hw);
+extern void rtl88e_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw);
+extern void rtl88e_phy_get_txpower_level(struct ieee80211_hw *hw,
+					 long *powerlevel);
+extern void rtl88e_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel);
+extern void rtl88e_phy_scan_operation_backup(struct ieee80211_hw *hw,
+					     u8 operation);
+extern void rtl88e_phy_set_bw_mode_callback(struct ieee80211_hw *hw);
+extern void rtl88e_phy_set_bw_mode(struct ieee80211_hw *hw,
+				   enum nl80211_channel_type ch_type);
+extern void rtl88e_phy_sw_chnl_callback(struct ieee80211_hw *hw);
+extern u8 rtl88e_phy_sw_chnl(struct ieee80211_hw *hw);
+extern void rtl88e_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery);
+void rtl88e_phy_lc_calibrate(struct ieee80211_hw *hw);
+void rtl88e_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain);
+bool rtl88e_phy_config_rf_with_headerfile(struct ieee80211_hw *hw,
+					  enum radio_path rfpath);
+bool rtl88e_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype);
+extern bool rtl88e_phy_set_rf_power_state(struct ieee80211_hw *hw,
+					  enum rf_pwrstate rfpwr_state);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseq.c b/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseq.c
new file mode 100644
index 0000000..6dc4e3a
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseq.c
@@ -0,0 +1,109 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2013  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 "pwrseqcmd.h"
+#include "pwrseq.h"
+
+/* drivers should parse below arrays and do the corresponding actions */
+/*3 Power on  Array*/
+struct wlan_pwr_cfg rtl8188e_power_on_flow[RTL8188E_TRANS_CARDEMU_TO_ACT_STEPS +
+					   RTL8188E_TRANS_END_STEPS] = {
+	RTL8188E_TRANS_CARDEMU_TO_ACT
+	RTL8188E_TRANS_END
+};
+
+/*3Radio off GPIO Array */
+struct wlan_pwr_cfg rtl8188e_radio_off_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS
+					    + RTL8188E_TRANS_END_STEPS] = {
+	RTL8188E_TRANS_ACT_TO_CARDEMU
+	RTL8188E_TRANS_END
+};
+
+/*3Card Disable Array*/
+struct wlan_pwr_cfg rtl8188e_card_disable_flow
+	[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS +
+	RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS +
+	RTL8188E_TRANS_END_STEPS] = {
+		RTL8188E_TRANS_ACT_TO_CARDEMU
+		RTL8188E_TRANS_CARDEMU_TO_CARDDIS
+		RTL8188E_TRANS_END
+};
+
+/*3 Card Enable Array*/
+struct wlan_pwr_cfg rtl8188e_card_enable_flow
+	[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS +
+	RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS +
+	RTL8188E_TRANS_END_STEPS] = {
+		RTL8188E_TRANS_CARDDIS_TO_CARDEMU
+		RTL8188E_TRANS_CARDEMU_TO_ACT
+		RTL8188E_TRANS_END
+};
+
+/*3Suspend Array*/
+struct wlan_pwr_cfg rtl8188e_suspend_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS
+					+ RTL8188E_TRANS_CARDEMU_TO_SUS_STEPS
+					+ RTL8188E_TRANS_END_STEPS] = {
+	RTL8188E_TRANS_ACT_TO_CARDEMU
+	RTL8188E_TRANS_CARDEMU_TO_SUS
+	RTL8188E_TRANS_END
+};
+
+/*3 Resume Array*/
+struct wlan_pwr_cfg rtl8188e_resume_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS
+					+ RTL8188E_TRANS_CARDEMU_TO_SUS_STEPS
+					+ RTL8188E_TRANS_END_STEPS] = {
+	RTL8188E_TRANS_SUS_TO_CARDEMU
+	RTL8188E_TRANS_CARDEMU_TO_ACT
+	RTL8188E_TRANS_END
+};
+
+/*3HWPDN Array*/
+struct wlan_pwr_cfg rtl8188e_hwpdn_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS
+				+ RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS
+				+ RTL8188E_TRANS_END_STEPS] = {
+	RTL8188E_TRANS_ACT_TO_CARDEMU
+	RTL8188E_TRANS_CARDEMU_TO_PDN
+	RTL8188E_TRANS_END
+};
+
+/*3 Enter LPS */
+struct wlan_pwr_cfg rtl8188e_enter_lps_flow[RTL8188E_TRANS_ACT_TO_LPS_STEPS
+					+ RTL8188E_TRANS_END_STEPS] = {
+	/*FW behavior*/
+	RTL8188E_TRANS_ACT_TO_LPS
+	RTL8188E_TRANS_END
+};
+
+/*3 Leave LPS */
+struct wlan_pwr_cfg rtl8188e_leave_lps_flow[RTL8188E_TRANS_LPS_TO_ACT_STEPS
+					+ RTL8188E_TRANS_END_STEPS] = {
+	/*FW behavior*/
+	RTL8188E_TRANS_LPS_TO_ACT
+	RTL8188E_TRANS_END
+};
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseq.h b/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseq.h
new file mode 100644
index 0000000..028ec6d
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseq.h
@@ -0,0 +1,327 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2013  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 __RTL8723E_PWRSEQ_H__
+#define __RTL8723E_PWRSEQ_H__
+
+#include "pwrseqcmd.h"
+/*
+	Check document WM-20110607-Paul-RTL8188E_Power_Architecture-R02.vsd
+	There are 6 HW Power States:
+	0: POFF--Power Off
+	1: PDN--Power Down
+	2: CARDEMU--Card Emulation
+	3: ACT--Active Mode
+	4: LPS--Low Power State
+	5: SUS--Suspend
+
+	The transision from different states are defined below
+	TRANS_CARDEMU_TO_ACT
+	TRANS_ACT_TO_CARDEMU
+	TRANS_CARDEMU_TO_SUS
+	TRANS_SUS_TO_CARDEMU
+	TRANS_CARDEMU_TO_PDN
+	TRANS_ACT_TO_LPS
+	TRANS_LPS_TO_ACT
+
+	TRANS_END
+	PWR SEQ Version: rtl8188e_PwrSeq_V09.h
+*/
+
+#define	RTL8188E_TRANS_CARDEMU_TO_ACT_STEPS	10
+#define	RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS	10
+#define	RTL8188E_TRANS_CARDEMU_TO_SUS_STEPS	10
+#define	RTL8188E_TRANS_SUS_TO_CARDEMU_STEPS	10
+#define	RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS	10
+#define	RTL8188E_TRANS_PDN_TO_CARDEMU_STEPS	10
+#define	RTL8188E_TRANS_ACT_TO_LPS_STEPS		15
+#define	RTL8188E_TRANS_LPS_TO_ACT_STEPS		15
+#define	RTL8188E_TRANS_END_STEPS		1
+
+
+#define RTL8188E_TRANS_CARDEMU_TO_ACT					\
+	/* format */							\
+	/* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value },*/\
+	{0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+	/* wait till 0x04[17] = 1    power ready*/			\
+	PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(1), BIT(1)},		\
+	{0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+	/* 0x02[1:0] = 0	reset BB*/				\
+	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0)|BIT(1), 0},		\
+	{0x0026, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+	/*0x24[23] = 2b'01 schmit trigger */				\
+	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), BIT(7)},		\
+	{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+	/* 0x04[15] = 0 disable HWPDN (control by DRV)*/		\
+	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), 0},			\
+	{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+	/*0x04[12:11] = 2b'00 disable WL suspend*/			\
+	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4)|BIT(3), 0},		\
+	{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+	/*0x04[8] = 1 polling until return 0*/				\
+	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), BIT(0)},		\
+	{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+	/*wait till 0x04[8] = 0*/					\
+	PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(0), 0},			\
+	{0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0}, /*LDO normal mode*/\
+	{0x0074, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,	\
+	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), BIT(4)}, /*SDIO Driving*/\
+
+#define RTL8188E_TRANS_ACT_TO_CARDEMU					\
+	/* format */							\
+	/* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value },*/\
+	{0x001F, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+	PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0},/*0x1F[7:0] = 0 turn off RF*/\
+	{0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), BIT(4)}, /*LDO Sleep mode*/\
+	{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+	/*0x04[9] = 1 turn off MAC by HW state machine*/		\
+	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), BIT(1)},		\
+	{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+	/*wait till 0x04[9] = 0 polling until return 0 to disable*/	\
+	PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(1), 0},			\
+
+
+#define RTL8188E_TRANS_CARDEMU_TO_SUS					\
+	/* format */							\
+	/* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value },*/\
+	{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK,			\
+	PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK,				\
+	/*0x04[12:11] = 2b'01enable WL suspend*/			\
+	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), BIT(3)},	\
+	{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK,	\
+	/*0x04[12:11] = 2b'11enable WL suspend for PCIe*/		\
+	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), BIT(3)|BIT(4)},\
+	{0x0007, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK,			\
+	PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK,				\
+	/*  0x04[31:30] = 2b'10 enable enable bandgap mbias in suspend */\
+	PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, BIT(7)},			\
+	{0x0041, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK,			\
+	PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK,				\
+	/*Clear SIC_EN register 0x40[12] = 1'b0 */			\
+	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0},			\
+	{0xfe10, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK,			\
+	PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK,				\
+	/*Set USB suspend enable local register  0xfe10[4]= 1 */	\
+	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), BIT(4)},		\
+	{0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,	\
+	/*Set SDIO suspend local register*/				\
+	PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT(0), BIT(0)},		\
+	{0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,	\
+	/*wait power state to suspend*/					\
+	PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT(1), 0},
+
+#define RTL8188E_TRANS_SUS_TO_CARDEMU					\
+	/* format */							\
+	/* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */\
+	{0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,	\
+	/*Set SDIO suspend local register*/				\
+	PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT(0), 0},			\
+	{0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,	\
+	/*wait power state to suspend*/					\
+	PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT(1), BIT(1)},		\
+	{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+	/*0x04[12:11] = 2b'01enable WL suspend*/			\
+	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), 0},
+
+#define RTL8188E_TRANS_CARDEMU_TO_CARDDIS				\
+	/* format */							\
+	/* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */\
+	{0x0026, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+	/*0x24[23] = 2b'01 schmit trigger */				\
+	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), BIT(7)},		\
+	{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK,			\
+	PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK,				\
+	/*0x04[12:11] = 2b'01 enable WL suspend*/			\
+	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), BIT(3)},	\
+	{0x0007, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK,			\
+	PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK,				\
+	/*  0x04[31:30] = 2b'10 enable enable bandgap mbias in suspend */\
+	PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0},			\
+	{0x0041, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK,			\
+	PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK,				\
+	/*Clear SIC_EN register 0x40[12] = 1'b0 */			\
+	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0},			\
+	{0xfe10, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK,	\
+	/*Set USB suspend enable local register  0xfe10[4]= 1 */	\
+	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), BIT(4)},		\
+	{0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,	\
+	/*Set SDIO suspend local register*/				\
+	PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT(0), BIT(0)},		\
+	{0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,	\
+	PWR_CMD_POLLING, BIT(1), 0}, /*wait power state to suspend*/
+
+#define RTL8188E_TRANS_CARDDIS_TO_CARDEMU				\
+	/* format */							\
+	/* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */\
+	{0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,	\
+	PWR_BASEADDR_SDIO,\
+	PWR_CMD_WRITE, BIT(0), 0}, /*Set SDIO suspend local register*/	\
+	{0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,	\
+	PWR_BASEADDR_SDIO,\
+	PWR_CMD_POLLING, BIT(1), BIT(1)}, /*wait power state to suspend*/\
+	{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+	PWR_BASEADDR_MAC,						\
+	PWR_CMD_WRITE, BIT(3)|BIT(4), 0},				\
+	/*0x04[12:11] = 2b'01enable WL suspend*/
+
+
+#define RTL8188E_TRANS_CARDEMU_TO_PDN					\
+	/* format */							\
+	/* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */\
+	{0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), 0},/* 0x04[16] = 0*/	\
+	{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), BIT(7)},/* 0x04[15] = 1*/
+
+
+#define RTL8188E_TRANS_PDN_TO_CARDEMU					\
+	/* format */							\
+	/* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */\
+	{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), 0},/* 0x04[15] = 0*/
+
+
+#define RTL8188E_TRANS_ACT_TO_LPS					\
+	/* format */							\
+	/* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value },*/\
+	{0x0522, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+	PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x7F},/*Tx Pause*/	\
+	{0x05F8, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+	/*zero if no pkt is tx*/\
+	PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0},			\
+	{0x05F9, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+	/*Should be zero if no packet is transmitting*/	\
+	PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0},			\
+	{0x05FA, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+	/*Should be zero if no packet is transmitting*/			\
+	PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0},			\
+	{0x05FB, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+	/*Should be zero if no packet is transmitting*/			\
+	PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0},			\
+	{0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+	/*CCK and OFDM are disabled, and clock are gated*/		\
+	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), 0},			\
+	{0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+	PWR_BASEADDR_MAC, PWR_CMD_DELAY, 0, PWRSEQ_DELAY_US},/*Delay 1us*/\
+	{0x0100, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+	PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x3F},/*Reset MAC TRX*/	\
+	{0x0101, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+	/*check if removed later*/					\
+	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), 0},			\
+	{0x0553, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+	/*Respond TxOK to scheduler*/					\
+	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(5), BIT(5)},		\
+
+
+#define RTL8188E_TRANS_LPS_TO_ACT					\
+	/* format */							\
+	/* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */\
+	{0x0080, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,	\
+	PWR_BASEADDR_SDIO, PWR_CMD_WRITE, 0xFF, 0x84}, /*SDIO RPWM*/	\
+	{0xFE58, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK,	\
+	PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x84}, /*USB RPWM*/	\
+	{0x0361, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK,	\
+	PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x84}, /*PCIe RPWM*/	\
+	{0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+	PWR_BASEADDR_MAC, PWR_CMD_DELAY, 0, PWRSEQ_DELAY_MS}, /*Delay*/	\
+	{0x0008, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+	/*.	0x08[4] = 0		 switch TSF to 40M*/		\
+	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0},			\
+	{0x0109, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+	/*Polling 0x109[7]= 0  TSF in 40M*/				\
+	PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(7), 0},			\
+	{0x0029, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+	/*. 0x29[7:6] = 2b'00	 enable BB clock*/			\
+	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(6)|BIT(7), 0},		\
+	{0x0101, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+	/*.	0x101[1] = 1*/\
+	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), BIT(1)},		\
+	{0x0100, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+	/*.	0x100[7:0] = 0xFF	 enable WMAC TRX*/\
+	PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0xFF},			\
+	{0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+	/*. 0x02[1:0] = 2b'11  enable BB macro*/\
+	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1)|BIT(0), BIT(1)|BIT(0)},	\
+	{0x0522, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\
+	PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0}, /*.	0x522 = 0*/
+
+
+#define RTL8188E_TRANS_END						\
+	/* format */							\
+	/* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value },*/\
+	{0xFFFF, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\
+	0, PWR_CMD_END, 0, 0}
+
+extern struct wlan_pwr_cfg rtl8188e_power_on_flow
+		[RTL8188E_TRANS_CARDEMU_TO_ACT_STEPS +
+		RTL8188E_TRANS_END_STEPS];
+extern struct wlan_pwr_cfg rtl8188e_radio_off_flow
+		[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS +
+		RTL8188E_TRANS_END_STEPS];
+extern struct wlan_pwr_cfg rtl8188e_card_disable_flow
+		[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS +
+		RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS +
+		RTL8188E_TRANS_END_STEPS];
+extern struct wlan_pwr_cfg rtl8188e_card_enable_flow
+		[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS +
+		RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS +
+		RTL8188E_TRANS_END_STEPS];
+extern struct wlan_pwr_cfg rtl8188e_suspend_flow
+		[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS +
+		RTL8188E_TRANS_CARDEMU_TO_SUS_STEPS +
+		RTL8188E_TRANS_END_STEPS];
+extern struct wlan_pwr_cfg rtl8188e_resume_flow
+		[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS +
+		RTL8188E_TRANS_CARDEMU_TO_SUS_STEPS +
+		RTL8188E_TRANS_END_STEPS];
+extern struct wlan_pwr_cfg rtl8188e_hwpdn_flow
+		[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS +
+		RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS +
+		RTL8188E_TRANS_END_STEPS];
+extern struct wlan_pwr_cfg rtl8188e_enter_lps_flow
+		[RTL8188E_TRANS_ACT_TO_LPS_STEPS +
+		RTL8188E_TRANS_END_STEPS];
+extern struct wlan_pwr_cfg rtl8188e_leave_lps_flow
+		[RTL8188E_TRANS_LPS_TO_ACT_STEPS +
+		RTL8188E_TRANS_END_STEPS];
+
+/* RTL8723 Power Configuration CMDs for PCIe interface */
+#define Rtl8188E_NIC_PWR_ON_FLOW	rtl8188e_power_on_flow
+#define Rtl8188E_NIC_RF_OFF_FLOW	rtl8188e_radio_off_flow
+#define Rtl8188E_NIC_DISABLE_FLOW	rtl8188e_card_disable_flow
+#define Rtl8188E_NIC_ENABLE_FLOW	rtl8188e_card_enable_flow
+#define Rtl8188E_NIC_SUSPEND_FLOW	rtl8188e_suspend_flow
+#define Rtl8188E_NIC_RESUME_FLOW	rtl8188e_resume_flow
+#define Rtl8188E_NIC_PDN_FLOW		rtl8188e_hwpdn_flow
+#define Rtl8188E_NIC_LPS_ENTER_FLOW	rtl8188e_enter_lps_flow
+#define Rtl8188E_NIC_LPS_LEAVE_FLOW	rtl8188e_leave_lps_flow
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseqcmd.c b/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseqcmd.c
new file mode 100644
index 0000000..a9cfa13
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseqcmd.c
@@ -0,0 +1,140 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2013  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 "pwrseq.h"
+
+
+/*	Description:
+ *		This routine deal with the Power Configuration CMDs
+ *		 parsing for RTL8723/RTL8188E Series IC.
+ *	Assumption:
+ *		We should follow specific format which was released from HW SD.
+ *
+ *	2011.07.07, added by Roger.
+ */
+
+bool rtl88_hal_pwrseqcmdparsing(struct rtl_priv *rtlpriv, u8 cut_version,
+				u8 fab_version, u8 interface_type,
+				struct wlan_pwr_cfg pwrcfgcmd[])
+{
+	struct wlan_pwr_cfg cmd = {0};
+	bool polling_bit = false;
+	u32 ary_idx = 0;
+	u8 val = 0;
+	u32 offset = 0;
+	u32 polling_count = 0;
+	u32 max_polling_cnt = 5000;
+
+	do {
+		cmd = pwrcfgcmd[ary_idx];
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 "rtl88_hal_pwrseqcmdparsing(): offset(%#x), cut_msk(%#x), fab_msk(%#x),"
+			 "interface_msk(%#x), base(%#x), cmd(%#x), msk(%#x), val(%#x)\n",
+			 GET_PWR_CFG_OFFSET(cmd),
+			 GET_PWR_CFG_CUT_MASK(cmd),
+			 GET_PWR_CFG_FAB_MASK(cmd),
+			 GET_PWR_CFG_INTF_MASK(cmd),
+			 GET_PWR_CFG_BASE(cmd),
+			 GET_PWR_CFG_CMD(cmd),
+			 GET_PWR_CFG_MASK(cmd),
+			 GET_PWR_CFG_VALUE(cmd));
+
+		if ((GET_PWR_CFG_FAB_MASK(cmd) & fab_version) &&
+		    (GET_PWR_CFG_CUT_MASK(cmd) & cut_version) &&
+		    (GET_PWR_CFG_INTF_MASK(cmd) & interface_type)) {
+			switch (GET_PWR_CFG_CMD(cmd)) {
+			case PWR_CMD_READ:
+				RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+					 "rtl88_hal_pwrseqcmdparsing(): PWR_CMD_READ\n");
+				break;
+			case PWR_CMD_WRITE: {
+				RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+					 "rtl88_hal_pwrseqcmdparsing(): PWR_CMD_WRITE\n");
+				offset = GET_PWR_CFG_OFFSET(cmd);
+
+					/*Read the val from system register*/
+					val = rtl_read_byte(rtlpriv, offset);
+					val &= (~(GET_PWR_CFG_MASK(cmd)));
+					val |= (GET_PWR_CFG_VALUE(cmd) &
+						GET_PWR_CFG_MASK(cmd));
+
+					/*Write the val back to sytem register*/
+					rtl_write_byte(rtlpriv, offset, val);
+				}
+				break;
+			case PWR_CMD_POLLING:
+				RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+					 "rtl88_hal_pwrseqcmdparsing(): PWR_CMD_POLLING\n");
+				polling_bit = false;
+				offset = GET_PWR_CFG_OFFSET(cmd);
+
+				do {
+					val = rtl_read_byte(rtlpriv, offset);
+
+					val = val & GET_PWR_CFG_MASK(cmd);
+					if (val == (GET_PWR_CFG_VALUE(cmd) &
+						    GET_PWR_CFG_MASK(cmd)))
+						polling_bit = true;
+					else
+						udelay(10);
+
+					if (polling_count++ > max_polling_cnt) {
+						RT_TRACE(rtlpriv, COMP_INIT,
+							 DBG_LOUD,
+							 "polling fail in pwrseqcmd\n");
+						return false;
+					}
+				} while (!polling_bit);
+
+				break;
+			case PWR_CMD_DELAY:
+				RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+					 "rtl88_hal_pwrseqcmdparsing(): PWR_CMD_DELAY\n");
+				if (GET_PWR_CFG_VALUE(cmd) == PWRSEQ_DELAY_US)
+					udelay(GET_PWR_CFG_OFFSET(cmd));
+				else
+					mdelay(GET_PWR_CFG_OFFSET(cmd));
+				break;
+			case PWR_CMD_END:
+				RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+					 "rtl88_hal_pwrseqcmdparsing(): PWR_CMD_END\n");
+				return true;
+				break;
+			default:
+				RT_ASSERT(false,
+					  "rtl88_hal_pwrseqcmdparsing(): Unknown CMD!!\n");
+				break;
+			}
+		}
+
+		ary_idx++;
+	} while (1);
+
+	return true;
+}
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseqcmd.h b/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseqcmd.h
new file mode 100644
index 0000000..d9ae280
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseqcmd.h
@@ -0,0 +1,97 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2013  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 __RTL8723E_PWRSEQCMD_H__
+#define __RTL8723E_PWRSEQCMD_H__
+
+#include "../wifi.h"
+/*---------------------------------------------*/
+/* The value of cmd: 4 bits */
+/*---------------------------------------------*/
+#define PWR_CMD_READ		0x00
+#define PWR_CMD_WRITE		0x01
+#define PWR_CMD_POLLING		0x02
+#define PWR_CMD_DELAY		0x03
+#define PWR_CMD_END		0x04
+
+/* define the base address of each block */
+#define PWR_BASEADDR_MAC	0x00
+#define PWR_BASEADDR_USB	0x01
+#define PWR_BASEADDR_PCIE	0x02
+#define PWR_BASEADDR_SDIO	0x03
+
+#define PWR_INTF_SDIO_MSK	BIT(0)
+#define PWR_INTF_USB_MSK	BIT(1)
+#define PWR_INTF_PCI_MSK	BIT(2)
+#define PWR_INTF_ALL_MSK	(BIT(0)|BIT(1)|BIT(2)|BIT(3))
+
+#define	PWR_FAB_TSMC_MSK	BIT(0)
+#define	PWR_FAB_UMC_MSK		BIT(1)
+#define	PWR_FAB_ALL_MSK		(BIT(0)|BIT(1)|BIT(2)|BIT(3))
+
+#define	PWR_CUT_TESTCHIP_MSK	BIT(0)
+#define	PWR_CUT_A_MSK		BIT(1)
+#define	PWR_CUT_B_MSK		BIT(2)
+#define	PWR_CUT_C_MSK		BIT(3)
+#define	PWR_CUT_D_MSK		BIT(4)
+#define	PWR_CUT_E_MSK		BIT(5)
+#define	PWR_CUT_F_MSK		BIT(6)
+#define	PWR_CUT_G_MSK		BIT(7)
+#define	PWR_CUT_ALL_MSK		0xFF
+
+enum pwrseq_delay_unit {
+	PWRSEQ_DELAY_US,
+	PWRSEQ_DELAY_MS,
+};
+
+struct wlan_pwr_cfg {
+	u16 offset;
+	u8 cut_msk;
+	u8 fab_msk:4;
+	u8 interface_msk:4;
+	u8 base:4;
+	u8 cmd:4;
+	u8 msk;
+	u8 value;
+};
+
+#define	GET_PWR_CFG_OFFSET(__PWR)	(__PWR.offset)
+#define	GET_PWR_CFG_CUT_MASK(__PWR)	(__PWR.cut_msk)
+#define	GET_PWR_CFG_FAB_MASK(__PWR)	(__PWR.fab_msk)
+#define	GET_PWR_CFG_INTF_MASK(__PWR)	(__PWR.interface_msk)
+#define	GET_PWR_CFG_BASE(__PWR)		(__PWR.base)
+#define	GET_PWR_CFG_CMD(__PWR)		(__PWR.cmd)
+#define	GET_PWR_CFG_MASK(__PWR)		(__PWR.msk)
+#define	GET_PWR_CFG_VALUE(__PWR)	(__PWR.value)
+
+bool rtl88_hal_pwrseqcmdparsing(struct rtl_priv *rtlpriv, u8 cut_version,
+				u8 fab_version, u8 interface_type,
+				struct wlan_pwr_cfg pwrcfgcmd[]);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/reg.h b/drivers/net/wireless/rtlwifi/rtl8188ee/reg.h
new file mode 100644
index 0000000..d849abf
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8188ee/reg.h
@@ -0,0 +1,2258 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2013  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_REG_H__
+#define __RTL92C_REG_H__
+
+#define TXPKT_BUF_SELECT			0x69
+#define RXPKT_BUF_SELECT			0xA5
+#define DISABLE_TRXPKT_BUF_ACCESS		0x0
+
+#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_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_LDO_CTRL			0x0027 /* 1.5v for 8188EE test
+							* chip, 1.4v for MP chip
+							*/
+#define REG_AFE_PLL_CTRL			0x0028
+#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_HSIMR				0x0058
+#define REG_HSISR				0x005c
+#define REG_GPIO_PIN_CTRL_2			0x0060
+#define REG_GPIO_IO_SEL_2			0x0062
+#define REG_GPIO_OUTPUT				0x006c
+#define REG_AFE_XTAL_CTRL_EXT			0x0078
+#define REG_XCK_OUT_CTRL			0x007c
+#define REG_MCUFWDL				0x0080
+#define REG_WOL_EVENT				0x0081
+#define REG_MCUTSTCFG				0x0084
+
+
+#define REG_HIMR				0x00B0
+#define REG_HISR				0x00B4
+#define REG_HIMRE				0x00B8
+#define REG_HISRE				0x00BC
+
+#define REG_EFUSE_ACCESS			0x00CF
+
+#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_CR					0x0100
+#define REG_PBP					0x0104
+#define REG_PKT_BUFF_ACCESS_CTRL		0x0106
+#define REG_TRXDMA_CTRL				0x010C
+#define REG_TRXFF_BNDY				0x0114
+#define REG_TRXFF_STATUS			0x0118
+#define REG_RXFF_PTR				0x011C
+
+#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_RXPKTBUF_CTRL			(REG_PKTBUF_DBG_CTRL+2)
+
+#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_32K_CTRL				0x0194
+#define REG_C2HEVT_MSG_NORMAL			0x01A0
+#define REG_C2HEVT_CLEAR			0x01AF
+#define REG_C2HEVT_MSG_TEST			0x01B8
+#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
+
+#define REG_HMEBOX_EXT_0			0x01F0
+#define REG_HMEBOX_EXT_1			0x01F4
+#define REG_HMEBOX_EXT_2			0x01F8
+#define REG_HMEBOX_EXT_3			0x01FC
+
+#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
+
+#define REG_RXDMA_AGG_PG_TH			0x0280
+#define REG_FW_UPD_RDPTR			0x0284 /* FW shall update this
+						* register before FW * write
+						* RXPKT_RELEASE_POLL to 1
+						*/
+#define REG_RXDMA_CONTROL			0x0286 /* Control the RX DMA.*/
+#define REG_RXPKT_NUM				0x0287 /* The number of packets
+							* in RXPKTBUF.
+							 */
+#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_MDIO				0x0354
+#define	REG_DBG_SEL				0x0360
+#define	REG_PCIE_HRPWM				0x0361
+#define	REG_PCIE_HCPWM				0x0363
+#define	REG_UART_CTRL				0x0364
+#define	REG_WATCH_DOG				0x0368
+#define	REG_UART_TX_DESA			0x0370
+#define	REG_UART_RX_DESA			0x0378
+
+
+#define	REG_HDAQ_DESA_NODEF			0x0000
+#define	REG_CMDQ_DESA_NODEF			0x0000
+
+#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_TXPKT_EMPTY				0x041A
+
+
+#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_BAR_MODE_CTRL			0x04CC
+#define REG_RA_TRY_RATE_AGG_LMT			0x04CF
+#define REG_EARLY_MODE_CONTROL			0x04D0
+#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_TX_RPT_CTRL				0x04EC
+#define REG_TX_RPT_TIME				0x04F0
+#define REG_DUMMY				0x04FC
+
+#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
+
+#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
+
+#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_TRXPTCL_CTL				0x0668
+
+#define REG_CAMCMD				0x0670
+#define REG_CAMWRITE				0x0674
+#define REG_CAMREAD				0x0678
+#define REG_CAMDBG				0x067C
+#define REG_SECCFG				0x0680
+
+#define REG_WOW_CTRL				0x0690
+#define REG_PSSTATUS				0x0691
+#define REG_PS_RX_INFO				0x0692
+#define REG_UAPSD_TID				0x0693
+#define REG_LPNAV_CTRL				0x0694
+#define REG_WKFMCAM_NUM				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
+
+#define REG_USB_INFO				0xFE17
+#define REG_USB_SPECIAL_OPTION			0xFE55
+#define REG_USB_DMA_AGG_TO			0xFE5B
+#define REG_USB_AGG_TO				0xFE5C
+#define REG_USB_AGG_TH				0xFE5D
+
+#define REG_TEST_USB_TXQS			0xFE48
+#define REG_TEST_SIE_VID			0xFE60
+#define REG_TEST_SIE_PID			0xFE62
+#define REG_TEST_SIE_OPTIONAL			0xFE64
+#define REG_TEST_SIE_CHIRP_K			0xFE65
+#define REG_TEST_SIE_PHY			0xFE66
+#define REG_TEST_SIE_MAC_ADDR			0xFE70
+#define REG_TEST_SIE_STRING			0xFE80
+
+#define REG_NORMAL_SIE_VID			0xFE60
+#define REG_NORMAL_SIE_PID			0xFE62
+#define REG_NORMAL_SIE_OPTIONAL			0xFE64
+#define REG_NORMAL_SIE_EP			0xFE65
+#define REG_NORMAL_SIE_PHY			0xFE68
+#define REG_NORMAL_SIE_MAC_ADDR			0xFE70
+#define REG_NORMAL_SIE_STRING			0xFE80
+
+#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
+
+#define	UNUSED_REGISTER				0x1BF
+#define	DCAM					UNUSED_REGISTER
+#define	PSR					UNUSED_REGISTER
+#define BBADDR					UNUSED_REGISTER
+#define	PHYDATAR				UNUSED_REGISTER
+
+#define	INVALID_BBRF_VALUE			0x12345678
+
+#define	MAX_MSS_DENSITY_2T			0x13
+#define	MAX_MSS_DENSITY_1T			0x0A
+
+#define	CMDEEPROM_EN				BIT(5)
+#define	CMDEEPROM_SEL				BIT(4)
+#define	CMD9346CR_9356SEL			BIT(4)
+#define	AUTOLOAD_EEPROM				(CMDEEPROM_EN|CMDEEPROM_SEL)
+#define	AUTOLOAD_EFUSE				CMDEEPROM_EN
+
+#define	GPIOSEL_GPIO				0
+#define	GPIOSEL_ENBT				BIT(5)
+
+#define	GPIO_IN					REG_GPIO_PIN_CTRL
+#define	GPIO_OUT				(REG_GPIO_PIN_CTRL+1)
+#define	GPIO_IO_SEL				(REG_GPIO_PIN_CTRL+2)
+#define	GPIO_MOD				(REG_GPIO_PIN_CTRL+3)
+
+/* 8723/8188E Host System Interrupt Mask Register (offset 0x58, 32 byte) */
+#define	HSIMR_GPIO12_0_INT_EN			BIT(0)
+#define	HSIMR_SPS_OCP_INT_EN			BIT(5)
+#define	HSIMR_RON_INT_EN			BIT(6)
+#define	HSIMR_PDN_INT_EN			BIT(7)
+#define	HSIMR_GPIO9_INT_EN			BIT(25)
+
+
+/* 8723/8188E Host System Interrupt Status Register (offset 0x5C, 32 byte) */
+#define	HSISR_GPIO12_0_INT			BIT(0)
+#define	HSISR_SPS_OCP_INT			BIT(5)
+#define	HSISR_RON_INT_EN			BIT(6)
+#define	HSISR_PDNINT				BIT(7)
+#define	HSISR_GPIO9_INT				BIT(25)
+
+#define	MSR_NOLINK				0x00
+#define	MSR_ADHOC				0x01
+#define	MSR_INFRA				0x02
+#define	MSR_AP					0x03
+
+#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					BIT(0)
+#define	RRSR_2M					BIT(1)
+#define	RRSR_5_5M				BIT(2)
+#define	RRSR_11M				BIT(3)
+#define	RRSR_6M					BIT(4)
+#define	RRSR_9M					BIT(5)
+#define	RRSR_12M				BIT(6)
+#define	RRSR_18M				BIT(7)
+#define	RRSR_24M				BIT(8)
+#define	RRSR_36M				BIT(9)
+#define	RRSR_48M				BIT(10)
+#define	RRSR_54M				BIT(11)
+#define	RRSR_MCS0				BIT(12)
+#define	RRSR_MCS1				BIT(13)
+#define	RRSR_MCS2				BIT(14)
+#define	RRSR_MCS3				BIT(15)
+#define	RRSR_MCS4				BIT(16)
+#define	RRSR_MCS5				BIT(17)
+#define	RRSR_MCS6				BIT(18)
+#define	RRSR_MCS7				BIT(19)
+#define	BRSR_ACKSHORTPMB			BIT(23)
+
+#define	RATR_1M					0x00000001
+#define	RATR_2M					0x00000002
+#define	RATR_55M				0x00000004
+#define	RATR_11M				0x00000008
+#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
+#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
+#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
+
+#define RATE_1M					BIT(0)
+#define RATE_2M					BIT(1)
+#define RATE_5_5M				BIT(2)
+#define RATE_11M				BIT(3)
+#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)
+#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)
+#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)
+
+#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)
+
+#define	BW_OPMODE_20MHZ				BIT(2)
+#define	BW_OPMODE_5G				BIT(1)
+#define	BW_OPMODE_11J				BIT(0)
+
+#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	TOTAL_CAM_ENTRY				32
+#define	HALF_CAM_ENTRY				16
+
+#define	CAM_WRITE				BIT(16)
+#define	CAM_READ				0x00000000
+#define	CAM_POLLINIG				BIT(31)
+
+#define	SCR_USEDK				0x01
+#define	SCR_TXSEC_ENABLE			0x02
+#define	SCR_RXSEC_ENABLE			0x04
+
+#define	WOW_PMEN				BIT(0)
+#define	WOW_WOMEN				BIT(1)
+#define	WOW_MAGIC				BIT(2)
+#define	WOW_UWF					BIT(3)
+
+/*********************************************
+*       8188 IMR/ISR bits
+**********************************************/
+#define	IMR_DISABLED				0x0
+/* IMR DW0(0x0060-0063) Bit 0-31 */
+#define	IMR_TXCCK		BIT(30) /* TXRPT interrupt when CCX bit of
+					 * the packet is set
+					 */
+#define	IMR_PSTIMEOUT		BIT(29)	/* Power Save Time Out Interrupt */
+#define	IMR_GTINT4		BIT(28)	/* When GTIMER4 expires,
+					 * this bit is set to 1
+					 */
+#define	IMR_GTINT3		BIT(27)	/* When GTIMER3 expires,
+					 * this bit is set to 1
+					 */
+#define	IMR_TBDER		BIT(26)	/* Transmit Beacon0 Error */
+#define	IMR_TBDOK		BIT(25)	/* Transmit Beacon0 OK	*/
+#define	IMR_TSF_BIT32_TOGGLE	BIT(24)	/* TSF Timer BIT32 toggle ind int */
+#define	IMR_BCNDMAINT0		BIT(20)	/* Beacon DMA Interrupt 0 */
+#define	IMR_BCNDOK0		BIT(16)	/* Beacon Queue DMA OK0	*/
+#define	IMR_HSISR_IND_ON_INT	BIT(15)	/* HSISR Indicator (HSIMR & HSISR is
+					 * true, this bit is set to 1)
+					 */
+#define	IMR_BCNDMAINT_E		BIT(14)	/* Beacon DMA Int Extension for Win7 */
+#define	IMR_ATIMEND		BIT(12)	/* CTWidnow End or ATIM Window End */
+#define	IMR_HISR1_IND_INT	BIT(11)	/* HISR1 Indicator (HISR1 & HIMR1 is
+					 * true, this bit is set to 1)
+					 */
+#define	IMR_C2HCMD		BIT(10)	/* CPU to Host Command INT Status,
+					 * Write 1 clear
+					 */
+#define	IMR_CPWM2		BIT(9)	/* CPU power Mode exchange INT Status,
+					 * Write 1 clear
+					 */
+#define	IMR_CPWM		BIT(8)	/* CPU power Mode exchange INT Status,
+					 * Write 1 clear
+					 */
+#define	IMR_HIGHDOK		BIT(7)	/* High Queue DMA OK	*/
+#define	IMR_MGNTDOK		BIT(6)	/* Management Queue DMA OK */
+#define	IMR_BKDOK		BIT(5)	/* AC_BK DMA OK		*/
+#define	IMR_BEDOK		BIT(4)	/* AC_BE DMA OK	*/
+#define	IMR_VIDOK		BIT(3)	/* AC_VI DMA OK	*/
+#define	IMR_VODOK		BIT(2)	/* AC_VO DMA OK	*/
+#define	IMR_RDU			BIT(1)	/* Rx Descriptor Unavailable */
+#define	IMR_ROK			BIT(0)	/* Receive DMA OK */
+
+/* IMR DW1(0x00B4-00B7) Bit 0-31 */
+#define	IMR_BCNDMAINT7		BIT(27)	/* Beacon DMA Interrupt 7 */
+#define	IMR_BCNDMAINT6		BIT(26)	/* Beacon DMA Interrupt 6 */
+#define	IMR_BCNDMAINT5		BIT(25)	/* Beacon DMA Interrupt 5 */
+#define	IMR_BCNDMAINT4		BIT(24)	/* Beacon DMA Interrupt 4 */
+#define	IMR_BCNDMAINT3		BIT(23)	/* Beacon DMA Interrupt 3 */
+#define	IMR_BCNDMAINT2		BIT(22)	/* Beacon DMA Interrupt 2 */
+#define	IMR_BCNDMAINT1		BIT(21)	/* Beacon DMA Interrupt 1 */
+#define	IMR_BCNDOK7		BIT(20)	/* Beacon Queue DMA OK Interrup 7 */
+#define	IMR_BCNDOK6		BIT(19)	/* Beacon Queue DMA OK Interrup 6 */
+#define	IMR_BCNDOK5		BIT(18)	/* Beacon Queue DMA OK Interrup 5 */
+#define	IMR_BCNDOK4		BIT(17)	/* Beacon Queue DMA OK Interrup 4 */
+#define	IMR_BCNDOK3		BIT(16)	/* Beacon Queue DMA OK Interrup 3 */
+#define	IMR_BCNDOK2		BIT(15)	/* Beacon Queue DMA OK Interrup 2 */
+#define	IMR_BCNDOK1		BIT(14)	/* Beacon Queue DMA OK Interrup 1 */
+#define	IMR_ATIMEND_E		BIT(13)	/* ATIM Window End Extension for Win7 */
+#define	IMR_TXERR		BIT(11)	/* Tx Err Flag Int Status,
+					 * write 1 clear.
+					 */
+#define	IMR_RXERR		BIT(10)	/* Rx Err Flag INT Status,
+					 * Write 1 clear
+					 */
+#define	IMR_TXFOVW		BIT(9)	/* Transmit FIFO Overflow */
+#define	IMR_RXFOVW		BIT(8)	/* Receive FIFO Overflow */
+
+
+#define	HWSET_MAX_SIZE				512
+#define   EFUSE_MAX_SECTION			64
+#define   EFUSE_REAL_CONTENT_LEN		256
+#define	EFUSE_OOB_PROTECT_BYTES			18 /* PG data exclude header,
+						    * dummy 7 bytes frome CP
+						    * test and reserved 1byte.
+						    */
+
+#define	EEPROM_DEFAULT_TSSI			0x0
+#define EEPROM_DEFAULT_TXPOWERDIFF		0x0
+#define EEPROM_DEFAULT_CRYSTALCAP		0x5
+#define EEPROM_DEFAULT_BOARDTYPE		0x02
+#define EEPROM_DEFAULT_TXPOWER			0x1010
+#define	EEPROM_DEFAULT_HT2T_TXPWR		0x10
+
+#define	EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF	0x3
+#define	EEPROM_DEFAULT_THERMALMETER		0x18
+#define	EEPROM_DEFAULT_ANTTXPOWERDIFF		0x0
+#define	EEPROM_DEFAULT_TXPWDIFF_CRYSTALCAP	0x5
+#define	EEPROM_DEFAULT_TXPOWERLEVEL		0x22
+#define	EEPROM_DEFAULT_HT40_2SDIFF		0x0
+#define EEPROM_DEFAULT_HT20_DIFF		2
+#define	EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF	0x3
+#define EEPROM_DEFAULT_HT40_PWRMAXOFFSET	0
+#define EEPROM_DEFAULT_HT20_PWRMAXOFFSET	0
+
+#define RF_OPTION1				0x79
+#define RF_OPTION2				0x7A
+#define RF_OPTION3				0x7B
+#define RF_OPTION4				0x7C
+
+#define EEPROM_DEFAULT_PID			0x1234
+#define EEPROM_DEFAULT_VID			0x5678
+#define EEPROM_DEFAULT_CUSTOMERID		0xAB
+#define EEPROM_DEFAULT_SUBCUSTOMERID		0xCD
+#define EEPROM_DEFAULT_VERSION			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	RTL8188E_EEPROM_ID			0x8129
+
+#define EEPROM_HPON				0x02
+#define EEPROM_CLK				0x06
+#define EEPROM_TESTR				0x08
+
+#define EEPROM_TXPOWERCCK			0x10
+#define	EEPROM_TXPOWERHT40_1S			0x16
+#define EEPROM_TXPOWERHT20DIFF			0x1B
+#define EEPROM_TXPOWER_OFDMDIFF			0x1B
+
+#define	EEPROM_TX_PWR_INX			0x10
+
+#define	EEPROM_CHANNELPLAN			0xB8
+#define	EEPROM_XTAL_88E				0xB9
+#define	EEPROM_THERMAL_METER_88E		0xBA
+#define	EEPROM_IQK_LCK_88E			0xBB
+
+#define	EEPROM_RF_BOARD_OPTION_88E		0xC1
+#define	EEPROM_RF_FEATURE_OPTION_88E		0xC2
+#define	EEPROM_RF_BT_SETTING_88E		0xC3
+#define	EEPROM_VERSION				0xC4
+#define	EEPROM_CUSTOMER_ID			0xC5
+#define	EEPROM_RF_ANTENNA_OPT_88E		0xC9
+
+#define	EEPROM_MAC_ADDR				0xD0
+#define EEPROM_VID				0xD6
+#define EEPROM_DID				0xD8
+#define EEPROM_SVID				0xDA
+#define EEPROM_SMID				0xDC
+
+#define	STOPBECON				BIT(6)
+#define	STOPHIGHT				BIT(5)
+#define	STOPMGT					BIT(4)
+#define	STOPVO					BIT(3)
+#define	STOPVI					BIT(2)
+#define	STOPBE					BIT(1)
+#define	STOPBK					BIT(0)
+
+#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_CBSSID				RCR_CBSSID_DATA
+#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
+
+#define RSV_CTRL				0x001C
+#define RD_CTRL					0x0524
+
+#define REG_USB_INFO				0xFE17
+#define REG_USB_SPECIAL_OPTION			0xFE55
+#define REG_USB_DMA_AGG_TO			0xFE5B
+#define REG_USB_AGG_TO				0xFE5C
+#define REG_USB_AGG_TH				0xFE5D
+
+#define REG_USB_VID				0xFE60
+#define REG_USB_PID				0xFE62
+#define REG_USB_OPTIONAL			0xFE64
+#define REG_USB_CHIRP_K				0xFE65
+#define REG_USB_PHY				0xFE66
+#define REG_USB_MAC_ADDR			0xFE70
+#define REG_USB_HRPWM				0xFE58
+#define REG_USB_HCPWM				0xFE57
+
+#define SW18_FPWM				BIT(3)
+
+#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)
+
+#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)
+
+#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)
+
+#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)
+
+#define	BOOT_FROM_EEPROM			BIT(4)
+#define	EEPROM_EN				BIT(5)
+
+#define AFE_BGEN				BIT(0)
+#define AFE_MBEN				BIT(1)
+#define MAC_ID_EN				BIT(7)
+
+#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)
+
+#define RF_EN					BIT(0)
+#define RF_RSTB					BIT(1)
+#define RF_SDMRSTB				BIT(2)
+
+#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)
+
+#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)
+
+#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)
+
+#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)
+
+#define ALD_EN					BIT(18)
+#define EF_PD					BIT(19)
+#define EF_FLAG					BIT(31)
+
+#define EF_TRPT					BIT(7)
+#define LDOE25_EN				BIT(31)
+
+#define RSM_EN					BIT(0)
+#define TIMER_EN				BIT(4)
+
+#define TRSW0EN					BIT(2)
+#define TRSW1EN					BIT(3)
+#define EROM_EN					BIT(4)
+#define ENBT					BIT(5)
+#define ENUART					BIT(8)
+#define UART_910				BIT(9)
+#define ENPMAC					BIT(10)
+#define SIC_SWRST				BIT(11)
+#define ENSIC					BIT(12)
+#define SIC_23					BIT(13)
+#define ENHDP					BIT(14)
+#define SIC_LBK					BIT(15)
+
+#define LED0PL					BIT(4)
+#define LED1PL					BIT(12)
+#define LED0DIS					BIT(7)
+
+#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 CPRST					BIT(23)
+
+#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 VENDOR_ID				BIT(19)
+#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)
+
+#define CHIP_VER_RTL_MASK			0xF000
+#define CHIP_VER_RTL_SHIFT			12
+
+#define REG_LBMODE				(REG_CR + 3)
+
+#define HCI_TXDMA_EN				BIT(0)
+#define HCI_RXDMA_EN				BIT(1)
+#define TXDMA_EN				BIT(2)
+#define RXDMA_EN				BIT(3)
+#define PROTOCOL_EN				BIT(4)
+#define SCHEDULE_EN				BIT(5)
+#define MACTXEN					BIT(6)
+#define MACRXEN					BIT(7)
+#define ENSWBCN					BIT(8)
+#define ENSEC					BIT(9)
+
+#define _NETTYPE(x)				(((x) & 0x3) << 16)
+#define MASK_NETTYPE				0x30000
+#define NT_NO_LINK				0x0
+#define NT_LINK_AD_HOC				0x1
+#define NT_LINK_AP				0x2
+#define NT_AS_AP				0x3
+
+#define _LBMODE(x)				(((x) & 0xF) << 24)
+#define MASK_LBMODE				0xF000000
+#define LOOPBACK_NORMAL				0x0
+#define LOOPBACK_IMMEDIATELY			0xB
+#define LOOPBACK_MAC_DELAY			0x3
+#define LOOPBACK_PHY				0x1
+#define LOOPBACK_DMA				0x7
+
+#define GET_RX_PAGE_SIZE(value)		((value) & 0xF)
+#define GET_TX_PAGE_SIZE(value)		(((value) & 0xF0) >> 4)
+#define _PSRX_MASK				0xF
+#define _PSTX_MASK				0xF0
+#define _PSRX(x)				(x)
+#define _PSTX(x)				((x) << 4)
+
+#define PBP_64					0x0
+#define PBP_128					0x1
+#define PBP_256					0x2
+#define PBP_512					0x3
+#define PBP_1024				0x4
+
+#define RXDMA_ARBBW_EN				BIT(0)
+#define RXSHFT_EN				BIT(1)
+#define RXDMA_AGG_EN				BIT(2)
+#define QS_VO_QUEUE				BIT(8)
+#define QS_VI_QUEUE				BIT(9)
+#define QS_BE_QUEUE				BIT(10)
+#define QS_BK_QUEUE				BIT(11)
+#define QS_MANAGER_QUEUE			BIT(12)
+#define QS_HIGH_QUEUE				BIT(13)
+
+#define HQSEL_VOQ				BIT(0)
+#define HQSEL_VIQ				BIT(1)
+#define HQSEL_BEQ				BIT(2)
+#define HQSEL_BKQ				BIT(3)
+#define HQSEL_MGTQ				BIT(4)
+#define HQSEL_HIQ				BIT(5)
+
+#define _TXDMA_HIQ_MAP(x)			(((x)&0x3) << 14)
+#define _TXDMA_MGQ_MAP(x)			(((x)&0x3) << 12)
+#define _TXDMA_BKQ_MAP(x)			(((x)&0x3) << 10)
+#define _TXDMA_BEQ_MAP(x)			(((x)&0x3) << 8)
+#define _TXDMA_VIQ_MAP(x)			(((x)&0x3) << 6)
+#define _TXDMA_VOQ_MAP(x)			(((x)&0x3) << 4)
+
+#define QUEUE_LOW				1
+#define QUEUE_NORMAL				2
+#define QUEUE_HIGH				3
+
+#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)
+
+#define BB_WRITE_READ_MASK			(BIT(31) | BIT(30))
+#define BB_WRITE_EN				BIT(30)
+#define BB_READ_EN				BIT(31)
+
+#define _HPQ(x)					((x) & 0xFF)
+#define _LPQ(x)					(((x) & 0xFF) << 8)
+#define _PUBQ(x)				(((x) & 0xFF) << 16)
+#define _NPQ(x)					((x) & 0xFF)
+
+#define HPQ_PUBLIC_DIS				BIT(24)
+#define LPQ_PUBLIC_DIS				BIT(25)
+#define LD_RQPN					BIT(31)
+
+#define BCN_VALID				BIT(16)
+#define BCN_HEAD(x)				(((x) & 0xFF) << 8)
+#define	BCN_HEAD_MASK				0xFF00
+
+#define BLK_DESC_NUM_SHIFT			4
+#define BLK_DESC_NUM_MASK			0xF
+
+#define DROP_DATA_EN				BIT(9)
+
+#define EN_AMPDU_RTY_NEW			BIT(7)
+
+#define _INIRTSMCS_SEL(x)			((x) & 0x3F)
+
+#define _SPEC_SIFS_CCK(x)			((x) & 0xFF)
+#define _SPEC_SIFS_OFDM(x)			(((x) & 0xFF) << 8)
+
+#define RATE_REG_BITMAP_ALL			0xFFFFF
+
+#define _RRSC_BITMAP(x)				((x) & 0xFFFFF)
+
+#define _RRSR_RSC(x)				(((x) & 0x3) << 21)
+#define RRSR_RSC_RESERVED			0x0
+#define RRSR_RSC_UPPER_SUBCHANNEL		0x1
+#define RRSR_RSC_LOWER_SUBCHANNEL		0x2
+#define RRSR_RSC_DUPLICATE_MODE			0x3
+
+#define USE_SHORT_G1				BIT(20)
+
+#define _AGGLMT_MCS0(x)				((x) & 0xF)
+#define _AGGLMT_MCS1(x)				(((x) & 0xF) << 4)
+#define _AGGLMT_MCS2(x)				(((x) & 0xF) << 8)
+#define _AGGLMT_MCS3(x)				(((x) & 0xF) << 12)
+#define _AGGLMT_MCS4(x)				(((x) & 0xF) << 16)
+#define _AGGLMT_MCS5(x)				(((x) & 0xF) << 20)
+#define _AGGLMT_MCS6(x)				(((x) & 0xF) << 24)
+#define _AGGLMT_MCS7(x)				(((x) & 0xF) << 28)
+
+#define	RETRY_LIMIT_SHORT_SHIFT			8
+#define	RETRY_LIMIT_LONG_SHIFT			0
+
+#define _DARF_RC1(x)				((x) & 0x1F)
+#define _DARF_RC2(x)				(((x) & 0x1F) << 8)
+#define _DARF_RC3(x)				(((x) & 0x1F) << 16)
+#define _DARF_RC4(x)				(((x) & 0x1F) << 24)
+#define _DARF_RC5(x)				((x) & 0x1F)
+#define _DARF_RC6(x)				(((x) & 0x1F) << 8)
+#define _DARF_RC7(x)				(((x) & 0x1F) << 16)
+#define _DARF_RC8(x)				(((x) & 0x1F) << 24)
+
+#define _RARF_RC1(x)				((x) & 0x1F)
+#define _RARF_RC2(x)				(((x) & 0x1F) << 8)
+#define _RARF_RC3(x)				(((x) & 0x1F) << 16)
+#define _RARF_RC4(x)				(((x) & 0x1F) << 24)
+#define _RARF_RC5(x)				((x) & 0x1F)
+#define _RARF_RC6(x)				(((x) & 0x1F) << 8)
+#define _RARF_RC7(x)				(((x) & 0x1F) << 16)
+#define _RARF_RC8(x)				(((x) & 0x1F) << 24)
+
+#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
+
+#define _AIFS(x)				(x)
+#define _ECW_MAX_MIN(x)				((x) << 8)
+#define _TXOP_LIMIT(x)				((x) << 16)
+
+#define _BCNIFS(x)				((x) & 0xFF)
+#define _BCNECW(x)				((((x) & 0xF)) << 8)
+
+#define _LRL(x)					((x) & 0x3F)
+#define _SRL(x)					(((x) & 0x3F) << 8)
+
+#define _SIFS_CCK_CTX(x)			((x) & 0xFF)
+#define _SIFS_CCK_TRX(x)			(((x) & 0xFF) << 8);
+
+#define _SIFS_OFDM_CTX(x)			((x) & 0xFF)
+#define _SIFS_OFDM_TRX(x)			(((x) & 0xFF) << 8);
+
+#define _TBTT_PROHIBIT_HOLD(x)			(((x) & 0xFF) << 8)
+
+#define DIS_EDCA_CNT_DWN			BIT(11)
+
+#define EN_MBSSID				BIT(1)
+#define EN_TXBCN_RPT				BIT(2)
+#define	EN_BCN_FUNCTION				BIT(3)
+
+#define TSFTR_RST				BIT(0)
+#define TSFTR1_RST				BIT(1)
+
+#define STOP_BCNQ				BIT(6)
+
+#define	DIS_TSF_UDT0_NORMAL_CHIP		BIT(4)
+#define	DIS_TSF_UDT0_TEST_CHIP			BIT(5)
+
+#define	ACMHW_HWEN				BIT(0)
+#define	ACMHW_BEQEN				BIT(1)
+#define	ACMHW_VIQEN				BIT(2)
+#define	ACMHW_VOQEN				BIT(3)
+#define	ACMHW_BEQSTATUS				BIT(4)
+#define	ACMHW_VIQSTATUS				BIT(5)
+#define	ACMHW_VOQSTATUS				BIT(6)
+
+#define APSDOFF					BIT(6)
+#define APSDOFF_STATUS				BIT(7)
+
+#define BW_20MHZ				BIT(2)
+
+#define RATE_BITMAP_ALL				0xFFFFF
+
+#define RATE_RRSR_CCK_ONLY_1M			0xFFFF1
+
+#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)
+
+#define AAP					BIT(0)
+#define APM					BIT(1)
+#define AM					BIT(2)
+#define AB					BIT(3)
+#define ADD3					BIT(4)
+#define APWRMGT					BIT(5)
+#define CBSSID					BIT(6)
+#define CBSSID_DATA				BIT(6)
+#define CBSSID_BCN				BIT(7)
+#define ACRC32					BIT(8)
+#define AICV					BIT(9)
+#define ADF					BIT(11)
+#define ACF					BIT(12)
+#define AMF					BIT(13)
+#define HTC_LOC_CTRL				BIT(14)
+#define UC_DATA_EN				BIT(16)
+#define BM_DATA_EN				BIT(17)
+#define MFBEN					BIT(22)
+#define LSIGEN					BIT(23)
+#define ENMBID					BIT(24)
+#define APP_BASSN				BIT(27)
+#define APP_PHYSTS				BIT(28)
+#define APP_ICV					BIT(29)
+#define APP_MIC					BIT(30)
+#define APP_FCS					BIT(31)
+
+#define _MIN_SPACE(x)				((x) & 0x7)
+#define _SHORT_GI_PADDING(x)			(((x) & 0x1F) << 3)
+
+#define RXERR_TYPE_OFDM_PPDU			0
+#define RXERR_TYPE_OFDM_FALSE_ALARM		1
+#define	RXERR_TYPE_OFDM_MPDU_OK			2
+#define RXERR_TYPE_OFDM_MPDU_FAIL		3
+#define RXERR_TYPE_CCK_PPDU			4
+#define RXERR_TYPE_CCK_FALSE_ALARM		5
+#define RXERR_TYPE_CCK_MPDU_OK			6
+#define RXERR_TYPE_CCK_MPDU_FAIL		7
+#define RXERR_TYPE_HT_PPDU			8
+#define RXERR_TYPE_HT_FALSE_ALARM		9
+#define RXERR_TYPE_HT_MPDU_TOTAL		10
+#define RXERR_TYPE_HT_MPDU_OK			11
+#define RXERR_TYPE_HT_MPDU_FAIL			12
+#define RXERR_TYPE_RX_FULL_DROP			15
+
+#define RXERR_COUNTER_MASK			0xFFFFF
+#define RXERR_RPT_RST				BIT(27)
+#define _RXERR_RPT_SEL(type)			((type) << 28)
+
+#define	SCR_TXUSEDK				BIT(0)
+#define	SCR_RXUSEDK				BIT(1)
+#define	SCR_TXENCENABLE				BIT(2)
+#define	SCR_RXDECENABLE				BIT(3)
+#define	SCR_SKBYA2				BIT(4)
+#define	SCR_NOSKMC				BIT(5)
+#define SCR_TXBCUSEDK				BIT(6)
+#define SCR_RXBCUSEDK				BIT(7)
+
+#define USB_IS_HIGH_SPEED			0
+#define USB_IS_FULL_SPEED			1
+#define USB_SPEED_MASK				BIT(5)
+
+#define USB_NORMAL_SIE_EP_MASK			0xF
+#define USB_NORMAL_SIE_EP_SHIFT			4
+
+#define USB_TEST_EP_MASK			0x30
+#define USB_TEST_EP_SHIFT			4
+
+#define USB_AGG_EN				BIT(3)
+
+#define MAC_ADDR_LEN				6
+#define LAST_ENTRY_OF_TX_PKT_BUFFER		175/*255    88e*/
+
+#define POLLING_LLT_THRESHOLD			20
+#define POLLING_READY_TIMEOUT_COUNT		3000
+
+#define	MAX_MSS_DENSITY_2T			0x13
+#define	MAX_MSS_DENSITY_1T			0x0A
+
+#define EPROM_CMD_OPERATING_MODE_MASK		((1<<7)|(1<<6))
+#define EPROM_CMD_CONFIG			0x3
+#define EPROM_CMD_LOAD				1
+
+#define	HWSET_MAX_SIZE_92S			HWSET_MAX_SIZE
+
+#define	HAL_8192C_HW_GPIO_WPS_BIT		BIT(2)
+
+#define	RPMAC_RESET				0x100
+#define	RPMAC_TXSTART				0x104
+#define	RPMAC_TXLEGACYSIG			0x108
+#define	RPMAC_TXHTSIG1				0x10c
+#define	RPMAC_TXHTSIG2				0x110
+#define	RPMAC_PHYDEBUG				0x114
+#define	RPMAC_TXPACKETNUM			0x118
+#define	RPMAC_TXIDLE				0x11c
+#define	RPMAC_TXMACHEADER0			0x120
+#define	RPMAC_TXMACHEADER1			0x124
+#define	RPMAC_TXMACHEADER2			0x128
+#define	RPMAC_TXMACHEADER3			0x12c
+#define	RPMAC_TXMACHEADER4			0x130
+#define	RPMAC_TXMACHEADER5			0x134
+#define	RPMAC_TXDADATYPE			0x138
+#define	RPMAC_TXRANDOMSEED			0x13c
+#define	RPMAC_CCKPLCPPREAMBLE			0x140
+#define	RPMAC_CCKPLCPHEADER			0x144
+#define	RPMAC_CCKCRC16				0x148
+#define	RPMAC_OFDMRXCRC32OK			0x170
+#define	RPMAC_OFDMRXCRC32Er			0x174
+#define	RPMAC_OFDMRXPARITYER			0x178
+#define	RPMAC_OFDMRXCRC8ER			0x17c
+#define	RPMAC_CCKCRXRC16ER			0x180
+#define	RPMAC_CCKCRXRC32ER			0x184
+#define	RPMAC_CCKCRXRC32OK			0x188
+#define	RPMAC_TXSTATUS				0x18c
+
+#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_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	TRANSCEIVEA_HSPI_READBACK		0x8b8
+#define	TRANSCEIVEB_HSPI_READBACK		0x8bc
+#define	REG_SC_CNT				0x8c4
+#define	RFPGA0_XAB_RFINTERFACERB		0x8e0
+#define	RFPGA0_XCD_RFINTERFACERB		0x8e4
+
+#define	RFPGA1_RFMOD				0x900
+
+#define	RFPGA1_TXBLOCK				0x904
+#define	RFPGA1_DEBUGSELECT			0x908
+#define	RFPGA1_TXINFO				0x90c
+
+#define	RCCK0_SYSTEM				0xa00
+
+#define	RCCK0_AFESETTING			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
+#define	RCCK0_CCA_CNT				0xa60
+
+
+/* PageB(0xB00) */
+#define	RPDP_ANTA				0xb00
+#define	RPDP_ANTA_4				0xb04
+#define	RPDP_ANTA_8				0xb08
+#define	RPDP_ANTA_C				0xb0c
+#define	RPDP_ANTA_10				0xb10
+#define	RPDP_ANTA_14				0xb14
+#define	RPDP_ANTA_18				0xb18
+#define	RPDP_ANTA_1C				0xb1c
+#define	RPDP_ANTA_20				0xb20
+#define	RPDP_ANTA_24				0xb24
+
+#define	RCONFIG_PMPD_ANTA			0xb28
+#define	RCONFIG_RAM64X16			0xb2c
+
+#define	RBNDA					0xb30
+#define	RHSSIPAR				0xb34
+
+#define	RCONFIG_ANTA				0xb68
+#define	RCONFIG_ANTB				0xb6c
+
+#define	RPDP_ANTB				0xb70
+#define	RPDP_ANTB_4				0xb74
+#define	RPDP_ANTB_8				0xb78
+#define	RPDP_ANTB_C				0xb7c
+#define	RPDP_ANTB_10				0xb80
+#define	RPDP_ANTB_14				0xb84
+#define	RPDP_ANTB_18				0xb88
+#define	RPDP_ANTB_1C				0xb8c
+#define	RPDP_ANTB_20				0xb90
+#define	RPDP_ANTB_24				0xb94
+
+#define	RCONFIG_PMPD_ANTB			0xb98
+
+#define	RBNDB					0xba0
+
+#define	RAPK					0xbd8
+#define	rPm_Rx0_AntA				0xbdc
+#define	rPm_Rx1_AntA				0xbe0
+#define	rPm_Rx2_AntA				0xbe4
+#define	rPm_Rx3_AntA				0xbe8
+#define	rPm_Rx0_AntB				0xbec
+#define	rPm_Rx1_AntB				0xbf0
+#define	rPm_Rx2_AntB				0xbf4
+#define	rPm_Rx3_AntB				0xbf8
+
+/*Page C*/
+#define	ROFDM0_LSTF				0xc00
+
+#define	ROFDM0_TRXPATHENABLE			0xc04
+#define	ROFDM0_TRMUXPAR				0xc08
+#define	ROFDM0_TRSWISOLATION			0xc0c
+
+#define	ROFDM0_XARXAFE				0xc10
+#define	ROFDM0_XARXIQIMBAL			0xc14
+#define	ROFDM0_XBRXAFE				0xc18
+#define	ROFDM0_XBRXIQIMBAL			0xc1c
+#define	ROFDM0_XCRXAFE				0xc20
+#define	ROFDM0_XCRXIQIMBAL			0xc24
+#define	ROFDM0_XDRXAFE				0xc28
+#define	ROFDM0_XDRXIQIMBAL			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_CCADROPTHRES			0xc48
+#define	ROFDM0_ECCATHRES			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_XATXIQIMBAL			0xc80
+#define	ROFDM0_XATXAFE				0xc84
+#define	ROFDM0_XBTXIQIMBAL			0xc88
+#define	ROFDM0_XBTXAFE				0xc8c
+#define	ROFDM0_XCTXIQIMBAL			0xc90
+#define	ROFDM0_XCTXAFE				0xc94
+#define	ROFDM0_XDTXIQIMBAL			0xc98
+#define	ROFDM0_XDTXAFE				0xc9c
+
+#define ROFDM0_RXIQEXTANTA			0xca0
+#define	ROFDM0_TXCOEFF1				0xca4
+#define	ROFDM0_TXCOEFF2				0xca8
+#define	ROFDM0_TXCOEFF3				0xcac
+#define	ROFDM0_TXCOEFF4				0xcb0
+#define	ROFDM0_TXCOEFF5				0xcb4
+#define	ROFDM0_TXCOEFF6				0xcb8
+
+#define	ROFDM0_RXHPPARAMETER			0xce0
+#define	ROFDM0_TXPSEUDONOISEWGT			0xce4
+#define	ROFDM0_FRAMESYNC			0xcf0
+#define	ROFDM0_DFSREPORT			0xcf4
+
+
+#define	ROFDM1_LSTF				0xd00
+#define	ROFDM1_TRXPATHENABLE			0xd04
+
+#define	ROFDM1_CF0				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_TAILCF0AB				0xdbc
+#define	ROFDM_TAILCF0CD				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
+
+#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
+
+#define	RFPGA0_IQK				0xe28
+#define	RTX_IQK_TONE_A				0xe30
+#define	RRX_IQK_TONE_A				0xe34
+#define	RTX_IQK_PI_A				0xe38
+#define	RRX_IQK_PI_A				0xe3c
+
+#define	RTX_IQK					0xe40
+#define	RRX_IQK					0xe44
+#define	RIQK_AGC_PTS				0xe48
+#define	RIQK_AGC_RSP				0xe4c
+#define	RTX_IQK_TONE_B				0xe50
+#define	RRX_IQK_TONE_B				0xe54
+#define	RTX_IQK_PI_B				0xe58
+#define	RRX_IQK_PI_B				0xe5c
+#define	RIQK_AGC_CONT				0xe60
+
+#define	RBLUE_TOOTH				0xe6c
+#define	RRX_WAIT_CCA				0xe70
+#define	RTX_CCK_RFON				0xe74
+#define	RTX_CCK_BBON				0xe78
+#define	RTX_OFDM_RFON				0xe7c
+#define	RTX_OFDM_BBON				0xe80
+#define	RTX_TO_RX				0xe84
+#define	RTX_TO_TX				0xe88
+#define	RRX_CCK					0xe8c
+
+#define	RTX_POWER_BEFORE_IQK_A			0xe94
+#define	RTX_POWER_AFTER_IQK_A			0xe9c
+
+#define	RRX_POWER_BEFORE_IQK_A			0xea0
+#define	RRX_POWER_BEFORE_IQK_A_2		0xea4
+#define	RRX_POWER_AFTER_IQK_A			0xea8
+#define	RRX_POWER_AFTER_IQK_A_2			0xeac
+
+#define	RTX_POWER_BEFORE_IQK_B			0xeb4
+#define	RTX_POWER_AFTER_IQK_B			0xebc
+
+#define	RRX_POWER_BEFORE_IQK_B			0xec0
+#define	RRX_POWER_BEFORE_IQK_B_2		0xec4
+#define	RRX_POWER_AFTER_IQK_B			0xec8
+#define	RRX_POWER_AFTER_IQK_B_2			0xecc
+
+#define	RRX_OFDM				0xed0
+#define	RRX_WAIT_RIFS				0xed4
+#define	RRX_TO_RX				0xed8
+#define	RSTANDBY				0xedc
+#define	RSLEEP					0xee0
+#define	RPMPD_ANAEN				0xeec
+
+#define	RZEBRA1_HSSIENABLE			0x0
+#define	RZEBRA1_TRXENABLE1			0x1
+#define	RZEBRA1_TRXENABLE2			0x2
+#define	RZEBRA1_AGC				0x4
+#define	RZEBRA1_CHARGEPUMP			0x5
+#define	RZEBRA1_CHANNEL				0x7
+
+#define	RZEBRA1_TXGAIN				0x8
+#define	RZEBRA1_TXLPF				0x9
+#define	RZEBRA1_RXLPF				0xb
+#define	RZEBRA1_RXHPFCORNER			0xc
+
+#define	RGLOBALCTRL				0
+#define	RRTL8256_TXLPF				19
+#define	RRTL8256_RXLPF				11
+#define	RRTL8258_TXLPF				0x11
+#define	RRTL8258_RXLPF				0x13
+#define	RRTL8258_RSSILPF			0xa
+
+#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
+
+#define	RF_TX_BIAS_A				0x35
+#define	RF_TX_BIAS_D				0x36
+#define	RF_LOBF_9				0x38
+#define	RF_RXRF_A3				0x3C
+#define	RF_TRSW					0x3F
+
+#define	RF_TXRF_A2				0x41
+#define	RF_TXPA_G4				0x46
+#define	RF_TXPA_A4				0x4B
+
+#define	RF_WE_LUT				0xEF
+
+#define	BBBRESETB				0x100
+#define	BGLOBALRESETB				0x200
+#define	BOFDMTXSTART				0x4
+#define	BCCKTXSTART				0x8
+#define	BCRC32DEBUG				0x100
+#define	BPMACLOOPBACK				0x10
+#define	BTXLSIG					0xffffff
+#define	BOFDMTXRATE				0xf
+#define	BOFDMTXRESERVED				0x10
+#define	BOFDMTXLENGTH				0x1ffe0
+#define	BOFDMTXPARITY				0x20000
+#define	BTXHTSIG1				0xffffff
+#define	BTXHTMCSRATE				0x7f
+#define	BTXHTBW					0x80
+#define	BTXHTLENGTH				0xffff00
+#define	BTXHTSIG2				0xffffff
+#define	BTXHTSMOOTHING				0x1
+#define	BTXHTSOUNDING				0x2
+#define	BTXHTRESERVED				0x4
+#define	BTXHTAGGREATION				0x8
+#define	BTXHTSTBC				0x30
+#define	BTXHTADVANCECODING			0x40
+#define	BTXHTSHORTGI				0x80
+#define	BTXHTNUMBERHT_LTF			0x300
+#define	BTXHTCRC8				0x3fc00
+#define	BCOUNTERRESET				0x10000
+#define	BNUMOFOFDMTX				0xffff
+#define	BNUMOFCCKTX				0xffff0000
+#define	BTXIDLEINTERVAL				0xffff
+#define	BOFDMSERVICE				0xffff0000
+#define	BTXMACHEADER				0xffffffff
+#define	BTXDATAINIT				0xff
+#define	BTXHTMODE				0x100
+#define	BTXDATATYPE				0x30000
+#define	BTXRANDOMSEED				0xffffffff
+#define	BCCKTXPREAMBLE				0x1
+#define	BCCKTXSFD				0xffff0000
+#define	BCCKTXSIG				0xff
+#define	BCCKTXSERVICE				0xff00
+#define	BCCKLENGTHEXT				0x8000
+#define	BCCKTXLENGHT				0xffff0000
+#define	BCCKTXCRC16				0xffff
+#define	BCCKTXSTATUS				0x1
+#define	BOFDMTXSTATUS				0x2
+#define IS_BB_REG_OFFSET_92S(_offset)	\
+	((_offset >= 0x800) && (_offset <= 0xfff))
+
+#define	BRFMOD					0x1
+#define	BJAPANMODE				0x2
+#define	BCCKTXSC				0x30
+#define	BCCKEN					0x1000000
+#define	BOFDMEN					0x2000000
+
+#define	BOFDMRXADCPHASE				0x10000
+#define	BOFDMTXDACPHASE				0x40000
+#define	BXATXAGC				0x3f
+
+#define	BXBTXAGC				0xf00
+#define	BXCTXAGC				0xf000
+#define	BXDTXAGC				0xf0000
+
+#define	BPASTART				0xf0000000
+#define	BTRSTART				0x00f00000
+#define	BRFSTART				0x0000f000
+#define	BBBSTART				0x000000f0
+#define	BBBCCKSTART				0x0000000f
+#define	BPAEND					0xf
+#define	BTREND					0x0f000000
+#define	BRFEND					0x000f0000
+#define	BCCAMASK				0x000000f0
+#define	BR2RCCAMASK				0x00000f00
+#define	BHSSI_R2TDELAY				0xf8000000
+#define	BHSSI_T2RDELAY				0xf80000
+#define	BCONTXHSSI				0x400
+#define	BIGFROMCCK				0x200
+#define	BAGCADDRESS				0x3f
+#define	BRXHPTX					0x7000
+#define	BRXHP2RX				0x38000
+#define	BRXHPCCKINI				0xc0000
+#define	BAGCTXCODE				0xc00000
+#define	BAGCRXCODE				0x300000
+
+#define	B3WIREDATALENGTH			0x800
+#define	B3WIREADDREAALENGTH			0x400
+
+#define	B3WIRERFPOWERDOWN			0x1
+#define	B5GPAPEPOLARITY				0x40000000
+#define	B2GPAPEPOLARITY				0x80000000
+#define	BRFSW_TXDEFAULTANT			0x3
+#define	BRFSW_TXOPTIONANT			0x30
+#define	BRFSW_RXDEFAULTANT			0x300
+#define	BRFSW_RXOPTIONANT			0x3000
+#define	BRFSI_3WIREDATA				0x1
+#define	BRFSI_3WIRECLOCK			0x2
+#define	BRFSI_3WIRELOAD				0x4
+#define	BRFSI_3WIRERW				0x8
+#define	BRFSI_3WIRE				0xf
+
+#define	BRFSI_RFENV				0x10
+
+#define	BRFSI_TRSW				0x20
+#define	BRFSI_TRSWB				0x40
+#define	BRFSI_ANTSW				0x100
+#define	BRFSI_ANTSWB				0x200
+#define	BRFSI_PAPE				0x400
+#define	BRFSI_PAPE5G				0x800
+#define	BBANDSELECT				0x1
+#define	BHTSIG2_GI				0x80
+#define	BHTSIG2_SMOOTHING			0x01
+#define	BHTSIG2_SOUNDING			0x02
+#define	BHTSIG2_AGGREATON			0x08
+#define	BHTSIG2_STBC				0x30
+#define	BHTSIG2_ADVCODING			0x40
+#define	BHTSIG2_NUMOFHTLTF			0x300
+#define	BHTSIG2_CRC8				0x3fc
+#define	BHTSIG1_MCS				0x7f
+#define	BHTSIG1_BANDWIDTH			0x80
+#define	BHTSIG1_HTLENGTH			0xffff
+#define	BLSIG_RATE				0xf
+#define	BLSIG_RESERVED				0x10
+#define	BLSIG_LENGTH				0x1fffe
+#define	BLSIG_PARITY				0x20
+#define	BCCKRXPHASE				0x4
+
+#define	BLSSIREADADDRESS			0x7f800000
+#define	BLSSIREADEDGE				0x80000000
+
+#define	BLSSIREADBACKDATA			0xfffff
+
+#define	BLSSIREADOKFLAG				0x1000
+#define	BCCKSAMPLERATE				0x8
+#define	BREGULATOR0STANDBY			0x1
+#define	BREGULATORPLLSTANDBY			0x2
+#define	BREGULATOR1STANDBY			0x4
+#define	BPLLPOWERUP				0x8
+#define	BDPLLPOWERUP				0x10
+#define	BDA10POWERUP				0x20
+#define	BAD7POWERUP				0x200
+#define	BDA6POWERUP				0x2000
+#define	BXTALPOWERUP				0x4000
+#define	B40MDCLKPOWERUP				0x8000
+#define	BDA6DEBUGMODE				0x20000
+#define	BDA6SWING				0x380000
+
+#define	BADCLKPHASE				0x4000000
+#define	B80MCLKDELAY				0x18000000
+#define	BAFEWATCHDOGENABLE			0x20000000
+
+#define	BXTALCAP01				0xc0000000
+#define	BXTALCAP23				0x3
+#define	BXTALCAP92X				0x0f000000
+#define BXTALCAP				0x0f000000
+
+#define	BINTDIFCLKENABLE			0x400
+#define	BEXTSIGCLKENABLE			0x800
+#define	BBANDGAP_MBIAS_POWERUP			0x10000
+#define	BAD11SH_GAIN				0xc0000
+#define	BAD11NPUT_RANGE				0x700000
+#define	BAD110P_CURRENT				0x3800000
+#define	BLPATH_LOOPBACK				0x4000000
+#define	BQPATH_LOOPBACK				0x8000000
+#define	BAFE_LOOPBACK				0x10000000
+#define	BDA10_SWING				0x7e0
+#define	BDA10_REVERSE				0x800
+#define	BDA_CLK_SOURCE				0x1000
+#define	BDA7INPUT_RANGE				0x6000
+#define	BDA7_GAIN				0x38000
+#define	BDA7OUTPUT_CM_MODE			0x40000
+#define	BDA7INPUT_CM_MODE			0x380000
+#define	BDA7CURRENT				0xc00000
+#define	BREGULATOR_ADJUST			0x7000000
+#define	BAD11POWERUP_ATTX			0x1
+#define	BDA10PS_ATTX				0x10
+#define	BAD11POWERUP_ATRX			0x100
+#define	BDA10PS_ATRX				0x1000
+#define	BCCKRX_AGC_FORMAT			0x200
+#define	BPSDFFT_SAMPLE_POINT			0xc000
+#define	BPSD_AVERAGE_NUM			0x3000
+#define	BIQPATH_CONTROL				0xc00
+#define	BPSD_FREQ				0x3ff
+#define	BPSD_ANTENNA_PATH			0x30
+#define	BPSD_IQ_SWITCH				0x40
+#define	BPSD_RX_TRIGGER				0x400000
+#define	BPSD_TX_TRIGGERCW			0x80000000
+#define	BPSD_SINE_TONE_SCALE			0x7f000000
+#define	BPSD_REPORT				0xffff
+
+#define	BOFDM_TXSC				0x30000000
+#define	BCCK_TXON				0x1
+#define	BOFDM_TXON				0x2
+#define	BDEBUG_PAGE				0xfff
+#define	BDEBUG_ITEM				0xff
+#define	BANTL					0x10
+#define	BANT_NONHT				0x100
+#define	BANT_HT1				0x1000
+#define	BANT_HT2				0x10000
+#define	BANT_HT1S1				0x100000
+#define	BANT_NONHTS1				0x1000000
+
+#define	BCCK_BBMODE				0x3
+#define	BCCK_TXPOWERSAVING			0x80
+#define	BCCK_RXPOWERSAVING			0x40
+
+#define	BCCK_SIDEBAND				0x10
+
+#define	BCCK_SCRAMBLE				0x8
+#define	BCCK_ANTDIVERSITY			0x8000
+#define	BCCK_CARRIER_RECOVERY			0x4000
+#define	BCCK_TXRATE				0x3000
+#define	BCCK_DCCANCEL				0x0800
+#define	BCCK_ISICANCEL				0x0400
+#define	BCCK_MATCH_FILTER			0x0200
+#define	BCCK_EQUALIZER				0x0100
+#define	BCCK_PREAMBLE_DETECT			0x800000
+#define	BCCK_FAST_FALSECCA			0x400000
+#define	BCCK_CH_ESTSTART			0x300000
+#define	BCCK_CCA_COUNT				0x080000
+#define	BCCK_CS_LIM				0x070000
+#define	BCCK_BIST_MODE				0x80000000
+#define	BCCK_CCAMASK				0x40000000
+#define	BCCK_TX_DAC_PHASE			0x4
+#define	BCCK_RX_ADC_PHASE			0x20000000
+#define	BCCKR_CP_MODE				0x0100
+#define	BCCK_TXDC_OFFSET			0xf0
+#define	BCCK_RXDC_OFFSET			0xf
+#define	BCCK_CCA_MODE				0xc000
+#define	BCCK_FALSECS_LIM			0x3f00
+#define	BCCK_CS_RATIO				0xc00000
+#define	BCCK_CORGBIT_SEL			0x300000
+#define	BCCK_PD_LIM				0x0f0000
+#define	BCCK_NEWCCA				0x80000000
+#define	BCCK_RXHP_OF_IG				0x8000
+#define	BCCK_RXIG				0x7f00
+#define	BCCK_LNA_POLARITY			0x800000
+#define	BCCK_RX1ST_BAIN				0x7f0000
+#define	BCCK_RF_EXTEND				0x20000000
+#define	BCCK_RXAGC_SATLEVEL			0x1f000000
+#define	BCCK_RXAGC_SATCOUNT			0xe0
+#define	BCCKRXRFSETTLE				0x1f
+#define	BCCK_FIXED_RXAGC			0x8000
+#define	BCCK_ANTENNA_POLARITY			0x2000
+#define	BCCK_TXFILTER_TYPE			0x0c00
+#define	BCCK_RXAGC_REPORTTYPE			0x0300
+#define	BCCK_RXDAGC_EN				0x80000000
+#define	BCCK_RXDAGC_PERIOD			0x20000000
+#define	BCCK_RXDAGC_SATLEVEL			0x1f000000
+#define	BCCK_TIMING_RECOVERY			0x800000
+#define	BCCK_TXC0				0x3f0000
+#define	BCCK_TXC1				0x3f000000
+#define	BCCK_TXC2				0x3f
+#define	BCCK_TXC3				0x3f00
+#define	BCCK_TXC4				0x3f0000
+#define	BCCK_TXC5				0x3f000000
+#define	BCCK_TXC6				0x3f
+#define	BCCK_TXC7				0x3f00
+#define	BCCK_DEBUGPORT				0xff0000
+#define	BCCK_DAC_DEBUG				0x0f000000
+#define	BCCK_FALSEALARM_ENABLE			0x8000
+#define	BCCK_FALSEALARM_READ			0x4000
+#define	BCCK_TRSSI				0x7f
+#define	BCCK_RXAGC_REPORT			0xfe
+#define	BCCK_RXREPORT_ANTSEL			0x80000000
+#define	BCCK_RXREPORT_MFOFF			0x40000000
+#define	BCCK_RXREPORT_SQLOSS			0x20000000
+#define	BCCK_RXREPORT_PKTLOSS			0x10000000
+#define	BCCK_RXREPORT_LOCKEDBIT			0x08000000
+#define	BCCK_RXREPORT_RATEERROR			0x04000000
+#define	BCCK_RXREPORT_RXRATE			0x03000000
+#define	BCCK_RXFA_COUNTER_LOWER			0xff
+#define	BCCK_RXFA_COUNTER_UPPER			0xff000000
+#define	BCCK_RXHPAGC_START			0xe000
+#define	BCCK_RXHPAGC_FINAL			0x1c00
+#define	BCCK_RXFALSEALARM_ENABLE		0x8000
+#define	BCCK_FACOUNTER_FREEZE			0x4000
+#define	BCCK_TXPATH_SEL				0x10000000
+#define	BCCK_DEFAULT_RXPATH			0xc000000
+#define	BCCK_OPTION_RXPATH			0x3000000
+
+#define	BNUM_OFSTF				0x3
+#define	BSHIFT_L				0xc0
+#define	BGI_TH					0xc
+#define	BRXPATH_A				0x1
+#define	BRXPATH_B				0x2
+#define	BRXPATH_C				0x4
+#define	BRXPATH_D				0x8
+#define	BTXPATH_A				0x1
+#define	BTXPATH_B				0x2
+#define	BTXPATH_C				0x4
+#define	BTXPATH_D				0x8
+#define	BTRSSI_FREQ				0x200
+#define	BADC_BACKOFF				0x3000
+#define	BDFIR_BACKOFF				0xc000
+#define	BTRSSI_LATCH_PHASE			0x10000
+#define	BRX_LDC_OFFSET				0xff
+#define	BRX_QDC_OFFSET				0xff00
+#define	BRX_DFIR_MODE				0x1800000
+#define	BRX_DCNF_TYPE				0xe000000
+#define	BRXIQIMB_A				0x3ff
+#define	BRXIQIMB_B				0xfc00
+#define	BRXIQIMB_C				0x3f0000
+#define	BRXIQIMB_D				0xffc00000
+#define	BDC_DC_NOTCH				0x60000
+#define	BRXNB_NOTCH				0x1f000000
+#define	BPD_TH					0xf
+#define	BPD_TH_OPT2				0xc000
+#define	BPWED_TH				0x700
+#define	BIFMF_WIN_L				0x800
+#define	BPD_OPTION				0x1000
+#define	BMF_WIN_L				0xe000
+#define	BBW_SEARCH_L				0x30000
+#define	BWIN_ENH_L				0xc0000
+#define	BBW_TH					0x700000
+#define	BED_TH2					0x3800000
+#define	BBW_OPTION				0x4000000
+#define	BRADIO_TH				0x18000000
+#define	BWINDOW_L				0xe0000000
+#define	BSBD_OPTION				0x1
+#define	BFRAME_TH				0x1c
+#define	BFS_OPTION				0x60
+#define	BDC_SLOPE_CHECK				0x80
+#define	BFGUARD_COUNTER_DC_L			0xe00
+#define	BFRAME_WEIGHT_SHORT			0x7000
+#define	BSUB_TUNE				0xe00000
+#define	BFRAME_DC_LENGTH			0xe000000
+#define	BSBD_START_OFFSET			0x30000000
+#define	BFRAME_TH_2				0x7
+#define	BFRAME_GI2_TH				0x38
+#define	BGI2_SYNC_EN				0x40
+#define	BSARCH_SHORT_EARLY			0x300
+#define	BSARCH_SHORT_LATE			0xc00
+#define	BSARCH_GI2_LATE				0x70000
+#define	BCFOANTSUM				0x1
+#define	BCFOACC					0x2
+#define	BCFOSTARTOFFSET				0xc
+#define	BCFOLOOPBACK				0x70
+#define	BCFOSUMWEIGHT				0x80
+#define	BDAGCENABLE				0x10000
+#define	BTXIQIMB_A				0x3ff
+#define	BTXIQIMB_B				0xfc00
+#define	BTXIQIMB_C				0x3f0000
+#define	BTXIQIMB_D				0xffc00000
+#define	BTXIDCOFFSET				0xff
+#define	BTXIQDCOFFSET				0xff00
+#define	BTXDFIRMODE				0x10000
+#define	BTXPESUDO_NOISEON			0x4000000
+#define	BTXPESUDO_NOISE_A			0xff
+#define	BTXPESUDO_NOISE_B			0xff00
+#define	BTXPESUDO_NOISE_C			0xff0000
+#define	BTXPESUDO_NOISE_D			0xff000000
+#define	BCCA_DROPOPTION				0x20000
+#define	BCCA_DROPTHRES				0xfff00000
+#define	BEDCCA_H				0xf
+#define	BEDCCA_L				0xf0
+#define	BLAMBDA_ED				0x300
+#define	BRX_INITIALGAIN				0x7f
+#define	BRX_ANTDIV_EN				0x80
+#define	BRX_AGC_ADDRESS_FOR_LNA			0x7f00
+#define	BRX_HIGHPOWER_FLOW			0x8000
+#define	BRX_AGC_FREEZE_THRES			0xc0000
+#define	BRX_FREEZESTEP_AGC1			0x300000
+#define	BRX_FREEZESTEP_AGC2			0xc00000
+#define	BRX_FREEZESTEP_AGC3			0x3000000
+#define	BRX_FREEZESTEP_AGC0			0xc000000
+#define	BRXRSSI_CMP_EN				0x10000000
+#define	BRXQUICK_AGCEN				0x20000000
+#define	BRXAGC_FREEZE_THRES_MODE		0x40000000
+#define	BRX_OVERFLOW_CHECKTYPE			0x80000000
+#define	BRX_AGCSHIFT				0x7f
+#define	BTRSW_TRI_ONLY				0x80
+#define	BPOWER_THRES				0x300
+#define	BRXAGC_EN				0x1
+#define	BRXAGC_TOGETHER_EN			0x2
+#define	BRXAGC_MIN				0x4
+#define	BRXHP_INI				0x7
+#define	BRXHP_TRLNA				0x70
+#define	BRXHP_RSSI				0x700
+#define	BRXHP_BBP1				0x7000
+#define	BRXHP_BBP2				0x70000
+#define	BRXHP_BBP3				0x700000
+#define	BRSSI_H					0x7f0000
+#define	BRSSI_GEN				0x7f000000
+#define	BRXSETTLE_TRSW				0x7
+#define	BRXSETTLE_LNA				0x38
+#define	BRXSETTLE_RSSI				0x1c0
+#define	BRXSETTLE_BBP				0xe00
+#define	BRXSETTLE_RXHP				0x7000
+#define	BRXSETTLE_ANTSW_RSSI			0x38000
+#define	BRXSETTLE_ANTSW				0xc0000
+#define	BRXPROCESS_TIME_DAGC			0x300000
+#define	BRXSETTLE_HSSI				0x400000
+#define	BRXPROCESS_TIME_BBPPW			0x800000
+#define	BRXANTENNA_POWER_SHIFT			0x3000000
+#define	BRSSI_TABLE_SELECT			0xc000000
+#define	BRXHP_FINAL				0x7000000
+#define	BRXHPSETTLE_BBP				0x7
+#define	BRXHTSETTLE_HSSI			0x8
+#define	BRXHTSETTLE_RXHP			0x70
+#define	BRXHTSETTLE_BBPPW			0x80
+#define	BRXHTSETTLE_IDLE			0x300
+#define	BRXHTSETTLE_RESERVED			0x1c00
+#define	BRXHT_RXHP_EN				0x8000
+#define	BRXAGC_FREEZE_THRES			0x30000
+#define	BRXAGC_TOGETHEREN			0x40000
+#define	BRXHTAGC_MIN				0x80000
+#define	BRXHTAGC_EN				0x100000
+#define	BRXHTDAGC_EN				0x200000
+#define	BRXHT_RXHP_BBP				0x1c00000
+#define	BRXHT_RXHP_FINAL			0xe0000000
+#define	BRXPW_RADIO_TH				0x3
+#define	BRXPW_RADIO_EN				0x4
+#define	BRXMF_HOLD				0x3800
+#define	BRXPD_DELAY_TH1				0x38
+#define	BRXPD_DELAY_TH2				0x1c0
+#define	BRXPD_DC_COUNT_MAX			0x600
+#define	BRXPD_DELAY_TH				0x8000
+#define	BRXPROCESS_DELAY			0xf0000
+#define	BRXSEARCHRANGE_GI2_EARLY		0x700000
+#define	BRXFRAME_FUARD_COUNTER_L		0x3800000
+#define	BRXSGI_GUARD_L				0xc000000
+#define	BRXSGI_SEARCH_L				0x30000000
+#define	BRXSGI_TH				0xc0000000
+#define	BDFSCNT0				0xff
+#define	BDFSCNT1				0xff00
+#define	BDFSFLAG				0xf0000
+#define	BMF_WEIGHT_SUM				0x300000
+#define	BMINIDX_TH				0x7f000000
+#define	BDAFORMAT				0x40000
+#define	BTXCH_EMU_ENABLE			0x01000000
+#define	BTRSW_ISOLATION_A			0x7f
+#define	BTRSW_ISOLATION_B			0x7f00
+#define	BTRSW_ISOLATION_C			0x7f0000
+#define	BTRSW_ISOLATION_D			0x7f000000
+#define	BEXT_LNA_GAIN				0x7c00
+
+#define	BSTBC_EN				0x4
+#define	BANTENNA_MAPPING			0x10
+#define	BNSS					0x20
+#define	BCFO_ANTSUM_ID				0x200
+#define	BPHY_COUNTER_RESET			0x8000000
+#define	BCFO_REPORT_GET				0x4000000
+#define	BOFDM_CONTINUE_TX			0x10000000
+#define	BOFDM_SINGLE_CARRIER			0x20000000
+#define	BOFDM_SINGLE_TONE			0x40000000
+#define	BHT_DETECT				0x100
+#define	BCFOEN					0x10000
+#define	BCFOVALUE				0xfff00000
+#define	BSIGTONE_RE				0x3f
+#define	BSIGTONE_IM				0x7f00
+#define	BCOUNTER_CCA				0xffff
+#define	BCOUNTER_PARITYFAIL			0xffff0000
+#define	BCOUNTER_RATEILLEGAL			0xffff
+#define	BCOUNTER_CRC8FAIL			0xffff0000
+#define	BCOUNTER_MCSNOSUPPORT			0xffff
+#define	BCOUNTER_FASTSYNC			0xffff
+#define	BSHORTCFO				0xfff
+#define	BSHORTCFOT_LENGTH			12
+#define	BSHORTCFOF_LENGTH			11
+#define	BLONGCFO				0x7ff
+#define	BLONGCFOT_LENGTH			11
+#define	BLONGCFOF_LENGTH			11
+#define	BTAILCFO				0x1fff
+#define	BTAILCFOT_LENGTH			13
+#define	BTAILCFOF_LENGTH			12
+#define	BNOISE_EN_PWDB				0xffff
+#define	BCC_POWER_DB				0xffff0000
+#define	BMOISE_PWDB				0xffff
+#define	BPOWERMEAST_LENGTH			10
+#define	BPOWERMEASF_LENGTH			3
+#define	BRX_HT_BW				0x1
+#define	BRXSC					0x6
+#define	BRX_HT					0x8
+#define	BNB_INTF_DET_ON				0x1
+#define	BINTF_WIN_LEN_CFG			0x30
+#define	BNB_INTF_TH_CFG				0x1c0
+#define	BRFGAIN					0x3f
+#define	BTABLESEL				0x40
+#define	BTRSW					0x80
+#define	BRXSNR_A				0xff
+#define	BRXSNR_B				0xff00
+#define	BRXSNR_C				0xff0000
+#define	BRXSNR_D				0xff000000
+#define	BSNR_EVMT_LENGTH			8
+#define	BSNR_EVMF_LENGTH			1
+#define	BCSI1ST					0xff
+#define	BCSI2ND					0xff00
+#define	BRXEVM1ST				0xff0000
+#define	BRXEVM2ND				0xff000000
+#define	BSIGEVM					0xff
+#define	BPWDB					0xff00
+#define	BSGIEN					0x10000
+
+#define	BSFACTOR_QMA1				0xf
+#define	BSFACTOR_QMA2				0xf0
+#define	BSFACTOR_QMA3				0xf00
+#define	BSFACTOR_QMA4				0xf000
+#define	BSFACTOR_QMA5				0xf0000
+#define	BSFACTOR_QMA6				0xf0000
+#define	BSFACTOR_QMA7				0xf00000
+#define	BSFACTOR_QMA8				0xf000000
+#define	BSFACTOR_QMA9				0xf0000000
+#define	BCSI_SCHEME				0x100000
+
+#define	BNOISE_LVL_TOP_SET			0x3
+#define	BCHSMOOTH				0x4
+#define	BCHSMOOTH_CFG1				0x38
+#define	BCHSMOOTH_CFG2				0x1c0
+#define	BCHSMOOTH_CFG3				0xe00
+#define	BCHSMOOTH_CFG4				0x7000
+#define	BMRCMODE				0x800000
+#define	BTHEVMCFG				0x7000000
+
+#define	BLOOP_FIT_TYPE				0x1
+#define	BUPD_CFO				0x40
+#define	BUPD_CFO_OFFDATA			0x80
+#define	BADV_UPD_CFO				0x100
+#define	BADV_TIME_CTRL				0x800
+#define	BUPD_CLKO				0x1000
+#define	BFC					0x6000
+#define	BTRACKING_MODE				0x8000
+#define	BPHCMP_ENABLE				0x10000
+#define	BUPD_CLKO_LTF				0x20000
+#define	BCOM_CH_CFO				0x40000
+#define	BCSI_ESTI_MODE				0x80000
+#define	BADV_UPD_EQZ				0x100000
+#define	BUCHCFG					0x7000000
+#define	BUPDEQZ					0x8000000
+
+#define	BRX_PESUDO_NOISE_ON			0x20000000
+#define	BRX_PESUDO_NOISE_A			0xff
+#define	BRX_PESUDO_NOISE_B			0xff00
+#define	BRX_PESUDO_NOISE_C			0xff0000
+#define	BRX_PESUDO_NOISE_D			0xff000000
+#define	BRX_PESUDO_NOISESTATE_A			0xffff
+#define	BRX_PESUDO_NOISESTATE_B			0xffff0000
+#define	BRX_PESUDO_NOISESTATE_C			0xffff
+#define	BRX_PESUDO_NOISESTATE_D			0xffff0000
+
+#define	BZEBRA1_HSSIENABLE			0x8
+#define	BZEBRA1_TRXCONTROL			0xc00
+#define	BZEBRA1_TRXGAINSETTING			0x07f
+#define	BZEBRA1_RXCOUNTER			0xc00
+#define	BZEBRA1_TXCHANGEPUMP			0x38
+#define	BZEBRA1_RXCHANGEPUMP			0x7
+#define	BZEBRA1_CHANNEL_NUM			0xf80
+#define	BZEBRA1_TXLPFBW				0x400
+#define	BZEBRA1_RXLPFBW				0x600
+
+#define	BRTL8256REG_MODE_CTRL1			0x100
+#define	BRTL8256REG_MODE_CTRL0			0x40
+#define	BRTL8256REG_TXLPFBW			0x18
+#define	BRTL8256REG_RXLPFBW			0x600
+
+#define	BRTL8258_TXLPFBW			0xc
+#define	BRTL8258_RXLPFBW			0xc00
+#define	BRTL8258_RSSILPFBW			0xc0
+
+#define	BBYTE0					0x1
+#define	BBYTE1					0x2
+#define	BBYTE2					0x4
+#define	BBYTE3					0x8
+#define	BWORD0					0x3
+#define	BWORD1					0xc
+#define	BWORD					0xf
+
+#define	MASKBYTE0				0xff
+#define	MASKBYTE1				0xff00
+#define	MASKBYTE2				0xff0000
+#define	MASKBYTE3				0xff000000
+#define	MASKHWORD				0xffff0000
+#define	MASKLWORD				0x0000ffff
+#define	MASKDWORD				0xffffffff
+#define	MASK12BITS				0xfff
+#define	MASKH4BITS				0xf0000000
+#define MASKOFDM_D				0xffc00000
+#define	MASKCCK					0x3f3f3f3f
+
+#define	MASK4BITS				0x0f
+#define	MASK20BITS				0xfffff
+#define RFREG_OFFSET_MASK			0xfffff
+
+#define	BENABLE					0x1
+#define	BDISABLE				0x0
+
+#define	LEFT_ANTENNA				0x0
+#define	RIGHT_ANTENNA				0x1
+
+#define	TCHECK_TXSTATUS				500
+#define	TUPDATE_RXCOUNTER			100
+
+#define	REG_UN_USED_REGISTER			0x01bf
+
+/* WOL bit information */
+#define	HAL92C_WOL_PTK_UPDATE_EVENT		BIT(0)
+#define	HAL92C_WOL_GTK_UPDATE_EVENT		BIT(1)
+#define	HAL92C_WOL_DISASSOC_EVENT		BIT(2)
+#define	HAL92C_WOL_DEAUTH_EVENT			BIT(3)
+#define	HAL92C_WOL_FW_DISCONNECT_EVENT		BIT(4)
+
+#define		WOL_REASON_PTK_UPDATE		BIT(0)
+#define		WOL_REASON_GTK_UPDATE		BIT(1)
+#define		WOL_REASON_DISASSOC		BIT(2)
+#define		WOL_REASON_DEAUTH		BIT(3)
+#define		WOL_REASON_FW_DISCONNECT	BIT(4)
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/rf.c b/drivers/net/wireless/rtlwifi/rtl8188ee/rf.c
new file mode 100644
index 0000000..4faafdb
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8188ee/rf.c
@@ -0,0 +1,467 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2013  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"
+
+void rtl88e_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+
+	switch (bandwidth) {
+	case HT_CHANNEL_WIDTH_20:
+		rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] &
+					     0xfffff3ff) | BIT(10) | BIT(11));
+		rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK,
+			      rtlphy->rfreg_chnlval[0]);
+		break;
+	case HT_CHANNEL_WIDTH_20_40:
+		rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] &
+					     0xfffff3ff) | BIT(10));
+		rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK,
+			      rtlphy->rfreg_chnlval[0]);
+		break;
+	default:
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 "unknown bandwidth: %#X\n", bandwidth);
+		break;
+	}
+}
+
+void rtl88e_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
+				       u8 *plevel)
+{
+	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;
+	u8 direction;
+	u32 pwrtrac_value;
+
+	if (rtlefuse->eeprom_regulatory != 0)
+		turbo_scanoff = true;
+
+	if (mac->act_scanning == true) {
+		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] = plevel[idx1] |
+					       (plevel[idx1] << 8) |
+					       (plevel[idx1] << 16) |
+					       (plevel[idx1] << 24);
+			}
+		}
+	} else {
+		for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {
+			tx_agc[idx1] = plevel[idx1] | (plevel[idx1] << 8) |
+				       (plevel[idx1] << 16) |
+				       (plevel[idx1] << 24);
+		}
+
+		if (rtlefuse->eeprom_regulatory == 0) {
+			tmpval = (rtlphy->mcs_offset[0][6]) +
+				 (rtlphy->mcs_offset[0][7] << 8);
+			tx_agc[RF90_PATH_A] += tmpval;
+
+			tmpval = (rtlphy->mcs_offset[0][14]) +
+				 (rtlphy->mcs_offset[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++;
+		}
+	}
+	rtl88e_dm_txpower_track_adjust(hw, 1, &direction, &pwrtrac_value);
+	if (direction == 1) {
+		tx_agc[0] += pwrtrac_value;
+		tx_agc[1] += pwrtrac_value;
+	} else if (direction == 2) {
+		tx_agc[0] -= pwrtrac_value;
+		tx_agc[1] -= pwrtrac_value;
+	}
+	tmpval = tx_agc[RF90_PATH_A] & 0xff;
+	rtl_set_bbreg(hw, RTXAGC_A_CCK1_MCS32, MASKBYTE1, 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, MASKBYTE0, 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 rtl88e_phy_get_power_base(struct ieee80211_hw *hw,
+				      u8 *pwrlvlofdm, u8 *pwrlvlbw20,
+				      u8 *pwrlvlbw40, u8 channel,
+				      u32 *ofdmbase, u32 *mcsbase)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	u32 base0, base1;
+	u8 i, powerlevel[2];
+
+	for (i = 0; i < 2; i++) {
+		base0 = pwrlvlofdm[i];
+
+		base0 = (base0 << 24) | (base0 << 16) |
+			     (base0 << 8) | base0;
+		*(ofdmbase + i) = base0;
+		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)
+			powerlevel[i] = pwrlvlbw20[i];
+		else
+			powerlevel[i] = pwrlvlbw40[i];
+		base1 = powerlevel[i];
+		base1 = (base1 << 24) |
+		    (base1 << 16) | (base1 << 8) | base1;
+
+		*(mcsbase + i) = base1;
+
+		RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+			"[MCS power base index rf(%c) = 0x%x]\n",
+			((i == 0) ? 'A' : 'B'), *(mcsbase + i));
+	}
+}
+
+static void get_txpwr_by_reg(struct ieee80211_hw *hw, u8 chan, u8 index,
+			     u32 *base0, u32 *base1, u32 *outval)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	u8 i, chg = 0, pwr_lim[4], pwr_diff = 0, cust_pwr_dif;
+	u32 writeval, cust_lim, rf, tmp;
+	u8 ch = chan - 1;
+	u8 j;
+
+	for (rf = 0; rf < 2; rf++) {
+		j = index + (rf ? 8 : 0);
+		tmp = ((index < 2) ? base0[rf] : base1[rf]);
+		switch (rtlefuse->eeprom_regulatory) {
+		case 0:
+			chg = 0;
+
+			writeval = rtlphy->mcs_offset[chg][j] + tmp;
+
+			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) {
+				chg = 0;
+			} else {
+				chg = chan / 3;
+				if (chan == 14)
+					chg = 5;
+			}
+			writeval = rtlphy->mcs_offset[chg][j] + tmp;
+
+			RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+				"Realtek regulatory, 20MHz, writeval(%c) = 0x%x\n",
+				 ((rf == 0) ? 'A' : 'B'), writeval);
+			break;
+		case 2:
+			writeval = ((index < 2) ? base0[rf] : base1[rf]);
+
+			RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+				"Better regulatory, writeval(%c) = 0x%x\n",
+				 ((rf == 0) ? 'A' : 'B'), writeval);
+			break;
+		case 3:
+			chg = 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][ch]);
+			} else {
+				RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+					"customer's limit, 20MHz rf(%c) = 0x%x\n",
+					 ((rf == 0) ? 'A' : 'B'),
+					 rtlefuse->pwrgroup_ht20[rf][ch]);
+			}
+
+			if (index < 2)
+				pwr_diff = rtlefuse->txpwr_legacyhtdiff[rf][ch];
+			else if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20)
+				pwr_diff = rtlefuse->txpwr_ht20diff[rf][ch];
+
+			if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40)
+				cust_pwr_dif = rtlefuse->pwrgroup_ht40[rf][ch];
+			else
+				cust_pwr_dif = rtlefuse->pwrgroup_ht20[rf][ch];
+
+			if (pwr_diff > cust_pwr_dif)
+				pwr_diff = 0;
+			else
+				pwr_diff = cust_pwr_dif - pwr_diff;
+
+			for (i = 0; i < 4; i++) {
+				pwr_lim[i] = (u8)((rtlphy->mcs_offset[chg][j] &
+					     (0x7f << (i * 8))) >> (i * 8));
+
+				if (pwr_lim[i] > pwr_diff)
+					pwr_lim[i] = pwr_diff;
+			}
+
+			cust_lim = (pwr_lim[3] << 24) | (pwr_lim[2] << 16) |
+				   (pwr_lim[1] << 8) | (pwr_lim[0]);
+
+			RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+				"Customer's limit rf(%c) = 0x%x\n",
+				((rf == 0) ? 'A' : 'B'), cust_lim);
+
+			writeval = cust_lim + tmp;
+
+			RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+				"Customer, writeval rf(%c) = 0x%x\n",
+				((rf == 0) ? 'A' : 'B'), writeval);
+			break;
+		default:
+			chg = 0;
+			writeval = rtlphy->mcs_offset[chg][j] + tmp;
+
+			RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+				"RTK better performance, writeval "
+				"rf(%c) = 0x%x\n",
+				((rf == 0) ? 'A' : 'B'), writeval);
+			break;
+		}
+
+		if (rtlpriv->dm.dynamic_txhighpower_lvl == TXHIGHPWRLEVEL_BT1)
+			writeval = writeval - 0x06060606;
+		else if (rtlpriv->dm.dynamic_txhighpower_lvl ==
+			 TXHIGHPWRLEVEL_BT2)
+			writeval -= 0x0c0c0c0c;
+		*(outval + rf) = writeval;
+	}
+}
+
+static void write_ofdm_pwr(struct ieee80211_hw *hw, u8 index, u32 *pvalue)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	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
+	};
+	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, MASKDWORD, writeval);
+
+		RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+			"Set 0x%x = %08x\n", regoffset, writeval);
+	}
+}
+
+void rtl88e_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw,
+					u8 *pwrlvlofdm,
+					u8 *pwrlvlbw20,
+					u8 *pwrlvlbw40, u8 chan)
+{
+	u32 writeval[2], base0[2], base1[2];
+	u8 index;
+	u8 direction;
+	u32 pwrtrac_value;
+
+	rtl88e_phy_get_power_base(hw, pwrlvlofdm, pwrlvlbw20,
+				  pwrlvlbw40, chan, &base0[0],
+				  &base1[0]);
+
+	rtl88e_dm_txpower_track_adjust(hw, 1, &direction, &pwrtrac_value);
+
+	for (index = 0; index < 6; index++) {
+		get_txpwr_by_reg(hw, chan, index, &base0[0], &base1[0],
+				 &writeval[0]);
+		if (direction == 1) {
+			writeval[0] += pwrtrac_value;
+			writeval[1] += pwrtrac_value;
+		} else if (direction == 2) {
+			writeval[0] -= pwrtrac_value;
+			writeval[1] -= pwrtrac_value;
+		}
+		write_ofdm_pwr(hw, index, &writeval[0]);
+	}
+}
+
+static bool rf6052_conf_para(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	u32 u4val = 0;
+	u8 rfpath;
+	bool rtstatus = true;
+	struct bb_reg_def *pphyreg;
+
+	for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) {
+		pphyreg = &rtlphy->phyreg_def[rfpath];
+
+		switch (rfpath) {
+		case RF90_PATH_A:
+		case RF90_PATH_C:
+			u4val = rtl_get_bbreg(hw, pphyreg->rfintfs,
+						    BRFSI_RFENV);
+			break;
+		case RF90_PATH_B:
+		case RF90_PATH_D:
+			u4val = 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);
+
+		rtl_set_bbreg(hw, pphyreg->rfhssi_para2,
+			      B3WIREADDREAALENGTH, 0x0);
+		udelay(1);
+
+		rtl_set_bbreg(hw, pphyreg->rfhssi_para2, B3WIREDATALENGTH, 0x0);
+		udelay(1);
+
+		switch (rfpath) {
+		case RF90_PATH_A:
+			rtstatus = rtl88e_phy_config_rf_with_headerfile(hw,
+					(enum radio_path)rfpath);
+			break;
+		case RF90_PATH_B:
+			rtstatus = rtl88e_phy_config_rf_with_headerfile(hw,
+					(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, u4val);
+			break;
+		case RF90_PATH_B:
+		case RF90_PATH_D:
+			rtl_set_bbreg(hw, pphyreg->rfintfs, BRFSI_RFENV << 16,
+				      u4val);
+			break;
+		}
+
+		if (rtstatus != true) {
+			RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+				 "Radio[%d] Fail!!", rfpath);
+			return false;
+		}
+	}
+
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "\n");
+	return rtstatus;
+}
+
+bool rtl88e_phy_rf6052_config(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+
+	if (rtlphy->rf_type == RF_1T1R)
+		rtlphy->num_total_rfpath = 1;
+	else
+		rtlphy->num_total_rfpath = 2;
+
+	return rf6052_conf_para(hw);
+}
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/rf.h b/drivers/net/wireless/rtlwifi/rtl8188ee/rf.h
new file mode 100644
index 0000000..a39a2a3
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8188ee/rf.h
@@ -0,0 +1,46 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2013  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_RF_H__
+#define __RTL92C_RF_H__
+
+#define RF6052_MAX_TX_PWR		0x3F
+#define RF6052_MAX_REG			0x3F
+
+void rtl88e_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw,
+				     u8 bandwidth);
+void rtl88e_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
+				       u8 *ppowerlevel);
+void rtl88e_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw,
+					u8 *ppowerlevel_ofdm,
+					u8 *ppowerlevel_bw20,
+					u8 *ppowerlevel_bw40, u8 channel);
+bool rtl88e_phy_rf6052_config(struct ieee80211_hw *hw);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c b/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c
new file mode 100644
index 0000000..c254693
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c
@@ -0,0 +1,400 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2013  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 "../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"
+#include "table.h"
+
+#include <linux/vmalloc.h>
+#include <linux/module.h>
+
+static void rtl88e_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;
+}
+
+int rtl88e_init_sw_vars(struct ieee80211_hw *hw)
+{
+	int err = 0;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+	u8 tid;
+
+	rtl8188ee_bt_reg_init(hw);
+
+	rtlpriv->dm.dm_initialgain_enable = 1;
+	rtlpriv->dm.dm_flag = 0;
+	rtlpriv->dm.disable_framebursting = 0;
+	rtlpriv->dm.thermalvalue = 0;
+	rtlpci->transmit_config = CFENDFORM | BIT(15);
+
+	/* compatible 5G band 88ce just 2.4G band & smsp */
+	rtlpriv->rtlhal.current_bandtype = BAND_ON_2_4G;
+	rtlpriv->rtlhal.bandset = BAND_ON_2_4G;
+	rtlpriv->rtlhal.macphymode = SINGLEMAC_SINGLEPHY;
+
+	rtlpci->receive_config = (RCR_APPFCS |
+				  RCR_APP_MIC |
+				  RCR_APP_ICV |
+				  RCR_APP_PHYST_RXFF |
+				  RCR_HTC_LOC_CTRL |
+				  RCR_AMF |
+				  RCR_ACF |
+				  RCR_ADF |
+				  RCR_AICV |
+				  RCR_ACRC32 |
+				  RCR_AB |
+				  RCR_AM |
+				  RCR_APM |
+				  0);
+
+	rtlpci->irq_mask[0] =
+				(u32) (IMR_PSTIMEOUT	|
+				IMR_HSISR_IND_ON_INT	|
+				IMR_C2HCMD		|
+				IMR_HIGHDOK		|
+				IMR_MGNTDOK		|
+				IMR_BKDOK		|
+				IMR_BEDOK		|
+				IMR_VIDOK		|
+				IMR_VODOK		|
+				IMR_RDU			|
+				IMR_ROK			|
+				0);
+	rtlpci->irq_mask[1] = (u32) (IMR_RXFOVW | 0);
+	rtlpci->sys_irq_mask = (u32) (HSIMR_PDN_INT_EN | HSIMR_RON_INT_EN);
+
+	/* for debug level */
+	rtlpriv->dbg.global_debuglevel = rtlpriv->cfg->mod_params->debug;
+	/* 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;
+	if (!rtlpriv->psc.inactiveps)
+		pr_info("rtl8188ee: Power Save off (module option)\n");
+	if (!rtlpriv->psc.fwctrl_lps)
+		pr_info("rtl8188ee: FW Power Save off (module option)\n");
+	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
+	 */
+	rtl88e_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 = vmalloc(0x8000);
+	if (!rtlpriv->rtlhal.pfirmware) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 "Can't alloc buffer for fw.\n");
+		return 1;
+	}
+
+	rtlpriv->cfg->fw_name = "rtlwifi/rtl8188efw.bin";
+	rtlpriv->max_fw_size = 0x8000;
+	pr_info("Using firmware %s\n", rtlpriv->cfg->fw_name);
+	err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name,
+				      rtlpriv->io.dev, GFP_KERNEL, hw,
+				      rtl_fw_cb);
+	if (err) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 "Failed to request firmware!\n");
+		return 1;
+	}
+
+	/* for early mode */
+	rtlpriv->rtlhal.earlymode_enable = false;
+	rtlpriv->rtlhal.max_earlymode_num = 10;
+	for (tid = 0; tid < 8; tid++)
+		skb_queue_head_init(&rtlpriv->mac80211.skb_waitq[tid]);
+
+	/*low power */
+	rtlpriv->psc.low_power_enable = false;
+	if (rtlpriv->psc.low_power_enable) {
+		init_timer(&rtlpriv->works.fw_clockoff_timer);
+		setup_timer(&rtlpriv->works.fw_clockoff_timer,
+			    rtl88ee_fw_clk_off_timer_callback,
+			    (unsigned long)hw);
+	}
+
+	init_timer(&rtlpriv->works.fast_antenna_training_timer);
+	setup_timer(&rtlpriv->works.fast_antenna_training_timer,
+		    rtl88e_dm_fast_antenna_training_callback,
+		    (unsigned long)hw);
+	return err;
+}
+
+void rtl88e_deinit_sw_vars(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	if (rtlpriv->rtlhal.pfirmware) {
+		vfree(rtlpriv->rtlhal.pfirmware);
+		rtlpriv->rtlhal.pfirmware = NULL;
+	}
+
+	if (rtlpriv->psc.low_power_enable)
+		del_timer_sync(&rtlpriv->works.fw_clockoff_timer);
+
+	del_timer_sync(&rtlpriv->works.fast_antenna_training_timer);
+}
+
+static struct rtl_hal_ops rtl8188ee_hal_ops = {
+	.init_sw_vars = rtl88e_init_sw_vars,
+	.deinit_sw_vars = rtl88e_deinit_sw_vars,
+	.read_eeprom_info = rtl88ee_read_eeprom_info,
+	.interrupt_recognized = rtl88ee_interrupt_recognized,/*need check*/
+	.hw_init = rtl88ee_hw_init,
+	.hw_disable = rtl88ee_card_disable,
+	.hw_suspend = rtl88ee_suspend,
+	.hw_resume = rtl88ee_resume,
+	.enable_interrupt = rtl88ee_enable_interrupt,
+	.disable_interrupt = rtl88ee_disable_interrupt,
+	.set_network_type = rtl88ee_set_network_type,
+	.set_chk_bssid = rtl88ee_set_check_bssid,
+	.set_qos = rtl88ee_set_qos,
+	.set_bcn_reg = rtl88ee_set_beacon_related_registers,
+	.set_bcn_intv = rtl88ee_set_beacon_interval,
+	.update_interrupt_mask = rtl88ee_update_interrupt_mask,
+	.get_hw_reg = rtl88ee_get_hw_reg,
+	.set_hw_reg = rtl88ee_set_hw_reg,
+	.update_rate_tbl = rtl88ee_update_hal_rate_tbl,
+	.fill_tx_desc = rtl88ee_tx_fill_desc,
+	.fill_tx_cmddesc = rtl88ee_tx_fill_cmddesc,
+	.query_rx_desc = rtl88ee_rx_query_desc,
+	.set_channel_access = rtl88ee_update_channel_access_setting,
+	.radio_onoff_checking = rtl88ee_gpio_radio_on_off_checking,
+	.set_bw_mode = rtl88e_phy_set_bw_mode,
+	.switch_channel = rtl88e_phy_sw_chnl,
+	.dm_watchdog = rtl88e_dm_watchdog,
+	.scan_operation_backup = rtl88e_phy_scan_operation_backup,
+	.set_rf_power_state = rtl88e_phy_set_rf_power_state,
+	.led_control = rtl88ee_led_control,
+	.set_desc = rtl88ee_set_desc,
+	.get_desc = rtl88ee_get_desc,
+	.tx_polling = rtl88ee_tx_polling,
+	.enable_hw_sec = rtl88ee_enable_hw_security_config,
+	.set_key = rtl88ee_set_key,
+	.init_sw_leds = rtl88ee_init_sw_leds,
+	.allow_all_destaddr = rtl88ee_allow_all_destaddr,
+	.get_bbreg = rtl88e_phy_query_bb_reg,
+	.set_bbreg = rtl88e_phy_set_bb_reg,
+	.get_rfreg = rtl88e_phy_query_rf_reg,
+	.set_rfreg = rtl88e_phy_set_rf_reg,
+};
+
+static struct rtl_mod_params rtl88ee_mod_params = {
+	.sw_crypto = false,
+	.inactiveps = true,
+	.swctrl_lps = false,
+	.fwctrl_lps = true,
+	.debug = DBG_EMERG,
+};
+
+static struct rtl_hal_cfg rtl88ee_hal_cfg = {
+	.bar_id = 2,
+	.write_readback = true,
+	.name = "rtl88e_pci",
+	.ops = &rtl8188ee_hal_ops,
+	.mod_params = &rtl88ee_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] = AM,
+	.maps[MAC_RCR_AB] = AB,
+	.maps[MAC_RCR_ACRC32] = ACRC32,
+	.maps[MAC_RCR_ACF] = ACF,
+	.maps[MAC_RCR_AAP] = AAP,
+
+	.maps[EFUSE_ACCESS] = REG_EFUSE_ACCESS,
+
+	.maps[EFUSE_TEST] = REG_EFUSE_TEST,
+	.maps[EFUSE_CTRL] = REG_EFUSE_CTRL,
+	.maps[EFUSE_CLK] = 0,
+	.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] = ANA8M,
+	.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[EFUSE_OOB_PROTECT_BYTES_LEN] = EFUSE_OOB_PROTECT_BYTES,
+
+	.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,     */   /*need check*/
+	.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_BCNDMAINT0,
+	.maps[RTL_IMR_RXFOVW] = IMR_RXFOVW,
+	.maps[RTL_IMR_RDU] = IMR_RDU,
+	.maps[RTL_IMR_ATIMEND] = IMR_ATIMEND,
+	.maps[RTL_IMR_BDOK] = IMR_BCNDOK0,
+	.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_BCNDMAINT0 | IMR_TBDOK | IMR_TBDER),
+
+	.maps[RTL_RC_CCK_RATE1M] = DESC92C_RATE1M,
+	.maps[RTL_RC_CCK_RATE2M] = DESC92C_RATE2M,
+	.maps[RTL_RC_CCK_RATE5_5M] = DESC92C_RATE5_5M,
+	.maps[RTL_RC_CCK_RATE11M] = DESC92C_RATE11M,
+	.maps[RTL_RC_OFDM_RATE6M] = DESC92C_RATE6M,
+	.maps[RTL_RC_OFDM_RATE9M] = DESC92C_RATE9M,
+	.maps[RTL_RC_OFDM_RATE12M] = DESC92C_RATE12M,
+	.maps[RTL_RC_OFDM_RATE18M] = DESC92C_RATE18M,
+	.maps[RTL_RC_OFDM_RATE24M] = DESC92C_RATE24M,
+	.maps[RTL_RC_OFDM_RATE36M] = DESC92C_RATE36M,
+	.maps[RTL_RC_OFDM_RATE48M] = DESC92C_RATE48M,
+	.maps[RTL_RC_OFDM_RATE54M] = DESC92C_RATE54M,
+
+	.maps[RTL_RC_HT_RATEMCS7] = DESC92C_RATEMCS7,
+	.maps[RTL_RC_HT_RATEMCS15] = DESC92C_RATEMCS15,
+};
+
+static DEFINE_PCI_DEVICE_TABLE(rtl88ee_pci_ids) = {
+	{RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8179, rtl88ee_hal_cfg)},
+	{},
+};
+
+MODULE_DEVICE_TABLE(pci, rtl88ee_pci_ids);
+
+MODULE_AUTHOR("zhiyuan_yang	<zhiyuan_yang@realsil.com.cn>");
+MODULE_AUTHOR("Realtek WlanFAE	<wlanfae@realtek.com>");
+MODULE_AUTHOR("Larry Finger	<Larry.Finger@lwfinger.net>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Realtek 8188E 802.11n PCI wireless");
+MODULE_FIRMWARE("rtlwifi/rtl8188efw.bin");
+
+module_param_named(swenc, rtl88ee_mod_params.sw_crypto, bool, 0444);
+module_param_named(debug, rtl88ee_mod_params.debug, int, 0444);
+module_param_named(ips, rtl88ee_mod_params.inactiveps, bool, 0444);
+module_param_named(swlps, rtl88ee_mod_params.swctrl_lps, bool, 0444);
+module_param_named(fwlps, rtl88ee_mod_params.fwctrl_lps, bool, 0444);
+MODULE_PARM_DESC(swenc, "Set to 1 for software crypto (default 0)\n");
+MODULE_PARM_DESC(ips, "Set to 0 to not use link power save (default 1)\n");
+MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 0)\n");
+MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 1)\n");
+MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)");
+
+static SIMPLE_DEV_PM_OPS(rtlwifi_pm_ops, rtl_pci_suspend, rtl_pci_resume);
+
+static struct pci_driver rtl88ee_driver = {
+	.name = KBUILD_MODNAME,
+	.id_table = rtl88ee_pci_ids,
+	.probe = rtl_pci_probe,
+	.remove = rtl_pci_disconnect,
+	.driver.pm = &rtlwifi_pm_ops,
+};
+
+module_pci_driver(rtl88ee_driver);
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/sw.h b/drivers/net/wireless/rtlwifi/rtl8188ee/sw.h
new file mode 100644
index 0000000..85e02b3
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8188ee/sw.h
@@ -0,0 +1,36 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2013  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_SW_H__
+#define __RTL92CE_SW_H__
+
+int rtl88e_init_sw_vars(struct ieee80211_hw *hw);
+void rtl88e_deinit_sw_vars(struct ieee80211_hw *hw);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/table.c b/drivers/net/wireless/rtlwifi/rtl8188ee/table.c
new file mode 100644
index 0000000..fad373f
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8188ee/table.c
@@ -0,0 +1,643 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2013  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.
+ *
+ * Created on  2010/ 5/18,  1:41
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "table.h"
+
+u32 RTL8188EEPHY_REG_1TARRAY[] = {
+		0x800, 0x80040000,
+		0x804, 0x00000003,
+		0x808, 0x0000FC00,
+		0x80C, 0x0000000A,
+		0x810, 0x10001331,
+		0x814, 0x020C3D10,
+		0x818, 0x02200385,
+		0x81C, 0x00000000,
+		0x820, 0x01000100,
+		0x824, 0x00390204,
+		0x828, 0x00000000,
+		0x82C, 0x00000000,
+		0x830, 0x00000000,
+		0x834, 0x00000000,
+		0x838, 0x00000000,
+		0x83C, 0x00000000,
+		0x840, 0x00010000,
+		0x844, 0x00000000,
+		0x848, 0x00000000,
+		0x84C, 0x00000000,
+		0x850, 0x00000000,
+		0x854, 0x00000000,
+		0x858, 0x569A11A9,
+		0x85C, 0x01000014,
+		0x860, 0x66F60110,
+		0x864, 0x061F0649,
+		0x868, 0x00000000,
+		0x86C, 0x27272700,
+		0x870, 0x07000760,
+		0x874, 0x25004000,
+		0x878, 0x00000808,
+		0x87C, 0x00000000,
+		0x880, 0xB0000C1C,
+		0x884, 0x00000001,
+		0x888, 0x00000000,
+		0x88C, 0xCCC000C0,
+		0x890, 0x00000800,
+		0x894, 0xFFFFFFFE,
+		0x898, 0x40302010,
+		0x89C, 0x00706050,
+		0x900, 0x00000000,
+		0x904, 0x00000023,
+		0x908, 0x00000000,
+		0x90C, 0x81121111,
+		0x910, 0x00000002,
+		0x914, 0x00000201,
+		0xA00, 0x00D047C8,
+		0xA04, 0x80FF000C,
+		0xA08, 0x8C838300,
+		0xA0C, 0x2E7F120F,
+		0xA10, 0x9500BB78,
+		0xA14, 0x1114D028,
+		0xA18, 0x00881117,
+		0xA1C, 0x89140F00,
+		0xA20, 0x1A1B0000,
+		0xA24, 0x090E1317,
+		0xA28, 0x00000204,
+		0xA2C, 0x00D30000,
+		0xA70, 0x101FBF00,
+		0xA74, 0x00000007,
+		0xA78, 0x00000900,
+		0xA7C, 0x225B0606,
+		0xA80, 0x218075B1,
+		0xB2C, 0x80000000,
+		0xC00, 0x48071D40,
+		0xC04, 0x03A05611,
+		0xC08, 0x000000E4,
+		0xC0C, 0x6C6C6C6C,
+		0xC10, 0x08800000,
+		0xC14, 0x40000100,
+		0xC18, 0x08800000,
+		0xC1C, 0x40000100,
+		0xC20, 0x00000000,
+		0xC24, 0x00000000,
+		0xC28, 0x00000000,
+		0xC2C, 0x00000000,
+		0xC30, 0x69E9AC47,
+		0xC34, 0x469652AF,
+		0xC38, 0x49795994,
+		0xC3C, 0x0A97971C,
+		0xC40, 0x1F7C403F,
+		0xC44, 0x000100B7,
+		0xC48, 0xEC020107,
+		0xC4C, 0x007F037F,
+		0xC50, 0x69553420,
+		0xC54, 0x43BC0094,
+		0xC58, 0x00013169,
+		0xC5C, 0x00250492,
+		0xC60, 0x00000000,
+		0xC64, 0x7112848B,
+		0xC68, 0x47C00BFF,
+		0xC6C, 0x00000036,
+		0xC70, 0x2C7F000D,
+		0xC74, 0x020610DB,
+		0xC78, 0x0000001F,
+		0xC7C, 0x00B91612,
+		0xC80, 0x390000E4,
+		0xC84, 0x20F60000,
+		0xC88, 0x40000100,
+		0xC8C, 0x20200000,
+		0xC90, 0x00091521,
+		0xC94, 0x00000000,
+		0xC98, 0x00121820,
+		0xC9C, 0x00007F7F,
+		0xCA0, 0x00000000,
+		0xCA4, 0x000300A0,
+		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, 0x64B22427,
+		0xCDC, 0x00766932,
+		0xCE0, 0x00222222,
+		0xCE4, 0x00000000,
+		0xCE8, 0x37644302,
+		0xCEC, 0x2F97D40C,
+		0xD00, 0x00000740,
+		0xD04, 0x00020401,
+		0xD08, 0x0000907F,
+		0xD0C, 0x20010201,
+		0xD10, 0xA0633333,
+		0xD14, 0x3333BC43,
+		0xD18, 0x7A8F5B6F,
+		0xD2C, 0xCC979975,
+		0xD30, 0x00000000,
+		0xD34, 0x80608000,
+		0xD38, 0x00000000,
+		0xD3C, 0x00127353,
+		0xD40, 0x00000000,
+		0xD44, 0x00000000,
+		0xD48, 0x00000000,
+		0xD4C, 0x00000000,
+		0xD50, 0x6437140A,
+		0xD54, 0x00000000,
+		0xD58, 0x00000282,
+		0xD5C, 0x30032064,
+		0xD60, 0x4653DE68,
+		0xD64, 0x04518A3C,
+		0xD68, 0x00002101,
+		0xD6C, 0x2A201C16,
+		0xD70, 0x1812362E,
+		0xD74, 0x322C2220,
+		0xD78, 0x000E3C24,
+		0xE00, 0x2D2D2D2D,
+		0xE04, 0x2D2D2D2D,
+		0xE08, 0x0390272D,
+		0xE10, 0x2D2D2D2D,
+		0xE14, 0x2D2D2D2D,
+		0xE18, 0x2D2D2D2D,
+		0xE1C, 0x2D2D2D2D,
+		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, 0x00000008,
+		0xE68, 0x001B25A4,
+		0xE6C, 0x00C00014,
+		0xE70, 0x00C00014,
+		0xE74, 0x01000014,
+		0xE78, 0x01000014,
+		0xE7C, 0x01000014,
+		0xE80, 0x01000014,
+		0xE84, 0x00C00014,
+		0xE88, 0x01000014,
+		0xE8C, 0x00C00014,
+		0xED0, 0x00C00014,
+		0xED4, 0x00C00014,
+		0xED8, 0x00C00014,
+		0xEDC, 0x00000014,
+		0xEE0, 0x00000014,
+		0xEEC, 0x01C00014,
+		0xF14, 0x00000003,
+		0xF4C, 0x00000000,
+		0xF00, 0x00000300,
+
+};
+
+u32 RTL8188EEPHY_REG_ARRAY_PG[] = {
+		0xE00, 0xFFFFFFFF, 0x06070809,
+		0xE04, 0xFFFFFFFF, 0x02020405,
+		0xE08, 0x0000FF00, 0x00000006,
+		0x86C, 0xFFFFFF00, 0x00020400,
+		0xE10, 0xFFFFFFFF, 0x08090A0B,
+		0xE14, 0xFFFFFFFF, 0x01030607,
+		0xE18, 0xFFFFFFFF, 0x08090A0B,
+		0xE1C, 0xFFFFFFFF, 0x01030607,
+		0xE00, 0xFFFFFFFF, 0x00000000,
+		0xE04, 0xFFFFFFFF, 0x00000000,
+		0xE08, 0x0000FF00, 0x00000000,
+		0x86C, 0xFFFFFF00, 0x00000000,
+		0xE10, 0xFFFFFFFF, 0x00000000,
+		0xE14, 0xFFFFFFFF, 0x00000000,
+		0xE18, 0xFFFFFFFF, 0x00000000,
+		0xE1C, 0xFFFFFFFF, 0x00000000,
+		0xE00, 0xFFFFFFFF, 0x02020202,
+		0xE04, 0xFFFFFFFF, 0x00020202,
+		0xE08, 0x0000FF00, 0x00000000,
+		0x86C, 0xFFFFFF00, 0x00000000,
+		0xE10, 0xFFFFFFFF, 0x04040404,
+		0xE14, 0xFFFFFFFF, 0x00020404,
+		0xE18, 0xFFFFFFFF, 0x00000000,
+		0xE1C, 0xFFFFFFFF, 0x00000000,
+		0xE00, 0xFFFFFFFF, 0x02020202,
+		0xE04, 0xFFFFFFFF, 0x00020202,
+		0xE08, 0x0000FF00, 0x00000000,
+		0x86C, 0xFFFFFF00, 0x00000000,
+		0xE10, 0xFFFFFFFF, 0x04040404,
+		0xE14, 0xFFFFFFFF, 0x00020404,
+		0xE18, 0xFFFFFFFF, 0x00000000,
+		0xE1C, 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,
+		0xE00, 0xFFFFFFFF, 0x02020202,
+		0xE04, 0xFFFFFFFF, 0x00020202,
+		0xE08, 0x0000FF00, 0x00000000,
+		0x86C, 0xFFFFFF00, 0x00000000,
+		0xE10, 0xFFFFFFFF, 0x04040404,
+		0xE14, 0xFFFFFFFF, 0x00020404,
+		0xE18, 0xFFFFFFFF, 0x00000000,
+		0xE1C, 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,
+		0xE00, 0xFFFFFFFF, 0x00000000,
+		0xE04, 0xFFFFFFFF, 0x00000000,
+		0xE08, 0x0000FF00, 0x00000000,
+		0x86C, 0xFFFFFF00, 0x00000000,
+		0xE10, 0xFFFFFFFF, 0x00000000,
+		0xE14, 0xFFFFFFFF, 0x00000000,
+		0xE18, 0xFFFFFFFF, 0x00000000,
+		0xE1C, 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,
+		0xE00, 0xFFFFFFFF, 0x00000000,
+		0xE04, 0xFFFFFFFF, 0x00000000,
+		0xE08, 0x0000FF00, 0x00000000,
+		0x86C, 0xFFFFFF00, 0x00000000,
+		0xE10, 0xFFFFFFFF, 0x00000000,
+		0xE14, 0xFFFFFFFF, 0x00000000,
+		0xE18, 0xFFFFFFFF, 0x00000000,
+		0xE1C, 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,
+
+};
+
+u32 RTL8188EE_RADIOA_1TARRAY[] = {
+		0x000, 0x00030000,
+		0x008, 0x00084000,
+		0x018, 0x00000407,
+		0x019, 0x00000012,
+		0x01E, 0x00080009,
+		0x01F, 0x00000880,
+		0x02F, 0x0001A060,
+		0x03F, 0x00000000,
+		0x042, 0x000060C0,
+		0x057, 0x000D0000,
+		0x058, 0x000BE180,
+		0x067, 0x00001552,
+		0x083, 0x00000000,
+		0x0B0, 0x000FF8FC,
+		0x0B1, 0x00054400,
+		0x0B2, 0x000CCC19,
+		0x0B4, 0x00043003,
+		0x0B6, 0x0004953E,
+		0x0B7, 0x0001C718,
+		0x0B8, 0x000060FF,
+		0x0B9, 0x00080001,
+		0x0BA, 0x00040000,
+		0x0BB, 0x00000400,
+		0x0BF, 0x000C0000,
+		0x0C2, 0x00002400,
+		0x0C3, 0x00000009,
+		0x0C4, 0x00040C91,
+		0x0C5, 0x00099999,
+		0x0C6, 0x000000A3,
+		0x0C7, 0x00088820,
+		0x0C8, 0x00076C06,
+		0x0C9, 0x00000000,
+		0x0CA, 0x00080000,
+		0x0DF, 0x00000180,
+		0x0EF, 0x000001A0,
+		0x051, 0x0006B27D,
+		0x052, 0x0007E49D,
+		0x053, 0x00000073,
+		0x056, 0x00051FF3,
+		0x035, 0x00000086,
+		0x035, 0x00000186,
+		0x035, 0x00000286,
+		0x036, 0x00001C25,
+		0x036, 0x00009C25,
+		0x036, 0x00011C25,
+		0x036, 0x00019C25,
+		0x0B6, 0x00048538,
+		0x018, 0x00000C07,
+		0x05A, 0x0004BD00,
+		0x019, 0x000739D0,
+		0x034, 0x0000ADF3,
+		0x034, 0x00009DF0,
+		0x034, 0x00008DED,
+		0x034, 0x00007DEA,
+		0x034, 0x00006DE7,
+		0x034, 0x000054EE,
+		0x034, 0x000044EB,
+		0x034, 0x000034E8,
+		0x034, 0x0000246B,
+		0x034, 0x00001468,
+		0x034, 0x0000006D,
+		0x000, 0x00030159,
+		0x084, 0x00068200,
+		0x086, 0x000000CE,
+		0x087, 0x00048A00,
+		0x08E, 0x00065540,
+		0x08F, 0x00088000,
+		0x0EF, 0x000020A0,
+		0x03B, 0x000F02B0,
+		0x03B, 0x000EF7B0,
+		0x03B, 0x000D4FB0,
+		0x03B, 0x000CF060,
+		0x03B, 0x000B0090,
+		0x03B, 0x000A0080,
+		0x03B, 0x00090080,
+		0x03B, 0x0008F780,
+		0x03B, 0x000722B0,
+		0x03B, 0x0006F7B0,
+		0x03B, 0x00054FB0,
+		0x03B, 0x0004F060,
+		0x03B, 0x00030090,
+		0x03B, 0x00020080,
+		0x03B, 0x00010080,
+		0x03B, 0x0000F780,
+		0x0EF, 0x000000A0,
+		0x000, 0x00010159,
+		0x018, 0x0000F407,
+		0xFFE, 0x00000000,
+		0xFFE, 0x00000000,
+		0x01F, 0x00080003,
+		0xFFE, 0x00000000,
+		0xFFE, 0x00000000,
+		0x01E, 0x00000001,
+		0x01F, 0x00080000,
+		0x000, 0x00033E60,
+
+};
+
+u32 RTL8188EEMAC_1T_ARRAY[] = {
+		0x026, 0x00000041,
+		0x027, 0x00000035,
+		0x428, 0x0000000A,
+		0x429, 0x00000010,
+		0x430, 0x00000000,
+		0x431, 0x00000001,
+		0x432, 0x00000002,
+		0x433, 0x00000004,
+		0x434, 0x00000005,
+		0x435, 0x00000006,
+		0x436, 0x00000007,
+		0x437, 0x00000008,
+		0x438, 0x00000000,
+		0x439, 0x00000000,
+		0x43A, 0x00000001,
+		0x43B, 0x00000002,
+		0x43C, 0x00000004,
+		0x43D, 0x00000005,
+		0x43E, 0x00000006,
+		0x43F, 0x00000007,
+		0x440, 0x0000005D,
+		0x441, 0x00000001,
+		0x442, 0x00000000,
+		0x444, 0x00000015,
+		0x445, 0x000000F0,
+		0x446, 0x0000000F,
+		0x447, 0x00000000,
+		0x458, 0x00000041,
+		0x459, 0x000000A8,
+		0x45A, 0x00000072,
+		0x45B, 0x000000B9,
+		0x460, 0x00000066,
+		0x461, 0x00000066,
+		0x480, 0x00000008,
+		0x4C8, 0x000000FF,
+		0x4C9, 0x00000008,
+		0x4CC, 0x000000FF,
+		0x4CD, 0x000000FF,
+		0x4CE, 0x00000001,
+		0x4D3, 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,
+		0x516, 0x0000000A,
+		0x525, 0x0000004F,
+		0x550, 0x00000010,
+		0x551, 0x00000010,
+		0x559, 0x00000002,
+		0x55D, 0x000000FF,
+		0x605, 0x00000030,
+		0x608, 0x0000000E,
+		0x609, 0x0000002A,
+		0x620, 0x000000FF,
+		0x621, 0x000000FF,
+		0x622, 0x000000FF,
+		0x623, 0x000000FF,
+		0x624, 0x000000FF,
+		0x625, 0x000000FF,
+		0x626, 0x000000FF,
+		0x627, 0x000000FF,
+		0x652, 0x00000020,
+		0x63C, 0x0000000A,
+		0x63D, 0x0000000A,
+		0x63E, 0x0000000E,
+		0x63F, 0x0000000E,
+		0x640, 0x00000040,
+		0x66E, 0x00000005,
+		0x700, 0x00000021,
+		0x701, 0x00000043,
+		0x702, 0x00000065,
+		0x703, 0x00000087,
+		0x708, 0x00000021,
+		0x709, 0x00000043,
+		0x70A, 0x00000065,
+		0x70B, 0x00000087,
+
+};
+
+u32 RTL8188EEAGCTAB_1TARRAY[] = {
+		0xC78, 0xFB000001,
+		0xC78, 0xFB010001,
+		0xC78, 0xFB020001,
+		0xC78, 0xFB030001,
+		0xC78, 0xFB040001,
+		0xC78, 0xFB050001,
+		0xC78, 0xFA060001,
+		0xC78, 0xF9070001,
+		0xC78, 0xF8080001,
+		0xC78, 0xF7090001,
+		0xC78, 0xF60A0001,
+		0xC78, 0xF50B0001,
+		0xC78, 0xF40C0001,
+		0xC78, 0xF30D0001,
+		0xC78, 0xF20E0001,
+		0xC78, 0xF10F0001,
+		0xC78, 0xF0100001,
+		0xC78, 0xEF110001,
+		0xC78, 0xEE120001,
+		0xC78, 0xED130001,
+		0xC78, 0xEC140001,
+		0xC78, 0xEB150001,
+		0xC78, 0xEA160001,
+		0xC78, 0xE9170001,
+		0xC78, 0xE8180001,
+		0xC78, 0xE7190001,
+		0xC78, 0xE61A0001,
+		0xC78, 0xE51B0001,
+		0xC78, 0xE41C0001,
+		0xC78, 0xE31D0001,
+		0xC78, 0xE21E0001,
+		0xC78, 0xE11F0001,
+		0xC78, 0x8A200001,
+		0xC78, 0x89210001,
+		0xC78, 0x88220001,
+		0xC78, 0x87230001,
+		0xC78, 0x86240001,
+		0xC78, 0x85250001,
+		0xC78, 0x84260001,
+		0xC78, 0x83270001,
+		0xC78, 0x82280001,
+		0xC78, 0x6B290001,
+		0xC78, 0x6A2A0001,
+		0xC78, 0x692B0001,
+		0xC78, 0x682C0001,
+		0xC78, 0x672D0001,
+		0xC78, 0x662E0001,
+		0xC78, 0x652F0001,
+		0xC78, 0x64300001,
+		0xC78, 0x63310001,
+		0xC78, 0x62320001,
+		0xC78, 0x61330001,
+		0xC78, 0x46340001,
+		0xC78, 0x45350001,
+		0xC78, 0x44360001,
+		0xC78, 0x43370001,
+		0xC78, 0x42380001,
+		0xC78, 0x41390001,
+		0xC78, 0x403A0001,
+		0xC78, 0x403B0001,
+		0xC78, 0x403C0001,
+		0xC78, 0x403D0001,
+		0xC78, 0x403E0001,
+		0xC78, 0x403F0001,
+		0xC78, 0xFB400001,
+		0xC78, 0xFB410001,
+		0xC78, 0xFB420001,
+		0xC78, 0xFB430001,
+		0xC78, 0xFB440001,
+		0xC78, 0xFB450001,
+		0xC78, 0xFB460001,
+		0xC78, 0xFB470001,
+		0xC78, 0xFB480001,
+		0xC78, 0xFA490001,
+		0xC78, 0xF94A0001,
+		0xC78, 0xF84B0001,
+		0xC78, 0xF74C0001,
+		0xC78, 0xF64D0001,
+		0xC78, 0xF54E0001,
+		0xC78, 0xF44F0001,
+		0xC78, 0xF3500001,
+		0xC78, 0xF2510001,
+		0xC78, 0xF1520001,
+		0xC78, 0xF0530001,
+		0xC78, 0xEF540001,
+		0xC78, 0xEE550001,
+		0xC78, 0xED560001,
+		0xC78, 0xEC570001,
+		0xC78, 0xEB580001,
+		0xC78, 0xEA590001,
+		0xC78, 0xE95A0001,
+		0xC78, 0xE85B0001,
+		0xC78, 0xE75C0001,
+		0xC78, 0xE65D0001,
+		0xC78, 0xE55E0001,
+		0xC78, 0xE45F0001,
+		0xC78, 0xE3600001,
+		0xC78, 0xE2610001,
+		0xC78, 0xC3620001,
+		0xC78, 0xC2630001,
+		0xC78, 0xC1640001,
+		0xC78, 0x8B650001,
+		0xC78, 0x8A660001,
+		0xC78, 0x89670001,
+		0xC78, 0x88680001,
+		0xC78, 0x87690001,
+		0xC78, 0x866A0001,
+		0xC78, 0x856B0001,
+		0xC78, 0x846C0001,
+		0xC78, 0x676D0001,
+		0xC78, 0x666E0001,
+		0xC78, 0x656F0001,
+		0xC78, 0x64700001,
+		0xC78, 0x63710001,
+		0xC78, 0x62720001,
+		0xC78, 0x61730001,
+		0xC78, 0x60740001,
+		0xC78, 0x46750001,
+		0xC78, 0x45760001,
+		0xC78, 0x44770001,
+		0xC78, 0x43780001,
+		0xC78, 0x42790001,
+		0xC78, 0x417A0001,
+		0xC78, 0x407B0001,
+		0xC78, 0x407C0001,
+		0xC78, 0x407D0001,
+		0xC78, 0x407E0001,
+		0xC78, 0x407F0001,
+};
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/table.h b/drivers/net/wireless/rtlwifi/rtl8188ee/table.h
new file mode 100644
index 0000000..c1218e83
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8188ee/table.h
@@ -0,0 +1,47 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2013  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.
+ *
+ * Created on  2010/ 5/18,  1:41
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL92CE_TABLE__H_
+#define __RTL92CE_TABLE__H_
+
+#include <linux/types.h>
+#define  RTL8188EEPHY_REG_1TARRAYLEN	382
+extern u32 RTL8188EEPHY_REG_1TARRAY[];
+#define RTL8188EEPHY_REG_ARRAY_PGLEN	264
+extern u32 RTL8188EEPHY_REG_ARRAY_PG[];
+#define	RTL8188EE_RADIOA_1TARRAYLEN	190
+extern u32 RTL8188EE_RADIOA_1TARRAY[];
+#define RTL8188EEMAC_1T_ARRAYLEN	180
+extern u32 RTL8188EEMAC_1T_ARRAY[];
+#define RTL8188EEAGCTAB_1TARRAYLEN	256
+extern u32 RTL8188EEAGCTAB_1TARRAY[];
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c b/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c
new file mode 100644
index 0000000..d075237
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c
@@ -0,0 +1,817 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2013  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 "../stats.h"
+#include "reg.h"
+#include "def.h"
+#include "phy.h"
+#include "trx.h"
+#include "led.h"
+#include "dm.h"
+
+static u8 _rtl88ee_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) || ieee80211_is_ctl(fc))
+		return QSLT_MGNT;
+
+	return skb->priority;
+}
+
+static void _rtl88ee_query_rxphystatus(struct ieee80211_hw *hw,
+			struct rtl_stats *pstatus, u8 *pdesc,
+			struct rx_fwinfo_88e *p_drvinfo,
+			bool bpacket_match_bssid,
+			bool bpacket_toself, bool packet_beacon)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv);
+	struct phy_sts_cck_8192s_t *cck_buf;
+	struct phy_status_rpt *phystrpt = (struct phy_status_rpt *)p_drvinfo;
+	struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
+	char rx_pwr_all = 0, rx_pwr[4];
+	u8 rf_rx_num = 0, evm, pwdb_all;
+	u8 i, max_spatial_stream;
+	u32 rssi, total_rssi = 0;
+	bool is_cck = pstatus->is_cck;
+	u8 lan_idx, vga_idx;
+
+	/* Record it for next packet processing */
+	pstatus->packet_matchbssid = bpacket_match_bssid;
+	pstatus->packet_toself = bpacket_toself;
+	pstatus->packet_beacon = packet_beacon;
+	pstatus->rx_mimo_sig_qual[0] = -1;
+	pstatus->rx_mimo_sig_qual[1] = -1;
+
+	if (is_cck) {
+		u8 cck_hipwr;
+		u8 cck_agc_rpt;
+		/* CCK Driver info Structure is not the same as OFDM packet. */
+		cck_buf = (struct phy_sts_cck_8192s_t *)p_drvinfo;
+		cck_agc_rpt = cck_buf->cck_agc_rpt;
+
+		/* (1)Hardware does not provide RSSI for CCK
+		 * (2)PWDB, Average PWDB cacluated by
+		 * hardware (for rate adaptive)
+		 */
+		if (ppsc->rfpwr_state == ERFON)
+			cck_hipwr = rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2,
+						  BIT(9));
+		else
+			cck_hipwr = false;
+
+		lan_idx = ((cck_agc_rpt & 0xE0) >> 5);
+		vga_idx = (cck_agc_rpt & 0x1f);
+		switch (lan_idx) {
+		case 7:
+			if (vga_idx <= 27)
+				rx_pwr_all = -100 + 2 * (27 - vga_idx);
+			else
+				rx_pwr_all = -100;
+			break;
+		case 6:
+			rx_pwr_all = -48 + 2 * (2 - vga_idx); /*VGA_idx = 2~0*/
+			break;
+		case 5:
+			rx_pwr_all = -42 + 2 * (7 - vga_idx); /*VGA_idx = 7~5*/
+			break;
+		case 4:
+			rx_pwr_all = -36 + 2 * (7 - vga_idx); /*VGA_idx = 7~4*/
+			break;
+		case 3:
+			rx_pwr_all = -24 + 2 * (7 - vga_idx); /*VGA_idx = 7~0*/
+			break;
+		case 2:
+			if (cck_hipwr)
+				rx_pwr_all = -12 + 2 * (5 - vga_idx);
+			else
+				rx_pwr_all = -6 + 2 * (5 - vga_idx);
+			break;
+		case 1:
+			rx_pwr_all = 8 - 2 * vga_idx;
+			break;
+		case 0:
+			rx_pwr_all = 14 - 2 * vga_idx;
+			break;
+		default:
+			break;
+		}
+		rx_pwr_all += 6;
+		pwdb_all = rtl_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;
+		if (cck_hipwr == false) {
+			if (pwdb_all >= 80)
+				pwdb_all = ((pwdb_all - 80)<<1) +
+					   ((pwdb_all - 80)>>1) + 80;
+			else if ((pwdb_all <= 78) && (pwdb_all >= 20))
+				pwdb_all += 3;
+			if (pwdb_all > 100)
+				pwdb_all = 100;
+		}
+
+		pstatus->rx_pwdb_all = pwdb_all;
+		pstatus->recvsignalpower = rx_pwr_all;
+
+		/* (3) Get Signal Quality (EVM) */
+		if (bpacket_match_bssid) {
+			u8 sq;
+
+			if (pstatus->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;
+			}
+
+			pstatus->signalquality = sq;
+			pstatus->rx_mimo_sig_qual[0] = sq;
+			pstatus->rx_mimo_sig_qual[1] = -1;
+		}
+	} else {
+		rtlpriv->dm.rfpath_rxenable[0] =
+		    rtlpriv->dm.rfpath_rxenable[1] = true;
+
+		/* (1)Get RSSI for HT rate */
+		for (i = RF90_PATH_A; i < RF6052_MAX_PATH; i++) {
+			/* we will judge RF RX path now. */
+			if (rtlpriv->dm.rfpath_rxenable[i])
+				rf_rx_num++;
+
+			rx_pwr[i] = ((p_drvinfo->gain_trsw[i] & 0x3f) * 2)-110;
+
+			/* Translate DBM to percentage. */
+			rssi = rtl_query_rxpwrpercentage(rx_pwr[i]);
+			total_rssi += rssi;
+
+			/* Get Rx snr value in DB */
+			rtlpriv->stats.rx_snr_db[i] = p_drvinfo->rxsnr[i] / 2;
+
+			/* Record Signal Strength for next packet */
+			if (bpacket_match_bssid)
+				pstatus->rx_mimo_signalstrength[i] = (u8) rssi;
+		}
+
+		/* (2)PWDB, Average PWDB cacluated by
+		 * hardware (for rate adaptive)
+		 */
+		rx_pwr_all = ((p_drvinfo->pwdb_all >> 1) & 0x7f) - 110;
+
+		pwdb_all = rtl_query_rxpwrpercentage(rx_pwr_all);
+		pstatus->rx_pwdb_all = pwdb_all;
+		pstatus->rxpower = rx_pwr_all;
+		pstatus->recvsignalpower = rx_pwr_all;
+
+		/* (3)EVM of HT rate */
+		if (pstatus->is_ht && pstatus->rate >= DESC92C_RATEMCS8 &&
+		    pstatus->rate <= DESC92C_RATEMCS15)
+			max_spatial_stream = 2;
+		else
+			max_spatial_stream = 1;
+
+		for (i = 0; i < max_spatial_stream; i++) {
+			evm = rtl_evm_db_to_percentage(p_drvinfo->rxevm[i]);
+
+			if (bpacket_match_bssid) {
+				/* Fill value in RFD, Get the first
+				 * spatial stream only
+				 */
+				if (i == 0)
+					pstatus->signalquality = evm & 0xff;
+				pstatus->rx_mimo_sig_qual[i] = evm & 0xff;
+			}
+		}
+	}
+
+	/* UI BSS List signal strength(in percentage),
+	 * make it good looking, from 0~100.
+	 */
+	if (is_cck)
+		pstatus->signalstrength = (u8)(rtl_signal_scale_mapping(hw,
+					  pwdb_all));
+	else if (rf_rx_num != 0)
+		pstatus->signalstrength = (u8)(rtl_signal_scale_mapping(hw,
+					  total_rssi /= rf_rx_num));
+	/*HW antenna diversity*/
+	rtldm->fat_table.antsel_rx_keep_0 = phystrpt->ant_sel;
+	rtldm->fat_table.antsel_rx_keep_1 = phystrpt->ant_sel_b;
+	rtldm->fat_table.antsel_rx_keep_2 = phystrpt->antsel_rx_keep_2;
+}
+
+static void _rtl88ee_smart_antenna(struct ieee80211_hw *hw,
+	struct rtl_stats *pstatus)
+{
+	struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	u8 ant_mux;
+	struct fast_ant_training *pfat = &(rtldm->fat_table);
+
+	if (rtlefuse->antenna_div_type == CG_TRX_SMART_ANTDIV) {
+		if (pfat->fat_state == FAT_TRAINING_STATE) {
+			if (pstatus->packet_toself) {
+				ant_mux = (pfat->antsel_rx_keep_2 << 2) |
+						(pfat->antsel_rx_keep_1 << 1) |
+						 pfat->antsel_rx_keep_0;
+				pfat->ant_sum[ant_mux] += pstatus->rx_pwdb_all;
+				pfat->ant_cnt[ant_mux]++;
+			}
+		}
+	} else if ((rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) ||
+		   (rtlefuse->antenna_div_type == CGCS_RX_HW_ANTDIV)) {
+		if (pstatus->packet_toself || pstatus->packet_matchbssid) {
+			ant_mux = (pfat->antsel_rx_keep_2 << 2) |
+				  (pfat->antsel_rx_keep_1 << 1) |
+				   pfat->antsel_rx_keep_0;
+			rtl88e_dm_ant_sel_statistics(hw, ant_mux, 0,
+						     pstatus->rx_pwdb_all);
+		}
+	}
+}
+
+static void _rtl88ee_translate_rx_signal_stuff(struct ieee80211_hw *hw,
+		struct sk_buff *skb, struct rtl_stats *pstatus,
+		u8 *pdesc, struct rx_fwinfo_88e *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;
+	u8 *psaddr;
+	__le16 fc;
+	u16 type, ufc;
+	bool match_bssid, packet_toself, packet_beacon, addr;
+
+	tmp_buf = skb->data + pstatus->rx_drvinfo_size + pstatus->rx_bufshift;
+
+	hdr = (struct ieee80211_hdr *)tmp_buf;
+	fc = hdr->frame_control;
+	ufc = le16_to_cpu(fc);
+	type = WLAN_FC_GET_TYPE(fc);
+	praddr = hdr->addr1;
+	psaddr = ieee80211_get_SA(hdr);
+	memcpy(pstatus->psaddr, psaddr, ETH_ALEN);
+
+	addr = (!compare_ether_addr(mac->bssid, (ufc & IEEE80211_FCTL_TODS) ?
+		hdr->addr1 : (ufc & IEEE80211_FCTL_FROMDS) ?
+		hdr->addr2 : hdr->addr3));
+	match_bssid = ((IEEE80211_FTYPE_CTL != type) && (!pstatus->hwerror) &&
+		       (!pstatus->crc) && (!pstatus->icv)) && addr;
+
+	addr = (!compare_ether_addr(praddr, rtlefuse->dev_addr));
+	packet_toself = match_bssid && addr;
+
+	if (ieee80211_is_beacon(fc))
+		packet_beacon = true;
+
+	_rtl88ee_query_rxphystatus(hw, pstatus, pdesc, p_drvinfo,
+				   match_bssid, packet_toself, packet_beacon);
+	_rtl88ee_smart_antenna(hw, pstatus);
+	rtl_process_phyinfo(hw, tmp_buf, pstatus);
+}
+
+static void insert_em(struct rtl_tcb_desc *ptcb_desc, u8 *virtualaddress)
+{
+	u32 dwtmp = 0;
+
+	memset(virtualaddress, 0, 8);
+
+	SET_EARLYMODE_PKTNUM(virtualaddress, ptcb_desc->empkt_num);
+	if (ptcb_desc->empkt_num == 1) {
+		dwtmp = ptcb_desc->empkt_len[0];
+	} else {
+		dwtmp = ptcb_desc->empkt_len[0];
+		dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4;
+		dwtmp += ptcb_desc->empkt_len[1];
+	}
+	SET_EARLYMODE_LEN0(virtualaddress, dwtmp);
+
+	if (ptcb_desc->empkt_num <= 3) {
+		dwtmp = ptcb_desc->empkt_len[2];
+	} else {
+		dwtmp = ptcb_desc->empkt_len[2];
+		dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4;
+		dwtmp += ptcb_desc->empkt_len[3];
+	}
+	SET_EARLYMODE_LEN1(virtualaddress, dwtmp);
+	if (ptcb_desc->empkt_num <= 5) {
+		dwtmp = ptcb_desc->empkt_len[4];
+	} else {
+		dwtmp = ptcb_desc->empkt_len[4];
+		dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4;
+		dwtmp += ptcb_desc->empkt_len[5];
+	}
+	SET_EARLYMODE_LEN2_1(virtualaddress, dwtmp & 0xF);
+	SET_EARLYMODE_LEN2_2(virtualaddress, dwtmp >> 4);
+	if (ptcb_desc->empkt_num <= 7) {
+		dwtmp = ptcb_desc->empkt_len[6];
+	} else {
+		dwtmp = ptcb_desc->empkt_len[6];
+		dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4;
+		dwtmp += ptcb_desc->empkt_len[7];
+	}
+	SET_EARLYMODE_LEN3(virtualaddress, dwtmp);
+	if (ptcb_desc->empkt_num <= 9) {
+		dwtmp = ptcb_desc->empkt_len[8];
+	} else {
+		dwtmp = ptcb_desc->empkt_len[8];
+		dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4;
+		dwtmp += ptcb_desc->empkt_len[9];
+	}
+	SET_EARLYMODE_LEN4(virtualaddress, dwtmp);
+}
+
+bool rtl88ee_rx_query_desc(struct ieee80211_hw *hw,
+			   struct rtl_stats *status,
+			   struct ieee80211_rx_status *rx_status,
+			   u8 *pdesc, struct sk_buff *skb)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rx_fwinfo_88e *p_drvinfo;
+	struct ieee80211_hdr *hdr;
+
+	u32 phystatus = GET_RX_DESC_PHYST(pdesc);
+	status->packet_report_type = (u8)GET_RX_STATUS_DESC_RPT_SEL(pdesc);
+	if (status->packet_report_type == TX_REPORT2)
+		status->length = (u16) GET_RX_RPT2_DESC_PKT_LEN(pdesc);
+	else
+		status->length = (u16) GET_RX_DESC_PKT_LEN(pdesc);
+	status->rx_drvinfo_size = (u8) GET_RX_DESC_DRV_INFO_SIZE(pdesc) *
+				       RX_DRV_INFO_SIZE_UNIT;
+	status->rx_bufshift = (u8) (GET_RX_DESC_SHIFT(pdesc) & 0x03);
+	status->icv = (u16) GET_RX_DESC_ICV(pdesc);
+	status->crc = (u16) GET_RX_DESC_CRC32(pdesc);
+	status->hwerror = (status->crc | status->icv);
+	status->decrypted = !GET_RX_DESC_SWDEC(pdesc);
+	status->rate = (u8) GET_RX_DESC_RXMCS(pdesc);
+	status->shortpreamble = (u16) GET_RX_DESC_SPLCP(pdesc);
+	status->isampdu = (bool) (GET_RX_DESC_PAGGR(pdesc) == 1);
+	status->isfirst_ampdu = (bool) ((GET_RX_DESC_PAGGR(pdesc) == 1) &&
+					(GET_RX_DESC_FAGGR(pdesc) == 1));
+	if (status->packet_report_type == NORMAL_RX)
+		status->timestamp_low = GET_RX_DESC_TSFL(pdesc);
+	status->rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(pdesc);
+	status->is_ht = (bool)GET_RX_DESC_RXHT(pdesc);
+
+	status->is_cck = RTL8188_RX_HAL_IS_CCK_RATE(status->rate);
+
+	status->macid = GET_RX_DESC_MACID(pdesc);
+	if (GET_RX_STATUS_DESC_MAGIC_MATCH(pdesc))
+		status->wake_match = BIT(2);
+	else if (GET_RX_STATUS_DESC_MAGIC_MATCH(pdesc))
+		status->wake_match = BIT(1);
+	else if (GET_RX_STATUS_DESC_UNICAST_MATCH(pdesc))
+		status->wake_match = BIT(0);
+	else
+		status->wake_match = 0;
+	if (status->wake_match)
+		RT_TRACE(rtlpriv, COMP_RXDESC, DBG_LOUD,
+			 "Get Wakeup Packet!! WakeMatch =%d\n",
+			 status->wake_match);
+	rx_status->freq = hw->conf.channel->center_freq;
+	rx_status->band = hw->conf.channel->band;
+
+	if (status->crc)
+		rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
+
+	if (status->rx_is40Mhzpacket)
+		rx_status->flag |= RX_FLAG_40MHZ;
+
+	if (status->is_ht)
+		rx_status->flag |= RX_FLAG_HT;
+
+	rx_status->flag |= RX_FLAG_MACTIME_START;
+
+	/* hw will set status->decrypted true, if it finds the
+	 * frame is open data frame or mgmt frame.
+	 * So hw will not decryption robust managment frame
+	 * for IEEE80211w but still set status->decrypted
+	 * true, so here we should set it back to undecrypted
+	 * for IEEE80211w frame, and mac80211 sw will help
+	 * to decrypt it
+	 */
+	if (status->decrypted) {
+		hdr = (struct ieee80211_hdr *)(skb->data +
+		       status->rx_drvinfo_size + status->rx_bufshift);
+
+		if (!hdr) {
+			/* During testing, hdr was NULL */
+			return false;
+		}
+		if ((ieee80211_is_robust_mgmt_frame(hdr)) &&
+		    (ieee80211_has_protected(hdr->frame_control)))
+			rx_status->flag &= ~RX_FLAG_DECRYPTED;
+		else
+			rx_status->flag |= RX_FLAG_DECRYPTED;
+	}
+
+	/* rate_idx: index of data rate into band's
+	 * supported rates or MCS index if HT rates
+	 * are use (RX_FLAG_HT)
+	 * Notice: this is diff with windows define
+	 */
+	rx_status->rate_idx = rtlwifi_rate_mapping(hw, status->is_ht,
+						   status->rate, false);
+
+	rx_status->mactime = status->timestamp_low;
+	if (phystatus == true) {
+		p_drvinfo = (struct rx_fwinfo_88e *)(skb->data +
+						     status->rx_bufshift);
+
+		_rtl88ee_translate_rx_signal_stuff(hw, skb, status, pdesc,
+						   p_drvinfo);
+	}
+
+	/*rx_status->qual = status->signal; */
+	rx_status->signal = status->recvsignalpower + 10;
+	/*rx_status->noise = -status->noise; */
+	if (status->packet_report_type == TX_REPORT2) {
+		status->macid_valid_entry[0] =
+			 GET_RX_RPT2_DESC_MACID_VALID_1(pdesc);
+		status->macid_valid_entry[1] =
+			 GET_RX_RPT2_DESC_MACID_VALID_2(pdesc);
+	}
+	return true;
+}
+
+void rtl88ee_tx_fill_desc(struct ieee80211_hw *hw,
+			  struct ieee80211_hdr *hdr, u8 *pdesc_tx,
+			  struct ieee80211_tx_info *info,
+			  struct ieee80211_sta *sta,
+			  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);
+	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 = _rtl88ee_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;
+	u8 short_gi = 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);
+	if (pci_dma_mapping_error(rtlpci->pdev, mapping)) {
+		RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE,
+			 "DMA mapping error");
+		return;
+	}
+	CLEAR_PCI_TX_DESC_CONTENT(pdesc, sizeof(struct tx_desc_88e));
+	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_TRACE,
+					 "Insert 8 byte.pTcb->EMPktNum:%d\n",
+					 ptcb_desc->empkt_num);
+				insert_em(ptcb_desc, (u8 *)(skb->data));
+			}
+		} else {
+			SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN);
+		}
+
+		ptcb_desc->use_driver_rate = true;
+		SET_TX_DESC_TX_RATE(pdesc, ptcb_desc->hw_rate);
+		if (ptcb_desc->hw_rate > DESC92C_RATEMCS0)
+			short_gi = (ptcb_desc->use_shortgi) ? 1 : 0;
+		else
+			short_gi = (ptcb_desc->use_shortpreamble) ? 1 : 0;
+		SET_TX_DESC_DATA_SHORTGI(pdesc, short_gi);
+
+		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, 0);
+		SET_TX_DESC_CTS2SELF(pdesc, ((ptcb_desc->cts_enable) ? 1 : 0));
+		SET_TX_DESC_RTS_STBC(pdesc, ((ptcb_desc->rts_stbc) ? 1 : 0));
+
+		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 <= DESC92C_RATE54M) ?
+			(ptcb_desc->rts_use_shortpreamble ? 1 : 0) :
+			(ptcb_desc->rts_use_shortgi ? 1 : 0)));
+
+		if (ptcb_desc->btx_enable_sw_calc_duration)
+			SET_TX_DESC_NAV_USE_HDR(pdesc, 1);
+
+		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_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))
+		SET_TX_DESC_HWSEQ_EN(pdesc, 1);
+	SET_TX_DESC_MORE_FRAG(pdesc, (lastseg ? 0 : 1));
+	if (is_multicast_ether_addr(ieee80211_get_DA(hdr)) ||
+	    is_broadcast_ether_addr(ieee80211_get_DA(hdr)))
+		SET_TX_DESC_BMC(pdesc, 1);
+
+	rtl88e_dm_set_tx_ant_by_tx_info(hw, pdesc, ptcb_desc->mac_id);
+	RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, "\n");
+}
+
+void rtl88ee_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));
+	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;
+
+	if (pci_dma_mapping_error(rtlpci->pdev, mapping)) {
+		RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE,
+			 "DMA mapping error");
+		return;
+	}
+	CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE);
+
+	if (firstseg)
+		SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN);
+
+	SET_TX_DESC_TX_RATE(pdesc, DESC92C_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_OWN(pdesc, 1);
+
+	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))
+		SET_TX_DESC_HWSEQ_EN(pdesc, 1);
+
+	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
+		      "H2C Tx Cmd Content\n",
+		      pdesc, TX_DESC_SIZE);
+}
+
+void rtl88ee_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val)
+{
+	if (istx == true) {
+		switch (desc_name) {
+		case HW_DESC_OWN:
+			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 processed\n",
+				  desc_name);
+			break;
+		}
+	} else {
+		switch (desc_name) {
+		case HW_DESC_RXOWN:
+			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 processed\n",
+				  desc_name);
+			break;
+		}
+	}
+}
+
+u32 rtl88ee_get_desc(u8 *pdesc, bool istx, u8 desc_name)
+{
+	u32 ret = 0;
+
+	if (istx == true) {
+		switch (desc_name) {
+		case HW_DESC_OWN:
+			ret = GET_TX_DESC_OWN(pdesc);
+			break;
+		case HW_DESC_TXBUFF_ADDR:
+			ret = GET_TX_DESC_TX_BUFFER_ADDRESS(pdesc);
+			break;
+		default:
+			RT_ASSERT(false, "ERR txdesc :%d not processed\n",
+				  desc_name);
+			break;
+		}
+	} else {
+		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 processed\n",
+				  desc_name);
+			break;
+		}
+	}
+	return ret;
+}
+
+void rtl88ee_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/rtl8188ee/trx.h b/drivers/net/wireless/rtlwifi/rtl8188ee/trx.h
new file mode 100644
index 0000000..d3a02e7
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8188ee/trx.h
@@ -0,0 +1,795 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2013  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_TRX_H__
+#define __RTL92CE_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 SET_TX_DESC_PKT_SIZE(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc, 0, 16, __val)
+#define SET_TX_DESC_OFFSET(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc, 16, 8, __val)
+#define SET_TX_DESC_BMC(__pdesc, __val)			\
+	SET_BITS_TO_LE_4BYTE(__pdesc, 24, 1, __val)
+#define SET_TX_DESC_HTC(__pdesc, __val)			\
+	SET_BITS_TO_LE_4BYTE(__pdesc, 25, 1, __val)
+#define SET_TX_DESC_LAST_SEG(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc, 26, 1, __val)
+#define SET_TX_DESC_FIRST_SEG(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc, 27, 1, __val)
+#define SET_TX_DESC_LINIP(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc, 28, 1, __val)
+#define SET_TX_DESC_NO_ACM(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc, 29, 1, __val)
+#define SET_TX_DESC_GF(__pdesc, __val)			\
+	SET_BITS_TO_LE_4BYTE(__pdesc, 30, 1, __val)
+#define SET_TX_DESC_OWN(__pdesc, __val)			\
+	SET_BITS_TO_LE_4BYTE(__pdesc, 31, 1, __val)
+
+#define GET_TX_DESC_PKT_SIZE(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc, 0, 16)
+#define GET_TX_DESC_OFFSET(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc, 16, 8)
+#define GET_TX_DESC_BMC(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc, 24, 1)
+#define GET_TX_DESC_HTC(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc, 25, 1)
+#define GET_TX_DESC_LAST_SEG(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc, 26, 1)
+#define GET_TX_DESC_FIRST_SEG(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc, 27, 1)
+#define GET_TX_DESC_LINIP(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc, 28, 1)
+#define GET_TX_DESC_NO_ACM(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc, 29, 1)
+#define GET_TX_DESC_GF(__pdesc)				\
+	LE_BITS_TO_4BYTE(__pdesc, 30, 1)
+#define GET_TX_DESC_OWN(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc, 31, 1)
+
+#define SET_TX_DESC_MACID(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+4, 0, 6, __val)
+#define SET_TX_DESC_QUEUE_SEL(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+4, 8, 5, __val)
+#define SET_TX_DESC_RDG_NAV_EXT(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+4, 13, 1, __val)
+#define SET_TX_DESC_LSIG_TXOP_EN(__pdesc, __val)	\
+	SET_BITS_TO_LE_4BYTE(__pdesc+4, 14, 1, __val)
+#define SET_TX_DESC_PIFS(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+4, 15, 1, __val)
+#define SET_TX_DESC_RATE_ID(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+4, 16, 4, __val)
+#define SET_TX_DESC_NAV_USE_HDR(__pdesc, __val)	\
+	SET_BITS_TO_LE_4BYTE(__pdesc+4, 20, 1, __val)
+#define SET_TX_DESC_EN_DESC_ID(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+4, 21, 1, __val)
+#define SET_TX_DESC_SEC_TYPE(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+4, 22, 2, __val)
+#define SET_TX_DESC_PKT_OFFSET(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+4, 26, 5, __val)
+#define SET_TX_DESC_PADDING_LEN(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+4, 24, 8, __val)
+
+#define GET_TX_DESC_MACID(__pdesc)				\
+	LE_BITS_TO_4BYTE(__pdesc+4, 0, 5)
+#define GET_TX_DESC_AGG_ENABLE(__pdesc)				\
+	LE_BITS_TO_4BYTE(__pdesc+4, 5, 1)
+#define GET_TX_DESC_AGG_BREAK(__pdesc)				\
+	LE_BITS_TO_4BYTE(__pdesc+4, 6, 1)
+#define GET_TX_DESC_RDG_ENABLE(__pdesc)				\
+	LE_BITS_TO_4BYTE(__pdesc+4, 7, 1)
+#define GET_TX_DESC_QUEUE_SEL(__pdesc)				\
+	LE_BITS_TO_4BYTE(__pdesc+4, 8, 5)
+#define GET_TX_DESC_RDG_NAV_EXT(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+4, 13, 1)
+#define GET_TX_DESC_LSIG_TXOP_EN(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+4, 14, 1)
+#define GET_TX_DESC_PIFS(__pdesc)				\
+	LE_BITS_TO_4BYTE(__pdesc+4, 15, 1)
+#define GET_TX_DESC_RATE_ID(__pdesc)				\
+	LE_BITS_TO_4BYTE(__pdesc+4, 16, 4)
+#define GET_TX_DESC_NAV_USE_HDR(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+4, 20, 1)
+#define GET_TX_DESC_EN_DESC_ID(__pdesc)				\
+	LE_BITS_TO_4BYTE(__pdesc+4, 21, 1)
+#define GET_TX_DESC_SEC_TYPE(__pdesc)				\
+	LE_BITS_TO_4BYTE(__pdesc+4, 22, 2)
+#define GET_TX_DESC_PKT_OFFSET(__pdesc)				\
+	LE_BITS_TO_4BYTE(__pdesc+4, 24, 8)
+
+#define SET_TX_DESC_RTS_RC(__pdesc, __val)			\
+	SET_BITS_TO_LE_4BYTE(__pdesc+8, 0, 6, __val)
+#define SET_TX_DESC_DATA_RC(__pdesc, __val)			\
+	SET_BITS_TO_LE_4BYTE(__pdesc+8, 6, 6, __val)
+#define SET_TX_DESC_AGG_ENABLE(__pdesc, __val)			\
+	SET_BITS_TO_LE_4BYTE(__pdesc+8, 12, 1, __val)
+#define SET_TX_DESC_RDG_ENABLE(__pdesc, __val)			\
+	SET_BITS_TO_LE_4BYTE(__pdesc+8, 13, 1, __val)
+#define SET_TX_DESC_BAR_RTY_TH(__pdesc, __val)			\
+	SET_BITS_TO_LE_4BYTE(__pdesc+8, 14, 2, __val)
+#define SET_TX_DESC_AGG_BREAK(__pdesc, __val)			\
+	SET_BITS_TO_LE_4BYTE(__pdesc+8, 16, 1, __val)
+#define SET_TX_DESC_MORE_FRAG(__pdesc, __val)			\
+	SET_BITS_TO_LE_4BYTE(__pdesc+8, 17, 1, __val)
+#define SET_TX_DESC_RAW(__pdesc, __val)				\
+	SET_BITS_TO_LE_4BYTE(__pdesc+8, 18, 1, __val)
+#define SET_TX_DESC_CCX(__pdesc, __val)				\
+	SET_BITS_TO_LE_4BYTE(__pdesc+8, 19, 1, __val)
+#define SET_TX_DESC_AMPDU_DENSITY(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+8, 20, 3, __val)
+#define SET_TX_DESC_BT_INT(__pdesc, __val)			\
+	SET_BITS_TO_LE_4BYTE(__pdesc+8, 23, 1, __val)
+#define SET_TX_DESC_ANTSEL_A(__pdesc, __val)			\
+	SET_BITS_TO_LE_4BYTE(__pdesc+8, 24, 1, __val)
+#define SET_TX_DESC_ANTSEL_B(__pdesc, __val)			\
+	SET_BITS_TO_LE_4BYTE(__pdesc+8, 25, 1, __val)
+#define SET_TX_DESC_TX_ANT_CCK(__pdesc, __val)			\
+	SET_BITS_TO_LE_4BYTE(__pdesc+8, 26, 2, __val)
+#define SET_TX_DESC_TX_ANTL(__pdesc, __val)			\
+	SET_BITS_TO_LE_4BYTE(__pdesc+8, 28, 2, __val)
+#define SET_TX_DESC_TX_ANT_HT(__pdesc, __val)			\
+	SET_BITS_TO_LE_4BYTE(__pdesc+8, 30, 2, __val)
+
+#define GET_TX_DESC_RTS_RC(__pdesc)				\
+	LE_BITS_TO_4BYTE(__pdesc+8, 0, 6)
+#define GET_TX_DESC_DATA_RC(__pdesc)				\
+	LE_BITS_TO_4BYTE(__pdesc+8, 6, 6)
+#define GET_TX_DESC_BAR_RTY_TH(__pdesc)				\
+	LE_BITS_TO_4BYTE(__pdesc+8, 14, 2)
+#define GET_TX_DESC_MORE_FRAG(__pdesc)				\
+	LE_BITS_TO_4BYTE(__pdesc+8, 17, 1)
+#define GET_TX_DESC_RAW(__pdesc)				\
+	LE_BITS_TO_4BYTE(__pdesc+8, 18, 1)
+#define GET_TX_DESC_CCX(__pdesc)				\
+	LE_BITS_TO_4BYTE(__pdesc+8, 19, 1)
+#define GET_TX_DESC_AMPDU_DENSITY(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+8, 20, 3)
+#define GET_TX_DESC_ANTSEL_A(__pdesc)				\
+	LE_BITS_TO_4BYTE(__pdesc+8, 24, 1)
+#define GET_TX_DESC_ANTSEL_B(__pdesc)				\
+	LE_BITS_TO_4BYTE(__pdesc+8, 25, 1)
+#define GET_TX_DESC_TX_ANT_CCK(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+8, 26, 2)
+#define GET_TX_DESC_TX_ANTL(__pdesc)				\
+	LE_BITS_TO_4BYTE(__pdesc+8, 28, 2)
+#define GET_TX_DESC_TX_ANT_HT(__pdesc)				\
+	LE_BITS_TO_4BYTE(__pdesc+8, 30, 2)
+
+#define SET_TX_DESC_NEXT_HEAP_PAGE(__pdesc, __val)	\
+	SET_BITS_TO_LE_4BYTE(__pdesc+12, 0, 8, __val)
+#define SET_TX_DESC_TAIL_PAGE(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+12, 8, 8, __val)
+#define SET_TX_DESC_SEQ(__pdesc, __val)			\
+	SET_BITS_TO_LE_4BYTE(__pdesc+12, 16, 12, __val)
+#define SET_TX_DESC_CPU_HANDLE(__pdesc, __val)			\
+	SET_BITS_TO_LE_4BYTE(__pdesc+12, 28, 1, __val)
+#define SET_TX_DESC_TAG1(__pdesc, __val)			\
+	SET_BITS_TO_LE_4BYTE(__pdesc+12, 29, 1, __val)
+#define SET_TX_DESC_TRIGGER_INT(__pdesc, __val)			\
+	SET_BITS_TO_LE_4BYTE(__pdesc+12, 30, 1, __val)
+#define SET_TX_DESC_HWSEQ_EN(__pdesc, __val)			\
+	SET_BITS_TO_LE_4BYTE(__pdesc+12, 31, 1, __val)
+
+
+#define GET_TX_DESC_NEXT_HEAP_PAGE(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+12, 0, 8)
+#define GET_TX_DESC_TAIL_PAGE(__pdesc)				\
+	LE_BITS_TO_4BYTE(__pdesc+12, 8, 8)
+#define GET_TX_DESC_SEQ(__pdesc)					\
+	LE_BITS_TO_4BYTE(__pdesc+12, 16, 12)
+
+
+#define SET_TX_DESC_RTS_RATE(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+16, 0, 5, __val)
+#define SET_TX_DESC_AP_DCFE(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+16, 5, 1, __val)
+#define SET_TX_DESC_QOS(__pdesc, __val)			\
+	SET_BITS_TO_LE_4BYTE(__pdesc+16, 6, 1, __val)
+#define SET_TX_DESC_HWSEQ_SSN(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+16, 7, 1, __val)
+#define SET_TX_DESC_USE_RATE(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+16, 8, 1, __val)
+#define SET_TX_DESC_DISABLE_RTS_FB(__pdesc, __val)	\
+	SET_BITS_TO_LE_4BYTE(__pdesc+16, 9, 1, __val)
+#define SET_TX_DESC_DISABLE_FB(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+16, 10, 1, __val)
+#define SET_TX_DESC_CTS2SELF(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+16, 11, 1, __val)
+#define SET_TX_DESC_RTS_ENABLE(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+16, 12, 1, __val)
+#define SET_TX_DESC_HW_RTS_ENABLE(__pdesc, __val)	\
+	SET_BITS_TO_LE_4BYTE(__pdesc+16, 13, 1, __val)
+#define SET_TX_DESC_PORT_ID(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+16, 14, 1, __val)
+#define SET_TX_DESC_PWR_STATUS(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+16, 15, 3, __val)
+#define SET_TX_DESC_WAIT_DCTS(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+16, 18, 1, __val)
+#define SET_TX_DESC_CTS2AP_EN(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+16, 19, 1, __val)
+#define SET_TX_DESC_TX_SUB_CARRIER(__pdesc, __val)	\
+	SET_BITS_TO_LE_4BYTE(__pdesc+16, 20, 2, __val)
+#define SET_TX_DESC_TX_STBC(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+16, 22, 2, __val)
+#define SET_TX_DESC_DATA_SHORT(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+16, 24, 1, __val)
+#define SET_TX_DESC_DATA_BW(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+16, 25, 1, __val)
+#define SET_TX_DESC_RTS_SHORT(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+16, 26, 1, __val)
+#define SET_TX_DESC_RTS_BW(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+16, 27, 1, __val)
+#define SET_TX_DESC_RTS_SC(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+16, 28, 2, __val)
+#define SET_TX_DESC_RTS_STBC(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+16, 30, 2, __val)
+
+#define GET_TX_DESC_RTS_RATE(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+16, 0, 5)
+#define GET_TX_DESC_AP_DCFE(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+16, 5, 1)
+#define GET_TX_DESC_QOS(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+16, 6, 1)
+#define GET_TX_DESC_HWSEQ_EN(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+16, 7, 1)
+#define GET_TX_DESC_USE_RATE(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+16, 8, 1)
+#define GET_TX_DESC_DISABLE_RTS_FB(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+16, 9, 1)
+#define GET_TX_DESC_DISABLE_FB(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+16, 10, 1)
+#define GET_TX_DESC_CTS2SELF(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+16, 11, 1)
+#define GET_TX_DESC_RTS_ENABLE(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+16, 12, 1)
+#define GET_TX_DESC_HW_RTS_ENABLE(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+16, 13, 1)
+#define GET_TX_DESC_PORT_ID(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+16, 14, 1)
+#define GET_TX_DESC_WAIT_DCTS(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+16, 18, 1)
+#define GET_TX_DESC_CTS2AP_EN(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+16, 19, 1)
+#define GET_TX_DESC_TX_SUB_CARRIER(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+16, 20, 2)
+#define GET_TX_DESC_TX_STBC(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+16, 22, 2)
+#define GET_TX_DESC_DATA_SHORT(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+16, 24, 1)
+#define GET_TX_DESC_DATA_BW(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+16, 25, 1)
+#define GET_TX_DESC_RTS_SHORT(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+16, 26, 1)
+#define GET_TX_DESC_RTS_BW(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+16, 27, 1)
+#define GET_TX_DESC_RTS_SC(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+16, 28, 2)
+#define GET_TX_DESC_RTS_STBC(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+16, 30, 2)
+
+#define SET_TX_DESC_TX_RATE(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+20, 0, 6, __val)
+#define SET_TX_DESC_DATA_SHORTGI(__pdesc, __val)	\
+	SET_BITS_TO_LE_4BYTE(__pdesc+20, 6, 1, __val)
+#define SET_TX_DESC_CCX_TAG(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+20, 7, 1, __val)
+#define SET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc, __val)	\
+	SET_BITS_TO_LE_4BYTE(__pdesc+20, 8, 5, __val)
+#define SET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc, __val)	\
+	SET_BITS_TO_LE_4BYTE(__pdesc+20, 13, 4, __val)
+#define SET_TX_DESC_RETRY_LIMIT_ENABLE(__pdesc, __val)	\
+	SET_BITS_TO_LE_4BYTE(__pdesc+20, 17, 1, __val)
+#define SET_TX_DESC_DATA_RETRY_LIMIT(__pdesc, __val)	\
+	SET_BITS_TO_LE_4BYTE(__pdesc+20, 18, 6, __val)
+#define SET_TX_DESC_USB_TXAGG_NUM(__pdesc, __val)	\
+	SET_BITS_TO_LE_4BYTE(__pdesc+20, 24, 8, __val)
+
+#define GET_TX_DESC_TX_RATE(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+20, 0, 6)
+#define GET_TX_DESC_DATA_SHORTGI(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+20, 6, 1)
+#define GET_TX_DESC_CCX_TAG(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+20, 7, 1)
+#define GET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+20, 8, 5)
+#define GET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+20, 13, 4)
+#define GET_TX_DESC_RETRY_LIMIT_ENABLE(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+20, 17, 1)
+#define GET_TX_DESC_DATA_RETRY_LIMIT(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+20, 18, 6)
+#define GET_TX_DESC_USB_TXAGG_NUM(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+20, 24, 8)
+
+#define SET_TX_DESC_TXAGC_A(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+24, 0, 5, __val)
+#define SET_TX_DESC_TXAGC_B(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+24, 5, 5, __val)
+#define SET_TX_DESC_USE_MAX_LEN(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+24, 10, 1, __val)
+#define SET_TX_DESC_MAX_AGG_NUM(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+24, 11, 5, __val)
+#define SET_TX_DESC_MCSG1_MAX_LEN(__pdesc, __val)	\
+	SET_BITS_TO_LE_4BYTE(__pdesc+24, 16, 4, __val)
+#define SET_TX_DESC_MCSG2_MAX_LEN(__pdesc, __val)	\
+	SET_BITS_TO_LE_4BYTE(__pdesc+24, 20, 4, __val)
+#define SET_TX_DESC_MCSG3_MAX_LEN(__pdesc, __val)	\
+	SET_BITS_TO_LE_4BYTE(__pdesc+24, 24, 4, __val)
+#define SET_TX_DESC_MCS7_SGI_MAX_LEN(__pdesc, __val)	\
+	SET_BITS_TO_LE_4BYTE(__pdesc+24, 28, 4, __val)
+
+#define GET_TX_DESC_TXAGC_A(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+24, 0, 5)
+#define GET_TX_DESC_TXAGC_B(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+24, 5, 5)
+#define GET_TX_DESC_USE_MAX_LEN(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+24, 10, 1)
+#define GET_TX_DESC_MAX_AGG_NUM(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+24, 11, 5)
+#define GET_TX_DESC_MCSG1_MAX_LEN(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+24, 16, 4)
+#define GET_TX_DESC_MCSG2_MAX_LEN(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+24, 20, 4)
+#define GET_TX_DESC_MCSG3_MAX_LEN(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+24, 24, 4)
+#define GET_TX_DESC_MCS7_SGI_MAX_LEN(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+24, 28, 4)
+
+#define SET_TX_DESC_TX_BUFFER_SIZE(__pdesc, __val)	\
+	SET_BITS_TO_LE_4BYTE(__pdesc+28, 0, 16, __val)
+#define SET_TX_DESC_SW_OFFSET30(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+28, 16, 8, __val)
+#define SET_TX_DESC_SW_OFFSET31(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+28, 24, 4, __val)
+#define SET_TX_DESC_ANTSEL_C(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+28, 29, 1, __val)
+#define SET_TX_DESC_NULL_0(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+28, 30, 1, __val)
+#define SET_TX_DESC_NULL_1(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+28, 30, 1, __val)
+
+#define GET_TX_DESC_TX_BUFFER_SIZE(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+28, 0, 16)
+
+
+#define SET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc, __val)	\
+	SET_BITS_TO_LE_4BYTE(__pdesc+32, 0, 32, __val)
+#define SET_TX_DESC_TX_BUFFER_ADDRESS64(__pdesc, __val) \
+	SET_BITS_TO_LE_4BYTE(__pdesc+36, 0, 32, __val)
+
+#define GET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+32, 0, 32)
+#define GET_TX_DESC_TX_BUFFER_ADDRESS64(__pdesc)	\
+	LE_BITS_TO_4BYTE(__pdesc+36, 0, 32)
+
+#define SET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc, __val)	\
+	SET_BITS_TO_LE_4BYTE(__pdesc+40, 0, 32, __val)
+#define SET_TX_DESC_NEXT_DESC_ADDRESS64(__pdesc, __val) \
+	SET_BITS_TO_LE_4BYTE(__pdesc+44, 0, 32, __val)
+
+#define GET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+40, 0, 32)
+#define GET_TX_DESC_NEXT_DESC_ADDRESS64(__pdesc)	\
+	LE_BITS_TO_4BYTE(__pdesc+44, 0, 32)
+
+#define GET_RX_DESC_PKT_LEN(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc, 0, 14)
+#define GET_RX_DESC_CRC32(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc, 14, 1)
+#define GET_RX_DESC_ICV(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc, 15, 1)
+#define GET_RX_DESC_DRV_INFO_SIZE(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc, 16, 4)
+#define GET_RX_DESC_SECURITY(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc, 20, 3)
+#define GET_RX_DESC_QOS(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc, 23, 1)
+#define GET_RX_DESC_SHIFT(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc, 24, 2)
+#define GET_RX_DESC_PHYST(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc, 26, 1)
+#define GET_RX_DESC_SWDEC(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc, 27, 1)
+#define GET_RX_DESC_LS(__pdesc)				\
+	LE_BITS_TO_4BYTE(__pdesc, 28, 1)
+#define GET_RX_DESC_FS(__pdesc)				\
+	LE_BITS_TO_4BYTE(__pdesc, 29, 1)
+#define GET_RX_DESC_EOR(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc, 30, 1)
+#define GET_RX_DESC_OWN(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc, 31, 1)
+
+#define SET_RX_DESC_PKT_LEN(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc, 0, 14, __val)
+#define SET_RX_DESC_EOR(__pdesc, __val)			\
+	SET_BITS_TO_LE_4BYTE(__pdesc, 30, 1, __val)
+#define SET_RX_DESC_OWN(__pdesc, __val)			\
+	SET_BITS_TO_LE_4BYTE(__pdesc, 31, 1, __val)
+
+#define GET_RX_DESC_MACID(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+4, 0, 6)
+#define GET_RX_DESC_PAGGR(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+4, 14, 1)
+#define GET_RX_DESC_FAGGR(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+4, 15, 1)
+#define GET_RX_DESC_A1_FIT(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+4, 16, 4)
+#define GET_RX_DESC_A2_FIT(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+4, 20, 4)
+#define GET_RX_DESC_PAM(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+4, 24, 1)
+#define GET_RX_DESC_PWR(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+4, 25, 1)
+#define GET_RX_DESC_MD(__pdesc)				\
+	LE_BITS_TO_4BYTE(__pdesc+4, 26, 1)
+#define GET_RX_DESC_MF(__pdesc)				\
+	LE_BITS_TO_4BYTE(__pdesc+4, 27, 1)
+#define GET_RX_DESC_TYPE(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+4, 28, 2)
+#define GET_RX_DESC_MC(__pdesc)				\
+	LE_BITS_TO_4BYTE(__pdesc+4, 30, 1)
+#define GET_RX_DESC_BC(__pdesc)				\
+	LE_BITS_TO_4BYTE(__pdesc+4, 31, 1)
+#define GET_RX_DESC_SEQ(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+8, 0, 12)
+#define GET_RX_DESC_FRAG(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+8, 12, 4)
+
+#define GET_RX_DESC_RXMCS(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+12, 0, 6)
+#define GET_RX_DESC_RXHT(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+12, 6, 1)
+#define GET_RX_STATUS_DESC_RX_GF(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+12, 7, 1)
+#define GET_RX_DESC_SPLCP(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+12, 8, 1)
+#define GET_RX_DESC_BW(__pdesc)				\
+	LE_BITS_TO_4BYTE(__pdesc+12, 9, 1)
+#define GET_RX_DESC_HTC(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+12, 10, 1)
+#define GET_RX_STATUS_DESC_EOSP(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+12, 11, 1)
+#define GET_RX_STATUS_DESC_BSSID_FIT(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+12, 12, 2)
+#define GET_RX_STATUS_DESC_RPT_SEL(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+12, 14, 2)
+
+#define GET_RX_STATUS_DESC_PATTERN_MATCH(__pdesc)	\
+	LE_BITS_TO_4BYTE(__pdesc+12, 29, 1)
+#define GET_RX_STATUS_DESC_UNICAST_MATCH(__pdesc)	\
+	LE_BITS_TO_4BYTE(__pdesc+12, 30, 1)
+#define GET_RX_STATUS_DESC_MAGIC_MATCH(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+12, 31, 1)
+
+#define GET_RX_DESC_IV1(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+16, 0, 32)
+#define GET_RX_DESC_TSFL(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+20, 0, 32)
+
+#define GET_RX_DESC_BUFF_ADDR(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+24, 0, 32)
+#define GET_RX_DESC_BUFF_ADDR64(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+28, 0, 32)
+
+#define SET_RX_DESC_BUFF_ADDR(__pdesc, __val)	\
+	SET_BITS_TO_LE_4BYTE(__pdesc+24, 0, 32, __val)
+#define SET_RX_DESC_BUFF_ADDR64(__pdesc, __val) \
+	SET_BITS_TO_LE_4BYTE(__pdesc+28, 0, 32, __val)
+
+/* TX report 2 format in Rx desc*/
+
+#define GET_RX_RPT2_DESC_PKT_LEN(__status)	\
+	LE_BITS_TO_4BYTE(__status, 0, 9)
+#define GET_RX_RPT2_DESC_MACID_VALID_1(__status)	\
+	LE_BITS_TO_4BYTE(__status+16, 0, 32)
+#define GET_RX_RPT2_DESC_MACID_VALID_2(__status)	\
+	LE_BITS_TO_4BYTE(__status+20, 0, 32)
+
+#define SET_EARLYMODE_PKTNUM(__paddr, __value)	\
+	SET_BITS_TO_LE_4BYTE(__paddr, 0, 4, __value)
+#define SET_EARLYMODE_LEN0(__paddr, __value)	\
+	SET_BITS_TO_LE_4BYTE(__paddr, 4, 12, __value)
+#define SET_EARLYMODE_LEN1(__paddr, __value)	\
+	SET_BITS_TO_LE_4BYTE(__paddr, 16, 12, __value)
+#define SET_EARLYMODE_LEN2_1(__paddr, __value)	\
+	SET_BITS_TO_LE_4BYTE(__paddr, 28, 4, __value)
+#define SET_EARLYMODE_LEN2_2(__paddr, __value)	\
+	SET_BITS_TO_LE_4BYTE(__paddr+4, 0, 8, __value)
+#define SET_EARLYMODE_LEN3(__paddr, __value)	\
+	SET_BITS_TO_LE_4BYTE(__paddr+4, 8, 12, __value)
+#define SET_EARLYMODE_LEN4(__paddr, __value)	\
+	SET_BITS_TO_LE_4BYTE(__paddr+4, 20, 12, __value)
+
+#define CLEAR_PCI_TX_DESC_CONTENT(__pdesc, _size)		\
+do {								\
+	if (_size > TX_DESC_NEXT_DESC_OFFSET)			\
+		memset(__pdesc, 0, TX_DESC_NEXT_DESC_OFFSET);	\
+	else							\
+		memset(__pdesc, 0, _size);			\
+} while (0)
+
+#define RTL8188_RX_HAL_IS_CCK_RATE(rxmcs)\
+	(rxmcs == DESC92C_RATE1M ||\
+	 rxmcs == DESC92C_RATE2M ||\
+	 rxmcs == DESC92C_RATE5_5M ||\
+	 rxmcs == DESC92C_RATE11M)
+
+struct phy_rx_agc_info_t {
+	#if __LITTLE_ENDIAN
+		u8	gain:7, trsw:1;
+	#else
+		u8	trsw:1, gain:7;
+	#endif
+};
+struct phy_status_rpt {
+	struct phy_rx_agc_info_t path_agc[2];
+	u8	ch_corr[2];
+	u8	cck_sig_qual_ofdm_pwdb_all;
+	u8	cck_agc_rpt_ofdm_cfosho_a;
+	u8	cck_rpt_b_ofdm_cfosho_b;
+	u8	rsvd_1;
+	u8	noise_power_db_msb;
+	u8	path_cfotail[2];
+	u8	pcts_mask[2];
+	u8	stream_rxevm[2];
+	u8	path_rxsnr[2];
+	u8	noise_power_db_lsb;
+	u8	rsvd_2[3];
+	u8	stream_csi[2];
+	u8	stream_target_csi[2];
+	u8	sig_evm;
+	u8	rsvd_3;
+#if __LITTLE_ENDIAN
+	u8	antsel_rx_keep_2:1;	/*ex_intf_flg:1;*/
+	u8	sgi_en:1;
+	u8	rxsc:2;
+	u8	idle_long:1;
+	u8	r_ant_train_en:1;
+	u8	ant_sel_b:1;
+	u8	ant_sel:1;
+#else	/* _BIG_ENDIAN_	*/
+	u8	ant_sel:1;
+	u8	ant_sel_b:1;
+	u8	r_ant_train_en:1;
+	u8	idle_long:1;
+	u8	rxsc:2;
+	u8	sgi_en:1;
+	u8	antsel_rx_keep_2:1;	/*ex_intf_flg:1;*/
+#endif
+} __packed;
+
+struct rx_fwinfo_88e {
+	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_88e {
+	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:6;
+	u32 rsvd0:2;
+	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 agg_en:1;
+	u32 rdg_en:1;
+	u32 bar_retryht:2;
+	u32 agg_break:1;
+	u32 morefrag:1;
+	u32 raw:1;
+	u32 ccx:1;
+	u32 ampdudensity:3;
+	u32 bt_int: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 cpu_handle:1;
+	u32 tag1:1;
+	u32 trigger_int:1;
+	u32 hwseq_en:1;
+
+	u32 rtsrate:5;
+	u32 apdcfe:1;
+	u32 qos:1;
+	u32 hwseq_ssn: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 pwr_status: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 sw_offset30:8;
+	u32 sw_offset31:4;
+	u32 rsvd1:1;
+	u32 antsel_c:1;
+	u32 null_0:1;
+	u32 null_1:1;
+
+	u32 txbuffaddr;
+	u32 txbufferaddr64;
+	u32 nextdescaddress;
+	u32 nextdescaddress64;
+
+	u32 reserve_pass_pcie_mm_limit[4];
+} __packed;
+
+struct rx_desc_88e {
+	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:6;
+	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 rtl88ee_tx_fill_desc(struct ieee80211_hw *hw,
+			  struct ieee80211_hdr *hdr, u8 *pdesc_tx,
+			  struct ieee80211_tx_info *info,
+			  struct ieee80211_sta *sta,
+			  struct sk_buff *skb,
+			  u8 hw_queue, struct rtl_tcb_desc *ptcb_desc);
+bool rtl88ee_rx_query_desc(struct ieee80211_hw *hw,
+			   struct rtl_stats *status,
+			   struct ieee80211_rx_status *rx_status,
+			   u8 *pdesc, struct sk_buff *skb);
+void rtl88ee_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val);
+u32 rtl88ee_get_desc(u8 *pdesc, bool istx, u8 desc_name);
+void rtl88ee_tx_polling(struct ieee80211_hw *hw, u8 hw_queue);
+void rtl88ee_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/rtl8192c/dm_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
index b793a65..926e2a3 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
@@ -174,8 +174,8 @@ static void rtl92c_dm_diginit(struct ieee80211_hw *hw)
 	dm_digtable->rssi_highthresh = DM_DIG_THRESH_HIGH;
 	dm_digtable->fa_lowthresh = DM_FALSEALARM_THRESH_LOW;
 	dm_digtable->fa_highthresh = DM_FALSEALARM_THRESH_HIGH;
-	dm_digtable->rx_gain_range_max = DM_DIG_MAX;
-	dm_digtable->rx_gain_range_min = DM_DIG_MIN;
+	dm_digtable->rx_gain_max = DM_DIG_MAX;
+	dm_digtable->rx_gain_min = DM_DIG_MIN;
 	dm_digtable->back_val = DM_DIG_BACKOFF_DEFAULT;
 	dm_digtable->back_range_max = DM_DIG_BACKOFF_MAX;
 	dm_digtable->back_range_min = DM_DIG_BACKOFF_MIN;
@@ -300,11 +300,11 @@ static void rtl92c_dm_ctrl_initgain_by_rssi(struct ieee80211_hw *hw)
 	}
 
 	if ((digtable->rssi_val_min + 10 - digtable->back_val) >
-	    digtable->rx_gain_range_max)
-		digtable->cur_igvalue = digtable->rx_gain_range_max;
+	    digtable->rx_gain_max)
+		digtable->cur_igvalue = digtable->rx_gain_max;
 	else if ((digtable->rssi_val_min + 10 -
-		  digtable->back_val) < digtable->rx_gain_range_min)
-		digtable->cur_igvalue = digtable->rx_gain_range_min;
+		  digtable->back_val) < digtable->rx_gain_min)
+		digtable->cur_igvalue = digtable->rx_gain_min;
 	else
 		digtable->cur_igvalue = digtable->rssi_val_min + 10 -
 		    digtable->back_val;
@@ -1147,75 +1147,6 @@ void rtl92c_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw)
 }
 EXPORT_SYMBOL(rtl92c_dm_init_rate_adaptive_mask);
 
-static void rtl92c_dm_refresh_rate_adaptive_mask(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 rate_adaptive *p_ra = &(rtlpriv->ra);
-	u32 low_rssi_thresh, high_rssi_thresh;
-	struct ieee80211_sta *sta = NULL;
-
-	if (is_hal_stop(rtlhal)) {
-		RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
-			 "<---- driver is going to unload\n");
-		return;
-	}
-
-	if (!rtlpriv->dm.useramask) {
-		RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
-			 "<---- driver does not control rate adaptive mask\n");
-		return;
-	}
-
-	if (mac->link_state == MAC80211_LINKED &&
-	    mac->opmode == NL80211_IFTYPE_STATION) {
-		switch (p_ra->pre_ratr_state) {
-		case DM_RATR_STA_HIGH:
-			high_rssi_thresh = 50;
-			low_rssi_thresh = 20;
-			break;
-		case DM_RATR_STA_MIDDLE:
-			high_rssi_thresh = 55;
-			low_rssi_thresh = 20;
-			break;
-		case DM_RATR_STA_LOW:
-			high_rssi_thresh = 50;
-			low_rssi_thresh = 25;
-			break;
-		default:
-			high_rssi_thresh = 50;
-			low_rssi_thresh = 20;
-			break;
-		}
-
-		if (rtlpriv->dm.undec_sm_pwdb > (long)high_rssi_thresh)
-			p_ra->ratr_state = DM_RATR_STA_HIGH;
-		else if (rtlpriv->dm.undec_sm_pwdb > (long)low_rssi_thresh)
-			p_ra->ratr_state = DM_RATR_STA_MIDDLE;
-		else
-			p_ra->ratr_state = DM_RATR_STA_LOW;
-
-		if (p_ra->pre_ratr_state != p_ra->ratr_state) {
-			RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, "RSSI = %ld\n",
-				 rtlpriv->dm.undec_sm_pwdb);
-			RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
-				 "RSSI_LEVEL = %d\n", p_ra->ratr_state);
-			RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
-				 "PreState = %d, CurState = %d\n",
-				 p_ra->pre_ratr_state, p_ra->ratr_state);
-
-			rcu_read_lock();
-			sta = ieee80211_find_sta(mac->vif, mac->bssid);
-			rtlpriv->cfg->ops->update_rate_tbl(hw, sta,
-					p_ra->ratr_state);
-
-			p_ra->pre_ratr_state = p_ra->ratr_state;
-			rcu_read_unlock();
-		}
-	}
-}
-
 static void rtl92c_dm_init_dynamic_bb_powersaving(struct ieee80211_hw *hw)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
@@ -1437,6 +1368,9 @@ void rtl92c_dm_watchdog(struct ieee80211_hw *hw)
 	rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON,
 				      (u8 *) (&fw_ps_awake));
 
+	if (ppsc->p2p_ps_info.p2p_ps_mode)
+		fw_ps_awake = false;
+
 	if ((ppsc->rfpwr_state == ERFON) && ((!fw_current_inpsmode) &&
 					     fw_ps_awake)
 	    && (!ppsc->rfchange_inprogress)) {
@@ -1446,7 +1380,7 @@ void rtl92c_dm_watchdog(struct ieee80211_hw *hw)
 		rtl92c_dm_dynamic_bb_powersaving(hw);
 		rtl92c_dm_dynamic_txpower(hw);
 		rtl92c_dm_check_txpower_tracking(hw);
-		rtl92c_dm_refresh_rate_adaptive_mask(hw);
+		/* rtl92c_dm_refresh_rate_adaptive_mask(hw); */
 		rtl92c_dm_bt_coexist(hw);
 		rtl92c_dm_check_edca_turbo(hw);
 	}
@@ -1651,7 +1585,7 @@ static void rtl92c_bt_set_normal(struct ieee80211_hw *hw)
 	}
 }
 
-static void rtl92c_bt_ant_isolation(struct ieee80211_hw *hw)
+static void rtl92c_bt_ant_isolation(struct ieee80211_hw *hw, u8 tmp1byte)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
@@ -1673,9 +1607,9 @@ static void rtl92c_bt_ant_isolation(struct ieee80211_hw *hw)
 			    BT_RSSI_STATE_SPECIAL_LOW)) {
 			rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0xa0);
 		} else if (rtlpcipriv->bt_coexist.bt_service == BT_PAN) {
-			rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0x00);
+			rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, tmp1byte);
 		} else {
-			rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0x00);
+			rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, tmp1byte);
 		}
 	}
 
@@ -1726,12 +1660,17 @@ static void rtl92c_check_bt_change(struct ieee80211_hw *hw)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	u8 tmp1byte = 0;
 
+	if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version) &&
+	    rtlpcipriv->bt_coexist.bt_coexistence)
+		tmp1byte |= BIT(5);
 	if (rtlpcipriv->bt_coexist.bt_cur_state) {
 		if (rtlpcipriv->bt_coexist.bt_ant_isolation)
-			rtl92c_bt_ant_isolation(hw);
+			rtl92c_bt_ant_isolation(hw, tmp1byte);
 	} else {
-		rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0x00);
+		rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, tmp1byte);
 		rtlpriv->cfg->ops->set_rfreg(hw, RF90_PATH_A, 0x1e, 0xf0,
 				rtlpcipriv->bt_coexist.bt_rfreg_origin_1e);
 
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c
index 883f23a..04a4162 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c
@@ -552,7 +552,9 @@ void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
 	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_SMART_PS(u1_h2c_set_pwrmode,
+					 (rtlpriv->mac80211.p2p) ?
+					 ppsc->smart_ps : 1);
 	SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(u1_h2c_set_pwrmode,
 					      ppsc->reg_max_lps_awakeintvl);
 
@@ -808,3 +810,98 @@ void rtl92c_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus)
 	rtl92c_fill_h2c_cmd(hw, H2C_JOINBSSRPT, 1, u1_joinbssrpt_parm);
 }
 EXPORT_SYMBOL(rtl92c_set_fw_joinbss_report_cmd);
+
+static void rtl92c_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, u8 ctwindow)
+{
+	u8 u1_ctwindow_period[1] = {ctwindow};
+
+	rtl92c_fill_h2c_cmd(hw, H2C_P2P_PS_CTW_CMD, 1, u1_ctwindow_period);
+}
+
+void rtl92c_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw));
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	struct rtl_p2p_ps_info *p2pinfo = &(rtlps->p2p_ps_info);
+	struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload;
+	u8	i;
+	u16	ctwindow;
+	u32	start_time, tsf_low;
+
+	switch (p2p_ps_state) {
+	case P2P_PS_DISABLE:
+		RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_DISABLE\n");
+		memset(p2p_ps_offload, 0, sizeof(struct p2p_ps_offload_t));
+		break;
+	case P2P_PS_ENABLE:
+		RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_ENABLE\n");
+		/* update CTWindow value. */
+		if (p2pinfo->ctwindow > 0) {
+			p2p_ps_offload->ctwindow_en = 1;
+			ctwindow = p2pinfo->ctwindow;
+			rtl92c_set_p2p_ctw_period_cmd(hw, ctwindow);
+		}
+		/* hw only support 2 set of NoA */
+		for (i = 0; i < p2pinfo->noa_num; i++) {
+			/* To control the register setting for which NOA*/
+			rtl_write_byte(rtlpriv, 0x5cf, (i << 4));
+			if (i == 0)
+				p2p_ps_offload->noa0_en = 1;
+			else
+				p2p_ps_offload->noa1_en = 1;
+
+			/* config P2P NoA Descriptor Register */
+			rtl_write_dword(rtlpriv, 0x5E0,
+					p2pinfo->noa_duration[i]);
+			rtl_write_dword(rtlpriv, 0x5E4,
+					p2pinfo->noa_interval[i]);
+
+			/*Get Current TSF value */
+			tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR);
+
+			start_time = p2pinfo->noa_start_time[i];
+			if (p2pinfo->noa_count_type[i] != 1) {
+				while (start_time <= (tsf_low+(50*1024))) {
+					start_time += p2pinfo->noa_interval[i];
+					if (p2pinfo->noa_count_type[i] != 255)
+						p2pinfo->noa_count_type[i]--;
+				}
+			}
+			rtl_write_dword(rtlpriv, 0x5E8, start_time);
+			rtl_write_dword(rtlpriv, 0x5EC,
+					p2pinfo->noa_count_type[i]);
+		}
+
+		if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) {
+			/* rst p2p circuit */
+			rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4));
+
+			p2p_ps_offload->offload_en = 1;
+
+			if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) {
+				p2p_ps_offload->role = 1;
+				p2p_ps_offload->allstasleep = 0;
+			} else {
+				p2p_ps_offload->role = 0;
+			}
+
+			p2p_ps_offload->discovery = 0;
+		}
+		break;
+	case P2P_PS_SCAN:
+		RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n");
+		p2p_ps_offload->discovery = 1;
+		break;
+	case P2P_PS_SCAN_DONE:
+		RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN_DONE\n");
+		p2p_ps_offload->discovery = 0;
+		p2pinfo->p2p_ps_state = P2P_PS_ENABLE;
+		break;
+	default:
+		break;
+	}
+
+	rtl92c_fill_h2c_cmd(hw, H2C_P2P_PS_OFFLOAD, 1, (u8 *)p2p_ps_offload);
+}
+EXPORT_SYMBOL_GPL(rtl92c_set_p2p_ps_offload_cmd);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h
index 780ea5b..15b2055 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h
@@ -67,6 +67,9 @@ enum rtl8192c_h2c_cmd {
 	H2C_RSVDPAGE = 3,
 	H2C_RSSI_REPORT = 5,
 	H2C_RA_MASK = 6,
+	H2C_MACID_PS_MODE = 7,
+	H2C_P2P_PS_OFFLOAD = 8,
+	H2C_P2P_PS_CTW_CMD = 32,
 	MAX_H2CCMD
 };
 
@@ -95,5 +98,6 @@ void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode);
 void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished);
 void rtl92c_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus);
 void usb_writeN_async(struct rtl_priv *rtlpriv, u32 addr, void *data, u16 len);
+void rtl92c_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state);
 
 #endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
index 1b65db7..a82b30a 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
@@ -475,6 +475,9 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
 
 			break;
 		}
+	case HW_VAR_H2C_FW_P2P_PS_OFFLOAD:
+		rtl92c_set_p2p_ps_offload_cmd(hw, (*(u8 *)val));
+		break;
 	case HW_VAR_AID:{
 			u16 u2btmp;
 			u2btmp = rtl_read_word(rtlpriv, REG_BCN_PSR_RPT);
@@ -505,6 +508,40 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
 			break;
 
 		}
+	case HW_VAR_FW_LPS_ACTION: {
+			bool enter_fwlps = *((bool *)val);
+			u8 rpwm_val, fw_pwrmode;
+			bool fw_current_inps;
+
+			if (enter_fwlps) {
+				rpwm_val = 0x02;	/* RF off */
+				fw_current_inps = true;
+				rtlpriv->cfg->ops->set_hw_reg(hw,
+						HW_VAR_FW_PSMODE_STATUS,
+						(u8 *)(&fw_current_inps));
+				rtlpriv->cfg->ops->set_hw_reg(hw,
+						HW_VAR_H2C_FW_PWRMODE,
+						(u8 *)(&ppsc->fwctrl_psmode));
+
+				rtlpriv->cfg->ops->set_hw_reg(hw,
+						HW_VAR_SET_RPWM,
+						(u8 *)(&rpwm_val));
+			} else {
+				rpwm_val = 0x0C;	/* RF on */
+				fw_pwrmode = FW_PS_ACTIVE_MODE;
+				fw_current_inps = false;
+				rtlpriv->cfg->ops->set_hw_reg(hw,
+						HW_VAR_SET_RPWM,
+						(u8 *)(&rpwm_val));
+				rtlpriv->cfg->ops->set_hw_reg(hw,
+						HW_VAR_H2C_FW_PWRMODE,
+						(u8 *)(&fw_pwrmode));
+
+				rtlpriv->cfg->ops->set_hw_reg(hw,
+						HW_VAR_FW_PSMODE_STATUS,
+						(u8 *)(&fw_current_inps));
+			}
+		break; }
 	default:
 		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
 			 "switch case not processed\n");
@@ -1105,7 +1142,8 @@ static int _rtl92ce_set_media_status(struct ieee80211_hw *hw,
 	    type == NL80211_IFTYPE_STATION) {
 		_rtl92ce_stop_tx_beacon(hw);
 		_rtl92ce_enable_bcn_sub_func(hw);
-	} else if (type == NL80211_IFTYPE_ADHOC || type == NL80211_IFTYPE_AP) {
+	} else if (type == NL80211_IFTYPE_ADHOC || type == NL80211_IFTYPE_AP ||
+		   type == NL80211_IFTYPE_MESH_POINT) {
 		_rtl92ce_resume_tx_beacon(hw);
 		_rtl92ce_disable_bcn_sub_func(hw);
 	} else {
@@ -1137,6 +1175,11 @@ static int _rtl92ce_set_media_status(struct ieee80211_hw *hw,
 		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
 			 "Set Network type to AP!\n");
 		break;
+	case NL80211_IFTYPE_MESH_POINT:
+		bt_msr |= MSR_ADHOC;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 "Set Network type to Mesh Point!\n");
+		break;
 	default:
 		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
 			 "Network type %d not supported!\n", type);
@@ -1184,7 +1227,8 @@ int rtl92ce_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type)
 		return -EOPNOTSUPP;
 
 	if (rtlpriv->mac80211.link_state == MAC80211_LINKED) {
-		if (type != NL80211_IFTYPE_AP)
+		if (type != NL80211_IFTYPE_AP &&
+		    type != NL80211_IFTYPE_MESH_POINT)
 			rtl92ce_set_check_bssid(hw, true);
 	} else {
 		rtl92ce_set_check_bssid(hw, false);
@@ -1459,7 +1503,7 @@ static void _rtl92ce_read_txpower_info_from_hwpg(struct ieee80211_hw *hw,
 		}
 
 		for (i = 0; i < 14; i++) {
-			RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+			RTPRINT(rtlpriv, FINIT, INIT_TXPOWER,
 				"RF(%d)-Ch(%d) [CCK / HT40_1S / HT40_2S] = [0x%x / 0x%x / 0x%x]\n",
 				rf_path, i,
 				rtlefuse->txpwrlevel_cck[rf_path][i],
@@ -1500,11 +1544,11 @@ static void _rtl92ce_read_txpower_info_from_hwpg(struct ieee80211_hw *hw,
 				      & 0xf0) >> 4);
 			}
 
-			RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+			RTPRINT(rtlpriv, FINIT, INIT_TXPOWER,
 				"RF-%d pwrgroup_ht20[%d] = 0x%x\n",
 				rf_path, i,
 				rtlefuse->pwrgroup_ht20[rf_path][i]);
-			RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+			RTPRINT(rtlpriv, FINIT, INIT_TXPOWER,
 				"RF-%d pwrgroup_ht40[%d] = 0x%x\n",
 				rf_path, i,
 				rtlefuse->pwrgroup_ht40[rf_path][i]);
@@ -1545,19 +1589,19 @@ static void _rtl92ce_read_txpower_info_from_hwpg(struct ieee80211_hw *hw,
 	    rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][7];
 
 	for (i = 0; i < 14; i++)
-		RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+		RTPRINT(rtlpriv, FINIT, INIT_TXPOWER,
 			"RF-A Ht20 to HT40 Diff[%d] = 0x%x\n",
 			i, rtlefuse->txpwr_ht20diff[RF90_PATH_A][i]);
 	for (i = 0; i < 14; i++)
-		RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+		RTPRINT(rtlpriv, FINIT, INIT_TXPOWER,
 			"RF-A Legacy to Ht40 Diff[%d] = 0x%x\n",
 			i, rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][i]);
 	for (i = 0; i < 14; i++)
-		RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+		RTPRINT(rtlpriv, FINIT, INIT_TXPOWER,
 			"RF-B Ht20 to HT40 Diff[%d] = 0x%x\n",
 			i, rtlefuse->txpwr_ht20diff[RF90_PATH_B][i]);
 	for (i = 0; i < 14; i++)
-		RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+		RTPRINT(rtlpriv, FINIT, INIT_TXPOWER,
 			"RF-B Legacy to HT40 Diff[%d] = 0x%x\n",
 			i, rtlefuse->txpwr_legacyhtdiff[RF90_PATH_B][i]);
 
@@ -1565,7 +1609,7 @@ static void _rtl92ce_read_txpower_info_from_hwpg(struct ieee80211_hw *hw,
 		rtlefuse->eeprom_regulatory = (hwinfo[RF_OPTION1] & 0x7);
 	else
 		rtlefuse->eeprom_regulatory = 0;
-	RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+	RTPRINT(rtlpriv, FINIT, INIT_TXPOWER,
 		"eeprom_regulatory = 0x%x\n", rtlefuse->eeprom_regulatory);
 
 	if (!autoload_fail) {
@@ -1575,7 +1619,7 @@ static void _rtl92ce_read_txpower_info_from_hwpg(struct ieee80211_hw *hw,
 		rtlefuse->eeprom_tssi[RF90_PATH_A] = EEPROM_DEFAULT_TSSI;
 		rtlefuse->eeprom_tssi[RF90_PATH_B] = EEPROM_DEFAULT_TSSI;
 	}
-	RTPRINT(rtlpriv, FINIT, INIT_TxPower, "TSSI_A = 0x%x, TSSI_B = 0x%x\n",
+	RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, "TSSI_A = 0x%x, TSSI_B = 0x%x\n",
 		rtlefuse->eeprom_tssi[RF90_PATH_A],
 		rtlefuse->eeprom_tssi[RF90_PATH_B]);
 
@@ -1589,7 +1633,7 @@ static void _rtl92ce_read_txpower_info_from_hwpg(struct ieee80211_hw *hw,
 		rtlefuse->apk_thermalmeterignore = true;
 
 	rtlefuse->thermalmeter[0] = rtlefuse->eeprom_thermalmeter;
-	RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+	RTPRINT(rtlpriv, FINIT, INIT_TXPOWER,
 		"thermalmeter = 0x%x\n", rtlefuse->eeprom_thermalmeter);
 }
 
@@ -1629,6 +1673,21 @@ static void _rtl92ce_read_adapter_info(struct ieee80211_hw *hw)
 	if (rtlefuse->autoload_failflag)
 		return;
 
+	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);
+
 	for (i = 0; i < 6; i += 2) {
 		usvalue = *(u16 *)&hwinfo[EEPROM_MAC_ADDR + i];
 		*((u16 *) (&rtlefuse->dev_addr[i])) = usvalue;
@@ -1766,6 +1825,9 @@ static void rtl92ce_update_hal_rate_table(struct ieee80211_hw *hw,
 		ratr_value = sta->supp_rates[1] << 4;
 	else
 		ratr_value = sta->supp_rates[0];
+	if (mac->opmode == NL80211_IFTYPE_ADHOC)
+		ratr_value = 0xfff;
+
 	ratr_value |= (sta->ht_cap.mcs.rx_mask[1] << 20 |
 			sta->ht_cap.mcs.rx_mask[0] << 12);
 	switch (wirelessmode) {
@@ -1860,7 +1922,8 @@ static void rtl92ce_update_hal_rate_mask(struct ieee80211_hw *hw,
 
 	sta_entry = (struct rtl_sta_info *) sta->drv_priv;
 	wirelessmode = sta_entry->wireless_mode;
-	if (mac->opmode == NL80211_IFTYPE_STATION)
+	if (mac->opmode == NL80211_IFTYPE_STATION ||
+	    mac->opmode == NL80211_IFTYPE_MESH_POINT)
 		curtxbw_40mhz = mac->bw_40;
 	else if (mac->opmode == NL80211_IFTYPE_AP ||
 		mac->opmode == NL80211_IFTYPE_ADHOC)
@@ -1870,6 +1933,8 @@ static void rtl92ce_update_hal_rate_mask(struct ieee80211_hw *hw,
 		ratr_bitmap = sta->supp_rates[1] << 4;
 	else
 		ratr_bitmap = sta->supp_rates[0];
+	if (mac->opmode == NL80211_IFTYPE_ADHOC)
+		ratr_bitmap = 0xfff;
 	ratr_bitmap |= (sta->ht_cap.mcs.rx_mask[1] << 20 |
 			sta->ht_cap.mcs.rx_mask[0] << 12);
 	switch (wirelessmode) {
@@ -2135,7 +2200,8 @@ void rtl92ce_set_key(struct ieee80211_hw *hw, u32 key_index,
 				macaddr = cam_const_broad;
 				entry_id = key_index;
 			} else {
-				if (mac->opmode == NL80211_IFTYPE_AP) {
+				if (mac->opmode == NL80211_IFTYPE_AP ||
+				    mac->opmode == NL80211_IFTYPE_MESH_POINT) {
 					entry_id = rtl_cam_get_free_entry(hw,
 								 p_macaddr);
 					if (entry_id >=  TOTAL_CAM_ENTRY) {
@@ -2157,7 +2223,8 @@ void rtl92ce_set_key(struct ieee80211_hw *hw, u32 key_index,
 			RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
 				 "delete one entry, entry_id is %d\n",
 				 entry_id);
-			if (mac->opmode == NL80211_IFTYPE_AP)
+			if (mac->opmode == NL80211_IFTYPE_AP ||
+			    mac->opmode == NL80211_IFTYPE_MESH_POINT)
 				rtl_cam_del_entry(hw, p_macaddr);
 			rtl_cam_delete_one_entry(hw, p_macaddr, entry_id);
 		} else {
@@ -2338,3 +2405,24 @@ void rtl92ce_suspend(struct ieee80211_hw *hw)
 void rtl92ce_resume(struct ieee80211_hw *hw)
 {
 }
+
+/* Turn on AAP (RCR:bit 0) for promicuous mode. */
+void rtl92ce_allow_all_destaddr(struct ieee80211_hw *hw,
+	bool allow_all_da, bool write_into_reg)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+
+	if (allow_all_da) {/* Set BIT0 */
+		rtlpci->receive_config |= RCR_AAP;
+	} else {/* Clear BIT0 */
+		rtlpci->receive_config &= ~RCR_AAP;
+	}
+
+	if (write_into_reg)
+		rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config);
+
+	RT_TRACE(rtlpriv, COMP_TURBO | COMP_INIT, DBG_LOUD,
+		 "receive_config=0x%08X, write_into_reg=%d\n",
+		 rtlpci->receive_config, write_into_reg);
+}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.h b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.h
index 52a3aea..2d063b0 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.h
@@ -61,6 +61,8 @@ void rtl92ce_update_interrupt_mask(struct ieee80211_hw *hw,
 void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val);
 void rtl92ce_update_hal_rate_tbl(struct ieee80211_hw *hw,
 				 struct ieee80211_sta *sta, u8 rssi_level);
+void rtl92ce_update_hal_rate_tbl(struct ieee80211_hw *hw,
+				 struct ieee80211_sta *sta, u8 rssi_level);
 void rtl92ce_update_channel_access_setting(struct ieee80211_hw *hw);
 bool rtl92ce_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid);
 void rtl92ce_enable_hw_security_config(struct ieee80211_hw *hw);
@@ -74,5 +76,7 @@ void rtl8192ce_bt_reg_init(struct ieee80211_hw *hw);
 void rtl8192ce_bt_hw_init(struct ieee80211_hw *hw);
 void rtl92ce_suspend(struct ieee80211_hw *hw);
 void rtl92ce_resume(struct ieee80211_hw *hw);
+void rtl92ce_allow_all_destaddr(struct ieee80211_hw *hw,
+				bool allow_all_da, bool write_into_reg);
 
 #endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h b/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h
index e4d738f..bd4aef7 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h
@@ -544,6 +544,7 @@
 #define	IMR_WLANOFF				BIT(0)
 
 #define EFUSE_REAL_CONTENT_LEN			512
+#define EFUSE_OOB_PROTECT_BYTES			15
 
 #define	EEPROM_DEFAULT_TSSI			0x0
 #define EEPROM_DEFAULT_TXPOWERDIFF		0x0
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c
index 49f663b..1420356 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c
@@ -228,6 +228,7 @@ static struct rtl_hal_ops rtl8192ce_hal_ops = {
 	.enable_hw_sec = rtl92ce_enable_hw_security_config,
 	.set_key = rtl92ce_set_key,
 	.init_sw_leds = rtl92ce_init_sw_leds,
+	.allow_all_destaddr = rtl92ce_allow_all_destaddr,
 	.get_bbreg = rtl92c_phy_query_bb_reg,
 	.set_bbreg = rtl92c_phy_set_bb_reg,
 	.set_rfreg = rtl92ce_phy_set_rf_reg,
@@ -278,6 +279,7 @@ static struct rtl_hal_cfg rtl92ce_hal_cfg = {
 	.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[EFUSE_OOB_PROTECT_BYTES_LEN] = EFUSE_OOB_PROTECT_BYTES,
 
 	.maps[RWCAM] = REG_CAMCMD,
 	.maps[WCAMI] = REG_CAMWRITE,
@@ -309,7 +311,7 @@ static struct rtl_hal_cfg rtl92ce_hal_cfg = {
 
 	.maps[RTL_IMR_TXFOVW] = IMR_TXFOVW,
 	.maps[RTL_IMR_PSTIMEOUT] = IMR_PSTIMEOUT,
-	.maps[RTL_IMR_BcnInt] = IMR_BCNINT,
+	.maps[RTL_IMR_BCNINT] = IMR_BCNINT,
 	.maps[RTL_IMR_RXFOVW] = IMR_RXFOVW,
 	.maps[RTL_IMR_RDU] = IMR_RDU,
 	.maps[RTL_IMR_ATIMEND] = IMR_ATIMEND,
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
index b9b1a6e..65bf5fb 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
@@ -30,6 +30,7 @@
 #include "../wifi.h"
 #include "../pci.h"
 #include "../base.h"
+#include "../stats.h"
 #include "reg.h"
 #include "def.h"
 #include "phy.h"
@@ -42,7 +43,7 @@ static u8 _rtl92ce_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 hw_queue)
 
 	if (unlikely(ieee80211_is_beacon(fc)))
 		return QSLT_BEACON;
-	if (ieee80211_is_mgmt(fc))
+	if (ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc))
 		return QSLT_MGNT;
 
 	return skb->priority;
@@ -78,16 +79,6 @@ static u8 _rtl92c_evm_db_to_percentage(char value)
 	return ret_val;
 }
 
-static long _rtl92ce_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 _rtl92ce_signal_scale_mapping(struct ieee80211_hw *hw,
 		long currsig)
 {
@@ -139,7 +130,6 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw,
 	pstats->packet_toself = packet_toself;
 	pstats->is_cck = is_cck_rate;
 	pstats->packet_beacon = packet_beacon;
-	pstats->is_cck = is_cck_rate;
 	pstats->rx_mimo_sig_qual[0] = -1;
 	pstats->rx_mimo_sig_qual[1] = -1;
 
@@ -192,10 +182,30 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw,
 			}
 		}
 
-		pwdb_all = _rtl92c_query_rxpwrpercentage(rx_pwr_all);
+		pwdb_all = rtl_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;
 
+		/* (3) Get Signal Quality (EVM) */
 		if (packet_match_bssid) {
 			u8 sq;
 			if (pstats->rx_pwdb_all > 40)
@@ -217,29 +227,38 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw,
 	} else {
 		rtlpriv->dm.rfpath_rxenable[0] =
 		    rtlpriv->dm.rfpath_rxenable[1] = true;
+		/* (1)Get RSSI for HT rate */
 		for (i = RF90_PATH_A; i < RF90_PATH_MAX; i++) {
+			/* we will judge RF RX path now. */
 			if (rtlpriv->dm.rfpath_rxenable[i])
 				rf_rx_num++;
 
 			rx_pwr[i] =
 			    ((p_drvinfo->gain_trsw[i] & 0x3f) * 2) - 110;
+			/* Translate DBM to percentage. */
 			rssi = _rtl92c_query_rxpwrpercentage(rx_pwr[i]);
 			total_rssi += rssi;
+			/* Get Rx snr value in DB */
 			rtlpriv->stats.rx_snr_db[i] =
 			    (long)(p_drvinfo->rxsnr[i] / 2);
 
+			/* Record Signal Strength for next packet */
 			if (packet_match_bssid)
 				pstats->rx_mimo_signalstrength[i] = (u8) rssi;
 		}
 
+		/* (2)PWDB, Average PWDB cacluated by
+		 * hardware (for rate adaptive)
+		 */
 		rx_pwr_all = ((p_drvinfo->pwdb_all >> 1) & 0x7f) - 110;
 		pwdb_all = _rtl92c_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 >= DESC92_RATEMCS8 &&
-		    pdesc->rxmcs <= DESC92_RATEMCS15)
+		/* (3)EVM of HT rate */
+		if (pstats->is_ht && pstats->rate >= DESC92_RATEMCS8 &&
+		    pstats->rate <= DESC92_RATEMCS15)
 			max_spatial_stream = 2;
 		else
 			max_spatial_stream = 1;
@@ -248,6 +267,9 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw,
 			evm = _rtl92c_evm_db_to_percentage(p_drvinfo->rxevm[i]);
 
 			if (packet_match_bssid) {
+				/* Fill value in RFD, Get the first
+				 * spatial stream only
+				 */
 				if (i == 0)
 					pstats->signalquality =
 					    (u8) (evm & 0xff);
@@ -256,6 +278,9 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw,
 		}
 	}
 
+	/* UI BSS List signal strength(in percentage),
+	 * make it good looking, from 0~100.
+	 */
 	if (is_cck_rate)
 		pstats->signalstrength =
 		    (u8) (_rtl92ce_signal_scale_mapping(hw, pwdb_all));
@@ -265,215 +290,6 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw,
 			  (hw, total_rssi /= rf_rx_num));
 }
 
-static void _rtl92ce_process_ui_rssi(struct ieee80211_hw *hw,
-		struct rtl_stats *pstats)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_phy *rtlphy = &(rtlpriv->phy);
-	u8 rfpath;
-	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 =
-		    _rtl92ce_translate_todbm(hw, (u8) tmpval);
-		pstats->rssi = rtlpriv->stats.signal_strength;
-	}
-
-	if (!pstats->is_cck && pstats->packet_toself) {
-		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 _rtl92ce_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 _rtl92ce_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 undec_sm_pwdb;
-
-	if (mac->opmode == NL80211_IFTYPE_ADHOC) {
-		return;
-	} else {
-		undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb;
-	}
-
-	if (pstats->packet_toself || pstats->packet_beacon) {
-		if (undec_sm_pwdb < 0)
-			undec_sm_pwdb = pstats->rx_pwdb_all;
-
-		if (pstats->rx_pwdb_all > (u32) undec_sm_pwdb) {
-			undec_sm_pwdb = (((undec_sm_pwdb) *
-			      (RX_SMOOTH_FACTOR - 1)) +
-			     (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
-
-			undec_sm_pwdb += 1;
-		} else {
-			undec_sm_pwdb = (((undec_sm_pwdb) *
-			      (RX_SMOOTH_FACTOR - 1)) +
-			     (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
-		}
-
-		rtlpriv->dm.undec_sm_pwdb = undec_sm_pwdb;
-		_rtl92ce_update_rxsignalstatistics(hw, pstats);
-	}
-}
-
-static void _rtl92ce_process_ui_link_quality(struct ieee80211_hw *hw,
-					     struct rtl_stats *pstats)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	u32 last_evm, n_spatialstream, tmpval;
-
-	if (pstats->signalquality != 0) {
-		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;
-
-			for (n_spatialstream = 0; n_spatialstream < 2;
-			     n_spatialstream++) {
-				if (pstats->
-				    rx_mimo_sig_qual[n_spatialstream] != -1) {
-					if (rtlpriv->stats.
-					    rx_evm_percentage[n_spatialstream]
-					    == 0) {
-						rtlpriv->stats.
-						   rx_evm_percentage
-						   [n_spatialstream] =
-						   pstats->rx_mimo_sig_qual
-						   [n_spatialstream];
-					}
-
-					rtlpriv->stats.
-					    rx_evm_percentage[n_spatialstream] =
-					    ((rtlpriv->
-					      stats.rx_evm_percentage
-					      [n_spatialstream] *
-					      (RX_SMOOTH_FACTOR - 1)) +
-					     (pstats->rx_mimo_sig_qual
-					      [n_spatialstream] * 1)) /
-					    (RX_SMOOTH_FACTOR);
-				}
-			}
-		}
-	} else {
-		;
-	}
-}
-
-static void _rtl92ce_process_phyinfo(struct ieee80211_hw *hw,
-				     u8 *buffer,
-				     struct rtl_stats *pcurrent_stats)
-{
-
-	if (!pcurrent_stats->packet_matchbssid &&
-	    !pcurrent_stats->packet_beacon)
-		return;
-
-	_rtl92ce_process_ui_rssi(hw, pcurrent_stats);
-	_rtl92ce_process_pwdb(hw, pcurrent_stats);
-	_rtl92ce_process_ui_link_quality(hw, pcurrent_stats);
-}
-
 static void _rtl92ce_translate_rx_signal_stuff(struct ieee80211_hw *hw,
 					       struct sk_buff *skb,
 					       struct rtl_stats *pstats,
@@ -516,7 +332,7 @@ static void _rtl92ce_translate_rx_signal_stuff(struct ieee80211_hw *hw,
 				   packet_matchbssid, packet_toself,
 				   packet_beacon);
 
-	_rtl92ce_process_phyinfo(hw, tmp_buf, pstats);
+	rtl_process_phyinfo(hw, tmp_buf, pstats);
 }
 
 bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw,
@@ -526,7 +342,7 @@ bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw,
 {
 	struct rx_fwinfo_92c *p_drvinfo;
 	struct rx_desc_92c *pdesc = (struct rx_desc_92c *)p_desc;
-
+	struct ieee80211_hdr *hdr;
 	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) *
@@ -539,37 +355,60 @@ bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw,
 	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->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);
+	stats->is_ht = (bool)GET_RX_DESC_RXHT(pdesc);
+
+	stats->is_cck = RX_HAL_IS_CCK_RATE(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;
+	hdr = (struct ieee80211_hdr *)(skb->data + stats->rx_drvinfo_size
+			+ stats->rx_bufshift);
 
-	if (!GET_RX_DESC_SWDEC(pdesc))
-		rx_status->flag |= RX_FLAG_DECRYPTED;
+	if (stats->crc)
+		rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
 
-	if (GET_RX_DESC_BW(pdesc))
+	if (stats->rx_is40Mhzpacket)
 		rx_status->flag |= RX_FLAG_40MHZ;
 
-	if (GET_RX_DESC_RXHT(pdesc))
+	if (stats->is_ht)
 		rx_status->flag |= RX_FLAG_HT;
 
 	rx_status->flag |= RX_FLAG_MACTIME_START;
 
-	if (stats->decrypted)
-		rx_status->flag |= RX_FLAG_DECRYPTED;
-
+	/* hw will set stats->decrypted true, if it finds the
+	 * frame is open data frame or mgmt frame.
+	 * So hw will not decryption robust managment frame
+	 * for IEEE80211w but still set status->decrypted
+	 * true, so here we should set it back to undecrypted
+	 * for IEEE80211w frame, and mac80211 sw will help
+	 * to decrypt it
+	 */
+	if (stats->decrypted) {
+		if (!hdr) {
+			/* In testing, hdr was NULL here */
+			return false;
+		}
+		if ((ieee80211_is_robust_mgmt_frame(hdr)) &&
+		    (ieee80211_has_protected(hdr->frame_control)))
+			rx_status->flag &= ~RX_FLAG_DECRYPTED;
+		else
+			rx_status->flag |= RX_FLAG_DECRYPTED;
+	}
+	/* rate_idx: index of data rate into band's
+	 * supported rates or MCS index if HT rates
+	 * are use (RX_FLAG_HT)
+	 * Notice: this is diff with windows define
+	 */
 	rx_status->rate_idx = rtlwifi_rate_mapping(hw,
-				(bool)GET_RX_DESC_RXHT(pdesc),
-				(u8)GET_RX_DESC_RXMCS(pdesc),
-				(bool)GET_RX_DESC_PAGGR(pdesc));
+				stats->is_ht, stats->rate,
+				stats->isfirst_ampdu);
 
-	rx_status->mactime = GET_RX_DESC_TSFL(pdesc);
+	rx_status->mactime = stats->timestamp_low;
 	if (phystatus) {
 		p_drvinfo = (struct rx_fwinfo_92c *)(skb->data +
 						     stats->rx_bufshift);
@@ -580,7 +419,7 @@ bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw,
 	}
 
 	/*rx_status->qual = stats->signal; */
-	rx_status->signal = stats->rssi + 10;
+	rx_status->signal = stats->recvsignalpower + 10;
 	/*rx_status->noise = -stats->noise; */
 
 	return true;
@@ -624,7 +463,8 @@ void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw,
 	if (mac->opmode == NL80211_IFTYPE_STATION) {
 		bw_40 = mac->bw_40;
 	} else if (mac->opmode == NL80211_IFTYPE_AP ||
-		mac->opmode == NL80211_IFTYPE_ADHOC) {
+		   mac->opmode == NL80211_IFTYPE_ADHOC ||
+		   mac->opmode == NL80211_IFTYPE_MESH_POINT) {
 		if (sta)
 			bw_40 = sta->bandwidth >= IEEE80211_STA_RX_BW_40;
 	}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
index c08d0f4..3d0498e 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
@@ -202,7 +202,7 @@ static void _rtl92cu_read_txpower_info_from_hwpg(struct ieee80211_hw *hw,
 			}
 		}
 		for (i = 0; i < 14; i++) {
-			RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+			RTPRINT(rtlpriv, FINIT, INIT_TXPOWER,
 				"RF(%d)-Ch(%d) [CCK / HT40_1S / HT40_2S] = [0x%x / 0x%x / 0x%x]\n", rf_path, i,
 				rtlefuse->txpwrlevel_cck[rf_path][i],
 				rtlefuse->txpwrlevel_ht40_1s[rf_path][i],
@@ -238,11 +238,11 @@ static void _rtl92cu_read_txpower_info_from_hwpg(struct ieee80211_hw *hw,
 				    ((rtlefuse->eeprom_pwrlimit_ht40[index]
 				      & 0xf0) >> 4);
 			}
-			RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+			RTPRINT(rtlpriv, FINIT, INIT_TXPOWER,
 				"RF-%d pwrgroup_ht20[%d] = 0x%x\n",
 				rf_path, i,
 				rtlefuse->pwrgroup_ht20[rf_path][i]);
-			RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+			RTPRINT(rtlpriv, FINIT, INIT_TXPOWER,
 				"RF-%d pwrgroup_ht40[%d] = 0x%x\n",
 				rf_path, i,
 				rtlefuse->pwrgroup_ht40[rf_path][i]);
@@ -273,26 +273,26 @@ static void _rtl92cu_read_txpower_info_from_hwpg(struct ieee80211_hw *hw,
 	rtlefuse->legacy_ht_txpowerdiff =
 	    rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][7];
 	for (i = 0; i < 14; i++)
-		RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+		RTPRINT(rtlpriv, FINIT, INIT_TXPOWER,
 			"RF-A Ht20 to HT40 Diff[%d] = 0x%x\n",
 			i, rtlefuse->txpwr_ht20diff[RF90_PATH_A][i]);
 	for (i = 0; i < 14; i++)
-		RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+		RTPRINT(rtlpriv, FINIT, INIT_TXPOWER,
 			"RF-A Legacy to Ht40 Diff[%d] = 0x%x\n",
 			i, rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][i]);
 	for (i = 0; i < 14; i++)
-		RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+		RTPRINT(rtlpriv, FINIT, INIT_TXPOWER,
 			"RF-B Ht20 to HT40 Diff[%d] = 0x%x\n",
 			i, rtlefuse->txpwr_ht20diff[RF90_PATH_B][i]);
 	for (i = 0; i < 14; i++)
-		RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+		RTPRINT(rtlpriv, FINIT, INIT_TXPOWER,
 			"RF-B Legacy to HT40 Diff[%d] = 0x%x\n",
 			i, rtlefuse->txpwr_legacyhtdiff[RF90_PATH_B][i]);
 	if (!autoload_fail)
 		rtlefuse->eeprom_regulatory = (hwinfo[RF_OPTION1] & 0x7);
 	else
 		rtlefuse->eeprom_regulatory = 0;
-	RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+	RTPRINT(rtlpriv, FINIT, INIT_TXPOWER,
 		"eeprom_regulatory = 0x%x\n", rtlefuse->eeprom_regulatory);
 	if (!autoload_fail) {
 		rtlefuse->eeprom_tssi[RF90_PATH_A] = hwinfo[EEPROM_TSSI_A];
@@ -301,7 +301,7 @@ static void _rtl92cu_read_txpower_info_from_hwpg(struct ieee80211_hw *hw,
 		rtlefuse->eeprom_tssi[RF90_PATH_A] = EEPROM_DEFAULT_TSSI;
 		rtlefuse->eeprom_tssi[RF90_PATH_B] = EEPROM_DEFAULT_TSSI;
 	}
-	RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+	RTPRINT(rtlpriv, FINIT, INIT_TXPOWER,
 		"TSSI_A = 0x%x, TSSI_B = 0x%x\n",
 		rtlefuse->eeprom_tssi[RF90_PATH_A],
 		rtlefuse->eeprom_tssi[RF90_PATH_B]);
@@ -316,7 +316,7 @@ static void _rtl92cu_read_txpower_info_from_hwpg(struct ieee80211_hw *hw,
 	if (rtlefuse->eeprom_thermalmeter == 0x1f || autoload_fail)
 		rtlefuse->apk_thermalmeterignore = true;
 	rtlefuse->thermalmeter[0] = rtlefuse->eeprom_thermalmeter;
-	RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+	RTPRINT(rtlpriv, FINIT, INIT_TXPOWER,
 		"thermalmeter = 0x%x\n", rtlefuse->eeprom_thermalmeter);
 }
 
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
index a73a17b..23d640a 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
@@ -223,7 +223,7 @@ static struct rtl_hal_cfg rtl92cu_hal_cfg = {
 
 	.maps[RTL_IMR_TXFOVW] = IMR_TXFOVW,
 	.maps[RTL_IMR_PSTIMEOUT] = IMR_PSTIMEOUT,
-	.maps[RTL_IMR_BcnInt] = IMR_BCNINT,
+	.maps[RTL_IMR_BCNINT] = IMR_BCNINT,
 	.maps[RTL_IMR_RXFOVW] = IMR_RXFOVW,
 	.maps[RTL_IMR_RDU] = IMR_RDU,
 	.maps[RTL_IMR_ATIMEND] = IMR_ATIMEND,
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c
index b6222ee..710f790 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c
@@ -434,7 +434,7 @@ static void _rtl_rx_process(struct ieee80211_hw *hw, struct sk_buff *skb)
 		 (u32)hdr->addr1[2], (u32)hdr->addr1[3],
 		 (u32)hdr->addr1[4], (u32)hdr->addr1[5]);
 	memcpy(IEEE80211_SKB_RXCB(skb), rx_status, sizeof(*rx_status));
-	ieee80211_rx_irqsafe(hw, skb);
+	ieee80211_rx(hw, skb);
 }
 
 void  rtl8192cu_rx_hdl(struct ieee80211_hw *hw, struct sk_buff * skb)
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/dm.c b/drivers/net/wireless/rtlwifi/rtl8192de/dm.c
index 5251fb8..19a7655 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192de/dm.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/dm.c
@@ -171,8 +171,8 @@ static void rtl92d_dm_diginit(struct ieee80211_hw *hw)
 	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->rx_gain_max = DM_DIG_FA_UPPER;
+	de_digtable->rx_gain_min = DM_DIG_FA_LOWER;
 	de_digtable->back_val = DM_DIG_BACKOFF_DEFAULT;
 	de_digtable->back_range_max = DM_DIG_BACKOFF_MAX;
 	de_digtable->back_range_min = DM_DIG_BACKOFF_MIN;
@@ -444,8 +444,8 @@ static void rtl92d_dm_dig(struct ieee80211_hw *hw)
 		 "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);
+		 "dm_DIG() Before: Recover_cnt=%d, rx_gain_min=%x\n",
+		 de_digtable->recover_cnt, de_digtable->rx_gain_min);
 
 	/* deal with abnorally large false alarm */
 	if (falsealm_cnt->cnt_all > 10000) {
@@ -459,9 +459,9 @@ static void rtl92d_dm_dig(struct ieee80211_hw *hw)
 		}
 		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;
+				de_digtable->rx_gain_min = DM_DIG_MAX;
 			else
-				de_digtable->rx_gain_range_min =
+				de_digtable->rx_gain_min =
 				    (de_digtable->forbidden_igi + 1);
 			de_digtable->recover_cnt = 3600;	/* 3600=2hr */
 		}
@@ -475,12 +475,12 @@ static void rtl92d_dm_dig(struct ieee80211_hw *hw)
 				    DM_DIG_FA_LOWER) {
 					de_digtable->forbidden_igi =
 							 DM_DIG_FA_LOWER;
-					de_digtable->rx_gain_range_min =
+					de_digtable->rx_gain_min =
 							 DM_DIG_FA_LOWER;
 
 				} else {
 					de_digtable->forbidden_igi--;
-					de_digtable->rx_gain_range_min =
+					de_digtable->rx_gain_min =
 					    (de_digtable->forbidden_igi + 1);
 				}
 			} else if (de_digtable->large_fa_hit == 3) {
@@ -492,13 +492,13 @@ static void rtl92d_dm_dig(struct ieee80211_hw *hw)
 		 "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);
+		 "dm_DIG() After: recover_cnt=%d, rx_gain_min=%x\n",
+		 de_digtable->recover_cnt, de_digtable->rx_gain_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;
+	else if (value_igi < de_digtable->rx_gain_min)
+		value_igi = de_digtable->rx_gain_min;
 	de_digtable->cur_igvalue = value_igi;
 	rtl92d_dm_write_dig(hw);
 	if (rtlpriv->rtlhal.current_bandtype != BAND_ON_5G)
@@ -1071,9 +1071,9 @@ static void rtl92d_dm_txpower_tracking_callback_thermalmeter(
 			}
 			ele_d = (ofdmswing_table[(u8) ofdm_index[0]] &
 						 0xFFC00000) >> 22;
-			val_x = rtlphy->iqk_matrix_regsetting
+			val_x = rtlphy->iqk_matrix
 						[indexforchannel].value[0][0];
-			val_y = rtlphy->iqk_matrix_regsetting
+			val_y = rtlphy->iqk_matrix
 						[indexforchannel].value[0][1];
 			if (val_x != 0) {
 				if ((val_x & 0x00000200) != 0)
@@ -1175,9 +1175,9 @@ static void rtl92d_dm_txpower_tracking_callback_thermalmeter(
 			if (is2t) {
 				ele_d = (ofdmswing_table[(u8) ofdm_index[1]] &
 						0xFFC00000) >> 22;
-				val_x = rtlphy->iqk_matrix_regsetting
+				val_x = rtlphy->iqk_matrix
 						[indexforchannel].value[0][4];
-				val_y = rtlphy->iqk_matrix_regsetting
+				val_y = rtlphy->iqk_matrix
 						[indexforchannel].value[0][5];
 				if (val_x != 0) {
 					if ((val_x & 0x00000200) != 0)
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/hw.c b/drivers/net/wireless/rtlwifi/rtl8192de/hw.c
index aa5b425..7dd8f6d 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192de/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/hw.c
@@ -1183,7 +1183,7 @@ void rtl92d_linked_set_reg(struct ieee80211_hw *hw)
 	u8 channel = rtlphy->current_channel;
 
 	indexforchannel = rtl92d_get_rightchnlplace_for_iqk(channel);
-	if (!rtlphy->iqk_matrix_regsetting[indexforchannel].iqk_done) {
+	if (!rtlphy->iqk_matrix[indexforchannel].iqk_done) {
 		RT_TRACE(rtlpriv, COMP_SCAN | COMP_INIT, DBG_DMESG,
 			 "Do IQK for channel:%d\n", channel);
 		rtl92d_phy_iq_calibrate(hw);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/phy.c b/drivers/net/wireless/rtlwifi/rtl8192de/phy.c
index 33041bd..840bac5 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192de/phy.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/phy.c
@@ -2479,9 +2479,9 @@ void rtl92d_phy_iq_calibrate(struct ieee80211_hw *hw)
 				  rtlphy->current_channel);
 
 		for (i = 0; i < IQK_MATRIX_REG_NUM; i++)
-			rtlphy->iqk_matrix_regsetting[indexforchannel].
+			rtlphy->iqk_matrix[indexforchannel].
 				value[0][i] = result[final_candidate][i];
-		rtlphy->iqk_matrix_regsetting[indexforchannel].iqk_done =
+		rtlphy->iqk_matrix[indexforchannel].iqk_done =
 			true;
 
 		RT_TRACE(rtlpriv, COMP_SCAN | COMP_MLME, DBG_LOUD,
@@ -2501,8 +2501,8 @@ void rtl92d_phy_reload_iqk_setting(struct ieee80211_hw *hw, u8 channel)
 	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->iqk_matrix[indexforchannel].iqk_done);
+	if (0 && !rtlphy->iqk_matrix[indexforchannel].iqk_done &&
 		rtlphy->need_iqk) {
 		/* Re Do IQK. */
 		RT_TRACE(rtlpriv, COMP_SCAN | COMP_INIT, DBG_LOUD,
@@ -2516,23 +2516,23 @@ void rtl92d_phy_reload_iqk_setting(struct ieee80211_hw *hw, u8 channel)
 			RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD,
 				 "Just Read IQK Matrix reg for channel:%d....\n",
 				 channel);
-			if ((rtlphy->iqk_matrix_regsetting[indexforchannel].
+			if ((rtlphy->iqk_matrix[indexforchannel].
 			     value[0] != NULL)
 				/*&&(regea4 != 0) */)
 				_rtl92d_phy_patha_fill_iqk_matrix(hw, true,
-					rtlphy->iqk_matrix_regsetting[
+					rtlphy->iqk_matrix[
 					indexforchannel].value,	0,
-					(rtlphy->iqk_matrix_regsetting[
+					(rtlphy->iqk_matrix[
 					indexforchannel].value[0][2] == 0));
 			if (IS_92D_SINGLEPHY(rtlhal->version)) {
-				if ((rtlphy->iqk_matrix_regsetting[
+				if ((rtlphy->iqk_matrix[
 					indexforchannel].value[0][4] != 0)
 					/*&&(regec4 != 0) */)
 					_rtl92d_phy_pathb_fill_iqk_matrix(hw,
 						true,
-						rtlphy->iqk_matrix_regsetting[
+						rtlphy->iqk_matrix[
 						indexforchannel].value, 0,
-						(rtlphy->iqk_matrix_regsetting[
+						(rtlphy->iqk_matrix[
 						indexforchannel].value[0][6]
 						== 0));
 			}
@@ -2830,20 +2830,20 @@ void rtl92d_phy_reset_iqk_result(struct ieee80211_hw *hw)
 
 	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
 		 "settings regs %d default regs %d\n",
-		 (int)(sizeof(rtlphy->iqk_matrix_regsetting) /
+		 (int)(sizeof(rtlphy->iqk_matrix) /
 		       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;
+		rtlphy->iqk_matrix[i].value[0][0] = 0x100;
+		rtlphy->iqk_matrix[i].value[0][2] = 0x100;
+		rtlphy->iqk_matrix[i].value[0][4] = 0x100;
+		rtlphy->iqk_matrix[i].value[0][6] = 0x100;
+		rtlphy->iqk_matrix[i].value[0][1] = 0x0;
+		rtlphy->iqk_matrix[i].value[0][3] = 0x0;
+		rtlphy->iqk_matrix[i].value[0][5] = 0x0;
+		rtlphy->iqk_matrix[i].value[0][7] = 0x0;
+		rtlphy->iqk_matrix[i].iqk_done = false;
 	}
 }
 
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/reg.h b/drivers/net/wireless/rtlwifi/rtl8192de/reg.h
index ebb1d5f..b7498c5 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192de/reg.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/reg.h
@@ -543,7 +543,7 @@
 #define	IMR_TIMEOUT1			BIT(16)
 #define	IMR_TXFOVW			BIT(15)
 #define	IMR_PSTIMEOUT			BIT(14)
-#define	IMR_BcnInt			BIT(13)
+#define	IMR_BCNINT			BIT(13)
 #define	IMR_RXFOVW			BIT(12)
 #define	IMR_RDU				BIT(11)
 #define	IMR_ATIMEND			BIT(10)
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/sw.c b/drivers/net/wireless/rtlwifi/rtl8192de/sw.c
index 03c6d18..c18c04b 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192de/sw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/sw.c
@@ -166,7 +166,7 @@ static int rtl92d_init_sw_vars(struct ieee80211_hw *hw)
 		rtlpriv->psc.fwctrl_psmode = FW_PS_DTIM_MODE;
 
 	/* for early mode */
-	rtlpriv->rtlhal.earlymode_enable = true;
+	rtlpriv->rtlhal.earlymode_enable = false;
 	for (tid = 0; tid < 8; tid++)
 		skb_queue_head_init(&rtlpriv->mac80211.skb_waitq[tid]);
 
@@ -319,7 +319,7 @@ static struct rtl_hal_cfg rtl92de_hal_cfg = {
 
 	.maps[RTL_IMR_TXFOVW] = IMR_TXFOVW,
 	.maps[RTL_IMR_PSTIMEOUT] = IMR_PSTIMEOUT,
-	.maps[RTL_IMR_BcnInt] = IMR_BcnInt,
+	.maps[RTL_IMR_BCNINT] = IMR_BCNINT,
 	.maps[RTL_IMR_RXFOVW] = IMR_RXFOVW,
 	.maps[RTL_IMR_RDU] = IMR_RDU,
 	.maps[RTL_IMR_ATIMEND] = IMR_ATIMEND,
@@ -333,7 +333,7 @@ static struct rtl_hal_cfg rtl92de_hal_cfg = {
 	.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_IBSS_INT_MASKS] = (IMR_BCNINT | IMR_TBDOK | IMR_TBDER),
 
 	.maps[RTL_RC_CCK_RATE1M] = DESC92_RATE1M,
 	.maps[RTL_RC_CCK_RATE2M] = DESC92_RATE2M,
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/def.h b/drivers/net/wireless/rtlwifi/rtl8192se/def.h
index 2d255e0..83c9867 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/def.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/def.h
@@ -36,9 +36,6 @@
 #define SHORT_SLOT_TIME				9
 #define NON_SHORT_SLOT_TIME			20
 
-/* Rx smooth factor */
-#define	RX_SMOOTH_FACTOR			20
-
 /* Queue Select Value in TxDesc */
 #define QSLT_BK					0x2
 #define QSLT_BE					0x0
@@ -49,10 +46,6 @@
 #define QSLT_MGNT				0x12
 #define QSLT_CMD				0x13
 
-#define	PHY_RSSI_SLID_WIN_MAX			100
-#define	PHY_LINKQUALITY_SLID_WIN_MAX		20
-#define	PHY_BEACON_RSSI_SLID_WIN_MAX		10
-
 /* Tx Desc */
 #define TX_DESC_SIZE_RTL8192S			(16 * 4)
 #define TX_CMDDESC_SIZE_RTL8192S		(16 * 4)
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/dm.c b/drivers/net/wireless/rtlwifi/rtl8192se/dm.c
index e551fe5..b3a2d5e 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/dm.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/dm.c
@@ -163,6 +163,7 @@ static void _rtl92s_dm_txpowertracking_callback_thermalmeter(
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
 	u8 thermalvalue = 0;
+	u32 fw_cmd = 0;
 
 	rtlpriv->dm.txpower_trackinginit = true;
 
@@ -175,7 +176,19 @@ static void _rtl92s_dm_txpowertracking_callback_thermalmeter(
 
 	if (thermalvalue) {
 		rtlpriv->dm.thermalvalue = thermalvalue;
-		rtl92s_phy_set_fw_cmd(hw, FW_CMD_TXPWR_TRACK_THERMAL);
+		if (hal_get_firmwareversion(rtlpriv) >= 0x35) {
+			rtl92s_phy_set_fw_cmd(hw, FW_CMD_TXPWR_TRACK_THERMAL);
+		} else {
+			fw_cmd = (FW_TXPWR_TRACK_THERMAL |
+				 (rtlpriv->efuse.thermalmeter[0] << 8) |
+				 (thermalvalue << 16));
+
+			RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+				 "Write to FW Thermal Val = 0x%x\n", fw_cmd);
+
+			rtl_write_dword(rtlpriv, WFM5, fw_cmd);
+			rtl92s_phy_chk_fwcmd_iodone(hw);
+		}
 	}
 
 	rtlpriv->dm.txpowercount = 0;
@@ -217,11 +230,10 @@ static void _rtl92s_dm_refresh_rateadaptive_mask(struct ieee80211_hw *hw)
 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 	struct rate_adaptive *ra = &(rtlpriv->ra);
-
+	struct ieee80211_sta *sta = NULL;
 	u32 low_rssi_thresh = 0;
 	u32 middle_rssi_thresh = 0;
 	u32 high_rssi_thresh = 0;
-	struct ieee80211_sta *sta = NULL;
 
 	if (is_hal_stop(rtlhal))
 		return;
@@ -229,14 +241,12 @@ static void _rtl92s_dm_refresh_rateadaptive_mask(struct ieee80211_hw *hw)
 	if (!rtlpriv->dm.useramask)
 		return;
 
-	if (!rtlpriv->dm.inform_fw_driverctrldm) {
+	if (hal_get_firmwareversion(rtlpriv) >= 61 &&
+	    !rtlpriv->dm.inform_fw_driverctrldm) {
 		rtl92s_phy_set_fw_cmd(hw, FW_CMD_CTRL_DM_BY_DRIVER);
 		rtlpriv->dm.inform_fw_driverctrldm = true;
 	}
 
-	rcu_read_lock();
-	if (mac->opmode == NL80211_IFTYPE_STATION)
-		sta = get_sta(hw, mac->vif, mac->bssid);
 	if ((mac->link_state == MAC80211_LINKED) &&
 	    (mac->opmode == NL80211_IFTYPE_STATION)) {
 		switch (ra->pre_ratr_state) {
@@ -285,12 +295,16 @@ static void _rtl92s_dm_refresh_rateadaptive_mask(struct ieee80211_hw *hw)
 				 rtlpriv->dm.undec_sm_pwdb, ra->ratr_state,
 				 ra->pre_ratr_state, ra->ratr_state);
 
-			rtlpriv->cfg->ops->update_rate_tbl(hw, sta,
+			rcu_read_lock();
+			sta = rtl_find_sta(hw, mac->bssid);
+			if (sta)
+				rtlpriv->cfg->ops->update_rate_tbl(hw, sta,
 							   ra->ratr_state);
+			rcu_read_unlock();
+
 			ra->pre_ratr_state = ra->ratr_state;
 		}
 	}
-	rcu_read_unlock();
 }
 
 static void _rtl92s_dm_switch_baseband_mrc(struct ieee80211_hw *hw)
@@ -370,7 +384,8 @@ static void _rtl92s_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw)
 	ra->ratr_state = DM_RATR_STA_MAX;
 	ra->pre_ratr_state = DM_RATR_STA_MAX;
 
-	if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER)
+	if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER &&
+	    hal_get_firmwareversion(rtlpriv) >= 60)
 		rtlpriv->dm.useramask = true;
 	else
 		rtlpriv->dm.useramask = false;
@@ -457,13 +472,13 @@ static void _rtl92s_dm_initial_gain_sta_beforeconnect(struct ieee80211_hw *hw)
 				digtable->back_val = DM_DIG_BACKOFF;
 
 			if ((digtable->rssi_val + 10 - digtable->back_val) >
-				digtable->rx_gain_range_max)
+				digtable->rx_gain_max)
 				digtable->cur_igvalue =
-						digtable->rx_gain_range_max;
+						digtable->rx_gain_max;
 			else if ((digtable->rssi_val + 10 - digtable->back_val)
-				 < digtable->rx_gain_range_min)
+				 < digtable->rx_gain_min)
 				digtable->cur_igvalue =
-						digtable->rx_gain_range_min;
+						digtable->rx_gain_min;
 			else
 				digtable->cur_igvalue = digtable->rssi_val + 10
 					- digtable->back_val;
@@ -475,7 +490,7 @@ static void _rtl92s_dm_initial_gain_sta_beforeconnect(struct ieee80211_hw *hw)
 
 			if (falsealm_cnt->cnt_all > 16000)
 				digtable->cur_igvalue =
-						 digtable->rx_gain_range_max;
+						 digtable->rx_gain_max;
 		/* connected -> connected or disconnected -> disconnected  */
 		} else {
 			/* Firmware control DIG, do nothing in driver dm */
@@ -677,9 +692,9 @@ static void _rtl92s_dm_init_dig(struct ieee80211_hw *hw)
 	/* for dig debug rssi value */
 	digtable->rssi_val = 50;
 	digtable->back_val = DM_DIG_BACKOFF;
-	digtable->rx_gain_range_max = DM_DIG_MAX;
+	digtable->rx_gain_max = DM_DIG_MAX;
 
-	digtable->rx_gain_range_min = DM_DIG_MIN;
+	digtable->rx_gain_min = DM_DIG_MIN;
 
 	digtable->backoffval_range_max = DM_DIG_BACKOFF_MAX;
 	digtable->backoffval_range_min = DM_DIG_BACKOFF_MIN;
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c b/drivers/net/wireless/rtlwifi/rtl8192se/hw.c
index 084e777..4f46178 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/hw.c
@@ -400,6 +400,39 @@ void rtl92se_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
 
 			break;
 		}
+	case HW_VAR_FW_LPS_ACTION: {
+		bool enter_fwlps = *((bool *)val);
+		u8 rpwm_val, fw_pwrmode;
+		bool fw_current_inps;
+
+		if (enter_fwlps) {
+			rpwm_val = 0x02;	/* RF off */
+			fw_current_inps = true;
+			rtlpriv->cfg->ops->set_hw_reg(hw,
+					HW_VAR_FW_PSMODE_STATUS,
+					(u8 *)(&fw_current_inps));
+			rtlpriv->cfg->ops->set_hw_reg(hw,
+					HW_VAR_H2C_FW_PWRMODE,
+					(u8 *)(&ppsc->fwctrl_psmode));
+
+			rtlpriv->cfg->ops->set_hw_reg(hw,
+					HW_VAR_SET_RPWM,
+					(u8 *)(&rpwm_val));
+		} else {
+			rpwm_val = 0x0C;	/* RF on */
+			fw_pwrmode = FW_PS_ACTIVE_MODE;
+			fw_current_inps = false;
+			rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM,
+					(u8 *)(&rpwm_val));
+			rtlpriv->cfg->ops->set_hw_reg(hw,
+					HW_VAR_H2C_FW_PWRMODE,
+					(u8 *)(&fw_pwrmode));
+
+			rtlpriv->cfg->ops->set_hw_reg(hw,
+					HW_VAR_FW_PSMODE_STATUS,
+					(u8 *)(&fw_current_inps));
+		}
+		break; }
 	default:
 		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
 			 "switch case not processed\n");
@@ -438,7 +471,7 @@ void rtl92se_enable_hw_security_config(struct ieee80211_hw *hw)
 
 }
 
-static u8 _rtl92ce_halset_sysclk(struct ieee80211_hw *hw, u8 data)
+static u8 _rtl92se_halset_sysclk(struct ieee80211_hw *hw, u8 data)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	u8 waitcount = 100;
@@ -547,7 +580,7 @@ static void _rtl92se_macconfig_before_fwdownload(struct ieee80211_hw *hw)
 		tmpu1b &= ~(BIT(6) | BIT(7));
 
 		/* Set failed, return to prevent hang. */
-		if (!_rtl92ce_halset_sysclk(hw, tmpu1b))
+		if (!_rtl92se_halset_sysclk(hw, tmpu1b))
 			return;
 	}
 
@@ -650,7 +683,7 @@ static void _rtl92se_macconfig_before_fwdownload(struct ieee80211_hw *hw)
 
 	tmpu1b = rtl_read_byte(rtlpriv, (SYS_CLKR + 1));
 	tmpu1b = ((tmpu1b | BIT(7)) & (~BIT(6)));
-	if (!_rtl92ce_halset_sysclk(hw, tmpu1b))
+	if (!_rtl92se_halset_sysclk(hw, tmpu1b))
 		return; /* Set failed, return to prevent hang. */
 
 	rtl_write_word(rtlpriv, CMDR, 0x07FC);
@@ -967,6 +1000,15 @@ int rtl92se_hw_init(struct ieee80211_hw *hw)
 		return rtstatus;
 	}
 
+	/* 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, RCR);
+	rtlpci->receive_config &= ~(RCR_ACRC32 | RCR_AICV);
+	rtl_write_dword(rtlpriv, RCR, rtlpci->receive_config);
+
 	/* Make sure BB/RF write OK. We should prevent enter IPS. radio off. */
 	/* We must set flag avoid BB/RF config period later!! */
 	rtl_write_dword(rtlpriv, CMDR, 0x37FC);
@@ -982,25 +1024,6 @@ int rtl92se_hw_init(struct ieee80211_hw *hw)
 
 	rtlphy->rf_mode = RF_OP_BY_SW_3WIRE;
 
-	/* RF Power Save */
-#if 0
-	/* H/W or S/W RF OFF before sleep. */
-	if (rtlpriv->psc.rfoff_reason > RF_CHANGE_BY_PS) {
-		u32 rfoffreason = rtlpriv->psc.rfoff_reason;
-
-		rtlpriv->psc.rfoff_reason = RF_CHANGE_BY_INIT;
-		rtlpriv->psc.rfpwr_state = ERFON;
-		/* 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) {
-			rtlpriv->psc.rfpwr_state = ERFON;
-			rtlpriv->psc.rfoff_reason = 0;
-		}
-	}
-#endif
-
 	/* Before RF-R/W we must execute the IO from Scott's suggestion. */
 	rtl_write_byte(rtlpriv, AFE_XTAL_CTRL + 1, 0xDB);
 	if (rtlhal->version == VERSION_8192S_ACUT)
@@ -1058,7 +1081,22 @@ int rtl92se_hw_init(struct ieee80211_hw *hw)
 
 	/* We enable high power and RA related mechanism after NIC
 	 * initialized. */
-	rtl92s_phy_set_fw_cmd(hw, FW_CMD_RA_INIT);
+	if (hal_get_firmwareversion(rtlpriv) >= 0x35) {
+		/* Fw v.53 and later. */
+		rtl92s_phy_set_fw_cmd(hw, FW_CMD_RA_INIT);
+	} else if (hal_get_firmwareversion(rtlpriv) == 0x34) {
+		/* Fw v.52. */
+		rtl_write_dword(rtlpriv, WFM5, FW_RA_INIT);
+		rtl92s_phy_chk_fwcmd_iodone(hw);
+	} else {
+		/* Compatible earlier FW version. */
+		rtl_write_dword(rtlpriv, WFM5, FW_RA_RESET);
+		rtl92s_phy_chk_fwcmd_iodone(hw);
+		rtl_write_dword(rtlpriv, WFM5, FW_RA_ACTIVE);
+		rtl92s_phy_chk_fwcmd_iodone(hw);
+		rtl_write_dword(rtlpriv, WFM5, FW_RA_REFRESH);
+		rtl92s_phy_chk_fwcmd_iodone(hw);
+	}
 
 	/* Add to prevent ASPM bug. */
 	/* Always enable hst and NIC clock request. */
@@ -1229,7 +1267,6 @@ void rtl92se_disable_interrupt(struct ieee80211_hw *hw)
 	synchronize_irq(rtlpci->pdev->irq);
 }
 
-
 static u8 _rtl92s_set_sysclk(struct ieee80211_hw *hw, u8 data)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
@@ -1754,7 +1791,7 @@ static void _rtl92se_read_adapter_info(struct ieee80211_hw *hw)
 		}
 
 		for (i = 0; i < 14; i++) {
-			RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+			RTPRINT(rtlpriv, FINIT, INIT_TXPOWER,
 				"RF(%d)-Ch(%d) [CCK / HT40_1S / HT40_2S] = [0x%x / 0x%x / 0x%x]\n",
 				rf_path, i,
 				rtlefuse->txpwrlevel_cck[rf_path][i],
@@ -1791,11 +1828,11 @@ static void _rtl92se_read_adapter_info(struct ieee80211_hw *hw)
 				((rtlefuse->eeprom_pwrgroup[rf_path][index] &
 				0xf0) >> 4);
 
-			RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+			RTPRINT(rtlpriv, FINIT, INIT_TXPOWER,
 				"RF-%d pwrgroup_ht20[%d] = 0x%x\n",
 				rf_path, i,
 				rtlefuse->pwrgroup_ht20[rf_path][i]);
-			RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+			RTPRINT(rtlpriv, FINIT, INIT_TXPOWER,
 				"RF-%d pwrgroup_ht40[%d] = 0x%x\n",
 				rf_path, i,
 				rtlefuse->pwrgroup_ht40[rf_path][i]);
@@ -1850,27 +1887,27 @@ static void _rtl92se_read_adapter_info(struct ieee80211_hw *hw)
 			rtlefuse->eeprom_regulatory =
 				 (hwinfo[EEPROM_REGULATORY] & 0x1);
 	}
-	RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+	RTPRINT(rtlpriv, FINIT, INIT_TXPOWER,
 		"eeprom_regulatory = 0x%x\n", rtlefuse->eeprom_regulatory);
 
 	for (i = 0; i < 14; i++)
-		RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+		RTPRINT(rtlpriv, FINIT, INIT_TXPOWER,
 			"RF-A Ht20 to HT40 Diff[%d] = 0x%x\n",
 			i, rtlefuse->txpwr_ht20diff[RF90_PATH_A][i]);
 	for (i = 0; i < 14; i++)
-		RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+		RTPRINT(rtlpriv, FINIT, INIT_TXPOWER,
 			"RF-A Legacy to Ht40 Diff[%d] = 0x%x\n",
 			i, rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][i]);
 	for (i = 0; i < 14; i++)
-		RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+		RTPRINT(rtlpriv, FINIT, INIT_TXPOWER,
 			"RF-B Ht20 to HT40 Diff[%d] = 0x%x\n",
 			i, rtlefuse->txpwr_ht20diff[RF90_PATH_B][i]);
 	for (i = 0; i < 14; i++)
-		RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+		RTPRINT(rtlpriv, FINIT, INIT_TXPOWER,
 			"RF-B Legacy to HT40 Diff[%d] = 0x%x\n",
 			i, rtlefuse->txpwr_legacyhtdiff[RF90_PATH_B][i]);
 
-	RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+	RTPRINT(rtlpriv, FINIT, INIT_TXPOWER,
 		"TxPwrSafetyFlag = %d\n", rtlefuse->txpwr_safetyflag);
 
 	/* Read RF-indication and Tx Power gain
@@ -1880,7 +1917,7 @@ static void _rtl92se_read_adapter_info(struct ieee80211_hw *hw)
 	rtlefuse->legacy_httxpowerdiff =
 		rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][0];
 
-	RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+	RTPRINT(rtlpriv, FINIT, INIT_TXPOWER,
 		"TxPowerDiff = %#x\n", rtlefuse->eeprom_txpowerdiff);
 
 	/* Get TSSI value for each path. */
@@ -1889,7 +1926,7 @@ static void _rtl92se_read_adapter_info(struct ieee80211_hw *hw)
 	usvalue = hwinfo[EEPROM_TSSI_B];
 	rtlefuse->eeprom_tssi[RF90_PATH_B] = (u8)(usvalue & 0xff);
 
-	RTPRINT(rtlpriv, FINIT, INIT_TxPower, "TSSI_A = 0x%x, TSSI_B = 0x%x\n",
+	RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, "TSSI_A = 0x%x, TSSI_B = 0x%x\n",
 		rtlefuse->eeprom_tssi[RF90_PATH_A],
 		rtlefuse->eeprom_tssi[RF90_PATH_B]);
 
@@ -1897,7 +1934,7 @@ static void _rtl92se_read_adapter_info(struct ieee80211_hw *hw)
 	/* and read ThermalMeter from EEPROM */
 	tempval = hwinfo[EEPROM_THERMALMETER];
 	rtlefuse->eeprom_thermalmeter = tempval;
-	RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+	RTPRINT(rtlpriv, FINIT, INIT_TXPOWER,
 		"thermalmeter = 0x%x\n", rtlefuse->eeprom_thermalmeter);
 
 	/* ThermalMeter, BIT(0)~3 for RFIC1, BIT(4)~7 for RFIC2 */
@@ -1914,7 +1951,7 @@ static void _rtl92se_read_adapter_info(struct ieee80211_hw *hw)
 	/* Version ID, Channel plan */
 	rtlefuse->eeprom_channelplan = hwinfo[EEPROM_CHANNELPLAN];
 	rtlefuse->txpwr_fromeprom = true;
-	RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+	RTPRINT(rtlpriv, FINIT, INIT_TXPOWER,
 		"EEPROM ChannelPlan = 0x%4x\n", rtlefuse->eeprom_channelplan);
 
 	/* Read Customer ID or Board Type!!! */
@@ -1999,6 +2036,8 @@ static void rtl92se_update_hal_rate_table(struct ieee80211_hw *hw,
 		ratr_value = sta->supp_rates[1] << 4;
 	else
 		ratr_value = sta->supp_rates[0];
+	if (mac->opmode == NL80211_IFTYPE_ADHOC)
+		ratr_value = 0xfff;
 	ratr_value |= (sta->ht_cap.mcs.rx_mask[1] << 20 |
 			sta->ht_cap.mcs.rx_mask[0] << 12);
 	switch (wirelessmode) {
@@ -2112,6 +2151,8 @@ static void rtl92se_update_hal_rate_mask(struct ieee80211_hw *hw,
 		ratr_bitmap = sta->supp_rates[1] << 4;
 	else
 		ratr_bitmap = sta->supp_rates[0];
+	if (mac->opmode == NL80211_IFTYPE_ADHOC)
+		ratr_bitmap = 0xfff;
 	ratr_bitmap |= (sta->ht_cap.mcs.rx_mask[1] << 20 |
 			sta->ht_cap.mcs.rx_mask[0] << 12);
 	switch (wirelessmode) {
@@ -2200,6 +2241,7 @@ static void rtl92se_update_hal_rate_mask(struct ieee80211_hw *hw,
 			ratr_bitmap &= 0x0f8ff0ff;
 		break;
 	}
+	sta_entry->ratr_index = ratr_index;
 
 	if (rtlpriv->rtlhal.version >= VERSION_8192S_BCUT)
 		ratr_bitmap &= 0x0FFFFFFF;
@@ -2438,23 +2480,9 @@ void rtl92se_set_key(struct ieee80211_hw *hw, u32 key_index, u8 *p_macaddr,
 				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,
-					      "Pairwise Key content",
-					      rtlpriv->sec.pairwise_key,
-					      rtlpriv->sec.
-					      key_len[PAIRWISE_KEYIDX]);
-
 				RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
 					 "set Pairwise key\n");
 
@@ -2502,3 +2530,23 @@ void rtl92se_resume(struct ieee80211_hw *hw)
 		pci_write_config_dword(rtlpci->pdev, 0x40,
 			val & 0xffff00ff);
 }
+
+/* Turn on AAP (RCR:bit 0) for promicuous mode. */
+void rtl92se_allow_all_destaddr(struct ieee80211_hw *hw,
+				bool allow_all_da, bool write_into_reg)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+
+	if (allow_all_da) /* Set BIT0 */
+		rtlpci->receive_config |= RCR_AAP;
+	else /* Clear BIT0 */
+		rtlpci->receive_config &= ~RCR_AAP;
+
+	if (write_into_reg)
+		rtl_write_dword(rtlpriv, RCR, rtlpci->receive_config);
+
+	RT_TRACE(rtlpriv, COMP_TURBO | COMP_INIT, DBG_LOUD,
+		 "receive_config=0x%08X, write_into_reg=%d\n",
+		 rtlpci->receive_config, write_into_reg);
+}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/hw.h b/drivers/net/wireless/rtlwifi/rtl8192se/hw.h
index a8e068c..da48aa8 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/hw.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/hw.h
@@ -74,6 +74,7 @@ void rtl92se_set_key(struct ieee80211_hw *hw,
 		     u8 enc_algo, bool is_wepkey, bool clear_all);
 void rtl92se_suspend(struct ieee80211_hw *hw);
 void rtl92se_resume(struct ieee80211_hw *hw);
+void rtl92se_allow_all_destaddr(struct ieee80211_hw *hw,
+				bool allow_all_da, bool write_into_reg);
 
 #endif
-
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/phy.c b/drivers/net/wireless/rtlwifi/rtl8192se/phy.c
index 6740497..9c092e6 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/phy.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/phy.c
@@ -1307,6 +1307,8 @@ static void _rtl92s_phy_set_fwcmd_io(struct ieee80211_hw *hw)
 	if (is_hal_stop(rtlhal))
 		return;
 
+	if (hal_get_firmwareversion(rtlpriv) < 0x34)
+		goto skip;
 	/* We re-map RA related CMD IO to combinational ones */
 	/* if FW version is v.52 or later. */
 	switch (rtlhal->current_fwcmd_io) {
@@ -1320,6 +1322,7 @@ static void _rtl92s_phy_set_fwcmd_io(struct ieee80211_hw *hw)
 		break;
 	}
 
+skip:
 	switch (rtlhal->current_fwcmd_io) {
 	case FW_CMD_RA_RESET:
 		RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, "FW_CMD_RA_RESET\n");
@@ -1440,7 +1443,7 @@ bool rtl92s_phy_set_fw_cmd(struct ieee80211_hw *hw, enum fwcmd_iotype fw_cmdio)
 	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
 	u32	fw_param = FW_CMD_IO_PARA_QUERY(rtlpriv);
 	u16	fw_cmdmap = FW_CMD_IO_QUERY(rtlpriv);
-	bool bPostProcessing = false;
+	bool postprocessing = false;
 
 	RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
 		 "Set FW Cmd(%#x), set_fwcmd_inprogress(%d)\n",
@@ -1449,15 +1452,24 @@ bool rtl92s_phy_set_fw_cmd(struct ieee80211_hw *hw, enum fwcmd_iotype fw_cmdio)
 	do {
 		/* We re-map to combined FW CMD ones if firmware version */
 		/* is v.53 or later. */
-		switch (fw_cmdio) {
-		case FW_CMD_RA_REFRESH_N:
-			fw_cmdio = FW_CMD_RA_REFRESH_N_COMB;
-			break;
-		case FW_CMD_RA_REFRESH_BG:
-			fw_cmdio = FW_CMD_RA_REFRESH_BG_COMB;
-			break;
-		default:
-			break;
+		if (hal_get_firmwareversion(rtlpriv) >= 0x35) {
+			switch (fw_cmdio) {
+			case FW_CMD_RA_REFRESH_N:
+				fw_cmdio = FW_CMD_RA_REFRESH_N_COMB;
+				break;
+			case FW_CMD_RA_REFRESH_BG:
+				fw_cmdio = FW_CMD_RA_REFRESH_BG_COMB;
+				break;
+			default:
+				break;
+			}
+		} else {
+			if ((fw_cmdio == FW_CMD_IQK_ENABLE) ||
+			    (fw_cmdio == FW_CMD_RA_REFRESH_N) ||
+			    (fw_cmdio == FW_CMD_RA_REFRESH_BG)) {
+				postprocessing = true;
+				break;
+			}
 		}
 
 		/* If firmware version is v.62 or later,
@@ -1588,19 +1600,19 @@ bool rtl92s_phy_set_fw_cmd(struct ieee80211_hw *hw, enum fwcmd_iotype fw_cmdio)
 				fw_cmdmap &= ~FW_DIG_ENABLE_CTL;
 
 			FW_CMD_IO_SET(rtlpriv, fw_cmdmap);
-			bPostProcessing = true;
+			postprocessing = true;
 			break;
 		case FW_CMD_PAUSE_DM_BY_SCAN:
 			fw_cmdmap &= ~(FW_DIG_ENABLE_CTL |
 				       FW_HIGH_PWR_ENABLE_CTL |
 				       FW_SS_CTL);
 			FW_CMD_IO_SET(rtlpriv, fw_cmdmap);
-			bPostProcessing = true;
+			postprocessing = true;
 			break;
 		case FW_CMD_HIGH_PWR_DISABLE:
 			fw_cmdmap &= ~FW_HIGH_PWR_ENABLE_CTL;
 			FW_CMD_IO_SET(rtlpriv, fw_cmdmap);
-			bPostProcessing = true;
+			postprocessing = true;
 			break;
 		case FW_CMD_HIGH_PWR_ENABLE:
 			if (!(rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) &&
@@ -1608,7 +1620,7 @@ bool rtl92s_phy_set_fw_cmd(struct ieee80211_hw *hw, enum fwcmd_iotype fw_cmdio)
 				fw_cmdmap |= (FW_HIGH_PWR_ENABLE_CTL |
 					      FW_SS_CTL);
 				FW_CMD_IO_SET(rtlpriv, fw_cmdmap);
-				bPostProcessing = true;
+				postprocessing = true;
 			}
 			break;
 		case FW_CMD_DIG_MODE_FA:
@@ -1629,14 +1641,15 @@ bool rtl92s_phy_set_fw_cmd(struct ieee80211_hw *hw, enum fwcmd_iotype fw_cmdio)
 		default:
 			/* Pass to original FW CMD processing callback
 			 * routine. */
-			bPostProcessing = true;
+			postprocessing = true;
 			break;
 		}
 	} while (false);
 
 	/* We shall post processing these FW CMD if
-	 * variable bPostProcessing is set. */
-	if (bPostProcessing && !rtlhal->set_fwcmd_inprogress) {
+	 * variable postprocessing is set.
+	 */
+	if (postprocessing && !rtlhal->set_fwcmd_inprogress) {
 		rtlhal->set_fwcmd_inprogress = true;
 		/* Update current FW Cmd for callback use. */
 		rtlhal->current_fwcmd_io = fw_cmdio;
@@ -1697,8 +1710,18 @@ void rtl92s_phy_switch_ephy_parameter(struct ieee80211_hw *hw)
 
 }
 
-void rtl92s_phy_set_beacon_hwreg(struct ieee80211_hw *hw, u16 BeaconInterval)
+void rtl92s_phy_set_beacon_hwreg(struct ieee80211_hw *hw, u16 beaconinterval)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	rtl_write_dword(rtlpriv, WFM5, 0xF1000000 | (BeaconInterval << 8));
+	u32 new_bcn_num = 0;
+
+	if (hal_get_firmwareversion(rtlpriv) >= 0x33) {
+		/* Fw v.51 and later. */
+		rtl_write_dword(rtlpriv, WFM5, 0xF1000000 |
+				(beaconinterval << 8));
+	} else {
+		new_bcn_num = beaconinterval * 32 - 64;
+		rtl_write_dword(rtlpriv, WFM3 + 4, new_bcn_num);
+		rtl_write_dword(rtlpriv, WFM3, 0xB026007C);
+	}
 }
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/phy.h b/drivers/net/wireless/rtlwifi/rtl8192se/phy.h
index ac03877..8acf476 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/phy.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/phy.h
@@ -39,6 +39,7 @@
 #define MAX_POSTCMD_CNT			16
 
 #define RF90_PATH_MAX			4
+#define RF6052_MAX_PATH			2
 
 enum version_8192s {
 	VERSION_8192S_ACUT,
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c
index cecc377..2e8e6f8 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c
@@ -290,6 +290,7 @@ static struct rtl_hal_ops rtl8192se_hal_ops = {
 	.enable_hw_sec = rtl92se_enable_hw_security_config,
 	.set_key = rtl92se_set_key,
 	.init_sw_leds = rtl92se_init_sw_leds,
+	.allow_all_destaddr = rtl92se_allow_all_destaddr,
 	.get_bbreg = rtl92s_phy_query_bb_reg,
 	.set_bbreg = rtl92s_phy_set_bb_reg,
 	.get_rfreg = rtl92s_phy_query_rf_reg,
@@ -366,7 +367,7 @@ static struct rtl_hal_cfg rtl92se_hal_cfg = {
 
 	.maps[RTL_IMR_TXFOVW] = IMR_TXFOVW,
 	.maps[RTL_IMR_PSTIMEOUT] = IMR_PSTIMEOUT,
-	.maps[RTL_IMR_BcnInt] = IMR_BCNINT,
+	.maps[RTL_IMR_BCNINT] = IMR_BCNINT,
 	.maps[RTL_IMR_RXFOVW] = IMR_RXFOVW,
 	.maps[RTL_IMR_RDU] = IMR_RDU,
 	.maps[RTL_IMR_ATIMEND] = IMR_ATIMEND,
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
index 7b0a2e7..960bc28 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
@@ -30,6 +30,7 @@
 #include "../wifi.h"
 #include "../pci.h"
 #include "../base.h"
+#include "../stats.h"
 #include "reg.h"
 #include "def.h"
 #include "phy.h"
@@ -43,7 +44,7 @@ static u8 _rtl92se_map_hwqueue_to_fwqueue(struct sk_buff *skb,	u8 skb_queue)
 
 	if (unlikely(ieee80211_is_beacon(fc)))
 		return QSLT_BEACON;
-	if (ieee80211_is_mgmt(fc))
+	if (ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc))
 		return QSLT_MGNT;
 	if (ieee80211_is_nullfunc(fc))
 		return QSLT_HIGH;
@@ -51,65 +52,6 @@ static u8 _rtl92se_map_hwqueue_to_fwqueue(struct sk_buff *skb,	u8 skb_queue)
 	return skb->priority;
 }
 
-static u8 _rtl92s_query_rxpwrpercentage(char antpower)
-{
-	if ((antpower <= -100) || (antpower >= 20))
-		return 0;
-	else if (antpower >= 0)
-		return 100;
-	else
-		return 100 + antpower;
-}
-
-static u8 _rtl92s_evm_db_to_percentage(char value)
-{
-	char ret_val;
-	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 _rtl92se_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 _rtl92se_signal_scale_mapping(struct ieee80211_hw *hw,
-		long currsig)
-{
-	long retsig = 0;
-
-	/* Step 1. Scale mapping. */
-	if (currsig > 47)
-		retsig = 100;
-	else if (currsig > 14 && currsig <= 47)
-		retsig = 100 - ((47 - currsig) * 3) / 2;
-	else if (currsig > 2 && currsig <= 14)
-		retsig = 48 - ((14 - currsig) * 15) / 7;
-	else if (currsig >= 0)
-		retsig = currsig * 9 + 1;
-
-	return retsig;
-}
-
-
 static void _rtl92se_query_rxphystatus(struct ieee80211_hw *hw,
 				       struct rtl_stats *pstats, u8 *pdesc,
 				       struct rx_fwinfo *p_drvinfo,
@@ -119,11 +61,11 @@ static void _rtl92se_query_rxphystatus(struct ieee80211_hw *hw,
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct phy_sts_cck_8192s_t *cck_buf;
+	struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv);
 	s8 rx_pwr_all = 0, rx_pwr[4];
 	u8 rf_rx_num = 0, evm, pwdb_all;
 	u8 i, max_spatial_stream;
 	u32 rssi, total_rssi = 0;
-	bool in_powersavemode = false;
 	bool is_cck = pstats->is_cck;
 
 	pstats->packet_matchbssid = packet_match_bssid;
@@ -136,7 +78,7 @@ static void _rtl92se_query_rxphystatus(struct ieee80211_hw *hw,
 		u8 report, cck_highpwr;
 		cck_buf = (struct phy_sts_cck_8192s_t *)p_drvinfo;
 
-		if (!in_powersavemode)
+		if (ppsc->rfpwr_state == ERFON)
 			cck_highpwr = (u8) rtl_get_bbreg(hw,
 						RFPGA0_XA_HSSIPARAMETER2,
 						0x200);
@@ -181,7 +123,7 @@ static void _rtl92se_query_rxphystatus(struct ieee80211_hw *hw,
 			}
 		}
 
-		pwdb_all = _rtl92s_query_rxpwrpercentage(rx_pwr_all);
+		pwdb_all = rtl_query_rxpwrpercentage(rx_pwr_all);
 
 		/* CCK gain is smaller than OFDM/MCS gain,  */
 		/* so we add gain diff by experiences, the val is 6 */
@@ -222,13 +164,13 @@ static void _rtl92se_query_rxphystatus(struct ieee80211_hw *hw,
 	} else {
 		rtlpriv->dm.rfpath_rxenable[0] =
 		    rtlpriv->dm.rfpath_rxenable[1] = true;
-		for (i = RF90_PATH_A; i < RF90_PATH_MAX; i++) {
+		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 = _rtl92s_query_rxpwrpercentage(rx_pwr[i]);
+			rssi = rtl_query_rxpwrpercentage(rx_pwr[i]);
 			total_rssi += rssi;
 			rtlpriv->stats.rx_snr_db[i] =
 					 (long)(p_drvinfo->rxsnr[i] / 2);
@@ -238,7 +180,7 @@ static void _rtl92se_query_rxphystatus(struct ieee80211_hw *hw,
 		}
 
 		rx_pwr_all = ((p_drvinfo->pwdb_all >> 1) & 0x7f) - 110;
-		pwdb_all = _rtl92s_query_rxpwrpercentage(rx_pwr_all);
+		pwdb_all = rtl_query_rxpwrpercentage(rx_pwr_all);
 		pstats->rx_pwdb_all = pwdb_all;
 		pstats->rxpower = rx_pwr_all;
 		pstats->recvsignalpower = rx_pwr_all;
@@ -250,7 +192,7 @@ static void _rtl92se_query_rxphystatus(struct ieee80211_hw *hw,
 			max_spatial_stream = 1;
 
 		for (i = 0; i < max_spatial_stream; i++) {
-			evm = _rtl92s_evm_db_to_percentage(p_drvinfo->rxevm[i]);
+			evm = rtl_evm_db_to_percentage(p_drvinfo->rxevm[i]);
 
 			if (packet_match_bssid) {
 				if (i == 0)
@@ -262,212 +204,13 @@ static void _rtl92se_query_rxphystatus(struct ieee80211_hw *hw,
 	}
 
 	if (is_cck)
-		pstats->signalstrength = (u8)(_rtl92se_signal_scale_mapping(hw,
+		pstats->signalstrength = (u8)(rtl_signal_scale_mapping(hw,
 					 pwdb_all));
 	else if (rf_rx_num != 0)
-		pstats->signalstrength = (u8) (_rtl92se_signal_scale_mapping(hw,
+		pstats->signalstrength = (u8) (rtl_signal_scale_mapping(hw,
 				total_rssi /= rf_rx_num));
 }
 
-static void _rtl92se_process_ui_rssi(struct ieee80211_hw *hw,
-				     struct rtl_stats *pstats)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_phy *rtlphy = &(rtlpriv->phy);
-	u8 rfpath;
-	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 = _rtl92se_translate_todbm(hw,
-								(u8) tmpval);
-		pstats->rssi = rtlpriv->stats.signal_strength;
-	}
-
-	if (!pstats->is_cck && pstats->packet_toself) {
-		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 _rtl92se_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 _rtl92se_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 undec_sm_pwdb = 0;
-
-	if (mac->opmode == NL80211_IFTYPE_ADHOC) {
-		return;
-	} else {
-		undec_sm_pwdb =
-		    rtlpriv->dm.undec_sm_pwdb;
-	}
-
-	if (pstats->packet_toself || pstats->packet_beacon) {
-		if (undec_sm_pwdb < 0)
-			undec_sm_pwdb = pstats->rx_pwdb_all;
-
-		if (pstats->rx_pwdb_all > (u32) undec_sm_pwdb) {
-			undec_sm_pwdb =
-			    (((undec_sm_pwdb) *
-			    (RX_SMOOTH_FACTOR - 1)) +
-			    (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
-
-			undec_sm_pwdb = undec_sm_pwdb + 1;
-		} else {
-			undec_sm_pwdb = (((undec_sm_pwdb) *
-			      (RX_SMOOTH_FACTOR - 1)) + (pstats->rx_pwdb_all)) /
-			      (RX_SMOOTH_FACTOR);
-		}
-
-		rtlpriv->dm.undec_sm_pwdb = undec_sm_pwdb;
-		_rtl92se_update_rxsignalstatistics(hw, pstats);
-	}
-}
-
-static void rtl_92s_process_streams(struct ieee80211_hw *hw,
-				    struct rtl_stats *pstats)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	u32 stream;
-
-	for (stream = 0; stream < 2; stream++) {
-		if (pstats->rx_mimo_sig_qual[stream] != -1) {
-			if (rtlpriv->stats.rx_evm_percentage[stream] == 0) {
-				rtlpriv->stats.rx_evm_percentage[stream] =
-				    pstats->rx_mimo_sig_qual[stream];
-			}
-
-			rtlpriv->stats.rx_evm_percentage[stream] =
-			    ((rtlpriv->stats.rx_evm_percentage[stream] *
-					(RX_SMOOTH_FACTOR - 1)) +
-			     (pstats->rx_mimo_sig_qual[stream] *
-					1)) / (RX_SMOOTH_FACTOR);
-		}
-	}
-}
-
-static void _rtl92se_process_ui_link_quality(struct ieee80211_hw *hw,
-					     struct rtl_stats *pstats)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	u32 last_evm = 0, tmpval;
-
-	if (pstats->signalquality != 0) {
-		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;
-
-			rtl_92s_process_streams(hw, pstats);
-
-		}
-	}
-}
-
-static void _rtl92se_process_phyinfo(struct ieee80211_hw *hw,
-				     u8 *buffer,
-				     struct rtl_stats *pcurrent_stats)
-{
-
-	if (!pcurrent_stats->packet_matchbssid &&
-	    !pcurrent_stats->packet_beacon)
-		return;
-
-	_rtl92se_process_ui_rssi(hw, pcurrent_stats);
-	_rtl92se_process_pwdb(hw, pcurrent_stats);
-	_rtl92se_process_ui_link_quality(hw, pcurrent_stats);
-}
-
 static void _rtl92se_translate_rx_signal_stuff(struct ieee80211_hw *hw,
 		struct sk_buff *skb, struct rtl_stats *pstats,
 		u8 *pdesc, struct rx_fwinfo *p_drvinfo)
@@ -505,7 +248,7 @@ static void _rtl92se_translate_rx_signal_stuff(struct ieee80211_hw *hw,
 
 	_rtl92se_query_rxphystatus(hw, pstats, pdesc, p_drvinfo,
 			packet_matchbssid, packet_toself, packet_beacon);
-	_rtl92se_process_phyinfo(hw, tmp_buf, pstats);
+	rtl_process_phyinfo(hw, tmp_buf, pstats);
 }
 
 bool rtl92se_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats,
@@ -541,9 +284,6 @@ bool rtl92se_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats,
 	rx_status->freq = hw->conf.channel->center_freq;
 	rx_status->band = hw->conf.channel->band;
 
-	hdr = (struct ieee80211_hdr *)(skb->data + stats->rx_drvinfo_size
-	      + stats->rx_bufshift);
-
 	if (stats->crc)
 		rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
 
@@ -563,6 +303,13 @@ bool rtl92se_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats,
 	 * for IEEE80211w frame, and mac80211 sw will help
 	 * to decrypt it */
 	if (stats->decrypted) {
+		hdr = (struct ieee80211_hdr *)(skb->data +
+		       stats->rx_drvinfo_size + stats->rx_bufshift);
+
+		if (!hdr) {
+			/* during testing, hdr was NULL here */
+			return false;
+		}
 		if ((ieee80211_is_robust_mgmt_frame(hdr)) &&
 			(ieee80211_has_protected(hdr->frame_control)))
 			rx_status->flag &= ~RX_FLAG_DECRYPTED;
@@ -630,6 +377,11 @@ void rtl92se_tx_fill_desc(struct ieee80211_hw *hw,
 
 	CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE_RTL8192S);
 
+	if (ieee80211_is_nullfunc(fc) || ieee80211_is_ctl(fc)) {
+		firstseg = true;
+		lastseg = true;
+	}
+
 	if (firstseg) {
 		if (rtlpriv->dm.useramask) {
 			/* set txdesc macId */
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/dm.c b/drivers/net/wireless/rtlwifi/rtl8723ae/dm.c
index 12e2a3c..a36eee2 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723ae/dm.c
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/dm.c
@@ -166,8 +166,8 @@ static void rtl8723ae_dm_diginit(struct ieee80211_hw *hw)
 	dm_digtable->rssi_highthresh = DM_DIG_THRESH_HIGH;
 	dm_digtable->fa_lowthresh = DM_FALSEALARM_THRESH_LOW;
 	dm_digtable->fa_highthresh = DM_FALSEALARM_THRESH_HIGH;
-	dm_digtable->rx_gain_range_max = DM_DIG_MAX;
-	dm_digtable->rx_gain_range_min = DM_DIG_MIN;
+	dm_digtable->rx_gain_max = DM_DIG_MAX;
+	dm_digtable->rx_gain_min = DM_DIG_MIN;
 	dm_digtable->back_val = DM_DIG_BACKOFF_DEFAULT;
 	dm_digtable->back_range_max = DM_DIG_BACKOFF_MAX;
 	dm_digtable->back_range_min = DM_DIG_BACKOFF_MIN;
@@ -291,11 +291,11 @@ static void rtl92c_dm_ctrl_initgain_by_rssi(struct ieee80211_hw *hw)
 	}
 
 	if ((dgtbl->rssi_val_min + 10 - dgtbl->back_val) >
-	    dgtbl->rx_gain_range_max)
-		dgtbl->cur_igvalue = dgtbl->rx_gain_range_max;
+	    dgtbl->rx_gain_max)
+		dgtbl->cur_igvalue = dgtbl->rx_gain_max;
 	else if ((dgtbl->rssi_val_min + 10 -
-		  dgtbl->back_val) < dgtbl->rx_gain_range_min)
-		dgtbl->cur_igvalue = dgtbl->rx_gain_range_min;
+		  dgtbl->back_val) < dgtbl->rx_gain_min)
+		dgtbl->cur_igvalue = dgtbl->rx_gain_min;
 	else
 		dgtbl->cur_igvalue = dgtbl->rssi_val_min + 10 - dgtbl->back_val;
 
@@ -707,6 +707,77 @@ void rtl8723ae_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw)
 		rtlpriv->dm.useramask = false;
 }
 
+static void rtl8723ae_dm_refresh_rate_adaptive_mask(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 rate_adaptive *p_ra = &(rtlpriv->ra);
+	u32 low_rssithresh_for_ra, high_rssithresh_for_ra;
+	struct ieee80211_sta *sta = NULL;
+
+	if (is_hal_stop(rtlhal)) {
+		RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
+			 " driver is going to unload\n");
+		return;
+	}
+
+	if (!rtlpriv->dm.useramask) {
+		RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
+			 " driver does not control rate adaptive mask\n");
+		return;
+	}
+
+	if (mac->link_state == MAC80211_LINKED &&
+	    mac->opmode == NL80211_IFTYPE_STATION) {
+		switch (p_ra->pre_ratr_state) {
+		case DM_RATR_STA_HIGH:
+			high_rssithresh_for_ra = 50;
+			low_rssithresh_for_ra = 20;
+			break;
+		case DM_RATR_STA_MIDDLE:
+			high_rssithresh_for_ra = 55;
+			low_rssithresh_for_ra = 20;
+			break;
+		case DM_RATR_STA_LOW:
+			high_rssithresh_for_ra = 50;
+			low_rssithresh_for_ra = 25;
+			break;
+		default:
+			high_rssithresh_for_ra = 50;
+			low_rssithresh_for_ra = 20;
+			break;
+		}
+
+		if (rtlpriv->dm.undec_sm_pwdb > high_rssithresh_for_ra)
+			p_ra->ratr_state = DM_RATR_STA_HIGH;
+		else if (rtlpriv->dm.undec_sm_pwdb > low_rssithresh_for_ra)
+			p_ra->ratr_state = DM_RATR_STA_MIDDLE;
+		else
+			p_ra->ratr_state = DM_RATR_STA_LOW;
+
+		if (p_ra->pre_ratr_state != p_ra->ratr_state) {
+			RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
+				 "RSSI = %ld\n",
+				 rtlpriv->dm.undec_sm_pwdb);
+			RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
+				 "RSSI_LEVEL = %d\n", p_ra->ratr_state);
+			RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
+				 "PreState = %d, CurState = %d\n",
+				 p_ra->pre_ratr_state, p_ra->ratr_state);
+
+			rcu_read_lock();
+			sta = rtl_find_sta(hw, mac->bssid);
+			if (sta)
+				rtlpriv->cfg->ops->update_rate_tbl(hw, sta,
+							   p_ra->ratr_state);
+			rcu_read_unlock();
+
+			p_ra->pre_ratr_state = p_ra->ratr_state;
+		}
+	}
+}
+
 static void rtl8723ae_dm_init_dynamic_bpowersaving(struct ieee80211_hw *hw)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
@@ -853,6 +924,9 @@ void rtl8723ae_dm_watchdog(struct ieee80211_hw *hw)
 	rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON,
 				      (u8 *) (&fw_ps_awake));
 
+	if (ppsc->p2p_ps_info.p2p_ps_mode)
+		fw_ps_awake = false;
+
 	if ((ppsc->rfpwr_state == ERFON) &&
 	    ((!fw_current_inpsmode) && fw_ps_awake) &&
 	    (!ppsc->rfchange_inprogress)) {
@@ -861,7 +935,7 @@ void rtl8723ae_dm_watchdog(struct ieee80211_hw *hw)
 		rtl8723ae_dm_false_alarm_counter_statistics(hw);
 		rtl8723ae_dm_dynamic_bpowersaving(hw);
 		rtl8723ae_dm_dynamic_txpower(hw);
-		/* rtl92c_dm_refresh_rate_adaptive_mask(hw); */
+		rtl8723ae_dm_refresh_rate_adaptive_mask(hw);
 		rtl8723ae_dm_bt_coexist(hw);
 		rtl8723ae_dm_check_edca_turbo(hw);
 	}
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/dm.h b/drivers/net/wireless/rtlwifi/rtl8723ae/dm.h
index 39d2461..a372b02 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723ae/dm.h
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/dm.h
@@ -55,7 +55,13 @@
 #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 TXHIGHPWRLEVEL_NORMAL			0
 #define TXHIGHPWRLEVEL_LEVEL1			1
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/fw.c b/drivers/net/wireless/rtlwifi/rtl8723ae/fw.c
index 35cb8f8..dedfa1e 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723ae/fw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/fw.c
@@ -494,7 +494,9 @@ void rtl8723ae_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
 	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_SMART_PS(u1_h2c_set_pwrmode,
+					 (rtlpriv->mac80211.p2p) ?
+					 ppsc->smart_ps : 1);
 	SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(u1_h2c_set_pwrmode,
 					      ppsc->reg_max_lps_awakeintvl);
 
@@ -741,3 +743,96 @@ void rtl8723ae_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus)
 
 	rtl8723ae_fill_h2c_cmd(hw, H2C_JOINBSSRPT, 1, u1_joinbssrpt_parm);
 }
+
+static void rtl8723e_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw,
+					    u8 ctwindow)
+{
+	u8 u1_ctwindow_period[1] = {ctwindow};
+
+	rtl8723ae_fill_h2c_cmd(hw, H2C_P2P_PS_CTW_CMD, 1, u1_ctwindow_period);
+}
+
+void rtl8723ae_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw));
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	struct rtl_p2p_ps_info *p2pinfo = &(rtlps->p2p_ps_info);
+	struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload;
+	u8	i;
+	u16	ctwindow;
+	u32	start_time, tsf_low;
+
+	switch (p2p_ps_state) {
+	case P2P_PS_DISABLE:
+		RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_DISABLE\n");
+		memset(p2p_ps_offload, 0, sizeof(struct p2p_ps_offload_t));
+		break;
+	case P2P_PS_ENABLE:
+		RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_ENABLE\n");
+		/* update CTWindow value. */
+		if (p2pinfo->ctwindow > 0) {
+			p2p_ps_offload->ctwindow_en = 1;
+			ctwindow = p2pinfo->ctwindow;
+			rtl8723e_set_p2p_ctw_period_cmd(hw, ctwindow);
+		}
+
+		/* hw only support 2 set of NoA */
+		for (i = 0; i < p2pinfo->noa_num; i++) {
+			/* To control the register setting for which NOA*/
+			rtl_write_byte(rtlpriv, 0x5cf, (i << 4));
+			if (i == 0)
+				p2p_ps_offload->noa0_en = 1;
+			else
+				p2p_ps_offload->noa1_en = 1;
+
+			/* config P2P NoA Descriptor Register */
+			rtl_write_dword(rtlpriv, 0x5E0,
+					p2pinfo->noa_duration[i]);
+			rtl_write_dword(rtlpriv, 0x5E4,
+					p2pinfo->noa_interval[i]);
+
+			/*Get Current TSF value */
+			tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR);
+
+			start_time = p2pinfo->noa_start_time[i];
+			if (p2pinfo->noa_count_type[i] != 1) {
+				while (start_time <= (tsf_low+(50*1024))) {
+					start_time += p2pinfo->noa_interval[i];
+					if (p2pinfo->noa_count_type[i] != 255)
+						p2pinfo->noa_count_type[i]--;
+				}
+			}
+			rtl_write_dword(rtlpriv, 0x5E8, start_time);
+			rtl_write_dword(rtlpriv, 0x5EC,
+					p2pinfo->noa_count_type[i]);
+		}
+		if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) {
+			/* rst p2p circuit */
+			rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4));
+
+			p2p_ps_offload->offload_en = 1;
+
+			if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) {
+				p2p_ps_offload->role = 1;
+				p2p_ps_offload->allstasleep = 0;
+			} else {
+				p2p_ps_offload->role = 0;
+			}
+			p2p_ps_offload->discovery = 0;
+		}
+		break;
+	case P2P_PS_SCAN:
+		RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n");
+		p2p_ps_offload->discovery = 1;
+		break;
+	case P2P_PS_SCAN_DONE:
+		RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN_DONE\n");
+		p2p_ps_offload->discovery = 0;
+		p2pinfo->p2p_ps_state = P2P_PS_ENABLE;
+		break;
+	default:
+		break;
+	}
+	rtl8723ae_fill_h2c_cmd(hw, H2C_P2P_PS_OFFLOAD, 1, (u8 *)p2p_ps_offload);
+}
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/fw.h b/drivers/net/wireless/rtlwifi/rtl8723ae/fw.h
index 89994e1..ed3b795 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723ae/fw.h
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/fw.h
@@ -70,8 +70,10 @@ enum rtl8192c_h2c_cmd {
 	H2C_SETPWRMODE = 1,
 	H2C_JOINBSSRPT = 2,
 	H2C_RSVDPAGE = 3,
-	H2C_RSSI_REPORT = 5,
-	H2C_RA_MASK = 6,
+	H2C_RSSI_REPORT = 4,
+	H2C_P2P_PS_CTW_CMD = 5,
+	H2C_P2P_PS_OFFLOAD = 6,
+	H2C_RA_MASK = 7,
 	MAX_H2CCMD
 };
 
@@ -97,5 +99,6 @@ void rtl8723ae_firmware_selfreset(struct ieee80211_hw *hw);
 void rtl8723ae_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode);
 void rtl8723ae_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished);
 void rtl8723ae_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus);
+void rtl8723ae_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state);
 
 #endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c b/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c
index 9a0c71c..c333dfd 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c
@@ -449,6 +449,9 @@ void rtl8723ae_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
 		rtl8723ae_set_fw_joinbss_report_cmd(hw, (*(u8 *) val));
 
 		break; }
+	case HW_VAR_H2C_FW_P2P_PS_OFFLOAD:
+		rtl8723ae_set_p2p_ps_offload_cmd(hw, (*(u8 *)val));
+		break;
 	case HW_VAR_AID:{
 		u16 u2btmp;
 		u2btmp = rtl_read_word(rtlpriv, REG_BCN_PSR_RPT);
@@ -474,6 +477,39 @@ void rtl8723ae_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
 		if (btype_ibss == true)
 			_rtl8723ae_resume_tx_beacon(hw);
 		break; }
+	case HW_VAR_FW_LPS_ACTION: {
+		bool enter_fwlps = *((bool *)val);
+		u8 rpwm_val, fw_pwrmode;
+		bool fw_current_inps;
+
+		if (enter_fwlps) {
+			rpwm_val = 0x02;	/* RF off */
+			fw_current_inps = true;
+			rtlpriv->cfg->ops->set_hw_reg(hw,
+					HW_VAR_FW_PSMODE_STATUS,
+					(u8 *)(&fw_current_inps));
+			rtlpriv->cfg->ops->set_hw_reg(hw,
+					HW_VAR_H2C_FW_PWRMODE,
+					(u8 *)(&ppsc->fwctrl_psmode));
+
+			rtlpriv->cfg->ops->set_hw_reg(hw,
+					HW_VAR_SET_RPWM,
+					(u8 *)(&rpwm_val));
+		} else {
+			rpwm_val = 0x0C;	/* RF on */
+			fw_pwrmode = FW_PS_ACTIVE_MODE;
+			fw_current_inps = false;
+			rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM,
+					(u8 *)(&rpwm_val));
+			rtlpriv->cfg->ops->set_hw_reg(hw,
+					HW_VAR_H2C_FW_PWRMODE,
+					(u8 *)(&fw_pwrmode));
+
+			rtlpriv->cfg->ops->set_hw_reg(hw,
+					HW_VAR_FW_PSMODE_STATUS,
+					(u8 *)(&fw_current_inps));
+		}
+		break; }
 	default:
 		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
 			 "switch case not processed\n");
@@ -1379,7 +1415,7 @@ static void _rtl8723ae_read_txpower_info_from_hwpg(struct ieee80211_hw *hw,
 		}
 
 		for (i = 0; i < 14; i++) {
-			RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+			RTPRINT(rtlpriv, FINIT, INIT_TXPOWER,
 				"RF(%d)-Ch(%d) [CCK / HT40_1S / HT40_2S] = "
 				"[0x%x / 0x%x / 0x%x]\n", rf_path, i,
 				rtlefuse->txpwrlevel_cck[rf_path][i],
@@ -1420,10 +1456,10 @@ static void _rtl8723ae_read_txpower_info_from_hwpg(struct ieee80211_hw *hw,
 				    0xf0) >> 4);
 			}
 
-			RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+			RTPRINT(rtlpriv, FINIT, INIT_TXPOWER,
 				"RF-%d pwrgroup_ht20[%d] = 0x%x\n", rf_path, i,
 				rtlefuse->pwrgroup_ht20[rf_path][i]);
-			RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+			RTPRINT(rtlpriv, FINIT, INIT_TXPOWER,
 				"RF-%d pwrgroup_ht40[%d] = 0x%x\n", rf_path, i,
 				rtlefuse->pwrgroup_ht40[rf_path][i]);
 		}
@@ -1463,19 +1499,19 @@ static void _rtl8723ae_read_txpower_info_from_hwpg(struct ieee80211_hw *hw,
 	    rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][7];
 
 	for (i = 0; i < 14; i++)
-		RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+		RTPRINT(rtlpriv, FINIT, INIT_TXPOWER,
 			"RF-A Ht20 to HT40 Diff[%d] = 0x%x\n", i,
 			rtlefuse->txpwr_ht20diff[RF90_PATH_A][i]);
 	for (i = 0; i < 14; i++)
-		RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+		RTPRINT(rtlpriv, FINIT, INIT_TXPOWER,
 			"RF-A Legacy to Ht40 Diff[%d] = 0x%x\n", i,
 			rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][i]);
 	for (i = 0; i < 14; i++)
-		RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+		RTPRINT(rtlpriv, FINIT, INIT_TXPOWER,
 			"RF-B Ht20 to HT40 Diff[%d] = 0x%x\n", i,
 			rtlefuse->txpwr_ht20diff[RF90_PATH_B][i]);
 	for (i = 0; i < 14; i++)
-		RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+		RTPRINT(rtlpriv, FINIT, INIT_TXPOWER,
 			"RF-B Legacy to HT40 Diff[%d] = 0x%x\n", i,
 			rtlefuse->txpwr_legacyhtdiff[RF90_PATH_B][i]);
 
@@ -1483,14 +1519,14 @@ static void _rtl8723ae_read_txpower_info_from_hwpg(struct ieee80211_hw *hw,
 		rtlefuse->eeprom_regulatory = (hwinfo[RF_OPTION1] & 0x7);
 	else
 		rtlefuse->eeprom_regulatory = 0;
-	RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+	RTPRINT(rtlpriv, FINIT, INIT_TXPOWER,
 		"eeprom_regulatory = 0x%x\n", rtlefuse->eeprom_regulatory);
 
 	if (!autoload_fail)
 		rtlefuse->eeprom_tssi[RF90_PATH_A] = hwinfo[EEPROM_TSSI_A];
 	else
 		rtlefuse->eeprom_tssi[RF90_PATH_A] = EEPROM_DEFAULT_TSSI;
-	RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+	RTPRINT(rtlpriv, FINIT, INIT_TXPOWER,
 		"TSSI_A = 0x%x, TSSI_B = 0x%x\n",
 		rtlefuse->eeprom_tssi[RF90_PATH_A],
 		rtlefuse->eeprom_tssi[RF90_PATH_B]);
@@ -1505,7 +1541,7 @@ static void _rtl8723ae_read_txpower_info_from_hwpg(struct ieee80211_hw *hw,
 		rtlefuse->apk_thermalmeterignore = true;
 
 	rtlefuse->thermalmeter[0] = rtlefuse->eeprom_thermalmeter;
-	RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+	RTPRINT(rtlpriv, FINIT, INIT_TXPOWER,
 		"thermalmeter = 0x%x\n", rtlefuse->eeprom_thermalmeter);
 }
 
@@ -1713,19 +1749,7 @@ static void _rtl8723ae_hal_customized_behavior(struct ieee80211_hw *hw)
 	struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 
-	switch (rtlhal->oem_id) {
-	case RT_CID_819x_HP:
-		pcipriv->ledctl.led_opendrain = true;
-		break;
-	case RT_CID_819x_Lenovo:
-	case RT_CID_DEFAULT:
-	case RT_CID_TOSHIBA:
-	case RT_CID_CCX:
-	case RT_CID_819x_Acer:
-	case RT_CID_WHQL:
-	default:
-		break;
-	}
+	pcipriv->ledctl.led_opendrain = true;
 	RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
 		 "RT Customized ID: 0x%02X\n", rtlhal->oem_id);
 }
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/led.c b/drivers/net/wireless/rtlwifi/rtl8723ae/led.c
index 9c4e1d8..061526f 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723ae/led.c
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/led.c
@@ -54,8 +54,9 @@ void rtl8723ae_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
 	case LED_PIN_GPIO0:
 		break;
 	case LED_PIN_LED0:
+		ledcfg &= ~BIT(6);
 		rtl_write_byte(rtlpriv,
-			       REG_LEDCFG2, (ledcfg & 0xf0) | BIT(5) | BIT(6));
+			       REG_LEDCFG2, (ledcfg & 0xf0) | BIT(5));
 		break;
 	case LED_PIN_LED1:
 		rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg & 0x0f) | BIT(5));
@@ -84,16 +85,21 @@ void rtl8723ae_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
 		break;
 	case LED_PIN_LED0:
 		ledcfg &= 0xf0;
-		if (pcipriv->ledctl.led_opendrain)
+		if (pcipriv->ledctl.led_opendrain) {
+			ledcfg &= 0x90;
+			rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg|BIT(3)));
+			ledcfg = rtl_read_byte(rtlpriv, REG_MAC_PINMUX_CFG);
+			ledcfg &= 0xFE;
+			rtl_write_byte(rtlpriv, REG_MAC_PINMUX_CFG, ledcfg);
+		} else {
+			ledcfg &= ~BIT(6);
 			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)));
+				       (ledcfg | BIT(3) | BIT(5)));
+		}
 		break;
 	case LED_PIN_LED1:
-		ledcfg &= 0x0f;
-		rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg | BIT(3)));
+		ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG1) & 0x10;
+		rtl_write_byte(rtlpriv, REG_LEDCFG1, (ledcfg | BIT(3)));
 		break;
 	default:
 		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/sw.c b/drivers/net/wireless/rtlwifi/rtl8723ae/sw.c
index bb7cc90..e4c4cdc 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723ae/sw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/sw.c
@@ -305,7 +305,7 @@ static struct rtl_hal_cfg rtl8723ae_hal_cfg = {
 
 	.maps[RTL_IMR_TXFOVW] = PHIMR_TXFOVW,
 	.maps[RTL_IMR_PSTIMEOUT] = PHIMR_PSTIMEOUT,
-	.maps[RTL_IMR_BcnInt] = PHIMR_BCNDMAINT0,
+	.maps[RTL_IMR_BCNINT] = PHIMR_BCNDMAINT0,
 	.maps[RTL_IMR_RXFOVW] = PHIMR_RXFOVW,
 	.maps[RTL_IMR_RDU] = PHIMR_RDU,
 	.maps[RTL_IMR_ATIMEND] = PHIMR_ATIMEND_E,
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c b/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c
index ac08129..6c64365 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c
@@ -307,9 +307,6 @@ bool rtl8723ae_rx_query_desc(struct ieee80211_hw *hw,
 	rx_status->freq = hw->conf.channel->center_freq;
 	rx_status->band = hw->conf.channel->band;
 
-	hdr = (struct ieee80211_hdr *)(skb->data + status->rx_drvinfo_size
-		+ status->rx_bufshift);
-
 	if (status->crc)
 		rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
 
@@ -330,6 +327,13 @@ bool rtl8723ae_rx_query_desc(struct ieee80211_hw *hw,
 	 * to decrypt it
 	 */
 	if (status->decrypted) {
+		hdr = (struct ieee80211_hdr *)(skb->data +
+		       status->rx_drvinfo_size + status->rx_bufshift);
+
+		if (!hdr) {
+			/* during testing, hdr could be NULL here */
+			return false;
+		}
 		if ((ieee80211_is_robust_mgmt_frame(hdr)) &&
 			(ieee80211_has_protected(hdr->frame_control)))
 			rx_status->flag &= ~RX_FLAG_DECRYPTED;
diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c
index 5847d6d..83915dc 100644
--- a/drivers/net/wireless/rtlwifi/usb.c
+++ b/drivers/net/wireless/rtlwifi/usb.c
@@ -224,10 +224,9 @@ static void _usb_writeN_sync(struct rtl_priv *rtlpriv, u32 addr, void *data,
 	u8 *buffer;
 
 	wvalue = (u16)(addr & 0x0000ffff);
-	buffer = kmalloc(len, GFP_ATOMIC);
+	buffer = kmemdup(data, len, GFP_ATOMIC);
 	if (!buffer)
 		return;
-	memcpy(buffer, data, len);
 	usb_control_msg(udev, pipe, request, reqtype, wvalue,
 			index, buffer, len, 50);
 
@@ -309,6 +308,8 @@ static int _rtl_usb_init_tx(struct ieee80211_hw *hw)
 	return 0;
 }
 
+static void _rtl_rx_work(unsigned long param);
+
 static int _rtl_usb_init_rx(struct ieee80211_hw *hw)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
@@ -325,6 +326,12 @@ static int _rtl_usb_init_rx(struct ieee80211_hw *hw)
 	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);
+	init_usb_anchor(&rtlusb->rx_cleanup_urbs);
+
+	skb_queue_head_init(&rtlusb->rx_queue);
+	rtlusb->rx_work_tasklet.func = _rtl_rx_work;
+	rtlusb->rx_work_tasklet.data = (unsigned long)rtlusb;
+
 	return 0;
 }
 
@@ -406,40 +413,30 @@ static void rtl_usb_init_sw(struct ieee80211_hw *hw)
 	rtlusb->disableHWSM =  true;
 }
 
-#define __RADIO_TAP_SIZE_RSV	32
-
 static void _rtl_rx_completed(struct urb *urb);
 
-static struct sk_buff *_rtl_prep_rx_urb(struct ieee80211_hw *hw,
-					struct rtl_usb *rtlusb,
-					struct urb *urb,
-					gfp_t gfp_mask)
+static int _rtl_prep_rx_urb(struct ieee80211_hw *hw, struct rtl_usb *rtlusb,
+			      struct urb *urb, gfp_t gfp_mask)
 {
-	struct sk_buff *skb;
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	void *buf;
 
-	skb = __dev_alloc_skb((rtlusb->rx_max_size + __RADIO_TAP_SIZE_RSV),
-			       gfp_mask);
-	if (!skb) {
+	buf = usb_alloc_coherent(rtlusb->udev, rtlusb->rx_max_size, gfp_mask,
+				 &urb->transfer_dma);
+	if (!buf) {
 		RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG,
-			 "Failed to __dev_alloc_skb!!\n");
-		return ERR_PTR(-ENOMEM);
+			 "Failed to usb_alloc_coherent!!\n");
+		return -ENOMEM;
 	}
 
-	/* reserve some space for mac80211's radiotap */
-	skb_reserve(skb, __RADIO_TAP_SIZE_RSV);
 	usb_fill_bulk_urb(urb, rtlusb->udev,
 			  usb_rcvbulkpipe(rtlusb->udev, rtlusb->in_ep),
-			  skb->data, min(skb_tailroom(skb),
-			  (int)rtlusb->rx_max_size),
-			  _rtl_rx_completed, skb);
+			  buf, rtlusb->rx_max_size, _rtl_rx_completed, rtlusb);
+	urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
-	_rtl_install_trx_info(rtlusb, skb, rtlusb->in_ep);
-	return skb;
+	return 0;
 }
 
-#undef __RADIO_TAP_SIZE_RSV
-
 static void _rtl_usb_rx_process_agg(struct ieee80211_hw *hw,
 				    struct sk_buff *skb)
 {
@@ -523,22 +520,11 @@ static void _rtl_usb_rx_process_noagg(struct ieee80211_hw *hw,
 			if (unicast)
 				rtlpriv->link_info.num_rx_inperiod++;
 		}
-		if (likely(rtl_action_proc(hw, skb, false))) {
-			struct sk_buff *uskb = NULL;
-			u8 *pdata;
-
-			uskb = dev_alloc_skb(skb->len + 128);
-			if (uskb) {	/* drop packet on allocation failure */
-				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);
-			}
-			dev_kfree_skb_any(skb);
-		} else {
+
+		if (likely(rtl_action_proc(hw, skb, false)))
+			ieee80211_rx(hw, skb);
+		else
 			dev_kfree_skb_any(skb);
-		}
 	}
 }
 
@@ -555,15 +541,70 @@ static void _rtl_rx_pre_process(struct ieee80211_hw *hw, struct sk_buff *skb)
 	while (!skb_queue_empty(&rx_queue)) {
 		_skb = skb_dequeue(&rx_queue);
 		_rtl_usb_rx_process_agg(hw, _skb);
-		ieee80211_rx_irqsafe(hw, _skb);
+		ieee80211_rx(hw, _skb);
 	}
 }
 
+#define __RX_SKB_MAX_QUEUED	32
+
+static void _rtl_rx_work(unsigned long param)
+{
+	struct rtl_usb *rtlusb = (struct rtl_usb *)param;
+	struct ieee80211_hw *hw = usb_get_intfdata(rtlusb->intf);
+	struct sk_buff *skb;
+
+	while ((skb = skb_dequeue(&rtlusb->rx_queue))) {
+		if (unlikely(IS_USB_STOP(rtlusb))) {
+			dev_kfree_skb_any(skb);
+			continue;
+		}
+
+		if (likely(!rtlusb->usb_rx_segregate_hdl)) {
+			_rtl_usb_rx_process_noagg(hw, skb);
+		} else {
+			/* TO DO */
+			_rtl_rx_pre_process(hw, skb);
+			pr_err("rx agg not supported\n");
+		}
+	}
+}
+
+static unsigned int _rtl_rx_get_padding(struct ieee80211_hdr *hdr,
+					unsigned int len)
+{
+	unsigned int padding = 0;
+
+	/* make function no-op when possible */
+	if (NET_IP_ALIGN == 0 || len < sizeof(*hdr))
+		return 0;
+
+	/* alignment calculation as in lbtf_rx() / carl9170_rx_copy_data() */
+	/* TODO: deduplicate common code, define helper function instead? */
+
+	if (ieee80211_is_data_qos(hdr->frame_control)) {
+		u8 *qc = ieee80211_get_qos_ctl(hdr);
+
+		padding ^= NET_IP_ALIGN;
+
+		/* Input might be invalid, avoid accessing memory outside
+		 * the buffer.
+		 */
+		if ((unsigned long)qc - (unsigned long)hdr < len &&
+		    *qc & IEEE80211_QOS_CTL_A_MSDU_PRESENT)
+			padding ^= NET_IP_ALIGN;
+	}
+
+	if (ieee80211_has_a4(hdr->frame_control))
+		padding ^= NET_IP_ALIGN;
+
+	return padding;
+}
+
+#define __RADIO_TAP_SIZE_RSV	32
+
 static void _rtl_rx_completed(struct urb *_urb)
 {
-	struct sk_buff *skb = (struct sk_buff *)_urb->context;
-	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-	struct rtl_usb *rtlusb = (struct rtl_usb *)info->rate_driver_data[0];
+	struct rtl_usb *rtlusb = (struct rtl_usb *)_urb->context;
 	struct ieee80211_hw *hw = usb_get_intfdata(rtlusb->intf);
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	int err = 0;
@@ -572,28 +613,50 @@ static void _rtl_rx_completed(struct urb *_urb)
 		goto free;
 
 	if (likely(0 == _urb->status)) {
-		/* If this code were moved to work queue, would CPU
-		 * utilization be improved?  NOTE: We shall allocate another skb
-		 * and reuse the original one.
-		 */
-		skb_put(skb, _urb->actual_length);
+		unsigned int padding;
+		struct sk_buff *skb;
+		unsigned int qlen;
+		unsigned int size = _urb->actual_length;
+		struct ieee80211_hdr *hdr;
 
-		if (likely(!rtlusb->usb_rx_segregate_hdl)) {
-			struct sk_buff *_skb;
-			_rtl_usb_rx_process_noagg(hw, skb);
-			_skb = _rtl_prep_rx_urb(hw, rtlusb, _urb, GFP_ATOMIC);
-			if (IS_ERR(_skb)) {
-				err = PTR_ERR(_skb);
-				RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG,
-					 "Can't allocate skb for bulk IN!\n");
-				return;
-			}
-			skb = _skb;
-		} else{
-			/* TO DO */
-			_rtl_rx_pre_process(hw, skb);
-			pr_err("rx agg not supported\n");
+		if (size < RTL_RX_DESC_SIZE + sizeof(struct ieee80211_hdr)) {
+			RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG,
+				 "Too short packet from bulk IN! (len: %d)\n",
+				 size);
+			goto resubmit;
+		}
+
+		qlen = skb_queue_len(&rtlusb->rx_queue);
+		if (qlen >= __RX_SKB_MAX_QUEUED) {
+			RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG,
+				 "Pending RX skbuff queue full! (qlen: %d)\n",
+				 qlen);
+			goto resubmit;
 		}
+
+		hdr = (void *)(_urb->transfer_buffer + RTL_RX_DESC_SIZE);
+		padding = _rtl_rx_get_padding(hdr, size - RTL_RX_DESC_SIZE);
+
+		skb = dev_alloc_skb(size + __RADIO_TAP_SIZE_RSV + padding);
+		if (!skb) {
+			RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG,
+				 "Can't allocate skb for bulk IN!\n");
+			goto resubmit;
+		}
+
+		_rtl_install_trx_info(rtlusb, skb, rtlusb->in_ep);
+
+		/* Make sure the payload data is 4 byte aligned. */
+		skb_reserve(skb, padding);
+
+		/* reserve some space for mac80211's radiotap */
+		skb_reserve(skb, __RADIO_TAP_SIZE_RSV);
+
+		memcpy(skb_put(skb, size), _urb->transfer_buffer, size);
+
+		skb_queue_tail(&rtlusb->rx_queue, skb);
+		tasklet_schedule(&rtlusb->rx_work_tasklet);
+
 		goto resubmit;
 	}
 
@@ -609,9 +672,6 @@ static void _rtl_rx_completed(struct urb *_urb)
 	}
 
 resubmit:
-	skb_reset_tail_pointer(skb);
-	skb_trim(skb, 0);
-
 	usb_anchor_urb(_urb, &rtlusb->rx_submitted);
 	err = usb_submit_urb(_urb, GFP_ATOMIC);
 	if (unlikely(err)) {
@@ -621,13 +681,34 @@ resubmit:
 	return;
 
 free:
-	dev_kfree_skb_irq(skb);
+	/* On some architectures, usb_free_coherent must not be called from
+	 * hardirq context. Queue urb to cleanup list.
+	 */
+	usb_anchor_urb(_urb, &rtlusb->rx_cleanup_urbs);
+}
+
+#undef __RADIO_TAP_SIZE_RSV
+
+static void _rtl_usb_cleanup_rx(struct ieee80211_hw *hw)
+{
+	struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
+	struct urb *urb;
+
+	usb_kill_anchored_urbs(&rtlusb->rx_submitted);
+
+	tasklet_kill(&rtlusb->rx_work_tasklet);
+	skb_queue_purge(&rtlusb->rx_queue);
+
+	while ((urb = usb_get_from_anchor(&rtlusb->rx_cleanup_urbs))) {
+		usb_free_coherent(urb->dev, urb->transfer_buffer_length,
+				urb->transfer_buffer, urb->transfer_dma);
+		usb_free_urb(urb);
+	}
 }
 
 static int _rtl_usb_receive(struct ieee80211_hw *hw)
 {
 	struct urb *urb;
-	struct sk_buff *skb;
 	int err;
 	int i;
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
@@ -646,11 +727,10 @@ static int _rtl_usb_receive(struct ieee80211_hw *hw)
 			goto err_out;
 		}
 
-		skb = _rtl_prep_rx_urb(hw, rtlusb, urb, GFP_KERNEL);
-		if (IS_ERR(skb)) {
+		err = _rtl_prep_rx_urb(hw, rtlusb, urb, GFP_KERNEL);
+		if (err < 0) {
 			RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG,
 				 "Failed to prep_rx_urb!!\n");
-			err = PTR_ERR(skb);
 			usb_free_urb(urb);
 			goto err_out;
 		}
@@ -665,6 +745,7 @@ static int _rtl_usb_receive(struct ieee80211_hw *hw)
 
 err_out:
 	usb_kill_anchored_urbs(&rtlusb->rx_submitted);
+	_rtl_usb_cleanup_rx(hw);
 	return err;
 }
 
@@ -706,7 +787,7 @@ static void rtl_usb_cleanup(struct ieee80211_hw *hw)
 	SET_USB_STOP(rtlusb);
 
 	/* clean up rx stuff. */
-	usb_kill_anchored_urbs(&rtlusb->rx_submitted);
+	_rtl_usb_cleanup_rx(hw);
 
 	/* clean up tx stuff */
 	for (i = 0; i < RTL_USB_MAX_EP_NUM; i++) {
diff --git a/drivers/net/wireless/rtlwifi/usb.h b/drivers/net/wireless/rtlwifi/usb.h
index fb986f9..685273c 100644
--- a/drivers/net/wireless/rtlwifi/usb.h
+++ b/drivers/net/wireless/rtlwifi/usb.h
@@ -136,11 +136,14 @@ struct rtl_usb {
 	void (*usb_tx_cleanup)(struct ieee80211_hw *, struct sk_buff *);
 
 	/* Rx */
-	u8 in_ep_nums ;
+	u8 in_ep_nums;
 	u32 in_ep;		/* Bulk IN endpoint number */
 	u32 rx_max_size;	/* Bulk IN max buffer size */
 	u32 rx_urb_num;		/* How many Bulk INs are submitted to host. */
 	struct usb_anchor	rx_submitted;
+	struct usb_anchor	rx_cleanup_urbs;
+	struct tasklet_struct   rx_work_tasklet;
+	struct sk_buff_head	rx_queue;
 	void (*usb_rx_segregate_hdl)(struct ieee80211_hw *, struct sk_buff *,
 				     struct sk_buff_head *);
 	void (*usb_rx_hdl)(struct ieee80211_hw *, struct sk_buff *);
diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h
index f13258a..44328ba 100644
--- a/drivers/net/wireless/rtlwifi/wifi.h
+++ b/drivers/net/wireless/rtlwifi/wifi.h
@@ -99,11 +99,36 @@
 #define	CHANNEL_GROUP_MAX_5G		9
 #define CHANNEL_MAX_NUMBER_2G		14
 #define AVG_THERMAL_NUM			8
+#define AVG_THERMAL_NUM_88E		4
 #define MAX_TID_COUNT			9
 
 /* for early mode */
 #define FCS_LEN				4
 #define EM_HDR_LEN			8
+
+#define MAX_TX_COUNT			4
+#define	MAX_RF_PATH			4
+#define	MAX_CHNL_GROUP_24G		6
+#define	MAX_CHNL_GROUP_5G		14
+
+struct txpower_info_2g {
+	u8 index_cck_base[MAX_RF_PATH][MAX_CHNL_GROUP_24G];
+	u8 index_bw40_base[MAX_RF_PATH][MAX_CHNL_GROUP_24G];
+	/*If only one tx, only BW20 and OFDM are used.*/
+	u8 cck_diff[MAX_RF_PATH][MAX_TX_COUNT];
+	u8 ofdm_diff[MAX_RF_PATH][MAX_TX_COUNT];
+	u8 bw20_diff[MAX_RF_PATH][MAX_TX_COUNT];
+	u8 bw40_diff[MAX_RF_PATH][MAX_TX_COUNT];
+};
+
+struct txpower_info_5g {
+	u8 index_bw40_base[MAX_RF_PATH][MAX_CHNL_GROUP_5G];
+	/*If only one tx, only BW20, OFDM, BW80 and BW160 are used.*/
+	u8 ofdm_diff[MAX_RF_PATH][MAX_TX_COUNT];
+	u8 bw20_diff[MAX_RF_PATH][MAX_TX_COUNT];
+	u8 bw40_diff[MAX_RF_PATH][MAX_TX_COUNT];
+};
+
 enum intf_type {
 	INTF_PCI = 0,
 	INTF_USB = 1,
@@ -137,6 +162,7 @@ enum hardware_type {
 	HARDWARE_TYPE_RTL8192DU,
 	HARDWARE_TYPE_RTL8723AE,
 	HARDWARE_TYPE_RTL8723U,
+	HARDWARE_TYPE_RTL8188EE,
 
 	/* keep it last */
 	HARDWARE_TYPE_NUM
@@ -263,7 +289,7 @@ enum hw_variables {
 	HW_VAR_RATR_0,
 	HW_VAR_RRSR,
 	HW_VAR_CPU_RST,
-	HW_VAR_CECHK_BSSID,
+	HW_VAR_CHECK_BSSID,
 	HW_VAR_LBK_MODE,
 	HW_VAR_AES_11N_FIX,
 	HW_VAR_USB_RX_AGGR,
@@ -278,7 +304,10 @@ enum hw_variables {
 	HW_VAR_SET_RPWM,
 	HW_VAR_H2C_FW_PWRMODE,
 	HW_VAR_H2C_FW_JOINBSSRPT,
+	HW_VAR_H2C_FW_P2P_PS_OFFLOAD,
 	HW_VAR_FW_PSMODE_STATUS,
+	HW_VAR_RESUME_CLK_ON,
+	HW_VAR_FW_LPS_ACTION,
 	HW_VAR_1X1_RECV_COMBINE,
 	HW_VAR_STOP_SEND_BEACON,
 	HW_VAR_TSF_TIMER,
@@ -305,6 +334,7 @@ enum hw_variables {
 	HW_VAR_INT_AC,
 	HW_VAR_RF_TIMING,
 
+	HAL_DEF_WOWLAN,
 	HW_VAR_MRC,
 
 	HW_VAR_MGT_FILTER,
@@ -461,6 +491,7 @@ enum rtl_var_map {
 	EFUSE_MAX_SECTION_MAP,
 	EFUSE_REAL_CONTENT_SIZE,
 	EFUSE_OOB_PROTECT_BYTES_LEN,
+	EFUSE_ACCESS,
 
 	/*CAM map */
 	RWCAM,
@@ -493,7 +524,7 @@ enum rtl_var_map {
 	RTL_IMR_TIMEOUT1,	/*Timeout interrupt 1 */
 	RTL_IMR_TXFOVW,		/*Transmit FIFO Overflow */
 	RTL_IMR_PSTIMEOUT,	/*Power save time out interrupt */
-	RTL_IMR_BcnInt,		/*Beacon DMA Interrupt 0 */
+	RTL_IMR_BCNINT,		/*Beacon DMA Interrupt 0 */
 	RTL_IMR_RXFOVW,		/*Receive FIFO Overflow */
 	RTL_IMR_RDU,		/*Receive Descriptor Unavailable */
 	RTL_IMR_ATIMEND,	/*For 92C,ATIM Window End Interrupt */
@@ -508,7 +539,7 @@ enum rtl_var_map {
 	RTL_IMR_VIDOK,		/*AC_VI DMA OK Interrupt */
 	RTL_IMR_VODOK,		/*AC_VO DMA Interrupt */
 	RTL_IMR_ROK,		/*Receive DMA OK Interrupt */
-	RTL_IBSS_INT_MASKS,	/*(RTL_IMR_BcnInt | RTL_IMR_TBDOK |
+	RTL_IBSS_INT_MASKS,	/*(RTL_IMR_BCNINT | RTL_IMR_TBDOK |
 				 * RTL_IMR_TBDER) */
 	RTL_IMR_C2HCMD,		/*fw interrupt*/
 
@@ -742,6 +773,11 @@ struct false_alarm_statistics {
 	u32 cnt_ofdm_fail;
 	u32 cnt_cck_fail;
 	u32 cnt_all;
+	u32 cnt_ofdm_cca;
+	u32 cnt_cck_cca;
+	u32 cnt_cca_all;
+	u32 cnt_bw_usc;
+	u32 cnt_bw_lsc;
 };
 
 struct init_gain {
@@ -826,8 +862,67 @@ struct rtl_rfkill {
 	bool rfkill_state;	/*0 is off, 1 is on */
 };
 
+/*for P2P PS**/
+#define	P2P_MAX_NOA_NUM		2
+
+enum p2p_role {
+	P2P_ROLE_DISABLE = 0,
+	P2P_ROLE_DEVICE = 1,
+	P2P_ROLE_CLIENT = 2,
+	P2P_ROLE_GO = 3
+};
+
+enum p2p_ps_state {
+	P2P_PS_DISABLE = 0,
+	P2P_PS_ENABLE = 1,
+	P2P_PS_SCAN = 2,
+	P2P_PS_SCAN_DONE = 3,
+	P2P_PS_ALLSTASLEEP = 4, /* for P2P GO */
+};
+
+enum p2p_ps_mode {
+	P2P_PS_NONE = 0,
+	P2P_PS_CTWINDOW = 1,
+	P2P_PS_NOA	 = 2,
+	P2P_PS_MIX = 3, /* CTWindow and NoA */
+};
+
+struct rtl_p2p_ps_info {
+	enum p2p_ps_mode p2p_ps_mode; /* indicate p2p ps mode */
+	enum p2p_ps_state p2p_ps_state; /*  indicate p2p ps state */
+	u8 noa_index; /*  Identifies instance of Notice of Absence timing. */
+	/*  Client traffic window. A period of time in TU after TBTT. */
+	u8 ctwindow;
+	u8 opp_ps; /*  opportunistic power save. */
+	u8 noa_num; /*  number of NoA descriptor in P2P IE. */
+	/*  Count for owner, Type of client. */
+	u8 noa_count_type[P2P_MAX_NOA_NUM];
+	/*  Max duration for owner, preferred or min acceptable duration
+	 * for client.
+	 */
+	u32 noa_duration[P2P_MAX_NOA_NUM];
+	/*  Length of interval for owner, preferred or max acceptable intervali
+	 * of client.
+	 */
+	u32 noa_interval[P2P_MAX_NOA_NUM];
+	/*  schedule in terms of the lower 4 bytes of the TSF timer. */
+	u32 noa_start_time[P2P_MAX_NOA_NUM];
+};
+
+struct p2p_ps_offload_t {
+	u8 offload_en:1;
+	u8 role:1; /* 1: Owner, 0: Client */
+	u8 ctwindow_en:1;
+	u8 noa0_en:1;
+	u8 noa1_en:1;
+	u8 allstasleep:1;
+	u8 discovery:1;
+	u8 reserved:1;
+};
+
 #define IQK_MATRIX_REG_NUM	8
 #define IQK_MATRIX_SETTINGS_NUM	(1 + 24 + 21)
+
 struct iqk_matrix_regs {
 	bool iqk_done;
 	long value[1][IQK_MATRIX_REG_NUM];
@@ -889,7 +984,7 @@ struct rtl_phy {
 
 	/* Dual mac */
 	bool need_iqk;
-	struct iqk_matrix_regs iqk_matrix_regsetting[IQK_MATRIX_SETTINGS_NUM];
+	struct iqk_matrix_regs iqk_matrix[IQK_MATRIX_SETTINGS_NUM];
 
 	bool rfpi_enable;
 
@@ -902,6 +997,8 @@ struct rtl_phy {
 	/* the current Tx power level */
 	u8 cur_cck_txpwridx;
 	u8 cur_ofdm24g_txpwridx;
+	u8 cur_bw20_txpwridx;
+	u8 cur_bw40_txpwridx;
 
 	u32 rfreg_chnlval[2];
 	bool apk_done;
@@ -940,20 +1037,21 @@ struct rtl_ht_agg {
 	u8 rx_agg_state;
 };
 
+struct rssi_sta {
+	long undec_sm_pwdb;
+};
+
 struct rtl_tid_data {
 	u16 seq_number;
 	struct rtl_ht_agg agg;
 };
 
-struct rssi_sta {
-	long undec_sm_pwdb;
-};
-
 struct rtl_sta_info {
 	struct list_head list;
 	u8 ratr_index;
 	u8 wireless_mode;
 	u8 mimo_ps;
+	u8 mac_addr[ETH_ALEN];
 	struct rtl_tid_data tids[MAX_TID_COUNT];
 
 	/* just used for ap adhoc or mesh*/
@@ -1005,6 +1103,8 @@ struct rtl_mac {
 	int n_bitrates;
 
 	bool offchan_delay;
+	u8 p2p;	/*using p2p role*/
+	bool p2p_in_use;
 
 	/*filters */
 	u32 rx_conf;
@@ -1014,11 +1114,11 @@ struct rtl_mac {
 
 	bool act_scanning;
 	u8 cnt_after_linked;
+	bool skip_scan;
 
 	/* early mode */
 	/* skb wait queue */
 	struct sk_buff_head skb_waitq[MAX_TID_COUNT];
-	u8 earlymode_threshold;
 
 	/*RDG*/
 	bool rdg_en;
@@ -1042,6 +1142,7 @@ struct rtl_mac {
 	u8 retry_short;
 	u8 retry_long;
 	u16 assoc_id;
+	bool hiddenssid;
 
 	/*IBSS*/
 	int beacon_interval;
@@ -1111,10 +1212,13 @@ struct bt_coexist_8723 {
 
 struct rtl_hal {
 	struct ieee80211_hw *hw;
-	struct bt_coexist_8723 hal_coex_8723;
+	bool driver_is_goingto_unload;
 	bool up_first_time;
+	bool first_init;
 	bool being_init_adapter;
 	bool bbrf_ready;
+	bool mac_func_enable;
+	struct bt_coexist_8723 hal_coex_8723;
 
 	enum intf_type interface;
 	u16 hw_type;		/*92c or 92d or 92s and so on */
@@ -1122,6 +1226,7 @@ struct rtl_hal {
 	u8 oem_id;
 	u32 version;		/*version of chip */
 	u8 state;		/*stop 0, start 1 */
+	u8 board_type;
 
 	/*firmware */
 	u32 fwsize;
@@ -1141,6 +1246,10 @@ struct rtl_hal {
 	bool set_fwcmd_inprogress;
 	u8 current_fwcmd_io;
 
+	struct p2p_ps_offload_t p2p_ps_offload;
+	bool fw_clk_change_in_progress;
+	bool allow_sw_to_change_hwclc;
+	u8 fw_ps_state;
 	/**/
 	bool driver_going2unload;
 
@@ -1157,6 +1266,7 @@ struct rtl_hal {
 	/* just for DualMac S3S4 */
 	u8 macphyctl_reg;
 	bool earlymode_enable;
+	u8 max_earlymode_num;
 	/* Dual mac*/
 	bool during_mac0init_radiob;
 	bool during_mac1init_radioa;
@@ -1193,6 +1303,29 @@ struct rtl_security {
 	u8 *pairwise_key;
 };
 
+#define ASSOCIATE_ENTRY_NUM	33
+
+struct fast_ant_training {
+	u8	bssid[6];
+	u8	antsel_rx_keep_0;
+	u8	antsel_rx_keep_1;
+	u8	antsel_rx_keep_2;
+	u32	ant_sum[7];
+	u32	ant_cnt[7];
+	u32	ant_ave[7];
+	u8	fat_state;
+	u32	train_idx;
+	u8	antsel_a[ASSOCIATE_ENTRY_NUM];
+	u8	antsel_b[ASSOCIATE_ENTRY_NUM];
+	u8	antsel_c[ASSOCIATE_ENTRY_NUM];
+	u32	main_ant_sum[ASSOCIATE_ENTRY_NUM];
+	u32	aux_ant_sum[ASSOCIATE_ENTRY_NUM];
+	u32	main_ant_cnt[ASSOCIATE_ENTRY_NUM];
+	u32	aux_ant_cnt[ASSOCIATE_ENTRY_NUM];
+	u8	rx_idle_ant;
+	bool	becomelinked;
+};
+
 struct rtl_dm {
 	/*PHY status for Dynamic Management */
 	long entry_min_undec_sm_pwdb;
@@ -1229,9 +1362,24 @@ struct rtl_dm {
 	bool disable_tx_int;
 	char ofdm_index[2];
 	char cck_index;
+	char delta_power_index;
+	char delta_power_index_last;
+	char power_index_offset;
+
+	/*88e tx power tracking*/
+	u8	swing_idx_ofdm[2];
+	u8	swing_idx_ofdm_cur;
+	u8	swing_idx_ofdm_base;
+	bool	swing_flag_ofdm;
+	u8	swing_idx_cck;
+	u8	swing_idx_cck_cur;
+	u8	swing_idx_cck_base;
+	bool	swing_flag_cck;
 
 	/* DMSP */
 	bool supp_phymode_switch;
+
+	struct fast_ant_training fat_table;
 };
 
 #define	EFUSE_MAX_LOGICAL_SIZE			256
@@ -1264,6 +1412,9 @@ struct rtl_efuse {
 	u8 external_pa;
 
 	u8 dev_addr[6];
+	u8 wowlan_enable;
+	u8 antenna_div_cfg;
+	u8 antenna_div_type;
 
 	bool txpwr_fromeprom;
 	u8 eeprom_crystalcap;
@@ -1319,14 +1470,12 @@ struct rtl_ps_ctl {
 	bool rfchange_inprogress;
 	bool swrf_processing;
 	bool hwradiooff;
-
 	/*
 	 * just for PCIE ASPM
 	 * If it supports ASPM, Offset[560h] = 0x40,
 	 * otherwise Offset[560h] = 0x00.
 	 * */
 	bool support_aspm;
-
 	bool support_backdoor;
 
 	/*for LPS */
@@ -1341,6 +1490,7 @@ struct rtl_ps_ctl {
 	bool fw_current_inpsmode;
 	u8 reg_max_lps_awakeintvl;
 	bool report_linked;
+	bool low_power_enable;/*for 32k*/
 
 	/*for IPS */
 	bool inactiveps;
@@ -1373,6 +1523,11 @@ struct rtl_ps_ctl {
 	unsigned long last_beacon;
 	unsigned long last_action;
 	unsigned long last_slept;
+
+	/*For P2P PS */
+	struct rtl_p2p_ps_info p2p_ps_info;
+	u8 pwr_mode;
+	u8 smart_ps;
 };
 
 struct rtl_stats {
@@ -1381,7 +1536,7 @@ struct rtl_stats {
 	s8 rssi;
 	u8 signal;
 	u8 noise;
-	u16 rate;		/*in 100 kbps */
+	u8 rate;		/* hw desc rate */
 	u8 received_channel;
 	u8 control;
 	u8 mask;
@@ -1423,8 +1578,16 @@ struct rtl_stats {
 	bool packet_toself;
 	bool packet_beacon;	/*for rssi */
 	char cck_adc_pwdb[4];	/*for rx path selection */
+
+	u8 packet_report_type;
+
+	u32 macid;
+	u8 wake_match;
+	u32 bt_rx_rssi_percentage;
+	u32 macid_valid_entry[2];
 };
 
+
 struct rt_link_detect {
 	/* count for roaming */
 	u32 bcn_rx_inperiod;
@@ -1477,7 +1640,8 @@ struct rtl_tcb_desc {
 	/* early mode */
 	u8 empkt_num;
 	/* The max value by HW */
-	u32 empkt_len[5];
+	u32 empkt_len[10];
+	bool btx_enable_sw_calc_duration;
 };
 
 struct rtl_hal_ops {
@@ -1553,7 +1717,7 @@ struct rtl_hal_ops {
 	void (*allow_all_destaddr)(struct ieee80211_hw *hw,
 		bool allow_all_da, bool write_into_reg);
 	void (*linked_set_reg) (struct ieee80211_hw *hw);
-	void (*check_switch_to_dmdp) (struct ieee80211_hw *hw);
+	void (*chk_switch_dmdp) (struct ieee80211_hw *hw);
 	void (*dualmac_easy_concurrent) (struct ieee80211_hw *hw);
 	void (*dualmac_switch_to_dmdp) (struct ieee80211_hw *hw);
 	bool (*phy_rf6052_config) (struct ieee80211_hw *hw);
@@ -1662,6 +1826,8 @@ struct rtl_locks {
 	/*spin lock */
 	spinlock_t ips_lock;
 	spinlock_t irq_th_lock;
+	spinlock_t irq_pci_lock;
+	spinlock_t tx_lock;
 	spinlock_t h2c_lock;
 	spinlock_t rf_ps_lock;
 	spinlock_t rf_lock;
@@ -1670,6 +1836,9 @@ struct rtl_locks {
 	spinlock_t entry_list_lock;
 	spinlock_t usb_lock;
 
+	/*FW clock change */
+	spinlock_t fw_ps_lock;
+
 	/*Dual mac*/
 	spinlock_t cck_and_rw_pagea_lock;
 
@@ -1683,7 +1852,8 @@ struct rtl_works {
 	/*timer */
 	struct timer_list watchdog_timer;
 	struct timer_list dualmac_easyconcurrent_retrytimer;
-
+	struct timer_list fw_clockoff_timer;
+	struct timer_list fast_antenna_training_timer;
 	/*task */
 	struct tasklet_struct irq_tasklet;
 	struct tasklet_struct irq_prepare_bcn_tasklet;
@@ -1696,8 +1866,9 @@ struct rtl_works {
 	/* For SW LPS */
 	struct delayed_work ps_work;
 	struct delayed_work ps_rfon_wq;
+	struct delayed_work fwevt_wq;
 
-	struct work_struct lps_leave_work;
+	struct work_struct lps_change_work;
 };
 
 struct rtl_debug {
@@ -1767,10 +1938,12 @@ struct dig_t {
 	char back_val;
 	char back_range_max;
 	char back_range_min;
-	u8 rx_gain_range_max;
-	u8 rx_gain_range_min;
+	u8 rx_gain_max;
+	u8 rx_gain_min;
 	u8 min_undec_pwdb_for_dm;
 	u8 rssi_val_min;
+	u8 pre_cck_cca_thres;
+	u8 cur_cck_cca_thres;
 	u8 pre_cck_pd_state;
 	u8 cur_cck_pd_state;
 	u8 pre_cck_fa_state;
@@ -1792,6 +1965,13 @@ struct dig_t {
 	u8 backoff_enable_flag;
 	char backoffval_range_max;
 	char backoffval_range_min;
+	u8 dig_min_0;
+	u8 dig_min_1;
+	bool media_connect_0;
+	bool media_connect_1;
+
+	u32 antdiv_rssi_max;
+	u32 rssi_max;
 };
 
 struct rtl_global_var {
@@ -1802,6 +1982,7 @@ struct rtl_global_var {
 };
 
 struct rtl_priv {
+	struct ieee80211_hw *hw;
 	struct completion firmware_loading_complete;
 	struct list_head list;
 	struct rtl_priv *buddy_priv;
@@ -1866,6 +2047,7 @@ struct rtl_priv {
 			bool bt_operation_on;
 		};
 	};
+	bool enter_ps;	/* true when entering PS */
 
 	/*This must be the last item so
 	   that it points to the data allocated
@@ -2127,9 +2309,7 @@ value to host byte ordering.*/
 #define WLAN_FC_GET_TYPE(fc)	(le16_to_cpu(fc) & IEEE80211_FCTL_FTYPE)
 #define WLAN_FC_GET_STYPE(fc)	(le16_to_cpu(fc) & IEEE80211_FCTL_STYPE)
 #define WLAN_FC_MORE_DATA(fc)	(le16_to_cpu(fc) & IEEE80211_FCTL_MOREDATA)
-#define SEQ_TO_SN(seq)		(((seq) & IEEE80211_SCTL_SEQ) >> 4)
-#define SN_TO_SEQ(ssn)		(((ssn) << 4) & IEEE80211_SCTL_SEQ)
-#define MAX_SN			((IEEE80211_SCTL_SEQ) >> 4)
+#define rtl_dm(rtlpriv)		(&((rtlpriv)->dm))
 
 #define	RT_RF_OFF_LEVL_ASPM		BIT(0)	/*PCI ASPM */
 #define	RT_RF_OFF_LEVL_CLK_REQ		BIT(1)	/*PCI clock request */
diff --git a/drivers/net/wireless/ti/wl1251/sdio.c b/drivers/net/wireless/ti/wl1251/sdio.c
index e57ee48..e2b3d9c 100644
--- a/drivers/net/wireless/ti/wl1251/sdio.c
+++ b/drivers/net/wireless/ti/wl1251/sdio.c
@@ -186,8 +186,10 @@ static int wl1251_sdio_set_power(struct wl1251 *wl, bool enable)
 			wl->set_power(true);
 
 		ret = pm_runtime_get_sync(&func->dev);
-		if (ret < 0)
+		if (ret < 0) {
+			pm_runtime_put_sync(&func->dev);
 			goto out;
+		}
 
 		sdio_claim_host(func);
 		sdio_enable_func(func);
diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c
index 09694e3..1c627da 100644
--- a/drivers/net/wireless/ti/wl12xx/main.c
+++ b/drivers/net/wireless/ti/wl12xx/main.c
@@ -723,6 +723,7 @@ static int wl12xx_identify_chip(struct wl1271 *wl)
 	wl->sched_scan_templ_id_2_4 = CMD_TEMPL_CFG_PROBE_REQ_2_4;
 	wl->sched_scan_templ_id_5 = CMD_TEMPL_CFG_PROBE_REQ_5;
 	wl->max_channels_5 = WL12XX_MAX_CHANNELS_5GHZ;
+	wl->ba_rx_session_count_max = WL12XX_RX_BA_MAX_SESSIONS;
 out:
 	return ret;
 }
diff --git a/drivers/net/wireless/ti/wl12xx/wl12xx.h b/drivers/net/wireless/ti/wl12xx/wl12xx.h
index d455285..222d035 100644
--- a/drivers/net/wireless/ti/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/ti/wl12xx/wl12xx.h
@@ -63,6 +63,8 @@
 
 #define WL12XX_NUM_MAC_ADDRESSES 2
 
+#define WL12XX_RX_BA_MAX_SESSIONS 3
+
 struct wl127x_rx_mem_pool_addr {
 	u32 addr;
 	u32 addr_extra;
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index da3ef1b..9fa692d 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -678,6 +678,7 @@ static int wl18xx_identify_chip(struct wl1271 *wl)
 	wl->sched_scan_templ_id_2_4 = CMD_TEMPL_PROBE_REQ_2_4_PERIODIC;
 	wl->sched_scan_templ_id_5 = CMD_TEMPL_PROBE_REQ_5_PERIODIC;
 	wl->max_channels_5 = WL18XX_MAX_CHANNELS_5GHZ;
+	wl->ba_rx_session_count_max = WL18XX_RX_BA_MAX_SESSIONS;
 out:
 	return ret;
 }
@@ -1144,6 +1145,7 @@ static u32 wl18xx_ap_get_mimo_wide_rate_mask(struct wl1271 *wl,
 static int wl18xx_get_pg_ver(struct wl1271 *wl, s8 *ver)
 {
 	u32 fuse;
+	s8 rom = 0, metal = 0, pg_ver = 0, rdl_ver = 0;
 	int ret;
 
 	ret = wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]);
@@ -1154,8 +1156,29 @@ static int wl18xx_get_pg_ver(struct wl1271 *wl, s8 *ver)
 	if (ret < 0)
 		goto out;
 
+	pg_ver = (fuse & WL18XX_PG_VER_MASK) >> WL18XX_PG_VER_OFFSET;
+	rom = (fuse & WL18XX_ROM_VER_MASK) >> WL18XX_ROM_VER_OFFSET;
+
+	if (rom <= 0xE)
+		metal = (fuse & WL18XX_METAL_VER_MASK) >>
+			WL18XX_METAL_VER_OFFSET;
+	else
+		metal = (fuse & WL18XX_NEW_METAL_VER_MASK) >>
+			WL18XX_NEW_METAL_VER_OFFSET;
+
+	ret = wlcore_read32(wl, WL18XX_REG_FUSE_DATA_2_3, &fuse);
+	if (ret < 0)
+		goto out;
+
+	rdl_ver = (fuse & WL18XX_RDL_VER_MASK) >> WL18XX_RDL_VER_OFFSET;
+	if (rdl_ver > RDL_MAX)
+		rdl_ver = RDL_NONE;
+
+	wl1271_info("wl18xx HW: RDL %d, %s, PG %x.%x (ROM %x)",
+		    rdl_ver, rdl_names[rdl_ver], pg_ver, metal, rom);
+
 	if (ver)
-		*ver = (fuse & WL18XX_PG_VER_MASK) >> WL18XX_PG_VER_OFFSET;
+		*ver = pg_ver;
 
 	ret = wlcore_set_partition(wl, &wl->ptable[PART_BOOT]);
 
diff --git a/drivers/net/wireless/ti/wl18xx/reg.h b/drivers/net/wireless/ti/wl18xx/reg.h
index 937b71d..6306e04 100644
--- a/drivers/net/wireless/ti/wl18xx/reg.h
+++ b/drivers/net/wireless/ti/wl18xx/reg.h
@@ -131,6 +131,16 @@
 #define WL18XX_REG_FUSE_DATA_1_3	0xA0260C
 #define WL18XX_PG_VER_MASK		0x70
 #define WL18XX_PG_VER_OFFSET		4
+#define WL18XX_ROM_VER_MASK		0x3
+#define WL18XX_ROM_VER_OFFSET		0
+#define WL18XX_METAL_VER_MASK		0xC
+#define WL18XX_METAL_VER_OFFSET		2
+#define WL18XX_NEW_METAL_VER_MASK	0x180
+#define WL18XX_NEW_METAL_VER_OFFSET	7
+
+#define WL18XX_REG_FUSE_DATA_2_3	0xA02614
+#define WL18XX_RDL_VER_MASK		0x1f00
+#define WL18XX_RDL_VER_OFFSET		8
 
 #define WL18XX_REG_FUSE_BD_ADDR_1	0xA02602
 #define WL18XX_REG_FUSE_BD_ADDR_2	0xA02606
@@ -188,4 +198,23 @@ enum {
 	NUM_BOARD_TYPES,
 };
 
+enum {
+	RDL_NONE	= 0,
+	RDL_1_HP	= 1,
+	RDL_2_SP	= 2,
+	RDL_3_HP	= 3,
+	RDL_4_SP	= 4,
+
+	_RDL_LAST,
+	RDL_MAX = _RDL_LAST - 1,
+};
+
+static const char * const rdl_names[] = {
+	[RDL_NONE]	= "",
+	[RDL_1_HP]	= "1853 SISO",
+	[RDL_2_SP]	= "1857 MIMO",
+	[RDL_3_HP]	= "1893 SISO",
+	[RDL_4_SP]	= "1897 MIMO",
+};
+
 #endif /* __REG_H__ */
diff --git a/drivers/net/wireless/ti/wl18xx/wl18xx.h b/drivers/net/wireless/ti/wl18xx/wl18xx.h
index b6739e7..9204e07 100644
--- a/drivers/net/wireless/ti/wl18xx/wl18xx.h
+++ b/drivers/net/wireless/ti/wl18xx/wl18xx.h
@@ -29,7 +29,7 @@
 #define WL18XX_IFTYPE_VER	5
 #define WL18XX_MAJOR_VER	WLCORE_FW_VER_IGNORE
 #define WL18XX_SUBTYPE_VER	WLCORE_FW_VER_IGNORE
-#define WL18XX_MINOR_VER	28
+#define WL18XX_MINOR_VER	39
 
 #define WL18XX_CMD_MAX_SIZE          740
 
@@ -40,6 +40,8 @@
 
 #define WL18XX_NUM_MAC_ADDRESSES 3
 
+#define WL18XX_RX_BA_MAX_SESSIONS 5
+
 struct wl18xx_priv {
 	/* buffer for sending commands to FW */
 	u8 cmd_buf[WL18XX_CMD_MAX_SIZE];
diff --git a/drivers/net/wireless/ti/wlcore/acx.c b/drivers/net/wireless/ti/wlcore/acx.c
index c796543..7a970cd 100644
--- a/drivers/net/wireless/ti/wlcore/acx.c
+++ b/drivers/net/wireless/ti/wlcore/acx.c
@@ -1736,6 +1736,35 @@ out:
 
 }
 
+int wlcore_acx_average_rssi(struct wl1271 *wl, struct wl12xx_vif *wlvif,
+			    s8 *avg_rssi)
+{
+	struct acx_roaming_stats *acx;
+	int ret = 0;
+
+	wl1271_debug(DEBUG_ACX, "acx roaming statistics");
+
+	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+	if (!acx) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	acx->role_id = wlvif->role_id;
+	ret = wl1271_cmd_interrogate(wl, ACX_ROAMING_STATISTICS_TBL,
+				     acx, sizeof(*acx));
+	if (ret	< 0) {
+		wl1271_warning("acx roaming statistics failed: %d", ret);
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	*avg_rssi = acx->rssi_beacon;
+out:
+	kfree(acx);
+	return ret;
+}
+
 #ifdef CONFIG_PM
 /* Set the global behaviour of RX filters - On/Off + default action */
 int wl1271_acx_default_rx_filter_enable(struct wl1271 *wl, bool enable,
diff --git a/drivers/net/wireless/ti/wlcore/acx.h b/drivers/net/wireless/ti/wlcore/acx.h
index 126536c..6dcfad9 100644
--- a/drivers/net/wireless/ti/wlcore/acx.h
+++ b/drivers/net/wireless/ti/wlcore/acx.h
@@ -728,8 +728,6 @@ struct wl1271_acx_ht_information {
 	u8 padding[2];
 } __packed;
 
-#define RX_BA_MAX_SESSIONS 3
-
 struct wl1271_acx_ba_initiator_policy {
 	struct acx_header header;
 
@@ -955,6 +953,18 @@ struct acx_rx_filter_cfg {
 	u8 fields[0];
 } __packed;
 
+struct acx_roaming_stats {
+	struct acx_header header;
+
+	u8	role_id;
+	u8	pad[3];
+	u32	missed_beacons;
+	u8	snr_data;
+	u8	snr_bacon;
+	s8	rssi_data;
+	s8	rssi_beacon;
+} __packed;
+
 enum {
 	ACX_WAKE_UP_CONDITIONS           = 0x0000,
 	ACX_MEM_CFG                      = 0x0001,
@@ -1112,6 +1122,8 @@ int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr);
 int wl1271_acx_fm_coex(struct wl1271 *wl);
 int wl12xx_acx_set_rate_mgmt_params(struct wl1271 *wl);
 int wl12xx_acx_config_hangover(struct wl1271 *wl);
+int wlcore_acx_average_rssi(struct wl1271 *wl, struct wl12xx_vif *wlvif,
+			    s8 *avg_rssi);
 
 #ifdef CONFIG_PM
 int wl1271_acx_default_rx_filter_enable(struct wl1271 *wl, bool enable,
diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c
index 6331f9e..c9e0607 100644
--- a/drivers/net/wireless/ti/wlcore/cmd.c
+++ b/drivers/net/wireless/ti/wlcore/cmd.c
@@ -327,6 +327,14 @@ int wl12xx_allocate_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid)
 	wl->links[link].prev_freed_pkts =
 			wl->fw_status_2->counters.tx_lnk_free_pkts[link];
 	wl->links[link].wlvif = wlvif;
+
+	/*
+	 * Take saved value for total freed packets from wlvif, in case this is
+	 * recovery/resume
+	 */
+	if (wlvif->bss_type != BSS_TYPE_AP_BSS)
+		wl->links[link].total_freed_pkts = wlvif->total_freed_pkts;
+
 	*hlid = link;
 
 	wl->active_link_count++;
@@ -358,6 +366,26 @@ void wl12xx_free_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid)
 	wl1271_tx_reset_link_queues(wl, *hlid);
 	wl->links[*hlid].wlvif = NULL;
 
+	if (wlvif->bss_type == BSS_TYPE_STA_BSS ||
+	    (wlvif->bss_type == BSS_TYPE_AP_BSS &&
+	     *hlid == wlvif->ap.bcast_hlid)) {
+		/*
+		 * save the total freed packets in the wlvif, in case this is
+		 * recovery or suspend
+		 */
+		wlvif->total_freed_pkts = wl->links[*hlid].total_freed_pkts;
+
+		/*
+		 * increment the initial seq number on recovery to account for
+		 * transmitted packets that we haven't yet got in the FW status
+		 */
+		if (test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags))
+			wlvif->total_freed_pkts +=
+					WL1271_TX_SQN_POST_RECOVERY_PADDING;
+	}
+
+	wl->links[*hlid].total_freed_pkts = 0;
+
 	*hlid = WL12XX_INVALID_LINK_ID;
 	wl->active_link_count--;
 	WARN_ON_ONCE(wl->active_link_count < 0);
@@ -609,6 +637,10 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif)
 	if (ret < 0)
 		goto out_free_global;
 
+	/* use the previous security seq, if this is a recovery/resume */
+	wl->links[wlvif->ap.bcast_hlid].total_freed_pkts =
+						wlvif->total_freed_pkts;
+
 	cmd->role_id = wlvif->role_id;
 	cmd->ap.aging_period = cpu_to_le16(wl->conf.tx.ap_aging_period);
 	cmd->ap.bss_index = WL1271_AP_BSS_INDEX;
diff --git a/drivers/net/wireless/ti/wlcore/debug.h b/drivers/net/wireless/ti/wlcore/debug.h
index db4bf5a..0420bd4 100644
--- a/drivers/net/wireless/ti/wlcore/debug.h
+++ b/drivers/net/wireless/ti/wlcore/debug.h
@@ -89,25 +89,24 @@ extern u32 wl12xx_debug_level;
 	} while (0)
 #endif
 
-/* TODO: use pr_debug_hex_dump when it becomes available */
-#define wl1271_dump(level, prefix, buf, len)	\
-	do { \
-		if (level & wl12xx_debug_level) \
-			print_hex_dump(KERN_DEBUG, DRIVER_PREFIX prefix, \
-				       DUMP_PREFIX_OFFSET, 16, 1,	\
-				       buf,				\
-				       min_t(size_t, len, DEBUG_DUMP_LIMIT), \
-				       0);				\
+#define wl1271_dump(level, prefix, buf, len)				      \
+	do {								      \
+		if (level & wl12xx_debug_level)				      \
+			print_hex_dump_debug(DRIVER_PREFIX prefix,	      \
+					DUMP_PREFIX_OFFSET, 16, 1,	      \
+					buf,				      \
+					min_t(size_t, len, DEBUG_DUMP_LIMIT), \
+					0);				      \
 	} while (0)
 
-#define wl1271_dump_ascii(level, prefix, buf, len)	\
-	do { \
-		if (level & wl12xx_debug_level) \
-			print_hex_dump(KERN_DEBUG, DRIVER_PREFIX prefix, \
-				       DUMP_PREFIX_OFFSET, 16, 1,	\
-				       buf,				\
-				       min_t(size_t, len, DEBUG_DUMP_LIMIT), \
-				       true);				\
+#define wl1271_dump_ascii(level, prefix, buf, len)			      \
+	do {								      \
+		if (level & wl12xx_debug_level)				      \
+			print_hex_dump_debug(DRIVER_PREFIX prefix,	      \
+					DUMP_PREFIX_OFFSET, 16, 1,	      \
+					buf,				      \
+					min_t(size_t, len, DEBUG_DUMP_LIMIT), \
+					true);				      \
 	} while (0)
 
 #endif /* __DEBUG_H__ */
diff --git a/drivers/net/wireless/ti/wlcore/debugfs.c b/drivers/net/wireless/ti/wlcore/debugfs.c
index e70a7c8..c3e1f79 100644
--- a/drivers/net/wireless/ti/wlcore/debugfs.c
+++ b/drivers/net/wireless/ti/wlcore/debugfs.c
@@ -598,8 +598,7 @@ static ssize_t vifs_state_read(struct file *file, char __user *user_buf,
 		VIF_STATE_PRINT_INT(last_rssi_event);
 		VIF_STATE_PRINT_INT(ba_support);
 		VIF_STATE_PRINT_INT(ba_allowed);
-		VIF_STATE_PRINT_LLHEX(tx_security_seq);
-		VIF_STATE_PRINT_INT(tx_security_last_seq_lsb);
+		VIF_STATE_PRINT_LLHEX(total_freed_pkts);
 	}
 
 #undef VIF_STATE_PRINT_INT
diff --git a/drivers/net/wireless/ti/wlcore/event.c b/drivers/net/wireless/ti/wlcore/event.c
index 70f289a..67f6168 100644
--- a/drivers/net/wireless/ti/wlcore/event.c
+++ b/drivers/net/wireless/ti/wlcore/event.c
@@ -237,6 +237,14 @@ void wlcore_event_beacon_loss(struct wl1271 *wl, unsigned long roles_bitmap)
 		    !test_bit(wlvif->role_id , &roles_bitmap))
 			continue;
 
+		vif = wl12xx_wlvif_to_vif(wlvif);
+
+		/* don't attempt roaming in case of p2p */
+		if (wlvif->p2p) {
+			ieee80211_connection_loss(vif);
+			continue;
+		}
+
 		/*
 		 * if the work is already queued, it should take place.
 		 * We don't want to delay the connection loss
@@ -246,7 +254,6 @@ void wlcore_event_beacon_loss(struct wl1271 *wl, unsigned long roles_bitmap)
 					     &wlvif->connection_loss_work,
 					     msecs_to_jiffies(delay));
 
-		vif = wl12xx_wlvif_to_vif(wlvif);
 		ieee80211_cqm_rssi_notify(
 				vif,
 				NL80211_CQM_RSSI_BEACON_LOSS_EVENT,
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index 2c2ff3e..d10954c 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -108,8 +108,7 @@ static void wl1271_reg_notify(struct wiphy *wiphy,
 
 	}
 
-	if (likely(wl->state == WLCORE_STATE_ON))
-		wlcore_regdomain_config(wl);
+	wlcore_regdomain_config(wl);
 }
 
 static int wl1271_set_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif,
@@ -332,10 +331,9 @@ static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl,
 					struct wl12xx_vif *wlvif,
 					u8 hlid, u8 tx_pkts)
 {
-	bool fw_ps, single_link;
+	bool fw_ps;
 
 	fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);
-	single_link = (wl->active_link_count == 1);
 
 	/*
 	 * Wake up from high level PS if the STA is asleep with too little
@@ -348,8 +346,13 @@ static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl,
 	 * Start high-level PS if the STA is asleep with enough blocks in FW.
 	 * Make an exception if this is the only connected link. In this
 	 * case FW-memory congestion is less of a problem.
+	 * Note that a single connected STA means 3 active links, since we must
+	 * account for the global and broadcast AP links. The "fw_ps" check
+	 * assures us the third link is a STA connected to the AP. Otherwise
+	 * the FW would not set the PSM bit.
 	 */
-	else if (!single_link && fw_ps && tx_pkts >= WL1271_PS_STA_MAX_PACKETS)
+	else if (wl->active_link_count > 3 && fw_ps &&
+		 tx_pkts >= WL1271_PS_STA_MAX_PACKETS)
 		wl12xx_ps_link_start(wl, wlvif, hlid, true);
 }
 
@@ -414,13 +417,21 @@ static int wlcore_fw_status(struct wl1271 *wl,
 
 
 	for_each_set_bit(i, wl->links_map, WL12XX_MAX_LINKS) {
+		u8 diff;
 		lnk = &wl->links[i];
+
 		/* prevent wrap-around in freed-packets counter */
-		lnk->allocated_pkts -=
-			(status_2->counters.tx_lnk_free_pkts[i] -
-			 lnk->prev_freed_pkts) & 0xff;
+		diff = (status_2->counters.tx_lnk_free_pkts[i] -
+		       lnk->prev_freed_pkts) & 0xff;
+
+		if (diff == 0)
+			continue;
 
+		lnk->allocated_pkts -= diff;
 		lnk->prev_freed_pkts = status_2->counters.tx_lnk_free_pkts[i];
+
+		/* accumulate the prev_freed_pkts counter */
+		lnk->total_freed_pkts += diff;
 	}
 
 	/* prevent wrap-around in total blocks counter */
@@ -640,6 +651,25 @@ static irqreturn_t wlcore_irq(int irq, void *cookie)
 	unsigned long flags;
 	struct wl1271 *wl = cookie;
 
+	/* complete the ELP completion */
+	spin_lock_irqsave(&wl->wl_lock, flags);
+	set_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags);
+	if (wl->elp_compl) {
+		complete(wl->elp_compl);
+		wl->elp_compl = NULL;
+	}
+
+	if (test_bit(WL1271_FLAG_SUSPENDED, &wl->flags)) {
+		/* don't enqueue a work right now. mark it as pending */
+		set_bit(WL1271_FLAG_PENDING_WORK, &wl->flags);
+		wl1271_debug(DEBUG_IRQ, "should not enqueue work");
+		disable_irq_nosync(wl->irq);
+		pm_wakeup_event(wl->dev, 0);
+		spin_unlock_irqrestore(&wl->wl_lock, flags);
+		return IRQ_HANDLED;
+	}
+	spin_unlock_irqrestore(&wl->wl_lock, flags);
+
 	/* TX might be handled here, avoid redundant work */
 	set_bit(WL1271_FLAG_TX_PENDING, &wl->flags);
 	cancel_work_sync(&wl->tx_work);
@@ -919,18 +949,6 @@ static void wl1271_recovery_work(struct work_struct *work)
 		goto out_unlock;
 	}
 
-	/*
-	 * Advance security sequence number to overcome potential progress
-	 * in the firmware during recovery. This doens't hurt if the network is
-	 * not encrypted.
-	 */
-	wl12xx_for_each_wlvif(wl, wlvif) {
-		if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags) ||
-		    test_bit(WLVIF_FLAG_AP_STARTED, &wlvif->flags))
-			wlvif->tx_security_seq +=
-				WL1271_TX_SQN_POST_RECOVERY_PADDING;
-	}
-
 	/* Prevent spurious TX during FW restart */
 	wlcore_stop_queues(wl, WLCORE_QUEUE_STOP_REASON_FW_RESTART);
 
@@ -2523,6 +2541,8 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
 		wl1271_ps_elp_sleep(wl);
 	}
 deinit:
+	wl12xx_tx_reset_wlvif(wl, wlvif);
+
 	/* clear all hlids (except system_hlid) */
 	wlvif->dev_hlid = WL12XX_INVALID_LINK_ID;
 
@@ -2546,7 +2566,6 @@ deinit:
 
 	dev_kfree_skb(wlvif->probereq);
 	wlvif->probereq = NULL;
-	wl12xx_tx_reset_wlvif(wl, wlvif);
 	if (wl->last_wlvif == wlvif)
 		wl->last_wlvif = NULL;
 	list_del(&wlvif->list);
@@ -2860,10 +2879,6 @@ static int wlcore_unset_assoc(struct wl1271 *wl, struct wl12xx_vif *wlvif)
 				     wlvif->sta.klv_template_id,
 				     ACX_KEEP_ALIVE_TPL_INVALID);
 
-	/* reset TX security counters on a clean disconnect */
-	wlvif->tx_security_last_seq_lsb = 0;
-	wlvif->tx_security_seq = 0;
-
 	return 0;
 }
 
@@ -3262,6 +3277,7 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
 	u32 tx_seq_32 = 0;
 	u16 tx_seq_16 = 0;
 	u8 key_type;
+	u8 hlid;
 
 	wl1271_debug(DEBUG_MAC80211, "mac80211 set key");
 
@@ -3271,6 +3287,22 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
 		     key_conf->keylen, key_conf->flags);
 	wl1271_dump(DEBUG_CRYPT, "KEY: ", key_conf->key, key_conf->keylen);
 
+	if (wlvif->bss_type == BSS_TYPE_AP_BSS)
+		if (sta) {
+			struct wl1271_station *wl_sta = (void *)sta->drv_priv;
+			hlid = wl_sta->hlid;
+		} else {
+			hlid = wlvif->ap.bcast_hlid;
+		}
+	else
+		hlid = wlvif->sta.hlid;
+
+	if (hlid != WL12XX_INVALID_LINK_ID) {
+		u64 tx_seq = wl->links[hlid].total_freed_pkts;
+		tx_seq_32 = WL1271_TX_SECURITY_HI32(tx_seq);
+		tx_seq_16 = WL1271_TX_SECURITY_LO16(tx_seq);
+	}
+
 	switch (key_conf->cipher) {
 	case WLAN_CIPHER_SUITE_WEP40:
 	case WLAN_CIPHER_SUITE_WEP104:
@@ -3280,22 +3312,14 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
 		break;
 	case WLAN_CIPHER_SUITE_TKIP:
 		key_type = KEY_TKIP;
-
 		key_conf->hw_key_idx = key_conf->keyidx;
-		tx_seq_32 = WL1271_TX_SECURITY_HI32(wlvif->tx_security_seq);
-		tx_seq_16 = WL1271_TX_SECURITY_LO16(wlvif->tx_security_seq);
 		break;
 	case WLAN_CIPHER_SUITE_CCMP:
 		key_type = KEY_AES;
-
 		key_conf->flags |= IEEE80211_KEY_FLAG_PUT_IV_SPACE;
-		tx_seq_32 = WL1271_TX_SECURITY_HI32(wlvif->tx_security_seq);
-		tx_seq_16 = WL1271_TX_SECURITY_LO16(wlvif->tx_security_seq);
 		break;
 	case WL1271_CIPHER_SUITE_GEM:
 		key_type = KEY_GEM;
-		tx_seq_32 = WL1271_TX_SECURITY_HI32(wlvif->tx_security_seq);
-		tx_seq_16 = WL1271_TX_SECURITY_LO16(wlvif->tx_security_seq);
 		break;
 	default:
 		wl1271_error("Unknown key algo 0x%x", key_conf->cipher);
@@ -3358,6 +3382,10 @@ void wlcore_regdomain_config(struct wl1271 *wl)
 		return;
 
 	mutex_lock(&wl->mutex);
+
+	if (unlikely(wl->state != WLCORE_STATE_ON))
+		goto out;
+
 	ret = wl1271_ps_elp_wakeup(wl);
 	if (ret < 0)
 		goto out;
@@ -4499,6 +4527,9 @@ static int wl1271_allocate_sta(struct wl1271 *wl,
 		return -EBUSY;
 	}
 
+	/* use the previous security seq, if this is a recovery/resume */
+	wl->links[wl_sta->hlid].total_freed_pkts = wl_sta->total_freed_pkts;
+
 	set_bit(wl_sta->hlid, wlvif->ap.sta_hlid_map);
 	memcpy(wl->links[wl_sta->hlid].addr, sta->addr, ETH_ALEN);
 	wl->active_sta_count++;
@@ -4507,12 +4538,37 @@ static int wl1271_allocate_sta(struct wl1271 *wl,
 
 void wl1271_free_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid)
 {
+	struct wl1271_station *wl_sta;
+	struct ieee80211_sta *sta;
+	struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
+
 	if (!test_bit(hlid, wlvif->ap.sta_hlid_map))
 		return;
 
 	clear_bit(hlid, wlvif->ap.sta_hlid_map);
 	__clear_bit(hlid, &wl->ap_ps_map);
 	__clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);
+
+	/*
+	 * save the last used PN in the private part of iee80211_sta,
+	 * in case of recovery/suspend
+	 */
+	rcu_read_lock();
+	sta = ieee80211_find_sta(vif, wl->links[hlid].addr);
+	if (sta) {
+		wl_sta = (void *)sta->drv_priv;
+		wl_sta->total_freed_pkts = wl->links[hlid].total_freed_pkts;
+
+		/*
+		 * increment the initial seq number on recovery to account for
+		 * transmitted packets that we haven't yet got in the FW status
+		 */
+		if (test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags))
+			wl_sta->total_freed_pkts +=
+					WL1271_TX_SQN_POST_RECOVERY_PADDING;
+	}
+	rcu_read_unlock();
+
 	wl12xx_free_link(wl, wlvif, &hlid);
 	wl->active_sta_count--;
 
@@ -4616,13 +4672,11 @@ static int wl12xx_update_sta_state(struct wl1271 *wl,
 				   enum ieee80211_sta_state new_state)
 {
 	struct wl1271_station *wl_sta;
-	u8 hlid;
 	bool is_ap = wlvif->bss_type == BSS_TYPE_AP_BSS;
 	bool is_sta = wlvif->bss_type == BSS_TYPE_STA_BSS;
 	int ret;
 
 	wl_sta = (struct wl1271_station *)sta->drv_priv;
-	hlid = wl_sta->hlid;
 
 	/* Add station (AP mode) */
 	if (is_ap &&
@@ -4648,12 +4702,12 @@ static int wl12xx_update_sta_state(struct wl1271 *wl,
 	/* Authorize station (AP mode) */
 	if (is_ap &&
 	    new_state == IEEE80211_STA_AUTHORIZED) {
-		ret = wl12xx_cmd_set_peer_state(wl, wlvif, hlid);
+		ret = wl12xx_cmd_set_peer_state(wl, wlvif, wl_sta->hlid);
 		if (ret < 0)
 			return ret;
 
 		ret = wl1271_acx_set_ht_capabilities(wl, &sta->ht_cap, true,
-						     hlid);
+						     wl_sta->hlid);
 		if (ret)
 			return ret;
 
@@ -4784,7 +4838,7 @@ static int wl1271_op_ampdu_action(struct ieee80211_hw *hw,
 			break;
 		}
 
-		if (wl->ba_rx_session_count >= RX_BA_MAX_SESSIONS) {
+		if (wl->ba_rx_session_count >= wl->ba_rx_session_count_max) {
 			ret = -EBUSY;
 			wl1271_error("exceeded max RX BA sessions");
 			break;
@@ -4946,7 +5000,7 @@ out:
 	mutex_unlock(&wl->mutex);
 }
 
-static void wlcore_op_flush(struct ieee80211_hw *hw, bool drop)
+static void wlcore_op_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
 {
 	struct wl1271 *wl = hw->priv;
 
@@ -4956,7 +5010,8 @@ static void wlcore_op_flush(struct ieee80211_hw *hw, bool drop)
 static int wlcore_op_remain_on_channel(struct ieee80211_hw *hw,
 				       struct ieee80211_vif *vif,
 				       struct ieee80211_channel *chan,
-				       int duration)
+				       int duration,
+				       enum ieee80211_roc_type type)
 {
 	struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
 	struct wl1271 *wl = hw->priv;
@@ -5091,6 +5146,39 @@ static void wlcore_op_sta_rc_update(struct ieee80211_hw *hw,
 	wlcore_hw_sta_rc_update(wl, wlvif, sta, changed);
 }
 
+static int wlcore_op_get_rssi(struct ieee80211_hw *hw,
+			       struct ieee80211_vif *vif,
+			       struct ieee80211_sta *sta,
+			       s8 *rssi_dbm)
+{
+	struct wl1271 *wl = hw->priv;
+	struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
+	int ret = 0;
+
+	wl1271_debug(DEBUG_MAC80211, "mac80211 get_rssi");
+
+	mutex_lock(&wl->mutex);
+
+	if (unlikely(wl->state != WLCORE_STATE_ON))
+		goto out;
+
+	ret = wl1271_ps_elp_wakeup(wl);
+	if (ret < 0)
+		goto out_sleep;
+
+	ret = wlcore_acx_average_rssi(wl, wlvif, rssi_dbm);
+	if (ret < 0)
+		goto out_sleep;
+
+out_sleep:
+	wl1271_ps_elp_sleep(wl);
+
+out:
+	mutex_unlock(&wl->mutex);
+
+	return ret;
+}
+
 static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw)
 {
 	struct wl1271 *wl = hw->priv;
@@ -5290,6 +5378,7 @@ static const struct ieee80211_ops wl1271_ops = {
 	.assign_vif_chanctx = wlcore_op_assign_vif_chanctx,
 	.unassign_vif_chanctx = wlcore_op_unassign_vif_chanctx,
 	.sta_rc_update = wlcore_op_sta_rc_update,
+	.get_rssi = wlcore_op_get_rssi,
 	CFG80211_TESTMODE_CMD(wl1271_tm_cmd)
 };
 
@@ -5929,35 +6018,6 @@ int wlcore_free_hw(struct wl1271 *wl)
 }
 EXPORT_SYMBOL_GPL(wlcore_free_hw);
 
-static irqreturn_t wl12xx_hardirq(int irq, void *cookie)
-{
-	struct wl1271 *wl = cookie;
-	unsigned long flags;
-
-	wl1271_debug(DEBUG_IRQ, "IRQ");
-
-	/* complete the ELP completion */
-	spin_lock_irqsave(&wl->wl_lock, flags);
-	set_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags);
-	if (wl->elp_compl) {
-		complete(wl->elp_compl);
-		wl->elp_compl = NULL;
-	}
-
-	if (test_bit(WL1271_FLAG_SUSPENDED, &wl->flags)) {
-		/* don't enqueue a work right now. mark it as pending */
-		set_bit(WL1271_FLAG_PENDING_WORK, &wl->flags);
-		wl1271_debug(DEBUG_IRQ, "should not enqueue work");
-		disable_irq_nosync(wl->irq);
-		pm_wakeup_event(wl->dev, 0);
-		spin_unlock_irqrestore(&wl->wl_lock, flags);
-		return IRQ_HANDLED;
-	}
-	spin_unlock_irqrestore(&wl->wl_lock, flags);
-
-	return IRQ_WAKE_THREAD;
-}
-
 static void wlcore_nvs_cb(const struct firmware *fw, void *context)
 {
 	struct wl1271 *wl = context;
@@ -5999,9 +6059,8 @@ static void wlcore_nvs_cb(const struct firmware *fw, void *context)
 	else
 		irqflags = IRQF_TRIGGER_HIGH | IRQF_ONESHOT;
 
-	ret = request_threaded_irq(wl->irq, wl12xx_hardirq, wlcore_irq,
-				   irqflags,
-				   pdev->name, wl);
+	ret = request_threaded_irq(wl->irq, NULL, wlcore_irq,
+				   irqflags, pdev->name, wl);
 	if (ret < 0) {
 		wl1271_error("request_irq() failed: %d", ret);
 		goto out_free_nvs;
diff --git a/drivers/net/wireless/ti/wlcore/ps.c b/drivers/net/wireless/ti/wlcore/ps.c
index 9b7b6e2..9654577 100644
--- a/drivers/net/wireless/ti/wlcore/ps.c
+++ b/drivers/net/wireless/ti/wlcore/ps.c
@@ -29,6 +29,7 @@
 #define WL1271_WAKEUP_TIMEOUT 500
 
 #define ELP_ENTRY_DELAY  30
+#define ELP_ENTRY_DELAY_FORCE_PS  5
 
 void wl1271_elp_work(struct work_struct *work)
 {
@@ -98,7 +99,8 @@ void wl1271_ps_elp_sleep(struct wl1271 *wl)
 			return;
 	}
 
-	timeout = ELP_ENTRY_DELAY;
+	timeout = wl->conf.conn.forced_ps ?
+			ELP_ENTRY_DELAY_FORCE_PS : ELP_ENTRY_DELAY;
 	ieee80211_queue_delayed_work(wl->hw, &wl->elp_work,
 				     msecs_to_jiffies(timeout));
 }
diff --git a/drivers/net/wireless/ti/wlcore/tx.c b/drivers/net/wireless/ti/wlcore/tx.c
index ece392c..004d02e 100644
--- a/drivers/net/wireless/ti/wlcore/tx.c
+++ b/drivers/net/wireless/ti/wlcore/tx.c
@@ -24,6 +24,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/etherdevice.h>
+#include <linux/spinlock.h>
 
 #include "wlcore.h"
 #include "debug.h"
@@ -104,7 +105,7 @@ static void wl1271_tx_regulate_link(struct wl1271 *wl,
 				    struct wl12xx_vif *wlvif,
 				    u8 hlid)
 {
-	bool fw_ps, single_link;
+	bool fw_ps;
 	u8 tx_pkts;
 
 	if (WARN_ON(!test_bit(hlid, wlvif->links_map)))
@@ -112,15 +113,19 @@ static void wl1271_tx_regulate_link(struct wl1271 *wl,
 
 	fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);
 	tx_pkts = wl->links[hlid].allocated_pkts;
-	single_link = (wl->active_link_count == 1);
 
 	/*
 	 * if in FW PS and there is enough data in FW we can put the link
 	 * into high-level PS and clean out its TX queues.
 	 * Make an exception if this is the only connected link. In this
 	 * case FW-memory congestion is less of a problem.
+	 * Note that a single connected STA means 3 active links, since we must
+	 * account for the global and broadcast AP links. The "fw_ps" check
+	 * assures us the third link is a STA connected to the AP. Otherwise
+	 * the FW would not set the PSM bit.
 	 */
-	if (!single_link && fw_ps && tx_pkts >= WL1271_PS_STA_MAX_PACKETS)
+	if (wl->active_link_count > 3 && fw_ps &&
+	    tx_pkts >= WL1271_PS_STA_MAX_PACKETS)
 		wl12xx_ps_link_start(wl, wlvif, hlid, true);
 }
 
@@ -639,6 +644,7 @@ next:
 
 	}
 
+out:
 	if (!skb &&
 	    test_and_clear_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags)) {
 		int q;
@@ -652,7 +658,6 @@ next:
 		spin_unlock_irqrestore(&wl->wl_lock, flags);
 	}
 
-out:
 	return skb;
 }
 
@@ -928,25 +933,6 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl,
 
 	wl->stats.retry_count += result->ack_failures;
 
-	/*
-	 * 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 = wlvif->tx_security_last_seq_lsb;
-
-		/*
-		 * update security sequence number, taking care of potential
-		 * wrap-around
-		 */
-		wlvif->tx_security_seq += (fw_lsb - cur_lsb) & 0xff;
-		wlvif->tx_security_last_seq_lsb = fw_lsb;
-	}
-
 	/* remove private header from packet */
 	skb_pull(skb, sizeof(struct wl1271_tx_hw_descr));
 
@@ -1061,7 +1047,8 @@ void wl12xx_tx_reset_wlvif(struct wl1271 *wl, struct wl12xx_vif *wlvif)
 
 	/* TX failure */
 	for_each_set_bit(i, wlvif->links_map, WL12XX_MAX_LINKS) {
-		if (wlvif->bss_type == BSS_TYPE_AP_BSS) {
+		if (wlvif->bss_type == BSS_TYPE_AP_BSS &&
+		    i != wlvif->ap.bcast_hlid && i != wlvif->ap.global_hlid) {
 			/* this calls wl12xx_free_link */
 			wl1271_free_sta(wl, wlvif, i);
 		} else {
@@ -1304,7 +1291,7 @@ bool wlcore_is_queue_stopped_by_reason_locked(struct wl1271 *wl,
 {
 	int hwq = wlcore_tx_get_mac80211_queue(wlvif, queue);
 
-	WARN_ON_ONCE(!spin_is_locked(&wl->wl_lock));
+	assert_spin_locked(&wl->wl_lock);
 	return test_bit(reason, &wl->queue_stop_reasons[hwq]);
 }
 
@@ -1313,6 +1300,6 @@ bool wlcore_is_queue_stopped_locked(struct wl1271 *wl, struct wl12xx_vif *wlvif,
 {
 	int hwq = wlcore_tx_get_mac80211_queue(wlvif, queue);
 
-	WARN_ON_ONCE(!spin_is_locked(&wl->wl_lock));
+	assert_spin_locked(&wl->wl_lock);
 	return !!wl->queue_stop_reasons[hwq];
 }
diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h
index af9feca..0034979 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore.h
@@ -390,6 +390,9 @@ struct wl1271 {
 	/* number of currently active RX BA sessions */
 	int ba_rx_session_count;
 
+	/* Maximum number of supported RX BA sessions */
+	int ba_rx_session_count_max;
+
 	/* AP-mode - number of currently connected stations */
 	int active_sta_count;
 
diff --git a/drivers/net/wireless/ti/wlcore/wlcore_i.h b/drivers/net/wireless/ti/wlcore/wlcore_i.h
index 508f5b0..e5e1464 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore_i.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h
@@ -274,6 +274,13 @@ struct wl1271_link {
 
 	/* The wlvif this link belongs to. Might be null for global links */
 	struct wl12xx_vif *wlvif;
+
+	/*
+	 * total freed FW packets on the link - used for tracking the
+	 * AES/TKIP PN across recoveries. Re-initialized each time
+	 * from the wl1271_station structure.
+	 */
+	u64 total_freed_pkts;
 };
 
 #define WL1271_MAX_RX_FILTERS 5
@@ -318,6 +325,13 @@ struct wl12xx_rx_filter {
 struct wl1271_station {
 	u8 hlid;
 	bool in_connection;
+
+	/*
+	 * total freed FW packets on the link to the STA - used for tracking the
+	 * AES/TKIP PN across recoveries. Re-initialized each time from the
+	 * wl1271_station structure.
+	 */
+	u64 total_freed_pkts;
 };
 
 struct wl12xx_vif {
@@ -449,16 +463,15 @@ struct wl12xx_vif {
 	 */
 	struct {
 		u8 persistent[0];
+
 		/*
-		 * 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
+		 * total freed FW packets on the link - used for
+		 * storing the AES/TKIP PN during recovery, as this
+		 * structure is not zeroed out.
+		 * For STA this holds the PN of the link to the AP.
+		 * For AP this holds the PN of the broadcast link.
 		 */
-		u64 tx_security_seq;
-
-		/* 8 bits of the last sequence number in use */
-		u8 tx_security_last_seq_lsb;
+		u64 total_freed_pkts;
 	};
 };
 
diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c
index 730186d..38d2089 100644
--- a/drivers/net/wireless/wl3501_cs.c
+++ b/drivers/net/wireless/wl3501_cs.c
@@ -2013,19 +2013,7 @@ static struct pcmcia_driver wl3501_driver = {
 	.suspend	= wl3501_suspend,
 	.resume		= wl3501_resume,
 };
-
-static int __init wl3501_init_module(void)
-{
-	return pcmcia_register_driver(&wl3501_driver);
-}
-
-static void __exit wl3501_exit_module(void)
-{
-	pcmcia_unregister_driver(&wl3501_driver);
-}
-
-module_init(wl3501_init_module);
-module_exit(wl3501_exit_module);
+module_pcmcia_driver(wl3501_driver);
 
 MODULE_AUTHOR("Fox Chen <mhchen@golf.ccl.itri.org.tw>, "
 	      "Arnaldo Carvalho de Melo <acme@conectiva.com.br>,"
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
index cd49ba9..83905a9 100644
--- a/drivers/net/xen-netback/netback.c
+++ b/drivers/net/xen-netback/netback.c
@@ -942,7 +942,6 @@ static int netbk_count_requests(struct xenvif *vif,
 }
 
 static struct page *xen_netbk_alloc_page(struct xen_netbk *netbk,
-					 struct sk_buff *skb,
 					 u16 pending_idx)
 {
 	struct page *page;
@@ -976,7 +975,7 @@ static struct gnttab_copy *xen_netbk_get_requests(struct xen_netbk *netbk,
 
 		index = pending_index(netbk->pending_cons++);
 		pending_idx = netbk->pending_ring[index];
-		page = xen_netbk_alloc_page(netbk, skb, pending_idx);
+		page = xen_netbk_alloc_page(netbk, pending_idx);
 		if (!page)
 			goto err;
 
@@ -1185,6 +1184,7 @@ static int checksum_setup(struct xenvif *vif, struct sk_buff *skb)
 	if (th >= skb_tail_pointer(skb))
 		goto out;
 
+	skb_set_transport_header(skb, 4 * iph->ihl);
 	skb->csum_start = th - skb->head;
 	switch (iph->protocol) {
 	case IPPROTO_TCP:
@@ -1381,7 +1381,7 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk)
 		}
 
 		/* XXX could copy straight to head */
-		page = xen_netbk_alloc_page(netbk, skb, pending_idx);
+		page = xen_netbk_alloc_page(netbk, pending_idx);
 		if (!page) {
 			kfree_skb(skb);
 			netbk_tx_err(vif, &txreq, idx);
@@ -1496,6 +1496,7 @@ static void xen_netbk_tx_submit(struct xen_netbk *netbk)
 
 		skb->dev      = vif->dev;
 		skb->protocol = eth_type_trans(skb, skb->dev);
+		skb_reset_network_header(skb);
 
 		if (checksum_setup(vif, skb)) {
 			netdev_dbg(vif->dev,
@@ -1504,6 +1505,8 @@ static void xen_netbk_tx_submit(struct xen_netbk *netbk)
 			continue;
 		}
 
+		skb_probe_transport_header(skb, 0);
+
 		vif->dev->stats.rx_bytes += skb->len;
 		vif->dev->stats.rx_packets++;
 
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index 7ffa43b..d9097a7 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -537,7 +537,6 @@ static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	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;
 	RING_IDX i;
 	grant_ref_t ref;
@@ -581,7 +580,6 @@ static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	tx->gref = np->grant_tx_ref[id] = ref;
 	tx->offset = offset;
 	tx->size = len;
-	extra = NULL;
 
 	tx->flags = 0;
 	if (skb->ip_summed == CHECKSUM_PARTIAL)
@@ -597,10 +595,7 @@ static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev)
 		gso = (struct xen_netif_extra_info *)
 			RING_GET_REQUEST(&np->tx, ++i);
 
-		if (extra)
-			extra->flags |= XEN_NETIF_EXTRA_FLAG_MORE;
-		else
-			tx->flags |= XEN_NETTXF_extra_info;
+		tx->flags |= XEN_NETTXF_extra_info;
 
 		gso->u.gso.size = skb_shinfo(skb)->gso_size;
 		gso->u.gso.type = XEN_NETIF_GSO_TYPE_TCPV4;
@@ -609,7 +604,6 @@ static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
 		gso->type = XEN_NETIF_EXTRA_TYPE_GSO;
 		gso->flags = 0;
-		extra = gso;
 	}
 
 	np->tx.req_prod_pvt = i + 1;
@@ -718,7 +712,7 @@ static int xennet_get_responses(struct netfront_info *np,
 	struct sk_buff *skb = xennet_get_rx_skb(np, cons);
 	grant_ref_t ref = xennet_get_rx_ref(np, cons);
 	int max = MAX_SKB_FRAGS + (rx->status <= RX_COPY_THRESHOLD);
-	int frags = 1;
+	int slots = 1;
 	int err = 0;
 	unsigned long ret;
 
@@ -762,27 +756,27 @@ next:
 		if (!(rx->flags & XEN_NETRXF_more_data))
 			break;
 
-		if (cons + frags == rp) {
+		if (cons + slots == rp) {
 			if (net_ratelimit())
-				dev_warn(dev, "Need more frags\n");
+				dev_warn(dev, "Need more slots\n");
 			err = -ENOENT;
 			break;
 		}
 
-		rx = RING_GET_RESPONSE(&np->rx, cons + frags);
-		skb = xennet_get_rx_skb(np, cons + frags);
-		ref = xennet_get_rx_ref(np, cons + frags);
-		frags++;
+		rx = RING_GET_RESPONSE(&np->rx, cons + slots);
+		skb = xennet_get_rx_skb(np, cons + slots);
+		ref = xennet_get_rx_ref(np, cons + slots);
+		slots++;
 	}
 
-	if (unlikely(frags > max)) {
+	if (unlikely(slots > max)) {
 		if (net_ratelimit())
 			dev_warn(dev, "Too many frags\n");
 		err = -E2BIG;
 	}
 
 	if (unlikely(err))
-		np->rx.rsp_cons = cons + frags;
+		np->rx.rsp_cons = cons + slots;
 
 	return err;
 }
diff --git a/drivers/nfc/microread/mei.c b/drivers/nfc/microread/mei.c
index eef38cf..ca33ae1 100644
--- a/drivers/nfc/microread/mei.c
+++ b/drivers/nfc/microread/mei.c
@@ -22,7 +22,7 @@
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/gpio.h>
-#include <linux/mei_bus.h>
+#include <linux/mei_cl_bus.h>
 
 #include <linux/nfc.h>
 #include <net/nfc/hci.h>
@@ -32,9 +32,6 @@
 
 #define MICROREAD_DRIVER_NAME "microread"
 
-#define MICROREAD_UUID UUID_LE(0x0bb17a78, 0x2a8e, 0x4c50, 0x94, \
-			       0xd4, 0x50, 0x26, 0x67, 0x23, 0x77, 0x5c)
-
 struct mei_nfc_hdr {
 	u8 cmd;
 	u8 status;
@@ -48,7 +45,7 @@ struct mei_nfc_hdr {
 #define MEI_NFC_MAX_READ (MEI_NFC_HEADER_SIZE + MEI_NFC_MAX_HCI_PAYLOAD)
 
 struct microread_mei_phy {
-	struct mei_device *mei_device;
+	struct mei_cl_device *device;
 	struct nfc_hci_dev *hdev;
 
 	int powered;
@@ -105,14 +102,14 @@ static int microread_mei_write(void *phy_id, struct sk_buff *skb)
 
 	MEI_DUMP_SKB_OUT("mei frame sent", skb);
 
-	r = mei_send(phy->device, skb->data, skb->len);
+	r = mei_cl_send(phy->device, skb->data, skb->len);
 	if (r > 0)
 		r = 0;
 
 	return r;
 }
 
-static void microread_event_cb(struct mei_device *device, u32 events,
+static void microread_event_cb(struct mei_cl_device *device, u32 events,
 			       void *context)
 {
 	struct microread_mei_phy *phy = context;
@@ -120,7 +117,7 @@ static void microread_event_cb(struct mei_device *device, u32 events,
 	if (phy->hard_fault != 0)
 		return;
 
-	if (events & BIT(MEI_EVENT_RX)) {
+	if (events & BIT(MEI_CL_EVENT_RX)) {
 		struct sk_buff *skb;
 		int reply_size;
 
@@ -128,7 +125,7 @@ static void microread_event_cb(struct mei_device *device, u32 events,
 		if (!skb)
 			return;
 
-		reply_size = mei_recv(device, skb->data, MEI_NFC_MAX_READ);
+		reply_size = mei_cl_recv(device, skb->data, MEI_NFC_MAX_READ);
 		if (reply_size < MEI_NFC_HEADER_SIZE) {
 			kfree(skb);
 			return;
@@ -149,8 +146,8 @@ static struct nfc_phy_ops mei_phy_ops = {
 	.disable = microread_mei_disable,
 };
 
-static int microread_mei_probe(struct mei_device *device,
-			       const struct mei_id *id)
+static int microread_mei_probe(struct mei_cl_device *device,
+			       const struct mei_cl_device_id *id)
 {
 	struct microread_mei_phy *phy;
 	int r;
@@ -164,9 +161,9 @@ static int microread_mei_probe(struct mei_device *device,
 	}
 
 	phy->device = device;
-	mei_set_clientdata(device, phy);
+	mei_cl_set_drvdata(device, phy);
 
-	r = mei_register_event_cb(device, microread_event_cb, phy);
+	r = mei_cl_register_event_cb(device, microread_event_cb, phy);
 	if (r) {
 		pr_err(MICROREAD_DRIVER_NAME ": event cb registration failed\n");
 		goto err_out;
@@ -186,9 +183,9 @@ err_out:
 	return r;
 }
 
-static int microread_mei_remove(struct mei_device *device)
+static int microread_mei_remove(struct mei_cl_device *device)
 {
-	struct microread_mei_phy *phy = mei_get_clientdata(device);
+	struct microread_mei_phy *phy = mei_cl_get_drvdata(device);
 
 	pr_info("Removing microread\n");
 
@@ -202,16 +199,15 @@ static int microread_mei_remove(struct mei_device *device)
 	return 0;
 }
 
-static struct mei_id microread_mei_tbl[] = {
-	{ MICROREAD_DRIVER_NAME, MICROREAD_UUID },
+static struct mei_cl_device_id microread_mei_tbl[] = {
+	{ MICROREAD_DRIVER_NAME },
 
 	/* required last entry */
 	{ }
 };
-
 MODULE_DEVICE_TABLE(mei, microread_mei_tbl);
 
-static struct mei_driver microread_driver = {
+static struct mei_cl_driver microread_driver = {
 	.id_table = microread_mei_tbl,
 	.name = MICROREAD_DRIVER_NAME,
 
@@ -225,7 +221,7 @@ static int microread_mei_init(void)
 
 	pr_debug(DRIVER_DESC ": %s\n", __func__);
 
-	r = mei_driver_register(&microread_driver);
+	r = mei_cl_driver_register(&microread_driver);
 	if (r) {
 		pr_err(MICROREAD_DRIVER_NAME ": driver registration failed\n");
 		return r;
@@ -236,7 +232,7 @@ static int microread_mei_init(void)
 
 static void microread_mei_exit(void)
 {
-	mei_driver_unregister(&microread_driver);
+	mei_cl_driver_unregister(&microread_driver);
 }
 
 module_init(microread_mei_init);
diff --git a/drivers/parisc/led.c b/drivers/parisc/led.c
index d4d800c..b482431 100644
--- a/drivers/parisc/led.c
+++ b/drivers/parisc/led.c
@@ -172,14 +172,14 @@ static int led_proc_show(struct seq_file *m, void *v)
 
 static int led_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, led_proc_show, PDE(inode)->data);
+	return single_open(file, led_proc_show, PDE_DATA(inode));
 }
 
 
 static ssize_t led_proc_write(struct file *file, const char *buf,
 	size_t count, loff_t *pos)
 {
-	void *data = PDE(file_inode(file))->data;
+	void *data = PDE_DATA(file_inode(file));
 	char *cur, lbuf[32];
 	int d;
 
diff --git a/drivers/parport/parport_amiga.c b/drivers/parport/parport_amiga.c
index ee78e0e..09503b8 100644
--- a/drivers/parport/parport_amiga.c
+++ b/drivers/parport/parport_amiga.c
@@ -244,20 +244,7 @@ static struct platform_driver amiga_parallel_driver = {
 	},
 };
 
-static int __init amiga_parallel_init(void)
-{
-	return platform_driver_probe(&amiga_parallel_driver,
-				     amiga_parallel_probe);
-}
-
-module_init(amiga_parallel_init);
-
-static void __exit amiga_parallel_exit(void)
-{
-	platform_driver_unregister(&amiga_parallel_driver);
-}
-
-module_exit(amiga_parallel_exit);
+module_platform_driver_probe(amiga_parallel_driver, amiga_parallel_probe);
 
 MODULE_AUTHOR("Joerg Dorchain <joerg@dorchain.net>");
 MODULE_DESCRIPTION("Parport Driver for Amiga builtin Port");
diff --git a/drivers/parport/parport_cs.c b/drivers/parport/parport_cs.c
index 067ad51..e9b52e4 100644
--- a/drivers/parport/parport_cs.c
+++ b/drivers/parport/parport_cs.c
@@ -193,16 +193,4 @@ static struct pcmcia_driver parport_cs_driver = {
 	.remove		= parport_detach,
 	.id_table	= parport_ids,
 };
-
-static int __init init_parport_cs(void)
-{
-	return pcmcia_register_driver(&parport_cs_driver);
-}
-
-static void __exit exit_parport_cs(void)
-{
-	pcmcia_unregister_driver(&parport_cs_driver);
-}
-
-module_init(init_parport_cs);
-module_exit(exit_parport_cs);
+module_pcmcia_driver(parport_cs_driver);
diff --git a/drivers/parport/parport_gsc.c b/drivers/parport/parport_gsc.c
index 050773c..a5251cb 100644
--- a/drivers/parport/parport_gsc.c
+++ b/drivers/parport/parport_gsc.c
@@ -246,14 +246,14 @@ struct parport *parport_gsc_probe_port(unsigned long base,
 		printk (KERN_DEBUG "parport (0x%lx): no memory!\n", base);
 		return NULL;
 	}
-	ops = kmalloc (sizeof (struct parport_operations), GFP_KERNEL);
+	ops = kmemdup(&parport_gsc_ops, sizeof(struct parport_operations),
+		      GFP_KERNEL);
 	if (!ops) {
 		printk (KERN_DEBUG "parport (0x%lx): no memory for ops!\n",
 			base);
 		kfree (priv);
 		return NULL;
 	}
-	memcpy (ops, &parport_gsc_ops, sizeof (struct parport_operations));
 	priv->ctr = 0xc;
 	priv->ctr_writable = 0xff;
 	priv->dma_buf = 0;
diff --git a/drivers/parport/parport_sunbpp.c b/drivers/parport/parport_sunbpp.c
index 5c4b6a1..dffd6d0b 100644
--- a/drivers/parport/parport_sunbpp.c
+++ b/drivers/parport/parport_sunbpp.c
@@ -284,12 +284,11 @@ static int bpp_probe(struct platform_device *op)
 	size = resource_size(&op->resource[0]);
 	dma = PARPORT_DMA_NONE;
 
-	ops = kmalloc(sizeof(struct parport_operations), GFP_KERNEL);
+	ops = kmemdup(&parport_sunbpp_ops, sizeof(struct parport_operations),
+		      GFP_KERNEL);
         if (!ops)
 		goto out_unmap;
 
-        memcpy (ops, &parport_sunbpp_ops, sizeof(struct parport_operations));
-
 	dprintk(("register_port\n"));
 	if (!(p = parport_register_port((unsigned long)base, irq, dma, ops)))
 		goto out_free_ops;
diff --git a/drivers/parport/procfs.c b/drivers/parport/procfs.c
index 3f56bc0..92ed045 100644
--- a/drivers/parport/procfs.c
+++ b/drivers/parport/procfs.c
@@ -476,10 +476,9 @@ int parport_proc_register(struct parport *port)
 	struct parport_sysctl_table *t;
 	int i;
 
-	t = kmalloc(sizeof(*t), GFP_KERNEL);
+	t = kmemdup(&parport_sysctl_template, sizeof(*t), GFP_KERNEL);
 	if (t == NULL)
 		return -ENOMEM;
-	memcpy(t, &parport_sysctl_template, sizeof(*t));
 
 	t->device_dir[0].extra1 = port;
 
@@ -523,10 +522,9 @@ int parport_device_proc_register(struct pardevice *device)
 	struct parport_device_sysctl_table *t;
 	struct parport * port = device->port;
 	
-	t = kmalloc(sizeof(*t), GFP_KERNEL);
+	t = kmemdup(&parport_device_sysctl_template, sizeof(*t), GFP_KERNEL);
 	if (t == NULL)
 		return -ENOMEM;
-	memcpy(t, &parport_device_sysctl_template, sizeof(*t));
 
 	t->dev_dir[0].child = t->parport_dir;
 	t->parport_dir[0].child = t->port_dir;
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index dee5ddd..5147c21 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -53,14 +53,15 @@ static void pci_acpi_wake_dev(acpi_handle handle, u32 event, void *context)
 		return;
 	}
 
-	if (!pci_dev->pm_cap || !pci_dev->pme_support
-	     || pci_check_pme_status(pci_dev)) {
-		if (pci_dev->pme_poll)
-			pci_dev->pme_poll = false;
+	/* Clear PME Status if set. */
+	if (pci_dev->pme_support)
+		pci_check_pme_status(pci_dev);
 
-		pci_wakeup_event(pci_dev);
-		pm_runtime_resume(&pci_dev->dev);
-	}
+	if (pci_dev->pme_poll)
+		pci_dev->pme_poll = false;
+
+	pci_wakeup_event(pci_dev);
+	pm_runtime_resume(&pci_dev->dev);
 
 	if (pci_dev->subordinate)
 		pci_pme_wakeup_bus(pci_dev->subordinate);
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 1fa1e48..79277fb 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -390,9 +390,10 @@ static void pci_device_shutdown(struct device *dev)
 
 	/*
 	 * Turn off Bus Master bit on the device to tell it to not
-	 * continue to do DMA
+	 * continue to do DMA. Don't touch devices in D3cold or unknown states.
 	 */
-	pci_clear_master(pci_dev);
+	if (pci_dev->current_state <= PCI_D3hot)
+		pci_clear_master(pci_dev);
 }
 
 #ifdef CONFIG_PM
diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c
index 564d97f..8ec8b4f 100644
--- a/drivers/pci/pcie/aer/aerdrv_core.c
+++ b/drivers/pci/pcie/aer/aerdrv_core.c
@@ -89,8 +89,6 @@ static int add_error_device(struct aer_err_info *e_info, struct pci_dev *dev)
 	return -ENOSPC;
 }
 
-#define	PCI_BUS(x)	(((x) >> 8) & 0xff)
-
 /**
  * is_error_source - check whether the device is source of reported error
  * @dev: pointer to pci_dev to be checked
@@ -106,7 +104,7 @@ static bool is_error_source(struct pci_dev *dev, struct aer_err_info *e_info)
 	 * When bus id is equal to 0, it might be a bad id
 	 * reported by root port.
 	 */
-	if (!nosourceid && (PCI_BUS(e_info->id) != 0)) {
+	if (!nosourceid && (PCI_BUS_NUM(e_info->id) != 0)) {
 		/* Device ID match? */
 		if (e_info->id == ((dev->bus->number << 8) | dev->devfn))
 			return true;
diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c
index 08c243a..ed4d094 100644
--- a/drivers/pci/pcie/portdrv_pci.c
+++ b/drivers/pci/pcie/portdrv_pci.c
@@ -185,14 +185,6 @@ static const struct dev_pm_ops pcie_portdrv_pm_ops = {
 #endif /* !PM */
 
 /*
- * PCIe port runtime suspend is broken for some chipsets, so use a
- * black list to disable runtime PM for these chipsets.
- */
-static const struct pci_device_id port_runtime_pm_black_list[] = {
-	{ /* end: all zeroes */ }
-};
-
-/*
  * pcie_portdrv_probe - Probe PCI-Express port devices
  * @dev: PCI-Express port device being probed
  *
@@ -225,16 +217,11 @@ static int pcie_portdrv_probe(struct pci_dev *dev,
 	 * it by default.
 	 */
 	dev->d3cold_allowed = false;
-	if (!pci_match_id(port_runtime_pm_black_list, dev))
-		pm_runtime_put_noidle(&dev->dev);
-
 	return 0;
 }
 
 static void pcie_portdrv_remove(struct pci_dev *dev)
 {
-	if (!pci_match_id(port_runtime_pm_black_list, dev))
-		pm_runtime_get_noresume(&dev->dev);
 	pcie_port_device_remove(dev);
 	pci_disable_device(dev);
 }
diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c
index 0b00947..12e4fb5 100644
--- a/drivers/pci/proc.c
+++ b/drivers/pci/proc.c
@@ -46,9 +46,7 @@ proc_bus_pci_lseek(struct file *file, loff_t off, int whence)
 static ssize_t
 proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
 {
-	const struct inode *ino = file_inode(file);
-	const struct proc_dir_entry *dp = PDE(ino);
-	struct pci_dev *dev = dp->data;
+	struct pci_dev *dev = PDE_DATA(file_inode(file));
 	unsigned int pos = *ppos;
 	unsigned int cnt, size;
 
@@ -59,7 +57,7 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp
 	 */
 
 	if (capable(CAP_SYS_ADMIN))
-		size = dp->size;
+		size = dev->cfg_size;
 	else if (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
 		size = 128;
 	else
@@ -133,10 +131,9 @@ static ssize_t
 proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, loff_t *ppos)
 {
 	struct inode *ino = file_inode(file);
-	const struct proc_dir_entry *dp = PDE(ino);
-	struct pci_dev *dev = dp->data;
+	struct pci_dev *dev = PDE_DATA(ino);
 	int pos = *ppos;
-	int size = dp->size;
+	int size = dev->cfg_size;
 	int cnt;
 
 	if (pos >= size)
@@ -200,7 +197,7 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof
 	pci_config_pm_runtime_put(dev);
 
 	*ppos = pos;
-	i_size_write(ino, dp->size);
+	i_size_write(ino, dev->cfg_size);
 	return nbytes;
 }
 
@@ -212,8 +209,7 @@ struct pci_filp_private {
 static long proc_bus_pci_ioctl(struct file *file, unsigned int cmd,
 			       unsigned long arg)
 {
-	const struct proc_dir_entry *dp = PDE(file_inode(file));
-	struct pci_dev *dev = dp->data;
+	struct pci_dev *dev = PDE_DATA(file_inode(file));
 #ifdef HAVE_PCI_MMAP
 	struct pci_filp_private *fpriv = file->private_data;
 #endif /* HAVE_PCI_MMAP */
@@ -253,9 +249,7 @@ static long proc_bus_pci_ioctl(struct file *file, unsigned int cmd,
 #ifdef HAVE_PCI_MMAP
 static int proc_bus_pci_mmap(struct file *file, struct vm_area_struct *vma)
 {
-	struct inode *inode = file_inode(file);
-	const struct proc_dir_entry *dp = PDE(inode);
-	struct pci_dev *dev = dp->data;
+	struct pci_dev *dev = PDE_DATA(file_inode(file));
 	struct pci_filp_private *fpriv = file->private_data;
 	int i, ret;
 
diff --git a/drivers/pci/rom.c b/drivers/pci/rom.c
index b41ac77..c5d0a08 100644
--- a/drivers/pci/rom.c
+++ b/drivers/pci/rom.c
@@ -100,27 +100,6 @@ size_t pci_get_rom_size(struct pci_dev *pdev, void __iomem *rom, size_t size)
 	return min((size_t)(image - rom), size);
 }
 
-static loff_t pci_find_rom(struct pci_dev *pdev, size_t *size)
-{
-	struct resource *res = &pdev->resource[PCI_ROM_RESOURCE];
-	loff_t start;
-
-	/* assign the ROM an address if it doesn't have one */
-	if (res->parent == NULL && pci_assign_resource(pdev, PCI_ROM_RESOURCE))
-		return 0;
-	start = pci_resource_start(pdev, PCI_ROM_RESOURCE);
-	*size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
-
-	if (*size == 0)
-		return 0;
-
-	/* Enable ROM space decodes */
-	if (pci_enable_rom(pdev))
-		return 0;
-
-	return start;
-}
-
 /**
  * pci_map_rom - map a PCI ROM to kernel space
  * @pdev: pointer to pci device struct
@@ -135,7 +114,7 @@ static loff_t pci_find_rom(struct pci_dev *pdev, size_t *size)
 void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size)
 {
 	struct resource *res = &pdev->resource[PCI_ROM_RESOURCE];
-	loff_t start = 0;
+	loff_t start;
 	void __iomem *rom;
 
 	/*
@@ -154,21 +133,21 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size)
 			return (void __iomem *)(unsigned long)
 				pci_resource_start(pdev, PCI_ROM_RESOURCE);
 		} else {
-			start = pci_find_rom(pdev, size);
-		}
-	}
+			/* assign the ROM an address if it doesn't have one */
+			if (res->parent == NULL &&
+			    pci_assign_resource(pdev,PCI_ROM_RESOURCE))
+				return NULL;
+			start = pci_resource_start(pdev, PCI_ROM_RESOURCE);
+			*size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
+			if (*size == 0)
+				return NULL;
 
-	/*
-	 * Some devices may provide ROMs via a source other than the BAR
-	 */
-	if (!start && pdev->rom && pdev->romlen) {
-		*size = pdev->romlen;
-		return phys_to_virt(pdev->rom);
+			/* Enable ROM space decodes */
+			if (pci_enable_rom(pdev))
+				return NULL;
+		}
 	}
 
-	if (!start)
-		return NULL;
-
 	rom = ioremap(start, *size);
 	if (!rom) {
 		/* restore enable if ioremap fails */
@@ -202,8 +181,7 @@ void pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom)
 	if (res->flags & (IORESOURCE_ROM_COPY | IORESOURCE_ROM_BIOS_COPY))
 		return;
 
-	if (!pdev->rom || !pdev->romlen)
-		iounmap(rom);
+	iounmap(rom);
 
 	/* Disable again before continuing, leave enabled if pci=rom */
 	if (!(res->flags & (IORESOURCE_ROM_ENABLE | IORESOURCE_ROM_SHADOW)))
@@ -227,7 +205,24 @@ void pci_cleanup_rom(struct pci_dev *pdev)
 	}
 }
 
+/**
+ * pci_platform_rom - provides a pointer to any ROM image provided by the
+ * platform
+ * @pdev: pointer to pci device struct
+ * @size: pointer to receive size of pci window over ROM
+ */
+void __iomem *pci_platform_rom(struct pci_dev *pdev, size_t *size)
+{
+	if (pdev->rom && pdev->romlen) {
+		*size = pdev->romlen;
+		return phys_to_virt((phys_addr_t)pdev->rom);
+	}
+
+	return NULL;
+}
+
 EXPORT_SYMBOL(pci_map_rom);
 EXPORT_SYMBOL(pci_unmap_rom);
 EXPORT_SYMBOL_GPL(pci_enable_rom);
 EXPORT_SYMBOL_GPL(pci_disable_rom);
+EXPORT_SYMBOL(pci_platform_rom);
diff --git a/drivers/pcmcia/m8xx_pcmcia.c b/drivers/pcmcia/m8xx_pcmcia.c
index a3a851e..18c0d8d 100644
--- a/drivers/pcmcia/m8xx_pcmcia.c
+++ b/drivers/pcmcia/m8xx_pcmcia.c
@@ -68,12 +68,6 @@ MODULE_LICENSE("Dual MPL/GPL");
 
 #if !defined(CONFIG_PCMCIA_SLOT_A) && !defined(CONFIG_PCMCIA_SLOT_B)
 
-/* The RPX series use SLOT_B */
-#if defined(CONFIG_RPXCLASSIC) || defined(CONFIG_RPXLITE)
-#define CONFIG_PCMCIA_SLOT_B
-#define CONFIG_BD_IS_MHZ
-#endif
-
 /* The ADS board use SLOT_A */
 #ifdef CONFIG_ADS
 #define CONFIG_PCMCIA_SLOT_A
@@ -253,81 +247,6 @@ static irqreturn_t m8xx_interrupt(int irq, void *dev);
 
 #define PCMCIA_BMT_LIMIT (15*4)	/* Bus Monitor Timeout value */
 
-/* ------------------------------------------------------------------------- */
-/* board specific stuff:                                                     */
-/* voltage_set(), hardware_enable() and hardware_disable()                   */
-/* ------------------------------------------------------------------------- */
-/* RPX Boards from Embedded Planet                                           */
-
-#if defined(CONFIG_RPXCLASSIC) || defined(CONFIG_RPXLITE)
-
-/* The RPX boards seems to have it's bus monitor timeout set to 6*8 clocks.
- * SYPCR is write once only, therefore must the slowest memory be faster
- * than the bus monitor or we will get a machine check due to the bus timeout.
- */
-
-#define PCMCIA_BOARD_MSG "RPX CLASSIC or RPX LITE"
-
-#undef PCMCIA_BMT_LIMIT
-#define PCMCIA_BMT_LIMIT (6*8)
-
-static int voltage_set(int slot, int vcc, int vpp)
-{
-	u32 reg = 0;
-
-	switch (vcc) {
-	case 0:
-		break;
-	case 33:
-		reg |= BCSR1_PCVCTL4;
-		break;
-	case 50:
-		reg |= BCSR1_PCVCTL5;
-		break;
-	default:
-		return 1;
-	}
-
-	switch (vpp) {
-	case 0:
-		break;
-	case 33:
-	case 50:
-		if (vcc == vpp)
-			reg |= BCSR1_PCVCTL6;
-		else
-			return 1;
-		break;
-	case 120:
-		reg |= BCSR1_PCVCTL7;
-	default:
-		return 1;
-	}
-
-	if (!((vcc == 50) || (vcc == 0)))
-		return 1;
-
-	/* first, turn off all power */
-
-	out_be32(((u32 *) RPX_CSR_ADDR),
-		 in_be32(((u32 *) RPX_CSR_ADDR)) & ~(BCSR1_PCVCTL4 |
-						     BCSR1_PCVCTL5 |
-						     BCSR1_PCVCTL6 |
-						     BCSR1_PCVCTL7));
-
-	/* enable new powersettings */
-
-	out_be32(((u32 *) RPX_CSR_ADDR), in_be32(((u32 *) RPX_CSR_ADDR)) | reg);
-
-	return 0;
-}
-
-#define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V
-#define hardware_enable(_slot_)	/* No hardware to enable */
-#define hardware_disable(_slot_)	/* No hardware to disable */
-
-#endif				/* CONFIG_RPXCLASSIC */
-
 /* FADS Boards from Motorola                                               */
 
 #if defined(CONFIG_FADS)
@@ -419,65 +338,6 @@ static inline int voltage_set(int slot, int vcc, int vpp)
 
 #endif
 
-/* ------------------------------------------------------------------------- */
-/* Motorola MBX860                                                           */
-
-#if defined(CONFIG_MBX)
-
-#define PCMCIA_BOARD_MSG "MBX"
-
-static int voltage_set(int slot, int vcc, int vpp)
-{
-	u8 reg = 0;
-
-	switch (vcc) {
-	case 0:
-		break;
-	case 33:
-		reg |= CSR2_VCC_33;
-		break;
-	case 50:
-		reg |= CSR2_VCC_50;
-		break;
-	default:
-		return 1;
-	}
-
-	switch (vpp) {
-	case 0:
-		break;
-	case 33:
-	case 50:
-		if (vcc == vpp)
-			reg |= CSR2_VPP_VCC;
-		else
-			return 1;
-		break;
-	case 120:
-		if ((vcc == 33) || (vcc == 50))
-			reg |= CSR2_VPP_12;
-		else
-			return 1;
-	default:
-		return 1;
-	}
-
-	/* first, turn off all power */
-	out_8((u8 *) MBX_CSR2_ADDR,
-	      in_8((u8 *) MBX_CSR2_ADDR) & ~(CSR2_VCC_MASK | CSR2_VPP_MASK));
-
-	/* enable new powersettings */
-	out_8((u8 *) MBX_CSR2_ADDR, in_8((u8 *) MBX_CSR2_ADDR) | reg);
-
-	return 0;
-}
-
-#define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V
-#define hardware_enable(_slot_)	/* No hardware to enable */
-#define hardware_disable(_slot_)	/* No hardware to disable */
-
-#endif				/* CONFIG_MBX */
-
 #if defined(CONFIG_PRxK)
 #include <asm/cpld.h>
 extern volatile fpga_pc_regs *fpga_pc;
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 34f51d2..f591284 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -93,12 +93,20 @@ config PINCTRL_IMX53
 	  Say Y here to enable the imx53 pinctrl driver
 
 config PINCTRL_IMX6Q
-	bool "IMX6Q pinctrl driver"
+	bool "IMX6Q/DL pinctrl driver"
 	depends on OF
 	depends on SOC_IMX6Q
 	select PINCTRL_IMX
 	help
-	  Say Y here to enable the imx6q pinctrl driver
+	  Say Y here to enable the imx6q/dl pinctrl driver
+
+config PINCTRL_IMX6SL
+	bool "IMX6SL pinctrl driver"
+	depends on OF
+	depends on SOC_IMX6SL
+	select PINCTRL_IMX
+	help
+	  Say Y here to enable the imx6sl pinctrl driver
 
 config PINCTRL_LANTIQ
 	bool
@@ -106,20 +114,11 @@ config PINCTRL_LANTIQ
 	select PINMUX
 	select PINCONF
 
-config PINCTRL_PXA3xx
-	bool
-	select PINMUX
-
 config PINCTRL_FALCON
 	bool
 	depends on SOC_FALCON
 	depends on PINCTRL_LANTIQ
 
-config PINCTRL_MMP2
-	bool "MMP2 pin controller driver"
-	depends on ARCH_MMP
-	select PINCTRL_PXA3xx
-
 config PINCTRL_MXS
 	bool
 	select PINMUX
@@ -151,21 +150,12 @@ config PINCTRL_DB8540
 	bool "DB8540 pin controller driver"
 	depends on PINCTRL_NOMADIK && ARCH_U8500
 
-config PINCTRL_PXA168
-	bool "PXA168 pin controller driver"
-	depends on ARCH_MMP
-	select PINCTRL_PXA3xx
-
-config PINCTRL_PXA910
-	bool "PXA910 pin controller driver"
-	depends on ARCH_MMP
-	select PINCTRL_PXA3xx
-
 config PINCTRL_SINGLE
 	tristate "One-register-per-pin type device tree based pinctrl driver"
 	depends on OF
 	select PINMUX
 	select PINCONF
+	select GENERIC_PINCONF
 	help
 	  This selects the device tree based generic pinctrl driver.
 
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index f82cc5b..1473817 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -21,9 +21,8 @@ obj-$(CONFIG_PINCTRL_IMX35)	+= pinctrl-imx35.o
 obj-$(CONFIG_PINCTRL_IMX51)	+= pinctrl-imx51.o
 obj-$(CONFIG_PINCTRL_IMX53)	+= pinctrl-imx53.o
 obj-$(CONFIG_PINCTRL_IMX6Q)	+= pinctrl-imx6q.o
-obj-$(CONFIG_PINCTRL_PXA3xx)	+= pinctrl-pxa3xx.o
+obj-$(CONFIG_PINCTRL_IMX6Q)	+= pinctrl-imx6dl.o
 obj-$(CONFIG_PINCTRL_FALCON)	+= pinctrl-falcon.o
-obj-$(CONFIG_PINCTRL_MMP2)	+= pinctrl-mmp2.o
 obj-$(CONFIG_PINCTRL_MXS)	+= pinctrl-mxs.o
 obj-$(CONFIG_PINCTRL_IMX23)	+= pinctrl-imx23.o
 obj-$(CONFIG_PINCTRL_IMX28)	+= pinctrl-imx28.o
@@ -31,8 +30,6 @@ obj-$(CONFIG_PINCTRL_NOMADIK)	+= pinctrl-nomadik.o
 obj-$(CONFIG_PINCTRL_STN8815)	+= pinctrl-nomadik-stn8815.o
 obj-$(CONFIG_PINCTRL_DB8500)	+= pinctrl-nomadik-db8500.o
 obj-$(CONFIG_PINCTRL_DB8540)	+= pinctrl-nomadik-db8540.o
-obj-$(CONFIG_PINCTRL_PXA168)	+= pinctrl-pxa168.o
-obj-$(CONFIG_PINCTRL_PXA910)	+= pinctrl-pxa910.o
 obj-$(CONFIG_PINCTRL_SINGLE)	+= pinctrl-single.o
 obj-$(CONFIG_PINCTRL_SIRF)	+= pinctrl-sirf.o
 obj-$(CONFIG_PINCTRL_SUNXI)	+= pinctrl-sunxi.o
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
index b0de6e7..8b832ce 100644
--- a/drivers/pinctrl/core.c
+++ b/drivers/pinctrl/core.c
@@ -27,6 +27,11 @@
 #include <linux/pinctrl/consumer.h>
 #include <linux/pinctrl/pinctrl.h>
 #include <linux/pinctrl/machine.h>
+
+#ifdef CONFIG_GPIOLIB
+#include <asm-generic/gpio.h>
+#endif
+
 #include "core.h"
 #include "devicetree.h"
 #include "pinmux.h"
@@ -277,6 +282,43 @@ pinctrl_match_gpio_range(struct pinctrl_dev *pctldev, unsigned gpio)
 }
 
 /**
+ * pinctrl_ready_for_gpio_range() - check if other GPIO pins of
+ * the same GPIO chip are in range
+ * @gpio: gpio pin to check taken from the global GPIO pin space
+ *
+ * This function is complement of pinctrl_match_gpio_range(). If the return
+ * value of pinctrl_match_gpio_range() is NULL, this function could be used
+ * to check whether pinctrl device is ready or not. Maybe some GPIO pins
+ * of the same GPIO chip don't have back-end pinctrl interface.
+ * If the return value is true, it means that pinctrl device is ready & the
+ * certain GPIO pin doesn't have back-end pinctrl device. If the return value
+ * is false, it means that pinctrl device may not be ready.
+ */
+#ifdef CONFIG_GPIOLIB
+static bool pinctrl_ready_for_gpio_range(unsigned gpio)
+{
+	struct pinctrl_dev *pctldev;
+	struct pinctrl_gpio_range *range = NULL;
+	struct gpio_chip *chip = gpio_to_chip(gpio);
+
+	/* Loop over the pin controllers */
+	list_for_each_entry(pctldev, &pinctrldev_list, node) {
+		/* Loop over the ranges */
+		list_for_each_entry(range, &pctldev->gpio_ranges, node) {
+			/* Check if any gpio range overlapped with gpio chip */
+			if (range->base + range->npins - 1 < chip->base ||
+			    range->base > chip->base + chip->ngpio - 1)
+				continue;
+			return true;
+		}
+	}
+	return false;
+}
+#else
+static bool pinctrl_ready_for_gpio_range(unsigned gpio) { return true; }
+#endif
+
+/**
  * pinctrl_get_device_gpio_range() - find device for GPIO range
  * @gpio: the pin to locate the pin controller for
  * @outdev: the pin control device if found
@@ -443,6 +485,8 @@ int pinctrl_request_gpio(unsigned gpio)
 
 	ret = pinctrl_get_device_gpio_range(gpio, &pctldev, &range);
 	if (ret) {
+		if (pinctrl_ready_for_gpio_range(gpio))
+			ret = 0;
 		mutex_unlock(&pinctrl_mutex);
 		return ret;
 	}
@@ -758,6 +802,24 @@ struct pinctrl *pinctrl_get(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(pinctrl_get);
 
+static void pinctrl_free_setting(bool disable_setting,
+				 struct pinctrl_setting *setting)
+{
+	switch (setting->type) {
+	case PIN_MAP_TYPE_MUX_GROUP:
+		if (disable_setting)
+			pinmux_disable_setting(setting);
+		pinmux_free_setting(setting);
+		break;
+	case PIN_MAP_TYPE_CONFIGS_PIN:
+	case PIN_MAP_TYPE_CONFIGS_GROUP:
+		pinconf_free_setting(setting);
+		break;
+	default:
+		break;
+	}
+}
+
 static void pinctrl_put_locked(struct pinctrl *p, bool inlist)
 {
 	struct pinctrl_state *state, *n1;
@@ -765,19 +827,7 @@ static void pinctrl_put_locked(struct pinctrl *p, bool inlist)
 
 	list_for_each_entry_safe(state, n1, &p->states, node) {
 		list_for_each_entry_safe(setting, n2, &state->settings, node) {
-			switch (setting->type) {
-			case PIN_MAP_TYPE_MUX_GROUP:
-				if (state == p->state)
-					pinmux_disable_setting(setting);
-				pinmux_free_setting(setting);
-				break;
-			case PIN_MAP_TYPE_CONFIGS_PIN:
-			case PIN_MAP_TYPE_CONFIGS_GROUP:
-				pinconf_free_setting(setting);
-				break;
-			default:
-				break;
-			}
+			pinctrl_free_setting(state == p->state, setting);
 			list_del(&setting->node);
 			kfree(setting);
 		}
@@ -855,6 +905,7 @@ static int pinctrl_select_state_locked(struct pinctrl *p,
 				       struct pinctrl_state *state)
 {
 	struct pinctrl_setting *setting, *setting2;
+	struct pinctrl_state *old_state = p->state;
 	int ret;
 
 	if (p->state == state)
@@ -888,7 +939,7 @@ static int pinctrl_select_state_locked(struct pinctrl *p,
 		}
 	}
 
-	p->state = state;
+	p->state = NULL;
 
 	/* Apply all the settings for the new state */
 	list_for_each_entry(setting, &state->settings, node) {
@@ -904,13 +955,37 @@ static int pinctrl_select_state_locked(struct pinctrl *p,
 			ret = -EINVAL;
 			break;
 		}
-		if (ret < 0) {
-			/* FIXME: Difficult to return to prev state */
-			return ret;
-		}
+
+		if (ret < 0)
+			goto unapply_new_state;
 	}
 
+	p->state = state;
+
 	return 0;
+
+unapply_new_state:
+	dev_err(p->dev, "Error applying setting, reverse things back\n");
+
+	list_for_each_entry(setting2, &state->settings, node) {
+		if (&setting2->node == &setting->node)
+			break;
+		/*
+		 * All we can do here is pinmux_disable_setting.
+		 * That means that some pins are muxed differently now
+		 * than they were before applying the setting (We can't
+		 * "unmux a pin"!), but it's not a big deal since the pins
+		 * are free to be muxed by another apply_setting.
+		 */
+		if (setting2->type == PIN_MAP_TYPE_MUX_GROUP)
+			pinmux_disable_setting(setting2);
+	}
+
+	/* There's no infinite recursive loop here because p->state is NULL */
+	if (old_state)
+		pinctrl_select_state_locked(p, old_state);
+
+	return ret;
 }
 
 /**
@@ -979,9 +1054,8 @@ static int devm_pinctrl_match(struct device *dev, void *res, void *data)
  */
 void devm_pinctrl_put(struct pinctrl *p)
 {
-	WARN_ON(devres_destroy(p->dev, devm_pinctrl_release,
+	WARN_ON(devres_release(p->dev, devm_pinctrl_release,
 			       devm_pinctrl_match, p));
-	pinctrl_put(p);
 }
 EXPORT_SYMBOL_GPL(devm_pinctrl_put);
 
diff --git a/drivers/pinctrl/core.h b/drivers/pinctrl/core.h
index ee72f1f..6d3d400 100644
--- a/drivers/pinctrl/core.h
+++ b/drivers/pinctrl/core.h
@@ -72,7 +72,7 @@ struct pinctrl {
 
 /**
  * struct pinctrl_state - a pinctrl state for a device
- * @node: list not for struct pinctrl's @states field
+ * @node: list node for struct pinctrl's @states field
  * @name: the name of this state
  * @settings: a list of settings for this state
  */
diff --git a/drivers/pinctrl/devicetree.c b/drivers/pinctrl/devicetree.c
index fd40a11..c7b7cb4 100644
--- a/drivers/pinctrl/devicetree.c
+++ b/drivers/pinctrl/devicetree.c
@@ -41,7 +41,7 @@ static void dt_free_map(struct pinctrl_dev *pctldev,
 		     struct pinctrl_map *map, unsigned num_maps)
 {
 	if (pctldev) {
-		struct pinctrl_ops *ops = pctldev->desc->pctlops;
+		const struct pinctrl_ops *ops = pctldev->desc->pctlops;
 		ops->dt_free_map(pctldev, map, num_maps);
 	} else {
 		/* There is no pctldev for PIN_MAP_TYPE_DUMMY_STATE */
@@ -122,7 +122,7 @@ static int dt_to_map_one_config(struct pinctrl *p, const char *statename,
 {
 	struct device_node *np_pctldev;
 	struct pinctrl_dev *pctldev;
-	struct pinctrl_ops *ops;
+	const struct pinctrl_ops *ops;
 	int ret;
 	struct pinctrl_map *map;
 	unsigned num_maps;
diff --git a/drivers/pinctrl/mvebu/pinctrl-mvebu.c b/drivers/pinctrl/mvebu/pinctrl-mvebu.c
index 2d2f0a4..bb7ddb1 100644
--- a/drivers/pinctrl/mvebu/pinctrl-mvebu.c
+++ b/drivers/pinctrl/mvebu/pinctrl-mvebu.c
@@ -263,7 +263,7 @@ static void mvebu_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
 	return;
 }
 
-static struct pinconf_ops mvebu_pinconf_ops = {
+static const struct pinconf_ops mvebu_pinconf_ops = {
 	.pin_config_group_get = mvebu_pinconf_group_get,
 	.pin_config_group_set = mvebu_pinconf_group_set,
 	.pin_config_group_dbg_show = mvebu_pinconf_group_dbg_show,
@@ -369,7 +369,7 @@ static int mvebu_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
 	return -ENOTSUPP;
 }
 
-static struct pinmux_ops mvebu_pinmux_ops = {
+static const struct pinmux_ops mvebu_pinmux_ops = {
 	.get_functions_count = mvebu_pinmux_get_funcs_count,
 	.get_function_name = mvebu_pinmux_get_func_name,
 	.get_function_groups = mvebu_pinmux_get_groups,
@@ -470,7 +470,7 @@ static void mvebu_pinctrl_dt_free_map(struct pinctrl_dev *pctldev,
 	kfree(map);
 }
 
-static struct pinctrl_ops mvebu_pinctrl_ops = {
+static const struct pinctrl_ops mvebu_pinctrl_ops = {
 	.get_groups_count = mvebu_pinctrl_get_groups_count,
 	.get_group_name = mvebu_pinctrl_get_group_name,
 	.get_group_pins = mvebu_pinctrl_get_group_pins,
@@ -478,8 +478,12 @@ static struct pinctrl_ops mvebu_pinctrl_ops = {
 	.dt_free_map = mvebu_pinctrl_dt_free_map,
 };
 
-static int _add_function(struct mvebu_pinctrl_function *funcs, const char *name)
+static int _add_function(struct mvebu_pinctrl_function *funcs, int *funcsize,
+			const char *name)
 {
+	if (*funcsize <= 0)
+		return -EOVERFLOW;
+
 	while (funcs->num_groups) {
 		/* function already there */
 		if (strcmp(funcs->name, name) == 0) {
@@ -488,8 +492,12 @@ static int _add_function(struct mvebu_pinctrl_function *funcs, const char *name)
 		}
 		funcs++;
 	}
+
+	/* append new unique function */
 	funcs->name = name;
 	funcs->num_groups = 1;
+	(*funcsize)--;
+
 	return 0;
 }
 
@@ -497,12 +505,12 @@ static int mvebu_pinctrl_build_functions(struct platform_device *pdev,
 					 struct mvebu_pinctrl *pctl)
 {
 	struct mvebu_pinctrl_function *funcs;
-	int num = 0;
+	int num = 0, funcsize = pctl->desc.npins;
 	int n, s;
 
 	/* we allocate functions for number of pins and hope
-	 * there are less unique functions than pins available */
-	funcs = devm_kzalloc(&pdev->dev, pctl->desc.npins *
+	 * there are fewer unique functions than pins available */
+	funcs = devm_kzalloc(&pdev->dev, funcsize *
 			     sizeof(struct mvebu_pinctrl_function), GFP_KERNEL);
 	if (!funcs)
 		return -ENOMEM;
@@ -510,26 +518,27 @@ static int mvebu_pinctrl_build_functions(struct platform_device *pdev,
 	for (n = 0; n < pctl->num_groups; n++) {
 		struct mvebu_pinctrl_group *grp = &pctl->groups[n];
 		for (s = 0; s < grp->num_settings; s++) {
+			int ret;
+
 			/* skip unsupported settings on this variant */
 			if (pctl->variant &&
 			    !(pctl->variant & grp->settings[s].variant))
 				continue;
 
 			/* check for unique functions and count groups */
-			if (_add_function(funcs, grp->settings[s].name))
+			ret = _add_function(funcs, &funcsize,
+					    grp->settings[s].name);
+			if (ret == -EOVERFLOW)
+				dev_err(&pdev->dev,
+					"More functions than pins(%d)\n",
+					pctl->desc.npins);
+			if (ret < 0)
 				continue;
 
 			num++;
 		}
 	}
 
-	/* with the number of unique functions and it's groups known,
-	   reallocate functions and assign group names */
-	funcs = krealloc(funcs, num * sizeof(struct mvebu_pinctrl_function),
-			 GFP_KERNEL);
-	if (!funcs)
-		return -ENOMEM;
-
 	pctl->num_functions = num;
 	pctl->functions = funcs;
 
diff --git a/drivers/pinctrl/pinconf-generic.c b/drivers/pinctrl/pinconf-generic.c
index 06c304a..2ad5a8d 100644
--- a/drivers/pinctrl/pinconf-generic.c
+++ b/drivers/pinctrl/pinconf-generic.c
@@ -12,6 +12,7 @@
 #define pr_fmt(fmt) "generic pinconfig core: " fmt
 
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/init.h>
 #include <linux/device.h>
 #include <linux/slab.h>
@@ -33,7 +34,7 @@ struct pin_config_item {
 
 #define PCONFDUMP(a, b, c) { .param = a, .display = b, .format = c }
 
-struct pin_config_item conf_items[] = {
+static struct pin_config_item conf_items[] = {
 	PCONFDUMP(PIN_CONFIG_BIAS_DISABLE, "input bias disabled", NULL),
 	PCONFDUMP(PIN_CONFIG_BIAS_HIGH_IMPEDANCE, "input bias high impedance", NULL),
 	PCONFDUMP(PIN_CONFIG_BIAS_PULL_UP, "input bias pull up", NULL),
@@ -59,7 +60,7 @@ void pinconf_generic_dump_pin(struct pinctrl_dev *pctldev,
 	if (!ops->is_generic)
 		return;
 
-	for(i = 0; i < ARRAY_SIZE(conf_items); i++) {
+	for (i = 0; i < ARRAY_SIZE(conf_items); i++) {
 		unsigned long config;
 		int ret;
 
@@ -94,7 +95,7 @@ void pinconf_generic_dump_group(struct pinctrl_dev *pctldev,
 	if (!ops->is_generic)
 		return;
 
-	for(i = 0; i < ARRAY_SIZE(conf_items); i++) {
+	for (i = 0; i < ARRAY_SIZE(conf_items); i++) {
 		unsigned long config;
 		int ret;
 
@@ -120,4 +121,17 @@ void pinconf_generic_dump_group(struct pinctrl_dev *pctldev,
 	}
 }
 
+void pinconf_generic_dump_config(struct pinctrl_dev *pctldev,
+				 struct seq_file *s, unsigned long config)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(conf_items); i++) {
+		if (pinconf_to_config_param(config) != conf_items[i].param)
+			continue;
+		seq_printf(s, "%s: 0x%x", conf_items[i].display,
+			   pinconf_to_config_argument(config));
+	}
+}
+EXPORT_SYMBOL_GPL(pinconf_generic_dump_config);
 #endif
diff --git a/drivers/pinctrl/pinconf.c b/drivers/pinctrl/pinconf.c
index d611ecf..baee2cc 100644
--- a/drivers/pinctrl/pinconf.c
+++ b/drivers/pinctrl/pinconf.c
@@ -574,207 +574,6 @@ static const struct file_operations pinconf_groups_ops = {
 	.release	= single_release,
 };
 
-/* 32bit read/write ressources */
-#define MAX_NAME_LEN 16
-char dbg_pinname[MAX_NAME_LEN]; /* shared: name of the state of the pin*/
-char dbg_state_name[MAX_NAME_LEN]; /* shared: state of the pin*/
-static u32 dbg_config; /* shared: config to be read/set for the pin & state*/
-
-static int pinconf_dbg_pinname_print(struct seq_file *s, void *d)
-{
-	if (strlen(dbg_pinname))
-		seq_printf(s, "%s\n", dbg_pinname);
-	else
-		seq_printf(s, "No pin name set\n");
-	return 0;
-}
-
-static int pinconf_dbg_pinname_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, pinconf_dbg_pinname_print, inode->i_private);
-}
-
-static int pinconf_dbg_pinname_write(struct file *file,
-	const char __user *user_buf, size_t count, loff_t *ppos)
-{
-	int err;
-
-	if (count > MAX_NAME_LEN)
-		return -EINVAL;
-
-	err = sscanf(user_buf, "%15s", dbg_pinname);
-
-	if (err != 1)
-		return -EINVAL;
-
-	return count;
-}
-
-static const struct file_operations pinconf_dbg_pinname_fops = {
-	.open = pinconf_dbg_pinname_open,
-	.write = pinconf_dbg_pinname_write,
-	.read = seq_read,
-	.llseek = seq_lseek,
-	.release = single_release,
-	.owner = THIS_MODULE,
-};
-
-static int pinconf_dbg_state_print(struct seq_file *s, void *d)
-{
-	if (strlen(dbg_state_name))
-		seq_printf(s, "%s\n", dbg_state_name);
-	else
-		seq_printf(s, "No pin state set\n");
-	return 0;
-}
-
-static int pinconf_dbg_state_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, pinconf_dbg_state_print, inode->i_private);
-}
-
-static int pinconf_dbg_state_write(struct file *file,
-	const char __user *user_buf, size_t count, loff_t *ppos)
-{
-	int err;
-
-	if (count > MAX_NAME_LEN)
-		return -EINVAL;
-
-	err = sscanf(user_buf, "%15s", dbg_state_name);
-
-	if (err != 1)
-		return -EINVAL;
-
-	return count;
-}
-
-static const struct file_operations pinconf_dbg_pinstate_fops = {
-	.open = pinconf_dbg_state_open,
-	.write = pinconf_dbg_state_write,
-	.read = seq_read,
-	.llseek = seq_lseek,
-	.release = single_release,
-	.owner = THIS_MODULE,
-};
-
-/**
- * pinconf_dbg_config_print() - display the pinctrl config from the pinctrl
- * map, of a pin/state pair based on pinname and state that have been
- * selected with the debugfs entries pinconf-name and pinconf-state
- * @s: contains the 32bits config to be written
- * @d: not used
- */
-static int pinconf_dbg_config_print(struct seq_file *s, void *d)
-{
-	struct pinctrl_maps *maps_node;
-	struct pinctrl_map const *map;
-	struct pinctrl_dev *pctldev = NULL;
-	struct pinconf_ops *confops = NULL;
-	int i, j;
-	bool found = false;
-
-	mutex_lock(&pinctrl_mutex);
-
-	/* Parse the pinctrl map and look for the elected pin/state */
-	for_each_maps(maps_node, i, map) {
-		if (map->type != PIN_MAP_TYPE_CONFIGS_PIN)
-			continue;
-
-		if (strncmp(map->name, dbg_state_name, MAX_NAME_LEN) > 0)
-			continue;
-
-		for (j = 0; j < map->data.configs.num_configs; j++) {
-			if (0 == strncmp(map->data.configs.group_or_pin,
-						dbg_pinname, MAX_NAME_LEN)) {
-				/* We found the right pin / state, read the
-				 * config and store the pctldev */
-				dbg_config = map->data.configs.configs[j];
-				pctldev = get_pinctrl_dev_from_devname
-					(map->ctrl_dev_name);
-				found = true;
-				break;
-			}
-		}
-	}
-
-	mutex_unlock(&pinctrl_mutex);
-
-	if (found) {
-		seq_printf(s, "Config of %s in state %s: 0x%08X\n", dbg_pinname,
-				 dbg_state_name, dbg_config);
-
-		if (pctldev)
-			confops = pctldev->desc->confops;
-
-		if (confops && confops->pin_config_config_dbg_show)
-			confops->pin_config_config_dbg_show(pctldev,
-					s, dbg_config);
-	} else {
-		seq_printf(s, "No pin found for defined name/state\n");
-	}
-
-	return 0;
-}
-
-static int pinconf_dbg_config_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, pinconf_dbg_config_print, inode->i_private);
-}
-
-/**
- * pinconf_dbg_config_write() - overwrite the pinctrl config in thepinctrl
- * map, of a pin/state pair based on pinname and state that have been
- * selected with the debugfs entries pinconf-name and pinconf-state
- */
-static int pinconf_dbg_config_write(struct file *file,
-	const char __user *user_buf, size_t count, loff_t *ppos)
-{
-	int err;
-	unsigned long config;
-	struct pinctrl_maps *maps_node;
-	struct pinctrl_map const *map;
-	int i, j;
-
-	err = kstrtoul_from_user(user_buf, count, 0, &config);
-
-	if (err)
-		return err;
-
-	dbg_config = config;
-
-	mutex_lock(&pinctrl_mutex);
-
-	/* Parse the pinctrl map and look for the selected pin/state */
-	for_each_maps(maps_node, i, map) {
-		if (map->type != PIN_MAP_TYPE_CONFIGS_PIN)
-			continue;
-
-		if (strncmp(map->name, dbg_state_name, MAX_NAME_LEN) > 0)
-			continue;
-
-		/*  we found the right pin / state, so overwrite config */
-		for (j = 0; j < map->data.configs.num_configs; j++) {
-			if (strncmp(map->data.configs.group_or_pin, dbg_pinname,
-						MAX_NAME_LEN) == 0)
-				map->data.configs.configs[j] = dbg_config;
-		}
-	}
-
-	mutex_unlock(&pinctrl_mutex);
-
-	return count;
-}
-
-static const struct file_operations pinconf_dbg_pinconfig_fops = {
-	.open = pinconf_dbg_config_open,
-	.write = pinconf_dbg_config_write,
-	.read = seq_read,
-	.llseek = seq_lseek,
-	.release = single_release,
-	.owner = THIS_MODULE,
-};
-
 void pinconf_init_device_debugfs(struct dentry *devroot,
 			 struct pinctrl_dev *pctldev)
 {
@@ -782,12 +581,6 @@ void pinconf_init_device_debugfs(struct dentry *devroot,
 			    devroot, pctldev, &pinconf_pins_ops);
 	debugfs_create_file("pinconf-groups", S_IFREG | S_IRUGO,
 			    devroot, pctldev, &pinconf_groups_ops);
-	debugfs_create_file("pinconf-name", (S_IRUGO | S_IWUSR | S_IWGRP),
-			    devroot, pctldev, &pinconf_dbg_pinname_fops);
-	debugfs_create_file("pinconf-state",  (S_IRUGO | S_IWUSR | S_IWGRP),
-			    devroot, pctldev, &pinconf_dbg_pinstate_fops);
-	debugfs_create_file("pinconf-config",  (S_IRUGO | S_IWUSR | S_IWGRP),
-			    devroot, pctldev, &pinconf_dbg_pinconfig_fops);
 }
 
 #endif
diff --git a/drivers/pinctrl/pinconf.h b/drivers/pinctrl/pinconf.h
index bfda73d..92c7267 100644
--- a/drivers/pinctrl/pinconf.h
+++ b/drivers/pinctrl/pinconf.h
@@ -98,6 +98,8 @@ void pinconf_generic_dump_pin(struct pinctrl_dev *pctldev,
 void pinconf_generic_dump_group(struct pinctrl_dev *pctldev,
 			      struct seq_file *s, const char *gname);
 
+void pinconf_generic_dump_config(struct pinctrl_dev *pctldev,
+				 struct seq_file *s, unsigned long config);
 #else
 
 static inline void pinconf_generic_dump_pin(struct pinctrl_dev *pctldev,
@@ -114,4 +116,10 @@ static inline void pinconf_generic_dump_group(struct pinctrl_dev *pctldev,
 	return;
 }
 
+static inline void pinconf_generic_dump_config(struct pinctrl_dev *pctldev,
+					       struct seq_file *s,
+					       unsigned long config)
+{
+	return;
+}
 #endif
diff --git a/drivers/pinctrl/pinctrl-ab8505.c b/drivers/pinctrl/pinctrl-ab8505.c
index 3a4238e..8ae076a 100644
--- a/drivers/pinctrl/pinctrl-ab8505.c
+++ b/drivers/pinctrl/pinctrl-ab8505.c
@@ -284,7 +284,7 @@ struct alternate_functions ab8505_alternate_functions[AB8505_GPIO_MAX_NUMBER + 1
 
 	ALTERNATE_FUNCTIONS(9, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO9, bit 0 reserved */
 	ALTERNATE_FUNCTIONS(10,      1,      0, UNUSED, 1, 0, 0), /* GPIO10, altA and altB controlled by bit 0 */
-	ALTERNATE_FUNCTIONS(11,      2, UNUSED, UNUSED, 0, 0, 0), /* GPIO11, altA controlled by bit 2 */
+	ALTERNATE_FUNCTIONS(11,      2,      1, UNUSED, 0, 0, 0), /* GPIO11, altA controlled by bit 2 */
 	ALTERNATE_FUNCTIONS(12, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO12, bit3 reseved */
 	ALTERNATE_FUNCTIONS(13,      4,      3,      4, 1, 0, 2), /* GPIO13, altA altB and altC controlled by bit 3 and 4 */
 	ALTERNATE_FUNCTIONS(14,      5, UNUSED, UNUSED, 0, 0, 0), /* GPIO14, altA controlled by bit 5 */
diff --git a/drivers/pinctrl/pinctrl-ab9540.c b/drivers/pinctrl/pinctrl-ab9540.c
index 7610bd0..80f3173 100644
--- a/drivers/pinctrl/pinctrl-ab9540.c
+++ b/drivers/pinctrl/pinctrl-ab9540.c
@@ -393,7 +393,7 @@ struct alternate_functions ab9540alternate_functions[AB9540_GPIO_MAX_NUMBER + 1]
 	/* GPIOSEL2 - bits 0 and 3 are reserved */
 	ALTERNATE_FUNCTIONS(9, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO9 */
 	ALTERNATE_FUNCTIONS(10,      1,      0, UNUSED, 1, 0, 0), /* GPIO10, altA and altB controlled by bit 0 */
-	ALTERNATE_FUNCTIONS(11,      2, UNUSED, UNUSED, 0, 0, 0), /* GPIO11, altA controlled by bit 1 */
+	ALTERNATE_FUNCTIONS(11,      2,	     1, UNUSED, 0, 0, 0), /* GPIO11, altA controlled by bit 1 */
 	ALTERNATE_FUNCTIONS(12, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO12 */
 	ALTERNATE_FUNCTIONS(13,      4,      3,      4, 1, 0, 2), /* GPIO13, altA altB and altC controlled by bit 3 and 4 */
 	ALTERNATE_FUNCTIONS(14,      5, UNUSED, UNUSED, 0, 0, 0), /* GPIO14, altA controlled by bit 5 */
diff --git a/drivers/pinctrl/pinctrl-abx500.c b/drivers/pinctrl/pinctrl-abx500.c
index c542a97..0cf3fa4 100644
--- a/drivers/pinctrl/pinctrl-abx500.c
+++ b/drivers/pinctrl/pinctrl-abx500.c
@@ -656,7 +656,7 @@ static void abx500_gpio_disable_free(struct pinctrl_dev *pctldev,
 {
 }
 
-static struct pinmux_ops abx500_pinmux_ops = {
+static const struct pinmux_ops abx500_pinmux_ops = {
 	.get_functions_count = abx500_pmx_get_funcs_cnt,
 	.get_function_name = abx500_pmx_get_func_name,
 	.get_function_groups = abx500_pmx_get_func_groups,
@@ -704,7 +704,7 @@ static void abx500_pin_dbg_show(struct pinctrl_dev *pctldev,
 				 chip->base + offset - 1);
 }
 
-static struct pinctrl_ops abx500_pinctrl_ops = {
+static const struct pinctrl_ops abx500_pinctrl_ops = {
 	.get_groups_count = abx500_get_groups_cnt,
 	.get_group_name = abx500_get_group_name,
 	.get_group_pins = abx500_get_group_pins,
@@ -778,7 +778,7 @@ int abx500_pin_config_set(struct pinctrl_dev *pctldev,
 	return ret;
 }
 
-static struct pinconf_ops abx500_pinconf_ops = {
+static const struct pinconf_ops abx500_pinconf_ops = {
 	.pin_config_get = abx500_pin_config_get,
 	.pin_config_set = abx500_pin_config_set,
 };
@@ -834,6 +834,7 @@ static const struct of_device_id abx500_gpio_match[] = {
 	{ .compatible = "stericsson,ab8505-gpio", .data = (void *)PINCTRL_AB8505, },
 	{ .compatible = "stericsson,ab8540-gpio", .data = (void *)PINCTRL_AB8540, },
 	{ .compatible = "stericsson,ab9540-gpio", .data = (void *)PINCTRL_AB9540, },
+	{ }
 };
 
 static int abx500_gpio_probe(struct platform_device *pdev)
diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c
index efb7f10..5d7529e 100644
--- a/drivers/pinctrl/pinctrl-at91.c
+++ b/drivers/pinctrl/pinctrl-at91.c
@@ -18,6 +18,7 @@
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/irqdomain.h>
+#include <linux/irqchip/chained_irq.h>
 #include <linux/io.h>
 #include <linux/gpio.h>
 #include <linux/pinctrl/machine.h>
@@ -27,8 +28,6 @@
 /* Since we request GPIOs from ourself */
 #include <linux/pinctrl/consumer.h>
 
-#include <asm/mach/irq.h>
-
 #include <mach/hardware.h>
 #include <mach/at91_pio.h>
 
@@ -294,7 +293,7 @@ static void at91_dt_free_map(struct pinctrl_dev *pctldev,
 {
 }
 
-static struct pinctrl_ops at91_pctrl_ops = {
+static const struct pinctrl_ops at91_pctrl_ops = {
 	.get_groups_count	= at91_get_groups_count,
 	.get_group_name		= at91_get_group_name,
 	.get_group_pins		= at91_get_group_pins,
@@ -303,7 +302,7 @@ static struct pinctrl_ops at91_pctrl_ops = {
 	.dt_free_map		= at91_dt_free_map,
 };
 
-static void __iomem * pin_to_controller(struct at91_pinctrl *info,
+static void __iomem *pin_to_controller(struct at91_pinctrl *info,
 				 unsigned int bank)
 {
 	return gpio_chips[bank]->regbase;
@@ -501,7 +500,7 @@ static void at91_pin_dbg(const struct device *dev, const struct at91_pmx_pin *pi
 	}
 }
 
-static int pin_check_config(struct at91_pinctrl *info, const char* name,
+static int pin_check_config(struct at91_pinctrl *info, const char *name,
 			    int index, const struct at91_pmx_pin *pin)
 {
 	int mux;
@@ -579,7 +578,7 @@ static int at91_pmx_enable(struct pinctrl_dev *pctldev, unsigned selector,
 		pio = pin_to_controller(info, pin->bank);
 		mask = pin_to_mask(pin->pin);
 		at91_mux_disable_interrupt(pio, mask);
-		switch(pin->mux) {
+		switch (pin->mux) {
 		case AT91_MUX_GPIO:
 			at91_mux_gpio_enable(pio, mask, 1);
 			break;
@@ -696,7 +695,7 @@ static void at91_gpio_disable_free(struct pinctrl_dev *pctldev,
 	/* Set the pin to some default state, GPIO is usually default */
 }
 
-static struct pinmux_ops at91_pmx_ops = {
+static const struct pinmux_ops at91_pmx_ops = {
 	.get_functions_count	= at91_pmx_get_funcs_count,
 	.get_function_name	= at91_pmx_get_func_name,
 	.get_function_groups	= at91_pmx_get_groups,
@@ -776,7 +775,7 @@ static void at91_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
 {
 }
 
-static struct pinconf_ops at91_pinconf_ops = {
+static const struct pinconf_ops at91_pinconf_ops = {
 	.pin_config_get			= at91_pinconf_get,
 	.pin_config_set			= at91_pinconf_set,
 	.pin_config_dbg_show		= at91_pinconf_dbg_show,
@@ -812,7 +811,7 @@ static int at91_pinctrl_mux_mask(struct at91_pinctrl *info,
 {
 	int ret = 0;
 	int size;
-	const const __be32 *list;
+	const __be32 *list;
 
 	list = of_get_property(np, "atmel,mux-mask", &size);
 	if (!list) {
@@ -846,7 +845,7 @@ static int at91_pinctrl_parse_groups(struct device_node *np,
 {
 	struct at91_pmx_pin *pin;
 	int size;
-	const const __be32 *list;
+	const __be32 *list;
 	int i, j;
 
 	dev_dbg(info->dev, "group(%d): %s\n", index, np->name);
@@ -944,7 +943,7 @@ static int at91_pinctrl_probe_dt(struct platform_device *pdev,
 		return -ENODEV;
 
 	info->dev = &pdev->dev;
-	info->ops = (struct at91_pinctrl_mux_ops*)
+	info->ops = (struct at91_pinctrl_mux_ops *)
 		of_match_device(at91_pinctrl_of_match, &pdev->dev)->data;
 	at91_pinctrl_child_count(info, np);
 
@@ -1002,7 +1001,7 @@ static int at91_pinctrl_probe(struct platform_device *pdev)
 {
 	struct at91_pinctrl *info;
 	struct pinctrl_pin_desc *pdesc;
-	int ret, i, j ,k;
+	int ret, i, j, k;
 
 	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
 	if (!info)
@@ -1568,7 +1567,7 @@ static int at91_gpio_probe(struct platform_device *pdev)
 		goto err;
 	}
 
-	at91_chip->ops = (struct at91_pinctrl_mux_ops*)
+	at91_chip->ops = (struct at91_pinctrl_mux_ops *)
 		of_match_device(at91_gpio_of_match, &pdev->dev)->data;
 	at91_chip->pioc_virq = irq;
 	at91_chip->pioc_idx = alias_idx;
@@ -1605,7 +1604,8 @@ static int at91_gpio_probe(struct platform_device *pdev)
 			chip->ngpio = ngpio;
 	}
 
-	names = devm_kzalloc(&pdev->dev, sizeof(char*) * chip->ngpio, GFP_KERNEL);
+	names = devm_kzalloc(&pdev->dev, sizeof(char *) * chip->ngpio,
+			     GFP_KERNEL);
 
 	if (!names) {
 		ret = -ENOMEM;
@@ -1615,7 +1615,7 @@ static int at91_gpio_probe(struct platform_device *pdev)
 	for (i = 0; i < chip->ngpio; i++)
 		names[i] = kasprintf(GFP_KERNEL, "pio%c%d", alias_idx + 'A', i);
 
-	chip->names = (const char*const*)names;
+	chip->names = (const char *const *)names;
 
 	range = &at91_chip->range;
 	range->name = chip->label;
diff --git a/drivers/pinctrl/pinctrl-bcm2835.c b/drivers/pinctrl/pinctrl-bcm2835.c
index 4eb6d2c..f28d4b0 100644
--- a/drivers/pinctrl/pinctrl-bcm2835.c
+++ b/drivers/pinctrl/pinctrl-bcm2835.c
@@ -795,7 +795,7 @@ out:
 	return err;
 }
 
-static struct pinctrl_ops bcm2835_pctl_ops = {
+static const struct pinctrl_ops bcm2835_pctl_ops = {
 	.get_groups_count = bcm2835_pctl_get_groups_count,
 	.get_group_name = bcm2835_pctl_get_group_name,
 	.get_group_pins = bcm2835_pctl_get_group_pins,
@@ -872,7 +872,7 @@ static int bcm2835_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
 	return 0;
 }
 
-static struct pinmux_ops bcm2835_pmx_ops = {
+static const struct pinmux_ops bcm2835_pmx_ops = {
 	.get_functions_count = bcm2835_pmx_get_functions_count,
 	.get_function_name = bcm2835_pmx_get_function_name,
 	.get_function_groups = bcm2835_pmx_get_function_groups,
@@ -916,7 +916,7 @@ static int bcm2835_pinconf_set(struct pinctrl_dev *pctldev,
 	return 0;
 }
 
-static struct pinconf_ops bcm2835_pinconf_ops = {
+static const struct pinconf_ops bcm2835_pinconf_ops = {
 	.pin_config_get = bcm2835_pinconf_get,
 	.pin_config_set = bcm2835_pinconf_set,
 };
diff --git a/drivers/pinctrl/pinctrl-coh901.c b/drivers/pinctrl/pinctrl-coh901.c
index 8b7e7bc..edde3ac 100644
--- a/drivers/pinctrl/pinctrl-coh901.c
+++ b/drivers/pinctrl/pinctrl-coh901.c
@@ -318,13 +318,16 @@ static int u300_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
 	struct u300_gpio_port *port = NULL;
 	struct list_head *p;
 	int retirq;
+	bool found = false;
 
 	list_for_each(p, &gpio->port_list) {
 		port = list_entry(p, struct u300_gpio_port, node);
-		if (port->number == portno)
+		if (port->number == portno) {
+			found = true;
 			break;
+		}
 	}
-	if (port == NULL) {
+	if (!found) {
 		dev_err(gpio->dev, "could not locate port for GPIO %d IRQ\n",
 			offset);
 		return -EINVAL;
@@ -359,7 +362,7 @@ int u300_gpio_config_get(struct gpio_chip *chip,
 	drmode &= (U300_GPIO_PXPCR_PIN_MODE_MASK << ((offset & 0x07) << 1));
 	drmode >>= ((offset & 0x07) << 1);
 
-	switch(param) {
+	switch (param) {
 	case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
 		*config = 0;
 		if (biasmode)
diff --git a/drivers/pinctrl/pinctrl-exynos.c b/drivers/pinctrl/pinctrl-exynos.c
index 538b9dd..911c5e7 100644
--- a/drivers/pinctrl/pinctrl-exynos.c
+++ b/drivers/pinctrl/pinctrl-exynos.c
@@ -23,13 +23,12 @@
 #include <linux/interrupt.h>
 #include <linux/irqdomain.h>
 #include <linux/irq.h>
+#include <linux/irqchip/chained_irq.h>
 #include <linux/of_irq.h>
 #include <linux/io.h>
 #include <linux/slab.h>
 #include <linux/err.h>
 
-#include <asm/mach/irq.h>
-
 #include "pinctrl-samsung.h"
 #include "pinctrl-exynos.h"
 
@@ -677,3 +676,111 @@ struct samsung_pin_ctrl exynos4x12_pin_ctrl[] = {
 		.label		= "exynos4x12-gpio-ctrl3",
 	},
 };
+
+/* pin banks of exynos5250 pin-controller 0 */
+static struct samsung_pin_bank exynos5250_pin_banks0[] = {
+	EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpa0", 0x00),
+	EXYNOS_PIN_BANK_EINTG(6, 0x020, "gpa1", 0x04),
+	EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpa2", 0x08),
+	EXYNOS_PIN_BANK_EINTG(5, 0x060, "gpb0", 0x0c),
+	EXYNOS_PIN_BANK_EINTG(5, 0x080, "gpb1", 0x10),
+	EXYNOS_PIN_BANK_EINTG(4, 0x0A0, "gpb2", 0x14),
+	EXYNOS_PIN_BANK_EINTG(4, 0x0C0, "gpb3", 0x18),
+	EXYNOS_PIN_BANK_EINTG(7, 0x0E0, "gpc0", 0x1c),
+	EXYNOS_PIN_BANK_EINTG(4, 0x100, "gpc1", 0x20),
+	EXYNOS_PIN_BANK_EINTG(7, 0x120, "gpc2", 0x24),
+	EXYNOS_PIN_BANK_EINTG(7, 0x140, "gpc3", 0x28),
+	EXYNOS_PIN_BANK_EINTG(4, 0x160, "gpd0", 0x2c),
+	EXYNOS_PIN_BANK_EINTG(8, 0x180, "gpd1", 0x30),
+	EXYNOS_PIN_BANK_EINTG(7, 0x2E0, "gpc4", 0x34),
+	EXYNOS_PIN_BANK_EINTN(6, 0x1A0, "gpy0"),
+	EXYNOS_PIN_BANK_EINTN(4, 0x1C0, "gpy1"),
+	EXYNOS_PIN_BANK_EINTN(6, 0x1E0, "gpy2"),
+	EXYNOS_PIN_BANK_EINTN(8, 0x200, "gpy3"),
+	EXYNOS_PIN_BANK_EINTN(8, 0x220, "gpy4"),
+	EXYNOS_PIN_BANK_EINTN(8, 0x240, "gpy5"),
+	EXYNOS_PIN_BANK_EINTN(8, 0x260, "gpy6"),
+	EXYNOS_PIN_BANK_EINTW(8, 0xC00, "gpx0", 0x00),
+	EXYNOS_PIN_BANK_EINTW(8, 0xC20, "gpx1", 0x04),
+	EXYNOS_PIN_BANK_EINTW(8, 0xC40, "gpx2", 0x08),
+	EXYNOS_PIN_BANK_EINTW(8, 0xC60, "gpx3", 0x0c),
+};
+
+/* pin banks of exynos5250 pin-controller 1 */
+static struct samsung_pin_bank exynos5250_pin_banks1[] = {
+	EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpe0", 0x00),
+	EXYNOS_PIN_BANK_EINTG(2, 0x020, "gpe1", 0x04),
+	EXYNOS_PIN_BANK_EINTG(4, 0x040, "gpf0", 0x08),
+	EXYNOS_PIN_BANK_EINTG(4, 0x060, "gpf1", 0x0c),
+	EXYNOS_PIN_BANK_EINTG(8, 0x080, "gpg0", 0x10),
+	EXYNOS_PIN_BANK_EINTG(8, 0x0A0, "gpg1", 0x14),
+	EXYNOS_PIN_BANK_EINTG(2, 0x0C0, "gpg2", 0x18),
+	EXYNOS_PIN_BANK_EINTG(4, 0x0E0, "gph0", 0x1c),
+	EXYNOS_PIN_BANK_EINTG(8, 0x100, "gph1", 0x20),
+};
+
+/* pin banks of exynos5250 pin-controller 2 */
+static struct samsung_pin_bank exynos5250_pin_banks2[] = {
+	EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpv0", 0x00),
+	EXYNOS_PIN_BANK_EINTG(8, 0x020, "gpv1", 0x04),
+	EXYNOS_PIN_BANK_EINTG(8, 0x060, "gpv2", 0x08),
+	EXYNOS_PIN_BANK_EINTG(8, 0x080, "gpv3", 0x0c),
+	EXYNOS_PIN_BANK_EINTG(2, 0x0C0, "gpv4", 0x10),
+};
+
+/* pin banks of exynos5250 pin-controller 3 */
+static struct samsung_pin_bank exynos5250_pin_banks3[] = {
+	EXYNOS_PIN_BANK_EINTG(7, 0x000, "gpz", 0x00),
+};
+
+/*
+ * Samsung pinctrl driver data for Exynos5250 SoC. Exynos5250 SoC includes
+ * four gpio/pin-mux/pinconfig controllers.
+ */
+struct samsung_pin_ctrl exynos5250_pin_ctrl[] = {
+	{
+		/* pin-controller instance 0 data */
+		.pin_banks	= exynos5250_pin_banks0,
+		.nr_banks	= ARRAY_SIZE(exynos5250_pin_banks0),
+		.geint_con	= EXYNOS_GPIO_ECON_OFFSET,
+		.geint_mask	= EXYNOS_GPIO_EMASK_OFFSET,
+		.geint_pend	= EXYNOS_GPIO_EPEND_OFFSET,
+		.weint_con	= EXYNOS_WKUP_ECON_OFFSET,
+		.weint_mask	= EXYNOS_WKUP_EMASK_OFFSET,
+		.weint_pend	= EXYNOS_WKUP_EPEND_OFFSET,
+		.svc		= EXYNOS_SVC_OFFSET,
+		.eint_gpio_init = exynos_eint_gpio_init,
+		.eint_wkup_init = exynos_eint_wkup_init,
+		.label		= "exynos5250-gpio-ctrl0",
+	}, {
+		/* pin-controller instance 1 data */
+		.pin_banks	= exynos5250_pin_banks1,
+		.nr_banks	= ARRAY_SIZE(exynos5250_pin_banks1),
+		.geint_con	= EXYNOS_GPIO_ECON_OFFSET,
+		.geint_mask	= EXYNOS_GPIO_EMASK_OFFSET,
+		.geint_pend	= EXYNOS_GPIO_EPEND_OFFSET,
+		.svc		= EXYNOS_SVC_OFFSET,
+		.eint_gpio_init = exynos_eint_gpio_init,
+		.label		= "exynos5250-gpio-ctrl1",
+	}, {
+		/* pin-controller instance 2 data */
+		.pin_banks	= exynos5250_pin_banks2,
+		.nr_banks	= ARRAY_SIZE(exynos5250_pin_banks2),
+		.geint_con	= EXYNOS_GPIO_ECON_OFFSET,
+		.geint_mask	= EXYNOS_GPIO_EMASK_OFFSET,
+		.geint_pend	= EXYNOS_GPIO_EPEND_OFFSET,
+		.svc		= EXYNOS_SVC_OFFSET,
+		.eint_gpio_init = exynos_eint_gpio_init,
+		.label		= "exynos5250-gpio-ctrl2",
+	}, {
+		/* pin-controller instance 3 data */
+		.pin_banks	= exynos5250_pin_banks3,
+		.nr_banks	= ARRAY_SIZE(exynos5250_pin_banks3),
+		.geint_con	= EXYNOS_GPIO_ECON_OFFSET,
+		.geint_mask	= EXYNOS_GPIO_EMASK_OFFSET,
+		.geint_pend	= EXYNOS_GPIO_EPEND_OFFSET,
+		.svc		= EXYNOS_SVC_OFFSET,
+		.eint_gpio_init = exynos_eint_gpio_init,
+		.label		= "exynos5250-gpio-ctrl3",
+	},
+};
diff --git a/drivers/pinctrl/pinctrl-exynos5440.c b/drivers/pinctrl/pinctrl-exynos5440.c
index 1376eb7..eb8e502 100644
--- a/drivers/pinctrl/pinctrl-exynos5440.c
+++ b/drivers/pinctrl/pinctrl-exynos5440.c
@@ -286,7 +286,7 @@ static void exynos5440_dt_free_map(struct pinctrl_dev *pctldev,
 }
 
 /* list of pinctrl callbacks for the pinctrl core */
-static struct pinctrl_ops exynos5440_pctrl_ops = {
+static const struct pinctrl_ops exynos5440_pctrl_ops = {
 	.get_groups_count	= exynos5440_get_group_count,
 	.get_group_name		= exynos5440_get_group_name,
 	.get_group_pins		= exynos5440_get_group_pins,
@@ -374,7 +374,7 @@ static int exynos5440_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
 }
 
 /* list of pinmux callbacks for the pinmux vertical in pinctrl core */
-static struct pinmux_ops exynos5440_pinmux_ops = {
+static const struct pinmux_ops exynos5440_pinmux_ops = {
 	.get_functions_count	= exynos5440_get_functions_count,
 	.get_function_name	= exynos5440_pinmux_get_fname,
 	.get_function_groups	= exynos5440_pinmux_get_groups,
@@ -523,7 +523,7 @@ static int exynos5440_pinconf_group_get(struct pinctrl_dev *pctldev,
 }
 
 /* list of pinconfig callbacks for pinconfig vertical in the pinctrl code */
-static struct pinconf_ops exynos5440_pinconf_ops = {
+static const struct pinconf_ops exynos5440_pinconf_ops = {
 	.pin_config_get		= exynos5440_pinconf_get,
 	.pin_config_set		= exynos5440_pinconf_set,
 	.pin_config_group_get	= exynos5440_pinconf_group_get,
@@ -854,7 +854,7 @@ static int exynos5440_pinctrl_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
-	priv = devm_kzalloc(dev, sizeof(priv), GFP_KERNEL);
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
 	if (!priv) {
 		dev_err(dev, "could not allocate memory for private data\n");
 		return -ENOMEM;
diff --git a/drivers/pinctrl/pinctrl-falcon.c b/drivers/pinctrl/pinctrl-falcon.c
index af97a1f..f9b2a1d 100644
--- a/drivers/pinctrl/pinctrl-falcon.c
+++ b/drivers/pinctrl/pinctrl-falcon.c
@@ -353,7 +353,7 @@ static void falcon_pinconf_group_dbg_show(struct pinctrl_dev *pctrldev,
 {
 }
 
-static struct pinconf_ops falcon_pinconf_ops = {
+static const struct pinconf_ops falcon_pinconf_ops = {
 	.pin_config_get			= falcon_pinconf_get,
 	.pin_config_set			= falcon_pinconf_set,
 	.pin_config_group_get		= falcon_pinconf_group_get,
diff --git a/drivers/pinctrl/pinctrl-imx.c b/drivers/pinctrl/pinctrl-imx.c
index 4cebb9c..02ef523 100644
--- a/drivers/pinctrl/pinctrl-imx.c
+++ b/drivers/pinctrl/pinctrl-imx.c
@@ -54,32 +54,6 @@ struct imx_pinctrl {
 	const struct imx_pinctrl_soc_info *info;
 };
 
-static const struct imx_pin_reg *imx_find_pin_reg(
-				const struct imx_pinctrl_soc_info *info,
-				unsigned pin, bool is_mux, unsigned mux)
-{
-	const struct imx_pin_reg *pin_reg = NULL;
-	int i;
-
-	for (i = 0; i < info->npin_regs; i++) {
-		pin_reg = &info->pin_regs[i];
-		if (pin_reg->pid != pin)
-			continue;
-		if (!is_mux)
-			break;
-		else if (pin_reg->mux_mode == (mux & IMX_MUX_MASK))
-			break;
-	}
-
-	if (i == info->npin_regs) {
-		dev_err(info->dev, "Pin(%s): unable to find pin reg map\n",
-			info->pins[pin].name);
-		return NULL;
-	}
-
-	return pin_reg;
-}
-
 static const inline struct imx_pin_group *imx_pinctrl_find_group_by_name(
 				const struct imx_pinctrl_soc_info *info,
 				const char *name)
@@ -207,7 +181,7 @@ static void imx_dt_free_map(struct pinctrl_dev *pctldev,
 	kfree(map);
 }
 
-static struct pinctrl_ops imx_pctrl_ops = {
+static const struct pinctrl_ops imx_pctrl_ops = {
 	.get_groups_count = imx_get_groups_count,
 	.get_group_name = imx_get_group_name,
 	.get_group_pins = imx_get_group_pins,
@@ -223,7 +197,7 @@ static int imx_pmx_enable(struct pinctrl_dev *pctldev, unsigned selector,
 	struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
 	const struct imx_pinctrl_soc_info *info = ipctl->info;
 	const struct imx_pin_reg *pin_reg;
-	const unsigned *pins, *mux;
+	const unsigned *pins, *mux, *input_val;
 	unsigned int npins, pin_id;
 	int i;
 
@@ -234,18 +208,16 @@ static int imx_pmx_enable(struct pinctrl_dev *pctldev, unsigned selector,
 	pins = info->groups[group].pins;
 	npins = info->groups[group].npins;
 	mux = info->groups[group].mux_mode;
+	input_val = info->groups[group].input_val;
 
-	WARN_ON(!pins || !npins || !mux);
+	WARN_ON(!pins || !npins || !mux || !input_val);
 
 	dev_dbg(ipctl->dev, "enable function %s group %s\n",
 		info->functions[selector].name, info->groups[group].name);
 
 	for (i = 0; i < npins; i++) {
 		pin_id = pins[i];
-
-		pin_reg = imx_find_pin_reg(info, pin_id, 1, mux[i]);
-		if (!pin_reg)
-			return -EINVAL;
+		pin_reg = &info->pin_regs[pin_id];
 
 		if (!pin_reg->mux_reg) {
 			dev_err(ipctl->dev, "Pin(%s) does not support mux function\n",
@@ -259,10 +231,10 @@ static int imx_pmx_enable(struct pinctrl_dev *pctldev, unsigned selector,
 
 		/* some pins also need select input setting, set it if found */
 		if (pin_reg->input_reg) {
-			writel(pin_reg->input_val, ipctl->base + pin_reg->input_reg);
+			writel(input_val[i], ipctl->base + pin_reg->input_reg);
 			dev_dbg(ipctl->dev,
 				"==>select_input: offset 0x%x val 0x%x\n",
-				pin_reg->input_reg, pin_reg->input_val);
+				pin_reg->input_reg, input_val[i]);
 		}
 	}
 
@@ -299,7 +271,7 @@ static int imx_pmx_get_groups(struct pinctrl_dev *pctldev, unsigned selector,
 	return 0;
 }
 
-static struct pinmux_ops imx_pmx_ops = {
+static const struct pinmux_ops imx_pmx_ops = {
 	.get_functions_count = imx_pmx_get_funcs_count,
 	.get_function_name = imx_pmx_get_func_name,
 	.get_function_groups = imx_pmx_get_groups,
@@ -311,11 +283,7 @@ static int imx_pinconf_get(struct pinctrl_dev *pctldev,
 {
 	struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
 	const struct imx_pinctrl_soc_info *info = ipctl->info;
-	const struct imx_pin_reg *pin_reg;
-
-	pin_reg = imx_find_pin_reg(info, pin_id, 0, 0);
-	if (!pin_reg)
-		return -EINVAL;
+	const struct imx_pin_reg *pin_reg = &info->pin_regs[pin_id];
 
 	if (!pin_reg->conf_reg) {
 		dev_err(info->dev, "Pin(%s) does not support config function\n",
@@ -333,11 +301,7 @@ static int imx_pinconf_set(struct pinctrl_dev *pctldev,
 {
 	struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
 	const struct imx_pinctrl_soc_info *info = ipctl->info;
-	const struct imx_pin_reg *pin_reg;
-
-	pin_reg = imx_find_pin_reg(info, pin_id, 0, 0);
-	if (!pin_reg)
-		return -EINVAL;
+	const struct imx_pin_reg *pin_reg = &info->pin_regs[pin_id];
 
 	if (!pin_reg->conf_reg) {
 		dev_err(info->dev, "Pin(%s) does not support config function\n",
@@ -360,10 +324,9 @@ static void imx_pinconf_dbg_show(struct pinctrl_dev *pctldev,
 {
 	struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
 	const struct imx_pinctrl_soc_info *info = ipctl->info;
-	const struct imx_pin_reg *pin_reg;
+	const struct imx_pin_reg *pin_reg = &info->pin_regs[pin_id];
 	unsigned long config;
 
-	pin_reg = imx_find_pin_reg(info, pin_id, 0, 0);
 	if (!pin_reg || !pin_reg->conf_reg) {
 		seq_printf(s, "N/A");
 		return;
@@ -397,7 +360,7 @@ static void imx_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
 	}
 }
 
-static struct pinconf_ops imx_pinconf_ops = {
+static const struct pinconf_ops imx_pinconf_ops = {
 	.pin_config_get = imx_pinconf_get,
 	.pin_config_set = imx_pinconf_set,
 	.pin_config_dbg_show = imx_pinconf_dbg_show,
@@ -411,29 +374,20 @@ static struct pinctrl_desc imx_pinctrl_desc = {
 	.owner = THIS_MODULE,
 };
 
-/* decode pin id and mux from pin function id got from device tree*/
-static int imx_pinctrl_get_pin_id_and_mux(const struct imx_pinctrl_soc_info *info,
-				unsigned int pin_func_id, unsigned int *pin_id,
-				unsigned int *mux)
-{
-	if (pin_func_id > info->npin_regs)
-		return -EINVAL;
-
-	*pin_id = info->pin_regs[pin_func_id].pid;
-	*mux = info->pin_regs[pin_func_id].mux_mode;
-
-	return 0;
-}
+/*
+ * Each pin represented in fsl,pins consists of 5 u32 PIN_FUNC_ID and
+ * 1 u32 CONFIG, so 24 types in total for each pin.
+ */
+#define FSL_PIN_SIZE 24
 
 static int imx_pinctrl_parse_groups(struct device_node *np,
 				    struct imx_pin_group *grp,
 				    struct imx_pinctrl_soc_info *info,
 				    u32 index)
 {
-	unsigned int pin_func_id;
-	int ret, size;
+	int size;
 	const __be32 *list;
-	int i, j;
+	int i;
 	u32 config;
 
 	dev_dbg(info->dev, "group(%d): %s\n", index, np->name);
@@ -447,32 +401,38 @@ static int imx_pinctrl_parse_groups(struct device_node *np,
 	 */
 	list = of_get_property(np, "fsl,pins", &size);
 	/* we do not check return since it's safe node passed down */
-	size /= sizeof(*list);
-	if (!size || size % 2) {
-		dev_err(info->dev, "wrong pins number or pins and configs should be pairs\n");
+	if (!size || size % FSL_PIN_SIZE) {
+		dev_err(info->dev, "Invalid fsl,pins property\n");
 		return -EINVAL;
 	}
 
-	grp->npins = size / 2;
+	grp->npins = size / FSL_PIN_SIZE;
 	grp->pins = devm_kzalloc(info->dev, grp->npins * sizeof(unsigned int),
 				GFP_KERNEL);
 	grp->mux_mode = devm_kzalloc(info->dev, grp->npins * sizeof(unsigned int),
 				GFP_KERNEL);
+	grp->input_val = devm_kzalloc(info->dev, grp->npins * sizeof(unsigned int),
+				GFP_KERNEL);
 	grp->configs = devm_kzalloc(info->dev, grp->npins * sizeof(unsigned long),
 				GFP_KERNEL);
-	for (i = 0, j = 0; i < size; i += 2, j++) {
-		pin_func_id = be32_to_cpu(*list++);
-		ret = imx_pinctrl_get_pin_id_and_mux(info, pin_func_id,
-					&grp->pins[j], &grp->mux_mode[j]);
-		if (ret) {
-			dev_err(info->dev, "get invalid pin function id\n");
-			return -EINVAL;
-		}
+	for (i = 0; i < grp->npins; i++) {
+		u32 mux_reg = be32_to_cpu(*list++);
+		u32 conf_reg = be32_to_cpu(*list++);
+		unsigned int pin_id = mux_reg ? mux_reg / 4 : conf_reg / 4;
+		struct imx_pin_reg *pin_reg = &info->pin_regs[pin_id];
+
+		grp->pins[i] = pin_id;
+		pin_reg->mux_reg = mux_reg;
+		pin_reg->conf_reg = conf_reg;
+		pin_reg->input_reg = be32_to_cpu(*list++);
+		grp->mux_mode[i] = be32_to_cpu(*list++);
+		grp->input_val[i] = be32_to_cpu(*list++);
+
 		/* SION bit is in mux register */
 		config = be32_to_cpu(*list++);
 		if (config & IMX_PAD_SION)
-			grp->mux_mode[j] |= IOMUXC_CONFIG_SION;
-		grp->configs[j] = config & ~IMX_PAD_SION;
+			grp->mux_mode[i] |= IOMUXC_CONFIG_SION;
+		grp->configs[i] = config & ~IMX_PAD_SION;
 	}
 
 #ifdef DEBUG
@@ -568,8 +528,7 @@ int imx_pinctrl_probe(struct platform_device *pdev,
 	struct resource *res;
 	int ret;
 
-	if (!info || !info->pins || !info->npins
-		  || !info->pin_regs || !info->npin_regs) {
+	if (!info || !info->pins || !info->npins) {
 		dev_err(&pdev->dev, "wrong pinctrl info\n");
 		return -EINVAL;
 	}
@@ -580,6 +539,11 @@ int imx_pinctrl_probe(struct platform_device *pdev,
 	if (!ipctl)
 		return -ENOMEM;
 
+	info->pin_regs = devm_kzalloc(&pdev->dev, sizeof(*info->pin_regs) *
+				      info->npins, GFP_KERNEL);
+	if (!info->pin_regs)
+		return -ENOMEM;
+
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res)
 		return -ENOENT;
diff --git a/drivers/pinctrl/pinctrl-imx.h b/drivers/pinctrl/pinctrl-imx.h
index 9b65e78..4749b0a 100644
--- a/drivers/pinctrl/pinctrl-imx.h
+++ b/drivers/pinctrl/pinctrl-imx.h
@@ -26,6 +26,8 @@ struct platform_device;
  *	elements in .pins so we can iterate over that array
  * @mux_mode: the mux mode for each pin in this group. The size of this
  *	array is the same as pins.
+ * @input_val: the select input value for each pin in this group. The size of
+ *	this array is the same as pins.
  * @configs: the config for each pin in this group. The size of this
  *	array is the same as pins.
  */
@@ -34,6 +36,7 @@ struct imx_pin_group {
 	unsigned int *pins;
 	unsigned npins;
 	unsigned int *mux_mode;
+	unsigned int *input_val;
 	unsigned long *configs;
 };
 
@@ -51,30 +54,22 @@ struct imx_pmx_func {
 
 /**
  * struct imx_pin_reg - describe a pin reg map
- * The last 3 members are used for select input setting
- * @pid: pin id
  * @mux_reg: mux register offset
  * @conf_reg: config register offset
- * @mux_mode: mux mode
  * @input_reg: select input register offset for this mux if any
  *  0 if no select input setting needed.
- * @input_val: the value set to select input register
  */
 struct imx_pin_reg {
-	u16 pid;
 	u16 mux_reg;
 	u16 conf_reg;
-	u8 mux_mode;
 	u16 input_reg;
-	u8 input_val;
 };
 
 struct imx_pinctrl_soc_info {
 	struct device *dev;
 	const struct pinctrl_pin_desc *pins;
 	unsigned int npins;
-	const struct imx_pin_reg *pin_regs;
-	unsigned int npin_regs;
+	struct imx_pin_reg *pin_regs;
 	struct imx_pin_group *groups;
 	unsigned int ngroups;
 	struct imx_pmx_func *functions;
diff --git a/drivers/pinctrl/pinctrl-imx35.c b/drivers/pinctrl/pinctrl-imx35.c
index 6e21411..51af329 100644
--- a/drivers/pinctrl/pinctrl-imx35.c
+++ b/drivers/pinctrl/pinctrl-imx35.c
@@ -24,1245 +24,289 @@
 #include "pinctrl-imx.h"
 
 enum imx35_pads {
-	MX35_PAD_CAPTURE = 0,
-	MX35_PAD_COMPARE = 1,
-	MX35_PAD_WDOG_RST = 2,
-	MX35_PAD_GPIO1_0 = 3,
-	MX35_PAD_GPIO1_1 = 4,
-	MX35_PAD_GPIO2_0 = 5,
-	MX35_PAD_GPIO3_0 = 6,
-	MX35_PAD_RESET_IN_B = 7,
-	MX35_PAD_POR_B = 8,
-	MX35_PAD_CLKO = 9,
-	MX35_PAD_BOOT_MODE0 = 10,
-	MX35_PAD_BOOT_MODE1 = 11,
-	MX35_PAD_CLK_MODE0 = 12,
-	MX35_PAD_CLK_MODE1 = 13,
-	MX35_PAD_POWER_FAIL = 14,
-	MX35_PAD_VSTBY = 15,
-	MX35_PAD_A0 = 16,
-	MX35_PAD_A1 = 17,
-	MX35_PAD_A2 = 18,
-	MX35_PAD_A3 = 19,
-	MX35_PAD_A4 = 20,
-	MX35_PAD_A5 = 21,
-	MX35_PAD_A6 = 22,
-	MX35_PAD_A7 = 23,
-	MX35_PAD_A8 = 24,
-	MX35_PAD_A9 = 25,
-	MX35_PAD_A10 = 26,
-	MX35_PAD_MA10 = 27,
-	MX35_PAD_A11 = 28,
-	MX35_PAD_A12 = 29,
-	MX35_PAD_A13 = 30,
-	MX35_PAD_A14 = 31,
-	MX35_PAD_A15 = 32,
-	MX35_PAD_A16 = 33,
-	MX35_PAD_A17 = 34,
-	MX35_PAD_A18 = 35,
-	MX35_PAD_A19 = 36,
-	MX35_PAD_A20 = 37,
-	MX35_PAD_A21 = 38,
-	MX35_PAD_A22 = 39,
-	MX35_PAD_A23 = 40,
-	MX35_PAD_A24 = 41,
-	MX35_PAD_A25 = 42,
-	MX35_PAD_SDBA1 = 43,
-	MX35_PAD_SDBA0 = 44,
-	MX35_PAD_SD0 = 45,
-	MX35_PAD_SD1 = 46,
-	MX35_PAD_SD2 = 47,
-	MX35_PAD_SD3 = 48,
-	MX35_PAD_SD4 = 49,
-	MX35_PAD_SD5 = 50,
-	MX35_PAD_SD6 = 51,
-	MX35_PAD_SD7 = 52,
-	MX35_PAD_SD8 = 53,
-	MX35_PAD_SD9 = 54,
-	MX35_PAD_SD10 = 55,
-	MX35_PAD_SD11 = 56,
-	MX35_PAD_SD12 = 57,
-	MX35_PAD_SD13 = 58,
-	MX35_PAD_SD14 = 59,
-	MX35_PAD_SD15 = 60,
-	MX35_PAD_SD16 = 61,
-	MX35_PAD_SD17 = 62,
-	MX35_PAD_SD18 = 63,
-	MX35_PAD_SD19 = 64,
-	MX35_PAD_SD20 = 65,
-	MX35_PAD_SD21 = 66,
-	MX35_PAD_SD22 = 67,
-	MX35_PAD_SD23 = 68,
-	MX35_PAD_SD24 = 69,
-	MX35_PAD_SD25 = 70,
-	MX35_PAD_SD26 = 71,
-	MX35_PAD_SD27 = 72,
-	MX35_PAD_SD28 = 73,
-	MX35_PAD_SD29 = 74,
-	MX35_PAD_SD30 = 75,
-	MX35_PAD_SD31 = 76,
-	MX35_PAD_DQM0 = 77,
-	MX35_PAD_DQM1 = 78,
-	MX35_PAD_DQM2 = 79,
-	MX35_PAD_DQM3 = 80,
-	MX35_PAD_EB0 = 81,
-	MX35_PAD_EB1 = 82,
-	MX35_PAD_OE = 83,
-	MX35_PAD_CS0 = 84,
-	MX35_PAD_CS1 = 85,
-	MX35_PAD_CS2 = 86,
-	MX35_PAD_CS3 = 87,
-	MX35_PAD_CS4 = 88,
-	MX35_PAD_CS5 = 89,
-	MX35_PAD_NF_CE0 = 90,
-	MX35_PAD_ECB = 91,
-	MX35_PAD_LBA = 92,
-	MX35_PAD_BCLK = 93,
-	MX35_PAD_RW = 94,
-	MX35_PAD_RAS = 95,
-	MX35_PAD_CAS = 96,
-	MX35_PAD_SDWE = 97,
-	MX35_PAD_SDCKE0 = 98,
-	MX35_PAD_SDCKE1 = 99,
-	MX35_PAD_SDCLK = 100,
-	MX35_PAD_SDQS0 = 101,
-	MX35_PAD_SDQS1 = 102,
-	MX35_PAD_SDQS2 = 103,
-	MX35_PAD_SDQS3 = 104,
-	MX35_PAD_NFWE_B = 105,
-	MX35_PAD_NFRE_B = 106,
-	MX35_PAD_NFALE = 107,
-	MX35_PAD_NFCLE = 108,
-	MX35_PAD_NFWP_B = 109,
-	MX35_PAD_NFRB = 110,
-	MX35_PAD_D15 = 111,
-	MX35_PAD_D14 = 112,
-	MX35_PAD_D13 = 113,
-	MX35_PAD_D12 = 114,
-	MX35_PAD_D11 = 115,
-	MX35_PAD_D10 = 116,
-	MX35_PAD_D9 = 117,
-	MX35_PAD_D8 = 118,
-	MX35_PAD_D7 = 119,
-	MX35_PAD_D6 = 120,
-	MX35_PAD_D5 = 121,
-	MX35_PAD_D4 = 122,
-	MX35_PAD_D3 = 123,
-	MX35_PAD_D2 = 124,
-	MX35_PAD_D1 = 125,
-	MX35_PAD_D0 = 126,
-	MX35_PAD_CSI_D8 = 127,
-	MX35_PAD_CSI_D9 = 128,
-	MX35_PAD_CSI_D10 = 129,
-	MX35_PAD_CSI_D11 = 130,
-	MX35_PAD_CSI_D12 = 131,
-	MX35_PAD_CSI_D13 = 132,
-	MX35_PAD_CSI_D14 = 133,
-	MX35_PAD_CSI_D15 = 134,
-	MX35_PAD_CSI_MCLK = 135,
-	MX35_PAD_CSI_VSYNC = 136,
-	MX35_PAD_CSI_HSYNC = 137,
-	MX35_PAD_CSI_PIXCLK = 138,
-	MX35_PAD_I2C1_CLK = 139,
-	MX35_PAD_I2C1_DAT = 140,
-	MX35_PAD_I2C2_CLK = 141,
-	MX35_PAD_I2C2_DAT = 142,
-	MX35_PAD_STXD4 = 143,
-	MX35_PAD_SRXD4 = 144,
-	MX35_PAD_SCK4 = 145,
-	MX35_PAD_STXFS4 = 146,
-	MX35_PAD_STXD5 = 147,
-	MX35_PAD_SRXD5 = 148,
-	MX35_PAD_SCK5 = 149,
-	MX35_PAD_STXFS5 = 150,
-	MX35_PAD_SCKR = 151,
-	MX35_PAD_FSR = 152,
-	MX35_PAD_HCKR = 153,
-	MX35_PAD_SCKT = 154,
-	MX35_PAD_FST = 155,
-	MX35_PAD_HCKT = 156,
-	MX35_PAD_TX5_RX0 = 157,
-	MX35_PAD_TX4_RX1 = 158,
-	MX35_PAD_TX3_RX2 = 159,
-	MX35_PAD_TX2_RX3 = 160,
-	MX35_PAD_TX1 = 161,
-	MX35_PAD_TX0 = 162,
-	MX35_PAD_CSPI1_MOSI = 163,
-	MX35_PAD_CSPI1_MISO = 164,
-	MX35_PAD_CSPI1_SS0 = 165,
-	MX35_PAD_CSPI1_SS1 = 166,
-	MX35_PAD_CSPI1_SCLK = 167,
-	MX35_PAD_CSPI1_SPI_RDY = 168,
-	MX35_PAD_RXD1 = 169,
-	MX35_PAD_TXD1 = 170,
-	MX35_PAD_RTS1 = 171,
-	MX35_PAD_CTS1 = 172,
-	MX35_PAD_RXD2 = 173,
-	MX35_PAD_TXD2 = 174,
-	MX35_PAD_RTS2 = 175,
-	MX35_PAD_CTS2 = 176,
-	MX35_PAD_RTCK = 177,
-	MX35_PAD_TCK = 178,
-	MX35_PAD_TMS = 179,
-	MX35_PAD_TDI = 180,
-	MX35_PAD_TDO = 181,
-	MX35_PAD_TRSTB = 182,
-	MX35_PAD_DE_B = 183,
-	MX35_PAD_SJC_MOD = 184,
-	MX35_PAD_USBOTG_PWR = 185,
-	MX35_PAD_USBOTG_OC = 186,
-	MX35_PAD_LD0 = 187,
-	MX35_PAD_LD1 = 188,
-	MX35_PAD_LD2 = 189,
-	MX35_PAD_LD3 = 190,
-	MX35_PAD_LD4 = 191,
-	MX35_PAD_LD5 = 192,
-	MX35_PAD_LD6 = 193,
-	MX35_PAD_LD7 = 194,
-	MX35_PAD_LD8 = 195,
-	MX35_PAD_LD9 = 196,
-	MX35_PAD_LD10 = 197,
-	MX35_PAD_LD11 = 198,
-	MX35_PAD_LD12 = 199,
-	MX35_PAD_LD13 = 200,
-	MX35_PAD_LD14 = 201,
-	MX35_PAD_LD15 = 202,
-	MX35_PAD_LD16 = 203,
-	MX35_PAD_LD17 = 204,
-	MX35_PAD_LD18 = 205,
-	MX35_PAD_LD19 = 206,
-	MX35_PAD_LD20 = 207,
-	MX35_PAD_LD21 = 208,
-	MX35_PAD_LD22 = 209,
-	MX35_PAD_LD23 = 210,
-	MX35_PAD_D3_HSYNC = 211,
-	MX35_PAD_D3_FPSHIFT = 212,
-	MX35_PAD_D3_DRDY = 213,
-	MX35_PAD_CONTRAST = 214,
-	MX35_PAD_D3_VSYNC = 215,
-	MX35_PAD_D3_REV = 216,
-	MX35_PAD_D3_CLS = 217,
-	MX35_PAD_D3_SPL = 218,
-	MX35_PAD_SD1_CMD = 219,
-	MX35_PAD_SD1_CLK = 220,
-	MX35_PAD_SD1_DATA0 = 221,
-	MX35_PAD_SD1_DATA1 = 222,
-	MX35_PAD_SD1_DATA2 = 223,
-	MX35_PAD_SD1_DATA3 = 224,
-	MX35_PAD_SD2_CMD = 225,
-	MX35_PAD_SD2_CLK = 226,
-	MX35_PAD_SD2_DATA0 = 227,
-	MX35_PAD_SD2_DATA1 = 228,
-	MX35_PAD_SD2_DATA2 = 229,
-	MX35_PAD_SD2_DATA3 = 230,
-	MX35_PAD_ATA_CS0 = 231,
-	MX35_PAD_ATA_CS1 = 232,
-	MX35_PAD_ATA_DIOR = 233,
-	MX35_PAD_ATA_DIOW = 234,
-	MX35_PAD_ATA_DMACK = 235,
-	MX35_PAD_ATA_RESET_B = 236,
-	MX35_PAD_ATA_IORDY = 237,
-	MX35_PAD_ATA_DATA0 = 238,
-	MX35_PAD_ATA_DATA1 = 239,
-	MX35_PAD_ATA_DATA2 = 240,
-	MX35_PAD_ATA_DATA3 = 241,
-	MX35_PAD_ATA_DATA4 = 242,
-	MX35_PAD_ATA_DATA5 = 243,
-	MX35_PAD_ATA_DATA6 = 244,
-	MX35_PAD_ATA_DATA7 = 245,
-	MX35_PAD_ATA_DATA8 = 246,
-	MX35_PAD_ATA_DATA9 = 247,
-	MX35_PAD_ATA_DATA10 = 248,
-	MX35_PAD_ATA_DATA11 = 249,
-	MX35_PAD_ATA_DATA12 = 250,
-	MX35_PAD_ATA_DATA13 = 251,
-	MX35_PAD_ATA_DATA14 = 252,
-	MX35_PAD_ATA_DATA15 = 253,
-	MX35_PAD_ATA_INTRQ = 254,
-	MX35_PAD_ATA_BUFF_EN = 255,
-	MX35_PAD_ATA_DMARQ = 256,
-	MX35_PAD_ATA_DA0 = 257,
-	MX35_PAD_ATA_DA1 = 258,
-	MX35_PAD_ATA_DA2 = 259,
-	MX35_PAD_MLB_CLK = 260,
-	MX35_PAD_MLB_DAT = 261,
-	MX35_PAD_MLB_SIG = 262,
-	MX35_PAD_FEC_TX_CLK = 263,
-	MX35_PAD_FEC_RX_CLK = 264,
-	MX35_PAD_FEC_RX_DV = 265,
-	MX35_PAD_FEC_COL = 266,
-	MX35_PAD_FEC_RDATA0 = 267,
-	MX35_PAD_FEC_TDATA0 = 268,
-	MX35_PAD_FEC_TX_EN = 269,
-	MX35_PAD_FEC_MDC = 270,
-	MX35_PAD_FEC_MDIO = 271,
-	MX35_PAD_FEC_TX_ERR = 272,
-	MX35_PAD_FEC_RX_ERR = 273,
-	MX35_PAD_FEC_CRS = 274,
-	MX35_PAD_FEC_RDATA1 = 275,
-	MX35_PAD_FEC_TDATA1 = 276,
-	MX35_PAD_FEC_RDATA2 = 277,
-	MX35_PAD_FEC_TDATA2 = 278,
-	MX35_PAD_FEC_RDATA3 = 279,
-	MX35_PAD_FEC_TDATA3 = 280,
-	MX35_PAD_EXT_ARMCLK = 281,
-	MX35_PAD_TEST_MODE = 282,
-};
-
-/* imx35 register maps */
-static struct imx_pin_reg imx35_pin_regs[] = {
-	[0] = IMX_PIN_REG(MX35_PAD_CAPTURE, 0x328, 0x004, 0, 0x0, 0), /* MX35_PAD_CAPTURE__GPT_CAPIN1 */
-	[1] = IMX_PIN_REG(MX35_PAD_CAPTURE, 0x328, 0x004, 1, 0x0, 0), /* MX35_PAD_CAPTURE__GPT_CMPOUT2 */
-	[2] = IMX_PIN_REG(MX35_PAD_CAPTURE, 0x328, 0x004, 2, 0x7f4, 0), /* MX35_PAD_CAPTURE__CSPI2_SS1 */
-	[3] = IMX_PIN_REG(MX35_PAD_CAPTURE, 0x328, 0x004, 3, 0x0, 0), /* MX35_PAD_CAPTURE__EPIT1_EPITO */
-	[4] = IMX_PIN_REG(MX35_PAD_CAPTURE, 0x328, 0x004, 4, 0x7d0, 0), /* MX35_PAD_CAPTURE__CCM_CLK32K */
-	[5] = IMX_PIN_REG(MX35_PAD_CAPTURE, 0x328, 0x004, 5, 0x850, 0), /* MX35_PAD_CAPTURE__GPIO1_4 */
-	[6] = IMX_PIN_REG(MX35_PAD_COMPARE, 0x32c, 0x008, 0, 0x0, 0), /* MX35_PAD_COMPARE__GPT_CMPOUT1 */
-	[7] = IMX_PIN_REG(MX35_PAD_COMPARE, 0x32c, 0x008, 1, 0x0, 0), /* MX35_PAD_COMPARE__GPT_CAPIN2 */
-	[8] = IMX_PIN_REG(MX35_PAD_COMPARE, 0x32c, 0x008, 2, 0x0, 0), /* MX35_PAD_COMPARE__GPT_CMPOUT3 */
-	[9] = IMX_PIN_REG(MX35_PAD_COMPARE, 0x32c, 0x008, 3, 0x0, 0), /* MX35_PAD_COMPARE__EPIT2_EPITO */
-	[10] = IMX_PIN_REG(MX35_PAD_COMPARE, 0x32c, 0x008, 5, 0x854, 0), /* MX35_PAD_COMPARE__GPIO1_5 */
-	[11] = IMX_PIN_REG(MX35_PAD_COMPARE, 0x32c, 0x008, 7, 0x0, 0), /* MX35_PAD_COMPARE__SDMA_EXTDMA_2 */
-	[12] = IMX_PIN_REG(MX35_PAD_WDOG_RST, 0x330, 0x00c, 0, 0x0, 0), /* MX35_PAD_WDOG_RST__WDOG_WDOG_B */
-	[13] = IMX_PIN_REG(MX35_PAD_WDOG_RST, 0x330, 0x00c, 3, 0x0, 0), /* MX35_PAD_WDOG_RST__IPU_FLASH_STROBE */
-	[14] = IMX_PIN_REG(MX35_PAD_WDOG_RST, 0x330, 0x00c, 5, 0x858, 0), /* MX35_PAD_WDOG_RST__GPIO1_6 */
-	[15] = IMX_PIN_REG(MX35_PAD_GPIO1_0, 0x334, 0x010, 0, 0x82c, 0), /* MX35_PAD_GPIO1_0__GPIO1_0 */
-	[16] = IMX_PIN_REG(MX35_PAD_GPIO1_0, 0x334, 0x010, 1, 0x7d4, 0), /* MX35_PAD_GPIO1_0__CCM_PMIC_RDY */
-	[17] = IMX_PIN_REG(MX35_PAD_GPIO1_0, 0x334, 0x010, 2, 0x990, 0), /* MX35_PAD_GPIO1_0__OWIRE_LINE */
-	[18] = IMX_PIN_REG(MX35_PAD_GPIO1_0, 0x334, 0x010, 7, 0x0, 0), /* MX35_PAD_GPIO1_0__SDMA_EXTDMA_0 */
-	[19] = IMX_PIN_REG(MX35_PAD_GPIO1_1, 0x338, 0x014, 0, 0x838, 0), /* MX35_PAD_GPIO1_1__GPIO1_1 */
-	[20] = IMX_PIN_REG(MX35_PAD_GPIO1_1, 0x338, 0x014, 2, 0x0, 0), /* MX35_PAD_GPIO1_1__PWM_PWMO */
-	[21] = IMX_PIN_REG(MX35_PAD_GPIO1_1, 0x338, 0x014, 3, 0x7d8, 0), /* MX35_PAD_GPIO1_1__CSPI1_SS2 */
-	[22] = IMX_PIN_REG(MX35_PAD_GPIO1_1, 0x338, 0x014, 6, 0x0, 0), /* MX35_PAD_GPIO1_1__SCC_TAMPER_DETECT */
-	[23] = IMX_PIN_REG(MX35_PAD_GPIO1_1, 0x338, 0x014, 7, 0x0, 0), /* MX35_PAD_GPIO1_1__SDMA_EXTDMA_1 */
-	[24] = IMX_PIN_REG(MX35_PAD_GPIO2_0, 0x33c, 0x018, 0, 0x868, 0), /* MX35_PAD_GPIO2_0__GPIO2_0 */
-	[25] = IMX_PIN_REG(MX35_PAD_GPIO2_0, 0x33c, 0x018, 1, 0x0, 0), /* MX35_PAD_GPIO2_0__USB_TOP_USBOTG_CLK */
-	[26] = IMX_PIN_REG(MX35_PAD_GPIO3_0, 0x340, 0x01c, 0, 0x8e8, 0), /* MX35_PAD_GPIO3_0__GPIO3_0 */
-	[27] = IMX_PIN_REG(MX35_PAD_GPIO3_0, 0x340, 0x01c, 1, 0x0, 0), /* MX35_PAD_GPIO3_0__USB_TOP_USBH2_CLK */
-	[28] = IMX_PIN_REG(MX35_PAD_RESET_IN_B, 0x344, 0x0, 0, 0x0, 0), /* MX35_PAD_RESET_IN_B__CCM_RESET_IN_B */
-	[29] = IMX_PIN_REG(MX35_PAD_POR_B, 0x348, 0x0, 0, 0x0, 0), /* MX35_PAD_POR_B__CCM_POR_B */
-	[30] = IMX_PIN_REG(MX35_PAD_CLKO, 0x34c, 0x020, 0, 0x0, 0), /* MX35_PAD_CLKO__CCM_CLKO */
-	[31] = IMX_PIN_REG(MX35_PAD_CLKO, 0x34c, 0x020, 5, 0x860, 0), /* MX35_PAD_CLKO__GPIO1_8 */
-	[32] = IMX_PIN_REG(MX35_PAD_BOOT_MODE0, 0x350, 0x0, 0, 0x0, 0), /* MX35_PAD_BOOT_MODE0__CCM_BOOT_MODE_0 */
-	[33] = IMX_PIN_REG(MX35_PAD_BOOT_MODE1, 0x354, 0x0, 0, 0x0, 0), /* MX35_PAD_BOOT_MODE1__CCM_BOOT_MODE_1 */
-	[34] = IMX_PIN_REG(MX35_PAD_CLK_MODE0, 0x358, 0x0, 0, 0x0, 0), /* MX35_PAD_CLK_MODE0__CCM_CLK_MODE_0 */
-	[35] = IMX_PIN_REG(MX35_PAD_CLK_MODE1, 0x35c, 0x0, 0, 0x0, 0), /* MX35_PAD_CLK_MODE1__CCM_CLK_MODE_1 */
-	[36] = IMX_PIN_REG(MX35_PAD_POWER_FAIL, 0x360, 0x0, 0, 0x0, 0), /* MX35_PAD_POWER_FAIL__CCM_DSM_WAKEUP_INT_26 */
-	[37] = IMX_PIN_REG(MX35_PAD_VSTBY, 0x364, 0x024, 0, 0x0, 0), /* MX35_PAD_VSTBY__CCM_VSTBY */
-	[38] = IMX_PIN_REG(MX35_PAD_VSTBY, 0x364, 0x024, 5, 0x85c, 0), /* MX35_PAD_VSTBY__GPIO1_7 */
-	[39] = IMX_PIN_REG(MX35_PAD_A0, 0x368, 0x028, 0, 0x0, 0), /* MX35_PAD_A0__EMI_EIM_DA_L_0 */
-	[40] = IMX_PIN_REG(MX35_PAD_A1, 0x36c, 0x02c, 0, 0x0, 0), /* MX35_PAD_A1__EMI_EIM_DA_L_1 */
-	[41] = IMX_PIN_REG(MX35_PAD_A2, 0x370, 0x030, 0, 0x0, 0), /* MX35_PAD_A2__EMI_EIM_DA_L_2 */
-	[42] = IMX_PIN_REG(MX35_PAD_A3, 0x374, 0x034, 0, 0x0, 0), /* MX35_PAD_A3__EMI_EIM_DA_L_3 */
-	[43] = IMX_PIN_REG(MX35_PAD_A4, 0x378, 0x038, 0, 0x0, 0), /* MX35_PAD_A4__EMI_EIM_DA_L_4 */
-	[44] = IMX_PIN_REG(MX35_PAD_A5, 0x37c, 0x03c, 0, 0x0, 0), /* MX35_PAD_A5__EMI_EIM_DA_L_5 */
-	[45] = IMX_PIN_REG(MX35_PAD_A6, 0x380, 0x040, 0, 0x0, 0), /* MX35_PAD_A6__EMI_EIM_DA_L_6 */
-	[46] = IMX_PIN_REG(MX35_PAD_A7, 0x384, 0x044, 0, 0x0, 0), /* MX35_PAD_A7__EMI_EIM_DA_L_7 */
-	[47] = IMX_PIN_REG(MX35_PAD_A8, 0x388, 0x048, 0, 0x0, 0), /* MX35_PAD_A8__EMI_EIM_DA_H_8 */
-	[48] = IMX_PIN_REG(MX35_PAD_A9, 0x38c, 0x04c, 0, 0x0, 0), /* MX35_PAD_A9__EMI_EIM_DA_H_9 */
-	[49] = IMX_PIN_REG(MX35_PAD_A10, 0x390, 0x050, 0, 0x0, 0), /* MX35_PAD_A10__EMI_EIM_DA_H_10 */
-	[50] = IMX_PIN_REG(MX35_PAD_MA10, 0x394, 0x054, 0, 0x0, 0), /* MX35_PAD_MA10__EMI_MA10 */
-	[51] = IMX_PIN_REG(MX35_PAD_A11, 0x398, 0x058, 0, 0x0, 0), /* MX35_PAD_A11__EMI_EIM_DA_H_11 */
-	[52] = IMX_PIN_REG(MX35_PAD_A12, 0x39c, 0x05c, 0, 0x0, 0), /* MX35_PAD_A12__EMI_EIM_DA_H_12 */
-	[53] = IMX_PIN_REG(MX35_PAD_A13, 0x3a0, 0x060, 0, 0x0, 0), /* MX35_PAD_A13__EMI_EIM_DA_H_13 */
-	[54] = IMX_PIN_REG(MX35_PAD_A14, 0x3a4, 0x064, 0, 0x0, 0), /* MX35_PAD_A14__EMI_EIM_DA_H2_14 */
-	[55] = IMX_PIN_REG(MX35_PAD_A15, 0x3a8, 0x068, 0, 0x0, 0), /* MX35_PAD_A15__EMI_EIM_DA_H2_15 */
-	[56] = IMX_PIN_REG(MX35_PAD_A16, 0x3ac, 0x06c, 0, 0x0, 0), /* MX35_PAD_A16__EMI_EIM_A_16 */
-	[57] = IMX_PIN_REG(MX35_PAD_A17, 0x3b0, 0x070, 0, 0x0, 0), /* MX35_PAD_A17__EMI_EIM_A_17 */
-	[58] = IMX_PIN_REG(MX35_PAD_A18, 0x3b4, 0x074, 0, 0x0, 0), /* MX35_PAD_A18__EMI_EIM_A_18 */
-	[59] = IMX_PIN_REG(MX35_PAD_A19, 0x3b8, 0x078, 0, 0x0, 0), /* MX35_PAD_A19__EMI_EIM_A_19 */
-	[60] = IMX_PIN_REG(MX35_PAD_A20, 0x3bc, 0x07c, 0, 0x0, 0), /* MX35_PAD_A20__EMI_EIM_A_20 */
-	[61] = IMX_PIN_REG(MX35_PAD_A21, 0x3c0, 0x080, 0, 0x0, 0), /* MX35_PAD_A21__EMI_EIM_A_21 */
-	[62] = IMX_PIN_REG(MX35_PAD_A22, 0x3c4, 0x084, 0, 0x0, 0), /* MX35_PAD_A22__EMI_EIM_A_22 */
-	[63] = IMX_PIN_REG(MX35_PAD_A23, 0x3c8, 0x088, 0, 0x0, 0), /* MX35_PAD_A23__EMI_EIM_A_23 */
-	[64] = IMX_PIN_REG(MX35_PAD_A24, 0x3cc, 0x08c, 0, 0x0, 0), /* MX35_PAD_A24__EMI_EIM_A_24 */
-	[65] = IMX_PIN_REG(MX35_PAD_A25, 0x3d0, 0x090, 0, 0x0, 0), /* MX35_PAD_A25__EMI_EIM_A_25 */
-	[66] = IMX_PIN_REG(MX35_PAD_SDBA1, 0x3d4, 0x0, 0, 0x0, 0), /* MX35_PAD_SDBA1__EMI_EIM_SDBA1 */
-	[67] = IMX_PIN_REG(MX35_PAD_SDBA0, 0x3d8, 0x0, 0, 0x0, 0), /* MX35_PAD_SDBA0__EMI_EIM_SDBA0 */
-	[68] = IMX_PIN_REG(MX35_PAD_SD0, 0x3dc, 0x0, 0, 0x0, 0), /* MX35_PAD_SD0__EMI_DRAM_D_0 */
-	[69] = IMX_PIN_REG(MX35_PAD_SD1, 0x3e0, 0x0, 0, 0x0, 0), /* MX35_PAD_SD1__EMI_DRAM_D_1 */
-	[70] = IMX_PIN_REG(MX35_PAD_SD2, 0x3e4, 0x0, 0, 0x0, 0), /* MX35_PAD_SD2__EMI_DRAM_D_2 */
-	[71] = IMX_PIN_REG(MX35_PAD_SD3, 0x3e8, 0x0, 0, 0x0, 0), /* MX35_PAD_SD3__EMI_DRAM_D_3 */
-	[72] = IMX_PIN_REG(MX35_PAD_SD4, 0x3ec, 0x0, 0, 0x0, 0), /* MX35_PAD_SD4__EMI_DRAM_D_4 */
-	[73] = IMX_PIN_REG(MX35_PAD_SD5, 0x3f0, 0x0, 0, 0x0, 0), /* MX35_PAD_SD5__EMI_DRAM_D_5 */
-	[74] = IMX_PIN_REG(MX35_PAD_SD6, 0x3f4, 0x0, 0, 0x0, 0), /* MX35_PAD_SD6__EMI_DRAM_D_6 */
-	[75] = IMX_PIN_REG(MX35_PAD_SD7, 0x3f8, 0x0, 0, 0x0, 0), /* MX35_PAD_SD7__EMI_DRAM_D_7 */
-	[76] = IMX_PIN_REG(MX35_PAD_SD8, 0x3fc, 0x0, 0, 0x0, 0), /* MX35_PAD_SD8__EMI_DRAM_D_8 */
-	[77] = IMX_PIN_REG(MX35_PAD_SD9, 0x400, 0x0, 0, 0x0, 0), /* MX35_PAD_SD9__EMI_DRAM_D_9 */
-	[78] = IMX_PIN_REG(MX35_PAD_SD10, 0x404, 0x0, 0, 0x0, 0), /* MX35_PAD_SD10__EMI_DRAM_D_10 */
-	[79] = IMX_PIN_REG(MX35_PAD_SD11, 0x408, 0x0, 0, 0x0, 0), /* MX35_PAD_SD11__EMI_DRAM_D_11 */
-	[80] = IMX_PIN_REG(MX35_PAD_SD12, 0x40c, 0x0, 0, 0x0, 0), /* MX35_PAD_SD12__EMI_DRAM_D_12 */
-	[81] = IMX_PIN_REG(MX35_PAD_SD13, 0x410, 0x0, 0, 0x0, 0), /* MX35_PAD_SD13__EMI_DRAM_D_13 */
-	[82] = IMX_PIN_REG(MX35_PAD_SD14, 0x414, 0x0, 0, 0x0, 0), /* MX35_PAD_SD14__EMI_DRAM_D_14 */
-	[83] = IMX_PIN_REG(MX35_PAD_SD15, 0x418, 0x0, 0, 0x0, 0), /* MX35_PAD_SD15__EMI_DRAM_D_15 */
-	[84] = IMX_PIN_REG(MX35_PAD_SD16, 0x41c, 0x0, 0, 0x0, 0), /* MX35_PAD_SD16__EMI_DRAM_D_16 */
-	[85] = IMX_PIN_REG(MX35_PAD_SD17, 0x420, 0x0, 0, 0x0, 0), /* MX35_PAD_SD17__EMI_DRAM_D_17 */
-	[86] = IMX_PIN_REG(MX35_PAD_SD18, 0x424, 0x0, 0, 0x0, 0), /* MX35_PAD_SD18__EMI_DRAM_D_18 */
-	[87] = IMX_PIN_REG(MX35_PAD_SD19, 0x428, 0x0, 0, 0x0, 0), /* MX35_PAD_SD19__EMI_DRAM_D_19 */
-	[88] = IMX_PIN_REG(MX35_PAD_SD20, 0x42c, 0x0, 0, 0x0, 0), /* MX35_PAD_SD20__EMI_DRAM_D_20 */
-	[89] = IMX_PIN_REG(MX35_PAD_SD21, 0x430, 0x0, 0, 0x0, 0), /* MX35_PAD_SD21__EMI_DRAM_D_21 */
-	[90] = IMX_PIN_REG(MX35_PAD_SD22, 0x434, 0x0, 0, 0x0, 0), /* MX35_PAD_SD22__EMI_DRAM_D_22 */
-	[91] = IMX_PIN_REG(MX35_PAD_SD23, 0x438, 0x0, 0, 0x0, 0), /* MX35_PAD_SD23__EMI_DRAM_D_23 */
-	[92] = IMX_PIN_REG(MX35_PAD_SD24, 0x43c, 0x0, 0, 0x0, 0), /* MX35_PAD_SD24__EMI_DRAM_D_24 */
-	[93] = IMX_PIN_REG(MX35_PAD_SD25, 0x440, 0x0, 0, 0x0, 0), /* MX35_PAD_SD25__EMI_DRAM_D_25 */
-	[94] = IMX_PIN_REG(MX35_PAD_SD26, 0x444, 0x0, 0, 0x0, 0), /* MX35_PAD_SD26__EMI_DRAM_D_26 */
-	[95] = IMX_PIN_REG(MX35_PAD_SD27, 0x448, 0x0, 0, 0x0, 0), /* MX35_PAD_SD27__EMI_DRAM_D_27 */
-	[96] = IMX_PIN_REG(MX35_PAD_SD28, 0x44c, 0x0, 0, 0x0, 0), /* MX35_PAD_SD28__EMI_DRAM_D_28 */
-	[97] = IMX_PIN_REG(MX35_PAD_SD29, 0x450, 0x0, 0, 0x0, 0), /* MX35_PAD_SD29__EMI_DRAM_D_29 */
-	[98] = IMX_PIN_REG(MX35_PAD_SD30, 0x454, 0x0, 0, 0x0, 0), /* MX35_PAD_SD30__EMI_DRAM_D_30 */
-	[99] = IMX_PIN_REG(MX35_PAD_SD31, 0x458, 0x0, 0, 0x0, 0), /* MX35_PAD_SD31__EMI_DRAM_D_31 */
-	[100] = IMX_PIN_REG(MX35_PAD_DQM0, 0x45c, 0x0, 0, 0x0, 0), /* MX35_PAD_DQM0__EMI_DRAM_DQM_0 */
-	[101] = IMX_PIN_REG(MX35_PAD_DQM1, 0x460, 0x0, 0, 0x0, 0), /* MX35_PAD_DQM1__EMI_DRAM_DQM_1 */
-	[102] = IMX_PIN_REG(MX35_PAD_DQM2, 0x464, 0x0, 0, 0x0, 0), /* MX35_PAD_DQM2__EMI_DRAM_DQM_2 */
-	[103] = IMX_PIN_REG(MX35_PAD_DQM3, 0x468, 0x0, 0, 0x0, 0), /* MX35_PAD_DQM3__EMI_DRAM_DQM_3 */
-	[104] = IMX_PIN_REG(MX35_PAD_EB0, 0x46c, 0x094, 0, 0x0, 0), /* MX35_PAD_EB0__EMI_EIM_EB0_B */
-	[105] = IMX_PIN_REG(MX35_PAD_EB1, 0x470, 0x098, 0, 0x0, 0), /* MX35_PAD_EB1__EMI_EIM_EB1_B */
-	[106] = IMX_PIN_REG(MX35_PAD_OE, 0x474, 0x09c, 0, 0x0, 0), /* MX35_PAD_OE__EMI_EIM_OE */
-	[107] = IMX_PIN_REG(MX35_PAD_CS0, 0x478, 0x0a0, 0, 0x0, 0), /* MX35_PAD_CS0__EMI_EIM_CS0 */
-	[108] = IMX_PIN_REG(MX35_PAD_CS1, 0x47c, 0x0a4, 0, 0x0, 0), /* MX35_PAD_CS1__EMI_EIM_CS1 */
-	[109] = IMX_PIN_REG(MX35_PAD_CS1, 0x47c, 0x0a4, 3, 0x0, 0), /* MX35_PAD_CS1__EMI_NANDF_CE3 */
-	[110] = IMX_PIN_REG(MX35_PAD_CS2, 0x480, 0x0a8, 0, 0x0, 0), /* MX35_PAD_CS2__EMI_EIM_CS2 */
-	[111] = IMX_PIN_REG(MX35_PAD_CS3, 0x484, 0x0ac, 0, 0x0, 0), /* MX35_PAD_CS3__EMI_EIM_CS3 */
-	[112] = IMX_PIN_REG(MX35_PAD_CS4, 0x488, 0x0b0, 0, 0x0, 0), /* MX35_PAD_CS4__EMI_EIM_CS4 */
-	[113] = IMX_PIN_REG(MX35_PAD_CS4, 0x488, 0x0b0, 1, 0x800, 0), /* MX35_PAD_CS4__EMI_DTACK_B */
-	[114] = IMX_PIN_REG(MX35_PAD_CS4, 0x488, 0x0b0, 3, 0x0, 0), /* MX35_PAD_CS4__EMI_NANDF_CE1 */
-	[115] = IMX_PIN_REG(MX35_PAD_CS4, 0x488, 0x0b0, 5, 0x83c, 0), /* MX35_PAD_CS4__GPIO1_20 */
-	[116] = IMX_PIN_REG(MX35_PAD_CS5, 0x48c, 0x0b4, 0, 0x0, 0), /* MX35_PAD_CS5__EMI_EIM_CS5 */
-	[117] = IMX_PIN_REG(MX35_PAD_CS5, 0x48c, 0x0b4, 1, 0x7f8, 0), /* MX35_PAD_CS5__CSPI2_SS2 */
-	[118] = IMX_PIN_REG(MX35_PAD_CS5, 0x48c, 0x0b4, 2, 0x7d8, 1), /* MX35_PAD_CS5__CSPI1_SS2 */
-	[119] = IMX_PIN_REG(MX35_PAD_CS5, 0x48c, 0x0b4, 3, 0x0, 0), /* MX35_PAD_CS5__EMI_NANDF_CE2 */
-	[120] = IMX_PIN_REG(MX35_PAD_CS5, 0x48c, 0x0b4, 5, 0x840, 0), /* MX35_PAD_CS5__GPIO1_21 */
-	[121] = IMX_PIN_REG(MX35_PAD_NF_CE0, 0x490, 0x0b8, 0, 0x0, 0), /* MX35_PAD_NF_CE0__EMI_NANDF_CE0 */
-	[122] = IMX_PIN_REG(MX35_PAD_NF_CE0, 0x490, 0x0b8, 5, 0x844, 0), /* MX35_PAD_NF_CE0__GPIO1_22 */
-	[123] = IMX_PIN_REG(MX35_PAD_ECB, 0x494, 0x0, 0, 0x0, 0), /* MX35_PAD_ECB__EMI_EIM_ECB */
-	[124] = IMX_PIN_REG(MX35_PAD_LBA, 0x498, 0x0bc, 0, 0x0, 0), /* MX35_PAD_LBA__EMI_EIM_LBA */
-	[125] = IMX_PIN_REG(MX35_PAD_BCLK, 0x49c, 0x0c0, 0, 0x0, 0), /* MX35_PAD_BCLK__EMI_EIM_BCLK */
-	[126] = IMX_PIN_REG(MX35_PAD_RW, 0x4a0, 0x0c4, 0, 0x0, 0), /* MX35_PAD_RW__EMI_EIM_RW */
-	[127] = IMX_PIN_REG(MX35_PAD_RAS, 0x4a4, 0x0, 0, 0x0, 0), /* MX35_PAD_RAS__EMI_DRAM_RAS */
-	[128] = IMX_PIN_REG(MX35_PAD_CAS, 0x4a8, 0x0, 0, 0x0, 0), /* MX35_PAD_CAS__EMI_DRAM_CAS */
-	[129] = IMX_PIN_REG(MX35_PAD_SDWE, 0x4ac, 0x0, 0, 0x0, 0), /* MX35_PAD_SDWE__EMI_DRAM_SDWE */
-	[130] = IMX_PIN_REG(MX35_PAD_SDCKE0, 0x4b0, 0x0, 0, 0x0, 0), /* MX35_PAD_SDCKE0__EMI_DRAM_SDCKE_0 */
-	[131] = IMX_PIN_REG(MX35_PAD_SDCKE1, 0x4b4, 0x0, 0, 0x0, 0), /* MX35_PAD_SDCKE1__EMI_DRAM_SDCKE_1 */
-	[132] = IMX_PIN_REG(MX35_PAD_SDCLK, 0x4b8, 0x0, 0, 0x0, 0), /* MX35_PAD_SDCLK__EMI_DRAM_SDCLK */
-	[133] = IMX_PIN_REG(MX35_PAD_SDQS0, 0x4bc, 0x0, 0, 0x0, 0), /* MX35_PAD_SDQS0__EMI_DRAM_SDQS_0 */
-	[134] = IMX_PIN_REG(MX35_PAD_SDQS1, 0x4c0, 0x0, 0, 0x0, 0), /* MX35_PAD_SDQS1__EMI_DRAM_SDQS_1 */
-	[135] = IMX_PIN_REG(MX35_PAD_SDQS2, 0x4c4, 0x0, 0, 0x0, 0), /* MX35_PAD_SDQS2__EMI_DRAM_SDQS_2 */
-	[136] = IMX_PIN_REG(MX35_PAD_SDQS3, 0x4c8, 0x0, 0, 0x0, 0), /* MX35_PAD_SDQS3__EMI_DRAM_SDQS_3 */
-	[137] = IMX_PIN_REG(MX35_PAD_NFWE_B, 0x4cc, 0x0c8, 0, 0x0, 0), /* MX35_PAD_NFWE_B__EMI_NANDF_WE_B */
-	[138] = IMX_PIN_REG(MX35_PAD_NFWE_B, 0x4cc, 0x0c8, 1, 0x9d8, 0), /* MX35_PAD_NFWE_B__USB_TOP_USBH2_DATA_3 */
-	[139] = IMX_PIN_REG(MX35_PAD_NFWE_B, 0x4cc, 0x0c8, 2, 0x924, 0), /* MX35_PAD_NFWE_B__IPU_DISPB_D0_VSYNC */
-	[140] = IMX_PIN_REG(MX35_PAD_NFWE_B, 0x4cc, 0x0c8, 5, 0x88c, 0), /* MX35_PAD_NFWE_B__GPIO2_18 */
-	[141] = IMX_PIN_REG(MX35_PAD_NFWE_B, 0x4cc, 0x0c8, 7, 0x0, 0), /* MX35_PAD_NFWE_B__ARM11P_TOP_TRACE_0 */
-	[142] = IMX_PIN_REG(MX35_PAD_NFRE_B, 0x4d0, 0x0cc, 0, 0x0, 0), /* MX35_PAD_NFRE_B__EMI_NANDF_RE_B */
-	[143] = IMX_PIN_REG(MX35_PAD_NFRE_B, 0x4d0, 0x0cc, 1, 0x9ec, 0), /* MX35_PAD_NFRE_B__USB_TOP_USBH2_DIR */
-	[144] = IMX_PIN_REG(MX35_PAD_NFRE_B, 0x4d0, 0x0cc, 2, 0x0, 0), /* MX35_PAD_NFRE_B__IPU_DISPB_BCLK */
-	[145] = IMX_PIN_REG(MX35_PAD_NFRE_B, 0x4d0, 0x0cc, 5, 0x890, 0), /* MX35_PAD_NFRE_B__GPIO2_19 */
-	[146] = IMX_PIN_REG(MX35_PAD_NFRE_B, 0x4d0, 0x0cc, 7, 0x0, 0), /* MX35_PAD_NFRE_B__ARM11P_TOP_TRACE_1 */
-	[147] = IMX_PIN_REG(MX35_PAD_NFALE, 0x4d4, 0x0d0, 0, 0x0, 0), /* MX35_PAD_NFALE__EMI_NANDF_ALE */
-	[148] = IMX_PIN_REG(MX35_PAD_NFALE, 0x4d4, 0x0d0, 1, 0x0, 0), /* MX35_PAD_NFALE__USB_TOP_USBH2_STP */
-	[149] = IMX_PIN_REG(MX35_PAD_NFALE, 0x4d4, 0x0d0, 2, 0x0, 0), /* MX35_PAD_NFALE__IPU_DISPB_CS0 */
-	[150] = IMX_PIN_REG(MX35_PAD_NFALE, 0x4d4, 0x0d0, 5, 0x898, 0), /* MX35_PAD_NFALE__GPIO2_20 */
-	[151] = IMX_PIN_REG(MX35_PAD_NFALE, 0x4d4, 0x0d0, 7, 0x0, 0), /* MX35_PAD_NFALE__ARM11P_TOP_TRACE_2 */
-	[152] = IMX_PIN_REG(MX35_PAD_NFCLE, 0x4d8, 0x0d4, 0, 0x0, 0), /* MX35_PAD_NFCLE__EMI_NANDF_CLE */
-	[153] = IMX_PIN_REG(MX35_PAD_NFCLE, 0x4d8, 0x0d4, 1, 0x9f0, 0), /* MX35_PAD_NFCLE__USB_TOP_USBH2_NXT */
-	[154] = IMX_PIN_REG(MX35_PAD_NFCLE, 0x4d8, 0x0d4, 2, 0x0, 0), /* MX35_PAD_NFCLE__IPU_DISPB_PAR_RS */
-	[155] = IMX_PIN_REG(MX35_PAD_NFCLE, 0x4d8, 0x0d4, 5, 0x89c, 0), /* MX35_PAD_NFCLE__GPIO2_21 */
-	[156] = IMX_PIN_REG(MX35_PAD_NFCLE, 0x4d8, 0x0d4, 7, 0x0, 0), /* MX35_PAD_NFCLE__ARM11P_TOP_TRACE_3 */
-	[157] = IMX_PIN_REG(MX35_PAD_NFWP_B, 0x4dc, 0x0d8, 0, 0x0, 0), /* MX35_PAD_NFWP_B__EMI_NANDF_WP_B */
-	[158] = IMX_PIN_REG(MX35_PAD_NFWP_B, 0x4dc, 0x0d8, 1, 0x9e8, 0), /* MX35_PAD_NFWP_B__USB_TOP_USBH2_DATA_7 */
-	[159] = IMX_PIN_REG(MX35_PAD_NFWP_B, 0x4dc, 0x0d8, 2, 0x0, 0), /* MX35_PAD_NFWP_B__IPU_DISPB_WR */
-	[160] = IMX_PIN_REG(MX35_PAD_NFWP_B, 0x4dc, 0x0d8, 5, 0x8a0, 0), /* MX35_PAD_NFWP_B__GPIO2_22 */
-	[161] = IMX_PIN_REG(MX35_PAD_NFWP_B, 0x4dc, 0x0d8, 7, 0x0, 0), /* MX35_PAD_NFWP_B__ARM11P_TOP_TRCTL */
-	[162] = IMX_PIN_REG(MX35_PAD_NFRB, 0x4e0, 0x0dc, 0, 0x0, 0), /* MX35_PAD_NFRB__EMI_NANDF_RB */
-	[163] = IMX_PIN_REG(MX35_PAD_NFRB, 0x4e0, 0x0dc, 2, 0x0, 0), /* MX35_PAD_NFRB__IPU_DISPB_RD */
-	[164] = IMX_PIN_REG(MX35_PAD_NFRB, 0x4e0, 0x0dc, 5, 0x8a4, 0), /* MX35_PAD_NFRB__GPIO2_23 */
-	[165] = IMX_PIN_REG(MX35_PAD_NFRB, 0x4e0, 0x0dc, 7, 0x0, 0), /* MX35_PAD_NFRB__ARM11P_TOP_TRCLK */
-	[166] = IMX_PIN_REG(MX35_PAD_D15, 0x4e4, 0x0, 0, 0x0, 0), /* MX35_PAD_D15__EMI_EIM_D_15 */
-	[167] = IMX_PIN_REG(MX35_PAD_D14, 0x4e8, 0x0, 0, 0x0, 0), /* MX35_PAD_D14__EMI_EIM_D_14 */
-	[168] = IMX_PIN_REG(MX35_PAD_D13, 0x4ec, 0x0, 0, 0x0, 0), /* MX35_PAD_D13__EMI_EIM_D_13 */
-	[169] = IMX_PIN_REG(MX35_PAD_D12, 0x4f0, 0x0, 0, 0x0, 0), /* MX35_PAD_D12__EMI_EIM_D_12 */
-	[170] = IMX_PIN_REG(MX35_PAD_D11, 0x4f4, 0x0, 0, 0x0, 0), /* MX35_PAD_D11__EMI_EIM_D_11 */
-	[171] = IMX_PIN_REG(MX35_PAD_D10, 0x4f8, 0x0, 0, 0x0, 0), /* MX35_PAD_D10__EMI_EIM_D_10 */
-	[172] = IMX_PIN_REG(MX35_PAD_D9, 0x4fc, 0x0, 0, 0x0, 0), /* MX35_PAD_D9__EMI_EIM_D_9 */
-	[173] = IMX_PIN_REG(MX35_PAD_D8, 0x500, 0x0, 0, 0x0, 0), /* MX35_PAD_D8__EMI_EIM_D_8 */
-	[174] = IMX_PIN_REG(MX35_PAD_D7, 0x504, 0x0, 0, 0x0, 0), /* MX35_PAD_D7__EMI_EIM_D_7 */
-	[175] = IMX_PIN_REG(MX35_PAD_D6, 0x508, 0x0, 0, 0x0, 0), /* MX35_PAD_D6__EMI_EIM_D_6 */
-	[176] = IMX_PIN_REG(MX35_PAD_D5, 0x50c, 0x0, 0, 0x0, 0), /* MX35_PAD_D5__EMI_EIM_D_5 */
-	[177] = IMX_PIN_REG(MX35_PAD_D4, 0x510, 0x0, 0, 0x0, 0), /* MX35_PAD_D4__EMI_EIM_D_4 */
-	[178] = IMX_PIN_REG(MX35_PAD_D3, 0x514, 0x0, 0, 0x0, 0), /* MX35_PAD_D3__EMI_EIM_D_3 */
-	[179] = IMX_PIN_REG(MX35_PAD_D2, 0x518, 0x0, 0, 0x0, 0), /* MX35_PAD_D2__EMI_EIM_D_2 */
-	[180] = IMX_PIN_REG(MX35_PAD_D1, 0x51c, 0x0, 0, 0x0, 0), /* MX35_PAD_D1__EMI_EIM_D_1 */
-	[181] = IMX_PIN_REG(MX35_PAD_D0, 0x520, 0x0, 0, 0x0, 0), /* MX35_PAD_D0__EMI_EIM_D_0 */
-	[182] = IMX_PIN_REG(MX35_PAD_CSI_D8, 0x524, 0x0e0, 0, 0x0, 0), /* MX35_PAD_CSI_D8__IPU_CSI_D_8 */
-	[183] = IMX_PIN_REG(MX35_PAD_CSI_D8, 0x524, 0x0e0, 1, 0x950, 0), /* MX35_PAD_CSI_D8__KPP_COL_0 */
-	[184] = IMX_PIN_REG(MX35_PAD_CSI_D8, 0x524, 0x0e0, 5, 0x83c, 1), /* MX35_PAD_CSI_D8__GPIO1_20 */
-	[185] = IMX_PIN_REG(MX35_PAD_CSI_D8, 0x524, 0x0e0, 7, 0x0, 0), /* MX35_PAD_CSI_D8__ARM11P_TOP_EVNTBUS_13 */
-	[186] = IMX_PIN_REG(MX35_PAD_CSI_D9, 0x528, 0x0e4, 0, 0x0, 0), /* MX35_PAD_CSI_D9__IPU_CSI_D_9 */
-	[187] = IMX_PIN_REG(MX35_PAD_CSI_D9, 0x528, 0x0e4, 1, 0x954, 0), /* MX35_PAD_CSI_D9__KPP_COL_1 */
-	[188] = IMX_PIN_REG(MX35_PAD_CSI_D9, 0x528, 0x0e4, 5, 0x840, 1), /* MX35_PAD_CSI_D9__GPIO1_21 */
-	[189] = IMX_PIN_REG(MX35_PAD_CSI_D9, 0x528, 0x0e4, 7, 0x0, 0), /* MX35_PAD_CSI_D9__ARM11P_TOP_EVNTBUS_14 */
-	[190] = IMX_PIN_REG(MX35_PAD_CSI_D10, 0x52c, 0x0e8, 0, 0x0, 0), /* MX35_PAD_CSI_D10__IPU_CSI_D_10 */
-	[191] = IMX_PIN_REG(MX35_PAD_CSI_D10, 0x52c, 0x0e8, 1, 0x958, 0), /* MX35_PAD_CSI_D10__KPP_COL_2 */
-	[192] = IMX_PIN_REG(MX35_PAD_CSI_D10, 0x52c, 0x0e8, 5, 0x844, 1), /* MX35_PAD_CSI_D10__GPIO1_22 */
-	[193] = IMX_PIN_REG(MX35_PAD_CSI_D10, 0x52c, 0x0e8, 7, 0x0, 0), /* MX35_PAD_CSI_D10__ARM11P_TOP_EVNTBUS_15 */
-	[194] = IMX_PIN_REG(MX35_PAD_CSI_D11, 0x530, 0x0ec, 0, 0x0, 0), /* MX35_PAD_CSI_D11__IPU_CSI_D_11 */
-	[195] = IMX_PIN_REG(MX35_PAD_CSI_D11, 0x530, 0x0ec, 1, 0x95c, 0), /* MX35_PAD_CSI_D11__KPP_COL_3 */
-	[196] = IMX_PIN_REG(MX35_PAD_CSI_D11, 0x530, 0x0ec, 5, 0x0, 0), /* MX35_PAD_CSI_D11__GPIO1_23 */
-	[197] = IMX_PIN_REG(MX35_PAD_CSI_D12, 0x534, 0x0f0, 0, 0x0, 0), /* MX35_PAD_CSI_D12__IPU_CSI_D_12 */
-	[198] = IMX_PIN_REG(MX35_PAD_CSI_D12, 0x534, 0x0f0, 1, 0x970, 0), /* MX35_PAD_CSI_D12__KPP_ROW_0 */
-	[199] = IMX_PIN_REG(MX35_PAD_CSI_D12, 0x534, 0x0f0, 5, 0x0, 0), /* MX35_PAD_CSI_D12__GPIO1_24 */
-	[200] = IMX_PIN_REG(MX35_PAD_CSI_D13, 0x538, 0x0f4, 0, 0x0, 0), /* MX35_PAD_CSI_D13__IPU_CSI_D_13 */
-	[201] = IMX_PIN_REG(MX35_PAD_CSI_D13, 0x538, 0x0f4, 1, 0x974, 0), /* MX35_PAD_CSI_D13__KPP_ROW_1 */
-	[202] = IMX_PIN_REG(MX35_PAD_CSI_D13, 0x538, 0x0f4, 5, 0x0, 0), /* MX35_PAD_CSI_D13__GPIO1_25 */
-	[203] = IMX_PIN_REG(MX35_PAD_CSI_D14, 0x53c, 0x0f8, 0, 0x0, 0), /* MX35_PAD_CSI_D14__IPU_CSI_D_14 */
-	[204] = IMX_PIN_REG(MX35_PAD_CSI_D14, 0x53c, 0x0f8, 1, 0x978, 0), /* MX35_PAD_CSI_D14__KPP_ROW_2 */
-	[205] = IMX_PIN_REG(MX35_PAD_CSI_D14, 0x53c, 0x0f8, 5, 0x0, 0), /* MX35_PAD_CSI_D14__GPIO1_26 */
-	[206] = IMX_PIN_REG(MX35_PAD_CSI_D15, 0x540, 0x0fc, 0, 0x97c, 0), /* MX35_PAD_CSI_D15__IPU_CSI_D_15 */
-	[207] = IMX_PIN_REG(MX35_PAD_CSI_D15, 0x540, 0x0fc, 1, 0x0, 0), /* MX35_PAD_CSI_D15__KPP_ROW_3 */
-	[208] = IMX_PIN_REG(MX35_PAD_CSI_D15, 0x540, 0x0fc, 5, 0x0, 0), /* MX35_PAD_CSI_D15__GPIO1_27 */
-	[209] = IMX_PIN_REG(MX35_PAD_CSI_MCLK, 0x544, 0x100, 0, 0x0, 0), /* MX35_PAD_CSI_MCLK__IPU_CSI_MCLK */
-	[210] = IMX_PIN_REG(MX35_PAD_CSI_MCLK, 0x544, 0x100, 5, 0x0, 0), /* MX35_PAD_CSI_MCLK__GPIO1_28 */
-	[211] = IMX_PIN_REG(MX35_PAD_CSI_VSYNC, 0x548, 0x104, 0, 0x0, 0), /* MX35_PAD_CSI_VSYNC__IPU_CSI_VSYNC */
-	[212] = IMX_PIN_REG(MX35_PAD_CSI_VSYNC, 0x548, 0x104, 5, 0x0, 0), /* MX35_PAD_CSI_VSYNC__GPIO1_29 */
-	[213] = IMX_PIN_REG(MX35_PAD_CSI_HSYNC, 0x54c, 0x108, 0, 0x0, 0), /* MX35_PAD_CSI_HSYNC__IPU_CSI_HSYNC */
-	[214] = IMX_PIN_REG(MX35_PAD_CSI_HSYNC, 0x54c, 0x108, 5, 0x0, 0), /* MX35_PAD_CSI_HSYNC__GPIO1_30 */
-	[215] = IMX_PIN_REG(MX35_PAD_CSI_PIXCLK, 0x550, 0x10c, 0, 0x0, 0), /* MX35_PAD_CSI_PIXCLK__IPU_CSI_PIXCLK */
-	[216] = IMX_PIN_REG(MX35_PAD_CSI_PIXCLK, 0x550, 0x10c, 5, 0x0, 0), /* MX35_PAD_CSI_PIXCLK__GPIO1_31 */
-	[217] = IMX_PIN_REG(MX35_PAD_I2C1_CLK, 0x554, 0x110, 0, 0x0, 0), /* MX35_PAD_I2C1_CLK__I2C1_SCL */
-	[218] = IMX_PIN_REG(MX35_PAD_I2C1_CLK, 0x554, 0x110, 5, 0x8a8, 0), /* MX35_PAD_I2C1_CLK__GPIO2_24 */
-	[219] = IMX_PIN_REG(MX35_PAD_I2C1_CLK, 0x554, 0x110, 6, 0x0, 0), /* MX35_PAD_I2C1_CLK__CCM_USB_BYP_CLK */
-	[220] = IMX_PIN_REG(MX35_PAD_I2C1_DAT, 0x558, 0x114, 0, 0x0, 0), /* MX35_PAD_I2C1_DAT__I2C1_SDA */
-	[221] = IMX_PIN_REG(MX35_PAD_I2C1_DAT, 0x558, 0x114, 5, 0x8ac, 0), /* MX35_PAD_I2C1_DAT__GPIO2_25 */
-	[222] = IMX_PIN_REG(MX35_PAD_I2C2_CLK, 0x55c, 0x118, 0, 0x0, 0), /* MX35_PAD_I2C2_CLK__I2C2_SCL */
-	[223] = IMX_PIN_REG(MX35_PAD_I2C2_CLK, 0x55c, 0x118, 1, 0x0, 0), /* MX35_PAD_I2C2_CLK__CAN1_TXCAN */
-	[224] = IMX_PIN_REG(MX35_PAD_I2C2_CLK, 0x55c, 0x118, 2, 0x0, 0), /* MX35_PAD_I2C2_CLK__USB_TOP_USBH2_PWR */
-	[225] = IMX_PIN_REG(MX35_PAD_I2C2_CLK, 0x55c, 0x118, 5, 0x8b0, 0), /* MX35_PAD_I2C2_CLK__GPIO2_26 */
-	[226] = IMX_PIN_REG(MX35_PAD_I2C2_CLK, 0x55c, 0x118, 6, 0x0, 0), /* MX35_PAD_I2C2_CLK__SDMA_DEBUG_BUS_DEVICE_2 */
-	[227] = IMX_PIN_REG(MX35_PAD_I2C2_DAT, 0x560, 0x11c, 0, 0x0, 0), /* MX35_PAD_I2C2_DAT__I2C2_SDA */
-	[228] = IMX_PIN_REG(MX35_PAD_I2C2_DAT, 0x560, 0x11c, 1, 0x7c8, 0), /* MX35_PAD_I2C2_DAT__CAN1_RXCAN */
-	[229] = IMX_PIN_REG(MX35_PAD_I2C2_DAT, 0x560, 0x11c, 2, 0x9f4, 0), /* MX35_PAD_I2C2_DAT__USB_TOP_USBH2_OC */
-	[230] = IMX_PIN_REG(MX35_PAD_I2C2_DAT, 0x560, 0x11c, 5, 0x8b4, 0), /* MX35_PAD_I2C2_DAT__GPIO2_27 */
-	[231] = IMX_PIN_REG(MX35_PAD_I2C2_DAT, 0x560, 0x11c, 6, 0x0, 0), /* MX35_PAD_I2C2_DAT__SDMA_DEBUG_BUS_DEVICE_3 */
-	[232] = IMX_PIN_REG(MX35_PAD_STXD4, 0x564, 0x120, 0, 0x0, 0), /* MX35_PAD_STXD4__AUDMUX_AUD4_TXD */
-	[233] = IMX_PIN_REG(MX35_PAD_STXD4, 0x564, 0x120, 5, 0x8b8, 0), /* MX35_PAD_STXD4__GPIO2_28 */
-	[234] = IMX_PIN_REG(MX35_PAD_STXD4, 0x564, 0x120, 7, 0x0, 0), /* MX35_PAD_STXD4__ARM11P_TOP_ARM_COREASID0 */
-	[235] = IMX_PIN_REG(MX35_PAD_SRXD4, 0x568, 0x124, 0, 0x0, 0), /* MX35_PAD_SRXD4__AUDMUX_AUD4_RXD */
-	[236] = IMX_PIN_REG(MX35_PAD_SRXD4, 0x568, 0x124, 5, 0x8bc, 0), /* MX35_PAD_SRXD4__GPIO2_29 */
-	[237] = IMX_PIN_REG(MX35_PAD_SRXD4, 0x568, 0x124, 7, 0x0, 0), /* MX35_PAD_SRXD4__ARM11P_TOP_ARM_COREASID1 */
-	[238] = IMX_PIN_REG(MX35_PAD_SCK4, 0x56c, 0x128, 0, 0x0, 0), /* MX35_PAD_SCK4__AUDMUX_AUD4_TXC */
-	[239] = IMX_PIN_REG(MX35_PAD_SCK4, 0x56c, 0x128, 5, 0x8c4, 0), /* MX35_PAD_SCK4__GPIO2_30 */
-	[240] = IMX_PIN_REG(MX35_PAD_SCK4, 0x56c, 0x128, 7, 0x0, 0), /* MX35_PAD_SCK4__ARM11P_TOP_ARM_COREASID2 */
-	[241] = IMX_PIN_REG(MX35_PAD_STXFS4, 0x570, 0x12c, 0, 0x0, 0), /* MX35_PAD_STXFS4__AUDMUX_AUD4_TXFS */
-	[242] = IMX_PIN_REG(MX35_PAD_STXFS4, 0x570, 0x12c, 5, 0x8c8, 0), /* MX35_PAD_STXFS4__GPIO2_31 */
-	[243] = IMX_PIN_REG(MX35_PAD_STXFS4, 0x570, 0x12c, 7, 0x0, 0), /* MX35_PAD_STXFS4__ARM11P_TOP_ARM_COREASID3 */
-	[244] = IMX_PIN_REG(MX35_PAD_STXD5, 0x574, 0x130, 0, 0x0, 0), /* MX35_PAD_STXD5__AUDMUX_AUD5_TXD */
-	[245] = IMX_PIN_REG(MX35_PAD_STXD5, 0x574, 0x130, 1, 0x0, 0), /* MX35_PAD_STXD5__SPDIF_SPDIF_OUT1 */
-	[246] = IMX_PIN_REG(MX35_PAD_STXD5, 0x574, 0x130, 2, 0x7ec, 0), /* MX35_PAD_STXD5__CSPI2_MOSI */
-	[247] = IMX_PIN_REG(MX35_PAD_STXD5, 0x574, 0x130, 5, 0x82c, 1), /* MX35_PAD_STXD5__GPIO1_0 */
-	[248] = IMX_PIN_REG(MX35_PAD_STXD5, 0x574, 0x130, 7, 0x0, 0), /* MX35_PAD_STXD5__ARM11P_TOP_ARM_COREASID4 */
-	[249] = IMX_PIN_REG(MX35_PAD_SRXD5, 0x578, 0x134, 0, 0x0, 0), /* MX35_PAD_SRXD5__AUDMUX_AUD5_RXD */
-	[250] = IMX_PIN_REG(MX35_PAD_SRXD5, 0x578, 0x134, 1, 0x998, 0), /* MX35_PAD_SRXD5__SPDIF_SPDIF_IN1 */
-	[251] = IMX_PIN_REG(MX35_PAD_SRXD5, 0x578, 0x134, 2, 0x7e8, 0), /* MX35_PAD_SRXD5__CSPI2_MISO */
-	[252] = IMX_PIN_REG(MX35_PAD_SRXD5, 0x578, 0x134, 5, 0x838, 1), /* MX35_PAD_SRXD5__GPIO1_1 */
-	[253] = IMX_PIN_REG(MX35_PAD_SRXD5, 0x578, 0x134, 7, 0x0, 0), /* MX35_PAD_SRXD5__ARM11P_TOP_ARM_COREASID5 */
-	[254] = IMX_PIN_REG(MX35_PAD_SCK5, 0x57c, 0x138, 0, 0x0, 0), /* MX35_PAD_SCK5__AUDMUX_AUD5_TXC */
-	[255] = IMX_PIN_REG(MX35_PAD_SCK5, 0x57c, 0x138, 1, 0x994, 0), /* MX35_PAD_SCK5__SPDIF_SPDIF_EXTCLK */
-	[256] = IMX_PIN_REG(MX35_PAD_SCK5, 0x57c, 0x138, 2, 0x7e0, 0), /* MX35_PAD_SCK5__CSPI2_SCLK */
-	[257] = IMX_PIN_REG(MX35_PAD_SCK5, 0x57c, 0x138, 5, 0x848, 0), /* MX35_PAD_SCK5__GPIO1_2 */
-	[258] = IMX_PIN_REG(MX35_PAD_SCK5, 0x57c, 0x138, 7, 0x0, 0), /* MX35_PAD_SCK5__ARM11P_TOP_ARM_COREASID6 */
-	[259] = IMX_PIN_REG(MX35_PAD_STXFS5, 0x580, 0x13c, 0, 0x0, 0), /* MX35_PAD_STXFS5__AUDMUX_AUD5_TXFS */
-	[260] = IMX_PIN_REG(MX35_PAD_STXFS5, 0x580, 0x13c, 2, 0x7e4, 0), /* MX35_PAD_STXFS5__CSPI2_RDY */
-	[261] = IMX_PIN_REG(MX35_PAD_STXFS5, 0x580, 0x13c, 5, 0x84c, 0), /* MX35_PAD_STXFS5__GPIO1_3 */
-	[262] = IMX_PIN_REG(MX35_PAD_STXFS5, 0x580, 0x13c, 7, 0x0, 0), /* MX35_PAD_STXFS5__ARM11P_TOP_ARM_COREASID7 */
-	[263] = IMX_PIN_REG(MX35_PAD_SCKR, 0x584, 0x140, 0, 0x0, 0), /* MX35_PAD_SCKR__ESAI_SCKR */
-	[264] = IMX_PIN_REG(MX35_PAD_SCKR, 0x584, 0x140, 5, 0x850, 1), /* MX35_PAD_SCKR__GPIO1_4 */
-	[265] = IMX_PIN_REG(MX35_PAD_SCKR, 0x584, 0x140, 7, 0x0, 0), /* MX35_PAD_SCKR__ARM11P_TOP_EVNTBUS_10 */
-	[266] = IMX_PIN_REG(MX35_PAD_FSR, 0x588, 0x144, 0, 0x0, 0), /* MX35_PAD_FSR__ESAI_FSR */
-	[267] = IMX_PIN_REG(MX35_PAD_FSR, 0x588, 0x144, 5, 0x854, 1), /* MX35_PAD_FSR__GPIO1_5 */
-	[268] = IMX_PIN_REG(MX35_PAD_FSR, 0x588, 0x144, 7, 0x0, 0), /* MX35_PAD_FSR__ARM11P_TOP_EVNTBUS_11 */
-	[269] = IMX_PIN_REG(MX35_PAD_HCKR, 0x58c, 0x148, 0, 0x0, 0), /* MX35_PAD_HCKR__ESAI_HCKR */
-	[270] = IMX_PIN_REG(MX35_PAD_HCKR, 0x58c, 0x148, 1, 0x0, 0), /* MX35_PAD_HCKR__AUDMUX_AUD5_RXFS */
-	[271] = IMX_PIN_REG(MX35_PAD_HCKR, 0x58c, 0x148, 2, 0x7f0, 0), /* MX35_PAD_HCKR__CSPI2_SS0 */
-	[272] = IMX_PIN_REG(MX35_PAD_HCKR, 0x58c, 0x148, 3, 0x0, 0), /* MX35_PAD_HCKR__IPU_FLASH_STROBE */
-	[273] = IMX_PIN_REG(MX35_PAD_HCKR, 0x58c, 0x148, 5, 0x858, 1), /* MX35_PAD_HCKR__GPIO1_6 */
-	[274] = IMX_PIN_REG(MX35_PAD_HCKR, 0x58c, 0x148, 7, 0x0, 0), /* MX35_PAD_HCKR__ARM11P_TOP_EVNTBUS_12 */
-	[275] = IMX_PIN_REG(MX35_PAD_SCKT, 0x590, 0x14c, 0, 0x0, 0), /* MX35_PAD_SCKT__ESAI_SCKT */
-	[276] = IMX_PIN_REG(MX35_PAD_SCKT, 0x590, 0x14c, 5, 0x85c, 1), /* MX35_PAD_SCKT__GPIO1_7 */
-	[277] = IMX_PIN_REG(MX35_PAD_SCKT, 0x590, 0x14c, 6, 0x930, 0), /* MX35_PAD_SCKT__IPU_CSI_D_0 */
-	[278] = IMX_PIN_REG(MX35_PAD_SCKT, 0x590, 0x14c, 7, 0x978, 1), /* MX35_PAD_SCKT__KPP_ROW_2 */
-	[279] = IMX_PIN_REG(MX35_PAD_FST, 0x594, 0x150, 0, 0x0, 0), /* MX35_PAD_FST__ESAI_FST */
-	[280] = IMX_PIN_REG(MX35_PAD_FST, 0x594, 0x150, 5, 0x860, 1), /* MX35_PAD_FST__GPIO1_8 */
-	[281] = IMX_PIN_REG(MX35_PAD_FST, 0x594, 0x150, 6, 0x934, 0), /* MX35_PAD_FST__IPU_CSI_D_1 */
-	[282] = IMX_PIN_REG(MX35_PAD_FST, 0x594, 0x150, 7, 0x97c, 1), /* MX35_PAD_FST__KPP_ROW_3 */
-	[283] = IMX_PIN_REG(MX35_PAD_HCKT, 0x598, 0x154, 0, 0x0, 0), /* MX35_PAD_HCKT__ESAI_HCKT */
-	[284] = IMX_PIN_REG(MX35_PAD_HCKT, 0x598, 0x154, 1, 0x7a8, 0), /* MX35_PAD_HCKT__AUDMUX_AUD5_RXC */
-	[285] = IMX_PIN_REG(MX35_PAD_HCKT, 0x598, 0x154, 5, 0x864, 0), /* MX35_PAD_HCKT__GPIO1_9 */
-	[286] = IMX_PIN_REG(MX35_PAD_HCKT, 0x598, 0x154, 6, 0x938, 0), /* MX35_PAD_HCKT__IPU_CSI_D_2 */
-	[287] = IMX_PIN_REG(MX35_PAD_HCKT, 0x598, 0x154, 7, 0x95c, 1), /* MX35_PAD_HCKT__KPP_COL_3 */
-	[288] = IMX_PIN_REG(MX35_PAD_TX5_RX0, 0x59c, 0x158, 0, 0x0, 0), /* MX35_PAD_TX5_RX0__ESAI_TX5_RX0 */
-	[289] = IMX_PIN_REG(MX35_PAD_TX5_RX0, 0x59c, 0x158, 1, 0x0, 0), /* MX35_PAD_TX5_RX0__AUDMUX_AUD4_RXC */
-	[290] = IMX_PIN_REG(MX35_PAD_TX5_RX0, 0x59c, 0x158, 2, 0x7f8, 1), /* MX35_PAD_TX5_RX0__CSPI2_SS2 */
-	[291] = IMX_PIN_REG(MX35_PAD_TX5_RX0, 0x59c, 0x158, 3, 0x0, 0), /* MX35_PAD_TX5_RX0__CAN2_TXCAN */
-	[292] = IMX_PIN_REG(MX35_PAD_TX5_RX0, 0x59c, 0x158, 4, 0x0, 0), /* MX35_PAD_TX5_RX0__UART2_DTR */
-	[293] = IMX_PIN_REG(MX35_PAD_TX5_RX0, 0x59c, 0x158, 5, 0x830, 0), /* MX35_PAD_TX5_RX0__GPIO1_10 */
-	[294] = IMX_PIN_REG(MX35_PAD_TX5_RX0, 0x59c, 0x158, 7, 0x0, 0), /* MX35_PAD_TX5_RX0__EMI_M3IF_CHOSEN_MASTER_0 */
-	[295] = IMX_PIN_REG(MX35_PAD_TX4_RX1, 0x5a0, 0x15c, 0, 0x0, 0), /* MX35_PAD_TX4_RX1__ESAI_TX4_RX1 */
-	[296] = IMX_PIN_REG(MX35_PAD_TX4_RX1, 0x5a0, 0x15c, 1, 0x0, 0), /* MX35_PAD_TX4_RX1__AUDMUX_AUD4_RXFS */
-	[297] = IMX_PIN_REG(MX35_PAD_TX4_RX1, 0x5a0, 0x15c, 2, 0x7fc, 0), /* MX35_PAD_TX4_RX1__CSPI2_SS3 */
-	[298] = IMX_PIN_REG(MX35_PAD_TX4_RX1, 0x5a0, 0x15c, 3, 0x7cc, 0), /* MX35_PAD_TX4_RX1__CAN2_RXCAN */
-	[299] = IMX_PIN_REG(MX35_PAD_TX4_RX1, 0x5a0, 0x15c, 4, 0x0, 0), /* MX35_PAD_TX4_RX1__UART2_DSR */
-	[300] = IMX_PIN_REG(MX35_PAD_TX4_RX1, 0x5a0, 0x15c, 5, 0x834, 0), /* MX35_PAD_TX4_RX1__GPIO1_11 */
-	[301] = IMX_PIN_REG(MX35_PAD_TX4_RX1, 0x5a0, 0x15c, 6, 0x93c, 0), /* MX35_PAD_TX4_RX1__IPU_CSI_D_3 */
-	[302] = IMX_PIN_REG(MX35_PAD_TX4_RX1, 0x5a0, 0x15c, 7, 0x970, 1), /* MX35_PAD_TX4_RX1__KPP_ROW_0 */
-	[303] = IMX_PIN_REG(MX35_PAD_TX3_RX2, 0x5a4, 0x160, 0, 0x0, 0), /* MX35_PAD_TX3_RX2__ESAI_TX3_RX2 */
-	[304] = IMX_PIN_REG(MX35_PAD_TX3_RX2, 0x5a4, 0x160, 1, 0x91c, 0), /* MX35_PAD_TX3_RX2__I2C3_SCL */
-	[305] = IMX_PIN_REG(MX35_PAD_TX3_RX2, 0x5a4, 0x160, 3, 0x0, 0), /* MX35_PAD_TX3_RX2__EMI_NANDF_CE1 */
-	[306] = IMX_PIN_REG(MX35_PAD_TX3_RX2, 0x5a4, 0x160, 5, 0x0, 0), /* MX35_PAD_TX3_RX2__GPIO1_12 */
-	[307] = IMX_PIN_REG(MX35_PAD_TX3_RX2, 0x5a4, 0x160, 6, 0x940, 0), /* MX35_PAD_TX3_RX2__IPU_CSI_D_4 */
-	[308] = IMX_PIN_REG(MX35_PAD_TX3_RX2, 0x5a4, 0x160, 7, 0x974, 1), /* MX35_PAD_TX3_RX2__KPP_ROW_1 */
-	[309] = IMX_PIN_REG(MX35_PAD_TX2_RX3, 0x5a8, 0x164, 0, 0x0, 0), /* MX35_PAD_TX2_RX3__ESAI_TX2_RX3 */
-	[310] = IMX_PIN_REG(MX35_PAD_TX2_RX3, 0x5a8, 0x164, 1, 0x920, 0), /* MX35_PAD_TX2_RX3__I2C3_SDA */
-	[311] = IMX_PIN_REG(MX35_PAD_TX2_RX3, 0x5a8, 0x164, 3, 0x0, 0), /* MX35_PAD_TX2_RX3__EMI_NANDF_CE2 */
-	[312] = IMX_PIN_REG(MX35_PAD_TX2_RX3, 0x5a8, 0x164, 5, 0x0, 0), /* MX35_PAD_TX2_RX3__GPIO1_13 */
-	[313] = IMX_PIN_REG(MX35_PAD_TX2_RX3, 0x5a8, 0x164, 6, 0x944, 0), /* MX35_PAD_TX2_RX3__IPU_CSI_D_5 */
-	[314] = IMX_PIN_REG(MX35_PAD_TX2_RX3, 0x5a8, 0x164, 7, 0x950, 1), /* MX35_PAD_TX2_RX3__KPP_COL_0 */
-	[315] = IMX_PIN_REG(MX35_PAD_TX1, 0x5ac, 0x168, 0, 0x0, 0), /* MX35_PAD_TX1__ESAI_TX1 */
-	[316] = IMX_PIN_REG(MX35_PAD_TX1, 0x5ac, 0x168, 1, 0x7d4, 1), /* MX35_PAD_TX1__CCM_PMIC_RDY */
-	[317] = IMX_PIN_REG(MX35_PAD_TX1, 0x5ac, 0x168, 2, 0x7d8, 2), /* MX35_PAD_TX1__CSPI1_SS2 */
-	[318] = IMX_PIN_REG(MX35_PAD_TX1, 0x5ac, 0x168, 3, 0x0, 0), /* MX35_PAD_TX1__EMI_NANDF_CE3 */
-	[319] = IMX_PIN_REG(MX35_PAD_TX1, 0x5ac, 0x168, 4, 0x0, 0), /* MX35_PAD_TX1__UART2_RI */
-	[320] = IMX_PIN_REG(MX35_PAD_TX1, 0x5ac, 0x168, 5, 0x0, 0), /* MX35_PAD_TX1__GPIO1_14 */
-	[321] = IMX_PIN_REG(MX35_PAD_TX1, 0x5ac, 0x168, 6, 0x948, 0), /* MX35_PAD_TX1__IPU_CSI_D_6 */
-	[322] = IMX_PIN_REG(MX35_PAD_TX1, 0x5ac, 0x168, 7, 0x954, 1), /* MX35_PAD_TX1__KPP_COL_1 */
-	[323] = IMX_PIN_REG(MX35_PAD_TX0, 0x5b0, 0x16c, 0, 0x0, 0), /* MX35_PAD_TX0__ESAI_TX0 */
-	[324] = IMX_PIN_REG(MX35_PAD_TX0, 0x5b0, 0x16c, 1, 0x994, 1), /* MX35_PAD_TX0__SPDIF_SPDIF_EXTCLK */
-	[325] = IMX_PIN_REG(MX35_PAD_TX0, 0x5b0, 0x16c, 2, 0x7dc, 0), /* MX35_PAD_TX0__CSPI1_SS3 */
-	[326] = IMX_PIN_REG(MX35_PAD_TX0, 0x5b0, 0x16c, 3, 0x800, 1), /* MX35_PAD_TX0__EMI_DTACK_B */
-	[327] = IMX_PIN_REG(MX35_PAD_TX0, 0x5b0, 0x16c, 4, 0x0, 0), /* MX35_PAD_TX0__UART2_DCD */
-	[328] = IMX_PIN_REG(MX35_PAD_TX0, 0x5b0, 0x16c, 5, 0x0, 0), /* MX35_PAD_TX0__GPIO1_15 */
-	[329] = IMX_PIN_REG(MX35_PAD_TX0, 0x5b0, 0x16c, 6, 0x94c, 0), /* MX35_PAD_TX0__IPU_CSI_D_7 */
-	[330] = IMX_PIN_REG(MX35_PAD_TX0, 0x5b0, 0x16c, 7, 0x958, 1), /* MX35_PAD_TX0__KPP_COL_2 */
-	[331] = IMX_PIN_REG(MX35_PAD_CSPI1_MOSI, 0x5b4, 0x170, 0, 0x0, 0), /* MX35_PAD_CSPI1_MOSI__CSPI1_MOSI */
-	[332] = IMX_PIN_REG(MX35_PAD_CSPI1_MOSI, 0x5b4, 0x170, 5, 0x0, 0), /* MX35_PAD_CSPI1_MOSI__GPIO1_16 */
-	[333] = IMX_PIN_REG(MX35_PAD_CSPI1_MOSI, 0x5b4, 0x170, 7, 0x0, 0), /* MX35_PAD_CSPI1_MOSI__ECT_CTI_TRIG_OUT1_2 */
-	[334] = IMX_PIN_REG(MX35_PAD_CSPI1_MISO, 0x5b8, 0x174, 0, 0x0, 0), /* MX35_PAD_CSPI1_MISO__CSPI1_MISO */
-	[335] = IMX_PIN_REG(MX35_PAD_CSPI1_MISO, 0x5b8, 0x174, 5, 0x0, 0), /* MX35_PAD_CSPI1_MISO__GPIO1_17 */
-	[336] = IMX_PIN_REG(MX35_PAD_CSPI1_MISO, 0x5b8, 0x174, 7, 0x0, 0), /* MX35_PAD_CSPI1_MISO__ECT_CTI_TRIG_OUT1_3 */
-	[337] = IMX_PIN_REG(MX35_PAD_CSPI1_SS0, 0x5bc, 0x178, 0, 0x0, 0), /* MX35_PAD_CSPI1_SS0__CSPI1_SS0 */
-	[338] = IMX_PIN_REG(MX35_PAD_CSPI1_SS0, 0x5bc, 0x178, 1, 0x990, 1), /* MX35_PAD_CSPI1_SS0__OWIRE_LINE */
-	[339] = IMX_PIN_REG(MX35_PAD_CSPI1_SS0, 0x5bc, 0x178, 2, 0x7fc, 1), /* MX35_PAD_CSPI1_SS0__CSPI2_SS3 */
-	[340] = IMX_PIN_REG(MX35_PAD_CSPI1_SS0, 0x5bc, 0x178, 5, 0x0, 0), /* MX35_PAD_CSPI1_SS0__GPIO1_18 */
-	[341] = IMX_PIN_REG(MX35_PAD_CSPI1_SS0, 0x5bc, 0x178, 7, 0x0, 0), /* MX35_PAD_CSPI1_SS0__ECT_CTI_TRIG_OUT1_4 */
-	[342] = IMX_PIN_REG(MX35_PAD_CSPI1_SS1, 0x5c0, 0x17c, 0, 0x0, 0), /* MX35_PAD_CSPI1_SS1__CSPI1_SS1 */
-	[343] = IMX_PIN_REG(MX35_PAD_CSPI1_SS1, 0x5c0, 0x17c, 1, 0x0, 0), /* MX35_PAD_CSPI1_SS1__PWM_PWMO */
-	[344] = IMX_PIN_REG(MX35_PAD_CSPI1_SS1, 0x5c0, 0x17c, 2, 0x7d0, 1), /* MX35_PAD_CSPI1_SS1__CCM_CLK32K */
-	[345] = IMX_PIN_REG(MX35_PAD_CSPI1_SS1, 0x5c0, 0x17c, 5, 0x0, 0), /* MX35_PAD_CSPI1_SS1__GPIO1_19 */
-	[346] = IMX_PIN_REG(MX35_PAD_CSPI1_SS1, 0x5c0, 0x17c, 6, 0x0, 0), /* MX35_PAD_CSPI1_SS1__IPU_DIAGB_29 */
-	[347] = IMX_PIN_REG(MX35_PAD_CSPI1_SS1, 0x5c0, 0x17c, 7, 0x0, 0), /* MX35_PAD_CSPI1_SS1__ECT_CTI_TRIG_OUT1_5 */
-	[348] = IMX_PIN_REG(MX35_PAD_CSPI1_SCLK, 0x5c4, 0x180, 0, 0x0, 0), /* MX35_PAD_CSPI1_SCLK__CSPI1_SCLK */
-	[349] = IMX_PIN_REG(MX35_PAD_CSPI1_SCLK, 0x5c4, 0x180, 5, 0x904, 0), /* MX35_PAD_CSPI1_SCLK__GPIO3_4 */
-	[350] = IMX_PIN_REG(MX35_PAD_CSPI1_SCLK, 0x5c4, 0x180, 6, 0x0, 0), /* MX35_PAD_CSPI1_SCLK__IPU_DIAGB_30 */
-	[351] = IMX_PIN_REG(MX35_PAD_CSPI1_SCLK, 0x5c4, 0x180, 7, 0x0, 0), /* MX35_PAD_CSPI1_SCLK__EMI_M3IF_CHOSEN_MASTER_1 */
-	[352] = IMX_PIN_REG(MX35_PAD_CSPI1_SPI_RDY, 0x5c8, 0x184, 0, 0x0, 0), /* MX35_PAD_CSPI1_SPI_RDY__CSPI1_RDY */
-	[353] = IMX_PIN_REG(MX35_PAD_CSPI1_SPI_RDY, 0x5c8, 0x184, 5, 0x908, 0), /* MX35_PAD_CSPI1_SPI_RDY__GPIO3_5 */
-	[354] = IMX_PIN_REG(MX35_PAD_CSPI1_SPI_RDY, 0x5c8, 0x184, 6, 0x0, 0), /* MX35_PAD_CSPI1_SPI_RDY__IPU_DIAGB_31 */
-	[355] = IMX_PIN_REG(MX35_PAD_CSPI1_SPI_RDY, 0x5c8, 0x184, 7, 0x0, 0), /* MX35_PAD_CSPI1_SPI_RDY__EMI_M3IF_CHOSEN_MASTER_2 */
-	[356] = IMX_PIN_REG(MX35_PAD_RXD1, 0x5cc, 0x188, 0, 0x0, 0), /* MX35_PAD_RXD1__UART1_RXD_MUX */
-	[357] = IMX_PIN_REG(MX35_PAD_RXD1, 0x5cc, 0x188, 1, 0x7ec, 1), /* MX35_PAD_RXD1__CSPI2_MOSI */
-	[358] = IMX_PIN_REG(MX35_PAD_RXD1, 0x5cc, 0x188, 4, 0x960, 0), /* MX35_PAD_RXD1__KPP_COL_4 */
-	[359] = IMX_PIN_REG(MX35_PAD_RXD1, 0x5cc, 0x188, 5, 0x90c, 0), /* MX35_PAD_RXD1__GPIO3_6 */
-	[360] = IMX_PIN_REG(MX35_PAD_RXD1, 0x5cc, 0x188, 7, 0x0, 0), /* MX35_PAD_RXD1__ARM11P_TOP_EVNTBUS_16 */
-	[361] = IMX_PIN_REG(MX35_PAD_TXD1, 0x5d0, 0x18c, 0, 0x0, 0), /* MX35_PAD_TXD1__UART1_TXD_MUX */
-	[362] = IMX_PIN_REG(MX35_PAD_TXD1, 0x5d0, 0x18c, 1, 0x7e8, 1), /* MX35_PAD_TXD1__CSPI2_MISO */
-	[363] = IMX_PIN_REG(MX35_PAD_TXD1, 0x5d0, 0x18c, 4, 0x964, 0), /* MX35_PAD_TXD1__KPP_COL_5 */
-	[364] = IMX_PIN_REG(MX35_PAD_TXD1, 0x5d0, 0x18c, 5, 0x910, 0), /* MX35_PAD_TXD1__GPIO3_7 */
-	[365] = IMX_PIN_REG(MX35_PAD_TXD1, 0x5d0, 0x18c, 7, 0x0, 0), /* MX35_PAD_TXD1__ARM11P_TOP_EVNTBUS_17 */
-	[366] = IMX_PIN_REG(MX35_PAD_RTS1, 0x5d4, 0x190, 0, 0x0, 0), /* MX35_PAD_RTS1__UART1_RTS */
-	[367] = IMX_PIN_REG(MX35_PAD_RTS1, 0x5d4, 0x190, 1, 0x7e0, 1), /* MX35_PAD_RTS1__CSPI2_SCLK */
-	[368] = IMX_PIN_REG(MX35_PAD_RTS1, 0x5d4, 0x190, 2, 0x91c, 1), /* MX35_PAD_RTS1__I2C3_SCL */
-	[369] = IMX_PIN_REG(MX35_PAD_RTS1, 0x5d4, 0x190, 3, 0x930, 1), /* MX35_PAD_RTS1__IPU_CSI_D_0 */
-	[370] = IMX_PIN_REG(MX35_PAD_RTS1, 0x5d4, 0x190, 4, 0x968, 0), /* MX35_PAD_RTS1__KPP_COL_6 */
-	[371] = IMX_PIN_REG(MX35_PAD_RTS1, 0x5d4, 0x190, 5, 0x914, 0), /* MX35_PAD_RTS1__GPIO3_8 */
-	[372] = IMX_PIN_REG(MX35_PAD_RTS1, 0x5d4, 0x190, 6, 0x0, 0), /* MX35_PAD_RTS1__EMI_NANDF_CE1 */
-	[373] = IMX_PIN_REG(MX35_PAD_RTS1, 0x5d4, 0x190, 7, 0x0, 0), /* MX35_PAD_RTS1__ARM11P_TOP_EVNTBUS_18 */
-	[374] = IMX_PIN_REG(MX35_PAD_CTS1, 0x5d8, 0x194, 0, 0x0, 0), /* MX35_PAD_CTS1__UART1_CTS */
-	[375] = IMX_PIN_REG(MX35_PAD_CTS1, 0x5d8, 0x194, 1, 0x7e4, 1), /* MX35_PAD_CTS1__CSPI2_RDY */
-	[376] = IMX_PIN_REG(MX35_PAD_CTS1, 0x5d8, 0x194, 2, 0x920, 1), /* MX35_PAD_CTS1__I2C3_SDA */
-	[377] = IMX_PIN_REG(MX35_PAD_CTS1, 0x5d8, 0x194, 3, 0x934, 1), /* MX35_PAD_CTS1__IPU_CSI_D_1 */
-	[378] = IMX_PIN_REG(MX35_PAD_CTS1, 0x5d8, 0x194, 4, 0x96c, 0), /* MX35_PAD_CTS1__KPP_COL_7 */
-	[379] = IMX_PIN_REG(MX35_PAD_CTS1, 0x5d8, 0x194, 5, 0x918, 0), /* MX35_PAD_CTS1__GPIO3_9 */
-	[380] = IMX_PIN_REG(MX35_PAD_CTS1, 0x5d8, 0x194, 6, 0x0, 0), /* MX35_PAD_CTS1__EMI_NANDF_CE2 */
-	[381] = IMX_PIN_REG(MX35_PAD_CTS1, 0x5d8, 0x194, 7, 0x0, 0), /* MX35_PAD_CTS1__ARM11P_TOP_EVNTBUS_19 */
-	[382] = IMX_PIN_REG(MX35_PAD_RXD2, 0x5dc, 0x198, 0, 0x0, 0), /* MX35_PAD_RXD2__UART2_RXD_MUX */
-	[383] = IMX_PIN_REG(MX35_PAD_RXD2, 0x5dc, 0x198, 4, 0x980, 0), /* MX35_PAD_RXD2__KPP_ROW_4 */
-	[384] = IMX_PIN_REG(MX35_PAD_RXD2, 0x5dc, 0x198, 5, 0x8ec, 0), /* MX35_PAD_RXD2__GPIO3_10 */
-	[385] = IMX_PIN_REG(MX35_PAD_TXD2, 0x5e0, 0x19c, 0, 0x0, 0), /* MX35_PAD_TXD2__UART2_TXD_MUX */
-	[386] = IMX_PIN_REG(MX35_PAD_TXD2, 0x5e0, 0x19c, 1, 0x994, 2), /* MX35_PAD_TXD2__SPDIF_SPDIF_EXTCLK */
-	[387] = IMX_PIN_REG(MX35_PAD_TXD2, 0x5e0, 0x19c, 4, 0x984, 0), /* MX35_PAD_TXD2__KPP_ROW_5 */
-	[388] = IMX_PIN_REG(MX35_PAD_TXD2, 0x5e0, 0x19c, 5, 0x8f0, 0), /* MX35_PAD_TXD2__GPIO3_11 */
-	[389] = IMX_PIN_REG(MX35_PAD_RTS2, 0x5e4, 0x1a0, 0, 0x0, 0), /* MX35_PAD_RTS2__UART2_RTS */
-	[390] = IMX_PIN_REG(MX35_PAD_RTS2, 0x5e4, 0x1a0, 1, 0x998, 1), /* MX35_PAD_RTS2__SPDIF_SPDIF_IN1 */
-	[391] = IMX_PIN_REG(MX35_PAD_RTS2, 0x5e4, 0x1a0, 2, 0x7cc, 1), /* MX35_PAD_RTS2__CAN2_RXCAN */
-	[392] = IMX_PIN_REG(MX35_PAD_RTS2, 0x5e4, 0x1a0, 3, 0x938, 1), /* MX35_PAD_RTS2__IPU_CSI_D_2 */
-	[393] = IMX_PIN_REG(MX35_PAD_RTS2, 0x5e4, 0x1a0, 4, 0x988, 0), /* MX35_PAD_RTS2__KPP_ROW_6 */
-	[394] = IMX_PIN_REG(MX35_PAD_RTS2, 0x5e4, 0x1a0, 5, 0x8f4, 0), /* MX35_PAD_RTS2__GPIO3_12 */
-	[395] = IMX_PIN_REG(MX35_PAD_RTS2, 0x5e4, 0x1a0, 6, 0x0, 0), /* MX35_PAD_RTS2__AUDMUX_AUD5_RXC */
-	[396] = IMX_PIN_REG(MX35_PAD_RTS2, 0x5e4, 0x1a0, 7, 0x9a0, 0), /* MX35_PAD_RTS2__UART3_RXD_MUX */
-	[397] = IMX_PIN_REG(MX35_PAD_CTS2, 0x5e8, 0x1a4, 0, 0x0, 0), /* MX35_PAD_CTS2__UART2_CTS */
-	[398] = IMX_PIN_REG(MX35_PAD_CTS2, 0x5e8, 0x1a4, 1, 0x0, 0), /* MX35_PAD_CTS2__SPDIF_SPDIF_OUT1 */
-	[399] = IMX_PIN_REG(MX35_PAD_CTS2, 0x5e8, 0x1a4, 2, 0x0, 0), /* MX35_PAD_CTS2__CAN2_TXCAN */
-	[400] = IMX_PIN_REG(MX35_PAD_CTS2, 0x5e8, 0x1a4, 3, 0x93c, 1), /* MX35_PAD_CTS2__IPU_CSI_D_3 */
-	[401] = IMX_PIN_REG(MX35_PAD_CTS2, 0x5e8, 0x1a4, 4, 0x98c, 0), /* MX35_PAD_CTS2__KPP_ROW_7 */
-	[402] = IMX_PIN_REG(MX35_PAD_CTS2, 0x5e8, 0x1a4, 5, 0x8f8, 0), /* MX35_PAD_CTS2__GPIO3_13 */
-	[403] = IMX_PIN_REG(MX35_PAD_CTS2, 0x5e8, 0x1a4, 6, 0x0, 0), /* MX35_PAD_CTS2__AUDMUX_AUD5_RXFS */
-	[404] = IMX_PIN_REG(MX35_PAD_CTS2, 0x5e8, 0x1a4, 7, 0x0, 0), /* MX35_PAD_CTS2__UART3_TXD_MUX */
-	[405] = IMX_PIN_REG(MX35_PAD_RTCK, 0x5ec, 0x0, 0, 0x0, 0), /* MX35_PAD_RTCK__ARM11P_TOP_RTCK */
-	[406] = IMX_PIN_REG(MX35_PAD_TCK, 0x5f0, 0x0, 0, 0x0, 0), /* MX35_PAD_TCK__SJC_TCK */
-	[407] = IMX_PIN_REG(MX35_PAD_TMS, 0x5f4, 0x0, 0, 0x0, 0), /* MX35_PAD_TMS__SJC_TMS */
-	[408] = IMX_PIN_REG(MX35_PAD_TDI, 0x5f8, 0x0, 0, 0x0, 0), /* MX35_PAD_TDI__SJC_TDI */
-	[409] = IMX_PIN_REG(MX35_PAD_TDO, 0x5fc, 0x0, 0, 0x0, 0), /* MX35_PAD_TDO__SJC_TDO */
-	[410] = IMX_PIN_REG(MX35_PAD_TRSTB, 0x600, 0x0, 0, 0x0, 0), /* MX35_PAD_TRSTB__SJC_TRSTB */
-	[411] = IMX_PIN_REG(MX35_PAD_DE_B, 0x604, 0x0, 0, 0x0, 0), /* MX35_PAD_DE_B__SJC_DE_B */
-	[412] = IMX_PIN_REG(MX35_PAD_SJC_MOD, 0x608, 0x0, 0, 0x0, 0), /* MX35_PAD_SJC_MOD__SJC_MOD */
-	[413] = IMX_PIN_REG(MX35_PAD_USBOTG_PWR, 0x60c, 0x1a8, 0, 0x0, 0), /* MX35_PAD_USBOTG_PWR__USB_TOP_USBOTG_PWR */
-	[414] = IMX_PIN_REG(MX35_PAD_USBOTG_PWR, 0x60c, 0x1a8, 1, 0x0, 0), /* MX35_PAD_USBOTG_PWR__USB_TOP_USBH2_PWR */
-	[415] = IMX_PIN_REG(MX35_PAD_USBOTG_PWR, 0x60c, 0x1a8, 5, 0x8fc, 0), /* MX35_PAD_USBOTG_PWR__GPIO3_14 */
-	[416] = IMX_PIN_REG(MX35_PAD_USBOTG_OC, 0x610, 0x1ac, 0, 0x0, 0), /* MX35_PAD_USBOTG_OC__USB_TOP_USBOTG_OC */
-	[417] = IMX_PIN_REG(MX35_PAD_USBOTG_OC, 0x610, 0x1ac, 1, 0x9f4, 1), /* MX35_PAD_USBOTG_OC__USB_TOP_USBH2_OC */
-	[418] = IMX_PIN_REG(MX35_PAD_USBOTG_OC, 0x610, 0x1ac, 5, 0x900, 0), /* MX35_PAD_USBOTG_OC__GPIO3_15 */
-	[419] = IMX_PIN_REG(MX35_PAD_LD0, 0x614, 0x1b0, 0, 0x0, 0), /* MX35_PAD_LD0__IPU_DISPB_DAT_0 */
-	[420] = IMX_PIN_REG(MX35_PAD_LD0, 0x614, 0x1b0, 5, 0x868, 1), /* MX35_PAD_LD0__GPIO2_0 */
-	[421] = IMX_PIN_REG(MX35_PAD_LD0, 0x614, 0x1b0, 6, 0x0, 0), /* MX35_PAD_LD0__SDMA_SDMA_DEBUG_PC_0 */
-	[422] = IMX_PIN_REG(MX35_PAD_LD1, 0x618, 0x1b4, 0, 0x0, 0), /* MX35_PAD_LD1__IPU_DISPB_DAT_1 */
-	[423] = IMX_PIN_REG(MX35_PAD_LD1, 0x618, 0x1b4, 5, 0x894, 0), /* MX35_PAD_LD1__GPIO2_1 */
-	[424] = IMX_PIN_REG(MX35_PAD_LD1, 0x618, 0x1b4, 6, 0x0, 0), /* MX35_PAD_LD1__SDMA_SDMA_DEBUG_PC_1 */
-	[425] = IMX_PIN_REG(MX35_PAD_LD2, 0x61c, 0x1b8, 0, 0x0, 0), /* MX35_PAD_LD2__IPU_DISPB_DAT_2 */
-	[426] = IMX_PIN_REG(MX35_PAD_LD2, 0x61c, 0x1b8, 5, 0x8c0, 0), /* MX35_PAD_LD2__GPIO2_2 */
-	[427] = IMX_PIN_REG(MX35_PAD_LD2, 0x61c, 0x1b8, 6, 0x0, 0), /* MX35_PAD_LD2__SDMA_SDMA_DEBUG_PC_2 */
-	[428] = IMX_PIN_REG(MX35_PAD_LD3, 0x620, 0x1bc, 0, 0x0, 0), /* MX35_PAD_LD3__IPU_DISPB_DAT_3 */
-	[429] = IMX_PIN_REG(MX35_PAD_LD3, 0x620, 0x1bc, 5, 0x8cc, 0), /* MX35_PAD_LD3__GPIO2_3 */
-	[430] = IMX_PIN_REG(MX35_PAD_LD3, 0x620, 0x1bc, 6, 0x0, 0), /* MX35_PAD_LD3__SDMA_SDMA_DEBUG_PC_3 */
-	[431] = IMX_PIN_REG(MX35_PAD_LD4, 0x624, 0x1c0, 0, 0x0, 0), /* MX35_PAD_LD4__IPU_DISPB_DAT_4 */
-	[432] = IMX_PIN_REG(MX35_PAD_LD4, 0x624, 0x1c0, 5, 0x8d0, 0), /* MX35_PAD_LD4__GPIO2_4 */
-	[433] = IMX_PIN_REG(MX35_PAD_LD4, 0x624, 0x1c0, 6, 0x0, 0), /* MX35_PAD_LD4__SDMA_SDMA_DEBUG_PC_4 */
-	[434] = IMX_PIN_REG(MX35_PAD_LD5, 0x628, 0x1c4, 0, 0x0, 0), /* MX35_PAD_LD5__IPU_DISPB_DAT_5 */
-	[435] = IMX_PIN_REG(MX35_PAD_LD5, 0x628, 0x1c4, 5, 0x8d4, 0), /* MX35_PAD_LD5__GPIO2_5 */
-	[436] = IMX_PIN_REG(MX35_PAD_LD5, 0x628, 0x1c4, 6, 0x0, 0), /* MX35_PAD_LD5__SDMA_SDMA_DEBUG_PC_5 */
-	[437] = IMX_PIN_REG(MX35_PAD_LD6, 0x62c, 0x1c8, 0, 0x0, 0), /* MX35_PAD_LD6__IPU_DISPB_DAT_6 */
-	[438] = IMX_PIN_REG(MX35_PAD_LD6, 0x62c, 0x1c8, 5, 0x8d8, 0), /* MX35_PAD_LD6__GPIO2_6 */
-	[439] = IMX_PIN_REG(MX35_PAD_LD6, 0x62c, 0x1c8, 6, 0x0, 0), /* MX35_PAD_LD6__SDMA_SDMA_DEBUG_PC_6 */
-	[440] = IMX_PIN_REG(MX35_PAD_LD7, 0x630, 0x1cc, 0, 0x0, 0), /* MX35_PAD_LD7__IPU_DISPB_DAT_7 */
-	[441] = IMX_PIN_REG(MX35_PAD_LD7, 0x630, 0x1cc, 5, 0x8dc, 0), /* MX35_PAD_LD7__GPIO2_7 */
-	[442] = IMX_PIN_REG(MX35_PAD_LD7, 0x630, 0x1cc, 6, 0x0, 0), /* MX35_PAD_LD7__SDMA_SDMA_DEBUG_PC_7 */
-	[443] = IMX_PIN_REG(MX35_PAD_LD8, 0x634, 0x1d0, 0, 0x0, 0), /* MX35_PAD_LD8__IPU_DISPB_DAT_8 */
-	[444] = IMX_PIN_REG(MX35_PAD_LD8, 0x634, 0x1d0, 5, 0x8e0, 0), /* MX35_PAD_LD8__GPIO2_8 */
-	[445] = IMX_PIN_REG(MX35_PAD_LD8, 0x634, 0x1d0, 6, 0x0, 0), /* MX35_PAD_LD8__SDMA_SDMA_DEBUG_PC_8 */
-	[446] = IMX_PIN_REG(MX35_PAD_LD9, 0x638, 0x1d4, 0, 0x0, 0), /* MX35_PAD_LD9__IPU_DISPB_DAT_9 */
-	[447] = IMX_PIN_REG(MX35_PAD_LD9, 0x638, 0x1d4, 5, 0x8e4, 0), /* MX35_PAD_LD9__GPIO2_9 */
-	[448] = IMX_PIN_REG(MX35_PAD_LD9, 0x638, 0x1d4, 6, 0x0, 0), /* MX35_PAD_LD9__SDMA_SDMA_DEBUG_PC_9 */
-	[449] = IMX_PIN_REG(MX35_PAD_LD10, 0x63c, 0x1d8, 0, 0x0, 0), /* MX35_PAD_LD10__IPU_DISPB_DAT_10 */
-	[450] = IMX_PIN_REG(MX35_PAD_LD10, 0x63c, 0x1d8, 5, 0x86c, 0), /* MX35_PAD_LD10__GPIO2_10 */
-	[451] = IMX_PIN_REG(MX35_PAD_LD10, 0x63c, 0x1d8, 6, 0x0, 0), /* MX35_PAD_LD10__SDMA_SDMA_DEBUG_PC_10 */
-	[452] = IMX_PIN_REG(MX35_PAD_LD11, 0x640, 0x1dc, 0, 0x0, 0), /* MX35_PAD_LD11__IPU_DISPB_DAT_11 */
-	[453] = IMX_PIN_REG(MX35_PAD_LD11, 0x640, 0x1dc, 5, 0x870, 0), /* MX35_PAD_LD11__GPIO2_11 */
-	[454] = IMX_PIN_REG(MX35_PAD_LD11, 0x640, 0x1dc, 6, 0x0, 0), /* MX35_PAD_LD11__SDMA_SDMA_DEBUG_PC_11 */
-	[455] = IMX_PIN_REG(MX35_PAD_LD11, 0x640, 0x1dc, 7, 0x0, 0), /* MX35_PAD_LD11__ARM11P_TOP_TRACE_4 */
-	[456] = IMX_PIN_REG(MX35_PAD_LD12, 0x644, 0x1e0, 0, 0x0, 0), /* MX35_PAD_LD12__IPU_DISPB_DAT_12 */
-	[457] = IMX_PIN_REG(MX35_PAD_LD12, 0x644, 0x1e0, 5, 0x874, 0), /* MX35_PAD_LD12__GPIO2_12 */
-	[458] = IMX_PIN_REG(MX35_PAD_LD12, 0x644, 0x1e0, 6, 0x0, 0), /* MX35_PAD_LD12__SDMA_SDMA_DEBUG_PC_12 */
-	[459] = IMX_PIN_REG(MX35_PAD_LD12, 0x644, 0x1e0, 7, 0x0, 0), /* MX35_PAD_LD12__ARM11P_TOP_TRACE_5 */
-	[460] = IMX_PIN_REG(MX35_PAD_LD13, 0x648, 0x1e4, 0, 0x0, 0), /* MX35_PAD_LD13__IPU_DISPB_DAT_13 */
-	[461] = IMX_PIN_REG(MX35_PAD_LD13, 0x648, 0x1e4, 5, 0x878, 0), /* MX35_PAD_LD13__GPIO2_13 */
-	[462] = IMX_PIN_REG(MX35_PAD_LD13, 0x648, 0x1e4, 6, 0x0, 0), /* MX35_PAD_LD13__SDMA_SDMA_DEBUG_PC_13 */
-	[463] = IMX_PIN_REG(MX35_PAD_LD13, 0x648, 0x1e4, 7, 0x0, 0), /* MX35_PAD_LD13__ARM11P_TOP_TRACE_6 */
-	[464] = IMX_PIN_REG(MX35_PAD_LD14, 0x64c, 0x1e8, 0, 0x0, 0), /* MX35_PAD_LD14__IPU_DISPB_DAT_14 */
-	[465] = IMX_PIN_REG(MX35_PAD_LD14, 0x64c, 0x1e8, 5, 0x87c, 0), /* MX35_PAD_LD14__GPIO2_14 */
-	[466] = IMX_PIN_REG(MX35_PAD_LD14, 0x64c, 0x1e8, 6, 0x0, 0), /* MX35_PAD_LD14__SDMA_SDMA_DEBUG_EVENT_CHANNEL_0 */
-	[467] = IMX_PIN_REG(MX35_PAD_LD14, 0x64c, 0x1e8, 7, 0x0, 0), /* MX35_PAD_LD14__ARM11P_TOP_TRACE_7 */
-	[468] = IMX_PIN_REG(MX35_PAD_LD15, 0x650, 0x1ec, 0, 0x0, 0), /* MX35_PAD_LD15__IPU_DISPB_DAT_15 */
-	[469] = IMX_PIN_REG(MX35_PAD_LD15, 0x650, 0x1ec, 5, 0x880, 0), /* MX35_PAD_LD15__GPIO2_15 */
-	[470] = IMX_PIN_REG(MX35_PAD_LD15, 0x650, 0x1ec, 6, 0x0, 0), /* MX35_PAD_LD15__SDMA_SDMA_DEBUG_EVENT_CHANNEL_1 */
-	[471] = IMX_PIN_REG(MX35_PAD_LD15, 0x650, 0x1ec, 7, 0x0, 0), /* MX35_PAD_LD15__ARM11P_TOP_TRACE_8 */
-	[472] = IMX_PIN_REG(MX35_PAD_LD16, 0x654, 0x1f0, 0, 0x0, 0), /* MX35_PAD_LD16__IPU_DISPB_DAT_16 */
-	[473] = IMX_PIN_REG(MX35_PAD_LD16, 0x654, 0x1f0, 2, 0x928, 0), /* MX35_PAD_LD16__IPU_DISPB_D12_VSYNC */
-	[474] = IMX_PIN_REG(MX35_PAD_LD16, 0x654, 0x1f0, 5, 0x884, 0), /* MX35_PAD_LD16__GPIO2_16 */
-	[475] = IMX_PIN_REG(MX35_PAD_LD16, 0x654, 0x1f0, 6, 0x0, 0), /* MX35_PAD_LD16__SDMA_SDMA_DEBUG_EVENT_CHANNEL_2 */
-	[476] = IMX_PIN_REG(MX35_PAD_LD16, 0x654, 0x1f0, 7, 0x0, 0), /* MX35_PAD_LD16__ARM11P_TOP_TRACE_9 */
-	[477] = IMX_PIN_REG(MX35_PAD_LD17, 0x658, 0x1f4, 0, 0x0, 0), /* MX35_PAD_LD17__IPU_DISPB_DAT_17 */
-	[478] = IMX_PIN_REG(MX35_PAD_LD17, 0x658, 0x1f4, 2, 0x0, 0), /* MX35_PAD_LD17__IPU_DISPB_CS2 */
-	[479] = IMX_PIN_REG(MX35_PAD_LD17, 0x658, 0x1f4, 5, 0x888, 0), /* MX35_PAD_LD17__GPIO2_17 */
-	[480] = IMX_PIN_REG(MX35_PAD_LD17, 0x658, 0x1f4, 6, 0x0, 0), /* MX35_PAD_LD17__SDMA_SDMA_DEBUG_EVENT_CHANNEL_3 */
-	[481] = IMX_PIN_REG(MX35_PAD_LD17, 0x658, 0x1f4, 7, 0x0, 0), /* MX35_PAD_LD17__ARM11P_TOP_TRACE_10 */
-	[482] = IMX_PIN_REG(MX35_PAD_LD18, 0x65c, 0x1f8, 0, 0x0, 0), /* MX35_PAD_LD18__IPU_DISPB_DAT_18 */
-	[483] = IMX_PIN_REG(MX35_PAD_LD18, 0x65c, 0x1f8, 1, 0x924, 1), /* MX35_PAD_LD18__IPU_DISPB_D0_VSYNC */
-	[484] = IMX_PIN_REG(MX35_PAD_LD18, 0x65c, 0x1f8, 2, 0x928, 1), /* MX35_PAD_LD18__IPU_DISPB_D12_VSYNC */
-	[485] = IMX_PIN_REG(MX35_PAD_LD18, 0x65c, 0x1f8, 3, 0x818, 0), /* MX35_PAD_LD18__ESDHC3_CMD */
-	[486] = IMX_PIN_REG(MX35_PAD_LD18, 0x65c, 0x1f8, 4, 0x9b0, 0), /* MX35_PAD_LD18__USB_TOP_USBOTG_DATA_3 */
-	[487] = IMX_PIN_REG(MX35_PAD_LD18, 0x65c, 0x1f8, 5, 0x0, 0), /* MX35_PAD_LD18__GPIO3_24 */
-	[488] = IMX_PIN_REG(MX35_PAD_LD18, 0x65c, 0x1f8, 6, 0x0, 0), /* MX35_PAD_LD18__SDMA_SDMA_DEBUG_EVENT_CHANNEL_4 */
-	[489] = IMX_PIN_REG(MX35_PAD_LD18, 0x65c, 0x1f8, 7, 0x0, 0), /* MX35_PAD_LD18__ARM11P_TOP_TRACE_11 */
-	[490] = IMX_PIN_REG(MX35_PAD_LD19, 0x660, 0x1fc, 0, 0x0, 0), /* MX35_PAD_LD19__IPU_DISPB_DAT_19 */
-	[491] = IMX_PIN_REG(MX35_PAD_LD19, 0x660, 0x1fc, 1, 0x0, 0), /* MX35_PAD_LD19__IPU_DISPB_BCLK */
-	[492] = IMX_PIN_REG(MX35_PAD_LD19, 0x660, 0x1fc, 2, 0x0, 0), /* MX35_PAD_LD19__IPU_DISPB_CS1 */
-	[493] = IMX_PIN_REG(MX35_PAD_LD19, 0x660, 0x1fc, 3, 0x814, 0), /* MX35_PAD_LD19__ESDHC3_CLK */
-	[494] = IMX_PIN_REG(MX35_PAD_LD19, 0x660, 0x1fc, 4, 0x9c4, 0), /* MX35_PAD_LD19__USB_TOP_USBOTG_DIR */
-	[495] = IMX_PIN_REG(MX35_PAD_LD19, 0x660, 0x1fc, 5, 0x0, 0), /* MX35_PAD_LD19__GPIO3_25 */
-	[496] = IMX_PIN_REG(MX35_PAD_LD19, 0x660, 0x1fc, 6, 0x0, 0), /* MX35_PAD_LD19__SDMA_SDMA_DEBUG_EVENT_CHANNEL_5 */
-	[497] = IMX_PIN_REG(MX35_PAD_LD19, 0x660, 0x1fc, 7, 0x0, 0), /* MX35_PAD_LD19__ARM11P_TOP_TRACE_12 */
-	[498] = IMX_PIN_REG(MX35_PAD_LD20, 0x664, 0x200, 0, 0x0, 0), /* MX35_PAD_LD20__IPU_DISPB_DAT_20 */
-	[499] = IMX_PIN_REG(MX35_PAD_LD20, 0x664, 0x200, 1, 0x0, 0), /* MX35_PAD_LD20__IPU_DISPB_CS0 */
-	[500] = IMX_PIN_REG(MX35_PAD_LD20, 0x664, 0x200, 2, 0x0, 0), /* MX35_PAD_LD20__IPU_DISPB_SD_CLK */
-	[501] = IMX_PIN_REG(MX35_PAD_LD20, 0x664, 0x200, 3, 0x81c, 0), /* MX35_PAD_LD20__ESDHC3_DAT0 */
-	[502] = IMX_PIN_REG(MX35_PAD_LD20, 0x664, 0x200, 5, 0x0, 0), /* MX35_PAD_LD20__GPIO3_26 */
-	[503] = IMX_PIN_REG(MX35_PAD_LD20, 0x664, 0x200, 6, 0x0, 0), /* MX35_PAD_LD20__SDMA_SDMA_DEBUG_CORE_STATUS_3 */
-	[504] = IMX_PIN_REG(MX35_PAD_LD20, 0x664, 0x200, 7, 0x0, 0), /* MX35_PAD_LD20__ARM11P_TOP_TRACE_13 */
-	[505] = IMX_PIN_REG(MX35_PAD_LD21, 0x668, 0x204, 0, 0x0, 0), /* MX35_PAD_LD21__IPU_DISPB_DAT_21 */
-	[506] = IMX_PIN_REG(MX35_PAD_LD21, 0x668, 0x204, 1, 0x0, 0), /* MX35_PAD_LD21__IPU_DISPB_PAR_RS */
-	[507] = IMX_PIN_REG(MX35_PAD_LD21, 0x668, 0x204, 2, 0x0, 0), /* MX35_PAD_LD21__IPU_DISPB_SER_RS */
-	[508] = IMX_PIN_REG(MX35_PAD_LD21, 0x668, 0x204, 3, 0x820, 0), /* MX35_PAD_LD21__ESDHC3_DAT1 */
-	[509] = IMX_PIN_REG(MX35_PAD_LD21, 0x668, 0x204, 4, 0x0, 0), /* MX35_PAD_LD21__USB_TOP_USBOTG_STP */
-	[510] = IMX_PIN_REG(MX35_PAD_LD21, 0x668, 0x204, 5, 0x0, 0), /* MX35_PAD_LD21__GPIO3_27 */
-	[511] = IMX_PIN_REG(MX35_PAD_LD21, 0x668, 0x204, 6, 0x0, 0), /* MX35_PAD_LD21__SDMA_DEBUG_EVENT_CHANNEL_SEL */
-	[512] = IMX_PIN_REG(MX35_PAD_LD21, 0x668, 0x204, 7, 0x0, 0), /* MX35_PAD_LD21__ARM11P_TOP_TRACE_14 */
-	[513] = IMX_PIN_REG(MX35_PAD_LD22, 0x66c, 0x208, 0, 0x0, 0), /* MX35_PAD_LD22__IPU_DISPB_DAT_22 */
-	[514] = IMX_PIN_REG(MX35_PAD_LD22, 0x66c, 0x208, 1, 0x0, 0), /* MX35_PAD_LD22__IPU_DISPB_WR */
-	[515] = IMX_PIN_REG(MX35_PAD_LD22, 0x66c, 0x208, 2, 0x92c, 0), /* MX35_PAD_LD22__IPU_DISPB_SD_D_I */
-	[516] = IMX_PIN_REG(MX35_PAD_LD22, 0x66c, 0x208, 3, 0x824, 0), /* MX35_PAD_LD22__ESDHC3_DAT2 */
-	[517] = IMX_PIN_REG(MX35_PAD_LD22, 0x66c, 0x208, 4, 0x9c8, 0), /* MX35_PAD_LD22__USB_TOP_USBOTG_NXT */
-	[518] = IMX_PIN_REG(MX35_PAD_LD22, 0x66c, 0x208, 5, 0x0, 0), /* MX35_PAD_LD22__GPIO3_28 */
-	[519] = IMX_PIN_REG(MX35_PAD_LD22, 0x66c, 0x208, 6, 0x0, 0), /* MX35_PAD_LD22__SDMA_DEBUG_BUS_ERROR */
-	[520] = IMX_PIN_REG(MX35_PAD_LD22, 0x66c, 0x208, 7, 0x0, 0), /* MX35_PAD_LD22__ARM11P_TOP_TRCTL */
-	[521] = IMX_PIN_REG(MX35_PAD_LD23, 0x670, 0x20c, 0, 0x0, 0), /* MX35_PAD_LD23__IPU_DISPB_DAT_23 */
-	[522] = IMX_PIN_REG(MX35_PAD_LD23, 0x670, 0x20c, 1, 0x0, 0), /* MX35_PAD_LD23__IPU_DISPB_RD */
-	[523] = IMX_PIN_REG(MX35_PAD_LD23, 0x670, 0x20c, 2, 0x92c, 1), /* MX35_PAD_LD23__IPU_DISPB_SD_D_IO */
-	[524] = IMX_PIN_REG(MX35_PAD_LD23, 0x670, 0x20c, 3, 0x828, 0), /* MX35_PAD_LD23__ESDHC3_DAT3 */
-	[525] = IMX_PIN_REG(MX35_PAD_LD23, 0x670, 0x20c, 4, 0x9c0, 0), /* MX35_PAD_LD23__USB_TOP_USBOTG_DATA_7 */
-	[526] = IMX_PIN_REG(MX35_PAD_LD23, 0x670, 0x20c, 5, 0x0, 0), /* MX35_PAD_LD23__GPIO3_29 */
-	[527] = IMX_PIN_REG(MX35_PAD_LD23, 0x670, 0x20c, 6, 0x0, 0), /* MX35_PAD_LD23__SDMA_DEBUG_MATCHED_DMBUS */
-	[528] = IMX_PIN_REG(MX35_PAD_LD23, 0x670, 0x20c, 7, 0x0, 0), /* MX35_PAD_LD23__ARM11P_TOP_TRCLK */
-	[529] = IMX_PIN_REG(MX35_PAD_D3_HSYNC, 0x674, 0x210, 0, 0x0, 0), /* MX35_PAD_D3_HSYNC__IPU_DISPB_D3_HSYNC */
-	[530] = IMX_PIN_REG(MX35_PAD_D3_HSYNC, 0x674, 0x210, 2, 0x92c, 2), /* MX35_PAD_D3_HSYNC__IPU_DISPB_SD_D_IO */
-	[531] = IMX_PIN_REG(MX35_PAD_D3_HSYNC, 0x674, 0x210, 5, 0x0, 0), /* MX35_PAD_D3_HSYNC__GPIO3_30 */
-	[532] = IMX_PIN_REG(MX35_PAD_D3_HSYNC, 0x674, 0x210, 6, 0x0, 0), /* MX35_PAD_D3_HSYNC__SDMA_DEBUG_RTBUFFER_WRITE */
-	[533] = IMX_PIN_REG(MX35_PAD_D3_HSYNC, 0x674, 0x210, 7, 0x0, 0), /* MX35_PAD_D3_HSYNC__ARM11P_TOP_TRACE_15 */
-	[534] = IMX_PIN_REG(MX35_PAD_D3_FPSHIFT, 0x678, 0x214, 0, 0x0, 0), /* MX35_PAD_D3_FPSHIFT__IPU_DISPB_D3_CLK */
-	[535] = IMX_PIN_REG(MX35_PAD_D3_FPSHIFT, 0x678, 0x214, 2, 0x0, 0), /* MX35_PAD_D3_FPSHIFT__IPU_DISPB_SD_CLK */
-	[536] = IMX_PIN_REG(MX35_PAD_D3_FPSHIFT, 0x678, 0x214, 5, 0x0, 0), /* MX35_PAD_D3_FPSHIFT__GPIO3_31 */
-	[537] = IMX_PIN_REG(MX35_PAD_D3_FPSHIFT, 0x678, 0x214, 6, 0x0, 0), /* MX35_PAD_D3_FPSHIFT__SDMA_SDMA_DEBUG_CORE_STATUS_0 */
-	[538] = IMX_PIN_REG(MX35_PAD_D3_FPSHIFT, 0x678, 0x214, 7, 0x0, 0), /* MX35_PAD_D3_FPSHIFT__ARM11P_TOP_TRACE_16 */
-	[539] = IMX_PIN_REG(MX35_PAD_D3_DRDY, 0x67c, 0x218, 0, 0x0, 0), /* MX35_PAD_D3_DRDY__IPU_DISPB_D3_DRDY */
-	[540] = IMX_PIN_REG(MX35_PAD_D3_DRDY, 0x67c, 0x218, 2, 0x0, 0), /* MX35_PAD_D3_DRDY__IPU_DISPB_SD_D_O */
-	[541] = IMX_PIN_REG(MX35_PAD_D3_DRDY, 0x67c, 0x218, 5, 0x82c, 2), /* MX35_PAD_D3_DRDY__GPIO1_0 */
-	[542] = IMX_PIN_REG(MX35_PAD_D3_DRDY, 0x67c, 0x218, 6, 0x0, 0), /* MX35_PAD_D3_DRDY__SDMA_SDMA_DEBUG_CORE_STATUS_1 */
-	[543] = IMX_PIN_REG(MX35_PAD_D3_DRDY, 0x67c, 0x218, 7, 0x0, 0), /* MX35_PAD_D3_DRDY__ARM11P_TOP_TRACE_17 */
-	[544] = IMX_PIN_REG(MX35_PAD_CONTRAST, 0x680, 0x21c, 0, 0x0, 0), /* MX35_PAD_CONTRAST__IPU_DISPB_CONTR */
-	[545] = IMX_PIN_REG(MX35_PAD_CONTRAST, 0x680, 0x21c, 5, 0x838, 2), /* MX35_PAD_CONTRAST__GPIO1_1 */
-	[546] = IMX_PIN_REG(MX35_PAD_CONTRAST, 0x680, 0x21c, 6, 0x0, 0), /* MX35_PAD_CONTRAST__SDMA_SDMA_DEBUG_CORE_STATUS_2 */
-	[547] = IMX_PIN_REG(MX35_PAD_CONTRAST, 0x680, 0x21c, 7, 0x0, 0), /* MX35_PAD_CONTRAST__ARM11P_TOP_TRACE_18 */
-	[548] = IMX_PIN_REG(MX35_PAD_D3_VSYNC, 0x684, 0x220, 0, 0x0, 0), /* MX35_PAD_D3_VSYNC__IPU_DISPB_D3_VSYNC */
-	[549] = IMX_PIN_REG(MX35_PAD_D3_VSYNC, 0x684, 0x220, 2, 0x0, 0), /* MX35_PAD_D3_VSYNC__IPU_DISPB_CS1 */
-	[550] = IMX_PIN_REG(MX35_PAD_D3_VSYNC, 0x684, 0x220, 5, 0x848, 1), /* MX35_PAD_D3_VSYNC__GPIO1_2 */
-	[551] = IMX_PIN_REG(MX35_PAD_D3_VSYNC, 0x684, 0x220, 6, 0x0, 0), /* MX35_PAD_D3_VSYNC__SDMA_DEBUG_YIELD */
-	[552] = IMX_PIN_REG(MX35_PAD_D3_VSYNC, 0x684, 0x220, 7, 0x0, 0), /* MX35_PAD_D3_VSYNC__ARM11P_TOP_TRACE_19 */
-	[553] = IMX_PIN_REG(MX35_PAD_D3_REV, 0x688, 0x224, 0, 0x0, 0), /* MX35_PAD_D3_REV__IPU_DISPB_D3_REV */
-	[554] = IMX_PIN_REG(MX35_PAD_D3_REV, 0x688, 0x224, 2, 0x0, 0), /* MX35_PAD_D3_REV__IPU_DISPB_SER_RS */
-	[555] = IMX_PIN_REG(MX35_PAD_D3_REV, 0x688, 0x224, 5, 0x84c, 1), /* MX35_PAD_D3_REV__GPIO1_3 */
-	[556] = IMX_PIN_REG(MX35_PAD_D3_REV, 0x688, 0x224, 6, 0x0, 0), /* MX35_PAD_D3_REV__SDMA_DEBUG_BUS_RWB */
-	[557] = IMX_PIN_REG(MX35_PAD_D3_REV, 0x688, 0x224, 7, 0x0, 0), /* MX35_PAD_D3_REV__ARM11P_TOP_TRACE_20 */
-	[558] = IMX_PIN_REG(MX35_PAD_D3_CLS, 0x68c, 0x228, 0, 0x0, 0), /* MX35_PAD_D3_CLS__IPU_DISPB_D3_CLS */
-	[559] = IMX_PIN_REG(MX35_PAD_D3_CLS, 0x68c, 0x228, 2, 0x0, 0), /* MX35_PAD_D3_CLS__IPU_DISPB_CS2 */
-	[560] = IMX_PIN_REG(MX35_PAD_D3_CLS, 0x68c, 0x228, 5, 0x850, 2), /* MX35_PAD_D3_CLS__GPIO1_4 */
-	[561] = IMX_PIN_REG(MX35_PAD_D3_CLS, 0x68c, 0x228, 6, 0x0, 0), /* MX35_PAD_D3_CLS__SDMA_DEBUG_BUS_DEVICE_0 */
-	[562] = IMX_PIN_REG(MX35_PAD_D3_CLS, 0x68c, 0x228, 7, 0x0, 0), /* MX35_PAD_D3_CLS__ARM11P_TOP_TRACE_21 */
-	[563] = IMX_PIN_REG(MX35_PAD_D3_SPL, 0x690, 0x22c, 0, 0x0, 0), /* MX35_PAD_D3_SPL__IPU_DISPB_D3_SPL */
-	[564] = IMX_PIN_REG(MX35_PAD_D3_SPL, 0x690, 0x22c, 2, 0x928, 2), /* MX35_PAD_D3_SPL__IPU_DISPB_D12_VSYNC */
-	[565] = IMX_PIN_REG(MX35_PAD_D3_SPL, 0x690, 0x22c, 5, 0x854, 2), /* MX35_PAD_D3_SPL__GPIO1_5 */
-	[566] = IMX_PIN_REG(MX35_PAD_D3_SPL, 0x690, 0x22c, 6, 0x0, 0), /* MX35_PAD_D3_SPL__SDMA_DEBUG_BUS_DEVICE_1 */
-	[567] = IMX_PIN_REG(MX35_PAD_D3_SPL, 0x690, 0x22c, 7, 0x0, 0), /* MX35_PAD_D3_SPL__ARM11P_TOP_TRACE_22 */
-	[568] = IMX_PIN_REG(MX35_PAD_SD1_CMD, 0x694, 0x230, 0, 0x0, 0), /* MX35_PAD_SD1_CMD__ESDHC1_CMD */
-	[569] = IMX_PIN_REG(MX35_PAD_SD1_CMD, 0x694, 0x230, 1, 0x0, 0), /* MX35_PAD_SD1_CMD__MSHC_SCLK */
-	[570] = IMX_PIN_REG(MX35_PAD_SD1_CMD, 0x694, 0x230, 3, 0x924, 2), /* MX35_PAD_SD1_CMD__IPU_DISPB_D0_VSYNC */
-	[571] = IMX_PIN_REG(MX35_PAD_SD1_CMD, 0x694, 0x230, 4, 0x9b4, 0), /* MX35_PAD_SD1_CMD__USB_TOP_USBOTG_DATA_4 */
-	[572] = IMX_PIN_REG(MX35_PAD_SD1_CMD, 0x694, 0x230, 5, 0x858, 2), /* MX35_PAD_SD1_CMD__GPIO1_6 */
-	[573] = IMX_PIN_REG(MX35_PAD_SD1_CMD, 0x694, 0x230, 7, 0x0, 0), /* MX35_PAD_SD1_CMD__ARM11P_TOP_TRCTL */
-	[574] = IMX_PIN_REG(MX35_PAD_SD1_CLK, 0x698, 0x234, 0, 0x0, 0), /* MX35_PAD_SD1_CLK__ESDHC1_CLK */
-	[575] = IMX_PIN_REG(MX35_PAD_SD1_CLK, 0x698, 0x234, 1, 0x0, 0), /* MX35_PAD_SD1_CLK__MSHC_BS */
-	[576] = IMX_PIN_REG(MX35_PAD_SD1_CLK, 0x698, 0x234, 3, 0x0, 0), /* MX35_PAD_SD1_CLK__IPU_DISPB_BCLK */
-	[577] = IMX_PIN_REG(MX35_PAD_SD1_CLK, 0x698, 0x234, 4, 0x9b8, 0), /* MX35_PAD_SD1_CLK__USB_TOP_USBOTG_DATA_5 */
-	[578] = IMX_PIN_REG(MX35_PAD_SD1_CLK, 0x698, 0x234, 5, 0x85c, 2), /* MX35_PAD_SD1_CLK__GPIO1_7 */
-	[579] = IMX_PIN_REG(MX35_PAD_SD1_CLK, 0x698, 0x234, 7, 0x0, 0), /* MX35_PAD_SD1_CLK__ARM11P_TOP_TRCLK */
-	[580] = IMX_PIN_REG(MX35_PAD_SD1_DATA0, 0x69c, 0x238, 0, 0x0, 0), /* MX35_PAD_SD1_DATA0__ESDHC1_DAT0 */
-	[581] = IMX_PIN_REG(MX35_PAD_SD1_DATA0, 0x69c, 0x238, 1, 0x0, 0), /* MX35_PAD_SD1_DATA0__MSHC_DATA_0 */
-	[582] = IMX_PIN_REG(MX35_PAD_SD1_DATA0, 0x69c, 0x238, 3, 0x0, 0), /* MX35_PAD_SD1_DATA0__IPU_DISPB_CS0 */
-	[583] = IMX_PIN_REG(MX35_PAD_SD1_DATA0, 0x69c, 0x238, 4, 0x9bc, 0), /* MX35_PAD_SD1_DATA0__USB_TOP_USBOTG_DATA_6 */
-	[584] = IMX_PIN_REG(MX35_PAD_SD1_DATA0, 0x69c, 0x238, 5, 0x860, 2), /* MX35_PAD_SD1_DATA0__GPIO1_8 */
-	[585] = IMX_PIN_REG(MX35_PAD_SD1_DATA0, 0x69c, 0x238, 7, 0x0, 0), /* MX35_PAD_SD1_DATA0__ARM11P_TOP_TRACE_23 */
-	[586] = IMX_PIN_REG(MX35_PAD_SD1_DATA1, 0x6a0, 0x23c, 0, 0x0, 0), /* MX35_PAD_SD1_DATA1__ESDHC1_DAT1 */
-	[587] = IMX_PIN_REG(MX35_PAD_SD1_DATA1, 0x6a0, 0x23c, 1, 0x0, 0), /* MX35_PAD_SD1_DATA1__MSHC_DATA_1 */
-	[588] = IMX_PIN_REG(MX35_PAD_SD1_DATA1, 0x6a0, 0x23c, 3, 0x0, 0), /* MX35_PAD_SD1_DATA1__IPU_DISPB_PAR_RS */
-	[589] = IMX_PIN_REG(MX35_PAD_SD1_DATA1, 0x6a0, 0x23c, 4, 0x9a4, 0), /* MX35_PAD_SD1_DATA1__USB_TOP_USBOTG_DATA_0 */
-	[590] = IMX_PIN_REG(MX35_PAD_SD1_DATA1, 0x6a0, 0x23c, 5, 0x864, 1), /* MX35_PAD_SD1_DATA1__GPIO1_9 */
-	[591] = IMX_PIN_REG(MX35_PAD_SD1_DATA1, 0x6a0, 0x23c, 7, 0x0, 0), /* MX35_PAD_SD1_DATA1__ARM11P_TOP_TRACE_24 */
-	[592] = IMX_PIN_REG(MX35_PAD_SD1_DATA2, 0x6a4, 0x240, 0, 0x0, 0), /* MX35_PAD_SD1_DATA2__ESDHC1_DAT2 */
-	[593] = IMX_PIN_REG(MX35_PAD_SD1_DATA2, 0x6a4, 0x240, 1, 0x0, 0), /* MX35_PAD_SD1_DATA2__MSHC_DATA_2 */
-	[594] = IMX_PIN_REG(MX35_PAD_SD1_DATA2, 0x6a4, 0x240, 3, 0x0, 0), /* MX35_PAD_SD1_DATA2__IPU_DISPB_WR */
-	[595] = IMX_PIN_REG(MX35_PAD_SD1_DATA2, 0x6a4, 0x240, 4, 0x9a8, 0), /* MX35_PAD_SD1_DATA2__USB_TOP_USBOTG_DATA_1 */
-	[596] = IMX_PIN_REG(MX35_PAD_SD1_DATA2, 0x6a4, 0x240, 5, 0x830, 1), /* MX35_PAD_SD1_DATA2__GPIO1_10 */
-	[597] = IMX_PIN_REG(MX35_PAD_SD1_DATA2, 0x6a4, 0x240, 7, 0x0, 0), /* MX35_PAD_SD1_DATA2__ARM11P_TOP_TRACE_25 */
-	[598] = IMX_PIN_REG(MX35_PAD_SD1_DATA3, 0x6a8, 0x244, 0, 0x0, 0), /* MX35_PAD_SD1_DATA3__ESDHC1_DAT3 */
-	[599] = IMX_PIN_REG(MX35_PAD_SD1_DATA3, 0x6a8, 0x244, 1, 0x0, 0), /* MX35_PAD_SD1_DATA3__MSHC_DATA_3 */
-	[600] = IMX_PIN_REG(MX35_PAD_SD1_DATA3, 0x6a8, 0x244, 3, 0x0, 0), /* MX35_PAD_SD1_DATA3__IPU_DISPB_RD */
-	[601] = IMX_PIN_REG(MX35_PAD_SD1_DATA3, 0x6a8, 0x244, 4, 0x9ac, 0), /* MX35_PAD_SD1_DATA3__USB_TOP_USBOTG_DATA_2 */
-	[602] = IMX_PIN_REG(MX35_PAD_SD1_DATA3, 0x6a8, 0x244, 5, 0x834, 1), /* MX35_PAD_SD1_DATA3__GPIO1_11 */
-	[603] = IMX_PIN_REG(MX35_PAD_SD1_DATA3, 0x6a8, 0x244, 7, 0x0, 0), /* MX35_PAD_SD1_DATA3__ARM11P_TOP_TRACE_26 */
-	[604] = IMX_PIN_REG(MX35_PAD_SD2_CMD, 0x6ac, 0x248, 0, 0x0, 0), /* MX35_PAD_SD2_CMD__ESDHC2_CMD */
-	[605] = IMX_PIN_REG(MX35_PAD_SD2_CMD, 0x6ac, 0x248, 1, 0x91c, 2), /* MX35_PAD_SD2_CMD__I2C3_SCL */
-	[606] = IMX_PIN_REG(MX35_PAD_SD2_CMD, 0x6ac, 0x248, 2, 0x804, 0), /* MX35_PAD_SD2_CMD__ESDHC1_DAT4 */
-	[607] = IMX_PIN_REG(MX35_PAD_SD2_CMD, 0x6ac, 0x248, 3, 0x938, 2), /* MX35_PAD_SD2_CMD__IPU_CSI_D_2 */
-	[608] = IMX_PIN_REG(MX35_PAD_SD2_CMD, 0x6ac, 0x248, 4, 0x9dc, 0), /* MX35_PAD_SD2_CMD__USB_TOP_USBH2_DATA_4 */
-	[609] = IMX_PIN_REG(MX35_PAD_SD2_CMD, 0x6ac, 0x248, 5, 0x868, 2), /* MX35_PAD_SD2_CMD__GPIO2_0 */
-	[610] = IMX_PIN_REG(MX35_PAD_SD2_CMD, 0x6ac, 0x248, 6, 0x0, 0), /* MX35_PAD_SD2_CMD__SPDIF_SPDIF_OUT1 */
-	[611] = IMX_PIN_REG(MX35_PAD_SD2_CMD, 0x6ac, 0x248, 7, 0x928, 3), /* MX35_PAD_SD2_CMD__IPU_DISPB_D12_VSYNC */
-	[612] = IMX_PIN_REG(MX35_PAD_SD2_CLK, 0x6b0, 0x24c, 0, 0x0, 0), /* MX35_PAD_SD2_CLK__ESDHC2_CLK */
-	[613] = IMX_PIN_REG(MX35_PAD_SD2_CLK, 0x6b0, 0x24c, 1, 0x920, 2), /* MX35_PAD_SD2_CLK__I2C3_SDA */
-	[614] = IMX_PIN_REG(MX35_PAD_SD2_CLK, 0x6b0, 0x24c, 2, 0x808, 0), /* MX35_PAD_SD2_CLK__ESDHC1_DAT5 */
-	[615] = IMX_PIN_REG(MX35_PAD_SD2_CLK, 0x6b0, 0x24c, 3, 0x93c, 2), /* MX35_PAD_SD2_CLK__IPU_CSI_D_3 */
-	[616] = IMX_PIN_REG(MX35_PAD_SD2_CLK, 0x6b0, 0x24c, 4, 0x9e0, 0), /* MX35_PAD_SD2_CLK__USB_TOP_USBH2_DATA_5 */
-	[617] = IMX_PIN_REG(MX35_PAD_SD2_CLK, 0x6b0, 0x24c, 5, 0x894, 1), /* MX35_PAD_SD2_CLK__GPIO2_1 */
-	[618] = IMX_PIN_REG(MX35_PAD_SD2_CLK, 0x6b0, 0x24c, 6, 0x998, 2), /* MX35_PAD_SD2_CLK__SPDIF_SPDIF_IN1 */
-	[619] = IMX_PIN_REG(MX35_PAD_SD2_CLK, 0x6b0, 0x24c, 7, 0x0, 0), /* MX35_PAD_SD2_CLK__IPU_DISPB_CS2 */
-	[620] = IMX_PIN_REG(MX35_PAD_SD2_DATA0, 0x6b4, 0x250, 0, 0x0, 0), /* MX35_PAD_SD2_DATA0__ESDHC2_DAT0 */
-	[621] = IMX_PIN_REG(MX35_PAD_SD2_DATA0, 0x6b4, 0x250, 1, 0x9a0, 1), /* MX35_PAD_SD2_DATA0__UART3_RXD_MUX */
-	[622] = IMX_PIN_REG(MX35_PAD_SD2_DATA0, 0x6b4, 0x250, 2, 0x80c, 0), /* MX35_PAD_SD2_DATA0__ESDHC1_DAT6 */
-	[623] = IMX_PIN_REG(MX35_PAD_SD2_DATA0, 0x6b4, 0x250, 3, 0x940, 1), /* MX35_PAD_SD2_DATA0__IPU_CSI_D_4 */
-	[624] = IMX_PIN_REG(MX35_PAD_SD2_DATA0, 0x6b4, 0x250, 4, 0x9e4, 0), /* MX35_PAD_SD2_DATA0__USB_TOP_USBH2_DATA_6 */
-	[625] = IMX_PIN_REG(MX35_PAD_SD2_DATA0, 0x6b4, 0x250, 5, 0x8c0, 1), /* MX35_PAD_SD2_DATA0__GPIO2_2 */
-	[626] = IMX_PIN_REG(MX35_PAD_SD2_DATA0, 0x6b4, 0x250, 6, 0x994, 3), /* MX35_PAD_SD2_DATA0__SPDIF_SPDIF_EXTCLK */
-	[627] = IMX_PIN_REG(MX35_PAD_SD2_DATA1, 0x6b8, 0x254, 0, 0x0, 0), /* MX35_PAD_SD2_DATA1__ESDHC2_DAT1 */
-	[628] = IMX_PIN_REG(MX35_PAD_SD2_DATA1, 0x6b8, 0x254, 1, 0x0, 0), /* MX35_PAD_SD2_DATA1__UART3_TXD_MUX */
-	[629] = IMX_PIN_REG(MX35_PAD_SD2_DATA1, 0x6b8, 0x254, 2, 0x810, 0), /* MX35_PAD_SD2_DATA1__ESDHC1_DAT7 */
-	[630] = IMX_PIN_REG(MX35_PAD_SD2_DATA1, 0x6b8, 0x254, 3, 0x944, 1), /* MX35_PAD_SD2_DATA1__IPU_CSI_D_5 */
-	[631] = IMX_PIN_REG(MX35_PAD_SD2_DATA1, 0x6b8, 0x254, 4, 0x9cc, 0), /* MX35_PAD_SD2_DATA1__USB_TOP_USBH2_DATA_0 */
-	[632] = IMX_PIN_REG(MX35_PAD_SD2_DATA1, 0x6b8, 0x254, 5, 0x8cc, 1), /* MX35_PAD_SD2_DATA1__GPIO2_3 */
-	[633] = IMX_PIN_REG(MX35_PAD_SD2_DATA2, 0x6bc, 0x258, 0, 0x0, 0), /* MX35_PAD_SD2_DATA2__ESDHC2_DAT2 */
-	[634] = IMX_PIN_REG(MX35_PAD_SD2_DATA2, 0x6bc, 0x258, 1, 0x99c, 0), /* MX35_PAD_SD2_DATA2__UART3_RTS */
-	[635] = IMX_PIN_REG(MX35_PAD_SD2_DATA2, 0x6bc, 0x258, 2, 0x7c8, 1), /* MX35_PAD_SD2_DATA2__CAN1_RXCAN */
-	[636] = IMX_PIN_REG(MX35_PAD_SD2_DATA2, 0x6bc, 0x258, 3, 0x948, 1), /* MX35_PAD_SD2_DATA2__IPU_CSI_D_6 */
-	[637] = IMX_PIN_REG(MX35_PAD_SD2_DATA2, 0x6bc, 0x258, 4, 0x9d0, 0), /* MX35_PAD_SD2_DATA2__USB_TOP_USBH2_DATA_1 */
-	[638] = IMX_PIN_REG(MX35_PAD_SD2_DATA2, 0x6bc, 0x258, 5, 0x8d0, 1), /* MX35_PAD_SD2_DATA2__GPIO2_4 */
-	[639] = IMX_PIN_REG(MX35_PAD_SD2_DATA3, 0x6c0, 0x25c, 0, 0x0, 0), /* MX35_PAD_SD2_DATA3__ESDHC2_DAT3 */
-	[640] = IMX_PIN_REG(MX35_PAD_SD2_DATA3, 0x6c0, 0x25c, 1, 0x0, 0), /* MX35_PAD_SD2_DATA3__UART3_CTS */
-	[641] = IMX_PIN_REG(MX35_PAD_SD2_DATA3, 0x6c0, 0x25c, 2, 0x0, 0), /* MX35_PAD_SD2_DATA3__CAN1_TXCAN */
-	[642] = IMX_PIN_REG(MX35_PAD_SD2_DATA3, 0x6c0, 0x25c, 3, 0x94c, 1), /* MX35_PAD_SD2_DATA3__IPU_CSI_D_7 */
-	[643] = IMX_PIN_REG(MX35_PAD_SD2_DATA3, 0x6c0, 0x25c, 4, 0x9d4, 0), /* MX35_PAD_SD2_DATA3__USB_TOP_USBH2_DATA_2 */
-	[644] = IMX_PIN_REG(MX35_PAD_SD2_DATA3, 0x6c0, 0x25c, 5, 0x8d4, 1), /* MX35_PAD_SD2_DATA3__GPIO2_5 */
-	[645] = IMX_PIN_REG(MX35_PAD_ATA_CS0, 0x6c4, 0x260, 0, 0x0, 0), /* MX35_PAD_ATA_CS0__ATA_CS0 */
-	[646] = IMX_PIN_REG(MX35_PAD_ATA_CS0, 0x6c4, 0x260, 1, 0x7dc, 1), /* MX35_PAD_ATA_CS0__CSPI1_SS3 */
-	[647] = IMX_PIN_REG(MX35_PAD_ATA_CS0, 0x6c4, 0x260, 3, 0x0, 0), /* MX35_PAD_ATA_CS0__IPU_DISPB_CS1 */
-	[648] = IMX_PIN_REG(MX35_PAD_ATA_CS0, 0x6c4, 0x260, 5, 0x8d8, 1), /* MX35_PAD_ATA_CS0__GPIO2_6 */
-	[649] = IMX_PIN_REG(MX35_PAD_ATA_CS0, 0x6c4, 0x260, 6, 0x0, 0), /* MX35_PAD_ATA_CS0__IPU_DIAGB_0 */
-	[650] = IMX_PIN_REG(MX35_PAD_ATA_CS0, 0x6c4, 0x260, 7, 0x0, 0), /* MX35_PAD_ATA_CS0__ARM11P_TOP_MAX1_HMASTER_0 */
-	[651] = IMX_PIN_REG(MX35_PAD_ATA_CS1, 0x6c8, 0x264, 0, 0x0, 0), /* MX35_PAD_ATA_CS1__ATA_CS1 */
-	[652] = IMX_PIN_REG(MX35_PAD_ATA_CS1, 0x6c8, 0x264, 3, 0x0, 0), /* MX35_PAD_ATA_CS1__IPU_DISPB_CS2 */
-	[653] = IMX_PIN_REG(MX35_PAD_ATA_CS1, 0x6c8, 0x264, 4, 0x7f0, 1), /* MX35_PAD_ATA_CS1__CSPI2_SS0 */
-	[654] = IMX_PIN_REG(MX35_PAD_ATA_CS1, 0x6c8, 0x264, 5, 0x8dc, 1), /* MX35_PAD_ATA_CS1__GPIO2_7 */
-	[655] = IMX_PIN_REG(MX35_PAD_ATA_CS1, 0x6c8, 0x264, 6, 0x0, 0), /* MX35_PAD_ATA_CS1__IPU_DIAGB_1 */
-	[656] = IMX_PIN_REG(MX35_PAD_ATA_CS1, 0x6c8, 0x264, 7, 0x0, 0), /* MX35_PAD_ATA_CS1__ARM11P_TOP_MAX1_HMASTER_1 */
-	[657] = IMX_PIN_REG(MX35_PAD_ATA_DIOR, 0x6cc, 0x268, 0, 0x0, 0), /* MX35_PAD_ATA_DIOR__ATA_DIOR */
-	[658] = IMX_PIN_REG(MX35_PAD_ATA_DIOR, 0x6cc, 0x268, 1, 0x81c, 1), /* MX35_PAD_ATA_DIOR__ESDHC3_DAT0 */
-	[659] = IMX_PIN_REG(MX35_PAD_ATA_DIOR, 0x6cc, 0x268, 2, 0x9c4, 1), /* MX35_PAD_ATA_DIOR__USB_TOP_USBOTG_DIR */
-	[660] = IMX_PIN_REG(MX35_PAD_ATA_DIOR, 0x6cc, 0x268, 3, 0x0, 0), /* MX35_PAD_ATA_DIOR__IPU_DISPB_BE0 */
-	[661] = IMX_PIN_REG(MX35_PAD_ATA_DIOR, 0x6cc, 0x268, 4, 0x7f4, 1), /* MX35_PAD_ATA_DIOR__CSPI2_SS1 */
-	[662] = IMX_PIN_REG(MX35_PAD_ATA_DIOR, 0x6cc, 0x268, 5, 0x8e0, 1), /* MX35_PAD_ATA_DIOR__GPIO2_8 */
-	[663] = IMX_PIN_REG(MX35_PAD_ATA_DIOR, 0x6cc, 0x268, 6, 0x0, 0), /* MX35_PAD_ATA_DIOR__IPU_DIAGB_2 */
-	[664] = IMX_PIN_REG(MX35_PAD_ATA_DIOR, 0x6cc, 0x268, 7, 0x0, 0), /* MX35_PAD_ATA_DIOR__ARM11P_TOP_MAX1_HMASTER_2 */
-	[665] = IMX_PIN_REG(MX35_PAD_ATA_DIOW, 0x6d0, 0x26c, 0, 0x0, 0), /* MX35_PAD_ATA_DIOW__ATA_DIOW */
-	[666] = IMX_PIN_REG(MX35_PAD_ATA_DIOW, 0x6d0, 0x26c, 1, 0x820, 1), /* MX35_PAD_ATA_DIOW__ESDHC3_DAT1 */
-	[667] = IMX_PIN_REG(MX35_PAD_ATA_DIOW, 0x6d0, 0x26c, 2, 0x0, 0), /* MX35_PAD_ATA_DIOW__USB_TOP_USBOTG_STP */
-	[668] = IMX_PIN_REG(MX35_PAD_ATA_DIOW, 0x6d0, 0x26c, 3, 0x0, 0), /* MX35_PAD_ATA_DIOW__IPU_DISPB_BE1 */
-	[669] = IMX_PIN_REG(MX35_PAD_ATA_DIOW, 0x6d0, 0x26c, 4, 0x7ec, 2), /* MX35_PAD_ATA_DIOW__CSPI2_MOSI */
-	[670] = IMX_PIN_REG(MX35_PAD_ATA_DIOW, 0x6d0, 0x26c, 5, 0x8e4, 1), /* MX35_PAD_ATA_DIOW__GPIO2_9 */
-	[671] = IMX_PIN_REG(MX35_PAD_ATA_DIOW, 0x6d0, 0x26c, 6, 0x0, 0), /* MX35_PAD_ATA_DIOW__IPU_DIAGB_3 */
-	[672] = IMX_PIN_REG(MX35_PAD_ATA_DIOW, 0x6d0, 0x26c, 7, 0x0, 0), /* MX35_PAD_ATA_DIOW__ARM11P_TOP_MAX1_HMASTER_3 */
-	[673] = IMX_PIN_REG(MX35_PAD_ATA_DMACK, 0x6d4, 0x270, 0, 0x0, 0), /* MX35_PAD_ATA_DMACK__ATA_DMACK */
-	[674] = IMX_PIN_REG(MX35_PAD_ATA_DMACK, 0x6d4, 0x270, 1, 0x824, 1), /* MX35_PAD_ATA_DMACK__ESDHC3_DAT2 */
-	[675] = IMX_PIN_REG(MX35_PAD_ATA_DMACK, 0x6d4, 0x270, 2, 0x9c8, 1), /* MX35_PAD_ATA_DMACK__USB_TOP_USBOTG_NXT */
-	[676] = IMX_PIN_REG(MX35_PAD_ATA_DMACK, 0x6d4, 0x270, 4, 0x7e8, 2), /* MX35_PAD_ATA_DMACK__CSPI2_MISO */
-	[677] = IMX_PIN_REG(MX35_PAD_ATA_DMACK, 0x6d4, 0x270, 5, 0x86c, 1), /* MX35_PAD_ATA_DMACK__GPIO2_10 */
-	[678] = IMX_PIN_REG(MX35_PAD_ATA_DMACK, 0x6d4, 0x270, 6, 0x0, 0), /* MX35_PAD_ATA_DMACK__IPU_DIAGB_4 */
-	[679] = IMX_PIN_REG(MX35_PAD_ATA_DMACK, 0x6d4, 0x270, 7, 0x0, 0), /* MX35_PAD_ATA_DMACK__ARM11P_TOP_MAX0_HMASTER_0 */
-	[680] = IMX_PIN_REG(MX35_PAD_ATA_RESET_B, 0x6d8, 0x274, 0, 0x0, 0), /* MX35_PAD_ATA_RESET_B__ATA_RESET_B */
-	[681] = IMX_PIN_REG(MX35_PAD_ATA_RESET_B, 0x6d8, 0x274, 1, 0x828, 1), /* MX35_PAD_ATA_RESET_B__ESDHC3_DAT3 */
-	[682] = IMX_PIN_REG(MX35_PAD_ATA_RESET_B, 0x6d8, 0x274, 2, 0x9a4, 1), /* MX35_PAD_ATA_RESET_B__USB_TOP_USBOTG_DATA_0 */
-	[683] = IMX_PIN_REG(MX35_PAD_ATA_RESET_B, 0x6d8, 0x274, 3, 0x0, 0), /* MX35_PAD_ATA_RESET_B__IPU_DISPB_SD_D_O */
-	[684] = IMX_PIN_REG(MX35_PAD_ATA_RESET_B, 0x6d8, 0x274, 4, 0x7e4, 2), /* MX35_PAD_ATA_RESET_B__CSPI2_RDY */
-	[685] = IMX_PIN_REG(MX35_PAD_ATA_RESET_B, 0x6d8, 0x274, 5, 0x870, 1), /* MX35_PAD_ATA_RESET_B__GPIO2_11 */
-	[686] = IMX_PIN_REG(MX35_PAD_ATA_RESET_B, 0x6d8, 0x274, 6, 0x0, 0), /* MX35_PAD_ATA_RESET_B__IPU_DIAGB_5 */
-	[687] = IMX_PIN_REG(MX35_PAD_ATA_RESET_B, 0x6d8, 0x274, 7, 0x0, 0), /* MX35_PAD_ATA_RESET_B__ARM11P_TOP_MAX0_HMASTER_1 */
-	[688] = IMX_PIN_REG(MX35_PAD_ATA_IORDY, 0x6dc, 0x278, 0, 0x0, 0), /* MX35_PAD_ATA_IORDY__ATA_IORDY */
-	[689] = IMX_PIN_REG(MX35_PAD_ATA_IORDY, 0x6dc, 0x278, 1, 0x0, 0), /* MX35_PAD_ATA_IORDY__ESDHC3_DAT4 */
-	[690] = IMX_PIN_REG(MX35_PAD_ATA_IORDY, 0x6dc, 0x278, 2, 0x9a8, 1), /* MX35_PAD_ATA_IORDY__USB_TOP_USBOTG_DATA_1 */
-	[691] = IMX_PIN_REG(MX35_PAD_ATA_IORDY, 0x6dc, 0x278, 3, 0x92c, 3), /* MX35_PAD_ATA_IORDY__IPU_DISPB_SD_D_IO */
-	[692] = IMX_PIN_REG(MX35_PAD_ATA_IORDY, 0x6dc, 0x278, 4, 0x0, 0), /* MX35_PAD_ATA_IORDY__ESDHC2_DAT4 */
-	[693] = IMX_PIN_REG(MX35_PAD_ATA_IORDY, 0x6dc, 0x278, 5, 0x874, 1), /* MX35_PAD_ATA_IORDY__GPIO2_12 */
-	[694] = IMX_PIN_REG(MX35_PAD_ATA_IORDY, 0x6dc, 0x278, 6, 0x0, 0), /* MX35_PAD_ATA_IORDY__IPU_DIAGB_6 */
-	[695] = IMX_PIN_REG(MX35_PAD_ATA_IORDY, 0x6dc, 0x278, 7, 0x0, 0), /* MX35_PAD_ATA_IORDY__ARM11P_TOP_MAX0_HMASTER_2 */
-	[696] = IMX_PIN_REG(MX35_PAD_ATA_DATA0, 0x6e0, 0x27c, 0, 0x0, 0), /* MX35_PAD_ATA_DATA0__ATA_DATA_0 */
-	[697] = IMX_PIN_REG(MX35_PAD_ATA_DATA0, 0x6e0, 0x27c, 1, 0x0, 0), /* MX35_PAD_ATA_DATA0__ESDHC3_DAT5 */
-	[698] = IMX_PIN_REG(MX35_PAD_ATA_DATA0, 0x6e0, 0x27c, 2, 0x9ac, 1), /* MX35_PAD_ATA_DATA0__USB_TOP_USBOTG_DATA_2 */
-	[699] = IMX_PIN_REG(MX35_PAD_ATA_DATA0, 0x6e0, 0x27c, 3, 0x928, 4), /* MX35_PAD_ATA_DATA0__IPU_DISPB_D12_VSYNC */
-	[700] = IMX_PIN_REG(MX35_PAD_ATA_DATA0, 0x6e0, 0x27c, 4, 0x0, 0), /* MX35_PAD_ATA_DATA0__ESDHC2_DAT5 */
-	[701] = IMX_PIN_REG(MX35_PAD_ATA_DATA0, 0x6e0, 0x27c, 5, 0x878, 1), /* MX35_PAD_ATA_DATA0__GPIO2_13 */
-	[702] = IMX_PIN_REG(MX35_PAD_ATA_DATA0, 0x6e0, 0x27c, 6, 0x0, 0), /* MX35_PAD_ATA_DATA0__IPU_DIAGB_7 */
-	[703] = IMX_PIN_REG(MX35_PAD_ATA_DATA0, 0x6e0, 0x27c, 7, 0x0, 0), /* MX35_PAD_ATA_DATA0__ARM11P_TOP_MAX0_HMASTER_3 */
-	[704] = IMX_PIN_REG(MX35_PAD_ATA_DATA1, 0x6e4, 0x280, 0, 0x0, 0), /* MX35_PAD_ATA_DATA1__ATA_DATA_1 */
-	[705] = IMX_PIN_REG(MX35_PAD_ATA_DATA1, 0x6e4, 0x280, 1, 0x0, 0), /* MX35_PAD_ATA_DATA1__ESDHC3_DAT6 */
-	[706] = IMX_PIN_REG(MX35_PAD_ATA_DATA1, 0x6e4, 0x280, 2, 0x9b0, 1), /* MX35_PAD_ATA_DATA1__USB_TOP_USBOTG_DATA_3 */
-	[707] = IMX_PIN_REG(MX35_PAD_ATA_DATA1, 0x6e4, 0x280, 3, 0x0, 0), /* MX35_PAD_ATA_DATA1__IPU_DISPB_SD_CLK */
-	[708] = IMX_PIN_REG(MX35_PAD_ATA_DATA1, 0x6e4, 0x280, 4, 0x0, 0), /* MX35_PAD_ATA_DATA1__ESDHC2_DAT6 */
-	[709] = IMX_PIN_REG(MX35_PAD_ATA_DATA1, 0x6e4, 0x280, 5, 0x87c, 1), /* MX35_PAD_ATA_DATA1__GPIO2_14 */
-	[710] = IMX_PIN_REG(MX35_PAD_ATA_DATA1, 0x6e4, 0x280, 6, 0x0, 0), /* MX35_PAD_ATA_DATA1__IPU_DIAGB_8 */
-	[711] = IMX_PIN_REG(MX35_PAD_ATA_DATA1, 0x6e4, 0x280, 7, 0x0, 0), /* MX35_PAD_ATA_DATA1__ARM11P_TOP_TRACE_27 */
-	[712] = IMX_PIN_REG(MX35_PAD_ATA_DATA2, 0x6e8, 0x284, 0, 0x0, 0), /* MX35_PAD_ATA_DATA2__ATA_DATA_2 */
-	[713] = IMX_PIN_REG(MX35_PAD_ATA_DATA2, 0x6e8, 0x284, 1, 0x0, 0), /* MX35_PAD_ATA_DATA2__ESDHC3_DAT7 */
-	[714] = IMX_PIN_REG(MX35_PAD_ATA_DATA2, 0x6e8, 0x284, 2, 0x9b4, 1), /* MX35_PAD_ATA_DATA2__USB_TOP_USBOTG_DATA_4 */
-	[715] = IMX_PIN_REG(MX35_PAD_ATA_DATA2, 0x6e8, 0x284, 3, 0x0, 0), /* MX35_PAD_ATA_DATA2__IPU_DISPB_SER_RS */
-	[716] = IMX_PIN_REG(MX35_PAD_ATA_DATA2, 0x6e8, 0x284, 4, 0x0, 0), /* MX35_PAD_ATA_DATA2__ESDHC2_DAT7 */
-	[717] = IMX_PIN_REG(MX35_PAD_ATA_DATA2, 0x6e8, 0x284, 5, 0x880, 1), /* MX35_PAD_ATA_DATA2__GPIO2_15 */
-	[718] = IMX_PIN_REG(MX35_PAD_ATA_DATA2, 0x6e8, 0x284, 6, 0x0, 0), /* MX35_PAD_ATA_DATA2__IPU_DIAGB_9 */
-	[719] = IMX_PIN_REG(MX35_PAD_ATA_DATA2, 0x6e8, 0x284, 7, 0x0, 0), /* MX35_PAD_ATA_DATA2__ARM11P_TOP_TRACE_28 */
-	[720] = IMX_PIN_REG(MX35_PAD_ATA_DATA3, 0x6ec, 0x288, 0, 0x0, 0), /* MX35_PAD_ATA_DATA3__ATA_DATA_3 */
-	[721] = IMX_PIN_REG(MX35_PAD_ATA_DATA3, 0x6ec, 0x288, 1, 0x814, 1), /* MX35_PAD_ATA_DATA3__ESDHC3_CLK */
-	[722] = IMX_PIN_REG(MX35_PAD_ATA_DATA3, 0x6ec, 0x288, 2, 0x9b8, 1), /* MX35_PAD_ATA_DATA3__USB_TOP_USBOTG_DATA_5 */
-	[723] = IMX_PIN_REG(MX35_PAD_ATA_DATA3, 0x6ec, 0x288, 4, 0x7e0, 2), /* MX35_PAD_ATA_DATA3__CSPI2_SCLK */
-	[724] = IMX_PIN_REG(MX35_PAD_ATA_DATA3, 0x6ec, 0x288, 5, 0x884, 1), /* MX35_PAD_ATA_DATA3__GPIO2_16 */
-	[725] = IMX_PIN_REG(MX35_PAD_ATA_DATA3, 0x6ec, 0x288, 6, 0x0, 0), /* MX35_PAD_ATA_DATA3__IPU_DIAGB_10 */
-	[726] = IMX_PIN_REG(MX35_PAD_ATA_DATA3, 0x6ec, 0x288, 7, 0x0, 0), /* MX35_PAD_ATA_DATA3__ARM11P_TOP_TRACE_29 */
-	[727] = IMX_PIN_REG(MX35_PAD_ATA_DATA4, 0x6f0, 0x28c, 0, 0x0, 0), /* MX35_PAD_ATA_DATA4__ATA_DATA_4 */
-	[728] = IMX_PIN_REG(MX35_PAD_ATA_DATA4, 0x6f0, 0x28c, 1, 0x818, 1), /* MX35_PAD_ATA_DATA4__ESDHC3_CMD */
-	[729] = IMX_PIN_REG(MX35_PAD_ATA_DATA4, 0x6f0, 0x28c, 2, 0x9bc, 1), /* MX35_PAD_ATA_DATA4__USB_TOP_USBOTG_DATA_6 */
-	[730] = IMX_PIN_REG(MX35_PAD_ATA_DATA4, 0x6f0, 0x28c, 5, 0x888, 1), /* MX35_PAD_ATA_DATA4__GPIO2_17 */
-	[731] = IMX_PIN_REG(MX35_PAD_ATA_DATA4, 0x6f0, 0x28c, 6, 0x0, 0), /* MX35_PAD_ATA_DATA4__IPU_DIAGB_11 */
-	[732] = IMX_PIN_REG(MX35_PAD_ATA_DATA4, 0x6f0, 0x28c, 7, 0x0, 0), /* MX35_PAD_ATA_DATA4__ARM11P_TOP_TRACE_30 */
-	[733] = IMX_PIN_REG(MX35_PAD_ATA_DATA5, 0x6f4, 0x290, 0, 0x0, 0), /* MX35_PAD_ATA_DATA5__ATA_DATA_5 */
-	[734] = IMX_PIN_REG(MX35_PAD_ATA_DATA5, 0x6f4, 0x290, 2, 0x9c0, 1), /* MX35_PAD_ATA_DATA5__USB_TOP_USBOTG_DATA_7 */
-	[735] = IMX_PIN_REG(MX35_PAD_ATA_DATA5, 0x6f4, 0x290, 5, 0x88c, 1), /* MX35_PAD_ATA_DATA5__GPIO2_18 */
-	[736] = IMX_PIN_REG(MX35_PAD_ATA_DATA5, 0x6f4, 0x290, 6, 0x0, 0), /* MX35_PAD_ATA_DATA5__IPU_DIAGB_12 */
-	[737] = IMX_PIN_REG(MX35_PAD_ATA_DATA5, 0x6f4, 0x290, 7, 0x0, 0), /* MX35_PAD_ATA_DATA5__ARM11P_TOP_TRACE_31 */
-	[738] = IMX_PIN_REG(MX35_PAD_ATA_DATA6, 0x6f8, 0x294, 0, 0x0, 0), /* MX35_PAD_ATA_DATA6__ATA_DATA_6 */
-	[739] = IMX_PIN_REG(MX35_PAD_ATA_DATA6, 0x6f8, 0x294, 1, 0x0, 0), /* MX35_PAD_ATA_DATA6__CAN1_TXCAN */
-	[740] = IMX_PIN_REG(MX35_PAD_ATA_DATA6, 0x6f8, 0x294, 2, 0x0, 0), /* MX35_PAD_ATA_DATA6__UART1_DTR */
-	[741] = IMX_PIN_REG(MX35_PAD_ATA_DATA6, 0x6f8, 0x294, 3, 0x7b4, 0), /* MX35_PAD_ATA_DATA6__AUDMUX_AUD6_TXD */
-	[742] = IMX_PIN_REG(MX35_PAD_ATA_DATA6, 0x6f8, 0x294, 5, 0x890, 1), /* MX35_PAD_ATA_DATA6__GPIO2_19 */
-	[743] = IMX_PIN_REG(MX35_PAD_ATA_DATA6, 0x6f8, 0x294, 6, 0x0, 0), /* MX35_PAD_ATA_DATA6__IPU_DIAGB_13 */
-	[744] = IMX_PIN_REG(MX35_PAD_ATA_DATA7, 0x6fc, 0x298, 0, 0x0, 0), /* MX35_PAD_ATA_DATA7__ATA_DATA_7 */
-	[745] = IMX_PIN_REG(MX35_PAD_ATA_DATA7, 0x6fc, 0x298, 1, 0x7c8, 2), /* MX35_PAD_ATA_DATA7__CAN1_RXCAN */
-	[746] = IMX_PIN_REG(MX35_PAD_ATA_DATA7, 0x6fc, 0x298, 2, 0x0, 0), /* MX35_PAD_ATA_DATA7__UART1_DSR */
-	[747] = IMX_PIN_REG(MX35_PAD_ATA_DATA7, 0x6fc, 0x298, 3, 0x7b0, 0), /* MX35_PAD_ATA_DATA7__AUDMUX_AUD6_RXD */
-	[748] = IMX_PIN_REG(MX35_PAD_ATA_DATA7, 0x6fc, 0x298, 5, 0x898, 1), /* MX35_PAD_ATA_DATA7__GPIO2_20 */
-	[749] = IMX_PIN_REG(MX35_PAD_ATA_DATA7, 0x6fc, 0x298, 6, 0x0, 0), /* MX35_PAD_ATA_DATA7__IPU_DIAGB_14 */
-	[750] = IMX_PIN_REG(MX35_PAD_ATA_DATA8, 0x700, 0x29c, 0, 0x0, 0), /* MX35_PAD_ATA_DATA8__ATA_DATA_8 */
-	[751] = IMX_PIN_REG(MX35_PAD_ATA_DATA8, 0x700, 0x29c, 1, 0x99c, 1), /* MX35_PAD_ATA_DATA8__UART3_RTS */
-	[752] = IMX_PIN_REG(MX35_PAD_ATA_DATA8, 0x700, 0x29c, 2, 0x0, 0), /* MX35_PAD_ATA_DATA8__UART1_RI */
-	[753] = IMX_PIN_REG(MX35_PAD_ATA_DATA8, 0x700, 0x29c, 3, 0x7c0, 0), /* MX35_PAD_ATA_DATA8__AUDMUX_AUD6_TXC */
-	[754] = IMX_PIN_REG(MX35_PAD_ATA_DATA8, 0x700, 0x29c, 5, 0x89c, 1), /* MX35_PAD_ATA_DATA8__GPIO2_21 */
-	[755] = IMX_PIN_REG(MX35_PAD_ATA_DATA8, 0x700, 0x29c, 6, 0x0, 0), /* MX35_PAD_ATA_DATA8__IPU_DIAGB_15 */
-	[756] = IMX_PIN_REG(MX35_PAD_ATA_DATA9, 0x704, 0x2a0, 0, 0x0, 0), /* MX35_PAD_ATA_DATA9__ATA_DATA_9 */
-	[757] = IMX_PIN_REG(MX35_PAD_ATA_DATA9, 0x704, 0x2a0, 1, 0x0, 0), /* MX35_PAD_ATA_DATA9__UART3_CTS */
-	[758] = IMX_PIN_REG(MX35_PAD_ATA_DATA9, 0x704, 0x2a0, 2, 0x0, 0), /* MX35_PAD_ATA_DATA9__UART1_DCD */
-	[759] = IMX_PIN_REG(MX35_PAD_ATA_DATA9, 0x704, 0x2a0, 3, 0x7c4, 0), /* MX35_PAD_ATA_DATA9__AUDMUX_AUD6_TXFS */
-	[760] = IMX_PIN_REG(MX35_PAD_ATA_DATA9, 0x704, 0x2a0, 5, 0x8a0, 1), /* MX35_PAD_ATA_DATA9__GPIO2_22 */
-	[761] = IMX_PIN_REG(MX35_PAD_ATA_DATA9, 0x704, 0x2a0, 6, 0x0, 0), /* MX35_PAD_ATA_DATA9__IPU_DIAGB_16 */
-	[762] = IMX_PIN_REG(MX35_PAD_ATA_DATA10, 0x708, 0x2a4, 0, 0x0, 0), /* MX35_PAD_ATA_DATA10__ATA_DATA_10 */
-	[763] = IMX_PIN_REG(MX35_PAD_ATA_DATA10, 0x708, 0x2a4, 1, 0x9a0, 2), /* MX35_PAD_ATA_DATA10__UART3_RXD_MUX */
-	[764] = IMX_PIN_REG(MX35_PAD_ATA_DATA10, 0x708, 0x2a4, 3, 0x7b8, 0), /* MX35_PAD_ATA_DATA10__AUDMUX_AUD6_RXC */
-	[765] = IMX_PIN_REG(MX35_PAD_ATA_DATA10, 0x708, 0x2a4, 5, 0x8a4, 1), /* MX35_PAD_ATA_DATA10__GPIO2_23 */
-	[766] = IMX_PIN_REG(MX35_PAD_ATA_DATA10, 0x708, 0x2a4, 6, 0x0, 0), /* MX35_PAD_ATA_DATA10__IPU_DIAGB_17 */
-	[767] = IMX_PIN_REG(MX35_PAD_ATA_DATA11, 0x70c, 0x2a8, 0, 0x0, 0), /* MX35_PAD_ATA_DATA11__ATA_DATA_11 */
-	[768] = IMX_PIN_REG(MX35_PAD_ATA_DATA11, 0x70c, 0x2a8, 1, 0x0, 0), /* MX35_PAD_ATA_DATA11__UART3_TXD_MUX */
-	[769] = IMX_PIN_REG(MX35_PAD_ATA_DATA11, 0x70c, 0x2a8, 3, 0x7bc, 0), /* MX35_PAD_ATA_DATA11__AUDMUX_AUD6_RXFS */
-	[770] = IMX_PIN_REG(MX35_PAD_ATA_DATA11, 0x70c, 0x2a8, 5, 0x8a8, 1), /* MX35_PAD_ATA_DATA11__GPIO2_24 */
-	[771] = IMX_PIN_REG(MX35_PAD_ATA_DATA11, 0x70c, 0x2a8, 6, 0x0, 0), /* MX35_PAD_ATA_DATA11__IPU_DIAGB_18 */
-	[772] = IMX_PIN_REG(MX35_PAD_ATA_DATA12, 0x710, 0x2ac, 0, 0x0, 0), /* MX35_PAD_ATA_DATA12__ATA_DATA_12 */
-	[773] = IMX_PIN_REG(MX35_PAD_ATA_DATA12, 0x710, 0x2ac, 1, 0x91c, 3), /* MX35_PAD_ATA_DATA12__I2C3_SCL */
-	[774] = IMX_PIN_REG(MX35_PAD_ATA_DATA12, 0x710, 0x2ac, 5, 0x8ac, 1), /* MX35_PAD_ATA_DATA12__GPIO2_25 */
-	[775] = IMX_PIN_REG(MX35_PAD_ATA_DATA12, 0x710, 0x2ac, 6, 0x0, 0), /* MX35_PAD_ATA_DATA12__IPU_DIAGB_19 */
-	[776] = IMX_PIN_REG(MX35_PAD_ATA_DATA13, 0x714, 0x2b0, 0, 0x0, 0), /* MX35_PAD_ATA_DATA13__ATA_DATA_13 */
-	[777] = IMX_PIN_REG(MX35_PAD_ATA_DATA13, 0x714, 0x2b0, 1, 0x920, 3), /* MX35_PAD_ATA_DATA13__I2C3_SDA */
-	[778] = IMX_PIN_REG(MX35_PAD_ATA_DATA13, 0x714, 0x2b0, 5, 0x8b0, 1), /* MX35_PAD_ATA_DATA13__GPIO2_26 */
-	[779] = IMX_PIN_REG(MX35_PAD_ATA_DATA13, 0x714, 0x2b0, 6, 0x0, 0), /* MX35_PAD_ATA_DATA13__IPU_DIAGB_20 */
-	[780] = IMX_PIN_REG(MX35_PAD_ATA_DATA14, 0x718, 0x2b4, 0, 0x0, 0), /* MX35_PAD_ATA_DATA14__ATA_DATA_14 */
-	[781] = IMX_PIN_REG(MX35_PAD_ATA_DATA14, 0x718, 0x2b4, 1, 0x930, 2), /* MX35_PAD_ATA_DATA14__IPU_CSI_D_0 */
-	[782] = IMX_PIN_REG(MX35_PAD_ATA_DATA14, 0x718, 0x2b4, 3, 0x970, 2), /* MX35_PAD_ATA_DATA14__KPP_ROW_0 */
-	[783] = IMX_PIN_REG(MX35_PAD_ATA_DATA14, 0x718, 0x2b4, 5, 0x8b4, 1), /* MX35_PAD_ATA_DATA14__GPIO2_27 */
-	[784] = IMX_PIN_REG(MX35_PAD_ATA_DATA14, 0x718, 0x2b4, 6, 0x0, 0), /* MX35_PAD_ATA_DATA14__IPU_DIAGB_21 */
-	[785] = IMX_PIN_REG(MX35_PAD_ATA_DATA15, 0x71c, 0x2b8, 0, 0x0, 0), /* MX35_PAD_ATA_DATA15__ATA_DATA_15 */
-	[786] = IMX_PIN_REG(MX35_PAD_ATA_DATA15, 0x71c, 0x2b8, 1, 0x934, 2), /* MX35_PAD_ATA_DATA15__IPU_CSI_D_1 */
-	[787] = IMX_PIN_REG(MX35_PAD_ATA_DATA15, 0x71c, 0x2b8, 3, 0x974, 2), /* MX35_PAD_ATA_DATA15__KPP_ROW_1 */
-	[788] = IMX_PIN_REG(MX35_PAD_ATA_DATA15, 0x71c, 0x2b8, 5, 0x8b8, 1), /* MX35_PAD_ATA_DATA15__GPIO2_28 */
-	[789] = IMX_PIN_REG(MX35_PAD_ATA_DATA15, 0x71c, 0x2b8, 6, 0x0, 0), /* MX35_PAD_ATA_DATA15__IPU_DIAGB_22 */
-	[790] = IMX_PIN_REG(MX35_PAD_ATA_INTRQ, 0x720, 0x2bc, 0, 0x0, 0), /* MX35_PAD_ATA_INTRQ__ATA_INTRQ */
-	[791] = IMX_PIN_REG(MX35_PAD_ATA_INTRQ, 0x720, 0x2bc, 1, 0x938, 3), /* MX35_PAD_ATA_INTRQ__IPU_CSI_D_2 */
-	[792] = IMX_PIN_REG(MX35_PAD_ATA_INTRQ, 0x720, 0x2bc, 3, 0x978, 2), /* MX35_PAD_ATA_INTRQ__KPP_ROW_2 */
-	[793] = IMX_PIN_REG(MX35_PAD_ATA_INTRQ, 0x720, 0x2bc, 5, 0x8bc, 1), /* MX35_PAD_ATA_INTRQ__GPIO2_29 */
-	[794] = IMX_PIN_REG(MX35_PAD_ATA_INTRQ, 0x720, 0x2bc, 6, 0x0, 0), /* MX35_PAD_ATA_INTRQ__IPU_DIAGB_23 */
-	[795] = IMX_PIN_REG(MX35_PAD_ATA_BUFF_EN, 0x724, 0x2c0, 0, 0x0, 0), /* MX35_PAD_ATA_BUFF_EN__ATA_BUFFER_EN */
-	[796] = IMX_PIN_REG(MX35_PAD_ATA_BUFF_EN, 0x724, 0x2c0, 1, 0x93c, 3), /* MX35_PAD_ATA_BUFF_EN__IPU_CSI_D_3 */
-	[797] = IMX_PIN_REG(MX35_PAD_ATA_BUFF_EN, 0x724, 0x2c0, 3, 0x97c, 2), /* MX35_PAD_ATA_BUFF_EN__KPP_ROW_3 */
-	[798] = IMX_PIN_REG(MX35_PAD_ATA_BUFF_EN, 0x724, 0x2c0, 5, 0x8c4, 1), /* MX35_PAD_ATA_BUFF_EN__GPIO2_30 */
-	[799] = IMX_PIN_REG(MX35_PAD_ATA_BUFF_EN, 0x724, 0x2c0, 6, 0x0, 0), /* MX35_PAD_ATA_BUFF_EN__IPU_DIAGB_24 */
-	[800] = IMX_PIN_REG(MX35_PAD_ATA_DMARQ, 0x728, 0x2c4, 0, 0x0, 0), /* MX35_PAD_ATA_DMARQ__ATA_DMARQ */
-	[801] = IMX_PIN_REG(MX35_PAD_ATA_DMARQ, 0x728, 0x2c4, 1, 0x940, 2), /* MX35_PAD_ATA_DMARQ__IPU_CSI_D_4 */
-	[802] = IMX_PIN_REG(MX35_PAD_ATA_DMARQ, 0x728, 0x2c4, 3, 0x950, 2), /* MX35_PAD_ATA_DMARQ__KPP_COL_0 */
-	[803] = IMX_PIN_REG(MX35_PAD_ATA_DMARQ, 0x728, 0x2c4, 5, 0x8c8, 1), /* MX35_PAD_ATA_DMARQ__GPIO2_31 */
-	[804] = IMX_PIN_REG(MX35_PAD_ATA_DMARQ, 0x728, 0x2c4, 6, 0x0, 0), /* MX35_PAD_ATA_DMARQ__IPU_DIAGB_25 */
-	[805] = IMX_PIN_REG(MX35_PAD_ATA_DMARQ, 0x728, 0x2c4, 7, 0x0, 0), /* MX35_PAD_ATA_DMARQ__ECT_CTI_TRIG_IN1_4 */
-	[806] = IMX_PIN_REG(MX35_PAD_ATA_DA0, 0x72c, 0x2c8, 0, 0x0, 0), /* MX35_PAD_ATA_DA0__ATA_DA_0 */
-	[807] = IMX_PIN_REG(MX35_PAD_ATA_DA0, 0x72c, 0x2c8, 1, 0x944, 2), /* MX35_PAD_ATA_DA0__IPU_CSI_D_5 */
-	[808] = IMX_PIN_REG(MX35_PAD_ATA_DA0, 0x72c, 0x2c8, 3, 0x954, 2), /* MX35_PAD_ATA_DA0__KPP_COL_1 */
-	[809] = IMX_PIN_REG(MX35_PAD_ATA_DA0, 0x72c, 0x2c8, 5, 0x8e8, 1), /* MX35_PAD_ATA_DA0__GPIO3_0 */
-	[810] = IMX_PIN_REG(MX35_PAD_ATA_DA0, 0x72c, 0x2c8, 6, 0x0, 0), /* MX35_PAD_ATA_DA0__IPU_DIAGB_26 */
-	[811] = IMX_PIN_REG(MX35_PAD_ATA_DA0, 0x72c, 0x2c8, 7, 0x0, 0), /* MX35_PAD_ATA_DA0__ECT_CTI_TRIG_IN1_5 */
-	[812] = IMX_PIN_REG(MX35_PAD_ATA_DA1, 0x730, 0x2cc, 0, 0x0, 0), /* MX35_PAD_ATA_DA1__ATA_DA_1 */
-	[813] = IMX_PIN_REG(MX35_PAD_ATA_DA1, 0x730, 0x2cc, 1, 0x948, 2), /* MX35_PAD_ATA_DA1__IPU_CSI_D_6 */
-	[814] = IMX_PIN_REG(MX35_PAD_ATA_DA1, 0x730, 0x2cc, 3, 0x958, 2), /* MX35_PAD_ATA_DA1__KPP_COL_2 */
-	[815] = IMX_PIN_REG(MX35_PAD_ATA_DA1, 0x730, 0x2cc, 5, 0x0, 0), /* MX35_PAD_ATA_DA1__GPIO3_1 */
-	[816] = IMX_PIN_REG(MX35_PAD_ATA_DA1, 0x730, 0x2cc, 6, 0x0, 0), /* MX35_PAD_ATA_DA1__IPU_DIAGB_27 */
-	[817] = IMX_PIN_REG(MX35_PAD_ATA_DA1, 0x730, 0x2cc, 7, 0x0, 0), /* MX35_PAD_ATA_DA1__ECT_CTI_TRIG_IN1_6 */
-	[818] = IMX_PIN_REG(MX35_PAD_ATA_DA2, 0x734, 0x2d0, 0, 0x0, 0), /* MX35_PAD_ATA_DA2__ATA_DA_2 */
-	[819] = IMX_PIN_REG(MX35_PAD_ATA_DA2, 0x734, 0x2d0, 1, 0x94c, 2), /* MX35_PAD_ATA_DA2__IPU_CSI_D_7 */
-	[820] = IMX_PIN_REG(MX35_PAD_ATA_DA2, 0x734, 0x2d0, 3, 0x95c, 2), /* MX35_PAD_ATA_DA2__KPP_COL_3 */
-	[821] = IMX_PIN_REG(MX35_PAD_ATA_DA2, 0x734, 0x2d0, 5, 0x0, 0), /* MX35_PAD_ATA_DA2__GPIO3_2 */
-	[822] = IMX_PIN_REG(MX35_PAD_ATA_DA2, 0x734, 0x2d0, 6, 0x0, 0), /* MX35_PAD_ATA_DA2__IPU_DIAGB_28 */
-	[823] = IMX_PIN_REG(MX35_PAD_ATA_DA2, 0x734, 0x2d0, 7, 0x0, 0), /* MX35_PAD_ATA_DA2__ECT_CTI_TRIG_IN1_7 */
-	[824] = IMX_PIN_REG(MX35_PAD_MLB_CLK, 0x738, 0x2d4, 0, 0x0, 0), /* MX35_PAD_MLB_CLK__MLB_MLBCLK */
-	[825] = IMX_PIN_REG(MX35_PAD_MLB_CLK, 0x738, 0x2d4, 5, 0x0, 0), /* MX35_PAD_MLB_CLK__GPIO3_3 */
-	[826] = IMX_PIN_REG(MX35_PAD_MLB_DAT, 0x73c, 0x2d8, 0, 0x0, 0), /* MX35_PAD_MLB_DAT__MLB_MLBDAT */
-	[827] = IMX_PIN_REG(MX35_PAD_MLB_DAT, 0x73c, 0x2d8, 5, 0x904, 1), /* MX35_PAD_MLB_DAT__GPIO3_4 */
-	[828] = IMX_PIN_REG(MX35_PAD_MLB_SIG, 0x740, 0x2dc, 0, 0x0, 0), /* MX35_PAD_MLB_SIG__MLB_MLBSIG */
-	[829] = IMX_PIN_REG(MX35_PAD_MLB_SIG, 0x740, 0x2dc, 5, 0x908, 1), /* MX35_PAD_MLB_SIG__GPIO3_5 */
-	[830] = IMX_PIN_REG(MX35_PAD_FEC_TX_CLK, 0x744, 0x2e0, 0, 0x0, 0), /* MX35_PAD_FEC_TX_CLK__FEC_TX_CLK */
-	[831] = IMX_PIN_REG(MX35_PAD_FEC_TX_CLK, 0x744, 0x2e0, 1, 0x804, 1), /* MX35_PAD_FEC_TX_CLK__ESDHC1_DAT4 */
-	[832] = IMX_PIN_REG(MX35_PAD_FEC_TX_CLK, 0x744, 0x2e0, 2, 0x9a0, 3), /* MX35_PAD_FEC_TX_CLK__UART3_RXD_MUX */
-	[833] = IMX_PIN_REG(MX35_PAD_FEC_TX_CLK, 0x744, 0x2e0, 3, 0x9ec, 1), /* MX35_PAD_FEC_TX_CLK__USB_TOP_USBH2_DIR */
-	[834] = IMX_PIN_REG(MX35_PAD_FEC_TX_CLK, 0x744, 0x2e0, 4, 0x7ec, 3), /* MX35_PAD_FEC_TX_CLK__CSPI2_MOSI */
-	[835] = IMX_PIN_REG(MX35_PAD_FEC_TX_CLK, 0x744, 0x2e0, 5, 0x90c, 1), /* MX35_PAD_FEC_TX_CLK__GPIO3_6 */
-	[836] = IMX_PIN_REG(MX35_PAD_FEC_TX_CLK, 0x744, 0x2e0, 6, 0x928, 5), /* MX35_PAD_FEC_TX_CLK__IPU_DISPB_D12_VSYNC */
-	[837] = IMX_PIN_REG(MX35_PAD_FEC_TX_CLK, 0x744, 0x2e0, 7, 0x0, 0), /* MX35_PAD_FEC_TX_CLK__ARM11P_TOP_EVNTBUS_0 */
-	[838] = IMX_PIN_REG(MX35_PAD_FEC_RX_CLK, 0x748, 0x2e4, 0, 0x0, 0), /* MX35_PAD_FEC_RX_CLK__FEC_RX_CLK */
-	[839] = IMX_PIN_REG(MX35_PAD_FEC_RX_CLK, 0x748, 0x2e4, 1, 0x808, 1), /* MX35_PAD_FEC_RX_CLK__ESDHC1_DAT5 */
-	[840] = IMX_PIN_REG(MX35_PAD_FEC_RX_CLK, 0x748, 0x2e4, 2, 0x0, 0), /* MX35_PAD_FEC_RX_CLK__UART3_TXD_MUX */
-	[841] = IMX_PIN_REG(MX35_PAD_FEC_RX_CLK, 0x748, 0x2e4, 3, 0x0, 0), /* MX35_PAD_FEC_RX_CLK__USB_TOP_USBH2_STP */
-	[842] = IMX_PIN_REG(MX35_PAD_FEC_RX_CLK, 0x748, 0x2e4, 4, 0x7e8, 3), /* MX35_PAD_FEC_RX_CLK__CSPI2_MISO */
-	[843] = IMX_PIN_REG(MX35_PAD_FEC_RX_CLK, 0x748, 0x2e4, 5, 0x910, 1), /* MX35_PAD_FEC_RX_CLK__GPIO3_7 */
-	[844] = IMX_PIN_REG(MX35_PAD_FEC_RX_CLK, 0x748, 0x2e4, 6, 0x92c, 4), /* MX35_PAD_FEC_RX_CLK__IPU_DISPB_SD_D_I */
-	[845] = IMX_PIN_REG(MX35_PAD_FEC_RX_CLK, 0x748, 0x2e4, 7, 0x0, 0), /* MX35_PAD_FEC_RX_CLK__ARM11P_TOP_EVNTBUS_1 */
-	[846] = IMX_PIN_REG(MX35_PAD_FEC_RX_DV, 0x74c, 0x2e8, 0, 0x0, 0), /* MX35_PAD_FEC_RX_DV__FEC_RX_DV */
-	[847] = IMX_PIN_REG(MX35_PAD_FEC_RX_DV, 0x74c, 0x2e8, 1, 0x80c, 1), /* MX35_PAD_FEC_RX_DV__ESDHC1_DAT6 */
-	[848] = IMX_PIN_REG(MX35_PAD_FEC_RX_DV, 0x74c, 0x2e8, 2, 0x99c, 2), /* MX35_PAD_FEC_RX_DV__UART3_RTS */
-	[849] = IMX_PIN_REG(MX35_PAD_FEC_RX_DV, 0x74c, 0x2e8, 3, 0x9f0, 1), /* MX35_PAD_FEC_RX_DV__USB_TOP_USBH2_NXT */
-	[850] = IMX_PIN_REG(MX35_PAD_FEC_RX_DV, 0x74c, 0x2e8, 4, 0x7e0, 3), /* MX35_PAD_FEC_RX_DV__CSPI2_SCLK */
-	[851] = IMX_PIN_REG(MX35_PAD_FEC_RX_DV, 0x74c, 0x2e8, 5, 0x914, 1), /* MX35_PAD_FEC_RX_DV__GPIO3_8 */
-	[852] = IMX_PIN_REG(MX35_PAD_FEC_RX_DV, 0x74c, 0x2e8, 6, 0x0, 0), /* MX35_PAD_FEC_RX_DV__IPU_DISPB_SD_CLK */
-	[853] = IMX_PIN_REG(MX35_PAD_FEC_RX_DV, 0x74c, 0x2e8, 7, 0x0, 0), /* MX35_PAD_FEC_RX_DV__ARM11P_TOP_EVNTBUS_2 */
-	[854] = IMX_PIN_REG(MX35_PAD_FEC_COL, 0x750, 0x2ec, 0, 0x0, 0), /* MX35_PAD_FEC_COL__FEC_COL */
-	[855] = IMX_PIN_REG(MX35_PAD_FEC_COL, 0x750, 0x2ec, 1, 0x810, 1), /* MX35_PAD_FEC_COL__ESDHC1_DAT7 */
-	[856] = IMX_PIN_REG(MX35_PAD_FEC_COL, 0x750, 0x2ec, 2, 0x0, 0), /* MX35_PAD_FEC_COL__UART3_CTS */
-	[857] = IMX_PIN_REG(MX35_PAD_FEC_COL, 0x750, 0x2ec, 3, 0x9cc, 1), /* MX35_PAD_FEC_COL__USB_TOP_USBH2_DATA_0 */
-	[858] = IMX_PIN_REG(MX35_PAD_FEC_COL, 0x750, 0x2ec, 4, 0x7e4, 3), /* MX35_PAD_FEC_COL__CSPI2_RDY */
-	[859] = IMX_PIN_REG(MX35_PAD_FEC_COL, 0x750, 0x2ec, 5, 0x918, 1), /* MX35_PAD_FEC_COL__GPIO3_9 */
-	[860] = IMX_PIN_REG(MX35_PAD_FEC_COL, 0x750, 0x2ec, 6, 0x0, 0), /* MX35_PAD_FEC_COL__IPU_DISPB_SER_RS */
-	[861] = IMX_PIN_REG(MX35_PAD_FEC_COL, 0x750, 0x2ec, 7, 0x0, 0), /* MX35_PAD_FEC_COL__ARM11P_TOP_EVNTBUS_3 */
-	[862] = IMX_PIN_REG(MX35_PAD_FEC_RDATA0, 0x754, 0x2f0, 0, 0x0, 0), /* MX35_PAD_FEC_RDATA0__FEC_RDATA_0 */
-	[863] = IMX_PIN_REG(MX35_PAD_FEC_RDATA0, 0x754, 0x2f0, 1, 0x0, 0), /* MX35_PAD_FEC_RDATA0__PWM_PWMO */
-	[864] = IMX_PIN_REG(MX35_PAD_FEC_RDATA0, 0x754, 0x2f0, 2, 0x0, 0), /* MX35_PAD_FEC_RDATA0__UART3_DTR */
-	[865] = IMX_PIN_REG(MX35_PAD_FEC_RDATA0, 0x754, 0x2f0, 3, 0x9d0, 1), /* MX35_PAD_FEC_RDATA0__USB_TOP_USBH2_DATA_1 */
-	[866] = IMX_PIN_REG(MX35_PAD_FEC_RDATA0, 0x754, 0x2f0, 4, 0x7f0, 2), /* MX35_PAD_FEC_RDATA0__CSPI2_SS0 */
-	[867] = IMX_PIN_REG(MX35_PAD_FEC_RDATA0, 0x754, 0x2f0, 5, 0x8ec, 1), /* MX35_PAD_FEC_RDATA0__GPIO3_10 */
-	[868] = IMX_PIN_REG(MX35_PAD_FEC_RDATA0, 0x754, 0x2f0, 6, 0x0, 0), /* MX35_PAD_FEC_RDATA0__IPU_DISPB_CS1 */
-	[869] = IMX_PIN_REG(MX35_PAD_FEC_RDATA0, 0x754, 0x2f0, 7, 0x0, 0), /* MX35_PAD_FEC_RDATA0__ARM11P_TOP_EVNTBUS_4 */
-	[870] = IMX_PIN_REG(MX35_PAD_FEC_TDATA0, 0x758, 0x2f4, 0, 0x0, 0), /* MX35_PAD_FEC_TDATA0__FEC_TDATA_0 */
-	[871] = IMX_PIN_REG(MX35_PAD_FEC_TDATA0, 0x758, 0x2f4, 1, 0x0, 0), /* MX35_PAD_FEC_TDATA0__SPDIF_SPDIF_OUT1 */
-	[872] = IMX_PIN_REG(MX35_PAD_FEC_TDATA0, 0x758, 0x2f4, 2, 0x0, 0), /* MX35_PAD_FEC_TDATA0__UART3_DSR */
-	[873] = IMX_PIN_REG(MX35_PAD_FEC_TDATA0, 0x758, 0x2f4, 3, 0x9d4, 1), /* MX35_PAD_FEC_TDATA0__USB_TOP_USBH2_DATA_2 */
-	[874] = IMX_PIN_REG(MX35_PAD_FEC_TDATA0, 0x758, 0x2f4, 4, 0x7f4, 2), /* MX35_PAD_FEC_TDATA0__CSPI2_SS1 */
-	[875] = IMX_PIN_REG(MX35_PAD_FEC_TDATA0, 0x758, 0x2f4, 5, 0x8f0, 1), /* MX35_PAD_FEC_TDATA0__GPIO3_11 */
-	[876] = IMX_PIN_REG(MX35_PAD_FEC_TDATA0, 0x758, 0x2f4, 6, 0x0, 0), /* MX35_PAD_FEC_TDATA0__IPU_DISPB_CS0 */
-	[877] = IMX_PIN_REG(MX35_PAD_FEC_TDATA0, 0x758, 0x2f4, 7, 0x0, 0), /* MX35_PAD_FEC_TDATA0__ARM11P_TOP_EVNTBUS_5 */
-	[878] = IMX_PIN_REG(MX35_PAD_FEC_TX_EN, 0x75c, 0x2f8, 0, 0x0, 0), /* MX35_PAD_FEC_TX_EN__FEC_TX_EN */
-	[879] = IMX_PIN_REG(MX35_PAD_FEC_TX_EN, 0x75c, 0x2f8, 1, 0x998, 3), /* MX35_PAD_FEC_TX_EN__SPDIF_SPDIF_IN1 */
-	[880] = IMX_PIN_REG(MX35_PAD_FEC_TX_EN, 0x75c, 0x2f8, 2, 0x0, 0), /* MX35_PAD_FEC_TX_EN__UART3_RI */
-	[881] = IMX_PIN_REG(MX35_PAD_FEC_TX_EN, 0x75c, 0x2f8, 3, 0x9d8, 1), /* MX35_PAD_FEC_TX_EN__USB_TOP_USBH2_DATA_3 */
-	[882] = IMX_PIN_REG(MX35_PAD_FEC_TX_EN, 0x75c, 0x2f8, 5, 0x8f4, 1), /* MX35_PAD_FEC_TX_EN__GPIO3_12 */
-	[883] = IMX_PIN_REG(MX35_PAD_FEC_TX_EN, 0x75c, 0x2f8, 6, 0x0, 0), /* MX35_PAD_FEC_TX_EN__IPU_DISPB_PAR_RS */
-	[884] = IMX_PIN_REG(MX35_PAD_FEC_TX_EN, 0x75c, 0x2f8, 7, 0x0, 0), /* MX35_PAD_FEC_TX_EN__ARM11P_TOP_EVNTBUS_6 */
-	[885] = IMX_PIN_REG(MX35_PAD_FEC_MDC, 0x760, 0x2fc, 0, 0x0, 0), /* MX35_PAD_FEC_MDC__FEC_MDC */
-	[886] = IMX_PIN_REG(MX35_PAD_FEC_MDC, 0x760, 0x2fc, 1, 0x0, 0), /* MX35_PAD_FEC_MDC__CAN2_TXCAN */
-	[887] = IMX_PIN_REG(MX35_PAD_FEC_MDC, 0x760, 0x2fc, 2, 0x0, 0), /* MX35_PAD_FEC_MDC__UART3_DCD */
-	[888] = IMX_PIN_REG(MX35_PAD_FEC_MDC, 0x760, 0x2fc, 3, 0x9dc, 1), /* MX35_PAD_FEC_MDC__USB_TOP_USBH2_DATA_4 */
-	[889] = IMX_PIN_REG(MX35_PAD_FEC_MDC, 0x760, 0x2fc, 5, 0x8f8, 1), /* MX35_PAD_FEC_MDC__GPIO3_13 */
-	[890] = IMX_PIN_REG(MX35_PAD_FEC_MDC, 0x760, 0x2fc, 6, 0x0, 0), /* MX35_PAD_FEC_MDC__IPU_DISPB_WR */
-	[891] = IMX_PIN_REG(MX35_PAD_FEC_MDC, 0x760, 0x2fc, 7, 0x0, 0), /* MX35_PAD_FEC_MDC__ARM11P_TOP_EVNTBUS_7 */
-	[892] = IMX_PIN_REG(MX35_PAD_FEC_MDIO, 0x764, 0x300, 0, 0x0, 0), /* MX35_PAD_FEC_MDIO__FEC_MDIO */
-	[893] = IMX_PIN_REG(MX35_PAD_FEC_MDIO, 0x764, 0x300, 1, 0x7cc, 2), /* MX35_PAD_FEC_MDIO__CAN2_RXCAN */
-	[894] = IMX_PIN_REG(MX35_PAD_FEC_MDIO, 0x764, 0x300, 3, 0x9e0, 1), /* MX35_PAD_FEC_MDIO__USB_TOP_USBH2_DATA_5 */
-	[895] = IMX_PIN_REG(MX35_PAD_FEC_MDIO, 0x764, 0x300, 5, 0x8fc, 1), /* MX35_PAD_FEC_MDIO__GPIO3_14 */
-	[896] = IMX_PIN_REG(MX35_PAD_FEC_MDIO, 0x764, 0x300, 6, 0x0, 0), /* MX35_PAD_FEC_MDIO__IPU_DISPB_RD */
-	[897] = IMX_PIN_REG(MX35_PAD_FEC_MDIO, 0x764, 0x300, 7, 0x0, 0), /* MX35_PAD_FEC_MDIO__ARM11P_TOP_EVNTBUS_8 */
-	[898] = IMX_PIN_REG(MX35_PAD_FEC_TX_ERR, 0x768, 0x304, 0, 0x0, 0), /* MX35_PAD_FEC_TX_ERR__FEC_TX_ERR */
-	[899] = IMX_PIN_REG(MX35_PAD_FEC_TX_ERR, 0x768, 0x304, 1, 0x990, 2), /* MX35_PAD_FEC_TX_ERR__OWIRE_LINE */
-	[900] = IMX_PIN_REG(MX35_PAD_FEC_TX_ERR, 0x768, 0x304, 2, 0x994, 4), /* MX35_PAD_FEC_TX_ERR__SPDIF_SPDIF_EXTCLK */
-	[901] = IMX_PIN_REG(MX35_PAD_FEC_TX_ERR, 0x768, 0x304, 3, 0x9e4, 1), /* MX35_PAD_FEC_TX_ERR__USB_TOP_USBH2_DATA_6 */
-	[902] = IMX_PIN_REG(MX35_PAD_FEC_TX_ERR, 0x768, 0x304, 5, 0x900, 1), /* MX35_PAD_FEC_TX_ERR__GPIO3_15 */
-	[903] = IMX_PIN_REG(MX35_PAD_FEC_TX_ERR, 0x768, 0x304, 6, 0x924, 3), /* MX35_PAD_FEC_TX_ERR__IPU_DISPB_D0_VSYNC */
-	[904] = IMX_PIN_REG(MX35_PAD_FEC_TX_ERR, 0x768, 0x304, 7, 0x0, 0), /* MX35_PAD_FEC_TX_ERR__ARM11P_TOP_EVNTBUS_9 */
-	[905] = IMX_PIN_REG(MX35_PAD_FEC_RX_ERR, 0x76c, 0x308, 0, 0x0, 0), /* MX35_PAD_FEC_RX_ERR__FEC_RX_ERR */
-	[906] = IMX_PIN_REG(MX35_PAD_FEC_RX_ERR, 0x76c, 0x308, 1, 0x930, 3), /* MX35_PAD_FEC_RX_ERR__IPU_CSI_D_0 */
-	[907] = IMX_PIN_REG(MX35_PAD_FEC_RX_ERR, 0x76c, 0x308, 3, 0x9e8, 1), /* MX35_PAD_FEC_RX_ERR__USB_TOP_USBH2_DATA_7 */
-	[908] = IMX_PIN_REG(MX35_PAD_FEC_RX_ERR, 0x76c, 0x308, 4, 0x960, 1), /* MX35_PAD_FEC_RX_ERR__KPP_COL_4 */
-	[909] = IMX_PIN_REG(MX35_PAD_FEC_RX_ERR, 0x76c, 0x308, 5, 0x0, 0), /* MX35_PAD_FEC_RX_ERR__GPIO3_16 */
-	[910] = IMX_PIN_REG(MX35_PAD_FEC_RX_ERR, 0x76c, 0x308, 6, 0x92c, 5), /* MX35_PAD_FEC_RX_ERR__IPU_DISPB_SD_D_IO */
-	[911] = IMX_PIN_REG(MX35_PAD_FEC_CRS, 0x770, 0x30c, 0, 0x0, 0), /* MX35_PAD_FEC_CRS__FEC_CRS */
-	[912] = IMX_PIN_REG(MX35_PAD_FEC_CRS, 0x770, 0x30c, 1, 0x934, 3), /* MX35_PAD_FEC_CRS__IPU_CSI_D_1 */
-	[913] = IMX_PIN_REG(MX35_PAD_FEC_CRS, 0x770, 0x30c, 3, 0x0, 0), /* MX35_PAD_FEC_CRS__USB_TOP_USBH2_PWR */
-	[914] = IMX_PIN_REG(MX35_PAD_FEC_CRS, 0x770, 0x30c, 4, 0x964, 1), /* MX35_PAD_FEC_CRS__KPP_COL_5 */
-	[915] = IMX_PIN_REG(MX35_PAD_FEC_CRS, 0x770, 0x30c, 5, 0x0, 0), /* MX35_PAD_FEC_CRS__GPIO3_17 */
-	[916] = IMX_PIN_REG(MX35_PAD_FEC_CRS, 0x770, 0x30c, 6, 0x0, 0), /* MX35_PAD_FEC_CRS__IPU_FLASH_STROBE */
-	[917] = IMX_PIN_REG(MX35_PAD_FEC_RDATA1, 0x774, 0x310, 0, 0x0, 0), /* MX35_PAD_FEC_RDATA1__FEC_RDATA_1 */
-	[918] = IMX_PIN_REG(MX35_PAD_FEC_RDATA1, 0x774, 0x310, 1, 0x938, 4), /* MX35_PAD_FEC_RDATA1__IPU_CSI_D_2 */
-	[919] = IMX_PIN_REG(MX35_PAD_FEC_RDATA1, 0x774, 0x310, 2, 0x0, 0), /* MX35_PAD_FEC_RDATA1__AUDMUX_AUD6_RXC */
-	[920] = IMX_PIN_REG(MX35_PAD_FEC_RDATA1, 0x774, 0x310, 3, 0x9f4, 2), /* MX35_PAD_FEC_RDATA1__USB_TOP_USBH2_OC */
-	[921] = IMX_PIN_REG(MX35_PAD_FEC_RDATA1, 0x774, 0x310, 4, 0x968, 1), /* MX35_PAD_FEC_RDATA1__KPP_COL_6 */
-	[922] = IMX_PIN_REG(MX35_PAD_FEC_RDATA1, 0x774, 0x310, 5, 0x0, 0), /* MX35_PAD_FEC_RDATA1__GPIO3_18 */
-	[923] = IMX_PIN_REG(MX35_PAD_FEC_RDATA1, 0x774, 0x310, 6, 0x0, 0), /* MX35_PAD_FEC_RDATA1__IPU_DISPB_BE0 */
-	[924] = IMX_PIN_REG(MX35_PAD_FEC_TDATA1, 0x778, 0x314, 0, 0x0, 0), /* MX35_PAD_FEC_TDATA1__FEC_TDATA_1 */
-	[925] = IMX_PIN_REG(MX35_PAD_FEC_TDATA1, 0x778, 0x314, 1, 0x93c, 4), /* MX35_PAD_FEC_TDATA1__IPU_CSI_D_3 */
-	[926] = IMX_PIN_REG(MX35_PAD_FEC_TDATA1, 0x778, 0x314, 2, 0x7bc, 1), /* MX35_PAD_FEC_TDATA1__AUDMUX_AUD6_RXFS */
-	[927] = IMX_PIN_REG(MX35_PAD_FEC_TDATA1, 0x778, 0x314, 4, 0x96c, 1), /* MX35_PAD_FEC_TDATA1__KPP_COL_7 */
-	[928] = IMX_PIN_REG(MX35_PAD_FEC_TDATA1, 0x778, 0x314, 5, 0x0, 0), /* MX35_PAD_FEC_TDATA1__GPIO3_19 */
-	[929] = IMX_PIN_REG(MX35_PAD_FEC_TDATA1, 0x778, 0x314, 6, 0x0, 0), /* MX35_PAD_FEC_TDATA1__IPU_DISPB_BE1 */
-	[930] = IMX_PIN_REG(MX35_PAD_FEC_RDATA2, 0x77c, 0x318, 0, 0x0, 0), /* MX35_PAD_FEC_RDATA2__FEC_RDATA_2 */
-	[931] = IMX_PIN_REG(MX35_PAD_FEC_RDATA2, 0x77c, 0x318, 1, 0x940, 3), /* MX35_PAD_FEC_RDATA2__IPU_CSI_D_4 */
-	[932] = IMX_PIN_REG(MX35_PAD_FEC_RDATA2, 0x77c, 0x318, 2, 0x7b4, 1), /* MX35_PAD_FEC_RDATA2__AUDMUX_AUD6_TXD */
-	[933] = IMX_PIN_REG(MX35_PAD_FEC_RDATA2, 0x77c, 0x318, 4, 0x980, 1), /* MX35_PAD_FEC_RDATA2__KPP_ROW_4 */
-	[934] = IMX_PIN_REG(MX35_PAD_FEC_RDATA2, 0x77c, 0x318, 5, 0x0, 0), /* MX35_PAD_FEC_RDATA2__GPIO3_20 */
-	[935] = IMX_PIN_REG(MX35_PAD_FEC_TDATA2, 0x780, 0x31c, 0, 0x0, 0), /* MX35_PAD_FEC_TDATA2__FEC_TDATA_2 */
-	[936] = IMX_PIN_REG(MX35_PAD_FEC_TDATA2, 0x780, 0x31c, 1, 0x944, 3), /* MX35_PAD_FEC_TDATA2__IPU_CSI_D_5 */
-	[937] = IMX_PIN_REG(MX35_PAD_FEC_TDATA2, 0x780, 0x31c, 2, 0x7b0, 1), /* MX35_PAD_FEC_TDATA2__AUDMUX_AUD6_RXD */
-	[938] = IMX_PIN_REG(MX35_PAD_FEC_TDATA2, 0x780, 0x31c, 4, 0x984, 1), /* MX35_PAD_FEC_TDATA2__KPP_ROW_5 */
-	[939] = IMX_PIN_REG(MX35_PAD_FEC_TDATA2, 0x780, 0x31c, 5, 0x0, 0), /* MX35_PAD_FEC_TDATA2__GPIO3_21 */
-	[940] = IMX_PIN_REG(MX35_PAD_FEC_RDATA3, 0x784, 0x320, 0, 0x0, 0), /* MX35_PAD_FEC_RDATA3__FEC_RDATA_3 */
-	[941] = IMX_PIN_REG(MX35_PAD_FEC_RDATA3, 0x784, 0x320, 1, 0x948, 3), /* MX35_PAD_FEC_RDATA3__IPU_CSI_D_6 */
-	[942] = IMX_PIN_REG(MX35_PAD_FEC_RDATA3, 0x784, 0x320, 2, 0x7c0, 1), /* MX35_PAD_FEC_RDATA3__AUDMUX_AUD6_TXC */
-	[943] = IMX_PIN_REG(MX35_PAD_FEC_RDATA3, 0x784, 0x320, 4, 0x988, 1), /* MX35_PAD_FEC_RDATA3__KPP_ROW_6 */
-	[944] = IMX_PIN_REG(MX35_PAD_FEC_RDATA3, 0x784, 0x320, 6, 0x0, 0), /* MX35_PAD_FEC_RDATA3__GPIO3_22 */
-	[945] = IMX_PIN_REG(MX35_PAD_FEC_TDATA3, 0x788, 0x324, 0, 0x0, 0), /* MX35_PAD_FEC_TDATA3__FEC_TDATA_3 */
-	[946] = IMX_PIN_REG(MX35_PAD_FEC_TDATA3, 0x788, 0x324, 1, 0x94c, 3), /* MX35_PAD_FEC_TDATA3__IPU_CSI_D_7 */
-	[947] = IMX_PIN_REG(MX35_PAD_FEC_TDATA3, 0x788, 0x324, 2, 0x7c4, 1), /* MX35_PAD_FEC_TDATA3__AUDMUX_AUD6_TXFS */
-	[948] = IMX_PIN_REG(MX35_PAD_FEC_TDATA3, 0x788, 0x324, 4, 0x98c, 1), /* MX35_PAD_FEC_TDATA3__KPP_ROW_7 */
-	[949] = IMX_PIN_REG(MX35_PAD_FEC_TDATA3, 0x788, 0x324, 5, 0x0, 0), /* MX35_PAD_FEC_TDATA3__GPIO3_23 */
-	[950] = IMX_PIN_REG(MX35_PAD_EXT_ARMCLK, 0x78c, 0x0, 0, 0x0, 0), /* MX35_PAD_EXT_ARMCLK__CCM_EXT_ARMCLK */
-	[951] = IMX_PIN_REG(MX35_PAD_TEST_MODE, 0x790, 0x0, 0, 0x0, 0), /* MX35_PAD_TEST_MODE__TCU_TEST_MODE */
+	MX35_PAD_CAPTURE = 1,
+	MX35_PAD_COMPARE = 2,
+	MX35_PAD_WDOG_RST = 3,
+	MX35_PAD_GPIO1_0 = 4,
+	MX35_PAD_GPIO1_1 = 5,
+	MX35_PAD_GPIO2_0 = 6,
+	MX35_PAD_GPIO3_0 = 7,
+	MX35_PAD_CLKO = 8,
+	MX35_PAD_VSTBY = 9,
+	MX35_PAD_A0 = 10,
+	MX35_PAD_A1 = 11,
+	MX35_PAD_A2 = 12,
+	MX35_PAD_A3 = 13,
+	MX35_PAD_A4 = 14,
+	MX35_PAD_A5 = 15,
+	MX35_PAD_A6 = 16,
+	MX35_PAD_A7 = 17,
+	MX35_PAD_A8 = 18,
+	MX35_PAD_A9 = 19,
+	MX35_PAD_A10 = 20,
+	MX35_PAD_MA10 = 21,
+	MX35_PAD_A11 = 22,
+	MX35_PAD_A12 = 23,
+	MX35_PAD_A13 = 24,
+	MX35_PAD_A14 = 25,
+	MX35_PAD_A15 = 26,
+	MX35_PAD_A16 = 27,
+	MX35_PAD_A17 = 28,
+	MX35_PAD_A18 = 29,
+	MX35_PAD_A19 = 30,
+	MX35_PAD_A20 = 31,
+	MX35_PAD_A21 = 32,
+	MX35_PAD_A22 = 33,
+	MX35_PAD_A23 = 34,
+	MX35_PAD_A24 = 35,
+	MX35_PAD_A25 = 36,
+	MX35_PAD_EB0 = 37,
+	MX35_PAD_EB1 = 38,
+	MX35_PAD_OE = 39,
+	MX35_PAD_CS0 = 40,
+	MX35_PAD_CS1 = 41,
+	MX35_PAD_CS2 = 42,
+	MX35_PAD_CS3 = 43,
+	MX35_PAD_CS4 = 44,
+	MX35_PAD_CS5 = 45,
+	MX35_PAD_NF_CE0 = 46,
+	MX35_PAD_LBA = 47,
+	MX35_PAD_BCLK = 48,
+	MX35_PAD_RW = 49,
+	MX35_PAD_NFWE_B = 50,
+	MX35_PAD_NFRE_B = 51,
+	MX35_PAD_NFALE = 52,
+	MX35_PAD_NFCLE = 53,
+	MX35_PAD_NFWP_B = 54,
+	MX35_PAD_NFRB = 55,
+	MX35_PAD_CSI_D8 = 56,
+	MX35_PAD_CSI_D9 = 57,
+	MX35_PAD_CSI_D10 = 58,
+	MX35_PAD_CSI_D11 = 59,
+	MX35_PAD_CSI_D12 = 60,
+	MX35_PAD_CSI_D13 = 61,
+	MX35_PAD_CSI_D14 = 62,
+	MX35_PAD_CSI_D15 = 63,
+	MX35_PAD_CSI_MCLK = 64,
+	MX35_PAD_CSI_VSYNC = 65,
+	MX35_PAD_CSI_HSYNC = 66,
+	MX35_PAD_CSI_PIXCLK = 67,
+	MX35_PAD_I2C1_CLK = 68,
+	MX35_PAD_I2C1_DAT = 69,
+	MX35_PAD_I2C2_CLK = 70,
+	MX35_PAD_I2C2_DAT = 71,
+	MX35_PAD_STXD4 = 72,
+	MX35_PAD_SRXD4 = 73,
+	MX35_PAD_SCK4 = 74,
+	MX35_PAD_STXFS4 = 75,
+	MX35_PAD_STXD5 = 76,
+	MX35_PAD_SRXD5 = 77,
+	MX35_PAD_SCK5 = 78,
+	MX35_PAD_STXFS5 = 79,
+	MX35_PAD_SCKR = 80,
+	MX35_PAD_FSR = 81,
+	MX35_PAD_HCKR = 82,
+	MX35_PAD_SCKT = 83,
+	MX35_PAD_FST = 84,
+	MX35_PAD_HCKT = 85,
+	MX35_PAD_TX5_RX0 = 86,
+	MX35_PAD_TX4_RX1 = 87,
+	MX35_PAD_TX3_RX2 = 88,
+	MX35_PAD_TX2_RX3 = 89,
+	MX35_PAD_TX1 = 90,
+	MX35_PAD_TX0 = 91,
+	MX35_PAD_CSPI1_MOSI = 92,
+	MX35_PAD_CSPI1_MISO = 93,
+	MX35_PAD_CSPI1_SS0 = 94,
+	MX35_PAD_CSPI1_SS1 = 95,
+	MX35_PAD_CSPI1_SCLK = 96,
+	MX35_PAD_CSPI1_SPI_RDY = 97,
+	MX35_PAD_RXD1 = 98,
+	MX35_PAD_TXD1 = 99,
+	MX35_PAD_RTS1 = 100,
+	MX35_PAD_CTS1 = 101,
+	MX35_PAD_RXD2 = 102,
+	MX35_PAD_TXD2 = 103,
+	MX35_PAD_RTS2 = 104,
+	MX35_PAD_CTS2 = 105,
+	MX35_PAD_USBOTG_PWR = 106,
+	MX35_PAD_USBOTG_OC = 107,
+	MX35_PAD_LD0 = 108,
+	MX35_PAD_LD1 = 109,
+	MX35_PAD_LD2 = 110,
+	MX35_PAD_LD3 = 111,
+	MX35_PAD_LD4 = 112,
+	MX35_PAD_LD5 = 113,
+	MX35_PAD_LD6 = 114,
+	MX35_PAD_LD7 = 115,
+	MX35_PAD_LD8 = 116,
+	MX35_PAD_LD9 = 117,
+	MX35_PAD_LD10 = 118,
+	MX35_PAD_LD11 = 119,
+	MX35_PAD_LD12 = 120,
+	MX35_PAD_LD13 = 121,
+	MX35_PAD_LD14 = 122,
+	MX35_PAD_LD15 = 123,
+	MX35_PAD_LD16 = 124,
+	MX35_PAD_LD17 = 125,
+	MX35_PAD_LD18 = 126,
+	MX35_PAD_LD19 = 127,
+	MX35_PAD_LD20 = 128,
+	MX35_PAD_LD21 = 129,
+	MX35_PAD_LD22 = 130,
+	MX35_PAD_LD23 = 131,
+	MX35_PAD_D3_HSYNC = 132,
+	MX35_PAD_D3_FPSHIFT = 133,
+	MX35_PAD_D3_DRDY = 134,
+	MX35_PAD_CONTRAST = 135,
+	MX35_PAD_D3_VSYNC = 136,
+	MX35_PAD_D3_REV = 137,
+	MX35_PAD_D3_CLS = 138,
+	MX35_PAD_D3_SPL = 139,
+	MX35_PAD_SD1_CMD = 140,
+	MX35_PAD_SD1_CLK = 141,
+	MX35_PAD_SD1_DATA0 = 142,
+	MX35_PAD_SD1_DATA1 = 143,
+	MX35_PAD_SD1_DATA2 = 144,
+	MX35_PAD_SD1_DATA3 = 145,
+	MX35_PAD_SD2_CMD = 146,
+	MX35_PAD_SD2_CLK = 147,
+	MX35_PAD_SD2_DATA0 = 148,
+	MX35_PAD_SD2_DATA1 = 149,
+	MX35_PAD_SD2_DATA2 = 150,
+	MX35_PAD_SD2_DATA3 = 151,
+	MX35_PAD_ATA_CS0 = 152,
+	MX35_PAD_ATA_CS1 = 153,
+	MX35_PAD_ATA_DIOR = 154,
+	MX35_PAD_ATA_DIOW = 155,
+	MX35_PAD_ATA_DMACK = 156,
+	MX35_PAD_ATA_RESET_B = 157,
+	MX35_PAD_ATA_IORDY = 158,
+	MX35_PAD_ATA_DATA0 = 159,
+	MX35_PAD_ATA_DATA1 = 160,
+	MX35_PAD_ATA_DATA2 = 161,
+	MX35_PAD_ATA_DATA3 = 162,
+	MX35_PAD_ATA_DATA4 = 163,
+	MX35_PAD_ATA_DATA5 = 164,
+	MX35_PAD_ATA_DATA6 = 165,
+	MX35_PAD_ATA_DATA7 = 166,
+	MX35_PAD_ATA_DATA8 = 167,
+	MX35_PAD_ATA_DATA9 = 168,
+	MX35_PAD_ATA_DATA10 = 169,
+	MX35_PAD_ATA_DATA11 = 170,
+	MX35_PAD_ATA_DATA12 = 171,
+	MX35_PAD_ATA_DATA13 = 172,
+	MX35_PAD_ATA_DATA14 = 173,
+	MX35_PAD_ATA_DATA15 = 174,
+	MX35_PAD_ATA_INTRQ = 175,
+	MX35_PAD_ATA_BUFF_EN = 176,
+	MX35_PAD_ATA_DMARQ = 177,
+	MX35_PAD_ATA_DA0 = 178,
+	MX35_PAD_ATA_DA1 = 179,
+	MX35_PAD_ATA_DA2 = 180,
+	MX35_PAD_MLB_CLK = 181,
+	MX35_PAD_MLB_DAT = 182,
+	MX35_PAD_MLB_SIG = 183,
+	MX35_PAD_FEC_TX_CLK = 184,
+	MX35_PAD_FEC_RX_CLK = 185,
+	MX35_PAD_FEC_RX_DV = 186,
+	MX35_PAD_FEC_COL = 187,
+	MX35_PAD_FEC_RDATA0 = 188,
+	MX35_PAD_FEC_TDATA0 = 189,
+	MX35_PAD_FEC_TX_EN = 190,
+	MX35_PAD_FEC_MDC = 191,
+	MX35_PAD_FEC_MDIO = 192,
+	MX35_PAD_FEC_TX_ERR = 193,
+	MX35_PAD_FEC_RX_ERR = 194,
+	MX35_PAD_FEC_CRS = 195,
+	MX35_PAD_FEC_RDATA1 = 196,
+	MX35_PAD_FEC_TDATA1 = 197,
+	MX35_PAD_FEC_RDATA2 = 198,
+	MX35_PAD_FEC_TDATA2 = 199,
+	MX35_PAD_FEC_RDATA3 = 200,
+	MX35_PAD_FEC_TDATA3 = 201,
+	MX35_PAD_RESET_IN_B = 209,
+	MX35_PAD_POR_B = 210,
+	MX35_PAD_BOOT_MODE0 = 212,
+	MX35_PAD_BOOT_MODE1 = 213,
+	MX35_PAD_CLK_MODE0 = 214,
+	MX35_PAD_CLK_MODE1 = 215,
+	MX35_PAD_POWER_FAIL = 216,
+	MX35_PAD_SDBA1 = 245,
+	MX35_PAD_SDBA0 = 246,
+	MX35_PAD_SD0 = 247,
+	MX35_PAD_SD1 = 248,
+	MX35_PAD_SD2 = 249,
+	MX35_PAD_SD3 = 250,
+	MX35_PAD_SD4 = 251,
+	MX35_PAD_SD5 = 252,
+	MX35_PAD_SD6 = 253,
+	MX35_PAD_SD7 = 254,
+	MX35_PAD_SD8 = 255,
+	MX35_PAD_SD9 = 256,
+	MX35_PAD_SD10 = 257,
+	MX35_PAD_SD11 = 258,
+	MX35_PAD_SD12 = 259,
+	MX35_PAD_SD13 = 260,
+	MX35_PAD_SD14 = 261,
+	MX35_PAD_SD15 = 262,
+	MX35_PAD_SD16 = 263,
+	MX35_PAD_SD17 = 264,
+	MX35_PAD_SD18 = 265,
+	MX35_PAD_SD19 = 266,
+	MX35_PAD_SD20 = 267,
+	MX35_PAD_SD21 = 268,
+	MX35_PAD_SD22 = 269,
+	MX35_PAD_SD23 = 270,
+	MX35_PAD_SD24 = 271,
+	MX35_PAD_SD25 = 272,
+	MX35_PAD_SD26 = 273,
+	MX35_PAD_SD27 = 274,
+	MX35_PAD_SD28 = 275,
+	MX35_PAD_SD29 = 276,
+	MX35_PAD_SD30 = 277,
+	MX35_PAD_SD31 = 278,
+	MX35_PAD_DQM0 = 279,
+	MX35_PAD_DQM1 = 280,
+	MX35_PAD_DQM2 = 281,
+	MX35_PAD_DQM3 = 282,
+	MX35_PAD_ECB = 293,
+	MX35_PAD_RAS = 297,
+	MX35_PAD_CAS = 298,
+	MX35_PAD_SDWE = 299,
+	MX35_PAD_SDCKE0 = 300,
+	MX35_PAD_SDCKE1 = 301,
+	MX35_PAD_SDCLK = 302,
+	MX35_PAD_SDQS0 = 303,
+	MX35_PAD_SDQS1 = 304,
+	MX35_PAD_SDQS2 = 305,
+	MX35_PAD_SDQS3 = 306,
+	MX35_PAD_D15 = 313,
+	MX35_PAD_D14 = 314,
+	MX35_PAD_D13 = 315,
+	MX35_PAD_D12 = 316,
+	MX35_PAD_D11 = 317,
+	MX35_PAD_D10 = 318,
+	MX35_PAD_D9 = 319,
+	MX35_PAD_D8 = 320,
+	MX35_PAD_D7 = 321,
+	MX35_PAD_D6 = 322,
+	MX35_PAD_D5 = 323,
+	MX35_PAD_D4 = 324,
+	MX35_PAD_D3 = 325,
+	MX35_PAD_D2 = 326,
+	MX35_PAD_D1 = 327,
+	MX35_PAD_D0 = 328,
+	MX35_PAD_RTCK = 379,
+	MX35_PAD_TCK = 380,
+	MX35_PAD_TMS = 381,
+	MX35_PAD_TDI = 382,
+	MX35_PAD_TDO = 383,
+	MX35_PAD_TRSTB = 384,
+	MX35_PAD_DE_B = 385,
+	MX35_PAD_SJC_MOD = 386,
+	MX35_PAD_EXT_ARMCLK = 483,
+	MX35_PAD_TEST_MODE = 484,
 };
 
 /* Pad names for the pinmux subsystem */
@@ -1555,8 +599,6 @@ static const struct pinctrl_pin_desc imx35_pinctrl_pads[] = {
 static struct imx_pinctrl_soc_info imx35_pinctrl_info = {
 	.pins = imx35_pinctrl_pads,
 	.npins = ARRAY_SIZE(imx35_pinctrl_pads),
-	.pin_regs = imx35_pin_regs,
-	.npin_regs = ARRAY_SIZE(imx35_pin_regs),
 };
 
 static struct of_device_id imx35_pinctrl_of_match[] = {
diff --git a/drivers/pinctrl/pinctrl-imx51.c b/drivers/pinctrl/pinctrl-imx51.c
index 9a92aaa..c64fb5f 100644
--- a/drivers/pinctrl/pinctrl-imx51.c
+++ b/drivers/pinctrl/pinctrl-imx51.c
@@ -23,1011 +23,251 @@
 #include "pinctrl-imx.h"
 
 enum imx51_pads {
-	MX51_PAD_EIM_D16 = 0,
-	MX51_PAD_EIM_D17 = 1,
-	MX51_PAD_EIM_D18 = 2,
-	MX51_PAD_EIM_D19 = 3,
-	MX51_PAD_EIM_D20 = 4,
-	MX51_PAD_EIM_D21 = 5,
-	MX51_PAD_EIM_D22 = 6,
-	MX51_PAD_EIM_D23 = 7,
-	MX51_PAD_EIM_D24 = 8,
-	MX51_PAD_EIM_D25 = 9,
-	MX51_PAD_EIM_D26 = 10,
-	MX51_PAD_EIM_D27 = 11,
-	MX51_PAD_EIM_D28 = 12,
-	MX51_PAD_EIM_D29 = 13,
-	MX51_PAD_EIM_D30 = 14,
-	MX51_PAD_EIM_D31 = 15,
-	MX51_PAD_EIM_A16 = 16,
-	MX51_PAD_EIM_A17 = 17,
-	MX51_PAD_EIM_A18 = 18,
-	MX51_PAD_EIM_A19 = 19,
-	MX51_PAD_EIM_A20 = 20,
-	MX51_PAD_EIM_A21 = 21,
-	MX51_PAD_EIM_A22 = 22,
-	MX51_PAD_EIM_A23 = 23,
-	MX51_PAD_EIM_A24 = 24,
-	MX51_PAD_EIM_A25 = 25,
-	MX51_PAD_EIM_A26 = 26,
-	MX51_PAD_EIM_A27 = 27,
-	MX51_PAD_EIM_EB0 = 28,
-	MX51_PAD_EIM_EB1 = 29,
-	MX51_PAD_EIM_EB2 = 30,
-	MX51_PAD_EIM_EB3 = 31,
-	MX51_PAD_EIM_OE = 32,
-	MX51_PAD_EIM_CS0 = 33,
-	MX51_PAD_EIM_CS1 = 34,
-	MX51_PAD_EIM_CS2 = 35,
-	MX51_PAD_EIM_CS3 = 36,
-	MX51_PAD_EIM_CS4 = 37,
-	MX51_PAD_EIM_CS5 = 38,
-	MX51_PAD_EIM_DTACK = 39,
-	MX51_PAD_EIM_LBA = 40,
-	MX51_PAD_EIM_CRE = 41,
-	MX51_PAD_DRAM_CS1 = 42,
-	MX51_PAD_NANDF_WE_B = 43,
-	MX51_PAD_NANDF_RE_B = 44,
-	MX51_PAD_NANDF_ALE = 45,
-	MX51_PAD_NANDF_CLE = 46,
-	MX51_PAD_NANDF_WP_B = 47,
-	MX51_PAD_NANDF_RB0 = 48,
-	MX51_PAD_NANDF_RB1 = 49,
-	MX51_PAD_NANDF_RB2 = 50,
-	MX51_PAD_NANDF_RB3 = 51,
-	MX51_PAD_GPIO_NAND = 52,
-	MX51_PAD_NANDF_CS0 = 53,
-	MX51_PAD_NANDF_CS1 = 54,
-	MX51_PAD_NANDF_CS2 = 55,
-	MX51_PAD_NANDF_CS3 = 56,
-	MX51_PAD_NANDF_CS4 = 57,
-	MX51_PAD_NANDF_CS5 = 58,
-	MX51_PAD_NANDF_CS6 = 59,
-	MX51_PAD_NANDF_CS7 = 60,
-	MX51_PAD_NANDF_RDY_INT = 61,
-	MX51_PAD_NANDF_D15 = 62,
-	MX51_PAD_NANDF_D14 = 63,
-	MX51_PAD_NANDF_D13 = 64,
-	MX51_PAD_NANDF_D12 = 65,
-	MX51_PAD_NANDF_D11 = 66,
-	MX51_PAD_NANDF_D10 = 67,
-	MX51_PAD_NANDF_D9 = 68,
-	MX51_PAD_NANDF_D8 = 69,
-	MX51_PAD_NANDF_D7 = 70,
-	MX51_PAD_NANDF_D6 = 71,
-	MX51_PAD_NANDF_D5 = 72,
-	MX51_PAD_NANDF_D4 = 73,
-	MX51_PAD_NANDF_D3 = 74,
-	MX51_PAD_NANDF_D2 = 75,
-	MX51_PAD_NANDF_D1 = 76,
-	MX51_PAD_NANDF_D0 = 77,
-	MX51_PAD_CSI1_D8 = 78,
-	MX51_PAD_CSI1_D9 = 79,
-	MX51_PAD_CSI1_D10 = 80,
-	MX51_PAD_CSI1_D11 = 81,
-	MX51_PAD_CSI1_D12 = 82,
-	MX51_PAD_CSI1_D13 = 83,
-	MX51_PAD_CSI1_D14 = 84,
-	MX51_PAD_CSI1_D15 = 85,
-	MX51_PAD_CSI1_D16 = 86,
-	MX51_PAD_CSI1_D17 = 87,
-	MX51_PAD_CSI1_D18 = 88,
-	MX51_PAD_CSI1_D19 = 89,
-	MX51_PAD_CSI1_VSYNC = 90,
-	MX51_PAD_CSI1_HSYNC = 91,
-	MX51_PAD_CSI1_PIXCLK = 92,
-	MX51_PAD_CSI1_MCLK = 93,
-	MX51_PAD_CSI2_D12 = 94,
-	MX51_PAD_CSI2_D13 = 95,
-	MX51_PAD_CSI2_D14 = 96,
-	MX51_PAD_CSI2_D15 = 97,
-	MX51_PAD_CSI2_D16 = 98,
-	MX51_PAD_CSI2_D17 = 99,
-	MX51_PAD_CSI2_D18 = 100,
-	MX51_PAD_CSI2_D19 = 101,
-	MX51_PAD_CSI2_VSYNC = 102,
-	MX51_PAD_CSI2_HSYNC = 103,
-	MX51_PAD_CSI2_PIXCLK = 104,
-	MX51_PAD_I2C1_CLK = 105,
-	MX51_PAD_I2C1_DAT = 106,
-	MX51_PAD_AUD3_BB_TXD = 107,
-	MX51_PAD_AUD3_BB_RXD = 108,
-	MX51_PAD_AUD3_BB_CK = 109,
-	MX51_PAD_AUD3_BB_FS = 110,
-	MX51_PAD_CSPI1_MOSI = 111,
-	MX51_PAD_CSPI1_MISO = 112,
-	MX51_PAD_CSPI1_SS0 = 113,
-	MX51_PAD_CSPI1_SS1 = 114,
-	MX51_PAD_CSPI1_RDY = 115,
-	MX51_PAD_CSPI1_SCLK = 116,
-	MX51_PAD_UART1_RXD = 117,
-	MX51_PAD_UART1_TXD = 118,
-	MX51_PAD_UART1_RTS = 119,
-	MX51_PAD_UART1_CTS = 120,
-	MX51_PAD_UART2_RXD = 121,
-	MX51_PAD_UART2_TXD = 122,
-	MX51_PAD_UART3_RXD = 123,
-	MX51_PAD_UART3_TXD = 124,
-	MX51_PAD_OWIRE_LINE = 125,
-	MX51_PAD_KEY_ROW0 = 126,
-	MX51_PAD_KEY_ROW1 = 127,
-	MX51_PAD_KEY_ROW2 = 128,
-	MX51_PAD_KEY_ROW3 = 129,
-	MX51_PAD_KEY_COL0 = 130,
-	MX51_PAD_KEY_COL1 = 131,
-	MX51_PAD_KEY_COL2 = 132,
-	MX51_PAD_KEY_COL3 = 133,
-	MX51_PAD_KEY_COL4 = 134,
-	MX51_PAD_KEY_COL5 = 135,
-	MX51_PAD_USBH1_CLK = 136,
-	MX51_PAD_USBH1_DIR = 137,
-	MX51_PAD_USBH1_STP = 138,
-	MX51_PAD_USBH1_NXT = 139,
-	MX51_PAD_USBH1_DATA0 = 140,
-	MX51_PAD_USBH1_DATA1 = 141,
-	MX51_PAD_USBH1_DATA2 = 142,
-	MX51_PAD_USBH1_DATA3 = 143,
-	MX51_PAD_USBH1_DATA4 = 144,
-	MX51_PAD_USBH1_DATA5 = 145,
-	MX51_PAD_USBH1_DATA6 = 146,
-	MX51_PAD_USBH1_DATA7 = 147,
-	MX51_PAD_DI1_PIN11 = 148,
-	MX51_PAD_DI1_PIN12 = 149,
-	MX51_PAD_DI1_PIN13 = 150,
-	MX51_PAD_DI1_D0_CS = 151,
-	MX51_PAD_DI1_D1_CS = 152,
-	MX51_PAD_DISPB2_SER_DIN = 153,
-	MX51_PAD_DISPB2_SER_DIO = 154,
-	MX51_PAD_DISPB2_SER_CLK = 155,
-	MX51_PAD_DISPB2_SER_RS = 156,
-	MX51_PAD_DISP1_DAT0 = 157,
-	MX51_PAD_DISP1_DAT1 = 158,
-	MX51_PAD_DISP1_DAT2 = 159,
-	MX51_PAD_DISP1_DAT3 = 160,
-	MX51_PAD_DISP1_DAT4 = 161,
-	MX51_PAD_DISP1_DAT5 = 162,
-	MX51_PAD_DISP1_DAT6 = 163,
-	MX51_PAD_DISP1_DAT7 = 164,
-	MX51_PAD_DISP1_DAT8 = 165,
-	MX51_PAD_DISP1_DAT9 = 166,
-	MX51_PAD_DISP1_DAT10 = 167,
-	MX51_PAD_DISP1_DAT11 = 168,
-	MX51_PAD_DISP1_DAT12 = 169,
-	MX51_PAD_DISP1_DAT13 = 170,
-	MX51_PAD_DISP1_DAT14 = 171,
-	MX51_PAD_DISP1_DAT15 = 172,
-	MX51_PAD_DISP1_DAT16 = 173,
-	MX51_PAD_DISP1_DAT17 = 174,
-	MX51_PAD_DISP1_DAT18 = 175,
-	MX51_PAD_DISP1_DAT19 = 176,
-	MX51_PAD_DISP1_DAT20 = 177,
-	MX51_PAD_DISP1_DAT21 = 178,
-	MX51_PAD_DISP1_DAT22 = 179,
-	MX51_PAD_DISP1_DAT23 = 180,
-	MX51_PAD_DI1_PIN3 = 181,
-	MX51_PAD_DI1_PIN2 = 182,
-	MX51_PAD_DI_GP2 = 183,
-	MX51_PAD_DI_GP3 = 184,
-	MX51_PAD_DI2_PIN4 = 185,
-	MX51_PAD_DI2_PIN2 = 186,
-	MX51_PAD_DI2_PIN3 = 187,
-	MX51_PAD_DI2_DISP_CLK = 188,
-	MX51_PAD_DI_GP4 = 189,
-	MX51_PAD_DISP2_DAT0 = 190,
-	MX51_PAD_DISP2_DAT1 = 191,
-	MX51_PAD_DISP2_DAT2 = 192,
-	MX51_PAD_DISP2_DAT3 = 193,
-	MX51_PAD_DISP2_DAT4 = 194,
-	MX51_PAD_DISP2_DAT5 = 195,
-	MX51_PAD_DISP2_DAT6 = 196,
-	MX51_PAD_DISP2_DAT7 = 197,
-	MX51_PAD_DISP2_DAT8 = 198,
-	MX51_PAD_DISP2_DAT9 = 199,
-	MX51_PAD_DISP2_DAT10 = 200,
-	MX51_PAD_DISP2_DAT11 = 201,
-	MX51_PAD_DISP2_DAT12 = 202,
-	MX51_PAD_DISP2_DAT13 = 203,
-	MX51_PAD_DISP2_DAT14 = 204,
-	MX51_PAD_DISP2_DAT15 = 205,
-	MX51_PAD_SD1_CMD = 206,
-	MX51_PAD_SD1_CLK = 207,
-	MX51_PAD_SD1_DATA0 = 208,
-	MX51_PAD_EIM_DA0 = 209,
-	MX51_PAD_EIM_DA1 = 210,
-	MX51_PAD_EIM_DA2 = 211,
-	MX51_PAD_EIM_DA3 = 212,
-	MX51_PAD_SD1_DATA1 = 213,
-	MX51_PAD_EIM_DA4 = 214,
-	MX51_PAD_EIM_DA5 = 215,
-	MX51_PAD_EIM_DA6 = 216,
-	MX51_PAD_EIM_DA7 = 217,
-	MX51_PAD_SD1_DATA2 = 218,
-	MX51_PAD_EIM_DA10 = 219,
-	MX51_PAD_EIM_DA11 = 220,
-	MX51_PAD_EIM_DA8 = 221,
-	MX51_PAD_EIM_DA9 = 222,
-	MX51_PAD_SD1_DATA3 = 223,
-	MX51_PAD_GPIO1_0 = 224,
-	MX51_PAD_GPIO1_1 = 225,
-	MX51_PAD_EIM_DA12 = 226,
-	MX51_PAD_EIM_DA13 = 227,
-	MX51_PAD_EIM_DA14 = 228,
-	MX51_PAD_EIM_DA15 = 229,
-	MX51_PAD_SD2_CMD = 230,
-	MX51_PAD_SD2_CLK = 231,
-	MX51_PAD_SD2_DATA0 = 232,
-	MX51_PAD_SD2_DATA1 = 233,
-	MX51_PAD_SD2_DATA2 = 234,
-	MX51_PAD_SD2_DATA3 = 235,
-	MX51_PAD_GPIO1_2 = 236,
-	MX51_PAD_GPIO1_3 = 237,
-	MX51_PAD_PMIC_INT_REQ = 238,
-	MX51_PAD_GPIO1_4 = 239,
-	MX51_PAD_GPIO1_5 = 240,
-	MX51_PAD_GPIO1_6 = 241,
-	MX51_PAD_GPIO1_7 = 242,
-	MX51_PAD_GPIO1_8 = 243,
-	MX51_PAD_GPIO1_9 = 244,
-};
-
-/* imx51 register maps */
-static struct imx_pin_reg imx51_pin_regs[] = {
-	IMX_PIN_REG(MX51_PAD_EIM_D16, 0x3f0, 0x05c, 5, 0x000, 0), /* MX51_PAD_EIM_D16__AUD4_RXFS */
-	IMX_PIN_REG(MX51_PAD_EIM_D16, 0x3f0, 0x05c, 7, 0x8d8, 0), /* MX51_PAD_EIM_D16__AUD5_TXD */
-	IMX_PIN_REG(MX51_PAD_EIM_D16, 0x3f0, 0x05c, 0, 0x000, 0), /* MX51_PAD_EIM_D16__EIM_D16 */
-	IMX_PIN_REG(MX51_PAD_EIM_D16, 0x3f0, 0x05c, 1, 0x000, 0), /* MX51_PAD_EIM_D16__GPIO2_0 */
-	IMX_PIN_REG(MX51_PAD_EIM_D16, 0x3f0, 0x05c, 4, 0x9b4, 0), /* MX51_PAD_EIM_D16__I2C1_SDA */
-	IMX_PIN_REG(MX51_PAD_EIM_D16, 0x3f0, 0x05c, 3, 0x000, 0), /* MX51_PAD_EIM_D16__UART2_CTS */
-	IMX_PIN_REG(MX51_PAD_EIM_D16, 0x3f0, 0x05c, 2, 0x000, 0), /* MX51_PAD_EIM_D16__USBH2_DATA0 */
-	IMX_PIN_REG(MX51_PAD_EIM_D17, 0x3f4, 0x060, 7, 0x8d4, 0), /* MX51_PAD_EIM_D17__AUD5_RXD */
-	IMX_PIN_REG(MX51_PAD_EIM_D17, 0x3f4, 0x060, 0, 0x000, 0), /* MX51_PAD_EIM_D17__EIM_D17 */
-	IMX_PIN_REG(MX51_PAD_EIM_D17, 0x3f4, 0x060, 1, 0x000, 0), /* MX51_PAD_EIM_D17__GPIO2_1 */
-	IMX_PIN_REG(MX51_PAD_EIM_D17, 0x3f4, 0x060, 3, 0x9ec, 0), /* MX51_PAD_EIM_D17__UART2_RXD */
-	IMX_PIN_REG(MX51_PAD_EIM_D17, 0x3f4, 0x060, 4, 0x000, 0), /* MX51_PAD_EIM_D17__UART3_CTS */
-	IMX_PIN_REG(MX51_PAD_EIM_D17, 0x3f4, 0x060, 2, 0x000, 0), /* MX51_PAD_EIM_D17__USBH2_DATA1 */
-	IMX_PIN_REG(MX51_PAD_EIM_D18, 0x3f8, 0x064, 7, 0x8e4, 0), /* MX51_PAD_EIM_D18__AUD5_TXC */
-	IMX_PIN_REG(MX51_PAD_EIM_D18, 0x3f8, 0x064, 0, 0x000, 0), /* MX51_PAD_EIM_D18__EIM_D18 */
-	IMX_PIN_REG(MX51_PAD_EIM_D18, 0x3f8, 0x064, 1, 0x000, 0), /* MX51_PAD_EIM_D18__GPIO2_2 */
-	IMX_PIN_REG(MX51_PAD_EIM_D18, 0x3f8, 0x064, 3, 0x000, 0), /* MX51_PAD_EIM_D18__UART2_TXD */
-	IMX_PIN_REG(MX51_PAD_EIM_D18, 0x3f8, 0x064, 4, 0x9f0, 1), /* MX51_PAD_EIM_D18__UART3_RTS */
-	IMX_PIN_REG(MX51_PAD_EIM_D18, 0x3f8, 0x064, 2, 0x000, 0), /* MX51_PAD_EIM_D18__USBH2_DATA2 */
-	IMX_PIN_REG(MX51_PAD_EIM_D19, 0x3fc, 0x068, 5, 0x000, 0), /* MX51_PAD_EIM_D19__AUD4_RXC */
-	IMX_PIN_REG(MX51_PAD_EIM_D19, 0x3fc, 0x068, 7, 0x8e8, 0), /* MX51_PAD_EIM_D19__AUD5_TXFS */
-	IMX_PIN_REG(MX51_PAD_EIM_D19, 0x3fc, 0x068, 0, 0x000, 0), /* MX51_PAD_EIM_D19__EIM_D19 */
-	IMX_PIN_REG(MX51_PAD_EIM_D19, 0x3fc, 0x068, 1, 0x000, 0), /* MX51_PAD_EIM_D19__GPIO2_3 */
-	IMX_PIN_REG(MX51_PAD_EIM_D19, 0x3fc, 0x068, 4, 0x9b0, 0), /* MX51_PAD_EIM_D19__I2C1_SCL */
-	IMX_PIN_REG(MX51_PAD_EIM_D19, 0x3fc, 0x068, 3, 0x9e8, 1), /* MX51_PAD_EIM_D19__UART2_RTS */
-	IMX_PIN_REG(MX51_PAD_EIM_D19, 0x3fc, 0x068, 2, 0x000, 0), /* MX51_PAD_EIM_D19__USBH2_DATA3 */
-	IMX_PIN_REG(MX51_PAD_EIM_D20, 0x400, 0x06c, 5, 0x8c8, 0), /* MX51_PAD_EIM_D20__AUD4_TXD */
-	IMX_PIN_REG(MX51_PAD_EIM_D20, 0x400, 0x06c, 0, 0x000, 0), /* MX51_PAD_EIM_D20__EIM_D20 */
-	IMX_PIN_REG(MX51_PAD_EIM_D20, 0x400, 0x06c, 1, 0x000, 0), /* MX51_PAD_EIM_D20__GPIO2_4 */
-	IMX_PIN_REG(MX51_PAD_EIM_D20, 0x400, 0x06c, 4, 0x000, 0), /* MX51_PAD_EIM_D20__SRTC_ALARM_DEB */
-	IMX_PIN_REG(MX51_PAD_EIM_D20, 0x400, 0x06c, 2, 0x000, 0), /* MX51_PAD_EIM_D20__USBH2_DATA4 */
-	IMX_PIN_REG(MX51_PAD_EIM_D21, 0x404, 0x070, 5, 0x8c4, 0), /* MX51_PAD_EIM_D21__AUD4_RXD */
-	IMX_PIN_REG(MX51_PAD_EIM_D21, 0x404, 0x070, 0, 0x000, 0), /* MX51_PAD_EIM_D21__EIM_D21 */
-	IMX_PIN_REG(MX51_PAD_EIM_D21, 0x404, 0x070, 1, 0x000, 0), /* MX51_PAD_EIM_D21__GPIO2_5 */
-	IMX_PIN_REG(MX51_PAD_EIM_D21, 0x404, 0x070, 3, 0x000, 0), /* MX51_PAD_EIM_D21__SRTC_ALARM_DEB */
-	IMX_PIN_REG(MX51_PAD_EIM_D21, 0x404, 0x070, 2, 0x000, 0), /* MX51_PAD_EIM_D21__USBH2_DATA5 */
-	IMX_PIN_REG(MX51_PAD_EIM_D22, 0x408, 0x074, 5, 0x8cc, 0), /* MX51_PAD_EIM_D22__AUD4_TXC */
-	IMX_PIN_REG(MX51_PAD_EIM_D22, 0x408, 0x074, 0, 0x000, 0), /* MX51_PAD_EIM_D22__EIM_D22 */
-	IMX_PIN_REG(MX51_PAD_EIM_D22, 0x408, 0x074, 1, 0x000, 0), /* MX51_PAD_EIM_D22__GPIO2_6 */
-	IMX_PIN_REG(MX51_PAD_EIM_D22, 0x408, 0x074, 2, 0x000, 0), /* MX51_PAD_EIM_D22__USBH2_DATA6 */
-	IMX_PIN_REG(MX51_PAD_EIM_D23, 0x40c, 0x078, 5, 0x8d0, 0), /* MX51_PAD_EIM_D23__AUD4_TXFS */
-	IMX_PIN_REG(MX51_PAD_EIM_D23, 0x40c, 0x078, 0, 0x000, 0), /* MX51_PAD_EIM_D23__EIM_D23 */
-	IMX_PIN_REG(MX51_PAD_EIM_D23, 0x40c, 0x078, 1, 0x000, 0), /* MX51_PAD_EIM_D23__GPIO2_7 */
-	IMX_PIN_REG(MX51_PAD_EIM_D23, 0x40c, 0x078, 4, 0x000, 0), /* MX51_PAD_EIM_D23__SPDIF_OUT1 */
-	IMX_PIN_REG(MX51_PAD_EIM_D23, 0x40c, 0x078, 2, 0x000, 0), /* MX51_PAD_EIM_D23__USBH2_DATA7 */
-	IMX_PIN_REG(MX51_PAD_EIM_D24, 0x410, 0x07c, 5, 0x8f8, 0), /* MX51_PAD_EIM_D24__AUD6_RXFS */
-	IMX_PIN_REG(MX51_PAD_EIM_D24, 0x410, 0x07c, 0, 0x000, 0), /* MX51_PAD_EIM_D24__EIM_D24 */
-	IMX_PIN_REG(MX51_PAD_EIM_D24, 0x410, 0x07c, 1, 0x000, 0), /* MX51_PAD_EIM_D24__GPIO2_8 */
-	IMX_PIN_REG(MX51_PAD_EIM_D24, 0x410, 0x07c, 4, 0x9bc, 0), /* MX51_PAD_EIM_D24__I2C2_SDA */
-	IMX_PIN_REG(MX51_PAD_EIM_D24, 0x410, 0x07c, 3, 0x000, 0), /* MX51_PAD_EIM_D24__UART3_CTS */
-	IMX_PIN_REG(MX51_PAD_EIM_D24, 0x410, 0x07c, 2, 0x000, 0), /* MX51_PAD_EIM_D24__USBOTG_DATA0 */
-	IMX_PIN_REG(MX51_PAD_EIM_D25, 0x414, 0x080, 0, 0x000, 0), /* MX51_PAD_EIM_D25__EIM_D25 */
-	IMX_PIN_REG(MX51_PAD_EIM_D25, 0x414, 0x080, 1, 0x9c8, 0), /* MX51_PAD_EIM_D25__KEY_COL6 */
-	IMX_PIN_REG(MX51_PAD_EIM_D25, 0x414, 0x080, 4, 0x000, 0), /* MX51_PAD_EIM_D25__UART2_CTS */
-	IMX_PIN_REG(MX51_PAD_EIM_D25, 0x414, 0x080, 3, 0x9f4, 0), /* MX51_PAD_EIM_D25__UART3_RXD */
-	IMX_PIN_REG(MX51_PAD_EIM_D25, 0x414, 0x080, 2, 0x000, 0), /* MX51_PAD_EIM_D25__USBOTG_DATA1 */
-	IMX_PIN_REG(MX51_PAD_EIM_D26, 0x418, 0x084, 0, 0x000, 0), /* MX51_PAD_EIM_D26__EIM_D26 */
-	IMX_PIN_REG(MX51_PAD_EIM_D26, 0x418, 0x084, 1, 0x9cc, 0), /* MX51_PAD_EIM_D26__KEY_COL7 */
-	IMX_PIN_REG(MX51_PAD_EIM_D26, 0x418, 0x084, 4, 0x9e8, 3), /* MX51_PAD_EIM_D26__UART2_RTS */
-	IMX_PIN_REG(MX51_PAD_EIM_D26, 0x418, 0x084, 3, 0x000, 0), /* MX51_PAD_EIM_D26__UART3_TXD */
-	IMX_PIN_REG(MX51_PAD_EIM_D26, 0x418, 0x084, 2, 0x000, 0), /* MX51_PAD_EIM_D26__USBOTG_DATA2 */
-	IMX_PIN_REG(MX51_PAD_EIM_D27, 0x41c, 0x088, 5, 0x8f4, 0), /* MX51_PAD_EIM_D27__AUD6_RXC */
-	IMX_PIN_REG(MX51_PAD_EIM_D27, 0x41c, 0x088, 0, 0x000, 0), /* MX51_PAD_EIM_D27__EIM_D27 */
-	IMX_PIN_REG(MX51_PAD_EIM_D27, 0x41c, 0x088, 1, 0x000, 0), /* MX51_PAD_EIM_D27__GPIO2_9 */
-	IMX_PIN_REG(MX51_PAD_EIM_D27, 0x41c, 0x088, 4, 0x9b8, 0), /* MX51_PAD_EIM_D27__I2C2_SCL */
-	IMX_PIN_REG(MX51_PAD_EIM_D27, 0x41c, 0x088, 3, 0x9f0, 3), /* MX51_PAD_EIM_D27__UART3_RTS */
-	IMX_PIN_REG(MX51_PAD_EIM_D27, 0x41c, 0x088, 2, 0x000, 0), /* MX51_PAD_EIM_D27__USBOTG_DATA3 */
-	IMX_PIN_REG(MX51_PAD_EIM_D28, 0x420, 0x08c, 5, 0x8f0, 0), /* MX51_PAD_EIM_D28__AUD6_TXD */
-	IMX_PIN_REG(MX51_PAD_EIM_D28, 0x420, 0x08c, 0, 0x000, 0), /* MX51_PAD_EIM_D28__EIM_D28 */
-	IMX_PIN_REG(MX51_PAD_EIM_D28, 0x420, 0x08c, 1, 0x9d0, 0), /* MX51_PAD_EIM_D28__KEY_ROW4 */
-	IMX_PIN_REG(MX51_PAD_EIM_D28, 0x420, 0x08c, 2, 0x000, 0), /* MX51_PAD_EIM_D28__USBOTG_DATA4 */
-	IMX_PIN_REG(MX51_PAD_EIM_D29, 0x424, 0x090, 5, 0x8ec, 0), /* MX51_PAD_EIM_D29__AUD6_RXD */
-	IMX_PIN_REG(MX51_PAD_EIM_D29, 0x424, 0x090, 0, 0x000, 0), /* MX51_PAD_EIM_D29__EIM_D29 */
-	IMX_PIN_REG(MX51_PAD_EIM_D29, 0x424, 0x090, 1, 0x9d4, 0), /* MX51_PAD_EIM_D29__KEY_ROW5 */
-	IMX_PIN_REG(MX51_PAD_EIM_D29, 0x424, 0x090, 2, 0x000, 0), /* MX51_PAD_EIM_D29__USBOTG_DATA5 */
-	IMX_PIN_REG(MX51_PAD_EIM_D30, 0x428, 0x094, 5, 0x8fc, 0), /* MX51_PAD_EIM_D30__AUD6_TXC */
-	IMX_PIN_REG(MX51_PAD_EIM_D30, 0x428, 0x094, 0, 0x000, 0), /* MX51_PAD_EIM_D30__EIM_D30 */
-	IMX_PIN_REG(MX51_PAD_EIM_D30, 0x428, 0x094, 1, 0x9d8, 0), /* MX51_PAD_EIM_D30__KEY_ROW6 */
-	IMX_PIN_REG(MX51_PAD_EIM_D30, 0x428, 0x094, 2, 0x000, 0), /* MX51_PAD_EIM_D30__USBOTG_DATA6 */
-	IMX_PIN_REG(MX51_PAD_EIM_D31, 0x42c, 0x098, 5, 0x900, 0), /* MX51_PAD_EIM_D31__AUD6_TXFS */
-	IMX_PIN_REG(MX51_PAD_EIM_D31, 0x42c, 0x098, 0, 0x000, 0), /* MX51_PAD_EIM_D31__EIM_D31 */
-	IMX_PIN_REG(MX51_PAD_EIM_D31, 0x42c, 0x098, 1, 0x9dc, 0), /* MX51_PAD_EIM_D31__KEY_ROW7 */
-	IMX_PIN_REG(MX51_PAD_EIM_D31, 0x42c, 0x098, 2, 0x000, 0), /* MX51_PAD_EIM_D31__USBOTG_DATA7 */
-	IMX_PIN_REG(MX51_PAD_EIM_A16, 0x430, 0x09c, 0, 0x000, 0), /* MX51_PAD_EIM_A16__EIM_A16 */
-	IMX_PIN_REG(MX51_PAD_EIM_A16, 0x430, 0x09c, 1, 0x000, 0), /* MX51_PAD_EIM_A16__GPIO2_10 */
-	IMX_PIN_REG(MX51_PAD_EIM_A16, 0x430, 0x09c, 7, 0x000, 0), /* MX51_PAD_EIM_A16__OSC_FREQ_SEL0 */
-	IMX_PIN_REG(MX51_PAD_EIM_A17, 0x434, 0x0a0, 0, 0x000, 0), /* MX51_PAD_EIM_A17__EIM_A17 */
-	IMX_PIN_REG(MX51_PAD_EIM_A17, 0x434, 0x0a0, 1, 0x000, 0), /* MX51_PAD_EIM_A17__GPIO2_11 */
-	IMX_PIN_REG(MX51_PAD_EIM_A17, 0x434, 0x0a0, 7, 0x000, 0), /* MX51_PAD_EIM_A17__OSC_FREQ_SEL1 */
-	IMX_PIN_REG(MX51_PAD_EIM_A18, 0x438, 0x0a4, 7, 0x000, 0), /* MX51_PAD_EIM_A18__BOOT_LPB0 */
-	IMX_PIN_REG(MX51_PAD_EIM_A18, 0x438, 0x0a4, 0, 0x000, 0), /* MX51_PAD_EIM_A18__EIM_A18 */
-	IMX_PIN_REG(MX51_PAD_EIM_A18, 0x438, 0x0a4, 1, 0x000, 0), /* MX51_PAD_EIM_A18__GPIO2_12 */
-	IMX_PIN_REG(MX51_PAD_EIM_A19, 0x43c, 0x0a8, 7, 0x000, 0), /* MX51_PAD_EIM_A19__BOOT_LPB1 */
-	IMX_PIN_REG(MX51_PAD_EIM_A19, 0x43c, 0x0a8, 0, 0x000, 0), /* MX51_PAD_EIM_A19__EIM_A19 */
-	IMX_PIN_REG(MX51_PAD_EIM_A19, 0x43c, 0x0a8, 1, 0x000, 0), /* MX51_PAD_EIM_A19__GPIO2_13 */
-	IMX_PIN_REG(MX51_PAD_EIM_A20, 0x440, 0x0ac, 7, 0x000, 0), /* MX51_PAD_EIM_A20__BOOT_UART_SRC0 */
-	IMX_PIN_REG(MX51_PAD_EIM_A20, 0x440, 0x0ac, 0, 0x000, 0), /* MX51_PAD_EIM_A20__EIM_A20 */
-	IMX_PIN_REG(MX51_PAD_EIM_A20, 0x440, 0x0ac, 1, 0x000, 0), /* MX51_PAD_EIM_A20__GPIO2_14 */
-	IMX_PIN_REG(MX51_PAD_EIM_A21, 0x444, 0x0b0, 7, 0x000, 0), /* MX51_PAD_EIM_A21__BOOT_UART_SRC1 */
-	IMX_PIN_REG(MX51_PAD_EIM_A21, 0x444, 0x0b0, 0, 0x000, 0), /* MX51_PAD_EIM_A21__EIM_A21 */
-	IMX_PIN_REG(MX51_PAD_EIM_A21, 0x444, 0x0b0, 1, 0x000, 0), /* MX51_PAD_EIM_A21__GPIO2_15 */
-	IMX_PIN_REG(MX51_PAD_EIM_A22, 0x448, 0x0b4, 0, 0x000, 0), /* MX51_PAD_EIM_A22__EIM_A22 */
-	IMX_PIN_REG(MX51_PAD_EIM_A22, 0x448, 0x0b4, 1, 0x000, 0), /* MX51_PAD_EIM_A22__GPIO2_16 */
-	IMX_PIN_REG(MX51_PAD_EIM_A23, 0x44c, 0x0b8, 7, 0x000, 0), /* MX51_PAD_EIM_A23__BOOT_HPN_EN */
-	IMX_PIN_REG(MX51_PAD_EIM_A23, 0x44c, 0x0b8, 0, 0x000, 0), /* MX51_PAD_EIM_A23__EIM_A23 */
-	IMX_PIN_REG(MX51_PAD_EIM_A23, 0x44c, 0x0b8, 1, 0x000, 0), /* MX51_PAD_EIM_A23__GPIO2_17 */
-	IMX_PIN_REG(MX51_PAD_EIM_A24, 0x450, 0x0bc, 0, 0x000, 0), /* MX51_PAD_EIM_A24__EIM_A24 */
-	IMX_PIN_REG(MX51_PAD_EIM_A24, 0x450, 0x0bc, 1, 0x000, 0), /* MX51_PAD_EIM_A24__GPIO2_18 */
-	IMX_PIN_REG(MX51_PAD_EIM_A24, 0x450, 0x0bc, 2, 0x000, 0), /* MX51_PAD_EIM_A24__USBH2_CLK */
-	IMX_PIN_REG(MX51_PAD_EIM_A25, 0x454, 0x0c0, 6, 0x000, 0), /* MX51_PAD_EIM_A25__DISP1_PIN4 */
-	IMX_PIN_REG(MX51_PAD_EIM_A25, 0x454, 0x0c0, 0, 0x000, 0), /* MX51_PAD_EIM_A25__EIM_A25 */
-	IMX_PIN_REG(MX51_PAD_EIM_A25, 0x454, 0x0c0, 1, 0x000, 0), /* MX51_PAD_EIM_A25__GPIO2_19 */
-	IMX_PIN_REG(MX51_PAD_EIM_A25, 0x454, 0x0c0, 2, 0x000, 0), /* MX51_PAD_EIM_A25__USBH2_DIR */
-	IMX_PIN_REG(MX51_PAD_EIM_A26, 0x458, 0x0c4, 5, 0x9a0, 0), /* MX51_PAD_EIM_A26__CSI1_DATA_EN */
-	IMX_PIN_REG(MX51_PAD_EIM_A26, 0x458, 0x0c4, 6, 0x908, 0), /* MX51_PAD_EIM_A26__DISP2_EXT_CLK */
-	IMX_PIN_REG(MX51_PAD_EIM_A26, 0x458, 0x0c4, 0, 0x000, 0), /* MX51_PAD_EIM_A26__EIM_A26 */
-	IMX_PIN_REG(MX51_PAD_EIM_A26, 0x458, 0x0c4, 1, 0x000, 0), /* MX51_PAD_EIM_A26__GPIO2_20 */
-	IMX_PIN_REG(MX51_PAD_EIM_A26, 0x458, 0x0c4, 2, 0x000, 0), /* MX51_PAD_EIM_A26__USBH2_STP */
-	IMX_PIN_REG(MX51_PAD_EIM_A27, 0x45c, 0x0c8, 5, 0x99c, 0), /* MX51_PAD_EIM_A27__CSI2_DATA_EN */
-	IMX_PIN_REG(MX51_PAD_EIM_A27, 0x45c, 0x0c8, 6, 0x9a4, 0), /* MX51_PAD_EIM_A27__DISP1_PIN1 */
-	IMX_PIN_REG(MX51_PAD_EIM_A27, 0x45c, 0x0c8, 0, 0x000, 0), /* MX51_PAD_EIM_A27__EIM_A27 */
-	IMX_PIN_REG(MX51_PAD_EIM_A27, 0x45c, 0x0c8, 1, 0x000, 0), /* MX51_PAD_EIM_A27__GPIO2_21 */
-	IMX_PIN_REG(MX51_PAD_EIM_A27, 0x45c, 0x0c8, 2, 0x000, 0), /* MX51_PAD_EIM_A27__USBH2_NXT */
-	IMX_PIN_REG(MX51_PAD_EIM_EB0, 0x460, 0x0cc, 0, 0x000, 0), /* MX51_PAD_EIM_EB0__EIM_EB0 */
-	IMX_PIN_REG(MX51_PAD_EIM_EB1, 0x464, 0x0d0, 0, 0x000, 0), /* MX51_PAD_EIM_EB1__EIM_EB1 */
-	IMX_PIN_REG(MX51_PAD_EIM_EB2, 0x468, 0x0d4, 6, 0x8e0, 0), /* MX51_PAD_EIM_EB2__AUD5_RXFS */
-	IMX_PIN_REG(MX51_PAD_EIM_EB2, 0x468, 0x0d4, 5, 0x000, 0), /* MX51_PAD_EIM_EB2__CSI1_D2 */
-	IMX_PIN_REG(MX51_PAD_EIM_EB2, 0x468, 0x0d4, 0, 0x000, 0), /* MX51_PAD_EIM_EB2__EIM_EB2 */
-	IMX_PIN_REG(MX51_PAD_EIM_EB2, 0x468, 0x0d4, 3, 0x954, 0), /* MX51_PAD_EIM_EB2__FEC_MDIO */
-	IMX_PIN_REG(MX51_PAD_EIM_EB2, 0x468, 0x0d4, 1, 0x000, 0), /* MX51_PAD_EIM_EB2__GPIO2_22 */
-	IMX_PIN_REG(MX51_PAD_EIM_EB2, 0x468, 0x0d4, 7, 0x000, 0), /* MX51_PAD_EIM_EB2__GPT_CMPOUT1 */
-	IMX_PIN_REG(MX51_PAD_EIM_EB3, 0x46c, 0x0d8, 6, 0x8dc, 0), /* MX51_PAD_EIM_EB3__AUD5_RXC */
-	IMX_PIN_REG(MX51_PAD_EIM_EB3, 0x46c, 0x0d8, 5, 0x000, 0), /* MX51_PAD_EIM_EB3__CSI1_D3 */
-	IMX_PIN_REG(MX51_PAD_EIM_EB3, 0x46c, 0x0d8, 0, 0x000, 0), /* MX51_PAD_EIM_EB3__EIM_EB3 */
-	IMX_PIN_REG(MX51_PAD_EIM_EB3, 0x46c, 0x0d8, 3, 0x95c, 0), /* MX51_PAD_EIM_EB3__FEC_RDATA1 */
-	IMX_PIN_REG(MX51_PAD_EIM_EB3, 0x46c, 0x0d8, 1, 0x000, 0), /* MX51_PAD_EIM_EB3__GPIO2_23 */
-	IMX_PIN_REG(MX51_PAD_EIM_EB3, 0x46c, 0x0d8, 7, 0x000, 0), /* MX51_PAD_EIM_EB3__GPT_CMPOUT2 */
-	IMX_PIN_REG(MX51_PAD_EIM_OE, 0x470, 0x0dc, 0, 0x000, 0), /* MX51_PAD_EIM_OE__EIM_OE */
-	IMX_PIN_REG(MX51_PAD_EIM_OE, 0x470, 0x0dc, 1, 0x000, 0), /* MX51_PAD_EIM_OE__GPIO2_24 */
-	IMX_PIN_REG(MX51_PAD_EIM_CS0, 0x474, 0x0e0, 0, 0x000, 0), /* MX51_PAD_EIM_CS0__EIM_CS0 */
-	IMX_PIN_REG(MX51_PAD_EIM_CS0, 0x474, 0x0e0, 1, 0x000, 0), /* MX51_PAD_EIM_CS0__GPIO2_25 */
-	IMX_PIN_REG(MX51_PAD_EIM_CS1, 0x478, 0x0e4, 0, 0x000, 0), /* MX51_PAD_EIM_CS1__EIM_CS1 */
-	IMX_PIN_REG(MX51_PAD_EIM_CS1, 0x478, 0x0e4, 1, 0x000, 0), /* MX51_PAD_EIM_CS1__GPIO2_26 */
-	IMX_PIN_REG(MX51_PAD_EIM_CS2, 0x47c, 0x0e8, 6, 0x8d8, 1), /* MX51_PAD_EIM_CS2__AUD5_TXD */
-	IMX_PIN_REG(MX51_PAD_EIM_CS2, 0x47c, 0x0e8, 5, 0x000, 0), /* MX51_PAD_EIM_CS2__CSI1_D4 */
-	IMX_PIN_REG(MX51_PAD_EIM_CS2, 0x47c, 0x0e8, 0, 0x000, 0), /* MX51_PAD_EIM_CS2__EIM_CS2 */
-	IMX_PIN_REG(MX51_PAD_EIM_CS2, 0x47c, 0x0e8, 3, 0x960, 0), /* MX51_PAD_EIM_CS2__FEC_RDATA2 */
-	IMX_PIN_REG(MX51_PAD_EIM_CS2, 0x47c, 0x0e8, 1, 0x000, 0), /* MX51_PAD_EIM_CS2__GPIO2_27 */
-	IMX_PIN_REG(MX51_PAD_EIM_CS2, 0x47c, 0x0e8, 2, 0x000, 0), /* MX51_PAD_EIM_CS2__USBOTG_STP */
-	IMX_PIN_REG(MX51_PAD_EIM_CS3, 0x480, 0x0ec, 6, 0x8d4, 1), /* MX51_PAD_EIM_CS3__AUD5_RXD */
-	IMX_PIN_REG(MX51_PAD_EIM_CS3, 0x480, 0x0ec, 5, 0x000, 0), /* MX51_PAD_EIM_CS3__CSI1_D5 */
-	IMX_PIN_REG(MX51_PAD_EIM_CS3, 0x480, 0x0ec, 0, 0x000, 0), /* MX51_PAD_EIM_CS3__EIM_CS3 */
-	IMX_PIN_REG(MX51_PAD_EIM_CS3, 0x480, 0x0ec, 3, 0x964, 0), /* MX51_PAD_EIM_CS3__FEC_RDATA3 */
-	IMX_PIN_REG(MX51_PAD_EIM_CS3, 0x480, 0x0ec, 1, 0x000, 0), /* MX51_PAD_EIM_CS3__GPIO2_28 */
-	IMX_PIN_REG(MX51_PAD_EIM_CS3, 0x480, 0x0ec, 2, 0x000, 0), /* MX51_PAD_EIM_CS3__USBOTG_NXT */
-	IMX_PIN_REG(MX51_PAD_EIM_CS4, 0x484, 0x0f0, 6, 0x8e4, 1), /* MX51_PAD_EIM_CS4__AUD5_TXC */
-	IMX_PIN_REG(MX51_PAD_EIM_CS4, 0x484, 0x0f0, 5, 0x000, 0), /* MX51_PAD_EIM_CS4__CSI1_D6 */
-	IMX_PIN_REG(MX51_PAD_EIM_CS4, 0x484, 0x0f0, 0, 0x000, 0), /* MX51_PAD_EIM_CS4__EIM_CS4 */
-	IMX_PIN_REG(MX51_PAD_EIM_CS4, 0x484, 0x0f0, 3, 0x970, 0), /* MX51_PAD_EIM_CS4__FEC_RX_ER */
-	IMX_PIN_REG(MX51_PAD_EIM_CS4, 0x484, 0x0f0, 1, 0x000, 0), /* MX51_PAD_EIM_CS4__GPIO2_29 */
-	IMX_PIN_REG(MX51_PAD_EIM_CS4, 0x484, 0x0f0, 2, 0x000, 0), /* MX51_PAD_EIM_CS4__USBOTG_CLK */
-	IMX_PIN_REG(MX51_PAD_EIM_CS5, 0x488, 0x0f4, 6, 0x8e8, 1), /* MX51_PAD_EIM_CS5__AUD5_TXFS */
-	IMX_PIN_REG(MX51_PAD_EIM_CS5, 0x488, 0x0f4, 5, 0x000, 0), /* MX51_PAD_EIM_CS5__CSI1_D7 */
-	IMX_PIN_REG(MX51_PAD_EIM_CS5, 0x488, 0x0f4, 4, 0x904, 0), /* MX51_PAD_EIM_CS5__DISP1_EXT_CLK */
-	IMX_PIN_REG(MX51_PAD_EIM_CS5, 0x488, 0x0f4, 0, 0x000, 0), /* MX51_PAD_EIM_CS5__EIM_CS5 */
-	IMX_PIN_REG(MX51_PAD_EIM_CS5, 0x488, 0x0f4, 3, 0x950, 0), /* MX51_PAD_EIM_CS5__FEC_CRS */
-	IMX_PIN_REG(MX51_PAD_EIM_CS5, 0x488, 0x0f4, 1, 0x000, 0), /* MX51_PAD_EIM_CS5__GPIO2_30 */
-	IMX_PIN_REG(MX51_PAD_EIM_CS5, 0x488, 0x0f4, 2, 0x000, 0), /* MX51_PAD_EIM_CS5__USBOTG_DIR */
-	IMX_PIN_REG(MX51_PAD_EIM_DTACK, 0x48c, 0x0f8, 0, 0x000, 0), /* MX51_PAD_EIM_DTACK__EIM_DTACK */
-	IMX_PIN_REG(MX51_PAD_EIM_DTACK, 0x48c, 0x0f8, 1, 0x000, 0), /* MX51_PAD_EIM_DTACK__GPIO2_31 */
-	IMX_PIN_REG(MX51_PAD_EIM_LBA, 0x494, 0x0fc, 0, 0x000, 0), /* MX51_PAD_EIM_LBA__EIM_LBA */
-	IMX_PIN_REG(MX51_PAD_EIM_LBA, 0x494, 0x0fc, 1, 0x978, 0), /* MX51_PAD_EIM_LBA__GPIO3_1 */
-	IMX_PIN_REG(MX51_PAD_EIM_CRE, 0x4a0, 0x100, 0, 0x000, 0), /* MX51_PAD_EIM_CRE__EIM_CRE */
-	IMX_PIN_REG(MX51_PAD_EIM_CRE, 0x4a0, 0x100, 1, 0x97c, 0), /* MX51_PAD_EIM_CRE__GPIO3_2 */
-	IMX_PIN_REG(MX51_PAD_DRAM_CS1, 0x4d0, 0x104, 0, 0x000, 0), /* MX51_PAD_DRAM_CS1__DRAM_CS1 */
-	IMX_PIN_REG(MX51_PAD_NANDF_WE_B, 0x4e4, 0x108, 3, 0x980, 0), /* MX51_PAD_NANDF_WE_B__GPIO3_3 */
-	IMX_PIN_REG(MX51_PAD_NANDF_WE_B, 0x4e4, 0x108, 0, 0x000, 0), /* MX51_PAD_NANDF_WE_B__NANDF_WE_B */
-	IMX_PIN_REG(MX51_PAD_NANDF_WE_B, 0x4e4, 0x108, 1, 0x000, 0), /* MX51_PAD_NANDF_WE_B__PATA_DIOW */
-	IMX_PIN_REG(MX51_PAD_NANDF_WE_B, 0x4e4, 0x108, 2, 0x93c, 0), /* MX51_PAD_NANDF_WE_B__SD3_DATA0 */
-	IMX_PIN_REG(MX51_PAD_NANDF_RE_B, 0x4e8, 0x10c, 3, 0x984, 0), /* MX51_PAD_NANDF_RE_B__GPIO3_4 */
-	IMX_PIN_REG(MX51_PAD_NANDF_RE_B, 0x4e8, 0x10c, 0, 0x000, 0), /* MX51_PAD_NANDF_RE_B__NANDF_RE_B */
-	IMX_PIN_REG(MX51_PAD_NANDF_RE_B, 0x4e8, 0x10c, 1, 0x000, 0), /* MX51_PAD_NANDF_RE_B__PATA_DIOR */
-	IMX_PIN_REG(MX51_PAD_NANDF_RE_B, 0x4e8, 0x10c, 2, 0x940, 0), /* MX51_PAD_NANDF_RE_B__SD3_DATA1 */
-	IMX_PIN_REG(MX51_PAD_NANDF_ALE, 0x4ec, 0x110, 3, 0x988, 0), /* MX51_PAD_NANDF_ALE__GPIO3_5 */
-	IMX_PIN_REG(MX51_PAD_NANDF_ALE, 0x4ec, 0x110, 0, 0x000, 0), /* MX51_PAD_NANDF_ALE__NANDF_ALE */
-	IMX_PIN_REG(MX51_PAD_NANDF_ALE, 0x4ec, 0x110, 1, 0x000, 0), /* MX51_PAD_NANDF_ALE__PATA_BUFFER_EN */
-	IMX_PIN_REG(MX51_PAD_NANDF_CLE, 0x4f0, 0x114, 3, 0x98c, 0), /* MX51_PAD_NANDF_CLE__GPIO3_6 */
-	IMX_PIN_REG(MX51_PAD_NANDF_CLE, 0x4f0, 0x114, 0, 0x000, 0), /* MX51_PAD_NANDF_CLE__NANDF_CLE */
-	IMX_PIN_REG(MX51_PAD_NANDF_CLE, 0x4f0, 0x114, 1, 0x000, 0), /* MX51_PAD_NANDF_CLE__PATA_RESET_B */
-	IMX_PIN_REG(MX51_PAD_NANDF_WP_B, 0x4f4, 0x118, 3, 0x990, 0), /* MX51_PAD_NANDF_WP_B__GPIO3_7 */
-	IMX_PIN_REG(MX51_PAD_NANDF_WP_B, 0x4f4, 0x118, 0, 0x000, 0), /* MX51_PAD_NANDF_WP_B__NANDF_WP_B */
-	IMX_PIN_REG(MX51_PAD_NANDF_WP_B, 0x4f4, 0x118, 1, 0x000, 0), /* MX51_PAD_NANDF_WP_B__PATA_DMACK */
-	IMX_PIN_REG(MX51_PAD_NANDF_WP_B, 0x4f4, 0x118, 2, 0x944, 0), /* MX51_PAD_NANDF_WP_B__SD3_DATA2 */
-	IMX_PIN_REG(MX51_PAD_NANDF_RB0, 0x4f8, 0x11c, 5, 0x930, 0), /* MX51_PAD_NANDF_RB0__ECSPI2_SS1 */
-	IMX_PIN_REG(MX51_PAD_NANDF_RB0, 0x4f8, 0x11c, 3, 0x994, 0), /* MX51_PAD_NANDF_RB0__GPIO3_8 */
-	IMX_PIN_REG(MX51_PAD_NANDF_RB0, 0x4f8, 0x11c, 0, 0x000, 0), /* MX51_PAD_NANDF_RB0__NANDF_RB0 */
-	IMX_PIN_REG(MX51_PAD_NANDF_RB0, 0x4f8, 0x11c, 1, 0x000, 0), /* MX51_PAD_NANDF_RB0__PATA_DMARQ */
-	IMX_PIN_REG(MX51_PAD_NANDF_RB0, 0x4f8, 0x11c, 2, 0x948, 0), /* MX51_PAD_NANDF_RB0__SD3_DATA3 */
-	IMX_PIN_REG(MX51_PAD_NANDF_RB1, 0x4fc, 0x120, 6, 0x91c, 0), /* MX51_PAD_NANDF_RB1__CSPI_MOSI */
-	IMX_PIN_REG(MX51_PAD_NANDF_RB1, 0x4fc, 0x120, 2, 0x000, 0), /* MX51_PAD_NANDF_RB1__ECSPI2_RDY */
-	IMX_PIN_REG(MX51_PAD_NANDF_RB1, 0x4fc, 0x120, 3, 0x000, 0), /* MX51_PAD_NANDF_RB1__GPIO3_9 */
-	IMX_PIN_REG(MX51_PAD_NANDF_RB1, 0x4fc, 0x120, 0, 0x000, 0), /* MX51_PAD_NANDF_RB1__NANDF_RB1 */
-	IMX_PIN_REG(MX51_PAD_NANDF_RB1, 0x4fc, 0x120, 1, 0x000, 0), /* MX51_PAD_NANDF_RB1__PATA_IORDY */
-	IMX_PIN_REG(MX51_PAD_NANDF_RB1, 0x4fc, 0x120, 5, 0x000, 0), /* MX51_PAD_NANDF_RB1__SD4_CMD */
-	IMX_PIN_REG(MX51_PAD_NANDF_RB2, 0x500, 0x124, 5, 0x9a8, 0), /* MX51_PAD_NANDF_RB2__DISP2_WAIT */
-	IMX_PIN_REG(MX51_PAD_NANDF_RB2, 0x500, 0x124, 2, 0x000, 0), /* MX51_PAD_NANDF_RB2__ECSPI2_SCLK */
-	IMX_PIN_REG(MX51_PAD_NANDF_RB2, 0x500, 0x124, 1, 0x94c, 0), /* MX51_PAD_NANDF_RB2__FEC_COL */
-	IMX_PIN_REG(MX51_PAD_NANDF_RB2, 0x500, 0x124, 3, 0x000, 0), /* MX51_PAD_NANDF_RB2__GPIO3_10 */
-	IMX_PIN_REG(MX51_PAD_NANDF_RB2, 0x500, 0x124, 0, 0x000, 0), /* MX51_PAD_NANDF_RB2__NANDF_RB2 */
-	IMX_PIN_REG(MX51_PAD_NANDF_RB2, 0x500, 0x124, 7, 0x000, 0), /* MX51_PAD_NANDF_RB2__USBH3_H3_DP */
-	IMX_PIN_REG(MX51_PAD_NANDF_RB2, 0x500, 0x124, 6, 0xa20, 0), /* MX51_PAD_NANDF_RB2__USBH3_NXT */
-	IMX_PIN_REG(MX51_PAD_NANDF_RB3, 0x504, 0x128, 5, 0x000, 0), /* MX51_PAD_NANDF_RB3__DISP1_WAIT */
-	IMX_PIN_REG(MX51_PAD_NANDF_RB3, 0x504, 0x128, 2, 0x000, 0), /* MX51_PAD_NANDF_RB3__ECSPI2_MISO */
-	IMX_PIN_REG(MX51_PAD_NANDF_RB3, 0x504, 0x128, 1, 0x968, 0), /* MX51_PAD_NANDF_RB3__FEC_RX_CLK */
-	IMX_PIN_REG(MX51_PAD_NANDF_RB3, 0x504, 0x128, 3, 0x000, 0), /* MX51_PAD_NANDF_RB3__GPIO3_11 */
-	IMX_PIN_REG(MX51_PAD_NANDF_RB3, 0x504, 0x128, 0, 0x000, 0), /* MX51_PAD_NANDF_RB3__NANDF_RB3 */
-	IMX_PIN_REG(MX51_PAD_NANDF_RB3, 0x504, 0x128, 6, 0x9f8, 0), /* MX51_PAD_NANDF_RB3__USBH3_CLK */
-	IMX_PIN_REG(MX51_PAD_NANDF_RB3, 0x504, 0x128, 7, 0x000, 0), /* MX51_PAD_NANDF_RB3__USBH3_H3_DM */
-	IMX_PIN_REG(MX51_PAD_GPIO_NAND, 0x514, 0x12c, 0, 0x998, 0), /* MX51_PAD_GPIO_NAND__GPIO_NAND */
-	IMX_PIN_REG(MX51_PAD_GPIO_NAND, 0x514, 0x12c, 1, 0x000, 0), /* MX51_PAD_GPIO_NAND__PATA_INTRQ */
-	IMX_PIN_REG(MX51_PAD_NANDF_CS0, 0x518, 0x130, 3, 0x000, 0), /* MX51_PAD_NANDF_CS0__GPIO3_16 */
-	IMX_PIN_REG(MX51_PAD_NANDF_CS0, 0x518, 0x130, 0, 0x000, 0), /* MX51_PAD_NANDF_CS0__NANDF_CS0 */
-	IMX_PIN_REG(MX51_PAD_NANDF_CS1, 0x51c, 0x134, 3, 0x000, 0), /* MX51_PAD_NANDF_CS1__GPIO3_17 */
-	IMX_PIN_REG(MX51_PAD_NANDF_CS1, 0x51c, 0x134, 0, 0x000, 0), /* MX51_PAD_NANDF_CS1__NANDF_CS1 */
-	IMX_PIN_REG(MX51_PAD_NANDF_CS2, 0x520, 0x138, 6, 0x914, 0), /* MX51_PAD_NANDF_CS2__CSPI_SCLK */
-	IMX_PIN_REG(MX51_PAD_NANDF_CS2, 0x520, 0x138, 2, 0x000, 0), /* MX51_PAD_NANDF_CS2__FEC_TX_ER */
-	IMX_PIN_REG(MX51_PAD_NANDF_CS2, 0x520, 0x138, 3, 0x000, 0), /* MX51_PAD_NANDF_CS2__GPIO3_18 */
-	IMX_PIN_REG(MX51_PAD_NANDF_CS2, 0x520, 0x138, 0, 0x000, 0), /* MX51_PAD_NANDF_CS2__NANDF_CS2 */
-	IMX_PIN_REG(MX51_PAD_NANDF_CS2, 0x520, 0x138, 1, 0x000, 0), /* MX51_PAD_NANDF_CS2__PATA_CS_0 */
-	IMX_PIN_REG(MX51_PAD_NANDF_CS2, 0x520, 0x138, 5, 0x000, 0), /* MX51_PAD_NANDF_CS2__SD4_CLK */
-	IMX_PIN_REG(MX51_PAD_NANDF_CS2, 0x520, 0x138, 7, 0x000, 0), /* MX51_PAD_NANDF_CS2__USBH3_H1_DP */
-	IMX_PIN_REG(MX51_PAD_NANDF_CS3, 0x524, 0x13c, 2, 0x000, 0), /* MX51_PAD_NANDF_CS3__FEC_MDC */
-	IMX_PIN_REG(MX51_PAD_NANDF_CS3, 0x524, 0x13c, 3, 0x000, 0), /* MX51_PAD_NANDF_CS3__GPIO3_19 */
-	IMX_PIN_REG(MX51_PAD_NANDF_CS3, 0x524, 0x13c, 0, 0x000, 0), /* MX51_PAD_NANDF_CS3__NANDF_CS3 */
-	IMX_PIN_REG(MX51_PAD_NANDF_CS3, 0x524, 0x13c, 1, 0x000, 0), /* MX51_PAD_NANDF_CS3__PATA_CS_1 */
-	IMX_PIN_REG(MX51_PAD_NANDF_CS3, 0x524, 0x13c, 5, 0x000, 0), /* MX51_PAD_NANDF_CS3__SD4_DAT0 */
-	IMX_PIN_REG(MX51_PAD_NANDF_CS3, 0x524, 0x13c, 7, 0x000, 0), /* MX51_PAD_NANDF_CS3__USBH3_H1_DM */
-	IMX_PIN_REG(MX51_PAD_NANDF_CS4, 0x528, 0x140, 2, 0x000, 0), /* MX51_PAD_NANDF_CS4__FEC_TDATA1 */
-	IMX_PIN_REG(MX51_PAD_NANDF_CS4, 0x528, 0x140, 3, 0x000, 0), /* MX51_PAD_NANDF_CS4__GPIO3_20 */
-	IMX_PIN_REG(MX51_PAD_NANDF_CS4, 0x528, 0x140, 0, 0x000, 0), /* MX51_PAD_NANDF_CS4__NANDF_CS4 */
-	IMX_PIN_REG(MX51_PAD_NANDF_CS4, 0x528, 0x140, 1, 0x000, 0), /* MX51_PAD_NANDF_CS4__PATA_DA_0 */
-	IMX_PIN_REG(MX51_PAD_NANDF_CS4, 0x528, 0x140, 5, 0x000, 0), /* MX51_PAD_NANDF_CS4__SD4_DAT1 */
-	IMX_PIN_REG(MX51_PAD_NANDF_CS4, 0x528, 0x140, 7, 0xa24, 0), /* MX51_PAD_NANDF_CS4__USBH3_STP */
-	IMX_PIN_REG(MX51_PAD_NANDF_CS5, 0x52c, 0x144, 2, 0x000, 0), /* MX51_PAD_NANDF_CS5__FEC_TDATA2 */
-	IMX_PIN_REG(MX51_PAD_NANDF_CS5, 0x52c, 0x144, 3, 0x000, 0), /* MX51_PAD_NANDF_CS5__GPIO3_21 */
-	IMX_PIN_REG(MX51_PAD_NANDF_CS5, 0x52c, 0x144, 0, 0x000, 0), /* MX51_PAD_NANDF_CS5__NANDF_CS5 */
-	IMX_PIN_REG(MX51_PAD_NANDF_CS5, 0x52c, 0x144, 1, 0x000, 0), /* MX51_PAD_NANDF_CS5__PATA_DA_1 */
-	IMX_PIN_REG(MX51_PAD_NANDF_CS5, 0x52c, 0x144, 5, 0x000, 0), /* MX51_PAD_NANDF_CS5__SD4_DAT2 */
-	IMX_PIN_REG(MX51_PAD_NANDF_CS5, 0x52c, 0x144, 7, 0xa1c, 0), /* MX51_PAD_NANDF_CS5__USBH3_DIR */
-	IMX_PIN_REG(MX51_PAD_NANDF_CS6, 0x530, 0x148, 7, 0x928, 0), /* MX51_PAD_NANDF_CS6__CSPI_SS3 */
-	IMX_PIN_REG(MX51_PAD_NANDF_CS6, 0x530, 0x148, 2, 0x000, 0), /* MX51_PAD_NANDF_CS6__FEC_TDATA3 */
-	IMX_PIN_REG(MX51_PAD_NANDF_CS6, 0x530, 0x148, 3, 0x000, 0), /* MX51_PAD_NANDF_CS6__GPIO3_22 */
-	IMX_PIN_REG(MX51_PAD_NANDF_CS6, 0x530, 0x148, 0, 0x000, 0), /* MX51_PAD_NANDF_CS6__NANDF_CS6 */
-	IMX_PIN_REG(MX51_PAD_NANDF_CS6, 0x530, 0x148, 1, 0x000, 0), /* MX51_PAD_NANDF_CS6__PATA_DA_2 */
-	IMX_PIN_REG(MX51_PAD_NANDF_CS6, 0x530, 0x148, 5, 0x000, 0), /* MX51_PAD_NANDF_CS6__SD4_DAT3 */
-	IMX_PIN_REG(MX51_PAD_NANDF_CS7, 0x534, 0x14c, 1, 0x000, 0), /* MX51_PAD_NANDF_CS7__FEC_TX_EN */
-	IMX_PIN_REG(MX51_PAD_NANDF_CS7, 0x534, 0x14c, 3, 0x000, 0), /* MX51_PAD_NANDF_CS7__GPIO3_23 */
-	IMX_PIN_REG(MX51_PAD_NANDF_CS7, 0x534, 0x14c, 0, 0x000, 0), /* MX51_PAD_NANDF_CS7__NANDF_CS7 */
-	IMX_PIN_REG(MX51_PAD_NANDF_CS7, 0x534, 0x14c, 5, 0x000, 0), /* MX51_PAD_NANDF_CS7__SD3_CLK */
-	IMX_PIN_REG(MX51_PAD_NANDF_RDY_INT, 0x538, 0x150, 2, 0x000, 0), /* MX51_PAD_NANDF_RDY_INT__ECSPI2_SS0 */
-	IMX_PIN_REG(MX51_PAD_NANDF_RDY_INT, 0x538, 0x150, 1, 0x974, 0), /* MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK */
-	IMX_PIN_REG(MX51_PAD_NANDF_RDY_INT, 0x538, 0x150, 3, 0x000, 0), /* MX51_PAD_NANDF_RDY_INT__GPIO3_24 */
-	IMX_PIN_REG(MX51_PAD_NANDF_RDY_INT, 0x538, 0x150, 0, 0x938, 0), /* MX51_PAD_NANDF_RDY_INT__NANDF_RDY_INT */
-	IMX_PIN_REG(MX51_PAD_NANDF_RDY_INT, 0x538, 0x150, 5, 0x000, 0), /* MX51_PAD_NANDF_RDY_INT__SD3_CMD */
-	IMX_PIN_REG(MX51_PAD_NANDF_D15, 0x53c, 0x154, 2, 0x000, 0), /* MX51_PAD_NANDF_D15__ECSPI2_MOSI */
-	IMX_PIN_REG(MX51_PAD_NANDF_D15, 0x53c, 0x154, 3, 0x000, 0), /* MX51_PAD_NANDF_D15__GPIO3_25 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D15, 0x53c, 0x154, 0, 0x000, 0), /* MX51_PAD_NANDF_D15__NANDF_D15 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D15, 0x53c, 0x154, 1, 0x000, 0), /* MX51_PAD_NANDF_D15__PATA_DATA15 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D15, 0x53c, 0x154, 5, 0x000, 0), /* MX51_PAD_NANDF_D15__SD3_DAT7 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D14, 0x540, 0x158, 2, 0x934, 0), /* MX51_PAD_NANDF_D14__ECSPI2_SS3 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D14, 0x540, 0x158, 3, 0x000, 0), /* MX51_PAD_NANDF_D14__GPIO3_26 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D14, 0x540, 0x158, 0, 0x000, 0), /* MX51_PAD_NANDF_D14__NANDF_D14 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D14, 0x540, 0x158, 1, 0x000, 0), /* MX51_PAD_NANDF_D14__PATA_DATA14 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D14, 0x540, 0x158, 5, 0x000, 0), /* MX51_PAD_NANDF_D14__SD3_DAT6 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D13, 0x544, 0x15c, 2, 0x000, 0), /* MX51_PAD_NANDF_D13__ECSPI2_SS2 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D13, 0x544, 0x15c, 3, 0x000, 0), /* MX51_PAD_NANDF_D13__GPIO3_27 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D13, 0x544, 0x15c, 0, 0x000, 0), /* MX51_PAD_NANDF_D13__NANDF_D13 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D13, 0x544, 0x15c, 1, 0x000, 0), /* MX51_PAD_NANDF_D13__PATA_DATA13 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D13, 0x544, 0x15c, 5, 0x000, 0), /* MX51_PAD_NANDF_D13__SD3_DAT5 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D12, 0x548, 0x160, 2, 0x930, 1), /* MX51_PAD_NANDF_D12__ECSPI2_SS1 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D12, 0x548, 0x160, 3, 0x000, 0), /* MX51_PAD_NANDF_D12__GPIO3_28 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D12, 0x548, 0x160, 0, 0x000, 0), /* MX51_PAD_NANDF_D12__NANDF_D12 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D12, 0x548, 0x160, 1, 0x000, 0), /* MX51_PAD_NANDF_D12__PATA_DATA12 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D12, 0x548, 0x160, 5, 0x000, 0), /* MX51_PAD_NANDF_D12__SD3_DAT4 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D11, 0x54c, 0x164, 2, 0x96c, 0), /* MX51_PAD_NANDF_D11__FEC_RX_DV */
-	IMX_PIN_REG(MX51_PAD_NANDF_D11, 0x54c, 0x164, 3, 0x000, 0), /* MX51_PAD_NANDF_D11__GPIO3_29 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D11, 0x54c, 0x164, 0, 0x000, 0), /* MX51_PAD_NANDF_D11__NANDF_D11 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D11, 0x54c, 0x164, 1, 0x000, 0), /* MX51_PAD_NANDF_D11__PATA_DATA11 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D11, 0x54c, 0x164, 5, 0x948, 1), /* MX51_PAD_NANDF_D11__SD3_DATA3 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D10, 0x550, 0x168, 3, 0x000, 0), /* MX51_PAD_NANDF_D10__GPIO3_30 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D10, 0x550, 0x168, 0, 0x000, 0), /* MX51_PAD_NANDF_D10__NANDF_D10 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D10, 0x550, 0x168, 1, 0x000, 0), /* MX51_PAD_NANDF_D10__PATA_DATA10 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D10, 0x550, 0x168, 5, 0x944, 1), /* MX51_PAD_NANDF_D10__SD3_DATA2 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D9, 0x554, 0x16c, 2, 0x958, 0), /* MX51_PAD_NANDF_D9__FEC_RDATA0 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D9, 0x554, 0x16c, 3, 0x000, 0), /* MX51_PAD_NANDF_D9__GPIO3_31 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D9, 0x554, 0x16c, 0, 0x000, 0), /* MX51_PAD_NANDF_D9__NANDF_D9 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D9, 0x554, 0x16c, 1, 0x000, 0), /* MX51_PAD_NANDF_D9__PATA_DATA9 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D9, 0x554, 0x16c, 5, 0x940, 1), /* MX51_PAD_NANDF_D9__SD3_DATA1 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D8, 0x558, 0x170, 2, 0x000, 0), /* MX51_PAD_NANDF_D8__FEC_TDATA0 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D8, 0x558, 0x170, 3, 0x000, 0), /* MX51_PAD_NANDF_D8__GPIO4_0 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D8, 0x558, 0x170, 0, 0x000, 0), /* MX51_PAD_NANDF_D8__NANDF_D8 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D8, 0x558, 0x170, 1, 0x000, 0), /* MX51_PAD_NANDF_D8__PATA_DATA8 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D8, 0x558, 0x170, 5, 0x93c, 1), /* MX51_PAD_NANDF_D8__SD3_DATA0 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D7, 0x55c, 0x174, 3, 0x000, 0), /* MX51_PAD_NANDF_D7__GPIO4_1 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D7, 0x55c, 0x174, 0, 0x000, 0), /* MX51_PAD_NANDF_D7__NANDF_D7 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D7, 0x55c, 0x174, 1, 0x000, 0), /* MX51_PAD_NANDF_D7__PATA_DATA7 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D7, 0x55c, 0x174, 5, 0x9fc, 0), /* MX51_PAD_NANDF_D7__USBH3_DATA0 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D6, 0x560, 0x178, 3, 0x000, 0), /* MX51_PAD_NANDF_D6__GPIO4_2 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D6, 0x560, 0x178, 0, 0x000, 0), /* MX51_PAD_NANDF_D6__NANDF_D6 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D6, 0x560, 0x178, 1, 0x000, 0), /* MX51_PAD_NANDF_D6__PATA_DATA6 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D6, 0x560, 0x178, 2, 0x000, 0), /* MX51_PAD_NANDF_D6__SD4_LCTL */
-	IMX_PIN_REG(MX51_PAD_NANDF_D6, 0x560, 0x178, 5, 0xa00, 0), /* MX51_PAD_NANDF_D6__USBH3_DATA1 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D5, 0x564, 0x17c, 3, 0x000, 0), /* MX51_PAD_NANDF_D5__GPIO4_3 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D5, 0x564, 0x17c, 0, 0x000, 0), /* MX51_PAD_NANDF_D5__NANDF_D5 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D5, 0x564, 0x17c, 1, 0x000, 0), /* MX51_PAD_NANDF_D5__PATA_DATA5 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D5, 0x564, 0x17c, 2, 0x000, 0), /* MX51_PAD_NANDF_D5__SD4_WP */
-	IMX_PIN_REG(MX51_PAD_NANDF_D5, 0x564, 0x17c, 5, 0xa04, 0), /* MX51_PAD_NANDF_D5__USBH3_DATA2 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D4, 0x568, 0x180, 3, 0x000, 0), /* MX51_PAD_NANDF_D4__GPIO4_4 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D4, 0x568, 0x180, 0, 0x000, 0), /* MX51_PAD_NANDF_D4__NANDF_D4 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D4, 0x568, 0x180, 1, 0x000, 0), /* MX51_PAD_NANDF_D4__PATA_DATA4 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D4, 0x568, 0x180, 2, 0x000, 0), /* MX51_PAD_NANDF_D4__SD4_CD */
-	IMX_PIN_REG(MX51_PAD_NANDF_D4, 0x568, 0x180, 5, 0xa08, 0), /* MX51_PAD_NANDF_D4__USBH3_DATA3 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D3, 0x56c, 0x184, 3, 0x000, 0), /* MX51_PAD_NANDF_D3__GPIO4_5 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D3, 0x56c, 0x184, 0, 0x000, 0), /* MX51_PAD_NANDF_D3__NANDF_D3 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D3, 0x56c, 0x184, 1, 0x000, 0), /* MX51_PAD_NANDF_D3__PATA_DATA3 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D3, 0x56c, 0x184, 2, 0x000, 0), /* MX51_PAD_NANDF_D3__SD4_DAT4 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D3, 0x56c, 0x184, 5, 0xa0c, 0), /* MX51_PAD_NANDF_D3__USBH3_DATA4 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D2, 0x570, 0x188, 3, 0x000, 0), /* MX51_PAD_NANDF_D2__GPIO4_6 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D2, 0x570, 0x188, 0, 0x000, 0), /* MX51_PAD_NANDF_D2__NANDF_D2 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D2, 0x570, 0x188, 1, 0x000, 0), /* MX51_PAD_NANDF_D2__PATA_DATA2 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D2, 0x570, 0x188, 2, 0x000, 0), /* MX51_PAD_NANDF_D2__SD4_DAT5 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D2, 0x570, 0x188, 5, 0xa10, 0), /* MX51_PAD_NANDF_D2__USBH3_DATA5 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D1, 0x574, 0x18c, 3, 0x000, 0), /* MX51_PAD_NANDF_D1__GPIO4_7 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D1, 0x574, 0x18c, 0, 0x000, 0), /* MX51_PAD_NANDF_D1__NANDF_D1 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D1, 0x574, 0x18c, 1, 0x000, 0), /* MX51_PAD_NANDF_D1__PATA_DATA1 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D1, 0x574, 0x18c, 2, 0x000, 0), /* MX51_PAD_NANDF_D1__SD4_DAT6 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D1, 0x574, 0x18c, 5, 0xa14, 0), /* MX51_PAD_NANDF_D1__USBH3_DATA6 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D0, 0x578, 0x190, 3, 0x000, 0), /* MX51_PAD_NANDF_D0__GPIO4_8 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D0, 0x578, 0x190, 0, 0x000, 0), /* MX51_PAD_NANDF_D0__NANDF_D0 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D0, 0x578, 0x190, 1, 0x000, 0), /* MX51_PAD_NANDF_D0__PATA_DATA0 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D0, 0x578, 0x190, 2, 0x000, 0), /* MX51_PAD_NANDF_D0__SD4_DAT7 */
-	IMX_PIN_REG(MX51_PAD_NANDF_D0, 0x578, 0x190, 5, 0xa18, 0), /* MX51_PAD_NANDF_D0__USBH3_DATA7 */
-	IMX_PIN_REG(MX51_PAD_CSI1_D8, 0x57c, 0x194, 0, 0x000, 0), /* MX51_PAD_CSI1_D8__CSI1_D8 */
-	IMX_PIN_REG(MX51_PAD_CSI1_D8, 0x57c, 0x194, 3, 0x998, 1), /* MX51_PAD_CSI1_D8__GPIO3_12 */
-	IMX_PIN_REG(MX51_PAD_CSI1_D9, 0x580, 0x198, 0, 0x000, 0), /* MX51_PAD_CSI1_D9__CSI1_D9 */
-	IMX_PIN_REG(MX51_PAD_CSI1_D9, 0x580, 0x198, 3, 0x000, 0), /* MX51_PAD_CSI1_D9__GPIO3_13 */
-	IMX_PIN_REG(MX51_PAD_CSI1_D10, 0x584, 0x19c, 0, 0x000, 0), /* MX51_PAD_CSI1_D10__CSI1_D10 */
-	IMX_PIN_REG(MX51_PAD_CSI1_D11, 0x588, 0x1a0, 0, 0x000, 0), /* MX51_PAD_CSI1_D11__CSI1_D11 */
-	IMX_PIN_REG(MX51_PAD_CSI1_D12, 0x58c, 0x1a4, 0, 0x000, 0), /* MX51_PAD_CSI1_D12__CSI1_D12 */
-	IMX_PIN_REG(MX51_PAD_CSI1_D13, 0x590, 0x1a8, 0, 0x000, 0), /* MX51_PAD_CSI1_D13__CSI1_D13 */
-	IMX_PIN_REG(MX51_PAD_CSI1_D14, 0x594, 0x1ac, 0, 0x000, 0), /* MX51_PAD_CSI1_D14__CSI1_D14 */
-	IMX_PIN_REG(MX51_PAD_CSI1_D15, 0x598, 0x1b0, 0, 0x000, 0), /* MX51_PAD_CSI1_D15__CSI1_D15 */
-	IMX_PIN_REG(MX51_PAD_CSI1_D16, 0x59c, 0x1b4, 0, 0x000, 0), /* MX51_PAD_CSI1_D16__CSI1_D16 */
-	IMX_PIN_REG(MX51_PAD_CSI1_D17, 0x5a0, 0x1b8, 0, 0x000, 0), /* MX51_PAD_CSI1_D17__CSI1_D17 */
-	IMX_PIN_REG(MX51_PAD_CSI1_D18, 0x5a4, 0x1bc, 0, 0x000, 0), /* MX51_PAD_CSI1_D18__CSI1_D18 */
-	IMX_PIN_REG(MX51_PAD_CSI1_D19, 0x5a8, 0x1c0, 0, 0x000, 0), /* MX51_PAD_CSI1_D19__CSI1_D19 */
-	IMX_PIN_REG(MX51_PAD_CSI1_VSYNC, 0x5ac, 0x1c4, 0, 0x000, 0), /* MX51_PAD_CSI1_VSYNC__CSI1_VSYNC */
-	IMX_PIN_REG(MX51_PAD_CSI1_VSYNC, 0x5ac, 0x1c4, 3, 0x000, 0), /* MX51_PAD_CSI1_VSYNC__GPIO3_14 */
-	IMX_PIN_REG(MX51_PAD_CSI1_HSYNC, 0x5b0, 0x1c8, 0, 0x000, 0), /* MX51_PAD_CSI1_HSYNC__CSI1_HSYNC */
-	IMX_PIN_REG(MX51_PAD_CSI1_HSYNC, 0x5b0, 0x1c8, 3, 0x000, 0), /* MX51_PAD_CSI1_HSYNC__GPIO3_15 */
-	IMX_PIN_REG(MX51_PAD_CSI1_PIXCLK, 0x5b4, NO_MUX, 0, 0x000, 0), /* MX51_PAD_CSI1_PIXCLK__CSI1_PIXCLK */
-	IMX_PIN_REG(MX51_PAD_CSI1_MCLK, 0x5b8, NO_MUX, 0, 0x000, 0), /* MX51_PAD_CSI1_MCLK__CSI1_MCLK */
-	IMX_PIN_REG(MX51_PAD_CSI2_D12, 0x5bc, 0x1cc, 0, 0x000, 0), /* MX51_PAD_CSI2_D12__CSI2_D12 */
-	IMX_PIN_REG(MX51_PAD_CSI2_D12, 0x5bc, 0x1cc, 3, 0x000, 0), /* MX51_PAD_CSI2_D12__GPIO4_9 */
-	IMX_PIN_REG(MX51_PAD_CSI2_D13, 0x5c0, 0x1d0, 0, 0x000, 0), /* MX51_PAD_CSI2_D13__CSI2_D13 */
-	IMX_PIN_REG(MX51_PAD_CSI2_D13, 0x5c0, 0x1d0, 3, 0x000, 0), /* MX51_PAD_CSI2_D13__GPIO4_10 */
-	IMX_PIN_REG(MX51_PAD_CSI2_D14, 0x5c4, 0x1d4, 0, 0x000, 0), /* MX51_PAD_CSI2_D14__CSI2_D14 */
-	IMX_PIN_REG(MX51_PAD_CSI2_D15, 0x5c8, 0x1d8, 0, 0x000, 0), /* MX51_PAD_CSI2_D15__CSI2_D15 */
-	IMX_PIN_REG(MX51_PAD_CSI2_D16, 0x5cc, 0x1dc, 0, 0x000, 0), /* MX51_PAD_CSI2_D16__CSI2_D16 */
-	IMX_PIN_REG(MX51_PAD_CSI2_D17, 0x5d0, 0x1e0, 0, 0x000, 0), /* MX51_PAD_CSI2_D17__CSI2_D17 */
-	IMX_PIN_REG(MX51_PAD_CSI2_D18, 0x5d4, 0x1e4, 0, 0x000, 0), /* MX51_PAD_CSI2_D18__CSI2_D18 */
-	IMX_PIN_REG(MX51_PAD_CSI2_D18, 0x5d4, 0x1e4, 3, 0x000, 0), /* MX51_PAD_CSI2_D18__GPIO4_11 */
-	IMX_PIN_REG(MX51_PAD_CSI2_D19, 0x5d8, 0x1e8, 0, 0x000, 0), /* MX51_PAD_CSI2_D19__CSI2_D19 */
-	IMX_PIN_REG(MX51_PAD_CSI2_D19, 0x5d8, 0x1e8, 3, 0x000, 0), /* MX51_PAD_CSI2_D19__GPIO4_12 */
-	IMX_PIN_REG(MX51_PAD_CSI2_VSYNC, 0x5dc, 0x1ec, 0, 0x000, 0), /* MX51_PAD_CSI2_VSYNC__CSI2_VSYNC */
-	IMX_PIN_REG(MX51_PAD_CSI2_VSYNC, 0x5dc, 0x1ec, 3, 0x000, 0), /* MX51_PAD_CSI2_VSYNC__GPIO4_13 */
-	IMX_PIN_REG(MX51_PAD_CSI2_HSYNC, 0x5e0, 0x1f0, 0, 0x000, 0), /* MX51_PAD_CSI2_HSYNC__CSI2_HSYNC */
-	IMX_PIN_REG(MX51_PAD_CSI2_HSYNC, 0x5e0, 0x1f0, 3, 0x000, 0), /* MX51_PAD_CSI2_HSYNC__GPIO4_14 */
-	IMX_PIN_REG(MX51_PAD_CSI2_PIXCLK, 0x5e4, 0x1f4, 0, 0x000, 0), /* MX51_PAD_CSI2_PIXCLK__CSI2_PIXCLK */
-	IMX_PIN_REG(MX51_PAD_CSI2_PIXCLK, 0x5e4, 0x1f4, 3, 0x000, 0), /* MX51_PAD_CSI2_PIXCLK__GPIO4_15 */
-	IMX_PIN_REG(MX51_PAD_I2C1_CLK, 0x5e8, 0x1f8, 3, 0x000, 0), /* MX51_PAD_I2C1_CLK__GPIO4_16 */
-	IMX_PIN_REG(MX51_PAD_I2C1_CLK, 0x5e8, 0x1f8, 0, 0x000, 0), /* MX51_PAD_I2C1_CLK__I2C1_CLK */
-	IMX_PIN_REG(MX51_PAD_I2C1_DAT, 0x5ec, 0x1fc, 3, 0x000, 0), /* MX51_PAD_I2C1_DAT__GPIO4_17 */
-	IMX_PIN_REG(MX51_PAD_I2C1_DAT, 0x5ec, 0x1fc, 0, 0x000, 0), /* MX51_PAD_I2C1_DAT__I2C1_DAT */
-	IMX_PIN_REG(MX51_PAD_AUD3_BB_TXD, 0x5f0, 0x200, 0, 0x000, 0), /* MX51_PAD_AUD3_BB_TXD__AUD3_TXD */
-	IMX_PIN_REG(MX51_PAD_AUD3_BB_TXD, 0x5f0, 0x200, 3, 0x000, 0), /* MX51_PAD_AUD3_BB_TXD__GPIO4_18 */
-	IMX_PIN_REG(MX51_PAD_AUD3_BB_RXD, 0x5f4, 0x204, 0, 0x000, 0), /* MX51_PAD_AUD3_BB_RXD__AUD3_RXD */
-	IMX_PIN_REG(MX51_PAD_AUD3_BB_RXD, 0x5f4, 0x204, 3, 0x000, 0), /* MX51_PAD_AUD3_BB_RXD__GPIO4_19 */
-	IMX_PIN_REG(MX51_PAD_AUD3_BB_RXD, 0x5f4, 0x204, 1, 0x9f4, 2), /* MX51_PAD_AUD3_BB_RXD__UART3_RXD */
-	IMX_PIN_REG(MX51_PAD_AUD3_BB_CK, 0x5f8, 0x208, 0, 0x000, 0), /* MX51_PAD_AUD3_BB_CK__AUD3_TXC */
-	IMX_PIN_REG(MX51_PAD_AUD3_BB_CK, 0x5f8, 0x208, 3, 0x000, 0), /* MX51_PAD_AUD3_BB_CK__GPIO4_20 */
-	IMX_PIN_REG(MX51_PAD_AUD3_BB_FS, 0x5fc, 0x20c, 0, 0x000, 0), /* MX51_PAD_AUD3_BB_FS__AUD3_TXFS */
-	IMX_PIN_REG(MX51_PAD_AUD3_BB_FS, 0x5fc, 0x20c, 3, 0x000, 0), /* MX51_PAD_AUD3_BB_FS__GPIO4_21 */
-	IMX_PIN_REG(MX51_PAD_AUD3_BB_FS, 0x5fc, 0x20c, 1, 0x000, 0), /* MX51_PAD_AUD3_BB_FS__UART3_TXD */
-	IMX_PIN_REG(MX51_PAD_CSPI1_MOSI, 0x600, 0x210, 0, 0x000, 0), /* MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI */
-	IMX_PIN_REG(MX51_PAD_CSPI1_MOSI, 0x600, 0x210, 3, 0x000, 0), /* MX51_PAD_CSPI1_MOSI__GPIO4_22 */
-	IMX_PIN_REG(MX51_PAD_CSPI1_MOSI, 0x600, 0x210, 1, 0x9b4, 1), /* MX51_PAD_CSPI1_MOSI__I2C1_SDA */
-	IMX_PIN_REG(MX51_PAD_CSPI1_MISO, 0x604, 0x214, 1, 0x8c4, 1), /* MX51_PAD_CSPI1_MISO__AUD4_RXD */
-	IMX_PIN_REG(MX51_PAD_CSPI1_MISO, 0x604, 0x214, 0, 0x000, 0), /* MX51_PAD_CSPI1_MISO__ECSPI1_MISO */
-	IMX_PIN_REG(MX51_PAD_CSPI1_MISO, 0x604, 0x214, 3, 0x000, 0), /* MX51_PAD_CSPI1_MISO__GPIO4_23 */
-	IMX_PIN_REG(MX51_PAD_CSPI1_SS0, 0x608, 0x218, 1, 0x8cc, 1), /* MX51_PAD_CSPI1_SS0__AUD4_TXC */
-	IMX_PIN_REG(MX51_PAD_CSPI1_SS0, 0x608, 0x218, 0, 0x000, 0), /* MX51_PAD_CSPI1_SS0__ECSPI1_SS0 */
-	IMX_PIN_REG(MX51_PAD_CSPI1_SS0, 0x608, 0x218, 3, 0x000, 0), /* MX51_PAD_CSPI1_SS0__GPIO4_24 */
-	IMX_PIN_REG(MX51_PAD_CSPI1_SS1, 0x60c, 0x21c, 1, 0x8c8, 1), /* MX51_PAD_CSPI1_SS1__AUD4_TXD */
-	IMX_PIN_REG(MX51_PAD_CSPI1_SS1, 0x60c, 0x21c, 0, 0x000, 0), /* MX51_PAD_CSPI1_SS1__ECSPI1_SS1 */
-	IMX_PIN_REG(MX51_PAD_CSPI1_SS1, 0x60c, 0x21c, 3, 0x000, 0), /* MX51_PAD_CSPI1_SS1__GPIO4_25 */
-	IMX_PIN_REG(MX51_PAD_CSPI1_RDY, 0x610, 0x220, 1, 0x8d0, 1), /* MX51_PAD_CSPI1_RDY__AUD4_TXFS */
-	IMX_PIN_REG(MX51_PAD_CSPI1_RDY, 0x610, 0x220, 0, 0x000, 0), /* MX51_PAD_CSPI1_RDY__ECSPI1_RDY */
-	IMX_PIN_REG(MX51_PAD_CSPI1_RDY, 0x610, 0x220, 3, 0x000, 0), /* MX51_PAD_CSPI1_RDY__GPIO4_26 */
-	IMX_PIN_REG(MX51_PAD_CSPI1_SCLK, 0x614, 0x224, 0, 0x000, 0), /* MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK */
-	IMX_PIN_REG(MX51_PAD_CSPI1_SCLK, 0x614, 0x224, 3, 0x000, 0), /* MX51_PAD_CSPI1_SCLK__GPIO4_27 */
-	IMX_PIN_REG(MX51_PAD_CSPI1_SCLK, 0x614, 0x224, 1, 0x9b0, 1), /* MX51_PAD_CSPI1_SCLK__I2C1_SCL */
-	IMX_PIN_REG(MX51_PAD_UART1_RXD, 0x618, 0x228, 3, 0x000, 0), /* MX51_PAD_UART1_RXD__GPIO4_28 */
-	IMX_PIN_REG(MX51_PAD_UART1_RXD, 0x618, 0x228, 0, 0x9e4, 0), /* MX51_PAD_UART1_RXD__UART1_RXD */
-	IMX_PIN_REG(MX51_PAD_UART1_TXD, 0x61c, 0x22c, 3, 0x000, 0), /* MX51_PAD_UART1_TXD__GPIO4_29 */
-	IMX_PIN_REG(MX51_PAD_UART1_TXD, 0x61c, 0x22c, 1, 0x000, 0), /* MX51_PAD_UART1_TXD__PWM2_PWMO */
-	IMX_PIN_REG(MX51_PAD_UART1_TXD, 0x61c, 0x22c, 0, 0x000, 0), /* MX51_PAD_UART1_TXD__UART1_TXD */
-	IMX_PIN_REG(MX51_PAD_UART1_RTS, 0x620, 0x230, 3, 0x000, 0), /* MX51_PAD_UART1_RTS__GPIO4_30 */
-	IMX_PIN_REG(MX51_PAD_UART1_RTS, 0x620, 0x230, 0, 0x9e0, 0), /* MX51_PAD_UART1_RTS__UART1_RTS */
-	IMX_PIN_REG(MX51_PAD_UART1_CTS, 0x624, 0x234, 3, 0x000, 0), /* MX51_PAD_UART1_CTS__GPIO4_31 */
-	IMX_PIN_REG(MX51_PAD_UART1_CTS, 0x624, 0x234, 0, 0x000, 0), /* MX51_PAD_UART1_CTS__UART1_CTS */
-	IMX_PIN_REG(MX51_PAD_UART2_RXD, 0x628, 0x238, 1, 0x000, 0), /* MX51_PAD_UART2_RXD__FIRI_TXD */
-	IMX_PIN_REG(MX51_PAD_UART2_RXD, 0x628, 0x238, 3, 0x000, 0), /* MX51_PAD_UART2_RXD__GPIO1_20 */
-	IMX_PIN_REG(MX51_PAD_UART2_RXD, 0x628, 0x238, 0, 0x9ec, 2), /* MX51_PAD_UART2_RXD__UART2_RXD */
-	IMX_PIN_REG(MX51_PAD_UART2_TXD, 0x62c, 0x23c, 1, 0x000, 0), /* MX51_PAD_UART2_TXD__FIRI_RXD */
-	IMX_PIN_REG(MX51_PAD_UART2_TXD, 0x62c, 0x23c, 3, 0x000, 0), /* MX51_PAD_UART2_TXD__GPIO1_21 */
-	IMX_PIN_REG(MX51_PAD_UART2_TXD, 0x62c, 0x23c, 0, 0x000, 0), /* MX51_PAD_UART2_TXD__UART2_TXD */
-	IMX_PIN_REG(MX51_PAD_UART3_RXD, 0x630, 0x240, 2, 0x000, 0), /* MX51_PAD_UART3_RXD__CSI1_D0 */
-	IMX_PIN_REG(MX51_PAD_UART3_RXD, 0x630, 0x240, 3, 0x000, 0), /* MX51_PAD_UART3_RXD__GPIO1_22 */
-	IMX_PIN_REG(MX51_PAD_UART3_RXD, 0x630, 0x240, 0, 0x000, 0), /* MX51_PAD_UART3_RXD__UART1_DTR */
-	IMX_PIN_REG(MX51_PAD_UART3_RXD, 0x630, 0x240, 1, 0x9f4, 4), /* MX51_PAD_UART3_RXD__UART3_RXD */
-	IMX_PIN_REG(MX51_PAD_UART3_TXD, 0x634, 0x244, 2, 0x000, 0), /* MX51_PAD_UART3_TXD__CSI1_D1 */
-	IMX_PIN_REG(MX51_PAD_UART3_TXD, 0x634, 0x244, 3, 0x000, 0), /* MX51_PAD_UART3_TXD__GPIO1_23 */
-	IMX_PIN_REG(MX51_PAD_UART3_TXD, 0x634, 0x244, 0, 0x000, 0), /* MX51_PAD_UART3_TXD__UART1_DSR */
-	IMX_PIN_REG(MX51_PAD_UART3_TXD, 0x634, 0x244, 1, 0x000, 0), /* MX51_PAD_UART3_TXD__UART3_TXD */
-	IMX_PIN_REG(MX51_PAD_OWIRE_LINE, 0x638, 0x248, 3, 0x000, 0), /* MX51_PAD_OWIRE_LINE__GPIO1_24 */
-	IMX_PIN_REG(MX51_PAD_OWIRE_LINE, 0x638, 0x248, 0, 0x000, 0), /* MX51_PAD_OWIRE_LINE__OWIRE_LINE */
-	IMX_PIN_REG(MX51_PAD_OWIRE_LINE, 0x638, 0x248, 6, 0x000, 0), /* MX51_PAD_OWIRE_LINE__SPDIF_OUT */
-	IMX_PIN_REG(MX51_PAD_KEY_ROW0, 0x63c, 0x24c, 0, 0x000, 0), /* MX51_PAD_KEY_ROW0__KEY_ROW0 */
-	IMX_PIN_REG(MX51_PAD_KEY_ROW1, 0x640, 0x250, 0, 0x000, 0), /* MX51_PAD_KEY_ROW1__KEY_ROW1 */
-	IMX_PIN_REG(MX51_PAD_KEY_ROW2, 0x644, 0x254, 0, 0x000, 0), /* MX51_PAD_KEY_ROW2__KEY_ROW2 */
-	IMX_PIN_REG(MX51_PAD_KEY_ROW3, 0x648, 0x258, 0, 0x000, 0), /* MX51_PAD_KEY_ROW3__KEY_ROW3 */
-	IMX_PIN_REG(MX51_PAD_KEY_COL0, 0x64c, 0x25c, 0, 0x000, 0), /* MX51_PAD_KEY_COL0__KEY_COL0 */
-	IMX_PIN_REG(MX51_PAD_KEY_COL0, 0x64c, 0x25c, 7, 0x90c, 0), /* MX51_PAD_KEY_COL0__PLL1_BYP */
-	IMX_PIN_REG(MX51_PAD_KEY_COL1, 0x650, 0x260, 0, 0x000, 0), /* MX51_PAD_KEY_COL1__KEY_COL1 */
-	IMX_PIN_REG(MX51_PAD_KEY_COL1, 0x650, 0x260, 7, 0x910, 0), /* MX51_PAD_KEY_COL1__PLL2_BYP */
-	IMX_PIN_REG(MX51_PAD_KEY_COL2, 0x654, 0x264, 0, 0x000, 0), /* MX51_PAD_KEY_COL2__KEY_COL2 */
-	IMX_PIN_REG(MX51_PAD_KEY_COL2, 0x654, 0x264, 7, 0x000, 0), /* MX51_PAD_KEY_COL2__PLL3_BYP */
-	IMX_PIN_REG(MX51_PAD_KEY_COL3, 0x658, 0x268, 0, 0x000, 0), /* MX51_PAD_KEY_COL3__KEY_COL3 */
-	IMX_PIN_REG(MX51_PAD_KEY_COL4, 0x65c, 0x26c, 3, 0x9b8, 1), /* MX51_PAD_KEY_COL4__I2C2_SCL */
-	IMX_PIN_REG(MX51_PAD_KEY_COL4, 0x65c, 0x26c, 0, 0x000, 0), /* MX51_PAD_KEY_COL4__KEY_COL4 */
-	IMX_PIN_REG(MX51_PAD_KEY_COL4, 0x65c, 0x26c, 6, 0x000, 0), /* MX51_PAD_KEY_COL4__SPDIF_OUT1 */
-	IMX_PIN_REG(MX51_PAD_KEY_COL4, 0x65c, 0x26c, 1, 0x000, 0), /* MX51_PAD_KEY_COL4__UART1_RI */
-	IMX_PIN_REG(MX51_PAD_KEY_COL4, 0x65c, 0x26c, 2, 0x9f0, 4), /* MX51_PAD_KEY_COL4__UART3_RTS */
-	IMX_PIN_REG(MX51_PAD_KEY_COL5, 0x660, 0x270, 3, 0x9bc, 1), /* MX51_PAD_KEY_COL5__I2C2_SDA */
-	IMX_PIN_REG(MX51_PAD_KEY_COL5, 0x660, 0x270, 0, 0x000, 0), /* MX51_PAD_KEY_COL5__KEY_COL5 */
-	IMX_PIN_REG(MX51_PAD_KEY_COL5, 0x660, 0x270, 1, 0x000, 0), /* MX51_PAD_KEY_COL5__UART1_DCD */
-	IMX_PIN_REG(MX51_PAD_KEY_COL5, 0x660, 0x270, 2, 0x000, 0), /* MX51_PAD_KEY_COL5__UART3_CTS */
-	IMX_PIN_REG(MX51_PAD_USBH1_CLK, 0x678, 0x278, 1, 0x914, 1), /* MX51_PAD_USBH1_CLK__CSPI_SCLK */
-	IMX_PIN_REG(MX51_PAD_USBH1_CLK, 0x678, 0x278, 2, 0x000, 0), /* MX51_PAD_USBH1_CLK__GPIO1_25 */
-	IMX_PIN_REG(MX51_PAD_USBH1_CLK, 0x678, 0x278, 5, 0x9b8, 2), /* MX51_PAD_USBH1_CLK__I2C2_SCL */
-	IMX_PIN_REG(MX51_PAD_USBH1_CLK, 0x678, 0x278, 0, 0x000, 0), /* MX51_PAD_USBH1_CLK__USBH1_CLK */
-	IMX_PIN_REG(MX51_PAD_USBH1_DIR, 0x67c, 0x27c, 1, 0x91c, 1), /* MX51_PAD_USBH1_DIR__CSPI_MOSI */
-	IMX_PIN_REG(MX51_PAD_USBH1_DIR, 0x67c, 0x27c, 2, 0x000, 0), /* MX51_PAD_USBH1_DIR__GPIO1_26 */
-	IMX_PIN_REG(MX51_PAD_USBH1_DIR, 0x67c, 0x27c, 5, 0x9bc, 2), /* MX51_PAD_USBH1_DIR__I2C2_SDA */
-	IMX_PIN_REG(MX51_PAD_USBH1_DIR, 0x67c, 0x27c, 0, 0x000, 0), /* MX51_PAD_USBH1_DIR__USBH1_DIR */
-	IMX_PIN_REG(MX51_PAD_USBH1_STP, 0x680, 0x280, 1, 0x000, 0), /* MX51_PAD_USBH1_STP__CSPI_RDY */
-	IMX_PIN_REG(MX51_PAD_USBH1_STP, 0x680, 0x280, 2, 0x000, 0), /* MX51_PAD_USBH1_STP__GPIO1_27 */
-	IMX_PIN_REG(MX51_PAD_USBH1_STP, 0x680, 0x280, 5, 0x9f4, 6), /* MX51_PAD_USBH1_STP__UART3_RXD */
-	IMX_PIN_REG(MX51_PAD_USBH1_STP, 0x680, 0x280, 0, 0x000, 0), /* MX51_PAD_USBH1_STP__USBH1_STP */
-	IMX_PIN_REG(MX51_PAD_USBH1_NXT, 0x684, 0x284, 1, 0x918, 0), /* MX51_PAD_USBH1_NXT__CSPI_MISO */
-	IMX_PIN_REG(MX51_PAD_USBH1_NXT, 0x684, 0x284, 2, 0x000, 0), /* MX51_PAD_USBH1_NXT__GPIO1_28 */
-	IMX_PIN_REG(MX51_PAD_USBH1_NXT, 0x684, 0x284, 5, 0x000, 0), /* MX51_PAD_USBH1_NXT__UART3_TXD */
-	IMX_PIN_REG(MX51_PAD_USBH1_NXT, 0x684, 0x284, 0, 0x000, 0), /* MX51_PAD_USBH1_NXT__USBH1_NXT */
-	IMX_PIN_REG(MX51_PAD_USBH1_DATA0, 0x688, 0x288, 2, 0x000, 0), /* MX51_PAD_USBH1_DATA0__GPIO1_11 */
-	IMX_PIN_REG(MX51_PAD_USBH1_DATA0, 0x688, 0x288, 1, 0x000, 0), /* MX51_PAD_USBH1_DATA0__UART2_CTS */
-	IMX_PIN_REG(MX51_PAD_USBH1_DATA0, 0x688, 0x288, 0, 0x000, 0), /* MX51_PAD_USBH1_DATA0__USBH1_DATA0 */
-	IMX_PIN_REG(MX51_PAD_USBH1_DATA1, 0x68c, 0x28c, 2, 0x000, 0), /* MX51_PAD_USBH1_DATA1__GPIO1_12 */
-	IMX_PIN_REG(MX51_PAD_USBH1_DATA1, 0x68c, 0x28c, 1, 0x9ec, 4), /* MX51_PAD_USBH1_DATA1__UART2_RXD */
-	IMX_PIN_REG(MX51_PAD_USBH1_DATA1, 0x68c, 0x28c, 0, 0x000, 0), /* MX51_PAD_USBH1_DATA1__USBH1_DATA1 */
-	IMX_PIN_REG(MX51_PAD_USBH1_DATA2, 0x690, 0x290, 2, 0x000, 0), /* MX51_PAD_USBH1_DATA2__GPIO1_13 */
-	IMX_PIN_REG(MX51_PAD_USBH1_DATA2, 0x690, 0x290, 1, 0x000, 0), /* MX51_PAD_USBH1_DATA2__UART2_TXD */
-	IMX_PIN_REG(MX51_PAD_USBH1_DATA2, 0x690, 0x290, 0, 0x000, 0), /* MX51_PAD_USBH1_DATA2__USBH1_DATA2 */
-	IMX_PIN_REG(MX51_PAD_USBH1_DATA3, 0x694, 0x294, 2, 0x000, 0), /* MX51_PAD_USBH1_DATA3__GPIO1_14 */
-	IMX_PIN_REG(MX51_PAD_USBH1_DATA3, 0x694, 0x294, 1, 0x9e8, 5), /* MX51_PAD_USBH1_DATA3__UART2_RTS */
-	IMX_PIN_REG(MX51_PAD_USBH1_DATA3, 0x694, 0x294, 0, 0x000, 0), /* MX51_PAD_USBH1_DATA3__USBH1_DATA3 */
-	IMX_PIN_REG(MX51_PAD_USBH1_DATA4, 0x698, 0x298, 1, 0x000, 0), /* MX51_PAD_USBH1_DATA4__CSPI_SS0 */
-	IMX_PIN_REG(MX51_PAD_USBH1_DATA4, 0x698, 0x298, 2, 0x000, 0), /* MX51_PAD_USBH1_DATA4__GPIO1_15 */
-	IMX_PIN_REG(MX51_PAD_USBH1_DATA4, 0x698, 0x298, 0, 0x000, 0), /* MX51_PAD_USBH1_DATA4__USBH1_DATA4 */
-	IMX_PIN_REG(MX51_PAD_USBH1_DATA5, 0x69c, 0x29c, 1, 0x920, 0), /* MX51_PAD_USBH1_DATA5__CSPI_SS1 */
-	IMX_PIN_REG(MX51_PAD_USBH1_DATA5, 0x69c, 0x29c, 2, 0x000, 0), /* MX51_PAD_USBH1_DATA5__GPIO1_16 */
-	IMX_PIN_REG(MX51_PAD_USBH1_DATA5, 0x69c, 0x29c, 0, 0x000, 0), /* MX51_PAD_USBH1_DATA5__USBH1_DATA5 */
-	IMX_PIN_REG(MX51_PAD_USBH1_DATA6, 0x6a0, 0x2a0, 1, 0x928, 1), /* MX51_PAD_USBH1_DATA6__CSPI_SS3 */
-	IMX_PIN_REG(MX51_PAD_USBH1_DATA6, 0x6a0, 0x2a0, 2, 0x000, 0), /* MX51_PAD_USBH1_DATA6__GPIO1_17 */
-	IMX_PIN_REG(MX51_PAD_USBH1_DATA6, 0x6a0, 0x2a0, 0, 0x000, 0), /* MX51_PAD_USBH1_DATA6__USBH1_DATA6 */
-	IMX_PIN_REG(MX51_PAD_USBH1_DATA7, 0x6a4, 0x2a4, 1, 0x000, 0), /* MX51_PAD_USBH1_DATA7__ECSPI1_SS3 */
-	IMX_PIN_REG(MX51_PAD_USBH1_DATA7, 0x6a4, 0x2a4, 5, 0x934, 1), /* MX51_PAD_USBH1_DATA7__ECSPI2_SS3 */
-	IMX_PIN_REG(MX51_PAD_USBH1_DATA7, 0x6a4, 0x2a4, 2, 0x000, 0), /* MX51_PAD_USBH1_DATA7__GPIO1_18 */
-	IMX_PIN_REG(MX51_PAD_USBH1_DATA7, 0x6a4, 0x2a4, 0, 0x000, 0), /* MX51_PAD_USBH1_DATA7__USBH1_DATA7 */
-	IMX_PIN_REG(MX51_PAD_DI1_PIN11, 0x6a8, 0x2a8, 0, 0x000, 0), /* MX51_PAD_DI1_PIN11__DI1_PIN11 */
-	IMX_PIN_REG(MX51_PAD_DI1_PIN11, 0x6a8, 0x2a8, 7, 0x000, 0), /* MX51_PAD_DI1_PIN11__ECSPI1_SS2 */
-	IMX_PIN_REG(MX51_PAD_DI1_PIN11, 0x6a8, 0x2a8, 4, 0x000, 0), /* MX51_PAD_DI1_PIN11__GPIO3_0 */
-	IMX_PIN_REG(MX51_PAD_DI1_PIN12, 0x6ac, 0x2ac, 0, 0x000, 0), /* MX51_PAD_DI1_PIN12__DI1_PIN12 */
-	IMX_PIN_REG(MX51_PAD_DI1_PIN12, 0x6ac, 0x2ac, 4, 0x978, 1), /* MX51_PAD_DI1_PIN12__GPIO3_1 */
-	IMX_PIN_REG(MX51_PAD_DI1_PIN13, 0x6b0, 0x2b0, 0, 0x000, 0), /* MX51_PAD_DI1_PIN13__DI1_PIN13 */
-	IMX_PIN_REG(MX51_PAD_DI1_PIN13, 0x6b0, 0x2b0, 4, 0x97c, 1), /* MX51_PAD_DI1_PIN13__GPIO3_2 */
-	IMX_PIN_REG(MX51_PAD_DI1_D0_CS, 0x6b4, 0x2b4, 0, 0x000, 0), /* MX51_PAD_DI1_D0_CS__DI1_D0_CS */
-	IMX_PIN_REG(MX51_PAD_DI1_D0_CS, 0x6b4, 0x2b4, 4, 0x980, 1), /* MX51_PAD_DI1_D0_CS__GPIO3_3 */
-	IMX_PIN_REG(MX51_PAD_DI1_D1_CS, 0x6b8, 0x2b8, 0, 0x000, 0), /* MX51_PAD_DI1_D1_CS__DI1_D1_CS */
-	IMX_PIN_REG(MX51_PAD_DI1_D1_CS, 0x6b8, 0x2b8, 2, 0x000, 0), /* MX51_PAD_DI1_D1_CS__DISP1_PIN14 */
-	IMX_PIN_REG(MX51_PAD_DI1_D1_CS, 0x6b8, 0x2b8, 3, 0x000, 0), /* MX51_PAD_DI1_D1_CS__DISP1_PIN5 */
-	IMX_PIN_REG(MX51_PAD_DI1_D1_CS, 0x6b8, 0x2b8, 4, 0x984, 1), /* MX51_PAD_DI1_D1_CS__GPIO3_4 */
-	IMX_PIN_REG(MX51_PAD_DISPB2_SER_DIN, 0x6bc, 0x2bc, 2, 0x9a4, 1), /* MX51_PAD_DISPB2_SER_DIN__DISP1_PIN1 */
-	IMX_PIN_REG(MX51_PAD_DISPB2_SER_DIN, 0x6bc, 0x2bc, 0, 0x9c4, 0), /* MX51_PAD_DISPB2_SER_DIN__DISPB2_SER_DIN */
-	IMX_PIN_REG(MX51_PAD_DISPB2_SER_DIN, 0x6bc, 0x2bc, 4, 0x988, 1), /* MX51_PAD_DISPB2_SER_DIN__GPIO3_5 */
-	IMX_PIN_REG(MX51_PAD_DISPB2_SER_DIO, 0x6c0, 0x2c0, 3, 0x000, 0), /* MX51_PAD_DISPB2_SER_DIO__DISP1_PIN6 */
-	IMX_PIN_REG(MX51_PAD_DISPB2_SER_DIO, 0x6c0, 0x2c0, 0, 0x9c4, 1), /* MX51_PAD_DISPB2_SER_DIO__DISPB2_SER_DIO */
-	IMX_PIN_REG(MX51_PAD_DISPB2_SER_DIO, 0x6c0, 0x2c0, 4, 0x98c, 1), /* MX51_PAD_DISPB2_SER_DIO__GPIO3_6 */
-	IMX_PIN_REG(MX51_PAD_DISPB2_SER_CLK, 0x6c4, 0x2c4, 2, 0x000, 0), /* MX51_PAD_DISPB2_SER_CLK__DISP1_PIN17 */
-	IMX_PIN_REG(MX51_PAD_DISPB2_SER_CLK, 0x6c4, 0x2c4, 3, 0x000, 0), /* MX51_PAD_DISPB2_SER_CLK__DISP1_PIN7 */
-	IMX_PIN_REG(MX51_PAD_DISPB2_SER_CLK, 0x6c4, 0x2c4, 0, 0x000, 0), /* MX51_PAD_DISPB2_SER_CLK__DISPB2_SER_CLK */
-	IMX_PIN_REG(MX51_PAD_DISPB2_SER_CLK, 0x6c4, 0x2c4, 4, 0x990, 1), /* MX51_PAD_DISPB2_SER_CLK__GPIO3_7 */
-	IMX_PIN_REG(MX51_PAD_DISPB2_SER_RS, 0x6c8, 0x2c8, 2, 0x000, 0), /* MX51_PAD_DISPB2_SER_RS__DISP1_EXT_CLK */
-	IMX_PIN_REG(MX51_PAD_DISPB2_SER_RS, 0x6c8, 0x2c8, 2, 0x000, 0), /* MX51_PAD_DISPB2_SER_RS__DISP1_PIN16 */
-	IMX_PIN_REG(MX51_PAD_DISPB2_SER_RS, 0x6c8, 0x2c8, 3, 0x000, 0), /* MX51_PAD_DISPB2_SER_RS__DISP1_PIN8 */
-	IMX_PIN_REG(MX51_PAD_DISPB2_SER_RS, 0x6c8, 0x2c8, 0, 0x000, 0), /* MX51_PAD_DISPB2_SER_RS__DISPB2_SER_RS */
-	IMX_PIN_REG(MX51_PAD_DISPB2_SER_RS, 0x6c8, 0x2c8, 0, 0x000, 0), /* MX51_PAD_DISPB2_SER_RS__DISPB2_SER_RS */
-	IMX_PIN_REG(MX51_PAD_DISPB2_SER_RS, 0x6c8, 0x2c8, 4, 0x994, 1), /* MX51_PAD_DISPB2_SER_RS__GPIO3_8 */
-	IMX_PIN_REG(MX51_PAD_DISP1_DAT0, 0x6cc, 0x2cc, 0, 0x000, 0), /* MX51_PAD_DISP1_DAT0__DISP1_DAT0 */
-	IMX_PIN_REG(MX51_PAD_DISP1_DAT1, 0x6d0, 0x2d0, 0, 0x000, 0), /* MX51_PAD_DISP1_DAT1__DISP1_DAT1 */
-	IMX_PIN_REG(MX51_PAD_DISP1_DAT2, 0x6d4, 0x2d4, 0, 0x000, 0), /* MX51_PAD_DISP1_DAT2__DISP1_DAT2 */
-	IMX_PIN_REG(MX51_PAD_DISP1_DAT3, 0x6d8, 0x2d8, 0, 0x000, 0), /* MX51_PAD_DISP1_DAT3__DISP1_DAT3 */
-	IMX_PIN_REG(MX51_PAD_DISP1_DAT4, 0x6dc, 0x2dc, 0, 0x000, 0), /* MX51_PAD_DISP1_DAT4__DISP1_DAT4 */
-	IMX_PIN_REG(MX51_PAD_DISP1_DAT5, 0x6e0, 0x2e0, 0, 0x000, 0), /* MX51_PAD_DISP1_DAT5__DISP1_DAT5 */
-	IMX_PIN_REG(MX51_PAD_DISP1_DAT6, 0x6e4, 0x2e4, 7, 0x000, 0), /* MX51_PAD_DISP1_DAT6__BOOT_USB_SRC */
-	IMX_PIN_REG(MX51_PAD_DISP1_DAT6, 0x6e4, 0x2e4, 0, 0x000, 0), /* MX51_PAD_DISP1_DAT6__DISP1_DAT6 */
-	IMX_PIN_REG(MX51_PAD_DISP1_DAT7, 0x6e8, 0x2e8, 7, 0x000, 0), /* MX51_PAD_DISP1_DAT7__BOOT_EEPROM_CFG */
-	IMX_PIN_REG(MX51_PAD_DISP1_DAT7, 0x6e8, 0x2e8, 0, 0x000, 0), /* MX51_PAD_DISP1_DAT7__DISP1_DAT7 */
-	IMX_PIN_REG(MX51_PAD_DISP1_DAT8, 0x6ec, 0x2ec, 7, 0x000, 0), /* MX51_PAD_DISP1_DAT8__BOOT_SRC0 */
-	IMX_PIN_REG(MX51_PAD_DISP1_DAT8, 0x6ec, 0x2ec, 0, 0x000, 0), /* MX51_PAD_DISP1_DAT8__DISP1_DAT8 */
-	IMX_PIN_REG(MX51_PAD_DISP1_DAT9, 0x6f0, 0x2f0, 7, 0x000, 0), /* MX51_PAD_DISP1_DAT9__BOOT_SRC1 */
-	IMX_PIN_REG(MX51_PAD_DISP1_DAT9, 0x6f0, 0x2f0, 0, 0x000, 0), /* MX51_PAD_DISP1_DAT9__DISP1_DAT9 */
-	IMX_PIN_REG(MX51_PAD_DISP1_DAT10, 0x6f4, 0x2f4, 7, 0x000, 0), /* MX51_PAD_DISP1_DAT10__BOOT_SPARE_SIZE */
-	IMX_PIN_REG(MX51_PAD_DISP1_DAT10, 0x6f4, 0x2f4, 0, 0x000, 0), /* MX51_PAD_DISP1_DAT10__DISP1_DAT10 */
-	IMX_PIN_REG(MX51_PAD_DISP1_DAT11, 0x6f8, 0x2f8, 7, 0x000, 0), /* MX51_PAD_DISP1_DAT11__BOOT_LPB_FREQ2 */
-	IMX_PIN_REG(MX51_PAD_DISP1_DAT11, 0x6f8, 0x2f8, 0, 0x000, 0), /* MX51_PAD_DISP1_DAT11__DISP1_DAT11 */
-	IMX_PIN_REG(MX51_PAD_DISP1_DAT12, 0x6fc, 0x2fc, 7, 0x000, 0), /* MX51_PAD_DISP1_DAT12__BOOT_MLC_SEL */
-	IMX_PIN_REG(MX51_PAD_DISP1_DAT12, 0x6fc, 0x2fc, 0, 0x000, 0), /* MX51_PAD_DISP1_DAT12__DISP1_DAT12 */
-	IMX_PIN_REG(MX51_PAD_DISP1_DAT13, 0x700, 0x300, 7, 0x000, 0), /* MX51_PAD_DISP1_DAT13__BOOT_MEM_CTL0 */
-	IMX_PIN_REG(MX51_PAD_DISP1_DAT13, 0x700, 0x300, 0, 0x000, 0), /* MX51_PAD_DISP1_DAT13__DISP1_DAT13 */
-	IMX_PIN_REG(MX51_PAD_DISP1_DAT14, 0x704, 0x304, 7, 0x000, 0), /* MX51_PAD_DISP1_DAT14__BOOT_MEM_CTL1 */
-	IMX_PIN_REG(MX51_PAD_DISP1_DAT14, 0x704, 0x304, 0, 0x000, 0), /* MX51_PAD_DISP1_DAT14__DISP1_DAT14 */
-	IMX_PIN_REG(MX51_PAD_DISP1_DAT15, 0x708, 0x308, 7, 0x000, 0), /* MX51_PAD_DISP1_DAT15__BOOT_BUS_WIDTH */
-	IMX_PIN_REG(MX51_PAD_DISP1_DAT15, 0x708, 0x308, 0, 0x000, 0), /* MX51_PAD_DISP1_DAT15__DISP1_DAT15 */
-	IMX_PIN_REG(MX51_PAD_DISP1_DAT16, 0x70c, 0x30c, 7, 0x000, 0), /* MX51_PAD_DISP1_DAT16__BOOT_PAGE_SIZE0 */
-	IMX_PIN_REG(MX51_PAD_DISP1_DAT16, 0x70c, 0x30c, 0, 0x000, 0), /* MX51_PAD_DISP1_DAT16__DISP1_DAT16 */
-	IMX_PIN_REG(MX51_PAD_DISP1_DAT17, 0x710, 0x310, 7, 0x000, 0), /* MX51_PAD_DISP1_DAT17__BOOT_PAGE_SIZE1 */
-	IMX_PIN_REG(MX51_PAD_DISP1_DAT17, 0x710, 0x310, 0, 0x000, 0), /* MX51_PAD_DISP1_DAT17__DISP1_DAT17 */
-	IMX_PIN_REG(MX51_PAD_DISP1_DAT18, 0x714, 0x314, 7, 0x000, 0), /* MX51_PAD_DISP1_DAT18__BOOT_WEIM_MUXED0 */
-	IMX_PIN_REG(MX51_PAD_DISP1_DAT18, 0x714, 0x314, 0, 0x000, 0), /* MX51_PAD_DISP1_DAT18__DISP1_DAT18 */
-	IMX_PIN_REG(MX51_PAD_DISP1_DAT18, 0x714, 0x314, 5, 0x000, 0), /* MX51_PAD_DISP1_DAT18__DISP2_PIN11 */
-	IMX_PIN_REG(MX51_PAD_DISP1_DAT18, 0x714, 0x314, 4, 0x000, 0), /* MX51_PAD_DISP1_DAT18__DISP2_PIN5 */
-	IMX_PIN_REG(MX51_PAD_DISP1_DAT19, 0x718, 0x318, 7, 0x000, 0), /* MX51_PAD_DISP1_DAT19__BOOT_WEIM_MUXED1 */
-	IMX_PIN_REG(MX51_PAD_DISP1_DAT19, 0x718, 0x318, 0, 0x000, 0), /* MX51_PAD_DISP1_DAT19__DISP1_DAT19 */
-	IMX_PIN_REG(MX51_PAD_DISP1_DAT19, 0x718, 0x318, 5, 0x000, 0), /* MX51_PAD_DISP1_DAT19__DISP2_PIN12 */
-	IMX_PIN_REG(MX51_PAD_DISP1_DAT19, 0x718, 0x318, 4, 0x000, 0), /* MX51_PAD_DISP1_DAT19__DISP2_PIN6 */
-	IMX_PIN_REG(MX51_PAD_DISP1_DAT20, 0x71c, 0x31c, 7, 0x000, 0), /* MX51_PAD_DISP1_DAT20__BOOT_MEM_TYPE0 */
-	IMX_PIN_REG(MX51_PAD_DISP1_DAT20, 0x71c, 0x31c, 0, 0x000, 0), /* MX51_PAD_DISP1_DAT20__DISP1_DAT20 */
-	IMX_PIN_REG(MX51_PAD_DISP1_DAT20, 0x71c, 0x31c, 5, 0x000, 0), /* MX51_PAD_DISP1_DAT20__DISP2_PIN13 */
-	IMX_PIN_REG(MX51_PAD_DISP1_DAT20, 0x71c, 0x31c, 4, 0x000, 0), /* MX51_PAD_DISP1_DAT20__DISP2_PIN7 */
-	IMX_PIN_REG(MX51_PAD_DISP1_DAT21, 0x720, 0x320, 7, 0x000, 0), /* MX51_PAD_DISP1_DAT21__BOOT_MEM_TYPE1 */
-	IMX_PIN_REG(MX51_PAD_DISP1_DAT21, 0x720, 0x320, 0, 0x000, 0), /* MX51_PAD_DISP1_DAT21__DISP1_DAT21 */
-	IMX_PIN_REG(MX51_PAD_DISP1_DAT21, 0x720, 0x320, 5, 0x000, 0), /* MX51_PAD_DISP1_DAT21__DISP2_PIN14 */
-	IMX_PIN_REG(MX51_PAD_DISP1_DAT21, 0x720, 0x320, 4, 0x000, 0), /* MX51_PAD_DISP1_DAT21__DISP2_PIN8 */
-	IMX_PIN_REG(MX51_PAD_DISP1_DAT22, 0x724, 0x324, 7, 0x000, 0), /* MX51_PAD_DISP1_DAT22__BOOT_LPB_FREQ0 */
-	IMX_PIN_REG(MX51_PAD_DISP1_DAT22, 0x724, 0x324, 0, 0x000, 0), /* MX51_PAD_DISP1_DAT22__DISP1_DAT22 */
-	IMX_PIN_REG(MX51_PAD_DISP1_DAT22, 0x724, 0x324, 6, 0x000, 0), /* MX51_PAD_DISP1_DAT22__DISP2_D0_CS */
-	IMX_PIN_REG(MX51_PAD_DISP1_DAT22, 0x724, 0x324, 5, 0x000, 0), /* MX51_PAD_DISP1_DAT22__DISP2_DAT16 */
-	IMX_PIN_REG(MX51_PAD_DISP1_DAT23, 0x728, 0x328, 7, 0x000, 0), /* MX51_PAD_DISP1_DAT23__BOOT_LPB_FREQ1 */
-	IMX_PIN_REG(MX51_PAD_DISP1_DAT23, 0x728, 0x328, 0, 0x000, 0), /* MX51_PAD_DISP1_DAT23__DISP1_DAT23 */
-	IMX_PIN_REG(MX51_PAD_DISP1_DAT23, 0x728, 0x328, 6, 0x000, 0), /* MX51_PAD_DISP1_DAT23__DISP2_D1_CS */
-	IMX_PIN_REG(MX51_PAD_DISP1_DAT23, 0x728, 0x328, 5, 0x000, 0), /* MX51_PAD_DISP1_DAT23__DISP2_DAT17 */
-	IMX_PIN_REG(MX51_PAD_DISP1_DAT23, 0x728, 0x328, 4, 0x000, 0), /* MX51_PAD_DISP1_DAT23__DISP2_SER_CS */
-	IMX_PIN_REG(MX51_PAD_DI1_PIN3, 0x72c, 0x32c, 0, 0x000, 0), /* MX51_PAD_DI1_PIN3__DI1_PIN3 */
-	IMX_PIN_REG(MX51_PAD_DI1_PIN2, 0x734, 0x330, 0, 0x000, 0), /* MX51_PAD_DI1_PIN2__DI1_PIN2 */
-	IMX_PIN_REG(MX51_PAD_DI_GP2, 0x740, 0x338, 0, 0x000, 0), /* MX51_PAD_DI_GP2__DISP1_SER_CLK */
-	IMX_PIN_REG(MX51_PAD_DI_GP2, 0x740, 0x338, 2, 0x9a8, 1), /* MX51_PAD_DI_GP2__DISP2_WAIT */
-	IMX_PIN_REG(MX51_PAD_DI_GP3, 0x744, 0x33c, 3, 0x9a0, 1), /* MX51_PAD_DI_GP3__CSI1_DATA_EN */
-	IMX_PIN_REG(MX51_PAD_DI_GP3, 0x744, 0x33c, 0, 0x9c0, 0), /* MX51_PAD_DI_GP3__DISP1_SER_DIO */
-	IMX_PIN_REG(MX51_PAD_DI_GP3, 0x744, 0x33c, 2, 0x000, 0), /* MX51_PAD_DI_GP3__FEC_TX_ER */
-	IMX_PIN_REG(MX51_PAD_DI2_PIN4, 0x748, 0x340, 3, 0x99c, 1), /* MX51_PAD_DI2_PIN4__CSI2_DATA_EN */
-	IMX_PIN_REG(MX51_PAD_DI2_PIN4, 0x748, 0x340, 0, 0x000, 0), /* MX51_PAD_DI2_PIN4__DI2_PIN4 */
-	IMX_PIN_REG(MX51_PAD_DI2_PIN4, 0x748, 0x340, 2, 0x950, 1), /* MX51_PAD_DI2_PIN4__FEC_CRS */
-	IMX_PIN_REG(MX51_PAD_DI2_PIN2, 0x74c, 0x344, 0, 0x000, 0), /* MX51_PAD_DI2_PIN2__DI2_PIN2 */
-	IMX_PIN_REG(MX51_PAD_DI2_PIN2, 0x74c, 0x344, 2, 0x000, 0), /* MX51_PAD_DI2_PIN2__FEC_MDC */
-	IMX_PIN_REG(MX51_PAD_DI2_PIN3, 0x750, 0x348, 0, 0x000, 0), /* MX51_PAD_DI2_PIN3__DI2_PIN3 */
-	IMX_PIN_REG(MX51_PAD_DI2_PIN3, 0x750, 0x348, 2, 0x954, 1), /* MX51_PAD_DI2_PIN3__FEC_MDIO */
-	IMX_PIN_REG(MX51_PAD_DI2_DISP_CLK, 0x754, 0x34c, 0, 0x000, 0), /* MX51_PAD_DI2_DISP_CLK__DI2_DISP_CLK */
-	IMX_PIN_REG(MX51_PAD_DI2_DISP_CLK, 0x754, 0x34c, 2, 0x95c, 1), /* MX51_PAD_DI2_DISP_CLK__FEC_RDATA1 */
-	IMX_PIN_REG(MX51_PAD_DI_GP4, 0x758, 0x350, 4, 0x000, 0), /* MX51_PAD_DI_GP4__DI2_PIN15 */
-	IMX_PIN_REG(MX51_PAD_DI_GP4, 0x758, 0x350, 0, 0x9c0, 1), /* MX51_PAD_DI_GP4__DISP1_SER_DIN */
-	IMX_PIN_REG(MX51_PAD_DI_GP4, 0x758, 0x350, 3, 0x000, 0), /* MX51_PAD_DI_GP4__DISP2_PIN1 */
-	IMX_PIN_REG(MX51_PAD_DI_GP4, 0x758, 0x350, 2, 0x960, 1), /* MX51_PAD_DI_GP4__FEC_RDATA2 */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT0, 0x75c, 0x354, 0, 0x000, 0), /* MX51_PAD_DISP2_DAT0__DISP2_DAT0 */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT0, 0x75c, 0x354, 2, 0x964, 1), /* MX51_PAD_DISP2_DAT0__FEC_RDATA3 */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT0, 0x75c, 0x354, 4, 0x9c8, 1), /* MX51_PAD_DISP2_DAT0__KEY_COL6 */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT0, 0x75c, 0x354, 5, 0x9f4, 8), /* MX51_PAD_DISP2_DAT0__UART3_RXD */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT0, 0x75c, 0x354, 3, 0x9f8, 1), /* MX51_PAD_DISP2_DAT0__USBH3_CLK */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT1, 0x760, 0x358, 0, 0x000, 0), /* MX51_PAD_DISP2_DAT1__DISP2_DAT1 */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT1, 0x760, 0x358, 2, 0x970, 1), /* MX51_PAD_DISP2_DAT1__FEC_RX_ER */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT1, 0x760, 0x358, 4, 0x9cc, 1), /* MX51_PAD_DISP2_DAT1__KEY_COL7 */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT1, 0x760, 0x358, 5, 0x000, 0), /* MX51_PAD_DISP2_DAT1__UART3_TXD */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT1, 0x760, 0x358, 3, 0xa1c, 1), /* MX51_PAD_DISP2_DAT1__USBH3_DIR */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT2, 0x764, 0x35c, 0, 0x000, 0), /* MX51_PAD_DISP2_DAT2__DISP2_DAT2 */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT3, 0x768, 0x360, 0, 0x000, 0), /* MX51_PAD_DISP2_DAT3__DISP2_DAT3 */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT4, 0x76c, 0x364, 0, 0x000, 0), /* MX51_PAD_DISP2_DAT4__DISP2_DAT4 */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT5, 0x770, 0x368, 0, 0x000, 0), /* MX51_PAD_DISP2_DAT5__DISP2_DAT5 */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT6, 0x774, 0x36c, 0, 0x000, 0), /* MX51_PAD_DISP2_DAT6__DISP2_DAT6 */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT6, 0x774, 0x36c, 2, 0x000, 0), /* MX51_PAD_DISP2_DAT6__FEC_TDATA1 */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT6, 0x774, 0x36c, 5, 0x000, 0), /* MX51_PAD_DISP2_DAT6__GPIO1_19 */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT6, 0x774, 0x36c, 4, 0x9d0, 1), /* MX51_PAD_DISP2_DAT6__KEY_ROW4 */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT6, 0x774, 0x36c, 3, 0xa24, 1), /* MX51_PAD_DISP2_DAT6__USBH3_STP */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT7, 0x778, 0x370, 0, 0x000, 0), /* MX51_PAD_DISP2_DAT7__DISP2_DAT7 */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT7, 0x778, 0x370, 2, 0x000, 0), /* MX51_PAD_DISP2_DAT7__FEC_TDATA2 */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT7, 0x778, 0x370, 5, 0x000, 0), /* MX51_PAD_DISP2_DAT7__GPIO1_29 */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT7, 0x778, 0x370, 4, 0x9d4, 1), /* MX51_PAD_DISP2_DAT7__KEY_ROW5 */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT7, 0x778, 0x370, 3, 0xa20, 1), /* MX51_PAD_DISP2_DAT7__USBH3_NXT */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT8, 0x77c, 0x374, 0, 0x000, 0), /* MX51_PAD_DISP2_DAT8__DISP2_DAT8 */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT8, 0x77c, 0x374, 2, 0x000, 0), /* MX51_PAD_DISP2_DAT8__FEC_TDATA3 */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT8, 0x77c, 0x374, 5, 0x000, 0), /* MX51_PAD_DISP2_DAT8__GPIO1_30 */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT8, 0x77c, 0x374, 4, 0x9d8, 1), /* MX51_PAD_DISP2_DAT8__KEY_ROW6 */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT8, 0x77c, 0x374, 3, 0x9fc, 1), /* MX51_PAD_DISP2_DAT8__USBH3_DATA0 */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT9, 0x780, 0x378, 4, 0x8f4, 1), /* MX51_PAD_DISP2_DAT9__AUD6_RXC */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT9, 0x780, 0x378, 0, 0x000, 0), /* MX51_PAD_DISP2_DAT9__DISP2_DAT9 */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT9, 0x780, 0x378, 2, 0x000, 0), /* MX51_PAD_DISP2_DAT9__FEC_TX_EN */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT9, 0x780, 0x378, 5, 0x000, 0), /* MX51_PAD_DISP2_DAT9__GPIO1_31 */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT9, 0x780, 0x378, 3, 0xa00, 1), /* MX51_PAD_DISP2_DAT9__USBH3_DATA1 */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT10, 0x784, 0x37c, 0, 0x000, 0), /* MX51_PAD_DISP2_DAT10__DISP2_DAT10 */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT10, 0x784, 0x37c, 5, 0x000, 0), /* MX51_PAD_DISP2_DAT10__DISP2_SER_CS */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT10, 0x784, 0x37c, 2, 0x94c, 1), /* MX51_PAD_DISP2_DAT10__FEC_COL */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT10, 0x784, 0x37c, 4, 0x9dc, 1), /* MX51_PAD_DISP2_DAT10__KEY_ROW7 */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT10, 0x784, 0x37c, 3, 0xa04, 1), /* MX51_PAD_DISP2_DAT10__USBH3_DATA2 */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT11, 0x788, 0x380, 4, 0x8f0, 1), /* MX51_PAD_DISP2_DAT11__AUD6_TXD */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT11, 0x788, 0x380, 0, 0x000, 0), /* MX51_PAD_DISP2_DAT11__DISP2_DAT11 */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT11, 0x788, 0x380, 2, 0x968, 1), /* MX51_PAD_DISP2_DAT11__FEC_RX_CLK */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT11, 0x788, 0x380, 7, 0x000, 0), /* MX51_PAD_DISP2_DAT11__GPIO1_10 */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT11, 0x788, 0x380, 3, 0xa08, 1), /* MX51_PAD_DISP2_DAT11__USBH3_DATA3 */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT12, 0x78c, 0x384, 4, 0x8ec, 1), /* MX51_PAD_DISP2_DAT12__AUD6_RXD */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT12, 0x78c, 0x384, 0, 0x000, 0), /* MX51_PAD_DISP2_DAT12__DISP2_DAT12 */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT12, 0x78c, 0x384, 2, 0x96c, 1), /* MX51_PAD_DISP2_DAT12__FEC_RX_DV */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT12, 0x78c, 0x384, 3, 0xa0c, 1), /* MX51_PAD_DISP2_DAT12__USBH3_DATA4 */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT13, 0x790, 0x388, 4, 0x8fc, 1), /* MX51_PAD_DISP2_DAT13__AUD6_TXC */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT13, 0x790, 0x388, 0, 0x000, 0), /* MX51_PAD_DISP2_DAT13__DISP2_DAT13 */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT13, 0x790, 0x388, 2, 0x974, 1), /* MX51_PAD_DISP2_DAT13__FEC_TX_CLK */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT13, 0x790, 0x388, 3, 0xa10, 1), /* MX51_PAD_DISP2_DAT13__USBH3_DATA5 */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT14, 0x794, 0x38c, 4, 0x900, 1), /* MX51_PAD_DISP2_DAT14__AUD6_TXFS */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT14, 0x794, 0x38c, 0, 0x000, 0), /* MX51_PAD_DISP2_DAT14__DISP2_DAT14 */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT14, 0x794, 0x38c, 2, 0x958, 1), /* MX51_PAD_DISP2_DAT14__FEC_RDATA0 */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT14, 0x794, 0x38c, 3, 0xa14, 1), /* MX51_PAD_DISP2_DAT14__USBH3_DATA6 */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT15, 0x798, 0x390, 4, 0x8f8, 1), /* MX51_PAD_DISP2_DAT15__AUD6_RXFS */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT15, 0x798, 0x390, 5, 0x000, 0), /* MX51_PAD_DISP2_DAT15__DISP1_SER_CS */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT15, 0x798, 0x390, 0, 0x000, 0), /* MX51_PAD_DISP2_DAT15__DISP2_DAT15 */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT15, 0x798, 0x390, 2, 0x000, 0), /* MX51_PAD_DISP2_DAT15__FEC_TDATA0 */
-	IMX_PIN_REG(MX51_PAD_DISP2_DAT15, 0x798, 0x390, 3, 0xa18, 1), /* MX51_PAD_DISP2_DAT15__USBH3_DATA7 */
-	IMX_PIN_REG(MX51_PAD_SD1_CMD, 0x79c, 0x394, 1, 0x8e0, 1), /* MX51_PAD_SD1_CMD__AUD5_RXFS */
-	IMX_PIN_REG(MX51_PAD_SD1_CMD, 0x79c, 0x394, 2, 0x91c, 2), /* MX51_PAD_SD1_CMD__CSPI_MOSI */
-	IMX_PIN_REG(MX51_PAD_SD1_CMD, 0x79c, 0x394, 0, 0x000, 0), /* MX51_PAD_SD1_CMD__SD1_CMD */
-	IMX_PIN_REG(MX51_PAD_SD1_CLK, 0x7a0, 0x398, 1, 0x8dc, 1), /* MX51_PAD_SD1_CLK__AUD5_RXC */
-	IMX_PIN_REG(MX51_PAD_SD1_CLK, 0x7a0, 0x398, 2, 0x914, 2), /* MX51_PAD_SD1_CLK__CSPI_SCLK */
-	IMX_PIN_REG(MX51_PAD_SD1_CLK, 0x7a0, 0x398, 0, 0x000, 0), /* MX51_PAD_SD1_CLK__SD1_CLK */
-	IMX_PIN_REG(MX51_PAD_SD1_DATA0, 0x7a4, 0x39c, 1, 0x8d8, 2), /* MX51_PAD_SD1_DATA0__AUD5_TXD */
-	IMX_PIN_REG(MX51_PAD_SD1_DATA0, 0x7a4, 0x39c, 2, 0x918, 1), /* MX51_PAD_SD1_DATA0__CSPI_MISO */
-	IMX_PIN_REG(MX51_PAD_SD1_DATA0, 0x7a4, 0x39c, 0, 0x000, 0), /* MX51_PAD_SD1_DATA0__SD1_DATA0 */
-	IMX_PIN_REG(MX51_PAD_EIM_DA0, NO_PAD, 0x01c, 0, 0x000, 0), /* MX51_PAD_EIM_DA0__EIM_DA0 */
-	IMX_PIN_REG(MX51_PAD_EIM_DA1, NO_PAD, 0x020, 0, 0x000, 0), /* MX51_PAD_EIM_DA1__EIM_DA1 */
-	IMX_PIN_REG(MX51_PAD_EIM_DA2, NO_PAD, 0x024, 0, 0x000, 0), /* MX51_PAD_EIM_DA2__EIM_DA2 */
-	IMX_PIN_REG(MX51_PAD_EIM_DA3, NO_PAD, 0x028, 0, 0x000, 0), /* MX51_PAD_EIM_DA3__EIM_DA3 */
-	IMX_PIN_REG(MX51_PAD_SD1_DATA1, 0x7a8, 0x3a0, 1, 0x8d4, 2), /* MX51_PAD_SD1_DATA1__AUD5_RXD */
-	IMX_PIN_REG(MX51_PAD_SD1_DATA1, 0x7a8, 0x3a0, 0, 0x000, 0), /* MX51_PAD_SD1_DATA1__SD1_DATA1 */
-	IMX_PIN_REG(MX51_PAD_EIM_DA4, NO_PAD, 0x02c, 0, 0x000, 0), /* MX51_PAD_EIM_DA4__EIM_DA4 */
-	IMX_PIN_REG(MX51_PAD_EIM_DA5, NO_PAD, 0x030, 0, 0x000, 0), /* MX51_PAD_EIM_DA5__EIM_DA5 */
-	IMX_PIN_REG(MX51_PAD_EIM_DA6, NO_PAD, 0x034, 0, 0x000, 0), /* MX51_PAD_EIM_DA6__EIM_DA6 */
-	IMX_PIN_REG(MX51_PAD_EIM_DA7, NO_PAD, 0x038, 0, 0x000, 0), /* MX51_PAD_EIM_DA7__EIM_DA7 */
-	IMX_PIN_REG(MX51_PAD_SD1_DATA2, 0x7ac, 0x3a4, 1, 0x8e4, 2), /* MX51_PAD_SD1_DATA2__AUD5_TXC */
-	IMX_PIN_REG(MX51_PAD_SD1_DATA2, 0x7ac, 0x3a4, 0, 0x000, 0), /* MX51_PAD_SD1_DATA2__SD1_DATA2 */
-	IMX_PIN_REG(MX51_PAD_EIM_DA10, NO_PAD, 0x044, 0, 0x000, 0), /* MX51_PAD_EIM_DA10__EIM_DA10 */
-	IMX_PIN_REG(MX51_PAD_EIM_DA11, NO_PAD, 0x048, 0, 0x000, 0), /* MX51_PAD_EIM_DA11__EIM_DA11 */
-	IMX_PIN_REG(MX51_PAD_EIM_DA8, NO_PAD, 0x03c, 0, 0x000, 0), /* MX51_PAD_EIM_DA8__EIM_DA8 */
-	IMX_PIN_REG(MX51_PAD_EIM_DA9, NO_PAD, 0x040, 0, 0x000, 0), /* MX51_PAD_EIM_DA9__EIM_DA9 */
-	IMX_PIN_REG(MX51_PAD_SD1_DATA3, 0x7b0, 0x3a8, 1, 0x8e8, 2), /* MX51_PAD_SD1_DATA3__AUD5_TXFS */
-	IMX_PIN_REG(MX51_PAD_SD1_DATA3, 0x7b0, 0x3a8, 2, 0x920, 1), /* MX51_PAD_SD1_DATA3__CSPI_SS1 */
-	IMX_PIN_REG(MX51_PAD_SD1_DATA3, 0x7b0, 0x3a8, 0, 0x000, 0), /* MX51_PAD_SD1_DATA3__SD1_DATA3 */
-	IMX_PIN_REG(MX51_PAD_GPIO1_0, 0x7b4, 0x3ac, 2, 0x924, 0), /* MX51_PAD_GPIO1_0__CSPI_SS2 */
-	IMX_PIN_REG(MX51_PAD_GPIO1_0, 0x7b4, 0x3ac, 1, 0x000, 0), /* MX51_PAD_GPIO1_0__GPIO1_0 */
-	IMX_PIN_REG(MX51_PAD_GPIO1_0, 0x7b4, 0x3ac, 0, 0x000, 0), /* MX51_PAD_GPIO1_0__SD1_CD */
-	IMX_PIN_REG(MX51_PAD_GPIO1_1, 0x7b8, 0x3b0, 2, 0x918, 2), /* MX51_PAD_GPIO1_1__CSPI_MISO */
-	IMX_PIN_REG(MX51_PAD_GPIO1_1, 0x7b8, 0x3b0, 1, 0x000, 0), /* MX51_PAD_GPIO1_1__GPIO1_1 */
-	IMX_PIN_REG(MX51_PAD_GPIO1_1, 0x7b8, 0x3b0, 0, 0x000, 0), /* MX51_PAD_GPIO1_1__SD1_WP */
-	IMX_PIN_REG(MX51_PAD_EIM_DA12, NO_PAD, 0x04c, 0, 0x000, 0), /* MX51_PAD_EIM_DA12__EIM_DA12 */
-	IMX_PIN_REG(MX51_PAD_EIM_DA13, NO_PAD, 0x050, 0, 0x000, 0), /* MX51_PAD_EIM_DA13__EIM_DA13 */
-	IMX_PIN_REG(MX51_PAD_EIM_DA14, NO_PAD, 0x054, 0, 0x000, 0), /* MX51_PAD_EIM_DA14__EIM_DA14 */
-	IMX_PIN_REG(MX51_PAD_EIM_DA15, NO_PAD, 0x058, 0, 0x000, 0), /* MX51_PAD_EIM_DA15__EIM_DA15 */
-	IMX_PIN_REG(MX51_PAD_SD2_CMD, 0x7bc, 0x3b4, 2, 0x91c, 3), /* MX51_PAD_SD2_CMD__CSPI_MOSI */
-	IMX_PIN_REG(MX51_PAD_SD2_CMD, 0x7bc, 0x3b4, 1, 0x9b0, 2), /* MX51_PAD_SD2_CMD__I2C1_SCL */
-	IMX_PIN_REG(MX51_PAD_SD2_CMD, 0x7bc, 0x3b4, 0, 0x000, 0), /* MX51_PAD_SD2_CMD__SD2_CMD */
-	IMX_PIN_REG(MX51_PAD_SD2_CLK, 0x7c0, 0x3b8, 2, 0x914, 3), /* MX51_PAD_SD2_CLK__CSPI_SCLK */
-	IMX_PIN_REG(MX51_PAD_SD2_CLK, 0x7c0, 0x3b8, 1, 0x9b4, 2), /* MX51_PAD_SD2_CLK__I2C1_SDA */
-	IMX_PIN_REG(MX51_PAD_SD2_CLK, 0x7c0, 0x3b8, 0, 0x000, 0), /* MX51_PAD_SD2_CLK__SD2_CLK */
-	IMX_PIN_REG(MX51_PAD_SD2_DATA0, 0x7c4, 0x3bc, 2, 0x918, 3), /* MX51_PAD_SD2_DATA0__CSPI_MISO */
-	IMX_PIN_REG(MX51_PAD_SD2_DATA0, 0x7c4, 0x3bc, 1, 0x000, 0), /* MX51_PAD_SD2_DATA0__SD1_DAT4 */
-	IMX_PIN_REG(MX51_PAD_SD2_DATA0, 0x7c4, 0x3bc, 0, 0x000, 0), /* MX51_PAD_SD2_DATA0__SD2_DATA0 */
-	IMX_PIN_REG(MX51_PAD_SD2_DATA1, 0x7c8, 0x3c0, 1, 0x000, 0), /* MX51_PAD_SD2_DATA1__SD1_DAT5 */
-	IMX_PIN_REG(MX51_PAD_SD2_DATA1, 0x7c8, 0x3c0, 0, 0x000, 0), /* MX51_PAD_SD2_DATA1__SD2_DATA1 */
-	IMX_PIN_REG(MX51_PAD_SD2_DATA1, 0x7c8, 0x3c0, 2, 0x000, 0), /* MX51_PAD_SD2_DATA1__USBH3_H2_DP */
-	IMX_PIN_REG(MX51_PAD_SD2_DATA2, 0x7cc, 0x3c4, 1, 0x000, 0), /* MX51_PAD_SD2_DATA2__SD1_DAT6 */
-	IMX_PIN_REG(MX51_PAD_SD2_DATA2, 0x7cc, 0x3c4, 0, 0x000, 0), /* MX51_PAD_SD2_DATA2__SD2_DATA2 */
-	IMX_PIN_REG(MX51_PAD_SD2_DATA2, 0x7cc, 0x3c4, 2, 0x000, 0), /* MX51_PAD_SD2_DATA2__USBH3_H2_DM */
-	IMX_PIN_REG(MX51_PAD_SD2_DATA3, 0x7d0, 0x3c8, 2, 0x924, 1), /* MX51_PAD_SD2_DATA3__CSPI_SS2 */
-	IMX_PIN_REG(MX51_PAD_SD2_DATA3, 0x7d0, 0x3c8, 1, 0x000, 0), /* MX51_PAD_SD2_DATA3__SD1_DAT7 */
-	IMX_PIN_REG(MX51_PAD_SD2_DATA3, 0x7d0, 0x3c8, 0, 0x000, 0), /* MX51_PAD_SD2_DATA3__SD2_DATA3 */
-	IMX_PIN_REG(MX51_PAD_GPIO1_2, 0x7d4, 0x3cc, 5, 0x000, 0), /* MX51_PAD_GPIO1_2__CCM_OUT_2 */
-	IMX_PIN_REG(MX51_PAD_GPIO1_2, 0x7d4, 0x3cc, 0, 0x000, 0), /* MX51_PAD_GPIO1_2__GPIO1_2 */
-	IMX_PIN_REG(MX51_PAD_GPIO1_2, 0x7d4, 0x3cc, 2, 0x9b8, 3), /* MX51_PAD_GPIO1_2__I2C2_SCL */
-	IMX_PIN_REG(MX51_PAD_GPIO1_2, 0x7d4, 0x3cc, 7, 0x90c, 1), /* MX51_PAD_GPIO1_2__PLL1_BYP */
-	IMX_PIN_REG(MX51_PAD_GPIO1_2, 0x7d4, 0x3cc, 1, 0x000, 0), /* MX51_PAD_GPIO1_2__PWM1_PWMO */
-	IMX_PIN_REG(MX51_PAD_GPIO1_3, 0x7d8, 0x3d0, 0, 0x000, 0), /* MX51_PAD_GPIO1_3__GPIO1_3 */
-	IMX_PIN_REG(MX51_PAD_GPIO1_3, 0x7d8, 0x3d0, 2, 0x9bc, 3), /* MX51_PAD_GPIO1_3__I2C2_SDA */
-	IMX_PIN_REG(MX51_PAD_GPIO1_3, 0x7d8, 0x3d0, 7, 0x910, 1), /* MX51_PAD_GPIO1_3__PLL2_BYP */
-	IMX_PIN_REG(MX51_PAD_GPIO1_3, 0x7d8, 0x3d0, 1, 0x000, 0), /* MX51_PAD_GPIO1_3__PWM2_PWMO */
-	IMX_PIN_REG(MX51_PAD_PMIC_INT_REQ, 0x7fc, 0x3d4, 0, 0x000, 0), /* MX51_PAD_PMIC_INT_REQ__PMIC_INT_REQ */
-	IMX_PIN_REG(MX51_PAD_PMIC_INT_REQ, 0x7fc, 0x3d4, 1, 0x000, 0), /* MX51_PAD_PMIC_INT_REQ__PMIC_PMU_IRQ_B */
-	IMX_PIN_REG(MX51_PAD_GPIO1_4, 0x804, 0x3d8, 4, 0x908, 1), /* MX51_PAD_GPIO1_4__DISP2_EXT_CLK */
-	IMX_PIN_REG(MX51_PAD_GPIO1_4, 0x804, 0x3d8, 3, 0x938, 1), /* MX51_PAD_GPIO1_4__EIM_RDY */
-	IMX_PIN_REG(MX51_PAD_GPIO1_4, 0x804, 0x3d8, 0, 0x000, 0), /* MX51_PAD_GPIO1_4__GPIO1_4 */
-	IMX_PIN_REG(MX51_PAD_GPIO1_4, 0x804, 0x3d8, 2, 0x000, 0), /* MX51_PAD_GPIO1_4__WDOG1_WDOG_B */
-	IMX_PIN_REG(MX51_PAD_GPIO1_5, 0x808, 0x3dc, 6, 0x000, 0), /* MX51_PAD_GPIO1_5__CSI2_MCLK */
-	IMX_PIN_REG(MX51_PAD_GPIO1_5, 0x808, 0x3dc, 3, 0x000, 0), /* MX51_PAD_GPIO1_5__DISP2_PIN16 */
-	IMX_PIN_REG(MX51_PAD_GPIO1_5, 0x808, 0x3dc, 0, 0x000, 0), /* MX51_PAD_GPIO1_5__GPIO1_5 */
-	IMX_PIN_REG(MX51_PAD_GPIO1_5, 0x808, 0x3dc, 2, 0x000, 0), /* MX51_PAD_GPIO1_5__WDOG2_WDOG_B */
-	IMX_PIN_REG(MX51_PAD_GPIO1_6, 0x80c, 0x3e0, 4, 0x000, 0), /* MX51_PAD_GPIO1_6__DISP2_PIN17 */
-	IMX_PIN_REG(MX51_PAD_GPIO1_6, 0x80c, 0x3e0, 0, 0x000, 0), /* MX51_PAD_GPIO1_6__GPIO1_6 */
-	IMX_PIN_REG(MX51_PAD_GPIO1_6, 0x80c, 0x3e0, 3, 0x000, 0), /* MX51_PAD_GPIO1_6__REF_EN_B */
-	IMX_PIN_REG(MX51_PAD_GPIO1_7, 0x810, 0x3e4, 3, 0x000, 0), /* MX51_PAD_GPIO1_7__CCM_OUT_0 */
-	IMX_PIN_REG(MX51_PAD_GPIO1_7, 0x810, 0x3e4, 0, 0x000, 0), /* MX51_PAD_GPIO1_7__GPIO1_7 */
-	IMX_PIN_REG(MX51_PAD_GPIO1_7, 0x810, 0x3e4, 6, 0x000, 0), /* MX51_PAD_GPIO1_7__SD2_WP */
-	IMX_PIN_REG(MX51_PAD_GPIO1_7, 0x810, 0x3e4, 2, 0x000, 0), /* MX51_PAD_GPIO1_7__SPDIF_OUT1 */
-	IMX_PIN_REG(MX51_PAD_GPIO1_8, 0x814, 0x3e8, 2, 0x99c, 2), /* MX51_PAD_GPIO1_8__CSI2_DATA_EN */
-	IMX_PIN_REG(MX51_PAD_GPIO1_8, 0x814, 0x3e8, 0, 0x000, 0), /* MX51_PAD_GPIO1_8__GPIO1_8 */
-	IMX_PIN_REG(MX51_PAD_GPIO1_8, 0x814, 0x3e8, 6, 0x000, 0), /* MX51_PAD_GPIO1_8__SD2_CD */
-	IMX_PIN_REG(MX51_PAD_GPIO1_8, 0x814, 0x3e8, 1, 0x000, 0), /* MX51_PAD_GPIO1_8__USBH3_PWR */
-	IMX_PIN_REG(MX51_PAD_GPIO1_9, 0x818, 0x3ec, 3, 0x000, 0), /* MX51_PAD_GPIO1_9__CCM_OUT_1 */
-	IMX_PIN_REG(MX51_PAD_GPIO1_9, 0x818, 0x3ec, 2, 0x000, 0), /* MX51_PAD_GPIO1_9__DISP2_D1_CS */
-	IMX_PIN_REG(MX51_PAD_GPIO1_9, 0x818, 0x3ec, 7, 0x000, 0), /* MX51_PAD_GPIO1_9__DISP2_SER_CS */
-	IMX_PIN_REG(MX51_PAD_GPIO1_9, 0x818, 0x3ec, 0, 0x000, 0), /* MX51_PAD_GPIO1_9__GPIO1_9 */
-	IMX_PIN_REG(MX51_PAD_GPIO1_9, 0x818, 0x3ec, 6, 0x000, 0), /* MX51_PAD_GPIO1_9__SD2_LCTL */
-	IMX_PIN_REG(MX51_PAD_GPIO1_9, 0x818, 0x3ec, 1, 0x000, 0), /* MX51_PAD_GPIO1_9__USBH3_OC */
+	MX51_PAD_EIM_DA0 = 7,
+	MX51_PAD_EIM_DA1 = 8,
+	MX51_PAD_EIM_DA2 = 9,
+	MX51_PAD_EIM_DA3 = 10,
+	MX51_PAD_EIM_DA4 = 11,
+	MX51_PAD_EIM_DA5 = 12,
+	MX51_PAD_EIM_DA6 = 13,
+	MX51_PAD_EIM_DA7 = 14,
+	MX51_PAD_EIM_DA8 = 15,
+	MX51_PAD_EIM_DA9 = 16,
+	MX51_PAD_EIM_DA10 = 17,
+	MX51_PAD_EIM_DA11 = 18,
+	MX51_PAD_EIM_DA12 = 19,
+	MX51_PAD_EIM_DA13 = 20,
+	MX51_PAD_EIM_DA14 = 21,
+	MX51_PAD_EIM_DA15 = 22,
+	MX51_PAD_EIM_D16 = 23,
+	MX51_PAD_EIM_D17 = 24,
+	MX51_PAD_EIM_D18 = 25,
+	MX51_PAD_EIM_D19 = 26,
+	MX51_PAD_EIM_D20 = 27,
+	MX51_PAD_EIM_D21 = 28,
+	MX51_PAD_EIM_D22 = 29,
+	MX51_PAD_EIM_D23 = 30,
+	MX51_PAD_EIM_D24 = 31,
+	MX51_PAD_EIM_D25 = 32,
+	MX51_PAD_EIM_D26 = 33,
+	MX51_PAD_EIM_D27 = 34,
+	MX51_PAD_EIM_D28 = 35,
+	MX51_PAD_EIM_D29 = 36,
+	MX51_PAD_EIM_D30 = 37,
+	MX51_PAD_EIM_D31 = 38,
+	MX51_PAD_EIM_A16 = 39,
+	MX51_PAD_EIM_A17 = 40,
+	MX51_PAD_EIM_A18 = 41,
+	MX51_PAD_EIM_A19 = 42,
+	MX51_PAD_EIM_A20 = 43,
+	MX51_PAD_EIM_A21 = 44,
+	MX51_PAD_EIM_A22 = 45,
+	MX51_PAD_EIM_A23 = 46,
+	MX51_PAD_EIM_A24 = 47,
+	MX51_PAD_EIM_A25 = 48,
+	MX51_PAD_EIM_A26 = 49,
+	MX51_PAD_EIM_A27 = 50,
+	MX51_PAD_EIM_EB0 = 51,
+	MX51_PAD_EIM_EB1 = 52,
+	MX51_PAD_EIM_EB2 = 53,
+	MX51_PAD_EIM_EB3 = 54,
+	MX51_PAD_EIM_OE = 55,
+	MX51_PAD_EIM_CS0 = 56,
+	MX51_PAD_EIM_CS1 = 57,
+	MX51_PAD_EIM_CS2 = 58,
+	MX51_PAD_EIM_CS3 = 59,
+	MX51_PAD_EIM_CS4 = 60,
+	MX51_PAD_EIM_CS5 = 61,
+	MX51_PAD_EIM_DTACK = 62,
+	MX51_PAD_EIM_LBA = 63,
+	MX51_PAD_EIM_CRE = 64,
+	MX51_PAD_DRAM_CS1 = 65,
+	MX51_PAD_NANDF_WE_B = 66,
+	MX51_PAD_NANDF_RE_B = 67,
+	MX51_PAD_NANDF_ALE = 68,
+	MX51_PAD_NANDF_CLE = 69,
+	MX51_PAD_NANDF_WP_B = 70,
+	MX51_PAD_NANDF_RB0 = 71,
+	MX51_PAD_NANDF_RB1 = 72,
+	MX51_PAD_NANDF_RB2 = 73,
+	MX51_PAD_NANDF_RB3 = 74,
+	MX51_PAD_GPIO_NAND = 75,
+	MX51_PAD_NANDF_CS0 = 76,
+	MX51_PAD_NANDF_CS1 = 77,
+	MX51_PAD_NANDF_CS2 = 78,
+	MX51_PAD_NANDF_CS3 = 79,
+	MX51_PAD_NANDF_CS4 = 80,
+	MX51_PAD_NANDF_CS5 = 81,
+	MX51_PAD_NANDF_CS6 = 82,
+	MX51_PAD_NANDF_CS7 = 83,
+	MX51_PAD_NANDF_RDY_INT = 84,
+	MX51_PAD_NANDF_D15 = 85,
+	MX51_PAD_NANDF_D14 = 86,
+	MX51_PAD_NANDF_D13 = 87,
+	MX51_PAD_NANDF_D12 = 88,
+	MX51_PAD_NANDF_D11 = 89,
+	MX51_PAD_NANDF_D10 = 90,
+	MX51_PAD_NANDF_D9 = 91,
+	MX51_PAD_NANDF_D8 = 92,
+	MX51_PAD_NANDF_D7 = 93,
+	MX51_PAD_NANDF_D6 = 94,
+	MX51_PAD_NANDF_D5 = 95,
+	MX51_PAD_NANDF_D4 = 96,
+	MX51_PAD_NANDF_D3 = 97,
+	MX51_PAD_NANDF_D2 = 98,
+	MX51_PAD_NANDF_D1 = 99,
+	MX51_PAD_NANDF_D0 = 100,
+	MX51_PAD_CSI1_D8 = 101,
+	MX51_PAD_CSI1_D9 = 102,
+	MX51_PAD_CSI1_D10 = 103,
+	MX51_PAD_CSI1_D11 = 104,
+	MX51_PAD_CSI1_D12 = 105,
+	MX51_PAD_CSI1_D13 = 106,
+	MX51_PAD_CSI1_D14 = 107,
+	MX51_PAD_CSI1_D15 = 108,
+	MX51_PAD_CSI1_D16 = 109,
+	MX51_PAD_CSI1_D17 = 110,
+	MX51_PAD_CSI1_D18 = 111,
+	MX51_PAD_CSI1_D19 = 112,
+	MX51_PAD_CSI1_VSYNC = 113,
+	MX51_PAD_CSI1_HSYNC = 114,
+	MX51_PAD_CSI2_D12 = 115,
+	MX51_PAD_CSI2_D13 = 116,
+	MX51_PAD_CSI2_D14 = 117,
+	MX51_PAD_CSI2_D15 = 118,
+	MX51_PAD_CSI2_D16 = 119,
+	MX51_PAD_CSI2_D17 = 120,
+	MX51_PAD_CSI2_D18 = 121,
+	MX51_PAD_CSI2_D19 = 122,
+	MX51_PAD_CSI2_VSYNC = 123,
+	MX51_PAD_CSI2_HSYNC = 124,
+	MX51_PAD_CSI2_PIXCLK = 125,
+	MX51_PAD_I2C1_CLK = 126,
+	MX51_PAD_I2C1_DAT = 127,
+	MX51_PAD_AUD3_BB_TXD = 128,
+	MX51_PAD_AUD3_BB_RXD = 129,
+	MX51_PAD_AUD3_BB_CK = 130,
+	MX51_PAD_AUD3_BB_FS = 131,
+	MX51_PAD_CSPI1_MOSI = 132,
+	MX51_PAD_CSPI1_MISO = 133,
+	MX51_PAD_CSPI1_SS0 = 134,
+	MX51_PAD_CSPI1_SS1 = 135,
+	MX51_PAD_CSPI1_RDY = 136,
+	MX51_PAD_CSPI1_SCLK = 137,
+	MX51_PAD_UART1_RXD = 138,
+	MX51_PAD_UART1_TXD = 139,
+	MX51_PAD_UART1_RTS = 140,
+	MX51_PAD_UART1_CTS = 141,
+	MX51_PAD_UART2_RXD = 142,
+	MX51_PAD_UART2_TXD = 143,
+	MX51_PAD_UART3_RXD = 144,
+	MX51_PAD_UART3_TXD = 145,
+	MX51_PAD_OWIRE_LINE = 146,
+	MX51_PAD_KEY_ROW0 = 147,
+	MX51_PAD_KEY_ROW1 = 148,
+	MX51_PAD_KEY_ROW2 = 149,
+	MX51_PAD_KEY_ROW3 = 150,
+	MX51_PAD_KEY_COL0 = 151,
+	MX51_PAD_KEY_COL1 = 152,
+	MX51_PAD_KEY_COL2 = 153,
+	MX51_PAD_KEY_COL3 = 154,
+	MX51_PAD_KEY_COL4 = 155,
+	MX51_PAD_KEY_COL5 = 156,
+	MX51_PAD_USBH1_CLK = 158,
+	MX51_PAD_USBH1_DIR = 159,
+	MX51_PAD_USBH1_STP = 160,
+	MX51_PAD_USBH1_NXT = 161,
+	MX51_PAD_USBH1_DATA0 = 162,
+	MX51_PAD_USBH1_DATA1 = 163,
+	MX51_PAD_USBH1_DATA2 = 164,
+	MX51_PAD_USBH1_DATA3 = 165,
+	MX51_PAD_USBH1_DATA4 = 166,
+	MX51_PAD_USBH1_DATA5 = 167,
+	MX51_PAD_USBH1_DATA6 = 168,
+	MX51_PAD_USBH1_DATA7 = 169,
+	MX51_PAD_DI1_PIN11 = 170,
+	MX51_PAD_DI1_PIN12 = 171,
+	MX51_PAD_DI1_PIN13 = 172,
+	MX51_PAD_DI1_D0_CS = 173,
+	MX51_PAD_DI1_D1_CS = 174,
+	MX51_PAD_DISPB2_SER_DIN = 175,
+	MX51_PAD_DISPB2_SER_DIO = 176,
+	MX51_PAD_DISPB2_SER_CLK = 177,
+	MX51_PAD_DISPB2_SER_RS = 178,
+	MX51_PAD_DISP1_DAT0 = 179,
+	MX51_PAD_DISP1_DAT1 = 180,
+	MX51_PAD_DISP1_DAT2 = 181,
+	MX51_PAD_DISP1_DAT3 = 182,
+	MX51_PAD_DISP1_DAT4 = 183,
+	MX51_PAD_DISP1_DAT5 = 184,
+	MX51_PAD_DISP1_DAT6 = 185,
+	MX51_PAD_DISP1_DAT7 = 186,
+	MX51_PAD_DISP1_DAT8 = 187,
+	MX51_PAD_DISP1_DAT9 = 188,
+	MX51_PAD_DISP1_DAT10 = 189,
+	MX51_PAD_DISP1_DAT11 = 190,
+	MX51_PAD_DISP1_DAT12 = 191,
+	MX51_PAD_DISP1_DAT13 = 192,
+	MX51_PAD_DISP1_DAT14 = 193,
+	MX51_PAD_DISP1_DAT15 = 194,
+	MX51_PAD_DISP1_DAT16 = 195,
+	MX51_PAD_DISP1_DAT17 = 196,
+	MX51_PAD_DISP1_DAT18 = 197,
+	MX51_PAD_DISP1_DAT19 = 198,
+	MX51_PAD_DISP1_DAT20 = 199,
+	MX51_PAD_DISP1_DAT21 = 200,
+	MX51_PAD_DISP1_DAT22 = 201,
+	MX51_PAD_DISP1_DAT23 = 202,
+	MX51_PAD_DI1_PIN3 = 203,
+	MX51_PAD_DI1_PIN2 = 204,
+	MX51_PAD_DI_GP2 = 206,
+	MX51_PAD_DI_GP3 = 207,
+	MX51_PAD_DI2_PIN4 = 208,
+	MX51_PAD_DI2_PIN2 = 209,
+	MX51_PAD_DI2_PIN3 = 210,
+	MX51_PAD_DI2_DISP_CLK = 211,
+	MX51_PAD_DI_GP4 = 212,
+	MX51_PAD_DISP2_DAT0 = 213,
+	MX51_PAD_DISP2_DAT1 = 214,
+	MX51_PAD_DISP2_DAT2 = 215,
+	MX51_PAD_DISP2_DAT3 = 216,
+	MX51_PAD_DISP2_DAT4 = 217,
+	MX51_PAD_DISP2_DAT5 = 218,
+	MX51_PAD_DISP2_DAT6 = 219,
+	MX51_PAD_DISP2_DAT7 = 220,
+	MX51_PAD_DISP2_DAT8 = 221,
+	MX51_PAD_DISP2_DAT9 = 222,
+	MX51_PAD_DISP2_DAT10 = 223,
+	MX51_PAD_DISP2_DAT11 = 224,
+	MX51_PAD_DISP2_DAT12 = 225,
+	MX51_PAD_DISP2_DAT13 = 226,
+	MX51_PAD_DISP2_DAT14 = 227,
+	MX51_PAD_DISP2_DAT15 = 228,
+	MX51_PAD_SD1_CMD = 229,
+	MX51_PAD_SD1_CLK = 230,
+	MX51_PAD_SD1_DATA0 = 231,
+	MX51_PAD_SD1_DATA1 = 232,
+	MX51_PAD_SD1_DATA2 = 233,
+	MX51_PAD_SD1_DATA3 = 234,
+	MX51_PAD_GPIO1_0 = 235,
+	MX51_PAD_GPIO1_1 = 236,
+	MX51_PAD_SD2_CMD = 237,
+	MX51_PAD_SD2_CLK = 238,
+	MX51_PAD_SD2_DATA0 = 239,
+	MX51_PAD_SD2_DATA1 = 240,
+	MX51_PAD_SD2_DATA2 = 241,
+	MX51_PAD_SD2_DATA3 = 242,
+	MX51_PAD_GPIO1_2 = 243,
+	MX51_PAD_GPIO1_3 = 244,
+	MX51_PAD_PMIC_INT_REQ = 245,
+	MX51_PAD_GPIO1_4 = 246,
+	MX51_PAD_GPIO1_5 = 247,
+	MX51_PAD_GPIO1_6 = 248,
+	MX51_PAD_GPIO1_7 = 249,
+	MX51_PAD_GPIO1_8 = 250,
+	MX51_PAD_GPIO1_9 = 251,
+	MX51_PAD_CSI1_PIXCLK = 365,
+	MX51_PAD_CSI1_MCLK = 366,
 };
 
 /* Pad names for the pinmux subsystem */
@@ -1282,8 +522,6 @@ static const struct pinctrl_pin_desc imx51_pinctrl_pads[] = {
 static struct imx_pinctrl_soc_info imx51_pinctrl_info = {
 	.pins = imx51_pinctrl_pads,
 	.npins = ARRAY_SIZE(imx51_pinctrl_pads),
-	.pin_regs = imx51_pin_regs,
-	.npin_regs = ARRAY_SIZE(imx51_pin_regs),
 };
 
 static struct of_device_id imx51_pinctrl_of_match[] = {
diff --git a/drivers/pinctrl/pinctrl-imx53.c b/drivers/pinctrl/pinctrl-imx53.c
index 2c9c8e2..30ac5c9 100644
--- a/drivers/pinctrl/pinctrl-imx53.c
+++ b/drivers/pinctrl/pinctrl-imx53.c
@@ -23,1382 +23,207 @@
 #include "pinctrl-imx.h"
 
 enum imx53_pads {
-	MX53_PAD_GPIO_19 = 0,
-	MX53_PAD_KEY_COL0 = 1,
-	MX53_PAD_KEY_ROW0 = 2,
-	MX53_PAD_KEY_COL1 = 3,
-	MX53_PAD_KEY_ROW1 = 4,
-	MX53_PAD_KEY_COL2 = 5,
-	MX53_PAD_KEY_ROW2 = 6,
-	MX53_PAD_KEY_COL3 = 7,
-	MX53_PAD_KEY_ROW3 = 8,
-	MX53_PAD_KEY_COL4 = 9,
-	MX53_PAD_KEY_ROW4 = 10,
-	MX53_PAD_DI0_DISP_CLK = 11,
-	MX53_PAD_DI0_PIN15 = 12,
-	MX53_PAD_DI0_PIN2 = 13,
-	MX53_PAD_DI0_PIN3 = 14,
-	MX53_PAD_DI0_PIN4 = 15,
-	MX53_PAD_DISP0_DAT0 = 16,
-	MX53_PAD_DISP0_DAT1 = 17,
-	MX53_PAD_DISP0_DAT2 = 18,
-	MX53_PAD_DISP0_DAT3 = 19,
-	MX53_PAD_DISP0_DAT4 = 20,
-	MX53_PAD_DISP0_DAT5 = 21,
-	MX53_PAD_DISP0_DAT6 = 22,
-	MX53_PAD_DISP0_DAT7 = 23,
-	MX53_PAD_DISP0_DAT8 = 24,
-	MX53_PAD_DISP0_DAT9 = 25,
-	MX53_PAD_DISP0_DAT10 = 26,
-	MX53_PAD_DISP0_DAT11 = 27,
-	MX53_PAD_DISP0_DAT12 = 28,
-	MX53_PAD_DISP0_DAT13 = 29,
-	MX53_PAD_DISP0_DAT14 = 30,
-	MX53_PAD_DISP0_DAT15 = 31,
-	MX53_PAD_DISP0_DAT16 = 32,
-	MX53_PAD_DISP0_DAT17 = 33,
-	MX53_PAD_DISP0_DAT18 = 34,
-	MX53_PAD_DISP0_DAT19 = 35,
-	MX53_PAD_DISP0_DAT20 = 36,
-	MX53_PAD_DISP0_DAT21 = 37,
-	MX53_PAD_DISP0_DAT22 = 38,
-	MX53_PAD_DISP0_DAT23 = 39,
-	MX53_PAD_CSI0_PIXCLK = 40,
-	MX53_PAD_CSI0_MCLK = 41,
-	MX53_PAD_CSI0_DATA_EN = 42,
-	MX53_PAD_CSI0_VSYNC = 43,
-	MX53_PAD_CSI0_DAT4 = 44,
-	MX53_PAD_CSI0_DAT5 = 45,
-	MX53_PAD_CSI0_DAT6 = 46,
-	MX53_PAD_CSI0_DAT7 = 47,
-	MX53_PAD_CSI0_DAT8 = 48,
-	MX53_PAD_CSI0_DAT9 = 49,
-	MX53_PAD_CSI0_DAT10 = 50,
-	MX53_PAD_CSI0_DAT11 = 51,
-	MX53_PAD_CSI0_DAT12 = 52,
-	MX53_PAD_CSI0_DAT13 = 53,
-	MX53_PAD_CSI0_DAT14 = 54,
-	MX53_PAD_CSI0_DAT15 = 55,
-	MX53_PAD_CSI0_DAT16 = 56,
-	MX53_PAD_CSI0_DAT17 = 57,
-	MX53_PAD_CSI0_DAT18 = 58,
-	MX53_PAD_CSI0_DAT19 = 59,
-	MX53_PAD_EIM_A25 = 60,
-	MX53_PAD_EIM_EB2 = 61,
-	MX53_PAD_EIM_D16 = 62,
-	MX53_PAD_EIM_D17 = 63,
-	MX53_PAD_EIM_D18 = 64,
-	MX53_PAD_EIM_D19 = 65,
-	MX53_PAD_EIM_D20 = 66,
-	MX53_PAD_EIM_D21 = 67,
-	MX53_PAD_EIM_D22 = 68,
-	MX53_PAD_EIM_D23 = 69,
-	MX53_PAD_EIM_EB3 = 70,
-	MX53_PAD_EIM_D24 = 71,
-	MX53_PAD_EIM_D25 = 72,
-	MX53_PAD_EIM_D26 = 73,
-	MX53_PAD_EIM_D27 = 74,
-	MX53_PAD_EIM_D28 = 75,
-	MX53_PAD_EIM_D29 = 76,
-	MX53_PAD_EIM_D30 = 77,
-	MX53_PAD_EIM_D31 = 78,
-	MX53_PAD_EIM_A24 = 79,
-	MX53_PAD_EIM_A23 = 80,
-	MX53_PAD_EIM_A22 = 81,
-	MX53_PAD_EIM_A21 = 82,
-	MX53_PAD_EIM_A20 = 83,
-	MX53_PAD_EIM_A19 = 84,
-	MX53_PAD_EIM_A18 = 85,
-	MX53_PAD_EIM_A17 = 86,
-	MX53_PAD_EIM_A16 = 87,
-	MX53_PAD_EIM_CS0 = 88,
-	MX53_PAD_EIM_CS1 = 89,
-	MX53_PAD_EIM_OE = 90,
-	MX53_PAD_EIM_RW = 91,
-	MX53_PAD_EIM_LBA = 92,
-	MX53_PAD_EIM_EB0 = 93,
-	MX53_PAD_EIM_EB1 = 94,
-	MX53_PAD_EIM_DA0 = 95,
-	MX53_PAD_EIM_DA1 = 96,
-	MX53_PAD_EIM_DA2 = 97,
-	MX53_PAD_EIM_DA3 = 98,
-	MX53_PAD_EIM_DA4 = 99,
-	MX53_PAD_EIM_DA5 = 100,
-	MX53_PAD_EIM_DA6 = 101,
-	MX53_PAD_EIM_DA7 = 102,
-	MX53_PAD_EIM_DA8 = 103,
-	MX53_PAD_EIM_DA9 = 104,
-	MX53_PAD_EIM_DA10 = 105,
-	MX53_PAD_EIM_DA11 = 106,
-	MX53_PAD_EIM_DA12 = 107,
-	MX53_PAD_EIM_DA13 = 108,
-	MX53_PAD_EIM_DA14 = 109,
-	MX53_PAD_EIM_DA15 = 110,
-	MX53_PAD_NANDF_WE_B = 111,
-	MX53_PAD_NANDF_RE_B = 112,
-	MX53_PAD_EIM_WAIT = 113,
-	MX53_PAD_LVDS1_TX3_P = 114,
-	MX53_PAD_LVDS1_TX2_P = 115,
-	MX53_PAD_LVDS1_CLK_P = 116,
-	MX53_PAD_LVDS1_TX1_P = 117,
-	MX53_PAD_LVDS1_TX0_P = 118,
-	MX53_PAD_LVDS0_TX3_P = 119,
-	MX53_PAD_LVDS0_CLK_P = 120,
-	MX53_PAD_LVDS0_TX2_P = 121,
-	MX53_PAD_LVDS0_TX1_P = 122,
-	MX53_PAD_LVDS0_TX0_P = 123,
-	MX53_PAD_GPIO_10 = 124,
-	MX53_PAD_GPIO_11 = 125,
-	MX53_PAD_GPIO_12 = 126,
-	MX53_PAD_GPIO_13 = 127,
-	MX53_PAD_GPIO_14 = 128,
-	MX53_PAD_NANDF_CLE = 129,
-	MX53_PAD_NANDF_ALE = 130,
-	MX53_PAD_NANDF_WP_B = 131,
-	MX53_PAD_NANDF_RB0 = 132,
-	MX53_PAD_NANDF_CS0 = 133,
-	MX53_PAD_NANDF_CS1 = 134,
-	MX53_PAD_NANDF_CS2 = 135,
-	MX53_PAD_NANDF_CS3 = 136,
-	MX53_PAD_FEC_MDIO = 137,
-	MX53_PAD_FEC_REF_CLK = 138,
-	MX53_PAD_FEC_RX_ER = 139,
-	MX53_PAD_FEC_CRS_DV = 140,
-	MX53_PAD_FEC_RXD1 = 141,
-	MX53_PAD_FEC_RXD0 = 142,
-	MX53_PAD_FEC_TX_EN = 143,
-	MX53_PAD_FEC_TXD1 = 144,
-	MX53_PAD_FEC_TXD0 = 145,
-	MX53_PAD_FEC_MDC = 146,
-	MX53_PAD_PATA_DIOW = 147,
-	MX53_PAD_PATA_DMACK = 148,
-	MX53_PAD_PATA_DMARQ = 149,
-	MX53_PAD_PATA_BUFFER_EN = 150,
-	MX53_PAD_PATA_INTRQ = 151,
-	MX53_PAD_PATA_DIOR = 152,
-	MX53_PAD_PATA_RESET_B = 153,
-	MX53_PAD_PATA_IORDY = 154,
-	MX53_PAD_PATA_DA_0 = 155,
-	MX53_PAD_PATA_DA_1 = 156,
-	MX53_PAD_PATA_DA_2 = 157,
-	MX53_PAD_PATA_CS_0 = 158,
-	MX53_PAD_PATA_CS_1 = 159,
-	MX53_PAD_PATA_DATA0 = 160,
-	MX53_PAD_PATA_DATA1 = 161,
-	MX53_PAD_PATA_DATA2 = 162,
-	MX53_PAD_PATA_DATA3 = 163,
-	MX53_PAD_PATA_DATA4 = 164,
-	MX53_PAD_PATA_DATA5 = 165,
-	MX53_PAD_PATA_DATA6 = 166,
-	MX53_PAD_PATA_DATA7 = 167,
-	MX53_PAD_PATA_DATA8 = 168,
-	MX53_PAD_PATA_DATA9 = 169,
-	MX53_PAD_PATA_DATA10 = 170,
-	MX53_PAD_PATA_DATA11 = 171,
-	MX53_PAD_PATA_DATA12 = 172,
-	MX53_PAD_PATA_DATA13 = 173,
-	MX53_PAD_PATA_DATA14 = 174,
-	MX53_PAD_PATA_DATA15 = 175,
-	MX53_PAD_SD1_DATA0 = 176,
-	MX53_PAD_SD1_DATA1 = 177,
-	MX53_PAD_SD1_CMD = 178,
-	MX53_PAD_SD1_DATA2 = 179,
-	MX53_PAD_SD1_CLK = 180,
-	MX53_PAD_SD1_DATA3 = 181,
-	MX53_PAD_SD2_CLK = 182,
-	MX53_PAD_SD2_CMD = 183,
-	MX53_PAD_SD2_DATA3 = 184,
-	MX53_PAD_SD2_DATA2 = 185,
-	MX53_PAD_SD2_DATA1 = 186,
-	MX53_PAD_SD2_DATA0 = 187,
-	MX53_PAD_GPIO_0 = 188,
-	MX53_PAD_GPIO_1 = 189,
-	MX53_PAD_GPIO_9 = 190,
-	MX53_PAD_GPIO_3 = 191,
-	MX53_PAD_GPIO_6 = 192,
-	MX53_PAD_GPIO_2 = 193,
-	MX53_PAD_GPIO_4 = 194,
-	MX53_PAD_GPIO_5 = 195,
-	MX53_PAD_GPIO_7 = 196,
-	MX53_PAD_GPIO_8 = 197,
-	MX53_PAD_GPIO_16 = 198,
-	MX53_PAD_GPIO_17 = 199,
-	MX53_PAD_GPIO_18 = 200,
-};
-
-/* imx53 register maps */
-static struct imx_pin_reg imx53_pin_regs[] = {
-	IMX_PIN_REG(MX53_PAD_GPIO_19, 0x348, 0x020, 0, 0x840, 0), /* MX53_PAD_GPIO_19__KPP_COL_5 */
-	IMX_PIN_REG(MX53_PAD_GPIO_19, 0x348, 0x020, 1, 0x000, 0), /* MX53_PAD_GPIO_19__GPIO4_5 */
-	IMX_PIN_REG(MX53_PAD_GPIO_19, 0x348, 0x020, 2, 0x000, 0), /* MX53_PAD_GPIO_19__CCM_CLKO */
-	IMX_PIN_REG(MX53_PAD_GPIO_19, 0x348, 0x020, 3, 0x000, 0), /* MX53_PAD_GPIO_19__SPDIF_OUT1 */
-	IMX_PIN_REG(MX53_PAD_GPIO_19, 0x348, 0x020, 4, 0x000, 0), /* MX53_PAD_GPIO_19__RTC_CE_RTC_EXT_TRIG2 */
-	IMX_PIN_REG(MX53_PAD_GPIO_19, 0x348, 0x020, 5, 0x000, 0), /* MX53_PAD_GPIO_19__ECSPI1_RDY */
-	IMX_PIN_REG(MX53_PAD_GPIO_19, 0x348, 0x020, 6, 0x000, 0), /* MX53_PAD_GPIO_19__FEC_TDATA_3 */
-	IMX_PIN_REG(MX53_PAD_GPIO_19, 0x348, 0x020, 7, 0x000, 0), /* MX53_PAD_GPIO_19__SRC_INT_BOOT */
-	IMX_PIN_REG(MX53_PAD_KEY_COL0, 0x34C, 0x024, 0, 0x000, 0), /* MX53_PAD_KEY_COL0__KPP_COL_0 */
-	IMX_PIN_REG(MX53_PAD_KEY_COL0, 0x34C, 0x024, 1, 0x000, 0), /* MX53_PAD_KEY_COL0__GPIO4_6 */
-	IMX_PIN_REG(MX53_PAD_KEY_COL0, 0x34C, 0x024, 2, 0x758, 0), /* MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC */
-	IMX_PIN_REG(MX53_PAD_KEY_COL0, 0x34C, 0x024, 4, 0x000, 0), /* MX53_PAD_KEY_COL0__UART4_TXD_MUX */
-	IMX_PIN_REG(MX53_PAD_KEY_COL0, 0x34C, 0x024, 5, 0x79C, 0), /* MX53_PAD_KEY_COL0__ECSPI1_SCLK */
-	IMX_PIN_REG(MX53_PAD_KEY_COL0, 0x34C, 0x024, 6, 0x000, 0), /* MX53_PAD_KEY_COL0__FEC_RDATA_3 */
-	IMX_PIN_REG(MX53_PAD_KEY_COL0, 0x34C, 0x024, 7, 0x000, 0), /* MX53_PAD_KEY_COL0__SRC_ANY_PU_RST */
-	IMX_PIN_REG(MX53_PAD_KEY_ROW0, 0x350, 0x028, 0, 0x000, 0), /* MX53_PAD_KEY_ROW0__KPP_ROW_0 */
-	IMX_PIN_REG(MX53_PAD_KEY_ROW0, 0x350, 0x028, 1, 0x000, 0), /* MX53_PAD_KEY_ROW0__GPIO4_7 */
-	IMX_PIN_REG(MX53_PAD_KEY_ROW0, 0x350, 0x028, 2, 0x74C, 0), /* MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD */
-	IMX_PIN_REG(MX53_PAD_KEY_ROW0, 0x350, 0x028, 4, 0x890, 1), /* MX53_PAD_KEY_ROW0__UART4_RXD_MUX */
-	IMX_PIN_REG(MX53_PAD_KEY_ROW0, 0x350, 0x028, 5, 0x7A4, 0), /* MX53_PAD_KEY_ROW0__ECSPI1_MOSI */
-	IMX_PIN_REG(MX53_PAD_KEY_ROW0, 0x350, 0x028, 6, 0x000, 0), /* MX53_PAD_KEY_ROW0__FEC_TX_ER */
-	IMX_PIN_REG(MX53_PAD_KEY_COL1, 0x354, 0x02C, 0, 0x000, 0), /* MX53_PAD_KEY_COL1__KPP_COL_1 */
-	IMX_PIN_REG(MX53_PAD_KEY_COL1, 0x354, 0x02C, 1, 0x000, 0), /* MX53_PAD_KEY_COL1__GPIO4_8 */
-	IMX_PIN_REG(MX53_PAD_KEY_COL1, 0x354, 0x02C, 2, 0x75C, 0), /* MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS */
-	IMX_PIN_REG(MX53_PAD_KEY_COL1, 0x354, 0x02C, 4, 0x000, 0), /* MX53_PAD_KEY_COL1__UART5_TXD_MUX */
-	IMX_PIN_REG(MX53_PAD_KEY_COL1, 0x354, 0x02C, 5, 0x7A0, 0), /* MX53_PAD_KEY_COL1__ECSPI1_MISO */
-	IMX_PIN_REG(MX53_PAD_KEY_COL1, 0x354, 0x02C, 6, 0x808, 0), /* MX53_PAD_KEY_COL1__FEC_RX_CLK */
-	IMX_PIN_REG(MX53_PAD_KEY_COL1, 0x354, 0x02C, 7, 0x000, 0), /* MX53_PAD_KEY_COL1__USBPHY1_TXREADY */
-	IMX_PIN_REG(MX53_PAD_KEY_ROW1, 0x358, 0x030, 0, 0x000, 0), /* MX53_PAD_KEY_ROW1__KPP_ROW_1 */
-	IMX_PIN_REG(MX53_PAD_KEY_ROW1, 0x358, 0x030, 1, 0x000, 0), /* MX53_PAD_KEY_ROW1__GPIO4_9 */
-	IMX_PIN_REG(MX53_PAD_KEY_ROW1, 0x358, 0x030, 2, 0x748, 0), /* MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD */
-	IMX_PIN_REG(MX53_PAD_KEY_ROW1, 0x358, 0x030, 4, 0x898, 1), /* MX53_PAD_KEY_ROW1__UART5_RXD_MUX */
-	IMX_PIN_REG(MX53_PAD_KEY_ROW1, 0x358, 0x030, 5, 0x7A8, 0), /* MX53_PAD_KEY_ROW1__ECSPI1_SS0 */
-	IMX_PIN_REG(MX53_PAD_KEY_ROW1, 0x358, 0x030, 6, 0x800, 0), /* MX53_PAD_KEY_ROW1__FEC_COL */
-	IMX_PIN_REG(MX53_PAD_KEY_ROW1, 0x358, 0x030, 7, 0x000, 0), /* MX53_PAD_KEY_ROW1__USBPHY1_RXVALID */
-	IMX_PIN_REG(MX53_PAD_KEY_COL2, 0x35C, 0x034, 0, 0x000, 0), /* MX53_PAD_KEY_COL2__KPP_COL_2 */
-	IMX_PIN_REG(MX53_PAD_KEY_COL2, 0x35C, 0x034, 1, 0x000, 0), /* MX53_PAD_KEY_COL2__GPIO4_10 */
-	IMX_PIN_REG(MX53_PAD_KEY_COL2, 0x35C, 0x034, 2, 0x000, 0), /* MX53_PAD_KEY_COL2__CAN1_TXCAN */
-	IMX_PIN_REG(MX53_PAD_KEY_COL2, 0x35C, 0x034, 4, 0x804, 0), /* MX53_PAD_KEY_COL2__FEC_MDIO */
-	IMX_PIN_REG(MX53_PAD_KEY_COL2, 0x35C, 0x034, 5, 0x7AC, 0), /* MX53_PAD_KEY_COL2__ECSPI1_SS1 */
-	IMX_PIN_REG(MX53_PAD_KEY_COL2, 0x35C, 0x034, 6, 0x000, 0), /* MX53_PAD_KEY_COL2__FEC_RDATA_2 */
-	IMX_PIN_REG(MX53_PAD_KEY_COL2, 0x35C, 0x034, 7, 0x000, 0), /* MX53_PAD_KEY_COL2__USBPHY1_RXACTIVE */
-	IMX_PIN_REG(MX53_PAD_KEY_ROW2, 0x360, 0x038, 0, 0x000, 0), /* MX53_PAD_KEY_ROW2__KPP_ROW_2 */
-	IMX_PIN_REG(MX53_PAD_KEY_ROW2, 0x360, 0x038, 1, 0x000, 0), /* MX53_PAD_KEY_ROW2__GPIO4_11 */
-	IMX_PIN_REG(MX53_PAD_KEY_ROW2, 0x360, 0x038, 2, 0x760, 0), /* MX53_PAD_KEY_ROW2__CAN1_RXCAN */
-	IMX_PIN_REG(MX53_PAD_KEY_ROW2, 0x360, 0x038, 4, 0x000, 0), /* MX53_PAD_KEY_ROW2__FEC_MDC */
-	IMX_PIN_REG(MX53_PAD_KEY_ROW2, 0x360, 0x038, 5, 0x7B0, 0), /* MX53_PAD_KEY_ROW2__ECSPI1_SS2 */
-	IMX_PIN_REG(MX53_PAD_KEY_ROW2, 0x360, 0x038, 6, 0x000, 0), /* MX53_PAD_KEY_ROW2__FEC_TDATA_2 */
-	IMX_PIN_REG(MX53_PAD_KEY_ROW2, 0x360, 0x038, 7, 0x000, 0), /* MX53_PAD_KEY_ROW2__USBPHY1_RXERROR */
-	IMX_PIN_REG(MX53_PAD_KEY_COL3, 0x364, 0x03C, 0, 0x000, 0), /* MX53_PAD_KEY_COL3__KPP_COL_3 */
-	IMX_PIN_REG(MX53_PAD_KEY_COL3, 0x364, 0x03C, 1, 0x000, 0), /* MX53_PAD_KEY_COL3__GPIO4_12 */
-	IMX_PIN_REG(MX53_PAD_KEY_COL3, 0x364, 0x03C, 2, 0x000, 0), /* MX53_PAD_KEY_COL3__USBOH3_H2_DP */
-	IMX_PIN_REG(MX53_PAD_KEY_COL3, 0x364, 0x03C, 3, 0x870, 0), /* MX53_PAD_KEY_COL3__SPDIF_IN1 */
-	IMX_PIN_REG(MX53_PAD_KEY_COL3, 0x364, 0x03C, 4, 0x81C, 0), /* MX53_PAD_KEY_COL3__I2C2_SCL */
-	IMX_PIN_REG(MX53_PAD_KEY_COL3, 0x364, 0x03C, 5, 0x7B4, 0), /* MX53_PAD_KEY_COL3__ECSPI1_SS3 */
-	IMX_PIN_REG(MX53_PAD_KEY_COL3, 0x364, 0x03C, 6, 0x000, 0), /* MX53_PAD_KEY_COL3__FEC_CRS */
-	IMX_PIN_REG(MX53_PAD_KEY_COL3, 0x364, 0x03C, 7, 0x000, 0), /* MX53_PAD_KEY_COL3__USBPHY1_SIECLOCK */
-	IMX_PIN_REG(MX53_PAD_KEY_ROW3, 0x368, 0x040, 0, 0x000, 0), /* MX53_PAD_KEY_ROW3__KPP_ROW_3 */
-	IMX_PIN_REG(MX53_PAD_KEY_ROW3, 0x368, 0x040, 1, 0x000, 0), /* MX53_PAD_KEY_ROW3__GPIO4_13 */
-	IMX_PIN_REG(MX53_PAD_KEY_ROW3, 0x368, 0x040, 2, 0x000, 0), /* MX53_PAD_KEY_ROW3__USBOH3_H2_DM */
-	IMX_PIN_REG(MX53_PAD_KEY_ROW3, 0x368, 0x040, 3, 0x768, 0), /* MX53_PAD_KEY_ROW3__CCM_ASRC_EXT_CLK */
-	IMX_PIN_REG(MX53_PAD_KEY_ROW3, 0x368, 0x040, 4, 0x820, 0), /* MX53_PAD_KEY_ROW3__I2C2_SDA */
-	IMX_PIN_REG(MX53_PAD_KEY_ROW3, 0x368, 0x040, 5, 0x000, 0), /* MX53_PAD_KEY_ROW3__OSC32K_32K_OUT */
-	IMX_PIN_REG(MX53_PAD_KEY_ROW3, 0x368, 0x040, 6, 0x77C, 0), /* MX53_PAD_KEY_ROW3__CCM_PLL4_BYP */
-	IMX_PIN_REG(MX53_PAD_KEY_ROW3, 0x368, 0x040, 7, 0x000, 0), /* MX53_PAD_KEY_ROW3__USBPHY1_LINESTATE_0 */
-	IMX_PIN_REG(MX53_PAD_KEY_COL4, 0x36C, 0x044, 0, 0x000, 0), /* MX53_PAD_KEY_COL4__KPP_COL_4 */
-	IMX_PIN_REG(MX53_PAD_KEY_COL4, 0x36C, 0x044, 1, 0x000, 0), /* MX53_PAD_KEY_COL4__GPIO4_14 */
-	IMX_PIN_REG(MX53_PAD_KEY_COL4, 0x36C, 0x044, 2, 0x000, 0), /* MX53_PAD_KEY_COL4__CAN2_TXCAN */
-	IMX_PIN_REG(MX53_PAD_KEY_COL4, 0x36C, 0x044, 3, 0x000, 0), /* MX53_PAD_KEY_COL4__IPU_SISG_4 */
-	IMX_PIN_REG(MX53_PAD_KEY_COL4, 0x36C, 0x044, 4, 0x894, 0), /* MX53_PAD_KEY_COL4__UART5_RTS */
-	IMX_PIN_REG(MX53_PAD_KEY_COL4, 0x36C, 0x044, 5, 0x89C, 0), /* MX53_PAD_KEY_COL4__USBOH3_USBOTG_OC */
-	IMX_PIN_REG(MX53_PAD_KEY_COL4, 0x36C, 0x044, 7, 0x000, 0), /* MX53_PAD_KEY_COL4__USBPHY1_LINESTATE_1 */
-	IMX_PIN_REG(MX53_PAD_KEY_ROW4, 0x370, 0x048, 0, 0x000, 0), /* MX53_PAD_KEY_ROW4__KPP_ROW_4 */
-	IMX_PIN_REG(MX53_PAD_KEY_ROW4, 0x370, 0x048, 1, 0x000, 0), /* MX53_PAD_KEY_ROW4__GPIO4_15 */
-	IMX_PIN_REG(MX53_PAD_KEY_ROW4, 0x370, 0x048, 2, 0x764, 0), /* MX53_PAD_KEY_ROW4__CAN2_RXCAN */
-	IMX_PIN_REG(MX53_PAD_KEY_ROW4, 0x370, 0x048, 3, 0x000, 0), /* MX53_PAD_KEY_ROW4__IPU_SISG_5 */
-	IMX_PIN_REG(MX53_PAD_KEY_ROW4, 0x370, 0x048, 4, 0x000, 0), /* MX53_PAD_KEY_ROW4__UART5_CTS */
-	IMX_PIN_REG(MX53_PAD_KEY_ROW4, 0x370, 0x048, 5, 0x000, 0), /* MX53_PAD_KEY_ROW4__USBOH3_USBOTG_PWR */
-	IMX_PIN_REG(MX53_PAD_KEY_ROW4, 0x370, 0x048, 7, 0x000, 0), /* MX53_PAD_KEY_ROW4__USBPHY1_VBUSVALID */
-	IMX_PIN_REG(MX53_PAD_DI0_DISP_CLK, 0x378, 0x04C, 0, 0x000, 0), /* MX53_PAD_DI0_DISP_CLK__IPU_DI0_DISP_CLK */
-	IMX_PIN_REG(MX53_PAD_DI0_DISP_CLK, 0x378, 0x04C, 1, 0x000, 0), /* MX53_PAD_DI0_DISP_CLK__GPIO4_16 */
-	IMX_PIN_REG(MX53_PAD_DI0_DISP_CLK, 0x378, 0x04C, 2, 0x000, 0), /* MX53_PAD_DI0_DISP_CLK__USBOH3_USBH2_DIR */
-	IMX_PIN_REG(MX53_PAD_DI0_DISP_CLK, 0x378, 0x04C, 5, 0x000, 0), /* MX53_PAD_DI0_DISP_CLK__SDMA_DEBUG_CORE_STATE_0 */
-	IMX_PIN_REG(MX53_PAD_DI0_DISP_CLK, 0x378, 0x04C, 6, 0x000, 0), /* MX53_PAD_DI0_DISP_CLK__EMI_EMI_DEBUG_0 */
-	IMX_PIN_REG(MX53_PAD_DI0_DISP_CLK, 0x378, 0x04C, 7, 0x000, 0), /* MX53_PAD_DI0_DISP_CLK__USBPHY1_AVALID */
-	IMX_PIN_REG(MX53_PAD_DI0_PIN15, 0x37C, 0x050, 0, 0x000, 0), /* MX53_PAD_DI0_PIN15__IPU_DI0_PIN15 */
-	IMX_PIN_REG(MX53_PAD_DI0_PIN15, 0x37C, 0x050, 1, 0x000, 0), /* MX53_PAD_DI0_PIN15__GPIO4_17 */
-	IMX_PIN_REG(MX53_PAD_DI0_PIN15, 0x37C, 0x050, 2, 0x000, 0), /* MX53_PAD_DI0_PIN15__AUDMUX_AUD6_TXC */
-	IMX_PIN_REG(MX53_PAD_DI0_PIN15, 0x37C, 0x050, 5, 0x000, 0), /* MX53_PAD_DI0_PIN15__SDMA_DEBUG_CORE_STATE_1 */
-	IMX_PIN_REG(MX53_PAD_DI0_PIN15, 0x37C, 0x050, 6, 0x000, 0), /* MX53_PAD_DI0_PIN15__EMI_EMI_DEBUG_1 */
-	IMX_PIN_REG(MX53_PAD_DI0_PIN15, 0x37C, 0x050, 7, 0x000, 0), /* MX53_PAD_DI0_PIN15__USBPHY1_BVALID */
-	IMX_PIN_REG(MX53_PAD_DI0_PIN2, 0x380, 0x054, 0, 0x000, 0), /* MX53_PAD_DI0_PIN2__IPU_DI0_PIN2 */
-	IMX_PIN_REG(MX53_PAD_DI0_PIN2, 0x380, 0x054, 1, 0x000, 0), /* MX53_PAD_DI0_PIN2__GPIO4_18 */
-	IMX_PIN_REG(MX53_PAD_DI0_PIN2, 0x380, 0x054, 2, 0x000, 0), /* MX53_PAD_DI0_PIN2__AUDMUX_AUD6_TXD */
-	IMX_PIN_REG(MX53_PAD_DI0_PIN2, 0x380, 0x054, 5, 0x000, 0), /* MX53_PAD_DI0_PIN2__SDMA_DEBUG_CORE_STATE_2 */
-	IMX_PIN_REG(MX53_PAD_DI0_PIN2, 0x380, 0x054, 6, 0x000, 0), /* MX53_PAD_DI0_PIN2__EMI_EMI_DEBUG_2 */
-	IMX_PIN_REG(MX53_PAD_DI0_PIN2, 0x380, 0x054, 7, 0x000, 0), /* MX53_PAD_DI0_PIN2__USBPHY1_ENDSESSION */
-	IMX_PIN_REG(MX53_PAD_DI0_PIN3, 0x384, 0x058, 0, 0x000, 0), /* MX53_PAD_DI0_PIN3__IPU_DI0_PIN3 */
-	IMX_PIN_REG(MX53_PAD_DI0_PIN3, 0x384, 0x058, 1, 0x000, 0), /* MX53_PAD_DI0_PIN3__GPIO4_19 */
-	IMX_PIN_REG(MX53_PAD_DI0_PIN3, 0x384, 0x058, 2, 0x000, 0), /* MX53_PAD_DI0_PIN3__AUDMUX_AUD6_TXFS */
-	IMX_PIN_REG(MX53_PAD_DI0_PIN3, 0x384, 0x058, 5, 0x000, 0), /* MX53_PAD_DI0_PIN3__SDMA_DEBUG_CORE_STATE_3 */
-	IMX_PIN_REG(MX53_PAD_DI0_PIN3, 0x384, 0x058, 6, 0x000, 0), /* MX53_PAD_DI0_PIN3__EMI_EMI_DEBUG_3 */
-	IMX_PIN_REG(MX53_PAD_DI0_PIN3, 0x384, 0x058, 7, 0x000, 0), /* MX53_PAD_DI0_PIN3__USBPHY1_IDDIG */
-	IMX_PIN_REG(MX53_PAD_DI0_PIN4, 0x388, 0x05C, 0, 0x000, 0), /* MX53_PAD_DI0_PIN4__IPU_DI0_PIN4 */
-	IMX_PIN_REG(MX53_PAD_DI0_PIN4, 0x388, 0x05C, 1, 0x000, 0), /* MX53_PAD_DI0_PIN4__GPIO4_20 */
-	IMX_PIN_REG(MX53_PAD_DI0_PIN4, 0x388, 0x05C, 2, 0x000, 0), /* MX53_PAD_DI0_PIN4__AUDMUX_AUD6_RXD */
-	IMX_PIN_REG(MX53_PAD_DI0_PIN4, 0x388, 0x05C, 3, 0x7FC, 0), /* MX53_PAD_DI0_PIN4__ESDHC1_WP */
-	IMX_PIN_REG(MX53_PAD_DI0_PIN4, 0x388, 0x05C, 5, 0x000, 0), /* MX53_PAD_DI0_PIN4__SDMA_DEBUG_YIELD */
-	IMX_PIN_REG(MX53_PAD_DI0_PIN4, 0x388, 0x05C, 6, 0x000, 0), /* MX53_PAD_DI0_PIN4__EMI_EMI_DEBUG_4 */
-	IMX_PIN_REG(MX53_PAD_DI0_PIN4, 0x388, 0x05C, 7, 0x000, 0), /* MX53_PAD_DI0_PIN4__USBPHY1_HOSTDISCONNECT */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT0, 0x38C, 0x060, 0, 0x000, 0), /* MX53_PAD_DISP0_DAT0__IPU_DISP0_DAT_0 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT0, 0x38C, 0x060, 1, 0x000, 0), /* MX53_PAD_DISP0_DAT0__GPIO4_21 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT0, 0x38C, 0x060, 2, 0x780, 0), /* MX53_PAD_DISP0_DAT0__CSPI_SCLK */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT0, 0x38C, 0x060, 3, 0x000, 0), /* MX53_PAD_DISP0_DAT0__USBOH3_USBH2_DATA_0 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT0, 0x38C, 0x060, 5, 0x000, 0), /* MX53_PAD_DISP0_DAT0__SDMA_DEBUG_CORE_RUN */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT0, 0x38C, 0x060, 6, 0x000, 0), /* MX53_PAD_DISP0_DAT0__EMI_EMI_DEBUG_5 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT0, 0x38C, 0x060, 7, 0x000, 0), /* MX53_PAD_DISP0_DAT0__USBPHY2_TXREADY */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT1, 0x390, 0x064, 0, 0x000, 0), /* MX53_PAD_DISP0_DAT1__IPU_DISP0_DAT_1 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT1, 0x390, 0x064, 1, 0x000, 0), /* MX53_PAD_DISP0_DAT1__GPIO4_22 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT1, 0x390, 0x064, 2, 0x788, 0), /* MX53_PAD_DISP0_DAT1__CSPI_MOSI */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT1, 0x390, 0x064, 3, 0x000, 0), /* MX53_PAD_DISP0_DAT1__USBOH3_USBH2_DATA_1 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT1, 0x390, 0x064, 5, 0x000, 0), /* MX53_PAD_DISP0_DAT1__SDMA_DEBUG_EVENT_CHANNEL_SEL */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT1, 0x390, 0x064, 6, 0x000, 0), /* MX53_PAD_DISP0_DAT1__EMI_EMI_DEBUG_6 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT1, 0x390, 0x064, 7, 0x000, 0), /* MX53_PAD_DISP0_DAT1__USBPHY2_RXVALID */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT2, 0x394, 0x068, 0, 0x000, 0), /* MX53_PAD_DISP0_DAT2__IPU_DISP0_DAT_2 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT2, 0x394, 0x068, 1, 0x000, 0), /* MX53_PAD_DISP0_DAT2__GPIO4_23 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT2, 0x394, 0x068, 2, 0x784, 0), /* MX53_PAD_DISP0_DAT2__CSPI_MISO */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT2, 0x394, 0x068, 3, 0x000, 0), /* MX53_PAD_DISP0_DAT2__USBOH3_USBH2_DATA_2 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT2, 0x394, 0x068, 5, 0x000, 0), /* MX53_PAD_DISP0_DAT2__SDMA_DEBUG_MODE */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT2, 0x394, 0x068, 6, 0x000, 0), /* MX53_PAD_DISP0_DAT2__EMI_EMI_DEBUG_7 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT2, 0x394, 0x068, 7, 0x000, 0), /* MX53_PAD_DISP0_DAT2__USBPHY2_RXACTIVE */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT3, 0x398, 0x06C, 0, 0x000, 0), /* MX53_PAD_DISP0_DAT3__IPU_DISP0_DAT_3 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT3, 0x398, 0x06C, 1, 0x000, 0), /* MX53_PAD_DISP0_DAT3__GPIO4_24 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT3, 0x398, 0x06C, 2, 0x78C, 0), /* MX53_PAD_DISP0_DAT3__CSPI_SS0 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT3, 0x398, 0x06C, 3, 0x000, 0), /* MX53_PAD_DISP0_DAT3__USBOH3_USBH2_DATA_3 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT3, 0x398, 0x06C, 5, 0x000, 0), /* MX53_PAD_DISP0_DAT3__SDMA_DEBUG_BUS_ERROR */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT3, 0x398, 0x06C, 6, 0x000, 0), /* MX53_PAD_DISP0_DAT3__EMI_EMI_DEBUG_8 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT3, 0x398, 0x06C, 7, 0x000, 0), /* MX53_PAD_DISP0_DAT3__USBPHY2_RXERROR */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT4, 0x39C, 0x070, 0, 0x000, 0), /* MX53_PAD_DISP0_DAT4__IPU_DISP0_DAT_4 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT4, 0x39C, 0x070, 1, 0x000, 0), /* MX53_PAD_DISP0_DAT4__GPIO4_25 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT4, 0x39C, 0x070, 2, 0x790, 0), /* MX53_PAD_DISP0_DAT4__CSPI_SS1 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT4, 0x39C, 0x070, 3, 0x000, 0), /* MX53_PAD_DISP0_DAT4__USBOH3_USBH2_DATA_4 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT4, 0x39C, 0x070, 5, 0x000, 0), /* MX53_PAD_DISP0_DAT4__SDMA_DEBUG_BUS_RWB */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT4, 0x39C, 0x070, 6, 0x000, 0), /* MX53_PAD_DISP0_DAT4__EMI_EMI_DEBUG_9 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT4, 0x39C, 0x070, 7, 0x000, 0), /* MX53_PAD_DISP0_DAT4__USBPHY2_SIECLOCK */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT5, 0x3A0, 0x074, 0, 0x000, 0), /* MX53_PAD_DISP0_DAT5__IPU_DISP0_DAT_5 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT5, 0x3A0, 0x074, 1, 0x000, 0), /* MX53_PAD_DISP0_DAT5__GPIO4_26 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT5, 0x3A0, 0x074, 2, 0x794, 0), /* MX53_PAD_DISP0_DAT5__CSPI_SS2 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT5, 0x3A0, 0x074, 3, 0x000, 0), /* MX53_PAD_DISP0_DAT5__USBOH3_USBH2_DATA_5 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT5, 0x3A0, 0x074, 5, 0x000, 0), /* MX53_PAD_DISP0_DAT5__SDMA_DEBUG_MATCHED_DMBUS */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT5, 0x3A0, 0x074, 6, 0x000, 0), /* MX53_PAD_DISP0_DAT5__EMI_EMI_DEBUG_10 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT5, 0x3A0, 0x074, 7, 0x000, 0), /* MX53_PAD_DISP0_DAT5__USBPHY2_LINESTATE_0 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT6, 0x3A4, 0x078, 0, 0x000, 0), /* MX53_PAD_DISP0_DAT6__IPU_DISP0_DAT_6 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT6, 0x3A4, 0x078, 1, 0x000, 0), /* MX53_PAD_DISP0_DAT6__GPIO4_27 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT6, 0x3A4, 0x078, 2, 0x798, 0), /* MX53_PAD_DISP0_DAT6__CSPI_SS3 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT6, 0x3A4, 0x078, 3, 0x000, 0), /* MX53_PAD_DISP0_DAT6__USBOH3_USBH2_DATA_6 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT6, 0x3A4, 0x078, 5, 0x000, 0), /* MX53_PAD_DISP0_DAT6__SDMA_DEBUG_RTBUFFER_WRITE */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT6, 0x3A4, 0x078, 6, 0x000, 0), /* MX53_PAD_DISP0_DAT6__EMI_EMI_DEBUG_11 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT6, 0x3A4, 0x078, 7, 0x000, 0), /* MX53_PAD_DISP0_DAT6__USBPHY2_LINESTATE_1 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT7, 0x3A8, 0x07C, 0, 0x000, 0), /* MX53_PAD_DISP0_DAT7__IPU_DISP0_DAT_7 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT7, 0x3A8, 0x07C, 1, 0x000, 0), /* MX53_PAD_DISP0_DAT7__GPIO4_28 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT7, 0x3A8, 0x07C, 2, 0x000, 0), /* MX53_PAD_DISP0_DAT7__CSPI_RDY */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT7, 0x3A8, 0x07C, 3, 0x000, 0), /* MX53_PAD_DISP0_DAT7__USBOH3_USBH2_DATA_7 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT7, 0x3A8, 0x07C, 5, 0x000, 0), /* MX53_PAD_DISP0_DAT7__SDMA_DEBUG_EVENT_CHANNEL_0 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT7, 0x3A8, 0x07C, 6, 0x000, 0), /* MX53_PAD_DISP0_DAT7__EMI_EMI_DEBUG_12 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT7, 0x3A8, 0x07C, 7, 0x000, 0), /* MX53_PAD_DISP0_DAT7__USBPHY2_VBUSVALID */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT8, 0x3AC, 0x080, 0, 0x000, 0), /* MX53_PAD_DISP0_DAT8__IPU_DISP0_DAT_8 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT8, 0x3AC, 0x080, 1, 0x000, 0), /* MX53_PAD_DISP0_DAT8__GPIO4_29 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT8, 0x3AC, 0x080, 2, 0x000, 0), /* MX53_PAD_DISP0_DAT8__PWM1_PWMO */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT8, 0x3AC, 0x080, 3, 0x000, 0), /* MX53_PAD_DISP0_DAT8__WDOG1_WDOG_B */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT8, 0x3AC, 0x080, 5, 0x000, 0), /* MX53_PAD_DISP0_DAT8__SDMA_DEBUG_EVENT_CHANNEL_1 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT8, 0x3AC, 0x080, 6, 0x000, 0), /* MX53_PAD_DISP0_DAT8__EMI_EMI_DEBUG_13 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT8, 0x3AC, 0x080, 7, 0x000, 0), /* MX53_PAD_DISP0_DAT8__USBPHY2_AVALID */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT9, 0x3B0, 0x084, 0, 0x000, 0), /* MX53_PAD_DISP0_DAT9__IPU_DISP0_DAT_9 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT9, 0x3B0, 0x084, 1, 0x000, 0), /* MX53_PAD_DISP0_DAT9__GPIO4_30 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT9, 0x3B0, 0x084, 2, 0x000, 0), /* MX53_PAD_DISP0_DAT9__PWM2_PWMO */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT9, 0x3B0, 0x084, 3, 0x000, 0), /* MX53_PAD_DISP0_DAT9__WDOG2_WDOG_B */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT9, 0x3B0, 0x084, 5, 0x000, 0), /* MX53_PAD_DISP0_DAT9__SDMA_DEBUG_EVENT_CHANNEL_2 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT9, 0x3B0, 0x084, 6, 0x000, 0), /* MX53_PAD_DISP0_DAT9__EMI_EMI_DEBUG_14 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT9, 0x3B0, 0x084, 7, 0x000, 0), /* MX53_PAD_DISP0_DAT9__USBPHY2_VSTATUS_0 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT10, 0x3B4, 0x088, 0, 0x000, 0), /* MX53_PAD_DISP0_DAT10__IPU_DISP0_DAT_10 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT10, 0x3B4, 0x088, 1, 0x000, 0), /* MX53_PAD_DISP0_DAT10__GPIO4_31 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT10, 0x3B4, 0x088, 2, 0x000, 0), /* MX53_PAD_DISP0_DAT10__USBOH3_USBH2_STP */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT10, 0x3B4, 0x088, 5, 0x000, 0), /* MX53_PAD_DISP0_DAT10__SDMA_DEBUG_EVENT_CHANNEL_3 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT10, 0x3B4, 0x088, 6, 0x000, 0), /* MX53_PAD_DISP0_DAT10__EMI_EMI_DEBUG_15 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT10, 0x3B4, 0x088, 7, 0x000, 0), /* MX53_PAD_DISP0_DAT10__USBPHY2_VSTATUS_1 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT11, 0x3B8, 0x08C, 0, 0x000, 0), /* MX53_PAD_DISP0_DAT11__IPU_DISP0_DAT_11 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT11, 0x3B8, 0x08C, 1, 0x000, 0), /* MX53_PAD_DISP0_DAT11__GPIO5_5 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT11, 0x3B8, 0x08C, 2, 0x000, 0), /* MX53_PAD_DISP0_DAT11__USBOH3_USBH2_NXT */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT11, 0x3B8, 0x08C, 5, 0x000, 0), /* MX53_PAD_DISP0_DAT11__SDMA_DEBUG_EVENT_CHANNEL_4 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT11, 0x3B8, 0x08C, 6, 0x000, 0), /* MX53_PAD_DISP0_DAT11__EMI_EMI_DEBUG_16 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT11, 0x3B8, 0x08C, 7, 0x000, 0), /* MX53_PAD_DISP0_DAT11__USBPHY2_VSTATUS_2 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT12, 0x3BC, 0x090, 0, 0x000, 0), /* MX53_PAD_DISP0_DAT12__IPU_DISP0_DAT_12 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT12, 0x3BC, 0x090, 1, 0x000, 0), /* MX53_PAD_DISP0_DAT12__GPIO5_6 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT12, 0x3BC, 0x090, 2, 0x000, 0), /* MX53_PAD_DISP0_DAT12__USBOH3_USBH2_CLK */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT12, 0x3BC, 0x090, 5, 0x000, 0), /* MX53_PAD_DISP0_DAT12__SDMA_DEBUG_EVENT_CHANNEL_5 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT12, 0x3BC, 0x090, 6, 0x000, 0), /* MX53_PAD_DISP0_DAT12__EMI_EMI_DEBUG_17 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT12, 0x3BC, 0x090, 7, 0x000, 0), /* MX53_PAD_DISP0_DAT12__USBPHY2_VSTATUS_3 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT13, 0x3C0, 0x094, 0, 0x000, 0), /* MX53_PAD_DISP0_DAT13__IPU_DISP0_DAT_13 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT13, 0x3C0, 0x094, 1, 0x000, 0), /* MX53_PAD_DISP0_DAT13__GPIO5_7 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT13, 0x3C0, 0x094, 3, 0x754, 0), /* MX53_PAD_DISP0_DAT13__AUDMUX_AUD5_RXFS */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT13, 0x3C0, 0x094, 5, 0x000, 0), /* MX53_PAD_DISP0_DAT13__SDMA_DEBUG_EVT_CHN_LINES_0 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT13, 0x3C0, 0x094, 6, 0x000, 0), /* MX53_PAD_DISP0_DAT13__EMI_EMI_DEBUG_18 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT13, 0x3C0, 0x094, 7, 0x000, 0), /* MX53_PAD_DISP0_DAT13__USBPHY2_VSTATUS_4 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT14, 0x3C4, 0x098, 0, 0x000, 0), /* MX53_PAD_DISP0_DAT14__IPU_DISP0_DAT_14 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT14, 0x3C4, 0x098, 1, 0x000, 0), /* MX53_PAD_DISP0_DAT14__GPIO5_8 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT14, 0x3C4, 0x098, 3, 0x750, 0), /* MX53_PAD_DISP0_DAT14__AUDMUX_AUD5_RXC */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT14, 0x3C4, 0x098, 5, 0x000, 0), /* MX53_PAD_DISP0_DAT14__SDMA_DEBUG_EVT_CHN_LINES_1 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT14, 0x3C4, 0x098, 6, 0x000, 0), /* MX53_PAD_DISP0_DAT14__EMI_EMI_DEBUG_19 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT14, 0x3C4, 0x098, 7, 0x000, 0), /* MX53_PAD_DISP0_DAT14__USBPHY2_VSTATUS_5 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT15, 0x3C8, 0x09C, 0, 0x000, 0), /* MX53_PAD_DISP0_DAT15__IPU_DISP0_DAT_15 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT15, 0x3C8, 0x09C, 1, 0x000, 0), /* MX53_PAD_DISP0_DAT15__GPIO5_9 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT15, 0x3C8, 0x09C, 2, 0x7AC, 1), /* MX53_PAD_DISP0_DAT15__ECSPI1_SS1 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT15, 0x3C8, 0x09C, 3, 0x7C8, 0), /* MX53_PAD_DISP0_DAT15__ECSPI2_SS1 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT15, 0x3C8, 0x09C, 5, 0x000, 0), /* MX53_PAD_DISP0_DAT15__SDMA_DEBUG_EVT_CHN_LINES_2 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT15, 0x3C8, 0x09C, 6, 0x000, 0), /* MX53_PAD_DISP0_DAT15__EMI_EMI_DEBUG_20 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT15, 0x3C8, 0x09C, 7, 0x000, 0), /* MX53_PAD_DISP0_DAT15__USBPHY2_VSTATUS_6 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT16, 0x3CC, 0x0A0, 0, 0x000, 0), /* MX53_PAD_DISP0_DAT16__IPU_DISP0_DAT_16 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT16, 0x3CC, 0x0A0, 1, 0x000, 0), /* MX53_PAD_DISP0_DAT16__GPIO5_10 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT16, 0x3CC, 0x0A0, 2, 0x7C0, 0), /* MX53_PAD_DISP0_DAT16__ECSPI2_MOSI */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT16, 0x3CC, 0x0A0, 3, 0x758, 1), /* MX53_PAD_DISP0_DAT16__AUDMUX_AUD5_TXC */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT16, 0x3CC, 0x0A0, 4, 0x868, 0), /* MX53_PAD_DISP0_DAT16__SDMA_EXT_EVENT_0 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT16, 0x3CC, 0x0A0, 5, 0x000, 0), /* MX53_PAD_DISP0_DAT16__SDMA_DEBUG_EVT_CHN_LINES_3 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT16, 0x3CC, 0x0A0, 6, 0x000, 0), /* MX53_PAD_DISP0_DAT16__EMI_EMI_DEBUG_21 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT16, 0x3CC, 0x0A0, 7, 0x000, 0), /* MX53_PAD_DISP0_DAT16__USBPHY2_VSTATUS_7 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT17, 0x3D0, 0x0A4, 0, 0x000, 0), /* MX53_PAD_DISP0_DAT17__IPU_DISP0_DAT_17 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT17, 0x3D0, 0x0A4, 1, 0x000, 0), /* MX53_PAD_DISP0_DAT17__GPIO5_11 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT17, 0x3D0, 0x0A4, 2, 0x7BC, 0), /* MX53_PAD_DISP0_DAT17__ECSPI2_MISO */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT17, 0x3D0, 0x0A4, 3, 0x74C, 1), /* MX53_PAD_DISP0_DAT17__AUDMUX_AUD5_TXD */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT17, 0x3D0, 0x0A4, 4, 0x86C, 0), /* MX53_PAD_DISP0_DAT17__SDMA_EXT_EVENT_1 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT17, 0x3D0, 0x0A4, 5, 0x000, 0), /* MX53_PAD_DISP0_DAT17__SDMA_DEBUG_EVT_CHN_LINES_4 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT17, 0x3D0, 0x0A4, 6, 0x000, 0), /* MX53_PAD_DISP0_DAT17__EMI_EMI_DEBUG_22 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT18, 0x3D4, 0x0A8, 0, 0x000, 0), /* MX53_PAD_DISP0_DAT18__IPU_DISP0_DAT_18 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT18, 0x3D4, 0x0A8, 1, 0x000, 0), /* MX53_PAD_DISP0_DAT18__GPIO5_12 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT18, 0x3D4, 0x0A8, 2, 0x7C4, 0), /* MX53_PAD_DISP0_DAT18__ECSPI2_SS0 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT18, 0x3D4, 0x0A8, 3, 0x75C, 1), /* MX53_PAD_DISP0_DAT18__AUDMUX_AUD5_TXFS */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT18, 0x3D4, 0x0A8, 4, 0x73C, 0), /* MX53_PAD_DISP0_DAT18__AUDMUX_AUD4_RXFS */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT18, 0x3D4, 0x0A8, 5, 0x000, 0), /* MX53_PAD_DISP0_DAT18__SDMA_DEBUG_EVT_CHN_LINES_5 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT18, 0x3D4, 0x0A8, 6, 0x000, 0), /* MX53_PAD_DISP0_DAT18__EMI_EMI_DEBUG_23 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT18, 0x3D4, 0x0A8, 7, 0x000, 0), /* MX53_PAD_DISP0_DAT18__EMI_WEIM_CS_2 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT19, 0x3D8, 0x0AC, 0, 0x000, 0), /* MX53_PAD_DISP0_DAT19__IPU_DISP0_DAT_19 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT19, 0x3D8, 0x0AC, 1, 0x000, 0), /* MX53_PAD_DISP0_DAT19__GPIO5_13 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT19, 0x3D8, 0x0AC, 2, 0x7B8, 0), /* MX53_PAD_DISP0_DAT19__ECSPI2_SCLK */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT19, 0x3D8, 0x0AC, 3, 0x748, 1), /* MX53_PAD_DISP0_DAT19__AUDMUX_AUD5_RXD */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT19, 0x3D8, 0x0AC, 4, 0x738, 0), /* MX53_PAD_DISP0_DAT19__AUDMUX_AUD4_RXC */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT19, 0x3D8, 0x0AC, 5, 0x000, 0), /* MX53_PAD_DISP0_DAT19__SDMA_DEBUG_EVT_CHN_LINES_6 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT19, 0x3D8, 0x0AC, 6, 0x000, 0), /* MX53_PAD_DISP0_DAT19__EMI_EMI_DEBUG_24 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT19, 0x3D8, 0x0AC, 7, 0x000, 0), /* MX53_PAD_DISP0_DAT19__EMI_WEIM_CS_3 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT20, 0x3DC, 0x0B0, 0, 0x000, 0), /* MX53_PAD_DISP0_DAT20__IPU_DISP0_DAT_20 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT20, 0x3DC, 0x0B0, 1, 0x000, 0), /* MX53_PAD_DISP0_DAT20__GPIO5_14 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT20, 0x3DC, 0x0B0, 2, 0x79C, 1), /* MX53_PAD_DISP0_DAT20__ECSPI1_SCLK */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT20, 0x3DC, 0x0B0, 3, 0x740, 0), /* MX53_PAD_DISP0_DAT20__AUDMUX_AUD4_TXC */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT20, 0x3DC, 0x0B0, 5, 0x000, 0), /* MX53_PAD_DISP0_DAT20__SDMA_DEBUG_EVT_CHN_LINES_7 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT20, 0x3DC, 0x0B0, 6, 0x000, 0), /* MX53_PAD_DISP0_DAT20__EMI_EMI_DEBUG_25 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT20, 0x3DC, 0x0B0, 7, 0x000, 0), /* MX53_PAD_DISP0_DAT20__SATA_PHY_TDI */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT21, 0x3E0, 0x0B4, 0, 0x000, 0), /* MX53_PAD_DISP0_DAT21__IPU_DISP0_DAT_21 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT21, 0x3E0, 0x0B4, 1, 0x000, 0), /* MX53_PAD_DISP0_DAT21__GPIO5_15 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT21, 0x3E0, 0x0B4, 2, 0x7A4, 1), /* MX53_PAD_DISP0_DAT21__ECSPI1_MOSI */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT21, 0x3E0, 0x0B4, 3, 0x734, 0), /* MX53_PAD_DISP0_DAT21__AUDMUX_AUD4_TXD */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT21, 0x3E0, 0x0B4, 5, 0x000, 0), /* MX53_PAD_DISP0_DAT21__SDMA_DEBUG_BUS_DEVICE_0 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT21, 0x3E0, 0x0B4, 6, 0x000, 0), /* MX53_PAD_DISP0_DAT21__EMI_EMI_DEBUG_26 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT21, 0x3E0, 0x0B4, 7, 0x000, 0), /* MX53_PAD_DISP0_DAT21__SATA_PHY_TDO */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT22, 0x3E4, 0x0B8, 0, 0x000, 0), /* MX53_PAD_DISP0_DAT22__IPU_DISP0_DAT_22 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT22, 0x3E4, 0x0B8, 1, 0x000, 0), /* MX53_PAD_DISP0_DAT22__GPIO5_16 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT22, 0x3E4, 0x0B8, 2, 0x7A0, 1), /* MX53_PAD_DISP0_DAT22__ECSPI1_MISO */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT22, 0x3E4, 0x0B8, 3, 0x744, 0), /* MX53_PAD_DISP0_DAT22__AUDMUX_AUD4_TXFS */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT22, 0x3E4, 0x0B8, 5, 0x000, 0), /* MX53_PAD_DISP0_DAT22__SDMA_DEBUG_BUS_DEVICE_1 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT22, 0x3E4, 0x0B8, 6, 0x000, 0), /* MX53_PAD_DISP0_DAT22__EMI_EMI_DEBUG_27 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT22, 0x3E4, 0x0B8, 7, 0x000, 0), /* MX53_PAD_DISP0_DAT22__SATA_PHY_TCK */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT23, 0x3E8, 0x0BC, 0, 0x000, 0), /* MX53_PAD_DISP0_DAT23__IPU_DISP0_DAT_23 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT23, 0x3E8, 0x0BC, 1, 0x000, 0), /* MX53_PAD_DISP0_DAT23__GPIO5_17 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT23, 0x3E8, 0x0BC, 2, 0x7A8, 1), /* MX53_PAD_DISP0_DAT23__ECSPI1_SS0 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT23, 0x3E8, 0x0BC, 3, 0x730, 0), /* MX53_PAD_DISP0_DAT23__AUDMUX_AUD4_RXD */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT23, 0x3E8, 0x0BC, 5, 0x000, 0), /* MX53_PAD_DISP0_DAT23__SDMA_DEBUG_BUS_DEVICE_2 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT23, 0x3E8, 0x0BC, 6, 0x000, 0), /* MX53_PAD_DISP0_DAT23__EMI_EMI_DEBUG_28 */
-	IMX_PIN_REG(MX53_PAD_DISP0_DAT23, 0x3E8, 0x0BC, 7, 0x000, 0), /* MX53_PAD_DISP0_DAT23__SATA_PHY_TMS */
-	IMX_PIN_REG(MX53_PAD_CSI0_PIXCLK, 0x3EC, 0x0C0, 0, 0x000, 0), /* MX53_PAD_CSI0_PIXCLK__IPU_CSI0_PIXCLK */
-	IMX_PIN_REG(MX53_PAD_CSI0_PIXCLK, 0x3EC, 0x0C0, 1, 0x000, 0), /* MX53_PAD_CSI0_PIXCLK__GPIO5_18 */
-	IMX_PIN_REG(MX53_PAD_CSI0_PIXCLK, 0x3EC, 0x0C0, 5, 0x000, 0), /* MX53_PAD_CSI0_PIXCLK__SDMA_DEBUG_PC_0 */
-	IMX_PIN_REG(MX53_PAD_CSI0_PIXCLK, 0x3EC, 0x0C0, 6, 0x000, 0), /* MX53_PAD_CSI0_PIXCLK__EMI_EMI_DEBUG_29 */
-	IMX_PIN_REG(MX53_PAD_CSI0_MCLK, 0x3F0, 0x0C4, 0, 0x000, 0), /* MX53_PAD_CSI0_MCLK__IPU_CSI0_HSYNC */
-	IMX_PIN_REG(MX53_PAD_CSI0_MCLK, 0x3F0, 0x0C4, 1, 0x000, 0), /* MX53_PAD_CSI0_MCLK__GPIO5_19 */
-	IMX_PIN_REG(MX53_PAD_CSI0_MCLK, 0x3F0, 0x0C4, 2, 0x000, 0), /* MX53_PAD_CSI0_MCLK__CCM_CSI0_MCLK */
-	IMX_PIN_REG(MX53_PAD_CSI0_MCLK, 0x3F0, 0x0C4, 5, 0x000, 0), /* MX53_PAD_CSI0_MCLK__SDMA_DEBUG_PC_1 */
-	IMX_PIN_REG(MX53_PAD_CSI0_MCLK, 0x3F0, 0x0C4, 6, 0x000, 0), /* MX53_PAD_CSI0_MCLK__EMI_EMI_DEBUG_30 */
-	IMX_PIN_REG(MX53_PAD_CSI0_MCLK, 0x3F0, 0x0C4, 7, 0x000, 0), /* MX53_PAD_CSI0_MCLK__TPIU_TRCTL */
-	IMX_PIN_REG(MX53_PAD_CSI0_DATA_EN, 0x3F4, 0x0C8, 0, 0x000, 0), /* MX53_PAD_CSI0_DATA_EN__IPU_CSI0_DATA_EN */
-	IMX_PIN_REG(MX53_PAD_CSI0_DATA_EN, 0x3F4, 0x0C8, 1, 0x000, 0), /* MX53_PAD_CSI0_DATA_EN__GPIO5_20 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DATA_EN, 0x3F4, 0x0C8, 5, 0x000, 0), /* MX53_PAD_CSI0_DATA_EN__SDMA_DEBUG_PC_2 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DATA_EN, 0x3F4, 0x0C8, 6, 0x000, 0), /* MX53_PAD_CSI0_DATA_EN__EMI_EMI_DEBUG_31 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DATA_EN, 0x3F4, 0x0C8, 7, 0x000, 0), /* MX53_PAD_CSI0_DATA_EN__TPIU_TRCLK */
-	IMX_PIN_REG(MX53_PAD_CSI0_VSYNC, 0x3F8, 0x0CC, 0, 0x000, 0), /* MX53_PAD_CSI0_VSYNC__IPU_CSI0_VSYNC */
-	IMX_PIN_REG(MX53_PAD_CSI0_VSYNC, 0x3F8, 0x0CC, 1, 0x000, 0), /* MX53_PAD_CSI0_VSYNC__GPIO5_21 */
-	IMX_PIN_REG(MX53_PAD_CSI0_VSYNC, 0x3F8, 0x0CC, 5, 0x000, 0), /* MX53_PAD_CSI0_VSYNC__SDMA_DEBUG_PC_3 */
-	IMX_PIN_REG(MX53_PAD_CSI0_VSYNC, 0x3F8, 0x0CC, 6, 0x000, 0), /* MX53_PAD_CSI0_VSYNC__EMI_EMI_DEBUG_32 */
-	IMX_PIN_REG(MX53_PAD_CSI0_VSYNC, 0x3F8, 0x0CC, 7, 0x000, 0), /* MX53_PAD_CSI0_VSYNC__TPIU_TRACE_0 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT4, 0x3FC, 0x0D0, 0, 0x000, 0), /* MX53_PAD_CSI0_DAT4__IPU_CSI0_D_4 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT4, 0x3FC, 0x0D0, 1, 0x000, 0), /* MX53_PAD_CSI0_DAT4__GPIO5_22 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT4, 0x3FC, 0x0D0, 2, 0x840, 1), /* MX53_PAD_CSI0_DAT4__KPP_COL_5 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT4, 0x3FC, 0x0D0, 3, 0x79C, 2), /* MX53_PAD_CSI0_DAT4__ECSPI1_SCLK */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT4, 0x3FC, 0x0D0, 4, 0x000, 0), /* MX53_PAD_CSI0_DAT4__USBOH3_USBH3_STP */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT4, 0x3FC, 0x0D0, 5, 0x000, 0), /* MX53_PAD_CSI0_DAT4__AUDMUX_AUD3_TXC */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT4, 0x3FC, 0x0D0, 6, 0x000, 0), /* MX53_PAD_CSI0_DAT4__EMI_EMI_DEBUG_33 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT4, 0x3FC, 0x0D0, 7, 0x000, 0), /* MX53_PAD_CSI0_DAT4__TPIU_TRACE_1 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT5, 0x400, 0x0D4, 0, 0x000, 0), /* MX53_PAD_CSI0_DAT5__IPU_CSI0_D_5 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT5, 0x400, 0x0D4, 1, 0x000, 0), /* MX53_PAD_CSI0_DAT5__GPIO5_23 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT5, 0x400, 0x0D4, 2, 0x84C, 0), /* MX53_PAD_CSI0_DAT5__KPP_ROW_5 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT5, 0x400, 0x0D4, 3, 0x7A4, 2), /* MX53_PAD_CSI0_DAT5__ECSPI1_MOSI */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT5, 0x400, 0x0D4, 4, 0x000, 0), /* MX53_PAD_CSI0_DAT5__USBOH3_USBH3_NXT */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT5, 0x400, 0x0D4, 5, 0x000, 0), /* MX53_PAD_CSI0_DAT5__AUDMUX_AUD3_TXD */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT5, 0x400, 0x0D4, 6, 0x000, 0), /* MX53_PAD_CSI0_DAT5__EMI_EMI_DEBUG_34 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT5, 0x400, 0x0D4, 7, 0x000, 0), /* MX53_PAD_CSI0_DAT5__TPIU_TRACE_2 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT6, 0x404, 0x0D8, 0, 0x000, 0), /* MX53_PAD_CSI0_DAT6__IPU_CSI0_D_6 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT6, 0x404, 0x0D8, 1, 0x000, 0), /* MX53_PAD_CSI0_DAT6__GPIO5_24 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT6, 0x404, 0x0D8, 2, 0x844, 0), /* MX53_PAD_CSI0_DAT6__KPP_COL_6 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT6, 0x404, 0x0D8, 3, 0x7A0, 2), /* MX53_PAD_CSI0_DAT6__ECSPI1_MISO */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT6, 0x404, 0x0D8, 4, 0x000, 0), /* MX53_PAD_CSI0_DAT6__USBOH3_USBH3_CLK */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT6, 0x404, 0x0D8, 5, 0x000, 0), /* MX53_PAD_CSI0_DAT6__AUDMUX_AUD3_TXFS */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT6, 0x404, 0x0D8, 6, 0x000, 0), /* MX53_PAD_CSI0_DAT6__EMI_EMI_DEBUG_35 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT6, 0x404, 0x0D8, 7, 0x000, 0), /* MX53_PAD_CSI0_DAT6__TPIU_TRACE_3 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT7, 0x408, 0x0DC, 0, 0x000, 0), /* MX53_PAD_CSI0_DAT7__IPU_CSI0_D_7 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT7, 0x408, 0x0DC, 1, 0x000, 0), /* MX53_PAD_CSI0_DAT7__GPIO5_25 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT7, 0x408, 0x0DC, 2, 0x850, 0), /* MX53_PAD_CSI0_DAT7__KPP_ROW_6 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT7, 0x408, 0x0DC, 3, 0x7A8, 2), /* MX53_PAD_CSI0_DAT7__ECSPI1_SS0 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT7, 0x408, 0x0DC, 4, 0x000, 0), /* MX53_PAD_CSI0_DAT7__USBOH3_USBH3_DIR */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT7, 0x408, 0x0DC, 5, 0x000, 0), /* MX53_PAD_CSI0_DAT7__AUDMUX_AUD3_RXD */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT7, 0x408, 0x0DC, 6, 0x000, 0), /* MX53_PAD_CSI0_DAT7__EMI_EMI_DEBUG_36 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT7, 0x408, 0x0DC, 7, 0x000, 0), /* MX53_PAD_CSI0_DAT7__TPIU_TRACE_4 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT8, 0x40C, 0x0E0, 0, 0x000, 0), /* MX53_PAD_CSI0_DAT8__IPU_CSI0_D_8 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT8, 0x40C, 0x0E0, 1, 0x000, 0), /* MX53_PAD_CSI0_DAT8__GPIO5_26 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT8, 0x40C, 0x0E0, 2, 0x848, 0), /* MX53_PAD_CSI0_DAT8__KPP_COL_7 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT8, 0x40C, 0x0E0, 3, 0x7B8, 1), /* MX53_PAD_CSI0_DAT8__ECSPI2_SCLK */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT8, 0x40C, 0x0E0, 4, 0x000, 0), /* MX53_PAD_CSI0_DAT8__USBOH3_USBH3_OC */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT8, 0x40C, 0x0E0, 5, 0x818, 0), /* MX53_PAD_CSI0_DAT8__I2C1_SDA */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT8, 0x40C, 0x0E0, 6, 0x000, 0), /* MX53_PAD_CSI0_DAT8__EMI_EMI_DEBUG_37 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT8, 0x40C, 0x0E0, 7, 0x000, 0), /* MX53_PAD_CSI0_DAT8__TPIU_TRACE_5 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT9, 0x410, 0x0E4, 0, 0x000, 0), /* MX53_PAD_CSI0_DAT9__IPU_CSI0_D_9 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT9, 0x410, 0x0E4, 1, 0x000, 0), /* MX53_PAD_CSI0_DAT9__GPIO5_27 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT9, 0x410, 0x0E4, 2, 0x854, 0), /* MX53_PAD_CSI0_DAT9__KPP_ROW_7 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT9, 0x410, 0x0E4, 3, 0x7C0, 1), /* MX53_PAD_CSI0_DAT9__ECSPI2_MOSI */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT9, 0x410, 0x0E4, 4, 0x000, 0), /* MX53_PAD_CSI0_DAT9__USBOH3_USBH3_PWR */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT9, 0x410, 0x0E4, 5, 0x814, 0), /* MX53_PAD_CSI0_DAT9__I2C1_SCL */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT9, 0x410, 0x0E4, 6, 0x000, 0), /* MX53_PAD_CSI0_DAT9__EMI_EMI_DEBUG_38 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT9, 0x410, 0x0E4, 7, 0x000, 0), /* MX53_PAD_CSI0_DAT9__TPIU_TRACE_6 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT10, 0x414, 0x0E8, 0, 0x000, 0), /* MX53_PAD_CSI0_DAT10__IPU_CSI0_D_10 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT10, 0x414, 0x0E8, 1, 0x000, 0), /* MX53_PAD_CSI0_DAT10__GPIO5_28 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT10, 0x414, 0x0E8, 2, 0x000, 0), /* MX53_PAD_CSI0_DAT10__UART1_TXD_MUX */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT10, 0x414, 0x0E8, 3, 0x7BC, 1), /* MX53_PAD_CSI0_DAT10__ECSPI2_MISO */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT10, 0x414, 0x0E8, 4, 0x000, 0), /* MX53_PAD_CSI0_DAT10__AUDMUX_AUD3_RXC */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT10, 0x414, 0x0E8, 5, 0x000, 0), /* MX53_PAD_CSI0_DAT10__SDMA_DEBUG_PC_4 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT10, 0x414, 0x0E8, 6, 0x000, 0), /* MX53_PAD_CSI0_DAT10__EMI_EMI_DEBUG_39 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT10, 0x414, 0x0E8, 7, 0x000, 0), /* MX53_PAD_CSI0_DAT10__TPIU_TRACE_7 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT11, 0x418, 0x0EC, 0, 0x000, 0), /* MX53_PAD_CSI0_DAT11__IPU_CSI0_D_11 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT11, 0x418, 0x0EC, 1, 0x000, 0), /* MX53_PAD_CSI0_DAT11__GPIO5_29 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT11, 0x418, 0x0EC, 2, 0x878, 1), /* MX53_PAD_CSI0_DAT11__UART1_RXD_MUX */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT11, 0x418, 0x0EC, 3, 0x7C4, 1), /* MX53_PAD_CSI0_DAT11__ECSPI2_SS0 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT11, 0x418, 0x0EC, 4, 0x000, 0), /* MX53_PAD_CSI0_DAT11__AUDMUX_AUD3_RXFS */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT11, 0x418, 0x0EC, 5, 0x000, 0), /* MX53_PAD_CSI0_DAT11__SDMA_DEBUG_PC_5 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT11, 0x418, 0x0EC, 6, 0x000, 0), /* MX53_PAD_CSI0_DAT11__EMI_EMI_DEBUG_40 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT11, 0x418, 0x0EC, 7, 0x000, 0), /* MX53_PAD_CSI0_DAT11__TPIU_TRACE_8 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT12, 0x41C, 0x0F0, 0, 0x000, 0), /* MX53_PAD_CSI0_DAT12__IPU_CSI0_D_12 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT12, 0x41C, 0x0F0, 1, 0x000, 0), /* MX53_PAD_CSI0_DAT12__GPIO5_30 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT12, 0x41C, 0x0F0, 2, 0x000, 0), /* MX53_PAD_CSI0_DAT12__UART4_TXD_MUX */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT12, 0x41C, 0x0F0, 4, 0x000, 0), /* MX53_PAD_CSI0_DAT12__USBOH3_USBH3_DATA_0 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT12, 0x41C, 0x0F0, 5, 0x000, 0), /* MX53_PAD_CSI0_DAT12__SDMA_DEBUG_PC_6 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT12, 0x41C, 0x0F0, 6, 0x000, 0), /* MX53_PAD_CSI0_DAT12__EMI_EMI_DEBUG_41 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT12, 0x41C, 0x0F0, 7, 0x000, 0), /* MX53_PAD_CSI0_DAT12__TPIU_TRACE_9 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT13, 0x420, 0x0F4, 0, 0x000, 0), /* MX53_PAD_CSI0_DAT13__IPU_CSI0_D_13 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT13, 0x420, 0x0F4, 1, 0x000, 0), /* MX53_PAD_CSI0_DAT13__GPIO5_31 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT13, 0x420, 0x0F4, 2, 0x890, 3), /* MX53_PAD_CSI0_DAT13__UART4_RXD_MUX */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT13, 0x420, 0x0F4, 4, 0x000, 0), /* MX53_PAD_CSI0_DAT13__USBOH3_USBH3_DATA_1 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT13, 0x420, 0x0F4, 5, 0x000, 0), /* MX53_PAD_CSI0_DAT13__SDMA_DEBUG_PC_7 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT13, 0x420, 0x0F4, 6, 0x000, 0), /* MX53_PAD_CSI0_DAT13__EMI_EMI_DEBUG_42 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT13, 0x420, 0x0F4, 7, 0x000, 0), /* MX53_PAD_CSI0_DAT13__TPIU_TRACE_10 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT14, 0x424, 0x0F8, 0, 0x000, 0), /* MX53_PAD_CSI0_DAT14__IPU_CSI0_D_14 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT14, 0x424, 0x0F8, 1, 0x000, 0), /* MX53_PAD_CSI0_DAT14__GPIO6_0 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT14, 0x424, 0x0F8, 2, 0x000, 0), /* MX53_PAD_CSI0_DAT14__UART5_TXD_MUX */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT14, 0x424, 0x0F8, 4, 0x000, 0), /* MX53_PAD_CSI0_DAT14__USBOH3_USBH3_DATA_2 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT14, 0x424, 0x0F8, 5, 0x000, 0), /* MX53_PAD_CSI0_DAT14__SDMA_DEBUG_PC_8 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT14, 0x424, 0x0F8, 6, 0x000, 0), /* MX53_PAD_CSI0_DAT14__EMI_EMI_DEBUG_43 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT14, 0x424, 0x0F8, 7, 0x000, 0), /* MX53_PAD_CSI0_DAT14__TPIU_TRACE_11 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT15, 0x428, 0x0FC, 0, 0x000, 0), /* MX53_PAD_CSI0_DAT15__IPU_CSI0_D_15 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT15, 0x428, 0x0FC, 1, 0x000, 0), /* MX53_PAD_CSI0_DAT15__GPIO6_1 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT15, 0x428, 0x0FC, 2, 0x898, 3), /* MX53_PAD_CSI0_DAT15__UART5_RXD_MUX */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT15, 0x428, 0x0FC, 4, 0x000, 0), /* MX53_PAD_CSI0_DAT15__USBOH3_USBH3_DATA_3 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT15, 0x428, 0x0FC, 5, 0x000, 0), /* MX53_PAD_CSI0_DAT15__SDMA_DEBUG_PC_9 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT15, 0x428, 0x0FC, 6, 0x000, 0), /* MX53_PAD_CSI0_DAT15__EMI_EMI_DEBUG_44 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT15, 0x428, 0x0FC, 7, 0x000, 0), /* MX53_PAD_CSI0_DAT15__TPIU_TRACE_12 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT16, 0x42C, 0x100, 0, 0x000, 0), /* MX53_PAD_CSI0_DAT16__IPU_CSI0_D_16 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT16, 0x42C, 0x100, 1, 0x000, 0), /* MX53_PAD_CSI0_DAT16__GPIO6_2 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT16, 0x42C, 0x100, 2, 0x88C, 0), /* MX53_PAD_CSI0_DAT16__UART4_RTS */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT16, 0x42C, 0x100, 4, 0x000, 0), /* MX53_PAD_CSI0_DAT16__USBOH3_USBH3_DATA_4 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT16, 0x42C, 0x100, 5, 0x000, 0), /* MX53_PAD_CSI0_DAT16__SDMA_DEBUG_PC_10 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT16, 0x42C, 0x100, 6, 0x000, 0), /* MX53_PAD_CSI0_DAT16__EMI_EMI_DEBUG_45 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT16, 0x42C, 0x100, 7, 0x000, 0), /* MX53_PAD_CSI0_DAT16__TPIU_TRACE_13 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT17, 0x430, 0x104, 0, 0x000, 0), /* MX53_PAD_CSI0_DAT17__IPU_CSI0_D_17 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT17, 0x430, 0x104, 1, 0x000, 0), /* MX53_PAD_CSI0_DAT17__GPIO6_3 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT17, 0x430, 0x104, 2, 0x000, 0), /* MX53_PAD_CSI0_DAT17__UART4_CTS */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT17, 0x430, 0x104, 4, 0x000, 0), /* MX53_PAD_CSI0_DAT17__USBOH3_USBH3_DATA_5 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT17, 0x430, 0x104, 5, 0x000, 0), /* MX53_PAD_CSI0_DAT17__SDMA_DEBUG_PC_11 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT17, 0x430, 0x104, 6, 0x000, 0), /* MX53_PAD_CSI0_DAT17__EMI_EMI_DEBUG_46 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT17, 0x430, 0x104, 7, 0x000, 0), /* MX53_PAD_CSI0_DAT17__TPIU_TRACE_14 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT18, 0x434, 0x108, 0, 0x000, 0), /* MX53_PAD_CSI0_DAT18__IPU_CSI0_D_18 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT18, 0x434, 0x108, 1, 0x000, 0), /* MX53_PAD_CSI0_DAT18__GPIO6_4 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT18, 0x434, 0x108, 2, 0x894, 2), /* MX53_PAD_CSI0_DAT18__UART5_RTS */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT18, 0x434, 0x108, 4, 0x000, 0), /* MX53_PAD_CSI0_DAT18__USBOH3_USBH3_DATA_6 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT18, 0x434, 0x108, 5, 0x000, 0), /* MX53_PAD_CSI0_DAT18__SDMA_DEBUG_PC_12 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT18, 0x434, 0x108, 6, 0x000, 0), /* MX53_PAD_CSI0_DAT18__EMI_EMI_DEBUG_47 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT18, 0x434, 0x108, 7, 0x000, 0), /* MX53_PAD_CSI0_DAT18__TPIU_TRACE_15 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT19, 0x438, 0x10C, 0, 0x000, 0), /* MX53_PAD_CSI0_DAT19__IPU_CSI0_D_19 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT19, 0x438, 0x10C, 1, 0x000, 0), /* MX53_PAD_CSI0_DAT19__GPIO6_5 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT19, 0x438, 0x10C, 2, 0x000, 0), /* MX53_PAD_CSI0_DAT19__UART5_CTS */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT19, 0x438, 0x10C, 4, 0x000, 0), /* MX53_PAD_CSI0_DAT19__USBOH3_USBH3_DATA_7 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT19, 0x438, 0x10C, 5, 0x000, 0), /* MX53_PAD_CSI0_DAT19__SDMA_DEBUG_PC_13 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT19, 0x438, 0x10C, 6, 0x000, 0), /* MX53_PAD_CSI0_DAT19__EMI_EMI_DEBUG_48 */
-	IMX_PIN_REG(MX53_PAD_CSI0_DAT19, 0x438, 0x10C, 7, 0x000, 0), /* MX53_PAD_CSI0_DAT19__USBPHY2_BISTOK */
-	IMX_PIN_REG(MX53_PAD_EIM_A25, 0x458, 0x110, 0, 0x000, 0), /* MX53_PAD_EIM_A25__EMI_WEIM_A_25 */
-	IMX_PIN_REG(MX53_PAD_EIM_A25, 0x458, 0x110, 1, 0x000, 0), /* MX53_PAD_EIM_A25__GPIO5_2 */
-	IMX_PIN_REG(MX53_PAD_EIM_A25, 0x458, 0x110, 2, 0x000, 0), /* MX53_PAD_EIM_A25__ECSPI2_RDY */
-	IMX_PIN_REG(MX53_PAD_EIM_A25, 0x458, 0x110, 3, 0x000, 0), /* MX53_PAD_EIM_A25__IPU_DI1_PIN12 */
-	IMX_PIN_REG(MX53_PAD_EIM_A25, 0x458, 0x110, 4, 0x790, 1), /* MX53_PAD_EIM_A25__CSPI_SS1 */
-	IMX_PIN_REG(MX53_PAD_EIM_A25, 0x458, 0x110, 6, 0x000, 0), /* MX53_PAD_EIM_A25__IPU_DI0_D1_CS */
-	IMX_PIN_REG(MX53_PAD_EIM_A25, 0x458, 0x110, 7, 0x000, 0), /* MX53_PAD_EIM_A25__USBPHY1_BISTOK */
-	IMX_PIN_REG(MX53_PAD_EIM_EB2, 0x45C, 0x114, 0, 0x000, 0), /* MX53_PAD_EIM_EB2__EMI_WEIM_EB_2 */
-	IMX_PIN_REG(MX53_PAD_EIM_EB2, 0x45C, 0x114, 1, 0x000, 0), /* MX53_PAD_EIM_EB2__GPIO2_30 */
-	IMX_PIN_REG(MX53_PAD_EIM_EB2, 0x45C, 0x114, 2, 0x76C, 0), /* MX53_PAD_EIM_EB2__CCM_DI1_EXT_CLK */
-	IMX_PIN_REG(MX53_PAD_EIM_EB2, 0x45C, 0x114, 3, 0x000, 0), /* MX53_PAD_EIM_EB2__IPU_SER_DISP1_CS */
-	IMX_PIN_REG(MX53_PAD_EIM_EB2, 0x45C, 0x114, 4, 0x7A8, 3), /* MX53_PAD_EIM_EB2__ECSPI1_SS0 */
-	IMX_PIN_REG(MX53_PAD_EIM_EB2, 0x45C, 0x114, 5, 0x81C, 1), /* MX53_PAD_EIM_EB2__I2C2_SCL */
-	IMX_PIN_REG(MX53_PAD_EIM_D16, 0x460, 0x118, 0, 0x000, 0), /* MX53_PAD_EIM_D16__EMI_WEIM_D_16 */
-	IMX_PIN_REG(MX53_PAD_EIM_D16, 0x460, 0x118, 1, 0x000, 0), /* MX53_PAD_EIM_D16__GPIO3_16 */
-	IMX_PIN_REG(MX53_PAD_EIM_D16, 0x460, 0x118, 2, 0x000, 0), /* MX53_PAD_EIM_D16__IPU_DI0_PIN5 */
-	IMX_PIN_REG(MX53_PAD_EIM_D16, 0x460, 0x118, 3, 0x000, 0), /* MX53_PAD_EIM_D16__IPU_DISPB1_SER_CLK */
-	IMX_PIN_REG(MX53_PAD_EIM_D16, 0x460, 0x118, 4, 0x79C, 3), /* MX53_PAD_EIM_D16__ECSPI1_SCLK */
-	IMX_PIN_REG(MX53_PAD_EIM_D16, 0x460, 0x118, 5, 0x820, 1), /* MX53_PAD_EIM_D16__I2C2_SDA */
-	IMX_PIN_REG(MX53_PAD_EIM_D17, 0x464, 0x11C, 0, 0x000, 0), /* MX53_PAD_EIM_D17__EMI_WEIM_D_17 */
-	IMX_PIN_REG(MX53_PAD_EIM_D17, 0x464, 0x11C, 1, 0x000, 0), /* MX53_PAD_EIM_D17__GPIO3_17 */
-	IMX_PIN_REG(MX53_PAD_EIM_D17, 0x464, 0x11C, 2, 0x000, 0), /* MX53_PAD_EIM_D17__IPU_DI0_PIN6 */
-	IMX_PIN_REG(MX53_PAD_EIM_D17, 0x464, 0x11C, 3, 0x830, 0), /* MX53_PAD_EIM_D17__IPU_DISPB1_SER_DIN */
-	IMX_PIN_REG(MX53_PAD_EIM_D17, 0x464, 0x11C, 4, 0x7A0, 3), /* MX53_PAD_EIM_D17__ECSPI1_MISO */
-	IMX_PIN_REG(MX53_PAD_EIM_D17, 0x464, 0x11C, 5, 0x824, 0), /* MX53_PAD_EIM_D17__I2C3_SCL */
-	IMX_PIN_REG(MX53_PAD_EIM_D18, 0x468, 0x120, 0, 0x000, 0), /* MX53_PAD_EIM_D18__EMI_WEIM_D_18 */
-	IMX_PIN_REG(MX53_PAD_EIM_D18, 0x468, 0x120, 1, 0x000, 0), /* MX53_PAD_EIM_D18__GPIO3_18 */
-	IMX_PIN_REG(MX53_PAD_EIM_D18, 0x468, 0x120, 2, 0x000, 0), /* MX53_PAD_EIM_D18__IPU_DI0_PIN7 */
-	IMX_PIN_REG(MX53_PAD_EIM_D18, 0x468, 0x120, 3, 0x830, 1), /* MX53_PAD_EIM_D18__IPU_DISPB1_SER_DIO */
-	IMX_PIN_REG(MX53_PAD_EIM_D18, 0x468, 0x120, 4, 0x7A4, 3), /* MX53_PAD_EIM_D18__ECSPI1_MOSI */
-	IMX_PIN_REG(MX53_PAD_EIM_D18, 0x468, 0x120, 5, 0x828, 0), /* MX53_PAD_EIM_D18__I2C3_SDA */
-	IMX_PIN_REG(MX53_PAD_EIM_D18, 0x468, 0x120, 6, 0x000, 0), /* MX53_PAD_EIM_D18__IPU_DI1_D0_CS */
-	IMX_PIN_REG(MX53_PAD_EIM_D19, 0x46C, 0x124, 0, 0x000, 0), /* MX53_PAD_EIM_D19__EMI_WEIM_D_19 */
-	IMX_PIN_REG(MX53_PAD_EIM_D19, 0x46C, 0x124, 1, 0x000, 0), /* MX53_PAD_EIM_D19__GPIO3_19 */
-	IMX_PIN_REG(MX53_PAD_EIM_D19, 0x46C, 0x124, 2, 0x000, 0), /* MX53_PAD_EIM_D19__IPU_DI0_PIN8 */
-	IMX_PIN_REG(MX53_PAD_EIM_D19, 0x46C, 0x124, 3, 0x000, 0), /* MX53_PAD_EIM_D19__IPU_DISPB1_SER_RS */
-	IMX_PIN_REG(MX53_PAD_EIM_D19, 0x46C, 0x124, 4, 0x7AC, 2), /* MX53_PAD_EIM_D19__ECSPI1_SS1 */
-	IMX_PIN_REG(MX53_PAD_EIM_D19, 0x46C, 0x124, 5, 0x000, 0), /* MX53_PAD_EIM_D19__EPIT1_EPITO */
-	IMX_PIN_REG(MX53_PAD_EIM_D19, 0x46C, 0x124, 6, 0x000, 0), /* MX53_PAD_EIM_D19__UART1_CTS */
-	IMX_PIN_REG(MX53_PAD_EIM_D19, 0x46C, 0x124, 7, 0x8A4, 0), /* MX53_PAD_EIM_D19__USBOH3_USBH2_OC */
-	IMX_PIN_REG(MX53_PAD_EIM_D20, 0x470, 0x128, 0, 0x000, 0), /* MX53_PAD_EIM_D20__EMI_WEIM_D_20 */
-	IMX_PIN_REG(MX53_PAD_EIM_D20, 0x470, 0x128, 1, 0x000, 0), /* MX53_PAD_EIM_D20__GPIO3_20 */
-	IMX_PIN_REG(MX53_PAD_EIM_D20, 0x470, 0x128, 2, 0x000, 0), /* MX53_PAD_EIM_D20__IPU_DI0_PIN16 */
-	IMX_PIN_REG(MX53_PAD_EIM_D20, 0x470, 0x128, 3, 0x000, 0), /* MX53_PAD_EIM_D20__IPU_SER_DISP0_CS */
-	IMX_PIN_REG(MX53_PAD_EIM_D20, 0x470, 0x128, 4, 0x78C, 1), /* MX53_PAD_EIM_D20__CSPI_SS0 */
-	IMX_PIN_REG(MX53_PAD_EIM_D20, 0x470, 0x128, 5, 0x000, 0), /* MX53_PAD_EIM_D20__EPIT2_EPITO */
-	IMX_PIN_REG(MX53_PAD_EIM_D20, 0x470, 0x128, 6, 0x874, 1), /* MX53_PAD_EIM_D20__UART1_RTS */
-	IMX_PIN_REG(MX53_PAD_EIM_D20, 0x470, 0x128, 7, 0x000, 0), /* MX53_PAD_EIM_D20__USBOH3_USBH2_PWR */
-	IMX_PIN_REG(MX53_PAD_EIM_D21, 0x474, 0x12C, 0, 0x000, 0), /* MX53_PAD_EIM_D21__EMI_WEIM_D_21 */
-	IMX_PIN_REG(MX53_PAD_EIM_D21, 0x474, 0x12C, 1, 0x000, 0), /* MX53_PAD_EIM_D21__GPIO3_21 */
-	IMX_PIN_REG(MX53_PAD_EIM_D21, 0x474, 0x12C, 2, 0x000, 0), /* MX53_PAD_EIM_D21__IPU_DI0_PIN17 */
-	IMX_PIN_REG(MX53_PAD_EIM_D21, 0x474, 0x12C, 3, 0x000, 0), /* MX53_PAD_EIM_D21__IPU_DISPB0_SER_CLK */
-	IMX_PIN_REG(MX53_PAD_EIM_D21, 0x474, 0x12C, 4, 0x780, 1), /* MX53_PAD_EIM_D21__CSPI_SCLK */
-	IMX_PIN_REG(MX53_PAD_EIM_D21, 0x474, 0x12C, 5, 0x814, 1), /* MX53_PAD_EIM_D21__I2C1_SCL */
-	IMX_PIN_REG(MX53_PAD_EIM_D21, 0x474, 0x12C, 6, 0x89C, 1), /* MX53_PAD_EIM_D21__USBOH3_USBOTG_OC */
-	IMX_PIN_REG(MX53_PAD_EIM_D22, 0x478, 0x130, 0, 0x000, 0), /* MX53_PAD_EIM_D22__EMI_WEIM_D_22 */
-	IMX_PIN_REG(MX53_PAD_EIM_D22, 0x478, 0x130, 1, 0x000, 0), /* MX53_PAD_EIM_D22__GPIO3_22 */
-	IMX_PIN_REG(MX53_PAD_EIM_D22, 0x478, 0x130, 2, 0x000, 0), /* MX53_PAD_EIM_D22__IPU_DI0_PIN1 */
-	IMX_PIN_REG(MX53_PAD_EIM_D22, 0x478, 0x130, 3, 0x82C, 0), /* MX53_PAD_EIM_D22__IPU_DISPB0_SER_DIN */
-	IMX_PIN_REG(MX53_PAD_EIM_D22, 0x478, 0x130, 4, 0x784, 1), /* MX53_PAD_EIM_D22__CSPI_MISO */
-	IMX_PIN_REG(MX53_PAD_EIM_D22, 0x478, 0x130, 6, 0x000, 0), /* MX53_PAD_EIM_D22__USBOH3_USBOTG_PWR */
-	IMX_PIN_REG(MX53_PAD_EIM_D23, 0x47C, 0x134, 0, 0x000, 0), /* MX53_PAD_EIM_D23__EMI_WEIM_D_23 */
-	IMX_PIN_REG(MX53_PAD_EIM_D23, 0x47C, 0x134, 1, 0x000, 0), /* MX53_PAD_EIM_D23__GPIO3_23 */
-	IMX_PIN_REG(MX53_PAD_EIM_D23, 0x47C, 0x134, 2, 0x000, 0), /* MX53_PAD_EIM_D23__UART3_CTS */
-	IMX_PIN_REG(MX53_PAD_EIM_D23, 0x47C, 0x134, 3, 0x000, 0), /* MX53_PAD_EIM_D23__UART1_DCD */
-	IMX_PIN_REG(MX53_PAD_EIM_D23, 0x47C, 0x134, 4, 0x000, 0), /* MX53_PAD_EIM_D23__IPU_DI0_D0_CS */
-	IMX_PIN_REG(MX53_PAD_EIM_D23, 0x47C, 0x134, 5, 0x000, 0), /* MX53_PAD_EIM_D23__IPU_DI1_PIN2 */
-	IMX_PIN_REG(MX53_PAD_EIM_D23, 0x47C, 0x134, 6, 0x834, 0), /* MX53_PAD_EIM_D23__IPU_CSI1_DATA_EN */
-	IMX_PIN_REG(MX53_PAD_EIM_D23, 0x47C, 0x134, 7, 0x000, 0), /* MX53_PAD_EIM_D23__IPU_DI1_PIN14 */
-	IMX_PIN_REG(MX53_PAD_EIM_EB3, 0x480, 0x138, 0, 0x000, 0), /* MX53_PAD_EIM_EB3__EMI_WEIM_EB_3 */
-	IMX_PIN_REG(MX53_PAD_EIM_EB3, 0x480, 0x138, 1, 0x000, 0), /* MX53_PAD_EIM_EB3__GPIO2_31 */
-	IMX_PIN_REG(MX53_PAD_EIM_EB3, 0x480, 0x138, 2, 0x884, 1), /* MX53_PAD_EIM_EB3__UART3_RTS */
-	IMX_PIN_REG(MX53_PAD_EIM_EB3, 0x480, 0x138, 3, 0x000, 0), /* MX53_PAD_EIM_EB3__UART1_RI */
-	IMX_PIN_REG(MX53_PAD_EIM_EB3, 0x480, 0x138, 5, 0x000, 0), /* MX53_PAD_EIM_EB3__IPU_DI1_PIN3 */
-	IMX_PIN_REG(MX53_PAD_EIM_EB3, 0x480, 0x138, 6, 0x838, 0), /* MX53_PAD_EIM_EB3__IPU_CSI1_HSYNC */
-	IMX_PIN_REG(MX53_PAD_EIM_EB3, 0x480, 0x138, 7, 0x000, 0), /* MX53_PAD_EIM_EB3__IPU_DI1_PIN16 */
-	IMX_PIN_REG(MX53_PAD_EIM_D24, 0x484, 0x13C, 0, 0x000, 0), /* MX53_PAD_EIM_D24__EMI_WEIM_D_24 */
-	IMX_PIN_REG(MX53_PAD_EIM_D24, 0x484, 0x13C, 1, 0x000, 0), /* MX53_PAD_EIM_D24__GPIO3_24 */
-	IMX_PIN_REG(MX53_PAD_EIM_D24, 0x484, 0x13C, 2, 0x000, 0), /* MX53_PAD_EIM_D24__UART3_TXD_MUX */
-	IMX_PIN_REG(MX53_PAD_EIM_D24, 0x484, 0x13C, 3, 0x7B0, 1), /* MX53_PAD_EIM_D24__ECSPI1_SS2 */
-	IMX_PIN_REG(MX53_PAD_EIM_D24, 0x484, 0x13C, 4, 0x794, 1), /* MX53_PAD_EIM_D24__CSPI_SS2 */
-	IMX_PIN_REG(MX53_PAD_EIM_D24, 0x484, 0x13C, 5, 0x754, 1), /* MX53_PAD_EIM_D24__AUDMUX_AUD5_RXFS */
-	IMX_PIN_REG(MX53_PAD_EIM_D24, 0x484, 0x13C, 6, 0x000, 0), /* MX53_PAD_EIM_D24__ECSPI2_SS2 */
-	IMX_PIN_REG(MX53_PAD_EIM_D24, 0x484, 0x13C, 7, 0x000, 0), /* MX53_PAD_EIM_D24__UART1_DTR */
-	IMX_PIN_REG(MX53_PAD_EIM_D25, 0x488, 0x140, 0, 0x000, 0), /* MX53_PAD_EIM_D25__EMI_WEIM_D_25 */
-	IMX_PIN_REG(MX53_PAD_EIM_D25, 0x488, 0x140, 1, 0x000, 0), /* MX53_PAD_EIM_D25__GPIO3_25 */
-	IMX_PIN_REG(MX53_PAD_EIM_D25, 0x488, 0x140, 2, 0x888, 1), /* MX53_PAD_EIM_D25__UART3_RXD_MUX */
-	IMX_PIN_REG(MX53_PAD_EIM_D25, 0x488, 0x140, 3, 0x7B4, 1), /* MX53_PAD_EIM_D25__ECSPI1_SS3 */
-	IMX_PIN_REG(MX53_PAD_EIM_D25, 0x488, 0x140, 4, 0x798, 1), /* MX53_PAD_EIM_D25__CSPI_SS3 */
-	IMX_PIN_REG(MX53_PAD_EIM_D25, 0x488, 0x140, 5, 0x750, 1), /* MX53_PAD_EIM_D25__AUDMUX_AUD5_RXC */
-	IMX_PIN_REG(MX53_PAD_EIM_D25, 0x488, 0x140, 6, 0x000, 0), /* MX53_PAD_EIM_D25__ECSPI2_SS3 */
-	IMX_PIN_REG(MX53_PAD_EIM_D25, 0x488, 0x140, 7, 0x000, 0), /* MX53_PAD_EIM_D25__UART1_DSR */
-	IMX_PIN_REG(MX53_PAD_EIM_D26, 0x48C, 0x144, 0, 0x000, 0), /* MX53_PAD_EIM_D26__EMI_WEIM_D_26 */
-	IMX_PIN_REG(MX53_PAD_EIM_D26, 0x48C, 0x144, 1, 0x000, 0), /* MX53_PAD_EIM_D26__GPIO3_26 */
-	IMX_PIN_REG(MX53_PAD_EIM_D26, 0x48C, 0x144, 2, 0x000, 0), /* MX53_PAD_EIM_D26__UART2_TXD_MUX */
-	IMX_PIN_REG(MX53_PAD_EIM_D26, 0x48C, 0x144, 3, 0x80C, 0), /* MX53_PAD_EIM_D26__FIRI_RXD */
-	IMX_PIN_REG(MX53_PAD_EIM_D26, 0x48C, 0x144, 4, 0x000, 0), /* MX53_PAD_EIM_D26__IPU_CSI0_D_1 */
-	IMX_PIN_REG(MX53_PAD_EIM_D26, 0x48C, 0x144, 5, 0x000, 0), /* MX53_PAD_EIM_D26__IPU_DI1_PIN11 */
-	IMX_PIN_REG(MX53_PAD_EIM_D26, 0x48C, 0x144, 6, 0x000, 0), /* MX53_PAD_EIM_D26__IPU_SISG_2 */
-	IMX_PIN_REG(MX53_PAD_EIM_D26, 0x48C, 0x144, 7, 0x000, 0), /* MX53_PAD_EIM_D26__IPU_DISP1_DAT_22 */
-	IMX_PIN_REG(MX53_PAD_EIM_D27, 0x490, 0x148, 0, 0x000, 0), /* MX53_PAD_EIM_D27__EMI_WEIM_D_27 */
-	IMX_PIN_REG(MX53_PAD_EIM_D27, 0x490, 0x148, 1, 0x000, 0), /* MX53_PAD_EIM_D27__GPIO3_27 */
-	IMX_PIN_REG(MX53_PAD_EIM_D27, 0x490, 0x148, 2, 0x880, 1), /* MX53_PAD_EIM_D27__UART2_RXD_MUX */
-	IMX_PIN_REG(MX53_PAD_EIM_D27, 0x490, 0x148, 3, 0x000, 0), /* MX53_PAD_EIM_D27__FIRI_TXD */
-	IMX_PIN_REG(MX53_PAD_EIM_D27, 0x490, 0x148, 4, 0x000, 0), /* MX53_PAD_EIM_D27__IPU_CSI0_D_0 */
-	IMX_PIN_REG(MX53_PAD_EIM_D27, 0x490, 0x148, 5, 0x000, 0), /* MX53_PAD_EIM_D27__IPU_DI1_PIN13 */
-	IMX_PIN_REG(MX53_PAD_EIM_D27, 0x490, 0x148, 6, 0x000, 0), /* MX53_PAD_EIM_D27__IPU_SISG_3 */
-	IMX_PIN_REG(MX53_PAD_EIM_D27, 0x490, 0x148, 7, 0x000, 0), /* MX53_PAD_EIM_D27__IPU_DISP1_DAT_23 */
-	IMX_PIN_REG(MX53_PAD_EIM_D28, 0x494, 0x14C, 0, 0x000, 0), /* MX53_PAD_EIM_D28__EMI_WEIM_D_28 */
-	IMX_PIN_REG(MX53_PAD_EIM_D28, 0x494, 0x14C, 1, 0x000, 0), /* MX53_PAD_EIM_D28__GPIO3_28 */
-	IMX_PIN_REG(MX53_PAD_EIM_D28, 0x494, 0x14C, 2, 0x000, 0), /* MX53_PAD_EIM_D28__UART2_CTS */
-	IMX_PIN_REG(MX53_PAD_EIM_D28, 0x494, 0x14C, 3, 0x82C, 1), /* MX53_PAD_EIM_D28__IPU_DISPB0_SER_DIO */
-	IMX_PIN_REG(MX53_PAD_EIM_D28, 0x494, 0x14C, 4, 0x788, 1), /* MX53_PAD_EIM_D28__CSPI_MOSI */
-	IMX_PIN_REG(MX53_PAD_EIM_D28, 0x494, 0x14C, 5, 0x818, 1), /* MX53_PAD_EIM_D28__I2C1_SDA */
-	IMX_PIN_REG(MX53_PAD_EIM_D28, 0x494, 0x14C, 6, 0x000, 0), /* MX53_PAD_EIM_D28__IPU_EXT_TRIG */
-	IMX_PIN_REG(MX53_PAD_EIM_D28, 0x494, 0x14C, 7, 0x000, 0), /* MX53_PAD_EIM_D28__IPU_DI0_PIN13 */
-	IMX_PIN_REG(MX53_PAD_EIM_D29, 0x498, 0x150, 0, 0x000, 0), /* MX53_PAD_EIM_D29__EMI_WEIM_D_29 */
-	IMX_PIN_REG(MX53_PAD_EIM_D29, 0x498, 0x150, 1, 0x000, 0), /* MX53_PAD_EIM_D29__GPIO3_29 */
-	IMX_PIN_REG(MX53_PAD_EIM_D29, 0x498, 0x150, 2, 0x87C, 1), /* MX53_PAD_EIM_D29__UART2_RTS */
-	IMX_PIN_REG(MX53_PAD_EIM_D29, 0x498, 0x150, 3, 0x000, 0), /* MX53_PAD_EIM_D29__IPU_DISPB0_SER_RS */
-	IMX_PIN_REG(MX53_PAD_EIM_D29, 0x498, 0x150, 4, 0x78C, 2), /* MX53_PAD_EIM_D29__CSPI_SS0 */
-	IMX_PIN_REG(MX53_PAD_EIM_D29, 0x498, 0x150, 5, 0x000, 0), /* MX53_PAD_EIM_D29__IPU_DI1_PIN15 */
-	IMX_PIN_REG(MX53_PAD_EIM_D29, 0x498, 0x150, 6, 0x83C, 0), /* MX53_PAD_EIM_D29__IPU_CSI1_VSYNC */
-	IMX_PIN_REG(MX53_PAD_EIM_D29, 0x498, 0x150, 7, 0x000, 0), /* MX53_PAD_EIM_D29__IPU_DI0_PIN14 */
-	IMX_PIN_REG(MX53_PAD_EIM_D30, 0x49C, 0x154, 0, 0x000, 0), /* MX53_PAD_EIM_D30__EMI_WEIM_D_30 */
-	IMX_PIN_REG(MX53_PAD_EIM_D30, 0x49C, 0x154, 1, 0x000, 0), /* MX53_PAD_EIM_D30__GPIO3_30 */
-	IMX_PIN_REG(MX53_PAD_EIM_D30, 0x49C, 0x154, 2, 0x000, 0), /* MX53_PAD_EIM_D30__UART3_CTS */
-	IMX_PIN_REG(MX53_PAD_EIM_D30, 0x49C, 0x154, 3, 0x000, 0), /* MX53_PAD_EIM_D30__IPU_CSI0_D_3 */
-	IMX_PIN_REG(MX53_PAD_EIM_D30, 0x49C, 0x154, 4, 0x000, 0), /* MX53_PAD_EIM_D30__IPU_DI0_PIN11 */
-	IMX_PIN_REG(MX53_PAD_EIM_D30, 0x49C, 0x154, 5, 0x000, 0), /* MX53_PAD_EIM_D30__IPU_DISP1_DAT_21 */
-	IMX_PIN_REG(MX53_PAD_EIM_D30, 0x49C, 0x154, 6, 0x8A0, 0), /* MX53_PAD_EIM_D30__USBOH3_USBH1_OC */
-	IMX_PIN_REG(MX53_PAD_EIM_D30, 0x49C, 0x154, 7, 0x8A4, 1), /* MX53_PAD_EIM_D30__USBOH3_USBH2_OC */
-	IMX_PIN_REG(MX53_PAD_EIM_D31, 0x4A0, 0x158, 0, 0x000, 0), /* MX53_PAD_EIM_D31__EMI_WEIM_D_31 */
-	IMX_PIN_REG(MX53_PAD_EIM_D31, 0x4A0, 0x158, 1, 0x000, 0), /* MX53_PAD_EIM_D31__GPIO3_31 */
-	IMX_PIN_REG(MX53_PAD_EIM_D31, 0x4A0, 0x158, 2, 0x884, 3), /* MX53_PAD_EIM_D31__UART3_RTS */
-	IMX_PIN_REG(MX53_PAD_EIM_D31, 0x4A0, 0x158, 3, 0x000, 0), /* MX53_PAD_EIM_D31__IPU_CSI0_D_2 */
-	IMX_PIN_REG(MX53_PAD_EIM_D31, 0x4A0, 0x158, 4, 0x000, 0), /* MX53_PAD_EIM_D31__IPU_DI0_PIN12 */
-	IMX_PIN_REG(MX53_PAD_EIM_D31, 0x4A0, 0x158, 5, 0x000, 0), /* MX53_PAD_EIM_D31__IPU_DISP1_DAT_20 */
-	IMX_PIN_REG(MX53_PAD_EIM_D31, 0x4A0, 0x158, 6, 0x000, 0), /* MX53_PAD_EIM_D31__USBOH3_USBH1_PWR */
-	IMX_PIN_REG(MX53_PAD_EIM_D31, 0x4A0, 0x158, 7, 0x000, 0), /* MX53_PAD_EIM_D31__USBOH3_USBH2_PWR */
-	IMX_PIN_REG(MX53_PAD_EIM_A24, 0x4A8, 0x15C, 0, 0x000, 0), /* MX53_PAD_EIM_A24__EMI_WEIM_A_24 */
-	IMX_PIN_REG(MX53_PAD_EIM_A24, 0x4A8, 0x15C, 1, 0x000, 0), /* MX53_PAD_EIM_A24__GPIO5_4 */
-	IMX_PIN_REG(MX53_PAD_EIM_A24, 0x4A8, 0x15C, 2, 0x000, 0), /* MX53_PAD_EIM_A24__IPU_DISP1_DAT_19 */
-	IMX_PIN_REG(MX53_PAD_EIM_A24, 0x4A8, 0x15C, 3, 0x000, 0), /* MX53_PAD_EIM_A24__IPU_CSI1_D_19 */
-	IMX_PIN_REG(MX53_PAD_EIM_A24, 0x4A8, 0x15C, 6, 0x000, 0), /* MX53_PAD_EIM_A24__IPU_SISG_2 */
-	IMX_PIN_REG(MX53_PAD_EIM_A24, 0x4A8, 0x15C, 7, 0x000, 0), /* MX53_PAD_EIM_A24__USBPHY2_BVALID */
-	IMX_PIN_REG(MX53_PAD_EIM_A23, 0x4AC, 0x160, 0, 0x000, 0), /* MX53_PAD_EIM_A23__EMI_WEIM_A_23 */
-	IMX_PIN_REG(MX53_PAD_EIM_A23, 0x4AC, 0x160, 1, 0x000, 0), /* MX53_PAD_EIM_A23__GPIO6_6 */
-	IMX_PIN_REG(MX53_PAD_EIM_A23, 0x4AC, 0x160, 2, 0x000, 0), /* MX53_PAD_EIM_A23__IPU_DISP1_DAT_18 */
-	IMX_PIN_REG(MX53_PAD_EIM_A23, 0x4AC, 0x160, 3, 0x000, 0), /* MX53_PAD_EIM_A23__IPU_CSI1_D_18 */
-	IMX_PIN_REG(MX53_PAD_EIM_A23, 0x4AC, 0x160, 6, 0x000, 0), /* MX53_PAD_EIM_A23__IPU_SISG_3 */
-	IMX_PIN_REG(MX53_PAD_EIM_A23, 0x4AC, 0x160, 7, 0x000, 0), /* MX53_PAD_EIM_A23__USBPHY2_ENDSESSION */
-	IMX_PIN_REG(MX53_PAD_EIM_A22, 0x4B0, 0x164, 0, 0x000, 0), /* MX53_PAD_EIM_A22__EMI_WEIM_A_22 */
-	IMX_PIN_REG(MX53_PAD_EIM_A22, 0x4B0, 0x164, 1, 0x000, 0), /* MX53_PAD_EIM_A22__GPIO2_16 */
-	IMX_PIN_REG(MX53_PAD_EIM_A22, 0x4B0, 0x164, 2, 0x000, 0), /* MX53_PAD_EIM_A22__IPU_DISP1_DAT_17 */
-	IMX_PIN_REG(MX53_PAD_EIM_A22, 0x4B0, 0x164, 3, 0x000, 0), /* MX53_PAD_EIM_A22__IPU_CSI1_D_17 */
-	IMX_PIN_REG(MX53_PAD_EIM_A22, 0x4B0, 0x164, 7, 0x000, 0), /* MX53_PAD_EIM_A22__SRC_BT_CFG1_7 */
-	IMX_PIN_REG(MX53_PAD_EIM_A21, 0x4B4, 0x168, 0, 0x000, 0), /* MX53_PAD_EIM_A21__EMI_WEIM_A_21 */
-	IMX_PIN_REG(MX53_PAD_EIM_A21, 0x4B4, 0x168, 1, 0x000, 0), /* MX53_PAD_EIM_A21__GPIO2_17 */
-	IMX_PIN_REG(MX53_PAD_EIM_A21, 0x4B4, 0x168, 2, 0x000, 0), /* MX53_PAD_EIM_A21__IPU_DISP1_DAT_16 */
-	IMX_PIN_REG(MX53_PAD_EIM_A21, 0x4B4, 0x168, 3, 0x000, 0), /* MX53_PAD_EIM_A21__IPU_CSI1_D_16 */
-	IMX_PIN_REG(MX53_PAD_EIM_A21, 0x4B4, 0x168, 7, 0x000, 0), /* MX53_PAD_EIM_A21__SRC_BT_CFG1_6 */
-	IMX_PIN_REG(MX53_PAD_EIM_A20, 0x4B8, 0x16C, 0, 0x000, 0), /* MX53_PAD_EIM_A20__EMI_WEIM_A_20 */
-	IMX_PIN_REG(MX53_PAD_EIM_A20, 0x4B8, 0x16C, 1, 0x000, 0), /* MX53_PAD_EIM_A20__GPIO2_18 */
-	IMX_PIN_REG(MX53_PAD_EIM_A20, 0x4B8, 0x16C, 2, 0x000, 0), /* MX53_PAD_EIM_A20__IPU_DISP1_DAT_15 */
-	IMX_PIN_REG(MX53_PAD_EIM_A20, 0x4B8, 0x16C, 3, 0x000, 0), /* MX53_PAD_EIM_A20__IPU_CSI1_D_15 */
-	IMX_PIN_REG(MX53_PAD_EIM_A20, 0x4B8, 0x16C, 7, 0x000, 0), /* MX53_PAD_EIM_A20__SRC_BT_CFG1_5 */
-	IMX_PIN_REG(MX53_PAD_EIM_A19, 0x4BC, 0x170, 0, 0x000, 0), /* MX53_PAD_EIM_A19__EMI_WEIM_A_19 */
-	IMX_PIN_REG(MX53_PAD_EIM_A19, 0x4BC, 0x170, 1, 0x000, 0), /* MX53_PAD_EIM_A19__GPIO2_19 */
-	IMX_PIN_REG(MX53_PAD_EIM_A19, 0x4BC, 0x170, 2, 0x000, 0), /* MX53_PAD_EIM_A19__IPU_DISP1_DAT_14 */
-	IMX_PIN_REG(MX53_PAD_EIM_A19, 0x4BC, 0x170, 3, 0x000, 0), /* MX53_PAD_EIM_A19__IPU_CSI1_D_14 */
-	IMX_PIN_REG(MX53_PAD_EIM_A19, 0x4BC, 0x170, 7, 0x000, 0), /* MX53_PAD_EIM_A19__SRC_BT_CFG1_4 */
-	IMX_PIN_REG(MX53_PAD_EIM_A18, 0x4C0, 0x174, 0, 0x000, 0), /* MX53_PAD_EIM_A18__EMI_WEIM_A_18 */
-	IMX_PIN_REG(MX53_PAD_EIM_A18, 0x4C0, 0x174, 1, 0x000, 0), /* MX53_PAD_EIM_A18__GPIO2_20 */
-	IMX_PIN_REG(MX53_PAD_EIM_A18, 0x4C0, 0x174, 2, 0x000, 0), /* MX53_PAD_EIM_A18__IPU_DISP1_DAT_13 */
-	IMX_PIN_REG(MX53_PAD_EIM_A18, 0x4C0, 0x174, 3, 0x000, 0), /* MX53_PAD_EIM_A18__IPU_CSI1_D_13 */
-	IMX_PIN_REG(MX53_PAD_EIM_A18, 0x4C0, 0x174, 7, 0x000, 0), /* MX53_PAD_EIM_A18__SRC_BT_CFG1_3 */
-	IMX_PIN_REG(MX53_PAD_EIM_A17, 0x4C4, 0x178, 0, 0x000, 0), /* MX53_PAD_EIM_A17__EMI_WEIM_A_17 */
-	IMX_PIN_REG(MX53_PAD_EIM_A17, 0x4C4, 0x178, 1, 0x000, 0), /* MX53_PAD_EIM_A17__GPIO2_21 */
-	IMX_PIN_REG(MX53_PAD_EIM_A17, 0x4C4, 0x178, 2, 0x000, 0), /* MX53_PAD_EIM_A17__IPU_DISP1_DAT_12 */
-	IMX_PIN_REG(MX53_PAD_EIM_A17, 0x4C4, 0x178, 3, 0x000, 0), /* MX53_PAD_EIM_A17__IPU_CSI1_D_12 */
-	IMX_PIN_REG(MX53_PAD_EIM_A17, 0x4C4, 0x178, 7, 0x000, 0), /* MX53_PAD_EIM_A17__SRC_BT_CFG1_2 */
-	IMX_PIN_REG(MX53_PAD_EIM_A16, 0x4C8, 0x17C, 0, 0x000, 0), /* MX53_PAD_EIM_A16__EMI_WEIM_A_16 */
-	IMX_PIN_REG(MX53_PAD_EIM_A16, 0x4C8, 0x17C, 1, 0x000, 0), /* MX53_PAD_EIM_A16__GPIO2_22 */
-	IMX_PIN_REG(MX53_PAD_EIM_A16, 0x4C8, 0x17C, 2, 0x000, 0), /* MX53_PAD_EIM_A16__IPU_DI1_DISP_CLK */
-	IMX_PIN_REG(MX53_PAD_EIM_A16, 0x4C8, 0x17C, 3, 0x000, 0), /* MX53_PAD_EIM_A16__IPU_CSI1_PIXCLK */
-	IMX_PIN_REG(MX53_PAD_EIM_A16, 0x4C8, 0x17C, 7, 0x000, 0), /* MX53_PAD_EIM_A16__SRC_BT_CFG1_1 */
-	IMX_PIN_REG(MX53_PAD_EIM_CS0, 0x4CC, 0x180, 0, 0x000, 0), /* MX53_PAD_EIM_CS0__EMI_WEIM_CS_0 */
-	IMX_PIN_REG(MX53_PAD_EIM_CS0, 0x4CC, 0x180, 1, 0x000, 0), /* MX53_PAD_EIM_CS0__GPIO2_23 */
-	IMX_PIN_REG(MX53_PAD_EIM_CS0, 0x4CC, 0x180, 2, 0x7B8, 2), /* MX53_PAD_EIM_CS0__ECSPI2_SCLK */
-	IMX_PIN_REG(MX53_PAD_EIM_CS0, 0x4CC, 0x180, 3, 0x000, 0), /* MX53_PAD_EIM_CS0__IPU_DI1_PIN5 */
-	IMX_PIN_REG(MX53_PAD_EIM_CS1, 0x4D0, 0x184, 0, 0x000, 0), /* MX53_PAD_EIM_CS1__EMI_WEIM_CS_1 */
-	IMX_PIN_REG(MX53_PAD_EIM_CS1, 0x4D0, 0x184, 1, 0x000, 0), /* MX53_PAD_EIM_CS1__GPIO2_24 */
-	IMX_PIN_REG(MX53_PAD_EIM_CS1, 0x4D0, 0x184, 2, 0x7C0, 2), /* MX53_PAD_EIM_CS1__ECSPI2_MOSI */
-	IMX_PIN_REG(MX53_PAD_EIM_CS1, 0x4D0, 0x184, 3, 0x000, 0), /* MX53_PAD_EIM_CS1__IPU_DI1_PIN6 */
-	IMX_PIN_REG(MX53_PAD_EIM_OE, 0x4D4, 0x188, 0, 0x000, 0), /* MX53_PAD_EIM_OE__EMI_WEIM_OE */
-	IMX_PIN_REG(MX53_PAD_EIM_OE, 0x4D4, 0x188, 1, 0x000, 0), /* MX53_PAD_EIM_OE__GPIO2_25 */
-	IMX_PIN_REG(MX53_PAD_EIM_OE, 0x4D4, 0x188, 2, 0x7BC, 2), /* MX53_PAD_EIM_OE__ECSPI2_MISO */
-	IMX_PIN_REG(MX53_PAD_EIM_OE, 0x4D4, 0x188, 3, 0x000, 0), /* MX53_PAD_EIM_OE__IPU_DI1_PIN7 */
-	IMX_PIN_REG(MX53_PAD_EIM_OE, 0x4D4, 0x188, 7, 0x000, 0), /* MX53_PAD_EIM_OE__USBPHY2_IDDIG */
-	IMX_PIN_REG(MX53_PAD_EIM_RW, 0x4D8, 0x18C, 0, 0x000, 0), /* MX53_PAD_EIM_RW__EMI_WEIM_RW */
-	IMX_PIN_REG(MX53_PAD_EIM_RW, 0x4D8, 0x18C, 1, 0x000, 0), /* MX53_PAD_EIM_RW__GPIO2_26 */
-	IMX_PIN_REG(MX53_PAD_EIM_RW, 0x4D8, 0x18C, 2, 0x7C4, 2), /* MX53_PAD_EIM_RW__ECSPI2_SS0 */
-	IMX_PIN_REG(MX53_PAD_EIM_RW, 0x4D8, 0x18C, 3, 0x000, 0), /* MX53_PAD_EIM_RW__IPU_DI1_PIN8 */
-	IMX_PIN_REG(MX53_PAD_EIM_RW, 0x4D8, 0x18C, 7, 0x000, 0), /* MX53_PAD_EIM_RW__USBPHY2_HOSTDISCONNECT */
-	IMX_PIN_REG(MX53_PAD_EIM_LBA, 0x4DC, 0x190, 0, 0x000, 0), /* MX53_PAD_EIM_LBA__EMI_WEIM_LBA */
-	IMX_PIN_REG(MX53_PAD_EIM_LBA, 0x4DC, 0x190, 1, 0x000, 0), /* MX53_PAD_EIM_LBA__GPIO2_27 */
-	IMX_PIN_REG(MX53_PAD_EIM_LBA, 0x4DC, 0x190, 2, 0x7C8, 1), /* MX53_PAD_EIM_LBA__ECSPI2_SS1 */
-	IMX_PIN_REG(MX53_PAD_EIM_LBA, 0x4DC, 0x190, 3, 0x000, 0), /* MX53_PAD_EIM_LBA__IPU_DI1_PIN17 */
-	IMX_PIN_REG(MX53_PAD_EIM_LBA, 0x4DC, 0x190, 7, 0x000, 0), /* MX53_PAD_EIM_LBA__SRC_BT_CFG1_0 */
-	IMX_PIN_REG(MX53_PAD_EIM_EB0, 0x4E4, 0x194, 0, 0x000, 0), /* MX53_PAD_EIM_EB0__EMI_WEIM_EB_0 */
-	IMX_PIN_REG(MX53_PAD_EIM_EB0, 0x4E4, 0x194, 1, 0x000, 0), /* MX53_PAD_EIM_EB0__GPIO2_28 */
-	IMX_PIN_REG(MX53_PAD_EIM_EB0, 0x4E4, 0x194, 3, 0x000, 0), /* MX53_PAD_EIM_EB0__IPU_DISP1_DAT_11 */
-	IMX_PIN_REG(MX53_PAD_EIM_EB0, 0x4E4, 0x194, 4, 0x000, 0), /* MX53_PAD_EIM_EB0__IPU_CSI1_D_11 */
-	IMX_PIN_REG(MX53_PAD_EIM_EB0, 0x4E4, 0x194, 5, 0x810, 0), /* MX53_PAD_EIM_EB0__GPC_PMIC_RDY */
-	IMX_PIN_REG(MX53_PAD_EIM_EB0, 0x4E4, 0x194, 7, 0x000, 0), /* MX53_PAD_EIM_EB0__SRC_BT_CFG2_7 */
-	IMX_PIN_REG(MX53_PAD_EIM_EB1, 0x4E8, 0x198, 0, 0x000, 0), /* MX53_PAD_EIM_EB1__EMI_WEIM_EB_1 */
-	IMX_PIN_REG(MX53_PAD_EIM_EB1, 0x4E8, 0x198, 1, 0x000, 0), /* MX53_PAD_EIM_EB1__GPIO2_29 */
-	IMX_PIN_REG(MX53_PAD_EIM_EB1, 0x4E8, 0x198, 3, 0x000, 0), /* MX53_PAD_EIM_EB1__IPU_DISP1_DAT_10 */
-	IMX_PIN_REG(MX53_PAD_EIM_EB1, 0x4E8, 0x198, 4, 0x000, 0), /* MX53_PAD_EIM_EB1__IPU_CSI1_D_10 */
-	IMX_PIN_REG(MX53_PAD_EIM_EB1, 0x4E8, 0x198, 7, 0x000, 0), /* MX53_PAD_EIM_EB1__SRC_BT_CFG2_6 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA0, 0x4EC, 0x19C, 0, 0x000, 0), /* MX53_PAD_EIM_DA0__EMI_NAND_WEIM_DA_0 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA0, 0x4EC, 0x19C, 1, 0x000, 0), /* MX53_PAD_EIM_DA0__GPIO3_0 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA0, 0x4EC, 0x19C, 3, 0x000, 0), /* MX53_PAD_EIM_DA0__IPU_DISP1_DAT_9 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA0, 0x4EC, 0x19C, 4, 0x000, 0), /* MX53_PAD_EIM_DA0__IPU_CSI1_D_9 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA0, 0x4EC, 0x19C, 7, 0x000, 0), /* MX53_PAD_EIM_DA0__SRC_BT_CFG2_5 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA1, 0x4F0, 0x1A0, 0, 0x000, 0), /* MX53_PAD_EIM_DA1__EMI_NAND_WEIM_DA_1 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA1, 0x4F0, 0x1A0, 1, 0x000, 0), /* MX53_PAD_EIM_DA1__GPIO3_1 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA1, 0x4F0, 0x1A0, 3, 0x000, 0), /* MX53_PAD_EIM_DA1__IPU_DISP1_DAT_8 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA1, 0x4F0, 0x1A0, 4, 0x000, 0), /* MX53_PAD_EIM_DA1__IPU_CSI1_D_8 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA1, 0x4F0, 0x1A0, 7, 0x000, 0), /* MX53_PAD_EIM_DA1__SRC_BT_CFG2_4 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA2, 0x4F4, 0x1A4, 0, 0x000, 0), /* MX53_PAD_EIM_DA2__EMI_NAND_WEIM_DA_2 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA2, 0x4F4, 0x1A4, 1, 0x000, 0), /* MX53_PAD_EIM_DA2__GPIO3_2 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA2, 0x4F4, 0x1A4, 3, 0x000, 0), /* MX53_PAD_EIM_DA2__IPU_DISP1_DAT_7 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA2, 0x4F4, 0x1A4, 4, 0x000, 0), /* MX53_PAD_EIM_DA2__IPU_CSI1_D_7 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA2, 0x4F4, 0x1A4, 7, 0x000, 0), /* MX53_PAD_EIM_DA2__SRC_BT_CFG2_3 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA3, 0x4F8, 0x1A8, 0, 0x000, 0), /* MX53_PAD_EIM_DA3__EMI_NAND_WEIM_DA_3 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA3, 0x4F8, 0x1A8, 1, 0x000, 0), /* MX53_PAD_EIM_DA3__GPIO3_3 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA3, 0x4F8, 0x1A8, 3, 0x000, 0), /* MX53_PAD_EIM_DA3__IPU_DISP1_DAT_6 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA3, 0x4F8, 0x1A8, 4, 0x000, 0), /* MX53_PAD_EIM_DA3__IPU_CSI1_D_6 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA3, 0x4F8, 0x1A8, 7, 0x000, 0), /* MX53_PAD_EIM_DA3__SRC_BT_CFG2_2 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA4, 0x4FC, 0x1AC, 0, 0x000, 0), /* MX53_PAD_EIM_DA4__EMI_NAND_WEIM_DA_4 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA4, 0x4FC, 0x1AC, 1, 0x000, 0), /* MX53_PAD_EIM_DA4__GPIO3_4 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA4, 0x4FC, 0x1AC, 3, 0x000, 0), /* MX53_PAD_EIM_DA4__IPU_DISP1_DAT_5 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA4, 0x4FC, 0x1AC, 4, 0x000, 0), /* MX53_PAD_EIM_DA4__IPU_CSI1_D_5 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA4, 0x4FC, 0x1AC, 7, 0x000, 0), /* MX53_PAD_EIM_DA4__SRC_BT_CFG3_7 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA5, 0x500, 0x1B0, 0, 0x000, 0), /* MX53_PAD_EIM_DA5__EMI_NAND_WEIM_DA_5 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA5, 0x500, 0x1B0, 1, 0x000, 0), /* MX53_PAD_EIM_DA5__GPIO3_5 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA5, 0x500, 0x1B0, 3, 0x000, 0), /* MX53_PAD_EIM_DA5__IPU_DISP1_DAT_4 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA5, 0x500, 0x1B0, 4, 0x000, 0), /* MX53_PAD_EIM_DA5__IPU_CSI1_D_4 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA5, 0x500, 0x1B0, 7, 0x000, 0), /* MX53_PAD_EIM_DA5__SRC_BT_CFG3_6 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA6, 0x504, 0x1B4, 0, 0x000, 0), /* MX53_PAD_EIM_DA6__EMI_NAND_WEIM_DA_6 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA6, 0x504, 0x1B4, 1, 0x000, 0), /* MX53_PAD_EIM_DA6__GPIO3_6 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA6, 0x504, 0x1B4, 3, 0x000, 0), /* MX53_PAD_EIM_DA6__IPU_DISP1_DAT_3 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA6, 0x504, 0x1B4, 4, 0x000, 0), /* MX53_PAD_EIM_DA6__IPU_CSI1_D_3 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA6, 0x504, 0x1B4, 7, 0x000, 0), /* MX53_PAD_EIM_DA6__SRC_BT_CFG3_5 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA7, 0x508, 0x1B8, 0, 0x000, 0), /* MX53_PAD_EIM_DA7__EMI_NAND_WEIM_DA_7 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA7, 0x508, 0x1B8, 1, 0x000, 0), /* MX53_PAD_EIM_DA7__GPIO3_7 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA7, 0x508, 0x1B8, 3, 0x000, 0), /* MX53_PAD_EIM_DA7__IPU_DISP1_DAT_2 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA7, 0x508, 0x1B8, 4, 0x000, 0), /* MX53_PAD_EIM_DA7__IPU_CSI1_D_2 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA7, 0x508, 0x1B8, 7, 0x000, 0), /* MX53_PAD_EIM_DA7__SRC_BT_CFG3_4 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA8, 0x50C, 0x1BC, 0, 0x000, 0), /* MX53_PAD_EIM_DA8__EMI_NAND_WEIM_DA_8 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA8, 0x50C, 0x1BC, 1, 0x000, 0), /* MX53_PAD_EIM_DA8__GPIO3_8 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA8, 0x50C, 0x1BC, 3, 0x000, 0), /* MX53_PAD_EIM_DA8__IPU_DISP1_DAT_1 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA8, 0x50C, 0x1BC, 4, 0x000, 0), /* MX53_PAD_EIM_DA8__IPU_CSI1_D_1 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA8, 0x50C, 0x1BC, 7, 0x000, 0), /* MX53_PAD_EIM_DA8__SRC_BT_CFG3_3 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA9, 0x510, 0x1C0, 0, 0x000, 0), /* MX53_PAD_EIM_DA9__EMI_NAND_WEIM_DA_9 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA9, 0x510, 0x1C0, 1, 0x000, 0), /* MX53_PAD_EIM_DA9__GPIO3_9 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA9, 0x510, 0x1C0, 3, 0x000, 0), /* MX53_PAD_EIM_DA9__IPU_DISP1_DAT_0 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA9, 0x510, 0x1C0, 4, 0x000, 0), /* MX53_PAD_EIM_DA9__IPU_CSI1_D_0 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA9, 0x510, 0x1C0, 7, 0x000, 0), /* MX53_PAD_EIM_DA9__SRC_BT_CFG3_2 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA10, 0x514, 0x1C4, 0, 0x000, 0), /* MX53_PAD_EIM_DA10__EMI_NAND_WEIM_DA_10 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA10, 0x514, 0x1C4, 1, 0x000, 0), /* MX53_PAD_EIM_DA10__GPIO3_10 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA10, 0x514, 0x1C4, 3, 0x000, 0), /* MX53_PAD_EIM_DA10__IPU_DI1_PIN15 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA10, 0x514, 0x1C4, 4, 0x834, 1), /* MX53_PAD_EIM_DA10__IPU_CSI1_DATA_EN */
-	IMX_PIN_REG(MX53_PAD_EIM_DA10, 0x514, 0x1C4, 7, 0x000, 0), /* MX53_PAD_EIM_DA10__SRC_BT_CFG3_1 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA11, 0x518, 0x1C8, 0, 0x000, 0), /* MX53_PAD_EIM_DA11__EMI_NAND_WEIM_DA_11 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA11, 0x518, 0x1C8, 1, 0x000, 0), /* MX53_PAD_EIM_DA11__GPIO3_11 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA11, 0x518, 0x1C8, 3, 0x000, 0), /* MX53_PAD_EIM_DA11__IPU_DI1_PIN2 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA11, 0x518, 0x1C8, 4, 0x838, 1), /* MX53_PAD_EIM_DA11__IPU_CSI1_HSYNC */
-	IMX_PIN_REG(MX53_PAD_EIM_DA12, 0x51C, 0x1CC, 0, 0x000, 0), /* MX53_PAD_EIM_DA12__EMI_NAND_WEIM_DA_12 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA12, 0x51C, 0x1CC, 1, 0x000, 0), /* MX53_PAD_EIM_DA12__GPIO3_12 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA12, 0x51C, 0x1CC, 3, 0x000, 0), /* MX53_PAD_EIM_DA12__IPU_DI1_PIN3 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA12, 0x51C, 0x1CC, 4, 0x83C, 1), /* MX53_PAD_EIM_DA12__IPU_CSI1_VSYNC */
-	IMX_PIN_REG(MX53_PAD_EIM_DA13, 0x520, 0x1D0, 0, 0x000, 0), /* MX53_PAD_EIM_DA13__EMI_NAND_WEIM_DA_13 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA13, 0x520, 0x1D0, 1, 0x000, 0), /* MX53_PAD_EIM_DA13__GPIO3_13 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA13, 0x520, 0x1D0, 3, 0x000, 0), /* MX53_PAD_EIM_DA13__IPU_DI1_D0_CS */
-	IMX_PIN_REG(MX53_PAD_EIM_DA13, 0x520, 0x1D0, 4, 0x76C, 1), /* MX53_PAD_EIM_DA13__CCM_DI1_EXT_CLK */
-	IMX_PIN_REG(MX53_PAD_EIM_DA14, 0x524, 0x1D4, 0, 0x000, 0), /* MX53_PAD_EIM_DA14__EMI_NAND_WEIM_DA_14 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA14, 0x524, 0x1D4, 1, 0x000, 0), /* MX53_PAD_EIM_DA14__GPIO3_14 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA14, 0x524, 0x1D4, 3, 0x000, 0), /* MX53_PAD_EIM_DA14__IPU_DI1_D1_CS */
-	IMX_PIN_REG(MX53_PAD_EIM_DA14, 0x524, 0x1D4, 4, 0x000, 0), /* MX53_PAD_EIM_DA14__CCM_DI0_EXT_CLK */
-	IMX_PIN_REG(MX53_PAD_EIM_DA15, 0x528, 0x1D8, 0, 0x000, 0), /* MX53_PAD_EIM_DA15__EMI_NAND_WEIM_DA_15 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA15, 0x528, 0x1D8, 1, 0x000, 0), /* MX53_PAD_EIM_DA15__GPIO3_15 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA15, 0x528, 0x1D8, 3, 0x000, 0), /* MX53_PAD_EIM_DA15__IPU_DI1_PIN1 */
-	IMX_PIN_REG(MX53_PAD_EIM_DA15, 0x528, 0x1D8, 4, 0x000, 0), /* MX53_PAD_EIM_DA15__IPU_DI1_PIN4 */
-	IMX_PIN_REG(MX53_PAD_NANDF_WE_B, 0x52C, 0x1DC, 0, 0x000, 0), /* MX53_PAD_NANDF_WE_B__EMI_NANDF_WE_B */
-	IMX_PIN_REG(MX53_PAD_NANDF_WE_B, 0x52C, 0x1DC, 1, 0x000, 0), /* MX53_PAD_NANDF_WE_B__GPIO6_12 */
-	IMX_PIN_REG(MX53_PAD_NANDF_RE_B, 0x530, 0x1E0, 0, 0x000, 0), /* MX53_PAD_NANDF_RE_B__EMI_NANDF_RE_B */
-	IMX_PIN_REG(MX53_PAD_NANDF_RE_B, 0x530, 0x1E0, 1, 0x000, 0), /* MX53_PAD_NANDF_RE_B__GPIO6_13 */
-	IMX_PIN_REG(MX53_PAD_EIM_WAIT, 0x534, 0x1E4, 0, 0x000, 0), /* MX53_PAD_EIM_WAIT__EMI_WEIM_WAIT */
-	IMX_PIN_REG(MX53_PAD_EIM_WAIT, 0x534, 0x1E4, 1, 0x000, 0), /* MX53_PAD_EIM_WAIT__GPIO5_0 */
-	IMX_PIN_REG(MX53_PAD_EIM_WAIT, 0x534, 0x1E4, 2, 0x000, 0), /* MX53_PAD_EIM_WAIT__EMI_WEIM_DTACK_B */
-	IMX_PIN_REG(MX53_PAD_LVDS1_TX3_P, NO_PAD, 0x1EC, 0, 0x000, 0), /* MX53_PAD_LVDS1_TX3_P__GPIO6_22 */
-	IMX_PIN_REG(MX53_PAD_LVDS1_TX3_P, NO_PAD, 0x1EC, 1, 0x000, 0), /* MX53_PAD_LVDS1_TX3_P__LDB_LVDS1_TX3 */
-	IMX_PIN_REG(MX53_PAD_LVDS1_TX2_P, NO_PAD, 0x1F0, 0, 0x000, 0), /* MX53_PAD_LVDS1_TX2_P__GPIO6_24 */
-	IMX_PIN_REG(MX53_PAD_LVDS1_TX2_P, NO_PAD, 0x1F0, 1, 0x000, 0), /* MX53_PAD_LVDS1_TX2_P__LDB_LVDS1_TX2 */
-	IMX_PIN_REG(MX53_PAD_LVDS1_CLK_P, NO_PAD, 0x1F4, 0, 0x000, 0), /* MX53_PAD_LVDS1_CLK_P__GPIO6_26 */
-	IMX_PIN_REG(MX53_PAD_LVDS1_CLK_P, NO_PAD, 0x1F4, 1, 0x000, 0), /* MX53_PAD_LVDS1_CLK_P__LDB_LVDS1_CLK */
-	IMX_PIN_REG(MX53_PAD_LVDS1_TX1_P, NO_PAD, 0x1F8, 0, 0x000, 0), /* MX53_PAD_LVDS1_TX1_P__GPIO6_28 */
-	IMX_PIN_REG(MX53_PAD_LVDS1_TX1_P, NO_PAD, 0x1F8, 1, 0x000, 0), /* MX53_PAD_LVDS1_TX1_P__LDB_LVDS1_TX1 */
-	IMX_PIN_REG(MX53_PAD_LVDS1_TX0_P, NO_PAD, 0x1FC, 0, 0x000, 0), /* MX53_PAD_LVDS1_TX0_P__GPIO6_30 */
-	IMX_PIN_REG(MX53_PAD_LVDS1_TX0_P, NO_PAD, 0x1FC, 1, 0x000, 0), /* MX53_PAD_LVDS1_TX0_P__LDB_LVDS1_TX0 */
-	IMX_PIN_REG(MX53_PAD_LVDS0_TX3_P, NO_PAD, 0x200, 0, 0x000, 0), /* MX53_PAD_LVDS0_TX3_P__GPIO7_22 */
-	IMX_PIN_REG(MX53_PAD_LVDS0_TX3_P, NO_PAD, 0x200, 1, 0x000, 0), /* MX53_PAD_LVDS0_TX3_P__LDB_LVDS0_TX3 */
-	IMX_PIN_REG(MX53_PAD_LVDS0_CLK_P, NO_PAD, 0x204, 0, 0x000, 0), /* MX53_PAD_LVDS0_CLK_P__GPIO7_24 */
-	IMX_PIN_REG(MX53_PAD_LVDS0_CLK_P, NO_PAD, 0x204, 1, 0x000, 0), /* MX53_PAD_LVDS0_CLK_P__LDB_LVDS0_CLK */
-	IMX_PIN_REG(MX53_PAD_LVDS0_TX2_P, NO_PAD, 0x208, 0, 0x000, 0), /* MX53_PAD_LVDS0_TX2_P__GPIO7_26 */
-	IMX_PIN_REG(MX53_PAD_LVDS0_TX2_P, NO_PAD, 0x208, 1, 0x000, 0), /* MX53_PAD_LVDS0_TX2_P__LDB_LVDS0_TX2 */
-	IMX_PIN_REG(MX53_PAD_LVDS0_TX1_P, NO_PAD, 0x20C, 0, 0x000, 0), /* MX53_PAD_LVDS0_TX1_P__GPIO7_28 */
-	IMX_PIN_REG(MX53_PAD_LVDS0_TX1_P, NO_PAD, 0x20C, 1, 0x000, 0), /* MX53_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1 */
-	IMX_PIN_REG(MX53_PAD_LVDS0_TX0_P, NO_PAD, 0x210, 0, 0x000, 0), /* MX53_PAD_LVDS0_TX0_P__GPIO7_30 */
-	IMX_PIN_REG(MX53_PAD_LVDS0_TX0_P, NO_PAD, 0x210, 1, 0x000, 0), /* MX53_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0 */
-	IMX_PIN_REG(MX53_PAD_GPIO_10, 0x540, 0x214, 0, 0x000, 0), /* MX53_PAD_GPIO_10__GPIO4_0 */
-	IMX_PIN_REG(MX53_PAD_GPIO_10, 0x540, 0x214, 1, 0x000, 0), /* MX53_PAD_GPIO_10__OSC32k_32K_OUT */
-	IMX_PIN_REG(MX53_PAD_GPIO_11, 0x544, 0x218, 0, 0x000, 0), /* MX53_PAD_GPIO_11__GPIO4_1 */
-	IMX_PIN_REG(MX53_PAD_GPIO_12, 0x548, 0x21C, 0, 0x000, 0), /* MX53_PAD_GPIO_12__GPIO4_2 */
-	IMX_PIN_REG(MX53_PAD_GPIO_13, 0x54C, 0x220, 0, 0x000, 0), /* MX53_PAD_GPIO_13__GPIO4_3 */
-	IMX_PIN_REG(MX53_PAD_GPIO_14, 0x550, 0x224, 0, 0x000, 0), /* MX53_PAD_GPIO_14__GPIO4_4 */
-	IMX_PIN_REG(MX53_PAD_NANDF_CLE, 0x5A0, 0x228, 0, 0x000, 0), /* MX53_PAD_NANDF_CLE__EMI_NANDF_CLE */
-	IMX_PIN_REG(MX53_PAD_NANDF_CLE, 0x5A0, 0x228, 1, 0x000, 0), /* MX53_PAD_NANDF_CLE__GPIO6_7 */
-	IMX_PIN_REG(MX53_PAD_NANDF_CLE, 0x5A0, 0x228, 7, 0x000, 0), /* MX53_PAD_NANDF_CLE__USBPHY1_VSTATUS_0 */
-	IMX_PIN_REG(MX53_PAD_NANDF_ALE, 0x5A4, 0x22C, 0, 0x000, 0), /* MX53_PAD_NANDF_ALE__EMI_NANDF_ALE */
-	IMX_PIN_REG(MX53_PAD_NANDF_ALE, 0x5A4, 0x22C, 1, 0x000, 0), /* MX53_PAD_NANDF_ALE__GPIO6_8 */
-	IMX_PIN_REG(MX53_PAD_NANDF_ALE, 0x5A4, 0x22C, 7, 0x000, 0), /* MX53_PAD_NANDF_ALE__USBPHY1_VSTATUS_1 */
-	IMX_PIN_REG(MX53_PAD_NANDF_WP_B, 0x5A8, 0x230, 0, 0x000, 0), /* MX53_PAD_NANDF_WP_B__EMI_NANDF_WP_B */
-	IMX_PIN_REG(MX53_PAD_NANDF_WP_B, 0x5A8, 0x230, 1, 0x000, 0), /* MX53_PAD_NANDF_WP_B__GPIO6_9 */
-	IMX_PIN_REG(MX53_PAD_NANDF_WP_B, 0x5A8, 0x230, 7, 0x000, 0), /* MX53_PAD_NANDF_WP_B__USBPHY1_VSTATUS_2 */
-	IMX_PIN_REG(MX53_PAD_NANDF_RB0, 0x5AC, 0x234, 0, 0x000, 0), /* MX53_PAD_NANDF_RB0__EMI_NANDF_RB_0 */
-	IMX_PIN_REG(MX53_PAD_NANDF_RB0, 0x5AC, 0x234, 1, 0x000, 0), /* MX53_PAD_NANDF_RB0__GPIO6_10 */
-	IMX_PIN_REG(MX53_PAD_NANDF_RB0, 0x5AC, 0x234, 7, 0x000, 0), /* MX53_PAD_NANDF_RB0__USBPHY1_VSTATUS_3 */
-	IMX_PIN_REG(MX53_PAD_NANDF_CS0, 0x5B0, 0x238, 0, 0x000, 0), /* MX53_PAD_NANDF_CS0__EMI_NANDF_CS_0 */
-	IMX_PIN_REG(MX53_PAD_NANDF_CS0, 0x5B0, 0x238, 1, 0x000, 0), /* MX53_PAD_NANDF_CS0__GPIO6_11 */
-	IMX_PIN_REG(MX53_PAD_NANDF_CS0, 0x5B0, 0x238, 7, 0x000, 0), /* MX53_PAD_NANDF_CS0__USBPHY1_VSTATUS_4 */
-	IMX_PIN_REG(MX53_PAD_NANDF_CS1, 0x5B4, 0x23C, 0, 0x000, 0), /* MX53_PAD_NANDF_CS1__EMI_NANDF_CS_1 */
-	IMX_PIN_REG(MX53_PAD_NANDF_CS1, 0x5B4, 0x23C, 1, 0x000, 0), /* MX53_PAD_NANDF_CS1__GPIO6_14 */
-	IMX_PIN_REG(MX53_PAD_NANDF_CS1, 0x5B4, 0x23C, 6, 0x858, 0), /* MX53_PAD_NANDF_CS1__MLB_MLBCLK */
-	IMX_PIN_REG(MX53_PAD_NANDF_CS1, 0x5B4, 0x23C, 7, 0x000, 0), /* MX53_PAD_NANDF_CS1__USBPHY1_VSTATUS_5 */
-	IMX_PIN_REG(MX53_PAD_NANDF_CS2, 0x5B8, 0x240, 0, 0x000, 0), /* MX53_PAD_NANDF_CS2__EMI_NANDF_CS_2 */
-	IMX_PIN_REG(MX53_PAD_NANDF_CS2, 0x5B8, 0x240, 1, 0x000, 0), /* MX53_PAD_NANDF_CS2__GPIO6_15 */
-	IMX_PIN_REG(MX53_PAD_NANDF_CS2, 0x5B8, 0x240, 2, 0x000, 0), /* MX53_PAD_NANDF_CS2__IPU_SISG_0 */
-	IMX_PIN_REG(MX53_PAD_NANDF_CS2, 0x5B8, 0x240, 3, 0x7E4, 0), /* MX53_PAD_NANDF_CS2__ESAI1_TX0 */
-	IMX_PIN_REG(MX53_PAD_NANDF_CS2, 0x5B8, 0x240, 4, 0x000, 0), /* MX53_PAD_NANDF_CS2__EMI_WEIM_CRE */
-	IMX_PIN_REG(MX53_PAD_NANDF_CS2, 0x5B8, 0x240, 5, 0x000, 0), /* MX53_PAD_NANDF_CS2__CCM_CSI0_MCLK */
-	IMX_PIN_REG(MX53_PAD_NANDF_CS2, 0x5B8, 0x240, 6, 0x860, 0), /* MX53_PAD_NANDF_CS2__MLB_MLBSIG */
-	IMX_PIN_REG(MX53_PAD_NANDF_CS2, 0x5B8, 0x240, 7, 0x000, 0), /* MX53_PAD_NANDF_CS2__USBPHY1_VSTATUS_6 */
-	IMX_PIN_REG(MX53_PAD_NANDF_CS3, 0x5BC, 0x244, 0, 0x000, 0), /* MX53_PAD_NANDF_CS3__EMI_NANDF_CS_3 */
-	IMX_PIN_REG(MX53_PAD_NANDF_CS3, 0x5BC, 0x244, 1, 0x000, 0), /* MX53_PAD_NANDF_CS3__GPIO6_16 */
-	IMX_PIN_REG(MX53_PAD_NANDF_CS3, 0x5BC, 0x244, 2, 0x000, 0), /* MX53_PAD_NANDF_CS3__IPU_SISG_1 */
-	IMX_PIN_REG(MX53_PAD_NANDF_CS3, 0x5BC, 0x244, 3, 0x7E8, 0), /* MX53_PAD_NANDF_CS3__ESAI1_TX1 */
-	IMX_PIN_REG(MX53_PAD_NANDF_CS3, 0x5BC, 0x244, 4, 0x000, 0), /* MX53_PAD_NANDF_CS3__EMI_WEIM_A_26 */
-	IMX_PIN_REG(MX53_PAD_NANDF_CS3, 0x5BC, 0x244, 6, 0x85C, 0), /* MX53_PAD_NANDF_CS3__MLB_MLBDAT */
-	IMX_PIN_REG(MX53_PAD_NANDF_CS3, 0x5BC, 0x244, 7, 0x000, 0), /* MX53_PAD_NANDF_CS3__USBPHY1_VSTATUS_7 */
-	IMX_PIN_REG(MX53_PAD_FEC_MDIO, 0x5C4, 0x248, 0, 0x804, 1), /* MX53_PAD_FEC_MDIO__FEC_MDIO */
-	IMX_PIN_REG(MX53_PAD_FEC_MDIO, 0x5C4, 0x248, 1, 0x000, 0), /* MX53_PAD_FEC_MDIO__GPIO1_22 */
-	IMX_PIN_REG(MX53_PAD_FEC_MDIO, 0x5C4, 0x248, 2, 0x7DC, 0), /* MX53_PAD_FEC_MDIO__ESAI1_SCKR */
-	IMX_PIN_REG(MX53_PAD_FEC_MDIO, 0x5C4, 0x248, 3, 0x800, 1), /* MX53_PAD_FEC_MDIO__FEC_COL */
-	IMX_PIN_REG(MX53_PAD_FEC_MDIO, 0x5C4, 0x248, 4, 0x000, 0), /* MX53_PAD_FEC_MDIO__RTC_CE_RTC_PS2 */
-	IMX_PIN_REG(MX53_PAD_FEC_MDIO, 0x5C4, 0x248, 5, 0x000, 0), /* MX53_PAD_FEC_MDIO__SDMA_DEBUG_BUS_DEVICE_3 */
-	IMX_PIN_REG(MX53_PAD_FEC_MDIO, 0x5C4, 0x248, 6, 0x000, 0), /* MX53_PAD_FEC_MDIO__EMI_EMI_DEBUG_49 */
-	IMX_PIN_REG(MX53_PAD_FEC_REF_CLK, 0x5C8, 0x24C, 0, 0x000, 0), /* MX53_PAD_FEC_REF_CLK__FEC_TX_CLK */
-	IMX_PIN_REG(MX53_PAD_FEC_REF_CLK, 0x5C8, 0x24C, 1, 0x000, 0), /* MX53_PAD_FEC_REF_CLK__GPIO1_23 */
-	IMX_PIN_REG(MX53_PAD_FEC_REF_CLK, 0x5C8, 0x24C, 2, 0x7CC, 0), /* MX53_PAD_FEC_REF_CLK__ESAI1_FSR */
-	IMX_PIN_REG(MX53_PAD_FEC_REF_CLK, 0x5C8, 0x24C, 5, 0x000, 0), /* MX53_PAD_FEC_REF_CLK__SDMA_DEBUG_BUS_DEVICE_4 */
-	IMX_PIN_REG(MX53_PAD_FEC_REF_CLK, 0x5C8, 0x24C, 6, 0x000, 0), /* MX53_PAD_FEC_REF_CLK__EMI_EMI_DEBUG_50 */
-	IMX_PIN_REG(MX53_PAD_FEC_RX_ER, 0x5CC, 0x250, 0, 0x000, 0), /* MX53_PAD_FEC_RX_ER__FEC_RX_ER */
-	IMX_PIN_REG(MX53_PAD_FEC_RX_ER, 0x5CC, 0x250, 1, 0x000, 0), /* MX53_PAD_FEC_RX_ER__GPIO1_24 */
-	IMX_PIN_REG(MX53_PAD_FEC_RX_ER, 0x5CC, 0x250, 2, 0x7D4, 0), /* MX53_PAD_FEC_RX_ER__ESAI1_HCKR */
-	IMX_PIN_REG(MX53_PAD_FEC_RX_ER, 0x5CC, 0x250, 3, 0x808, 1), /* MX53_PAD_FEC_RX_ER__FEC_RX_CLK */
-	IMX_PIN_REG(MX53_PAD_FEC_RX_ER, 0x5CC, 0x250, 4, 0x000, 0), /* MX53_PAD_FEC_RX_ER__RTC_CE_RTC_PS3 */
-	IMX_PIN_REG(MX53_PAD_FEC_CRS_DV, 0x5D0, 0x254, 0, 0x000, 0), /* MX53_PAD_FEC_CRS_DV__FEC_RX_DV */
-	IMX_PIN_REG(MX53_PAD_FEC_CRS_DV, 0x5D0, 0x254, 1, 0x000, 0), /* MX53_PAD_FEC_CRS_DV__GPIO1_25 */
-	IMX_PIN_REG(MX53_PAD_FEC_CRS_DV, 0x5D0, 0x254, 2, 0x7E0, 0), /* MX53_PAD_FEC_CRS_DV__ESAI1_SCKT */
-	IMX_PIN_REG(MX53_PAD_FEC_RXD1, 0x5D4, 0x258, 0, 0x000, 0), /* MX53_PAD_FEC_RXD1__FEC_RDATA_1 */
-	IMX_PIN_REG(MX53_PAD_FEC_RXD1, 0x5D4, 0x258, 1, 0x000, 0), /* MX53_PAD_FEC_RXD1__GPIO1_26 */
-	IMX_PIN_REG(MX53_PAD_FEC_RXD1, 0x5D4, 0x258, 2, 0x7D0, 0), /* MX53_PAD_FEC_RXD1__ESAI1_FST */
-	IMX_PIN_REG(MX53_PAD_FEC_RXD1, 0x5D4, 0x258, 3, 0x860, 1), /* MX53_PAD_FEC_RXD1__MLB_MLBSIG */
-	IMX_PIN_REG(MX53_PAD_FEC_RXD1, 0x5D4, 0x258, 4, 0x000, 0), /* MX53_PAD_FEC_RXD1__RTC_CE_RTC_PS1 */
-	IMX_PIN_REG(MX53_PAD_FEC_RXD0, 0x5D8, 0x25C, 0, 0x000, 0), /* MX53_PAD_FEC_RXD0__FEC_RDATA_0 */
-	IMX_PIN_REG(MX53_PAD_FEC_RXD0, 0x5D8, 0x25C, 1, 0x000, 0), /* MX53_PAD_FEC_RXD0__GPIO1_27 */
-	IMX_PIN_REG(MX53_PAD_FEC_RXD0, 0x5D8, 0x25C, 2, 0x7D8, 0), /* MX53_PAD_FEC_RXD0__ESAI1_HCKT */
-	IMX_PIN_REG(MX53_PAD_FEC_RXD0, 0x5D8, 0x25C, 3, 0x000, 0), /* MX53_PAD_FEC_RXD0__OSC32k_32K_OUT */
-	IMX_PIN_REG(MX53_PAD_FEC_TX_EN, 0x5DC, 0x260, 0, 0x000, 0), /* MX53_PAD_FEC_TX_EN__FEC_TX_EN */
-	IMX_PIN_REG(MX53_PAD_FEC_TX_EN, 0x5DC, 0x260, 1, 0x000, 0), /* MX53_PAD_FEC_TX_EN__GPIO1_28 */
-	IMX_PIN_REG(MX53_PAD_FEC_TX_EN, 0x5DC, 0x260, 2, 0x7F0, 0), /* MX53_PAD_FEC_TX_EN__ESAI1_TX3_RX2 */
-	IMX_PIN_REG(MX53_PAD_FEC_TXD1, 0x5E0, 0x264, 0, 0x000, 0), /* MX53_PAD_FEC_TXD1__FEC_TDATA_1 */
-	IMX_PIN_REG(MX53_PAD_FEC_TXD1, 0x5E0, 0x264, 1, 0x000, 0), /* MX53_PAD_FEC_TXD1__GPIO1_29 */
-	IMX_PIN_REG(MX53_PAD_FEC_TXD1, 0x5E0, 0x264, 2, 0x7EC, 0), /* MX53_PAD_FEC_TXD1__ESAI1_TX2_RX3 */
-	IMX_PIN_REG(MX53_PAD_FEC_TXD1, 0x5E0, 0x264, 3, 0x858, 1), /* MX53_PAD_FEC_TXD1__MLB_MLBCLK */
-	IMX_PIN_REG(MX53_PAD_FEC_TXD1, 0x5E0, 0x264, 4, 0x000, 0), /* MX53_PAD_FEC_TXD1__RTC_CE_RTC_PRSC_CLK */
-	IMX_PIN_REG(MX53_PAD_FEC_TXD0, 0x5E4, 0x268, 0, 0x000, 0), /* MX53_PAD_FEC_TXD0__FEC_TDATA_0 */
-	IMX_PIN_REG(MX53_PAD_FEC_TXD0, 0x5E4, 0x268, 1, 0x000, 0), /* MX53_PAD_FEC_TXD0__GPIO1_30 */
-	IMX_PIN_REG(MX53_PAD_FEC_TXD0, 0x5E4, 0x268, 2, 0x7F4, 0), /* MX53_PAD_FEC_TXD0__ESAI1_TX4_RX1 */
-	IMX_PIN_REG(MX53_PAD_FEC_TXD0, 0x5E4, 0x268, 7, 0x000, 0), /* MX53_PAD_FEC_TXD0__USBPHY2_DATAOUT_0 */
-	IMX_PIN_REG(MX53_PAD_FEC_MDC, 0x5E8, 0x26C, 0, 0x000, 0), /* MX53_PAD_FEC_MDC__FEC_MDC */
-	IMX_PIN_REG(MX53_PAD_FEC_MDC, 0x5E8, 0x26C, 1, 0x000, 0), /* MX53_PAD_FEC_MDC__GPIO1_31 */
-	IMX_PIN_REG(MX53_PAD_FEC_MDC, 0x5E8, 0x26C, 2, 0x7F8, 0), /* MX53_PAD_FEC_MDC__ESAI1_TX5_RX0 */
-	IMX_PIN_REG(MX53_PAD_FEC_MDC, 0x5E8, 0x26C, 3, 0x85C, 1), /* MX53_PAD_FEC_MDC__MLB_MLBDAT */
-	IMX_PIN_REG(MX53_PAD_FEC_MDC, 0x5E8, 0x26C, 4, 0x000, 0), /* MX53_PAD_FEC_MDC__RTC_CE_RTC_ALARM1_TRIG */
-	IMX_PIN_REG(MX53_PAD_FEC_MDC, 0x5E8, 0x26C, 7, 0x000, 0), /* MX53_PAD_FEC_MDC__USBPHY2_DATAOUT_1 */
-	IMX_PIN_REG(MX53_PAD_PATA_DIOW, 0x5F0, 0x270, 0, 0x000, 0), /* MX53_PAD_PATA_DIOW__PATA_DIOW */
-	IMX_PIN_REG(MX53_PAD_PATA_DIOW, 0x5F0, 0x270, 1, 0x000, 0), /* MX53_PAD_PATA_DIOW__GPIO6_17 */
-	IMX_PIN_REG(MX53_PAD_PATA_DIOW, 0x5F0, 0x270, 3, 0x000, 0), /* MX53_PAD_PATA_DIOW__UART1_TXD_MUX */
-	IMX_PIN_REG(MX53_PAD_PATA_DIOW, 0x5F0, 0x270, 7, 0x000, 0), /* MX53_PAD_PATA_DIOW__USBPHY2_DATAOUT_2 */
-	IMX_PIN_REG(MX53_PAD_PATA_DMACK, 0x5F4, 0x274, 0, 0x000, 0), /* MX53_PAD_PATA_DMACK__PATA_DMACK */
-	IMX_PIN_REG(MX53_PAD_PATA_DMACK, 0x5F4, 0x274, 1, 0x000, 0), /* MX53_PAD_PATA_DMACK__GPIO6_18 */
-	IMX_PIN_REG(MX53_PAD_PATA_DMACK, 0x5F4, 0x274, 3, 0x878, 3), /* MX53_PAD_PATA_DMACK__UART1_RXD_MUX */
-	IMX_PIN_REG(MX53_PAD_PATA_DMACK, 0x5F4, 0x274, 7, 0x000, 0), /* MX53_PAD_PATA_DMACK__USBPHY2_DATAOUT_3 */
-	IMX_PIN_REG(MX53_PAD_PATA_DMARQ, 0x5F8, 0x278, 0, 0x000, 0), /* MX53_PAD_PATA_DMARQ__PATA_DMARQ */
-	IMX_PIN_REG(MX53_PAD_PATA_DMARQ, 0x5F8, 0x278, 1, 0x000, 0), /* MX53_PAD_PATA_DMARQ__GPIO7_0 */
-	IMX_PIN_REG(MX53_PAD_PATA_DMARQ, 0x5F8, 0x278, 3, 0x000, 0), /* MX53_PAD_PATA_DMARQ__UART2_TXD_MUX */
-	IMX_PIN_REG(MX53_PAD_PATA_DMARQ, 0x5F8, 0x278, 5, 0x000, 0), /* MX53_PAD_PATA_DMARQ__CCM_CCM_OUT_0 */
-	IMX_PIN_REG(MX53_PAD_PATA_DMARQ, 0x5F8, 0x278, 7, 0x000, 0), /* MX53_PAD_PATA_DMARQ__USBPHY2_DATAOUT_4 */
-	IMX_PIN_REG(MX53_PAD_PATA_BUFFER_EN, 0x5FC, 0x27C, 0, 0x000, 0), /* MX53_PAD_PATA_BUFFER_EN__PATA_BUFFER_EN */
-	IMX_PIN_REG(MX53_PAD_PATA_BUFFER_EN, 0x5FC, 0x27C, 1, 0x000, 0), /* MX53_PAD_PATA_BUFFER_EN__GPIO7_1 */
-	IMX_PIN_REG(MX53_PAD_PATA_BUFFER_EN, 0x5FC, 0x27C, 3, 0x880, 3), /* MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX */
-	IMX_PIN_REG(MX53_PAD_PATA_BUFFER_EN, 0x5FC, 0x27C, 5, 0x000, 0), /* MX53_PAD_PATA_BUFFER_EN__CCM_CCM_OUT_1 */
-	IMX_PIN_REG(MX53_PAD_PATA_BUFFER_EN, 0x5FC, 0x27C, 7, 0x000, 0), /* MX53_PAD_PATA_BUFFER_EN__USBPHY2_DATAOUT_5 */
-	IMX_PIN_REG(MX53_PAD_PATA_INTRQ, 0x600, 0x280, 0, 0x000, 0), /* MX53_PAD_PATA_INTRQ__PATA_INTRQ */
-	IMX_PIN_REG(MX53_PAD_PATA_INTRQ, 0x600, 0x280, 1, 0x000, 0), /* MX53_PAD_PATA_INTRQ__GPIO7_2 */
-	IMX_PIN_REG(MX53_PAD_PATA_INTRQ, 0x600, 0x280, 3, 0x000, 0), /* MX53_PAD_PATA_INTRQ__UART2_CTS */
-	IMX_PIN_REG(MX53_PAD_PATA_INTRQ, 0x600, 0x280, 4, 0x000, 0), /* MX53_PAD_PATA_INTRQ__CAN1_TXCAN */
-	IMX_PIN_REG(MX53_PAD_PATA_INTRQ, 0x600, 0x280, 5, 0x000, 0), /* MX53_PAD_PATA_INTRQ__CCM_CCM_OUT_2 */
-	IMX_PIN_REG(MX53_PAD_PATA_INTRQ, 0x600, 0x280, 7, 0x000, 0), /* MX53_PAD_PATA_INTRQ__USBPHY2_DATAOUT_6 */
-	IMX_PIN_REG(MX53_PAD_PATA_DIOR, 0x604, 0x284, 0, 0x000, 0), /* MX53_PAD_PATA_DIOR__PATA_DIOR */
-	IMX_PIN_REG(MX53_PAD_PATA_DIOR, 0x604, 0x284, 1, 0x000, 0), /* MX53_PAD_PATA_DIOR__GPIO7_3 */
-	IMX_PIN_REG(MX53_PAD_PATA_DIOR, 0x604, 0x284, 3, 0x87C, 3), /* MX53_PAD_PATA_DIOR__UART2_RTS */
-	IMX_PIN_REG(MX53_PAD_PATA_DIOR, 0x604, 0x284, 4, 0x760, 1), /* MX53_PAD_PATA_DIOR__CAN1_RXCAN */
-	IMX_PIN_REG(MX53_PAD_PATA_DIOR, 0x604, 0x284, 7, 0x000, 0), /* MX53_PAD_PATA_DIOR__USBPHY2_DATAOUT_7 */
-	IMX_PIN_REG(MX53_PAD_PATA_RESET_B, 0x608, 0x288, 0, 0x000, 0), /* MX53_PAD_PATA_RESET_B__PATA_PATA_RESET_B */
-	IMX_PIN_REG(MX53_PAD_PATA_RESET_B, 0x608, 0x288, 1, 0x000, 0), /* MX53_PAD_PATA_RESET_B__GPIO7_4 */
-	IMX_PIN_REG(MX53_PAD_PATA_RESET_B, 0x608, 0x288, 2, 0x000, 0), /* MX53_PAD_PATA_RESET_B__ESDHC3_CMD */
-	IMX_PIN_REG(MX53_PAD_PATA_RESET_B, 0x608, 0x288, 3, 0x000, 0), /* MX53_PAD_PATA_RESET_B__UART1_CTS */
-	IMX_PIN_REG(MX53_PAD_PATA_RESET_B, 0x608, 0x288, 4, 0x000, 0), /* MX53_PAD_PATA_RESET_B__CAN2_TXCAN */
-	IMX_PIN_REG(MX53_PAD_PATA_RESET_B, 0x608, 0x288, 7, 0x000, 0), /* MX53_PAD_PATA_RESET_B__USBPHY1_DATAOUT_0 */
-	IMX_PIN_REG(MX53_PAD_PATA_IORDY, 0x60C, 0x28C, 0, 0x000, 0), /* MX53_PAD_PATA_IORDY__PATA_IORDY */
-	IMX_PIN_REG(MX53_PAD_PATA_IORDY, 0x60C, 0x28C, 1, 0x000, 0), /* MX53_PAD_PATA_IORDY__GPIO7_5 */
-	IMX_PIN_REG(MX53_PAD_PATA_IORDY, 0x60C, 0x28C, 2, 0x000, 0), /* MX53_PAD_PATA_IORDY__ESDHC3_CLK */
-	IMX_PIN_REG(MX53_PAD_PATA_IORDY, 0x60C, 0x28C, 3, 0x874, 3), /* MX53_PAD_PATA_IORDY__UART1_RTS */
-	IMX_PIN_REG(MX53_PAD_PATA_IORDY, 0x60C, 0x28C, 4, 0x764, 1), /* MX53_PAD_PATA_IORDY__CAN2_RXCAN */
-	IMX_PIN_REG(MX53_PAD_PATA_IORDY, 0x60C, 0x28C, 7, 0x000, 0), /* MX53_PAD_PATA_IORDY__USBPHY1_DATAOUT_1 */
-	IMX_PIN_REG(MX53_PAD_PATA_DA_0, 0x610, 0x290, 0, 0x000, 0), /* MX53_PAD_PATA_DA_0__PATA_DA_0 */
-	IMX_PIN_REG(MX53_PAD_PATA_DA_0, 0x610, 0x290, 1, 0x000, 0), /* MX53_PAD_PATA_DA_0__GPIO7_6 */
-	IMX_PIN_REG(MX53_PAD_PATA_DA_0, 0x610, 0x290, 2, 0x000, 0), /* MX53_PAD_PATA_DA_0__ESDHC3_RST */
-	IMX_PIN_REG(MX53_PAD_PATA_DA_0, 0x610, 0x290, 4, 0x864, 0), /* MX53_PAD_PATA_DA_0__OWIRE_LINE */
-	IMX_PIN_REG(MX53_PAD_PATA_DA_0, 0x610, 0x290, 7, 0x000, 0), /* MX53_PAD_PATA_DA_0__USBPHY1_DATAOUT_2 */
-	IMX_PIN_REG(MX53_PAD_PATA_DA_1, 0x614, 0x294, 0, 0x000, 0), /* MX53_PAD_PATA_DA_1__PATA_DA_1 */
-	IMX_PIN_REG(MX53_PAD_PATA_DA_1, 0x614, 0x294, 1, 0x000, 0), /* MX53_PAD_PATA_DA_1__GPIO7_7 */
-	IMX_PIN_REG(MX53_PAD_PATA_DA_1, 0x614, 0x294, 2, 0x000, 0), /* MX53_PAD_PATA_DA_1__ESDHC4_CMD */
-	IMX_PIN_REG(MX53_PAD_PATA_DA_1, 0x614, 0x294, 4, 0x000, 0), /* MX53_PAD_PATA_DA_1__UART3_CTS */
-	IMX_PIN_REG(MX53_PAD_PATA_DA_1, 0x614, 0x294, 7, 0x000, 0), /* MX53_PAD_PATA_DA_1__USBPHY1_DATAOUT_3 */
-	IMX_PIN_REG(MX53_PAD_PATA_DA_2, 0x618, 0x298, 0, 0x000, 0), /* MX53_PAD_PATA_DA_2__PATA_DA_2 */
-	IMX_PIN_REG(MX53_PAD_PATA_DA_2, 0x618, 0x298, 1, 0x000, 0), /* MX53_PAD_PATA_DA_2__GPIO7_8 */
-	IMX_PIN_REG(MX53_PAD_PATA_DA_2, 0x618, 0x298, 2, 0x000, 0), /* MX53_PAD_PATA_DA_2__ESDHC4_CLK */
-	IMX_PIN_REG(MX53_PAD_PATA_DA_2, 0x618, 0x298, 4, 0x884, 5), /* MX53_PAD_PATA_DA_2__UART3_RTS */
-	IMX_PIN_REG(MX53_PAD_PATA_DA_2, 0x618, 0x298, 7, 0x000, 0), /* MX53_PAD_PATA_DA_2__USBPHY1_DATAOUT_4 */
-	IMX_PIN_REG(MX53_PAD_PATA_CS_0, 0x61C, 0x29C, 0, 0x000, 0), /* MX53_PAD_PATA_CS_0__PATA_CS_0 */
-	IMX_PIN_REG(MX53_PAD_PATA_CS_0, 0x61C, 0x29C, 1, 0x000, 0), /* MX53_PAD_PATA_CS_0__GPIO7_9 */
-	IMX_PIN_REG(MX53_PAD_PATA_CS_0, 0x61C, 0x29C, 4, 0x000, 0), /* MX53_PAD_PATA_CS_0__UART3_TXD_MUX */
-	IMX_PIN_REG(MX53_PAD_PATA_CS_0, 0x61C, 0x29C, 7, 0x000, 0), /* MX53_PAD_PATA_CS_0__USBPHY1_DATAOUT_5 */
-	IMX_PIN_REG(MX53_PAD_PATA_CS_1, 0x620, 0x2A0, 0, 0x000, 0), /* MX53_PAD_PATA_CS_1__PATA_CS_1 */
-	IMX_PIN_REG(MX53_PAD_PATA_CS_1, 0x620, 0x2A0, 1, 0x000, 0), /* MX53_PAD_PATA_CS_1__GPIO7_10 */
-	IMX_PIN_REG(MX53_PAD_PATA_CS_1, 0x620, 0x2A0, 4, 0x888, 3), /* MX53_PAD_PATA_CS_1__UART3_RXD_MUX */
-	IMX_PIN_REG(MX53_PAD_PATA_CS_1, 0x620, 0x2A0, 7, 0x000, 0), /* MX53_PAD_PATA_CS_1__USBPHY1_DATAOUT_6 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA0, 0x628, 0x2A4, 0, 0x000, 0), /* MX53_PAD_PATA_DATA0__PATA_DATA_0 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA0, 0x628, 0x2A4, 1, 0x000, 0), /* MX53_PAD_PATA_DATA0__GPIO2_0 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA0, 0x628, 0x2A4, 3, 0x000, 0), /* MX53_PAD_PATA_DATA0__EMI_NANDF_D_0 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA0, 0x628, 0x2A4, 4, 0x000, 0), /* MX53_PAD_PATA_DATA0__ESDHC3_DAT4 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA0, 0x628, 0x2A4, 5, 0x000, 0), /* MX53_PAD_PATA_DATA0__GPU3d_GPU_DEBUG_OUT_0 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA0, 0x628, 0x2A4, 6, 0x000, 0), /* MX53_PAD_PATA_DATA0__IPU_DIAG_BUS_0 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA0, 0x628, 0x2A4, 7, 0x000, 0), /* MX53_PAD_PATA_DATA0__USBPHY1_DATAOUT_7 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA1, 0x62C, 0x2A8, 0, 0x000, 0), /* MX53_PAD_PATA_DATA1__PATA_DATA_1 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA1, 0x62C, 0x2A8, 1, 0x000, 0), /* MX53_PAD_PATA_DATA1__GPIO2_1 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA1, 0x62C, 0x2A8, 3, 0x000, 0), /* MX53_PAD_PATA_DATA1__EMI_NANDF_D_1 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA1, 0x62C, 0x2A8, 4, 0x000, 0), /* MX53_PAD_PATA_DATA1__ESDHC3_DAT5 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA1, 0x62C, 0x2A8, 5, 0x000, 0), /* MX53_PAD_PATA_DATA1__GPU3d_GPU_DEBUG_OUT_1 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA1, 0x62C, 0x2A8, 6, 0x000, 0), /* MX53_PAD_PATA_DATA1__IPU_DIAG_BUS_1 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA2, 0x630, 0x2AC, 0, 0x000, 0), /* MX53_PAD_PATA_DATA2__PATA_DATA_2 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA2, 0x630, 0x2AC, 1, 0x000, 0), /* MX53_PAD_PATA_DATA2__GPIO2_2 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA2, 0x630, 0x2AC, 3, 0x000, 0), /* MX53_PAD_PATA_DATA2__EMI_NANDF_D_2 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA2, 0x630, 0x2AC, 4, 0x000, 0), /* MX53_PAD_PATA_DATA2__ESDHC3_DAT6 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA2, 0x630, 0x2AC, 5, 0x000, 0), /* MX53_PAD_PATA_DATA2__GPU3d_GPU_DEBUG_OUT_2 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA2, 0x630, 0x2AC, 6, 0x000, 0), /* MX53_PAD_PATA_DATA2__IPU_DIAG_BUS_2 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA3, 0x634, 0x2B0, 0, 0x000, 0), /* MX53_PAD_PATA_DATA3__PATA_DATA_3 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA3, 0x634, 0x2B0, 1, 0x000, 0), /* MX53_PAD_PATA_DATA3__GPIO2_3 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA3, 0x634, 0x2B0, 3, 0x000, 0), /* MX53_PAD_PATA_DATA3__EMI_NANDF_D_3 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA3, 0x634, 0x2B0, 4, 0x000, 0), /* MX53_PAD_PATA_DATA3__ESDHC3_DAT7 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA3, 0x634, 0x2B0, 5, 0x000, 0), /* MX53_PAD_PATA_DATA3__GPU3d_GPU_DEBUG_OUT_3 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA3, 0x634, 0x2B0, 6, 0x000, 0), /* MX53_PAD_PATA_DATA3__IPU_DIAG_BUS_3 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA4, 0x638, 0x2B4, 0, 0x000, 0), /* MX53_PAD_PATA_DATA4__PATA_DATA_4 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA4, 0x638, 0x2B4, 1, 0x000, 0), /* MX53_PAD_PATA_DATA4__GPIO2_4 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA4, 0x638, 0x2B4, 3, 0x000, 0), /* MX53_PAD_PATA_DATA4__EMI_NANDF_D_4 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA4, 0x638, 0x2B4, 4, 0x000, 0), /* MX53_PAD_PATA_DATA4__ESDHC4_DAT4 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA4, 0x638, 0x2B4, 5, 0x000, 0), /* MX53_PAD_PATA_DATA4__GPU3d_GPU_DEBUG_OUT_4 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA4, 0x638, 0x2B4, 6, 0x000, 0), /* MX53_PAD_PATA_DATA4__IPU_DIAG_BUS_4 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA5, 0x63C, 0x2B8, 0, 0x000, 0), /* MX53_PAD_PATA_DATA5__PATA_DATA_5 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA5, 0x63C, 0x2B8, 1, 0x000, 0), /* MX53_PAD_PATA_DATA5__GPIO2_5 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA5, 0x63C, 0x2B8, 3, 0x000, 0), /* MX53_PAD_PATA_DATA5__EMI_NANDF_D_5 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA5, 0x63C, 0x2B8, 4, 0x000, 0), /* MX53_PAD_PATA_DATA5__ESDHC4_DAT5 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA5, 0x63C, 0x2B8, 5, 0x000, 0), /* MX53_PAD_PATA_DATA5__GPU3d_GPU_DEBUG_OUT_5 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA5, 0x63C, 0x2B8, 6, 0x000, 0), /* MX53_PAD_PATA_DATA5__IPU_DIAG_BUS_5 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA6, 0x640, 0x2BC, 0, 0x000, 0), /* MX53_PAD_PATA_DATA6__PATA_DATA_6 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA6, 0x640, 0x2BC, 1, 0x000, 0), /* MX53_PAD_PATA_DATA6__GPIO2_6 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA6, 0x640, 0x2BC, 3, 0x000, 0), /* MX53_PAD_PATA_DATA6__EMI_NANDF_D_6 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA6, 0x640, 0x2BC, 4, 0x000, 0), /* MX53_PAD_PATA_DATA6__ESDHC4_DAT6 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA6, 0x640, 0x2BC, 5, 0x000, 0), /* MX53_PAD_PATA_DATA6__GPU3d_GPU_DEBUG_OUT_6 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA6, 0x640, 0x2BC, 6, 0x000, 0), /* MX53_PAD_PATA_DATA6__IPU_DIAG_BUS_6 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA7, 0x644, 0x2C0, 0, 0x000, 0), /* MX53_PAD_PATA_DATA7__PATA_DATA_7 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA7, 0x644, 0x2C0, 1, 0x000, 0), /* MX53_PAD_PATA_DATA7__GPIO2_7 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA7, 0x644, 0x2C0, 3, 0x000, 0), /* MX53_PAD_PATA_DATA7__EMI_NANDF_D_7 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA7, 0x644, 0x2C0, 4, 0x000, 0), /* MX53_PAD_PATA_DATA7__ESDHC4_DAT7 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA7, 0x644, 0x2C0, 5, 0x000, 0), /* MX53_PAD_PATA_DATA7__GPU3d_GPU_DEBUG_OUT_7 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA7, 0x644, 0x2C0, 6, 0x000, 0), /* MX53_PAD_PATA_DATA7__IPU_DIAG_BUS_7 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA8, 0x648, 0x2C4, 0, 0x000, 0), /* MX53_PAD_PATA_DATA8__PATA_DATA_8 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA8, 0x648, 0x2C4, 1, 0x000, 0), /* MX53_PAD_PATA_DATA8__GPIO2_8 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA8, 0x648, 0x2C4, 2, 0x000, 0), /* MX53_PAD_PATA_DATA8__ESDHC1_DAT4 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA8, 0x648, 0x2C4, 3, 0x000, 0), /* MX53_PAD_PATA_DATA8__EMI_NANDF_D_8 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA8, 0x648, 0x2C4, 4, 0x000, 0), /* MX53_PAD_PATA_DATA8__ESDHC3_DAT0 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA8, 0x648, 0x2C4, 5, 0x000, 0), /* MX53_PAD_PATA_DATA8__GPU3d_GPU_DEBUG_OUT_8 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA8, 0x648, 0x2C4, 6, 0x000, 0), /* MX53_PAD_PATA_DATA8__IPU_DIAG_BUS_8 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA9, 0x64C, 0x2C8, 0, 0x000, 0), /* MX53_PAD_PATA_DATA9__PATA_DATA_9 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA9, 0x64C, 0x2C8, 1, 0x000, 0), /* MX53_PAD_PATA_DATA9__GPIO2_9 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA9, 0x64C, 0x2C8, 2, 0x000, 0), /* MX53_PAD_PATA_DATA9__ESDHC1_DAT5 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA9, 0x64C, 0x2C8, 3, 0x000, 0), /* MX53_PAD_PATA_DATA9__EMI_NANDF_D_9 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA9, 0x64C, 0x2C8, 4, 0x000, 0), /* MX53_PAD_PATA_DATA9__ESDHC3_DAT1 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA9, 0x64C, 0x2C8, 5, 0x000, 0), /* MX53_PAD_PATA_DATA9__GPU3d_GPU_DEBUG_OUT_9 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA9, 0x64C, 0x2C8, 6, 0x000, 0), /* MX53_PAD_PATA_DATA9__IPU_DIAG_BUS_9 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA10, 0x650, 0x2CC, 0, 0x000, 0), /* MX53_PAD_PATA_DATA10__PATA_DATA_10 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA10, 0x650, 0x2CC, 1, 0x000, 0), /* MX53_PAD_PATA_DATA10__GPIO2_10 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA10, 0x650, 0x2CC, 2, 0x000, 0), /* MX53_PAD_PATA_DATA10__ESDHC1_DAT6 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA10, 0x650, 0x2CC, 3, 0x000, 0), /* MX53_PAD_PATA_DATA10__EMI_NANDF_D_10 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA10, 0x650, 0x2CC, 4, 0x000, 0), /* MX53_PAD_PATA_DATA10__ESDHC3_DAT2 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA10, 0x650, 0x2CC, 5, 0x000, 0), /* MX53_PAD_PATA_DATA10__GPU3d_GPU_DEBUG_OUT_10 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA10, 0x650, 0x2CC, 6, 0x000, 0), /* MX53_PAD_PATA_DATA10__IPU_DIAG_BUS_10 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA11, 0x654, 0x2D0, 0, 0x000, 0), /* MX53_PAD_PATA_DATA11__PATA_DATA_11 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA11, 0x654, 0x2D0, 1, 0x000, 0), /* MX53_PAD_PATA_DATA11__GPIO2_11 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA11, 0x654, 0x2D0, 2, 0x000, 0), /* MX53_PAD_PATA_DATA11__ESDHC1_DAT7 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA11, 0x654, 0x2D0, 3, 0x000, 0), /* MX53_PAD_PATA_DATA11__EMI_NANDF_D_11 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA11, 0x654, 0x2D0, 4, 0x000, 0), /* MX53_PAD_PATA_DATA11__ESDHC3_DAT3 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA11, 0x654, 0x2D0, 5, 0x000, 0), /* MX53_PAD_PATA_DATA11__GPU3d_GPU_DEBUG_OUT_11 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA11, 0x654, 0x2D0, 6, 0x000, 0), /* MX53_PAD_PATA_DATA11__IPU_DIAG_BUS_11 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA12, 0x658, 0x2D4, 0, 0x000, 0), /* MX53_PAD_PATA_DATA12__PATA_DATA_12 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA12, 0x658, 0x2D4, 1, 0x000, 0), /* MX53_PAD_PATA_DATA12__GPIO2_12 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA12, 0x658, 0x2D4, 2, 0x000, 0), /* MX53_PAD_PATA_DATA12__ESDHC2_DAT4 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA12, 0x658, 0x2D4, 3, 0x000, 0), /* MX53_PAD_PATA_DATA12__EMI_NANDF_D_12 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA12, 0x658, 0x2D4, 4, 0x000, 0), /* MX53_PAD_PATA_DATA12__ESDHC4_DAT0 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA12, 0x658, 0x2D4, 5, 0x000, 0), /* MX53_PAD_PATA_DATA12__GPU3d_GPU_DEBUG_OUT_12 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA12, 0x658, 0x2D4, 6, 0x000, 0), /* MX53_PAD_PATA_DATA12__IPU_DIAG_BUS_12 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA13, 0x65C, 0x2D8, 0, 0x000, 0), /* MX53_PAD_PATA_DATA13__PATA_DATA_13 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA13, 0x65C, 0x2D8, 1, 0x000, 0), /* MX53_PAD_PATA_DATA13__GPIO2_13 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA13, 0x65C, 0x2D8, 2, 0x000, 0), /* MX53_PAD_PATA_DATA13__ESDHC2_DAT5 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA13, 0x65C, 0x2D8, 3, 0x000, 0), /* MX53_PAD_PATA_DATA13__EMI_NANDF_D_13 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA13, 0x65C, 0x2D8, 4, 0x000, 0), /* MX53_PAD_PATA_DATA13__ESDHC4_DAT1 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA13, 0x65C, 0x2D8, 5, 0x000, 0), /* MX53_PAD_PATA_DATA13__GPU3d_GPU_DEBUG_OUT_13 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA13, 0x65C, 0x2D8, 6, 0x000, 0), /* MX53_PAD_PATA_DATA13__IPU_DIAG_BUS_13 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA14, 0x660, 0x2DC, 0, 0x000, 0), /* MX53_PAD_PATA_DATA14__PATA_DATA_14 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA14, 0x660, 0x2DC, 1, 0x000, 0), /* MX53_PAD_PATA_DATA14__GPIO2_14 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA14, 0x660, 0x2DC, 2, 0x000, 0), /* MX53_PAD_PATA_DATA14__ESDHC2_DAT6 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA14, 0x660, 0x2DC, 3, 0x000, 0), /* MX53_PAD_PATA_DATA14__EMI_NANDF_D_14 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA14, 0x660, 0x2DC, 4, 0x000, 0), /* MX53_PAD_PATA_DATA14__ESDHC4_DAT2 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA14, 0x660, 0x2DC, 5, 0x000, 0), /* MX53_PAD_PATA_DATA14__GPU3d_GPU_DEBUG_OUT_14 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA14, 0x660, 0x2DC, 6, 0x000, 0), /* MX53_PAD_PATA_DATA14__IPU_DIAG_BUS_14 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA15, 0x664, 0x2E0, 0, 0x000, 0), /* MX53_PAD_PATA_DATA15__PATA_DATA_15 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA15, 0x664, 0x2E0, 1, 0x000, 0), /* MX53_PAD_PATA_DATA15__GPIO2_15 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA15, 0x664, 0x2E0, 2, 0x000, 0), /* MX53_PAD_PATA_DATA15__ESDHC2_DAT7 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA15, 0x664, 0x2E0, 3, 0x000, 0), /* MX53_PAD_PATA_DATA15__EMI_NANDF_D_15 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA15, 0x664, 0x2E0, 4, 0x000, 0), /* MX53_PAD_PATA_DATA15__ESDHC4_DAT3 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA15, 0x664, 0x2E0, 5, 0x000, 0), /* MX53_PAD_PATA_DATA15__GPU3d_GPU_DEBUG_OUT_15 */
-	IMX_PIN_REG(MX53_PAD_PATA_DATA15, 0x664, 0x2E0, 6, 0x000, 0), /* MX53_PAD_PATA_DATA15__IPU_DIAG_BUS_15 */
-	IMX_PIN_REG(MX53_PAD_SD1_DATA0, 0x66C, 0x2E4, 0, 0x000, 0), /* MX53_PAD_SD1_DATA0__ESDHC1_DAT0 */
-	IMX_PIN_REG(MX53_PAD_SD1_DATA0, 0x66C, 0x2E4, 1, 0x000, 0), /* MX53_PAD_SD1_DATA0__GPIO1_16 */
-	IMX_PIN_REG(MX53_PAD_SD1_DATA0, 0x66C, 0x2E4, 3, 0x000, 0), /* MX53_PAD_SD1_DATA0__GPT_CAPIN1 */
-	IMX_PIN_REG(MX53_PAD_SD1_DATA0, 0x66C, 0x2E4, 5, 0x784, 2), /* MX53_PAD_SD1_DATA0__CSPI_MISO */
-	IMX_PIN_REG(MX53_PAD_SD1_DATA0, 0x66C, 0x2E4, 7, 0x778, 0), /* MX53_PAD_SD1_DATA0__CCM_PLL3_BYP */
-	IMX_PIN_REG(MX53_PAD_SD1_DATA1, 0x670, 0x2E8, 0, 0x000, 0), /* MX53_PAD_SD1_DATA1__ESDHC1_DAT1 */
-	IMX_PIN_REG(MX53_PAD_SD1_DATA1, 0x670, 0x2E8, 1, 0x000, 0), /* MX53_PAD_SD1_DATA1__GPIO1_17 */
-	IMX_PIN_REG(MX53_PAD_SD1_DATA1, 0x670, 0x2E8, 3, 0x000, 0), /* MX53_PAD_SD1_DATA1__GPT_CAPIN2 */
-	IMX_PIN_REG(MX53_PAD_SD1_DATA1, 0x670, 0x2E8, 5, 0x78C, 3), /* MX53_PAD_SD1_DATA1__CSPI_SS0 */
-	IMX_PIN_REG(MX53_PAD_SD1_DATA1, 0x670, 0x2E8, 7, 0x77C, 1), /* MX53_PAD_SD1_DATA1__CCM_PLL4_BYP */
-	IMX_PIN_REG(MX53_PAD_SD1_CMD, 0x674, 0x2EC, 0, 0x000, 0), /* MX53_PAD_SD1_CMD__ESDHC1_CMD */
-	IMX_PIN_REG(MX53_PAD_SD1_CMD, 0x674, 0x2EC, 1, 0x000, 0), /* MX53_PAD_SD1_CMD__GPIO1_18 */
-	IMX_PIN_REG(MX53_PAD_SD1_CMD, 0x674, 0x2EC, 3, 0x000, 0), /* MX53_PAD_SD1_CMD__GPT_CMPOUT1 */
-	IMX_PIN_REG(MX53_PAD_SD1_CMD, 0x674, 0x2EC, 5, 0x788, 2), /* MX53_PAD_SD1_CMD__CSPI_MOSI */
-	IMX_PIN_REG(MX53_PAD_SD1_CMD, 0x674, 0x2EC, 7, 0x770, 0), /* MX53_PAD_SD1_CMD__CCM_PLL1_BYP */
-	IMX_PIN_REG(MX53_PAD_SD1_DATA2, 0x678, 0x2F0, 0, 0x000, 0), /* MX53_PAD_SD1_DATA2__ESDHC1_DAT2 */
-	IMX_PIN_REG(MX53_PAD_SD1_DATA2, 0x678, 0x2F0, 1, 0x000, 0), /* MX53_PAD_SD1_DATA2__GPIO1_19 */
-	IMX_PIN_REG(MX53_PAD_SD1_DATA2, 0x678, 0x2F0, 2, 0x000, 0), /* MX53_PAD_SD1_DATA2__GPT_CMPOUT2 */
-	IMX_PIN_REG(MX53_PAD_SD1_DATA2, 0x678, 0x2F0, 3, 0x000, 0), /* MX53_PAD_SD1_DATA2__PWM2_PWMO */
-	IMX_PIN_REG(MX53_PAD_SD1_DATA2, 0x678, 0x2F0, 4, 0x000, 0), /* MX53_PAD_SD1_DATA2__WDOG1_WDOG_B */
-	IMX_PIN_REG(MX53_PAD_SD1_DATA2, 0x678, 0x2F0, 5, 0x790, 2), /* MX53_PAD_SD1_DATA2__CSPI_SS1 */
-	IMX_PIN_REG(MX53_PAD_SD1_DATA2, 0x678, 0x2F0, 6, 0x000, 0), /* MX53_PAD_SD1_DATA2__WDOG1_WDOG_RST_B_DEB */
-	IMX_PIN_REG(MX53_PAD_SD1_DATA2, 0x678, 0x2F0, 7, 0x774, 0), /* MX53_PAD_SD1_DATA2__CCM_PLL2_BYP */
-	IMX_PIN_REG(MX53_PAD_SD1_CLK, 0x67C, 0x2F4, 0, 0x000, 0), /* MX53_PAD_SD1_CLK__ESDHC1_CLK */
-	IMX_PIN_REG(MX53_PAD_SD1_CLK, 0x67C, 0x2F4, 1, 0x000, 0), /* MX53_PAD_SD1_CLK__GPIO1_20 */
-	IMX_PIN_REG(MX53_PAD_SD1_CLK, 0x67C, 0x2F4, 2, 0x000, 0), /* MX53_PAD_SD1_CLK__OSC32k_32K_OUT */
-	IMX_PIN_REG(MX53_PAD_SD1_CLK, 0x67C, 0x2F4, 3, 0x000, 0), /* MX53_PAD_SD1_CLK__GPT_CLKIN */
-	IMX_PIN_REG(MX53_PAD_SD1_CLK, 0x67C, 0x2F4, 5, 0x780, 2), /* MX53_PAD_SD1_CLK__CSPI_SCLK */
-	IMX_PIN_REG(MX53_PAD_SD1_CLK, 0x67C, 0x2F4, 7, 0x000, 0), /* MX53_PAD_SD1_CLK__SATA_PHY_DTB_0 */
-	IMX_PIN_REG(MX53_PAD_SD1_DATA3, 0x680, 0x2F8, 0, 0x000, 0), /* MX53_PAD_SD1_DATA3__ESDHC1_DAT3 */
-	IMX_PIN_REG(MX53_PAD_SD1_DATA3, 0x680, 0x2F8, 1, 0x000, 0), /* MX53_PAD_SD1_DATA3__GPIO1_21 */
-	IMX_PIN_REG(MX53_PAD_SD1_DATA3, 0x680, 0x2F8, 2, 0x000, 0), /* MX53_PAD_SD1_DATA3__GPT_CMPOUT3 */
-	IMX_PIN_REG(MX53_PAD_SD1_DATA3, 0x680, 0x2F8, 3, 0x000, 0), /* MX53_PAD_SD1_DATA3__PWM1_PWMO */
-	IMX_PIN_REG(MX53_PAD_SD1_DATA3, 0x680, 0x2F8, 4, 0x000, 0), /* MX53_PAD_SD1_DATA3__WDOG2_WDOG_B */
-	IMX_PIN_REG(MX53_PAD_SD1_DATA3, 0x680, 0x2F8, 5, 0x794, 2), /* MX53_PAD_SD1_DATA3__CSPI_SS2 */
-	IMX_PIN_REG(MX53_PAD_SD1_DATA3, 0x680, 0x2F8, 6, 0x000, 0), /* MX53_PAD_SD1_DATA3__WDOG2_WDOG_RST_B_DEB */
-	IMX_PIN_REG(MX53_PAD_SD1_DATA3, 0x680, 0x2F8, 7, 0x000, 0), /* MX53_PAD_SD1_DATA3__SATA_PHY_DTB_1 */
-	IMX_PIN_REG(MX53_PAD_SD2_CLK, 0x688, 0x2FC, 0, 0x000, 0), /* MX53_PAD_SD2_CLK__ESDHC2_CLK */
-	IMX_PIN_REG(MX53_PAD_SD2_CLK, 0x688, 0x2FC, 1, 0x000, 0), /* MX53_PAD_SD2_CLK__GPIO1_10 */
-	IMX_PIN_REG(MX53_PAD_SD2_CLK, 0x688, 0x2FC, 2, 0x840, 2), /* MX53_PAD_SD2_CLK__KPP_COL_5 */
-	IMX_PIN_REG(MX53_PAD_SD2_CLK, 0x688, 0x2FC, 3, 0x73C, 1), /* MX53_PAD_SD2_CLK__AUDMUX_AUD4_RXFS */
-	IMX_PIN_REG(MX53_PAD_SD2_CLK, 0x688, 0x2FC, 5, 0x780, 3), /* MX53_PAD_SD2_CLK__CSPI_SCLK */
-	IMX_PIN_REG(MX53_PAD_SD2_CLK, 0x688, 0x2FC, 7, 0x000, 0), /* MX53_PAD_SD2_CLK__SCC_RANDOM_V */
-	IMX_PIN_REG(MX53_PAD_SD2_CMD, 0x68C, 0x300, 0, 0x000, 0), /* MX53_PAD_SD2_CMD__ESDHC2_CMD */
-	IMX_PIN_REG(MX53_PAD_SD2_CMD, 0x68C, 0x300, 1, 0x000, 0), /* MX53_PAD_SD2_CMD__GPIO1_11 */
-	IMX_PIN_REG(MX53_PAD_SD2_CMD, 0x68C, 0x300, 2, 0x84C, 1), /* MX53_PAD_SD2_CMD__KPP_ROW_5 */
-	IMX_PIN_REG(MX53_PAD_SD2_CMD, 0x68C, 0x300, 3, 0x738, 1), /* MX53_PAD_SD2_CMD__AUDMUX_AUD4_RXC */
-	IMX_PIN_REG(MX53_PAD_SD2_CMD, 0x68C, 0x300, 5, 0x788, 3), /* MX53_PAD_SD2_CMD__CSPI_MOSI */
-	IMX_PIN_REG(MX53_PAD_SD2_CMD, 0x68C, 0x300, 7, 0x000, 0), /* MX53_PAD_SD2_CMD__SCC_RANDOM */
-	IMX_PIN_REG(MX53_PAD_SD2_DATA3, 0x690, 0x304, 0, 0x000, 0), /* MX53_PAD_SD2_DATA3__ESDHC2_DAT3 */
-	IMX_PIN_REG(MX53_PAD_SD2_DATA3, 0x690, 0x304, 1, 0x000, 0), /* MX53_PAD_SD2_DATA3__GPIO1_12 */
-	IMX_PIN_REG(MX53_PAD_SD2_DATA3, 0x690, 0x304, 2, 0x844, 1), /* MX53_PAD_SD2_DATA3__KPP_COL_6 */
-	IMX_PIN_REG(MX53_PAD_SD2_DATA3, 0x690, 0x304, 3, 0x740, 1), /* MX53_PAD_SD2_DATA3__AUDMUX_AUD4_TXC */
-	IMX_PIN_REG(MX53_PAD_SD2_DATA3, 0x690, 0x304, 5, 0x794, 3), /* MX53_PAD_SD2_DATA3__CSPI_SS2 */
-	IMX_PIN_REG(MX53_PAD_SD2_DATA3, 0x690, 0x304, 7, 0x000, 0), /* MX53_PAD_SD2_DATA3__SJC_DONE */
-	IMX_PIN_REG(MX53_PAD_SD2_DATA2, 0x694, 0x308, 0, 0x000, 0), /* MX53_PAD_SD2_DATA2__ESDHC2_DAT2 */
-	IMX_PIN_REG(MX53_PAD_SD2_DATA2, 0x694, 0x308, 1, 0x000, 0), /* MX53_PAD_SD2_DATA2__GPIO1_13 */
-	IMX_PIN_REG(MX53_PAD_SD2_DATA2, 0x694, 0x308, 2, 0x850, 1), /* MX53_PAD_SD2_DATA2__KPP_ROW_6 */
-	IMX_PIN_REG(MX53_PAD_SD2_DATA2, 0x694, 0x308, 3, 0x734, 1), /* MX53_PAD_SD2_DATA2__AUDMUX_AUD4_TXD */
-	IMX_PIN_REG(MX53_PAD_SD2_DATA2, 0x694, 0x308, 5, 0x790, 3), /* MX53_PAD_SD2_DATA2__CSPI_SS1 */
-	IMX_PIN_REG(MX53_PAD_SD2_DATA2, 0x694, 0x308, 7, 0x000, 0), /* MX53_PAD_SD2_DATA2__SJC_FAIL */
-	IMX_PIN_REG(MX53_PAD_SD2_DATA1, 0x698, 0x30C, 0, 0x000, 0), /* MX53_PAD_SD2_DATA1__ESDHC2_DAT1 */
-	IMX_PIN_REG(MX53_PAD_SD2_DATA1, 0x698, 0x30C, 1, 0x000, 0), /* MX53_PAD_SD2_DATA1__GPIO1_14 */
-	IMX_PIN_REG(MX53_PAD_SD2_DATA1, 0x698, 0x30C, 2, 0x848, 1), /* MX53_PAD_SD2_DATA1__KPP_COL_7 */
-	IMX_PIN_REG(MX53_PAD_SD2_DATA1, 0x698, 0x30C, 3, 0x744, 0), /* MX53_PAD_SD2_DATA1__AUDMUX_AUD4_TXFS */
-	IMX_PIN_REG(MX53_PAD_SD2_DATA1, 0x698, 0x30C, 5, 0x78C, 4), /* MX53_PAD_SD2_DATA1__CSPI_SS0 */
-	IMX_PIN_REG(MX53_PAD_SD2_DATA1, 0x698, 0x30C, 7, 0x000, 0), /* MX53_PAD_SD2_DATA1__RTIC_SEC_VIO */
-	IMX_PIN_REG(MX53_PAD_SD2_DATA0, 0x69C, 0x310, 0, 0x000, 0), /* MX53_PAD_SD2_DATA0__ESDHC2_DAT0 */
-	IMX_PIN_REG(MX53_PAD_SD2_DATA0, 0x69C, 0x310, 1, 0x000, 0), /* MX53_PAD_SD2_DATA0__GPIO1_15 */
-	IMX_PIN_REG(MX53_PAD_SD2_DATA0, 0x69C, 0x310, 2, 0x854, 1), /* MX53_PAD_SD2_DATA0__KPP_ROW_7 */
-	IMX_PIN_REG(MX53_PAD_SD2_DATA0, 0x69C, 0x310, 3, 0x730, 1), /* MX53_PAD_SD2_DATA0__AUDMUX_AUD4_RXD */
-	IMX_PIN_REG(MX53_PAD_SD2_DATA0, 0x69C, 0x310, 5, 0x784, 3), /* MX53_PAD_SD2_DATA0__CSPI_MISO */
-	IMX_PIN_REG(MX53_PAD_SD2_DATA0, 0x69C, 0x310, 7, 0x000, 0), /* MX53_PAD_SD2_DATA0__RTIC_DONE_INT */
-	IMX_PIN_REG(MX53_PAD_GPIO_0, 0x6A4, 0x314, 0, 0x000, 0), /* MX53_PAD_GPIO_0__CCM_CLKO */
-	IMX_PIN_REG(MX53_PAD_GPIO_0, 0x6A4, 0x314, 1, 0x000, 0), /* MX53_PAD_GPIO_0__GPIO1_0 */
-	IMX_PIN_REG(MX53_PAD_GPIO_0, 0x6A4, 0x314, 2, 0x840, 3), /* MX53_PAD_GPIO_0__KPP_COL_5 */
-	IMX_PIN_REG(MX53_PAD_GPIO_0, 0x6A4, 0x314, 3, 0x000, 0), /* MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK */
-	IMX_PIN_REG(MX53_PAD_GPIO_0, 0x6A4, 0x314, 4, 0x000, 0), /* MX53_PAD_GPIO_0__EPIT1_EPITO */
-	IMX_PIN_REG(MX53_PAD_GPIO_0, 0x6A4, 0x314, 5, 0x000, 0), /* MX53_PAD_GPIO_0__SRTC_ALARM_DEB */
-	IMX_PIN_REG(MX53_PAD_GPIO_0, 0x6A4, 0x314, 6, 0x000, 0), /* MX53_PAD_GPIO_0__USBOH3_USBH1_PWR */
-	IMX_PIN_REG(MX53_PAD_GPIO_0, 0x6A4, 0x314, 7, 0x000, 0), /* MX53_PAD_GPIO_0__CSU_TD */
-	IMX_PIN_REG(MX53_PAD_GPIO_1, 0x6A8, 0x318, 0, 0x7DC, 1), /* MX53_PAD_GPIO_1__ESAI1_SCKR */
-	IMX_PIN_REG(MX53_PAD_GPIO_1, 0x6A8, 0x318, 1, 0x000, 0), /* MX53_PAD_GPIO_1__GPIO1_1 */
-	IMX_PIN_REG(MX53_PAD_GPIO_1, 0x6A8, 0x318, 2, 0x84C, 2), /* MX53_PAD_GPIO_1__KPP_ROW_5 */
-	IMX_PIN_REG(MX53_PAD_GPIO_1, 0x6A8, 0x318, 3, 0x000, 0), /* MX53_PAD_GPIO_1__CCM_SSI_EXT2_CLK */
-	IMX_PIN_REG(MX53_PAD_GPIO_1, 0x6A8, 0x318, 4, 0x000, 0), /* MX53_PAD_GPIO_1__PWM2_PWMO */
-	IMX_PIN_REG(MX53_PAD_GPIO_1, 0x6A8, 0x318, 5, 0x000, 0), /* MX53_PAD_GPIO_1__WDOG2_WDOG_B */
-	IMX_PIN_REG(MX53_PAD_GPIO_1, 0x6A8, 0x318, 6, 0x000, 0), /* MX53_PAD_GPIO_1__ESDHC1_CD */
-	IMX_PIN_REG(MX53_PAD_GPIO_1, 0x6A8, 0x318, 7, 0x000, 0), /* MX53_PAD_GPIO_1__SRC_TESTER_ACK */
-	IMX_PIN_REG(MX53_PAD_GPIO_9, 0x6AC, 0x31C, 0, 0x7CC, 1), /* MX53_PAD_GPIO_9__ESAI1_FSR */
-	IMX_PIN_REG(MX53_PAD_GPIO_9, 0x6AC, 0x31C, 1, 0x000, 0), /* MX53_PAD_GPIO_9__GPIO1_9 */
-	IMX_PIN_REG(MX53_PAD_GPIO_9, 0x6AC, 0x31C, 2, 0x844, 2), /* MX53_PAD_GPIO_9__KPP_COL_6 */
-	IMX_PIN_REG(MX53_PAD_GPIO_9, 0x6AC, 0x31C, 3, 0x000, 0), /* MX53_PAD_GPIO_9__CCM_REF_EN_B */
-	IMX_PIN_REG(MX53_PAD_GPIO_9, 0x6AC, 0x31C, 4, 0x000, 0), /* MX53_PAD_GPIO_9__PWM1_PWMO */
-	IMX_PIN_REG(MX53_PAD_GPIO_9, 0x6AC, 0x31C, 5, 0x000, 0), /* MX53_PAD_GPIO_9__WDOG1_WDOG_B */
-	IMX_PIN_REG(MX53_PAD_GPIO_9, 0x6AC, 0x31C, 6, 0x7FC, 1), /* MX53_PAD_GPIO_9__ESDHC1_WP */
-	IMX_PIN_REG(MX53_PAD_GPIO_9, 0x6AC, 0x31C, 7, 0x000, 0), /* MX53_PAD_GPIO_9__SCC_FAIL_STATE */
-	IMX_PIN_REG(MX53_PAD_GPIO_3, 0x6B0, 0x320, 0, 0x7D4, 1), /* MX53_PAD_GPIO_3__ESAI1_HCKR */
-	IMX_PIN_REG(MX53_PAD_GPIO_3, 0x6B0, 0x320, 1, 0x000, 0), /* MX53_PAD_GPIO_3__GPIO1_3 */
-	IMX_PIN_REG(MX53_PAD_GPIO_3, 0x6B0, 0x320, 2, 0x824, 1), /* MX53_PAD_GPIO_3__I2C3_SCL */
-	IMX_PIN_REG(MX53_PAD_GPIO_3, 0x6B0, 0x320, 3, 0x000, 0), /* MX53_PAD_GPIO_3__DPLLIP1_TOG_EN */
-	IMX_PIN_REG(MX53_PAD_GPIO_3, 0x6B0, 0x320, 4, 0x000, 0), /* MX53_PAD_GPIO_3__CCM_CLKO2 */
-	IMX_PIN_REG(MX53_PAD_GPIO_3, 0x6B0, 0x320, 5, 0x000, 0), /* MX53_PAD_GPIO_3__OBSERVE_MUX_OBSRV_INT_OUT0 */
-	IMX_PIN_REG(MX53_PAD_GPIO_3, 0x6B0, 0x320, 6, 0x8A0, 1), /* MX53_PAD_GPIO_3__USBOH3_USBH1_OC */
-	IMX_PIN_REG(MX53_PAD_GPIO_3, 0x6B0, 0x320, 7, 0x858, 2), /* MX53_PAD_GPIO_3__MLB_MLBCLK */
-	IMX_PIN_REG(MX53_PAD_GPIO_6, 0x6B4, 0x324, 0, 0x7E0, 1), /* MX53_PAD_GPIO_6__ESAI1_SCKT */
-	IMX_PIN_REG(MX53_PAD_GPIO_6, 0x6B4, 0x324, 1, 0x000, 0), /* MX53_PAD_GPIO_6__GPIO1_6 */
-	IMX_PIN_REG(MX53_PAD_GPIO_6, 0x6B4, 0x324, 2, 0x828, 1), /* MX53_PAD_GPIO_6__I2C3_SDA */
-	IMX_PIN_REG(MX53_PAD_GPIO_6, 0x6B4, 0x324, 3, 0x000, 0), /* MX53_PAD_GPIO_6__CCM_CCM_OUT_0 */
-	IMX_PIN_REG(MX53_PAD_GPIO_6, 0x6B4, 0x324, 4, 0x000, 0), /* MX53_PAD_GPIO_6__CSU_CSU_INT_DEB */
-	IMX_PIN_REG(MX53_PAD_GPIO_6, 0x6B4, 0x324, 5, 0x000, 0), /* MX53_PAD_GPIO_6__OBSERVE_MUX_OBSRV_INT_OUT1 */
-	IMX_PIN_REG(MX53_PAD_GPIO_6, 0x6B4, 0x324, 6, 0x000, 0), /* MX53_PAD_GPIO_6__ESDHC2_LCTL */
-	IMX_PIN_REG(MX53_PAD_GPIO_6, 0x6B4, 0x324, 7, 0x860, 2), /* MX53_PAD_GPIO_6__MLB_MLBSIG */
-	IMX_PIN_REG(MX53_PAD_GPIO_2, 0x6B8, 0x328, 0, 0x7D0, 1), /* MX53_PAD_GPIO_2__ESAI1_FST */
-	IMX_PIN_REG(MX53_PAD_GPIO_2, 0x6B8, 0x328, 1, 0x000, 0), /* MX53_PAD_GPIO_2__GPIO1_2 */
-	IMX_PIN_REG(MX53_PAD_GPIO_2, 0x6B8, 0x328, 2, 0x850, 2), /* MX53_PAD_GPIO_2__KPP_ROW_6 */
-	IMX_PIN_REG(MX53_PAD_GPIO_2, 0x6B8, 0x328, 3, 0x000, 0), /* MX53_PAD_GPIO_2__CCM_CCM_OUT_1 */
-	IMX_PIN_REG(MX53_PAD_GPIO_2, 0x6B8, 0x328, 4, 0x000, 0), /* MX53_PAD_GPIO_2__CSU_CSU_ALARM_AUT_0 */
-	IMX_PIN_REG(MX53_PAD_GPIO_2, 0x6B8, 0x328, 5, 0x000, 0), /* MX53_PAD_GPIO_2__OBSERVE_MUX_OBSRV_INT_OUT2 */
-	IMX_PIN_REG(MX53_PAD_GPIO_2, 0x6B8, 0x328, 6, 0x000, 0), /* MX53_PAD_GPIO_2__ESDHC2_WP */
-	IMX_PIN_REG(MX53_PAD_GPIO_2, 0x6B8, 0x328, 7, 0x85C, 2), /* MX53_PAD_GPIO_2__MLB_MLBDAT */
-	IMX_PIN_REG(MX53_PAD_GPIO_4, 0x6BC, 0x32C, 0, 0x7D8, 1), /* MX53_PAD_GPIO_4__ESAI1_HCKT */
-	IMX_PIN_REG(MX53_PAD_GPIO_4, 0x6BC, 0x32C, 1, 0x000, 0), /* MX53_PAD_GPIO_4__GPIO1_4 */
-	IMX_PIN_REG(MX53_PAD_GPIO_4, 0x6BC, 0x32C, 2, 0x848, 2), /* MX53_PAD_GPIO_4__KPP_COL_7 */
-	IMX_PIN_REG(MX53_PAD_GPIO_4, 0x6BC, 0x32C, 3, 0x000, 0), /* MX53_PAD_GPIO_4__CCM_CCM_OUT_2 */
-	IMX_PIN_REG(MX53_PAD_GPIO_4, 0x6BC, 0x32C, 4, 0x000, 0), /* MX53_PAD_GPIO_4__CSU_CSU_ALARM_AUT_1 */
-	IMX_PIN_REG(MX53_PAD_GPIO_4, 0x6BC, 0x32C, 5, 0x000, 0), /* MX53_PAD_GPIO_4__OBSERVE_MUX_OBSRV_INT_OUT3 */
-	IMX_PIN_REG(MX53_PAD_GPIO_4, 0x6BC, 0x32C, 6, 0x000, 0), /* MX53_PAD_GPIO_4__ESDHC2_CD */
-	IMX_PIN_REG(MX53_PAD_GPIO_4, 0x6BC, 0x32C, 7, 0x000, 0), /* MX53_PAD_GPIO_4__SCC_SEC_STATE */
-	IMX_PIN_REG(MX53_PAD_GPIO_5, 0x6C0, 0x330, 0, 0x7EC, 1), /* MX53_PAD_GPIO_5__ESAI1_TX2_RX3 */
-	IMX_PIN_REG(MX53_PAD_GPIO_5, 0x6C0, 0x330, 1, 0x000, 0), /* MX53_PAD_GPIO_5__GPIO1_5 */
-	IMX_PIN_REG(MX53_PAD_GPIO_5, 0x6C0, 0x330, 2, 0x854, 2), /* MX53_PAD_GPIO_5__KPP_ROW_7 */
-	IMX_PIN_REG(MX53_PAD_GPIO_5, 0x6C0, 0x330, 3, 0x000, 0), /* MX53_PAD_GPIO_5__CCM_CLKO */
-	IMX_PIN_REG(MX53_PAD_GPIO_5, 0x6C0, 0x330, 4, 0x000, 0), /* MX53_PAD_GPIO_5__CSU_CSU_ALARM_AUT_2 */
-	IMX_PIN_REG(MX53_PAD_GPIO_5, 0x6C0, 0x330, 5, 0x000, 0), /* MX53_PAD_GPIO_5__OBSERVE_MUX_OBSRV_INT_OUT4 */
-	IMX_PIN_REG(MX53_PAD_GPIO_5, 0x6C0, 0x330, 6, 0x824, 2), /* MX53_PAD_GPIO_5__I2C3_SCL */
-	IMX_PIN_REG(MX53_PAD_GPIO_5, 0x6C0, 0x330, 7, 0x770, 1), /* MX53_PAD_GPIO_5__CCM_PLL1_BYP */
-	IMX_PIN_REG(MX53_PAD_GPIO_7, 0x6C4, 0x334, 0, 0x7F4, 1), /* MX53_PAD_GPIO_7__ESAI1_TX4_RX1 */
-	IMX_PIN_REG(MX53_PAD_GPIO_7, 0x6C4, 0x334, 1, 0x000, 0), /* MX53_PAD_GPIO_7__GPIO1_7 */
-	IMX_PIN_REG(MX53_PAD_GPIO_7, 0x6C4, 0x334, 2, 0x000, 0), /* MX53_PAD_GPIO_7__EPIT1_EPITO */
-	IMX_PIN_REG(MX53_PAD_GPIO_7, 0x6C4, 0x334, 3, 0x000, 0), /* MX53_PAD_GPIO_7__CAN1_TXCAN */
-	IMX_PIN_REG(MX53_PAD_GPIO_7, 0x6C4, 0x334, 4, 0x000, 0), /* MX53_PAD_GPIO_7__UART2_TXD_MUX */
-	IMX_PIN_REG(MX53_PAD_GPIO_7, 0x6C4, 0x334, 5, 0x80C, 1), /* MX53_PAD_GPIO_7__FIRI_RXD */
-	IMX_PIN_REG(MX53_PAD_GPIO_7, 0x6C4, 0x334, 6, 0x000, 0), /* MX53_PAD_GPIO_7__SPDIF_PLOCK */
-	IMX_PIN_REG(MX53_PAD_GPIO_7, 0x6C4, 0x334, 7, 0x774, 1), /* MX53_PAD_GPIO_7__CCM_PLL2_BYP */
-	IMX_PIN_REG(MX53_PAD_GPIO_8, 0x6C8, 0x338, 0, 0x7F8, 1), /* MX53_PAD_GPIO_8__ESAI1_TX5_RX0 */
-	IMX_PIN_REG(MX53_PAD_GPIO_8, 0x6C8, 0x338, 1, 0x000, 0), /* MX53_PAD_GPIO_8__GPIO1_8 */
-	IMX_PIN_REG(MX53_PAD_GPIO_8, 0x6C8, 0x338, 2, 0x000, 0), /* MX53_PAD_GPIO_8__EPIT2_EPITO */
-	IMX_PIN_REG(MX53_PAD_GPIO_8, 0x6C8, 0x338, 3, 0x760, 2), /* MX53_PAD_GPIO_8__CAN1_RXCAN */
-	IMX_PIN_REG(MX53_PAD_GPIO_8, 0x6C8, 0x338, 4, 0x880, 5), /* MX53_PAD_GPIO_8__UART2_RXD_MUX */
-	IMX_PIN_REG(MX53_PAD_GPIO_8, 0x6C8, 0x338, 5, 0x000, 0), /* MX53_PAD_GPIO_8__FIRI_TXD */
-	IMX_PIN_REG(MX53_PAD_GPIO_8, 0x6C8, 0x338, 6, 0x000, 0), /* MX53_PAD_GPIO_8__SPDIF_SRCLK */
-	IMX_PIN_REG(MX53_PAD_GPIO_8, 0x6C8, 0x338, 7, 0x778, 1), /* MX53_PAD_GPIO_8__CCM_PLL3_BYP */
-	IMX_PIN_REG(MX53_PAD_GPIO_16, 0x6CC, 0x33C, 0, 0x7F0, 1), /* MX53_PAD_GPIO_16__ESAI1_TX3_RX2 */
-	IMX_PIN_REG(MX53_PAD_GPIO_16, 0x6CC, 0x33C, 1, 0x000, 0), /* MX53_PAD_GPIO_16__GPIO7_11 */
-	IMX_PIN_REG(MX53_PAD_GPIO_16, 0x6CC, 0x33C, 2, 0x000, 0), /* MX53_PAD_GPIO_16__TZIC_PWRFAIL_INT */
-	IMX_PIN_REG(MX53_PAD_GPIO_16, 0x6CC, 0x33C, 4, 0x000, 0), /* MX53_PAD_GPIO_16__RTC_CE_RTC_EXT_TRIG1 */
-	IMX_PIN_REG(MX53_PAD_GPIO_16, 0x6CC, 0x33C, 5, 0x870, 1), /* MX53_PAD_GPIO_16__SPDIF_IN1 */
-	IMX_PIN_REG(MX53_PAD_GPIO_16, 0x6CC, 0x33C, 6, 0x828, 2), /* MX53_PAD_GPIO_16__I2C3_SDA */
-	IMX_PIN_REG(MX53_PAD_GPIO_16, 0x6CC, 0x33C, 7, 0x000, 0), /* MX53_PAD_GPIO_16__SJC_DE_B */
-	IMX_PIN_REG(MX53_PAD_GPIO_17, 0x6D0, 0x340, 0, 0x7E4, 1), /* MX53_PAD_GPIO_17__ESAI1_TX0 */
-	IMX_PIN_REG(MX53_PAD_GPIO_17, 0x6D0, 0x340, 1, 0x000, 0), /* MX53_PAD_GPIO_17__GPIO7_12 */
-	IMX_PIN_REG(MX53_PAD_GPIO_17, 0x6D0, 0x340, 2, 0x868, 1), /* MX53_PAD_GPIO_17__SDMA_EXT_EVENT_0 */
-	IMX_PIN_REG(MX53_PAD_GPIO_17, 0x6D0, 0x340, 3, 0x810, 1), /* MX53_PAD_GPIO_17__GPC_PMIC_RDY */
-	IMX_PIN_REG(MX53_PAD_GPIO_17, 0x6D0, 0x340, 4, 0x000, 0), /* MX53_PAD_GPIO_17__RTC_CE_RTC_FSV_TRIG */
-	IMX_PIN_REG(MX53_PAD_GPIO_17, 0x6D0, 0x340, 5, 0x000, 0), /* MX53_PAD_GPIO_17__SPDIF_OUT1 */
-	IMX_PIN_REG(MX53_PAD_GPIO_17, 0x6D0, 0x340, 6, 0x000, 0), /* MX53_PAD_GPIO_17__IPU_SNOOP2 */
-	IMX_PIN_REG(MX53_PAD_GPIO_17, 0x6D0, 0x340, 7, 0x000, 0), /* MX53_PAD_GPIO_17__SJC_JTAG_ACT */
-	IMX_PIN_REG(MX53_PAD_GPIO_18, 0x6D4, 0x344, 0, 0x7E8, 1), /* MX53_PAD_GPIO_18__ESAI1_TX1 */
-	IMX_PIN_REG(MX53_PAD_GPIO_18, 0x6D4, 0x344, 1, 0x000, 0), /* MX53_PAD_GPIO_18__GPIO7_13 */
-	IMX_PIN_REG(MX53_PAD_GPIO_18, 0x6D4, 0x344, 2, 0x86C, 1), /* MX53_PAD_GPIO_18__SDMA_EXT_EVENT_1 */
-	IMX_PIN_REG(MX53_PAD_GPIO_18, 0x6D4, 0x344, 3, 0x864, 1), /* MX53_PAD_GPIO_18__OWIRE_LINE */
-	IMX_PIN_REG(MX53_PAD_GPIO_18, 0x6D4, 0x344, 4, 0x000, 0), /* MX53_PAD_GPIO_18__RTC_CE_RTC_ALARM2_TRIG */
-	IMX_PIN_REG(MX53_PAD_GPIO_18, 0x6D4, 0x344, 5, 0x768, 1), /* MX53_PAD_GPIO_18__CCM_ASRC_EXT_CLK */
-	IMX_PIN_REG(MX53_PAD_GPIO_18, 0x6D4, 0x344, 6, 0x000, 0), /* MX53_PAD_GPIO_18__ESDHC1_LCTL */
-	IMX_PIN_REG(MX53_PAD_GPIO_18, 0x6D4, 0x344, 7, 0x000, 0), /* MX53_PAD_GPIO_18__SRC_SYSTEM_RST */
+	MX53_PAD_GPIO_19 = 8,
+	MX53_PAD_KEY_COL0 = 9,
+	MX53_PAD_KEY_ROW0 = 10,
+	MX53_PAD_KEY_COL1 = 11,
+	MX53_PAD_KEY_ROW1 = 12,
+	MX53_PAD_KEY_COL2 = 13,
+	MX53_PAD_KEY_ROW2 = 14,
+	MX53_PAD_KEY_COL3 = 15,
+	MX53_PAD_KEY_ROW3 = 16,
+	MX53_PAD_KEY_COL4 = 17,
+	MX53_PAD_KEY_ROW4 = 18,
+	MX53_PAD_DI0_DISP_CLK = 19,
+	MX53_PAD_DI0_PIN15 = 20,
+	MX53_PAD_DI0_PIN2 = 21,
+	MX53_PAD_DI0_PIN3 = 22,
+	MX53_PAD_DI0_PIN4 = 23,
+	MX53_PAD_DISP0_DAT0 = 24,
+	MX53_PAD_DISP0_DAT1 = 25,
+	MX53_PAD_DISP0_DAT2 = 26,
+	MX53_PAD_DISP0_DAT3 = 27,
+	MX53_PAD_DISP0_DAT4 = 28,
+	MX53_PAD_DISP0_DAT5 = 29,
+	MX53_PAD_DISP0_DAT6 = 30,
+	MX53_PAD_DISP0_DAT7 = 31,
+	MX53_PAD_DISP0_DAT8 = 32,
+	MX53_PAD_DISP0_DAT9 = 33,
+	MX53_PAD_DISP0_DAT10 = 34,
+	MX53_PAD_DISP0_DAT11 = 35,
+	MX53_PAD_DISP0_DAT12 = 36,
+	MX53_PAD_DISP0_DAT13 = 37,
+	MX53_PAD_DISP0_DAT14 = 38,
+	MX53_PAD_DISP0_DAT15 = 39,
+	MX53_PAD_DISP0_DAT16 = 40,
+	MX53_PAD_DISP0_DAT17 = 41,
+	MX53_PAD_DISP0_DAT18 = 42,
+	MX53_PAD_DISP0_DAT19 = 43,
+	MX53_PAD_DISP0_DAT20 = 44,
+	MX53_PAD_DISP0_DAT21 = 45,
+	MX53_PAD_DISP0_DAT22 = 46,
+	MX53_PAD_DISP0_DAT23 = 47,
+	MX53_PAD_CSI0_PIXCLK = 48,
+	MX53_PAD_CSI0_MCLK = 49,
+	MX53_PAD_CSI0_DATA_EN = 50,
+	MX53_PAD_CSI0_VSYNC = 51,
+	MX53_PAD_CSI0_DAT4 = 52,
+	MX53_PAD_CSI0_DAT5 = 53,
+	MX53_PAD_CSI0_DAT6 = 54,
+	MX53_PAD_CSI0_DAT7 = 55,
+	MX53_PAD_CSI0_DAT8 = 56,
+	MX53_PAD_CSI0_DAT9 = 57,
+	MX53_PAD_CSI0_DAT10 = 58,
+	MX53_PAD_CSI0_DAT11 = 59,
+	MX53_PAD_CSI0_DAT12 = 60,
+	MX53_PAD_CSI0_DAT13 = 61,
+	MX53_PAD_CSI0_DAT14 = 62,
+	MX53_PAD_CSI0_DAT15 = 63,
+	MX53_PAD_CSI0_DAT16 = 64,
+	MX53_PAD_CSI0_DAT17 = 65,
+	MX53_PAD_CSI0_DAT18 = 66,
+	MX53_PAD_CSI0_DAT19 = 67,
+	MX53_PAD_EIM_A25 = 68,
+	MX53_PAD_EIM_EB2 = 69,
+	MX53_PAD_EIM_D16 = 70,
+	MX53_PAD_EIM_D17 = 71,
+	MX53_PAD_EIM_D18 = 72,
+	MX53_PAD_EIM_D19 = 73,
+	MX53_PAD_EIM_D20 = 74,
+	MX53_PAD_EIM_D21 = 75,
+	MX53_PAD_EIM_D22 = 76,
+	MX53_PAD_EIM_D23 = 77,
+	MX53_PAD_EIM_EB3 = 78,
+	MX53_PAD_EIM_D24 = 79,
+	MX53_PAD_EIM_D25 = 80,
+	MX53_PAD_EIM_D26 = 81,
+	MX53_PAD_EIM_D27 = 82,
+	MX53_PAD_EIM_D28 = 83,
+	MX53_PAD_EIM_D29 = 84,
+	MX53_PAD_EIM_D30 = 85,
+	MX53_PAD_EIM_D31 = 86,
+	MX53_PAD_EIM_A24 = 87,
+	MX53_PAD_EIM_A23 = 88,
+	MX53_PAD_EIM_A22 = 89,
+	MX53_PAD_EIM_A21 = 90,
+	MX53_PAD_EIM_A20 = 91,
+	MX53_PAD_EIM_A19 = 92,
+	MX53_PAD_EIM_A18 = 93,
+	MX53_PAD_EIM_A17 = 94,
+	MX53_PAD_EIM_A16 = 95,
+	MX53_PAD_EIM_CS0 = 96,
+	MX53_PAD_EIM_CS1 = 97,
+	MX53_PAD_EIM_OE = 98,
+	MX53_PAD_EIM_RW = 99,
+	MX53_PAD_EIM_LBA = 100,
+	MX53_PAD_EIM_EB0 = 101,
+	MX53_PAD_EIM_EB1 = 102,
+	MX53_PAD_EIM_DA0 = 103,
+	MX53_PAD_EIM_DA1 = 104,
+	MX53_PAD_EIM_DA2 = 105,
+	MX53_PAD_EIM_DA3 = 106,
+	MX53_PAD_EIM_DA4 = 107,
+	MX53_PAD_EIM_DA5 = 108,
+	MX53_PAD_EIM_DA6 = 109,
+	MX53_PAD_EIM_DA7 = 110,
+	MX53_PAD_EIM_DA8 = 111,
+	MX53_PAD_EIM_DA9 = 112,
+	MX53_PAD_EIM_DA10 = 113,
+	MX53_PAD_EIM_DA11 = 114,
+	MX53_PAD_EIM_DA12 = 115,
+	MX53_PAD_EIM_DA13 = 116,
+	MX53_PAD_EIM_DA14 = 117,
+	MX53_PAD_EIM_DA15 = 118,
+	MX53_PAD_NANDF_WE_B = 119,
+	MX53_PAD_NANDF_RE_B = 120,
+	MX53_PAD_EIM_WAIT = 121,
+	MX53_PAD_LVDS1_TX3_P = 123,
+	MX53_PAD_LVDS1_TX2_P = 124,
+	MX53_PAD_LVDS1_CLK_P = 125,
+	MX53_PAD_LVDS1_TX1_P = 126,
+	MX53_PAD_LVDS1_TX0_P = 127,
+	MX53_PAD_LVDS0_TX3_P = 128,
+	MX53_PAD_LVDS0_CLK_P = 129,
+	MX53_PAD_LVDS0_TX2_P = 130,
+	MX53_PAD_LVDS0_TX1_P = 131,
+	MX53_PAD_LVDS0_TX0_P = 132,
+	MX53_PAD_GPIO_10 = 133,
+	MX53_PAD_GPIO_11 = 134,
+	MX53_PAD_GPIO_12 = 135,
+	MX53_PAD_GPIO_13 = 136,
+	MX53_PAD_GPIO_14 = 137,
+	MX53_PAD_NANDF_CLE = 138,
+	MX53_PAD_NANDF_ALE = 139,
+	MX53_PAD_NANDF_WP_B = 140,
+	MX53_PAD_NANDF_RB0 = 141,
+	MX53_PAD_NANDF_CS0 = 142,
+	MX53_PAD_NANDF_CS1 = 143,
+	MX53_PAD_NANDF_CS2 = 144,
+	MX53_PAD_NANDF_CS3 = 145,
+	MX53_PAD_FEC_MDIO = 146,
+	MX53_PAD_FEC_REF_CLK = 147,
+	MX53_PAD_FEC_RX_ER = 148,
+	MX53_PAD_FEC_CRS_DV = 149,
+	MX53_PAD_FEC_RXD1 = 150,
+	MX53_PAD_FEC_RXD0 = 151,
+	MX53_PAD_FEC_TX_EN = 152,
+	MX53_PAD_FEC_TXD1 = 153,
+	MX53_PAD_FEC_TXD0 = 154,
+	MX53_PAD_FEC_MDC = 155,
+	MX53_PAD_PATA_DIOW = 156,
+	MX53_PAD_PATA_DMACK = 157,
+	MX53_PAD_PATA_DMARQ = 158,
+	MX53_PAD_PATA_BUFFER_EN = 159,
+	MX53_PAD_PATA_INTRQ = 160,
+	MX53_PAD_PATA_DIOR = 161,
+	MX53_PAD_PATA_RESET_B = 162,
+	MX53_PAD_PATA_IORDY = 163,
+	MX53_PAD_PATA_DA_0 = 164,
+	MX53_PAD_PATA_DA_1 = 165,
+	MX53_PAD_PATA_DA_2 = 166,
+	MX53_PAD_PATA_CS_0 = 167,
+	MX53_PAD_PATA_CS_1 = 168,
+	MX53_PAD_PATA_DATA0 = 169,
+	MX53_PAD_PATA_DATA1 = 170,
+	MX53_PAD_PATA_DATA2 = 171,
+	MX53_PAD_PATA_DATA3 = 172,
+	MX53_PAD_PATA_DATA4 = 173,
+	MX53_PAD_PATA_DATA5 = 174,
+	MX53_PAD_PATA_DATA6 = 175,
+	MX53_PAD_PATA_DATA7 = 176,
+	MX53_PAD_PATA_DATA8 = 177,
+	MX53_PAD_PATA_DATA9 = 178,
+	MX53_PAD_PATA_DATA10 = 179,
+	MX53_PAD_PATA_DATA11 = 180,
+	MX53_PAD_PATA_DATA12 = 181,
+	MX53_PAD_PATA_DATA13 = 182,
+	MX53_PAD_PATA_DATA14 = 183,
+	MX53_PAD_PATA_DATA15 = 184,
+	MX53_PAD_SD1_DATA0 = 185,
+	MX53_PAD_SD1_DATA1 = 186,
+	MX53_PAD_SD1_CMD = 187,
+	MX53_PAD_SD1_DATA2 = 188,
+	MX53_PAD_SD1_CLK = 189,
+	MX53_PAD_SD1_DATA3 = 190,
+	MX53_PAD_SD2_CLK = 191,
+	MX53_PAD_SD2_CMD = 192,
+	MX53_PAD_SD2_DATA3 = 193,
+	MX53_PAD_SD2_DATA2 = 194,
+	MX53_PAD_SD2_DATA1 = 195,
+	MX53_PAD_SD2_DATA0 = 196,
+	MX53_PAD_GPIO_0 = 197,
+	MX53_PAD_GPIO_1 = 198,
+	MX53_PAD_GPIO_9 = 199,
+	MX53_PAD_GPIO_3 = 200,
+	MX53_PAD_GPIO_6 = 201,
+	MX53_PAD_GPIO_2 = 202,
+	MX53_PAD_GPIO_4 = 203,
+	MX53_PAD_GPIO_5 = 204,
+	MX53_PAD_GPIO_7 = 205,
+	MX53_PAD_GPIO_8 = 206,
+	MX53_PAD_GPIO_16 = 207,
+	MX53_PAD_GPIO_17 = 208,
+	MX53_PAD_GPIO_18 = 209,
 };
 
 /* Pad names for the pinmux subsystem */
@@ -1609,8 +434,6 @@ static const struct pinctrl_pin_desc imx53_pinctrl_pads[] = {
 static struct imx_pinctrl_soc_info imx53_pinctrl_info = {
 	.pins = imx53_pinctrl_pads,
 	.npins = ARRAY_SIZE(imx53_pinctrl_pads),
-	.pin_regs = imx53_pin_regs,
-	.npin_regs = ARRAY_SIZE(imx53_pin_regs),
 };
 
 static struct of_device_id imx53_pinctrl_of_match[] = {
diff --git a/drivers/pinctrl/pinctrl-imx6dl.c b/drivers/pinctrl/pinctrl-imx6dl.c
new file mode 100644
index 0000000..66487c1
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-imx6dl.c
@@ -0,0 +1,459 @@
+/*
+ * Copyright (C) 2013 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-imx.h"
+
+enum imx6dl_pads {
+	MX6DL_PAD_CSI0_DAT10 = 19,
+	MX6DL_PAD_CSI0_DAT11 = 20,
+	MX6DL_PAD_CSI0_DAT12 = 21,
+	MX6DL_PAD_CSI0_DAT13 = 22,
+	MX6DL_PAD_CSI0_DAT14 = 23,
+	MX6DL_PAD_CSI0_DAT15 = 24,
+	MX6DL_PAD_CSI0_DAT16 = 25,
+	MX6DL_PAD_CSI0_DAT17 = 26,
+	MX6DL_PAD_CSI0_DAT18 = 27,
+	MX6DL_PAD_CSI0_DAT19 = 28,
+	MX6DL_PAD_CSI0_DAT4 = 29,
+	MX6DL_PAD_CSI0_DAT5 = 30,
+	MX6DL_PAD_CSI0_DAT6 = 31,
+	MX6DL_PAD_CSI0_DAT7 = 32,
+	MX6DL_PAD_CSI0_DAT8 = 33,
+	MX6DL_PAD_CSI0_DAT9 = 34,
+	MX6DL_PAD_CSI0_DATA_EN = 35,
+	MX6DL_PAD_CSI0_MCLK = 36,
+	MX6DL_PAD_CSI0_PIXCLK = 37,
+	MX6DL_PAD_CSI0_VSYNC = 38,
+	MX6DL_PAD_DI0_DISP_CLK = 39,
+	MX6DL_PAD_DI0_PIN15 = 40,
+	MX6DL_PAD_DI0_PIN2 = 41,
+	MX6DL_PAD_DI0_PIN3 = 42,
+	MX6DL_PAD_DI0_PIN4 = 43,
+	MX6DL_PAD_DISP0_DAT0 = 44,
+	MX6DL_PAD_DISP0_DAT1 = 45,
+	MX6DL_PAD_DISP0_DAT10 = 46,
+	MX6DL_PAD_DISP0_DAT11 = 47,
+	MX6DL_PAD_DISP0_DAT12 = 48,
+	MX6DL_PAD_DISP0_DAT13 = 49,
+	MX6DL_PAD_DISP0_DAT14 = 50,
+	MX6DL_PAD_DISP0_DAT15 = 51,
+	MX6DL_PAD_DISP0_DAT16 = 52,
+	MX6DL_PAD_DISP0_DAT17 = 53,
+	MX6DL_PAD_DISP0_DAT18 = 54,
+	MX6DL_PAD_DISP0_DAT19 = 55,
+	MX6DL_PAD_DISP0_DAT2 = 56,
+	MX6DL_PAD_DISP0_DAT20 = 57,
+	MX6DL_PAD_DISP0_DAT21 = 58,
+	MX6DL_PAD_DISP0_DAT22 = 59,
+	MX6DL_PAD_DISP0_DAT23 = 60,
+	MX6DL_PAD_DISP0_DAT3 = 61,
+	MX6DL_PAD_DISP0_DAT4 = 62,
+	MX6DL_PAD_DISP0_DAT5 = 63,
+	MX6DL_PAD_DISP0_DAT6 = 64,
+	MX6DL_PAD_DISP0_DAT7 = 65,
+	MX6DL_PAD_DISP0_DAT8 = 66,
+	MX6DL_PAD_DISP0_DAT9 = 67,
+	MX6DL_PAD_EIM_A16 = 68,
+	MX6DL_PAD_EIM_A17 = 69,
+	MX6DL_PAD_EIM_A18 = 70,
+	MX6DL_PAD_EIM_A19 = 71,
+	MX6DL_PAD_EIM_A20 = 72,
+	MX6DL_PAD_EIM_A21 = 73,
+	MX6DL_PAD_EIM_A22 = 74,
+	MX6DL_PAD_EIM_A23 = 75,
+	MX6DL_PAD_EIM_A24 = 76,
+	MX6DL_PAD_EIM_A25 = 77,
+	MX6DL_PAD_EIM_BCLK = 78,
+	MX6DL_PAD_EIM_CS0 = 79,
+	MX6DL_PAD_EIM_CS1 = 80,
+	MX6DL_PAD_EIM_D16 = 81,
+	MX6DL_PAD_EIM_D17 = 82,
+	MX6DL_PAD_EIM_D18 = 83,
+	MX6DL_PAD_EIM_D19 = 84,
+	MX6DL_PAD_EIM_D20 = 85,
+	MX6DL_PAD_EIM_D21 = 86,
+	MX6DL_PAD_EIM_D22 = 87,
+	MX6DL_PAD_EIM_D23 = 88,
+	MX6DL_PAD_EIM_D24 = 89,
+	MX6DL_PAD_EIM_D25 = 90,
+	MX6DL_PAD_EIM_D26 = 91,
+	MX6DL_PAD_EIM_D27 = 92,
+	MX6DL_PAD_EIM_D28 = 93,
+	MX6DL_PAD_EIM_D29 = 94,
+	MX6DL_PAD_EIM_D30 = 95,
+	MX6DL_PAD_EIM_D31 = 96,
+	MX6DL_PAD_EIM_DA0 = 97,
+	MX6DL_PAD_EIM_DA1 = 98,
+	MX6DL_PAD_EIM_DA10 = 99,
+	MX6DL_PAD_EIM_DA11 = 100,
+	MX6DL_PAD_EIM_DA12 = 101,
+	MX6DL_PAD_EIM_DA13 = 102,
+	MX6DL_PAD_EIM_DA14 = 103,
+	MX6DL_PAD_EIM_DA15 = 104,
+	MX6DL_PAD_EIM_DA2 = 105,
+	MX6DL_PAD_EIM_DA3 = 106,
+	MX6DL_PAD_EIM_DA4 = 107,
+	MX6DL_PAD_EIM_DA5 = 108,
+	MX6DL_PAD_EIM_DA6 = 109,
+	MX6DL_PAD_EIM_DA7 = 110,
+	MX6DL_PAD_EIM_DA8 = 111,
+	MX6DL_PAD_EIM_DA9 = 112,
+	MX6DL_PAD_EIM_EB0 = 113,
+	MX6DL_PAD_EIM_EB1 = 114,
+	MX6DL_PAD_EIM_EB2 = 115,
+	MX6DL_PAD_EIM_EB3 = 116,
+	MX6DL_PAD_EIM_LBA = 117,
+	MX6DL_PAD_EIM_OE = 118,
+	MX6DL_PAD_EIM_RW = 119,
+	MX6DL_PAD_EIM_WAIT = 120,
+	MX6DL_PAD_ENET_CRS_DV = 121,
+	MX6DL_PAD_ENET_MDC = 122,
+	MX6DL_PAD_ENET_MDIO = 123,
+	MX6DL_PAD_ENET_REF_CLK = 124,
+	MX6DL_PAD_ENET_RX_ER = 125,
+	MX6DL_PAD_ENET_RXD0 = 126,
+	MX6DL_PAD_ENET_RXD1 = 127,
+	MX6DL_PAD_ENET_TX_EN = 128,
+	MX6DL_PAD_ENET_TXD0 = 129,
+	MX6DL_PAD_ENET_TXD1 = 130,
+	MX6DL_PAD_GPIO_0 = 131,
+	MX6DL_PAD_GPIO_1 = 132,
+	MX6DL_PAD_GPIO_16 = 133,
+	MX6DL_PAD_GPIO_17 = 134,
+	MX6DL_PAD_GPIO_18 = 135,
+	MX6DL_PAD_GPIO_19 = 136,
+	MX6DL_PAD_GPIO_2 = 137,
+	MX6DL_PAD_GPIO_3 = 138,
+	MX6DL_PAD_GPIO_4 = 139,
+	MX6DL_PAD_GPIO_5 = 140,
+	MX6DL_PAD_GPIO_6 = 141,
+	MX6DL_PAD_GPIO_7 = 142,
+	MX6DL_PAD_GPIO_8 = 143,
+	MX6DL_PAD_GPIO_9 = 144,
+	MX6DL_PAD_KEY_COL0 = 145,
+	MX6DL_PAD_KEY_COL1 = 146,
+	MX6DL_PAD_KEY_COL2 = 147,
+	MX6DL_PAD_KEY_COL3 = 148,
+	MX6DL_PAD_KEY_COL4 = 149,
+	MX6DL_PAD_KEY_ROW0 = 150,
+	MX6DL_PAD_KEY_ROW1 = 151,
+	MX6DL_PAD_KEY_ROW2 = 152,
+	MX6DL_PAD_KEY_ROW3 = 153,
+	MX6DL_PAD_KEY_ROW4 = 154,
+	MX6DL_PAD_NANDF_ALE = 155,
+	MX6DL_PAD_NANDF_CLE = 156,
+	MX6DL_PAD_NANDF_CS0 = 157,
+	MX6DL_PAD_NANDF_CS1 = 158,
+	MX6DL_PAD_NANDF_CS2 = 159,
+	MX6DL_PAD_NANDF_CS3 = 160,
+	MX6DL_PAD_NANDF_D0 = 161,
+	MX6DL_PAD_NANDF_D1 = 162,
+	MX6DL_PAD_NANDF_D2 = 163,
+	MX6DL_PAD_NANDF_D3 = 164,
+	MX6DL_PAD_NANDF_D4 = 165,
+	MX6DL_PAD_NANDF_D5 = 166,
+	MX6DL_PAD_NANDF_D6 = 167,
+	MX6DL_PAD_NANDF_D7 = 168,
+	MX6DL_PAD_NANDF_RB0 = 169,
+	MX6DL_PAD_NANDF_WP_B = 170,
+	MX6DL_PAD_RGMII_RD0 = 171,
+	MX6DL_PAD_RGMII_RD1 = 172,
+	MX6DL_PAD_RGMII_RD2 = 173,
+	MX6DL_PAD_RGMII_RD3 = 174,
+	MX6DL_PAD_RGMII_RX_CTL = 175,
+	MX6DL_PAD_RGMII_RXC = 176,
+	MX6DL_PAD_RGMII_TD0 = 177,
+	MX6DL_PAD_RGMII_TD1 = 178,
+	MX6DL_PAD_RGMII_TD2 = 179,
+	MX6DL_PAD_RGMII_TD3 = 180,
+	MX6DL_PAD_RGMII_TX_CTL = 181,
+	MX6DL_PAD_RGMII_TXC = 182,
+	MX6DL_PAD_SD1_CLK = 183,
+	MX6DL_PAD_SD1_CMD = 184,
+	MX6DL_PAD_SD1_DAT0 = 185,
+	MX6DL_PAD_SD1_DAT1 = 186,
+	MX6DL_PAD_SD1_DAT2 = 187,
+	MX6DL_PAD_SD1_DAT3 = 188,
+	MX6DL_PAD_SD2_CLK = 189,
+	MX6DL_PAD_SD2_CMD = 190,
+	MX6DL_PAD_SD2_DAT0 = 191,
+	MX6DL_PAD_SD2_DAT1 = 192,
+	MX6DL_PAD_SD2_DAT2 = 193,
+	MX6DL_PAD_SD2_DAT3 = 194,
+	MX6DL_PAD_SD3_CLK = 195,
+	MX6DL_PAD_SD3_CMD = 196,
+	MX6DL_PAD_SD3_DAT0 = 197,
+	MX6DL_PAD_SD3_DAT1 = 198,
+	MX6DL_PAD_SD3_DAT2 = 199,
+	MX6DL_PAD_SD3_DAT3 = 200,
+	MX6DL_PAD_SD3_DAT4 = 201,
+	MX6DL_PAD_SD3_DAT5 = 202,
+	MX6DL_PAD_SD3_DAT6 = 203,
+	MX6DL_PAD_SD3_DAT7 = 204,
+	MX6DL_PAD_SD3_RST = 205,
+	MX6DL_PAD_SD4_CLK = 206,
+	MX6DL_PAD_SD4_CMD = 207,
+	MX6DL_PAD_SD4_DAT0 = 208,
+	MX6DL_PAD_SD4_DAT1 = 209,
+	MX6DL_PAD_SD4_DAT2 = 210,
+	MX6DL_PAD_SD4_DAT3 = 211,
+	MX6DL_PAD_SD4_DAT4 = 212,
+	MX6DL_PAD_SD4_DAT5 = 213,
+	MX6DL_PAD_SD4_DAT6 = 214,
+	MX6DL_PAD_SD4_DAT7 = 215,
+};
+
+/* Pad names for the pinmux subsystem */
+static const struct pinctrl_pin_desc imx6dl_pinctrl_pads[] = {
+	IMX_PINCTRL_PIN(MX6DL_PAD_CSI0_DAT10),
+	IMX_PINCTRL_PIN(MX6DL_PAD_CSI0_DAT11),
+	IMX_PINCTRL_PIN(MX6DL_PAD_CSI0_DAT12),
+	IMX_PINCTRL_PIN(MX6DL_PAD_CSI0_DAT13),
+	IMX_PINCTRL_PIN(MX6DL_PAD_CSI0_DAT14),
+	IMX_PINCTRL_PIN(MX6DL_PAD_CSI0_DAT15),
+	IMX_PINCTRL_PIN(MX6DL_PAD_CSI0_DAT16),
+	IMX_PINCTRL_PIN(MX6DL_PAD_CSI0_DAT17),
+	IMX_PINCTRL_PIN(MX6DL_PAD_CSI0_DAT18),
+	IMX_PINCTRL_PIN(MX6DL_PAD_CSI0_DAT19),
+	IMX_PINCTRL_PIN(MX6DL_PAD_CSI0_DAT4),
+	IMX_PINCTRL_PIN(MX6DL_PAD_CSI0_DAT5),
+	IMX_PINCTRL_PIN(MX6DL_PAD_CSI0_DAT6),
+	IMX_PINCTRL_PIN(MX6DL_PAD_CSI0_DAT7),
+	IMX_PINCTRL_PIN(MX6DL_PAD_CSI0_DAT8),
+	IMX_PINCTRL_PIN(MX6DL_PAD_CSI0_DAT9),
+	IMX_PINCTRL_PIN(MX6DL_PAD_CSI0_DATA_EN),
+	IMX_PINCTRL_PIN(MX6DL_PAD_CSI0_MCLK),
+	IMX_PINCTRL_PIN(MX6DL_PAD_CSI0_PIXCLK),
+	IMX_PINCTRL_PIN(MX6DL_PAD_CSI0_VSYNC),
+	IMX_PINCTRL_PIN(MX6DL_PAD_DI0_DISP_CLK),
+	IMX_PINCTRL_PIN(MX6DL_PAD_DI0_PIN15),
+	IMX_PINCTRL_PIN(MX6DL_PAD_DI0_PIN2),
+	IMX_PINCTRL_PIN(MX6DL_PAD_DI0_PIN3),
+	IMX_PINCTRL_PIN(MX6DL_PAD_DI0_PIN4),
+	IMX_PINCTRL_PIN(MX6DL_PAD_DISP0_DAT0),
+	IMX_PINCTRL_PIN(MX6DL_PAD_DISP0_DAT1),
+	IMX_PINCTRL_PIN(MX6DL_PAD_DISP0_DAT10),
+	IMX_PINCTRL_PIN(MX6DL_PAD_DISP0_DAT11),
+	IMX_PINCTRL_PIN(MX6DL_PAD_DISP0_DAT12),
+	IMX_PINCTRL_PIN(MX6DL_PAD_DISP0_DAT13),
+	IMX_PINCTRL_PIN(MX6DL_PAD_DISP0_DAT14),
+	IMX_PINCTRL_PIN(MX6DL_PAD_DISP0_DAT15),
+	IMX_PINCTRL_PIN(MX6DL_PAD_DISP0_DAT16),
+	IMX_PINCTRL_PIN(MX6DL_PAD_DISP0_DAT17),
+	IMX_PINCTRL_PIN(MX6DL_PAD_DISP0_DAT18),
+	IMX_PINCTRL_PIN(MX6DL_PAD_DISP0_DAT19),
+	IMX_PINCTRL_PIN(MX6DL_PAD_DISP0_DAT2),
+	IMX_PINCTRL_PIN(MX6DL_PAD_DISP0_DAT20),
+	IMX_PINCTRL_PIN(MX6DL_PAD_DISP0_DAT21),
+	IMX_PINCTRL_PIN(MX6DL_PAD_DISP0_DAT22),
+	IMX_PINCTRL_PIN(MX6DL_PAD_DISP0_DAT23),
+	IMX_PINCTRL_PIN(MX6DL_PAD_DISP0_DAT3),
+	IMX_PINCTRL_PIN(MX6DL_PAD_DISP0_DAT4),
+	IMX_PINCTRL_PIN(MX6DL_PAD_DISP0_DAT5),
+	IMX_PINCTRL_PIN(MX6DL_PAD_DISP0_DAT6),
+	IMX_PINCTRL_PIN(MX6DL_PAD_DISP0_DAT7),
+	IMX_PINCTRL_PIN(MX6DL_PAD_DISP0_DAT8),
+	IMX_PINCTRL_PIN(MX6DL_PAD_DISP0_DAT9),
+	IMX_PINCTRL_PIN(MX6DL_PAD_EIM_A16),
+	IMX_PINCTRL_PIN(MX6DL_PAD_EIM_A17),
+	IMX_PINCTRL_PIN(MX6DL_PAD_EIM_A18),
+	IMX_PINCTRL_PIN(MX6DL_PAD_EIM_A19),
+	IMX_PINCTRL_PIN(MX6DL_PAD_EIM_A20),
+	IMX_PINCTRL_PIN(MX6DL_PAD_EIM_A21),
+	IMX_PINCTRL_PIN(MX6DL_PAD_EIM_A22),
+	IMX_PINCTRL_PIN(MX6DL_PAD_EIM_A23),
+	IMX_PINCTRL_PIN(MX6DL_PAD_EIM_A24),
+	IMX_PINCTRL_PIN(MX6DL_PAD_EIM_A25),
+	IMX_PINCTRL_PIN(MX6DL_PAD_EIM_BCLK),
+	IMX_PINCTRL_PIN(MX6DL_PAD_EIM_CS0),
+	IMX_PINCTRL_PIN(MX6DL_PAD_EIM_CS1),
+	IMX_PINCTRL_PIN(MX6DL_PAD_EIM_D16),
+	IMX_PINCTRL_PIN(MX6DL_PAD_EIM_D17),
+	IMX_PINCTRL_PIN(MX6DL_PAD_EIM_D18),
+	IMX_PINCTRL_PIN(MX6DL_PAD_EIM_D19),
+	IMX_PINCTRL_PIN(MX6DL_PAD_EIM_D20),
+	IMX_PINCTRL_PIN(MX6DL_PAD_EIM_D21),
+	IMX_PINCTRL_PIN(MX6DL_PAD_EIM_D22),
+	IMX_PINCTRL_PIN(MX6DL_PAD_EIM_D23),
+	IMX_PINCTRL_PIN(MX6DL_PAD_EIM_D24),
+	IMX_PINCTRL_PIN(MX6DL_PAD_EIM_D25),
+	IMX_PINCTRL_PIN(MX6DL_PAD_EIM_D26),
+	IMX_PINCTRL_PIN(MX6DL_PAD_EIM_D27),
+	IMX_PINCTRL_PIN(MX6DL_PAD_EIM_D28),
+	IMX_PINCTRL_PIN(MX6DL_PAD_EIM_D29),
+	IMX_PINCTRL_PIN(MX6DL_PAD_EIM_D30),
+	IMX_PINCTRL_PIN(MX6DL_PAD_EIM_D31),
+	IMX_PINCTRL_PIN(MX6DL_PAD_EIM_DA0),
+	IMX_PINCTRL_PIN(MX6DL_PAD_EIM_DA1),
+	IMX_PINCTRL_PIN(MX6DL_PAD_EIM_DA10),
+	IMX_PINCTRL_PIN(MX6DL_PAD_EIM_DA11),
+	IMX_PINCTRL_PIN(MX6DL_PAD_EIM_DA12),
+	IMX_PINCTRL_PIN(MX6DL_PAD_EIM_DA13),
+	IMX_PINCTRL_PIN(MX6DL_PAD_EIM_DA14),
+	IMX_PINCTRL_PIN(MX6DL_PAD_EIM_DA15),
+	IMX_PINCTRL_PIN(MX6DL_PAD_EIM_DA2),
+	IMX_PINCTRL_PIN(MX6DL_PAD_EIM_DA3),
+	IMX_PINCTRL_PIN(MX6DL_PAD_EIM_DA4),
+	IMX_PINCTRL_PIN(MX6DL_PAD_EIM_DA5),
+	IMX_PINCTRL_PIN(MX6DL_PAD_EIM_DA6),
+	IMX_PINCTRL_PIN(MX6DL_PAD_EIM_DA7),
+	IMX_PINCTRL_PIN(MX6DL_PAD_EIM_DA8),
+	IMX_PINCTRL_PIN(MX6DL_PAD_EIM_DA9),
+	IMX_PINCTRL_PIN(MX6DL_PAD_EIM_EB0),
+	IMX_PINCTRL_PIN(MX6DL_PAD_EIM_EB1),
+	IMX_PINCTRL_PIN(MX6DL_PAD_EIM_EB2),
+	IMX_PINCTRL_PIN(MX6DL_PAD_EIM_EB3),
+	IMX_PINCTRL_PIN(MX6DL_PAD_EIM_LBA),
+	IMX_PINCTRL_PIN(MX6DL_PAD_EIM_OE),
+	IMX_PINCTRL_PIN(MX6DL_PAD_EIM_RW),
+	IMX_PINCTRL_PIN(MX6DL_PAD_EIM_WAIT),
+	IMX_PINCTRL_PIN(MX6DL_PAD_ENET_CRS_DV),
+	IMX_PINCTRL_PIN(MX6DL_PAD_ENET_MDC),
+	IMX_PINCTRL_PIN(MX6DL_PAD_ENET_MDIO),
+	IMX_PINCTRL_PIN(MX6DL_PAD_ENET_REF_CLK),
+	IMX_PINCTRL_PIN(MX6DL_PAD_ENET_RX_ER),
+	IMX_PINCTRL_PIN(MX6DL_PAD_ENET_RXD0),
+	IMX_PINCTRL_PIN(MX6DL_PAD_ENET_RXD1),
+	IMX_PINCTRL_PIN(MX6DL_PAD_ENET_TX_EN),
+	IMX_PINCTRL_PIN(MX6DL_PAD_ENET_TXD0),
+	IMX_PINCTRL_PIN(MX6DL_PAD_ENET_TXD1),
+	IMX_PINCTRL_PIN(MX6DL_PAD_GPIO_0),
+	IMX_PINCTRL_PIN(MX6DL_PAD_GPIO_1),
+	IMX_PINCTRL_PIN(MX6DL_PAD_GPIO_16),
+	IMX_PINCTRL_PIN(MX6DL_PAD_GPIO_17),
+	IMX_PINCTRL_PIN(MX6DL_PAD_GPIO_18),
+	IMX_PINCTRL_PIN(MX6DL_PAD_GPIO_19),
+	IMX_PINCTRL_PIN(MX6DL_PAD_GPIO_2),
+	IMX_PINCTRL_PIN(MX6DL_PAD_GPIO_3),
+	IMX_PINCTRL_PIN(MX6DL_PAD_GPIO_4),
+	IMX_PINCTRL_PIN(MX6DL_PAD_GPIO_5),
+	IMX_PINCTRL_PIN(MX6DL_PAD_GPIO_6),
+	IMX_PINCTRL_PIN(MX6DL_PAD_GPIO_7),
+	IMX_PINCTRL_PIN(MX6DL_PAD_GPIO_8),
+	IMX_PINCTRL_PIN(MX6DL_PAD_GPIO_9),
+	IMX_PINCTRL_PIN(MX6DL_PAD_KEY_COL0),
+	IMX_PINCTRL_PIN(MX6DL_PAD_KEY_COL1),
+	IMX_PINCTRL_PIN(MX6DL_PAD_KEY_COL2),
+	IMX_PINCTRL_PIN(MX6DL_PAD_KEY_COL3),
+	IMX_PINCTRL_PIN(MX6DL_PAD_KEY_COL4),
+	IMX_PINCTRL_PIN(MX6DL_PAD_KEY_ROW0),
+	IMX_PINCTRL_PIN(MX6DL_PAD_KEY_ROW1),
+	IMX_PINCTRL_PIN(MX6DL_PAD_KEY_ROW2),
+	IMX_PINCTRL_PIN(MX6DL_PAD_KEY_ROW3),
+	IMX_PINCTRL_PIN(MX6DL_PAD_KEY_ROW4),
+	IMX_PINCTRL_PIN(MX6DL_PAD_NANDF_ALE),
+	IMX_PINCTRL_PIN(MX6DL_PAD_NANDF_CLE),
+	IMX_PINCTRL_PIN(MX6DL_PAD_NANDF_CS0),
+	IMX_PINCTRL_PIN(MX6DL_PAD_NANDF_CS1),
+	IMX_PINCTRL_PIN(MX6DL_PAD_NANDF_CS2),
+	IMX_PINCTRL_PIN(MX6DL_PAD_NANDF_CS3),
+	IMX_PINCTRL_PIN(MX6DL_PAD_NANDF_D0),
+	IMX_PINCTRL_PIN(MX6DL_PAD_NANDF_D1),
+	IMX_PINCTRL_PIN(MX6DL_PAD_NANDF_D2),
+	IMX_PINCTRL_PIN(MX6DL_PAD_NANDF_D3),
+	IMX_PINCTRL_PIN(MX6DL_PAD_NANDF_D4),
+	IMX_PINCTRL_PIN(MX6DL_PAD_NANDF_D5),
+	IMX_PINCTRL_PIN(MX6DL_PAD_NANDF_D6),
+	IMX_PINCTRL_PIN(MX6DL_PAD_NANDF_D7),
+	IMX_PINCTRL_PIN(MX6DL_PAD_NANDF_RB0),
+	IMX_PINCTRL_PIN(MX6DL_PAD_NANDF_WP_B),
+	IMX_PINCTRL_PIN(MX6DL_PAD_RGMII_RD0),
+	IMX_PINCTRL_PIN(MX6DL_PAD_RGMII_RD1),
+	IMX_PINCTRL_PIN(MX6DL_PAD_RGMII_RD2),
+	IMX_PINCTRL_PIN(MX6DL_PAD_RGMII_RD3),
+	IMX_PINCTRL_PIN(MX6DL_PAD_RGMII_RX_CTL),
+	IMX_PINCTRL_PIN(MX6DL_PAD_RGMII_RXC),
+	IMX_PINCTRL_PIN(MX6DL_PAD_RGMII_TD0),
+	IMX_PINCTRL_PIN(MX6DL_PAD_RGMII_TD1),
+	IMX_PINCTRL_PIN(MX6DL_PAD_RGMII_TD2),
+	IMX_PINCTRL_PIN(MX6DL_PAD_RGMII_TD3),
+	IMX_PINCTRL_PIN(MX6DL_PAD_RGMII_TX_CTL),
+	IMX_PINCTRL_PIN(MX6DL_PAD_RGMII_TXC),
+	IMX_PINCTRL_PIN(MX6DL_PAD_SD1_CLK),
+	IMX_PINCTRL_PIN(MX6DL_PAD_SD1_CMD),
+	IMX_PINCTRL_PIN(MX6DL_PAD_SD1_DAT0),
+	IMX_PINCTRL_PIN(MX6DL_PAD_SD1_DAT1),
+	IMX_PINCTRL_PIN(MX6DL_PAD_SD1_DAT2),
+	IMX_PINCTRL_PIN(MX6DL_PAD_SD1_DAT3),
+	IMX_PINCTRL_PIN(MX6DL_PAD_SD2_CLK),
+	IMX_PINCTRL_PIN(MX6DL_PAD_SD2_CMD),
+	IMX_PINCTRL_PIN(MX6DL_PAD_SD2_DAT0),
+	IMX_PINCTRL_PIN(MX6DL_PAD_SD2_DAT1),
+	IMX_PINCTRL_PIN(MX6DL_PAD_SD2_DAT2),
+	IMX_PINCTRL_PIN(MX6DL_PAD_SD2_DAT3),
+	IMX_PINCTRL_PIN(MX6DL_PAD_SD3_CLK),
+	IMX_PINCTRL_PIN(MX6DL_PAD_SD3_CMD),
+	IMX_PINCTRL_PIN(MX6DL_PAD_SD3_DAT0),
+	IMX_PINCTRL_PIN(MX6DL_PAD_SD3_DAT1),
+	IMX_PINCTRL_PIN(MX6DL_PAD_SD3_DAT2),
+	IMX_PINCTRL_PIN(MX6DL_PAD_SD3_DAT3),
+	IMX_PINCTRL_PIN(MX6DL_PAD_SD3_DAT4),
+	IMX_PINCTRL_PIN(MX6DL_PAD_SD3_DAT5),
+	IMX_PINCTRL_PIN(MX6DL_PAD_SD3_DAT6),
+	IMX_PINCTRL_PIN(MX6DL_PAD_SD3_DAT7),
+	IMX_PINCTRL_PIN(MX6DL_PAD_SD3_RST),
+	IMX_PINCTRL_PIN(MX6DL_PAD_SD4_CLK),
+	IMX_PINCTRL_PIN(MX6DL_PAD_SD4_CMD),
+	IMX_PINCTRL_PIN(MX6DL_PAD_SD4_DAT0),
+	IMX_PINCTRL_PIN(MX6DL_PAD_SD4_DAT1),
+	IMX_PINCTRL_PIN(MX6DL_PAD_SD4_DAT2),
+	IMX_PINCTRL_PIN(MX6DL_PAD_SD4_DAT3),
+	IMX_PINCTRL_PIN(MX6DL_PAD_SD4_DAT4),
+	IMX_PINCTRL_PIN(MX6DL_PAD_SD4_DAT5),
+	IMX_PINCTRL_PIN(MX6DL_PAD_SD4_DAT6),
+	IMX_PINCTRL_PIN(MX6DL_PAD_SD4_DAT7),
+};
+
+static struct imx_pinctrl_soc_info imx6dl_pinctrl_info = {
+	.pins = imx6dl_pinctrl_pads,
+	.npins = ARRAY_SIZE(imx6dl_pinctrl_pads),
+};
+
+static struct of_device_id imx6dl_pinctrl_of_match[] = {
+	{ .compatible = "fsl,imx6dl-iomuxc", },
+	{ /* sentinel */ }
+};
+
+static int imx6dl_pinctrl_probe(struct platform_device *pdev)
+{
+	return imx_pinctrl_probe(pdev, &imx6dl_pinctrl_info);
+}
+
+static struct platform_driver imx6dl_pinctrl_driver = {
+	.driver = {
+		.name = "imx6dl-pinctrl",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(imx6dl_pinctrl_of_match),
+	},
+	.probe = imx6dl_pinctrl_probe,
+	.remove = imx_pinctrl_remove,
+};
+
+static int __init imx6dl_pinctrl_init(void)
+{
+	return platform_driver_register(&imx6dl_pinctrl_driver);
+}
+arch_initcall(imx6dl_pinctrl_init);
+
+static void __exit imx6dl_pinctrl_exit(void)
+{
+	platform_driver_unregister(&imx6dl_pinctrl_driver);
+}
+module_exit(imx6dl_pinctrl_exit);
+
+MODULE_AUTHOR("Shawn Guo <shawn.guo@linaro.org>");
+MODULE_DESCRIPTION("Freescale imx6dl pinctrl driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/pinctrl-imx6q.c b/drivers/pinctrl/pinctrl-imx6q.c
index 663346b..74ea946 100644
--- a/drivers/pinctrl/pinctrl-imx6q.c
+++ b/drivers/pinctrl/pinctrl-imx6q.c
@@ -23,1935 +23,256 @@
 #include "pinctrl-imx.h"
 
 enum imx6q_pads {
-	MX6Q_PAD_SD2_DAT1 = 0,
-	MX6Q_PAD_SD2_DAT2 = 1,
-	MX6Q_PAD_SD2_DAT0 = 2,
-	MX6Q_PAD_RGMII_TXC = 3,
-	MX6Q_PAD_RGMII_TD0 = 4,
-	MX6Q_PAD_RGMII_TD1 = 5,
-	MX6Q_PAD_RGMII_TD2 = 6,
-	MX6Q_PAD_RGMII_TD3 = 7,
-	MX6Q_PAD_RGMII_RX_CTL = 8,
-	MX6Q_PAD_RGMII_RD0 = 9,
-	MX6Q_PAD_RGMII_TX_CTL = 10,
-	MX6Q_PAD_RGMII_RD1 = 11,
-	MX6Q_PAD_RGMII_RD2 = 12,
-	MX6Q_PAD_RGMII_RD3 = 13,
-	MX6Q_PAD_RGMII_RXC = 14,
-	MX6Q_PAD_EIM_A25 = 15,
-	MX6Q_PAD_EIM_EB2 = 16,
-	MX6Q_PAD_EIM_D16 = 17,
-	MX6Q_PAD_EIM_D17 = 18,
-	MX6Q_PAD_EIM_D18 = 19,
-	MX6Q_PAD_EIM_D19 = 20,
-	MX6Q_PAD_EIM_D20 = 21,
-	MX6Q_PAD_EIM_D21 = 22,
-	MX6Q_PAD_EIM_D22 = 23,
-	MX6Q_PAD_EIM_D23 = 24,
-	MX6Q_PAD_EIM_EB3 = 25,
-	MX6Q_PAD_EIM_D24 = 26,
-	MX6Q_PAD_EIM_D25 = 27,
-	MX6Q_PAD_EIM_D26 = 28,
-	MX6Q_PAD_EIM_D27 = 29,
-	MX6Q_PAD_EIM_D28 = 30,
-	MX6Q_PAD_EIM_D29 = 31,
-	MX6Q_PAD_EIM_D30 = 32,
-	MX6Q_PAD_EIM_D31 = 33,
-	MX6Q_PAD_EIM_A24 = 34,
-	MX6Q_PAD_EIM_A23 = 35,
-	MX6Q_PAD_EIM_A22 = 36,
-	MX6Q_PAD_EIM_A21 = 37,
-	MX6Q_PAD_EIM_A20 = 38,
-	MX6Q_PAD_EIM_A19 = 39,
-	MX6Q_PAD_EIM_A18 = 40,
-	MX6Q_PAD_EIM_A17 = 41,
-	MX6Q_PAD_EIM_A16 = 42,
-	MX6Q_PAD_EIM_CS0 = 43,
-	MX6Q_PAD_EIM_CS1 = 44,
-	MX6Q_PAD_EIM_OE = 45,
-	MX6Q_PAD_EIM_RW = 46,
-	MX6Q_PAD_EIM_LBA = 47,
-	MX6Q_PAD_EIM_EB0 = 48,
-	MX6Q_PAD_EIM_EB1 = 49,
-	MX6Q_PAD_EIM_DA0 = 50,
-	MX6Q_PAD_EIM_DA1 = 51,
-	MX6Q_PAD_EIM_DA2 = 52,
-	MX6Q_PAD_EIM_DA3 = 53,
-	MX6Q_PAD_EIM_DA4 = 54,
-	MX6Q_PAD_EIM_DA5 = 55,
-	MX6Q_PAD_EIM_DA6 = 56,
-	MX6Q_PAD_EIM_DA7 = 57,
-	MX6Q_PAD_EIM_DA8 = 58,
-	MX6Q_PAD_EIM_DA9 = 59,
-	MX6Q_PAD_EIM_DA10 = 60,
-	MX6Q_PAD_EIM_DA11 = 61,
-	MX6Q_PAD_EIM_DA12 = 62,
-	MX6Q_PAD_EIM_DA13 = 63,
-	MX6Q_PAD_EIM_DA14 = 64,
-	MX6Q_PAD_EIM_DA15 = 65,
-	MX6Q_PAD_EIM_WAIT = 66,
-	MX6Q_PAD_EIM_BCLK = 67,
-	MX6Q_PAD_DI0_DISP_CLK = 68,
-	MX6Q_PAD_DI0_PIN15 = 69,
-	MX6Q_PAD_DI0_PIN2 = 70,
-	MX6Q_PAD_DI0_PIN3 = 71,
-	MX6Q_PAD_DI0_PIN4 = 72,
-	MX6Q_PAD_DISP0_DAT0 = 73,
-	MX6Q_PAD_DISP0_DAT1 = 74,
-	MX6Q_PAD_DISP0_DAT2 = 75,
-	MX6Q_PAD_DISP0_DAT3 = 76,
-	MX6Q_PAD_DISP0_DAT4 = 77,
-	MX6Q_PAD_DISP0_DAT5 = 78,
-	MX6Q_PAD_DISP0_DAT6 = 79,
-	MX6Q_PAD_DISP0_DAT7 = 80,
-	MX6Q_PAD_DISP0_DAT8 = 81,
-	MX6Q_PAD_DISP0_DAT9 = 82,
-	MX6Q_PAD_DISP0_DAT10 = 83,
-	MX6Q_PAD_DISP0_DAT11 = 84,
-	MX6Q_PAD_DISP0_DAT12 = 85,
-	MX6Q_PAD_DISP0_DAT13 = 86,
-	MX6Q_PAD_DISP0_DAT14 = 87,
-	MX6Q_PAD_DISP0_DAT15 = 88,
-	MX6Q_PAD_DISP0_DAT16 = 89,
-	MX6Q_PAD_DISP0_DAT17 = 90,
-	MX6Q_PAD_DISP0_DAT18 = 91,
-	MX6Q_PAD_DISP0_DAT19 = 92,
-	MX6Q_PAD_DISP0_DAT20 = 93,
-	MX6Q_PAD_DISP0_DAT21 = 94,
-	MX6Q_PAD_DISP0_DAT22 = 95,
-	MX6Q_PAD_DISP0_DAT23 = 96,
-	MX6Q_PAD_ENET_MDIO = 97,
-	MX6Q_PAD_ENET_REF_CLK = 98,
-	MX6Q_PAD_ENET_RX_ER = 99,
-	MX6Q_PAD_ENET_CRS_DV = 100,
-	MX6Q_PAD_ENET_RXD1 = 101,
-	MX6Q_PAD_ENET_RXD0 = 102,
-	MX6Q_PAD_ENET_TX_EN = 103,
-	MX6Q_PAD_ENET_TXD1 = 104,
-	MX6Q_PAD_ENET_TXD0 = 105,
-	MX6Q_PAD_ENET_MDC = 106,
-	MX6Q_PAD_DRAM_D40 = 107,
-	MX6Q_PAD_DRAM_D41 = 108,
-	MX6Q_PAD_DRAM_D42 = 109,
-	MX6Q_PAD_DRAM_D43 = 110,
-	MX6Q_PAD_DRAM_D44 = 111,
-	MX6Q_PAD_DRAM_D45 = 112,
-	MX6Q_PAD_DRAM_D46 = 113,
-	MX6Q_PAD_DRAM_D47 = 114,
-	MX6Q_PAD_DRAM_SDQS5 = 115,
-	MX6Q_PAD_DRAM_DQM5 = 116,
-	MX6Q_PAD_DRAM_D32 = 117,
-	MX6Q_PAD_DRAM_D33 = 118,
-	MX6Q_PAD_DRAM_D34 = 119,
-	MX6Q_PAD_DRAM_D35 = 120,
-	MX6Q_PAD_DRAM_D36 = 121,
-	MX6Q_PAD_DRAM_D37 = 122,
-	MX6Q_PAD_DRAM_D38 = 123,
-	MX6Q_PAD_DRAM_D39 = 124,
-	MX6Q_PAD_DRAM_DQM4 = 125,
-	MX6Q_PAD_DRAM_SDQS4 = 126,
-	MX6Q_PAD_DRAM_D24 = 127,
-	MX6Q_PAD_DRAM_D25 = 128,
-	MX6Q_PAD_DRAM_D26 = 129,
-	MX6Q_PAD_DRAM_D27 = 130,
-	MX6Q_PAD_DRAM_D28 = 131,
-	MX6Q_PAD_DRAM_D29 = 132,
-	MX6Q_PAD_DRAM_SDQS3 = 133,
-	MX6Q_PAD_DRAM_D30 = 134,
-	MX6Q_PAD_DRAM_D31 = 135,
-	MX6Q_PAD_DRAM_DQM3 = 136,
-	MX6Q_PAD_DRAM_D16 = 137,
-	MX6Q_PAD_DRAM_D17 = 138,
-	MX6Q_PAD_DRAM_D18 = 139,
-	MX6Q_PAD_DRAM_D19 = 140,
-	MX6Q_PAD_DRAM_D20 = 141,
-	MX6Q_PAD_DRAM_D21 = 142,
-	MX6Q_PAD_DRAM_D22 = 143,
-	MX6Q_PAD_DRAM_SDQS2 = 144,
-	MX6Q_PAD_DRAM_D23 = 145,
-	MX6Q_PAD_DRAM_DQM2 = 146,
-	MX6Q_PAD_DRAM_A0 = 147,
-	MX6Q_PAD_DRAM_A1 = 148,
-	MX6Q_PAD_DRAM_A2 = 149,
-	MX6Q_PAD_DRAM_A3 = 150,
-	MX6Q_PAD_DRAM_A4 = 151,
-	MX6Q_PAD_DRAM_A5 = 152,
-	MX6Q_PAD_DRAM_A6 = 153,
-	MX6Q_PAD_DRAM_A7 = 154,
-	MX6Q_PAD_DRAM_A8 = 155,
-	MX6Q_PAD_DRAM_A9 = 156,
-	MX6Q_PAD_DRAM_A10 = 157,
-	MX6Q_PAD_DRAM_A11 = 158,
-	MX6Q_PAD_DRAM_A12 = 159,
-	MX6Q_PAD_DRAM_A13 = 160,
-	MX6Q_PAD_DRAM_A14 = 161,
-	MX6Q_PAD_DRAM_A15 = 162,
-	MX6Q_PAD_DRAM_CAS = 163,
-	MX6Q_PAD_DRAM_CS0 = 164,
-	MX6Q_PAD_DRAM_CS1 = 165,
-	MX6Q_PAD_DRAM_RAS = 166,
-	MX6Q_PAD_DRAM_RESET = 167,
-	MX6Q_PAD_DRAM_SDBA0 = 168,
-	MX6Q_PAD_DRAM_SDBA1 = 169,
-	MX6Q_PAD_DRAM_SDCLK_0 = 170,
-	MX6Q_PAD_DRAM_SDBA2 = 171,
-	MX6Q_PAD_DRAM_SDCKE0 = 172,
-	MX6Q_PAD_DRAM_SDCLK_1 = 173,
-	MX6Q_PAD_DRAM_SDCKE1 = 174,
-	MX6Q_PAD_DRAM_SDODT0 = 175,
-	MX6Q_PAD_DRAM_SDODT1 = 176,
-	MX6Q_PAD_DRAM_SDWE = 177,
-	MX6Q_PAD_DRAM_D0 = 178,
-	MX6Q_PAD_DRAM_D1 = 179,
-	MX6Q_PAD_DRAM_D2 = 180,
-	MX6Q_PAD_DRAM_D3 = 181,
-	MX6Q_PAD_DRAM_D4 = 182,
-	MX6Q_PAD_DRAM_D5 = 183,
-	MX6Q_PAD_DRAM_SDQS0 = 184,
-	MX6Q_PAD_DRAM_D6 = 185,
-	MX6Q_PAD_DRAM_D7 = 186,
-	MX6Q_PAD_DRAM_DQM0 = 187,
-	MX6Q_PAD_DRAM_D8 = 188,
-	MX6Q_PAD_DRAM_D9 = 189,
-	MX6Q_PAD_DRAM_D10 = 190,
-	MX6Q_PAD_DRAM_D11 = 191,
-	MX6Q_PAD_DRAM_D12 = 192,
-	MX6Q_PAD_DRAM_D13 = 193,
-	MX6Q_PAD_DRAM_D14 = 194,
-	MX6Q_PAD_DRAM_SDQS1 = 195,
-	MX6Q_PAD_DRAM_D15 = 196,
-	MX6Q_PAD_DRAM_DQM1 = 197,
-	MX6Q_PAD_DRAM_D48 = 198,
-	MX6Q_PAD_DRAM_D49 = 199,
-	MX6Q_PAD_DRAM_D50 = 200,
-	MX6Q_PAD_DRAM_D51 = 201,
-	MX6Q_PAD_DRAM_D52 = 202,
-	MX6Q_PAD_DRAM_D53 = 203,
-	MX6Q_PAD_DRAM_D54 = 204,
-	MX6Q_PAD_DRAM_D55 = 205,
-	MX6Q_PAD_DRAM_SDQS6 = 206,
-	MX6Q_PAD_DRAM_DQM6 = 207,
-	MX6Q_PAD_DRAM_D56 = 208,
-	MX6Q_PAD_DRAM_SDQS7 = 209,
-	MX6Q_PAD_DRAM_D57 = 210,
-	MX6Q_PAD_DRAM_D58 = 211,
-	MX6Q_PAD_DRAM_D59 = 212,
-	MX6Q_PAD_DRAM_D60 = 213,
-	MX6Q_PAD_DRAM_DQM7 = 214,
-	MX6Q_PAD_DRAM_D61 = 215,
-	MX6Q_PAD_DRAM_D62 = 216,
-	MX6Q_PAD_DRAM_D63 = 217,
-	MX6Q_PAD_KEY_COL0 = 218,
-	MX6Q_PAD_KEY_ROW0 = 219,
-	MX6Q_PAD_KEY_COL1 = 220,
-	MX6Q_PAD_KEY_ROW1 = 221,
-	MX6Q_PAD_KEY_COL2 = 222,
-	MX6Q_PAD_KEY_ROW2 = 223,
-	MX6Q_PAD_KEY_COL3 = 224,
-	MX6Q_PAD_KEY_ROW3 = 225,
-	MX6Q_PAD_KEY_COL4 = 226,
-	MX6Q_PAD_KEY_ROW4 = 227,
-	MX6Q_PAD_GPIO_0 = 228,
-	MX6Q_PAD_GPIO_1 = 229,
-	MX6Q_PAD_GPIO_9 = 230,
-	MX6Q_PAD_GPIO_3 = 231,
-	MX6Q_PAD_GPIO_6 = 232,
-	MX6Q_PAD_GPIO_2 = 233,
-	MX6Q_PAD_GPIO_4 = 234,
-	MX6Q_PAD_GPIO_5 = 235,
-	MX6Q_PAD_GPIO_7 = 236,
-	MX6Q_PAD_GPIO_8 = 237,
-	MX6Q_PAD_GPIO_16 = 238,
-	MX6Q_PAD_GPIO_17 = 239,
-	MX6Q_PAD_GPIO_18 = 240,
-	MX6Q_PAD_GPIO_19 = 241,
-	MX6Q_PAD_CSI0_PIXCLK = 242,
-	MX6Q_PAD_CSI0_MCLK = 243,
-	MX6Q_PAD_CSI0_DATA_EN = 244,
-	MX6Q_PAD_CSI0_VSYNC = 245,
-	MX6Q_PAD_CSI0_DAT4 = 246,
-	MX6Q_PAD_CSI0_DAT5 = 247,
-	MX6Q_PAD_CSI0_DAT6 = 248,
-	MX6Q_PAD_CSI0_DAT7 = 249,
-	MX6Q_PAD_CSI0_DAT8 = 250,
-	MX6Q_PAD_CSI0_DAT9 = 251,
-	MX6Q_PAD_CSI0_DAT10 = 252,
-	MX6Q_PAD_CSI0_DAT11 = 253,
-	MX6Q_PAD_CSI0_DAT12 = 254,
-	MX6Q_PAD_CSI0_DAT13 = 255,
-	MX6Q_PAD_CSI0_DAT14 = 256,
-	MX6Q_PAD_CSI0_DAT15 = 257,
-	MX6Q_PAD_CSI0_DAT16 = 258,
-	MX6Q_PAD_CSI0_DAT17 = 259,
-	MX6Q_PAD_CSI0_DAT18 = 260,
-	MX6Q_PAD_CSI0_DAT19 = 261,
-	MX6Q_PAD_JTAG_TMS = 262,
-	MX6Q_PAD_JTAG_MOD = 263,
-	MX6Q_PAD_JTAG_TRSTB = 264,
-	MX6Q_PAD_JTAG_TDI = 265,
-	MX6Q_PAD_JTAG_TCK = 266,
-	MX6Q_PAD_JTAG_TDO = 267,
-	MX6Q_PAD_LVDS1_TX3_P = 268,
-	MX6Q_PAD_LVDS1_TX2_P = 269,
-	MX6Q_PAD_LVDS1_CLK_P = 270,
-	MX6Q_PAD_LVDS1_TX1_P = 271,
-	MX6Q_PAD_LVDS1_TX0_P = 272,
-	MX6Q_PAD_LVDS0_TX3_P = 273,
-	MX6Q_PAD_LVDS0_CLK_P = 274,
-	MX6Q_PAD_LVDS0_TX2_P = 275,
-	MX6Q_PAD_LVDS0_TX1_P = 276,
-	MX6Q_PAD_LVDS0_TX0_P = 277,
-	MX6Q_PAD_TAMPER = 278,
-	MX6Q_PAD_PMIC_ON_REQ = 279,
-	MX6Q_PAD_PMIC_STBY_REQ = 280,
-	MX6Q_PAD_POR_B = 281,
-	MX6Q_PAD_BOOT_MODE1 = 282,
-	MX6Q_PAD_RESET_IN_B = 283,
-	MX6Q_PAD_BOOT_MODE0 = 284,
-	MX6Q_PAD_TEST_MODE = 285,
-	MX6Q_PAD_SD3_DAT7 = 286,
-	MX6Q_PAD_SD3_DAT6 = 287,
-	MX6Q_PAD_SD3_DAT5 = 288,
-	MX6Q_PAD_SD3_DAT4 = 289,
-	MX6Q_PAD_SD3_CMD = 290,
-	MX6Q_PAD_SD3_CLK = 291,
-	MX6Q_PAD_SD3_DAT0 = 292,
-	MX6Q_PAD_SD3_DAT1 = 293,
-	MX6Q_PAD_SD3_DAT2 = 294,
-	MX6Q_PAD_SD3_DAT3 = 295,
-	MX6Q_PAD_SD3_RST = 296,
-	MX6Q_PAD_NANDF_CLE = 297,
-	MX6Q_PAD_NANDF_ALE = 298,
-	MX6Q_PAD_NANDF_WP_B = 299,
-	MX6Q_PAD_NANDF_RB0 = 300,
-	MX6Q_PAD_NANDF_CS0 = 301,
-	MX6Q_PAD_NANDF_CS1 = 302,
-	MX6Q_PAD_NANDF_CS2 = 303,
-	MX6Q_PAD_NANDF_CS3 = 304,
-	MX6Q_PAD_SD4_CMD = 305,
-	MX6Q_PAD_SD4_CLK = 306,
-	MX6Q_PAD_NANDF_D0 = 307,
-	MX6Q_PAD_NANDF_D1 = 308,
-	MX6Q_PAD_NANDF_D2 = 309,
-	MX6Q_PAD_NANDF_D3 = 310,
-	MX6Q_PAD_NANDF_D4 = 311,
-	MX6Q_PAD_NANDF_D5 = 312,
-	MX6Q_PAD_NANDF_D6 = 313,
-	MX6Q_PAD_NANDF_D7 = 314,
-	MX6Q_PAD_SD4_DAT0 = 315,
-	MX6Q_PAD_SD4_DAT1 = 316,
-	MX6Q_PAD_SD4_DAT2 = 317,
-	MX6Q_PAD_SD4_DAT3 = 318,
-	MX6Q_PAD_SD4_DAT4 = 319,
-	MX6Q_PAD_SD4_DAT5 = 320,
-	MX6Q_PAD_SD4_DAT6 = 321,
-	MX6Q_PAD_SD4_DAT7 = 322,
-	MX6Q_PAD_SD1_DAT1 = 323,
-	MX6Q_PAD_SD1_DAT0 = 324,
-	MX6Q_PAD_SD1_DAT3 = 325,
-	MX6Q_PAD_SD1_CMD = 326,
-	MX6Q_PAD_SD1_DAT2 = 327,
-	MX6Q_PAD_SD1_CLK = 328,
-	MX6Q_PAD_SD2_CLK = 329,
-	MX6Q_PAD_SD2_CMD = 330,
-	MX6Q_PAD_SD2_DAT3 = 331,
-};
-
-/* imx6q register maps */
-static struct imx_pin_reg imx6q_pin_regs[] = {
-	IMX_PIN_REG(MX6Q_PAD_SD2_DAT1, 0x0360, 0x004C, 0, 0x0000, 0), /* MX6Q_PAD_SD2_DAT1__USDHC2_DAT1 */
-	IMX_PIN_REG(MX6Q_PAD_SD2_DAT1, 0x0360, 0x004C, 1, 0x0834, 0), /* MX6Q_PAD_SD2_DAT1__ECSPI5_SS0 */
-	IMX_PIN_REG(MX6Q_PAD_SD2_DAT1, 0x0360, 0x004C, 2, 0x0000, 0), /* MX6Q_PAD_SD2_DAT1__WEIM_WEIM_CS_2 */
-	IMX_PIN_REG(MX6Q_PAD_SD2_DAT1, 0x0360, 0x004C, 3, 0x07C8, 0), /* MX6Q_PAD_SD2_DAT1__AUDMUX_AUD4_TXFS */
-	IMX_PIN_REG(MX6Q_PAD_SD2_DAT1, 0x0360, 0x004C, 4, 0x08F0, 0), /* MX6Q_PAD_SD2_DAT1__KPP_COL_7 */
-	IMX_PIN_REG(MX6Q_PAD_SD2_DAT1, 0x0360, 0x004C, 5, 0x0000, 0), /* MX6Q_PAD_SD2_DAT1__GPIO_1_14 */
-	IMX_PIN_REG(MX6Q_PAD_SD2_DAT1, 0x0360, 0x004C, 6, 0x0000, 0), /* MX6Q_PAD_SD2_DAT1__CCM_WAIT */
-	IMX_PIN_REG(MX6Q_PAD_SD2_DAT1, 0x0360, 0x004C, 7, 0x0000, 0), /* MX6Q_PAD_SD2_DAT1__ANATOP_TESTO_0 */
-	IMX_PIN_REG(MX6Q_PAD_SD2_DAT2, 0x0364, 0x0050, 0, 0x0000, 0), /* MX6Q_PAD_SD2_DAT2__USDHC2_DAT2 */
-	IMX_PIN_REG(MX6Q_PAD_SD2_DAT2, 0x0364, 0x0050, 1, 0x0838, 0), /* MX6Q_PAD_SD2_DAT2__ECSPI5_SS1 */
-	IMX_PIN_REG(MX6Q_PAD_SD2_DAT2, 0x0364, 0x0050, 2, 0x0000, 0), /* MX6Q_PAD_SD2_DAT2__WEIM_WEIM_CS_3 */
-	IMX_PIN_REG(MX6Q_PAD_SD2_DAT2, 0x0364, 0x0050, 3, 0x07B8, 0), /* MX6Q_PAD_SD2_DAT2__AUDMUX_AUD4_TXD */
-	IMX_PIN_REG(MX6Q_PAD_SD2_DAT2, 0x0364, 0x0050, 4, 0x08F8, 0), /* MX6Q_PAD_SD2_DAT2__KPP_ROW_6 */
-	IMX_PIN_REG(MX6Q_PAD_SD2_DAT2, 0x0364, 0x0050, 5, 0x0000, 0), /* MX6Q_PAD_SD2_DAT2__GPIO_1_13 */
-	IMX_PIN_REG(MX6Q_PAD_SD2_DAT2, 0x0364, 0x0050, 6, 0x0000, 0), /* MX6Q_PAD_SD2_DAT2__CCM_STOP */
-	IMX_PIN_REG(MX6Q_PAD_SD2_DAT2, 0x0364, 0x0050, 7, 0x0000, 0), /* MX6Q_PAD_SD2_DAT2__ANATOP_TESTO_1 */
-	IMX_PIN_REG(MX6Q_PAD_SD2_DAT0, 0x0368, 0x0054, 0, 0x0000, 0), /* MX6Q_PAD_SD2_DAT0__USDHC2_DAT0 */
-	IMX_PIN_REG(MX6Q_PAD_SD2_DAT0, 0x0368, 0x0054, 1, 0x082C, 0), /* MX6Q_PAD_SD2_DAT0__ECSPI5_MISO */
-	IMX_PIN_REG(MX6Q_PAD_SD2_DAT0, 0x0368, 0x0054, 3, 0x07B4, 0), /* MX6Q_PAD_SD2_DAT0__AUDMUX_AUD4_RXD */
-	IMX_PIN_REG(MX6Q_PAD_SD2_DAT0, 0x0368, 0x0054, 4, 0x08FC, 0), /* MX6Q_PAD_SD2_DAT0__KPP_ROW_7 */
-	IMX_PIN_REG(MX6Q_PAD_SD2_DAT0, 0x0368, 0x0054, 5, 0x0000, 0), /* MX6Q_PAD_SD2_DAT0__GPIO_1_15 */
-	IMX_PIN_REG(MX6Q_PAD_SD2_DAT0, 0x0368, 0x0054, 6, 0x0000, 0), /* MX6Q_PAD_SD2_DAT0__DCIC2_DCIC_OUT */
-	IMX_PIN_REG(MX6Q_PAD_SD2_DAT0, 0x0368, 0x0054, 7, 0x0000, 0), /* MX6Q_PAD_SD2_DAT0__TESTO_2 */
-	IMX_PIN_REG(MX6Q_PAD_RGMII_TXC, 0x036C, 0x0058, 0, 0x0000, 0), /* MX6Q_PAD_RGMII_TXC__USBOH3_H2_DATA */
-	IMX_PIN_REG(MX6Q_PAD_RGMII_TXC, 0x036C, 0x0058, 1, 0x0000, 0), /* MX6Q_PAD_RGMII_TXC__ENET_RGMII_TXC */
-	IMX_PIN_REG(MX6Q_PAD_RGMII_TXC, 0x036C, 0x0058, 2, 0x0918, 0), /* MX6Q_PAD_RGMII_TXC__SPDIF_SPDIF_EXTCLK */
-	IMX_PIN_REG(MX6Q_PAD_RGMII_TXC, 0x036C, 0x0058, 5, 0x0000, 0), /* MX6Q_PAD_RGMII_TXC__GPIO_6_19 */
-	IMX_PIN_REG(MX6Q_PAD_RGMII_TXC, 0x036C, 0x0058, 6, 0x0000, 0), /* MX6Q_PAD_RGMII_TXC__MIPI_CORE_DPHY_IN_0 */
-	IMX_PIN_REG(MX6Q_PAD_RGMII_TXC, 0x036C, 0x0058, 7, 0x0000, 0), /* MX6Q_PAD_RGMII_TXC__ANATOP_24M_OUT */
-	IMX_PIN_REG(MX6Q_PAD_RGMII_TD0, 0x0370, 0x005C, 0, 0x0000, 0), /* MX6Q_PAD_RGMII_TD0__MIPI_HSI_CRL_TX_RDY */
-	IMX_PIN_REG(MX6Q_PAD_RGMII_TD0, 0x0370, 0x005C, 1, 0x0000, 0), /* MX6Q_PAD_RGMII_TD0__ENET_RGMII_TD0 */
-	IMX_PIN_REG(MX6Q_PAD_RGMII_TD0, 0x0370, 0x005C, 5, 0x0000, 0), /* MX6Q_PAD_RGMII_TD0__GPIO_6_20 */
-	IMX_PIN_REG(MX6Q_PAD_RGMII_TD0, 0x0370, 0x005C, 6, 0x0000, 0), /* MX6Q_PAD_RGMII_TD0__MIPI_CORE_DPHY_IN_1 */
-	IMX_PIN_REG(MX6Q_PAD_RGMII_TD1, 0x0374, 0x0060, 0, 0x0000, 0), /* MX6Q_PAD_RGMII_TD1__MIPI_HSI_CRL_RX_FLG */
-	IMX_PIN_REG(MX6Q_PAD_RGMII_TD1, 0x0374, 0x0060, 1, 0x0000, 0), /* MX6Q_PAD_RGMII_TD1__ENET_RGMII_TD1 */
-	IMX_PIN_REG(MX6Q_PAD_RGMII_TD1, 0x0374, 0x0060, 5, 0x0000, 0), /* MX6Q_PAD_RGMII_TD1__GPIO_6_21 */
-	IMX_PIN_REG(MX6Q_PAD_RGMII_TD1, 0x0374, 0x0060, 6, 0x0000, 0), /* MX6Q_PAD_RGMII_TD1__MIPI_CORE_DPHY_IN_2 */
-	IMX_PIN_REG(MX6Q_PAD_RGMII_TD1, 0x0374, 0x0060, 7, 0x0000, 0), /* MX6Q_PAD_RGMII_TD1__CCM_PLL3_BYP */
-	IMX_PIN_REG(MX6Q_PAD_RGMII_TD2, 0x0378, 0x0064, 0, 0x0000, 0), /* MX6Q_PAD_RGMII_TD2__MIPI_HSI_CRL_RX_DTA */
-	IMX_PIN_REG(MX6Q_PAD_RGMII_TD2, 0x0378, 0x0064, 1, 0x0000, 0), /* MX6Q_PAD_RGMII_TD2__ENET_RGMII_TD2 */
-	IMX_PIN_REG(MX6Q_PAD_RGMII_TD2, 0x0378, 0x0064, 5, 0x0000, 0), /* MX6Q_PAD_RGMII_TD2__GPIO_6_22 */
-	IMX_PIN_REG(MX6Q_PAD_RGMII_TD2, 0x0378, 0x0064, 6, 0x0000, 0), /* MX6Q_PAD_RGMII_TD2__MIPI_CORE_DPHY_IN_3 */
-	IMX_PIN_REG(MX6Q_PAD_RGMII_TD2, 0x0378, 0x0064, 7, 0x0000, 0), /* MX6Q_PAD_RGMII_TD2__CCM_PLL2_BYP */
-	IMX_PIN_REG(MX6Q_PAD_RGMII_TD3, 0x037C, 0x0068, 0, 0x0000, 0), /* MX6Q_PAD_RGMII_TD3__MIPI_HSI_CRL_RX_WAK */
-	IMX_PIN_REG(MX6Q_PAD_RGMII_TD3, 0x037C, 0x0068, 1, 0x0000, 0), /* MX6Q_PAD_RGMII_TD3__ENET_RGMII_TD3 */
-	IMX_PIN_REG(MX6Q_PAD_RGMII_TD3, 0x037C, 0x0068, 5, 0x0000, 0), /* MX6Q_PAD_RGMII_TD3__GPIO_6_23 */
-	IMX_PIN_REG(MX6Q_PAD_RGMII_TD3, 0x037C, 0x0068, 6, 0x0000, 0), /* MX6Q_PAD_RGMII_TD3__MIPI_CORE_DPHY_IN_4 */
-	IMX_PIN_REG(MX6Q_PAD_RGMII_RX_CTL, 0x0380, 0x006C, 0, 0x0000, 0), /* MX6Q_PAD_RGMII_RX_CTL__USBOH3_H3_DATA */
-	IMX_PIN_REG(MX6Q_PAD_RGMII_RX_CTL, 0x0380, 0x006C, 1, 0x0858, 0), /* MX6Q_PAD_RGMII_RX_CTL__RGMII_RX_CTL */
-	IMX_PIN_REG(MX6Q_PAD_RGMII_RX_CTL, 0x0380, 0x006C, 5, 0x0000, 0), /* MX6Q_PAD_RGMII_RX_CTL__GPIO_6_24 */
-	IMX_PIN_REG(MX6Q_PAD_RGMII_RX_CTL, 0x0380, 0x006C, 6, 0x0000, 0), /* MX6Q_PAD_RGMII_RX_CTL__MIPI_DPHY_IN_5 */
-	IMX_PIN_REG(MX6Q_PAD_RGMII_RD0, 0x0384, 0x0070, 0, 0x0000, 0), /* MX6Q_PAD_RGMII_RD0__MIPI_HSI_CRL_RX_RDY */
-	IMX_PIN_REG(MX6Q_PAD_RGMII_RD0, 0x0384, 0x0070, 1, 0x0848, 0), /* MX6Q_PAD_RGMII_RD0__ENET_RGMII_RD0 */
-	IMX_PIN_REG(MX6Q_PAD_RGMII_RD0, 0x0384, 0x0070, 5, 0x0000, 0), /* MX6Q_PAD_RGMII_RD0__GPIO_6_25 */
-	IMX_PIN_REG(MX6Q_PAD_RGMII_RD0, 0x0384, 0x0070, 6, 0x0000, 0), /* MX6Q_PAD_RGMII_RD0__MIPI_CORE_DPHY_IN_6 */
-	IMX_PIN_REG(MX6Q_PAD_RGMII_TX_CTL, 0x0388, 0x0074, 0, 0x0000, 0), /* MX6Q_PAD_RGMII_TX_CTL__USBOH3_H2_STROBE */
-	IMX_PIN_REG(MX6Q_PAD_RGMII_TX_CTL, 0x0388, 0x0074, 1, 0x0000, 0), /* MX6Q_PAD_RGMII_TX_CTL__RGMII_TX_CTL */
-	IMX_PIN_REG(MX6Q_PAD_RGMII_TX_CTL, 0x0388, 0x0074, 5, 0x0000, 0), /* MX6Q_PAD_RGMII_TX_CTL__GPIO_6_26 */
-	IMX_PIN_REG(MX6Q_PAD_RGMII_TX_CTL, 0x0388, 0x0074, 6, 0x0000, 0), /* MX6Q_PAD_RGMII_TX_CTL__CORE_DPHY_IN_7 */
-	IMX_PIN_REG(MX6Q_PAD_RGMII_TX_CTL, 0x0388, 0x0074, 7, 0x083C, 0), /* MX6Q_PAD_RGMII_TX_CTL__ANATOP_REF_OUT */
-	IMX_PIN_REG(MX6Q_PAD_RGMII_RD1, 0x038C, 0x0078, 0, 0x0000, 0), /* MX6Q_PAD_RGMII_RD1__MIPI_HSI_CTRL_TX_FL */
-	IMX_PIN_REG(MX6Q_PAD_RGMII_RD1, 0x038C, 0x0078, 1, 0x084C, 0), /* MX6Q_PAD_RGMII_RD1__ENET_RGMII_RD1 */
-	IMX_PIN_REG(MX6Q_PAD_RGMII_RD1, 0x038C, 0x0078, 5, 0x0000, 0), /* MX6Q_PAD_RGMII_RD1__GPIO_6_27 */
-	IMX_PIN_REG(MX6Q_PAD_RGMII_RD1, 0x038C, 0x0078, 6, 0x0000, 0), /* MX6Q_PAD_RGMII_RD1__CORE_DPHY_TEST_IN_8 */
-	IMX_PIN_REG(MX6Q_PAD_RGMII_RD1, 0x038C, 0x0078, 7, 0x0000, 0), /* MX6Q_PAD_RGMII_RD1__SJC_FAIL */
-	IMX_PIN_REG(MX6Q_PAD_RGMII_RD2, 0x0390, 0x007C, 0, 0x0000, 0), /* MX6Q_PAD_RGMII_RD2__MIPI_HSI_CRL_TX_DTA */
-	IMX_PIN_REG(MX6Q_PAD_RGMII_RD2, 0x0390, 0x007C, 1, 0x0850, 0), /* MX6Q_PAD_RGMII_RD2__ENET_RGMII_RD2 */
-	IMX_PIN_REG(MX6Q_PAD_RGMII_RD2, 0x0390, 0x007C, 5, 0x0000, 0), /* MX6Q_PAD_RGMII_RD2__GPIO_6_28 */
-	IMX_PIN_REG(MX6Q_PAD_RGMII_RD2, 0x0390, 0x007C, 6, 0x0000, 0), /* MX6Q_PAD_RGMII_RD2__MIPI_CORE_DPHY_IN_9 */
-	IMX_PIN_REG(MX6Q_PAD_RGMII_RD3, 0x0394, 0x0080, 0, 0x0000, 0), /* MX6Q_PAD_RGMII_RD3__MIPI_HSI_CRL_TX_WAK */
-	IMX_PIN_REG(MX6Q_PAD_RGMII_RD3, 0x0394, 0x0080, 1, 0x0854, 0), /* MX6Q_PAD_RGMII_RD3__ENET_RGMII_RD3 */
-	IMX_PIN_REG(MX6Q_PAD_RGMII_RD3, 0x0394, 0x0080, 5, 0x0000, 0), /* MX6Q_PAD_RGMII_RD3__GPIO_6_29 */
-	IMX_PIN_REG(MX6Q_PAD_RGMII_RD3, 0x0394, 0x0080, 6, 0x0000, 0), /* MX6Q_PAD_RGMII_RD3__MIPI_CORE_DPHY_IN10 */
-	IMX_PIN_REG(MX6Q_PAD_RGMII_RXC, 0x0398, 0x0084, 0, 0x0000, 0), /* MX6Q_PAD_RGMII_RXC__USBOH3_H3_STROBE */
-	IMX_PIN_REG(MX6Q_PAD_RGMII_RXC, 0x0398, 0x0084, 1, 0x0844, 0), /* MX6Q_PAD_RGMII_RXC__ENET_RGMII_RXC */
-	IMX_PIN_REG(MX6Q_PAD_RGMII_RXC, 0x0398, 0x0084, 5, 0x0000, 0), /* MX6Q_PAD_RGMII_RXC__GPIO_6_30 */
-	IMX_PIN_REG(MX6Q_PAD_RGMII_RXC, 0x0398, 0x0084, 6, 0x0000, 0), /* MX6Q_PAD_RGMII_RXC__MIPI_CORE_DPHY_IN11 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A25, 0x039C, 0x0088, 0, 0x0000, 0), /* MX6Q_PAD_EIM_A25__WEIM_WEIM_A_25 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A25, 0x039C, 0x0088, 1, 0x0000, 0), /* MX6Q_PAD_EIM_A25__ECSPI4_SS1 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A25, 0x039C, 0x0088, 2, 0x0000, 0), /* MX6Q_PAD_EIM_A25__ECSPI2_RDY */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A25, 0x039C, 0x0088, 3, 0x0000, 0), /* MX6Q_PAD_EIM_A25__IPU1_DI1_PIN12 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A25, 0x039C, 0x0088, 4, 0x0000, 0), /* MX6Q_PAD_EIM_A25__IPU1_DI0_D1_CS */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A25, 0x039C, 0x0088, 5, 0x0000, 0), /* MX6Q_PAD_EIM_A25__GPIO_5_2 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A25, 0x039C, 0x0088, 6, 0x088C, 0), /* MX6Q_PAD_EIM_A25__HDMI_TX_CEC_LINE */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A25, 0x039C, 0x0088, 7, 0x0000, 0), /* MX6Q_PAD_EIM_A25__PL301_PER1_HBURST_0 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_EB2, 0x03A0, 0x008C, 0, 0x0000, 0), /* MX6Q_PAD_EIM_EB2__WEIM_WEIM_EB_2 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_EB2, 0x03A0, 0x008C, 1, 0x0800, 0), /* MX6Q_PAD_EIM_EB2__ECSPI1_SS0 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_EB2, 0x03A0, 0x008C, 2, 0x07EC, 0), /* MX6Q_PAD_EIM_EB2__CCM_DI1_EXT_CLK */
-	IMX_PIN_REG(MX6Q_PAD_EIM_EB2, 0x03A0, 0x008C, 3, 0x08D4, 0), /* MX6Q_PAD_EIM_EB2__IPU2_CSI1_D_19 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_EB2, 0x03A0, 0x008C, 4, 0x0890, 0), /* MX6Q_PAD_EIM_EB2__HDMI_TX_DDC_SCL */
-	IMX_PIN_REG(MX6Q_PAD_EIM_EB2, 0x03A0, 0x008C, 5, 0x0000, 0), /* MX6Q_PAD_EIM_EB2__GPIO_2_30 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_EB2, 0x03A0, 0x008C, 6, 0x08A0, 0), /* MX6Q_PAD_EIM_EB2__I2C2_SCL */
-	IMX_PIN_REG(MX6Q_PAD_EIM_EB2, 0x03A0, 0x008C, 7, 0x0000, 0), /* MX6Q_PAD_EIM_EB2__SRC_BT_CFG_30 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D16, 0x03A4, 0x0090, 0, 0x0000, 0), /* MX6Q_PAD_EIM_D16__WEIM_WEIM_D_16 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D16, 0x03A4, 0x0090, 1, 0x07F4, 0), /* MX6Q_PAD_EIM_D16__ECSPI1_SCLK */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D16, 0x03A4, 0x0090, 2, 0x0000, 0), /* MX6Q_PAD_EIM_D16__IPU1_DI0_PIN5 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D16, 0x03A4, 0x0090, 3, 0x08D0, 0), /* MX6Q_PAD_EIM_D16__IPU2_CSI1_D_18 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D16, 0x03A4, 0x0090, 4, 0x0894, 0), /* MX6Q_PAD_EIM_D16__HDMI_TX_DDC_SDA */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D16, 0x03A4, 0x0090, 5, 0x0000, 0), /* MX6Q_PAD_EIM_D16__GPIO_3_16 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D16, 0x03A4, 0x0090, 6, 0x08A4, 0), /* MX6Q_PAD_EIM_D16__I2C2_SDA */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D17, 0x03A8, 0x0094, 0, 0x0000, 0), /* MX6Q_PAD_EIM_D17__WEIM_WEIM_D_17 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D17, 0x03A8, 0x0094, 1, 0x07F8, 0), /* MX6Q_PAD_EIM_D17__ECSPI1_MISO */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D17, 0x03A8, 0x0094, 2, 0x0000, 0), /* MX6Q_PAD_EIM_D17__IPU1_DI0_PIN6 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D17, 0x03A8, 0x0094, 3, 0x08E0, 0), /* MX6Q_PAD_EIM_D17__IPU2_CSI1_PIXCLK */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D17, 0x03A8, 0x0094, 4, 0x0000, 0), /* MX6Q_PAD_EIM_D17__DCIC1_DCIC_OUT */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D17, 0x03A8, 0x0094, 5, 0x0000, 0), /* MX6Q_PAD_EIM_D17__GPIO_3_17 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D17, 0x03A8, 0x0094, 6, 0x08A8, 0), /* MX6Q_PAD_EIM_D17__I2C3_SCL */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D17, 0x03A8, 0x0094, 7, 0x0000, 0), /* MX6Q_PAD_EIM_D17__PL301_PER1_HBURST_1 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D18, 0x03AC, 0x0098, 0, 0x0000, 0), /* MX6Q_PAD_EIM_D18__WEIM_WEIM_D_18 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D18, 0x03AC, 0x0098, 1, 0x07FC, 0), /* MX6Q_PAD_EIM_D18__ECSPI1_MOSI */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D18, 0x03AC, 0x0098, 2, 0x0000, 0), /* MX6Q_PAD_EIM_D18__IPU1_DI0_PIN7 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D18, 0x03AC, 0x0098, 3, 0x08CC, 0), /* MX6Q_PAD_EIM_D18__IPU2_CSI1_D_17 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D18, 0x03AC, 0x0098, 4, 0x0000, 0), /* MX6Q_PAD_EIM_D18__IPU1_DI1_D0_CS */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D18, 0x03AC, 0x0098, 5, 0x0000, 0), /* MX6Q_PAD_EIM_D18__GPIO_3_18 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D18, 0x03AC, 0x0098, 6, 0x08AC, 0), /* MX6Q_PAD_EIM_D18__I2C3_SDA */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D18, 0x03AC, 0x0098, 7, 0x0000, 0), /* MX6Q_PAD_EIM_D18__PL301_PER1_HBURST_2 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D19, 0x03B0, 0x009C, 0, 0x0000, 0), /* MX6Q_PAD_EIM_D19__WEIM_WEIM_D_19 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D19, 0x03B0, 0x009C, 1, 0x0804, 0), /* MX6Q_PAD_EIM_D19__ECSPI1_SS1 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D19, 0x03B0, 0x009C, 2, 0x0000, 0), /* MX6Q_PAD_EIM_D19__IPU1_DI0_PIN8 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D19, 0x03B0, 0x009C, 3, 0x08C8, 0), /* MX6Q_PAD_EIM_D19__IPU2_CSI1_D_16 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D19, 0x03B0, 0x009C, 4, 0x091C, 0), /* MX6Q_PAD_EIM_D19__UART1_CTS */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D19, 0x03B0, 0x009C, 5, 0x0000, 0), /* MX6Q_PAD_EIM_D19__GPIO_3_19 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D19, 0x03B0, 0x009C, 6, 0x0000, 0), /* MX6Q_PAD_EIM_D19__EPIT1_EPITO */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D19, 0x03B0, 0x009C, 7, 0x0000, 0), /* MX6Q_PAD_EIM_D19__PL301_PER1_HRESP */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D20, 0x03B4, 0x00A0, 0, 0x0000, 0), /* MX6Q_PAD_EIM_D20__WEIM_WEIM_D_20 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D20, 0x03B4, 0x00A0, 1, 0x0824, 0), /* MX6Q_PAD_EIM_D20__ECSPI4_SS0 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D20, 0x03B4, 0x00A0, 2, 0x0000, 0), /* MX6Q_PAD_EIM_D20__IPU1_DI0_PIN16 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D20, 0x03B4, 0x00A0, 3, 0x08C4, 0), /* MX6Q_PAD_EIM_D20__IPU2_CSI1_D_15 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D20, 0x03B4, 0x00A0, 4, 0x091C, 1), /* MX6Q_PAD_EIM_D20__UART1_RTS */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D20, 0x03B4, 0x00A0, 5, 0x0000, 0), /* MX6Q_PAD_EIM_D20__GPIO_3_20 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D20, 0x03B4, 0x00A0, 6, 0x0000, 0), /* MX6Q_PAD_EIM_D20__EPIT2_EPITO */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D21, 0x03B8, 0x00A4, 0, 0x0000, 0), /* MX6Q_PAD_EIM_D21__WEIM_WEIM_D_21 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D21, 0x03B8, 0x00A4, 1, 0x0000, 0), /* MX6Q_PAD_EIM_D21__ECSPI4_SCLK */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D21, 0x03B8, 0x00A4, 2, 0x0000, 0), /* MX6Q_PAD_EIM_D21__IPU1_DI0_PIN17 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D21, 0x03B8, 0x00A4, 3, 0x08B4, 0), /* MX6Q_PAD_EIM_D21__IPU2_CSI1_D_11 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D21, 0x03B8, 0x00A4, 4, 0x0944, 0), /* MX6Q_PAD_EIM_D21__USBOH3_USBOTG_OC */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D21, 0x03B8, 0x00A4, 5, 0x0000, 0), /* MX6Q_PAD_EIM_D21__GPIO_3_21 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D21, 0x03B8, 0x00A4, 6, 0x0898, 0), /* MX6Q_PAD_EIM_D21__I2C1_SCL */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D21, 0x03B8, 0x00A4, 7, 0x0914, 0), /* MX6Q_PAD_EIM_D21__SPDIF_IN1 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D22, 0x03BC, 0x00A8, 0, 0x0000, 0), /* MX6Q_PAD_EIM_D22__WEIM_WEIM_D_22 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D22, 0x03BC, 0x00A8, 1, 0x0000, 0), /* MX6Q_PAD_EIM_D22__ECSPI4_MISO */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D22, 0x03BC, 0x00A8, 2, 0x0000, 0), /* MX6Q_PAD_EIM_D22__IPU1_DI0_PIN1 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D22, 0x03BC, 0x00A8, 3, 0x08B0, 0), /* MX6Q_PAD_EIM_D22__IPU2_CSI1_D_10 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D22, 0x03BC, 0x00A8, 4, 0x0000, 0), /* MX6Q_PAD_EIM_D22__USBOH3_USBOTG_PWR */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D22, 0x03BC, 0x00A8, 5, 0x0000, 0), /* MX6Q_PAD_EIM_D22__GPIO_3_22 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D22, 0x03BC, 0x00A8, 6, 0x0000, 0), /* MX6Q_PAD_EIM_D22__SPDIF_OUT1 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D22, 0x03BC, 0x00A8, 7, 0x0000, 0), /* MX6Q_PAD_EIM_D22__PL301_PER1_HWRITE */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D23, 0x03C0, 0x00AC, 0, 0x0000, 0), /* MX6Q_PAD_EIM_D23__WEIM_WEIM_D_23 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D23, 0x03C0, 0x00AC, 1, 0x0000, 0), /* MX6Q_PAD_EIM_D23__IPU1_DI0_D0_CS */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D23, 0x03C0, 0x00AC, 2, 0x092C, 0), /* MX6Q_PAD_EIM_D23__UART3_CTS */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D23, 0x03C0, 0x00AC, 3, 0x0000, 0), /* MX6Q_PAD_EIM_D23__UART1_DCD */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D23, 0x03C0, 0x00AC, 4, 0x08D8, 0), /* MX6Q_PAD_EIM_D23__IPU2_CSI1_DATA_EN */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D23, 0x03C0, 0x00AC, 5, 0x0000, 0), /* MX6Q_PAD_EIM_D23__GPIO_3_23 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D23, 0x03C0, 0x00AC, 6, 0x0000, 0), /* MX6Q_PAD_EIM_D23__IPU1_DI1_PIN2 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D23, 0x03C0, 0x00AC, 7, 0x0000, 0), /* MX6Q_PAD_EIM_D23__IPU1_DI1_PIN14 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_EB3, 0x03C4, 0x00B0, 0, 0x0000, 0), /* MX6Q_PAD_EIM_EB3__WEIM_WEIM_EB_3 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_EB3, 0x03C4, 0x00B0, 1, 0x0000, 0), /* MX6Q_PAD_EIM_EB3__ECSPI4_RDY */
-	IMX_PIN_REG(MX6Q_PAD_EIM_EB3, 0x03C4, 0x00B0, 2, 0x092C, 1), /* MX6Q_PAD_EIM_EB3__UART3_RTS */
-	IMX_PIN_REG(MX6Q_PAD_EIM_EB3, 0x03C4, 0x00B0, 3, 0x0000, 0), /* MX6Q_PAD_EIM_EB3__UART1_RI */
-	IMX_PIN_REG(MX6Q_PAD_EIM_EB3, 0x03C4, 0x00B0, 4, 0x08DC, 0), /* MX6Q_PAD_EIM_EB3__IPU2_CSI1_HSYNC */
-	IMX_PIN_REG(MX6Q_PAD_EIM_EB3, 0x03C4, 0x00B0, 5, 0x0000, 0), /* MX6Q_PAD_EIM_EB3__GPIO_2_31 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_EB3, 0x03C4, 0x00B0, 6, 0x0000, 0), /* MX6Q_PAD_EIM_EB3__IPU1_DI1_PIN3 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_EB3, 0x03C4, 0x00B0, 7, 0x0000, 0), /* MX6Q_PAD_EIM_EB3__SRC_BT_CFG_31 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D24, 0x03C8, 0x00B4, 0, 0x0000, 0), /* MX6Q_PAD_EIM_D24__WEIM_WEIM_D_24 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D24, 0x03C8, 0x00B4, 1, 0x0000, 0), /* MX6Q_PAD_EIM_D24__ECSPI4_SS2 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D24, 0x03C8, 0x00B4, 2, 0x0000, 0), /* MX6Q_PAD_EIM_D24__UART3_TXD */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D24, 0x03C8, 0x00B4, 3, 0x0808, 0), /* MX6Q_PAD_EIM_D24__ECSPI1_SS2 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D24, 0x03C8, 0x00B4, 4, 0x0000, 0), /* MX6Q_PAD_EIM_D24__ECSPI2_SS2 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D24, 0x03C8, 0x00B4, 5, 0x0000, 0), /* MX6Q_PAD_EIM_D24__GPIO_3_24 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D24, 0x03C8, 0x00B4, 6, 0x07D8, 0), /* MX6Q_PAD_EIM_D24__AUDMUX_AUD5_RXFS */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D24, 0x03C8, 0x00B4, 7, 0x0000, 0), /* MX6Q_PAD_EIM_D24__UART1_DTR */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D25, 0x03CC, 0x00B8, 0, 0x0000, 0), /* MX6Q_PAD_EIM_D25__WEIM_WEIM_D_25 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D25, 0x03CC, 0x00B8, 1, 0x0000, 0), /* MX6Q_PAD_EIM_D25__ECSPI4_SS3 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D25, 0x03CC, 0x00B8, 2, 0x0930, 1), /* MX6Q_PAD_EIM_D25__UART3_RXD */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D25, 0x03CC, 0x00B8, 3, 0x080C, 0), /* MX6Q_PAD_EIM_D25__ECSPI1_SS3 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D25, 0x03CC, 0x00B8, 4, 0x0000, 0), /* MX6Q_PAD_EIM_D25__ECSPI2_SS3 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D25, 0x03CC, 0x00B8, 5, 0x0000, 0), /* MX6Q_PAD_EIM_D25__GPIO_3_25 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D25, 0x03CC, 0x00B8, 6, 0x07D4, 0), /* MX6Q_PAD_EIM_D25__AUDMUX_AUD5_RXC */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D25, 0x03CC, 0x00B8, 7, 0x0000, 0), /* MX6Q_PAD_EIM_D25__UART1_DSR */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D26, 0x03D0, 0x00BC, 0, 0x0000, 0), /* MX6Q_PAD_EIM_D26__WEIM_WEIM_D_26 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D26, 0x03D0, 0x00BC, 1, 0x0000, 0), /* MX6Q_PAD_EIM_D26__IPU1_DI1_PIN11 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D26, 0x03D0, 0x00BC, 2, 0x0000, 0), /* MX6Q_PAD_EIM_D26__IPU1_CSI0_D_1 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D26, 0x03D0, 0x00BC, 3, 0x08C0, 0), /* MX6Q_PAD_EIM_D26__IPU2_CSI1_D_14 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D26, 0x03D0, 0x00BC, 4, 0x0000, 0), /* MX6Q_PAD_EIM_D26__UART2_TXD */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D26, 0x03D0, 0x00BC, 5, 0x0000, 0), /* MX6Q_PAD_EIM_D26__GPIO_3_26 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D26, 0x03D0, 0x00BC, 6, 0x0000, 0), /* MX6Q_PAD_EIM_D26__IPU1_SISG_2 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D26, 0x03D0, 0x00BC, 7, 0x0000, 0), /* MX6Q_PAD_EIM_D26__IPU1_DISP1_DAT_22 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D27, 0x03D4, 0x00C0, 0, 0x0000, 0), /* MX6Q_PAD_EIM_D27__WEIM_WEIM_D_27 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D27, 0x03D4, 0x00C0, 1, 0x0000, 0), /* MX6Q_PAD_EIM_D27__IPU1_DI1_PIN13 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D27, 0x03D4, 0x00C0, 2, 0x0000, 0), /* MX6Q_PAD_EIM_D27__IPU1_CSI0_D_0 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D27, 0x03D4, 0x00C0, 3, 0x08BC, 0), /* MX6Q_PAD_EIM_D27__IPU2_CSI1_D_13 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D27, 0x03D4, 0x00C0, 4, 0x0928, 1), /* MX6Q_PAD_EIM_D27__UART2_RXD */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D27, 0x03D4, 0x00C0, 5, 0x0000, 0), /* MX6Q_PAD_EIM_D27__GPIO_3_27 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D27, 0x03D4, 0x00C0, 6, 0x0000, 0), /* MX6Q_PAD_EIM_D27__IPU1_SISG_3 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D27, 0x03D4, 0x00C0, 7, 0x0000, 0), /* MX6Q_PAD_EIM_D27__IPU1_DISP1_DAT_23 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D28, 0x03D8, 0x00C4, 0, 0x0000, 0), /* MX6Q_PAD_EIM_D28__WEIM_WEIM_D_28 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D28, 0x03D8, 0x00C4, 1, 0x089C, 0), /* MX6Q_PAD_EIM_D28__I2C1_SDA */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D28, 0x03D8, 0x00C4, 2, 0x0000, 0), /* MX6Q_PAD_EIM_D28__ECSPI4_MOSI */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D28, 0x03D8, 0x00C4, 3, 0x08B8, 0), /* MX6Q_PAD_EIM_D28__IPU2_CSI1_D_12 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D28, 0x03D8, 0x00C4, 4, 0x0924, 0), /* MX6Q_PAD_EIM_D28__UART2_CTS */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D28, 0x03D8, 0x00C4, 5, 0x0000, 0), /* MX6Q_PAD_EIM_D28__GPIO_3_28 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D28, 0x03D8, 0x00C4, 6, 0x0000, 0), /* MX6Q_PAD_EIM_D28__IPU1_EXT_TRIG */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D28, 0x03D8, 0x00C4, 7, 0x0000, 0), /* MX6Q_PAD_EIM_D28__IPU1_DI0_PIN13 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D29, 0x03DC, 0x00C8, 0, 0x0000, 0), /* MX6Q_PAD_EIM_D29__WEIM_WEIM_D_29 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D29, 0x03DC, 0x00C8, 1, 0x0000, 0), /* MX6Q_PAD_EIM_D29__IPU1_DI1_PIN15 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D29, 0x03DC, 0x00C8, 2, 0x0824, 1), /* MX6Q_PAD_EIM_D29__ECSPI4_SS0 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D29, 0x03DC, 0x00C8, 4, 0x0924, 1), /* MX6Q_PAD_EIM_D29__UART2_RTS */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D29, 0x03DC, 0x00C8, 5, 0x0000, 0), /* MX6Q_PAD_EIM_D29__GPIO_3_29 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D29, 0x03DC, 0x00C8, 6, 0x08E4, 0), /* MX6Q_PAD_EIM_D29__IPU2_CSI1_VSYNC */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D29, 0x03DC, 0x00C8, 7, 0x0000, 0), /* MX6Q_PAD_EIM_D29__IPU1_DI0_PIN14 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D30, 0x03E0, 0x00CC, 0, 0x0000, 0), /* MX6Q_PAD_EIM_D30__WEIM_WEIM_D_30 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D30, 0x03E0, 0x00CC, 1, 0x0000, 0), /* MX6Q_PAD_EIM_D30__IPU1_DISP1_DAT_21 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D30, 0x03E0, 0x00CC, 2, 0x0000, 0), /* MX6Q_PAD_EIM_D30__IPU1_DI0_PIN11 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D30, 0x03E0, 0x00CC, 3, 0x0000, 0), /* MX6Q_PAD_EIM_D30__IPU1_CSI0_D_3 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D30, 0x03E0, 0x00CC, 4, 0x092C, 2), /* MX6Q_PAD_EIM_D30__UART3_CTS */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D30, 0x03E0, 0x00CC, 5, 0x0000, 0), /* MX6Q_PAD_EIM_D30__GPIO_3_30 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D30, 0x03E0, 0x00CC, 6, 0x0948, 0), /* MX6Q_PAD_EIM_D30__USBOH3_USBH1_OC */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D30, 0x03E0, 0x00CC, 7, 0x0000, 0), /* MX6Q_PAD_EIM_D30__PL301_PER1_HPROT_0 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D31, 0x03E4, 0x00D0, 0, 0x0000, 0), /* MX6Q_PAD_EIM_D31__WEIM_WEIM_D_31 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D31, 0x03E4, 0x00D0, 1, 0x0000, 0), /* MX6Q_PAD_EIM_D31__IPU1_DISP1_DAT_20 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D31, 0x03E4, 0x00D0, 2, 0x0000, 0), /* MX6Q_PAD_EIM_D31__IPU1_DI0_PIN12 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D31, 0x03E4, 0x00D0, 3, 0x0000, 0), /* MX6Q_PAD_EIM_D31__IPU1_CSI0_D_2 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D31, 0x03E4, 0x00D0, 4, 0x092C, 3), /* MX6Q_PAD_EIM_D31__UART3_RTS */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D31, 0x03E4, 0x00D0, 5, 0x0000, 0), /* MX6Q_PAD_EIM_D31__GPIO_3_31 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D31, 0x03E4, 0x00D0, 6, 0x0000, 0), /* MX6Q_PAD_EIM_D31__USBOH3_USBH1_PWR */
-	IMX_PIN_REG(MX6Q_PAD_EIM_D31, 0x03E4, 0x00D0, 7, 0x0000, 0), /* MX6Q_PAD_EIM_D31__PL301_PER1_HPROT_1 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A24, 0x03E8, 0x00D4, 0, 0x0000, 0), /* MX6Q_PAD_EIM_A24__WEIM_WEIM_A_24 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A24, 0x03E8, 0x00D4, 1, 0x0000, 0), /* MX6Q_PAD_EIM_A24__IPU1_DISP1_DAT_19 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A24, 0x03E8, 0x00D4, 2, 0x08D4, 1), /* MX6Q_PAD_EIM_A24__IPU2_CSI1_D_19 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A24, 0x03E8, 0x00D4, 3, 0x0000, 0), /* MX6Q_PAD_EIM_A24__IPU2_SISG_2 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A24, 0x03E8, 0x00D4, 4, 0x0000, 0), /* MX6Q_PAD_EIM_A24__IPU1_SISG_2 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A24, 0x03E8, 0x00D4, 5, 0x0000, 0), /* MX6Q_PAD_EIM_A24__GPIO_5_4 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A24, 0x03E8, 0x00D4, 6, 0x0000, 0), /* MX6Q_PAD_EIM_A24__PL301_PER1_HPROT_2 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A24, 0x03E8, 0x00D4, 7, 0x0000, 0), /* MX6Q_PAD_EIM_A24__SRC_BT_CFG_24 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A23, 0x03EC, 0x00D8, 0, 0x0000, 0), /* MX6Q_PAD_EIM_A23__WEIM_WEIM_A_23 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A23, 0x03EC, 0x00D8, 1, 0x0000, 0), /* MX6Q_PAD_EIM_A23__IPU1_DISP1_DAT_18 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A23, 0x03EC, 0x00D8, 2, 0x08D0, 1), /* MX6Q_PAD_EIM_A23__IPU2_CSI1_D_18 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A23, 0x03EC, 0x00D8, 3, 0x0000, 0), /* MX6Q_PAD_EIM_A23__IPU2_SISG_3 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A23, 0x03EC, 0x00D8, 4, 0x0000, 0), /* MX6Q_PAD_EIM_A23__IPU1_SISG_3 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A23, 0x03EC, 0x00D8, 5, 0x0000, 0), /* MX6Q_PAD_EIM_A23__GPIO_6_6 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A23, 0x03EC, 0x00D8, 6, 0x0000, 0), /* MX6Q_PAD_EIM_A23__PL301_PER1_HPROT_3 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A23, 0x03EC, 0x00D8, 7, 0x0000, 0), /* MX6Q_PAD_EIM_A23__SRC_BT_CFG_23 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A22, 0x03F0, 0x00DC, 0, 0x0000, 0), /* MX6Q_PAD_EIM_A22__WEIM_WEIM_A_22 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A22, 0x03F0, 0x00DC, 1, 0x0000, 0), /* MX6Q_PAD_EIM_A22__IPU1_DISP1_DAT_17 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A22, 0x03F0, 0x00DC, 2, 0x08CC, 1), /* MX6Q_PAD_EIM_A22__IPU2_CSI1_D_17 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A22, 0x03F0, 0x00DC, 5, 0x0000, 0), /* MX6Q_PAD_EIM_A22__GPIO_2_16 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A22, 0x03F0, 0x00DC, 6, 0x0000, 0), /* MX6Q_PAD_EIM_A22__TPSMP_HDATA_0 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A22, 0x03F0, 0x00DC, 7, 0x0000, 0), /* MX6Q_PAD_EIM_A22__SRC_BT_CFG_22 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A21, 0x03F4, 0x00E0, 0, 0x0000, 0), /* MX6Q_PAD_EIM_A21__WEIM_WEIM_A_21 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A21, 0x03F4, 0x00E0, 1, 0x0000, 0), /* MX6Q_PAD_EIM_A21__IPU1_DISP1_DAT_16 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A21, 0x03F4, 0x00E0, 2, 0x08C8, 1), /* MX6Q_PAD_EIM_A21__IPU2_CSI1_D_16 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A21, 0x03F4, 0x00E0, 3, 0x0000, 0), /* MX6Q_PAD_EIM_A21__RESERVED_RESERVED */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A21, 0x03F4, 0x00E0, 4, 0x0000, 0), /* MX6Q_PAD_EIM_A21__MIPI_CORE_DPHY_OUT_18 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A21, 0x03F4, 0x00E0, 5, 0x0000, 0), /* MX6Q_PAD_EIM_A21__GPIO_2_17 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A21, 0x03F4, 0x00E0, 6, 0x0000, 0), /* MX6Q_PAD_EIM_A21__TPSMP_HDATA_1 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A21, 0x03F4, 0x00E0, 7, 0x0000, 0), /* MX6Q_PAD_EIM_A21__SRC_BT_CFG_21 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A20, 0x03F8, 0x00E4, 0, 0x0000, 0), /* MX6Q_PAD_EIM_A20__WEIM_WEIM_A_20 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A20, 0x03F8, 0x00E4, 1, 0x0000, 0), /* MX6Q_PAD_EIM_A20__IPU1_DISP1_DAT_15 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A20, 0x03F8, 0x00E4, 2, 0x08C4, 1), /* MX6Q_PAD_EIM_A20__IPU2_CSI1_D_15 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A20, 0x03F8, 0x00E4, 3, 0x0000, 0), /* MX6Q_PAD_EIM_A20__RESERVED_RESERVED */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A20, 0x03F8, 0x00E4, 4, 0x0000, 0), /* MX6Q_PAD_EIM_A20__MIPI_CORE_DPHY_OUT_19 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A20, 0x03F8, 0x00E4, 5, 0x0000, 0), /* MX6Q_PAD_EIM_A20__GPIO_2_18 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A20, 0x03F8, 0x00E4, 6, 0x0000, 0), /* MX6Q_PAD_EIM_A20__TPSMP_HDATA_2 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A20, 0x03F8, 0x00E4, 7, 0x0000, 0), /* MX6Q_PAD_EIM_A20__SRC_BT_CFG_20 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A19, 0x03FC, 0x00E8, 0, 0x0000, 0), /* MX6Q_PAD_EIM_A19__WEIM_WEIM_A_19 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A19, 0x03FC, 0x00E8, 1, 0x0000, 0), /* MX6Q_PAD_EIM_A19__IPU1_DISP1_DAT_14 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A19, 0x03FC, 0x00E8, 2, 0x08C0, 1), /* MX6Q_PAD_EIM_A19__IPU2_CSI1_D_14 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A19, 0x03FC, 0x00E8, 3, 0x0000, 0), /* MX6Q_PAD_EIM_A19__RESERVED_RESERVED */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A19, 0x03FC, 0x00E8, 4, 0x0000, 0), /* MX6Q_PAD_EIM_A19__MIPI_CORE_DPHY_OUT_20 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A19, 0x03FC, 0x00E8, 5, 0x0000, 0), /* MX6Q_PAD_EIM_A19__GPIO_2_19 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A19, 0x03FC, 0x00E8, 6, 0x0000, 0), /* MX6Q_PAD_EIM_A19__TPSMP_HDATA_3 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A19, 0x03FC, 0x00E8, 7, 0x0000, 0), /* MX6Q_PAD_EIM_A19__SRC_BT_CFG_19 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A18, 0x0400, 0x00EC, 0, 0x0000, 0), /* MX6Q_PAD_EIM_A18__WEIM_WEIM_A_18 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A18, 0x0400, 0x00EC, 1, 0x0000, 0), /* MX6Q_PAD_EIM_A18__IPU1_DISP1_DAT_13 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A18, 0x0400, 0x00EC, 2, 0x08BC, 1), /* MX6Q_PAD_EIM_A18__IPU2_CSI1_D_13 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A18, 0x0400, 0x00EC, 3, 0x0000, 0), /* MX6Q_PAD_EIM_A18__RESERVED_RESERVED */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A18, 0x0400, 0x00EC, 4, 0x0000, 0), /* MX6Q_PAD_EIM_A18__MIPI_CORE_DPHY_OUT_21 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A18, 0x0400, 0x00EC, 5, 0x0000, 0), /* MX6Q_PAD_EIM_A18__GPIO_2_20 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A18, 0x0400, 0x00EC, 6, 0x0000, 0), /* MX6Q_PAD_EIM_A18__TPSMP_HDATA_4 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A18, 0x0400, 0x00EC, 7, 0x0000, 0), /* MX6Q_PAD_EIM_A18__SRC_BT_CFG_18 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A17, 0x0404, 0x00F0, 0, 0x0000, 0), /* MX6Q_PAD_EIM_A17__WEIM_WEIM_A_17 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A17, 0x0404, 0x00F0, 1, 0x0000, 0), /* MX6Q_PAD_EIM_A17__IPU1_DISP1_DAT_12 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A17, 0x0404, 0x00F0, 2, 0x08B8, 1), /* MX6Q_PAD_EIM_A17__IPU2_CSI1_D_12 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A17, 0x0404, 0x00F0, 3, 0x0000, 0), /* MX6Q_PAD_EIM_A17__RESERVED_RESERVED */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A17, 0x0404, 0x00F0, 4, 0x0000, 0), /* MX6Q_PAD_EIM_A17__MIPI_CORE_DPHY_OUT_22 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A17, 0x0404, 0x00F0, 5, 0x0000, 0), /* MX6Q_PAD_EIM_A17__GPIO_2_21 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A17, 0x0404, 0x00F0, 6, 0x0000, 0), /* MX6Q_PAD_EIM_A17__TPSMP_HDATA_5 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A17, 0x0404, 0x00F0, 7, 0x0000, 0), /* MX6Q_PAD_EIM_A17__SRC_BT_CFG_17 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A16, 0x0408, 0x00F4, 0, 0x0000, 0), /* MX6Q_PAD_EIM_A16__WEIM_WEIM_A_16 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A16, 0x0408, 0x00F4, 1, 0x0000, 0), /* MX6Q_PAD_EIM_A16__IPU1_DI1_DISP_CLK */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A16, 0x0408, 0x00F4, 2, 0x08E0, 1), /* MX6Q_PAD_EIM_A16__IPU2_CSI1_PIXCLK */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A16, 0x0408, 0x00F4, 4, 0x0000, 0), /* MX6Q_PAD_EIM_A16__MIPI_CORE_DPHY_OUT_23 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A16, 0x0408, 0x00F4, 5, 0x0000, 0), /* MX6Q_PAD_EIM_A16__GPIO_2_22 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A16, 0x0408, 0x00F4, 6, 0x0000, 0), /* MX6Q_PAD_EIM_A16__TPSMP_HDATA_6 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_A16, 0x0408, 0x00F4, 7, 0x0000, 0), /* MX6Q_PAD_EIM_A16__SRC_BT_CFG_16 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_CS0, 0x040C, 0x00F8, 0, 0x0000, 0), /* MX6Q_PAD_EIM_CS0__WEIM_WEIM_CS_0 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_CS0, 0x040C, 0x00F8, 1, 0x0000, 0), /* MX6Q_PAD_EIM_CS0__IPU1_DI1_PIN5 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_CS0, 0x040C, 0x00F8, 2, 0x0810, 0), /* MX6Q_PAD_EIM_CS0__ECSPI2_SCLK */
-	IMX_PIN_REG(MX6Q_PAD_EIM_CS0, 0x040C, 0x00F8, 4, 0x0000, 0), /* MX6Q_PAD_EIM_CS0__MIPI_CORE_DPHY_OUT_24 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_CS0, 0x040C, 0x00F8, 5, 0x0000, 0), /* MX6Q_PAD_EIM_CS0__GPIO_2_23 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_CS0, 0x040C, 0x00F8, 6, 0x0000, 0), /* MX6Q_PAD_EIM_CS0__TPSMP_HDATA_7 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_CS1, 0x0410, 0x00FC, 0, 0x0000, 0), /* MX6Q_PAD_EIM_CS1__WEIM_WEIM_CS_1 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_CS1, 0x0410, 0x00FC, 1, 0x0000, 0), /* MX6Q_PAD_EIM_CS1__IPU1_DI1_PIN6 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_CS1, 0x0410, 0x00FC, 2, 0x0818, 0), /* MX6Q_PAD_EIM_CS1__ECSPI2_MOSI */
-	IMX_PIN_REG(MX6Q_PAD_EIM_CS1, 0x0410, 0x00FC, 4, 0x0000, 0), /* MX6Q_PAD_EIM_CS1__MIPI_CORE_DPHY_OUT_25 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_CS1, 0x0410, 0x00FC, 5, 0x0000, 0), /* MX6Q_PAD_EIM_CS1__GPIO_2_24 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_CS1, 0x0410, 0x00FC, 6, 0x0000, 0), /* MX6Q_PAD_EIM_CS1__TPSMP_HDATA_8 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_OE, 0x0414, 0x0100, 0, 0x0000, 0), /* MX6Q_PAD_EIM_OE__WEIM_WEIM_OE */
-	IMX_PIN_REG(MX6Q_PAD_EIM_OE, 0x0414, 0x0100, 1, 0x0000, 0), /* MX6Q_PAD_EIM_OE__IPU1_DI1_PIN7 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_OE, 0x0414, 0x0100, 2, 0x0814, 0), /* MX6Q_PAD_EIM_OE__ECSPI2_MISO */
-	IMX_PIN_REG(MX6Q_PAD_EIM_OE, 0x0414, 0x0100, 4, 0x0000, 0), /* MX6Q_PAD_EIM_OE__MIPI_CORE_DPHY_OUT_26 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_OE, 0x0414, 0x0100, 5, 0x0000, 0), /* MX6Q_PAD_EIM_OE__GPIO_2_25 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_OE, 0x0414, 0x0100, 6, 0x0000, 0), /* MX6Q_PAD_EIM_OE__TPSMP_HDATA_9 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_RW, 0x0418, 0x0104, 0, 0x0000, 0), /* MX6Q_PAD_EIM_RW__WEIM_WEIM_RW */
-	IMX_PIN_REG(MX6Q_PAD_EIM_RW, 0x0418, 0x0104, 1, 0x0000, 0), /* MX6Q_PAD_EIM_RW__IPU1_DI1_PIN8 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_RW, 0x0418, 0x0104, 2, 0x081C, 0), /* MX6Q_PAD_EIM_RW__ECSPI2_SS0 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_RW, 0x0418, 0x0104, 4, 0x0000, 0), /* MX6Q_PAD_EIM_RW__MIPI_CORE_DPHY_OUT_27 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_RW, 0x0418, 0x0104, 5, 0x0000, 0), /* MX6Q_PAD_EIM_RW__GPIO_2_26 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_RW, 0x0418, 0x0104, 6, 0x0000, 0), /* MX6Q_PAD_EIM_RW__TPSMP_HDATA_10 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_RW, 0x0418, 0x0104, 7, 0x0000, 0), /* MX6Q_PAD_EIM_RW__SRC_BT_CFG_29 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_LBA, 0x041C, 0x0108, 0, 0x0000, 0), /* MX6Q_PAD_EIM_LBA__WEIM_WEIM_LBA */
-	IMX_PIN_REG(MX6Q_PAD_EIM_LBA, 0x041C, 0x0108, 1, 0x0000, 0), /* MX6Q_PAD_EIM_LBA__IPU1_DI1_PIN17 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_LBA, 0x041C, 0x0108, 2, 0x0820, 0), /* MX6Q_PAD_EIM_LBA__ECSPI2_SS1 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_LBA, 0x041C, 0x0108, 5, 0x0000, 0), /* MX6Q_PAD_EIM_LBA__GPIO_2_27 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_LBA, 0x041C, 0x0108, 6, 0x0000, 0), /* MX6Q_PAD_EIM_LBA__TPSMP_HDATA_11 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_LBA, 0x041C, 0x0108, 7, 0x0000, 0), /* MX6Q_PAD_EIM_LBA__SRC_BT_CFG_26 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_EB0, 0x0420, 0x010C, 0, 0x0000, 0), /* MX6Q_PAD_EIM_EB0__WEIM_WEIM_EB_0 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_EB0, 0x0420, 0x010C, 1, 0x0000, 0), /* MX6Q_PAD_EIM_EB0__IPU1_DISP1_DAT_11 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_EB0, 0x0420, 0x010C, 2, 0x08B4, 1), /* MX6Q_PAD_EIM_EB0__IPU2_CSI1_D_11 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_EB0, 0x0420, 0x010C, 3, 0x0000, 0), /* MX6Q_PAD_EIM_EB0__MIPI_CORE_DPHY_OUT_0 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_EB0, 0x0420, 0x010C, 4, 0x07F0, 0), /* MX6Q_PAD_EIM_EB0__CCM_PMIC_RDY */
-	IMX_PIN_REG(MX6Q_PAD_EIM_EB0, 0x0420, 0x010C, 5, 0x0000, 0), /* MX6Q_PAD_EIM_EB0__GPIO_2_28 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_EB0, 0x0420, 0x010C, 6, 0x0000, 0), /* MX6Q_PAD_EIM_EB0__TPSMP_HDATA_12 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_EB0, 0x0420, 0x010C, 7, 0x0000, 0), /* MX6Q_PAD_EIM_EB0__SRC_BT_CFG_27 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_EB1, 0x0424, 0x0110, 0, 0x0000, 0), /* MX6Q_PAD_EIM_EB1__WEIM_WEIM_EB_1 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_EB1, 0x0424, 0x0110, 1, 0x0000, 0), /* MX6Q_PAD_EIM_EB1__IPU1_DISP1_DAT_10 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_EB1, 0x0424, 0x0110, 2, 0x08B0, 1), /* MX6Q_PAD_EIM_EB1__IPU2_CSI1_D_10 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_EB1, 0x0424, 0x0110, 3, 0x0000, 0), /* MX6Q_PAD_EIM_EB1__MIPI_CORE_DPHY__OUT_1 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_EB1, 0x0424, 0x0110, 5, 0x0000, 0), /* MX6Q_PAD_EIM_EB1__GPIO_2_29 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_EB1, 0x0424, 0x0110, 6, 0x0000, 0), /* MX6Q_PAD_EIM_EB1__TPSMP_HDATA_13 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_EB1, 0x0424, 0x0110, 7, 0x0000, 0), /* MX6Q_PAD_EIM_EB1__SRC_BT_CFG_28 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA0, 0x0428, 0x0114, 0, 0x0000, 0), /* MX6Q_PAD_EIM_DA0__WEIM_WEIM_DA_A_0 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA0, 0x0428, 0x0114, 1, 0x0000, 0), /* MX6Q_PAD_EIM_DA0__IPU1_DISP1_DAT_9 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA0, 0x0428, 0x0114, 2, 0x0000, 0), /* MX6Q_PAD_EIM_DA0__IPU2_CSI1_D_9 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA0, 0x0428, 0x0114, 3, 0x0000, 0), /* MX6Q_PAD_EIM_DA0__MIPI_CORE_DPHY__OUT_2 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA0, 0x0428, 0x0114, 5, 0x0000, 0), /* MX6Q_PAD_EIM_DA0__GPIO_3_0 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA0, 0x0428, 0x0114, 6, 0x0000, 0), /* MX6Q_PAD_EIM_DA0__TPSMP_HDATA_14 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA0, 0x0428, 0x0114, 7, 0x0000, 0), /* MX6Q_PAD_EIM_DA0__SRC_BT_CFG_0 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA1, 0x042C, 0x0118, 0, 0x0000, 0), /* MX6Q_PAD_EIM_DA1__WEIM_WEIM_DA_A_1 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA1, 0x042C, 0x0118, 1, 0x0000, 0), /* MX6Q_PAD_EIM_DA1__IPU1_DISP1_DAT_8 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA1, 0x042C, 0x0118, 2, 0x0000, 0), /* MX6Q_PAD_EIM_DA1__IPU2_CSI1_D_8 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA1, 0x042C, 0x0118, 3, 0x0000, 0), /* MX6Q_PAD_EIM_DA1__MIPI_CORE_DPHY_OUT_3 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA1, 0x042C, 0x0118, 4, 0x0000, 0), /* MX6Q_PAD_EIM_DA1__USBPHY1_TX_LS_MODE */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA1, 0x042C, 0x0118, 5, 0x0000, 0), /* MX6Q_PAD_EIM_DA1__GPIO_3_1 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA1, 0x042C, 0x0118, 6, 0x0000, 0), /* MX6Q_PAD_EIM_DA1__TPSMP_HDATA_15 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA1, 0x042C, 0x0118, 7, 0x0000, 0), /* MX6Q_PAD_EIM_DA1__SRC_BT_CFG_1 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA2, 0x0430, 0x011C, 0, 0x0000, 0), /* MX6Q_PAD_EIM_DA2__WEIM_WEIM_DA_A_2 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA2, 0x0430, 0x011C, 1, 0x0000, 0), /* MX6Q_PAD_EIM_DA2__IPU1_DISP1_DAT_7 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA2, 0x0430, 0x011C, 2, 0x0000, 0), /* MX6Q_PAD_EIM_DA2__IPU2_CSI1_D_7 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA2, 0x0430, 0x011C, 3, 0x0000, 0), /* MX6Q_PAD_EIM_DA2__MIPI_CORE_DPHY_OUT_4 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA2, 0x0430, 0x011C, 4, 0x0000, 0), /* MX6Q_PAD_EIM_DA2__USBPHY1_TX_HS_MODE */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA2, 0x0430, 0x011C, 5, 0x0000, 0), /* MX6Q_PAD_EIM_DA2__GPIO_3_2 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA2, 0x0430, 0x011C, 6, 0x0000, 0), /* MX6Q_PAD_EIM_DA2__TPSMP_HDATA_16 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA2, 0x0430, 0x011C, 7, 0x0000, 0), /* MX6Q_PAD_EIM_DA2__SRC_BT_CFG_2 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA3, 0x0434, 0x0120, 0, 0x0000, 0), /* MX6Q_PAD_EIM_DA3__WEIM_WEIM_DA_A_3 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA3, 0x0434, 0x0120, 1, 0x0000, 0), /* MX6Q_PAD_EIM_DA3__IPU1_DISP1_DAT_6 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA3, 0x0434, 0x0120, 2, 0x0000, 0), /* MX6Q_PAD_EIM_DA3__IPU2_CSI1_D_6 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA3, 0x0434, 0x0120, 3, 0x0000, 0), /* MX6Q_PAD_EIM_DA3__MIPI_CORE_DPHY_OUT_5 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA3, 0x0434, 0x0120, 4, 0x0000, 0), /* MX6Q_PAD_EIM_DA3__USBPHY1_TX_HIZ */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA3, 0x0434, 0x0120, 5, 0x0000, 0), /* MX6Q_PAD_EIM_DA3__GPIO_3_3 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA3, 0x0434, 0x0120, 6, 0x0000, 0), /* MX6Q_PAD_EIM_DA3__TPSMP_HDATA_17 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA3, 0x0434, 0x0120, 7, 0x0000, 0), /* MX6Q_PAD_EIM_DA3__SRC_BT_CFG_3 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA4, 0x0438, 0x0124, 0, 0x0000, 0), /* MX6Q_PAD_EIM_DA4__WEIM_WEIM_DA_A_4 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA4, 0x0438, 0x0124, 1, 0x0000, 0), /* MX6Q_PAD_EIM_DA4__IPU1_DISP1_DAT_5 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA4, 0x0438, 0x0124, 2, 0x0000, 0), /* MX6Q_PAD_EIM_DA4__IPU2_CSI1_D_5 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA4, 0x0438, 0x0124, 3, 0x0000, 0), /* MX6Q_PAD_EIM_DA4__MIPI_CORE_DPHY_OUT_6 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA4, 0x0438, 0x0124, 4, 0x0000, 0), /* MX6Q_PAD_EIM_DA4__ANATOP_USBPHY1_TX_EN */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA4, 0x0438, 0x0124, 5, 0x0000, 0), /* MX6Q_PAD_EIM_DA4__GPIO_3_4 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA4, 0x0438, 0x0124, 6, 0x0000, 0), /* MX6Q_PAD_EIM_DA4__TPSMP_HDATA_18 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA4, 0x0438, 0x0124, 7, 0x0000, 0), /* MX6Q_PAD_EIM_DA4__SRC_BT_CFG_4 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA5, 0x043C, 0x0128, 0, 0x0000, 0), /* MX6Q_PAD_EIM_DA5__WEIM_WEIM_DA_A_5 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA5, 0x043C, 0x0128, 1, 0x0000, 0), /* MX6Q_PAD_EIM_DA5__IPU1_DISP1_DAT_4 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA5, 0x043C, 0x0128, 2, 0x0000, 0), /* MX6Q_PAD_EIM_DA5__IPU2_CSI1_D_4 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA5, 0x043C, 0x0128, 3, 0x0000, 0), /* MX6Q_PAD_EIM_DA5__MIPI_CORE_DPHY_OUT_7 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA5, 0x043C, 0x0128, 4, 0x0000, 0), /* MX6Q_PAD_EIM_DA5__ANATOP_USBPHY1_TX_DP */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA5, 0x043C, 0x0128, 5, 0x0000, 0), /* MX6Q_PAD_EIM_DA5__GPIO_3_5 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA5, 0x043C, 0x0128, 6, 0x0000, 0), /* MX6Q_PAD_EIM_DA5__TPSMP_HDATA_19 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA5, 0x043C, 0x0128, 7, 0x0000, 0), /* MX6Q_PAD_EIM_DA5__SRC_BT_CFG_5 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA6, 0x0440, 0x012C, 0, 0x0000, 0), /* MX6Q_PAD_EIM_DA6__WEIM_WEIM_DA_A_6 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA6, 0x0440, 0x012C, 1, 0x0000, 0), /* MX6Q_PAD_EIM_DA6__IPU1_DISP1_DAT_3 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA6, 0x0440, 0x012C, 2, 0x0000, 0), /* MX6Q_PAD_EIM_DA6__IPU2_CSI1_D_3 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA6, 0x0440, 0x012C, 3, 0x0000, 0), /* MX6Q_PAD_EIM_DA6__MIPI_CORE_DPHY_OUT_8 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA6, 0x0440, 0x012C, 4, 0x0000, 0), /* MX6Q_PAD_EIM_DA6__ANATOP_USBPHY1_TX_DN */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA6, 0x0440, 0x012C, 5, 0x0000, 0), /* MX6Q_PAD_EIM_DA6__GPIO_3_6 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA6, 0x0440, 0x012C, 6, 0x0000, 0), /* MX6Q_PAD_EIM_DA6__TPSMP_HDATA_20 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA6, 0x0440, 0x012C, 7, 0x0000, 0), /* MX6Q_PAD_EIM_DA6__SRC_BT_CFG_6 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA7, 0x0444, 0x0130, 0, 0x0000, 0), /* MX6Q_PAD_EIM_DA7__WEIM_WEIM_DA_A_7 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA7, 0x0444, 0x0130, 1, 0x0000, 0), /* MX6Q_PAD_EIM_DA7__IPU1_DISP1_DAT_2 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA7, 0x0444, 0x0130, 2, 0x0000, 0), /* MX6Q_PAD_EIM_DA7__IPU2_CSI1_D_2 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA7, 0x0444, 0x0130, 3, 0x0000, 0), /* MX6Q_PAD_EIM_DA7__MIPI_CORE_DPHY_OUT_9 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA7, 0x0444, 0x0130, 5, 0x0000, 0), /* MX6Q_PAD_EIM_DA7__GPIO_3_7 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA7, 0x0444, 0x0130, 6, 0x0000, 0), /* MX6Q_PAD_EIM_DA7__TPSMP_HDATA_21 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA7, 0x0444, 0x0130, 7, 0x0000, 0), /* MX6Q_PAD_EIM_DA7__SRC_BT_CFG_7 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA8, 0x0448, 0x0134, 0, 0x0000, 0), /* MX6Q_PAD_EIM_DA8__WEIM_WEIM_DA_A_8 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA8, 0x0448, 0x0134, 1, 0x0000, 0), /* MX6Q_PAD_EIM_DA8__IPU1_DISP1_DAT_1 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA8, 0x0448, 0x0134, 2, 0x0000, 0), /* MX6Q_PAD_EIM_DA8__IPU2_CSI1_D_1 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA8, 0x0448, 0x0134, 3, 0x0000, 0), /* MX6Q_PAD_EIM_DA8__MIPI_CORE_DPHY_OUT_10 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA8, 0x0448, 0x0134, 5, 0x0000, 0), /* MX6Q_PAD_EIM_DA8__GPIO_3_8 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA8, 0x0448, 0x0134, 6, 0x0000, 0), /* MX6Q_PAD_EIM_DA8__TPSMP_HDATA_22 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA8, 0x0448, 0x0134, 7, 0x0000, 0), /* MX6Q_PAD_EIM_DA8__SRC_BT_CFG_8 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA9, 0x044C, 0x0138, 0, 0x0000, 0), /* MX6Q_PAD_EIM_DA9__WEIM_WEIM_DA_A_9 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA9, 0x044C, 0x0138, 1, 0x0000, 0), /* MX6Q_PAD_EIM_DA9__IPU1_DISP1_DAT_0 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA9, 0x044C, 0x0138, 2, 0x0000, 0), /* MX6Q_PAD_EIM_DA9__IPU2_CSI1_D_0 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA9, 0x044C, 0x0138, 3, 0x0000, 0), /* MX6Q_PAD_EIM_DA9__MIPI_CORE_DPHY_OUT_11 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA9, 0x044C, 0x0138, 5, 0x0000, 0), /* MX6Q_PAD_EIM_DA9__GPIO_3_9 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA9, 0x044C, 0x0138, 6, 0x0000, 0), /* MX6Q_PAD_EIM_DA9__TPSMP_HDATA_23 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA9, 0x044C, 0x0138, 7, 0x0000, 0), /* MX6Q_PAD_EIM_DA9__SRC_BT_CFG_9 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA10, 0x0450, 0x013C, 0, 0x0000, 0), /* MX6Q_PAD_EIM_DA10__WEIM_WEIM_DA_A_10 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA10, 0x0450, 0x013C, 1, 0x0000, 0), /* MX6Q_PAD_EIM_DA10__IPU1_DI1_PIN15 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA10, 0x0450, 0x013C, 2, 0x08D8, 1), /* MX6Q_PAD_EIM_DA10__IPU2_CSI1_DATA_EN */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA10, 0x0450, 0x013C, 3, 0x0000, 0), /* MX6Q_PAD_EIM_DA10__MIPI_CORE_DPHY_OUT12 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA10, 0x0450, 0x013C, 5, 0x0000, 0), /* MX6Q_PAD_EIM_DA10__GPIO_3_10 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA10, 0x0450, 0x013C, 6, 0x0000, 0), /* MX6Q_PAD_EIM_DA10__TPSMP_HDATA_24 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA10, 0x0450, 0x013C, 7, 0x0000, 0), /* MX6Q_PAD_EIM_DA10__SRC_BT_CFG_10 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA11, 0x0454, 0x0140, 0, 0x0000, 0), /* MX6Q_PAD_EIM_DA11__WEIM_WEIM_DA_A_11 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA11, 0x0454, 0x0140, 1, 0x0000, 0), /* MX6Q_PAD_EIM_DA11__IPU1_DI1_PIN2 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA11, 0x0454, 0x0140, 2, 0x08DC, 1), /* MX6Q_PAD_EIM_DA11__IPU2_CSI1_HSYNC */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA11, 0x0454, 0x0140, 3, 0x0000, 0), /* MX6Q_PAD_EIM_DA11__MIPI_CORE_DPHY_OUT13 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA11, 0x0454, 0x0140, 4, 0x0000, 0), /* MX6Q_PAD_EIM_DA11__SDMA_DBG_EVT_CHN_6 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA11, 0x0454, 0x0140, 5, 0x0000, 0), /* MX6Q_PAD_EIM_DA11__GPIO_3_11 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA11, 0x0454, 0x0140, 6, 0x0000, 0), /* MX6Q_PAD_EIM_DA11__TPSMP_HDATA_25 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA11, 0x0454, 0x0140, 7, 0x0000, 0), /* MX6Q_PAD_EIM_DA11__SRC_BT_CFG_11 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA12, 0x0458, 0x0144, 0, 0x0000, 0), /* MX6Q_PAD_EIM_DA12__WEIM_WEIM_DA_A_12 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA12, 0x0458, 0x0144, 1, 0x0000, 0), /* MX6Q_PAD_EIM_DA12__IPU1_DI1_PIN3 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA12, 0x0458, 0x0144, 2, 0x08E4, 1), /* MX6Q_PAD_EIM_DA12__IPU2_CSI1_VSYNC */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA12, 0x0458, 0x0144, 3, 0x0000, 0), /* MX6Q_PAD_EIM_DA12__MIPI_CORE_DPHY_OUT14 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA12, 0x0458, 0x0144, 4, 0x0000, 0), /* MX6Q_PAD_EIM_DA12__SDMA_DEBUG_EVT_CHN_3 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA12, 0x0458, 0x0144, 5, 0x0000, 0), /* MX6Q_PAD_EIM_DA12__GPIO_3_12 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA12, 0x0458, 0x0144, 6, 0x0000, 0), /* MX6Q_PAD_EIM_DA12__TPSMP_HDATA_26 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA12, 0x0458, 0x0144, 7, 0x0000, 0), /* MX6Q_PAD_EIM_DA12__SRC_BT_CFG_12 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA13, 0x045C, 0x0148, 0, 0x0000, 0), /* MX6Q_PAD_EIM_DA13__WEIM_WEIM_DA_A_13 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA13, 0x045C, 0x0148, 1, 0x0000, 0), /* MX6Q_PAD_EIM_DA13__IPU1_DI1_D0_CS */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA13, 0x045C, 0x0148, 2, 0x07EC, 1), /* MX6Q_PAD_EIM_DA13__CCM_DI1_EXT_CLK */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA13, 0x045C, 0x0148, 3, 0x0000, 0), /* MX6Q_PAD_EIM_DA13__MIPI_CORE_DPHY_OUT15 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA13, 0x045C, 0x0148, 4, 0x0000, 0), /* MX6Q_PAD_EIM_DA13__SDMA_DEBUG_EVT_CHN_4 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA13, 0x045C, 0x0148, 5, 0x0000, 0), /* MX6Q_PAD_EIM_DA13__GPIO_3_13 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA13, 0x045C, 0x0148, 6, 0x0000, 0), /* MX6Q_PAD_EIM_DA13__TPSMP_HDATA_27 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA13, 0x045C, 0x0148, 7, 0x0000, 0), /* MX6Q_PAD_EIM_DA13__SRC_BT_CFG_13 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA14, 0x0460, 0x014C, 0, 0x0000, 0), /* MX6Q_PAD_EIM_DA14__WEIM_WEIM_DA_A_14 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA14, 0x0460, 0x014C, 1, 0x0000, 0), /* MX6Q_PAD_EIM_DA14__IPU1_DI1_D1_CS */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA14, 0x0460, 0x014C, 2, 0x0000, 0), /* MX6Q_PAD_EIM_DA14__CCM_DI0_EXT_CLK */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA14, 0x0460, 0x014C, 3, 0x0000, 0), /* MX6Q_PAD_EIM_DA14__MIPI_CORE_DPHY_OUT16 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA14, 0x0460, 0x014C, 4, 0x0000, 0), /* MX6Q_PAD_EIM_DA14__SDMA_DEBUG_EVT_CHN_5 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA14, 0x0460, 0x014C, 5, 0x0000, 0), /* MX6Q_PAD_EIM_DA14__GPIO_3_14 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA14, 0x0460, 0x014C, 6, 0x0000, 0), /* MX6Q_PAD_EIM_DA14__TPSMP_HDATA_28 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA14, 0x0460, 0x014C, 7, 0x0000, 0), /* MX6Q_PAD_EIM_DA14__SRC_BT_CFG_14 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA15, 0x0464, 0x0150, 0, 0x0000, 0), /* MX6Q_PAD_EIM_DA15__WEIM_WEIM_DA_A_15 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA15, 0x0464, 0x0150, 1, 0x0000, 0), /* MX6Q_PAD_EIM_DA15__IPU1_DI1_PIN1 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA15, 0x0464, 0x0150, 2, 0x0000, 0), /* MX6Q_PAD_EIM_DA15__IPU1_DI1_PIN4 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA15, 0x0464, 0x0150, 3, 0x0000, 0), /* MX6Q_PAD_EIM_DA15__MIPI_CORE_DPHY_OUT17 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA15, 0x0464, 0x0150, 5, 0x0000, 0), /* MX6Q_PAD_EIM_DA15__GPIO_3_15 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA15, 0x0464, 0x0150, 6, 0x0000, 0), /* MX6Q_PAD_EIM_DA15__TPSMP_HDATA_29 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_DA15, 0x0464, 0x0150, 7, 0x0000, 0), /* MX6Q_PAD_EIM_DA15__SRC_BT_CFG_15 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_WAIT, 0x0468, 0x0154, 0, 0x0000, 0), /* MX6Q_PAD_EIM_WAIT__WEIM_WEIM_WAIT */
-	IMX_PIN_REG(MX6Q_PAD_EIM_WAIT, 0x0468, 0x0154, 1, 0x0000, 0), /* MX6Q_PAD_EIM_WAIT__WEIM_WEIM_DTACK_B */
-	IMX_PIN_REG(MX6Q_PAD_EIM_WAIT, 0x0468, 0x0154, 5, 0x0000, 0), /* MX6Q_PAD_EIM_WAIT__GPIO_5_0 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_WAIT, 0x0468, 0x0154, 6, 0x0000, 0), /* MX6Q_PAD_EIM_WAIT__TPSMP_HDATA_30 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_WAIT, 0x0468, 0x0154, 7, 0x0000, 0), /* MX6Q_PAD_EIM_WAIT__SRC_BT_CFG_25 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_BCLK, 0x046C, 0x0158, 0, 0x0000, 0), /* MX6Q_PAD_EIM_BCLK__WEIM_WEIM_BCLK */
-	IMX_PIN_REG(MX6Q_PAD_EIM_BCLK, 0x046C, 0x0158, 1, 0x0000, 0), /* MX6Q_PAD_EIM_BCLK__IPU1_DI1_PIN16 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_BCLK, 0x046C, 0x0158, 5, 0x0000, 0), /* MX6Q_PAD_EIM_BCLK__GPIO_6_31 */
-	IMX_PIN_REG(MX6Q_PAD_EIM_BCLK, 0x046C, 0x0158, 6, 0x0000, 0), /* MX6Q_PAD_EIM_BCLK__TPSMP_HDATA_31 */
-	IMX_PIN_REG(MX6Q_PAD_DI0_DISP_CLK, 0x0470, 0x015C, 0, 0x0000, 0), /* MX6Q_PAD_DI0_DISP_CLK__IPU1_DI0_DSP_CLK */
-	IMX_PIN_REG(MX6Q_PAD_DI0_DISP_CLK, 0x0470, 0x015C, 1, 0x0000, 0), /* MX6Q_PAD_DI0_DISP_CLK__IPU2_DI0_DSP_CLK */
-	IMX_PIN_REG(MX6Q_PAD_DI0_DISP_CLK, 0x0470, 0x015C, 3, 0x0000, 0), /* MX6Q_PAD_DI0_DISP_CLK__MIPI_CR_DPY_OT28 */
-	IMX_PIN_REG(MX6Q_PAD_DI0_DISP_CLK, 0x0470, 0x015C, 4, 0x0000, 0), /* MX6Q_PAD_DI0_DISP_CLK__SDMA_DBG_CR_STA0 */
-	IMX_PIN_REG(MX6Q_PAD_DI0_DISP_CLK, 0x0470, 0x015C, 5, 0x0000, 0), /* MX6Q_PAD_DI0_DISP_CLK__GPIO_4_16 */
-	IMX_PIN_REG(MX6Q_PAD_DI0_DISP_CLK, 0x0470, 0x015C, 6, 0x0000, 0), /* MX6Q_PAD_DI0_DISP_CLK__MMDC_DEBUG_0 */
-	IMX_PIN_REG(MX6Q_PAD_DI0_PIN15, 0x0474, 0x0160, 0, 0x0000, 0), /* MX6Q_PAD_DI0_PIN15__IPU1_DI0_PIN15 */
-	IMX_PIN_REG(MX6Q_PAD_DI0_PIN15, 0x0474, 0x0160, 1, 0x0000, 0), /* MX6Q_PAD_DI0_PIN15__IPU2_DI0_PIN15 */
-	IMX_PIN_REG(MX6Q_PAD_DI0_PIN15, 0x0474, 0x0160, 2, 0x0000, 0), /* MX6Q_PAD_DI0_PIN15__AUDMUX_AUD6_TXC */
-	IMX_PIN_REG(MX6Q_PAD_DI0_PIN15, 0x0474, 0x0160, 3, 0x0000, 0), /* MX6Q_PAD_DI0_PIN15__MIPI_CR_DPHY_OUT_29 */
-	IMX_PIN_REG(MX6Q_PAD_DI0_PIN15, 0x0474, 0x0160, 4, 0x0000, 0), /* MX6Q_PAD_DI0_PIN15__SDMA_DBG_CORE_STA_1 */
-	IMX_PIN_REG(MX6Q_PAD_DI0_PIN15, 0x0474, 0x0160, 5, 0x0000, 0), /* MX6Q_PAD_DI0_PIN15__GPIO_4_17 */
-	IMX_PIN_REG(MX6Q_PAD_DI0_PIN15, 0x0474, 0x0160, 6, 0x0000, 0), /* MX6Q_PAD_DI0_PIN15__MMDC_MMDC_DEBUG_1 */
-	IMX_PIN_REG(MX6Q_PAD_DI0_PIN2, 0x0478, 0x0164, 0, 0x0000, 0), /* MX6Q_PAD_DI0_PIN2__IPU1_DI0_PIN2 */
-	IMX_PIN_REG(MX6Q_PAD_DI0_PIN2, 0x0478, 0x0164, 1, 0x0000, 0), /* MX6Q_PAD_DI0_PIN2__IPU2_DI0_PIN2 */
-	IMX_PIN_REG(MX6Q_PAD_DI0_PIN2, 0x0478, 0x0164, 2, 0x0000, 0), /* MX6Q_PAD_DI0_PIN2__AUDMUX_AUD6_TXD */
-	IMX_PIN_REG(MX6Q_PAD_DI0_PIN2, 0x0478, 0x0164, 3, 0x0000, 0), /* MX6Q_PAD_DI0_PIN2__MIPI_CR_DPHY_OUT_30 */
-	IMX_PIN_REG(MX6Q_PAD_DI0_PIN2, 0x0478, 0x0164, 4, 0x0000, 0), /* MX6Q_PAD_DI0_PIN2__SDMA_DBG_CORE_STA_2 */
-	IMX_PIN_REG(MX6Q_PAD_DI0_PIN2, 0x0478, 0x0164, 5, 0x0000, 0), /* MX6Q_PAD_DI0_PIN2__GPIO_4_18 */
-	IMX_PIN_REG(MX6Q_PAD_DI0_PIN2, 0x0478, 0x0164, 6, 0x0000, 0), /* MX6Q_PAD_DI0_PIN2__MMDC_DEBUG_2 */
-	IMX_PIN_REG(MX6Q_PAD_DI0_PIN2, 0x0478, 0x0164, 7, 0x0000, 0), /* MX6Q_PAD_DI0_PIN2__PL301_PER1_HADDR_9 */
-	IMX_PIN_REG(MX6Q_PAD_DI0_PIN3, 0x047C, 0x0168, 0, 0x0000, 0), /* MX6Q_PAD_DI0_PIN3__IPU1_DI0_PIN3 */
-	IMX_PIN_REG(MX6Q_PAD_DI0_PIN3, 0x047C, 0x0168, 1, 0x0000, 0), /* MX6Q_PAD_DI0_PIN3__IPU2_DI0_PIN3 */
-	IMX_PIN_REG(MX6Q_PAD_DI0_PIN3, 0x047C, 0x0168, 2, 0x0000, 0), /* MX6Q_PAD_DI0_PIN3__AUDMUX_AUD6_TXFS */
-	IMX_PIN_REG(MX6Q_PAD_DI0_PIN3, 0x047C, 0x0168, 3, 0x0000, 0), /* MX6Q_PAD_DI0_PIN3__MIPI_CORE_DPHY_OUT31 */
-	IMX_PIN_REG(MX6Q_PAD_DI0_PIN3, 0x047C, 0x0168, 4, 0x0000, 0), /* MX6Q_PAD_DI0_PIN3__SDMA_DBG_CORE_STA_3 */
-	IMX_PIN_REG(MX6Q_PAD_DI0_PIN3, 0x047C, 0x0168, 5, 0x0000, 0), /* MX6Q_PAD_DI0_PIN3__GPIO_4_19 */
-	IMX_PIN_REG(MX6Q_PAD_DI0_PIN3, 0x047C, 0x0168, 6, 0x0000, 0), /* MX6Q_PAD_DI0_PIN3__MMDC_MMDC_DEBUG_3 */
-	IMX_PIN_REG(MX6Q_PAD_DI0_PIN3, 0x047C, 0x0168, 7, 0x0000, 0), /* MX6Q_PAD_DI0_PIN3__PL301_PER1_HADDR_10 */
-	IMX_PIN_REG(MX6Q_PAD_DI0_PIN4, 0x0480, 0x016C, 0, 0x0000, 0), /* MX6Q_PAD_DI0_PIN4__IPU1_DI0_PIN4 */
-	IMX_PIN_REG(MX6Q_PAD_DI0_PIN4, 0x0480, 0x016C, 1, 0x0000, 0), /* MX6Q_PAD_DI0_PIN4__IPU2_DI0_PIN4 */
-	IMX_PIN_REG(MX6Q_PAD_DI0_PIN4, 0x0480, 0x016C, 2, 0x0000, 0), /* MX6Q_PAD_DI0_PIN4__AUDMUX_AUD6_RXD */
-	IMX_PIN_REG(MX6Q_PAD_DI0_PIN4, 0x0480, 0x016C, 3, 0x094C, 0), /* MX6Q_PAD_DI0_PIN4__USDHC1_WP */
-	IMX_PIN_REG(MX6Q_PAD_DI0_PIN4, 0x0480, 0x016C, 4, 0x0000, 0), /* MX6Q_PAD_DI0_PIN4__SDMA_DEBUG_YIELD */
-	IMX_PIN_REG(MX6Q_PAD_DI0_PIN4, 0x0480, 0x016C, 5, 0x0000, 0), /* MX6Q_PAD_DI0_PIN4__GPIO_4_20 */
-	IMX_PIN_REG(MX6Q_PAD_DI0_PIN4, 0x0480, 0x016C, 6, 0x0000, 0), /* MX6Q_PAD_DI0_PIN4__MMDC_MMDC_DEBUG_4 */
-	IMX_PIN_REG(MX6Q_PAD_DI0_PIN4, 0x0480, 0x016C, 7, 0x0000, 0), /* MX6Q_PAD_DI0_PIN4__PL301_PER1_HADDR_11 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT0, 0x0484, 0x0170, 0, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT0__IPU1_DISP0_DAT_0 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT0, 0x0484, 0x0170, 1, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT0__IPU2_DISP0_DAT_0 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT0, 0x0484, 0x0170, 2, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT0__ECSPI3_SCLK */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT0, 0x0484, 0x0170, 3, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT0__USDHC1_USDHC_DBG_0 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT0, 0x0484, 0x0170, 4, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT0__SDMA_DBG_CORE_RUN */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT0, 0x0484, 0x0170, 5, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT0__GPIO_4_21 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT0, 0x0484, 0x0170, 6, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT0__MMDC_MMDC_DEBUG_5 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT1, 0x0488, 0x0174, 0, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT1__IPU1_DISP0_DAT_1 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT1, 0x0488, 0x0174, 1, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT1__IPU2_DISP0_DAT_1 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT1, 0x0488, 0x0174, 2, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT1__ECSPI3_MOSI */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT1, 0x0488, 0x0174, 3, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT1__USDHC1_USDHC_DBG_1 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT1, 0x0488, 0x0174, 4, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT1__SDMA_DBG_EVT_CHNSL */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT1, 0x0488, 0x0174, 5, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT1__GPIO_4_22 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT1, 0x0488, 0x0174, 6, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT1__MMDC_DEBUG_6 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT1, 0x0488, 0x0174, 7, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT1__PL301_PER1_HADR_12 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT2, 0x048C, 0x0178, 0, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT2__IPU1_DISP0_DAT_2 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT2, 0x048C, 0x0178, 1, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT2__IPU2_DISP0_DAT_2 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT2, 0x048C, 0x0178, 2, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT2__ECSPI3_MISO */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT2, 0x048C, 0x0178, 3, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT2__USDHC1_USDHC_DBG_2 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT2, 0x048C, 0x0178, 4, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT2__SDMA_DEBUG_MODE */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT2, 0x048C, 0x0178, 5, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT2__GPIO_4_23 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT2, 0x048C, 0x0178, 6, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT2__MMDC_DEBUG_7 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT2, 0x048C, 0x0178, 7, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT2__PL301_PER1_HADR_13 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT3, 0x0490, 0x017C, 0, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT3__IPU1_DISP0_DAT_3 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT3, 0x0490, 0x017C, 1, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT3__IPU2_DISP0_DAT_3 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT3, 0x0490, 0x017C, 2, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT3__ECSPI3_SS0 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT3, 0x0490, 0x017C, 3, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT3__USDHC1_USDHC_DBG_3 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT3, 0x0490, 0x017C, 4, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT3__SDMA_DBG_BUS_ERROR */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT3, 0x0490, 0x017C, 5, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT3__GPIO_4_24 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT3, 0x0490, 0x017C, 6, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT3__MMDC_MMDC_DBG_8 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT3, 0x0490, 0x017C, 7, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT3__PL301_PER1_HADR_14 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT4, 0x0494, 0x0180, 0, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT4__IPU1_DISP0_DAT_4 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT4, 0x0494, 0x0180, 1, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT4__IPU2_DISP0_DAT_4 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT4, 0x0494, 0x0180, 2, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT4__ECSPI3_SS1 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT4, 0x0494, 0x0180, 3, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT4__USDHC1_USDHC_DBG_4 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT4, 0x0494, 0x0180, 4, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT4__SDMA_DEBUG_BUS_RWB */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT4, 0x0494, 0x0180, 5, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT4__GPIO_4_25 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT4, 0x0494, 0x0180, 6, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT4__MMDC_MMDC_DEBUG_9 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT4, 0x0494, 0x0180, 7, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT4__PL301_PER1_HADR_15 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT5, 0x0498, 0x0184, 0, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT5__IPU1_DISP0_DAT_5 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT5, 0x0498, 0x0184, 1, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT5__IPU2_DISP0_DAT_5 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT5, 0x0498, 0x0184, 2, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT5__ECSPI3_SS2 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT5, 0x0498, 0x0184, 3, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT5__AUDMUX_AUD6_RXFS */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT5, 0x0498, 0x0184, 4, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT5__SDMA_DBG_MCH_DMBUS */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT5, 0x0498, 0x0184, 5, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT5__GPIO_4_26 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT5, 0x0498, 0x0184, 6, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT5__MMDC_DEBUG_10 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT5, 0x0498, 0x0184, 7, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT5__PL301_PER1_HADR_16 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT6, 0x049C, 0x0188, 0, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT6__IPU1_DISP0_DAT_6 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT6, 0x049C, 0x0188, 1, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT6__IPU2_DISP0_DAT_6 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT6, 0x049C, 0x0188, 2, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT6__ECSPI3_SS3 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT6, 0x049C, 0x0188, 3, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT6__AUDMUX_AUD6_RXC */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT6, 0x049C, 0x0188, 4, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT6__SDMA_DBG_RTBUF_WRT */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT6, 0x049C, 0x0188, 5, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT6__GPIO_4_27 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT6, 0x049C, 0x0188, 6, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT6__MMDC_DEBUG_11 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT6, 0x049C, 0x0188, 7, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT6__PL301_PER1_HADR_17 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT7, 0x04A0, 0x018C, 0, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT7__IPU1_DISP0_DAT_7 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT7, 0x04A0, 0x018C, 1, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT7__IPU2_DISP0_DAT_7 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT7, 0x04A0, 0x018C, 2, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT7__ECSPI3_RDY */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT7, 0x04A0, 0x018C, 3, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT7__USDHC1_USDHC_DBG_5 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT7, 0x04A0, 0x018C, 4, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT7__SDMA_DBG_EVT_CHN_0 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT7, 0x04A0, 0x018C, 5, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT7__GPIO_4_28 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT7, 0x04A0, 0x018C, 6, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT7__MMDC_DEBUG_12 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT7, 0x04A0, 0x018C, 7, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT7__PL301_PER1_HADR_18 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT8, 0x04A4, 0x0190, 0, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT8__IPU1_DISP0_DAT_8 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT8, 0x04A4, 0x0190, 1, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT8__IPU2_DISP0_DAT_8 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT8, 0x04A4, 0x0190, 2, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT8__PWM1_PWMO */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT8, 0x04A4, 0x0190, 3, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT8__WDOG1_WDOG_B */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT8, 0x04A4, 0x0190, 4, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT8__SDMA_DBG_EVT_CHN_1 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT8, 0x04A4, 0x0190, 5, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT8__GPIO_4_29 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT8, 0x04A4, 0x0190, 6, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT8__MMDC_DEBUG_13 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT8, 0x04A4, 0x0190, 7, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT8__PL301_PER1_HADR_19 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT9, 0x04A8, 0x0194, 0, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT9__IPU1_DISP0_DAT_9 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT9, 0x04A8, 0x0194, 1, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT9__IPU2_DISP0_DAT_9 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT9, 0x04A8, 0x0194, 2, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT9__PWM2_PWMO */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT9, 0x04A8, 0x0194, 3, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT9__WDOG2_WDOG_B */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT9, 0x04A8, 0x0194, 4, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT9__SDMA_DBG_EVT_CHN_2 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT9, 0x04A8, 0x0194, 5, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT9__GPIO_4_30 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT9, 0x04A8, 0x0194, 6, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT9__MMDC_DEBUG_14 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT9, 0x04A8, 0x0194, 7, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT9__PL301_PER1_HADR_20 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT10, 0x04AC, 0x0198, 0, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT10__IPU1_DISP0_DAT_10 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT10, 0x04AC, 0x0198, 1, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT10__IPU2_DISP0_DAT_10 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT10, 0x04AC, 0x0198, 3, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT10__USDHC1_DBG_6 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT10, 0x04AC, 0x0198, 4, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT10__SDMA_DBG_EVT_CHN3 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT10, 0x04AC, 0x0198, 5, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT10__GPIO_4_31 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT10, 0x04AC, 0x0198, 6, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT10__MMDC_DEBUG_15 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT10, 0x04AC, 0x0198, 7, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT10__PL301_PER1_HADR21 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT11, 0x04B0, 0x019C, 0, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT11__IPU1_DISP0_DAT_11 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT11, 0x04B0, 0x019C, 1, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT11__IPU2_DISP0_DAT_11 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT11, 0x04B0, 0x019C, 3, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT11__USDHC1_USDHC_DBG7 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT11, 0x04B0, 0x019C, 4, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT11__SDMA_DBG_EVT_CHN4 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT11, 0x04B0, 0x019C, 5, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT11__GPIO_5_5 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT11, 0x04B0, 0x019C, 6, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT11__MMDC_DEBUG_16 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT11, 0x04B0, 0x019C, 7, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT11__PL301_PER1_HADR22 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT12, 0x04B4, 0x01A0, 0, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT12__IPU1_DISP0_DAT_12 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT12, 0x04B4, 0x01A0, 1, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT12__IPU2_DISP0_DAT_12 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT12, 0x04B4, 0x01A0, 3, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT12__RESERVED_RESERVED */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT12, 0x04B4, 0x01A0, 4, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT12__SDMA_DBG_EVT_CHN5 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT12, 0x04B4, 0x01A0, 5, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT12__GPIO_5_6 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT12, 0x04B4, 0x01A0, 6, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT12__MMDC_DEBUG_17 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT12, 0x04B4, 0x01A0, 7, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT12__PL301_PER1_HADR23 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT13, 0x04B8, 0x01A4, 0, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT13__IPU1_DISP0_DAT_13 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT13, 0x04B8, 0x01A4, 1, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT13__IPU2_DISP0_DAT_13 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT13, 0x04B8, 0x01A4, 3, 0x07D8, 1), /* MX6Q_PAD_DISP0_DAT13__AUDMUX_AUD5_RXFS */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT13, 0x04B8, 0x01A4, 4, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT13__SDMA_DBG_EVT_CHN0 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT13, 0x04B8, 0x01A4, 5, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT13__GPIO_5_7 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT13, 0x04B8, 0x01A4, 6, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT13__MMDC_DEBUG_18 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT13, 0x04B8, 0x01A4, 7, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT13__PL301_PER1_HADR24 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT14, 0x04BC, 0x01A8, 0, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT14__IPU1_DISP0_DAT_14 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT14, 0x04BC, 0x01A8, 1, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT14__IPU2_DISP0_DAT_14 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT14, 0x04BC, 0x01A8, 3, 0x07D4, 1), /* MX6Q_PAD_DISP0_DAT14__AUDMUX_AUD5_RXC */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT14, 0x04BC, 0x01A8, 4, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT14__SDMA_DBG_EVT_CHN1 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT14, 0x04BC, 0x01A8, 5, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT14__GPIO_5_8 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT14, 0x04BC, 0x01A8, 6, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT14__MMDC_DEBUG_19 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT15, 0x04C0, 0x01AC, 0, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT15__IPU1_DISP0_DAT_15 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT15, 0x04C0, 0x01AC, 1, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT15__IPU2_DISP0_DAT_15 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT15, 0x04C0, 0x01AC, 2, 0x0804, 1), /* MX6Q_PAD_DISP0_DAT15__ECSPI1_SS1 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT15, 0x04C0, 0x01AC, 3, 0x0820, 1), /* MX6Q_PAD_DISP0_DAT15__ECSPI2_SS1 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT15, 0x04C0, 0x01AC, 4, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT15__SDMA_DBG_EVT_CHN2 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT15, 0x04C0, 0x01AC, 5, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT15__GPIO_5_9 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT15, 0x04C0, 0x01AC, 6, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT15__MMDC_DEBUG_20 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT15, 0x04C0, 0x01AC, 7, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT15__PL301_PER1_HADR25 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT16, 0x04C4, 0x01B0, 0, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT16__IPU1_DISP0_DAT_16 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT16, 0x04C4, 0x01B0, 1, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT16__IPU2_DISP0_DAT_16 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT16, 0x04C4, 0x01B0, 2, 0x0818, 1), /* MX6Q_PAD_DISP0_DAT16__ECSPI2_MOSI */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT16, 0x04C4, 0x01B0, 3, 0x07DC, 0), /* MX6Q_PAD_DISP0_DAT16__AUDMUX_AUD5_TXC */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT16, 0x04C4, 0x01B0, 4, 0x090C, 0), /* MX6Q_PAD_DISP0_DAT16__SDMA_EXT_EVENT_0 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT16, 0x04C4, 0x01B0, 5, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT16__GPIO_5_10 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT16, 0x04C4, 0x01B0, 6, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT16__MMDC_DEBUG_21 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT16, 0x04C4, 0x01B0, 7, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT16__PL301_PER1_HADR26 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT17, 0x04C8, 0x01B4, 0, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT17__IPU1_DISP0_DAT_17 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT17, 0x04C8, 0x01B4, 1, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT17__IPU2_DISP0_DAT_17 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT17, 0x04C8, 0x01B4, 2, 0x0814, 1), /* MX6Q_PAD_DISP0_DAT17__ECSPI2_MISO */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT17, 0x04C8, 0x01B4, 3, 0x07D0, 0), /* MX6Q_PAD_DISP0_DAT17__AUDMUX_AUD5_TXD */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT17, 0x04C8, 0x01B4, 4, 0x0910, 0), /* MX6Q_PAD_DISP0_DAT17__SDMA_EXT_EVENT_1 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT17, 0x04C8, 0x01B4, 5, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT17__GPIO_5_11 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT17, 0x04C8, 0x01B4, 6, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT17__MMDC_DEBUG_22 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT17, 0x04C8, 0x01B4, 7, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT17__PL301_PER1_HADR27 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT18, 0x04CC, 0x01B8, 0, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT18__IPU1_DISP0_DAT_18 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT18, 0x04CC, 0x01B8, 1, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT18__IPU2_DISP0_DAT_18 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT18, 0x04CC, 0x01B8, 2, 0x081C, 1), /* MX6Q_PAD_DISP0_DAT18__ECSPI2_SS0 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT18, 0x04CC, 0x01B8, 3, 0x07E0, 0), /* MX6Q_PAD_DISP0_DAT18__AUDMUX_AUD5_TXFS */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT18, 0x04CC, 0x01B8, 4, 0x07C0, 0), /* MX6Q_PAD_DISP0_DAT18__AUDMUX_AUD4_RXFS */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT18, 0x04CC, 0x01B8, 5, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT18__GPIO_5_12 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT18, 0x04CC, 0x01B8, 6, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT18__MMDC_DEBUG_23 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT18, 0x04CC, 0x01B8, 7, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT18__WEIM_WEIM_CS_2 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT19, 0x04D0, 0x01BC, 0, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT19__IPU1_DISP0_DAT_19 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT19, 0x04D0, 0x01BC, 1, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT19__IPU2_DISP0_DAT_19 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT19, 0x04D0, 0x01BC, 2, 0x0810, 1), /* MX6Q_PAD_DISP0_DAT19__ECSPI2_SCLK */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT19, 0x04D0, 0x01BC, 3, 0x07CC, 0), /* MX6Q_PAD_DISP0_DAT19__AUDMUX_AUD5_RXD */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT19, 0x04D0, 0x01BC, 4, 0x07BC, 0), /* MX6Q_PAD_DISP0_DAT19__AUDMUX_AUD4_RXC */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT19, 0x04D0, 0x01BC, 5, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT19__GPIO_5_13 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT19, 0x04D0, 0x01BC, 6, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT19__MMDC_DEBUG_24 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT19, 0x04D0, 0x01BC, 7, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT19__WEIM_WEIM_CS_3 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT20, 0x04D4, 0x01C0, 0, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT20__IPU1_DISP0_DAT_20 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT20, 0x04D4, 0x01C0, 1, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT20__IPU2_DISP0_DAT_20 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT20, 0x04D4, 0x01C0, 2, 0x07F4, 1), /* MX6Q_PAD_DISP0_DAT20__ECSPI1_SCLK */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT20, 0x04D4, 0x01C0, 3, 0x07C4, 0), /* MX6Q_PAD_DISP0_DAT20__AUDMUX_AUD4_TXC */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT20, 0x04D4, 0x01C0, 4, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT20__SDMA_DBG_EVT_CHN7 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT20, 0x04D4, 0x01C0, 5, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT20__GPIO_5_14 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT20, 0x04D4, 0x01C0, 6, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT20__MMDC_DEBUG_25 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT20, 0x04D4, 0x01C0, 7, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT20__PL301_PER1_HADR28 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT21, 0x04D8, 0x01C4, 0, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT21__IPU1_DISP0_DAT_21 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT21, 0x04D8, 0x01C4, 1, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT21__IPU2_DISP0_DAT_21 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT21, 0x04D8, 0x01C4, 2, 0x07FC, 1), /* MX6Q_PAD_DISP0_DAT21__ECSPI1_MOSI */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT21, 0x04D8, 0x01C4, 3, 0x07B8, 1), /* MX6Q_PAD_DISP0_DAT21__AUDMUX_AUD4_TXD */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT21, 0x04D8, 0x01C4, 4, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT21__SDMA_DBG_BUS_DEV0 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT21, 0x04D8, 0x01C4, 5, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT21__GPIO_5_15 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT21, 0x04D8, 0x01C4, 6, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT21__MMDC_DEBUG_26 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT21, 0x04D8, 0x01C4, 7, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT21__PL301_PER1_HADR29 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT22, 0x04DC, 0x01C8, 0, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT22__IPU1_DISP0_DAT_22 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT22, 0x04DC, 0x01C8, 1, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT22__IPU2_DISP0_DAT_22 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT22, 0x04DC, 0x01C8, 2, 0x07F8, 1), /* MX6Q_PAD_DISP0_DAT22__ECSPI1_MISO */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT22, 0x04DC, 0x01C8, 3, 0x07C8, 1), /* MX6Q_PAD_DISP0_DAT22__AUDMUX_AUD4_TXFS */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT22, 0x04DC, 0x01C8, 4, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT22__SDMA_DBG_BUS_DEV1 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT22, 0x04DC, 0x01C8, 5, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT22__GPIO_5_16 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT22, 0x04DC, 0x01C8, 6, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT22__MMDC_DEBUG_27 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT22, 0x04DC, 0x01C8, 7, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT22__PL301_PER1_HADR30 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT23, 0x04E0, 0x01CC, 0, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT23__IPU1_DISP0_DAT_23 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT23, 0x04E0, 0x01CC, 1, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT23__IPU2_DISP0_DAT_23 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT23, 0x04E0, 0x01CC, 2, 0x0800, 1), /* MX6Q_PAD_DISP0_DAT23__ECSPI1_SS0 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT23, 0x04E0, 0x01CC, 3, 0x07B4, 1), /* MX6Q_PAD_DISP0_DAT23__AUDMUX_AUD4_RXD */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT23, 0x04E0, 0x01CC, 4, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT23__SDMA_DBG_BUS_DEV2 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT23, 0x04E0, 0x01CC, 5, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT23__GPIO_5_17 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT23, 0x04E0, 0x01CC, 6, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT23__MMDC_DEBUG_28 */
-	IMX_PIN_REG(MX6Q_PAD_DISP0_DAT23, 0x04E0, 0x01CC, 7, 0x0000, 0), /* MX6Q_PAD_DISP0_DAT23__PL301_PER1_HADR31 */
-	IMX_PIN_REG(MX6Q_PAD_ENET_MDIO, 0x04E4, 0x01D0, 0, 0x0000, 0), /* MX6Q_PAD_ENET_MDIO__RESERVED_RESERVED */
-	IMX_PIN_REG(MX6Q_PAD_ENET_MDIO, 0x04E4, 0x01D0, 1, 0x0840, 0), /* MX6Q_PAD_ENET_MDIO__ENET_MDIO */
-	IMX_PIN_REG(MX6Q_PAD_ENET_MDIO, 0x04E4, 0x01D0, 2, 0x086C, 0), /* MX6Q_PAD_ENET_MDIO__ESAI1_SCKR */
-	IMX_PIN_REG(MX6Q_PAD_ENET_MDIO, 0x04E4, 0x01D0, 3, 0x0000, 0), /* MX6Q_PAD_ENET_MDIO__SDMA_DEBUG_BUS_DEV3 */
-	IMX_PIN_REG(MX6Q_PAD_ENET_MDIO, 0x04E4, 0x01D0, 4, 0x0000, 0), /* MX6Q_PAD_ENET_MDIO__ENET_1588_EVT1_OUT */
-	IMX_PIN_REG(MX6Q_PAD_ENET_MDIO, 0x04E4, 0x01D0, 5, 0x0000, 0), /* MX6Q_PAD_ENET_MDIO__GPIO_1_22 */
-	IMX_PIN_REG(MX6Q_PAD_ENET_MDIO, 0x04E4, 0x01D0, 6, 0x0000, 0), /* MX6Q_PAD_ENET_MDIO__SPDIF_PLOCK */
-	IMX_PIN_REG(MX6Q_PAD_ENET_REF_CLK, 0x04E8, 0x01D4, 0, 0x0000, 0), /* MX6Q_PAD_ENET_REF_CLK__RESERVED_RSRVED */
-	IMX_PIN_REG(MX6Q_PAD_ENET_REF_CLK, 0x04E8, 0x01D4, 1, 0x0000, 0), /* MX6Q_PAD_ENET_REF_CLK__ENET_TX_CLK */
-	IMX_PIN_REG(MX6Q_PAD_ENET_REF_CLK, 0x04E8, 0x01D4, 2, 0x085C, 0), /* MX6Q_PAD_ENET_REF_CLK__ESAI1_FSR */
-	IMX_PIN_REG(MX6Q_PAD_ENET_REF_CLK, 0x04E8, 0x01D4, 3, 0x0000, 0), /* MX6Q_PAD_ENET_REF_CLK__SDMA_DBGBUS_DEV4 */
-	IMX_PIN_REG(MX6Q_PAD_ENET_REF_CLK, 0x04E8, 0x01D4, 5, 0x0000, 0), /* MX6Q_PAD_ENET_REF_CLK__GPIO_1_23 */
-	IMX_PIN_REG(MX6Q_PAD_ENET_REF_CLK, 0x04E8, 0x01D4, 6, 0x0000, 0), /* MX6Q_PAD_ENET_REF_CLK__SPDIF_SRCLK */
-	IMX_PIN_REG(MX6Q_PAD_ENET_REF_CLK, 0x04E8, 0x01D4, 7, 0x0000, 0), /* MX6Q_PAD_ENET_REF_CLK__USBPHY1_RX_SQH */
-	IMX_PIN_REG(MX6Q_PAD_ENET_RX_ER, 0x04EC, 0x01D8, 1, 0x0000, 0), /* MX6Q_PAD_ENET_RX_ER__ENET_RX_ER */
-	IMX_PIN_REG(MX6Q_PAD_ENET_RX_ER, 0x04EC, 0x01D8, 2, 0x0864, 0), /* MX6Q_PAD_ENET_RX_ER__ESAI1_HCKR */
-	IMX_PIN_REG(MX6Q_PAD_ENET_RX_ER, 0x04EC, 0x01D8, 3, 0x0914, 1), /* MX6Q_PAD_ENET_RX_ER__SPDIF_IN1 */
-	IMX_PIN_REG(MX6Q_PAD_ENET_RX_ER, 0x04EC, 0x01D8, 4, 0x0000, 0), /* MX6Q_PAD_ENET_RX_ER__ENET_1588_EVT2_OUT */
-	IMX_PIN_REG(MX6Q_PAD_ENET_RX_ER, 0x04EC, 0x01D8, 5, 0x0000, 0), /* MX6Q_PAD_ENET_RX_ER__GPIO_1_24 */
-	IMX_PIN_REG(MX6Q_PAD_ENET_RX_ER, 0x04EC, 0x01D8, 6, 0x0000, 0), /* MX6Q_PAD_ENET_RX_ER__PHY_TDI */
-	IMX_PIN_REG(MX6Q_PAD_ENET_RX_ER, 0x04EC, 0x01D8, 7, 0x0000, 0), /* MX6Q_PAD_ENET_RX_ER__USBPHY1_RX_HS_RXD */
-	IMX_PIN_REG(MX6Q_PAD_ENET_CRS_DV, 0x04F0, 0x01DC, 0, 0x0000, 0), /* MX6Q_PAD_ENET_CRS_DV__RESERVED_RSRVED */
-	IMX_PIN_REG(MX6Q_PAD_ENET_CRS_DV, 0x04F0, 0x01DC, 1, 0x0858, 1), /* MX6Q_PAD_ENET_CRS_DV__ENET_RX_EN */
-	IMX_PIN_REG(MX6Q_PAD_ENET_CRS_DV, 0x04F0, 0x01DC, 2, 0x0870, 0), /* MX6Q_PAD_ENET_CRS_DV__ESAI1_SCKT */
-	IMX_PIN_REG(MX6Q_PAD_ENET_CRS_DV, 0x04F0, 0x01DC, 3, 0x0918, 1), /* MX6Q_PAD_ENET_CRS_DV__SPDIF_EXTCLK */
-	IMX_PIN_REG(MX6Q_PAD_ENET_CRS_DV, 0x04F0, 0x01DC, 5, 0x0000, 0), /* MX6Q_PAD_ENET_CRS_DV__GPIO_1_25 */
-	IMX_PIN_REG(MX6Q_PAD_ENET_CRS_DV, 0x04F0, 0x01DC, 6, 0x0000, 0), /* MX6Q_PAD_ENET_CRS_DV__PHY_TDO */
-	IMX_PIN_REG(MX6Q_PAD_ENET_CRS_DV, 0x04F0, 0x01DC, 7, 0x0000, 0), /* MX6Q_PAD_ENET_CRS_DV__USBPHY1_RX_FS_RXD */
-	IMX_PIN_REG(MX6Q_PAD_ENET_RXD1, 0x04F4, 0x01E0, 0, 0x0908, 0), /* MX6Q_PAD_ENET_RXD1__MLB_MLBSIG */
-	IMX_PIN_REG(MX6Q_PAD_ENET_RXD1, 0x04F4, 0x01E0, 1, 0x084C, 1), /* MX6Q_PAD_ENET_RXD1__ENET_RDATA_1 */
-	IMX_PIN_REG(MX6Q_PAD_ENET_RXD1, 0x04F4, 0x01E0, 2, 0x0860, 0), /* MX6Q_PAD_ENET_RXD1__ESAI1_FST */
-	IMX_PIN_REG(MX6Q_PAD_ENET_RXD1, 0x04F4, 0x01E0, 4, 0x0000, 0), /* MX6Q_PAD_ENET_RXD1__ENET_1588_EVT3_OUT */
-	IMX_PIN_REG(MX6Q_PAD_ENET_RXD1, 0x04F4, 0x01E0, 5, 0x0000, 0), /* MX6Q_PAD_ENET_RXD1__GPIO_1_26 */
-	IMX_PIN_REG(MX6Q_PAD_ENET_RXD1, 0x04F4, 0x01E0, 6, 0x0000, 0), /* MX6Q_PAD_ENET_RXD1__PHY_TCK */
-	IMX_PIN_REG(MX6Q_PAD_ENET_RXD1, 0x04F4, 0x01E0, 7, 0x0000, 0), /* MX6Q_PAD_ENET_RXD1__USBPHY1_RX_DISCON */
-	IMX_PIN_REG(MX6Q_PAD_ENET_RXD0, 0x04F8, 0x01E4, 0, 0x0000, 0), /* MX6Q_PAD_ENET_RXD0__OSC32K_32K_OUT */
-	IMX_PIN_REG(MX6Q_PAD_ENET_RXD0, 0x04F8, 0x01E4, 1, 0x0848, 1), /* MX6Q_PAD_ENET_RXD0__ENET_RDATA_0 */
-	IMX_PIN_REG(MX6Q_PAD_ENET_RXD0, 0x04F8, 0x01E4, 2, 0x0868, 0), /* MX6Q_PAD_ENET_RXD0__ESAI1_HCKT */
-	IMX_PIN_REG(MX6Q_PAD_ENET_RXD0, 0x04F8, 0x01E4, 3, 0x0000, 0), /* MX6Q_PAD_ENET_RXD0__SPDIF_OUT1 */
-	IMX_PIN_REG(MX6Q_PAD_ENET_RXD0, 0x04F8, 0x01E4, 5, 0x0000, 0), /* MX6Q_PAD_ENET_RXD0__GPIO_1_27 */
-	IMX_PIN_REG(MX6Q_PAD_ENET_RXD0, 0x04F8, 0x01E4, 6, 0x0000, 0), /* MX6Q_PAD_ENET_RXD0__PHY_TMS */
-	IMX_PIN_REG(MX6Q_PAD_ENET_RXD0, 0x04F8, 0x01E4, 7, 0x0000, 0), /* MX6Q_PAD_ENET_RXD0__USBPHY1_PLL_CK20DIV */
-	IMX_PIN_REG(MX6Q_PAD_ENET_TX_EN, 0x04FC, 0x01E8, 0, 0x0000, 0), /* MX6Q_PAD_ENET_TX_EN__RESERVED_RSRVED */
-	IMX_PIN_REG(MX6Q_PAD_ENET_TX_EN, 0x04FC, 0x01E8, 1, 0x0000, 0), /* MX6Q_PAD_ENET_TX_EN__ENET_TX_EN */
-	IMX_PIN_REG(MX6Q_PAD_ENET_TX_EN, 0x04FC, 0x01E8, 2, 0x0880, 0), /* MX6Q_PAD_ENET_TX_EN__ESAI1_TX3_RX2 */
-	IMX_PIN_REG(MX6Q_PAD_ENET_TX_EN, 0x04FC, 0x01E8, 5, 0x0000, 0), /* MX6Q_PAD_ENET_TX_EN__GPIO_1_28 */
-	IMX_PIN_REG(MX6Q_PAD_ENET_TX_EN, 0x04FC, 0x01E8, 6, 0x0000, 0), /* MX6Q_PAD_ENET_TX_EN__SATA_PHY_TDI */
-	IMX_PIN_REG(MX6Q_PAD_ENET_TX_EN, 0x04FC, 0x01E8, 7, 0x0000, 0), /* MX6Q_PAD_ENET_TX_EN__USBPHY2_RX_SQH */
-	IMX_PIN_REG(MX6Q_PAD_ENET_TXD1, 0x0500, 0x01EC, 0, 0x0900, 0), /* MX6Q_PAD_ENET_TXD1__MLB_MLBCLK */
-	IMX_PIN_REG(MX6Q_PAD_ENET_TXD1, 0x0500, 0x01EC, 1, 0x0000, 0), /* MX6Q_PAD_ENET_TXD1__ENET_TDATA_1 */
-	IMX_PIN_REG(MX6Q_PAD_ENET_TXD1, 0x0500, 0x01EC, 2, 0x087C, 0), /* MX6Q_PAD_ENET_TXD1__ESAI1_TX2_RX3 */
-	IMX_PIN_REG(MX6Q_PAD_ENET_TXD1, 0x0500, 0x01EC, 4, 0x0000, 0), /* MX6Q_PAD_ENET_TXD1__ENET_1588_EVENT0_IN */
-	IMX_PIN_REG(MX6Q_PAD_ENET_TXD1, 0x0500, 0x01EC, 5, 0x0000, 0), /* MX6Q_PAD_ENET_TXD1__GPIO_1_29 */
-	IMX_PIN_REG(MX6Q_PAD_ENET_TXD1, 0x0500, 0x01EC, 6, 0x0000, 0), /* MX6Q_PAD_ENET_TXD1__SATA_PHY_TDO */
-	IMX_PIN_REG(MX6Q_PAD_ENET_TXD1, 0x0500, 0x01EC, 7, 0x0000, 0), /* MX6Q_PAD_ENET_TXD1__USBPHY2_RX_HS_RXD */
-	IMX_PIN_REG(MX6Q_PAD_ENET_TXD0, 0x0504, 0x01F0, 0, 0x0000, 0), /* MX6Q_PAD_ENET_TXD0__RESERVED_RSRVED */
-	IMX_PIN_REG(MX6Q_PAD_ENET_TXD0, 0x0504, 0x01F0, 1, 0x0000, 0), /* MX6Q_PAD_ENET_TXD0__ENET_TDATA_0 */
-	IMX_PIN_REG(MX6Q_PAD_ENET_TXD0, 0x0504, 0x01F0, 2, 0x0884, 0), /* MX6Q_PAD_ENET_TXD0__ESAI1_TX4_RX1 */
-	IMX_PIN_REG(MX6Q_PAD_ENET_TXD0, 0x0504, 0x01F0, 5, 0x0000, 0), /* MX6Q_PAD_ENET_TXD0__GPIO_1_30 */
-	IMX_PIN_REG(MX6Q_PAD_ENET_TXD0, 0x0504, 0x01F0, 6, 0x0000, 0), /* MX6Q_PAD_ENET_TXD0__SATA_PHY_TCK */
-	IMX_PIN_REG(MX6Q_PAD_ENET_TXD0, 0x0504, 0x01F0, 7, 0x0000, 0), /* MX6Q_PAD_ENET_TXD0__USBPHY2_RX_FS_RXD */
-	IMX_PIN_REG(MX6Q_PAD_ENET_MDC, 0x0508, 0x01F4, 0, 0x0904, 0), /* MX6Q_PAD_ENET_MDC__MLB_MLBDAT */
-	IMX_PIN_REG(MX6Q_PAD_ENET_MDC, 0x0508, 0x01F4, 1, 0x0000, 0), /* MX6Q_PAD_ENET_MDC__ENET_MDC */
-	IMX_PIN_REG(MX6Q_PAD_ENET_MDC, 0x0508, 0x01F4, 2, 0x0888, 0), /* MX6Q_PAD_ENET_MDC__ESAI1_TX5_RX0 */
-	IMX_PIN_REG(MX6Q_PAD_ENET_MDC, 0x0508, 0x01F4, 4, 0x0000, 0), /* MX6Q_PAD_ENET_MDC__ENET_1588_EVENT1_IN */
-	IMX_PIN_REG(MX6Q_PAD_ENET_MDC, 0x0508, 0x01F4, 5, 0x0000, 0), /* MX6Q_PAD_ENET_MDC__GPIO_1_31 */
-	IMX_PIN_REG(MX6Q_PAD_ENET_MDC, 0x0508, 0x01F4, 6, 0x0000, 0), /* MX6Q_PAD_ENET_MDC__SATA_PHY_TMS */
-	IMX_PIN_REG(MX6Q_PAD_ENET_MDC, 0x0508, 0x01F4, 7, 0x0000, 0), /* MX6Q_PAD_ENET_MDC__USBPHY2_RX_DISCON */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D40, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D40__MMDC_DRAM_D_40 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D41, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D41__MMDC_DRAM_D_41 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D42, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D42__MMDC_DRAM_D_42 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D43, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D43__MMDC_DRAM_D_43 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D44, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D44__MMDC_DRAM_D_44 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D45, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D45__MMDC_DRAM_D_45 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D46, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D46__MMDC_DRAM_D_46 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D47, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D47__MMDC_DRAM_D_47 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_SDQS5, 0x050C, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_SDQS5__MMDC_DRAM_SDQS_5 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_DQM5, 0x0510, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_DQM5__MMDC_DRAM_DQM_5 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D32, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D32__MMDC_DRAM_D_32 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D33, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D33__MMDC_DRAM_D_33 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D34, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D34__MMDC_DRAM_D_34 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D35, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D35__MMDC_DRAM_D_35 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D36, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D36__MMDC_DRAM_D_36 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D37, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D37__MMDC_DRAM_D_37 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D38, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D38__MMDC_DRAM_D_38 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D39, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D39__MMDC_DRAM_D_39 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_DQM4, 0x0514, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_DQM4__MMDC_DRAM_DQM_4 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_SDQS4, 0x0518, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_SDQS4__MMDC_DRAM_SDQS_4 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D24, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D24__MMDC_DRAM_D_24 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D25, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D25__MMDC_DRAM_D_25 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D26, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D26__MMDC_DRAM_D_26 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D27, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D27__MMDC_DRAM_D_27 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D28, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D28__MMDC_DRAM_D_28 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D29, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D29__MMDC_DRAM_D_29 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_SDQS3, 0x051C, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_SDQS3__MMDC_DRAM_SDQS_3 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D30, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D30__MMDC_DRAM_D_30 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D31, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D31__MMDC_DRAM_D_31 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_DQM3, 0x0520, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_DQM3__MMDC_DRAM_DQM_3 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D16, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D16__MMDC_DRAM_D_16 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D17, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D17__MMDC_DRAM_D_17 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D18, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D18__MMDC_DRAM_D_18 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D19, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D19__MMDC_DRAM_D_19 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D20, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D20__MMDC_DRAM_D_20 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D21, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D21__MMDC_DRAM_D_21 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D22, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D22__MMDC_DRAM_D_22 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_SDQS2, 0x0524, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_SDQS2__MMDC_DRAM_SDQS_2 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D23, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D23__MMDC_DRAM_D_23 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_DQM2, 0x0528, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_DQM2__MMDC_DRAM_DQM_2 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_A0, 0x052C, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_A0__MMDC_DRAM_A_0 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_A1, 0x0530, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_A1__MMDC_DRAM_A_1 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_A2, 0x0534, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_A2__MMDC_DRAM_A_2 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_A3, 0x0538, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_A3__MMDC_DRAM_A_3 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_A4, 0x053C, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_A4__MMDC_DRAM_A_4 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_A5, 0x0540, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_A5__MMDC_DRAM_A_5 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_A6, 0x0544, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_A6__MMDC_DRAM_A_6 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_A7, 0x0548, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_A7__MMDC_DRAM_A_7 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_A8, 0x054C, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_A8__MMDC_DRAM_A_8 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_A9, 0x0550, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_A9__MMDC_DRAM_A_9 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_A10, 0x0554, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_A10__MMDC_DRAM_A_10 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_A11, 0x0558, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_A11__MMDC_DRAM_A_11 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_A12, 0x055C, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_A12__MMDC_DRAM_A_12 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_A13, 0x0560, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_A13__MMDC_DRAM_A_13 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_A14, 0x0564, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_A14__MMDC_DRAM_A_14 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_A15, 0x0568, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_A15__MMDC_DRAM_A_15 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_CAS, 0x056C, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_CAS__MMDC_DRAM_CAS */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_CS0, 0x0570, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_CS0__MMDC_DRAM_CS_0 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_CS1, 0x0574, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_CS1__MMDC_DRAM_CS_1 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_RAS, 0x0578, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_RAS__MMDC_DRAM_RAS */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_RESET, 0x057C, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_RESET__MMDC_DRAM_RESET */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_SDBA0, 0x0580, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_SDBA0__MMDC_DRAM_SDBA_0 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_SDBA1, 0x0584, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_SDBA1__MMDC_DRAM_SDBA_1 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_SDCLK_0, 0x0588, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_SDCLK_0__MMDC_DRAM_SDCLK0 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_SDBA2, 0x058C, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_SDBA2__MMDC_DRAM_SDBA_2 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_SDCKE0, 0x0590, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_SDCKE0__MMDC_DRAM_SDCKE_0 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_SDCLK_1, 0x0594, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_SDCLK_1__MMDC_DRAM_SDCLK1 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_SDCKE1, 0x0598, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_SDCKE1__MMDC_DRAM_SDCKE_1 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_SDODT0, 0x059C, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_SDODT0__MMDC_DRAM_ODT_0 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_SDODT1, 0x05A0, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_SDODT1__MMDC_DRAM_ODT_1 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_SDWE, 0x05A4, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_SDWE__MMDC_DRAM_SDWE */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D0, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D0__MMDC_DRAM_D_0 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D1, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D1__MMDC_DRAM_D_1 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D2, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D2__MMDC_DRAM_D_2 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D3, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D3__MMDC_DRAM_D_3 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D4, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D4__MMDC_DRAM_D_4 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D5, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D5__MMDC_DRAM_D_5 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_SDQS0, 0x05A8, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_SDQS0__MMDC_DRAM_SDQS_0 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D6, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D6__MMDC_DRAM_D_6 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D7, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D7__MMDC_DRAM_D_7 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_DQM0, 0x05AC, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_DQM0__MMDC_DRAM_DQM_0 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D8, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D8__MMDC_DRAM_D_8 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D9, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D9__MMDC_DRAM_D_9 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D10, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D10__MMDC_DRAM_D_10 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D11, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D11__MMDC_DRAM_D_11 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D12, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D12__MMDC_DRAM_D_12 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D13, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D13__MMDC_DRAM_D_13 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D14, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D14__MMDC_DRAM_D_14 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_SDQS1, 0x05B0, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_SDQS1__MMDC_DRAM_SDQS_1 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D15, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D15__MMDC_DRAM_D_15 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_DQM1, 0x05B4, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_DQM1__MMDC_DRAM_DQM_1 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D48, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D48__MMDC_DRAM_D_48 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D49, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D49__MMDC_DRAM_D_49 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D50, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D50__MMDC_DRAM_D_50 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D51, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D51__MMDC_DRAM_D_51 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D52, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D52__MMDC_DRAM_D_52 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D53, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D53__MMDC_DRAM_D_53 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D54, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D54__MMDC_DRAM_D_54 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D55, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D55__MMDC_DRAM_D_55 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_SDQS6, 0x05B8, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_SDQS6__MMDC_DRAM_SDQS_6 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_DQM6, 0x05BC, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_DQM6__MMDC_DRAM_DQM_6 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D56, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D56__MMDC_DRAM_D_56 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_SDQS7, 0x05C0, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_SDQS7__MMDC_DRAM_SDQS_7 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D57, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D57__MMDC_DRAM_D_57 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D58, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D58__MMDC_DRAM_D_58 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D59, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D59__MMDC_DRAM_D_59 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D60, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D60__MMDC_DRAM_D_60 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_DQM7, 0x05C4, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_DQM7__MMDC_DRAM_DQM_7 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D61, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D61__MMDC_DRAM_D_61 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D62, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D62__MMDC_DRAM_D_62 */
-	IMX_PIN_REG(MX6Q_PAD_DRAM_D63, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_DRAM_D63__MMDC_DRAM_D_63 */
-	IMX_PIN_REG(MX6Q_PAD_KEY_COL0, 0x05C8, 0x01F8, 0, 0x07F4, 2), /* MX6Q_PAD_KEY_COL0__ECSPI1_SCLK */
-	IMX_PIN_REG(MX6Q_PAD_KEY_COL0, 0x05C8, 0x01F8, 1, 0x0854, 1), /* MX6Q_PAD_KEY_COL0__ENET_RDATA_3 */
-	IMX_PIN_REG(MX6Q_PAD_KEY_COL0, 0x05C8, 0x01F8, 2, 0x07DC, 1), /* MX6Q_PAD_KEY_COL0__AUDMUX_AUD5_TXC */
-	IMX_PIN_REG(MX6Q_PAD_KEY_COL0, 0x05C8, 0x01F8, 3, 0x0000, 0), /* MX6Q_PAD_KEY_COL0__KPP_COL_0 */
-	IMX_PIN_REG(MX6Q_PAD_KEY_COL0, 0x05C8, 0x01F8, 4, 0x0000, 0), /* MX6Q_PAD_KEY_COL0__UART4_TXD */
-	IMX_PIN_REG(MX6Q_PAD_KEY_COL0, 0x05C8, 0x01F8, 5, 0x0000, 0), /* MX6Q_PAD_KEY_COL0__GPIO_4_6 */
-	IMX_PIN_REG(MX6Q_PAD_KEY_COL0, 0x05C8, 0x01F8, 6, 0x0000, 0), /* MX6Q_PAD_KEY_COL0__DCIC1_DCIC_OUT */
-	IMX_PIN_REG(MX6Q_PAD_KEY_COL0, 0x05C8, 0x01F8, 7, 0x0000, 0), /* MX6Q_PAD_KEY_COL0__SRC_ANY_PU_RST */
-	IMX_PIN_REG(MX6Q_PAD_KEY_ROW0, 0x05CC, 0x01FC, 0, 0x07FC, 2), /* MX6Q_PAD_KEY_ROW0__ECSPI1_MOSI */
-	IMX_PIN_REG(MX6Q_PAD_KEY_ROW0, 0x05CC, 0x01FC, 1, 0x0000, 0), /* MX6Q_PAD_KEY_ROW0__ENET_TDATA_3 */
-	IMX_PIN_REG(MX6Q_PAD_KEY_ROW0, 0x05CC, 0x01FC, 2, 0x07D0, 1), /* MX6Q_PAD_KEY_ROW0__AUDMUX_AUD5_TXD */
-	IMX_PIN_REG(MX6Q_PAD_KEY_ROW0, 0x05CC, 0x01FC, 3, 0x0000, 0), /* MX6Q_PAD_KEY_ROW0__KPP_ROW_0 */
-	IMX_PIN_REG(MX6Q_PAD_KEY_ROW0, 0x05CC, 0x01FC, 4, 0x0938, 1), /* MX6Q_PAD_KEY_ROW0__UART4_RXD */
-	IMX_PIN_REG(MX6Q_PAD_KEY_ROW0, 0x05CC, 0x01FC, 5, 0x0000, 0), /* MX6Q_PAD_KEY_ROW0__GPIO_4_7 */
-	IMX_PIN_REG(MX6Q_PAD_KEY_ROW0, 0x05CC, 0x01FC, 6, 0x0000, 0), /* MX6Q_PAD_KEY_ROW0__DCIC2_DCIC_OUT */
-	IMX_PIN_REG(MX6Q_PAD_KEY_ROW0, 0x05CC, 0x01FC, 7, 0x0000, 0), /* MX6Q_PAD_KEY_ROW0__PL301_PER1_HADR_0 */
-	IMX_PIN_REG(MX6Q_PAD_KEY_COL1, 0x05D0, 0x0200, 0, 0x07F8, 2), /* MX6Q_PAD_KEY_COL1__ECSPI1_MISO */
-	IMX_PIN_REG(MX6Q_PAD_KEY_COL1, 0x05D0, 0x0200, 1, 0x0840, 1), /* MX6Q_PAD_KEY_COL1__ENET_MDIO */
-	IMX_PIN_REG(MX6Q_PAD_KEY_COL1, 0x05D0, 0x0200, 2, 0x07E0, 1), /* MX6Q_PAD_KEY_COL1__AUDMUX_AUD5_TXFS */
-	IMX_PIN_REG(MX6Q_PAD_KEY_COL1, 0x05D0, 0x0200, 3, 0x0000, 0), /* MX6Q_PAD_KEY_COL1__KPP_COL_1 */
-	IMX_PIN_REG(MX6Q_PAD_KEY_COL1, 0x05D0, 0x0200, 4, 0x0000, 0), /* MX6Q_PAD_KEY_COL1__UART5_TXD */
-	IMX_PIN_REG(MX6Q_PAD_KEY_COL1, 0x05D0, 0x0200, 5, 0x0000, 0), /* MX6Q_PAD_KEY_COL1__GPIO_4_8 */
-	IMX_PIN_REG(MX6Q_PAD_KEY_COL1, 0x05D0, 0x0200, 6, 0x0000, 0), /* MX6Q_PAD_KEY_COL1__USDHC1_VSELECT */
-	IMX_PIN_REG(MX6Q_PAD_KEY_COL1, 0x05D0, 0x0200, 7, 0x0000, 0), /* MX6Q_PAD_KEY_COL1__PL301MX_PER1_HADR_1 */
-	IMX_PIN_REG(MX6Q_PAD_KEY_ROW1, 0x05D4, 0x0204, 0, 0x0800, 2), /* MX6Q_PAD_KEY_ROW1__ECSPI1_SS0 */
-	IMX_PIN_REG(MX6Q_PAD_KEY_ROW1, 0x05D4, 0x0204, 1, 0x0000, 0), /* MX6Q_PAD_KEY_ROW1__ENET_COL */
-	IMX_PIN_REG(MX6Q_PAD_KEY_ROW1, 0x05D4, 0x0204, 2, 0x07CC, 1), /* MX6Q_PAD_KEY_ROW1__AUDMUX_AUD5_RXD */
-	IMX_PIN_REG(MX6Q_PAD_KEY_ROW1, 0x05D4, 0x0204, 3, 0x0000, 0), /* MX6Q_PAD_KEY_ROW1__KPP_ROW_1 */
-	IMX_PIN_REG(MX6Q_PAD_KEY_ROW1, 0x05D4, 0x0204, 4, 0x0940, 1), /* MX6Q_PAD_KEY_ROW1__UART5_RXD */
-	IMX_PIN_REG(MX6Q_PAD_KEY_ROW1, 0x05D4, 0x0204, 5, 0x0000, 0), /* MX6Q_PAD_KEY_ROW1__GPIO_4_9 */
-	IMX_PIN_REG(MX6Q_PAD_KEY_ROW1, 0x05D4, 0x0204, 6, 0x0000, 0), /* MX6Q_PAD_KEY_ROW1__USDHC2_VSELECT */
-	IMX_PIN_REG(MX6Q_PAD_KEY_ROW1, 0x05D4, 0x0204, 7, 0x0000, 0), /* MX6Q_PAD_KEY_ROW1__PL301_PER1_HADDR_2 */
-	IMX_PIN_REG(MX6Q_PAD_KEY_COL2, 0x05D8, 0x0208, 0, 0x0804, 2), /* MX6Q_PAD_KEY_COL2__ECSPI1_SS1 */
-	IMX_PIN_REG(MX6Q_PAD_KEY_COL2, 0x05D8, 0x0208, 1, 0x0850, 1), /* MX6Q_PAD_KEY_COL2__ENET_RDATA_2 */
-	IMX_PIN_REG(MX6Q_PAD_KEY_COL2, 0x05D8, 0x0208, 2, 0x0000, 0), /* MX6Q_PAD_KEY_COL2__CAN1_TXCAN */
-	IMX_PIN_REG(MX6Q_PAD_KEY_COL2, 0x05D8, 0x0208, 3, 0x0000, 0), /* MX6Q_PAD_KEY_COL2__KPP_COL_2 */
-	IMX_PIN_REG(MX6Q_PAD_KEY_COL2, 0x05D8, 0x0208, 4, 0x0000, 0), /* MX6Q_PAD_KEY_COL2__ENET_MDC */
-	IMX_PIN_REG(MX6Q_PAD_KEY_COL2, 0x05D8, 0x0208, 5, 0x0000, 0), /* MX6Q_PAD_KEY_COL2__GPIO_4_10 */
-	IMX_PIN_REG(MX6Q_PAD_KEY_COL2, 0x05D8, 0x0208, 6, 0x0000, 0), /* MX6Q_PAD_KEY_COL2__USBOH3_H1_PWRCTL_WKP */
-	IMX_PIN_REG(MX6Q_PAD_KEY_COL2, 0x05D8, 0x0208, 7, 0x0000, 0), /* MX6Q_PAD_KEY_COL2__PL301_PER1_HADDR_3 */
-	IMX_PIN_REG(MX6Q_PAD_KEY_ROW2, 0x05DC, 0x020C, 0, 0x0808, 1), /* MX6Q_PAD_KEY_ROW2__ECSPI1_SS2 */
-	IMX_PIN_REG(MX6Q_PAD_KEY_ROW2, 0x05DC, 0x020C, 1, 0x0000, 0), /* MX6Q_PAD_KEY_ROW2__ENET_TDATA_2 */
-	IMX_PIN_REG(MX6Q_PAD_KEY_ROW2, 0x05DC, 0x020C, 2, 0x07E4, 0), /* MX6Q_PAD_KEY_ROW2__CAN1_RXCAN */
-	IMX_PIN_REG(MX6Q_PAD_KEY_ROW2, 0x05DC, 0x020C, 3, 0x0000, 0), /* MX6Q_PAD_KEY_ROW2__KPP_ROW_2 */
-	IMX_PIN_REG(MX6Q_PAD_KEY_ROW2, 0x05DC, 0x020C, 4, 0x0000, 0), /* MX6Q_PAD_KEY_ROW2__USDHC2_VSELECT */
-	IMX_PIN_REG(MX6Q_PAD_KEY_ROW2, 0x05DC, 0x020C, 5, 0x0000, 0), /* MX6Q_PAD_KEY_ROW2__GPIO_4_11 */
-	IMX_PIN_REG(MX6Q_PAD_KEY_ROW2, 0x05DC, 0x020C, 6, 0x088C, 1), /* MX6Q_PAD_KEY_ROW2__HDMI_TX_CEC_LINE */
-	IMX_PIN_REG(MX6Q_PAD_KEY_ROW2, 0x05DC, 0x020C, 7, 0x0000, 0), /* MX6Q_PAD_KEY_ROW2__PL301_PER1_HADR_4 */
-	IMX_PIN_REG(MX6Q_PAD_KEY_COL3, 0x05E0, 0x0210, 0, 0x080C, 1), /* MX6Q_PAD_KEY_COL3__ECSPI1_SS3 */
-	IMX_PIN_REG(MX6Q_PAD_KEY_COL3, 0x05E0, 0x0210, 1, 0x0000, 0), /* MX6Q_PAD_KEY_COL3__ENET_CRS */
-	IMX_PIN_REG(MX6Q_PAD_KEY_COL3, 0x05E0, 0x0210, 2, 0x0890, 1), /* MX6Q_PAD_KEY_COL3__HDMI_TX_DDC_SCL */
-	IMX_PIN_REG(MX6Q_PAD_KEY_COL3, 0x05E0, 0x0210, 3, 0x0000, 0), /* MX6Q_PAD_KEY_COL3__KPP_COL_3 */
-	IMX_PIN_REG(MX6Q_PAD_KEY_COL3, 0x05E0, 0x0210, 4, 0x08A0, 1), /* MX6Q_PAD_KEY_COL3__I2C2_SCL */
-	IMX_PIN_REG(MX6Q_PAD_KEY_COL3, 0x05E0, 0x0210, 5, 0x0000, 0), /* MX6Q_PAD_KEY_COL3__GPIO_4_12 */
-	IMX_PIN_REG(MX6Q_PAD_KEY_COL3, 0x05E0, 0x0210, 6, 0x0914, 2), /* MX6Q_PAD_KEY_COL3__SPDIF_IN1 */
-	IMX_PIN_REG(MX6Q_PAD_KEY_COL3, 0x05E0, 0x0210, 7, 0x0000, 0), /* MX6Q_PAD_KEY_COL3__PL301_PER1_HADR_5 */
-	IMX_PIN_REG(MX6Q_PAD_KEY_ROW3, 0x05E4, 0x0214, 0, 0x0000, 0), /* MX6Q_PAD_KEY_ROW3__OSC32K_32K_OUT */
-	IMX_PIN_REG(MX6Q_PAD_KEY_ROW3, 0x05E4, 0x0214, 1, 0x07B0, 0), /* MX6Q_PAD_KEY_ROW3__ASRC_ASRC_EXT_CLK */
-	IMX_PIN_REG(MX6Q_PAD_KEY_ROW3, 0x05E4, 0x0214, 2, 0x0894, 1), /* MX6Q_PAD_KEY_ROW3__HDMI_TX_DDC_SDA */
-	IMX_PIN_REG(MX6Q_PAD_KEY_ROW3, 0x05E4, 0x0214, 3, 0x0000, 0), /* MX6Q_PAD_KEY_ROW3__KPP_ROW_3 */
-	IMX_PIN_REG(MX6Q_PAD_KEY_ROW3, 0x05E4, 0x0214, 4, 0x08A4, 1), /* MX6Q_PAD_KEY_ROW3__I2C2_SDA */
-	IMX_PIN_REG(MX6Q_PAD_KEY_ROW3, 0x05E4, 0x0214, 5, 0x0000, 0), /* MX6Q_PAD_KEY_ROW3__GPIO_4_13 */
-	IMX_PIN_REG(MX6Q_PAD_KEY_ROW3, 0x05E4, 0x0214, 6, 0x0000, 0), /* MX6Q_PAD_KEY_ROW3__USDHC1_VSELECT */
-	IMX_PIN_REG(MX6Q_PAD_KEY_ROW3, 0x05E4, 0x0214, 7, 0x0000, 0), /* MX6Q_PAD_KEY_ROW3__PL301_PER1_HADR_6 */
-	IMX_PIN_REG(MX6Q_PAD_KEY_COL4, 0x05E8, 0x0218, 0, 0x0000, 0), /* MX6Q_PAD_KEY_COL4__CAN2_TXCAN */
-	IMX_PIN_REG(MX6Q_PAD_KEY_COL4, 0x05E8, 0x0218, 1, 0x0000, 0), /* MX6Q_PAD_KEY_COL4__IPU1_SISG_4 */
-	IMX_PIN_REG(MX6Q_PAD_KEY_COL4, 0x05E8, 0x0218, 2, 0x0944, 1), /* MX6Q_PAD_KEY_COL4__USBOH3_USBOTG_OC */
-	IMX_PIN_REG(MX6Q_PAD_KEY_COL4, 0x05E8, 0x0218, 3, 0x0000, 0), /* MX6Q_PAD_KEY_COL4__KPP_COL_4 */
-	IMX_PIN_REG(MX6Q_PAD_KEY_COL4, 0x05E8, 0x0218, 4, 0x093C, 0), /* MX6Q_PAD_KEY_COL4__UART5_RTS */
-	IMX_PIN_REG(MX6Q_PAD_KEY_COL4, 0x05E8, 0x0218, 5, 0x0000, 0), /* MX6Q_PAD_KEY_COL4__GPIO_4_14 */
-	IMX_PIN_REG(MX6Q_PAD_KEY_COL4, 0x05E8, 0x0218, 6, 0x0000, 0), /* MX6Q_PAD_KEY_COL4__MMDC_DEBUG_49 */
-	IMX_PIN_REG(MX6Q_PAD_KEY_COL4, 0x05E8, 0x0218, 7, 0x0000, 0), /* MX6Q_PAD_KEY_COL4__PL301_PER1_HADDR_7 */
-	IMX_PIN_REG(MX6Q_PAD_KEY_ROW4, 0x05EC, 0x021C, 0, 0x07E8, 0), /* MX6Q_PAD_KEY_ROW4__CAN2_RXCAN */
-	IMX_PIN_REG(MX6Q_PAD_KEY_ROW4, 0x05EC, 0x021C, 1, 0x0000, 0), /* MX6Q_PAD_KEY_ROW4__IPU1_SISG_5 */
-	IMX_PIN_REG(MX6Q_PAD_KEY_ROW4, 0x05EC, 0x021C, 2, 0x0000, 0), /* MX6Q_PAD_KEY_ROW4__USBOH3_USBOTG_PWR */
-	IMX_PIN_REG(MX6Q_PAD_KEY_ROW4, 0x05EC, 0x021C, 3, 0x0000, 0), /* MX6Q_PAD_KEY_ROW4__KPP_ROW_4 */
-	IMX_PIN_REG(MX6Q_PAD_KEY_ROW4, 0x05EC, 0x021C, 4, 0x093C, 1), /* MX6Q_PAD_KEY_ROW4__UART5_CTS */
-	IMX_PIN_REG(MX6Q_PAD_KEY_ROW4, 0x05EC, 0x021C, 5, 0x0000, 0), /* MX6Q_PAD_KEY_ROW4__GPIO_4_15 */
-	IMX_PIN_REG(MX6Q_PAD_KEY_ROW4, 0x05EC, 0x021C, 6, 0x0000, 0), /* MX6Q_PAD_KEY_ROW4__MMDC_DEBUG_50 */
-	IMX_PIN_REG(MX6Q_PAD_KEY_ROW4, 0x05EC, 0x021C, 7, 0x0000, 0), /* MX6Q_PAD_KEY_ROW4__PL301_PER1_HADR_8 */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_0, 0x05F0, 0x0220, 0, 0x0000, 0), /* MX6Q_PAD_GPIO_0__CCM_CLKO */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_0, 0x05F0, 0x0220, 2, 0x08E8, 0), /* MX6Q_PAD_GPIO_0__KPP_COL_5 */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_0, 0x05F0, 0x0220, 3, 0x07B0, 1), /* MX6Q_PAD_GPIO_0__ASRC_ASRC_EXT_CLK */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_0, 0x05F0, 0x0220, 4, 0x0000, 0), /* MX6Q_PAD_GPIO_0__EPIT1_EPITO */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_0, 0x05F0, 0x0220, 5, 0x0000, 0), /* MX6Q_PAD_GPIO_0__GPIO_1_0 */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_0, 0x05F0, 0x0220, 6, 0x0000, 0), /* MX6Q_PAD_GPIO_0__USBOH3_USBH1_PWR */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_0, 0x05F0, 0x0220, 7, 0x0000, 0), /* MX6Q_PAD_GPIO_0__SNVS_HP_WRAP_SNVS_VIO5 */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_1, 0x05F4, 0x0224, 0, 0x086C, 1), /* MX6Q_PAD_GPIO_1__ESAI1_SCKR */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_1, 0x05F4, 0x0224, 1, 0x0000, 0), /* MX6Q_PAD_GPIO_1__WDOG2_WDOG_B */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_1, 0x05F4, 0x0224, 2, 0x08F4, 0), /* MX6Q_PAD_GPIO_1__KPP_ROW_5 */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_1, 0x05F4, 0x0224, 4, 0x0000, 0), /* MX6Q_PAD_GPIO_1__PWM2_PWMO */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_1, 0x05F4, 0x0224, 5, 0x0000, 0), /* MX6Q_PAD_GPIO_1__GPIO_1_1 */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_1, 0x05F4, 0x0224, 6, 0x0000, 0), /* MX6Q_PAD_GPIO_1__USDHC1_CD */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_1, 0x05F4, 0x0224, 7, 0x0000, 0), /* MX6Q_PAD_GPIO_1__SRC_TESTER_ACK */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_9, 0x05F8, 0x0228, 0, 0x085C, 1), /* MX6Q_PAD_GPIO_9__ESAI1_FSR */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_9, 0x05F8, 0x0228, 1, 0x0000, 0), /* MX6Q_PAD_GPIO_9__WDOG1_WDOG_B */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_9, 0x05F8, 0x0228, 2, 0x08EC, 0), /* MX6Q_PAD_GPIO_9__KPP_COL_6 */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_9, 0x05F8, 0x0228, 3, 0x0000, 0), /* MX6Q_PAD_GPIO_9__CCM_REF_EN_B */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_9, 0x05F8, 0x0228, 4, 0x0000, 0), /* MX6Q_PAD_GPIO_9__PWM1_PWMO */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_9, 0x05F8, 0x0228, 5, 0x0000, 0), /* MX6Q_PAD_GPIO_9__GPIO_1_9 */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_9, 0x05F8, 0x0228, 6, 0x094C, 1), /* MX6Q_PAD_GPIO_9__USDHC1_WP */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_9, 0x05F8, 0x0228, 7, 0x0000, 0), /* MX6Q_PAD_GPIO_9__SRC_EARLY_RST */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_3, 0x05FC, 0x022C, 0, 0x0864, 1), /* MX6Q_PAD_GPIO_3__ESAI1_HCKR */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_3, 0x05FC, 0x022C, 1, 0x0000, 0), /* MX6Q_PAD_GPIO_3__OBSERVE_MUX_INT_OUT0 */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_3, 0x05FC, 0x022C, 2, 0x08A8, 1), /* MX6Q_PAD_GPIO_3__I2C3_SCL */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_3, 0x05FC, 0x022C, 3, 0x0000, 0), /* MX6Q_PAD_GPIO_3__ANATOP_24M_OUT */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_3, 0x05FC, 0x022C, 4, 0x0000, 0), /* MX6Q_PAD_GPIO_3__CCM_CLKO2 */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_3, 0x05FC, 0x022C, 5, 0x0000, 0), /* MX6Q_PAD_GPIO_3__GPIO_1_3 */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_3, 0x05FC, 0x022C, 6, 0x0948, 1), /* MX6Q_PAD_GPIO_3__USBOH3_USBH1_OC */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_3, 0x05FC, 0x022C, 7, 0x0900, 1), /* MX6Q_PAD_GPIO_3__MLB_MLBCLK */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_6, 0x0600, 0x0230, 0, 0x0870, 1), /* MX6Q_PAD_GPIO_6__ESAI1_SCKT */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_6, 0x0600, 0x0230, 1, 0x0000, 0), /* MX6Q_PAD_GPIO_6__OBSERVE_MUX_INT_OUT1 */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_6, 0x0600, 0x0230, 2, 0x08AC, 1), /* MX6Q_PAD_GPIO_6__I2C3_SDA */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_6, 0x0600, 0x0230, 3, 0x0000, 0), /* MX6Q_PAD_GPIO_6__CCM_CCM_OUT_0 */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_6, 0x0600, 0x0230, 4, 0x0000, 0), /* MX6Q_PAD_GPIO_6__CSU_CSU_INT_DEB */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_6, 0x0600, 0x0230, 5, 0x0000, 0), /* MX6Q_PAD_GPIO_6__GPIO_1_6 */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_6, 0x0600, 0x0230, 6, 0x0000, 0), /* MX6Q_PAD_GPIO_6__USDHC2_LCTL */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_6, 0x0600, 0x0230, 7, 0x0908, 1), /* MX6Q_PAD_GPIO_6__MLB_MLBSIG */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_2, 0x0604, 0x0234, 0, 0x0860, 1), /* MX6Q_PAD_GPIO_2__ESAI1_FST */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_2, 0x0604, 0x0234, 1, 0x0000, 0), /* MX6Q_PAD_GPIO_2__OBSERVE_MUX_INT_OUT2 */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_2, 0x0604, 0x0234, 2, 0x08F8, 1), /* MX6Q_PAD_GPIO_2__KPP_ROW_6 */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_2, 0x0604, 0x0234, 3, 0x0000, 0), /* MX6Q_PAD_GPIO_2__CCM_CCM_OUT_1 */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_2, 0x0604, 0x0234, 4, 0x0000, 0), /* MX6Q_PAD_GPIO_2__CSU_CSU_ALARM_AUT_0 */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_2, 0x0604, 0x0234, 5, 0x0000, 0), /* MX6Q_PAD_GPIO_2__GPIO_1_2 */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_2, 0x0604, 0x0234, 6, 0x0000, 0), /* MX6Q_PAD_GPIO_2__USDHC2_WP */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_2, 0x0604, 0x0234, 7, 0x0904, 1), /* MX6Q_PAD_GPIO_2__MLB_MLBDAT */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_4, 0x0608, 0x0238, 0, 0x0868, 1), /* MX6Q_PAD_GPIO_4__ESAI1_HCKT */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_4, 0x0608, 0x0238, 1, 0x0000, 0), /* MX6Q_PAD_GPIO_4__OBSERVE_MUX_INT_OUT3 */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_4, 0x0608, 0x0238, 2, 0x08F0, 1), /* MX6Q_PAD_GPIO_4__KPP_COL_7 */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_4, 0x0608, 0x0238, 3, 0x0000, 0), /* MX6Q_PAD_GPIO_4__CCM_CCM_OUT_2 */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_4, 0x0608, 0x0238, 4, 0x0000, 0), /* MX6Q_PAD_GPIO_4__CSU_CSU_ALARM_AUT_1 */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_4, 0x0608, 0x0238, 5, 0x0000, 0), /* MX6Q_PAD_GPIO_4__GPIO_1_4 */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_4, 0x0608, 0x0238, 6, 0x0000, 0), /* MX6Q_PAD_GPIO_4__USDHC2_CD */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_4, 0x0608, 0x0238, 7, 0x0000, 0), /* MX6Q_PAD_GPIO_4__OCOTP_CRL_WRAR_FUSE_LA */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_5, 0x060C, 0x023C, 0, 0x087C, 1), /* MX6Q_PAD_GPIO_5__ESAI1_TX2_RX3 */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_5, 0x060C, 0x023C, 1, 0x0000, 0), /* MX6Q_PAD_GPIO_5__OBSERVE_MUX_INT_OUT4 */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_5, 0x060C, 0x023C, 2, 0x08FC, 1), /* MX6Q_PAD_GPIO_5__KPP_ROW_7 */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_5, 0x060C, 0x023C, 3, 0x0000, 0), /* MX6Q_PAD_GPIO_5__CCM_CLKO */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_5, 0x060C, 0x023C, 4, 0x0000, 0), /* MX6Q_PAD_GPIO_5__CSU_CSU_ALARM_AUT_2 */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_5, 0x060C, 0x023C, 5, 0x0000, 0), /* MX6Q_PAD_GPIO_5__GPIO_1_5 */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_5, 0x060C, 0x023C, 6, 0x08A8, 2), /* MX6Q_PAD_GPIO_5__I2C3_SCL */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_5, 0x060C, 0x023C, 7, 0x0000, 0), /* MX6Q_PAD_GPIO_5__CHEETAH_EVENTI */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_7, 0x0610, 0x0240, 0, 0x0884, 1), /* MX6Q_PAD_GPIO_7__ESAI1_TX4_RX1 */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_7, 0x0610, 0x0240, 1, 0x0000, 0), /* MX6Q_PAD_GPIO_7__ECSPI5_RDY */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_7, 0x0610, 0x0240, 2, 0x0000, 0), /* MX6Q_PAD_GPIO_7__EPIT1_EPITO */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_7, 0x0610, 0x0240, 3, 0x0000, 0), /* MX6Q_PAD_GPIO_7__CAN1_TXCAN */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_7, 0x0610, 0x0240, 4, 0x0000, 0), /* MX6Q_PAD_GPIO_7__UART2_TXD */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_7, 0x0610, 0x0240, 5, 0x0000, 0), /* MX6Q_PAD_GPIO_7__GPIO_1_7 */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_7, 0x0610, 0x0240, 6, 0x0000, 0), /* MX6Q_PAD_GPIO_7__SPDIF_PLOCK */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_7, 0x0610, 0x0240, 7, 0x0000, 0), /* MX6Q_PAD_GPIO_7__USBOH3_OTGUSB_HST_MODE */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_8, 0x0614, 0x0244, 0, 0x0888, 1), /* MX6Q_PAD_GPIO_8__ESAI1_TX5_RX0 */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_8, 0x0614, 0x0244, 1, 0x0000, 0), /* MX6Q_PAD_GPIO_8__ANATOP_ANATOP_32K_OUT */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_8, 0x0614, 0x0244, 2, 0x0000, 0), /* MX6Q_PAD_GPIO_8__EPIT2_EPITO */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_8, 0x0614, 0x0244, 3, 0x07E4, 1), /* MX6Q_PAD_GPIO_8__CAN1_RXCAN */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_8, 0x0614, 0x0244, 4, 0x0928, 3), /* MX6Q_PAD_GPIO_8__UART2_RXD */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_8, 0x0614, 0x0244, 5, 0x0000, 0), /* MX6Q_PAD_GPIO_8__GPIO_1_8 */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_8, 0x0614, 0x0244, 6, 0x0000, 0), /* MX6Q_PAD_GPIO_8__SPDIF_SRCLK */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_8, 0x0614, 0x0244, 7, 0x0000, 0), /* MX6Q_PAD_GPIO_8__USBOH3_OTG_PWRCTL_WAK */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_16, 0x0618, 0x0248, 0, 0x0880, 1), /* MX6Q_PAD_GPIO_16__ESAI1_TX3_RX2 */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_16, 0x0618, 0x0248, 1, 0x0000, 0), /* MX6Q_PAD_GPIO_16__ENET_1588_EVENT2_IN */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_16, 0x0618, 0x0248, 2, 0x083C, 1), /* MX6Q_PAD_GPIO_16__ENET_ETHERNET_REF_OUT */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_16, 0x0618, 0x0248, 3, 0x0000, 0), /* MX6Q_PAD_GPIO_16__USDHC1_LCTL */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_16, 0x0618, 0x0248, 4, 0x0914, 3), /* MX6Q_PAD_GPIO_16__SPDIF_IN1 */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_16, 0x0618, 0x0248, 5, 0x0000, 0), /* MX6Q_PAD_GPIO_16__GPIO_7_11 */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_16, 0x0618, 0x0248, 6, 0x08AC, 2), /* MX6Q_PAD_GPIO_16__I2C3_SDA */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_16, 0x0618, 0x0248, 7, 0x0000, 0), /* MX6Q_PAD_GPIO_16__SJC_DE_B */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_17, 0x061C, 0x024C, 0, 0x0874, 0), /* MX6Q_PAD_GPIO_17__ESAI1_TX0 */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_17, 0x061C, 0x024C, 1, 0x0000, 0), /* MX6Q_PAD_GPIO_17__ENET_1588_EVENT3_IN */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_17, 0x061C, 0x024C, 2, 0x07F0, 1), /* MX6Q_PAD_GPIO_17__CCM_PMIC_RDY */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_17, 0x061C, 0x024C, 3, 0x090C, 1), /* MX6Q_PAD_GPIO_17__SDMA_SDMA_EXT_EVENT_0 */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_17, 0x061C, 0x024C, 4, 0x0000, 0), /* MX6Q_PAD_GPIO_17__SPDIF_OUT1 */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_17, 0x061C, 0x024C, 5, 0x0000, 0), /* MX6Q_PAD_GPIO_17__GPIO_7_12 */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_17, 0x061C, 0x024C, 7, 0x0000, 0), /* MX6Q_PAD_GPIO_17__SJC_JTAG_ACT */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_18, 0x0620, 0x0250, 0, 0x0878, 0), /* MX6Q_PAD_GPIO_18__ESAI1_TX1 */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_18, 0x0620, 0x0250, 1, 0x0844, 1), /* MX6Q_PAD_GPIO_18__ENET_RX_CLK */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_18, 0x0620, 0x0250, 2, 0x0000, 0), /* MX6Q_PAD_GPIO_18__USDHC3_VSELECT */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_18, 0x0620, 0x0250, 3, 0x0910, 1), /* MX6Q_PAD_GPIO_18__SDMA_SDMA_EXT_EVENT_1 */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_18, 0x0620, 0x0250, 4, 0x07B0, 2), /* MX6Q_PAD_GPIO_18__ASRC_ASRC_EXT_CLK */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_18, 0x0620, 0x0250, 5, 0x0000, 0), /* MX6Q_PAD_GPIO_18__GPIO_7_13 */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_18, 0x0620, 0x0250, 6, 0x0000, 0), /* MX6Q_PAD_GPIO_18__SNVS_HP_WRA_SNVS_VIO5 */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_18, 0x0620, 0x0250, 7, 0x0000, 0), /* MX6Q_PAD_GPIO_18__SRC_SYSTEM_RST */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_19, 0x0624, 0x0254, 0, 0x08E8, 1), /* MX6Q_PAD_GPIO_19__KPP_COL_5 */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_19, 0x0624, 0x0254, 1, 0x0000, 0), /* MX6Q_PAD_GPIO_19__ENET_1588_EVENT0_OUT */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_19, 0x0624, 0x0254, 2, 0x0000, 0), /* MX6Q_PAD_GPIO_19__SPDIF_OUT1 */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_19, 0x0624, 0x0254, 3, 0x0000, 0), /* MX6Q_PAD_GPIO_19__CCM_CLKO */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_19, 0x0624, 0x0254, 4, 0x0000, 0), /* MX6Q_PAD_GPIO_19__ECSPI1_RDY */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_19, 0x0624, 0x0254, 5, 0x0000, 0), /* MX6Q_PAD_GPIO_19__GPIO_4_5 */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_19, 0x0624, 0x0254, 6, 0x0000, 0), /* MX6Q_PAD_GPIO_19__ENET_TX_ER */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_19, 0x0624, 0x0254, 7, 0x0000, 0), /* MX6Q_PAD_GPIO_19__SRC_INT_BOOT */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_PIXCLK, 0x0628, 0x0258, 0, 0x0000, 0), /* MX6Q_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_PIXCLK, 0x0628, 0x0258, 2, 0x0000, 0), /* MX6Q_PAD_CSI0_PIXCLK__PCIE_CTRL_MUX_12 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_PIXCLK, 0x0628, 0x0258, 4, 0x0000, 0), /* MX6Q_PAD_CSI0_PIXCLK__SDMA_DEBUG_PC_0 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_PIXCLK, 0x0628, 0x0258, 5, 0x0000, 0), /* MX6Q_PAD_CSI0_PIXCLK__GPIO_5_18 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_PIXCLK, 0x0628, 0x0258, 6, 0x0000, 0), /* MX6Q_PAD_CSI0_PIXCLK___MMDC_DEBUG_29 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_PIXCLK, 0x0628, 0x0258, 7, 0x0000, 0), /* MX6Q_PAD_CSI0_PIXCLK__CHEETAH_EVENTO */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_MCLK, 0x062C, 0x025C, 0, 0x0000, 0), /* MX6Q_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_MCLK, 0x062C, 0x025C, 2, 0x0000, 0), /* MX6Q_PAD_CSI0_MCLK__PCIE_CTRL_MUX_13 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_MCLK, 0x062C, 0x025C, 3, 0x0000, 0), /* MX6Q_PAD_CSI0_MCLK__CCM_CLKO */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_MCLK, 0x062C, 0x025C, 4, 0x0000, 0), /* MX6Q_PAD_CSI0_MCLK__SDMA_DEBUG_PC_1 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_MCLK, 0x062C, 0x025C, 5, 0x0000, 0), /* MX6Q_PAD_CSI0_MCLK__GPIO_5_19 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_MCLK, 0x062C, 0x025C, 6, 0x0000, 0), /* MX6Q_PAD_CSI0_MCLK__MMDC_MMDC_DEBUG_30 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_MCLK, 0x062C, 0x025C, 7, 0x0000, 0), /* MX6Q_PAD_CSI0_MCLK__CHEETAH_TRCTL */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DATA_EN, 0x0630, 0x0260, 0, 0x0000, 0), /* MX6Q_PAD_CSI0_DATA_EN__IPU1_CSI0_DA_EN */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DATA_EN, 0x0630, 0x0260, 1, 0x0000, 0), /* MX6Q_PAD_CSI0_DATA_EN__WEIM_WEIM_D_0 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DATA_EN, 0x0630, 0x0260, 2, 0x0000, 0), /* MX6Q_PAD_CSI0_DATA_EN__PCIE_CTRL_MUX_14 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DATA_EN, 0x0630, 0x0260, 4, 0x0000, 0), /* MX6Q_PAD_CSI0_DATA_EN__SDMA_DEBUG_PC_2 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DATA_EN, 0x0630, 0x0260, 5, 0x0000, 0), /* MX6Q_PAD_CSI0_DATA_EN__GPIO_5_20 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DATA_EN, 0x0630, 0x0260, 6, 0x0000, 0), /* MX6Q_PAD_CSI0_DATA_EN__MMDC_DEBUG_31 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DATA_EN, 0x0630, 0x0260, 7, 0x0000, 0), /* MX6Q_PAD_CSI0_DATA_EN__CHEETAH_TRCLK */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_VSYNC, 0x0634, 0x0264, 0, 0x0000, 0), /* MX6Q_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_VSYNC, 0x0634, 0x0264, 1, 0x0000, 0), /* MX6Q_PAD_CSI0_VSYNC__WEIM_WEIM_D_1 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_VSYNC, 0x0634, 0x0264, 2, 0x0000, 0), /* MX6Q_PAD_CSI0_VSYNC__PCIE_CTRL_MUX_15 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_VSYNC, 0x0634, 0x0264, 4, 0x0000, 0), /* MX6Q_PAD_CSI0_VSYNC__SDMA_DEBUG_PC_3 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_VSYNC, 0x0634, 0x0264, 5, 0x0000, 0), /* MX6Q_PAD_CSI0_VSYNC__GPIO_5_21 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_VSYNC, 0x0634, 0x0264, 6, 0x0000, 0), /* MX6Q_PAD_CSI0_VSYNC__MMDC_DEBUG_32 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_VSYNC, 0x0634, 0x0264, 7, 0x0000, 0), /* MX6Q_PAD_CSI0_VSYNC__CHEETAH_TRACE_0 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT4, 0x0638, 0x0268, 0, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT4__IPU1_CSI0_D_4 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT4, 0x0638, 0x0268, 1, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT4__WEIM_WEIM_D_2 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT4, 0x0638, 0x0268, 2, 0x07F4, 3), /* MX6Q_PAD_CSI0_DAT4__ECSPI1_SCLK */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT4, 0x0638, 0x0268, 3, 0x08E8, 2), /* MX6Q_PAD_CSI0_DAT4__KPP_COL_5 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT4, 0x0638, 0x0268, 4, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT4__AUDMUX_AUD3_TXC */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT4, 0x0638, 0x0268, 5, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT4__GPIO_5_22 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT4, 0x0638, 0x0268, 6, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT4__MMDC_DEBUG_43 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT4, 0x0638, 0x0268, 7, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT4__CHEETAH_TRACE_1 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT5, 0x063C, 0x026C, 0, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT5__IPU1_CSI0_D_5 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT5, 0x063C, 0x026C, 1, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT5__WEIM_WEIM_D_3 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT5, 0x063C, 0x026C, 2, 0x07FC, 3), /* MX6Q_PAD_CSI0_DAT5__ECSPI1_MOSI */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT5, 0x063C, 0x026C, 3, 0x08F4, 1), /* MX6Q_PAD_CSI0_DAT5__KPP_ROW_5 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT5, 0x063C, 0x026C, 4, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT5__AUDMUX_AUD3_TXD */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT5, 0x063C, 0x026C, 5, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT5__GPIO_5_23 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT5, 0x063C, 0x026C, 6, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT5__MMDC_MMDC_DEBUG_44 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT5, 0x063C, 0x026C, 7, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT5__CHEETAH_TRACE_2 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT6, 0x0640, 0x0270, 0, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT6__IPU1_CSI0_D_6 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT6, 0x0640, 0x0270, 1, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT6__WEIM_WEIM_D_4 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT6, 0x0640, 0x0270, 2, 0x07F8, 3), /* MX6Q_PAD_CSI0_DAT6__ECSPI1_MISO */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT6, 0x0640, 0x0270, 3, 0x08EC, 1), /* MX6Q_PAD_CSI0_DAT6__KPP_COL_6 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT6, 0x0640, 0x0270, 4, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT6__AUDMUX_AUD3_TXFS */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT6, 0x0640, 0x0270, 5, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT6__GPIO_5_24 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT6, 0x0640, 0x0270, 6, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT6__MMDC_MMDC_DEBUG_45 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT6, 0x0640, 0x0270, 7, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT6__CHEETAH_TRACE_3 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT7, 0x0644, 0x0274, 0, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT7__IPU1_CSI0_D_7 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT7, 0x0644, 0x0274, 1, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT7__WEIM_WEIM_D_5 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT7, 0x0644, 0x0274, 2, 0x0800, 3), /* MX6Q_PAD_CSI0_DAT7__ECSPI1_SS0 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT7, 0x0644, 0x0274, 3, 0x08F8, 2), /* MX6Q_PAD_CSI0_DAT7__KPP_ROW_6 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT7, 0x0644, 0x0274, 4, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT7__AUDMUX_AUD3_RXD */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT7, 0x0644, 0x0274, 5, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT7__GPIO_5_25 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT7, 0x0644, 0x0274, 6, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT7__MMDC_MMDC_DEBUG_46 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT7, 0x0644, 0x0274, 7, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT7__CHEETAH_TRACE_4 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT8, 0x0648, 0x0278, 0, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT8__IPU1_CSI0_D_8 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT8, 0x0648, 0x0278, 1, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT8__WEIM_WEIM_D_6 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT8, 0x0648, 0x0278, 2, 0x0810, 2), /* MX6Q_PAD_CSI0_DAT8__ECSPI2_SCLK */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT8, 0x0648, 0x0278, 3, 0x08F0, 2), /* MX6Q_PAD_CSI0_DAT8__KPP_COL_7 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT8, 0x0648, 0x0278, 4, 0x089C, 1), /* MX6Q_PAD_CSI0_DAT8__I2C1_SDA */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT8, 0x0648, 0x0278, 5, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT8__GPIO_5_26 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT8, 0x0648, 0x0278, 6, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT8__MMDC_MMDC_DEBUG_47 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT8, 0x0648, 0x0278, 7, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT8__CHEETAH_TRACE_5 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT9, 0x064C, 0x027C, 0, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT9__IPU1_CSI0_D_9 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT9, 0x064C, 0x027C, 1, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT9__WEIM_WEIM_D_7 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT9, 0x064C, 0x027C, 2, 0x0818, 2), /* MX6Q_PAD_CSI0_DAT9__ECSPI2_MOSI */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT9, 0x064C, 0x027C, 3, 0x08FC, 2), /* MX6Q_PAD_CSI0_DAT9__KPP_ROW_7 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT9, 0x064C, 0x027C, 4, 0x0898, 1), /* MX6Q_PAD_CSI0_DAT9__I2C1_SCL */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT9, 0x064C, 0x027C, 5, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT9__GPIO_5_27 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT9, 0x064C, 0x027C, 6, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT9__MMDC_MMDC_DEBUG_48 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT9, 0x064C, 0x027C, 7, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT9__CHEETAH_TRACE_6 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT10, 0x0650, 0x0280, 0, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT10__IPU1_CSI0_D_10 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT10, 0x0650, 0x0280, 1, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT10__AUDMUX_AUD3_RXC */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT10, 0x0650, 0x0280, 2, 0x0814, 2), /* MX6Q_PAD_CSI0_DAT10__ECSPI2_MISO */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT10, 0x0650, 0x0280, 3, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT10__UART1_TXD */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT10, 0x0650, 0x0280, 4, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT10__SDMA_DEBUG_PC_4 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT10, 0x0650, 0x0280, 5, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT10__GPIO_5_28 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT10, 0x0650, 0x0280, 6, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT10__MMDC_MMDC_DEBUG_33 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT10, 0x0650, 0x0280, 7, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT10__CHEETAH_TRACE_7 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT11, 0x0654, 0x0284, 0, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT11__IPU1_CSI0_D_11 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT11, 0x0654, 0x0284, 1, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT11__AUDMUX_AUD3_RXFS */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT11, 0x0654, 0x0284, 2, 0x081C, 2), /* MX6Q_PAD_CSI0_DAT11__ECSPI2_SS0 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT11, 0x0654, 0x0284, 3, 0x0920, 1), /* MX6Q_PAD_CSI0_DAT11__UART1_RXD */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT11, 0x0654, 0x0284, 4, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT11__SDMA_DEBUG_PC_5 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT11, 0x0654, 0x0284, 5, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT11__GPIO_5_29 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT11, 0x0654, 0x0284, 6, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT11__MMDC_MMDC_DEBUG_34 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT11, 0x0654, 0x0284, 7, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT11__CHEETAH_TRACE_8 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT12, 0x0658, 0x0288, 0, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT12__IPU1_CSI0_D_12 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT12, 0x0658, 0x0288, 1, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT12__WEIM_WEIM_D_8 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT12, 0x0658, 0x0288, 2, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT12__PCIE_CTRL_MUX_16 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT12, 0x0658, 0x0288, 3, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT12__UART4_TXD */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT12, 0x0658, 0x0288, 4, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT12__SDMA_DEBUG_PC_6 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT12, 0x0658, 0x0288, 5, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT12__GPIO_5_30 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT12, 0x0658, 0x0288, 6, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT12__MMDC_MMDC_DEBUG_35 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT12, 0x0658, 0x0288, 7, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT12__CHEETAH_TRACE_9 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT13, 0x065C, 0x028C, 0, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT13__IPU1_CSI0_D_13 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT13, 0x065C, 0x028C, 1, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT13__WEIM_WEIM_D_9 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT13, 0x065C, 0x028C, 2, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT13__PCIE_CTRL_MUX_17 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT13, 0x065C, 0x028C, 3, 0x0938, 3), /* MX6Q_PAD_CSI0_DAT13__UART4_RXD */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT13, 0x065C, 0x028C, 4, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT13__SDMA_DEBUG_PC_7 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT13, 0x065C, 0x028C, 5, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT13__GPIO_5_31 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT13, 0x065C, 0x028C, 6, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT13__MMDC_MMDC_DEBUG_36 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT13, 0x065C, 0x028C, 7, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT13__CHEETAH_TRACE_10 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT14, 0x0660, 0x0290, 0, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT14__IPU1_CSI0_D_14 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT14, 0x0660, 0x0290, 1, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT14__WEIM_WEIM_D_10 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT14, 0x0660, 0x0290, 2, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT14__PCIE_CTRL_MUX_18 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT14, 0x0660, 0x0290, 3, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT14__UART5_TXD */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT14, 0x0660, 0x0290, 4, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT14__SDMA_DEBUG_PC_8 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT14, 0x0660, 0x0290, 5, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT14__GPIO_6_0 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT14, 0x0660, 0x0290, 6, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT14__MMDC_MMDC_DEBUG_37 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT14, 0x0660, 0x0290, 7, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT14__CHEETAH_TRACE_11 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT15, 0x0664, 0x0294, 0, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT15__IPU1_CSI0_D_15 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT15, 0x0664, 0x0294, 1, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT15__WEIM_WEIM_D_11 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT15, 0x0664, 0x0294, 2, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT15__PCIE_CTRL_MUX_19 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT15, 0x0664, 0x0294, 3, 0x0940, 3), /* MX6Q_PAD_CSI0_DAT15__UART5_RXD */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT15, 0x0664, 0x0294, 4, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT15__SDMA_DEBUG_PC_9 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT15, 0x0664, 0x0294, 5, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT15__GPIO_6_1 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT15, 0x0664, 0x0294, 6, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT15__MMDC_MMDC_DEBUG_38 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT15, 0x0664, 0x0294, 7, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT15__CHEETAH_TRACE_12 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT16, 0x0668, 0x0298, 0, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT16__IPU1_CSI0_D_16 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT16, 0x0668, 0x0298, 1, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT16__WEIM_WEIM_D_12 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT16, 0x0668, 0x0298, 2, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT16__PCIE_CTRL_MUX_20 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT16, 0x0668, 0x0298, 3, 0x0934, 0), /* MX6Q_PAD_CSI0_DAT16__UART4_RTS */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT16, 0x0668, 0x0298, 4, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT16__SDMA_DEBUG_PC_10 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT16, 0x0668, 0x0298, 5, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT16__GPIO_6_2 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT16, 0x0668, 0x0298, 6, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT16__MMDC_MMDC_DEBUG_39 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT16, 0x0668, 0x0298, 7, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT16__CHEETAH_TRACE_13 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT17, 0x066C, 0x029C, 0, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT17__IPU1_CSI0_D_17 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT17, 0x066C, 0x029C, 1, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT17__WEIM_WEIM_D_13 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT17, 0x066C, 0x029C, 2, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT17__PCIE_CTRL_MUX_21 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT17, 0x066C, 0x029C, 3, 0x0934, 1), /* MX6Q_PAD_CSI0_DAT17__UART4_CTS */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT17, 0x066C, 0x029C, 4, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT17__SDMA_DEBUG_PC_11 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT17, 0x066C, 0x029C, 5, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT17__GPIO_6_3 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT17, 0x066C, 0x029C, 6, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT17__MMDC_MMDC_DEBUG_40 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT17, 0x066C, 0x029C, 7, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT17__CHEETAH_TRACE_14 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT18, 0x0670, 0x02A0, 0, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT18__IPU1_CSI0_D_18 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT18, 0x0670, 0x02A0, 1, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT18__WEIM_WEIM_D_14 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT18, 0x0670, 0x02A0, 2, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT18__PCIE_CTRL_MUX_22 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT18, 0x0670, 0x02A0, 3, 0x093C, 2), /* MX6Q_PAD_CSI0_DAT18__UART5_RTS */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT18, 0x0670, 0x02A0, 4, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT18__SDMA_DEBUG_PC_12 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT18, 0x0670, 0x02A0, 5, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT18__GPIO_6_4 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT18, 0x0670, 0x02A0, 6, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT18__MMDC_MMDC_DEBUG_41 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT18, 0x0670, 0x02A0, 7, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT18__CHEETAH_TRACE_15 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT19, 0x0674, 0x02A4, 0, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT19__IPU1_CSI0_D_19 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT19, 0x0674, 0x02A4, 1, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT19__WEIM_WEIM_D_15 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT19, 0x0674, 0x02A4, 2, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT19__PCIE_CTRL_MUX_23 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT19, 0x0674, 0x02A4, 3, 0x093C, 3), /* MX6Q_PAD_CSI0_DAT19__UART5_CTS */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT19, 0x0674, 0x02A4, 4, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT19__SDMA_DEBUG_PC_13 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT19, 0x0674, 0x02A4, 5, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT19__GPIO_6_5 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT19, 0x0674, 0x02A4, 6, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT19__MMDC_MMDC_DEBUG_42 */
-	IMX_PIN_REG(MX6Q_PAD_CSI0_DAT19, 0x0674, 0x02A4, 7, 0x0000, 0), /* MX6Q_PAD_CSI0_DAT19__ANATOP_TESTO_9 */
-	IMX_PIN_REG(MX6Q_PAD_JTAG_TMS, 0x0678, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_JTAG_TMS__SJC_TMS */
-	IMX_PIN_REG(MX6Q_PAD_JTAG_MOD, 0x067C, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_JTAG_MOD__SJC_MOD */
-	IMX_PIN_REG(MX6Q_PAD_JTAG_TRSTB, 0x0680, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_JTAG_TRSTB__SJC_TRSTB */
-	IMX_PIN_REG(MX6Q_PAD_JTAG_TDI, 0x0684, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_JTAG_TDI__SJC_TDI */
-	IMX_PIN_REG(MX6Q_PAD_JTAG_TCK, 0x0688, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_JTAG_TCK__SJC_TCK */
-	IMX_PIN_REG(MX6Q_PAD_JTAG_TDO, 0x068C, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_JTAG_TDO__SJC_TDO */
-	IMX_PIN_REG(MX6Q_PAD_LVDS1_TX3_P, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_LVDS1_TX3_P__LDB_LVDS1_TX3 */
-	IMX_PIN_REG(MX6Q_PAD_LVDS1_TX2_P, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_LVDS1_TX2_P__LDB_LVDS1_TX2 */
-	IMX_PIN_REG(MX6Q_PAD_LVDS1_CLK_P, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_LVDS1_CLK_P__LDB_LVDS1_CLK */
-	IMX_PIN_REG(MX6Q_PAD_LVDS1_TX1_P, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_LVDS1_TX1_P__LDB_LVDS1_TX1 */
-	IMX_PIN_REG(MX6Q_PAD_LVDS1_TX0_P, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_LVDS1_TX0_P__LDB_LVDS1_TX0 */
-	IMX_PIN_REG(MX6Q_PAD_LVDS0_TX3_P, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_LVDS0_TX3_P__LDB_LVDS0_TX3 */
-	IMX_PIN_REG(MX6Q_PAD_LVDS0_CLK_P, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_LVDS0_CLK_P__LDB_LVDS0_CLK */
-	IMX_PIN_REG(MX6Q_PAD_LVDS0_TX2_P, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_LVDS0_TX2_P__LDB_LVDS0_TX2 */
-	IMX_PIN_REG(MX6Q_PAD_LVDS0_TX1_P, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1 */
-	IMX_PIN_REG(MX6Q_PAD_LVDS0_TX0_P, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0 */
-	IMX_PIN_REG(MX6Q_PAD_TAMPER, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_TAMPER__SNVS_LP_WRAP_SNVS_TD1 */
-	IMX_PIN_REG(MX6Q_PAD_PMIC_ON_REQ, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_PMIC_ON_REQ__SNVS_LPWRAP_WKALM */
-	IMX_PIN_REG(MX6Q_PAD_PMIC_STBY_REQ, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_PMIC_STBY_REQ__CCM_PMIC_STBYRQ */
-	IMX_PIN_REG(MX6Q_PAD_POR_B, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_POR_B__SRC_POR_B */
-	IMX_PIN_REG(MX6Q_PAD_BOOT_MODE1, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_BOOT_MODE1__SRC_BOOT_MODE_1 */
-	IMX_PIN_REG(MX6Q_PAD_RESET_IN_B, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_RESET_IN_B__SRC_RESET_B */
-	IMX_PIN_REG(MX6Q_PAD_BOOT_MODE0, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_BOOT_MODE0__SRC_BOOT_MODE_0 */
-	IMX_PIN_REG(MX6Q_PAD_TEST_MODE, NO_PAD, NO_MUX, 0, 0x0000, 0), /* MX6Q_PAD_TEST_MODE__TCU_TEST_MODE */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT7, 0x0690, 0x02A8, 0, 0x0000, 0), /* MX6Q_PAD_SD3_DAT7__USDHC3_DAT7 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT7, 0x0690, 0x02A8, 1, 0x0000, 0), /* MX6Q_PAD_SD3_DAT7__UART1_TXD */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT7, 0x0690, 0x02A8, 2, 0x0000, 0), /* MX6Q_PAD_SD3_DAT7__PCIE_CTRL_MUX_24 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT7, 0x0690, 0x02A8, 3, 0x0000, 0), /* MX6Q_PAD_SD3_DAT7__USBOH3_UH3_DFD_OUT_0 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT7, 0x0690, 0x02A8, 4, 0x0000, 0), /* MX6Q_PAD_SD3_DAT7__USBOH3_UH2_DFD_OUT_0 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT7, 0x0690, 0x02A8, 5, 0x0000, 0), /* MX6Q_PAD_SD3_DAT7__GPIO_6_17 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT7, 0x0690, 0x02A8, 6, 0x0000, 0), /* MX6Q_PAD_SD3_DAT7__MIPI_CORE_DPHY_IN_12 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT7, 0x0690, 0x02A8, 7, 0x0000, 0), /* MX6Q_PAD_SD3_DAT7__USBPHY2_CLK20DIV */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT6, 0x0694, 0x02AC, 0, 0x0000, 0), /* MX6Q_PAD_SD3_DAT6__USDHC3_DAT6 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT6, 0x0694, 0x02AC, 1, 0x0920, 3), /* MX6Q_PAD_SD3_DAT6__UART1_RXD */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT6, 0x0694, 0x02AC, 2, 0x0000, 0), /* MX6Q_PAD_SD3_DAT6__PCIE_CTRL_MUX_25 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT6, 0x0694, 0x02AC, 3, 0x0000, 0), /* MX6Q_PAD_SD3_DAT6__USBOH3_UH3_DFD_OUT_1 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT6, 0x0694, 0x02AC, 4, 0x0000, 0), /* MX6Q_PAD_SD3_DAT6__USBOH3_UH2_DFD_OUT_1 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT6, 0x0694, 0x02AC, 5, 0x0000, 0), /* MX6Q_PAD_SD3_DAT6__GPIO_6_18 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT6, 0x0694, 0x02AC, 6, 0x0000, 0), /* MX6Q_PAD_SD3_DAT6__MIPI_CORE_DPHY_IN_13 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT6, 0x0694, 0x02AC, 7, 0x0000, 0), /* MX6Q_PAD_SD3_DAT6__ANATOP_TESTO_10 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT5, 0x0698, 0x02B0, 0, 0x0000, 0), /* MX6Q_PAD_SD3_DAT5__USDHC3_DAT5 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT5, 0x0698, 0x02B0, 1, 0x0000, 0), /* MX6Q_PAD_SD3_DAT5__UART2_TXD */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT5, 0x0698, 0x02B0, 2, 0x0000, 0), /* MX6Q_PAD_SD3_DAT5__PCIE_CTRL_MUX_26 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT5, 0x0698, 0x02B0, 3, 0x0000, 0), /* MX6Q_PAD_SD3_DAT5__USBOH3_UH3_DFD_OUT_2 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT5, 0x0698, 0x02B0, 4, 0x0000, 0), /* MX6Q_PAD_SD3_DAT5__USBOH3_UH2_DFD_OUT_2 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT5, 0x0698, 0x02B0, 5, 0x0000, 0), /* MX6Q_PAD_SD3_DAT5__GPIO_7_0 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT5, 0x0698, 0x02B0, 6, 0x0000, 0), /* MX6Q_PAD_SD3_DAT5__MIPI_CORE_DPHY_IN_14 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT5, 0x0698, 0x02B0, 7, 0x0000, 0), /* MX6Q_PAD_SD3_DAT5__ANATOP_TESTO_11 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT4, 0x069C, 0x02B4, 0, 0x0000, 0), /* MX6Q_PAD_SD3_DAT4__USDHC3_DAT4 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT4, 0x069C, 0x02B4, 1, 0x0928, 5), /* MX6Q_PAD_SD3_DAT4__UART2_RXD */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT4, 0x069C, 0x02B4, 2, 0x0000, 0), /* MX6Q_PAD_SD3_DAT4__PCIE_CTRL_MUX_27 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT4, 0x069C, 0x02B4, 3, 0x0000, 0), /* MX6Q_PAD_SD3_DAT4__USBOH3_UH3_DFD_OUT_3 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT4, 0x069C, 0x02B4, 4, 0x0000, 0), /* MX6Q_PAD_SD3_DAT4__USBOH3_UH2_DFD_OUT_3 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT4, 0x069C, 0x02B4, 5, 0x0000, 0), /* MX6Q_PAD_SD3_DAT4__GPIO_7_1 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT4, 0x069C, 0x02B4, 6, 0x0000, 0), /* MX6Q_PAD_SD3_DAT4__MIPI_CORE_DPHY_IN_15 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT4, 0x069C, 0x02B4, 7, 0x0000, 0), /* MX6Q_PAD_SD3_DAT4__ANATOP_TESTO_12 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_CMD, 0x06A0, 0x02B8, 0, 0x0000, 0), /* MX6Q_PAD_SD3_CMD__USDHC3_CMD */
-	IMX_PIN_REG(MX6Q_PAD_SD3_CMD, 0x06A0, 0x02B8, 1, 0x0924, 2), /* MX6Q_PAD_SD3_CMD__UART2_CTS */
-	IMX_PIN_REG(MX6Q_PAD_SD3_CMD, 0x06A0, 0x02B8, 2, 0x0000, 0), /* MX6Q_PAD_SD3_CMD__CAN1_TXCAN */
-	IMX_PIN_REG(MX6Q_PAD_SD3_CMD, 0x06A0, 0x02B8, 3, 0x0000, 0), /* MX6Q_PAD_SD3_CMD__USBOH3_UH3_DFD_OUT_4 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_CMD, 0x06A0, 0x02B8, 4, 0x0000, 0), /* MX6Q_PAD_SD3_CMD__USBOH3_UH2_DFD_OUT_4 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_CMD, 0x06A0, 0x02B8, 5, 0x0000, 0), /* MX6Q_PAD_SD3_CMD__GPIO_7_2 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_CMD, 0x06A0, 0x02B8, 6, 0x0000, 0), /* MX6Q_PAD_SD3_CMD__MIPI_CORE_DPHY_IN_16 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_CMD, 0x06A0, 0x02B8, 7, 0x0000, 0), /* MX6Q_PAD_SD3_CMD__ANATOP_TESTO_13 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_CLK, 0x06A4, 0x02BC, 0, 0x0000, 0), /* MX6Q_PAD_SD3_CLK__USDHC3_CLK */
-	IMX_PIN_REG(MX6Q_PAD_SD3_CLK, 0x06A4, 0x02BC, 1, 0x0924, 3), /* MX6Q_PAD_SD3_CLK__UART2_RTS */
-	IMX_PIN_REG(MX6Q_PAD_SD3_CLK, 0x06A4, 0x02BC, 2, 0x07E4, 2), /* MX6Q_PAD_SD3_CLK__CAN1_RXCAN */
-	IMX_PIN_REG(MX6Q_PAD_SD3_CLK, 0x06A4, 0x02BC, 3, 0x0000, 0), /* MX6Q_PAD_SD3_CLK__USBOH3_UH3_DFD_OUT_5 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_CLK, 0x06A4, 0x02BC, 4, 0x0000, 0), /* MX6Q_PAD_SD3_CLK__USBOH3_UH2_DFD_OUT_5 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_CLK, 0x06A4, 0x02BC, 5, 0x0000, 0), /* MX6Q_PAD_SD3_CLK__GPIO_7_3 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_CLK, 0x06A4, 0x02BC, 6, 0x0000, 0), /* MX6Q_PAD_SD3_CLK__MIPI_CORE_DPHY_IN_17 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_CLK, 0x06A4, 0x02BC, 7, 0x0000, 0), /* MX6Q_PAD_SD3_CLK__ANATOP_TESTO_14 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT0, 0x06A8, 0x02C0, 0, 0x0000, 0), /* MX6Q_PAD_SD3_DAT0__USDHC3_DAT0 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT0, 0x06A8, 0x02C0, 1, 0x091C, 2), /* MX6Q_PAD_SD3_DAT0__UART1_CTS */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT0, 0x06A8, 0x02C0, 2, 0x0000, 0), /* MX6Q_PAD_SD3_DAT0__CAN2_TXCAN */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT0, 0x06A8, 0x02C0, 3, 0x0000, 0), /* MX6Q_PAD_SD3_DAT0__USBOH3_UH3_DFD_OUT_6 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT0, 0x06A8, 0x02C0, 4, 0x0000, 0), /* MX6Q_PAD_SD3_DAT0__USBOH3_UH2_DFD_OUT_6 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT0, 0x06A8, 0x02C0, 5, 0x0000, 0), /* MX6Q_PAD_SD3_DAT0__GPIO_7_4 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT0, 0x06A8, 0x02C0, 6, 0x0000, 0), /* MX6Q_PAD_SD3_DAT0__MIPI_CORE_DPHY_IN_18 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT0, 0x06A8, 0x02C0, 7, 0x0000, 0), /* MX6Q_PAD_SD3_DAT0__ANATOP_TESTO_15 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT1, 0x06AC, 0x02C4, 0, 0x0000, 0), /* MX6Q_PAD_SD3_DAT1__USDHC3_DAT1 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT1, 0x06AC, 0x02C4, 1, 0x091C, 3), /* MX6Q_PAD_SD3_DAT1__UART1_RTS */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT1, 0x06AC, 0x02C4, 2, 0x07E8, 1), /* MX6Q_PAD_SD3_DAT1__CAN2_RXCAN */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT1, 0x06AC, 0x02C4, 3, 0x0000, 0), /* MX6Q_PAD_SD3_DAT1__USBOH3_UH3_DFD_OUT_7 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT1, 0x06AC, 0x02C4, 4, 0x0000, 0), /* MX6Q_PAD_SD3_DAT1__USBOH3_UH2_DFD_OUT_7 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT1, 0x06AC, 0x02C4, 5, 0x0000, 0), /* MX6Q_PAD_SD3_DAT1__GPIO_7_5 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT1, 0x06AC, 0x02C4, 6, 0x0000, 0), /* MX6Q_PAD_SD3_DAT1__MIPI_CORE_DPHY_IN_19 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT1, 0x06AC, 0x02C4, 7, 0x0000, 0), /* MX6Q_PAD_SD3_DAT1__ANATOP_TESTI_0 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT2, 0x06B0, 0x02C8, 0, 0x0000, 0), /* MX6Q_PAD_SD3_DAT2__USDHC3_DAT2 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT2, 0x06B0, 0x02C8, 2, 0x0000, 0), /* MX6Q_PAD_SD3_DAT2__PCIE_CTRL_MUX_28 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT2, 0x06B0, 0x02C8, 3, 0x0000, 0), /* MX6Q_PAD_SD3_DAT2__USBOH3_UH3_DFD_OUT_8 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT2, 0x06B0, 0x02C8, 4, 0x0000, 0), /* MX6Q_PAD_SD3_DAT2__USBOH3_UH2_DFD_OUT_8 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT2, 0x06B0, 0x02C8, 5, 0x0000, 0), /* MX6Q_PAD_SD3_DAT2__GPIO_7_6 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT2, 0x06B0, 0x02C8, 6, 0x0000, 0), /* MX6Q_PAD_SD3_DAT2__MIPI_CORE_DPHY_IN_20 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT2, 0x06B0, 0x02C8, 7, 0x0000, 0), /* MX6Q_PAD_SD3_DAT2__ANATOP_TESTI_1 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT3, 0x06B4, 0x02CC, 0, 0x0000, 0), /* MX6Q_PAD_SD3_DAT3__USDHC3_DAT3 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT3, 0x06B4, 0x02CC, 1, 0x092C, 4), /* MX6Q_PAD_SD3_DAT3__UART3_CTS */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT3, 0x06B4, 0x02CC, 2, 0x0000, 0), /* MX6Q_PAD_SD3_DAT3__PCIE_CTRL_MUX_29 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT3, 0x06B4, 0x02CC, 3, 0x0000, 0), /* MX6Q_PAD_SD3_DAT3__USBOH3_UH3_DFD_OUT_9 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT3, 0x06B4, 0x02CC, 4, 0x0000, 0), /* MX6Q_PAD_SD3_DAT3__USBOH3_UH2_DFD_OUT_9 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT3, 0x06B4, 0x02CC, 5, 0x0000, 0), /* MX6Q_PAD_SD3_DAT3__GPIO_7_7 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT3, 0x06B4, 0x02CC, 6, 0x0000, 0), /* MX6Q_PAD_SD3_DAT3__MIPI_CORE_DPHY_IN_21 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_DAT3, 0x06B4, 0x02CC, 7, 0x0000, 0), /* MX6Q_PAD_SD3_DAT3__ANATOP_TESTI_2 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_RST, 0x06B8, 0x02D0, 0, 0x0000, 0), /* MX6Q_PAD_SD3_RST__USDHC3_RST */
-	IMX_PIN_REG(MX6Q_PAD_SD3_RST, 0x06B8, 0x02D0, 1, 0x092C, 5), /* MX6Q_PAD_SD3_RST__UART3_RTS */
-	IMX_PIN_REG(MX6Q_PAD_SD3_RST, 0x06B8, 0x02D0, 2, 0x0000, 0), /* MX6Q_PAD_SD3_RST__PCIE_CTRL_MUX_30 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_RST, 0x06B8, 0x02D0, 3, 0x0000, 0), /* MX6Q_PAD_SD3_RST__USBOH3_UH3_DFD_OUT_10 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_RST, 0x06B8, 0x02D0, 4, 0x0000, 0), /* MX6Q_PAD_SD3_RST__USBOH3_UH2_DFD_OUT_10 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_RST, 0x06B8, 0x02D0, 5, 0x0000, 0), /* MX6Q_PAD_SD3_RST__GPIO_7_8 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_RST, 0x06B8, 0x02D0, 6, 0x0000, 0), /* MX6Q_PAD_SD3_RST__MIPI_CORE_DPHY_IN_22 */
-	IMX_PIN_REG(MX6Q_PAD_SD3_RST, 0x06B8, 0x02D0, 7, 0x0000, 0), /* MX6Q_PAD_SD3_RST__ANATOP_ANATOP_TESTI_3 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_CLE, 0x06BC, 0x02D4, 0, 0x0000, 0), /* MX6Q_PAD_NANDF_CLE__RAWNAND_CLE */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_CLE, 0x06BC, 0x02D4, 1, 0x0000, 0), /* MX6Q_PAD_NANDF_CLE__IPU2_SISG_4 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_CLE, 0x06BC, 0x02D4, 2, 0x0000, 0), /* MX6Q_PAD_NANDF_CLE__PCIE_CTRL_MUX_31 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_CLE, 0x06BC, 0x02D4, 3, 0x0000, 0), /* MX6Q_PAD_NANDF_CLE__USBOH3_UH3_DFD_OT11 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_CLE, 0x06BC, 0x02D4, 4, 0x0000, 0), /* MX6Q_PAD_NANDF_CLE__USBOH3_UH2_DFD_OT11 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_CLE, 0x06BC, 0x02D4, 5, 0x0000, 0), /* MX6Q_PAD_NANDF_CLE__GPIO_6_7 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_CLE, 0x06BC, 0x02D4, 6, 0x0000, 0), /* MX6Q_PAD_NANDF_CLE__MIPI_CORE_DPHY_IN23 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_CLE, 0x06BC, 0x02D4, 7, 0x0000, 0), /* MX6Q_PAD_NANDF_CLE__TPSMP_HTRANS_0 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_ALE, 0x06C0, 0x02D8, 0, 0x0000, 0), /* MX6Q_PAD_NANDF_ALE__RAWNAND_ALE */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_ALE, 0x06C0, 0x02D8, 1, 0x0000, 0), /* MX6Q_PAD_NANDF_ALE__USDHC4_RST */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_ALE, 0x06C0, 0x02D8, 2, 0x0000, 0), /* MX6Q_PAD_NANDF_ALE__PCIE_CTRL_MUX_0 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_ALE, 0x06C0, 0x02D8, 3, 0x0000, 0), /* MX6Q_PAD_NANDF_ALE__USBOH3_UH3_DFD_OT12 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_ALE, 0x06C0, 0x02D8, 4, 0x0000, 0), /* MX6Q_PAD_NANDF_ALE__USBOH3_UH2_DFD_OT12 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_ALE, 0x06C0, 0x02D8, 5, 0x0000, 0), /* MX6Q_PAD_NANDF_ALE__GPIO_6_8 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_ALE, 0x06C0, 0x02D8, 6, 0x0000, 0), /* MX6Q_PAD_NANDF_ALE__MIPI_CR_DPHY_IN_24 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_ALE, 0x06C0, 0x02D8, 7, 0x0000, 0), /* MX6Q_PAD_NANDF_ALE__TPSMP_HTRANS_1 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_WP_B, 0x06C4, 0x02DC, 0, 0x0000, 0), /* MX6Q_PAD_NANDF_WP_B__RAWNAND_RESETN */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_WP_B, 0x06C4, 0x02DC, 1, 0x0000, 0), /* MX6Q_PAD_NANDF_WP_B__IPU2_SISG_5 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_WP_B, 0x06C4, 0x02DC, 2, 0x0000, 0), /* MX6Q_PAD_NANDF_WP_B__PCIE_CTRL__MUX_1 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_WP_B, 0x06C4, 0x02DC, 3, 0x0000, 0), /* MX6Q_PAD_NANDF_WP_B__USBOH3_UH3_DFDOT13 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_WP_B, 0x06C4, 0x02DC, 4, 0x0000, 0), /* MX6Q_PAD_NANDF_WP_B__USBOH3_UH2_DFDOT13 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_WP_B, 0x06C4, 0x02DC, 5, 0x0000, 0), /* MX6Q_PAD_NANDF_WP_B__GPIO_6_9 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_WP_B, 0x06C4, 0x02DC, 6, 0x0000, 0), /* MX6Q_PAD_NANDF_WP_B__MIPI_CR_DPHY_OUT32 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_WP_B, 0x06C4, 0x02DC, 7, 0x0000, 0), /* MX6Q_PAD_NANDF_WP_B__PL301_PER1_HSIZE_0 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_RB0, 0x06C8, 0x02E0, 0, 0x0000, 0), /* MX6Q_PAD_NANDF_RB0__RAWNAND_READY0 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_RB0, 0x06C8, 0x02E0, 1, 0x0000, 0), /* MX6Q_PAD_NANDF_RB0__IPU2_DI0_PIN1 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_RB0, 0x06C8, 0x02E0, 2, 0x0000, 0), /* MX6Q_PAD_NANDF_RB0__PCIE_CTRL_MUX_2 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_RB0, 0x06C8, 0x02E0, 3, 0x0000, 0), /* MX6Q_PAD_NANDF_RB0__USBOH3_UH3_DFD_OT14 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_RB0, 0x06C8, 0x02E0, 4, 0x0000, 0), /* MX6Q_PAD_NANDF_RB0__USBOH3_UH2_DFD_OT14 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_RB0, 0x06C8, 0x02E0, 5, 0x0000, 0), /* MX6Q_PAD_NANDF_RB0__GPIO_6_10 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_RB0, 0x06C8, 0x02E0, 6, 0x0000, 0), /* MX6Q_PAD_NANDF_RB0__MIPI_CR_DPHY_OUT_33 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_RB0, 0x06C8, 0x02E0, 7, 0x0000, 0), /* MX6Q_PAD_NANDF_RB0__PL301_PER1_HSIZE_1 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_CS0, 0x06CC, 0x02E4, 0, 0x0000, 0), /* MX6Q_PAD_NANDF_CS0__RAWNAND_CE0N */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_CS0, 0x06CC, 0x02E4, 3, 0x0000, 0), /* MX6Q_PAD_NANDF_CS0__USBOH3_UH3_DFD_OT15 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_CS0, 0x06CC, 0x02E4, 4, 0x0000, 0), /* MX6Q_PAD_NANDF_CS0__USBOH3_UH2_DFD_OT15 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_CS0, 0x06CC, 0x02E4, 5, 0x0000, 0), /* MX6Q_PAD_NANDF_CS0__GPIO_6_11 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_CS0, 0x06CC, 0x02E4, 7, 0x0000, 0), /* MX6Q_PAD_NANDF_CS0__PL301_PER1_HSIZE_2 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_CS1, 0x06D0, 0x02E8, 0, 0x0000, 0), /* MX6Q_PAD_NANDF_CS1__RAWNAND_CE1N */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_CS1, 0x06D0, 0x02E8, 1, 0x0000, 0), /* MX6Q_PAD_NANDF_CS1__USDHC4_VSELECT */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_CS1, 0x06D0, 0x02E8, 2, 0x0000, 0), /* MX6Q_PAD_NANDF_CS1__USDHC3_VSELECT */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_CS1, 0x06D0, 0x02E8, 4, 0x0000, 0), /* MX6Q_PAD_NANDF_CS1__PCIE_CTRL_MUX_3 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_CS1, 0x06D0, 0x02E8, 5, 0x0000, 0), /* MX6Q_PAD_NANDF_CS1__GPIO_6_14 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_CS1, 0x06D0, 0x02E8, 7, 0x0000, 0), /* MX6Q_PAD_NANDF_CS1__PL301_PER1_HRDYOUT */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_CS2, 0x06D4, 0x02EC, 0, 0x0000, 0), /* MX6Q_PAD_NANDF_CS2__RAWNAND_CE2N */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_CS2, 0x06D4, 0x02EC, 1, 0x0000, 0), /* MX6Q_PAD_NANDF_CS2__IPU1_SISG_0 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_CS2, 0x06D4, 0x02EC, 2, 0x0874, 1), /* MX6Q_PAD_NANDF_CS2__ESAI1_TX0 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_CS2, 0x06D4, 0x02EC, 3, 0x0000, 0), /* MX6Q_PAD_NANDF_CS2__WEIM_WEIM_CRE */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_CS2, 0x06D4, 0x02EC, 4, 0x0000, 0), /* MX6Q_PAD_NANDF_CS2__CCM_CLKO2 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_CS2, 0x06D4, 0x02EC, 5, 0x0000, 0), /* MX6Q_PAD_NANDF_CS2__GPIO_6_15 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_CS2, 0x06D4, 0x02EC, 6, 0x0000, 0), /* MX6Q_PAD_NANDF_CS2__IPU2_SISG_0 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_CS3, 0x06D8, 0x02F0, 0, 0x0000, 0), /* MX6Q_PAD_NANDF_CS3__RAWNAND_CE3N */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_CS3, 0x06D8, 0x02F0, 1, 0x0000, 0), /* MX6Q_PAD_NANDF_CS3__IPU1_SISG_1 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_CS3, 0x06D8, 0x02F0, 2, 0x0878, 1), /* MX6Q_PAD_NANDF_CS3__ESAI1_TX1 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_CS3, 0x06D8, 0x02F0, 3, 0x0000, 0), /* MX6Q_PAD_NANDF_CS3__WEIM_WEIM_A_26 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_CS3, 0x06D8, 0x02F0, 4, 0x0000, 0), /* MX6Q_PAD_NANDF_CS3__PCIE_CTRL_MUX_4 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_CS3, 0x06D8, 0x02F0, 5, 0x0000, 0), /* MX6Q_PAD_NANDF_CS3__GPIO_6_16 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_CS3, 0x06D8, 0x02F0, 6, 0x0000, 0), /* MX6Q_PAD_NANDF_CS3__IPU2_SISG_1 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_CS3, 0x06D8, 0x02F0, 7, 0x0000, 0), /* MX6Q_PAD_NANDF_CS3__TPSMP_CLK */
-	IMX_PIN_REG(MX6Q_PAD_SD4_CMD, 0x06DC, 0x02F4, 0, 0x0000, 0), /* MX6Q_PAD_SD4_CMD__USDHC4_CMD */
-	IMX_PIN_REG(MX6Q_PAD_SD4_CMD, 0x06DC, 0x02F4, 1, 0x0000, 0), /* MX6Q_PAD_SD4_CMD__RAWNAND_RDN */
-	IMX_PIN_REG(MX6Q_PAD_SD4_CMD, 0x06DC, 0x02F4, 2, 0x0000, 0), /* MX6Q_PAD_SD4_CMD__UART3_TXD */
-	IMX_PIN_REG(MX6Q_PAD_SD4_CMD, 0x06DC, 0x02F4, 4, 0x0000, 0), /* MX6Q_PAD_SD4_CMD__PCIE_CTRL_MUX_5 */
-	IMX_PIN_REG(MX6Q_PAD_SD4_CMD, 0x06DC, 0x02F4, 5, 0x0000, 0), /* MX6Q_PAD_SD4_CMD__GPIO_7_9 */
-	IMX_PIN_REG(MX6Q_PAD_SD4_CMD, 0x06DC, 0x02F4, 7, 0x0000, 0), /* MX6Q_PAD_SD4_CMD__TPSMP_HDATA_DIR */
-	IMX_PIN_REG(MX6Q_PAD_SD4_CLK, 0x06E0, 0x02F8, 0, 0x0000, 0), /* MX6Q_PAD_SD4_CLK__USDHC4_CLK */
-	IMX_PIN_REG(MX6Q_PAD_SD4_CLK, 0x06E0, 0x02F8, 1, 0x0000, 0), /* MX6Q_PAD_SD4_CLK__RAWNAND_WRN */
-	IMX_PIN_REG(MX6Q_PAD_SD4_CLK, 0x06E0, 0x02F8, 2, 0x0930, 3), /* MX6Q_PAD_SD4_CLK__UART3_RXD */
-	IMX_PIN_REG(MX6Q_PAD_SD4_CLK, 0x06E0, 0x02F8, 4, 0x0000, 0), /* MX6Q_PAD_SD4_CLK__PCIE_CTRL_MUX_6 */
-	IMX_PIN_REG(MX6Q_PAD_SD4_CLK, 0x06E0, 0x02F8, 5, 0x0000, 0), /* MX6Q_PAD_SD4_CLK__GPIO_7_10 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D0, 0x06E4, 0x02FC, 0, 0x0000, 0), /* MX6Q_PAD_NANDF_D0__RAWNAND_D0 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D0, 0x06E4, 0x02FC, 1, 0x0000, 0), /* MX6Q_PAD_NANDF_D0__USDHC1_DAT4 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D0, 0x06E4, 0x02FC, 2, 0x0000, 0), /* MX6Q_PAD_NANDF_D0__GPU3D_GPU_DBG_OUT_0 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D0, 0x06E4, 0x02FC, 3, 0x0000, 0), /* MX6Q_PAD_NANDF_D0__USBOH3_UH2_DFD_OUT16 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D0, 0x06E4, 0x02FC, 4, 0x0000, 0), /* MX6Q_PAD_NANDF_D0__USBOH3_UH3_DFD_OUT16 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D0, 0x06E4, 0x02FC, 5, 0x0000, 0), /* MX6Q_PAD_NANDF_D0__GPIO_2_0 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D0, 0x06E4, 0x02FC, 6, 0x0000, 0), /* MX6Q_PAD_NANDF_D0__IPU1_IPU_DIAG_BUS_0 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D0, 0x06E4, 0x02FC, 7, 0x0000, 0), /* MX6Q_PAD_NANDF_D0__IPU2_IPU_DIAG_BUS_0 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D1, 0x06E8, 0x0300, 0, 0x0000, 0), /* MX6Q_PAD_NANDF_D1__RAWNAND_D1 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D1, 0x06E8, 0x0300, 1, 0x0000, 0), /* MX6Q_PAD_NANDF_D1__USDHC1_DAT5 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D1, 0x06E8, 0x0300, 2, 0x0000, 0), /* MX6Q_PAD_NANDF_D1__GPU3D_GPU_DEBUG_OUT1 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D1, 0x06E8, 0x0300, 3, 0x0000, 0), /* MX6Q_PAD_NANDF_D1__USBOH3_UH2_DFD_OUT17 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D1, 0x06E8, 0x0300, 4, 0x0000, 0), /* MX6Q_PAD_NANDF_D1__USBOH3_UH3_DFD_OUT17 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D1, 0x06E8, 0x0300, 5, 0x0000, 0), /* MX6Q_PAD_NANDF_D1__GPIO_2_1 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D1, 0x06E8, 0x0300, 6, 0x0000, 0), /* MX6Q_PAD_NANDF_D1__IPU1_IPU_DIAG_BUS_1 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D1, 0x06E8, 0x0300, 7, 0x0000, 0), /* MX6Q_PAD_NANDF_D1__IPU2_IPU_DIAG_BUS_1 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D2, 0x06EC, 0x0304, 0, 0x0000, 0), /* MX6Q_PAD_NANDF_D2__RAWNAND_D2 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D2, 0x06EC, 0x0304, 1, 0x0000, 0), /* MX6Q_PAD_NANDF_D2__USDHC1_DAT6 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D2, 0x06EC, 0x0304, 2, 0x0000, 0), /* MX6Q_PAD_NANDF_D2__GPU3D_GPU_DBG_OUT_2 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D2, 0x06EC, 0x0304, 3, 0x0000, 0), /* MX6Q_PAD_NANDF_D2__USBOH3_UH2_DFD_OUT18 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D2, 0x06EC, 0x0304, 4, 0x0000, 0), /* MX6Q_PAD_NANDF_D2__USBOH3_UH3_DFD_OUT18 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D2, 0x06EC, 0x0304, 5, 0x0000, 0), /* MX6Q_PAD_NANDF_D2__GPIO_2_2 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D2, 0x06EC, 0x0304, 6, 0x0000, 0), /* MX6Q_PAD_NANDF_D2__IPU1_IPU_DIAG_BUS_2 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D2, 0x06EC, 0x0304, 7, 0x0000, 0), /* MX6Q_PAD_NANDF_D2__IPU2_IPU_DIAG_BUS_2 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D3, 0x06F0, 0x0308, 0, 0x0000, 0), /* MX6Q_PAD_NANDF_D3__RAWNAND_D3 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D3, 0x06F0, 0x0308, 1, 0x0000, 0), /* MX6Q_PAD_NANDF_D3__USDHC1_DAT7 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D3, 0x06F0, 0x0308, 2, 0x0000, 0), /* MX6Q_PAD_NANDF_D3__GPU3D_GPU_DBG_OUT_3 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D3, 0x06F0, 0x0308, 3, 0x0000, 0), /* MX6Q_PAD_NANDF_D3__USBOH3_UH2_DFD_OUT19 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D3, 0x06F0, 0x0308, 4, 0x0000, 0), /* MX6Q_PAD_NANDF_D3__USBOH3_UH3_DFD_OUT19 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D3, 0x06F0, 0x0308, 5, 0x0000, 0), /* MX6Q_PAD_NANDF_D3__GPIO_2_3 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D3, 0x06F0, 0x0308, 6, 0x0000, 0), /* MX6Q_PAD_NANDF_D3__IPU1_IPU_DIAG_BUS_3 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D3, 0x06F0, 0x0308, 7, 0x0000, 0), /* MX6Q_PAD_NANDF_D3__IPU2_IPU_DIAG_BUS_3 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D4, 0x06F4, 0x030C, 0, 0x0000, 0), /* MX6Q_PAD_NANDF_D4__RAWNAND_D4 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D4, 0x06F4, 0x030C, 1, 0x0000, 0), /* MX6Q_PAD_NANDF_D4__USDHC2_DAT4 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D4, 0x06F4, 0x030C, 2, 0x0000, 0), /* MX6Q_PAD_NANDF_D4__GPU3D_GPU_DBG_OUT_4 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D4, 0x06F4, 0x030C, 3, 0x0000, 0), /* MX6Q_PAD_NANDF_D4__USBOH3_UH2_DFD_OUT20 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D4, 0x06F4, 0x030C, 4, 0x0000, 0), /* MX6Q_PAD_NANDF_D4__USBOH3_UH3_DFD_OUT20 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D4, 0x06F4, 0x030C, 5, 0x0000, 0), /* MX6Q_PAD_NANDF_D4__GPIO_2_4 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D4, 0x06F4, 0x030C, 6, 0x0000, 0), /* MX6Q_PAD_NANDF_D4__IPU1_IPU_DIAG_BUS_4 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D4, 0x06F4, 0x030C, 7, 0x0000, 0), /* MX6Q_PAD_NANDF_D4__IPU2_IPU_DIAG_BUS_4 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D5, 0x06F8, 0x0310, 0, 0x0000, 0), /* MX6Q_PAD_NANDF_D5__RAWNAND_D5 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D5, 0x06F8, 0x0310, 1, 0x0000, 0), /* MX6Q_PAD_NANDF_D5__USDHC2_DAT5 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D5, 0x06F8, 0x0310, 2, 0x0000, 0), /* MX6Q_PAD_NANDF_D5__GPU3D_GPU_DBG_OUT_5 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D5, 0x06F8, 0x0310, 3, 0x0000, 0), /* MX6Q_PAD_NANDF_D5__USBOH3_UH2_DFD_OUT21 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D5, 0x06F8, 0x0310, 4, 0x0000, 0), /* MX6Q_PAD_NANDF_D5__USBOH3_UH3_DFD_OUT21 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D5, 0x06F8, 0x0310, 5, 0x0000, 0), /* MX6Q_PAD_NANDF_D5__GPIO_2_5 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D5, 0x06F8, 0x0310, 6, 0x0000, 0), /* MX6Q_PAD_NANDF_D5__IPU1_IPU_DIAG_BUS_5 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D5, 0x06F8, 0x0310, 7, 0x0000, 0), /* MX6Q_PAD_NANDF_D5__IPU2_IPU_DIAG_BUS_5 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D6, 0x06FC, 0x0314, 0, 0x0000, 0), /* MX6Q_PAD_NANDF_D6__RAWNAND_D6 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D6, 0x06FC, 0x0314, 1, 0x0000, 0), /* MX6Q_PAD_NANDF_D6__USDHC2_DAT6 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D6, 0x06FC, 0x0314, 2, 0x0000, 0), /* MX6Q_PAD_NANDF_D6__GPU3D_GPU_DBG_OUT_6 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D6, 0x06FC, 0x0314, 3, 0x0000, 0), /* MX6Q_PAD_NANDF_D6__USBOH3_UH2_DFD_OUT22 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D6, 0x06FC, 0x0314, 4, 0x0000, 0), /* MX6Q_PAD_NANDF_D6__USBOH3_UH3_DFD_OUT22 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D6, 0x06FC, 0x0314, 5, 0x0000, 0), /* MX6Q_PAD_NANDF_D6__GPIO_2_6 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D6, 0x06FC, 0x0314, 6, 0x0000, 0), /* MX6Q_PAD_NANDF_D6__IPU1_IPU_DIAG_BUS_6 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D6, 0x06FC, 0x0314, 7, 0x0000, 0), /* MX6Q_PAD_NANDF_D6__IPU2_IPU_DIAG_BUS_6 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D7, 0x0700, 0x0318, 0, 0x0000, 0), /* MX6Q_PAD_NANDF_D7__RAWNAND_D7 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D7, 0x0700, 0x0318, 1, 0x0000, 0), /* MX6Q_PAD_NANDF_D7__USDHC2_DAT7 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D7, 0x0700, 0x0318, 2, 0x0000, 0), /* MX6Q_PAD_NANDF_D7__GPU3D_GPU_DBG_OUT_7 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D7, 0x0700, 0x0318, 3, 0x0000, 0), /* MX6Q_PAD_NANDF_D7__USBOH3_UH2_DFD_OUT23 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D7, 0x0700, 0x0318, 4, 0x0000, 0), /* MX6Q_PAD_NANDF_D7__USBOH3_UH3_DFD_OUT23 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D7, 0x0700, 0x0318, 5, 0x0000, 0), /* MX6Q_PAD_NANDF_D7__GPIO_2_7 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D7, 0x0700, 0x0318, 6, 0x0000, 0), /* MX6Q_PAD_NANDF_D7__IPU1_IPU_DIAG_BUS_7 */
-	IMX_PIN_REG(MX6Q_PAD_NANDF_D7, 0x0700, 0x0318, 7, 0x0000, 0), /* MX6Q_PAD_NANDF_D7__IPU2_IPU_DIAG_BUS_7 */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT0, 0x0704, 0x031C, 0, 0x0000, 0), /* MX6Q_PAD_SD4_DAT0__RAWNAND_D8 */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT0, 0x0704, 0x031C, 1, 0x0000, 0), /* MX6Q_PAD_SD4_DAT0__USDHC4_DAT0 */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT0, 0x0704, 0x031C, 2, 0x0000, 0), /* MX6Q_PAD_SD4_DAT0__RAWNAND_DQS */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT0, 0x0704, 0x031C, 3, 0x0000, 0), /* MX6Q_PAD_SD4_DAT0__USBOH3_UH2_DFD_OUT24 */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT0, 0x0704, 0x031C, 4, 0x0000, 0), /* MX6Q_PAD_SD4_DAT0__USBOH3_UH3_DFD_OUT24 */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT0, 0x0704, 0x031C, 5, 0x0000, 0), /* MX6Q_PAD_SD4_DAT0__GPIO_2_8 */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT0, 0x0704, 0x031C, 6, 0x0000, 0), /* MX6Q_PAD_SD4_DAT0__IPU1_IPU_DIAG_BUS_8 */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT0, 0x0704, 0x031C, 7, 0x0000, 0), /* MX6Q_PAD_SD4_DAT0__IPU2_IPU_DIAG_BUS_8 */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT1, 0x0708, 0x0320, 0, 0x0000, 0), /* MX6Q_PAD_SD4_DAT1__RAWNAND_D9 */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT1, 0x0708, 0x0320, 1, 0x0000, 0), /* MX6Q_PAD_SD4_DAT1__USDHC4_DAT1 */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT1, 0x0708, 0x0320, 2, 0x0000, 0), /* MX6Q_PAD_SD4_DAT1__PWM3_PWMO */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT1, 0x0708, 0x0320, 3, 0x0000, 0), /* MX6Q_PAD_SD4_DAT1__USBOH3_UH2_DFD_OUT25 */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT1, 0x0708, 0x0320, 4, 0x0000, 0), /* MX6Q_PAD_SD4_DAT1__USBOH3_UH3_DFD_OUT25 */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT1, 0x0708, 0x0320, 5, 0x0000, 0), /* MX6Q_PAD_SD4_DAT1__GPIO_2_9 */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT1, 0x0708, 0x0320, 6, 0x0000, 0), /* MX6Q_PAD_SD4_DAT1__IPU1_IPU_DIAG_BUS_9 */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT1, 0x0708, 0x0320, 7, 0x0000, 0), /* MX6Q_PAD_SD4_DAT1__IPU2_IPU_DIAG_BUS_9 */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT2, 0x070C, 0x0324, 0, 0x0000, 0), /* MX6Q_PAD_SD4_DAT2__RAWNAND_D10 */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT2, 0x070C, 0x0324, 1, 0x0000, 0), /* MX6Q_PAD_SD4_DAT2__USDHC4_DAT2 */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT2, 0x070C, 0x0324, 2, 0x0000, 0), /* MX6Q_PAD_SD4_DAT2__PWM4_PWMO */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT2, 0x070C, 0x0324, 3, 0x0000, 0), /* MX6Q_PAD_SD4_DAT2__USBOH3_UH2_DFD_OUT26 */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT2, 0x070C, 0x0324, 4, 0x0000, 0), /* MX6Q_PAD_SD4_DAT2__USBOH3_UH3_DFD_OUT26 */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT2, 0x070C, 0x0324, 5, 0x0000, 0), /* MX6Q_PAD_SD4_DAT2__GPIO_2_10 */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT2, 0x070C, 0x0324, 6, 0x0000, 0), /* MX6Q_PAD_SD4_DAT2__IPU1_IPU_DIAG_BUS_10 */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT2, 0x070C, 0x0324, 7, 0x0000, 0), /* MX6Q_PAD_SD4_DAT2__IPU2_IPU_DIAG_BUS_10 */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT3, 0x0710, 0x0328, 0, 0x0000, 0), /* MX6Q_PAD_SD4_DAT3__RAWNAND_D11 */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT3, 0x0710, 0x0328, 1, 0x0000, 0), /* MX6Q_PAD_SD4_DAT3__USDHC4_DAT3 */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT3, 0x0710, 0x0328, 3, 0x0000, 0), /* MX6Q_PAD_SD4_DAT3__USBOH3_UH2_DFD_OUT27 */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT3, 0x0710, 0x0328, 4, 0x0000, 0), /* MX6Q_PAD_SD4_DAT3__USBOH3_UH3_DFD_OUT27 */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT3, 0x0710, 0x0328, 5, 0x0000, 0), /* MX6Q_PAD_SD4_DAT3__GPIO_2_11 */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT3, 0x0710, 0x0328, 6, 0x0000, 0), /* MX6Q_PAD_SD4_DAT3__IPU1_IPU_DIAG_BUS_11 */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT3, 0x0710, 0x0328, 7, 0x0000, 0), /* MX6Q_PAD_SD4_DAT3__IPU2_IPU_DIAG_BUS_11 */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT4, 0x0714, 0x032C, 0, 0x0000, 0), /* MX6Q_PAD_SD4_DAT4__RAWNAND_D12 */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT4, 0x0714, 0x032C, 1, 0x0000, 0), /* MX6Q_PAD_SD4_DAT4__USDHC4_DAT4 */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT4, 0x0714, 0x032C, 2, 0x0928, 6), /* MX6Q_PAD_SD4_DAT4__UART2_RXD */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT4, 0x0714, 0x032C, 3, 0x0000, 0), /* MX6Q_PAD_SD4_DAT4__USBOH3_UH2_DFD_OUT28 */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT4, 0x0714, 0x032C, 4, 0x0000, 0), /* MX6Q_PAD_SD4_DAT4__USBOH3_UH3_DFD_OUT28 */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT4, 0x0714, 0x032C, 5, 0x0000, 0), /* MX6Q_PAD_SD4_DAT4__GPIO_2_12 */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT4, 0x0714, 0x032C, 6, 0x0000, 0), /* MX6Q_PAD_SD4_DAT4__IPU1_IPU_DIAG_BUS_12 */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT4, 0x0714, 0x032C, 7, 0x0000, 0), /* MX6Q_PAD_SD4_DAT4__IPU2_IPU_DIAG_BUS_12 */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT5, 0x0718, 0x0330, 0, 0x0000, 0), /* MX6Q_PAD_SD4_DAT5__RAWNAND_D13 */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT5, 0x0718, 0x0330, 1, 0x0000, 0), /* MX6Q_PAD_SD4_DAT5__USDHC4_DAT5 */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT5, 0x0718, 0x0330, 2, 0x0924, 4), /* MX6Q_PAD_SD4_DAT5__UART2_RTS */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT5, 0x0718, 0x0330, 3, 0x0000, 0), /* MX6Q_PAD_SD4_DAT5__USBOH3_UH2_DFD_OUT29 */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT5, 0x0718, 0x0330, 4, 0x0000, 0), /* MX6Q_PAD_SD4_DAT5__USBOH3_UH3_DFD_OUT29 */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT5, 0x0718, 0x0330, 5, 0x0000, 0), /* MX6Q_PAD_SD4_DAT5__GPIO_2_13 */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT5, 0x0718, 0x0330, 6, 0x0000, 0), /* MX6Q_PAD_SD4_DAT5__IPU1_IPU_DIAG_BUS_13 */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT5, 0x0718, 0x0330, 7, 0x0000, 0), /* MX6Q_PAD_SD4_DAT5__IPU2_IPU_DIAG_BUS_13 */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT6, 0x071C, 0x0334, 0, 0x0000, 0), /* MX6Q_PAD_SD4_DAT6__RAWNAND_D14 */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT6, 0x071C, 0x0334, 1, 0x0000, 0), /* MX6Q_PAD_SD4_DAT6__USDHC4_DAT6 */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT6, 0x071C, 0x0334, 2, 0x0924, 5), /* MX6Q_PAD_SD4_DAT6__UART2_CTS */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT6, 0x071C, 0x0334, 3, 0x0000, 0), /* MX6Q_PAD_SD4_DAT6__USBOH3_UH2_DFD_OUT30 */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT6, 0x071C, 0x0334, 4, 0x0000, 0), /* MX6Q_PAD_SD4_DAT6__USBOH3_UH3_DFD_OUT30 */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT6, 0x071C, 0x0334, 5, 0x0000, 0), /* MX6Q_PAD_SD4_DAT6__GPIO_2_14 */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT6, 0x071C, 0x0334, 6, 0x0000, 0), /* MX6Q_PAD_SD4_DAT6__IPU1_IPU_DIAG_BUS_14 */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT6, 0x071C, 0x0334, 7, 0x0000, 0), /* MX6Q_PAD_SD4_DAT6__IPU2_IPU_DIAG_BUS_14 */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT7, 0x0720, 0x0338, 0, 0x0000, 0), /* MX6Q_PAD_SD4_DAT7__RAWNAND_D15 */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT7, 0x0720, 0x0338, 1, 0x0000, 0), /* MX6Q_PAD_SD4_DAT7__USDHC4_DAT7 */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT7, 0x0720, 0x0338, 2, 0x0000, 0), /* MX6Q_PAD_SD4_DAT7__UART2_TXD */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT7, 0x0720, 0x0338, 3, 0x0000, 0), /* MX6Q_PAD_SD4_DAT7__USBOH3_UH2_DFD_OUT31 */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT7, 0x0720, 0x0338, 4, 0x0000, 0), /* MX6Q_PAD_SD4_DAT7__USBOH3_UH3_DFD_OUT31 */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT7, 0x0720, 0x0338, 5, 0x0000, 0), /* MX6Q_PAD_SD4_DAT7__GPIO_2_15 */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT7, 0x0720, 0x0338, 6, 0x0000, 0), /* MX6Q_PAD_SD4_DAT7__IPU1_IPU_DIAG_BUS_15 */
-	IMX_PIN_REG(MX6Q_PAD_SD4_DAT7, 0x0720, 0x0338, 7, 0x0000, 0), /* MX6Q_PAD_SD4_DAT7__IPU2_IPU_DIAG_BUS_15 */
-	IMX_PIN_REG(MX6Q_PAD_SD1_DAT1, 0x0724, 0x033C, 0, 0x0000, 0), /* MX6Q_PAD_SD1_DAT1__USDHC1_DAT1 */
-	IMX_PIN_REG(MX6Q_PAD_SD1_DAT1, 0x0724, 0x033C, 1, 0x0834, 1), /* MX6Q_PAD_SD1_DAT1__ECSPI5_SS0 */
-	IMX_PIN_REG(MX6Q_PAD_SD1_DAT1, 0x0724, 0x033C, 2, 0x0000, 0), /* MX6Q_PAD_SD1_DAT1__PWM3_PWMO */
-	IMX_PIN_REG(MX6Q_PAD_SD1_DAT1, 0x0724, 0x033C, 3, 0x0000, 0), /* MX6Q_PAD_SD1_DAT1__GPT_CAPIN2 */
-	IMX_PIN_REG(MX6Q_PAD_SD1_DAT1, 0x0724, 0x033C, 4, 0x0000, 0), /* MX6Q_PAD_SD1_DAT1__PCIE_CTRL_MUX_7 */
-	IMX_PIN_REG(MX6Q_PAD_SD1_DAT1, 0x0724, 0x033C, 5, 0x0000, 0), /* MX6Q_PAD_SD1_DAT1__GPIO_1_17 */
-	IMX_PIN_REG(MX6Q_PAD_SD1_DAT1, 0x0724, 0x033C, 6, 0x0000, 0), /* MX6Q_PAD_SD1_DAT1__HDMI_TX_OPHYDTB_0 */
-	IMX_PIN_REG(MX6Q_PAD_SD1_DAT1, 0x0724, 0x033C, 7, 0x0000, 0), /* MX6Q_PAD_SD1_DAT1__ANATOP_TESTO_8 */
-	IMX_PIN_REG(MX6Q_PAD_SD1_DAT0, 0x0728, 0x0340, 0, 0x0000, 0), /* MX6Q_PAD_SD1_DAT0__USDHC1_DAT0 */
-	IMX_PIN_REG(MX6Q_PAD_SD1_DAT0, 0x0728, 0x0340, 1, 0x082C, 1), /* MX6Q_PAD_SD1_DAT0__ECSPI5_MISO */
-	IMX_PIN_REG(MX6Q_PAD_SD1_DAT0, 0x0728, 0x0340, 2, 0x0000, 0), /* MX6Q_PAD_SD1_DAT0__CAAM_WRAP_RNG_OSCOBS */
-	IMX_PIN_REG(MX6Q_PAD_SD1_DAT0, 0x0728, 0x0340, 3, 0x0000, 0), /* MX6Q_PAD_SD1_DAT0__GPT_CAPIN1 */
-	IMX_PIN_REG(MX6Q_PAD_SD1_DAT0, 0x0728, 0x0340, 4, 0x0000, 0), /* MX6Q_PAD_SD1_DAT0__PCIE_CTRL_MUX_8 */
-	IMX_PIN_REG(MX6Q_PAD_SD1_DAT0, 0x0728, 0x0340, 5, 0x0000, 0), /* MX6Q_PAD_SD1_DAT0__GPIO_1_16 */
-	IMX_PIN_REG(MX6Q_PAD_SD1_DAT0, 0x0728, 0x0340, 6, 0x0000, 0), /* MX6Q_PAD_SD1_DAT0__HDMI_TX_OPHYDTB_1 */
-	IMX_PIN_REG(MX6Q_PAD_SD1_DAT0, 0x0728, 0x0340, 7, 0x0000, 0), /* MX6Q_PAD_SD1_DAT0__ANATOP_TESTO_7 */
-	IMX_PIN_REG(MX6Q_PAD_SD1_DAT3, 0x072C, 0x0344, 0, 0x0000, 0), /* MX6Q_PAD_SD1_DAT3__USDHC1_DAT3 */
-	IMX_PIN_REG(MX6Q_PAD_SD1_DAT3, 0x072C, 0x0344, 1, 0x0000, 0), /* MX6Q_PAD_SD1_DAT3__ECSPI5_SS2 */
-	IMX_PIN_REG(MX6Q_PAD_SD1_DAT3, 0x072C, 0x0344, 2, 0x0000, 0), /* MX6Q_PAD_SD1_DAT3__GPT_CMPOUT3 */
-	IMX_PIN_REG(MX6Q_PAD_SD1_DAT3, 0x072C, 0x0344, 3, 0x0000, 0), /* MX6Q_PAD_SD1_DAT3__PWM1_PWMO */
-	IMX_PIN_REG(MX6Q_PAD_SD1_DAT3, 0x072C, 0x0344, 4, 0x0000, 0), /* MX6Q_PAD_SD1_DAT3__WDOG2_WDOG_B */
-	IMX_PIN_REG(MX6Q_PAD_SD1_DAT3, 0x072C, 0x0344, 5, 0x0000, 0), /* MX6Q_PAD_SD1_DAT3__GPIO_1_21 */
-	IMX_PIN_REG(MX6Q_PAD_SD1_DAT3, 0x072C, 0x0344, 6, 0x0000, 0), /* MX6Q_PAD_SD1_DAT3__WDOG2_WDOG_RST_B_DEB */
-	IMX_PIN_REG(MX6Q_PAD_SD1_DAT3, 0x072C, 0x0344, 7, 0x0000, 0), /* MX6Q_PAD_SD1_DAT3__ANATOP_TESTO_6 */
-	IMX_PIN_REG(MX6Q_PAD_SD1_CMD, 0x0730, 0x0348, 0, 0x0000, 0), /* MX6Q_PAD_SD1_CMD__USDHC1_CMD */
-	IMX_PIN_REG(MX6Q_PAD_SD1_CMD, 0x0730, 0x0348, 1, 0x0830, 0), /* MX6Q_PAD_SD1_CMD__ECSPI5_MOSI */
-	IMX_PIN_REG(MX6Q_PAD_SD1_CMD, 0x0730, 0x0348, 2, 0x0000, 0), /* MX6Q_PAD_SD1_CMD__PWM4_PWMO */
-	IMX_PIN_REG(MX6Q_PAD_SD1_CMD, 0x0730, 0x0348, 3, 0x0000, 0), /* MX6Q_PAD_SD1_CMD__GPT_CMPOUT1 */
-	IMX_PIN_REG(MX6Q_PAD_SD1_CMD, 0x0730, 0x0348, 5, 0x0000, 0), /* MX6Q_PAD_SD1_CMD__GPIO_1_18 */
-	IMX_PIN_REG(MX6Q_PAD_SD1_CMD, 0x0730, 0x0348, 7, 0x0000, 0), /* MX6Q_PAD_SD1_CMD__ANATOP_TESTO_5 */
-	IMX_PIN_REG(MX6Q_PAD_SD1_DAT2, 0x0734, 0x034C, 0, 0x0000, 0), /* MX6Q_PAD_SD1_DAT2__USDHC1_DAT2 */
-	IMX_PIN_REG(MX6Q_PAD_SD1_DAT2, 0x0734, 0x034C, 1, 0x0838, 1), /* MX6Q_PAD_SD1_DAT2__ECSPI5_SS1 */
-	IMX_PIN_REG(MX6Q_PAD_SD1_DAT2, 0x0734, 0x034C, 2, 0x0000, 0), /* MX6Q_PAD_SD1_DAT2__GPT_CMPOUT2 */
-	IMX_PIN_REG(MX6Q_PAD_SD1_DAT2, 0x0734, 0x034C, 3, 0x0000, 0), /* MX6Q_PAD_SD1_DAT2__PWM2_PWMO */
-	IMX_PIN_REG(MX6Q_PAD_SD1_DAT2, 0x0734, 0x034C, 4, 0x0000, 0), /* MX6Q_PAD_SD1_DAT2__WDOG1_WDOG_B */
-	IMX_PIN_REG(MX6Q_PAD_SD1_DAT2, 0x0734, 0x034C, 5, 0x0000, 0), /* MX6Q_PAD_SD1_DAT2__GPIO_1_19 */
-	IMX_PIN_REG(MX6Q_PAD_SD1_DAT2, 0x0734, 0x034C, 6, 0x0000, 0), /* MX6Q_PAD_SD1_DAT2__WDOG1_WDOG_RST_B_DEB */
-	IMX_PIN_REG(MX6Q_PAD_SD1_DAT2, 0x0734, 0x034C, 7, 0x0000, 0), /* MX6Q_PAD_SD1_DAT2__ANATOP_TESTO_4 */
-	IMX_PIN_REG(MX6Q_PAD_SD1_CLK, 0x0738, 0x0350, 0, 0x0000, 0), /* MX6Q_PAD_SD1_CLK__USDHC1_CLK */
-	IMX_PIN_REG(MX6Q_PAD_SD1_CLK, 0x0738, 0x0350, 1, 0x0828, 0), /* MX6Q_PAD_SD1_CLK__ECSPI5_SCLK */
-	IMX_PIN_REG(MX6Q_PAD_SD1_CLK, 0x0738, 0x0350, 2, 0x0000, 0), /* MX6Q_PAD_SD1_CLK__OSC32K_32K_OUT */
-	IMX_PIN_REG(MX6Q_PAD_SD1_CLK, 0x0738, 0x0350, 3, 0x0000, 0), /* MX6Q_PAD_SD1_CLK__GPT_CLKIN */
-	IMX_PIN_REG(MX6Q_PAD_SD1_CLK, 0x0738, 0x0350, 5, 0x0000, 0), /* MX6Q_PAD_SD1_CLK__GPIO_1_20 */
-	IMX_PIN_REG(MX6Q_PAD_SD1_CLK, 0x0738, 0x0350, 6, 0x0000, 0), /* MX6Q_PAD_SD1_CLK__PHY_DTB_0 */
-	IMX_PIN_REG(MX6Q_PAD_SD1_CLK, 0x0738, 0x0350, 7, 0x0000, 0), /* MX6Q_PAD_SD1_CLK__SATA_PHY_DTB_0 */
-	IMX_PIN_REG(MX6Q_PAD_SD2_CLK, 0x073C, 0x0354, 0, 0x0000, 0), /* MX6Q_PAD_SD2_CLK__USDHC2_CLK */
-	IMX_PIN_REG(MX6Q_PAD_SD2_CLK, 0x073C, 0x0354, 1, 0x0828, 1), /* MX6Q_PAD_SD2_CLK__ECSPI5_SCLK */
-	IMX_PIN_REG(MX6Q_PAD_SD2_CLK, 0x073C, 0x0354, 2, 0x08E8, 3), /* MX6Q_PAD_SD2_CLK__KPP_COL_5 */
-	IMX_PIN_REG(MX6Q_PAD_SD2_CLK, 0x073C, 0x0354, 3, 0x07C0, 1), /* MX6Q_PAD_SD2_CLK__AUDMUX_AUD4_RXFS */
-	IMX_PIN_REG(MX6Q_PAD_SD2_CLK, 0x073C, 0x0354, 4, 0x0000, 0), /* MX6Q_PAD_SD2_CLK__PCIE_CTRL_MUX_9 */
-	IMX_PIN_REG(MX6Q_PAD_SD2_CLK, 0x073C, 0x0354, 5, 0x0000, 0), /* MX6Q_PAD_SD2_CLK__GPIO_1_10 */
-	IMX_PIN_REG(MX6Q_PAD_SD2_CLK, 0x073C, 0x0354, 6, 0x0000, 0), /* MX6Q_PAD_SD2_CLK__PHY_DTB_1 */
-	IMX_PIN_REG(MX6Q_PAD_SD2_CLK, 0x073C, 0x0354, 7, 0x0000, 0), /* MX6Q_PAD_SD2_CLK__SATA_PHY_DTB_1 */
-	IMX_PIN_REG(MX6Q_PAD_SD2_CMD, 0x0740, 0x0358, 0, 0x0000, 0), /* MX6Q_PAD_SD2_CMD__USDHC2_CMD */
-	IMX_PIN_REG(MX6Q_PAD_SD2_CMD, 0x0740, 0x0358, 1, 0x0830, 1), /* MX6Q_PAD_SD2_CMD__ECSPI5_MOSI */
-	IMX_PIN_REG(MX6Q_PAD_SD2_CMD, 0x0740, 0x0358, 2, 0x08F4, 2), /* MX6Q_PAD_SD2_CMD__KPP_ROW_5 */
-	IMX_PIN_REG(MX6Q_PAD_SD2_CMD, 0x0740, 0x0358, 3, 0x07BC, 1), /* MX6Q_PAD_SD2_CMD__AUDMUX_AUD4_RXC */
-	IMX_PIN_REG(MX6Q_PAD_SD2_CMD, 0x0740, 0x0358, 4, 0x0000, 0), /* MX6Q_PAD_SD2_CMD__PCIE_CTRL_MUX_10 */
-	IMX_PIN_REG(MX6Q_PAD_SD2_CMD, 0x0740, 0x0358, 5, 0x0000, 0), /* MX6Q_PAD_SD2_CMD__GPIO_1_11 */
-	IMX_PIN_REG(MX6Q_PAD_SD2_DAT3, 0x0744, 0x035C, 0, 0x0000, 0), /* MX6Q_PAD_SD2_DAT3__USDHC2_DAT3 */
-	IMX_PIN_REG(MX6Q_PAD_SD2_DAT3, 0x0744, 0x035C, 1, 0x0000, 0), /* MX6Q_PAD_SD2_DAT3__ECSPI5_SS3 */
-	IMX_PIN_REG(MX6Q_PAD_SD2_DAT3, 0x0744, 0x035C, 2, 0x08EC, 2), /* MX6Q_PAD_SD2_DAT3__KPP_COL_6 */
-	IMX_PIN_REG(MX6Q_PAD_SD2_DAT3, 0x0744, 0x035C, 3, 0x07C4, 1), /* MX6Q_PAD_SD2_DAT3__AUDMUX_AUD4_TXC */
-	IMX_PIN_REG(MX6Q_PAD_SD2_DAT3, 0x0744, 0x035C, 4, 0x0000, 0), /* MX6Q_PAD_SD2_DAT3__PCIE_CTRL_MUX_11 */
-	IMX_PIN_REG(MX6Q_PAD_SD2_DAT3, 0x0744, 0x035C, 5, 0x0000, 0), /* MX6Q_PAD_SD2_DAT3__GPIO_1_12 */
-	IMX_PIN_REG(MX6Q_PAD_SD2_DAT3, 0x0744, 0x035C, 6, 0x0000, 0), /* MX6Q_PAD_SD2_DAT3__SJC_DONE */
-	IMX_PIN_REG(MX6Q_PAD_SD2_DAT3, 0x0744, 0x035C, 7, 0x0000, 0), /* MX6Q_PAD_SD2_DAT3__ANATOP_TESTO_3 */
-	IMX_PIN_REG(MX6Q_PAD_ENET_RX_ER, 0x04EC, 0x01D8, 0, 0x0000, 0), /* MX6Q_PAD_ENET_RX_ER__ANATOP_USBOTG_ID */
-	IMX_PIN_REG(MX6Q_PAD_GPIO_1, 0x05F4, 0x0224, 3, 0x0000, 0), /* MX6Q_PAD_GPIO_1__ANATOP_USBOTG_ID */
+	MX6Q_PAD_SD2_DAT1 = 19,
+	MX6Q_PAD_SD2_DAT2 = 20,
+	MX6Q_PAD_SD2_DAT0 = 21,
+	MX6Q_PAD_RGMII_TXC = 22,
+	MX6Q_PAD_RGMII_TD0 = 23,
+	MX6Q_PAD_RGMII_TD1 = 24,
+	MX6Q_PAD_RGMII_TD2 = 25,
+	MX6Q_PAD_RGMII_TD3 = 26,
+	MX6Q_PAD_RGMII_RX_CTL = 27,
+	MX6Q_PAD_RGMII_RD0 = 28,
+	MX6Q_PAD_RGMII_TX_CTL = 29,
+	MX6Q_PAD_RGMII_RD1 = 30,
+	MX6Q_PAD_RGMII_RD2 = 31,
+	MX6Q_PAD_RGMII_RD3 = 32,
+	MX6Q_PAD_RGMII_RXC = 33,
+	MX6Q_PAD_EIM_A25 = 34,
+	MX6Q_PAD_EIM_EB2 = 35,
+	MX6Q_PAD_EIM_D16 = 36,
+	MX6Q_PAD_EIM_D17 = 37,
+	MX6Q_PAD_EIM_D18 = 38,
+	MX6Q_PAD_EIM_D19 = 39,
+	MX6Q_PAD_EIM_D20 = 40,
+	MX6Q_PAD_EIM_D21 = 41,
+	MX6Q_PAD_EIM_D22 = 42,
+	MX6Q_PAD_EIM_D23 = 43,
+	MX6Q_PAD_EIM_EB3 = 44,
+	MX6Q_PAD_EIM_D24 = 45,
+	MX6Q_PAD_EIM_D25 = 46,
+	MX6Q_PAD_EIM_D26 = 47,
+	MX6Q_PAD_EIM_D27 = 48,
+	MX6Q_PAD_EIM_D28 = 49,
+	MX6Q_PAD_EIM_D29 = 50,
+	MX6Q_PAD_EIM_D30 = 51,
+	MX6Q_PAD_EIM_D31 = 52,
+	MX6Q_PAD_EIM_A24 = 53,
+	MX6Q_PAD_EIM_A23 = 54,
+	MX6Q_PAD_EIM_A22 = 55,
+	MX6Q_PAD_EIM_A21 = 56,
+	MX6Q_PAD_EIM_A20 = 57,
+	MX6Q_PAD_EIM_A19 = 58,
+	MX6Q_PAD_EIM_A18 = 59,
+	MX6Q_PAD_EIM_A17 = 60,
+	MX6Q_PAD_EIM_A16 = 61,
+	MX6Q_PAD_EIM_CS0 = 62,
+	MX6Q_PAD_EIM_CS1 = 63,
+	MX6Q_PAD_EIM_OE = 64,
+	MX6Q_PAD_EIM_RW = 65,
+	MX6Q_PAD_EIM_LBA = 66,
+	MX6Q_PAD_EIM_EB0 = 67,
+	MX6Q_PAD_EIM_EB1 = 68,
+	MX6Q_PAD_EIM_DA0 = 69,
+	MX6Q_PAD_EIM_DA1 = 70,
+	MX6Q_PAD_EIM_DA2 = 71,
+	MX6Q_PAD_EIM_DA3 = 72,
+	MX6Q_PAD_EIM_DA4 = 73,
+	MX6Q_PAD_EIM_DA5 = 74,
+	MX6Q_PAD_EIM_DA6 = 75,
+	MX6Q_PAD_EIM_DA7 = 76,
+	MX6Q_PAD_EIM_DA8 = 77,
+	MX6Q_PAD_EIM_DA9 = 78,
+	MX6Q_PAD_EIM_DA10 = 79,
+	MX6Q_PAD_EIM_DA11 = 80,
+	MX6Q_PAD_EIM_DA12 = 81,
+	MX6Q_PAD_EIM_DA13 = 82,
+	MX6Q_PAD_EIM_DA14 = 83,
+	MX6Q_PAD_EIM_DA15 = 84,
+	MX6Q_PAD_EIM_WAIT = 85,
+	MX6Q_PAD_EIM_BCLK = 86,
+	MX6Q_PAD_DI0_DISP_CLK = 87,
+	MX6Q_PAD_DI0_PIN15 = 88,
+	MX6Q_PAD_DI0_PIN2 = 89,
+	MX6Q_PAD_DI0_PIN3 = 90,
+	MX6Q_PAD_DI0_PIN4 = 91,
+	MX6Q_PAD_DISP0_DAT0 = 92,
+	MX6Q_PAD_DISP0_DAT1 = 93,
+	MX6Q_PAD_DISP0_DAT2 = 94,
+	MX6Q_PAD_DISP0_DAT3 = 95,
+	MX6Q_PAD_DISP0_DAT4 = 96,
+	MX6Q_PAD_DISP0_DAT5 = 97,
+	MX6Q_PAD_DISP0_DAT6 = 98,
+	MX6Q_PAD_DISP0_DAT7 = 99,
+	MX6Q_PAD_DISP0_DAT8 = 100,
+	MX6Q_PAD_DISP0_DAT9 = 101,
+	MX6Q_PAD_DISP0_DAT10 = 102,
+	MX6Q_PAD_DISP0_DAT11 = 103,
+	MX6Q_PAD_DISP0_DAT12 = 104,
+	MX6Q_PAD_DISP0_DAT13 = 105,
+	MX6Q_PAD_DISP0_DAT14 = 106,
+	MX6Q_PAD_DISP0_DAT15 = 107,
+	MX6Q_PAD_DISP0_DAT16 = 108,
+	MX6Q_PAD_DISP0_DAT17 = 109,
+	MX6Q_PAD_DISP0_DAT18 = 110,
+	MX6Q_PAD_DISP0_DAT19 = 111,
+	MX6Q_PAD_DISP0_DAT20 = 112,
+	MX6Q_PAD_DISP0_DAT21 = 113,
+	MX6Q_PAD_DISP0_DAT22 = 114,
+	MX6Q_PAD_DISP0_DAT23 = 115,
+	MX6Q_PAD_ENET_MDIO = 116,
+	MX6Q_PAD_ENET_REF_CLK = 117,
+	MX6Q_PAD_ENET_RX_ER = 118,
+	MX6Q_PAD_ENET_CRS_DV = 119,
+	MX6Q_PAD_ENET_RXD1 = 120,
+	MX6Q_PAD_ENET_RXD0 = 121,
+	MX6Q_PAD_ENET_TX_EN = 122,
+	MX6Q_PAD_ENET_TXD1 = 123,
+	MX6Q_PAD_ENET_TXD0 = 124,
+	MX6Q_PAD_ENET_MDC = 125,
+	MX6Q_PAD_KEY_COL0 = 126,
+	MX6Q_PAD_KEY_ROW0 = 127,
+	MX6Q_PAD_KEY_COL1 = 128,
+	MX6Q_PAD_KEY_ROW1 = 129,
+	MX6Q_PAD_KEY_COL2 = 130,
+	MX6Q_PAD_KEY_ROW2 = 131,
+	MX6Q_PAD_KEY_COL3 = 132,
+	MX6Q_PAD_KEY_ROW3 = 133,
+	MX6Q_PAD_KEY_COL4 = 134,
+	MX6Q_PAD_KEY_ROW4 = 135,
+	MX6Q_PAD_GPIO_0 = 136,
+	MX6Q_PAD_GPIO_1 = 137,
+	MX6Q_PAD_GPIO_9 = 138,
+	MX6Q_PAD_GPIO_3 = 139,
+	MX6Q_PAD_GPIO_6 = 140,
+	MX6Q_PAD_GPIO_2 = 141,
+	MX6Q_PAD_GPIO_4 = 142,
+	MX6Q_PAD_GPIO_5 = 143,
+	MX6Q_PAD_GPIO_7 = 144,
+	MX6Q_PAD_GPIO_8 = 145,
+	MX6Q_PAD_GPIO_16 = 146,
+	MX6Q_PAD_GPIO_17 = 147,
+	MX6Q_PAD_GPIO_18 = 148,
+	MX6Q_PAD_GPIO_19 = 149,
+	MX6Q_PAD_CSI0_PIXCLK = 150,
+	MX6Q_PAD_CSI0_MCLK = 151,
+	MX6Q_PAD_CSI0_DATA_EN = 152,
+	MX6Q_PAD_CSI0_VSYNC = 153,
+	MX6Q_PAD_CSI0_DAT4 = 154,
+	MX6Q_PAD_CSI0_DAT5 = 155,
+	MX6Q_PAD_CSI0_DAT6 = 156,
+	MX6Q_PAD_CSI0_DAT7 = 157,
+	MX6Q_PAD_CSI0_DAT8 = 158,
+	MX6Q_PAD_CSI0_DAT9 = 159,
+	MX6Q_PAD_CSI0_DAT10 = 160,
+	MX6Q_PAD_CSI0_DAT11 = 161,
+	MX6Q_PAD_CSI0_DAT12 = 162,
+	MX6Q_PAD_CSI0_DAT13 = 163,
+	MX6Q_PAD_CSI0_DAT14 = 164,
+	MX6Q_PAD_CSI0_DAT15 = 165,
+	MX6Q_PAD_CSI0_DAT16 = 166,
+	MX6Q_PAD_CSI0_DAT17 = 167,
+	MX6Q_PAD_CSI0_DAT18 = 168,
+	MX6Q_PAD_CSI0_DAT19 = 169,
+	MX6Q_PAD_SD3_DAT7 = 170,
+	MX6Q_PAD_SD3_DAT6 = 171,
+	MX6Q_PAD_SD3_DAT5 = 172,
+	MX6Q_PAD_SD3_DAT4 = 173,
+	MX6Q_PAD_SD3_CMD = 174,
+	MX6Q_PAD_SD3_CLK = 175,
+	MX6Q_PAD_SD3_DAT0 = 176,
+	MX6Q_PAD_SD3_DAT1 = 177,
+	MX6Q_PAD_SD3_DAT2 = 178,
+	MX6Q_PAD_SD3_DAT3 = 179,
+	MX6Q_PAD_SD3_RST = 180,
+	MX6Q_PAD_NANDF_CLE = 181,
+	MX6Q_PAD_NANDF_ALE = 182,
+	MX6Q_PAD_NANDF_WP_B = 183,
+	MX6Q_PAD_NANDF_RB0 = 184,
+	MX6Q_PAD_NANDF_CS0 = 185,
+	MX6Q_PAD_NANDF_CS1 = 186,
+	MX6Q_PAD_NANDF_CS2 = 187,
+	MX6Q_PAD_NANDF_CS3 = 188,
+	MX6Q_PAD_SD4_CMD = 189,
+	MX6Q_PAD_SD4_CLK = 190,
+	MX6Q_PAD_NANDF_D0 = 191,
+	MX6Q_PAD_NANDF_D1 = 192,
+	MX6Q_PAD_NANDF_D2 = 193,
+	MX6Q_PAD_NANDF_D3 = 194,
+	MX6Q_PAD_NANDF_D4 = 195,
+	MX6Q_PAD_NANDF_D5 = 196,
+	MX6Q_PAD_NANDF_D6 = 197,
+	MX6Q_PAD_NANDF_D7 = 198,
+	MX6Q_PAD_SD4_DAT0 = 199,
+	MX6Q_PAD_SD4_DAT1 = 200,
+	MX6Q_PAD_SD4_DAT2 = 201,
+	MX6Q_PAD_SD4_DAT3 = 202,
+	MX6Q_PAD_SD4_DAT4 = 203,
+	MX6Q_PAD_SD4_DAT5 = 204,
+	MX6Q_PAD_SD4_DAT6 = 205,
+	MX6Q_PAD_SD4_DAT7 = 206,
+	MX6Q_PAD_SD1_DAT1 = 207,
+	MX6Q_PAD_SD1_DAT0 = 208,
+	MX6Q_PAD_SD1_DAT3 = 209,
+	MX6Q_PAD_SD1_CMD = 210,
+	MX6Q_PAD_SD1_DAT2 = 211,
+	MX6Q_PAD_SD1_CLK = 212,
+	MX6Q_PAD_SD2_CLK = 213,
+	MX6Q_PAD_SD2_CMD = 214,
+	MX6Q_PAD_SD2_DAT3 = 215,
+	MX6Q_PAD_DRAM_SDQS5 = 323,
+	MX6Q_PAD_DRAM_DQM5 = 324,
+	MX6Q_PAD_DRAM_DQM4 = 325,
+	MX6Q_PAD_DRAM_SDQS4 = 326,
+	MX6Q_PAD_DRAM_SDQS3 = 327,
+	MX6Q_PAD_DRAM_DQM3 = 328,
+	MX6Q_PAD_DRAM_SDQS2 = 329,
+	MX6Q_PAD_DRAM_DQM2 = 330,
+	MX6Q_PAD_DRAM_A0 = 331,
+	MX6Q_PAD_DRAM_A1 = 332,
+	MX6Q_PAD_DRAM_A2 = 333,
+	MX6Q_PAD_DRAM_A3 = 334,
+	MX6Q_PAD_DRAM_A4 = 335,
+	MX6Q_PAD_DRAM_A5 = 336,
+	MX6Q_PAD_DRAM_A6 = 337,
+	MX6Q_PAD_DRAM_A7 = 338,
+	MX6Q_PAD_DRAM_A8 = 339,
+	MX6Q_PAD_DRAM_A9 = 340,
+	MX6Q_PAD_DRAM_A10 = 341,
+	MX6Q_PAD_DRAM_A11 = 342,
+	MX6Q_PAD_DRAM_A12 = 343,
+	MX6Q_PAD_DRAM_A13 = 344,
+	MX6Q_PAD_DRAM_A14 = 345,
+	MX6Q_PAD_DRAM_A15 = 346,
+	MX6Q_PAD_DRAM_CAS = 347,
+	MX6Q_PAD_DRAM_CS0 = 348,
+	MX6Q_PAD_DRAM_CS1 = 349,
+	MX6Q_PAD_DRAM_RAS = 350,
+	MX6Q_PAD_DRAM_RESET = 351,
+	MX6Q_PAD_DRAM_SDBA0 = 352,
+	MX6Q_PAD_DRAM_SDBA1 = 353,
+	MX6Q_PAD_DRAM_SDCLK_0 = 354,
+	MX6Q_PAD_DRAM_SDBA2 = 355,
+	MX6Q_PAD_DRAM_SDCKE0 = 356,
+	MX6Q_PAD_DRAM_SDCLK_1 = 357,
+	MX6Q_PAD_DRAM_SDCKE1 = 358,
+	MX6Q_PAD_DRAM_SDODT0 = 359,
+	MX6Q_PAD_DRAM_SDODT1 = 360,
+	MX6Q_PAD_DRAM_SDWE = 361,
+	MX6Q_PAD_DRAM_SDQS0 = 362,
+	MX6Q_PAD_DRAM_DQM0 = 363,
+	MX6Q_PAD_DRAM_SDQS1 = 364,
+	MX6Q_PAD_DRAM_DQM1 = 365,
+	MX6Q_PAD_DRAM_SDQS6 = 366,
+	MX6Q_PAD_DRAM_DQM6 = 367,
+	MX6Q_PAD_DRAM_SDQS7 = 368,
+	MX6Q_PAD_DRAM_DQM7 = 369,
+	MX6Q_PAD_JTAG_TMS = 414,
+	MX6Q_PAD_JTAG_MOD = 415,
+	MX6Q_PAD_JTAG_TRSTB = 416,
+	MX6Q_PAD_JTAG_TDI = 417,
+	MX6Q_PAD_JTAG_TCK = 418,
+	MX6Q_PAD_JTAG_TDO = 419,
 };
 
 /* Pad names for the pinmux subsystem */
@@ -2063,45 +384,13 @@ static const struct pinctrl_pin_desc imx6q_pinctrl_pads[] = {
 	IMX_PINCTRL_PIN(MX6Q_PAD_ENET_TXD1),
 	IMX_PINCTRL_PIN(MX6Q_PAD_ENET_TXD0),
 	IMX_PINCTRL_PIN(MX6Q_PAD_ENET_MDC),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D40),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D41),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D42),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D43),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D44),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D45),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D46),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D47),
 	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_SDQS5),
 	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_DQM5),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D32),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D33),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D34),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D35),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D36),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D37),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D38),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D39),
 	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_DQM4),
 	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_SDQS4),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D24),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D25),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D26),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D27),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D28),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D29),
 	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_SDQS3),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D30),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D31),
 	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_DQM3),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D16),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D17),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D18),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D19),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D20),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D21),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D22),
 	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_SDQS2),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D23),
 	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_DQM2),
 	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_A0),
 	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_A1),
@@ -2134,46 +423,14 @@ static const struct pinctrl_pin_desc imx6q_pinctrl_pads[] = {
 	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_SDODT0),
 	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_SDODT1),
 	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_SDWE),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D0),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D1),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D2),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D3),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D4),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D5),
 	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_SDQS0),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D6),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D7),
 	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_DQM0),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D8),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D9),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D10),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D11),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D12),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D13),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D14),
 	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_SDQS1),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D15),
 	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_DQM1),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D48),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D49),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D50),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D51),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D52),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D53),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D54),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D55),
 	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_SDQS6),
 	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_DQM6),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D56),
 	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_SDQS7),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D57),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D58),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D59),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D60),
 	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_DQM7),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D61),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D62),
-	IMX_PINCTRL_PIN(MX6Q_PAD_DRAM_D63),
 	IMX_PINCTRL_PIN(MX6Q_PAD_KEY_COL0),
 	IMX_PINCTRL_PIN(MX6Q_PAD_KEY_ROW0),
 	IMX_PINCTRL_PIN(MX6Q_PAD_KEY_COL1),
@@ -2224,24 +481,6 @@ static const struct pinctrl_pin_desc imx6q_pinctrl_pads[] = {
 	IMX_PINCTRL_PIN(MX6Q_PAD_JTAG_TDI),
 	IMX_PINCTRL_PIN(MX6Q_PAD_JTAG_TCK),
 	IMX_PINCTRL_PIN(MX6Q_PAD_JTAG_TDO),
-	IMX_PINCTRL_PIN(MX6Q_PAD_LVDS1_TX3_P),
-	IMX_PINCTRL_PIN(MX6Q_PAD_LVDS1_TX2_P),
-	IMX_PINCTRL_PIN(MX6Q_PAD_LVDS1_CLK_P),
-	IMX_PINCTRL_PIN(MX6Q_PAD_LVDS1_TX1_P),
-	IMX_PINCTRL_PIN(MX6Q_PAD_LVDS1_TX0_P),
-	IMX_PINCTRL_PIN(MX6Q_PAD_LVDS0_TX3_P),
-	IMX_PINCTRL_PIN(MX6Q_PAD_LVDS0_CLK_P),
-	IMX_PINCTRL_PIN(MX6Q_PAD_LVDS0_TX2_P),
-	IMX_PINCTRL_PIN(MX6Q_PAD_LVDS0_TX1_P),
-	IMX_PINCTRL_PIN(MX6Q_PAD_LVDS0_TX0_P),
-	IMX_PINCTRL_PIN(MX6Q_PAD_TAMPER),
-	IMX_PINCTRL_PIN(MX6Q_PAD_PMIC_ON_REQ),
-	IMX_PINCTRL_PIN(MX6Q_PAD_PMIC_STBY_REQ),
-	IMX_PINCTRL_PIN(MX6Q_PAD_POR_B),
-	IMX_PINCTRL_PIN(MX6Q_PAD_BOOT_MODE1),
-	IMX_PINCTRL_PIN(MX6Q_PAD_RESET_IN_B),
-	IMX_PINCTRL_PIN(MX6Q_PAD_BOOT_MODE0),
-	IMX_PINCTRL_PIN(MX6Q_PAD_TEST_MODE),
 	IMX_PINCTRL_PIN(MX6Q_PAD_SD3_DAT7),
 	IMX_PINCTRL_PIN(MX6Q_PAD_SD3_DAT6),
 	IMX_PINCTRL_PIN(MX6Q_PAD_SD3_DAT5),
@@ -2293,8 +532,6 @@ static const struct pinctrl_pin_desc imx6q_pinctrl_pads[] = {
 static struct imx_pinctrl_soc_info imx6q_pinctrl_info = {
 	.pins = imx6q_pinctrl_pads,
 	.npins = ARRAY_SIZE(imx6q_pinctrl_pads),
-	.pin_regs = imx6q_pin_regs,
-	.npin_regs = ARRAY_SIZE(imx6q_pin_regs),
 };
 
 static struct of_device_id imx6q_pinctrl_of_match[] = {
diff --git a/drivers/pinctrl/pinctrl-imx6sl.c b/drivers/pinctrl/pinctrl-imx6sl.c
new file mode 100644
index 0000000..cac184d
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-imx6sl.c
@@ -0,0 +1,365 @@
+/*
+ * Copyright (C) 2013 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-imx.h"
+
+enum imx6sl_pads {
+	MX6SL_PAD_AUD_MCLK = 19,
+	MX6SL_PAD_AUD_RXC = 20,
+	MX6SL_PAD_AUD_RXD = 21,
+	MX6SL_PAD_AUD_RXFS = 22,
+	MX6SL_PAD_AUD_TXC = 23,
+	MX6SL_PAD_AUD_TXD = 24,
+	MX6SL_PAD_AUD_TXFS = 25,
+	MX6SL_PAD_ECSPI1_MISO = 26,
+	MX6SL_PAD_ECSPI1_MOSI = 27,
+	MX6SL_PAD_ECSPI1_SCLK = 28,
+	MX6SL_PAD_ECSPI1_SS0 = 29,
+	MX6SL_PAD_ECSPI2_MISO = 30,
+	MX6SL_PAD_ECSPI2_MOSI = 31,
+	MX6SL_PAD_ECSPI2_SCLK = 32,
+	MX6SL_PAD_ECSPI2_SS0 = 33,
+	MX6SL_PAD_EPDC_BDR0 = 34,
+	MX6SL_PAD_EPDC_BDR1 = 35,
+	MX6SL_PAD_EPDC_D0 = 36,
+	MX6SL_PAD_EPDC_D1 = 37,
+	MX6SL_PAD_EPDC_D10 = 38,
+	MX6SL_PAD_EPDC_D11 = 39,
+	MX6SL_PAD_EPDC_D12 = 40,
+	MX6SL_PAD_EPDC_D13 = 41,
+	MX6SL_PAD_EPDC_D14 = 42,
+	MX6SL_PAD_EPDC_D15 = 43,
+	MX6SL_PAD_EPDC_D2 = 44,
+	MX6SL_PAD_EPDC_D3 = 45,
+	MX6SL_PAD_EPDC_D4 = 46,
+	MX6SL_PAD_EPDC_D5 = 47,
+	MX6SL_PAD_EPDC_D6 = 48,
+	MX6SL_PAD_EPDC_D7 = 49,
+	MX6SL_PAD_EPDC_D8 = 50,
+	MX6SL_PAD_EPDC_D9 = 51,
+	MX6SL_PAD_EPDC_GDCLK = 52,
+	MX6SL_PAD_EPDC_GDOE = 53,
+	MX6SL_PAD_EPDC_GDRL = 54,
+	MX6SL_PAD_EPDC_GDSP = 55,
+	MX6SL_PAD_EPDC_PWRCOM = 56,
+	MX6SL_PAD_EPDC_PWRCTRL0 = 57,
+	MX6SL_PAD_EPDC_PWRCTRL1 = 58,
+	MX6SL_PAD_EPDC_PWRCTRL2 = 59,
+	MX6SL_PAD_EPDC_PWRCTRL3 = 60,
+	MX6SL_PAD_EPDC_PWRINT = 61,
+	MX6SL_PAD_EPDC_PWRSTAT = 62,
+	MX6SL_PAD_EPDC_PWRWAKEUP = 63,
+	MX6SL_PAD_EPDC_SDCE0 = 64,
+	MX6SL_PAD_EPDC_SDCE1 = 65,
+	MX6SL_PAD_EPDC_SDCE2 = 66,
+	MX6SL_PAD_EPDC_SDCE3 = 67,
+	MX6SL_PAD_EPDC_SDCLK = 68,
+	MX6SL_PAD_EPDC_SDLE = 69,
+	MX6SL_PAD_EPDC_SDOE = 70,
+	MX6SL_PAD_EPDC_SDSHR = 71,
+	MX6SL_PAD_EPDC_VCOM0 = 72,
+	MX6SL_PAD_EPDC_VCOM1 = 73,
+	MX6SL_PAD_FEC_CRS_DV = 74,
+	MX6SL_PAD_FEC_MDC = 75,
+	MX6SL_PAD_FEC_MDIO = 76,
+	MX6SL_PAD_FEC_REF_CLK = 77,
+	MX6SL_PAD_FEC_RX_ER = 78,
+	MX6SL_PAD_FEC_RXD0 = 79,
+	MX6SL_PAD_FEC_RXD1 = 80,
+	MX6SL_PAD_FEC_TX_CLK = 81,
+	MX6SL_PAD_FEC_TX_EN = 82,
+	MX6SL_PAD_FEC_TXD0 = 83,
+	MX6SL_PAD_FEC_TXD1 = 84,
+	MX6SL_PAD_HSIC_DAT = 85,
+	MX6SL_PAD_HSIC_STROBE = 86,
+	MX6SL_PAD_I2C1_SCL = 87,
+	MX6SL_PAD_I2C1_SDA = 88,
+	MX6SL_PAD_I2C2_SCL = 89,
+	MX6SL_PAD_I2C2_SDA = 90,
+	MX6SL_PAD_KEY_COL0 = 91,
+	MX6SL_PAD_KEY_COL1 = 92,
+	MX6SL_PAD_KEY_COL2 = 93,
+	MX6SL_PAD_KEY_COL3 = 94,
+	MX6SL_PAD_KEY_COL4 = 95,
+	MX6SL_PAD_KEY_COL5 = 96,
+	MX6SL_PAD_KEY_COL6 = 97,
+	MX6SL_PAD_KEY_COL7 = 98,
+	MX6SL_PAD_KEY_ROW0 = 99,
+	MX6SL_PAD_KEY_ROW1 = 100,
+	MX6SL_PAD_KEY_ROW2 = 101,
+	MX6SL_PAD_KEY_ROW3 = 102,
+	MX6SL_PAD_KEY_ROW4 = 103,
+	MX6SL_PAD_KEY_ROW5 = 104,
+	MX6SL_PAD_KEY_ROW6 = 105,
+	MX6SL_PAD_KEY_ROW7 = 106,
+	MX6SL_PAD_LCD_CLK = 107,
+	MX6SL_PAD_LCD_DAT0 = 108,
+	MX6SL_PAD_LCD_DAT1 = 109,
+	MX6SL_PAD_LCD_DAT10 = 110,
+	MX6SL_PAD_LCD_DAT11 = 111,
+	MX6SL_PAD_LCD_DAT12 = 112,
+	MX6SL_PAD_LCD_DAT13 = 113,
+	MX6SL_PAD_LCD_DAT14 = 114,
+	MX6SL_PAD_LCD_DAT15 = 115,
+	MX6SL_PAD_LCD_DAT16 = 116,
+	MX6SL_PAD_LCD_DAT17 = 117,
+	MX6SL_PAD_LCD_DAT18 = 118,
+	MX6SL_PAD_LCD_DAT19 = 119,
+	MX6SL_PAD_LCD_DAT2 = 120,
+	MX6SL_PAD_LCD_DAT20 = 121,
+	MX6SL_PAD_LCD_DAT21 = 122,
+	MX6SL_PAD_LCD_DAT22 = 123,
+	MX6SL_PAD_LCD_DAT23 = 124,
+	MX6SL_PAD_LCD_DAT3 = 125,
+	MX6SL_PAD_LCD_DAT4 = 126,
+	MX6SL_PAD_LCD_DAT5 = 127,
+	MX6SL_PAD_LCD_DAT6 = 128,
+	MX6SL_PAD_LCD_DAT7 = 129,
+	MX6SL_PAD_LCD_DAT8 = 130,
+	MX6SL_PAD_LCD_DAT9 = 131,
+	MX6SL_PAD_LCD_ENABLE = 132,
+	MX6SL_PAD_LCD_HSYNC = 133,
+	MX6SL_PAD_LCD_RESET = 134,
+	MX6SL_PAD_LCD_VSYNC = 135,
+	MX6SL_PAD_PWM1 = 136,
+	MX6SL_PAD_REF_CLK_24M = 137,
+	MX6SL_PAD_REF_CLK_32K = 138,
+	MX6SL_PAD_SD1_CLK = 139,
+	MX6SL_PAD_SD1_CMD = 140,
+	MX6SL_PAD_SD1_DAT0 = 141,
+	MX6SL_PAD_SD1_DAT1 = 142,
+	MX6SL_PAD_SD1_DAT2 = 143,
+	MX6SL_PAD_SD1_DAT3 = 144,
+	MX6SL_PAD_SD1_DAT4 = 145,
+	MX6SL_PAD_SD1_DAT5 = 146,
+	MX6SL_PAD_SD1_DAT6 = 147,
+	MX6SL_PAD_SD1_DAT7 = 148,
+	MX6SL_PAD_SD2_CLK = 149,
+	MX6SL_PAD_SD2_CMD = 150,
+	MX6SL_PAD_SD2_DAT0 = 151,
+	MX6SL_PAD_SD2_DAT1 = 152,
+	MX6SL_PAD_SD2_DAT2 = 153,
+	MX6SL_PAD_SD2_DAT3 = 154,
+	MX6SL_PAD_SD2_DAT4 = 155,
+	MX6SL_PAD_SD2_DAT5 = 156,
+	MX6SL_PAD_SD2_DAT6 = 157,
+	MX6SL_PAD_SD2_DAT7 = 158,
+	MX6SL_PAD_SD2_RST = 159,
+	MX6SL_PAD_SD3_CLK = 160,
+	MX6SL_PAD_SD3_CMD = 161,
+	MX6SL_PAD_SD3_DAT0 = 162,
+	MX6SL_PAD_SD3_DAT1 = 163,
+	MX6SL_PAD_SD3_DAT2 = 164,
+	MX6SL_PAD_SD3_DAT3 = 165,
+	MX6SL_PAD_UART1_RXD = 166,
+	MX6SL_PAD_UART1_TXD = 167,
+	MX6SL_PAD_WDOG_B = 168,
+};
+
+/* Pad names for the pinmux subsystem */
+static const struct pinctrl_pin_desc imx6sl_pinctrl_pads[] = {
+	IMX_PINCTRL_PIN(MX6SL_PAD_AUD_MCLK),
+	IMX_PINCTRL_PIN(MX6SL_PAD_AUD_RXC),
+	IMX_PINCTRL_PIN(MX6SL_PAD_AUD_RXD),
+	IMX_PINCTRL_PIN(MX6SL_PAD_AUD_RXFS),
+	IMX_PINCTRL_PIN(MX6SL_PAD_AUD_TXC),
+	IMX_PINCTRL_PIN(MX6SL_PAD_AUD_TXD),
+	IMX_PINCTRL_PIN(MX6SL_PAD_AUD_TXFS),
+	IMX_PINCTRL_PIN(MX6SL_PAD_ECSPI1_MISO),
+	IMX_PINCTRL_PIN(MX6SL_PAD_ECSPI1_MOSI),
+	IMX_PINCTRL_PIN(MX6SL_PAD_ECSPI1_SCLK),
+	IMX_PINCTRL_PIN(MX6SL_PAD_ECSPI1_SS0),
+	IMX_PINCTRL_PIN(MX6SL_PAD_ECSPI2_MISO),
+	IMX_PINCTRL_PIN(MX6SL_PAD_ECSPI2_MOSI),
+	IMX_PINCTRL_PIN(MX6SL_PAD_ECSPI2_SCLK),
+	IMX_PINCTRL_PIN(MX6SL_PAD_ECSPI2_SS0),
+	IMX_PINCTRL_PIN(MX6SL_PAD_EPDC_BDR0),
+	IMX_PINCTRL_PIN(MX6SL_PAD_EPDC_BDR1),
+	IMX_PINCTRL_PIN(MX6SL_PAD_EPDC_D0),
+	IMX_PINCTRL_PIN(MX6SL_PAD_EPDC_D1),
+	IMX_PINCTRL_PIN(MX6SL_PAD_EPDC_D10),
+	IMX_PINCTRL_PIN(MX6SL_PAD_EPDC_D11),
+	IMX_PINCTRL_PIN(MX6SL_PAD_EPDC_D12),
+	IMX_PINCTRL_PIN(MX6SL_PAD_EPDC_D13),
+	IMX_PINCTRL_PIN(MX6SL_PAD_EPDC_D14),
+	IMX_PINCTRL_PIN(MX6SL_PAD_EPDC_D15),
+	IMX_PINCTRL_PIN(MX6SL_PAD_EPDC_D2),
+	IMX_PINCTRL_PIN(MX6SL_PAD_EPDC_D3),
+	IMX_PINCTRL_PIN(MX6SL_PAD_EPDC_D4),
+	IMX_PINCTRL_PIN(MX6SL_PAD_EPDC_D5),
+	IMX_PINCTRL_PIN(MX6SL_PAD_EPDC_D6),
+	IMX_PINCTRL_PIN(MX6SL_PAD_EPDC_D7),
+	IMX_PINCTRL_PIN(MX6SL_PAD_EPDC_D8),
+	IMX_PINCTRL_PIN(MX6SL_PAD_EPDC_D9),
+	IMX_PINCTRL_PIN(MX6SL_PAD_EPDC_GDCLK),
+	IMX_PINCTRL_PIN(MX6SL_PAD_EPDC_GDOE),
+	IMX_PINCTRL_PIN(MX6SL_PAD_EPDC_GDRL),
+	IMX_PINCTRL_PIN(MX6SL_PAD_EPDC_GDSP),
+	IMX_PINCTRL_PIN(MX6SL_PAD_EPDC_PWRCOM),
+	IMX_PINCTRL_PIN(MX6SL_PAD_EPDC_PWRCTRL0),
+	IMX_PINCTRL_PIN(MX6SL_PAD_EPDC_PWRCTRL1),
+	IMX_PINCTRL_PIN(MX6SL_PAD_EPDC_PWRCTRL2),
+	IMX_PINCTRL_PIN(MX6SL_PAD_EPDC_PWRCTRL3),
+	IMX_PINCTRL_PIN(MX6SL_PAD_EPDC_PWRINT),
+	IMX_PINCTRL_PIN(MX6SL_PAD_EPDC_PWRSTAT),
+	IMX_PINCTRL_PIN(MX6SL_PAD_EPDC_PWRWAKEUP),
+	IMX_PINCTRL_PIN(MX6SL_PAD_EPDC_SDCE0),
+	IMX_PINCTRL_PIN(MX6SL_PAD_EPDC_SDCE1),
+	IMX_PINCTRL_PIN(MX6SL_PAD_EPDC_SDCE2),
+	IMX_PINCTRL_PIN(MX6SL_PAD_EPDC_SDCE3),
+	IMX_PINCTRL_PIN(MX6SL_PAD_EPDC_SDCLK),
+	IMX_PINCTRL_PIN(MX6SL_PAD_EPDC_SDLE),
+	IMX_PINCTRL_PIN(MX6SL_PAD_EPDC_SDOE),
+	IMX_PINCTRL_PIN(MX6SL_PAD_EPDC_SDSHR),
+	IMX_PINCTRL_PIN(MX6SL_PAD_EPDC_VCOM0),
+	IMX_PINCTRL_PIN(MX6SL_PAD_EPDC_VCOM1),
+	IMX_PINCTRL_PIN(MX6SL_PAD_FEC_CRS_DV),
+	IMX_PINCTRL_PIN(MX6SL_PAD_FEC_MDC),
+	IMX_PINCTRL_PIN(MX6SL_PAD_FEC_MDIO),
+	IMX_PINCTRL_PIN(MX6SL_PAD_FEC_REF_CLK),
+	IMX_PINCTRL_PIN(MX6SL_PAD_FEC_RX_ER),
+	IMX_PINCTRL_PIN(MX6SL_PAD_FEC_RXD0),
+	IMX_PINCTRL_PIN(MX6SL_PAD_FEC_RXD1),
+	IMX_PINCTRL_PIN(MX6SL_PAD_FEC_TX_CLK),
+	IMX_PINCTRL_PIN(MX6SL_PAD_FEC_TX_EN),
+	IMX_PINCTRL_PIN(MX6SL_PAD_FEC_TXD0),
+	IMX_PINCTRL_PIN(MX6SL_PAD_FEC_TXD1),
+	IMX_PINCTRL_PIN(MX6SL_PAD_HSIC_DAT),
+	IMX_PINCTRL_PIN(MX6SL_PAD_HSIC_STROBE),
+	IMX_PINCTRL_PIN(MX6SL_PAD_I2C1_SCL),
+	IMX_PINCTRL_PIN(MX6SL_PAD_I2C1_SDA),
+	IMX_PINCTRL_PIN(MX6SL_PAD_I2C2_SCL),
+	IMX_PINCTRL_PIN(MX6SL_PAD_I2C2_SDA),
+	IMX_PINCTRL_PIN(MX6SL_PAD_KEY_COL0),
+	IMX_PINCTRL_PIN(MX6SL_PAD_KEY_COL1),
+	IMX_PINCTRL_PIN(MX6SL_PAD_KEY_COL2),
+	IMX_PINCTRL_PIN(MX6SL_PAD_KEY_COL3),
+	IMX_PINCTRL_PIN(MX6SL_PAD_KEY_COL4),
+	IMX_PINCTRL_PIN(MX6SL_PAD_KEY_COL5),
+	IMX_PINCTRL_PIN(MX6SL_PAD_KEY_COL6),
+	IMX_PINCTRL_PIN(MX6SL_PAD_KEY_COL7),
+	IMX_PINCTRL_PIN(MX6SL_PAD_KEY_ROW0),
+	IMX_PINCTRL_PIN(MX6SL_PAD_KEY_ROW1),
+	IMX_PINCTRL_PIN(MX6SL_PAD_KEY_ROW2),
+	IMX_PINCTRL_PIN(MX6SL_PAD_KEY_ROW3),
+	IMX_PINCTRL_PIN(MX6SL_PAD_KEY_ROW4),
+	IMX_PINCTRL_PIN(MX6SL_PAD_KEY_ROW5),
+	IMX_PINCTRL_PIN(MX6SL_PAD_KEY_ROW6),
+	IMX_PINCTRL_PIN(MX6SL_PAD_KEY_ROW7),
+	IMX_PINCTRL_PIN(MX6SL_PAD_LCD_CLK),
+	IMX_PINCTRL_PIN(MX6SL_PAD_LCD_DAT0),
+	IMX_PINCTRL_PIN(MX6SL_PAD_LCD_DAT1),
+	IMX_PINCTRL_PIN(MX6SL_PAD_LCD_DAT10),
+	IMX_PINCTRL_PIN(MX6SL_PAD_LCD_DAT11),
+	IMX_PINCTRL_PIN(MX6SL_PAD_LCD_DAT12),
+	IMX_PINCTRL_PIN(MX6SL_PAD_LCD_DAT13),
+	IMX_PINCTRL_PIN(MX6SL_PAD_LCD_DAT14),
+	IMX_PINCTRL_PIN(MX6SL_PAD_LCD_DAT15),
+	IMX_PINCTRL_PIN(MX6SL_PAD_LCD_DAT16),
+	IMX_PINCTRL_PIN(MX6SL_PAD_LCD_DAT17),
+	IMX_PINCTRL_PIN(MX6SL_PAD_LCD_DAT18),
+	IMX_PINCTRL_PIN(MX6SL_PAD_LCD_DAT19),
+	IMX_PINCTRL_PIN(MX6SL_PAD_LCD_DAT2),
+	IMX_PINCTRL_PIN(MX6SL_PAD_LCD_DAT20),
+	IMX_PINCTRL_PIN(MX6SL_PAD_LCD_DAT21),
+	IMX_PINCTRL_PIN(MX6SL_PAD_LCD_DAT22),
+	IMX_PINCTRL_PIN(MX6SL_PAD_LCD_DAT23),
+	IMX_PINCTRL_PIN(MX6SL_PAD_LCD_DAT3),
+	IMX_PINCTRL_PIN(MX6SL_PAD_LCD_DAT4),
+	IMX_PINCTRL_PIN(MX6SL_PAD_LCD_DAT5),
+	IMX_PINCTRL_PIN(MX6SL_PAD_LCD_DAT6),
+	IMX_PINCTRL_PIN(MX6SL_PAD_LCD_DAT7),
+	IMX_PINCTRL_PIN(MX6SL_PAD_LCD_DAT8),
+	IMX_PINCTRL_PIN(MX6SL_PAD_LCD_DAT9),
+	IMX_PINCTRL_PIN(MX6SL_PAD_LCD_ENABLE),
+	IMX_PINCTRL_PIN(MX6SL_PAD_LCD_HSYNC),
+	IMX_PINCTRL_PIN(MX6SL_PAD_LCD_RESET),
+	IMX_PINCTRL_PIN(MX6SL_PAD_LCD_VSYNC),
+	IMX_PINCTRL_PIN(MX6SL_PAD_PWM1),
+	IMX_PINCTRL_PIN(MX6SL_PAD_REF_CLK_24M),
+	IMX_PINCTRL_PIN(MX6SL_PAD_REF_CLK_32K),
+	IMX_PINCTRL_PIN(MX6SL_PAD_SD1_CLK),
+	IMX_PINCTRL_PIN(MX6SL_PAD_SD1_CMD),
+	IMX_PINCTRL_PIN(MX6SL_PAD_SD1_DAT0),
+	IMX_PINCTRL_PIN(MX6SL_PAD_SD1_DAT1),
+	IMX_PINCTRL_PIN(MX6SL_PAD_SD1_DAT2),
+	IMX_PINCTRL_PIN(MX6SL_PAD_SD1_DAT3),
+	IMX_PINCTRL_PIN(MX6SL_PAD_SD1_DAT4),
+	IMX_PINCTRL_PIN(MX6SL_PAD_SD1_DAT5),
+	IMX_PINCTRL_PIN(MX6SL_PAD_SD1_DAT6),
+	IMX_PINCTRL_PIN(MX6SL_PAD_SD1_DAT7),
+	IMX_PINCTRL_PIN(MX6SL_PAD_SD2_CLK),
+	IMX_PINCTRL_PIN(MX6SL_PAD_SD2_CMD),
+	IMX_PINCTRL_PIN(MX6SL_PAD_SD2_DAT0),
+	IMX_PINCTRL_PIN(MX6SL_PAD_SD2_DAT1),
+	IMX_PINCTRL_PIN(MX6SL_PAD_SD2_DAT2),
+	IMX_PINCTRL_PIN(MX6SL_PAD_SD2_DAT3),
+	IMX_PINCTRL_PIN(MX6SL_PAD_SD2_DAT4),
+	IMX_PINCTRL_PIN(MX6SL_PAD_SD2_DAT5),
+	IMX_PINCTRL_PIN(MX6SL_PAD_SD2_DAT6),
+	IMX_PINCTRL_PIN(MX6SL_PAD_SD2_DAT7),
+	IMX_PINCTRL_PIN(MX6SL_PAD_SD2_RST),
+	IMX_PINCTRL_PIN(MX6SL_PAD_SD3_CLK),
+	IMX_PINCTRL_PIN(MX6SL_PAD_SD3_CMD),
+	IMX_PINCTRL_PIN(MX6SL_PAD_SD3_DAT0),
+	IMX_PINCTRL_PIN(MX6SL_PAD_SD3_DAT1),
+	IMX_PINCTRL_PIN(MX6SL_PAD_SD3_DAT2),
+	IMX_PINCTRL_PIN(MX6SL_PAD_SD3_DAT3),
+	IMX_PINCTRL_PIN(MX6SL_PAD_UART1_RXD),
+	IMX_PINCTRL_PIN(MX6SL_PAD_UART1_TXD),
+	IMX_PINCTRL_PIN(MX6SL_PAD_WDOG_B),
+};
+
+static struct imx_pinctrl_soc_info imx6sl_pinctrl_info = {
+	.pins = imx6sl_pinctrl_pads,
+	.npins = ARRAY_SIZE(imx6sl_pinctrl_pads),
+};
+
+static struct of_device_id imx6sl_pinctrl_of_match[] = {
+	{ .compatible = "fsl,imx6sl-iomuxc", },
+	{ /* sentinel */ }
+};
+
+static int imx6sl_pinctrl_probe(struct platform_device *pdev)
+{
+	return imx_pinctrl_probe(pdev, &imx6sl_pinctrl_info);
+}
+
+static struct platform_driver imx6sl_pinctrl_driver = {
+	.driver = {
+		.name = "imx6sl-pinctrl",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(imx6sl_pinctrl_of_match),
+	},
+	.probe = imx6sl_pinctrl_probe,
+	.remove = imx_pinctrl_remove,
+};
+
+static int __init imx6sl_pinctrl_init(void)
+{
+	return platform_driver_register(&imx6sl_pinctrl_driver);
+}
+arch_initcall(imx6sl_pinctrl_init);
+
+static void __exit imx6sl_pinctrl_exit(void)
+{
+	platform_driver_unregister(&imx6sl_pinctrl_driver);
+}
+module_exit(imx6sl_pinctrl_exit);
+
+MODULE_AUTHOR("Shawn Guo <shawn.guo@linaro.org>");
+MODULE_DESCRIPTION("Freescale imx6sl pinctrl driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/pinctrl-lantiq.c b/drivers/pinctrl/pinctrl-lantiq.c
index a703846..615c500 100644
--- a/drivers/pinctrl/pinctrl-lantiq.c
+++ b/drivers/pinctrl/pinctrl-lantiq.c
@@ -169,7 +169,7 @@ static int ltq_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
 	return 0;
 }
 
-static struct pinctrl_ops ltq_pctrl_ops = {
+static const struct pinctrl_ops ltq_pctrl_ops = {
 	.get_groups_count	= ltq_get_group_count,
 	.get_group_name		= ltq_get_group_name,
 	.get_group_pins		= ltq_get_group_pins,
@@ -311,7 +311,7 @@ static int ltq_pmx_gpio_request_enable(struct pinctrl_dev *pctrldev,
 	return info->apply_mux(pctrldev, mfp, pin_func);
 }
 
-static struct pinmux_ops ltq_pmx_ops = {
+static const struct pinmux_ops ltq_pmx_ops = {
 	.get_functions_count	= ltq_pmx_func_count,
 	.get_function_name	= ltq_pmx_func_name,
 	.get_function_groups	= ltq_pmx_get_groups,
diff --git a/drivers/pinctrl/pinctrl-mmp2.c b/drivers/pinctrl/pinctrl-mmp2.c
deleted file mode 100644
index 4afa56a..0000000
--- a/drivers/pinctrl/pinctrl-mmp2.c
+++ /dev/null
@@ -1,722 +0,0 @@
-/*
- *  linux/drivers/pinctrl/pinmux-mmp2.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
- *  publishhed by the Free Software Foundation.
- *
- *  Copyright (C) 2011, Marvell Technology Group Ltd.
- *
- *  Author: Haojian Zhuang <haojian.zhuang@marvell.com>
- *
- */
-
-#include <linux/device.h>
-#include <linux/module.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include "pinctrl-pxa3xx.h"
-
-#define MMP2_DS_MASK		0x1800
-#define MMP2_DS_SHIFT		11
-#define MMP2_SLEEP_MASK		0x38
-#define MMP2_SLEEP_SELECT	(1 << 9)
-#define MMP2_SLEEP_DATA		(1 << 8)
-#define MMP2_SLEEP_DIR		(1 << 7)
-
-#define MFPR_MMP2(a, r, f0, f1, f2, f3, f4, f5, f6, f7)		\
-	{							\
-		.name = #a,					\
-		.pin = a,					\
-		.mfpr = r,					\
-		.func = {					\
-			MMP2_MUX_##f0,				\
-			MMP2_MUX_##f1,				\
-			MMP2_MUX_##f2,				\
-			MMP2_MUX_##f3,				\
-			MMP2_MUX_##f4,				\
-			MMP2_MUX_##f5,				\
-			MMP2_MUX_##f6,				\
-			MMP2_MUX_##f7,				\
-		},						\
-	}
-
-#define GRP_MMP2(a, m, p)		\
-	{ .name = a, .mux = MMP2_MUX_##m, .pins = p, .npins = ARRAY_SIZE(p), }
-
-/* 174 pins */
-enum mmp2_pin_list {
-	/* 0~168: GPIO0~GPIO168 */
-	TWSI4_SCL = 169,
-	TWSI4_SDA, /* 170 */
-	G_CLKREQ,
-	VCXO_REQ,
-	VCXO_OUT,
-};
-
-enum mmp2_mux {
-	/* PXA3xx_MUX_GPIO = 0 (predefined in pinctrl-pxa3xx.h) */
-	MMP2_MUX_GPIO = 0,
-	MMP2_MUX_G_CLKREQ,
-	MMP2_MUX_VCXO_REQ,
-	MMP2_MUX_VCXO_OUT,
-	MMP2_MUX_KP_MK,
-	MMP2_MUX_KP_DK,
-	MMP2_MUX_CCIC1,
-	MMP2_MUX_CCIC2,
-	MMP2_MUX_SPI,
-	MMP2_MUX_SSPA2,
-	MMP2_MUX_ROT,
-	MMP2_MUX_I2S,
-	MMP2_MUX_TB,
-	MMP2_MUX_CAM2,
-	MMP2_MUX_HDMI,
-	MMP2_MUX_TWSI2,
-	MMP2_MUX_TWSI3,
-	MMP2_MUX_TWSI4,
-	MMP2_MUX_TWSI5,
-	MMP2_MUX_TWSI6,
-	MMP2_MUX_UART1,
-	MMP2_MUX_UART2,
-	MMP2_MUX_UART3,
-	MMP2_MUX_UART4,
-	MMP2_MUX_SSP1_RX,
-	MMP2_MUX_SSP1_FRM,
-	MMP2_MUX_SSP1_TXRX,
-	MMP2_MUX_SSP2_RX,
-	MMP2_MUX_SSP2_FRM,
-	MMP2_MUX_SSP1,
-	MMP2_MUX_SSP2,
-	MMP2_MUX_SSP3,
-	MMP2_MUX_SSP4,
-	MMP2_MUX_MMC1,
-	MMP2_MUX_MMC2,
-	MMP2_MUX_MMC3,
-	MMP2_MUX_MMC4,
-	MMP2_MUX_ULPI,
-	MMP2_MUX_AC,
-	MMP2_MUX_CA,
-	MMP2_MUX_PWM,
-	MMP2_MUX_USIM,
-	MMP2_MUX_TIPU,
-	MMP2_MUX_PLL,
-	MMP2_MUX_NAND,
-	MMP2_MUX_FSIC,
-	MMP2_MUX_SLEEP_IND,
-	MMP2_MUX_EXT_DMA,
-	MMP2_MUX_ONE_WIRE,
-	MMP2_MUX_LCD,
-	MMP2_MUX_SMC,
-	MMP2_MUX_SMC_INT,
-	MMP2_MUX_MSP,
-	MMP2_MUX_G_CLKOUT,
-	MMP2_MUX_32K_CLKOUT,
-	MMP2_MUX_PRI_JTAG,
-	MMP2_MUX_AAS_JTAG,
-	MMP2_MUX_AAS_GPIO,
-	MMP2_MUX_AAS_SPI,
-	MMP2_MUX_AAS_TWSI,
-	MMP2_MUX_AAS_DEU_EX,
-	MMP2_MUX_NONE = 0xffff,
-};
-
-static struct pinctrl_pin_desc mmp2_pads[] = {
-	/*
-	 * The name indicates function 0 of this pin.
-	 * After reset, function 0 is the default function of pin.
-	 */
-	PINCTRL_PIN(GPIO0, "GPIO0"),
-	PINCTRL_PIN(GPIO1, "GPIO1"),
-	PINCTRL_PIN(GPIO2, "GPIO2"),
-	PINCTRL_PIN(GPIO3, "GPIO3"),
-	PINCTRL_PIN(GPIO4, "GPIO4"),
-	PINCTRL_PIN(GPIO5, "GPIO5"),
-	PINCTRL_PIN(GPIO6, "GPIO6"),
-	PINCTRL_PIN(GPIO7, "GPIO7"),
-	PINCTRL_PIN(GPIO8, "GPIO8"),
-	PINCTRL_PIN(GPIO9, "GPIO9"),
-	PINCTRL_PIN(GPIO10, "GPIO10"),
-	PINCTRL_PIN(GPIO11, "GPIO11"),
-	PINCTRL_PIN(GPIO12, "GPIO12"),
-	PINCTRL_PIN(GPIO13, "GPIO13"),
-	PINCTRL_PIN(GPIO14, "GPIO14"),
-	PINCTRL_PIN(GPIO15, "GPIO15"),
-	PINCTRL_PIN(GPIO16, "GPIO16"),
-	PINCTRL_PIN(GPIO17, "GPIO17"),
-	PINCTRL_PIN(GPIO18, "GPIO18"),
-	PINCTRL_PIN(GPIO19, "GPIO19"),
-	PINCTRL_PIN(GPIO20, "GPIO20"),
-	PINCTRL_PIN(GPIO21, "GPIO21"),
-	PINCTRL_PIN(GPIO22, "GPIO22"),
-	PINCTRL_PIN(GPIO23, "GPIO23"),
-	PINCTRL_PIN(GPIO24, "GPIO24"),
-	PINCTRL_PIN(GPIO25, "GPIO25"),
-	PINCTRL_PIN(GPIO26, "GPIO26"),
-	PINCTRL_PIN(GPIO27, "GPIO27"),
-	PINCTRL_PIN(GPIO28, "GPIO28"),
-	PINCTRL_PIN(GPIO29, "GPIO29"),
-	PINCTRL_PIN(GPIO30, "GPIO30"),
-	PINCTRL_PIN(GPIO31, "GPIO31"),
-	PINCTRL_PIN(GPIO32, "GPIO32"),
-	PINCTRL_PIN(GPIO33, "GPIO33"),
-	PINCTRL_PIN(GPIO34, "GPIO34"),
-	PINCTRL_PIN(GPIO35, "GPIO35"),
-	PINCTRL_PIN(GPIO36, "GPIO36"),
-	PINCTRL_PIN(GPIO37, "GPIO37"),
-	PINCTRL_PIN(GPIO38, "GPIO38"),
-	PINCTRL_PIN(GPIO39, "GPIO39"),
-	PINCTRL_PIN(GPIO40, "GPIO40"),
-	PINCTRL_PIN(GPIO41, "GPIO41"),
-	PINCTRL_PIN(GPIO42, "GPIO42"),
-	PINCTRL_PIN(GPIO43, "GPIO43"),
-	PINCTRL_PIN(GPIO44, "GPIO44"),
-	PINCTRL_PIN(GPIO45, "GPIO45"),
-	PINCTRL_PIN(GPIO46, "GPIO46"),
-	PINCTRL_PIN(GPIO47, "GPIO47"),
-	PINCTRL_PIN(GPIO48, "GPIO48"),
-	PINCTRL_PIN(GPIO49, "GPIO49"),
-	PINCTRL_PIN(GPIO50, "GPIO50"),
-	PINCTRL_PIN(GPIO51, "GPIO51"),
-	PINCTRL_PIN(GPIO52, "GPIO52"),
-	PINCTRL_PIN(GPIO53, "GPIO53"),
-	PINCTRL_PIN(GPIO54, "GPIO54"),
-	PINCTRL_PIN(GPIO55, "GPIO55"),
-	PINCTRL_PIN(GPIO56, "GPIO56"),
-	PINCTRL_PIN(GPIO57, "GPIO57"),
-	PINCTRL_PIN(GPIO58, "GPIO58"),
-	PINCTRL_PIN(GPIO59, "GPIO59"),
-	PINCTRL_PIN(GPIO60, "GPIO60"),
-	PINCTRL_PIN(GPIO61, "GPIO61"),
-	PINCTRL_PIN(GPIO62, "GPIO62"),
-	PINCTRL_PIN(GPIO63, "GPIO63"),
-	PINCTRL_PIN(GPIO64, "GPIO64"),
-	PINCTRL_PIN(GPIO65, "GPIO65"),
-	PINCTRL_PIN(GPIO66, "GPIO66"),
-	PINCTRL_PIN(GPIO67, "GPIO67"),
-	PINCTRL_PIN(GPIO68, "GPIO68"),
-	PINCTRL_PIN(GPIO69, "GPIO69"),
-	PINCTRL_PIN(GPIO70, "GPIO70"),
-	PINCTRL_PIN(GPIO71, "GPIO71"),
-	PINCTRL_PIN(GPIO72, "GPIO72"),
-	PINCTRL_PIN(GPIO73, "GPIO73"),
-	PINCTRL_PIN(GPIO74, "GPIO74"),
-	PINCTRL_PIN(GPIO75, "GPIO75"),
-	PINCTRL_PIN(GPIO76, "GPIO76"),
-	PINCTRL_PIN(GPIO77, "GPIO77"),
-	PINCTRL_PIN(GPIO78, "GPIO78"),
-	PINCTRL_PIN(GPIO79, "GPIO79"),
-	PINCTRL_PIN(GPIO80, "GPIO80"),
-	PINCTRL_PIN(GPIO81, "GPIO81"),
-	PINCTRL_PIN(GPIO82, "GPIO82"),
-	PINCTRL_PIN(GPIO83, "GPIO83"),
-	PINCTRL_PIN(GPIO84, "GPIO84"),
-	PINCTRL_PIN(GPIO85, "GPIO85"),
-	PINCTRL_PIN(GPIO86, "GPIO86"),
-	PINCTRL_PIN(GPIO87, "GPIO87"),
-	PINCTRL_PIN(GPIO88, "GPIO88"),
-	PINCTRL_PIN(GPIO89, "GPIO89"),
-	PINCTRL_PIN(GPIO90, "GPIO90"),
-	PINCTRL_PIN(GPIO91, "GPIO91"),
-	PINCTRL_PIN(GPIO92, "GPIO92"),
-	PINCTRL_PIN(GPIO93, "GPIO93"),
-	PINCTRL_PIN(GPIO94, "GPIO94"),
-	PINCTRL_PIN(GPIO95, "GPIO95"),
-	PINCTRL_PIN(GPIO96, "GPIO96"),
-	PINCTRL_PIN(GPIO97, "GPIO97"),
-	PINCTRL_PIN(GPIO98, "GPIO98"),
-	PINCTRL_PIN(GPIO99, "GPIO99"),
-	PINCTRL_PIN(GPIO100, "GPIO100"),
-	PINCTRL_PIN(GPIO101, "GPIO101"),
-	PINCTRL_PIN(GPIO102, "GPIO102"),
-	PINCTRL_PIN(GPIO103, "GPIO103"),
-	PINCTRL_PIN(GPIO104, "GPIO104"),
-	PINCTRL_PIN(GPIO105, "GPIO105"),
-	PINCTRL_PIN(GPIO106, "GPIO106"),
-	PINCTRL_PIN(GPIO107, "GPIO107"),
-	PINCTRL_PIN(GPIO108, "GPIO108"),
-	PINCTRL_PIN(GPIO109, "GPIO109"),
-	PINCTRL_PIN(GPIO110, "GPIO110"),
-	PINCTRL_PIN(GPIO111, "GPIO111"),
-	PINCTRL_PIN(GPIO112, "GPIO112"),
-	PINCTRL_PIN(GPIO113, "GPIO113"),
-	PINCTRL_PIN(GPIO114, "GPIO114"),
-	PINCTRL_PIN(GPIO115, "GPIO115"),
-	PINCTRL_PIN(GPIO116, "GPIO116"),
-	PINCTRL_PIN(GPIO117, "GPIO117"),
-	PINCTRL_PIN(GPIO118, "GPIO118"),
-	PINCTRL_PIN(GPIO119, "GPIO119"),
-	PINCTRL_PIN(GPIO120, "GPIO120"),
-	PINCTRL_PIN(GPIO121, "GPIO121"),
-	PINCTRL_PIN(GPIO122, "GPIO122"),
-	PINCTRL_PIN(GPIO123, "GPIO123"),
-	PINCTRL_PIN(GPIO124, "GPIO124"),
-	PINCTRL_PIN(GPIO125, "GPIO125"),
-	PINCTRL_PIN(GPIO126, "GPIO126"),
-	PINCTRL_PIN(GPIO127, "GPIO127"),
-	PINCTRL_PIN(GPIO128, "GPIO128"),
-	PINCTRL_PIN(GPIO129, "GPIO129"),
-	PINCTRL_PIN(GPIO130, "GPIO130"),
-	PINCTRL_PIN(GPIO131, "GPIO131"),
-	PINCTRL_PIN(GPIO132, "GPIO132"),
-	PINCTRL_PIN(GPIO133, "GPIO133"),
-	PINCTRL_PIN(GPIO134, "GPIO134"),
-	PINCTRL_PIN(GPIO135, "GPIO135"),
-	PINCTRL_PIN(GPIO136, "GPIO136"),
-	PINCTRL_PIN(GPIO137, "GPIO137"),
-	PINCTRL_PIN(GPIO138, "GPIO138"),
-	PINCTRL_PIN(GPIO139, "GPIO139"),
-	PINCTRL_PIN(GPIO140, "GPIO140"),
-	PINCTRL_PIN(GPIO141, "GPIO141"),
-	PINCTRL_PIN(GPIO142, "GPIO142"),
-	PINCTRL_PIN(GPIO143, "GPIO143"),
-	PINCTRL_PIN(GPIO144, "GPIO144"),
-	PINCTRL_PIN(GPIO145, "GPIO145"),
-	PINCTRL_PIN(GPIO146, "GPIO146"),
-	PINCTRL_PIN(GPIO147, "GPIO147"),
-	PINCTRL_PIN(GPIO148, "GPIO148"),
-	PINCTRL_PIN(GPIO149, "GPIO149"),
-	PINCTRL_PIN(GPIO150, "GPIO150"),
-	PINCTRL_PIN(GPIO151, "GPIO151"),
-	PINCTRL_PIN(GPIO152, "GPIO152"),
-	PINCTRL_PIN(GPIO153, "GPIO153"),
-	PINCTRL_PIN(GPIO154, "GPIO154"),
-	PINCTRL_PIN(GPIO155, "GPIO155"),
-	PINCTRL_PIN(GPIO156, "GPIO156"),
-	PINCTRL_PIN(GPIO157, "GPIO157"),
-	PINCTRL_PIN(GPIO158, "GPIO158"),
-	PINCTRL_PIN(GPIO159, "GPIO159"),
-	PINCTRL_PIN(GPIO160, "GPIO160"),
-	PINCTRL_PIN(GPIO161, "GPIO161"),
-	PINCTRL_PIN(GPIO162, "GPIO162"),
-	PINCTRL_PIN(GPIO163, "GPIO163"),
-	PINCTRL_PIN(GPIO164, "GPIO164"),
-	PINCTRL_PIN(GPIO165, "GPIO165"),
-	PINCTRL_PIN(GPIO166, "GPIO166"),
-	PINCTRL_PIN(GPIO167, "GPIO167"),
-	PINCTRL_PIN(GPIO168, "GPIO168"),
-	PINCTRL_PIN(TWSI4_SCL, "TWSI4_SCL"),
-	PINCTRL_PIN(TWSI4_SDA, "TWSI4_SDA"),
-	PINCTRL_PIN(G_CLKREQ, "G_CLKREQ"),
-	PINCTRL_PIN(VCXO_REQ, "VCXO_REQ"),
-	PINCTRL_PIN(VCXO_OUT, "VCXO_OUT"),
-};
-
-struct pxa3xx_mfp_pin mmp2_mfp[] = {
-	/*       pin         offs   f0        f1          f2          f3          f4          f5        f6        f7  */
-	MFPR_MMP2(GPIO0,     0x054, GPIO,     KP_MK,      NONE,       SPI,        NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO1,     0x058, GPIO,     KP_MK,      NONE,       SPI,        NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO2,     0x05C, GPIO,     KP_MK,      NONE,       SPI,        NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO3,     0x060, GPIO,     KP_MK,      NONE,       SPI,        NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO4,     0x064, GPIO,     KP_MK,      NONE,       NONE,       NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO5,     0x068, GPIO,     KP_MK,      NONE,       SPI,        NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO6,     0x06C, GPIO,     KP_MK,      NONE,       SPI,        NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO7,     0x070, GPIO,     KP_MK,      NONE,       SPI,        NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO8,     0x074, GPIO,     KP_MK,      NONE,       NONE,       NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO9,     0x078, GPIO,     KP_MK,      NONE,       NONE,       NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO10,    0x07C, GPIO,     KP_MK,      NONE,       NONE,       NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO11,    0x080, GPIO,     KP_MK,      NONE,       NONE,       NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO12,    0x084, GPIO,     KP_MK,      NONE,       CCIC1,      NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO13,    0x088, GPIO,     KP_MK,      NONE,       CCIC1,      NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO14,    0x08C, GPIO,     KP_MK,      NONE,       CCIC1,      NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO15,    0x090, GPIO,     KP_MK,      KP_DK,      CCIC1,      NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO16,    0x094, GPIO,     KP_DK,      ROT,        CCIC1,      NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO17,    0x098, GPIO,     KP_DK,      ROT,        CCIC1,      NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO18,    0x09C, GPIO,     KP_DK,      ROT,        CCIC1,      NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO19,    0x0A0, GPIO,     KP_DK,      ROT,        CCIC1,      NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO20,    0x0A4, GPIO,     KP_DK,      TB,         CCIC1,      NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO21,    0x0A8, GPIO,     KP_DK,      TB,         CCIC1,      NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO22,    0x0AC, GPIO,     KP_DK,      TB,         CCIC1,      NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO23,    0x0B0, GPIO,     KP_DK,      TB,         CCIC1,      NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO24,    0x0B4, GPIO,     I2S,        VCXO_OUT,   NONE,       NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO25,    0x0B8, GPIO,     I2S,        HDMI,       SSPA2,      NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO26,    0x0BC, GPIO,     I2S,        HDMI,       SSPA2,      NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO27,    0x0C0, GPIO,     I2S,        HDMI,       SSPA2,      NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO28,    0x0C4, GPIO,     I2S,        NONE,       SSPA2,      NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO29,    0x0C8, GPIO,     UART1,      KP_MK,      NONE,       NONE,       NONE,     AAS_SPI,  NONE),
-	MFPR_MMP2(GPIO30,    0x0CC, GPIO,     UART1,      KP_MK,      NONE,       NONE,       NONE,     AAS_SPI,  NONE),
-	MFPR_MMP2(GPIO31,    0x0D0, GPIO,     UART1,      KP_MK,      NONE,       NONE,       NONE,     AAS_SPI,  NONE),
-	MFPR_MMP2(GPIO32,    0x0D4, GPIO,     UART1,      KP_MK,      NONE,       NONE,       NONE,     AAS_SPI,  NONE),
-	MFPR_MMP2(GPIO33,    0x0D8, GPIO,     SSPA2,      I2S,        NONE,       NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO34,    0x0DC, GPIO,     SSPA2,      I2S,        NONE,       NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO35,    0x0E0, GPIO,     SSPA2,      I2S,        NONE,       NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO36,    0x0E4, GPIO,     SSPA2,      I2S,        NONE,       NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO37,    0x0E8, GPIO,     MMC2,       SSP1,       TWSI2,      UART2,      UART3,    AAS_SPI,  AAS_TWSI),
-	MFPR_MMP2(GPIO38,    0x0EC, GPIO,     MMC2,       SSP1,       TWSI2,      UART2,      UART3,    AAS_SPI,  AAS_TWSI),
-	MFPR_MMP2(GPIO39,    0x0F0, GPIO,     MMC2,       SSP1,       TWSI2,      UART2,      UART3,    AAS_SPI,  AAS_TWSI),
-	MFPR_MMP2(GPIO40,    0x0F4, GPIO,     MMC2,       SSP1,       TWSI2,      UART2,      UART3,    AAS_SPI,  AAS_TWSI),
-	MFPR_MMP2(GPIO41,    0x0F8, GPIO,     MMC2,       TWSI5,      NONE,       NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO42,    0x0FC, GPIO,     MMC2,       TWSI5,      NONE,       NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO43,    0x100, GPIO,     TWSI2,      UART4,      SSP1,       UART2,      UART3,    NONE,     AAS_TWSI),
-	MFPR_MMP2(GPIO44,    0x104, GPIO,     TWSI2,      UART4,      SSP1,       UART2,      UART3,    NONE,     AAS_TWSI),
-	MFPR_MMP2(GPIO45,    0x108, GPIO,     UART1,      UART4,      SSP1,       UART2,      UART3,    NONE,     NONE),
-	MFPR_MMP2(GPIO46,    0x10C, GPIO,     UART1,      UART4,      SSP1,       UART2,      UART3,    NONE,     NONE),
-	MFPR_MMP2(GPIO47,    0x110, GPIO,     UART2,      SSP2,       TWSI6,      CAM2,       AAS_SPI,  AAS_GPIO, NONE),
-	MFPR_MMP2(GPIO48,    0x114, GPIO,     UART2,      SSP2,       TWSI6,      CAM2,       AAS_SPI,  AAS_GPIO, NONE),
-	MFPR_MMP2(GPIO49,    0x118, GPIO,     UART2,      SSP2,       PWM,        CCIC2,      AAS_SPI,  NONE,     NONE),
-	MFPR_MMP2(GPIO50,    0x11C, GPIO,     UART2,      SSP2,       PWM,        CCIC2,      AAS_SPI,  NONE,     NONE),
-	MFPR_MMP2(GPIO51,    0x120, GPIO,     UART3,      ROT,        AAS_GPIO,   PWM,        NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO52,    0x124, GPIO,     UART3,      ROT,        AAS_GPIO,   PWM,        NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO53,    0x128, GPIO,     UART3,      TWSI2,      VCXO_REQ,   NONE,       PWM,      NONE,     AAS_TWSI),
-	MFPR_MMP2(GPIO54,    0x12C, GPIO,     UART3,      TWSI2,      VCXO_OUT,   HDMI,       PWM,      NONE,     AAS_TWSI),
-	MFPR_MMP2(GPIO55,    0x130, GPIO,     SSP2,       SSP1,       UART2,      ROT,        TWSI2,    SSP3,     AAS_TWSI),
-	MFPR_MMP2(GPIO56,    0x134, GPIO,     SSP2,       SSP1,       UART2,      ROT,        TWSI2,    KP_DK,    AAS_TWSI),
-	MFPR_MMP2(GPIO57,    0x138, GPIO,     SSP2_RX,    SSP1_TXRX,  SSP2_FRM,   SSP1_RX,    VCXO_REQ, KP_DK,    NONE),
-	MFPR_MMP2(GPIO58,    0x13C, GPIO,     SSP2,       SSP1_RX,    SSP1_FRM,   SSP1_TXRX,  VCXO_REQ, KP_DK,    NONE),
-	MFPR_MMP2(GPIO59,    0x280, GPIO,     CCIC1,      ULPI,       MMC3,       CCIC2,      UART3,    UART4,    NONE),
-	MFPR_MMP2(GPIO60,    0x284, GPIO,     CCIC1,      ULPI,       MMC3,       CCIC2,      UART3,    UART4,    NONE),
-	MFPR_MMP2(GPIO61,    0x288, GPIO,     CCIC1,      ULPI,       MMC3,       CCIC2,      UART3,    HDMI,     NONE),
-	MFPR_MMP2(GPIO62,    0x28C, GPIO,     CCIC1,      ULPI,       MMC3,       CCIC2,      UART3,    NONE,     NONE),
-	MFPR_MMP2(GPIO63,    0x290, GPIO,     CCIC1,      ULPI,       MMC3,       CCIC2,      MSP,      UART4,    NONE),
-	MFPR_MMP2(GPIO64,    0x294, GPIO,     CCIC1,      ULPI,       MMC3,       CCIC2,      MSP,      UART4,    NONE),
-	MFPR_MMP2(GPIO65,    0x298, GPIO,     CCIC1,      ULPI,       MMC3,       CCIC2,      MSP,      UART4,    NONE),
-	MFPR_MMP2(GPIO66,    0x29C, GPIO,     CCIC1,      ULPI,       MMC3,       CCIC2,      MSP,      UART4,    NONE),
-	MFPR_MMP2(GPIO67,    0x2A0, GPIO,     CCIC1,      ULPI,       MMC3,       CCIC2,      MSP,      NONE,     NONE),
-	MFPR_MMP2(GPIO68,    0x2A4, GPIO,     CCIC1,      ULPI,       MMC3,       CCIC2,      MSP,      LCD,      NONE),
-	MFPR_MMP2(GPIO69,    0x2A8, GPIO,     CCIC1,      ULPI,       MMC3,       CCIC2,      NONE,     LCD,      NONE),
-	MFPR_MMP2(GPIO70,    0x2AC, GPIO,     CCIC1,      ULPI,       MMC3,       CCIC2,      MSP,      LCD,      NONE),
-	MFPR_MMP2(GPIO71,    0x2B0, GPIO,     TWSI3,      NONE,       PWM,        NONE,       NONE,     LCD,      AAS_TWSI),
-	MFPR_MMP2(GPIO72,    0x2B4, GPIO,     TWSI3,      HDMI,       PWM,        NONE,       NONE,     LCD,      AAS_TWSI),
-	MFPR_MMP2(GPIO73,    0x2B8, GPIO,     VCXO_REQ,   32K_CLKOUT, PWM,        VCXO_OUT,   NONE,     LCD,      NONE),
-	MFPR_MMP2(GPIO74,    0x170, GPIO,     LCD,        SMC,        MMC4,       SSP3,       UART2,    UART4,    TIPU),
-	MFPR_MMP2(GPIO75,    0x174, GPIO,     LCD,        SMC,        MMC4,       SSP3,       UART2,    UART4,    TIPU),
-	MFPR_MMP2(GPIO76,    0x178, GPIO,     LCD,        SMC,        MMC4,       SSP3,       UART2,    UART4,    TIPU),
-	MFPR_MMP2(GPIO77,    0x17C, GPIO,     LCD,        SMC,        MMC4,       SSP3,       UART2,    UART4,    TIPU),
-	MFPR_MMP2(GPIO78,    0x180, GPIO,     LCD,        HDMI,       MMC4,       NONE,       SSP4,     AAS_SPI,  TIPU),
-	MFPR_MMP2(GPIO79,    0x184, GPIO,     LCD,        AAS_GPIO,   MMC4,       NONE,       SSP4,     AAS_SPI,  TIPU),
-	MFPR_MMP2(GPIO80,    0x188, GPIO,     LCD,        AAS_GPIO,   MMC4,       NONE,       SSP4,     AAS_SPI,  TIPU),
-	MFPR_MMP2(GPIO81,    0x18C, GPIO,     LCD,        AAS_GPIO,   MMC4,       NONE,       SSP4,     AAS_SPI,  TIPU),
-	MFPR_MMP2(GPIO82,    0x190, GPIO,     LCD,        NONE,       MMC4,       NONE,       NONE,     CCIC2,    TIPU),
-	MFPR_MMP2(GPIO83,    0x194, GPIO,     LCD,        NONE,       MMC4,       NONE,       NONE,     CCIC2,    TIPU),
-	MFPR_MMP2(GPIO84,    0x198, GPIO,     LCD,        SMC,        MMC2,       NONE,       TWSI5,    AAS_TWSI, TIPU),
-	MFPR_MMP2(GPIO85,    0x19C, GPIO,     LCD,        SMC,        MMC2,       NONE,       TWSI5,    AAS_TWSI, TIPU),
-	MFPR_MMP2(GPIO86,    0x1A0, GPIO,     LCD,        SMC,        MMC2,       NONE,       TWSI6,    CCIC2,    TIPU),
-	MFPR_MMP2(GPIO87,    0x1A4, GPIO,     LCD,        SMC,        MMC2,       NONE,       TWSI6,    CCIC2,    TIPU),
-	MFPR_MMP2(GPIO88,    0x1A8, GPIO,     LCD,        AAS_GPIO,   MMC2,       NONE,       NONE,     CCIC2,    TIPU),
-	MFPR_MMP2(GPIO89,    0x1AC, GPIO,     LCD,        AAS_GPIO,   MMC2,       NONE,       NONE,     CCIC2,    TIPU),
-	MFPR_MMP2(GPIO90,    0x1B0, GPIO,     LCD,        AAS_GPIO,   MMC2,       NONE,       NONE,     CCIC2,    TIPU),
-	MFPR_MMP2(GPIO91,    0x1B4, GPIO,     LCD,        AAS_GPIO,   MMC2,       NONE,       NONE,     CCIC2,    TIPU),
-	MFPR_MMP2(GPIO92,    0x1B8, GPIO,     LCD,        AAS_GPIO,   MMC2,       NONE,       NONE,     CCIC2,    TIPU),
-	MFPR_MMP2(GPIO93,    0x1BC, GPIO,     LCD,        AAS_GPIO,   MMC2,       NONE,       NONE,     CCIC2,    TIPU),
-	MFPR_MMP2(GPIO94,    0x1C0, GPIO,     LCD,        AAS_GPIO,   SPI,        NONE,       AAS_SPI,  CCIC2,    TIPU),
-	MFPR_MMP2(GPIO95,    0x1C4, GPIO,     LCD,        TWSI3,      SPI,        AAS_DEU_EX, AAS_SPI,  CCIC2,    TIPU),
-	MFPR_MMP2(GPIO96,    0x1C8, GPIO,     LCD,        TWSI3,      SPI,        AAS_DEU_EX, AAS_SPI,  NONE,     TIPU),
-	MFPR_MMP2(GPIO97,    0x1CC, GPIO,     LCD,        TWSI6,      SPI,        AAS_DEU_EX, AAS_SPI,  NONE,     TIPU),
-	MFPR_MMP2(GPIO98,    0x1D0, GPIO,     LCD,        TWSI6,      SPI,        ONE_WIRE,   NONE,     NONE,     TIPU),
-	MFPR_MMP2(GPIO99,    0x1D4, GPIO,     LCD,        SMC,        SPI,        TWSI5,      NONE,     NONE,     TIPU),
-	MFPR_MMP2(GPIO100,   0x1D8, GPIO,     LCD,        SMC,        SPI,        TWSI5,      NONE,     NONE,     TIPU),
-	MFPR_MMP2(GPIO101,   0x1DC, GPIO,     LCD,        SMC,        SPI,        NONE,       NONE,     NONE,     TIPU),
-	MFPR_MMP2(GPIO102,   0x000, USIM,     GPIO,       FSIC,       KP_DK,      LCD,        NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO103,   0x004, USIM,     GPIO,       FSIC,       KP_DK,      LCD,        NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO104,   0x1FC, NAND,     GPIO,       NONE,       NONE,       NAND,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO105,   0x1F8, NAND,     GPIO,       NONE,       NONE,       NAND,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO106,   0x1F4, NAND,     GPIO,       NONE,       NONE,       NAND,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO107,   0x1F0, NAND,     GPIO,       NONE,       NONE,       NAND,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO108,   0x21C, NAND,     GPIO,       NONE,       NONE,       NAND,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO109,   0x218, NAND,     GPIO,       NONE,       NONE,       NAND,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO110,   0x214, NAND,     GPIO,       NONE,       NONE,       NAND,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO111,   0x200, NAND,     GPIO,       MMC3,       NONE,       NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO112,   0x244, NAND,     GPIO,       MMC3,       SMC,        NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO113,   0x25C, SMC,      GPIO,       EXT_DMA,    MMC3,       SMC,        HDMI,     NONE,     NONE),
-	MFPR_MMP2(GPIO114,   0x164, G_CLKOUT, 32K_CLKOUT, HDMI,       NONE,       NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO115,   0x260, GPIO,     NONE,       AC,         UART4,      UART3,      SSP1,     NONE,     NONE),
-	MFPR_MMP2(GPIO116,   0x264, GPIO,     NONE,       AC,         UART4,      UART3,      SSP1,     NONE,     NONE),
-	MFPR_MMP2(GPIO117,   0x268, GPIO,     NONE,       AC,         UART4,      UART3,      SSP1,     NONE,     NONE),
-	MFPR_MMP2(GPIO118,   0x26C, GPIO,     NONE,       AC,         UART4,      UART3,      SSP1,     NONE,     NONE),
-	MFPR_MMP2(GPIO119,   0x270, GPIO,     NONE,       CA,         SSP3,       NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO120,   0x274, GPIO,     NONE,       CA,         SSP3,       NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO121,   0x278, GPIO,     NONE,       CA,         SSP3,       NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO122,   0x27C, GPIO,     NONE,       CA,         SSP3,       NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO123,   0x148, GPIO,     SLEEP_IND,  ONE_WIRE,   32K_CLKOUT, NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO124,   0x00C, GPIO,     MMC1,       LCD,        MMC3,       NAND,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO125,   0x010, GPIO,     MMC1,       LCD,        MMC3,       NAND,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO126,   0x014, GPIO,     MMC1,       LCD,        MMC3,       NAND,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO127,   0x018, GPIO,     NONE,       LCD,        MMC3,       NAND,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO128,   0x01C, GPIO,     NONE,       LCD,        MMC3,       NAND,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO129,   0x020, GPIO,     MMC1,       LCD,        MMC3,       NAND,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO130,   0x024, GPIO,     MMC1,       LCD,        MMC3,       NAND,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO131,   0x028, GPIO,     MMC1,       NONE,       MSP,        NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO132,   0x02C, GPIO,     MMC1,       PRI_JTAG,   MSP,        SSP3,       AAS_JTAG, NONE,     NONE),
-	MFPR_MMP2(GPIO133,   0x030, GPIO,     MMC1,       PRI_JTAG,   MSP,        SSP3,       AAS_JTAG, NONE,     NONE),
-	MFPR_MMP2(GPIO134,   0x034, GPIO,     MMC1,       PRI_JTAG,   MSP,        SSP3,       AAS_JTAG, NONE,     NONE),
-	MFPR_MMP2(GPIO135,   0x038, GPIO,     NONE,       LCD,        MMC3,       NAND,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO136,   0x03C, GPIO,     MMC1,       PRI_JTAG,   MSP,        SSP3,       AAS_JTAG, NONE,     NONE),
-	MFPR_MMP2(GPIO137,   0x040, GPIO,     HDMI,       LCD,        MSP,        NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO138,   0x044, GPIO,     NONE,       LCD,        MMC3,       SMC,        NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO139,   0x048, GPIO,     MMC1,       PRI_JTAG,   MSP,        NONE,       AAS_JTAG, NONE,     NONE),
-	MFPR_MMP2(GPIO140,   0x04C, GPIO,     MMC1,       LCD,        NONE,       NONE,       UART2,    UART1,    NONE),
-	MFPR_MMP2(GPIO141,   0x050, GPIO,     MMC1,       LCD,        NONE,       NONE,       UART2,    UART1,    NONE),
-	MFPR_MMP2(GPIO142,   0x008, USIM,     GPIO,       FSIC,       KP_DK,      NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO143,   0x220, NAND,     GPIO,       SMC,        NONE,       NAND,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO144,   0x224, NAND,     GPIO,       SMC_INT,    SMC,        NAND,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO145,   0x228, SMC,      GPIO,       NONE,       NONE,       SMC,        NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO146,   0x22C, SMC,      GPIO,       NONE,       NONE,       SMC,        NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO147,   0x230, NAND,     GPIO,       NONE,       NONE,       NAND,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO148,   0x234, NAND,     GPIO,       NONE,       NONE,       NAND,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO149,   0x238, NAND,     GPIO,       NONE,       NONE,       NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO150,   0x23C, NAND,     GPIO,       NONE,       NONE,       NAND,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO151,   0x240, SMC,      GPIO,       MMC3,       NONE,       NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO152,   0x248, SMC,      GPIO,       NONE,       NONE,       SMC,        NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO153,   0x24C, SMC,      GPIO,       NONE,       NONE,       SMC,        NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO154,   0x254, SMC_INT,  GPIO,       SMC,        NONE,       NAND,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO155,   0x258, EXT_DMA,  GPIO,       SMC,        NONE,       EXT_DMA,    NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO156,   0x14C, PRI_JTAG, GPIO,       PWM,        NONE,       NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO157,   0x150, PRI_JTAG, GPIO,       PWM,        NONE,       NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO158,   0x154, PRI_JTAG, GPIO,       PWM,        NONE,       NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO159,   0x158, PRI_JTAG, GPIO,       PWM,        NONE,       NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO160,   0x250, NAND,     GPIO,       SMC,        NONE,       NAND,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO161,   0x210, NAND,     GPIO,       NONE,       NONE,       NAND,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO162,   0x20C, NAND,     GPIO,       MMC3,       NONE,       NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO163,   0x208, NAND,     GPIO,       MMC3,       NONE,       NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO164,   0x204, NAND,     GPIO,       MMC3,       NONE,       NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO165,   0x1EC, NAND,     GPIO,       MMC3,       NONE,       NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO166,   0x1E8, NAND,     GPIO,       MMC3,       NONE,       NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO167,   0x1E4, NAND,     GPIO,       MMC3,       NONE,       NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(GPIO168,   0x1E0, NAND,     GPIO,       MMC3,       NONE,       NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(TWSI4_SCL, 0x2BC, TWSI4,    LCD,        NONE,       NONE,       NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(TWSI4_SDA, 0x2C0, TWSI4,    LCD,        NONE,       NONE,       NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(G_CLKREQ,  0x160, G_CLKREQ, ONE_WIRE,   NONE,       NONE,       NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(VCXO_REQ,  0x168, VCXO_REQ, ONE_WIRE,   PLL,        NONE,       NONE,       NONE,     NONE,     NONE),
-	MFPR_MMP2(VCXO_OUT,  0x16C, VCXO_OUT, 32K_CLKOUT, NONE,       NONE,       NONE,       NONE,     NONE,     NONE),
-};
-
-static const unsigned mmp2_uart1_pin1[] = {GPIO29, GPIO30, GPIO31, GPIO32};
-static const unsigned mmp2_uart1_pin2[] = {GPIO45, GPIO46};
-static const unsigned mmp2_uart1_pin3[] = {GPIO140, GPIO141};
-static const unsigned mmp2_uart2_pin1[] = {GPIO37, GPIO38, GPIO39, GPIO40};
-static const unsigned mmp2_uart2_pin2[] = {GPIO43, GPIO44, GPIO45, GPIO46};
-static const unsigned mmp2_uart2_pin3[] = {GPIO47, GPIO48, GPIO49, GPIO50};
-static const unsigned mmp2_uart2_pin4[] = {GPIO74, GPIO75, GPIO76, GPIO77};
-static const unsigned mmp2_uart2_pin5[] = {GPIO55, GPIO56};
-static const unsigned mmp2_uart2_pin6[] = {GPIO140, GPIO141};
-static const unsigned mmp2_uart3_pin1[] = {GPIO37, GPIO38, GPIO39, GPIO40};
-static const unsigned mmp2_uart3_pin2[] = {GPIO43, GPIO44, GPIO45, GPIO46};
-static const unsigned mmp2_uart3_pin3[] = {GPIO51, GPIO52, GPIO53, GPIO54};
-static const unsigned mmp2_uart3_pin4[] = {GPIO59, GPIO60, GPIO61, GPIO62};
-static const unsigned mmp2_uart3_pin5[] = {GPIO115, GPIO116, GPIO117, GPIO118};
-static const unsigned mmp2_uart3_pin6[] = {GPIO51, GPIO52};
-static const unsigned mmp2_uart4_pin1[] = {GPIO43, GPIO44, GPIO45, GPIO46};
-static const unsigned mmp2_uart4_pin2[] = {GPIO63, GPIO64, GPIO65, GPIO66};
-static const unsigned mmp2_uart4_pin3[] = {GPIO74, GPIO75, GPIO76, GPIO77};
-static const unsigned mmp2_uart4_pin4[] = {GPIO115, GPIO116, GPIO117, GPIO118};
-static const unsigned mmp2_uart4_pin5[] = {GPIO59, GPIO60};
-static const unsigned mmp2_kpdk_pin1[] = {GPIO16, GPIO17, GPIO18, GPIO19};
-static const unsigned mmp2_kpdk_pin2[] = {GPIO16, GPIO17};
-static const unsigned mmp2_twsi2_pin1[] = {GPIO37, GPIO38};
-static const unsigned mmp2_twsi2_pin2[] = {GPIO39, GPIO40};
-static const unsigned mmp2_twsi2_pin3[] = {GPIO43, GPIO44};
-static const unsigned mmp2_twsi2_pin4[] = {GPIO53, GPIO54};
-static const unsigned mmp2_twsi2_pin5[] = {GPIO55, GPIO56};
-static const unsigned mmp2_twsi3_pin1[] = {GPIO71, GPIO72};
-static const unsigned mmp2_twsi3_pin2[] = {GPIO95, GPIO96};
-static const unsigned mmp2_twsi4_pin1[] = {TWSI4_SCL, TWSI4_SDA};
-static const unsigned mmp2_twsi5_pin1[] = {GPIO41, GPIO42};
-static const unsigned mmp2_twsi5_pin2[] = {GPIO84, GPIO85};
-static const unsigned mmp2_twsi5_pin3[] = {GPIO99, GPIO100};
-static const unsigned mmp2_twsi6_pin1[] = {GPIO47, GPIO48};
-static const unsigned mmp2_twsi6_pin2[] = {GPIO86, GPIO87};
-static const unsigned mmp2_twsi6_pin3[] = {GPIO97, GPIO98};
-static const unsigned mmp2_ccic1_pin1[] = {GPIO12, GPIO13, GPIO14, GPIO15,
-	GPIO16, GPIO17, GPIO18, GPIO19, GPIO20, GPIO21, GPIO22, GPIO23};
-static const unsigned mmp2_ccic1_pin2[] = {GPIO59, GPIO60, GPIO61, GPIO62,
-	GPIO63, GPIO64, GPIO65, GPIO66, GPIO67, GPIO68, GPIO69, GPIO70};
-static const unsigned mmp2_ccic2_pin1[] = {GPIO59, GPIO60, GPIO61, GPIO62,
-	GPIO63, GPIO64, GPIO65, GPIO66, GPIO67, GPIO68, GPIO69, GPIO70};
-static const unsigned mmp2_ccic2_pin2[] = {GPIO82, GPIO83, GPIO86, GPIO87,
-	GPIO88, GPIO89, GPIO90, GPIO91, GPIO92, GPIO93, GPIO94, GPIO95};
-static const unsigned mmp2_ulpi_pin1[] = {GPIO59, GPIO60, GPIO61, GPIO62,
-	GPIO63, GPIO64, GPIO65, GPIO66, GPIO67, GPIO68, GPIO69, GPIO70};
-static const unsigned mmp2_ro_pin1[] = {GPIO16, GPIO17};
-static const unsigned mmp2_ro_pin2[] = {GPIO18, GPIO19};
-static const unsigned mmp2_ro_pin3[] = {GPIO51, GPIO52};
-static const unsigned mmp2_ro_pin4[] = {GPIO55, GPIO56};
-static const unsigned mmp2_i2s_pin1[] = {GPIO24, GPIO25, GPIO26, GPIO27,
-	GPIO28};
-static const unsigned mmp2_i2s_pin2[] = {GPIO33, GPIO34, GPIO35, GPIO36};
-static const unsigned mmp2_ssp1_pin1[] = {GPIO37, GPIO38, GPIO39, GPIO40};
-static const unsigned mmp2_ssp1_pin2[] = {GPIO43, GPIO44, GPIO45, GPIO46};
-static const unsigned mmp2_ssp1_pin3[] = {GPIO115, GPIO116, GPIO117, GPIO118};
-static const unsigned mmp2_ssp2_pin1[] = {GPIO47, GPIO48, GPIO49, GPIO50};
-static const unsigned mmp2_ssp3_pin1[] = {GPIO119, GPIO120, GPIO121, GPIO122};
-static const unsigned mmp2_ssp3_pin2[] = {GPIO132, GPIO133, GPIO133, GPIO136};
-static const unsigned mmp2_sspa2_pin1[] = {GPIO25, GPIO26, GPIO27, GPIO28};
-static const unsigned mmp2_sspa2_pin2[] = {GPIO33, GPIO34, GPIO35, GPIO36};
-static const unsigned mmp2_mmc1_pin1[] = {GPIO131, GPIO132, GPIO133, GPIO134,
-	GPIO136, GPIO139, GPIO140, GPIO141};
-static const unsigned mmp2_mmc2_pin1[] = {GPIO37, GPIO38, GPIO39, GPIO40,
-	GPIO41, GPIO42};
-static const unsigned mmp2_mmc3_pin1[] = {GPIO111, GPIO112, GPIO151, GPIO162,
-	GPIO163, GPIO164, GPIO165, GPIO166, GPIO167, GPIO168};
-
-static struct pxa3xx_pin_group mmp2_grps[] = {
-	GRP_MMP2("uart1 4p1", UART1, mmp2_uart1_pin1),
-	GRP_MMP2("uart1 2p2", UART1, mmp2_uart1_pin2),
-	GRP_MMP2("uart1 2p3", UART1, mmp2_uart1_pin3),
-	GRP_MMP2("uart2 4p1", UART2, mmp2_uart2_pin1),
-	GRP_MMP2("uart2 4p2", UART2, mmp2_uart2_pin2),
-	GRP_MMP2("uart2 4p3", UART2, mmp2_uart2_pin3),
-	GRP_MMP2("uart2 4p4", UART2, mmp2_uart2_pin4),
-	GRP_MMP2("uart2 2p5", UART2, mmp2_uart2_pin5),
-	GRP_MMP2("uart2 2p6", UART2, mmp2_uart2_pin6),
-	GRP_MMP2("uart3 4p1", UART3, mmp2_uart3_pin1),
-	GRP_MMP2("uart3 4p2", UART3, mmp2_uart3_pin2),
-	GRP_MMP2("uart3 4p3", UART3, mmp2_uart3_pin3),
-	GRP_MMP2("uart3 4p4", UART3, mmp2_uart3_pin4),
-	GRP_MMP2("uart3 4p5", UART3, mmp2_uart3_pin5),
-	GRP_MMP2("uart3 2p6", UART3, mmp2_uart3_pin6),
-	GRP_MMP2("uart4 4p1", UART4, mmp2_uart4_pin1),
-	GRP_MMP2("uart4 4p2", UART4, mmp2_uart4_pin2),
-	GRP_MMP2("uart4 4p3", UART4, mmp2_uart4_pin3),
-	GRP_MMP2("uart4 4p4", UART4, mmp2_uart4_pin4),
-	GRP_MMP2("uart4 2p5", UART4, mmp2_uart4_pin5),
-	GRP_MMP2("kpdk 4p1", KP_DK, mmp2_kpdk_pin1),
-	GRP_MMP2("kpdk 4p2", KP_DK, mmp2_kpdk_pin2),
-	GRP_MMP2("twsi2-1", TWSI2, mmp2_twsi2_pin1),
-	GRP_MMP2("twsi2-2", TWSI2, mmp2_twsi2_pin2),
-	GRP_MMP2("twsi2-3", TWSI2, mmp2_twsi2_pin3),
-	GRP_MMP2("twsi2-4", TWSI2, mmp2_twsi2_pin4),
-	GRP_MMP2("twsi2-5", TWSI2, mmp2_twsi2_pin5),
-	GRP_MMP2("twsi3-1", TWSI3, mmp2_twsi3_pin1),
-	GRP_MMP2("twsi3-2", TWSI3, mmp2_twsi3_pin2),
-	GRP_MMP2("twsi4", TWSI4, mmp2_twsi4_pin1),
-	GRP_MMP2("twsi5-1", TWSI5, mmp2_twsi5_pin1),
-	GRP_MMP2("twsi5-2", TWSI5, mmp2_twsi5_pin2),
-	GRP_MMP2("twsi5-3", TWSI5, mmp2_twsi5_pin3),
-	GRP_MMP2("twsi6-1", TWSI6, mmp2_twsi6_pin1),
-	GRP_MMP2("twsi6-2", TWSI6, mmp2_twsi6_pin2),
-	GRP_MMP2("twsi6-3", TWSI6, mmp2_twsi6_pin3),
-	GRP_MMP2("ccic1-1", CCIC1, mmp2_ccic1_pin1),
-	GRP_MMP2("ccic1-2", CCIC1, mmp2_ccic1_pin2),
-	GRP_MMP2("ccic2-1", CCIC2, mmp2_ccic2_pin1),
-	GRP_MMP2("ccic2-1", CCIC2, mmp2_ccic2_pin2),
-	GRP_MMP2("ulpi", ULPI, mmp2_ulpi_pin1),
-	GRP_MMP2("ro-1", ROT, mmp2_ro_pin1),
-	GRP_MMP2("ro-2", ROT, mmp2_ro_pin2),
-	GRP_MMP2("ro-3", ROT, mmp2_ro_pin3),
-	GRP_MMP2("ro-4", ROT, mmp2_ro_pin4),
-	GRP_MMP2("i2s 5p1", I2S, mmp2_i2s_pin1),
-	GRP_MMP2("i2s 4p2", I2S, mmp2_i2s_pin2),
-	GRP_MMP2("ssp1 4p1", SSP1, mmp2_ssp1_pin1),
-	GRP_MMP2("ssp1 4p2", SSP1, mmp2_ssp1_pin2),
-	GRP_MMP2("ssp1 4p3", SSP1, mmp2_ssp1_pin3),
-	GRP_MMP2("ssp2 4p1", SSP2, mmp2_ssp2_pin1),
-	GRP_MMP2("ssp3 4p1", SSP3, mmp2_ssp3_pin1),
-	GRP_MMP2("ssp3 4p2", SSP3, mmp2_ssp3_pin2),
-	GRP_MMP2("sspa2 4p1", SSPA2, mmp2_sspa2_pin1),
-	GRP_MMP2("sspa2 4p2", SSPA2, mmp2_sspa2_pin2),
-	GRP_MMP2("mmc1 8p1", MMC1, mmp2_mmc1_pin1),
-	GRP_MMP2("mmc2 6p1", MMC2, mmp2_mmc2_pin1),
-	GRP_MMP2("mmc3 10p1", MMC3, mmp2_mmc3_pin1),
-};
-
-static const char * const mmp2_uart1_grps[] = {"uart1 4p1", "uart1 2p2",
-	"uart1 2p3"};
-static const char * const mmp2_uart2_grps[] = {"uart2 4p1", "uart2 4p2",
-	"uart2 4p3", "uart2 4p4", "uart2 4p5", "uart2 4p6"};
-static const char * const mmp2_uart3_grps[] = {"uart3 4p1", "uart3 4p2",
-	"uart3 4p3", "uart3 4p4", "uart3 4p5", "uart3 2p6"};
-static const char * const mmp2_uart4_grps[] = {"uart4 4p1", "uart4 4p2",
-	"uart4 4p3", "uart4 4p4", "uart4 2p5"};
-static const char * const mmp2_kpdk_grps[] = {"kpdk 4p1", "kpdk 4p2"};
-static const char * const mmp2_twsi2_grps[] = {"twsi2-1", "twsi2-2",
-	"twsi2-3", "twsi2-4", "twsi2-5"};
-static const char * const mmp2_twsi3_grps[] = {"twsi3-1", "twsi3-2"};
-static const char * const mmp2_twsi4_grps[] = {"twsi4"};
-static const char * const mmp2_twsi5_grps[] = {"twsi5-1", "twsi5-2",
-	"twsi5-3"};
-static const char * const mmp2_twsi6_grps[] = {"twsi6-1", "twsi6-2",
-	"twsi6-3"};
-static const char * const mmp2_ccic1_grps[] = {"ccic1-1", "ccic1-2"};
-static const char * const mmp2_ccic2_grps[] = {"ccic2-1", "ccic2-2"};
-static const char * const mmp2_ulpi_grps[] = {"ulpi"};
-static const char * const mmp2_ro_grps[] = {"ro-1", "ro-2", "ro-3", "ro-4"};
-static const char * const mmp2_i2s_grps[] = {"i2s 5p1", "i2s 4p2"};
-static const char * const mmp2_ssp1_grps[] = {"ssp1 4p1", "ssp1 4p2",
-	"ssp1 4p3"};
-static const char * const mmp2_ssp2_grps[] = {"ssp2 4p1"};
-static const char * const mmp2_ssp3_grps[] = {"ssp3 4p1", "ssp3 4p2"};
-static const char * const mmp2_sspa2_grps[] = {"sspa2 4p1", "sspa2 4p2"};
-static const char * const mmp2_mmc1_grps[] = {"mmc1 8p1"};
-static const char * const mmp2_mmc2_grps[] = {"mmc2 6p1"};
-static const char * const mmp2_mmc3_grps[] = {"mmc3 10p1"};
-
-static struct pxa3xx_pmx_func mmp2_funcs[] = {
-	{"uart1",	ARRAY_AND_SIZE(mmp2_uart1_grps)},
-	{"uart2",	ARRAY_AND_SIZE(mmp2_uart2_grps)},
-	{"uart3",	ARRAY_AND_SIZE(mmp2_uart3_grps)},
-	{"uart4",	ARRAY_AND_SIZE(mmp2_uart4_grps)},
-	{"kpdk",	ARRAY_AND_SIZE(mmp2_kpdk_grps)},
-	{"twsi2",	ARRAY_AND_SIZE(mmp2_twsi2_grps)},
-	{"twsi3",	ARRAY_AND_SIZE(mmp2_twsi3_grps)},
-	{"twsi4",	ARRAY_AND_SIZE(mmp2_twsi4_grps)},
-	{"twsi5",	ARRAY_AND_SIZE(mmp2_twsi5_grps)},
-	{"twsi6",	ARRAY_AND_SIZE(mmp2_twsi6_grps)},
-	{"ccic1",	ARRAY_AND_SIZE(mmp2_ccic1_grps)},
-	{"ccic2",	ARRAY_AND_SIZE(mmp2_ccic2_grps)},
-	{"ulpi",	ARRAY_AND_SIZE(mmp2_ulpi_grps)},
-	{"ro",		ARRAY_AND_SIZE(mmp2_ro_grps)},
-	{"i2s",		ARRAY_AND_SIZE(mmp2_i2s_grps)},
-	{"ssp1",	ARRAY_AND_SIZE(mmp2_ssp1_grps)},
-	{"ssp2",	ARRAY_AND_SIZE(mmp2_ssp2_grps)},
-	{"ssp3",	ARRAY_AND_SIZE(mmp2_ssp3_grps)},
-	{"sspa2",	ARRAY_AND_SIZE(mmp2_sspa2_grps)},
-	{"mmc1",	ARRAY_AND_SIZE(mmp2_mmc1_grps)},
-	{"mmc2",	ARRAY_AND_SIZE(mmp2_mmc2_grps)},
-	{"mmc3",	ARRAY_AND_SIZE(mmp2_mmc3_grps)},
-};
-
-static struct pinctrl_desc mmp2_pctrl_desc = {
-	.name		= "mmp2-pinctrl",
-	.owner		= THIS_MODULE,
-};
-
-static struct pxa3xx_pinmux_info mmp2_info = {
-	.mfp		= mmp2_mfp,
-	.num_mfp	= ARRAY_SIZE(mmp2_mfp),
-	.grps		= mmp2_grps,
-	.num_grps	= ARRAY_SIZE(mmp2_grps),
-	.funcs		= mmp2_funcs,
-	.num_funcs	= ARRAY_SIZE(mmp2_funcs),
-	.num_gpio	= 169,
-	.desc		= &mmp2_pctrl_desc,
-	.pads		= mmp2_pads,
-	.num_pads	= ARRAY_SIZE(mmp2_pads),
-
-	.cputype	= PINCTRL_MMP2,
-	.ds_mask	= MMP2_DS_MASK,
-	.ds_shift	= MMP2_DS_SHIFT,
-};
-
-static int mmp2_pinmux_probe(struct platform_device *pdev)
-{
-	return pxa3xx_pinctrl_register(pdev, &mmp2_info);
-}
-
-static int mmp2_pinmux_remove(struct platform_device *pdev)
-{
-	return pxa3xx_pinctrl_unregister(pdev);
-}
-
-static struct platform_driver mmp2_pinmux_driver = {
-	.driver = {
-		.name	= "mmp2-pinmux",
-		.owner	= THIS_MODULE,
-	},
-	.probe	= mmp2_pinmux_probe,
-	.remove	= mmp2_pinmux_remove,
-};
-
-static int __init mmp2_pinmux_init(void)
-{
-	return platform_driver_register(&mmp2_pinmux_driver);
-}
-core_initcall_sync(mmp2_pinmux_init);
-
-static void __exit mmp2_pinmux_exit(void)
-{
-	platform_driver_unregister(&mmp2_pinmux_driver);
-}
-module_exit(mmp2_pinmux_exit);
-
-MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
-MODULE_DESCRIPTION("PXA3xx pin control driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/pinctrl-mxs.c b/drivers/pinctrl/pinctrl-mxs.c
index 23af9f1..b45c4eb 100644
--- a/drivers/pinctrl/pinctrl-mxs.c
+++ b/drivers/pinctrl/pinctrl-mxs.c
@@ -158,7 +158,7 @@ static void mxs_dt_free_map(struct pinctrl_dev *pctldev,
 	kfree(map);
 }
 
-static struct pinctrl_ops mxs_pinctrl_ops = {
+static const struct pinctrl_ops mxs_pinctrl_ops = {
 	.get_groups_count = mxs_get_groups_count,
 	.get_group_name = mxs_get_group_name,
 	.get_group_pins = mxs_get_group_pins,
@@ -219,7 +219,7 @@ static int mxs_pinctrl_enable(struct pinctrl_dev *pctldev, unsigned selector,
 	return 0;
 }
 
-static struct pinmux_ops mxs_pinmux_ops = {
+static const struct pinmux_ops mxs_pinmux_ops = {
 	.get_functions_count = mxs_pinctrl_get_funcs_count,
 	.get_function_name = mxs_pinctrl_get_func_name,
 	.get_function_groups = mxs_pinctrl_get_func_groups,
@@ -319,7 +319,7 @@ static void mxs_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
 		seq_printf(s, "0x%lx", config);
 }
 
-static struct pinconf_ops mxs_pinconf_ops = {
+static const struct pinconf_ops mxs_pinconf_ops = {
 	.pin_config_get = mxs_pinconf_get,
 	.pin_config_set = mxs_pinconf_set,
 	.pin_config_group_get = mxs_pinconf_group_get,
diff --git a/drivers/pinctrl/pinctrl-nomadik-db8500.c b/drivers/pinctrl/pinctrl-nomadik-db8500.c
index 30b4da9..c748407 100644
--- a/drivers/pinctrl/pinctrl-nomadik-db8500.c
+++ b/drivers/pinctrl/pinctrl-nomadik-db8500.c
@@ -466,7 +466,7 @@ static const unsigned mc1_a_1_pins[] = { DB8500_PIN_AH16, DB8500_PIN_AG15,
 	DB8500_PIN_AJ15, DB8500_PIN_AG14, DB8500_PIN_AF13, DB8500_PIN_AG13,
 	DB8500_PIN_AH15 };
 static const unsigned mc1_a_2_pins[] = { DB8500_PIN_AH16, DB8500_PIN_AJ15,
-	DB8500_PIN_AG14, DB8500_PIN_AF13, DB8500_PIN_AG13,DB8500_PIN_AH15 };
+	DB8500_PIN_AG14, DB8500_PIN_AF13, DB8500_PIN_AG13, DB8500_PIN_AH15 };
 static const unsigned mc1dir_a_1_pins[] = { DB8500_PIN_AH13, DB8500_PIN_AG12,
 	DB8500_PIN_AH12, DB8500_PIN_AH11 };
 static const unsigned hsir_a_1_pins[] = { DB8500_PIN_AG10, DB8500_PIN_AH10,
@@ -663,7 +663,7 @@ static const unsigned hwobs_oc4_1_pins[] = { DB8500_PIN_D17, DB8500_PIN_D16,
 	DB8500_PIN_D21, DB8500_PIN_D20,	DB8500_PIN_C20, DB8500_PIN_B21,
 	DB8500_PIN_C21, DB8500_PIN_A22, DB8500_PIN_B24, DB8500_PIN_C22 };
 
-#define DB8500_PIN_GROUP(a,b) { .name = #a, .pins = a##_pins,		\
+#define DB8500_PIN_GROUP(a, b) { .name = #a, .pins = a##_pins,		\
 			.npins = ARRAY_SIZE(a##_pins), .altsetting = b }
 
 static const struct nmk_pingroup nmk_db8500_groups[] = {
diff --git a/drivers/pinctrl/pinctrl-nomadik-stn8815.c b/drivers/pinctrl/pinctrl-nomadik-stn8815.c
index 924a339..ed39dca 100644
--- a/drivers/pinctrl/pinctrl-nomadik-stn8815.c
+++ b/drivers/pinctrl/pinctrl-nomadik-stn8815.c
@@ -299,7 +299,7 @@ static const unsigned i2c0_a_1_pins[] = { STN8815_PIN_D3, STN8815_PIN_D2 };
 static const unsigned u1_b_1_pins[] = { STN8815_PIN_B16, STN8815_PIN_A16 };
 static const unsigned i2cusb_b_1_pins[] = { STN8815_PIN_C21, STN8815_PIN_C20 };
 
-#define STN8815_PIN_GROUP(a,b) { .name = #a, .pins = a##_pins,		\
+#define STN8815_PIN_GROUP(a, b) { .name = #a, .pins = a##_pins,		\
 			.npins = ARRAY_SIZE(a##_pins), .altsetting = b }
 
 static const struct nmk_pingroup nmk_stn8815_groups[] = {
diff --git a/drivers/pinctrl/pinctrl-nomadik.c b/drivers/pinctrl/pinctrl-nomadik.c
index 36d2029..3428175 100644
--- a/drivers/pinctrl/pinctrl-nomadik.c
+++ b/drivers/pinctrl/pinctrl-nomadik.c
@@ -23,6 +23,7 @@
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/irqdomain.h>
+#include <linux/irqchip/chained_irq.h>
 #include <linux/slab.h>
 #include <linux/of_device.h>
 #include <linux/of_address.h>
@@ -33,7 +34,6 @@
 /* Since we request GPIOs from ourself */
 #include <linux/pinctrl/consumer.h>
 #include <linux/platform_data/pinctrl-nomadik.h>
-#include <asm/mach/irq.h>
 #include "pinctrl-nomadik.h"
 #include "core.h"
 
@@ -1565,8 +1565,8 @@ static int nmk_dt_add_map_configs(struct pinctrl_map **map,
 	return 0;
 }
 
-#define NMK_CONFIG_PIN(x,y) { .property = x, .config = y, }
-#define NMK_CONFIG_PIN_ARRAY(x,y) { .property = x, .choice = y, \
+#define NMK_CONFIG_PIN(x, y) { .property = x, .config = y, }
+#define NMK_CONFIG_PIN_ARRAY(x, y) { .property = x, .choice = y, \
 	.size = ARRAY_SIZE(y), }
 
 static const unsigned long nmk_pin_input_modes[] = {
@@ -1764,7 +1764,7 @@ int nmk_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
 	return 0;
 }
 
-static struct pinctrl_ops nmk_pinctrl_ops = {
+static const struct pinctrl_ops nmk_pinctrl_ops = {
 	.get_groups_count = nmk_get_groups_cnt,
 	.get_group_name = nmk_get_group_name,
 	.get_group_pins = nmk_get_group_pins,
@@ -1975,7 +1975,7 @@ static void nmk_gpio_disable_free(struct pinctrl_dev *pctldev,
 	/* Set the pin to some default state, GPIO is usually default */
 }
 
-static struct pinmux_ops nmk_pinmux_ops = {
+static const struct pinmux_ops nmk_pinmux_ops = {
 	.get_functions_count = nmk_pmx_get_funcs_cnt,
 	.get_function_name = nmk_pmx_get_func_name,
 	.get_function_groups = nmk_pmx_get_func_groups,
@@ -2068,7 +2068,7 @@ static int nmk_pin_config_set(struct pinctrl_dev *pctldev, unsigned pin,
 		pin, cfg, pullnames[pull], slpmnames[slpm],
 		output ? "output " : "input",
 		output ? (val ? "high" : "low") : "",
-		lowemi ? "on" : "off" );
+		lowemi ? "on" : "off");
 
 	clk_enable(nmk_chip->clk);
 	bit = pin % NMK_GPIO_PER_CHIP;
@@ -2089,7 +2089,7 @@ static int nmk_pin_config_set(struct pinctrl_dev *pctldev, unsigned pin,
 	return 0;
 }
 
-static struct pinconf_ops nmk_pinconf_ops = {
+static const struct pinconf_ops nmk_pinconf_ops = {
 	.pin_config_get = nmk_pin_config_get,
 	.pin_config_set = nmk_pin_config_set,
 };
@@ -2111,6 +2111,10 @@ static const struct of_device_id nmk_pinctrl_match[] = {
 		.compatible = "stericsson,nmk-pinctrl",
 		.data = (void *)PINCTRL_NMK_DB8500,
 	},
+	{
+		.compatible = "stericsson,nmk-pinctrl-db8540",
+		.data = (void *)PINCTRL_NMK_DB8540,
+	},
 	{},
 };
 
diff --git a/drivers/pinctrl/pinctrl-pxa168.c b/drivers/pinctrl/pinctrl-pxa168.c
deleted file mode 100644
index d9cd2b4..0000000
--- a/drivers/pinctrl/pinctrl-pxa168.c
+++ /dev/null
@@ -1,651 +0,0 @@
-/*
- *  linux/drivers/pinctrl/pinmux-pxa168.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
- *  publishhed by the Free Software Foundation.
- *
- *  Copyright (C) 2011, Marvell Technology Group Ltd.
- *
- *  Author: Haojian Zhuang <haojian.zhuang@marvell.com>
- *
- */
-
-#include <linux/device.h>
-#include <linux/module.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include "pinctrl-pxa3xx.h"
-
-#define PXA168_DS_MASK		0x1800
-#define PXA168_DS_SHIFT		11
-#define PXA168_SLEEP_MASK	0x38
-#define PXA168_SLEEP_SELECT	(1 << 9)
-#define PXA168_SLEEP_DATA	(1 << 8)
-#define PXA168_SLEEP_DIR	(1 << 7)
-
-#define MFPR_168(a, r, f0, f1, f2, f3, f4, f5, f6, f7)		\
-	{							\
-		.name = #a,					\
-		.pin = a,					\
-		.mfpr = r,					\
-		.func = {					\
-			PXA168_MUX_##f0,			\
-			PXA168_MUX_##f1,			\
-			PXA168_MUX_##f2,			\
-			PXA168_MUX_##f3,			\
-			PXA168_MUX_##f4,			\
-			PXA168_MUX_##f5,			\
-			PXA168_MUX_##f6,			\
-			PXA168_MUX_##f7,			\
-		},						\
-	}
-
-#define GRP_168(a, m, p)		\
-	{ .name = a, .mux = PXA168_MUX_##m, .pins = p, .npins = ARRAY_SIZE(p), }
-
-/* 131 pins */
-enum pxa168_pin_list {
-	/* 0~122: GPIO0~GPIO122 */
-	PWR_SCL = 123,
-	PWR_SDA,
-	TDI,
-	TMS,
-	TCK,
-	TDO,
-	TRST,
-	WAKEUP = 130,
-};
-
-enum pxa168_mux {
-	/* PXA3xx_MUX_GPIO = 0 (predefined in pinctrl-pxa3xx.h) */
-	PXA168_MUX_GPIO = 0,
-	PXA168_MUX_DFIO,
-	PXA168_MUX_NAND,
-	PXA168_MUX_SMC,
-	PXA168_MUX_SMC_CS0,
-	PXA168_MUX_SMC_CS1,
-	PXA168_MUX_SMC_INT,
-	PXA168_MUX_SMC_RDY,
-	PXA168_MUX_MMC1,
-	PXA168_MUX_MMC2,
-	PXA168_MUX_MMC2_CMD,
-	PXA168_MUX_MMC2_CLK,
-	PXA168_MUX_MMC3,
-	PXA168_MUX_MMC3_CMD,
-	PXA168_MUX_MMC3_CLK,
-	PXA168_MUX_MMC4,
-	PXA168_MUX_MSP,
-	PXA168_MUX_MSP_DAT3,
-	PXA168_MUX_MSP_INS,
-	PXA168_MUX_I2C,
-	PXA168_MUX_PWRI2C,
-	PXA168_MUX_AC97,
-	PXA168_MUX_AC97_SYSCLK,
-	PXA168_MUX_PWM,
-	PXA168_MUX_PWM1,
-	PXA168_MUX_XD,
-	PXA168_MUX_XP,
-	PXA168_MUX_LCD,
-	PXA168_MUX_CCIC,
-	PXA168_MUX_CF,
-	PXA168_MUX_CF_RDY,
-	PXA168_MUX_CF_nINPACK,
-	PXA168_MUX_CF_nWAIT,
-	PXA168_MUX_KP_MKOUT,
-	PXA168_MUX_KP_MKIN,
-	PXA168_MUX_KP_DK,
-	PXA168_MUX_ETH,
-	PXA168_MUX_ETH_TX,
-	PXA168_MUX_ETH_RX,
-	PXA168_MUX_ONE_WIRE,
-	PXA168_MUX_UART1,
-	PXA168_MUX_UART1_TX,
-	PXA168_MUX_UART1_CTS,
-	PXA168_MUX_UART1_nRI,
-	PXA168_MUX_UART1_DTR,
-	PXA168_MUX_UART2,
-	PXA168_MUX_UART2_TX,
-	PXA168_MUX_UART3,
-	PXA168_MUX_UART3_TX,
-	PXA168_MUX_UART3_CTS,
-	PXA168_MUX_SSP1,
-	PXA168_MUX_SSP1_TX,
-	PXA168_MUX_SSP2,
-	PXA168_MUX_SSP2_TX,
-	PXA168_MUX_SSP3,
-	PXA168_MUX_SSP3_TX,
-	PXA168_MUX_SSP4,
-	PXA168_MUX_SSP4_TX,
-	PXA168_MUX_SSP5,
-	PXA168_MUX_SSP5_TX,
-	PXA168_MUX_USB,
-	PXA168_MUX_JTAG,
-	PXA168_MUX_RESET,
-	PXA168_MUX_WAKEUP,
-	PXA168_MUX_EXT_32K_IN,
-	PXA168_MUX_NONE = 0xffff,
-};
-
-static struct pinctrl_pin_desc pxa168_pads[] = {
-	PINCTRL_PIN(GPIO0, "GPIO0"),
-	PINCTRL_PIN(GPIO1, "GPIO1"),
-	PINCTRL_PIN(GPIO2, "GPIO2"),
-	PINCTRL_PIN(GPIO3, "GPIO3"),
-	PINCTRL_PIN(GPIO4, "GPIO4"),
-	PINCTRL_PIN(GPIO5, "GPIO5"),
-	PINCTRL_PIN(GPIO6, "GPIO6"),
-	PINCTRL_PIN(GPIO7, "GPIO7"),
-	PINCTRL_PIN(GPIO8, "GPIO8"),
-	PINCTRL_PIN(GPIO9, "GPIO9"),
-	PINCTRL_PIN(GPIO10, "GPIO10"),
-	PINCTRL_PIN(GPIO11, "GPIO11"),
-	PINCTRL_PIN(GPIO12, "GPIO12"),
-	PINCTRL_PIN(GPIO13, "GPIO13"),
-	PINCTRL_PIN(GPIO14, "GPIO14"),
-	PINCTRL_PIN(GPIO15, "GPIO15"),
-	PINCTRL_PIN(GPIO16, "GPIO16"),
-	PINCTRL_PIN(GPIO17, "GPIO17"),
-	PINCTRL_PIN(GPIO18, "GPIO18"),
-	PINCTRL_PIN(GPIO19, "GPIO19"),
-	PINCTRL_PIN(GPIO20, "GPIO20"),
-	PINCTRL_PIN(GPIO21, "GPIO21"),
-	PINCTRL_PIN(GPIO22, "GPIO22"),
-	PINCTRL_PIN(GPIO23, "GPIO23"),
-	PINCTRL_PIN(GPIO24, "GPIO24"),
-	PINCTRL_PIN(GPIO25, "GPIO25"),
-	PINCTRL_PIN(GPIO26, "GPIO26"),
-	PINCTRL_PIN(GPIO27, "GPIO27"),
-	PINCTRL_PIN(GPIO28, "GPIO28"),
-	PINCTRL_PIN(GPIO29, "GPIO29"),
-	PINCTRL_PIN(GPIO30, "GPIO30"),
-	PINCTRL_PIN(GPIO31, "GPIO31"),
-	PINCTRL_PIN(GPIO32, "GPIO32"),
-	PINCTRL_PIN(GPIO33, "GPIO33"),
-	PINCTRL_PIN(GPIO34, "GPIO34"),
-	PINCTRL_PIN(GPIO35, "GPIO35"),
-	PINCTRL_PIN(GPIO36, "GPIO36"),
-	PINCTRL_PIN(GPIO37, "GPIO37"),
-	PINCTRL_PIN(GPIO38, "GPIO38"),
-	PINCTRL_PIN(GPIO39, "GPIO39"),
-	PINCTRL_PIN(GPIO40, "GPIO40"),
-	PINCTRL_PIN(GPIO41, "GPIO41"),
-	PINCTRL_PIN(GPIO42, "GPIO42"),
-	PINCTRL_PIN(GPIO43, "GPIO43"),
-	PINCTRL_PIN(GPIO44, "GPIO44"),
-	PINCTRL_PIN(GPIO45, "GPIO45"),
-	PINCTRL_PIN(GPIO46, "GPIO46"),
-	PINCTRL_PIN(GPIO47, "GPIO47"),
-	PINCTRL_PIN(GPIO48, "GPIO48"),
-	PINCTRL_PIN(GPIO49, "GPIO49"),
-	PINCTRL_PIN(GPIO50, "GPIO50"),
-	PINCTRL_PIN(GPIO51, "GPIO51"),
-	PINCTRL_PIN(GPIO52, "GPIO52"),
-	PINCTRL_PIN(GPIO53, "GPIO53"),
-	PINCTRL_PIN(GPIO54, "GPIO54"),
-	PINCTRL_PIN(GPIO55, "GPIO55"),
-	PINCTRL_PIN(GPIO56, "GPIO56"),
-	PINCTRL_PIN(GPIO57, "GPIO57"),
-	PINCTRL_PIN(GPIO58, "GPIO58"),
-	PINCTRL_PIN(GPIO59, "GPIO59"),
-	PINCTRL_PIN(GPIO60, "GPIO60"),
-	PINCTRL_PIN(GPIO61, "GPIO61"),
-	PINCTRL_PIN(GPIO62, "GPIO62"),
-	PINCTRL_PIN(GPIO63, "GPIO63"),
-	PINCTRL_PIN(GPIO64, "GPIO64"),
-	PINCTRL_PIN(GPIO65, "GPIO65"),
-	PINCTRL_PIN(GPIO66, "GPIO66"),
-	PINCTRL_PIN(GPIO67, "GPIO67"),
-	PINCTRL_PIN(GPIO68, "GPIO68"),
-	PINCTRL_PIN(GPIO69, "GPIO69"),
-	PINCTRL_PIN(GPIO70, "GPIO70"),
-	PINCTRL_PIN(GPIO71, "GPIO71"),
-	PINCTRL_PIN(GPIO72, "GPIO72"),
-	PINCTRL_PIN(GPIO73, "GPIO73"),
-	PINCTRL_PIN(GPIO74, "GPIO74"),
-	PINCTRL_PIN(GPIO75, "GPIO75"),
-	PINCTRL_PIN(GPIO76, "GPIO76"),
-	PINCTRL_PIN(GPIO77, "GPIO77"),
-	PINCTRL_PIN(GPIO78, "GPIO78"),
-	PINCTRL_PIN(GPIO79, "GPIO79"),
-	PINCTRL_PIN(GPIO80, "GPIO80"),
-	PINCTRL_PIN(GPIO81, "GPIO81"),
-	PINCTRL_PIN(GPIO82, "GPIO82"),
-	PINCTRL_PIN(GPIO83, "GPIO83"),
-	PINCTRL_PIN(GPIO84, "GPIO84"),
-	PINCTRL_PIN(GPIO85, "GPIO85"),
-	PINCTRL_PIN(GPIO86, "GPIO86"),
-	PINCTRL_PIN(GPIO87, "GPIO87"),
-	PINCTRL_PIN(GPIO88, "GPIO88"),
-	PINCTRL_PIN(GPIO89, "GPIO89"),
-	PINCTRL_PIN(GPIO90, "GPIO90"),
-	PINCTRL_PIN(GPIO91, "GPIO91"),
-	PINCTRL_PIN(GPIO92, "GPIO92"),
-	PINCTRL_PIN(GPIO93, "GPIO93"),
-	PINCTRL_PIN(GPIO94, "GPIO94"),
-	PINCTRL_PIN(GPIO95, "GPIO95"),
-	PINCTRL_PIN(GPIO96, "GPIO96"),
-	PINCTRL_PIN(GPIO97, "GPIO97"),
-	PINCTRL_PIN(GPIO98, "GPIO98"),
-	PINCTRL_PIN(GPIO99, "GPIO99"),
-	PINCTRL_PIN(GPIO100, "GPIO100"),
-	PINCTRL_PIN(GPIO101, "GPIO101"),
-	PINCTRL_PIN(GPIO102, "GPIO102"),
-	PINCTRL_PIN(GPIO103, "GPIO103"),
-	PINCTRL_PIN(GPIO104, "GPIO104"),
-	PINCTRL_PIN(GPIO105, "GPIO105"),
-	PINCTRL_PIN(GPIO106, "GPIO106"),
-	PINCTRL_PIN(GPIO107, "GPIO107"),
-	PINCTRL_PIN(GPIO108, "GPIO108"),
-	PINCTRL_PIN(GPIO109, "GPIO109"),
-	PINCTRL_PIN(GPIO110, "GPIO110"),
-	PINCTRL_PIN(GPIO111, "GPIO111"),
-	PINCTRL_PIN(GPIO112, "GPIO112"),
-	PINCTRL_PIN(GPIO113, "GPIO113"),
-	PINCTRL_PIN(GPIO114, "GPIO114"),
-	PINCTRL_PIN(GPIO115, "GPIO115"),
-	PINCTRL_PIN(GPIO116, "GPIO116"),
-	PINCTRL_PIN(GPIO117, "GPIO117"),
-	PINCTRL_PIN(GPIO118, "GPIO118"),
-	PINCTRL_PIN(GPIO119, "GPIO119"),
-	PINCTRL_PIN(GPIO120, "GPIO120"),
-	PINCTRL_PIN(GPIO121, "GPIO121"),
-	PINCTRL_PIN(GPIO122, "GPIO122"),
-	PINCTRL_PIN(PWR_SCL, "PWR_SCL"),
-	PINCTRL_PIN(PWR_SDA, "PWR_SDA"),
-	PINCTRL_PIN(TDI, "TDI"),
-	PINCTRL_PIN(TMS, "TMS"),
-	PINCTRL_PIN(TCK, "TCK"),
-	PINCTRL_PIN(TDO, "TDO"),
-	PINCTRL_PIN(TRST, "TRST"),
-	PINCTRL_PIN(WAKEUP, "WAKEUP"),
-};
-
-struct pxa3xx_mfp_pin pxa168_mfp[] = {
-	/*       pin      offs   f0       f1           f2         f3           f4           f5        f6           f7  */
-	MFPR_168(GPIO0,   0x04C, DFIO,    NONE,        NONE,      MSP,         MMC3_CMD,    GPIO,     MMC3,        NONE),
-	MFPR_168(GPIO1,   0x050, DFIO,    NONE,        NONE,      MSP,         MMC3_CLK,    GPIO,     MMC3,        NONE),
-	MFPR_168(GPIO2,   0x054, DFIO,    NONE,        NONE,      MSP,         NONE,        GPIO,     MMC3,        NONE),
-	MFPR_168(GPIO3,   0x058, DFIO,    NONE,        NONE,      NONE,        NONE,        GPIO,     MMC3,        NONE),
-	MFPR_168(GPIO4,   0x05C, DFIO,    NONE,        NONE,      MSP_DAT3,    NONE,        GPIO,     MMC3,        NONE),
-	MFPR_168(GPIO5,   0x060, DFIO,    NONE,        NONE,      MSP,         NONE,        GPIO,     MMC3,        NONE),
-	MFPR_168(GPIO6,   0x064, DFIO,    NONE,        NONE,      MSP,         NONE,        GPIO,     MMC3,        NONE),
-	MFPR_168(GPIO7,   0x068, DFIO,    NONE,        NONE,      MSP,         NONE,        GPIO,     MMC3,        NONE),
-	MFPR_168(GPIO8,   0x06C, DFIO,    MMC2,        UART3_TX,  NONE,        MMC2_CMD,    GPIO,     MMC3_CLK,    NONE),
-	MFPR_168(GPIO9,   0x070, DFIO,    MMC2,        UART3,     NONE,        MMC2_CLK,    GPIO,     MMC3_CMD,    NONE),
-	MFPR_168(GPIO10,  0x074, DFIO,    MMC2,        UART3,     NONE,        NONE,        GPIO,     MSP_DAT3,    NONE),
-	MFPR_168(GPIO11,  0x078, DFIO,    MMC2,        UART3,     NONE,        NONE,        GPIO,     MSP,         NONE),
-	MFPR_168(GPIO12,  0x07C, DFIO,    MMC2,        UART3,     NONE,        NONE,        GPIO,     MSP,         NONE),
-	MFPR_168(GPIO13,  0x080, DFIO,    MMC2,        UART3,     NONE,        NONE,        GPIO,     MSP,         NONE),
-	MFPR_168(GPIO14,  0x084, DFIO,    MMC2,        NONE,      NONE,        NONE,        GPIO,     MSP,         NONE),
-	MFPR_168(GPIO15,  0x088, DFIO,    MMC2,        NONE,      NONE,        NONE,        GPIO,     MSP,         NONE),
-	MFPR_168(GPIO16,  0x08C, GPIO,    NAND,        SMC_CS0,   SMC_CS1,     NONE,        NONE,     MMC3,        NONE),
-	MFPR_168(GPIO17,  0x090, NAND,    NONE,        NONE,      NONE,        NONE,        GPIO,     MSP,         NONE),
-	MFPR_168(GPIO18,  0x094, GPIO,    NAND,        SMC_CS1,   SMC_CS0,     NONE,        NONE,     NONE,        NONE),
-	MFPR_168(GPIO19,  0x098, SMC_CS0, NONE,        NONE,      CF,          NONE,        GPIO,     NONE,        NONE),
-	MFPR_168(GPIO20,  0x09C, GPIO,    NONE,        SMC_CS1,   CF,          CF_RDY,      NONE,     NONE,        NONE),
-	MFPR_168(GPIO21,  0x0A0, NAND,    MMC2_CLK,    NONE,      NONE,        NONE,        GPIO,     NONE,        NONE),
-	MFPR_168(GPIO22,  0x0A4, NAND,    MMC2_CMD,    NONE,      NONE,        NONE,        GPIO,     NONE,        NONE),
-	MFPR_168(GPIO23,  0x0A8, SMC,     NAND,        NONE,      CF,          NONE,        GPIO,     NONE,        NONE),
-	MFPR_168(GPIO24,  0x0AC, NAND,    NONE,        NONE,      NONE,        NONE,        GPIO,     NONE,        NONE),
-	MFPR_168(GPIO25,  0x0B0, SMC,     NAND,        NONE,      CF,          NONE,        GPIO,     NONE,        NONE),
-	MFPR_168(GPIO26,  0x0B4, GPIO,    NAND,        NONE,      NONE,        CF,          NONE,     NONE,        NONE),
-	MFPR_168(GPIO27,  0x0B8, SMC_INT, NAND,        SMC,       NONE,        SMC_RDY,     GPIO,     NONE,        NONE),
-	MFPR_168(GPIO28,  0x0BC, SMC_RDY, MMC4,        SMC,       CF_RDY,      NONE,        GPIO,     MMC2_CMD,    NONE),
-	MFPR_168(GPIO29,  0x0C0, SMC,     MMC4,        NONE,      CF,          NONE,        GPIO,     MMC2_CLK,    KP_DK),
-	MFPR_168(GPIO30,  0x0C4, SMC,     MMC4,        UART3_TX,  CF,          NONE,        GPIO,     MMC2,        KP_DK),
-	MFPR_168(GPIO31,  0x0C8, SMC,     MMC4,        UART3,     CF,          NONE,        GPIO,     MMC2,        KP_DK),
-	MFPR_168(GPIO32,  0x0CC, SMC,     MMC4,        UART3,     CF,          NONE,        GPIO,     MMC2,        KP_DK),
-	MFPR_168(GPIO33,  0x0D0, SMC,     MMC4,        UART3,     CF,          CF_nINPACK,  GPIO,     MMC2,        KP_DK),
-	MFPR_168(GPIO34,  0x0D4, GPIO,    NONE,        SMC_CS1,   CF,          CF_nWAIT,    NONE,     MMC3,        KP_DK),
-	MFPR_168(GPIO35,  0x0D8, GPIO,    NONE,        SMC,       CF_nINPACK,  NONE,        NONE,     MMC3_CMD,    KP_DK),
-	MFPR_168(GPIO36,  0x0DC, GPIO,    NONE,        SMC,       CF_nWAIT,    NONE,        NONE,     MMC3_CLK,    KP_DK),
-	MFPR_168(GPIO37,  0x000, GPIO,    MMC1,        NONE,      KP_MKOUT,    CCIC,        XP,       KP_MKIN,     KP_DK),
-	MFPR_168(GPIO38,  0x004, GPIO,    MMC1,        NONE,      KP_MKOUT,    CCIC,        XP,       KP_MKIN,     KP_DK),
-	MFPR_168(GPIO39,  0x008, GPIO,    NONE,        NONE,      KP_MKOUT,    CCIC,        XP,       KP_MKIN,     KP_DK),
-	MFPR_168(GPIO40,  0x00C, GPIO,    MMC1,        MSP,       KP_MKOUT,    CCIC,        XP,       KP_MKIN,     KP_DK),
-	MFPR_168(GPIO41,  0x010, GPIO,    MMC1,        MSP,       NONE,        CCIC,        XP,       KP_MKIN,     KP_DK),
-	MFPR_168(GPIO42,  0x014, GPIO,    I2C,         NONE,      MSP,         CCIC,        XP,       KP_MKIN,     KP_DK),
-	MFPR_168(GPIO43,  0x018, GPIO,    MMC1,        MSP,       MSP_INS,     NONE,        NONE,     KP_MKIN,     KP_DK),
-	MFPR_168(GPIO44,  0x01C, GPIO,    MMC1,        MSP_DAT3,  MSP,         CCIC,        XP,       KP_MKIN,     KP_DK),
-	MFPR_168(GPIO45,  0x020, GPIO,    NONE,        NONE,      MSP,         CCIC,        XP,       NONE,        KP_DK),
-	MFPR_168(GPIO46,  0x024, GPIO,    MMC1,        MSP_INS,   MSP,         CCIC,        NONE,     KP_MKOUT,    KP_DK),
-	MFPR_168(GPIO47,  0x028, GPIO,    NONE,        NONE,      MSP_INS,     NONE,        XP,       NONE,        KP_DK),
-	MFPR_168(GPIO48,  0x02C, GPIO,    MMC1,        NONE,      MSP_DAT3,    CCIC,        NONE,     NONE,        KP_DK),
-	MFPR_168(GPIO49,  0x030, GPIO,    MMC1,        NONE,      MSP,         NONE,        XD,       KP_MKOUT,    NONE),
-	MFPR_168(GPIO50,  0x034, GPIO,    I2C,         NONE,      MSP,         CCIC,        XD,       KP_MKOUT,    NONE),
-	MFPR_168(GPIO51,  0x038, GPIO,    MMC1,        NONE,      MSP,         NONE,        XD,       KP_MKOUT,    NONE),
-	MFPR_168(GPIO52,  0x03C, GPIO,    MMC1,        NONE,      MSP,         NONE,        XD,       KP_MKOUT,    NONE),
-	MFPR_168(GPIO53,  0x040, GPIO,    MMC1,        NONE,      NONE,        NONE,        XD,       KP_MKOUT,    NONE),
-	MFPR_168(GPIO54,  0x044, GPIO,    MMC1,        NONE,      NONE,        CCIC,        XD,       KP_MKOUT,    NONE),
-	MFPR_168(GPIO55,  0x048, GPIO,    NONE,        NONE,      MSP,         CCIC,        XD,       KP_MKOUT,    NONE),
-	MFPR_168(GPIO56,  0x0E0, GPIO,    LCD,         NONE,      NONE,        NONE,        NONE,     NONE,        NONE),
-	MFPR_168(GPIO57,  0x0E4, GPIO,    LCD,         NONE,      NONE,        NONE,        NONE,     NONE,        NONE),
-	MFPR_168(GPIO58,  0x0E8, GPIO,    LCD,         NONE,      NONE,        NONE,        NONE,     NONE,        NONE),
-	MFPR_168(GPIO59,  0x0EC, GPIO,    LCD,         NONE,      NONE,        NONE,        NONE,     NONE,        NONE),
-	MFPR_168(GPIO60,  0x0F0, GPIO,    LCD,         NONE,      NONE,        NONE,        NONE,     NONE,        NONE),
-	MFPR_168(GPIO61,  0x0F4, GPIO,    LCD,         NONE,      NONE,        NONE,        NONE,     NONE,        NONE),
-	MFPR_168(GPIO62,  0x0F8, GPIO,    LCD,         NONE,      NONE,        NONE,        NONE,     NONE,        NONE),
-	MFPR_168(GPIO63,  0x0FC, GPIO,    LCD,         NONE,      NONE,        NONE,        NONE,     NONE,        NONE),
-	MFPR_168(GPIO64,  0x100, GPIO,    LCD,         NONE,      NONE,        NONE,        NONE,     NONE,        NONE),
-	MFPR_168(GPIO65,  0x104, GPIO,    LCD,         NONE,      NONE,        NONE,        NONE,     NONE,        NONE),
-	MFPR_168(GPIO66,  0x108, GPIO,    LCD,         NONE,      NONE,        NONE,        NONE,     NONE,        NONE),
-	MFPR_168(GPIO67,  0x10C, GPIO,    LCD,         NONE,      NONE,        NONE,        NONE,     NONE,        NONE),
-	MFPR_168(GPIO68,  0x110, GPIO,    LCD,         NONE,      XD,          NONE,        NONE,     NONE,        NONE),
-	MFPR_168(GPIO69,  0x114, GPIO,    LCD,         NONE,      XD,          NONE,        NONE,     NONE,        NONE),
-	MFPR_168(GPIO70,  0x118, GPIO,    LCD,         NONE,      XD,          NONE,        NONE,     NONE,        NONE),
-	MFPR_168(GPIO71,  0x11C, GPIO,    LCD,         NONE,      XD,          NONE,        NONE,     NONE,        NONE),
-	MFPR_168(GPIO72,  0x120, GPIO,    LCD,         NONE,      XD,          NONE,        NONE,     NONE,        NONE),
-	MFPR_168(GPIO73,  0x124, GPIO,    LCD,         NONE,      XD,          NONE,        NONE,     NONE,        NONE),
-	MFPR_168(GPIO74,  0x128, GPIO,    LCD,         PWM,       XD,          NONE,        NONE,     NONE,        NONE),
-	MFPR_168(GPIO75,  0x12C, GPIO,    LCD,         PWM,       XD,          ONE_WIRE,    NONE,     NONE,        NONE),
-	MFPR_168(GPIO76,  0x130, GPIO,    LCD,         PWM,       I2C,         NONE,        NONE,     MSP_INS,     NONE),
-	MFPR_168(GPIO77,  0x134, GPIO,    LCD,         PWM1,      I2C,         ONE_WIRE,    NONE,     XD,          NONE),
-	MFPR_168(GPIO78,  0x138, GPIO,    LCD,         NONE,      NONE,        NONE,        MMC4,     NONE,        NONE),
-	MFPR_168(GPIO79,  0x13C, GPIO,    LCD,         NONE,      NONE,        ONE_WIRE,    MMC4,     NONE,        NONE),
-	MFPR_168(GPIO80,  0x140, GPIO,    LCD,         NONE,      I2C,         NONE,        MMC4,     NONE,        NONE),
-	MFPR_168(GPIO81,  0x144, GPIO,    LCD,         NONE,      I2C,         ONE_WIRE,    MMC4,     NONE,        NONE),
-	MFPR_168(GPIO82,  0x148, GPIO,    LCD,         PWM,       NONE,        NONE,        MMC4,     NONE,        NONE),
-	MFPR_168(GPIO83,  0x14C, GPIO,    LCD,         PWM,       NONE,        RESET,       MMC4,     NONE,        NONE),
-	MFPR_168(GPIO84,  0x150, GPIO,    NONE,        PWM,       ONE_WIRE,    PWM1,        NONE,     NONE,        EXT_32K_IN),
-	MFPR_168(GPIO85,  0x154, GPIO,    NONE,        PWM1,      NONE,        NONE,        NONE,     NONE,        USB),
-	MFPR_168(GPIO86,  0x158, GPIO,    MMC2,        UART2,     NONE,        JTAG,        ETH_TX,   SSP5_TX,     SSP5),
-	MFPR_168(GPIO87,  0x15C, GPIO,    MMC2,        UART2,     NONE,        JTAG,        ETH_TX,   SSP5,        SSP5_TX),
-	MFPR_168(GPIO88,  0x160, GPIO,    MMC2,        UART2,     UART2_TX,    JTAG,        ETH_TX,   ETH_RX,      SSP5),
-	MFPR_168(GPIO89,  0x164, GPIO,    MMC2,        UART2_TX,  UART2,       JTAG,        ETH_TX,   ETH_RX,      SSP5),
-	MFPR_168(GPIO90,  0x168, GPIO,    MMC2,        NONE,      SSP3,        JTAG,        ETH_TX,   ETH_RX,      NONE),
-	MFPR_168(GPIO91,  0x16C, GPIO,    MMC2,        NONE,      SSP3,        SSP4,        ETH_TX,   ETH_RX,      NONE),
-	MFPR_168(GPIO92,  0x170, GPIO,    MMC2,        NONE,      SSP3,        SSP3_TX,     ETH,      NONE,        NONE),
-	MFPR_168(GPIO93,  0x174, GPIO,    MMC2,        NONE,      SSP3_TX,     SSP3,        ETH,      NONE,        NONE),
-	MFPR_168(GPIO94,  0x178, GPIO,    MMC2_CMD,    SSP3,      AC97_SYSCLK, AC97,        ETH,      NONE,        NONE),
-	MFPR_168(GPIO95,  0x17C, GPIO,    MMC2_CLK,    NONE,      NONE,        AC97,        ETH,      NONE,        NONE),
-	MFPR_168(GPIO96,  0x180, GPIO,    PWM,         NONE,      MMC2,        NONE,        ETH_RX,   ETH_TX,      NONE),
-	MFPR_168(GPIO97,  0x184, GPIO,    PWM,         ONE_WIRE,  NONE,        NONE,        ETH_RX,   ETH_TX,      NONE),
-	MFPR_168(GPIO98,  0x188, GPIO,    PWM1,        UART3_TX,  UART3,       NONE,        ETH_RX,   ETH_TX,      NONE),
-	MFPR_168(GPIO99,  0x18C, GPIO,    ONE_WIRE,    UART3,     UART3_TX,    NONE,        ETH_RX,   ETH_TX,      NONE),
-	MFPR_168(GPIO100, 0x190, GPIO,    NONE,        UART3_CTS, UART3,       NONE,        ETH,      NONE,        NONE),
-	MFPR_168(GPIO101, 0x194, GPIO,    NONE,        UART3,     UART3_CTS,   NONE,        ETH,      NONE,        NONE),
-	MFPR_168(GPIO102, 0x198, GPIO,    I2C,         UART3,     SSP4,        NONE,        NONE,     NONE,        NONE),
-	MFPR_168(GPIO103, 0x19C, GPIO,    I2C,         UART3,     SSP4,        SSP2,        ETH,      NONE,        NONE),
-	MFPR_168(GPIO104, 0x1A0, GPIO,    PWM,         UART1,     SSP4,        SSP4_TX,     AC97,     KP_MKOUT,    NONE),
-	MFPR_168(GPIO105, 0x1A4, GPIO,    I2C,         UART1,     SSP4_TX,     SSP4,        AC97,     KP_MKOUT,    NONE),
-	MFPR_168(GPIO106, 0x1A8, GPIO,    I2C,         PWM1,      AC97_SYSCLK, MMC2,        NONE,     KP_MKOUT,    NONE),
-	MFPR_168(GPIO107, 0x1AC, GPIO,    UART1_TX,    UART1,     NONE,        SSP2,        MSP_DAT3, NONE,        KP_MKIN),
-	MFPR_168(GPIO108, 0x1B0, GPIO,    UART1,       UART1_TX,  NONE,        SSP2_TX,     MSP,      NONE,        KP_MKIN),
-	MFPR_168(GPIO109, 0x1B4, GPIO,    UART1_CTS,   UART1,     NONE,        AC97_SYSCLK, MSP,      NONE,        KP_MKIN),
-	MFPR_168(GPIO110, 0x1B8, GPIO,    UART1,       UART1_CTS, NONE,        SMC_RDY,     MSP,      NONE,        KP_MKIN),
-	MFPR_168(GPIO111, 0x1BC, GPIO,    UART1_nRI,   UART1,     SSP3,        SSP2,        MSP,      XD,          KP_MKOUT),
-	MFPR_168(GPIO112, 0x1C0, GPIO,    UART1_DTR,   UART1,     ONE_WIRE,    SSP2,        MSP,      XD,          KP_MKOUT),
-	MFPR_168(GPIO113, 0x1C4, GPIO,    NONE,        NONE,      NONE,        NONE,        NONE,     AC97_SYSCLK, NONE),
-	MFPR_168(GPIO114, 0x1C8, GPIO,    SSP1,        NONE,      NONE,        NONE,        NONE,     AC97,        NONE),
-	MFPR_168(GPIO115, 0x1CC, GPIO,    SSP1,        NONE,      NONE,        NONE,        NONE,     AC97,        NONE),
-	MFPR_168(GPIO116, 0x1D0, GPIO,    SSP1_TX,     SSP1,      NONE,        NONE,        NONE,     AC97,        NONE),
-	MFPR_168(GPIO117, 0x1D4, GPIO,    SSP1,        SSP1_TX,   NONE,        MMC2_CMD,    NONE,     AC97,        NONE),
-	MFPR_168(GPIO118, 0x1D8, GPIO,    SSP2,        NONE,      NONE,        MMC2_CLK,    NONE,     AC97,        KP_MKIN),
-	MFPR_168(GPIO119, 0x1DC, GPIO,    SSP2,        NONE,      NONE,        MMC2,        NONE,     AC97,        KP_MKIN),
-	MFPR_168(GPIO120, 0x1E0, GPIO,    SSP2,        SSP2_TX,   NONE,        MMC2,        NONE,     NONE,        KP_MKIN),
-	MFPR_168(GPIO121, 0x1E4, GPIO,    SSP2_TX,     SSP2,      NONE,        MMC2,        NONE,     NONE,        KP_MKIN),
-	MFPR_168(GPIO122, 0x1E8, GPIO,    AC97_SYSCLK, SSP2,      PWM,         MMC2,        NONE,     NONE,        NONE),
-	MFPR_168(PWR_SCL, 0x1EC, PWRI2C,  NONE,        NONE,      NONE,        NONE,        NONE,     GPIO,        MMC4),
-	MFPR_168(PWR_SDA, 0x1F0, PWRI2C,  NONE,        NONE,      NONE,        NONE,        NONE,     GPIO,        NONE),
-	MFPR_168(TDI,     0x1F4, JTAG,    PWM1,        UART2,     MMC4,        SSP5,        NONE,     XD,          MMC4),
-	MFPR_168(TMS,     0x1F8, JTAG,    PWM,         UART2,     NONE,        SSP5,        NONE,     XD,          MMC4),
-	MFPR_168(TCK,     0x1FC, JTAG,    PWM,         UART2,     UART2_TX,    SSP5,        NONE,     XD,          MMC4),
-	MFPR_168(TDO,     0x200, JTAG,    PWM,         UART2_TX,  UART2,       SSP5_TX,     NONE,     XD,          MMC4),
-	MFPR_168(TRST,    0x204, JTAG,    ONE_WIRE,    SSP2,      SSP3,        AC97_SYSCLK, NONE,     XD,          MMC4),
-	MFPR_168(WAKEUP,  0x208, WAKEUP,  ONE_WIRE,    PWM1,      PWM,         SSP2,        NONE,     GPIO,        MMC4),
-};
-
-static const unsigned p168_jtag_pin1[] = {TDI, TMS, TCK, TDO, TRST};
-static const unsigned p168_wakeup_pin1[] = {WAKEUP};
-static const unsigned p168_ssp1rx_pin1[] = {GPIO114, GPIO115, GPIO116};
-static const unsigned p168_ssp1tx_pin1[] = {GPIO117};
-static const unsigned p168_ssp4rx_pin1[] = {GPIO102, GPIO103, GPIO104};
-static const unsigned p168_ssp4tx_pin1[] = {GPIO105};
-static const unsigned p168_ssp5rx_pin1[] = {GPIO86, GPIO88, GPIO89};
-static const unsigned p168_ssp5tx_pin1[] = {GPIO87};
-static const unsigned p168_i2c_pin1[] = {GPIO105, GPIO106};
-static const unsigned p168_pwri2c_pin1[] = {PWR_SCL, PWR_SDA};
-static const unsigned p168_mmc1_pin1[] = {GPIO40, GPIO41, GPIO43, GPIO46,
-	GPIO49, GPIO51, GPIO52, GPIO53};
-static const unsigned p168_mmc2_data_pin1[] = {GPIO90, GPIO91, GPIO92, GPIO93};
-static const unsigned p168_mmc2_cmd_pin1[] = {GPIO94};
-static const unsigned p168_mmc2_clk_pin1[] = {GPIO95};
-static const unsigned p168_mmc3_data_pin1[] = {GPIO0, GPIO1, GPIO2, GPIO3,
-	GPIO4, GPIO5, GPIO6, GPIO7};
-static const unsigned p168_mmc3_cmd_pin1[] = {GPIO9};
-static const unsigned p168_mmc3_clk_pin1[] = {GPIO8};
-static const unsigned p168_eth_pin1[] = {GPIO92, GPIO93, GPIO100, GPIO101,
-	GPIO103};
-static const unsigned p168_ethtx_pin1[] = {GPIO86, GPIO87, GPIO88, GPIO89,
-	GPIO90, GPIO91};
-static const unsigned p168_ethrx_pin1[] = {GPIO94, GPIO95, GPIO96, GPIO97,
-	GPIO98, GPIO99};
-static const unsigned p168_uart1rx_pin1[] = {GPIO107};
-static const unsigned p168_uart1tx_pin1[] = {GPIO108};
-static const unsigned p168_uart3rx_pin1[] = {GPIO98, GPIO100, GPIO101};
-static const unsigned p168_uart3tx_pin1[] = {GPIO99};
-static const unsigned p168_msp_pin1[] = {GPIO40, GPIO41, GPIO42, GPIO43,
-	GPIO44, GPIO50};
-static const unsigned p168_ccic_pin1[] = {GPIO37, GPIO38, GPIO39, GPIO40,
-	GPIO41, GPIO42, GPIO44, GPIO45, GPIO46, GPIO48, GPIO54, GPIO55};
-static const unsigned p168_xd_pin1[] = {GPIO37, GPIO38, GPIO39, GPIO40,
-	GPIO41, GPIO42, GPIO44, GPIO45, GPIO47, GPIO48, GPIO49, GPIO50,
-	GPIO51, GPIO52};
-static const unsigned p168_lcd_pin1[] = {GPIO56, GPIO57, GPIO58, GPIO59,
-	GPIO60, GPIO61, GPIO62, GPIO63, GPIO64, GPIO65, GPIO66, GPIO67,
-	GPIO68, GPIO69, GPIO70, GPIO71, GPIO72, GPIO73, GPIO74, GPIO75,
-	GPIO76, GPIO77, GPIO78, GPIO79, GPIO80, GPIO81, GPIO82, GPIO83};
-static const unsigned p168_dfio_pin1[] = {GPIO0, GPIO1, GPIO2, GPIO3,
-	GPIO4, GPIO5, GPIO6, GPIO7, GPIO8, GPIO9, GPIO10, GPIO11, GPIO12,
-	GPIO13, GPIO14, GPIO15};
-static const unsigned p168_nand_pin1[] = {GPIO16, GPIO17, GPIO21, GPIO22,
-	GPIO24, GPIO26};
-static const unsigned p168_smc_pin1[] = {GPIO23, GPIO25, GPIO29, GPIO35,
-	GPIO36};
-static const unsigned p168_smccs0_pin1[] = {GPIO18};
-static const unsigned p168_smccs1_pin1[] = {GPIO34};
-static const unsigned p168_smcrdy_pin1[] = {GPIO28};
-static const unsigned p168_ac97sysclk_pin1[] = {GPIO113};
-static const unsigned p168_ac97_pin1[] = {GPIO114, GPIO115, GPIO117, GPIO118,
-	GPIO119};
-static const unsigned p168_cf_pin1[] = {GPIO19, GPIO20, GPIO23, GPIO25,
-	GPIO28, GPIO29, GPIO30, GPIO31, GPIO32, GPIO33, GPIO34, GPIO35,
-	GPIO36};
-static const unsigned p168_kpmkin_pin1[] = {GPIO109, GPIO110, GPIO121};
-static const unsigned p168_kpmkout_pin1[] = {GPIO111, GPIO112};
-static const unsigned p168_gpio86_pin1[] = {WAKEUP};
-static const unsigned p168_gpio86_pin2[] = {GPIO86};
-static const unsigned p168_gpio87_pin1[] = {GPIO87};
-static const unsigned p168_gpio87_pin2[] = {PWR_SDA};
-static const unsigned p168_gpio88_pin1[] = {GPIO88};
-static const unsigned p168_gpio88_pin2[] = {PWR_SCL};
-
-static struct pxa3xx_pin_group pxa168_grps[] = {
-	GRP_168("uart1rx-1", UART1, p168_uart1rx_pin1),
-	GRP_168("uart1tx-1", UART1_TX, p168_uart1tx_pin1),
-	GRP_168("uart3rx-1", UART3, p168_uart3rx_pin1),
-	GRP_168("uart3tx-1", UART3_TX, p168_uart3tx_pin1),
-	GRP_168("ssp1rx-1", SSP1, p168_ssp1rx_pin1),
-	GRP_168("ssp1tx-1", SSP1_TX, p168_ssp1tx_pin1),
-	GRP_168("ssp4rx-1", SSP4, p168_ssp4rx_pin1),
-	GRP_168("ssp4tx-1", SSP4_TX, p168_ssp4tx_pin1),
-	GRP_168("ssp5rx-1", SSP5, p168_ssp5rx_pin1),
-	GRP_168("ssp5tx-1", SSP5_TX, p168_ssp5tx_pin1),
-	GRP_168("jtag", JTAG, p168_jtag_pin1),
-	GRP_168("wakeup", WAKEUP, p168_wakeup_pin1),
-	GRP_168("i2c", I2C, p168_i2c_pin1),
-	GRP_168("pwri2c", PWRI2C, p168_pwri2c_pin1),
-	GRP_168("mmc1 8p1", MMC1, p168_mmc1_pin1),
-	GRP_168("mmc2 4p1", MMC2, p168_mmc2_data_pin1),
-	GRP_168("mmc2 cmd1", MMC2_CMD, p168_mmc2_cmd_pin1),
-	GRP_168("mmc2 clk1", MMC2_CLK, p168_mmc2_clk_pin1),
-	GRP_168("mmc3 8p1", MMC3, p168_mmc3_data_pin1),
-	GRP_168("mmc3 cmd1", MMC3_CMD, p168_mmc3_cmd_pin1),
-	GRP_168("mmc3 clk1", MMC3_CLK, p168_mmc3_clk_pin1),
-	GRP_168("eth", ETH, p168_eth_pin1),
-	GRP_168("eth rx", ETH_RX, p168_ethrx_pin1),
-	GRP_168("eth tx", ETH_TX, p168_ethtx_pin1),
-	GRP_168("msp", MSP, p168_msp_pin1),
-	GRP_168("ccic", CCIC, p168_ccic_pin1),
-	GRP_168("xd", XD, p168_xd_pin1),
-	GRP_168("lcd", LCD, p168_lcd_pin1),
-	GRP_168("dfio", DFIO, p168_dfio_pin1),
-	GRP_168("nand", NAND, p168_nand_pin1),
-	GRP_168("smc", SMC, p168_smc_pin1),
-	GRP_168("smc cs0", SMC_CS0, p168_smccs0_pin1),
-	GRP_168("smc cs1", SMC_CS1, p168_smccs1_pin1),
-	GRP_168("smc rdy", SMC_RDY, p168_smcrdy_pin1),
-	GRP_168("ac97 sysclk", AC97_SYSCLK, p168_ac97sysclk_pin1),
-	GRP_168("ac97", AC97, p168_ac97_pin1),
-	GRP_168("cf", CF, p168_cf_pin1),
-	GRP_168("kp mkin 3p1", KP_MKIN, p168_kpmkin_pin1),
-	GRP_168("kp mkout 2p1", KP_MKOUT, p168_kpmkout_pin1),
-	GRP_168("gpio86-1", GPIO, p168_gpio86_pin1),
-	GRP_168("gpio86-2", GPIO, p168_gpio86_pin2),
-	GRP_168("gpio87-1", GPIO, p168_gpio87_pin1),
-	GRP_168("gpio87-2", GPIO, p168_gpio87_pin2),
-	GRP_168("gpio88-1", GPIO, p168_gpio88_pin1),
-	GRP_168("gpio88-2", GPIO, p168_gpio88_pin2),
-};
-
-static const char * const p168_uart1rx_grps[] = {"uart1rx-1"};
-static const char * const p168_uart1tx_grps[] = {"uart1tx-1"};
-static const char * const p168_uart3rx_grps[] = {"uart3rx-1"};
-static const char * const p168_uart3tx_grps[] = {"uart3tx-1"};
-static const char * const p168_ssp1rx_grps[] = {"ssp1rx-1"};
-static const char * const p168_ssp1tx_grps[] = {"ssp1tx-1"};
-static const char * const p168_ssp4rx_grps[] = {"ssp4rx-1"};
-static const char * const p168_ssp4tx_grps[] = {"ssp4tx-1"};
-static const char * const p168_ssp5rx_grps[] = {"ssp5rx-1"};
-static const char * const p168_ssp5tx_grps[] = {"ssp5tx-1"};
-static const char * const p168_i2c_grps[] = {"i2c"};
-static const char * const p168_pwri2c_grps[] = {"pwri2c"};
-static const char * const p168_mmc1_grps[] = {"mmc1 8p1"};
-static const char * const p168_mmc2_data_grps[] = {"mmc2 4p1"};
-static const char * const p168_mmc2_cmd_grps[] = {"mmc2 cmd1"};
-static const char * const p168_mmc2_clk_grps[] = {"mmc2 clk1"};
-static const char * const p168_mmc3_data_grps[] = {"mmc3 8p1"};
-static const char * const p168_mmc3_cmd_grps[] = {"mmc3 cmd1"};
-static const char * const p168_mmc3_clk_grps[] = {"mmc3 clk1"};
-static const char * const p168_eth_grps[] = {"eth"};
-static const char * const p168_ethrx_grps[] = {"eth rx"};
-static const char * const p168_ethtx_grps[] = {"eth tx"};
-static const char * const p168_msp_grps[] = {"msp"};
-static const char * const p168_ccic_grps[] = {"ccic"};
-static const char * const p168_xd_grps[] = {"xd"};
-static const char * const p168_lcd_grps[] = {"lcd"};
-static const char * const p168_dfio_grps[] = {"dfio"};
-static const char * const p168_nand_grps[] = {"nand"};
-static const char * const p168_smc_grps[] = {"smc"};
-static const char * const p168_smccs0_grps[] = {"smc cs0"};
-static const char * const p168_smccs1_grps[] = {"smc cs1"};
-static const char * const p168_smcrdy_grps[] = {"smc rdy"};
-static const char * const p168_ac97sysclk_grps[] = {"ac97 sysclk"};
-static const char * const p168_ac97_grps[] = {"ac97"};
-static const char * const p168_cf_grps[] = {"cf"};
-static const char * const p168_kpmkin_grps[] = {"kp mkin 3p1"};
-static const char * const p168_kpmkout_grps[] = {"kp mkout 2p1"};
-static const char * const p168_gpio86_grps[] = {"gpio86-1", "gpio86-2"};
-static const char * const p168_gpio87_grps[] = {"gpio87-1", "gpio87-2"};
-static const char * const p168_gpio88_grps[] = {"gpio88-1", "gpio88-2"};
-
-static struct pxa3xx_pmx_func pxa168_funcs[] = {
-	{"uart1 rx",	ARRAY_AND_SIZE(p168_uart1rx_grps)},
-	{"uart1 tx",	ARRAY_AND_SIZE(p168_uart1tx_grps)},
-	{"uart3 rx",	ARRAY_AND_SIZE(p168_uart3rx_grps)},
-	{"uart3 tx",	ARRAY_AND_SIZE(p168_uart3tx_grps)},
-	{"ssp1 rx",	ARRAY_AND_SIZE(p168_ssp1rx_grps)},
-	{"ssp1 tx",	ARRAY_AND_SIZE(p168_ssp1tx_grps)},
-	{"ssp4 rx",	ARRAY_AND_SIZE(p168_ssp4rx_grps)},
-	{"ssp4 tx",	ARRAY_AND_SIZE(p168_ssp4tx_grps)},
-	{"ssp5 rx",	ARRAY_AND_SIZE(p168_ssp5rx_grps)},
-	{"ssp5 tx",	ARRAY_AND_SIZE(p168_ssp5tx_grps)},
-	{"i2c",		ARRAY_AND_SIZE(p168_i2c_grps)},
-	{"pwri2c",	ARRAY_AND_SIZE(p168_pwri2c_grps)},
-	{"mmc1",	ARRAY_AND_SIZE(p168_mmc1_grps)},
-	{"mmc2",	ARRAY_AND_SIZE(p168_mmc2_data_grps)},
-	{"mmc2 cmd",	ARRAY_AND_SIZE(p168_mmc2_cmd_grps)},
-	{"mmc2 clk",	ARRAY_AND_SIZE(p168_mmc2_clk_grps)},
-	{"mmc3",	ARRAY_AND_SIZE(p168_mmc3_data_grps)},
-	{"mmc3 cmd",	ARRAY_AND_SIZE(p168_mmc3_cmd_grps)},
-	{"mmc3 clk",	ARRAY_AND_SIZE(p168_mmc3_clk_grps)},
-	{"eth",		ARRAY_AND_SIZE(p168_eth_grps)},
-	{"eth rx",	ARRAY_AND_SIZE(p168_ethrx_grps)},
-	{"eth tx",	ARRAY_AND_SIZE(p168_ethtx_grps)},
-	{"msp",		ARRAY_AND_SIZE(p168_msp_grps)},
-	{"ccic",	ARRAY_AND_SIZE(p168_ccic_grps)},
-	{"xd",		ARRAY_AND_SIZE(p168_xd_grps)},
-	{"lcd",		ARRAY_AND_SIZE(p168_lcd_grps)},
-	{"dfio",	ARRAY_AND_SIZE(p168_dfio_grps)},
-	{"nand",	ARRAY_AND_SIZE(p168_nand_grps)},
-	{"smc",		ARRAY_AND_SIZE(p168_smc_grps)},
-	{"smc cs0",	ARRAY_AND_SIZE(p168_smccs0_grps)},
-	{"smc cs1",	ARRAY_AND_SIZE(p168_smccs1_grps)},
-	{"smc rdy",	ARRAY_AND_SIZE(p168_smcrdy_grps)},
-	{"ac97",	ARRAY_AND_SIZE(p168_ac97_grps)},
-	{"ac97 sysclk",	ARRAY_AND_SIZE(p168_ac97sysclk_grps)},
-	{"cf",		ARRAY_AND_SIZE(p168_cf_grps)},
-	{"kpmkin",	ARRAY_AND_SIZE(p168_kpmkin_grps)},
-	{"kpmkout",	ARRAY_AND_SIZE(p168_kpmkout_grps)},
-	{"gpio86",	ARRAY_AND_SIZE(p168_gpio86_grps)},
-	{"gpio87",	ARRAY_AND_SIZE(p168_gpio87_grps)},
-	{"gpio88",	ARRAY_AND_SIZE(p168_gpio88_grps)},
-};
-
-static struct pinctrl_desc pxa168_pctrl_desc = {
-	.name		= "pxa168-pinctrl",
-	.owner		= THIS_MODULE,
-};
-
-static struct pxa3xx_pinmux_info pxa168_info = {
-	.mfp		= pxa168_mfp,
-	.num_mfp	= ARRAY_SIZE(pxa168_mfp),
-	.grps		= pxa168_grps,
-	.num_grps	= ARRAY_SIZE(pxa168_grps),
-	.funcs		= pxa168_funcs,
-	.num_funcs	= ARRAY_SIZE(pxa168_funcs),
-	.num_gpio	= 128,
-	.desc		= &pxa168_pctrl_desc,
-	.pads		= pxa168_pads,
-	.num_pads	= ARRAY_SIZE(pxa168_pads),
-
-	.cputype	= PINCTRL_PXA168,
-	.ds_mask	= PXA168_DS_MASK,
-	.ds_shift	= PXA168_DS_SHIFT,
-};
-
-static int pxa168_pinmux_probe(struct platform_device *pdev)
-{
-	return pxa3xx_pinctrl_register(pdev, &pxa168_info);
-}
-
-static int pxa168_pinmux_remove(struct platform_device *pdev)
-{
-	return pxa3xx_pinctrl_unregister(pdev);
-}
-
-static struct platform_driver pxa168_pinmux_driver = {
-	.driver = {
-		.name	= "pxa168-pinmux",
-		.owner	= THIS_MODULE,
-	},
-	.probe	= pxa168_pinmux_probe,
-	.remove	= pxa168_pinmux_remove,
-};
-
-static int __init pxa168_pinmux_init(void)
-{
-	return platform_driver_register(&pxa168_pinmux_driver);
-}
-core_initcall_sync(pxa168_pinmux_init);
-
-static void __exit pxa168_pinmux_exit(void)
-{
-	platform_driver_unregister(&pxa168_pinmux_driver);
-}
-module_exit(pxa168_pinmux_exit);
-
-MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
-MODULE_DESCRIPTION("PXA3xx pin control driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/pinctrl-pxa3xx.c b/drivers/pinctrl/pinctrl-pxa3xx.c
deleted file mode 100644
index 1f49bb0..0000000
--- a/drivers/pinctrl/pinctrl-pxa3xx.c
+++ /dev/null
@@ -1,227 +0,0 @@
-/*
- *  linux/drivers/pinctrl/pinctrl-pxa3xx.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
- *  publishhed by the Free Software Foundation.
- *
- *  Copyright (C) 2011, Marvell Technology Group Ltd.
- *
- *  Author: Haojian Zhuang <haojian.zhuang@marvell.com>
- *
- */
-
-#include <linux/err.h>
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include "pinctrl-pxa3xx.h"
-
-static struct pinctrl_gpio_range pxa3xx_pinctrl_gpio_range = {
-	.name		= "PXA3xx GPIO",
-	.id		= 0,
-	.base		= 0,
-	.pin_base	= 0,
-};
-
-static int pxa3xx_get_groups_count(struct pinctrl_dev *pctrldev)
-{
-	struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
-
-	return info->num_grps;
-}
-
-static const char *pxa3xx_get_group_name(struct pinctrl_dev *pctrldev,
-					 unsigned selector)
-{
-	struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
-
-	return info->grps[selector].name;
-}
-
-static int pxa3xx_get_group_pins(struct pinctrl_dev *pctrldev,
-				 unsigned selector,
-				 const unsigned **pins,
-				 unsigned *num_pins)
-{
-	struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
-
-	*pins = info->grps[selector].pins;
-	*num_pins = info->grps[selector].npins;
-	return 0;
-}
-
-static struct pinctrl_ops pxa3xx_pctrl_ops = {
-	.get_groups_count = pxa3xx_get_groups_count,
-	.get_group_name	= pxa3xx_get_group_name,
-	.get_group_pins	= pxa3xx_get_group_pins,
-};
-
-static int pxa3xx_pmx_get_funcs_count(struct pinctrl_dev *pctrldev)
-{
-	struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
-
-	return info->num_funcs;
-}
-
-static const char *pxa3xx_pmx_get_func_name(struct pinctrl_dev *pctrldev,
-					    unsigned func)
-{
-	struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
-	return info->funcs[func].name;
-}
-
-static int pxa3xx_pmx_get_groups(struct pinctrl_dev *pctrldev, unsigned func,
-				 const char * const **groups,
-				 unsigned * const num_groups)
-{
-	struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
-	*groups = info->funcs[func].groups;
-	*num_groups = info->funcs[func].num_groups;
-	return 0;
-}
-
-/* Return function number. If failure, return negative value. */
-static int match_mux(struct pxa3xx_mfp_pin *mfp, unsigned mux)
-{
-	int i;
-	for (i = 0; i < PXA3xx_MAX_MUX; i++) {
-		if (mfp->func[i] == mux)
-			break;
-	}
-	if (i >= PXA3xx_MAX_MUX)
-		return -EINVAL;
-	return i;
-}
-
-/* check whether current pin configuration is valid. Negative for failure */
-static int match_group_mux(struct pxa3xx_pin_group *grp,
-			   struct pxa3xx_pinmux_info *info,
-			   unsigned mux)
-{
-	int i, pin, ret = 0;
-	for (i = 0; i < grp->npins; i++) {
-		pin = grp->pins[i];
-		ret = match_mux(&info->mfp[pin], mux);
-		if (ret < 0) {
-			dev_err(info->dev, "Can't find mux %d on pin%d\n",
-				mux, pin);
-			break;
-		}
-	}
-	return ret;
-}
-
-static int pxa3xx_pmx_enable(struct pinctrl_dev *pctrldev, unsigned func,
-			     unsigned group)
-{
-	struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
-	struct pxa3xx_pin_group *pin_grp = &info->grps[group];
-	unsigned int data;
-	int i, mfpr, pin, pin_func;
-
-	if (!pin_grp->npins ||
-		(match_group_mux(pin_grp, info, pin_grp->mux) < 0)) {
-		dev_err(info->dev, "Failed to set the pin group: %d\n", group);
-		return -EINVAL;
-	}
-	for (i = 0; i < pin_grp->npins; i++) {
-		pin = pin_grp->pins[i];
-		pin_func = match_mux(&info->mfp[pin], pin_grp->mux);
-		mfpr = info->mfp[pin].mfpr;
-		data = readl_relaxed(info->virt_base + mfpr);
-		data &= ~MFPR_FUNC_MASK;
-		data |= pin_func;
-		writel_relaxed(data, info->virt_base + mfpr);
-	}
-	return 0;
-}
-
-static int pxa3xx_pmx_request_gpio(struct pinctrl_dev *pctrldev,
-				   struct pinctrl_gpio_range *range,
-				   unsigned pin)
-{
-	struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
-	unsigned int data;
-	int pin_func, mfpr;
-
-	pin_func = match_mux(&info->mfp[pin], PXA3xx_MUX_GPIO);
-	if (pin_func < 0) {
-		dev_err(info->dev, "No GPIO function on pin%d (%s)\n",
-			pin, info->pads[pin].name);
-		return -EINVAL;
-	}
-	mfpr = info->mfp[pin].mfpr;
-	/* write gpio function into mfpr register */
-	data = readl_relaxed(info->virt_base + mfpr) & ~MFPR_FUNC_MASK;
-	data |= pin_func;
-	writel_relaxed(data, info->virt_base + mfpr);
-	return 0;
-}
-
-static struct pinmux_ops pxa3xx_pmx_ops = {
-	.get_functions_count	= pxa3xx_pmx_get_funcs_count,
-	.get_function_name	= pxa3xx_pmx_get_func_name,
-	.get_function_groups	= pxa3xx_pmx_get_groups,
-	.enable			= pxa3xx_pmx_enable,
-	.gpio_request_enable	= pxa3xx_pmx_request_gpio,
-};
-
-int pxa3xx_pinctrl_register(struct platform_device *pdev,
-			    struct pxa3xx_pinmux_info *info)
-{
-	struct pinctrl_desc *desc;
-	struct resource *res;
-
-	if (!info || !info->cputype)
-		return -EINVAL;
-	desc = info->desc;
-	desc->pins = info->pads;
-	desc->npins = info->num_pads;
-	desc->pctlops = &pxa3xx_pctrl_ops;
-	desc->pmxops = &pxa3xx_pmx_ops;
-	info->dev = &pdev->dev;
-	pxa3xx_pinctrl_gpio_range.npins = info->num_gpio;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res)
-		return -ENOENT;
-	info->virt_base = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(info->virt_base))
-		return PTR_ERR(info->virt_base);
-	info->pctrl = pinctrl_register(desc, &pdev->dev, info);
-	if (!info->pctrl) {
-		dev_err(&pdev->dev, "failed to register PXA pinmux driver\n");
-		return -EINVAL;
-	}
-	pinctrl_add_gpio_range(info->pctrl, &pxa3xx_pinctrl_gpio_range);
-	platform_set_drvdata(pdev, info);
-	return 0;
-}
-
-int pxa3xx_pinctrl_unregister(struct platform_device *pdev)
-{
-	struct pxa3xx_pinmux_info *info = platform_get_drvdata(pdev);
-
-	pinctrl_unregister(info->pctrl);
-	platform_set_drvdata(pdev, NULL);
-	return 0;
-}
-
-static int __init pxa3xx_pinctrl_init(void)
-{
-	pr_info("pxa3xx-pinctrl: PXA3xx pinctrl driver initializing\n");
-	return 0;
-}
-core_initcall_sync(pxa3xx_pinctrl_init);
-
-static void __exit pxa3xx_pinctrl_exit(void)
-{
-}
-module_exit(pxa3xx_pinctrl_exit);
-
-MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
-MODULE_DESCRIPTION("PXA3xx pin control driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/pinctrl-pxa3xx.h b/drivers/pinctrl/pinctrl-pxa3xx.h
deleted file mode 100644
index 92fad08..0000000
--- a/drivers/pinctrl/pinctrl-pxa3xx.h
+++ /dev/null
@@ -1,262 +0,0 @@
-/*
- *  linux/drivers/pinctrl/pinctrl-pxa3xx.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
- *  publishhed by the Free Software Foundation.
- *
- *  Copyright (C) 2011, Marvell Technology Group Ltd.
- *
- *  Author: Haojian Zhuang <haojian.zhuang@marvell.com>
- *
- */
-
-#ifndef __PINCTRL_PXA3XX_H
-
-#include <linux/pinctrl/pinctrl.h>
-#include <linux/pinctrl/pinmux.h>
-
-#define ARRAY_AND_SIZE(x)	(x), ARRAY_SIZE(x)
-
-#define PXA3xx_MUX_GPIO		0
-
-#define PXA3xx_MAX_MUX		8
-#define MFPR_FUNC_MASK		0x7
-
-enum pxa_cpu_type {
-	PINCTRL_INVALID = 0,
-	PINCTRL_PXA300,
-	PINCTRL_PXA310,
-	PINCTRL_PXA320,
-	PINCTRL_PXA168,
-	PINCTRL_PXA910,
-	PINCTRL_PXA930,
-	PINCTRL_PXA955,
-	PINCTRL_MMP2,
-	PINCTRL_MAX,
-};
-
-struct pxa3xx_mfp_pin {
-	const char *name;
-	const unsigned int pin;
-	const unsigned int mfpr;	/* register offset */
-	const unsigned short func[8];
-};
-
-struct pxa3xx_pin_group {
-	const char *name;
-	const unsigned mux;
-	const unsigned *pins;
-	const unsigned npins;
-};
-
-struct pxa3xx_pmx_func {
-	const char *name;
-	const char * const * groups;
-	const unsigned num_groups;
-};
-
-struct pxa3xx_pinmux_info {
-	struct device *dev;
-	struct pinctrl_dev *pctrl;
-	enum pxa_cpu_type cputype;
-	void __iomem *virt_base;
-
-	struct pxa3xx_mfp_pin *mfp;
-	unsigned int num_mfp;
-	struct pxa3xx_pin_group *grps;
-	unsigned int num_grps;
-	struct pxa3xx_pmx_func *funcs;
-	unsigned int num_funcs;
-	unsigned int num_gpio;
-	struct pinctrl_desc *desc;
-	struct pinctrl_pin_desc *pads;
-	unsigned int num_pads;
-
-	unsigned ds_mask;	/* drive strength mask */
-	unsigned ds_shift;	/* drive strength shift */
-	unsigned slp_mask;	/* sleep mask */
-	unsigned slp_input_low;
-	unsigned slp_input_high;
-	unsigned slp_output_low;
-	unsigned slp_output_high;
-	unsigned slp_float;
-};
-
-enum pxa3xx_pin_list {
-	GPIO0 = 0,
-	GPIO1,
-	GPIO2,
-	GPIO3,
-	GPIO4,
-	GPIO5,
-	GPIO6,
-	GPIO7,
-	GPIO8,
-	GPIO9,
-	GPIO10, /* 10 */
-	GPIO11,
-	GPIO12,
-	GPIO13,
-	GPIO14,
-	GPIO15,
-	GPIO16,
-	GPIO17,
-	GPIO18,
-	GPIO19,
-	GPIO20, /* 20 */
-	GPIO21,
-	GPIO22,
-	GPIO23,
-	GPIO24,
-	GPIO25,
-	GPIO26,
-	GPIO27,
-	GPIO28,
-	GPIO29,
-	GPIO30, /* 30 */
-	GPIO31,
-	GPIO32,
-	GPIO33,
-	GPIO34,
-	GPIO35,
-	GPIO36,
-	GPIO37,
-	GPIO38,
-	GPIO39,
-	GPIO40, /* 40 */
-	GPIO41,
-	GPIO42,
-	GPIO43,
-	GPIO44,
-	GPIO45,
-	GPIO46,
-	GPIO47,
-	GPIO48,
-	GPIO49,
-	GPIO50, /* 50 */
-	GPIO51,
-	GPIO52,
-	GPIO53,
-	GPIO54,
-	GPIO55,
-	GPIO56,
-	GPIO57,
-	GPIO58,
-	GPIO59,
-	GPIO60, /* 60 */
-	GPIO61,
-	GPIO62,
-	GPIO63,
-	GPIO64,
-	GPIO65,
-	GPIO66,
-	GPIO67,
-	GPIO68,
-	GPIO69,
-	GPIO70, /* 70 */
-	GPIO71,
-	GPIO72,
-	GPIO73,
-	GPIO74,
-	GPIO75,
-	GPIO76,
-	GPIO77,
-	GPIO78,
-	GPIO79,
-	GPIO80, /* 80 */
-	GPIO81,
-	GPIO82,
-	GPIO83,
-	GPIO84,
-	GPIO85,
-	GPIO86,
-	GPIO87,
-	GPIO88,
-	GPIO89,
-	GPIO90, /* 90 */
-	GPIO91,
-	GPIO92,
-	GPIO93,
-	GPIO94,
-	GPIO95,
-	GPIO96,
-	GPIO97,
-	GPIO98,
-	GPIO99,
-	GPIO100, /* 100 */
-	GPIO101,
-	GPIO102,
-	GPIO103,
-	GPIO104,
-	GPIO105,
-	GPIO106,
-	GPIO107,
-	GPIO108,
-	GPIO109,
-	GPIO110, /* 110 */
-	GPIO111,
-	GPIO112,
-	GPIO113,
-	GPIO114,
-	GPIO115,
-	GPIO116,
-	GPIO117,
-	GPIO118,
-	GPIO119,
-	GPIO120, /* 120 */
-	GPIO121,
-	GPIO122,
-	GPIO123,
-	GPIO124,
-	GPIO125,
-	GPIO126,
-	GPIO127,
-	GPIO128,
-	GPIO129,
-	GPIO130, /* 130 */
-	GPIO131,
-	GPIO132,
-	GPIO133,
-	GPIO134,
-	GPIO135,
-	GPIO136,
-	GPIO137,
-	GPIO138,
-	GPIO139,
-	GPIO140, /* 140 */
-	GPIO141,
-	GPIO142,
-	GPIO143,
-	GPIO144,
-	GPIO145,
-	GPIO146,
-	GPIO147,
-	GPIO148,
-	GPIO149,
-	GPIO150, /* 150 */
-	GPIO151,
-	GPIO152,
-	GPIO153,
-	GPIO154,
-	GPIO155,
-	GPIO156,
-	GPIO157,
-	GPIO158,
-	GPIO159,
-	GPIO160, /* 160 */
-	GPIO161,
-	GPIO162,
-	GPIO163,
-	GPIO164,
-	GPIO165,
-	GPIO166,
-	GPIO167,
-	GPIO168,
-	GPIO169,
-};
-
-extern int pxa3xx_pinctrl_register(struct platform_device *pdev,
-				   struct pxa3xx_pinmux_info *info);
-extern int pxa3xx_pinctrl_unregister(struct platform_device *pdev);
-#endif	/* __PINCTRL_PXA3XX_H */
diff --git a/drivers/pinctrl/pinctrl-pxa910.c b/drivers/pinctrl/pinctrl-pxa910.c
deleted file mode 100644
index a2f917b..0000000
--- a/drivers/pinctrl/pinctrl-pxa910.c
+++ /dev/null
@@ -1,1007 +0,0 @@
-/*
- *  linux/drivers/pinctrl/pinmux-pxa910.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
- *  publishhed by the Free Software Foundation.
- *
- *  Copyright (C) 2011, Marvell Technology Group Ltd.
- *
- *  Author: Haojian Zhuang <haojian.zhuang@marvell.com>
- *
- */
-
-#include <linux/device.h>
-#include <linux/module.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include "pinctrl-pxa3xx.h"
-
-#define PXA910_DS_MASK		0x1800
-#define PXA910_DS_SHIFT		11
-#define PXA910_SLEEP_MASK	0x38
-#define PXA910_SLEEP_SELECT	(1 << 9)
-#define PXA910_SLEEP_DATA	(1 << 8)
-#define PXA910_SLEEP_DIR	(1 << 7)
-
-#define MFPR_910(a, r, f0, f1, f2, f3, f4, f5, f6, f7)		\
-	{							\
-		.name = #a,					\
-		.pin = a,					\
-		.mfpr = r,					\
-		.func = {					\
-			PXA910_MUX_##f0,			\
-			PXA910_MUX_##f1,			\
-			PXA910_MUX_##f2,			\
-			PXA910_MUX_##f3,			\
-			PXA910_MUX_##f4,			\
-			PXA910_MUX_##f5,			\
-			PXA910_MUX_##f6,			\
-			PXA910_MUX_##f7,			\
-		},						\
-	}
-
-#define GRP_910(a, m, p)		\
-	{ .name = a, .mux = PXA910_MUX_##m, .pins = p, .npins = ARRAY_SIZE(p), }
-
-/* 170 pins */
-enum pxa910_pin_list {
-	/* 0~127: GPIO0~GPIO127 */
-	ND_IO15 = 128,
-	ND_IO14,
-	ND_IO13, /* 130 */
-	ND_IO12,
-	ND_IO11,
-	ND_IO10,
-	ND_IO9,
-	ND_IO8,
-	ND_IO7,
-	ND_IO6,
-	ND_IO5,
-	ND_IO4,
-	ND_IO3, /* 140 */
-	ND_IO2,
-	ND_IO1,
-	ND_IO0,
-	ND_NCS0,
-	ND_NCS1,
-	SM_NCS0,
-	SM_NCS1,
-	ND_NWE,
-	ND_NRE,
-	ND_CLE, /* 150 */
-	ND_ALE,
-	SM_SCLK,
-	ND_RDY0,
-	SM_ADV,
-	ND_RDY1,
-	SM_ADVMUX,
-	SM_RDY,
-	MMC1_DAT7,
-	MMC1_DAT6,
-	MMC1_DAT5, /* 160 */
-	MMC1_DAT4,
-	MMC1_DAT3,
-	MMC1_DAT2,
-	MMC1_DAT1,
-	MMC1_DAT0,
-	MMC1_CMD,
-	MMC1_CLK,
-	MMC1_CD,
-	VCXO_OUT,
-};
-
-enum pxa910_mux {
-	/* PXA3xx_MUX_GPIO = 0 (predefined in pinctrl-pxa3xx.h) */
-	PXA910_MUX_GPIO = 0,
-	PXA910_MUX_NAND,
-	PXA910_MUX_USIM2,
-	PXA910_MUX_EXT_DMA,
-	PXA910_MUX_EXT_INT,
-	PXA910_MUX_MMC1,
-	PXA910_MUX_MMC2,
-	PXA910_MUX_MMC3,
-	PXA910_MUX_SM_INT,
-	PXA910_MUX_PRI_JTAG,
-	PXA910_MUX_SEC1_JTAG,
-	PXA910_MUX_SEC2_JTAG,
-	PXA910_MUX_RESET,	/* SLAVE RESET OUT */
-	PXA910_MUX_CLK_REQ,
-	PXA910_MUX_VCXO_REQ,
-	PXA910_MUX_VCXO_OUT,
-	PXA910_MUX_VCXO_REQ2,
-	PXA910_MUX_VCXO_OUT2,
-	PXA910_MUX_SPI,
-	PXA910_MUX_SPI2,
-	PXA910_MUX_GSSP,
-	PXA910_MUX_SSP0,
-	PXA910_MUX_SSP1,
-	PXA910_MUX_SSP2,
-	PXA910_MUX_DSSP2,
-	PXA910_MUX_DSSP3,
-	PXA910_MUX_UART0,
-	PXA910_MUX_UART1,
-	PXA910_MUX_UART2,
-	PXA910_MUX_TWSI,
-	PXA910_MUX_CCIC,
-	PXA910_MUX_PWM0,
-	PXA910_MUX_PWM1,
-	PXA910_MUX_PWM2,
-	PXA910_MUX_PWM3,
-	PXA910_MUX_HSL,
-	PXA910_MUX_ONE_WIRE,
-	PXA910_MUX_LCD,
-	PXA910_MUX_DAC_ST23,
-	PXA910_MUX_ULPI,
-	PXA910_MUX_TB,
-	PXA910_MUX_KP_MK,
-	PXA910_MUX_KP_DK,
-	PXA910_MUX_TCU_GPOA,
-	PXA910_MUX_TCU_GPOB,
-	PXA910_MUX_ROT,
-	PXA910_MUX_TDS,
-	PXA910_MUX_32K_CLK, /* 32KHz CLK OUT */
-	PXA910_MUX_MN_CLK, /* MN CLK OUT */
-	PXA910_MUX_SMC,
-	PXA910_MUX_SM_ADDR18,
-	PXA910_MUX_SM_ADDR19,
-	PXA910_MUX_SM_ADDR20,
-	PXA910_MUX_NONE = 0xffff,
-};
-
-
-static struct pinctrl_pin_desc pxa910_pads[] = {
-	PINCTRL_PIN(GPIO0, "GPIO0"),
-	PINCTRL_PIN(GPIO1, "GPIO1"),
-	PINCTRL_PIN(GPIO2, "GPIO2"),
-	PINCTRL_PIN(GPIO3, "GPIO3"),
-	PINCTRL_PIN(GPIO4, "GPIO4"),
-	PINCTRL_PIN(GPIO5, "GPIO5"),
-	PINCTRL_PIN(GPIO6, "GPIO6"),
-	PINCTRL_PIN(GPIO7, "GPIO7"),
-	PINCTRL_PIN(GPIO8, "GPIO8"),
-	PINCTRL_PIN(GPIO9, "GPIO9"),
-	PINCTRL_PIN(GPIO10, "GPIO10"),
-	PINCTRL_PIN(GPIO11, "GPIO11"),
-	PINCTRL_PIN(GPIO12, "GPIO12"),
-	PINCTRL_PIN(GPIO13, "GPIO13"),
-	PINCTRL_PIN(GPIO14, "GPIO14"),
-	PINCTRL_PIN(GPIO15, "GPIO15"),
-	PINCTRL_PIN(GPIO16, "GPIO16"),
-	PINCTRL_PIN(GPIO17, "GPIO17"),
-	PINCTRL_PIN(GPIO18, "GPIO18"),
-	PINCTRL_PIN(GPIO19, "GPIO19"),
-	PINCTRL_PIN(GPIO20, "GPIO20"),
-	PINCTRL_PIN(GPIO21, "GPIO21"),
-	PINCTRL_PIN(GPIO22, "GPIO22"),
-	PINCTRL_PIN(GPIO23, "GPIO23"),
-	PINCTRL_PIN(GPIO24, "GPIO24"),
-	PINCTRL_PIN(GPIO25, "GPIO25"),
-	PINCTRL_PIN(GPIO26, "GPIO26"),
-	PINCTRL_PIN(GPIO27, "GPIO27"),
-	PINCTRL_PIN(GPIO28, "GPIO28"),
-	PINCTRL_PIN(GPIO29, "GPIO29"),
-	PINCTRL_PIN(GPIO30, "GPIO30"),
-	PINCTRL_PIN(GPIO31, "GPIO31"),
-	PINCTRL_PIN(GPIO32, "GPIO32"),
-	PINCTRL_PIN(GPIO33, "GPIO33"),
-	PINCTRL_PIN(GPIO34, "GPIO34"),
-	PINCTRL_PIN(GPIO35, "GPIO35"),
-	PINCTRL_PIN(GPIO36, "GPIO36"),
-	PINCTRL_PIN(GPIO37, "GPIO37"),
-	PINCTRL_PIN(GPIO38, "GPIO38"),
-	PINCTRL_PIN(GPIO39, "GPIO39"),
-	PINCTRL_PIN(GPIO40, "GPIO40"),
-	PINCTRL_PIN(GPIO41, "GPIO41"),
-	PINCTRL_PIN(GPIO42, "GPIO42"),
-	PINCTRL_PIN(GPIO43, "GPIO43"),
-	PINCTRL_PIN(GPIO44, "GPIO44"),
-	PINCTRL_PIN(GPIO45, "GPIO45"),
-	PINCTRL_PIN(GPIO46, "GPIO46"),
-	PINCTRL_PIN(GPIO47, "GPIO47"),
-	PINCTRL_PIN(GPIO48, "GPIO48"),
-	PINCTRL_PIN(GPIO49, "GPIO49"),
-	PINCTRL_PIN(GPIO50, "GPIO50"),
-	PINCTRL_PIN(GPIO51, "GPIO51"),
-	PINCTRL_PIN(GPIO52, "GPIO52"),
-	PINCTRL_PIN(GPIO53, "GPIO53"),
-	PINCTRL_PIN(GPIO54, "GPIO54"),
-	PINCTRL_PIN(GPIO55, "GPIO55"),
-	PINCTRL_PIN(GPIO56, "GPIO56"),
-	PINCTRL_PIN(GPIO57, "GPIO57"),
-	PINCTRL_PIN(GPIO58, "GPIO58"),
-	PINCTRL_PIN(GPIO59, "GPIO59"),
-	PINCTRL_PIN(GPIO60, "GPIO60"),
-	PINCTRL_PIN(GPIO61, "GPIO61"),
-	PINCTRL_PIN(GPIO62, "GPIO62"),
-	PINCTRL_PIN(GPIO63, "GPIO63"),
-	PINCTRL_PIN(GPIO64, "GPIO64"),
-	PINCTRL_PIN(GPIO65, "GPIO65"),
-	PINCTRL_PIN(GPIO66, "GPIO66"),
-	PINCTRL_PIN(GPIO67, "GPIO67"),
-	PINCTRL_PIN(GPIO68, "GPIO68"),
-	PINCTRL_PIN(GPIO69, "GPIO69"),
-	PINCTRL_PIN(GPIO70, "GPIO70"),
-	PINCTRL_PIN(GPIO71, "GPIO71"),
-	PINCTRL_PIN(GPIO72, "GPIO72"),
-	PINCTRL_PIN(GPIO73, "GPIO73"),
-	PINCTRL_PIN(GPIO74, "GPIO74"),
-	PINCTRL_PIN(GPIO75, "GPIO75"),
-	PINCTRL_PIN(GPIO76, "GPIO76"),
-	PINCTRL_PIN(GPIO77, "GPIO77"),
-	PINCTRL_PIN(GPIO78, "GPIO78"),
-	PINCTRL_PIN(GPIO79, "GPIO79"),
-	PINCTRL_PIN(GPIO80, "GPIO80"),
-	PINCTRL_PIN(GPIO81, "GPIO81"),
-	PINCTRL_PIN(GPIO82, "GPIO82"),
-	PINCTRL_PIN(GPIO83, "GPIO83"),
-	PINCTRL_PIN(GPIO84, "GPIO84"),
-	PINCTRL_PIN(GPIO85, "GPIO85"),
-	PINCTRL_PIN(GPIO86, "GPIO86"),
-	PINCTRL_PIN(GPIO87, "GPIO87"),
-	PINCTRL_PIN(GPIO88, "GPIO88"),
-	PINCTRL_PIN(GPIO89, "GPIO89"),
-	PINCTRL_PIN(GPIO90, "GPIO90"),
-	PINCTRL_PIN(GPIO91, "GPIO91"),
-	PINCTRL_PIN(GPIO92, "GPIO92"),
-	PINCTRL_PIN(GPIO93, "GPIO93"),
-	PINCTRL_PIN(GPIO94, "GPIO94"),
-	PINCTRL_PIN(GPIO95, "GPIO95"),
-	PINCTRL_PIN(GPIO96, "GPIO96"),
-	PINCTRL_PIN(GPIO97, "GPIO97"),
-	PINCTRL_PIN(GPIO98, "GPIO98"),
-	PINCTRL_PIN(GPIO99, "GPIO99"),
-	PINCTRL_PIN(GPIO100, "GPIO100"),
-	PINCTRL_PIN(GPIO101, "GPIO101"),
-	PINCTRL_PIN(GPIO102, "GPIO102"),
-	PINCTRL_PIN(GPIO103, "GPIO103"),
-	PINCTRL_PIN(GPIO104, "GPIO104"),
-	PINCTRL_PIN(GPIO105, "GPIO105"),
-	PINCTRL_PIN(GPIO106, "GPIO106"),
-	PINCTRL_PIN(GPIO107, "GPIO107"),
-	PINCTRL_PIN(GPIO108, "GPIO108"),
-	PINCTRL_PIN(GPIO109, "GPIO109"),
-	PINCTRL_PIN(GPIO110, "GPIO110"),
-	PINCTRL_PIN(GPIO111, "GPIO111"),
-	PINCTRL_PIN(GPIO112, "GPIO112"),
-	PINCTRL_PIN(GPIO113, "GPIO113"),
-	PINCTRL_PIN(GPIO114, "GPIO114"),
-	PINCTRL_PIN(GPIO115, "GPIO115"),
-	PINCTRL_PIN(GPIO116, "GPIO116"),
-	PINCTRL_PIN(GPIO117, "GPIO117"),
-	PINCTRL_PIN(GPIO118, "GPIO118"),
-	PINCTRL_PIN(GPIO119, "GPIO119"),
-	PINCTRL_PIN(GPIO120, "GPIO120"),
-	PINCTRL_PIN(GPIO121, "GPIO121"),
-	PINCTRL_PIN(GPIO122, "GPIO122"),
-	PINCTRL_PIN(GPIO123, "GPIO123"),
-	PINCTRL_PIN(GPIO124, "GPIO124"),
-	PINCTRL_PIN(GPIO125, "GPIO125"),
-	PINCTRL_PIN(GPIO126, "GPIO126"),
-	PINCTRL_PIN(GPIO127, "GPIO127"),
-	PINCTRL_PIN(ND_IO15, "ND_IO15"),
-	PINCTRL_PIN(ND_IO14, "ND_IO14"),
-	PINCTRL_PIN(ND_IO13, "ND_IO13"),
-	PINCTRL_PIN(ND_IO12, "ND_IO12"),
-	PINCTRL_PIN(ND_IO11, "ND_IO11"),
-	PINCTRL_PIN(ND_IO10, "ND_IO10"),
-	PINCTRL_PIN(ND_IO9, "ND_IO9"),
-	PINCTRL_PIN(ND_IO8, "ND_IO8"),
-	PINCTRL_PIN(ND_IO7, "ND_IO7"),
-	PINCTRL_PIN(ND_IO6, "ND_IO6"),
-	PINCTRL_PIN(ND_IO5, "ND_IO5"),
-	PINCTRL_PIN(ND_IO4, "ND_IO4"),
-	PINCTRL_PIN(ND_IO3, "ND_IO3"),
-	PINCTRL_PIN(ND_IO2, "ND_IO2"),
-	PINCTRL_PIN(ND_IO1, "ND_IO1"),
-	PINCTRL_PIN(ND_IO0, "ND_IO0"),
-	PINCTRL_PIN(ND_NCS0, "ND_NCS0_SM_NCS2"),
-	PINCTRL_PIN(ND_NCS1, "ND_NCS1_SM_NCS3"),
-	PINCTRL_PIN(SM_NCS0, "SM_NCS0"),
-	PINCTRL_PIN(SM_NCS1, "SM_NCS1"),
-	PINCTRL_PIN(ND_NWE, "ND_NWE"),
-	PINCTRL_PIN(ND_NRE, "ND_NRE"),
-	PINCTRL_PIN(ND_CLE, "ND_CLE_SM_NOE"),
-	PINCTRL_PIN(ND_ALE, "ND_ALE_SM_NWE"),
-	PINCTRL_PIN(SM_SCLK, "SM_SCLK"),
-	PINCTRL_PIN(ND_RDY0, "ND_RDY0"),
-	PINCTRL_PIN(SM_ADV, "SM_ADV"),
-	PINCTRL_PIN(ND_RDY1, "ND_RDY1"),
-	PINCTRL_PIN(SM_RDY, "SM_RDY"),
-	PINCTRL_PIN(MMC1_DAT7, "MMC1_DAT7"),
-	PINCTRL_PIN(MMC1_DAT6, "MMC1_DAT6"),
-	PINCTRL_PIN(MMC1_DAT5, "MMC1_DAT5"),
-	PINCTRL_PIN(MMC1_DAT4, "MMC1_DAT4"),
-	PINCTRL_PIN(MMC1_DAT3, "MMC1_DAT3"),
-	PINCTRL_PIN(MMC1_DAT2, "MMC1_DAT2"),
-	PINCTRL_PIN(MMC1_DAT1, "MMC1_DAT1"),
-	PINCTRL_PIN(MMC1_DAT0, "MMC1_DAT0"),
-	PINCTRL_PIN(MMC1_CMD, "MMC1 CMD"),
-	PINCTRL_PIN(MMC1_CLK, "MMC1 CLK"),
-	PINCTRL_PIN(MMC1_CD, "MMC1 CD"),
-	PINCTRL_PIN(VCXO_OUT, "VCXO_OUT"),
-};
-
-struct pxa3xx_mfp_pin pxa910_mfp[] = {
-	/*       pin        offs   f0        f1      f2         f3         f4         f5        f6        f7  */
-	MFPR_910(GPIO0,     0x0DC, GPIO,     KP_MK,  NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO1,     0x0E0, GPIO,     KP_MK,  NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO2,     0x0E4, GPIO,     KP_MK,  NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO3,     0x0E8, GPIO,     KP_MK,  NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO4,     0x0EC, GPIO,     KP_MK,  NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO5,     0x0F0, GPIO,     KP_MK,  NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO6,     0x0F4, GPIO,     KP_MK,  NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO7,     0x0F8, GPIO,     KP_MK,  NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO8,     0x0FC, GPIO,     KP_MK,  NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO9,     0x100, GPIO,     KP_MK,  NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO10,    0x104, GPIO,     KP_MK,  NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO11,    0x108, GPIO,     KP_MK,  NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO12,    0x10C, GPIO,     KP_MK,  NONE,      NONE,      KP_DK,     NONE,     NONE,     NONE),
-	MFPR_910(GPIO13,    0x110, GPIO,     KP_MK,  NONE,      NONE,      KP_DK,     NONE,     NONE,     NONE),
-	MFPR_910(GPIO14,    0x114, GPIO,     KP_MK,  NONE,      NONE,      KP_DK,     TB,       NONE,     NONE),
-	MFPR_910(GPIO15,    0x118, GPIO,     KP_MK,  NONE,      NONE,      KP_DK,     TB,       NONE,     NONE),
-	MFPR_910(GPIO16,    0x11C, GPIO,     KP_DK,  NONE,      NONE,      NONE,      TB,       NONE,     NONE),
-	MFPR_910(GPIO17,    0x120, GPIO,     KP_DK,  NONE,      NONE,      NONE,      TB,       NONE,     NONE),
-	MFPR_910(GPIO18,    0x124, GPIO,     KP_DK,  NONE,      NONE,      ROT,       NONE,     NONE,     NONE),
-	MFPR_910(GPIO19,    0x128, GPIO,     KP_DK,  NONE,      NONE,      ROT,       NONE,     NONE,     NONE),
-	MFPR_910(GPIO20,    0x12C, GPIO,     SSP1,   NONE,      NONE,      VCXO_OUT,  NONE,     NONE,     NONE),
-	MFPR_910(GPIO21,    0x130, GPIO,     SSP1,   NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO22,    0x134, GPIO,     SSP1,   NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO23,    0x138, GPIO,     SSP1,   NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO24,    0x13C, GPIO,     SSP1,   NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO25,    0x140, GPIO,     GSSP,   NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO26,    0x144, GPIO,     GSSP,   NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO27,    0x148, GPIO,     GSSP,   NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO28,    0x14C, GPIO,     GSSP,   NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO29,    0x150, GPIO,     UART0,  NONE,      NONE,      UART1,     NONE,     NONE,     NONE),
-	MFPR_910(GPIO30,    0x154, GPIO,     UART0,  NONE,      NONE,      UART1,     NONE,     NONE,     NONE),
-	MFPR_910(GPIO31,    0x158, GPIO,     UART0,  NONE,      NONE,      UART1,     NONE,     NONE,     NONE),
-	MFPR_910(GPIO32,    0x15C, GPIO,     UART0,  DAC_ST23,  NONE,      UART1,     NONE,     NONE,     NONE),
-	MFPR_910(GPIO33,    0x160, GPIO,     MMC2,   SSP0,      SSP2,      NONE,      SPI,      NONE,     MMC3),
-	MFPR_910(GPIO34,    0x164, GPIO,     MMC2,   SSP0,      SSP2,      NONE,      SPI,      NONE,     MMC3),
-	MFPR_910(GPIO35,    0x168, GPIO,     MMC2,   SSP0,      SSP2,      NONE,      SPI,      NONE,     MMC3),
-	MFPR_910(GPIO36,    0x16C, GPIO,     MMC2,   SSP0,      SSP2,      NONE,      SPI,      NONE,     MMC3),
-	MFPR_910(GPIO37,    0x170, GPIO,     MMC2,   NONE,      NONE,      NONE,      SPI,      HSL,      NONE),
-	MFPR_910(GPIO38,    0x174, GPIO,     MMC2,   NONE,      NONE,      NONE,      NONE,     HSL,      NONE),
-	MFPR_910(GPIO39,    0x178, GPIO,     MMC2,   NONE,      NONE,      NONE,      NONE,     HSL,      NONE),
-	MFPR_910(GPIO40,    0x17C, GPIO,     MMC2,   NONE,      NONE,      NONE,      NONE,     HSL,      NONE),
-	MFPR_910(GPIO41,    0x180, GPIO,     MMC2,   NONE,      NONE,      NONE,      NONE,     HSL,      NONE),
-	MFPR_910(GPIO42,    0x184, GPIO,     MMC2,   NONE,      NONE,      NONE,      NONE,     HSL,      NONE),
-	MFPR_910(GPIO43,    0x188, GPIO,     UART1,  NONE,      DAC_ST23,  NONE,      DSSP2,    SPI,      UART2),
-	MFPR_910(GPIO44,    0x18C, GPIO,     UART1,  NONE,      EXT_INT,   NONE,      DSSP2,    SPI,      UART2),
-	MFPR_910(GPIO45,    0x190, GPIO,     UART1,  NONE,      EXT_INT,   NONE,      DSSP2,    SPI,      UART2),
-	MFPR_910(GPIO46,    0x194, GPIO,     UART1,  NONE,      EXT_INT,   NONE,      DSSP2,    SPI,      UART2),
-	MFPR_910(GPIO47,    0x198, GPIO,     SSP0,   NONE,      NONE,      NONE,      SSP2,     UART1,    NONE),
-	MFPR_910(GPIO48,    0x19C, GPIO,     SSP0,   NONE,      NONE,      NONE,      SSP2,     UART1,    NONE),
-	MFPR_910(GPIO49,    0x1A0, GPIO,     SSP0,   UART0,     VCXO_REQ,  NONE,      SSP2,     NONE,     MMC3),
-	MFPR_910(GPIO50,    0x1A4, GPIO,     SSP0,   UART0,     VCXO_OUT,  NONE,      SSP2,     NONE,     MMC3),
-	MFPR_910(GPIO51,    0x1A8, GPIO,     UART2,  PWM1,      TWSI,      SSP0,      NONE,     DSSP3,    NONE),
-	MFPR_910(GPIO52,    0x1AC, GPIO,     UART2,  DAC_ST23,  TWSI,      SSP0,      NONE,     DSSP3,    NONE),
-	MFPR_910(GPIO53,    0x1B0, GPIO,     UART2,  TWSI,      NONE,      SSP0,      NONE,     DSSP3,    NONE),
-	MFPR_910(GPIO54,    0x1B4, GPIO,     UART2,  TWSI,      SSP0,      NONE,      NONE,     DSSP3,    NONE),
-	MFPR_910(GPIO55,    0x2F0, TDS,      GPIO,   TB,        NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO56,    0x2F4, TDS,      GPIO,   TB,        NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO57,    0x2F8, TDS,      GPIO,   TB,        NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO58,    0x2FC, TDS,      GPIO,   TB,        NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO59,    0x300, TDS,      GPIO,   TCU_GPOA,  TCU_GPOB,  ONE_WIRE,  NONE,     NONE,     NONE),
-	MFPR_910(GPIO60,    0x304, GPIO,     NONE,   NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO61,    0x308, GPIO,     NONE,   NONE,      NONE,      NONE,      NONE,     NONE,     HSL),
-	MFPR_910(GPIO62,    0x30C, GPIO,     NONE,   NONE,      NONE,      NONE,      NONE,     NONE,     HSL),
-	MFPR_910(GPIO63,    0x310, GPIO,     NONE,   NONE,      NONE,      NONE,      NONE,     NONE,     HSL),
-	MFPR_910(GPIO64,    0x314, GPIO,     SPI2,   NONE,      NONE,      NONE,      NONE,     NONE,     HSL),
-	MFPR_910(GPIO65,    0x318, GPIO,     SPI2,   NONE,      NONE,      NONE,      NONE,     ONE_WIRE, HSL),
-	MFPR_910(GPIO66,    0x31C, GPIO,     NONE,   NONE,      NONE,      NONE,      NONE,     NONE,     HSL),
-	MFPR_910(GPIO67,    0x1B8, GPIO,     CCIC,   SPI,       NONE,      NONE,      ULPI,     NONE,     USIM2),
-	MFPR_910(GPIO68,    0x1BC, GPIO,     CCIC,   SPI,       NONE,      NONE,      ULPI,     NONE,     USIM2),
-	MFPR_910(GPIO69,    0x1C0, GPIO,     CCIC,   SPI,       NONE,      NONE,      ULPI,     NONE,     USIM2),
-	MFPR_910(GPIO70,    0x1C4, GPIO,     CCIC,   SPI,       NONE,      NONE,      ULPI,     NONE,     NONE),
-	MFPR_910(GPIO71,    0x1C8, GPIO,     CCIC,   SPI,       NONE,      NONE,      ULPI,     NONE,     NONE),
-	MFPR_910(GPIO72,    0x1CC, GPIO,     CCIC,   EXT_DMA,   NONE,      NONE,      ULPI,     NONE,     NONE),
-	MFPR_910(GPIO73,    0x1D0, GPIO,     CCIC,   EXT_DMA,   NONE,      NONE,      ULPI,     NONE,     NONE),
-	MFPR_910(GPIO74,    0x1D4, GPIO,     CCIC,   EXT_DMA,   NONE,      NONE,      ULPI,     NONE,     NONE),
-	MFPR_910(GPIO75,    0x1D8, GPIO,     CCIC,   NONE,      NONE,      NONE,      ULPI,     NONE,     NONE),
-	MFPR_910(GPIO76,    0x1DC, GPIO,     CCIC,   NONE,      NONE,      NONE,      ULPI,     NONE,     NONE),
-	MFPR_910(GPIO77,    0x1E0, GPIO,     CCIC,   NONE,      NONE,      NONE,      ULPI,     NONE,     NONE),
-	MFPR_910(GPIO78,    0x1E4, GPIO,     CCIC,   NONE,      NONE,      NONE,      ULPI,     NONE,     NONE),
-	MFPR_910(GPIO79,    0x1E8, GPIO,     TWSI,   NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO80,    0x1EC, GPIO,     TWSI,   NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO81,    0x1F0, GPIO,     LCD,    NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO82,    0x1F4, GPIO,     LCD,    NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO83,    0x1F8, GPIO,     LCD,    NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO84,    0x1FC, GPIO,     LCD,    VCXO_REQ2, NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO85,    0x200, GPIO,     LCD,    NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO86,    0x204, GPIO,     LCD,    VCXO_OUT2, NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO87,    0x208, GPIO,     LCD,    NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO88,    0x20C, GPIO,     LCD,    NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO89,    0x210, GPIO,     LCD,    NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO90,    0x214, GPIO,     LCD,    NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO91,    0x218, GPIO,     LCD,    NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO92,    0x21C, GPIO,     LCD,    NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO93,    0x220, GPIO,     LCD,    NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO94,    0x224, GPIO,     LCD,    NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO95,    0x228, GPIO,     LCD,    NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO96,    0x22C, GPIO,     LCD,    NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO97,    0x230, GPIO,     LCD,    NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO98,    0x234, GPIO,     LCD,    NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO99,    0x0B0, MMC1,     GPIO,   NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO100,   0x238, GPIO,     LCD,    NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO101,   0x23C, GPIO,     LCD,    NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO102,   0x240, GPIO,     LCD,    DSSP2,     SPI,       NONE,      NONE,     NONE,     SPI2),
-	MFPR_910(GPIO103,   0x244, GPIO,     LCD,    DSSP2,     SPI,       NONE,      NONE,     NONE,     SPI2),
-	MFPR_910(GPIO104,   0x248, GPIO,     LCD,    DSSP2,     SPI,       NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO105,   0x24C, GPIO,     LCD,    DSSP2,     SPI,       NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO106,   0x250, GPIO,     LCD,    DSSP3,     ONE_WIRE,  NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO107,   0x254, GPIO,     LCD,    DSSP3,     SPI,       NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO108,   0x258, GPIO,     LCD,    DSSP3,     SPI,       NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO109,   0x25C, GPIO,     LCD,    DSSP3,     SPI,       NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO110,   0x298, GPIO,     NONE,   NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO111,   0x29C, GPIO,     NONE,   DSSP2,     NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO112,   0x2A0, GPIO,     NONE,   DSSP2,     NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO113,   0x2A4, GPIO,     NONE,   DSSP2,     NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO114,   0x2A8, GPIO,     NONE,   DSSP3,     NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO115,   0x2AC, GPIO,     NONE,   DSSP3,     NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO116,   0x2B0, GPIO,     NONE,   DSSP3,     NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO117,   0x0B4, PRI_JTAG, GPIO,   PWM0,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO118,   0x0B8, PRI_JTAG, GPIO,   PWM1,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO119,   0x0BC, PRI_JTAG, GPIO,   PWM2,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO120,   0x0C0, PRI_JTAG, GPIO,   PWM3,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO121,   0x32C, GPIO,     NONE,   NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO122,   0x0C8, RESET,    GPIO,   32K_CLK,   NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO123,   0x0CC, CLK_REQ,  GPIO,   ONE_WIRE,  EXT_DMA,   NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO124,   0x0D0, GPIO,     MN_CLK, DAC_ST23,  NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO125,   0x0D4, VCXO_REQ, GPIO,   NONE,      EXT_INT,   NONE,      NONE,     NONE,     NONE),
-	MFPR_910(GPIO126,   0x06C, GPIO,     SMC,    NONE,      SM_ADDR18, NONE,      EXT_DMA,  NONE,     NONE),
-	MFPR_910(GPIO127,   0x070, GPIO,     SMC,    NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(ND_IO15,   0x004, NAND,     GPIO,   USIM2,     EXT_DMA,   NONE,      NONE,     NONE,     NONE),
-	MFPR_910(ND_IO14,   0x008, NAND,     GPIO,   USIM2,     NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(ND_IO13,   0x00C, NAND,     GPIO,   USIM2,     EXT_INT,   NONE,      NONE,     NONE,     NONE),
-	MFPR_910(ND_IO12,   0x010, NAND,     GPIO,   SSP2,      EXT_INT,   NONE,      NONE,     NONE,     NONE),
-	MFPR_910(ND_IO11,   0x014, NAND,     GPIO,   SSP2,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(ND_IO10,   0x018, NAND,     GPIO,   SSP2,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(ND_IO9,    0x01C, NAND,     GPIO,   SSP2,      NONE,      VCXO_OUT2, NONE,     NONE,     NONE),
-	MFPR_910(ND_IO8,    0x020, NAND,     GPIO,   NONE,      NONE,      PWM3,      NONE,     NONE,     NONE),
-	MFPR_910(ND_IO7,    0x024, NAND,     MMC3,   NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(ND_IO6,    0x028, NAND,     MMC3,   NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(ND_IO5,    0x02C, NAND,     MMC3,   NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(ND_IO4,    0x030, NAND,     MMC3,   NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(ND_IO3,    0x034, NAND,     MMC3,   NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(ND_IO2,    0x038, NAND,     MMC3,   NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(ND_IO1,    0x03C, NAND,     MMC3,   NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(ND_IO0,    0x040, NAND,     MMC3,   NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(ND_NCS0,   0x044, NAND,     GPIO,   NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(ND_NCS1,   0x048, NAND,     GPIO,   NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(SM_NCS0,   0x04C, SMC,      GPIO,   NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(SM_NCS1,   0x050, SMC,      GPIO,   NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(ND_NWE,    0x054, GPIO,     NAND,   NONE,      SM_ADDR20, NONE,      SMC,      NONE,     NONE),
-	MFPR_910(ND_NRE,    0x058, GPIO,     NAND,   NONE,      SMC,       NONE,      EXT_DMA,  NONE,     NONE),
-	MFPR_910(ND_CLE,    0x05C, NAND,     MMC3,   NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(ND_ALE,    0x060, GPIO,     NAND,   NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(SM_SCLK,   0x064, MMC3,     NONE,   NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(ND_RDY0,   0x068, NAND,     GPIO,   NONE,      SMC,       NONE,      NONE,     NONE,     NONE),
-	MFPR_910(SM_ADV,    0x074, SMC,      GPIO,   NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(ND_RDY1,   0x078, NAND,     GPIO,   NONE,      SMC,       NONE,      NONE,     NONE,     NONE),
-	MFPR_910(SM_ADVMUX, 0x07C, SMC,      GPIO,   NONE,      SM_ADDR19, NONE,      NONE,     NONE,     NONE),
-	MFPR_910(SM_RDY,    0x080, SMC,      GPIO,   NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(MMC1_DAT7, 0x084, MMC1,     GPIO,   SEC1_JTAG, TB,        NONE,      NONE,     NONE,     NONE),
-	MFPR_910(MMC1_DAT6, 0x088, MMC1,     GPIO,   SEC1_JTAG, TB,        NONE,      NONE,     NONE,     NONE),
-	MFPR_910(MMC1_DAT5, 0x08C, MMC1,     GPIO,   SEC1_JTAG, TB,        NONE,      NONE,     NONE,     NONE),
-	MFPR_910(MMC1_DAT4, 0x090, MMC1,     GPIO,   NONE,      TB,        NONE,      NONE,     NONE,     NONE),
-	MFPR_910(MMC1_DAT3, 0x094, MMC1,     HSL,    SEC2_JTAG, SSP0,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(MMC1_DAT2, 0x098, MMC1,     HSL,    SEC2_JTAG, SSP2,      SSP0,      NONE,     NONE,     NONE),
-	MFPR_910(MMC1_DAT1, 0x09C, MMC1,     HSL,    SEC2_JTAG, SSP2,      SSP0,      NONE,     NONE,     NONE),
-	MFPR_910(MMC1_DAT0, 0x0A0, MMC1,     HSL,    SEC2_JTAG, SSP2,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(MMC1_CMD,  0x0A4, MMC1,     HSL,    SEC1_JTAG, SSP2,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(MMC1_CLK,  0x0A8, MMC1,     HSL,    SEC2_JTAG, SSP0,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(MMC1_CD,   0x0AC, MMC1,     GPIO,   SEC1_JTAG, NONE,      NONE,      NONE,     NONE,     NONE),
-	MFPR_910(VCXO_OUT,  0x0D8, VCXO_OUT, PWM3,   NONE,      NONE,      NONE,      NONE,     NONE,     NONE),
-};
-
-
-static const unsigned p910_usim2_pin1[] = {GPIO67, GPIO68, GPIO69};
-static const unsigned p910_usim2_pin2[] = {ND_IO15, ND_IO14, ND_IO13};
-static const unsigned p910_mmc1_pin1[] = {MMC1_DAT7, MMC1_DAT6, MMC1_DAT5,
-	MMC1_DAT4, MMC1_DAT3, MMC1_DAT2, MMC1_DAT1, MMC1_DAT0, MMC1_CMD,
-	MMC1_CLK, MMC1_CD, GPIO99};
-static const unsigned p910_mmc2_pin1[] = {GPIO33, GPIO34, GPIO35, GPIO36,
-	GPIO37, GPIO38, GPIO39, GPIO40, GPIO41, GPIO42};
-static const unsigned p910_mmc3_pin1[] = {GPIO33, GPIO34, GPIO35, GPIO36,
-	GPIO49, GPIO50};
-static const unsigned p910_mmc3_pin2[] = {ND_IO7, ND_IO6, ND_IO5, ND_IO4,
-	ND_IO3, ND_IO2, ND_IO1, ND_IO0, ND_CLE, SM_SCLK};
-static const unsigned p910_uart0_pin1[] = {GPIO29, GPIO30, GPIO31, GPIO32};
-static const unsigned p910_uart1_pin1[] = {GPIO47, GPIO48};
-static const unsigned p910_uart1_pin2[] = {GPIO31, GPIO32};
-static const unsigned p910_uart1_pin3[] = {GPIO45, GPIO46};
-static const unsigned p910_uart1_pin4[] = {GPIO29, GPIO30, GPIO31, GPIO32};
-static const unsigned p910_uart1_pin5[] = {GPIO43, GPIO44, GPIO45, GPIO46};
-static const unsigned p910_uart2_pin1[] = {GPIO43, GPIO44};
-static const unsigned p910_uart2_pin2[] = {GPIO51, GPIO52};
-static const unsigned p910_uart2_pin3[] = {GPIO43, GPIO44, GPIO45, GPIO46};
-static const unsigned p910_uart2_pin4[] = {GPIO51, GPIO52, GPIO53, GPIO54};
-static const unsigned p910_twsi_pin1[] = {GPIO51, GPIO52};
-static const unsigned p910_twsi_pin2[] = {GPIO53, GPIO54};
-static const unsigned p910_twsi_pin3[] = {GPIO79, GPIO80};
-static const unsigned p910_ccic_pin1[] = {GPIO67, GPIO68, GPIO69, GPIO70,
-	GPIO71, GPIO72, GPIO73, GPIO74, GPIO75, GPIO76, GPIO77, GPIO78};
-static const unsigned p910_lcd_pin1[] = {GPIO81, GPIO82, GPIO83, GPIO84,
-	GPIO85, GPIO86, GPIO87, GPIO88, GPIO89, GPIO90, GPIO91, GPIO92,
-	GPIO93, GPIO94, GPIO95, GPIO96, GPIO97, GPIO98, GPIO100, GPIO101,
-	GPIO102, GPIO103};
-static const unsigned p910_spi_pin1[] = {GPIO104, GPIO105, GPIO107, GPIO108};
-static const unsigned p910_spi_pin2[] = {GPIO43, GPIO44, GPIO45, GPIO46};
-static const unsigned p910_spi_pin3[] = {GPIO33, GPIO34, GPIO35, GPIO36,
-	GPIO37};
-static const unsigned p910_spi_pin4[] = {GPIO67, GPIO68, GPIO69, GPIO70,
-	GPIO71};
-static const unsigned p910_spi2_pin1[] = {GPIO64, GPIO65};
-static const unsigned p910_spi2_pin2[] = {GPIO102, GPIO103};
-static const unsigned p910_dssp2_pin1[] = {GPIO102, GPIO103, GPIO104, GPIO105};
-static const unsigned p910_dssp2_pin2[] = {GPIO43, GPIO44, GPIO45, GPIO46};
-static const unsigned p910_dssp2_pin3[] = {GPIO111, GPIO112, GPIO113};
-static const unsigned p910_dssp3_pin1[] = {GPIO106, GPIO107, GPIO108, GPIO109};
-static const unsigned p910_dssp3_pin2[] = {GPIO51, GPIO52, GPIO53, GPIO54};
-static const unsigned p910_dssp3_pin3[] = {GPIO114, GPIO115, GPIO116};
-static const unsigned p910_ssp0_pin1[] = {MMC1_DAT3, MMC1_DAT2, MMC1_DAT1,
-	MMC1_CLK};
-static const unsigned p910_ssp0_pin2[] = {GPIO33, GPIO34, GPIO35, GPIO36};
-static const unsigned p910_ssp0_pin3[] = {GPIO47, GPIO48, GPIO49, GPIO50};
-static const unsigned p910_ssp0_pin4[] = {GPIO51, GPIO52, GPIO53, GPIO54};
-static const unsigned p910_ssp1_pin1[] = {GPIO21, GPIO22, GPIO23, GPIO24};
-static const unsigned p910_ssp1_pin2[] = {GPIO20, GPIO21, GPIO22, GPIO23,
-	GPIO24};
-static const unsigned p910_ssp2_pin1[] = {MMC1_DAT2, MMC1_DAT1, MMC1_DAT0,
-	MMC1_CMD};
-static const unsigned p910_ssp2_pin2[] = {GPIO33, GPIO34, GPIO35, GPIO36};
-static const unsigned p910_ssp2_pin3[] = {GPIO47, GPIO48, GPIO49, GPIO50};
-static const unsigned p910_ssp2_pin4[] = {ND_IO12, ND_IO11, ND_IO10, ND_IO9};
-static const unsigned p910_gssp_pin1[] = {GPIO25, GPIO26, GPIO27, GPIO28};
-static const unsigned p910_pwm0_pin1[] = {GPIO117};
-static const unsigned p910_pwm1_pin1[] = {GPIO118};
-static const unsigned p910_pwm1_pin2[] = {GPIO51};
-static const unsigned p910_pwm2_pin1[] = {GPIO119};
-static const unsigned p910_pwm3_pin1[] = {GPIO120};
-static const unsigned p910_pwm3_pin2[] = {ND_IO8};
-static const unsigned p910_pwm3_pin3[] = {VCXO_OUT};
-static const unsigned p910_pri_jtag_pin1[] = {GPIO117, GPIO118, GPIO119,
-	GPIO120};
-static const unsigned p910_sec1_jtag_pin1[] = {MMC1_DAT7, MMC1_DAT6, MMC1_DAT5,
-	MMC1_CMD, MMC1_CD};
-static const unsigned p910_sec2_jtag_pin1[] = {MMC1_DAT3, MMC1_DAT2, MMC1_DAT1,
-	MMC1_DAT0, MMC1_CLK};
-static const unsigned p910_hsl_pin1[] = {GPIO37, GPIO38, GPIO39, GPIO40,
-	GPIO41, GPIO42};
-static const unsigned p910_hsl_pin2[] = {GPIO61, GPIO62, GPIO63, GPIO64,
-	GPIO65, GPIO66};
-static const unsigned p910_hsl_pin3[] = {MMC1_DAT3, MMC1_DAT2, MMC1_DAT1,
-	MMC1_DAT0, MMC1_CMD, MMC1_CLK};
-static const unsigned p910_w1_pin1[] = {GPIO59};
-static const unsigned p910_w1_pin2[] = {GPIO65};
-static const unsigned p910_w1_pin3[] = {GPIO106};
-static const unsigned p910_w1_pin4[] = {GPIO123};
-static const unsigned p910_kpmk_pin1[] = {GPIO0, GPIO1, GPIO2, GPIO3, GPIO4,
-	GPIO5, GPIO6, GPIO7, GPIO8, GPIO9, GPIO10, GPIO11, GPIO12, GPIO13,
-	GPIO14, GPIO15};
-static const unsigned p910_kpmk_pin2[] = {GPIO0, GPIO1, GPIO2, GPIO3, GPIO4,
-	GPIO5, GPIO6, GPIO7, GPIO8, GPIO9, GPIO12};
-static const unsigned p910_kpdk_pin1[] = {GPIO12, GPIO13, GPIO14, GPIO15,
-	GPIO16, GPIO17, GPIO18, GPIO19};
-static const unsigned p910_tds_pin1[] = {GPIO55, GPIO56, GPIO57, GPIO58,
-	GPIO59};
-static const unsigned p910_tds_pin2[] = {GPIO55, GPIO57, GPIO58, GPIO59};
-static const unsigned p910_tb_pin1[] = {GPIO14, GPIO15, GPIO16, GPIO17};
-static const unsigned p910_tb_pin2[] = {GPIO55, GPIO56, GPIO57, GPIO58};
-static const unsigned p910_tb_pin3[] = {MMC1_DAT7, MMC1_DAT6, MMC1_DAT5,
-	MMC1_DAT4};
-static const unsigned p910_ext_dma0_pin1[] = {GPIO72};
-static const unsigned p910_ext_dma0_pin2[] = {ND_IO15};
-static const unsigned p910_ext_dma0_pin3[] = {ND_NRE};
-static const unsigned p910_ext_dma1_pin1[] = {GPIO73};
-static const unsigned p910_ext_dma1_pin2[] = {GPIO123};
-static const unsigned p910_ext_dma1_pin3[] = {GPIO126};
-static const unsigned p910_ext_dma2_pin1[] = {GPIO74};
-static const unsigned p910_ext0_int_pin1[] = {GPIO44};
-static const unsigned p910_ext0_int_pin2[] = {ND_IO13};
-static const unsigned p910_ext1_int_pin1[] = {GPIO45};
-static const unsigned p910_ext1_int_pin2[] = {ND_IO12};
-static const unsigned p910_ext2_int_pin1[] = {GPIO46};
-static const unsigned p910_ext2_int_pin2[] = {GPIO125};
-static const unsigned p910_dac_st23_pin1[] = {GPIO32};
-static const unsigned p910_dac_st23_pin2[] = {GPIO43};
-static const unsigned p910_dac_st23_pin3[] = {GPIO52};
-static const unsigned p910_dac_st23_pin4[] = {GPIO124};
-static const unsigned p910_vcxo_out_pin1[] = {GPIO50};
-static const unsigned p910_vcxo_out_pin2[] = {VCXO_OUT};
-static const unsigned p910_vcxo_out_pin3[] = {GPIO20};
-static const unsigned p910_vcxo_req_pin1[] = {GPIO49};
-static const unsigned p910_vcxo_req_pin2[] = {GPIO125};
-static const unsigned p910_vcxo_out2_pin1[] = {GPIO86};
-static const unsigned p910_vcxo_out2_pin2[] = {ND_IO9};
-static const unsigned p910_vcxo_req2_pin1[] = {GPIO84};
-static const unsigned p910_ulpi_pin1[] = {GPIO67, GPIO68, GPIO69, GPIO70,
-	GPIO71, GPIO72, GPIO73, GPIO74, GPIO75, GPIO76, GPIO77, GPIO78};
-static const unsigned p910_nand_pin1[] = {ND_IO15, ND_IO14, ND_IO13, ND_IO12,
-	ND_IO11, ND_IO10, ND_IO9, ND_IO8, ND_IO7, ND_IO6, ND_IO5, ND_IO4,
-	ND_IO3, ND_IO2, ND_IO1, ND_IO0, ND_NCS0, ND_NWE, ND_NRE, ND_CLE,
-	ND_ALE, ND_RDY0};
-static const unsigned p910_gpio0_pin1[] = {GPIO0};
-static const unsigned p910_gpio0_pin2[] = {SM_ADV};
-static const unsigned p910_gpio1_pin1[] = {GPIO1};
-static const unsigned p910_gpio1_pin2[] = {ND_RDY1};
-static const unsigned p910_gpio2_pin1[] = {GPIO2};
-static const unsigned p910_gpio2_pin2[] = {SM_ADVMUX};
-static const unsigned p910_gpio3_pin1[] = {GPIO3};
-static const unsigned p910_gpio3_pin2[] = {SM_RDY};
-static const unsigned p910_gpio20_pin1[] = {GPIO20};
-static const unsigned p910_gpio20_pin2[] = {ND_IO15};
-static const unsigned p910_gpio20_pin3[] = {MMC1_DAT6};
-static const unsigned p910_gpio21_pin1[] = {GPIO21};
-static const unsigned p910_gpio21_pin2[] = {ND_IO14};
-static const unsigned p910_gpio21_pin3[] = {MMC1_DAT5};
-static const unsigned p910_gpio22_pin1[] = {GPIO22};
-static const unsigned p910_gpio22_pin2[] = {ND_IO13};
-static const unsigned p910_gpio22_pin3[] = {MMC1_DAT4};
-static const unsigned p910_gpio23_pin1[] = {GPIO23};
-static const unsigned p910_gpio23_pin2[] = {ND_IO12};
-static const unsigned p910_gpio23_pin3[] = {MMC1_CD};
-static const unsigned p910_gpio24_pin1[] = {GPIO24};
-static const unsigned p910_gpio24_pin2[] = {ND_IO11};
-static const unsigned p910_gpio24_pin3[] = {MMC1_DAT7};
-static const unsigned p910_gpio25_pin1[] = {GPIO25};
-static const unsigned p910_gpio25_pin2[] = {ND_IO10};
-static const unsigned p910_gpio26_pin1[] = {GPIO26};
-static const unsigned p910_gpio26_pin2[] = {ND_IO9};
-static const unsigned p910_gpio27_pin1[] = {GPIO27};
-static const unsigned p910_gpio27_pin2[] = {ND_IO8};
-static const unsigned p910_gpio85_pin1[] = {GPIO85};
-static const unsigned p910_gpio85_pin2[] = {ND_NCS0};
-static const unsigned p910_gpio86_pin1[] = {GPIO86};
-static const unsigned p910_gpio86_pin2[] = {ND_NCS1};
-static const unsigned p910_gpio87_pin1[] = {GPIO87};
-static const unsigned p910_gpio87_pin2[] = {SM_NCS0};
-static const unsigned p910_gpio88_pin1[] = {GPIO88};
-static const unsigned p910_gpio88_pin2[] = {SM_NCS1};
-static const unsigned p910_gpio89_pin1[] = {GPIO89};
-static const unsigned p910_gpio89_pin2[] = {ND_NWE};
-static const unsigned p910_gpio90_pin1[] = {GPIO90};
-static const unsigned p910_gpio90_pin2[] = {ND_NRE};
-static const unsigned p910_gpio91_pin1[] = {GPIO91};
-static const unsigned p910_gpio91_pin2[] = {ND_ALE};
-static const unsigned p910_gpio92_pin1[] = {GPIO92};
-static const unsigned p910_gpio92_pin2[] = {ND_RDY0};
-
-static struct pxa3xx_pin_group pxa910_grps[] = {
-	GRP_910("usim2 3p1", USIM2, p910_usim2_pin1),
-	GRP_910("usim2 3p2", USIM2, p910_usim2_pin2),
-	GRP_910("mmc1 12p", MMC1, p910_mmc1_pin1),
-	GRP_910("mmc2 10p", MMC2, p910_mmc2_pin1),
-	GRP_910("mmc3 6p", MMC3, p910_mmc3_pin1),
-	GRP_910("mmc3 10p", MMC3, p910_mmc3_pin2),
-	GRP_910("uart0 4p", UART0, p910_uart0_pin1),
-	GRP_910("uart1 2p1", UART1, p910_uart1_pin1),
-	GRP_910("uart1 2p2", UART1, p910_uart1_pin2),
-	GRP_910("uart1 2p3", UART1, p910_uart1_pin3),
-	GRP_910("uart1 4p4", UART1, p910_uart1_pin4),
-	GRP_910("uart1 4p5", UART1, p910_uart1_pin5),
-	GRP_910("uart2 2p1", UART2, p910_uart2_pin1),
-	GRP_910("uart2 2p2", UART2, p910_uart2_pin2),
-	GRP_910("uart2 4p3", UART2, p910_uart2_pin3),
-	GRP_910("uart2 4p4", UART2, p910_uart2_pin4),
-	GRP_910("twsi 2p1", TWSI, p910_twsi_pin1),
-	GRP_910("twsi 2p2", TWSI, p910_twsi_pin2),
-	GRP_910("twsi 2p3", TWSI, p910_twsi_pin3),
-	GRP_910("ccic", CCIC, p910_ccic_pin1),
-	GRP_910("lcd", LCD, p910_lcd_pin1),
-	GRP_910("spi 4p1", SPI, p910_spi_pin1),
-	GRP_910("spi 4p2", SPI, p910_spi_pin2),
-	GRP_910("spi 5p3", SPI, p910_spi_pin3),
-	GRP_910("spi 5p4", SPI, p910_spi_pin4),
-	GRP_910("dssp2 4p1", DSSP2, p910_dssp2_pin1),
-	GRP_910("dssp2 4p2", DSSP2, p910_dssp2_pin2),
-	GRP_910("dssp2 3p3", DSSP2, p910_dssp2_pin3),
-	GRP_910("dssp3 4p1", DSSP3, p910_dssp3_pin1),
-	GRP_910("dssp3 4p2", DSSP3, p910_dssp3_pin2),
-	GRP_910("dssp3 3p3", DSSP3, p910_dssp3_pin3),
-	GRP_910("ssp0 4p1", SSP0, p910_ssp0_pin1),
-	GRP_910("ssp0 4p2", SSP0, p910_ssp0_pin2),
-	GRP_910("ssp0 4p3", SSP0, p910_ssp0_pin3),
-	GRP_910("ssp0 4p4", SSP0, p910_ssp0_pin4),
-	GRP_910("ssp1 4p1", SSP1, p910_ssp1_pin1),
-	GRP_910("ssp1 5p2", SSP1, p910_ssp1_pin2),
-	GRP_910("ssp2 4p1", SSP2, p910_ssp2_pin1),
-	GRP_910("ssp2 4p2", SSP2, p910_ssp2_pin2),
-	GRP_910("ssp2 4p3", SSP2, p910_ssp2_pin3),
-	GRP_910("ssp2 4p4", SSP2, p910_ssp2_pin4),
-	GRP_910("gssp", GSSP, p910_gssp_pin1),
-	GRP_910("pwm0", PWM0, p910_pwm0_pin1),
-	GRP_910("pwm1-1", PWM1, p910_pwm1_pin1),
-	GRP_910("pwm1-2", PWM1, p910_pwm1_pin2),
-	GRP_910("pwm2", PWM2, p910_pwm2_pin1),
-	GRP_910("pwm3-1", PWM3, p910_pwm3_pin1),
-	GRP_910("pwm3-2", PWM3, p910_pwm3_pin2),
-	GRP_910("pwm3-3", PWM3, p910_pwm3_pin3),
-	GRP_910("pri jtag", PRI_JTAG, p910_pri_jtag_pin1),
-	GRP_910("sec1 jtag", SEC1_JTAG, p910_sec1_jtag_pin1),
-	GRP_910("sec2 jtag", SEC2_JTAG, p910_sec2_jtag_pin1),
-	GRP_910("hsl 6p1", HSL, p910_hsl_pin1),
-	GRP_910("hsl 6p2", HSL, p910_hsl_pin2),
-	GRP_910("hsl 6p3", HSL, p910_hsl_pin3),
-	GRP_910("w1-1", ONE_WIRE, p910_w1_pin1),
-	GRP_910("w1-2", ONE_WIRE, p910_w1_pin2),
-	GRP_910("w1-3", ONE_WIRE, p910_w1_pin3),
-	GRP_910("w1-4", ONE_WIRE, p910_w1_pin4),
-	GRP_910("kpmk 16p1", KP_MK, p910_kpmk_pin1),
-	GRP_910("kpmk 11p2", KP_MK, p910_kpmk_pin2),
-	GRP_910("kpdk 8p1", KP_DK, p910_kpdk_pin1),
-	GRP_910("tds 5p1", TDS, p910_tds_pin1),
-	GRP_910("tds 4p2", TDS, p910_tds_pin2),
-	GRP_910("tb 4p1", TB, p910_tb_pin1),
-	GRP_910("tb 4p2", TB, p910_tb_pin2),
-	GRP_910("tb 4p3", TB, p910_tb_pin3),
-	GRP_910("ext dma0-1", EXT_DMA, p910_ext_dma0_pin1),
-	GRP_910("ext dma0-2", EXT_DMA, p910_ext_dma0_pin2),
-	GRP_910("ext dma0-3", EXT_DMA, p910_ext_dma0_pin3),
-	GRP_910("ext dma1-1", EXT_DMA, p910_ext_dma1_pin1),
-	GRP_910("ext dma1-2", EXT_DMA, p910_ext_dma1_pin2),
-	GRP_910("ext dma1-3", EXT_DMA, p910_ext_dma1_pin3),
-	GRP_910("ext dma2", EXT_DMA, p910_ext_dma2_pin1),
-	GRP_910("ext0 int-1", EXT_INT, p910_ext0_int_pin1),
-	GRP_910("ext0 int-2", EXT_INT, p910_ext0_int_pin2),
-	GRP_910("ext1 int-1", EXT_INT, p910_ext1_int_pin1),
-	GRP_910("ext1 int-2", EXT_INT, p910_ext1_int_pin2),
-	GRP_910("ext2 int-1", EXT_INT, p910_ext2_int_pin1),
-	GRP_910("ext2 int-2", EXT_INT, p910_ext2_int_pin2),
-	GRP_910("dac st23-1", DAC_ST23, p910_dac_st23_pin1),
-	GRP_910("dac st23-2", DAC_ST23, p910_dac_st23_pin2),
-	GRP_910("dac st23-3", DAC_ST23, p910_dac_st23_pin3),
-	GRP_910("dac st23-4", DAC_ST23, p910_dac_st23_pin4),
-	GRP_910("vcxo out-1", VCXO_OUT, p910_vcxo_out_pin1),
-	GRP_910("vcxo out-2", VCXO_OUT, p910_vcxo_out_pin2),
-	GRP_910("vcxo out-3", VCXO_OUT, p910_vcxo_out_pin3),
-	GRP_910("vcxo req-1", VCXO_REQ, p910_vcxo_req_pin1),
-	GRP_910("vcxo req-2", VCXO_REQ, p910_vcxo_req_pin2),
-	GRP_910("vcxo out2-1", VCXO_OUT2, p910_vcxo_out2_pin1),
-	GRP_910("vcxo out2-2", VCXO_OUT2, p910_vcxo_out2_pin2),
-	GRP_910("vcxo req2", VCXO_REQ2, p910_vcxo_req2_pin1),
-	GRP_910("ulpi", ULPI, p910_ulpi_pin1),
-	GRP_910("nand", NAND, p910_nand_pin1),
-	GRP_910("gpio0-1", GPIO, p910_gpio0_pin1),
-	GRP_910("gpio0-2", GPIO, p910_gpio0_pin2),
-	GRP_910("gpio1-1", GPIO, p910_gpio1_pin1),
-	GRP_910("gpio1-2", GPIO, p910_gpio1_pin2),
-	GRP_910("gpio2-1", GPIO, p910_gpio2_pin1),
-	GRP_910("gpio2-2", GPIO, p910_gpio2_pin2),
-	GRP_910("gpio3-1", GPIO, p910_gpio3_pin1),
-	GRP_910("gpio3-2", GPIO, p910_gpio3_pin2),
-	GRP_910("gpio20-1", GPIO, p910_gpio20_pin1),
-	GRP_910("gpio20-2", GPIO, p910_gpio20_pin2),
-	GRP_910("gpio21-1", GPIO, p910_gpio21_pin1),
-	GRP_910("gpio21-2", GPIO, p910_gpio21_pin2),
-	GRP_910("gpio22-1", GPIO, p910_gpio22_pin1),
-	GRP_910("gpio22-2", GPIO, p910_gpio22_pin2),
-	GRP_910("gpio23-1", GPIO, p910_gpio23_pin1),
-	GRP_910("gpio23-2", GPIO, p910_gpio23_pin2),
-	GRP_910("gpio24-1", GPIO, p910_gpio24_pin1),
-	GRP_910("gpio24-2", GPIO, p910_gpio24_pin2),
-	GRP_910("gpio25-1", GPIO, p910_gpio25_pin1),
-	GRP_910("gpio25-2", GPIO, p910_gpio25_pin2),
-	GRP_910("gpio26-1", GPIO, p910_gpio26_pin1),
-	GRP_910("gpio26-2", GPIO, p910_gpio26_pin2),
-	GRP_910("gpio27-1", GPIO, p910_gpio27_pin1),
-	GRP_910("gpio27-2", GPIO, p910_gpio27_pin2),
-	GRP_910("gpio85-1", GPIO, p910_gpio85_pin1),
-	GRP_910("gpio85-2", GPIO, p910_gpio85_pin2),
-	GRP_910("gpio86-1", GPIO, p910_gpio86_pin1),
-	GRP_910("gpio86-2", GPIO, p910_gpio86_pin2),
-	GRP_910("gpio87-1", GPIO, p910_gpio87_pin1),
-	GRP_910("gpio87-2", GPIO, p910_gpio87_pin2),
-	GRP_910("gpio88-1", GPIO, p910_gpio88_pin1),
-	GRP_910("gpio88-2", GPIO, p910_gpio88_pin2),
-	GRP_910("gpio89-1", GPIO, p910_gpio89_pin1),
-	GRP_910("gpio89-2", GPIO, p910_gpio89_pin2),
-	GRP_910("gpio90-1", GPIO, p910_gpio90_pin1),
-	GRP_910("gpio90-2", GPIO, p910_gpio90_pin2),
-	GRP_910("gpio91-1", GPIO, p910_gpio91_pin1),
-	GRP_910("gpio91-2", GPIO, p910_gpio91_pin2),
-	GRP_910("gpio92-1", GPIO, p910_gpio92_pin1),
-	GRP_910("gpio92-2", GPIO, p910_gpio92_pin2),
-};
-
-static const char * const p910_usim2_grps[] = {"usim2 3p1", "usim2 3p2"};
-static const char * const p910_mmc1_grps[] = {"mmc1 12p"};
-static const char * const p910_mmc2_grps[] = {"mmc2 10p"};
-static const char * const p910_mmc3_grps[] = {"mmc3 6p", "mmc3 10p"};
-static const char * const p910_uart0_grps[] = {"uart0 4p"};
-static const char * const p910_uart1_grps[] = {"uart1 2p1", "uart1 2p2",
-	"uart1 2p3", "uart1 4p4", "uart1 4p5"};
-static const char * const p910_uart2_grps[] = {"uart2 2p1", "uart2 2p2",
-	"uart2 4p3", "uart2 4p4"};
-static const char * const p910_twsi_grps[] = {"twsi 2p1", "twsi 2p2",
-	"twsi 2p3"};
-static const char * const p910_ccic_grps[] = {"ccic"};
-static const char * const p910_lcd_grps[] = {"lcd"};
-static const char * const p910_spi_grps[] = {"spi 4p1", "spi 4p2", "spi 5p3",
-	"spi 5p4"};
-static const char * const p910_dssp2_grps[] = {"dssp2 4p1", "dssp2 4p2",
-	"dssp2 3p3"};
-static const char * const p910_dssp3_grps[] = {"dssp3 4p1", "dssp3 4p2",
-	"dssp3 3p3"};
-static const char * const p910_ssp0_grps[] = {"ssp0 4p1", "ssp0 4p2",
-	"ssp0 4p3", "ssp0 4p4"};
-static const char * const p910_ssp1_grps[] = {"ssp1 4p1", "ssp1 5p2"};
-static const char * const p910_ssp2_grps[] = {"ssp2 4p1", "ssp2 4p2",
-	"ssp2 4p3", "ssp2 4p4"};
-static const char * const p910_gssp_grps[] = {"gssp"};
-static const char * const p910_pwm0_grps[] = {"pwm0"};
-static const char * const p910_pwm1_grps[] = {"pwm1-1", "pwm1-2"};
-static const char * const p910_pwm2_grps[] = {"pwm2"};
-static const char * const p910_pwm3_grps[] = {"pwm3-1", "pwm3-2", "pwm3-3"};
-static const char * const p910_pri_jtag_grps[] = {"pri jtag"};
-static const char * const p910_sec1_jtag_grps[] = {"sec1 jtag"};
-static const char * const p910_sec2_jtag_grps[] = {"sec2 jtag"};
-static const char * const p910_hsl_grps[] = {"hsl 6p1", "hsl 6p2", "hsl 6p3"};
-static const char * const p910_w1_grps[] = {"w1-1", "w1-2", "w1-3", "w1-4"};
-static const char * const p910_kpmk_grps[] = {"kpmk 16p1", "kpmk 11p2"};
-static const char * const p910_kpdk_grps[] = {"kpdk 8p1"};
-static const char * const p910_tds_grps[] = {"tds 5p1", "tds 4p2"};
-static const char * const p910_tb_grps[] = {"tb 4p1", "tb 4p2", "tb 4p3"};
-static const char * const p910_dma0_grps[] = {"ext dma0-1", "ext dma0-2",
-	"ext dma0-3"};
-static const char * const p910_dma1_grps[] = {"ext dma1-1", "ext dma1-2",
-	"ext dma1-3"};
-static const char * const p910_dma2_grps[] = {"ext dma2"};
-static const char * const p910_int0_grps[] = {"ext0 int-1", "ext0 int-2"};
-static const char * const p910_int1_grps[] = {"ext1 int-1", "ext1 int-2"};
-static const char * const p910_int2_grps[] = {"ext2 int-1", "ext2 int-2"};
-static const char * const p910_dac_st23_grps[] = {"dac st23-1", "dac st23-2",
-	"dac st23-3", "dac st23-4"};
-static const char * const p910_vcxo_out_grps[] = {"vcxo out-1", "vcxo out-2",
-	"vcxo out-3"};
-static const char * const p910_vcxo_req_grps[] = {"vcxo req-1", "vcxo req-2"};
-static const char * const p910_vcxo_out2_grps[] = {"vcxo out2-1",
-	"vcxo out2-2"};
-static const char * const p910_vcxo_req2_grps[] = {"vcxo req2"};
-static const char * const p910_ulpi_grps[] = {"ulpi"};
-static const char * const p910_nand_grps[] = {"nand"};
-static const char * const p910_gpio0_grps[] = {"gpio0-1", "gpio0-2"};
-static const char * const p910_gpio1_grps[] = {"gpio1-1", "gpio1-2"};
-static const char * const p910_gpio2_grps[] = {"gpio2-1", "gpio2-2"};
-static const char * const p910_gpio3_grps[] = {"gpio3-1", "gpio3-2"};
-static const char * const p910_gpio20_grps[] = {"gpio20-1", "gpio20-2"};
-static const char * const p910_gpio21_grps[] = {"gpio21-1", "gpio21-2"};
-static const char * const p910_gpio22_grps[] = {"gpio22-1", "gpio22-2"};
-static const char * const p910_gpio23_grps[] = {"gpio23-1", "gpio23-2"};
-static const char * const p910_gpio24_grps[] = {"gpio24-1", "gpio24-2"};
-static const char * const p910_gpio25_grps[] = {"gpio25-1", "gpio25-2"};
-static const char * const p910_gpio26_grps[] = {"gpio26-1", "gpio26-2"};
-static const char * const p910_gpio27_grps[] = {"gpio27-1", "gpio27-2"};
-static const char * const p910_gpio85_grps[] = {"gpio85-1", "gpio85-2"};
-static const char * const p910_gpio86_grps[] = {"gpio86-1", "gpio86-2"};
-static const char * const p910_gpio87_grps[] = {"gpio87-1", "gpio87-2"};
-static const char * const p910_gpio88_grps[] = {"gpio88-1", "gpio88-2"};
-static const char * const p910_gpio89_grps[] = {"gpio89-1", "gpio89-2"};
-static const char * const p910_gpio90_grps[] = {"gpio90-1", "gpio90-2"};
-static const char * const p910_gpio91_grps[] = {"gpio91-1", "gpio91-2"};
-static const char * const p910_gpio92_grps[] = {"gpio92-1", "gpio92-2"};
-
-static struct pxa3xx_pmx_func pxa910_funcs[] = {
-	{"usim2",	ARRAY_AND_SIZE(p910_usim2_grps)},
-	{"mmc1",	ARRAY_AND_SIZE(p910_mmc1_grps)},
-	{"mmc2",	ARRAY_AND_SIZE(p910_mmc2_grps)},
-	{"mmc3",	ARRAY_AND_SIZE(p910_mmc3_grps)},
-	{"uart0",	ARRAY_AND_SIZE(p910_uart0_grps)},
-	{"uart1",	ARRAY_AND_SIZE(p910_uart1_grps)},
-	{"uart2",	ARRAY_AND_SIZE(p910_uart2_grps)},
-	{"twsi",	ARRAY_AND_SIZE(p910_twsi_grps)},
-	{"ccic",	ARRAY_AND_SIZE(p910_ccic_grps)},
-	{"lcd",		ARRAY_AND_SIZE(p910_lcd_grps)},
-	{"spi",		ARRAY_AND_SIZE(p910_spi_grps)},
-	{"dssp2",	ARRAY_AND_SIZE(p910_dssp2_grps)},
-	{"dssp3",	ARRAY_AND_SIZE(p910_dssp3_grps)},
-	{"ssp0",	ARRAY_AND_SIZE(p910_ssp0_grps)},
-	{"ssp1",	ARRAY_AND_SIZE(p910_ssp1_grps)},
-	{"ssp2",	ARRAY_AND_SIZE(p910_ssp2_grps)},
-	{"gssp",	ARRAY_AND_SIZE(p910_gssp_grps)},
-	{"pwm0",	ARRAY_AND_SIZE(p910_pwm0_grps)},
-	{"pwm1",	ARRAY_AND_SIZE(p910_pwm1_grps)},
-	{"pwm2",	ARRAY_AND_SIZE(p910_pwm2_grps)},
-	{"pwm3",	ARRAY_AND_SIZE(p910_pwm3_grps)},
-	{"pri_jtag",	ARRAY_AND_SIZE(p910_pri_jtag_grps)},
-	{"sec1_jtag",	ARRAY_AND_SIZE(p910_sec1_jtag_grps)},
-	{"sec2_jtag",	ARRAY_AND_SIZE(p910_sec2_jtag_grps)},
-	{"hsl",		ARRAY_AND_SIZE(p910_hsl_grps)},
-	{"w1",		ARRAY_AND_SIZE(p910_w1_grps)},
-	{"kpmk",	ARRAY_AND_SIZE(p910_kpmk_grps)},
-	{"kpdk",	ARRAY_AND_SIZE(p910_kpdk_grps)},
-	{"tds",		ARRAY_AND_SIZE(p910_tds_grps)},
-	{"tb",		ARRAY_AND_SIZE(p910_tb_grps)},
-	{"dma0",	ARRAY_AND_SIZE(p910_dma0_grps)},
-	{"dma1",	ARRAY_AND_SIZE(p910_dma1_grps)},
-	{"dma2",	ARRAY_AND_SIZE(p910_dma2_grps)},
-	{"int0",	ARRAY_AND_SIZE(p910_int0_grps)},
-	{"int1",	ARRAY_AND_SIZE(p910_int1_grps)},
-	{"int2",	ARRAY_AND_SIZE(p910_int2_grps)},
-	{"dac_st23",	ARRAY_AND_SIZE(p910_dac_st23_grps)},
-	{"vcxo_out",	ARRAY_AND_SIZE(p910_vcxo_out_grps)},
-	{"vcxo_req",	ARRAY_AND_SIZE(p910_vcxo_req_grps)},
-	{"vcxo_out2",	ARRAY_AND_SIZE(p910_vcxo_out2_grps)},
-	{"vcxo_req2",	ARRAY_AND_SIZE(p910_vcxo_req2_grps)},
-	{"ulpi",	ARRAY_AND_SIZE(p910_ulpi_grps)},
-	{"nand",	ARRAY_AND_SIZE(p910_nand_grps)},
-	{"gpio0",	ARRAY_AND_SIZE(p910_gpio0_grps)},
-	{"gpio1",	ARRAY_AND_SIZE(p910_gpio1_grps)},
-	{"gpio2",	ARRAY_AND_SIZE(p910_gpio2_grps)},
-	{"gpio3",	ARRAY_AND_SIZE(p910_gpio3_grps)},
-	{"gpio20",	ARRAY_AND_SIZE(p910_gpio20_grps)},
-	{"gpio21",	ARRAY_AND_SIZE(p910_gpio21_grps)},
-	{"gpio22",	ARRAY_AND_SIZE(p910_gpio22_grps)},
-	{"gpio23",	ARRAY_AND_SIZE(p910_gpio23_grps)},
-	{"gpio24",	ARRAY_AND_SIZE(p910_gpio24_grps)},
-	{"gpio25",	ARRAY_AND_SIZE(p910_gpio25_grps)},
-	{"gpio26",	ARRAY_AND_SIZE(p910_gpio26_grps)},
-	{"gpio27",	ARRAY_AND_SIZE(p910_gpio27_grps)},
-	{"gpio85",	ARRAY_AND_SIZE(p910_gpio85_grps)},
-	{"gpio86",	ARRAY_AND_SIZE(p910_gpio86_grps)},
-	{"gpio87",	ARRAY_AND_SIZE(p910_gpio87_grps)},
-	{"gpio88",	ARRAY_AND_SIZE(p910_gpio88_grps)},
-	{"gpio89",	ARRAY_AND_SIZE(p910_gpio89_grps)},
-	{"gpio90",	ARRAY_AND_SIZE(p910_gpio90_grps)},
-	{"gpio91",	ARRAY_AND_SIZE(p910_gpio91_grps)},
-	{"gpio92",	ARRAY_AND_SIZE(p910_gpio92_grps)},
-};
-
-static struct pinctrl_desc pxa910_pctrl_desc = {
-	.name		= "pxa910-pinctrl",
-	.owner		= THIS_MODULE,
-};
-
-static struct pxa3xx_pinmux_info pxa910_info = {
-	.mfp		= pxa910_mfp,
-	.num_mfp	= ARRAY_SIZE(pxa910_mfp),
-	.grps		= pxa910_grps,
-	.num_grps	= ARRAY_SIZE(pxa910_grps),
-	.funcs		= pxa910_funcs,
-	.num_funcs	= ARRAY_SIZE(pxa910_funcs),
-	.num_gpio	= 128,
-	.desc		= &pxa910_pctrl_desc,
-	.pads		= pxa910_pads,
-	.num_pads	= ARRAY_SIZE(pxa910_pads),
-
-	.cputype	= PINCTRL_PXA910,
-	.ds_mask	= PXA910_DS_MASK,
-	.ds_shift	= PXA910_DS_SHIFT,
-};
-
-static int pxa910_pinmux_probe(struct platform_device *pdev)
-{
-	return pxa3xx_pinctrl_register(pdev, &pxa910_info);
-}
-
-static int pxa910_pinmux_remove(struct platform_device *pdev)
-{
-	return pxa3xx_pinctrl_unregister(pdev);
-}
-
-static struct platform_driver pxa910_pinmux_driver = {
-	.driver = {
-		.name	= "pxa910-pinmux",
-		.owner	= THIS_MODULE,
-	},
-	.probe	= pxa910_pinmux_probe,
-	.remove	= pxa910_pinmux_remove,
-};
-
-static int __init pxa910_pinmux_init(void)
-{
-	return platform_driver_register(&pxa910_pinmux_driver);
-}
-core_initcall_sync(pxa910_pinmux_init);
-
-static void __exit pxa910_pinmux_exit(void)
-{
-	platform_driver_unregister(&pxa910_pinmux_driver);
-}
-module_exit(pxa910_pinmux_exit);
-
-MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
-MODULE_DESCRIPTION("PXA3xx pin control driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/pinctrl-samsung.c b/drivers/pinctrl/pinctrl-samsung.c
index f206df1..fe7ace2 100644
--- a/drivers/pinctrl/pinctrl-samsung.c
+++ b/drivers/pinctrl/pinctrl-samsung.c
@@ -214,7 +214,7 @@ static void samsung_dt_free_map(struct pinctrl_dev *pctldev,
 }
 
 /* list of pinctrl callbacks for the pinctrl core */
-static struct pinctrl_ops samsung_pctrl_ops = {
+static const struct pinctrl_ops samsung_pctrl_ops = {
 	.get_groups_count	= samsung_get_group_count,
 	.get_group_name		= samsung_get_group_name,
 	.get_group_pins		= samsung_get_group_pins,
@@ -357,7 +357,7 @@ static int samsung_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
 }
 
 /* list of pinmux callbacks for the pinmux vertical in pinctrl core */
-static struct pinmux_ops samsung_pinmux_ops = {
+static const struct pinmux_ops samsung_pinmux_ops = {
 	.get_functions_count	= samsung_get_functions_count,
 	.get_function_name	= samsung_pinmux_get_fname,
 	.get_function_groups	= samsung_pinmux_get_groups,
@@ -468,7 +468,7 @@ static int samsung_pinconf_group_get(struct pinctrl_dev *pctldev,
 }
 
 /* list of pinconfig callbacks for pinconfig vertical in the pinctrl code */
-static struct pinconf_ops samsung_pinconf_ops = {
+static const struct pinconf_ops samsung_pinconf_ops = {
 	.pin_config_get		= samsung_pinconf_get,
 	.pin_config_set		= samsung_pinconf_set,
 	.pin_config_group_get	= samsung_pinconf_group_get,
@@ -948,6 +948,8 @@ static const struct of_device_id samsung_pinctrl_dt_match[] = {
 		.data = (void *)exynos4210_pin_ctrl },
 	{ .compatible = "samsung,exynos4x12-pinctrl",
 		.data = (void *)exynos4x12_pin_ctrl },
+	{ .compatible = "samsung,exynos5250-pinctrl",
+		.data = (void *)exynos5250_pin_ctrl },
 	{},
 };
 MODULE_DEVICE_TABLE(of, samsung_pinctrl_dt_match);
diff --git a/drivers/pinctrl/pinctrl-samsung.h b/drivers/pinctrl/pinctrl-samsung.h
index e2d4e67..ee964aa 100644
--- a/drivers/pinctrl/pinctrl-samsung.h
+++ b/drivers/pinctrl/pinctrl-samsung.h
@@ -237,5 +237,6 @@ struct samsung_pmx_func {
 /* list of all exported SoC specific data */
 extern struct samsung_pin_ctrl exynos4210_pin_ctrl[];
 extern struct samsung_pin_ctrl exynos4x12_pin_ctrl[];
+extern struct samsung_pin_ctrl exynos5250_pin_ctrl[];
 
 #endif /* __PINCTRL_SAMSUNG_H */
diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
index 5c32e88..5f2d2bf 100644
--- a/drivers/pinctrl/pinctrl-single.c
+++ b/drivers/pinctrl/pinctrl-single.c
@@ -22,8 +22,10 @@
 
 #include <linux/pinctrl/pinctrl.h>
 #include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/pinconf-generic.h>
 
 #include "core.h"
+#include "pinconf.h"
 
 #define DRIVER_NAME			"pinctrl-single"
 #define PCS_MUX_PINS_NAME		"pinctrl-single,pins"
@@ -59,6 +61,33 @@ struct pcs_func_vals {
 };
 
 /**
+ * struct pcs_conf_vals - pinconf parameter, pinconf register offset
+ * and value, enable, disable, mask
+ * @param:	config parameter
+ * @val:	user input bits in the pinconf register
+ * @enable:	enable bits in the pinconf register
+ * @disable:	disable bits in the pinconf register
+ * @mask:	mask bits in the register value
+ */
+struct pcs_conf_vals {
+	enum pin_config_param param;
+	unsigned val;
+	unsigned enable;
+	unsigned disable;
+	unsigned mask;
+};
+
+/**
+ * struct pcs_conf_type - pinconf property name, pinconf param pair
+ * @name:	property name in DTS file
+ * @param:	config parameter
+ */
+struct pcs_conf_type {
+	const char *name;
+	enum pin_config_param param;
+};
+
+/**
  * struct pcs_function - pinctrl function
  * @name:	pinctrl function name
  * @vals:	register and vals array
@@ -73,6 +102,22 @@ struct pcs_function {
 	unsigned nvals;
 	const char **pgnames;
 	int npgnames;
+	struct pcs_conf_vals *conf;
+	int nconfs;
+	struct list_head node;
+};
+
+/**
+ * struct pcs_gpiofunc_range - pin ranges with same mux value of gpio function
+ * @offset:	offset base of pins
+ * @npins:	number pins with the same mux value of gpio function
+ * @gpiofunc:	mux value of gpio function
+ * @node:	list node
+ */
+struct pcs_gpiofunc_range {
+	unsigned offset;
+	unsigned npins;
+	unsigned gpiofunc;
 	struct list_head node;
 };
 
@@ -117,12 +162,14 @@ struct pcs_name {
  * @fshift:	function register shift
  * @foff:	value to turn mux off
  * @fmax:	max number of functions in fmask
+ * @is_pinconf:	whether supports pinconf
  * @names:	array of register names for pins
  * @pins:	physical pins on the SoC
  * @pgtree:	pingroup index radix tree
  * @ftree:	function index radix tree
  * @pingroups:	list of pingroups
  * @functions:	list of functions
+ * @gpiofuncs:	list of gpio functions
  * @ngroups:	number of pingroups
  * @nfuncs:	number of functions
  * @desc:	pin controller descriptor
@@ -142,12 +189,14 @@ struct pcs_device {
 	unsigned foff;
 	unsigned fmax;
 	bool bits_per_mux;
+	bool is_pinconf;
 	struct pcs_name *names;
 	struct pcs_data pins;
 	struct radix_tree_root pgtree;
 	struct radix_tree_root ftree;
 	struct list_head pingroups;
 	struct list_head functions;
+	struct list_head gpiofuncs;
 	unsigned ngroups;
 	unsigned nfuncs;
 	struct pinctrl_desc desc;
@@ -155,6 +204,16 @@ struct pcs_device {
 	void (*write)(unsigned val, void __iomem *reg);
 };
 
+static int pcs_pinconf_get(struct pinctrl_dev *pctldev, unsigned pin,
+			   unsigned long *config);
+static int pcs_pinconf_set(struct pinctrl_dev *pctldev, unsigned pin,
+			   unsigned long config);
+
+static enum pin_config_param pcs_bias[] = {
+	PIN_CONFIG_BIAS_PULL_DOWN,
+	PIN_CONFIG_BIAS_PULL_UP,
+};
+
 /*
  * REVISIT: Reads and writes could eventually use regmap or something
  * generic. But at least on omaps, some mux registers are performance
@@ -270,7 +329,7 @@ static int pcs_dt_node_to_map(struct pinctrl_dev *pctldev,
 				struct device_node *np_config,
 				struct pinctrl_map **map, unsigned *num_maps);
 
-static struct pinctrl_ops pcs_pinctrl_ops = {
+static const struct pinctrl_ops pcs_pinctrl_ops = {
 	.get_groups_count = pcs_get_groups_count,
 	.get_group_name = pcs_get_group_name,
 	.get_group_pins = pcs_get_group_pins,
@@ -326,6 +385,28 @@ static int pcs_get_function_groups(struct pinctrl_dev *pctldev,
 	return 0;
 }
 
+static int pcs_get_function(struct pinctrl_dev *pctldev, unsigned pin,
+			    struct pcs_function **func)
+{
+	struct pcs_device *pcs = pinctrl_dev_get_drvdata(pctldev);
+	struct pin_desc *pdesc = pin_desc_get(pctldev, pin);
+	const struct pinctrl_setting_mux *setting;
+	unsigned fselector;
+
+	/* If pin is not described in DTS & enabled, mux_setting is NULL. */
+	setting = pdesc->mux_setting;
+	if (!setting)
+		return -ENOTSUPP;
+	fselector = setting->func;
+	*func = radix_tree_lookup(&pcs->ftree, fselector);
+	if (!(*func)) {
+		dev_err(pcs->dev, "%s could not find function%i\n",
+			__func__, fselector);
+		return -ENOTSUPP;
+	}
+	return 0;
+}
+
 static int pcs_enable(struct pinctrl_dev *pctldev, unsigned fselector,
 	unsigned group)
 {
@@ -334,6 +415,9 @@ static int pcs_enable(struct pinctrl_dev *pctldev, unsigned fselector,
 	int i;
 
 	pcs = pinctrl_dev_get_drvdata(pctldev);
+	/* If function mask is null, needn't enable it. */
+	if (!pcs->fmask)
+		return 0;
 	func = radix_tree_lookup(&pcs->ftree, fselector);
 	if (!func)
 		return -EINVAL;
@@ -368,6 +452,10 @@ static void pcs_disable(struct pinctrl_dev *pctldev, unsigned fselector,
 	int i;
 
 	pcs = pinctrl_dev_get_drvdata(pctldev);
+	/* If function mask is null, needn't disable it. */
+	if (!pcs->fmask)
+		return;
+
 	func = radix_tree_lookup(&pcs->ftree, fselector);
 	if (!func) {
 		dev_err(pcs->dev, "%s could not find function%i\n",
@@ -403,12 +491,33 @@ static void pcs_disable(struct pinctrl_dev *pctldev, unsigned fselector,
 }
 
 static int pcs_request_gpio(struct pinctrl_dev *pctldev,
-			struct pinctrl_gpio_range *range, unsigned offset)
+			    struct pinctrl_gpio_range *range, unsigned pin)
 {
-	return -ENOTSUPP;
+	struct pcs_device *pcs = pinctrl_dev_get_drvdata(pctldev);
+	struct pcs_gpiofunc_range *frange = NULL;
+	struct list_head *pos, *tmp;
+	int mux_bytes = 0;
+	unsigned data;
+
+	/* If function mask is null, return directly. */
+	if (!pcs->fmask)
+		return -ENOTSUPP;
+
+	list_for_each_safe(pos, tmp, &pcs->gpiofuncs) {
+		frange = list_entry(pos, struct pcs_gpiofunc_range, node);
+		if (pin >= frange->offset + frange->npins
+			|| pin < frange->offset)
+			continue;
+		mux_bytes = pcs->width / BITS_PER_BYTE;
+		data = pcs->read(pcs->base + pin * mux_bytes) & ~pcs->fmask;
+		data |= frange->gpiofunc;
+		pcs->write(data, pcs->base + pin * mux_bytes);
+		break;
+	}
+	return 0;
 }
 
-static struct pinmux_ops pcs_pinmux_ops = {
+static const struct pinmux_ops pcs_pinmux_ops = {
 	.get_functions_count = pcs_get_functions_count,
 	.get_function_name = pcs_get_function_name,
 	.get_function_groups = pcs_get_function_groups,
@@ -417,32 +526,190 @@ static struct pinmux_ops pcs_pinmux_ops = {
 	.gpio_request_enable = pcs_request_gpio,
 };
 
+/* Clear BIAS value */
+static void pcs_pinconf_clear_bias(struct pinctrl_dev *pctldev, unsigned pin)
+{
+	unsigned long config;
+	int i;
+	for (i = 0; i < ARRAY_SIZE(pcs_bias); i++) {
+		config = pinconf_to_config_packed(pcs_bias[i], 0);
+		pcs_pinconf_set(pctldev, pin, config);
+	}
+}
+
+/*
+ * Check whether PIN_CONFIG_BIAS_DISABLE is valid.
+ * It's depend on that PULL_DOWN & PULL_UP configs are all invalid.
+ */
+static bool pcs_pinconf_bias_disable(struct pinctrl_dev *pctldev, unsigned pin)
+{
+	unsigned long config;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(pcs_bias); i++) {
+		config = pinconf_to_config_packed(pcs_bias[i], 0);
+		if (!pcs_pinconf_get(pctldev, pin, &config))
+			goto out;
+	}
+	return true;
+out:
+	return false;
+}
+
 static int pcs_pinconf_get(struct pinctrl_dev *pctldev,
 				unsigned pin, unsigned long *config)
 {
+	struct pcs_device *pcs = pinctrl_dev_get_drvdata(pctldev);
+	struct pcs_function *func;
+	enum pin_config_param param;
+	unsigned offset = 0, data = 0, i, j, ret;
+
+	ret = pcs_get_function(pctldev, pin, &func);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < func->nconfs; i++) {
+		param = pinconf_to_config_param(*config);
+		if (param == PIN_CONFIG_BIAS_DISABLE) {
+			if (pcs_pinconf_bias_disable(pctldev, pin)) {
+				*config = 0;
+				return 0;
+			} else {
+				return -ENOTSUPP;
+			}
+		} else if (param != func->conf[i].param) {
+			continue;
+		}
+
+		offset = pin * (pcs->width / BITS_PER_BYTE);
+		data = pcs->read(pcs->base + offset) & func->conf[i].mask;
+		switch (func->conf[i].param) {
+		/* 4 parameters */
+		case PIN_CONFIG_BIAS_PULL_DOWN:
+		case PIN_CONFIG_BIAS_PULL_UP:
+		case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+			if ((data != func->conf[i].enable) ||
+			    (data == func->conf[i].disable))
+				return -ENOTSUPP;
+			*config = 0;
+			break;
+		/* 2 parameters */
+		case PIN_CONFIG_INPUT_SCHMITT:
+			for (j = 0; j < func->nconfs; j++) {
+				switch (func->conf[j].param) {
+				case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+					if (data != func->conf[j].enable)
+						return -ENOTSUPP;
+					break;
+				default:
+					break;
+				}
+			}
+			*config = data;
+			break;
+		case PIN_CONFIG_DRIVE_STRENGTH:
+		case PIN_CONFIG_SLEW_RATE:
+		default:
+			*config = data;
+			break;
+		}
+		return 0;
+	}
 	return -ENOTSUPP;
 }
 
 static int pcs_pinconf_set(struct pinctrl_dev *pctldev,
 				unsigned pin, unsigned long config)
 {
+	struct pcs_device *pcs = pinctrl_dev_get_drvdata(pctldev);
+	struct pcs_function *func;
+	unsigned offset = 0, shift = 0, i, data, ret;
+	u16 arg;
+
+	ret = pcs_get_function(pctldev, pin, &func);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < func->nconfs; i++) {
+		if (pinconf_to_config_param(config) == func->conf[i].param) {
+			offset = pin * (pcs->width / BITS_PER_BYTE);
+			data = pcs->read(pcs->base + offset);
+			arg = pinconf_to_config_argument(config);
+			switch (func->conf[i].param) {
+			/* 2 parameters */
+			case PIN_CONFIG_INPUT_SCHMITT:
+			case PIN_CONFIG_DRIVE_STRENGTH:
+			case PIN_CONFIG_SLEW_RATE:
+				shift = ffs(func->conf[i].mask) - 1;
+				data &= ~func->conf[i].mask;
+				data |= (arg << shift) & func->conf[i].mask;
+				break;
+			/* 4 parameters */
+			case PIN_CONFIG_BIAS_DISABLE:
+				pcs_pinconf_clear_bias(pctldev, pin);
+				break;
+			case PIN_CONFIG_BIAS_PULL_DOWN:
+			case PIN_CONFIG_BIAS_PULL_UP:
+				if (arg)
+					pcs_pinconf_clear_bias(pctldev, pin);
+				/* fall through */
+			case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+				data &= ~func->conf[i].mask;
+				if (arg)
+					data |= func->conf[i].enable;
+				else
+					data |= func->conf[i].disable;
+				break;
+			default:
+				return -ENOTSUPP;
+			}
+			pcs->write(data, pcs->base + offset);
+			return 0;
+		}
+	}
 	return -ENOTSUPP;
 }
 
 static int pcs_pinconf_group_get(struct pinctrl_dev *pctldev,
 				unsigned group, unsigned long *config)
 {
-	return -ENOTSUPP;
+	const unsigned *pins;
+	unsigned npins, old = 0;
+	int i, ret;
+
+	ret = pcs_get_group_pins(pctldev, group, &pins, &npins);
+	if (ret)
+		return ret;
+	for (i = 0; i < npins; i++) {
+		if (pcs_pinconf_get(pctldev, pins[i], config))
+			return -ENOTSUPP;
+		/* configs do not match between two pins */
+		if (i && (old != *config))
+			return -ENOTSUPP;
+		old = *config;
+	}
+	return 0;
 }
 
 static int pcs_pinconf_group_set(struct pinctrl_dev *pctldev,
 				unsigned group, unsigned long config)
 {
-	return -ENOTSUPP;
+	const unsigned *pins;
+	unsigned npins;
+	int i, ret;
+
+	ret = pcs_get_group_pins(pctldev, group, &pins, &npins);
+	if (ret)
+		return ret;
+	for (i = 0; i < npins; i++) {
+		if (pcs_pinconf_set(pctldev, pins[i], config))
+			return -ENOTSUPP;
+	}
+	return 0;
 }
 
 static void pcs_pinconf_dbg_show(struct pinctrl_dev *pctldev,
-				struct seq_file *s, unsigned offset)
+				struct seq_file *s, unsigned pin)
 {
 }
 
@@ -451,13 +718,22 @@ static void pcs_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
 {
 }
 
-static struct pinconf_ops pcs_pinconf_ops = {
+static void pcs_pinconf_config_dbg_show(struct pinctrl_dev *pctldev,
+					struct seq_file *s,
+					unsigned long config)
+{
+	pinconf_generic_dump_config(pctldev, s, config);
+}
+
+static const struct pinconf_ops pcs_pinconf_ops = {
 	.pin_config_get = pcs_pinconf_get,
 	.pin_config_set = pcs_pinconf_set,
 	.pin_config_group_get = pcs_pinconf_group_get,
 	.pin_config_group_set = pcs_pinconf_group_set,
 	.pin_config_dbg_show = pcs_pinconf_dbg_show,
 	.pin_config_group_dbg_show = pcs_pinconf_group_dbg_show,
+	.pin_config_config_dbg_show = pcs_pinconf_config_dbg_show,
+	.is_generic = true,
 };
 
 /**
@@ -648,11 +924,158 @@ static int pcs_get_pin_by_offset(struct pcs_device *pcs, unsigned offset)
 	return index;
 }
 
+/*
+ * check whether data matches enable bits or disable bits
+ * Return value: 1 for matching enable bits, 0 for matching disable bits,
+ *               and negative value for matching failure.
+ */
+static int pcs_config_match(unsigned data, unsigned enable, unsigned disable)
+{
+	int ret = -EINVAL;
+
+	if (data == enable)
+		ret = 1;
+	else if (data == disable)
+		ret = 0;
+	return ret;
+}
+
+static void add_config(struct pcs_conf_vals **conf, enum pin_config_param param,
+		       unsigned value, unsigned enable, unsigned disable,
+		       unsigned mask)
+{
+	(*conf)->param = param;
+	(*conf)->val = value;
+	(*conf)->enable = enable;
+	(*conf)->disable = disable;
+	(*conf)->mask = mask;
+	(*conf)++;
+}
+
+static void add_setting(unsigned long **setting, enum pin_config_param param,
+			unsigned arg)
+{
+	**setting = pinconf_to_config_packed(param, arg);
+	(*setting)++;
+}
+
+/* add pinconf setting with 2 parameters */
+static void pcs_add_conf2(struct pcs_device *pcs, struct device_node *np,
+			  const char *name, enum pin_config_param param,
+			  struct pcs_conf_vals **conf, unsigned long **settings)
+{
+	unsigned value[2], shift;
+	int ret;
+
+	ret = of_property_read_u32_array(np, name, value, 2);
+	if (ret)
+		return;
+	/* set value & mask */
+	value[0] &= value[1];
+	shift = ffs(value[1]) - 1;
+	/* skip enable & disable */
+	add_config(conf, param, value[0], 0, 0, value[1]);
+	add_setting(settings, param, value[0] >> shift);
+}
+
+/* add pinconf setting with 4 parameters */
+static void pcs_add_conf4(struct pcs_device *pcs, struct device_node *np,
+			  const char *name, enum pin_config_param param,
+			  struct pcs_conf_vals **conf, unsigned long **settings)
+{
+	unsigned value[4];
+	int ret;
+
+	/* value to set, enable, disable, mask */
+	ret = of_property_read_u32_array(np, name, value, 4);
+	if (ret)
+		return;
+	if (!value[3]) {
+		dev_err(pcs->dev, "mask field of the property can't be 0\n");
+		return;
+	}
+	value[0] &= value[3];
+	value[1] &= value[3];
+	value[2] &= value[3];
+	ret = pcs_config_match(value[0], value[1], value[2]);
+	if (ret < 0)
+		dev_dbg(pcs->dev, "failed to match enable or disable bits\n");
+	add_config(conf, param, value[0], value[1], value[2], value[3]);
+	add_setting(settings, param, ret);
+}
+
+static int pcs_parse_pinconf(struct pcs_device *pcs, struct device_node *np,
+			     struct pcs_function *func,
+			     struct pinctrl_map **map)
+
+{
+	struct pinctrl_map *m = *map;
+	int i = 0, nconfs = 0;
+	unsigned long *settings = NULL, *s = NULL;
+	struct pcs_conf_vals *conf = NULL;
+	struct pcs_conf_type prop2[] = {
+		{ "pinctrl-single,drive-strength", PIN_CONFIG_DRIVE_STRENGTH, },
+		{ "pinctrl-single,slew-rate", PIN_CONFIG_SLEW_RATE, },
+		{ "pinctrl-single,input-schmitt", PIN_CONFIG_INPUT_SCHMITT, },
+	};
+	struct pcs_conf_type prop4[] = {
+		{ "pinctrl-single,bias-pullup", PIN_CONFIG_BIAS_PULL_UP, },
+		{ "pinctrl-single,bias-pulldown", PIN_CONFIG_BIAS_PULL_DOWN, },
+		{ "pinctrl-single,input-schmitt-enable",
+			PIN_CONFIG_INPUT_SCHMITT_ENABLE, },
+	};
+
+	/* If pinconf isn't supported, don't parse properties in below. */
+	if (!pcs->is_pinconf)
+		return 0;
+
+	/* cacluate how much properties are supported in current node */
+	for (i = 0; i < ARRAY_SIZE(prop2); i++) {
+		if (of_find_property(np, prop2[i].name, NULL))
+			nconfs++;
+	}
+	for (i = 0; i < ARRAY_SIZE(prop4); i++) {
+		if (of_find_property(np, prop4[i].name, NULL))
+			nconfs++;
+	}
+	if (!nconfs)
+		return 0;
+
+	func->conf = devm_kzalloc(pcs->dev,
+				  sizeof(struct pcs_conf_vals) * nconfs,
+				  GFP_KERNEL);
+	if (!func->conf)
+		return -ENOMEM;
+	func->nconfs = nconfs;
+	conf = &(func->conf[0]);
+	m++;
+	settings = devm_kzalloc(pcs->dev, sizeof(unsigned long) * nconfs,
+				GFP_KERNEL);
+	if (!settings)
+		return -ENOMEM;
+	s = &settings[0];
+
+	for (i = 0; i < ARRAY_SIZE(prop2); i++)
+		pcs_add_conf2(pcs, np, prop2[i].name, prop2[i].param,
+			      &conf, &s);
+	for (i = 0; i < ARRAY_SIZE(prop4); i++)
+		pcs_add_conf4(pcs, np, prop4[i].name, prop4[i].param,
+			      &conf, &s);
+	m->type = PIN_MAP_TYPE_CONFIGS_GROUP;
+	m->data.configs.group_or_pin = np->name;
+	m->data.configs.configs = settings;
+	m->data.configs.num_configs = nconfs;
+	return 0;
+}
+
+static void pcs_free_pingroups(struct pcs_device *pcs);
+
 /**
  * smux_parse_one_pinctrl_entry() - parses a device tree mux entry
  * @pcs: pinctrl driver instance
  * @np: device node of the mux entry
  * @map: map entry
+ * @num_maps: number of map
  * @pgnames: pingroup names
  *
  * Note that this binding currently supports only sets of one register + value.
@@ -669,6 +1092,7 @@ static int pcs_get_pin_by_offset(struct pcs_device *pcs, unsigned offset)
 static int pcs_parse_one_pinctrl_entry(struct pcs_device *pcs,
 						struct device_node *np,
 						struct pinctrl_map **map,
+						unsigned *num_maps,
 						const char **pgnames)
 {
 	struct pcs_func_vals *vals;
@@ -741,8 +1165,18 @@ static int pcs_parse_one_pinctrl_entry(struct pcs_device *pcs,
 	(*map)->data.mux.group = np->name;
 	(*map)->data.mux.function = np->name;
 
+	if (pcs->is_pinconf) {
+		if (pcs_parse_pinconf(pcs, np, function, map))
+			goto free_pingroups;
+		*num_maps = 2;
+	} else {
+		*num_maps = 1;
+	}
 	return 0;
 
+free_pingroups:
+	pcs_free_pingroups(pcs);
+	*num_maps = 1;
 free_function:
 	pcs_remove_function(pcs, function);
 
@@ -771,7 +1205,8 @@ static int pcs_dt_node_to_map(struct pinctrl_dev *pctldev,
 
 	pcs = pinctrl_dev_get_drvdata(pctldev);
 
-	*map = devm_kzalloc(pcs->dev, sizeof(**map), GFP_KERNEL);
+	/* create 2 maps. One is for pinmux, and the other is for pinconf. */
+	*map = devm_kzalloc(pcs->dev, sizeof(**map) * 2, GFP_KERNEL);
 	if (!*map)
 		return -ENOMEM;
 
@@ -783,13 +1218,13 @@ static int pcs_dt_node_to_map(struct pinctrl_dev *pctldev,
 		goto free_map;
 	}
 
-	ret = pcs_parse_one_pinctrl_entry(pcs, np_config, map, pgnames);
+	ret = pcs_parse_one_pinctrl_entry(pcs, np_config, map, num_maps,
+					  pgnames);
 	if (ret < 0) {
 		dev_err(pcs->dev, "no pins entries for %s\n",
 			np_config->name);
 		goto free_pgnames;
 	}
-	*num_maps = 1;
 
 	return 0;
 
@@ -879,6 +1314,37 @@ static void pcs_free_resources(struct pcs_device *pcs)
 
 static struct of_device_id pcs_of_match[];
 
+static int pcs_add_gpio_func(struct device_node *node, struct pcs_device *pcs)
+{
+	const char *propname = "pinctrl-single,gpio-range";
+	const char *cellname = "#pinctrl-single,gpio-range-cells";
+	struct of_phandle_args gpiospec;
+	struct pcs_gpiofunc_range *range;
+	int ret, i;
+
+	for (i = 0; ; i++) {
+		ret = of_parse_phandle_with_args(node, propname, cellname,
+						 i, &gpiospec);
+		/* Do not treat it as error. Only treat it as end condition. */
+		if (ret) {
+			ret = 0;
+			break;
+		}
+		range = devm_kzalloc(pcs->dev, sizeof(*range), GFP_KERNEL);
+		if (!range) {
+			ret = -ENOMEM;
+			break;
+		}
+		range->offset = gpiospec.args[0];
+		range->npins = gpiospec.args[1];
+		range->gpiofunc = gpiospec.args[2];
+		mutex_lock(&pcs->mutex);
+		list_add_tail(&range->node, &pcs->gpiofuncs);
+		mutex_unlock(&pcs->mutex);
+	}
+	return ret;
+}
+
 static int pcs_probe(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
@@ -900,14 +1366,23 @@ static int pcs_probe(struct platform_device *pdev)
 	mutex_init(&pcs->mutex);
 	INIT_LIST_HEAD(&pcs->pingroups);
 	INIT_LIST_HEAD(&pcs->functions);
+	INIT_LIST_HEAD(&pcs->gpiofuncs);
+	pcs->is_pinconf = match->data;
 
 	PCS_GET_PROP_U32("pinctrl-single,register-width", &pcs->width,
 			 "register width not specified\n");
 
-	PCS_GET_PROP_U32("pinctrl-single,function-mask", &pcs->fmask,
-			 "function register mask not specified\n");
-	pcs->fshift = ffs(pcs->fmask) - 1;
-	pcs->fmax = pcs->fmask >> pcs->fshift;
+	ret = of_property_read_u32(np, "pinctrl-single,function-mask",
+				   &pcs->fmask);
+	if (!ret) {
+		pcs->fshift = ffs(pcs->fmask) - 1;
+		pcs->fmax = pcs->fmask >> pcs->fshift;
+	} else {
+		/* If mask property doesn't exist, function mux is invalid. */
+		pcs->fmask = 0;
+		pcs->fshift = 0;
+		pcs->fmax = 0;
+	}
 
 	ret = of_property_read_u32(np, "pinctrl-single,function-off",
 					&pcs->foff);
@@ -961,7 +1436,8 @@ static int pcs_probe(struct platform_device *pdev)
 	pcs->desc.name = DRIVER_NAME;
 	pcs->desc.pctlops = &pcs_pinctrl_ops;
 	pcs->desc.pmxops = &pcs_pinmux_ops;
-	pcs->desc.confops = &pcs_pinconf_ops;
+	if (pcs->is_pinconf)
+		pcs->desc.confops = &pcs_pinconf_ops;
 	pcs->desc.owner = THIS_MODULE;
 
 	ret = pcs_allocate_pin_table(pcs);
@@ -975,6 +1451,10 @@ static int pcs_probe(struct platform_device *pdev)
 		goto free;
 	}
 
+	ret = pcs_add_gpio_func(np, pcs);
+	if (ret < 0)
+		goto free;
+
 	dev_info(pcs->dev, "%i pins at pa %p size %u\n",
 		 pcs->desc.npins, pcs->base, pcs->size);
 
@@ -999,7 +1479,8 @@ static int pcs_remove(struct platform_device *pdev)
 }
 
 static struct of_device_id pcs_of_match[] = {
-	{ .compatible = DRIVER_NAME, },
+	{ .compatible = "pinctrl-single", .data = (void *)false },
+	{ .compatible = "pinconf-single", .data = (void *)true },
 	{ },
 };
 MODULE_DEVICE_TABLE(of, pcs_of_match);
diff --git a/drivers/pinctrl/pinctrl-sirf.c b/drivers/pinctrl/pinctrl-sirf.c
index d02498b..bc9d1be 100644
--- a/drivers/pinctrl/pinctrl-sirf.c
+++ b/drivers/pinctrl/pinctrl-sirf.c
@@ -14,6 +14,7 @@
 #include <linux/slab.h>
 #include <linux/err.h>
 #include <linux/irqdomain.h>
+#include <linux/irqchip/chained_irq.h>
 #include <linux/pinctrl/pinctrl.h>
 #include <linux/pinctrl/pinmux.h>
 #include <linux/pinctrl/consumer.h>
@@ -25,7 +26,6 @@
 #include <linux/bitops.h>
 #include <linux/gpio.h>
 #include <linux/of_gpio.h>
-#include <asm/mach/irq.h>
 
 #define DRIVER_NAME "pinmux-sirf"
 
@@ -979,7 +979,7 @@ static void sirfsoc_dt_free_map(struct pinctrl_dev *pctldev,
 	kfree(map);
 }
 
-static struct pinctrl_ops sirfsoc_pctrl_ops = {
+static const struct pinctrl_ops sirfsoc_pctrl_ops = {
 	.get_groups_count = sirfsoc_get_groups_count,
 	.get_group_name = sirfsoc_get_group_name,
 	.get_group_pins = sirfsoc_get_group_pins,
@@ -1181,7 +1181,7 @@ static int sirfsoc_pinmux_request_gpio(struct pinctrl_dev *pmxdev,
 	return 0;
 }
 
-static struct pinmux_ops sirfsoc_pinmux_ops = {
+static const struct pinmux_ops sirfsoc_pinmux_ops = {
 	.enable = sirfsoc_pinmux_enable,
 	.disable = sirfsoc_pinmux_disable,
 	.get_functions_count = sirfsoc_pinmux_get_funcs_count,
@@ -1347,7 +1347,7 @@ static inline int sirfsoc_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
 	struct sirfsoc_gpio_bank *bank = container_of(to_of_mm_gpio_chip(chip),
 		struct sirfsoc_gpio_bank, chip);
 
-	return irq_find_mapping(bank->domain, offset);
+	return irq_create_mapping(bank->domain, offset);
 }
 
 static inline int sirfsoc_gpio_to_offset(unsigned int gpio)
@@ -1485,7 +1485,6 @@ static void sirfsoc_gpio_handle_irq(unsigned int irq, struct irq_desc *desc)
 	struct sirfsoc_gpio_bank *bank = irq_get_handler_data(irq);
 	u32 status, ctrl;
 	int idx = 0;
-	unsigned int first_irq;
 	struct irq_chip *chip = irq_get_chip(irq);
 
 	chained_irq_enter(chip, desc);
@@ -1499,8 +1498,6 @@ static void sirfsoc_gpio_handle_irq(unsigned int irq, struct irq_desc *desc)
 		return;
 	}
 
-	first_irq = bank->domain->revmap_data.legacy.first_irq;
-
 	while (status) {
 		ctrl = readl(bank->chip.regs + SIRFSOC_GPIO_CTRL(bank->id, idx));
 
@@ -1511,7 +1508,7 @@ static void sirfsoc_gpio_handle_irq(unsigned int irq, struct irq_desc *desc)
 		if ((status & 0x1) && (ctrl & SIRFSOC_GPIO_CTL_INTR_EN_MASK)) {
 			pr_debug("%s: gpio id %d idx %d happens\n",
 				__func__, bank->id, idx);
-			generic_handle_irq(first_irq + idx);
+			generic_handle_irq(irq_find_mapping(bank->domain, idx));
 		}
 
 		idx++;
@@ -1685,15 +1682,12 @@ static void sirfsoc_gpio_set_pullup(const u32 *pullups)
 	const unsigned long *p = (const unsigned long *)pullups;
 
 	for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) {
-		n = find_first_bit(p + i, BITS_PER_LONG);
-		while (n < BITS_PER_LONG) {
+		for_each_set_bit(n, p + i, BITS_PER_LONG) {
 			u32 offset = SIRFSOC_GPIO_CTRL(i, n);
 			u32 val = readl(sgpio_bank[i].chip.regs + offset);
 			val |= SIRFSOC_GPIO_CTL_PULL_MASK;
 			val |= SIRFSOC_GPIO_CTL_PULL_HIGH;
 			writel(val, sgpio_bank[i].chip.regs + offset);
-
-			n = find_next_bit(p + i, BITS_PER_LONG, n + 1);
 		}
 	}
 }
@@ -1704,15 +1698,12 @@ static void sirfsoc_gpio_set_pulldown(const u32 *pulldowns)
 	const unsigned long *p = (const unsigned long *)pulldowns;
 
 	for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) {
-		n = find_first_bit(p + i, BITS_PER_LONG);
-		while (n < BITS_PER_LONG) {
+		for_each_set_bit(n, p + i, BITS_PER_LONG) {
 			u32 offset = SIRFSOC_GPIO_CTRL(i, n);
 			u32 val = readl(sgpio_bank[i].chip.regs + offset);
 			val |= SIRFSOC_GPIO_CTL_PULL_MASK;
 			val &= ~SIRFSOC_GPIO_CTL_PULL_HIGH;
 			writel(val, sgpio_bank[i].chip.regs + offset);
-
-			n = find_next_bit(p + i, BITS_PER_LONG, n + 1);
 		}
 	}
 }
@@ -1770,9 +1761,8 @@ static int sirfsoc_gpio_probe(struct device_node *np)
 			goto out;
 		}
 
-		bank->domain = irq_domain_add_legacy(np, SIRFSOC_GPIO_BANK_SIZE,
-			SIRFSOC_GPIO_IRQ_START + i * SIRFSOC_GPIO_BANK_SIZE, 0,
-			&sirfsoc_gpio_irq_simple_ops, bank);
+		bank->domain = irq_domain_add_linear(np, SIRFSOC_GPIO_BANK_SIZE,
+						&sirfsoc_gpio_irq_simple_ops, bank);
 
 		if (!bank->domain) {
 			pr_err("%s: Failed to create irqdomain\n", np->full_name);
diff --git a/drivers/pinctrl/pinctrl-sunxi.c b/drivers/pinctrl/pinctrl-sunxi.c
index 80b11e3..617d351 100644
--- a/drivers/pinctrl/pinctrl-sunxi.c
+++ b/drivers/pinctrl/pinctrl-sunxi.c
@@ -11,6 +11,7 @@
  */
 
 #include <linux/io.h>
+#include <linux/clk.h>
 #include <linux/gpio.h>
 #include <linux/module.h>
 #include <linux/of.h>
@@ -30,482 +31,856 @@
 static const struct sunxi_desc_pin sun4i_a10_pins[] = {
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PA0,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "wemac"),		/* ERXD3 */
+		SUNXI_FUNCTION(0x3, "spi1"),		/* CS0 */
+		SUNXI_FUNCTION(0x4, "uart2")),		/* RTS */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PA1,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "wemac"),		/* ERXD2 */
+		SUNXI_FUNCTION(0x3, "spi1"),		/* CLK */
+		SUNXI_FUNCTION(0x4, "uart2")),		/* CTS */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PA2,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "wemac"),		/* ERXD1 */
+		SUNXI_FUNCTION(0x3, "spi1"),		/* MOSI */
+		SUNXI_FUNCTION(0x4, "uart2")),		/* TX */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PA3,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "wemac"),		/* ERXD0 */
+		SUNXI_FUNCTION(0x3, "spi1"),		/* MISO */
+		SUNXI_FUNCTION(0x4, "uart2")),		/* RX */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PA4,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "wemac"),		/* ETXD3 */
+		SUNXI_FUNCTION(0x3, "spi1")),		/* CS1 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PA5,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "wemac"),		/* ETXD2 */
+		SUNXI_FUNCTION(0x3, "spi3")),		/* CS0 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PA6,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "wemac"),		/* ETXD1 */
+		SUNXI_FUNCTION(0x3, "spi3")),		/* CLK */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PA7,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "wemac"),		/* ETXD0 */
+		SUNXI_FUNCTION(0x3, "spi3")),		/* MOSI */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PA8,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "wemac"),		/* ERXCK */
+		SUNXI_FUNCTION(0x3, "spi3")),		/* MISO */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PA9,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "wemac"),		/* ERXERR */
+		SUNXI_FUNCTION(0x3, "spi3")),		/* CS1 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PA10,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
 		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "wemac"),		/* ERXDV */
 		SUNXI_FUNCTION(0x4, "uart1")),		/* TX */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PA11,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
 		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "wemac"),		/* EMDC */
 		SUNXI_FUNCTION(0x4, "uart1")),		/* RX */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PA12,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
 		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "wemac"),		/* EMDIO */
+		SUNXI_FUNCTION(0x3, "uart6"),		/* TX */
 		SUNXI_FUNCTION(0x4, "uart1")),		/* RTS */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PA13,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
 		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "wemac"),		/* ETXEN */
+		SUNXI_FUNCTION(0x3, "uart6"),		/* RX */
 		SUNXI_FUNCTION(0x4, "uart1")),		/* CTS */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PA14,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
 		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "wemac"),		/* ETXCK */
+		SUNXI_FUNCTION(0x3, "uart7"),		/* TX */
 		SUNXI_FUNCTION(0x4, "uart1")),		/* DTR */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PA15,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
 		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "wemac"),		/* ECRS */
+		SUNXI_FUNCTION(0x3, "uart7"),		/* RX */
 		SUNXI_FUNCTION(0x4, "uart1")),		/* DSR */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PA16,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
 		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "wemac"),		/* ECOL */
+		SUNXI_FUNCTION(0x3, "can"),		/* TX */
 		SUNXI_FUNCTION(0x4, "uart1")),		/* DCD */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PA17,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
 		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "wemac"),		/* ETXERR */
+		SUNXI_FUNCTION(0x3, "can"),		/* RX */
 		SUNXI_FUNCTION(0x4, "uart1")),		/* RING */
 	/* Hole */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PB0,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "i2c0")),		/* SCK */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PB1,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "i2c0")),		/* SDA */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PB2,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "pwm")),		/* PWM0 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PB3,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ir0")),		/* TX */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PB4,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ir0")),		/* RX */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PB5,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "i2s"),		/* MCLK */
+		SUNXI_FUNCTION(0x3, "ac97")),		/* MCLK */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PB6,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "i2s"),		/* BCLK */
+		SUNXI_FUNCTION(0x3, "ac97")),		/* BCLK */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PB7,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "i2s"),		/* LRCK */
+		SUNXI_FUNCTION(0x3, "ac97")),		/* SYNC */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PB8,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "i2s"),		/* DO0 */
+		SUNXI_FUNCTION(0x3, "ac97")),		/* DO */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PB9,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "i2s")),		/* DO1 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PB10,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "i2s")),		/* DO2 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PB11,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "i2s")),		/* DO3 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PB12,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "i2s"),		/* DI */
+		SUNXI_FUNCTION(0x3, "ac97")),		/* DI */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PB13,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "spi2")),		/* CS1 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PB14,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "spi2"),		/* CS0 */
+		SUNXI_FUNCTION(0x3, "jtag")),		/* MS0 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PB15,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "spi2"),		/* CLK */
+		SUNXI_FUNCTION(0x3, "jtag")),		/* CK0 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PB16,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "spi2"),		/* MOSI */
+		SUNXI_FUNCTION(0x3, "jtag")),		/* DO0 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PB17,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "spi2"),		/* MISO */
+		SUNXI_FUNCTION(0x3, "jtag")),		/* DI0 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PB18,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "i2c1")),		/* SCK */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PB19,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "i2c1")),		/* SDA */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PB20,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "i2c2")),		/* SCK */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PB21,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "i2c2")),		/* SDA */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PB22,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
 		SUNXI_FUNCTION(0x1, "gpio_out"),
-		SUNXI_FUNCTION(0x2, "uart0")),		/* TX */
+		SUNXI_FUNCTION(0x2, "uart0"),		/* TX */
+		SUNXI_FUNCTION(0x3, "ir1")),		/* TX */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PB23,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
 		SUNXI_FUNCTION(0x1, "gpio_out"),
-		SUNXI_FUNCTION(0x2, "uart0")),		/* RX */
+		SUNXI_FUNCTION(0x2, "uart0"),		/* RX */
+		SUNXI_FUNCTION(0x3, "ir1")),		/* RX */
 	/* Hole */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PC0,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "nand0"),		/* NWE */
+		SUNXI_FUNCTION(0x3, "spi0")),		/* MOSI */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PC1,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "nand0"),		/* NALE */
+		SUNXI_FUNCTION(0x3, "spi0")),		/* MISO */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PC2,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "nand0"),		/* NCLE */
+		SUNXI_FUNCTION(0x3, "spi0")),		/* SCK */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PC3,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "nand0")),		/* NCE1 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PC4,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "nand0")),		/* NCE0 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PC5,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "nand0")),	/* NRE# */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PC6,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "nand0"),		/* NRB0 */
+		SUNXI_FUNCTION(0x3, "mmc2")),		/* CMD */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PC7,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "nand0"),		/* NRB1 */
+		SUNXI_FUNCTION(0x3, "mmc2")),		/* CLK */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PC8,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "nand0"),		/* NDQ0 */
+		SUNXI_FUNCTION(0x3, "mmc2")),		/* D0 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PC9,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "nand0"),		/* NDQ1 */
+		SUNXI_FUNCTION(0x3, "mmc2")),		/* D1 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PC10,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "nand0"),		/* NDQ2 */
+		SUNXI_FUNCTION(0x3, "mmc2")),		/* D2 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PC11,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "nand0"),		/* NDQ3 */
+		SUNXI_FUNCTION(0x3, "mmc2")),		/* D3 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PC12,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "nand0")),		/* NDQ4 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PC13,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "nand0")),		/* NDQ5 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PC14,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "nand0")),		/* NDQ6 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PC15,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "nand0")),		/* NDQ7 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PC16,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "nand0")),		/* NWP */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PC17,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "nand0")),		/* NCE2 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PC18,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "nand0")),		/* NCE3 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PC19,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "nand0"),		/* NCE4 */
+		SUNXI_FUNCTION(0x3, "spi2")),		/* CS0 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PC20,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "nand0"),		/* NCE5 */
+		SUNXI_FUNCTION(0x3, "spi2")),		/* CLK */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PC21,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "nand0"),		/* NCE6 */
+		SUNXI_FUNCTION(0x3, "spi2")),		/* MOSI */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PC22,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "nand0"),		/* NCE7 */
+		SUNXI_FUNCTION(0x3, "spi2")),		/* MISO */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PC23,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x3, "spi0")),		/* CS0 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PC24,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "nand0")),		/* NDQS */
 	/* Hole */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PD0,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D0 */
+		SUNXI_FUNCTION(0x3, "lvds0")),		/* VP0 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PD1,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D1 */
+		SUNXI_FUNCTION(0x3, "lvds0")),		/* VN0 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PD2,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D2 */
+		SUNXI_FUNCTION(0x3, "lvds0")),		/* VP1 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PD3,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D3 */
+		SUNXI_FUNCTION(0x3, "lvds0")),		/* VN1 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PD4,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D4 */
+		SUNXI_FUNCTION(0x3, "lvds0")),		/* VP2 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PD5,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D5 */
+		SUNXI_FUNCTION(0x3, "lvds0")),		/* VN2 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PD6,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D6 */
+		SUNXI_FUNCTION(0x3, "lvds0")),		/* VPC */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PD7,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D7 */
+		SUNXI_FUNCTION(0x3, "lvds0")),		/* VNC */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PD8,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D8 */
+		SUNXI_FUNCTION(0x3, "lvds0")),		/* VP3 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PD9,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D9 */
+		SUNXI_FUNCTION(0x3, "lvds0")),		/* VM3 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PD10,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D10 */
+		SUNXI_FUNCTION(0x3, "lvds1")),		/* VP0 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PD11,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D11 */
+		SUNXI_FUNCTION(0x3, "lvds1")),		/* VN0 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PD12,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D12 */
+		SUNXI_FUNCTION(0x3, "lvds1")),		/* VP1 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PD13,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D13 */
+		SUNXI_FUNCTION(0x3, "lvds1")),		/* VN1 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PD14,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D14 */
+		SUNXI_FUNCTION(0x3, "lvds1")),		/* VP2 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PD15,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D15 */
+		SUNXI_FUNCTION(0x3, "lvds1")),		/* VN2 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PD16,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D16 */
+		SUNXI_FUNCTION(0x3, "lvds1")),		/* VPC */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PD17,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D17 */
+		SUNXI_FUNCTION(0x3, "lvds1")),		/* VNC */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PD18,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D18 */
+		SUNXI_FUNCTION(0x3, "lvds1")),		/* VP3 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PD19,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D19 */
+		SUNXI_FUNCTION(0x3, "lvds1")),		/* VN3 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PD20,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D20 */
+		SUNXI_FUNCTION(0x3, "csi1")),		/* MCLK */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PD21,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D21 */
+		SUNXI_FUNCTION(0x3, "sim")),		/* VPPEN */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PD22,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D22 */
+		SUNXI_FUNCTION(0x3, "sim")),		/* VPPPP */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PD23,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D23 */
+		SUNXI_FUNCTION(0x3, "sim")),		/* DET */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PD24,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* CLK */
+		SUNXI_FUNCTION(0x3, "sim")),		/* VCCEN */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PD25,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* DE */
+		SUNXI_FUNCTION(0x3, "sim")),		/* RST */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PD26,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* HSYNC */
+		SUNXI_FUNCTION(0x3, "sim")),		/* SCK */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PD27,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* VSYNC */
+		SUNXI_FUNCTION(0x3, "sim")),		/* SDA */
 	/* Hole */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PE0,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ts0"),		/* CLK */
+		SUNXI_FUNCTION(0x3, "csi0")),		/* PCK */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PE1,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ts0"),		/* ERR */
+		SUNXI_FUNCTION(0x3, "csi0")),		/* CK */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PE2,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ts0"),		/* SYNC */
+		SUNXI_FUNCTION(0x3, "csi0")),		/* HSYNC */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PE3,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ts0"),		/* DVLD */
+		SUNXI_FUNCTION(0x3, "csi0")),		/* VSYNC */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PE4,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ts0"),		/* D0 */
+		SUNXI_FUNCTION(0x3, "csi0")),		/* D0 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PE5,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ts0"),		/* D1 */
+		SUNXI_FUNCTION(0x3, "csi0"),		/* D1 */
+		SUNXI_FUNCTION(0x4, "sim")),		/* VPPEN */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PE6,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ts0"),		/* D2 */
+		SUNXI_FUNCTION(0x3, "csi0")),		/* D2 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PE7,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ts0"),		/* D3 */
+		SUNXI_FUNCTION(0x3, "csi0")),		/* D3 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PE8,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ts0"),		/* D4 */
+		SUNXI_FUNCTION(0x3, "csi0")),		/* D4 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PE9,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ts0"),		/* D5 */
+		SUNXI_FUNCTION(0x3, "csi0")),		/* D5 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PE10,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ts0"),		/* D6 */
+		SUNXI_FUNCTION(0x3, "csi0")),		/* D6 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PE11,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ts0"),		/* D7 */
+		SUNXI_FUNCTION(0x3, "csi0")),		/* D7 */
 	/* Hole */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PF0,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "mmc0"),		/* D1 */
+		SUNXI_FUNCTION(0x4, "jtag")),		/* MSI */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PF1,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "mmc0"),		/* D0 */
+		SUNXI_FUNCTION(0x4, "jtag")),		/* DI1 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PF2,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
 		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "mmc0"),		/* CLK */
 		SUNXI_FUNCTION(0x4, "uart0")),		/* TX */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PF3,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "mmc0"),		/* CMD */
+		SUNXI_FUNCTION(0x4, "jtag")),		/* DO1 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PF4,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
 		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "mmc0"),		/* D3 */
 		SUNXI_FUNCTION(0x4, "uart0")),		/* RX */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PF5,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "mmc0"),		/* D2 */
+		SUNXI_FUNCTION(0x4, "jtag")),		/* CK1 */
 	/* Hole */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PG0,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ts1"),		/* CLK */
+		SUNXI_FUNCTION(0x3, "csi1"),		/* PCK */
+		SUNXI_FUNCTION(0x4, "mmc1")),		/* CMD */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PG1,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ts1"),		/* ERR */
+		SUNXI_FUNCTION(0x3, "csi1"),		/* CK */
+		SUNXI_FUNCTION(0x4, "mmc1")),		/* CLK */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PG2,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ts1"),		/* SYNC */
+		SUNXI_FUNCTION(0x3, "csi1"),		/* HSYNC */
+		SUNXI_FUNCTION(0x4, "mmc1")),		/* D0 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PG3,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ts1"),		/* DVLD */
+		SUNXI_FUNCTION(0x3, "csi1"),		/* VSYNC */
+		SUNXI_FUNCTION(0x4, "mmc1")),		/* D1 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PG4,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ts1"),		/* D0 */
+		SUNXI_FUNCTION(0x3, "csi1"),		/* D0 */
+		SUNXI_FUNCTION(0x4, "mmc1"),		/* D2 */
+		SUNXI_FUNCTION(0x5, "csi0")),		/* D8 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PG5,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ts1"),		/* D1 */
+		SUNXI_FUNCTION(0x3, "csi1"),		/* D1 */
+		SUNXI_FUNCTION(0x4, "mmc1"),		/* D3 */
+		SUNXI_FUNCTION(0x5, "csi0")),		/* D9 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PG6,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ts1"),		/* D2 */
+		SUNXI_FUNCTION(0x3, "csi1"),		/* D2 */
+		SUNXI_FUNCTION(0x4, "uart3"),		/* TX */
+		SUNXI_FUNCTION(0x5, "csi0")),		/* D10 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PG7,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ts1"),		/* D3 */
+		SUNXI_FUNCTION(0x3, "csi1"),		/* D3 */
+		SUNXI_FUNCTION(0x4, "uart3"),		/* RX */
+		SUNXI_FUNCTION(0x5, "csi0")),		/* D11 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PG8,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ts1"),		/* D4 */
+		SUNXI_FUNCTION(0x3, "csi1"),		/* D4 */
+		SUNXI_FUNCTION(0x4, "uart3"),		/* RTS */
+		SUNXI_FUNCTION(0x5, "csi0")),		/* D12 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PG9,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ts1"),		/* D5 */
+		SUNXI_FUNCTION(0x3, "csi1"),		/* D5 */
+		SUNXI_FUNCTION(0x4, "uart3"),		/* CTS */
+		SUNXI_FUNCTION(0x5, "csi0")),		/* D13 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PG10,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ts1"),		/* D6 */
+		SUNXI_FUNCTION(0x3, "csi1"),		/* D6 */
+		SUNXI_FUNCTION(0x4, "uart4"),		/* TX */
+		SUNXI_FUNCTION(0x5, "csi0")),		/* D14 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PG11,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ts1"),		/* D7 */
+		SUNXI_FUNCTION(0x3, "csi1"),		/* D7 */
+		SUNXI_FUNCTION(0x4, "uart4"),		/* RX */
+		SUNXI_FUNCTION(0x5, "csi0")),		/* D15 */
 	/* Hole */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PH0,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd1"),		/* D0 */
+		SUNXI_FUNCTION(0x3, "pata"),		/* ATAA0 */
+		SUNXI_FUNCTION(0x4, "uart3"),		/* TX */
+		SUNXI_FUNCTION(0x7, "csi1")),		/* D0 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PH1,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd1"),		/* D1 */
+		SUNXI_FUNCTION(0x3, "pata"),		/* ATAA1 */
+		SUNXI_FUNCTION(0x4, "uart3"),		/* RX */
+		SUNXI_FUNCTION(0x7, "csi1")),		/* D1 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PH2,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd1"),		/* D2 */
+		SUNXI_FUNCTION(0x3, "pata"),		/* ATAA2 */
+		SUNXI_FUNCTION(0x4, "uart3"),		/* RTS */
+		SUNXI_FUNCTION(0x7, "csi1")),		/* D2 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PH3,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd1"),		/* D3 */
+		SUNXI_FUNCTION(0x3, "pata"),		/* ATAIRQ */
+		SUNXI_FUNCTION(0x4, "uart3"),		/* CTS */
+		SUNXI_FUNCTION(0x7, "csi1")),		/* D3 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PH4,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd1"),		/* D4 */
+		SUNXI_FUNCTION(0x3, "pata"),		/* ATAD0 */
+		SUNXI_FUNCTION(0x4, "uart4"),		/* TX */
+		SUNXI_FUNCTION(0x7, "csi1")),		/* D4 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PH5,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd1"),		/* D5 */
+		SUNXI_FUNCTION(0x3, "pata"),		/* ATAD1 */
+		SUNXI_FUNCTION(0x4, "uart4"),		/* RX */
+		SUNXI_FUNCTION(0x7, "csi1")),		/* D5 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PH6,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd1"),		/* D6 */
+		SUNXI_FUNCTION(0x3, "pata"),		/* ATAD2 */
+		SUNXI_FUNCTION(0x4, "uart5"),		/* TX */
+		SUNXI_FUNCTION(0x5, "ms"),		/* BS */
+		SUNXI_FUNCTION(0x7, "csi1")),		/* D6 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PH7,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd1"),		/* D7 */
+		SUNXI_FUNCTION(0x3, "pata"),		/* ATAD3 */
+		SUNXI_FUNCTION(0x4, "uart5"),		/* RX */
+		SUNXI_FUNCTION(0x5, "ms"),		/* CLK */
+		SUNXI_FUNCTION(0x7, "csi1")),		/* D7 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PH8,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd1"),		/* D8 */
+		SUNXI_FUNCTION(0x3, "pata"),		/* ATAD4 */
+		SUNXI_FUNCTION(0x4, "keypad"),		/* IN0 */
+		SUNXI_FUNCTION(0x5, "ms"),		/* D0 */
+		SUNXI_FUNCTION(0x7, "csi1")),		/* D8 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PH9,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd1"),		/* D9 */
+		SUNXI_FUNCTION(0x3, "pata"),		/* ATAD5 */
+		SUNXI_FUNCTION(0x4, "keypad"),		/* IN1 */
+		SUNXI_FUNCTION(0x5, "ms"),		/* D1 */
+		SUNXI_FUNCTION(0x7, "csi1")),		/* D9 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PH10,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd1"),		/* D10 */
+		SUNXI_FUNCTION(0x3, "pata"),		/* ATAD6 */
+		SUNXI_FUNCTION(0x4, "keypad"),		/* IN2 */
+		SUNXI_FUNCTION(0x5, "ms"),		/* D2 */
+		SUNXI_FUNCTION(0x7, "csi1")),		/* D10 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PH11,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd1"),		/* D11 */
+		SUNXI_FUNCTION(0x3, "pata"),		/* ATAD7 */
+		SUNXI_FUNCTION(0x4, "keypad"),		/* IN3 */
+		SUNXI_FUNCTION(0x5, "ms"),		/* D3 */
+		SUNXI_FUNCTION(0x7, "csi1")),		/* D11 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PH12,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd1"),		/* D12 */
+		SUNXI_FUNCTION(0x3, "pata"),		/* ATAD8 */
+		SUNXI_FUNCTION(0x4, "ps2"),		/* SCK1 */
+		SUNXI_FUNCTION(0x7, "csi1")),		/* D12 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PH13,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd1"),		/* D13 */
+		SUNXI_FUNCTION(0x3, "pata"),		/* ATAD9 */
+		SUNXI_FUNCTION(0x4, "ps2"),		/* SDA1 */
+		SUNXI_FUNCTION(0x5, "sim"),		/* RST */
+		SUNXI_FUNCTION(0x7, "csi1")),		/* D13 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PH14,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd1"),		/* D14 */
+		SUNXI_FUNCTION(0x3, "pata"),		/* ATAD10 */
+		SUNXI_FUNCTION(0x4, "keypad"),		/* IN4 */
+		SUNXI_FUNCTION(0x5, "sim"),		/* VPPEN */
+		SUNXI_FUNCTION(0x7, "csi1")),		/* D14 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PH15,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd1"),		/* D15 */
+		SUNXI_FUNCTION(0x3, "pata"),		/* ATAD11 */
+		SUNXI_FUNCTION(0x4, "keypad"),		/* IN5 */
+		SUNXI_FUNCTION(0x5, "sim"),		/* VPPPP */
+		SUNXI_FUNCTION(0x7, "csi1")),		/* D15 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PH16,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd1"),		/* D16 */
+		SUNXI_FUNCTION(0x3, "pata"),		/* ATAD12 */
+		SUNXI_FUNCTION(0x4, "keypad"),		/* IN6 */
+		SUNXI_FUNCTION(0x7, "csi1")),		/* D16 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PH17,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd1"),		/* D17 */
+		SUNXI_FUNCTION(0x3, "pata"),		/* ATAD13 */
+		SUNXI_FUNCTION(0x4, "keypad"),		/* IN7 */
+		SUNXI_FUNCTION(0x5, "sim"),		/* VCCEN */
+		SUNXI_FUNCTION(0x7, "csi1")),		/* D17 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PH18,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd1"),		/* D18 */
+		SUNXI_FUNCTION(0x3, "pata"),		/* ATAD14 */
+		SUNXI_FUNCTION(0x4, "keypad"),		/* OUT0 */
+		SUNXI_FUNCTION(0x5, "sim"),		/* SCK */
+		SUNXI_FUNCTION(0x7, "csi1")),		/* D18 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PH19,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd1"),		/* D19 */
+		SUNXI_FUNCTION(0x3, "pata"),		/* ATAD15 */
+		SUNXI_FUNCTION(0x4, "keypad"),		/* OUT1 */
+		SUNXI_FUNCTION(0x5, "sim"),		/* SDA */
+		SUNXI_FUNCTION(0x7, "csi1")),		/* D19 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PH20,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd1"),		/* D20 */
+		SUNXI_FUNCTION(0x3, "pata"),		/* ATAOE */
+		SUNXI_FUNCTION(0x4, "can"),		/* TX */
+		SUNXI_FUNCTION(0x7, "csi1")),		/* D20 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PH21,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd1"),		/* D21 */
+		SUNXI_FUNCTION(0x3, "pata"),		/* ATADREQ */
+		SUNXI_FUNCTION(0x4, "can"),		/* RX */
+		SUNXI_FUNCTION(0x7, "csi1")),		/* D21 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PH22,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd1"),		/* D22 */
+		SUNXI_FUNCTION(0x3, "pata"),		/* ATADACK */
+		SUNXI_FUNCTION(0x4, "keypad"),		/* OUT2 */
+		SUNXI_FUNCTION(0x5, "mmc1"),		/* CMD */
+		SUNXI_FUNCTION(0x7, "csi1")),		/* D22 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PH23,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd1"),		/* D23 */
+		SUNXI_FUNCTION(0x3, "pata"),		/* ATACS0 */
+		SUNXI_FUNCTION(0x4, "keypad"),		/* OUT3 */
+		SUNXI_FUNCTION(0x5, "mmc1"),		/* CLK */
+		SUNXI_FUNCTION(0x7, "csi1")),		/* D23 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PH24,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd1"),		/* CLK */
+		SUNXI_FUNCTION(0x3, "pata"),		/* ATACS1 */
+		SUNXI_FUNCTION(0x4, "keypad"),		/* OUT4 */
+		SUNXI_FUNCTION(0x5, "mmc1"),		/* D0 */
+		SUNXI_FUNCTION(0x7, "csi1")),		/* PCLK */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PH25,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd1"),		/* DE */
+		SUNXI_FUNCTION(0x3, "pata"),		/* ATAIORDY */
+		SUNXI_FUNCTION(0x4, "keypad"),		/* OUT5 */
+		SUNXI_FUNCTION(0x5, "mmc1"),		/* D1 */
+		SUNXI_FUNCTION(0x7, "csi1")),		/* FIELD */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PH26,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd1"),		/* HSYNC */
+		SUNXI_FUNCTION(0x3, "pata"),		/* ATAIOR */
+		SUNXI_FUNCTION(0x4, "keypad"),		/* OUT6 */
+		SUNXI_FUNCTION(0x5, "mmc1"),		/* D2 */
+		SUNXI_FUNCTION(0x7, "csi1")),		/* HSYNC */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PH27,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd1"),		/* VSYNC */
+		SUNXI_FUNCTION(0x3, "pata"),		/* ATAIOW */
+		SUNXI_FUNCTION(0x4, "keypad"),		/* OUT7 */
+		SUNXI_FUNCTION(0x5, "mmc1"),		/* D3 */
+		SUNXI_FUNCTION(0x7, "csi1")),		/* VSYNC */
 	/* Hole */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PI0,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
@@ -518,277 +893,401 @@ static const struct sunxi_desc_pin sun4i_a10_pins[] = {
 		SUNXI_FUNCTION(0x1, "gpio_out")),
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PI3,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "pwm")),		/* PWM1 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PI4,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "mmc3")),		/* CMD */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PI5,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "mmc3")),		/* CLK */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PI6,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "mmc3")),		/* D0 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PI7,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "mmc3")),		/* D1 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PI8,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "mmc3")),		/* D2 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PI9,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "mmc3")),		/* D3 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PI10,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "spi0"),		/* CS0 */
+		SUNXI_FUNCTION(0x3, "uart5")),		/* TX */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PI11,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "spi0"),		/* CLK */
+		SUNXI_FUNCTION(0x3, "uart5")),		/* RX */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PI12,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "spi0"),		/* MOSI */
+		SUNXI_FUNCTION(0x3, "uart6")),		/* TX */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PI13,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "spi0"),		/* MISO */
+		SUNXI_FUNCTION(0x3, "uart6")),		/* RX */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PI14,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "spi0"),		/* CS1 */
+		SUNXI_FUNCTION(0x3, "ps2"),		/* SCK1 */
+		SUNXI_FUNCTION(0x4, "timer4")),		/* TCLKIN0 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PI15,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "spi1"),		/* CS1 */
+		SUNXI_FUNCTION(0x3, "ps2"),		/* SDA1 */
+		SUNXI_FUNCTION(0x4, "timer5")),		/* TCLKIN1 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PI16,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "spi1"),		/* CS0 */
+		SUNXI_FUNCTION(0x3, "uart2")),		/* RTS */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PI17,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "spi1"),		/* CLK */
+		SUNXI_FUNCTION(0x3, "uart2")),		/* CTS */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PI18,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "spi1"),		/* MOSI */
+		SUNXI_FUNCTION(0x3, "uart2")),		/* TX */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PI19,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "spi1"),		/* MISO */
+		SUNXI_FUNCTION(0x3, "uart2")),		/* RX */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PI20,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ps2"),		/* SCK0 */
+		SUNXI_FUNCTION(0x3, "uart7"),		/* TX */
+		SUNXI_FUNCTION(0x4, "hdmi")),		/* HSCL */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PI21,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ps2"),		/* SDA0 */
+		SUNXI_FUNCTION(0x3, "uart7"),		/* RX */
+		SUNXI_FUNCTION(0x4, "hdmi")),		/* HSDA */
 };
 
 static const struct sunxi_desc_pin sun5i_a13_pins[] = {
 	/* Hole */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PB0,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "i2c0")),		/* SCK */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PB1,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "i2c0")),		/* SDA */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PB2,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "pwm")),
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PB3,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ir0")),		/* TX */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PB4,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ir0")),		/* RX */
 	/* Hole */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PB10,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "spi2")),		/* CS1 */
 	/* Hole */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PB15,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "i2c1")),		/* SCK */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PB16,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "i2c1")),		/* SDA */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PB17,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "i2c2")),		/* SCK */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PB18,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "i2c2")),		/* SDA */
 	/* Hole */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PC0,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "nand0"),		/* NWE */
+		SUNXI_FUNCTION(0x3, "spi0")),		/* MOSI */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PC1,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "nand0"),		/* NALE */
+		SUNXI_FUNCTION(0x3, "spi0")),		/* MISO */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PC2,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "nand0"),		/* NCLE */
+		SUNXI_FUNCTION(0x3, "spi0")),		/* CLK */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PC3,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "nand0"),		/* NCE1 */
+		SUNXI_FUNCTION(0x3, "spi0")),		/* CS0 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PC4,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "nand0")),		/* NCE0 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PC5,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "nand0")),		/* NRE */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PC6,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "nand0"),		/* NRB0 */
+		SUNXI_FUNCTION(0x3, "mmc2")),		/* CMD */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PC7,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "nand0"),		/* NRB1 */
+		SUNXI_FUNCTION(0x3, "mmc2")),		/* CLK */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PC8,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "nand0"),		/* NDQ0 */
+		SUNXI_FUNCTION(0x3, "mmc2")),		/* D0 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PC9,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "nand0"),		/* NDQ1 */
+		SUNXI_FUNCTION(0x3, "mmc2")),		/* D1 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PC10,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "nand0"),		/* NDQ2 */
+		SUNXI_FUNCTION(0x3, "mmc2")),		/* D2 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PC11,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "nand0"),		/* NDQ3 */
+		SUNXI_FUNCTION(0x3, "mmc2")),		/* D3 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PC12,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "nand0"),		/* NDQ4 */
+		SUNXI_FUNCTION(0x3, "mmc2")),		/* D4 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PC13,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "nand0"),		/* NDQ5 */
+		SUNXI_FUNCTION(0x3, "mmc2")),		/* D5 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PC14,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "nand0"),		/* NDQ6 */
+		SUNXI_FUNCTION(0x3, "mmc2")),		/* D6 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PC15,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "nand0"),		/* NDQ7 */
+		SUNXI_FUNCTION(0x3, "mmc2")),		/* D7 */
 	/* Hole */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PC19,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "nand0"),		/* NDQS */
+		SUNXI_FUNCTION(0x4, "uart3")),		/* RTS */
 	/* Hole */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PD2,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0")),		/* D2 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PD3,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0")),		/* D3 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PD4,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0")),		/* D4 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PD5,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0")),		/* D5 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PD6,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0")),		/* D6 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PD7,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0")),		/* D7 */
 	/* Hole */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PD10,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0")),		/* D10 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PD11,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0")),		/* D11 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PD12,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0")),		/* D12 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PD13,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0")),		/* D13 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PD14,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0")),		/* D14 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PD15,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0")),		/* D15 */
 	/* Hole */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PD18,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0")),		/* D18 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PD19,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0")),		/* D19 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PD20,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0")),		/* D20 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PD21,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0")),		/* D21 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PD22,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0")),		/* D22 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PD23,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0")),		/* D23 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PD24,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0")),		/* CLK */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PD25,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0")),		/* DE */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PD26,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0")),		/* HSYNC */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PD27,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0")),		/* VSYNC */
 	/* Hole */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PE0,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x3, "csi0"),		/* PCLK */
+		SUNXI_FUNCTION(0x4, "spi2")),		/* CS0 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PE1,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x3, "csi0"),		/* MCLK */
+		SUNXI_FUNCTION(0x4, "spi2")),		/* CLK */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PE2,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x3, "csi0"),		/* HSYNC */
+		SUNXI_FUNCTION(0x4, "spi2")),		/* MOSI */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PE3,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x3, "csi0"),		/* VSYNC */
+		SUNXI_FUNCTION(0x4, "spi2")),		/* MISO */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PE4,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x3, "csi0"),		/* D0 */
+		SUNXI_FUNCTION(0x4, "mmc2")),		/* D0 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PE5,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x3, "csi0"),		/* D1 */
+		SUNXI_FUNCTION(0x4, "mmc2")),		/* D1 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PE6,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x3, "csi0"),		/* D2 */
+		SUNXI_FUNCTION(0x4, "mmc2")),		/* D2 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PE7,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x3, "csi0"),		/* D3 */
+		SUNXI_FUNCTION(0x4, "mmc2")),		/* D3 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PE8,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x3, "csi0"),		/* D4 */
+		SUNXI_FUNCTION(0x4, "mmc2")),		/* CMD */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PE9,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x3, "csi0"),		/* D5 */
+		SUNXI_FUNCTION(0x4, "mmc2")),		/* CLK */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PE10,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
 		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x3, "csi0"),		/* D6 */
 		SUNXI_FUNCTION(0x4, "uart1")),		/* TX */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PE11,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
 		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x3, "csi0"),		/* D7 */
 		SUNXI_FUNCTION(0x4, "uart1")),		/* RX */
 	/* Hole */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PF0,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x4, "mmc0")),		/* D1 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PF1,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x4, "mmc0")),		/* D0 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PF2,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x4, "mmc0")),		/* CLK */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PF3,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x4, "mmc0")),		/* CMD */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PF4,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x4, "mmc0")),		/* D3 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PF5,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x4, "mmc0")),		/* D2 */
 	/* Hole */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PG0,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
@@ -802,24 +1301,34 @@ static const struct sunxi_desc_pin sun5i_a13_pins[] = {
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PG3,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
 		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "mmc1"),		/* CMD */
 		SUNXI_FUNCTION(0x4, "uart1")),		/* TX */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PG4,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
 		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "mmc1"),		/* CLK */
 		SUNXI_FUNCTION(0x4, "uart1")),		/* RX */
-	/* Hole */
+/* Hole */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PG9,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "spi1"),		/* CS0 */
+		SUNXI_FUNCTION(0x3, "uart3")),		/* TX */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PG10,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "spi1"),		/* CLK */
+		SUNXI_FUNCTION(0x3, "uart3")),		/* RX */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PG11,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "spi1"),		/* MOSI */
+		SUNXI_FUNCTION(0x3, "uart3")),		/* CTS */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN_PG12,
 		SUNXI_FUNCTION(0x0, "gpio_in"),
-		SUNXI_FUNCTION(0x1, "gpio_out")),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "spi1"),		/* MISO */
+		SUNXI_FUNCTION(0x3, "uart3")),		/* RTS */
 };
 
 static const struct sunxi_pinctrl_desc sun4i_a10_pinctrl_data = {
@@ -1029,7 +1538,7 @@ static void sunxi_pctrl_dt_free_map(struct pinctrl_dev *pctldev,
 	kfree(map);
 }
 
-static struct pinctrl_ops sunxi_pctrl_ops = {
+static const struct pinctrl_ops sunxi_pctrl_ops = {
 	.dt_node_to_map		= sunxi_pctrl_dt_node_to_map,
 	.dt_free_map		= sunxi_pctrl_dt_free_map,
 	.get_groups_count	= sunxi_pctrl_get_groups_count,
@@ -1098,7 +1607,7 @@ static int sunxi_pconf_group_set(struct pinctrl_dev *pctldev,
 	return 0;
 }
 
-static struct pinconf_ops sunxi_pconf_ops = {
+static const struct pinconf_ops sunxi_pconf_ops = {
 	.pin_config_group_get	= sunxi_pconf_group_get,
 	.pin_config_group_set	= sunxi_pconf_group_set,
 };
@@ -1204,7 +1713,7 @@ error:
 	return ret;
 }
 
-static struct pinmux_ops sunxi_pmx_ops = {
+static const struct pinmux_ops sunxi_pmx_ops = {
 	.get_functions_count	= sunxi_pmx_get_funcs_cnt,
 	.get_function_name	= sunxi_pmx_get_func_name,
 	.get_function_groups	= sunxi_pmx_get_func_groups,
@@ -1409,6 +1918,7 @@ static int sunxi_pinctrl_probe(struct platform_device *pdev)
 	struct pinctrl_pin_desc *pins;
 	struct sunxi_pinctrl *pctl;
 	int i, ret, last_pin;
+	struct clk *clk;
 
 	pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
 	if (!pctl)
@@ -1479,6 +1989,12 @@ static int sunxi_pinctrl_probe(struct platform_device *pdev)
 			goto gpiochip_error;
 	}
 
+	clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(clk))
+		goto gpiochip_error;
+
+	clk_prepare_enable(clk);
+
 	dev_info(&pdev->dev, "initialized sunXi PIO driver\n");
 
 	return 0;
diff --git a/drivers/pinctrl/pinctrl-tegra.c b/drivers/pinctrl/pinctrl-tegra.c
index f195d77..2fa9bc6 100644
--- a/drivers/pinctrl/pinctrl-tegra.c
+++ b/drivers/pinctrl/pinctrl-tegra.c
@@ -316,7 +316,7 @@ static int tegra_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
 	return 0;
 }
 
-static struct pinctrl_ops tegra_pinctrl_ops = {
+static const struct pinctrl_ops tegra_pinctrl_ops = {
 	.get_groups_count = tegra_pinctrl_get_groups_count,
 	.get_group_name = tegra_pinctrl_get_group_name,
 	.get_group_pins = tegra_pinctrl_get_group_pins,
@@ -401,7 +401,7 @@ static void tegra_pinctrl_disable(struct pinctrl_dev *pctldev,
 	pmx_writel(pmx, val, g->mux_bank, g->mux_reg);
 }
 
-static struct pinmux_ops tegra_pinmux_ops = {
+static const struct pinmux_ops tegra_pinmux_ops = {
 	.get_functions_count = tegra_pinctrl_get_funcs_count,
 	.get_function_name = tegra_pinctrl_get_func_name,
 	.get_function_groups = tegra_pinctrl_get_func_groups,
@@ -676,7 +676,7 @@ static void tegra_pinconf_config_dbg_show(struct pinctrl_dev *pctldev,
 }
 #endif
 
-static struct pinconf_ops tegra_pinconf_ops = {
+static const struct pinconf_ops tegra_pinconf_ops = {
 	.pin_config_get = tegra_pinconf_get,
 	.pin_config_set = tegra_pinconf_set,
 	.pin_config_group_get = tegra_pinconf_group_get,
diff --git a/drivers/pinctrl/pinctrl-u300.c b/drivers/pinctrl/pinctrl-u300.c
index 2b57725..6a3a750 100644
--- a/drivers/pinctrl/pinctrl-u300.c
+++ b/drivers/pinctrl/pinctrl-u300.c
@@ -860,7 +860,7 @@ static void u300_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
 	seq_printf(s, " " DRIVER_NAME);
 }
 
-static struct pinctrl_ops u300_pctrl_ops = {
+static const struct pinctrl_ops u300_pctrl_ops = {
 	.get_groups_count = u300_get_groups_count,
 	.get_group_name = u300_get_group_name,
 	.get_group_pins = u300_get_group_pins,
@@ -1003,7 +1003,7 @@ static int u300_pmx_get_groups(struct pinctrl_dev *pctldev, unsigned selector,
 	return 0;
 }
 
-static struct pinmux_ops u300_pmx_ops = {
+static const struct pinmux_ops u300_pmx_ops = {
 	.get_functions_count = u300_pmx_get_funcs_count,
 	.get_function_name = u300_pmx_get_func_name,
 	.get_function_groups = u300_pmx_get_groups,
@@ -1046,7 +1046,7 @@ static int u300_pin_config_set(struct pinctrl_dev *pctldev, unsigned pin,
 	return 0;
 }
 
-static struct pinconf_ops u300_pconf_ops = {
+static const struct pinconf_ops u300_pconf_ops = {
 	.is_generic = true,
 	.pin_config_get = u300_pin_config_get,
 	.pin_config_set = u300_pin_config_set,
diff --git a/drivers/pinctrl/pinctrl-xway.c b/drivers/pinctrl/pinctrl-xway.c
index 068224e..f2977cf 100644
--- a/drivers/pinctrl/pinctrl-xway.c
+++ b/drivers/pinctrl/pinctrl-xway.c
@@ -553,7 +553,7 @@ int xway_pinconf_group_set(struct pinctrl_dev *pctldev,
 	return ret;
 }
 
-static struct pinconf_ops xway_pinconf_ops = {
+static const struct pinconf_ops xway_pinconf_ops = {
 	.pin_config_get	= xway_pinconf_get,
 	.pin_config_set	= xway_pinconf_set,
 	.pin_config_group_set = xway_pinconf_group_set,
diff --git a/drivers/pinctrl/sh-pfc/Kconfig b/drivers/pinctrl/sh-pfc/Kconfig
index c3340f5..0e1f99c 100644
--- a/drivers/pinctrl/sh-pfc/Kconfig
+++ b/drivers/pinctrl/sh-pfc/Kconfig
@@ -10,6 +10,7 @@ config PINCTRL_SH_PFC
 	select GPIO_SH_PFC if ARCH_REQUIRE_GPIOLIB
 	select PINMUX
 	select PINCONF
+	select GENERIC_PINCONF
 	def_bool y
 	help
 	  This enables pin control drivers for SH and SH Mobile platforms
@@ -21,6 +22,11 @@ config GPIO_SH_PFC
 	  This enables support for GPIOs within the SoC's pin function
 	  controller.
 
+config PINCTRL_PFC_R8A73A4
+	def_bool y
+	depends on ARCH_R8A73A4
+	select PINCTRL_SH_PFC
+
 config PINCTRL_PFC_R8A7740
 	def_bool y
 	depends on ARCH_R8A7740
diff --git a/drivers/pinctrl/sh-pfc/Makefile b/drivers/pinctrl/sh-pfc/Makefile
index e8b9562..211cd8e 100644
--- a/drivers/pinctrl/sh-pfc/Makefile
+++ b/drivers/pinctrl/sh-pfc/Makefile
@@ -3,6 +3,7 @@ ifeq ($(CONFIG_GPIO_SH_PFC),y)
 sh-pfc-objs			+= gpio.o
 endif
 obj-$(CONFIG_PINCTRL_SH_PFC)	+= sh-pfc.o
+obj-$(CONFIG_PINCTRL_PFC_R8A73A4)	+= pfc-r8a73a4.o
 obj-$(CONFIG_PINCTRL_PFC_R8A7740)	+= pfc-r8a7740.o
 obj-$(CONFIG_PINCTRL_PFC_R8A7779)	+= pfc-r8a7779.o
 obj-$(CONFIG_PINCTRL_PFC_SH7203)	+= pfc-sh7203.o
diff --git a/drivers/pinctrl/sh-pfc/core.c b/drivers/pinctrl/sh-pfc/core.c
index 970ddff..b551336 100644
--- a/drivers/pinctrl/sh-pfc/core.c
+++ b/drivers/pinctrl/sh-pfc/core.c
@@ -10,7 +10,6 @@
  */
 
 #define DRV_NAME "sh-pfc"
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/bitops.h>
 #include <linux/err.h>
@@ -30,10 +29,8 @@ static int sh_pfc_ioremap(struct sh_pfc *pfc, struct platform_device *pdev)
 	struct resource *res;
 	int k;
 
-	if (pdev->num_resources == 0) {
-		pfc->num_windows = 0;
-		return 0;
-	}
+	if (pdev->num_resources == 0)
+		return -EINVAL;
 
 	pfc->window = devm_kzalloc(pfc->dev, pdev->num_resources *
 				   sizeof(*pfc->window), GFP_NOWAIT);
@@ -59,11 +56,11 @@ static void __iomem *sh_pfc_phys_to_virt(struct sh_pfc *pfc,
 					 unsigned long address)
 {
 	struct sh_pfc_window *window;
-	int k;
+	unsigned int i;
 
 	/* scan through physical windows and convert address */
-	for (k = 0; k < pfc->num_windows; k++) {
-		window = pfc->window + k;
+	for (i = 0; i < pfc->num_windows; i++) {
+		window = pfc->window + i;
 
 		if (address < window->phys)
 			continue;
@@ -74,11 +71,33 @@ static void __iomem *sh_pfc_phys_to_virt(struct sh_pfc *pfc,
 		return window->virt + (address - window->phys);
 	}
 
-	/* no windows defined, register must be 1:1 mapped virt:phys */
-	return (void __iomem *)address;
+	BUG();
+	return NULL;
+}
+
+int sh_pfc_get_pin_index(struct sh_pfc *pfc, unsigned int pin)
+{
+	unsigned int offset;
+	unsigned int i;
+
+	if (pfc->info->ranges == NULL)
+		return pin;
+
+	for (i = 0, offset = 0; i < pfc->info->nr_ranges; ++i) {
+		const struct pinmux_range *range = &pfc->info->ranges[i];
+
+		if (pin <= range->end)
+			return pin >= range->begin
+			     ? offset + pin - range->begin : -1;
+
+		offset += range->end - range->begin + 1;
+	}
+
+	return -EINVAL;
 }
 
-static int sh_pfc_enum_in_range(pinmux_enum_t enum_id, struct pinmux_range *r)
+static int sh_pfc_enum_in_range(pinmux_enum_t enum_id,
+				const struct pinmux_range *r)
 {
 	if (enum_id < r->begin)
 		return 0;
@@ -89,8 +108,8 @@ static int sh_pfc_enum_in_range(pinmux_enum_t enum_id, struct pinmux_range *r)
 	return 1;
 }
 
-static unsigned long sh_pfc_read_raw_reg(void __iomem *mapped_reg,
-					 unsigned long reg_width)
+unsigned long sh_pfc_read_raw_reg(void __iomem *mapped_reg,
+				  unsigned long reg_width)
 {
 	switch (reg_width) {
 	case 8:
@@ -105,8 +124,8 @@ static unsigned long sh_pfc_read_raw_reg(void __iomem *mapped_reg,
 	return 0;
 }
 
-static void sh_pfc_write_raw_reg(void __iomem *mapped_reg,
-				 unsigned long reg_width, unsigned long data)
+void sh_pfc_write_raw_reg(void __iomem *mapped_reg, unsigned long reg_width,
+			  unsigned long data)
 {
 	switch (reg_width) {
 	case 8:
@@ -123,39 +142,8 @@ static void sh_pfc_write_raw_reg(void __iomem *mapped_reg,
 	BUG();
 }
 
-int sh_pfc_read_bit(struct pinmux_data_reg *dr, unsigned long in_pos)
-{
-	unsigned long pos;
-
-	pos = dr->reg_width - (in_pos + 1);
-
-	pr_debug("read_bit: addr = %lx, pos = %ld, "
-		 "r_width = %ld\n", dr->reg, pos, dr->reg_width);
-
-	return (sh_pfc_read_raw_reg(dr->mapped_reg, dr->reg_width) >> pos) & 1;
-}
-
-void sh_pfc_write_bit(struct pinmux_data_reg *dr, unsigned long in_pos,
-		      unsigned long value)
-{
-	unsigned long pos;
-
-	pos = dr->reg_width - (in_pos + 1);
-
-	pr_debug("write_bit addr = %lx, value = %d, pos = %ld, "
-		 "r_width = %ld\n",
-		 dr->reg, !!value, pos, dr->reg_width);
-
-	if (value)
-		set_bit(pos, &dr->reg_shadow);
-	else
-		clear_bit(pos, &dr->reg_shadow);
-
-	sh_pfc_write_raw_reg(dr->mapped_reg, dr->reg_width, dr->reg_shadow);
-}
-
 static void sh_pfc_config_reg_helper(struct sh_pfc *pfc,
-				     struct pinmux_cfg_reg *crp,
+				     const struct pinmux_cfg_reg *crp,
 				     unsigned long in_pos,
 				     void __iomem **mapped_regp,
 				     unsigned long *maskp,
@@ -176,24 +164,8 @@ static void sh_pfc_config_reg_helper(struct sh_pfc *pfc,
 	}
 }
 
-static int sh_pfc_read_config_reg(struct sh_pfc *pfc,
-				  struct pinmux_cfg_reg *crp,
-				  unsigned long field)
-{
-	void __iomem *mapped_reg;
-	unsigned long mask, pos;
-
-	sh_pfc_config_reg_helper(pfc, crp, field, &mapped_reg, &mask, &pos);
-
-	pr_debug("read_reg: addr = %lx, field = %ld, "
-		 "r_width = %ld, f_width = %ld\n",
-		 crp->reg, field, crp->reg_width, crp->field_width);
-
-	return (sh_pfc_read_raw_reg(mapped_reg, crp->reg_width) >> pos) & mask;
-}
-
 static void sh_pfc_write_config_reg(struct sh_pfc *pfc,
-				    struct pinmux_cfg_reg *crp,
+				    const struct pinmux_cfg_reg *crp,
 				    unsigned long field, unsigned long value)
 {
 	void __iomem *mapped_reg;
@@ -201,9 +173,9 @@ static void sh_pfc_write_config_reg(struct sh_pfc *pfc,
 
 	sh_pfc_config_reg_helper(pfc, crp, field, &mapped_reg, &mask, &pos);
 
-	pr_debug("write_reg addr = %lx, value = %ld, field = %ld, "
-		 "r_width = %ld, f_width = %ld\n",
-		 crp->reg, value, field, crp->reg_width, crp->field_width);
+	dev_dbg(pfc->dev, "write_reg addr = %lx, value = %ld, field = %ld, "
+		"r_width = %ld, f_width = %ld\n",
+		crp->reg, value, field, crp->reg_width, crp->field_width);
 
 	mask = ~(mask << pos);
 	value = value << pos;
@@ -220,83 +192,11 @@ static void sh_pfc_write_config_reg(struct sh_pfc *pfc,
 	sh_pfc_write_raw_reg(mapped_reg, crp->reg_width, data);
 }
 
-static int sh_pfc_setup_data_reg(struct sh_pfc *pfc, unsigned gpio)
-{
-	struct pinmux_gpio *gpiop = &pfc->info->gpios[gpio];
-	struct pinmux_data_reg *data_reg;
-	int k, n;
-
-	if (!sh_pfc_enum_in_range(gpiop->enum_id, &pfc->info->data))
-		return -1;
-
-	k = 0;
-	while (1) {
-		data_reg = pfc->info->data_regs + k;
-
-		if (!data_reg->reg_width)
-			break;
-
-		data_reg->mapped_reg = sh_pfc_phys_to_virt(pfc, data_reg->reg);
-
-		for (n = 0; n < data_reg->reg_width; n++) {
-			if (data_reg->enum_ids[n] == gpiop->enum_id) {
-				gpiop->flags &= ~PINMUX_FLAG_DREG;
-				gpiop->flags |= (k << PINMUX_FLAG_DREG_SHIFT);
-				gpiop->flags &= ~PINMUX_FLAG_DBIT;
-				gpiop->flags |= (n << PINMUX_FLAG_DBIT_SHIFT);
-				return 0;
-			}
-		}
-		k++;
-	}
-
-	BUG();
-
-	return -1;
-}
-
-static void sh_pfc_setup_data_regs(struct sh_pfc *pfc)
-{
-	struct pinmux_data_reg *drp;
-	int k;
-
-	for (k = pfc->info->first_gpio; k <= pfc->info->last_gpio; k++)
-		sh_pfc_setup_data_reg(pfc, k);
-
-	k = 0;
-	while (1) {
-		drp = pfc->info->data_regs + k;
-
-		if (!drp->reg_width)
-			break;
-
-		drp->reg_shadow = sh_pfc_read_raw_reg(drp->mapped_reg,
-						      drp->reg_width);
-		k++;
-	}
-}
-
-int sh_pfc_get_data_reg(struct sh_pfc *pfc, unsigned gpio,
-			struct pinmux_data_reg **drp, int *bitp)
-{
-	struct pinmux_gpio *gpiop = &pfc->info->gpios[gpio];
-	int k, n;
-
-	if (!sh_pfc_enum_in_range(gpiop->enum_id, &pfc->info->data))
-		return -1;
-
-	k = (gpiop->flags & PINMUX_FLAG_DREG) >> PINMUX_FLAG_DREG_SHIFT;
-	n = (gpiop->flags & PINMUX_FLAG_DBIT) >> PINMUX_FLAG_DBIT_SHIFT;
-	*drp = pfc->info->data_regs + k;
-	*bitp = n;
-	return 0;
-}
-
 static int sh_pfc_get_config_reg(struct sh_pfc *pfc, pinmux_enum_t enum_id,
-				 struct pinmux_cfg_reg **crp, int *fieldp,
-				 int *valuep, unsigned long **cntp)
+				 const struct pinmux_cfg_reg **crp, int *fieldp,
+				 int *valuep)
 {
-	struct pinmux_cfg_reg *config_reg;
+	const struct pinmux_cfg_reg *config_reg;
 	unsigned long r_width, f_width, curr_width, ncomb;
 	int k, m, n, pos, bit_pos;
 
@@ -324,7 +224,6 @@ static int sh_pfc_get_config_reg(struct sh_pfc *pfc, pinmux_enum_t enum_id,
 					*crp = config_reg;
 					*fieldp = m;
 					*valuep = n;
-					*cntp = &config_reg->cnt[m];
 					return 0;
 				}
 			}
@@ -334,50 +233,42 @@ static int sh_pfc_get_config_reg(struct sh_pfc *pfc, pinmux_enum_t enum_id,
 		k++;
 	}
 
-	return -1;
+	return -EINVAL;
 }
 
-int sh_pfc_gpio_to_enum(struct sh_pfc *pfc, unsigned gpio, int pos,
-			pinmux_enum_t *enum_idp)
+static int sh_pfc_mark_to_enum(struct sh_pfc *pfc, pinmux_enum_t mark, int pos,
+			      pinmux_enum_t *enum_idp)
 {
-	pinmux_enum_t enum_id = pfc->info->gpios[gpio].enum_id;
-	pinmux_enum_t *data = pfc->info->gpio_data;
+	const pinmux_enum_t *data = pfc->info->gpio_data;
 	int k;
 
-	if (!sh_pfc_enum_in_range(enum_id, &pfc->info->data)) {
-		if (!sh_pfc_enum_in_range(enum_id, &pfc->info->mark)) {
-			pr_err("non data/mark enum_id for gpio %d\n", gpio);
-			return -1;
-		}
-	}
-
 	if (pos) {
 		*enum_idp = data[pos + 1];
 		return pos + 1;
 	}
 
 	for (k = 0; k < pfc->info->gpio_data_size; k++) {
-		if (data[k] == enum_id) {
+		if (data[k] == mark) {
 			*enum_idp = data[k + 1];
 			return k + 1;
 		}
 	}
 
-	pr_err("cannot locate data/mark enum_id for gpio %d\n", gpio);
-	return -1;
+	dev_err(pfc->dev, "cannot locate data/mark enum_id for mark %d\n",
+		mark);
+	return -EINVAL;
 }
 
-int sh_pfc_config_gpio(struct sh_pfc *pfc, unsigned gpio, int pinmux_type,
-		       int cfg_mode)
+int sh_pfc_config_mux(struct sh_pfc *pfc, unsigned mark, int pinmux_type)
 {
-	struct pinmux_cfg_reg *cr = NULL;
+	const struct pinmux_cfg_reg *cr = NULL;
 	pinmux_enum_t enum_id;
-	struct pinmux_range *range;
+	const struct pinmux_range *range;
 	int in_range, pos, field, value;
-	unsigned long *cntp;
+	int ret;
 
 	switch (pinmux_type) {
-
+	case PINMUX_TYPE_GPIO:
 	case PINMUX_TYPE_FUNCTION:
 		range = NULL;
 		break;
@@ -399,33 +290,37 @@ int sh_pfc_config_gpio(struct sh_pfc *pfc, unsigned gpio, int pinmux_type,
 		break;
 
 	default:
-		goto out_err;
+		return -EINVAL;
 	}
 
 	pos = 0;
 	enum_id = 0;
 	field = 0;
 	value = 0;
+
+	/* Iterate over all the configuration fields we need to update. */
 	while (1) {
-		pos = sh_pfc_gpio_to_enum(pfc, gpio, pos, &enum_id);
-		if (pos <= 0)
-			goto out_err;
+		pos = sh_pfc_mark_to_enum(pfc, mark, pos, &enum_id);
+		if (pos < 0)
+			return pos;
 
 		if (!enum_id)
 			break;
 
-		/* first check if this is a function enum */
+		/* Check if the configuration field selects a function. If it
+		 * doesn't, skip the field if it's not applicable to the
+		 * requested pinmux type.
+		 */
 		in_range = sh_pfc_enum_in_range(enum_id, &pfc->info->function);
 		if (!in_range) {
-			/* not a function enum */
-			if (range) {
-				/*
-				 * other range exists, so this pin is
-				 * a regular GPIO pin that now is being
-				 * bound to a specific direction.
-				 *
-				 * for this case we only allow function enums
-				 * and the enums that match the other range.
+			if (pinmux_type == PINMUX_TYPE_FUNCTION) {
+				/* Functions are allowed to modify all
+				 * fields.
+				 */
+				in_range = 1;
+			} else if (pinmux_type != PINMUX_TYPE_GPIO) {
+				/* Input/output types can only modify fields
+				 * that correspond to their respective ranges.
 				 */
 				in_range = sh_pfc_enum_in_range(enum_id, range);
 
@@ -436,60 +331,29 @@ int sh_pfc_config_gpio(struct sh_pfc *pfc, unsigned gpio, int pinmux_type,
 				 */
 				if (in_range && enum_id == range->force)
 					continue;
-			} else {
-				/*
-				 * no other range exists, so this pin
-				 * must then be of the function type.
-				 *
-				 * allow function type pins to select
-				 * any combination of function/in/out
-				 * in their MARK lists.
-				 */
-				in_range = 1;
 			}
+			/* GPIOs are only allowed to modify function fields. */
 		}
 
 		if (!in_range)
 			continue;
 
-		if (sh_pfc_get_config_reg(pfc, enum_id, &cr,
-					  &field, &value, &cntp) != 0)
-			goto out_err;
-
-		switch (cfg_mode) {
-		case GPIO_CFG_DRYRUN:
-			if (!*cntp ||
-			    (sh_pfc_read_config_reg(pfc, cr, field) != value))
-				continue;
-			break;
-
-		case GPIO_CFG_REQ:
-			sh_pfc_write_config_reg(pfc, cr, field, value);
-			*cntp = *cntp + 1;
-			break;
+		ret = sh_pfc_get_config_reg(pfc, enum_id, &cr, &field, &value);
+		if (ret < 0)
+			return ret;
 
-		case GPIO_CFG_FREE:
-			*cntp = *cntp - 1;
-			break;
-		}
+		sh_pfc_write_config_reg(pfc, cr, field, value);
 	}
 
 	return 0;
- out_err:
-	return -1;
 }
 
 static int sh_pfc_probe(struct platform_device *pdev)
 {
-	struct sh_pfc_soc_info *info;
+	const struct sh_pfc_soc_info *info;
 	struct sh_pfc *pfc;
 	int ret;
 
-	/*
-	 * Ensure that the type encoding fits
-	 */
-	BUILD_BUG_ON(PINMUX_FLAG_TYPE > ((1 << PINMUX_FLAG_DBIT_SHIFT) - 1));
-
 	info = pdev->id_entry->driver_data
 	      ? (void *)pdev->id_entry->driver_data : pdev->dev.platform_data;
 	if (info == NULL)
@@ -509,7 +373,6 @@ static int sh_pfc_probe(struct platform_device *pdev)
 	spin_lock_init(&pfc->lock);
 
 	pinctrl_provide_dummies();
-	sh_pfc_setup_data_regs(pfc);
 
 	/*
 	 * Initialize pinctrl bindings first
@@ -529,13 +392,13 @@ static int sh_pfc_probe(struct platform_device *pdev)
 		 * PFC state as it is, given that there are already
 		 * extant users of it that have succeeded by this point.
 		 */
-		pr_notice("failed to init GPIO chip, ignoring...\n");
+		dev_notice(pfc->dev, "failed to init GPIO chip, ignoring...\n");
 	}
 #endif
 
 	platform_set_drvdata(pdev, pfc);
 
-	pr_info("%s support registered\n", info->name);
+	dev_info(pfc->dev, "%s support registered\n", info->name);
 
 	return 0;
 }
@@ -555,6 +418,9 @@ static int sh_pfc_remove(struct platform_device *pdev)
 }
 
 static const struct platform_device_id sh_pfc_id_table[] = {
+#ifdef CONFIG_PINCTRL_PFC_R8A73A4
+	{ "pfc-r8a73a4", (kernel_ulong_t)&r8a73a4_pinmux_info },
+#endif
 #ifdef CONFIG_PINCTRL_PFC_R8A7740
 	{ "pfc-r8a7740", (kernel_ulong_t)&r8a7740_pinmux_info },
 #endif
diff --git a/drivers/pinctrl/sh-pfc/core.h b/drivers/pinctrl/sh-pfc/core.h
index ba7c33c..89cb428 100644
--- a/drivers/pinctrl/sh-pfc/core.h
+++ b/drivers/pinctrl/sh-pfc/core.h
@@ -26,13 +26,17 @@ struct sh_pfc_pinctrl;
 
 struct sh_pfc {
 	struct device *dev;
-	struct sh_pfc_soc_info *info;
+	const struct sh_pfc_soc_info *info;
 	spinlock_t lock;
 
 	unsigned int num_windows;
 	struct sh_pfc_window *window;
 
+	unsigned int nr_pins;
+
 	struct sh_pfc_chip *gpio;
+	struct sh_pfc_chip *func;
+
 	struct sh_pfc_pinctrl *pinctrl;
 };
 
@@ -42,31 +46,30 @@ int sh_pfc_unregister_gpiochip(struct sh_pfc *pfc);
 int sh_pfc_register_pinctrl(struct sh_pfc *pfc);
 int sh_pfc_unregister_pinctrl(struct sh_pfc *pfc);
 
-int sh_pfc_read_bit(struct pinmux_data_reg *dr, unsigned long in_pos);
-void sh_pfc_write_bit(struct pinmux_data_reg *dr, unsigned long in_pos,
-		      unsigned long value);
-int sh_pfc_get_data_reg(struct sh_pfc *pfc, unsigned gpio,
-			struct pinmux_data_reg **drp, int *bitp);
-int sh_pfc_gpio_to_enum(struct sh_pfc *pfc, unsigned gpio, int pos,
-			pinmux_enum_t *enum_idp);
-int sh_pfc_config_gpio(struct sh_pfc *pfc, unsigned gpio, int pinmux_type,
-		       int cfg_mode);
+unsigned long sh_pfc_read_raw_reg(void __iomem *mapped_reg,
+				  unsigned long reg_width);
+void sh_pfc_write_raw_reg(void __iomem *mapped_reg, unsigned long reg_width,
+			  unsigned long data);
+
+int sh_pfc_get_pin_index(struct sh_pfc *pfc, unsigned int pin);
+int sh_pfc_config_mux(struct sh_pfc *pfc, unsigned mark, int pinmux_type);
 
-extern struct sh_pfc_soc_info r8a7740_pinmux_info;
-extern struct sh_pfc_soc_info r8a7779_pinmux_info;
-extern struct sh_pfc_soc_info sh7203_pinmux_info;
-extern struct sh_pfc_soc_info sh7264_pinmux_info;
-extern struct sh_pfc_soc_info sh7269_pinmux_info;
-extern struct sh_pfc_soc_info sh7372_pinmux_info;
-extern struct sh_pfc_soc_info sh73a0_pinmux_info;
-extern struct sh_pfc_soc_info sh7720_pinmux_info;
-extern struct sh_pfc_soc_info sh7722_pinmux_info;
-extern struct sh_pfc_soc_info sh7723_pinmux_info;
-extern struct sh_pfc_soc_info sh7724_pinmux_info;
-extern struct sh_pfc_soc_info sh7734_pinmux_info;
-extern struct sh_pfc_soc_info sh7757_pinmux_info;
-extern struct sh_pfc_soc_info sh7785_pinmux_info;
-extern struct sh_pfc_soc_info sh7786_pinmux_info;
-extern struct sh_pfc_soc_info shx3_pinmux_info;
+extern const struct sh_pfc_soc_info r8a73a4_pinmux_info;
+extern const struct sh_pfc_soc_info r8a7740_pinmux_info;
+extern const struct sh_pfc_soc_info r8a7779_pinmux_info;
+extern const struct sh_pfc_soc_info sh7203_pinmux_info;
+extern const struct sh_pfc_soc_info sh7264_pinmux_info;
+extern const struct sh_pfc_soc_info sh7269_pinmux_info;
+extern const struct sh_pfc_soc_info sh7372_pinmux_info;
+extern const struct sh_pfc_soc_info sh73a0_pinmux_info;
+extern const struct sh_pfc_soc_info sh7720_pinmux_info;
+extern const struct sh_pfc_soc_info sh7722_pinmux_info;
+extern const struct sh_pfc_soc_info sh7723_pinmux_info;
+extern const struct sh_pfc_soc_info sh7724_pinmux_info;
+extern const struct sh_pfc_soc_info sh7734_pinmux_info;
+extern const struct sh_pfc_soc_info sh7757_pinmux_info;
+extern const struct sh_pfc_soc_info sh7785_pinmux_info;
+extern const struct sh_pfc_soc_info sh7786_pinmux_info;
+extern const struct sh_pfc_soc_info shx3_pinmux_info;
 
 #endif /* __SH_PFC_CORE_H__ */
diff --git a/drivers/pinctrl/sh-pfc/gpio.c b/drivers/pinctrl/sh-pfc/gpio.c
index a535075..d37efa7 100644
--- a/drivers/pinctrl/sh-pfc/gpio.c
+++ b/drivers/pinctrl/sh-pfc/gpio.c
@@ -9,8 +9,6 @@
  * for more details.
  */
 
-#define pr_fmt(fmt) KBUILD_MODNAME " gpio: " fmt
-
 #include <linux/device.h>
 #include <linux/gpio.h>
 #include <linux/init.h>
@@ -21,9 +19,23 @@
 
 #include "core.h"
 
+struct sh_pfc_gpio_data_reg {
+	const struct pinmux_data_reg *info;
+	unsigned long shadow;
+};
+
+struct sh_pfc_gpio_pin {
+	u8 dbit;
+	u8 dreg;
+};
+
 struct sh_pfc_chip {
-	struct sh_pfc		*pfc;
-	struct gpio_chip	gpio_chip;
+	struct sh_pfc			*pfc;
+	struct gpio_chip		gpio_chip;
+
+	struct sh_pfc_window		*mem;
+	struct sh_pfc_gpio_data_reg	*regs;
+	struct sh_pfc_gpio_pin		*pins;
 };
 
 static struct sh_pfc_chip *gpio_to_pfc_chip(struct gpio_chip *gc)
@@ -36,143 +48,367 @@ static struct sh_pfc *gpio_to_pfc(struct gpio_chip *gc)
 	return gpio_to_pfc_chip(gc)->pfc;
 }
 
-static int sh_gpio_request(struct gpio_chip *gc, unsigned offset)
+static void gpio_get_data_reg(struct sh_pfc_chip *chip, unsigned int gpio,
+			      struct sh_pfc_gpio_data_reg **reg,
+			      unsigned int *bit)
 {
-	return pinctrl_request_gpio(offset);
+	int idx = sh_pfc_get_pin_index(chip->pfc, gpio);
+	struct sh_pfc_gpio_pin *gpio_pin = &chip->pins[idx];
+
+	*reg = &chip->regs[gpio_pin->dreg];
+	*bit = gpio_pin->dbit;
 }
 
-static void sh_gpio_free(struct gpio_chip *gc, unsigned offset)
+static unsigned long gpio_read_data_reg(struct sh_pfc_chip *chip,
+					const struct pinmux_data_reg *dreg)
 {
-	pinctrl_free_gpio(offset);
+	void __iomem *mem = dreg->reg - chip->mem->phys + chip->mem->virt;
+
+	return sh_pfc_read_raw_reg(mem, dreg->reg_width);
 }
 
-static void sh_gpio_set_value(struct sh_pfc *pfc, unsigned gpio, int value)
+static void gpio_write_data_reg(struct sh_pfc_chip *chip,
+				const struct pinmux_data_reg *dreg,
+				unsigned long value)
 {
-	struct pinmux_data_reg *dr = NULL;
-	int bit = 0;
+	void __iomem *mem = dreg->reg - chip->mem->phys + chip->mem->virt;
 
-	if (sh_pfc_get_data_reg(pfc, gpio, &dr, &bit) != 0)
-		BUG();
-	else
-		sh_pfc_write_bit(dr, bit, value);
+	sh_pfc_write_raw_reg(mem, dreg->reg_width, value);
 }
 
-static int sh_gpio_get_value(struct sh_pfc *pfc, unsigned gpio)
+static void gpio_setup_data_reg(struct sh_pfc_chip *chip, unsigned gpio)
 {
-	struct pinmux_data_reg *dr = NULL;
-	int bit = 0;
+	struct sh_pfc *pfc = chip->pfc;
+	struct sh_pfc_gpio_pin *gpio_pin = &chip->pins[gpio];
+	const struct sh_pfc_pin *pin = &pfc->info->pins[gpio];
+	const struct pinmux_data_reg *dreg;
+	unsigned int bit;
+	unsigned int i;
+
+	for (i = 0, dreg = pfc->info->data_regs; dreg->reg; ++i, ++dreg) {
+		for (bit = 0; bit < dreg->reg_width; bit++) {
+			if (dreg->enum_ids[bit] == pin->enum_id) {
+				gpio_pin->dreg = i;
+				gpio_pin->dbit = bit;
+				return;
+			}
+		}
+	}
 
-	if (sh_pfc_get_data_reg(pfc, gpio, &dr, &bit) != 0)
+	BUG();
+}
+
+static int gpio_setup_data_regs(struct sh_pfc_chip *chip)
+{
+	struct sh_pfc *pfc = chip->pfc;
+	const struct pinmux_data_reg *dreg;
+	unsigned int i;
+
+	/* Count the number of data registers, allocate memory and initialize
+	 * them.
+	 */
+	for (i = 0; pfc->info->data_regs[i].reg_width; ++i)
+		;
+
+	chip->regs = devm_kzalloc(pfc->dev, i * sizeof(*chip->regs),
+				  GFP_KERNEL);
+	if (chip->regs == NULL)
+		return -ENOMEM;
+
+	for (i = 0, dreg = pfc->info->data_regs; dreg->reg_width; ++i, ++dreg) {
+		chip->regs[i].info = dreg;
+		chip->regs[i].shadow = gpio_read_data_reg(chip, dreg);
+	}
+
+	for (i = 0; i < pfc->info->nr_pins; i++) {
+		if (pfc->info->pins[i].enum_id == 0)
+			continue;
+
+		gpio_setup_data_reg(chip, i);
+	}
+
+	return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Pin GPIOs
+ */
+
+static int gpio_pin_request(struct gpio_chip *gc, unsigned offset)
+{
+	struct sh_pfc *pfc = gpio_to_pfc(gc);
+	int idx = sh_pfc_get_pin_index(pfc, offset);
+
+	if (idx < 0 || pfc->info->pins[idx].enum_id == 0)
 		return -EINVAL;
 
-	return sh_pfc_read_bit(dr, bit);
+	return pinctrl_request_gpio(offset);
+}
+
+static void gpio_pin_free(struct gpio_chip *gc, unsigned offset)
+{
+	return pinctrl_free_gpio(offset);
+}
+
+static void gpio_pin_set_value(struct sh_pfc_chip *chip, unsigned offset,
+			       int value)
+{
+	struct sh_pfc_gpio_data_reg *reg;
+	unsigned long pos;
+	unsigned int bit;
+
+	gpio_get_data_reg(chip, offset, &reg, &bit);
+
+	pos = reg->info->reg_width - (bit + 1);
+
+	if (value)
+		set_bit(pos, &reg->shadow);
+	else
+		clear_bit(pos, &reg->shadow);
+
+	gpio_write_data_reg(chip, reg->info, reg->shadow);
 }
 
-static int sh_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
+static int gpio_pin_direction_input(struct gpio_chip *gc, unsigned offset)
 {
 	return pinctrl_gpio_direction_input(offset);
 }
 
-static int sh_gpio_direction_output(struct gpio_chip *gc, unsigned offset,
+static int gpio_pin_direction_output(struct gpio_chip *gc, unsigned offset,
 				    int value)
 {
-	sh_gpio_set_value(gpio_to_pfc(gc), offset, value);
+	gpio_pin_set_value(gpio_to_pfc_chip(gc), offset, value);
 
 	return pinctrl_gpio_direction_output(offset);
 }
 
-static int sh_gpio_get(struct gpio_chip *gc, unsigned offset)
+static int gpio_pin_get(struct gpio_chip *gc, unsigned offset)
 {
-	return sh_gpio_get_value(gpio_to_pfc(gc), offset);
+	struct sh_pfc_chip *chip = gpio_to_pfc_chip(gc);
+	struct sh_pfc_gpio_data_reg *reg;
+	unsigned long pos;
+	unsigned int bit;
+
+	gpio_get_data_reg(chip, offset, &reg, &bit);
+
+	pos = reg->info->reg_width - (bit + 1);
+
+	return (gpio_read_data_reg(chip, reg->info) >> pos) & 1;
 }
 
-static void sh_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
+static void gpio_pin_set(struct gpio_chip *gc, unsigned offset, int value)
 {
-	sh_gpio_set_value(gpio_to_pfc(gc), offset, value);
+	gpio_pin_set_value(gpio_to_pfc_chip(gc), offset, value);
 }
 
-static int sh_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
+static int gpio_pin_to_irq(struct gpio_chip *gc, unsigned offset)
 {
 	struct sh_pfc *pfc = gpio_to_pfc(gc);
-	pinmux_enum_t enum_id;
-	pinmux_enum_t *enum_ids;
-	int i, k, pos;
-
-	pos = 0;
-	enum_id = 0;
-	while (1) {
-		pos = sh_pfc_gpio_to_enum(pfc, offset, pos, &enum_id);
-		if (pos <= 0 || !enum_id)
-			break;
+	int i, k;
 
-		for (i = 0; i < pfc->info->gpio_irq_size; i++) {
-			enum_ids = pfc->info->gpio_irq[i].enum_ids;
-			for (k = 0; enum_ids[k]; k++) {
-				if (enum_ids[k] == enum_id)
-					return pfc->info->gpio_irq[i].irq;
-			}
+	for (i = 0; i < pfc->info->gpio_irq_size; i++) {
+		unsigned short *gpios = pfc->info->gpio_irq[i].gpios;
+
+		for (k = 0; gpios[k]; k++) {
+			if (gpios[k] == offset)
+				return pfc->info->gpio_irq[i].irq;
 		}
 	}
 
 	return -ENOSYS;
 }
 
-static void sh_pfc_gpio_setup(struct sh_pfc_chip *chip)
+static int gpio_pin_setup(struct sh_pfc_chip *chip)
 {
 	struct sh_pfc *pfc = chip->pfc;
 	struct gpio_chip *gc = &chip->gpio_chip;
+	int ret;
+
+	chip->pins = devm_kzalloc(pfc->dev, pfc->nr_pins * sizeof(*chip->pins),
+				  GFP_KERNEL);
+	if (chip->pins == NULL)
+		return -ENOMEM;
+
+	ret = gpio_setup_data_regs(chip);
+	if (ret < 0)
+		return ret;
+
+	gc->request = gpio_pin_request;
+	gc->free = gpio_pin_free;
+	gc->direction_input = gpio_pin_direction_input;
+	gc->get = gpio_pin_get;
+	gc->direction_output = gpio_pin_direction_output;
+	gc->set = gpio_pin_set;
+	gc->to_irq = gpio_pin_to_irq;
 
-	gc->request = sh_gpio_request;
-	gc->free = sh_gpio_free;
-	gc->direction_input = sh_gpio_direction_input;
-	gc->get = sh_gpio_get;
-	gc->direction_output = sh_gpio_direction_output;
-	gc->set = sh_gpio_set;
-	gc->to_irq = sh_gpio_to_irq;
+	gc->label = pfc->info->name;
+	gc->dev = pfc->dev;
+	gc->owner = THIS_MODULE;
+	gc->base = 0;
+	gc->ngpio = pfc->nr_pins;
+
+	return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Function GPIOs
+ */
+
+static int gpio_function_request(struct gpio_chip *gc, unsigned offset)
+{
+	static bool __print_once;
+	struct sh_pfc *pfc = gpio_to_pfc(gc);
+	unsigned int mark = pfc->info->func_gpios[offset].enum_id;
+	unsigned long flags;
+	int ret;
+
+	if (!__print_once) {
+		dev_notice(pfc->dev,
+			   "Use of GPIO API for function requests is deprecated."
+			   " Convert to pinctrl\n");
+		__print_once = true;
+	}
+
+	if (mark == 0)
+		return -EINVAL;
 
-	WARN_ON(pfc->info->first_gpio != 0); /* needs testing */
+	spin_lock_irqsave(&pfc->lock, flags);
+	ret = sh_pfc_config_mux(pfc, mark, PINMUX_TYPE_FUNCTION);
+	spin_unlock_irqrestore(&pfc->lock, flags);
+
+	return ret;
+}
+
+static void gpio_function_free(struct gpio_chip *gc, unsigned offset)
+{
+}
+
+static int gpio_function_setup(struct sh_pfc_chip *chip)
+{
+	struct sh_pfc *pfc = chip->pfc;
+	struct gpio_chip *gc = &chip->gpio_chip;
+
+	gc->request = gpio_function_request;
+	gc->free = gpio_function_free;
 
 	gc->label = pfc->info->name;
 	gc->owner = THIS_MODULE;
-	gc->base = pfc->info->first_gpio;
-	gc->ngpio = (pfc->info->last_gpio - pfc->info->first_gpio) + 1;
+	gc->base = pfc->nr_pins;
+	gc->ngpio = pfc->info->nr_func_gpios;
+
+	return 0;
 }
 
-int sh_pfc_register_gpiochip(struct sh_pfc *pfc)
+/* -----------------------------------------------------------------------------
+ * Register/unregister
+ */
+
+static struct sh_pfc_chip *
+sh_pfc_add_gpiochip(struct sh_pfc *pfc, int(*setup)(struct sh_pfc_chip *),
+		    struct sh_pfc_window *mem)
 {
 	struct sh_pfc_chip *chip;
 	int ret;
 
 	chip = devm_kzalloc(pfc->dev, sizeof(*chip), GFP_KERNEL);
 	if (unlikely(!chip))
-		return -ENOMEM;
+		return ERR_PTR(-ENOMEM);
 
+	chip->mem = mem;
 	chip->pfc = pfc;
 
-	sh_pfc_gpio_setup(chip);
+	ret = setup(chip);
+	if (ret < 0)
+		return ERR_PTR(ret);
 
 	ret = gpiochip_add(&chip->gpio_chip);
 	if (unlikely(ret < 0))
-		return ret;
+		return ERR_PTR(ret);
+
+	dev_info(pfc->dev, "%s handling gpio %u -> %u\n",
+		 chip->gpio_chip.label, chip->gpio_chip.base,
+		 chip->gpio_chip.base + chip->gpio_chip.ngpio - 1);
+
+	return chip;
+}
+
+int sh_pfc_register_gpiochip(struct sh_pfc *pfc)
+{
+	const struct pinmux_range *ranges;
+	struct pinmux_range def_range;
+	struct sh_pfc_chip *chip;
+	unsigned int nr_ranges;
+	unsigned int i;
+	int ret;
+
+	if (pfc->info->data_regs == NULL)
+		return 0;
+
+	/* Find the memory window that contain the GPIO registers. Boards that
+	 * register a separate GPIO device will not supply a memory resource
+	 * that covers the data registers. In that case don't try to handle
+	 * GPIOs.
+	 */
+	for (i = 0; i < pfc->num_windows; ++i) {
+		struct sh_pfc_window *window = &pfc->window[i];
+
+		if (pfc->info->data_regs[0].reg >= window->phys &&
+		    pfc->info->data_regs[0].reg < window->phys + window->size)
+			break;
+	}
+
+	if (i == pfc->num_windows)
+		return 0;
+
+	/* Register the real GPIOs chip. */
+	chip = sh_pfc_add_gpiochip(pfc, gpio_pin_setup, &pfc->window[i]);
+	if (IS_ERR(chip))
+		return PTR_ERR(chip);
 
 	pfc->gpio = chip;
 
-	pr_info("%s handling gpio %d -> %d\n",
-		pfc->info->name, pfc->info->first_gpio,
-		pfc->info->last_gpio);
+	/* Register the GPIO to pin mappings. */
+	if (pfc->info->ranges == NULL) {
+		def_range.begin = 0;
+		def_range.end = pfc->info->nr_pins - 1;
+		ranges = &def_range;
+		nr_ranges = 1;
+	} else {
+		ranges = pfc->info->ranges;
+		nr_ranges = pfc->info->nr_ranges;
+	}
+
+	for (i = 0; i < nr_ranges; ++i) {
+		const struct pinmux_range *range = &ranges[i];
+
+		ret = gpiochip_add_pin_range(&chip->gpio_chip,
+					     dev_name(pfc->dev),
+					     range->begin, range->begin,
+					     range->end - range->begin + 1);
+		if (ret < 0)
+			return ret;
+	}
+
+	/* Register the function GPIOs chip. */
+	if (pfc->info->nr_func_gpios == 0)
+		return 0;
+
+	chip = sh_pfc_add_gpiochip(pfc, gpio_function_setup, NULL);
+	if (IS_ERR(chip))
+		return PTR_ERR(chip);
+
+	pfc->func = chip;
 
 	return 0;
 }
 
 int sh_pfc_unregister_gpiochip(struct sh_pfc *pfc)
 {
-	struct sh_pfc_chip *chip = pfc->gpio;
+	int err;
 	int ret;
 
-	ret = gpiochip_remove(&chip->gpio_chip);
-	if (unlikely(ret < 0))
-		return ret;
+	ret = gpiochip_remove(&pfc->gpio->gpio_chip);
+	err = gpiochip_remove(&pfc->func->gpio_chip);
 
-	pfc->gpio = NULL;
-	return 0;
+	return ret < 0 ? ret : err;
 }
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a73a4.c b/drivers/pinctrl/sh-pfc/pfc-r8a73a4.c
new file mode 100644
index 0000000..bbff559
--- /dev/null
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a73a4.c
@@ -0,0 +1,2587 @@
+/*
+ * Copyright (C) 2012-2013  Renesas Solutions Corp.
+ * Copyright (C) 2013  Magnus Damm
+ * Copyright (C) 2012  Kuninori Morimoto <kuninori.morimoto.gx@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 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/io.h>
+#include <linux/kernel.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <mach/irqs.h>
+#include <mach/r8a73a4.h>
+
+#include "core.h"
+#include "sh_pfc.h"
+
+#define CPU_ALL_PORT(fn, pfx, sfx)					\
+	/*  Port0 - Port30 */						\
+	PORT_10(fn, pfx, sfx),						\
+	PORT_10(fn, pfx##1, sfx),					\
+	PORT_10(fn, pfx##2, sfx),					\
+	PORT_1(fn,  pfx##30, sfx),					\
+	/* Port32 - Port40 */						\
+	PORT_1(fn,  pfx##32, sfx),	PORT_1(fn,  pfx##33, sfx),	\
+	PORT_1(fn,  pfx##34, sfx),	PORT_1(fn,  pfx##35, sfx),	\
+	PORT_1(fn,  pfx##36, sfx),	PORT_1(fn,  pfx##37, sfx),	\
+	PORT_1(fn,  pfx##38, sfx),	PORT_1(fn,  pfx##39, sfx),	\
+	PORT_1(fn,  pfx##40, sfx),					\
+	/* Port64  - Port85 */						\
+	PORT_1(fn, pfx##64, sfx),	PORT_1(fn, pfx##65, sfx),	\
+	PORT_1(fn, pfx##66, sfx),	PORT_1(fn, pfx##67, sfx),	\
+	PORT_1(fn, pfx##68, sfx),	PORT_1(fn, pfx##69, sfx),	\
+	PORT_10(fn, pfx##7, sfx),					\
+	PORT_1(fn, pfx##80, sfx),	PORT_1(fn, pfx##81, sfx),	\
+	PORT_1(fn, pfx##82, sfx),	PORT_1(fn, pfx##83, sfx),	\
+	PORT_1(fn, pfx##84, sfx),	PORT_1(fn, pfx##85, sfx),	\
+	/* Port96  - Port126 */						\
+	PORT_1(fn, pfx##96, sfx),	PORT_1(fn, pfx##97, sfx),	\
+	PORT_1(fn, pfx##98, sfx),	PORT_1(fn, pfx##99, sfx),	\
+	PORT_10(fn, pfx##10, sfx),					\
+	PORT_10(fn, pfx##11, sfx),					\
+	PORT_1(fn, pfx##120, sfx),	PORT_1(fn, pfx##121, sfx),	\
+	PORT_1(fn, pfx##122, sfx),	PORT_1(fn, pfx##123, sfx),	\
+	PORT_1(fn, pfx##124, sfx),	PORT_1(fn, pfx##125, sfx),	\
+	PORT_1(fn, pfx##126, sfx),					\
+	/* Port128 - Port134 */						\
+	PORT_1(fn, pfx##128, sfx),	PORT_1(fn, pfx##129, sfx),	\
+	PORT_1(fn, pfx##130, sfx),	PORT_1(fn, pfx##131, sfx),	\
+	PORT_1(fn, pfx##132, sfx),	PORT_1(fn, pfx##133, sfx),	\
+	PORT_1(fn, pfx##134, sfx),					\
+	/* Port160 - Port178 */						\
+	PORT_10(fn, pfx##16, sfx),					\
+	PORT_1(fn, pfx##170, sfx),	PORT_1(fn, pfx##171, sfx),	\
+	PORT_1(fn, pfx##172, sfx),	PORT_1(fn, pfx##173, sfx),	\
+	PORT_1(fn, pfx##174, sfx),	PORT_1(fn, pfx##175, sfx),	\
+	PORT_1(fn, pfx##176, sfx),	PORT_1(fn, pfx##177, sfx),	\
+	PORT_1(fn, pfx##178, sfx),					\
+	/* Port192 - Port222 */						\
+	PORT_1(fn, pfx##192, sfx),	PORT_1(fn, pfx##193, sfx),	\
+	PORT_1(fn, pfx##194, sfx),	PORT_1(fn, pfx##195, sfx),	\
+	PORT_1(fn, pfx##196, sfx),	PORT_1(fn, pfx##197, sfx),	\
+	PORT_1(fn, pfx##198, sfx),	PORT_1(fn, pfx##199, sfx),	\
+	PORT_10(fn, pfx##20, sfx),					\
+	PORT_10(fn, pfx##21, sfx),					\
+	PORT_1(fn, pfx##220, sfx),	PORT_1(fn, pfx##221, sfx),	\
+	PORT_1(fn, pfx##222, sfx),					\
+	/* Port224 - Port250 */						\
+	PORT_1(fn, pfx##224, sfx),	PORT_1(fn, pfx##225, sfx),	\
+	PORT_1(fn, pfx##226, sfx),	PORT_1(fn, pfx##227, sfx),	\
+	PORT_1(fn, pfx##228, sfx),	PORT_1(fn, pfx##229, sfx),	\
+	PORT_10(fn, pfx##23, sfx),					\
+	PORT_10(fn, pfx##24, sfx),					\
+	PORT_1(fn, pfx##250, sfx),					\
+	/* Port256 - Port283 */						\
+	PORT_1(fn, pfx##256, sfx),	PORT_1(fn, pfx##257, sfx),	\
+	PORT_1(fn, pfx##258, sfx),	PORT_1(fn, pfx##259, sfx),	\
+	PORT_10(fn, pfx##26, sfx),					\
+	PORT_10(fn, pfx##27, sfx),					\
+	PORT_1(fn, pfx##280, sfx),	PORT_1(fn, pfx##281, sfx),	\
+	PORT_1(fn, pfx##282, sfx),	PORT_1(fn, pfx##283, sfx),	\
+	/* Port288 - Port308 */						\
+	PORT_1(fn, pfx##288, sfx),	PORT_1(fn, pfx##289, sfx),	\
+	PORT_10(fn, pfx##29, sfx),					\
+	PORT_1(fn, pfx##300, sfx),	PORT_1(fn, pfx##301, sfx),	\
+	PORT_1(fn, pfx##302, sfx),	PORT_1(fn, pfx##303, sfx),	\
+	PORT_1(fn, pfx##304, sfx),	PORT_1(fn, pfx##305, sfx),	\
+	PORT_1(fn, pfx##306, sfx),	PORT_1(fn, pfx##307, sfx),	\
+	PORT_1(fn, pfx##308, sfx),					\
+	/* Port320 - Port329 */						\
+	PORT_10(fn, pfx##32, sfx)
+
+
+enum {
+	PINMUX_RESERVED = 0,
+
+	/* PORT0_DATA -> PORT329_DATA */
+	PINMUX_DATA_BEGIN,
+	PORT_ALL(DATA),
+	PINMUX_DATA_END,
+
+	/* PORT0_IN -> PORT329_IN */
+	PINMUX_INPUT_BEGIN,
+	PORT_ALL(IN),
+	PINMUX_INPUT_END,
+
+	/* PORT0_OUT -> PORT329_OUT */
+	PINMUX_OUTPUT_BEGIN,
+	PORT_ALL(OUT),
+	PINMUX_OUTPUT_END,
+
+	PINMUX_FUNCTION_BEGIN,
+	PORT_ALL(FN_IN), /* PORT0_FN_IN -> PORT329_FN_IN */
+	PORT_ALL(FN_OUT), /* PORT0_FN_OUT -> PORT329_FN_OUT */
+	PORT_ALL(FN0), /* PORT0_FN0 -> PORT329_FN0 */
+	PORT_ALL(FN1), /* PORT0_FN1 -> PORT329_FN1 */
+	PORT_ALL(FN2), /* PORT0_FN2 -> PORT329_FN2 */
+	PORT_ALL(FN3), /* PORT0_FN3 -> PORT329_FN3 */
+	PORT_ALL(FN4), /* PORT0_FN4 -> PORT329_FN4 */
+	PORT_ALL(FN5), /* PORT0_FN5 -> PORT329_FN5 */
+	PORT_ALL(FN6), /* PORT0_FN6 -> PORT329_FN6 */
+	PORT_ALL(FN7), /* PORT0_FN7 -> PORT329_FN7 */
+
+	MSEL1CR_31_0, MSEL1CR_31_1,
+	MSEL1CR_27_0, MSEL1CR_27_1,
+	MSEL1CR_25_0, MSEL1CR_25_1,
+	MSEL1CR_24_0, MSEL1CR_24_1,
+	MSEL1CR_22_0, MSEL1CR_22_1,
+	MSEL1CR_21_0, MSEL1CR_21_1,
+	MSEL1CR_20_0, MSEL1CR_20_1,
+	MSEL1CR_19_0, MSEL1CR_19_1,
+	MSEL1CR_18_0, MSEL1CR_18_1,
+	MSEL1CR_17_0, MSEL1CR_17_1,
+	MSEL1CR_16_0, MSEL1CR_16_1,
+	MSEL1CR_15_0, MSEL1CR_15_1,
+	MSEL1CR_14_0, MSEL1CR_14_1,
+	MSEL1CR_13_0, MSEL1CR_13_1,
+	MSEL1CR_12_0, MSEL1CR_12_1,
+	MSEL1CR_11_0, MSEL1CR_11_1,
+	MSEL1CR_10_0, MSEL1CR_10_1,
+	MSEL1CR_09_0, MSEL1CR_09_1,
+	MSEL1CR_08_0, MSEL1CR_08_1,
+	MSEL1CR_07_0, MSEL1CR_07_1,
+	MSEL1CR_06_0, MSEL1CR_06_1,
+	MSEL1CR_05_0, MSEL1CR_05_1,
+	MSEL1CR_04_0, MSEL1CR_04_1,
+	MSEL1CR_03_0, MSEL1CR_03_1,
+	MSEL1CR_02_0, MSEL1CR_02_1,
+	MSEL1CR_01_0, MSEL1CR_01_1,
+	MSEL1CR_00_0, MSEL1CR_00_1,
+
+	MSEL3CR_31_0, MSEL3CR_31_1,
+	MSEL3CR_28_0, MSEL3CR_28_1,
+	MSEL3CR_27_0, MSEL3CR_27_1,
+	MSEL3CR_26_0, MSEL3CR_26_1,
+	MSEL3CR_23_0, MSEL3CR_23_1,
+	MSEL3CR_22_0, MSEL3CR_22_1,
+	MSEL3CR_21_0, MSEL3CR_21_1,
+	MSEL3CR_20_0, MSEL3CR_20_1,
+	MSEL3CR_19_0, MSEL3CR_19_1,
+	MSEL3CR_18_0, MSEL3CR_18_1,
+	MSEL3CR_17_0, MSEL3CR_17_1,
+	MSEL3CR_16_0, MSEL3CR_16_1,
+	MSEL3CR_15_0, MSEL3CR_15_1,
+	MSEL3CR_12_0, MSEL3CR_12_1,
+	MSEL3CR_11_0, MSEL3CR_11_1,
+	MSEL3CR_10_0, MSEL3CR_10_1,
+	MSEL3CR_09_0, MSEL3CR_09_1,
+	MSEL3CR_06_0, MSEL3CR_06_1,
+	MSEL3CR_03_0, MSEL3CR_03_1,
+	MSEL3CR_01_0, MSEL3CR_01_1,
+	MSEL3CR_00_0, MSEL3CR_00_1,
+
+	MSEL4CR_30_0, MSEL4CR_30_1,
+	MSEL4CR_29_0, MSEL4CR_29_1,
+	MSEL4CR_28_0, MSEL4CR_28_1,
+	MSEL4CR_27_0, MSEL4CR_27_1,
+	MSEL4CR_26_0, MSEL4CR_26_1,
+	MSEL4CR_25_0, MSEL4CR_25_1,
+	MSEL4CR_24_0, MSEL4CR_24_1,
+	MSEL4CR_23_0, MSEL4CR_23_1,
+	MSEL4CR_22_0, MSEL4CR_22_1,
+	MSEL4CR_21_0, MSEL4CR_21_1,
+	MSEL4CR_20_0, MSEL4CR_20_1,
+	MSEL4CR_19_0, MSEL4CR_19_1,
+	MSEL4CR_18_0, MSEL4CR_18_1,
+	MSEL4CR_17_0, MSEL4CR_17_1,
+	MSEL4CR_16_0, MSEL4CR_16_1,
+	MSEL4CR_15_0, MSEL4CR_15_1,
+	MSEL4CR_14_0, MSEL4CR_14_1,
+	MSEL4CR_13_0, MSEL4CR_13_1,
+	MSEL4CR_12_0, MSEL4CR_12_1,
+	MSEL4CR_11_0, MSEL4CR_11_1,
+	MSEL4CR_10_0, MSEL4CR_10_1,
+	MSEL4CR_09_0, MSEL4CR_09_1,
+	MSEL4CR_07_0, MSEL4CR_07_1,
+	MSEL4CR_04_0, MSEL4CR_04_1,
+	MSEL4CR_01_0, MSEL4CR_01_1,
+
+	MSEL5CR_31_0, MSEL5CR_31_1,
+	MSEL5CR_30_0, MSEL5CR_30_1,
+	MSEL5CR_29_0, MSEL5CR_29_1,
+	MSEL5CR_28_0, MSEL5CR_28_1,
+	MSEL5CR_27_0, MSEL5CR_27_1,
+	MSEL5CR_26_0, MSEL5CR_26_1,
+	MSEL5CR_25_0, MSEL5CR_25_1,
+	MSEL5CR_24_0, MSEL5CR_24_1,
+	MSEL5CR_23_0, MSEL5CR_23_1,
+	MSEL5CR_22_0, MSEL5CR_22_1,
+	MSEL5CR_21_0, MSEL5CR_21_1,
+	MSEL5CR_20_0, MSEL5CR_20_1,
+	MSEL5CR_19_0, MSEL5CR_19_1,
+	MSEL5CR_18_0, MSEL5CR_18_1,
+	MSEL5CR_17_0, MSEL5CR_17_1,
+	MSEL5CR_16_0, MSEL5CR_16_1,
+	MSEL5CR_15_0, MSEL5CR_15_1,
+	MSEL5CR_14_0, MSEL5CR_14_1,
+	MSEL5CR_13_0, MSEL5CR_13_1,
+	MSEL5CR_12_0, MSEL5CR_12_1,
+	MSEL5CR_11_0, MSEL5CR_11_1,
+	MSEL5CR_10_0, MSEL5CR_10_1,
+	MSEL5CR_09_0, MSEL5CR_09_1,
+	MSEL5CR_08_0, MSEL5CR_08_1,
+	MSEL5CR_07_0, MSEL5CR_07_1,
+	MSEL5CR_06_0, MSEL5CR_06_1,
+
+	MSEL8CR_16_0, MSEL8CR_16_1,
+	MSEL8CR_01_0, MSEL8CR_01_1,
+	MSEL8CR_00_0, MSEL8CR_00_1,
+
+	PINMUX_FUNCTION_END,
+
+	PINMUX_MARK_BEGIN,
+
+
+#define F1(a)	a##_MARK
+#define F2(a)	a##_MARK
+#define F3(a)	a##_MARK
+#define F4(a)	a##_MARK
+#define F5(a)	a##_MARK
+#define F6(a)	a##_MARK
+#define F7(a)	a##_MARK
+#define IRQ(a)	IRQ##a##_MARK
+
+	F1(LCDD0), F3(PDM2_CLK_0), F7(DU0_DR0), IRQ(0), /* Port0 */
+	F1(LCDD1), F3(PDM2_DATA_1), F7(DU0_DR19), IRQ(1),
+	F1(LCDD2), F3(PDM3_CLK_2), F7(DU0_DR2), IRQ(2),
+	F1(LCDD3), F3(PDM3_DATA_3), F7(DU0_DR3), IRQ(3),
+	F1(LCDD4), F3(PDM4_CLK_4), F7(DU0_DR4), IRQ(4),
+	F1(LCDD5), F3(PDM4_DATA_5), F7(DU0_DR5), IRQ(5),
+	F1(LCDD6), F3(PDM0_OUTCLK_6), F7(DU0_DR6), IRQ(6),
+	F1(LCDD7), F3(PDM0_OUTDATA_7), F7(DU0_DR7), IRQ(7),
+	F1(LCDD8), F3(PDM1_OUTCLK_8), F7(DU0_DG0), IRQ(8),
+	F1(LCDD9), F3(PDM1_OUTDATA_9), F7(DU0_DG1), IRQ(9),
+	F1(LCDD10), F3(FSICCK), F7(DU0_DG2), IRQ(10), /* Port10 */
+	F1(LCDD11), F3(FSICISLD), F7(DU0_DG3), IRQ(11),
+	F1(LCDD12), F3(FSICOMC), F7(DU0_DG4), IRQ(12),
+	F1(LCDD13), F3(FSICOLR), F4(FSICILR), F7(DU0_DG5), IRQ(13),
+	F1(LCDD14), F3(FSICOBT), F4(FSICIBT), F7(DU0_DG6), IRQ(14),
+	F1(LCDD15), F3(FSICOSLD), F7(DU0_DG7), IRQ(15),
+	F1(LCDD16), F4(TPU1TO1), F7(DU0_DB0),
+	F1(LCDD17), F4(SF_IRQ_00), F7(DU0_DB1),
+	F1(LCDD18), F4(SF_IRQ_01), F7(DU0_DB2),
+	F1(LCDD19), F3(SCIFB3_RTS_19), F7(DU0_DB3),
+	F1(LCDD20), F3(SCIFB3_CTS_20), F7(DU0_DB4), /* Port20 */
+	F1(LCDD21), F3(SCIFB3_TXD_21), F7(DU0_DB5),
+	F1(LCDD22), F3(SCIFB3_RXD_22), F7(DU0_DB6),
+	F1(LCDD23), F3(SCIFB3_SCK_23), F7(DU0_DB7),
+	F1(LCDHSYN), F2(LCDCS), F3(SCIFB1_RTS_24),
+	F7(DU0_EXHSYNC_N_CSYNC_N_HSYNC_N),
+	F1(LCDVSYN), F3(SCIFB1_CTS_25), F7(DU0_EXVSYNC_N_VSYNC_N_CSYNC_N),
+	F1(LCDDCK), F2(LCDWR), F3(SCIFB1_TXD_26), F7(DU0_DOTCLKIN),
+	F1(LCDDISP), F2(LCDRS), F3(SCIFB1_RXD_27), F7(DU0_DOTCLKOUT),
+	F1(LCDRD_N), F3(SCIFB1_SCK_28), F7(DU0_DOTCLKOUTB),
+	F1(LCDLCLK), F4(SF_IRQ_02), F7(DU0_DISP_CSYNC_N_DE),
+	F1(LCDDON), F4(SF_IRQ_03), F7(DU0_ODDF_N_CLAMP), /* Port30 */
+
+	F1(SCIFA0_RTS), F5(SIM0_DET), F7(CSCIF0_RTS), /* Port32 */
+	F1(SCIFA0_CTS), F5(SIM1_DET), F7(CSCIF0_CTS),
+	F1(SCIFA0_SCK), F5(SIM0_PWRON), F7(CSCIF0_SCK),
+	F1(SCIFA1_RTS), F7(CSCIF1_RTS),
+	F1(SCIFA1_CTS), F7(CSCIF1_CTS),
+	F1(SCIFA1_SCK), F7(CSCIF1_SCK),
+	F1(SCIFB0_RTS), F3(TPU0TO1), F4(SCIFB3_RTS_38), F7(CHSCIF0_HRTS),
+	F1(SCIFB0_CTS), F3(TPU0TO2), F4(SCIFB3_CTS_39), F7(CHSCIF0_HCTS),
+	F1(SCIFB0_SCK), F3(TPU0TO3), F4(SCIFB3_SCK_40),
+	F7(CHSCIF0_HSCK), /* Port40 */
+
+	F1(PDM0_DATA), /* Port64 */
+	F1(PDM1_DATA),
+	F1(HSI_RX_WAKE), F2(SCIFB2_CTS_66), F3(MSIOF3_SYNC), F5(GenIO4),
+	IRQ(40),
+	F1(HSI_RX_READY), F2(SCIFB1_TXD_67), F5(GIO_OUT3_67), F7(CHSCIF1_HTX),
+	F1(HSI_RX_FLAG), F2(SCIFB2_TXD_68), F3(MSIOF3_TXD), F5(GIO_OUT4_68),
+	F1(HSI_RX_DATA), F2(SCIFB2_RXD_69), F3(MSIOF3_RXD), F5(GIO_OUT5_69),
+	F1(HSI_TX_FLAG), F2(SCIFB1_RTS_70), F5(GIO_OUT1_70), F6(HSIC_TSTCLK0),
+	F7(CHSCIF1_HRTS), /* Port70 */
+	F1(HSI_TX_DATA), F2(SCIFB1_CTS_71), F5(GIO_OUT2_71), F6(HSIC_TSTCLK1),
+	F7(CHSCIF1_HCTS),
+	F1(HSI_TX_WAKE), F2(SCIFB1_RXD_72), F5(GenIO8), F7(CHSCIF1_HRX),
+	F1(HSI_TX_READY), F2(SCIFB2_RTS_73), F3(MSIOF3_SCK), F5(GIO_OUT0_73),
+	F1(IRDA_OUT), F1(IRDA_IN), F1(IRDA_FIRSEL), F1(TPU0TO0),
+	F1(DIGRFEN), F1(GPS_TIMESTAMP), F1(TXP), /* Port80 */
+	F1(TXP2), F1(COEX_0), F1(COEX_1), IRQ(19), IRQ(18), /* Port85 */
+
+	F1(KEYIN0), /* Port96 */
+	F1(KEYIN1), F1(KEYIN2), F1(KEYIN3), F1(KEYIN4), /* Port100 */
+	F1(KEYIN5), F1(KEYIN6), IRQ(41), F1(KEYIN7), IRQ(42),
+	F2(KEYOUT0), F2(KEYOUT1), F2(KEYOUT2), F2(KEYOUT3),
+	F2(KEYOUT4), F2(KEYOUT5), IRQ(43), F2(KEYOUT6), IRQ(44), /* Port110 */
+	F2(KEYOUT7), F5(RFANAEN), IRQ(45),
+	F1(KEYIN8), F2(KEYOUT8), F4(SF_IRQ_04), IRQ(46),
+	F1(KEYIN9), F2(KEYOUT9), F4(SF_IRQ_05), IRQ(47),
+	F1(KEYIN10), F2(KEYOUT10), F4(SF_IRQ_06), IRQ(48),
+	F1(KEYIN11), F2(KEYOUT11), F4(SF_IRQ_07), IRQ(49),
+	F1(SCIFA0_TXD), F7(CSCIF0_TX), F1(SCIFA0_RXD), F7(CSCIF0_RX),
+	F1(SCIFA1_TXD), F7(CSCIF1_TX), F1(SCIFA1_RXD), F7(CSCIF1_RX),
+	F3(SF_PORT_1_120), F4(SCIFB3_RXD_120), F7(DU0_CDE), /* Port120 */
+	F3(SF_PORT_0_121), F4(SCIFB3_TXD_121),
+	F1(SCIFB0_TXD), F7(CHSCIF0_HTX),
+	F1(SCIFB0_RXD), F7(CHSCIF0_HRX), F3(ISP_STROBE_124),
+	F1(STP_ISD_0), F2(PDM4_CLK_125), F3(MSIOF2_TXD), F5(SIM0_VOLTSEL0),
+	F1(TS_SDEN), F2(MSIOF7_SYNC), F3(STP_ISEN_1),
+	F1(STP_ISEN_0), F2(PDM1_OUTDATA_128), F3(MSIOF2_SYNC),
+	F5(SIM1_VOLTSEL1), F1(TS_SPSYNC), F2(MSIOF7_RXD), F3(STP_ISSYNC_1),
+	F1(STP_ISSYNC_0), F2(PDM4_DATA_130), F3(MSIOF2_RXD),
+	F5(SIM0_VOLTSEL1), /* Port130 */
+	F1(STP_OPWM_0), F5(SIM1_PWRON), F1(TS_SCK), F2(MSIOF7_SCK),
+	F3(STP_ISCLK_1), F1(STP_ISCLK_0), F2(PDM1_OUTCLK_133), F3(MSIOF2_SCK),
+	F5(SIM1_VOLTSEL0), F1(TS_SDAT), F2(MSIOF7_TXD), F3(STP_ISD_1),
+	IRQ(20), /* Port160 */
+	IRQ(21), IRQ(22), IRQ(23),
+	F1(MMCD0_0), F1(MMCD0_1), F1(MMCD0_2), F1(MMCD0_3),
+	F1(MMCD0_4), F1(MMCD0_5), F1(MMCD0_6), /* Port170 */
+	F1(MMCD0_7), F1(MMCCMD0), F1(MMCCLK0), F1(MMCRST),
+	IRQ(24), IRQ(25), IRQ(26), IRQ(27),
+	F1(A10), F2(MMCD1_7), IRQ(31), /* Port192 */
+	F1(A9), F2(MMCD1_6), IRQ(32),
+	F1(A8), F2(MMCD1_5), IRQ(33),
+	F1(A7), F2(MMCD1_4), IRQ(34),
+	F1(A6), F2(MMCD1_3), IRQ(35),
+	F1(A5), F2(MMCD1_2), IRQ(36),
+	F1(A4), F2(MMCD1_1), IRQ(37),
+	F1(A3), F2(MMCD1_0), IRQ(38),
+	F1(A2), F2(MMCCMD1), IRQ(39), /* Port200 */
+	F1(A1),
+	F1(A0), F2(BS),
+	F1(CKO), F2(MMCCLK1),
+	F1(CS0_N), F5(SIM0_GPO1),
+	F1(CS2_N), F5(SIM0_GPO2),
+	F1(CS4_N), F2(VIO_VD), F5(SIM1_GPO0),
+	F1(D15), F5(GIO_OUT15),
+	F1(D14), F5(GIO_OUT14),
+	F1(D13), F5(GIO_OUT13),
+	F1(D12), F5(GIO_OUT12), /* Port210 */
+	F1(D11), F5(WGM_TXP2),
+	F1(D10), F5(WGM_GPS_TIMEM_ASK_RFCLK),
+	F1(D9), F2(VIO_D9), F5(GIO_OUT9),
+	F1(D8), F2(VIO_D8), F5(GIO_OUT8),
+	F1(D7), F2(VIO_D7), F5(GIO_OUT7),
+	F1(D6), F2(VIO_D6), F5(GIO_OUT6),
+	F1(D5), F2(VIO_D5), F5(GIO_OUT5_217),
+	F1(D4), F2(VIO_D4), F5(GIO_OUT4_218),
+	F1(D3), F2(VIO_D3), F5(GIO_OUT3_219),
+	F1(D2), F2(VIO_D2), F5(GIO_OUT2_220), /* Port220 */
+	F1(D1), F2(VIO_D1), F5(GIO_OUT1_221),
+	F1(D0), F2(VIO_D0), F5(GIO_OUT0_222),
+	F1(RDWR_224), F2(VIO_HD), F5(SIM1_GPO2),
+	F1(RD_N), F1(WAIT_N), F2(VIO_CLK), F5(SIM1_GPO1),
+	F1(WE0_N), F2(RDWR_227),
+	F1(WE1_N), F5(SIM0_GPO0),
+	F1(PWMO), F2(VIO_CKO1_229),
+	F1(SLIM_CLK), F2(VIO_CKO4_230), /* Port230 */
+	F1(SLIM_DATA), F2(VIO_CKO5_231), F2(VIO_CKO2_232), F4(SF_PORT_0_232),
+	F2(VIO_CKO3_233), F4(SF_PORT_1_233),
+	F1(FSIACK), F2(PDM3_CLK_234), F3(ISP_IRIS1_234),
+	F1(FSIAISLD), F2(PDM3_DATA_235),
+	F1(FSIAOMC), F2(PDM0_OUTCLK_236), F3(ISP_IRIS0_236),
+	F1(FSIAOLR), F2(FSIAILR), F1(FSIAOBT), F2(FSIAIBT),
+	F1(FSIAOSLD), F2(PDM0_OUTDATA_239),
+	F1(FSIBISLD), /* Port240 */
+	F1(FSIBOLR), F2(FSIBILR), F1(FSIBOMC), F3(ISP_SHUTTER1_242),
+	F1(FSIBOBT), F2(FSIBIBT), F1(FSIBOSLD), F2(FSIASPDIF),
+	F1(FSIBCK), F3(ISP_SHUTTER0_245),
+	F1(ISP_IRIS1_246), F1(ISP_IRIS0_247), F1(ISP_SHUTTER1_248),
+	F1(ISP_SHUTTER0_249), F1(ISP_STROBE_250), /* Port250 */
+	F1(MSIOF0_SYNC), F1(MSIOF0_RXD), F1(MSIOF0_SCK), F1(MSIOF0_SS2),
+	F3(VIO_CKO3_259), F1(MSIOF0_TXD), /* Port260 */
+	F2(SCIFB1_SCK_261), F7(CHSCIF1_HSCK), F2(SCIFB2_SCK_262),
+	F1(MSIOF1_SS2), F4(MSIOF5_SS2), F1(MSIOF1_TXD), F4(MSIOF5_TXD),
+	F1(MSIOF1_RXD), F4(MSIOF5_RXD), F1(MSIOF1_SS1), F4(MSIOF5_SS1),
+	F1(MSIOF0_SS1), F1(MSIOF1_SCK), F4(MSIOF5_SCK),
+	F1(MSIOF1_SYNC), F4(MSIOF5_SYNC),
+	F1(MSIOF2_SS1), F3(VIO_CKO5_270), /* Port270 */
+	F1(MSIOF2_SS2), F3(VIO_CKO2_271), F1(MSIOF3_SS2), F3(VIO_CKO1_272),
+	F1(MSIOF3_SS1), F3(VIO_CKO4_273), F1(MSIOF4_SS2), F4(TPU1TO0),
+	F1(IC_DP), F1(SIM0_RST), F1(IC_DM), F1(SIM0_BSICOMP),
+	F1(SIM0_CLK), F1(SIM0_IO), /* Port280 */
+	F1(SIM1_IO), F2(PDM2_DATA_281), F1(SIM1_CLK), F2(PDM2_CLK_282),
+	F1(SIM1_RST), F1(SDHID1_0), F3(STMDATA0_2),
+	F1(SDHID1_1), F3(STMDATA1_2), IRQ(51), /* Port290 */
+	F1(SDHID1_2), F3(STMDATA2_2), F1(SDHID1_3), F3(STMDATA3_2),
+	F1(SDHICLK1), F3(STMCLK_2), F1(SDHICMD1), F3(STMSIDI_2),
+	F1(SDHID2_0), F2(MSIOF4_TXD), F3(SCIFB2_TXD_295), F4(MSIOF6_TXD),
+	F1(SDHID2_1), F4(MSIOF6_SS2), IRQ(52),
+	F1(SDHID2_2), F2(MSIOF4_RXD), F3(SCIFB2_RXD_297), F4(MSIOF6_RXD),
+	F1(SDHID2_3), F2(MSIOF4_SYNC), F3(SCIFB2_CTS_298), F4(MSIOF6_SYNC),
+	F1(SDHICLK2), F2(MSIOF4_SCK), F3(SCIFB2_SCK_299), F4(MSIOF6_SCK),
+	F1(SDHICMD2), F2(MSIOF4_SS1), F3(SCIFB2_RTS_300),
+	F4(MSIOF6_SS1), /* Port300 */
+	F1(SDHICD0), IRQ(50), F1(SDHID0_0), F3(STMDATA0_1),
+	F1(SDHID0_1), F3(STMDATA1_1), F1(SDHID0_2), F3(STMDATA2_1),
+	F1(SDHID0_3), F3(STMDATA3_1), F1(SDHICMD0), F3(STMSIDI_1),
+	F1(SDHIWP0), F1(SDHICLK0), F3(STMCLK_1), IRQ(16), /* Port320 */
+	IRQ(17), IRQ(28), IRQ(29), IRQ(30), IRQ(53), IRQ(54),
+	IRQ(55), IRQ(56), IRQ(57),
+	PINMUX_MARK_END,
+};
+
+#define _PORT_DATA(pfx, sfx)	PORT_DATA_IO(pfx)
+#define PINMUX_DATA_ALL()    CPU_ALL_PORT(_PORT_DATA, , unused)
+
+static const pinmux_enum_t pinmux_data[] = {
+	/* specify valid pin states for each pin in GPIO mode */
+	PINMUX_DATA_ALL(),
+
+	/* Port0 */
+	PINMUX_DATA(LCDD0_MARK,		PORT0_FN1),
+	PINMUX_DATA(PDM2_CLK_0_MARK,	PORT0_FN3),
+	PINMUX_DATA(DU0_DR0_MARK,	PORT0_FN7),
+	PINMUX_DATA(IRQ0_MARK,		PORT0_FN0),
+
+	/* Port1 */
+	PINMUX_DATA(LCDD1_MARK,		PORT1_FN1),
+	PINMUX_DATA(PDM2_DATA_1_MARK,	PORT1_FN3,	MSEL3CR_12_0),
+	PINMUX_DATA(DU0_DR19_MARK,	PORT1_FN7),
+	PINMUX_DATA(IRQ1_MARK,		PORT1_FN0),
+
+	/* Port2 */
+	PINMUX_DATA(LCDD2_MARK,		PORT2_FN1),
+	PINMUX_DATA(PDM3_CLK_2_MARK,	PORT2_FN3),
+	PINMUX_DATA(DU0_DR2_MARK,	PORT2_FN7),
+	PINMUX_DATA(IRQ2_MARK,		PORT2_FN0),
+
+	/* Port3 */
+	PINMUX_DATA(LCDD3_MARK,		PORT3_FN1),
+	PINMUX_DATA(PDM3_DATA_3_MARK,	PORT3_FN3,	MSEL3CR_12_0),
+	PINMUX_DATA(DU0_DR3_MARK,	PORT3_FN7),
+	PINMUX_DATA(IRQ3_MARK,		PORT3_FN0),
+
+	/* Port4 */
+	PINMUX_DATA(LCDD4_MARK,		PORT4_FN1),
+	PINMUX_DATA(PDM4_CLK_4_MARK,	PORT4_FN3),
+	PINMUX_DATA(DU0_DR4_MARK,	PORT4_FN7),
+	PINMUX_DATA(IRQ4_MARK,		PORT4_FN0),
+
+	/* Port5 */
+	PINMUX_DATA(LCDD5_MARK,		PORT5_FN1),
+	PINMUX_DATA(PDM4_DATA_5_MARK,	PORT5_FN3,	MSEL3CR_12_0),
+	PINMUX_DATA(DU0_DR5_MARK,	PORT5_FN7),
+	PINMUX_DATA(IRQ5_MARK,		PORT5_FN0),
+
+	/* Port6 */
+	PINMUX_DATA(LCDD6_MARK,		PORT6_FN1),
+	PINMUX_DATA(PDM0_OUTCLK_6_MARK,	PORT6_FN3),
+	PINMUX_DATA(DU0_DR6_MARK,	PORT6_FN7),
+	PINMUX_DATA(IRQ6_MARK,		PORT6_FN0),
+
+	/* Port7 */
+	PINMUX_DATA(LCDD7_MARK,			PORT7_FN1),
+	PINMUX_DATA(PDM0_OUTDATA_7_MARK,	PORT7_FN3),
+	PINMUX_DATA(DU0_DR7_MARK,		PORT7_FN7),
+	PINMUX_DATA(IRQ7_MARK,			PORT7_FN0),
+
+	/* Port8 */
+	PINMUX_DATA(LCDD8_MARK,		PORT8_FN1),
+	PINMUX_DATA(PDM1_OUTCLK_8_MARK,	PORT8_FN3),
+	PINMUX_DATA(DU0_DG0_MARK,	PORT8_FN7),
+	PINMUX_DATA(IRQ8_MARK,		PORT8_FN0),
+
+	/* Port9 */
+	PINMUX_DATA(LCDD9_MARK,		PORT9_FN1),
+	PINMUX_DATA(PDM1_OUTDATA_9_MARK, PORT9_FN3),
+	PINMUX_DATA(DU0_DG1_MARK,	PORT9_FN7),
+	PINMUX_DATA(IRQ9_MARK,		PORT9_FN0),
+
+	/* Port10 */
+	PINMUX_DATA(LCDD10_MARK,		PORT10_FN1),
+	PINMUX_DATA(FSICCK_MARK,		PORT10_FN3),
+	PINMUX_DATA(DU0_DG2_MARK,		PORT10_FN7),
+	PINMUX_DATA(IRQ10_MARK,			PORT10_FN0),
+
+	/* Port11 */
+	PINMUX_DATA(LCDD11_MARK,		PORT11_FN1),
+	PINMUX_DATA(FSICISLD_MARK,		PORT11_FN3),
+	PINMUX_DATA(DU0_DG3_MARK,		PORT11_FN7),
+	PINMUX_DATA(IRQ11_MARK,			PORT11_FN0),
+
+	/* Port12 */
+	PINMUX_DATA(LCDD12_MARK,		PORT12_FN1),
+	PINMUX_DATA(FSICOMC_MARK,		PORT12_FN3),
+	PINMUX_DATA(DU0_DG4_MARK,		PORT12_FN7),
+	PINMUX_DATA(IRQ12_MARK,			PORT12_FN0),
+
+	/* Port13 */
+	PINMUX_DATA(LCDD13_MARK,		PORT13_FN1),
+	PINMUX_DATA(FSICOLR_MARK,		PORT13_FN3),
+	PINMUX_DATA(FSICILR_MARK,		PORT13_FN4),
+	PINMUX_DATA(DU0_DG5_MARK,		PORT13_FN7),
+	PINMUX_DATA(IRQ13_MARK,			PORT13_FN0),
+
+	/* Port14 */
+	PINMUX_DATA(LCDD14_MARK,		PORT14_FN1),
+	PINMUX_DATA(FSICOBT_MARK,		PORT14_FN3),
+	PINMUX_DATA(FSICIBT_MARK,		PORT14_FN4),
+	PINMUX_DATA(DU0_DG6_MARK,		PORT14_FN7),
+	PINMUX_DATA(IRQ14_MARK,			PORT14_FN0),
+
+	/* Port15 */
+	PINMUX_DATA(LCDD15_MARK,		PORT15_FN1),
+	PINMUX_DATA(FSICOSLD_MARK,		PORT15_FN3),
+	PINMUX_DATA(DU0_DG7_MARK,		PORT15_FN7),
+	PINMUX_DATA(IRQ15_MARK,			PORT15_FN0),
+
+	/* Port16 */
+	PINMUX_DATA(LCDD16_MARK,		PORT16_FN1),
+	PINMUX_DATA(TPU1TO1_MARK,		PORT16_FN4),
+	PINMUX_DATA(DU0_DB0_MARK,		PORT16_FN7),
+
+	/* Port17 */
+	PINMUX_DATA(LCDD17_MARK,		PORT17_FN1),
+	PINMUX_DATA(SF_IRQ_00_MARK,		PORT17_FN4),
+	PINMUX_DATA(DU0_DB1_MARK,		PORT17_FN7),
+
+	/* Port18 */
+	PINMUX_DATA(LCDD18_MARK,		PORT18_FN1),
+	PINMUX_DATA(SF_IRQ_01_MARK,		PORT18_FN4),
+	PINMUX_DATA(DU0_DB2_MARK,		PORT18_FN7),
+
+	/* Port19 */
+	PINMUX_DATA(LCDD19_MARK,		PORT19_FN1),
+	PINMUX_DATA(SCIFB3_RTS_19_MARK,		PORT19_FN3),
+	PINMUX_DATA(DU0_DB3_MARK,		PORT19_FN7),
+
+	/* Port20 */
+	PINMUX_DATA(LCDD20_MARK,		PORT20_FN1),
+	PINMUX_DATA(SCIFB3_CTS_20_MARK,		PORT20_FN3,	MSEL3CR_09_0),
+	PINMUX_DATA(DU0_DB4_MARK,		PORT20_FN7),
+
+	/* Port21 */
+	PINMUX_DATA(LCDD21_MARK,		PORT21_FN1),
+	PINMUX_DATA(SCIFB3_TXD_21_MARK,		PORT21_FN3,	MSEL3CR_09_0),
+	PINMUX_DATA(DU0_DB5_MARK,		PORT21_FN7),
+
+	/* Port22 */
+	PINMUX_DATA(LCDD22_MARK,		PORT22_FN1),
+	PINMUX_DATA(SCIFB3_RXD_22_MARK,		PORT22_FN3,	MSEL3CR_09_0),
+	PINMUX_DATA(DU0_DB6_MARK,		PORT22_FN7),
+
+	/* Port23 */
+	PINMUX_DATA(LCDD23_MARK,		PORT23_FN1),
+	PINMUX_DATA(SCIFB3_SCK_23_MARK,		PORT23_FN3),
+	PINMUX_DATA(DU0_DB7_MARK,		PORT23_FN7),
+
+	/* Port24 */
+	PINMUX_DATA(LCDHSYN_MARK,			PORT24_FN1),
+	PINMUX_DATA(LCDCS_MARK,				PORT24_FN2),
+	PINMUX_DATA(SCIFB1_RTS_24_MARK,			PORT24_FN3),
+	PINMUX_DATA(DU0_EXHSYNC_N_CSYNC_N_HSYNC_N_MARK,	PORT24_FN7),
+
+	/* Port25 */
+	PINMUX_DATA(LCDVSYN_MARK,			PORT25_FN1),
+	PINMUX_DATA(SCIFB1_CTS_25_MARK, PORT25_FN3, MSEL3CR_11_0),
+	PINMUX_DATA(DU0_EXVSYNC_N_VSYNC_N_CSYNC_N_MARK,	PORT25_FN7),
+
+	/* Port26 */
+	PINMUX_DATA(LCDDCK_MARK,		PORT26_FN1),
+	PINMUX_DATA(LCDWR_MARK,			PORT26_FN2),
+	PINMUX_DATA(SCIFB1_TXD_26_MARK,		PORT26_FN3,	MSEL3CR_11_0),
+	PINMUX_DATA(DU0_DOTCLKIN_MARK,		PORT26_FN7),
+
+	/* Port27 */
+	PINMUX_DATA(LCDDISP_MARK,		PORT27_FN1),
+	PINMUX_DATA(LCDRS_MARK,			PORT27_FN2),
+	PINMUX_DATA(SCIFB1_RXD_27_MARK,		PORT27_FN3,	MSEL3CR_11_0),
+	PINMUX_DATA(DU0_DOTCLKOUT_MARK,		PORT27_FN7),
+
+	/* Port28 */
+	PINMUX_DATA(LCDRD_N_MARK,		PORT28_FN1),
+	PINMUX_DATA(SCIFB1_SCK_28_MARK,		PORT28_FN3),
+	PINMUX_DATA(DU0_DOTCLKOUTB_MARK,	PORT28_FN7),
+
+	/* Port29 */
+	PINMUX_DATA(LCDLCLK_MARK,		PORT29_FN1),
+	PINMUX_DATA(SF_IRQ_02_MARK,		PORT29_FN4),
+	PINMUX_DATA(DU0_DISP_CSYNC_N_DE_MARK,	PORT29_FN7),
+
+	/* Port30 */
+	PINMUX_DATA(LCDDON_MARK,		PORT30_FN1),
+	PINMUX_DATA(SF_IRQ_03_MARK,		PORT30_FN4),
+	PINMUX_DATA(DU0_ODDF_N_CLAMP_MARK,	PORT30_FN7),
+
+	/* Port32 */
+	PINMUX_DATA(SCIFA0_RTS_MARK,		PORT32_FN1),
+	PINMUX_DATA(SIM0_DET_MARK,		PORT32_FN5),
+	PINMUX_DATA(CSCIF0_RTS_MARK,		PORT32_FN7),
+
+	/* Port33 */
+	PINMUX_DATA(SCIFA0_CTS_MARK,		PORT33_FN1),
+	PINMUX_DATA(SIM1_DET_MARK,		PORT33_FN5),
+	PINMUX_DATA(CSCIF0_CTS_MARK,		PORT33_FN7),
+
+	/* Port34 */
+	PINMUX_DATA(SCIFA0_SCK_MARK,		PORT34_FN1),
+	PINMUX_DATA(SIM0_PWRON_MARK,		PORT34_FN5),
+	PINMUX_DATA(CSCIF0_SCK_MARK,		PORT34_FN7),
+
+	/* Port35 */
+	PINMUX_DATA(SCIFA1_RTS_MARK,		PORT35_FN1),
+	PINMUX_DATA(CSCIF1_RTS_MARK,		PORT35_FN7),
+
+	/* Port36 */
+	PINMUX_DATA(SCIFA1_CTS_MARK,		PORT36_FN1),
+	PINMUX_DATA(CSCIF1_CTS_MARK,		PORT36_FN7),
+
+	/* Port37 */
+	PINMUX_DATA(SCIFA1_SCK_MARK,		PORT37_FN1),
+	PINMUX_DATA(CSCIF1_SCK_MARK,		PORT37_FN7),
+
+	/* Port38 */
+	PINMUX_DATA(SCIFB0_RTS_MARK,		PORT38_FN1),
+	PINMUX_DATA(TPU0TO1_MARK,		PORT38_FN3),
+	PINMUX_DATA(SCIFB3_RTS_38_MARK,		PORT38_FN4),
+	PINMUX_DATA(CHSCIF0_HRTS_MARK,		PORT38_FN7),
+
+	/* Port39 */
+	PINMUX_DATA(SCIFB0_CTS_MARK,		PORT39_FN1),
+	PINMUX_DATA(TPU0TO2_MARK,		PORT39_FN3),
+	PINMUX_DATA(SCIFB3_CTS_39_MARK,		PORT39_FN4,	MSEL3CR_09_1),
+	PINMUX_DATA(CHSCIF0_HCTS_MARK,		PORT39_FN7),
+
+	/* Port40 */
+	PINMUX_DATA(SCIFB0_SCK_MARK,		PORT40_FN1),
+	PINMUX_DATA(TPU0TO3_MARK,		PORT40_FN3),
+	PINMUX_DATA(SCIFB3_SCK_40_MARK,		PORT40_FN4),
+	PINMUX_DATA(CHSCIF0_HSCK_MARK,		PORT40_FN7),
+
+	/* Port64 */
+	PINMUX_DATA(PDM0_DATA_MARK,		PORT64_FN1),
+
+	/* Port65 */
+	PINMUX_DATA(PDM1_DATA_MARK,		PORT65_FN1),
+
+	/* Port66 */
+	PINMUX_DATA(HSI_RX_WAKE_MARK,		PORT66_FN1),
+	PINMUX_DATA(SCIFB2_CTS_66_MARK,		PORT66_FN2,	MSEL3CR_10_0),
+	PINMUX_DATA(MSIOF3_SYNC_MARK,		PORT66_FN3),
+	PINMUX_DATA(GenIO4_MARK,		PORT66_FN5),
+	PINMUX_DATA(IRQ40_MARK,			PORT66_FN0),
+
+	/* Port67 */
+	PINMUX_DATA(HSI_RX_READY_MARK,		PORT67_FN1),
+	PINMUX_DATA(SCIFB1_TXD_67_MARK,		PORT67_FN2,	MSEL3CR_11_1),
+	PINMUX_DATA(GIO_OUT3_67_MARK,		PORT67_FN5),
+	PINMUX_DATA(CHSCIF1_HTX_MARK,		PORT67_FN7),
+
+	/* Port68 */
+	PINMUX_DATA(HSI_RX_FLAG_MARK,		PORT68_FN1),
+	PINMUX_DATA(SCIFB2_TXD_68_MARK,		PORT68_FN2,	MSEL3CR_10_0),
+	PINMUX_DATA(MSIOF3_TXD_MARK,		PORT68_FN3),
+	PINMUX_DATA(GIO_OUT4_68_MARK,		PORT68_FN5),
+
+	/* Port69 */
+	PINMUX_DATA(HSI_RX_DATA_MARK,		PORT69_FN1),
+	PINMUX_DATA(SCIFB2_RXD_69_MARK,		PORT69_FN2,	MSEL3CR_10_0),
+	PINMUX_DATA(MSIOF3_RXD_MARK,		PORT69_FN3),
+	PINMUX_DATA(GIO_OUT5_69_MARK,		PORT69_FN5),
+
+	/* Port70 */
+	PINMUX_DATA(HSI_TX_FLAG_MARK,		PORT70_FN1),
+	PINMUX_DATA(SCIFB1_RTS_70_MARK,		PORT70_FN2),
+	PINMUX_DATA(GIO_OUT1_70_MARK,		PORT70_FN5),
+	PINMUX_DATA(HSIC_TSTCLK0_MARK,		PORT70_FN6),
+	PINMUX_DATA(CHSCIF1_HRTS_MARK,		PORT70_FN7),
+
+	/* Port71 */
+	PINMUX_DATA(HSI_TX_DATA_MARK,		PORT71_FN1),
+	PINMUX_DATA(SCIFB1_CTS_71_MARK,		PORT71_FN2,	MSEL3CR_11_1),
+	PINMUX_DATA(GIO_OUT2_71_MARK,		PORT71_FN5),
+	PINMUX_DATA(HSIC_TSTCLK1_MARK,		PORT71_FN6),
+	PINMUX_DATA(CHSCIF1_HCTS_MARK,		PORT71_FN7),
+
+	/* Port72 */
+	PINMUX_DATA(HSI_TX_WAKE_MARK,		PORT72_FN1),
+	PINMUX_DATA(SCIFB1_RXD_72_MARK,		PORT72_FN2,	MSEL3CR_11_1),
+	PINMUX_DATA(GenIO8_MARK,		PORT72_FN5),
+	PINMUX_DATA(CHSCIF1_HRX_MARK,		PORT72_FN7),
+
+	/* Port73 */
+	PINMUX_DATA(HSI_TX_READY_MARK,		PORT73_FN1),
+	PINMUX_DATA(SCIFB2_RTS_73_MARK,		PORT73_FN2),
+	PINMUX_DATA(MSIOF3_SCK_MARK,		PORT73_FN3),
+	PINMUX_DATA(GIO_OUT0_73_MARK,		PORT73_FN5),
+
+	/* Port74 - Port85 */
+	PINMUX_DATA(IRDA_OUT_MARK,		PORT74_FN1),
+	PINMUX_DATA(IRDA_IN_MARK,		PORT75_FN1),
+	PINMUX_DATA(IRDA_FIRSEL_MARK,		PORT76_FN1),
+	PINMUX_DATA(TPU0TO0_MARK,		PORT77_FN1),
+	PINMUX_DATA(DIGRFEN_MARK,		PORT78_FN1),
+	PINMUX_DATA(GPS_TIMESTAMP_MARK,		PORT79_FN1),
+	PINMUX_DATA(TXP_MARK,			PORT80_FN1),
+	PINMUX_DATA(TXP2_MARK,			PORT81_FN1),
+	PINMUX_DATA(COEX_0_MARK,		PORT82_FN1),
+	PINMUX_DATA(COEX_1_MARK,		PORT83_FN1),
+	PINMUX_DATA(IRQ19_MARK,			PORT84_FN0),
+	PINMUX_DATA(IRQ18_MARK,			PORT85_FN0),
+
+	/* Port96 - Port101 */
+	PINMUX_DATA(KEYIN0_MARK,		PORT96_FN1),
+	PINMUX_DATA(KEYIN1_MARK,		PORT97_FN1),
+	PINMUX_DATA(KEYIN2_MARK,		PORT98_FN1),
+	PINMUX_DATA(KEYIN3_MARK,		PORT99_FN1),
+	PINMUX_DATA(KEYIN4_MARK,		PORT100_FN1),
+	PINMUX_DATA(KEYIN5_MARK,		PORT101_FN1),
+
+	/* Port102 */
+	PINMUX_DATA(KEYIN6_MARK,		PORT102_FN1),
+	PINMUX_DATA(IRQ41_MARK,			PORT102_FN0),
+
+	/* Port103 */
+	PINMUX_DATA(KEYIN7_MARK,		PORT103_FN1),
+	PINMUX_DATA(IRQ42_MARK,			PORT103_FN0),
+
+	/* Port104 - Port108 */
+	PINMUX_DATA(KEYOUT0_MARK,		PORT104_FN2),
+	PINMUX_DATA(KEYOUT1_MARK,		PORT105_FN2),
+	PINMUX_DATA(KEYOUT2_MARK,		PORT106_FN2),
+	PINMUX_DATA(KEYOUT3_MARK,		PORT107_FN2),
+	PINMUX_DATA(KEYOUT4_MARK,		PORT108_FN2),
+
+	/* Port109 */
+	PINMUX_DATA(KEYOUT5_MARK,		PORT109_FN2),
+	PINMUX_DATA(IRQ43_MARK,			PORT109_FN0),
+
+	/* Port110 */
+	PINMUX_DATA(KEYOUT6_MARK,		PORT110_FN2),
+	PINMUX_DATA(IRQ44_MARK,			PORT110_FN0),
+
+	/* Port111 */
+	PINMUX_DATA(KEYOUT7_MARK,		PORT111_FN2),
+	PINMUX_DATA(RFANAEN_MARK,		PORT111_FN5),
+	PINMUX_DATA(IRQ45_MARK,			PORT111_FN0),
+
+	/* Port112 */
+	PINMUX_DATA(KEYIN8_MARK,		PORT112_FN1),
+	PINMUX_DATA(KEYOUT8_MARK,		PORT112_FN2),
+	PINMUX_DATA(SF_IRQ_04_MARK,		PORT112_FN4),
+	PINMUX_DATA(IRQ46_MARK,			PORT112_FN0),
+
+	/* Port113 */
+	PINMUX_DATA(KEYIN9_MARK,		PORT113_FN1),
+	PINMUX_DATA(KEYOUT9_MARK,		PORT113_FN2),
+	PINMUX_DATA(SF_IRQ_05_MARK,		PORT113_FN4),
+	PINMUX_DATA(IRQ47_MARK,			PORT113_FN0),
+
+	/* Port114 */
+	PINMUX_DATA(KEYIN10_MARK,		PORT114_FN1),
+	PINMUX_DATA(KEYOUT10_MARK,		PORT114_FN2),
+	PINMUX_DATA(SF_IRQ_06_MARK,		PORT114_FN4),
+	PINMUX_DATA(IRQ48_MARK,			PORT114_FN0),
+
+	/* Port115 */
+	PINMUX_DATA(KEYIN11_MARK,		PORT115_FN1),
+	PINMUX_DATA(KEYOUT11_MARK,		PORT115_FN2),
+	PINMUX_DATA(SF_IRQ_07_MARK,		PORT115_FN4),
+	PINMUX_DATA(IRQ49_MARK,			PORT115_FN0),
+
+	/* Port116 */
+	PINMUX_DATA(SCIFA0_TXD_MARK,		PORT116_FN1),
+	PINMUX_DATA(CSCIF0_TX_MARK,		PORT116_FN7),
+
+	/* Port117 */
+	PINMUX_DATA(SCIFA0_RXD_MARK,		PORT117_FN1),
+	PINMUX_DATA(CSCIF0_RX_MARK,		PORT117_FN7),
+
+	/* Port118 */
+	PINMUX_DATA(SCIFA1_TXD_MARK,		PORT118_FN1),
+	PINMUX_DATA(CSCIF1_TX_MARK,		PORT118_FN7),
+
+	/* Port119 */
+	PINMUX_DATA(SCIFA1_RXD_MARK,		PORT119_FN1),
+	PINMUX_DATA(CSCIF1_RX_MARK,		PORT119_FN7),
+
+	/* Port120 */
+	PINMUX_DATA(SF_PORT_1_120_MARK,		PORT120_FN3),
+	PINMUX_DATA(SCIFB3_RXD_120_MARK,	PORT120_FN4,	MSEL3CR_09_1),
+	PINMUX_DATA(DU0_CDE_MARK,		PORT120_FN7),
+
+	/* Port121 */
+	PINMUX_DATA(SF_PORT_0_121_MARK,		PORT121_FN3),
+	PINMUX_DATA(SCIFB3_TXD_121_MARK,	PORT121_FN4,	MSEL3CR_09_1),
+
+	/* Port122 */
+	PINMUX_DATA(SCIFB0_TXD_MARK,		PORT122_FN1),
+	PINMUX_DATA(CHSCIF0_HTX_MARK,		PORT122_FN7),
+
+	/* Port123 */
+	PINMUX_DATA(SCIFB0_RXD_MARK,		PORT123_FN1),
+	PINMUX_DATA(CHSCIF0_HRX_MARK,		PORT123_FN7),
+
+	/* Port124 */
+	PINMUX_DATA(ISP_STROBE_124_MARK,	PORT124_FN3),
+
+	/* Port125 */
+	PINMUX_DATA(STP_ISD_0_MARK,		PORT125_FN1),
+	PINMUX_DATA(PDM4_CLK_125_MARK,		PORT125_FN2),
+	PINMUX_DATA(MSIOF2_TXD_MARK,		PORT125_FN3),
+	PINMUX_DATA(SIM0_VOLTSEL0_MARK,		PORT125_FN5),
+
+	/* Port126 */
+	PINMUX_DATA(TS_SDEN_MARK,		PORT126_FN1),
+	PINMUX_DATA(MSIOF7_SYNC_MARK,		PORT126_FN2),
+	PINMUX_DATA(STP_ISEN_1_MARK,		PORT126_FN3),
+
+	/* Port128 */
+	PINMUX_DATA(STP_ISEN_0_MARK,		PORT128_FN1),
+	PINMUX_DATA(PDM1_OUTDATA_128_MARK,	PORT128_FN2),
+	PINMUX_DATA(MSIOF2_SYNC_MARK,		PORT128_FN3),
+	PINMUX_DATA(SIM1_VOLTSEL1_MARK,		PORT128_FN5),
+
+	/* Port129 */
+	PINMUX_DATA(TS_SPSYNC_MARK,		PORT129_FN1),
+	PINMUX_DATA(MSIOF7_RXD_MARK,		PORT129_FN2),
+	PINMUX_DATA(STP_ISSYNC_1_MARK,		PORT129_FN3),
+
+	/* Port130 */
+	PINMUX_DATA(STP_ISSYNC_0_MARK,		PORT130_FN1),
+	PINMUX_DATA(PDM4_DATA_130_MARK,		PORT130_FN2,	MSEL3CR_12_1),
+	PINMUX_DATA(MSIOF2_RXD_MARK,		PORT130_FN3),
+	PINMUX_DATA(SIM0_VOLTSEL1_MARK,		PORT130_FN5),
+
+	/* Port131 */
+	PINMUX_DATA(STP_OPWM_0_MARK,		PORT131_FN1),
+	PINMUX_DATA(SIM1_PWRON_MARK,		PORT131_FN5),
+
+	/* Port132 */
+	PINMUX_DATA(TS_SCK_MARK,		PORT132_FN1),
+	PINMUX_DATA(MSIOF7_SCK_MARK,		PORT132_FN2),
+	PINMUX_DATA(STP_ISCLK_1_MARK,		PORT132_FN3),
+
+	/* Port133 */
+	PINMUX_DATA(STP_ISCLK_0_MARK,		PORT133_FN1),
+	PINMUX_DATA(PDM1_OUTCLK_133_MARK,	PORT133_FN2),
+	PINMUX_DATA(MSIOF2_SCK_MARK,		PORT133_FN3),
+	PINMUX_DATA(SIM1_VOLTSEL0_MARK,		PORT133_FN5),
+
+	/* Port134 */
+	PINMUX_DATA(TS_SDAT_MARK,		PORT134_FN1),
+	PINMUX_DATA(MSIOF7_TXD_MARK,		PORT134_FN2),
+	PINMUX_DATA(STP_ISD_1_MARK,		PORT134_FN3),
+
+	/* Port160 - Port178 */
+	PINMUX_DATA(IRQ20_MARK,			PORT160_FN0),
+	PINMUX_DATA(IRQ21_MARK,			PORT161_FN0),
+	PINMUX_DATA(IRQ22_MARK,			PORT162_FN0),
+	PINMUX_DATA(IRQ23_MARK,			PORT163_FN0),
+	PINMUX_DATA(MMCD0_0_MARK,		PORT164_FN1),
+	PINMUX_DATA(MMCD0_1_MARK,		PORT165_FN1),
+	PINMUX_DATA(MMCD0_2_MARK,		PORT166_FN1),
+	PINMUX_DATA(MMCD0_3_MARK,		PORT167_FN1),
+	PINMUX_DATA(MMCD0_4_MARK,		PORT168_FN1),
+	PINMUX_DATA(MMCD0_5_MARK,		PORT169_FN1),
+	PINMUX_DATA(MMCD0_6_MARK,		PORT170_FN1),
+	PINMUX_DATA(MMCD0_7_MARK,		PORT171_FN1),
+	PINMUX_DATA(MMCCMD0_MARK,		PORT172_FN1),
+	PINMUX_DATA(MMCCLK0_MARK,		PORT173_FN1),
+	PINMUX_DATA(MMCRST_MARK,		PORT174_FN1),
+	PINMUX_DATA(IRQ24_MARK,			PORT175_FN0),
+	PINMUX_DATA(IRQ25_MARK,			PORT176_FN0),
+	PINMUX_DATA(IRQ26_MARK,			PORT177_FN0),
+	PINMUX_DATA(IRQ27_MARK,			PORT178_FN0),
+
+	/* Port192 - Port200 FN1 */
+	PINMUX_DATA(A10_MARK,		PORT192_FN1),
+	PINMUX_DATA(A9_MARK,		PORT193_FN1),
+	PINMUX_DATA(A8_MARK,		PORT194_FN1),
+	PINMUX_DATA(A7_MARK,		PORT195_FN1),
+	PINMUX_DATA(A6_MARK,		PORT196_FN1),
+	PINMUX_DATA(A5_MARK,		PORT197_FN1),
+	PINMUX_DATA(A4_MARK,		PORT198_FN1),
+	PINMUX_DATA(A3_MARK,		PORT199_FN1),
+	PINMUX_DATA(A2_MARK,		PORT200_FN1),
+
+	/* Port192 - Port200 FN2 */
+	PINMUX_DATA(MMCD1_7_MARK,		PORT192_FN2),
+	PINMUX_DATA(MMCD1_6_MARK,		PORT193_FN2),
+	PINMUX_DATA(MMCD1_5_MARK,		PORT194_FN2),
+	PINMUX_DATA(MMCD1_4_MARK,		PORT195_FN2),
+	PINMUX_DATA(MMCD1_3_MARK,		PORT196_FN2),
+	PINMUX_DATA(MMCD1_2_MARK,		PORT197_FN2),
+	PINMUX_DATA(MMCD1_1_MARK,		PORT198_FN2),
+	PINMUX_DATA(MMCD1_0_MARK,		PORT199_FN2),
+	PINMUX_DATA(MMCCMD1_MARK,		PORT200_FN2),
+
+	/* Port192 - Port200 IRQ */
+	PINMUX_DATA(IRQ31_MARK,			PORT192_FN0),
+	PINMUX_DATA(IRQ32_MARK,			PORT193_FN0),
+	PINMUX_DATA(IRQ33_MARK,			PORT194_FN0),
+	PINMUX_DATA(IRQ34_MARK,			PORT195_FN0),
+	PINMUX_DATA(IRQ35_MARK,			PORT196_FN0),
+	PINMUX_DATA(IRQ36_MARK,			PORT197_FN0),
+	PINMUX_DATA(IRQ37_MARK,			PORT198_FN0),
+	PINMUX_DATA(IRQ38_MARK,			PORT199_FN0),
+	PINMUX_DATA(IRQ39_MARK,			PORT200_FN0),
+
+	/* Port201 */
+	PINMUX_DATA(A1_MARK,		PORT201_FN1),
+
+	/* Port202 */
+	PINMUX_DATA(A0_MARK,		PORT202_FN1),
+	PINMUX_DATA(BS_MARK,		PORT202_FN2),
+
+	/* Port203 */
+	PINMUX_DATA(CKO_MARK,		PORT203_FN1),
+	PINMUX_DATA(MMCCLK1_MARK,	PORT203_FN2),
+
+	/* Port204 */
+	PINMUX_DATA(CS0_N_MARK,		PORT204_FN1),
+	PINMUX_DATA(SIM0_GPO1_MARK,	PORT204_FN5),
+
+	/* Port205 */
+	PINMUX_DATA(CS2_N_MARK,		PORT205_FN1),
+	PINMUX_DATA(SIM0_GPO2_MARK,	PORT205_FN5),
+
+	/* Port206 */
+	PINMUX_DATA(CS4_N_MARK,		PORT206_FN1),
+	PINMUX_DATA(VIO_VD_MARK,	PORT206_FN2),
+	PINMUX_DATA(SIM1_GPO0_MARK,	PORT206_FN5),
+
+	/* Port207 - Port212 FN1 */
+	PINMUX_DATA(D15_MARK,		PORT207_FN1),
+	PINMUX_DATA(D14_MARK,		PORT208_FN1),
+	PINMUX_DATA(D13_MARK,		PORT209_FN1),
+	PINMUX_DATA(D12_MARK,		PORT210_FN1),
+	PINMUX_DATA(D11_MARK,		PORT211_FN1),
+	PINMUX_DATA(D10_MARK,		PORT212_FN1),
+
+	/* Port207 - Port212 FN5 */
+	PINMUX_DATA(GIO_OUT15_MARK,			PORT207_FN5),
+	PINMUX_DATA(GIO_OUT14_MARK,			PORT208_FN5),
+	PINMUX_DATA(GIO_OUT13_MARK,			PORT209_FN5),
+	PINMUX_DATA(GIO_OUT12_MARK,			PORT210_FN5),
+	PINMUX_DATA(WGM_TXP2_MARK,			PORT211_FN5),
+	PINMUX_DATA(WGM_GPS_TIMEM_ASK_RFCLK_MARK,	PORT212_FN5),
+
+	/* Port213 - Port222 FN1 */
+	PINMUX_DATA(D9_MARK,		PORT213_FN1),
+	PINMUX_DATA(D8_MARK,		PORT214_FN1),
+	PINMUX_DATA(D7_MARK,		PORT215_FN1),
+	PINMUX_DATA(D6_MARK,		PORT216_FN1),
+	PINMUX_DATA(D5_MARK,		PORT217_FN1),
+	PINMUX_DATA(D4_MARK,		PORT218_FN1),
+	PINMUX_DATA(D3_MARK,		PORT219_FN1),
+	PINMUX_DATA(D2_MARK,		PORT220_FN1),
+	PINMUX_DATA(D1_MARK,		PORT221_FN1),
+	PINMUX_DATA(D0_MARK,		PORT222_FN1),
+
+	/* Port213 - Port222 FN2 */
+	PINMUX_DATA(VIO_D9_MARK,	PORT213_FN2),
+	PINMUX_DATA(VIO_D8_MARK,	PORT214_FN2),
+	PINMUX_DATA(VIO_D7_MARK,	PORT215_FN2),
+	PINMUX_DATA(VIO_D6_MARK,	PORT216_FN2),
+	PINMUX_DATA(VIO_D5_MARK,	PORT217_FN2),
+	PINMUX_DATA(VIO_D4_MARK,	PORT218_FN2),
+	PINMUX_DATA(VIO_D3_MARK,	PORT219_FN2),
+	PINMUX_DATA(VIO_D2_MARK,	PORT220_FN2),
+	PINMUX_DATA(VIO_D1_MARK,	PORT221_FN2),
+	PINMUX_DATA(VIO_D0_MARK,	PORT222_FN2),
+
+	/* Port213 - Port222 FN5 */
+	PINMUX_DATA(GIO_OUT9_MARK,	PORT213_FN5),
+	PINMUX_DATA(GIO_OUT8_MARK,	PORT214_FN5),
+	PINMUX_DATA(GIO_OUT7_MARK,	PORT215_FN5),
+	PINMUX_DATA(GIO_OUT6_MARK,	PORT216_FN5),
+	PINMUX_DATA(GIO_OUT5_217_MARK,	PORT217_FN5),
+	PINMUX_DATA(GIO_OUT4_218_MARK,	PORT218_FN5),
+	PINMUX_DATA(GIO_OUT3_219_MARK,	PORT219_FN5),
+	PINMUX_DATA(GIO_OUT2_220_MARK,	PORT220_FN5),
+	PINMUX_DATA(GIO_OUT1_221_MARK,	PORT221_FN5),
+	PINMUX_DATA(GIO_OUT0_222_MARK,	PORT222_FN5),
+
+	/* Port224 */
+	PINMUX_DATA(RDWR_224_MARK,	PORT224_FN1),
+	PINMUX_DATA(VIO_HD_MARK,	PORT224_FN2),
+	PINMUX_DATA(SIM1_GPO2_MARK,	PORT224_FN5),
+
+	/* Port225 */
+	PINMUX_DATA(RD_N_MARK,		PORT225_FN1),
+
+	/* Port226 */
+	PINMUX_DATA(WAIT_N_MARK,	PORT226_FN1),
+	PINMUX_DATA(VIO_CLK_MARK,	PORT226_FN2),
+	PINMUX_DATA(SIM1_GPO1_MARK,	PORT226_FN5),
+
+	/* Port227 */
+	PINMUX_DATA(WE0_N_MARK,		PORT227_FN1),
+	PINMUX_DATA(RDWR_227_MARK,	PORT227_FN2),
+
+	/* Port228 */
+	PINMUX_DATA(WE1_N_MARK,		PORT228_FN1),
+	PINMUX_DATA(SIM0_GPO0_MARK,	PORT228_FN5),
+
+	/* Port229 */
+	PINMUX_DATA(PWMO_MARK,		PORT229_FN1),
+	PINMUX_DATA(VIO_CKO1_229_MARK,	PORT229_FN2),
+
+	/* Port230 */
+	PINMUX_DATA(SLIM_CLK_MARK,	PORT230_FN1),
+	PINMUX_DATA(VIO_CKO4_230_MARK,	PORT230_FN2),
+
+	/* Port231 */
+	PINMUX_DATA(SLIM_DATA_MARK,	PORT231_FN1),
+	PINMUX_DATA(VIO_CKO5_231_MARK,	PORT231_FN2),
+
+	/* Port232 */
+	PINMUX_DATA(VIO_CKO2_232_MARK,	PORT232_FN2),
+	PINMUX_DATA(SF_PORT_0_232_MARK,	PORT232_FN4),
+
+	/* Port233 */
+	PINMUX_DATA(VIO_CKO3_233_MARK,	PORT233_FN2),
+	PINMUX_DATA(SF_PORT_1_233_MARK,	PORT233_FN4),
+
+	/* Port234 */
+	PINMUX_DATA(FSIACK_MARK,	PORT234_FN1),
+	PINMUX_DATA(PDM3_CLK_234_MARK,	PORT234_FN2),
+	PINMUX_DATA(ISP_IRIS1_234_MARK,	PORT234_FN3),
+
+	/* Port235 */
+	PINMUX_DATA(FSIAISLD_MARK,	PORT235_FN1),
+	PINMUX_DATA(PDM3_DATA_235_MARK,	PORT235_FN2,	MSEL3CR_12_1),
+
+	/* Port236 */
+	PINMUX_DATA(FSIAOMC_MARK,		PORT236_FN1),
+	PINMUX_DATA(PDM0_OUTCLK_236_MARK,	PORT236_FN2),
+	PINMUX_DATA(ISP_IRIS0_236_MARK,		PORT236_FN3),
+
+	/* Port237 */
+	PINMUX_DATA(FSIAOLR_MARK,	PORT237_FN1),
+	PINMUX_DATA(FSIAILR_MARK,	PORT237_FN2),
+
+	/* Port238 */
+	PINMUX_DATA(FSIAOBT_MARK,	PORT238_FN1),
+	PINMUX_DATA(FSIAIBT_MARK,	PORT238_FN2),
+
+	/* Port239 */
+	PINMUX_DATA(FSIAOSLD_MARK,		PORT239_FN1),
+	PINMUX_DATA(PDM0_OUTDATA_239_MARK,	PORT239_FN2),
+
+	/* Port240 */
+	PINMUX_DATA(FSIBISLD_MARK,	PORT240_FN1),
+
+	/* Port241 */
+	PINMUX_DATA(FSIBOLR_MARK,	PORT241_FN1),
+	PINMUX_DATA(FSIBILR_MARK,	PORT241_FN2),
+
+	/* Port242 */
+	PINMUX_DATA(FSIBOMC_MARK,		PORT242_FN1),
+	PINMUX_DATA(ISP_SHUTTER1_242_MARK,	PORT242_FN3),
+
+	/* Port243 */
+	PINMUX_DATA(FSIBOBT_MARK,	PORT243_FN1),
+	PINMUX_DATA(FSIBIBT_MARK,	PORT243_FN2),
+
+	/* Port244 */
+	PINMUX_DATA(FSIBOSLD_MARK,	PORT244_FN1),
+	PINMUX_DATA(FSIASPDIF_MARK,	PORT244_FN2),
+
+	/* Port245 */
+	PINMUX_DATA(FSIBCK_MARK,		PORT245_FN1),
+	PINMUX_DATA(ISP_SHUTTER0_245_MARK,	PORT245_FN3),
+
+	/* Port246 - Port250 FN1 */
+	PINMUX_DATA(ISP_IRIS1_246_MARK,		PORT246_FN1),
+	PINMUX_DATA(ISP_IRIS0_247_MARK,		PORT247_FN1),
+	PINMUX_DATA(ISP_SHUTTER1_248_MARK,	PORT248_FN1),
+	PINMUX_DATA(ISP_SHUTTER0_249_MARK,	PORT249_FN1),
+	PINMUX_DATA(ISP_STROBE_250_MARK,	PORT250_FN1),
+
+	/* Port256 - Port258 */
+	PINMUX_DATA(MSIOF0_SYNC_MARK,		PORT256_FN1),
+	PINMUX_DATA(MSIOF0_RXD_MARK,		PORT257_FN1),
+	PINMUX_DATA(MSIOF0_SCK_MARK,		PORT258_FN1),
+
+	/* Port259 */
+	PINMUX_DATA(MSIOF0_SS2_MARK,		PORT259_FN1),
+	PINMUX_DATA(VIO_CKO3_259_MARK,		PORT259_FN3),
+
+	/* Port260 */
+	PINMUX_DATA(MSIOF0_TXD_MARK,		PORT260_FN1),
+
+	/* Port261 */
+	PINMUX_DATA(SCIFB1_SCK_261_MARK,	PORT261_FN2),
+	PINMUX_DATA(CHSCIF1_HSCK_MARK,		PORT261_FN7),
+
+	/* Port262 */
+	PINMUX_DATA(SCIFB2_SCK_262_MARK,	PORT262_FN2),
+
+	/* Port263 - Port266 FN1 */
+	PINMUX_DATA(MSIOF1_SS2_MARK,		PORT263_FN1),
+	PINMUX_DATA(MSIOF1_TXD_MARK,		PORT264_FN1),
+	PINMUX_DATA(MSIOF1_RXD_MARK,		PORT265_FN1),
+	PINMUX_DATA(MSIOF1_SS1_MARK,		PORT266_FN1),
+
+	/* Port263 - Port266 FN4 */
+	PINMUX_DATA(MSIOF5_SS2_MARK,		PORT263_FN4),
+	PINMUX_DATA(MSIOF5_TXD_MARK,		PORT264_FN4),
+	PINMUX_DATA(MSIOF5_RXD_MARK,		PORT265_FN4),
+	PINMUX_DATA(MSIOF5_SS1_MARK,		PORT266_FN4),
+
+	/* Port267 */
+	PINMUX_DATA(MSIOF0_SS1_MARK,		PORT267_FN1),
+
+	/* Port268 */
+	PINMUX_DATA(MSIOF1_SCK_MARK,		PORT268_FN1),
+	PINMUX_DATA(MSIOF5_SCK_MARK,		PORT268_FN4),
+
+	/* Port269 */
+	PINMUX_DATA(MSIOF1_SYNC_MARK,		PORT269_FN1),
+	PINMUX_DATA(MSIOF5_SYNC_MARK,		PORT269_FN4),
+
+	/* Port270 - Port273 FN1 */
+	PINMUX_DATA(MSIOF2_SS1_MARK,		PORT270_FN1),
+	PINMUX_DATA(MSIOF2_SS2_MARK,		PORT271_FN1),
+	PINMUX_DATA(MSIOF3_SS2_MARK,		PORT272_FN1),
+	PINMUX_DATA(MSIOF3_SS1_MARK,		PORT273_FN1),
+
+	/* Port270 - Port273 FN3 */
+	PINMUX_DATA(VIO_CKO5_270_MARK,		PORT270_FN3),
+	PINMUX_DATA(VIO_CKO2_271_MARK,		PORT271_FN3),
+	PINMUX_DATA(VIO_CKO1_272_MARK,		PORT272_FN3),
+	PINMUX_DATA(VIO_CKO4_273_MARK,		PORT273_FN3),
+
+	/* Port274 */
+	PINMUX_DATA(MSIOF4_SS2_MARK,		PORT274_FN1),
+	PINMUX_DATA(TPU1TO0_MARK,		PORT274_FN4),
+
+	/* Port275 - Port280 */
+	PINMUX_DATA(IC_DP_MARK,			PORT275_FN1),
+	PINMUX_DATA(SIM0_RST_MARK,		PORT276_FN1),
+	PINMUX_DATA(IC_DM_MARK,			PORT277_FN1),
+	PINMUX_DATA(SIM0_BSICOMP_MARK,		PORT278_FN1),
+	PINMUX_DATA(SIM0_CLK_MARK,		PORT279_FN1),
+	PINMUX_DATA(SIM0_IO_MARK,		PORT280_FN1),
+
+	/* Port281 */
+	PINMUX_DATA(SIM1_IO_MARK,		PORT281_FN1),
+	PINMUX_DATA(PDM2_DATA_281_MARK,		PORT281_FN2,	MSEL3CR_12_1),
+
+	/* Port282 */
+	PINMUX_DATA(SIM1_CLK_MARK,		PORT282_FN1),
+	PINMUX_DATA(PDM2_CLK_282_MARK,		PORT282_FN2),
+
+	/* Port283 */
+	PINMUX_DATA(SIM1_RST_MARK,		PORT283_FN1),
+
+	/* Port289 */
+	PINMUX_DATA(SDHID1_0_MARK,		PORT289_FN1),
+	PINMUX_DATA(STMDATA0_2_MARK,		PORT289_FN3),
+
+	/* Port290 */
+	PINMUX_DATA(SDHID1_1_MARK,		PORT290_FN1),
+	PINMUX_DATA(STMDATA1_2_MARK,		PORT290_FN3),
+	PINMUX_DATA(IRQ51_MARK,			PORT290_FN0),
+
+	/* Port291 - Port294 FN1 */
+	PINMUX_DATA(SDHID1_2_MARK,		PORT291_FN1),
+	PINMUX_DATA(SDHID1_3_MARK,		PORT292_FN1),
+	PINMUX_DATA(SDHICLK1_MARK,		PORT293_FN1),
+	PINMUX_DATA(SDHICMD1_MARK,		PORT294_FN1),
+
+	/* Port291 - Port294 FN3 */
+	PINMUX_DATA(STMDATA2_2_MARK,		PORT291_FN3),
+	PINMUX_DATA(STMDATA3_2_MARK,		PORT292_FN3),
+	PINMUX_DATA(STMCLK_2_MARK,		PORT293_FN3),
+	PINMUX_DATA(STMSIDI_2_MARK,		PORT294_FN3),
+
+	/* Port295 */
+	PINMUX_DATA(SDHID2_0_MARK,		PORT295_FN1),
+	PINMUX_DATA(MSIOF4_TXD_MARK,		PORT295_FN2),
+	PINMUX_DATA(SCIFB2_TXD_295_MARK,	PORT295_FN3,	MSEL3CR_10_1),
+	PINMUX_DATA(MSIOF6_TXD_MARK,		PORT295_FN4),
+
+	/* Port296 */
+	PINMUX_DATA(SDHID2_1_MARK,		PORT296_FN1),
+	PINMUX_DATA(MSIOF6_SS2_MARK,		PORT296_FN4),
+	PINMUX_DATA(IRQ52_MARK,			PORT296_FN0),
+
+	/* Port297 - Port300 FN1 */
+	PINMUX_DATA(SDHID2_2_MARK,		PORT297_FN1),
+	PINMUX_DATA(SDHID2_3_MARK,		PORT298_FN1),
+	PINMUX_DATA(SDHICLK2_MARK,		PORT299_FN1),
+	PINMUX_DATA(SDHICMD2_MARK,		PORT300_FN1),
+
+	/* Port297 - Port300 FN2 */
+	PINMUX_DATA(MSIOF4_RXD_MARK,		PORT297_FN2),
+	PINMUX_DATA(MSIOF4_SYNC_MARK,		PORT298_FN2),
+	PINMUX_DATA(MSIOF4_SCK_MARK,		PORT299_FN2),
+	PINMUX_DATA(MSIOF4_SS1_MARK,		PORT300_FN2),
+
+	/* Port297 - Port300 FN3 */
+	PINMUX_DATA(SCIFB2_RXD_297_MARK,	PORT297_FN3,	MSEL3CR_10_1),
+	PINMUX_DATA(SCIFB2_CTS_298_MARK,	PORT298_FN3,	MSEL3CR_10_1),
+	PINMUX_DATA(SCIFB2_SCK_299_MARK,	PORT299_FN3),
+	PINMUX_DATA(SCIFB2_RTS_300_MARK,	PORT300_FN3),
+
+	/* Port297 - Port300 FN4 */
+	PINMUX_DATA(MSIOF6_RXD_MARK,		PORT297_FN4),
+	PINMUX_DATA(MSIOF6_SYNC_MARK,		PORT298_FN4),
+	PINMUX_DATA(MSIOF6_SCK_MARK,		PORT299_FN4),
+	PINMUX_DATA(MSIOF6_SS1_MARK,		PORT300_FN4),
+
+	/* Port301 */
+	PINMUX_DATA(SDHICD0_MARK,		PORT301_FN1),
+	PINMUX_DATA(IRQ50_MARK,			PORT301_FN0),
+
+	/* Port302 - Port306 FN1 */
+	PINMUX_DATA(SDHID0_0_MARK,		PORT302_FN1),
+	PINMUX_DATA(SDHID0_1_MARK,		PORT303_FN1),
+	PINMUX_DATA(SDHID0_2_MARK,		PORT304_FN1),
+	PINMUX_DATA(SDHID0_3_MARK,		PORT305_FN1),
+	PINMUX_DATA(SDHICMD0_MARK,		PORT306_FN1),
+
+	/* Port302 - Port306 FN3 */
+	PINMUX_DATA(STMDATA0_1_MARK,		PORT302_FN3),
+	PINMUX_DATA(STMDATA1_1_MARK,		PORT303_FN3),
+	PINMUX_DATA(STMDATA2_1_MARK,		PORT304_FN3),
+	PINMUX_DATA(STMDATA3_1_MARK,		PORT305_FN3),
+	PINMUX_DATA(STMSIDI_1_MARK,		PORT306_FN3),
+
+	/* Port307 */
+	PINMUX_DATA(SDHIWP0_MARK,		PORT307_FN1),
+
+	/* Port308 */
+	PINMUX_DATA(SDHICLK0_MARK,		PORT308_FN1),
+	PINMUX_DATA(STMCLK_1_MARK,		PORT308_FN3),
+
+	/* Port320 - Port329 */
+	PINMUX_DATA(IRQ16_MARK,			PORT320_FN0),
+	PINMUX_DATA(IRQ17_MARK,			PORT321_FN0),
+	PINMUX_DATA(IRQ28_MARK,			PORT322_FN0),
+	PINMUX_DATA(IRQ29_MARK,			PORT323_FN0),
+	PINMUX_DATA(IRQ30_MARK,			PORT324_FN0),
+	PINMUX_DATA(IRQ53_MARK,			PORT325_FN0),
+	PINMUX_DATA(IRQ54_MARK,			PORT326_FN0),
+	PINMUX_DATA(IRQ55_MARK,			PORT327_FN0),
+	PINMUX_DATA(IRQ56_MARK,			PORT328_FN0),
+	PINMUX_DATA(IRQ57_MARK,			PORT329_FN0),
+};
+
+#define R8A73A4_PIN(pin, cfgs)			\
+	{					\
+		.name = __stringify(PORT##pin),	\
+		.enum_id = PORT##pin##_DATA,	\
+		.configs = cfgs,		\
+	}
+
+#define __O	(SH_PFC_PIN_CFG_OUTPUT)
+#define __IO	(SH_PFC_PIN_CFG_INPUT | SH_PFC_PIN_CFG_OUTPUT)
+#define __PUD	(SH_PFC_PIN_CFG_PULL_DOWN | SH_PFC_PIN_CFG_PULL_UP)
+
+#define R8A73A4_PIN_IO_PU_PD(pin)       R8A73A4_PIN(pin, __IO | __PUD)
+#define R8A73A4_PIN_O(pin)              R8A73A4_PIN(pin, __O)
+
+static struct sh_pfc_pin pinmux_pins[] = {
+	R8A73A4_PIN_IO_PU_PD(0), R8A73A4_PIN_IO_PU_PD(1),
+	R8A73A4_PIN_IO_PU_PD(2), R8A73A4_PIN_IO_PU_PD(3),
+	R8A73A4_PIN_IO_PU_PD(4), R8A73A4_PIN_IO_PU_PD(5),
+	R8A73A4_PIN_IO_PU_PD(6), R8A73A4_PIN_IO_PU_PD(7),
+	R8A73A4_PIN_IO_PU_PD(8), R8A73A4_PIN_IO_PU_PD(9),
+	R8A73A4_PIN_IO_PU_PD(10), R8A73A4_PIN_IO_PU_PD(11),
+	R8A73A4_PIN_IO_PU_PD(12), R8A73A4_PIN_IO_PU_PD(13),
+	R8A73A4_PIN_IO_PU_PD(14), R8A73A4_PIN_IO_PU_PD(15),
+	R8A73A4_PIN_IO_PU_PD(16), R8A73A4_PIN_IO_PU_PD(17),
+	R8A73A4_PIN_IO_PU_PD(18), R8A73A4_PIN_IO_PU_PD(19),
+	R8A73A4_PIN_IO_PU_PD(20), R8A73A4_PIN_IO_PU_PD(21),
+	R8A73A4_PIN_IO_PU_PD(22), R8A73A4_PIN_IO_PU_PD(23),
+	R8A73A4_PIN_IO_PU_PD(24), R8A73A4_PIN_IO_PU_PD(25),
+	R8A73A4_PIN_IO_PU_PD(26), R8A73A4_PIN_IO_PU_PD(27),
+	R8A73A4_PIN_IO_PU_PD(28), R8A73A4_PIN_IO_PU_PD(29),
+	R8A73A4_PIN_IO_PU_PD(30),
+	R8A73A4_PIN_IO_PU_PD(32), R8A73A4_PIN_IO_PU_PD(33),
+	R8A73A4_PIN_IO_PU_PD(34), R8A73A4_PIN_IO_PU_PD(35),
+	R8A73A4_PIN_IO_PU_PD(36), R8A73A4_PIN_IO_PU_PD(37),
+	R8A73A4_PIN_IO_PU_PD(38), R8A73A4_PIN_IO_PU_PD(39),
+	R8A73A4_PIN_IO_PU_PD(40),
+	R8A73A4_PIN_IO_PU_PD(64), R8A73A4_PIN_IO_PU_PD(65),
+	R8A73A4_PIN_IO_PU_PD(66), R8A73A4_PIN_IO_PU_PD(67),
+	R8A73A4_PIN_IO_PU_PD(68), R8A73A4_PIN_IO_PU_PD(69),
+	R8A73A4_PIN_IO_PU_PD(70), R8A73A4_PIN_IO_PU_PD(71),
+	R8A73A4_PIN_IO_PU_PD(72), R8A73A4_PIN_IO_PU_PD(73),
+	R8A73A4_PIN_O(74), R8A73A4_PIN_IO_PU_PD(75),
+	R8A73A4_PIN_IO_PU_PD(76), R8A73A4_PIN_IO_PU_PD(77),
+	R8A73A4_PIN_IO_PU_PD(78), R8A73A4_PIN_IO_PU_PD(79),
+	R8A73A4_PIN_IO_PU_PD(80), R8A73A4_PIN_IO_PU_PD(81),
+	R8A73A4_PIN_IO_PU_PD(82), R8A73A4_PIN_IO_PU_PD(83),
+	R8A73A4_PIN_IO_PU_PD(84), R8A73A4_PIN_IO_PU_PD(85),
+	R8A73A4_PIN_IO_PU_PD(96), R8A73A4_PIN_IO_PU_PD(97),
+	R8A73A4_PIN_IO_PU_PD(98), R8A73A4_PIN_IO_PU_PD(99),
+	R8A73A4_PIN_IO_PU_PD(100), R8A73A4_PIN_IO_PU_PD(101),
+	R8A73A4_PIN_IO_PU_PD(102), R8A73A4_PIN_IO_PU_PD(103),
+	R8A73A4_PIN_IO_PU_PD(104), R8A73A4_PIN_IO_PU_PD(105),
+	R8A73A4_PIN_IO_PU_PD(106), R8A73A4_PIN_IO_PU_PD(107),
+	R8A73A4_PIN_IO_PU_PD(108), R8A73A4_PIN_IO_PU_PD(109),
+	R8A73A4_PIN_IO_PU_PD(110), R8A73A4_PIN_IO_PU_PD(111),
+	R8A73A4_PIN_IO_PU_PD(112), R8A73A4_PIN_IO_PU_PD(113),
+	R8A73A4_PIN_IO_PU_PD(114), R8A73A4_PIN_IO_PU_PD(115),
+	R8A73A4_PIN_IO_PU_PD(116), R8A73A4_PIN_IO_PU_PD(117),
+	R8A73A4_PIN_IO_PU_PD(118), R8A73A4_PIN_IO_PU_PD(119),
+	R8A73A4_PIN_IO_PU_PD(120), R8A73A4_PIN_IO_PU_PD(121),
+	R8A73A4_PIN_IO_PU_PD(122), R8A73A4_PIN_IO_PU_PD(123),
+	R8A73A4_PIN_IO_PU_PD(124), R8A73A4_PIN_IO_PU_PD(125),
+	R8A73A4_PIN_IO_PU_PD(126),
+	R8A73A4_PIN_IO_PU_PD(128), R8A73A4_PIN_IO_PU_PD(129),
+	R8A73A4_PIN_IO_PU_PD(130), R8A73A4_PIN_IO_PU_PD(131),
+	R8A73A4_PIN_IO_PU_PD(132), R8A73A4_PIN_IO_PU_PD(133),
+	R8A73A4_PIN_IO_PU_PD(134),
+	R8A73A4_PIN_IO_PU_PD(160), R8A73A4_PIN_IO_PU_PD(161),
+	R8A73A4_PIN_IO_PU_PD(162), R8A73A4_PIN_IO_PU_PD(163),
+	R8A73A4_PIN_IO_PU_PD(164), R8A73A4_PIN_IO_PU_PD(165),
+	R8A73A4_PIN_IO_PU_PD(166), R8A73A4_PIN_IO_PU_PD(167),
+	R8A73A4_PIN_IO_PU_PD(168), R8A73A4_PIN_IO_PU_PD(169),
+	R8A73A4_PIN_IO_PU_PD(170), R8A73A4_PIN_IO_PU_PD(171),
+	R8A73A4_PIN_IO_PU_PD(172), R8A73A4_PIN_IO_PU_PD(173),
+	R8A73A4_PIN_IO_PU_PD(174), R8A73A4_PIN_IO_PU_PD(175),
+	R8A73A4_PIN_IO_PU_PD(176), R8A73A4_PIN_IO_PU_PD(177),
+	R8A73A4_PIN_IO_PU_PD(178),
+	R8A73A4_PIN_IO_PU_PD(192), R8A73A4_PIN_IO_PU_PD(193),
+	R8A73A4_PIN_IO_PU_PD(194), R8A73A4_PIN_IO_PU_PD(195),
+	R8A73A4_PIN_IO_PU_PD(196), R8A73A4_PIN_IO_PU_PD(197),
+	R8A73A4_PIN_IO_PU_PD(198), R8A73A4_PIN_IO_PU_PD(199),
+	R8A73A4_PIN_IO_PU_PD(200), R8A73A4_PIN_IO_PU_PD(201),
+	R8A73A4_PIN_IO_PU_PD(202), R8A73A4_PIN_IO_PU_PD(203),
+	R8A73A4_PIN_IO_PU_PD(204), R8A73A4_PIN_IO_PU_PD(205),
+	R8A73A4_PIN_IO_PU_PD(206), R8A73A4_PIN_IO_PU_PD(207),
+	R8A73A4_PIN_IO_PU_PD(208), R8A73A4_PIN_IO_PU_PD(209),
+	R8A73A4_PIN_IO_PU_PD(210), R8A73A4_PIN_IO_PU_PD(211),
+	R8A73A4_PIN_IO_PU_PD(212), R8A73A4_PIN_IO_PU_PD(213),
+	R8A73A4_PIN_IO_PU_PD(214), R8A73A4_PIN_IO_PU_PD(215),
+	R8A73A4_PIN_IO_PU_PD(216), R8A73A4_PIN_IO_PU_PD(217),
+	R8A73A4_PIN_IO_PU_PD(218), R8A73A4_PIN_IO_PU_PD(219),
+	R8A73A4_PIN_IO_PU_PD(220), R8A73A4_PIN_IO_PU_PD(221),
+	R8A73A4_PIN_IO_PU_PD(222),
+	R8A73A4_PIN_IO_PU_PD(224), R8A73A4_PIN_IO_PU_PD(225),
+	R8A73A4_PIN_IO_PU_PD(226), R8A73A4_PIN_IO_PU_PD(227),
+	R8A73A4_PIN_IO_PU_PD(228), R8A73A4_PIN_IO_PU_PD(229),
+	R8A73A4_PIN_IO_PU_PD(230), R8A73A4_PIN_IO_PU_PD(231),
+	R8A73A4_PIN_IO_PU_PD(232), R8A73A4_PIN_IO_PU_PD(233),
+	R8A73A4_PIN_IO_PU_PD(234), R8A73A4_PIN_IO_PU_PD(235),
+	R8A73A4_PIN_IO_PU_PD(236), R8A73A4_PIN_IO_PU_PD(237),
+	R8A73A4_PIN_IO_PU_PD(238), R8A73A4_PIN_IO_PU_PD(239),
+	R8A73A4_PIN_IO_PU_PD(240), R8A73A4_PIN_IO_PU_PD(241),
+	R8A73A4_PIN_IO_PU_PD(242), R8A73A4_PIN_IO_PU_PD(243),
+	R8A73A4_PIN_IO_PU_PD(244), R8A73A4_PIN_IO_PU_PD(245),
+	R8A73A4_PIN_IO_PU_PD(246), R8A73A4_PIN_IO_PU_PD(247),
+	R8A73A4_PIN_IO_PU_PD(248), R8A73A4_PIN_IO_PU_PD(249),
+	R8A73A4_PIN_IO_PU_PD(250),
+	R8A73A4_PIN_IO_PU_PD(256), R8A73A4_PIN_IO_PU_PD(257),
+	R8A73A4_PIN_IO_PU_PD(258), R8A73A4_PIN_IO_PU_PD(259),
+	R8A73A4_PIN_IO_PU_PD(260), R8A73A4_PIN_IO_PU_PD(261),
+	R8A73A4_PIN_IO_PU_PD(262), R8A73A4_PIN_IO_PU_PD(263),
+	R8A73A4_PIN_IO_PU_PD(264), R8A73A4_PIN_IO_PU_PD(265),
+	R8A73A4_PIN_IO_PU_PD(266), R8A73A4_PIN_IO_PU_PD(267),
+	R8A73A4_PIN_IO_PU_PD(268), R8A73A4_PIN_IO_PU_PD(269),
+	R8A73A4_PIN_IO_PU_PD(270), R8A73A4_PIN_IO_PU_PD(271),
+	R8A73A4_PIN_IO_PU_PD(272), R8A73A4_PIN_IO_PU_PD(273),
+	R8A73A4_PIN_IO_PU_PD(274), R8A73A4_PIN_IO_PU_PD(275),
+	R8A73A4_PIN_IO_PU_PD(276), R8A73A4_PIN_IO_PU_PD(277),
+	R8A73A4_PIN_IO_PU_PD(278), R8A73A4_PIN_IO_PU_PD(279),
+	R8A73A4_PIN_IO_PU_PD(280), R8A73A4_PIN_IO_PU_PD(281),
+	R8A73A4_PIN_IO_PU_PD(282), R8A73A4_PIN_IO_PU_PD(283),
+	R8A73A4_PIN_O(288), R8A73A4_PIN_IO_PU_PD(289),
+	R8A73A4_PIN_IO_PU_PD(290), R8A73A4_PIN_IO_PU_PD(291),
+	R8A73A4_PIN_IO_PU_PD(292), R8A73A4_PIN_IO_PU_PD(293),
+	R8A73A4_PIN_IO_PU_PD(294), R8A73A4_PIN_IO_PU_PD(295),
+	R8A73A4_PIN_IO_PU_PD(296), R8A73A4_PIN_IO_PU_PD(297),
+	R8A73A4_PIN_IO_PU_PD(298), R8A73A4_PIN_IO_PU_PD(299),
+	R8A73A4_PIN_IO_PU_PD(300), R8A73A4_PIN_IO_PU_PD(301),
+	R8A73A4_PIN_IO_PU_PD(302), R8A73A4_PIN_IO_PU_PD(303),
+	R8A73A4_PIN_IO_PU_PD(304), R8A73A4_PIN_IO_PU_PD(305),
+	R8A73A4_PIN_IO_PU_PD(306), R8A73A4_PIN_IO_PU_PD(307),
+	R8A73A4_PIN_IO_PU_PD(308),
+	R8A73A4_PIN_IO_PU_PD(320), R8A73A4_PIN_IO_PU_PD(321),
+	R8A73A4_PIN_IO_PU_PD(322), R8A73A4_PIN_IO_PU_PD(323),
+	R8A73A4_PIN_IO_PU_PD(324), R8A73A4_PIN_IO_PU_PD(325),
+	R8A73A4_PIN_IO_PU_PD(326), R8A73A4_PIN_IO_PU_PD(327),
+	R8A73A4_PIN_IO_PU_PD(328), R8A73A4_PIN_IO_PU_PD(329),
+};
+
+static const struct pinmux_range pinmux_ranges[] = {
+	{.begin = 0, .end = 30,},
+	{.begin = 32, .end = 40,},
+	{.begin = 64, .end = 85,},
+	{.begin = 96, .end = 126,},
+	{.begin = 128, .end = 134,},
+	{.begin = 160, .end = 178,},
+	{.begin = 192, .end = 222,},
+	{.begin = 224, .end = 250,},
+	{.begin = 256, .end = 283,},
+	{.begin = 288, .end = 308,},
+	{.begin = 320, .end = 329,},
+};
+
+/* - IRQC ------------------------------------------------------------------- */
+#define IRQC_PINS_MUX(pin, irq_mark)				\
+static const unsigned int irqc_irq##irq_mark##_pins[] = {	\
+	pin,							\
+};								\
+static const unsigned int irqc_irq##irq_mark##_mux[] = {	\
+	IRQ##irq_mark##_MARK,					\
+}
+IRQC_PINS_MUX(0, 0);
+IRQC_PINS_MUX(1, 1);
+IRQC_PINS_MUX(2, 2);
+IRQC_PINS_MUX(3, 3);
+IRQC_PINS_MUX(4, 4);
+IRQC_PINS_MUX(5, 5);
+IRQC_PINS_MUX(6, 6);
+IRQC_PINS_MUX(7, 7);
+IRQC_PINS_MUX(8, 8);
+IRQC_PINS_MUX(9, 9);
+IRQC_PINS_MUX(10, 10);
+IRQC_PINS_MUX(11, 11);
+IRQC_PINS_MUX(12, 12);
+IRQC_PINS_MUX(13, 13);
+IRQC_PINS_MUX(14, 14);
+IRQC_PINS_MUX(15, 15);
+IRQC_PINS_MUX(66, 40);
+IRQC_PINS_MUX(84, 19);
+IRQC_PINS_MUX(85, 18);
+IRQC_PINS_MUX(102, 41);
+IRQC_PINS_MUX(103, 42);
+IRQC_PINS_MUX(109, 43);
+IRQC_PINS_MUX(110, 44);
+IRQC_PINS_MUX(111, 45);
+IRQC_PINS_MUX(112, 46);
+IRQC_PINS_MUX(113, 47);
+IRQC_PINS_MUX(114, 48);
+IRQC_PINS_MUX(115, 49);
+IRQC_PINS_MUX(160, 20);
+IRQC_PINS_MUX(161, 21);
+IRQC_PINS_MUX(162, 22);
+IRQC_PINS_MUX(163, 23);
+IRQC_PINS_MUX(175, 24);
+IRQC_PINS_MUX(176, 25);
+IRQC_PINS_MUX(177, 26);
+IRQC_PINS_MUX(178, 27);
+IRQC_PINS_MUX(192, 31);
+IRQC_PINS_MUX(193, 32);
+IRQC_PINS_MUX(194, 33);
+IRQC_PINS_MUX(195, 34);
+IRQC_PINS_MUX(196, 35);
+IRQC_PINS_MUX(197, 36);
+IRQC_PINS_MUX(198, 37);
+IRQC_PINS_MUX(199, 38);
+IRQC_PINS_MUX(200, 39);
+IRQC_PINS_MUX(290, 51);
+IRQC_PINS_MUX(296, 52);
+IRQC_PINS_MUX(301, 50);
+IRQC_PINS_MUX(320, 16);
+IRQC_PINS_MUX(321, 17);
+IRQC_PINS_MUX(322, 28);
+IRQC_PINS_MUX(323, 29);
+IRQC_PINS_MUX(324, 30);
+IRQC_PINS_MUX(325, 53);
+IRQC_PINS_MUX(326, 54);
+IRQC_PINS_MUX(327, 55);
+IRQC_PINS_MUX(328, 56);
+IRQC_PINS_MUX(329, 57);
+/* - SCIFA0 ----------------------------------------------------------------- */
+static const unsigned int scifa0_data_pins[] = {
+	/* SCIFA0_RXD, SCIFA0_TXD */
+	117, 116,
+};
+static const unsigned int scifa0_data_mux[] = {
+	SCIFA0_RXD_MARK, SCIFA0_TXD_MARK,
+};
+static const unsigned int scifa0_clk_pins[] = {
+	/* SCIFA0_SCK */
+	34,
+};
+static const unsigned int scifa0_clk_mux[] = {
+	SCIFA0_SCK_MARK,
+};
+static const unsigned int scifa0_ctrl_pins[] = {
+	/* SCIFA0_RTS, SCIFA0_CTS */
+	32, 33,
+};
+static const unsigned int scifa0_ctrl_mux[] = {
+	SCIFA0_RTS_MARK, SCIFA0_CTS_MARK,
+};
+/* - SCIFA1 ----------------------------------------------------------------- */
+static const unsigned int scifa1_data_pins[] = {
+	/* SCIFA1_RXD, SCIFA1_TXD */
+	119, 118,
+};
+static const unsigned int scifa1_data_mux[] = {
+	SCIFA1_RXD_MARK, SCIFA1_TXD_MARK,
+};
+static const unsigned int scifa1_clk_pins[] = {
+	/* SCIFA1_SCK */
+	37,
+};
+static const unsigned int scifa1_clk_mux[] = {
+	SCIFA1_SCK_MARK,
+};
+static const unsigned int scifa1_ctrl_pins[] = {
+	/* SCIFA1_RTS, SCIFA1_CTS */
+	35, 36,
+};
+static const unsigned int scifa1_ctrl_mux[] = {
+	SCIFA1_RTS_MARK, SCIFA1_CTS_MARK,
+};
+/* - SCIFB0 ----------------------------------------------------------------- */
+static const unsigned int scifb0_data_pins[] = {
+	/* SCIFB0_RXD, SCIFB0_TXD */
+	123, 122,
+};
+static const unsigned int scifb0_data_mux[] = {
+	SCIFB0_RXD_MARK, SCIFB0_TXD_MARK,
+};
+static const unsigned int scifb0_clk_pins[] = {
+	/* SCIFB0_SCK */
+	40,
+};
+static const unsigned int scifb0_clk_mux[] = {
+	SCIFB0_SCK_MARK,
+};
+static const unsigned int scifb0_ctrl_pins[] = {
+	/* SCIFB0_RTS, SCIFB0_CTS */
+	38, 39,
+};
+static const unsigned int scifb0_ctrl_mux[] = {
+	SCIFB0_RTS_MARK, SCIFB0_CTS_MARK,
+};
+/* - SCIFB1 ----------------------------------------------------------------- */
+static const unsigned int scifb1_data_pins[] = {
+	/* SCIFB1_RXD, SCIFB1_TXD */
+	27, 26,
+};
+static const unsigned int scifb1_data_mux[] = {
+	SCIFB1_RXD_27_MARK, SCIFB1_TXD_26_MARK,
+};
+static const unsigned int scifb1_clk_pins[] = {
+	/* SCIFB1_SCK */
+	28,
+};
+static const unsigned int scifb1_clk_mux[] = {
+	SCIFB1_SCK_28_MARK,
+};
+static const unsigned int scifb1_ctrl_pins[] = {
+	/* SCIFB1_RTS, SCIFB1_CTS */
+	24, 25,
+};
+static const unsigned int scifb1_ctrl_mux[] = {
+	SCIFB1_RTS_24_MARK, SCIFB1_CTS_25_MARK,
+};
+static const unsigned int scifb1_data_b_pins[] = {
+	/* SCIFB1_RXD, SCIFB1_TXD */
+	72, 67,
+};
+static const unsigned int scifb1_data_b_mux[] = {
+	SCIFB1_RXD_72_MARK, SCIFB1_TXD_67_MARK,
+};
+static const unsigned int scifb1_clk_b_pins[] = {
+	/* SCIFB1_SCK */
+	261,
+};
+static const unsigned int scifb1_clk_b_mux[] = {
+	SCIFB1_SCK_261_MARK,
+};
+static const unsigned int scifb1_ctrl_b_pins[] = {
+	/* SCIFB1_RTS, SCIFB1_CTS */
+	70, 71,
+};
+static const unsigned int scifb1_ctrl_b_mux[] = {
+	SCIFB1_RTS_70_MARK, SCIFB1_CTS_71_MARK,
+};
+/* - SCIFB2 ----------------------------------------------------------------- */
+static const unsigned int scifb2_data_pins[] = {
+	/* SCIFB2_RXD, SCIFB2_TXD */
+	69, 68,
+};
+static const unsigned int scifb2_data_mux[] = {
+	SCIFB2_RXD_69_MARK, SCIFB2_TXD_68_MARK,
+};
+static const unsigned int scifb2_clk_pins[] = {
+	/* SCIFB2_SCK */
+	262,
+};
+static const unsigned int scifb2_clk_mux[] = {
+	SCIFB2_SCK_262_MARK,
+};
+static const unsigned int scifb2_ctrl_pins[] = {
+	/* SCIFB2_RTS, SCIFB2_CTS */
+	73, 66,
+};
+static const unsigned int scifb2_ctrl_mux[] = {
+	SCIFB2_RTS_73_MARK, SCIFB2_CTS_66_MARK,
+};
+static const unsigned int scifb2_data_b_pins[] = {
+	/* SCIFB2_RXD, SCIFB2_TXD */
+	297, 295,
+};
+static const unsigned int scifb2_data_b_mux[] = {
+	SCIFB2_RXD_297_MARK, SCIFB2_TXD_295_MARK,
+};
+static const unsigned int scifb2_clk_b_pins[] = {
+	/* SCIFB2_SCK */
+	299,
+};
+static const unsigned int scifb2_clk_b_mux[] = {
+	SCIFB2_SCK_299_MARK,
+};
+static const unsigned int scifb2_ctrl_b_pins[] = {
+	/* SCIFB2_RTS, SCIFB2_CTS */
+	300, 298,
+};
+static const unsigned int scifb2_ctrl_b_mux[] = {
+	SCIFB2_RTS_300_MARK, SCIFB2_CTS_298_MARK,
+};
+/* - SCIFB3 ----------------------------------------------------------------- */
+static const unsigned int scifb3_data_pins[] = {
+	/* SCIFB3_RXD, SCIFB3_TXD */
+	22, 21,
+};
+static const unsigned int scifb3_data_mux[] = {
+	SCIFB3_RXD_22_MARK, SCIFB3_TXD_21_MARK,
+};
+static const unsigned int scifb3_clk_pins[] = {
+	/* SCIFB3_SCK */
+	23,
+};
+static const unsigned int scifb3_clk_mux[] = {
+	SCIFB3_SCK_23_MARK,
+};
+static const unsigned int scifb3_ctrl_pins[] = {
+	/* SCIFB3_RTS, SCIFB3_CTS */
+	19, 20,
+};
+static const unsigned int scifb3_ctrl_mux[] = {
+	SCIFB3_RTS_19_MARK, SCIFB3_CTS_20_MARK,
+};
+static const unsigned int scifb3_data_b_pins[] = {
+	/* SCIFB3_RXD, SCIFB3_TXD */
+	120, 121,
+};
+static const unsigned int scifb3_data_b_mux[] = {
+	SCIFB3_RXD_120_MARK, SCIFB3_TXD_121_MARK,
+};
+static const unsigned int scifb3_clk_b_pins[] = {
+	/* SCIFB3_SCK */
+	40,
+};
+static const unsigned int scifb3_clk_b_mux[] = {
+	SCIFB3_SCK_40_MARK,
+};
+static const unsigned int scifb3_ctrl_b_pins[] = {
+	/* SCIFB3_RTS, SCIFB3_CTS */
+	38, 39,
+};
+static const unsigned int scifb3_ctrl_b_mux[] = {
+	SCIFB3_RTS_38_MARK, SCIFB3_CTS_39_MARK,
+};
+
+static const struct sh_pfc_pin_group pinmux_groups[] = {
+	SH_PFC_PIN_GROUP(irqc_irq0),
+	SH_PFC_PIN_GROUP(irqc_irq1),
+	SH_PFC_PIN_GROUP(irqc_irq2),
+	SH_PFC_PIN_GROUP(irqc_irq3),
+	SH_PFC_PIN_GROUP(irqc_irq4),
+	SH_PFC_PIN_GROUP(irqc_irq5),
+	SH_PFC_PIN_GROUP(irqc_irq6),
+	SH_PFC_PIN_GROUP(irqc_irq7),
+	SH_PFC_PIN_GROUP(irqc_irq8),
+	SH_PFC_PIN_GROUP(irqc_irq9),
+	SH_PFC_PIN_GROUP(irqc_irq10),
+	SH_PFC_PIN_GROUP(irqc_irq11),
+	SH_PFC_PIN_GROUP(irqc_irq12),
+	SH_PFC_PIN_GROUP(irqc_irq13),
+	SH_PFC_PIN_GROUP(irqc_irq14),
+	SH_PFC_PIN_GROUP(irqc_irq15),
+	SH_PFC_PIN_GROUP(irqc_irq16),
+	SH_PFC_PIN_GROUP(irqc_irq17),
+	SH_PFC_PIN_GROUP(irqc_irq18),
+	SH_PFC_PIN_GROUP(irqc_irq19),
+	SH_PFC_PIN_GROUP(irqc_irq20),
+	SH_PFC_PIN_GROUP(irqc_irq21),
+	SH_PFC_PIN_GROUP(irqc_irq22),
+	SH_PFC_PIN_GROUP(irqc_irq23),
+	SH_PFC_PIN_GROUP(irqc_irq24),
+	SH_PFC_PIN_GROUP(irqc_irq25),
+	SH_PFC_PIN_GROUP(irqc_irq26),
+	SH_PFC_PIN_GROUP(irqc_irq27),
+	SH_PFC_PIN_GROUP(irqc_irq28),
+	SH_PFC_PIN_GROUP(irqc_irq29),
+	SH_PFC_PIN_GROUP(irqc_irq30),
+	SH_PFC_PIN_GROUP(irqc_irq31),
+	SH_PFC_PIN_GROUP(irqc_irq32),
+	SH_PFC_PIN_GROUP(irqc_irq33),
+	SH_PFC_PIN_GROUP(irqc_irq34),
+	SH_PFC_PIN_GROUP(irqc_irq35),
+	SH_PFC_PIN_GROUP(irqc_irq36),
+	SH_PFC_PIN_GROUP(irqc_irq37),
+	SH_PFC_PIN_GROUP(irqc_irq38),
+	SH_PFC_PIN_GROUP(irqc_irq39),
+	SH_PFC_PIN_GROUP(irqc_irq40),
+	SH_PFC_PIN_GROUP(irqc_irq41),
+	SH_PFC_PIN_GROUP(irqc_irq42),
+	SH_PFC_PIN_GROUP(irqc_irq43),
+	SH_PFC_PIN_GROUP(irqc_irq44),
+	SH_PFC_PIN_GROUP(irqc_irq45),
+	SH_PFC_PIN_GROUP(irqc_irq46),
+	SH_PFC_PIN_GROUP(irqc_irq47),
+	SH_PFC_PIN_GROUP(irqc_irq48),
+	SH_PFC_PIN_GROUP(irqc_irq49),
+	SH_PFC_PIN_GROUP(irqc_irq50),
+	SH_PFC_PIN_GROUP(irqc_irq51),
+	SH_PFC_PIN_GROUP(irqc_irq52),
+	SH_PFC_PIN_GROUP(irqc_irq53),
+	SH_PFC_PIN_GROUP(irqc_irq54),
+	SH_PFC_PIN_GROUP(irqc_irq55),
+	SH_PFC_PIN_GROUP(irqc_irq56),
+	SH_PFC_PIN_GROUP(irqc_irq57),
+	SH_PFC_PIN_GROUP(scifa0_data),
+	SH_PFC_PIN_GROUP(scifa0_clk),
+	SH_PFC_PIN_GROUP(scifa0_ctrl),
+	SH_PFC_PIN_GROUP(scifa1_data),
+	SH_PFC_PIN_GROUP(scifa1_clk),
+	SH_PFC_PIN_GROUP(scifa1_ctrl),
+	SH_PFC_PIN_GROUP(scifb0_data),
+	SH_PFC_PIN_GROUP(scifb0_clk),
+	SH_PFC_PIN_GROUP(scifb0_ctrl),
+	SH_PFC_PIN_GROUP(scifb1_data),
+	SH_PFC_PIN_GROUP(scifb1_clk),
+	SH_PFC_PIN_GROUP(scifb1_ctrl),
+	SH_PFC_PIN_GROUP(scifb1_data_b),
+	SH_PFC_PIN_GROUP(scifb1_clk_b),
+	SH_PFC_PIN_GROUP(scifb1_ctrl_b),
+	SH_PFC_PIN_GROUP(scifb2_data),
+	SH_PFC_PIN_GROUP(scifb2_clk),
+	SH_PFC_PIN_GROUP(scifb2_ctrl),
+	SH_PFC_PIN_GROUP(scifb2_data_b),
+	SH_PFC_PIN_GROUP(scifb2_clk_b),
+	SH_PFC_PIN_GROUP(scifb2_ctrl_b),
+	SH_PFC_PIN_GROUP(scifb3_data),
+	SH_PFC_PIN_GROUP(scifb3_clk),
+	SH_PFC_PIN_GROUP(scifb3_ctrl),
+	SH_PFC_PIN_GROUP(scifb3_data_b),
+	SH_PFC_PIN_GROUP(scifb3_clk_b),
+	SH_PFC_PIN_GROUP(scifb3_ctrl_b),
+};
+
+static const char * const irqc_groups[] = {
+	"irqc_irq0",
+	"irqc_irq1",
+	"irqc_irq2",
+	"irqc_irq3",
+	"irqc_irq4",
+	"irqc_irq5",
+	"irqc_irq6",
+	"irqc_irq7",
+	"irqc_irq8",
+	"irqc_irq9",
+	"irqc_irq10",
+	"irqc_irq11",
+	"irqc_irq12",
+	"irqc_irq13",
+	"irqc_irq14",
+	"irqc_irq15",
+	"irqc_irq16",
+	"irqc_irq17",
+	"irqc_irq18",
+	"irqc_irq19",
+	"irqc_irq20",
+	"irqc_irq21",
+	"irqc_irq22",
+	"irqc_irq23",
+	"irqc_irq24",
+	"irqc_irq25",
+	"irqc_irq26",
+	"irqc_irq27",
+	"irqc_irq28",
+	"irqc_irq29",
+	"irqc_irq30",
+	"irqc_irq31",
+	"irqc_irq32",
+	"irqc_irq33",
+	"irqc_irq34",
+	"irqc_irq35",
+	"irqc_irq36",
+	"irqc_irq37",
+	"irqc_irq38",
+	"irqc_irq39",
+	"irqc_irq40",
+	"irqc_irq41",
+	"irqc_irq42",
+	"irqc_irq43",
+	"irqc_irq44",
+	"irqc_irq45",
+	"irqc_irq46",
+	"irqc_irq47",
+	"irqc_irq48",
+	"irqc_irq49",
+	"irqc_irq50",
+	"irqc_irq51",
+	"irqc_irq52",
+	"irqc_irq53",
+	"irqc_irq54",
+	"irqc_irq55",
+	"irqc_irq56",
+	"irqc_irq57",
+};
+
+static const char * const scifa0_groups[] = {
+	"scifa0_data",
+	"scifa0_clk",
+	"scifa0_ctrl",
+};
+
+static const char * const scifa1_groups[] = {
+	"scifa1_data",
+	"scifa1_clk",
+	"scifa1_ctrl",
+};
+
+static const char * const scifb0_groups[] = {
+	"scifb0_data",
+	"scifb0_clk",
+	"scifb0_ctrl",
+};
+
+static const char * const scifb1_groups[] = {
+	"scifb1_data",
+	"scifb1_clk",
+	"scifb1_ctrl",
+	"scifb1_data_b",
+	"scifb1_clk_b",
+	"scifb1_ctrl_b",
+};
+
+static const char * const scifb2_groups[] = {
+	"scifb2_data",
+	"scifb2_clk",
+	"scifb2_ctrl",
+	"scifb2_data_b",
+	"scifb2_clk_b",
+	"scifb2_ctrl_b",
+};
+
+static const char * const scifb3_groups[] = {
+	"scifb3_data",
+	"scifb3_clk",
+	"scifb3_ctrl",
+	"scifb3_data_b",
+	"scifb3_clk_b",
+	"scifb3_ctrl_b",
+};
+
+static const struct sh_pfc_function pinmux_functions[] = {
+	SH_PFC_FUNCTION(irqc),
+	SH_PFC_FUNCTION(scifa0),
+	SH_PFC_FUNCTION(scifa1),
+	SH_PFC_FUNCTION(scifb0),
+	SH_PFC_FUNCTION(scifb1),
+	SH_PFC_FUNCTION(scifb2),
+	SH_PFC_FUNCTION(scifb3),
+};
+
+#undef PORTCR
+#define PORTCR(nr, reg)							\
+	{								\
+		PINMUX_CFG_REG("PORT" nr "CR", reg, 8, 4) {		\
+			_PCRH(PORT##nr##_IN, 0, 0, PORT##nr##_OUT),	\
+				PORT##nr##_FN0, PORT##nr##_FN1,		\
+				PORT##nr##_FN2, PORT##nr##_FN3,		\
+				PORT##nr##_FN4, PORT##nr##_FN5,		\
+				PORT##nr##_FN6, PORT##nr##_FN7 }	\
+	}
+
+static const struct pinmux_cfg_reg pinmux_config_regs[] = {
+	PORTCR(0, 0xe6050000),
+	PORTCR(1, 0xe6050001),
+	PORTCR(2, 0xe6050002),
+	PORTCR(3, 0xe6050003),
+	PORTCR(4, 0xe6050004),
+	PORTCR(5, 0xe6050005),
+	PORTCR(6, 0xe6050006),
+	PORTCR(7, 0xe6050007),
+	PORTCR(8, 0xe6050008),
+	PORTCR(9, 0xe6050009),
+	PORTCR(10, 0xe605000A),
+	PORTCR(11, 0xe605000B),
+	PORTCR(12, 0xe605000C),
+	PORTCR(13, 0xe605000D),
+	PORTCR(14, 0xe605000E),
+	PORTCR(15, 0xe605000F),
+	PORTCR(16, 0xe6050010),
+	PORTCR(17, 0xe6050011),
+	PORTCR(18, 0xe6050012),
+	PORTCR(19, 0xe6050013),
+	PORTCR(20, 0xe6050014),
+	PORTCR(21, 0xe6050015),
+	PORTCR(22, 0xe6050016),
+	PORTCR(23, 0xe6050017),
+	PORTCR(24, 0xe6050018),
+	PORTCR(25, 0xe6050019),
+	PORTCR(26, 0xe605001A),
+	PORTCR(27, 0xe605001B),
+	PORTCR(28, 0xe605001C),
+	PORTCR(29, 0xe605001D),
+	PORTCR(30, 0xe605001E),
+	PORTCR(32, 0xe6051020),
+	PORTCR(33, 0xe6051021),
+	PORTCR(34, 0xe6051022),
+	PORTCR(35, 0xe6051023),
+	PORTCR(36, 0xe6051024),
+	PORTCR(37, 0xe6051025),
+	PORTCR(38, 0xe6051026),
+	PORTCR(39, 0xe6051027),
+	PORTCR(40, 0xe6051028),
+	PORTCR(64, 0xe6050040),
+	PORTCR(65, 0xe6050041),
+	PORTCR(66, 0xe6050042),
+	PORTCR(67, 0xe6050043),
+	PORTCR(68, 0xe6050044),
+	PORTCR(69, 0xe6050045),
+	PORTCR(70, 0xe6050046),
+	PORTCR(71, 0xe6050047),
+	PORTCR(72, 0xe6050048),
+	PORTCR(73, 0xe6050049),
+	PORTCR(74, 0xe605004A),
+	PORTCR(75, 0xe605004B),
+	PORTCR(76, 0xe605004C),
+	PORTCR(77, 0xe605004D),
+	PORTCR(78, 0xe605004E),
+	PORTCR(79, 0xe605004F),
+	PORTCR(80, 0xe6050050),
+	PORTCR(81, 0xe6050051),
+	PORTCR(82, 0xe6050052),
+	PORTCR(83, 0xe6050053),
+	PORTCR(84, 0xe6050054),
+	PORTCR(85, 0xe6050055),
+	PORTCR(96, 0xe6051060),
+	PORTCR(97, 0xe6051061),
+	PORTCR(98, 0xe6051062),
+	PORTCR(99, 0xe6051063),
+	PORTCR(100, 0xe6051064),
+	PORTCR(101, 0xe6051065),
+	PORTCR(102, 0xe6051066),
+	PORTCR(103, 0xe6051067),
+	PORTCR(104, 0xe6051068),
+	PORTCR(105, 0xe6051069),
+	PORTCR(106, 0xe605106A),
+	PORTCR(107, 0xe605106B),
+	PORTCR(108, 0xe605106C),
+	PORTCR(109, 0xe605106D),
+	PORTCR(110, 0xe605106E),
+	PORTCR(111, 0xe605106F),
+	PORTCR(112, 0xe6051070),
+	PORTCR(113, 0xe6051071),
+	PORTCR(114, 0xe6051072),
+	PORTCR(115, 0xe6051073),
+	PORTCR(116, 0xe6051074),
+	PORTCR(117, 0xe6051075),
+	PORTCR(118, 0xe6051076),
+	PORTCR(119, 0xe6051077),
+	PORTCR(120, 0xe6051078),
+	PORTCR(121, 0xe6051079),
+	PORTCR(122, 0xe605107A),
+	PORTCR(123, 0xe605107B),
+	PORTCR(124, 0xe605107C),
+	PORTCR(125, 0xe605107D),
+	PORTCR(126, 0xe605107E),
+	PORTCR(128, 0xe6051080),
+	PORTCR(129, 0xe6051081),
+	PORTCR(130, 0xe6051082),
+	PORTCR(131, 0xe6051083),
+	PORTCR(132, 0xe6051084),
+	PORTCR(133, 0xe6051085),
+	PORTCR(134, 0xe6051086),
+	PORTCR(160, 0xe60520A0),
+	PORTCR(161, 0xe60520A1),
+	PORTCR(162, 0xe60520A2),
+	PORTCR(163, 0xe60520A3),
+	PORTCR(164, 0xe60520A4),
+	PORTCR(165, 0xe60520A5),
+	PORTCR(166, 0xe60520A6),
+	PORTCR(167, 0xe60520A7),
+	PORTCR(168, 0xe60520A8),
+	PORTCR(169, 0xe60520A9),
+	PORTCR(170, 0xe60520AA),
+	PORTCR(171, 0xe60520AB),
+	PORTCR(172, 0xe60520AC),
+	PORTCR(173, 0xe60520AD),
+	PORTCR(174, 0xe60520AE),
+	PORTCR(175, 0xe60520AF),
+	PORTCR(176, 0xe60520B0),
+	PORTCR(177, 0xe60520B1),
+	PORTCR(178, 0xe60520B2),
+	PORTCR(192, 0xe60520C0),
+	PORTCR(193, 0xe60520C1),
+	PORTCR(194, 0xe60520C2),
+	PORTCR(195, 0xe60520C3),
+	PORTCR(196, 0xe60520C4),
+	PORTCR(197, 0xe60520C5),
+	PORTCR(198, 0xe60520C6),
+	PORTCR(199, 0xe60520C7),
+	PORTCR(200, 0xe60520C8),
+	PORTCR(201, 0xe60520C9),
+	PORTCR(202, 0xe60520CA),
+	PORTCR(203, 0xe60520CB),
+	PORTCR(204, 0xe60520CC),
+	PORTCR(205, 0xe60520CD),
+	PORTCR(206, 0xe60520CE),
+	PORTCR(207, 0xe60520CF),
+	PORTCR(208, 0xe60520D0),
+	PORTCR(209, 0xe60520D1),
+	PORTCR(210, 0xe60520D2),
+	PORTCR(211, 0xe60520D3),
+	PORTCR(212, 0xe60520D4),
+	PORTCR(213, 0xe60520D5),
+	PORTCR(214, 0xe60520D6),
+	PORTCR(215, 0xe60520D7),
+	PORTCR(216, 0xe60520D8),
+	PORTCR(217, 0xe60520D9),
+	PORTCR(218, 0xe60520DA),
+	PORTCR(219, 0xe60520DB),
+	PORTCR(220, 0xe60520DC),
+	PORTCR(221, 0xe60520DD),
+	PORTCR(222, 0xe60520DE),
+	PORTCR(224, 0xe60520E0),
+	PORTCR(225, 0xe60520E1),
+	PORTCR(226, 0xe60520E2),
+	PORTCR(227, 0xe60520E3),
+	PORTCR(228, 0xe60520E4),
+	PORTCR(229, 0xe60520E5),
+	PORTCR(230, 0xe60520e6),
+	PORTCR(231, 0xe60520E7),
+	PORTCR(232, 0xe60520E8),
+	PORTCR(233, 0xe60520E9),
+	PORTCR(234, 0xe60520EA),
+	PORTCR(235, 0xe60520EB),
+	PORTCR(236, 0xe60520EC),
+	PORTCR(237, 0xe60520ED),
+	PORTCR(238, 0xe60520EE),
+	PORTCR(239, 0xe60520EF),
+	PORTCR(240, 0xe60520F0),
+	PORTCR(241, 0xe60520F1),
+	PORTCR(242, 0xe60520F2),
+	PORTCR(243, 0xe60520F3),
+	PORTCR(244, 0xe60520F4),
+	PORTCR(245, 0xe60520F5),
+	PORTCR(246, 0xe60520F6),
+	PORTCR(247, 0xe60520F7),
+	PORTCR(248, 0xe60520F8),
+	PORTCR(249, 0xe60520F9),
+	PORTCR(250, 0xe60520FA),
+	PORTCR(256, 0xe6052100),
+	PORTCR(257, 0xe6052101),
+	PORTCR(258, 0xe6052102),
+	PORTCR(259, 0xe6052103),
+	PORTCR(260, 0xe6052104),
+	PORTCR(261, 0xe6052105),
+	PORTCR(262, 0xe6052106),
+	PORTCR(263, 0xe6052107),
+	PORTCR(264, 0xe6052108),
+	PORTCR(265, 0xe6052109),
+	PORTCR(266, 0xe605210A),
+	PORTCR(267, 0xe605210B),
+	PORTCR(268, 0xe605210C),
+	PORTCR(269, 0xe605210D),
+	PORTCR(270, 0xe605210E),
+	PORTCR(271, 0xe605210F),
+	PORTCR(272, 0xe6052110),
+	PORTCR(273, 0xe6052111),
+	PORTCR(274, 0xe6052112),
+	PORTCR(275, 0xe6052113),
+	PORTCR(276, 0xe6052114),
+	PORTCR(277, 0xe6052115),
+	PORTCR(278, 0xe6052116),
+	PORTCR(279, 0xe6052117),
+	PORTCR(280, 0xe6052118),
+	PORTCR(281, 0xe6052119),
+	PORTCR(282, 0xe605211A),
+	PORTCR(283, 0xe605211B),
+	PORTCR(288, 0xe6053120),
+	PORTCR(289, 0xe6053121),
+	PORTCR(290, 0xe6053122),
+	PORTCR(291, 0xe6053123),
+	PORTCR(292, 0xe6053124),
+	PORTCR(293, 0xe6053125),
+	PORTCR(294, 0xe6053126),
+	PORTCR(295, 0xe6053127),
+	PORTCR(296, 0xe6053128),
+	PORTCR(297, 0xe6053129),
+	PORTCR(298, 0xe605312A),
+	PORTCR(299, 0xe605312B),
+	PORTCR(300, 0xe605312C),
+	PORTCR(301, 0xe605312D),
+	PORTCR(302, 0xe605312E),
+	PORTCR(303, 0xe605312F),
+	PORTCR(304, 0xe6053130),
+	PORTCR(305, 0xe6053131),
+	PORTCR(306, 0xe6053132),
+	PORTCR(307, 0xe6053133),
+	PORTCR(308, 0xe6053134),
+	PORTCR(320, 0xe6053140),
+	PORTCR(321, 0xe6053141),
+	PORTCR(322, 0xe6053142),
+	PORTCR(323, 0xe6053143),
+	PORTCR(324, 0xe6053144),
+	PORTCR(325, 0xe6053145),
+	PORTCR(326, 0xe6053146),
+	PORTCR(327, 0xe6053147),
+	PORTCR(328, 0xe6053148),
+	PORTCR(329, 0xe6053149),
+
+	{ PINMUX_CFG_REG("MSEL1CR", 0xe605800c, 32, 1) {
+			MSEL1CR_31_0, MSEL1CR_31_1,
+			0, 0,
+			0, 0,
+			0, 0,
+			MSEL1CR_27_0, MSEL1CR_27_1,
+			0, 0,
+			MSEL1CR_25_0, MSEL1CR_25_1,
+			MSEL1CR_24_0, MSEL1CR_24_1,
+			0, 0,
+			MSEL1CR_22_0, MSEL1CR_22_1,
+			MSEL1CR_21_0, MSEL1CR_21_1,
+			MSEL1CR_20_0, MSEL1CR_20_1,
+			MSEL1CR_19_0, MSEL1CR_19_1,
+			MSEL1CR_18_0, MSEL1CR_18_1,
+			MSEL1CR_17_0, MSEL1CR_17_1,
+			MSEL1CR_16_0, MSEL1CR_16_1,
+			MSEL1CR_15_0, MSEL1CR_15_1,
+			MSEL1CR_14_0, MSEL1CR_14_1,
+			MSEL1CR_13_0, MSEL1CR_13_1,
+			MSEL1CR_12_0, MSEL1CR_12_1,
+			MSEL1CR_11_0, MSEL1CR_11_1,
+			MSEL1CR_10_0, MSEL1CR_10_1,
+			MSEL1CR_09_0, MSEL1CR_09_1,
+			MSEL1CR_08_0, MSEL1CR_08_1,
+			MSEL1CR_07_0, MSEL1CR_07_1,
+			MSEL1CR_06_0, MSEL1CR_06_1,
+			MSEL1CR_05_0, MSEL1CR_05_1,
+			MSEL1CR_04_0, MSEL1CR_04_1,
+			MSEL1CR_03_0, MSEL1CR_03_1,
+			MSEL1CR_02_0, MSEL1CR_02_1,
+			MSEL1CR_01_0, MSEL1CR_01_1,
+			MSEL1CR_00_0, MSEL1CR_00_1,
+		}
+	},
+	{ PINMUX_CFG_REG("MSEL3CR", 0xe6058020, 32, 1) {
+			MSEL3CR_31_0, MSEL3CR_31_1,
+			0, 0,
+			0, 0,
+			MSEL3CR_28_0, MSEL3CR_28_1,
+			MSEL3CR_27_0, MSEL3CR_27_1,
+			MSEL3CR_26_0, MSEL3CR_26_1,
+			0, 0,
+			0, 0,
+			MSEL3CR_23_0, MSEL3CR_23_1,
+			MSEL3CR_22_0, MSEL3CR_22_1,
+			MSEL3CR_21_0, MSEL3CR_21_1,
+			MSEL3CR_20_0, MSEL3CR_20_1,
+			MSEL3CR_19_0, MSEL3CR_19_1,
+			MSEL3CR_18_0, MSEL3CR_18_1,
+			MSEL3CR_17_0, MSEL3CR_17_1,
+			MSEL3CR_16_0, MSEL3CR_16_1,
+			MSEL3CR_15_0, MSEL3CR_15_1,
+			0, 0,
+			0, 0,
+			MSEL3CR_12_0, MSEL3CR_12_1,
+			MSEL3CR_11_0, MSEL3CR_11_1,
+			MSEL3CR_10_0, MSEL3CR_10_1,
+			MSEL3CR_09_0, MSEL3CR_09_1,
+			0, 0,
+			0, 0,
+			MSEL3CR_06_0, MSEL3CR_06_1,
+			0, 0,
+			0, 0,
+			MSEL3CR_03_0, MSEL3CR_03_1,
+			0, 0,
+			MSEL3CR_01_0, MSEL3CR_01_1,
+			MSEL3CR_00_0, MSEL3CR_00_1,
+			}
+	},
+	{ PINMUX_CFG_REG("MSEL4CR", 0xe6058024, 32, 1) {
+			0, 0,
+			MSEL4CR_30_0, MSEL4CR_30_1,
+			MSEL4CR_29_0, MSEL4CR_29_1,
+			MSEL4CR_28_0, MSEL4CR_28_1,
+			MSEL4CR_27_0, MSEL4CR_27_1,
+			MSEL4CR_26_0, MSEL4CR_26_1,
+			MSEL4CR_25_0, MSEL4CR_25_1,
+			MSEL4CR_24_0, MSEL4CR_24_1,
+			MSEL4CR_23_0, MSEL4CR_23_1,
+			MSEL4CR_22_0, MSEL4CR_22_1,
+			MSEL4CR_21_0, MSEL4CR_21_1,
+			MSEL4CR_20_0, MSEL4CR_20_1,
+			MSEL4CR_19_0, MSEL4CR_19_1,
+			MSEL4CR_18_0, MSEL4CR_18_1,
+			MSEL4CR_17_0, MSEL4CR_17_1,
+			MSEL4CR_16_0, MSEL4CR_16_1,
+			MSEL4CR_15_0, MSEL4CR_15_1,
+			MSEL4CR_14_0, MSEL4CR_14_1,
+			MSEL4CR_13_0, MSEL4CR_13_1,
+			MSEL4CR_12_0, MSEL4CR_12_1,
+			MSEL4CR_11_0, MSEL4CR_11_1,
+			MSEL4CR_10_0, MSEL4CR_10_1,
+			MSEL4CR_09_0, MSEL4CR_09_1,
+			0, 0,
+			MSEL4CR_07_0, MSEL4CR_07_1,
+			0, 0,
+			0, 0,
+			MSEL4CR_04_0, MSEL4CR_04_1,
+			0, 0,
+			0, 0,
+			MSEL4CR_01_0, MSEL4CR_01_1,
+			0, 0,
+		}
+	},
+	{ PINMUX_CFG_REG("MSEL5CR", 0xe6058028, 32, 1) {
+			MSEL5CR_31_0, MSEL5CR_31_1,
+			MSEL5CR_30_0, MSEL5CR_30_1,
+			MSEL5CR_29_0, MSEL5CR_29_1,
+			MSEL5CR_28_0, MSEL5CR_28_1,
+			MSEL5CR_27_0, MSEL5CR_27_1,
+			MSEL5CR_26_0, MSEL5CR_26_1,
+			MSEL5CR_25_0, MSEL5CR_25_1,
+			MSEL5CR_24_0, MSEL5CR_24_1,
+			MSEL5CR_23_0, MSEL5CR_23_1,
+			MSEL5CR_22_0, MSEL5CR_22_1,
+			MSEL5CR_21_0, MSEL5CR_21_1,
+			MSEL5CR_20_0, MSEL5CR_20_1,
+			MSEL5CR_19_0, MSEL5CR_19_1,
+			MSEL5CR_18_0, MSEL5CR_18_1,
+			MSEL5CR_17_0, MSEL5CR_17_1,
+			MSEL5CR_16_0, MSEL5CR_16_1,
+			MSEL5CR_15_0, MSEL5CR_15_1,
+			MSEL5CR_14_0, MSEL5CR_14_1,
+			MSEL5CR_13_0, MSEL5CR_13_1,
+			MSEL5CR_12_0, MSEL5CR_12_1,
+			MSEL5CR_11_0, MSEL5CR_11_1,
+			MSEL5CR_10_0, MSEL5CR_10_1,
+			MSEL5CR_09_0, MSEL5CR_09_1,
+			MSEL5CR_08_0, MSEL5CR_08_1,
+			MSEL5CR_07_0, MSEL5CR_07_1,
+			MSEL5CR_06_0, MSEL5CR_06_1,
+			0, 0,
+			0, 0,
+			0, 0,
+			0, 0,
+			0, 0,
+			0, 0,
+		}
+	},
+	{ PINMUX_CFG_REG("MSEL8CR", 0xe6058034, 32, 1) {
+			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,
+			MSEL8CR_16_0, MSEL8CR_16_1,
+			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,
+			MSEL8CR_01_0, MSEL8CR_01_1,
+			MSEL8CR_00_0, MSEL8CR_00_1,
+		}
+	},
+	{ },
+};
+
+static const struct pinmux_data_reg pinmux_data_regs[] = {
+
+	{ PINMUX_DATA_REG("PORTL031_000DR", 0xe6054000, 32) {
+			0, PORT30_DATA, PORT29_DATA, PORT28_DATA,
+			PORT27_DATA, PORT26_DATA, PORT25_DATA, PORT24_DATA,
+			PORT23_DATA, PORT22_DATA, PORT21_DATA, PORT20_DATA,
+			PORT19_DATA, PORT18_DATA, PORT17_DATA, PORT16_DATA,
+			PORT15_DATA, PORT14_DATA, PORT13_DATA, PORT12_DATA,
+			PORT11_DATA, PORT10_DATA, PORT9_DATA, PORT8_DATA,
+			PORT7_DATA, PORT6_DATA, PORT5_DATA, PORT4_DATA,
+			PORT3_DATA, PORT2_DATA, PORT1_DATA, PORT0_DATA,
+		}
+	},
+	{ PINMUX_DATA_REG("PORTD063_032DR", 0xe6055000, 32) {
+			0, 0, 0, 0,
+			0, 0, 0, 0,
+			0, 0, 0, 0,
+			0, 0, 0, 0,
+			0, 0, 0, 0,
+			0, 0, 0, PORT40_DATA,
+			PORT39_DATA, PORT38_DATA, PORT37_DATA, PORT36_DATA,
+			PORT35_DATA, PORT34_DATA, PORT33_DATA, PORT32_DATA,
+		}
+	},
+	{ PINMUX_DATA_REG("PORTL095_064DR", 0xe6054004, 32) {
+			0, 0, 0, 0,
+			0, 0, 0, 0,
+			0, 0, PORT85_DATA, PORT84_DATA,
+			PORT83_DATA, PORT82_DATA, PORT81_DATA, PORT80_DATA,
+			PORT79_DATA, PORT78_DATA, PORT77_DATA, PORT76_DATA,
+			PORT75_DATA, PORT74_DATA, PORT73_DATA, PORT72_DATA,
+			PORT71_DATA, PORT70_DATA, PORT69_DATA, PORT68_DATA,
+			PORT67_DATA, PORT66_DATA, PORT65_DATA, PORT64_DATA,
+		}
+	},
+	{ PINMUX_DATA_REG("PORTD127_096DR", 0xe6055004, 32) {
+			0, PORT126_DATA, PORT125_DATA, PORT124_DATA,
+			PORT123_DATA, PORT122_DATA, PORT121_DATA, PORT120_DATA,
+			PORT119_DATA, PORT118_DATA, PORT117_DATA, PORT116_DATA,
+			PORT115_DATA, PORT114_DATA, PORT113_DATA, PORT112_DATA,
+			PORT111_DATA, PORT110_DATA, PORT109_DATA, PORT108_DATA,
+			PORT107_DATA, PORT106_DATA, PORT105_DATA, PORT104_DATA,
+			PORT103_DATA, PORT102_DATA, PORT101_DATA, PORT100_DATA,
+			PORT99_DATA, PORT98_DATA, PORT97_DATA, PORT96_DATA,
+		}
+	},
+	{ PINMUX_DATA_REG("PORTD159_128DR", 0xe6055008, 32) {
+			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, PORT134_DATA, PORT133_DATA, PORT132_DATA,
+			PORT131_DATA, PORT130_DATA, PORT129_DATA, PORT128_DATA,
+		}
+	},
+	{ PINMUX_DATA_REG("PORTR191_160DR", 0xe6056000, 32) {
+			0, 0, 0, 0,
+			0, 0, 0, 0,
+			0, 0, 0, 0,
+			0, PORT178_DATA, PORT177_DATA, PORT176_DATA,
+			PORT175_DATA, PORT174_DATA, PORT173_DATA, PORT172_DATA,
+			PORT171_DATA, PORT170_DATA, PORT169_DATA, PORT168_DATA,
+			PORT167_DATA, PORT166_DATA, PORT165_DATA, PORT164_DATA,
+			PORT163_DATA, PORT162_DATA, PORT161_DATA, PORT160_DATA,
+		}
+	},
+	{ PINMUX_DATA_REG("PORTR223_192DR", 0xe6056004, 32) {
+			0, PORT222_DATA, PORT221_DATA, PORT220_DATA,
+			PORT219_DATA, PORT218_DATA, PORT217_DATA, PORT216_DATA,
+			PORT215_DATA, PORT214_DATA, PORT213_DATA, PORT212_DATA,
+			PORT211_DATA, PORT210_DATA, PORT209_DATA, PORT208_DATA,
+			PORT207_DATA, PORT206_DATA, PORT205_DATA, PORT204_DATA,
+			PORT203_DATA, PORT202_DATA, PORT201_DATA, PORT200_DATA,
+			PORT199_DATA, PORT198_DATA, PORT197_DATA, PORT196_DATA,
+			PORT195_DATA, PORT194_DATA, PORT193_DATA, PORT192_DATA,
+		}
+	},
+	{ PINMUX_DATA_REG("PORTR255_224DR", 0xe6056008, 32) {
+			0, 0, 0, 0,
+			0, PORT250_DATA, PORT249_DATA, PORT248_DATA,
+			PORT247_DATA, PORT246_DATA, PORT245_DATA, PORT244_DATA,
+			PORT243_DATA, PORT242_DATA, PORT241_DATA, PORT240_DATA,
+			PORT239_DATA, PORT238_DATA, PORT237_DATA, PORT236_DATA,
+			PORT235_DATA, PORT234_DATA, PORT233_DATA, PORT232_DATA,
+			PORT231_DATA, PORT230_DATA, PORT229_DATA, PORT228_DATA,
+			PORT227_DATA, PORT226_DATA, PORT225_DATA, PORT224_DATA,
+		}
+	},
+	{ PINMUX_DATA_REG("PORTR287_256DR", 0xe605600C, 32) {
+			0, 0, 0, 0,
+			PORT283_DATA, PORT282_DATA, PORT281_DATA, PORT280_DATA,
+			PORT279_DATA, PORT278_DATA, PORT277_DATA, PORT276_DATA,
+			PORT275_DATA, PORT274_DATA, PORT273_DATA, PORT272_DATA,
+			PORT271_DATA, PORT270_DATA, PORT269_DATA, PORT268_DATA,
+			PORT267_DATA, PORT266_DATA, PORT265_DATA, PORT264_DATA,
+			PORT263_DATA, PORT262_DATA, PORT261_DATA, PORT260_DATA,
+			PORT259_DATA, PORT258_DATA, PORT257_DATA, PORT256_DATA,
+		}
+	},
+	{ PINMUX_DATA_REG("PORTU319_288DR", 0xe6057000, 32) {
+			0, 0, 0, 0,
+			0, 0, 0, 0,
+			0, 0, 0, PORT308_DATA,
+			PORT307_DATA, PORT306_DATA, PORT305_DATA, PORT304_DATA,
+			PORT303_DATA, PORT302_DATA, PORT301_DATA, PORT300_DATA,
+			PORT299_DATA, PORT298_DATA, PORT297_DATA, PORT296_DATA,
+			PORT295_DATA, PORT294_DATA, PORT293_DATA, PORT292_DATA,
+			PORT291_DATA, PORT290_DATA, PORT289_DATA, PORT288_DATA,
+		}
+	},
+	{ PINMUX_DATA_REG("PORTU351_320DR", 0xe6057004, 32) {
+			0, 0, 0, 0,
+			0, 0, 0, 0,
+			0, 0, 0, 0,
+			0, 0, 0, 0,
+			0, 0, 0, 0,
+			0, 0, PORT329_DATA, PORT328_DATA,
+			PORT327_DATA, PORT326_DATA, PORT325_DATA, PORT324_DATA,
+			PORT323_DATA, PORT322_DATA, PORT321_DATA, PORT320_DATA,
+		}
+	},
+	{ },
+};
+
+static const struct pinmux_irq pinmux_irqs[] = {
+	PINMUX_IRQ(irq_pin(0), 0),
+	PINMUX_IRQ(irq_pin(1), 1),
+	PINMUX_IRQ(irq_pin(2), 2),
+	PINMUX_IRQ(irq_pin(3), 3),
+	PINMUX_IRQ(irq_pin(4), 4),
+	PINMUX_IRQ(irq_pin(5), 5),
+	PINMUX_IRQ(irq_pin(6), 6),
+	PINMUX_IRQ(irq_pin(7), 7),
+	PINMUX_IRQ(irq_pin(8), 8),
+	PINMUX_IRQ(irq_pin(9), 9),
+	PINMUX_IRQ(irq_pin(10), 10),
+	PINMUX_IRQ(irq_pin(11), 11),
+	PINMUX_IRQ(irq_pin(12), 12),
+	PINMUX_IRQ(irq_pin(13), 13),
+	PINMUX_IRQ(irq_pin(14), 14),
+	PINMUX_IRQ(irq_pin(15), 15),
+	PINMUX_IRQ(irq_pin(16), 320),
+	PINMUX_IRQ(irq_pin(17), 321),
+	PINMUX_IRQ(irq_pin(18), 85),
+	PINMUX_IRQ(irq_pin(19), 84),
+	PINMUX_IRQ(irq_pin(20), 160),
+	PINMUX_IRQ(irq_pin(21), 161),
+	PINMUX_IRQ(irq_pin(22), 162),
+	PINMUX_IRQ(irq_pin(23), 163),
+	PINMUX_IRQ(irq_pin(24), 175),
+	PINMUX_IRQ(irq_pin(25), 176),
+	PINMUX_IRQ(irq_pin(26), 177),
+	PINMUX_IRQ(irq_pin(27), 178),
+	PINMUX_IRQ(irq_pin(28), 322),
+	PINMUX_IRQ(irq_pin(29), 323),
+	PINMUX_IRQ(irq_pin(30), 324),
+	PINMUX_IRQ(irq_pin(31), 192),
+	PINMUX_IRQ(irq_pin(32), 193),
+	PINMUX_IRQ(irq_pin(33), 194),
+	PINMUX_IRQ(irq_pin(34), 195),
+	PINMUX_IRQ(irq_pin(35), 196),
+	PINMUX_IRQ(irq_pin(36), 197),
+	PINMUX_IRQ(irq_pin(37), 198),
+	PINMUX_IRQ(irq_pin(38), 199),
+	PINMUX_IRQ(irq_pin(39), 200),
+	PINMUX_IRQ(irq_pin(40), 66),
+	PINMUX_IRQ(irq_pin(41), 102),
+	PINMUX_IRQ(irq_pin(42), 103),
+	PINMUX_IRQ(irq_pin(43), 109),
+	PINMUX_IRQ(irq_pin(44), 110),
+	PINMUX_IRQ(irq_pin(45), 111),
+	PINMUX_IRQ(irq_pin(46), 112),
+	PINMUX_IRQ(irq_pin(47), 113),
+	PINMUX_IRQ(irq_pin(48), 114),
+	PINMUX_IRQ(irq_pin(49), 115),
+	PINMUX_IRQ(irq_pin(50), 301),
+	PINMUX_IRQ(irq_pin(51), 290),
+	PINMUX_IRQ(irq_pin(52), 296),
+	PINMUX_IRQ(irq_pin(53), 325),
+	PINMUX_IRQ(irq_pin(54), 326),
+	PINMUX_IRQ(irq_pin(55), 327),
+	PINMUX_IRQ(irq_pin(56), 328),
+	PINMUX_IRQ(irq_pin(57), 329),
+};
+
+#define PORTCR_PULMD_OFF (0 << 6)
+#define PORTCR_PULMD_DOWN (2 << 6)
+#define PORTCR_PULMD_UP (3 << 6)
+#define PORTCR_PULMD_MASK (3 << 6)
+
+static const unsigned int r8a73a4_portcr_offsets[] = {
+	0x00000000, 0x00001000, 0x00000000, 0x00001000,
+	0x00001000, 0x00002000, 0x00002000, 0x00002000,
+	0x00002000, 0x00003000, 0x00003000,
+};
+
+static unsigned int r8a73a4_pinmux_get_bias(struct sh_pfc *pfc,
+					    unsigned int pin)
+{
+	void __iomem *addr;
+
+	addr = pfc->window->virt + r8a73a4_portcr_offsets[pin >> 5] + pin;
+
+	switch (ioread8(addr) & PORTCR_PULMD_MASK) {
+	case PORTCR_PULMD_UP:
+		return PIN_CONFIG_BIAS_PULL_UP;
+	case PORTCR_PULMD_DOWN:
+		return PIN_CONFIG_BIAS_PULL_DOWN;
+	case PORTCR_PULMD_OFF:
+	default:
+		return PIN_CONFIG_BIAS_DISABLE;
+	}
+}
+
+static void r8a73a4_pinmux_set_bias(struct sh_pfc *pfc, unsigned int pin,
+				   unsigned int bias)
+{
+	void __iomem *addr;
+	u32 value;
+
+	addr = pfc->window->virt + r8a73a4_portcr_offsets[pin >> 5] + pin;
+	value = ioread8(addr) & ~PORTCR_PULMD_MASK;
+
+	switch (bias) {
+	case PIN_CONFIG_BIAS_PULL_UP:
+		value |= PORTCR_PULMD_UP;
+		break;
+	case PIN_CONFIG_BIAS_PULL_DOWN:
+		value |= PORTCR_PULMD_DOWN;
+		break;
+	}
+
+	iowrite8(value, addr);
+}
+
+static const struct sh_pfc_soc_operations r8a73a4_pinmux_ops = {
+	.get_bias = r8a73a4_pinmux_get_bias,
+	.set_bias = r8a73a4_pinmux_set_bias,
+};
+
+const struct sh_pfc_soc_info r8a73a4_pinmux_info = {
+	.name		= "r8a73a4_pfc",
+	.ops		= &r8a73a4_pinmux_ops,
+
+	.input = { PINMUX_INPUT_BEGIN, PINMUX_INPUT_END },
+	.output = { PINMUX_OUTPUT_BEGIN, PINMUX_OUTPUT_END },
+	.function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END },
+
+	.pins = pinmux_pins,
+	.nr_pins = ARRAY_SIZE(pinmux_pins),
+
+	.ranges = pinmux_ranges,
+	.nr_ranges = ARRAY_SIZE(pinmux_ranges),
+
+	.groups = pinmux_groups,
+	.nr_groups = ARRAY_SIZE(pinmux_groups),
+	.functions = pinmux_functions,
+	.nr_functions = ARRAY_SIZE(pinmux_functions),
+
+	.cfg_regs	= pinmux_config_regs,
+	.data_regs	= pinmux_data_regs,
+
+	.gpio_data	= pinmux_data,
+	.gpio_data_size	= ARRAY_SIZE(pinmux_data),
+
+	.gpio_irq = pinmux_irqs,
+	.gpio_irq_size = ARRAY_SIZE(pinmux_irqs),
+};
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7740.c b/drivers/pinctrl/sh-pfc/pfc-r8a7740.c
index 214788c..bbd87d2 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a7740.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a7740.c
@@ -577,7 +577,7 @@ enum {
 	PINMUX_MARK_END,
 };
 
-static pinmux_enum_t pinmux_data[] = {
+static const pinmux_enum_t pinmux_data[] = {
 	/* specify valid pin states for each pin in GPIO mode */
 
 	/* I/O and Pull U/D */
@@ -1654,11 +1654,532 @@ static pinmux_enum_t pinmux_data[] = {
 	PINMUX_DATA(TRACEAUD_FROM_MEMC_MARK,			MSEL5CR_30_1,	MSEL5CR_29_0),
 };
 
-static struct pinmux_gpio pinmux_gpios[] = {
-
-	/* PORT */
+static struct sh_pfc_pin pinmux_pins[] = {
 	GPIO_PORT_ALL(),
+};
+
+/* - LCD0 ------------------------------------------------------------------- */
+static const unsigned int lcd0_data8_pins[] = {
+	/* D[0:7] */
+	58, 57, 56, 55, 54, 53, 52, 51,
+};
+static const unsigned int lcd0_data8_mux[] = {
+	LCD0_D0_MARK, LCD0_D1_MARK, LCD0_D2_MARK, LCD0_D3_MARK,
+	LCD0_D4_MARK, LCD0_D5_MARK, LCD0_D6_MARK, LCD0_D7_MARK,
+};
+static const unsigned int lcd0_data9_pins[] = {
+	/* D[0:8] */
+	58, 57, 56, 55, 54, 53, 52, 51,
+	50,
+};
+static const unsigned int lcd0_data9_mux[] = {
+	LCD0_D0_MARK, LCD0_D1_MARK, LCD0_D2_MARK, LCD0_D3_MARK,
+	LCD0_D4_MARK, LCD0_D5_MARK, LCD0_D6_MARK, LCD0_D7_MARK,
+	LCD0_D8_MARK,
+};
+static const unsigned int lcd0_data12_pins[] = {
+	/* D[0:11] */
+	58, 57, 56, 55, 54, 53, 52, 51,
+	50, 49, 48, 47,
+};
+static const unsigned int lcd0_data12_mux[] = {
+	LCD0_D0_MARK, LCD0_D1_MARK, LCD0_D2_MARK, LCD0_D3_MARK,
+	LCD0_D4_MARK, LCD0_D5_MARK, LCD0_D6_MARK, LCD0_D7_MARK,
+	LCD0_D8_MARK, LCD0_D9_MARK, LCD0_D10_MARK, LCD0_D11_MARK,
+};
+static const unsigned int lcd0_data16_pins[] = {
+	/* D[0:15] */
+	58, 57, 56, 55, 54, 53, 52, 51,
+	50, 49, 48, 47, 46, 45, 44, 43,
+};
+static const unsigned int lcd0_data16_mux[] = {
+	LCD0_D0_MARK, LCD0_D1_MARK, LCD0_D2_MARK, LCD0_D3_MARK,
+	LCD0_D4_MARK, LCD0_D5_MARK, LCD0_D6_MARK, LCD0_D7_MARK,
+	LCD0_D8_MARK, LCD0_D9_MARK, LCD0_D10_MARK, LCD0_D11_MARK,
+	LCD0_D12_MARK, LCD0_D13_MARK, LCD0_D14_MARK, LCD0_D15_MARK,
+};
+static const unsigned int lcd0_data18_pins[] = {
+	/* D[0:17] */
+	58, 57, 56, 55, 54, 53, 52, 51,
+	50, 49, 48, 47, 46, 45, 44, 43,
+	42, 41,
+};
+static const unsigned int lcd0_data18_mux[] = {
+	LCD0_D0_MARK, LCD0_D1_MARK, LCD0_D2_MARK, LCD0_D3_MARK,
+	LCD0_D4_MARK, LCD0_D5_MARK, LCD0_D6_MARK, LCD0_D7_MARK,
+	LCD0_D8_MARK, LCD0_D9_MARK, LCD0_D10_MARK, LCD0_D11_MARK,
+	LCD0_D12_MARK, LCD0_D13_MARK, LCD0_D14_MARK, LCD0_D15_MARK,
+	LCD0_D16_MARK, LCD0_D17_MARK,
+};
+static const unsigned int lcd0_data24_0_pins[] = {
+	/* D[0:23] */
+	58, 57, 56, 55, 54, 53, 52, 51,
+	50, 49, 48, 47, 46, 45, 44, 43,
+	42, 41, 40, 4, 3, 2, 0, 1,
+};
+static const unsigned int lcd0_data24_0_mux[] = {
+	LCD0_D0_MARK, LCD0_D1_MARK, LCD0_D2_MARK, LCD0_D3_MARK,
+	LCD0_D4_MARK, LCD0_D5_MARK, LCD0_D6_MARK, LCD0_D7_MARK,
+	LCD0_D8_MARK, LCD0_D9_MARK, LCD0_D10_MARK, LCD0_D11_MARK,
+	LCD0_D12_MARK, LCD0_D13_MARK, LCD0_D14_MARK, LCD0_D15_MARK,
+	LCD0_D16_MARK, LCD0_D17_MARK, LCD0_D18_PORT40_MARK, LCD0_D19_PORT4_MARK,
+	LCD0_D20_PORT3_MARK, LCD0_D21_PORT2_MARK, LCD0_D22_PORT0_MARK,
+	LCD0_D23_PORT1_MARK,
+};
+static const unsigned int lcd0_data24_1_pins[] = {
+	/* D[0:23] */
+	58, 57, 56, 55, 54, 53, 52, 51,
+	50, 49, 48, 47, 46, 45, 44, 43,
+	42, 41, 163, 162, 161, 158, 160, 159,
+};
+static const unsigned int lcd0_data24_1_mux[] = {
+	LCD0_D0_MARK, LCD0_D1_MARK, LCD0_D2_MARK, LCD0_D3_MARK,
+	LCD0_D4_MARK, LCD0_D5_MARK, LCD0_D6_MARK, LCD0_D7_MARK,
+	LCD0_D8_MARK, LCD0_D9_MARK, LCD0_D10_MARK, LCD0_D11_MARK,
+	LCD0_D16_MARK, LCD0_D17_MARK, LCD0_D18_PORT163_MARK,
+	LCD0_D19_PORT162_MARK, LCD0_D20_PORT161_MARK, LCD0_D21_PORT158_MARK,
+	LCD0_D22_PORT160_MARK, LCD0_D23_PORT159_MARK,
+};
+static const unsigned int lcd0_display_pins[] = {
+	/* DON, VCPWC, VEPWC */
+	61, 59, 60,
+};
+static const unsigned int lcd0_display_mux[] = {
+	LCD0_DON_MARK, LCD0_VCPWC_MARK, LCD0_VEPWC_MARK,
+};
+static const unsigned int lcd0_lclk_0_pins[] = {
+	/* LCLK */
+	102,
+};
+static const unsigned int lcd0_lclk_0_mux[] = {
+	LCD0_LCLK_PORT102_MARK,
+};
+static const unsigned int lcd0_lclk_1_pins[] = {
+	/* LCLK */
+	165,
+};
+static const unsigned int lcd0_lclk_1_mux[] = {
+	LCD0_LCLK_PORT165_MARK,
+};
+static const unsigned int lcd0_sync_pins[] = {
+	/* VSYN, HSYN, DCK, DISP */
+	63, 64, 62, 65,
+};
+static const unsigned int lcd0_sync_mux[] = {
+	LCD0_VSYN_MARK, LCD0_HSYN_MARK, LCD0_DCK_MARK, LCD0_DISP_MARK,
+};
+static const unsigned int lcd0_sys_pins[] = {
+	/* CS, WR, RD, RS */
+	64, 62, 164, 65,
+};
+static const unsigned int lcd0_sys_mux[] = {
+	LCD0_CS_MARK, LCD0_WR_MARK, LCD0_RD_MARK, LCD0_RS_MARK,
+};
+/* - LCD1 ------------------------------------------------------------------- */
+static const unsigned int lcd1_data8_pins[] = {
+	/* D[0:7] */
+	4, 3, 2, 1, 0, 91, 92, 23,
+};
+static const unsigned int lcd1_data8_mux[] = {
+	LCD1_D0_MARK, LCD1_D1_MARK, LCD1_D2_MARK, LCD1_D3_MARK,
+	LCD1_D4_MARK, LCD1_D5_MARK, LCD1_D6_MARK, LCD1_D7_MARK,
+};
+static const unsigned int lcd1_data9_pins[] = {
+	/* D[0:8] */
+	4, 3, 2, 1, 0, 91, 92, 23,
+	93,
+};
+static const unsigned int lcd1_data9_mux[] = {
+	LCD1_D0_MARK, LCD1_D1_MARK, LCD1_D2_MARK, LCD1_D3_MARK,
+	LCD1_D4_MARK, LCD1_D5_MARK, LCD1_D6_MARK, LCD1_D7_MARK,
+	LCD1_D8_MARK,
+};
+static const unsigned int lcd1_data12_pins[] = {
+	/* D[0:12] */
+	4, 3, 2, 1, 0, 91, 92, 23,
+	93, 94, 21, 201,
+};
+static const unsigned int lcd1_data12_mux[] = {
+	LCD1_D0_MARK, LCD1_D1_MARK, LCD1_D2_MARK, LCD1_D3_MARK,
+	LCD1_D4_MARK, LCD1_D5_MARK, LCD1_D6_MARK, LCD1_D7_MARK,
+	LCD1_D8_MARK, LCD1_D9_MARK, LCD1_D10_MARK, LCD1_D11_MARK,
+};
+static const unsigned int lcd1_data16_pins[] = {
+	/* D[0:15] */
+	4, 3, 2, 1, 0, 91, 92, 23,
+	93, 94, 21, 201, 200, 199, 196, 195,
+};
+static const unsigned int lcd1_data16_mux[] = {
+	LCD1_D0_MARK, LCD1_D1_MARK, LCD1_D2_MARK, LCD1_D3_MARK,
+	LCD1_D4_MARK, LCD1_D5_MARK, LCD1_D6_MARK, LCD1_D7_MARK,
+	LCD1_D8_MARK, LCD1_D9_MARK, LCD1_D10_MARK, LCD1_D11_MARK,
+	LCD1_D12_MARK, LCD1_D13_MARK, LCD1_D14_MARK, LCD1_D15_MARK,
+};
+static const unsigned int lcd1_data18_pins[] = {
+	/* D[0:17] */
+	4, 3, 2, 1, 0, 91, 92, 23,
+	93, 94, 21, 201, 200, 199, 196, 195,
+	194, 193,
+};
+static const unsigned int lcd1_data18_mux[] = {
+	LCD1_D0_MARK, LCD1_D1_MARK, LCD1_D2_MARK, LCD1_D3_MARK,
+	LCD1_D4_MARK, LCD1_D5_MARK, LCD1_D6_MARK, LCD1_D7_MARK,
+	LCD1_D8_MARK, LCD1_D9_MARK, LCD1_D10_MARK, LCD1_D11_MARK,
+	LCD1_D12_MARK, LCD1_D13_MARK, LCD1_D14_MARK, LCD1_D15_MARK,
+	LCD1_D16_MARK, LCD1_D17_MARK,
+};
+static const unsigned int lcd1_data24_pins[] = {
+	/* D[0:23] */
+	4, 3, 2, 1, 0, 91, 92, 23,
+	93, 94, 21, 201, 200, 199, 196, 195,
+	194, 193, 198, 197, 75, 74, 15, 14,
+};
+static const unsigned int lcd1_data24_mux[] = {
+	LCD1_D0_MARK, LCD1_D1_MARK, LCD1_D2_MARK, LCD1_D3_MARK,
+	LCD1_D4_MARK, LCD1_D5_MARK, LCD1_D6_MARK, LCD1_D7_MARK,
+	LCD1_D8_MARK, LCD1_D9_MARK, LCD1_D10_MARK, LCD1_D11_MARK,
+	LCD1_D12_MARK, LCD1_D13_MARK, LCD1_D14_MARK, LCD1_D15_MARK,
+	LCD1_D16_MARK, LCD1_D17_MARK, LCD1_D18_MARK, LCD1_D19_MARK,
+	LCD1_D20_MARK, LCD1_D21_MARK, LCD1_D22_MARK, LCD1_D23_MARK,
+};
+static const unsigned int lcd1_display_pins[] = {
+	/* DON, VCPWC, VEPWC */
+	100, 5, 6,
+};
+static const unsigned int lcd1_display_mux[] = {
+	LCD1_DON_MARK, LCD1_VCPWC_MARK, LCD1_VEPWC_MARK,
+};
+static const unsigned int lcd1_lclk_pins[] = {
+	/* LCLK */
+	40,
+};
+static const unsigned int lcd1_lclk_mux[] = {
+	LCD1_LCLK_MARK,
+};
+static const unsigned int lcd1_sync_pins[] = {
+	/* VSYN, HSYN, DCK, DISP */
+	98, 97, 99, 12,
+};
+static const unsigned int lcd1_sync_mux[] = {
+	LCD1_VSYN_MARK, LCD1_HSYN_MARK, LCD1_DCK_MARK, LCD1_DISP_MARK,
+};
+static const unsigned int lcd1_sys_pins[] = {
+	/* CS, WR, RD, RS */
+	97, 99, 13, 12,
+};
+static const unsigned int lcd1_sys_mux[] = {
+	LCD1_CS_MARK, LCD1_WR_MARK, LCD1_RD_MARK, LCD1_RS_MARK,
+};
+/* - MMCIF ------------------------------------------------------------------ */
+static const unsigned int mmc0_data1_0_pins[] = {
+	/* D[0] */
+	68,
+};
+static const unsigned int mmc0_data1_0_mux[] = {
+	MMC0_D0_PORT68_MARK,
+};
+static const unsigned int mmc0_data4_0_pins[] = {
+	/* D[0:3] */
+	68, 69, 70, 71,
+};
+static const unsigned int mmc0_data4_0_mux[] = {
+	MMC0_D0_PORT68_MARK, MMC0_D1_PORT69_MARK, MMC0_D2_PORT70_MARK, MMC0_D3_PORT71_MARK,
+};
+static const unsigned int mmc0_data8_0_pins[] = {
+	/* D[0:7] */
+	68, 69, 70, 71, 72, 73, 74, 75,
+};
+static const unsigned int mmc0_data8_0_mux[] = {
+	MMC0_D0_PORT68_MARK, MMC0_D1_PORT69_MARK, MMC0_D2_PORT70_MARK, MMC0_D3_PORT71_MARK,
+	MMC0_D4_PORT72_MARK, MMC0_D5_PORT73_MARK, MMC0_D6_PORT74_MARK, MMC0_D7_PORT75_MARK,
+};
+static const unsigned int mmc0_ctrl_0_pins[] = {
+	/* CMD, CLK */
+	67, 66,
+};
+static const unsigned int mmc0_ctrl_0_mux[] = {
+	MMC0_CMD_PORT67_MARK, MMC0_CLK_PORT66_MARK,
+};
+
+static const unsigned int mmc0_data1_1_pins[] = {
+	/* D[0] */
+	149,
+};
+static const unsigned int mmc0_data1_1_mux[] = {
+	MMC1_D0_PORT149_MARK,
+};
+static const unsigned int mmc0_data4_1_pins[] = {
+	/* D[0:3] */
+	149, 148, 147, 146,
+};
+static const unsigned int mmc0_data4_1_mux[] = {
+	MMC1_D0_PORT149_MARK, MMC1_D1_PORT148_MARK, MMC1_D2_PORT147_MARK, MMC1_D3_PORT146_MARK,
+};
+static const unsigned int mmc0_data8_1_pins[] = {
+	/* D[0:7] */
+	149, 148, 147, 146, 145, 144, 143, 142,
+};
+static const unsigned int mmc0_data8_1_mux[] = {
+	MMC1_D0_PORT149_MARK, MMC1_D1_PORT148_MARK, MMC1_D2_PORT147_MARK, MMC1_D3_PORT146_MARK,
+	MMC1_D4_PORT145_MARK, MMC1_D5_PORT144_MARK, MMC1_D6_PORT143_MARK, MMC1_D7_PORT142_MARK,
+};
+static const unsigned int mmc0_ctrl_1_pins[] = {
+	/* CMD, CLK */
+	104, 103,
+};
+static const unsigned int mmc0_ctrl_1_mux[] = {
+	MMC1_CMD_PORT104_MARK, MMC1_CLK_PORT103_MARK,
+};
+/* - SDHI0 ------------------------------------------------------------------ */
+static const unsigned int sdhi0_data1_pins[] = {
+	/* D0 */
+	77,
+};
+static const unsigned int sdhi0_data1_mux[] = {
+	SDHI0_D0_MARK,
+};
+static const unsigned int sdhi0_data4_pins[] = {
+	/* D[0:3] */
+	77, 78, 79, 80,
+};
+static const unsigned int sdhi0_data4_mux[] = {
+	SDHI0_D0_MARK, SDHI0_D1_MARK, SDHI0_D2_MARK, SDHI0_D3_MARK,
+};
+static const unsigned int sdhi0_ctrl_pins[] = {
+	/* CMD, CLK */
+	76, 82,
+};
+static const unsigned int sdhi0_ctrl_mux[] = {
+	SDHI0_CMD_MARK, SDHI0_CLK_MARK,
+};
+static const unsigned int sdhi0_cd_pins[] = {
+	/* CD */
+	81,
+};
+static const unsigned int sdhi0_cd_mux[] = {
+	SDHI0_CD_MARK,
+};
+static const unsigned int sdhi0_wp_pins[] = {
+	/* WP */
+	83,
+};
+static const unsigned int sdhi0_wp_mux[] = {
+	SDHI0_WP_MARK,
+};
+/* - SDHI1 ------------------------------------------------------------------ */
+static const unsigned int sdhi1_data1_pins[] = {
+	/* D0 */
+	68,
+};
+static const unsigned int sdhi1_data1_mux[] = {
+	SDHI1_D0_MARK,
+};
+static const unsigned int sdhi1_data4_pins[] = {
+	/* D[0:3] */
+	68, 69, 70, 71,
+};
+static const unsigned int sdhi1_data4_mux[] = {
+	SDHI1_D0_MARK, SDHI1_D1_MARK, SDHI1_D2_MARK, SDHI1_D3_MARK,
+};
+static const unsigned int sdhi1_ctrl_pins[] = {
+	/* CMD, CLK */
+	67, 66,
+};
+static const unsigned int sdhi1_ctrl_mux[] = {
+	SDHI1_CMD_MARK, SDHI1_CLK_MARK,
+};
+static const unsigned int sdhi1_cd_pins[] = {
+	/* CD */
+	72,
+};
+static const unsigned int sdhi1_cd_mux[] = {
+	SDHI1_CD_MARK,
+};
+static const unsigned int sdhi1_wp_pins[] = {
+	/* WP */
+	73,
+};
+static const unsigned int sdhi1_wp_mux[] = {
+	SDHI1_WP_MARK,
+};
+/* - SDHI2 ------------------------------------------------------------------ */
+static const unsigned int sdhi2_data1_pins[] = {
+	/* D0 */
+	205,
+};
+static const unsigned int sdhi2_data1_mux[] = {
+	SDHI2_D0_MARK,
+};
+static const unsigned int sdhi2_data4_pins[] = {
+	/* D[0:3] */
+	205, 206, 207, 208,
+};
+static const unsigned int sdhi2_data4_mux[] = {
+	SDHI2_D0_MARK, SDHI2_D1_MARK, SDHI2_D2_MARK, SDHI2_D3_MARK,
+};
+static const unsigned int sdhi2_ctrl_pins[] = {
+	/* CMD, CLK */
+	204, 203,
+};
+static const unsigned int sdhi2_ctrl_mux[] = {
+	SDHI2_CMD_MARK, SDHI2_CLK_MARK,
+};
+static const unsigned int sdhi2_cd_0_pins[] = {
+	/* CD */
+	202,
+};
+static const unsigned int sdhi2_cd_0_mux[] = {
+	SDHI2_CD_PORT202_MARK,
+};
+static const unsigned int sdhi2_wp_0_pins[] = {
+	/* WP */
+	177,
+};
+static const unsigned int sdhi2_wp_0_mux[] = {
+	SDHI2_WP_PORT177_MARK,
+};
+static const unsigned int sdhi2_cd_1_pins[] = {
+	/* CD */
+	24,
+};
+static const unsigned int sdhi2_cd_1_mux[] = {
+	SDHI2_CD_PORT24_MARK,
+};
+static const unsigned int sdhi2_wp_1_pins[] = {
+	/* WP */
+	25,
+};
+static const unsigned int sdhi2_wp_1_mux[] = {
+	SDHI2_WP_PORT25_MARK,
+};
 
+static const struct sh_pfc_pin_group pinmux_groups[] = {
+	SH_PFC_PIN_GROUP(lcd0_data8),
+	SH_PFC_PIN_GROUP(lcd0_data9),
+	SH_PFC_PIN_GROUP(lcd0_data12),
+	SH_PFC_PIN_GROUP(lcd0_data16),
+	SH_PFC_PIN_GROUP(lcd0_data18),
+	SH_PFC_PIN_GROUP(lcd0_data24_0),
+	SH_PFC_PIN_GROUP(lcd0_data24_1),
+	SH_PFC_PIN_GROUP(lcd0_display),
+	SH_PFC_PIN_GROUP(lcd0_lclk_0),
+	SH_PFC_PIN_GROUP(lcd0_lclk_1),
+	SH_PFC_PIN_GROUP(lcd0_sync),
+	SH_PFC_PIN_GROUP(lcd0_sys),
+	SH_PFC_PIN_GROUP(lcd1_data8),
+	SH_PFC_PIN_GROUP(lcd1_data9),
+	SH_PFC_PIN_GROUP(lcd1_data12),
+	SH_PFC_PIN_GROUP(lcd1_data16),
+	SH_PFC_PIN_GROUP(lcd1_data18),
+	SH_PFC_PIN_GROUP(lcd1_data24),
+	SH_PFC_PIN_GROUP(lcd1_display),
+	SH_PFC_PIN_GROUP(lcd1_lclk),
+	SH_PFC_PIN_GROUP(lcd1_sync),
+	SH_PFC_PIN_GROUP(lcd1_sys),
+	SH_PFC_PIN_GROUP(mmc0_data1_0),
+	SH_PFC_PIN_GROUP(mmc0_data4_0),
+	SH_PFC_PIN_GROUP(mmc0_data8_0),
+	SH_PFC_PIN_GROUP(mmc0_ctrl_0),
+	SH_PFC_PIN_GROUP(mmc0_data1_1),
+	SH_PFC_PIN_GROUP(mmc0_data4_1),
+	SH_PFC_PIN_GROUP(mmc0_data8_1),
+	SH_PFC_PIN_GROUP(mmc0_ctrl_1),
+	SH_PFC_PIN_GROUP(sdhi0_data1),
+	SH_PFC_PIN_GROUP(sdhi0_data4),
+	SH_PFC_PIN_GROUP(sdhi0_ctrl),
+	SH_PFC_PIN_GROUP(sdhi0_cd),
+	SH_PFC_PIN_GROUP(sdhi0_wp),
+	SH_PFC_PIN_GROUP(sdhi1_data1),
+	SH_PFC_PIN_GROUP(sdhi1_data4),
+	SH_PFC_PIN_GROUP(sdhi1_ctrl),
+	SH_PFC_PIN_GROUP(sdhi1_cd),
+	SH_PFC_PIN_GROUP(sdhi1_wp),
+	SH_PFC_PIN_GROUP(sdhi2_data1),
+	SH_PFC_PIN_GROUP(sdhi2_data4),
+	SH_PFC_PIN_GROUP(sdhi2_ctrl),
+	SH_PFC_PIN_GROUP(sdhi2_cd_0),
+	SH_PFC_PIN_GROUP(sdhi2_wp_0),
+	SH_PFC_PIN_GROUP(sdhi2_cd_1),
+	SH_PFC_PIN_GROUP(sdhi2_wp_1),
+};
+
+static const char * const lcd0_groups[] = {
+	"lcd0_data8",
+	"lcd0_data9",
+	"lcd0_data12",
+	"lcd0_data16",
+	"lcd0_data18",
+	"lcd0_data24_0",
+	"lcd0_data24_1",
+	"lcd0_display",
+	"lcd0_lclk_0",
+	"lcd0_lclk_1",
+	"lcd0_sync",
+	"lcd0_sys",
+};
+
+static const char * const lcd1_groups[] = {
+	"lcd1_data8",
+	"lcd1_data9",
+	"lcd1_data12",
+	"lcd1_data16",
+	"lcd1_data18",
+	"lcd1_data24",
+	"lcd1_display",
+	"lcd1_lclk",
+	"lcd1_sync",
+	"lcd1_sys",
+};
+
+static const char * const mmc0_groups[] = {
+	"mmc0_data1_0",
+	"mmc0_data4_0",
+	"mmc0_data8_0",
+	"mmc0_ctrl_0",
+	"mmc0_data1_1",
+	"mmc0_data4_1",
+	"mmc0_data8_1",
+	"mmc0_ctrl_1",
+};
+
+static const char * const sdhi0_groups[] = {
+	"sdhi0_data1",
+	"sdhi0_data4",
+	"sdhi0_ctrl",
+	"sdhi0_cd",
+	"sdhi0_wp",
+};
+
+static const char * const sdhi1_groups[] = {
+	"sdhi1_data1",
+	"sdhi1_data4",
+	"sdhi1_ctrl",
+	"sdhi1_cd",
+	"sdhi1_wp",
+};
+
+static const char * const sdhi2_groups[] = {
+	"sdhi2_data1",
+	"sdhi2_data4",
+	"sdhi2_ctrl",
+	"sdhi2_cd_0",
+	"sdhi2_wp_0",
+	"sdhi2_cd_1",
+	"sdhi2_wp_1",
+};
+
+static const struct sh_pfc_function pinmux_functions[] = {
+	SH_PFC_FUNCTION(lcd0),
+	SH_PFC_FUNCTION(lcd1),
+	SH_PFC_FUNCTION(mmc0),
+	SH_PFC_FUNCTION(sdhi0),
+	SH_PFC_FUNCTION(sdhi1),
+	SH_PFC_FUNCTION(sdhi2),
+};
+
+#define PINMUX_FN_BASE	ARRAY_SIZE(pinmux_pins)
+
+static const struct pinmux_func pinmux_func_gpios[] = {
 	/* IRQ */
 	GPIO_FN(IRQ0_PORT2),	GPIO_FN(IRQ0_PORT13),
 	GPIO_FN(IRQ1),
@@ -1792,43 +2313,6 @@ static struct pinmux_gpio pinmux_gpios[] = {
 	GPIO_FN(SCIFB_RTS_PORT172),
 	GPIO_FN(SCIFB_CTS_PORT173),
 
-	/* LCD0 */
-	GPIO_FN(LCD0_D0),	GPIO_FN(LCD0_D1),	GPIO_FN(LCD0_D2),
-	GPIO_FN(LCD0_D3),	GPIO_FN(LCD0_D4),	GPIO_FN(LCD0_D5),
-	GPIO_FN(LCD0_D6),	GPIO_FN(LCD0_D7),	GPIO_FN(LCD0_D8),
-	GPIO_FN(LCD0_D9),	GPIO_FN(LCD0_D10),	GPIO_FN(LCD0_D11),
-	GPIO_FN(LCD0_D12),	GPIO_FN(LCD0_D13),	GPIO_FN(LCD0_D14),
-	GPIO_FN(LCD0_D15),	GPIO_FN(LCD0_D16),	GPIO_FN(LCD0_D17),
-	GPIO_FN(LCD0_DON),	GPIO_FN(LCD0_VCPWC),	GPIO_FN(LCD0_VEPWC),
-	GPIO_FN(LCD0_DCK),	GPIO_FN(LCD0_VSYN),
-	GPIO_FN(LCD0_HSYN),	GPIO_FN(LCD0_DISP),
-	GPIO_FN(LCD0_WR),	GPIO_FN(LCD0_RD),
-	GPIO_FN(LCD0_CS),	GPIO_FN(LCD0_RS),
-
-	GPIO_FN(LCD0_D18_PORT163),	GPIO_FN(LCD0_D19_PORT162),
-	GPIO_FN(LCD0_D20_PORT161),	GPIO_FN(LCD0_D21_PORT158),
-	GPIO_FN(LCD0_D22_PORT160),	GPIO_FN(LCD0_D23_PORT159),
-	GPIO_FN(LCD0_LCLK_PORT165),	/* MSEL5CR_6_1 */
-
-	GPIO_FN(LCD0_D18_PORT40),	GPIO_FN(LCD0_D19_PORT4),
-	GPIO_FN(LCD0_D20_PORT3),	GPIO_FN(LCD0_D21_PORT2),
-	GPIO_FN(LCD0_D22_PORT0),	GPIO_FN(LCD0_D23_PORT1),
-	GPIO_FN(LCD0_LCLK_PORT102),	/* MSEL5CR_6_0 */
-
-	/* LCD1 */
-	GPIO_FN(LCD1_D0),	GPIO_FN(LCD1_D1),	GPIO_FN(LCD1_D2),
-	GPIO_FN(LCD1_D3),	GPIO_FN(LCD1_D4),	GPIO_FN(LCD1_D5),
-	GPIO_FN(LCD1_D6),	GPIO_FN(LCD1_D7),	GPIO_FN(LCD1_D8),
-	GPIO_FN(LCD1_D9),	GPIO_FN(LCD1_D10),	GPIO_FN(LCD1_D11),
-	GPIO_FN(LCD1_D12),	GPIO_FN(LCD1_D13),	GPIO_FN(LCD1_D14),
-	GPIO_FN(LCD1_D15),	GPIO_FN(LCD1_D16),	GPIO_FN(LCD1_D17),
-	GPIO_FN(LCD1_D18),	GPIO_FN(LCD1_D19),	GPIO_FN(LCD1_D20),
-	GPIO_FN(LCD1_D21),	GPIO_FN(LCD1_D22),	GPIO_FN(LCD1_D23),
-	GPIO_FN(LCD1_RS),	GPIO_FN(LCD1_RD),	GPIO_FN(LCD1_CS),
-	GPIO_FN(LCD1_WR),	GPIO_FN(LCD1_DCK),	GPIO_FN(LCD1_DON),
-	GPIO_FN(LCD1_VCPWC),	GPIO_FN(LCD1_LCLK),	GPIO_FN(LCD1_HSYN),
-	GPIO_FN(LCD1_VSYN),	GPIO_FN(LCD1_VEPWC),	GPIO_FN(LCD1_DISP),
-
 	/* RSPI */
 	GPIO_FN(RSPI_SSL0_A),	GPIO_FN(RSPI_SSL1_A),	GPIO_FN(RSPI_SSL2_A),
 	GPIO_FN(RSPI_SSL3_A),	GPIO_FN(RSPI_CK_A),	GPIO_FN(RSPI_MOSI_A),
@@ -1889,26 +2373,6 @@ static struct pinmux_gpio pinmux_gpios[] = {
 	GPIO_FN(SIM_D_PORT22), /* SIM_D  Port 22/199 */
 	GPIO_FN(SIM_D_PORT199),
 
-	/* SDHI0 */
-	GPIO_FN(SDHI0_D0),	GPIO_FN(SDHI0_D1),	GPIO_FN(SDHI0_D2),
-	GPIO_FN(SDHI0_D3),	GPIO_FN(SDHI0_CD),	GPIO_FN(SDHI0_WP),
-	GPIO_FN(SDHI0_CMD),	GPIO_FN(SDHI0_CLK),
-
-	/* SDHI1 */
-	GPIO_FN(SDHI1_D0),	GPIO_FN(SDHI1_D1),	GPIO_FN(SDHI1_D2),
-	GPIO_FN(SDHI1_D3),	GPIO_FN(SDHI1_CD),	GPIO_FN(SDHI1_WP),
-	GPIO_FN(SDHI1_CMD),	GPIO_FN(SDHI1_CLK),
-
-	/* SDHI2 */
-	GPIO_FN(SDHI2_D0),	GPIO_FN(SDHI2_D1),	GPIO_FN(SDHI2_D2),
-	GPIO_FN(SDHI2_D3),	GPIO_FN(SDHI2_CLK),	GPIO_FN(SDHI2_CMD),
-
-	GPIO_FN(SDHI2_CD_PORT24), /* MSEL5CR_19_0 */
-	GPIO_FN(SDHI2_WP_PORT25),
-
-	GPIO_FN(SDHI2_WP_PORT177), /* MSEL5CR_19_1 */
-	GPIO_FN(SDHI2_CD_PORT202),
-
 	/* MSIOF2 */
 	GPIO_FN(MSIOF2_TXD),	GPIO_FN(MSIOF2_RXD),	GPIO_FN(MSIOF2_TSCK),
 	GPIO_FN(MSIOF2_SS2),	GPIO_FN(MSIOF2_TSYNC),	GPIO_FN(MSIOF2_SS1),
@@ -1953,21 +2417,6 @@ static struct pinmux_gpio pinmux_gpios[] = {
 	GPIO_FN(MEMC_WAIT),	GPIO_FN(MEMC_DREQ1),	GPIO_FN(MEMC_BUSCLK),
 	GPIO_FN(MEMC_A0),
 
-	/* MMC */
-	GPIO_FN(MMC0_D0_PORT68),	GPIO_FN(MMC0_D1_PORT69),
-	GPIO_FN(MMC0_D2_PORT70),	GPIO_FN(MMC0_D3_PORT71),
-	GPIO_FN(MMC0_D4_PORT72),	GPIO_FN(MMC0_D5_PORT73),
-	GPIO_FN(MMC0_D6_PORT74),	GPIO_FN(MMC0_D7_PORT75),
-	GPIO_FN(MMC0_CLK_PORT66),
-	GPIO_FN(MMC0_CMD_PORT67),	/* MSEL4CR_15_0 */
-
-	GPIO_FN(MMC1_D0_PORT149),	GPIO_FN(MMC1_D1_PORT148),
-	GPIO_FN(MMC1_D2_PORT147),	GPIO_FN(MMC1_D3_PORT146),
-	GPIO_FN(MMC1_D4_PORT145),	GPIO_FN(MMC1_D5_PORT144),
-	GPIO_FN(MMC1_D6_PORT143),	GPIO_FN(MMC1_D7_PORT142),
-	GPIO_FN(MMC1_CLK_PORT103),
-	GPIO_FN(MMC1_CMD_PORT104),	/* MSEL4CR_15_1 */
-
 	/* MSIOF0 */
 	GPIO_FN(MSIOF0_SS1),	GPIO_FN(MSIOF0_SS2),	GPIO_FN(MSIOF0_RXD),
 	GPIO_FN(MSIOF0_TXD),	GPIO_FN(MSIOF0_MCK0),	GPIO_FN(MSIOF0_MCK1),
@@ -2126,7 +2575,7 @@ static struct pinmux_gpio pinmux_gpios[] = {
 	GPIO_FN(TRACEAUD_FROM_MEMC),
 };
 
-static struct pinmux_cfg_reg pinmux_config_regs[] = {
+static const struct pinmux_cfg_reg pinmux_config_regs[] = {
 	PORTCR(0,	0xe6050000), /* PORT0CR */
 	PORTCR(1,	0xe6050001), /* PORT1CR */
 	PORTCR(2,	0xe6050002), /* PORT2CR */
@@ -2440,7 +2889,7 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = {
 	{ },
 };
 
-static struct pinmux_data_reg pinmux_data_regs[] = {
+static const struct pinmux_data_reg pinmux_data_regs[] = {
 	{ PINMUX_DATA_REG("PORTL031_000DR", 0xe6054800, 32) {
 		PORT31_DATA,	PORT30_DATA,	PORT29_DATA,	PORT28_DATA,
 		PORT27_DATA,	PORT26_DATA,	PORT25_DATA,	PORT24_DATA,
@@ -2544,46 +2993,43 @@ static struct pinmux_data_reg pinmux_data_regs[] = {
 	{ },
 };
 
-static struct pinmux_irq pinmux_irqs[] = {
-	PINMUX_IRQ(evt2irq(0x0200), PORT2_FN0,	 PORT13_FN0),	/* IRQ0A */
-	PINMUX_IRQ(evt2irq(0x0220), PORT20_FN0),		/* IRQ1A */
-	PINMUX_IRQ(evt2irq(0x0240), PORT11_FN0,	 PORT12_FN0),	/* IRQ2A */
-	PINMUX_IRQ(evt2irq(0x0260), PORT10_FN0,	 PORT14_FN0),	/* IRQ3A */
-	PINMUX_IRQ(evt2irq(0x0280), PORT15_FN0,	 PORT172_FN0),	/* IRQ4A */
-	PINMUX_IRQ(evt2irq(0x02A0), PORT0_FN0,	 PORT1_FN0),	/* IRQ5A */
-	PINMUX_IRQ(evt2irq(0x02C0), PORT121_FN0, PORT173_FN0),	/* IRQ6A */
-	PINMUX_IRQ(evt2irq(0x02E0), PORT120_FN0, PORT209_FN0),	/* IRQ7A */
-	PINMUX_IRQ(evt2irq(0x0300), PORT119_FN0),		/* IRQ8A */
-	PINMUX_IRQ(evt2irq(0x0320), PORT118_FN0, PORT210_FN0),	/* IRQ9A */
-	PINMUX_IRQ(evt2irq(0x0340), PORT19_FN0),		/* IRQ10A */
-	PINMUX_IRQ(evt2irq(0x0360), PORT104_FN0),		/* IRQ11A */
-	PINMUX_IRQ(evt2irq(0x0380), PORT42_FN0,	 PORT97_FN0),	/* IRQ12A */
-	PINMUX_IRQ(evt2irq(0x03A0), PORT64_FN0,	 PORT98_FN0),	/* IRQ13A */
-	PINMUX_IRQ(evt2irq(0x03C0), PORT63_FN0,	 PORT99_FN0),	/* IRQ14A */
-	PINMUX_IRQ(evt2irq(0x03E0), PORT62_FN0,	 PORT100_FN0),	/* IRQ15A */
-	PINMUX_IRQ(evt2irq(0x3200), PORT68_FN0,	 PORT211_FN0),	/* IRQ16A */
-	PINMUX_IRQ(evt2irq(0x3220), PORT69_FN0),		/* IRQ17A */
-	PINMUX_IRQ(evt2irq(0x3240), PORT70_FN0),		/* IRQ18A */
-	PINMUX_IRQ(evt2irq(0x3260), PORT71_FN0),		/* IRQ19A */
-	PINMUX_IRQ(evt2irq(0x3280), PORT67_FN0),		/* IRQ20A */
-	PINMUX_IRQ(evt2irq(0x32A0), PORT202_FN0),		/* IRQ21A */
-	PINMUX_IRQ(evt2irq(0x32C0), PORT95_FN0),		/* IRQ22A */
-	PINMUX_IRQ(evt2irq(0x32E0), PORT96_FN0),		/* IRQ23A */
-	PINMUX_IRQ(evt2irq(0x3300), PORT180_FN0),		/* IRQ24A */
-	PINMUX_IRQ(evt2irq(0x3320), PORT38_FN0),		/* IRQ25A */
-	PINMUX_IRQ(evt2irq(0x3340), PORT58_FN0,	 PORT81_FN0),	/* IRQ26A */
-	PINMUX_IRQ(evt2irq(0x3360), PORT57_FN0,	 PORT168_FN0),	/* IRQ27A */
-	PINMUX_IRQ(evt2irq(0x3380), PORT56_FN0,	 PORT169_FN0),	/* IRQ28A */
-	PINMUX_IRQ(evt2irq(0x33A0), PORT50_FN0,	 PORT170_FN0),	/* IRQ29A */
-	PINMUX_IRQ(evt2irq(0x33C0), PORT49_FN0,	 PORT171_FN0),	/* IRQ30A */
-	PINMUX_IRQ(evt2irq(0x33E0), PORT41_FN0,	 PORT167_FN0),	/* IRQ31A */
-};
-
-struct sh_pfc_soc_info r8a7740_pinmux_info = {
+static const struct pinmux_irq pinmux_irqs[] = {
+	PINMUX_IRQ(irq_pin(0), GPIO_PORT2,   GPIO_PORT13),	/* IRQ0A */
+	PINMUX_IRQ(irq_pin(1), GPIO_PORT20),		/* IRQ1A */
+	PINMUX_IRQ(irq_pin(2), GPIO_PORT11,  GPIO_PORT12),	/* IRQ2A */
+	PINMUX_IRQ(irq_pin(3), GPIO_PORT10,  GPIO_PORT14),	/* IRQ3A */
+	PINMUX_IRQ(irq_pin(4), GPIO_PORT15,  GPIO_PORT172),/* IRQ4A */
+	PINMUX_IRQ(irq_pin(5), GPIO_PORT0,   GPIO_PORT1),	/* IRQ5A */
+	PINMUX_IRQ(irq_pin(6), GPIO_PORT121, GPIO_PORT173),/* IRQ6A */
+	PINMUX_IRQ(irq_pin(7), GPIO_PORT120, GPIO_PORT209),/* IRQ7A */
+	PINMUX_IRQ(irq_pin(8), GPIO_PORT119),		/* IRQ8A */
+	PINMUX_IRQ(irq_pin(9), GPIO_PORT118, GPIO_PORT210),/* IRQ9A */
+	PINMUX_IRQ(irq_pin(10), GPIO_PORT19),		/* IRQ10A */
+	PINMUX_IRQ(irq_pin(11), GPIO_PORT104),		/* IRQ11A */
+	PINMUX_IRQ(irq_pin(12), GPIO_PORT42,  GPIO_PORT97),	/* IRQ12A */
+	PINMUX_IRQ(irq_pin(13), GPIO_PORT64,  GPIO_PORT98),	/* IRQ13A */
+	PINMUX_IRQ(irq_pin(14), GPIO_PORT63,  GPIO_PORT99),	/* IRQ14A */
+	PINMUX_IRQ(irq_pin(15), GPIO_PORT62,  GPIO_PORT100),/* IRQ15A */
+	PINMUX_IRQ(irq_pin(16), GPIO_PORT68,  GPIO_PORT211),/* IRQ16A */
+	PINMUX_IRQ(irq_pin(17), GPIO_PORT69),		/* IRQ17A */
+	PINMUX_IRQ(irq_pin(18), GPIO_PORT70),		/* IRQ18A */
+	PINMUX_IRQ(irq_pin(19), GPIO_PORT71),		/* IRQ19A */
+	PINMUX_IRQ(irq_pin(20), GPIO_PORT67),		/* IRQ20A */
+	PINMUX_IRQ(irq_pin(21), GPIO_PORT202),		/* IRQ21A */
+	PINMUX_IRQ(irq_pin(22), GPIO_PORT95),		/* IRQ22A */
+	PINMUX_IRQ(irq_pin(23), GPIO_PORT96),		/* IRQ23A */
+	PINMUX_IRQ(irq_pin(24), GPIO_PORT180),		/* IRQ24A */
+	PINMUX_IRQ(irq_pin(25), GPIO_PORT38),		/* IRQ25A */
+	PINMUX_IRQ(irq_pin(26), GPIO_PORT58,  GPIO_PORT81),	/* IRQ26A */
+	PINMUX_IRQ(irq_pin(27), GPIO_PORT57,  GPIO_PORT168),/* IRQ27A */
+	PINMUX_IRQ(irq_pin(28), GPIO_PORT56,  GPIO_PORT169),/* IRQ28A */
+	PINMUX_IRQ(irq_pin(29), GPIO_PORT50,  GPIO_PORT170),/* IRQ29A */
+	PINMUX_IRQ(irq_pin(30), GPIO_PORT49,  GPIO_PORT171),/* IRQ30A */
+	PINMUX_IRQ(irq_pin(31), GPIO_PORT41,  GPIO_PORT167),/* IRQ31A */
+};
+
+const struct sh_pfc_soc_info r8a7740_pinmux_info = {
 	.name		= "r8a7740_pfc",
-	.reserved_id	= PINMUX_RESERVED,
-	.data		= { PINMUX_DATA_BEGIN,
-			    PINMUX_DATA_END },
 	.input		= { PINMUX_INPUT_BEGIN,
 			    PINMUX_INPUT_END },
 	.input_pu	= { PINMUX_INPUT_PULLUP_BEGIN,
@@ -2592,15 +3038,19 @@ struct sh_pfc_soc_info r8a7740_pinmux_info = {
 			    PINMUX_INPUT_PULLDOWN_END },
 	.output		= { PINMUX_OUTPUT_BEGIN,
 			    PINMUX_OUTPUT_END },
-	.mark		= { PINMUX_MARK_BEGIN,
-			    PINMUX_MARK_END },
 	.function	= { PINMUX_FUNCTION_BEGIN,
 			    PINMUX_FUNCTION_END },
 
-	.first_gpio	= GPIO_PORT0,
-	.last_gpio	= GPIO_FN_TRACEAUD_FROM_MEMC,
+	.pins		= pinmux_pins,
+	.nr_pins	= ARRAY_SIZE(pinmux_pins),
+	.groups		= pinmux_groups,
+	.nr_groups	= ARRAY_SIZE(pinmux_groups),
+	.functions	= pinmux_functions,
+	.nr_functions	= ARRAY_SIZE(pinmux_functions),
+
+	.func_gpios	= pinmux_func_gpios,
+	.nr_func_gpios	= ARRAY_SIZE(pinmux_func_gpios),
 
-	.gpios		= pinmux_gpios,
 	.cfg_regs	= pinmux_config_regs,
 	.data_regs	= pinmux_data_regs,
 
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7779.c b/drivers/pinctrl/sh-pfc/pfc-r8a7779.c
index 13feaa0..62dcdcd 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a7779.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a7779.c
@@ -19,57 +19,77 @@
  */
 
 #include <linux/kernel.h>
-#include <mach/r8a7779.h>
 
 #include "sh_pfc.h"
 
-#define CPU_32_PORT(fn, pfx, sfx)				\
-	PORT_10(fn, pfx, sfx), PORT_10(fn, pfx##1, sfx),	\
-	PORT_10(fn, pfx##2, sfx), PORT_1(fn, pfx##30, sfx),	\
-	PORT_1(fn, pfx##31, sfx)
-
-#define CPU_32_PORT6(fn, pfx, sfx)				\
-	PORT_1(fn, pfx##0, sfx), PORT_1(fn, pfx##1, sfx),	\
-	PORT_1(fn, pfx##2, sfx), PORT_1(fn, pfx##3, sfx),	\
-	PORT_1(fn, pfx##4, sfx), PORT_1(fn, pfx##5, sfx),	\
-	PORT_1(fn, pfx##6, sfx), PORT_1(fn, pfx##7, sfx),	\
-	PORT_1(fn, pfx##8, sfx)
-
-#define CPU_ALL_PORT(fn, pfx, sfx)				\
-	CPU_32_PORT(fn, pfx##_0_, sfx),				\
-	CPU_32_PORT(fn, pfx##_1_, sfx),				\
-	CPU_32_PORT(fn, pfx##_2_, sfx),				\
-	CPU_32_PORT(fn, pfx##_3_, sfx),				\
-	CPU_32_PORT(fn, pfx##_4_, sfx),				\
-	CPU_32_PORT(fn, pfx##_5_, sfx),				\
-	CPU_32_PORT6(fn, pfx##_6_, sfx)
-
-#define _GP_GPIO(pfx, sfx) PINMUX_GPIO(GPIO_GP##pfx, GP##pfx##_DATA)
-#define _GP_DATA(pfx, sfx) PINMUX_DATA(GP##pfx##_DATA, GP##pfx##_FN,	\
-				       GP##pfx##_IN, GP##pfx##_OUT)
-
-#define _GP_INOUTSEL(pfx, sfx) GP##pfx##_IN, GP##pfx##_OUT
-#define _GP_INDT(pfx, sfx) GP##pfx##_DATA
-
-#define GP_ALL(str)	CPU_ALL_PORT(_PORT_ALL, GP, str)
-#define PINMUX_GPIO_GP_ALL()	CPU_ALL_PORT(_GP_GPIO, , unused)
-#define PINMUX_DATA_GP_ALL()	CPU_ALL_PORT(_GP_DATA, , unused)
-
-
-#define PORT_10_REV(fn, pfx, sfx)				\
-	PORT_1(fn, pfx##9, sfx), PORT_1(fn, pfx##8, sfx),	\
-	PORT_1(fn, pfx##7, sfx), PORT_1(fn, pfx##6, sfx),	\
-	PORT_1(fn, pfx##5, sfx), PORT_1(fn, pfx##4, sfx),	\
-	PORT_1(fn, pfx##3, sfx), PORT_1(fn, pfx##2, sfx),	\
-	PORT_1(fn, pfx##1, sfx), PORT_1(fn, pfx##0, sfx)
-
-#define CPU_32_PORT_REV(fn, pfx, sfx)					\
-	PORT_1(fn, pfx##31, sfx), PORT_1(fn, pfx##30, sfx),		\
-	PORT_10_REV(fn, pfx##2, sfx), PORT_10_REV(fn, pfx##1, sfx),	\
-	PORT_10_REV(fn, pfx, sfx)
-
-#define GP_INOUTSEL(bank) CPU_32_PORT_REV(_GP_INOUTSEL, _##bank##_, unused)
-#define GP_INDT(bank) CPU_32_PORT_REV(_GP_INDT, _##bank##_, unused)
+#define PORT_GP_1(bank, pin, fn, sfx) fn(bank, pin, GP_##bank##_##pin, sfx)
+
+#define PORT_GP_32(bank, fn, sfx)					\
+	PORT_GP_1(bank, 0,  fn, sfx), PORT_GP_1(bank, 1,  fn, sfx),	\
+	PORT_GP_1(bank, 2,  fn, sfx), PORT_GP_1(bank, 3,  fn, sfx),	\
+	PORT_GP_1(bank, 4,  fn, sfx), PORT_GP_1(bank, 5,  fn, sfx),	\
+	PORT_GP_1(bank, 6,  fn, sfx), PORT_GP_1(bank, 7,  fn, sfx),	\
+	PORT_GP_1(bank, 8,  fn, sfx), PORT_GP_1(bank, 9,  fn, sfx),	\
+	PORT_GP_1(bank, 10, fn, sfx), PORT_GP_1(bank, 11, fn, sfx),	\
+	PORT_GP_1(bank, 12, fn, sfx), PORT_GP_1(bank, 13, fn, sfx),	\
+	PORT_GP_1(bank, 14, fn, sfx), PORT_GP_1(bank, 15, fn, sfx),	\
+	PORT_GP_1(bank, 16, fn, sfx), PORT_GP_1(bank, 17, fn, sfx),	\
+	PORT_GP_1(bank, 18, fn, sfx), PORT_GP_1(bank, 19, fn, sfx),	\
+	PORT_GP_1(bank, 20, fn, sfx), PORT_GP_1(bank, 21, fn, sfx),	\
+	PORT_GP_1(bank, 22, fn, sfx), PORT_GP_1(bank, 23, fn, sfx),	\
+	PORT_GP_1(bank, 24, fn, sfx), PORT_GP_1(bank, 25, fn, sfx),	\
+	PORT_GP_1(bank, 26, fn, sfx), PORT_GP_1(bank, 27, fn, sfx),	\
+	PORT_GP_1(bank, 28, fn, sfx), PORT_GP_1(bank, 29, fn, sfx),	\
+	PORT_GP_1(bank, 30, fn, sfx), PORT_GP_1(bank, 31, fn, sfx)
+
+#define PORT_GP_32_9(bank, fn, sfx)					\
+	PORT_GP_1(bank, 0, fn, sfx), PORT_GP_1(bank, 1, fn, sfx),	\
+	PORT_GP_1(bank, 2, fn, sfx), PORT_GP_1(bank, 3, fn, sfx),	\
+	PORT_GP_1(bank, 4, fn, sfx), PORT_GP_1(bank, 5, fn, sfx),	\
+	PORT_GP_1(bank, 6, fn, sfx), PORT_GP_1(bank, 7, fn, sfx),	\
+	PORT_GP_1(bank, 8, fn, sfx)
+
+#define PORT_GP_32_REV(bank, fn, sfx)					\
+	PORT_GP_1(bank, 31, fn, sfx), PORT_GP_1(bank, 30, fn, sfx),	\
+	PORT_GP_1(bank, 29, fn, sfx), PORT_GP_1(bank, 28, fn, sfx),	\
+	PORT_GP_1(bank, 27, fn, sfx), PORT_GP_1(bank, 26, fn, sfx),	\
+	PORT_GP_1(bank, 25, fn, sfx), PORT_GP_1(bank, 24, fn, sfx),	\
+	PORT_GP_1(bank, 23, fn, sfx), PORT_GP_1(bank, 22, fn, sfx),	\
+	PORT_GP_1(bank, 21, fn, sfx), PORT_GP_1(bank, 20, fn, sfx),	\
+	PORT_GP_1(bank, 19, fn, sfx), PORT_GP_1(bank, 18, fn, sfx),	\
+	PORT_GP_1(bank, 17, fn, sfx), PORT_GP_1(bank, 16, fn, sfx),	\
+	PORT_GP_1(bank, 15, fn, sfx), PORT_GP_1(bank, 14, fn, sfx),	\
+	PORT_GP_1(bank, 13, fn, sfx), PORT_GP_1(bank, 12, fn, sfx),	\
+	PORT_GP_1(bank, 11, fn, sfx), PORT_GP_1(bank, 10, fn, sfx),	\
+	PORT_GP_1(bank, 9,  fn, sfx), PORT_GP_1(bank, 8,  fn, sfx),	\
+	PORT_GP_1(bank, 7,  fn, sfx), PORT_GP_1(bank, 6,  fn, sfx),	\
+	PORT_GP_1(bank, 5,  fn, sfx), PORT_GP_1(bank, 4,  fn, sfx),	\
+	PORT_GP_1(bank, 3,  fn, sfx), PORT_GP_1(bank, 2,  fn, sfx),	\
+	PORT_GP_1(bank, 1,  fn, sfx), PORT_GP_1(bank, 0,  fn, sfx)
+
+#define CPU_ALL_PORT(fn, sfx)						\
+	PORT_GP_32(0, fn, sfx),						\
+	PORT_GP_32(1, fn, sfx),						\
+	PORT_GP_32(2, fn, sfx),						\
+	PORT_GP_32(3, fn, sfx),						\
+	PORT_GP_32(4, fn, sfx),						\
+	PORT_GP_32(5, fn, sfx),						\
+	PORT_GP_32_9(6, fn, sfx)
+
+#define _GP_PORT_ALL(bank, pin, name, sfx)	name##_##sfx
+
+#define _GP_GPIO(bank, pin, _name, sfx)					\
+	[(bank * 32) + pin] = {						\
+		.name = __stringify(_name),				\
+		.enum_id = _name##_DATA,				\
+	}
+
+#define _GP_DATA(bank, pin, name, sfx)					\
+	PINMUX_DATA(name##_DATA, name##_FN)
+
+#define GP_ALL(str)		CPU_ALL_PORT(_GP_PORT_ALL, str)
+#define PINMUX_GPIO_GP_ALL()	CPU_ALL_PORT(_GP_GPIO, unused)
+#define PINMUX_DATA_GP_ALL()	CPU_ALL_PORT(_GP_DATA, unused)
 
 #define PINMUX_IPSR_DATA(ipsr, fn) PINMUX_DATA(fn##_MARK, FN_##ipsr, FN_##fn)
 #define PINMUX_IPSR_MODSEL_DATA(ipsr, fn, ms) PINMUX_DATA(fn##_MARK, FN_##ms, \
@@ -82,14 +102,6 @@ enum {
 	GP_ALL(DATA), /* GP_0_0_DATA -> GP_6_8_DATA */
 	PINMUX_DATA_END,
 
-	PINMUX_INPUT_BEGIN,
-	GP_ALL(IN), /* GP_0_0_IN -> GP_6_8_IN */
-	PINMUX_INPUT_END,
-
-	PINMUX_OUTPUT_BEGIN,
-	GP_ALL(OUT), /* GP_0_0_OUT -> GP_6_8_OUT */
-	PINMUX_OUTPUT_END,
-
 	PINMUX_FUNCTION_BEGIN,
 	GP_ALL(FN), /* GP_0_0_FN -> GP_6_8_FN */
 
@@ -371,7 +383,7 @@ enum {
 	FN_VI1_DATA6_VI1_B6, FN_SD2_CD, FN_MT0_VCXO, FN_SPA_TMS,
 	FN_HSPI_TX1_D, FN_VI1_DATA7_VI1_B7, FN_SD2_WP, FN_MT0_PWM,
 	FN_SPA_TDI, FN_HSPI_RX1_D, FN_VI1_G0, FN_VI3_DATA0,
-	FN_DU1_DOTCLKOUT1, FN_TS_SCK1, FN_DREQ2_B, FN_TX2,
+	FN_TS_SCK1, FN_DREQ2_B, FN_TX2,
 	FN_SPA_TDO, FN_HCTS0_B, FN_VI1_G1, FN_VI3_DATA1,
 	FN_SSI_SCK1, FN_TS_SDEN1, FN_DACK2_B, FN_RX2, FN_HRTS0_B,
 
@@ -447,7 +459,8 @@ enum {
 	A0_MARK, SD1_DAT3_MARK, MMC0_D3_MARK, FD3_MARK,
 	BS_MARK, SD1_DAT2_MARK, MMC0_D2_MARK, FD2_MARK,
 	ATADIR0_MARK, SDSELF_MARK, HCTS1_MARK, TX4_C_MARK,
-	USB_PENC2_MARK, SCK0_MARK, PWM1_MARK, PWMFSW0_MARK,
+	USB_PENC0_MARK, USB_PENC1_MARK, USB_PENC2_MARK,
+	SCK0_MARK, PWM1_MARK, PWMFSW0_MARK,
 	SCIF_CLK_MARK, TCLK0_C_MARK,
 
 	EX_CS0_MARK, RX3_C_IRDA_RX_C_MARK, MMC0_D6_MARK,
@@ -632,7 +645,7 @@ enum {
 	HSPI_CS1_D_MARK, ADICHS2_B_MARK, VI1_DATA6_VI1_B6_MARK, SD2_CD_MARK,
 	MT0_VCXO_MARK, SPA_TMS_MARK, HSPI_TX1_D_MARK, VI1_DATA7_VI1_B7_MARK,
 	SD2_WP_MARK, MT0_PWM_MARK, SPA_TDI_MARK, HSPI_RX1_D_MARK,
-	VI1_G0_MARK, VI3_DATA0_MARK, DU1_DOTCLKOUT1_MARK, TS_SCK1_MARK,
+	VI1_G0_MARK, VI3_DATA0_MARK, TS_SCK1_MARK,
 	DREQ2_B_MARK, TX2_MARK,	SPA_TDO_MARK, HCTS0_B_MARK,
 	VI1_G1_MARK, VI3_DATA1_MARK, SSI_SCK1_MARK, TS_SDEN1_MARK,
 	DACK2_B_MARK, RX2_MARK, HRTS0_B_MARK,
@@ -649,7 +662,7 @@ enum {
 	PINMUX_MARK_END,
 };
 
-static pinmux_enum_t pinmux_data[] = {
+static const pinmux_enum_t pinmux_data[] = {
 	PINMUX_DATA_GP_ALL(), /* PINMUX_DATA(GP_M_N_DATA, GP_M_N_FN...), */
 
 	PINMUX_DATA(AVS1_MARK, FN_AVS1),
@@ -658,6 +671,9 @@ static pinmux_enum_t pinmux_data[] = {
 	PINMUX_DATA(A18_MARK, FN_A18),
 	PINMUX_DATA(A19_MARK, FN_A19),
 
+	PINMUX_DATA(USB_PENC0_MARK, FN_USB_PENC0),
+	PINMUX_DATA(USB_PENC1_MARK, FN_USB_PENC1),
+
 	PINMUX_IPSR_DATA(IP0_2_0, USB_PENC2),
 	PINMUX_IPSR_MODSEL_DATA(IP0_2_0, SCK0, SEL_SCIF0_0),
 	PINMUX_IPSR_DATA(IP0_2_0, PWM1),
@@ -1399,7 +1415,6 @@ static pinmux_enum_t pinmux_data[] = {
 	PINMUX_IPSR_MODSEL_DATA(IP11_23_21, HSPI_RX1_D, SEL_HSPI1_3),
 	PINMUX_IPSR_DATA(IP11_26_24, VI1_G0),
 	PINMUX_IPSR_DATA(IP11_26_24, VI3_DATA0),
-	PINMUX_IPSR_DATA(IP11_26_24, DU1_DOTCLKOUT1),
 	PINMUX_IPSR_DATA(IP11_26_24, TS_SCK1),
 	PINMUX_IPSR_MODSEL_DATA(IP11_26_24, DREQ2_B, SEL_EXBUS2_1),
 	PINMUX_IPSR_DATA(IP11_26_24, TX2),
@@ -1450,280 +1465,1260 @@ static pinmux_enum_t pinmux_data[] = {
 	PINMUX_IPSR_MODSEL_DATA(IP12_17_15, SCK4_B, SEL_SCIF4_1),
 };
 
-static struct pinmux_gpio pinmux_gpios[] = {
+static struct sh_pfc_pin pinmux_pins[] = {
 	PINMUX_GPIO_GP_ALL(),
-	GPIO_FN(AVS1), GPIO_FN(AVS2), GPIO_FN(A17), GPIO_FN(A18),
-	GPIO_FN(A19),
+};
 
-	/* IPSR0 */
-	GPIO_FN(USB_PENC2), GPIO_FN(SCK0), GPIO_FN(PWM1), GPIO_FN(PWMFSW0),
-	GPIO_FN(SCIF_CLK), GPIO_FN(TCLK0_C), GPIO_FN(BS), GPIO_FN(SD1_DAT2),
-	GPIO_FN(MMC0_D2), GPIO_FN(FD2), GPIO_FN(ATADIR0), GPIO_FN(SDSELF),
-	GPIO_FN(HCTS1), GPIO_FN(TX4_C), GPIO_FN(A0), GPIO_FN(SD1_DAT3),
-	GPIO_FN(MMC0_D3), GPIO_FN(FD3), GPIO_FN(A20), GPIO_FN(TX5_D),
-	GPIO_FN(HSPI_TX2_B), GPIO_FN(A21), GPIO_FN(SCK5_D),
-	GPIO_FN(HSPI_CLK2_B), GPIO_FN(A22), GPIO_FN(RX5_D),
-	GPIO_FN(HSPI_RX2_B), GPIO_FN(VI1_R0), GPIO_FN(A23), GPIO_FN(FCLE),
-	GPIO_FN(HSPI_CLK2), GPIO_FN(VI1_R1), GPIO_FN(A24), GPIO_FN(SD1_CD),
-	GPIO_FN(MMC0_D4), GPIO_FN(FD4),	GPIO_FN(HSPI_CS2), GPIO_FN(VI1_R2),
-	GPIO_FN(SSI_WS78_B), GPIO_FN(A25), GPIO_FN(SD1_WP), GPIO_FN(MMC0_D5),
-	GPIO_FN(FD5), GPIO_FN(HSPI_RX2), GPIO_FN(VI1_R3), GPIO_FN(TX5_B),
-	GPIO_FN(SSI_SDATA7_B), GPIO_FN(CTS0_B), GPIO_FN(CLKOUT),
-	GPIO_FN(TX3C_IRDA_TX_C), GPIO_FN(PWM0_B), GPIO_FN(CS0),
-	GPIO_FN(HSPI_CS2_B), GPIO_FN(CS1_A26), GPIO_FN(HSPI_TX2),
-	GPIO_FN(SDSELF_B), GPIO_FN(RD_WR), GPIO_FN(FWE), GPIO_FN(ATAG0),
-	GPIO_FN(VI1_R7), GPIO_FN(HRTS1), GPIO_FN(RX4_C),
+/* - DU0 -------------------------------------------------------------------- */
+static const unsigned int du0_rgb666_pins[] = {
+	/* R[7:2], G[7:2], B[7:2] */
+	188, 187, 186, 185, 184, 183,
+	194, 193, 192, 191, 190, 189,
+	200, 199, 198, 197, 196, 195,
+};
+static const unsigned int du0_rgb666_mux[] = {
+	DU0_DR7_MARK, DU0_DR6_MARK, DU0_DR5_MARK, DU0_DR4_MARK,
+	DU0_DR3_MARK, DU0_DR2_MARK,
+	DU0_DG7_MARK, DU0_DG6_MARK, DU0_DG5_MARK, DU0_DG4_MARK,
+	DU0_DG3_MARK, DU0_DG2_MARK,
+	DU0_DB7_MARK, DU0_DB6_MARK, DU0_DB5_MARK, DU0_DB4_MARK,
+	DU0_DB3_MARK, DU0_DB2_MARK,
+};
+static const unsigned int du0_rgb888_pins[] = {
+	/* R[7:0], G[7:0], B[7:0] */
+	188, 187, 186, 185, 184, 183, 24, 23,
+	194, 193, 192, 191, 190, 189, 26, 25,
+	200, 199, 198, 197, 196, 195, 28, 27,
+};
+static const unsigned int du0_rgb888_mux[] = {
+	DU0_DR7_MARK, DU0_DR6_MARK, DU0_DR5_MARK, DU0_DR4_MARK,
+	DU0_DR3_MARK, DU0_DR2_MARK, DU0_DR1_MARK, DU0_DR0_MARK,
+	DU0_DG7_MARK, DU0_DG6_MARK, DU0_DG5_MARK, DU0_DG4_MARK,
+	DU0_DG3_MARK, DU0_DG2_MARK, DU0_DG1_MARK, DU0_DG0_MARK,
+	DU0_DB7_MARK, DU0_DB6_MARK, DU0_DB5_MARK, DU0_DB4_MARK,
+	DU0_DB3_MARK, DU0_DB2_MARK, DU0_DB1_MARK, DU0_DB0_MARK,
+};
+static const unsigned int du0_clk_in_pins[] = {
+	/* CLKIN */
+	29,
+};
+static const unsigned int du0_clk_in_mux[] = {
+	DU0_DOTCLKIN_MARK,
+};
+static const unsigned int du0_clk_out_0_pins[] = {
+	/* CLKOUT */
+	180,
+};
+static const unsigned int du0_clk_out_0_mux[] = {
+	DU0_DOTCLKOUT0_MARK,
+};
+static const unsigned int du0_clk_out_1_pins[] = {
+	/* CLKOUT */
+	30,
+};
+static const unsigned int du0_clk_out_1_mux[] = {
+	DU0_DOTCLKOUT1_MARK,
+};
+static const unsigned int du0_sync_0_pins[] = {
+	/* VSYNC, HSYNC, DISP */
+	182, 181, 31,
+};
+static const unsigned int du0_sync_0_mux[] = {
+	DU0_EXHSYNC_DU0_HSYNC_MARK, DU0_EXVSYNC_DU0_VSYNC_MARK,
+	DU0_EXODDF_DU0_ODDF_DISP_CDE_MARK
+};
+static const unsigned int du0_sync_1_pins[] = {
+	/* VSYNC, HSYNC, DISP */
+	182, 181, 32,
+};
+static const unsigned int du0_sync_1_mux[] = {
+	DU0_EXHSYNC_DU0_HSYNC_MARK, DU0_EXVSYNC_DU0_VSYNC_MARK,
+	DU0_DISP_MARK
+};
+static const unsigned int du0_oddf_pins[] = {
+	/* ODDF */
+	31,
+};
+static const unsigned int du0_oddf_mux[] = {
+	DU0_EXODDF_DU0_ODDF_DISP_CDE_MARK
+};
+static const unsigned int du0_cde_pins[] = {
+	/* CDE */
+	33,
+};
+static const unsigned int du0_cde_mux[] = {
+	DU0_CDE_MARK
+};
+/* - DU1 -------------------------------------------------------------------- */
+static const unsigned int du1_rgb666_pins[] = {
+	/* R[7:2], G[7:2], B[7:2] */
+	41, 40, 39, 38, 37, 36,
+	49, 48, 47, 46, 45, 44,
+	57, 56, 55, 54, 53, 52,
+};
+static const unsigned int du1_rgb666_mux[] = {
+	DU1_DR7_MARK, DU1_DR6_MARK, DU1_DR5_MARK, DU1_DR4_MARK,
+	DU1_DR3_MARK, DU1_DR2_MARK,
+	DU1_DG7_MARK, DU1_DG6_MARK, DU1_DG5_MARK, DU1_DG4_MARK,
+	DU1_DG3_MARK, DU1_DG2_MARK,
+	DU1_DB7_MARK, DU1_DB6_MARK, DU1_DB5_MARK, DU1_DB4_MARK,
+	DU1_DB3_MARK, DU1_DB2_MARK,
+};
+static const unsigned int du1_rgb888_pins[] = {
+	/* R[7:0], G[7:0], B[7:0] */
+	41, 40, 39, 38, 37, 36, 35, 34,
+	49, 48, 47, 46, 45, 44, 43, 32,
+	57, 56, 55, 54, 53, 52, 51, 50,
+};
+static const unsigned int du1_rgb888_mux[] = {
+	DU1_DR7_MARK, DU1_DR6_MARK, DU1_DR5_MARK, DU1_DR4_MARK,
+	DU1_DR3_MARK, DU1_DR2_MARK, DU1_DR1_MARK, DU1_DR0_MARK,
+	DU1_DG7_MARK, DU1_DG6_MARK, DU1_DG5_MARK, DU1_DG4_MARK,
+	DU1_DG3_MARK, DU1_DG2_MARK, DU1_DG1_MARK, DU1_DG0_MARK,
+	DU1_DB7_MARK, DU1_DB6_MARK, DU1_DB5_MARK, DU1_DB4_MARK,
+	DU1_DB3_MARK, DU1_DB2_MARK, DU1_DB1_MARK, DU1_DB0_MARK,
+};
+static const unsigned int du1_clk_in_pins[] = {
+	/* CLKIN */
+	58,
+};
+static const unsigned int du1_clk_in_mux[] = {
+	DU1_DOTCLKIN_MARK,
+};
+static const unsigned int du1_clk_out_pins[] = {
+	/* CLKOUT */
+	59,
+};
+static const unsigned int du1_clk_out_mux[] = {
+	DU1_DOTCLKOUT_MARK,
+};
+static const unsigned int du1_sync_0_pins[] = {
+	/* VSYNC, HSYNC, DISP */
+	61, 60, 62,
+};
+static const unsigned int du1_sync_0_mux[] = {
+	DU1_EXVSYNC_DU1_VSYNC_MARK, DU1_EXHSYNC_DU1_HSYNC_MARK,
+	DU1_EXODDF_DU1_ODDF_DISP_CDE_MARK
+};
+static const unsigned int du1_sync_1_pins[] = {
+	/* VSYNC, HSYNC, DISP */
+	61, 60, 63,
+};
+static const unsigned int du1_sync_1_mux[] = {
+	DU1_EXVSYNC_DU1_VSYNC_MARK, DU1_EXHSYNC_DU1_HSYNC_MARK,
+	DU1_DISP_MARK
+};
+static const unsigned int du1_oddf_pins[] = {
+	/* ODDF */
+	62,
+};
+static const unsigned int du1_oddf_mux[] = {
+	DU1_EXODDF_DU1_ODDF_DISP_CDE_MARK
+};
+static const unsigned int du1_cde_pins[] = {
+	/* CDE */
+	64,
+};
+static const unsigned int du1_cde_mux[] = {
+	DU1_CDE_MARK
+};
+/* - HSPI0 ------------------------------------------------------------------ */
+static const unsigned int hspi0_pins[] = {
+	/* CLK, CS, RX, TX */
+	150, 151, 153, 152,
+};
+static const unsigned int hspi0_mux[] = {
+	HSPI_CLK0_MARK, HSPI_CS0_MARK, HSPI_RX0_MARK, HSPI_TX0_MARK,
+};
+/* - HSPI1 ------------------------------------------------------------------ */
+static const unsigned int hspi1_pins[] = {
+	/* CLK, CS, RX, TX */
+	63, 58, 64, 62,
+};
+static const unsigned int hspi1_mux[] = {
+	HSPI_CLK1_MARK, HSPI_CS1_MARK, HSPI_RX1_MARK, HSPI_TX1_MARK,
+};
+static const unsigned int hspi1_b_pins[] = {
+	/* CLK, CS, RX, TX */
+	90, 91, 93, 92,
+};
+static const unsigned int hspi1_b_mux[] = {
+	HSPI_CLK1_B_MARK, HSPI_CS1_B_MARK, HSPI_RX1_B_MARK, HSPI_TX1_B_MARK,
+};
+static const unsigned int hspi1_c_pins[] = {
+	/* CLK, CS, RX, TX */
+	141, 142, 144, 143,
+};
+static const unsigned int hspi1_c_mux[] = {
+	HSPI_CLK1_C_MARK, HSPI_CS1_C_MARK, HSPI_RX1_C_MARK, HSPI_TX1_C_MARK,
+};
+static const unsigned int hspi1_d_pins[] = {
+	/* CLK, CS, RX, TX */
+	101, 102, 104, 103,
+};
+static const unsigned int hspi1_d_mux[] = {
+	HSPI_CLK1_D_MARK, HSPI_CS1_D_MARK, HSPI_RX1_D_MARK, HSPI_TX1_D_MARK,
+};
+/* - HSPI2 ------------------------------------------------------------------ */
+static const unsigned int hspi2_pins[] = {
+	/* CLK, CS, RX, TX */
+	9, 10, 11, 14,
+};
+static const unsigned int hspi2_mux[] = {
+	HSPI_CLK2_MARK, HSPI_CS2_MARK, HSPI_RX2_MARK, HSPI_TX2_MARK,
+};
+static const unsigned int hspi2_b_pins[] = {
+	/* CLK, CS, RX, TX */
+	7, 13, 8, 6,
+};
+static const unsigned int hspi2_b_mux[] = {
+	HSPI_CLK2_B_MARK, HSPI_CS2_B_MARK, HSPI_RX2_B_MARK, HSPI_TX2_B_MARK,
+};
+/* - INTC ------------------------------------------------------------------- */
+static const unsigned int intc_irq0_pins[] = {
+	/* IRQ */
+	78,
+};
+static const unsigned int intc_irq0_mux[] = {
+	IRQ0_MARK,
+};
+static const unsigned int intc_irq0_b_pins[] = {
+	/* IRQ */
+	141,
+};
+static const unsigned int intc_irq0_b_mux[] = {
+	IRQ0_B_MARK,
+};
+static const unsigned int intc_irq1_pins[] = {
+	/* IRQ */
+	79,
+};
+static const unsigned int intc_irq1_mux[] = {
+	IRQ1_MARK,
+};
+static const unsigned int intc_irq1_b_pins[] = {
+	/* IRQ */
+	142,
+};
+static const unsigned int intc_irq1_b_mux[] = {
+	IRQ1_B_MARK,
+};
+static const unsigned int intc_irq2_pins[] = {
+	/* IRQ */
+	88,
+};
+static const unsigned int intc_irq2_mux[] = {
+	IRQ2_MARK,
+};
+static const unsigned int intc_irq2_b_pins[] = {
+	/* IRQ */
+	143,
+};
+static const unsigned int intc_irq2_b_mux[] = {
+	IRQ2_B_MARK,
+};
+static const unsigned int intc_irq3_pins[] = {
+	/* IRQ */
+	89,
+};
+static const unsigned int intc_irq3_mux[] = {
+	IRQ3_MARK,
+};
+static const unsigned int intc_irq3_b_pins[] = {
+	/* IRQ */
+	144,
+};
+static const unsigned int intc_irq3_b_mux[] = {
+	IRQ3_B_MARK,
+};
+/* - LSBC ------------------------------------------------------------------- */
+static const unsigned int lbsc_cs0_pins[] = {
+	/* CS */
+	13,
+};
+static const unsigned int lbsc_cs0_mux[] = {
+	CS0_MARK,
+};
+static const unsigned int lbsc_cs1_pins[] = {
+	/* CS */
+	14,
+};
+static const unsigned int lbsc_cs1_mux[] = {
+	CS1_A26_MARK,
+};
+static const unsigned int lbsc_ex_cs0_pins[] = {
+	/* CS */
+	15,
+};
+static const unsigned int lbsc_ex_cs0_mux[] = {
+	EX_CS0_MARK,
+};
+static const unsigned int lbsc_ex_cs1_pins[] = {
+	/* CS */
+	16,
+};
+static const unsigned int lbsc_ex_cs1_mux[] = {
+	EX_CS1_MARK,
+};
+static const unsigned int lbsc_ex_cs2_pins[] = {
+	/* CS */
+	17,
+};
+static const unsigned int lbsc_ex_cs2_mux[] = {
+	EX_CS2_MARK,
+};
+static const unsigned int lbsc_ex_cs3_pins[] = {
+	/* CS */
+	18,
+};
+static const unsigned int lbsc_ex_cs3_mux[] = {
+	EX_CS3_MARK,
+};
+static const unsigned int lbsc_ex_cs4_pins[] = {
+	/* CS */
+	19,
+};
+static const unsigned int lbsc_ex_cs4_mux[] = {
+	EX_CS4_MARK,
+};
+static const unsigned int lbsc_ex_cs5_pins[] = {
+	/* CS */
+	20,
+};
+static const unsigned int lbsc_ex_cs5_mux[] = {
+	EX_CS5_MARK,
+};
+/* - MMCIF ------------------------------------------------------------------ */
+static const unsigned int mmc0_data1_pins[] = {
+	/* D[0] */
+	19,
+};
+static const unsigned int mmc0_data1_mux[] = {
+	MMC0_D0_MARK,
+};
+static const unsigned int mmc0_data4_pins[] = {
+	/* D[0:3] */
+	19, 20, 21, 2,
+};
+static const unsigned int mmc0_data4_mux[] = {
+	MMC0_D0_MARK, MMC0_D1_MARK, MMC0_D2_MARK, MMC0_D3_MARK,
+};
+static const unsigned int mmc0_data8_pins[] = {
+	/* D[0:7] */
+	19, 20, 21, 2, 10, 11, 15, 16,
+};
+static const unsigned int mmc0_data8_mux[] = {
+	MMC0_D0_MARK, MMC0_D1_MARK, MMC0_D2_MARK, MMC0_D3_MARK,
+	MMC0_D4_MARK, MMC0_D5_MARK, MMC0_D6_MARK, MMC0_D7_MARK,
+};
+static const unsigned int mmc0_ctrl_pins[] = {
+	/* CMD, CLK */
+	18, 17,
+};
+static const unsigned int mmc0_ctrl_mux[] = {
+	MMC0_CMD_MARK, MMC0_CLK_MARK,
+};
+static const unsigned int mmc1_data1_pins[] = {
+	/* D[0] */
+	72,
+};
+static const unsigned int mmc1_data1_mux[] = {
+	MMC1_D0_MARK,
+};
+static const unsigned int mmc1_data4_pins[] = {
+	/* D[0:3] */
+	72, 73, 74, 75,
+};
+static const unsigned int mmc1_data4_mux[] = {
+	MMC1_D0_MARK, MMC1_D1_MARK, MMC1_D2_MARK, MMC1_D3_MARK,
+};
+static const unsigned int mmc1_data8_pins[] = {
+	/* D[0:7] */
+	72, 73, 74, 75, 76, 77, 80, 81,
+};
+static const unsigned int mmc1_data8_mux[] = {
+	MMC1_D0_MARK, MMC1_D1_MARK, MMC1_D2_MARK, MMC1_D3_MARK,
+	MMC1_D4_MARK, MMC1_D5_MARK, MMC1_D6_MARK, MMC1_D7_MARK,
+};
+static const unsigned int mmc1_ctrl_pins[] = {
+	/* CMD, CLK */
+	68, 65,
+};
+static const unsigned int mmc1_ctrl_mux[] = {
+	MMC1_CMD_MARK, MMC1_CLK_MARK,
+};
+/* - SCIF0 ------------------------------------------------------------------ */
+static const unsigned int scif0_data_pins[] = {
+	/* RXD, TXD */
+	153, 152,
+};
+static const unsigned int scif0_data_mux[] = {
+	RX0_MARK, TX0_MARK,
+};
+static const unsigned int scif0_clk_pins[] = {
+	/* SCK */
+	156,
+};
+static const unsigned int scif0_clk_mux[] = {
+	SCK0_MARK,
+};
+static const unsigned int scif0_ctrl_pins[] = {
+	/* RTS, CTS */
+	151, 150,
+};
+static const unsigned int scif0_ctrl_mux[] = {
+	RTS0_TANS_MARK, CTS0_MARK,
+};
+static const unsigned int scif0_data_b_pins[] = {
+	/* RXD, TXD */
+	20, 19,
+};
+static const unsigned int scif0_data_b_mux[] = {
+	RX0_B_MARK, TX0_B_MARK,
+};
+static const unsigned int scif0_clk_b_pins[] = {
+	/* SCK */
+	33,
+};
+static const unsigned int scif0_clk_b_mux[] = {
+	SCK0_B_MARK,
+};
+static const unsigned int scif0_ctrl_b_pins[] = {
+	/* RTS, CTS */
+	18, 11,
+};
+static const unsigned int scif0_ctrl_b_mux[] = {
+	RTS0_B_TANS_B_MARK, CTS0_B_MARK,
+};
+static const unsigned int scif0_data_c_pins[] = {
+	/* RXD, TXD */
+	146, 147,
+};
+static const unsigned int scif0_data_c_mux[] = {
+	RX0_C_MARK, TX0_C_MARK,
+};
+static const unsigned int scif0_clk_c_pins[] = {
+	/* SCK */
+	145,
+};
+static const unsigned int scif0_clk_c_mux[] = {
+	SCK0_C_MARK,
+};
+static const unsigned int scif0_ctrl_c_pins[] = {
+	/* RTS, CTS */
+	149, 148,
+};
+static const unsigned int scif0_ctrl_c_mux[] = {
+	RTS0_C_TANS_C_MARK, CTS0_C_MARK,
+};
+static const unsigned int scif0_data_d_pins[] = {
+	/* RXD, TXD */
+	43, 42,
+};
+static const unsigned int scif0_data_d_mux[] = {
+	RX0_D_MARK, TX0_D_MARK,
+};
+static const unsigned int scif0_clk_d_pins[] = {
+	/* SCK */
+	50,
+};
+static const unsigned int scif0_clk_d_mux[] = {
+	SCK0_D_MARK,
+};
+static const unsigned int scif0_ctrl_d_pins[] = {
+	/* RTS, CTS */
+	51, 35,
+};
+static const unsigned int scif0_ctrl_d_mux[] = {
+	RTS0_D_TANS_D_MARK, CTS0_D_MARK,
+};
+/* - SCIF1 ------------------------------------------------------------------ */
+static const unsigned int scif1_data_pins[] = {
+	/* RXD, TXD */
+	149, 148,
+};
+static const unsigned int scif1_data_mux[] = {
+	RX1_MARK, TX1_MARK,
+};
+static const unsigned int scif1_clk_pins[] = {
+	/* SCK */
+	145,
+};
+static const unsigned int scif1_clk_mux[] = {
+	SCK1_MARK,
+};
+static const unsigned int scif1_ctrl_pins[] = {
+	/* RTS, CTS */
+	147, 146,
+};
+static const unsigned int scif1_ctrl_mux[] = {
+	RTS1_TANS_MARK, CTS1_MARK,
+};
+static const unsigned int scif1_data_b_pins[] = {
+	/* RXD, TXD */
+	117, 114,
+};
+static const unsigned int scif1_data_b_mux[] = {
+	RX1_B_MARK, TX1_B_MARK,
+};
+static const unsigned int scif1_clk_b_pins[] = {
+	/* SCK */
+	113,
+};
+static const unsigned int scif1_clk_b_mux[] = {
+	SCK1_B_MARK,
+};
+static const unsigned int scif1_ctrl_b_pins[] = {
+	/* RTS, CTS */
+	115, 116,
+};
+static const unsigned int scif1_ctrl_b_mux[] = {
+	RTS1_B_TANS_B_MARK, CTS1_B_MARK,
+};
+static const unsigned int scif1_data_c_pins[] = {
+	/* RXD, TXD */
+	67, 66,
+};
+static const unsigned int scif1_data_c_mux[] = {
+	RX1_C_MARK, TX1_C_MARK,
+};
+static const unsigned int scif1_clk_c_pins[] = {
+	/* SCK */
+	86,
+};
+static const unsigned int scif1_clk_c_mux[] = {
+	SCK1_C_MARK,
+};
+static const unsigned int scif1_ctrl_c_pins[] = {
+	/* RTS, CTS */
+	69, 68,
+};
+static const unsigned int scif1_ctrl_c_mux[] = {
+	RTS1_C_TANS_C_MARK, CTS1_C_MARK,
+};
+/* - SCIF2 ------------------------------------------------------------------ */
+static const unsigned int scif2_data_pins[] = {
+	/* RXD, TXD */
+	106, 105,
+};
+static const unsigned int scif2_data_mux[] = {
+	RX2_MARK, TX2_MARK,
+};
+static const unsigned int scif2_clk_pins[] = {
+	/* SCK */
+	107,
+};
+static const unsigned int scif2_clk_mux[] = {
+	SCK2_MARK,
+};
+static const unsigned int scif2_data_b_pins[] = {
+	/* RXD, TXD */
+	120, 119,
+};
+static const unsigned int scif2_data_b_mux[] = {
+	RX2_B_MARK, TX2_B_MARK,
+};
+static const unsigned int scif2_clk_b_pins[] = {
+	/* SCK */
+	118,
+};
+static const unsigned int scif2_clk_b_mux[] = {
+	SCK2_B_MARK,
+};
+static const unsigned int scif2_data_c_pins[] = {
+	/* RXD, TXD */
+	33, 31,
+};
+static const unsigned int scif2_data_c_mux[] = {
+	RX2_C_MARK, TX2_C_MARK,
+};
+static const unsigned int scif2_clk_c_pins[] = {
+	/* SCK */
+	32,
+};
+static const unsigned int scif2_clk_c_mux[] = {
+	SCK2_C_MARK,
+};
+static const unsigned int scif2_data_d_pins[] = {
+	/* RXD, TXD */
+	64, 62,
+};
+static const unsigned int scif2_data_d_mux[] = {
+	RX2_D_MARK, TX2_D_MARK,
+};
+static const unsigned int scif2_clk_d_pins[] = {
+	/* SCK */
+	63,
+};
+static const unsigned int scif2_clk_d_mux[] = {
+	SCK2_D_MARK,
+};
+static const unsigned int scif2_data_e_pins[] = {
+	/* RXD, TXD */
+	20, 19,
+};
+static const unsigned int scif2_data_e_mux[] = {
+	RX2_E_MARK, TX2_E_MARK,
+};
+/* - SCIF3 ------------------------------------------------------------------ */
+static const unsigned int scif3_data_pins[] = {
+	/* RXD, TXD */
+	137, 136,
+};
+static const unsigned int scif3_data_mux[] = {
+	RX3_IRDA_RX_MARK, TX3_IRDA_TX_MARK,
+};
+static const unsigned int scif3_clk_pins[] = {
+	/* SCK */
+	135,
+};
+static const unsigned int scif3_clk_mux[] = {
+	SCK3_MARK,
+};
 
-	/* IPSR1 */
-	GPIO_FN(EX_CS0), GPIO_FN(RX3_C_IRDA_RX_C), GPIO_FN(MMC0_D6),
-	GPIO_FN(FD6), GPIO_FN(EX_CS1), GPIO_FN(MMC0_D7), GPIO_FN(FD7),
-	GPIO_FN(EX_CS2), GPIO_FN(SD1_CLK), GPIO_FN(MMC0_CLK), GPIO_FN(FALE),
-	GPIO_FN(ATACS00), GPIO_FN(EX_CS3), GPIO_FN(SD1_CMD), GPIO_FN(MMC0_CMD),
-	GPIO_FN(FRE), GPIO_FN(ATACS10), GPIO_FN(VI1_R4), GPIO_FN(RX5_B),
-	GPIO_FN(HSCK1), GPIO_FN(SSI_SDATA8_B), GPIO_FN(RTS0_B_TANS_B),
-	GPIO_FN(SSI_SDATA9), GPIO_FN(EX_CS4), GPIO_FN(SD1_DAT0),
-	GPIO_FN(MMC0_D0), GPIO_FN(FD0), GPIO_FN(ATARD0), GPIO_FN(VI1_R5),
-	GPIO_FN(SCK5_B), GPIO_FN(HTX1), GPIO_FN(TX2_E), GPIO_FN(TX0_B),
-	GPIO_FN(SSI_SCK9), GPIO_FN(EX_CS5), GPIO_FN(SD1_DAT1),
-	GPIO_FN(MMC0_D1), GPIO_FN(FD1),	GPIO_FN(ATAWR0), GPIO_FN(VI1_R6),
-	GPIO_FN(HRX1), GPIO_FN(RX2_E), GPIO_FN(RX0_B), GPIO_FN(SSI_WS9),
-	GPIO_FN(MLB_CLK), GPIO_FN(PWM2), GPIO_FN(SCK4), GPIO_FN(MLB_SIG),
-	GPIO_FN(PWM3), GPIO_FN(TX4), GPIO_FN(MLB_DAT), GPIO_FN(PWM4),
-	GPIO_FN(RX4), GPIO_FN(HTX0), GPIO_FN(TX1), GPIO_FN(SDATA),
-	GPIO_FN(CTS0_C), GPIO_FN(SUB_TCK), GPIO_FN(CC5_STATE2),
-	GPIO_FN(CC5_STATE10), GPIO_FN(CC5_STATE18), GPIO_FN(CC5_STATE26),
-	GPIO_FN(CC5_STATE34),
+static const unsigned int scif3_data_b_pins[] = {
+	/* RXD, TXD */
+	64, 62,
+};
+static const unsigned int scif3_data_b_mux[] = {
+	RX3_B_IRDA_RX_B_MARK, TX3_B_IRDA_TX_B_MARK,
+};
+static const unsigned int scif3_data_c_pins[] = {
+	/* RXD, TXD */
+	15, 12,
+};
+static const unsigned int scif3_data_c_mux[] = {
+	RX3_C_IRDA_RX_C_MARK, TX3C_IRDA_TX_C_MARK,
+};
+static const unsigned int scif3_data_d_pins[] = {
+	/* RXD, TXD */
+	30, 29,
+};
+static const unsigned int scif3_data_d_mux[] = {
+	RX3_D_IRDA_RX_D_MARK, TX3_D_IRDA_TX_D_MARK,
+};
+static const unsigned int scif3_data_e_pins[] = {
+	/* RXD, TXD */
+	35, 34,
+};
+static const unsigned int scif3_data_e_mux[] = {
+	RX3_E_IRDA_RX_E_MARK, TX3_E_IRDA_TX_E_MARK,
+};
+static const unsigned int scif3_clk_e_pins[] = {
+	/* SCK */
+	42,
+};
+static const unsigned int scif3_clk_e_mux[] = {
+	SCK3_E_MARK,
+};
+/* - SCIF4 ------------------------------------------------------------------ */
+static const unsigned int scif4_data_pins[] = {
+	/* RXD, TXD */
+	123, 122,
+};
+static const unsigned int scif4_data_mux[] = {
+	RX4_MARK, TX4_MARK,
+};
+static const unsigned int scif4_clk_pins[] = {
+	/* SCK */
+	121,
+};
+static const unsigned int scif4_clk_mux[] = {
+	SCK4_MARK,
+};
+static const unsigned int scif4_data_b_pins[] = {
+	/* RXD, TXD */
+	111, 110,
+};
+static const unsigned int scif4_data_b_mux[] = {
+	RX4_B_MARK, TX4_B_MARK,
+};
+static const unsigned int scif4_clk_b_pins[] = {
+	/* SCK */
+	112,
+};
+static const unsigned int scif4_clk_b_mux[] = {
+	SCK4_B_MARK,
+};
+static const unsigned int scif4_data_c_pins[] = {
+	/* RXD, TXD */
+	22, 21,
+};
+static const unsigned int scif4_data_c_mux[] = {
+	RX4_C_MARK, TX4_C_MARK,
+};
+static const unsigned int scif4_data_d_pins[] = {
+	/* RXD, TXD */
+	69, 68,
+};
+static const unsigned int scif4_data_d_mux[] = {
+	RX4_D_MARK, TX4_D_MARK,
+};
+/* - SCIF5 ------------------------------------------------------------------ */
+static const unsigned int scif5_data_pins[] = {
+	/* RXD, TXD */
+	51, 50,
+};
+static const unsigned int scif5_data_mux[] = {
+	RX5_MARK, TX5_MARK,
+};
+static const unsigned int scif5_clk_pins[] = {
+	/* SCK */
+	43,
+};
+static const unsigned int scif5_clk_mux[] = {
+	SCK5_MARK,
+};
+static const unsigned int scif5_data_b_pins[] = {
+	/* RXD, TXD */
+	18, 11,
+};
+static const unsigned int scif5_data_b_mux[] = {
+	RX5_B_MARK, TX5_B_MARK,
+};
+static const unsigned int scif5_clk_b_pins[] = {
+	/* SCK */
+	19,
+};
+static const unsigned int scif5_clk_b_mux[] = {
+	SCK5_B_MARK,
+};
+static const unsigned int scif5_data_c_pins[] = {
+	/* RXD, TXD */
+	24, 23,
+};
+static const unsigned int scif5_data_c_mux[] = {
+	RX5_C_MARK, TX5_C_MARK,
+};
+static const unsigned int scif5_clk_c_pins[] = {
+	/* SCK */
+	28,
+};
+static const unsigned int scif5_clk_c_mux[] = {
+	SCK5_C_MARK,
+};
+static const unsigned int scif5_data_d_pins[] = {
+	/* RXD, TXD */
+	8, 6,
+};
+static const unsigned int scif5_data_d_mux[] = {
+	RX5_D_MARK, TX5_D_MARK,
+};
+static const unsigned int scif5_clk_d_pins[] = {
+	/* SCK */
+	7,
+};
+static const unsigned int scif5_clk_d_mux[] = {
+	SCK5_D_MARK,
+};
+/* - SDHI0 ------------------------------------------------------------------ */
+static const unsigned int sdhi0_data1_pins[] = {
+	/* D0 */
+	117,
+};
+static const unsigned int sdhi0_data1_mux[] = {
+	SD0_DAT0_MARK,
+};
+static const unsigned int sdhi0_data4_pins[] = {
+	/* D[0:3] */
+	117, 118, 119, 120,
+};
+static const unsigned int sdhi0_data4_mux[] = {
+	SD0_DAT0_MARK, SD0_DAT1_MARK, SD0_DAT2_MARK, SD0_DAT3_MARK,
+};
+static const unsigned int sdhi0_ctrl_pins[] = {
+	/* CMD, CLK */
+	114, 113,
+};
+static const unsigned int sdhi0_ctrl_mux[] = {
+	SD0_CMD_MARK, SD0_CLK_MARK,
+};
+static const unsigned int sdhi0_cd_pins[] = {
+	/* CD */
+	115,
+};
+static const unsigned int sdhi0_cd_mux[] = {
+	SD0_CD_MARK,
+};
+static const unsigned int sdhi0_wp_pins[] = {
+	/* WP */
+	116,
+};
+static const unsigned int sdhi0_wp_mux[] = {
+	SD0_WP_MARK,
+};
+/* - SDHI1 ------------------------------------------------------------------ */
+static const unsigned int sdhi1_data1_pins[] = {
+	/* D0 */
+	19,
+};
+static const unsigned int sdhi1_data1_mux[] = {
+	SD1_DAT0_MARK,
+};
+static const unsigned int sdhi1_data4_pins[] = {
+	/* D[0:3] */
+	19, 20, 21, 2,
+};
+static const unsigned int sdhi1_data4_mux[] = {
+	SD1_DAT0_MARK, SD1_DAT1_MARK, SD1_DAT2_MARK, SD1_DAT3_MARK,
+};
+static const unsigned int sdhi1_ctrl_pins[] = {
+	/* CMD, CLK */
+	18, 17,
+};
+static const unsigned int sdhi1_ctrl_mux[] = {
+	SD1_CMD_MARK, SD1_CLK_MARK,
+};
+static const unsigned int sdhi1_cd_pins[] = {
+	/* CD */
+	10,
+};
+static const unsigned int sdhi1_cd_mux[] = {
+	SD1_CD_MARK,
+};
+static const unsigned int sdhi1_wp_pins[] = {
+	/* WP */
+	11,
+};
+static const unsigned int sdhi1_wp_mux[] = {
+	SD1_WP_MARK,
+};
+/* - SDHI2 ------------------------------------------------------------------ */
+static const unsigned int sdhi2_data1_pins[] = {
+	/* D0 */
+	97,
+};
+static const unsigned int sdhi2_data1_mux[] = {
+	SD2_DAT0_MARK,
+};
+static const unsigned int sdhi2_data4_pins[] = {
+	/* D[0:3] */
+	97, 98, 99, 100,
+};
+static const unsigned int sdhi2_data4_mux[] = {
+	SD2_DAT0_MARK, SD2_DAT1_MARK, SD2_DAT2_MARK, SD2_DAT3_MARK,
+};
+static const unsigned int sdhi2_ctrl_pins[] = {
+	/* CMD, CLK */
+	102, 101,
+};
+static const unsigned int sdhi2_ctrl_mux[] = {
+	SD2_CMD_MARK, SD2_CLK_MARK,
+};
+static const unsigned int sdhi2_cd_pins[] = {
+	/* CD */
+	103,
+};
+static const unsigned int sdhi2_cd_mux[] = {
+	SD2_CD_MARK,
+};
+static const unsigned int sdhi2_wp_pins[] = {
+	/* WP */
+	104,
+};
+static const unsigned int sdhi2_wp_mux[] = {
+	SD2_WP_MARK,
+};
+/* - SDHI3 ------------------------------------------------------------------ */
+static const unsigned int sdhi3_data1_pins[] = {
+	/* D0 */
+	50,
+};
+static const unsigned int sdhi3_data1_mux[] = {
+	SD3_DAT0_MARK,
+};
+static const unsigned int sdhi3_data4_pins[] = {
+	/* D[0:3] */
+	50, 51, 52, 53,
+};
+static const unsigned int sdhi3_data4_mux[] = {
+	SD3_DAT0_MARK, SD3_DAT1_MARK, SD3_DAT2_MARK, SD3_DAT3_MARK,
+};
+static const unsigned int sdhi3_ctrl_pins[] = {
+	/* CMD, CLK */
+	35, 34,
+};
+static const unsigned int sdhi3_ctrl_mux[] = {
+	SD3_CMD_MARK, SD3_CLK_MARK,
+};
+static const unsigned int sdhi3_cd_pins[] = {
+	/* CD */
+	62,
+};
+static const unsigned int sdhi3_cd_mux[] = {
+	SD3_CD_MARK,
+};
+static const unsigned int sdhi3_wp_pins[] = {
+	/* WP */
+	64,
+};
+static const unsigned int sdhi3_wp_mux[] = {
+	SD3_WP_MARK,
+};
+/* - USB0 ------------------------------------------------------------------- */
+static const unsigned int usb0_pins[] = {
+	/* OVC */
+	150, 154,
+};
+static const unsigned int usb0_mux[] = {
+	USB_OVC0_MARK, USB_PENC0_MARK,
+};
+/* - USB1 ------------------------------------------------------------------- */
+static const unsigned int usb1_pins[] = {
+	/* OVC */
+	152, 155,
+};
+static const unsigned int usb1_mux[] = {
+	USB_OVC1_MARK, USB_PENC1_MARK,
+};
+/* - USB2 ------------------------------------------------------------------- */
+static const unsigned int usb2_pins[] = {
+	/* OVC, PENC */
+	125, 156,
+};
+static const unsigned int usb2_mux[] = {
+	USB_OVC2_MARK, USB_PENC2_MARK,
+};
 
-	/* IPSR2 */
-	GPIO_FN(HRX0), GPIO_FN(RX1), GPIO_FN(SCKZ), GPIO_FN(RTS0_C_TANS_C),
-	GPIO_FN(SUB_TDI), GPIO_FN(CC5_STATE3), GPIO_FN(CC5_STATE11),
-	GPIO_FN(CC5_STATE19), GPIO_FN(CC5_STATE27), GPIO_FN(CC5_STATE35),
-	GPIO_FN(HSCK0), GPIO_FN(SCK1), GPIO_FN(MTS), GPIO_FN(PWM5),
-	GPIO_FN(SCK0_C), GPIO_FN(SSI_SDATA9_B), GPIO_FN(SUB_TDO),
-	GPIO_FN(CC5_STATE0), GPIO_FN(CC5_STATE8), GPIO_FN(CC5_STATE16),
-	GPIO_FN(CC5_STATE24), GPIO_FN(CC5_STATE32), GPIO_FN(HCTS0),
-	GPIO_FN(CTS1), GPIO_FN(STM), GPIO_FN(PWM0_D), GPIO_FN(RX0_C),
-	GPIO_FN(SCIF_CLK_C), GPIO_FN(SUB_TRST), GPIO_FN(TCLK1_B),
-	GPIO_FN(CC5_OSCOUT), GPIO_FN(HRTS0), GPIO_FN(RTS1_TANS),
-	GPIO_FN(MDATA), GPIO_FN(TX0_C), GPIO_FN(SUB_TMS), GPIO_FN(CC5_STATE1),
-	GPIO_FN(CC5_STATE9), GPIO_FN(CC5_STATE17), GPIO_FN(CC5_STATE25),
-	GPIO_FN(CC5_STATE33), GPIO_FN(DU0_DR0), GPIO_FN(LCDOUT0),
-	GPIO_FN(DREQ0), GPIO_FN(GPS_CLK_B), GPIO_FN(AUDATA0),
-	GPIO_FN(TX5_C), GPIO_FN(DU0_DR1), GPIO_FN(LCDOUT1), GPIO_FN(DACK0),
-	GPIO_FN(DRACK0), GPIO_FN(GPS_SIGN_B), GPIO_FN(AUDATA1), GPIO_FN(RX5_C),
-	GPIO_FN(DU0_DR2), GPIO_FN(LCDOUT2), GPIO_FN(DU0_DR3), GPIO_FN(LCDOUT3),
-	GPIO_FN(DU0_DR4), GPIO_FN(LCDOUT4), GPIO_FN(DU0_DR5), GPIO_FN(LCDOUT5),
-	GPIO_FN(DU0_DR6), GPIO_FN(LCDOUT6), GPIO_FN(DU0_DR7), GPIO_FN(LCDOUT7),
-	GPIO_FN(DU0_DG0), GPIO_FN(LCDOUT8), GPIO_FN(DREQ1), GPIO_FN(SCL2),
-	GPIO_FN(AUDATA2),
+static const struct sh_pfc_pin_group pinmux_groups[] = {
+	SH_PFC_PIN_GROUP(du0_rgb666),
+	SH_PFC_PIN_GROUP(du0_rgb888),
+	SH_PFC_PIN_GROUP(du0_clk_in),
+	SH_PFC_PIN_GROUP(du0_clk_out_0),
+	SH_PFC_PIN_GROUP(du0_clk_out_1),
+	SH_PFC_PIN_GROUP(du0_sync_0),
+	SH_PFC_PIN_GROUP(du0_sync_1),
+	SH_PFC_PIN_GROUP(du0_oddf),
+	SH_PFC_PIN_GROUP(du0_cde),
+	SH_PFC_PIN_GROUP(du1_rgb666),
+	SH_PFC_PIN_GROUP(du1_rgb888),
+	SH_PFC_PIN_GROUP(du1_clk_in),
+	SH_PFC_PIN_GROUP(du1_clk_out),
+	SH_PFC_PIN_GROUP(du1_sync_0),
+	SH_PFC_PIN_GROUP(du1_sync_1),
+	SH_PFC_PIN_GROUP(du1_oddf),
+	SH_PFC_PIN_GROUP(du1_cde),
+	SH_PFC_PIN_GROUP(hspi0),
+	SH_PFC_PIN_GROUP(hspi1),
+	SH_PFC_PIN_GROUP(hspi1_b),
+	SH_PFC_PIN_GROUP(hspi1_c),
+	SH_PFC_PIN_GROUP(hspi1_d),
+	SH_PFC_PIN_GROUP(hspi2),
+	SH_PFC_PIN_GROUP(hspi2_b),
+	SH_PFC_PIN_GROUP(intc_irq0),
+	SH_PFC_PIN_GROUP(intc_irq0_b),
+	SH_PFC_PIN_GROUP(intc_irq1),
+	SH_PFC_PIN_GROUP(intc_irq1_b),
+	SH_PFC_PIN_GROUP(intc_irq2),
+	SH_PFC_PIN_GROUP(intc_irq2_b),
+	SH_PFC_PIN_GROUP(intc_irq3),
+	SH_PFC_PIN_GROUP(intc_irq3_b),
+	SH_PFC_PIN_GROUP(lbsc_cs0),
+	SH_PFC_PIN_GROUP(lbsc_cs1),
+	SH_PFC_PIN_GROUP(lbsc_ex_cs0),
+	SH_PFC_PIN_GROUP(lbsc_ex_cs1),
+	SH_PFC_PIN_GROUP(lbsc_ex_cs2),
+	SH_PFC_PIN_GROUP(lbsc_ex_cs3),
+	SH_PFC_PIN_GROUP(lbsc_ex_cs4),
+	SH_PFC_PIN_GROUP(lbsc_ex_cs5),
+	SH_PFC_PIN_GROUP(mmc0_data1),
+	SH_PFC_PIN_GROUP(mmc0_data4),
+	SH_PFC_PIN_GROUP(mmc0_data8),
+	SH_PFC_PIN_GROUP(mmc0_ctrl),
+	SH_PFC_PIN_GROUP(mmc1_data1),
+	SH_PFC_PIN_GROUP(mmc1_data4),
+	SH_PFC_PIN_GROUP(mmc1_data8),
+	SH_PFC_PIN_GROUP(mmc1_ctrl),
+	SH_PFC_PIN_GROUP(scif0_data),
+	SH_PFC_PIN_GROUP(scif0_clk),
+	SH_PFC_PIN_GROUP(scif0_ctrl),
+	SH_PFC_PIN_GROUP(scif0_data_b),
+	SH_PFC_PIN_GROUP(scif0_clk_b),
+	SH_PFC_PIN_GROUP(scif0_ctrl_b),
+	SH_PFC_PIN_GROUP(scif0_data_c),
+	SH_PFC_PIN_GROUP(scif0_clk_c),
+	SH_PFC_PIN_GROUP(scif0_ctrl_c),
+	SH_PFC_PIN_GROUP(scif0_data_d),
+	SH_PFC_PIN_GROUP(scif0_clk_d),
+	SH_PFC_PIN_GROUP(scif0_ctrl_d),
+	SH_PFC_PIN_GROUP(scif1_data),
+	SH_PFC_PIN_GROUP(scif1_clk),
+	SH_PFC_PIN_GROUP(scif1_ctrl),
+	SH_PFC_PIN_GROUP(scif1_data_b),
+	SH_PFC_PIN_GROUP(scif1_clk_b),
+	SH_PFC_PIN_GROUP(scif1_ctrl_b),
+	SH_PFC_PIN_GROUP(scif1_data_c),
+	SH_PFC_PIN_GROUP(scif1_clk_c),
+	SH_PFC_PIN_GROUP(scif1_ctrl_c),
+	SH_PFC_PIN_GROUP(scif2_data),
+	SH_PFC_PIN_GROUP(scif2_clk),
+	SH_PFC_PIN_GROUP(scif2_data_b),
+	SH_PFC_PIN_GROUP(scif2_clk_b),
+	SH_PFC_PIN_GROUP(scif2_data_c),
+	SH_PFC_PIN_GROUP(scif2_clk_c),
+	SH_PFC_PIN_GROUP(scif2_data_d),
+	SH_PFC_PIN_GROUP(scif2_clk_d),
+	SH_PFC_PIN_GROUP(scif2_data_e),
+	SH_PFC_PIN_GROUP(scif3_data),
+	SH_PFC_PIN_GROUP(scif3_clk),
+	SH_PFC_PIN_GROUP(scif3_data_b),
+	SH_PFC_PIN_GROUP(scif3_data_c),
+	SH_PFC_PIN_GROUP(scif3_data_d),
+	SH_PFC_PIN_GROUP(scif3_data_e),
+	SH_PFC_PIN_GROUP(scif3_clk_e),
+	SH_PFC_PIN_GROUP(scif4_data),
+	SH_PFC_PIN_GROUP(scif4_clk),
+	SH_PFC_PIN_GROUP(scif4_data_b),
+	SH_PFC_PIN_GROUP(scif4_clk_b),
+	SH_PFC_PIN_GROUP(scif4_data_c),
+	SH_PFC_PIN_GROUP(scif4_data_d),
+	SH_PFC_PIN_GROUP(scif5_data),
+	SH_PFC_PIN_GROUP(scif5_clk),
+	SH_PFC_PIN_GROUP(scif5_data_b),
+	SH_PFC_PIN_GROUP(scif5_clk_b),
+	SH_PFC_PIN_GROUP(scif5_data_c),
+	SH_PFC_PIN_GROUP(scif5_clk_c),
+	SH_PFC_PIN_GROUP(scif5_data_d),
+	SH_PFC_PIN_GROUP(scif5_clk_d),
+	SH_PFC_PIN_GROUP(sdhi0_data1),
+	SH_PFC_PIN_GROUP(sdhi0_data4),
+	SH_PFC_PIN_GROUP(sdhi0_ctrl),
+	SH_PFC_PIN_GROUP(sdhi0_cd),
+	SH_PFC_PIN_GROUP(sdhi0_wp),
+	SH_PFC_PIN_GROUP(sdhi1_data1),
+	SH_PFC_PIN_GROUP(sdhi1_data4),
+	SH_PFC_PIN_GROUP(sdhi1_ctrl),
+	SH_PFC_PIN_GROUP(sdhi1_cd),
+	SH_PFC_PIN_GROUP(sdhi1_wp),
+	SH_PFC_PIN_GROUP(sdhi2_data1),
+	SH_PFC_PIN_GROUP(sdhi2_data4),
+	SH_PFC_PIN_GROUP(sdhi2_ctrl),
+	SH_PFC_PIN_GROUP(sdhi2_cd),
+	SH_PFC_PIN_GROUP(sdhi2_wp),
+	SH_PFC_PIN_GROUP(sdhi3_data1),
+	SH_PFC_PIN_GROUP(sdhi3_data4),
+	SH_PFC_PIN_GROUP(sdhi3_ctrl),
+	SH_PFC_PIN_GROUP(sdhi3_cd),
+	SH_PFC_PIN_GROUP(sdhi3_wp),
+	SH_PFC_PIN_GROUP(usb0),
+	SH_PFC_PIN_GROUP(usb1),
+	SH_PFC_PIN_GROUP(usb2),
+};
 
-	/* IPSR3 */
-	GPIO_FN(DU0_DG1), GPIO_FN(LCDOUT9), GPIO_FN(DACK1), GPIO_FN(SDA2),
-	GPIO_FN(AUDATA3), GPIO_FN(DU0_DG2), GPIO_FN(LCDOUT10),
-	GPIO_FN(DU0_DG3), GPIO_FN(LCDOUT11), GPIO_FN(DU0_DG4),
-	GPIO_FN(LCDOUT12), GPIO_FN(DU0_DG5), GPIO_FN(LCDOUT13),
-	GPIO_FN(DU0_DG6), GPIO_FN(LCDOUT14), GPIO_FN(DU0_DG7),
-	GPIO_FN(LCDOUT15), GPIO_FN(DU0_DB0), GPIO_FN(LCDOUT16),
-	GPIO_FN(EX_WAIT1), GPIO_FN(SCL1), GPIO_FN(TCLK1), GPIO_FN(AUDATA4),
-	GPIO_FN(DU0_DB1), GPIO_FN(LCDOUT17), GPIO_FN(EX_WAIT2), GPIO_FN(SDA1),
-	GPIO_FN(GPS_MAG_B), GPIO_FN(AUDATA5), GPIO_FN(SCK5_C),
-	GPIO_FN(DU0_DB2), GPIO_FN(LCDOUT18), GPIO_FN(DU0_DB3),
-	GPIO_FN(LCDOUT19), GPIO_FN(DU0_DB4), GPIO_FN(LCDOUT20),
-	GPIO_FN(DU0_DB5), GPIO_FN(LCDOUT21), GPIO_FN(DU0_DB6),
-	GPIO_FN(LCDOUT22), GPIO_FN(DU0_DB7), GPIO_FN(LCDOUT23),
-	GPIO_FN(DU0_DOTCLKIN), GPIO_FN(QSTVA_QVS), GPIO_FN(TX3_D_IRDA_TX_D),
-	GPIO_FN(SCL3_B), GPIO_FN(DU0_DOTCLKOUT0), GPIO_FN(QCLK),
-	GPIO_FN(DU0_DOTCLKOUT1), GPIO_FN(QSTVB_QVE), GPIO_FN(RX3_D_IRDA_RX_D),
-	GPIO_FN(SDA3_B), GPIO_FN(SDA2_C), GPIO_FN(DACK0_B), GPIO_FN(DRACK0_B),
-	GPIO_FN(DU0_EXHSYNC_DU0_HSYNC), GPIO_FN(QSTH_QHS),
-	GPIO_FN(DU0_EXVSYNC_DU0_VSYNC), GPIO_FN(QSTB_QHE),
-	GPIO_FN(DU0_EXODDF_DU0_ODDF_DISP_CDE), GPIO_FN(QCPV_QDE),
-	GPIO_FN(CAN1_TX), GPIO_FN(TX2_C), GPIO_FN(SCL2_C), GPIO_FN(REMOCON),
+static const char * const du0_groups[] = {
+	"du0_rgb666",
+	"du0_rgb888",
+	"du0_clk_in",
+	"du0_clk_out_0",
+	"du0_clk_out_1",
+	"du0_sync_0",
+	"du0_sync_1",
+	"du0_oddf",
+	"du0_cde",
+};
 
-	/* IPSR4 */
-	GPIO_FN(DU0_DISP), GPIO_FN(QPOLA), GPIO_FN(CAN_CLK_C), GPIO_FN(SCK2_C),
-	GPIO_FN(DU0_CDE), GPIO_FN(QPOLB), GPIO_FN(CAN1_RX), GPIO_FN(RX2_C),
-	GPIO_FN(DREQ0_B), GPIO_FN(SSI_SCK78_B), GPIO_FN(SCK0_B),
-	GPIO_FN(DU1_DR0), GPIO_FN(VI2_DATA0_VI2_B0), GPIO_FN(PWM6),
-	GPIO_FN(SD3_CLK), GPIO_FN(TX3_E_IRDA_TX_E), GPIO_FN(AUDCK),
-	GPIO_FN(PWMFSW0_B), GPIO_FN(DU1_DR1), GPIO_FN(VI2_DATA1_VI2_B1),
-	GPIO_FN(PWM0), GPIO_FN(SD3_CMD), GPIO_FN(RX3_E_IRDA_RX_E),
-	GPIO_FN(AUDSYNC), GPIO_FN(CTS0_D), GPIO_FN(DU1_DR2), GPIO_FN(VI2_G0),
-	GPIO_FN(DU1_DR3), GPIO_FN(VI2_G1), GPIO_FN(DU1_DR4), GPIO_FN(VI2_G2),
-	GPIO_FN(DU1_DR5), GPIO_FN(VI2_G3), GPIO_FN(DU1_DR6), GPIO_FN(VI2_G4),
-	GPIO_FN(DU1_DR7), GPIO_FN(VI2_G5), GPIO_FN(DU1_DG0),
-	GPIO_FN(VI2_DATA2_VI2_B2), GPIO_FN(SCL1_B), GPIO_FN(SD3_DAT2),
-	GPIO_FN(SCK3_E), GPIO_FN(AUDATA6), GPIO_FN(TX0_D), GPIO_FN(DU1_DG1),
-	GPIO_FN(VI2_DATA3_VI2_B3), GPIO_FN(SDA1_B), GPIO_FN(SD3_DAT3),
-	GPIO_FN(SCK5), GPIO_FN(AUDATA7), GPIO_FN(RX0_D), GPIO_FN(DU1_DG2),
-	GPIO_FN(VI2_G6), GPIO_FN(DU1_DG3), GPIO_FN(VI2_G7), GPIO_FN(DU1_DG4),
-	GPIO_FN(VI2_R0), GPIO_FN(DU1_DG5), GPIO_FN(VI2_R1), GPIO_FN(DU1_DG6),
-	GPIO_FN(VI2_R2), GPIO_FN(DU1_DG7), GPIO_FN(VI2_R3), GPIO_FN(DU1_DB0),
-	GPIO_FN(VI2_DATA4_VI2_B4), GPIO_FN(SCL2_B), GPIO_FN(SD3_DAT0),
-	GPIO_FN(TX5), GPIO_FN(SCK0_D),
+static const char * const du1_groups[] = {
+	"du1_rgb666",
+	"du1_rgb888",
+	"du1_clk_in",
+	"du1_clk_out",
+	"du1_sync_0",
+	"du1_sync_1",
+	"du1_oddf",
+	"du1_cde",
+};
 
-	/* IPSR5 */
-	GPIO_FN(DU1_DB1), GPIO_FN(VI2_DATA5_VI2_B5), GPIO_FN(SDA2_B),
-	GPIO_FN(SD3_DAT1), GPIO_FN(RX5), GPIO_FN(RTS0_D_TANS_D),
-	GPIO_FN(DU1_DB2), GPIO_FN(VI2_R4), GPIO_FN(DU1_DB3), GPIO_FN(VI2_R5),
-	GPIO_FN(DU1_DB4), GPIO_FN(VI2_R6), GPIO_FN(DU1_DB5), GPIO_FN(VI2_R7),
-	GPIO_FN(DU1_DB6), GPIO_FN(SCL2_D), GPIO_FN(DU1_DB7), GPIO_FN(SDA2_D),
-	GPIO_FN(DU1_DOTCLKIN), GPIO_FN(VI2_CLKENB), GPIO_FN(HSPI_CS1),
-	GPIO_FN(SCL1_D), GPIO_FN(DU1_DOTCLKOUT), GPIO_FN(VI2_FIELD),
-	GPIO_FN(SDA1_D), GPIO_FN(DU1_EXHSYNC_DU1_HSYNC), GPIO_FN(VI2_HSYNC),
-	GPIO_FN(VI3_HSYNC), GPIO_FN(DU1_EXVSYNC_DU1_VSYNC), GPIO_FN(VI2_VSYNC),
-	GPIO_FN(VI3_VSYNC), GPIO_FN(DU1_EXODDF_DU1_ODDF_DISP_CDE),
-	GPIO_FN(VI2_CLK), GPIO_FN(TX3_B_IRDA_TX_B), GPIO_FN(SD3_CD),
-	GPIO_FN(HSPI_TX1), GPIO_FN(VI1_CLKENB), GPIO_FN(VI3_CLKENB),
-	GPIO_FN(AUDIO_CLKC), GPIO_FN(TX2_D), GPIO_FN(SPEEDIN),
-	GPIO_FN(GPS_SIGN_D), GPIO_FN(DU1_DISP), GPIO_FN(VI2_DATA6_VI2_B6),
-	GPIO_FN(TCLK0), GPIO_FN(QSTVA_B_QVS_B), GPIO_FN(HSPI_CLK1),
-	GPIO_FN(SCK2_D), GPIO_FN(AUDIO_CLKOUT_B), GPIO_FN(GPS_MAG_D),
-	GPIO_FN(DU1_CDE), GPIO_FN(VI2_DATA7_VI2_B7), GPIO_FN(RX3_B_IRDA_RX_B),
-	GPIO_FN(SD3_WP), GPIO_FN(HSPI_RX1), GPIO_FN(VI1_FIELD),
-	GPIO_FN(VI3_FIELD), GPIO_FN(AUDIO_CLKOUT), GPIO_FN(RX2_D),
-	GPIO_FN(GPS_CLK_C), GPIO_FN(GPS_CLK_D), GPIO_FN(AUDIO_CLKA),
-	GPIO_FN(CAN_TXCLK), GPIO_FN(AUDIO_CLKB), GPIO_FN(USB_OVC2),
-	GPIO_FN(CAN_DEBUGOUT0), GPIO_FN(MOUT0),
+static const char * const hspi0_groups[] = {
+	"hspi0",
+};
 
-	/* IPSR6 */
-	GPIO_FN(SSI_SCK0129), GPIO_FN(CAN_DEBUGOUT1), GPIO_FN(MOUT1),
-	GPIO_FN(SSI_WS0129), GPIO_FN(CAN_DEBUGOUT2), GPIO_FN(MOUT2),
-	GPIO_FN(SSI_SDATA0), GPIO_FN(CAN_DEBUGOUT3), GPIO_FN(MOUT5),
-	GPIO_FN(SSI_SDATA1), GPIO_FN(CAN_DEBUGOUT4), GPIO_FN(MOUT6),
-	GPIO_FN(SSI_SDATA2), GPIO_FN(CAN_DEBUGOUT5), GPIO_FN(SSI_SCK34),
-	GPIO_FN(CAN_DEBUGOUT6), GPIO_FN(CAN0_TX_B), GPIO_FN(IERX),
-	GPIO_FN(SSI_SCK9_C), GPIO_FN(SSI_WS34), GPIO_FN(CAN_DEBUGOUT7),
-	GPIO_FN(CAN0_RX_B), GPIO_FN(IETX), GPIO_FN(SSI_WS9_C),
-	GPIO_FN(SSI_SDATA3), GPIO_FN(PWM0_C), GPIO_FN(CAN_DEBUGOUT8),
-	GPIO_FN(CAN_CLK_B), GPIO_FN(IECLK), GPIO_FN(SCIF_CLK_B),
-	GPIO_FN(TCLK0_B), GPIO_FN(SSI_SDATA4), GPIO_FN(CAN_DEBUGOUT9),
-	GPIO_FN(SSI_SDATA9_C), GPIO_FN(SSI_SCK5), GPIO_FN(ADICLK),
-	GPIO_FN(CAN_DEBUGOUT10), GPIO_FN(SCK3), GPIO_FN(TCLK0_D),
-	GPIO_FN(SSI_WS5), GPIO_FN(ADICS_SAMP), GPIO_FN(CAN_DEBUGOUT11),
-	GPIO_FN(TX3_IRDA_TX), GPIO_FN(SSI_SDATA5), GPIO_FN(ADIDATA),
-	GPIO_FN(CAN_DEBUGOUT12), GPIO_FN(RX3_IRDA_RX), GPIO_FN(SSI_SCK6),
-	GPIO_FN(ADICHS0), GPIO_FN(CAN0_TX), GPIO_FN(IERX_B),
+static const char * const hspi1_groups[] = {
+	"hspi1",
+	"hspi1_b",
+	"hspi1_c",
+	"hspi1_d",
+};
 
-	/* IPSR7 */
-	GPIO_FN(SSI_WS6), GPIO_FN(ADICHS1), GPIO_FN(CAN0_RX), GPIO_FN(IETX_B),
-	GPIO_FN(SSI_SDATA6), GPIO_FN(ADICHS2), GPIO_FN(CAN_CLK),
-	GPIO_FN(IECLK_B), GPIO_FN(SSI_SCK78), GPIO_FN(CAN_DEBUGOUT13),
-	GPIO_FN(IRQ0_B), GPIO_FN(SSI_SCK9_B), GPIO_FN(HSPI_CLK1_C),
-	GPIO_FN(SSI_WS78), GPIO_FN(CAN_DEBUGOUT14), GPIO_FN(IRQ1_B),
-	GPIO_FN(SSI_WS9_B), GPIO_FN(HSPI_CS1_C), GPIO_FN(SSI_SDATA7),
-	GPIO_FN(CAN_DEBUGOUT15), GPIO_FN(IRQ2_B), GPIO_FN(TCLK1_C),
-	GPIO_FN(HSPI_TX1_C), GPIO_FN(SSI_SDATA8), GPIO_FN(VSP),
-	GPIO_FN(IRQ3_B), GPIO_FN(HSPI_RX1_C), GPIO_FN(SD0_CLK),
-	GPIO_FN(ATACS01), GPIO_FN(SCK1_B), GPIO_FN(SD0_CMD), GPIO_FN(ATACS11),
-	GPIO_FN(TX1_B), GPIO_FN(CC5_TDO), GPIO_FN(SD0_DAT0), GPIO_FN(ATADIR1),
-	GPIO_FN(RX1_B), GPIO_FN(CC5_TRST), GPIO_FN(SD0_DAT1), GPIO_FN(ATAG1),
-	GPIO_FN(SCK2_B), GPIO_FN(CC5_TMS), GPIO_FN(SD0_DAT2), GPIO_FN(ATARD1),
-	GPIO_FN(TX2_B), GPIO_FN(CC5_TCK), GPIO_FN(SD0_DAT3), GPIO_FN(ATAWR1),
-	GPIO_FN(RX2_B), GPIO_FN(CC5_TDI), GPIO_FN(SD0_CD), GPIO_FN(DREQ2),
-	GPIO_FN(RTS1_B_TANS_B), GPIO_FN(SD0_WP), GPIO_FN(DACK2),
-	GPIO_FN(CTS1_B),
+static const char * const hspi2_groups[] = {
+	"hspi2",
+	"hspi2_b",
+};
 
-	/* IPSR8 */
-	GPIO_FN(HSPI_CLK0), GPIO_FN(CTS0), GPIO_FN(USB_OVC0), GPIO_FN(AD_CLK),
-	GPIO_FN(CC5_STATE4), GPIO_FN(CC5_STATE12), GPIO_FN(CC5_STATE20),
-	GPIO_FN(CC5_STATE28), GPIO_FN(CC5_STATE36), GPIO_FN(HSPI_CS0),
-	GPIO_FN(RTS0_TANS), GPIO_FN(USB_OVC1), GPIO_FN(AD_DI),
-	GPIO_FN(CC5_STATE5), GPIO_FN(CC5_STATE13), GPIO_FN(CC5_STATE21),
-	GPIO_FN(CC5_STATE29), GPIO_FN(CC5_STATE37), GPIO_FN(HSPI_TX0),
-	GPIO_FN(TX0), GPIO_FN(CAN_DEBUG_HW_TRIGGER), GPIO_FN(AD_DO),
-	GPIO_FN(CC5_STATE6), GPIO_FN(CC5_STATE14), GPIO_FN(CC5_STATE22),
-	GPIO_FN(CC5_STATE30), GPIO_FN(CC5_STATE38), GPIO_FN(HSPI_RX0),
-	GPIO_FN(RX0), GPIO_FN(CAN_STEP0), GPIO_FN(AD_NCS), GPIO_FN(CC5_STATE7),
-	GPIO_FN(CC5_STATE15), GPIO_FN(CC5_STATE23), GPIO_FN(CC5_STATE31),
-	GPIO_FN(CC5_STATE39), GPIO_FN(FMCLK), GPIO_FN(RDS_CLK), GPIO_FN(PCMOE),
-	GPIO_FN(BPFCLK), GPIO_FN(PCMWE), GPIO_FN(FMIN), GPIO_FN(RDS_DATA),
-	GPIO_FN(VI0_CLK), GPIO_FN(MMC1_CLK), GPIO_FN(VI0_CLKENB),
-	GPIO_FN(TX1_C), GPIO_FN(HTX1_B), GPIO_FN(MT1_SYNC),
-	GPIO_FN(VI0_FIELD), GPIO_FN(RX1_C), GPIO_FN(HRX1_B),
-	GPIO_FN(VI0_HSYNC), GPIO_FN(VI0_DATA0_B_VI0_B0_B), GPIO_FN(CTS1_C),
-	GPIO_FN(TX4_D), GPIO_FN(MMC1_CMD), GPIO_FN(HSCK1_B),
-	GPIO_FN(VI0_VSYNC), GPIO_FN(VI0_DATA1_B_VI0_B1_B),
-	GPIO_FN(RTS1_C_TANS_C), GPIO_FN(RX4_D), GPIO_FN(PWMFSW0_C),
+static const char * const intc_groups[] = {
+	"intc_irq0",
+	"intc_irq0_b",
+	"intc_irq1",
+	"intc_irq1_b",
+	"intc_irq2",
+	"intc_irq2_b",
+	"intc_irq3",
+	"intc_irq4_b",
+};
 
-	/* IPSR9 */
-	GPIO_FN(VI0_DATA0_VI0_B0), GPIO_FN(HRTS1_B), GPIO_FN(MT1_VCXO),
-	GPIO_FN(VI0_DATA1_VI0_B1), GPIO_FN(HCTS1_B), GPIO_FN(MT1_PWM),
-	GPIO_FN(VI0_DATA2_VI0_B2), GPIO_FN(MMC1_D0), GPIO_FN(VI0_DATA3_VI0_B3),
-	GPIO_FN(MMC1_D1), GPIO_FN(VI0_DATA4_VI0_B4), GPIO_FN(MMC1_D2),
-	GPIO_FN(VI0_DATA5_VI0_B5), GPIO_FN(MMC1_D3), GPIO_FN(VI0_DATA6_VI0_B6),
-	GPIO_FN(MMC1_D4), GPIO_FN(ARM_TRACEDATA_0), GPIO_FN(VI0_DATA7_VI0_B7),
-	GPIO_FN(MMC1_D5), GPIO_FN(ARM_TRACEDATA_1), GPIO_FN(VI0_G0),
-	GPIO_FN(SSI_SCK78_C), GPIO_FN(IRQ0), GPIO_FN(ARM_TRACEDATA_2),
-	GPIO_FN(VI0_G1), GPIO_FN(SSI_WS78_C), GPIO_FN(IRQ1),
-	GPIO_FN(ARM_TRACEDATA_3), GPIO_FN(VI0_G2), GPIO_FN(ETH_TXD1),
-	GPIO_FN(MMC1_D6), GPIO_FN(ARM_TRACEDATA_4), GPIO_FN(TS_SPSYNC0),
-	GPIO_FN(VI0_G3), GPIO_FN(ETH_CRS_DV), GPIO_FN(MMC1_D7),
-	GPIO_FN(ARM_TRACEDATA_5), GPIO_FN(TS_SDAT0), GPIO_FN(VI0_G4),
-	GPIO_FN(ETH_TX_EN), GPIO_FN(SD2_DAT0_B), GPIO_FN(ARM_TRACEDATA_6),
-	GPIO_FN(VI0_G5), GPIO_FN(ETH_RX_ER), GPIO_FN(SD2_DAT1_B),
-	GPIO_FN(ARM_TRACEDATA_7), GPIO_FN(VI0_G6), GPIO_FN(ETH_RXD0),
-	GPIO_FN(SD2_DAT2_B), GPIO_FN(ARM_TRACEDATA_8), GPIO_FN(VI0_G7),
-	GPIO_FN(ETH_RXD1), GPIO_FN(SD2_DAT3_B), GPIO_FN(ARM_TRACEDATA_9),
+static const char * const lbsc_groups[] = {
+	"lbsc_cs0",
+	"lbsc_cs1",
+	"lbsc_ex_cs0",
+	"lbsc_ex_cs1",
+	"lbsc_ex_cs2",
+	"lbsc_ex_cs3",
+	"lbsc_ex_cs4",
+	"lbsc_ex_cs5",
+};
 
-	/* IPSR10 */
-	GPIO_FN(VI0_R0), GPIO_FN(SSI_SDATA7_C), GPIO_FN(SCK1_C),
-	GPIO_FN(DREQ1_B), GPIO_FN(ARM_TRACEDATA_10), GPIO_FN(DREQ0_C),
-	GPIO_FN(VI0_R1), GPIO_FN(SSI_SDATA8_C), GPIO_FN(DACK1_B),
-	GPIO_FN(ARM_TRACEDATA_11), GPIO_FN(DACK0_C), GPIO_FN(DRACK0_C),
-	GPIO_FN(VI0_R2), GPIO_FN(ETH_LINK), GPIO_FN(SD2_CLK_B), GPIO_FN(IRQ2),
-	GPIO_FN(ARM_TRACEDATA_12), GPIO_FN(VI0_R3), GPIO_FN(ETH_MAGIC),
-	GPIO_FN(SD2_CMD_B), GPIO_FN(IRQ3), GPIO_FN(ARM_TRACEDATA_13),
-	GPIO_FN(VI0_R4), GPIO_FN(ETH_REFCLK), GPIO_FN(SD2_CD_B),
-	GPIO_FN(HSPI_CLK1_B), GPIO_FN(ARM_TRACEDATA_14), GPIO_FN(MT1_CLK),
-	GPIO_FN(TS_SCK0), GPIO_FN(VI0_R5), GPIO_FN(ETH_TXD0),
-	GPIO_FN(SD2_WP_B), GPIO_FN(HSPI_CS1_B), GPIO_FN(ARM_TRACEDATA_15),
-	GPIO_FN(MT1_D), GPIO_FN(TS_SDEN0), GPIO_FN(VI0_R6), GPIO_FN(ETH_MDC),
-	GPIO_FN(DREQ2_C), GPIO_FN(HSPI_TX1_B), GPIO_FN(TRACECLK),
-	GPIO_FN(MT1_BEN), GPIO_FN(PWMFSW0_D), GPIO_FN(VI0_R7),
-	GPIO_FN(ETH_MDIO), GPIO_FN(DACK2_C), GPIO_FN(HSPI_RX1_B),
-	GPIO_FN(SCIF_CLK_D), GPIO_FN(TRACECTL), GPIO_FN(MT1_PEN),
-	GPIO_FN(VI1_CLK), GPIO_FN(SIM_D), GPIO_FN(SDA3), GPIO_FN(VI1_HSYNC),
-	GPIO_FN(VI3_CLK), GPIO_FN(SSI_SCK4), GPIO_FN(GPS_SIGN_C),
-	GPIO_FN(PWMFSW0_E), GPIO_FN(VI1_VSYNC), GPIO_FN(AUDIO_CLKOUT_C),
-	GPIO_FN(SSI_WS4), GPIO_FN(SIM_CLK), GPIO_FN(GPS_MAG_C),
-	GPIO_FN(SPV_TRST), GPIO_FN(SCL3),
+static const char * const mmc0_groups[] = {
+	"mmc0_data1",
+	"mmc0_data4",
+	"mmc0_data8",
+	"mmc0_ctrl",
+};
 
-	/* IPSR11 */
-	GPIO_FN(VI1_DATA0_VI1_B0), GPIO_FN(SD2_DAT0), GPIO_FN(SIM_RST),
-	GPIO_FN(SPV_TCK), GPIO_FN(ADICLK_B), GPIO_FN(VI1_DATA1_VI1_B1),
-	GPIO_FN(SD2_DAT1), GPIO_FN(MT0_CLK), GPIO_FN(SPV_TMS),
-	GPIO_FN(ADICS_B_SAMP_B), GPIO_FN(VI1_DATA2_VI1_B2), GPIO_FN(SD2_DAT2),
-	GPIO_FN(MT0_D), GPIO_FN(SPVTDI), GPIO_FN(ADIDATA_B),
-	GPIO_FN(VI1_DATA3_VI1_B3), GPIO_FN(SD2_DAT3), GPIO_FN(MT0_BEN),
-	GPIO_FN(SPV_TDO), GPIO_FN(ADICHS0_B), GPIO_FN(VI1_DATA4_VI1_B4),
-	GPIO_FN(SD2_CLK), GPIO_FN(MT0_PEN), GPIO_FN(SPA_TRST),
-	GPIO_FN(HSPI_CLK1_D), GPIO_FN(ADICHS1_B), GPIO_FN(VI1_DATA5_VI1_B5),
-	GPIO_FN(SD2_CMD), GPIO_FN(MT0_SYNC), GPIO_FN(SPA_TCK),
-	GPIO_FN(HSPI_CS1_D), GPIO_FN(ADICHS2_B), GPIO_FN(VI1_DATA6_VI1_B6),
-	GPIO_FN(SD2_CD), GPIO_FN(MT0_VCXO), GPIO_FN(SPA_TMS),
-	GPIO_FN(HSPI_TX1_D), GPIO_FN(VI1_DATA7_VI1_B7), GPIO_FN(SD2_WP),
-	GPIO_FN(MT0_PWM), GPIO_FN(SPA_TDI), GPIO_FN(HSPI_RX1_D),
-	GPIO_FN(VI1_G0), GPIO_FN(VI3_DATA0), GPIO_FN(DU1_DOTCLKOUT1),
-	GPIO_FN(TS_SCK1), GPIO_FN(DREQ2_B), GPIO_FN(TX2), GPIO_FN(SPA_TDO),
-	GPIO_FN(HCTS0_B), GPIO_FN(VI1_G1), GPIO_FN(VI3_DATA1),
-	GPIO_FN(SSI_SCK1), GPIO_FN(TS_SDEN1), GPIO_FN(DACK2_B), GPIO_FN(RX2),
-	GPIO_FN(HRTS0_B),
+static const char * const mmc1_groups[] = {
+	"mmc1_data1",
+	"mmc1_data4",
+	"mmc1_data8",
+	"mmc1_ctrl",
+};
 
-	/* IPSR12 */
-	GPIO_FN(VI1_G2), GPIO_FN(VI3_DATA2), GPIO_FN(SSI_WS1),
-	GPIO_FN(TS_SPSYNC1), GPIO_FN(SCK2), GPIO_FN(HSCK0_B), GPIO_FN(VI1_G3),
-	GPIO_FN(VI3_DATA3), GPIO_FN(SSI_SCK2), GPIO_FN(TS_SDAT1),
-	GPIO_FN(SCL1_C), GPIO_FN(HTX0_B), GPIO_FN(VI1_G4), GPIO_FN(VI3_DATA4),
-	GPIO_FN(SSI_WS2), GPIO_FN(SDA1_C), GPIO_FN(SIM_RST_B),
-	GPIO_FN(HRX0_B), GPIO_FN(VI1_G5), GPIO_FN(VI3_DATA5),
-	GPIO_FN(GPS_CLK), GPIO_FN(FSE), GPIO_FN(TX4_B), GPIO_FN(SIM_D_B),
-	GPIO_FN(VI1_G6), GPIO_FN(VI3_DATA6), GPIO_FN(GPS_SIGN), GPIO_FN(FRB),
-	GPIO_FN(RX4_B), GPIO_FN(SIM_CLK_B), GPIO_FN(VI1_G7),
-	GPIO_FN(VI3_DATA7), GPIO_FN(GPS_MAG), GPIO_FN(FCE), GPIO_FN(SCK4_B),
-};
-
-static struct pinmux_cfg_reg pinmux_config_regs[] = {
+static const char * const scif0_groups[] = {
+	"scif0_data",
+	"scif0_clk",
+	"scif0_ctrl",
+	"scif0_data_b",
+	"scif0_clk_b",
+	"scif0_ctrl_b",
+	"scif0_data_c",
+	"scif0_clk_c",
+	"scif0_ctrl_c",
+	"scif0_data_d",
+	"scif0_clk_d",
+	"scif0_ctrl_d",
+};
+
+static const char * const scif1_groups[] = {
+	"scif1_data",
+	"scif1_clk",
+	"scif1_ctrl",
+	"scif1_data_b",
+	"scif1_clk_b",
+	"scif1_ctrl_b",
+	"scif1_data_c",
+	"scif1_clk_c",
+	"scif1_ctrl_c",
+};
+
+static const char * const scif2_groups[] = {
+	"scif2_data",
+	"scif2_clk",
+	"scif2_data_b",
+	"scif2_clk_b",
+	"scif2_data_c",
+	"scif2_clk_c",
+	"scif2_data_d",
+	"scif2_clk_d",
+	"scif2_data_e",
+};
+
+static const char * const scif3_groups[] = {
+	"scif3_data",
+	"scif3_clk",
+	"scif3_data_b",
+	"scif3_data_c",
+	"scif3_data_d",
+	"scif3_data_e",
+	"scif3_clk_e",
+};
+
+static const char * const scif4_groups[] = {
+	"scif4_data",
+	"scif4_clk",
+	"scif4_data_b",
+	"scif4_clk_b",
+	"scif4_data_c",
+	"scif4_data_d",
+};
+
+static const char * const scif5_groups[] = {
+	"scif5_data",
+	"scif5_clk",
+	"scif5_data_b",
+	"scif5_clk_b",
+	"scif5_data_c",
+	"scif5_clk_c",
+	"scif5_data_d",
+	"scif5_clk_d",
+};
+
+static const char * const sdhi0_groups[] = {
+	"sdhi0_data1",
+	"sdhi0_data4",
+	"sdhi0_ctrl",
+	"sdhi0_cd",
+	"sdhi0_wp",
+};
+
+static const char * const sdhi1_groups[] = {
+	"sdhi1_data1",
+	"sdhi1_data4",
+	"sdhi1_ctrl",
+	"sdhi1_cd",
+	"sdhi1_wp",
+};
+
+static const char * const sdhi2_groups[] = {
+	"sdhi2_data1",
+	"sdhi2_data4",
+	"sdhi2_ctrl",
+	"sdhi2_cd",
+	"sdhi2_wp",
+};
+
+static const char * const sdhi3_groups[] = {
+	"sdhi3_data1",
+	"sdhi3_data4",
+	"sdhi3_ctrl",
+	"sdhi3_cd",
+	"sdhi3_wp",
+};
+
+static const char * const usb0_groups[] = {
+	"usb0",
+};
+
+static const char * const usb1_groups[] = {
+	"usb1",
+};
+
+static const char * const usb2_groups[] = {
+	"usb2",
+};
+
+static const struct sh_pfc_function pinmux_functions[] = {
+	SH_PFC_FUNCTION(du0),
+	SH_PFC_FUNCTION(du1),
+	SH_PFC_FUNCTION(hspi0),
+	SH_PFC_FUNCTION(hspi1),
+	SH_PFC_FUNCTION(hspi2),
+	SH_PFC_FUNCTION(intc),
+	SH_PFC_FUNCTION(lbsc),
+	SH_PFC_FUNCTION(mmc0),
+	SH_PFC_FUNCTION(mmc1),
+	SH_PFC_FUNCTION(sdhi0),
+	SH_PFC_FUNCTION(sdhi1),
+	SH_PFC_FUNCTION(sdhi2),
+	SH_PFC_FUNCTION(sdhi3),
+	SH_PFC_FUNCTION(scif0),
+	SH_PFC_FUNCTION(scif1),
+	SH_PFC_FUNCTION(scif2),
+	SH_PFC_FUNCTION(scif3),
+	SH_PFC_FUNCTION(scif4),
+	SH_PFC_FUNCTION(scif5),
+	SH_PFC_FUNCTION(usb0),
+	SH_PFC_FUNCTION(usb1),
+	SH_PFC_FUNCTION(usb2),
+};
+
+static const struct pinmux_cfg_reg pinmux_config_regs[] = {
 	{ PINMUX_CFG_REG("GPSR0", 0xfffc0004, 32, 1) {
 		GP_0_31_FN, FN_IP3_31_29,
 		GP_0_30_FN, FN_IP3_26_24,
@@ -2412,7 +3407,7 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = {
 	    FN_VI1_G1, FN_VI3_DATA1, FN_SSI_SCK1, FN_TS_SDEN1,
 	    FN_DACK2_B, FN_RX2, FN_HRTS0_B, 0,
 	    /* IP11_26_24 [3] */
-	    FN_VI1_G0, FN_VI3_DATA0, FN_DU1_DOTCLKOUT1, FN_TS_SCK1,
+	    FN_VI1_G0, FN_VI3_DATA0, 0, FN_TS_SCK1,
 	    FN_DREQ2_B, FN_TX2, FN_SPA_TDO, FN_HCTS0_B,
 	    /* IP11_23_21 [3] */
 	    FN_VI1_DATA7_VI1_B7, FN_SD2_WP, FN_MT0_PWM, FN_SPA_TDI,
@@ -2558,66 +3553,24 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = {
 	    /* SEL_I2C1 [2] */
 	    FN_SEL_I2C1_0, FN_SEL_I2C1_1, FN_SEL_I2C1_2, FN_SEL_I2C1_3 }
 	},
-	{ PINMUX_CFG_REG("INOUTSEL0", 0xffc40004, 32, 1) { GP_INOUTSEL(0) } },
-	{ PINMUX_CFG_REG("INOUTSEL1", 0xffc41004, 32, 1) { GP_INOUTSEL(1) } },
-	{ PINMUX_CFG_REG("INOUTSEL2", 0xffc42004, 32, 1) { GP_INOUTSEL(2) } },
-	{ PINMUX_CFG_REG("INOUTSEL3", 0xffc43004, 32, 1) { GP_INOUTSEL(3) } },
-	{ PINMUX_CFG_REG("INOUTSEL4", 0xffc44004, 32, 1) { GP_INOUTSEL(4) } },
-	{ PINMUX_CFG_REG("INOUTSEL5", 0xffc45004, 32, 1) { GP_INOUTSEL(5) } },
-	{ PINMUX_CFG_REG("INOUTSEL6", 0xffc46004, 32, 1) {
-		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,
-		0, 0, 0, 0, 0, 0, 0, 0,
-		0, 0,
-		0, 0,
-		0, 0,
-		GP_6_8_IN, GP_6_8_OUT,
-		GP_6_7_IN, GP_6_7_OUT,
-		GP_6_6_IN, GP_6_6_OUT,
-		GP_6_5_IN, GP_6_5_OUT,
-		GP_6_4_IN, GP_6_4_OUT,
-		GP_6_3_IN, GP_6_3_OUT,
-		GP_6_2_IN, GP_6_2_OUT,
-		GP_6_1_IN, GP_6_1_OUT,
-		GP_6_0_IN, GP_6_0_OUT, }
-	},
-	{ },
-};
-
-static struct pinmux_data_reg pinmux_data_regs[] = {
-	{ PINMUX_DATA_REG("INDT0", 0xffc40008, 32) { GP_INDT(0) } },
-	{ PINMUX_DATA_REG("INDT1", 0xffc41008, 32) { GP_INDT(1) } },
-	{ PINMUX_DATA_REG("INDT2", 0xffc42008, 32) { GP_INDT(2) } },
-	{ PINMUX_DATA_REG("INDT3", 0xffc43008, 32) { GP_INDT(3) } },
-	{ PINMUX_DATA_REG("INDT4", 0xffc44008, 32) { GP_INDT(4) } },
-	{ PINMUX_DATA_REG("INDT5", 0xffc45008, 32) { GP_INDT(5) } },
-	{ PINMUX_DATA_REG("INDT6", 0xffc46008, 32) {
-		0, 0, 0, 0, 0, 0, 0, 0,	0, 0, 0, 0, 0, 0, 0, 0,
-		0, 0, 0, 0, 0, 0, 0, GP_6_8_DATA,
-		GP_6_7_DATA, GP_6_6_DATA, GP_6_5_DATA, GP_6_4_DATA,
-		GP_6_3_DATA, GP_6_2_DATA, GP_6_1_DATA, GP_6_0_DATA }
-	},
 	{ },
 };
 
-struct sh_pfc_soc_info r8a7779_pinmux_info = {
+const struct sh_pfc_soc_info r8a7779_pinmux_info = {
 	.name = "r8a7779_pfc",
 
 	.unlock_reg = 0xfffc0000, /* PMMR */
 
-	.reserved_id = PINMUX_RESERVED,
-	.data = { PINMUX_DATA_BEGIN, PINMUX_DATA_END },
-	.input = { PINMUX_INPUT_BEGIN, PINMUX_INPUT_END },
-	.output = { PINMUX_OUTPUT_BEGIN, PINMUX_OUTPUT_END },
-	.mark = { PINMUX_MARK_BEGIN, PINMUX_MARK_END },
 	.function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END },
 
-	.first_gpio = GPIO_GP_0_0,
-	.last_gpio = GPIO_FN_SCK4_B,
+	.pins = pinmux_pins,
+	.nr_pins = ARRAY_SIZE(pinmux_pins),
+	.groups = pinmux_groups,
+	.nr_groups = ARRAY_SIZE(pinmux_groups),
+	.functions = pinmux_functions,
+	.nr_functions = ARRAY_SIZE(pinmux_functions),
 
-	.gpios = pinmux_gpios,
 	.cfg_regs = pinmux_config_regs,
-	.data_regs = pinmux_data_regs,
 
 	.gpio_data = pinmux_data,
 	.gpio_data_size = ARRAY_SIZE(pinmux_data),
diff --git a/drivers/pinctrl/sh-pfc/pfc-sh7203.c b/drivers/pinctrl/sh-pfc/pfc-sh7203.c
index 01b425d..f63d51d 100644
--- a/drivers/pinctrl/sh-pfc/pfc-sh7203.c
+++ b/drivers/pinctrl/sh-pfc/pfc-sh7203.c
@@ -272,7 +272,7 @@ enum {
 	PINMUX_MARK_END,
 };
 
-static pinmux_enum_t pinmux_data[] = {
+static const pinmux_enum_t pinmux_data[] = {
 
 	/* PA */
 	PINMUX_DATA(PA7_DATA, PA7_IN),
@@ -703,7 +703,7 @@ static pinmux_enum_t pinmux_data[] = {
 	PINMUX_DATA(SSCK0_PF_MARK, PF0MD_11),
 };
 
-static struct pinmux_gpio pinmux_gpios[] = {
+static struct sh_pfc_pin pinmux_pins[] = {
 
 	/* PA */
 	PINMUX_GPIO(GPIO_PA7, PA7_DATA),
@@ -815,265 +815,269 @@ static struct pinmux_gpio pinmux_gpios[] = {
 	PINMUX_GPIO(GPIO_PF2, PF2_DATA),
 	PINMUX_GPIO(GPIO_PF1, PF1_DATA),
 	PINMUX_GPIO(GPIO_PF0, PF0_DATA),
+};
+
+#define PINMUX_FN_BASE	ARRAY_SIZE(pinmux_pins)
 
+static const struct pinmux_func pinmux_func_gpios[] = {
 	/* INTC */
-	PINMUX_GPIO(GPIO_FN_PINT7_PB, PINT7_PB_MARK),
-	PINMUX_GPIO(GPIO_FN_PINT6_PB, PINT6_PB_MARK),
-	PINMUX_GPIO(GPIO_FN_PINT5_PB, PINT5_PB_MARK),
-	PINMUX_GPIO(GPIO_FN_PINT4_PB, PINT4_PB_MARK),
-	PINMUX_GPIO(GPIO_FN_PINT3_PB, PINT3_PB_MARK),
-	PINMUX_GPIO(GPIO_FN_PINT2_PB, PINT2_PB_MARK),
-	PINMUX_GPIO(GPIO_FN_PINT1_PB, PINT1_PB_MARK),
-	PINMUX_GPIO(GPIO_FN_PINT0_PB, PINT0_PB_MARK),
-	PINMUX_GPIO(GPIO_FN_PINT7_PD, PINT7_PD_MARK),
-	PINMUX_GPIO(GPIO_FN_PINT6_PD, PINT6_PD_MARK),
-	PINMUX_GPIO(GPIO_FN_PINT5_PD, PINT5_PD_MARK),
-	PINMUX_GPIO(GPIO_FN_PINT4_PD, PINT4_PD_MARK),
-	PINMUX_GPIO(GPIO_FN_PINT3_PD, PINT3_PD_MARK),
-	PINMUX_GPIO(GPIO_FN_PINT2_PD, PINT2_PD_MARK),
-	PINMUX_GPIO(GPIO_FN_PINT1_PD, PINT1_PD_MARK),
-	PINMUX_GPIO(GPIO_FN_PINT0_PD, PINT0_PD_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ7_PB, IRQ7_PB_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ6_PB, IRQ6_PB_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ5_PB, IRQ5_PB_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ4_PB, IRQ4_PB_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ3_PB, IRQ3_PB_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ2_PB, IRQ2_PB_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ1_PB, IRQ1_PB_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ0_PB, IRQ0_PB_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ7_PD, IRQ7_PD_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ6_PD, IRQ6_PD_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ5_PD, IRQ5_PD_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ4_PD, IRQ4_PD_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ3_PD, IRQ3_PD_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ2_PD, IRQ2_PD_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ1_PD, IRQ1_PD_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ0_PD, IRQ0_PD_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ7_PE, IRQ7_PE_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ6_PE, IRQ6_PE_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ5_PE, IRQ5_PE_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ4_PE, IRQ4_PE_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ3_PE, IRQ3_PE_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ2_PE, IRQ2_PE_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ1_PE, IRQ1_PE_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ0_PE, IRQ0_PE_MARK),
-
-	PINMUX_GPIO(GPIO_FN_WDTOVF, WDTOVF_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQOUT, IRQOUT_MARK),
-	PINMUX_GPIO(GPIO_FN_REFOUT, REFOUT_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQOUT_REFOUT, IRQOUT_REFOUT_MARK),
-	PINMUX_GPIO(GPIO_FN_UBCTRG, UBCTRG_MARK),
+	GPIO_FN(PINT7_PB),
+	GPIO_FN(PINT6_PB),
+	GPIO_FN(PINT5_PB),
+	GPIO_FN(PINT4_PB),
+	GPIO_FN(PINT3_PB),
+	GPIO_FN(PINT2_PB),
+	GPIO_FN(PINT1_PB),
+	GPIO_FN(PINT0_PB),
+	GPIO_FN(PINT7_PD),
+	GPIO_FN(PINT6_PD),
+	GPIO_FN(PINT5_PD),
+	GPIO_FN(PINT4_PD),
+	GPIO_FN(PINT3_PD),
+	GPIO_FN(PINT2_PD),
+	GPIO_FN(PINT1_PD),
+	GPIO_FN(PINT0_PD),
+	GPIO_FN(IRQ7_PB),
+	GPIO_FN(IRQ6_PB),
+	GPIO_FN(IRQ5_PB),
+	GPIO_FN(IRQ4_PB),
+	GPIO_FN(IRQ3_PB),
+	GPIO_FN(IRQ2_PB),
+	GPIO_FN(IRQ1_PB),
+	GPIO_FN(IRQ0_PB),
+	GPIO_FN(IRQ7_PD),
+	GPIO_FN(IRQ6_PD),
+	GPIO_FN(IRQ5_PD),
+	GPIO_FN(IRQ4_PD),
+	GPIO_FN(IRQ3_PD),
+	GPIO_FN(IRQ2_PD),
+	GPIO_FN(IRQ1_PD),
+	GPIO_FN(IRQ0_PD),
+	GPIO_FN(IRQ7_PE),
+	GPIO_FN(IRQ6_PE),
+	GPIO_FN(IRQ5_PE),
+	GPIO_FN(IRQ4_PE),
+	GPIO_FN(IRQ3_PE),
+	GPIO_FN(IRQ2_PE),
+	GPIO_FN(IRQ1_PE),
+	GPIO_FN(IRQ0_PE),
+
+	GPIO_FN(WDTOVF),
+	GPIO_FN(IRQOUT),
+	GPIO_FN(REFOUT),
+	GPIO_FN(IRQOUT_REFOUT),
+	GPIO_FN(UBCTRG),
 
 	/* CAN */
-	PINMUX_GPIO(GPIO_FN_CTX1, CTX1_MARK),
-	PINMUX_GPIO(GPIO_FN_CRX1, CRX1_MARK),
-	PINMUX_GPIO(GPIO_FN_CTX0, CTX0_MARK),
-	PINMUX_GPIO(GPIO_FN_CTX0_CTX1, CTX0_CTX1_MARK),
-	PINMUX_GPIO(GPIO_FN_CRX0, CRX0_MARK),
-	PINMUX_GPIO(GPIO_FN_CRX0_CRX1, CRX0_CRX1_MARK),
+	GPIO_FN(CTX1),
+	GPIO_FN(CRX1),
+	GPIO_FN(CTX0),
+	GPIO_FN(CTX0_CTX1),
+	GPIO_FN(CRX0),
+	GPIO_FN(CRX0_CRX1),
 
 	/* IIC3 */
-	PINMUX_GPIO(GPIO_FN_SDA3, SDA3_MARK),
-	PINMUX_GPIO(GPIO_FN_SCL3, SCL3_MARK),
-	PINMUX_GPIO(GPIO_FN_SDA2, SDA2_MARK),
-	PINMUX_GPIO(GPIO_FN_SCL2, SCL2_MARK),
-	PINMUX_GPIO(GPIO_FN_SDA1, SDA1_MARK),
-	PINMUX_GPIO(GPIO_FN_SCL1, SCL1_MARK),
-	PINMUX_GPIO(GPIO_FN_SDA0, SDA0_MARK),
-	PINMUX_GPIO(GPIO_FN_SCL0, SCL0_MARK),
+	GPIO_FN(SDA3),
+	GPIO_FN(SCL3),
+	GPIO_FN(SDA2),
+	GPIO_FN(SCL2),
+	GPIO_FN(SDA1),
+	GPIO_FN(SCL1),
+	GPIO_FN(SDA0),
+	GPIO_FN(SCL0),
 
 	/* DMAC */
-	PINMUX_GPIO(GPIO_FN_TEND0_PD, TEND0_PD_MARK),
-	PINMUX_GPIO(GPIO_FN_TEND0_PE, TEND0_PE_MARK),
-	PINMUX_GPIO(GPIO_FN_DACK0_PD, DACK0_PD_MARK),
-	PINMUX_GPIO(GPIO_FN_DACK0_PE, DACK0_PE_MARK),
-	PINMUX_GPIO(GPIO_FN_DREQ0_PD, DREQ0_PD_MARK),
-	PINMUX_GPIO(GPIO_FN_DREQ0_PE, DREQ0_PE_MARK),
-	PINMUX_GPIO(GPIO_FN_TEND1_PD, TEND1_PD_MARK),
-	PINMUX_GPIO(GPIO_FN_TEND1_PE, TEND1_PE_MARK),
-	PINMUX_GPIO(GPIO_FN_DACK1_PD, DACK1_PD_MARK),
-	PINMUX_GPIO(GPIO_FN_DACK1_PE, DACK1_PE_MARK),
-	PINMUX_GPIO(GPIO_FN_DREQ1_PD, DREQ1_PD_MARK),
-	PINMUX_GPIO(GPIO_FN_DREQ1_PE, DREQ1_PE_MARK),
-	PINMUX_GPIO(GPIO_FN_DACK2, DACK2_MARK),
-	PINMUX_GPIO(GPIO_FN_DREQ2, DREQ2_MARK),
-	PINMUX_GPIO(GPIO_FN_DACK3, DACK3_MARK),
-	PINMUX_GPIO(GPIO_FN_DREQ3, DREQ3_MARK),
+	GPIO_FN(TEND0_PD),
+	GPIO_FN(TEND0_PE),
+	GPIO_FN(DACK0_PD),
+	GPIO_FN(DACK0_PE),
+	GPIO_FN(DREQ0_PD),
+	GPIO_FN(DREQ0_PE),
+	GPIO_FN(TEND1_PD),
+	GPIO_FN(TEND1_PE),
+	GPIO_FN(DACK1_PD),
+	GPIO_FN(DACK1_PE),
+	GPIO_FN(DREQ1_PD),
+	GPIO_FN(DREQ1_PE),
+	GPIO_FN(DACK2),
+	GPIO_FN(DREQ2),
+	GPIO_FN(DACK3),
+	GPIO_FN(DREQ3),
 
 	/* ADC */
-	PINMUX_GPIO(GPIO_FN_ADTRG_PD, ADTRG_PD_MARK),
-	PINMUX_GPIO(GPIO_FN_ADTRG_PE, ADTRG_PE_MARK),
+	GPIO_FN(ADTRG_PD),
+	GPIO_FN(ADTRG_PE),
 
 	/* BSC */
-	PINMUX_GPIO(GPIO_FN_D31, D31_MARK),
-	PINMUX_GPIO(GPIO_FN_D30, D30_MARK),
-	PINMUX_GPIO(GPIO_FN_D29, D29_MARK),
-	PINMUX_GPIO(GPIO_FN_D28, D28_MARK),
-	PINMUX_GPIO(GPIO_FN_D27, D27_MARK),
-	PINMUX_GPIO(GPIO_FN_D26, D26_MARK),
-	PINMUX_GPIO(GPIO_FN_D25, D25_MARK),
-	PINMUX_GPIO(GPIO_FN_D24, D24_MARK),
-	PINMUX_GPIO(GPIO_FN_D23, D23_MARK),
-	PINMUX_GPIO(GPIO_FN_D22, D22_MARK),
-	PINMUX_GPIO(GPIO_FN_D21, D21_MARK),
-	PINMUX_GPIO(GPIO_FN_D20, D20_MARK),
-	PINMUX_GPIO(GPIO_FN_D19, D19_MARK),
-	PINMUX_GPIO(GPIO_FN_D18, D18_MARK),
-	PINMUX_GPIO(GPIO_FN_D17, D17_MARK),
-	PINMUX_GPIO(GPIO_FN_D16, D16_MARK),
-	PINMUX_GPIO(GPIO_FN_A25, A25_MARK),
-	PINMUX_GPIO(GPIO_FN_A24, A24_MARK),
-	PINMUX_GPIO(GPIO_FN_A23, A23_MARK),
-	PINMUX_GPIO(GPIO_FN_A22, A22_MARK),
-	PINMUX_GPIO(GPIO_FN_A21, A21_MARK),
-	PINMUX_GPIO(GPIO_FN_CS4, CS4_MARK),
-	PINMUX_GPIO(GPIO_FN_MRES, MRES_MARK),
-	PINMUX_GPIO(GPIO_FN_BS, BS_MARK),
-	PINMUX_GPIO(GPIO_FN_IOIS16, IOIS16_MARK),
-	PINMUX_GPIO(GPIO_FN_CS1, CS1_MARK),
-	PINMUX_GPIO(GPIO_FN_CS6_CE1B, CS6_CE1B_MARK),
-	PINMUX_GPIO(GPIO_FN_CE2B, CE2B_MARK),
-	PINMUX_GPIO(GPIO_FN_CS5_CE1A, CS5_CE1A_MARK),
-	PINMUX_GPIO(GPIO_FN_CE2A, CE2A_MARK),
-	PINMUX_GPIO(GPIO_FN_FRAME, FRAME_MARK),
-	PINMUX_GPIO(GPIO_FN_WAIT, WAIT_MARK),
-	PINMUX_GPIO(GPIO_FN_RDWR, RDWR_MARK),
-	PINMUX_GPIO(GPIO_FN_CKE, CKE_MARK),
-	PINMUX_GPIO(GPIO_FN_CASU, CASU_MARK),
-	PINMUX_GPIO(GPIO_FN_BREQ, BREQ_MARK),
-	PINMUX_GPIO(GPIO_FN_RASU, RASU_MARK),
-	PINMUX_GPIO(GPIO_FN_BACK, BACK_MARK),
-	PINMUX_GPIO(GPIO_FN_CASL, CASL_MARK),
-	PINMUX_GPIO(GPIO_FN_RASL, RASL_MARK),
-	PINMUX_GPIO(GPIO_FN_WE3_DQMUU_AH_ICIO_WR, WE3_DQMUU_AH_ICIO_WR_MARK),
-	PINMUX_GPIO(GPIO_FN_WE2_DQMUL_ICIORD, WE2_DQMUL_ICIORD_MARK),
-	PINMUX_GPIO(GPIO_FN_WE1_DQMLU_WE, WE1_DQMLU_WE_MARK),
-	PINMUX_GPIO(GPIO_FN_WE0_DQMLL, WE0_DQMLL_MARK),
-	PINMUX_GPIO(GPIO_FN_CS3, CS3_MARK),
-	PINMUX_GPIO(GPIO_FN_CS2, CS2_MARK),
-	PINMUX_GPIO(GPIO_FN_A1, A1_MARK),
-	PINMUX_GPIO(GPIO_FN_A0, A0_MARK),
-	PINMUX_GPIO(GPIO_FN_CS7, CS7_MARK),
+	GPIO_FN(D31),
+	GPIO_FN(D30),
+	GPIO_FN(D29),
+	GPIO_FN(D28),
+	GPIO_FN(D27),
+	GPIO_FN(D26),
+	GPIO_FN(D25),
+	GPIO_FN(D24),
+	GPIO_FN(D23),
+	GPIO_FN(D22),
+	GPIO_FN(D21),
+	GPIO_FN(D20),
+	GPIO_FN(D19),
+	GPIO_FN(D18),
+	GPIO_FN(D17),
+	GPIO_FN(D16),
+	GPIO_FN(A25),
+	GPIO_FN(A24),
+	GPIO_FN(A23),
+	GPIO_FN(A22),
+	GPIO_FN(A21),
+	GPIO_FN(CS4),
+	GPIO_FN(MRES),
+	GPIO_FN(BS),
+	GPIO_FN(IOIS16),
+	GPIO_FN(CS1),
+	GPIO_FN(CS6_CE1B),
+	GPIO_FN(CE2B),
+	GPIO_FN(CS5_CE1A),
+	GPIO_FN(CE2A),
+	GPIO_FN(FRAME),
+	GPIO_FN(WAIT),
+	GPIO_FN(RDWR),
+	GPIO_FN(CKE),
+	GPIO_FN(CASU),
+	GPIO_FN(BREQ),
+	GPIO_FN(RASU),
+	GPIO_FN(BACK),
+	GPIO_FN(CASL),
+	GPIO_FN(RASL),
+	GPIO_FN(WE3_DQMUU_AH_ICIO_WR),
+	GPIO_FN(WE2_DQMUL_ICIORD),
+	GPIO_FN(WE1_DQMLU_WE),
+	GPIO_FN(WE0_DQMLL),
+	GPIO_FN(CS3),
+	GPIO_FN(CS2),
+	GPIO_FN(A1),
+	GPIO_FN(A0),
+	GPIO_FN(CS7),
 
 	/* TMU */
-	PINMUX_GPIO(GPIO_FN_TIOC4D, TIOC4D_MARK),
-	PINMUX_GPIO(GPIO_FN_TIOC4C, TIOC4C_MARK),
-	PINMUX_GPIO(GPIO_FN_TIOC4B, TIOC4B_MARK),
-	PINMUX_GPIO(GPIO_FN_TIOC4A, TIOC4A_MARK),
-	PINMUX_GPIO(GPIO_FN_TIOC3D, TIOC3D_MARK),
-	PINMUX_GPIO(GPIO_FN_TIOC3C, TIOC3C_MARK),
-	PINMUX_GPIO(GPIO_FN_TIOC3B, TIOC3B_MARK),
-	PINMUX_GPIO(GPIO_FN_TIOC3A, TIOC3A_MARK),
-	PINMUX_GPIO(GPIO_FN_TIOC2B, TIOC2B_MARK),
-	PINMUX_GPIO(GPIO_FN_TIOC1B, TIOC1B_MARK),
-	PINMUX_GPIO(GPIO_FN_TIOC2A, TIOC2A_MARK),
-	PINMUX_GPIO(GPIO_FN_TIOC1A, TIOC1A_MARK),
-	PINMUX_GPIO(GPIO_FN_TIOC0D, TIOC0D_MARK),
-	PINMUX_GPIO(GPIO_FN_TIOC0C, TIOC0C_MARK),
-	PINMUX_GPIO(GPIO_FN_TIOC0B, TIOC0B_MARK),
-	PINMUX_GPIO(GPIO_FN_TIOC0A, TIOC0A_MARK),
-	PINMUX_GPIO(GPIO_FN_TCLKD_PD, TCLKD_PD_MARK),
-	PINMUX_GPIO(GPIO_FN_TCLKC_PD, TCLKC_PD_MARK),
-	PINMUX_GPIO(GPIO_FN_TCLKB_PD, TCLKB_PD_MARK),
-	PINMUX_GPIO(GPIO_FN_TCLKA_PD, TCLKA_PD_MARK),
-	PINMUX_GPIO(GPIO_FN_TCLKD_PF, TCLKD_PF_MARK),
-	PINMUX_GPIO(GPIO_FN_TCLKC_PF, TCLKC_PF_MARK),
-	PINMUX_GPIO(GPIO_FN_TCLKB_PF, TCLKB_PF_MARK),
-	PINMUX_GPIO(GPIO_FN_TCLKA_PF, TCLKA_PF_MARK),
+	GPIO_FN(TIOC4D),
+	GPIO_FN(TIOC4C),
+	GPIO_FN(TIOC4B),
+	GPIO_FN(TIOC4A),
+	GPIO_FN(TIOC3D),
+	GPIO_FN(TIOC3C),
+	GPIO_FN(TIOC3B),
+	GPIO_FN(TIOC3A),
+	GPIO_FN(TIOC2B),
+	GPIO_FN(TIOC1B),
+	GPIO_FN(TIOC2A),
+	GPIO_FN(TIOC1A),
+	GPIO_FN(TIOC0D),
+	GPIO_FN(TIOC0C),
+	GPIO_FN(TIOC0B),
+	GPIO_FN(TIOC0A),
+	GPIO_FN(TCLKD_PD),
+	GPIO_FN(TCLKC_PD),
+	GPIO_FN(TCLKB_PD),
+	GPIO_FN(TCLKA_PD),
+	GPIO_FN(TCLKD_PF),
+	GPIO_FN(TCLKC_PF),
+	GPIO_FN(TCLKB_PF),
+	GPIO_FN(TCLKA_PF),
 
 	/* SSU */
-	PINMUX_GPIO(GPIO_FN_SCS0_PD, SCS0_PD_MARK),
-	PINMUX_GPIO(GPIO_FN_SSO0_PD, SSO0_PD_MARK),
-	PINMUX_GPIO(GPIO_FN_SSI0_PD, SSI0_PD_MARK),
-	PINMUX_GPIO(GPIO_FN_SSCK0_PD, SSCK0_PD_MARK),
-	PINMUX_GPIO(GPIO_FN_SCS0_PF, SCS0_PF_MARK),
-	PINMUX_GPIO(GPIO_FN_SSO0_PF, SSO0_PF_MARK),
-	PINMUX_GPIO(GPIO_FN_SSI0_PF, SSI0_PF_MARK),
-	PINMUX_GPIO(GPIO_FN_SSCK0_PF, SSCK0_PF_MARK),
-	PINMUX_GPIO(GPIO_FN_SCS1_PD, SCS1_PD_MARK),
-	PINMUX_GPIO(GPIO_FN_SSO1_PD, SSO1_PD_MARK),
-	PINMUX_GPIO(GPIO_FN_SSI1_PD, SSI1_PD_MARK),
-	PINMUX_GPIO(GPIO_FN_SSCK1_PD, SSCK1_PD_MARK),
-	PINMUX_GPIO(GPIO_FN_SCS1_PF, SCS1_PF_MARK),
-	PINMUX_GPIO(GPIO_FN_SSO1_PF, SSO1_PF_MARK),
-	PINMUX_GPIO(GPIO_FN_SSI1_PF, SSI1_PF_MARK),
-	PINMUX_GPIO(GPIO_FN_SSCK1_PF, SSCK1_PF_MARK),
+	GPIO_FN(SCS0_PD),
+	GPIO_FN(SSO0_PD),
+	GPIO_FN(SSI0_PD),
+	GPIO_FN(SSCK0_PD),
+	GPIO_FN(SCS0_PF),
+	GPIO_FN(SSO0_PF),
+	GPIO_FN(SSI0_PF),
+	GPIO_FN(SSCK0_PF),
+	GPIO_FN(SCS1_PD),
+	GPIO_FN(SSO1_PD),
+	GPIO_FN(SSI1_PD),
+	GPIO_FN(SSCK1_PD),
+	GPIO_FN(SCS1_PF),
+	GPIO_FN(SSO1_PF),
+	GPIO_FN(SSI1_PF),
+	GPIO_FN(SSCK1_PF),
 
 	/* SCIF */
-	PINMUX_GPIO(GPIO_FN_TXD0, TXD0_MARK),
-	PINMUX_GPIO(GPIO_FN_RXD0, RXD0_MARK),
-	PINMUX_GPIO(GPIO_FN_SCK0, SCK0_MARK),
-	PINMUX_GPIO(GPIO_FN_TXD1, TXD1_MARK),
-	PINMUX_GPIO(GPIO_FN_RXD1, RXD1_MARK),
-	PINMUX_GPIO(GPIO_FN_SCK1, SCK1_MARK),
-	PINMUX_GPIO(GPIO_FN_TXD2, TXD2_MARK),
-	PINMUX_GPIO(GPIO_FN_RXD2, RXD2_MARK),
-	PINMUX_GPIO(GPIO_FN_SCK2, SCK2_MARK),
-	PINMUX_GPIO(GPIO_FN_RTS3, RTS3_MARK),
-	PINMUX_GPIO(GPIO_FN_CTS3, CTS3_MARK),
-	PINMUX_GPIO(GPIO_FN_TXD3, TXD3_MARK),
-	PINMUX_GPIO(GPIO_FN_RXD3, RXD3_MARK),
-	PINMUX_GPIO(GPIO_FN_SCK3, SCK3_MARK),
+	GPIO_FN(TXD0),
+	GPIO_FN(RXD0),
+	GPIO_FN(SCK0),
+	GPIO_FN(TXD1),
+	GPIO_FN(RXD1),
+	GPIO_FN(SCK1),
+	GPIO_FN(TXD2),
+	GPIO_FN(RXD2),
+	GPIO_FN(SCK2),
+	GPIO_FN(RTS3),
+	GPIO_FN(CTS3),
+	GPIO_FN(TXD3),
+	GPIO_FN(RXD3),
+	GPIO_FN(SCK3),
 
 	/* SSI */
-	PINMUX_GPIO(GPIO_FN_AUDIO_CLK, AUDIO_CLK_MARK),
-	PINMUX_GPIO(GPIO_FN_SSIDATA3, SSIDATA3_MARK),
-	PINMUX_GPIO(GPIO_FN_SSIWS3, SSIWS3_MARK),
-	PINMUX_GPIO(GPIO_FN_SSISCK3, SSISCK3_MARK),
-	PINMUX_GPIO(GPIO_FN_SSIDATA2, SSIDATA2_MARK),
-	PINMUX_GPIO(GPIO_FN_SSIWS2, SSIWS2_MARK),
-	PINMUX_GPIO(GPIO_FN_SSISCK2, SSISCK2_MARK),
-	PINMUX_GPIO(GPIO_FN_SSIDATA1, SSIDATA1_MARK),
-	PINMUX_GPIO(GPIO_FN_SSIWS1, SSIWS1_MARK),
-	PINMUX_GPIO(GPIO_FN_SSISCK1, SSISCK1_MARK),
-	PINMUX_GPIO(GPIO_FN_SSIDATA0, SSIDATA0_MARK),
-	PINMUX_GPIO(GPIO_FN_SSIWS0, SSIWS0_MARK),
-	PINMUX_GPIO(GPIO_FN_SSISCK0, SSISCK0_MARK),
+	GPIO_FN(AUDIO_CLK),
+	GPIO_FN(SSIDATA3),
+	GPIO_FN(SSIWS3),
+	GPIO_FN(SSISCK3),
+	GPIO_FN(SSIDATA2),
+	GPIO_FN(SSIWS2),
+	GPIO_FN(SSISCK2),
+	GPIO_FN(SSIDATA1),
+	GPIO_FN(SSIWS1),
+	GPIO_FN(SSISCK1),
+	GPIO_FN(SSIDATA0),
+	GPIO_FN(SSIWS0),
+	GPIO_FN(SSISCK0),
 
 	/* FLCTL */
-	PINMUX_GPIO(GPIO_FN_FCE, FCE_MARK),
-	PINMUX_GPIO(GPIO_FN_FRB, FRB_MARK),
-	PINMUX_GPIO(GPIO_FN_NAF7, NAF7_MARK),
-	PINMUX_GPIO(GPIO_FN_NAF6, NAF6_MARK),
-	PINMUX_GPIO(GPIO_FN_NAF5, NAF5_MARK),
-	PINMUX_GPIO(GPIO_FN_NAF4, NAF4_MARK),
-	PINMUX_GPIO(GPIO_FN_NAF3, NAF3_MARK),
-	PINMUX_GPIO(GPIO_FN_NAF2, NAF2_MARK),
-	PINMUX_GPIO(GPIO_FN_NAF1, NAF1_MARK),
-	PINMUX_GPIO(GPIO_FN_NAF0, NAF0_MARK),
-	PINMUX_GPIO(GPIO_FN_FSC, FSC_MARK),
-	PINMUX_GPIO(GPIO_FN_FOE, FOE_MARK),
-	PINMUX_GPIO(GPIO_FN_FCDE, FCDE_MARK),
-	PINMUX_GPIO(GPIO_FN_FWE, FWE_MARK),
+	GPIO_FN(FCE),
+	GPIO_FN(FRB),
+	GPIO_FN(NAF7),
+	GPIO_FN(NAF6),
+	GPIO_FN(NAF5),
+	GPIO_FN(NAF4),
+	GPIO_FN(NAF3),
+	GPIO_FN(NAF2),
+	GPIO_FN(NAF1),
+	GPIO_FN(NAF0),
+	GPIO_FN(FSC),
+	GPIO_FN(FOE),
+	GPIO_FN(FCDE),
+	GPIO_FN(FWE),
 
 	/* LCDC */
-	PINMUX_GPIO(GPIO_FN_LCD_VEPWC, LCD_VEPWC_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_VCPWC, LCD_VCPWC_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_CLK, LCD_CLK_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_FLM, LCD_FLM_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_M_DISP, LCD_M_DISP_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_CL2, LCD_CL2_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_CL1, LCD_CL1_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DON, LCD_DON_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA15, LCD_DATA15_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA14, LCD_DATA14_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA13, LCD_DATA13_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA12, LCD_DATA12_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA11, LCD_DATA11_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA10, LCD_DATA10_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA9, LCD_DATA9_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA8, LCD_DATA8_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA7, LCD_DATA7_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA6, LCD_DATA6_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA5, LCD_DATA5_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA4, LCD_DATA4_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA3, LCD_DATA3_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA2, LCD_DATA2_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA1, LCD_DATA1_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA0, LCD_DATA0_MARK),
+	GPIO_FN(LCD_VEPWC),
+	GPIO_FN(LCD_VCPWC),
+	GPIO_FN(LCD_CLK),
+	GPIO_FN(LCD_FLM),
+	GPIO_FN(LCD_M_DISP),
+	GPIO_FN(LCD_CL2),
+	GPIO_FN(LCD_CL1),
+	GPIO_FN(LCD_DON),
+	GPIO_FN(LCD_DATA15),
+	GPIO_FN(LCD_DATA14),
+	GPIO_FN(LCD_DATA13),
+	GPIO_FN(LCD_DATA12),
+	GPIO_FN(LCD_DATA11),
+	GPIO_FN(LCD_DATA10),
+	GPIO_FN(LCD_DATA9),
+	GPIO_FN(LCD_DATA8),
+	GPIO_FN(LCD_DATA7),
+	GPIO_FN(LCD_DATA6),
+	GPIO_FN(LCD_DATA5),
+	GPIO_FN(LCD_DATA4),
+	GPIO_FN(LCD_DATA3),
+	GPIO_FN(LCD_DATA2),
+	GPIO_FN(LCD_DATA1),
+	GPIO_FN(LCD_DATA0),
 };
 
-static struct pinmux_cfg_reg pinmux_config_regs[] = {
+static const struct pinmux_cfg_reg pinmux_config_regs[] = {
 	{ PINMUX_CFG_REG("PBIORL", 0xfffe3886, 16, 1) {
 		0, 0,
 		0, 0,
@@ -1525,7 +1529,7 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = {
 	{}
 };
 
-static struct pinmux_data_reg pinmux_data_regs[] = {
+static const struct pinmux_data_reg pinmux_data_regs[] = {
 	{ PINMUX_DATA_REG("PADRL", 0xfffe3802, 16) {
 		0, 0, 0, 0,
 		0, 0, 0, 0,
@@ -1571,19 +1575,17 @@ static struct pinmux_data_reg pinmux_data_regs[] = {
 	{ },
 };
 
-struct sh_pfc_soc_info sh7203_pinmux_info = {
+const struct sh_pfc_soc_info sh7203_pinmux_info = {
 	.name = "sh7203_pfc",
-	.reserved_id = PINMUX_RESERVED,
-	.data = { PINMUX_DATA_BEGIN, PINMUX_DATA_END },
 	.input = { PINMUX_INPUT_BEGIN, PINMUX_INPUT_END, FORCE_IN },
 	.output = { PINMUX_OUTPUT_BEGIN, PINMUX_OUTPUT_END, FORCE_OUT },
-	.mark = { PINMUX_MARK_BEGIN, PINMUX_MARK_END },
 	.function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END },
 
-	.first_gpio = GPIO_PA7,
-	.last_gpio = GPIO_FN_LCD_DATA0,
+	.pins = pinmux_pins,
+	.nr_pins = ARRAY_SIZE(pinmux_pins),
+	.func_gpios = pinmux_func_gpios,
+	.nr_func_gpios = ARRAY_SIZE(pinmux_func_gpios),
 
-	.gpios = pinmux_gpios,
 	.cfg_regs = pinmux_config_regs,
 	.data_regs = pinmux_data_regs,
 
diff --git a/drivers/pinctrl/sh-pfc/pfc-sh7264.c b/drivers/pinctrl/sh-pfc/pfc-sh7264.c
index 2ba5639..2846752 100644
--- a/drivers/pinctrl/sh-pfc/pfc-sh7264.c
+++ b/drivers/pinctrl/sh-pfc/pfc-sh7264.c
@@ -604,7 +604,7 @@ enum {
 	PINMUX_MARK_END,
 };
 
-static pinmux_enum_t pinmux_data[] = {
+static const pinmux_enum_t pinmux_data[] = {
 
 	/* Port A */
 	PINMUX_DATA(PA3_DATA, PA3_IN),
@@ -1072,7 +1072,7 @@ static pinmux_enum_t pinmux_data[] = {
 	PINMUX_DATA(SD_D2_MARK, PK0MD_10),
 };
 
-static struct pinmux_gpio pinmux_gpios[] = {
+static struct sh_pfc_pin pinmux_pins[] = {
 
 	/* Port A */
 	PINMUX_GPIO(GPIO_PA3, PA3_DATA),
@@ -1216,257 +1216,261 @@ static struct pinmux_gpio pinmux_gpios[] = {
 	PINMUX_GPIO(GPIO_PK2, PK2_DATA),
 	PINMUX_GPIO(GPIO_PK1, PK1_DATA),
 	PINMUX_GPIO(GPIO_PK0, PK0_DATA),
+};
+
+#define PINMUX_FN_BASE	ARRAY_SIZE(pinmux_pins)
 
+static const struct pinmux_func pinmux_func_gpios[] = {
 	/* INTC */
-	PINMUX_GPIO(GPIO_FN_PINT7_PG, PINT7_PG_MARK),
-	PINMUX_GPIO(GPIO_FN_PINT6_PG, PINT6_PG_MARK),
-	PINMUX_GPIO(GPIO_FN_PINT5_PG, PINT5_PG_MARK),
-	PINMUX_GPIO(GPIO_FN_PINT4_PG, PINT4_PG_MARK),
-	PINMUX_GPIO(GPIO_FN_PINT3_PG, PINT3_PG_MARK),
-	PINMUX_GPIO(GPIO_FN_PINT2_PG, PINT2_PG_MARK),
-	PINMUX_GPIO(GPIO_FN_PINT1_PG, PINT1_PG_MARK),
-
-	PINMUX_GPIO(GPIO_FN_IRQ7_PC, IRQ7_PC_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ6_PC, IRQ6_PC_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ5_PC, IRQ5_PC_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ4_PC, IRQ4_PC_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ3_PG, IRQ3_PG_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ2_PG, IRQ2_PG_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ1_PJ, IRQ1_PJ_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ0_PJ, IRQ0_PJ_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ3_PE, IRQ3_PE_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ2_PE, IRQ2_PE_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ1_PE, IRQ1_PE_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ0_PE, IRQ0_PE_MARK),
+	GPIO_FN(PINT7_PG),
+	GPIO_FN(PINT6_PG),
+	GPIO_FN(PINT5_PG),
+	GPIO_FN(PINT4_PG),
+	GPIO_FN(PINT3_PG),
+	GPIO_FN(PINT2_PG),
+	GPIO_FN(PINT1_PG),
+
+	GPIO_FN(IRQ7_PC),
+	GPIO_FN(IRQ6_PC),
+	GPIO_FN(IRQ5_PC),
+	GPIO_FN(IRQ4_PC),
+	GPIO_FN(IRQ3_PG),
+	GPIO_FN(IRQ2_PG),
+	GPIO_FN(IRQ1_PJ),
+	GPIO_FN(IRQ0_PJ),
+	GPIO_FN(IRQ3_PE),
+	GPIO_FN(IRQ2_PE),
+	GPIO_FN(IRQ1_PE),
+	GPIO_FN(IRQ0_PE),
 
 	/* WDT */
-	PINMUX_GPIO(GPIO_FN_WDTOVF, WDTOVF_MARK),
+	GPIO_FN(WDTOVF),
 
 	/* CAN */
-	PINMUX_GPIO(GPIO_FN_CTX1, CTX1_MARK),
-	PINMUX_GPIO(GPIO_FN_CRX1, CRX1_MARK),
-	PINMUX_GPIO(GPIO_FN_CTX0, CTX0_MARK),
-	PINMUX_GPIO(GPIO_FN_CRX0, CRX0_MARK),
-	PINMUX_GPIO(GPIO_FN_CRX0_CRX1, CRX0_CRX1_MARK),
+	GPIO_FN(CTX1),
+	GPIO_FN(CRX1),
+	GPIO_FN(CTX0),
+	GPIO_FN(CRX0),
+	GPIO_FN(CRX0_CRX1),
 
 	/* DMAC */
-	PINMUX_GPIO(GPIO_FN_TEND0, TEND0_MARK),
-	PINMUX_GPIO(GPIO_FN_DACK0, DACK0_MARK),
-	PINMUX_GPIO(GPIO_FN_DREQ0, DREQ0_MARK),
-	PINMUX_GPIO(GPIO_FN_TEND1, TEND1_MARK),
-	PINMUX_GPIO(GPIO_FN_DACK1, DACK1_MARK),
-	PINMUX_GPIO(GPIO_FN_DREQ1, DREQ1_MARK),
+	GPIO_FN(TEND0),
+	GPIO_FN(DACK0),
+	GPIO_FN(DREQ0),
+	GPIO_FN(TEND1),
+	GPIO_FN(DACK1),
+	GPIO_FN(DREQ1),
 
 	/* ADC */
-	PINMUX_GPIO(GPIO_FN_ADTRG, ADTRG_MARK),
+	GPIO_FN(ADTRG),
 
 	/* BSCh */
-	PINMUX_GPIO(GPIO_FN_A25, A25_MARK),
-	PINMUX_GPIO(GPIO_FN_A24, A24_MARK),
-	PINMUX_GPIO(GPIO_FN_A23, A23_MARK),
-	PINMUX_GPIO(GPIO_FN_A22, A22_MARK),
-	PINMUX_GPIO(GPIO_FN_A21, A21_MARK),
-	PINMUX_GPIO(GPIO_FN_A20, A20_MARK),
-	PINMUX_GPIO(GPIO_FN_A19, A19_MARK),
-	PINMUX_GPIO(GPIO_FN_A18, A18_MARK),
-	PINMUX_GPIO(GPIO_FN_A17, A17_MARK),
-	PINMUX_GPIO(GPIO_FN_A16, A16_MARK),
-	PINMUX_GPIO(GPIO_FN_A15, A15_MARK),
-	PINMUX_GPIO(GPIO_FN_A14, A14_MARK),
-	PINMUX_GPIO(GPIO_FN_A13, A13_MARK),
-	PINMUX_GPIO(GPIO_FN_A12, A12_MARK),
-	PINMUX_GPIO(GPIO_FN_A11, A11_MARK),
-	PINMUX_GPIO(GPIO_FN_A10, A10_MARK),
-	PINMUX_GPIO(GPIO_FN_A9, A9_MARK),
-	PINMUX_GPIO(GPIO_FN_A8, A8_MARK),
-	PINMUX_GPIO(GPIO_FN_A7, A7_MARK),
-	PINMUX_GPIO(GPIO_FN_A6, A6_MARK),
-	PINMUX_GPIO(GPIO_FN_A5, A5_MARK),
-	PINMUX_GPIO(GPIO_FN_A4, A4_MARK),
-	PINMUX_GPIO(GPIO_FN_A3, A3_MARK),
-	PINMUX_GPIO(GPIO_FN_A2, A2_MARK),
-	PINMUX_GPIO(GPIO_FN_A1, A1_MARK),
-	PINMUX_GPIO(GPIO_FN_A0, A0_MARK),
-
-	PINMUX_GPIO(GPIO_FN_D15, D15_MARK),
-	PINMUX_GPIO(GPIO_FN_D14, D14_MARK),
-	PINMUX_GPIO(GPIO_FN_D13, D13_MARK),
-	PINMUX_GPIO(GPIO_FN_D12, D12_MARK),
-	PINMUX_GPIO(GPIO_FN_D11, D11_MARK),
-	PINMUX_GPIO(GPIO_FN_D10, D10_MARK),
-	PINMUX_GPIO(GPIO_FN_D9, D9_MARK),
-	PINMUX_GPIO(GPIO_FN_D8, D8_MARK),
-	PINMUX_GPIO(GPIO_FN_D7, D7_MARK),
-	PINMUX_GPIO(GPIO_FN_D6, D6_MARK),
-	PINMUX_GPIO(GPIO_FN_D5, D5_MARK),
-	PINMUX_GPIO(GPIO_FN_D4, D4_MARK),
-	PINMUX_GPIO(GPIO_FN_D3, D3_MARK),
-	PINMUX_GPIO(GPIO_FN_D2, D2_MARK),
-	PINMUX_GPIO(GPIO_FN_D1, D1_MARK),
-	PINMUX_GPIO(GPIO_FN_D0, D0_MARK),
-
-	PINMUX_GPIO(GPIO_FN_BS, BS_MARK),
-	PINMUX_GPIO(GPIO_FN_CS4, CS4_MARK),
-	PINMUX_GPIO(GPIO_FN_CS3, CS3_MARK),
-	PINMUX_GPIO(GPIO_FN_CS2, CS2_MARK),
-	PINMUX_GPIO(GPIO_FN_CS1, CS1_MARK),
-	PINMUX_GPIO(GPIO_FN_CS0, CS0_MARK),
-	PINMUX_GPIO(GPIO_FN_CS6CE1B, CS6CE1B_MARK),
-	PINMUX_GPIO(GPIO_FN_CS5CE1A, CS5CE1A_MARK),
-	PINMUX_GPIO(GPIO_FN_CE2A, CE2A_MARK),
-	PINMUX_GPIO(GPIO_FN_CE2B, CE2B_MARK),
-	PINMUX_GPIO(GPIO_FN_RD, RD_MARK),
-	PINMUX_GPIO(GPIO_FN_RDWR, RDWR_MARK),
-	PINMUX_GPIO(GPIO_FN_ICIOWRAH, ICIOWRAH_MARK),
-	PINMUX_GPIO(GPIO_FN_ICIORD, ICIORD_MARK),
-	PINMUX_GPIO(GPIO_FN_WE1DQMUWE, WE1DQMUWE_MARK),
-	PINMUX_GPIO(GPIO_FN_WE0DQML, WE0DQML_MARK),
-	PINMUX_GPIO(GPIO_FN_RAS, RAS_MARK),
-	PINMUX_GPIO(GPIO_FN_CAS, CAS_MARK),
-	PINMUX_GPIO(GPIO_FN_CKE, CKE_MARK),
-	PINMUX_GPIO(GPIO_FN_WAIT, WAIT_MARK),
-	PINMUX_GPIO(GPIO_FN_BREQ, BREQ_MARK),
-	PINMUX_GPIO(GPIO_FN_BACK, BACK_MARK),
-	PINMUX_GPIO(GPIO_FN_IOIS16, IOIS16_MARK),
+	GPIO_FN(A25),
+	GPIO_FN(A24),
+	GPIO_FN(A23),
+	GPIO_FN(A22),
+	GPIO_FN(A21),
+	GPIO_FN(A20),
+	GPIO_FN(A19),
+	GPIO_FN(A18),
+	GPIO_FN(A17),
+	GPIO_FN(A16),
+	GPIO_FN(A15),
+	GPIO_FN(A14),
+	GPIO_FN(A13),
+	GPIO_FN(A12),
+	GPIO_FN(A11),
+	GPIO_FN(A10),
+	GPIO_FN(A9),
+	GPIO_FN(A8),
+	GPIO_FN(A7),
+	GPIO_FN(A6),
+	GPIO_FN(A5),
+	GPIO_FN(A4),
+	GPIO_FN(A3),
+	GPIO_FN(A2),
+	GPIO_FN(A1),
+	GPIO_FN(A0),
+
+	GPIO_FN(D15),
+	GPIO_FN(D14),
+	GPIO_FN(D13),
+	GPIO_FN(D12),
+	GPIO_FN(D11),
+	GPIO_FN(D10),
+	GPIO_FN(D9),
+	GPIO_FN(D8),
+	GPIO_FN(D7),
+	GPIO_FN(D6),
+	GPIO_FN(D5),
+	GPIO_FN(D4),
+	GPIO_FN(D3),
+	GPIO_FN(D2),
+	GPIO_FN(D1),
+	GPIO_FN(D0),
+
+	GPIO_FN(BS),
+	GPIO_FN(CS4),
+	GPIO_FN(CS3),
+	GPIO_FN(CS2),
+	GPIO_FN(CS1),
+	GPIO_FN(CS0),
+	GPIO_FN(CS6CE1B),
+	GPIO_FN(CS5CE1A),
+	GPIO_FN(CE2A),
+	GPIO_FN(CE2B),
+	GPIO_FN(RD),
+	GPIO_FN(RDWR),
+	GPIO_FN(ICIOWRAH),
+	GPIO_FN(ICIORD),
+	GPIO_FN(WE1DQMUWE),
+	GPIO_FN(WE0DQML),
+	GPIO_FN(RAS),
+	GPIO_FN(CAS),
+	GPIO_FN(CKE),
+	GPIO_FN(WAIT),
+	GPIO_FN(BREQ),
+	GPIO_FN(BACK),
+	GPIO_FN(IOIS16),
 
 	/* TMU */
-	PINMUX_GPIO(GPIO_FN_TIOC4D, TIOC4D_MARK),
-	PINMUX_GPIO(GPIO_FN_TIOC4C, TIOC4C_MARK),
-	PINMUX_GPIO(GPIO_FN_TIOC4B, TIOC4B_MARK),
-	PINMUX_GPIO(GPIO_FN_TIOC4A, TIOC4A_MARK),
-	PINMUX_GPIO(GPIO_FN_TIOC3D, TIOC3D_MARK),
-	PINMUX_GPIO(GPIO_FN_TIOC3C, TIOC3C_MARK),
-	PINMUX_GPIO(GPIO_FN_TIOC3B, TIOC3B_MARK),
-	PINMUX_GPIO(GPIO_FN_TIOC3A, TIOC3A_MARK),
-	PINMUX_GPIO(GPIO_FN_TIOC2B, TIOC2B_MARK),
-	PINMUX_GPIO(GPIO_FN_TIOC1B, TIOC1B_MARK),
-	PINMUX_GPIO(GPIO_FN_TIOC2A, TIOC2A_MARK),
-	PINMUX_GPIO(GPIO_FN_TIOC1A, TIOC1A_MARK),
-	PINMUX_GPIO(GPIO_FN_TIOC0D, TIOC0D_MARK),
-	PINMUX_GPIO(GPIO_FN_TIOC0C, TIOC0C_MARK),
-	PINMUX_GPIO(GPIO_FN_TIOC0B, TIOC0B_MARK),
-	PINMUX_GPIO(GPIO_FN_TIOC0A, TIOC0A_MARK),
-	PINMUX_GPIO(GPIO_FN_TCLKD, TCLKD_MARK),
-	PINMUX_GPIO(GPIO_FN_TCLKC, TCLKC_MARK),
-	PINMUX_GPIO(GPIO_FN_TCLKB, TCLKB_MARK),
-	PINMUX_GPIO(GPIO_FN_TCLKA, TCLKA_MARK),
+	GPIO_FN(TIOC4D),
+	GPIO_FN(TIOC4C),
+	GPIO_FN(TIOC4B),
+	GPIO_FN(TIOC4A),
+	GPIO_FN(TIOC3D),
+	GPIO_FN(TIOC3C),
+	GPIO_FN(TIOC3B),
+	GPIO_FN(TIOC3A),
+	GPIO_FN(TIOC2B),
+	GPIO_FN(TIOC1B),
+	GPIO_FN(TIOC2A),
+	GPIO_FN(TIOC1A),
+	GPIO_FN(TIOC0D),
+	GPIO_FN(TIOC0C),
+	GPIO_FN(TIOC0B),
+	GPIO_FN(TIOC0A),
+	GPIO_FN(TCLKD),
+	GPIO_FN(TCLKC),
+	GPIO_FN(TCLKB),
+	GPIO_FN(TCLKA),
 
 	/* SCIF */
-	PINMUX_GPIO(GPIO_FN_TXD0, TXD0_MARK),
-	PINMUX_GPIO(GPIO_FN_RXD0, RXD0_MARK),
-	PINMUX_GPIO(GPIO_FN_SCK0, SCK0_MARK),
-	PINMUX_GPIO(GPIO_FN_TXD1, TXD1_MARK),
-	PINMUX_GPIO(GPIO_FN_RXD1, RXD1_MARK),
-	PINMUX_GPIO(GPIO_FN_SCK1, SCK1_MARK),
-	PINMUX_GPIO(GPIO_FN_TXD2, TXD2_MARK),
-	PINMUX_GPIO(GPIO_FN_RXD2, RXD2_MARK),
-	PINMUX_GPIO(GPIO_FN_SCK2, SCK2_MARK),
-	PINMUX_GPIO(GPIO_FN_RTS3, RTS3_MARK),
-	PINMUX_GPIO(GPIO_FN_CTS3, CTS3_MARK),
-	PINMUX_GPIO(GPIO_FN_TXD3, TXD3_MARK),
-	PINMUX_GPIO(GPIO_FN_RXD3, RXD3_MARK),
-	PINMUX_GPIO(GPIO_FN_SCK3, SCK3_MARK),
-	PINMUX_GPIO(GPIO_FN_TXD4, TXD4_MARK),
-	PINMUX_GPIO(GPIO_FN_RXD4, RXD4_MARK),
-	PINMUX_GPIO(GPIO_FN_TXD5, TXD5_MARK),
-	PINMUX_GPIO(GPIO_FN_RXD5, RXD5_MARK),
-	PINMUX_GPIO(GPIO_FN_TXD6, TXD6_MARK),
-	PINMUX_GPIO(GPIO_FN_RXD6, RXD6_MARK),
-	PINMUX_GPIO(GPIO_FN_TXD7, TXD7_MARK),
-	PINMUX_GPIO(GPIO_FN_RXD7, RXD7_MARK),
-	PINMUX_GPIO(GPIO_FN_RTS1, RTS1_MARK),
-	PINMUX_GPIO(GPIO_FN_CTS1, CTS1_MARK),
+	GPIO_FN(TXD0),
+	GPIO_FN(RXD0),
+	GPIO_FN(SCK0),
+	GPIO_FN(TXD1),
+	GPIO_FN(RXD1),
+	GPIO_FN(SCK1),
+	GPIO_FN(TXD2),
+	GPIO_FN(RXD2),
+	GPIO_FN(SCK2),
+	GPIO_FN(RTS3),
+	GPIO_FN(CTS3),
+	GPIO_FN(TXD3),
+	GPIO_FN(RXD3),
+	GPIO_FN(SCK3),
+	GPIO_FN(TXD4),
+	GPIO_FN(RXD4),
+	GPIO_FN(TXD5),
+	GPIO_FN(RXD5),
+	GPIO_FN(TXD6),
+	GPIO_FN(RXD6),
+	GPIO_FN(TXD7),
+	GPIO_FN(RXD7),
+	GPIO_FN(RTS1),
+	GPIO_FN(CTS1),
 
 	/* RSPI */
-	PINMUX_GPIO(GPIO_FN_RSPCK0, RSPCK0_MARK),
-	PINMUX_GPIO(GPIO_FN_MOSI0, MOSI0_MARK),
-	PINMUX_GPIO(GPIO_FN_MISO0_PF12, MISO0_PF12_MARK),
-	PINMUX_GPIO(GPIO_FN_MISO1, MISO1_MARK),
-	PINMUX_GPIO(GPIO_FN_SSL00, SSL00_MARK),
-	PINMUX_GPIO(GPIO_FN_RSPCK1, RSPCK1_MARK),
-	PINMUX_GPIO(GPIO_FN_MOSI1, MOSI1_MARK),
-	PINMUX_GPIO(GPIO_FN_MISO1_PG19, MISO1_PG19_MARK),
-	PINMUX_GPIO(GPIO_FN_SSL10, SSL10_MARK),
+	GPIO_FN(RSPCK0),
+	GPIO_FN(MOSI0),
+	GPIO_FN(MISO0_PF12),
+	GPIO_FN(MISO1),
+	GPIO_FN(SSL00),
+	GPIO_FN(RSPCK1),
+	GPIO_FN(MOSI1),
+	GPIO_FN(MISO1_PG19),
+	GPIO_FN(SSL10),
 
 	/* IIC3 */
-	PINMUX_GPIO(GPIO_FN_SCL0, SCL0_MARK),
-	PINMUX_GPIO(GPIO_FN_SCL1, SCL1_MARK),
-	PINMUX_GPIO(GPIO_FN_SCL2, SCL2_MARK),
-	PINMUX_GPIO(GPIO_FN_SDA0, SDA0_MARK),
-	PINMUX_GPIO(GPIO_FN_SDA1, SDA1_MARK),
-	PINMUX_GPIO(GPIO_FN_SDA2, SDA2_MARK),
+	GPIO_FN(SCL0),
+	GPIO_FN(SCL1),
+	GPIO_FN(SCL2),
+	GPIO_FN(SDA0),
+	GPIO_FN(SDA1),
+	GPIO_FN(SDA2),
 
 	/* SSI */
-	PINMUX_GPIO(GPIO_FN_SSISCK0, SSISCK0_MARK),
-	PINMUX_GPIO(GPIO_FN_SSIWS0, SSIWS0_MARK),
-	PINMUX_GPIO(GPIO_FN_SSITXD0, SSITXD0_MARK),
-	PINMUX_GPIO(GPIO_FN_SSIRXD0, SSIRXD0_MARK),
-	PINMUX_GPIO(GPIO_FN_SSIWS1, SSIWS1_MARK),
-	PINMUX_GPIO(GPIO_FN_SSIWS2, SSIWS2_MARK),
-	PINMUX_GPIO(GPIO_FN_SSIWS3, SSIWS3_MARK),
-	PINMUX_GPIO(GPIO_FN_SSISCK1, SSISCK1_MARK),
-	PINMUX_GPIO(GPIO_FN_SSISCK2, SSISCK2_MARK),
-	PINMUX_GPIO(GPIO_FN_SSISCK3, SSISCK3_MARK),
-	PINMUX_GPIO(GPIO_FN_SSIDATA1, SSIDATA1_MARK),
-	PINMUX_GPIO(GPIO_FN_SSIDATA2, SSIDATA2_MARK),
-	PINMUX_GPIO(GPIO_FN_SSIDATA3, SSIDATA3_MARK),
-	PINMUX_GPIO(GPIO_FN_AUDIO_CLK, AUDIO_CLK_MARK),
+	GPIO_FN(SSISCK0),
+	GPIO_FN(SSIWS0),
+	GPIO_FN(SSITXD0),
+	GPIO_FN(SSIRXD0),
+	GPIO_FN(SSIWS1),
+	GPIO_FN(SSIWS2),
+	GPIO_FN(SSIWS3),
+	GPIO_FN(SSISCK1),
+	GPIO_FN(SSISCK2),
+	GPIO_FN(SSISCK3),
+	GPIO_FN(SSIDATA1),
+	GPIO_FN(SSIDATA2),
+	GPIO_FN(SSIDATA3),
+	GPIO_FN(AUDIO_CLK),
 
 	/* SIOF */ /* NOTE Shares AUDIO_CLK with SSI */
-	PINMUX_GPIO(GPIO_FN_SIOFTXD, SIOFTXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SIOFRXD, SIOFRXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SIOFSYNC, SIOFSYNC_MARK),
-	PINMUX_GPIO(GPIO_FN_SIOFSCK, SIOFSCK_MARK),
+	GPIO_FN(SIOFTXD),
+	GPIO_FN(SIOFRXD),
+	GPIO_FN(SIOFSYNC),
+	GPIO_FN(SIOFSCK),
 
 	/* SPDIF */ /* NOTE Shares AUDIO_CLK with SSI */
-	PINMUX_GPIO(GPIO_FN_SPDIF_IN, SPDIF_IN_MARK),
-	PINMUX_GPIO(GPIO_FN_SPDIF_OUT, SPDIF_OUT_MARK),
+	GPIO_FN(SPDIF_IN),
+	GPIO_FN(SPDIF_OUT),
 
 	/* NANDFMC */ /* NOTE Controller is not available in boot mode 0 */
-	PINMUX_GPIO(GPIO_FN_FCE, FCE_MARK),
-	PINMUX_GPIO(GPIO_FN_FRB, FRB_MARK),
+	GPIO_FN(FCE),
+	GPIO_FN(FRB),
 
 	/* VDC3 */
-	PINMUX_GPIO(GPIO_FN_DV_CLK, DV_CLK_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_VSYNC, DV_VSYNC_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_HSYNC, DV_HSYNC_MARK),
-
-	PINMUX_GPIO(GPIO_FN_DV_DATA7, DV_DATA7_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_DATA6, DV_DATA6_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_DATA5, DV_DATA5_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_DATA4, DV_DATA4_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_DATA3, DV_DATA3_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_DATA2, DV_DATA2_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_DATA1, DV_DATA1_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_DATA0, DV_DATA0_MARK),
-
-	PINMUX_GPIO(GPIO_FN_LCD_CLK, LCD_CLK_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_EXTCLK, LCD_EXTCLK_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_VSYNC, LCD_VSYNC_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_HSYNC, LCD_HSYNC_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DE, LCD_DE_MARK),
-
-	PINMUX_GPIO(GPIO_FN_LCD_DATA15, LCD_DATA15_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA14, LCD_DATA14_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA13, LCD_DATA13_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA12, LCD_DATA12_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA11, LCD_DATA11_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA10, LCD_DATA10_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA9, LCD_DATA9_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA8, LCD_DATA8_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA7, LCD_DATA7_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA6, LCD_DATA6_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA5, LCD_DATA5_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA4, LCD_DATA4_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA3, LCD_DATA3_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA2, LCD_DATA2_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA1, LCD_DATA1_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA0, LCD_DATA0_MARK),
-
-	PINMUX_GPIO(GPIO_FN_LCD_M_DISP, LCD_M_DISP_MARK),
+	GPIO_FN(DV_CLK),
+	GPIO_FN(DV_VSYNC),
+	GPIO_FN(DV_HSYNC),
+
+	GPIO_FN(DV_DATA7),
+	GPIO_FN(DV_DATA6),
+	GPIO_FN(DV_DATA5),
+	GPIO_FN(DV_DATA4),
+	GPIO_FN(DV_DATA3),
+	GPIO_FN(DV_DATA2),
+	GPIO_FN(DV_DATA1),
+	GPIO_FN(DV_DATA0),
+
+	GPIO_FN(LCD_CLK),
+	GPIO_FN(LCD_EXTCLK),
+	GPIO_FN(LCD_VSYNC),
+	GPIO_FN(LCD_HSYNC),
+	GPIO_FN(LCD_DE),
+
+	GPIO_FN(LCD_DATA15),
+	GPIO_FN(LCD_DATA14),
+	GPIO_FN(LCD_DATA13),
+	GPIO_FN(LCD_DATA12),
+	GPIO_FN(LCD_DATA11),
+	GPIO_FN(LCD_DATA10),
+	GPIO_FN(LCD_DATA9),
+	GPIO_FN(LCD_DATA8),
+	GPIO_FN(LCD_DATA7),
+	GPIO_FN(LCD_DATA6),
+	GPIO_FN(LCD_DATA5),
+	GPIO_FN(LCD_DATA4),
+	GPIO_FN(LCD_DATA3),
+	GPIO_FN(LCD_DATA2),
+	GPIO_FN(LCD_DATA1),
+	GPIO_FN(LCD_DATA0),
+
+	GPIO_FN(LCD_M_DISP),
 };
 
-static struct pinmux_cfg_reg pinmux_config_regs[] = {
+static const struct pinmux_cfg_reg pinmux_config_regs[] = {
 	{ PINMUX_CFG_REG("PAIOR0", 0xfffe3812, 16, 1) {
 		0, 0, 0, 0, 0, 0, 0, 0,
 		0, 0, 0, 0, 0, 0, 0, 0,
@@ -2032,7 +2036,7 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = {
 	{}
 };
 
-static struct pinmux_data_reg pinmux_data_regs[] = {
+static const struct pinmux_data_reg pinmux_data_regs[] = {
 	{ PINMUX_DATA_REG("PADR1", 0xfffe3814, 16) {
 		0, 0, 0, 0, 0, 0, 0, PA3_DATA,
 		0, 0, 0, 0, 0, 0, 0, PA2_DATA }
@@ -2110,19 +2114,17 @@ static struct pinmux_data_reg pinmux_data_regs[] = {
 	{ }
 };
 
-struct sh_pfc_soc_info sh7264_pinmux_info = {
+const struct sh_pfc_soc_info sh7264_pinmux_info = {
 	.name = "sh7264_pfc",
-	.reserved_id = PINMUX_RESERVED,
-	.data = { PINMUX_DATA_BEGIN, PINMUX_DATA_END },
 	.input = { PINMUX_INPUT_BEGIN, PINMUX_INPUT_END, FORCE_IN },
 	.output = { PINMUX_OUTPUT_BEGIN, PINMUX_OUTPUT_END, FORCE_OUT },
-	.mark = { PINMUX_MARK_BEGIN, PINMUX_MARK_END },
 	.function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END },
 
-	.first_gpio = GPIO_PA3,
-	.last_gpio = GPIO_FN_LCD_M_DISP,
+	.pins = pinmux_pins,
+	.nr_pins = ARRAY_SIZE(pinmux_pins),
+	.func_gpios = pinmux_func_gpios,
+	.nr_func_gpios = ARRAY_SIZE(pinmux_func_gpios),
 
-	.gpios = pinmux_gpios,
 	.cfg_regs = pinmux_config_regs,
 	.data_regs = pinmux_data_regs,
 
diff --git a/drivers/pinctrl/sh-pfc/pfc-sh7269.c b/drivers/pinctrl/sh-pfc/pfc-sh7269.c
index b1b5d6d..4c401a7 100644
--- a/drivers/pinctrl/sh-pfc/pfc-sh7269.c
+++ b/drivers/pinctrl/sh-pfc/pfc-sh7269.c
@@ -781,7 +781,7 @@ enum {
 	PINMUX_MARK_END,
 };
 
-static pinmux_enum_t pinmux_data[] = {
+static const pinmux_enum_t pinmux_data[] = {
 
 	/* Port A */
 	PINMUX_DATA(PA1_DATA, PA1_IN),
@@ -1452,7 +1452,7 @@ static pinmux_enum_t pinmux_data[] = {
 	PINMUX_DATA(PWM1A_MARK, PJ0MD_100),
 };
 
-static struct pinmux_gpio pinmux_gpios[] = {
+static struct sh_pfc_pin pinmux_pins[] = {
 	/* Port A */
 	PINMUX_GPIO(GPIO_PA1, PA1_DATA),
 	PINMUX_GPIO(GPIO_PA0, PA0_DATA),
@@ -1613,339 +1613,343 @@ static struct pinmux_gpio pinmux_gpios[] = {
 	PINMUX_GPIO(GPIO_PJ2, PJ2_DATA),
 	PINMUX_GPIO(GPIO_PJ1, PJ1_DATA),
 	PINMUX_GPIO(GPIO_PJ0, PJ0_DATA),
+};
+
+#define PINMUX_FN_BASE	ARRAY_SIZE(pinmux_pins)
 
+static const struct pinmux_func pinmux_func_gpios[] = {
 	/* INTC */
-	PINMUX_GPIO(GPIO_FN_IRQ7_PG, IRQ7_PG_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ6_PG, IRQ6_PG_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ5_PG, IRQ5_PG_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ4_PG, IRQ4_PG_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ3_PG, IRQ3_PG_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ2_PG, IRQ2_PG_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ1_PG, IRQ1_PG_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ0_PG, IRQ0_PG_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ7_PF, IRQ7_PF_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ6_PF, IRQ6_PF_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ5_PF, IRQ5_PF_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ4_PF, IRQ4_PF_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ3_PJ, IRQ3_PJ_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ2_PJ, IRQ2_PJ_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ1_PJ, IRQ1_PJ_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ0_PJ, IRQ0_PJ_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ1_PC, IRQ1_PC_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ0_PC, IRQ0_PC_MARK),
-
-	PINMUX_GPIO(GPIO_FN_PINT7_PG, PINT7_PG_MARK),
-	PINMUX_GPIO(GPIO_FN_PINT6_PG, PINT6_PG_MARK),
-	PINMUX_GPIO(GPIO_FN_PINT5_PG, PINT5_PG_MARK),
-	PINMUX_GPIO(GPIO_FN_PINT4_PG, PINT4_PG_MARK),
-	PINMUX_GPIO(GPIO_FN_PINT3_PG, PINT3_PG_MARK),
-	PINMUX_GPIO(GPIO_FN_PINT2_PG, PINT2_PG_MARK),
-	PINMUX_GPIO(GPIO_FN_PINT1_PG, PINT1_PG_MARK),
-	PINMUX_GPIO(GPIO_FN_PINT0_PG, PINT0_PG_MARK),
-	PINMUX_GPIO(GPIO_FN_PINT7_PH, PINT7_PH_MARK),
-	PINMUX_GPIO(GPIO_FN_PINT6_PH, PINT6_PH_MARK),
-	PINMUX_GPIO(GPIO_FN_PINT5_PH, PINT5_PH_MARK),
-	PINMUX_GPIO(GPIO_FN_PINT4_PH, PINT4_PH_MARK),
-	PINMUX_GPIO(GPIO_FN_PINT3_PH, PINT3_PH_MARK),
-	PINMUX_GPIO(GPIO_FN_PINT2_PH, PINT2_PH_MARK),
-	PINMUX_GPIO(GPIO_FN_PINT1_PH, PINT1_PH_MARK),
-	PINMUX_GPIO(GPIO_FN_PINT0_PH, PINT0_PH_MARK),
-	PINMUX_GPIO(GPIO_FN_PINT7_PJ, PINT7_PJ_MARK),
-	PINMUX_GPIO(GPIO_FN_PINT6_PJ, PINT6_PJ_MARK),
-	PINMUX_GPIO(GPIO_FN_PINT5_PJ, PINT5_PJ_MARK),
-	PINMUX_GPIO(GPIO_FN_PINT4_PJ, PINT4_PJ_MARK),
-	PINMUX_GPIO(GPIO_FN_PINT3_PJ, PINT3_PJ_MARK),
-	PINMUX_GPIO(GPIO_FN_PINT2_PJ, PINT2_PJ_MARK),
-	PINMUX_GPIO(GPIO_FN_PINT1_PJ, PINT1_PJ_MARK),
-	PINMUX_GPIO(GPIO_FN_PINT0_PJ, PINT0_PJ_MARK),
+	GPIO_FN(IRQ7_PG),
+	GPIO_FN(IRQ6_PG),
+	GPIO_FN(IRQ5_PG),
+	GPIO_FN(IRQ4_PG),
+	GPIO_FN(IRQ3_PG),
+	GPIO_FN(IRQ2_PG),
+	GPIO_FN(IRQ1_PG),
+	GPIO_FN(IRQ0_PG),
+	GPIO_FN(IRQ7_PF),
+	GPIO_FN(IRQ6_PF),
+	GPIO_FN(IRQ5_PF),
+	GPIO_FN(IRQ4_PF),
+	GPIO_FN(IRQ3_PJ),
+	GPIO_FN(IRQ2_PJ),
+	GPIO_FN(IRQ1_PJ),
+	GPIO_FN(IRQ0_PJ),
+	GPIO_FN(IRQ1_PC),
+	GPIO_FN(IRQ0_PC),
+
+	GPIO_FN(PINT7_PG),
+	GPIO_FN(PINT6_PG),
+	GPIO_FN(PINT5_PG),
+	GPIO_FN(PINT4_PG),
+	GPIO_FN(PINT3_PG),
+	GPIO_FN(PINT2_PG),
+	GPIO_FN(PINT1_PG),
+	GPIO_FN(PINT0_PG),
+	GPIO_FN(PINT7_PH),
+	GPIO_FN(PINT6_PH),
+	GPIO_FN(PINT5_PH),
+	GPIO_FN(PINT4_PH),
+	GPIO_FN(PINT3_PH),
+	GPIO_FN(PINT2_PH),
+	GPIO_FN(PINT1_PH),
+	GPIO_FN(PINT0_PH),
+	GPIO_FN(PINT7_PJ),
+	GPIO_FN(PINT6_PJ),
+	GPIO_FN(PINT5_PJ),
+	GPIO_FN(PINT4_PJ),
+	GPIO_FN(PINT3_PJ),
+	GPIO_FN(PINT2_PJ),
+	GPIO_FN(PINT1_PJ),
+	GPIO_FN(PINT0_PJ),
 
 	/* WDT */
-	PINMUX_GPIO(GPIO_FN_WDTOVF, WDTOVF_MARK),
+	GPIO_FN(WDTOVF),
 
 	/* CAN */
-	PINMUX_GPIO(GPIO_FN_CTX1, CTX1_MARK),
-	PINMUX_GPIO(GPIO_FN_CRX1, CRX1_MARK),
-	PINMUX_GPIO(GPIO_FN_CTX0, CTX0_MARK),
-	PINMUX_GPIO(GPIO_FN_CRX0, CRX0_MARK),
-	PINMUX_GPIO(GPIO_FN_CRX0_CRX1, CRX0_CRX1_MARK),
-	PINMUX_GPIO(GPIO_FN_CRX0_CRX1_CRX2, CRX0_CRX1_CRX2_MARK),
+	GPIO_FN(CTX1),
+	GPIO_FN(CRX1),
+	GPIO_FN(CTX0),
+	GPIO_FN(CRX0),
+	GPIO_FN(CRX0_CRX1),
+	GPIO_FN(CRX0_CRX1_CRX2),
 
 	/* DMAC */
-	PINMUX_GPIO(GPIO_FN_TEND0, TEND0_MARK),
-	PINMUX_GPIO(GPIO_FN_DACK0, DACK0_MARK),
-	PINMUX_GPIO(GPIO_FN_DREQ0, DREQ0_MARK),
-	PINMUX_GPIO(GPIO_FN_TEND1, TEND1_MARK),
-	PINMUX_GPIO(GPIO_FN_DACK1, DACK1_MARK),
-	PINMUX_GPIO(GPIO_FN_DREQ1, DREQ1_MARK),
+	GPIO_FN(TEND0),
+	GPIO_FN(DACK0),
+	GPIO_FN(DREQ0),
+	GPIO_FN(TEND1),
+	GPIO_FN(DACK1),
+	GPIO_FN(DREQ1),
 
 	/* ADC */
-	PINMUX_GPIO(GPIO_FN_ADTRG, ADTRG_MARK),
+	GPIO_FN(ADTRG),
 
 	/* BSCh */
-	PINMUX_GPIO(GPIO_FN_A25, A25_MARK),
-	PINMUX_GPIO(GPIO_FN_A24, A24_MARK),
-	PINMUX_GPIO(GPIO_FN_A23, A23_MARK),
-	PINMUX_GPIO(GPIO_FN_A22, A22_MARK),
-	PINMUX_GPIO(GPIO_FN_A21, A21_MARK),
-	PINMUX_GPIO(GPIO_FN_A20, A20_MARK),
-	PINMUX_GPIO(GPIO_FN_A19, A19_MARK),
-	PINMUX_GPIO(GPIO_FN_A18, A18_MARK),
-	PINMUX_GPIO(GPIO_FN_A17, A17_MARK),
-	PINMUX_GPIO(GPIO_FN_A16, A16_MARK),
-	PINMUX_GPIO(GPIO_FN_A15, A15_MARK),
-	PINMUX_GPIO(GPIO_FN_A14, A14_MARK),
-	PINMUX_GPIO(GPIO_FN_A13, A13_MARK),
-	PINMUX_GPIO(GPIO_FN_A12, A12_MARK),
-	PINMUX_GPIO(GPIO_FN_A11, A11_MARK),
-	PINMUX_GPIO(GPIO_FN_A10, A10_MARK),
-	PINMUX_GPIO(GPIO_FN_A9, A9_MARK),
-	PINMUX_GPIO(GPIO_FN_A8, A8_MARK),
-	PINMUX_GPIO(GPIO_FN_A7, A7_MARK),
-	PINMUX_GPIO(GPIO_FN_A6, A6_MARK),
-	PINMUX_GPIO(GPIO_FN_A5, A5_MARK),
-	PINMUX_GPIO(GPIO_FN_A4, A4_MARK),
-	PINMUX_GPIO(GPIO_FN_A3, A3_MARK),
-	PINMUX_GPIO(GPIO_FN_A2, A2_MARK),
-	PINMUX_GPIO(GPIO_FN_A1, A1_MARK),
-	PINMUX_GPIO(GPIO_FN_A0, A0_MARK),
-
-	PINMUX_GPIO(GPIO_FN_D15, D15_MARK),
-	PINMUX_GPIO(GPIO_FN_D14, D14_MARK),
-	PINMUX_GPIO(GPIO_FN_D13, D13_MARK),
-	PINMUX_GPIO(GPIO_FN_D12, D12_MARK),
-	PINMUX_GPIO(GPIO_FN_D11, D11_MARK),
-	PINMUX_GPIO(GPIO_FN_D10, D10_MARK),
-	PINMUX_GPIO(GPIO_FN_D9, D9_MARK),
-	PINMUX_GPIO(GPIO_FN_D8, D8_MARK),
-	PINMUX_GPIO(GPIO_FN_D7, D7_MARK),
-	PINMUX_GPIO(GPIO_FN_D6, D6_MARK),
-	PINMUX_GPIO(GPIO_FN_D5, D5_MARK),
-	PINMUX_GPIO(GPIO_FN_D4, D4_MARK),
-	PINMUX_GPIO(GPIO_FN_D3, D3_MARK),
-	PINMUX_GPIO(GPIO_FN_D2, D2_MARK),
-	PINMUX_GPIO(GPIO_FN_D1, D1_MARK),
-	PINMUX_GPIO(GPIO_FN_D0, D0_MARK),
-
-	PINMUX_GPIO(GPIO_FN_BS, BS_MARK),
-	PINMUX_GPIO(GPIO_FN_CS4, CS4_MARK),
-	PINMUX_GPIO(GPIO_FN_CS3, CS3_MARK),
-	PINMUX_GPIO(GPIO_FN_CS2, CS2_MARK),
-	PINMUX_GPIO(GPIO_FN_CS1, CS1_MARK),
-	PINMUX_GPIO(GPIO_FN_CS0, CS0_MARK),
-	PINMUX_GPIO(GPIO_FN_CS5CE1A, CS5CE1A_MARK),
-	PINMUX_GPIO(GPIO_FN_CE2A, CE2A_MARK),
-	PINMUX_GPIO(GPIO_FN_CE2B, CE2B_MARK),
-	PINMUX_GPIO(GPIO_FN_RD, RD_MARK),
-	PINMUX_GPIO(GPIO_FN_RDWR, RDWR_MARK),
-	PINMUX_GPIO(GPIO_FN_WE3ICIOWRAHDQMUU, WE3ICIOWRAHDQMUU_MARK),
-	PINMUX_GPIO(GPIO_FN_WE2ICIORDDQMUL, WE2ICIORDDQMUL_MARK),
-	PINMUX_GPIO(GPIO_FN_WE1DQMUWE, WE1DQMUWE_MARK),
-	PINMUX_GPIO(GPIO_FN_WE0DQML, WE0DQML_MARK),
-	PINMUX_GPIO(GPIO_FN_RAS, RAS_MARK),
-	PINMUX_GPIO(GPIO_FN_CAS, CAS_MARK),
-	PINMUX_GPIO(GPIO_FN_CKE, CKE_MARK),
-	PINMUX_GPIO(GPIO_FN_WAIT, WAIT_MARK),
-	PINMUX_GPIO(GPIO_FN_BREQ, BREQ_MARK),
-	PINMUX_GPIO(GPIO_FN_BACK, BACK_MARK),
-	PINMUX_GPIO(GPIO_FN_IOIS16, IOIS16_MARK),
+	GPIO_FN(A25),
+	GPIO_FN(A24),
+	GPIO_FN(A23),
+	GPIO_FN(A22),
+	GPIO_FN(A21),
+	GPIO_FN(A20),
+	GPIO_FN(A19),
+	GPIO_FN(A18),
+	GPIO_FN(A17),
+	GPIO_FN(A16),
+	GPIO_FN(A15),
+	GPIO_FN(A14),
+	GPIO_FN(A13),
+	GPIO_FN(A12),
+	GPIO_FN(A11),
+	GPIO_FN(A10),
+	GPIO_FN(A9),
+	GPIO_FN(A8),
+	GPIO_FN(A7),
+	GPIO_FN(A6),
+	GPIO_FN(A5),
+	GPIO_FN(A4),
+	GPIO_FN(A3),
+	GPIO_FN(A2),
+	GPIO_FN(A1),
+	GPIO_FN(A0),
+
+	GPIO_FN(D15),
+	GPIO_FN(D14),
+	GPIO_FN(D13),
+	GPIO_FN(D12),
+	GPIO_FN(D11),
+	GPIO_FN(D10),
+	GPIO_FN(D9),
+	GPIO_FN(D8),
+	GPIO_FN(D7),
+	GPIO_FN(D6),
+	GPIO_FN(D5),
+	GPIO_FN(D4),
+	GPIO_FN(D3),
+	GPIO_FN(D2),
+	GPIO_FN(D1),
+	GPIO_FN(D0),
+
+	GPIO_FN(BS),
+	GPIO_FN(CS4),
+	GPIO_FN(CS3),
+	GPIO_FN(CS2),
+	GPIO_FN(CS1),
+	GPIO_FN(CS0),
+	GPIO_FN(CS5CE1A),
+	GPIO_FN(CE2A),
+	GPIO_FN(CE2B),
+	GPIO_FN(RD),
+	GPIO_FN(RDWR),
+	GPIO_FN(WE3ICIOWRAHDQMUU),
+	GPIO_FN(WE2ICIORDDQMUL),
+	GPIO_FN(WE1DQMUWE),
+	GPIO_FN(WE0DQML),
+	GPIO_FN(RAS),
+	GPIO_FN(CAS),
+	GPIO_FN(CKE),
+	GPIO_FN(WAIT),
+	GPIO_FN(BREQ),
+	GPIO_FN(BACK),
+	GPIO_FN(IOIS16),
 
 	/* TMU */
-	PINMUX_GPIO(GPIO_FN_TIOC4D, TIOC4D_MARK),
-	PINMUX_GPIO(GPIO_FN_TIOC4C, TIOC4C_MARK),
-	PINMUX_GPIO(GPIO_FN_TIOC4B, TIOC4B_MARK),
-	PINMUX_GPIO(GPIO_FN_TIOC4A, TIOC4A_MARK),
-	PINMUX_GPIO(GPIO_FN_TIOC3D, TIOC3D_MARK),
-	PINMUX_GPIO(GPIO_FN_TIOC3C, TIOC3C_MARK),
-	PINMUX_GPIO(GPIO_FN_TIOC3B, TIOC3B_MARK),
-	PINMUX_GPIO(GPIO_FN_TIOC3A, TIOC3A_MARK),
-	PINMUX_GPIO(GPIO_FN_TIOC2B, TIOC2B_MARK),
-	PINMUX_GPIO(GPIO_FN_TIOC1B, TIOC1B_MARK),
-	PINMUX_GPIO(GPIO_FN_TIOC2A, TIOC2A_MARK),
-	PINMUX_GPIO(GPIO_FN_TIOC1A, TIOC1A_MARK),
-	PINMUX_GPIO(GPIO_FN_TIOC0D, TIOC0D_MARK),
-	PINMUX_GPIO(GPIO_FN_TIOC0C, TIOC0C_MARK),
-	PINMUX_GPIO(GPIO_FN_TIOC0B, TIOC0B_MARK),
-	PINMUX_GPIO(GPIO_FN_TIOC0A, TIOC0A_MARK),
-	PINMUX_GPIO(GPIO_FN_TCLKD, TCLKD_MARK),
-	PINMUX_GPIO(GPIO_FN_TCLKC, TCLKC_MARK),
-	PINMUX_GPIO(GPIO_FN_TCLKB, TCLKB_MARK),
-	PINMUX_GPIO(GPIO_FN_TCLKA, TCLKA_MARK),
+	GPIO_FN(TIOC4D),
+	GPIO_FN(TIOC4C),
+	GPIO_FN(TIOC4B),
+	GPIO_FN(TIOC4A),
+	GPIO_FN(TIOC3D),
+	GPIO_FN(TIOC3C),
+	GPIO_FN(TIOC3B),
+	GPIO_FN(TIOC3A),
+	GPIO_FN(TIOC2B),
+	GPIO_FN(TIOC1B),
+	GPIO_FN(TIOC2A),
+	GPIO_FN(TIOC1A),
+	GPIO_FN(TIOC0D),
+	GPIO_FN(TIOC0C),
+	GPIO_FN(TIOC0B),
+	GPIO_FN(TIOC0A),
+	GPIO_FN(TCLKD),
+	GPIO_FN(TCLKC),
+	GPIO_FN(TCLKB),
+	GPIO_FN(TCLKA),
 
 	/* SCIF */
-	PINMUX_GPIO(GPIO_FN_SCK0, SCK0_MARK),
-	PINMUX_GPIO(GPIO_FN_TXD0, TXD0_MARK),
-	PINMUX_GPIO(GPIO_FN_RXD0, RXD0_MARK),
-	PINMUX_GPIO(GPIO_FN_SCK1, SCK1_MARK),
-	PINMUX_GPIO(GPIO_FN_TXD1, TXD1_MARK),
-	PINMUX_GPIO(GPIO_FN_RXD1, RXD1_MARK),
-	PINMUX_GPIO(GPIO_FN_RTS1, RTS1_MARK),
-	PINMUX_GPIO(GPIO_FN_CTS1, CTS1_MARK),
-	PINMUX_GPIO(GPIO_FN_SCK2, SCK2_MARK),
-	PINMUX_GPIO(GPIO_FN_TXD2, TXD2_MARK),
-	PINMUX_GPIO(GPIO_FN_RXD2, RXD2_MARK),
-	PINMUX_GPIO(GPIO_FN_SCK3, SCK3_MARK),
-	PINMUX_GPIO(GPIO_FN_TXD3, TXD3_MARK),
-	PINMUX_GPIO(GPIO_FN_RXD3, RXD3_MARK),
-	PINMUX_GPIO(GPIO_FN_SCK4, SCK4_MARK),
-	PINMUX_GPIO(GPIO_FN_TXD4, TXD4_MARK),
-	PINMUX_GPIO(GPIO_FN_RXD4, RXD4_MARK),
-	PINMUX_GPIO(GPIO_FN_SCK5, SCK5_MARK),
-	PINMUX_GPIO(GPIO_FN_TXD5, TXD5_MARK),
-	PINMUX_GPIO(GPIO_FN_RXD5, RXD5_MARK),
-	PINMUX_GPIO(GPIO_FN_RTS5, RTS5_MARK),
-	PINMUX_GPIO(GPIO_FN_CTS5, CTS5_MARK),
-	PINMUX_GPIO(GPIO_FN_SCK6, SCK6_MARK),
-	PINMUX_GPIO(GPIO_FN_TXD6, TXD6_MARK),
-	PINMUX_GPIO(GPIO_FN_RXD6, RXD6_MARK),
-	PINMUX_GPIO(GPIO_FN_SCK7, SCK7_MARK),
-	PINMUX_GPIO(GPIO_FN_TXD7, TXD7_MARK),
-	PINMUX_GPIO(GPIO_FN_RXD7, RXD7_MARK),
-	PINMUX_GPIO(GPIO_FN_RTS7, RTS7_MARK),
-	PINMUX_GPIO(GPIO_FN_CTS7, CTS7_MARK),
+	GPIO_FN(SCK0),
+	GPIO_FN(TXD0),
+	GPIO_FN(RXD0),
+	GPIO_FN(SCK1),
+	GPIO_FN(TXD1),
+	GPIO_FN(RXD1),
+	GPIO_FN(RTS1),
+	GPIO_FN(CTS1),
+	GPIO_FN(SCK2),
+	GPIO_FN(TXD2),
+	GPIO_FN(RXD2),
+	GPIO_FN(SCK3),
+	GPIO_FN(TXD3),
+	GPIO_FN(RXD3),
+	GPIO_FN(SCK4),
+	GPIO_FN(TXD4),
+	GPIO_FN(RXD4),
+	GPIO_FN(SCK5),
+	GPIO_FN(TXD5),
+	GPIO_FN(RXD5),
+	GPIO_FN(RTS5),
+	GPIO_FN(CTS5),
+	GPIO_FN(SCK6),
+	GPIO_FN(TXD6),
+	GPIO_FN(RXD6),
+	GPIO_FN(SCK7),
+	GPIO_FN(TXD7),
+	GPIO_FN(RXD7),
+	GPIO_FN(RTS7),
+	GPIO_FN(CTS7),
 
 	/* RSPI */
-	PINMUX_GPIO(GPIO_FN_RSPCK0_PJ16, RSPCK0_PJ16_MARK),
-	PINMUX_GPIO(GPIO_FN_SSL00_PJ17, SSL00_PJ17_MARK),
-	PINMUX_GPIO(GPIO_FN_MOSI0_PJ18, MOSI0_PJ18_MARK),
-	PINMUX_GPIO(GPIO_FN_MISO0_PJ19, MISO0_PJ19_MARK),
-	PINMUX_GPIO(GPIO_FN_RSPCK0_PB17, RSPCK0_PB17_MARK),
-	PINMUX_GPIO(GPIO_FN_SSL00_PB18, SSL00_PB18_MARK),
-	PINMUX_GPIO(GPIO_FN_MOSI0_PB19, MOSI0_PB19_MARK),
-	PINMUX_GPIO(GPIO_FN_MISO0_PB20, MISO0_PB20_MARK),
-	PINMUX_GPIO(GPIO_FN_RSPCK1, RSPCK1_MARK),
-	PINMUX_GPIO(GPIO_FN_MOSI1, MOSI1_MARK),
-	PINMUX_GPIO(GPIO_FN_MISO1, MISO1_MARK),
-	PINMUX_GPIO(GPIO_FN_SSL10, SSL10_MARK),
+	GPIO_FN(RSPCK0_PJ16),
+	GPIO_FN(SSL00_PJ17),
+	GPIO_FN(MOSI0_PJ18),
+	GPIO_FN(MISO0_PJ19),
+	GPIO_FN(RSPCK0_PB17),
+	GPIO_FN(SSL00_PB18),
+	GPIO_FN(MOSI0_PB19),
+	GPIO_FN(MISO0_PB20),
+	GPIO_FN(RSPCK1),
+	GPIO_FN(MOSI1),
+	GPIO_FN(MISO1),
+	GPIO_FN(SSL10),
 
 	/* IIC3 */
-	PINMUX_GPIO(GPIO_FN_SCL0, SCL0_MARK),
-	PINMUX_GPIO(GPIO_FN_SCL1, SCL1_MARK),
-	PINMUX_GPIO(GPIO_FN_SCL2, SCL2_MARK),
-	PINMUX_GPIO(GPIO_FN_SDA0, SDA0_MARK),
-	PINMUX_GPIO(GPIO_FN_SDA1, SDA1_MARK),
-	PINMUX_GPIO(GPIO_FN_SDA2, SDA2_MARK),
+	GPIO_FN(SCL0),
+	GPIO_FN(SCL1),
+	GPIO_FN(SCL2),
+	GPIO_FN(SDA0),
+	GPIO_FN(SDA1),
+	GPIO_FN(SDA2),
 
 	/* SSI */
-	PINMUX_GPIO(GPIO_FN_SSISCK0, SSISCK0_MARK),
-	PINMUX_GPIO(GPIO_FN_SSIWS0, SSIWS0_MARK),
-	PINMUX_GPIO(GPIO_FN_SSITXD0, SSITXD0_MARK),
-	PINMUX_GPIO(GPIO_FN_SSIRXD0, SSIRXD0_MARK),
-	PINMUX_GPIO(GPIO_FN_SSIWS1, SSIWS1_MARK),
-	PINMUX_GPIO(GPIO_FN_SSIWS2, SSIWS2_MARK),
-	PINMUX_GPIO(GPIO_FN_SSIWS3, SSIWS3_MARK),
-	PINMUX_GPIO(GPIO_FN_SSISCK1, SSISCK1_MARK),
-	PINMUX_GPIO(GPIO_FN_SSISCK2, SSISCK2_MARK),
-	PINMUX_GPIO(GPIO_FN_SSISCK3, SSISCK3_MARK),
-	PINMUX_GPIO(GPIO_FN_SSIDATA1, SSIDATA1_MARK),
-	PINMUX_GPIO(GPIO_FN_SSIDATA2, SSIDATA2_MARK),
-	PINMUX_GPIO(GPIO_FN_SSIDATA3, SSIDATA3_MARK),
-	PINMUX_GPIO(GPIO_FN_AUDIO_CLK, AUDIO_CLK_MARK),
-	PINMUX_GPIO(GPIO_FN_AUDIO_XOUT, AUDIO_XOUT_MARK),
+	GPIO_FN(SSISCK0),
+	GPIO_FN(SSIWS0),
+	GPIO_FN(SSITXD0),
+	GPIO_FN(SSIRXD0),
+	GPIO_FN(SSIWS1),
+	GPIO_FN(SSIWS2),
+	GPIO_FN(SSIWS3),
+	GPIO_FN(SSISCK1),
+	GPIO_FN(SSISCK2),
+	GPIO_FN(SSISCK3),
+	GPIO_FN(SSIDATA1),
+	GPIO_FN(SSIDATA2),
+	GPIO_FN(SSIDATA3),
+	GPIO_FN(AUDIO_CLK),
+	GPIO_FN(AUDIO_XOUT),
 
 	/* SIOF */ /* NOTE Shares AUDIO_CLK with SSI */
-	PINMUX_GPIO(GPIO_FN_SIOFTXD, SIOFTXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SIOFRXD, SIOFRXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SIOFSYNC, SIOFSYNC_MARK),
-	PINMUX_GPIO(GPIO_FN_SIOFSCK, SIOFSCK_MARK),
+	GPIO_FN(SIOFTXD),
+	GPIO_FN(SIOFRXD),
+	GPIO_FN(SIOFSYNC),
+	GPIO_FN(SIOFSCK),
 
 	/* SPDIF */ /* NOTE Shares AUDIO_CLK with SSI */
-	PINMUX_GPIO(GPIO_FN_SPDIF_IN, SPDIF_IN_MARK),
-	PINMUX_GPIO(GPIO_FN_SPDIF_OUT, SPDIF_OUT_MARK),
+	GPIO_FN(SPDIF_IN),
+	GPIO_FN(SPDIF_OUT),
 
 	/* NANDFMC */ /* NOTE Controller is not available in boot mode 0 */
-	PINMUX_GPIO(GPIO_FN_FCE, FCE_MARK),
-	PINMUX_GPIO(GPIO_FN_FRB, FRB_MARK),
+	GPIO_FN(FCE),
+	GPIO_FN(FRB),
 
 	/* VDC3 */
-	PINMUX_GPIO(GPIO_FN_DV_CLK, DV_CLK_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_VSYNC, DV_VSYNC_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_HSYNC, DV_HSYNC_MARK),
-
-	PINMUX_GPIO(GPIO_FN_DV_DATA23, DV_DATA23_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_DATA22, DV_DATA22_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_DATA21, DV_DATA21_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_DATA20, DV_DATA20_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_DATA19, DV_DATA19_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_DATA18, DV_DATA18_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_DATA17, DV_DATA17_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_DATA16, DV_DATA16_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_DATA15, DV_DATA15_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_DATA14, DV_DATA14_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_DATA13, DV_DATA13_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_DATA12, DV_DATA12_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_DATA11, DV_DATA11_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_DATA10, DV_DATA10_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_DATA9, DV_DATA9_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_DATA8, DV_DATA8_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_DATA7, DV_DATA7_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_DATA6, DV_DATA6_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_DATA5, DV_DATA5_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_DATA4, DV_DATA4_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_DATA3, DV_DATA3_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_DATA2, DV_DATA2_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_DATA1, DV_DATA1_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_DATA0, DV_DATA0_MARK),
-
-	PINMUX_GPIO(GPIO_FN_LCD_CLK, LCD_CLK_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_EXTCLK, LCD_EXTCLK_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_VSYNC, LCD_VSYNC_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_HSYNC, LCD_HSYNC_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DE, LCD_DE_MARK),
-
-	PINMUX_GPIO(GPIO_FN_LCD_DATA23_PG23, LCD_DATA23_PG23_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA22_PG22, LCD_DATA22_PG22_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA21_PG21, LCD_DATA21_PG21_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA20_PG20, LCD_DATA20_PG20_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA19_PG19, LCD_DATA19_PG19_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA18_PG18, LCD_DATA18_PG18_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA17_PG17, LCD_DATA17_PG17_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA16_PG16, LCD_DATA16_PG16_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA15_PG15, LCD_DATA15_PG15_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA14_PG14, LCD_DATA14_PG14_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA13_PG13, LCD_DATA13_PG13_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA12_PG12, LCD_DATA12_PG12_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA11_PG11, LCD_DATA11_PG11_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA10_PG10, LCD_DATA10_PG10_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA9_PG9, LCD_DATA9_PG9_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA8_PG8, LCD_DATA8_PG8_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA7_PG7, LCD_DATA7_PG7_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA6_PG6, LCD_DATA6_PG6_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA5_PG5, LCD_DATA5_PG5_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA4_PG4, LCD_DATA4_PG4_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA3_PG3, LCD_DATA3_PG3_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA2_PG2, LCD_DATA2_PG2_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA1_PG1, LCD_DATA1_PG1_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA0_PG0, LCD_DATA0_PG0_MARK),
-
-	PINMUX_GPIO(GPIO_FN_LCD_DATA23_PJ23, LCD_DATA23_PJ23_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA22_PJ22, LCD_DATA22_PJ22_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA21_PJ21, LCD_DATA21_PJ21_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA20_PJ20, LCD_DATA20_PJ20_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA19_PJ19, LCD_DATA19_PJ19_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA18_PJ18, LCD_DATA18_PJ18_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA17_PJ17, LCD_DATA17_PJ17_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA16_PJ16, LCD_DATA16_PJ16_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA15_PJ15, LCD_DATA15_PJ15_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA14_PJ14, LCD_DATA14_PJ14_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA13_PJ13, LCD_DATA13_PJ13_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA12_PJ12, LCD_DATA12_PJ12_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA11_PJ11, LCD_DATA11_PJ11_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA10_PJ10, LCD_DATA10_PJ10_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA9_PJ9, LCD_DATA9_PJ9_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA8_PJ8, LCD_DATA8_PJ8_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA7_PJ7, LCD_DATA7_PJ7_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA6_PJ6, LCD_DATA6_PJ6_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA5_PJ5, LCD_DATA5_PJ5_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA4_PJ4, LCD_DATA4_PJ4_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA3_PJ3, LCD_DATA3_PJ3_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA2_PJ2, LCD_DATA2_PJ2_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA1_PJ1, LCD_DATA1_PJ1_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA0_PJ0, LCD_DATA0_PJ0_MARK),
-
-	PINMUX_GPIO(GPIO_FN_LCD_M_DISP, LCD_M_DISP_MARK),
+	GPIO_FN(DV_CLK),
+	GPIO_FN(DV_VSYNC),
+	GPIO_FN(DV_HSYNC),
+
+	GPIO_FN(DV_DATA23),
+	GPIO_FN(DV_DATA22),
+	GPIO_FN(DV_DATA21),
+	GPIO_FN(DV_DATA20),
+	GPIO_FN(DV_DATA19),
+	GPIO_FN(DV_DATA18),
+	GPIO_FN(DV_DATA17),
+	GPIO_FN(DV_DATA16),
+	GPIO_FN(DV_DATA15),
+	GPIO_FN(DV_DATA14),
+	GPIO_FN(DV_DATA13),
+	GPIO_FN(DV_DATA12),
+	GPIO_FN(DV_DATA11),
+	GPIO_FN(DV_DATA10),
+	GPIO_FN(DV_DATA9),
+	GPIO_FN(DV_DATA8),
+	GPIO_FN(DV_DATA7),
+	GPIO_FN(DV_DATA6),
+	GPIO_FN(DV_DATA5),
+	GPIO_FN(DV_DATA4),
+	GPIO_FN(DV_DATA3),
+	GPIO_FN(DV_DATA2),
+	GPIO_FN(DV_DATA1),
+	GPIO_FN(DV_DATA0),
+
+	GPIO_FN(LCD_CLK),
+	GPIO_FN(LCD_EXTCLK),
+	GPIO_FN(LCD_VSYNC),
+	GPIO_FN(LCD_HSYNC),
+	GPIO_FN(LCD_DE),
+
+	GPIO_FN(LCD_DATA23_PG23),
+	GPIO_FN(LCD_DATA22_PG22),
+	GPIO_FN(LCD_DATA21_PG21),
+	GPIO_FN(LCD_DATA20_PG20),
+	GPIO_FN(LCD_DATA19_PG19),
+	GPIO_FN(LCD_DATA18_PG18),
+	GPIO_FN(LCD_DATA17_PG17),
+	GPIO_FN(LCD_DATA16_PG16),
+	GPIO_FN(LCD_DATA15_PG15),
+	GPIO_FN(LCD_DATA14_PG14),
+	GPIO_FN(LCD_DATA13_PG13),
+	GPIO_FN(LCD_DATA12_PG12),
+	GPIO_FN(LCD_DATA11_PG11),
+	GPIO_FN(LCD_DATA10_PG10),
+	GPIO_FN(LCD_DATA9_PG9),
+	GPIO_FN(LCD_DATA8_PG8),
+	GPIO_FN(LCD_DATA7_PG7),
+	GPIO_FN(LCD_DATA6_PG6),
+	GPIO_FN(LCD_DATA5_PG5),
+	GPIO_FN(LCD_DATA4_PG4),
+	GPIO_FN(LCD_DATA3_PG3),
+	GPIO_FN(LCD_DATA2_PG2),
+	GPIO_FN(LCD_DATA1_PG1),
+	GPIO_FN(LCD_DATA0_PG0),
+
+	GPIO_FN(LCD_DATA23_PJ23),
+	GPIO_FN(LCD_DATA22_PJ22),
+	GPIO_FN(LCD_DATA21_PJ21),
+	GPIO_FN(LCD_DATA20_PJ20),
+	GPIO_FN(LCD_DATA19_PJ19),
+	GPIO_FN(LCD_DATA18_PJ18),
+	GPIO_FN(LCD_DATA17_PJ17),
+	GPIO_FN(LCD_DATA16_PJ16),
+	GPIO_FN(LCD_DATA15_PJ15),
+	GPIO_FN(LCD_DATA14_PJ14),
+	GPIO_FN(LCD_DATA13_PJ13),
+	GPIO_FN(LCD_DATA12_PJ12),
+	GPIO_FN(LCD_DATA11_PJ11),
+	GPIO_FN(LCD_DATA10_PJ10),
+	GPIO_FN(LCD_DATA9_PJ9),
+	GPIO_FN(LCD_DATA8_PJ8),
+	GPIO_FN(LCD_DATA7_PJ7),
+	GPIO_FN(LCD_DATA6_PJ6),
+	GPIO_FN(LCD_DATA5_PJ5),
+	GPIO_FN(LCD_DATA4_PJ4),
+	GPIO_FN(LCD_DATA3_PJ3),
+	GPIO_FN(LCD_DATA2_PJ2),
+	GPIO_FN(LCD_DATA1_PJ1),
+	GPIO_FN(LCD_DATA0_PJ0),
+
+	GPIO_FN(LCD_M_DISP),
 };
 
-static struct pinmux_cfg_reg pinmux_config_regs[] = {
+static const struct pinmux_cfg_reg pinmux_config_regs[] = {
 	/* "name" addr register_size Field_Width */
 
 	/* where Field_Width is 1 for single mode registers or 4 for upto 16
@@ -2734,7 +2738,7 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = {
 	{}
 };
 
-static struct pinmux_data_reg pinmux_data_regs[] = {
+static const struct pinmux_data_reg pinmux_data_regs[] = {
 	{ PINMUX_DATA_REG("PADR0", 0xfffe3816, 16) {
 		0, 0, 0, 0, 0, 0, 0, PA1_DATA,
 		0, 0, 0, 0, 0, 0, 0, PA0_DATA }
@@ -2813,19 +2817,17 @@ static struct pinmux_data_reg pinmux_data_regs[] = {
 	{ }
 };
 
-struct sh_pfc_soc_info sh7269_pinmux_info = {
+const struct sh_pfc_soc_info sh7269_pinmux_info = {
 	.name = "sh7269_pfc",
-	.reserved_id = PINMUX_RESERVED,
-	.data = { PINMUX_DATA_BEGIN, PINMUX_DATA_END },
 	.input = { PINMUX_INPUT_BEGIN, PINMUX_INPUT_END, FORCE_IN },
 	.output = { PINMUX_OUTPUT_BEGIN, PINMUX_OUTPUT_END, FORCE_OUT },
-	.mark = { PINMUX_MARK_BEGIN, PINMUX_MARK_END },
 	.function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END },
 
-	.first_gpio = GPIO_PA1,
-	.last_gpio = GPIO_FN_LCD_M_DISP,
+	.pins = pinmux_pins,
+	.nr_pins = ARRAY_SIZE(pinmux_pins),
+	.func_gpios = pinmux_func_gpios,
+	.nr_func_gpios = ARRAY_SIZE(pinmux_func_gpios),
 
-	.gpios = pinmux_gpios,
 	.cfg_regs = pinmux_config_regs,
 	.data_regs = pinmux_data_regs,
 
diff --git a/drivers/pinctrl/sh-pfc/pfc-sh7372.c b/drivers/pinctrl/sh-pfc/pfc-sh7372.c
index d44e7f0..df0ae21 100644
--- a/drivers/pinctrl/sh-pfc/pfc-sh7372.c
+++ b/drivers/pinctrl/sh-pfc/pfc-sh7372.c
@@ -368,7 +368,7 @@ enum {
 	PINMUX_MARK_END,
 };
 
-static pinmux_enum_t pinmux_data[] = {
+static const pinmux_enum_t pinmux_data[] = {
 
 	/* specify valid pin states for each pin in GPIO mode */
 	PORT_DATA_IO_PD(0),		PORT_DATA_IO_PD(1),
@@ -929,11 +929,214 @@ static pinmux_enum_t pinmux_data[] = {
 	PINMUX_DATA(MFIv4_MARK,		MSEL4CR_6_1),
 };
 
-static struct pinmux_gpio pinmux_gpios[] = {
-
-	/* PORT */
+static struct sh_pfc_pin pinmux_pins[] = {
 	GPIO_PORT_ALL(),
+};
 
+/* - MMCIF ------------------------------------------------------------------ */
+static const unsigned int mmc0_data1_0_pins[] = {
+	/* D[0] */
+	84,
+};
+static const unsigned int mmc0_data1_0_mux[] = {
+	MMCD0_0_MARK,
+};
+static const unsigned int mmc0_data4_0_pins[] = {
+	/* D[0:3] */
+	84, 85, 86, 87,
+};
+static const unsigned int mmc0_data4_0_mux[] = {
+	MMCD0_0_MARK, MMCD0_1_MARK, MMCD0_2_MARK, MMCD0_3_MARK,
+};
+static const unsigned int mmc0_data8_0_pins[] = {
+	/* D[0:7] */
+	84, 85, 86, 87, 88, 89, 90, 91,
+};
+static const unsigned int mmc0_data8_0_mux[] = {
+	MMCD0_0_MARK, MMCD0_1_MARK, MMCD0_2_MARK, MMCD0_3_MARK,
+	MMCD0_4_MARK, MMCD0_5_MARK, MMCD0_6_MARK, MMCD0_7_MARK,
+};
+static const unsigned int mmc0_ctrl_0_pins[] = {
+	/* CMD, CLK */
+	92, 99,
+};
+static const unsigned int mmc0_ctrl_0_mux[] = {
+	MMCCMD0_MARK, MMCCLK0_MARK,
+};
+
+static const unsigned int mmc0_data1_1_pins[] = {
+	/* D[0] */
+	54,
+};
+static const unsigned int mmc0_data1_1_mux[] = {
+	MMCD1_0_MARK,
+};
+static const unsigned int mmc0_data4_1_pins[] = {
+	/* D[0:3] */
+	54, 55, 56, 57,
+};
+static const unsigned int mmc0_data4_1_mux[] = {
+	MMCD1_0_MARK, MMCD1_1_MARK, MMCD1_2_MARK, MMCD1_3_MARK,
+};
+static const unsigned int mmc0_data8_1_pins[] = {
+	/* D[0:7] */
+	54, 55, 56, 57, 58, 59, 60, 61,
+};
+static const unsigned int mmc0_data8_1_mux[] = {
+	MMCD1_0_MARK, MMCD1_1_MARK, MMCD1_2_MARK, MMCD1_3_MARK,
+	MMCD1_4_MARK, MMCD1_5_MARK, MMCD1_6_MARK, MMCD1_7_MARK,
+};
+static const unsigned int mmc0_ctrl_1_pins[] = {
+	/* CMD, CLK */
+	67, 66,
+};
+static const unsigned int mmc0_ctrl_1_mux[] = {
+	MMCCMD1_MARK, MMCCLK1_MARK,
+};
+/* - SDHI0 ------------------------------------------------------------------ */
+static const unsigned int sdhi0_data1_pins[] = {
+	/* D0 */
+	173,
+};
+static const unsigned int sdhi0_data1_mux[] = {
+	SDHID0_0_MARK,
+};
+static const unsigned int sdhi0_data4_pins[] = {
+	/* D[0:3] */
+	173, 174, 175, 176,
+};
+static const unsigned int sdhi0_data4_mux[] = {
+	SDHID0_0_MARK, SDHID0_1_MARK, SDHID0_2_MARK, SDHID0_3_MARK,
+};
+static const unsigned int sdhi0_ctrl_pins[] = {
+	/* CMD, CLK */
+	177, 171,
+};
+static const unsigned int sdhi0_ctrl_mux[] = {
+	SDHICMD0_MARK, SDHICLK0_MARK,
+};
+static const unsigned int sdhi0_cd_pins[] = {
+	/* CD */
+	172,
+};
+static const unsigned int sdhi0_cd_mux[] = {
+	SDHICD0_MARK,
+};
+static const unsigned int sdhi0_wp_pins[] = {
+	/* WP */
+	178,
+};
+static const unsigned int sdhi0_wp_mux[] = {
+	SDHIWP0_MARK,
+};
+/* - SDHI1 ------------------------------------------------------------------ */
+static const unsigned int sdhi1_data1_pins[] = {
+	/* D0 */
+	180,
+};
+static const unsigned int sdhi1_data1_mux[] = {
+	SDHID1_0_MARK,
+};
+static const unsigned int sdhi1_data4_pins[] = {
+	/* D[0:3] */
+	180, 181, 182, 183,
+};
+static const unsigned int sdhi1_data4_mux[] = {
+	SDHID1_0_MARK, SDHID1_1_MARK, SDHID1_2_MARK, SDHID1_3_MARK,
+};
+static const unsigned int sdhi1_ctrl_pins[] = {
+	/* CMD, CLK */
+	184, 179,
+};
+static const unsigned int sdhi1_ctrl_mux[] = {
+	SDHICMD1_MARK, SDHICLK1_MARK,
+};
+
+static const unsigned int sdhi2_data1_pins[] = {
+	/* D0 */
+	186,
+};
+static const unsigned int sdhi2_data1_mux[] = {
+	SDHID2_0_MARK,
+};
+static const unsigned int sdhi2_data4_pins[] = {
+	/* D[0:3] */
+	186, 187, 188, 189,
+};
+static const unsigned int sdhi2_data4_mux[] = {
+	SDHID2_0_MARK, SDHID2_1_MARK, SDHID2_2_MARK, SDHID2_3_MARK,
+};
+static const unsigned int sdhi2_ctrl_pins[] = {
+	/* CMD, CLK */
+	190, 185,
+};
+static const unsigned int sdhi2_ctrl_mux[] = {
+	SDHICMD2_MARK, SDHICLK2_MARK,
+};
+
+static const struct sh_pfc_pin_group pinmux_groups[] = {
+	SH_PFC_PIN_GROUP(mmc0_data1_0),
+	SH_PFC_PIN_GROUP(mmc0_data4_0),
+	SH_PFC_PIN_GROUP(mmc0_data8_0),
+	SH_PFC_PIN_GROUP(mmc0_ctrl_0),
+	SH_PFC_PIN_GROUP(mmc0_data1_1),
+	SH_PFC_PIN_GROUP(mmc0_data4_1),
+	SH_PFC_PIN_GROUP(mmc0_data8_1),
+	SH_PFC_PIN_GROUP(mmc0_ctrl_1),
+	SH_PFC_PIN_GROUP(sdhi0_data1),
+	SH_PFC_PIN_GROUP(sdhi0_data4),
+	SH_PFC_PIN_GROUP(sdhi0_ctrl),
+	SH_PFC_PIN_GROUP(sdhi0_cd),
+	SH_PFC_PIN_GROUP(sdhi0_wp),
+	SH_PFC_PIN_GROUP(sdhi1_data1),
+	SH_PFC_PIN_GROUP(sdhi1_data4),
+	SH_PFC_PIN_GROUP(sdhi1_ctrl),
+	SH_PFC_PIN_GROUP(sdhi2_data1),
+	SH_PFC_PIN_GROUP(sdhi2_data4),
+	SH_PFC_PIN_GROUP(sdhi2_ctrl),
+};
+
+static const char * const mmc0_groups[] = {
+	"mmc0_data1_0",
+	"mmc0_data4_0",
+	"mmc0_data8_0",
+	"mmc0_ctrl_0",
+	"mmc0_data1_1",
+	"mmc0_data4_1",
+	"mmc0_data8_1",
+	"mmc0_ctrl_1",
+};
+
+static const char * const sdhi0_groups[] = {
+	"sdhi0_data1",
+	"sdhi0_data4",
+	"sdhi0_ctrl",
+	"sdhi0_cd",
+	"sdhi0_wp",
+};
+
+static const char * const sdhi1_groups[] = {
+	"sdhi1_data1",
+	"sdhi1_data4",
+	"sdhi1_ctrl",
+};
+
+static const char * const sdhi2_groups[] = {
+	"sdhi2_data1",
+	"sdhi2_data4",
+	"sdhi2_ctrl",
+};
+
+static const struct sh_pfc_function pinmux_functions[] = {
+	SH_PFC_FUNCTION(mmc0),
+	SH_PFC_FUNCTION(sdhi0),
+	SH_PFC_FUNCTION(sdhi1),
+	SH_PFC_FUNCTION(sdhi2),
+};
+
+#define PINMUX_FN_BASE	ARRAY_SIZE(pinmux_pins)
+
+static const struct pinmux_func pinmux_func_gpios[] = {
 	/* IRQ */
 	GPIO_FN(IRQ0_6),	GPIO_FN(IRQ0_162),	GPIO_FN(IRQ1),
 	GPIO_FN(IRQ2_4),	GPIO_FN(IRQ2_5),	GPIO_FN(IRQ3_8),
@@ -1074,18 +1277,6 @@ static struct pinmux_gpio pinmux_gpios[] = {
 	GPIO_FN(D11_NAF11),	GPIO_FN(D12_NAF12),	GPIO_FN(D13_NAF13),
 	GPIO_FN(D14_NAF14),	GPIO_FN(D15_NAF15),
 
-	/* MMCIF(1) */
-	GPIO_FN(MMCD0_0),	GPIO_FN(MMCD0_1),	GPIO_FN(MMCD0_2),
-	GPIO_FN(MMCD0_3),	GPIO_FN(MMCD0_4),	GPIO_FN(MMCD0_5),
-	GPIO_FN(MMCD0_6),	GPIO_FN(MMCD0_7),	GPIO_FN(MMCCMD0),
-	GPIO_FN(MMCCLK0),
-
-	/* MMCIF(2) */
-	GPIO_FN(MMCD1_0),	GPIO_FN(MMCD1_1),	GPIO_FN(MMCD1_2),
-	GPIO_FN(MMCD1_3),	GPIO_FN(MMCD1_4),	GPIO_FN(MMCD1_5),
-	GPIO_FN(MMCD1_6),	GPIO_FN(MMCD1_7),	GPIO_FN(MMCCLK1),
-	GPIO_FN(MMCCMD1),
-
 	/* SPU2 */
 	GPIO_FN(VINT_I),
 
@@ -1182,25 +1373,12 @@ static struct pinmux_gpio pinmux_gpios[] = {
 	/* HDMI */
 	GPIO_FN(HDMI_HPD),	GPIO_FN(HDMI_CEC),
 
-	/* SDHI0 */
-	GPIO_FN(SDHICLK0),	GPIO_FN(SDHICD0),	GPIO_FN(SDHICMD0),
-	GPIO_FN(SDHIWP0),	GPIO_FN(SDHID0_0),	GPIO_FN(SDHID0_1),
-	GPIO_FN(SDHID0_2),	GPIO_FN(SDHID0_3),
-
-	/* SDHI1 */
-	GPIO_FN(SDHICLK1),	GPIO_FN(SDHICMD1),	GPIO_FN(SDHID1_0),
-	GPIO_FN(SDHID1_1),	GPIO_FN(SDHID1_2),	GPIO_FN(SDHID1_3),
-
-	/* SDHI2 */
-	GPIO_FN(SDHICLK2),	GPIO_FN(SDHICMD2),	GPIO_FN(SDHID2_0),
-	GPIO_FN(SDHID2_1),	GPIO_FN(SDHID2_2),	GPIO_FN(SDHID2_3),
-
 	/* SDENC */
 	GPIO_FN(SDENC_CPG),
 	GPIO_FN(SDENC_DV_CLKI),
 };
 
-static struct pinmux_cfg_reg pinmux_config_regs[] = {
+static const struct pinmux_cfg_reg pinmux_config_regs[] = {
 	PORTCR(0,	0xE6051000), /* PORT0CR */
 	PORTCR(1,	0xE6051001), /* PORT1CR */
 	PORTCR(2,	0xE6051002), /* PORT2CR */
@@ -1472,7 +1650,7 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = {
 	{ },
 };
 
-static struct pinmux_data_reg pinmux_data_regs[] = {
+static const struct pinmux_data_reg pinmux_data_regs[] = {
 	{ PINMUX_DATA_REG("PORTL095_064DR", 0xE6054008, 32) {
 			PORT95_DATA, PORT94_DATA, PORT93_DATA, PORT92_DATA,
 			PORT91_DATA, PORT90_DATA, PORT89_DATA, PORT88_DATA,
@@ -1597,56 +1775,59 @@ static struct pinmux_data_reg pinmux_data_regs[] = {
 
 #define EXT_IRQ16L(n) evt2irq(0x200 + ((n) << 5))
 #define EXT_IRQ16H(n) evt2irq(0x3200 + (((n) - 16) << 5))
-static struct pinmux_irq pinmux_irqs[] = {
-	PINMUX_IRQ(EXT_IRQ16L(0), PORT6_FN0, PORT162_FN0),
-	PINMUX_IRQ(EXT_IRQ16L(1), PORT12_FN0),
-	PINMUX_IRQ(EXT_IRQ16L(2), PORT4_FN0, PORT5_FN0),
-	PINMUX_IRQ(EXT_IRQ16L(3), PORT8_FN0, PORT16_FN0),
-	PINMUX_IRQ(EXT_IRQ16L(4), PORT17_FN0, PORT163_FN0),
-	PINMUX_IRQ(EXT_IRQ16L(5), PORT18_FN0),
-	PINMUX_IRQ(EXT_IRQ16L(6), PORT39_FN0, PORT164_FN0),
-	PINMUX_IRQ(EXT_IRQ16L(7), PORT40_FN0, PORT167_FN0),
-	PINMUX_IRQ(EXT_IRQ16L(8), PORT41_FN0, PORT168_FN0),
-	PINMUX_IRQ(EXT_IRQ16L(9), PORT42_FN0, PORT169_FN0),
-	PINMUX_IRQ(EXT_IRQ16L(10), PORT65_FN0),
-	PINMUX_IRQ(EXT_IRQ16L(11), PORT67_FN0),
-	PINMUX_IRQ(EXT_IRQ16L(12), PORT80_FN0, PORT137_FN0),
-	PINMUX_IRQ(EXT_IRQ16L(13), PORT81_FN0, PORT145_FN0),
-	PINMUX_IRQ(EXT_IRQ16L(14), PORT82_FN0, PORT146_FN0),
-	PINMUX_IRQ(EXT_IRQ16L(15), PORT83_FN0, PORT147_FN0),
-	PINMUX_IRQ(EXT_IRQ16H(16), PORT84_FN0, PORT170_FN0),
-	PINMUX_IRQ(EXT_IRQ16H(17), PORT85_FN0),
-	PINMUX_IRQ(EXT_IRQ16H(18), PORT86_FN0),
-	PINMUX_IRQ(EXT_IRQ16H(19), PORT87_FN0),
-	PINMUX_IRQ(EXT_IRQ16H(20), PORT92_FN0),
-	PINMUX_IRQ(EXT_IRQ16H(21), PORT93_FN0),
-	PINMUX_IRQ(EXT_IRQ16H(22), PORT94_FN0),
-	PINMUX_IRQ(EXT_IRQ16H(23), PORT95_FN0),
-	PINMUX_IRQ(EXT_IRQ16H(24), PORT112_FN0),
-	PINMUX_IRQ(EXT_IRQ16H(25), PORT119_FN0),
-	PINMUX_IRQ(EXT_IRQ16H(26), PORT121_FN0, PORT172_FN0),
-	PINMUX_IRQ(EXT_IRQ16H(27), PORT122_FN0, PORT180_FN0),
-	PINMUX_IRQ(EXT_IRQ16H(28), PORT123_FN0, PORT181_FN0),
-	PINMUX_IRQ(EXT_IRQ16H(29), PORT129_FN0, PORT182_FN0),
-	PINMUX_IRQ(EXT_IRQ16H(30), PORT130_FN0, PORT183_FN0),
-	PINMUX_IRQ(EXT_IRQ16H(31), PORT138_FN0, PORT184_FN0),
+static const struct pinmux_irq pinmux_irqs[] = {
+	PINMUX_IRQ(EXT_IRQ16L(0), GPIO_PORT6, GPIO_PORT162),
+	PINMUX_IRQ(EXT_IRQ16L(1), GPIO_PORT12),
+	PINMUX_IRQ(EXT_IRQ16L(2), GPIO_PORT4, GPIO_PORT5),
+	PINMUX_IRQ(EXT_IRQ16L(3), GPIO_PORT8, GPIO_PORT16),
+	PINMUX_IRQ(EXT_IRQ16L(4), GPIO_PORT17, GPIO_PORT163),
+	PINMUX_IRQ(EXT_IRQ16L(5), GPIO_PORT18),
+	PINMUX_IRQ(EXT_IRQ16L(6), GPIO_PORT39, GPIO_PORT164),
+	PINMUX_IRQ(EXT_IRQ16L(7), GPIO_PORT40, GPIO_PORT167),
+	PINMUX_IRQ(EXT_IRQ16L(8), GPIO_PORT41, GPIO_PORT168),
+	PINMUX_IRQ(EXT_IRQ16L(9), GPIO_PORT42, GPIO_PORT169),
+	PINMUX_IRQ(EXT_IRQ16L(10), GPIO_PORT65),
+	PINMUX_IRQ(EXT_IRQ16L(11), GPIO_PORT67),
+	PINMUX_IRQ(EXT_IRQ16L(12), GPIO_PORT80, GPIO_PORT137),
+	PINMUX_IRQ(EXT_IRQ16L(13), GPIO_PORT81, GPIO_PORT145),
+	PINMUX_IRQ(EXT_IRQ16L(14), GPIO_PORT82, GPIO_PORT146),
+	PINMUX_IRQ(EXT_IRQ16L(15), GPIO_PORT83, GPIO_PORT147),
+	PINMUX_IRQ(EXT_IRQ16H(16), GPIO_PORT84, GPIO_PORT170),
+	PINMUX_IRQ(EXT_IRQ16H(17), GPIO_PORT85),
+	PINMUX_IRQ(EXT_IRQ16H(18), GPIO_PORT86),
+	PINMUX_IRQ(EXT_IRQ16H(19), GPIO_PORT87),
+	PINMUX_IRQ(EXT_IRQ16H(20), GPIO_PORT92),
+	PINMUX_IRQ(EXT_IRQ16H(21), GPIO_PORT93),
+	PINMUX_IRQ(EXT_IRQ16H(22), GPIO_PORT94),
+	PINMUX_IRQ(EXT_IRQ16H(23), GPIO_PORT95),
+	PINMUX_IRQ(EXT_IRQ16H(24), GPIO_PORT112),
+	PINMUX_IRQ(EXT_IRQ16H(25), GPIO_PORT119),
+	PINMUX_IRQ(EXT_IRQ16H(26), GPIO_PORT121, GPIO_PORT172),
+	PINMUX_IRQ(EXT_IRQ16H(27), GPIO_PORT122, GPIO_PORT180),
+	PINMUX_IRQ(EXT_IRQ16H(28), GPIO_PORT123, GPIO_PORT181),
+	PINMUX_IRQ(EXT_IRQ16H(29), GPIO_PORT129, GPIO_PORT182),
+	PINMUX_IRQ(EXT_IRQ16H(30), GPIO_PORT130, GPIO_PORT183),
+	PINMUX_IRQ(EXT_IRQ16H(31), GPIO_PORT138, GPIO_PORT184),
 };
 
-struct sh_pfc_soc_info sh7372_pinmux_info = {
+const struct sh_pfc_soc_info sh7372_pinmux_info = {
 	.name = "sh7372_pfc",
-	.reserved_id = PINMUX_RESERVED,
-	.data = { PINMUX_DATA_BEGIN, PINMUX_DATA_END },
 	.input = { PINMUX_INPUT_BEGIN, PINMUX_INPUT_END },
 	.input_pu = { PINMUX_INPUT_PULLUP_BEGIN, PINMUX_INPUT_PULLUP_END },
 	.input_pd = { PINMUX_INPUT_PULLDOWN_BEGIN, PINMUX_INPUT_PULLDOWN_END },
 	.output = { PINMUX_OUTPUT_BEGIN, PINMUX_OUTPUT_END },
-	.mark = { PINMUX_MARK_BEGIN, PINMUX_MARK_END },
 	.function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END },
 
-	.first_gpio = GPIO_PORT0,
-	.last_gpio = GPIO_FN_SDENC_DV_CLKI,
+	.pins = pinmux_pins,
+	.nr_pins = ARRAY_SIZE(pinmux_pins),
+	.groups = pinmux_groups,
+	.nr_groups = ARRAY_SIZE(pinmux_groups),
+	.functions = pinmux_functions,
+	.nr_functions = ARRAY_SIZE(pinmux_functions),
+
+	.func_gpios = pinmux_func_gpios,
+	.nr_func_gpios = ARRAY_SIZE(pinmux_func_gpios),
 
-	.gpios = pinmux_gpios,
 	.cfg_regs = pinmux_config_regs,
 	.data_regs = pinmux_data_regs,
 
diff --git a/drivers/pinctrl/sh-pfc/pfc-sh73a0.c b/drivers/pinctrl/sh-pfc/pfc-sh73a0.c
index 709008e..587f777 100644
--- a/drivers/pinctrl/sh-pfc/pfc-sh73a0.c
+++ b/drivers/pinctrl/sh-pfc/pfc-sh73a0.c
@@ -18,18 +18,18 @@
  * 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/io.h>
 #include <linux/kernel.h>
+#include <linux/pinctrl/pinconf-generic.h>
+
 #include <mach/sh73a0.h>
 #include <mach/irqs.h>
 
+#include "core.h"
 #include "sh_pfc.h"
 
 #define CPU_ALL_PORT(fn, pfx, sfx)				\
-	PORT_10(fn, pfx,    sfx), PORT_10(fn, pfx##1, sfx),	\
-	PORT_10(fn, pfx##2, sfx), PORT_10(fn, pfx##3, sfx),	\
-	PORT_10(fn, pfx##4, sfx), PORT_10(fn, pfx##5, sfx),	\
-	PORT_10(fn, pfx##6, sfx), PORT_10(fn, pfx##7, sfx),	\
-	PORT_10(fn, pfx##8, sfx), PORT_10(fn, pfx##9, sfx),	\
+	PORT_10(fn, pfx,    sfx), PORT_90(fn, pfx, sfx),	\
 	PORT_10(fn, pfx##10, sfx),				\
 	PORT_1(fn, pfx##110, sfx), PORT_1(fn, pfx##111, sfx),	\
 	PORT_1(fn, pfx##112, sfx), PORT_1(fn, pfx##113, sfx),	\
@@ -66,14 +66,6 @@ enum {
 	PORT_ALL(IN),			/* PORT0_IN -> PORT309_IN */
 	PINMUX_INPUT_END,
 
-	PINMUX_INPUT_PULLUP_BEGIN,
-	PORT_ALL(IN_PU),		/* PORT0_IN_PU -> PORT309_IN_PU */
-	PINMUX_INPUT_PULLUP_END,
-
-	PINMUX_INPUT_PULLDOWN_BEGIN,
-	PORT_ALL(IN_PD),		/* PORT0_IN_PD -> PORT309_IN_PD */
-	PINMUX_INPUT_PULLDOWN_END,
-
 	PINMUX_OUTPUT_BEGIN,
 	PORT_ALL(OUT),			/* PORT0_OUT -> PORT309_OUT */
 	PINMUX_OUTPUT_END,
@@ -468,328 +460,15 @@ enum {
 	EDBGREQ_PD_MARK,
 	EDBGREQ_PU_MARK,
 
-	/* Functions with pull-ups */
-	KEYIN0_PU_MARK,
-	KEYIN1_PU_MARK,
-	KEYIN2_PU_MARK,
-	KEYIN3_PU_MARK,
-	KEYIN4_PU_MARK,
-	KEYIN5_PU_MARK,
-	KEYIN6_PU_MARK,
-	KEYIN7_PU_MARK,
-	SDHICD0_PU_MARK,
-	SDHID0_0_PU_MARK,
-	SDHID0_1_PU_MARK,
-	SDHID0_2_PU_MARK,
-	SDHID0_3_PU_MARK,
-	SDHICMD0_PU_MARK,
-	SDHIWP0_PU_MARK,
-	SDHID1_0_PU_MARK,
-	SDHID1_1_PU_MARK,
-	SDHID1_2_PU_MARK,
-	SDHID1_3_PU_MARK,
-	SDHICMD1_PU_MARK,
-	SDHID2_0_PU_MARK,
-	SDHID2_1_PU_MARK,
-	SDHID2_2_PU_MARK,
-	SDHID2_3_PU_MARK,
-	SDHICMD2_PU_MARK,
-	MMCCMD0_PU_MARK,
-	MMCCMD1_PU_MARK,
-	MMCD0_0_PU_MARK,
-	MMCD0_1_PU_MARK,
-	MMCD0_2_PU_MARK,
-	MMCD0_3_PU_MARK,
-	MMCD0_4_PU_MARK,
-	MMCD0_5_PU_MARK,
-	MMCD0_6_PU_MARK,
-	MMCD0_7_PU_MARK,
-	FSIBISLD_PU_MARK,
-	FSIACK_PU_MARK,
-	FSIAILR_PU_MARK,
-	FSIAIBT_PU_MARK,
-	FSIAISLD_PU_MARK,
-
 	PINMUX_MARK_END,
 };
 
-static pinmux_enum_t pinmux_data[] = {
-	/* specify valid pin states for each pin in GPIO mode */
+#define _PORT_DATA(pfx, sfx)	PORT_DATA_IO(pfx)
+#define PINMUX_DATA_GP_ALL()    CPU_ALL_PORT(_PORT_DATA, , unused)
 
-	/* Table 25-1 (I/O and Pull U/D) */
-	PORT_DATA_I_PD(0),
-	PORT_DATA_I_PU(1),
-	PORT_DATA_I_PU(2),
-	PORT_DATA_I_PU(3),
-	PORT_DATA_I_PU(4),
-	PORT_DATA_I_PU(5),
-	PORT_DATA_I_PU(6),
-	PORT_DATA_I_PU(7),
-	PORT_DATA_I_PU(8),
-	PORT_DATA_I_PD(9),
-	PORT_DATA_I_PD(10),
-	PORT_DATA_I_PU_PD(11),
-	PORT_DATA_IO_PU_PD(12),
-	PORT_DATA_IO_PU_PD(13),
-	PORT_DATA_IO_PU_PD(14),
-	PORT_DATA_IO_PU_PD(15),
-	PORT_DATA_IO_PD(16),
-	PORT_DATA_IO_PD(17),
-	PORT_DATA_IO_PU(18),
-	PORT_DATA_IO_PU(19),
-	PORT_DATA_O(20),
-	PORT_DATA_O(21),
-	PORT_DATA_O(22),
-	PORT_DATA_O(23),
-	PORT_DATA_O(24),
-	PORT_DATA_I_PD(25),
-	PORT_DATA_I_PD(26),
-	PORT_DATA_IO_PU(27),
-	PORT_DATA_IO_PU(28),
-	PORT_DATA_IO_PD(29),
-	PORT_DATA_IO_PD(30),
-	PORT_DATA_IO_PU(31),
-	PORT_DATA_IO_PD(32),
-	PORT_DATA_I_PU_PD(33),
-	PORT_DATA_IO_PD(34),
-	PORT_DATA_I_PU_PD(35),
-	PORT_DATA_IO_PD(36),
-	PORT_DATA_IO(37),
-	PORT_DATA_O(38),
-	PORT_DATA_I_PU(39),
-	PORT_DATA_I_PU_PD(40),
-	PORT_DATA_O(41),
-	PORT_DATA_IO_PD(42),
-	PORT_DATA_IO_PU_PD(43),
-	PORT_DATA_IO_PU_PD(44),
-	PORT_DATA_IO_PD(45),
-	PORT_DATA_IO_PD(46),
-	PORT_DATA_IO_PD(47),
-	PORT_DATA_I_PD(48),
-	PORT_DATA_IO_PU_PD(49),
-	PORT_DATA_IO_PD(50),
-
-	PORT_DATA_IO_PD(51),
-	PORT_DATA_O(52),
-	PORT_DATA_IO_PU_PD(53),
-	PORT_DATA_IO_PU_PD(54),
-	PORT_DATA_IO_PD(55),
-	PORT_DATA_I_PU_PD(56),
-	PORT_DATA_IO(57),
-	PORT_DATA_IO(58),
-	PORT_DATA_IO(59),
-	PORT_DATA_IO(60),
-	PORT_DATA_IO(61),
-	PORT_DATA_IO_PD(62),
-	PORT_DATA_IO_PD(63),
-	PORT_DATA_IO_PU_PD(64),
-	PORT_DATA_IO_PD(65),
-	PORT_DATA_IO_PU_PD(66),
-	PORT_DATA_IO_PU_PD(67),
-	PORT_DATA_IO_PU_PD(68),
-	PORT_DATA_IO_PU_PD(69),
-	PORT_DATA_IO_PU_PD(70),
-	PORT_DATA_IO_PU_PD(71),
-	PORT_DATA_IO_PU_PD(72),
-	PORT_DATA_I_PU_PD(73),
-	PORT_DATA_IO_PU(74),
-	PORT_DATA_IO_PU(75),
-	PORT_DATA_IO_PU(76),
-	PORT_DATA_IO_PU(77),
-	PORT_DATA_IO_PU(78),
-	PORT_DATA_IO_PU(79),
-	PORT_DATA_IO_PU(80),
-	PORT_DATA_IO_PU(81),
-	PORT_DATA_IO_PU(82),
-	PORT_DATA_IO_PU(83),
-	PORT_DATA_IO_PU(84),
-	PORT_DATA_IO_PU(85),
-	PORT_DATA_IO_PU(86),
-	PORT_DATA_IO_PU(87),
-	PORT_DATA_IO_PU(88),
-	PORT_DATA_IO_PU(89),
-	PORT_DATA_O(90),
-	PORT_DATA_IO_PU(91),
-	PORT_DATA_O(92),
-	PORT_DATA_IO_PU(93),
-	PORT_DATA_O(94),
-	PORT_DATA_I_PU_PD(95),
-	PORT_DATA_IO(96),
-	PORT_DATA_IO(97),
-	PORT_DATA_IO(98),
-	PORT_DATA_I_PU(99),
-	PORT_DATA_O(100),
-	PORT_DATA_O(101),
-	PORT_DATA_I_PU(102),
-	PORT_DATA_IO_PD(103),
-	PORT_DATA_I_PU_PD(104),
-	PORT_DATA_I_PD(105),
-	PORT_DATA_I_PD(106),
-	PORT_DATA_I_PU_PD(107),
-	PORT_DATA_I_PU_PD(108),
-	PORT_DATA_IO_PD(109),
-	PORT_DATA_IO_PD(110),
-	PORT_DATA_IO_PU_PD(111),
-	PORT_DATA_IO_PU_PD(112),
-	PORT_DATA_IO_PU_PD(113),
-	PORT_DATA_IO_PD(114),
-	PORT_DATA_IO_PU(115),
-	PORT_DATA_IO_PU(116),
-	PORT_DATA_IO_PU_PD(117),
-	PORT_DATA_IO_PU_PD(118),
-	PORT_DATA_IO_PD(128),
-
-	PORT_DATA_IO_PD(129),
-	PORT_DATA_IO_PU_PD(130),
-	PORT_DATA_IO_PD(131),
-	PORT_DATA_IO_PD(132),
-	PORT_DATA_IO_PD(133),
-	PORT_DATA_IO_PU_PD(134),
-	PORT_DATA_IO_PU_PD(135),
-	PORT_DATA_IO_PU_PD(136),
-	PORT_DATA_IO_PU_PD(137),
-	PORT_DATA_IO_PD(138),
-	PORT_DATA_IO_PD(139),
-	PORT_DATA_IO_PD(140),
-	PORT_DATA_IO_PD(141),
-	PORT_DATA_IO_PD(142),
-	PORT_DATA_IO_PD(143),
-	PORT_DATA_IO_PU_PD(144),
-	PORT_DATA_IO_PD(145),
-	PORT_DATA_IO_PU_PD(146),
-	PORT_DATA_IO_PU_PD(147),
-	PORT_DATA_IO_PU_PD(148),
-	PORT_DATA_IO_PU_PD(149),
-	PORT_DATA_I_PU_PD(150),
-	PORT_DATA_IO_PU_PD(151),
-	PORT_DATA_IO_PU_PD(152),
-	PORT_DATA_IO_PD(153),
-	PORT_DATA_IO_PD(154),
-	PORT_DATA_I_PU_PD(155),
-	PORT_DATA_IO_PU_PD(156),
-	PORT_DATA_I_PD(157),
-	PORT_DATA_IO_PD(158),
-	PORT_DATA_IO_PU_PD(159),
-	PORT_DATA_IO_PU_PD(160),
-	PORT_DATA_I_PU_PD(161),
-	PORT_DATA_I_PU_PD(162),
-	PORT_DATA_IO_PU_PD(163),
-	PORT_DATA_I_PU_PD(164),
-	PORT_DATA_IO_PD(192),
-	PORT_DATA_IO_PU_PD(193),
-	PORT_DATA_IO_PD(194),
-	PORT_DATA_IO_PU_PD(195),
-	PORT_DATA_IO_PD(196),
-	PORT_DATA_IO_PD(197),
-	PORT_DATA_IO_PD(198),
-	PORT_DATA_IO_PD(199),
-	PORT_DATA_IO_PU_PD(200),
-	PORT_DATA_IO_PU_PD(201),
-	PORT_DATA_IO_PU_PD(202),
-	PORT_DATA_IO_PU_PD(203),
-	PORT_DATA_IO_PU_PD(204),
-	PORT_DATA_IO_PU_PD(205),
-	PORT_DATA_IO_PU_PD(206),
-	PORT_DATA_IO_PD(207),
-	PORT_DATA_IO_PD(208),
-	PORT_DATA_IO_PD(209),
-	PORT_DATA_IO_PD(210),
-	PORT_DATA_IO_PD(211),
-	PORT_DATA_IO_PD(212),
-	PORT_DATA_IO_PD(213),
-	PORT_DATA_IO_PU_PD(214),
-	PORT_DATA_IO_PU_PD(215),
-	PORT_DATA_IO_PD(216),
-	PORT_DATA_IO_PD(217),
-	PORT_DATA_O(218),
-	PORT_DATA_IO_PD(219),
-	PORT_DATA_IO_PD(220),
-	PORT_DATA_IO_PU_PD(221),
-	PORT_DATA_IO_PU_PD(222),
-	PORT_DATA_I_PU_PD(223),
-	PORT_DATA_I_PU_PD(224),
-
-	PORT_DATA_IO_PU_PD(225),
-	PORT_DATA_O(226),
-	PORT_DATA_IO_PU_PD(227),
-	PORT_DATA_I_PU_PD(228),
-	PORT_DATA_I_PD(229),
-	PORT_DATA_IO(230),
-	PORT_DATA_IO_PU_PD(231),
-	PORT_DATA_IO_PU_PD(232),
-	PORT_DATA_I_PU_PD(233),
-	PORT_DATA_IO_PU_PD(234),
-	PORT_DATA_IO_PU_PD(235),
-	PORT_DATA_IO_PU_PD(236),
-	PORT_DATA_IO_PD(237),
-	PORT_DATA_IO_PU_PD(238),
-	PORT_DATA_IO_PU_PD(239),
-	PORT_DATA_IO_PU_PD(240),
-	PORT_DATA_O(241),
-	PORT_DATA_I_PD(242),
-	PORT_DATA_IO_PU_PD(243),
-	PORT_DATA_IO_PU_PD(244),
-	PORT_DATA_IO_PU_PD(245),
-	PORT_DATA_IO_PU_PD(246),
-	PORT_DATA_IO_PU_PD(247),
-	PORT_DATA_IO_PU_PD(248),
-	PORT_DATA_IO_PU_PD(249),
-	PORT_DATA_IO_PU_PD(250),
-	PORT_DATA_IO_PU_PD(251),
-	PORT_DATA_IO_PU_PD(252),
-	PORT_DATA_IO_PU_PD(253),
-	PORT_DATA_IO_PU_PD(254),
-	PORT_DATA_IO_PU_PD(255),
-	PORT_DATA_IO_PU_PD(256),
-	PORT_DATA_IO_PU_PD(257),
-	PORT_DATA_IO_PU_PD(258),
-	PORT_DATA_IO_PU_PD(259),
-	PORT_DATA_IO_PU_PD(260),
-	PORT_DATA_IO_PU_PD(261),
-	PORT_DATA_IO_PU_PD(262),
-	PORT_DATA_IO_PU_PD(263),
-	PORT_DATA_IO_PU_PD(264),
-	PORT_DATA_IO_PU_PD(265),
-	PORT_DATA_IO_PU_PD(266),
-	PORT_DATA_IO_PU_PD(267),
-	PORT_DATA_IO_PU_PD(268),
-	PORT_DATA_IO_PU_PD(269),
-	PORT_DATA_IO_PU_PD(270),
-	PORT_DATA_IO_PU_PD(271),
-	PORT_DATA_IO_PU_PD(272),
-	PORT_DATA_IO_PU_PD(273),
-	PORT_DATA_IO_PU_PD(274),
-	PORT_DATA_IO_PU_PD(275),
-	PORT_DATA_IO_PU_PD(276),
-	PORT_DATA_IO_PU_PD(277),
-	PORT_DATA_IO_PU_PD(278),
-	PORT_DATA_IO_PU_PD(279),
-	PORT_DATA_IO_PU_PD(280),
-	PORT_DATA_O(281),
-	PORT_DATA_O(282),
-	PORT_DATA_I_PU(288),
-	PORT_DATA_IO_PU_PD(289),
-	PORT_DATA_IO_PU_PD(290),
-	PORT_DATA_IO_PU_PD(291),
-	PORT_DATA_IO_PU_PD(292),
-	PORT_DATA_IO_PU_PD(293),
-	PORT_DATA_IO_PU_PD(294),
-	PORT_DATA_IO_PU_PD(295),
-	PORT_DATA_IO_PU_PD(296),
-	PORT_DATA_IO_PU_PD(297),
-	PORT_DATA_IO_PU_PD(298),
-
-	PORT_DATA_IO_PU_PD(299),
-	PORT_DATA_IO_PU_PD(300),
-	PORT_DATA_IO_PU_PD(301),
-	PORT_DATA_IO_PU_PD(302),
-	PORT_DATA_IO_PU_PD(303),
-	PORT_DATA_IO_PU_PD(304),
-	PORT_DATA_IO_PU_PD(305),
-	PORT_DATA_O(306),
-	PORT_DATA_O(307),
-	PORT_DATA_I_PU(308),
-	PORT_DATA_O(309),
+static const pinmux_enum_t pinmux_data[] = {
+	/* specify valid pin states for each pin in GPIO mode */
+	PINMUX_DATA_GP_ALL(),
 
 	/* Table 25-1 (Function 0-7) */
 	PINMUX_DATA(VBUS_0_MARK, PORT0_FN1),
@@ -1358,28 +1037,19 @@ static pinmux_enum_t pinmux_data[] = {
 	PINMUX_DATA(TS_SCK4_MARK, PORT268_FN3),
 	PINMUX_DATA(SDHICMD2_MARK, PORT269_FN1),
 	PINMUX_DATA(MMCCLK0_MARK, PORT270_FN1, MSEL4CR_MSEL15_0),
-	PINMUX_DATA(MMCD0_0_MARK, PORT271_FN1, PORT271_IN_PU,
-		MSEL4CR_MSEL15_0),
-	PINMUX_DATA(MMCD0_1_MARK, PORT272_FN1, PORT272_IN_PU,
-		MSEL4CR_MSEL15_0),
-	PINMUX_DATA(MMCD0_2_MARK, PORT273_FN1, PORT273_IN_PU,
-		MSEL4CR_MSEL15_0),
-	PINMUX_DATA(MMCD0_3_MARK, PORT274_FN1, PORT274_IN_PU,
-		MSEL4CR_MSEL15_0),
-	PINMUX_DATA(MMCD0_4_MARK, PORT275_FN1, PORT275_IN_PU,
-		MSEL4CR_MSEL15_0), \
+	PINMUX_DATA(MMCD0_0_MARK, PORT271_FN1, MSEL4CR_MSEL15_0),
+	PINMUX_DATA(MMCD0_1_MARK, PORT272_FN1, MSEL4CR_MSEL15_0),
+	PINMUX_DATA(MMCD0_2_MARK, PORT273_FN1, MSEL4CR_MSEL15_0),
+	PINMUX_DATA(MMCD0_3_MARK, PORT274_FN1, MSEL4CR_MSEL15_0),
+	PINMUX_DATA(MMCD0_4_MARK, PORT275_FN1, MSEL4CR_MSEL15_0),
 	PINMUX_DATA(TS_SPSYNC5_MARK, PORT275_FN3),
-	PINMUX_DATA(MMCD0_5_MARK, PORT276_FN1, PORT276_IN_PU,
-		MSEL4CR_MSEL15_0), \
+	PINMUX_DATA(MMCD0_5_MARK, PORT276_FN1, MSEL4CR_MSEL15_0),
 	PINMUX_DATA(TS_SDAT5_MARK, PORT276_FN3),
-	PINMUX_DATA(MMCD0_6_MARK, PORT277_FN1, PORT277_IN_PU,
-		MSEL4CR_MSEL15_0), \
+	PINMUX_DATA(MMCD0_6_MARK, PORT277_FN1, MSEL4CR_MSEL15_0),
 	PINMUX_DATA(TS_SDEN5_MARK, PORT277_FN3),
-	PINMUX_DATA(MMCD0_7_MARK, PORT278_FN1, PORT278_IN_PU,
-		MSEL4CR_MSEL15_0), \
+	PINMUX_DATA(MMCD0_7_MARK, PORT278_FN1, MSEL4CR_MSEL15_0),
 	PINMUX_DATA(TS_SCK5_MARK, PORT278_FN3),
-	PINMUX_DATA(MMCCMD0_MARK, PORT279_FN1, PORT279_IN_PU,
-		MSEL4CR_MSEL15_0),
+	PINMUX_DATA(MMCCMD0_MARK, PORT279_FN1, MSEL4CR_MSEL15_0),
 	PINMUX_DATA(RESETOUTS__MARK, PORT281_FN1), \
 	PINMUX_DATA(EXTAL2OUT_MARK, PORT281_FN2),
 	PINMUX_DATA(MCP_WAIT__MCP_FRB_MARK, PORT288_FN1),
@@ -1485,69 +1155,1791 @@ static pinmux_enum_t pinmux_data[] = {
 	PINMUX_DATA(RESETA_N_PU_OFF_MARK, MSEL4CR_MSEL4_1),
 	PINMUX_DATA(EDBGREQ_PD_MARK, MSEL4CR_MSEL1_0),
 	PINMUX_DATA(EDBGREQ_PU_MARK, MSEL4CR_MSEL1_1),
+};
+
+#define SH73A0_PIN(pin, cfgs)						\
+	{								\
+		.name = __stringify(PORT##pin),				\
+		.enum_id = PORT##pin##_DATA,				\
+		.configs = cfgs,					\
+	}
+
+#define __I		(SH_PFC_PIN_CFG_INPUT)
+#define __O		(SH_PFC_PIN_CFG_OUTPUT)
+#define __IO		(SH_PFC_PIN_CFG_INPUT | SH_PFC_PIN_CFG_OUTPUT)
+#define __PD		(SH_PFC_PIN_CFG_PULL_DOWN)
+#define __PU		(SH_PFC_PIN_CFG_PULL_UP)
+#define __PUD		(SH_PFC_PIN_CFG_PULL_DOWN | SH_PFC_PIN_CFG_PULL_UP)
+
+#define SH73A0_PIN_I_PD(pin)		SH73A0_PIN(pin, __I | __PD)
+#define SH73A0_PIN_I_PU(pin)		SH73A0_PIN(pin, __I | __PU)
+#define SH73A0_PIN_I_PU_PD(pin)		SH73A0_PIN(pin, __I | __PUD)
+#define SH73A0_PIN_IO(pin)		SH73A0_PIN(pin, __IO)
+#define SH73A0_PIN_IO_PD(pin)		SH73A0_PIN(pin, __IO | __PD)
+#define SH73A0_PIN_IO_PU(pin)		SH73A0_PIN(pin, __IO | __PU)
+#define SH73A0_PIN_IO_PU_PD(pin)	SH73A0_PIN(pin, __IO | __PUD)
+#define SH73A0_PIN_O(pin)		SH73A0_PIN(pin, __O)
+
+static struct sh_pfc_pin pinmux_pins[] = {
+	/* Table 25-1 (I/O and Pull U/D) */
+	SH73A0_PIN_I_PD(0),
+	SH73A0_PIN_I_PU(1),
+	SH73A0_PIN_I_PU(2),
+	SH73A0_PIN_I_PU(3),
+	SH73A0_PIN_I_PU(4),
+	SH73A0_PIN_I_PU(5),
+	SH73A0_PIN_I_PU(6),
+	SH73A0_PIN_I_PU(7),
+	SH73A0_PIN_I_PU(8),
+	SH73A0_PIN_I_PD(9),
+	SH73A0_PIN_I_PD(10),
+	SH73A0_PIN_I_PU_PD(11),
+	SH73A0_PIN_IO_PU_PD(12),
+	SH73A0_PIN_IO_PU_PD(13),
+	SH73A0_PIN_IO_PU_PD(14),
+	SH73A0_PIN_IO_PU_PD(15),
+	SH73A0_PIN_IO_PD(16),
+	SH73A0_PIN_IO_PD(17),
+	SH73A0_PIN_IO_PU(18),
+	SH73A0_PIN_IO_PU(19),
+	SH73A0_PIN_O(20),
+	SH73A0_PIN_O(21),
+	SH73A0_PIN_O(22),
+	SH73A0_PIN_O(23),
+	SH73A0_PIN_O(24),
+	SH73A0_PIN_I_PD(25),
+	SH73A0_PIN_I_PD(26),
+	SH73A0_PIN_IO_PU(27),
+	SH73A0_PIN_IO_PU(28),
+	SH73A0_PIN_IO_PD(29),
+	SH73A0_PIN_IO_PD(30),
+	SH73A0_PIN_IO_PU(31),
+	SH73A0_PIN_IO_PD(32),
+	SH73A0_PIN_I_PU_PD(33),
+	SH73A0_PIN_IO_PD(34),
+	SH73A0_PIN_I_PU_PD(35),
+	SH73A0_PIN_IO_PD(36),
+	SH73A0_PIN_IO(37),
+	SH73A0_PIN_O(38),
+	SH73A0_PIN_I_PU(39),
+	SH73A0_PIN_I_PU_PD(40),
+	SH73A0_PIN_O(41),
+	SH73A0_PIN_IO_PD(42),
+	SH73A0_PIN_IO_PU_PD(43),
+	SH73A0_PIN_IO_PU_PD(44),
+	SH73A0_PIN_IO_PD(45),
+	SH73A0_PIN_IO_PD(46),
+	SH73A0_PIN_IO_PD(47),
+	SH73A0_PIN_I_PD(48),
+	SH73A0_PIN_IO_PU_PD(49),
+	SH73A0_PIN_IO_PD(50),
+	SH73A0_PIN_IO_PD(51),
+	SH73A0_PIN_O(52),
+	SH73A0_PIN_IO_PU_PD(53),
+	SH73A0_PIN_IO_PU_PD(54),
+	SH73A0_PIN_IO_PD(55),
+	SH73A0_PIN_I_PU_PD(56),
+	SH73A0_PIN_IO(57),
+	SH73A0_PIN_IO(58),
+	SH73A0_PIN_IO(59),
+	SH73A0_PIN_IO(60),
+	SH73A0_PIN_IO(61),
+	SH73A0_PIN_IO_PD(62),
+	SH73A0_PIN_IO_PD(63),
+	SH73A0_PIN_IO_PU_PD(64),
+	SH73A0_PIN_IO_PD(65),
+	SH73A0_PIN_IO_PU_PD(66),
+	SH73A0_PIN_IO_PU_PD(67),
+	SH73A0_PIN_IO_PU_PD(68),
+	SH73A0_PIN_IO_PU_PD(69),
+	SH73A0_PIN_IO_PU_PD(70),
+	SH73A0_PIN_IO_PU_PD(71),
+	SH73A0_PIN_IO_PU_PD(72),
+	SH73A0_PIN_I_PU_PD(73),
+	SH73A0_PIN_IO_PU(74),
+	SH73A0_PIN_IO_PU(75),
+	SH73A0_PIN_IO_PU(76),
+	SH73A0_PIN_IO_PU(77),
+	SH73A0_PIN_IO_PU(78),
+	SH73A0_PIN_IO_PU(79),
+	SH73A0_PIN_IO_PU(80),
+	SH73A0_PIN_IO_PU(81),
+	SH73A0_PIN_IO_PU(82),
+	SH73A0_PIN_IO_PU(83),
+	SH73A0_PIN_IO_PU(84),
+	SH73A0_PIN_IO_PU(85),
+	SH73A0_PIN_IO_PU(86),
+	SH73A0_PIN_IO_PU(87),
+	SH73A0_PIN_IO_PU(88),
+	SH73A0_PIN_IO_PU(89),
+	SH73A0_PIN_O(90),
+	SH73A0_PIN_IO_PU(91),
+	SH73A0_PIN_O(92),
+	SH73A0_PIN_IO_PU(93),
+	SH73A0_PIN_O(94),
+	SH73A0_PIN_I_PU_PD(95),
+	SH73A0_PIN_IO(96),
+	SH73A0_PIN_IO(97),
+	SH73A0_PIN_IO(98),
+	SH73A0_PIN_I_PU(99),
+	SH73A0_PIN_O(100),
+	SH73A0_PIN_O(101),
+	SH73A0_PIN_I_PU(102),
+	SH73A0_PIN_IO_PD(103),
+	SH73A0_PIN_I_PU_PD(104),
+	SH73A0_PIN_I_PD(105),
+	SH73A0_PIN_I_PD(106),
+	SH73A0_PIN_I_PU_PD(107),
+	SH73A0_PIN_I_PU_PD(108),
+	SH73A0_PIN_IO_PD(109),
+	SH73A0_PIN_IO_PD(110),
+	SH73A0_PIN_IO_PU_PD(111),
+	SH73A0_PIN_IO_PU_PD(112),
+	SH73A0_PIN_IO_PU_PD(113),
+	SH73A0_PIN_IO_PD(114),
+	SH73A0_PIN_IO_PU(115),
+	SH73A0_PIN_IO_PU(116),
+	SH73A0_PIN_IO_PU_PD(117),
+	SH73A0_PIN_IO_PU_PD(118),
+	SH73A0_PIN_IO_PD(128),
+	SH73A0_PIN_IO_PD(129),
+	SH73A0_PIN_IO_PU_PD(130),
+	SH73A0_PIN_IO_PD(131),
+	SH73A0_PIN_IO_PD(132),
+	SH73A0_PIN_IO_PD(133),
+	SH73A0_PIN_IO_PU_PD(134),
+	SH73A0_PIN_IO_PU_PD(135),
+	SH73A0_PIN_IO_PU_PD(136),
+	SH73A0_PIN_IO_PU_PD(137),
+	SH73A0_PIN_IO_PD(138),
+	SH73A0_PIN_IO_PD(139),
+	SH73A0_PIN_IO_PD(140),
+	SH73A0_PIN_IO_PD(141),
+	SH73A0_PIN_IO_PD(142),
+	SH73A0_PIN_IO_PD(143),
+	SH73A0_PIN_IO_PU_PD(144),
+	SH73A0_PIN_IO_PD(145),
+	SH73A0_PIN_IO_PU_PD(146),
+	SH73A0_PIN_IO_PU_PD(147),
+	SH73A0_PIN_IO_PU_PD(148),
+	SH73A0_PIN_IO_PU_PD(149),
+	SH73A0_PIN_I_PU_PD(150),
+	SH73A0_PIN_IO_PU_PD(151),
+	SH73A0_PIN_IO_PU_PD(152),
+	SH73A0_PIN_IO_PD(153),
+	SH73A0_PIN_IO_PD(154),
+	SH73A0_PIN_I_PU_PD(155),
+	SH73A0_PIN_IO_PU_PD(156),
+	SH73A0_PIN_I_PD(157),
+	SH73A0_PIN_IO_PD(158),
+	SH73A0_PIN_IO_PU_PD(159),
+	SH73A0_PIN_IO_PU_PD(160),
+	SH73A0_PIN_I_PU_PD(161),
+	SH73A0_PIN_I_PU_PD(162),
+	SH73A0_PIN_IO_PU_PD(163),
+	SH73A0_PIN_I_PU_PD(164),
+	SH73A0_PIN_IO_PD(192),
+	SH73A0_PIN_IO_PU_PD(193),
+	SH73A0_PIN_IO_PD(194),
+	SH73A0_PIN_IO_PU_PD(195),
+	SH73A0_PIN_IO_PD(196),
+	SH73A0_PIN_IO_PD(197),
+	SH73A0_PIN_IO_PD(198),
+	SH73A0_PIN_IO_PD(199),
+	SH73A0_PIN_IO_PU_PD(200),
+	SH73A0_PIN_IO_PU_PD(201),
+	SH73A0_PIN_IO_PU_PD(202),
+	SH73A0_PIN_IO_PU_PD(203),
+	SH73A0_PIN_IO_PU_PD(204),
+	SH73A0_PIN_IO_PU_PD(205),
+	SH73A0_PIN_IO_PU_PD(206),
+	SH73A0_PIN_IO_PD(207),
+	SH73A0_PIN_IO_PD(208),
+	SH73A0_PIN_IO_PD(209),
+	SH73A0_PIN_IO_PD(210),
+	SH73A0_PIN_IO_PD(211),
+	SH73A0_PIN_IO_PD(212),
+	SH73A0_PIN_IO_PD(213),
+	SH73A0_PIN_IO_PU_PD(214),
+	SH73A0_PIN_IO_PU_PD(215),
+	SH73A0_PIN_IO_PD(216),
+	SH73A0_PIN_IO_PD(217),
+	SH73A0_PIN_O(218),
+	SH73A0_PIN_IO_PD(219),
+	SH73A0_PIN_IO_PD(220),
+	SH73A0_PIN_IO_PU_PD(221),
+	SH73A0_PIN_IO_PU_PD(222),
+	SH73A0_PIN_I_PU_PD(223),
+	SH73A0_PIN_I_PU_PD(224),
+	SH73A0_PIN_IO_PU_PD(225),
+	SH73A0_PIN_O(226),
+	SH73A0_PIN_IO_PU_PD(227),
+	SH73A0_PIN_I_PU_PD(228),
+	SH73A0_PIN_I_PD(229),
+	SH73A0_PIN_IO(230),
+	SH73A0_PIN_IO_PU_PD(231),
+	SH73A0_PIN_IO_PU_PD(232),
+	SH73A0_PIN_I_PU_PD(233),
+	SH73A0_PIN_IO_PU_PD(234),
+	SH73A0_PIN_IO_PU_PD(235),
+	SH73A0_PIN_IO_PU_PD(236),
+	SH73A0_PIN_IO_PD(237),
+	SH73A0_PIN_IO_PU_PD(238),
+	SH73A0_PIN_IO_PU_PD(239),
+	SH73A0_PIN_IO_PU_PD(240),
+	SH73A0_PIN_O(241),
+	SH73A0_PIN_I_PD(242),
+	SH73A0_PIN_IO_PU_PD(243),
+	SH73A0_PIN_IO_PU_PD(244),
+	SH73A0_PIN_IO_PU_PD(245),
+	SH73A0_PIN_IO_PU_PD(246),
+	SH73A0_PIN_IO_PU_PD(247),
+	SH73A0_PIN_IO_PU_PD(248),
+	SH73A0_PIN_IO_PU_PD(249),
+	SH73A0_PIN_IO_PU_PD(250),
+	SH73A0_PIN_IO_PU_PD(251),
+	SH73A0_PIN_IO_PU_PD(252),
+	SH73A0_PIN_IO_PU_PD(253),
+	SH73A0_PIN_IO_PU_PD(254),
+	SH73A0_PIN_IO_PU_PD(255),
+	SH73A0_PIN_IO_PU_PD(256),
+	SH73A0_PIN_IO_PU_PD(257),
+	SH73A0_PIN_IO_PU_PD(258),
+	SH73A0_PIN_IO_PU_PD(259),
+	SH73A0_PIN_IO_PU_PD(260),
+	SH73A0_PIN_IO_PU_PD(261),
+	SH73A0_PIN_IO_PU_PD(262),
+	SH73A0_PIN_IO_PU_PD(263),
+	SH73A0_PIN_IO_PU_PD(264),
+	SH73A0_PIN_IO_PU_PD(265),
+	SH73A0_PIN_IO_PU_PD(266),
+	SH73A0_PIN_IO_PU_PD(267),
+	SH73A0_PIN_IO_PU_PD(268),
+	SH73A0_PIN_IO_PU_PD(269),
+	SH73A0_PIN_IO_PU_PD(270),
+	SH73A0_PIN_IO_PU_PD(271),
+	SH73A0_PIN_IO_PU_PD(272),
+	SH73A0_PIN_IO_PU_PD(273),
+	SH73A0_PIN_IO_PU_PD(274),
+	SH73A0_PIN_IO_PU_PD(275),
+	SH73A0_PIN_IO_PU_PD(276),
+	SH73A0_PIN_IO_PU_PD(277),
+	SH73A0_PIN_IO_PU_PD(278),
+	SH73A0_PIN_IO_PU_PD(279),
+	SH73A0_PIN_IO_PU_PD(280),
+	SH73A0_PIN_O(281),
+	SH73A0_PIN_O(282),
+	SH73A0_PIN_I_PU(288),
+	SH73A0_PIN_IO_PU_PD(289),
+	SH73A0_PIN_IO_PU_PD(290),
+	SH73A0_PIN_IO_PU_PD(291),
+	SH73A0_PIN_IO_PU_PD(292),
+	SH73A0_PIN_IO_PU_PD(293),
+	SH73A0_PIN_IO_PU_PD(294),
+	SH73A0_PIN_IO_PU_PD(295),
+	SH73A0_PIN_IO_PU_PD(296),
+	SH73A0_PIN_IO_PU_PD(297),
+	SH73A0_PIN_IO_PU_PD(298),
+	SH73A0_PIN_IO_PU_PD(299),
+	SH73A0_PIN_IO_PU_PD(300),
+	SH73A0_PIN_IO_PU_PD(301),
+	SH73A0_PIN_IO_PU_PD(302),
+	SH73A0_PIN_IO_PU_PD(303),
+	SH73A0_PIN_IO_PU_PD(304),
+	SH73A0_PIN_IO_PU_PD(305),
+	SH73A0_PIN_O(306),
+	SH73A0_PIN_O(307),
+	SH73A0_PIN_I_PU(308),
+	SH73A0_PIN_O(309),
+};
+
+static const struct pinmux_range pinmux_ranges[] = {
+	{.begin = 0, .end = 118,},
+	{.begin = 128, .end = 164,},
+	{.begin = 192, .end = 282,},
+	{.begin = 288, .end = 309,},
+};
+
+/* Pin numbers for pins without a corresponding GPIO port number are computed
+ * from the row and column numbers with a 1000 offset to avoid collisions with
+ * GPIO port numbers.
+ */
+#define PIN_NUMBER(row, col)		(1000+((row)-1)*34+(col)-1)
+
+/* - BSC -------------------------------------------------------------------- */
+static const unsigned int bsc_data_0_7_pins[] = {
+	/* D[0:7] */
+	74, 75, 76, 77, 78, 79, 80, 81,
+};
+static const unsigned int bsc_data_0_7_mux[] = {
+	D0_NAF0_MARK, D1_NAF1_MARK, D2_NAF2_MARK, D3_NAF3_MARK,
+	D4_NAF4_MARK, D5_NAF5_MARK, D6_NAF6_MARK, D7_NAF7_MARK,
+};
+static const unsigned int bsc_data_8_15_pins[] = {
+	/* D[8:15] */
+	82, 83, 84, 85, 86, 87, 88, 89,
+};
+static const unsigned int bsc_data_8_15_mux[] = {
+	D8_NAF8_MARK, D9_NAF9_MARK, D10_NAF10_MARK, D11_NAF11_MARK,
+	D12_NAF12_MARK, D13_NAF13_MARK, D14_NAF14_MARK, D15_NAF15_MARK,
+};
+static const unsigned int bsc_cs4_pins[] = {
+	/* CS */
+	90,
+};
+static const unsigned int bsc_cs4_mux[] = {
+	CS4__MARK,
+};
+static const unsigned int bsc_cs5_a_pins[] = {
+	/* CS */
+	91,
+};
+static const unsigned int bsc_cs5_a_mux[] = {
+	CS5A__MARK,
+};
+static const unsigned int bsc_cs5_b_pins[] = {
+	/* CS */
+	92,
+};
+static const unsigned int bsc_cs5_b_mux[] = {
+	CS5B__MARK,
+};
+static const unsigned int bsc_cs6_a_pins[] = {
+	/* CS */
+	94,
+};
+static const unsigned int bsc_cs6_a_mux[] = {
+	CS6A__MARK,
+};
+static const unsigned int bsc_cs6_b_pins[] = {
+	/* CS */
+	93,
+};
+static const unsigned int bsc_cs6_b_mux[] = {
+	CS6B__MARK,
+};
+static const unsigned int bsc_rd_pins[] = {
+	/* RD */
+	96,
+};
+static const unsigned int bsc_rd_mux[] = {
+	RD__FSC_MARK,
+};
+static const unsigned int bsc_rdwr_0_pins[] = {
+	/* RDWR */
+	91,
+};
+static const unsigned int bsc_rdwr_0_mux[] = {
+	PORT91_RDWR_MARK,
+};
+static const unsigned int bsc_rdwr_1_pins[] = {
+	/* RDWR */
+	97,
+};
+static const unsigned int bsc_rdwr_1_mux[] = {
+	RDWR_FWE_MARK,
+};
+static const unsigned int bsc_rdwr_2_pins[] = {
+	/* RDWR */
+	149,
+};
+static const unsigned int bsc_rdwr_2_mux[] = {
+	PORT149_RDWR_MARK,
+};
+static const unsigned int bsc_we0_pins[] = {
+	/* WE0 */
+	97,
+};
+static const unsigned int bsc_we0_mux[] = {
+	WE0__FWE_MARK,
+};
+static const unsigned int bsc_we1_pins[] = {
+	/* WE1 */
+	98,
+};
+static const unsigned int bsc_we1_mux[] = {
+	WE1__MARK,
+};
+/* - FSIA ------------------------------------------------------------------- */
+static const unsigned int fsia_mclk_in_pins[] = {
+	/* CK */
+	49,
+};
+static const unsigned int fsia_mclk_in_mux[] = {
+	FSIACK_MARK,
+};
+static const unsigned int fsia_mclk_out_pins[] = {
+	/* OMC */
+	49,
+};
+static const unsigned int fsia_mclk_out_mux[] = {
+	FSIAOMC_MARK,
+};
+static const unsigned int fsia_sclk_in_pins[] = {
+	/* ILR, IBT */
+	50, 51,
+};
+static const unsigned int fsia_sclk_in_mux[] = {
+	FSIAILR_MARK, FSIAIBT_MARK,
+};
+static const unsigned int fsia_sclk_out_pins[] = {
+	/* OLR, OBT */
+	50, 51,
+};
+static const unsigned int fsia_sclk_out_mux[] = {
+	FSIAOLR_MARK, FSIAOBT_MARK,
+};
+static const unsigned int fsia_data_in_pins[] = {
+	/* ISLD */
+	55,
+};
+static const unsigned int fsia_data_in_mux[] = {
+	FSIAISLD_MARK,
+};
+static const unsigned int fsia_data_out_pins[] = {
+	/* OSLD */
+	52,
+};
+static const unsigned int fsia_data_out_mux[] = {
+	FSIAOSLD_MARK,
+};
+static const unsigned int fsia_spdif_pins[] = {
+	/* SPDIF */
+	53,
+};
+static const unsigned int fsia_spdif_mux[] = {
+	FSIASPDIF_MARK,
+};
+/* - FSIB ------------------------------------------------------------------- */
+static const unsigned int fsib_mclk_in_pins[] = {
+	/* CK */
+	54,
+};
+static const unsigned int fsib_mclk_in_mux[] = {
+	FSIBCK_MARK,
+};
+static const unsigned int fsib_mclk_out_pins[] = {
+	/* OMC */
+	54,
+};
+static const unsigned int fsib_mclk_out_mux[] = {
+	FSIBOMC_MARK,
+};
+static const unsigned int fsib_sclk_in_pins[] = {
+	/* ILR, IBT */
+	37, 36,
+};
+static const unsigned int fsib_sclk_in_mux[] = {
+	FSIBILR_MARK, FSIBIBT_MARK,
+};
+static const unsigned int fsib_sclk_out_pins[] = {
+	/* OLR, OBT */
+	37, 36,
+};
+static const unsigned int fsib_sclk_out_mux[] = {
+	FSIBOLR_MARK, FSIBOBT_MARK,
+};
+static const unsigned int fsib_data_in_pins[] = {
+	/* ISLD */
+	39,
+};
+static const unsigned int fsib_data_in_mux[] = {
+	FSIBISLD_MARK,
+};
+static const unsigned int fsib_data_out_pins[] = {
+	/* OSLD */
+	38,
+};
+static const unsigned int fsib_data_out_mux[] = {
+	FSIBOSLD_MARK,
+};
+static const unsigned int fsib_spdif_pins[] = {
+	/* SPDIF */
+	53,
+};
+static const unsigned int fsib_spdif_mux[] = {
+	FSIBSPDIF_MARK,
+};
+/* - FSIC ------------------------------------------------------------------- */
+static const unsigned int fsic_mclk_in_pins[] = {
+	/* CK */
+	54,
+};
+static const unsigned int fsic_mclk_in_mux[] = {
+	FSICCK_MARK,
+};
+static const unsigned int fsic_mclk_out_pins[] = {
+	/* OMC */
+	54,
+};
+static const unsigned int fsic_mclk_out_mux[] = {
+	FSICOMC_MARK,
+};
+static const unsigned int fsic_sclk_in_pins[] = {
+	/* ILR, IBT */
+	46, 45,
+};
+static const unsigned int fsic_sclk_in_mux[] = {
+	FSICILR_MARK, FSICIBT_MARK,
+};
+static const unsigned int fsic_sclk_out_pins[] = {
+	/* OLR, OBT */
+	46, 45,
+};
+static const unsigned int fsic_sclk_out_mux[] = {
+	FSICOLR_MARK, FSICOBT_MARK,
+};
+static const unsigned int fsic_data_in_pins[] = {
+	/* ISLD */
+	48,
+};
+static const unsigned int fsic_data_in_mux[] = {
+	FSICISLD_MARK,
+};
+static const unsigned int fsic_data_out_pins[] = {
+	/* OSLD, OSLDT1, OSLDT2, OSLDT3 */
+	47, 44, 42, 16,
+};
+static const unsigned int fsic_data_out_mux[] = {
+	FSICOSLD_MARK, FSICOSLDT1_MARK, FSICOSLDT2_MARK, FSICOSLDT3_MARK,
+};
+static const unsigned int fsic_spdif_0_pins[] = {
+	/* SPDIF */
+	53,
+};
+static const unsigned int fsic_spdif_0_mux[] = {
+	PORT53_FSICSPDIF_MARK,
+};
+static const unsigned int fsic_spdif_1_pins[] = {
+	/* SPDIF */
+	47,
+};
+static const unsigned int fsic_spdif_1_mux[] = {
+	PORT47_FSICSPDIF_MARK,
+};
+/* - FSID ------------------------------------------------------------------- */
+static const unsigned int fsid_sclk_in_pins[] = {
+	/* ILR, IBT */
+	46, 45,
+};
+static const unsigned int fsid_sclk_in_mux[] = {
+	FSIDILR_MARK, FSIDIBT_MARK,
+};
+static const unsigned int fsid_sclk_out_pins[] = {
+	/* OLR, OBT */
+	46, 45,
+};
+static const unsigned int fsid_sclk_out_mux[] = {
+	FSIDOLR_MARK, FSIDOBT_MARK,
+};
+static const unsigned int fsid_data_in_pins[] = {
+	/* ISLD */
+	48,
+};
+static const unsigned int fsid_data_in_mux[] = {
+	FSIDISLD_MARK,
+};
+/* - I2C2 ------------------------------------------------------------------- */
+static const unsigned int i2c2_0_pins[] = {
+	/* SCL, SDA */
+	237, 236,
+};
+static const unsigned int i2c2_0_mux[] = {
+	PORT237_I2C_SCL2_MARK, PORT236_I2C_SDA2_MARK,
+};
+static const unsigned int i2c2_1_pins[] = {
+	/* SCL, SDA */
+	27, 28,
+};
+static const unsigned int i2c2_1_mux[] = {
+	PORT27_I2C_SCL2_MARK, PORT28_I2C_SDA2_MARK,
+};
+static const unsigned int i2c2_2_pins[] = {
+	/* SCL, SDA */
+	115, 116,
+};
+static const unsigned int i2c2_2_mux[] = {
+	PORT115_I2C_SCL2_MARK, PORT116_I2C_SDA2_MARK,
+};
+/* - I2C3 ------------------------------------------------------------------- */
+static const unsigned int i2c3_0_pins[] = {
+	/* SCL, SDA */
+	248, 249,
+};
+static const unsigned int i2c3_0_mux[] = {
+	PORT248_I2C_SCL3_MARK, PORT249_I2C_SDA3_MARK,
+};
+static const unsigned int i2c3_1_pins[] = {
+	/* SCL, SDA */
+	27, 28,
+};
+static const unsigned int i2c3_1_mux[] = {
+	PORT27_I2C_SCL3_MARK, PORT28_I2C_SDA3_MARK,
+};
+static const unsigned int i2c3_2_pins[] = {
+	/* SCL, SDA */
+	115, 116,
+};
+static const unsigned int i2c3_2_mux[] = {
+	PORT115_I2C_SCL3_MARK, PORT116_I2C_SDA3_MARK,
+};
+/* - IrDA ------------------------------------------------------------------- */
+static const unsigned int irda_0_pins[] = {
+	/* OUT, IN, FIRSEL */
+	241, 242, 243,
+};
+static const unsigned int irda_0_mux[] = {
+	PORT241_IRDA_OUT_MARK, PORT242_IRDA_IN_MARK, PORT243_IRDA_FIRSEL_MARK,
+};
+static const unsigned int irda_1_pins[] = {
+	/* OUT, IN, FIRSEL */
+	49, 53, 54,
+};
+static const unsigned int irda_1_mux[] = {
+	PORT49_IRDA_OUT_MARK, PORT53_IRDA_IN_MARK, PORT54_IRDA_FIRSEL_MARK,
+};
+/* - KEYSC ------------------------------------------------------------------ */
+static const unsigned int keysc_in5_pins[] = {
+	/* KEYIN[0:4] */
+	66, 67, 68, 69, 70,
+};
+static const unsigned int keysc_in5_mux[] = {
+	KEYIN0_MARK, KEYIN1_MARK, KEYIN2_MARK, KEYIN3_MARK,
+	KEYIN4_MARK,
+};
+static const unsigned int keysc_in6_pins[] = {
+	/* KEYIN[0:5] */
+	66, 67, 68, 69, 70, 71,
+};
+static const unsigned int keysc_in6_mux[] = {
+	KEYIN0_MARK, KEYIN1_MARK, KEYIN2_MARK, KEYIN3_MARK,
+	KEYIN4_MARK, KEYIN5_MARK,
+};
+static const unsigned int keysc_in7_pins[] = {
+	/* KEYIN[0:6] */
+	66, 67, 68, 69, 70, 71, 72,
+};
+static const unsigned int keysc_in7_mux[] = {
+	KEYIN0_MARK, KEYIN1_MARK, KEYIN2_MARK, KEYIN3_MARK,
+	KEYIN4_MARK, KEYIN5_MARK, KEYIN6_MARK,
+};
+static const unsigned int keysc_in8_pins[] = {
+	/* KEYIN[0:7] */
+	66, 67, 68, 69, 70, 71, 72, 73,
+};
+static const unsigned int keysc_in8_mux[] = {
+	KEYIN0_MARK, KEYIN1_MARK, KEYIN2_MARK, KEYIN3_MARK,
+	KEYIN4_MARK, KEYIN5_MARK, KEYIN6_MARK, KEYIN7_MARK,
+};
+static const unsigned int keysc_out04_pins[] = {
+	/* KEYOUT[0:4] */
+	65, 64, 63, 62, 61,
+};
+static const unsigned int keysc_out04_mux[] = {
+	KEYOUT0_MARK, KEYOUT1_MARK, KEYOUT2_MARK, KEYOUT3_MARK, KEYOUT4_MARK,
+};
+static const unsigned int keysc_out5_pins[] = {
+	/* KEYOUT5 */
+	60,
+};
+static const unsigned int keysc_out5_mux[] = {
+	KEYOUT5_MARK,
+};
+static const unsigned int keysc_out6_0_pins[] = {
+	/* KEYOUT6 */
+	59,
+};
+static const unsigned int keysc_out6_0_mux[] = {
+	PORT59_KEYOUT6_MARK,
+};
+static const unsigned int keysc_out6_1_pins[] = {
+	/* KEYOUT6 */
+	131,
+};
+static const unsigned int keysc_out6_1_mux[] = {
+	PORT131_KEYOUT6_MARK,
+};
+static const unsigned int keysc_out6_2_pins[] = {
+	/* KEYOUT6 */
+	143,
+};
+static const unsigned int keysc_out6_2_mux[] = {
+	PORT143_KEYOUT6_MARK,
+};
+static const unsigned int keysc_out7_0_pins[] = {
+	/* KEYOUT7 */
+	58,
+};
+static const unsigned int keysc_out7_0_mux[] = {
+	PORT58_KEYOUT7_MARK,
+};
+static const unsigned int keysc_out7_1_pins[] = {
+	/* KEYOUT7 */
+	132,
+};
+static const unsigned int keysc_out7_1_mux[] = {
+	PORT132_KEYOUT7_MARK,
+};
+static const unsigned int keysc_out7_2_pins[] = {
+	/* KEYOUT7 */
+	144,
+};
+static const unsigned int keysc_out7_2_mux[] = {
+	PORT144_KEYOUT7_MARK,
+};
+static const unsigned int keysc_out8_0_pins[] = {
+	/* KEYOUT8 */
+	PIN_NUMBER(6, 26),
+};
+static const unsigned int keysc_out8_0_mux[] = {
+	KEYOUT8_MARK,
+};
+static const unsigned int keysc_out8_1_pins[] = {
+	/* KEYOUT8 */
+	136,
+};
+static const unsigned int keysc_out8_1_mux[] = {
+	PORT136_KEYOUT8_MARK,
+};
+static const unsigned int keysc_out8_2_pins[] = {
+	/* KEYOUT8 */
+	138,
+};
+static const unsigned int keysc_out8_2_mux[] = {
+	PORT138_KEYOUT8_MARK,
+};
+static const unsigned int keysc_out9_0_pins[] = {
+	/* KEYOUT9 */
+	137,
+};
+static const unsigned int keysc_out9_0_mux[] = {
+	PORT137_KEYOUT9_MARK,
+};
+static const unsigned int keysc_out9_1_pins[] = {
+	/* KEYOUT9 */
+	139,
+};
+static const unsigned int keysc_out9_1_mux[] = {
+	PORT139_KEYOUT9_MARK,
+};
+static const unsigned int keysc_out9_2_pins[] = {
+	/* KEYOUT9 */
+	149,
+};
+static const unsigned int keysc_out9_2_mux[] = {
+	PORT149_KEYOUT9_MARK,
+};
+static const unsigned int keysc_out10_0_pins[] = {
+	/* KEYOUT10 */
+	132,
+};
+static const unsigned int keysc_out10_0_mux[] = {
+	PORT132_KEYOUT10_MARK,
+};
+static const unsigned int keysc_out10_1_pins[] = {
+	/* KEYOUT10 */
+	142,
+};
+static const unsigned int keysc_out10_1_mux[] = {
+	PORT142_KEYOUT10_MARK,
+};
+static const unsigned int keysc_out11_0_pins[] = {
+	/* KEYOUT11 */
+	131,
+};
+static const unsigned int keysc_out11_0_mux[] = {
+	PORT131_KEYOUT11_MARK,
+};
+static const unsigned int keysc_out11_1_pins[] = {
+	/* KEYOUT11 */
+	143,
+};
+static const unsigned int keysc_out11_1_mux[] = {
+	PORT143_KEYOUT11_MARK,
+};
+/* - LCD -------------------------------------------------------------------- */
+static const unsigned int lcd_data8_pins[] = {
+	/* D[0:7] */
+	192, 193, 194, 195, 196, 197, 198, 199,
+};
+static const unsigned int lcd_data8_mux[] = {
+	LCDD0_MARK, LCDD1_MARK, LCDD2_MARK, LCDD3_MARK,
+	LCDD4_MARK, LCDD5_MARK, LCDD6_MARK, LCDD7_MARK,
+};
+static const unsigned int lcd_data9_pins[] = {
+	/* D[0:8] */
+	192, 193, 194, 195, 196, 197, 198, 199,
+	200,
+};
+static const unsigned int lcd_data9_mux[] = {
+	LCDD0_MARK, LCDD1_MARK, LCDD2_MARK, LCDD3_MARK,
+	LCDD4_MARK, LCDD5_MARK, LCDD6_MARK, LCDD7_MARK,
+	LCDD8_MARK,
+};
+static const unsigned int lcd_data12_pins[] = {
+	/* D[0:11] */
+	192, 193, 194, 195, 196, 197, 198, 199,
+	200, 201, 202, 203,
+};
+static const unsigned int lcd_data12_mux[] = {
+	LCDD0_MARK, LCDD1_MARK, LCDD2_MARK, LCDD3_MARK,
+	LCDD4_MARK, LCDD5_MARK, LCDD6_MARK, LCDD7_MARK,
+	LCDD8_MARK, LCDD9_MARK, LCDD10_MARK, LCDD11_MARK,
+};
+static const unsigned int lcd_data16_pins[] = {
+	/* D[0:15] */
+	192, 193, 194, 195, 196, 197, 198, 199,
+	200, 201, 202, 203, 204, 205, 206, 207,
+};
+static const unsigned int lcd_data16_mux[] = {
+	LCDD0_MARK, LCDD1_MARK, LCDD2_MARK, LCDD3_MARK,
+	LCDD4_MARK, LCDD5_MARK, LCDD6_MARK, LCDD7_MARK,
+	LCDD8_MARK, LCDD9_MARK, LCDD10_MARK, LCDD11_MARK,
+	LCDD12_MARK, LCDD13_MARK, LCDD14_MARK, LCDD15_MARK,
+};
+static const unsigned int lcd_data18_pins[] = {
+	/* D[0:17] */
+	192, 193, 194, 195, 196, 197, 198, 199,
+	200, 201, 202, 203, 204, 205, 206, 207,
+	208, 209,
+};
+static const unsigned int lcd_data18_mux[] = {
+	LCDD0_MARK, LCDD1_MARK, LCDD2_MARK, LCDD3_MARK,
+	LCDD4_MARK, LCDD5_MARK, LCDD6_MARK, LCDD7_MARK,
+	LCDD8_MARK, LCDD9_MARK, LCDD10_MARK, LCDD11_MARK,
+	LCDD12_MARK, LCDD13_MARK, LCDD14_MARK, LCDD15_MARK,
+	LCDD16_MARK, LCDD17_MARK,
+};
+static const unsigned int lcd_data24_pins[] = {
+	/* D[0:23] */
+	192, 193, 194, 195, 196, 197, 198, 199,
+	200, 201, 202, 203, 204, 205, 206, 207,
+	208, 209, 210, 211, 212, 213, 214, 215
+};
+static const unsigned int lcd_data24_mux[] = {
+	LCDD0_MARK, LCDD1_MARK, LCDD2_MARK, LCDD3_MARK,
+	LCDD4_MARK, LCDD5_MARK, LCDD6_MARK, LCDD7_MARK,
+	LCDD8_MARK, LCDD9_MARK, LCDD10_MARK, LCDD11_MARK,
+	LCDD12_MARK, LCDD13_MARK, LCDD14_MARK, LCDD15_MARK,
+	LCDD16_MARK, LCDD17_MARK, LCDD18_MARK, LCDD19_MARK,
+	LCDD20_MARK, LCDD21_MARK, LCDD22_MARK, LCDD23_MARK,
+};
+static const unsigned int lcd_display_pins[] = {
+	/* DON */
+	222,
+};
+static const unsigned int lcd_display_mux[] = {
+	LCDDON_MARK,
+};
+static const unsigned int lcd_lclk_pins[] = {
+	/* LCLK */
+	221,
+};
+static const unsigned int lcd_lclk_mux[] = {
+	LCDLCLK_MARK,
+};
+static const unsigned int lcd_sync_pins[] = {
+	/* VSYN, HSYN, DCK, DISP */
+	220, 218, 216, 219,
+};
+static const unsigned int lcd_sync_mux[] = {
+	LCDVSYN_MARK, LCDHSYN_MARK, LCDDCK_MARK, LCDDISP_MARK,
+};
+static const unsigned int lcd_sys_pins[] = {
+	/* CS, WR, RD, RS */
+	218, 216, 217, 219,
+};
+static const unsigned int lcd_sys_mux[] = {
+	LCDCS__MARK, LCDWR__MARK, LCDRD__MARK, LCDRS_MARK,
+};
+/* - LCD2 ------------------------------------------------------------------- */
+static const unsigned int lcd2_data8_pins[] = {
+	/* D[0:7] */
+	128, 129, 142, 143, 144, 145, 138, 139,
+};
+static const unsigned int lcd2_data8_mux[] = {
+	LCD2D0_MARK, LCD2D1_MARK, LCD2D2_MARK, LCD2D3_MARK,
+	LCD2D4_MARK, LCD2D5_MARK, LCD2D6_MARK, LCD2D7_MARK,
+};
+static const unsigned int lcd2_data9_pins[] = {
+	/* D[0:8] */
+	128, 129, 142, 143, 144, 145, 138, 139,
+	140,
+};
+static const unsigned int lcd2_data9_mux[] = {
+	LCD2D0_MARK, LCD2D1_MARK, LCD2D2_MARK, LCD2D3_MARK,
+	LCD2D4_MARK, LCD2D5_MARK, LCD2D6_MARK, LCD2D7_MARK,
+	LCD2D8_MARK,
+};
+static const unsigned int lcd2_data12_pins[] = {
+	/* D[0:12] */
+	128, 129, 142, 143, 144, 145, 138, 139,
+	140, 141, 130, 131,
+};
+static const unsigned int lcd2_data12_mux[] = {
+	LCD2D0_MARK, LCD2D1_MARK, LCD2D2_MARK, LCD2D3_MARK,
+	LCD2D4_MARK, LCD2D5_MARK, LCD2D6_MARK, LCD2D7_MARK,
+	LCD2D8_MARK, LCD2D9_MARK, LCD2D10_MARK, LCD2D11_MARK,
+};
+static const unsigned int lcd2_data16_pins[] = {
+	/* D[0:15] */
+	128, 129, 142, 143, 144, 145, 138, 139,
+	140, 141, 130, 131, 132, 133, 134, 135,
+};
+static const unsigned int lcd2_data16_mux[] = {
+	LCD2D0_MARK, LCD2D1_MARK, LCD2D2_MARK, LCD2D3_MARK,
+	LCD2D4_MARK, LCD2D5_MARK, LCD2D6_MARK, LCD2D7_MARK,
+	LCD2D8_MARK, LCD2D9_MARK, LCD2D10_MARK, LCD2D11_MARK,
+	LCD2D12_MARK, LCD2D13_MARK, LCD2D14_MARK, LCD2D15_MARK,
+};
+static const unsigned int lcd2_data18_pins[] = {
+	/* D[0:17] */
+	128, 129, 142, 143, 144, 145, 138, 139,
+	140, 141, 130, 131, 132, 133, 134, 135,
+	136, 137,
+};
+static const unsigned int lcd2_data18_mux[] = {
+	LCD2D0_MARK, LCD2D1_MARK, LCD2D2_MARK, LCD2D3_MARK,
+	LCD2D4_MARK, LCD2D5_MARK, LCD2D6_MARK, LCD2D7_MARK,
+	LCD2D8_MARK, LCD2D9_MARK, LCD2D10_MARK, LCD2D11_MARK,
+	LCD2D12_MARK, LCD2D13_MARK, LCD2D14_MARK, LCD2D15_MARK,
+	LCD2D16_MARK, LCD2D17_MARK,
+};
+static const unsigned int lcd2_data24_pins[] = {
+	/* D[0:23] */
+	128, 129, 142, 143, 144, 145, 138, 139,
+	140, 141, 130, 131, 132, 133, 134, 135,
+	136, 137, 146, 147, 234, 235, 238, 239
+};
+static const unsigned int lcd2_data24_mux[] = {
+	LCD2D0_MARK, LCD2D1_MARK, LCD2D2_MARK, LCD2D3_MARK,
+	LCD2D4_MARK, LCD2D5_MARK, LCD2D6_MARK, LCD2D7_MARK,
+	LCD2D8_MARK, LCD2D9_MARK, LCD2D10_MARK, LCD2D11_MARK,
+	LCD2D12_MARK, LCD2D13_MARK, LCD2D14_MARK, LCD2D15_MARK,
+	LCD2D16_MARK, LCD2D17_MARK, LCD2D18_MARK, LCD2D19_MARK,
+	LCD2D20_MARK, LCD2D21_MARK, LCD2D22_MARK, LCD2D23_MARK,
+};
+static const unsigned int lcd2_sync_0_pins[] = {
+	/* VSYN, HSYN, DCK, DISP */
+	128, 129, 146, 145,
+};
+static const unsigned int lcd2_sync_0_mux[] = {
+	PORT128_LCD2VSYN_MARK, PORT129_LCD2HSYN_MARK,
+	LCD2DCK_MARK, PORT145_LCD2DISP_MARK,
+};
+static const unsigned int lcd2_sync_1_pins[] = {
+	/* VSYN, HSYN, DCK, DISP */
+	222, 221, 219, 217,
+};
+static const unsigned int lcd2_sync_1_mux[] = {
+	PORT222_LCD2VSYN_MARK, PORT221_LCD2HSYN_MARK,
+	LCD2DCK_2_MARK, PORT217_LCD2DISP_MARK,
+};
+static const unsigned int lcd2_sys_0_pins[] = {
+	/* CS, WR, RD, RS */
+	129, 146, 147, 145,
+};
+static const unsigned int lcd2_sys_0_mux[] = {
+	PORT129_LCD2CS__MARK, PORT146_LCD2WR__MARK,
+	LCD2RD__MARK, PORT145_LCD2RS_MARK,
+};
+static const unsigned int lcd2_sys_1_pins[] = {
+	/* CS, WR, RD, RS */
+	221, 219, 147, 217,
+};
+static const unsigned int lcd2_sys_1_mux[] = {
+	PORT221_LCD2CS__MARK, PORT219_LCD2WR__MARK,
+	LCD2RD__MARK, PORT217_LCD2RS_MARK,
+};
+/* - MMCIF ------------------------------------------------------------------ */
+static const unsigned int mmc0_data1_0_pins[] = {
+	/* D[0] */
+	271,
+};
+static const unsigned int mmc0_data1_0_mux[] = {
+	MMCD0_0_MARK,
+};
+static const unsigned int mmc0_data4_0_pins[] = {
+	/* D[0:3] */
+	271, 272, 273, 274,
+};
+static const unsigned int mmc0_data4_0_mux[] = {
+	MMCD0_0_MARK, MMCD0_1_MARK, MMCD0_2_MARK, MMCD0_3_MARK,
+};
+static const unsigned int mmc0_data8_0_pins[] = {
+	/* D[0:7] */
+	271, 272, 273, 274, 275, 276, 277, 278,
+};
+static const unsigned int mmc0_data8_0_mux[] = {
+	MMCD0_0_MARK, MMCD0_1_MARK, MMCD0_2_MARK, MMCD0_3_MARK,
+	MMCD0_4_MARK, MMCD0_5_MARK, MMCD0_6_MARK, MMCD0_7_MARK,
+};
+static const unsigned int mmc0_ctrl_0_pins[] = {
+	/* CMD, CLK */
+	279, 270,
+};
+static const unsigned int mmc0_ctrl_0_mux[] = {
+	MMCCMD0_MARK, MMCCLK0_MARK,
+};
 
-	/* Functions with pull-ups */
-	PINMUX_DATA(KEYIN0_PU_MARK, PORT66_FN2, PORT66_IN_PU),
-	PINMUX_DATA(KEYIN1_PU_MARK, PORT67_FN2, PORT67_IN_PU),
-	PINMUX_DATA(KEYIN2_PU_MARK, PORT68_FN2, PORT68_IN_PU),
-	PINMUX_DATA(KEYIN3_PU_MARK, PORT69_FN2, PORT69_IN_PU),
-	PINMUX_DATA(KEYIN4_PU_MARK, PORT70_FN2, PORT70_IN_PU),
-	PINMUX_DATA(KEYIN5_PU_MARK, PORT71_FN2, PORT71_IN_PU),
-	PINMUX_DATA(KEYIN6_PU_MARK, PORT72_FN2, PORT72_IN_PU),
-	PINMUX_DATA(KEYIN7_PU_MARK, PORT73_FN2, PORT73_IN_PU),
-
-	PINMUX_DATA(SDHICD0_PU_MARK,  PORT251_FN1, PORT251_IN_PU),
-	PINMUX_DATA(SDHID0_0_PU_MARK, PORT252_FN1, PORT252_IN_PU),
-	PINMUX_DATA(SDHID0_1_PU_MARK, PORT253_FN1, PORT253_IN_PU),
-	PINMUX_DATA(SDHID0_2_PU_MARK, PORT254_FN1, PORT254_IN_PU),
-	PINMUX_DATA(SDHID0_3_PU_MARK, PORT255_FN1, PORT255_IN_PU),
-	PINMUX_DATA(SDHICMD0_PU_MARK, PORT256_FN1, PORT256_IN_PU),
-	PINMUX_DATA(SDHIWP0_PU_MARK,  PORT257_FN1, PORT256_IN_PU),
-	PINMUX_DATA(SDHID1_0_PU_MARK, PORT259_FN1, PORT259_IN_PU),
-	PINMUX_DATA(SDHID1_1_PU_MARK, PORT260_FN1, PORT260_IN_PU),
-	PINMUX_DATA(SDHID1_2_PU_MARK, PORT261_FN1, PORT261_IN_PU),
-	PINMUX_DATA(SDHID1_3_PU_MARK, PORT262_FN1, PORT262_IN_PU),
-	PINMUX_DATA(SDHICMD1_PU_MARK, PORT263_FN1, PORT263_IN_PU),
-	PINMUX_DATA(SDHID2_0_PU_MARK, PORT265_FN1, PORT265_IN_PU),
-	PINMUX_DATA(SDHID2_1_PU_MARK, PORT266_FN1, PORT266_IN_PU),
-	PINMUX_DATA(SDHID2_2_PU_MARK, PORT267_FN1, PORT267_IN_PU),
-	PINMUX_DATA(SDHID2_3_PU_MARK, PORT268_FN1, PORT268_IN_PU),
-	PINMUX_DATA(SDHICMD2_PU_MARK, PORT269_FN1, PORT269_IN_PU),
-
-	PINMUX_DATA(MMCCMD0_PU_MARK, PORT279_FN1, PORT279_IN_PU,
-		MSEL4CR_MSEL15_0),
-	PINMUX_DATA(MMCCMD1_PU_MARK, PORT297_FN2, PORT297_IN_PU,
-		MSEL4CR_MSEL15_1),
-
-	PINMUX_DATA(MMCD0_0_PU_MARK,
-		    PORT271_FN1, PORT271_IN_PU, MSEL4CR_MSEL15_0),
-	PINMUX_DATA(MMCD0_1_PU_MARK,
-		    PORT272_FN1, PORT272_IN_PU, MSEL4CR_MSEL15_0),
-	PINMUX_DATA(MMCD0_2_PU_MARK,
-		    PORT273_FN1, PORT273_IN_PU, MSEL4CR_MSEL15_0),
-	PINMUX_DATA(MMCD0_3_PU_MARK,
-		    PORT274_FN1, PORT274_IN_PU, MSEL4CR_MSEL15_0),
-	PINMUX_DATA(MMCD0_4_PU_MARK,
-		    PORT275_FN1, PORT275_IN_PU, MSEL4CR_MSEL15_0),
-	PINMUX_DATA(MMCD0_5_PU_MARK,
-		    PORT276_FN1, PORT276_IN_PU, MSEL4CR_MSEL15_0),
-	PINMUX_DATA(MMCD0_6_PU_MARK,
-		    PORT277_FN1, PORT277_IN_PU, MSEL4CR_MSEL15_0),
-	PINMUX_DATA(MMCD0_7_PU_MARK,
-		    PORT278_FN1, PORT278_IN_PU, MSEL4CR_MSEL15_0),
-
-	PINMUX_DATA(FSIBISLD_PU_MARK, PORT39_FN1, PORT39_IN_PU),
-	PINMUX_DATA(FSIACK_PU_MARK, PORT49_FN1, PORT49_IN_PU),
-	PINMUX_DATA(FSIAILR_PU_MARK, PORT50_FN5, PORT50_IN_PU),
-	PINMUX_DATA(FSIAIBT_PU_MARK, PORT51_FN5, PORT51_IN_PU),
-	PINMUX_DATA(FSIAISLD_PU_MARK, PORT55_FN1, PORT55_IN_PU),
-};
-
-static struct pinmux_gpio pinmux_gpios[] = {
-	GPIO_PORT_ALL(),
+static const unsigned int mmc0_data1_1_pins[] = {
+	/* D[0] */
+	305,
+};
+static const unsigned int mmc0_data1_1_mux[] = {
+	MMCD1_0_MARK,
+};
+static const unsigned int mmc0_data4_1_pins[] = {
+	/* D[0:3] */
+	305, 304, 303, 302,
+};
+static const unsigned int mmc0_data4_1_mux[] = {
+	MMCD1_0_MARK, MMCD1_1_MARK, MMCD1_2_MARK, MMCD1_3_MARK,
+};
+static const unsigned int mmc0_data8_1_pins[] = {
+	/* D[0:7] */
+	305, 304, 303, 302, 301, 300, 299, 298,
+};
+static const unsigned int mmc0_data8_1_mux[] = {
+	MMCD1_0_MARK, MMCD1_1_MARK, MMCD1_2_MARK, MMCD1_3_MARK,
+	MMCD1_4_MARK, MMCD1_5_MARK, MMCD1_6_MARK, MMCD1_7_MARK,
+};
+static const unsigned int mmc0_ctrl_1_pins[] = {
+	/* CMD, CLK */
+	297, 289,
+};
+static const unsigned int mmc0_ctrl_1_mux[] = {
+	MMCCMD1_MARK, MMCCLK1_MARK,
+};
+/* - SCIFA0 ----------------------------------------------------------------- */
+static const unsigned int scifa0_data_pins[] = {
+	/* RXD, TXD */
+	43, 17,
+};
+static const unsigned int scifa0_data_mux[] = {
+	SCIFA0_RXD_MARK, SCIFA0_TXD_MARK,
+};
+static const unsigned int scifa0_clk_pins[] = {
+	/* SCK */
+	16,
+};
+static const unsigned int scifa0_clk_mux[] = {
+	SCIFA0_SCK_MARK,
+};
+static const unsigned int scifa0_ctrl_pins[] = {
+	/* RTS, CTS */
+	42, 44,
+};
+static const unsigned int scifa0_ctrl_mux[] = {
+	SCIFA0_RTS__MARK, SCIFA0_CTS__MARK,
+};
+/* - SCIFA1 ----------------------------------------------------------------- */
+static const unsigned int scifa1_data_pins[] = {
+	/* RXD, TXD */
+	228, 225,
+};
+static const unsigned int scifa1_data_mux[] = {
+	SCIFA1_RXD_MARK, SCIFA1_TXD_MARK,
+};
+static const unsigned int scifa1_clk_pins[] = {
+	/* SCK */
+	226,
+};
+static const unsigned int scifa1_clk_mux[] = {
+	SCIFA1_SCK_MARK,
+};
+static const unsigned int scifa1_ctrl_pins[] = {
+	/* RTS, CTS */
+	227, 229,
+};
+static const unsigned int scifa1_ctrl_mux[] = {
+	SCIFA1_RTS__MARK, SCIFA1_CTS__MARK,
+};
+/* - SCIFA2 ----------------------------------------------------------------- */
+static const unsigned int scifa2_data_0_pins[] = {
+	/* RXD, TXD */
+	155, 154,
+};
+static const unsigned int scifa2_data_0_mux[] = {
+	SCIFA2_RXD1_MARK, SCIFA2_TXD1_MARK,
+};
+static const unsigned int scifa2_clk_0_pins[] = {
+	/* SCK */
+	158,
+};
+static const unsigned int scifa2_clk_0_mux[] = {
+	SCIFA2_SCK1_MARK,
+};
+static const unsigned int scifa2_ctrl_0_pins[] = {
+	/* RTS, CTS */
+	156, 157,
+};
+static const unsigned int scifa2_ctrl_0_mux[] = {
+	SCIFA2_RTS1__MARK, SCIFA2_CTS1__MARK,
+};
+static const unsigned int scifa2_data_1_pins[] = {
+	/* RXD, TXD */
+	233, 230,
+};
+static const unsigned int scifa2_data_1_mux[] = {
+	SCIFA2_RXD2_MARK, SCIFA2_TXD2_MARK,
+};
+static const unsigned int scifa2_clk_1_pins[] = {
+	/* SCK */
+	232,
+};
+static const unsigned int scifa2_clk_1_mux[] = {
+	SCIFA2_SCK2_MARK,
+};
+static const unsigned int scifa2_ctrl_1_pins[] = {
+	/* RTS, CTS */
+	234, 231,
+};
+static const unsigned int scifa2_ctrl_1_mux[] = {
+	SCIFA2_RTS2__MARK, SCIFA2_CTS2__MARK,
+};
+/* - SCIFA3 ----------------------------------------------------------------- */
+static const unsigned int scifa3_data_pins[] = {
+	/* RXD, TXD */
+	108, 110,
+};
+static const unsigned int scifa3_data_mux[] = {
+	SCIFA3_RXD_MARK, SCIFA3_TXD_MARK,
+};
+static const unsigned int scifa3_ctrl_pins[] = {
+	/* RTS, CTS */
+	109, 107,
+};
+static const unsigned int scifa3_ctrl_mux[] = {
+	SCIFA3_RTS__MARK, SCIFA3_CTS__MARK,
+};
+/* - SCIFA4 ----------------------------------------------------------------- */
+static const unsigned int scifa4_data_pins[] = {
+	/* RXD, TXD */
+	33, 32,
+};
+static const unsigned int scifa4_data_mux[] = {
+	SCIFA4_RXD_MARK, SCIFA4_TXD_MARK,
+};
+static const unsigned int scifa4_ctrl_pins[] = {
+	/* RTS, CTS */
+	34, 35,
+};
+static const unsigned int scifa4_ctrl_mux[] = {
+	SCIFA4_RTS__MARK, SCIFA4_CTS__MARK,
+};
+/* - SCIFA5 ----------------------------------------------------------------- */
+static const unsigned int scifa5_data_0_pins[] = {
+	/* RXD, TXD */
+	246, 247,
+};
+static const unsigned int scifa5_data_0_mux[] = {
+	PORT246_SCIFA5_RXD_MARK, PORT247_SCIFA5_TXD_MARK,
+};
+static const unsigned int scifa5_clk_0_pins[] = {
+	/* SCK */
+	248,
+};
+static const unsigned int scifa5_clk_0_mux[] = {
+	PORT248_SCIFA5_SCK_MARK,
+};
+static const unsigned int scifa5_ctrl_0_pins[] = {
+	/* RTS, CTS */
+	245, 244,
+};
+static const unsigned int scifa5_ctrl_0_mux[] = {
+	PORT245_SCIFA5_RTS__MARK, PORT244_SCIFA5_CTS__MARK,
+};
+static const unsigned int scifa5_data_1_pins[] = {
+	/* RXD, TXD */
+	195, 196,
+};
+static const unsigned int scifa5_data_1_mux[] = {
+	PORT195_SCIFA5_RXD_MARK, PORT196_SCIFA5_TXD_MARK,
+};
+static const unsigned int scifa5_clk_1_pins[] = {
+	/* SCK */
+	197,
+};
+static const unsigned int scifa5_clk_1_mux[] = {
+	PORT197_SCIFA5_SCK_MARK,
+};
+static const unsigned int scifa5_ctrl_1_pins[] = {
+	/* RTS, CTS */
+	194, 193,
+};
+static const unsigned int scifa5_ctrl_1_mux[] = {
+	PORT194_SCIFA5_RTS__MARK, PORT193_SCIFA5_CTS__MARK,
+};
+static const unsigned int scifa5_data_2_pins[] = {
+	/* RXD, TXD */
+	162, 160,
+};
+static const unsigned int scifa5_data_2_mux[] = {
+	PORT162_SCIFA5_RXD_MARK, PORT160_SCIFA5_TXD_MARK,
+};
+static const unsigned int scifa5_clk_2_pins[] = {
+	/* SCK */
+	159,
+};
+static const unsigned int scifa5_clk_2_mux[] = {
+	PORT159_SCIFA5_SCK_MARK,
+};
+static const unsigned int scifa5_ctrl_2_pins[] = {
+	/* RTS, CTS */
+	163, 161,
+};
+static const unsigned int scifa5_ctrl_2_mux[] = {
+	PORT163_SCIFA5_RTS__MARK, PORT161_SCIFA5_CTS__MARK,
+};
+/* - SCIFA6 ----------------------------------------------------------------- */
+static const unsigned int scifa6_pins[] = {
+	/* TXD */
+	240,
+};
+static const unsigned int scifa6_mux[] = {
+	SCIFA6_TXD_MARK,
+};
+/* - SCIFA7 ----------------------------------------------------------------- */
+static const unsigned int scifa7_data_pins[] = {
+	/* RXD, TXD */
+	12, 18,
+};
+static const unsigned int scifa7_data_mux[] = {
+	SCIFA7_RXD_MARK, SCIFA7_TXD_MARK,
+};
+static const unsigned int scifa7_ctrl_pins[] = {
+	/* RTS, CTS */
+	19, 13,
+};
+static const unsigned int scifa7_ctrl_mux[] = {
+	SCIFA7_RTS__MARK, SCIFA7_CTS__MARK,
+};
+/* - SCIFB ------------------------------------------------------------------ */
+static const unsigned int scifb_data_0_pins[] = {
+	/* RXD, TXD */
+	162, 160,
+};
+static const unsigned int scifb_data_0_mux[] = {
+	PORT162_SCIFB_RXD_MARK, PORT160_SCIFB_TXD_MARK,
+};
+static const unsigned int scifb_clk_0_pins[] = {
+	/* SCK */
+	159,
+};
+static const unsigned int scifb_clk_0_mux[] = {
+	PORT159_SCIFB_SCK_MARK,
+};
+static const unsigned int scifb_ctrl_0_pins[] = {
+	/* RTS, CTS */
+	163, 161,
+};
+static const unsigned int scifb_ctrl_0_mux[] = {
+	PORT163_SCIFB_RTS__MARK, PORT161_SCIFB_CTS__MARK,
+};
+static const unsigned int scifb_data_1_pins[] = {
+	/* RXD, TXD */
+	246, 247,
+};
+static const unsigned int scifb_data_1_mux[] = {
+	PORT246_SCIFB_RXD_MARK, PORT247_SCIFB_TXD_MARK,
+};
+static const unsigned int scifb_clk_1_pins[] = {
+	/* SCK */
+	248,
+};
+static const unsigned int scifb_clk_1_mux[] = {
+	PORT248_SCIFB_SCK_MARK,
+};
+static const unsigned int scifb_ctrl_1_pins[] = {
+	/* RTS, CTS */
+	245, 244,
+};
+static const unsigned int scifb_ctrl_1_mux[] = {
+	PORT245_SCIFB_RTS__MARK, PORT244_SCIFB_CTS__MARK,
+};
+/* - SDHI0 ------------------------------------------------------------------ */
+static const unsigned int sdhi0_data1_pins[] = {
+	/* D0 */
+	252,
+};
+static const unsigned int sdhi0_data1_mux[] = {
+	SDHID0_0_MARK,
+};
+static const unsigned int sdhi0_data4_pins[] = {
+	/* D[0:3] */
+	252, 253, 254, 255,
+};
+static const unsigned int sdhi0_data4_mux[] = {
+	SDHID0_0_MARK, SDHID0_1_MARK, SDHID0_2_MARK, SDHID0_3_MARK,
+};
+static const unsigned int sdhi0_ctrl_pins[] = {
+	/* CMD, CLK */
+	256, 250,
+};
+static const unsigned int sdhi0_ctrl_mux[] = {
+	SDHICMD0_MARK, SDHICLK0_MARK,
+};
+static const unsigned int sdhi0_cd_pins[] = {
+	/* CD */
+	251,
+};
+static const unsigned int sdhi0_cd_mux[] = {
+	SDHICD0_MARK,
+};
+static const unsigned int sdhi0_wp_pins[] = {
+	/* WP */
+	257,
+};
+static const unsigned int sdhi0_wp_mux[] = {
+	SDHIWP0_MARK,
+};
+/* - SDHI1 ------------------------------------------------------------------ */
+static const unsigned int sdhi1_data1_pins[] = {
+	/* D0 */
+	259,
+};
+static const unsigned int sdhi1_data1_mux[] = {
+	SDHID1_0_MARK,
+};
+static const unsigned int sdhi1_data4_pins[] = {
+	/* D[0:3] */
+	259, 260, 261, 262,
+};
+static const unsigned int sdhi1_data4_mux[] = {
+	SDHID1_0_MARK, SDHID1_1_MARK, SDHID1_2_MARK, SDHID1_3_MARK,
+};
+static const unsigned int sdhi1_ctrl_pins[] = {
+	/* CMD, CLK */
+	263, 258,
+};
+static const unsigned int sdhi1_ctrl_mux[] = {
+	SDHICMD1_MARK, SDHICLK1_MARK,
+};
+/* - SDHI2 ------------------------------------------------------------------ */
+static const unsigned int sdhi2_data1_pins[] = {
+	/* D0 */
+	265,
+};
+static const unsigned int sdhi2_data1_mux[] = {
+	SDHID2_0_MARK,
+};
+static const unsigned int sdhi2_data4_pins[] = {
+	/* D[0:3] */
+	265, 266, 267, 268,
+};
+static const unsigned int sdhi2_data4_mux[] = {
+	SDHID2_0_MARK, SDHID2_1_MARK, SDHID2_2_MARK, SDHID2_3_MARK,
+};
+static const unsigned int sdhi2_ctrl_pins[] = {
+	/* CMD, CLK */
+	269, 264,
+};
+static const unsigned int sdhi2_ctrl_mux[] = {
+	SDHICMD2_MARK, SDHICLK2_MARK,
+};
+/* - USB -------------------------------------------------------------------- */
+static const unsigned int usb_vbus_pins[] = {
+	/* VBUS */
+	0,
+};
+static const unsigned int usb_vbus_mux[] = {
+	VBUS_0_MARK,
+};
+
+static const struct sh_pfc_pin_group pinmux_groups[] = {
+	SH_PFC_PIN_GROUP(bsc_data_0_7),
+	SH_PFC_PIN_GROUP(bsc_data_8_15),
+	SH_PFC_PIN_GROUP(bsc_cs4),
+	SH_PFC_PIN_GROUP(bsc_cs5_a),
+	SH_PFC_PIN_GROUP(bsc_cs5_b),
+	SH_PFC_PIN_GROUP(bsc_cs6_a),
+	SH_PFC_PIN_GROUP(bsc_cs6_b),
+	SH_PFC_PIN_GROUP(bsc_rd),
+	SH_PFC_PIN_GROUP(bsc_rdwr_0),
+	SH_PFC_PIN_GROUP(bsc_rdwr_1),
+	SH_PFC_PIN_GROUP(bsc_rdwr_2),
+	SH_PFC_PIN_GROUP(bsc_we0),
+	SH_PFC_PIN_GROUP(bsc_we1),
+	SH_PFC_PIN_GROUP(fsia_mclk_in),
+	SH_PFC_PIN_GROUP(fsia_mclk_out),
+	SH_PFC_PIN_GROUP(fsia_sclk_in),
+	SH_PFC_PIN_GROUP(fsia_sclk_out),
+	SH_PFC_PIN_GROUP(fsia_data_in),
+	SH_PFC_PIN_GROUP(fsia_data_out),
+	SH_PFC_PIN_GROUP(fsia_spdif),
+	SH_PFC_PIN_GROUP(fsib_mclk_in),
+	SH_PFC_PIN_GROUP(fsib_mclk_out),
+	SH_PFC_PIN_GROUP(fsib_sclk_in),
+	SH_PFC_PIN_GROUP(fsib_sclk_out),
+	SH_PFC_PIN_GROUP(fsib_data_in),
+	SH_PFC_PIN_GROUP(fsib_data_out),
+	SH_PFC_PIN_GROUP(fsib_spdif),
+	SH_PFC_PIN_GROUP(fsic_mclk_in),
+	SH_PFC_PIN_GROUP(fsic_mclk_out),
+	SH_PFC_PIN_GROUP(fsic_sclk_in),
+	SH_PFC_PIN_GROUP(fsic_sclk_out),
+	SH_PFC_PIN_GROUP(fsic_data_in),
+	SH_PFC_PIN_GROUP(fsic_data_out),
+	SH_PFC_PIN_GROUP(fsic_spdif_0),
+	SH_PFC_PIN_GROUP(fsic_spdif_1),
+	SH_PFC_PIN_GROUP(fsid_sclk_in),
+	SH_PFC_PIN_GROUP(fsid_sclk_out),
+	SH_PFC_PIN_GROUP(fsid_data_in),
+	SH_PFC_PIN_GROUP(i2c2_0),
+	SH_PFC_PIN_GROUP(i2c2_1),
+	SH_PFC_PIN_GROUP(i2c2_2),
+	SH_PFC_PIN_GROUP(i2c3_0),
+	SH_PFC_PIN_GROUP(i2c3_1),
+	SH_PFC_PIN_GROUP(i2c3_2),
+	SH_PFC_PIN_GROUP(irda_0),
+	SH_PFC_PIN_GROUP(irda_1),
+	SH_PFC_PIN_GROUP(keysc_in5),
+	SH_PFC_PIN_GROUP(keysc_in6),
+	SH_PFC_PIN_GROUP(keysc_in7),
+	SH_PFC_PIN_GROUP(keysc_in8),
+	SH_PFC_PIN_GROUP(keysc_out04),
+	SH_PFC_PIN_GROUP(keysc_out5),
+	SH_PFC_PIN_GROUP(keysc_out6_0),
+	SH_PFC_PIN_GROUP(keysc_out6_1),
+	SH_PFC_PIN_GROUP(keysc_out6_2),
+	SH_PFC_PIN_GROUP(keysc_out7_0),
+	SH_PFC_PIN_GROUP(keysc_out7_1),
+	SH_PFC_PIN_GROUP(keysc_out7_2),
+	SH_PFC_PIN_GROUP(keysc_out8_0),
+	SH_PFC_PIN_GROUP(keysc_out8_1),
+	SH_PFC_PIN_GROUP(keysc_out8_2),
+	SH_PFC_PIN_GROUP(keysc_out9_0),
+	SH_PFC_PIN_GROUP(keysc_out9_1),
+	SH_PFC_PIN_GROUP(keysc_out9_2),
+	SH_PFC_PIN_GROUP(keysc_out10_0),
+	SH_PFC_PIN_GROUP(keysc_out10_1),
+	SH_PFC_PIN_GROUP(keysc_out11_0),
+	SH_PFC_PIN_GROUP(keysc_out11_1),
+	SH_PFC_PIN_GROUP(lcd_data8),
+	SH_PFC_PIN_GROUP(lcd_data9),
+	SH_PFC_PIN_GROUP(lcd_data12),
+	SH_PFC_PIN_GROUP(lcd_data16),
+	SH_PFC_PIN_GROUP(lcd_data18),
+	SH_PFC_PIN_GROUP(lcd_data24),
+	SH_PFC_PIN_GROUP(lcd_display),
+	SH_PFC_PIN_GROUP(lcd_lclk),
+	SH_PFC_PIN_GROUP(lcd_sync),
+	SH_PFC_PIN_GROUP(lcd_sys),
+	SH_PFC_PIN_GROUP(lcd2_data8),
+	SH_PFC_PIN_GROUP(lcd2_data9),
+	SH_PFC_PIN_GROUP(lcd2_data12),
+	SH_PFC_PIN_GROUP(lcd2_data16),
+	SH_PFC_PIN_GROUP(lcd2_data18),
+	SH_PFC_PIN_GROUP(lcd2_data24),
+	SH_PFC_PIN_GROUP(lcd2_sync_0),
+	SH_PFC_PIN_GROUP(lcd2_sync_1),
+	SH_PFC_PIN_GROUP(lcd2_sys_0),
+	SH_PFC_PIN_GROUP(lcd2_sys_1),
+	SH_PFC_PIN_GROUP(mmc0_data1_0),
+	SH_PFC_PIN_GROUP(mmc0_data4_0),
+	SH_PFC_PIN_GROUP(mmc0_data8_0),
+	SH_PFC_PIN_GROUP(mmc0_ctrl_0),
+	SH_PFC_PIN_GROUP(mmc0_data1_1),
+	SH_PFC_PIN_GROUP(mmc0_data4_1),
+	SH_PFC_PIN_GROUP(mmc0_data8_1),
+	SH_PFC_PIN_GROUP(mmc0_ctrl_1),
+	SH_PFC_PIN_GROUP(scifa0_data),
+	SH_PFC_PIN_GROUP(scifa0_clk),
+	SH_PFC_PIN_GROUP(scifa0_ctrl),
+	SH_PFC_PIN_GROUP(scifa1_data),
+	SH_PFC_PIN_GROUP(scifa1_clk),
+	SH_PFC_PIN_GROUP(scifa1_ctrl),
+	SH_PFC_PIN_GROUP(scifa2_data_0),
+	SH_PFC_PIN_GROUP(scifa2_clk_0),
+	SH_PFC_PIN_GROUP(scifa2_ctrl_0),
+	SH_PFC_PIN_GROUP(scifa2_data_1),
+	SH_PFC_PIN_GROUP(scifa2_clk_1),
+	SH_PFC_PIN_GROUP(scifa2_ctrl_1),
+	SH_PFC_PIN_GROUP(scifa3_data),
+	SH_PFC_PIN_GROUP(scifa3_ctrl),
+	SH_PFC_PIN_GROUP(scifa4_data),
+	SH_PFC_PIN_GROUP(scifa4_ctrl),
+	SH_PFC_PIN_GROUP(scifa5_data_0),
+	SH_PFC_PIN_GROUP(scifa5_clk_0),
+	SH_PFC_PIN_GROUP(scifa5_ctrl_0),
+	SH_PFC_PIN_GROUP(scifa5_data_1),
+	SH_PFC_PIN_GROUP(scifa5_clk_1),
+	SH_PFC_PIN_GROUP(scifa5_ctrl_1),
+	SH_PFC_PIN_GROUP(scifa5_data_2),
+	SH_PFC_PIN_GROUP(scifa5_clk_2),
+	SH_PFC_PIN_GROUP(scifa5_ctrl_2),
+	SH_PFC_PIN_GROUP(scifa6),
+	SH_PFC_PIN_GROUP(scifa7_data),
+	SH_PFC_PIN_GROUP(scifa7_ctrl),
+	SH_PFC_PIN_GROUP(scifb_data_0),
+	SH_PFC_PIN_GROUP(scifb_clk_0),
+	SH_PFC_PIN_GROUP(scifb_ctrl_0),
+	SH_PFC_PIN_GROUP(scifb_data_1),
+	SH_PFC_PIN_GROUP(scifb_clk_1),
+	SH_PFC_PIN_GROUP(scifb_ctrl_1),
+	SH_PFC_PIN_GROUP(sdhi0_data1),
+	SH_PFC_PIN_GROUP(sdhi0_data4),
+	SH_PFC_PIN_GROUP(sdhi0_ctrl),
+	SH_PFC_PIN_GROUP(sdhi0_cd),
+	SH_PFC_PIN_GROUP(sdhi0_wp),
+	SH_PFC_PIN_GROUP(sdhi1_data1),
+	SH_PFC_PIN_GROUP(sdhi1_data4),
+	SH_PFC_PIN_GROUP(sdhi1_ctrl),
+	SH_PFC_PIN_GROUP(sdhi2_data1),
+	SH_PFC_PIN_GROUP(sdhi2_data4),
+	SH_PFC_PIN_GROUP(sdhi2_ctrl),
+	SH_PFC_PIN_GROUP(usb_vbus),
+};
+
+static const char * const bsc_groups[] = {
+	"bsc_data_0_7",
+	"bsc_data_8_15",
+	"bsc_cs4",
+	"bsc_cs5_a",
+	"bsc_cs5_b",
+	"bsc_cs6_a",
+	"bsc_cs6_b",
+	"bsc_rd",
+	"bsc_rdwr_0",
+	"bsc_rdwr_1",
+	"bsc_rdwr_2",
+	"bsc_we0",
+	"bsc_we1",
+};
+
+static const char * const fsia_groups[] = {
+	"fsia_mclk_in",
+	"fsia_mclk_out",
+	"fsia_sclk_in",
+	"fsia_sclk_out",
+	"fsia_data_in",
+	"fsia_data_out",
+	"fsia_spdif",
+};
+
+static const char * const fsib_groups[] = {
+	"fsib_mclk_in",
+	"fsib_mclk_out",
+	"fsib_sclk_in",
+	"fsib_sclk_out",
+	"fsib_data_in",
+	"fsib_data_out",
+	"fsib_spdif",
+};
+
+static const char * const fsic_groups[] = {
+	"fsic_mclk_in",
+	"fsic_mclk_out",
+	"fsic_sclk_in",
+	"fsic_sclk_out",
+	"fsic_data_in",
+	"fsic_data_out",
+	"fsic_spdif",
+};
+
+static const char * const fsid_groups[] = {
+	"fsid_sclk_in",
+	"fsid_sclk_out",
+	"fsid_data_in",
+};
+
+static const char * const i2c2_groups[] = {
+	"i2c2_0",
+	"i2c2_1",
+	"i2c2_2",
+};
+
+static const char * const i2c3_groups[] = {
+	"i2c3_0",
+	"i2c3_1",
+	"i2c3_2",
+};
+
+static const char * const irda_groups[] = {
+	"irda_0",
+	"irda_1",
+};
 
+static const char * const keysc_groups[] = {
+	"keysc_in5",
+	"keysc_in6",
+	"keysc_in7",
+	"keysc_in8",
+	"keysc_out04",
+	"keysc_out5",
+	"keysc_out6_0",
+	"keysc_out6_1",
+	"keysc_out6_2",
+	"keysc_out7_0",
+	"keysc_out7_1",
+	"keysc_out7_2",
+	"keysc_out8_0",
+	"keysc_out8_1",
+	"keysc_out8_2",
+	"keysc_out9_0",
+	"keysc_out9_1",
+	"keysc_out9_2",
+	"keysc_out10_0",
+	"keysc_out10_1",
+	"keysc_out11_0",
+	"keysc_out11_1",
+};
+
+static const char * const lcd_groups[] = {
+	"lcd_data8",
+	"lcd_data9",
+	"lcd_data12",
+	"lcd_data16",
+	"lcd_data18",
+	"lcd_data24",
+	"lcd_display",
+	"lcd_lclk",
+	"lcd_sync",
+	"lcd_sys",
+};
+
+static const char * const lcd2_groups[] = {
+	"lcd2_data8",
+	"lcd2_data9",
+	"lcd2_data12",
+	"lcd2_data16",
+	"lcd2_data18",
+	"lcd2_data24",
+	"lcd2_sync_0",
+	"lcd2_sync_1",
+	"lcd2_sys_0",
+	"lcd2_sys_1",
+};
+
+static const char * const mmc0_groups[] = {
+	"mmc0_data1_0",
+	"mmc0_data4_0",
+	"mmc0_data8_0",
+	"mmc0_ctrl_0",
+	"mmc0_data1_1",
+	"mmc0_data4_1",
+	"mmc0_data8_1",
+	"mmc0_ctrl_1",
+};
+
+static const char * const scifa0_groups[] = {
+	"scifa0_data",
+	"scifa0_clk",
+	"scifa0_ctrl",
+};
+
+static const char * const scifa1_groups[] = {
+	"scifa1_data",
+	"scifa1_clk",
+	"scifa1_ctrl",
+};
+
+static const char * const scifa2_groups[] = {
+	"scifa2_data_0",
+	"scifa2_clk_0",
+	"scifa2_ctrl_0",
+	"scifa2_data_1",
+	"scifa2_clk_1",
+	"scifa2_ctrl_1",
+};
+
+static const char * const scifa3_groups[] = {
+	"scifa3_data",
+	"scifa3_ctrl",
+};
+
+static const char * const scifa4_groups[] = {
+	"scifa4_data",
+	"scifa4_ctrl",
+};
+
+static const char * const scifa5_groups[] = {
+	"scifa5_data_0",
+	"scifa5_clk_0",
+	"scifa5_ctrl_0",
+	"scifa5_data_1",
+	"scifa5_clk_1",
+	"scifa5_ctrl_1",
+	"scifa5_data_2",
+	"scifa5_clk_2",
+	"scifa5_ctrl_2",
+};
+
+static const char * const scifa6_groups[] = {
+	"scifa6",
+};
+
+static const char * const scifa7_groups[] = {
+	"scifa7_data",
+	"scifa7_ctrl",
+};
+
+static const char * const scifb_groups[] = {
+	"scifb_data_0",
+	"scifb_clk_0",
+	"scifb_ctrl_0",
+	"scifb_data_1",
+	"scifb_clk_1",
+	"scifb_ctrl_1",
+};
+
+static const char * const sdhi0_groups[] = {
+	"sdhi0_data1",
+	"sdhi0_data4",
+	"sdhi0_ctrl",
+	"sdhi0_cd",
+	"sdhi0_wp",
+};
+
+static const char * const sdhi1_groups[] = {
+	"sdhi1_data1",
+	"sdhi1_data4",
+	"sdhi1_ctrl",
+};
+
+static const char * const sdhi2_groups[] = {
+	"sdhi2_data1",
+	"sdhi2_data4",
+	"sdhi2_ctrl",
+};
+
+static const char * const usb_groups[] = {
+	"usb_vbus",
+};
+
+static const struct sh_pfc_function pinmux_functions[] = {
+	SH_PFC_FUNCTION(bsc),
+	SH_PFC_FUNCTION(fsia),
+	SH_PFC_FUNCTION(fsib),
+	SH_PFC_FUNCTION(fsic),
+	SH_PFC_FUNCTION(fsid),
+	SH_PFC_FUNCTION(i2c2),
+	SH_PFC_FUNCTION(i2c3),
+	SH_PFC_FUNCTION(irda),
+	SH_PFC_FUNCTION(keysc),
+	SH_PFC_FUNCTION(lcd),
+	SH_PFC_FUNCTION(lcd2),
+	SH_PFC_FUNCTION(mmc0),
+	SH_PFC_FUNCTION(scifa0),
+	SH_PFC_FUNCTION(scifa1),
+	SH_PFC_FUNCTION(scifa2),
+	SH_PFC_FUNCTION(scifa3),
+	SH_PFC_FUNCTION(scifa4),
+	SH_PFC_FUNCTION(scifa5),
+	SH_PFC_FUNCTION(scifa6),
+	SH_PFC_FUNCTION(scifa7),
+	SH_PFC_FUNCTION(scifb),
+	SH_PFC_FUNCTION(sdhi0),
+	SH_PFC_FUNCTION(sdhi1),
+	SH_PFC_FUNCTION(sdhi2),
+	SH_PFC_FUNCTION(usb),
+};
+
+#define PINMUX_FN_BASE	GPIO_FN_GPI0
+
+static const struct pinmux_func pinmux_func_gpios[] = {
 	/* Table 25-1 (Functions 0-7) */
-	GPIO_FN(VBUS_0),
 	GPIO_FN(GPI0),
 	GPIO_FN(GPI1),
 	GPIO_FN(GPI2),
@@ -1556,19 +2948,12 @@ static struct pinmux_gpio pinmux_gpios[] = {
 	GPIO_FN(GPI5),
 	GPIO_FN(GPI6),
 	GPIO_FN(GPI7),
-	GPIO_FN(SCIFA7_RXD),
-	GPIO_FN(SCIFA7_CTS_),
 	GPIO_FN(GPO7), \
 	GPIO_FN(MFG0_OUT2),
 	GPIO_FN(GPO6), \
 	GPIO_FN(MFG1_OUT2),
 	GPIO_FN(GPO5), \
-	GPIO_FN(SCIFA0_SCK), \
-	GPIO_FN(FSICOSLDT3), \
 	GPIO_FN(PORT16_VIO_CKOR),
-	GPIO_FN(SCIFA0_TXD),
-	GPIO_FN(SCIFA7_TXD),
-	GPIO_FN(SCIFA7_RTS_), \
 	GPIO_FN(PORT19_VIO_CKO2),
 	GPIO_FN(GPO0),
 	GPIO_FN(GPO1),
@@ -1581,13 +2966,9 @@ static struct pinmux_gpio pinmux_gpios[] = {
 	GPIO_FN(VINT),
 	GPIO_FN(TCKON),
 	GPIO_FN(XDVFS1), \
-	GPIO_FN(PORT27_I2C_SCL2), \
-	GPIO_FN(PORT27_I2C_SCL3), \
 	GPIO_FN(MFG0_OUT1), \
 	GPIO_FN(PORT27_IROUT),
 	GPIO_FN(XDVFS2), \
-	GPIO_FN(PORT28_I2C_SDA2), \
-	GPIO_FN(PORT28_I2C_SDA3), \
 	GPIO_FN(PORT28_TPU1TO1),
 	GPIO_FN(SIM_RST), \
 	GPIO_FN(PORT29_TPU1TO1),
@@ -1595,140 +2976,53 @@ static struct pinmux_gpio pinmux_gpios[] = {
 	GPIO_FN(PORT30_VIO_CKOR),
 	GPIO_FN(SIM_D), \
 	GPIO_FN(PORT31_IROUT),
-	GPIO_FN(SCIFA4_TXD),
-	GPIO_FN(SCIFA4_RXD), \
 	GPIO_FN(XWUP),
-	GPIO_FN(SCIFA4_RTS_),
-	GPIO_FN(SCIFA4_CTS_),
-	GPIO_FN(FSIBOBT), \
-	GPIO_FN(FSIBIBT),
-	GPIO_FN(FSIBOLR), \
-	GPIO_FN(FSIBILR),
-	GPIO_FN(FSIBOSLD),
-	GPIO_FN(FSIBISLD),
 	GPIO_FN(VACK),
 	GPIO_FN(XTAL1L),
-	GPIO_FN(SCIFA0_RTS_), \
-	GPIO_FN(FSICOSLDT2),
-	GPIO_FN(SCIFA0_RXD),
-	GPIO_FN(SCIFA0_CTS_), \
-	GPIO_FN(FSICOSLDT1),
-	GPIO_FN(FSICOBT), \
-	GPIO_FN(FSICIBT), \
-	GPIO_FN(FSIDOBT), \
-	GPIO_FN(FSIDIBT),
-	GPIO_FN(FSICOLR), \
-	GPIO_FN(FSICILR), \
-	GPIO_FN(FSIDOLR), \
-	GPIO_FN(FSIDILR),
-	GPIO_FN(FSICOSLD), \
-	GPIO_FN(PORT47_FSICSPDIF),
-	GPIO_FN(FSICISLD), \
-	GPIO_FN(FSIDISLD),
-	GPIO_FN(FSIACK), \
-	GPIO_FN(PORT49_IRDA_OUT), \
 	GPIO_FN(PORT49_IROUT), \
-	GPIO_FN(FSIAOMC),
-	GPIO_FN(FSIAOLR), \
 	GPIO_FN(BBIF2_TSYNC2), \
 	GPIO_FN(TPU2TO2), \
-	GPIO_FN(FSIAILR),
 
-	GPIO_FN(FSIAOBT), \
 	GPIO_FN(BBIF2_TSCK2), \
 	GPIO_FN(TPU2TO3), \
-	GPIO_FN(FSIAIBT),
-	GPIO_FN(FSIAOSLD), \
 	GPIO_FN(BBIF2_TXD2),
-	GPIO_FN(FSIASPDIF), \
-	GPIO_FN(PORT53_IRDA_IN), \
 	GPIO_FN(TPU3TO3), \
-	GPIO_FN(FSIBSPDIF), \
-	GPIO_FN(PORT53_FSICSPDIF),
-	GPIO_FN(FSIBCK), \
-	GPIO_FN(PORT54_IRDA_FIRSEL), \
 	GPIO_FN(TPU3TO2), \
-	GPIO_FN(FSIBOMC), \
-	GPIO_FN(FSICCK), \
-	GPIO_FN(FSICOMC),
-	GPIO_FN(FSIAISLD), \
 	GPIO_FN(TPU0TO0),
 	GPIO_FN(A0), \
 	GPIO_FN(BS_),
 	GPIO_FN(A12), \
-	GPIO_FN(PORT58_KEYOUT7), \
 	GPIO_FN(TPU4TO2),
 	GPIO_FN(A13), \
-	GPIO_FN(PORT59_KEYOUT6), \
 	GPIO_FN(TPU0TO1),
 	GPIO_FN(A14), \
-	GPIO_FN(KEYOUT5),
 	GPIO_FN(A15), \
-	GPIO_FN(KEYOUT4),
 	GPIO_FN(A16), \
-	GPIO_FN(KEYOUT3), \
 	GPIO_FN(MSIOF0_SS1),
 	GPIO_FN(A17), \
-	GPIO_FN(KEYOUT2), \
 	GPIO_FN(MSIOF0_TSYNC),
 	GPIO_FN(A18), \
-	GPIO_FN(KEYOUT1), \
 	GPIO_FN(MSIOF0_TSCK),
 	GPIO_FN(A19), \
-	GPIO_FN(KEYOUT0), \
 	GPIO_FN(MSIOF0_TXD),
 	GPIO_FN(A20), \
-	GPIO_FN(KEYIN0), \
 	GPIO_FN(MSIOF0_RSCK),
 	GPIO_FN(A21), \
-	GPIO_FN(KEYIN1), \
 	GPIO_FN(MSIOF0_RSYNC),
 	GPIO_FN(A22), \
-	GPIO_FN(KEYIN2), \
 	GPIO_FN(MSIOF0_MCK0),
 	GPIO_FN(A23), \
-	GPIO_FN(KEYIN3), \
 	GPIO_FN(MSIOF0_MCK1),
 	GPIO_FN(A24), \
-	GPIO_FN(KEYIN4), \
 	GPIO_FN(MSIOF0_RXD),
 	GPIO_FN(A25), \
-	GPIO_FN(KEYIN5), \
 	GPIO_FN(MSIOF0_SS2),
 	GPIO_FN(A26), \
-	GPIO_FN(KEYIN6),
-	GPIO_FN(KEYIN7),
-	GPIO_FN(D0_NAF0),
-	GPIO_FN(D1_NAF1),
-	GPIO_FN(D2_NAF2),
-	GPIO_FN(D3_NAF3),
-	GPIO_FN(D4_NAF4),
-	GPIO_FN(D5_NAF5),
-	GPIO_FN(D6_NAF6),
-	GPIO_FN(D7_NAF7),
-	GPIO_FN(D8_NAF8),
-	GPIO_FN(D9_NAF9),
-	GPIO_FN(D10_NAF10),
-	GPIO_FN(D11_NAF11),
-	GPIO_FN(D12_NAF12),
-	GPIO_FN(D13_NAF13),
-	GPIO_FN(D14_NAF14),
-	GPIO_FN(D15_NAF15),
-	GPIO_FN(CS4_),
-	GPIO_FN(CS5A_), \
-	GPIO_FN(PORT91_RDWR),
-	GPIO_FN(CS5B_), \
 	GPIO_FN(FCE1_),
-	GPIO_FN(CS6B_), \
 	GPIO_FN(DACK0),
 	GPIO_FN(FCE0_), \
-	GPIO_FN(CS6A_),
 	GPIO_FN(WAIT_), \
 	GPIO_FN(DREQ0),
-	GPIO_FN(RD__FSC),
-	GPIO_FN(WE0__FWE), \
-	GPIO_FN(RDWR_FWE),
-	GPIO_FN(WE1_),
 	GPIO_FN(FRB),
 	GPIO_FN(CKO),
 	GPIO_FN(NBRSTOUT_),
@@ -1737,14 +3031,10 @@ static struct pinmux_gpio pinmux_gpios[] = {
 	GPIO_FN(BBIF2_RXD),
 	GPIO_FN(BBIF2_SYNC),
 	GPIO_FN(BBIF2_SCK),
-	GPIO_FN(SCIFA3_CTS_), \
 	GPIO_FN(MFG3_IN2),
-	GPIO_FN(SCIFA3_RXD), \
 	GPIO_FN(MFG3_IN1),
 	GPIO_FN(BBIF1_SS2), \
-	GPIO_FN(SCIFA3_RTS_), \
 	GPIO_FN(MFG3_OUT1),
-	GPIO_FN(SCIFA3_TXD),
 	GPIO_FN(HSI_RX_DATA), \
 	GPIO_FN(BBIF1_RXD),
 	GPIO_FN(HSI_TX_WAKE), \
@@ -1755,103 +3045,57 @@ static struct pinmux_gpio pinmux_gpios[] = {
 	GPIO_FN(BBIF1_TXD),
 	GPIO_FN(HSI_RX_READY), \
 	GPIO_FN(BBIF1_RSCK), \
-	GPIO_FN(PORT115_I2C_SCL2), \
-	GPIO_FN(PORT115_I2C_SCL3),
 	GPIO_FN(HSI_RX_WAKE), \
 	GPIO_FN(BBIF1_RSYNC), \
-	GPIO_FN(PORT116_I2C_SDA2), \
-	GPIO_FN(PORT116_I2C_SDA3),
 	GPIO_FN(HSI_RX_FLAG), \
 	GPIO_FN(BBIF1_SS1), \
 	GPIO_FN(BBIF1_FLOW),
 	GPIO_FN(HSI_TX_FLAG),
 	GPIO_FN(VIO_VD), \
-	GPIO_FN(PORT128_LCD2VSYN), \
 	GPIO_FN(VIO2_VD), \
-	GPIO_FN(LCD2D0),
 
 	GPIO_FN(VIO_HD), \
-	GPIO_FN(PORT129_LCD2HSYN), \
-	GPIO_FN(PORT129_LCD2CS_), \
 	GPIO_FN(VIO2_HD), \
-	GPIO_FN(LCD2D1),
 	GPIO_FN(VIO_D0), \
 	GPIO_FN(PORT130_MSIOF2_RXD), \
-	GPIO_FN(LCD2D10),
 	GPIO_FN(VIO_D1), \
-	GPIO_FN(PORT131_KEYOUT6), \
 	GPIO_FN(PORT131_MSIOF2_SS1), \
-	GPIO_FN(PORT131_KEYOUT11), \
-	GPIO_FN(LCD2D11),
 	GPIO_FN(VIO_D2), \
-	GPIO_FN(PORT132_KEYOUT7), \
 	GPIO_FN(PORT132_MSIOF2_SS2), \
-	GPIO_FN(PORT132_KEYOUT10), \
-	GPIO_FN(LCD2D12),
 	GPIO_FN(VIO_D3), \
 	GPIO_FN(MSIOF2_TSYNC), \
-	GPIO_FN(LCD2D13),
 	GPIO_FN(VIO_D4), \
 	GPIO_FN(MSIOF2_TXD), \
-	GPIO_FN(LCD2D14),
 	GPIO_FN(VIO_D5), \
 	GPIO_FN(MSIOF2_TSCK), \
-	GPIO_FN(LCD2D15),
 	GPIO_FN(VIO_D6), \
-	GPIO_FN(PORT136_KEYOUT8), \
-	GPIO_FN(LCD2D16),
 	GPIO_FN(VIO_D7), \
-	GPIO_FN(PORT137_KEYOUT9), \
-	GPIO_FN(LCD2D17),
 	GPIO_FN(VIO_D8), \
-	GPIO_FN(PORT138_KEYOUT8), \
 	GPIO_FN(VIO2_D0), \
-	GPIO_FN(LCD2D6),
 	GPIO_FN(VIO_D9), \
-	GPIO_FN(PORT139_KEYOUT9), \
 	GPIO_FN(VIO2_D1), \
-	GPIO_FN(LCD2D7),
 	GPIO_FN(VIO_D10), \
 	GPIO_FN(TPU0TO2), \
 	GPIO_FN(VIO2_D2), \
-	GPIO_FN(LCD2D8),
 	GPIO_FN(VIO_D11), \
 	GPIO_FN(TPU0TO3), \
 	GPIO_FN(VIO2_D3), \
-	GPIO_FN(LCD2D9),
 	GPIO_FN(VIO_D12), \
-	GPIO_FN(PORT142_KEYOUT10), \
 	GPIO_FN(VIO2_D4), \
-	GPIO_FN(LCD2D2),
 	GPIO_FN(VIO_D13), \
-	GPIO_FN(PORT143_KEYOUT11), \
-	GPIO_FN(PORT143_KEYOUT6), \
 	GPIO_FN(VIO2_D5), \
-	GPIO_FN(LCD2D3),
 	GPIO_FN(VIO_D14), \
-	GPIO_FN(PORT144_KEYOUT7), \
 	GPIO_FN(VIO2_D6), \
-	GPIO_FN(LCD2D4),
 	GPIO_FN(VIO_D15), \
 	GPIO_FN(TPU1TO3), \
-	GPIO_FN(PORT145_LCD2DISP), \
-	GPIO_FN(PORT145_LCD2RS), \
 	GPIO_FN(VIO2_D7), \
-	GPIO_FN(LCD2D5),
 	GPIO_FN(VIO_CLK), \
-	GPIO_FN(LCD2DCK), \
-	GPIO_FN(PORT146_LCD2WR_), \
 	GPIO_FN(VIO2_CLK), \
-	GPIO_FN(LCD2D18),
 	GPIO_FN(VIO_FIELD), \
-	GPIO_FN(LCD2RD_), \
 	GPIO_FN(VIO2_FIELD), \
-	GPIO_FN(LCD2D19),
 	GPIO_FN(VIO_CKO),
 	GPIO_FN(A27), \
-	GPIO_FN(PORT149_RDWR), \
 	GPIO_FN(MFG0_IN1), \
-	GPIO_FN(PORT149_KEYOUT9),
 	GPIO_FN(MFG0_IN2),
 	GPIO_FN(TS_SPSYNC3), \
 	GPIO_FN(MSIOF2_RSCK),
@@ -1860,201 +3104,105 @@ static struct pinmux_gpio pinmux_gpios[] = {
 	GPIO_FN(TPU1TO2), \
 	GPIO_FN(TS_SDEN3), \
 	GPIO_FN(PORT153_MSIOF2_SS1),
-	GPIO_FN(SCIFA2_TXD1), \
 	GPIO_FN(MSIOF2_MCK0),
-	GPIO_FN(SCIFA2_RXD1), \
 	GPIO_FN(MSIOF2_MCK1),
-	GPIO_FN(SCIFA2_RTS1_), \
 	GPIO_FN(PORT156_MSIOF2_SS2),
-	GPIO_FN(SCIFA2_CTS1_), \
 	GPIO_FN(PORT157_MSIOF2_RXD),
 	GPIO_FN(DINT_), \
-	GPIO_FN(SCIFA2_SCK1), \
 	GPIO_FN(TS_SCK3),
-	GPIO_FN(PORT159_SCIFB_SCK), \
-	GPIO_FN(PORT159_SCIFA5_SCK), \
 	GPIO_FN(NMI),
-	GPIO_FN(PORT160_SCIFB_TXD), \
-	GPIO_FN(PORT160_SCIFA5_TXD),
-	GPIO_FN(PORT161_SCIFB_CTS_), \
-	GPIO_FN(PORT161_SCIFA5_CTS_),
-	GPIO_FN(PORT162_SCIFB_RXD), \
-	GPIO_FN(PORT162_SCIFA5_RXD),
-	GPIO_FN(PORT163_SCIFB_RTS_), \
-	GPIO_FN(PORT163_SCIFA5_RTS_), \
 	GPIO_FN(TPU3TO0),
-	GPIO_FN(LCDD0),
-	GPIO_FN(LCDD1), \
-	GPIO_FN(PORT193_SCIFA5_CTS_), \
 	GPIO_FN(BBIF2_TSYNC1),
-	GPIO_FN(LCDD2), \
-	GPIO_FN(PORT194_SCIFA5_RTS_), \
 	GPIO_FN(BBIF2_TSCK1),
-	GPIO_FN(LCDD3), \
-	GPIO_FN(PORT195_SCIFA5_RXD), \
 	GPIO_FN(BBIF2_TXD1),
-	GPIO_FN(LCDD4), \
-	GPIO_FN(PORT196_SCIFA5_TXD),
-	GPIO_FN(LCDD5), \
-	GPIO_FN(PORT197_SCIFA5_SCK), \
 	GPIO_FN(MFG2_OUT2), \
 	GPIO_FN(TPU2TO1),
-	GPIO_FN(LCDD6),
-	GPIO_FN(LCDD7), \
 	GPIO_FN(TPU4TO1), \
 	GPIO_FN(MFG4_OUT2),
-	GPIO_FN(LCDD8), \
 	GPIO_FN(D16),
-	GPIO_FN(LCDD9), \
 	GPIO_FN(D17),
-	GPIO_FN(LCDD10), \
 	GPIO_FN(D18),
-	GPIO_FN(LCDD11), \
 	GPIO_FN(D19),
-	GPIO_FN(LCDD12), \
 	GPIO_FN(D20),
-	GPIO_FN(LCDD13), \
 	GPIO_FN(D21),
-	GPIO_FN(LCDD14), \
 	GPIO_FN(D22),
-	GPIO_FN(LCDD15), \
 	GPIO_FN(PORT207_MSIOF0L_SS1), \
 	GPIO_FN(D23),
-	GPIO_FN(LCDD16), \
 	GPIO_FN(PORT208_MSIOF0L_SS2), \
 	GPIO_FN(D24),
-	GPIO_FN(LCDD17), \
 	GPIO_FN(D25),
-	GPIO_FN(LCDD18), \
 	GPIO_FN(DREQ2), \
 	GPIO_FN(PORT210_MSIOF0L_SS1), \
 	GPIO_FN(D26),
-	GPIO_FN(LCDD19), \
 	GPIO_FN(PORT211_MSIOF0L_SS2), \
 	GPIO_FN(D27),
-	GPIO_FN(LCDD20), \
 	GPIO_FN(TS_SPSYNC1), \
 	GPIO_FN(MSIOF0L_MCK0), \
 	GPIO_FN(D28),
-	GPIO_FN(LCDD21), \
 	GPIO_FN(TS_SDAT1), \
 	GPIO_FN(MSIOF0L_MCK1), \
 	GPIO_FN(D29),
-	GPIO_FN(LCDD22), \
 	GPIO_FN(TS_SDEN1), \
 	GPIO_FN(MSIOF0L_RSCK), \
 	GPIO_FN(D30),
-	GPIO_FN(LCDD23), \
 	GPIO_FN(TS_SCK1), \
 	GPIO_FN(MSIOF0L_RSYNC), \
 	GPIO_FN(D31),
-	GPIO_FN(LCDDCK), \
-	GPIO_FN(LCDWR_),
-	GPIO_FN(LCDRD_), \
 	GPIO_FN(DACK2), \
-	GPIO_FN(PORT217_LCD2RS), \
 	GPIO_FN(MSIOF0L_TSYNC), \
 	GPIO_FN(VIO2_FIELD3), \
-	GPIO_FN(PORT217_LCD2DISP),
-	GPIO_FN(LCDHSYN), \
-	GPIO_FN(LCDCS_), \
-	GPIO_FN(LCDCS2_), \
 	GPIO_FN(DACK3), \
 	GPIO_FN(PORT218_VIO_CKOR),
-	GPIO_FN(LCDDISP), \
-	GPIO_FN(LCDRS), \
-	GPIO_FN(PORT219_LCD2WR_), \
 	GPIO_FN(DREQ3), \
 	GPIO_FN(MSIOF0L_TSCK), \
 	GPIO_FN(VIO2_CLK3), \
-	GPIO_FN(LCD2DCK_2),
-	GPIO_FN(LCDVSYN), \
-	GPIO_FN(LCDVSYN2),
-	GPIO_FN(LCDLCLK), \
 	GPIO_FN(DREQ1), \
-	GPIO_FN(PORT221_LCD2CS_), \
 	GPIO_FN(PWEN), \
 	GPIO_FN(MSIOF0L_RXD), \
 	GPIO_FN(VIO2_HD3), \
-	GPIO_FN(PORT221_LCD2HSYN),
-	GPIO_FN(LCDDON), \
-	GPIO_FN(LCDDON2), \
 	GPIO_FN(DACK1), \
 	GPIO_FN(OVCN), \
 	GPIO_FN(MSIOF0L_TXD), \
 	GPIO_FN(VIO2_VD3), \
-	GPIO_FN(PORT222_LCD2VSYN),
 
-	GPIO_FN(SCIFA1_TXD), \
 	GPIO_FN(OVCN2),
 	GPIO_FN(EXTLP), \
-	GPIO_FN(SCIFA1_SCK), \
 	GPIO_FN(PORT226_VIO_CKO2),
-	GPIO_FN(SCIFA1_RTS_), \
 	GPIO_FN(IDIN),
-	GPIO_FN(SCIFA1_RXD),
-	GPIO_FN(SCIFA1_CTS_), \
 	GPIO_FN(MFG1_IN1),
 	GPIO_FN(MSIOF1_TXD), \
-	GPIO_FN(SCIFA2_TXD2),
 	GPIO_FN(MSIOF1_TSYNC), \
-	GPIO_FN(SCIFA2_CTS2_),
 	GPIO_FN(MSIOF1_TSCK), \
-	GPIO_FN(SCIFA2_SCK2),
 	GPIO_FN(MSIOF1_RXD), \
-	GPIO_FN(SCIFA2_RXD2),
 	GPIO_FN(MSIOF1_RSCK), \
-	GPIO_FN(SCIFA2_RTS2_), \
 	GPIO_FN(VIO2_CLK2), \
-	GPIO_FN(LCD2D20),
 	GPIO_FN(MSIOF1_RSYNC), \
 	GPIO_FN(MFG1_IN2), \
 	GPIO_FN(VIO2_VD2), \
-	GPIO_FN(LCD2D21),
 	GPIO_FN(MSIOF1_MCK0), \
-	GPIO_FN(PORT236_I2C_SDA2),
 	GPIO_FN(MSIOF1_MCK1), \
-	GPIO_FN(PORT237_I2C_SCL2),
 	GPIO_FN(MSIOF1_SS1), \
 	GPIO_FN(VIO2_FIELD2), \
-	GPIO_FN(LCD2D22),
 	GPIO_FN(MSIOF1_SS2), \
 	GPIO_FN(VIO2_HD2), \
-	GPIO_FN(LCD2D23),
-	GPIO_FN(SCIFA6_TXD),
-	GPIO_FN(PORT241_IRDA_OUT), \
 	GPIO_FN(PORT241_IROUT), \
 	GPIO_FN(MFG4_OUT1), \
 	GPIO_FN(TPU4TO0),
-	GPIO_FN(PORT242_IRDA_IN), \
 	GPIO_FN(MFG4_IN2),
-	GPIO_FN(PORT243_IRDA_FIRSEL), \
 	GPIO_FN(PORT243_VIO_CKO2),
-	GPIO_FN(PORT244_SCIFA5_CTS_), \
 	GPIO_FN(MFG2_IN1), \
-	GPIO_FN(PORT244_SCIFB_CTS_), \
 	GPIO_FN(MSIOF2R_RXD),
-	GPIO_FN(PORT245_SCIFA5_RTS_), \
 	GPIO_FN(MFG2_IN2), \
-	GPIO_FN(PORT245_SCIFB_RTS_), \
 	GPIO_FN(MSIOF2R_TXD),
-	GPIO_FN(PORT246_SCIFA5_RXD), \
 	GPIO_FN(MFG1_OUT1), \
-	GPIO_FN(PORT246_SCIFB_RXD), \
 	GPIO_FN(TPU1TO0),
-	GPIO_FN(PORT247_SCIFA5_TXD), \
 	GPIO_FN(MFG3_OUT2), \
-	GPIO_FN(PORT247_SCIFB_TXD), \
 	GPIO_FN(TPU3TO1),
-	GPIO_FN(PORT248_SCIFA5_SCK), \
 	GPIO_FN(MFG2_OUT1), \
-	GPIO_FN(PORT248_SCIFB_SCK), \
 	GPIO_FN(TPU2TO0), \
-	GPIO_FN(PORT248_I2C_SCL3), \
 	GPIO_FN(MSIOF2R_TSCK),
 	GPIO_FN(PORT249_IROUT), \
 	GPIO_FN(MFG4_IN1), \
-	GPIO_FN(PORT249_I2C_SDA3), \
 	GPIO_FN(MSIOF2R_TSYNC),
 	GPIO_FN(SDHICLK0),
 	GPIO_FN(SDHICD0),
@@ -2172,56 +3320,24 @@ static struct pinmux_gpio pinmux_gpios[] = {
 	GPIO_FN(IRQ9_MEM_INT),
 	GPIO_FN(IRQ9_MCP_INT),
 	GPIO_FN(A11),
-	GPIO_FN(KEYOUT8),
 	GPIO_FN(TPU4TO3),
 	GPIO_FN(RESETA_N_PU_ON),
 	GPIO_FN(RESETA_N_PU_OFF),
 	GPIO_FN(EDBGREQ_PD),
 	GPIO_FN(EDBGREQ_PU),
+};
 
-	/* Functions with pull-ups */
-	GPIO_FN(KEYIN0_PU),
-	GPIO_FN(KEYIN1_PU),
-	GPIO_FN(KEYIN2_PU),
-	GPIO_FN(KEYIN3_PU),
-	GPIO_FN(KEYIN4_PU),
-	GPIO_FN(KEYIN5_PU),
-	GPIO_FN(KEYIN6_PU),
-	GPIO_FN(KEYIN7_PU),
-	GPIO_FN(SDHICD0_PU),
-	GPIO_FN(SDHID0_0_PU),
-	GPIO_FN(SDHID0_1_PU),
-	GPIO_FN(SDHID0_2_PU),
-	GPIO_FN(SDHID0_3_PU),
-	GPIO_FN(SDHICMD0_PU),
-	GPIO_FN(SDHIWP0_PU),
-	GPIO_FN(SDHID1_0_PU),
-	GPIO_FN(SDHID1_1_PU),
-	GPIO_FN(SDHID1_2_PU),
-	GPIO_FN(SDHID1_3_PU),
-	GPIO_FN(SDHICMD1_PU),
-	GPIO_FN(SDHID2_0_PU),
-	GPIO_FN(SDHID2_1_PU),
-	GPIO_FN(SDHID2_2_PU),
-	GPIO_FN(SDHID2_3_PU),
-	GPIO_FN(SDHICMD2_PU),
-	GPIO_FN(MMCCMD0_PU),
-	GPIO_FN(MMCCMD1_PU),
-	GPIO_FN(MMCD0_0_PU),
-	GPIO_FN(MMCD0_1_PU),
-	GPIO_FN(MMCD0_2_PU),
-	GPIO_FN(MMCD0_3_PU),
-	GPIO_FN(MMCD0_4_PU),
-	GPIO_FN(MMCD0_5_PU),
-	GPIO_FN(MMCD0_6_PU),
-	GPIO_FN(MMCD0_7_PU),
-	GPIO_FN(FSIACK_PU),
-	GPIO_FN(FSIAILR_PU),
-	GPIO_FN(FSIAIBT_PU),
-	GPIO_FN(FSIAISLD_PU),
-};
-
-static struct pinmux_cfg_reg pinmux_config_regs[] = {
+#undef PORTCR
+#define PORTCR(nr, reg)							\
+	{								\
+		PINMUX_CFG_REG("PORT" nr "CR", reg, 8, 4) {		\
+			_PCRH(PORT##nr##_IN, 0, 0, PORT##nr##_OUT),	\
+				PORT##nr##_FN0, PORT##nr##_FN1,		\
+				PORT##nr##_FN2, PORT##nr##_FN3,		\
+				PORT##nr##_FN4, PORT##nr##_FN5,		\
+				PORT##nr##_FN6, PORT##nr##_FN7 }	\
+	}
+static const struct pinmux_cfg_reg pinmux_config_regs[] = {
 	PORTCR(0, 0xe6050000), /* PORT0CR */
 	PORTCR(1, 0xe6050001), /* PORT1CR */
 	PORTCR(2, 0xe6050002), /* PORT2CR */
@@ -2629,7 +3745,7 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = {
 	{ },
 };
 
-static struct pinmux_data_reg pinmux_data_regs[] = {
+static const struct pinmux_data_reg pinmux_data_regs[] = {
 	{ PINMUX_DATA_REG("PORTL031_000DR", 0xe6054000, 32) {
 			PORT31_DATA, PORT30_DATA, PORT29_DATA, PORT28_DATA,
 			PORT27_DATA, PORT26_DATA, PORT25_DATA, PORT24_DATA,
@@ -2733,60 +3849,116 @@ static struct pinmux_data_reg pinmux_data_regs[] = {
 	{ },
 };
 
-/* IRQ pins through INTCS with IRQ0->15 from 0x200 and IRQ16-31 from 0x3200 */
-#define EXT_IRQ16L(n) intcs_evt2irq(0x200 + ((n) << 5))
-#define EXT_IRQ16H(n) intcs_evt2irq(0x3200 + ((n - 16) << 5))
-
-static struct pinmux_irq pinmux_irqs[] = {
-	PINMUX_IRQ(EXT_IRQ16H(19), PORT9_FN0),
-	PINMUX_IRQ(EXT_IRQ16L(1), PORT10_FN0),
-	PINMUX_IRQ(EXT_IRQ16L(0), PORT11_FN0),
-	PINMUX_IRQ(EXT_IRQ16H(18), PORT13_FN0),
-	PINMUX_IRQ(EXT_IRQ16H(20), PORT14_FN0),
-	PINMUX_IRQ(EXT_IRQ16H(21), PORT15_FN0),
-	PINMUX_IRQ(EXT_IRQ16H(31), PORT26_FN0),
-	PINMUX_IRQ(EXT_IRQ16H(30), PORT27_FN0),
-	PINMUX_IRQ(EXT_IRQ16H(29), PORT28_FN0),
-	PINMUX_IRQ(EXT_IRQ16H(22), PORT40_FN0),
-	PINMUX_IRQ(EXT_IRQ16H(23), PORT53_FN0),
-	PINMUX_IRQ(EXT_IRQ16L(10), PORT54_FN0),
-	PINMUX_IRQ(EXT_IRQ16L(9), PORT56_FN0),
-	PINMUX_IRQ(EXT_IRQ16H(26), PORT115_FN0),
-	PINMUX_IRQ(EXT_IRQ16H(27), PORT116_FN0),
-	PINMUX_IRQ(EXT_IRQ16H(28), PORT117_FN0),
-	PINMUX_IRQ(EXT_IRQ16H(24), PORT118_FN0),
-	PINMUX_IRQ(EXT_IRQ16L(6), PORT147_FN0),
-	PINMUX_IRQ(EXT_IRQ16L(2), PORT149_FN0),
-	PINMUX_IRQ(EXT_IRQ16L(7), PORT150_FN0),
-	PINMUX_IRQ(EXT_IRQ16L(12), PORT156_FN0),
-	PINMUX_IRQ(EXT_IRQ16L(4), PORT159_FN0),
-	PINMUX_IRQ(EXT_IRQ16H(25), PORT164_FN0),
-	PINMUX_IRQ(EXT_IRQ16L(8), PORT223_FN0),
-	PINMUX_IRQ(EXT_IRQ16L(3), PORT224_FN0),
-	PINMUX_IRQ(EXT_IRQ16L(5), PORT227_FN0),
-	PINMUX_IRQ(EXT_IRQ16H(17), PORT234_FN0),
-	PINMUX_IRQ(EXT_IRQ16L(11), PORT238_FN0),
-	PINMUX_IRQ(EXT_IRQ16L(13), PORT239_FN0),
-	PINMUX_IRQ(EXT_IRQ16H(16), PORT249_FN0),
-	PINMUX_IRQ(EXT_IRQ16L(14), PORT251_FN0),
-	PINMUX_IRQ(EXT_IRQ16L(9), PORT308_FN0),
-};
-
-struct sh_pfc_soc_info sh73a0_pinmux_info = {
+/* External IRQ pins mapped at IRQPIN_BASE */
+#define EXT_IRQ16L(n) irq_pin(n)
+#define EXT_IRQ16H(n) irq_pin(n)
+
+static const struct pinmux_irq pinmux_irqs[] = {
+	PINMUX_IRQ(EXT_IRQ16H(19), 9),
+	PINMUX_IRQ(EXT_IRQ16L(1), 10),
+	PINMUX_IRQ(EXT_IRQ16L(0), 11),
+	PINMUX_IRQ(EXT_IRQ16H(18), 13),
+	PINMUX_IRQ(EXT_IRQ16H(20), 14),
+	PINMUX_IRQ(EXT_IRQ16H(21), 15),
+	PINMUX_IRQ(EXT_IRQ16H(31), 26),
+	PINMUX_IRQ(EXT_IRQ16H(30), 27),
+	PINMUX_IRQ(EXT_IRQ16H(29), 28),
+	PINMUX_IRQ(EXT_IRQ16H(22), 40),
+	PINMUX_IRQ(EXT_IRQ16H(23), 53),
+	PINMUX_IRQ(EXT_IRQ16L(10), 54),
+	PINMUX_IRQ(EXT_IRQ16L(9), 56),
+	PINMUX_IRQ(EXT_IRQ16H(26), 115),
+	PINMUX_IRQ(EXT_IRQ16H(27), 116),
+	PINMUX_IRQ(EXT_IRQ16H(28), 117),
+	PINMUX_IRQ(EXT_IRQ16H(24), 118),
+	PINMUX_IRQ(EXT_IRQ16L(6), 147),
+	PINMUX_IRQ(EXT_IRQ16L(2), 149),
+	PINMUX_IRQ(EXT_IRQ16L(7), 150),
+	PINMUX_IRQ(EXT_IRQ16L(12), 156),
+	PINMUX_IRQ(EXT_IRQ16L(4), 159),
+	PINMUX_IRQ(EXT_IRQ16H(25), 164),
+	PINMUX_IRQ(EXT_IRQ16L(8), 223),
+	PINMUX_IRQ(EXT_IRQ16L(3), 224),
+	PINMUX_IRQ(EXT_IRQ16L(5), 227),
+	PINMUX_IRQ(EXT_IRQ16H(17), 234),
+	PINMUX_IRQ(EXT_IRQ16L(11), 238),
+	PINMUX_IRQ(EXT_IRQ16L(13), 239),
+	PINMUX_IRQ(EXT_IRQ16H(16), 249),
+	PINMUX_IRQ(EXT_IRQ16L(14), 251),
+	PINMUX_IRQ(EXT_IRQ16L(9), 308),
+};
+
+#define PORTnCR_PULMD_OFF	(0 << 6)
+#define PORTnCR_PULMD_DOWN	(2 << 6)
+#define PORTnCR_PULMD_UP	(3 << 6)
+#define PORTnCR_PULMD_MASK	(3 << 6)
+
+static const unsigned int sh73a0_portcr_offsets[] = {
+	0x00000000, 0x00001000, 0x00001000, 0x00002000, 0x00002000,
+	0x00002000, 0x00002000, 0x00003000, 0x00003000, 0x00002000,
+};
+
+static unsigned int sh73a0_pinmux_get_bias(struct sh_pfc *pfc, unsigned int pin)
+{
+	void __iomem *addr = pfc->window->virt
+			   + sh73a0_portcr_offsets[pin >> 5] + pin;
+	u32 value = ioread8(addr) & PORTnCR_PULMD_MASK;
+
+	switch (value) {
+	case PORTnCR_PULMD_UP:
+		return PIN_CONFIG_BIAS_PULL_UP;
+	case PORTnCR_PULMD_DOWN:
+		return PIN_CONFIG_BIAS_PULL_DOWN;
+	case PORTnCR_PULMD_OFF:
+	default:
+		return PIN_CONFIG_BIAS_DISABLE;
+	}
+}
+
+static void sh73a0_pinmux_set_bias(struct sh_pfc *pfc, unsigned int pin,
+				   unsigned int bias)
+{
+	void __iomem *addr = pfc->window->virt
+			   + sh73a0_portcr_offsets[pin >> 5] + pin;
+	u32 value = ioread8(addr) & ~PORTnCR_PULMD_MASK;
+
+	switch (bias) {
+	case PIN_CONFIG_BIAS_PULL_UP:
+		value |= PORTnCR_PULMD_UP;
+		break;
+	case PIN_CONFIG_BIAS_PULL_DOWN:
+		value |= PORTnCR_PULMD_DOWN;
+		break;
+	}
+
+	iowrite8(value, addr);
+}
+
+static const struct sh_pfc_soc_operations sh73a0_pinmux_ops = {
+	.get_bias = sh73a0_pinmux_get_bias,
+	.set_bias = sh73a0_pinmux_set_bias,
+};
+
+const struct sh_pfc_soc_info sh73a0_pinmux_info = {
 	.name = "sh73a0_pfc",
-	.reserved_id = PINMUX_RESERVED,
-	.data = { PINMUX_DATA_BEGIN, PINMUX_DATA_END },
+	.ops = &sh73a0_pinmux_ops,
+
 	.input = { PINMUX_INPUT_BEGIN, PINMUX_INPUT_END },
-	.input_pu = { PINMUX_INPUT_PULLUP_BEGIN, PINMUX_INPUT_PULLUP_END },
-	.input_pd = { PINMUX_INPUT_PULLDOWN_BEGIN, PINMUX_INPUT_PULLDOWN_END },
 	.output = { PINMUX_OUTPUT_BEGIN, PINMUX_OUTPUT_END },
-	.mark = { PINMUX_MARK_BEGIN, PINMUX_MARK_END },
 	.function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END },
 
-	.first_gpio = GPIO_PORT0,
-	.last_gpio = GPIO_FN_FSIAISLD_PU,
+	.pins = pinmux_pins,
+	.nr_pins = ARRAY_SIZE(pinmux_pins),
+	.ranges = pinmux_ranges,
+	.nr_ranges = ARRAY_SIZE(pinmux_ranges),
+	.groups = pinmux_groups,
+	.nr_groups = ARRAY_SIZE(pinmux_groups),
+	.functions = pinmux_functions,
+	.nr_functions = ARRAY_SIZE(pinmux_functions),
+
+	.func_gpios = pinmux_func_gpios,
+	.nr_func_gpios = ARRAY_SIZE(pinmux_func_gpios),
 
-	.gpios = pinmux_gpios,
 	.cfg_regs = pinmux_config_regs,
 	.data_regs = pinmux_data_regs,
 
diff --git a/drivers/pinctrl/sh-pfc/pfc-sh7720.c b/drivers/pinctrl/sh-pfc/pfc-sh7720.c
index 10872ed..52e9f6b 100644
--- a/drivers/pinctrl/sh-pfc/pfc-sh7720.c
+++ b/drivers/pinctrl/sh-pfc/pfc-sh7720.c
@@ -262,7 +262,7 @@ enum {
 	PINMUX_MARK_END,
 };
 
-static pinmux_enum_t pinmux_data[] = {
+static const pinmux_enum_t pinmux_data[] = {
 	/* PTA GPIO */
 	PINMUX_DATA(PTA7_DATA, PTA7_IN, PTA7_OUT, PTA7_IN_PU),
 	PINMUX_DATA(PTA6_DATA, PTA6_IN, PTA6_OUT, PTA6_IN_PU),
@@ -606,7 +606,7 @@ static pinmux_enum_t pinmux_data[] = {
 	PINMUX_DATA(SIM_CLK_MARK, PSELD_1_0_10, PTV0_FN),
 };
 
-static struct pinmux_gpio pinmux_gpios[] = {
+static struct sh_pfc_pin pinmux_pins[] = {
 	/* PTA */
 	PINMUX_GPIO(GPIO_PTA7, PTA7_DATA),
 	PINMUX_GPIO(GPIO_PTA6, PTA6_DATA),
@@ -759,202 +759,205 @@ static struct pinmux_gpio pinmux_gpios[] = {
 	PINMUX_GPIO(GPIO_PTV2, PTV2_DATA),
 	PINMUX_GPIO(GPIO_PTV1, PTV1_DATA),
 	PINMUX_GPIO(GPIO_PTV0, PTV0_DATA),
+};
+
+#define PINMUX_FN_BASE	ARRAY_SIZE(pinmux_pins)
 
+static const struct pinmux_func pinmux_func_gpios[] = {
 	/* BSC */
-	PINMUX_GPIO(GPIO_FN_D31, D31_MARK),
-	PINMUX_GPIO(GPIO_FN_D30, D30_MARK),
-	PINMUX_GPIO(GPIO_FN_D29, D29_MARK),
-	PINMUX_GPIO(GPIO_FN_D28, D28_MARK),
-	PINMUX_GPIO(GPIO_FN_D27, D27_MARK),
-	PINMUX_GPIO(GPIO_FN_D26, D26_MARK),
-	PINMUX_GPIO(GPIO_FN_D25, D25_MARK),
-	PINMUX_GPIO(GPIO_FN_D24, D24_MARK),
-	PINMUX_GPIO(GPIO_FN_D23, D23_MARK),
-	PINMUX_GPIO(GPIO_FN_D22, D22_MARK),
-	PINMUX_GPIO(GPIO_FN_D21, D21_MARK),
-	PINMUX_GPIO(GPIO_FN_D20, D20_MARK),
-	PINMUX_GPIO(GPIO_FN_D19, D19_MARK),
-	PINMUX_GPIO(GPIO_FN_D18, D18_MARK),
-	PINMUX_GPIO(GPIO_FN_D17, D17_MARK),
-	PINMUX_GPIO(GPIO_FN_D16, D16_MARK),
-	PINMUX_GPIO(GPIO_FN_IOIS16, IOIS16_MARK),
-	PINMUX_GPIO(GPIO_FN_RAS, RAS_MARK),
-	PINMUX_GPIO(GPIO_FN_CAS, CAS_MARK),
-	PINMUX_GPIO(GPIO_FN_CKE, CKE_MARK),
-	PINMUX_GPIO(GPIO_FN_CS5B_CE1A, CS5B_CE1A_MARK),
-	PINMUX_GPIO(GPIO_FN_CS6B_CE1B, CS6B_CE1B_MARK),
-	PINMUX_GPIO(GPIO_FN_A25, A25_MARK),
-	PINMUX_GPIO(GPIO_FN_A24, A24_MARK),
-	PINMUX_GPIO(GPIO_FN_A23, A23_MARK),
-	PINMUX_GPIO(GPIO_FN_A22, A22_MARK),
-	PINMUX_GPIO(GPIO_FN_A21, A21_MARK),
-	PINMUX_GPIO(GPIO_FN_A20, A20_MARK),
-	PINMUX_GPIO(GPIO_FN_A19, A19_MARK),
-	PINMUX_GPIO(GPIO_FN_A0, A0_MARK),
-	PINMUX_GPIO(GPIO_FN_REFOUT, REFOUT_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQOUT, IRQOUT_MARK),
+	GPIO_FN(D31),
+	GPIO_FN(D30),
+	GPIO_FN(D29),
+	GPIO_FN(D28),
+	GPIO_FN(D27),
+	GPIO_FN(D26),
+	GPIO_FN(D25),
+	GPIO_FN(D24),
+	GPIO_FN(D23),
+	GPIO_FN(D22),
+	GPIO_FN(D21),
+	GPIO_FN(D20),
+	GPIO_FN(D19),
+	GPIO_FN(D18),
+	GPIO_FN(D17),
+	GPIO_FN(D16),
+	GPIO_FN(IOIS16),
+	GPIO_FN(RAS),
+	GPIO_FN(CAS),
+	GPIO_FN(CKE),
+	GPIO_FN(CS5B_CE1A),
+	GPIO_FN(CS6B_CE1B),
+	GPIO_FN(A25),
+	GPIO_FN(A24),
+	GPIO_FN(A23),
+	GPIO_FN(A22),
+	GPIO_FN(A21),
+	GPIO_FN(A20),
+	GPIO_FN(A19),
+	GPIO_FN(A0),
+	GPIO_FN(REFOUT),
+	GPIO_FN(IRQOUT),
 
 	/* LCDC */
-	PINMUX_GPIO(GPIO_FN_LCD_DATA15, LCD_DATA15_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA14, LCD_DATA14_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA13, LCD_DATA13_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA12, LCD_DATA12_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA11, LCD_DATA11_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA10, LCD_DATA10_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA9, LCD_DATA9_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA8, LCD_DATA8_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA7, LCD_DATA7_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA6, LCD_DATA6_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA5, LCD_DATA5_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA4, LCD_DATA4_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA3, LCD_DATA3_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA2, LCD_DATA2_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA1, LCD_DATA1_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DATA0, LCD_DATA0_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_M_DISP, LCD_M_DISP_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_CL1, LCD_CL1_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_CL2, LCD_CL2_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_DON, LCD_DON_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_FLM, LCD_FLM_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_VEPWC, LCD_VEPWC_MARK),
-	PINMUX_GPIO(GPIO_FN_LCD_VCPWC, LCD_VCPWC_MARK),
+	GPIO_FN(LCD_DATA15),
+	GPIO_FN(LCD_DATA14),
+	GPIO_FN(LCD_DATA13),
+	GPIO_FN(LCD_DATA12),
+	GPIO_FN(LCD_DATA11),
+	GPIO_FN(LCD_DATA10),
+	GPIO_FN(LCD_DATA9),
+	GPIO_FN(LCD_DATA8),
+	GPIO_FN(LCD_DATA7),
+	GPIO_FN(LCD_DATA6),
+	GPIO_FN(LCD_DATA5),
+	GPIO_FN(LCD_DATA4),
+	GPIO_FN(LCD_DATA3),
+	GPIO_FN(LCD_DATA2),
+	GPIO_FN(LCD_DATA1),
+	GPIO_FN(LCD_DATA0),
+	GPIO_FN(LCD_M_DISP),
+	GPIO_FN(LCD_CL1),
+	GPIO_FN(LCD_CL2),
+	GPIO_FN(LCD_DON),
+	GPIO_FN(LCD_FLM),
+	GPIO_FN(LCD_VEPWC),
+	GPIO_FN(LCD_VCPWC),
 
 	/* AFEIF */
-	PINMUX_GPIO(GPIO_FN_AFE_RXIN, AFE_RXIN_MARK),
-	PINMUX_GPIO(GPIO_FN_AFE_RDET, AFE_RDET_MARK),
-	PINMUX_GPIO(GPIO_FN_AFE_FS, AFE_FS_MARK),
-	PINMUX_GPIO(GPIO_FN_AFE_TXOUT, AFE_TXOUT_MARK),
-	PINMUX_GPIO(GPIO_FN_AFE_SCLK, AFE_SCLK_MARK),
-	PINMUX_GPIO(GPIO_FN_AFE_RLYCNT, AFE_RLYCNT_MARK),
-	PINMUX_GPIO(GPIO_FN_AFE_HC1, AFE_HC1_MARK),
+	GPIO_FN(AFE_RXIN),
+	GPIO_FN(AFE_RDET),
+	GPIO_FN(AFE_FS),
+	GPIO_FN(AFE_TXOUT),
+	GPIO_FN(AFE_SCLK),
+	GPIO_FN(AFE_RLYCNT),
+	GPIO_FN(AFE_HC1),
 
 	/* IIC */
-	PINMUX_GPIO(GPIO_FN_IIC_SCL, IIC_SCL_MARK),
-	PINMUX_GPIO(GPIO_FN_IIC_SDA, IIC_SDA_MARK),
+	GPIO_FN(IIC_SCL),
+	GPIO_FN(IIC_SDA),
 
 	/* DAC */
-	PINMUX_GPIO(GPIO_FN_DA1, DA1_MARK),
-	PINMUX_GPIO(GPIO_FN_DA0, DA0_MARK),
+	GPIO_FN(DA1),
+	GPIO_FN(DA0),
 
 	/* ADC */
-	PINMUX_GPIO(GPIO_FN_AN3, AN3_MARK),
-	PINMUX_GPIO(GPIO_FN_AN2, AN2_MARK),
-	PINMUX_GPIO(GPIO_FN_AN1, AN1_MARK),
-	PINMUX_GPIO(GPIO_FN_AN0, AN0_MARK),
-	PINMUX_GPIO(GPIO_FN_ADTRG, ADTRG_MARK),
+	GPIO_FN(AN3),
+	GPIO_FN(AN2),
+	GPIO_FN(AN1),
+	GPIO_FN(AN0),
+	GPIO_FN(ADTRG),
 
 	/* USB */
-	PINMUX_GPIO(GPIO_FN_USB1D_RCV, USB1D_RCV_MARK),
-	PINMUX_GPIO(GPIO_FN_USB1D_TXSE0, USB1D_TXSE0_MARK),
-	PINMUX_GPIO(GPIO_FN_USB1D_TXDPLS, USB1D_TXDPLS_MARK),
-	PINMUX_GPIO(GPIO_FN_USB1D_DMNS, USB1D_DMNS_MARK),
-	PINMUX_GPIO(GPIO_FN_USB1D_DPLS, USB1D_DPLS_MARK),
-	PINMUX_GPIO(GPIO_FN_USB1D_SPEED, USB1D_SPEED_MARK),
-	PINMUX_GPIO(GPIO_FN_USB1D_TXENL, USB1D_TXENL_MARK),
-
-	PINMUX_GPIO(GPIO_FN_USB2_PWR_EN, USB2_PWR_EN_MARK),
-	PINMUX_GPIO(GPIO_FN_USB1_PWR_EN_USBF_UPLUP,
-		    USB1_PWR_EN_USBF_UPLUP_MARK),
-	PINMUX_GPIO(GPIO_FN_USB1D_SUSPEND, USB1D_SUSPEND_MARK),
+	GPIO_FN(USB1D_RCV),
+	GPIO_FN(USB1D_TXSE0),
+	GPIO_FN(USB1D_TXDPLS),
+	GPIO_FN(USB1D_DMNS),
+	GPIO_FN(USB1D_DPLS),
+	GPIO_FN(USB1D_SPEED),
+	GPIO_FN(USB1D_TXENL),
+
+	GPIO_FN(USB2_PWR_EN),
+	GPIO_FN(USB1_PWR_EN_USBF_UPLUP),
+	GPIO_FN(USB1D_SUSPEND),
 
 	/* INTC */
-	PINMUX_GPIO(GPIO_FN_IRQ5, IRQ5_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ4, IRQ4_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ3_IRL3, IRQ3_IRL3_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ2_IRL2, IRQ2_IRL2_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ1_IRL1, IRQ1_IRL1_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ0_IRL0, IRQ0_IRL0_MARK),
+	GPIO_FN(IRQ5),
+	GPIO_FN(IRQ4),
+	GPIO_FN(IRQ3_IRL3),
+	GPIO_FN(IRQ2_IRL2),
+	GPIO_FN(IRQ1_IRL1),
+	GPIO_FN(IRQ0_IRL0),
 
 	/* PCC */
-	PINMUX_GPIO(GPIO_FN_PCC_REG, PCC_REG_MARK),
-	PINMUX_GPIO(GPIO_FN_PCC_DRV, PCC_DRV_MARK),
-	PINMUX_GPIO(GPIO_FN_PCC_BVD2, PCC_BVD2_MARK),
-	PINMUX_GPIO(GPIO_FN_PCC_BVD1, PCC_BVD1_MARK),
-	PINMUX_GPIO(GPIO_FN_PCC_CD2, PCC_CD2_MARK),
-	PINMUX_GPIO(GPIO_FN_PCC_CD1, PCC_CD1_MARK),
-	PINMUX_GPIO(GPIO_FN_PCC_RESET, PCC_RESET_MARK),
-	PINMUX_GPIO(GPIO_FN_PCC_RDY, PCC_RDY_MARK),
-	PINMUX_GPIO(GPIO_FN_PCC_VS2, PCC_VS2_MARK),
-	PINMUX_GPIO(GPIO_FN_PCC_VS1, PCC_VS1_MARK),
+	GPIO_FN(PCC_REG),
+	GPIO_FN(PCC_DRV),
+	GPIO_FN(PCC_BVD2),
+	GPIO_FN(PCC_BVD1),
+	GPIO_FN(PCC_CD2),
+	GPIO_FN(PCC_CD1),
+	GPIO_FN(PCC_RESET),
+	GPIO_FN(PCC_RDY),
+	GPIO_FN(PCC_VS2),
+	GPIO_FN(PCC_VS1),
 
 	/* HUDI */
-	PINMUX_GPIO(GPIO_FN_AUDATA3, AUDATA3_MARK),
-	PINMUX_GPIO(GPIO_FN_AUDATA2, AUDATA2_MARK),
-	PINMUX_GPIO(GPIO_FN_AUDATA1, AUDATA1_MARK),
-	PINMUX_GPIO(GPIO_FN_AUDATA0, AUDATA0_MARK),
-	PINMUX_GPIO(GPIO_FN_AUDCK, AUDCK_MARK),
-	PINMUX_GPIO(GPIO_FN_AUDSYNC, AUDSYNC_MARK),
-	PINMUX_GPIO(GPIO_FN_ASEBRKAK, ASEBRKAK_MARK),
-	PINMUX_GPIO(GPIO_FN_TRST, TRST_MARK),
-	PINMUX_GPIO(GPIO_FN_TMS, TMS_MARK),
-	PINMUX_GPIO(GPIO_FN_TDO, TDO_MARK),
-	PINMUX_GPIO(GPIO_FN_TDI, TDI_MARK),
-	PINMUX_GPIO(GPIO_FN_TCK, TCK_MARK),
+	GPIO_FN(AUDATA3),
+	GPIO_FN(AUDATA2),
+	GPIO_FN(AUDATA1),
+	GPIO_FN(AUDATA0),
+	GPIO_FN(AUDCK),
+	GPIO_FN(AUDSYNC),
+	GPIO_FN(ASEBRKAK),
+	GPIO_FN(TRST),
+	GPIO_FN(TMS),
+	GPIO_FN(TDO),
+	GPIO_FN(TDI),
+	GPIO_FN(TCK),
 
 	/* DMAC */
-	PINMUX_GPIO(GPIO_FN_DACK1, DACK1_MARK),
-	PINMUX_GPIO(GPIO_FN_DREQ1, DREQ1_MARK),
-	PINMUX_GPIO(GPIO_FN_DACK0, DACK0_MARK),
-	PINMUX_GPIO(GPIO_FN_DREQ0, DREQ0_MARK),
-	PINMUX_GPIO(GPIO_FN_TEND1, TEND1_MARK),
-	PINMUX_GPIO(GPIO_FN_TEND0, TEND0_MARK),
+	GPIO_FN(DACK1),
+	GPIO_FN(DREQ1),
+	GPIO_FN(DACK0),
+	GPIO_FN(DREQ0),
+	GPIO_FN(TEND1),
+	GPIO_FN(TEND0),
 
 	/* SIOF0 */
-	PINMUX_GPIO(GPIO_FN_SIOF0_SYNC, SIOF0_SYNC_MARK),
-	PINMUX_GPIO(GPIO_FN_SIOF0_MCLK, SIOF0_MCLK_MARK),
-	PINMUX_GPIO(GPIO_FN_SIOF0_TXD, SIOF0_TXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SIOF0_RXD, SIOF0_RXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SIOF0_SCK, SIOF0_SCK_MARK),
+	GPIO_FN(SIOF0_SYNC),
+	GPIO_FN(SIOF0_MCLK),
+	GPIO_FN(SIOF0_TXD),
+	GPIO_FN(SIOF0_RXD),
+	GPIO_FN(SIOF0_SCK),
 
 	/* SIOF1 */
-	PINMUX_GPIO(GPIO_FN_SIOF1_SYNC, SIOF1_SYNC_MARK),
-	PINMUX_GPIO(GPIO_FN_SIOF1_MCLK, SIOF1_MCLK_MARK),
-	PINMUX_GPIO(GPIO_FN_SIOF1_TXD, SIOF1_TXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SIOF1_RXD, SIOF1_RXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SIOF1_SCK, SIOF1_SCK_MARK),
+	GPIO_FN(SIOF1_SYNC),
+	GPIO_FN(SIOF1_MCLK),
+	GPIO_FN(SIOF1_TXD),
+	GPIO_FN(SIOF1_RXD),
+	GPIO_FN(SIOF1_SCK),
 
 	/* SCIF0 */
-	PINMUX_GPIO(GPIO_FN_SCIF0_TXD, SCIF0_TXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF0_RXD, SCIF0_RXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF0_RTS, SCIF0_RTS_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF0_CTS, SCIF0_CTS_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF0_SCK, SCIF0_SCK_MARK),
+	GPIO_FN(SCIF0_TXD),
+	GPIO_FN(SCIF0_RXD),
+	GPIO_FN(SCIF0_RTS),
+	GPIO_FN(SCIF0_CTS),
+	GPIO_FN(SCIF0_SCK),
 
 	/* SCIF1 */
-	PINMUX_GPIO(GPIO_FN_SCIF1_TXD, SCIF1_TXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF1_RXD, SCIF1_RXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF1_RTS, SCIF1_RTS_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF1_CTS, SCIF1_CTS_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF1_SCK, SCIF1_SCK_MARK),
+	GPIO_FN(SCIF1_TXD),
+	GPIO_FN(SCIF1_RXD),
+	GPIO_FN(SCIF1_RTS),
+	GPIO_FN(SCIF1_CTS),
+	GPIO_FN(SCIF1_SCK),
 
 	/* TPU */
-	PINMUX_GPIO(GPIO_FN_TPU_TO1, TPU_TO1_MARK),
-	PINMUX_GPIO(GPIO_FN_TPU_TO0, TPU_TO0_MARK),
-	PINMUX_GPIO(GPIO_FN_TPU_TI3B, TPU_TI3B_MARK),
-	PINMUX_GPIO(GPIO_FN_TPU_TI3A, TPU_TI3A_MARK),
-	PINMUX_GPIO(GPIO_FN_TPU_TI2B, TPU_TI2B_MARK),
-	PINMUX_GPIO(GPIO_FN_TPU_TI2A, TPU_TI2A_MARK),
-	PINMUX_GPIO(GPIO_FN_TPU_TO3, TPU_TO3_MARK),
-	PINMUX_GPIO(GPIO_FN_TPU_TO2, TPU_TO2_MARK),
+	GPIO_FN(TPU_TO1),
+	GPIO_FN(TPU_TO0),
+	GPIO_FN(TPU_TI3B),
+	GPIO_FN(TPU_TI3A),
+	GPIO_FN(TPU_TI2B),
+	GPIO_FN(TPU_TI2A),
+	GPIO_FN(TPU_TO3),
+	GPIO_FN(TPU_TO2),
 
 	/* SIM */
-	PINMUX_GPIO(GPIO_FN_SIM_D, SIM_D_MARK),
-	PINMUX_GPIO(GPIO_FN_SIM_CLK, SIM_CLK_MARK),
-	PINMUX_GPIO(GPIO_FN_SIM_RST, SIM_RST_MARK),
+	GPIO_FN(SIM_D),
+	GPIO_FN(SIM_CLK),
+	GPIO_FN(SIM_RST),
 
 	/* MMC */
-	PINMUX_GPIO(GPIO_FN_MMC_DAT, MMC_DAT_MARK),
-	PINMUX_GPIO(GPIO_FN_MMC_CMD, MMC_CMD_MARK),
-	PINMUX_GPIO(GPIO_FN_MMC_CLK, MMC_CLK_MARK),
-	PINMUX_GPIO(GPIO_FN_MMC_VDDON, MMC_VDDON_MARK),
-	PINMUX_GPIO(GPIO_FN_MMC_ODMOD, MMC_ODMOD_MARK),
+	GPIO_FN(MMC_DAT),
+	GPIO_FN(MMC_CMD),
+	GPIO_FN(MMC_CLK),
+	GPIO_FN(MMC_VDDON),
+	GPIO_FN(MMC_ODMOD),
 
 	/* SYSC */
-	PINMUX_GPIO(GPIO_FN_STATUS0, STATUS0_MARK),
-	PINMUX_GPIO(GPIO_FN_STATUS1, STATUS1_MARK),
+	GPIO_FN(STATUS0),
+	GPIO_FN(STATUS1),
 };
 
-static struct pinmux_cfg_reg pinmux_config_regs[] = {
+static const struct pinmux_cfg_reg pinmux_config_regs[] = {
 	{ PINMUX_CFG_REG("PACR", 0xa4050100, 16, 2) {
 		PTA7_FN, PTA7_OUT, PTA7_IN_PU, PTA7_IN,
 		PTA6_FN, PTA6_OUT, PTA6_IN_PU, PTA6_IN,
@@ -1138,7 +1141,7 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = {
 	{}
 };
 
-static struct pinmux_data_reg pinmux_data_regs[] = {
+static const struct pinmux_data_reg pinmux_data_regs[] = {
 	{ PINMUX_DATA_REG("PADR", 0xa4050140, 8) {
 		PTA7_DATA, PTA6_DATA, PTA5_DATA, PTA4_DATA,
 		PTA3_DATA, PTA2_DATA, PTA1_DATA, PTA0_DATA }
@@ -1214,20 +1217,18 @@ static struct pinmux_data_reg pinmux_data_regs[] = {
 	{ },
 };
 
-struct sh_pfc_soc_info sh7720_pinmux_info = {
+const struct sh_pfc_soc_info sh7720_pinmux_info = {
 	.name = "sh7720_pfc",
-	.reserved_id = PINMUX_RESERVED,
-	.data = { PINMUX_DATA_BEGIN, PINMUX_DATA_END },
 	.input = { PINMUX_INPUT_BEGIN, PINMUX_INPUT_END },
 	.input_pu = { PINMUX_INPUT_PULLUP_BEGIN, PINMUX_INPUT_PULLUP_END },
 	.output = { PINMUX_OUTPUT_BEGIN, PINMUX_OUTPUT_END },
-	.mark = { PINMUX_MARK_BEGIN, PINMUX_MARK_END },
 	.function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END },
 
-	.first_gpio = GPIO_PTA7,
-	.last_gpio = GPIO_FN_STATUS1,
+	.pins = pinmux_pins,
+	.nr_pins = ARRAY_SIZE(pinmux_pins),
+	.func_gpios = pinmux_func_gpios,
+	.nr_func_gpios = ARRAY_SIZE(pinmux_func_gpios),
 
-	.gpios = pinmux_gpios,
 	.cfg_regs = pinmux_config_regs,
 	.data_regs = pinmux_data_regs,
 
diff --git a/drivers/pinctrl/sh-pfc/pfc-sh7722.c b/drivers/pinctrl/sh-pfc/pfc-sh7722.c
index 2de0929..3203438 100644
--- a/drivers/pinctrl/sh-pfc/pfc-sh7722.c
+++ b/drivers/pinctrl/sh-pfc/pfc-sh7722.c
@@ -296,7 +296,7 @@ enum {
 	PINMUX_FUNCTION_END,
 };
 
-static pinmux_enum_t pinmux_data[] = {
+static const pinmux_enum_t pinmux_data[] = {
 	/* PTA */
 	PINMUX_DATA(PTA7_DATA, PTA7_IN, PTA7_IN_PD, PTA7_OUT),
 	PINMUX_DATA(PTA6_DATA, PTA6_IN, PTA6_IN_PD),
@@ -787,7 +787,7 @@ static pinmux_enum_t pinmux_data[] = {
 	PINMUX_DATA(KEYOUT5_IN5_MARK, HIZA14_KEYSC, KEYOUT5_IN5),
 };
 
-static struct pinmux_gpio pinmux_gpios[] = {
+static struct sh_pfc_pin pinmux_pins[] = {
 	/* PTA */
 	PINMUX_GPIO(GPIO_PTA7, PTA7_DATA),
 	PINMUX_GPIO(GPIO_PTA6, PTA6_DATA),
@@ -982,289 +982,293 @@ static struct pinmux_gpio pinmux_gpios[] = {
 	PINMUX_GPIO(GPIO_PTZ3, PTZ3_DATA),
 	PINMUX_GPIO(GPIO_PTZ2, PTZ2_DATA),
 	PINMUX_GPIO(GPIO_PTZ1, PTZ1_DATA),
+};
+
+#define PINMUX_FN_BASE	ARRAY_SIZE(pinmux_pins)
 
+static const struct pinmux_func pinmux_func_gpios[] = {
 	/* SCIF0 */
-	PINMUX_GPIO(GPIO_FN_SCIF0_TXD, SCIF0_TXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF0_RXD, SCIF0_RXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF0_RTS, SCIF0_RTS_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF0_CTS, SCIF0_CTS_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF0_SCK, SCIF0_SCK_MARK),
+	GPIO_FN(SCIF0_TXD),
+	GPIO_FN(SCIF0_RXD),
+	GPIO_FN(SCIF0_RTS),
+	GPIO_FN(SCIF0_CTS),
+	GPIO_FN(SCIF0_SCK),
 
 	/* SCIF1 */
-	PINMUX_GPIO(GPIO_FN_SCIF1_TXD, SCIF1_TXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF1_RXD, SCIF1_RXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF1_RTS, SCIF1_RTS_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF1_CTS, SCIF1_CTS_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF1_SCK, SCIF1_SCK_MARK),
+	GPIO_FN(SCIF1_TXD),
+	GPIO_FN(SCIF1_RXD),
+	GPIO_FN(SCIF1_RTS),
+	GPIO_FN(SCIF1_CTS),
+	GPIO_FN(SCIF1_SCK),
 
 	/* SCIF2 */
-	PINMUX_GPIO(GPIO_FN_SCIF2_TXD, SCIF2_TXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF2_RXD, SCIF2_RXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF2_RTS, SCIF2_RTS_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF2_CTS, SCIF2_CTS_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF2_SCK, SCIF2_SCK_MARK),
+	GPIO_FN(SCIF2_TXD),
+	GPIO_FN(SCIF2_RXD),
+	GPIO_FN(SCIF2_RTS),
+	GPIO_FN(SCIF2_CTS),
+	GPIO_FN(SCIF2_SCK),
 
 	/* SIO */
-	PINMUX_GPIO(GPIO_FN_SIOTXD, SIOTXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SIORXD, SIORXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SIOD, SIOD_MARK),
-	PINMUX_GPIO(GPIO_FN_SIOSTRB0, SIOSTRB0_MARK),
-	PINMUX_GPIO(GPIO_FN_SIOSTRB1, SIOSTRB1_MARK),
-	PINMUX_GPIO(GPIO_FN_SIOSCK, SIOSCK_MARK),
-	PINMUX_GPIO(GPIO_FN_SIOMCK, SIOMCK_MARK),
+	GPIO_FN(SIOTXD),
+	GPIO_FN(SIORXD),
+	GPIO_FN(SIOD),
+	GPIO_FN(SIOSTRB0),
+	GPIO_FN(SIOSTRB1),
+	GPIO_FN(SIOSCK),
+	GPIO_FN(SIOMCK),
 
 	/* CEU */
-	PINMUX_GPIO(GPIO_FN_VIO_D15, VIO_D15_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO_D14, VIO_D14_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO_D13, VIO_D13_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO_D12, VIO_D12_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO_D11, VIO_D11_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO_D10, VIO_D10_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO_D9, VIO_D9_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO_D8, VIO_D8_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO_D7, VIO_D7_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO_D6, VIO_D6_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO_D5, VIO_D5_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO_D4, VIO_D4_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO_D3, VIO_D3_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO_D2, VIO_D2_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO_D1, VIO_D1_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO_D0, VIO_D0_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO_CLK, VIO_CLK_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO_VD, VIO_VD_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO_HD, VIO_HD_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO_FLD, VIO_FLD_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO_CKO, VIO_CKO_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO_STEX, VIO_STEX_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO_STEM, VIO_STEM_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO_VD2, VIO_VD2_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO_HD2, VIO_HD2_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO_CLK2, VIO_CLK2_MARK),
+	GPIO_FN(VIO_D15),
+	GPIO_FN(VIO_D14),
+	GPIO_FN(VIO_D13),
+	GPIO_FN(VIO_D12),
+	GPIO_FN(VIO_D11),
+	GPIO_FN(VIO_D10),
+	GPIO_FN(VIO_D9),
+	GPIO_FN(VIO_D8),
+	GPIO_FN(VIO_D7),
+	GPIO_FN(VIO_D6),
+	GPIO_FN(VIO_D5),
+	GPIO_FN(VIO_D4),
+	GPIO_FN(VIO_D3),
+	GPIO_FN(VIO_D2),
+	GPIO_FN(VIO_D1),
+	GPIO_FN(VIO_D0),
+	GPIO_FN(VIO_CLK),
+	GPIO_FN(VIO_VD),
+	GPIO_FN(VIO_HD),
+	GPIO_FN(VIO_FLD),
+	GPIO_FN(VIO_CKO),
+	GPIO_FN(VIO_STEX),
+	GPIO_FN(VIO_STEM),
+	GPIO_FN(VIO_VD2),
+	GPIO_FN(VIO_HD2),
+	GPIO_FN(VIO_CLK2),
 
 	/* LCDC */
-	PINMUX_GPIO(GPIO_FN_LCDD23, LCDD23_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD22, LCDD22_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD21, LCDD21_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD20, LCDD20_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD19, LCDD19_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD18, LCDD18_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD17, LCDD17_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD16, LCDD16_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD15, LCDD15_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD14, LCDD14_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD13, LCDD13_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD12, LCDD12_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD11, LCDD11_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD10, LCDD10_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD9, LCDD9_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD8, LCDD8_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD7, LCDD7_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD6, LCDD6_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD5, LCDD5_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD4, LCDD4_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD3, LCDD3_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD2, LCDD2_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD1, LCDD1_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD0, LCDD0_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDLCLK, LCDLCLK_MARK),
+	GPIO_FN(LCDD23),
+	GPIO_FN(LCDD22),
+	GPIO_FN(LCDD21),
+	GPIO_FN(LCDD20),
+	GPIO_FN(LCDD19),
+	GPIO_FN(LCDD18),
+	GPIO_FN(LCDD17),
+	GPIO_FN(LCDD16),
+	GPIO_FN(LCDD15),
+	GPIO_FN(LCDD14),
+	GPIO_FN(LCDD13),
+	GPIO_FN(LCDD12),
+	GPIO_FN(LCDD11),
+	GPIO_FN(LCDD10),
+	GPIO_FN(LCDD9),
+	GPIO_FN(LCDD8),
+	GPIO_FN(LCDD7),
+	GPIO_FN(LCDD6),
+	GPIO_FN(LCDD5),
+	GPIO_FN(LCDD4),
+	GPIO_FN(LCDD3),
+	GPIO_FN(LCDD2),
+	GPIO_FN(LCDD1),
+	GPIO_FN(LCDD0),
+	GPIO_FN(LCDLCLK),
 	/* Main LCD */
-	PINMUX_GPIO(GPIO_FN_LCDDON, LCDDON_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDVCPWC, LCDVCPWC_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDVEPWC, LCDVEPWC_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDVSYN, LCDVSYN_MARK),
+	GPIO_FN(LCDDON),
+	GPIO_FN(LCDVCPWC),
+	GPIO_FN(LCDVEPWC),
+	GPIO_FN(LCDVSYN),
 	/* Main LCD - RGB Mode */
-	PINMUX_GPIO(GPIO_FN_LCDDCK, LCDDCK_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDHSYN, LCDHSYN_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDDISP, LCDDISP_MARK),
+	GPIO_FN(LCDDCK),
+	GPIO_FN(LCDHSYN),
+	GPIO_FN(LCDDISP),
 	/* Main LCD - SYS Mode */
-	PINMUX_GPIO(GPIO_FN_LCDRS, LCDRS_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDCS, LCDCS_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDWR, LCDWR_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDRD, LCDRD_MARK),
+	GPIO_FN(LCDRS),
+	GPIO_FN(LCDCS),
+	GPIO_FN(LCDWR),
+	GPIO_FN(LCDRD),
 	/* Sub LCD - SYS Mode */
-	PINMUX_GPIO(GPIO_FN_LCDDON2, LCDDON2_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDVCPWC2, LCDVCPWC2_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDVEPWC2, LCDVEPWC2_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDVSYN2, LCDVSYN2_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDCS2, LCDCS2_MARK),
+	GPIO_FN(LCDDON2),
+	GPIO_FN(LCDVCPWC2),
+	GPIO_FN(LCDVEPWC2),
+	GPIO_FN(LCDVSYN2),
+	GPIO_FN(LCDCS2),
 
 	/* BSC */
-	PINMUX_GPIO(GPIO_FN_IOIS16, IOIS16_MARK),
-	PINMUX_GPIO(GPIO_FN_A25, A25_MARK),
-	PINMUX_GPIO(GPIO_FN_A24, A24_MARK),
-	PINMUX_GPIO(GPIO_FN_A23, A23_MARK),
-	PINMUX_GPIO(GPIO_FN_A22, A22_MARK),
-	PINMUX_GPIO(GPIO_FN_BS, BS_MARK),
-	PINMUX_GPIO(GPIO_FN_CS6B_CE1B, CS6B_CE1B_MARK),
-	PINMUX_GPIO(GPIO_FN_WAIT, WAIT_MARK),
-	PINMUX_GPIO(GPIO_FN_CS6A_CE2B, CS6A_CE2B_MARK),
+	GPIO_FN(IOIS16),
+	GPIO_FN(A25),
+	GPIO_FN(A24),
+	GPIO_FN(A23),
+	GPIO_FN(A22),
+	GPIO_FN(BS),
+	GPIO_FN(CS6B_CE1B),
+	GPIO_FN(WAIT),
+	GPIO_FN(CS6A_CE2B),
 
 	/* SBSC */
-	PINMUX_GPIO(GPIO_FN_HPD63, HPD63_MARK),
-	PINMUX_GPIO(GPIO_FN_HPD62, HPD62_MARK),
-	PINMUX_GPIO(GPIO_FN_HPD61, HPD61_MARK),
-	PINMUX_GPIO(GPIO_FN_HPD60, HPD60_MARK),
-	PINMUX_GPIO(GPIO_FN_HPD59, HPD59_MARK),
-	PINMUX_GPIO(GPIO_FN_HPD58, HPD58_MARK),
-	PINMUX_GPIO(GPIO_FN_HPD57, HPD57_MARK),
-	PINMUX_GPIO(GPIO_FN_HPD56, HPD56_MARK),
-	PINMUX_GPIO(GPIO_FN_HPD55, HPD55_MARK),
-	PINMUX_GPIO(GPIO_FN_HPD54, HPD54_MARK),
-	PINMUX_GPIO(GPIO_FN_HPD53, HPD53_MARK),
-	PINMUX_GPIO(GPIO_FN_HPD52, HPD52_MARK),
-	PINMUX_GPIO(GPIO_FN_HPD51, HPD51_MARK),
-	PINMUX_GPIO(GPIO_FN_HPD50, HPD50_MARK),
-	PINMUX_GPIO(GPIO_FN_HPD49, HPD49_MARK),
-	PINMUX_GPIO(GPIO_FN_HPD48, HPD48_MARK),
-	PINMUX_GPIO(GPIO_FN_HPDQM7, HPDQM7_MARK),
-	PINMUX_GPIO(GPIO_FN_HPDQM6, HPDQM6_MARK),
-	PINMUX_GPIO(GPIO_FN_HPDQM5, HPDQM5_MARK),
-	PINMUX_GPIO(GPIO_FN_HPDQM4, HPDQM4_MARK),
+	GPIO_FN(HPD63),
+	GPIO_FN(HPD62),
+	GPIO_FN(HPD61),
+	GPIO_FN(HPD60),
+	GPIO_FN(HPD59),
+	GPIO_FN(HPD58),
+	GPIO_FN(HPD57),
+	GPIO_FN(HPD56),
+	GPIO_FN(HPD55),
+	GPIO_FN(HPD54),
+	GPIO_FN(HPD53),
+	GPIO_FN(HPD52),
+	GPIO_FN(HPD51),
+	GPIO_FN(HPD50),
+	GPIO_FN(HPD49),
+	GPIO_FN(HPD48),
+	GPIO_FN(HPDQM7),
+	GPIO_FN(HPDQM6),
+	GPIO_FN(HPDQM5),
+	GPIO_FN(HPDQM4),
 
 	/* IRQ */
-	PINMUX_GPIO(GPIO_FN_IRQ0, IRQ0_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ1, IRQ1_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ2, IRQ2_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ3, IRQ3_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ4, IRQ4_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ5, IRQ5_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ6, IRQ6_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ7, IRQ7_MARK),
+	GPIO_FN(IRQ0),
+	GPIO_FN(IRQ1),
+	GPIO_FN(IRQ2),
+	GPIO_FN(IRQ3),
+	GPIO_FN(IRQ4),
+	GPIO_FN(IRQ5),
+	GPIO_FN(IRQ6),
+	GPIO_FN(IRQ7),
 
 	/* SDHI */
-	PINMUX_GPIO(GPIO_FN_SDHICD, SDHICD_MARK),
-	PINMUX_GPIO(GPIO_FN_SDHIWP, SDHIWP_MARK),
-	PINMUX_GPIO(GPIO_FN_SDHID3, SDHID3_MARK),
-	PINMUX_GPIO(GPIO_FN_SDHID2, SDHID2_MARK),
-	PINMUX_GPIO(GPIO_FN_SDHID1, SDHID1_MARK),
-	PINMUX_GPIO(GPIO_FN_SDHID0, SDHID0_MARK),
-	PINMUX_GPIO(GPIO_FN_SDHICMD, SDHICMD_MARK),
-	PINMUX_GPIO(GPIO_FN_SDHICLK, SDHICLK_MARK),
+	GPIO_FN(SDHICD),
+	GPIO_FN(SDHIWP),
+	GPIO_FN(SDHID3),
+	GPIO_FN(SDHID2),
+	GPIO_FN(SDHID1),
+	GPIO_FN(SDHID0),
+	GPIO_FN(SDHICMD),
+	GPIO_FN(SDHICLK),
 
 	/* SIU - Port A */
-	PINMUX_GPIO(GPIO_FN_SIUAOLR, SIUAOLR_MARK),
-	PINMUX_GPIO(GPIO_FN_SIUAOBT, SIUAOBT_MARK),
-	PINMUX_GPIO(GPIO_FN_SIUAISLD, SIUAISLD_MARK),
-	PINMUX_GPIO(GPIO_FN_SIUAILR, SIUAILR_MARK),
-	PINMUX_GPIO(GPIO_FN_SIUAIBT, SIUAIBT_MARK),
-	PINMUX_GPIO(GPIO_FN_SIUAOSLD, SIUAOSLD_MARK),
-	PINMUX_GPIO(GPIO_FN_SIUMCKA, SIUMCKA_MARK),
-	PINMUX_GPIO(GPIO_FN_SIUFCKA, SIUFCKA_MARK),
+	GPIO_FN(SIUAOLR),
+	GPIO_FN(SIUAOBT),
+	GPIO_FN(SIUAISLD),
+	GPIO_FN(SIUAILR),
+	GPIO_FN(SIUAIBT),
+	GPIO_FN(SIUAOSLD),
+	GPIO_FN(SIUMCKA),
+	GPIO_FN(SIUFCKA),
 
 	/* SIU - Port B */
-	PINMUX_GPIO(GPIO_FN_SIUBOLR, SIUBOLR_MARK),
-	PINMUX_GPIO(GPIO_FN_SIUBOBT, SIUBOBT_MARK),
-	PINMUX_GPIO(GPIO_FN_SIUBISLD, SIUBISLD_MARK),
-	PINMUX_GPIO(GPIO_FN_SIUBILR, SIUBILR_MARK),
-	PINMUX_GPIO(GPIO_FN_SIUBIBT, SIUBIBT_MARK),
-	PINMUX_GPIO(GPIO_FN_SIUBOSLD, SIUBOSLD_MARK),
-	PINMUX_GPIO(GPIO_FN_SIUMCKB, SIUMCKB_MARK),
-	PINMUX_GPIO(GPIO_FN_SIUFCKB, SIUFCKB_MARK),
+	GPIO_FN(SIUBOLR),
+	GPIO_FN(SIUBOBT),
+	GPIO_FN(SIUBISLD),
+	GPIO_FN(SIUBILR),
+	GPIO_FN(SIUBIBT),
+	GPIO_FN(SIUBOSLD),
+	GPIO_FN(SIUMCKB),
+	GPIO_FN(SIUFCKB),
 
 	/* AUD */
-	PINMUX_GPIO(GPIO_FN_AUDSYNC, AUDSYNC_MARK),
-	PINMUX_GPIO(GPIO_FN_AUDATA3, AUDATA3_MARK),
-	PINMUX_GPIO(GPIO_FN_AUDATA2, AUDATA2_MARK),
-	PINMUX_GPIO(GPIO_FN_AUDATA1, AUDATA1_MARK),
-	PINMUX_GPIO(GPIO_FN_AUDATA0, AUDATA0_MARK),
+	GPIO_FN(AUDSYNC),
+	GPIO_FN(AUDATA3),
+	GPIO_FN(AUDATA2),
+	GPIO_FN(AUDATA1),
+	GPIO_FN(AUDATA0),
 
 	/* DMAC */
-	PINMUX_GPIO(GPIO_FN_DACK, DACK_MARK),
-	PINMUX_GPIO(GPIO_FN_DREQ0, DREQ0_MARK),
+	GPIO_FN(DACK),
+	GPIO_FN(DREQ0),
 
 	/* VOU */
-	PINMUX_GPIO(GPIO_FN_DV_CLKI, DV_CLKI_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_CLK, DV_CLK_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_HSYNC, DV_HSYNC_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_VSYNC, DV_VSYNC_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_D15, DV_D15_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_D14, DV_D14_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_D13, DV_D13_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_D12, DV_D12_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_D11, DV_D11_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_D10, DV_D10_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_D9, DV_D9_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_D8, DV_D8_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_D7, DV_D7_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_D6, DV_D6_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_D5, DV_D5_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_D4, DV_D4_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_D3, DV_D3_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_D2, DV_D2_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_D1, DV_D1_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_D0, DV_D0_MARK),
+	GPIO_FN(DV_CLKI),
+	GPIO_FN(DV_CLK),
+	GPIO_FN(DV_HSYNC),
+	GPIO_FN(DV_VSYNC),
+	GPIO_FN(DV_D15),
+	GPIO_FN(DV_D14),
+	GPIO_FN(DV_D13),
+	GPIO_FN(DV_D12),
+	GPIO_FN(DV_D11),
+	GPIO_FN(DV_D10),
+	GPIO_FN(DV_D9),
+	GPIO_FN(DV_D8),
+	GPIO_FN(DV_D7),
+	GPIO_FN(DV_D6),
+	GPIO_FN(DV_D5),
+	GPIO_FN(DV_D4),
+	GPIO_FN(DV_D3),
+	GPIO_FN(DV_D2),
+	GPIO_FN(DV_D1),
+	GPIO_FN(DV_D0),
 
 	/* CPG */
-	PINMUX_GPIO(GPIO_FN_STATUS0, STATUS0_MARK),
-	PINMUX_GPIO(GPIO_FN_PDSTATUS, PDSTATUS_MARK),
+	GPIO_FN(STATUS0),
+	GPIO_FN(PDSTATUS),
 
 	/* SIOF0 */
-	PINMUX_GPIO(GPIO_FN_SIOF0_MCK, SIOF0_MCK_MARK),
-	PINMUX_GPIO(GPIO_FN_SIOF0_SCK, SIOF0_SCK_MARK),
-	PINMUX_GPIO(GPIO_FN_SIOF0_SYNC, SIOF0_SYNC_MARK),
-	PINMUX_GPIO(GPIO_FN_SIOF0_SS1, SIOF0_SS1_MARK),
-	PINMUX_GPIO(GPIO_FN_SIOF0_SS2, SIOF0_SS2_MARK),
-	PINMUX_GPIO(GPIO_FN_SIOF0_TXD, SIOF0_TXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SIOF0_RXD, SIOF0_RXD_MARK),
+	GPIO_FN(SIOF0_MCK),
+	GPIO_FN(SIOF0_SCK),
+	GPIO_FN(SIOF0_SYNC),
+	GPIO_FN(SIOF0_SS1),
+	GPIO_FN(SIOF0_SS2),
+	GPIO_FN(SIOF0_TXD),
+	GPIO_FN(SIOF0_RXD),
 
 	/* SIOF1 */
-	PINMUX_GPIO(GPIO_FN_SIOF1_MCK, SIOF1_MCK_MARK),
-	PINMUX_GPIO(GPIO_FN_SIOF1_SCK, SIOF1_SCK_MARK),
-	PINMUX_GPIO(GPIO_FN_SIOF1_SYNC, SIOF1_SYNC_MARK),
-	PINMUX_GPIO(GPIO_FN_SIOF1_SS1, SIOF1_SS1_MARK),
-	PINMUX_GPIO(GPIO_FN_SIOF1_SS2, SIOF1_SS2_MARK),
-	PINMUX_GPIO(GPIO_FN_SIOF1_TXD, SIOF1_TXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SIOF1_RXD, SIOF1_RXD_MARK),
+	GPIO_FN(SIOF1_MCK),
+	GPIO_FN(SIOF1_SCK),
+	GPIO_FN(SIOF1_SYNC),
+	GPIO_FN(SIOF1_SS1),
+	GPIO_FN(SIOF1_SS2),
+	GPIO_FN(SIOF1_TXD),
+	GPIO_FN(SIOF1_RXD),
 
 	/* SIM */
-	PINMUX_GPIO(GPIO_FN_SIM_D, SIM_D_MARK),
-	PINMUX_GPIO(GPIO_FN_SIM_CLK, SIM_CLK_MARK),
-	PINMUX_GPIO(GPIO_FN_SIM_RST, SIM_RST_MARK),
+	GPIO_FN(SIM_D),
+	GPIO_FN(SIM_CLK),
+	GPIO_FN(SIM_RST),
 
 	/* TSIF */
-	PINMUX_GPIO(GPIO_FN_TS_SDAT, TS_SDAT_MARK),
-	PINMUX_GPIO(GPIO_FN_TS_SCK, TS_SCK_MARK),
-	PINMUX_GPIO(GPIO_FN_TS_SDEN, TS_SDEN_MARK),
-	PINMUX_GPIO(GPIO_FN_TS_SPSYNC, TS_SPSYNC_MARK),
+	GPIO_FN(TS_SDAT),
+	GPIO_FN(TS_SCK),
+	GPIO_FN(TS_SDEN),
+	GPIO_FN(TS_SPSYNC),
 
 	/* IRDA */
-	PINMUX_GPIO(GPIO_FN_IRDA_IN, IRDA_IN_MARK),
-	PINMUX_GPIO(GPIO_FN_IRDA_OUT, IRDA_OUT_MARK),
+	GPIO_FN(IRDA_IN),
+	GPIO_FN(IRDA_OUT),
 
 	/* TPU */
-	PINMUX_GPIO(GPIO_FN_TPUTO, TPUTO_MARK),
+	GPIO_FN(TPUTO),
 
 	/* FLCTL */
-	PINMUX_GPIO(GPIO_FN_FCE, FCE_MARK),
-	PINMUX_GPIO(GPIO_FN_NAF7, NAF7_MARK),
-	PINMUX_GPIO(GPIO_FN_NAF6, NAF6_MARK),
-	PINMUX_GPIO(GPIO_FN_NAF5, NAF5_MARK),
-	PINMUX_GPIO(GPIO_FN_NAF4, NAF4_MARK),
-	PINMUX_GPIO(GPIO_FN_NAF3, NAF3_MARK),
-	PINMUX_GPIO(GPIO_FN_NAF2, NAF2_MARK),
-	PINMUX_GPIO(GPIO_FN_NAF1, NAF1_MARK),
-	PINMUX_GPIO(GPIO_FN_NAF0, NAF0_MARK),
-	PINMUX_GPIO(GPIO_FN_FCDE, FCDE_MARK),
-	PINMUX_GPIO(GPIO_FN_FOE, FOE_MARK),
-	PINMUX_GPIO(GPIO_FN_FSC, FSC_MARK),
-	PINMUX_GPIO(GPIO_FN_FWE, FWE_MARK),
-	PINMUX_GPIO(GPIO_FN_FRB, FRB_MARK),
+	GPIO_FN(FCE),
+	GPIO_FN(NAF7),
+	GPIO_FN(NAF6),
+	GPIO_FN(NAF5),
+	GPIO_FN(NAF4),
+	GPIO_FN(NAF3),
+	GPIO_FN(NAF2),
+	GPIO_FN(NAF1),
+	GPIO_FN(NAF0),
+	GPIO_FN(FCDE),
+	GPIO_FN(FOE),
+	GPIO_FN(FSC),
+	GPIO_FN(FWE),
+	GPIO_FN(FRB),
 
 	/* KEYSC */
-	PINMUX_GPIO(GPIO_FN_KEYIN0, KEYIN0_MARK),
-	PINMUX_GPIO(GPIO_FN_KEYIN1, KEYIN1_MARK),
-	PINMUX_GPIO(GPIO_FN_KEYIN2, KEYIN2_MARK),
-	PINMUX_GPIO(GPIO_FN_KEYIN3, KEYIN3_MARK),
-	PINMUX_GPIO(GPIO_FN_KEYIN4, KEYIN4_MARK),
-	PINMUX_GPIO(GPIO_FN_KEYOUT0, KEYOUT0_MARK),
-	PINMUX_GPIO(GPIO_FN_KEYOUT1, KEYOUT1_MARK),
-	PINMUX_GPIO(GPIO_FN_KEYOUT2, KEYOUT2_MARK),
-	PINMUX_GPIO(GPIO_FN_KEYOUT3, KEYOUT3_MARK),
-	PINMUX_GPIO(GPIO_FN_KEYOUT4_IN6, KEYOUT4_IN6_MARK),
-	PINMUX_GPIO(GPIO_FN_KEYOUT5_IN5, KEYOUT5_IN5_MARK),
+	GPIO_FN(KEYIN0),
+	GPIO_FN(KEYIN1),
+	GPIO_FN(KEYIN2),
+	GPIO_FN(KEYIN3),
+	GPIO_FN(KEYIN4),
+	GPIO_FN(KEYOUT0),
+	GPIO_FN(KEYOUT1),
+	GPIO_FN(KEYOUT2),
+	GPIO_FN(KEYOUT3),
+	GPIO_FN(KEYOUT4_IN6),
+	GPIO_FN(KEYOUT5_IN5),
 };
 
-static struct pinmux_cfg_reg pinmux_config_regs[] = {
+static const struct pinmux_cfg_reg pinmux_config_regs[] = {
 	{ PINMUX_CFG_REG("PACR", 0xa4050100, 16, 2) {
 		VIO_D7_SCIF1_SCK, PTA7_OUT, PTA7_IN_PD, PTA7_IN,
 		VIO_D6_SCIF1_RXD, 0, PTA6_IN_PD, PTA6_IN,
@@ -1660,7 +1664,7 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = {
 	{}
 };
 
-static struct pinmux_data_reg pinmux_data_regs[] = {
+static const struct pinmux_data_reg pinmux_data_regs[] = {
 	{ PINMUX_DATA_REG("PADR", 0xa4050120, 8) {
 		PTA7_DATA, PTA6_DATA, PTA5_DATA, PTA4_DATA,
 		PTA3_DATA, PTA2_DATA, PTA1_DATA, PTA0_DATA }
@@ -1756,21 +1760,19 @@ static struct pinmux_data_reg pinmux_data_regs[] = {
 	{ },
 };
 
-struct sh_pfc_soc_info sh7722_pinmux_info = {
+const struct sh_pfc_soc_info sh7722_pinmux_info = {
 	.name = "sh7722_pfc",
-	.reserved_id = PINMUX_RESERVED,
-	.data = { PINMUX_DATA_BEGIN, PINMUX_DATA_END },
 	.input = { PINMUX_INPUT_BEGIN, PINMUX_INPUT_END },
 	.input_pd = { PINMUX_INPUT_PULLDOWN_BEGIN, PINMUX_INPUT_PULLDOWN_END },
 	.input_pu = { PINMUX_INPUT_PULLUP_BEGIN, PINMUX_INPUT_PULLUP_END },
 	.output = { PINMUX_OUTPUT_BEGIN, PINMUX_OUTPUT_END },
-	.mark = { PINMUX_MARK_BEGIN, PINMUX_MARK_END },
 	.function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END },
 
-	.first_gpio = GPIO_PTA7,
-	.last_gpio = GPIO_FN_KEYOUT5_IN5,
+	.pins = pinmux_pins,
+	.nr_pins = ARRAY_SIZE(pinmux_pins),
+	.func_gpios = pinmux_func_gpios,
+	.nr_func_gpios = ARRAY_SIZE(pinmux_func_gpios),
 
-	.gpios = pinmux_gpios,
 	.cfg_regs = pinmux_config_regs,
 	.data_regs = pinmux_data_regs,
 
diff --git a/drivers/pinctrl/sh-pfc/pfc-sh7723.c b/drivers/pinctrl/sh-pfc/pfc-sh7723.c
index 609673d..07ad1d8 100644
--- a/drivers/pinctrl/sh-pfc/pfc-sh7723.c
+++ b/drivers/pinctrl/sh-pfc/pfc-sh7723.c
@@ -350,7 +350,7 @@ enum {
 	PINMUX_MARK_END,
 };
 
-static pinmux_enum_t pinmux_data[] = {
+static const pinmux_enum_t pinmux_data[] = {
 	/* PTA GPIO */
 	PINMUX_DATA(PTA7_DATA, PTA7_IN, PTA7_OUT),
 	PINMUX_DATA(PTA6_DATA, PTA6_IN, PTA6_OUT),
@@ -923,7 +923,7 @@ static pinmux_enum_t pinmux_data[] = {
 	PINMUX_DATA(SIUBISLD_MARK, PSD1_PSD0_FN2, PTZ0_FN),
 };
 
-static struct pinmux_gpio pinmux_gpios[] = {
+static struct sh_pfc_pin pinmux_pins[] = {
 	/* PTA */
 	PINMUX_GPIO(GPIO_PTA7, PTA7_DATA),
 	PINMUX_GPIO(GPIO_PTA6, PTA6_DATA),
@@ -1139,379 +1139,383 @@ static struct pinmux_gpio pinmux_gpios[] = {
 	PINMUX_GPIO(GPIO_PTZ2, PTZ2_DATA),
 	PINMUX_GPIO(GPIO_PTZ1, PTZ1_DATA),
 	PINMUX_GPIO(GPIO_PTZ0, PTZ0_DATA),
+};
+
+#define PINMUX_FN_BASE	ARRAY_SIZE(pinmux_pins)
 
+static const struct pinmux_func pinmux_func_gpios[] = {
 	/* SCIF0 */
-	PINMUX_GPIO(GPIO_FN_SCIF0_PTT_TXD, SCIF0_PTT_TXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF0_PTT_RXD, SCIF0_PTT_RXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF0_PTT_SCK, SCIF0_PTT_SCK_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF0_PTU_TXD, SCIF0_PTU_TXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF0_PTU_RXD, SCIF0_PTU_RXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF0_PTU_SCK, SCIF0_PTU_SCK_MARK),
+	GPIO_FN(SCIF0_PTT_TXD),
+	GPIO_FN(SCIF0_PTT_RXD),
+	GPIO_FN(SCIF0_PTT_SCK),
+	GPIO_FN(SCIF0_PTU_TXD),
+	GPIO_FN(SCIF0_PTU_RXD),
+	GPIO_FN(SCIF0_PTU_SCK),
 
 	/* SCIF1 */
-	PINMUX_GPIO(GPIO_FN_SCIF1_PTS_TXD, SCIF1_PTS_TXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF1_PTS_RXD, SCIF1_PTS_RXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF1_PTS_SCK, SCIF1_PTS_SCK_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF1_PTV_TXD, SCIF1_PTV_TXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF1_PTV_RXD, SCIF1_PTV_RXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF1_PTV_SCK, SCIF1_PTV_SCK_MARK),
+	GPIO_FN(SCIF1_PTS_TXD),
+	GPIO_FN(SCIF1_PTS_RXD),
+	GPIO_FN(SCIF1_PTS_SCK),
+	GPIO_FN(SCIF1_PTV_TXD),
+	GPIO_FN(SCIF1_PTV_RXD),
+	GPIO_FN(SCIF1_PTV_SCK),
 
 	/* SCIF2 */
-	PINMUX_GPIO(GPIO_FN_SCIF2_PTT_TXD, SCIF2_PTT_TXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF2_PTT_RXD, SCIF2_PTT_RXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF2_PTT_SCK, SCIF2_PTT_SCK_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF2_PTU_TXD, SCIF2_PTU_TXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF2_PTU_RXD, SCIF2_PTU_RXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF2_PTU_SCK, SCIF2_PTU_SCK_MARK),
+	GPIO_FN(SCIF2_PTT_TXD),
+	GPIO_FN(SCIF2_PTT_RXD),
+	GPIO_FN(SCIF2_PTT_SCK),
+	GPIO_FN(SCIF2_PTU_TXD),
+	GPIO_FN(SCIF2_PTU_RXD),
+	GPIO_FN(SCIF2_PTU_SCK),
 
 	/* SCIF3 */
-	PINMUX_GPIO(GPIO_FN_SCIF3_PTS_TXD, SCIF3_PTS_TXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF3_PTS_RXD, SCIF3_PTS_RXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF3_PTS_SCK, SCIF3_PTS_SCK_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF3_PTS_RTS, SCIF3_PTS_RTS_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF3_PTS_CTS, SCIF3_PTS_CTS_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF3_PTV_TXD, SCIF3_PTV_TXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF3_PTV_RXD, SCIF3_PTV_RXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF3_PTV_SCK, SCIF3_PTV_SCK_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF3_PTV_RTS, SCIF3_PTV_RTS_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF3_PTV_CTS, SCIF3_PTV_CTS_MARK),
+	GPIO_FN(SCIF3_PTS_TXD),
+	GPIO_FN(SCIF3_PTS_RXD),
+	GPIO_FN(SCIF3_PTS_SCK),
+	GPIO_FN(SCIF3_PTS_RTS),
+	GPIO_FN(SCIF3_PTS_CTS),
+	GPIO_FN(SCIF3_PTV_TXD),
+	GPIO_FN(SCIF3_PTV_RXD),
+	GPIO_FN(SCIF3_PTV_SCK),
+	GPIO_FN(SCIF3_PTV_RTS),
+	GPIO_FN(SCIF3_PTV_CTS),
 
 	/* SCIF4 */
-	PINMUX_GPIO(GPIO_FN_SCIF4_PTE_TXD, SCIF4_PTE_TXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF4_PTE_RXD, SCIF4_PTE_RXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF4_PTE_SCK, SCIF4_PTE_SCK_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF4_PTN_TXD, SCIF4_PTN_TXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF4_PTN_RXD, SCIF4_PTN_RXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF4_PTN_SCK, SCIF4_PTN_SCK_MARK),
+	GPIO_FN(SCIF4_PTE_TXD),
+	GPIO_FN(SCIF4_PTE_RXD),
+	GPIO_FN(SCIF4_PTE_SCK),
+	GPIO_FN(SCIF4_PTN_TXD),
+	GPIO_FN(SCIF4_PTN_RXD),
+	GPIO_FN(SCIF4_PTN_SCK),
 
 	/* SCIF5 */
-	PINMUX_GPIO(GPIO_FN_SCIF5_PTE_TXD, SCIF5_PTE_TXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF5_PTE_RXD, SCIF5_PTE_RXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF5_PTE_SCK, SCIF5_PTE_SCK_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF5_PTN_TXD, SCIF5_PTN_TXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF5_PTN_RXD, SCIF5_PTN_RXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF5_PTN_SCK, SCIF5_PTN_SCK_MARK),
+	GPIO_FN(SCIF5_PTE_TXD),
+	GPIO_FN(SCIF5_PTE_RXD),
+	GPIO_FN(SCIF5_PTE_SCK),
+	GPIO_FN(SCIF5_PTN_TXD),
+	GPIO_FN(SCIF5_PTN_RXD),
+	GPIO_FN(SCIF5_PTN_SCK),
 
 	/* CEU */
-	PINMUX_GPIO(GPIO_FN_VIO_D15, VIO_D15_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO_D14, VIO_D14_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO_D13, VIO_D13_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO_D12, VIO_D12_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO_D11, VIO_D11_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO_D10, VIO_D10_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO_D9, VIO_D9_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO_D8, VIO_D8_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO_D7, VIO_D7_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO_D6, VIO_D6_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO_D5, VIO_D5_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO_D4, VIO_D4_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO_D3, VIO_D3_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO_D2, VIO_D2_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO_D1, VIO_D1_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO_D0, VIO_D0_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO_CLK1, VIO_CLK1_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO_VD1, VIO_VD1_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO_HD1, VIO_HD1_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO_FLD, VIO_FLD_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO_CKO, VIO_CKO_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO_VD2, VIO_VD2_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO_HD2, VIO_HD2_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO_CLK2, VIO_CLK2_MARK),
+	GPIO_FN(VIO_D15),
+	GPIO_FN(VIO_D14),
+	GPIO_FN(VIO_D13),
+	GPIO_FN(VIO_D12),
+	GPIO_FN(VIO_D11),
+	GPIO_FN(VIO_D10),
+	GPIO_FN(VIO_D9),
+	GPIO_FN(VIO_D8),
+	GPIO_FN(VIO_D7),
+	GPIO_FN(VIO_D6),
+	GPIO_FN(VIO_D5),
+	GPIO_FN(VIO_D4),
+	GPIO_FN(VIO_D3),
+	GPIO_FN(VIO_D2),
+	GPIO_FN(VIO_D1),
+	GPIO_FN(VIO_D0),
+	GPIO_FN(VIO_CLK1),
+	GPIO_FN(VIO_VD1),
+	GPIO_FN(VIO_HD1),
+	GPIO_FN(VIO_FLD),
+	GPIO_FN(VIO_CKO),
+	GPIO_FN(VIO_VD2),
+	GPIO_FN(VIO_HD2),
+	GPIO_FN(VIO_CLK2),
 
 	/* LCDC */
-	PINMUX_GPIO(GPIO_FN_LCDD23, LCDD23_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD22, LCDD22_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD21, LCDD21_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD20, LCDD20_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD19, LCDD19_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD18, LCDD18_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD17, LCDD17_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD16, LCDD16_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD15, LCDD15_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD14, LCDD14_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD13, LCDD13_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD12, LCDD12_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD11, LCDD11_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD10, LCDD10_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD9, LCDD9_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD8, LCDD8_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD7, LCDD7_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD6, LCDD6_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD5, LCDD5_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD4, LCDD4_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD3, LCDD3_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD2, LCDD2_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD1, LCDD1_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD0, LCDD0_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDLCLK_PTR, LCDLCLK_PTR_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDLCLK_PTW, LCDLCLK_PTW_MARK),
+	GPIO_FN(LCDD23),
+	GPIO_FN(LCDD22),
+	GPIO_FN(LCDD21),
+	GPIO_FN(LCDD20),
+	GPIO_FN(LCDD19),
+	GPIO_FN(LCDD18),
+	GPIO_FN(LCDD17),
+	GPIO_FN(LCDD16),
+	GPIO_FN(LCDD15),
+	GPIO_FN(LCDD14),
+	GPIO_FN(LCDD13),
+	GPIO_FN(LCDD12),
+	GPIO_FN(LCDD11),
+	GPIO_FN(LCDD10),
+	GPIO_FN(LCDD9),
+	GPIO_FN(LCDD8),
+	GPIO_FN(LCDD7),
+	GPIO_FN(LCDD6),
+	GPIO_FN(LCDD5),
+	GPIO_FN(LCDD4),
+	GPIO_FN(LCDD3),
+	GPIO_FN(LCDD2),
+	GPIO_FN(LCDD1),
+	GPIO_FN(LCDD0),
+	GPIO_FN(LCDLCLK_PTR),
+	GPIO_FN(LCDLCLK_PTW),
 	/* Main LCD */
-	PINMUX_GPIO(GPIO_FN_LCDDON, LCDDON_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDVCPWC, LCDVCPWC_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDVEPWC, LCDVEPWC_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDVSYN, LCDVSYN_MARK),
+	GPIO_FN(LCDDON),
+	GPIO_FN(LCDVCPWC),
+	GPIO_FN(LCDVEPWC),
+	GPIO_FN(LCDVSYN),
 	/* Main LCD - RGB Mode */
-	PINMUX_GPIO(GPIO_FN_LCDDCK, LCDDCK_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDHSYN, LCDHSYN_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDDISP, LCDDISP_MARK),
+	GPIO_FN(LCDDCK),
+	GPIO_FN(LCDHSYN),
+	GPIO_FN(LCDDISP),
 	/* Main LCD - SYS Mode */
-	PINMUX_GPIO(GPIO_FN_LCDRS, LCDRS_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDCS, LCDCS_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDWR, LCDWR_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDRD, LCDRD_MARK),
+	GPIO_FN(LCDRS),
+	GPIO_FN(LCDCS),
+	GPIO_FN(LCDWR),
+	GPIO_FN(LCDRD),
 
 	/* IRQ */
-	PINMUX_GPIO(GPIO_FN_IRQ0, IRQ0_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ1, IRQ1_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ2, IRQ2_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ3, IRQ3_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ4, IRQ4_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ5, IRQ5_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ6, IRQ6_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ7, IRQ7_MARK),
+	GPIO_FN(IRQ0),
+	GPIO_FN(IRQ1),
+	GPIO_FN(IRQ2),
+	GPIO_FN(IRQ3),
+	GPIO_FN(IRQ4),
+	GPIO_FN(IRQ5),
+	GPIO_FN(IRQ6),
+	GPIO_FN(IRQ7),
 
 	/* AUD */
-	PINMUX_GPIO(GPIO_FN_AUDCK, AUDCK_MARK),
-	PINMUX_GPIO(GPIO_FN_AUDSYNC, AUDSYNC_MARK),
-	PINMUX_GPIO(GPIO_FN_AUDATA3, AUDATA3_MARK),
-	PINMUX_GPIO(GPIO_FN_AUDATA2, AUDATA2_MARK),
-	PINMUX_GPIO(GPIO_FN_AUDATA1, AUDATA1_MARK),
-	PINMUX_GPIO(GPIO_FN_AUDATA0, AUDATA0_MARK),
+	GPIO_FN(AUDCK),
+	GPIO_FN(AUDSYNC),
+	GPIO_FN(AUDATA3),
+	GPIO_FN(AUDATA2),
+	GPIO_FN(AUDATA1),
+	GPIO_FN(AUDATA0),
 
 	/* SDHI0 (PTD) */
-	PINMUX_GPIO(GPIO_FN_SDHI0CD_PTD, SDHI0CD_PTD_MARK),
-	PINMUX_GPIO(GPIO_FN_SDHI0WP_PTD, SDHI0WP_PTD_MARK),
-	PINMUX_GPIO(GPIO_FN_SDHI0D3_PTD, SDHI0D3_PTD_MARK),
-	PINMUX_GPIO(GPIO_FN_SDHI0D2_PTD, SDHI0D2_PTD_MARK),
-	PINMUX_GPIO(GPIO_FN_SDHI0D1_PTD, SDHI0D1_PTD_MARK),
-	PINMUX_GPIO(GPIO_FN_SDHI0D0_PTD, SDHI0D0_PTD_MARK),
-	PINMUX_GPIO(GPIO_FN_SDHI0CMD_PTD, SDHI0CMD_PTD_MARK),
-	PINMUX_GPIO(GPIO_FN_SDHI0CLK_PTD, SDHI0CLK_PTD_MARK),
+	GPIO_FN(SDHI0CD_PTD),
+	GPIO_FN(SDHI0WP_PTD),
+	GPIO_FN(SDHI0D3_PTD),
+	GPIO_FN(SDHI0D2_PTD),
+	GPIO_FN(SDHI0D1_PTD),
+	GPIO_FN(SDHI0D0_PTD),
+	GPIO_FN(SDHI0CMD_PTD),
+	GPIO_FN(SDHI0CLK_PTD),
 
 	/* SDHI0 (PTS) */
-	PINMUX_GPIO(GPIO_FN_SDHI0CD_PTS, SDHI0CD_PTS_MARK),
-	PINMUX_GPIO(GPIO_FN_SDHI0WP_PTS, SDHI0WP_PTS_MARK),
-	PINMUX_GPIO(GPIO_FN_SDHI0D3_PTS, SDHI0D3_PTS_MARK),
-	PINMUX_GPIO(GPIO_FN_SDHI0D2_PTS, SDHI0D2_PTS_MARK),
-	PINMUX_GPIO(GPIO_FN_SDHI0D1_PTS, SDHI0D1_PTS_MARK),
-	PINMUX_GPIO(GPIO_FN_SDHI0D0_PTS, SDHI0D0_PTS_MARK),
-	PINMUX_GPIO(GPIO_FN_SDHI0CMD_PTS, SDHI0CMD_PTS_MARK),
-	PINMUX_GPIO(GPIO_FN_SDHI0CLK_PTS, SDHI0CLK_PTS_MARK),
+	GPIO_FN(SDHI0CD_PTS),
+	GPIO_FN(SDHI0WP_PTS),
+	GPIO_FN(SDHI0D3_PTS),
+	GPIO_FN(SDHI0D2_PTS),
+	GPIO_FN(SDHI0D1_PTS),
+	GPIO_FN(SDHI0D0_PTS),
+	GPIO_FN(SDHI0CMD_PTS),
+	GPIO_FN(SDHI0CLK_PTS),
 
 	/* SDHI1 */
-	PINMUX_GPIO(GPIO_FN_SDHI1CD, SDHI1CD_MARK),
-	PINMUX_GPIO(GPIO_FN_SDHI1WP, SDHI1WP_MARK),
-	PINMUX_GPIO(GPIO_FN_SDHI1D3, SDHI1D3_MARK),
-	PINMUX_GPIO(GPIO_FN_SDHI1D2, SDHI1D2_MARK),
-	PINMUX_GPIO(GPIO_FN_SDHI1D1, SDHI1D1_MARK),
-	PINMUX_GPIO(GPIO_FN_SDHI1D0, SDHI1D0_MARK),
-	PINMUX_GPIO(GPIO_FN_SDHI1CMD, SDHI1CMD_MARK),
-	PINMUX_GPIO(GPIO_FN_SDHI1CLK, SDHI1CLK_MARK),
+	GPIO_FN(SDHI1CD),
+	GPIO_FN(SDHI1WP),
+	GPIO_FN(SDHI1D3),
+	GPIO_FN(SDHI1D2),
+	GPIO_FN(SDHI1D1),
+	GPIO_FN(SDHI1D0),
+	GPIO_FN(SDHI1CMD),
+	GPIO_FN(SDHI1CLK),
 
 	/* SIUA */
-	PINMUX_GPIO(GPIO_FN_SIUAFCK, SIUAFCK_MARK),
-	PINMUX_GPIO(GPIO_FN_SIUAILR, SIUAILR_MARK),
-	PINMUX_GPIO(GPIO_FN_SIUAIBT, SIUAIBT_MARK),
-	PINMUX_GPIO(GPIO_FN_SIUAISLD, SIUAISLD_MARK),
-	PINMUX_GPIO(GPIO_FN_SIUAOLR, SIUAOLR_MARK),
-	PINMUX_GPIO(GPIO_FN_SIUAOBT, SIUAOBT_MARK),
-	PINMUX_GPIO(GPIO_FN_SIUAOSLD, SIUAOSLD_MARK),
-	PINMUX_GPIO(GPIO_FN_SIUAMCK, SIUAMCK_MARK),
-	PINMUX_GPIO(GPIO_FN_SIUAISPD, SIUAISPD_MARK),
-	PINMUX_GPIO(GPIO_FN_SIUAOSPD, SIUAOSPD_MARK),
+	GPIO_FN(SIUAFCK),
+	GPIO_FN(SIUAILR),
+	GPIO_FN(SIUAIBT),
+	GPIO_FN(SIUAISLD),
+	GPIO_FN(SIUAOLR),
+	GPIO_FN(SIUAOBT),
+	GPIO_FN(SIUAOSLD),
+	GPIO_FN(SIUAMCK),
+	GPIO_FN(SIUAISPD),
+	GPIO_FN(SIUAOSPD),
 
 	/* SIUB */
-	PINMUX_GPIO(GPIO_FN_SIUBFCK, SIUBFCK_MARK),
-	PINMUX_GPIO(GPIO_FN_SIUBILR, SIUBILR_MARK),
-	PINMUX_GPIO(GPIO_FN_SIUBIBT, SIUBIBT_MARK),
-	PINMUX_GPIO(GPIO_FN_SIUBISLD, SIUBISLD_MARK),
-	PINMUX_GPIO(GPIO_FN_SIUBOLR, SIUBOLR_MARK),
-	PINMUX_GPIO(GPIO_FN_SIUBOBT, SIUBOBT_MARK),
-	PINMUX_GPIO(GPIO_FN_SIUBOSLD, SIUBOSLD_MARK),
-	PINMUX_GPIO(GPIO_FN_SIUBMCK, SIUBMCK_MARK),
+	GPIO_FN(SIUBFCK),
+	GPIO_FN(SIUBILR),
+	GPIO_FN(SIUBIBT),
+	GPIO_FN(SIUBISLD),
+	GPIO_FN(SIUBOLR),
+	GPIO_FN(SIUBOBT),
+	GPIO_FN(SIUBOSLD),
+	GPIO_FN(SIUBMCK),
 
 	/* IRDA */
-	PINMUX_GPIO(GPIO_FN_IRDA_IN, IRDA_IN_MARK),
-	PINMUX_GPIO(GPIO_FN_IRDA_OUT, IRDA_OUT_MARK),
+	GPIO_FN(IRDA_IN),
+	GPIO_FN(IRDA_OUT),
 
 	/* VOU */
-	PINMUX_GPIO(GPIO_FN_DV_CLKI, DV_CLKI_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_CLK, DV_CLK_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_HSYNC, DV_HSYNC_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_VSYNC, DV_VSYNC_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_D15, DV_D15_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_D14, DV_D14_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_D13, DV_D13_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_D12, DV_D12_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_D11, DV_D11_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_D10, DV_D10_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_D9, DV_D9_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_D8, DV_D8_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_D7, DV_D7_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_D6, DV_D6_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_D5, DV_D5_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_D4, DV_D4_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_D3, DV_D3_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_D2, DV_D2_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_D1, DV_D1_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_D0, DV_D0_MARK),
+	GPIO_FN(DV_CLKI),
+	GPIO_FN(DV_CLK),
+	GPIO_FN(DV_HSYNC),
+	GPIO_FN(DV_VSYNC),
+	GPIO_FN(DV_D15),
+	GPIO_FN(DV_D14),
+	GPIO_FN(DV_D13),
+	GPIO_FN(DV_D12),
+	GPIO_FN(DV_D11),
+	GPIO_FN(DV_D10),
+	GPIO_FN(DV_D9),
+	GPIO_FN(DV_D8),
+	GPIO_FN(DV_D7),
+	GPIO_FN(DV_D6),
+	GPIO_FN(DV_D5),
+	GPIO_FN(DV_D4),
+	GPIO_FN(DV_D3),
+	GPIO_FN(DV_D2),
+	GPIO_FN(DV_D1),
+	GPIO_FN(DV_D0),
 
 	/* KEYSC */
-	PINMUX_GPIO(GPIO_FN_KEYIN0, KEYIN0_MARK),
-	PINMUX_GPIO(GPIO_FN_KEYIN1, KEYIN1_MARK),
-	PINMUX_GPIO(GPIO_FN_KEYIN2, KEYIN2_MARK),
-	PINMUX_GPIO(GPIO_FN_KEYIN3, KEYIN3_MARK),
-	PINMUX_GPIO(GPIO_FN_KEYIN4, KEYIN4_MARK),
-	PINMUX_GPIO(GPIO_FN_KEYOUT0, KEYOUT0_MARK),
-	PINMUX_GPIO(GPIO_FN_KEYOUT1, KEYOUT1_MARK),
-	PINMUX_GPIO(GPIO_FN_KEYOUT2, KEYOUT2_MARK),
-	PINMUX_GPIO(GPIO_FN_KEYOUT3, KEYOUT3_MARK),
-	PINMUX_GPIO(GPIO_FN_KEYOUT4_IN6, KEYOUT4_IN6_MARK),
-	PINMUX_GPIO(GPIO_FN_KEYOUT5_IN5, KEYOUT5_IN5_MARK),
+	GPIO_FN(KEYIN0),
+	GPIO_FN(KEYIN1),
+	GPIO_FN(KEYIN2),
+	GPIO_FN(KEYIN3),
+	GPIO_FN(KEYIN4),
+	GPIO_FN(KEYOUT0),
+	GPIO_FN(KEYOUT1),
+	GPIO_FN(KEYOUT2),
+	GPIO_FN(KEYOUT3),
+	GPIO_FN(KEYOUT4_IN6),
+	GPIO_FN(KEYOUT5_IN5),
 
 	/* MSIOF0 (PTF) */
-	PINMUX_GPIO(GPIO_FN_MSIOF0_PTF_TXD, MSIOF0_PTF_TXD_MARK),
-	PINMUX_GPIO(GPIO_FN_MSIOF0_PTF_RXD, MSIOF0_PTF_RXD_MARK),
-	PINMUX_GPIO(GPIO_FN_MSIOF0_PTF_MCK, MSIOF0_PTF_MCK_MARK),
-	PINMUX_GPIO(GPIO_FN_MSIOF0_PTF_TSYNC, MSIOF0_PTF_TSYNC_MARK),
-	PINMUX_GPIO(GPIO_FN_MSIOF0_PTF_TSCK, MSIOF0_PTF_TSCK_MARK),
-	PINMUX_GPIO(GPIO_FN_MSIOF0_PTF_RSYNC, MSIOF0_PTF_RSYNC_MARK),
-	PINMUX_GPIO(GPIO_FN_MSIOF0_PTF_RSCK, MSIOF0_PTF_RSCK_MARK),
-	PINMUX_GPIO(GPIO_FN_MSIOF0_PTF_SS1, MSIOF0_PTF_SS1_MARK),
-	PINMUX_GPIO(GPIO_FN_MSIOF0_PTF_SS2, MSIOF0_PTF_SS2_MARK),
+	GPIO_FN(MSIOF0_PTF_TXD),
+	GPIO_FN(MSIOF0_PTF_RXD),
+	GPIO_FN(MSIOF0_PTF_MCK),
+	GPIO_FN(MSIOF0_PTF_TSYNC),
+	GPIO_FN(MSIOF0_PTF_TSCK),
+	GPIO_FN(MSIOF0_PTF_RSYNC),
+	GPIO_FN(MSIOF0_PTF_RSCK),
+	GPIO_FN(MSIOF0_PTF_SS1),
+	GPIO_FN(MSIOF0_PTF_SS2),
 
 	/* MSIOF0 (PTT+PTX) */
-	PINMUX_GPIO(GPIO_FN_MSIOF0_PTT_TXD, MSIOF0_PTT_TXD_MARK),
-	PINMUX_GPIO(GPIO_FN_MSIOF0_PTT_RXD, MSIOF0_PTT_RXD_MARK),
-	PINMUX_GPIO(GPIO_FN_MSIOF0_PTX_MCK, MSIOF0_PTX_MCK_MARK),
-	PINMUX_GPIO(GPIO_FN_MSIOF0_PTT_TSYNC, MSIOF0_PTT_TSYNC_MARK),
-	PINMUX_GPIO(GPIO_FN_MSIOF0_PTT_TSCK, MSIOF0_PTT_TSCK_MARK),
-	PINMUX_GPIO(GPIO_FN_MSIOF0_PTT_RSYNC, MSIOF0_PTT_RSYNC_MARK),
-	PINMUX_GPIO(GPIO_FN_MSIOF0_PTT_RSCK, MSIOF0_PTT_RSCK_MARK),
-	PINMUX_GPIO(GPIO_FN_MSIOF0_PTT_SS1, MSIOF0_PTT_SS1_MARK),
-	PINMUX_GPIO(GPIO_FN_MSIOF0_PTT_SS2, MSIOF0_PTT_SS2_MARK),
+	GPIO_FN(MSIOF0_PTT_TXD),
+	GPIO_FN(MSIOF0_PTT_RXD),
+	GPIO_FN(MSIOF0_PTX_MCK),
+	GPIO_FN(MSIOF0_PTT_TSYNC),
+	GPIO_FN(MSIOF0_PTT_TSCK),
+	GPIO_FN(MSIOF0_PTT_RSYNC),
+	GPIO_FN(MSIOF0_PTT_RSCK),
+	GPIO_FN(MSIOF0_PTT_SS1),
+	GPIO_FN(MSIOF0_PTT_SS2),
 
 	/* MSIOF1 */
-	PINMUX_GPIO(GPIO_FN_MSIOF1_TXD, MSIOF1_TXD_MARK),
-	PINMUX_GPIO(GPIO_FN_MSIOF1_RXD, MSIOF1_RXD_MARK),
-	PINMUX_GPIO(GPIO_FN_MSIOF1_MCK, MSIOF1_MCK_MARK),
-	PINMUX_GPIO(GPIO_FN_MSIOF1_TSYNC, MSIOF1_TSYNC_MARK),
-	PINMUX_GPIO(GPIO_FN_MSIOF1_TSCK, MSIOF1_TSCK_MARK),
-	PINMUX_GPIO(GPIO_FN_MSIOF1_RSYNC, MSIOF1_RSYNC_MARK),
-	PINMUX_GPIO(GPIO_FN_MSIOF1_RSCK, MSIOF1_RSCK_MARK),
-	PINMUX_GPIO(GPIO_FN_MSIOF1_SS1, MSIOF1_SS1_MARK),
-	PINMUX_GPIO(GPIO_FN_MSIOF1_SS2, MSIOF1_SS2_MARK),
+	GPIO_FN(MSIOF1_TXD),
+	GPIO_FN(MSIOF1_RXD),
+	GPIO_FN(MSIOF1_MCK),
+	GPIO_FN(MSIOF1_TSYNC),
+	GPIO_FN(MSIOF1_TSCK),
+	GPIO_FN(MSIOF1_RSYNC),
+	GPIO_FN(MSIOF1_RSCK),
+	GPIO_FN(MSIOF1_SS1),
+	GPIO_FN(MSIOF1_SS2),
 
 	/* TSIF */
-	PINMUX_GPIO(GPIO_FN_TS0_SDAT, TS0_SDAT_MARK),
-	PINMUX_GPIO(GPIO_FN_TS0_SCK, TS0_SCK_MARK),
-	PINMUX_GPIO(GPIO_FN_TS0_SDEN, TS0_SDEN_MARK),
-	PINMUX_GPIO(GPIO_FN_TS0_SPSYNC, TS0_SPSYNC_MARK),
+	GPIO_FN(TS0_SDAT),
+	GPIO_FN(TS0_SCK),
+	GPIO_FN(TS0_SDEN),
+	GPIO_FN(TS0_SPSYNC),
 
 	/* FLCTL */
-	PINMUX_GPIO(GPIO_FN_FCE, FCE_MARK),
-	PINMUX_GPIO(GPIO_FN_NAF7, NAF7_MARK),
-	PINMUX_GPIO(GPIO_FN_NAF6, NAF6_MARK),
-	PINMUX_GPIO(GPIO_FN_NAF5, NAF5_MARK),
-	PINMUX_GPIO(GPIO_FN_NAF4, NAF4_MARK),
-	PINMUX_GPIO(GPIO_FN_NAF3, NAF3_MARK),
-	PINMUX_GPIO(GPIO_FN_NAF2, NAF2_MARK),
-	PINMUX_GPIO(GPIO_FN_NAF1, NAF1_MARK),
-	PINMUX_GPIO(GPIO_FN_NAF0, NAF0_MARK),
-	PINMUX_GPIO(GPIO_FN_FCDE, FCDE_MARK),
-	PINMUX_GPIO(GPIO_FN_FOE, FOE_MARK),
-	PINMUX_GPIO(GPIO_FN_FSC, FSC_MARK),
-	PINMUX_GPIO(GPIO_FN_FWE, FWE_MARK),
-	PINMUX_GPIO(GPIO_FN_FRB, FRB_MARK),
+	GPIO_FN(FCE),
+	GPIO_FN(NAF7),
+	GPIO_FN(NAF6),
+	GPIO_FN(NAF5),
+	GPIO_FN(NAF4),
+	GPIO_FN(NAF3),
+	GPIO_FN(NAF2),
+	GPIO_FN(NAF1),
+	GPIO_FN(NAF0),
+	GPIO_FN(FCDE),
+	GPIO_FN(FOE),
+	GPIO_FN(FSC),
+	GPIO_FN(FWE),
+	GPIO_FN(FRB),
 
 	/* DMAC */
-	PINMUX_GPIO(GPIO_FN_DACK1, DACK1_MARK),
-	PINMUX_GPIO(GPIO_FN_DREQ1, DREQ1_MARK),
-	PINMUX_GPIO(GPIO_FN_DACK0, DACK0_MARK),
-	PINMUX_GPIO(GPIO_FN_DREQ0, DREQ0_MARK),
+	GPIO_FN(DACK1),
+	GPIO_FN(DREQ1),
+	GPIO_FN(DACK0),
+	GPIO_FN(DREQ0),
 
 	/* ADC */
-	PINMUX_GPIO(GPIO_FN_AN3, AN3_MARK),
-	PINMUX_GPIO(GPIO_FN_AN2, AN2_MARK),
-	PINMUX_GPIO(GPIO_FN_AN1, AN1_MARK),
-	PINMUX_GPIO(GPIO_FN_AN0, AN0_MARK),
-	PINMUX_GPIO(GPIO_FN_ADTRG, ADTRG_MARK),
+	GPIO_FN(AN3),
+	GPIO_FN(AN2),
+	GPIO_FN(AN1),
+	GPIO_FN(AN0),
+	GPIO_FN(ADTRG),
 
 	/* CPG */
-	PINMUX_GPIO(GPIO_FN_STATUS0, STATUS0_MARK),
-	PINMUX_GPIO(GPIO_FN_PDSTATUS, PDSTATUS_MARK),
+	GPIO_FN(STATUS0),
+	GPIO_FN(PDSTATUS),
 
 	/* TPU */
-	PINMUX_GPIO(GPIO_FN_TPUTO0, TPUTO0_MARK),
-	PINMUX_GPIO(GPIO_FN_TPUTO1, TPUTO1_MARK),
-	PINMUX_GPIO(GPIO_FN_TPUTO2, TPUTO2_MARK),
-	PINMUX_GPIO(GPIO_FN_TPUTO3, TPUTO3_MARK),
+	GPIO_FN(TPUTO0),
+	GPIO_FN(TPUTO1),
+	GPIO_FN(TPUTO2),
+	GPIO_FN(TPUTO3),
 
 	/* BSC */
-	PINMUX_GPIO(GPIO_FN_D31, D31_MARK),
-	PINMUX_GPIO(GPIO_FN_D30, D30_MARK),
-	PINMUX_GPIO(GPIO_FN_D29, D29_MARK),
-	PINMUX_GPIO(GPIO_FN_D28, D28_MARK),
-	PINMUX_GPIO(GPIO_FN_D27, D27_MARK),
-	PINMUX_GPIO(GPIO_FN_D26, D26_MARK),
-	PINMUX_GPIO(GPIO_FN_D25, D25_MARK),
-	PINMUX_GPIO(GPIO_FN_D24, D24_MARK),
-	PINMUX_GPIO(GPIO_FN_D23, D23_MARK),
-	PINMUX_GPIO(GPIO_FN_D22, D22_MARK),
-	PINMUX_GPIO(GPIO_FN_D21, D21_MARK),
-	PINMUX_GPIO(GPIO_FN_D20, D20_MARK),
-	PINMUX_GPIO(GPIO_FN_D19, D19_MARK),
-	PINMUX_GPIO(GPIO_FN_D18, D18_MARK),
-	PINMUX_GPIO(GPIO_FN_D17, D17_MARK),
-	PINMUX_GPIO(GPIO_FN_D16, D16_MARK),
-	PINMUX_GPIO(GPIO_FN_IOIS16, IOIS16_MARK),
-	PINMUX_GPIO(GPIO_FN_WAIT, WAIT_MARK),
-	PINMUX_GPIO(GPIO_FN_BS, BS_MARK),
-	PINMUX_GPIO(GPIO_FN_A25, A25_MARK),
-	PINMUX_GPIO(GPIO_FN_A24, A24_MARK),
-	PINMUX_GPIO(GPIO_FN_A23, A23_MARK),
-	PINMUX_GPIO(GPIO_FN_A22, A22_MARK),
-	PINMUX_GPIO(GPIO_FN_CS6B_CE1B, CS6B_CE1B_MARK),
-	PINMUX_GPIO(GPIO_FN_CS6A_CE2B, CS6A_CE2B_MARK),
-	PINMUX_GPIO(GPIO_FN_CS5B_CE1A, CS5B_CE1A_MARK),
-	PINMUX_GPIO(GPIO_FN_CS5A_CE2A, CS5A_CE2A_MARK),
-	PINMUX_GPIO(GPIO_FN_WE3_ICIOWR, WE3_ICIOWR_MARK),
-	PINMUX_GPIO(GPIO_FN_WE2_ICIORD, WE2_ICIORD_MARK),
+	GPIO_FN(D31),
+	GPIO_FN(D30),
+	GPIO_FN(D29),
+	GPIO_FN(D28),
+	GPIO_FN(D27),
+	GPIO_FN(D26),
+	GPIO_FN(D25),
+	GPIO_FN(D24),
+	GPIO_FN(D23),
+	GPIO_FN(D22),
+	GPIO_FN(D21),
+	GPIO_FN(D20),
+	GPIO_FN(D19),
+	GPIO_FN(D18),
+	GPIO_FN(D17),
+	GPIO_FN(D16),
+	GPIO_FN(IOIS16),
+	GPIO_FN(WAIT),
+	GPIO_FN(BS),
+	GPIO_FN(A25),
+	GPIO_FN(A24),
+	GPIO_FN(A23),
+	GPIO_FN(A22),
+	GPIO_FN(CS6B_CE1B),
+	GPIO_FN(CS6A_CE2B),
+	GPIO_FN(CS5B_CE1A),
+	GPIO_FN(CS5A_CE2A),
+	GPIO_FN(WE3_ICIOWR),
+	GPIO_FN(WE2_ICIORD),
 
 	/* ATAPI */
-	PINMUX_GPIO(GPIO_FN_IDED15, IDED15_MARK),
-	PINMUX_GPIO(GPIO_FN_IDED14, IDED14_MARK),
-	PINMUX_GPIO(GPIO_FN_IDED13, IDED13_MARK),
-	PINMUX_GPIO(GPIO_FN_IDED12, IDED12_MARK),
-	PINMUX_GPIO(GPIO_FN_IDED11, IDED11_MARK),
-	PINMUX_GPIO(GPIO_FN_IDED10, IDED10_MARK),
-	PINMUX_GPIO(GPIO_FN_IDED9, IDED9_MARK),
-	PINMUX_GPIO(GPIO_FN_IDED8, IDED8_MARK),
-	PINMUX_GPIO(GPIO_FN_IDED7, IDED7_MARK),
-	PINMUX_GPIO(GPIO_FN_IDED6, IDED6_MARK),
-	PINMUX_GPIO(GPIO_FN_IDED5, IDED5_MARK),
-	PINMUX_GPIO(GPIO_FN_IDED4, IDED4_MARK),
-	PINMUX_GPIO(GPIO_FN_IDED3, IDED3_MARK),
-	PINMUX_GPIO(GPIO_FN_IDED2, IDED2_MARK),
-	PINMUX_GPIO(GPIO_FN_IDED1, IDED1_MARK),
-	PINMUX_GPIO(GPIO_FN_IDED0, IDED0_MARK),
-	PINMUX_GPIO(GPIO_FN_DIRECTION, DIRECTION_MARK),
-	PINMUX_GPIO(GPIO_FN_EXBUF_ENB, EXBUF_ENB_MARK),
-	PINMUX_GPIO(GPIO_FN_IDERST, IDERST_MARK),
-	PINMUX_GPIO(GPIO_FN_IODACK, IODACK_MARK),
-	PINMUX_GPIO(GPIO_FN_IODREQ, IODREQ_MARK),
-	PINMUX_GPIO(GPIO_FN_IDEIORDY, IDEIORDY_MARK),
-	PINMUX_GPIO(GPIO_FN_IDEINT, IDEINT_MARK),
-	PINMUX_GPIO(GPIO_FN_IDEIOWR, IDEIOWR_MARK),
-	PINMUX_GPIO(GPIO_FN_IDEIORD, IDEIORD_MARK),
-	PINMUX_GPIO(GPIO_FN_IDECS1, IDECS1_MARK),
-	PINMUX_GPIO(GPIO_FN_IDECS0, IDECS0_MARK),
-	PINMUX_GPIO(GPIO_FN_IDEA2, IDEA2_MARK),
-	PINMUX_GPIO(GPIO_FN_IDEA1, IDEA1_MARK),
-	PINMUX_GPIO(GPIO_FN_IDEA0, IDEA0_MARK),
+	GPIO_FN(IDED15),
+	GPIO_FN(IDED14),
+	GPIO_FN(IDED13),
+	GPIO_FN(IDED12),
+	GPIO_FN(IDED11),
+	GPIO_FN(IDED10),
+	GPIO_FN(IDED9),
+	GPIO_FN(IDED8),
+	GPIO_FN(IDED7),
+	GPIO_FN(IDED6),
+	GPIO_FN(IDED5),
+	GPIO_FN(IDED4),
+	GPIO_FN(IDED3),
+	GPIO_FN(IDED2),
+	GPIO_FN(IDED1),
+	GPIO_FN(IDED0),
+	GPIO_FN(DIRECTION),
+	GPIO_FN(EXBUF_ENB),
+	GPIO_FN(IDERST),
+	GPIO_FN(IODACK),
+	GPIO_FN(IODREQ),
+	GPIO_FN(IDEIORDY),
+	GPIO_FN(IDEINT),
+	GPIO_FN(IDEIOWR),
+	GPIO_FN(IDEIORD),
+	GPIO_FN(IDECS1),
+	GPIO_FN(IDECS0),
+	GPIO_FN(IDEA2),
+	GPIO_FN(IDEA1),
+	GPIO_FN(IDEA0),
 };
 
-static struct pinmux_cfg_reg pinmux_config_regs[] = {
+static const struct pinmux_cfg_reg pinmux_config_regs[] = {
 	{ PINMUX_CFG_REG("PACR", 0xa4050100, 16, 2) {
 		PTA7_FN, PTA7_OUT, 0, PTA7_IN,
 		PTA6_FN, PTA6_OUT, 0, PTA6_IN,
@@ -1785,7 +1789,7 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = {
 	{}
 };
 
-static struct pinmux_data_reg pinmux_data_regs[] = {
+static const struct pinmux_data_reg pinmux_data_regs[] = {
 	{ PINMUX_DATA_REG("PADR", 0xa4050120, 8) {
 		PTA7_DATA, PTA6_DATA, PTA5_DATA, PTA4_DATA,
 		PTA3_DATA, PTA2_DATA, PTA1_DATA, PTA0_DATA }
@@ -1881,20 +1885,18 @@ static struct pinmux_data_reg pinmux_data_regs[] = {
 	{ },
 };
 
-struct sh_pfc_soc_info sh7723_pinmux_info = {
+const struct sh_pfc_soc_info sh7723_pinmux_info = {
 	.name = "sh7723_pfc",
-	.reserved_id = PINMUX_RESERVED,
-	.data = { PINMUX_DATA_BEGIN, PINMUX_DATA_END },
 	.input = { PINMUX_INPUT_BEGIN, PINMUX_INPUT_END },
 	.input_pu = { PINMUX_INPUT_PULLUP_BEGIN, PINMUX_INPUT_PULLUP_END },
 	.output = { PINMUX_OUTPUT_BEGIN, PINMUX_OUTPUT_END },
-	.mark = { PINMUX_MARK_BEGIN, PINMUX_MARK_END },
 	.function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END },
 
-	.first_gpio = GPIO_PTA7,
-	.last_gpio = GPIO_FN_IDEA0,
+	.pins = pinmux_pins,
+	.nr_pins = ARRAY_SIZE(pinmux_pins),
+	.func_gpios = pinmux_func_gpios,
+	.nr_func_gpios = ARRAY_SIZE(pinmux_func_gpios),
 
-	.gpios = pinmux_gpios,
 	.cfg_regs = pinmux_config_regs,
 	.data_regs = pinmux_data_regs,
 
diff --git a/drivers/pinctrl/sh-pfc/pfc-sh7724.c b/drivers/pinctrl/sh-pfc/pfc-sh7724.c
index 233fbf7..35e5516 100644
--- a/drivers/pinctrl/sh-pfc/pfc-sh7724.c
+++ b/drivers/pinctrl/sh-pfc/pfc-sh7724.c
@@ -572,7 +572,7 @@ enum {
 	PINMUX_MARK_END,
 };
 
-static pinmux_enum_t pinmux_data[] = {
+static const pinmux_enum_t pinmux_data[] = {
 	/* PTA GPIO */
 	PINMUX_DATA(PTA7_DATA, PTA7_IN, PTA7_OUT, PTA7_IN_PU),
 	PINMUX_DATA(PTA6_DATA, PTA6_IN, PTA6_OUT, PTA6_IN_PU),
@@ -1192,7 +1192,7 @@ static pinmux_enum_t pinmux_data[] = {
 	PINMUX_DATA(SCIF3_I_TXD_MARK,	PSB14_1, PTZ3_FN),
 };
 
-static struct pinmux_gpio pinmux_gpios[] = {
+static struct sh_pfc_pin pinmux_pins[] = {
 	/* PTA */
 	PINMUX_GPIO(GPIO_PTA7, PTA7_DATA),
 	PINMUX_GPIO(GPIO_PTA6, PTA6_DATA),
@@ -1418,372 +1418,376 @@ static struct pinmux_gpio pinmux_gpios[] = {
 	PINMUX_GPIO(GPIO_PTZ2, PTZ2_DATA),
 	PINMUX_GPIO(GPIO_PTZ1, PTZ1_DATA),
 	PINMUX_GPIO(GPIO_PTZ0, PTZ0_DATA),
+};
+
+#define PINMUX_FN_BASE	ARRAY_SIZE(pinmux_pins)
 
+static const struct pinmux_func pinmux_func_gpios[] = {
 	/* BSC */
-	PINMUX_GPIO(GPIO_FN_D31,	D31_MARK),
-	PINMUX_GPIO(GPIO_FN_D30,	D30_MARK),
-	PINMUX_GPIO(GPIO_FN_D29,	D29_MARK),
-	PINMUX_GPIO(GPIO_FN_D28,	D28_MARK),
-	PINMUX_GPIO(GPIO_FN_D27,	D27_MARK),
-	PINMUX_GPIO(GPIO_FN_D26,	D26_MARK),
-	PINMUX_GPIO(GPIO_FN_D25,	D25_MARK),
-	PINMUX_GPIO(GPIO_FN_D24,	D24_MARK),
-	PINMUX_GPIO(GPIO_FN_D23,	D23_MARK),
-	PINMUX_GPIO(GPIO_FN_D22,	D22_MARK),
-	PINMUX_GPIO(GPIO_FN_D21,	D21_MARK),
-	PINMUX_GPIO(GPIO_FN_D20,	D20_MARK),
-	PINMUX_GPIO(GPIO_FN_D19,	D19_MARK),
-	PINMUX_GPIO(GPIO_FN_D18,	D18_MARK),
-	PINMUX_GPIO(GPIO_FN_D17,	D17_MARK),
-	PINMUX_GPIO(GPIO_FN_D16,	D16_MARK),
-	PINMUX_GPIO(GPIO_FN_D15,	D15_MARK),
-	PINMUX_GPIO(GPIO_FN_D14,	D14_MARK),
-	PINMUX_GPIO(GPIO_FN_D13,	D13_MARK),
-	PINMUX_GPIO(GPIO_FN_D12,	D12_MARK),
-	PINMUX_GPIO(GPIO_FN_D11,	D11_MARK),
-	PINMUX_GPIO(GPIO_FN_D10,	D10_MARK),
-	PINMUX_GPIO(GPIO_FN_D9,		D9_MARK),
-	PINMUX_GPIO(GPIO_FN_D8,		D8_MARK),
-	PINMUX_GPIO(GPIO_FN_D7,		D7_MARK),
-	PINMUX_GPIO(GPIO_FN_D6,		D6_MARK),
-	PINMUX_GPIO(GPIO_FN_D5,		D5_MARK),
-	PINMUX_GPIO(GPIO_FN_D4,		D4_MARK),
-	PINMUX_GPIO(GPIO_FN_D3,		D3_MARK),
-	PINMUX_GPIO(GPIO_FN_D2,		D2_MARK),
-	PINMUX_GPIO(GPIO_FN_D1,		D1_MARK),
-	PINMUX_GPIO(GPIO_FN_D0,		D0_MARK),
-	PINMUX_GPIO(GPIO_FN_A25,	A25_MARK),
-	PINMUX_GPIO(GPIO_FN_A24,	A24_MARK),
-	PINMUX_GPIO(GPIO_FN_A23,	A23_MARK),
-	PINMUX_GPIO(GPIO_FN_A22,	A22_MARK),
-	PINMUX_GPIO(GPIO_FN_CS6B_CE1B,	CS6B_CE1B_MARK),
-	PINMUX_GPIO(GPIO_FN_CS6A_CE2B,	CS6A_CE2B_MARK),
-	PINMUX_GPIO(GPIO_FN_CS5B_CE1A,	CS5B_CE1A_MARK),
-	PINMUX_GPIO(GPIO_FN_CS5A_CE2A,	CS5A_CE2A_MARK),
-	PINMUX_GPIO(GPIO_FN_WE3_ICIOWR,	WE3_ICIOWR_MARK),
-	PINMUX_GPIO(GPIO_FN_WE2_ICIORD,	WE2_ICIORD_MARK),
-	PINMUX_GPIO(GPIO_FN_IOIS16,	IOIS16_MARK),
-	PINMUX_GPIO(GPIO_FN_WAIT,	WAIT_MARK),
-	PINMUX_GPIO(GPIO_FN_BS,		BS_MARK),
+	GPIO_FN(D31),
+	GPIO_FN(D30),
+	GPIO_FN(D29),
+	GPIO_FN(D28),
+	GPIO_FN(D27),
+	GPIO_FN(D26),
+	GPIO_FN(D25),
+	GPIO_FN(D24),
+	GPIO_FN(D23),
+	GPIO_FN(D22),
+	GPIO_FN(D21),
+	GPIO_FN(D20),
+	GPIO_FN(D19),
+	GPIO_FN(D18),
+	GPIO_FN(D17),
+	GPIO_FN(D16),
+	GPIO_FN(D15),
+	GPIO_FN(D14),
+	GPIO_FN(D13),
+	GPIO_FN(D12),
+	GPIO_FN(D11),
+	GPIO_FN(D10),
+	GPIO_FN(D9),
+	GPIO_FN(D8),
+	GPIO_FN(D7),
+	GPIO_FN(D6),
+	GPIO_FN(D5),
+	GPIO_FN(D4),
+	GPIO_FN(D3),
+	GPIO_FN(D2),
+	GPIO_FN(D1),
+	GPIO_FN(D0),
+	GPIO_FN(A25),
+	GPIO_FN(A24),
+	GPIO_FN(A23),
+	GPIO_FN(A22),
+	GPIO_FN(CS6B_CE1B),
+	GPIO_FN(CS6A_CE2B),
+	GPIO_FN(CS5B_CE1A),
+	GPIO_FN(CS5A_CE2A),
+	GPIO_FN(WE3_ICIOWR),
+	GPIO_FN(WE2_ICIORD),
+	GPIO_FN(IOIS16),
+	GPIO_FN(WAIT),
+	GPIO_FN(BS),
 
 	/* KEYSC */
-	PINMUX_GPIO(GPIO_FN_KEYOUT5_IN5,	KEYOUT5_IN5_MARK),
-	PINMUX_GPIO(GPIO_FN_KEYOUT4_IN6,	KEYOUT4_IN6_MARK),
-	PINMUX_GPIO(GPIO_FN_KEYIN4,		KEYIN4_MARK),
-	PINMUX_GPIO(GPIO_FN_KEYIN3,		KEYIN3_MARK),
-	PINMUX_GPIO(GPIO_FN_KEYIN2,		KEYIN2_MARK),
-	PINMUX_GPIO(GPIO_FN_KEYIN1,		KEYIN1_MARK),
-	PINMUX_GPIO(GPIO_FN_KEYIN0,		KEYIN0_MARK),
-	PINMUX_GPIO(GPIO_FN_KEYOUT3,		KEYOUT3_MARK),
-	PINMUX_GPIO(GPIO_FN_KEYOUT2,		KEYOUT2_MARK),
-	PINMUX_GPIO(GPIO_FN_KEYOUT1,		KEYOUT1_MARK),
-	PINMUX_GPIO(GPIO_FN_KEYOUT0,		KEYOUT0_MARK),
+	GPIO_FN(KEYOUT5_IN5),
+	GPIO_FN(KEYOUT4_IN6),
+	GPIO_FN(KEYIN4),
+	GPIO_FN(KEYIN3),
+	GPIO_FN(KEYIN2),
+	GPIO_FN(KEYIN1),
+	GPIO_FN(KEYIN0),
+	GPIO_FN(KEYOUT3),
+	GPIO_FN(KEYOUT2),
+	GPIO_FN(KEYOUT1),
+	GPIO_FN(KEYOUT0),
 
 	/* ATAPI */
-	PINMUX_GPIO(GPIO_FN_IDED15,	IDED15_MARK),
-	PINMUX_GPIO(GPIO_FN_IDED14,	IDED14_MARK),
-	PINMUX_GPIO(GPIO_FN_IDED13,	IDED13_MARK),
-	PINMUX_GPIO(GPIO_FN_IDED12,	IDED12_MARK),
-	PINMUX_GPIO(GPIO_FN_IDED11,	IDED11_MARK),
-	PINMUX_GPIO(GPIO_FN_IDED10,	IDED10_MARK),
-	PINMUX_GPIO(GPIO_FN_IDED9,	IDED9_MARK),
-	PINMUX_GPIO(GPIO_FN_IDED8,	IDED8_MARK),
-	PINMUX_GPIO(GPIO_FN_IDED7,	IDED7_MARK),
-	PINMUX_GPIO(GPIO_FN_IDED6,	IDED6_MARK),
-	PINMUX_GPIO(GPIO_FN_IDED5,	IDED5_MARK),
-	PINMUX_GPIO(GPIO_FN_IDED4,	IDED4_MARK),
-	PINMUX_GPIO(GPIO_FN_IDED3,	IDED3_MARK),
-	PINMUX_GPIO(GPIO_FN_IDED2,	IDED2_MARK),
-	PINMUX_GPIO(GPIO_FN_IDED1,	IDED1_MARK),
-	PINMUX_GPIO(GPIO_FN_IDED0,	IDED0_MARK),
-	PINMUX_GPIO(GPIO_FN_IDEA2,	IDEA2_MARK),
-	PINMUX_GPIO(GPIO_FN_IDEA1,	IDEA1_MARK),
-	PINMUX_GPIO(GPIO_FN_IDEA0,	IDEA0_MARK),
-	PINMUX_GPIO(GPIO_FN_IDEIOWR,	IDEIOWR_MARK),
-	PINMUX_GPIO(GPIO_FN_IODREQ,	IODREQ_MARK),
-	PINMUX_GPIO(GPIO_FN_IDECS0,	IDECS0_MARK),
-	PINMUX_GPIO(GPIO_FN_IDECS1,	IDECS1_MARK),
-	PINMUX_GPIO(GPIO_FN_IDEIORD,	IDEIORD_MARK),
-	PINMUX_GPIO(GPIO_FN_DIRECTION,	DIRECTION_MARK),
-	PINMUX_GPIO(GPIO_FN_EXBUF_ENB,	EXBUF_ENB_MARK),
-	PINMUX_GPIO(GPIO_FN_IDERST,	IDERST_MARK),
-	PINMUX_GPIO(GPIO_FN_IODACK,	IODACK_MARK),
-	PINMUX_GPIO(GPIO_FN_IDEINT,	IDEINT_MARK),
-	PINMUX_GPIO(GPIO_FN_IDEIORDY,	IDEIORDY_MARK),
+	GPIO_FN(IDED15),
+	GPIO_FN(IDED14),
+	GPIO_FN(IDED13),
+	GPIO_FN(IDED12),
+	GPIO_FN(IDED11),
+	GPIO_FN(IDED10),
+	GPIO_FN(IDED9),
+	GPIO_FN(IDED8),
+	GPIO_FN(IDED7),
+	GPIO_FN(IDED6),
+	GPIO_FN(IDED5),
+	GPIO_FN(IDED4),
+	GPIO_FN(IDED3),
+	GPIO_FN(IDED2),
+	GPIO_FN(IDED1),
+	GPIO_FN(IDED0),
+	GPIO_FN(IDEA2),
+	GPIO_FN(IDEA1),
+	GPIO_FN(IDEA0),
+	GPIO_FN(IDEIOWR),
+	GPIO_FN(IODREQ),
+	GPIO_FN(IDECS0),
+	GPIO_FN(IDECS1),
+	GPIO_FN(IDEIORD),
+	GPIO_FN(DIRECTION),
+	GPIO_FN(EXBUF_ENB),
+	GPIO_FN(IDERST),
+	GPIO_FN(IODACK),
+	GPIO_FN(IDEINT),
+	GPIO_FN(IDEIORDY),
 
 	/* TPU */
-	PINMUX_GPIO(GPIO_FN_TPUTO3,	TPUTO3_MARK),
-	PINMUX_GPIO(GPIO_FN_TPUTO2,	TPUTO2_MARK),
-	PINMUX_GPIO(GPIO_FN_TPUTO1,	TPUTO1_MARK),
-	PINMUX_GPIO(GPIO_FN_TPUTO0,	TPUTO0_MARK),
-	PINMUX_GPIO(GPIO_FN_TPUTI3,	TPUTI3_MARK),
-	PINMUX_GPIO(GPIO_FN_TPUTI2,	TPUTI2_MARK),
+	GPIO_FN(TPUTO3),
+	GPIO_FN(TPUTO2),
+	GPIO_FN(TPUTO1),
+	GPIO_FN(TPUTO0),
+	GPIO_FN(TPUTI3),
+	GPIO_FN(TPUTI2),
 
 	/* LCDC */
-	PINMUX_GPIO(GPIO_FN_LCDD23,	LCDD23_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD22,	LCDD22_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD21,	LCDD21_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD20,	LCDD20_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD19,	LCDD19_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD18,	LCDD18_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD17,	LCDD17_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD16,	LCDD16_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD15,	LCDD15_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD14,	LCDD14_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD13,	LCDD13_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD12,	LCDD12_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD11,	LCDD11_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD10,	LCDD10_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD9,	LCDD9_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD8,	LCDD8_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD7,	LCDD7_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD6,	LCDD6_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD5,	LCDD5_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD4,	LCDD4_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD3,	LCDD3_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD2,	LCDD2_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD1,	LCDD1_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDD0,	LCDD0_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDVSYN,	LCDVSYN_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDDISP,	LCDDISP_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDRS,	LCDRS_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDHSYN,	LCDHSYN_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDCS,	LCDCS_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDDON,	LCDDON_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDDCK,	LCDDCK_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDWR,	LCDWR_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDVEPWC,	LCDVEPWC_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDVCPWC,	LCDVCPWC_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDRD,	LCDRD_MARK),
-	PINMUX_GPIO(GPIO_FN_LCDLCLK,	LCDLCLK_MARK),
+	GPIO_FN(LCDD23),
+	GPIO_FN(LCDD22),
+	GPIO_FN(LCDD21),
+	GPIO_FN(LCDD20),
+	GPIO_FN(LCDD19),
+	GPIO_FN(LCDD18),
+	GPIO_FN(LCDD17),
+	GPIO_FN(LCDD16),
+	GPIO_FN(LCDD15),
+	GPIO_FN(LCDD14),
+	GPIO_FN(LCDD13),
+	GPIO_FN(LCDD12),
+	GPIO_FN(LCDD11),
+	GPIO_FN(LCDD10),
+	GPIO_FN(LCDD9),
+	GPIO_FN(LCDD8),
+	GPIO_FN(LCDD7),
+	GPIO_FN(LCDD6),
+	GPIO_FN(LCDD5),
+	GPIO_FN(LCDD4),
+	GPIO_FN(LCDD3),
+	GPIO_FN(LCDD2),
+	GPIO_FN(LCDD1),
+	GPIO_FN(LCDD0),
+	GPIO_FN(LCDVSYN),
+	GPIO_FN(LCDDISP),
+	GPIO_FN(LCDRS),
+	GPIO_FN(LCDHSYN),
+	GPIO_FN(LCDCS),
+	GPIO_FN(LCDDON),
+	GPIO_FN(LCDDCK),
+	GPIO_FN(LCDWR),
+	GPIO_FN(LCDVEPWC),
+	GPIO_FN(LCDVCPWC),
+	GPIO_FN(LCDRD),
+	GPIO_FN(LCDLCLK),
 
 	/* SCIF0 */
-	PINMUX_GPIO(GPIO_FN_SCIF0_TXD,	SCIF0_TXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF0_RXD,	SCIF0_RXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF0_SCK,	SCIF0_SCK_MARK),
+	GPIO_FN(SCIF0_TXD),
+	GPIO_FN(SCIF0_RXD),
+	GPIO_FN(SCIF0_SCK),
 
 	/* SCIF1 */
-	PINMUX_GPIO(GPIO_FN_SCIF1_SCK,	SCIF1_SCK_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF1_RXD,	SCIF1_RXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF1_TXD,	SCIF1_TXD_MARK),
+	GPIO_FN(SCIF1_SCK),
+	GPIO_FN(SCIF1_RXD),
+	GPIO_FN(SCIF1_TXD),
 
 	/* SCIF2 */
-	PINMUX_GPIO(GPIO_FN_SCIF2_L_TXD,	SCIF2_L_TXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF2_L_SCK,	SCIF2_L_SCK_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF2_L_RXD,	SCIF2_L_RXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF2_V_TXD,	SCIF2_V_TXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF2_V_SCK,	SCIF2_V_SCK_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF2_V_RXD,	SCIF2_V_RXD_MARK),
+	GPIO_FN(SCIF2_L_TXD),
+	GPIO_FN(SCIF2_L_SCK),
+	GPIO_FN(SCIF2_L_RXD),
+	GPIO_FN(SCIF2_V_TXD),
+	GPIO_FN(SCIF2_V_SCK),
+	GPIO_FN(SCIF2_V_RXD),
 
 	/* SCIF3 */
-	PINMUX_GPIO(GPIO_FN_SCIF3_V_SCK,	SCIF3_V_SCK_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF3_V_RXD,	SCIF3_V_RXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF3_V_TXD,	SCIF3_V_TXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF3_V_CTS,	SCIF3_V_CTS_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF3_V_RTS,	SCIF3_V_RTS_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF3_I_SCK,	SCIF3_I_SCK_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF3_I_RXD,	SCIF3_I_RXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF3_I_TXD,	SCIF3_I_TXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF3_I_CTS,	SCIF3_I_CTS_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF3_I_RTS,	SCIF3_I_RTS_MARK),
+	GPIO_FN(SCIF3_V_SCK),
+	GPIO_FN(SCIF3_V_RXD),
+	GPIO_FN(SCIF3_V_TXD),
+	GPIO_FN(SCIF3_V_CTS),
+	GPIO_FN(SCIF3_V_RTS),
+	GPIO_FN(SCIF3_I_SCK),
+	GPIO_FN(SCIF3_I_RXD),
+	GPIO_FN(SCIF3_I_TXD),
+	GPIO_FN(SCIF3_I_CTS),
+	GPIO_FN(SCIF3_I_RTS),
 
 	/* SCIF4 */
-	PINMUX_GPIO(GPIO_FN_SCIF4_SCK,	SCIF4_SCK_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF4_RXD,	SCIF4_RXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF4_TXD,	SCIF4_TXD_MARK),
+	GPIO_FN(SCIF4_SCK),
+	GPIO_FN(SCIF4_RXD),
+	GPIO_FN(SCIF4_TXD),
 
 	/* SCIF5 */
-	PINMUX_GPIO(GPIO_FN_SCIF5_SCK,	SCIF5_SCK_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF5_RXD,	SCIF5_RXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF5_TXD,	SCIF5_TXD_MARK),
+	GPIO_FN(SCIF5_SCK),
+	GPIO_FN(SCIF5_RXD),
+	GPIO_FN(SCIF5_TXD),
 
 	/* FSI */
-	PINMUX_GPIO(GPIO_FN_FSIMCKB,	FSIMCKB_MARK),
-	PINMUX_GPIO(GPIO_FN_FSIMCKA,	FSIMCKA_MARK),
-	PINMUX_GPIO(GPIO_FN_FSIOASD,	FSIOASD_MARK),
-	PINMUX_GPIO(GPIO_FN_FSIIABCK,	FSIIABCK_MARK),
-	PINMUX_GPIO(GPIO_FN_FSIIALRCK,	FSIIALRCK_MARK),
-	PINMUX_GPIO(GPIO_FN_FSIOABCK,	FSIOABCK_MARK),
-	PINMUX_GPIO(GPIO_FN_FSIOALRCK,	FSIOALRCK_MARK),
-	PINMUX_GPIO(GPIO_FN_CLKAUDIOAO,	CLKAUDIOAO_MARK),
-	PINMUX_GPIO(GPIO_FN_FSIIBSD,	FSIIBSD_MARK),
-	PINMUX_GPIO(GPIO_FN_FSIOBSD,	FSIOBSD_MARK),
-	PINMUX_GPIO(GPIO_FN_FSIIBBCK,	FSIIBBCK_MARK),
-	PINMUX_GPIO(GPIO_FN_FSIIBLRCK,	FSIIBLRCK_MARK),
-	PINMUX_GPIO(GPIO_FN_FSIOBBCK,	FSIOBBCK_MARK),
-	PINMUX_GPIO(GPIO_FN_FSIOBLRCK,	FSIOBLRCK_MARK),
-	PINMUX_GPIO(GPIO_FN_CLKAUDIOBO,	CLKAUDIOBO_MARK),
-	PINMUX_GPIO(GPIO_FN_FSIIASD,	FSIIASD_MARK),
+	GPIO_FN(FSIMCKB),
+	GPIO_FN(FSIMCKA),
+	GPIO_FN(FSIOASD),
+	GPIO_FN(FSIIABCK),
+	GPIO_FN(FSIIALRCK),
+	GPIO_FN(FSIOABCK),
+	GPIO_FN(FSIOALRCK),
+	GPIO_FN(CLKAUDIOAO),
+	GPIO_FN(FSIIBSD),
+	GPIO_FN(FSIOBSD),
+	GPIO_FN(FSIIBBCK),
+	GPIO_FN(FSIIBLRCK),
+	GPIO_FN(FSIOBBCK),
+	GPIO_FN(FSIOBLRCK),
+	GPIO_FN(CLKAUDIOBO),
+	GPIO_FN(FSIIASD),
 
 	/* AUD */
-	PINMUX_GPIO(GPIO_FN_AUDCK,	AUDCK_MARK),
-	PINMUX_GPIO(GPIO_FN_AUDSYNC,	AUDSYNC_MARK),
-	PINMUX_GPIO(GPIO_FN_AUDATA3,	AUDATA3_MARK),
-	PINMUX_GPIO(GPIO_FN_AUDATA2,	AUDATA2_MARK),
-	PINMUX_GPIO(GPIO_FN_AUDATA1,	AUDATA1_MARK),
-	PINMUX_GPIO(GPIO_FN_AUDATA0,	AUDATA0_MARK),
+	GPIO_FN(AUDCK),
+	GPIO_FN(AUDSYNC),
+	GPIO_FN(AUDATA3),
+	GPIO_FN(AUDATA2),
+	GPIO_FN(AUDATA1),
+	GPIO_FN(AUDATA0),
 
 	/* VIO */
-	PINMUX_GPIO(GPIO_FN_VIO_CKO,	VIO_CKO_MARK),
+	GPIO_FN(VIO_CKO),
 
 	/* VIO0 */
-	PINMUX_GPIO(GPIO_FN_VIO0_D15,	VIO0_D15_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO0_D14,	VIO0_D14_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO0_D13,	VIO0_D13_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO0_D12,	VIO0_D12_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO0_D11,	VIO0_D11_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO0_D10,	VIO0_D10_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO0_D9,	VIO0_D9_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO0_D8,	VIO0_D8_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO0_D7,	VIO0_D7_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO0_D6,	VIO0_D6_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO0_D5,	VIO0_D5_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO0_D4,	VIO0_D4_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO0_D3,	VIO0_D3_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO0_D2,	VIO0_D2_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO0_D1,	VIO0_D1_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO0_D0,	VIO0_D0_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO0_VD,	VIO0_VD_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO0_CLK,	VIO0_CLK_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO0_FLD,	VIO0_FLD_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO0_HD,	VIO0_HD_MARK),
+	GPIO_FN(VIO0_D15),
+	GPIO_FN(VIO0_D14),
+	GPIO_FN(VIO0_D13),
+	GPIO_FN(VIO0_D12),
+	GPIO_FN(VIO0_D11),
+	GPIO_FN(VIO0_D10),
+	GPIO_FN(VIO0_D9),
+	GPIO_FN(VIO0_D8),
+	GPIO_FN(VIO0_D7),
+	GPIO_FN(VIO0_D6),
+	GPIO_FN(VIO0_D5),
+	GPIO_FN(VIO0_D4),
+	GPIO_FN(VIO0_D3),
+	GPIO_FN(VIO0_D2),
+	GPIO_FN(VIO0_D1),
+	GPIO_FN(VIO0_D0),
+	GPIO_FN(VIO0_VD),
+	GPIO_FN(VIO0_CLK),
+	GPIO_FN(VIO0_FLD),
+	GPIO_FN(VIO0_HD),
 
 	/* VIO1 */
-	PINMUX_GPIO(GPIO_FN_VIO1_D7,	VIO1_D7_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO1_D6,	VIO1_D6_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO1_D5,	VIO1_D5_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO1_D4,	VIO1_D4_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO1_D3,	VIO1_D3_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO1_D2,	VIO1_D2_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO1_D1,	VIO1_D1_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO1_D0,	VIO1_D0_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO1_FLD,	VIO1_FLD_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO1_HD,	VIO1_HD_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO1_VD,	VIO1_VD_MARK),
-	PINMUX_GPIO(GPIO_FN_VIO1_CLK,	VIO1_CLK_MARK),
+	GPIO_FN(VIO1_D7),
+	GPIO_FN(VIO1_D6),
+	GPIO_FN(VIO1_D5),
+	GPIO_FN(VIO1_D4),
+	GPIO_FN(VIO1_D3),
+	GPIO_FN(VIO1_D2),
+	GPIO_FN(VIO1_D1),
+	GPIO_FN(VIO1_D0),
+	GPIO_FN(VIO1_FLD),
+	GPIO_FN(VIO1_HD),
+	GPIO_FN(VIO1_VD),
+	GPIO_FN(VIO1_CLK),
 
 	/* Eth */
-	PINMUX_GPIO(GPIO_FN_RMII_RXD0,		RMII_RXD0_MARK),
-	PINMUX_GPIO(GPIO_FN_RMII_RXD1,		RMII_RXD1_MARK),
-	PINMUX_GPIO(GPIO_FN_RMII_TXD0,		RMII_TXD0_MARK),
-	PINMUX_GPIO(GPIO_FN_RMII_TXD1,		RMII_TXD1_MARK),
-	PINMUX_GPIO(GPIO_FN_RMII_REF_CLK,	RMII_REF_CLK_MARK),
-	PINMUX_GPIO(GPIO_FN_RMII_TX_EN,		RMII_TX_EN_MARK),
-	PINMUX_GPIO(GPIO_FN_RMII_RX_ER,		RMII_RX_ER_MARK),
-	PINMUX_GPIO(GPIO_FN_RMII_CRS_DV,	RMII_CRS_DV_MARK),
-	PINMUX_GPIO(GPIO_FN_LNKSTA,		LNKSTA_MARK),
-	PINMUX_GPIO(GPIO_FN_MDIO,		MDIO_MARK),
-	PINMUX_GPIO(GPIO_FN_MDC,		MDC_MARK),
+	GPIO_FN(RMII_RXD0),
+	GPIO_FN(RMII_RXD1),
+	GPIO_FN(RMII_TXD0),
+	GPIO_FN(RMII_TXD1),
+	GPIO_FN(RMII_REF_CLK),
+	GPIO_FN(RMII_TX_EN),
+	GPIO_FN(RMII_RX_ER),
+	GPIO_FN(RMII_CRS_DV),
+	GPIO_FN(LNKSTA),
+	GPIO_FN(MDIO),
+	GPIO_FN(MDC),
 
 	/* System */
-	PINMUX_GPIO(GPIO_FN_PDSTATUS,	PDSTATUS_MARK),
-	PINMUX_GPIO(GPIO_FN_STATUS2,	STATUS2_MARK),
-	PINMUX_GPIO(GPIO_FN_STATUS0,	STATUS0_MARK),
+	GPIO_FN(PDSTATUS),
+	GPIO_FN(STATUS2),
+	GPIO_FN(STATUS0),
 
 	/* VOU */
-	PINMUX_GPIO(GPIO_FN_DV_D15,	DV_D15_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_D14,	DV_D14_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_D13,	DV_D13_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_D12,	DV_D12_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_D11,	DV_D11_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_D10,	DV_D10_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_D9,	DV_D9_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_D8,	DV_D8_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_D7,	DV_D7_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_D6,	DV_D6_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_D5,	DV_D5_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_D4,	DV_D4_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_D3,	DV_D3_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_D2,	DV_D2_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_D1,	DV_D1_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_D0,	DV_D0_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_CLKI,	DV_CLKI_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_CLK,	DV_CLK_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_VSYNC,	DV_VSYNC_MARK),
-	PINMUX_GPIO(GPIO_FN_DV_HSYNC,	DV_HSYNC_MARK),
+	GPIO_FN(DV_D15),
+	GPIO_FN(DV_D14),
+	GPIO_FN(DV_D13),
+	GPIO_FN(DV_D12),
+	GPIO_FN(DV_D11),
+	GPIO_FN(DV_D10),
+	GPIO_FN(DV_D9),
+	GPIO_FN(DV_D8),
+	GPIO_FN(DV_D7),
+	GPIO_FN(DV_D6),
+	GPIO_FN(DV_D5),
+	GPIO_FN(DV_D4),
+	GPIO_FN(DV_D3),
+	GPIO_FN(DV_D2),
+	GPIO_FN(DV_D1),
+	GPIO_FN(DV_D0),
+	GPIO_FN(DV_CLKI),
+	GPIO_FN(DV_CLK),
+	GPIO_FN(DV_VSYNC),
+	GPIO_FN(DV_HSYNC),
 
 	/* MSIOF0 */
-	PINMUX_GPIO(GPIO_FN_MSIOF0_RXD,		MSIOF0_RXD_MARK),
-	PINMUX_GPIO(GPIO_FN_MSIOF0_TXD,		MSIOF0_TXD_MARK),
-	PINMUX_GPIO(GPIO_FN_MSIOF0_MCK,		MSIOF0_MCK_MARK),
-	PINMUX_GPIO(GPIO_FN_MSIOF0_TSCK,	MSIOF0_TSCK_MARK),
-	PINMUX_GPIO(GPIO_FN_MSIOF0_SS1,		MSIOF0_SS1_MARK),
-	PINMUX_GPIO(GPIO_FN_MSIOF0_SS2,		MSIOF0_SS2_MARK),
-	PINMUX_GPIO(GPIO_FN_MSIOF0_TSYNC,	MSIOF0_TSYNC_MARK),
-	PINMUX_GPIO(GPIO_FN_MSIOF0_RSCK,	MSIOF0_RSCK_MARK),
-	PINMUX_GPIO(GPIO_FN_MSIOF0_RSYNC,	MSIOF0_RSYNC_MARK),
+	GPIO_FN(MSIOF0_RXD),
+	GPIO_FN(MSIOF0_TXD),
+	GPIO_FN(MSIOF0_MCK),
+	GPIO_FN(MSIOF0_TSCK),
+	GPIO_FN(MSIOF0_SS1),
+	GPIO_FN(MSIOF0_SS2),
+	GPIO_FN(MSIOF0_TSYNC),
+	GPIO_FN(MSIOF0_RSCK),
+	GPIO_FN(MSIOF0_RSYNC),
 
 	/* MSIOF1 */
-	PINMUX_GPIO(GPIO_FN_MSIOF1_RXD,		MSIOF1_RXD_MARK),
-	PINMUX_GPIO(GPIO_FN_MSIOF1_TXD,		MSIOF1_TXD_MARK),
-	PINMUX_GPIO(GPIO_FN_MSIOF1_MCK,		MSIOF1_MCK_MARK),
-	PINMUX_GPIO(GPIO_FN_MSIOF1_TSCK,	MSIOF1_TSCK_MARK),
-	PINMUX_GPIO(GPIO_FN_MSIOF1_SS1,		MSIOF1_SS1_MARK),
-	PINMUX_GPIO(GPIO_FN_MSIOF1_SS2,		MSIOF1_SS2_MARK),
-	PINMUX_GPIO(GPIO_FN_MSIOF1_TSYNC,	MSIOF1_TSYNC_MARK),
-	PINMUX_GPIO(GPIO_FN_MSIOF1_RSCK,	MSIOF1_RSCK_MARK),
-	PINMUX_GPIO(GPIO_FN_MSIOF1_RSYNC,	MSIOF1_RSYNC_MARK),
+	GPIO_FN(MSIOF1_RXD),
+	GPIO_FN(MSIOF1_TXD),
+	GPIO_FN(MSIOF1_MCK),
+	GPIO_FN(MSIOF1_TSCK),
+	GPIO_FN(MSIOF1_SS1),
+	GPIO_FN(MSIOF1_SS2),
+	GPIO_FN(MSIOF1_TSYNC),
+	GPIO_FN(MSIOF1_RSCK),
+	GPIO_FN(MSIOF1_RSYNC),
 
 	/* DMAC */
-	PINMUX_GPIO(GPIO_FN_DMAC_DACK0,	DMAC_DACK0_MARK),
-	PINMUX_GPIO(GPIO_FN_DMAC_DREQ0,	DMAC_DREQ0_MARK),
-	PINMUX_GPIO(GPIO_FN_DMAC_DACK1,	DMAC_DACK1_MARK),
-	PINMUX_GPIO(GPIO_FN_DMAC_DREQ1,	DMAC_DREQ1_MARK),
+	GPIO_FN(DMAC_DACK0),
+	GPIO_FN(DMAC_DREQ0),
+	GPIO_FN(DMAC_DACK1),
+	GPIO_FN(DMAC_DREQ1),
 
 	/* SDHI0 */
-	PINMUX_GPIO(GPIO_FN_SDHI0CD,	SDHI0CD_MARK),
-	PINMUX_GPIO(GPIO_FN_SDHI0WP,	SDHI0WP_MARK),
-	PINMUX_GPIO(GPIO_FN_SDHI0CMD,	SDHI0CMD_MARK),
-	PINMUX_GPIO(GPIO_FN_SDHI0CLK,	SDHI0CLK_MARK),
-	PINMUX_GPIO(GPIO_FN_SDHI0D3,	SDHI0D3_MARK),
-	PINMUX_GPIO(GPIO_FN_SDHI0D2,	SDHI0D2_MARK),
-	PINMUX_GPIO(GPIO_FN_SDHI0D1,	SDHI0D1_MARK),
-	PINMUX_GPIO(GPIO_FN_SDHI0D0,	SDHI0D0_MARK),
+	GPIO_FN(SDHI0CD),
+	GPIO_FN(SDHI0WP),
+	GPIO_FN(SDHI0CMD),
+	GPIO_FN(SDHI0CLK),
+	GPIO_FN(SDHI0D3),
+	GPIO_FN(SDHI0D2),
+	GPIO_FN(SDHI0D1),
+	GPIO_FN(SDHI0D0),
 
 	/* SDHI1 */
-	PINMUX_GPIO(GPIO_FN_SDHI1CD,	SDHI1CD_MARK),
-	PINMUX_GPIO(GPIO_FN_SDHI1WP,	SDHI1WP_MARK),
-	PINMUX_GPIO(GPIO_FN_SDHI1CMD,	SDHI1CMD_MARK),
-	PINMUX_GPIO(GPIO_FN_SDHI1CLK,	SDHI1CLK_MARK),
-	PINMUX_GPIO(GPIO_FN_SDHI1D3,	SDHI1D3_MARK),
-	PINMUX_GPIO(GPIO_FN_SDHI1D2,	SDHI1D2_MARK),
-	PINMUX_GPIO(GPIO_FN_SDHI1D1,	SDHI1D1_MARK),
-	PINMUX_GPIO(GPIO_FN_SDHI1D0,	SDHI1D0_MARK),
+	GPIO_FN(SDHI1CD),
+	GPIO_FN(SDHI1WP),
+	GPIO_FN(SDHI1CMD),
+	GPIO_FN(SDHI1CLK),
+	GPIO_FN(SDHI1D3),
+	GPIO_FN(SDHI1D2),
+	GPIO_FN(SDHI1D1),
+	GPIO_FN(SDHI1D0),
 
 	/* MMC */
-	PINMUX_GPIO(GPIO_FN_MMC_D7,	MMC_D7_MARK),
-	PINMUX_GPIO(GPIO_FN_MMC_D6,	MMC_D6_MARK),
-	PINMUX_GPIO(GPIO_FN_MMC_D5,	MMC_D5_MARK),
-	PINMUX_GPIO(GPIO_FN_MMC_D4,	MMC_D4_MARK),
-	PINMUX_GPIO(GPIO_FN_MMC_D3,	MMC_D3_MARK),
-	PINMUX_GPIO(GPIO_FN_MMC_D2,	MMC_D2_MARK),
-	PINMUX_GPIO(GPIO_FN_MMC_D1,	MMC_D1_MARK),
-	PINMUX_GPIO(GPIO_FN_MMC_D0,	MMC_D0_MARK),
-	PINMUX_GPIO(GPIO_FN_MMC_CLK,	MMC_CLK_MARK),
-	PINMUX_GPIO(GPIO_FN_MMC_CMD,	MMC_CMD_MARK),
+	GPIO_FN(MMC_D7),
+	GPIO_FN(MMC_D6),
+	GPIO_FN(MMC_D5),
+	GPIO_FN(MMC_D4),
+	GPIO_FN(MMC_D3),
+	GPIO_FN(MMC_D2),
+	GPIO_FN(MMC_D1),
+	GPIO_FN(MMC_D0),
+	GPIO_FN(MMC_CLK),
+	GPIO_FN(MMC_CMD),
 
 	/* IrDA */
-	PINMUX_GPIO(GPIO_FN_IRDA_OUT,	IRDA_OUT_MARK),
-	PINMUX_GPIO(GPIO_FN_IRDA_IN,	IRDA_IN_MARK),
+	GPIO_FN(IRDA_OUT),
+	GPIO_FN(IRDA_IN),
 
 	/* TSIF */
-	PINMUX_GPIO(GPIO_FN_TSIF_TS0_SDAT,	TSIF_TS0_SDAT_MARK),
-	PINMUX_GPIO(GPIO_FN_TSIF_TS0_SCK,	TSIF_TS0_SCK_MARK),
-	PINMUX_GPIO(GPIO_FN_TSIF_TS0_SDEN,	TSIF_TS0_SDEN_MARK),
-	PINMUX_GPIO(GPIO_FN_TSIF_TS0_SPSYNC,	TSIF_TS0_SPSYNC_MARK),
+	GPIO_FN(TSIF_TS0_SDAT),
+	GPIO_FN(TSIF_TS0_SCK),
+	GPIO_FN(TSIF_TS0_SDEN),
+	GPIO_FN(TSIF_TS0_SPSYNC),
 
 	/* IRQ */
-	PINMUX_GPIO(GPIO_FN_INTC_IRQ7,	INTC_IRQ7_MARK),
-	PINMUX_GPIO(GPIO_FN_INTC_IRQ6,	INTC_IRQ6_MARK),
-	PINMUX_GPIO(GPIO_FN_INTC_IRQ5,	INTC_IRQ5_MARK),
-	PINMUX_GPIO(GPIO_FN_INTC_IRQ4,	INTC_IRQ4_MARK),
-	PINMUX_GPIO(GPIO_FN_INTC_IRQ3,	INTC_IRQ3_MARK),
-	PINMUX_GPIO(GPIO_FN_INTC_IRQ2,	INTC_IRQ2_MARK),
-	PINMUX_GPIO(GPIO_FN_INTC_IRQ1,	INTC_IRQ1_MARK),
-	PINMUX_GPIO(GPIO_FN_INTC_IRQ0,	INTC_IRQ0_MARK),
+	GPIO_FN(INTC_IRQ7),
+	GPIO_FN(INTC_IRQ6),
+	GPIO_FN(INTC_IRQ5),
+	GPIO_FN(INTC_IRQ4),
+	GPIO_FN(INTC_IRQ3),
+	GPIO_FN(INTC_IRQ2),
+	GPIO_FN(INTC_IRQ1),
+	GPIO_FN(INTC_IRQ0),
 };
 
-static struct pinmux_cfg_reg pinmux_config_regs[] = {
+static const struct pinmux_cfg_reg pinmux_config_regs[] = {
 	{ PINMUX_CFG_REG("PACR", 0xa4050100, 16, 2) {
 		PTA7_FN, PTA7_OUT, PTA7_IN_PU, PTA7_IN,
 		PTA6_FN, PTA6_OUT, PTA6_IN_PU, PTA6_IN,
@@ -2107,7 +2111,7 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = {
 	{}
 };
 
-static struct pinmux_data_reg pinmux_data_regs[] = {
+static const struct pinmux_data_reg pinmux_data_regs[] = {
 	{ PINMUX_DATA_REG("PADR", 0xa4050120, 8) {
 		PTA7_DATA, PTA6_DATA, PTA5_DATA, PTA4_DATA,
 		PTA3_DATA, PTA2_DATA, PTA1_DATA, PTA0_DATA }
@@ -2203,20 +2207,18 @@ static struct pinmux_data_reg pinmux_data_regs[] = {
 	{ },
 };
 
-struct sh_pfc_soc_info sh7724_pinmux_info = {
+const struct sh_pfc_soc_info sh7724_pinmux_info = {
 	.name = "sh7724_pfc",
-	.reserved_id = PINMUX_RESERVED,
-	.data = { PINMUX_DATA_BEGIN, PINMUX_DATA_END },
 	.input = { PINMUX_INPUT_BEGIN, PINMUX_INPUT_END },
 	.input_pu = { PINMUX_INPUT_PULLUP_BEGIN, PINMUX_INPUT_PULLUP_END },
 	.output = { PINMUX_OUTPUT_BEGIN, PINMUX_OUTPUT_END },
-	.mark = { PINMUX_MARK_BEGIN, PINMUX_MARK_END },
 	.function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END },
 
-	.first_gpio = GPIO_PTA7,
-	.last_gpio = GPIO_FN_INTC_IRQ0,
+	.pins = pinmux_pins,
+	.nr_pins = ARRAY_SIZE(pinmux_pins),
+	.func_gpios = pinmux_func_gpios,
+	.nr_func_gpios = ARRAY_SIZE(pinmux_func_gpios),
 
-	.gpios = pinmux_gpios,
 	.cfg_regs = pinmux_config_regs,
 	.data_regs = pinmux_data_regs,
 
diff --git a/drivers/pinctrl/sh-pfc/pfc-sh7734.c b/drivers/pinctrl/sh-pfc/pfc-sh7734.c
index 23d76d2..2fd5b7d 100644
--- a/drivers/pinctrl/sh-pfc/pfc-sh7734.c
+++ b/drivers/pinctrl/sh-pfc/pfc-sh7734.c
@@ -14,11 +14,6 @@
 
 #include "sh_pfc.h"
 
-#define CPU_32_PORT(fn, pfx, sfx)				\
-	PORT_10(fn, pfx, sfx), PORT_10(fn, pfx##1, sfx),	\
-	PORT_10(fn, pfx##2, sfx), PORT_1(fn, pfx##30, sfx),	\
-	PORT_1(fn, pfx##31, sfx)
-
 #define CPU_32_PORT5(fn, pfx, sfx)				\
 	PORT_1(fn, pfx##0, sfx), PORT_1(fn, pfx##1, sfx),	\
 	PORT_1(fn, pfx##2, sfx), PORT_1(fn, pfx##3, sfx),	\
@@ -29,11 +24,11 @@
 
 /* GPSR0 - GPSR5 */
 #define CPU_ALL_PORT(fn, pfx, sfx)				\
-	CPU_32_PORT(fn, pfx##_0_, sfx),			\
-	CPU_32_PORT(fn, pfx##_1_, sfx),				\
-	CPU_32_PORT(fn, pfx##_2_, sfx),				\
-	CPU_32_PORT(fn, pfx##_3_, sfx),				\
-	CPU_32_PORT(fn, pfx##_4_, sfx),				\
+	PORT_32(fn, pfx##_0_, sfx),			\
+	PORT_32(fn, pfx##_1_, sfx),				\
+	PORT_32(fn, pfx##_2_, sfx),				\
+	PORT_32(fn, pfx##_3_, sfx),				\
+	PORT_32(fn, pfx##_4_, sfx),				\
 	CPU_32_PORT5(fn, pfx##_5_, sfx)
 
 #define _GP_GPIO(pfx, sfx) PINMUX_GPIO(GPIO_GP##pfx, GP##pfx##_DATA)
@@ -47,20 +42,8 @@
 #define PINMUX_GPIO_GP_ALL()	CPU_ALL_PORT(_GP_GPIO, , unused)
 #define PINMUX_DATA_GP_ALL()	CPU_ALL_PORT(_GP_DATA, , unused)
 
-#define PORT_10_REV(fn, pfx, sfx)	\
-	PORT_1(fn, pfx##9, sfx), PORT_1(fn, pfx##8, sfx),	\
-	PORT_1(fn, pfx##7, sfx), PORT_1(fn, pfx##6, sfx),	\
-	PORT_1(fn, pfx##5, sfx), PORT_1(fn, pfx##4, sfx),	\
-	PORT_1(fn, pfx##3, sfx), PORT_1(fn, pfx##2, sfx),	\
-	PORT_1(fn, pfx##1, sfx), PORT_1(fn, pfx##0, sfx)
-
-#define CPU_32_PORT_REV(fn, pfx, sfx)	\
-	PORT_1(fn, pfx##31, sfx), PORT_1(fn, pfx##30, sfx),	\
-	PORT_10_REV(fn, pfx##2, sfx), PORT_10_REV(fn, pfx##1, sfx),	\
-	PORT_10_REV(fn, pfx, sfx)
-
-#define GP_INOUTSEL(bank) CPU_32_PORT_REV(_GP_INOUTSEL, _##bank##_, unused)
-#define GP_INDT(bank) CPU_32_PORT_REV(_GP_INDT, _##bank##_, unused)
+#define GP_INOUTSEL(bank) PORT_32_REV(_GP_INOUTSEL, _##bank##_, unused)
+#define GP_INDT(bank) PORT_32_REV(_GP_INDT, _##bank##_, unused)
 
 #define PINMUX_IPSR_DATA(ipsr, fn) PINMUX_DATA(fn##_MARK, FN_##ipsr, FN_##fn)
 #define PINMUX_IPSR_MODSEL_DATA(ipsr, fn, ms) PINMUX_DATA(fn##_MARK, FN_##ms, \
@@ -609,7 +592,7 @@ enum {
 	PINMUX_MARK_END,
 };
 
-static pinmux_enum_t pinmux_data[] = {
+static const pinmux_enum_t pinmux_data[] = {
 	PINMUX_DATA_GP_ALL(), /* PINMUX_DATA(GP_M_N_DATA, GP_M_N_FN...), */
 
 	PINMUX_DATA(CLKOUT_MARK, FN_CLKOUT),
@@ -1384,9 +1367,13 @@ static pinmux_enum_t pinmux_data[] = {
 	PINMUX_IPSR_DATA(IP11_28, ST_CLKOUT),
 };
 
-static struct pinmux_gpio pinmux_gpios[] = {
+static struct sh_pfc_pin pinmux_pins[] = {
 	PINMUX_GPIO_GP_ALL(),
+};
+
+#define PINMUX_FN_BASE	ARRAY_SIZE(pinmux_pins)
 
+static const struct pinmux_func pinmux_func_gpios[] = {
 	GPIO_FN(CLKOUT), GPIO_FN(BS), GPIO_FN(CS0), GPIO_FN(EX_CS0),
 	GPIO_FN(RD), GPIO_FN(WE0), GPIO_FN(WE1),
 	GPIO_FN(SCL0), GPIO_FN(PENC0), GPIO_FN(USB_OVC0),
@@ -1665,7 +1652,7 @@ static struct pinmux_gpio pinmux_gpios[] = {
 	GPIO_FN(SCL1), GPIO_FN(SCIF_CLK_C),
 };
 
-static struct pinmux_cfg_reg pinmux_config_regs[] = {
+static const struct pinmux_cfg_reg pinmux_config_regs[] = {
 	{ PINMUX_CFG_REG("GPSR0", 0xFFFC0004, 32, 1) {
 		GP_0_31_FN, FN_IP2_2_0,
 		GP_0_30_FN, FN_IP1_31_29,
@@ -2434,7 +2421,7 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = {
 	{ },
 };
 
-static struct pinmux_data_reg pinmux_data_regs[] = {
+static const struct pinmux_data_reg pinmux_data_regs[] = {
 	/* GPIO 0 - 5*/
 	{ PINMUX_DATA_REG("INDT0", 0xFFC4000C, 32) { GP_INDT(0) } },
 	{ PINMUX_DATA_REG("INDT1", 0xFFC4100C, 32) { GP_INDT(1) } },
@@ -2451,22 +2438,20 @@ static struct pinmux_data_reg pinmux_data_regs[] = {
 	{ },
 };
 
-struct sh_pfc_soc_info sh7734_pinmux_info = {
+const struct sh_pfc_soc_info sh7734_pinmux_info = {
 	.name = "sh7734_pfc",
 
 	.unlock_reg = 0xFFFC0000,
 
-	.reserved_id = PINMUX_RESERVED,
-	.data = { PINMUX_DATA_BEGIN, PINMUX_DATA_END },
 	.input = { PINMUX_INPUT_BEGIN, PINMUX_INPUT_END },
 	.output = { PINMUX_OUTPUT_BEGIN, PINMUX_OUTPUT_END },
-	.mark = { PINMUX_MARK_BEGIN, PINMUX_MARK_END },
 	.function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END },
 
-	.first_gpio = GPIO_GP_0_0,
-	.last_gpio = GPIO_FN_ST_CLKOUT,
+	.pins = pinmux_pins,
+	.nr_pins = ARRAY_SIZE(pinmux_pins),
+	.func_gpios = pinmux_func_gpios,
+	.nr_func_gpios = ARRAY_SIZE(pinmux_func_gpios),
 
-	.gpios = pinmux_gpios,
 	.cfg_regs = pinmux_config_regs,
 	.data_regs = pinmux_data_regs,
 
diff --git a/drivers/pinctrl/sh-pfc/pfc-sh7757.c b/drivers/pinctrl/sh-pfc/pfc-sh7757.c
index 5ed74cd..e074230 100644
--- a/drivers/pinctrl/sh-pfc/pfc-sh7757.c
+++ b/drivers/pinctrl/sh-pfc/pfc-sh7757.c
@@ -526,7 +526,7 @@ enum {
 	PINMUX_MARK_END,
 };
 
-static pinmux_enum_t pinmux_data[] = {
+static const pinmux_enum_t pinmux_data[] = {
 	/* PTA GPIO */
 	PINMUX_DATA(PTA7_DATA, PTA7_IN, PTA7_OUT),
 	PINMUX_DATA(PTA6_DATA, PTA6_IN, PTA6_OUT),
@@ -1114,7 +1114,7 @@ static pinmux_enum_t pinmux_data[] = {
 	PINMUX_DATA(ON_DQ0_MARK, PS8_8_FN2, PTZ0_FN),
 };
 
-static struct pinmux_gpio pinmux_gpios[] = {
+static struct sh_pfc_pin pinmux_pins[] = {
 	/* PTA */
 	PINMUX_GPIO(GPIO_PTA7, PTA7_DATA),
 	PINMUX_GPIO(GPIO_PTA6, PTA6_DATA),
@@ -1370,359 +1370,363 @@ static struct pinmux_gpio pinmux_gpios[] = {
 	PINMUX_GPIO(GPIO_PTZ2, PTZ2_DATA),
 	PINMUX_GPIO(GPIO_PTZ1, PTZ1_DATA),
 	PINMUX_GPIO(GPIO_PTZ0, PTZ0_DATA),
+};
+
+#define PINMUX_FN_BASE	ARRAY_SIZE(pinmux_pins)
 
+static const struct pinmux_func pinmux_func_gpios[] = {
 	/* PTA (mobule: LBSC, RGMII) */
-	PINMUX_GPIO(GPIO_FN_BS, BS_MARK),
-	PINMUX_GPIO(GPIO_FN_RDWR, RDWR_MARK),
-	PINMUX_GPIO(GPIO_FN_WE1, WE1_MARK),
-	PINMUX_GPIO(GPIO_FN_RDY, RDY_MARK),
-	PINMUX_GPIO(GPIO_FN_ET0_MDC, ET0_MDC_MARK),
-	PINMUX_GPIO(GPIO_FN_ET0_MDIO, ET0_MDIO_MARK),
-	PINMUX_GPIO(GPIO_FN_ET1_MDC, ET1_MDC_MARK),
-	PINMUX_GPIO(GPIO_FN_ET1_MDIO, ET1_MDIO_MARK),
+	GPIO_FN(BS),
+	GPIO_FN(RDWR),
+	GPIO_FN(WE1),
+	GPIO_FN(RDY),
+	GPIO_FN(ET0_MDC),
+	GPIO_FN(ET0_MDIO),
+	GPIO_FN(ET1_MDC),
+	GPIO_FN(ET1_MDIO),
 
 	/* PTB (mobule: INTC, ONFI, TMU) */
-	PINMUX_GPIO(GPIO_FN_IRQ15, IRQ15_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ14, IRQ14_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ13, IRQ13_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ12, IRQ12_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ11, IRQ11_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ10, IRQ10_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ9, IRQ9_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ8, IRQ8_MARK),
-	PINMUX_GPIO(GPIO_FN_ON_NRE, ON_NRE_MARK),
-	PINMUX_GPIO(GPIO_FN_ON_NWE, ON_NWE_MARK),
-	PINMUX_GPIO(GPIO_FN_ON_NWP, ON_NWP_MARK),
-	PINMUX_GPIO(GPIO_FN_ON_NCE0, ON_NCE0_MARK),
-	PINMUX_GPIO(GPIO_FN_ON_R_B0, ON_R_B0_MARK),
-	PINMUX_GPIO(GPIO_FN_ON_ALE, ON_ALE_MARK),
-	PINMUX_GPIO(GPIO_FN_ON_CLE, ON_CLE_MARK),
-	PINMUX_GPIO(GPIO_FN_TCLK, TCLK_MARK),
+	GPIO_FN(IRQ15),
+	GPIO_FN(IRQ14),
+	GPIO_FN(IRQ13),
+	GPIO_FN(IRQ12),
+	GPIO_FN(IRQ11),
+	GPIO_FN(IRQ10),
+	GPIO_FN(IRQ9),
+	GPIO_FN(IRQ8),
+	GPIO_FN(ON_NRE),
+	GPIO_FN(ON_NWE),
+	GPIO_FN(ON_NWP),
+	GPIO_FN(ON_NCE0),
+	GPIO_FN(ON_R_B0),
+	GPIO_FN(ON_ALE),
+	GPIO_FN(ON_CLE),
+	GPIO_FN(TCLK),
 
 	/* PTC (mobule: IRQ, PWMU) */
-	PINMUX_GPIO(GPIO_FN_IRQ7, IRQ7_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ6, IRQ6_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ5, IRQ5_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ4, IRQ4_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ3, IRQ3_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ2, IRQ2_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ1, IRQ1_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ0, IRQ0_MARK),
-	PINMUX_GPIO(GPIO_FN_PWMU0, PWMU0_MARK),
-	PINMUX_GPIO(GPIO_FN_PWMU1, PWMU1_MARK),
-	PINMUX_GPIO(GPIO_FN_PWMU2, PWMU2_MARK),
-	PINMUX_GPIO(GPIO_FN_PWMU3, PWMU3_MARK),
-	PINMUX_GPIO(GPIO_FN_PWMU4, PWMU4_MARK),
-	PINMUX_GPIO(GPIO_FN_PWMU5, PWMU5_MARK),
+	GPIO_FN(IRQ7),
+	GPIO_FN(IRQ6),
+	GPIO_FN(IRQ5),
+	GPIO_FN(IRQ4),
+	GPIO_FN(IRQ3),
+	GPIO_FN(IRQ2),
+	GPIO_FN(IRQ1),
+	GPIO_FN(IRQ0),
+	GPIO_FN(PWMU0),
+	GPIO_FN(PWMU1),
+	GPIO_FN(PWMU2),
+	GPIO_FN(PWMU3),
+	GPIO_FN(PWMU4),
+	GPIO_FN(PWMU5),
 
 	/* PTD (mobule: SPI0, DMAC) */
-	PINMUX_GPIO(GPIO_FN_SP0_MOSI, SP0_MOSI_MARK),
-	PINMUX_GPIO(GPIO_FN_SP0_MISO, SP0_MISO_MARK),
-	PINMUX_GPIO(GPIO_FN_SP0_SCK, SP0_SCK_MARK),
-	PINMUX_GPIO(GPIO_FN_SP0_SCK_FB, SP0_SCK_FB_MARK),
-	PINMUX_GPIO(GPIO_FN_SP0_SS0, SP0_SS0_MARK),
-	PINMUX_GPIO(GPIO_FN_SP0_SS1, SP0_SS1_MARK),
-	PINMUX_GPIO(GPIO_FN_SP0_SS2, SP0_SS2_MARK),
-	PINMUX_GPIO(GPIO_FN_SP0_SS3, SP0_SS3_MARK),
-	PINMUX_GPIO(GPIO_FN_DREQ0, DREQ0_MARK),
-	PINMUX_GPIO(GPIO_FN_DACK0, DACK0_MARK),
-	PINMUX_GPIO(GPIO_FN_TEND0, TEND0_MARK),
+	GPIO_FN(SP0_MOSI),
+	GPIO_FN(SP0_MISO),
+	GPIO_FN(SP0_SCK),
+	GPIO_FN(SP0_SCK_FB),
+	GPIO_FN(SP0_SS0),
+	GPIO_FN(SP0_SS1),
+	GPIO_FN(SP0_SS2),
+	GPIO_FN(SP0_SS3),
+	GPIO_FN(DREQ0),
+	GPIO_FN(DACK0),
+	GPIO_FN(TEND0),
 
 	/* PTE (mobule: RMII) */
-	PINMUX_GPIO(GPIO_FN_RMII0_CRS_DV, RMII0_CRS_DV_MARK),
-	PINMUX_GPIO(GPIO_FN_RMII0_TXD1, RMII0_TXD1_MARK),
-	PINMUX_GPIO(GPIO_FN_RMII0_TXD0, RMII0_TXD0_MARK),
-	PINMUX_GPIO(GPIO_FN_RMII0_TXEN, RMII0_TXEN_MARK),
-	PINMUX_GPIO(GPIO_FN_RMII0_REFCLK, RMII0_REFCLK_MARK),
-	PINMUX_GPIO(GPIO_FN_RMII0_RXD1, RMII0_RXD1_MARK),
-	PINMUX_GPIO(GPIO_FN_RMII0_RXD0, RMII0_RXD0_MARK),
-	PINMUX_GPIO(GPIO_FN_RMII0_RX_ER, RMII0_RX_ER_MARK),
+	GPIO_FN(RMII0_CRS_DV),
+	GPIO_FN(RMII0_TXD1),
+	GPIO_FN(RMII0_TXD0),
+	GPIO_FN(RMII0_TXEN),
+	GPIO_FN(RMII0_REFCLK),
+	GPIO_FN(RMII0_RXD1),
+	GPIO_FN(RMII0_RXD0),
+	GPIO_FN(RMII0_RX_ER),
 
 	/* PTF (mobule: RMII, SerMux) */
-	PINMUX_GPIO(GPIO_FN_RMII1_CRS_DV, RMII1_CRS_DV_MARK),
-	PINMUX_GPIO(GPIO_FN_RMII1_TXD1, RMII1_TXD1_MARK),
-	PINMUX_GPIO(GPIO_FN_RMII1_TXD0, RMII1_TXD0_MARK),
-	PINMUX_GPIO(GPIO_FN_RMII1_TXEN, RMII1_TXEN_MARK),
-	PINMUX_GPIO(GPIO_FN_RMII1_REFCLK, RMII1_REFCLK_MARK),
-	PINMUX_GPIO(GPIO_FN_RMII1_RXD1, RMII1_RXD1_MARK),
-	PINMUX_GPIO(GPIO_FN_RMII1_RXD0, RMII1_RXD0_MARK),
-	PINMUX_GPIO(GPIO_FN_RMII1_RX_ER, RMII1_RX_ER_MARK),
-	PINMUX_GPIO(GPIO_FN_RAC_RI, RAC_RI_MARK),
+	GPIO_FN(RMII1_CRS_DV),
+	GPIO_FN(RMII1_TXD1),
+	GPIO_FN(RMII1_TXD0),
+	GPIO_FN(RMII1_TXEN),
+	GPIO_FN(RMII1_REFCLK),
+	GPIO_FN(RMII1_RXD1),
+	GPIO_FN(RMII1_RXD0),
+	GPIO_FN(RMII1_RX_ER),
+	GPIO_FN(RAC_RI),
 
 	/* PTG (mobule: system, LBSC, LPC, WDT, LPC, eMMC) */
-	PINMUX_GPIO(GPIO_FN_BOOTFMS, BOOTFMS_MARK),
-	PINMUX_GPIO(GPIO_FN_BOOTWP, BOOTWP_MARK),
-	PINMUX_GPIO(GPIO_FN_A25, A25_MARK),
-	PINMUX_GPIO(GPIO_FN_A24, A24_MARK),
-	PINMUX_GPIO(GPIO_FN_SERIRQ, SERIRQ_MARK),
-	PINMUX_GPIO(GPIO_FN_WDTOVF, WDTOVF_MARK),
-	PINMUX_GPIO(GPIO_FN_LPCPD, LPCPD_MARK),
-	PINMUX_GPIO(GPIO_FN_LDRQ, LDRQ_MARK),
-	PINMUX_GPIO(GPIO_FN_MMCCLK, MMCCLK_MARK),
-	PINMUX_GPIO(GPIO_FN_MMCCMD, MMCCMD_MARK),
+	GPIO_FN(BOOTFMS),
+	GPIO_FN(BOOTWP),
+	GPIO_FN(A25),
+	GPIO_FN(A24),
+	GPIO_FN(SERIRQ),
+	GPIO_FN(WDTOVF),
+	GPIO_FN(LPCPD),
+	GPIO_FN(LDRQ),
+	GPIO_FN(MMCCLK),
+	GPIO_FN(MMCCMD),
 
 	/* PTH (mobule: SPI1, LPC, DMAC, ADC) */
-	PINMUX_GPIO(GPIO_FN_SP1_MOSI, SP1_MOSI_MARK),
-	PINMUX_GPIO(GPIO_FN_SP1_MISO, SP1_MISO_MARK),
-	PINMUX_GPIO(GPIO_FN_SP1_SCK, SP1_SCK_MARK),
-	PINMUX_GPIO(GPIO_FN_SP1_SCK_FB, SP1_SCK_FB_MARK),
-	PINMUX_GPIO(GPIO_FN_SP1_SS0, SP1_SS0_MARK),
-	PINMUX_GPIO(GPIO_FN_SP1_SS1, SP1_SS1_MARK),
-	PINMUX_GPIO(GPIO_FN_WP, WP_MARK),
-	PINMUX_GPIO(GPIO_FN_FMS0, FMS0_MARK),
-	PINMUX_GPIO(GPIO_FN_TEND1, TEND1_MARK),
-	PINMUX_GPIO(GPIO_FN_DREQ1, DREQ1_MARK),
-	PINMUX_GPIO(GPIO_FN_DACK1, DACK1_MARK),
-	PINMUX_GPIO(GPIO_FN_ADTRG1, ADTRG1_MARK),
-	PINMUX_GPIO(GPIO_FN_ADTRG0, ADTRG0_MARK),
+	GPIO_FN(SP1_MOSI),
+	GPIO_FN(SP1_MISO),
+	GPIO_FN(SP1_SCK),
+	GPIO_FN(SP1_SCK_FB),
+	GPIO_FN(SP1_SS0),
+	GPIO_FN(SP1_SS1),
+	GPIO_FN(WP),
+	GPIO_FN(FMS0),
+	GPIO_FN(TEND1),
+	GPIO_FN(DREQ1),
+	GPIO_FN(DACK1),
+	GPIO_FN(ADTRG1),
+	GPIO_FN(ADTRG0),
 
 	/* PTI (mobule: LBSC, SDHI) */
-	PINMUX_GPIO(GPIO_FN_D15, D15_MARK),
-	PINMUX_GPIO(GPIO_FN_D14, D14_MARK),
-	PINMUX_GPIO(GPIO_FN_D13, D13_MARK),
-	PINMUX_GPIO(GPIO_FN_D12, D12_MARK),
-	PINMUX_GPIO(GPIO_FN_D11, D11_MARK),
-	PINMUX_GPIO(GPIO_FN_D10, D10_MARK),
-	PINMUX_GPIO(GPIO_FN_D9, D9_MARK),
-	PINMUX_GPIO(GPIO_FN_D8, D8_MARK),
-	PINMUX_GPIO(GPIO_FN_SD_WP, SD_WP_MARK),
-	PINMUX_GPIO(GPIO_FN_SD_CD, SD_CD_MARK),
-	PINMUX_GPIO(GPIO_FN_SD_CLK, SD_CLK_MARK),
-	PINMUX_GPIO(GPIO_FN_SD_CMD, SD_CMD_MARK),
-	PINMUX_GPIO(GPIO_FN_SD_D3, SD_D3_MARK),
-	PINMUX_GPIO(GPIO_FN_SD_D2, SD_D2_MARK),
-	PINMUX_GPIO(GPIO_FN_SD_D1, SD_D1_MARK),
-	PINMUX_GPIO(GPIO_FN_SD_D0, SD_D0_MARK),
+	GPIO_FN(D15),
+	GPIO_FN(D14),
+	GPIO_FN(D13),
+	GPIO_FN(D12),
+	GPIO_FN(D11),
+	GPIO_FN(D10),
+	GPIO_FN(D9),
+	GPIO_FN(D8),
+	GPIO_FN(SD_WP),
+	GPIO_FN(SD_CD),
+	GPIO_FN(SD_CLK),
+	GPIO_FN(SD_CMD),
+	GPIO_FN(SD_D3),
+	GPIO_FN(SD_D2),
+	GPIO_FN(SD_D1),
+	GPIO_FN(SD_D0),
 
 	/* PTJ (mobule: SCIF234, SERMUX) */
-	PINMUX_GPIO(GPIO_FN_RTS3, RTS3_MARK),
-	PINMUX_GPIO(GPIO_FN_CTS3, CTS3_MARK),
-	PINMUX_GPIO(GPIO_FN_TXD3, TXD3_MARK),
-	PINMUX_GPIO(GPIO_FN_RXD3, RXD3_MARK),
-	PINMUX_GPIO(GPIO_FN_RTS4, RTS4_MARK),
-	PINMUX_GPIO(GPIO_FN_RXD4, RXD4_MARK),
-	PINMUX_GPIO(GPIO_FN_TXD4, TXD4_MARK),
+	GPIO_FN(RTS3),
+	GPIO_FN(CTS3),
+	GPIO_FN(TXD3),
+	GPIO_FN(RXD3),
+	GPIO_FN(RTS4),
+	GPIO_FN(RXD4),
+	GPIO_FN(TXD4),
 
 	/* PTK (mobule: SERMUX, LBSC, SCIF) */
-	PINMUX_GPIO(GPIO_FN_COM2_TXD, COM2_TXD_MARK),
-	PINMUX_GPIO(GPIO_FN_COM2_RXD, COM2_RXD_MARK),
-	PINMUX_GPIO(GPIO_FN_COM2_RTS, COM2_RTS_MARK),
-	PINMUX_GPIO(GPIO_FN_COM2_CTS, COM2_CTS_MARK),
-	PINMUX_GPIO(GPIO_FN_COM2_DTR, COM2_DTR_MARK),
-	PINMUX_GPIO(GPIO_FN_COM2_DSR, COM2_DSR_MARK),
-	PINMUX_GPIO(GPIO_FN_COM2_DCD, COM2_DCD_MARK),
-	PINMUX_GPIO(GPIO_FN_CLKOUT, CLKOUT_MARK),
-	PINMUX_GPIO(GPIO_FN_SCK2, SCK2_MARK),
-	PINMUX_GPIO(GPIO_FN_SCK4, SCK4_MARK),
-	PINMUX_GPIO(GPIO_FN_SCK3, SCK3_MARK),
+	GPIO_FN(COM2_TXD),
+	GPIO_FN(COM2_RXD),
+	GPIO_FN(COM2_RTS),
+	GPIO_FN(COM2_CTS),
+	GPIO_FN(COM2_DTR),
+	GPIO_FN(COM2_DSR),
+	GPIO_FN(COM2_DCD),
+	GPIO_FN(CLKOUT),
+	GPIO_FN(SCK2),
+	GPIO_FN(SCK4),
+	GPIO_FN(SCK3),
 
 	/* PTL (mobule: SERMUX, SCIF, LBSC, AUD) */
-	PINMUX_GPIO(GPIO_FN_RAC_RXD, RAC_RXD_MARK),
-	PINMUX_GPIO(GPIO_FN_RAC_RTS, RAC_RTS_MARK),
-	PINMUX_GPIO(GPIO_FN_RAC_CTS, RAC_CTS_MARK),
-	PINMUX_GPIO(GPIO_FN_RAC_DTR, RAC_DTR_MARK),
-	PINMUX_GPIO(GPIO_FN_RAC_DSR, RAC_DSR_MARK),
-	PINMUX_GPIO(GPIO_FN_RAC_DCD, RAC_DCD_MARK),
-	PINMUX_GPIO(GPIO_FN_RAC_TXD, RAC_TXD_MARK),
-	PINMUX_GPIO(GPIO_FN_RXD2, RXD2_MARK),
-	PINMUX_GPIO(GPIO_FN_CS5, CS5_MARK),
-	PINMUX_GPIO(GPIO_FN_CS6, CS6_MARK),
-	PINMUX_GPIO(GPIO_FN_AUDSYNC, AUDSYNC_MARK),
-	PINMUX_GPIO(GPIO_FN_AUDCK, AUDCK_MARK),
-	PINMUX_GPIO(GPIO_FN_TXD2, TXD2_MARK),
+	GPIO_FN(RAC_RXD),
+	GPIO_FN(RAC_RTS),
+	GPIO_FN(RAC_CTS),
+	GPIO_FN(RAC_DTR),
+	GPIO_FN(RAC_DSR),
+	GPIO_FN(RAC_DCD),
+	GPIO_FN(RAC_TXD),
+	GPIO_FN(RXD2),
+	GPIO_FN(CS5),
+	GPIO_FN(CS6),
+	GPIO_FN(AUDSYNC),
+	GPIO_FN(AUDCK),
+	GPIO_FN(TXD2),
 
 	/* PTM (mobule: LBSC, IIC) */
-	PINMUX_GPIO(GPIO_FN_CS4, CS4_MARK),
-	PINMUX_GPIO(GPIO_FN_RD, RD_MARK),
-	PINMUX_GPIO(GPIO_FN_WE0, WE0_MARK),
-	PINMUX_GPIO(GPIO_FN_CS0, CS0_MARK),
-	PINMUX_GPIO(GPIO_FN_SDA6, SDA6_MARK),
-	PINMUX_GPIO(GPIO_FN_SCL6, SCL6_MARK),
-	PINMUX_GPIO(GPIO_FN_SDA7, SDA7_MARK),
-	PINMUX_GPIO(GPIO_FN_SCL7, SCL7_MARK),
+	GPIO_FN(CS4),
+	GPIO_FN(RD),
+	GPIO_FN(WE0),
+	GPIO_FN(CS0),
+	GPIO_FN(SDA6),
+	GPIO_FN(SCL6),
+	GPIO_FN(SDA7),
+	GPIO_FN(SCL7),
 
 	/* PTN (mobule: USB, JMC, SGPIO, WDT) */
-	PINMUX_GPIO(GPIO_FN_VBUS_EN, VBUS_EN_MARK),
-	PINMUX_GPIO(GPIO_FN_VBUS_OC, VBUS_OC_MARK),
-	PINMUX_GPIO(GPIO_FN_JMCTCK, JMCTCK_MARK),
-	PINMUX_GPIO(GPIO_FN_JMCTMS, JMCTMS_MARK),
-	PINMUX_GPIO(GPIO_FN_JMCTDO, JMCTDO_MARK),
-	PINMUX_GPIO(GPIO_FN_JMCTDI, JMCTDI_MARK),
-	PINMUX_GPIO(GPIO_FN_JMCTRST, JMCTRST_MARK),
-	PINMUX_GPIO(GPIO_FN_SGPIO1_CLK, SGPIO1_CLK_MARK),
-	PINMUX_GPIO(GPIO_FN_SGPIO1_LOAD, SGPIO1_LOAD_MARK),
-	PINMUX_GPIO(GPIO_FN_SGPIO1_DI, SGPIO1_DI_MARK),
-	PINMUX_GPIO(GPIO_FN_SGPIO1_DO, SGPIO1_DO_MARK),
-	PINMUX_GPIO(GPIO_FN_SUB_CLKIN, SUB_CLKIN_MARK),
+	GPIO_FN(VBUS_EN),
+	GPIO_FN(VBUS_OC),
+	GPIO_FN(JMCTCK),
+	GPIO_FN(JMCTMS),
+	GPIO_FN(JMCTDO),
+	GPIO_FN(JMCTDI),
+	GPIO_FN(JMCTRST),
+	GPIO_FN(SGPIO1_CLK),
+	GPIO_FN(SGPIO1_LOAD),
+	GPIO_FN(SGPIO1_DI),
+	GPIO_FN(SGPIO1_DO),
+	GPIO_FN(SUB_CLKIN),
 
 	/* PTO (mobule: SGPIO, SerMux) */
-	PINMUX_GPIO(GPIO_FN_SGPIO0_CLK, SGPIO0_CLK_MARK),
-	PINMUX_GPIO(GPIO_FN_SGPIO0_LOAD, SGPIO0_LOAD_MARK),
-	PINMUX_GPIO(GPIO_FN_SGPIO0_DI, SGPIO0_DI_MARK),
-	PINMUX_GPIO(GPIO_FN_SGPIO0_DO, SGPIO0_DO_MARK),
-	PINMUX_GPIO(GPIO_FN_SGPIO2_CLK, SGPIO2_CLK_MARK),
-	PINMUX_GPIO(GPIO_FN_SGPIO2_LOAD, SGPIO2_LOAD_MARK),
-	PINMUX_GPIO(GPIO_FN_SGPIO2_DI, SGPIO2_DI_MARK),
-	PINMUX_GPIO(GPIO_FN_SGPIO2_DO, SGPIO2_DO_MARK),
-	PINMUX_GPIO(GPIO_FN_COM1_TXD, COM1_TXD_MARK),
-	PINMUX_GPIO(GPIO_FN_COM1_RXD, COM1_RXD_MARK),
-	PINMUX_GPIO(GPIO_FN_COM1_RTS, COM1_RTS_MARK),
-	PINMUX_GPIO(GPIO_FN_COM1_CTS, COM1_CTS_MARK),
+	GPIO_FN(SGPIO0_CLK),
+	GPIO_FN(SGPIO0_LOAD),
+	GPIO_FN(SGPIO0_DI),
+	GPIO_FN(SGPIO0_DO),
+	GPIO_FN(SGPIO2_CLK),
+	GPIO_FN(SGPIO2_LOAD),
+	GPIO_FN(SGPIO2_DI),
+	GPIO_FN(SGPIO2_DO),
+	GPIO_FN(COM1_TXD),
+	GPIO_FN(COM1_RXD),
+	GPIO_FN(COM1_RTS),
+	GPIO_FN(COM1_CTS),
 
 	/* PTP (mobule: EVC, ADC) */
 
 	/* PTQ (mobule: LPC) */
-	PINMUX_GPIO(GPIO_FN_LAD3, LAD3_MARK),
-	PINMUX_GPIO(GPIO_FN_LAD2, LAD2_MARK),
-	PINMUX_GPIO(GPIO_FN_LAD1, LAD1_MARK),
-	PINMUX_GPIO(GPIO_FN_LAD0, LAD0_MARK),
-	PINMUX_GPIO(GPIO_FN_LFRAME, LFRAME_MARK),
-	PINMUX_GPIO(GPIO_FN_LRESET, LRESET_MARK),
-	PINMUX_GPIO(GPIO_FN_LCLK, LCLK_MARK),
+	GPIO_FN(LAD3),
+	GPIO_FN(LAD2),
+	GPIO_FN(LAD1),
+	GPIO_FN(LAD0),
+	GPIO_FN(LFRAME),
+	GPIO_FN(LRESET),
+	GPIO_FN(LCLK),
 
 	/* PTR (mobule: GRA, IIC) */
-	PINMUX_GPIO(GPIO_FN_DDC3, DDC3_MARK),
-	PINMUX_GPIO(GPIO_FN_DDC2, DDC2_MARK),
-	PINMUX_GPIO(GPIO_FN_SDA8, SDA8_MARK),
-	PINMUX_GPIO(GPIO_FN_SCL8, SCL8_MARK),
-	PINMUX_GPIO(GPIO_FN_SDA2, SDA2_MARK),
-	PINMUX_GPIO(GPIO_FN_SCL2, SCL2_MARK),
-	PINMUX_GPIO(GPIO_FN_SDA1, SDA1_MARK),
-	PINMUX_GPIO(GPIO_FN_SCL1, SCL1_MARK),
-	PINMUX_GPIO(GPIO_FN_SDA0, SDA0_MARK),
-	PINMUX_GPIO(GPIO_FN_SCL0, SCL0_MARK),
+	GPIO_FN(DDC3),
+	GPIO_FN(DDC2),
+	GPIO_FN(SDA8),
+	GPIO_FN(SCL8),
+	GPIO_FN(SDA2),
+	GPIO_FN(SCL2),
+	GPIO_FN(SDA1),
+	GPIO_FN(SCL1),
+	GPIO_FN(SDA0),
+	GPIO_FN(SCL0),
 
 	/* PTS (mobule: GRA, IIC) */
-	PINMUX_GPIO(GPIO_FN_DDC1, DDC1_MARK),
-	PINMUX_GPIO(GPIO_FN_DDC0, DDC0_MARK),
-	PINMUX_GPIO(GPIO_FN_SDA9, SDA9_MARK),
-	PINMUX_GPIO(GPIO_FN_SCL9, SCL9_MARK),
-	PINMUX_GPIO(GPIO_FN_SDA5, SDA5_MARK),
-	PINMUX_GPIO(GPIO_FN_SCL5, SCL5_MARK),
-	PINMUX_GPIO(GPIO_FN_SDA4, SDA4_MARK),
-	PINMUX_GPIO(GPIO_FN_SCL4, SCL4_MARK),
-	PINMUX_GPIO(GPIO_FN_SDA3, SDA3_MARK),
-	PINMUX_GPIO(GPIO_FN_SCL3, SCL3_MARK),
+	GPIO_FN(DDC1),
+	GPIO_FN(DDC0),
+	GPIO_FN(SDA9),
+	GPIO_FN(SCL9),
+	GPIO_FN(SDA5),
+	GPIO_FN(SCL5),
+	GPIO_FN(SDA4),
+	GPIO_FN(SCL4),
+	GPIO_FN(SDA3),
+	GPIO_FN(SCL3),
 
 	/* PTT (mobule: PWMX, AUD) */
-	PINMUX_GPIO(GPIO_FN_PWMX7, PWMX7_MARK),
-	PINMUX_GPIO(GPIO_FN_PWMX6, PWMX6_MARK),
-	PINMUX_GPIO(GPIO_FN_PWMX5, PWMX5_MARK),
-	PINMUX_GPIO(GPIO_FN_PWMX4, PWMX4_MARK),
-	PINMUX_GPIO(GPIO_FN_PWMX3, PWMX3_MARK),
-	PINMUX_GPIO(GPIO_FN_PWMX2, PWMX2_MARK),
-	PINMUX_GPIO(GPIO_FN_PWMX1, PWMX1_MARK),
-	PINMUX_GPIO(GPIO_FN_PWMX0, PWMX0_MARK),
-	PINMUX_GPIO(GPIO_FN_AUDATA3, AUDATA3_MARK),
-	PINMUX_GPIO(GPIO_FN_AUDATA2, AUDATA2_MARK),
-	PINMUX_GPIO(GPIO_FN_AUDATA1, AUDATA1_MARK),
-	PINMUX_GPIO(GPIO_FN_AUDATA0, AUDATA0_MARK),
-	PINMUX_GPIO(GPIO_FN_STATUS1, STATUS1_MARK),
-	PINMUX_GPIO(GPIO_FN_STATUS0, STATUS0_MARK),
+	GPIO_FN(PWMX7),
+	GPIO_FN(PWMX6),
+	GPIO_FN(PWMX5),
+	GPIO_FN(PWMX4),
+	GPIO_FN(PWMX3),
+	GPIO_FN(PWMX2),
+	GPIO_FN(PWMX1),
+	GPIO_FN(PWMX0),
+	GPIO_FN(AUDATA3),
+	GPIO_FN(AUDATA2),
+	GPIO_FN(AUDATA1),
+	GPIO_FN(AUDATA0),
+	GPIO_FN(STATUS1),
+	GPIO_FN(STATUS0),
 
 	/* PTU (mobule: LPC, APM) */
-	PINMUX_GPIO(GPIO_FN_LGPIO7, LGPIO7_MARK),
-	PINMUX_GPIO(GPIO_FN_LGPIO6, LGPIO6_MARK),
-	PINMUX_GPIO(GPIO_FN_LGPIO5, LGPIO5_MARK),
-	PINMUX_GPIO(GPIO_FN_LGPIO4, LGPIO4_MARK),
-	PINMUX_GPIO(GPIO_FN_LGPIO3, LGPIO3_MARK),
-	PINMUX_GPIO(GPIO_FN_LGPIO2, LGPIO2_MARK),
-	PINMUX_GPIO(GPIO_FN_LGPIO1, LGPIO1_MARK),
-	PINMUX_GPIO(GPIO_FN_LGPIO0, LGPIO0_MARK),
-	PINMUX_GPIO(GPIO_FN_APMONCTL_O, APMONCTL_O_MARK),
-	PINMUX_GPIO(GPIO_FN_APMPWBTOUT_O, APMPWBTOUT_O_MARK),
-	PINMUX_GPIO(GPIO_FN_APMSCI_O, APMSCI_O_MARK),
-	PINMUX_GPIO(GPIO_FN_APMVDDON, APMVDDON_MARK),
-	PINMUX_GPIO(GPIO_FN_APMSLPBTN, APMSLPBTN_MARK),
-	PINMUX_GPIO(GPIO_FN_APMPWRBTN, APMPWRBTN_MARK),
-	PINMUX_GPIO(GPIO_FN_APMS5N, APMS5N_MARK),
-	PINMUX_GPIO(GPIO_FN_APMS3N, APMS3N_MARK),
+	GPIO_FN(LGPIO7),
+	GPIO_FN(LGPIO6),
+	GPIO_FN(LGPIO5),
+	GPIO_FN(LGPIO4),
+	GPIO_FN(LGPIO3),
+	GPIO_FN(LGPIO2),
+	GPIO_FN(LGPIO1),
+	GPIO_FN(LGPIO0),
+	GPIO_FN(APMONCTL_O),
+	GPIO_FN(APMPWBTOUT_O),
+	GPIO_FN(APMSCI_O),
+	GPIO_FN(APMVDDON),
+	GPIO_FN(APMSLPBTN),
+	GPIO_FN(APMPWRBTN),
+	GPIO_FN(APMS5N),
+	GPIO_FN(APMS3N),
 
 	/* PTV (mobule: LBSC, SerMux, R-SPI, EVC, GRA) */
-	PINMUX_GPIO(GPIO_FN_A23, A23_MARK),
-	PINMUX_GPIO(GPIO_FN_A22, A22_MARK),
-	PINMUX_GPIO(GPIO_FN_A21, A21_MARK),
-	PINMUX_GPIO(GPIO_FN_A20, A20_MARK),
-	PINMUX_GPIO(GPIO_FN_A19, A19_MARK),
-	PINMUX_GPIO(GPIO_FN_A18, A18_MARK),
-	PINMUX_GPIO(GPIO_FN_A17, A17_MARK),
-	PINMUX_GPIO(GPIO_FN_A16, A16_MARK),
-	PINMUX_GPIO(GPIO_FN_COM2_RI, COM2_RI_MARK),
-	PINMUX_GPIO(GPIO_FN_R_SPI_MOSI, R_SPI_MOSI_MARK),
-	PINMUX_GPIO(GPIO_FN_R_SPI_MISO, R_SPI_MISO_MARK),
-	PINMUX_GPIO(GPIO_FN_R_SPI_RSPCK, R_SPI_RSPCK_MARK),
-	PINMUX_GPIO(GPIO_FN_R_SPI_SSL0, R_SPI_SSL0_MARK),
-	PINMUX_GPIO(GPIO_FN_R_SPI_SSL1, R_SPI_SSL1_MARK),
-	PINMUX_GPIO(GPIO_FN_EVENT7, EVENT7_MARK),
-	PINMUX_GPIO(GPIO_FN_EVENT6, EVENT6_MARK),
-	PINMUX_GPIO(GPIO_FN_VBIOS_DI, VBIOS_DI_MARK),
-	PINMUX_GPIO(GPIO_FN_VBIOS_DO, VBIOS_DO_MARK),
-	PINMUX_GPIO(GPIO_FN_VBIOS_CLK, VBIOS_CLK_MARK),
-	PINMUX_GPIO(GPIO_FN_VBIOS_CS, VBIOS_CS_MARK),
+	GPIO_FN(A23),
+	GPIO_FN(A22),
+	GPIO_FN(A21),
+	GPIO_FN(A20),
+	GPIO_FN(A19),
+	GPIO_FN(A18),
+	GPIO_FN(A17),
+	GPIO_FN(A16),
+	GPIO_FN(COM2_RI),
+	GPIO_FN(R_SPI_MOSI),
+	GPIO_FN(R_SPI_MISO),
+	GPIO_FN(R_SPI_RSPCK),
+	GPIO_FN(R_SPI_SSL0),
+	GPIO_FN(R_SPI_SSL1),
+	GPIO_FN(EVENT7),
+	GPIO_FN(EVENT6),
+	GPIO_FN(VBIOS_DI),
+	GPIO_FN(VBIOS_DO),
+	GPIO_FN(VBIOS_CLK),
+	GPIO_FN(VBIOS_CS),
 
 	/* PTW (mobule: LBSC, EVC, SCIF) */
-	PINMUX_GPIO(GPIO_FN_A16, A16_MARK),
-	PINMUX_GPIO(GPIO_FN_A15, A15_MARK),
-	PINMUX_GPIO(GPIO_FN_A14, A14_MARK),
-	PINMUX_GPIO(GPIO_FN_A13, A13_MARK),
-	PINMUX_GPIO(GPIO_FN_A12, A12_MARK),
-	PINMUX_GPIO(GPIO_FN_A11, A11_MARK),
-	PINMUX_GPIO(GPIO_FN_A10, A10_MARK),
-	PINMUX_GPIO(GPIO_FN_A9, A9_MARK),
-	PINMUX_GPIO(GPIO_FN_A8, A8_MARK),
-	PINMUX_GPIO(GPIO_FN_EVENT5, EVENT5_MARK),
-	PINMUX_GPIO(GPIO_FN_EVENT4, EVENT4_MARK),
-	PINMUX_GPIO(GPIO_FN_EVENT3, EVENT3_MARK),
-	PINMUX_GPIO(GPIO_FN_EVENT2, EVENT2_MARK),
-	PINMUX_GPIO(GPIO_FN_EVENT1, EVENT1_MARK),
-	PINMUX_GPIO(GPIO_FN_EVENT0, EVENT0_MARK),
-	PINMUX_GPIO(GPIO_FN_CTS4, CTS4_MARK),
-	PINMUX_GPIO(GPIO_FN_CTS2, CTS2_MARK),
+	GPIO_FN(A16),
+	GPIO_FN(A15),
+	GPIO_FN(A14),
+	GPIO_FN(A13),
+	GPIO_FN(A12),
+	GPIO_FN(A11),
+	GPIO_FN(A10),
+	GPIO_FN(A9),
+	GPIO_FN(A8),
+	GPIO_FN(EVENT5),
+	GPIO_FN(EVENT4),
+	GPIO_FN(EVENT3),
+	GPIO_FN(EVENT2),
+	GPIO_FN(EVENT1),
+	GPIO_FN(EVENT0),
+	GPIO_FN(CTS4),
+	GPIO_FN(CTS2),
 
 	/* PTX (mobule: LBSC) */
-	PINMUX_GPIO(GPIO_FN_A7, A7_MARK),
-	PINMUX_GPIO(GPIO_FN_A6, A6_MARK),
-	PINMUX_GPIO(GPIO_FN_A5, A5_MARK),
-	PINMUX_GPIO(GPIO_FN_A4, A4_MARK),
-	PINMUX_GPIO(GPIO_FN_A3, A3_MARK),
-	PINMUX_GPIO(GPIO_FN_A2, A2_MARK),
-	PINMUX_GPIO(GPIO_FN_A1, A1_MARK),
-	PINMUX_GPIO(GPIO_FN_A0, A0_MARK),
-	PINMUX_GPIO(GPIO_FN_RTS2, RTS2_MARK),
-	PINMUX_GPIO(GPIO_FN_SIM_D, SIM_D_MARK),
-	PINMUX_GPIO(GPIO_FN_SIM_CLK, SIM_CLK_MARK),
-	PINMUX_GPIO(GPIO_FN_SIM_RST, SIM_RST_MARK),
+	GPIO_FN(A7),
+	GPIO_FN(A6),
+	GPIO_FN(A5),
+	GPIO_FN(A4),
+	GPIO_FN(A3),
+	GPIO_FN(A2),
+	GPIO_FN(A1),
+	GPIO_FN(A0),
+	GPIO_FN(RTS2),
+	GPIO_FN(SIM_D),
+	GPIO_FN(SIM_CLK),
+	GPIO_FN(SIM_RST),
 
 	/* PTY (mobule: LBSC) */
-	PINMUX_GPIO(GPIO_FN_D7, D7_MARK),
-	PINMUX_GPIO(GPIO_FN_D6, D6_MARK),
-	PINMUX_GPIO(GPIO_FN_D5, D5_MARK),
-	PINMUX_GPIO(GPIO_FN_D4, D4_MARK),
-	PINMUX_GPIO(GPIO_FN_D3, D3_MARK),
-	PINMUX_GPIO(GPIO_FN_D2, D2_MARK),
-	PINMUX_GPIO(GPIO_FN_D1, D1_MARK),
-	PINMUX_GPIO(GPIO_FN_D0, D0_MARK),
+	GPIO_FN(D7),
+	GPIO_FN(D6),
+	GPIO_FN(D5),
+	GPIO_FN(D4),
+	GPIO_FN(D3),
+	GPIO_FN(D2),
+	GPIO_FN(D1),
+	GPIO_FN(D0),
 
 	/* PTZ (mobule: eMMC, ONFI) */
-	PINMUX_GPIO(GPIO_FN_MMCDAT7, MMCDAT7_MARK),
-	PINMUX_GPIO(GPIO_FN_MMCDAT6, MMCDAT6_MARK),
-	PINMUX_GPIO(GPIO_FN_MMCDAT5, MMCDAT5_MARK),
-	PINMUX_GPIO(GPIO_FN_MMCDAT4, MMCDAT4_MARK),
-	PINMUX_GPIO(GPIO_FN_MMCDAT3, MMCDAT3_MARK),
-	PINMUX_GPIO(GPIO_FN_MMCDAT2, MMCDAT2_MARK),
-	PINMUX_GPIO(GPIO_FN_MMCDAT1, MMCDAT1_MARK),
-	PINMUX_GPIO(GPIO_FN_MMCDAT0, MMCDAT0_MARK),
-	PINMUX_GPIO(GPIO_FN_ON_DQ7, ON_DQ7_MARK),
-	PINMUX_GPIO(GPIO_FN_ON_DQ6, ON_DQ6_MARK),
-	PINMUX_GPIO(GPIO_FN_ON_DQ5, ON_DQ5_MARK),
-	PINMUX_GPIO(GPIO_FN_ON_DQ4, ON_DQ4_MARK),
-	PINMUX_GPIO(GPIO_FN_ON_DQ3, ON_DQ3_MARK),
-	PINMUX_GPIO(GPIO_FN_ON_DQ2, ON_DQ2_MARK),
-	PINMUX_GPIO(GPIO_FN_ON_DQ1, ON_DQ1_MARK),
-	PINMUX_GPIO(GPIO_FN_ON_DQ0, ON_DQ0_MARK),
+	GPIO_FN(MMCDAT7),
+	GPIO_FN(MMCDAT6),
+	GPIO_FN(MMCDAT5),
+	GPIO_FN(MMCDAT4),
+	GPIO_FN(MMCDAT3),
+	GPIO_FN(MMCDAT2),
+	GPIO_FN(MMCDAT1),
+	GPIO_FN(MMCDAT0),
+	GPIO_FN(ON_DQ7),
+	GPIO_FN(ON_DQ6),
+	GPIO_FN(ON_DQ5),
+	GPIO_FN(ON_DQ4),
+	GPIO_FN(ON_DQ3),
+	GPIO_FN(ON_DQ2),
+	GPIO_FN(ON_DQ1),
+	GPIO_FN(ON_DQ0),
 };
 
-static struct pinmux_cfg_reg pinmux_config_regs[] = {
+static const struct pinmux_cfg_reg pinmux_config_regs[] = {
 	{ PINMUX_CFG_REG("PACR", 0xffec0000, 16, 2) {
 		PTA7_FN, PTA7_OUT, PTA7_IN, PTA7_IN_PU,
 		PTA6_FN, PTA6_OUT, PTA6_IN, PTA6_IN_PU,
@@ -2152,7 +2156,7 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = {
 	{}
 };
 
-static struct pinmux_data_reg pinmux_data_regs[] = {
+static const struct pinmux_data_reg pinmux_data_regs[] = {
 	{ PINMUX_DATA_REG("PADR", 0xffec0034, 8) {
 		PTA7_DATA, PTA6_DATA, PTA5_DATA, PTA4_DATA,
 		PTA3_DATA, PTA2_DATA, PTA1_DATA, PTA0_DATA }
@@ -2260,20 +2264,18 @@ static struct pinmux_data_reg pinmux_data_regs[] = {
 	{ },
 };
 
-struct sh_pfc_soc_info sh7757_pinmux_info = {
+const struct sh_pfc_soc_info sh7757_pinmux_info = {
 	.name = "sh7757_pfc",
-	.reserved_id = PINMUX_RESERVED,
-	.data = { PINMUX_DATA_BEGIN, PINMUX_DATA_END },
 	.input = { PINMUX_INPUT_BEGIN, PINMUX_INPUT_END },
 	.input_pu = { PINMUX_INPUT_PULLUP_BEGIN, PINMUX_INPUT_PULLUP_END },
 	.output = { PINMUX_OUTPUT_BEGIN, PINMUX_OUTPUT_END },
-	.mark = { PINMUX_MARK_BEGIN, PINMUX_MARK_END },
 	.function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END },
 
-	.first_gpio = GPIO_PTA0,
-	.last_gpio = GPIO_FN_ON_DQ0,
+	.pins = pinmux_pins,
+	.nr_pins = ARRAY_SIZE(pinmux_pins),
+	.func_gpios = pinmux_func_gpios,
+	.nr_func_gpios = ARRAY_SIZE(pinmux_func_gpios),
 
-	.gpios = pinmux_gpios,
 	.cfg_regs = pinmux_config_regs,
 	.data_regs = pinmux_data_regs,
 
diff --git a/drivers/pinctrl/sh-pfc/pfc-sh7785.c b/drivers/pinctrl/sh-pfc/pfc-sh7785.c
index 3b1825d..c176b79 100644
--- a/drivers/pinctrl/sh-pfc/pfc-sh7785.c
+++ b/drivers/pinctrl/sh-pfc/pfc-sh7785.c
@@ -355,7 +355,7 @@ enum {
 	PINMUX_MARK_END,
 };
 
-static pinmux_enum_t pinmux_data[] = {
+static const pinmux_enum_t pinmux_data[] = {
 
 	/* PA GPIO */
 	PINMUX_DATA(PA7_DATA, PA7_IN, PA7_OUT, PA7_IN_PU),
@@ -702,7 +702,7 @@ static pinmux_enum_t pinmux_data[] = {
 	PINMUX_DATA(IRQOUT_MARK, P2MSEL2_1),
 };
 
-static struct pinmux_gpio pinmux_gpios[] = {
+static struct sh_pfc_pin pinmux_pins[] = {
 	/* PA */
 	PINMUX_GPIO(GPIO_PA7, PA7_DATA),
 	PINMUX_GPIO(GPIO_PA6, PA6_DATA),
@@ -845,176 +845,180 @@ static struct pinmux_gpio pinmux_gpios[] = {
 	PINMUX_GPIO(GPIO_PR2, PR2_DATA),
 	PINMUX_GPIO(GPIO_PR1, PR1_DATA),
 	PINMUX_GPIO(GPIO_PR0, PR0_DATA),
+};
+
+#define PINMUX_FN_BASE	ARRAY_SIZE(pinmux_pins)
 
+static const struct pinmux_func pinmux_func_gpios[] = {
 	/* FN */
-	PINMUX_GPIO(GPIO_FN_D63_AD31, D63_AD31_MARK),
-	PINMUX_GPIO(GPIO_FN_D62_AD30, D62_AD30_MARK),
-	PINMUX_GPIO(GPIO_FN_D61_AD29, D61_AD29_MARK),
-	PINMUX_GPIO(GPIO_FN_D60_AD28, D60_AD28_MARK),
-	PINMUX_GPIO(GPIO_FN_D59_AD27, D59_AD27_MARK),
-	PINMUX_GPIO(GPIO_FN_D58_AD26, D58_AD26_MARK),
-	PINMUX_GPIO(GPIO_FN_D57_AD25, D57_AD25_MARK),
-	PINMUX_GPIO(GPIO_FN_D56_AD24, D56_AD24_MARK),
-	PINMUX_GPIO(GPIO_FN_D55_AD23, D55_AD23_MARK),
-	PINMUX_GPIO(GPIO_FN_D54_AD22, D54_AD22_MARK),
-	PINMUX_GPIO(GPIO_FN_D53_AD21, D53_AD21_MARK),
-	PINMUX_GPIO(GPIO_FN_D52_AD20, D52_AD20_MARK),
-	PINMUX_GPIO(GPIO_FN_D51_AD19, D51_AD19_MARK),
-	PINMUX_GPIO(GPIO_FN_D50_AD18, D50_AD18_MARK),
-	PINMUX_GPIO(GPIO_FN_D49_AD17_DB5, D49_AD17_DB5_MARK),
-	PINMUX_GPIO(GPIO_FN_D48_AD16_DB4, D48_AD16_DB4_MARK),
-	PINMUX_GPIO(GPIO_FN_D47_AD15_DB3, D47_AD15_DB3_MARK),
-	PINMUX_GPIO(GPIO_FN_D46_AD14_DB2, D46_AD14_DB2_MARK),
-	PINMUX_GPIO(GPIO_FN_D45_AD13_DB1, D45_AD13_DB1_MARK),
-	PINMUX_GPIO(GPIO_FN_D44_AD12_DB0, D44_AD12_DB0_MARK),
-	PINMUX_GPIO(GPIO_FN_D43_AD11_DG5, D43_AD11_DG5_MARK),
-	PINMUX_GPIO(GPIO_FN_D42_AD10_DG4, D42_AD10_DG4_MARK),
-	PINMUX_GPIO(GPIO_FN_D41_AD9_DG3, D41_AD9_DG3_MARK),
-	PINMUX_GPIO(GPIO_FN_D40_AD8_DG2, D40_AD8_DG2_MARK),
-	PINMUX_GPIO(GPIO_FN_D39_AD7_DG1, D39_AD7_DG1_MARK),
-	PINMUX_GPIO(GPIO_FN_D38_AD6_DG0, D38_AD6_DG0_MARK),
-	PINMUX_GPIO(GPIO_FN_D37_AD5_DR5, D37_AD5_DR5_MARK),
-	PINMUX_GPIO(GPIO_FN_D36_AD4_DR4, D36_AD4_DR4_MARK),
-	PINMUX_GPIO(GPIO_FN_D35_AD3_DR3, D35_AD3_DR3_MARK),
-	PINMUX_GPIO(GPIO_FN_D34_AD2_DR2, D34_AD2_DR2_MARK),
-	PINMUX_GPIO(GPIO_FN_D33_AD1_DR1, D33_AD1_DR1_MARK),
-	PINMUX_GPIO(GPIO_FN_D32_AD0_DR0, D32_AD0_DR0_MARK),
-	PINMUX_GPIO(GPIO_FN_REQ1, REQ1_MARK),
-	PINMUX_GPIO(GPIO_FN_REQ2, REQ2_MARK),
-	PINMUX_GPIO(GPIO_FN_REQ3, REQ3_MARK),
-	PINMUX_GPIO(GPIO_FN_GNT1, GNT1_MARK),
-	PINMUX_GPIO(GPIO_FN_GNT2, GNT2_MARK),
-	PINMUX_GPIO(GPIO_FN_GNT3, GNT3_MARK),
-	PINMUX_GPIO(GPIO_FN_MMCCLK, MMCCLK_MARK),
-	PINMUX_GPIO(GPIO_FN_D31, D31_MARK),
-	PINMUX_GPIO(GPIO_FN_D30, D30_MARK),
-	PINMUX_GPIO(GPIO_FN_D29, D29_MARK),
-	PINMUX_GPIO(GPIO_FN_D28, D28_MARK),
-	PINMUX_GPIO(GPIO_FN_D27, D27_MARK),
-	PINMUX_GPIO(GPIO_FN_D26, D26_MARK),
-	PINMUX_GPIO(GPIO_FN_D25, D25_MARK),
-	PINMUX_GPIO(GPIO_FN_D24, D24_MARK),
-	PINMUX_GPIO(GPIO_FN_D23, D23_MARK),
-	PINMUX_GPIO(GPIO_FN_D22, D22_MARK),
-	PINMUX_GPIO(GPIO_FN_D21, D21_MARK),
-	PINMUX_GPIO(GPIO_FN_D20, D20_MARK),
-	PINMUX_GPIO(GPIO_FN_D19, D19_MARK),
-	PINMUX_GPIO(GPIO_FN_D18, D18_MARK),
-	PINMUX_GPIO(GPIO_FN_D17, D17_MARK),
-	PINMUX_GPIO(GPIO_FN_D16, D16_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF1_SCK, SCIF1_SCK_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF1_RXD, SCIF1_RXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF1_TXD, SCIF1_TXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF0_CTS, SCIF0_CTS_MARK),
-	PINMUX_GPIO(GPIO_FN_INTD, INTD_MARK),
-	PINMUX_GPIO(GPIO_FN_FCE, FCE_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF0_RTS, SCIF0_RTS_MARK),
-	PINMUX_GPIO(GPIO_FN_HSPI_CS, HSPI_CS_MARK),
-	PINMUX_GPIO(GPIO_FN_FSE, FSE_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF0_SCK, SCIF0_SCK_MARK),
-	PINMUX_GPIO(GPIO_FN_HSPI_CLK, HSPI_CLK_MARK),
-	PINMUX_GPIO(GPIO_FN_FRE, FRE_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF0_RXD, SCIF0_RXD_MARK),
-	PINMUX_GPIO(GPIO_FN_HSPI_RX, HSPI_RX_MARK),
-	PINMUX_GPIO(GPIO_FN_FRB, FRB_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF0_TXD, SCIF0_TXD_MARK),
-	PINMUX_GPIO(GPIO_FN_HSPI_TX, HSPI_TX_MARK),
-	PINMUX_GPIO(GPIO_FN_FWE, FWE_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF5_TXD, SCIF5_TXD_MARK),
-	PINMUX_GPIO(GPIO_FN_HAC1_SYNC, HAC1_SYNC_MARK),
-	PINMUX_GPIO(GPIO_FN_SSI1_WS, SSI1_WS_MARK),
-	PINMUX_GPIO(GPIO_FN_SIOF_TXD_PJ, SIOF_TXD_PJ_MARK),
-	PINMUX_GPIO(GPIO_FN_HAC0_SDOUT, HAC0_SDOUT_MARK),
-	PINMUX_GPIO(GPIO_FN_SSI0_SDATA, SSI0_SDATA_MARK),
-	PINMUX_GPIO(GPIO_FN_SIOF_RXD_PJ, SIOF_RXD_PJ_MARK),
-	PINMUX_GPIO(GPIO_FN_HAC0_SDIN, HAC0_SDIN_MARK),
-	PINMUX_GPIO(GPIO_FN_SSI0_SCK, SSI0_SCK_MARK),
-	PINMUX_GPIO(GPIO_FN_SIOF_SYNC_PJ, SIOF_SYNC_PJ_MARK),
-	PINMUX_GPIO(GPIO_FN_HAC0_SYNC, HAC0_SYNC_MARK),
-	PINMUX_GPIO(GPIO_FN_SSI0_WS, SSI0_WS_MARK),
-	PINMUX_GPIO(GPIO_FN_SIOF_MCLK_PJ, SIOF_MCLK_PJ_MARK),
-	PINMUX_GPIO(GPIO_FN_HAC_RES, HAC_RES_MARK),
-	PINMUX_GPIO(GPIO_FN_SIOF_SCK_PJ, SIOF_SCK_PJ_MARK),
-	PINMUX_GPIO(GPIO_FN_HAC0_BITCLK, HAC0_BITCLK_MARK),
-	PINMUX_GPIO(GPIO_FN_SSI0_CLK, SSI0_CLK_MARK),
-	PINMUX_GPIO(GPIO_FN_HAC1_BITCLK, HAC1_BITCLK_MARK),
-	PINMUX_GPIO(GPIO_FN_SSI1_CLK, SSI1_CLK_MARK),
-	PINMUX_GPIO(GPIO_FN_TCLK, TCLK_MARK),
-	PINMUX_GPIO(GPIO_FN_IOIS16, IOIS16_MARK),
-	PINMUX_GPIO(GPIO_FN_STATUS0, STATUS0_MARK),
-	PINMUX_GPIO(GPIO_FN_DRAK0_PK3, DRAK0_PK3_MARK),
-	PINMUX_GPIO(GPIO_FN_STATUS1, STATUS1_MARK),
-	PINMUX_GPIO(GPIO_FN_DRAK1_PK2, DRAK1_PK2_MARK),
-	PINMUX_GPIO(GPIO_FN_DACK2, DACK2_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF2_TXD, SCIF2_TXD_MARK),
-	PINMUX_GPIO(GPIO_FN_MMCCMD, MMCCMD_MARK),
-	PINMUX_GPIO(GPIO_FN_SIOF_TXD_PK, SIOF_TXD_PK_MARK),
-	PINMUX_GPIO(GPIO_FN_DACK3, DACK3_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF2_SCK, SCIF2_SCK_MARK),
-	PINMUX_GPIO(GPIO_FN_MMCDAT, MMCDAT_MARK),
-	PINMUX_GPIO(GPIO_FN_SIOF_SCK_PK, SIOF_SCK_PK_MARK),
-	PINMUX_GPIO(GPIO_FN_DREQ0, DREQ0_MARK),
-	PINMUX_GPIO(GPIO_FN_DREQ1, DREQ1_MARK),
-	PINMUX_GPIO(GPIO_FN_DRAK0_PK1, DRAK0_PK1_MARK),
-	PINMUX_GPIO(GPIO_FN_DRAK1_PK0, DRAK1_PK0_MARK),
-	PINMUX_GPIO(GPIO_FN_DREQ2, DREQ2_MARK),
-	PINMUX_GPIO(GPIO_FN_INTB, INTB_MARK),
-	PINMUX_GPIO(GPIO_FN_DREQ3, DREQ3_MARK),
-	PINMUX_GPIO(GPIO_FN_INTC, INTC_MARK),
-	PINMUX_GPIO(GPIO_FN_DRAK2, DRAK2_MARK),
-	PINMUX_GPIO(GPIO_FN_CE2A, CE2A_MARK),
-	PINMUX_GPIO(GPIO_FN_IRL4, IRL4_MARK),
-	PINMUX_GPIO(GPIO_FN_FD4, FD4_MARK),
-	PINMUX_GPIO(GPIO_FN_IRL5, IRL5_MARK),
-	PINMUX_GPIO(GPIO_FN_FD5, FD5_MARK),
-	PINMUX_GPIO(GPIO_FN_IRL6, IRL6_MARK),
-	PINMUX_GPIO(GPIO_FN_FD6, FD6_MARK),
-	PINMUX_GPIO(GPIO_FN_IRL7, IRL7_MARK),
-	PINMUX_GPIO(GPIO_FN_FD7, FD7_MARK),
-	PINMUX_GPIO(GPIO_FN_DRAK3, DRAK3_MARK),
-	PINMUX_GPIO(GPIO_FN_CE2B, CE2B_MARK),
-	PINMUX_GPIO(GPIO_FN_BREQ_BSACK, BREQ_BSACK_MARK),
-	PINMUX_GPIO(GPIO_FN_BACK_BSREQ, BACK_BSREQ_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF5_RXD, SCIF5_RXD_MARK),
-	PINMUX_GPIO(GPIO_FN_HAC1_SDIN, HAC1_SDIN_MARK),
-	PINMUX_GPIO(GPIO_FN_SSI1_SCK, SSI1_SCK_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF5_SCK, SCIF5_SCK_MARK),
-	PINMUX_GPIO(GPIO_FN_HAC1_SDOUT, HAC1_SDOUT_MARK),
-	PINMUX_GPIO(GPIO_FN_SSI1_SDATA, SSI1_SDATA_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF3_TXD, SCIF3_TXD_MARK),
-	PINMUX_GPIO(GPIO_FN_FCLE, FCLE_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF3_RXD, SCIF3_RXD_MARK),
-	PINMUX_GPIO(GPIO_FN_FALE, FALE_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF3_SCK, SCIF3_SCK_MARK),
-	PINMUX_GPIO(GPIO_FN_FD0, FD0_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF4_TXD, SCIF4_TXD_MARK),
-	PINMUX_GPIO(GPIO_FN_FD1, FD1_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF4_RXD, SCIF4_RXD_MARK),
-	PINMUX_GPIO(GPIO_FN_FD2, FD2_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF4_SCK, SCIF4_SCK_MARK),
-	PINMUX_GPIO(GPIO_FN_FD3, FD3_MARK),
-	PINMUX_GPIO(GPIO_FN_DEVSEL_DCLKOUT, DEVSEL_DCLKOUT_MARK),
-	PINMUX_GPIO(GPIO_FN_STOP_CDE, STOP_CDE_MARK),
-	PINMUX_GPIO(GPIO_FN_LOCK_ODDF, LOCK_ODDF_MARK),
-	PINMUX_GPIO(GPIO_FN_TRDY_DISPL, TRDY_DISPL_MARK),
-	PINMUX_GPIO(GPIO_FN_IRDY_HSYNC, IRDY_HSYNC_MARK),
-	PINMUX_GPIO(GPIO_FN_PCIFRAME_VSYNC, PCIFRAME_VSYNC_MARK),
-	PINMUX_GPIO(GPIO_FN_INTA, INTA_MARK),
-	PINMUX_GPIO(GPIO_FN_GNT0_GNTIN, GNT0_GNTIN_MARK),
-	PINMUX_GPIO(GPIO_FN_REQ0_REQOUT, REQ0_REQOUT_MARK),
-	PINMUX_GPIO(GPIO_FN_PERR, PERR_MARK),
-	PINMUX_GPIO(GPIO_FN_SERR, SERR_MARK),
-	PINMUX_GPIO(GPIO_FN_WE7_CBE3, WE7_CBE3_MARK),
-	PINMUX_GPIO(GPIO_FN_WE6_CBE2, WE6_CBE2_MARK),
-	PINMUX_GPIO(GPIO_FN_WE5_CBE1, WE5_CBE1_MARK),
-	PINMUX_GPIO(GPIO_FN_WE4_CBE0, WE4_CBE0_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF2_RXD, SCIF2_RXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SIOF_RXD, SIOF_RXD_MARK),
-	PINMUX_GPIO(GPIO_FN_MRESETOUT, MRESETOUT_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQOUT, IRQOUT_MARK),
+	GPIO_FN(D63_AD31),
+	GPIO_FN(D62_AD30),
+	GPIO_FN(D61_AD29),
+	GPIO_FN(D60_AD28),
+	GPIO_FN(D59_AD27),
+	GPIO_FN(D58_AD26),
+	GPIO_FN(D57_AD25),
+	GPIO_FN(D56_AD24),
+	GPIO_FN(D55_AD23),
+	GPIO_FN(D54_AD22),
+	GPIO_FN(D53_AD21),
+	GPIO_FN(D52_AD20),
+	GPIO_FN(D51_AD19),
+	GPIO_FN(D50_AD18),
+	GPIO_FN(D49_AD17_DB5),
+	GPIO_FN(D48_AD16_DB4),
+	GPIO_FN(D47_AD15_DB3),
+	GPIO_FN(D46_AD14_DB2),
+	GPIO_FN(D45_AD13_DB1),
+	GPIO_FN(D44_AD12_DB0),
+	GPIO_FN(D43_AD11_DG5),
+	GPIO_FN(D42_AD10_DG4),
+	GPIO_FN(D41_AD9_DG3),
+	GPIO_FN(D40_AD8_DG2),
+	GPIO_FN(D39_AD7_DG1),
+	GPIO_FN(D38_AD6_DG0),
+	GPIO_FN(D37_AD5_DR5),
+	GPIO_FN(D36_AD4_DR4),
+	GPIO_FN(D35_AD3_DR3),
+	GPIO_FN(D34_AD2_DR2),
+	GPIO_FN(D33_AD1_DR1),
+	GPIO_FN(D32_AD0_DR0),
+	GPIO_FN(REQ1),
+	GPIO_FN(REQ2),
+	GPIO_FN(REQ3),
+	GPIO_FN(GNT1),
+	GPIO_FN(GNT2),
+	GPIO_FN(GNT3),
+	GPIO_FN(MMCCLK),
+	GPIO_FN(D31),
+	GPIO_FN(D30),
+	GPIO_FN(D29),
+	GPIO_FN(D28),
+	GPIO_FN(D27),
+	GPIO_FN(D26),
+	GPIO_FN(D25),
+	GPIO_FN(D24),
+	GPIO_FN(D23),
+	GPIO_FN(D22),
+	GPIO_FN(D21),
+	GPIO_FN(D20),
+	GPIO_FN(D19),
+	GPIO_FN(D18),
+	GPIO_FN(D17),
+	GPIO_FN(D16),
+	GPIO_FN(SCIF1_SCK),
+	GPIO_FN(SCIF1_RXD),
+	GPIO_FN(SCIF1_TXD),
+	GPIO_FN(SCIF0_CTS),
+	GPIO_FN(INTD),
+	GPIO_FN(FCE),
+	GPIO_FN(SCIF0_RTS),
+	GPIO_FN(HSPI_CS),
+	GPIO_FN(FSE),
+	GPIO_FN(SCIF0_SCK),
+	GPIO_FN(HSPI_CLK),
+	GPIO_FN(FRE),
+	GPIO_FN(SCIF0_RXD),
+	GPIO_FN(HSPI_RX),
+	GPIO_FN(FRB),
+	GPIO_FN(SCIF0_TXD),
+	GPIO_FN(HSPI_TX),
+	GPIO_FN(FWE),
+	GPIO_FN(SCIF5_TXD),
+	GPIO_FN(HAC1_SYNC),
+	GPIO_FN(SSI1_WS),
+	GPIO_FN(SIOF_TXD_PJ),
+	GPIO_FN(HAC0_SDOUT),
+	GPIO_FN(SSI0_SDATA),
+	GPIO_FN(SIOF_RXD_PJ),
+	GPIO_FN(HAC0_SDIN),
+	GPIO_FN(SSI0_SCK),
+	GPIO_FN(SIOF_SYNC_PJ),
+	GPIO_FN(HAC0_SYNC),
+	GPIO_FN(SSI0_WS),
+	GPIO_FN(SIOF_MCLK_PJ),
+	GPIO_FN(HAC_RES),
+	GPIO_FN(SIOF_SCK_PJ),
+	GPIO_FN(HAC0_BITCLK),
+	GPIO_FN(SSI0_CLK),
+	GPIO_FN(HAC1_BITCLK),
+	GPIO_FN(SSI1_CLK),
+	GPIO_FN(TCLK),
+	GPIO_FN(IOIS16),
+	GPIO_FN(STATUS0),
+	GPIO_FN(DRAK0_PK3),
+	GPIO_FN(STATUS1),
+	GPIO_FN(DRAK1_PK2),
+	GPIO_FN(DACK2),
+	GPIO_FN(SCIF2_TXD),
+	GPIO_FN(MMCCMD),
+	GPIO_FN(SIOF_TXD_PK),
+	GPIO_FN(DACK3),
+	GPIO_FN(SCIF2_SCK),
+	GPIO_FN(MMCDAT),
+	GPIO_FN(SIOF_SCK_PK),
+	GPIO_FN(DREQ0),
+	GPIO_FN(DREQ1),
+	GPIO_FN(DRAK0_PK1),
+	GPIO_FN(DRAK1_PK0),
+	GPIO_FN(DREQ2),
+	GPIO_FN(INTB),
+	GPIO_FN(DREQ3),
+	GPIO_FN(INTC),
+	GPIO_FN(DRAK2),
+	GPIO_FN(CE2A),
+	GPIO_FN(IRL4),
+	GPIO_FN(FD4),
+	GPIO_FN(IRL5),
+	GPIO_FN(FD5),
+	GPIO_FN(IRL6),
+	GPIO_FN(FD6),
+	GPIO_FN(IRL7),
+	GPIO_FN(FD7),
+	GPIO_FN(DRAK3),
+	GPIO_FN(CE2B),
+	GPIO_FN(BREQ_BSACK),
+	GPIO_FN(BACK_BSREQ),
+	GPIO_FN(SCIF5_RXD),
+	GPIO_FN(HAC1_SDIN),
+	GPIO_FN(SSI1_SCK),
+	GPIO_FN(SCIF5_SCK),
+	GPIO_FN(HAC1_SDOUT),
+	GPIO_FN(SSI1_SDATA),
+	GPIO_FN(SCIF3_TXD),
+	GPIO_FN(FCLE),
+	GPIO_FN(SCIF3_RXD),
+	GPIO_FN(FALE),
+	GPIO_FN(SCIF3_SCK),
+	GPIO_FN(FD0),
+	GPIO_FN(SCIF4_TXD),
+	GPIO_FN(FD1),
+	GPIO_FN(SCIF4_RXD),
+	GPIO_FN(FD2),
+	GPIO_FN(SCIF4_SCK),
+	GPIO_FN(FD3),
+	GPIO_FN(DEVSEL_DCLKOUT),
+	GPIO_FN(STOP_CDE),
+	GPIO_FN(LOCK_ODDF),
+	GPIO_FN(TRDY_DISPL),
+	GPIO_FN(IRDY_HSYNC),
+	GPIO_FN(PCIFRAME_VSYNC),
+	GPIO_FN(INTA),
+	GPIO_FN(GNT0_GNTIN),
+	GPIO_FN(REQ0_REQOUT),
+	GPIO_FN(PERR),
+	GPIO_FN(SERR),
+	GPIO_FN(WE7_CBE3),
+	GPIO_FN(WE6_CBE2),
+	GPIO_FN(WE5_CBE1),
+	GPIO_FN(WE4_CBE0),
+	GPIO_FN(SCIF2_RXD),
+	GPIO_FN(SIOF_RXD),
+	GPIO_FN(MRESETOUT),
+	GPIO_FN(IRQOUT),
 };
 
-static struct pinmux_cfg_reg pinmux_config_regs[] = {
+static const struct pinmux_cfg_reg pinmux_config_regs[] = {
 	{ PINMUX_CFG_REG("PACR", 0xffe70000, 16, 2) {
 		PA7_FN, PA7_OUT, PA7_IN, PA7_IN_PU,
 		PA6_FN, PA6_OUT, PA6_IN, PA6_IN_PU,
@@ -1214,7 +1218,7 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = {
 	{}
 };
 
-static struct pinmux_data_reg pinmux_data_regs[] = {
+static const struct pinmux_data_reg pinmux_data_regs[] = {
 	{ PINMUX_DATA_REG("PADR", 0xffe70020, 8) {
 		PA7_DATA, PA6_DATA, PA5_DATA, PA4_DATA,
 		PA3_DATA, PA2_DATA, PA1_DATA, PA0_DATA }
@@ -1282,20 +1286,18 @@ static struct pinmux_data_reg pinmux_data_regs[] = {
 	{ },
 };
 
-struct sh_pfc_soc_info sh7785_pinmux_info = {
+const struct sh_pfc_soc_info sh7785_pinmux_info = {
 	.name = "sh7785_pfc",
-	.reserved_id = PINMUX_RESERVED,
-	.data = { PINMUX_DATA_BEGIN, PINMUX_DATA_END },
 	.input = { PINMUX_INPUT_BEGIN, PINMUX_INPUT_END },
 	.input_pu = { PINMUX_INPUT_PULLUP_BEGIN, PINMUX_INPUT_PULLUP_END },
 	.output = { PINMUX_OUTPUT_BEGIN, PINMUX_OUTPUT_END },
-	.mark = { PINMUX_MARK_BEGIN, PINMUX_MARK_END },
 	.function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END },
 
-	.first_gpio = GPIO_PA7,
-	.last_gpio = GPIO_FN_IRQOUT,
+	.pins = pinmux_pins,
+	.nr_pins = ARRAY_SIZE(pinmux_pins),
+	.func_gpios = pinmux_func_gpios,
+	.nr_func_gpios = ARRAY_SIZE(pinmux_func_gpios),
 
-	.gpios = pinmux_gpios,
 	.cfg_regs = pinmux_config_regs,
 	.data_regs = pinmux_data_regs,
 
diff --git a/drivers/pinctrl/sh-pfc/pfc-sh7786.c b/drivers/pinctrl/sh-pfc/pfc-sh7786.c
index 1e18b58..8ae0e32 100644
--- a/drivers/pinctrl/sh-pfc/pfc-sh7786.c
+++ b/drivers/pinctrl/sh-pfc/pfc-sh7786.c
@@ -191,7 +191,7 @@ enum {
 	PINMUX_MARK_END,
 };
 
-static pinmux_enum_t pinmux_data[] = {
+static const pinmux_enum_t pinmux_data[] = {
 
 	/* PA GPIO */
 	PINMUX_DATA(PA7_DATA, PA7_IN, PA7_OUT, PA7_IN_PU),
@@ -427,7 +427,7 @@ static pinmux_enum_t pinmux_data[] = {
 	PINMUX_DATA(SSI3_SCK_MARK,	P2MSEL6_1, P2MSEL5_1, PJ1_FN),
 };
 
-static struct pinmux_gpio pinmux_gpios[] = {
+static struct sh_pfc_pin pinmux_pins[] = {
 	/* PA */
 	PINMUX_GPIO(GPIO_PA7, PA7_DATA),
 	PINMUX_GPIO(GPIO_PA6, PA6_DATA),
@@ -505,147 +505,151 @@ static struct pinmux_gpio pinmux_gpios[] = {
 	PINMUX_GPIO(GPIO_PJ3, PJ3_DATA),
 	PINMUX_GPIO(GPIO_PJ2, PJ2_DATA),
 	PINMUX_GPIO(GPIO_PJ1, PJ1_DATA),
+};
+
+#define PINMUX_FN_BASE	ARRAY_SIZE(pinmux_pins)
 
+static const struct pinmux_func pinmux_func_gpios[] = {
 	/* FN */
-	PINMUX_GPIO(GPIO_FN_CDE,		CDE_MARK),
-	PINMUX_GPIO(GPIO_FN_ETH_MAGIC,		ETH_MAGIC_MARK),
-	PINMUX_GPIO(GPIO_FN_DISP,		DISP_MARK),
-	PINMUX_GPIO(GPIO_FN_ETH_LINK,		ETH_LINK_MARK),
-	PINMUX_GPIO(GPIO_FN_DR5,		DR5_MARK),
-	PINMUX_GPIO(GPIO_FN_ETH_TX_ER,		ETH_TX_ER_MARK),
-	PINMUX_GPIO(GPIO_FN_DR4,		DR4_MARK),
-	PINMUX_GPIO(GPIO_FN_ETH_TX_EN,		ETH_TX_EN_MARK),
-	PINMUX_GPIO(GPIO_FN_DR3,		DR3_MARK),
-	PINMUX_GPIO(GPIO_FN_ETH_TXD3,		ETH_TXD3_MARK),
-	PINMUX_GPIO(GPIO_FN_DR2,		DR2_MARK),
-	PINMUX_GPIO(GPIO_FN_ETH_TXD2,		ETH_TXD2_MARK),
-	PINMUX_GPIO(GPIO_FN_DR1,		DR1_MARK),
-	PINMUX_GPIO(GPIO_FN_ETH_TXD1,		ETH_TXD1_MARK),
-	PINMUX_GPIO(GPIO_FN_DR0,		DR0_MARK),
-	PINMUX_GPIO(GPIO_FN_ETH_TXD0,		ETH_TXD0_MARK),
-	PINMUX_GPIO(GPIO_FN_VSYNC,		VSYNC_MARK),
-	PINMUX_GPIO(GPIO_FN_HSPI_CLK,		HSPI_CLK_MARK),
-	PINMUX_GPIO(GPIO_FN_ODDF,		ODDF_MARK),
-	PINMUX_GPIO(GPIO_FN_HSPI_CS,		HSPI_CS_MARK),
-	PINMUX_GPIO(GPIO_FN_DG5,		DG5_MARK),
-	PINMUX_GPIO(GPIO_FN_ETH_MDIO,		ETH_MDIO_MARK),
-	PINMUX_GPIO(GPIO_FN_DG4,		DG4_MARK),
-	PINMUX_GPIO(GPIO_FN_ETH_RX_CLK,		ETH_RX_CLK_MARK),
-	PINMUX_GPIO(GPIO_FN_DG3,		DG3_MARK),
-	PINMUX_GPIO(GPIO_FN_ETH_MDC,		ETH_MDC_MARK),
-	PINMUX_GPIO(GPIO_FN_DG2,		DG2_MARK),
-	PINMUX_GPIO(GPIO_FN_ETH_COL,		ETH_COL_MARK),
-	PINMUX_GPIO(GPIO_FN_DG1,		DG1_MARK),
-	PINMUX_GPIO(GPIO_FN_ETH_TX_CLK,		ETH_TX_CLK_MARK),
-	PINMUX_GPIO(GPIO_FN_DG0,		DG0_MARK),
-	PINMUX_GPIO(GPIO_FN_ETH_CRS,		ETH_CRS_MARK),
-	PINMUX_GPIO(GPIO_FN_DCLKIN,		DCLKIN_MARK),
-	PINMUX_GPIO(GPIO_FN_HSPI_RX,		HSPI_RX_MARK),
-	PINMUX_GPIO(GPIO_FN_HSYNC,		HSYNC_MARK),
-	PINMUX_GPIO(GPIO_FN_HSPI_TX,		HSPI_TX_MARK),
-	PINMUX_GPIO(GPIO_FN_DB5,		DB5_MARK),
-	PINMUX_GPIO(GPIO_FN_ETH_RXD3,		ETH_RXD3_MARK),
-	PINMUX_GPIO(GPIO_FN_DB4,		DB4_MARK),
-	PINMUX_GPIO(GPIO_FN_ETH_RXD2,		ETH_RXD2_MARK),
-	PINMUX_GPIO(GPIO_FN_DB3,		DB3_MARK),
-	PINMUX_GPIO(GPIO_FN_ETH_RXD1,		ETH_RXD1_MARK),
-	PINMUX_GPIO(GPIO_FN_DB2,		DB2_MARK),
-	PINMUX_GPIO(GPIO_FN_ETH_RXD0,		ETH_RXD0_MARK),
-	PINMUX_GPIO(GPIO_FN_DB1,		DB1_MARK),
-	PINMUX_GPIO(GPIO_FN_ETH_RX_DV,		ETH_RX_DV_MARK),
-	PINMUX_GPIO(GPIO_FN_DB0,		DB0_MARK),
-	PINMUX_GPIO(GPIO_FN_ETH_RX_ER,		ETH_RX_ER_MARK),
-	PINMUX_GPIO(GPIO_FN_DCLKOUT,		DCLKOUT_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF1_SCK,		SCIF1_SCK_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF1_RXD,		SCIF1_RXD_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF1_TXD,		SCIF1_TXD_MARK),
-	PINMUX_GPIO(GPIO_FN_DACK1,		DACK1_MARK),
-	PINMUX_GPIO(GPIO_FN_BACK,		BACK_MARK),
-	PINMUX_GPIO(GPIO_FN_FALE,		FALE_MARK),
-	PINMUX_GPIO(GPIO_FN_DACK0,		DACK0_MARK),
-	PINMUX_GPIO(GPIO_FN_FCLE,		FCLE_MARK),
-	PINMUX_GPIO(GPIO_FN_DREQ1,		DREQ1_MARK),
-	PINMUX_GPIO(GPIO_FN_BREQ,		BREQ_MARK),
-	PINMUX_GPIO(GPIO_FN_USB_OVC1,		USB_OVC1_MARK),
-	PINMUX_GPIO(GPIO_FN_DREQ0,		DREQ0_MARK),
-	PINMUX_GPIO(GPIO_FN_USB_OVC0,		USB_OVC0_MARK),
-	PINMUX_GPIO(GPIO_FN_USB_PENC1,		USB_PENC1_MARK),
-	PINMUX_GPIO(GPIO_FN_USB_PENC0,		USB_PENC0_MARK),
-	PINMUX_GPIO(GPIO_FN_HAC1_SDOUT,		HAC1_SDOUT_MARK),
-	PINMUX_GPIO(GPIO_FN_SSI1_SDATA,		SSI1_SDATA_MARK),
-	PINMUX_GPIO(GPIO_FN_SDIF1CMD,		SDIF1CMD_MARK),
-	PINMUX_GPIO(GPIO_FN_HAC1_SDIN,		HAC1_SDIN_MARK),
-	PINMUX_GPIO(GPIO_FN_SSI1_SCK,		SSI1_SCK_MARK),
-	PINMUX_GPIO(GPIO_FN_SDIF1CD,		SDIF1CD_MARK),
-	PINMUX_GPIO(GPIO_FN_HAC1_SYNC,		HAC1_SYNC_MARK),
-	PINMUX_GPIO(GPIO_FN_SSI1_WS,		SSI1_WS_MARK),
-	PINMUX_GPIO(GPIO_FN_SDIF1WP,		SDIF1WP_MARK),
-	PINMUX_GPIO(GPIO_FN_HAC1_BITCLK,	HAC1_BITCLK_MARK),
-	PINMUX_GPIO(GPIO_FN_SSI1_CLK,		SSI1_CLK_MARK),
-	PINMUX_GPIO(GPIO_FN_SDIF1CLK,		SDIF1CLK_MARK),
-	PINMUX_GPIO(GPIO_FN_HAC0_SDOUT,		HAC0_SDOUT_MARK),
-	PINMUX_GPIO(GPIO_FN_SSI0_SDATA,		SSI0_SDATA_MARK),
-	PINMUX_GPIO(GPIO_FN_SDIF1D3,		SDIF1D3_MARK),
-	PINMUX_GPIO(GPIO_FN_HAC0_SDIN,		HAC0_SDIN_MARK),
-	PINMUX_GPIO(GPIO_FN_SSI0_SCK,		SSI0_SCK_MARK),
-	PINMUX_GPIO(GPIO_FN_SDIF1D2,		SDIF1D2_MARK),
-	PINMUX_GPIO(GPIO_FN_HAC0_SYNC,		HAC0_SYNC_MARK),
-	PINMUX_GPIO(GPIO_FN_SSI0_WS,		SSI0_WS_MARK),
-	PINMUX_GPIO(GPIO_FN_SDIF1D1,		SDIF1D1_MARK),
-	PINMUX_GPIO(GPIO_FN_HAC0_BITCLK,	HAC0_BITCLK_MARK),
-	PINMUX_GPIO(GPIO_FN_SSI0_CLK,		SSI0_CLK_MARK),
-	PINMUX_GPIO(GPIO_FN_SDIF1D0,		SDIF1D0_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF3_SCK,		SCIF3_SCK_MARK),
-	PINMUX_GPIO(GPIO_FN_SSI2_SDATA,		SSI2_SDATA_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF3_RXD,		SCIF3_RXD_MARK),
-	PINMUX_GPIO(GPIO_FN_TCLK,		TCLK_MARK),
-	PINMUX_GPIO(GPIO_FN_SSI2_SCK,		SSI2_SCK_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF3_TXD,		SCIF3_TXD_MARK),
-	PINMUX_GPIO(GPIO_FN_HAC_RES,		HAC_RES_MARK),
-	PINMUX_GPIO(GPIO_FN_SSI2_WS,		SSI2_WS_MARK),
-	PINMUX_GPIO(GPIO_FN_DACK3,		DACK3_MARK),
-	PINMUX_GPIO(GPIO_FN_SDIF0CMD,		SDIF0CMD_MARK),
-	PINMUX_GPIO(GPIO_FN_DACK2,		DACK2_MARK),
-	PINMUX_GPIO(GPIO_FN_SDIF0CD,		SDIF0CD_MARK),
-	PINMUX_GPIO(GPIO_FN_DREQ3,		DREQ3_MARK),
-	PINMUX_GPIO(GPIO_FN_SDIF0WP,		SDIF0WP_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF0_CTS,		SCIF0_CTS_MARK),
-	PINMUX_GPIO(GPIO_FN_DREQ2,		DREQ2_MARK),
-	PINMUX_GPIO(GPIO_FN_SDIF0CLK,		SDIF0CLK_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF0_RTS,		SCIF0_RTS_MARK),
-	PINMUX_GPIO(GPIO_FN_IRL7,		IRL7_MARK),
-	PINMUX_GPIO(GPIO_FN_SDIF0D3,		SDIF0D3_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF0_SCK,		SCIF0_SCK_MARK),
-	PINMUX_GPIO(GPIO_FN_IRL6,		IRL6_MARK),
-	PINMUX_GPIO(GPIO_FN_SDIF0D2,		SDIF0D2_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF0_RXD,		SCIF0_RXD_MARK),
-	PINMUX_GPIO(GPIO_FN_IRL5,		IRL5_MARK),
-	PINMUX_GPIO(GPIO_FN_SDIF0D1,		SDIF0D1_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF0_TXD,		SCIF0_TXD_MARK),
-	PINMUX_GPIO(GPIO_FN_IRL4,		IRL4_MARK),
-	PINMUX_GPIO(GPIO_FN_SDIF0D0,		SDIF0D0_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF5_SCK,		SCIF5_SCK_MARK),
-	PINMUX_GPIO(GPIO_FN_FRB,		FRB_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF5_RXD,		SCIF5_RXD_MARK),
-	PINMUX_GPIO(GPIO_FN_IOIS16,		IOIS16_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF5_TXD,		SCIF5_TXD_MARK),
-	PINMUX_GPIO(GPIO_FN_CE2B,		CE2B_MARK),
-	PINMUX_GPIO(GPIO_FN_DRAK3,		DRAK3_MARK),
-	PINMUX_GPIO(GPIO_FN_CE2A,		CE2A_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF4_SCK,		SCIF4_SCK_MARK),
-	PINMUX_GPIO(GPIO_FN_DRAK2,		DRAK2_MARK),
-	PINMUX_GPIO(GPIO_FN_SSI3_WS,		SSI3_WS_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF4_RXD,		SCIF4_RXD_MARK),
-	PINMUX_GPIO(GPIO_FN_DRAK1,		DRAK1_MARK),
-	PINMUX_GPIO(GPIO_FN_SSI3_SDATA,		SSI3_SDATA_MARK),
-	PINMUX_GPIO(GPIO_FN_FSTATUS,		FSTATUS_MARK),
-	PINMUX_GPIO(GPIO_FN_SCIF4_TXD,		SCIF4_TXD_MARK),
-	PINMUX_GPIO(GPIO_FN_DRAK0,		DRAK0_MARK),
-	PINMUX_GPIO(GPIO_FN_SSI3_SCK,		SSI3_SCK_MARK),
-	PINMUX_GPIO(GPIO_FN_FSE,		FSE_MARK),
+	GPIO_FN(CDE),
+	GPIO_FN(ETH_MAGIC),
+	GPIO_FN(DISP),
+	GPIO_FN(ETH_LINK),
+	GPIO_FN(DR5),
+	GPIO_FN(ETH_TX_ER),
+	GPIO_FN(DR4),
+	GPIO_FN(ETH_TX_EN),
+	GPIO_FN(DR3),
+	GPIO_FN(ETH_TXD3),
+	GPIO_FN(DR2),
+	GPIO_FN(ETH_TXD2),
+	GPIO_FN(DR1),
+	GPIO_FN(ETH_TXD1),
+	GPIO_FN(DR0),
+	GPIO_FN(ETH_TXD0),
+	GPIO_FN(VSYNC),
+	GPIO_FN(HSPI_CLK),
+	GPIO_FN(ODDF),
+	GPIO_FN(HSPI_CS),
+	GPIO_FN(DG5),
+	GPIO_FN(ETH_MDIO),
+	GPIO_FN(DG4),
+	GPIO_FN(ETH_RX_CLK),
+	GPIO_FN(DG3),
+	GPIO_FN(ETH_MDC),
+	GPIO_FN(DG2),
+	GPIO_FN(ETH_COL),
+	GPIO_FN(DG1),
+	GPIO_FN(ETH_TX_CLK),
+	GPIO_FN(DG0),
+	GPIO_FN(ETH_CRS),
+	GPIO_FN(DCLKIN),
+	GPIO_FN(HSPI_RX),
+	GPIO_FN(HSYNC),
+	GPIO_FN(HSPI_TX),
+	GPIO_FN(DB5),
+	GPIO_FN(ETH_RXD3),
+	GPIO_FN(DB4),
+	GPIO_FN(ETH_RXD2),
+	GPIO_FN(DB3),
+	GPIO_FN(ETH_RXD1),
+	GPIO_FN(DB2),
+	GPIO_FN(ETH_RXD0),
+	GPIO_FN(DB1),
+	GPIO_FN(ETH_RX_DV),
+	GPIO_FN(DB0),
+	GPIO_FN(ETH_RX_ER),
+	GPIO_FN(DCLKOUT),
+	GPIO_FN(SCIF1_SCK),
+	GPIO_FN(SCIF1_RXD),
+	GPIO_FN(SCIF1_TXD),
+	GPIO_FN(DACK1),
+	GPIO_FN(BACK),
+	GPIO_FN(FALE),
+	GPIO_FN(DACK0),
+	GPIO_FN(FCLE),
+	GPIO_FN(DREQ1),
+	GPIO_FN(BREQ),
+	GPIO_FN(USB_OVC1),
+	GPIO_FN(DREQ0),
+	GPIO_FN(USB_OVC0),
+	GPIO_FN(USB_PENC1),
+	GPIO_FN(USB_PENC0),
+	GPIO_FN(HAC1_SDOUT),
+	GPIO_FN(SSI1_SDATA),
+	GPIO_FN(SDIF1CMD),
+	GPIO_FN(HAC1_SDIN),
+	GPIO_FN(SSI1_SCK),
+	GPIO_FN(SDIF1CD),
+	GPIO_FN(HAC1_SYNC),
+	GPIO_FN(SSI1_WS),
+	GPIO_FN(SDIF1WP),
+	GPIO_FN(HAC1_BITCLK),
+	GPIO_FN(SSI1_CLK),
+	GPIO_FN(SDIF1CLK),
+	GPIO_FN(HAC0_SDOUT),
+	GPIO_FN(SSI0_SDATA),
+	GPIO_FN(SDIF1D3),
+	GPIO_FN(HAC0_SDIN),
+	GPIO_FN(SSI0_SCK),
+	GPIO_FN(SDIF1D2),
+	GPIO_FN(HAC0_SYNC),
+	GPIO_FN(SSI0_WS),
+	GPIO_FN(SDIF1D1),
+	GPIO_FN(HAC0_BITCLK),
+	GPIO_FN(SSI0_CLK),
+	GPIO_FN(SDIF1D0),
+	GPIO_FN(SCIF3_SCK),
+	GPIO_FN(SSI2_SDATA),
+	GPIO_FN(SCIF3_RXD),
+	GPIO_FN(TCLK),
+	GPIO_FN(SSI2_SCK),
+	GPIO_FN(SCIF3_TXD),
+	GPIO_FN(HAC_RES),
+	GPIO_FN(SSI2_WS),
+	GPIO_FN(DACK3),
+	GPIO_FN(SDIF0CMD),
+	GPIO_FN(DACK2),
+	GPIO_FN(SDIF0CD),
+	GPIO_FN(DREQ3),
+	GPIO_FN(SDIF0WP),
+	GPIO_FN(SCIF0_CTS),
+	GPIO_FN(DREQ2),
+	GPIO_FN(SDIF0CLK),
+	GPIO_FN(SCIF0_RTS),
+	GPIO_FN(IRL7),
+	GPIO_FN(SDIF0D3),
+	GPIO_FN(SCIF0_SCK),
+	GPIO_FN(IRL6),
+	GPIO_FN(SDIF0D2),
+	GPIO_FN(SCIF0_RXD),
+	GPIO_FN(IRL5),
+	GPIO_FN(SDIF0D1),
+	GPIO_FN(SCIF0_TXD),
+	GPIO_FN(IRL4),
+	GPIO_FN(SDIF0D0),
+	GPIO_FN(SCIF5_SCK),
+	GPIO_FN(FRB),
+	GPIO_FN(SCIF5_RXD),
+	GPIO_FN(IOIS16),
+	GPIO_FN(SCIF5_TXD),
+	GPIO_FN(CE2B),
+	GPIO_FN(DRAK3),
+	GPIO_FN(CE2A),
+	GPIO_FN(SCIF4_SCK),
+	GPIO_FN(DRAK2),
+	GPIO_FN(SSI3_WS),
+	GPIO_FN(SCIF4_RXD),
+	GPIO_FN(DRAK1),
+	GPIO_FN(SSI3_SDATA),
+	GPIO_FN(FSTATUS),
+	GPIO_FN(SCIF4_TXD),
+	GPIO_FN(DRAK0),
+	GPIO_FN(SSI3_SCK),
+	GPIO_FN(FSE),
 };
 
-static struct pinmux_cfg_reg pinmux_config_regs[] = {
+static const struct pinmux_cfg_reg pinmux_config_regs[] = {
 	{ PINMUX_CFG_REG("PACR", 0xffcc0000, 16, 2) {
 		PA7_FN, PA7_OUT, PA7_IN, PA7_IN_PU,
 		PA6_FN, PA6_OUT, PA6_IN, PA6_IN_PU,
@@ -775,7 +779,7 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = {
 	{}
 };
 
-static struct pinmux_data_reg pinmux_data_regs[] = {
+static const struct pinmux_data_reg pinmux_data_regs[] = {
 	{ PINMUX_DATA_REG("PADR", 0xffcc0020, 8) {
 		PA7_DATA, PA6_DATA, PA5_DATA, PA4_DATA,
 		PA3_DATA, PA2_DATA, PA1_DATA, PA0_DATA }
@@ -815,20 +819,18 @@ static struct pinmux_data_reg pinmux_data_regs[] = {
 	{ },
 };
 
-struct sh_pfc_soc_info sh7786_pinmux_info = {
+const struct sh_pfc_soc_info sh7786_pinmux_info = {
 	.name = "sh7786_pfc",
-	.reserved_id = PINMUX_RESERVED,
-	.data = { PINMUX_DATA_BEGIN, PINMUX_DATA_END },
 	.input = { PINMUX_INPUT_BEGIN, PINMUX_INPUT_END },
 	.input_pu = { PINMUX_INPUT_PULLUP_BEGIN, PINMUX_INPUT_PULLUP_END },
 	.output = { PINMUX_OUTPUT_BEGIN, PINMUX_OUTPUT_END },
-	.mark = { PINMUX_MARK_BEGIN, PINMUX_MARK_END },
 	.function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END },
 
-	.first_gpio = GPIO_PA7,
-	.last_gpio = GPIO_FN_IRL4,
+	.pins = pinmux_pins,
+	.nr_pins = ARRAY_SIZE(pinmux_pins),
+	.func_gpios = pinmux_func_gpios,
+	.nr_func_gpios = ARRAY_SIZE(pinmux_func_gpios),
 
-	.gpios = pinmux_gpios,
 	.cfg_regs = pinmux_config_regs,
 	.data_regs = pinmux_data_regs,
 
diff --git a/drivers/pinctrl/sh-pfc/pfc-shx3.c b/drivers/pinctrl/sh-pfc/pfc-shx3.c
index ccf6918..6594c8c 100644
--- a/drivers/pinctrl/sh-pfc/pfc-shx3.c
+++ b/drivers/pinctrl/sh-pfc/pfc-shx3.c
@@ -147,7 +147,7 @@ enum {
 	PINMUX_MARK_END,
 };
 
-static pinmux_enum_t shx3_pinmux_data[] = {
+static const pinmux_enum_t shx3_pinmux_data[] = {
 
 	/* PA GPIO */
 	PINMUX_DATA(PA7_DATA, PA7_IN, PA7_OUT, PA7_IN_PU),
@@ -306,7 +306,7 @@ static pinmux_enum_t shx3_pinmux_data[] = {
 	PINMUX_DATA(IRQOUT_MARK,	PH0_FN),
 };
 
-static struct pinmux_gpio shx3_pinmux_gpios[] = {
+static struct sh_pfc_pin shx3_pinmux_pins[] = {
 	/* PA */
 	PINMUX_GPIO(GPIO_PA7, PA7_DATA),
 	PINMUX_GPIO(GPIO_PA6, PA6_DATA),
@@ -384,73 +384,77 @@ static struct pinmux_gpio shx3_pinmux_gpios[] = {
 	PINMUX_GPIO(GPIO_PH2, PH2_DATA),
 	PINMUX_GPIO(GPIO_PH1, PH1_DATA),
 	PINMUX_GPIO(GPIO_PH0, PH0_DATA),
+};
+
+#define PINMUX_FN_BASE	ARRAY_SIZE(shx3_pinmux_pins)
 
+static const struct pinmux_func shx3_pinmux_func_gpios[] = {
 	/* FN */
-	PINMUX_GPIO(GPIO_FN_D31,	D31_MARK),
-	PINMUX_GPIO(GPIO_FN_D30,	D30_MARK),
-	PINMUX_GPIO(GPIO_FN_D29,	D29_MARK),
-	PINMUX_GPIO(GPIO_FN_D28,	D28_MARK),
-	PINMUX_GPIO(GPIO_FN_D27,	D27_MARK),
-	PINMUX_GPIO(GPIO_FN_D26,	D26_MARK),
-	PINMUX_GPIO(GPIO_FN_D25,	D25_MARK),
-	PINMUX_GPIO(GPIO_FN_D24,	D24_MARK),
-	PINMUX_GPIO(GPIO_FN_D23,	D23_MARK),
-	PINMUX_GPIO(GPIO_FN_D22,	D22_MARK),
-	PINMUX_GPIO(GPIO_FN_D21,	D21_MARK),
-	PINMUX_GPIO(GPIO_FN_D20,	D20_MARK),
-	PINMUX_GPIO(GPIO_FN_D19,	D19_MARK),
-	PINMUX_GPIO(GPIO_FN_D18,	D18_MARK),
-	PINMUX_GPIO(GPIO_FN_D17,	D17_MARK),
-	PINMUX_GPIO(GPIO_FN_D16,	D16_MARK),
-	PINMUX_GPIO(GPIO_FN_BACK,	BACK_MARK),
-	PINMUX_GPIO(GPIO_FN_BREQ,	BREQ_MARK),
-	PINMUX_GPIO(GPIO_FN_WE3,	WE3_MARK),
-	PINMUX_GPIO(GPIO_FN_WE2,	WE2_MARK),
-	PINMUX_GPIO(GPIO_FN_CS6,	CS6_MARK),
-	PINMUX_GPIO(GPIO_FN_CS5,	CS5_MARK),
-	PINMUX_GPIO(GPIO_FN_CS4,	CS4_MARK),
-	PINMUX_GPIO(GPIO_FN_CLKOUTENB,	CLKOUTENB_MARK),
-	PINMUX_GPIO(GPIO_FN_DACK3,	DACK3_MARK),
-	PINMUX_GPIO(GPIO_FN_DACK2,	DACK2_MARK),
-	PINMUX_GPIO(GPIO_FN_DACK1,	DACK1_MARK),
-	PINMUX_GPIO(GPIO_FN_DACK0,	DACK0_MARK),
-	PINMUX_GPIO(GPIO_FN_DREQ3,	DREQ3_MARK),
-	PINMUX_GPIO(GPIO_FN_DREQ2,	DREQ2_MARK),
-	PINMUX_GPIO(GPIO_FN_DREQ1,	DREQ1_MARK),
-	PINMUX_GPIO(GPIO_FN_DREQ0,	DREQ0_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ3,	IRQ3_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ2,	IRQ2_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ1,	IRQ1_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQ0,	IRQ0_MARK),
-	PINMUX_GPIO(GPIO_FN_DRAK3,	DRAK3_MARK),
-	PINMUX_GPIO(GPIO_FN_DRAK2,	DRAK2_MARK),
-	PINMUX_GPIO(GPIO_FN_DRAK1,	DRAK1_MARK),
-	PINMUX_GPIO(GPIO_FN_DRAK0,	DRAK0_MARK),
-	PINMUX_GPIO(GPIO_FN_SCK3,	SCK3_MARK),
-	PINMUX_GPIO(GPIO_FN_SCK2,	SCK2_MARK),
-	PINMUX_GPIO(GPIO_FN_SCK1,	SCK1_MARK),
-	PINMUX_GPIO(GPIO_FN_SCK0,	SCK0_MARK),
-	PINMUX_GPIO(GPIO_FN_IRL3,	IRL3_MARK),
-	PINMUX_GPIO(GPIO_FN_IRL2,	IRL2_MARK),
-	PINMUX_GPIO(GPIO_FN_IRL1,	IRL1_MARK),
-	PINMUX_GPIO(GPIO_FN_IRL0,	IRL0_MARK),
-	PINMUX_GPIO(GPIO_FN_TXD3,	TXD3_MARK),
-	PINMUX_GPIO(GPIO_FN_TXD2,	TXD2_MARK),
-	PINMUX_GPIO(GPIO_FN_TXD1,	TXD1_MARK),
-	PINMUX_GPIO(GPIO_FN_TXD0,	TXD0_MARK),
-	PINMUX_GPIO(GPIO_FN_RXD3,	RXD3_MARK),
-	PINMUX_GPIO(GPIO_FN_RXD2,	RXD2_MARK),
-	PINMUX_GPIO(GPIO_FN_RXD1,	RXD1_MARK),
-	PINMUX_GPIO(GPIO_FN_RXD0,	RXD0_MARK),
-	PINMUX_GPIO(GPIO_FN_CE2B,	CE2B_MARK),
-	PINMUX_GPIO(GPIO_FN_CE2A,	CE2A_MARK),
-	PINMUX_GPIO(GPIO_FN_IOIS16,	IOIS16_MARK),
-	PINMUX_GPIO(GPIO_FN_STATUS1,	STATUS1_MARK),
-	PINMUX_GPIO(GPIO_FN_STATUS0,	STATUS0_MARK),
-	PINMUX_GPIO(GPIO_FN_IRQOUT,	IRQOUT_MARK),
+	GPIO_FN(D31),
+	GPIO_FN(D30),
+	GPIO_FN(D29),
+	GPIO_FN(D28),
+	GPIO_FN(D27),
+	GPIO_FN(D26),
+	GPIO_FN(D25),
+	GPIO_FN(D24),
+	GPIO_FN(D23),
+	GPIO_FN(D22),
+	GPIO_FN(D21),
+	GPIO_FN(D20),
+	GPIO_FN(D19),
+	GPIO_FN(D18),
+	GPIO_FN(D17),
+	GPIO_FN(D16),
+	GPIO_FN(BACK),
+	GPIO_FN(BREQ),
+	GPIO_FN(WE3),
+	GPIO_FN(WE2),
+	GPIO_FN(CS6),
+	GPIO_FN(CS5),
+	GPIO_FN(CS4),
+	GPIO_FN(CLKOUTENB),
+	GPIO_FN(DACK3),
+	GPIO_FN(DACK2),
+	GPIO_FN(DACK1),
+	GPIO_FN(DACK0),
+	GPIO_FN(DREQ3),
+	GPIO_FN(DREQ2),
+	GPIO_FN(DREQ1),
+	GPIO_FN(DREQ0),
+	GPIO_FN(IRQ3),
+	GPIO_FN(IRQ2),
+	GPIO_FN(IRQ1),
+	GPIO_FN(IRQ0),
+	GPIO_FN(DRAK3),
+	GPIO_FN(DRAK2),
+	GPIO_FN(DRAK1),
+	GPIO_FN(DRAK0),
+	GPIO_FN(SCK3),
+	GPIO_FN(SCK2),
+	GPIO_FN(SCK1),
+	GPIO_FN(SCK0),
+	GPIO_FN(IRL3),
+	GPIO_FN(IRL2),
+	GPIO_FN(IRL1),
+	GPIO_FN(IRL0),
+	GPIO_FN(TXD3),
+	GPIO_FN(TXD2),
+	GPIO_FN(TXD1),
+	GPIO_FN(TXD0),
+	GPIO_FN(RXD3),
+	GPIO_FN(RXD2),
+	GPIO_FN(RXD1),
+	GPIO_FN(RXD0),
+	GPIO_FN(CE2B),
+	GPIO_FN(CE2A),
+	GPIO_FN(IOIS16),
+	GPIO_FN(STATUS1),
+	GPIO_FN(STATUS0),
+	GPIO_FN(IRQOUT),
 };
 
-static struct pinmux_cfg_reg shx3_pinmux_config_regs[] = {
+static const struct pinmux_cfg_reg shx3_pinmux_config_regs[] = {
 	{ PINMUX_CFG_REG("PABCR", 0xffc70000, 32, 2) {
 		PA7_FN, PA7_OUT, PA7_IN, PA7_IN_PU,
 		PA6_FN, PA6_OUT, PA6_IN, PA6_IN_PU,
@@ -526,7 +530,7 @@ static struct pinmux_cfg_reg shx3_pinmux_config_regs[] = {
 	{ },
 };
 
-static struct pinmux_data_reg shx3_pinmux_data_regs[] = {
+static const struct pinmux_data_reg shx3_pinmux_data_regs[] = {
 	{ PINMUX_DATA_REG("PABDR", 0xffc70010, 32) {
 		0, 0, 0, 0, 0, 0, 0, 0,
 		PA7_DATA, PA6_DATA, PA5_DATA, PA4_DATA,
@@ -562,19 +566,17 @@ static struct pinmux_data_reg shx3_pinmux_data_regs[] = {
 	{ },
 };
 
-struct sh_pfc_soc_info shx3_pinmux_info = {
+const struct sh_pfc_soc_info shx3_pinmux_info = {
 	.name		= "shx3_pfc",
-	.reserved_id	= PINMUX_RESERVED,
-	.data		= { PINMUX_DATA_BEGIN,	   PINMUX_DATA_END },
 	.input		= { PINMUX_INPUT_BEGIN,	   PINMUX_INPUT_END },
 	.input_pu	= { PINMUX_INPUT_PULLUP_BEGIN,
 			    PINMUX_INPUT_PULLUP_END },
 	.output		= { PINMUX_OUTPUT_BEGIN,   PINMUX_OUTPUT_END },
-	.mark		= { PINMUX_MARK_BEGIN,     PINMUX_MARK_END },
 	.function	= { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END },
-	.first_gpio	= GPIO_PA7,
-	.last_gpio	= GPIO_FN_STATUS0,
-	.gpios		= shx3_pinmux_gpios,
+	.pins		= shx3_pinmux_pins,
+	.nr_pins	= ARRAY_SIZE(shx3_pinmux_pins),
+	.func_gpios	= shx3_pinmux_func_gpios,
+	.nr_func_gpios	= ARRAY_SIZE(shx3_pinmux_func_gpios),
 	.gpio_data	= shx3_pinmux_data,
 	.gpio_data_size	= ARRAY_SIZE(shx3_pinmux_data),
 	.cfg_regs	= shx3_pinmux_config_regs,
diff --git a/drivers/pinctrl/sh-pfc/pinctrl.c b/drivers/pinctrl/sh-pfc/pinctrl.c
index 11e0e13..3492ec9 100644
--- a/drivers/pinctrl/sh-pfc/pinctrl.c
+++ b/drivers/pinctrl/sh-pfc/pinctrl.c
@@ -9,7 +9,6 @@
  */
 
 #define DRV_NAME "sh-pfc"
-#define pr_fmt(fmt) KBUILD_MODNAME " pinctrl: " fmt
 
 #include <linux/device.h>
 #include <linux/err.h>
@@ -24,25 +23,28 @@
 #include <linux/spinlock.h>
 
 #include "core.h"
+#include "../core.h"
+#include "../pinconf.h"
+
+struct sh_pfc_pin_config {
+	u32 type;
+};
 
 struct sh_pfc_pinctrl {
 	struct pinctrl_dev *pctl;
-	struct sh_pfc *pfc;
-
-	struct pinmux_gpio **functions;
-	unsigned int nr_functions;
+	struct pinctrl_desc pctl_desc;
 
-	struct pinctrl_pin_desc *pads;
-	unsigned int nr_pads;
+	struct sh_pfc *pfc;
 
-	spinlock_t lock;
+	struct pinctrl_pin_desc *pins;
+	struct sh_pfc_pin_config *configs;
 };
 
 static int sh_pfc_get_groups_count(struct pinctrl_dev *pctldev)
 {
 	struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
 
-	return pmx->nr_pads;
+	return pmx->pfc->info->nr_groups;
 }
 
 static const char *sh_pfc_get_group_name(struct pinctrl_dev *pctldev,
@@ -50,16 +52,16 @@ static const char *sh_pfc_get_group_name(struct pinctrl_dev *pctldev,
 {
 	struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
 
-	return pmx->pads[selector].name;
+	return pmx->pfc->info->groups[selector].name;
 }
 
-static int sh_pfc_get_group_pins(struct pinctrl_dev *pctldev, unsigned group,
+static int sh_pfc_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector,
 				 const unsigned **pins, unsigned *num_pins)
 {
 	struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
 
-	*pins = &pmx->pads[group].number;
-	*num_pins = 1;
+	*pins = pmx->pfc->info->groups[selector].pins;
+	*num_pins = pmx->pfc->info->groups[selector].nr_pins;
 
 	return 0;
 }
@@ -70,7 +72,7 @@ static void sh_pfc_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
 	seq_printf(s, "%s", DRV_NAME);
 }
 
-static struct pinctrl_ops sh_pfc_pinctrl_ops = {
+static const struct pinctrl_ops sh_pfc_pinctrl_ops = {
 	.get_groups_count	= sh_pfc_get_groups_count,
 	.get_group_name		= sh_pfc_get_group_name,
 	.get_group_pins		= sh_pfc_get_group_pins,
@@ -81,7 +83,7 @@ static int sh_pfc_get_functions_count(struct pinctrl_dev *pctldev)
 {
 	struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
 
-	return pmx->nr_functions;
+	return pmx->pfc->info->nr_functions;
 }
 
 static const char *sh_pfc_get_function_name(struct pinctrl_dev *pctldev,
@@ -89,136 +91,113 @@ static const char *sh_pfc_get_function_name(struct pinctrl_dev *pctldev,
 {
 	struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
 
-	return pmx->functions[selector]->name;
+	return pmx->pfc->info->functions[selector].name;
 }
 
-static int sh_pfc_get_function_groups(struct pinctrl_dev *pctldev, unsigned func,
+static int sh_pfc_get_function_groups(struct pinctrl_dev *pctldev,
+				      unsigned selector,
 				      const char * const **groups,
 				      unsigned * const num_groups)
 {
 	struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
 
-	*groups = &pmx->functions[func]->name;
-	*num_groups = 1;
+	*groups = pmx->pfc->info->functions[selector].groups;
+	*num_groups = pmx->pfc->info->functions[selector].nr_groups;
 
 	return 0;
 }
 
-static int sh_pfc_noop_enable(struct pinctrl_dev *pctldev, unsigned func,
+static int sh_pfc_func_enable(struct pinctrl_dev *pctldev, unsigned selector,
 			      unsigned group)
 {
-	return 0;
-}
+	struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
+	struct sh_pfc *pfc = pmx->pfc;
+	const struct sh_pfc_pin_group *grp = &pfc->info->groups[group];
+	unsigned long flags;
+	unsigned int i;
+	int ret = 0;
 
-static void sh_pfc_noop_disable(struct pinctrl_dev *pctldev, unsigned func,
-				unsigned group)
-{
-}
+	spin_lock_irqsave(&pfc->lock, flags);
 
-static int sh_pfc_config_function(struct sh_pfc *pfc, unsigned offset)
-{
-	if (sh_pfc_config_gpio(pfc, offset,
-			       PINMUX_TYPE_FUNCTION,
-			       GPIO_CFG_DRYRUN) != 0)
-		return -EINVAL;
+	for (i = 0; i < grp->nr_pins; ++i) {
+		int idx = sh_pfc_get_pin_index(pfc, grp->pins[i]);
+		struct sh_pfc_pin_config *cfg = &pmx->configs[idx];
 
-	if (sh_pfc_config_gpio(pfc, offset,
-			       PINMUX_TYPE_FUNCTION,
-			       GPIO_CFG_REQ) != 0)
-		return -EINVAL;
+		if (cfg->type != PINMUX_TYPE_NONE) {
+			ret = -EBUSY;
+			goto done;
+		}
+	}
 
-	return 0;
+	for (i = 0; i < grp->nr_pins; ++i) {
+		ret = sh_pfc_config_mux(pfc, grp->mux[i], PINMUX_TYPE_FUNCTION);
+		if (ret < 0)
+			break;
+	}
+
+done:
+	spin_unlock_irqrestore(&pfc->lock, flags);
+	return ret;
 }
 
-static int sh_pfc_reconfig_pin(struct sh_pfc *pfc, unsigned offset,
-			       int new_type)
+static void sh_pfc_func_disable(struct pinctrl_dev *pctldev, unsigned selector,
+				unsigned group)
 {
+	struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
+	struct sh_pfc *pfc = pmx->pfc;
+	const struct sh_pfc_pin_group *grp = &pfc->info->groups[group];
 	unsigned long flags;
-	int pinmux_type;
-	int ret = -EINVAL;
+	unsigned int i;
 
 	spin_lock_irqsave(&pfc->lock, flags);
 
-	pinmux_type = pfc->info->gpios[offset].flags & PINMUX_FLAG_TYPE;
+	for (i = 0; i < grp->nr_pins; ++i) {
+		int idx = sh_pfc_get_pin_index(pfc, grp->pins[i]);
+		struct sh_pfc_pin_config *cfg = &pmx->configs[idx];
 
-	/*
-	 * See if the present config needs to first be de-configured.
-	 */
-	switch (pinmux_type) {
-	case PINMUX_TYPE_GPIO:
-		break;
-	case PINMUX_TYPE_OUTPUT:
-	case PINMUX_TYPE_INPUT:
-	case PINMUX_TYPE_INPUT_PULLUP:
-	case PINMUX_TYPE_INPUT_PULLDOWN:
-		sh_pfc_config_gpio(pfc, offset, pinmux_type, GPIO_CFG_FREE);
-		break;
-	default:
-		goto err;
+		cfg->type = PINMUX_TYPE_NONE;
 	}
 
-	/*
-	 * Dry run
-	 */
-	if (sh_pfc_config_gpio(pfc, offset, new_type,
-			       GPIO_CFG_DRYRUN) != 0)
-		goto err;
-
-	/*
-	 * Request
-	 */
-	if (sh_pfc_config_gpio(pfc, offset, new_type,
-			       GPIO_CFG_REQ) != 0)
-		goto err;
-
-	pfc->info->gpios[offset].flags &= ~PINMUX_FLAG_TYPE;
-	pfc->info->gpios[offset].flags |= new_type;
-
-	ret = 0;
-
-err:
 	spin_unlock_irqrestore(&pfc->lock, flags);
-
-	return ret;
 }
 
-
 static int sh_pfc_gpio_request_enable(struct pinctrl_dev *pctldev,
 				      struct pinctrl_gpio_range *range,
 				      unsigned offset)
 {
 	struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
 	struct sh_pfc *pfc = pmx->pfc;
+	int idx = sh_pfc_get_pin_index(pfc, offset);
+	struct sh_pfc_pin_config *cfg = &pmx->configs[idx];
 	unsigned long flags;
-	int ret, pinmux_type;
+	int ret;
 
 	spin_lock_irqsave(&pfc->lock, flags);
 
-	pinmux_type = pfc->info->gpios[offset].flags & PINMUX_FLAG_TYPE;
+	if (cfg->type != PINMUX_TYPE_NONE) {
+		dev_err(pfc->dev,
+			"Pin %u is busy, can't configure it as GPIO.\n",
+			offset);
+		ret = -EBUSY;
+		goto done;
+	}
 
-	switch (pinmux_type) {
-	case PINMUX_TYPE_FUNCTION:
-		pr_notice_once("Use of GPIO API for function requests is "
-			       "deprecated, convert to pinctrl\n");
-		/* handle for now */
-		ret = sh_pfc_config_function(pfc, offset);
-		if (unlikely(ret < 0))
-			goto err;
+	if (!pfc->gpio) {
+		/* If GPIOs are handled externally the pin mux type need to be
+		 * set to GPIO here.
+		 */
+		const struct sh_pfc_pin *pin = &pfc->info->pins[idx];
 
-		break;
-	case PINMUX_TYPE_GPIO:
-	case PINMUX_TYPE_INPUT:
-	case PINMUX_TYPE_OUTPUT:
-		break;
-	default:
-		pr_err("Unsupported mux type (%d), bailing...\n", pinmux_type);
-		ret = -ENOTSUPP;
-		goto err;
+		ret = sh_pfc_config_mux(pfc, pin->enum_id, PINMUX_TYPE_GPIO);
+		if (ret < 0)
+			goto done;
 	}
 
+	cfg->type = PINMUX_TYPE_GPIO;
+
 	ret = 0;
 
-err:
+done:
 	spin_unlock_irqrestore(&pfc->lock, flags);
 
 	return ret;
@@ -230,15 +209,12 @@ static void sh_pfc_gpio_disable_free(struct pinctrl_dev *pctldev,
 {
 	struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
 	struct sh_pfc *pfc = pmx->pfc;
+	int idx = sh_pfc_get_pin_index(pfc, offset);
+	struct sh_pfc_pin_config *cfg = &pmx->configs[idx];
 	unsigned long flags;
-	int pinmux_type;
 
 	spin_lock_irqsave(&pfc->lock, flags);
-
-	pinmux_type = pfc->info->gpios[offset].flags & PINMUX_FLAG_TYPE;
-
-	sh_pfc_config_gpio(pfc, offset, pinmux_type, GPIO_CFG_FREE);
-
+	cfg->type = PINMUX_TYPE_NONE;
 	spin_unlock_irqrestore(&pfc->lock, flags);
 }
 
@@ -247,207 +223,242 @@ static int sh_pfc_gpio_set_direction(struct pinctrl_dev *pctldev,
 				     unsigned offset, bool input)
 {
 	struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
-	int type = input ? PINMUX_TYPE_INPUT : PINMUX_TYPE_OUTPUT;
+	struct sh_pfc *pfc = pmx->pfc;
+	int new_type = input ? PINMUX_TYPE_INPUT : PINMUX_TYPE_OUTPUT;
+	int idx = sh_pfc_get_pin_index(pfc, offset);
+	const struct sh_pfc_pin *pin = &pfc->info->pins[idx];
+	struct sh_pfc_pin_config *cfg = &pmx->configs[idx];
+	unsigned long flags;
+	unsigned int dir;
+	int ret;
+
+	/* Check if the requested direction is supported by the pin. Not all SoC
+	 * provide pin config data, so perform the check conditionally.
+	 */
+	if (pin->configs) {
+		dir = input ? SH_PFC_PIN_CFG_INPUT : SH_PFC_PIN_CFG_OUTPUT;
+		if (!(pin->configs & dir))
+			return -EINVAL;
+	}
+
+	spin_lock_irqsave(&pfc->lock, flags);
+
+	ret = sh_pfc_config_mux(pfc, pin->enum_id, new_type);
+	if (ret < 0)
+		goto done;
+
+	cfg->type = new_type;
 
-	return sh_pfc_reconfig_pin(pmx->pfc, offset, type);
+done:
+	spin_unlock_irqrestore(&pfc->lock, flags);
+	return ret;
 }
 
-static struct pinmux_ops sh_pfc_pinmux_ops = {
+static const struct pinmux_ops sh_pfc_pinmux_ops = {
 	.get_functions_count	= sh_pfc_get_functions_count,
 	.get_function_name	= sh_pfc_get_function_name,
 	.get_function_groups	= sh_pfc_get_function_groups,
-	.enable			= sh_pfc_noop_enable,
-	.disable		= sh_pfc_noop_disable,
+	.enable			= sh_pfc_func_enable,
+	.disable		= sh_pfc_func_disable,
 	.gpio_request_enable	= sh_pfc_gpio_request_enable,
 	.gpio_disable_free	= sh_pfc_gpio_disable_free,
 	.gpio_set_direction	= sh_pfc_gpio_set_direction,
 };
 
-static int sh_pfc_pinconf_get(struct pinctrl_dev *pctldev, unsigned pin,
-			      unsigned long *config)
+/* Check whether the requested parameter is supported for a pin. */
+static bool sh_pfc_pinconf_validate(struct sh_pfc *pfc, unsigned int _pin,
+				    enum pin_config_param param)
 {
-	struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
-	struct sh_pfc *pfc = pmx->pfc;
+	int idx = sh_pfc_get_pin_index(pfc, _pin);
+	const struct sh_pfc_pin *pin = &pfc->info->pins[idx];
 
-	*config = pfc->info->gpios[pin].flags & PINMUX_FLAG_TYPE;
+	switch (param) {
+	case PIN_CONFIG_BIAS_DISABLE:
+		return true;
 
-	return 0;
-}
+	case PIN_CONFIG_BIAS_PULL_UP:
+		return pin->configs & SH_PFC_PIN_CFG_PULL_UP;
 
-static int sh_pfc_pinconf_set(struct pinctrl_dev *pctldev, unsigned pin,
-			      unsigned long config)
-{
-	struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
-
-	/* Validate the new type */
-	if (config >= PINMUX_FLAG_TYPE)
-		return -EINVAL;
+	case PIN_CONFIG_BIAS_PULL_DOWN:
+		return pin->configs & SH_PFC_PIN_CFG_PULL_DOWN;
 
-	return sh_pfc_reconfig_pin(pmx->pfc, pin, config);
+	default:
+		return false;
+	}
 }
 
-static void sh_pfc_pinconf_dbg_show(struct pinctrl_dev *pctldev,
-				    struct seq_file *s, unsigned pin)
+static int sh_pfc_pinconf_get(struct pinctrl_dev *pctldev, unsigned _pin,
+			      unsigned long *config)
 {
-	const char *pinmux_type_str[] = {
-		[PINMUX_TYPE_NONE]		= "none",
-		[PINMUX_TYPE_FUNCTION]		= "function",
-		[PINMUX_TYPE_GPIO]		= "gpio",
-		[PINMUX_TYPE_OUTPUT]		= "output",
-		[PINMUX_TYPE_INPUT]		= "input",
-		[PINMUX_TYPE_INPUT_PULLUP]	= "input bias pull up",
-		[PINMUX_TYPE_INPUT_PULLDOWN]	= "input bias pull down",
-	};
-	unsigned long config;
-	int rc;
-
-	rc = sh_pfc_pinconf_get(pctldev, pin, &config);
-	if (unlikely(rc != 0))
-		return;
-
-	seq_printf(s, " %s", pinmux_type_str[config]);
-}
+	struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
+	struct sh_pfc *pfc = pmx->pfc;
+	enum pin_config_param param = pinconf_to_config_param(*config);
+	unsigned long flags;
+	unsigned int bias;
 
-static struct pinconf_ops sh_pfc_pinconf_ops = {
-	.pin_config_get		= sh_pfc_pinconf_get,
-	.pin_config_set		= sh_pfc_pinconf_set,
-	.pin_config_dbg_show	= sh_pfc_pinconf_dbg_show,
-};
+	if (!sh_pfc_pinconf_validate(pfc, _pin, param))
+		return -ENOTSUPP;
 
-static struct pinctrl_gpio_range sh_pfc_gpio_range = {
-	.name		= DRV_NAME,
-	.id		= 0,
-};
+	switch (param) {
+	case PIN_CONFIG_BIAS_DISABLE:
+	case PIN_CONFIG_BIAS_PULL_UP:
+	case PIN_CONFIG_BIAS_PULL_DOWN:
+		if (!pfc->info->ops || !pfc->info->ops->get_bias)
+			return -ENOTSUPP;
 
-static struct pinctrl_desc sh_pfc_pinctrl_desc = {
-	.name		= DRV_NAME,
-	.owner		= THIS_MODULE,
-	.pctlops	= &sh_pfc_pinctrl_ops,
-	.pmxops		= &sh_pfc_pinmux_ops,
-	.confops	= &sh_pfc_pinconf_ops,
-};
+		spin_lock_irqsave(&pfc->lock, flags);
+		bias = pfc->info->ops->get_bias(pfc, _pin);
+		spin_unlock_irqrestore(&pfc->lock, flags);
 
-static void sh_pfc_map_one_gpio(struct sh_pfc *pfc, struct sh_pfc_pinctrl *pmx,
-				struct pinmux_gpio *gpio, unsigned offset)
-{
-	struct pinmux_data_reg *dummy;
-	unsigned long flags;
-	int bit;
-
-	gpio->flags &= ~PINMUX_FLAG_TYPE;
+		if (bias != param)
+			return -EINVAL;
 
-	if (sh_pfc_get_data_reg(pfc, offset, &dummy, &bit) == 0)
-		gpio->flags |= PINMUX_TYPE_GPIO;
-	else {
-		gpio->flags |= PINMUX_TYPE_FUNCTION;
+		*config = 0;
+		break;
 
-		spin_lock_irqsave(&pmx->lock, flags);
-		pmx->nr_functions++;
-		spin_unlock_irqrestore(&pmx->lock, flags);
+	default:
+		return -ENOTSUPP;
 	}
+
+	return 0;
 }
 
-/* pinmux ranges -> pinctrl pin descs */
-static int sh_pfc_map_gpios(struct sh_pfc *pfc, struct sh_pfc_pinctrl *pmx)
+static int sh_pfc_pinconf_set(struct pinctrl_dev *pctldev, unsigned _pin,
+			      unsigned long config)
 {
+	struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
+	struct sh_pfc *pfc = pmx->pfc;
+	enum pin_config_param param = pinconf_to_config_param(config);
 	unsigned long flags;
-	int i;
 
-	pmx->nr_pads = pfc->info->last_gpio - pfc->info->first_gpio + 1;
+	if (!sh_pfc_pinconf_validate(pfc, _pin, param))
+		return -ENOTSUPP;
 
-	pmx->pads = devm_kzalloc(pfc->dev, sizeof(*pmx->pads) * pmx->nr_pads,
-				 GFP_KERNEL);
-	if (unlikely(!pmx->pads)) {
-		pmx->nr_pads = 0;
-		return -ENOMEM;
-	}
+	switch (param) {
+	case PIN_CONFIG_BIAS_PULL_UP:
+	case PIN_CONFIG_BIAS_PULL_DOWN:
+	case PIN_CONFIG_BIAS_DISABLE:
+		if (!pfc->info->ops || !pfc->info->ops->set_bias)
+			return -ENOTSUPP;
 
-	spin_lock_irqsave(&pfc->lock, flags);
+		spin_lock_irqsave(&pfc->lock, flags);
+		pfc->info->ops->set_bias(pfc, _pin, param);
+		spin_unlock_irqrestore(&pfc->lock, flags);
 
-	/*
-	 * We don't necessarily have a 1:1 mapping between pin and linux
-	 * GPIO number, as the latter maps to the associated enum_id.
-	 * Care needs to be taken to translate back to pin space when
-	 * dealing with any pin configurations.
-	 */
-	for (i = 0; i < pmx->nr_pads; i++) {
-		struct pinctrl_pin_desc *pin = pmx->pads + i;
-		struct pinmux_gpio *gpio = pfc->info->gpios + i;
+		break;
 
-		pin->number = pfc->info->first_gpio + i;
-		pin->name = gpio->name;
+	default:
+		return -ENOTSUPP;
+	}
 
-		/* XXX */
-		if (unlikely(!gpio->enum_id))
-			continue;
+	return 0;
+}
 
-		sh_pfc_map_one_gpio(pfc, pmx, gpio, i);
-	}
+static int sh_pfc_pinconf_group_set(struct pinctrl_dev *pctldev, unsigned group,
+				    unsigned long config)
+{
+	struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
+	const unsigned int *pins;
+	unsigned int num_pins;
+	unsigned int i;
 
-	spin_unlock_irqrestore(&pfc->lock, flags);
+	pins = pmx->pfc->info->groups[group].pins;
+	num_pins = pmx->pfc->info->groups[group].nr_pins;
 
-	sh_pfc_pinctrl_desc.pins = pmx->pads;
-	sh_pfc_pinctrl_desc.npins = pmx->nr_pads;
+	for (i = 0; i < num_pins; ++i)
+		sh_pfc_pinconf_set(pctldev, pins[i], config);
 
 	return 0;
 }
 
-static int sh_pfc_map_functions(struct sh_pfc *pfc, struct sh_pfc_pinctrl *pmx)
+static const struct pinconf_ops sh_pfc_pinconf_ops = {
+	.is_generic			= true,
+	.pin_config_get			= sh_pfc_pinconf_get,
+	.pin_config_set			= sh_pfc_pinconf_set,
+	.pin_config_group_set		= sh_pfc_pinconf_group_set,
+	.pin_config_config_dbg_show	= pinconf_generic_dump_config,
+};
+
+/* PFC ranges -> pinctrl pin descs */
+static int sh_pfc_map_pins(struct sh_pfc *pfc, struct sh_pfc_pinctrl *pmx)
 {
-	unsigned long flags;
-	int i, fn;
+	const struct pinmux_range *ranges;
+	struct pinmux_range def_range;
+	unsigned int nr_ranges;
+	unsigned int nr_pins;
+	unsigned int i;
+
+	if (pfc->info->ranges == NULL) {
+		def_range.begin = 0;
+		def_range.end = pfc->info->nr_pins - 1;
+		ranges = &def_range;
+		nr_ranges = 1;
+	} else {
+		ranges = pfc->info->ranges;
+		nr_ranges = pfc->info->nr_ranges;
+	}
 
-	pmx->functions = devm_kzalloc(pfc->dev, pmx->nr_functions *
-				      sizeof(*pmx->functions), GFP_KERNEL);
-	if (unlikely(!pmx->functions))
+	pmx->pins = devm_kzalloc(pfc->dev,
+				 sizeof(*pmx->pins) * pfc->info->nr_pins,
+				 GFP_KERNEL);
+	if (unlikely(!pmx->pins))
 		return -ENOMEM;
 
-	spin_lock_irqsave(&pmx->lock, flags);
-
-	for (i = fn = 0; i < pmx->nr_pads; i++) {
-		struct pinmux_gpio *gpio = pfc->info->gpios + i;
+	pmx->configs = devm_kzalloc(pfc->dev,
+				    sizeof(*pmx->configs) * pfc->info->nr_pins,
+				    GFP_KERNEL);
+	if (unlikely(!pmx->configs))
+		return -ENOMEM;
 
-		if ((gpio->flags & PINMUX_FLAG_TYPE) == PINMUX_TYPE_FUNCTION)
-			pmx->functions[fn++] = gpio;
+	for (i = 0, nr_pins = 0; i < nr_ranges; ++i) {
+		const struct pinmux_range *range = &ranges[i];
+		unsigned int number;
+
+		for (number = range->begin; number <= range->end;
+		     number++, nr_pins++) {
+			struct sh_pfc_pin_config *cfg = &pmx->configs[nr_pins];
+			struct pinctrl_pin_desc *pin = &pmx->pins[nr_pins];
+			const struct sh_pfc_pin *info =
+				&pfc->info->pins[nr_pins];
+
+			pin->number = number;
+			pin->name = info->name;
+			cfg->type = PINMUX_TYPE_NONE;
+		}
 	}
 
-	spin_unlock_irqrestore(&pmx->lock, flags);
+	pfc->nr_pins = ranges[nr_ranges-1].end + 1;
 
-	return 0;
+	return nr_ranges;
 }
 
 int sh_pfc_register_pinctrl(struct sh_pfc *pfc)
 {
 	struct sh_pfc_pinctrl *pmx;
-	int ret;
+	int nr_ranges;
 
 	pmx = devm_kzalloc(pfc->dev, sizeof(*pmx), GFP_KERNEL);
 	if (unlikely(!pmx))
 		return -ENOMEM;
 
-	spin_lock_init(&pmx->lock);
-
 	pmx->pfc = pfc;
 	pfc->pinctrl = pmx;
 
-	ret = sh_pfc_map_gpios(pfc, pmx);
-	if (unlikely(ret != 0))
-		return ret;
+	nr_ranges = sh_pfc_map_pins(pfc, pmx);
+	if (unlikely(nr_ranges < 0))
+		return nr_ranges;
 
-	ret = sh_pfc_map_functions(pfc, pmx);
-	if (unlikely(ret != 0))
-		return ret;
+	pmx->pctl_desc.name = DRV_NAME;
+	pmx->pctl_desc.owner = THIS_MODULE;
+	pmx->pctl_desc.pctlops = &sh_pfc_pinctrl_ops;
+	pmx->pctl_desc.pmxops = &sh_pfc_pinmux_ops;
+	pmx->pctl_desc.confops = &sh_pfc_pinconf_ops;
+	pmx->pctl_desc.pins = pmx->pins;
+	pmx->pctl_desc.npins = pfc->info->nr_pins;
 
-	pmx->pctl = pinctrl_register(&sh_pfc_pinctrl_desc, pfc->dev, pmx);
-	if (IS_ERR(pmx->pctl))
-		return PTR_ERR(pmx->pctl);
-
-	sh_pfc_gpio_range.npins = pfc->info->last_gpio
-				- pfc->info->first_gpio + 1;
-	sh_pfc_gpio_range.base = pfc->info->first_gpio;
-	sh_pfc_gpio_range.pin_base = pfc->info->first_gpio;
-
-	pinctrl_add_gpio_range(pmx->pctl, &sh_pfc_gpio_range);
+	pmx->pctl = pinctrl_register(&pmx->pctl_desc, pfc->dev, pmx);
+	if (pmx->pctl == NULL)
+		return -EINVAL;
 
 	return 0;
 }
diff --git a/drivers/pinctrl/sh-pfc/sh_pfc.h b/drivers/pinctrl/sh-pfc/sh_pfc.h
index 13049c4..3b785fc 100644
--- a/drivers/pinctrl/sh-pfc/sh_pfc.h
+++ b/drivers/pinctrl/sh-pfc/sh_pfc.h
@@ -15,7 +15,8 @@
 #include <asm-generic/gpio.h>
 
 typedef unsigned short pinmux_enum_t;
-typedef unsigned short pinmux_flag_t;
+
+#define SH_PFC_MARK_INVALID	((pinmux_enum_t)-1)
 
 enum {
 	PINMUX_TYPE_NONE,
@@ -30,44 +31,81 @@ enum {
 	PINMUX_FLAG_TYPE,	/* must be last */
 };
 
-#define PINMUX_FLAG_DBIT_SHIFT      5
-#define PINMUX_FLAG_DBIT            (0x1f << PINMUX_FLAG_DBIT_SHIFT)
-#define PINMUX_FLAG_DREG_SHIFT      10
-#define PINMUX_FLAG_DREG            (0x3f << PINMUX_FLAG_DREG_SHIFT)
+#define SH_PFC_PIN_CFG_INPUT		(1 << 0)
+#define SH_PFC_PIN_CFG_OUTPUT		(1 << 1)
+#define SH_PFC_PIN_CFG_PULL_UP		(1 << 2)
+#define SH_PFC_PIN_CFG_PULL_DOWN	(1 << 3)
 
-struct pinmux_gpio {
-	pinmux_enum_t enum_id;
-	pinmux_flag_t flags;
+struct sh_pfc_pin {
+	const pinmux_enum_t enum_id;
 	const char *name;
+	unsigned int configs;
 };
 
-#define PINMUX_GPIO(gpio, data_or_mark) \
-	[gpio] = { .name = __stringify(gpio), .enum_id = data_or_mark, .flags = PINMUX_TYPE_NONE }
+#define SH_PFC_PIN_GROUP(n)				\
+	{						\
+		.name = #n,				\
+		.pins = n##_pins,			\
+		.mux = n##_mux,				\
+		.nr_pins = ARRAY_SIZE(n##_pins),	\
+	}
+
+struct sh_pfc_pin_group {
+	const char *name;
+	const unsigned int *pins;
+	const unsigned int *mux;
+	unsigned int nr_pins;
+};
+
+#define SH_PFC_FUNCTION(n)				\
+	{						\
+		.name = #n,				\
+		.groups = n##_groups,			\
+		.nr_groups = ARRAY_SIZE(n##_groups),	\
+	}
+
+struct sh_pfc_function {
+	const char *name;
+	const char * const *groups;
+	unsigned int nr_groups;
+};
+
+struct pinmux_func {
+	const pinmux_enum_t enum_id;
+	const char *name;
+};
+
+#define PINMUX_GPIO(gpio, data_or_mark)			\
+	[gpio] = {					\
+		.name = __stringify(gpio),		\
+		.enum_id = data_or_mark,		\
+	}
+#define PINMUX_GPIO_FN(gpio, base, data_or_mark)	\
+	[gpio - (base)] = {				\
+		.name = __stringify(gpio),		\
+		.enum_id = data_or_mark,		\
+	}
 
 #define PINMUX_DATA(data_or_mark, ids...) data_or_mark, ids, 0
 
 struct pinmux_cfg_reg {
 	unsigned long reg, reg_width, field_width;
-	unsigned long *cnt;
-	pinmux_enum_t *enum_ids;
-	unsigned long *var_field_width;
+	const pinmux_enum_t *enum_ids;
+	const unsigned long *var_field_width;
 };
 
 #define PINMUX_CFG_REG(name, r, r_width, f_width) \
 	.reg = r, .reg_width = r_width, .field_width = f_width,		\
-	.cnt = (unsigned long [r_width / f_width]) {}, \
 	.enum_ids = (pinmux_enum_t [(r_width / f_width) * (1 << f_width)])
 
 #define PINMUX_CFG_REG_VAR(name, r, r_width, var_fw0, var_fwn...) \
 	.reg = r, .reg_width = r_width,	\
-	.cnt = (unsigned long [r_width]) {}, \
 	.var_field_width = (unsigned long [r_width]) { var_fw0, var_fwn, 0 }, \
 	.enum_ids = (pinmux_enum_t [])
 
 struct pinmux_data_reg {
-	unsigned long reg, reg_width, reg_shadow;
-	pinmux_enum_t *enum_ids;
-	void __iomem *mapped_reg;
+	unsigned long reg, reg_width;
+	const pinmux_enum_t *enum_ids;
 };
 
 #define PINMUX_DATA_REG(name, r, r_width) \
@@ -76,11 +114,11 @@ struct pinmux_data_reg {
 
 struct pinmux_irq {
 	int irq;
-	pinmux_enum_t *enum_ids;
+	unsigned short *gpios;
 };
 
 #define PINMUX_IRQ(irq_nr, ids...)			   \
-	{ .irq = irq_nr, .enum_ids = (pinmux_enum_t []) { ids, 0 } }	\
+	{ .irq = irq_nr, .gpios = (unsigned short []) { ids, 0 } }	\
 
 struct pinmux_range {
 	pinmux_enum_t begin;
@@ -88,33 +126,49 @@ struct pinmux_range {
 	pinmux_enum_t force;
 };
 
+struct sh_pfc;
+
+struct sh_pfc_soc_operations {
+	unsigned int (*get_bias)(struct sh_pfc *pfc, unsigned int pin);
+	void (*set_bias)(struct sh_pfc *pfc, unsigned int pin,
+			 unsigned int bias);
+};
+
 struct sh_pfc_soc_info {
-	char *name;
-	pinmux_enum_t reserved_id;
-	struct pinmux_range data;
+	const char *name;
+	const struct sh_pfc_soc_operations *ops;
+
 	struct pinmux_range input;
 	struct pinmux_range input_pd;
 	struct pinmux_range input_pu;
 	struct pinmux_range output;
-	struct pinmux_range mark;
 	struct pinmux_range function;
 
-	unsigned first_gpio, last_gpio;
+	const struct sh_pfc_pin *pins;
+	unsigned int nr_pins;
+	const struct pinmux_range *ranges;
+	unsigned int nr_ranges;
+	const struct sh_pfc_pin_group *groups;
+	unsigned int nr_groups;
+	const struct sh_pfc_function *functions;
+	unsigned int nr_functions;
+
+	const struct pinmux_func *func_gpios;
+	unsigned int nr_func_gpios;
 
-	struct pinmux_gpio *gpios;
-	struct pinmux_cfg_reg *cfg_regs;
-	struct pinmux_data_reg *data_regs;
+	const struct pinmux_cfg_reg *cfg_regs;
+	const struct pinmux_data_reg *data_regs;
 
-	pinmux_enum_t *gpio_data;
+	const pinmux_enum_t *gpio_data;
 	unsigned int gpio_data_size;
 
-	struct pinmux_irq *gpio_irq;
+	const struct pinmux_irq *gpio_irq;
 	unsigned int gpio_irq_size;
 
 	unsigned long unlock_reg;
 };
 
-enum { GPIO_CFG_DRYRUN, GPIO_CFG_REQ, GPIO_CFG_FREE };
+enum { GPIO_CFG_REQ, GPIO_CFG_FREE };
 
 /* helper macro for port */
 #define PORT_1(fn, pfx, sfx) fn(pfx, sfx)
@@ -126,6 +180,23 @@ enum { GPIO_CFG_DRYRUN, GPIO_CFG_REQ, GPIO_CFG_FREE };
 	PORT_1(fn, pfx##6, sfx), PORT_1(fn, pfx##7, sfx),	\
 	PORT_1(fn, pfx##8, sfx), PORT_1(fn, pfx##9, sfx)
 
+#define PORT_10_REV(fn, pfx, sfx)	\
+	PORT_1(fn, pfx##9, sfx), PORT_1(fn, pfx##8, sfx),	\
+	PORT_1(fn, pfx##7, sfx), PORT_1(fn, pfx##6, sfx),	\
+	PORT_1(fn, pfx##5, sfx), PORT_1(fn, pfx##4, sfx),	\
+	PORT_1(fn, pfx##3, sfx), PORT_1(fn, pfx##2, sfx),	\
+	PORT_1(fn, pfx##1, sfx), PORT_1(fn, pfx##0, sfx)
+
+#define PORT_32(fn, pfx, sfx)					\
+	PORT_10(fn, pfx, sfx), PORT_10(fn, pfx##1, sfx),	\
+	PORT_10(fn, pfx##2, sfx), PORT_1(fn, pfx##30, sfx),	\
+	PORT_1(fn, pfx##31, sfx)
+
+#define PORT_32_REV(fn, pfx, sfx)					\
+	PORT_1(fn, pfx##31, sfx), PORT_1(fn, pfx##30, sfx),		\
+	PORT_10_REV(fn, pfx##2, sfx), PORT_10_REV(fn, pfx##1, sfx),	\
+	PORT_10_REV(fn, pfx, sfx)
+
 #define PORT_90(fn, pfx, sfx) \
 	PORT_10(fn, pfx##1, sfx), PORT_10(fn, pfx##2, sfx),	\
 	PORT_10(fn, pfx##3, sfx), PORT_10(fn, pfx##4, sfx),	\
@@ -137,7 +208,7 @@ enum { GPIO_CFG_DRYRUN, GPIO_CFG_REQ, GPIO_CFG_FREE };
 #define _GPIO_PORT(pfx, sfx) PINMUX_GPIO(GPIO_PORT##pfx, PORT##pfx##_DATA)
 #define PORT_ALL(str)	CPU_ALL_PORT(_PORT_ALL, PORT, str)
 #define GPIO_PORT_ALL()	CPU_ALL_PORT(_GPIO_PORT, , unused)
-#define GPIO_FN(str) PINMUX_GPIO(GPIO_FN_##str, str##_MARK)
+#define GPIO_FN(str) PINMUX_GPIO_FN(GPIO_FN_##str, PINMUX_FN_BASE, str##_MARK)
 
 /* helper macro for pinmux_enum_t */
 #define PORT_DATA_I(nr)	\
diff --git a/drivers/pinctrl/spear/pinctrl-plgpio.c b/drivers/pinctrl/spear/pinctrl-plgpio.c
index 295b349..3e5a887 100644
--- a/drivers/pinctrl/spear/pinctrl-plgpio.c
+++ b/drivers/pinctrl/spear/pinctrl-plgpio.c
@@ -15,12 +15,12 @@
 #include <linux/io.h>
 #include <linux/irq.h>
 #include <linux/irqdomain.h>
+#include <linux/irqchip/chained_irq.h>
 #include <linux/module.h>
 #include <linux/pinctrl/consumer.h>
 #include <linux/platform_device.h>
 #include <linux/pm.h>
 #include <linux/spinlock.h>
-#include <asm/mach/irq.h>
 
 #define MAX_GPIO_PER_REG		32
 #define PIN_OFFSET(pin)			(pin % MAX_GPIO_PER_REG)
@@ -75,7 +75,7 @@ struct plgpio {
 	int			(*o2p)(int offset);	/* offset_to_pin */
 	u32			p2o_regs;
 	struct plgpio_regs	regs;
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 	struct plgpio_regs	*csave_regs;
 #endif
 };
@@ -554,7 +554,7 @@ static int plgpio_probe(struct platform_device *pdev)
 	if (IS_ERR(plgpio->clk))
 		dev_warn(&pdev->dev, "clk_get() failed, work without it\n");
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 	plgpio->csave_regs = devm_kzalloc(&pdev->dev,
 			sizeof(*plgpio->csave_regs) *
 			DIV_ROUND_UP(plgpio->chip.ngpio, MAX_GPIO_PER_REG),
@@ -641,7 +641,7 @@ unprepare_clk:
 	return ret;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int plgpio_suspend(struct device *dev)
 {
 	struct plgpio *plgpio = dev_get_drvdata(dev);
diff --git a/drivers/pinctrl/spear/pinctrl-spear.c b/drivers/pinctrl/spear/pinctrl-spear.c
index 6a7dae7..116da04 100644
--- a/drivers/pinctrl/spear/pinctrl-spear.c
+++ b/drivers/pinctrl/spear/pinctrl-spear.c
@@ -198,7 +198,7 @@ static void spear_pinctrl_dt_free_map(struct pinctrl_dev *pctldev,
 	kfree(map);
 }
 
-static struct pinctrl_ops spear_pinctrl_ops = {
+static const struct pinctrl_ops spear_pinctrl_ops = {
 	.get_groups_count = spear_pinctrl_get_groups_cnt,
 	.get_group_name = spear_pinctrl_get_group_name,
 	.get_group_pins = spear_pinctrl_get_group_pins,
@@ -340,7 +340,7 @@ static void gpio_disable_free(struct pinctrl_dev *pctldev,
 	gpio_request_endisable(pctldev, range, offset, false);
 }
 
-static struct pinmux_ops spear_pinmux_ops = {
+static const struct pinmux_ops spear_pinmux_ops = {
 	.get_functions_count = spear_pinctrl_get_funcs_count,
 	.get_function_name = spear_pinctrl_get_func_name,
 	.get_function_groups = spear_pinctrl_get_func_groups,
diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c
index fa3ee62..1134119 100644
--- a/drivers/platform/x86/dell-laptop.c
+++ b/drivers/platform/x86/dell-laptop.c
@@ -284,6 +284,7 @@ static void __init parse_da_table(const struct dmi_header *dm)
 {
 	/* Final token is a terminator, so we don't want to copy it */
 	int tokens = (dm->length-11)/sizeof(struct calling_interface_token)-1;
+	struct calling_interface_token *new_da_tokens;
 	struct calling_interface_structure *table =
 		container_of(dm, struct calling_interface_structure, header);
 
@@ -296,12 +297,13 @@ static void __init parse_da_table(const struct dmi_header *dm)
 	da_command_address = table->cmdIOAddress;
 	da_command_code = table->cmdIOCode;
 
-	da_tokens = krealloc(da_tokens, (da_num_tokens + tokens) *
-			     sizeof(struct calling_interface_token),
-			     GFP_KERNEL);
+	new_da_tokens = krealloc(da_tokens, (da_num_tokens + tokens) *
+				 sizeof(struct calling_interface_token),
+				 GFP_KERNEL);
 
-	if (!da_tokens)
+	if (!new_da_tokens)
 		return;
+	da_tokens = new_da_tokens;
 
 	memcpy(da_tokens+da_num_tokens, table->tokens,
 	       sizeof(struct calling_interface_token) * tokens);
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c
index 14d4dce..d544e3a 100644
--- a/drivers/platform/x86/sony-laptop.c
+++ b/drivers/platform/x86/sony-laptop.c
@@ -4121,7 +4121,7 @@ static int sony_pic_enable(struct acpi_device *device,
 		resource->res3.data.irq.sharable = ACPI_SHARED;
 
 		resource->res4.type = ACPI_RESOURCE_TYPE_END_TAG;
-
+		resource->res4.length = sizeof(struct acpi_resource);
 	}
 	/* setup Type 2/3 resources */
 	else {
@@ -4140,6 +4140,7 @@ static int sony_pic_enable(struct acpi_device *device,
 		resource->res2.data.irq.sharable = ACPI_SHARED;
 
 		resource->res3.type = ACPI_RESOURCE_TYPE_END_TAG;
+		resource->res3.length = sizeof(struct acpi_resource);
 	}
 
 	/* Attempt to set the resource */
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index 9a90756..54d31c0 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -844,14 +844,14 @@ static int dispatch_proc_show(struct seq_file *m, void *v)
 
 static int dispatch_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, dispatch_proc_show, PDE(inode)->data);
+	return single_open(file, dispatch_proc_show, PDE_DATA(inode));
 }
 
 static ssize_t dispatch_proc_write(struct file *file,
 			const char __user *userbuf,
 			size_t count, loff_t *pos)
 {
-	struct ibm_struct *ibm = PDE(file_inode(file))->data;
+	struct ibm_struct *ibm = PDE_DATA(file_inode(file));
 	char *kernbuf;
 	int ret;
 
@@ -1964,9 +1964,6 @@ struct tp_nvram_state {
 /* kthread for the hotkey poller */
 static struct task_struct *tpacpi_hotkey_task;
 
-/* Acquired while the poller kthread is running, use to sync start/stop */
-static struct mutex hotkey_thread_mutex;
-
 /*
  * Acquire mutex to write poller control variables as an
  * atomic block.
@@ -2462,8 +2459,6 @@ static int hotkey_kthread(void *data)
 	unsigned int poll_freq;
 	bool was_frozen;
 
-	mutex_lock(&hotkey_thread_mutex);
-
 	if (tpacpi_lifecycle == TPACPI_LIFE_EXITING)
 		goto exit;
 
@@ -2523,7 +2518,6 @@ static int hotkey_kthread(void *data)
 	}
 
 exit:
-	mutex_unlock(&hotkey_thread_mutex);
 	return 0;
 }
 
@@ -2533,9 +2527,6 @@ static void hotkey_poll_stop_sync(void)
 	if (tpacpi_hotkey_task) {
 		kthread_stop(tpacpi_hotkey_task);
 		tpacpi_hotkey_task = NULL;
-		mutex_lock(&hotkey_thread_mutex);
-		/* at this point, the thread did exit */
-		mutex_unlock(&hotkey_thread_mutex);
 	}
 }
 
@@ -3234,7 +3225,6 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
 	mutex_init(&hotkey_mutex);
 
 #ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL
-	mutex_init(&hotkey_thread_mutex);
 	mutex_init(&hotkey_thread_data_mutex);
 #endif
 
diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c
index 242abac..eb3467e 100644
--- a/drivers/platform/x86/toshiba_acpi.c
+++ b/drivers/platform/x86/toshiba_acpi.c
@@ -553,7 +553,7 @@ static int lcd_proc_show(struct seq_file *m, void *v)
 
 static int lcd_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, lcd_proc_show, PDE(inode)->data);
+	return single_open(file, lcd_proc_show, PDE_DATA(inode));
 }
 
 static int set_lcd_brightness(struct toshiba_acpi_dev *dev, int value)
@@ -583,7 +583,7 @@ static int set_lcd_status(struct backlight_device *bd)
 static ssize_t lcd_proc_write(struct file *file, const char __user *buf,
 			      size_t count, loff_t *pos)
 {
-	struct toshiba_acpi_dev *dev = PDE(file_inode(file))->data;
+	struct toshiba_acpi_dev *dev = PDE_DATA(file_inode(file));
 	char cmd[42];
 	size_t len;
 	int value;
@@ -644,13 +644,13 @@ static int video_proc_show(struct seq_file *m, void *v)
 
 static int video_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, video_proc_show, PDE(inode)->data);
+	return single_open(file, video_proc_show, PDE_DATA(inode));
 }
 
 static ssize_t video_proc_write(struct file *file, const char __user *buf,
 				size_t count, loff_t *pos)
 {
-	struct toshiba_acpi_dev *dev = PDE(file_inode(file))->data;
+	struct toshiba_acpi_dev *dev = PDE_DATA(file_inode(file));
 	char *cmd, *buffer;
 	int ret;
 	int value;
@@ -744,13 +744,13 @@ static int fan_proc_show(struct seq_file *m, void *v)
 
 static int fan_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, fan_proc_show, PDE(inode)->data);
+	return single_open(file, fan_proc_show, PDE_DATA(inode));
 }
 
 static ssize_t fan_proc_write(struct file *file, const char __user *buf,
 			      size_t count, loff_t *pos)
 {
-	struct toshiba_acpi_dev *dev = PDE(file_inode(file))->data;
+	struct toshiba_acpi_dev *dev = PDE_DATA(file_inode(file));
 	char cmd[42];
 	size_t len;
 	int value;
@@ -816,13 +816,13 @@ static int keys_proc_show(struct seq_file *m, void *v)
 
 static int keys_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, keys_proc_show, PDE(inode)->data);
+	return single_open(file, keys_proc_show, PDE_DATA(inode));
 }
 
 static ssize_t keys_proc_write(struct file *file, const char __user *buf,
 			       size_t count, loff_t *pos)
 {
-	struct toshiba_acpi_dev *dev = PDE(file_inode(file))->data;
+	struct toshiba_acpi_dev *dev = PDE_DATA(file_inode(file));
 	char cmd[42];
 	size_t len;
 	int value;
@@ -859,7 +859,7 @@ static int version_proc_show(struct seq_file *m, void *v)
 
 static int version_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, version_proc_show, PDE(inode)->data);
+	return single_open(file, version_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations version_proc_fops = {
diff --git a/drivers/pnp/isapnp/proc.c b/drivers/pnp/isapnp/proc.c
index 65f735a..af4d40a 100644
--- a/drivers/pnp/isapnp/proc.c
+++ b/drivers/pnp/isapnp/proc.c
@@ -55,9 +55,7 @@ static loff_t isapnp_proc_bus_lseek(struct file *file, loff_t off, int whence)
 static ssize_t isapnp_proc_bus_read(struct file *file, char __user * buf,
 				    size_t nbytes, loff_t * ppos)
 {
-	struct inode *ino = file_inode(file);
-	struct proc_dir_entry *dp = PDE(ino);
-	struct pnp_dev *dev = dp->data;
+	struct pnp_dev *dev = PDE_DATA(file_inode(file));
 	int pos = *ppos;
 	int cnt, size = 256;
 
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c
index b8f4ea7..9847ab1 100644
--- a/drivers/pnp/pnpacpi/rsparser.c
+++ b/drivers/pnp/pnpacpi/rsparser.c
@@ -634,6 +634,7 @@ int pnpacpi_build_resource_template(struct pnp_dev *dev,
 	}
 	/* resource will pointer the end resource now */
 	resource->type = ACPI_RESOURCE_TYPE_END_TAG;
+	resource->length = sizeof(struct acpi_resource);
 
 	return 0;
 }
diff --git a/drivers/pnp/pnpbios/proc.c b/drivers/pnp/pnpbios/proc.c
index 63ddb01..8dafd65 100644
--- a/drivers/pnp/pnpbios/proc.c
+++ b/drivers/pnp/pnpbios/proc.c
@@ -238,13 +238,13 @@ static int pnpbios_proc_show(struct seq_file *m, void *v)
 
 static int pnpbios_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, pnpbios_proc_show, PDE(inode)->data);
+	return single_open(file, pnpbios_proc_show, PDE_DATA(inode));
 }
 
 static ssize_t pnpbios_proc_write(struct file *file, const char __user *buf,
 				  size_t count, loff_t *pos)
 {
-	void *data = PDE(file_inode(file))->data;
+	void *data = PDE_DATA(file_inode(file));
 	struct pnp_bios_node *node;
 	int boot = (long)data >> 8;
 	u8 nodenum = (long)data;
diff --git a/drivers/power/88pm860x_charger.c b/drivers/power/88pm860x_charger.c
index 4b37a5a..36fb4b5 100644
--- a/drivers/power/88pm860x_charger.c
+++ b/drivers/power/88pm860x_charger.c
@@ -714,7 +714,6 @@ out_irq:
 	while (--i >= 0)
 		free_irq(info->irq[i], info);
 out:
-	kfree(info);
 	return ret;
 }
 
@@ -728,7 +727,6 @@ static int pm860x_charger_remove(struct platform_device *pdev)
 	free_irq(info->irq[0], info);
 	for (i = 0; i < info->irq_nums; i++)
 		free_irq(info->irq[i], info);
-	kfree(info);
 	return 0;
 }
 
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 9e00c38..0d0b5d7 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -254,7 +254,7 @@ config BATTERY_RX51
 
 config CHARGER_ISP1704
 	tristate "ISP1704 USB Charger Detection"
-	depends on USB_OTG_UTILS
+	depends on USB_PHY
 	help
 	  Say Y to enable support for USB Charger Detection with
 	  ISP1707/ISP1704 USB transceivers.
@@ -340,6 +340,13 @@ config CHARGER_SMB347
 	  Say Y to include support for Summit Microelectronics SMB347
 	  Battery Charger.
 
+config CHARGER_TPS65090
+	tristate "TPS65090 battery charger driver"
+	depends on MFD_TPS65090
+	help
+	 Say Y here to enable support for battery charging with TPS65090
+	 PMIC chips.
+
 config AB8500_BM
 	bool "AB8500 Battery Management Driver"
 	depends on AB8500_CORE && AB8500_GPADC
@@ -353,13 +360,6 @@ config BATTERY_GOLDFISH
 	  Say Y to enable support for the battery and AC power in the
 	  Goldfish emulator.
 
-config CHARGER_PM2301
-	bool "PM2301 Battery Charger Driver"
-	depends on AB8500_BM
-	help
-	  Say Y to include support for PM2301 charger driver.
-	  Depends on AB8500 battery management core.
-
 source "drivers/power/reset/Kconfig"
 
 endif # POWER_SUPPLY
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index 3f66436..653bf6c 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -39,7 +39,7 @@ obj-$(CONFIG_CHARGER_PCF50633)	+= pcf50633-charger.o
 obj-$(CONFIG_BATTERY_JZ4740)	+= jz4740-battery.o
 obj-$(CONFIG_BATTERY_INTEL_MID)	+= intel_mid_battery.o
 obj-$(CONFIG_BATTERY_RX51)	+= rx51_battery.o
-obj-$(CONFIG_AB8500_BM)		+= ab8500_bmdata.o ab8500_charger.o ab8500_fg.o ab8500_btemp.o abx500_chargalg.o
+obj-$(CONFIG_AB8500_BM)		+= ab8500_bmdata.o ab8500_charger.o ab8500_fg.o ab8500_btemp.o abx500_chargalg.o pm2301_charger.o
 obj-$(CONFIG_CHARGER_ISP1704)	+= isp1704_charger.o
 obj-$(CONFIG_CHARGER_MAX8903)	+= max8903_charger.o
 obj-$(CONFIG_CHARGER_TWL4030)	+= twl4030_charger.o
@@ -47,10 +47,10 @@ obj-$(CONFIG_CHARGER_LP8727)	+= lp8727_charger.o
 obj-$(CONFIG_CHARGER_LP8788)	+= lp8788-charger.o
 obj-$(CONFIG_CHARGER_GPIO)	+= gpio-charger.o
 obj-$(CONFIG_CHARGER_MANAGER)	+= charger-manager.o
-obj-$(CONFIG_CHARGER_PM2301)	+= pm2301_charger.o
 obj-$(CONFIG_CHARGER_MAX8997)	+= max8997_charger.o
 obj-$(CONFIG_CHARGER_MAX8998)	+= max8998_charger.o
 obj-$(CONFIG_CHARGER_BQ2415X)	+= bq2415x_charger.o
 obj-$(CONFIG_POWER_AVS)		+= avs/
 obj-$(CONFIG_CHARGER_SMB347)	+= smb347-charger.o
+obj-$(CONFIG_CHARGER_TPS65090)	+= tps65090-charger.o
 obj-$(CONFIG_POWER_RESET)	+= reset/
diff --git a/drivers/power/ab8500_bmdata.c b/drivers/power/ab8500_bmdata.c
index 7a96c06..85742a6 100644
--- a/drivers/power/ab8500_bmdata.c
+++ b/drivers/power/ab8500_bmdata.c
@@ -407,15 +407,27 @@ static const struct abx500_fg_parameters fg = {
 	.battok_raising_th_sel1 = 2860,
 	.maint_thres = 95,
 	.user_cap_limit = 15,
+	.pcut_enable = 1,
+	.pcut_max_time = 127,
+	.pcut_flag_time = 112,
+	.pcut_max_restart = 15,
+	.pcut_debounce_time = 2,
 };
 
-static const struct abx500_maxim_parameters maxi_params = {
+static const struct abx500_maxim_parameters ab8500_maxi_params = {
 	.ena_maxi = true,
 	.chg_curr = 910,
 	.wait_cycles = 10,
 	.charger_curr_step = 100,
 };
 
+static const struct abx500_maxim_parameters abx540_maxi_params = {
+        .ena_maxi = true,
+        .chg_curr = 3000,
+        .wait_cycles = 10,
+        .charger_curr_step = 200,
+};
+
 static const struct abx500_bm_charger_parameters chg = {
 	.usb_volt_max		= 5500,
 	.usb_curr_max		= 1500,
@@ -423,6 +435,46 @@ static const struct abx500_bm_charger_parameters chg = {
 	.ac_curr_max		= 1500,
 };
 
+/*
+ * This array maps the raw hex value to charger output current used by the
+ * AB8500 values
+ */
+static int ab8500_charge_output_curr_map[] = {
+        100,    200,    300,    400,    500,    600,    700,    800,
+        900,    1000,   1100,   1200,   1300,   1400,   1500,   1500,
+};
+
+static int ab8540_charge_output_curr_map[] = {
+        0,      0,      0,      75,     100,    125,    150,    175,
+        200,    225,    250,    275,    300,    325,    350,    375,
+        400,    425,    450,    475,    500,    525,    550,    575,
+        600,    625,    650,    675,    700,    725,    750,    775,
+        800,    825,    850,    875,    900,    925,    950,    975,
+        1000,   1025,   1050,   1075,   1100,   1125,   1150,   1175,
+        1200,   1225,   1250,   1275,   1300,   1325,   1350,   1375,
+        1400,   1425,   1450,   1500,   1600,   1700,   1900,   2000,
+};
+
+/*
+ * This array maps the raw hex value to charger input current used by the
+ * AB8500 values
+ */
+static int ab8500_charge_input_curr_map[] = {
+        50,     98,     193,    290,    380,    450,    500,    600,
+        700,    800,    900,    1000,   1100,   1300,   1400,   1500,
+};
+
+static int ab8540_charge_input_curr_map[] = {
+        25,     50,     75,     100,    125,    150,    175,    200,
+        225,    250,    275,    300,    325,    350,    375,    400,
+        425,    450,    475,    500,    525,    550,    575,    600,
+        625,    650,    675,    700,    725,    750,    775,    800,
+        825,    850,    875,    900,    925,    950,    975,    1000,
+        1025,   1050,   1075,   1100,   1125,   1150,   1175,   1200,
+        1225,   1250,   1275,   1300,   1325,   1350,   1375,   1400,
+        1425,   1450,   1475,   1500,   1500,   1500,   1500,   1500,
+};
+
 struct abx500_bm_data ab8500_bm_data = {
 	.temp_under             = 3,
 	.temp_low               = 8,
@@ -442,15 +494,53 @@ struct abx500_bm_data ab8500_bm_data = {
 	.fg_res                 = 100,
 	.cap_levels             = &cap_levels,
 	.bat_type               = bat_type_thermistor,
-	.n_btypes               = 3,
+	.n_btypes               = ARRAY_SIZE(bat_type_thermistor),
 	.batt_id                = 0,
 	.interval_charging      = 5,
 	.interval_not_charging  = 120,
 	.temp_hysteresis        = 3,
 	.gnd_lift_resistance    = 34,
-	.maxi                   = &maxi_params,
+	.chg_output_curr        = ab8500_charge_output_curr_map,
+	.n_chg_out_curr         = ARRAY_SIZE(ab8500_charge_output_curr_map),
+	.maxi                   = &ab8500_maxi_params,
 	.chg_params             = &chg,
 	.fg_params              = &fg,
+        .chg_input_curr         = ab8500_charge_input_curr_map,
+        .n_chg_in_curr          = ARRAY_SIZE(ab8500_charge_input_curr_map),
+};
+
+struct abx500_bm_data ab8540_bm_data = {
+        .temp_under             = 3,
+        .temp_low               = 8,
+        .temp_high              = 43,
+        .temp_over              = 48,
+        .main_safety_tmr_h      = 4,
+        .temp_interval_chg      = 20,
+        .temp_interval_nochg    = 120,
+        .usb_safety_tmr_h       = 4,
+        .bkup_bat_v             = BUP_VCH_SEL_2P6V,
+        .bkup_bat_i             = BUP_ICH_SEL_150UA,
+        .no_maintenance         = false,
+        .capacity_scaling       = false,
+        .adc_therm              = ABx500_ADC_THERM_BATCTRL,
+        .chg_unknown_bat        = false,
+        .enable_overshoot       = false,
+        .fg_res                 = 100,
+        .cap_levels             = &cap_levels,
+        .bat_type               = bat_type_thermistor,
+        .n_btypes               = ARRAY_SIZE(bat_type_thermistor),
+        .batt_id                = 0,
+        .interval_charging      = 5,
+        .interval_not_charging  = 120,
+        .temp_hysteresis        = 3,
+        .gnd_lift_resistance    = 0,
+        .maxi                   = &abx540_maxi_params,
+        .chg_params             = &chg,
+        .fg_params              = &fg,
+        .chg_output_curr        = ab8540_charge_output_curr_map,
+        .n_chg_out_curr         = ARRAY_SIZE(ab8540_charge_output_curr_map),
+        .chg_input_curr         = ab8540_charge_input_curr_map,
+        .n_chg_in_curr          = ARRAY_SIZE(ab8540_charge_input_curr_map),
 };
 
 int ab8500_bm_of_probe(struct device *dev,
diff --git a/drivers/power/ab8500_btemp.c b/drivers/power/ab8500_btemp.c
index 0768906..a9486f1 100644
--- a/drivers/power/ab8500_btemp.c
+++ b/drivers/power/ab8500_btemp.c
@@ -42,6 +42,9 @@
 #define BTEMP_BATCTRL_CURR_SRC_16UA	16
 #define BTEMP_BATCTRL_CURR_SRC_18UA	18
 
+#define BTEMP_BATCTRL_CURR_SRC_60UA	60
+#define BTEMP_BATCTRL_CURR_SRC_120UA	120
+
 #define to_ab8500_btemp_device_info(x) container_of((x), \
 	struct ab8500_btemp, btemp_psy);
 
@@ -76,8 +79,8 @@ struct ab8500_btemp_ranges {
  * @dev:		Pointer to the structure device
  * @node:		List of AB8500 BTEMPs, hence prepared for reentrance
  * @curr_source:	What current source we use, in uA
- * @bat_temp:		Battery temperature in degree Celcius
- * @prev_bat_temp	Last dispatched battery temperature
+ * @bat_temp:		Dispatched battery temperature in degree Celcius
+ * @prev_bat_temp	Last measured battery temperature in degree Celcius
  * @parent:		Pointer to the struct ab8500
  * @gpadc:		Pointer to the struct gpadc
  * @fg:			Pointer to the struct fg
@@ -155,7 +158,7 @@ static int ab8500_btemp_batctrl_volt_to_res(struct ab8500_btemp *di,
 	if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL) {
 		/*
 		 * If the battery has internal NTC, we use the current
-		 * source to calculate the resistance, 7uA or 20uA
+		 * source to calculate the resistance.
 		 */
 		rbs = (v_batctrl * 1000
 		       - di->bm->gnd_lift_resistance * inst_curr)
@@ -216,7 +219,12 @@ static int ab8500_btemp_curr_source_enable(struct ab8500_btemp *di,
 	/* Only do this for batteries with internal NTC */
 	if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL && enable) {
 
-		if (is_ab9540(di->parent) || is_ab8505(di->parent)) {
+		if (is_ab8540(di->parent)) {
+			if (di->curr_source == BTEMP_BATCTRL_CURR_SRC_60UA)
+				curr = BAT_CTRL_60U_ENA;
+			else
+				curr = BAT_CTRL_120U_ENA;
+		} else if (is_ab9540(di->parent) || is_ab8505(di->parent)) {
 			if (di->curr_source == BTEMP_BATCTRL_CURR_SRC_16UA)
 				curr = BAT_CTRL_16U_ENA;
 			else
@@ -257,7 +265,14 @@ static int ab8500_btemp_curr_source_enable(struct ab8500_btemp *di,
 	} else if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL && !enable) {
 		dev_dbg(di->dev, "Disable BATCTRL curr source\n");
 
-		if (is_ab9540(di->parent) || is_ab8505(di->parent)) {
+		if (is_ab8540(di->parent)) {
+			/* Write 0 to the curr bits */
+			ret = abx500_mask_and_set_register_interruptible(
+				di->dev,
+				AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE,
+				BAT_CTRL_60U_ENA | BAT_CTRL_120U_ENA,
+				~(BAT_CTRL_60U_ENA | BAT_CTRL_120U_ENA));
+		} else if (is_ab9540(di->parent) || is_ab8505(di->parent)) {
 			/* Write 0 to the curr bits */
 			ret = abx500_mask_and_set_register_interruptible(
 				di->dev,
@@ -314,7 +329,13 @@ static int ab8500_btemp_curr_source_enable(struct ab8500_btemp *di,
 	 * if we got an error above
 	 */
 disable_curr_source:
-	if (is_ab9540(di->parent) || is_ab8505(di->parent)) {
+	if (is_ab8540(di->parent)) {
+		/* Write 0 to the curr bits */
+		ret = abx500_mask_and_set_register_interruptible(di->dev,
+			AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE,
+			BAT_CTRL_60U_ENA | BAT_CTRL_120U_ENA,
+			~(BAT_CTRL_60U_ENA | BAT_CTRL_120U_ENA));
+	} else if (is_ab9540(di->parent) || is_ab8505(di->parent)) {
 		/* Write 0 to the curr bits */
 		ret = abx500_mask_and_set_register_interruptible(di->dev,
 			AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE,
@@ -541,7 +562,9 @@ static int ab8500_btemp_id(struct ab8500_btemp *di)
 {
 	int res;
 	u8 i;
-	if (is_ab9540(di->parent) || is_ab8505(di->parent))
+	if (is_ab8540(di->parent))
+		di->curr_source = BTEMP_BATCTRL_CURR_SRC_60UA;
+	else if (is_ab9540(di->parent) || is_ab8505(di->parent))
 		di->curr_source = BTEMP_BATCTRL_CURR_SRC_16UA;
 	else
 		di->curr_source = BTEMP_BATCTRL_CURR_SRC_7UA;
@@ -579,12 +602,17 @@ static int ab8500_btemp_id(struct ab8500_btemp *di)
 
 	/*
 	 * We only have to change current source if the
-	 * detected type is Type 1, else we use the 7uA source
+	 * detected type is Type 1.
 	 */
 	if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL &&
-			di->bm->batt_id == 1) {
-		if (is_ab9540(di->parent) || is_ab8505(di->parent)) {
-			dev_dbg(di->dev, "Set BATCTRL current source to 16uA\n");
+	    di->bm->batt_id == 1) {
+		if (is_ab8540(di->parent)) {
+			dev_dbg(di->dev,
+				"Set BATCTRL current source to 60uA\n");
+			di->curr_source = BTEMP_BATCTRL_CURR_SRC_60UA;
+		} else if (is_ab9540(di->parent) || is_ab8505(di->parent)) {
+			dev_dbg(di->dev,
+				"Set BATCTRL current source to 16uA\n");
 			di->curr_source = BTEMP_BATCTRL_CURR_SRC_16UA;
 		} else {
 			dev_dbg(di->dev, "Set BATCTRL current source to 20uA\n");
@@ -604,22 +632,37 @@ static int ab8500_btemp_id(struct ab8500_btemp *di)
 static void ab8500_btemp_periodic_work(struct work_struct *work)
 {
 	int interval;
+	int bat_temp;
 	struct ab8500_btemp *di = container_of(work,
 		struct ab8500_btemp, btemp_periodic_work.work);
 
 	if (!di->initialized) {
-		di->initialized = true;
 		/* Identify the battery */
 		if (ab8500_btemp_id(di) < 0)
 			dev_warn(di->dev, "failed to identify the battery\n");
 	}
 
-	di->bat_temp = ab8500_btemp_measure_temp(di);
-
-	if (di->bat_temp != di->prev_bat_temp) {
-		di->prev_bat_temp = di->bat_temp;
+	bat_temp = ab8500_btemp_measure_temp(di);
+	/*
+	 * Filter battery temperature.
+	 * Allow direct updates on temperature only if two samples result in
+	 * same temperature. Else only allow 1 degree change from previous
+	 * reported value in the direction of the new measurement.
+	 */
+	if ((bat_temp == di->prev_bat_temp) || !di->initialized) {
+		if ((di->bat_temp != di->prev_bat_temp) || !di->initialized) {
+			di->initialized = true;
+			di->bat_temp = bat_temp;
+			power_supply_changed(&di->btemp_psy);
+		}
+	} else if (bat_temp < di->prev_bat_temp) {
+		di->bat_temp--;
+		power_supply_changed(&di->btemp_psy);
+	} else if (bat_temp > di->prev_bat_temp) {
+		di->bat_temp++;
 		power_supply_changed(&di->btemp_psy);
 	}
+	di->prev_bat_temp = bat_temp;
 
 	if (di->events.ac_conn || di->events.usb_conn)
 		interval = di->bm->temp_interval_chg;
diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c
index 24b30b7..a558318 100644
--- a/drivers/power/ab8500_charger.c
+++ b/drivers/power/ab8500_charger.c
@@ -15,6 +15,7 @@
 #include <linux/device.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
+#include <linux/notifier.h>
 #include <linux/slab.h>
 #include <linux/platform_device.h>
 #include <linux/power_supply.h>
@@ -52,10 +53,15 @@
 #define VBUS_DET_DBNC100		0x02
 #define VBUS_DET_DBNC1			0x01
 #define OTP_ENABLE_WD			0x01
+#define DROP_COUNT_RESET		0x01
+#define USB_CH_DET			0x01
 
 #define MAIN_CH_INPUT_CURR_SHIFT	4
 #define VBUS_IN_CURR_LIM_SHIFT		4
+#define AB8540_VBUS_IN_CURR_LIM_SHIFT	2
 #define AUTO_VBUS_IN_CURR_LIM_SHIFT	4
+#define AB8540_AUTO_VBUS_IN_CURR_MASK	0x3F
+#define VBUS_IN_CURR_LIM_RETRY_SET_TIME	30 /* seconds */
 
 #define LED_INDICATOR_PWM_ENA		0x01
 #define LED_INDICATOR_PWM_DIS		0x00
@@ -77,7 +83,9 @@
 
 /* UsbLineStatus register bit masks */
 #define AB8500_USB_LINK_STATUS		0x78
+#define AB8505_USB_LINK_STATUS		0xF8
 #define AB8500_STD_HOST_SUSP		0x18
+#define USB_LINK_STATUS_SHIFT		3
 
 /* Watchdog timeout constant */
 #define WD_TIMER			0x30 /* 4min */
@@ -96,6 +104,10 @@
 #define AB8500_SW_CONTROL_FALLBACK	0x03
 /* Wait for enumeration before charing in us */
 #define WAIT_ACA_RID_ENUMERATION	(5 * 1000)
+/*External charger control*/
+#define AB8500_SYS_CHARGER_CONTROL_REG		0x52
+#define EXTERNAL_CHARGER_DISABLE_REG_VAL	0x03
+#define EXTERNAL_CHARGER_ENABLE_REG_VAL		0x07
 
 /* UsbLineStatus register - usb types */
 enum ab8500_charger_link_status {
@@ -196,10 +208,15 @@ struct ab8500_charger_usb_state {
 	spinlock_t usb_lock;
 };
 
+struct ab8500_charger_max_usb_in_curr {
+	int usb_type_max;
+	int set_max;
+	int calculated_max;
+};
+
 /**
  * struct ab8500_charger - ab8500 Charger device information
  * @dev:		Pointer to the structure device
- * @max_usb_in_curr:	Max USB charger input current
  * @vbus_detected:	VBUS detected
  * @vbus_detected_start:
  *			VBUS detected during startup
@@ -214,7 +231,6 @@ struct ab8500_charger_usb_state {
  * @autopower		Indicate if we should have automatic pwron after pwrloss
  * @autopower_cfg	platform specific power config support for "pwron after pwrloss"
  * @invalid_charger_detect_state State when forcing AB to use invalid charger
- * @is_usb_host:	Indicate if last detected USB type is host
  * @is_aca_rid:		Incicate if accessory is ACA type
  * @current_stepping_sessions:
  *			Counter for current stepping sessions
@@ -223,6 +239,7 @@ struct ab8500_charger_usb_state {
  * @bm:           	Platform specific battery management information
  * @flags:		Structure for information about events triggered
  * @usb_state:		Structure for usb stack information
+ * @max_usb_in_curr:	Max USB charger input current
  * @ac_chg:		AC charger power supply
  * @usb_chg:		USB charger power supply
  * @ac:			Structure that holds the AC charger properties
@@ -254,7 +271,6 @@ struct ab8500_charger_usb_state {
  */
 struct ab8500_charger {
 	struct device *dev;
-	int max_usb_in_curr;
 	bool vbus_detected;
 	bool vbus_detected_start;
 	bool ac_conn;
@@ -266,7 +282,6 @@ struct ab8500_charger {
 	bool autopower;
 	bool autopower_cfg;
 	int invalid_charger_detect_state;
-	bool is_usb_host;
 	int is_aca_rid;
 	atomic_t current_stepping_sessions;
 	struct ab8500 *parent;
@@ -274,6 +289,7 @@ struct ab8500_charger {
 	struct abx500_bm_data *bm;
 	struct ab8500_charger_event_flags flags;
 	struct ab8500_charger_usb_state usb_state;
+	struct ab8500_charger_max_usb_in_curr max_usb_in_curr;
 	struct ux500_charger ac_chg;
 	struct ux500_charger usb_chg;
 	struct ab8500_charger_info ac;
@@ -415,13 +431,18 @@ static void ab8500_charger_set_usb_connected(struct ab8500_charger *di,
 	if (connected != di->usb.charger_connected) {
 		dev_dbg(di->dev, "USB connected:%i\n", connected);
 		di->usb.charger_connected = connected;
+
+		if (!connected)
+			di->flags.vbus_drop_end = false;
+
 		sysfs_notify(&di->usb_chg.psy.dev->kobj, NULL, "present");
 
 		if (connected) {
 			mutex_lock(&di->charger_attached_mutex);
 			mutex_unlock(&di->charger_attached_mutex);
 
-			queue_delayed_work(di->charger_wq,
+			if (is_ab8500(di->parent))
+				queue_delayed_work(di->charger_wq,
 					   &di->usb_charger_attached_work,
 					   HZ);
 		} else {
@@ -668,23 +689,19 @@ static int ab8500_charger_max_usb_curr(struct ab8500_charger *di,
 	case USB_STAT_STD_HOST_C_S:
 		dev_dbg(di->dev, "USB Type - Standard host is "
 			"detected through USB driver\n");
-		di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P5;
-		di->is_usb_host = true;
+		di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P5;
 		di->is_aca_rid = 0;
 		break;
 	case USB_STAT_HOST_CHG_HS_CHIRP:
-		di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P5;
-		di->is_usb_host = true;
+		di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P5;
 		di->is_aca_rid = 0;
 		break;
 	case USB_STAT_HOST_CHG_HS:
-		di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P5;
-		di->is_usb_host = true;
+		di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P5;
 		di->is_aca_rid = 0;
 		break;
 	case USB_STAT_ACA_RID_C_HS:
-		di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P9;
-		di->is_usb_host = false;
+		di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P9;
 		di->is_aca_rid = 0;
 		break;
 	case USB_STAT_ACA_RID_A:
@@ -693,8 +710,7 @@ static int ab8500_charger_max_usb_curr(struct ab8500_charger *di,
 		 * can consume (900mA). Closest level is 500mA
 		 */
 		dev_dbg(di->dev, "USB_STAT_ACA_RID_A detected\n");
-		di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P5;
-		di->is_usb_host = false;
+		di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P5;
 		di->is_aca_rid = 1;
 		break;
 	case USB_STAT_ACA_RID_B:
@@ -702,38 +718,35 @@ static int ab8500_charger_max_usb_curr(struct ab8500_charger *di,
 		 * Dedicated charger level minus 120mA (20mA for ACA and
 		 * 100mA for potential accessory). Closest level is 1300mA
 		 */
-		di->max_usb_in_curr = USB_CH_IP_CUR_LVL_1P3;
+		di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_1P3;
 		dev_dbg(di->dev, "USB Type - 0x%02x MaxCurr: %d", link_status,
-				di->max_usb_in_curr);
-		di->is_usb_host = false;
+				di->max_usb_in_curr.usb_type_max);
 		di->is_aca_rid = 1;
 		break;
 	case USB_STAT_HOST_CHG_NM:
-		di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P5;
-		di->is_usb_host = true;
+		di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P5;
 		di->is_aca_rid = 0;
 		break;
 	case USB_STAT_DEDICATED_CHG:
-		di->max_usb_in_curr = USB_CH_IP_CUR_LVL_1P5;
-		di->is_usb_host = false;
+		di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_1P5;
 		di->is_aca_rid = 0;
 		break;
 	case USB_STAT_ACA_RID_C_HS_CHIRP:
 	case USB_STAT_ACA_RID_C_NM:
-		di->max_usb_in_curr = USB_CH_IP_CUR_LVL_1P5;
-		di->is_usb_host = false;
+		di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_1P5;
 		di->is_aca_rid = 1;
 		break;
 	case USB_STAT_NOT_CONFIGURED:
 		if (di->vbus_detected) {
 			di->usb_device_is_unrecognised = true;
 			dev_dbg(di->dev, "USB Type - Legacy charger.\n");
-			di->max_usb_in_curr = USB_CH_IP_CUR_LVL_1P5;
+			di->max_usb_in_curr.usb_type_max =
+						USB_CH_IP_CUR_LVL_1P5;
 			break;
 		}
 	case USB_STAT_HM_IDGND:
 		dev_err(di->dev, "USB Type - Charging not allowed\n");
-		di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P05;
+		di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P05;
 		ret = -ENXIO;
 		break;
 	case USB_STAT_RESERVED:
@@ -743,12 +756,13 @@ static int ab8500_charger_max_usb_curr(struct ab8500_charger *di,
 						"VBUS has collapsed\n");
 			ret = -ENXIO;
 			break;
-		}
-		if (is_ab9540(di->parent) || is_ab8505(di->parent)) {
+		} else {
 			dev_dbg(di->dev, "USB Type - Charging not allowed\n");
-			di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P05;
+			di->max_usb_in_curr.usb_type_max =
+						USB_CH_IP_CUR_LVL_0P05;
 			dev_dbg(di->dev, "USB Type - 0x%02x MaxCurr: %d",
-					link_status, di->max_usb_in_curr);
+				link_status,
+				di->max_usb_in_curr.usb_type_max);
 			ret = -ENXIO;
 			break;
 		}
@@ -757,23 +771,24 @@ static int ab8500_charger_max_usb_curr(struct ab8500_charger *di,
 	case USB_STAT_CARKIT_2:
 	case USB_STAT_ACA_DOCK_CHARGER:
 	case USB_STAT_CHARGER_LINE_1:
-		di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P5;
+		di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P5;
 		dev_dbg(di->dev, "USB Type - 0x%02x MaxCurr: %d", link_status,
-				di->max_usb_in_curr);
+				di->max_usb_in_curr.usb_type_max);
 	case USB_STAT_NOT_VALID_LINK:
 		dev_err(di->dev, "USB Type invalid - try charging anyway\n");
-		di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P5;
+		di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P5;
 		break;
 
 	default:
 		dev_err(di->dev, "USB Type - Unknown\n");
-		di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P05;
+		di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P05;
 		ret = -ENXIO;
 		break;
 	};
 
+	di->max_usb_in_curr.set_max = di->max_usb_in_curr.usb_type_max;
 	dev_dbg(di->dev, "USB Type - 0x%02x MaxCurr: %d",
-		link_status, di->max_usb_in_curr);
+		link_status, di->max_usb_in_curr.set_max);
 
 	return ret;
 }
@@ -796,21 +811,22 @@ static int ab8500_charger_read_usb_type(struct ab8500_charger *di)
 		dev_err(di->dev, "%s ab8500 read failed\n", __func__);
 		return ret;
 	}
-	if (is_ab8500(di->parent)) {
+	if (is_ab8500(di->parent))
 		ret = abx500_get_register_interruptible(di->dev, AB8500_USB,
-				AB8500_USB_LINE_STAT_REG, &val);
-	} else {
-		if (is_ab9540(di->parent) || is_ab8505(di->parent))
-			ret = abx500_get_register_interruptible(di->dev,
-				AB8500_USB, AB8500_USB_LINK1_STAT_REG, &val);
-	}
+			AB8500_USB_LINE_STAT_REG, &val);
+	else
+		ret = abx500_get_register_interruptible(di->dev,
+			AB8500_USB, AB8500_USB_LINK1_STAT_REG, &val);
 	if (ret < 0) {
 		dev_err(di->dev, "%s ab8500 read failed\n", __func__);
 		return ret;
 	}
 
 	/* get the USB type */
-	val = (val & AB8500_USB_LINK_STATUS) >> 3;
+	if (is_ab8500(di->parent))
+		val = (val & AB8500_USB_LINK_STATUS) >> USB_LINK_STATUS_SHIFT;
+	else
+		val = (val & AB8505_USB_LINK_STATUS) >> USB_LINK_STATUS_SHIFT;
 	ret = ab8500_charger_max_usb_curr(di,
 		(enum ab8500_charger_link_status) val);
 
@@ -865,7 +881,12 @@ static int ab8500_charger_detect_usb_type(struct ab8500_charger *di)
 		 */
 
 		/* get the USB type */
-		val = (val & AB8500_USB_LINK_STATUS) >> 3;
+		if (is_ab8500(di->parent))
+			val = (val & AB8500_USB_LINK_STATUS) >>
+							USB_LINK_STATUS_SHIFT;
+		else
+			val = (val & AB8505_USB_LINK_STATUS) >>
+							USB_LINK_STATUS_SHIFT;
 		if (val)
 			break;
 	}
@@ -960,51 +981,6 @@ static int ab8500_charger_voltage_map[] = {
 	4600 ,
 };
 
-/*
- * This array maps the raw hex value to charger current used by the AB8500
- * Values taken from the UM0836
- */
-static int ab8500_charger_current_map[] = {
-	100 ,
-	200 ,
-	300 ,
-	400 ,
-	500 ,
-	600 ,
-	700 ,
-	800 ,
-	900 ,
-	1000 ,
-	1100 ,
-	1200 ,
-	1300 ,
-	1400 ,
-	1500 ,
-};
-
-/*
- * This array maps the raw hex value to VBUS input current used by the AB8500
- * Values taken from the UM0836
- */
-static int ab8500_charger_vbus_in_curr_map[] = {
-	USB_CH_IP_CUR_LVL_0P05,
-	USB_CH_IP_CUR_LVL_0P09,
-	USB_CH_IP_CUR_LVL_0P19,
-	USB_CH_IP_CUR_LVL_0P29,
-	USB_CH_IP_CUR_LVL_0P38,
-	USB_CH_IP_CUR_LVL_0P45,
-	USB_CH_IP_CUR_LVL_0P5,
-	USB_CH_IP_CUR_LVL_0P6,
-	USB_CH_IP_CUR_LVL_0P7,
-	USB_CH_IP_CUR_LVL_0P8,
-	USB_CH_IP_CUR_LVL_0P9,
-	USB_CH_IP_CUR_LVL_1P0,
-	USB_CH_IP_CUR_LVL_1P1,
-	USB_CH_IP_CUR_LVL_1P3,
-	USB_CH_IP_CUR_LVL_1P4,
-	USB_CH_IP_CUR_LVL_1P5,
-};
-
 static int ab8500_voltage_to_regval(int voltage)
 {
 	int i;
@@ -1026,41 +1002,41 @@ static int ab8500_voltage_to_regval(int voltage)
 		return -1;
 }
 
-static int ab8500_current_to_regval(int curr)
+static int ab8500_current_to_regval(struct ab8500_charger *di, int curr)
 {
 	int i;
 
-	if (curr < ab8500_charger_current_map[0])
+	if (curr < di->bm->chg_output_curr[0])
 		return 0;
 
-	for (i = 0; i < ARRAY_SIZE(ab8500_charger_current_map); i++) {
-		if (curr < ab8500_charger_current_map[i])
+	for (i = 0; i < di->bm->n_chg_out_curr; i++) {
+		if (curr < di->bm->chg_output_curr[i])
 			return i - 1;
 	}
 
 	/* If not last element, return error */
-	i = ARRAY_SIZE(ab8500_charger_current_map) - 1;
-	if (curr == ab8500_charger_current_map[i])
+	i = di->bm->n_chg_out_curr - 1;
+	if (curr == di->bm->chg_output_curr[i])
 		return i;
 	else
 		return -1;
 }
 
-static int ab8500_vbus_in_curr_to_regval(int curr)
+static int ab8500_vbus_in_curr_to_regval(struct ab8500_charger *di, int curr)
 {
 	int i;
 
-	if (curr < ab8500_charger_vbus_in_curr_map[0])
+	if (curr < di->bm->chg_input_curr[0])
 		return 0;
 
-	for (i = 0; i < ARRAY_SIZE(ab8500_charger_vbus_in_curr_map); i++) {
-		if (curr < ab8500_charger_vbus_in_curr_map[i])
+	for (i = 0; i < di->bm->n_chg_in_curr; i++) {
+		if (curr < di->bm->chg_input_curr[i])
 			return i - 1;
 	}
 
 	/* If not last element, return error */
-	i = ARRAY_SIZE(ab8500_charger_vbus_in_curr_map) - 1;
-	if (curr == ab8500_charger_vbus_in_curr_map[i])
+	i = di->bm->n_chg_in_curr - 1;
+	if (curr == di->bm->chg_input_curr[i])
 		return i;
 	else
 		return -1;
@@ -1077,28 +1053,48 @@ static int ab8500_vbus_in_curr_to_regval(int curr)
  */
 static int ab8500_charger_get_usb_cur(struct ab8500_charger *di)
 {
+	int ret = 0;
 	switch (di->usb_state.usb_current) {
 	case 100:
-		di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P09;
+		di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P09;
 		break;
 	case 200:
-		di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P19;
+		di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P19;
 		break;
 	case 300:
-		di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P29;
+		di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P29;
 		break;
 	case 400:
-		di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P38;
+		di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P38;
 		break;
 	case 500:
-		di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P5;
+		di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P5;
 		break;
 	default:
-		di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P05;
-		return -1;
+		di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P05;
+		ret = -EPERM;
 		break;
 	};
-	return 0;
+	di->max_usb_in_curr.set_max = di->max_usb_in_curr.usb_type_max;
+	return ret;
+}
+
+/**
+ * ab8500_charger_check_continue_stepping() - Check to allow stepping
+ * @di:		pointer to the ab8500_charger structure
+ * @reg:	select what charger register to check
+ *
+ * Check if current stepping should be allowed to continue.
+ * Checks if charger source has not collapsed. If it has, further stepping
+ * is not allowed.
+ */
+static bool ab8500_charger_check_continue_stepping(struct ab8500_charger *di,
+						   int reg)
+{
+	if (reg == AB8500_USBCH_IPT_CRNTLVL_REG)
+		return !di->flags.vbus_drop_end;
+	else
+		return true;
 }
 
 /**
@@ -1118,7 +1114,7 @@ static int ab8500_charger_set_current(struct ab8500_charger *di,
 	int ich, int reg)
 {
 	int ret = 0;
-	int auto_curr_index, curr_index, prev_curr_index, shift_value, i;
+	int curr_index, prev_curr_index, shift_value, i;
 	u8 reg_value;
 	u32 step_udelay;
 	bool no_stepping = false;
@@ -1136,39 +1132,27 @@ static int ab8500_charger_set_current(struct ab8500_charger *di,
 	case AB8500_MCH_IPT_CURLVL_REG:
 		shift_value = MAIN_CH_INPUT_CURR_SHIFT;
 		prev_curr_index = (reg_value >> shift_value);
-		curr_index = ab8500_current_to_regval(ich);
+		curr_index = ab8500_current_to_regval(di, ich);
 		step_udelay = STEP_UDELAY;
 		if (!di->ac.charger_connected)
 			no_stepping = true;
 		break;
 	case AB8500_USBCH_IPT_CRNTLVL_REG:
-		shift_value = VBUS_IN_CURR_LIM_SHIFT;
+		if (is_ab8540(di->parent))
+			shift_value = AB8540_VBUS_IN_CURR_LIM_SHIFT;
+		else
+			shift_value = VBUS_IN_CURR_LIM_SHIFT;
 		prev_curr_index = (reg_value >> shift_value);
-		curr_index = ab8500_vbus_in_curr_to_regval(ich);
+		curr_index = ab8500_vbus_in_curr_to_regval(di, ich);
 		step_udelay = STEP_UDELAY * 100;
 
-		ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER,
-					AB8500_CH_USBCH_STAT2_REG, &reg_value);
-		if (ret < 0) {
-			dev_err(di->dev, "%s read failed\n", __func__);
-			goto exit_set_current;
-		}
-		auto_curr_index =
-			reg_value >> AUTO_VBUS_IN_CURR_LIM_SHIFT;
-
-		dev_dbg(di->dev, "%s Auto VBUS curr is %d mA\n",
-			__func__,
-			ab8500_charger_vbus_in_curr_map[auto_curr_index]);
-
-		prev_curr_index = min(prev_curr_index, auto_curr_index);
-
 		if (!di->usb.charger_connected)
 			no_stepping = true;
 		break;
 	case AB8500_CH_OPT_CRNTLVL_REG:
 		shift_value = 0;
 		prev_curr_index = (reg_value >> shift_value);
-		curr_index = ab8500_current_to_regval(ich);
+		curr_index = ab8500_current_to_regval(di, ich);
 		step_udelay = STEP_UDELAY;
 		if (curr_index && (curr_index - prev_curr_index) > 1)
 			step_udelay *= 100;
@@ -1219,7 +1203,8 @@ static int ab8500_charger_set_current(struct ab8500_charger *di,
 				usleep_range(step_udelay, step_udelay * 2);
 		}
 	} else {
-		for (i = prev_curr_index + 1; i <= curr_index; i++) {
+		bool allow = true;
+		for (i = prev_curr_index + 1; i <= curr_index && allow; i++) {
 			dev_dbg(di->dev, "curr change_2 to: %x for 0x%02x\n",
 				(u8)i << shift_value, reg);
 			ret = abx500_set_register_interruptible(di->dev,
@@ -1230,6 +1215,8 @@ static int ab8500_charger_set_current(struct ab8500_charger *di,
 			}
 			if (i != curr_index)
 				usleep_range(step_udelay, step_udelay * 2);
+
+			allow = ab8500_charger_check_continue_stepping(di, reg);
 		}
 	}
 
@@ -1255,6 +1242,11 @@ static int ab8500_charger_set_vbus_in_curr(struct ab8500_charger *di,
 
 	/* We should always use to lowest current limit */
 	min_value = min(di->bm->chg_params->usb_curr_max, ich_in);
+	if (di->max_usb_in_curr.set_max > 0)
+		min_value = min(di->max_usb_in_curr.set_max, min_value);
+
+	if (di->usb_state.usb_current >= 0)
+		min_value = min(di->usb_state.usb_current, min_value);
 
 	switch (min_value) {
 	case 100:
@@ -1400,8 +1392,8 @@ static int ab8500_charger_ac_en(struct ux500_charger *charger,
 
 		/* Check if the requested voltage or current is valid */
 		volt_index = ab8500_voltage_to_regval(vset);
-		curr_index = ab8500_current_to_regval(iset);
-		input_curr_index = ab8500_current_to_regval(
+		curr_index = ab8500_current_to_regval(di, iset);
+		input_curr_index = ab8500_current_to_regval(di,
 			di->bm->chg_params->ac_curr_max);
 		if (volt_index < 0 || curr_index < 0 || input_curr_index < 0) {
 			dev_err(di->dev,
@@ -1572,7 +1564,7 @@ static int ab8500_charger_usb_en(struct ux500_charger *charger,
 
 		/* Check if the requested voltage or current is valid */
 		volt_index = ab8500_voltage_to_regval(vset);
-		curr_index = ab8500_current_to_regval(ich_out);
+		curr_index = ab8500_current_to_regval(di, ich_out);
 		if (volt_index < 0 || curr_index < 0) {
 			dev_err(di->dev,
 				"Charger voltage or current too high, "
@@ -1609,7 +1601,8 @@ static int ab8500_charger_usb_en(struct ux500_charger *charger,
 		di->usb.charger_online = 1;
 
 		/* USBChInputCurr: current that can be drawn from the usb */
-		ret = ab8500_charger_set_vbus_in_curr(di, di->max_usb_in_curr);
+		ret = ab8500_charger_set_vbus_in_curr(di,
+					di->max_usb_in_curr.usb_type_max);
 		if (ret) {
 			dev_err(di->dev, "setting USBChInputCurr failed\n");
 			return ret;
@@ -1668,8 +1661,7 @@ static int ab8500_charger_usb_en(struct ux500_charger *charger,
 		dev_dbg(di->dev, "%s Disabled USB charging\n", __func__);
 
 		/* Cancel any pending Vbat check work */
-		if (delayed_work_pending(&di->check_vbat_work))
-			cancel_delayed_work(&di->check_vbat_work);
+		cancel_delayed_work(&di->check_vbat_work);
 
 	}
 	ab8500_power_supply_changed(di, &di->usb_chg.psy);
@@ -1677,6 +1669,128 @@ static int ab8500_charger_usb_en(struct ux500_charger *charger,
 	return ret;
 }
 
+static int ab8500_external_charger_prepare(struct notifier_block *charger_nb,
+				unsigned long event, void *data)
+{
+	int ret;
+	struct device *dev = data;
+	/*Toggle External charger control pin*/
+	ret = abx500_set_register_interruptible(dev, AB8500_SYS_CTRL1_BLOCK,
+				  AB8500_SYS_CHARGER_CONTROL_REG,
+				  EXTERNAL_CHARGER_DISABLE_REG_VAL);
+	if (ret < 0) {
+		dev_err(dev, "write reg failed %d\n", ret);
+		goto out;
+	}
+	ret = abx500_set_register_interruptible(dev, AB8500_SYS_CTRL1_BLOCK,
+				  AB8500_SYS_CHARGER_CONTROL_REG,
+				  EXTERNAL_CHARGER_ENABLE_REG_VAL);
+	if (ret < 0)
+		dev_err(dev, "Write reg failed %d\n", ret);
+
+out:
+	return ret;
+}
+
+/**
+ * ab8500_charger_usb_check_enable() - enable usb charging
+ * @charger:	pointer to the ux500_charger structure
+ * @vset:	charging voltage
+ * @iset:	charger output current
+ *
+ * Check if the VBUS charger has been disconnected and reconnected without
+ * AB8500 rising an interrupt. Returns 0 on success.
+ */
+static int ab8500_charger_usb_check_enable(struct ux500_charger *charger,
+	int vset, int iset)
+{
+	u8 usbch_ctrl1 = 0;
+	int ret = 0;
+
+	struct ab8500_charger *di = to_ab8500_charger_usb_device_info(charger);
+
+	if (!di->usb.charger_connected)
+		return ret;
+
+	ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER,
+				AB8500_USBCH_CTRL1_REG, &usbch_ctrl1);
+	if (ret < 0) {
+		dev_err(di->dev, "ab8500 read failed %d\n", __LINE__);
+		return ret;
+	}
+	dev_dbg(di->dev, "USB charger ctrl: 0x%02x\n", usbch_ctrl1);
+
+	if (!(usbch_ctrl1 & USB_CH_ENA)) {
+		dev_info(di->dev, "Charging has been disabled abnormally and will be re-enabled\n");
+
+		ret = abx500_mask_and_set_register_interruptible(di->dev,
+					AB8500_CHARGER, AB8500_CHARGER_CTRL,
+					DROP_COUNT_RESET, DROP_COUNT_RESET);
+		if (ret < 0) {
+			dev_err(di->dev, "ab8500 write failed %d\n", __LINE__);
+			return ret;
+		}
+
+		ret = ab8500_charger_usb_en(&di->usb_chg, true, vset, iset);
+		if (ret < 0) {
+			dev_err(di->dev, "Failed to enable VBUS charger %d\n",
+					__LINE__);
+			return ret;
+		}
+	}
+	return ret;
+}
+
+/**
+ * ab8500_charger_ac_check_enable() - enable usb charging
+ * @charger:	pointer to the ux500_charger structure
+ * @vset:	charging voltage
+ * @iset:	charger output current
+ *
+ * Check if the AC charger has been disconnected and reconnected without
+ * AB8500 rising an interrupt. Returns 0 on success.
+ */
+static int ab8500_charger_ac_check_enable(struct ux500_charger *charger,
+	int vset, int iset)
+{
+	u8 mainch_ctrl1 = 0;
+	int ret = 0;
+
+	struct ab8500_charger *di = to_ab8500_charger_ac_device_info(charger);
+
+	if (!di->ac.charger_connected)
+		return ret;
+
+	ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER,
+				AB8500_MCH_CTRL1, &mainch_ctrl1);
+	if (ret < 0) {
+		dev_err(di->dev, "ab8500 read failed %d\n", __LINE__);
+		return ret;
+	}
+	dev_dbg(di->dev, "AC charger ctrl: 0x%02x\n", mainch_ctrl1);
+
+	if (!(mainch_ctrl1 & MAIN_CH_ENA)) {
+		dev_info(di->dev, "Charging has been disabled abnormally and will be re-enabled\n");
+
+		ret = abx500_mask_and_set_register_interruptible(di->dev,
+					AB8500_CHARGER, AB8500_CHARGER_CTRL,
+					DROP_COUNT_RESET, DROP_COUNT_RESET);
+
+		if (ret < 0) {
+			dev_err(di->dev, "ab8500 write failed %d\n", __LINE__);
+			return ret;
+		}
+
+		ret = ab8500_charger_ac_en(&di->usb_chg, true, vset, iset);
+		if (ret < 0) {
+			dev_err(di->dev, "failed to enable AC charger %d\n",
+				__LINE__);
+			return ret;
+		}
+	}
+	return ret;
+}
+
 /**
  * ab8500_charger_watchdog_kick() - kick charger watchdog
  * @di:		pointer to the ab8500_charger structure
@@ -1734,8 +1848,68 @@ static int ab8500_charger_update_charger_current(struct ux500_charger *charger,
 
 	/* Reset the main and usb drop input current measurement counter */
 	ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER,
-				AB8500_CHARGER_CTRL,
-				0x1);
+				AB8500_CHARGER_CTRL, DROP_COUNT_RESET);
+	if (ret) {
+		dev_err(di->dev, "%s write failed\n", __func__);
+		return ret;
+	}
+
+	return ret;
+}
+
+/**
+ * ab8540_charger_power_path_enable() - enable usb power path mode
+ * @charger:	pointer to the ux500_charger structure
+ * @enable:	enable/disable flag
+ *
+ * Enable or disable the power path for usb mode
+ * Returns error code in case of failure else 0(on success)
+ */
+static int ab8540_charger_power_path_enable(struct ux500_charger *charger,
+		bool enable)
+{
+	int ret;
+	struct ab8500_charger *di;
+
+	if (charger->psy.type == POWER_SUPPLY_TYPE_USB)
+		di = to_ab8500_charger_usb_device_info(charger);
+	else
+		return -ENXIO;
+
+	ret = abx500_mask_and_set_register_interruptible(di->dev,
+				AB8500_CHARGER, AB8540_USB_PP_MODE_REG,
+				BUS_POWER_PATH_MODE_ENA, enable);
+	if (ret) {
+		dev_err(di->dev, "%s write failed\n", __func__);
+		return ret;
+	}
+
+	return ret;
+}
+
+
+/**
+ * ab8540_charger_usb_pre_chg_enable() - enable usb pre change
+ * @charger:	pointer to the ux500_charger structure
+ * @enable:	enable/disable flag
+ *
+ * Enable or disable the pre-chage for usb mode
+ * Returns error code in case of failure else 0(on success)
+ */
+static int ab8540_charger_usb_pre_chg_enable(struct ux500_charger *charger,
+		bool enable)
+{
+	int ret;
+	struct ab8500_charger *di;
+
+	if (charger->psy.type == POWER_SUPPLY_TYPE_USB)
+		di = to_ab8500_charger_usb_device_info(charger);
+	else
+		return -ENXIO;
+
+	ret = abx500_mask_and_set_register_interruptible(di->dev,
+				AB8500_CHARGER, AB8540_USB_PP_CHR_REG,
+				BUS_POWER_PATH_PRECHG_ENA, enable);
 	if (ret) {
 		dev_err(di->dev, "%s write failed\n", __func__);
 		return ret;
@@ -1823,9 +1997,10 @@ static void ab8500_charger_check_vbat_work(struct work_struct *work)
 		di->vbat > VBAT_TRESH_IP_CUR_RED))) {
 
 		dev_dbg(di->dev, "Vbat did cross threshold, curr: %d, new: %d,"
-			" old: %d\n", di->max_usb_in_curr, di->vbat,
-			di->old_vbat);
-		ab8500_charger_set_vbus_in_curr(di, di->max_usb_in_curr);
+			" old: %d\n", di->max_usb_in_curr.usb_type_max,
+			di->vbat, di->old_vbat);
+		ab8500_charger_set_vbus_in_curr(di,
+					di->max_usb_in_curr.usb_type_max);
 		power_supply_changed(&di->usb_chg.psy);
 	}
 
@@ -2105,7 +2280,8 @@ static void ab8500_charger_usb_link_attach_work(struct work_struct *work)
 
 	/* Update maximum input current if USB enumeration is not detected */
 	if (!di->usb.charger_online) {
-		ret = ab8500_charger_set_vbus_in_curr(di, di->max_usb_in_curr);
+		ret = ab8500_charger_set_vbus_in_curr(di,
+					di->max_usb_in_curr.usb_type_max);
 		if (ret)
 			return;
 	}
@@ -2125,6 +2301,7 @@ static void ab8500_charger_usb_link_status_work(struct work_struct *work)
 	int detected_chargers;
 	int ret;
 	u8 val;
+	u8 link_status;
 
 	struct ab8500_charger *di = container_of(work,
 		struct ab8500_charger, usb_link_status_work);
@@ -2144,38 +2321,61 @@ static void ab8500_charger_usb_link_status_work(struct work_struct *work)
 	 * to start the charging process. but by jumping
 	 * thru a few hoops it can be forced to start.
 	 */
-	ret = abx500_get_register_interruptible(di->dev, AB8500_USB,
-			AB8500_USB_LINE_STAT_REG, &val);
+	if (is_ab8500(di->parent))
+		ret = abx500_get_register_interruptible(di->dev, AB8500_USB,
+					AB8500_USB_LINE_STAT_REG, &val);
+	else
+		ret = abx500_get_register_interruptible(di->dev, AB8500_USB,
+					AB8500_USB_LINK1_STAT_REG, &val);
+
 	if (ret >= 0)
 		dev_dbg(di->dev, "UsbLineStatus register = 0x%02x\n", val);
 	else
 		dev_dbg(di->dev, "Error reading USB link status\n");
 
+	if (is_ab8500(di->parent))
+		link_status = AB8500_USB_LINK_STATUS;
+	else
+		link_status = AB8505_USB_LINK_STATUS;
+
 	if (detected_chargers & USB_PW_CONN) {
-		if (((val & AB8500_USB_LINK_STATUS) >> 3) == USB_STAT_NOT_VALID_LINK &&
+		if (((val & link_status) >> USB_LINK_STATUS_SHIFT) ==
+				USB_STAT_NOT_VALID_LINK &&
 				di->invalid_charger_detect_state == 0) {
-			dev_dbg(di->dev, "Invalid charger detected, state= 0\n");
+			dev_dbg(di->dev,
+					"Invalid charger detected, state= 0\n");
 			/*Enable charger*/
 			abx500_mask_and_set_register_interruptible(di->dev,
-					AB8500_CHARGER, AB8500_USBCH_CTRL1_REG, 0x01, 0x01);
+					AB8500_CHARGER, AB8500_USBCH_CTRL1_REG,
+					USB_CH_ENA, USB_CH_ENA);
 			/*Enable charger detection*/
-			abx500_mask_and_set_register_interruptible(di->dev, AB8500_USB,
-					AB8500_MCH_IPT_CURLVL_REG, 0x01, 0x01);
+			abx500_mask_and_set_register_interruptible(di->dev,
+					AB8500_USB, AB8500_USB_LINE_CTRL2_REG,
+					USB_CH_DET, USB_CH_DET);
 			di->invalid_charger_detect_state = 1;
 			/*exit and wait for new link status interrupt.*/
 			return;
 
 		}
 		if (di->invalid_charger_detect_state == 1) {
-			dev_dbg(di->dev, "Invalid charger detected, state= 1\n");
+			dev_dbg(di->dev,
+					"Invalid charger detected, state= 1\n");
 			/*Stop charger detection*/
-			abx500_mask_and_set_register_interruptible(di->dev, AB8500_USB,
-					AB8500_MCH_IPT_CURLVL_REG, 0x01, 0x00);
+			abx500_mask_and_set_register_interruptible(di->dev,
+					AB8500_USB, AB8500_USB_LINE_CTRL2_REG,
+					USB_CH_DET, 0x00);
 			/*Check link status*/
-			ret = abx500_get_register_interruptible(di->dev, AB8500_USB,
-					AB8500_USB_LINE_STAT_REG, &val);
+			if (is_ab8500(di->parent))
+				ret = abx500_get_register_interruptible(di->dev,
+					AB8500_USB, AB8500_USB_LINE_STAT_REG,
+					&val);
+			else
+				ret = abx500_get_register_interruptible(di->dev,
+					AB8500_USB, AB8500_USB_LINK1_STAT_REG,
+					&val);
+
 			dev_dbg(di->dev, "USB link status= 0x%02x\n",
-					(val & AB8500_USB_LINK_STATUS) >> 3);
+				(val & link_status) >> USB_LINK_STATUS_SHIFT);
 			di->invalid_charger_detect_state = 2;
 		}
 	} else {
@@ -2273,7 +2473,7 @@ static void ab8500_charger_usb_state_changed_work(struct work_struct *work)
 		if (!ab8500_charger_get_usb_cur(di)) {
 			/* Update maximum input current */
 			ret = ab8500_charger_set_vbus_in_curr(di,
-					di->max_usb_in_curr);
+					di->max_usb_in_curr.usb_type_max);
 			if (ret)
 				return;
 
@@ -2422,7 +2622,9 @@ static irqreturn_t ab8500_charger_mainchplugdet_handler(int irq, void *_di)
 
 	mutex_lock(&di->charger_attached_mutex);
 	mutex_unlock(&di->charger_attached_mutex);
-	queue_delayed_work(di->charger_wq,
+
+	if (is_ab8500(di->parent))
+		queue_delayed_work(di->charger_wq,
 			   &di->ac_charger_attached_work,
 			   HZ);
 	return IRQ_HANDLED;
@@ -2491,6 +2693,8 @@ static void ab8500_charger_vbus_drop_end_work(struct work_struct *work)
 {
 	struct ab8500_charger *di = container_of(work,
 		struct ab8500_charger, vbus_drop_end_work.work);
+	int ret, curr;
+	u8 reg_value;
 
 	di->flags.vbus_drop_end = false;
 
@@ -2498,8 +2702,45 @@ static void ab8500_charger_vbus_drop_end_work(struct work_struct *work)
 	abx500_set_register_interruptible(di->dev,
 				  AB8500_CHARGER, AB8500_CHARGER_CTRL, 0x01);
 
+	if (is_ab8540(di->parent))
+		ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER,
+				AB8540_CH_USBCH_STAT3_REG, &reg_value);
+	else
+		ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER,
+				AB8500_CH_USBCH_STAT2_REG, &reg_value);
+	if (ret < 0) {
+		dev_err(di->dev, "%s read failed\n", __func__);
+		return;
+	}
+
+	if (is_ab8540(di->parent))
+		curr = di->bm->chg_input_curr[
+			reg_value & AB8540_AUTO_VBUS_IN_CURR_MASK];
+	else
+		curr = di->bm->chg_input_curr[
+			reg_value >> AUTO_VBUS_IN_CURR_LIM_SHIFT];
+
+	if (di->max_usb_in_curr.calculated_max != curr) {
+		/* USB source is collapsing */
+		di->max_usb_in_curr.calculated_max = curr;
+		dev_dbg(di->dev,
+			 "VBUS input current limiting to %d mA\n",
+			 di->max_usb_in_curr.calculated_max);
+	} else {
+		/*
+		 * USB source can not give more than this amount.
+		 * Taking more will collapse the source.
+		 */
+		di->max_usb_in_curr.set_max =
+			di->max_usb_in_curr.calculated_max;
+		dev_dbg(di->dev,
+			 "VBUS input current limited to %d mA\n",
+			 di->max_usb_in_curr.set_max);
+	}
+
 	if (di->usb.charger_connected)
-		ab8500_charger_set_vbus_in_curr(di, di->max_usb_in_curr);
+		ab8500_charger_set_vbus_in_curr(di,
+					di->max_usb_in_curr.usb_type_max);
 }
 
 /**
@@ -2654,8 +2895,13 @@ static irqreturn_t ab8500_charger_vbuschdropend_handler(int irq, void *_di)
 
 	dev_dbg(di->dev, "VBUS charger drop ended\n");
 	di->flags.vbus_drop_end = true;
+
+	/*
+	 * VBUS might have dropped due to bad connection.
+	 * Schedule a new input limit set to the value SW requests.
+	 */
 	queue_delayed_work(di->charger_wq, &di->vbus_drop_end_work,
-			   round_jiffies(30 * HZ));
+			   round_jiffies(VBUS_IN_CURR_LIM_RETRY_SET_TIME * HZ));
 
 	return IRQ_HANDLED;
 }
@@ -2836,6 +3082,7 @@ static int ab8500_charger_usb_get_property(struct power_supply *psy,
 static int ab8500_charger_init_hw_registers(struct ab8500_charger *di)
 {
 	int ret = 0;
+	u8 bup_vch_range = 0, vbup33_vrtcn = 0;
 
 	/* Setup maximum charger current and voltage for ABB cut2.0 */
 	if (!is_ab8500_1p1_or_earlier(di->parent)) {
@@ -2848,9 +3095,14 @@ static int ab8500_charger_init_hw_registers(struct ab8500_charger *di)
 			goto out;
 		}
 
-		ret = abx500_set_register_interruptible(di->dev,
-			AB8500_CHARGER,
-			AB8500_CH_OPT_CRNTLVL_MAX_REG, CH_OP_CUR_LVL_1P6);
+		if (is_ab8540(di->parent))
+			ret = abx500_set_register_interruptible(di->dev,
+				AB8500_CHARGER, AB8500_CH_OPT_CRNTLVL_MAX_REG,
+				CH_OP_CUR_LVL_2P);
+		else
+			ret = abx500_set_register_interruptible(di->dev,
+				AB8500_CHARGER, AB8500_CH_OPT_CRNTLVL_MAX_REG,
+				CH_OP_CUR_LVL_1P6);
 		if (ret) {
 			dev_err(di->dev,
 				"failed to set CH_OPT_CRNTLVL_MAX_REG\n");
@@ -2858,7 +3110,8 @@ static int ab8500_charger_init_hw_registers(struct ab8500_charger *di)
 		}
 	}
 
-	if (is_ab9540_2p0(di->parent) || is_ab8505_2p0(di->parent))
+	if (is_ab9540_2p0(di->parent) || is_ab9540_3p0(di->parent)
+	 || is_ab8505_2p0(di->parent) || is_ab8540(di->parent))
 		ret = abx500_mask_and_set_register_interruptible(di->dev,
 			AB8500_CHARGER,
 			AB8500_USBCH_CTRL2_REG,
@@ -2930,14 +3183,6 @@ static int ab8500_charger_init_hw_registers(struct ab8500_charger *di)
 		goto out;
 	}
 
-	/* Set charger watchdog timeout */
-	ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER,
-		AB8500_CH_WD_TIMER_REG, WD_TIMER);
-	if (ret) {
-		dev_err(di->dev, "failed to set charger watchdog timeout\n");
-		goto out;
-	}
-
 	ret = ab8500_charger_led_en(di, false);
 	if (ret < 0) {
 		dev_err(di->dev, "failed to disable LED\n");
@@ -2945,15 +3190,30 @@ static int ab8500_charger_init_hw_registers(struct ab8500_charger *di)
 	}
 
 	/* Backup battery voltage and current */
+	if (di->bm->bkup_bat_v > BUP_VCH_SEL_3P1V)
+		bup_vch_range = BUP_VCH_RANGE;
+	if (di->bm->bkup_bat_v == BUP_VCH_SEL_3P3V)
+		vbup33_vrtcn = VBUP33_VRTCN;
+
 	ret = abx500_set_register_interruptible(di->dev,
 		AB8500_RTC,
 		AB8500_RTC_BACKUP_CHG_REG,
-		di->bm->bkup_bat_v |
-		di->bm->bkup_bat_i);
+		(di->bm->bkup_bat_v & 0x3) | di->bm->bkup_bat_i);
 	if (ret) {
 		dev_err(di->dev, "failed to setup backup battery charging\n");
 		goto out;
 	}
+	if (is_ab8540(di->parent)) {
+		ret = abx500_set_register_interruptible(di->dev,
+			AB8500_RTC,
+			AB8500_RTC_CTRL1_REG,
+			bup_vch_range | vbup33_vrtcn);
+		if (ret) {
+			dev_err(di->dev,
+				"failed to setup backup battery charging\n");
+			goto out;
+		}
+	}
 
 	/* Enable backup battery charging */
 	abx500_mask_and_set_register_interruptible(di->dev,
@@ -2962,6 +3222,25 @@ static int ab8500_charger_init_hw_registers(struct ab8500_charger *di)
 	if (ret < 0)
 		dev_err(di->dev, "%s mask and set failed\n", __func__);
 
+	if (is_ab8540(di->parent)) {
+		ret = abx500_mask_and_set_register_interruptible(di->dev,
+			AB8500_CHARGER, AB8540_USB_PP_MODE_REG,
+			BUS_VSYS_VOL_SELECT_MASK, BUS_VSYS_VOL_SELECT_3P6V);
+		if (ret) {
+			dev_err(di->dev,
+				"failed to setup usb power path vsys voltage\n");
+			goto out;
+		}
+		ret = abx500_mask_and_set_register_interruptible(di->dev,
+			AB8500_CHARGER, AB8540_USB_PP_CHR_REG,
+			BUS_PP_PRECHG_CURRENT_MASK, 0);
+		if (ret) {
+			dev_err(di->dev,
+				"failed to setup usb power path prechage current\n");
+			goto out;
+		}
+	}
+
 out:
 	return ret;
 }
@@ -3055,11 +3334,8 @@ static int ab8500_charger_resume(struct platform_device *pdev)
 			dev_err(di->dev, "Failed to kick WD!\n");
 
 		/* If not already pending start a new timer */
-		if (!delayed_work_pending(
-			&di->kick_wd_work)) {
-			queue_delayed_work(di->charger_wq, &di->kick_wd_work,
-				round_jiffies(WD_KICK_INTERVAL));
-		}
+		queue_delayed_work(di->charger_wq, &di->kick_wd_work,
+				   round_jiffies(WD_KICK_INTERVAL));
 	}
 
 	/* If we still have a HW failure, schedule a new check */
@@ -3079,12 +3355,9 @@ static int ab8500_charger_suspend(struct platform_device *pdev,
 {
 	struct ab8500_charger *di = platform_get_drvdata(pdev);
 
-	/* Cancel any pending HW failure check */
-	if (delayed_work_pending(&di->check_hw_failure_work))
-		cancel_delayed_work(&di->check_hw_failure_work);
-
-	if (delayed_work_pending(&di->vbus_drop_end_work))
-		cancel_delayed_work(&di->vbus_drop_end_work);
+	/* Cancel any pending jobs */
+	cancel_delayed_work(&di->check_hw_failure_work);
+	cancel_delayed_work(&di->vbus_drop_end_work);
 
 	flush_delayed_work(&di->attach_work);
 	flush_delayed_work(&di->usb_charger_attached_work);
@@ -3107,6 +3380,10 @@ static int ab8500_charger_suspend(struct platform_device *pdev,
 #define ab8500_charger_resume       NULL
 #endif
 
+static struct notifier_block charger_nb = {
+	.notifier_call = ab8500_external_charger_prepare,
+};
+
 static int ab8500_charger_remove(struct platform_device *pdev)
 {
 	struct ab8500_charger *di = platform_get_drvdata(pdev);
@@ -3136,13 +3413,18 @@ static int ab8500_charger_remove(struct platform_device *pdev)
 	/* Delete the work queue */
 	destroy_workqueue(di->charger_wq);
 
+	/* Unregister external charger enable notifier */
+	if (!di->ac_chg.enabled)
+		blocking_notifier_chain_unregister(
+			&charger_notifier_list, &charger_nb);
+
 	flush_scheduled_work();
-	if(di->usb_chg.enabled)
+	if (di->usb_chg.enabled)
 		power_supply_unregister(&di->usb_chg.psy);
-#if !defined(CONFIG_CHARGER_PM2301)
-	if(di->ac_chg.enabled)
+
+	if (di->ac_chg.enabled && !di->ac_chg.external)
 		power_supply_unregister(&di->ac_chg.psy);
-#endif
+
 	platform_set_drvdata(pdev, NULL);
 
 	return 0;
@@ -3206,16 +3488,22 @@ static int ab8500_charger_probe(struct platform_device *pdev)
 	di->ac_chg.psy.num_supplicants = ARRAY_SIZE(supply_interface),
 	/* ux500_charger sub-class */
 	di->ac_chg.ops.enable = &ab8500_charger_ac_en;
+	di->ac_chg.ops.check_enable = &ab8500_charger_ac_check_enable;
 	di->ac_chg.ops.kick_wd = &ab8500_charger_watchdog_kick;
 	di->ac_chg.ops.update_curr = &ab8500_charger_update_charger_current;
 	di->ac_chg.max_out_volt = ab8500_charger_voltage_map[
 		ARRAY_SIZE(ab8500_charger_voltage_map) - 1];
-	di->ac_chg.max_out_curr = ab8500_charger_current_map[
-		ARRAY_SIZE(ab8500_charger_current_map) - 1];
+	di->ac_chg.max_out_curr =
+		di->bm->chg_output_curr[di->bm->n_chg_out_curr - 1];
 	di->ac_chg.wdt_refresh = CHG_WD_INTERVAL;
 	di->ac_chg.enabled = di->bm->ac_enabled;
 	di->ac_chg.external = false;
 
+	/*notifier for external charger enabling*/
+	if (!di->ac_chg.enabled)
+		blocking_notifier_chain_register(
+			&charger_notifier_list, &charger_nb);
+
 	/* USB supply */
 	/* power_supply base class */
 	di->usb_chg.psy.name = "ab8500_usb";
@@ -3227,15 +3515,20 @@ static int ab8500_charger_probe(struct platform_device *pdev)
 	di->usb_chg.psy.num_supplicants = ARRAY_SIZE(supply_interface),
 	/* ux500_charger sub-class */
 	di->usb_chg.ops.enable = &ab8500_charger_usb_en;
+	di->usb_chg.ops.check_enable = &ab8500_charger_usb_check_enable;
 	di->usb_chg.ops.kick_wd = &ab8500_charger_watchdog_kick;
 	di->usb_chg.ops.update_curr = &ab8500_charger_update_charger_current;
+	di->usb_chg.ops.pp_enable = &ab8540_charger_power_path_enable;
+	di->usb_chg.ops.pre_chg_enable = &ab8540_charger_usb_pre_chg_enable;
 	di->usb_chg.max_out_volt = ab8500_charger_voltage_map[
 		ARRAY_SIZE(ab8500_charger_voltage_map) - 1];
-	di->usb_chg.max_out_curr = ab8500_charger_current_map[
-		ARRAY_SIZE(ab8500_charger_current_map) - 1];
+	di->usb_chg.max_out_curr =
+		di->bm->chg_output_curr[di->bm->n_chg_out_curr - 1];
 	di->usb_chg.wdt_refresh = CHG_WD_INTERVAL;
 	di->usb_chg.enabled = di->bm->usb_enabled;
 	di->usb_chg.external = false;
+	di->usb_chg.power_path = di->bm->usb_power_path;
+	di->usb_state.usb_current = -1;
 
 	/* Create a work queue for the charger */
 	di->charger_wq =
@@ -3316,7 +3609,7 @@ static int ab8500_charger_probe(struct platform_device *pdev)
 	}
 
 	/* Register AC charger class */
-	if(di->ac_chg.enabled) {
+	if (di->ac_chg.enabled) {
 		ret = power_supply_register(di->dev, &di->ac_chg.psy);
 		if (ret) {
 			dev_err(di->dev, "failed to register AC charger\n");
@@ -3325,7 +3618,7 @@ static int ab8500_charger_probe(struct platform_device *pdev)
 	}
 
 	/* Register USB charger class */
-	if(di->usb_chg.enabled) {
+	if (di->usb_chg.enabled) {
 		ret = power_supply_register(di->dev, &di->usb_chg.psy);
 		if (ret) {
 			dev_err(di->dev, "failed to register USB charger\n");
@@ -3385,14 +3678,16 @@ static int ab8500_charger_probe(struct platform_device *pdev)
 	ch_stat = ab8500_charger_detect_chargers(di, false);
 
 	if ((ch_stat & AC_PW_CONN) == AC_PW_CONN) {
-		queue_delayed_work(di->charger_wq,
-				   &di->ac_charger_attached_work,
-				   HZ);
+		if (is_ab8500(di->parent))
+			queue_delayed_work(di->charger_wq,
+					   &di->ac_charger_attached_work,
+					   HZ);
 	}
 	if ((ch_stat & USB_PW_CONN) == USB_PW_CONN) {
-		queue_delayed_work(di->charger_wq,
-				   &di->usb_charger_attached_work,
-				   HZ);
+		if (is_ab8500(di->parent))
+			queue_delayed_work(di->charger_wq,
+					   &di->usb_charger_attached_work,
+					   HZ);
 	}
 
 	mutex_unlock(&di->charger_attached_mutex);
@@ -3410,10 +3705,10 @@ free_irq:
 put_usb_phy:
 	usb_put_phy(di->usb_phy);
 free_usb:
-	if(di->usb_chg.enabled)
+	if (di->usb_chg.enabled)
 		power_supply_unregister(&di->usb_chg.psy);
 free_ac:
-	if(di->ac_chg.enabled)
+	if (di->ac_chg.enabled)
 		power_supply_unregister(&di->ac_chg.psy);
 free_charger_wq:
 	destroy_workqueue(di->charger_wq);
diff --git a/drivers/power/ab8500_fg.c b/drivers/power/ab8500_fg.c
index 25dae4c..1601d27 100644
--- a/drivers/power/ab8500_fg.c
+++ b/drivers/power/ab8500_fg.c
@@ -36,7 +36,7 @@
 
 #define MILLI_TO_MICRO			1000
 #define FG_LSB_IN_MA			1627
-#define QLSB_NANO_AMP_HOURS_X10		1129
+#define QLSB_NANO_AMP_HOURS_X10		1071
 #define INS_CURR_TIMEOUT		(3 * HZ)
 
 #define SEC_TO_SAMPLE(S)		(S * 4)
@@ -672,11 +672,11 @@ int ab8500_fg_inst_curr_finalize(struct ab8500_fg *di, int *res)
 	/*
 	 * Convert to unit value in mA
 	 * Full scale input voltage is
-	 * 66.660mV => LSB = 66.660mV/(4096*res) = 1.627mA
+	 * 63.160mV => LSB = 63.160mV/(4096*res) = 1.542mA
 	 * Given a 250ms conversion cycle time the LSB corresponds
-	 * to 112.9 nAh. Convert to current by dividing by the conversion
+	 * to 107.1 nAh. Convert to current by dividing by the conversion
 	 * time in hours (250ms = 1 / (3600 * 4)h)
-	 * 112.9nAh assumes 10mOhm, but fg_res is in 0.1mOhm
+	 * 107.1nAh assumes 10mOhm, but fg_res is in 0.1mOhm
 	 */
 	val = (val * QLSB_NANO_AMP_HOURS_X10 * 36 * 4) /
 		(1000 * di->bm->fg_res);
@@ -1354,9 +1354,6 @@ static void ab8500_fg_check_capacity_limits(struct ab8500_fg *di, bool init)
 			 * algorithm says.
 			 */
 			di->bat_cap.prev_percent = 1;
-			di->bat_cap.permille = 1;
-			di->bat_cap.prev_mah = 1;
-			di->bat_cap.mah = 1;
 			percent = 1;
 
 			changed = true;
@@ -1683,7 +1680,6 @@ static void ab8500_fg_algorithm_discharging(struct ab8500_fg *di)
 		break;
 
 	case AB8500_FG_DISCHARGE_WAKEUP:
-		ab8500_fg_coulomb_counter(di, true);
 		ab8500_fg_calc_cap_discharge_voltage(di, true);
 
 		di->fg_samples = SEC_TO_SAMPLE(
@@ -1768,9 +1764,10 @@ static void ab8500_fg_algorithm(struct ab8500_fg *di)
 			ab8500_fg_algorithm_discharging(di);
 	}
 
-	dev_dbg(di->dev, "[FG_DATA] %d %d %d %d %d %d %d %d %d "
+	dev_dbg(di->dev, "[FG_DATA] %d %d %d %d %d %d %d %d %d %d "
 		"%d %d %d %d %d %d %d\n",
 		di->bat_cap.max_mah_design,
+		di->bat_cap.max_mah,
 		di->bat_cap.mah,
 		di->bat_cap.permille,
 		di->bat_cap.level,
@@ -1982,7 +1979,7 @@ static void ab8500_fg_instant_work(struct work_struct *work)
 }
 
 /**
- * ab8500_fg_cc_data_end_handler() - isr to get battery avg current.
+ * ab8500_fg_cc_data_end_handler() - end of data conversion isr.
  * @irq:       interrupt number
  * @_di:       pointer to the ab8500_fg structure
  *
@@ -2002,7 +1999,7 @@ static irqreturn_t ab8500_fg_cc_data_end_handler(int irq, void *_di)
 }
 
 /**
- * ab8500_fg_cc_convend_handler() - isr to get battery avg current.
+ * ab8500_fg_cc_int_calib_handler () - end of calibration isr.
  * @irq:       interrupt number
  * @_di:       pointer to the ab8500_fg structure
  *
@@ -2153,9 +2150,7 @@ static int ab8500_fg_get_property(struct power_supply *psy,
 			val->intval = di->bat_cap.prev_mah;
 		break;
 	case POWER_SUPPLY_PROP_CAPACITY:
-		if (di->bm->capacity_scaling)
-			val->intval = di->bat_cap.cap_scale.scaled_cap;
-		else if (di->flags.batt_unknown && !di->bm->chg_unknown_bat &&
+		if (di->flags.batt_unknown && !di->bm->chg_unknown_bat &&
 				di->flags.batt_id_received)
 			val->intval = 100;
 		else
@@ -2344,6 +2339,50 @@ static int ab8500_fg_init_hw_registers(struct ab8500_fg *di)
 		dev_err(di->dev, "BattOk init write failed.\n");
 		goto out;
 	}
+
+	if (((is_ab8505(di->parent) || is_ab9540(di->parent)) &&
+			abx500_get_chip_id(di->dev) >= AB8500_CUT2P0)
+			|| is_ab8540(di->parent)) {
+		ret = abx500_set_register_interruptible(di->dev, AB8500_RTC,
+			AB8505_RTC_PCUT_MAX_TIME_REG, di->bm->fg_params->pcut_max_time);
+
+		if (ret) {
+			dev_err(di->dev, "%s write failed AB8505_RTC_PCUT_MAX_TIME_REG\n", __func__);
+			goto out;
+		};
+
+		ret = abx500_set_register_interruptible(di->dev, AB8500_RTC,
+			AB8505_RTC_PCUT_FLAG_TIME_REG, di->bm->fg_params->pcut_flag_time);
+
+		if (ret) {
+			dev_err(di->dev, "%s write failed AB8505_RTC_PCUT_FLAG_TIME_REG\n", __func__);
+			goto out;
+		};
+
+		ret = abx500_set_register_interruptible(di->dev, AB8500_RTC,
+			AB8505_RTC_PCUT_RESTART_REG, di->bm->fg_params->pcut_max_restart);
+
+		if (ret) {
+			dev_err(di->dev, "%s write failed AB8505_RTC_PCUT_RESTART_REG\n", __func__);
+			goto out;
+		};
+
+		ret = abx500_set_register_interruptible(di->dev, AB8500_RTC,
+			AB8505_RTC_PCUT_DEBOUNCE_REG, di->bm->fg_params->pcut_debounce_time);
+
+		if (ret) {
+			dev_err(di->dev, "%s write failed AB8505_RTC_PCUT_DEBOUNCE_REG\n", __func__);
+			goto out;
+		};
+
+		ret = abx500_set_register_interruptible(di->dev, AB8500_RTC,
+			AB8505_RTC_PCUT_CTL_STATUS_REG, di->bm->fg_params->pcut_enable);
+
+		if (ret) {
+			dev_err(di->dev, "%s write failed AB8505_RTC_PCUT_CTL_STATUS_REG\n", __func__);
+			goto out;
+		};
+	}
 out:
 	return ret;
 }
@@ -2546,6 +2585,428 @@ static int ab8500_fg_sysfs_init(struct ab8500_fg *di)
 
 	return ret;
 }
+
+static ssize_t ab8505_powercut_flagtime_read(struct device *dev,
+			     struct device_attribute *attr,
+			     char *buf)
+{
+	int ret;
+	u8 reg_value;
+	struct power_supply *psy = dev_get_drvdata(dev);
+	struct ab8500_fg *di;
+
+	di = to_ab8500_fg_device_info(psy);
+
+	ret = abx500_get_register_interruptible(di->dev, AB8500_RTC,
+		AB8505_RTC_PCUT_FLAG_TIME_REG, &reg_value);
+
+	if (ret < 0) {
+		dev_err(dev, "Failed to read AB8505_RTC_PCUT_FLAG_TIME_REG\n");
+		goto fail;
+	}
+
+	return scnprintf(buf, PAGE_SIZE, "%d\n", (reg_value & 0x7F));
+
+fail:
+	return ret;
+}
+
+static ssize_t ab8505_powercut_flagtime_write(struct device *dev,
+				  struct device_attribute *attr,
+				  const char *buf, size_t count)
+{
+	int ret;
+	long unsigned reg_value;
+	struct power_supply *psy = dev_get_drvdata(dev);
+	struct ab8500_fg *di;
+
+	di = to_ab8500_fg_device_info(psy);
+
+	reg_value = simple_strtoul(buf, NULL, 10);
+
+	if (reg_value > 0x7F) {
+		dev_err(dev, "Incorrect parameter, echo 0 (1.98s) - 127 (15.625ms) for flagtime\n");
+		goto fail;
+	}
+
+	ret = abx500_set_register_interruptible(di->dev, AB8500_RTC,
+		AB8505_RTC_PCUT_FLAG_TIME_REG, (u8)reg_value);
+
+	if (ret < 0)
+		dev_err(dev, "Failed to set AB8505_RTC_PCUT_FLAG_TIME_REG\n");
+
+fail:
+	return count;
+}
+
+static ssize_t ab8505_powercut_maxtime_read(struct device *dev,
+			     struct device_attribute *attr,
+			     char *buf)
+{
+	int ret;
+	u8 reg_value;
+	struct power_supply *psy = dev_get_drvdata(dev);
+	struct ab8500_fg *di;
+
+	di = to_ab8500_fg_device_info(psy);
+
+	ret = abx500_get_register_interruptible(di->dev, AB8500_RTC,
+		AB8505_RTC_PCUT_MAX_TIME_REG, &reg_value);
+
+	if (ret < 0) {
+		dev_err(dev, "Failed to read AB8505_RTC_PCUT_MAX_TIME_REG\n");
+		goto fail;
+	}
+
+	return scnprintf(buf, PAGE_SIZE, "%d\n", (reg_value & 0x7F));
+
+fail:
+	return ret;
+
+}
+
+static ssize_t ab8505_powercut_maxtime_write(struct device *dev,
+				  struct device_attribute *attr,
+				  const char *buf, size_t count)
+{
+	int ret;
+	int reg_value;
+	struct power_supply *psy = dev_get_drvdata(dev);
+	struct ab8500_fg *di;
+
+	di = to_ab8500_fg_device_info(psy);
+
+	reg_value = simple_strtoul(buf, NULL, 10);
+	if (reg_value > 0x7F) {
+		dev_err(dev, "Incorrect parameter, echo 0 (0.0s) - 127 (1.98s) for maxtime\n");
+		goto fail;
+	}
+
+	ret = abx500_set_register_interruptible(di->dev, AB8500_RTC,
+		AB8505_RTC_PCUT_MAX_TIME_REG, (u8)reg_value);
+
+	if (ret < 0)
+		dev_err(dev, "Failed to set AB8505_RTC_PCUT_MAX_TIME_REG\n");
+
+fail:
+	return count;
+}
+
+static ssize_t ab8505_powercut_restart_read(struct device *dev,
+			     struct device_attribute *attr,
+			     char *buf)
+{
+	int ret;
+	u8 reg_value;
+	struct power_supply *psy = dev_get_drvdata(dev);
+	struct ab8500_fg *di;
+
+	di = to_ab8500_fg_device_info(psy);
+
+	ret = abx500_get_register_interruptible(di->dev, AB8500_RTC,
+		AB8505_RTC_PCUT_RESTART_REG, &reg_value);
+
+	if (ret < 0) {
+		dev_err(dev, "Failed to read AB8505_RTC_PCUT_RESTART_REG\n");
+		goto fail;
+	}
+
+	return scnprintf(buf, PAGE_SIZE, "%d\n", (reg_value & 0xF));
+
+fail:
+	return ret;
+}
+
+static ssize_t ab8505_powercut_restart_write(struct device *dev,
+					     struct device_attribute *attr,
+					     const char *buf, size_t count)
+{
+	int ret;
+	int reg_value;
+	struct power_supply *psy = dev_get_drvdata(dev);
+	struct ab8500_fg *di;
+
+	di = to_ab8500_fg_device_info(psy);
+
+	reg_value = simple_strtoul(buf, NULL, 10);
+	if (reg_value > 0xF) {
+		dev_err(dev, "Incorrect parameter, echo 0 - 15 for number of restart\n");
+		goto fail;
+	}
+
+	ret = abx500_set_register_interruptible(di->dev, AB8500_RTC,
+						AB8505_RTC_PCUT_RESTART_REG, (u8)reg_value);
+
+	if (ret < 0)
+		dev_err(dev, "Failed to set AB8505_RTC_PCUT_RESTART_REG\n");
+
+fail:
+	return count;
+
+}
+
+static ssize_t ab8505_powercut_timer_read(struct device *dev,
+					  struct device_attribute *attr,
+					  char *buf)
+{
+	int ret;
+	u8 reg_value;
+	struct power_supply *psy = dev_get_drvdata(dev);
+	struct ab8500_fg *di;
+
+	di = to_ab8500_fg_device_info(psy);
+
+	ret = abx500_get_register_interruptible(di->dev, AB8500_RTC,
+						AB8505_RTC_PCUT_TIME_REG, &reg_value);
+
+	if (ret < 0) {
+		dev_err(dev, "Failed to read AB8505_RTC_PCUT_TIME_REG\n");
+		goto fail;
+	}
+
+	return scnprintf(buf, PAGE_SIZE, "%d\n", (reg_value & 0x7F));
+
+fail:
+	return ret;
+}
+
+static ssize_t ab8505_powercut_restart_counter_read(struct device *dev,
+						    struct device_attribute *attr,
+						    char *buf)
+{
+	int ret;
+	u8 reg_value;
+	struct power_supply *psy = dev_get_drvdata(dev);
+	struct ab8500_fg *di;
+
+	di = to_ab8500_fg_device_info(psy);
+
+	ret = abx500_get_register_interruptible(di->dev, AB8500_RTC,
+						AB8505_RTC_PCUT_RESTART_REG, &reg_value);
+
+	if (ret < 0) {
+		dev_err(dev, "Failed to read AB8505_RTC_PCUT_RESTART_REG\n");
+		goto fail;
+	}
+
+	return scnprintf(buf, PAGE_SIZE, "%d\n", (reg_value & 0xF0) >> 4);
+
+fail:
+	return ret;
+}
+
+static ssize_t ab8505_powercut_read(struct device *dev,
+				    struct device_attribute *attr,
+				    char *buf)
+{
+	int ret;
+	u8 reg_value;
+	struct power_supply *psy = dev_get_drvdata(dev);
+	struct ab8500_fg *di;
+
+	di = to_ab8500_fg_device_info(psy);
+
+	ret = abx500_get_register_interruptible(di->dev, AB8500_RTC,
+						AB8505_RTC_PCUT_CTL_STATUS_REG, &reg_value);
+
+	if (ret < 0)
+		goto fail;
+
+	return scnprintf(buf, PAGE_SIZE, "%d\n", (reg_value & 0x1));
+
+fail:
+	return ret;
+}
+
+static ssize_t ab8505_powercut_write(struct device *dev,
+				     struct device_attribute *attr,
+				     const char *buf, size_t count)
+{
+	int ret;
+	int reg_value;
+	struct power_supply *psy = dev_get_drvdata(dev);
+	struct ab8500_fg *di;
+
+	di = to_ab8500_fg_device_info(psy);
+
+	reg_value = simple_strtoul(buf, NULL, 10);
+	if (reg_value > 0x1) {
+		dev_err(dev, "Incorrect parameter, echo 0/1 to disable/enable Pcut feature\n");
+		goto fail;
+	}
+
+	ret = abx500_set_register_interruptible(di->dev, AB8500_RTC,
+						AB8505_RTC_PCUT_CTL_STATUS_REG, (u8)reg_value);
+
+	if (ret < 0)
+		dev_err(dev, "Failed to set AB8505_RTC_PCUT_CTL_STATUS_REG\n");
+
+fail:
+	return count;
+}
+
+static ssize_t ab8505_powercut_flag_read(struct device *dev,
+					 struct device_attribute *attr,
+					 char *buf)
+{
+
+	int ret;
+	u8 reg_value;
+	struct power_supply *psy = dev_get_drvdata(dev);
+	struct ab8500_fg *di;
+
+	di = to_ab8500_fg_device_info(psy);
+
+	ret = abx500_get_register_interruptible(di->dev, AB8500_RTC,
+						AB8505_RTC_PCUT_CTL_STATUS_REG,  &reg_value);
+
+	if (ret < 0) {
+		dev_err(dev, "Failed to read AB8505_RTC_PCUT_CTL_STATUS_REG\n");
+		goto fail;
+	}
+
+	return scnprintf(buf, PAGE_SIZE, "%d\n", ((reg_value & 0x10) >> 4));
+
+fail:
+	return ret;
+}
+
+static ssize_t ab8505_powercut_debounce_read(struct device *dev,
+					     struct device_attribute *attr,
+					     char *buf)
+{
+	int ret;
+	u8 reg_value;
+	struct power_supply *psy = dev_get_drvdata(dev);
+	struct ab8500_fg *di;
+
+	di = to_ab8500_fg_device_info(psy);
+
+	ret = abx500_get_register_interruptible(di->dev, AB8500_RTC,
+						AB8505_RTC_PCUT_DEBOUNCE_REG,  &reg_value);
+
+	if (ret < 0) {
+		dev_err(dev, "Failed to read AB8505_RTC_PCUT_DEBOUNCE_REG\n");
+		goto fail;
+	}
+
+	return scnprintf(buf, PAGE_SIZE, "%d\n", (reg_value & 0x7));
+
+fail:
+	return ret;
+}
+
+static ssize_t ab8505_powercut_debounce_write(struct device *dev,
+					      struct device_attribute *attr,
+					      const char *buf, size_t count)
+{
+	int ret;
+	int reg_value;
+	struct power_supply *psy = dev_get_drvdata(dev);
+	struct ab8500_fg *di;
+
+	di = to_ab8500_fg_device_info(psy);
+
+	reg_value = simple_strtoul(buf, NULL, 10);
+	if (reg_value > 0x7) {
+		dev_err(dev, "Incorrect parameter, echo 0 to 7 for debounce setting\n");
+		goto fail;
+	}
+
+	ret = abx500_set_register_interruptible(di->dev, AB8500_RTC,
+						AB8505_RTC_PCUT_DEBOUNCE_REG, (u8)reg_value);
+
+	if (ret < 0)
+		dev_err(dev, "Failed to set AB8505_RTC_PCUT_DEBOUNCE_REG\n");
+
+fail:
+	return count;
+}
+
+static ssize_t ab8505_powercut_enable_status_read(struct device *dev,
+						  struct device_attribute *attr,
+						  char *buf)
+{
+	int ret;
+	u8 reg_value;
+	struct power_supply *psy = dev_get_drvdata(dev);
+	struct ab8500_fg *di;
+
+	di = to_ab8500_fg_device_info(psy);
+
+	ret = abx500_get_register_interruptible(di->dev, AB8500_RTC,
+						AB8505_RTC_PCUT_CTL_STATUS_REG, &reg_value);
+
+	if (ret < 0) {
+		dev_err(dev, "Failed to read AB8505_RTC_PCUT_CTL_STATUS_REG\n");
+		goto fail;
+	}
+
+	return scnprintf(buf, PAGE_SIZE, "%d\n", ((reg_value & 0x20) >> 5));
+
+fail:
+	return ret;
+}
+
+static struct device_attribute ab8505_fg_sysfs_psy_attrs[] = {
+	__ATTR(powercut_flagtime, (S_IRUGO | S_IWUSR | S_IWGRP),
+		ab8505_powercut_flagtime_read, ab8505_powercut_flagtime_write),
+	__ATTR(powercut_maxtime, (S_IRUGO | S_IWUSR | S_IWGRP),
+		ab8505_powercut_maxtime_read, ab8505_powercut_maxtime_write),
+	__ATTR(powercut_restart_max, (S_IRUGO | S_IWUSR | S_IWGRP),
+		ab8505_powercut_restart_read, ab8505_powercut_restart_write),
+	__ATTR(powercut_timer, S_IRUGO, ab8505_powercut_timer_read, NULL),
+	__ATTR(powercut_restart_counter, S_IRUGO,
+		ab8505_powercut_restart_counter_read, NULL),
+	__ATTR(powercut_enable, (S_IRUGO | S_IWUSR | S_IWGRP),
+		ab8505_powercut_read, ab8505_powercut_write),
+	__ATTR(powercut_flag, S_IRUGO, ab8505_powercut_flag_read, NULL),
+	__ATTR(powercut_debounce_time, (S_IRUGO | S_IWUSR | S_IWGRP),
+		ab8505_powercut_debounce_read, ab8505_powercut_debounce_write),
+	__ATTR(powercut_enable_status, S_IRUGO,
+		ab8505_powercut_enable_status_read, NULL),
+};
+
+static int ab8500_fg_sysfs_psy_create_attrs(struct device *dev)
+{
+	unsigned int i, j;
+	struct power_supply *psy = dev_get_drvdata(dev);
+	struct ab8500_fg *di;
+
+	di = to_ab8500_fg_device_info(psy);
+
+	if (((is_ab8505(di->parent) || is_ab9540(di->parent)) &&
+	     abx500_get_chip_id(dev->parent) >= AB8500_CUT2P0)
+	    || is_ab8540(di->parent)) {
+		for (j = 0; j < ARRAY_SIZE(ab8505_fg_sysfs_psy_attrs); j++)
+			if (device_create_file(dev, &ab8505_fg_sysfs_psy_attrs[j]))
+				goto sysfs_psy_create_attrs_failed_ab8505;
+	}
+	return 0;
+sysfs_psy_create_attrs_failed_ab8505:
+	dev_err(dev, "Failed creating sysfs psy attrs for ab8505.\n");
+	while (j--)
+		device_remove_file(dev, &ab8505_fg_sysfs_psy_attrs[i]);
+
+	return -EIO;
+}
+
+static void ab8500_fg_sysfs_psy_remove_attrs(struct device *dev)
+{
+	unsigned int i;
+	struct power_supply *psy = dev_get_drvdata(dev);
+	struct ab8500_fg *di;
+
+	di = to_ab8500_fg_device_info(psy);
+
+	if (((is_ab8505(di->parent) || is_ab9540(di->parent)) &&
+	     abx500_get_chip_id(dev->parent) >= AB8500_CUT2P0)
+	    || is_ab8540(di->parent)) {
+		for (i = 0; i < ARRAY_SIZE(ab8505_fg_sysfs_psy_attrs); i++)
+			(void)device_remove_file(dev, &ab8505_fg_sysfs_psy_attrs[i]);
+	}
+}
+
 /* Exposure to the sysfs interface <<END>> */
 
 #if defined(CONFIG_PM)
@@ -2607,6 +3068,7 @@ static int ab8500_fg_remove(struct platform_device *pdev)
 	ab8500_fg_sysfs_exit(di);
 
 	flush_scheduled_work();
+	ab8500_fg_sysfs_psy_remove_attrs(di->fg_psy.dev);
 	power_supply_unregister(&di->fg_psy);
 	platform_set_drvdata(pdev, NULL);
 	return ret;
@@ -2772,6 +3234,13 @@ static int ab8500_fg_probe(struct platform_device *pdev)
 		goto free_irq;
 	}
 
+	ret = ab8500_fg_sysfs_psy_create_attrs(di->fg_psy.dev);
+	if (ret) {
+		dev_err(di->dev, "failed to create FG psy\n");
+		ab8500_fg_sysfs_exit(di);
+		goto free_irq;
+	}
+
 	/* Calibrate the fg first time */
 	di->flags.calibrate = true;
 	di->calib_state = AB8500_FG_CALIB_INIT;
diff --git a/drivers/power/abx500_chargalg.c b/drivers/power/abx500_chargalg.c
index f043c08..9863e42 100644
--- a/drivers/power/abx500_chargalg.c
+++ b/drivers/power/abx500_chargalg.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) ST-Ericsson SA 2012
+ * Copyright (c) 2012 Sony Mobile Communications AB
  *
  * Charging algorithm driver for abx500 variants
  *
@@ -8,11 +9,13 @@
  *	Johan Palsson <johan.palsson@stericsson.com>
  *	Karl Komierowski <karl.komierowski@stericsson.com>
  *	Arun R Murthy <arun.murthy@stericsson.com>
+ *	Author: Imre Sunyi <imre.sunyi@sonymobile.com>
  */
 
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/device.h>
+#include <linux/hrtimer.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
@@ -24,8 +27,10 @@
 #include <linux/of.h>
 #include <linux/mfd/core.h>
 #include <linux/mfd/abx500.h>
+#include <linux/mfd/abx500/ab8500.h>
 #include <linux/mfd/abx500/ux500_chargalg.h>
 #include <linux/mfd/abx500/ab8500-bm.h>
+#include <linux/notifier.h>
 
 /* Watchdog kick interval */
 #define CHG_WD_INTERVAL			(6 * HZ)
@@ -33,6 +38,18 @@
 /* End-of-charge criteria counter */
 #define EOC_COND_CNT			10
 
+/* One hour expressed in seconds */
+#define ONE_HOUR_IN_SECONDS            3600
+
+/* Five minutes expressed in seconds */
+#define FIVE_MINUTES_IN_SECONDS        300
+
+/* Plus margin for the low battery threshold */
+#define BAT_PLUS_MARGIN                (100)
+
+#define CHARGALG_CURR_STEP_LOW		0
+#define CHARGALG_CURR_STEP_HIGH	100
+
 #define to_abx500_chargalg_device_info(x) container_of((x), \
 	struct abx500_chargalg, chargalg_psy);
 
@@ -66,6 +83,11 @@ struct abx500_chargalg_suspension_status {
 	bool usb_suspended;
 };
 
+struct abx500_chargalg_current_step_status {
+	bool curr_step_change;
+	int curr_step;
+};
+
 struct abx500_chargalg_battery_data {
 	int temp;
 	int volt;
@@ -82,6 +104,7 @@ enum abx500_chargalg_states {
 	STATE_HW_TEMP_PROTECT_INIT,
 	STATE_HW_TEMP_PROTECT,
 	STATE_NORMAL_INIT,
+	STATE_USB_PP_PRE_CHARGE,
 	STATE_NORMAL,
 	STATE_WAIT_FOR_RECHARGE_INIT,
 	STATE_WAIT_FOR_RECHARGE,
@@ -113,6 +136,7 @@ static const char *states[] = {
 	"HW_TEMP_PROTECT_INIT",
 	"HW_TEMP_PROTECT",
 	"NORMAL_INIT",
+	"USB_PP_PRE_CHARGE",
 	"NORMAL",
 	"WAIT_FOR_RECHARGE_INIT",
 	"WAIT_FOR_RECHARGE",
@@ -204,6 +228,8 @@ enum maxim_ret {
  * @batt_data:		data of the battery
  * @susp_status:	current charger suspension status
  * @bm:           	Platform specific battery management information
+ * @curr_status:	Current step status for over-current protection
+ * @parent:		pointer to the struct abx500
  * @chargalg_psy:	structure that holds the battery properties exposed by
  *			the charging algorithm
  * @events:		structure for information about events triggered
@@ -227,6 +253,8 @@ struct abx500_chargalg {
 	struct abx500_chargalg_charger_info chg_info;
 	struct abx500_chargalg_battery_data batt_data;
 	struct abx500_chargalg_suspension_status susp_status;
+	struct ab8500 *parent;
+	struct abx500_chargalg_current_step_status curr_status;
 	struct abx500_bm_data *bm;
 	struct power_supply chargalg_psy;
 	struct ux500_charger *ac_chg;
@@ -236,51 +264,69 @@ struct abx500_chargalg {
 	struct delayed_work chargalg_periodic_work;
 	struct delayed_work chargalg_wd_work;
 	struct work_struct chargalg_work;
-	struct timer_list safety_timer;
-	struct timer_list maintenance_timer;
+	struct hrtimer safety_timer;
+	struct hrtimer maintenance_timer;
 	struct kobject chargalg_kobject;
 };
 
+/*External charger prepare notifier*/
+BLOCKING_NOTIFIER_HEAD(charger_notifier_list);
+
 /* Main battery properties */
 static enum power_supply_property abx500_chargalg_props[] = {
 	POWER_SUPPLY_PROP_STATUS,
 	POWER_SUPPLY_PROP_HEALTH,
 };
 
+struct abx500_chargalg_sysfs_entry {
+	struct attribute attr;
+	ssize_t (*show)(struct abx500_chargalg *, char *);
+	ssize_t (*store)(struct abx500_chargalg *, const char *, size_t);
+};
+
 /**
  * abx500_chargalg_safety_timer_expired() - Expiration of the safety timer
- * @data:	pointer to the abx500_chargalg structure
+ * @timer:     pointer to the hrtimer structure
  *
  * This function gets called when the safety timer for the charger
  * expires
  */
-static void abx500_chargalg_safety_timer_expired(unsigned long data)
+static enum hrtimer_restart
+abx500_chargalg_safety_timer_expired(struct hrtimer *timer)
 {
-	struct abx500_chargalg *di = (struct abx500_chargalg *) data;
+	struct abx500_chargalg *di = container_of(timer, struct abx500_chargalg,
+						  safety_timer);
 	dev_err(di->dev, "Safety timer expired\n");
 	di->events.safety_timer_expired = true;
 
 	/* Trigger execution of the algorithm instantly */
 	queue_work(di->chargalg_wq, &di->chargalg_work);
+
+	return HRTIMER_NORESTART;
 }
 
 /**
  * abx500_chargalg_maintenance_timer_expired() - Expiration of
  * the maintenance timer
- * @i:		pointer to the abx500_chargalg structure
+ * @timer:     pointer to the timer structure
  *
  * This function gets called when the maintenence timer
  * expires
  */
-static void abx500_chargalg_maintenance_timer_expired(unsigned long data)
+static enum hrtimer_restart
+abx500_chargalg_maintenance_timer_expired(struct hrtimer *timer)
 {
 
-	struct abx500_chargalg *di = (struct abx500_chargalg *) data;
+	struct abx500_chargalg *di = container_of(timer, struct abx500_chargalg,
+						  maintenance_timer);
+
 	dev_dbg(di->dev, "Maintenance timer expired\n");
 	di->events.maintenance_timer_expired = true;
 
 	/* Trigger execution of the algorithm instantly */
 	queue_work(di->chargalg_wq, &di->chargalg_work);
+
+	return HRTIMER_NORESTART;
 }
 
 /**
@@ -303,6 +349,30 @@ static void abx500_chargalg_state_to(struct abx500_chargalg *di,
 	di->charge_state = state;
 }
 
+static int abx500_chargalg_check_charger_enable(struct abx500_chargalg *di)
+{
+	switch (di->charge_state) {
+	case STATE_NORMAL:
+	case STATE_MAINTENANCE_A:
+	case STATE_MAINTENANCE_B:
+		break;
+	default:
+		return 0;
+	}
+
+	if (di->chg_info.charger_type & USB_CHG) {
+		return di->usb_chg->ops.check_enable(di->usb_chg,
+                         di->bm->bat_type[di->bm->batt_id].normal_vol_lvl,
+                         di->bm->bat_type[di->bm->batt_id].normal_cur_lvl);
+	} else if ((di->chg_info.charger_type & AC_CHG) &&
+		   !(di->ac_chg->external)) {
+		return di->ac_chg->ops.check_enable(di->ac_chg,
+                         di->bm->bat_type[di->bm->batt_id].normal_vol_lvl,
+                         di->bm->bat_type[di->bm->batt_id].normal_cur_lvl);
+	}
+	return 0;
+}
+
 /**
  * abx500_chargalg_check_charger_connection() - Check charger connection change
  * @di:		pointer to the abx500_chargalg structure
@@ -348,6 +418,22 @@ static int abx500_chargalg_check_charger_connection(struct abx500_chargalg *di)
 }
 
 /**
+ * abx500_chargalg_check_current_step_status() - Check charging current
+ * step status.
+ * @di:		pointer to the abx500_chargalg structure
+ *
+ * This function will check if there is a change in the charging current step
+ * and change charge state accordingly.
+ */
+static void abx500_chargalg_check_current_step_status
+	(struct abx500_chargalg *di)
+{
+	if (di->curr_status.curr_step_change)
+		abx500_chargalg_state_to(di, STATE_NORMAL_INIT);
+	di->curr_status.curr_step_change = false;
+}
+
+/**
  * abx500_chargalg_start_safety_timer() - Start charging safety timer
  * @di:		pointer to the abx500_chargalg structure
  *
@@ -356,19 +442,16 @@ static int abx500_chargalg_check_charger_connection(struct abx500_chargalg *di)
  */
 static void abx500_chargalg_start_safety_timer(struct abx500_chargalg *di)
 {
-	unsigned long timer_expiration = 0;
+	/* Charger-dependent expiration time in hours*/
+	int timer_expiration = 0;
 
 	switch (di->chg_info.charger_type) {
 	case AC_CHG:
-		timer_expiration =
-		round_jiffies(jiffies +
-			(di->bm->main_safety_tmr_h * 3600 * HZ));
+		timer_expiration = di->bm->main_safety_tmr_h;
 		break;
 
 	case USB_CHG:
-		timer_expiration =
-		round_jiffies(jiffies +
-			(di->bm->usb_safety_tmr_h * 3600 * HZ));
+		timer_expiration = di->bm->usb_safety_tmr_h;
 		break;
 
 	default:
@@ -377,11 +460,10 @@ static void abx500_chargalg_start_safety_timer(struct abx500_chargalg *di)
 	}
 
 	di->events.safety_timer_expired = false;
-	di->safety_timer.expires = timer_expiration;
-	if (!timer_pending(&di->safety_timer))
-		add_timer(&di->safety_timer);
-	else
-		mod_timer(&di->safety_timer, timer_expiration);
+	hrtimer_set_expires_range(&di->safety_timer,
+		ktime_set(timer_expiration * ONE_HOUR_IN_SECONDS, 0),
+		ktime_set(FIVE_MINUTES_IN_SECONDS, 0));
+	hrtimer_start_expires(&di->safety_timer, HRTIMER_MODE_REL);
 }
 
 /**
@@ -392,8 +474,8 @@ static void abx500_chargalg_start_safety_timer(struct abx500_chargalg *di)
  */
 static void abx500_chargalg_stop_safety_timer(struct abx500_chargalg *di)
 {
-	di->events.safety_timer_expired = false;
-	del_timer(&di->safety_timer);
+	if (hrtimer_try_to_cancel(&di->safety_timer) >= 0)
+		di->events.safety_timer_expired = false;
 }
 
 /**
@@ -408,17 +490,11 @@ static void abx500_chargalg_stop_safety_timer(struct abx500_chargalg *di)
 static void abx500_chargalg_start_maintenance_timer(struct abx500_chargalg *di,
 	int duration)
 {
-	unsigned long timer_expiration;
-
-	/* Convert from hours to jiffies */
-	timer_expiration = round_jiffies(jiffies + (duration * 3600 * HZ));
-
+	hrtimer_set_expires_range(&di->maintenance_timer,
+		ktime_set(duration * ONE_HOUR_IN_SECONDS, 0),
+		ktime_set(FIVE_MINUTES_IN_SECONDS, 0));
 	di->events.maintenance_timer_expired = false;
-	di->maintenance_timer.expires = timer_expiration;
-	if (!timer_pending(&di->maintenance_timer))
-		add_timer(&di->maintenance_timer);
-	else
-		mod_timer(&di->maintenance_timer, timer_expiration);
+	hrtimer_start_expires(&di->maintenance_timer, HRTIMER_MODE_REL);
 }
 
 /**
@@ -430,8 +506,8 @@ static void abx500_chargalg_start_maintenance_timer(struct abx500_chargalg *di,
  */
 static void abx500_chargalg_stop_maintenance_timer(struct abx500_chargalg *di)
 {
-	di->events.maintenance_timer_expired = false;
-	del_timer(&di->maintenance_timer);
+	if (hrtimer_try_to_cancel(&di->maintenance_timer) >= 0)
+		di->events.maintenance_timer_expired = false;
 }
 
 /**
@@ -477,6 +553,8 @@ static int abx500_chargalg_kick_watchdog(struct abx500_chargalg *di)
 static int abx500_chargalg_ac_en(struct abx500_chargalg *di, int enable,
 	int vset, int iset)
 {
+	static int abx500_chargalg_ex_ac_enable_toggle;
+
 	if (!di->ac_chg || !di->ac_chg->ops.enable)
 		return -ENXIO;
 
@@ -489,6 +567,14 @@ static int abx500_chargalg_ac_en(struct abx500_chargalg *di, int enable,
 	di->chg_info.ac_iset = iset;
 	di->chg_info.ac_vset = vset;
 
+	/* Enable external charger */
+	if (enable && di->ac_chg->external &&
+	    !abx500_chargalg_ex_ac_enable_toggle) {
+		blocking_notifier_call_chain(&charger_notifier_list,
+					     0, di->dev);
+		abx500_chargalg_ex_ac_enable_toggle++;
+	}
+
 	return di->ac_chg->ops.enable(di->ac_chg, enable, vset, iset);
 }
 
@@ -520,6 +606,37 @@ static int abx500_chargalg_usb_en(struct abx500_chargalg *di, int enable,
 	return di->usb_chg->ops.enable(di->usb_chg, enable, vset, iset);
 }
 
+ /**
+ * ab8540_chargalg_usb_pp_en() - Enable/ disable USB power path
+ * @di:                pointer to the abx500_chargalg structure
+ * @enable:    power path enable/disable
+ *
+ * The USB power path will be enable/ disable
+ */
+static int ab8540_chargalg_usb_pp_en(struct abx500_chargalg *di, bool enable)
+{
+	if (!di->usb_chg || !di->usb_chg->ops.pp_enable)
+		return -ENXIO;
+
+	return di->usb_chg->ops.pp_enable(di->usb_chg, enable);
+}
+
+/**
+ * ab8540_chargalg_usb_pre_chg_en() - Enable/ disable USB pre-charge
+ * @di:                pointer to the abx500_chargalg structure
+ * @enable:    USB pre-charge enable/disable
+ *
+ * The USB USB pre-charge will be enable/ disable
+ */
+static int ab8540_chargalg_usb_pre_chg_en(struct abx500_chargalg *di,
+					  bool enable)
+{
+	if (!di->usb_chg || !di->usb_chg->ops.pre_chg_enable)
+		return -ENXIO;
+
+	return di->usb_chg->ops.pre_chg_enable(di->usb_chg, enable);
+}
+
 /**
  * abx500_chargalg_update_chg_curr() - Update charger current
  * @di:		pointer to the abx500_chargalg structure
@@ -613,8 +730,6 @@ static void abx500_chargalg_hold_charging(struct abx500_chargalg *di)
 static void abx500_chargalg_start_charging(struct abx500_chargalg *di,
 	int vset, int iset)
 {
-	bool start_chargalg_wd = true;
-
 	switch (di->chg_info.charger_type) {
 	case AC_CHG:
 		dev_dbg(di->dev,
@@ -632,12 +747,8 @@ static void abx500_chargalg_start_charging(struct abx500_chargalg *di,
 
 	default:
 		dev_err(di->dev, "Unknown charger to charge from\n");
-		start_chargalg_wd = false;
 		break;
 	}
-
-	if (start_chargalg_wd && !delayed_work_pending(&di->chargalg_wd_work))
-		queue_delayed_work(di->chargalg_wq, &di->chargalg_wd_work, 0);
 }
 
 /**
@@ -725,6 +836,9 @@ static void abx500_chargalg_end_of_charge(struct abx500_chargalg *di)
 		di->batt_data.avg_curr > 0) {
 		if (++di->eoc_cnt >= EOC_COND_CNT) {
 			di->eoc_cnt = 0;
+			if ((di->chg_info.charger_type & USB_CHG) &&
+			   (di->usb_chg->power_path))
+				ab8540_chargalg_usb_pp_en(di, true);
 			di->charge_status = POWER_SUPPLY_STATUS_FULL;
 			di->maintenance_chg = true;
 			dev_dbg(di->dev, "EOC reached!\n");
@@ -1217,6 +1331,8 @@ static void abx500_chargalg_external_power_changed(struct power_supply *psy)
 static void abx500_chargalg_algorithm(struct abx500_chargalg *di)
 {
 	int charger_status;
+	int ret;
+	int curr_step_lvl;
 
 	/* Collect data from all power_supply class devices */
 	class_for_each_device(power_supply_class, NULL,
@@ -1227,6 +1343,15 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di)
 	abx500_chargalg_check_charger_voltage(di);
 
 	charger_status = abx500_chargalg_check_charger_connection(di);
+	abx500_chargalg_check_current_step_status(di);
+
+	if (is_ab8500(di->parent)) {
+		ret = abx500_chargalg_check_charger_enable(di);
+		if (ret < 0)
+			dev_err(di->dev, "Checking charger is enabled error"
+					": Returned Value %d\n", ret);
+	}
+
 	/*
 	 * First check if we have a charger connected.
 	 * Also we don't allow charging of unknown batteries if configured
@@ -1416,9 +1541,34 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di)
 		break;
 
 	case STATE_NORMAL_INIT:
-		abx500_chargalg_start_charging(di,
-			di->bm->bat_type[di->bm->batt_id].normal_vol_lvl,
-			di->bm->bat_type[di->bm->batt_id].normal_cur_lvl);
+		if ((di->chg_info.charger_type & USB_CHG) &&
+				di->usb_chg->power_path) {
+			if (di->batt_data.volt >
+			    (di->bm->fg_params->lowbat_threshold +
+			     BAT_PLUS_MARGIN)) {
+				ab8540_chargalg_usb_pre_chg_en(di, false);
+				ab8540_chargalg_usb_pp_en(di, false);
+			} else {
+				ab8540_chargalg_usb_pp_en(di, true);
+				ab8540_chargalg_usb_pre_chg_en(di, true);
+				abx500_chargalg_state_to(di,
+					STATE_USB_PP_PRE_CHARGE);
+				break;
+			}
+		}
+
+		if (di->curr_status.curr_step == CHARGALG_CURR_STEP_LOW)
+			abx500_chargalg_stop_charging(di);
+		else {
+			curr_step_lvl = di->bm->bat_type[
+				di->bm->batt_id].normal_cur_lvl
+				* di->curr_status.curr_step
+				/ CHARGALG_CURR_STEP_HIGH;
+			abx500_chargalg_start_charging(di,
+				di->bm->bat_type[di->bm->batt_id]
+				.normal_vol_lvl, curr_step_lvl);
+		}
+
 		abx500_chargalg_state_to(di, STATE_NORMAL);
 		abx500_chargalg_start_safety_timer(di);
 		abx500_chargalg_stop_maintenance_timer(di);
@@ -1430,6 +1580,13 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di)
 
 		break;
 
+	case STATE_USB_PP_PRE_CHARGE:
+		if (di->batt_data.volt >
+			(di->bm->fg_params->lowbat_threshold +
+			BAT_PLUS_MARGIN))
+			abx500_chargalg_state_to(di, STATE_NORMAL_INIT);
+		break;
+
 	case STATE_NORMAL:
 		handle_maxim_chg_curr(di);
 		if (di->charge_status == POWER_SUPPLY_STATUS_FULL &&
@@ -1653,99 +1810,134 @@ static int abx500_chargalg_get_property(struct power_supply *psy,
 
 /* Exposure to the sysfs interface */
 
-/**
- * abx500_chargalg_sysfs_show() - sysfs show operations
- * @kobj:      pointer to the struct kobject
- * @attr:      pointer to the struct attribute
- * @buf:       buffer that holds the parameter to send to userspace
- *
- * Returns a buffer to be displayed in user space
- */
-static ssize_t abx500_chargalg_sysfs_show(struct kobject *kobj,
-					  struct attribute *attr, char *buf)
+static ssize_t abx500_chargalg_curr_step_show(struct abx500_chargalg *di,
+					      char *buf)
 {
-	struct abx500_chargalg *di = container_of(kobj,
-               struct abx500_chargalg, chargalg_kobject);
+	return sprintf(buf, "%d\n", di->curr_status.curr_step);
+}
+
+static ssize_t abx500_chargalg_curr_step_store(struct abx500_chargalg *di,
+					       const char *buf, size_t length)
+{
+	long int param;
+	int ret;
+
+	ret = kstrtol(buf, 10, &param);
+	if (ret < 0)
+		return ret;
+
+	di->curr_status.curr_step = param;
+	if (di->curr_status.curr_step >= CHARGALG_CURR_STEP_LOW &&
+		di->curr_status.curr_step <= CHARGALG_CURR_STEP_HIGH) {
+		di->curr_status.curr_step_change = true;
+		queue_work(di->chargalg_wq, &di->chargalg_work);
+	} else
+		dev_info(di->dev, "Wrong current step\n"
+			"Enter 0. Disable AC/USB Charging\n"
+			"1--100. Set AC/USB charging current step\n"
+			"100. Enable AC/USB Charging\n");
+
+	return strlen(buf);
+}
+
 
+static ssize_t abx500_chargalg_en_show(struct abx500_chargalg *di,
+				       char *buf)
+{
 	return sprintf(buf, "%d\n",
 		       di->susp_status.ac_suspended &&
 		       di->susp_status.usb_suspended);
 }
 
-/**
- * abx500_chargalg_sysfs_charger() - sysfs store operations
- * @kobj:      pointer to the struct kobject
- * @attr:      pointer to the struct attribute
- * @buf:       buffer that holds the parameter passed from userspace
- * @length:    length of the parameter passed
- *
- * Returns length of the buffer(input taken from user space) on success
- * else error code on failure
- * The operation to be performed on passing the parameters from the user space.
- */
-static ssize_t abx500_chargalg_sysfs_charger(struct kobject *kobj,
-	struct attribute *attr, const char *buf, size_t length)
+static ssize_t abx500_chargalg_en_store(struct abx500_chargalg *di,
+	const char *buf, size_t length)
 {
-	struct abx500_chargalg *di = container_of(kobj,
-		struct abx500_chargalg, chargalg_kobject);
 	long int param;
 	int ac_usb;
 	int ret;
-	char entry = *attr->name;
 
-	switch (entry) {
-	case 'c':
-		ret = strict_strtol(buf, 10, &param);
-		if (ret < 0)
-			return ret;
-
-		ac_usb = param;
-		switch (ac_usb) {
-		case 0:
-			/* Disable charging */
-			di->susp_status.ac_suspended = true;
-			di->susp_status.usb_suspended = true;
-			di->susp_status.suspended_change = true;
-			/* Trigger a state change */
-			queue_work(di->chargalg_wq,
-				&di->chargalg_work);
-			break;
-		case 1:
-			/* Enable AC Charging */
-			di->susp_status.ac_suspended = false;
-			di->susp_status.suspended_change = true;
-			/* Trigger a state change */
-			queue_work(di->chargalg_wq,
-				&di->chargalg_work);
-			break;
-		case 2:
-			/* Enable USB charging */
-			di->susp_status.usb_suspended = false;
-			di->susp_status.suspended_change = true;
-			/* Trigger a state change */
-			queue_work(di->chargalg_wq,
-				&di->chargalg_work);
-			break;
-		default:
-			dev_info(di->dev, "Wrong input\n"
-				"Enter 0. Disable AC/USB Charging\n"
-				"1. Enable AC charging\n"
-				"2. Enable USB Charging\n");
-		};
+	ret = kstrtol(buf, 10, &param);
+	if (ret < 0)
+		return ret;
+
+	ac_usb = param;
+	switch (ac_usb) {
+	case 0:
+		/* Disable charging */
+		di->susp_status.ac_suspended = true;
+		di->susp_status.usb_suspended = true;
+		di->susp_status.suspended_change = true;
+		/* Trigger a state change */
+		queue_work(di->chargalg_wq,
+			&di->chargalg_work);
+		break;
+	case 1:
+		/* Enable AC Charging */
+		di->susp_status.ac_suspended = false;
+		di->susp_status.suspended_change = true;
+		/* Trigger a state change */
+		queue_work(di->chargalg_wq,
+			&di->chargalg_work);
+		break;
+	case 2:
+		/* Enable USB charging */
+		di->susp_status.usb_suspended = false;
+		di->susp_status.suspended_change = true;
+		/* Trigger a state change */
+		queue_work(di->chargalg_wq,
+			&di->chargalg_work);
 		break;
+	default:
+		dev_info(di->dev, "Wrong input\n"
+			"Enter 0. Disable AC/USB Charging\n"
+			"1. Enable AC charging\n"
+			"2. Enable USB Charging\n");
 	};
 	return strlen(buf);
 }
 
-static struct attribute abx500_chargalg_en_charger = \
+static struct abx500_chargalg_sysfs_entry abx500_chargalg_en_charger =
+	__ATTR(chargalg, 0644, abx500_chargalg_en_show,
+				abx500_chargalg_en_store);
+
+static struct abx500_chargalg_sysfs_entry abx500_chargalg_curr_step =
+	__ATTR(chargalg_curr_step, 0644, abx500_chargalg_curr_step_show,
+					abx500_chargalg_curr_step_store);
+
+static ssize_t abx500_chargalg_sysfs_show(struct kobject *kobj,
+	struct attribute *attr, char *buf)
 {
-	.name = "chargalg",
-	.mode = S_IRUGO | S_IWUSR,
-};
+	struct abx500_chargalg_sysfs_entry *entry = container_of(attr,
+		struct abx500_chargalg_sysfs_entry, attr);
+
+	struct abx500_chargalg *di = container_of(kobj,
+		struct abx500_chargalg, chargalg_kobject);
+
+	if (!entry->show)
+		return -EIO;
+
+	return entry->show(di, buf);
+}
+
+static ssize_t abx500_chargalg_sysfs_charger(struct kobject *kobj,
+	struct attribute *attr, const char *buf, size_t length)
+{
+	struct abx500_chargalg_sysfs_entry *entry = container_of(attr,
+		struct abx500_chargalg_sysfs_entry, attr);
+
+	struct abx500_chargalg *di = container_of(kobj,
+		struct abx500_chargalg, chargalg_kobject);
+
+	if (!entry->store)
+		return -EIO;
+
+	return entry->store(di, buf, length);
+}
 
 static struct attribute *abx500_chargalg_chg[] = {
-	&abx500_chargalg_en_charger,
-	NULL
+	&abx500_chargalg_en_charger.attr,
+	&abx500_chargalg_curr_step.attr,
+	NULL,
 };
 
 static const struct sysfs_ops abx500_chargalg_sysfs_ops = {
@@ -1832,10 +2024,16 @@ static int abx500_chargalg_remove(struct platform_device *pdev)
 	/* sysfs interface to enable/disbale charging from user space */
 	abx500_chargalg_sysfs_exit(di);
 
+	hrtimer_cancel(&di->safety_timer);
+	hrtimer_cancel(&di->maintenance_timer);
+
+	cancel_delayed_work_sync(&di->chargalg_periodic_work);
+	cancel_delayed_work_sync(&di->chargalg_wd_work);
+	cancel_work_sync(&di->chargalg_work);
+
 	/* Delete the work queue */
 	destroy_workqueue(di->chargalg_wq);
 
-	flush_scheduled_work();
 	power_supply_unregister(&di->chargalg_psy);
 	platform_set_drvdata(pdev, NULL);
 
@@ -1873,8 +2071,9 @@ static int abx500_chargalg_probe(struct platform_device *pdev)
 		}
 	}
 
-	/* get device struct */
+	/* get device struct and parent */
 	di->dev = &pdev->dev;
+	di->parent = dev_get_drvdata(pdev->dev.parent);
 
 	/* chargalg supply */
 	di->chargalg_psy.name = "abx500_chargalg";
@@ -1888,15 +2087,13 @@ static int abx500_chargalg_probe(struct platform_device *pdev)
 		abx500_chargalg_external_power_changed;
 
 	/* Initilialize safety timer */
-	init_timer(&di->safety_timer);
+	hrtimer_init(&di->safety_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS);
 	di->safety_timer.function = abx500_chargalg_safety_timer_expired;
-	di->safety_timer.data = (unsigned long) di;
 
 	/* Initilialize maintenance timer */
-	init_timer(&di->maintenance_timer);
+	hrtimer_init(&di->maintenance_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS);
 	di->maintenance_timer.function =
 		abx500_chargalg_maintenance_timer_expired;
-	di->maintenance_timer.data = (unsigned long) di;
 
 	/* Create a work queue for the chargalg */
 	di->chargalg_wq =
@@ -1933,6 +2130,7 @@ static int abx500_chargalg_probe(struct platform_device *pdev)
 		dev_err(di->dev, "failed to create sysfs entry\n");
 		goto free_psy;
 	}
+	di->curr_status.curr_step = CHARGALG_CURR_STEP_HIGH;
 
 	/* Run the charging algorithm */
 	queue_delayed_work(di->chargalg_wq, &di->chargalg_periodic_work, 0);
@@ -1964,18 +2162,7 @@ static struct platform_driver abx500_chargalg_driver = {
 	},
 };
 
-static int __init abx500_chargalg_init(void)
-{
-	return platform_driver_register(&abx500_chargalg_driver);
-}
-
-static void __exit abx500_chargalg_exit(void)
-{
-	platform_driver_unregister(&abx500_chargalg_driver);
-}
-
-module_init(abx500_chargalg_init);
-module_exit(abx500_chargalg_exit);
+module_platform_driver(abx500_chargalg_driver);
 
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Johan Palsson, Karl Komierowski");
diff --git a/drivers/power/da9030_battery.c b/drivers/power/da9030_battery.c
index e8c5a39..ae6c418 100644
--- a/drivers/power/da9030_battery.c
+++ b/drivers/power/da9030_battery.c
@@ -505,7 +505,7 @@ static int da9030_battery_probe(struct platform_device *pdev)
 	    pdata->charge_millivolt > 4350)
 		return -EINVAL;
 
-	charger = kzalloc(sizeof(*charger), GFP_KERNEL);
+	charger = devm_kzalloc(&pdev->dev, sizeof(*charger), GFP_KERNEL);
 	if (charger == NULL)
 		return -ENOMEM;
 
@@ -557,8 +557,6 @@ err_notifier:
 	cancel_delayed_work(&charger->work);
 
 err_charger_init:
-	kfree(charger);
-
 	return ret;
 }
 
@@ -575,8 +573,6 @@ static int da9030_battery_remove(struct platform_device *dev)
 	da9030_set_charge(charger, 0);
 	power_supply_unregister(&charger->psy);
 
-	kfree(charger);
-
 	return 0;
 }
 
diff --git a/drivers/power/da9052-battery.c b/drivers/power/da9052-battery.c
index 08193fe..f8f4c0f 100644
--- a/drivers/power/da9052-battery.c
+++ b/drivers/power/da9052-battery.c
@@ -594,7 +594,8 @@ static s32 da9052_bat_probe(struct platform_device *pdev)
 	int ret;
 	int i;
 
-	bat = kzalloc(sizeof(struct da9052_battery), GFP_KERNEL);
+	bat = devm_kzalloc(&pdev->dev, sizeof(struct da9052_battery),
+				GFP_KERNEL);
 	if (!bat)
 		return -ENOMEM;
 
@@ -635,7 +636,6 @@ err:
 	while (--i >= 0)
 		da9052_free_irq(bat->da9052, da9052_bat_irq_bits[i], bat);
 
-	kfree(bat);
 	return ret;
 }
 static int da9052_bat_remove(struct platform_device *pdev)
@@ -647,7 +647,6 @@ static int da9052_bat_remove(struct platform_device *pdev)
 		da9052_free_irq(bat->da9052, da9052_bat_irq_bits[i], bat);
 
 	power_supply_unregister(&bat->psy);
-	kfree(bat);
 
 	return 0;
 }
diff --git a/drivers/power/ds2760_battery.c b/drivers/power/ds2760_battery.c
index 704e652..85b4e6e 100644
--- a/drivers/power/ds2760_battery.c
+++ b/drivers/power/ds2760_battery.c
@@ -512,7 +512,7 @@ static int ds2760_battery_probe(struct platform_device *pdev)
 	int retval = 0;
 	struct ds2760_device_info *di;
 
-	di = kzalloc(sizeof(*di), GFP_KERNEL);
+	di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL);
 	if (!di) {
 		retval = -ENOMEM;
 		goto di_alloc_failed;
@@ -576,7 +576,6 @@ static int ds2760_battery_probe(struct platform_device *pdev)
 workqueue_failed:
 	power_supply_unregister(&di->bat);
 batt_failed:
-	kfree(di);
 di_alloc_failed:
 success:
 	return retval;
@@ -590,7 +589,6 @@ static int ds2760_battery_remove(struct platform_device *pdev)
 	cancel_delayed_work_sync(&di->set_charged_work);
 	destroy_workqueue(di->monitor_wqueue);
 	power_supply_unregister(&di->bat);
-	kfree(di);
 
 	return 0;
 }
diff --git a/drivers/power/ds2780_battery.c b/drivers/power/ds2780_battery.c
index 8b6c453..9f418fa 100644
--- a/drivers/power/ds2780_battery.c
+++ b/drivers/power/ds2780_battery.c
@@ -760,7 +760,7 @@ static int ds2780_battery_probe(struct platform_device *pdev)
 	int ret = 0;
 	struct ds2780_device_info *dev_info;
 
-	dev_info = kzalloc(sizeof(*dev_info), GFP_KERNEL);
+	dev_info = devm_kzalloc(&pdev->dev, sizeof(*dev_info), GFP_KERNEL);
 	if (!dev_info) {
 		ret = -ENOMEM;
 		goto fail;
@@ -779,7 +779,7 @@ static int ds2780_battery_probe(struct platform_device *pdev)
 	ret = power_supply_register(&pdev->dev, &dev_info->bat);
 	if (ret) {
 		dev_err(dev_info->dev, "failed to register battery\n");
-		goto fail_free_info;
+		goto fail;
 	}
 
 	ret = sysfs_create_group(&dev_info->bat.dev->kobj, &ds2780_attr_group);
@@ -813,8 +813,6 @@ fail_remove_group:
 	sysfs_remove_group(&dev_info->bat.dev->kobj, &ds2780_attr_group);
 fail_unregister:
 	power_supply_unregister(&dev_info->bat);
-fail_free_info:
-	kfree(dev_info);
 fail:
 	return ret;
 }
@@ -828,7 +826,6 @@ static int ds2780_battery_remove(struct platform_device *pdev)
 
 	power_supply_unregister(&dev_info->bat);
 
-	kfree(dev_info);
 	return 0;
 }
 
diff --git a/drivers/power/ds2782_battery.c b/drivers/power/ds2782_battery.c
index c09e772..5631748 100644
--- a/drivers/power/ds2782_battery.c
+++ b/drivers/power/ds2782_battery.c
@@ -332,32 +332,32 @@ static int ds278x_battery_remove(struct i2c_client *client)
 	return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 
-static int ds278x_suspend(struct i2c_client *client,
-		pm_message_t state)
+static int ds278x_suspend(struct device *dev)
 {
+	struct i2c_client *client = to_i2c_client(dev);
 	struct ds278x_info *info = i2c_get_clientdata(client);
 
 	cancel_delayed_work(&info->bat_work);
 	return 0;
 }
 
-static int ds278x_resume(struct i2c_client *client)
+static int ds278x_resume(struct device *dev)
 {
+	struct i2c_client *client = to_i2c_client(dev);
 	struct ds278x_info *info = i2c_get_clientdata(client);
 
 	schedule_delayed_work(&info->bat_work, DS278x_DELAY);
 	return 0;
 }
 
-#else
-
-#define ds278x_suspend NULL
-#define ds278x_resume NULL
-
-#endif /* CONFIG_PM */
+static SIMPLE_DEV_PM_OPS(ds278x_battery_pm_ops, ds278x_suspend, ds278x_resume);
+#define DS278X_BATTERY_PM_OPS (&ds278x_battery_pm_ops)
 
+#else
+#define DS278X_BATTERY_PM_OPS NULL
+#endif /* CONFIG_PM_SLEEP */
 
 enum ds278x_num_id {
 	DS2782 = 0,
@@ -460,11 +460,10 @@ MODULE_DEVICE_TABLE(i2c, ds278x_id);
 static struct i2c_driver ds278x_battery_driver = {
 	.driver 	= {
 		.name	= "ds2782-battery",
+		.pm	= DS278X_BATTERY_PM_OPS,
 	},
 	.probe		= ds278x_battery_probe,
 	.remove		= ds278x_battery_remove,
-	.suspend	= ds278x_suspend,
-	.resume		= ds278x_resume,
 	.id_table	= ds278x_id,
 };
 module_i2c_driver(ds278x_battery_driver);
diff --git a/drivers/power/goldfish_battery.c b/drivers/power/goldfish_battery.c
index c10f460..29eba88 100644
--- a/drivers/power/goldfish_battery.c
+++ b/drivers/power/goldfish_battery.c
@@ -178,7 +178,7 @@ static int goldfish_battery_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
-	data->reg_base = devm_ioremap(&pdev->dev, r->start, r->end - r->start + 1);
+	data->reg_base = devm_ioremap(&pdev->dev, r->start, resource_size(r));
 	if (data->reg_base == NULL) {
 		dev_err(&pdev->dev, "unable to remap MMIO\n");
 		return -ENOMEM;
diff --git a/drivers/power/gpio-charger.c b/drivers/power/gpio-charger.c
index e3e40a9..e9883ee 100644
--- a/drivers/power/gpio-charger.c
+++ b/drivers/power/gpio-charger.c
@@ -86,7 +86,8 @@ static int gpio_charger_probe(struct platform_device *pdev)
 		return -EINVAL;
 	}
 
-	gpio_charger = kzalloc(sizeof(*gpio_charger), GFP_KERNEL);
+	gpio_charger = devm_kzalloc(&pdev->dev, sizeof(*gpio_charger),
+					GFP_KERNEL);
 	if (!gpio_charger) {
 		dev_err(&pdev->dev, "Failed to alloc driver structure\n");
 		return -ENOMEM;
@@ -140,7 +141,6 @@ static int gpio_charger_probe(struct platform_device *pdev)
 err_gpio_free:
 	gpio_free(pdata->gpio);
 err_free:
-	kfree(gpio_charger);
 	return ret;
 }
 
@@ -156,7 +156,6 @@ static int gpio_charger_remove(struct platform_device *pdev)
 	gpio_free(gpio_charger->pdata->gpio);
 
 	platform_set_drvdata(pdev, NULL);
-	kfree(gpio_charger);
 
 	return 0;
 }
diff --git a/drivers/power/isp1704_charger.c b/drivers/power/isp1704_charger.c
index 176ad59..fc04d19 100644
--- a/drivers/power/isp1704_charger.c
+++ b/drivers/power/isp1704_charger.c
@@ -411,7 +411,7 @@ static int isp1704_charger_probe(struct platform_device *pdev)
 	struct isp1704_charger	*isp;
 	int			ret = -ENODEV;
 
-	isp = kzalloc(sizeof *isp, GFP_KERNEL);
+	isp = devm_kzalloc(&pdev->dev, sizeof(*isp), GFP_KERNEL);
 	if (!isp)
 		return -ENOMEM;
 
@@ -477,8 +477,6 @@ fail1:
 	isp1704_charger_set_power(isp, 0);
 	usb_put_phy(isp->phy);
 fail0:
-	kfree(isp);
-
 	dev_err(&pdev->dev, "failed to register isp1704 with error %d\n", ret);
 
 	return ret;
@@ -492,7 +490,6 @@ static int isp1704_charger_remove(struct platform_device *pdev)
 	power_supply_unregister(&isp->psy);
 	usb_put_phy(isp->phy);
 	isp1704_charger_set_power(isp, 0);
-	kfree(isp);
 
 	return 0;
 }
diff --git a/drivers/power/lp8788-charger.c b/drivers/power/lp8788-charger.c
index 6d1f452..ed49b50 100644
--- a/drivers/power/lp8788-charger.c
+++ b/drivers/power/lp8788-charger.c
@@ -49,7 +49,6 @@
 #define LP8788_CHG_START		0x11
 #define LP8788_CHG_END			0x1C
 
-#define LP8788_BUF_SIZE			40
 #define LP8788_ISEL_MAX			23
 #define LP8788_ISEL_STEP		50
 #define LP8788_VTERM_MIN		4100
@@ -633,7 +632,7 @@ static ssize_t lp8788_show_charger_status(struct device *dev,
 	lp8788_read_byte(pchg->lp, LP8788_CHG_STATUS, &data);
 	state = (data & LP8788_CHG_STATE_M) >> LP8788_CHG_STATE_S;
 
-	return scnprintf(buf, LP8788_BUF_SIZE, "%s\n", desc[state]);
+	return scnprintf(buf, PAGE_SIZE, "%s\n", desc[state]);
 }
 
 static ssize_t lp8788_show_eoc_time(struct device *dev,
@@ -647,7 +646,7 @@ static ssize_t lp8788_show_eoc_time(struct device *dev,
 	lp8788_read_byte(pchg->lp, LP8788_CHG_EOC, &val);
 	val = (val & LP8788_CHG_EOC_TIME_M) >> LP8788_CHG_EOC_TIME_S;
 
-	return scnprintf(buf, LP8788_BUF_SIZE, "End Of Charge Time: %s\n",
+	return scnprintf(buf, PAGE_SIZE, "End Of Charge Time: %s\n",
 			stime[val]);
 }
 
@@ -667,8 +666,7 @@ static ssize_t lp8788_show_eoc_level(struct device *dev,
 	val = (val & LP8788_CHG_EOC_LEVEL_M) >> LP8788_CHG_EOC_LEVEL_S;
 	level = mode ? abs_level[val] : relative_level[val];
 
-	return scnprintf(buf, LP8788_BUF_SIZE, "End Of Charge Level: %s\n",
-			level);
+	return scnprintf(buf, PAGE_SIZE, "End Of Charge Level: %s\n", level);
 }
 
 static DEVICE_ATTR(charger_status, S_IRUSR, lp8788_show_charger_status, NULL);
diff --git a/drivers/power/max17040_battery.c b/drivers/power/max17040_battery.c
index 74a0bd9..c7ff6d6 100644
--- a/drivers/power/max17040_battery.c
+++ b/drivers/power/max17040_battery.c
@@ -246,31 +246,34 @@ static int max17040_remove(struct i2c_client *client)
 	return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 
-static int max17040_suspend(struct i2c_client *client,
-		pm_message_t state)
+static int max17040_suspend(struct device *dev)
 {
+	struct i2c_client *client = to_i2c_client(dev);
 	struct max17040_chip *chip = i2c_get_clientdata(client);
 
 	cancel_delayed_work(&chip->work);
 	return 0;
 }
 
-static int max17040_resume(struct i2c_client *client)
+static int max17040_resume(struct device *dev)
 {
+	struct i2c_client *client = to_i2c_client(dev);
 	struct max17040_chip *chip = i2c_get_clientdata(client);
 
 	schedule_delayed_work(&chip->work, MAX17040_DELAY);
 	return 0;
 }
 
+static SIMPLE_DEV_PM_OPS(max17040_pm_ops, max17040_suspend, max17040_resume);
+#define MAX17040_PM_OPS (&max17040_pm_ops)
+
 #else
 
-#define max17040_suspend NULL
-#define max17040_resume NULL
+#define MAX17040_PM_OPS NULL
 
-#endif /* CONFIG_PM */
+#endif /* CONFIG_PM_SLEEP */
 
 static const struct i2c_device_id max17040_id[] = {
 	{ "max17040", 0 },
@@ -281,11 +284,10 @@ MODULE_DEVICE_TABLE(i2c, max17040_id);
 static struct i2c_driver max17040_i2c_driver = {
 	.driver	= {
 		.name	= "max17040",
+		.pm	= MAX17040_PM_OPS,
 	},
 	.probe		= max17040_probe,
 	.remove		= max17040_remove,
-	.suspend	= max17040_suspend,
-	.resume		= max17040_resume,
 	.id_table	= max17040_id,
 };
 module_i2c_driver(max17040_i2c_driver);
diff --git a/drivers/power/max8903_charger.c b/drivers/power/max8903_charger.c
index 14e2b96..08f0d79 100644
--- a/drivers/power/max8903_charger.c
+++ b/drivers/power/max8903_charger.c
@@ -189,7 +189,7 @@ static int max8903_probe(struct platform_device *pdev)
 	int ta_in = 0;
 	int usb_in = 0;
 
-	data = kzalloc(sizeof(struct max8903_data), GFP_KERNEL);
+	data = devm_kzalloc(dev, sizeof(struct max8903_data), GFP_KERNEL);
 	if (data == NULL) {
 		dev_err(dev, "Cannot allocate memory.\n");
 		return -ENOMEM;
@@ -341,7 +341,6 @@ err_dc_irq:
 err_psy:
 	power_supply_unregister(&data->psy);
 err:
-	kfree(data);
 	return ret;
 }
 
@@ -359,7 +358,6 @@ static int max8903_remove(struct platform_device *pdev)
 		if (pdata->dc_valid)
 			free_irq(gpio_to_irq(pdata->dok), data);
 		power_supply_unregister(&data->psy);
-		kfree(data);
 	}
 
 	return 0;
diff --git a/drivers/power/max8925_power.c b/drivers/power/max8925_power.c
index 665cdc7..0ee1e14 100644
--- a/drivers/power/max8925_power.c
+++ b/drivers/power/max8925_power.c
@@ -489,7 +489,8 @@ static int max8925_power_probe(struct platform_device *pdev)
 		return -EINVAL;
 	}
 
-	info = kzalloc(sizeof(struct max8925_power_info), GFP_KERNEL);
+	info = devm_kzalloc(&pdev->dev, sizeof(struct max8925_power_info),
+				GFP_KERNEL);
 	if (!info)
 		return -ENOMEM;
 	info->chip = chip;
@@ -546,7 +547,6 @@ out_battery:
 out_usb:
 	power_supply_unregister(&info->ac);
 out:
-	kfree(info);
 	return ret;
 }
 
@@ -559,7 +559,6 @@ static int max8925_power_remove(struct platform_device *pdev)
 		power_supply_unregister(&info->usb);
 		power_supply_unregister(&info->battery);
 		max8925_deinit_charger(info);
-		kfree(info);
 	}
 	return 0;
 }
diff --git a/drivers/power/max8997_charger.c b/drivers/power/max8997_charger.c
index e757885..4bdedfe 100644
--- a/drivers/power/max8997_charger.c
+++ b/drivers/power/max8997_charger.c
@@ -138,7 +138,8 @@ static int max8997_battery_probe(struct platform_device *pdev)
 		return ret;
 	}
 
-	charger = kzalloc(sizeof(struct charger_data), GFP_KERNEL);
+	charger = devm_kzalloc(&pdev->dev, sizeof(struct charger_data),
+				GFP_KERNEL);
 	if (charger == NULL) {
 		dev_err(&pdev->dev, "Cannot allocate memory.\n");
 		return -ENOMEM;
@@ -158,13 +159,10 @@ static int max8997_battery_probe(struct platform_device *pdev)
 	ret = power_supply_register(&pdev->dev, &charger->battery);
 	if (ret) {
 		dev_err(&pdev->dev, "failed: power supply register\n");
-		goto err;
+		return ret;
 	}
 
 	return 0;
-err:
-	kfree(charger);
-	return ret;
 }
 
 static int max8997_battery_remove(struct platform_device *pdev)
@@ -172,7 +170,6 @@ static int max8997_battery_remove(struct platform_device *pdev)
 	struct charger_data *charger = platform_get_drvdata(pdev);
 
 	power_supply_unregister(&charger->battery);
-	kfree(charger);
 	return 0;
 }
 
diff --git a/drivers/power/max8998_charger.c b/drivers/power/max8998_charger.c
index bf677e3..5017470 100644
--- a/drivers/power/max8998_charger.c
+++ b/drivers/power/max8998_charger.c
@@ -88,7 +88,8 @@ static int max8998_battery_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
-	max8998 = kzalloc(sizeof(struct max8998_battery_data), GFP_KERNEL);
+	max8998 = devm_kzalloc(&pdev->dev, sizeof(struct max8998_battery_data),
+				GFP_KERNEL);
 	if (!max8998)
 		return -ENOMEM;
 
@@ -174,7 +175,6 @@ static int max8998_battery_probe(struct platform_device *pdev)
 
 	return 0;
 err:
-	kfree(max8998);
 	return ret;
 }
 
@@ -183,7 +183,6 @@ static int max8998_battery_remove(struct platform_device *pdev)
 	struct max8998_battery_data *max8998 = platform_get_drvdata(pdev);
 
 	power_supply_unregister(&max8998->battery);
-	kfree(max8998);
 
 	return 0;
 }
diff --git a/drivers/power/pcf50633-charger.c b/drivers/power/pcf50633-charger.c
index c2122a7..17fd77f 100644
--- a/drivers/power/pcf50633-charger.c
+++ b/drivers/power/pcf50633-charger.c
@@ -373,7 +373,7 @@ static int pcf50633_mbc_probe(struct platform_device *pdev)
 	int i;
 	u8 mbcs1;
 
-	mbc = kzalloc(sizeof(*mbc), GFP_KERNEL);
+	mbc = devm_kzalloc(&pdev->dev, sizeof(*mbc), GFP_KERNEL);
 	if (!mbc)
 		return -ENOMEM;
 
@@ -413,7 +413,6 @@ static int pcf50633_mbc_probe(struct platform_device *pdev)
 	ret = power_supply_register(&pdev->dev, &mbc->adapter);
 	if (ret) {
 		dev_err(mbc->pcf->dev, "failed to register adapter\n");
-		kfree(mbc);
 		return ret;
 	}
 
@@ -421,7 +420,6 @@ static int pcf50633_mbc_probe(struct platform_device *pdev)
 	if (ret) {
 		dev_err(mbc->pcf->dev, "failed to register usb\n");
 		power_supply_unregister(&mbc->adapter);
-		kfree(mbc);
 		return ret;
 	}
 
@@ -430,7 +428,6 @@ static int pcf50633_mbc_probe(struct platform_device *pdev)
 		dev_err(mbc->pcf->dev, "failed to register ac\n");
 		power_supply_unregister(&mbc->adapter);
 		power_supply_unregister(&mbc->usb);
-		kfree(mbc);
 		return ret;
 	}
 
@@ -461,8 +458,6 @@ static int pcf50633_mbc_remove(struct platform_device *pdev)
 	power_supply_unregister(&mbc->adapter);
 	power_supply_unregister(&mbc->ac);
 
-	kfree(mbc);
-
 	return 0;
 }
 
diff --git a/drivers/power/pda_power.c b/drivers/power/pda_power.c
index 7df7c5f..0c52e2a 100644
--- a/drivers/power/pda_power.c
+++ b/drivers/power/pda_power.c
@@ -35,7 +35,7 @@ static struct timer_list supply_timer;
 static struct timer_list polling_timer;
 static int polling;
 
-#ifdef CONFIG_USB_OTG_UTILS
+#if IS_ENABLED(CONFIG_USB_PHY)
 static struct usb_phy *transceiver;
 static struct notifier_block otg_nb;
 #endif
@@ -218,7 +218,7 @@ static void polling_timer_func(unsigned long unused)
 		  jiffies + msecs_to_jiffies(pdata->polling_interval));
 }
 
-#ifdef CONFIG_USB_OTG_UTILS
+#if IS_ENABLED(CONFIG_USB_PHY)
 static int otg_is_usb_online(void)
 {
 	return (transceiver->last_event == USB_EVENT_VBUS ||
@@ -315,7 +315,7 @@ static int pda_power_probe(struct platform_device *pdev)
 		pda_psy_usb.num_supplicants = pdata->num_supplicants;
 	}
 
-#ifdef CONFIG_USB_OTG_UTILS
+#if IS_ENABLED(CONFIG_USB_PHY)
 	transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
 	if (!IS_ERR_OR_NULL(transceiver)) {
 		if (!pdata->is_usb_online)
@@ -367,7 +367,7 @@ static int pda_power_probe(struct platform_device *pdev)
 		}
 	}
 
-#ifdef CONFIG_USB_OTG_UTILS
+#if IS_ENABLED(CONFIG_USB_PHY)
 	if (!IS_ERR_OR_NULL(transceiver) && pdata->use_otg_notifier) {
 		otg_nb.notifier_call = otg_handle_notification;
 		ret = usb_register_notifier(transceiver, &otg_nb);
@@ -391,7 +391,7 @@ static int pda_power_probe(struct platform_device *pdev)
 
 	return 0;
 
-#ifdef CONFIG_USB_OTG_UTILS
+#if IS_ENABLED(CONFIG_USB_PHY)
 otg_reg_notifier_failed:
 	if (pdata->is_usb_online && usb_irq)
 		free_irq(usb_irq->start, &pda_psy_usb);
@@ -402,7 +402,7 @@ usb_irq_failed:
 usb_supply_failed:
 	if (pdata->is_ac_online && ac_irq)
 		free_irq(ac_irq->start, &pda_psy_ac);
-#ifdef CONFIG_USB_OTG_UTILS
+#if IS_ENABLED(CONFIG_USB_PHY)
 	if (!IS_ERR_OR_NULL(transceiver))
 		usb_put_phy(transceiver);
 #endif
@@ -437,7 +437,7 @@ static int pda_power_remove(struct platform_device *pdev)
 		power_supply_unregister(&pda_psy_usb);
 	if (pdata->is_ac_online)
 		power_supply_unregister(&pda_psy_ac);
-#ifdef CONFIG_USB_OTG_UTILS
+#if IS_ENABLED(CONFIG_USB_PHY)
 	if (!IS_ERR_OR_NULL(transceiver))
 		usb_put_phy(transceiver);
 #endif
diff --git a/drivers/power/pm2301_charger.c b/drivers/power/pm2301_charger.c
index ed48d75..425cbcf 100644
--- a/drivers/power/pm2301_charger.c
+++ b/drivers/power/pm2301_charger.c
@@ -16,24 +16,24 @@
 #include <linux/slab.h>
 #include <linux/platform_device.h>
 #include <linux/power_supply.h>
-#include <linux/completion.h>
 #include <linux/regulator/consumer.h>
 #include <linux/err.h>
 #include <linux/i2c.h>
 #include <linux/workqueue.h>
-#include <linux/kobject.h>
-#include <linux/mfd/abx500.h>
 #include <linux/mfd/abx500/ab8500.h>
 #include <linux/mfd/abx500/ab8500-bm.h>
-#include <linux/mfd/abx500/ab8500-gpadc.h>
 #include <linux/mfd/abx500/ux500_chargalg.h>
 #include <linux/pm2301_charger.h>
 #include <linux/gpio.h>
+#include <linux/pm_runtime.h>
 
 #include "pm2301_charger.h"
 
 #define to_pm2xxx_charger_ac_device_info(x) container_of((x), \
 		struct pm2xxx_charger, ac_chg)
+#define SLEEP_MIN		50
+#define SLEEP_MAX		100
+#define PM2XXX_AUTOSUSPEND_DELAY 500
 
 static int pm2xxx_interrupt_registers[] = {
 	PM2XXX_REG_INT1,
@@ -113,33 +113,24 @@ static const struct i2c_device_id pm2xxx_ident[] = {
 
 static void set_lpn_pin(struct pm2xxx_charger *pm2)
 {
-	if (pm2->ac.charger_connected)
-		return;
-	gpio_set_value(pm2->lpn_pin, 1);
-
-	return;
+	if (!pm2->ac.charger_connected && gpio_is_valid(pm2->lpn_pin)) {
+		gpio_set_value(pm2->lpn_pin, 1);
+		usleep_range(SLEEP_MIN, SLEEP_MAX);
+	}
 }
 
 static void clear_lpn_pin(struct pm2xxx_charger *pm2)
 {
-	if (pm2->ac.charger_connected)
-		return;
-	gpio_set_value(pm2->lpn_pin, 0);
-
-	return;
+	if (!pm2->ac.charger_connected && gpio_is_valid(pm2->lpn_pin))
+		gpio_set_value(pm2->lpn_pin, 0);
 }
 
 static int pm2xxx_reg_read(struct pm2xxx_charger *pm2, int reg, u8 *val)
 {
 	int ret;
-	/*
-	 * When AC adaptor is unplugged, the host
-	 * must put LPN high to be able to
-	 * communicate by I2C with PM2301
-	 * and receive I2C "acknowledge" from PM2301.
-	 */
-	mutex_lock(&pm2->lock);
-	set_lpn_pin(pm2);
+
+	/* wake up the device */
+	pm_runtime_get_sync(pm2->dev);
 
 	ret = i2c_smbus_read_i2c_block_data(pm2->config.pm2xxx_i2c, reg,
 				1, val);
@@ -147,8 +138,8 @@ static int pm2xxx_reg_read(struct pm2xxx_charger *pm2, int reg, u8 *val)
 		dev_err(pm2->dev, "Error reading register at 0x%x\n", reg);
 	else
 		ret = 0;
-	clear_lpn_pin(pm2);
-	mutex_unlock(&pm2->lock);
+
+	pm_runtime_put_sync(pm2->dev);
 
 	return ret;
 }
@@ -156,14 +147,9 @@ static int pm2xxx_reg_read(struct pm2xxx_charger *pm2, int reg, u8 *val)
 static int pm2xxx_reg_write(struct pm2xxx_charger *pm2, int reg, u8 val)
 {
 	int ret;
-	/*
-	 * When AC adaptor is unplugged, the host
-	 * must put LPN high to be able to
-	 * communicate by I2C with PM2301
-	 * and receive I2C "acknowledge" from PM2301.
-	 */
-	mutex_lock(&pm2->lock);
-	set_lpn_pin(pm2);
+
+	/* wake up the device */
+	pm_runtime_get_sync(pm2->dev);
 
 	ret = i2c_smbus_write_i2c_block_data(pm2->config.pm2xxx_i2c, reg,
 				1, &val);
@@ -171,8 +157,8 @@ static int pm2xxx_reg_write(struct pm2xxx_charger *pm2, int reg, u8 val)
 		dev_err(pm2->dev, "Error writing register at 0x%x\n", reg);
 	else
 		ret = 0;
-	clear_lpn_pin(pm2);
-	mutex_unlock(&pm2->lock);
+
+	pm_runtime_put_sync(pm2->dev);
 
 	return ret;
 }
@@ -192,11 +178,22 @@ static int pm2xxx_charging_disable_mngt(struct pm2xxx_charger *pm2)
 {
 	int ret;
 
+	/* Disable SW EOC ctrl */
+	ret = pm2xxx_reg_write(pm2, PM2XXX_SW_CTRL_REG, PM2XXX_SWCTRL_HW);
+	if (ret < 0) {
+		dev_err(pm2->dev, "%s pm2xxx write failed\n", __func__);
+		return ret;
+	}
+
 	/* Disable charging */
 	ret = pm2xxx_reg_write(pm2, PM2XXX_BATT_CTRL_REG2,
 			(PM2XXX_CH_AUTO_RESUME_DIS | PM2XXX_CHARGER_DIS));
+	if (ret < 0) {
+		dev_err(pm2->dev, "%s pm2xxx write failed\n", __func__);
+		return ret;
+	}
 
-	return ret;
+	return 0;
 }
 
 static int pm2xxx_charger_batt_therm_mngt(struct pm2xxx_charger *pm2, int val)
@@ -216,26 +213,19 @@ int pm2xxx_charger_die_therm_mngt(struct pm2xxx_charger *pm2, int val)
 
 static int pm2xxx_charger_ovv_mngt(struct pm2xxx_charger *pm2, int val)
 {
-	int ret = 0;
+	dev_err(pm2->dev, "Overvoltage detected\n");
+	pm2->flags.ovv = true;
+	power_supply_changed(&pm2->ac_chg.psy);
 
-	pm2->failure_input_ovv++;
-	if (pm2->failure_input_ovv < 4) {
-		ret = pm2xxx_charging_enable_mngt(pm2);
-		goto out;
-	} else {
-		pm2->failure_input_ovv = 0;
-		dev_err(pm2->dev, "Overvoltage detected\n");
-		pm2->flags.ovv = true;
-		power_supply_changed(&pm2->ac_chg.psy);
-	}
+	/* Schedule a new HW failure check */
+	queue_delayed_work(pm2->charger_wq, &pm2->check_hw_failure_work, 0);
 
-out:
-	return ret;
+	return 0;
 }
 
 static int pm2xxx_charger_wd_exp_mngt(struct pm2xxx_charger *pm2, int val)
 {
-	dev_dbg(pm2->dev , "20 minutes watchdog occured\n");
+	dev_dbg(pm2->dev , "20 minutes watchdog expired\n");
 
 	pm2->ac.wd_expired = true;
 	power_supply_changed(&pm2->ac_chg.psy);
@@ -245,13 +235,29 @@ static int pm2xxx_charger_wd_exp_mngt(struct pm2xxx_charger *pm2, int val)
 
 static int pm2xxx_charger_vbat_lsig_mngt(struct pm2xxx_charger *pm2, int val)
 {
+	int ret;
+
 	switch (val) {
 	case PM2XXX_INT1_ITVBATLOWR:
 		dev_dbg(pm2->dev, "VBAT grows above VBAT_LOW level\n");
+		/* Enable SW EOC ctrl */
+		ret = pm2xxx_reg_write(pm2, PM2XXX_SW_CTRL_REG,
+							PM2XXX_SWCTRL_SW);
+		if (ret < 0) {
+			dev_err(pm2->dev, "%s pm2xxx write failed\n", __func__);
+			return ret;
+		}
 		break;
 
 	case PM2XXX_INT1_ITVBATLOWF:
 		dev_dbg(pm2->dev, "VBAT drops below VBAT_LOW level\n");
+		/* Disable SW EOC ctrl */
+		ret = pm2xxx_reg_write(pm2, PM2XXX_SW_CTRL_REG,
+							PM2XXX_SWCTRL_HW);
+		if (ret < 0) {
+			dev_err(pm2->dev, "%s pm2xxx write failed\n", __func__);
+			return ret;
+		}
 		break;
 
 	default:
@@ -322,16 +328,27 @@ static int pm2_int_reg0(void *pm2_data, int val)
 	struct pm2xxx_charger *pm2 = pm2_data;
 	int ret = 0;
 
-	if (val & (PM2XXX_INT1_ITVBATLOWR | PM2XXX_INT1_ITVBATLOWF)) {
-		ret = pm2xxx_charger_vbat_lsig_mngt(pm2, val &
-			(PM2XXX_INT1_ITVBATLOWR | PM2XXX_INT1_ITVBATLOWF));
+	if (val & PM2XXX_INT1_ITVBATLOWR) {
+		ret = pm2xxx_charger_vbat_lsig_mngt(pm2,
+						PM2XXX_INT1_ITVBATLOWR);
+		if (ret < 0)
+			goto out;
+	}
+
+	if (val & PM2XXX_INT1_ITVBATLOWF) {
+		ret = pm2xxx_charger_vbat_lsig_mngt(pm2,
+						PM2XXX_INT1_ITVBATLOWF);
+		if (ret < 0)
+			goto out;
 	}
 
 	if (val & PM2XXX_INT1_ITVBATDISCONNECT) {
 		ret = pm2xxx_charger_bat_disc_mngt(pm2,
 				PM2XXX_INT1_ITVBATDISCONNECT);
+		if (ret < 0)
+			goto out;
 	}
-
+out:
 	return ret;
 }
 
@@ -447,7 +464,6 @@ static int pm2_int_reg5(void *pm2_data, int val)
 	struct pm2xxx_charger *pm2 = pm2_data;
 	int ret = 0;
 
-
 	if (val & (PM2XXX_INT6_ITVPWR2DROP | PM2XXX_INT6_ITVPWR1DROP)) {
 		dev_dbg(pm2->dev, "VMPWR drop to VBAT level\n");
 	}
@@ -468,14 +484,22 @@ static irqreturn_t  pm2xxx_irq_int(int irq, void *data)
 	struct pm2xxx_interrupts *interrupt = pm2->pm2_int;
 	int i;
 
-	for (i = 0; i < PM2XXX_NUM_INT_REG; i++) {
-		 pm2xxx_reg_read(pm2,
+	/* wake up the device */
+	pm_runtime_get_sync(pm2->dev);
+
+	do {
+		for (i = 0; i < PM2XXX_NUM_INT_REG; i++) {
+			pm2xxx_reg_read(pm2,
 				pm2xxx_interrupt_registers[i],
 				&(interrupt->reg[i]));
 
-		if (interrupt->reg[i] > 0)
-			interrupt->handler[i](pm2, interrupt->reg[i]);
-	}
+			if (interrupt->reg[i] > 0)
+				interrupt->handler[i](pm2, interrupt->reg[i]);
+		}
+	} while (gpio_get_value(pm2->pdata->gpio_irq_number) == 0);
+
+	pm_runtime_mark_last_busy(pm2->dev);
+	pm_runtime_put_autosuspend(pm2->dev);
 
 	return IRQ_HANDLED;
 }
@@ -592,6 +616,8 @@ static int pm2xxx_charger_ac_get_property(struct power_supply *psy,
 			val->intval = POWER_SUPPLY_HEALTH_DEAD;
 		else if (pm2->flags.main_thermal_prot)
 			val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;
+		else if (pm2->flags.ovv)
+			val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
 		else
 			val->intval = POWER_SUPPLY_HEALTH_GOOD;
 		break;
@@ -674,10 +700,6 @@ static int pm2xxx_charging_init(struct pm2xxx_charger *pm2)
 	ret = pm2xxx_reg_write(pm2, PM2XXX_BATT_LOW_LEV_COMP_REG,
 		PM2XXX_VBAT_LOW_MONITORING_ENA);
 
-	/* Disable LED */
-	ret = pm2xxx_reg_write(pm2, PM2XXX_LED_CTRL_REG,
-		PM2XXX_LED_SELECT_DIS);
-
 	return ret;
 }
 
@@ -822,10 +844,54 @@ static void pm2xxx_charger_ac_work(struct work_struct *work)
 	sysfs_notify(&pm2->ac_chg.psy.dev->kobj, NULL, "present");
 };
 
+static void pm2xxx_charger_check_hw_failure_work(struct work_struct *work)
+{
+	u8 reg_value;
+
+	struct pm2xxx_charger *pm2 = container_of(work,
+		struct pm2xxx_charger, check_hw_failure_work.work);
+
+	if (pm2->flags.ovv) {
+		pm2xxx_reg_read(pm2, PM2XXX_SRCE_REG_INT4, &reg_value);
+
+		if (!(reg_value & (PM2XXX_INT4_S_ITVPWR1OVV |
+					PM2XXX_INT4_S_ITVPWR2OVV))) {
+			pm2->flags.ovv = false;
+			power_supply_changed(&pm2->ac_chg.psy);
+		}
+	}
+
+	/* If we still have a failure, schedule a new check */
+	if (pm2->flags.ovv) {
+		queue_delayed_work(pm2->charger_wq,
+			&pm2->check_hw_failure_work, round_jiffies(HZ));
+	}
+}
+
 static void pm2xxx_charger_check_main_thermal_prot_work(
 	struct work_struct *work)
 {
-};
+	int ret;
+	u8 val;
+
+	struct pm2xxx_charger *pm2 = container_of(work, struct pm2xxx_charger,
+					check_main_thermal_prot_work);
+
+	/* Check if die temp warning is still active */
+	ret = pm2xxx_reg_read(pm2, PM2XXX_SRCE_REG_INT5, &val);
+	if (ret < 0) {
+		dev_err(pm2->dev, "%s pm2xxx read failed\n", __func__);
+		return;
+	}
+	if (val & (PM2XXX_INT5_S_ITTHERMALWARNINGRISE
+			| PM2XXX_INT5_S_ITTHERMALSHUTDOWNRISE))
+		pm2->flags.main_thermal_prot = true;
+	else if (val & (PM2XXX_INT5_S_ITTHERMALWARNINGFALL
+				| PM2XXX_INT5_S_ITTHERMALSHUTDOWNFALL))
+		pm2->flags.main_thermal_prot = false;
+
+	power_supply_changed(&pm2->ac_chg.psy);
+}
 
 static struct pm2xxx_interrupts pm2xxx_int = {
 	.handler[0] = pm2_int_reg0,
@@ -842,22 +908,92 @@ static struct pm2xxx_irq pm2xxx_charger_irq[] = {
 
 static int pm2xxx_wall_charger_resume(struct i2c_client *i2c_client)
 {
+	struct pm2xxx_charger *pm2;
+
+	pm2 =  (struct pm2xxx_charger *)i2c_get_clientdata(i2c_client);
+	set_lpn_pin(pm2);
+
+	/* If we still have a HW failure, schedule a new check */
+	if (pm2->flags.ovv)
+		queue_delayed_work(pm2->charger_wq,
+				&pm2->check_hw_failure_work, 0);
+
 	return 0;
 }
 
 static int pm2xxx_wall_charger_suspend(struct i2c_client *i2c_client,
 	pm_message_t state)
 {
+	struct pm2xxx_charger *pm2;
+
+	pm2 =  (struct pm2xxx_charger *)i2c_get_clientdata(i2c_client);
+	clear_lpn_pin(pm2);
+
+	/* Cancel any pending HW failure check */
+	if (delayed_work_pending(&pm2->check_hw_failure_work))
+		cancel_delayed_work(&pm2->check_hw_failure_work);
+
+	flush_work(&pm2->ac_work);
+	flush_work(&pm2->check_main_thermal_prot_work);
+
 	return 0;
 }
 
-static int __devinit pm2xxx_wall_charger_probe(struct i2c_client *i2c_client,
+#ifdef CONFIG_PM
+static int  pm2xxx_runtime_suspend(struct device *dev)
+{
+	struct i2c_client *pm2xxx_i2c_client = to_i2c_client(dev);
+	struct pm2xxx_charger *pm2;
+	int ret = 0;
+
+	pm2 = (struct pm2xxx_charger *)i2c_get_clientdata(pm2xxx_i2c_client);
+	if (!pm2) {
+		dev_err(pm2->dev, "no pm2xxx_charger data supplied\n");
+		ret = -EINVAL;
+		return ret;
+	}
+
+	clear_lpn_pin(pm2);
+
+	return ret;
+}
+
+static int  pm2xxx_runtime_resume(struct device *dev)
+{
+	struct i2c_client *pm2xxx_i2c_client = to_i2c_client(dev);
+	struct pm2xxx_charger *pm2;
+	int ret = 0;
+
+	pm2 = (struct pm2xxx_charger *)i2c_get_clientdata(pm2xxx_i2c_client);
+	if (!pm2) {
+		dev_err(pm2->dev, "no pm2xxx_charger data supplied\n");
+		ret = -EINVAL;
+		return ret;
+	}
+
+	if (gpio_is_valid(pm2->lpn_pin) && gpio_get_value(pm2->lpn_pin) == 0)
+		set_lpn_pin(pm2);
+
+	return ret;
+}
+
+static const struct dev_pm_ops pm2xxx_pm_ops = {
+	.runtime_suspend = pm2xxx_runtime_suspend,
+	.runtime_resume = pm2xxx_runtime_resume,
+};
+#define  PM2XXX_PM_OPS (&pm2xxx_pm_ops)
+#else
+#define  PM2XXX_PM_OPS  NULL
+#endif
+
+static int pm2xxx_wall_charger_probe(struct i2c_client *i2c_client,
 		const struct i2c_device_id *id)
 {
 	struct pm2xxx_platform_data *pl_data = i2c_client->dev.platform_data;
 	struct pm2xxx_charger *pm2;
 	int ret = 0;
 	u8 val;
+	int i;
 
 	pm2 = kzalloc(sizeof(struct pm2xxx_charger), GFP_KERNEL);
 	if (!pm2) {
@@ -867,7 +1003,6 @@ static int __devinit pm2xxx_wall_charger_probe(struct i2c_client *i2c_client,
 
 	/* get parent data */
 	pm2->dev = &i2c_client->dev;
-	pm2->gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
 
 	pm2->pm2_int = &pm2xxx_int;
 
@@ -889,14 +1024,6 @@ static int __devinit pm2xxx_wall_charger_probe(struct i2c_client *i2c_client,
 
 	pm2->bat = pl_data->battery;
 
-	/*get lpn GPIO from platform data*/
-	if (!pm2->pdata->lpn_gpio) {
-		dev_err(pm2->dev, "no lpn gpio data supplied\n");
-		ret = -EINVAL;
-		goto free_device_info;
-	}
-	pm2->lpn_pin = pm2->pdata->lpn_gpio;
-
 	if (!i2c_check_functionality(i2c_client->adapter,
 			I2C_FUNC_SMBUS_BYTE_DATA |
 			I2C_FUNC_SMBUS_READ_WORD_DATA)) {
@@ -945,6 +1072,10 @@ static int __devinit pm2xxx_wall_charger_probe(struct i2c_client *i2c_client,
 	INIT_WORK(&pm2->check_main_thermal_prot_work,
 		pm2xxx_charger_check_main_thermal_prot_work);
 
+	/* Init work for HW failure check */
+	INIT_DEFERRABLE_WORK(&pm2->check_hw_failure_work,
+		pm2xxx_charger_check_hw_failure_work);
+
 	/*
 	 * VDD ADC supply needs to be enabled from this driver when there
 	 * is a charger connected to avoid erroneous BTEMP_HIGH/LOW
@@ -965,40 +1096,72 @@ static int __devinit pm2xxx_wall_charger_probe(struct i2c_client *i2c_client,
 	}
 
 	/* Register interrupts */
-	ret = request_threaded_irq(pm2->pdata->irq_number, NULL,
+	ret = request_threaded_irq(gpio_to_irq(pm2->pdata->gpio_irq_number),
+				NULL,
 				pm2xxx_charger_irq[0].isr,
 				pm2->pdata->irq_type,
 				pm2xxx_charger_irq[0].name, pm2);
 
 	if (ret != 0) {
 		dev_err(pm2->dev, "failed to request %s IRQ %d: %d\n",
-		pm2xxx_charger_irq[0].name, pm2->pdata->irq_number, ret);
+		pm2xxx_charger_irq[0].name,
+			gpio_to_irq(pm2->pdata->gpio_irq_number), ret);
 		goto unregister_pm2xxx_charger;
 	}
 
-	/*Initialize lock*/
-	mutex_init(&pm2->lock);
+	ret = pm_runtime_set_active(pm2->dev);
+	if (ret)
+		dev_err(pm2->dev, "set active Error\n");
 
-	/*
-	 * Charger detection mechanism requires pulling up the LPN pin
-	 * while i2c communication if Charger is not connected
-	 * LPN pin of PM2301 is GPIO60 of AB9540
-	 */
-	ret = gpio_request(pm2->lpn_pin, "pm2301_lpm_gpio");
-	if (ret < 0) {
-		dev_err(pm2->dev, "pm2301_lpm_gpio request failed\n");
-		goto unregister_pm2xxx_charger;
+	pm_runtime_enable(pm2->dev);
+	pm_runtime_set_autosuspend_delay(pm2->dev, PM2XXX_AUTOSUSPEND_DELAY);
+	pm_runtime_use_autosuspend(pm2->dev);
+	pm_runtime_resume(pm2->dev);
+
+	/* pm interrupt can wake up system */
+	ret = enable_irq_wake(gpio_to_irq(pm2->pdata->gpio_irq_number));
+	if (ret) {
+		dev_err(pm2->dev, "failed to set irq wake\n");
+		goto unregister_pm2xxx_interrupt;
 	}
-	ret = gpio_direction_output(pm2->lpn_pin, 0);
-	if (ret < 0) {
-		dev_err(pm2->dev, "pm2301_lpm_gpio direction failed\n");
-		goto free_gpio;
+
+	mutex_init(&pm2->lock);
+
+	if (gpio_is_valid(pm2->pdata->lpn_gpio)) {
+		/* get lpn GPIO from platform data */
+		pm2->lpn_pin = pm2->pdata->lpn_gpio;
+
+		/*
+		 * Charger detection mechanism requires pulling up the LPN pin
+		 * while i2c communication if Charger is not connected
+		 * LPN pin of PM2301 is GPIO60 of AB9540
+		 */
+		ret = gpio_request(pm2->lpn_pin, "pm2301_lpm_gpio");
+
+		if (ret < 0) {
+			dev_err(pm2->dev, "pm2301_lpm_gpio request failed\n");
+			goto disable_pm2_irq_wake;
+		}
+		ret = gpio_direction_output(pm2->lpn_pin, 0);
+		if (ret < 0) {
+			dev_err(pm2->dev, "pm2301_lpm_gpio direction failed\n");
+			goto free_gpio;
+		}
+		set_lpn_pin(pm2);
 	}
 
+	/* read  interrupt registers */
+	for (i = 0; i < PM2XXX_NUM_INT_REG; i++)
+		pm2xxx_reg_read(pm2,
+			pm2xxx_interrupt_registers[i],
+			&val);
+
 	ret = pm2xxx_charger_detection(pm2, &val);
 
 	if ((ret == 0) && val) {
 		pm2->ac.charger_connected = 1;
+		ab8500_override_turn_on_stat(~AB8500_POW_KEY_1_ON,
+					     AB8500_MAIN_CH_DET);
 		pm2->ac_conn = true;
 		power_supply_changed(&pm2->ac_chg.psy);
 		sysfs_notify(&pm2->ac_chg.psy.dev->kobj, NULL, "present");
@@ -1007,7 +1170,13 @@ static int __devinit pm2xxx_wall_charger_probe(struct i2c_client *i2c_client,
 	return 0;
 
 free_gpio:
-	gpio_free(pm2->lpn_pin);
+	if (gpio_is_valid(pm2->lpn_pin))
+		gpio_free(pm2->lpn_pin);
+disable_pm2_irq_wake:
+	disable_irq_wake(gpio_to_irq(pm2->pdata->gpio_irq_number));
+unregister_pm2xxx_interrupt:
+	/* disable interrupt */
+	free_irq(gpio_to_irq(pm2->pdata->gpio_irq_number), pm2);
 unregister_pm2xxx_charger:
 	/* unregister power supply */
 	power_supply_unregister(&pm2->ac_chg.psy);
@@ -1018,18 +1187,24 @@ free_charger_wq:
 	destroy_workqueue(pm2->charger_wq);
 free_device_info:
 	kfree(pm2);
+
 	return ret;
 }
 
-static int __devexit pm2xxx_wall_charger_remove(struct i2c_client *i2c_client)
+static int pm2xxx_wall_charger_remove(struct i2c_client *i2c_client)
 {
 	struct pm2xxx_charger *pm2 = i2c_get_clientdata(i2c_client);
 
+	/* Disable pm_runtime */
+	pm_runtime_disable(pm2->dev);
 	/* Disable AC charging */
 	pm2xxx_charger_ac_en(&pm2->ac_chg, false, 0, 0);
 
+	/* Disable wake by pm interrupt */
+	disable_irq_wake(gpio_to_irq(pm2->pdata->gpio_irq_number));
+
 	/* Disable interrupts */
-	free_irq(pm2->pdata->irq_number, pm2);
+	free_irq(gpio_to_irq(pm2->pdata->gpio_irq_number), pm2);
 
 	/* Delete the work queue */
 	destroy_workqueue(pm2->charger_wq);
@@ -1041,8 +1216,8 @@ static int __devexit pm2xxx_wall_charger_remove(struct i2c_client *i2c_client)
 
 	power_supply_unregister(&pm2->ac_chg.psy);
 
-	/*Free GPIO60*/
-	gpio_free(pm2->lpn_pin);
+	if (gpio_is_valid(pm2->lpn_pin))
+		gpio_free(pm2->lpn_pin);
 
 	kfree(pm2);
 
@@ -1058,12 +1233,13 @@ MODULE_DEVICE_TABLE(i2c, pm2xxx_id);
 
 static struct i2c_driver pm2xxx_charger_driver = {
 	.probe = pm2xxx_wall_charger_probe,
-	.remove = __devexit_p(pm2xxx_wall_charger_remove),
+	.remove = pm2xxx_wall_charger_remove,
 	.suspend = pm2xxx_wall_charger_suspend,
 	.resume = pm2xxx_wall_charger_resume,
 	.driver = {
 		.name = "pm2xxx-wall_charger",
 		.owner = THIS_MODULE,
+		.pm = PM2XXX_PM_OPS,
 	},
 	.id_table = pm2xxx_id,
 };
@@ -1078,11 +1254,10 @@ static void __exit pm2xxx_charger_exit(void)
 	i2c_del_driver(&pm2xxx_charger_driver);
 }
 
-subsys_initcall_sync(pm2xxx_charger_init);
+device_initcall_sync(pm2xxx_charger_init);
 module_exit(pm2xxx_charger_exit);
 
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Rajkumar kasirajan, Olivier Launay");
 MODULE_ALIAS("platform:pm2xxx-charger");
 MODULE_DESCRIPTION("PM2xxx charger management driver");
-
diff --git a/drivers/power/pm2301_charger.h b/drivers/power/pm2301_charger.h
index e6319cd..8ce3cc0 100644
--- a/drivers/power/pm2301_charger.h
+++ b/drivers/power/pm2301_charger.h
@@ -9,27 +9,6 @@
 #ifndef PM2301_CHARGER_H
 #define PM2301_CHARGER_H
 
-#define MAIN_WDOG_ENA			0x01
-#define MAIN_WDOG_KICK			0x02
-#define MAIN_WDOG_DIS			0x00
-#define CHARG_WD_KICK			0x01
-#define MAIN_CH_ENA			0x01
-#define MAIN_CH_NO_OVERSHOOT_ENA_N	0x02
-#define MAIN_CH_DET			0x01
-#define MAIN_CH_CV_ON			0x04
-#define OTP_ENABLE_WD			0x01
-
-#define MAIN_CH_INPUT_CURR_SHIFT	4
-
-#define LED_INDICATOR_PWM_ENA		0x01
-#define LED_INDICATOR_PWM_DIS		0x00
-#define LED_IND_CUR_5MA			0x04
-#define LED_INDICATOR_PWM_DUTY_252_256	0xBF
-
-/* HW failure constants */
-#define MAIN_CH_TH_PROT			0x02
-#define MAIN_CH_NOK			0x01
-
 /* Watchdog timeout constant */
 #define WD_TIMER			0x30 /* 4min */
 #define WD_KICK_INTERVAL		(30 * HZ)
@@ -495,7 +474,6 @@ struct pm2xxx_charger {
 	int failure_input_ovv;
 	unsigned int lpn_pin;
 	struct pm2xxx_interrupts *pm2_int;
-	struct ab8500_gpadc *gpadc;
 	struct regulator *regu;
 	struct pm2xxx_bm_data *bat;
 	struct mutex lock;
@@ -506,6 +484,7 @@ struct pm2xxx_charger {
 	struct delayed_work check_vbat_work;
 	struct work_struct ac_work;
 	struct work_struct check_main_thermal_prot_work;
+	struct delayed_work check_hw_failure_work;
 	struct ux500_charger ac_chg;
 	struct pm2xxx_charger_event_flags flags;
 };
diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
index 1ae65b8..349e9ae 100644
--- a/drivers/power/reset/Kconfig
+++ b/drivers/power/reset/Kconfig
@@ -30,3 +30,10 @@ config POWER_RESET_RESTART
 	  Some boards don't actually have the ability to power off.
 	  Instead they restart, and u-boot holds the SoC until the
 	  user presses a key. u-boot then boots into Linux.
+
+config POWER_RESET_VEXPRESS
+	bool
+	depends on POWER_RESET
+	help
+	  Power off and reset support for the ARM Ltd. Versatile
+	  Express boards.
diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile
index 0f317f5..372807f 100644
--- a/drivers/power/reset/Makefile
+++ b/drivers/power/reset/Makefile
@@ -1,3 +1,4 @@
 obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o
 obj-$(CONFIG_POWER_RESET_QNAP) += qnap-poweroff.o
-obj-$(CONFIG_POWER_RESET_RESTART) += restart-poweroff.o
\ No newline at end of file
+obj-$(CONFIG_POWER_RESET_RESTART) += restart-poweroff.o
+obj-$(CONFIG_POWER_RESET_VEXPRESS) += vexpress-poweroff.o
diff --git a/drivers/power/reset/vexpress-poweroff.c b/drivers/power/reset/vexpress-poweroff.c
new file mode 100644
index 0000000..469e696
--- /dev/null
+++ b/drivers/power/reset/vexpress-poweroff.c
@@ -0,0 +1,146 @@
+/*
+ * This program is free software; you can 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 (C) 2012 ARM Limited
+ */
+
+#include <linux/jiffies.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/stat.h>
+#include <linux/vexpress.h>
+
+#include <asm/system_misc.h>
+
+static void vexpress_reset_do(struct device *dev, const char *what)
+{
+	int err = -ENOENT;
+	struct vexpress_config_func *func =
+			vexpress_config_func_get_by_dev(dev);
+
+	if (func) {
+		unsigned long timeout;
+
+		err = vexpress_config_write(func, 0, 0);
+
+		timeout = jiffies + HZ;
+		while (time_before(jiffies, timeout))
+			cpu_relax();
+	}
+
+	dev_emerg(dev, "Unable to %s (%d)\n", what, err);
+}
+
+static struct device *vexpress_power_off_device;
+
+static void vexpress_power_off(void)
+{
+	vexpress_reset_do(vexpress_power_off_device, "power off");
+}
+
+static struct device *vexpress_restart_device;
+
+static void vexpress_restart(char str, const char *cmd)
+{
+	vexpress_reset_do(vexpress_restart_device, "restart");
+}
+
+static ssize_t vexpress_reset_active_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%d\n", vexpress_restart_device == dev);
+}
+
+static ssize_t vexpress_reset_active_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	long value;
+	int err = kstrtol(buf, 0, &value);
+
+	if (!err && value)
+		vexpress_restart_device = dev;
+
+	return err ? err : count;
+}
+
+DEVICE_ATTR(active, S_IRUGO | S_IWUSR, vexpress_reset_active_show,
+		vexpress_reset_active_store);
+
+
+enum vexpress_reset_func { FUNC_RESET, FUNC_SHUTDOWN, FUNC_REBOOT };
+
+static struct of_device_id vexpress_reset_of_match[] = {
+	{
+		.compatible = "arm,vexpress-reset",
+		.data = (void *)FUNC_RESET,
+	}, {
+		.compatible = "arm,vexpress-shutdown",
+		.data = (void *)FUNC_SHUTDOWN
+	}, {
+		.compatible = "arm,vexpress-reboot",
+		.data = (void *)FUNC_REBOOT
+	},
+	{}
+};
+
+static int vexpress_reset_probe(struct platform_device *pdev)
+{
+	enum vexpress_reset_func func;
+	const struct of_device_id *match =
+			of_match_device(vexpress_reset_of_match, &pdev->dev);
+
+	if (match)
+		func = (enum vexpress_reset_func)match->data;
+	else
+		func = pdev->id_entry->driver_data;
+
+	switch (func) {
+	case FUNC_SHUTDOWN:
+		vexpress_power_off_device = &pdev->dev;
+		pm_power_off = vexpress_power_off;
+		break;
+	case FUNC_RESET:
+		if (!vexpress_restart_device)
+			vexpress_restart_device = &pdev->dev;
+		arm_pm_restart = vexpress_restart;
+		device_create_file(&pdev->dev, &dev_attr_active);
+		break;
+	case FUNC_REBOOT:
+		vexpress_restart_device = &pdev->dev;
+		arm_pm_restart = vexpress_restart;
+		device_create_file(&pdev->dev, &dev_attr_active);
+		break;
+	};
+
+	return 0;
+}
+
+static const struct platform_device_id vexpress_reset_id_table[] = {
+	{ .name = "vexpress-reset", .driver_data = FUNC_RESET, },
+	{ .name = "vexpress-shutdown", .driver_data = FUNC_SHUTDOWN, },
+	{ .name = "vexpress-reboot", .driver_data = FUNC_REBOOT, },
+	{}
+};
+
+static struct platform_driver vexpress_reset_driver = {
+	.probe = vexpress_reset_probe,
+	.driver = {
+		.name = "vexpress-reset",
+		.of_match_table = vexpress_reset_of_match,
+	},
+	.id_table = vexpress_reset_id_table,
+};
+
+static int __init vexpress_reset_init(void)
+{
+	return platform_driver_register(&vexpress_reset_driver);
+}
+device_initcall(vexpress_reset_init);
diff --git a/drivers/power/rx51_battery.c b/drivers/power/rx51_battery.c
index 8208888..f9dc9ff 100644
--- a/drivers/power/rx51_battery.c
+++ b/drivers/power/rx51_battery.c
@@ -202,7 +202,7 @@ static int rx51_battery_probe(struct platform_device *pdev)
 	struct rx51_device_info *di;
 	int ret;
 
-	di = kzalloc(sizeof(*di), GFP_KERNEL);
+	di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL);
 	if (!di)
 		return -ENOMEM;
 
@@ -217,7 +217,6 @@ static int rx51_battery_probe(struct platform_device *pdev)
 	ret = power_supply_register(di->dev, &di->bat);
 	if (ret) {
 		platform_set_drvdata(pdev, NULL);
-		kfree(di);
 		return ret;
 	}
 
@@ -230,7 +229,6 @@ static int rx51_battery_remove(struct platform_device *pdev)
 
 	power_supply_unregister(&di->bat);
 	platform_set_drvdata(pdev, NULL);
-	kfree(di);
 
 	return 0;
 }
diff --git a/drivers/power/s3c_adc_battery.c b/drivers/power/s3c_adc_battery.c
index d2ca989..5948ce0 100644
--- a/drivers/power/s3c_adc_battery.c
+++ b/drivers/power/s3c_adc_battery.c
@@ -145,14 +145,17 @@ static int s3c_adc_bat_get_property(struct power_supply *psy,
 
 	int new_level;
 	int full_volt;
-	const struct s3c_adc_bat_thresh *lut = bat->pdata->lut_noac;
-	unsigned int lut_size = bat->pdata->lut_noac_cnt;
+	const struct s3c_adc_bat_thresh *lut;
+	unsigned int lut_size;
 
 	if (!bat) {
 		dev_err(psy->dev, "no battery infos ?!\n");
 		return -EINVAL;
 	}
 
+	lut = bat->pdata->lut_noac;
+	lut_size = bat->pdata->lut_noac_cnt;
+
 	if (bat->volt_value < 0 || bat->cur_value < 0 ||
 		jiffies_to_msecs(jiffies - bat->timestamp) >
 			BAT_POLL_INTERVAL) {
diff --git a/drivers/power/sbs-battery.c b/drivers/power/sbs-battery.c
index 3960f0b..c8c78a7 100644
--- a/drivers/power/sbs-battery.c
+++ b/drivers/power/sbs-battery.c
@@ -27,6 +27,7 @@
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/gpio.h>
+#include <linux/of.h>
 
 #include <linux/power/sbs-battery.h>
 
@@ -667,7 +668,6 @@ of_out:
 	return pdata;
 }
 #else
-#define sbs_dt_ids NULL
 static struct sbs_platform_data *sbs_of_populate_pdata(
 	struct i2c_client *client)
 {
@@ -820,10 +820,11 @@ static int sbs_remove(struct i2c_client *client)
 	return 0;
 }
 
-#if defined CONFIG_PM
-static int sbs_suspend(struct i2c_client *client,
-	pm_message_t state)
+#if defined CONFIG_PM_SLEEP
+
+static int sbs_suspend(struct device *dev)
 {
+	struct i2c_client *client = to_i2c_client(dev);
 	struct sbs_info *chip = i2c_get_clientdata(client);
 	s32 ret;
 
@@ -838,11 +839,13 @@ static int sbs_suspend(struct i2c_client *client,
 
 	return 0;
 }
+
+static SIMPLE_DEV_PM_OPS(sbs_pm_ops, sbs_suspend, NULL);
+#define SBS_PM_OPS (&sbs_pm_ops)
+
 #else
-#define sbs_suspend		NULL
+#define SBS_PM_OPS NULL
 #endif
-/* any smbus transaction will wake up sbs */
-#define sbs_resume		NULL
 
 static const struct i2c_device_id sbs_id[] = {
 	{ "bq20z75", 0 },
@@ -854,12 +857,11 @@ MODULE_DEVICE_TABLE(i2c, sbs_id);
 static struct i2c_driver sbs_battery_driver = {
 	.probe		= sbs_probe,
 	.remove		= sbs_remove,
-	.suspend	= sbs_suspend,
-	.resume		= sbs_resume,
 	.id_table	= sbs_id,
 	.driver = {
 		.name	= "sbs-battery",
-		.of_match_table = sbs_dt_ids,
+		.of_match_table = of_match_ptr(sbs_dt_ids),
+		.pm	= SBS_PM_OPS,
 	},
 };
 module_i2c_driver(sbs_battery_driver);
diff --git a/drivers/power/test_power.c b/drivers/power/test_power.c
index b99a452..0152f35 100644
--- a/drivers/power/test_power.c
+++ b/drivers/power/test_power.c
@@ -30,6 +30,8 @@ static int battery_technology		= POWER_SUPPLY_TECHNOLOGY_LION;
 static int battery_capacity		= 50;
 static int battery_voltage		= 3300;
 
+static bool module_initialized;
+
 static int test_power_get_ac_property(struct power_supply *psy,
 				      enum power_supply_property psp,
 				      union power_supply_propval *val)
@@ -185,6 +187,7 @@ static int __init test_power_init(void)
 		}
 	}
 
+	module_initialized = true;
 	return 0;
 failed:
 	while (--i >= 0)
@@ -209,6 +212,8 @@ static void __exit test_power_exit(void)
 
 	for (i = 0; i < ARRAY_SIZE(test_power_supplies); i++)
 		power_supply_unregister(&test_power_supplies[i]);
+
+	module_initialized = false;
 }
 module_exit(test_power_exit);
 
@@ -221,8 +226,8 @@ struct battery_property_map {
 };
 
 static struct battery_property_map map_ac_online[] = {
-	{ 0,  "on"  },
-	{ 1,  "off" },
+	{ 0,  "off"  },
+	{ 1,  "on" },
 	{ -1, NULL  },
 };
 
@@ -295,10 +300,16 @@ static const char *map_get_key(struct battery_property_map *map, int value,
 	return def_key;
 }
 
+static inline void signal_power_supply_changed(struct power_supply *psy)
+{
+	if (module_initialized)
+		power_supply_changed(psy);
+}
+
 static int param_set_ac_online(const char *key, const struct kernel_param *kp)
 {
 	ac_online = map_get_value(map_ac_online, key, ac_online);
-	power_supply_changed(&test_power_supplies[0]);
+	signal_power_supply_changed(&test_power_supplies[0]);
 	return 0;
 }
 
@@ -311,7 +322,7 @@ static int param_get_ac_online(char *buffer, const struct kernel_param *kp)
 static int param_set_usb_online(const char *key, const struct kernel_param *kp)
 {
 	usb_online = map_get_value(map_ac_online, key, usb_online);
-	power_supply_changed(&test_power_supplies[2]);
+	signal_power_supply_changed(&test_power_supplies[2]);
 	return 0;
 }
 
@@ -325,7 +336,7 @@ static int param_set_battery_status(const char *key,
 					const struct kernel_param *kp)
 {
 	battery_status = map_get_value(map_status, key, battery_status);
-	power_supply_changed(&test_power_supplies[1]);
+	signal_power_supply_changed(&test_power_supplies[1]);
 	return 0;
 }
 
@@ -339,7 +350,7 @@ static int param_set_battery_health(const char *key,
 					const struct kernel_param *kp)
 {
 	battery_health = map_get_value(map_health, key, battery_health);
-	power_supply_changed(&test_power_supplies[1]);
+	signal_power_supply_changed(&test_power_supplies[1]);
 	return 0;
 }
 
@@ -353,7 +364,7 @@ static int param_set_battery_present(const char *key,
 					const struct kernel_param *kp)
 {
 	battery_present = map_get_value(map_present, key, battery_present);
-	power_supply_changed(&test_power_supplies[0]);
+	signal_power_supply_changed(&test_power_supplies[0]);
 	return 0;
 }
 
@@ -369,7 +380,7 @@ static int param_set_battery_technology(const char *key,
 {
 	battery_technology = map_get_value(map_technology, key,
 						battery_technology);
-	power_supply_changed(&test_power_supplies[1]);
+	signal_power_supply_changed(&test_power_supplies[1]);
 	return 0;
 }
 
@@ -390,7 +401,7 @@ static int param_set_battery_capacity(const char *key,
 		return -EINVAL;
 
 	battery_capacity = tmp;
-	power_supply_changed(&test_power_supplies[1]);
+	signal_power_supply_changed(&test_power_supplies[1]);
 	return 0;
 }
 
@@ -405,7 +416,7 @@ static int param_set_battery_voltage(const char *key,
 		return -EINVAL;
 
 	battery_voltage = tmp;
-	power_supply_changed(&test_power_supplies[1]);
+	signal_power_supply_changed(&test_power_supplies[1]);
 	return 0;
 }
 
diff --git a/drivers/power/tps65090-charger.c b/drivers/power/tps65090-charger.c
new file mode 100644
index 0000000..9fbca31
--- /dev/null
+++ b/drivers/power/tps65090-charger.c
@@ -0,0 +1,320 @@
+/*
+ * Battery charger driver for TI's tps65090
+ *
+ * Copyright (c) 2013, NVIDIA 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, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/mfd/tps65090.h>
+
+#define TPS65090_REG_INTR_STS	0x00
+#define TPS65090_REG_CG_CTRL0	0x04
+#define TPS65090_REG_CG_CTRL1	0x05
+#define TPS65090_REG_CG_CTRL2	0x06
+#define TPS65090_REG_CG_CTRL3	0x07
+#define TPS65090_REG_CG_CTRL4	0x08
+#define TPS65090_REG_CG_CTRL5	0x09
+#define TPS65090_REG_CG_STATUS1	0x0a
+#define TPS65090_REG_CG_STATUS2	0x0b
+
+#define TPS65090_CHARGER_ENABLE	BIT(0)
+#define TPS65090_VACG		BIT(1)
+#define TPS65090_NOITERM	BIT(5)
+
+struct tps65090_charger {
+	struct	device	*dev;
+	int	ac_online;
+	int	prev_ac_online;
+	int	irq;
+	struct power_supply	ac;
+	struct tps65090_platform_data *pdata;
+};
+
+static enum power_supply_property tps65090_ac_props[] = {
+	POWER_SUPPLY_PROP_ONLINE,
+};
+
+static int tps65090_low_chrg_current(struct tps65090_charger *charger)
+{
+	int ret;
+
+	ret = tps65090_write(charger->dev->parent, TPS65090_REG_CG_CTRL5,
+			TPS65090_NOITERM);
+	if (ret < 0) {
+		dev_err(charger->dev, "%s(): error reading in register 0x%x\n",
+			__func__, TPS65090_REG_CG_CTRL5);
+		return ret;
+	}
+	return 0;
+}
+
+static int tps65090_enable_charging(struct tps65090_charger *charger,
+	uint8_t enable)
+{
+	int ret;
+	uint8_t ctrl0 = 0;
+
+	ret = tps65090_read(charger->dev->parent, TPS65090_REG_CG_CTRL0,
+			    &ctrl0);
+	if (ret < 0) {
+		dev_err(charger->dev, "%s(): error reading in register 0x%x\n",
+				__func__, TPS65090_REG_CG_CTRL0);
+		return ret;
+	}
+
+	ret = tps65090_write(charger->dev->parent, TPS65090_REG_CG_CTRL0,
+				(ctrl0 | TPS65090_CHARGER_ENABLE));
+	if (ret < 0) {
+		dev_err(charger->dev, "%s(): error reading in register 0x%x\n",
+				__func__, TPS65090_REG_CG_CTRL0);
+		return ret;
+	}
+	return 0;
+}
+
+static int tps65090_config_charger(struct tps65090_charger *charger)
+{
+	int ret;
+
+	if (charger->pdata->enable_low_current_chrg) {
+		ret = tps65090_low_chrg_current(charger);
+		if (ret < 0) {
+			dev_err(charger->dev,
+				"error configuring low charge current\n");
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static int tps65090_ac_get_property(struct power_supply *psy,
+			enum power_supply_property psp,
+			union power_supply_propval *val)
+{
+	struct tps65090_charger *charger = container_of(psy,
+					struct tps65090_charger, ac);
+
+	if (psp == POWER_SUPPLY_PROP_ONLINE) {
+		val->intval = charger->ac_online;
+		charger->prev_ac_online = charger->ac_online;
+		return 0;
+	}
+	return -EINVAL;
+}
+
+static irqreturn_t tps65090_charger_isr(int irq, void *dev_id)
+{
+	struct tps65090_charger *charger = dev_id;
+	int ret;
+	uint8_t status1 = 0;
+	uint8_t intrsts = 0;
+
+	ret = tps65090_read(charger->dev->parent, TPS65090_REG_CG_STATUS1,
+			    &status1);
+	if (ret < 0) {
+		dev_err(charger->dev, "%s(): Error in reading reg 0x%x\n",
+				__func__, TPS65090_REG_CG_STATUS1);
+		return IRQ_HANDLED;
+	}
+	msleep(75);
+	ret = tps65090_read(charger->dev->parent, TPS65090_REG_INTR_STS,
+			    &intrsts);
+	if (ret < 0) {
+		dev_err(charger->dev, "%s(): Error in reading reg 0x%x\n",
+				__func__, TPS65090_REG_INTR_STS);
+		return IRQ_HANDLED;
+	}
+
+	if (intrsts & TPS65090_VACG) {
+		ret = tps65090_enable_charging(charger, 1);
+		if (ret < 0)
+			return IRQ_HANDLED;
+		charger->ac_online = 1;
+	} else {
+		charger->ac_online = 0;
+	}
+
+	if (charger->prev_ac_online != charger->ac_online)
+		power_supply_changed(&charger->ac);
+
+	return IRQ_HANDLED;
+}
+
+#if defined(CONFIG_OF)
+
+#include <linux/of_device.h>
+
+static struct tps65090_platform_data *
+		tps65090_parse_dt_charger_data(struct platform_device *pdev)
+{
+	struct tps65090_platform_data *pdata;
+	struct device_node *np = pdev->dev.of_node;
+	unsigned int prop;
+
+	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata) {
+		dev_err(&pdev->dev, "Memory alloc for tps65090_pdata failed\n");
+		return NULL;
+	}
+
+	prop = of_property_read_bool(np, "ti,enable-low-current-chrg");
+	pdata->enable_low_current_chrg = prop;
+
+	pdata->irq_base = -1;
+
+	return pdata;
+
+}
+#else
+static struct tps65090_platform_data *
+		tps65090_parse_dt_charger_data(struct platform_device *pdev)
+{
+	return NULL;
+}
+#endif
+
+static int tps65090_charger_probe(struct platform_device *pdev)
+{
+	struct tps65090_charger *cdata;
+	struct tps65090_platform_data *pdata;
+	uint8_t status1 = 0;
+	int ret;
+	int irq;
+
+	pdata = dev_get_platdata(pdev->dev.parent);
+
+	if (!pdata && pdev->dev.of_node)
+		pdata = tps65090_parse_dt_charger_data(pdev);
+
+	if (!pdata) {
+		dev_err(&pdev->dev, "%s():no platform data available\n",
+				__func__);
+		return -ENODEV;
+	}
+
+	cdata = devm_kzalloc(&pdev->dev, sizeof(*cdata), GFP_KERNEL);
+	if (!cdata) {
+		dev_err(&pdev->dev, "failed to allocate memory status\n");
+		return -ENOMEM;
+	}
+
+	dev_set_drvdata(&pdev->dev, cdata);
+
+	cdata->dev			= &pdev->dev;
+	cdata->pdata			= pdata;
+
+	cdata->ac.name			= "tps65090-ac";
+	cdata->ac.type			= POWER_SUPPLY_TYPE_MAINS;
+	cdata->ac.get_property		= tps65090_ac_get_property;
+	cdata->ac.properties		= tps65090_ac_props;
+	cdata->ac.num_properties	= ARRAY_SIZE(tps65090_ac_props);
+	cdata->ac.supplied_to		= pdata->supplied_to;
+	cdata->ac.num_supplicants	= pdata->num_supplicants;
+
+	ret = power_supply_register(&pdev->dev, &cdata->ac);
+	if (ret) {
+		dev_err(&pdev->dev, "failed: power supply register\n");
+		return ret;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq <= 0) {
+		dev_warn(&pdev->dev, "Unable to get charger irq = %d\n", irq);
+		ret = irq;
+		goto fail_unregister_supply;
+	}
+
+	cdata->irq = irq;
+
+	ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+		tps65090_charger_isr, 0, "tps65090-charger", cdata);
+	if (ret) {
+		dev_err(cdata->dev, "Unable to register irq %d err %d\n", irq,
+			ret);
+		goto fail_free_irq;
+	}
+
+	ret = tps65090_config_charger(cdata);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "charger config failed, err %d\n", ret);
+		goto fail_free_irq;
+	}
+
+	/* Check for charger presence */
+	ret = tps65090_read(cdata->dev->parent, TPS65090_REG_CG_STATUS1,
+			&status1);
+	if (ret < 0) {
+		dev_err(cdata->dev, "%s(): Error in reading reg 0x%x", __func__,
+			TPS65090_REG_CG_STATUS1);
+		goto fail_free_irq;
+	}
+
+	if (status1 != 0) {
+		ret = tps65090_enable_charging(cdata, 1);
+		if (ret < 0) {
+			dev_err(cdata->dev, "error enabling charger\n");
+			goto fail_free_irq;
+		}
+		cdata->ac_online = 1;
+		power_supply_changed(&cdata->ac);
+	}
+
+	return 0;
+
+fail_free_irq:
+	devm_free_irq(cdata->dev, irq, cdata);
+fail_unregister_supply:
+	power_supply_unregister(&cdata->ac);
+
+	return ret;
+}
+
+static int tps65090_charger_remove(struct platform_device *pdev)
+{
+	struct tps65090_charger *cdata = dev_get_drvdata(&pdev->dev);
+
+	devm_free_irq(cdata->dev, cdata->irq, cdata);
+	power_supply_unregister(&cdata->ac);
+
+	return 0;
+}
+
+static struct of_device_id of_tps65090_charger_match[] = {
+	{ .compatible = "ti,tps65090-charger", },
+	{ /* end */ }
+};
+
+static struct platform_driver tps65090_charger_driver = {
+	.driver	= {
+		.name	= "tps65090-charger",
+		.of_match_table = of_tps65090_charger_match,
+		.owner	= THIS_MODULE,
+	},
+	.probe	= tps65090_charger_probe,
+	.remove = tps65090_charger_remove,
+};
+module_platform_driver(tps65090_charger_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Syed Rafiuddin <srafiuddin@nvidia.com>");
+MODULE_DESCRIPTION("tps65090 battery charger driver");
diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c
index a69d0d1..bed4581 100644
--- a/drivers/power/twl4030_charger.c
+++ b/drivers/power/twl4030_charger.c
@@ -636,17 +636,7 @@ static struct platform_driver twl4030_bci_driver = {
 	.remove	= __exit_p(twl4030_bci_remove),
 };
 
-static int __init twl4030_bci_init(void)
-{
-	return platform_driver_probe(&twl4030_bci_driver, twl4030_bci_probe);
-}
-module_init(twl4030_bci_init);
-
-static void __exit twl4030_bci_exit(void)
-{
-	platform_driver_unregister(&twl4030_bci_driver);
-}
-module_exit(twl4030_bci_exit);
+module_platform_driver_probe(twl4030_bci_driver, twl4030_bci_probe);
 
 MODULE_AUTHOR("Gražvydas Ignotas");
 MODULE_DESCRIPTION("TWL4030 Battery Charger Interface driver");
diff --git a/drivers/power/wm831x_backup.c b/drivers/power/wm831x_backup.c
index d9cc169..58cbb00 100644
--- a/drivers/power/wm831x_backup.c
+++ b/drivers/power/wm831x_backup.c
@@ -169,7 +169,8 @@ static int wm831x_backup_probe(struct platform_device *pdev)
 	struct power_supply *backup;
 	int ret;
 
-	devdata = kzalloc(sizeof(struct wm831x_backup), GFP_KERNEL);
+	devdata = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_backup),
+				GFP_KERNEL);
 	if (devdata == NULL)
 		return -ENOMEM;
 
@@ -197,14 +198,8 @@ static int wm831x_backup_probe(struct platform_device *pdev)
 	backup->num_properties = ARRAY_SIZE(wm831x_backup_props);
 	backup->get_property = wm831x_backup_get_prop;
 	ret = power_supply_register(&pdev->dev, backup);
-	if (ret)
-		goto err_kmalloc;
 
 	return ret;
-
-err_kmalloc:
-	kfree(devdata);
-	return ret;
 }
 
 static int wm831x_backup_remove(struct platform_device *pdev)
@@ -213,7 +208,6 @@ static int wm831x_backup_remove(struct platform_device *pdev)
 
 	power_supply_unregister(&devdata->backup);
 	kfree(devdata->backup.name);
-	kfree(devdata);
 
 	return 0;
 }
diff --git a/drivers/ptp/ptp_pch.c b/drivers/ptp/ptp_pch.c
index 1367655..bea9451 100644
--- a/drivers/ptp/ptp_pch.c
+++ b/drivers/ptp/ptp_pch.c
@@ -118,7 +118,7 @@ struct pch_ts_regs {
  * struct pch_dev - Driver private data
  */
 struct pch_dev {
-	struct pch_ts_regs *regs;
+	struct pch_ts_regs __iomem *regs;
 	struct ptp_clock *ptp_clock;
 	struct ptp_clock_info caps;
 	int exts0_enabled;
@@ -154,7 +154,7 @@ static inline void pch_eth_enable_set(struct pch_dev *chip)
 	iowrite32(val, (&chip->regs->ts_sel));
 }
 
-static u64 pch_systime_read(struct pch_ts_regs *regs)
+static u64 pch_systime_read(struct pch_ts_regs __iomem *regs)
 {
 	u64 ns;
 	u32 lo, hi;
@@ -169,7 +169,7 @@ static u64 pch_systime_read(struct pch_ts_regs *regs)
 	return ns;
 }
 
-static void pch_systime_write(struct pch_ts_regs *regs, u64 ns)
+static void pch_systime_write(struct pch_ts_regs __iomem *regs, u64 ns)
 {
 	u32 hi, lo;
 
@@ -315,7 +315,7 @@ int pch_set_station_address(u8 *addr, struct pci_dev *pdev)
 	struct pch_dev *chip = pci_get_drvdata(pdev);
 
 	/* Verify the parameter */
-	if ((chip->regs == 0) || addr == (u8 *)NULL) {
+	if ((chip->regs == NULL) || addr == (u8 *)NULL) {
 		dev_err(&pdev->dev,
 			"invalid params returning PCH_INVALIDPARAM\n");
 		return PCH_INVALIDPARAM;
@@ -361,7 +361,7 @@ EXPORT_SYMBOL(pch_set_station_address);
 static irqreturn_t isr(int irq, void *priv)
 {
 	struct pch_dev *pch_dev = priv;
-	struct pch_ts_regs *regs = pch_dev->regs;
+	struct pch_ts_regs __iomem *regs = pch_dev->regs;
 	struct ptp_clock_event event;
 	u32 ack = 0, lo, hi, val;
 
@@ -415,7 +415,7 @@ static int ptp_pch_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
 	u32 diff, addend;
 	int neg_adj = 0;
 	struct pch_dev *pch_dev = container_of(ptp, struct pch_dev, caps);
-	struct pch_ts_regs *regs = pch_dev->regs;
+	struct pch_ts_regs __iomem *regs = pch_dev->regs;
 
 	if (ppb < 0) {
 		neg_adj = 1;
@@ -438,7 +438,7 @@ static int ptp_pch_adjtime(struct ptp_clock_info *ptp, s64 delta)
 	s64 now;
 	unsigned long flags;
 	struct pch_dev *pch_dev = container_of(ptp, struct pch_dev, caps);
-	struct pch_ts_regs *regs = pch_dev->regs;
+	struct pch_ts_regs __iomem *regs = pch_dev->regs;
 
 	spin_lock_irqsave(&pch_dev->register_lock, flags);
 	now = pch_systime_read(regs);
@@ -455,7 +455,7 @@ static int ptp_pch_gettime(struct ptp_clock_info *ptp, struct timespec *ts)
 	u32 remainder;
 	unsigned long flags;
 	struct pch_dev *pch_dev = container_of(ptp, struct pch_dev, caps);
-	struct pch_ts_regs *regs = pch_dev->regs;
+	struct pch_ts_regs __iomem *regs = pch_dev->regs;
 
 	spin_lock_irqsave(&pch_dev->register_lock, flags);
 	ns = pch_systime_read(regs);
@@ -472,7 +472,7 @@ static int ptp_pch_settime(struct ptp_clock_info *ptp,
 	u64 ns;
 	unsigned long flags;
 	struct pch_dev *pch_dev = container_of(ptp, struct pch_dev, caps);
-	struct pch_ts_regs *regs = pch_dev->regs;
+	struct pch_ts_regs __iomem *regs = pch_dev->regs;
 
 	ns = ts->tv_sec * 1000000000ULL;
 	ns += ts->tv_nsec;
@@ -567,9 +567,9 @@ static void pch_remove(struct pci_dev *pdev)
 		free_irq(pdev->irq, chip);
 
 	/* unmap the virtual IO memory space */
-	if (chip->regs != 0) {
+	if (chip->regs != NULL) {
 		iounmap(chip->regs);
-		chip->regs = 0;
+		chip->regs = NULL;
 	}
 	/* release the reserved IO memory space */
 	if (chip->mem_base != 0) {
@@ -670,7 +670,7 @@ pch_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 err_req_irq:
 	ptp_clock_unregister(chip->ptp_clock);
 	iounmap(chip->regs);
-	chip->regs = 0;
+	chip->regs = NULL;
 
 err_ioremap:
 	release_mem_region(chip->mem_base, chip->mem_size);
@@ -723,9 +723,10 @@ static s32 __init ptp_pch_init(void)
 module_init(ptp_pch_init);
 module_exit(ptp_pch_exit);
 
-module_param_string(station, pch_param.station, sizeof pch_param.station, 0444);
+module_param_string(station,
+		    pch_param.station, sizeof(pch_param.station), 0444);
 MODULE_PARM_DESC(station,
-	 "IEEE 1588 station address to use - column separated hex values");
+	 "IEEE 1588 station address to use - colon separated hex values");
 
 MODULE_AUTHOR("LAPIS SEMICONDUCTOR, <tshimizu818@gmail.com>");
 MODULE_DESCRIPTION("PTP clock using the EG20T timer");
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index 0e0bfa0..115b644 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -147,8 +147,7 @@ config PWM_TEGRA
 
 config  PWM_TIECAP
 	tristate "ECAP PWM support"
-	depends on SOC_AM33XX
-	select PWM_TIPWMSS
+	depends on SOC_AM33XX || ARCH_DAVINCI_DA8XX
 	help
 	  PWM driver support for the ECAP APWM controller found on AM33XX
 	  TI SOC
@@ -158,8 +157,7 @@ config  PWM_TIECAP
 
 config  PWM_TIEHRPWM
 	tristate "EHRPWM PWM support"
-	depends on SOC_AM33XX
-	select PWM_TIPWMSS
+	depends on SOC_AM33XX || ARCH_DAVINCI_DA8XX
 	help
 	  PWM driver support for the EHRPWM controller found on AM33XX
 	  TI SOC
@@ -169,7 +167,7 @@ config  PWM_TIEHRPWM
 
 config  PWM_TIPWMSS
 	bool
-	depends on SOC_AM33XX && (PWM_TIEHRPWM || PWM_TIECAP)
+	default y if SOC_AM33XX && (PWM_TIECAP || PWM_TIEHRPWM)
 	help
 	  PWM Subsystem driver support for AM33xx SOC.
 
diff --git a/drivers/pwm/pwm-ab8500.c b/drivers/pwm/pwm-ab8500.c
index 4248d04..1d07a6f 100644
--- a/drivers/pwm/pwm-ab8500.c
+++ b/drivers/pwm/pwm-ab8500.c
@@ -66,7 +66,7 @@ static int ab8500_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
 				AB8500_MISC, AB8500_PWM_OUT_CTRL7_REG,
 				1 << (chip->base - 1), ENABLE_PWM);
 	if (ret < 0)
-		dev_err(chip->dev, "%s: Failed to disable PWM, Error %d\n",
+		dev_err(chip->dev, "%s: Failed to enable PWM, Error %d\n",
 							pwm->label, ret);
 	return ret;
 }
@@ -88,6 +88,7 @@ static const struct pwm_ops ab8500_pwm_ops = {
 	.config = ab8500_pwm_config,
 	.enable = ab8500_pwm_enable,
 	.disable = ab8500_pwm_disable,
+	.owner = THIS_MODULE,
 };
 
 static int ab8500_pwm_probe(struct platform_device *pdev)
@@ -99,7 +100,7 @@ static int ab8500_pwm_probe(struct platform_device *pdev)
 	 * Nothing to be done in probe, this is required to get the
 	 * device which is required for ab8500 read and write
 	 */
-	ab8500 = kzalloc(sizeof(*ab8500), GFP_KERNEL);
+	ab8500 = devm_kzalloc(&pdev->dev, sizeof(*ab8500), GFP_KERNEL);
 	if (ab8500 == NULL) {
 		dev_err(&pdev->dev, "failed to allocate memory\n");
 		return -ENOMEM;
@@ -111,10 +112,8 @@ static int ab8500_pwm_probe(struct platform_device *pdev)
 	ab8500->chip.npwm = 1;
 
 	err = pwmchip_add(&ab8500->chip);
-	if (err < 0) {
-		kfree(ab8500);
+	if (err < 0)
 		return err;
-	}
 
 	dev_dbg(&pdev->dev, "pwm probe successful\n");
 	platform_set_drvdata(pdev, ab8500);
@@ -132,7 +131,6 @@ static int ab8500_pwm_remove(struct platform_device *pdev)
 		return err;
 
 	dev_dbg(&pdev->dev, "pwm driver removed\n");
-	kfree(ab8500);
 
 	return 0;
 }
diff --git a/drivers/pwm/pwm-atmel-tcb.c b/drivers/pwm/pwm-atmel-tcb.c
index 16cb530..0a7b658 100644
--- a/drivers/pwm/pwm-atmel-tcb.c
+++ b/drivers/pwm/pwm-atmel-tcb.c
@@ -358,6 +358,7 @@ static const struct pwm_ops atmel_tcb_pwm_ops = {
 	.set_polarity = atmel_tcb_pwm_set_polarity,
 	.enable = atmel_tcb_pwm_enable,
 	.disable = atmel_tcb_pwm_disable,
+	.owner = THIS_MODULE,
 };
 
 static int atmel_tcb_pwm_probe(struct platform_device *pdev)
diff --git a/drivers/pwm/pwm-imx.c b/drivers/pwm/pwm-imx.c
index 3f5677b..ec28798 100644
--- a/drivers/pwm/pwm-imx.c
+++ b/drivers/pwm/pwm-imx.c
@@ -43,7 +43,6 @@ struct imx_chip {
 	struct clk	*clk_per;
 	struct clk	*clk_ipg;
 
-	int		enabled;
 	void __iomem	*mmio_base;
 
 	struct pwm_chip	chip;
@@ -135,7 +134,7 @@ static int imx_pwm_config_v2(struct pwm_chip *chip,
 		MX3_PWMCR_DOZEEN | MX3_PWMCR_WAITEN |
 		MX3_PWMCR_DBGEN | MX3_PWMCR_CLKSRC_IPG_HIGH;
 
-	if (imx->enabled)
+	if (test_bit(PWMF_ENABLED, &pwm->flags))
 		cr |= MX3_PWMCR_EN;
 
 	writel(cr, imx->mmio_base + MX3_PWMCR);
@@ -186,8 +185,6 @@ static int imx_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
 
 	imx->set_enable(chip, true);
 
-	imx->enabled = 1;
-
 	return 0;
 }
 
@@ -198,7 +195,6 @@ static void imx_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
 	imx->set_enable(chip, false);
 
 	clk_disable_unprepare(imx->clk_per);
-	imx->enabled = 0;
 }
 
 static struct pwm_ops imx_pwm_ops = {
diff --git a/drivers/pwm/pwm-mxs.c b/drivers/pwm/pwm-mxs.c
index a53d309..23d5180 100644
--- a/drivers/pwm/pwm-mxs.c
+++ b/drivers/pwm/pwm-mxs.c
@@ -38,7 +38,6 @@
 
 struct mxs_pwm_chip {
 	struct pwm_chip chip;
-	struct device *dev;
 	struct clk *clk;
 	void __iomem *base;
 };
@@ -166,7 +165,6 @@ static int mxs_pwm_probe(struct platform_device *pdev)
 		return ret;
 	}
 
-	mxs->dev = &pdev->dev;
 	platform_set_drvdata(pdev, mxs);
 
 	stmp_reset_block(mxs->base);
diff --git a/drivers/pwm/pwm-puv3.c b/drivers/pwm/pwm-puv3.c
index db964e6..d1eb499 100644
--- a/drivers/pwm/pwm-puv3.c
+++ b/drivers/pwm/pwm-puv3.c
@@ -27,7 +27,6 @@ struct puv3_pwm_chip {
 	struct pwm_chip chip;
 	void __iomem *base;
 	struct clk *clk;
-	bool enabled;
 };
 
 static inline struct puv3_pwm_chip *to_puv3(struct pwm_chip *chip)
diff --git a/drivers/pwm/pwm-pxa.c b/drivers/pwm/pwm-pxa.c
index 20370e6..dee6ab55 100644
--- a/drivers/pwm/pwm-pxa.c
+++ b/drivers/pwm/pwm-pxa.c
@@ -23,14 +23,13 @@
 #include <asm/div64.h>
 
 #define HAS_SECONDARY_PWM	0x10
-#define PWM_ID_BASE(d)		((d) & 0xf)
 
 static const struct platform_device_id pwm_id_table[] = {
 	/*   PWM    has_secondary_pwm? */
 	{ "pxa25x-pwm", 0 },
-	{ "pxa27x-pwm", 0 | HAS_SECONDARY_PWM },
-	{ "pxa168-pwm", 1 },
-	{ "pxa910-pwm", 1 },
+	{ "pxa27x-pwm", HAS_SECONDARY_PWM },
+	{ "pxa168-pwm", 0 },
+	{ "pxa910-pwm", 0 },
 	{ },
 };
 MODULE_DEVICE_TABLE(platform, pwm_id_table);
@@ -48,7 +47,6 @@ struct pxa_pwm_chip {
 	struct device	*dev;
 
 	struct clk	*clk;
-	int		clk_enabled;
 	void __iomem	*mmio_base;
 };
 
@@ -108,24 +106,15 @@ static int pxa_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
 static int pxa_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
 {
 	struct pxa_pwm_chip *pc = to_pxa_pwm_chip(chip);
-	int rc = 0;
 
-	if (!pc->clk_enabled) {
-		rc = clk_prepare_enable(pc->clk);
-		if (!rc)
-			pc->clk_enabled++;
-	}
-	return rc;
+	return clk_prepare_enable(pc->clk);
 }
 
 static void pxa_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
 {
 	struct pxa_pwm_chip *pc = to_pxa_pwm_chip(chip);
 
-	if (pc->clk_enabled) {
-		clk_disable_unprepare(pc->clk);
-		pc->clk_enabled--;
-	}
+	clk_disable_unprepare(pc->clk);
 }
 
 static struct pwm_ops pxa_pwm_ops = {
@@ -152,8 +141,6 @@ static int pwm_probe(struct platform_device *pdev)
 	if (IS_ERR(pwm->clk))
 		return PTR_ERR(pwm->clk);
 
-	pwm->clk_enabled = 0;
-
 	pwm->chip.dev = &pdev->dev;
 	pwm->chip.ops = &pxa_pwm_ops;
 	pwm->chip.base = -1;
diff --git a/drivers/pwm/pwm-samsung.c b/drivers/pwm/pwm-samsung.c
index 5207e6c..a0ece50 100644
--- a/drivers/pwm/pwm-samsung.c
+++ b/drivers/pwm/pwm-samsung.c
@@ -289,10 +289,10 @@ static int s3c_pwm_remove(struct platform_device *pdev)
 	return 0;
 }
 
-#ifdef CONFIG_PM
-static int s3c_pwm_suspend(struct platform_device *pdev, pm_message_t state)
+#ifdef CONFIG_PM_SLEEP
+static int s3c_pwm_suspend(struct device *dev)
 {
-	struct s3c_chip *s3c = platform_get_drvdata(pdev);
+	struct s3c_chip *s3c = dev_get_drvdata(dev);
 
 	/* No one preserve these values during suspend so reset them
 	 * Otherwise driver leaves PWM unconfigured if same values
@@ -304,9 +304,9 @@ static int s3c_pwm_suspend(struct platform_device *pdev, pm_message_t state)
 	return 0;
 }
 
-static int s3c_pwm_resume(struct platform_device *pdev)
+static int s3c_pwm_resume(struct device *dev)
 {
-	struct s3c_chip *s3c = platform_get_drvdata(pdev);
+	struct s3c_chip *s3c = dev_get_drvdata(dev);
 	unsigned long tcon;
 
 	/* Restore invertion */
@@ -316,21 +316,19 @@ static int s3c_pwm_resume(struct platform_device *pdev)
 
 	return 0;
 }
-
-#else
-#define s3c_pwm_suspend NULL
-#define s3c_pwm_resume NULL
 #endif
 
+static SIMPLE_DEV_PM_OPS(s3c_pwm_pm_ops, s3c_pwm_suspend,
+			s3c_pwm_resume);
+
 static struct platform_driver s3c_pwm_driver = {
 	.driver		= {
 		.name	= "s3c24xx-pwm",
 		.owner	= THIS_MODULE,
+		.pm	= &s3c_pwm_pm_ops,
 	},
 	.probe		= s3c_pwm_probe,
 	.remove		= s3c_pwm_remove,
-	.suspend	= s3c_pwm_suspend,
-	.resume		= s3c_pwm_resume,
 };
 
 static int __init pwm_init(void)
diff --git a/drivers/pwm/pwm-spear.c b/drivers/pwm/pwm-spear.c
index 69a2d9e..9563599 100644
--- a/drivers/pwm/pwm-spear.c
+++ b/drivers/pwm/pwm-spear.c
@@ -49,13 +49,11 @@
  * @mmio_base: base address of pwm chip
  * @clk: pointer to clk structure of pwm chip
  * @chip: linux pwm chip representation
- * @dev: pointer to device structure of pwm chip
  */
 struct spear_pwm_chip {
 	void __iomem *mmio_base;
 	struct clk *clk;
 	struct pwm_chip chip;
-	struct device *dev;
 };
 
 static inline struct spear_pwm_chip *to_spear_pwm_chip(struct pwm_chip *chip)
@@ -143,7 +141,7 @@ static int spear_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
 	u32 val;
 
 	rc = clk_enable(pc->clk);
-	if (!rc)
+	if (rc)
 		return rc;
 
 	val = spear_pwm_readl(pc, pwm->hwpwm, PWMCR);
@@ -200,7 +198,6 @@ static int spear_pwm_probe(struct platform_device *pdev)
 	if (IS_ERR(pc->clk))
 		return PTR_ERR(pc->clk);
 
-	pc->dev = &pdev->dev;
 	platform_set_drvdata(pdev, pc);
 
 	pc->chip.dev = &pdev->dev;
@@ -209,12 +206,12 @@ static int spear_pwm_probe(struct platform_device *pdev)
 	pc->chip.npwm = NUM_PWM;
 
 	ret = clk_prepare(pc->clk);
-	if (!ret)
+	if (ret)
 		return ret;
 
 	if (of_device_is_compatible(np, "st,spear1340-pwm")) {
 		ret = clk_enable(pc->clk);
-		if (!ret) {
+		if (ret) {
 			clk_unprepare(pc->clk);
 			return ret;
 		}
diff --git a/drivers/pwm/pwm-tiecap.c b/drivers/pwm/pwm-tiecap.c
index 22e96e2..0d65fb2 100644
--- a/drivers/pwm/pwm-tiecap.c
+++ b/drivers/pwm/pwm-tiecap.c
@@ -295,7 +295,7 @@ static int ecap_pwm_remove(struct platform_device *pdev)
 	return pwmchip_remove(&pc->chip);
 }
 
-void ecap_pwm_save_context(struct ecap_pwm_chip *pc)
+static void ecap_pwm_save_context(struct ecap_pwm_chip *pc)
 {
 	pm_runtime_get_sync(pc->chip.dev);
 	pc->ctx.ecctl2 = readw(pc->mmio_base + ECCTL2);
@@ -304,13 +304,14 @@ void ecap_pwm_save_context(struct ecap_pwm_chip *pc)
 	pm_runtime_put_sync(pc->chip.dev);
 }
 
-void ecap_pwm_restore_context(struct ecap_pwm_chip *pc)
+static void ecap_pwm_restore_context(struct ecap_pwm_chip *pc)
 {
 	writel(pc->ctx.cap3, pc->mmio_base + CAP3);
 	writel(pc->ctx.cap4, pc->mmio_base + CAP4);
 	writew(pc->ctx.ecctl2, pc->mmio_base + ECCTL2);
 }
 
+#ifdef CONFIG_PM_SLEEP
 static int ecap_pwm_suspend(struct device *dev)
 {
 	struct ecap_pwm_chip *pc = dev_get_drvdata(dev);
@@ -337,6 +338,7 @@ static int ecap_pwm_resume(struct device *dev)
 	ecap_pwm_restore_context(pc);
 	return 0;
 }
+#endif
 
 static SIMPLE_DEV_PM_OPS(ecap_pwm_pm_ops, ecap_pwm_suspend, ecap_pwm_resume);
 
diff --git a/drivers/pwm/pwm-tiehrpwm.c b/drivers/pwm/pwm-tiehrpwm.c
index 8b4c86f..6a21759 100644
--- a/drivers/pwm/pwm-tiehrpwm.c
+++ b/drivers/pwm/pwm-tiehrpwm.c
@@ -533,7 +533,7 @@ static int ehrpwm_pwm_remove(struct platform_device *pdev)
 	return pwmchip_remove(&pc->chip);
 }
 
-void ehrpwm_pwm_save_context(struct ehrpwm_pwm_chip *pc)
+static void ehrpwm_pwm_save_context(struct ehrpwm_pwm_chip *pc)
 {
 	pm_runtime_get_sync(pc->chip.dev);
 	pc->ctx.tbctl = ehrpwm_read(pc->mmio_base, TBCTL);
@@ -547,7 +547,7 @@ void ehrpwm_pwm_save_context(struct ehrpwm_pwm_chip *pc)
 	pm_runtime_put_sync(pc->chip.dev);
 }
 
-void ehrpwm_pwm_restore_context(struct ehrpwm_pwm_chip *pc)
+static void ehrpwm_pwm_restore_context(struct ehrpwm_pwm_chip *pc)
 {
 	ehrpwm_write(pc->mmio_base, TBPRD, pc->ctx.tbprd);
 	ehrpwm_write(pc->mmio_base, CMPA, pc->ctx.cmpa);
@@ -559,6 +559,7 @@ void ehrpwm_pwm_restore_context(struct ehrpwm_pwm_chip *pc)
 	ehrpwm_write(pc->mmio_base, TBCTL, pc->ctx.tbctl);
 }
 
+#ifdef CONFIG_PM_SLEEP
 static int ehrpwm_pwm_suspend(struct device *dev)
 {
 	struct ehrpwm_pwm_chip *pc = dev_get_drvdata(dev);
@@ -594,6 +595,7 @@ static int ehrpwm_pwm_resume(struct device *dev)
 	ehrpwm_pwm_restore_context(pc);
 	return 0;
 }
+#endif
 
 static SIMPLE_DEV_PM_OPS(ehrpwm_pwm_pm_ops, ehrpwm_pwm_suspend,
 		ehrpwm_pwm_resume);
diff --git a/drivers/pwm/pwm-tipwmss.c b/drivers/pwm/pwm-tipwmss.c
index 17cbc59..c9c3d3a 100644
--- a/drivers/pwm/pwm-tipwmss.c
+++ b/drivers/pwm/pwm-tipwmss.c
@@ -101,6 +101,7 @@ static int pwmss_remove(struct platform_device *pdev)
 	return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
 static int pwmss_suspend(struct device *dev)
 {
 	struct pwmss_info *info = dev_get_drvdata(dev);
@@ -118,6 +119,7 @@ static int pwmss_resume(struct device *dev)
 	writew(info->pwmss_clkconfig, info->mmio_base + PWMSS_CLKCONFIG);
 	return 0;
 }
+#endif
 
 static SIMPLE_DEV_PM_OPS(pwmss_pm_ops, pwmss_suspend, pwmss_resume);
 
diff --git a/drivers/pwm/pwm-tipwmss.h b/drivers/pwm/pwm-tipwmss.h
index 11f76a1..10ad804 100644
--- a/drivers/pwm/pwm-tipwmss.h
+++ b/drivers/pwm/pwm-tipwmss.h
@@ -18,7 +18,6 @@
 #ifndef __TIPWMSS_H
 #define __TIPWMSS_H
 
-#ifdef CONFIG_PWM_TIPWMSS
 /* PWM substem clock gating */
 #define PWMSS_ECAPCLK_EN	BIT(0)
 #define PWMSS_ECAPCLK_STOP_REQ	BIT(1)
@@ -28,6 +27,7 @@
 #define PWMSS_ECAPCLK_EN_ACK	BIT(0)
 #define PWMSS_EPWMCLK_EN_ACK	BIT(8)
 
+#ifdef CONFIG_PWM_TIPWMSS
 extern u16 pwmss_submodule_state_change(struct device *dev, int set);
 #else
 static inline u16 pwmss_submodule_state_change(struct device *dev, int set)
diff --git a/drivers/pwm/pwm-twl-led.c b/drivers/pwm/pwm-twl-led.c
index 83e25d4..f912e87 100644
--- a/drivers/pwm/pwm-twl-led.c
+++ b/drivers/pwm/pwm-twl-led.c
@@ -271,6 +271,7 @@ static const struct pwm_ops twl4030_pwmled_ops = {
 	.enable = twl4030_pwmled_enable,
 	.disable = twl4030_pwmled_disable,
 	.config = twl4030_pwmled_config,
+	.owner = THIS_MODULE,
 };
 
 static const struct pwm_ops twl6030_pwmled_ops = {
@@ -279,6 +280,7 @@ static const struct pwm_ops twl6030_pwmled_ops = {
 	.config = twl6030_pwmled_config,
 	.request = twl6030_pwmled_request,
 	.free = twl6030_pwmled_free,
+	.owner = THIS_MODULE,
 };
 
 static int twl_pwmled_probe(struct platform_device *pdev)
diff --git a/drivers/pwm/pwm-twl.c b/drivers/pwm/pwm-twl.c
index bf3fda2..2782001 100644
--- a/drivers/pwm/pwm-twl.c
+++ b/drivers/pwm/pwm-twl.c
@@ -248,7 +248,7 @@ static int twl6030_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
 	twl->twl6030_toggle3 = val;
 out:
 	mutex_unlock(&twl->mutex);
-	return 0;
+	return ret;
 }
 
 static void twl6030_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
@@ -287,12 +287,14 @@ static const struct pwm_ops twl4030_pwm_ops = {
 	.disable = twl4030_pwm_disable,
 	.request = twl4030_pwm_request,
 	.free = twl4030_pwm_free,
+	.owner = THIS_MODULE,
 };
 
 static const struct pwm_ops twl6030_pwm_ops = {
 	.config = twl_pwm_config,
 	.enable = twl6030_pwm_enable,
 	.disable = twl6030_pwm_disable,
+	.owner = THIS_MODULE,
 };
 
 static int twl_pwm_probe(struct platform_device *pdev)
diff --git a/drivers/regulator/88pm8607.c b/drivers/regulator/88pm8607.c
index c79ab84..493948a 100644
--- a/drivers/regulator/88pm8607.c
+++ b/drivers/regulator/88pm8607.c
@@ -220,35 +220,6 @@ static int pm8607_list_voltage(struct regulator_dev *rdev, unsigned index)
 	return ret;
 }
 
-static int pm8606_preg_enable(struct regulator_dev *rdev)
-{
-	struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
-
-	return pm860x_set_bits(info->i2c, rdev->desc->enable_reg,
-			       1 << rdev->desc->enable_mask, 0);
-}
-
-static int pm8606_preg_disable(struct regulator_dev *rdev)
-{
-	struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
-
-	return pm860x_set_bits(info->i2c, rdev->desc->enable_reg,
-			       1 << rdev->desc->enable_mask,
-			       1 << rdev->desc->enable_mask);
-}
-
-static int pm8606_preg_is_enabled(struct regulator_dev *rdev)
-{
-	struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
-	int ret;
-
-	ret = pm860x_reg_read(info->i2c, rdev->desc->enable_reg);
-	if (ret < 0)
-		return ret;
-
-	return !((unsigned char)ret & (1 << rdev->desc->enable_mask));
-}
-
 static struct regulator_ops pm8607_regulator_ops = {
 	.list_voltage	= pm8607_list_voltage,
 	.set_voltage_sel = regulator_set_voltage_sel_regmap,
@@ -259,9 +230,9 @@ static struct regulator_ops pm8607_regulator_ops = {
 };
 
 static struct regulator_ops pm8606_preg_ops = {
-	.enable		= pm8606_preg_enable,
-	.disable	= pm8606_preg_disable,
-	.is_enabled	= pm8606_preg_is_enabled,
+	.enable		= regulator_enable_regmap,
+	.disable	= regulator_disable_regmap,
+	.is_enabled	= regulator_is_enabled_regmap,
 };
 
 #define PM8606_PREG(ereg, ebit)						\
@@ -274,6 +245,7 @@ static struct regulator_ops pm8606_preg_ops = {
 		.owner	= THIS_MODULE,					\
 		.enable_reg = PM8606_##ereg,				\
 		.enable_mask = (ebit),					\
+		.enable_is_inverted = true,				\
 	},								\
 }
 
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 6e82503..47a34ff 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -12,7 +12,7 @@ obj-$(CONFIG_REGULATOR_USERSPACE_CONSUMER) += userspace-consumer.o
 obj-$(CONFIG_REGULATOR_88PM8607) += 88pm8607.o
 obj-$(CONFIG_REGULATOR_AAT2870) += aat2870-regulator.o
 obj-$(CONFIG_REGULATOR_AB3100) += ab3100.o
-obj-$(CONFIG_REGULATOR_AB8500)	+= ab8500.o
+obj-$(CONFIG_REGULATOR_AB8500)	+= ab8500.o ab8500-ext.o
 obj-$(CONFIG_REGULATOR_AD5398) += ad5398.o
 obj-$(CONFIG_REGULATOR_ANATOP) += anatop-regulator.o
 obj-$(CONFIG_REGULATOR_ARIZONA) += arizona-micsupp.o arizona-ldo1.o
diff --git a/drivers/regulator/ab8500-ext.c b/drivers/regulator/ab8500-ext.c
new file mode 100644
index 0000000..57d43a1
--- /dev/null
+++ b/drivers/regulator/ab8500-ext.c
@@ -0,0 +1,448 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License Terms: GNU General Public License v2
+ *
+ * Authors: Bengt Jonsson <bengt.g.jonsson@stericsson.com>
+ *
+ * This file is based on drivers/regulator/ab8500.c
+ *
+ * AB8500 external regulators
+ *
+ * ab8500-ext supports the following regulators:
+ * - VextSupply3
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/mfd/abx500.h>
+#include <linux/mfd/abx500/ab8500.h>
+#include <linux/regulator/ab8500.h>
+
+/**
+ * struct ab8500_ext_regulator_info - ab8500 regulator information
+ * @dev: device pointer
+ * @desc: regulator description
+ * @rdev: regulator device
+ * @cfg: regulator configuration (extension of regulator FW configuration)
+ * @is_enabled: status of regulator (on/off)
+ * @update_bank: bank to control on/off
+ * @update_reg: register to control on/off
+ * @update_mask: mask to enable/disable and set mode of regulator
+ * @update_val: bits holding the regulator current mode
+ * @update_val_hp: bits to set EN pin active (LPn pin deactive)
+ *                 normally this means high power mode
+ * @update_val_lp: bits to set EN pin active and LPn pin active
+ *                 normally this means low power mode
+ * @update_val_hw: bits to set regulator pins in HW control
+ *                 SysClkReq pins and logic will choose mode
+ */
+struct ab8500_ext_regulator_info {
+	struct device *dev;
+	struct regulator_desc desc;
+	struct regulator_dev *rdev;
+	struct ab8500_ext_regulator_cfg *cfg;
+	bool is_enabled;
+	u8 update_bank;
+	u8 update_reg;
+	u8 update_mask;
+	u8 update_val;
+	u8 update_val_hp;
+	u8 update_val_lp;
+	u8 update_val_hw;
+};
+
+static int enable(struct ab8500_ext_regulator_info *info, u8 *regval)
+{
+	int ret;
+
+	*regval = info->update_val;
+
+	/*
+	 * To satisfy both HW high power request and SW request, the regulator
+	 * must be on in high power.
+	 */
+	if (info->cfg && info->cfg->hwreq)
+		*regval = info->update_val_hp;
+
+	ret = abx500_mask_and_set_register_interruptible(info->dev,
+		info->update_bank, info->update_reg,
+		info->update_mask, *regval);
+	if (ret < 0) {
+		dev_err(rdev_get_dev(info->rdev),
+			"couldn't set enable bits for regulator\n");
+		return ret;
+	}
+
+	info->is_enabled = true;
+
+	return ret;
+}
+
+static int ab8500_ext_regulator_enable(struct regulator_dev *rdev)
+{
+	int ret;
+	struct ab8500_ext_regulator_info *info = rdev_get_drvdata(rdev);
+	u8 regval;
+
+	if (info == NULL) {
+		dev_err(rdev_get_dev(rdev), "regulator info null pointer\n");
+		return -EINVAL;
+	}
+
+	ret = enable(info, &regval);
+
+	dev_dbg(rdev_get_dev(rdev), "%s-enable (bank, reg, mask, value):"
+		" 0x%02x, 0x%02x, 0x%02x, 0x%02x\n",
+		info->desc.name, info->update_bank, info->update_reg,
+		info->update_mask, regval);
+
+	return ret;
+}
+
+static int disable(struct ab8500_ext_regulator_info *info, u8 *regval)
+{
+	int ret;
+
+	*regval = 0x0;
+
+	/*
+	 * Set the regulator in HW request mode if configured
+	 */
+	if (info->cfg && info->cfg->hwreq)
+		*regval = info->update_val_hw;
+
+	ret = abx500_mask_and_set_register_interruptible(info->dev,
+		info->update_bank, info->update_reg,
+		info->update_mask, *regval);
+	if (ret < 0) {
+		dev_err(rdev_get_dev(info->rdev),
+			"couldn't set disable bits for regulator\n");
+		return ret;
+	}
+
+	info->is_enabled = false;
+
+	return ret;
+}
+
+static int ab8500_ext_regulator_disable(struct regulator_dev *rdev)
+{
+	int ret;
+	struct ab8500_ext_regulator_info *info = rdev_get_drvdata(rdev);
+	u8 regval;
+
+	if (info == NULL) {
+		dev_err(rdev_get_dev(rdev), "regulator info null pointer\n");
+		return -EINVAL;
+	}
+
+	ret = disable(info, &regval);
+
+	dev_dbg(rdev_get_dev(rdev), "%s-disable (bank, reg, mask, value):"
+		" 0x%02x, 0x%02x, 0x%02x, 0x%02x\n",
+		info->desc.name, info->update_bank, info->update_reg,
+		info->update_mask, regval);
+
+	return ret;
+}
+
+static int ab8500_ext_regulator_is_enabled(struct regulator_dev *rdev)
+{
+	int ret;
+	struct ab8500_ext_regulator_info *info = rdev_get_drvdata(rdev);
+	u8 regval;
+
+	if (info == NULL) {
+		dev_err(rdev_get_dev(rdev), "regulator info null pointer\n");
+		return -EINVAL;
+	}
+
+	ret = abx500_get_register_interruptible(info->dev,
+		info->update_bank, info->update_reg, &regval);
+	if (ret < 0) {
+		dev_err(rdev_get_dev(rdev),
+			"couldn't read 0x%x register\n", info->update_reg);
+		return ret;
+	}
+
+	dev_dbg(rdev_get_dev(rdev), "%s-is_enabled (bank, reg, mask, value):"
+		" 0x%02x, 0x%02x, 0x%02x, 0x%02x\n",
+		info->desc.name, info->update_bank, info->update_reg,
+		info->update_mask, regval);
+
+	if (((regval & info->update_mask) == info->update_val_lp) ||
+	    ((regval & info->update_mask) == info->update_val_hp))
+		info->is_enabled = true;
+	else
+		info->is_enabled = false;
+
+	return info->is_enabled;
+}
+
+static int ab8500_ext_regulator_set_mode(struct regulator_dev *rdev,
+					 unsigned int mode)
+{
+	int ret = 0;
+	struct ab8500_ext_regulator_info *info = rdev_get_drvdata(rdev);
+
+	if (info == NULL) {
+		dev_err(rdev_get_dev(rdev), "regulator info null pointer\n");
+		return -EINVAL;
+	}
+
+	switch (mode) {
+	case REGULATOR_MODE_NORMAL:
+		info->update_val = info->update_val_hp;
+		break;
+	case REGULATOR_MODE_IDLE:
+		info->update_val = info->update_val_lp;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	if (info->is_enabled) {
+		u8 regval;
+
+		ret = enable(info, &regval);
+		if (ret < 0)
+			dev_err(rdev_get_dev(rdev),
+				"Could not set regulator mode.\n");
+
+		dev_dbg(rdev_get_dev(rdev),
+			"%s-set_mode (bank, reg, mask, value): "
+			"0x%x, 0x%x, 0x%x, 0x%x\n",
+			info->desc.name, info->update_bank, info->update_reg,
+			info->update_mask, regval);
+	}
+
+	return ret;
+}
+
+static unsigned int ab8500_ext_regulator_get_mode(struct regulator_dev *rdev)
+{
+	struct ab8500_ext_regulator_info *info = rdev_get_drvdata(rdev);
+	int ret;
+
+	if (info == NULL) {
+		dev_err(rdev_get_dev(rdev), "regulator info null pointer\n");
+		return -EINVAL;
+	}
+
+	if (info->update_val == info->update_val_hp)
+		ret = REGULATOR_MODE_NORMAL;
+	else if (info->update_val == info->update_val_lp)
+		ret = REGULATOR_MODE_IDLE;
+	else
+		ret = -EINVAL;
+
+	return ret;
+}
+
+static int ab8500_ext_fixed_get_voltage(struct regulator_dev *rdev)
+{
+	struct regulation_constraints *regu_constraints = rdev->constraints;
+
+	if (regu_constraints == NULL) {
+		dev_err(rdev_get_dev(rdev), "regulator constraints null pointer\n");
+		return -EINVAL;
+	}
+	if (regu_constraints->min_uV && regu_constraints->max_uV) {
+		if (regu_constraints->min_uV == regu_constraints->max_uV)
+			return regu_constraints->min_uV;
+	}
+	return -EINVAL;
+}
+
+static int ab8500_ext_list_voltage(struct regulator_dev *rdev,
+				   unsigned selector)
+{
+	struct regulation_constraints *regu_constraints = rdev->constraints;
+
+	if (regu_constraints == NULL) {
+		dev_err(rdev_get_dev(rdev), "regulator constraints null pointer\n");
+		return -EINVAL;
+	}
+	/* return the uV for the fixed regulators */
+	if (regu_constraints->min_uV && regu_constraints->max_uV) {
+		if (regu_constraints->min_uV == regu_constraints->max_uV)
+			return regu_constraints->min_uV;
+	}
+	return -EINVAL;
+}
+
+static struct regulator_ops ab8500_ext_regulator_ops = {
+	.enable			= ab8500_ext_regulator_enable,
+	.disable		= ab8500_ext_regulator_disable,
+	.is_enabled		= ab8500_ext_regulator_is_enabled,
+	.set_mode		= ab8500_ext_regulator_set_mode,
+	.get_mode		= ab8500_ext_regulator_get_mode,
+	.get_voltage		= ab8500_ext_fixed_get_voltage,
+	.list_voltage		= ab8500_ext_list_voltage,
+};
+
+static struct ab8500_ext_regulator_info
+		ab8500_ext_regulator_info[AB8500_NUM_EXT_REGULATORS] = {
+	[AB8500_EXT_SUPPLY1] = {
+		.desc = {
+			.name		= "VEXTSUPPLY1",
+			.ops		= &ab8500_ext_regulator_ops,
+			.type		= REGULATOR_VOLTAGE,
+			.id		= AB8500_EXT_SUPPLY1,
+			.owner		= THIS_MODULE,
+			.n_voltages	= 1,
+		},
+		.update_bank		= 0x04,
+		.update_reg		= 0x08,
+		.update_mask		= 0x03,
+		.update_val		= 0x01,
+		.update_val_hp		= 0x01,
+		.update_val_lp		= 0x03,
+		.update_val_hw		= 0x02,
+	},
+	[AB8500_EXT_SUPPLY2] = {
+		.desc = {
+			.name		= "VEXTSUPPLY2",
+			.ops		= &ab8500_ext_regulator_ops,
+			.type		= REGULATOR_VOLTAGE,
+			.id		= AB8500_EXT_SUPPLY2,
+			.owner		= THIS_MODULE,
+			.n_voltages	= 1,
+		},
+		.update_bank		= 0x04,
+		.update_reg		= 0x08,
+		.update_mask		= 0x0c,
+		.update_val		= 0x04,
+		.update_val_hp		= 0x04,
+		.update_val_lp		= 0x0c,
+		.update_val_hw		= 0x08,
+	},
+	[AB8500_EXT_SUPPLY3] = {
+		.desc = {
+			.name		= "VEXTSUPPLY3",
+			.ops		= &ab8500_ext_regulator_ops,
+			.type		= REGULATOR_VOLTAGE,
+			.id		= AB8500_EXT_SUPPLY3,
+			.owner		= THIS_MODULE,
+			.n_voltages	= 1,
+		},
+		.update_bank		= 0x04,
+		.update_reg		= 0x08,
+		.update_mask		= 0x30,
+		.update_val		= 0x10,
+		.update_val_hp		= 0x10,
+		.update_val_lp		= 0x30,
+		.update_val_hw		= 0x20,
+	},
+};
+
+int ab8500_ext_regulator_init(struct platform_device *pdev)
+{
+	struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent);
+	struct ab8500_platform_data *ppdata;
+	struct ab8500_regulator_platform_data *pdata;
+	struct regulator_config config = { };
+	int i, err;
+
+	if (!ab8500) {
+		dev_err(&pdev->dev, "null mfd parent\n");
+		return -EINVAL;
+	}
+	ppdata = dev_get_platdata(ab8500->dev);
+	if (!ppdata) {
+		dev_err(&pdev->dev, "null parent pdata\n");
+		return -EINVAL;
+	}
+
+	pdata = ppdata->regulator;
+	if (!pdata) {
+		dev_err(&pdev->dev, "null pdata\n");
+		return -EINVAL;
+	}
+
+	/* make sure the platform data has the correct size */
+	if (pdata->num_ext_regulator != ARRAY_SIZE(ab8500_ext_regulator_info)) {
+		dev_err(&pdev->dev, "Configuration error: size mismatch.\n");
+		return -EINVAL;
+	}
+
+	/* check for AB8500 2.x */
+	if (is_ab8500_2p0_or_earlier(ab8500)) {
+		struct ab8500_ext_regulator_info *info;
+
+		/* VextSupply3LPn is inverted on AB8500 2.x */
+		info = &ab8500_ext_regulator_info[AB8500_EXT_SUPPLY3];
+		info->update_val = 0x30;
+		info->update_val_hp = 0x30;
+		info->update_val_lp = 0x10;
+	}
+
+	/* register all regulators */
+	for (i = 0; i < ARRAY_SIZE(ab8500_ext_regulator_info); i++) {
+		struct ab8500_ext_regulator_info *info = NULL;
+
+		/* assign per-regulator data */
+		info = &ab8500_ext_regulator_info[i];
+		info->dev = &pdev->dev;
+		info->cfg = (struct ab8500_ext_regulator_cfg *)
+			pdata->ext_regulator[i].driver_data;
+
+		config.dev = &pdev->dev;
+		config.init_data = &pdata->ext_regulator[i];
+		config.driver_data = info;
+
+		if ((is_ab9540(ab8500) || is_ab8540(ab8500)) &&
+		    ((info->desc.id == AB8500_EXT_SUPPLY1) ||
+		     (info->desc.id == AB8500_EXT_SUPPLY2) ||
+		     (info->desc.id == AB8500_EXT_SUPPLY3)))
+			info->desc.ops = &ab8500_ext_regulator_ops;
+
+		/* register regulator with framework */
+		info->rdev = regulator_register(&info->desc, &config);
+
+		if (IS_ERR(info->rdev)) {
+			err = PTR_ERR(info->rdev);
+			dev_err(&pdev->dev, "failed to register regulator %s\n",
+					info->desc.name);
+			/* when we fail, un-register all earlier regulators */
+			while (--i >= 0) {
+				info = &ab8500_ext_regulator_info[i];
+				regulator_unregister(info->rdev);
+			}
+			return err;
+		}
+
+		dev_dbg(rdev_get_dev(info->rdev),
+			"%s-probed\n", info->desc.name);
+	}
+
+	return 0;
+}
+
+int ab8500_ext_regulator_exit(struct platform_device *pdev)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(ab8500_ext_regulator_info); i++) {
+		struct ab8500_ext_regulator_info *info = NULL;
+		info = &ab8500_ext_regulator_info[i];
+
+		dev_vdbg(rdev_get_dev(info->rdev),
+			"%s-remove\n", info->desc.name);
+
+		regulator_unregister(info->rdev);
+	}
+
+	return 0;
+}
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Bengt Jonsson <bengt.g.jonsson@stericsson.com>");
+MODULE_DESCRIPTION("AB8500 external regulator driver");
+MODULE_ALIAS("platform:ab8500-ext-regulator");
diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c
index 09014f3..a8552a5 100644
--- a/drivers/regulator/ab8500.c
+++ b/drivers/regulator/ab8500.c
@@ -5,11 +5,15 @@
  *
  * Authors: Sundar Iyer <sundar.iyer@stericsson.com> for ST-Ericsson
  *          Bengt Jonsson <bengt.g.jonsson@stericsson.com> for ST-Ericsson
+ *          Daniel Willerud <daniel.willerud@stericsson.com> for ST-Ericsson
  *
  * AB8500 peripheral regulators
  *
  * AB8500 supports the following regulators:
  *   VAUX1/2/3, VINTCORE, VTVOUT, VUSB, VAUDIO, VAMIC1/2, VDMIC, VANA
+ *
+ * AB8505 supports the following regulators:
+ *   VAUX1/2/3/4/5/6, VINTCORE, VADC, VUSB, VAUDIO, VAMIC1/2, VDMIC, VANA
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -26,33 +30,69 @@
 #include <linux/slab.h>
 
 /**
+ * struct ab8500_shared_mode - is used when mode is shared between
+ * two regulators.
+ * @shared_regulator: pointer to the other sharing regulator
+ * @lp_mode_req: low power mode requested by this regulator
+ */
+struct ab8500_shared_mode {
+	struct ab8500_regulator_info *shared_regulator;
+	bool lp_mode_req;
+};
+
+/**
  * struct ab8500_regulator_info - ab8500 regulator information
  * @dev: device pointer
  * @desc: regulator description
  * @regulator_dev: regulator device
+ * @shared_mode: used when mode is shared between two regulators
+ * @is_enabled: status of regulator (on/off)
+ * @load_lp_uA: maximum load in idle (low power) mode
  * @update_bank: bank to control on/off
  * @update_reg: register to control on/off
- * @update_mask: mask to enable/disable regulator
- * @update_val_enable: bits to enable the regulator in normal (high power) mode
+ * @update_mask: mask to enable/disable and set mode of regulator
+ * @update_val: bits holding the regulator current mode
+ * @update_val_idle: bits to enable the regulator in idle (low power) mode
+ * @update_val_normal: bits to enable the regulator in normal (high power) mode
+ * @mode_bank: bank with location of mode register
+ * @mode_reg: mode register
+ * @mode_mask: mask for setting mode
+ * @mode_val_idle: mode setting for low power
+ * @mode_val_normal: mode setting for normal power
  * @voltage_bank: bank to control regulator voltage
  * @voltage_reg: register to control regulator voltage
  * @voltage_mask: mask to control regulator voltage
  * @voltage_shift: shift to control regulator voltage
- * @delay: startup/set voltage delay in us
  */
 struct ab8500_regulator_info {
 	struct device		*dev;
 	struct regulator_desc	desc;
 	struct regulator_dev	*regulator;
+	struct ab8500_shared_mode *shared_mode;
+	bool is_enabled;
+	int load_lp_uA;
 	u8 update_bank;
 	u8 update_reg;
 	u8 update_mask;
-	u8 update_val_enable;
+	u8 update_val;
+	u8 update_val_idle;
+	u8 update_val_normal;
+	u8 mode_bank;
+	u8 mode_reg;
+	u8 mode_mask;
+	u8 mode_val_idle;
+	u8 mode_val_normal;
 	u8 voltage_bank;
 	u8 voltage_reg;
 	u8 voltage_mask;
 	u8 voltage_shift;
-	unsigned int delay;
+	struct {
+		u8 voltage_limit;
+		u8 voltage_bank;
+		u8 voltage_reg;
+		u8 voltage_mask;
+		u8 voltage_shift;
+	} expand_register;
 };
 
 /* voltage tables for the vauxn/vintcore supplies */
@@ -86,6 +126,44 @@ static const unsigned int ldo_vaux3_voltages[] = {
 	2910000,
 };
 
+static const unsigned int ldo_vaux56_voltages[] = {
+	1800000,
+	1050000,
+	1100000,
+	1200000,
+	1500000,
+	2200000,
+	2500000,
+	2790000,
+};
+
+static const unsigned int ldo_vaux3_ab8540_voltages[] = {
+	1200000,
+	1500000,
+	1800000,
+	2100000,
+	2500000,
+	2750000,
+	2790000,
+	2910000,
+	3050000,
+};
+
+static const unsigned int ldo_vaux56_ab8540_voltages[] = {
+	750000, 760000, 770000, 780000, 790000, 800000,
+	810000, 820000, 830000, 840000, 850000, 860000,
+	870000, 880000, 890000, 900000, 910000, 920000,
+	930000, 940000, 950000, 960000, 970000, 980000,
+	990000, 1000000, 1010000, 1020000, 1030000,
+	1040000, 1050000, 1060000, 1070000, 1080000,
+	1090000, 1100000, 1110000, 1120000, 1130000,
+	1140000, 1150000, 1160000, 1170000, 1180000,
+	1190000, 1200000, 1210000, 1220000, 1230000,
+	1240000, 1250000, 1260000, 1270000, 1280000,
+	1290000, 1300000, 1310000, 1320000, 1330000,
+	1340000, 1350000, 1360000, 1800000, 2790000,
+};
+
 static const unsigned int ldo_vintcore_voltages[] = {
 	1200000,
 	1225000,
@@ -96,6 +174,72 @@ static const unsigned int ldo_vintcore_voltages[] = {
 	1350000,
 };
 
+static const unsigned int ldo_sdio_voltages[] = {
+	1160000,
+	1050000,
+	1100000,
+	1500000,
+	1800000,
+	2200000,
+	2910000,
+	3050000,
+};
+
+static const unsigned int fixed_1200000_voltage[] = {
+	1200000,
+};
+
+static const unsigned int fixed_1800000_voltage[] = {
+	1800000,
+};
+
+static const unsigned int fixed_2000000_voltage[] = {
+	2000000,
+};
+
+static const unsigned int fixed_2050000_voltage[] = {
+	2050000,
+};
+
+static const unsigned int fixed_3300000_voltage[] = {
+	3300000,
+};
+
+static const unsigned int ldo_vana_voltages[] = {
+	1050000,
+	1075000,
+	1100000,
+	1125000,
+	1150000,
+	1175000,
+	1200000,
+	1225000,
+};
+
+static const unsigned int ldo_vaudio_voltages[] = {
+	2000000,
+	2100000,
+	2200000,
+	2300000,
+	2400000,
+	2500000,
+	2600000,
+	2600000,	/* Duplicated in Vaudio and IsoUicc Control register. */
+};
+
+static const unsigned int ldo_vdmic_voltages[] = {
+	1800000,
+	1900000,
+	2000000,
+	2850000,
+};
+
+static DEFINE_MUTEX(shared_mode_mutex);
+static struct ab8500_shared_mode ldo_anamic1_shared;
+static struct ab8500_shared_mode ldo_anamic2_shared;
+static struct ab8500_shared_mode ab8540_ldo_anamic1_shared;
+static struct ab8500_shared_mode ab8540_ldo_anamic2_shared;
+
 static int ab8500_regulator_enable(struct regulator_dev *rdev)
 {
 	int ret;
@@ -108,15 +252,19 @@ static int ab8500_regulator_enable(struct regulator_dev *rdev)
 
 	ret = abx500_mask_and_set_register_interruptible(info->dev,
 		info->update_bank, info->update_reg,
-		info->update_mask, info->update_val_enable);
-	if (ret < 0)
+		info->update_mask, info->update_val);
+	if (ret < 0) {
 		dev_err(rdev_get_dev(rdev),
 			"couldn't set enable bits for regulator\n");
+		return ret;
+	}
+
+	info->is_enabled = true;
 
 	dev_vdbg(rdev_get_dev(rdev),
 		"%s-enable (bank, reg, mask, value): 0x%x, 0x%x, 0x%x, 0x%x\n",
 		info->desc.name, info->update_bank, info->update_reg,
-		info->update_mask, info->update_val_enable);
+		info->update_mask, info->update_val);
 
 	return ret;
 }
@@ -134,9 +282,13 @@ static int ab8500_regulator_disable(struct regulator_dev *rdev)
 	ret = abx500_mask_and_set_register_interruptible(info->dev,
 		info->update_bank, info->update_reg,
 		info->update_mask, 0x0);
-	if (ret < 0)
+	if (ret < 0) {
 		dev_err(rdev_get_dev(rdev),
 			"couldn't set disable bits for regulator\n");
+		return ret;
+	}
+
+	info->is_enabled = false;
 
 	dev_vdbg(rdev_get_dev(rdev),
 		"%s-disable (bank, reg, mask, value): 0x%x, 0x%x, 0x%x, 0x%x\n",
@@ -146,6 +298,172 @@ static int ab8500_regulator_disable(struct regulator_dev *rdev)
 	return ret;
 }
 
+static unsigned int ab8500_regulator_get_optimum_mode(
+		struct regulator_dev *rdev, int input_uV,
+		int output_uV, int load_uA)
+{
+	unsigned int mode;
+
+	struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
+
+	if (info == NULL) {
+		dev_err(rdev_get_dev(rdev), "regulator info null pointer\n");
+		return -EINVAL;
+	}
+
+	if (load_uA <= info->load_lp_uA)
+		mode = REGULATOR_MODE_IDLE;
+	else
+		mode = REGULATOR_MODE_NORMAL;
+
+	return mode;
+}
+
+static int ab8500_regulator_set_mode(struct regulator_dev *rdev,
+				     unsigned int mode)
+{
+	int ret = 0;
+	u8 bank;
+	u8 reg;
+	u8 mask;
+	u8 val;
+	bool dmr = false; /* Dedicated mode register */
+	struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
+
+	if (info == NULL) {
+		dev_err(rdev_get_dev(rdev), "regulator info null pointer\n");
+		return -EINVAL;
+	}
+
+	if (info->shared_mode) {
+		/*
+		 * Special case where mode is shared between two regulators.
+		 */
+		struct ab8500_shared_mode *sm = info->shared_mode;
+		mutex_lock(&shared_mode_mutex);
+
+		if (mode == REGULATOR_MODE_IDLE) {
+			sm->lp_mode_req = true; /* Low power mode requested */
+			if (!((sm->shared_regulator)->
+			      shared_mode->lp_mode_req)) {
+				mutex_unlock(&shared_mode_mutex);
+				return 0; /* Other regulator prevent LP mode */
+			}
+		} else {
+			sm->lp_mode_req = false;
+		}
+	}
+
+	if (info->mode_mask) {
+		/* Dedicated register for handling mode */
+
+		dmr = true;
+
+		switch (mode) {
+		case REGULATOR_MODE_NORMAL:
+			val = info->mode_val_normal;
+			break;
+		case REGULATOR_MODE_IDLE:
+			val = info->mode_val_idle;
+			break;
+		default:
+			if (info->shared_mode)
+				mutex_unlock(&shared_mode_mutex);
+			return -EINVAL;
+		}
+
+		bank = info->mode_bank;
+		reg = info->mode_reg;
+		mask = info->mode_mask;
+	} else {
+		/* Mode register same as enable register */
+
+		switch (mode) {
+		case REGULATOR_MODE_NORMAL:
+			info->update_val = info->update_val_normal;
+			val = info->update_val_normal;
+			break;
+		case REGULATOR_MODE_IDLE:
+			info->update_val = info->update_val_idle;
+			val = info->update_val_idle;
+			break;
+		default:
+			if (info->shared_mode)
+				mutex_unlock(&shared_mode_mutex);
+			return -EINVAL;
+		}
+
+		bank = info->update_bank;
+		reg = info->update_reg;
+		mask = info->update_mask;
+	}
+
+	if (info->is_enabled || dmr) {
+		ret = abx500_mask_and_set_register_interruptible(info->dev,
+			bank, reg, mask, val);
+		if (ret < 0)
+			dev_err(rdev_get_dev(rdev),
+				"couldn't set regulator mode\n");
+
+		dev_vdbg(rdev_get_dev(rdev),
+			"%s-set_mode (bank, reg, mask, value): "
+			"0x%x, 0x%x, 0x%x, 0x%x\n",
+			info->desc.name, bank, reg,
+			mask, val);
+	}
+
+	if (info->shared_mode)
+		mutex_unlock(&shared_mode_mutex);
+
+	return ret;
+}
+
+static unsigned int ab8500_regulator_get_mode(struct regulator_dev *rdev)
+{
+	struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
+	int ret;
+	u8 val;
+	u8 val_normal;
+	u8 val_idle;
+
+	if (info == NULL) {
+		dev_err(rdev_get_dev(rdev), "regulator info null pointer\n");
+		return -EINVAL;
+	}
+
+	/* Need special handling for shared mode */
+	if (info->shared_mode) {
+		if (info->shared_mode->lp_mode_req)
+			return REGULATOR_MODE_IDLE;
+		else
+			return REGULATOR_MODE_NORMAL;
+	}
+
+	if (info->mode_mask) {
+		/* Dedicated register for handling mode */
+		ret = abx500_get_register_interruptible(info->dev,
+		info->mode_bank, info->mode_reg, &val);
+		val = val & info->mode_mask;
+
+		val_normal = info->mode_val_normal;
+		val_idle = info->mode_val_idle;
+	} else {
+		/* Mode register same as enable register */
+		val = info->update_val;
+		val_normal = info->update_val_normal;
+		val_idle = info->update_val_idle;
+	}
+
+	if (val == val_normal)
+		ret = REGULATOR_MODE_NORMAL;
+	else if (val == val_idle)
+		ret = REGULATOR_MODE_IDLE;
+	else
+		ret = -EINVAL;
+
+	return ret;
+}
+
 static int ab8500_regulator_is_enabled(struct regulator_dev *rdev)
 {
 	int ret;
@@ -172,9 +490,11 @@ static int ab8500_regulator_is_enabled(struct regulator_dev *rdev)
 		info->update_mask, regval);
 
 	if (regval & info->update_mask)
-		return true;
+		info->is_enabled = true;
 	else
-		return false;
+		info->is_enabled = false;
+
+	return info->is_enabled;
 }
 
 static int ab8500_regulator_get_voltage_sel(struct regulator_dev *rdev)
@@ -207,6 +527,57 @@ static int ab8500_regulator_get_voltage_sel(struct regulator_dev *rdev)
 	return val >> info->voltage_shift;
 }
 
+static int ab8540_aux3_regulator_get_voltage_sel(struct regulator_dev *rdev)
+{
+	int ret, val;
+	struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
+	u8 regval, regval_expand;
+
+	if (info == NULL) {
+		dev_err(rdev_get_dev(rdev), "regulator info null pointer\n");
+		return -EINVAL;
+	}
+
+	ret = abx500_get_register_interruptible(info->dev,
+			info->voltage_bank, info->voltage_reg, &regval);
+
+	if (ret < 0) {
+		dev_err(rdev_get_dev(rdev),
+			"couldn't read voltage reg for regulator\n");
+		return ret;
+	}
+
+	ret = abx500_get_register_interruptible(info->dev,
+			info->expand_register.voltage_bank,
+			info->expand_register.voltage_reg, &regval_expand);
+
+	if (ret < 0) {
+		dev_err(rdev_get_dev(rdev),
+			"couldn't read voltage reg for regulator\n");
+		return ret;
+	}
+
+	dev_vdbg(rdev_get_dev(rdev),
+		"%s-get_voltage (bank, reg, mask, value): 0x%x, 0x%x, 0x%x,"
+		" 0x%x\n",
+		info->desc.name, info->voltage_bank, info->voltage_reg,
+		info->voltage_mask, regval);
+	dev_vdbg(rdev_get_dev(rdev),
+		"%s-get_voltage expand (bank, reg, mask, value): 0x%x, 0x%x, 0x%x,"
+		" 0x%x\n",
+		info->desc.name, info->expand_register.voltage_bank,
+		info->expand_register.voltage_reg,
+		info->expand_register.voltage_mask, regval_expand);
+
+	if (regval_expand&(info->expand_register.voltage_mask))
+		/* Vaux3 has a different layout */
+		val = info->expand_register.voltage_limit;
+	else
+		val = (regval & info->voltage_mask) >> info->voltage_shift;
+
+	return val;
+}
+
 static int ab8500_regulator_set_voltage_sel(struct regulator_dev *rdev,
 					    unsigned selector)
 {
@@ -237,16 +608,81 @@ static int ab8500_regulator_set_voltage_sel(struct regulator_dev *rdev,
 	return ret;
 }
 
+static int ab8540_aux3_regulator_set_voltage_sel(struct regulator_dev *rdev,
+						unsigned selector)
+{
+	int ret;
+	struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
+	u8 regval;
+
+	if (info == NULL) {
+		dev_err(rdev_get_dev(rdev), "regulator info null pointer\n");
+		return -EINVAL;
+	}
+
+	if (selector >= info->expand_register.voltage_limit) {
+		/* Vaux3 bit4 has different layout */
+		regval = (u8)selector << info->expand_register.voltage_shift;
+		ret = abx500_mask_and_set_register_interruptible(info->dev,
+					info->expand_register.voltage_bank,
+					info->expand_register.voltage_reg,
+					info->expand_register.voltage_mask,
+					regval);
+	} else {
+		/* set the registers for the request */
+		regval = (u8)selector << info->voltage_shift;
+		ret = abx500_mask_and_set_register_interruptible(info->dev,
+				info->voltage_bank, info->voltage_reg,
+				info->voltage_mask, regval);
+	}
+	if (ret < 0)
+		dev_err(rdev_get_dev(rdev),
+			"couldn't set voltage reg for regulator\n");
+
+	dev_vdbg(rdev_get_dev(rdev),
+			"%s-set_voltage (bank, reg, mask, value): 0x%x, 0x%x, 0x%x,"
+			" 0x%x\n",
+			info->desc.name, info->voltage_bank, info->voltage_reg,
+			info->voltage_mask, regval);
+
+	return ret;
+}
+
 static int ab8500_regulator_set_voltage_time_sel(struct regulator_dev *rdev,
 					     unsigned int old_sel,
 					     unsigned int new_sel)
 {
 	struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
 
-	return info->delay;
+	return info->desc.enable_time;
 }
 
-static struct regulator_ops ab8500_regulator_ops = {
+static struct regulator_ops ab8500_regulator_volt_mode_ops = {
+	.enable			= ab8500_regulator_enable,
+	.disable		= ab8500_regulator_disable,
+	.is_enabled		= ab8500_regulator_is_enabled,
+	.get_optimum_mode	= ab8500_regulator_get_optimum_mode,
+	.set_mode		= ab8500_regulator_set_mode,
+	.get_mode		= ab8500_regulator_get_mode,
+	.get_voltage_sel 	= ab8500_regulator_get_voltage_sel,
+	.set_voltage_sel	= ab8500_regulator_set_voltage_sel,
+	.list_voltage		= regulator_list_voltage_table,
+};
+
+static struct regulator_ops ab8540_aux3_regulator_volt_mode_ops = {
+	.enable		= ab8500_regulator_enable,
+	.disable	= ab8500_regulator_disable,
+	.get_optimum_mode	= ab8500_regulator_get_optimum_mode,
+	.set_mode	= ab8500_regulator_set_mode,
+	.get_mode	= ab8500_regulator_get_mode,
+	.is_enabled	= ab8500_regulator_is_enabled,
+	.get_voltage_sel = ab8540_aux3_regulator_get_voltage_sel,
+	.set_voltage_sel = ab8540_aux3_regulator_set_voltage_sel,
+	.list_voltage	= regulator_list_voltage_table,
+	.set_voltage_time_sel = ab8500_regulator_set_voltage_time_sel,
+};
+
+static struct regulator_ops ab8500_regulator_volt_ops = {
 	.enable		= ab8500_regulator_enable,
 	.disable	= ab8500_regulator_disable,
 	.is_enabled	= ab8500_regulator_is_enabled,
@@ -256,13 +692,33 @@ static struct regulator_ops ab8500_regulator_ops = {
 	.set_voltage_time_sel = ab8500_regulator_set_voltage_time_sel,
 };
 
-static struct regulator_ops ab8500_regulator_fixed_ops = {
+static struct regulator_ops ab8500_regulator_mode_ops = {
+	.enable			= ab8500_regulator_enable,
+	.disable		= ab8500_regulator_disable,
+	.is_enabled		= ab8500_regulator_is_enabled,
+	.get_optimum_mode	= ab8500_regulator_get_optimum_mode,
+	.set_mode		= ab8500_regulator_set_mode,
+	.get_mode		= ab8500_regulator_get_mode,
+	.list_voltage		= regulator_list_voltage_table,
+};
+
+static struct regulator_ops ab8500_regulator_ops = {
+	.enable			= ab8500_regulator_enable,
+	.disable		= ab8500_regulator_disable,
+	.is_enabled		= ab8500_regulator_is_enabled,
+	.list_voltage		= regulator_list_voltage_table,
+};
+
+static struct regulator_ops ab8500_regulator_anamic_mode_ops = {
 	.enable		= ab8500_regulator_enable,
 	.disable	= ab8500_regulator_disable,
 	.is_enabled	= ab8500_regulator_is_enabled,
-	.list_voltage	= regulator_list_voltage_linear,
+	.set_mode	= ab8500_regulator_set_mode,
+	.get_mode	= ab8500_regulator_get_mode,
+	.list_voltage	= regulator_list_voltage_table,
 };
 
+/* AB8500 regulator information */
 static struct ab8500_regulator_info
 		ab8500_regulator_info[AB8500_NUM_REGULATORS] = {
 	/*
@@ -274,17 +730,21 @@ static struct ab8500_regulator_info
 	[AB8500_LDO_AUX1] = {
 		.desc = {
 			.name		= "LDO-AUX1",
-			.ops		= &ab8500_regulator_ops,
+			.ops		= &ab8500_regulator_volt_mode_ops,
 			.type		= REGULATOR_VOLTAGE,
 			.id		= AB8500_LDO_AUX1,
 			.owner		= THIS_MODULE,
 			.n_voltages	= ARRAY_SIZE(ldo_vauxn_voltages),
 			.volt_table	= ldo_vauxn_voltages,
+			.enable_time	= 200,
 		},
+		.load_lp_uA		= 5000,
 		.update_bank		= 0x04,
 		.update_reg		= 0x09,
 		.update_mask		= 0x03,
-		.update_val_enable	= 0x01,
+		.update_val		= 0x01,
+		.update_val_idle	= 0x03,
+		.update_val_normal	= 0x01,
 		.voltage_bank		= 0x04,
 		.voltage_reg		= 0x1f,
 		.voltage_mask		= 0x0f,
@@ -292,17 +752,21 @@ static struct ab8500_regulator_info
 	[AB8500_LDO_AUX2] = {
 		.desc = {
 			.name		= "LDO-AUX2",
-			.ops		= &ab8500_regulator_ops,
+			.ops		= &ab8500_regulator_volt_mode_ops,
 			.type		= REGULATOR_VOLTAGE,
 			.id		= AB8500_LDO_AUX2,
 			.owner		= THIS_MODULE,
 			.n_voltages	= ARRAY_SIZE(ldo_vauxn_voltages),
 			.volt_table	= ldo_vauxn_voltages,
+			.enable_time	= 200,
 		},
+		.load_lp_uA		= 5000,
 		.update_bank		= 0x04,
 		.update_reg		= 0x09,
 		.update_mask		= 0x0c,
-		.update_val_enable	= 0x04,
+		.update_val		= 0x04,
+		.update_val_idle	= 0x0c,
+		.update_val_normal	= 0x04,
 		.voltage_bank		= 0x04,
 		.voltage_reg		= 0x20,
 		.voltage_mask		= 0x0f,
@@ -310,17 +774,21 @@ static struct ab8500_regulator_info
 	[AB8500_LDO_AUX3] = {
 		.desc = {
 			.name		= "LDO-AUX3",
-			.ops		= &ab8500_regulator_ops,
+			.ops		= &ab8500_regulator_volt_mode_ops,
 			.type		= REGULATOR_VOLTAGE,
 			.id		= AB8500_LDO_AUX3,
 			.owner		= THIS_MODULE,
 			.n_voltages	= ARRAY_SIZE(ldo_vaux3_voltages),
 			.volt_table	= ldo_vaux3_voltages,
+			.enable_time	= 450,
 		},
+		.load_lp_uA		= 5000,
 		.update_bank		= 0x04,
 		.update_reg		= 0x0a,
 		.update_mask		= 0x03,
-		.update_val_enable	= 0x01,
+		.update_val		= 0x01,
+		.update_val_idle	= 0x03,
+		.update_val_normal	= 0x01,
 		.voltage_bank		= 0x04,
 		.voltage_reg		= 0x21,
 		.voltage_mask		= 0x07,
@@ -328,17 +796,21 @@ static struct ab8500_regulator_info
 	[AB8500_LDO_INTCORE] = {
 		.desc = {
 			.name		= "LDO-INTCORE",
-			.ops		= &ab8500_regulator_ops,
+			.ops		= &ab8500_regulator_volt_mode_ops,
 			.type		= REGULATOR_VOLTAGE,
 			.id		= AB8500_LDO_INTCORE,
 			.owner		= THIS_MODULE,
 			.n_voltages	= ARRAY_SIZE(ldo_vintcore_voltages),
 			.volt_table	= ldo_vintcore_voltages,
+			.enable_time	= 750,
 		},
+		.load_lp_uA		= 5000,
 		.update_bank		= 0x03,
 		.update_reg		= 0x80,
 		.update_mask		= 0x44,
-		.update_val_enable	= 0x04,
+		.update_val		= 0x44,
+		.update_val_idle	= 0x44,
+		.update_val_normal	= 0x04,
 		.voltage_bank		= 0x03,
 		.voltage_reg		= 0x80,
 		.voltage_mask		= 0x38,
@@ -353,144 +825,1021 @@ static struct ab8500_regulator_info
 	[AB8500_LDO_TVOUT] = {
 		.desc = {
 			.name		= "LDO-TVOUT",
-			.ops		= &ab8500_regulator_fixed_ops,
+			.ops		= &ab8500_regulator_mode_ops,
 			.type		= REGULATOR_VOLTAGE,
 			.id		= AB8500_LDO_TVOUT,
 			.owner		= THIS_MODULE,
 			.n_voltages	= 1,
-			.min_uV		= 2000000,
-			.enable_time	= 10000,
+			.volt_table	= fixed_2000000_voltage,
+			.enable_time	= 500,
 		},
-		.delay			= 10000,
+		.load_lp_uA		= 1000,
 		.update_bank		= 0x03,
 		.update_reg		= 0x80,
 		.update_mask		= 0x82,
-		.update_val_enable	= 0x02,
-	},
-	[AB8500_LDO_USB] = {
-		.desc = {
-			.name           = "LDO-USB",
-			.ops            = &ab8500_regulator_fixed_ops,
-			.type           = REGULATOR_VOLTAGE,
-			.id             = AB8500_LDO_USB,
-			.owner          = THIS_MODULE,
-			.n_voltages     = 1,
-			.min_uV		= 3300000,
-		},
-		.update_bank            = 0x03,
-		.update_reg             = 0x82,
-		.update_mask            = 0x03,
-		.update_val_enable      = 0x01,
+		.update_val		= 0x02,
+		.update_val_idle	= 0x82,
+		.update_val_normal	= 0x02,
 	},
 	[AB8500_LDO_AUDIO] = {
 		.desc = {
 			.name		= "LDO-AUDIO",
-			.ops		= &ab8500_regulator_fixed_ops,
+			.ops		= &ab8500_regulator_ops,
 			.type		= REGULATOR_VOLTAGE,
 			.id		= AB8500_LDO_AUDIO,
 			.owner		= THIS_MODULE,
 			.n_voltages	= 1,
-			.min_uV		= 2000000,
+			.enable_time	= 140,
+			.volt_table	= fixed_2000000_voltage,
 		},
 		.update_bank		= 0x03,
 		.update_reg		= 0x83,
 		.update_mask		= 0x02,
-		.update_val_enable	= 0x02,
+		.update_val		= 0x02,
 	},
 	[AB8500_LDO_ANAMIC1] = {
 		.desc = {
 			.name		= "LDO-ANAMIC1",
-			.ops		= &ab8500_regulator_fixed_ops,
+			.ops		= &ab8500_regulator_ops,
 			.type		= REGULATOR_VOLTAGE,
 			.id		= AB8500_LDO_ANAMIC1,
 			.owner		= THIS_MODULE,
 			.n_voltages	= 1,
-			.min_uV		= 2050000,
+			.enable_time	= 500,
+			.volt_table	= fixed_2050000_voltage,
 		},
 		.update_bank		= 0x03,
 		.update_reg		= 0x83,
 		.update_mask		= 0x08,
-		.update_val_enable	= 0x08,
+		.update_val		= 0x08,
 	},
 	[AB8500_LDO_ANAMIC2] = {
 		.desc = {
 			.name		= "LDO-ANAMIC2",
-			.ops		= &ab8500_regulator_fixed_ops,
+			.ops		= &ab8500_regulator_ops,
 			.type		= REGULATOR_VOLTAGE,
 			.id		= AB8500_LDO_ANAMIC2,
 			.owner		= THIS_MODULE,
 			.n_voltages	= 1,
-			.min_uV		= 2050000,
+			.enable_time	= 500,
+			.volt_table	= fixed_2050000_voltage,
 		},
 		.update_bank		= 0x03,
 		.update_reg		= 0x83,
 		.update_mask		= 0x10,
-		.update_val_enable	= 0x10,
+		.update_val		= 0x10,
 	},
 	[AB8500_LDO_DMIC] = {
 		.desc = {
 			.name		= "LDO-DMIC",
-			.ops		= &ab8500_regulator_fixed_ops,
+			.ops		= &ab8500_regulator_ops,
 			.type		= REGULATOR_VOLTAGE,
 			.id		= AB8500_LDO_DMIC,
 			.owner		= THIS_MODULE,
 			.n_voltages	= 1,
-			.min_uV		= 1800000,
+			.enable_time	= 420,
+			.volt_table	= fixed_1800000_voltage,
 		},
 		.update_bank		= 0x03,
 		.update_reg		= 0x83,
 		.update_mask		= 0x04,
-		.update_val_enable	= 0x04,
+		.update_val		= 0x04,
 	},
+
+	/*
+	 * Regulators with fixed voltage and normal/idle modes
+	 */
 	[AB8500_LDO_ANA] = {
 		.desc = {
 			.name		= "LDO-ANA",
-			.ops		= &ab8500_regulator_fixed_ops,
+			.ops		= &ab8500_regulator_mode_ops,
 			.type		= REGULATOR_VOLTAGE,
 			.id		= AB8500_LDO_ANA,
 			.owner		= THIS_MODULE,
 			.n_voltages	= 1,
-			.min_uV		= 1200000,
+			.enable_time	= 140,
+			.volt_table	= fixed_1200000_voltage,
 		},
+		.load_lp_uA		= 1000,
 		.update_bank		= 0x04,
 		.update_reg		= 0x06,
 		.update_mask		= 0x0c,
-		.update_val_enable	= 0x04,
+		.update_val		= 0x04,
+		.update_val_idle	= 0x0c,
+		.update_val_normal	= 0x04,
 	},
-
-
 };
 
-struct ab8500_reg_init {
-	u8 bank;
-	u8 addr;
-	u8 mask;
-};
-
-#define REG_INIT(_id, _bank, _addr, _mask)	\
-	[_id] = {				\
-		.bank = _bank,			\
-		.addr = _addr,			\
-		.mask = _mask,			\
-	}
-
-static struct ab8500_reg_init ab8500_reg_init[] = {
-	/*
-	 * 0x30, VanaRequestCtrl
-	 * 0x0C, VpllRequestCtrl
-	 * 0xc0, VextSupply1RequestCtrl
-	 */
-	REG_INIT(AB8500_REGUREQUESTCTRL2,	0x03, 0x04, 0xfc),
-	/*
-	 * 0x03, VextSupply2RequestCtrl
-	 * 0x0c, VextSupply3RequestCtrl
-	 * 0x30, Vaux1RequestCtrl
-	 * 0xc0, Vaux2RequestCtrl
-	 */
-	REG_INIT(AB8500_REGUREQUESTCTRL3,	0x03, 0x05, 0xff),
+/* AB8505 regulator information */
+static struct ab8500_regulator_info
+		ab8505_regulator_info[AB8505_NUM_REGULATORS] = {
 	/*
-	 * 0x03, Vaux3RequestCtrl
-	 * 0x04, SwHPReq
+	 * Variable Voltage Regulators
+	 *   name, min mV, max mV,
+	 *   update bank, reg, mask, enable val
+	 *   volt bank, reg, mask
+	 */
+	[AB8505_LDO_AUX1] = {
+		.desc = {
+			.name		= "LDO-AUX1",
+			.ops		= &ab8500_regulator_volt_mode_ops,
+			.type		= REGULATOR_VOLTAGE,
+			.id		= AB8505_LDO_AUX1,
+			.owner		= THIS_MODULE,
+			.n_voltages	= ARRAY_SIZE(ldo_vauxn_voltages),
+			.volt_table	= ldo_vauxn_voltages,
+		},
+		.load_lp_uA		= 5000,
+		.update_bank		= 0x04,
+		.update_reg		= 0x09,
+		.update_mask		= 0x03,
+		.update_val		= 0x01,
+		.update_val_idle	= 0x03,
+		.update_val_normal	= 0x01,
+		.voltage_bank		= 0x04,
+		.voltage_reg		= 0x1f,
+		.voltage_mask		= 0x0f,
+	},
+	[AB8505_LDO_AUX2] = {
+		.desc = {
+			.name		= "LDO-AUX2",
+			.ops		= &ab8500_regulator_volt_mode_ops,
+			.type		= REGULATOR_VOLTAGE,
+			.id		= AB8505_LDO_AUX2,
+			.owner		= THIS_MODULE,
+			.n_voltages	= ARRAY_SIZE(ldo_vauxn_voltages),
+			.volt_table	= ldo_vauxn_voltages,
+		},
+		.load_lp_uA		= 5000,
+		.update_bank		= 0x04,
+		.update_reg		= 0x09,
+		.update_mask		= 0x0c,
+		.update_val		= 0x04,
+		.update_val_idle	= 0x0c,
+		.update_val_normal	= 0x04,
+		.voltage_bank		= 0x04,
+		.voltage_reg		= 0x20,
+		.voltage_mask		= 0x0f,
+	},
+	[AB8505_LDO_AUX3] = {
+		.desc = {
+			.name		= "LDO-AUX3",
+			.ops		= &ab8500_regulator_volt_mode_ops,
+			.type		= REGULATOR_VOLTAGE,
+			.id		= AB8505_LDO_AUX3,
+			.owner		= THIS_MODULE,
+			.n_voltages	= ARRAY_SIZE(ldo_vaux3_voltages),
+			.volt_table	= ldo_vaux3_voltages,
+		},
+		.load_lp_uA		= 5000,
+		.update_bank		= 0x04,
+		.update_reg		= 0x0a,
+		.update_mask		= 0x03,
+		.update_val		= 0x01,
+		.update_val_idle	= 0x03,
+		.update_val_normal	= 0x01,
+		.voltage_bank		= 0x04,
+		.voltage_reg		= 0x21,
+		.voltage_mask		= 0x07,
+	},
+	[AB8505_LDO_AUX4] = {
+		.desc = {
+			.name		= "LDO-AUX4",
+			.ops		= &ab8500_regulator_volt_mode_ops,
+			.type		= REGULATOR_VOLTAGE,
+			.id		= AB8505_LDO_AUX4,
+			.owner		= THIS_MODULE,
+			.n_voltages	= ARRAY_SIZE(ldo_vauxn_voltages),
+			.volt_table	= ldo_vauxn_voltages,
+		},
+		.load_lp_uA		= 5000,
+		/* values for Vaux4Regu register */
+		.update_bank		= 0x04,
+		.update_reg		= 0x2e,
+		.update_mask		= 0x03,
+		.update_val		= 0x01,
+		.update_val_idle	= 0x03,
+		.update_val_normal	= 0x01,
+		/* values for Vaux4SEL register */
+		.voltage_bank		= 0x04,
+		.voltage_reg		= 0x2f,
+		.voltage_mask		= 0x0f,
+	},
+	[AB8505_LDO_AUX5] = {
+		.desc = {
+			.name		= "LDO-AUX5",
+			.ops		= &ab8500_regulator_volt_mode_ops,
+			.type		= REGULATOR_VOLTAGE,
+			.id		= AB8505_LDO_AUX5,
+			.owner		= THIS_MODULE,
+			.n_voltages	= ARRAY_SIZE(ldo_vaux56_voltages),
+			.volt_table	= ldo_vaux56_voltages,
+		},
+		.load_lp_uA		= 2000,
+		/* values for CtrlVaux5 register */
+		.update_bank		= 0x01,
+		.update_reg		= 0x55,
+		.update_mask		= 0x18,
+		.update_val		= 0x10,
+		.update_val_idle	= 0x18,
+		.update_val_normal	= 0x10,
+		.voltage_bank		= 0x01,
+		.voltage_reg		= 0x55,
+		.voltage_mask		= 0x07,
+	},
+	[AB8505_LDO_AUX6] = {
+		.desc = {
+			.name		= "LDO-AUX6",
+			.ops		= &ab8500_regulator_volt_mode_ops,
+			.type		= REGULATOR_VOLTAGE,
+			.id		= AB8505_LDO_AUX6,
+			.owner		= THIS_MODULE,
+			.n_voltages	= ARRAY_SIZE(ldo_vaux56_voltages),
+			.volt_table	= ldo_vaux56_voltages,
+		},
+		.load_lp_uA		= 2000,
+		/* values for CtrlVaux6 register */
+		.update_bank		= 0x01,
+		.update_reg		= 0x56,
+		.update_mask		= 0x18,
+		.update_val		= 0x10,
+		.update_val_idle	= 0x18,
+		.update_val_normal	= 0x10,
+		.voltage_bank		= 0x01,
+		.voltage_reg		= 0x56,
+		.voltage_mask		= 0x07,
+	},
+	[AB8505_LDO_INTCORE] = {
+		.desc = {
+			.name		= "LDO-INTCORE",
+			.ops		= &ab8500_regulator_volt_mode_ops,
+			.type		= REGULATOR_VOLTAGE,
+			.id		= AB8505_LDO_INTCORE,
+			.owner		= THIS_MODULE,
+			.n_voltages	= ARRAY_SIZE(ldo_vintcore_voltages),
+			.volt_table	= ldo_vintcore_voltages,
+		},
+		.load_lp_uA		= 5000,
+		.update_bank		= 0x03,
+		.update_reg		= 0x80,
+		.update_mask		= 0x44,
+		.update_val		= 0x04,
+		.update_val_idle	= 0x44,
+		.update_val_normal	= 0x04,
+		.voltage_bank		= 0x03,
+		.voltage_reg		= 0x80,
+		.voltage_mask		= 0x38,
+		.voltage_shift		= 3,
+	},
+
+	/*
+	 * Fixed Voltage Regulators
+	 *   name, fixed mV,
+	 *   update bank, reg, mask, enable val
+	 */
+	[AB8505_LDO_ADC] = {
+		.desc = {
+			.name		= "LDO-ADC",
+			.ops		= &ab8500_regulator_mode_ops,
+			.type		= REGULATOR_VOLTAGE,
+			.id		= AB8505_LDO_ADC,
+			.owner		= THIS_MODULE,
+			.n_voltages	= 1,
+			.volt_table	= fixed_2000000_voltage,
+			.enable_time	= 10000,
+		},
+		.load_lp_uA		= 1000,
+		.update_bank		= 0x03,
+		.update_reg		= 0x80,
+		.update_mask		= 0x82,
+		.update_val		= 0x02,
+		.update_val_idle	= 0x82,
+		.update_val_normal	= 0x02,
+	},
+	[AB8505_LDO_USB] = {
+		.desc = {
+			.name           = "LDO-USB",
+			.ops            = &ab8500_regulator_mode_ops,
+			.type           = REGULATOR_VOLTAGE,
+			.id             = AB8505_LDO_USB,
+			.owner          = THIS_MODULE,
+			.n_voltages     = 1,
+			.volt_table	= fixed_3300000_voltage,
+		},
+		.update_bank            = 0x03,
+		.update_reg             = 0x82,
+		.update_mask            = 0x03,
+		.update_val		= 0x01,
+		.update_val_idle	= 0x03,
+		.update_val_normal	= 0x01,
+	},
+	[AB8505_LDO_AUDIO] = {
+		.desc = {
+			.name		= "LDO-AUDIO",
+			.ops		= &ab8500_regulator_volt_ops,
+			.type		= REGULATOR_VOLTAGE,
+			.id		= AB8505_LDO_AUDIO,
+			.owner		= THIS_MODULE,
+			.n_voltages	= ARRAY_SIZE(ldo_vaudio_voltages),
+			.volt_table	= ldo_vaudio_voltages,
+		},
+		.update_bank		= 0x03,
+		.update_reg		= 0x83,
+		.update_mask		= 0x02,
+		.update_val		= 0x02,
+		.voltage_bank		= 0x01,
+		.voltage_reg		= 0x57,
+		.voltage_mask		= 0x7,
+		.voltage_shift		= 4,
+	},
+	[AB8505_LDO_ANAMIC1] = {
+		.desc = {
+			.name		= "LDO-ANAMIC1",
+			.ops		= &ab8500_regulator_anamic_mode_ops,
+			.type		= REGULATOR_VOLTAGE,
+			.id		= AB8505_LDO_ANAMIC1,
+			.owner		= THIS_MODULE,
+			.n_voltages	= 1,
+			.volt_table	= fixed_2050000_voltage,
+		},
+		.shared_mode		= &ldo_anamic1_shared,
+		.update_bank		= 0x03,
+		.update_reg		= 0x83,
+		.update_mask		= 0x08,
+		.update_val		= 0x08,
+		.mode_bank		= 0x01,
+		.mode_reg		= 0x54,
+		.mode_mask		= 0x04,
+		.mode_val_idle		= 0x04,
+		.mode_val_normal	= 0x00,
+	},
+	[AB8505_LDO_ANAMIC2] = {
+		.desc = {
+			.name		= "LDO-ANAMIC2",
+			.ops		= &ab8500_regulator_anamic_mode_ops,
+			.type		= REGULATOR_VOLTAGE,
+			.id		= AB8505_LDO_ANAMIC2,
+			.owner		= THIS_MODULE,
+			.n_voltages	= 1,
+			.volt_table	= fixed_2050000_voltage,
+		},
+		.shared_mode		= &ldo_anamic2_shared,
+		.update_bank		= 0x03,
+		.update_reg		= 0x83,
+		.update_mask		= 0x10,
+		.update_val		= 0x10,
+		.mode_bank		= 0x01,
+		.mode_reg		= 0x54,
+		.mode_mask		= 0x04,
+		.mode_val_idle		= 0x04,
+		.mode_val_normal	= 0x00,
+	},
+	[AB8505_LDO_AUX8] = {
+		.desc = {
+			.name		= "LDO-AUX8",
+			.ops		= &ab8500_regulator_ops,
+			.type		= REGULATOR_VOLTAGE,
+			.id		= AB8505_LDO_AUX8,
+			.owner		= THIS_MODULE,
+			.n_voltages	= 1,
+			.volt_table	= fixed_1800000_voltage,
+		},
+		.update_bank		= 0x03,
+		.update_reg		= 0x83,
+		.update_mask		= 0x04,
+		.update_val		= 0x04,
+	},
+	/*
+	 * Regulators with fixed voltage and normal/idle modes
+	 */
+	[AB8505_LDO_ANA] = {
+		.desc = {
+			.name		= "LDO-ANA",
+			.ops		= &ab8500_regulator_volt_mode_ops,
+			.type		= REGULATOR_VOLTAGE,
+			.id		= AB8505_LDO_ANA,
+			.owner		= THIS_MODULE,
+			.n_voltages	= ARRAY_SIZE(ldo_vana_voltages),
+			.volt_table	= ldo_vana_voltages,
+		},
+		.load_lp_uA		= 1000,
+		.update_bank		= 0x04,
+		.update_reg		= 0x06,
+		.update_mask		= 0x0c,
+		.update_val		= 0x04,
+		.update_val_idle	= 0x0c,
+		.update_val_normal	= 0x04,
+		.voltage_bank		= 0x04,
+		.voltage_reg		= 0x29,
+		.voltage_mask		= 0x7,
+	},
+};
+
+/* AB9540 regulator information */
+static struct ab8500_regulator_info
+		ab9540_regulator_info[AB9540_NUM_REGULATORS] = {
+	/*
+	 * Variable Voltage Regulators
+	 *   name, min mV, max mV,
+	 *   update bank, reg, mask, enable val
+	 *   volt bank, reg, mask
+	 */
+	[AB9540_LDO_AUX1] = {
+		.desc = {
+			.name		= "LDO-AUX1",
+			.ops		= &ab8500_regulator_volt_mode_ops,
+			.type		= REGULATOR_VOLTAGE,
+			.id		= AB9540_LDO_AUX1,
+			.owner		= THIS_MODULE,
+			.n_voltages	= ARRAY_SIZE(ldo_vauxn_voltages),
+			.volt_table	= ldo_vauxn_voltages,
+		},
+		.load_lp_uA		= 5000,
+		.update_bank		= 0x04,
+		.update_reg		= 0x09,
+		.update_mask		= 0x03,
+		.update_val		= 0x01,
+		.update_val_idle	= 0x03,
+		.update_val_normal	= 0x01,
+		.voltage_bank		= 0x04,
+		.voltage_reg		= 0x1f,
+		.voltage_mask		= 0x0f,
+	},
+	[AB9540_LDO_AUX2] = {
+		.desc = {
+			.name		= "LDO-AUX2",
+			.ops		= &ab8500_regulator_volt_mode_ops,
+			.type		= REGULATOR_VOLTAGE,
+			.id		= AB9540_LDO_AUX2,
+			.owner		= THIS_MODULE,
+			.n_voltages	= ARRAY_SIZE(ldo_vauxn_voltages),
+			.volt_table	= ldo_vauxn_voltages,
+		},
+		.load_lp_uA		= 5000,
+		.update_bank		= 0x04,
+		.update_reg		= 0x09,
+		.update_mask		= 0x0c,
+		.update_val		= 0x04,
+		.update_val_idle	= 0x0c,
+		.update_val_normal	= 0x04,
+		.voltage_bank		= 0x04,
+		.voltage_reg		= 0x20,
+		.voltage_mask		= 0x0f,
+	},
+	[AB9540_LDO_AUX3] = {
+		.desc = {
+			.name		= "LDO-AUX3",
+			.ops		= &ab8500_regulator_volt_mode_ops,
+			.type		= REGULATOR_VOLTAGE,
+			.id		= AB9540_LDO_AUX3,
+			.owner		= THIS_MODULE,
+			.n_voltages	= ARRAY_SIZE(ldo_vaux3_voltages),
+			.volt_table	= ldo_vaux3_voltages,
+		},
+		.load_lp_uA		= 5000,
+		.update_bank		= 0x04,
+		.update_reg		= 0x0a,
+		.update_mask		= 0x03,
+		.update_val		= 0x01,
+		.update_val_idle	= 0x03,
+		.update_val_normal	= 0x01,
+		.voltage_bank		= 0x04,
+		.voltage_reg		= 0x21,
+		.voltage_mask		= 0x07,
+	},
+	[AB9540_LDO_AUX4] = {
+		.desc = {
+			.name		= "LDO-AUX4",
+			.ops		= &ab8500_regulator_volt_mode_ops,
+			.type		= REGULATOR_VOLTAGE,
+			.id		= AB9540_LDO_AUX4,
+			.owner		= THIS_MODULE,
+			.n_voltages	= ARRAY_SIZE(ldo_vauxn_voltages),
+			.volt_table	= ldo_vauxn_voltages,
+		},
+		.load_lp_uA		= 5000,
+		/* values for Vaux4Regu register */
+		.update_bank		= 0x04,
+		.update_reg		= 0x2e,
+		.update_mask		= 0x03,
+		.update_val		= 0x01,
+		.update_val_idle	= 0x03,
+		.update_val_normal	= 0x01,
+		/* values for Vaux4SEL register */
+		.voltage_bank		= 0x04,
+		.voltage_reg		= 0x2f,
+		.voltage_mask		= 0x0f,
+	},
+	[AB9540_LDO_INTCORE] = {
+		.desc = {
+			.name		= "LDO-INTCORE",
+			.ops		= &ab8500_regulator_volt_mode_ops,
+			.type		= REGULATOR_VOLTAGE,
+			.id		= AB9540_LDO_INTCORE,
+			.owner		= THIS_MODULE,
+			.n_voltages	= ARRAY_SIZE(ldo_vintcore_voltages),
+			.volt_table	= ldo_vintcore_voltages,
+		},
+		.load_lp_uA		= 5000,
+		.update_bank		= 0x03,
+		.update_reg		= 0x80,
+		.update_mask		= 0x44,
+		.update_val		= 0x44,
+		.update_val_idle	= 0x44,
+		.update_val_normal	= 0x04,
+		.voltage_bank		= 0x03,
+		.voltage_reg		= 0x80,
+		.voltage_mask		= 0x38,
+		.voltage_shift		= 3,
+	},
+
+	/*
+	 * Fixed Voltage Regulators
+	 *   name, fixed mV,
+	 *   update bank, reg, mask, enable val
+	 */
+	[AB9540_LDO_TVOUT] = {
+		.desc = {
+			.name		= "LDO-TVOUT",
+			.ops		= &ab8500_regulator_mode_ops,
+			.type		= REGULATOR_VOLTAGE,
+			.id		= AB9540_LDO_TVOUT,
+			.owner		= THIS_MODULE,
+			.n_voltages	= 1,
+			.volt_table	= fixed_2000000_voltage,
+			.enable_time	= 10000,
+		},
+		.load_lp_uA		= 1000,
+		.update_bank		= 0x03,
+		.update_reg		= 0x80,
+		.update_mask		= 0x82,
+		.update_val		= 0x02,
+		.update_val_idle	= 0x82,
+		.update_val_normal	= 0x02,
+	},
+	[AB9540_LDO_USB] = {
+		.desc = {
+			.name           = "LDO-USB",
+			.ops            = &ab8500_regulator_ops,
+			.type           = REGULATOR_VOLTAGE,
+			.id             = AB9540_LDO_USB,
+			.owner          = THIS_MODULE,
+			.n_voltages     = 1,
+			.volt_table	= fixed_3300000_voltage,
+		},
+		.update_bank            = 0x03,
+		.update_reg             = 0x82,
+		.update_mask            = 0x03,
+		.update_val		= 0x01,
+		.update_val_idle	= 0x03,
+		.update_val_normal	= 0x01,
+	},
+	[AB9540_LDO_AUDIO] = {
+		.desc = {
+			.name		= "LDO-AUDIO",
+			.ops		= &ab8500_regulator_ops,
+			.type		= REGULATOR_VOLTAGE,
+			.id		= AB9540_LDO_AUDIO,
+			.owner		= THIS_MODULE,
+			.n_voltages	= 1,
+			.volt_table	= fixed_2000000_voltage,
+		},
+		.update_bank		= 0x03,
+		.update_reg		= 0x83,
+		.update_mask		= 0x02,
+		.update_val		= 0x02,
+	},
+	[AB9540_LDO_ANAMIC1] = {
+		.desc = {
+			.name		= "LDO-ANAMIC1",
+			.ops		= &ab8500_regulator_ops,
+			.type		= REGULATOR_VOLTAGE,
+			.id		= AB9540_LDO_ANAMIC1,
+			.owner		= THIS_MODULE,
+			.n_voltages	= 1,
+			.volt_table	= fixed_2050000_voltage,
+		},
+		.update_bank		= 0x03,
+		.update_reg		= 0x83,
+		.update_mask		= 0x08,
+		.update_val		= 0x08,
+	},
+	[AB9540_LDO_ANAMIC2] = {
+		.desc = {
+			.name		= "LDO-ANAMIC2",
+			.ops		= &ab8500_regulator_ops,
+			.type		= REGULATOR_VOLTAGE,
+			.id		= AB9540_LDO_ANAMIC2,
+			.owner		= THIS_MODULE,
+			.n_voltages	= 1,
+			.volt_table	= fixed_2050000_voltage,
+		},
+		.update_bank		= 0x03,
+		.update_reg		= 0x83,
+		.update_mask		= 0x10,
+		.update_val		= 0x10,
+	},
+	[AB9540_LDO_DMIC] = {
+		.desc = {
+			.name		= "LDO-DMIC",
+			.ops		= &ab8500_regulator_ops,
+			.type		= REGULATOR_VOLTAGE,
+			.id		= AB9540_LDO_DMIC,
+			.owner		= THIS_MODULE,
+			.n_voltages	= 1,
+			.volt_table	= fixed_1800000_voltage,
+		},
+		.update_bank		= 0x03,
+		.update_reg		= 0x83,
+		.update_mask		= 0x04,
+		.update_val		= 0x04,
+	},
+
+	/*
+	 * Regulators with fixed voltage and normal/idle modes
+	 */
+	[AB9540_LDO_ANA] = {
+		.desc = {
+			.name		= "LDO-ANA",
+			.ops		= &ab8500_regulator_mode_ops,
+			.type		= REGULATOR_VOLTAGE,
+			.id		= AB9540_LDO_ANA,
+			.owner		= THIS_MODULE,
+			.n_voltages	= 1,
+			.volt_table	= fixed_1200000_voltage,
+		},
+		.load_lp_uA		= 1000,
+		.update_bank		= 0x04,
+		.update_reg		= 0x06,
+		.update_mask		= 0x0c,
+		.update_val		= 0x08,
+		.update_val_idle	= 0x0c,
+		.update_val_normal	= 0x08,
+	},
+};
+
+/* AB8540 regulator information */
+static struct ab8500_regulator_info
+		ab8540_regulator_info[AB8540_NUM_REGULATORS] = {
+	/*
+	 * Variable Voltage Regulators
+	 *   name, min mV, max mV,
+	 *   update bank, reg, mask, enable val
+	 *   volt bank, reg, mask
+	 */
+	[AB8540_LDO_AUX1] = {
+		.desc = {
+			.name		= "LDO-AUX1",
+			.ops		= &ab8500_regulator_volt_mode_ops,
+			.type		= REGULATOR_VOLTAGE,
+			.id		= AB8540_LDO_AUX1,
+			.owner		= THIS_MODULE,
+			.n_voltages	= ARRAY_SIZE(ldo_vauxn_voltages),
+			.volt_table	= ldo_vauxn_voltages,
+		},
+		.load_lp_uA		= 5000,
+		.update_bank		= 0x04,
+		.update_reg		= 0x09,
+		.update_mask		= 0x03,
+		.update_val		= 0x01,
+		.update_val_idle	= 0x03,
+		.update_val_normal	= 0x01,
+		.voltage_bank		= 0x04,
+		.voltage_reg		= 0x1f,
+		.voltage_mask		= 0x0f,
+	},
+	[AB8540_LDO_AUX2] = {
+		.desc = {
+			.name		= "LDO-AUX2",
+			.ops		= &ab8500_regulator_volt_mode_ops,
+			.type		= REGULATOR_VOLTAGE,
+			.id		= AB8540_LDO_AUX2,
+			.owner		= THIS_MODULE,
+			.n_voltages	= ARRAY_SIZE(ldo_vauxn_voltages),
+			.volt_table	= ldo_vauxn_voltages,
+		},
+		.load_lp_uA		= 5000,
+		.update_bank		= 0x04,
+		.update_reg		= 0x09,
+		.update_mask		= 0x0c,
+		.update_val		= 0x04,
+		.update_val_idle	= 0x0c,
+		.update_val_normal	= 0x04,
+		.voltage_bank		= 0x04,
+		.voltage_reg		= 0x20,
+		.voltage_mask		= 0x0f,
+	},
+	[AB8540_LDO_AUX3] = {
+		.desc = {
+			.name		= "LDO-AUX3",
+			.ops		= &ab8540_aux3_regulator_volt_mode_ops,
+			.type		= REGULATOR_VOLTAGE,
+			.id		= AB8540_LDO_AUX3,
+			.owner		= THIS_MODULE,
+			.n_voltages	= ARRAY_SIZE(ldo_vaux3_ab8540_voltages),
+			.volt_table	= ldo_vaux3_ab8540_voltages,
+		},
+		.load_lp_uA		= 5000,
+		.update_bank		= 0x04,
+		.update_reg		= 0x0a,
+		.update_mask		= 0x03,
+		.update_val		= 0x01,
+		.update_val_idle	= 0x03,
+		.update_val_normal	= 0x01,
+		.voltage_bank		= 0x04,
+		.voltage_reg		= 0x21,
+		.voltage_mask		= 0x07,
+		.expand_register = {
+			.voltage_limit		= 8,
+			.voltage_bank		= 0x04,
+			.voltage_reg		= 0x01,
+			.voltage_mask		= 0x10,
+			.voltage_shift		= 1,
+		}
+	},
+	[AB8540_LDO_AUX4] = {
+		.desc = {
+			.name		= "LDO-AUX4",
+			.ops		= &ab8500_regulator_volt_mode_ops,
+			.type		= REGULATOR_VOLTAGE,
+			.id		= AB8540_LDO_AUX4,
+			.owner		= THIS_MODULE,
+			.n_voltages	= ARRAY_SIZE(ldo_vauxn_voltages),
+			.volt_table	= ldo_vauxn_voltages,
+		},
+		.load_lp_uA		= 5000,
+		/* values for Vaux4Regu register */
+		.update_bank		= 0x04,
+		.update_reg		= 0x2e,
+		.update_mask		= 0x03,
+		.update_val		= 0x01,
+		.update_val_idle	= 0x03,
+		.update_val_normal	= 0x01,
+		/* values for Vaux4SEL register */
+		.voltage_bank		= 0x04,
+		.voltage_reg		= 0x2f,
+		.voltage_mask		= 0x0f,
+	},
+	[AB8540_LDO_AUX5] = {
+		.desc = {
+			.name		= "LDO-AUX5",
+			.ops		= &ab8500_regulator_volt_mode_ops,
+			.type		= REGULATOR_VOLTAGE,
+			.id		= AB8540_LDO_AUX5,
+			.owner		= THIS_MODULE,
+			.n_voltages	= ARRAY_SIZE(ldo_vaux56_ab8540_voltages),
+			.volt_table	= ldo_vaux56_ab8540_voltages,
+		},
+		.load_lp_uA		= 20000,
+		/* values for Vaux5Regu register */
+		.update_bank		= 0x04,
+		.update_reg		= 0x32,
+		.update_mask		= 0x03,
+		.update_val		= 0x01,
+		.update_val_idle	= 0x03,
+		.update_val_normal	= 0x01,
+		/* values for Vaux5SEL register */
+		.voltage_bank		= 0x04,
+		.voltage_reg		= 0x33,
+		.voltage_mask		= 0x3f,
+	},
+	[AB8540_LDO_AUX6] = {
+		.desc = {
+			.name		= "LDO-AUX6",
+			.ops		= &ab8500_regulator_volt_mode_ops,
+			.type		= REGULATOR_VOLTAGE,
+			.id		= AB8540_LDO_AUX6,
+			.owner		= THIS_MODULE,
+			.n_voltages	= ARRAY_SIZE(ldo_vaux56_ab8540_voltages),
+			.volt_table	= ldo_vaux56_ab8540_voltages,
+		},
+		.load_lp_uA		= 20000,
+		/* values for Vaux6Regu register */
+		.update_bank		= 0x04,
+		.update_reg		= 0x35,
+		.update_mask		= 0x03,
+		.update_val		= 0x01,
+		.update_val_idle	= 0x03,
+		.update_val_normal	= 0x01,
+		/* values for Vaux6SEL register */
+		.voltage_bank		= 0x04,
+		.voltage_reg		= 0x36,
+		.voltage_mask		= 0x3f,
+	},
+	[AB8540_LDO_INTCORE] = {
+		.desc = {
+			.name		= "LDO-INTCORE",
+			.ops		= &ab8500_regulator_volt_mode_ops,
+			.type		= REGULATOR_VOLTAGE,
+			.id		= AB8540_LDO_INTCORE,
+			.owner		= THIS_MODULE,
+			.n_voltages	= ARRAY_SIZE(ldo_vintcore_voltages),
+			.volt_table	= ldo_vintcore_voltages,
+		},
+		.load_lp_uA		= 5000,
+		.update_bank		= 0x03,
+		.update_reg		= 0x80,
+		.update_mask		= 0x44,
+		.update_val		= 0x44,
+		.update_val_idle	= 0x44,
+		.update_val_normal	= 0x04,
+		.voltage_bank		= 0x03,
+		.voltage_reg		= 0x80,
+		.voltage_mask		= 0x38,
+		.voltage_shift		= 3,
+	},
+
+	/*
+	 * Fixed Voltage Regulators
+	 *   name, fixed mV,
+	 *   update bank, reg, mask, enable val
+	 */
+	[AB8540_LDO_TVOUT] = {
+		.desc = {
+			.name		= "LDO-TVOUT",
+			.ops		= &ab8500_regulator_mode_ops,
+			.type		= REGULATOR_VOLTAGE,
+			.id		= AB8540_LDO_TVOUT,
+			.owner		= THIS_MODULE,
+			.n_voltages	= 1,
+			.volt_table     = fixed_2000000_voltage,
+			.enable_time	= 10000,
+		},
+		.load_lp_uA		= 1000,
+		.update_bank		= 0x03,
+		.update_reg		= 0x80,
+		.update_mask		= 0x82,
+		.update_val		= 0x02,
+		.update_val_idle	= 0x82,
+		.update_val_normal	= 0x02,
+	},
+	[AB8540_LDO_AUDIO] = {
+		.desc = {
+			.name		= "LDO-AUDIO",
+			.ops		= &ab8500_regulator_ops,
+			.type		= REGULATOR_VOLTAGE,
+			.id		= AB8540_LDO_AUDIO,
+			.owner		= THIS_MODULE,
+			.n_voltages	= 1,
+			.volt_table	= fixed_2000000_voltage,
+		},
+		.update_bank		= 0x03,
+		.update_reg		= 0x83,
+		.update_mask		= 0x02,
+		.update_val		= 0x02,
+	},
+	[AB8540_LDO_ANAMIC1] = {
+		.desc = {
+			.name		= "LDO-ANAMIC1",
+			.ops		= &ab8500_regulator_anamic_mode_ops,
+			.type		= REGULATOR_VOLTAGE,
+			.id		= AB8540_LDO_ANAMIC1,
+			.owner		= THIS_MODULE,
+			.n_voltages	= 1,
+			.volt_table	= fixed_2050000_voltage,
+		},
+		.shared_mode		= &ab8540_ldo_anamic1_shared,
+		.update_bank		= 0x03,
+		.update_reg		= 0x83,
+		.update_mask		= 0x08,
+		.update_val		= 0x08,
+		.mode_bank		= 0x03,
+		.mode_reg		= 0x83,
+		.mode_mask		= 0x20,
+		.mode_val_idle		= 0x20,
+		.mode_val_normal	= 0x00,
+	},
+	[AB8540_LDO_ANAMIC2] = {
+		.desc = {
+			.name		= "LDO-ANAMIC2",
+			.ops		= &ab8500_regulator_anamic_mode_ops,
+			.type		= REGULATOR_VOLTAGE,
+			.id		= AB8540_LDO_ANAMIC2,
+			.owner		= THIS_MODULE,
+			.n_voltages	= 1,
+			.volt_table	= fixed_2050000_voltage,
+		},
+		.shared_mode		= &ab8540_ldo_anamic2_shared,
+		.update_bank		= 0x03,
+		.update_reg		= 0x83,
+		.update_mask		= 0x10,
+		.update_val		= 0x10,
+		.mode_bank		= 0x03,
+		.mode_reg		= 0x83,
+		.mode_mask		= 0x20,
+		.mode_val_idle		= 0x20,
+		.mode_val_normal	= 0x00,
+	},
+	[AB8540_LDO_DMIC] = {
+		.desc = {
+			.name		= "LDO-DMIC",
+			.ops		= &ab8500_regulator_volt_mode_ops,
+			.type		= REGULATOR_VOLTAGE,
+			.id		= AB8540_LDO_DMIC,
+			.owner		= THIS_MODULE,
+			.n_voltages	= ARRAY_SIZE(ldo_vdmic_voltages),
+			.volt_table	= ldo_vdmic_voltages,
+		},
+		.load_lp_uA		= 1000,
+		.update_bank		= 0x03,
+		.update_reg		= 0x83,
+		.update_mask		= 0x04,
+		.update_val		= 0x04,
+		.voltage_bank		= 0x03,
+		.voltage_reg		= 0x83,
+		.voltage_mask		= 0xc0,
+	},
+
+	/*
+	 * Regulators with fixed voltage and normal/idle modes
+	 */
+	[AB8540_LDO_ANA] = {
+		.desc = {
+			.name		= "LDO-ANA",
+			.ops		= &ab8500_regulator_mode_ops,
+			.type		= REGULATOR_VOLTAGE,
+			.id		= AB8540_LDO_ANA,
+			.owner		= THIS_MODULE,
+			.n_voltages	= 1,
+			.volt_table     = fixed_1200000_voltage,
+		},
+		.load_lp_uA		= 1000,
+		.update_bank		= 0x04,
+		.update_reg		= 0x06,
+		.update_mask		= 0x0c,
+		.update_val		= 0x04,
+		.update_val_idle	= 0x0c,
+		.update_val_normal	= 0x04,
+	},
+	[AB8540_LDO_SDIO] = {
+		.desc = {
+			.name		= "LDO-SDIO",
+			.ops		= &ab8500_regulator_volt_mode_ops,
+			.type		= REGULATOR_VOLTAGE,
+			.id		= AB8540_LDO_SDIO,
+			.owner		= THIS_MODULE,
+			.n_voltages 	= ARRAY_SIZE(ldo_sdio_voltages),
+			.volt_table	= ldo_sdio_voltages,
+		},
+		.load_lp_uA		= 5000,
+		.update_bank		= 0x03,
+		.update_reg		= 0x88,
+		.update_mask		= 0x30,
+		.update_val		= 0x10,
+		.update_val_idle	= 0x30,
+		.update_val_normal	= 0x10,
+		.voltage_bank		= 0x03,
+		.voltage_reg		= 0x88,
+		.voltage_mask		= 0x07,
+	},
+};
+
+static struct ab8500_shared_mode ldo_anamic1_shared = {
+	.shared_regulator = &ab8505_regulator_info[AB8505_LDO_ANAMIC2],
+};
+
+static struct ab8500_shared_mode ldo_anamic2_shared = {
+	.shared_regulator = &ab8505_regulator_info[AB8505_LDO_ANAMIC1],
+};
+
+static struct ab8500_shared_mode ab8540_ldo_anamic1_shared = {
+	.shared_regulator = &ab8540_regulator_info[AB8540_LDO_ANAMIC2],
+};
+
+static struct ab8500_shared_mode ab8540_ldo_anamic2_shared = {
+	.shared_regulator = &ab8540_regulator_info[AB8540_LDO_ANAMIC1],
+};
+
+struct ab8500_reg_init {
+	u8 bank;
+	u8 addr;
+	u8 mask;
+};
+
+#define REG_INIT(_id, _bank, _addr, _mask)	\
+	[_id] = {				\
+		.bank = _bank,			\
+		.addr = _addr,			\
+		.mask = _mask,			\
+	}
+
+/* AB8500 register init */
+static struct ab8500_reg_init ab8500_reg_init[] = {
+	/*
+	 * 0x30, VanaRequestCtrl
+	 * 0xc0, VextSupply1RequestCtrl
+	 */
+	REG_INIT(AB8500_REGUREQUESTCTRL2,	0x03, 0x04, 0xf0),
+	/*
+	 * 0x03, VextSupply2RequestCtrl
+	 * 0x0c, VextSupply3RequestCtrl
+	 * 0x30, Vaux1RequestCtrl
+	 * 0xc0, Vaux2RequestCtrl
+	 */
+	REG_INIT(AB8500_REGUREQUESTCTRL3,	0x03, 0x05, 0xff),
+	/*
+	 * 0x03, Vaux3RequestCtrl
+	 * 0x04, SwHPReq
 	 */
 	REG_INIT(AB8500_REGUREQUESTCTRL4,	0x03, 0x06, 0x07),
 	/*
@@ -499,44 +1848,801 @@ static struct ab8500_reg_init ab8500_reg_init[] = {
 	 * 0x40, Vaux2SysClkReq1HPValid
 	 * 0x80, Vaux3SysClkReq1HPValid
 	 */
-	REG_INIT(AB8500_REGUSYSCLKREQ1HPVALID1,	0x03, 0x07, 0xe8),
+	REG_INIT(AB8500_REGUSYSCLKREQ1HPVALID1,	0x03, 0x07, 0xe8),
+	/*
+	 * 0x10, VextSupply1SysClkReq1HPValid
+	 * 0x20, VextSupply2SysClkReq1HPValid
+	 * 0x40, VextSupply3SysClkReq1HPValid
+	 */
+	REG_INIT(AB8500_REGUSYSCLKREQ1HPVALID2,	0x03, 0x08, 0x70),
+	/*
+	 * 0x08, VanaHwHPReq1Valid
+	 * 0x20, Vaux1HwHPReq1Valid
+	 * 0x40, Vaux2HwHPReq1Valid
+	 * 0x80, Vaux3HwHPReq1Valid
+	 */
+	REG_INIT(AB8500_REGUHWHPREQ1VALID1,	0x03, 0x09, 0xe8),
+	/*
+	 * 0x01, VextSupply1HwHPReq1Valid
+	 * 0x02, VextSupply2HwHPReq1Valid
+	 * 0x04, VextSupply3HwHPReq1Valid
+	 */
+	REG_INIT(AB8500_REGUHWHPREQ1VALID2,	0x03, 0x0a, 0x07),
+	/*
+	 * 0x08, VanaHwHPReq2Valid
+	 * 0x20, Vaux1HwHPReq2Valid
+	 * 0x40, Vaux2HwHPReq2Valid
+	 * 0x80, Vaux3HwHPReq2Valid
+	 */
+	REG_INIT(AB8500_REGUHWHPREQ2VALID1,	0x03, 0x0b, 0xe8),
+	/*
+	 * 0x01, VextSupply1HwHPReq2Valid
+	 * 0x02, VextSupply2HwHPReq2Valid
+	 * 0x04, VextSupply3HwHPReq2Valid
+	 */
+	REG_INIT(AB8500_REGUHWHPREQ2VALID2,	0x03, 0x0c, 0x07),
+	/*
+	 * 0x20, VanaSwHPReqValid
+	 * 0x80, Vaux1SwHPReqValid
+	 */
+	REG_INIT(AB8500_REGUSWHPREQVALID1,	0x03, 0x0d, 0xa0),
+	/*
+	 * 0x01, Vaux2SwHPReqValid
+	 * 0x02, Vaux3SwHPReqValid
+	 * 0x04, VextSupply1SwHPReqValid
+	 * 0x08, VextSupply2SwHPReqValid
+	 * 0x10, VextSupply3SwHPReqValid
+	 */
+	REG_INIT(AB8500_REGUSWHPREQVALID2,	0x03, 0x0e, 0x1f),
+	/*
+	 * 0x02, SysClkReq2Valid1
+	 * 0x04, SysClkReq3Valid1
+	 * 0x08, SysClkReq4Valid1
+	 * 0x10, SysClkReq5Valid1
+	 * 0x20, SysClkReq6Valid1
+	 * 0x40, SysClkReq7Valid1
+	 * 0x80, SysClkReq8Valid1
+	 */
+	REG_INIT(AB8500_REGUSYSCLKREQVALID1,	0x03, 0x0f, 0xfe),
+	/*
+	 * 0x02, SysClkReq2Valid2
+	 * 0x04, SysClkReq3Valid2
+	 * 0x08, SysClkReq4Valid2
+	 * 0x10, SysClkReq5Valid2
+	 * 0x20, SysClkReq6Valid2
+	 * 0x40, SysClkReq7Valid2
+	 * 0x80, SysClkReq8Valid2
+	 */
+	REG_INIT(AB8500_REGUSYSCLKREQVALID2,	0x03, 0x10, 0xfe),
+	/*
+	 * 0x02, VTVoutEna
+	 * 0x04, Vintcore12Ena
+	 * 0x38, Vintcore12Sel
+	 * 0x40, Vintcore12LP
+	 * 0x80, VTVoutLP
+	 */
+	REG_INIT(AB8500_REGUMISC1,		0x03, 0x80, 0xfe),
+	/*
+	 * 0x02, VaudioEna
+	 * 0x04, VdmicEna
+	 * 0x08, Vamic1Ena
+	 * 0x10, Vamic2Ena
+	 */
+	REG_INIT(AB8500_VAUDIOSUPPLY,		0x03, 0x83, 0x1e),
+	/*
+	 * 0x01, Vamic1_dzout
+	 * 0x02, Vamic2_dzout
+	 */
+	REG_INIT(AB8500_REGUCTRL1VAMIC,		0x03, 0x84, 0x03),
+	/*
+	 * 0x03, VpllRegu (NOTE! PRCMU register bits)
+	 * 0x0c, VanaRegu
+	 */
+	REG_INIT(AB8500_VPLLVANAREGU,		0x04, 0x06, 0x0f),
+	/*
+	 * 0x01, VrefDDREna
+	 * 0x02, VrefDDRSleepMode
+	 */
+	REG_INIT(AB8500_VREFDDR,		0x04, 0x07, 0x03),
+	/*
+	 * 0x03, VextSupply1Regu
+	 * 0x0c, VextSupply2Regu
+	 * 0x30, VextSupply3Regu
+	 * 0x40, ExtSupply2Bypass
+	 * 0x80, ExtSupply3Bypass
+	 */
+	REG_INIT(AB8500_EXTSUPPLYREGU,		0x04, 0x08, 0xff),
+	/*
+	 * 0x03, Vaux1Regu
+	 * 0x0c, Vaux2Regu
+	 */
+	REG_INIT(AB8500_VAUX12REGU,		0x04, 0x09, 0x0f),
+	/*
+	 * 0x03, Vaux3Regu
+	 */
+	REG_INIT(AB8500_VRF1VAUX3REGU,		0x04, 0x0a, 0x03),
+	/*
+	 * 0x0f, Vaux1Sel
+	 */
+	REG_INIT(AB8500_VAUX1SEL,		0x04, 0x1f, 0x0f),
+	/*
+	 * 0x0f, Vaux2Sel
+	 */
+	REG_INIT(AB8500_VAUX2SEL,		0x04, 0x20, 0x0f),
+	/*
+	 * 0x07, Vaux3Sel
+	 */
+	REG_INIT(AB8500_VRF1VAUX3SEL,		0x04, 0x21, 0x07),
+	/*
+	 * 0x01, VextSupply12LP
+	 */
+	REG_INIT(AB8500_REGUCTRL2SPARE,		0x04, 0x22, 0x01),
+	/*
+	 * 0x04, Vaux1Disch
+	 * 0x08, Vaux2Disch
+	 * 0x10, Vaux3Disch
+	 * 0x20, Vintcore12Disch
+	 * 0x40, VTVoutDisch
+	 * 0x80, VaudioDisch
+	 */
+	REG_INIT(AB8500_REGUCTRLDISCH,		0x04, 0x43, 0xfc),
+	/*
+	 * 0x02, VanaDisch
+	 * 0x04, VdmicPullDownEna
+	 * 0x10, VdmicDisch
+	 */
+	REG_INIT(AB8500_REGUCTRLDISCH2,		0x04, 0x44, 0x16),
+};
+
+/* AB8505 register init */
+static struct ab8500_reg_init ab8505_reg_init[] = {
+	/*
+	 * 0x03, VarmRequestCtrl
+	 * 0x0c, VsmpsCRequestCtrl
+	 * 0x30, VsmpsARequestCtrl
+	 * 0xc0, VsmpsBRequestCtrl
+	 */
+	REG_INIT(AB8505_REGUREQUESTCTRL1,	0x03, 0x03, 0xff),
+	/*
+	 * 0x03, VsafeRequestCtrl
+	 * 0x0c, VpllRequestCtrl
+	 * 0x30, VanaRequestCtrl
+	 */
+	REG_INIT(AB8505_REGUREQUESTCTRL2,	0x03, 0x04, 0x3f),
+	/*
+	 * 0x30, Vaux1RequestCtrl
+	 * 0xc0, Vaux2RequestCtrl
+	 */
+	REG_INIT(AB8505_REGUREQUESTCTRL3,	0x03, 0x05, 0xf0),
+	/*
+	 * 0x03, Vaux3RequestCtrl
+	 * 0x04, SwHPReq
+	 */
+	REG_INIT(AB8505_REGUREQUESTCTRL4,	0x03, 0x06, 0x07),
+	/*
+	 * 0x01, VsmpsASysClkReq1HPValid
+	 * 0x02, VsmpsBSysClkReq1HPValid
+	 * 0x04, VsafeSysClkReq1HPValid
+	 * 0x08, VanaSysClkReq1HPValid
+	 * 0x10, VpllSysClkReq1HPValid
+	 * 0x20, Vaux1SysClkReq1HPValid
+	 * 0x40, Vaux2SysClkReq1HPValid
+	 * 0x80, Vaux3SysClkReq1HPValid
+	 */
+	REG_INIT(AB8505_REGUSYSCLKREQ1HPVALID1,	0x03, 0x07, 0xff),
+	/*
+	 * 0x01, VsmpsCSysClkReq1HPValid
+	 * 0x02, VarmSysClkReq1HPValid
+	 * 0x04, VbbSysClkReq1HPValid
+	 * 0x08, VsmpsMSysClkReq1HPValid
+	 */
+	REG_INIT(AB8505_REGUSYSCLKREQ1HPVALID2,	0x03, 0x08, 0x0f),
+	/*
+	 * 0x01, VsmpsAHwHPReq1Valid
+	 * 0x02, VsmpsBHwHPReq1Valid
+	 * 0x04, VsafeHwHPReq1Valid
+	 * 0x08, VanaHwHPReq1Valid
+	 * 0x10, VpllHwHPReq1Valid
+	 * 0x20, Vaux1HwHPReq1Valid
+	 * 0x40, Vaux2HwHPReq1Valid
+	 * 0x80, Vaux3HwHPReq1Valid
+	 */
+	REG_INIT(AB8505_REGUHWHPREQ1VALID1,	0x03, 0x09, 0xff),
+	/*
+	 * 0x08, VsmpsMHwHPReq1Valid
+	 */
+	REG_INIT(AB8505_REGUHWHPREQ1VALID2,	0x03, 0x0a, 0x08),
+	/*
+	 * 0x01, VsmpsAHwHPReq2Valid
+	 * 0x02, VsmpsBHwHPReq2Valid
+	 * 0x04, VsafeHwHPReq2Valid
+	 * 0x08, VanaHwHPReq2Valid
+	 * 0x10, VpllHwHPReq2Valid
+	 * 0x20, Vaux1HwHPReq2Valid
+	 * 0x40, Vaux2HwHPReq2Valid
+	 * 0x80, Vaux3HwHPReq2Valid
+	 */
+	REG_INIT(AB8505_REGUHWHPREQ2VALID1,	0x03, 0x0b, 0xff),
+	/*
+	 * 0x08, VsmpsMHwHPReq2Valid
+	 */
+	REG_INIT(AB8505_REGUHWHPREQ2VALID2,	0x03, 0x0c, 0x08),
+	/*
+	 * 0x01, VsmpsCSwHPReqValid
+	 * 0x02, VarmSwHPReqValid
+	 * 0x04, VsmpsASwHPReqValid
+	 * 0x08, VsmpsBSwHPReqValid
+	 * 0x10, VsafeSwHPReqValid
+	 * 0x20, VanaSwHPReqValid
+	 * 0x40, VpllSwHPReqValid
+	 * 0x80, Vaux1SwHPReqValid
+	 */
+	REG_INIT(AB8505_REGUSWHPREQVALID1,	0x03, 0x0d, 0xff),
+	/*
+	 * 0x01, Vaux2SwHPReqValid
+	 * 0x02, Vaux3SwHPReqValid
+	 * 0x20, VsmpsMSwHPReqValid
+	 */
+	REG_INIT(AB8505_REGUSWHPREQVALID2,	0x03, 0x0e, 0x23),
+	/*
+	 * 0x02, SysClkReq2Valid1
+	 * 0x04, SysClkReq3Valid1
+	 * 0x08, SysClkReq4Valid1
+	 */
+	REG_INIT(AB8505_REGUSYSCLKREQVALID1,	0x03, 0x0f, 0x0e),
+	/*
+	 * 0x02, SysClkReq2Valid2
+	 * 0x04, SysClkReq3Valid2
+	 * 0x08, SysClkReq4Valid2
+	 */
+	REG_INIT(AB8505_REGUSYSCLKREQVALID2,	0x03, 0x10, 0x0e),
+	/*
+	 * 0x01, Vaux4SwHPReqValid
+	 * 0x02, Vaux4HwHPReq2Valid
+	 * 0x04, Vaux4HwHPReq1Valid
+	 * 0x08, Vaux4SysClkReq1HPValid
+	 */
+	REG_INIT(AB8505_REGUVAUX4REQVALID,	0x03, 0x11, 0x0f),
+	/*
+	 * 0x02, VadcEna
+	 * 0x04, VintCore12Ena
+	 * 0x38, VintCore12Sel
+	 * 0x40, VintCore12LP
+	 * 0x80, VadcLP
+	 */
+	REG_INIT(AB8505_REGUMISC1,		0x03, 0x80, 0xfe),
+	/*
+	 * 0x02, VaudioEna
+	 * 0x04, VdmicEna
+	 * 0x08, Vamic1Ena
+	 * 0x10, Vamic2Ena
+	 */
+	REG_INIT(AB8505_VAUDIOSUPPLY,		0x03, 0x83, 0x1e),
+	/*
+	 * 0x01, Vamic1_dzout
+	 * 0x02, Vamic2_dzout
+	 */
+	REG_INIT(AB8505_REGUCTRL1VAMIC,		0x03, 0x84, 0x03),
+	/*
+	 * 0x03, VsmpsARegu
+	 * 0x0c, VsmpsASelCtrl
+	 * 0x10, VsmpsAAutoMode
+	 * 0x20, VsmpsAPWMMode
+	 */
+	REG_INIT(AB8505_VSMPSAREGU,		0x04, 0x03, 0x3f),
+	/*
+	 * 0x03, VsmpsBRegu
+	 * 0x0c, VsmpsBSelCtrl
+	 * 0x10, VsmpsBAutoMode
+	 * 0x20, VsmpsBPWMMode
+	 */
+	REG_INIT(AB8505_VSMPSBREGU,		0x04, 0x04, 0x3f),
+	/*
+	 * 0x03, VsafeRegu
+	 * 0x0c, VsafeSelCtrl
+	 * 0x10, VsafeAutoMode
+	 * 0x20, VsafePWMMode
+	 */
+	REG_INIT(AB8505_VSAFEREGU,		0x04, 0x05, 0x3f),
+	/*
+	 * 0x03, VpllRegu (NOTE! PRCMU register bits)
+	 * 0x0c, VanaRegu
+	 */
+	REG_INIT(AB8505_VPLLVANAREGU,		0x04, 0x06, 0x0f),
+	/*
+	 * 0x03, VextSupply1Regu
+	 * 0x0c, VextSupply2Regu
+	 * 0x30, VextSupply3Regu
+	 * 0x40, ExtSupply2Bypass
+	 * 0x80, ExtSupply3Bypass
+	 */
+	REG_INIT(AB8505_EXTSUPPLYREGU,		0x04, 0x08, 0xff),
+	/*
+	 * 0x03, Vaux1Regu
+	 * 0x0c, Vaux2Regu
+	 */
+	REG_INIT(AB8505_VAUX12REGU,		0x04, 0x09, 0x0f),
+	/*
+	 * 0x0f, Vaux3Regu
+	 */
+	REG_INIT(AB8505_VRF1VAUX3REGU,		0x04, 0x0a, 0x0f),
+	/*
+	 * 0x3f, VsmpsASel1
+	 */
+	REG_INIT(AB8505_VSMPSASEL1,		0x04, 0x13, 0x3f),
+	/*
+	 * 0x3f, VsmpsASel2
+	 */
+	REG_INIT(AB8505_VSMPSASEL2,		0x04, 0x14, 0x3f),
+	/*
+	 * 0x3f, VsmpsASel3
+	 */
+	REG_INIT(AB8505_VSMPSASEL3,		0x04, 0x15, 0x3f),
+	/*
+	 * 0x3f, VsmpsBSel1
+	 */
+	REG_INIT(AB8505_VSMPSBSEL1,		0x04, 0x17, 0x3f),
+	/*
+	 * 0x3f, VsmpsBSel2
+	 */
+	REG_INIT(AB8505_VSMPSBSEL2,		0x04, 0x18, 0x3f),
+	/*
+	 * 0x3f, VsmpsBSel3
+	 */
+	REG_INIT(AB8505_VSMPSBSEL3,		0x04, 0x19, 0x3f),
+	/*
+	 * 0x7f, VsafeSel1
+	 */
+	REG_INIT(AB8505_VSAFESEL1,		0x04, 0x1b, 0x7f),
+	/*
+	 * 0x3f, VsafeSel2
+	 */
+	REG_INIT(AB8505_VSAFESEL2,		0x04, 0x1c, 0x7f),
+	/*
+	 * 0x3f, VsafeSel3
+	 */
+	REG_INIT(AB8505_VSAFESEL3,		0x04, 0x1d, 0x7f),
+	/*
+	 * 0x0f, Vaux1Sel
+	 */
+	REG_INIT(AB8505_VAUX1SEL,		0x04, 0x1f, 0x0f),
+	/*
+	 * 0x0f, Vaux2Sel
+	 */
+	REG_INIT(AB8505_VAUX2SEL,		0x04, 0x20, 0x0f),
+	/*
+	 * 0x07, Vaux3Sel
+	 * 0x30, VRF1Sel
+	 */
+	REG_INIT(AB8505_VRF1VAUX3SEL,		0x04, 0x21, 0x37),
+	/*
+	 * 0x03, Vaux4RequestCtrl
+	 */
+	REG_INIT(AB8505_VAUX4REQCTRL,		0x04, 0x2d, 0x03),
+	/*
+	 * 0x03, Vaux4Regu
+	 */
+	REG_INIT(AB8505_VAUX4REGU,		0x04, 0x2e, 0x03),
+	/*
+	 * 0x0f, Vaux4Sel
+	 */
+	REG_INIT(AB8505_VAUX4SEL,		0x04, 0x2f, 0x0f),
+	/*
+	 * 0x04, Vaux1Disch
+	 * 0x08, Vaux2Disch
+	 * 0x10, Vaux3Disch
+	 * 0x20, Vintcore12Disch
+	 * 0x40, VTVoutDisch
+	 * 0x80, VaudioDisch
+	 */
+	REG_INIT(AB8505_REGUCTRLDISCH,		0x04, 0x43, 0xfc),
+	/*
+	 * 0x02, VanaDisch
+	 * 0x04, VdmicPullDownEna
+	 * 0x10, VdmicDisch
+	 */
+	REG_INIT(AB8505_REGUCTRLDISCH2,		0x04, 0x44, 0x16),
+	/*
+	 * 0x01, Vaux4Disch
+	 */
+	REG_INIT(AB8505_REGUCTRLDISCH3,		0x04, 0x48, 0x01),
+	/*
+	 * 0x07, Vaux5Sel
+	 * 0x08, Vaux5LP
+	 * 0x10, Vaux5Ena
+	 * 0x20, Vaux5Disch
+	 * 0x40, Vaux5DisSfst
+	 * 0x80, Vaux5DisPulld
+	 */
+	REG_INIT(AB8505_CTRLVAUX5,		0x01, 0x55, 0xff),
+	/*
+	 * 0x07, Vaux6Sel
+	 * 0x08, Vaux6LP
+	 * 0x10, Vaux6Ena
+	 * 0x80, Vaux6DisPulld
+	 */
+	REG_INIT(AB8505_CTRLVAUX6,		0x01, 0x56, 0x9f),
+};
+
+/* AB9540 register init */
+static struct ab8500_reg_init ab9540_reg_init[] = {
+	/*
+	 * 0x03, VarmRequestCtrl
+	 * 0x0c, VapeRequestCtrl
+	 * 0x30, Vsmps1RequestCtrl
+	 * 0xc0, Vsmps2RequestCtrl
+	 */
+	REG_INIT(AB9540_REGUREQUESTCTRL1,	0x03, 0x03, 0xff),
+	/*
+	 * 0x03, Vsmps3RequestCtrl
+	 * 0x0c, VpllRequestCtrl
+	 * 0x30, VanaRequestCtrl
+	 * 0xc0, VextSupply1RequestCtrl
+	 */
+	REG_INIT(AB9540_REGUREQUESTCTRL2,	0x03, 0x04, 0xff),
+	/*
+	 * 0x03, VextSupply2RequestCtrl
+	 * 0x0c, VextSupply3RequestCtrl
+	 * 0x30, Vaux1RequestCtrl
+	 * 0xc0, Vaux2RequestCtrl
+	 */
+	REG_INIT(AB9540_REGUREQUESTCTRL3,	0x03, 0x05, 0xff),
+	/*
+	 * 0x03, Vaux3RequestCtrl
+	 * 0x04, SwHPReq
+	 */
+	REG_INIT(AB9540_REGUREQUESTCTRL4,	0x03, 0x06, 0x07),
+	/*
+	 * 0x01, Vsmps1SysClkReq1HPValid
+	 * 0x02, Vsmps2SysClkReq1HPValid
+	 * 0x04, Vsmps3SysClkReq1HPValid
+	 * 0x08, VanaSysClkReq1HPValid
+	 * 0x10, VpllSysClkReq1HPValid
+	 * 0x20, Vaux1SysClkReq1HPValid
+	 * 0x40, Vaux2SysClkReq1HPValid
+	 * 0x80, Vaux3SysClkReq1HPValid
+	 */
+	REG_INIT(AB9540_REGUSYSCLKREQ1HPVALID1,	0x03, 0x07, 0xff),
+	/*
+	 * 0x01, VapeSysClkReq1HPValid
+	 * 0x02, VarmSysClkReq1HPValid
+	 * 0x04, VbbSysClkReq1HPValid
+	 * 0x08, VmodSysClkReq1HPValid
+	 * 0x10, VextSupply1SysClkReq1HPValid
+	 * 0x20, VextSupply2SysClkReq1HPValid
+	 * 0x40, VextSupply3SysClkReq1HPValid
+	 */
+	REG_INIT(AB9540_REGUSYSCLKREQ1HPVALID2,	0x03, 0x08, 0x7f),
+	/*
+	 * 0x01, Vsmps1HwHPReq1Valid
+	 * 0x02, Vsmps2HwHPReq1Valid
+	 * 0x04, Vsmps3HwHPReq1Valid
+	 * 0x08, VanaHwHPReq1Valid
+	 * 0x10, VpllHwHPReq1Valid
+	 * 0x20, Vaux1HwHPReq1Valid
+	 * 0x40, Vaux2HwHPReq1Valid
+	 * 0x80, Vaux3HwHPReq1Valid
+	 */
+	REG_INIT(AB9540_REGUHWHPREQ1VALID1,	0x03, 0x09, 0xff),
+	/*
+	 * 0x01, VextSupply1HwHPReq1Valid
+	 * 0x02, VextSupply2HwHPReq1Valid
+	 * 0x04, VextSupply3HwHPReq1Valid
+	 * 0x08, VmodHwHPReq1Valid
+	 */
+	REG_INIT(AB9540_REGUHWHPREQ1VALID2,	0x03, 0x0a, 0x0f),
+	/*
+	 * 0x01, Vsmps1HwHPReq2Valid
+	 * 0x02, Vsmps2HwHPReq2Valid
+	 * 0x03, Vsmps3HwHPReq2Valid
+	 * 0x08, VanaHwHPReq2Valid
+	 * 0x10, VpllHwHPReq2Valid
+	 * 0x20, Vaux1HwHPReq2Valid
+	 * 0x40, Vaux2HwHPReq2Valid
+	 * 0x80, Vaux3HwHPReq2Valid
+	 */
+	REG_INIT(AB9540_REGUHWHPREQ2VALID1,	0x03, 0x0b, 0xff),
+	/*
+	 * 0x01, VextSupply1HwHPReq2Valid
+	 * 0x02, VextSupply2HwHPReq2Valid
+	 * 0x04, VextSupply3HwHPReq2Valid
+	 * 0x08, VmodHwHPReq2Valid
+	 */
+	REG_INIT(AB9540_REGUHWHPREQ2VALID2,	0x03, 0x0c, 0x0f),
+	/*
+	 * 0x01, VapeSwHPReqValid
+	 * 0x02, VarmSwHPReqValid
+	 * 0x04, Vsmps1SwHPReqValid
+	 * 0x08, Vsmps2SwHPReqValid
+	 * 0x10, Vsmps3SwHPReqValid
+	 * 0x20, VanaSwHPReqValid
+	 * 0x40, VpllSwHPReqValid
+	 * 0x80, Vaux1SwHPReqValid
+	 */
+	REG_INIT(AB9540_REGUSWHPREQVALID1,	0x03, 0x0d, 0xff),
+	/*
+	 * 0x01, Vaux2SwHPReqValid
+	 * 0x02, Vaux3SwHPReqValid
+	 * 0x04, VextSupply1SwHPReqValid
+	 * 0x08, VextSupply2SwHPReqValid
+	 * 0x10, VextSupply3SwHPReqValid
+	 * 0x20, VmodSwHPReqValid
+	 */
+	REG_INIT(AB9540_REGUSWHPREQVALID2,	0x03, 0x0e, 0x3f),
+	/*
+	 * 0x02, SysClkReq2Valid1
+	 * ...
+	 * 0x80, SysClkReq8Valid1
+	 */
+	REG_INIT(AB9540_REGUSYSCLKREQVALID1,	0x03, 0x0f, 0xfe),
+	/*
+	 * 0x02, SysClkReq2Valid2
+	 * ...
+	 * 0x80, SysClkReq8Valid2
+	 */
+	REG_INIT(AB9540_REGUSYSCLKREQVALID2,	0x03, 0x10, 0xfe),
+	/*
+	 * 0x01, Vaux4SwHPReqValid
+	 * 0x02, Vaux4HwHPReq2Valid
+	 * 0x04, Vaux4HwHPReq1Valid
+	 * 0x08, Vaux4SysClkReq1HPValid
+	 */
+	REG_INIT(AB9540_REGUVAUX4REQVALID,	0x03, 0x11, 0x0f),
+	/*
+	 * 0x02, VTVoutEna
+	 * 0x04, Vintcore12Ena
+	 * 0x38, Vintcore12Sel
+	 * 0x40, Vintcore12LP
+	 * 0x80, VTVoutLP
+	 */
+	REG_INIT(AB9540_REGUMISC1,		0x03, 0x80, 0xfe),
+	/*
+	 * 0x02, VaudioEna
+	 * 0x04, VdmicEna
+	 * 0x08, Vamic1Ena
+	 * 0x10, Vamic2Ena
+	 */
+	REG_INIT(AB9540_VAUDIOSUPPLY,		0x03, 0x83, 0x1e),
+	/*
+	 * 0x01, Vamic1_dzout
+	 * 0x02, Vamic2_dzout
+	 */
+	REG_INIT(AB9540_REGUCTRL1VAMIC,		0x03, 0x84, 0x03),
+	/*
+	 * 0x03, Vsmps1Regu
+	 * 0x0c, Vsmps1SelCtrl
+	 * 0x10, Vsmps1AutoMode
+	 * 0x20, Vsmps1PWMMode
+	 */
+	REG_INIT(AB9540_VSMPS1REGU,		0x04, 0x03, 0x3f),
+	/*
+	 * 0x03, Vsmps2Regu
+	 * 0x0c, Vsmps2SelCtrl
+	 * 0x10, Vsmps2AutoMode
+	 * 0x20, Vsmps2PWMMode
+	 */
+	REG_INIT(AB9540_VSMPS2REGU,		0x04, 0x04, 0x3f),
+	/*
+	 * 0x03, Vsmps3Regu
+	 * 0x0c, Vsmps3SelCtrl
+	 * NOTE! PRCMU register
+	 */
+	REG_INIT(AB9540_VSMPS3REGU,		0x04, 0x05, 0x0f),
+	/*
+	 * 0x03, VpllRegu
+	 * 0x0c, VanaRegu
+	 */
+	REG_INIT(AB9540_VPLLVANAREGU,		0x04, 0x06, 0x0f),
+	/*
+	 * 0x03, VextSupply1Regu
+	 * 0x0c, VextSupply2Regu
+	 * 0x30, VextSupply3Regu
+	 * 0x40, ExtSupply2Bypass
+	 * 0x80, ExtSupply3Bypass
+	 */
+	REG_INIT(AB9540_EXTSUPPLYREGU,		0x04, 0x08, 0xff),
+	/*
+	 * 0x03, Vaux1Regu
+	 * 0x0c, Vaux2Regu
+	 */
+	REG_INIT(AB9540_VAUX12REGU,		0x04, 0x09, 0x0f),
+	/*
+	 * 0x0c, Vrf1Regu
+	 * 0x03, Vaux3Regu
+	 */
+	REG_INIT(AB9540_VRF1VAUX3REGU,		0x04, 0x0a, 0x0f),
+	/*
+	 * 0x3f, Vsmps1Sel1
+	 */
+	REG_INIT(AB9540_VSMPS1SEL1,		0x04, 0x13, 0x3f),
+	/*
+	 * 0x3f, Vsmps1Sel2
+	 */
+	REG_INIT(AB9540_VSMPS1SEL2,		0x04, 0x14, 0x3f),
+	/*
+	 * 0x3f, Vsmps1Sel3
+	 */
+	REG_INIT(AB9540_VSMPS1SEL3,		0x04, 0x15, 0x3f),
+	/*
+	 * 0x3f, Vsmps2Sel1
+	 */
+	REG_INIT(AB9540_VSMPS2SEL1,		0x04, 0x17, 0x3f),
+	/*
+	 * 0x3f, Vsmps2Sel2
+	 */
+	REG_INIT(AB9540_VSMPS2SEL2,		0x04, 0x18, 0x3f),
+	/*
+	 * 0x3f, Vsmps2Sel3
+	 */
+	REG_INIT(AB9540_VSMPS2SEL3,		0x04, 0x19, 0x3f),
+	/*
+	 * 0x7f, Vsmps3Sel1
+	 * NOTE! PRCMU register
+	 */
+	REG_INIT(AB9540_VSMPS3SEL1,             0x04, 0x1b, 0x7f),
+	/*
+	 * 0x7f, Vsmps3Sel2
+	 * NOTE! PRCMU register
+	 */
+	REG_INIT(AB9540_VSMPS3SEL2,             0x04, 0x1c, 0x7f),
+	/*
+	 * 0x0f, Vaux1Sel
+	 */
+	REG_INIT(AB9540_VAUX1SEL,		0x04, 0x1f, 0x0f),
+	/*
+	 * 0x0f, Vaux2Sel
+	 */
+	REG_INIT(AB9540_VAUX2SEL,		0x04, 0x20, 0x0f),
+	/*
+	 * 0x07, Vaux3Sel
+	 * 0x30, Vrf1Sel
+	 */
+	REG_INIT(AB9540_VRF1VAUX3SEL,		0x04, 0x21, 0x37),
+	/*
+	 * 0x01, VextSupply12LP
+	 */
+	REG_INIT(AB9540_REGUCTRL2SPARE,		0x04, 0x22, 0x01),
+	/*
+	 * 0x03, Vaux4RequestCtrl
+	 */
+	REG_INIT(AB9540_VAUX4REQCTRL,		0x04, 0x2d, 0x03),
+	/*
+	 * 0x03, Vaux4Regu
+	 */
+	REG_INIT(AB9540_VAUX4REGU,		0x04, 0x2e, 0x03),
+	/*
+	 * 0x08, Vaux4Sel
+	 */
+	REG_INIT(AB9540_VAUX4SEL,		0x04, 0x2f, 0x0f),
+	/*
+	 * 0x01, VpllDisch
+	 * 0x02, Vrf1Disch
+	 * 0x04, Vaux1Disch
+	 * 0x08, Vaux2Disch
+	 * 0x10, Vaux3Disch
+	 * 0x20, Vintcore12Disch
+	 * 0x40, VTVoutDisch
+	 * 0x80, VaudioDisch
+	 */
+	REG_INIT(AB9540_REGUCTRLDISCH,		0x04, 0x43, 0xff),
+	/*
+	 * 0x01, VsimDisch
+	 * 0x02, VanaDisch
+	 * 0x04, VdmicPullDownEna
+	 * 0x08, VpllPullDownEna
+	 * 0x10, VdmicDisch
+	 */
+	REG_INIT(AB9540_REGUCTRLDISCH2,		0x04, 0x44, 0x1f),
+	/*
+	 * 0x01, Vaux4Disch
+	 */
+	REG_INIT(AB9540_REGUCTRLDISCH3,		0x04, 0x48, 0x01),
+};
+
+/* AB8540 register init */
+static struct ab8500_reg_init ab8540_reg_init[] = {
+	/*
+	 * 0x01, VSimSycClkReq1Valid
+	 * 0x02, VSimSycClkReq2Valid
+	 * 0x04, VSimSycClkReq3Valid
+	 * 0x08, VSimSycClkReq4Valid
+	 * 0x10, VSimSycClkReq5Valid
+	 * 0x20, VSimSycClkReq6Valid
+	 * 0x40, VSimSycClkReq7Valid
+	 * 0x80, VSimSycClkReq8Valid
+	 */
+	REG_INIT(AB8540_VSIMSYSCLKCTRL,		0x02, 0x33, 0xff),
+	/*
+	 * 0x03, VarmRequestCtrl
+	 * 0x0c, VapeRequestCtrl
+	 * 0x30, Vsmps1RequestCtrl
+	 * 0xc0, Vsmps2RequestCtrl
+	 */
+	REG_INIT(AB8540_REGUREQUESTCTRL1,	0x03, 0x03, 0xff),
+	/*
+	 * 0x03, Vsmps3RequestCtrl
+	 * 0x0c, VpllRequestCtrl
+	 * 0x30, VanaRequestCtrl
+	 * 0xc0, VextSupply1RequestCtrl
+	 */
+	REG_INIT(AB8540_REGUREQUESTCTRL2,	0x03, 0x04, 0xff),
+	/*
+	 * 0x03, VextSupply2RequestCtrl
+	 * 0x0c, VextSupply3RequestCtrl
+	 * 0x30, Vaux1RequestCtrl
+	 * 0xc0, Vaux2RequestCtrl
+	 */
+	REG_INIT(AB8540_REGUREQUESTCTRL3,	0x03, 0x05, 0xff),
+	/*
+	 * 0x03, Vaux3RequestCtrl
+	 * 0x04, SwHPReq
+	 */
+	REG_INIT(AB8540_REGUREQUESTCTRL4,	0x03, 0x06, 0x07),
+	/*
+	 * 0x01, Vsmps1SysClkReq1HPValid
+	 * 0x02, Vsmps2SysClkReq1HPValid
+	 * 0x04, Vsmps3SysClkReq1HPValid
+	 * 0x08, VanaSysClkReq1HPValid
+	 * 0x10, VpllSysClkReq1HPValid
+	 * 0x20, Vaux1SysClkReq1HPValid
+	 * 0x40, Vaux2SysClkReq1HPValid
+	 * 0x80, Vaux3SysClkReq1HPValid
+	 */
+	REG_INIT(AB8540_REGUSYSCLKREQ1HPVALID1,	0x03, 0x07, 0xff),
 	/*
+	 * 0x01, VapeSysClkReq1HPValid
+	 * 0x02, VarmSysClkReq1HPValid
+	 * 0x04, VbbSysClkReq1HPValid
 	 * 0x10, VextSupply1SysClkReq1HPValid
 	 * 0x20, VextSupply2SysClkReq1HPValid
 	 * 0x40, VextSupply3SysClkReq1HPValid
 	 */
-	REG_INIT(AB8500_REGUSYSCLKREQ1HPVALID2,	0x03, 0x08, 0x70),
+	REG_INIT(AB8540_REGUSYSCLKREQ1HPVALID2,	0x03, 0x08, 0x77),
 	/*
+	 * 0x01, Vsmps1HwHPReq1Valid
+	 * 0x02, Vsmps2HwHPReq1Valid
+	 * 0x04, Vsmps3HwHPReq1Valid
 	 * 0x08, VanaHwHPReq1Valid
+	 * 0x10, VpllHwHPReq1Valid
 	 * 0x20, Vaux1HwHPReq1Valid
 	 * 0x40, Vaux2HwHPReq1Valid
 	 * 0x80, Vaux3HwHPReq1Valid
 	 */
-	REG_INIT(AB8500_REGUHWHPREQ1VALID1,	0x03, 0x09, 0xe8),
+	REG_INIT(AB8540_REGUHWHPREQ1VALID1,	0x03, 0x09, 0xff),
 	/*
 	 * 0x01, VextSupply1HwHPReq1Valid
 	 * 0x02, VextSupply2HwHPReq1Valid
 	 * 0x04, VextSupply3HwHPReq1Valid
 	 */
-	REG_INIT(AB8500_REGUHWHPREQ1VALID2,	0x03, 0x0a, 0x07),
+	REG_INIT(AB8540_REGUHWHPREQ1VALID2,	0x03, 0x0a, 0x07),
 	/*
+	 * 0x01, Vsmps1HwHPReq2Valid
+	 * 0x02, Vsmps2HwHPReq2Valid
+	 * 0x03, Vsmps3HwHPReq2Valid
 	 * 0x08, VanaHwHPReq2Valid
+	 * 0x10, VpllHwHPReq2Valid
 	 * 0x20, Vaux1HwHPReq2Valid
 	 * 0x40, Vaux2HwHPReq2Valid
 	 * 0x80, Vaux3HwHPReq2Valid
 	 */
-	REG_INIT(AB8500_REGUHWHPREQ2VALID1,	0x03, 0x0b, 0xe8),
+	REG_INIT(AB8540_REGUHWHPREQ2VALID1,	0x03, 0x0b, 0xff),
 	/*
 	 * 0x01, VextSupply1HwHPReq2Valid
 	 * 0x02, VextSupply2HwHPReq2Valid
 	 * 0x04, VextSupply3HwHPReq2Valid
 	 */
-	REG_INIT(AB8500_REGUHWHPREQ2VALID2,	0x03, 0x0c, 0x07),
+	REG_INIT(AB8540_REGUHWHPREQ2VALID2,	0x03, 0x0c, 0x07),
 	/*
+	 * 0x01, VapeSwHPReqValid
+	 * 0x02, VarmSwHPReqValid
+	 * 0x04, Vsmps1SwHPReqValid
+	 * 0x08, Vsmps2SwHPReqValid
+	 * 0x10, Vsmps3SwHPReqValid
 	 * 0x20, VanaSwHPReqValid
+	 * 0x40, VpllSwHPReqValid
 	 * 0x80, Vaux1SwHPReqValid
 	 */
-	REG_INIT(AB8500_REGUSWHPREQVALID1,	0x03, 0x0d, 0xa0),
+	REG_INIT(AB8540_REGUSWHPREQVALID1,	0x03, 0x0d, 0xff),
 	/*
 	 * 0x01, Vaux2SwHPReqValid
 	 * 0x02, Vaux3SwHPReqValid
@@ -544,19 +2650,54 @@ static struct ab8500_reg_init ab8500_reg_init[] = {
 	 * 0x08, VextSupply2SwHPReqValid
 	 * 0x10, VextSupply3SwHPReqValid
 	 */
-	REG_INIT(AB8500_REGUSWHPREQVALID2,	0x03, 0x0e, 0x1f),
+	REG_INIT(AB8540_REGUSWHPREQVALID2,	0x03, 0x0e, 0x1f),
 	/*
 	 * 0x02, SysClkReq2Valid1
 	 * ...
 	 * 0x80, SysClkReq8Valid1
 	 */
-	REG_INIT(AB8500_REGUSYSCLKREQVALID1,	0x03, 0x0f, 0xfe),
+	REG_INIT(AB8540_REGUSYSCLKREQVALID1,	0x03, 0x0f, 0xff),
 	/*
 	 * 0x02, SysClkReq2Valid2
 	 * ...
 	 * 0x80, SysClkReq8Valid2
 	 */
-	REG_INIT(AB8500_REGUSYSCLKREQVALID2,	0x03, 0x10, 0xfe),
+	REG_INIT(AB8540_REGUSYSCLKREQVALID2,	0x03, 0x10, 0xff),
+	/*
+	 * 0x01, Vaux4SwHPReqValid
+	 * 0x02, Vaux4HwHPReq2Valid
+	 * 0x04, Vaux4HwHPReq1Valid
+	 * 0x08, Vaux4SysClkReq1HPValid
+	 */
+	REG_INIT(AB8540_REGUVAUX4REQVALID,	0x03, 0x11, 0x0f),
+	/*
+	 * 0x01, Vaux5SwHPReqValid
+	 * 0x02, Vaux5HwHPReq2Valid
+	 * 0x04, Vaux5HwHPReq1Valid
+	 * 0x08, Vaux5SysClkReq1HPValid
+	 */
+	REG_INIT(AB8540_REGUVAUX5REQVALID,	0x03, 0x12, 0x0f),
+	/*
+	 * 0x01, Vaux6SwHPReqValid
+	 * 0x02, Vaux6HwHPReq2Valid
+	 * 0x04, Vaux6HwHPReq1Valid
+	 * 0x08, Vaux6SysClkReq1HPValid
+	 */
+	REG_INIT(AB8540_REGUVAUX6REQVALID,	0x03, 0x13, 0x0f),
+	/*
+	 * 0x01, VclkbSwHPReqValid
+	 * 0x02, VclkbHwHPReq2Valid
+	 * 0x04, VclkbHwHPReq1Valid
+	 * 0x08, VclkbSysClkReq1HPValid
+	 */
+	REG_INIT(AB8540_REGUVCLKBREQVALID,	0x03, 0x14, 0x0f),
+	/*
+	 * 0x01, Vrf1SwHPReqValid
+	 * 0x02, Vrf1HwHPReq2Valid
+	 * 0x04, Vrf1HwHPReq1Valid
+	 * 0x08, Vrf1SysClkReq1HPValid
+	 */
+	REG_INIT(AB8540_REGUVRF1REQVALID,	0x03, 0x15, 0x0f),
 	/*
 	 * 0x02, VTVoutEna
 	 * 0x04, Vintcore12Ena
@@ -564,29 +2705,62 @@ static struct ab8500_reg_init ab8500_reg_init[] = {
 	 * 0x40, Vintcore12LP
 	 * 0x80, VTVoutLP
 	 */
-	REG_INIT(AB8500_REGUMISC1,		0x03, 0x80, 0xfe),
+	REG_INIT(AB8540_REGUMISC1,		0x03, 0x80, 0xfe),
 	/*
 	 * 0x02, VaudioEna
 	 * 0x04, VdmicEna
 	 * 0x08, Vamic1Ena
 	 * 0x10, Vamic2Ena
+	 * 0x20, Vamic12LP
+	 * 0xC0, VdmicSel
 	 */
-	REG_INIT(AB8500_VAUDIOSUPPLY,		0x03, 0x83, 0x1e),
+	REG_INIT(AB8540_VAUDIOSUPPLY,		0x03, 0x83, 0xfe),
 	/*
 	 * 0x01, Vamic1_dzout
 	 * 0x02, Vamic2_dzout
 	 */
-	REG_INIT(AB8500_REGUCTRL1VAMIC,		0x03, 0x84, 0x03),
+	REG_INIT(AB8540_REGUCTRL1VAMIC,		0x03, 0x84, 0x03),
 	/*
-	 * 0x0c, VanaRegu
-	 * 0x03, VpllRegu
+	 * 0x07, VHSICSel
+	 * 0x08, VHSICOffState
+	 * 0x10, VHSIEna
+	 * 0x20, VHSICLP
 	 */
-	REG_INIT(AB8500_VPLLVANAREGU,		0x04, 0x06, 0x0f),
+	REG_INIT(AB8540_VHSIC,			0x03, 0x87, 0x3f),
 	/*
-	 * 0x01, VrefDDREna
-	 * 0x02, VrefDDRSleepMode
+	 * 0x07, VSDIOSel
+	 * 0x08, VSDIOOffState
+	 * 0x10, VSDIOEna
+	 * 0x20, VSDIOLP
 	 */
-	REG_INIT(AB8500_VREFDDR,		0x04, 0x07, 0x03),
+	REG_INIT(AB8540_VSDIO,			0x03, 0x88, 0x3f),
+	/*
+	 * 0x03, Vsmps1Regu
+	 * 0x0c, Vsmps1SelCtrl
+	 * 0x10, Vsmps1AutoMode
+	 * 0x20, Vsmps1PWMMode
+	 */
+	REG_INIT(AB8540_VSMPS1REGU,		0x04, 0x03, 0x3f),
+	/*
+	 * 0x03, Vsmps2Regu
+	 * 0x0c, Vsmps2SelCtrl
+	 * 0x10, Vsmps2AutoMode
+	 * 0x20, Vsmps2PWMMode
+	 */
+	REG_INIT(AB8540_VSMPS2REGU,		0x04, 0x04, 0x3f),
+	/*
+	 * 0x03, Vsmps3Regu
+	 * 0x0c, Vsmps3SelCtrl
+	 * 0x10, Vsmps3AutoMode
+	 * 0x20, Vsmps3PWMMode
+	 * NOTE! PRCMU register
+	 */
+	REG_INIT(AB8540_VSMPS3REGU,		0x04, 0x05, 0x0f),
+	/*
+	 * 0x03, VpllRegu
+	 * 0x0c, VanaRegu
+	 */
+	REG_INIT(AB8540_VPLLVANAREGU,		0x04, 0x06, 0x0f),
 	/*
 	 * 0x03, VextSupply1Regu
 	 * 0x0c, VextSupply2Regu
@@ -594,37 +2768,128 @@ static struct ab8500_reg_init ab8500_reg_init[] = {
 	 * 0x40, ExtSupply2Bypass
 	 * 0x80, ExtSupply3Bypass
 	 */
-	REG_INIT(AB8500_EXTSUPPLYREGU,		0x04, 0x08, 0xff),
+	REG_INIT(AB8540_EXTSUPPLYREGU,		0x04, 0x08, 0xff),
 	/*
 	 * 0x03, Vaux1Regu
 	 * 0x0c, Vaux2Regu
 	 */
-	REG_INIT(AB8500_VAUX12REGU,		0x04, 0x09, 0x0f),
+	REG_INIT(AB8540_VAUX12REGU,		0x04, 0x09, 0x0f),
 	/*
+	 * 0x0c, VRF1Regu
 	 * 0x03, Vaux3Regu
 	 */
-	REG_INIT(AB8500_VRF1VAUX3REGU,		0x04, 0x0a, 0x03),
+	REG_INIT(AB8540_VRF1VAUX3REGU,		0x04, 0x0a, 0x0f),
 	/*
 	 * 0x3f, Vsmps1Sel1
 	 */
-	REG_INIT(AB8500_VSMPS1SEL1,		0x04, 0x13, 0x3f),
+	REG_INIT(AB8540_VSMPS1SEL1,		0x04, 0x13, 0x3f),
+	/*
+	 * 0x3f, Vsmps1Sel2
+	 */
+	REG_INIT(AB8540_VSMPS1SEL2,		0x04, 0x14, 0x3f),
+	/*
+	 * 0x3f, Vsmps1Sel3
+	 */
+	REG_INIT(AB8540_VSMPS1SEL3,		0x04, 0x15, 0x3f),
+	/*
+	 * 0x3f, Vsmps2Sel1
+	 */
+	REG_INIT(AB8540_VSMPS2SEL1,		0x04, 0x17, 0x3f),
+	/*
+	 * 0x3f, Vsmps2Sel2
+	 */
+	REG_INIT(AB8540_VSMPS2SEL2,		0x04, 0x18, 0x3f),
+	/*
+	 * 0x3f, Vsmps2Sel3
+	 */
+	REG_INIT(AB8540_VSMPS2SEL3,		0x04, 0x19, 0x3f),
+	/*
+	 * 0x7f, Vsmps3Sel1
+	 * NOTE! PRCMU register
+	 */
+	REG_INIT(AB8540_VSMPS3SEL1,             0x04, 0x1b, 0x7f),
+	/*
+	 * 0x7f, Vsmps3Sel2
+	 * NOTE! PRCMU register
+	 */
+	REG_INIT(AB8540_VSMPS3SEL2,             0x04, 0x1c, 0x7f),
 	/*
 	 * 0x0f, Vaux1Sel
 	 */
-	REG_INIT(AB8500_VAUX1SEL,		0x04, 0x1f, 0x0f),
+	REG_INIT(AB8540_VAUX1SEL,		0x04, 0x1f, 0x0f),
 	/*
 	 * 0x0f, Vaux2Sel
 	 */
-	REG_INIT(AB8500_VAUX2SEL,		0x04, 0x20, 0x0f),
+	REG_INIT(AB8540_VAUX2SEL,		0x04, 0x20, 0x0f),
 	/*
 	 * 0x07, Vaux3Sel
+	 * 0x70, Vrf1Sel
 	 */
-	REG_INIT(AB8500_VRF1VAUX3SEL,		0x04, 0x21, 0x07),
+	REG_INIT(AB8540_VRF1VAUX3SEL,		0x04, 0x21, 0x77),
 	/*
 	 * 0x01, VextSupply12LP
 	 */
-	REG_INIT(AB8500_REGUCTRL2SPARE,		0x04, 0x22, 0x01),
+	REG_INIT(AB8540_REGUCTRL2SPARE,		0x04, 0x22, 0x01),
+	/*
+	 * 0x07, Vanasel
+	 * 0x30, Vpllsel
+	 */
+	REG_INIT(AB8540_VANAVPLLSEL,		0x04, 0x29, 0x37),
+	/*
+	 * 0x03, Vaux4RequestCtrl
+	 */
+	REG_INIT(AB8540_VAUX4REQCTRL,		0x04, 0x2d, 0x03),
+	/*
+	 * 0x03, Vaux4Regu
+	 */
+	REG_INIT(AB8540_VAUX4REGU,		0x04, 0x2e, 0x03),
+	/*
+	 * 0x0f, Vaux4Sel
+	 */
+	REG_INIT(AB8540_VAUX4SEL,		0x04, 0x2f, 0x0f),
+	/*
+	 * 0x03, Vaux5RequestCtrl
+	 */
+	REG_INIT(AB8540_VAUX5REQCTRL,		0x04, 0x31, 0x03),
+	/*
+	 * 0x03, Vaux5Regu
+	 */
+	REG_INIT(AB8540_VAUX5REGU,		0x04, 0x32, 0x03),
+	/*
+	 * 0x3f, Vaux5Sel
+	 */
+	REG_INIT(AB8540_VAUX5SEL,		0x04, 0x33, 0x3f),
+	/*
+	 * 0x03, Vaux6RequestCtrl
+	 */
+	REG_INIT(AB8540_VAUX6REQCTRL,		0x04, 0x34, 0x03),
+	/*
+	 * 0x03, Vaux6Regu
+	 */
+	REG_INIT(AB8540_VAUX6REGU,		0x04, 0x35, 0x03),
+	/*
+	 * 0x3f, Vaux6Sel
+	 */
+	REG_INIT(AB8540_VAUX6SEL,		0x04, 0x36, 0x3f),
+	/*
+	 * 0x03, VCLKBRequestCtrl
+	 */
+	REG_INIT(AB8540_VCLKBREQCTRL,		0x04, 0x37, 0x03),
+	/*
+	 * 0x03, VCLKBRegu
+	 */
+	REG_INIT(AB8540_VCLKBREGU,		0x04, 0x38, 0x03),
+	/*
+	 * 0x07, VCLKBSel
+	 */
+	REG_INIT(AB8540_VCLKBSEL,		0x04, 0x39, 0x07),
+	/*
+	 * 0x03, Vrf1RequestCtrl
+	 */
+	REG_INIT(AB8540_VRF1REQCTRL,		0x04, 0x3a, 0x03),
 	/*
+	 * 0x01, VpllDisch
+	 * 0x02, Vrf1Disch
 	 * 0x04, Vaux1Disch
 	 * 0x08, Vaux2Disch
 	 * 0x10, Vaux3Disch
@@ -632,61 +2897,170 @@ static struct ab8500_reg_init ab8500_reg_init[] = {
 	 * 0x40, VTVoutDisch
 	 * 0x80, VaudioDisch
 	 */
-	REG_INIT(AB8500_REGUCTRLDISCH,		0x04, 0x43, 0xfc),
+	REG_INIT(AB8540_REGUCTRLDISCH,		0x04, 0x43, 0xff),
 	/*
 	 * 0x02, VanaDisch
 	 * 0x04, VdmicPullDownEna
+	 * 0x08, VpllPullDownEna
 	 * 0x10, VdmicDisch
 	 */
-	REG_INIT(AB8500_REGUCTRLDISCH2,		0x04, 0x44, 0x16),
+	REG_INIT(AB8540_REGUCTRLDISCH2,		0x04, 0x44, 0x1e),
+	/*
+	 * 0x01, Vaux4Disch
+	 */
+	REG_INIT(AB8540_REGUCTRLDISCH3,		0x04, 0x48, 0x01),
+	/*
+	 * 0x01, Vaux5Disch
+	 * 0x02, Vaux6Disch
+	 * 0x04, VCLKBDisch
+	 */
+	REG_INIT(AB8540_REGUCTRLDISCH4,		0x04, 0x49, 0x07),
 };
 
-static int
-ab8500_regulator_init_registers(struct platform_device *pdev, int id, int value)
+static struct of_regulator_match ab8500_regulator_match[] = {
+	{ .name	= "ab8500_ldo_aux1",    .driver_data = (void *) AB8500_LDO_AUX1, },
+	{ .name	= "ab8500_ldo_aux2",    .driver_data = (void *) AB8500_LDO_AUX2, },
+	{ .name	= "ab8500_ldo_aux3",    .driver_data = (void *) AB8500_LDO_AUX3, },
+	{ .name	= "ab8500_ldo_intcore", .driver_data = (void *) AB8500_LDO_INTCORE, },
+	{ .name	= "ab8500_ldo_tvout",   .driver_data = (void *) AB8500_LDO_TVOUT, },
+	{ .name = "ab8500_ldo_audio",   .driver_data = (void *) AB8500_LDO_AUDIO, },
+	{ .name	= "ab8500_ldo_anamic1", .driver_data = (void *) AB8500_LDO_ANAMIC1, },
+	{ .name	= "ab8500_ldo_amamic2", .driver_data = (void *) AB8500_LDO_ANAMIC2, },
+	{ .name	= "ab8500_ldo_dmic",    .driver_data = (void *) AB8500_LDO_DMIC, },
+	{ .name	= "ab8500_ldo_ana",     .driver_data = (void *) AB8500_LDO_ANA, },
+};
+
+static struct of_regulator_match ab8505_regulator_match[] = {
+	{ .name	= "ab8500_ldo_aux1",    .driver_data = (void *) AB8505_LDO_AUX1, },
+	{ .name	= "ab8500_ldo_aux2",    .driver_data = (void *) AB8505_LDO_AUX2, },
+	{ .name	= "ab8500_ldo_aux3",    .driver_data = (void *) AB8505_LDO_AUX3, },
+	{ .name	= "ab8500_ldo_aux4",    .driver_data = (void *) AB8505_LDO_AUX4, },
+	{ .name	= "ab8500_ldo_aux5",    .driver_data = (void *) AB8505_LDO_AUX5, },
+	{ .name	= "ab8500_ldo_aux6",    .driver_data = (void *) AB8505_LDO_AUX6, },
+	{ .name	= "ab8500_ldo_intcore", .driver_data = (void *) AB8505_LDO_INTCORE, },
+	{ .name	= "ab8500_ldo_adc",	.driver_data = (void *) AB8505_LDO_ADC, },
+	{ .name = "ab8500_ldo_audio",   .driver_data = (void *) AB8505_LDO_AUDIO, },
+	{ .name	= "ab8500_ldo_anamic1", .driver_data = (void *) AB8505_LDO_ANAMIC1, },
+	{ .name	= "ab8500_ldo_amamic2", .driver_data = (void *) AB8505_LDO_ANAMIC2, },
+	{ .name	= "ab8500_ldo_aux8",    .driver_data = (void *) AB8505_LDO_AUX8, },
+	{ .name	= "ab8500_ldo_ana",     .driver_data = (void *) AB8505_LDO_ANA, },
+};
+
+static struct of_regulator_match ab8540_regulator_match[] = {
+	{ .name	= "ab8500_ldo_aux1",    .driver_data = (void *) AB8540_LDO_AUX1, },
+	{ .name	= "ab8500_ldo_aux2",    .driver_data = (void *) AB8540_LDO_AUX2, },
+	{ .name	= "ab8500_ldo_aux3",    .driver_data = (void *) AB8540_LDO_AUX3, },
+	{ .name	= "ab8500_ldo_aux4",    .driver_data = (void *) AB8540_LDO_AUX4, },
+	{ .name	= "ab8500_ldo_aux5",    .driver_data = (void *) AB8540_LDO_AUX5, },
+	{ .name	= "ab8500_ldo_aux6",    .driver_data = (void *) AB8540_LDO_AUX6, },
+	{ .name	= "ab8500_ldo_intcore", .driver_data = (void *) AB8540_LDO_INTCORE, },
+	{ .name	= "ab8500_ldo_tvout",   .driver_data = (void *) AB8540_LDO_TVOUT, },
+	{ .name = "ab8500_ldo_audio",   .driver_data = (void *) AB8540_LDO_AUDIO, },
+	{ .name	= "ab8500_ldo_anamic1", .driver_data = (void *) AB8540_LDO_ANAMIC1, },
+	{ .name	= "ab8500_ldo_amamic2", .driver_data = (void *) AB8540_LDO_ANAMIC2, },
+	{ .name	= "ab8500_ldo_dmic",    .driver_data = (void *) AB8540_LDO_DMIC, },
+	{ .name	= "ab8500_ldo_ana",     .driver_data = (void *) AB8540_LDO_ANA, },
+	{ .name = "ab8500_ldo_sdio",    .driver_data = (void *) AB8540_LDO_SDIO, },
+};
+
+static struct of_regulator_match ab9540_regulator_match[] = {
+	{ .name	= "ab8500_ldo_aux1",    .driver_data = (void *) AB9540_LDO_AUX1, },
+	{ .name	= "ab8500_ldo_aux2",    .driver_data = (void *) AB9540_LDO_AUX2, },
+	{ .name	= "ab8500_ldo_aux3",    .driver_data = (void *) AB9540_LDO_AUX3, },
+	{ .name	= "ab8500_ldo_aux4",    .driver_data = (void *) AB9540_LDO_AUX4, },
+	{ .name	= "ab8500_ldo_intcore", .driver_data = (void *) AB9540_LDO_INTCORE, },
+	{ .name	= "ab8500_ldo_tvout",   .driver_data = (void *) AB9540_LDO_TVOUT, },
+	{ .name = "ab8500_ldo_audio",   .driver_data = (void *) AB9540_LDO_AUDIO, },
+	{ .name	= "ab8500_ldo_anamic1", .driver_data = (void *) AB9540_LDO_ANAMIC1, },
+	{ .name	= "ab8500_ldo_amamic2", .driver_data = (void *) AB9540_LDO_ANAMIC2, },
+	{ .name	= "ab8500_ldo_dmic",    .driver_data = (void *) AB9540_LDO_DMIC, },
+	{ .name	= "ab8500_ldo_ana",     .driver_data = (void *) AB9540_LDO_ANA, },
+};
+
+static struct {
+	struct ab8500_regulator_info *info;
+	int info_size;
+	struct ab8500_reg_init *init;
+	int init_size;
+	struct of_regulator_match *match;
+	int match_size;
+} abx500_regulator;
+
+static void abx500_get_regulator_info(struct ab8500 *ab8500)
+{
+	if (is_ab9540(ab8500)) {
+		abx500_regulator.info = ab9540_regulator_info;
+		abx500_regulator.info_size = ARRAY_SIZE(ab9540_regulator_info);
+		abx500_regulator.init = ab9540_reg_init;
+		abx500_regulator.init_size = AB9540_NUM_REGULATOR_REGISTERS;
+		abx500_regulator.match = ab9540_regulator_match;
+		abx500_regulator.match_size = ARRAY_SIZE(ab9540_regulator_match);
+	} else if (is_ab8505(ab8500)) {
+		abx500_regulator.info = ab8505_regulator_info;
+		abx500_regulator.info_size = ARRAY_SIZE(ab8505_regulator_info);
+		abx500_regulator.init = ab8505_reg_init;
+		abx500_regulator.init_size = AB8505_NUM_REGULATOR_REGISTERS;
+		abx500_regulator.match = ab8505_regulator_match;
+		abx500_regulator.match_size = ARRAY_SIZE(ab8505_regulator_match);
+	} else if (is_ab8540(ab8500)) {
+		abx500_regulator.info = ab8540_regulator_info;
+		abx500_regulator.info_size = ARRAY_SIZE(ab8540_regulator_info);
+		abx500_regulator.init = ab8540_reg_init;
+		abx500_regulator.init_size = AB8540_NUM_REGULATOR_REGISTERS;
+		abx500_regulator.match = ab8540_regulator_match;
+		abx500_regulator.match_size = ARRAY_SIZE(ab8540_regulator_match);
+	} else {
+		abx500_regulator.info = ab8500_regulator_info;
+		abx500_regulator.info_size = ARRAY_SIZE(ab8500_regulator_info);
+		abx500_regulator.init = ab8500_reg_init;
+		abx500_regulator.init_size = AB8500_NUM_REGULATOR_REGISTERS;
+		abx500_regulator.match = ab8500_regulator_match;
+		abx500_regulator.match_size = ARRAY_SIZE(ab8500_regulator_match);
+	}
+}
+
+static int ab8500_regulator_init_registers(struct platform_device *pdev,
+					   int id, int mask, int value)
 {
+	struct ab8500_reg_init *reg_init = abx500_regulator.init;
 	int err;
 
-	if (value & ~ab8500_reg_init[id].mask) {
-		dev_err(&pdev->dev,
-			"Configuration error: value outside mask.\n");
-		return -EINVAL;
-	}
+	BUG_ON(value & ~mask);
+	BUG_ON(mask & ~reg_init[id].mask);
 
+	/* initialize register */
 	err = abx500_mask_and_set_register_interruptible(
 		&pdev->dev,
-		ab8500_reg_init[id].bank,
-		ab8500_reg_init[id].addr,
-		ab8500_reg_init[id].mask,
-		value);
+		reg_init[id].bank,
+		reg_init[id].addr,
+		mask, value);
 	if (err < 0) {
 		dev_err(&pdev->dev,
 			"Failed to initialize 0x%02x, 0x%02x.\n",
-			ab8500_reg_init[id].bank,
-			ab8500_reg_init[id].addr);
+			reg_init[id].bank,
+			reg_init[id].addr);
 		return err;
 	}
-
 	dev_vdbg(&pdev->dev,
-		"init: 0x%02x, 0x%02x, 0x%02x, 0x%02x\n",
-		ab8500_reg_init[id].bank,
-		ab8500_reg_init[id].addr,
-		ab8500_reg_init[id].mask,
-		value);
+		 "  init: 0x%02x, 0x%02x, 0x%02x, 0x%02x\n",
+		 reg_init[id].bank,
+		 reg_init[id].addr,
+		 mask, value);
 
 	return 0;
 }
 
 static int ab8500_regulator_register(struct platform_device *pdev,
-					struct regulator_init_data *init_data,
-					int id,
-					struct device_node *np)
+				     struct regulator_init_data *init_data,
+				     int id, struct device_node *np)
 {
+	struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent);
 	struct ab8500_regulator_info *info = NULL;
 	struct regulator_config config = { };
 	int err;
 
 	/* assign per-regulator data */
-	info = &ab8500_regulator_info[id];
+	info = &abx500_regulator.info[id];
 	info->dev = &pdev->dev;
 
 	config.dev = &pdev->dev;
@@ -695,7 +3069,7 @@ static int ab8500_regulator_register(struct platform_device *pdev,
 	config.of_node = np;
 
 	/* fix for hardware before ab8500v2.0 */
-	if (abx500_get_chip_id(info->dev) < 0x20) {
+	if (is_ab8500_1p1_or_earlier(ab8500)) {
 		if (info->desc.id == AB8500_LDO_AUX3) {
 			info->desc.n_voltages =
 				ARRAY_SIZE(ldo_vauxn_voltages);
@@ -712,7 +3086,7 @@ static int ab8500_regulator_register(struct platform_device *pdev,
 			info->desc.name);
 		/* when we fail, un-register all earlier regulators */
 		while (--id >= 0) {
-			info = &ab8500_regulator_info[id];
+			info = &abx500_regulator.info[id];
 			regulator_unregister(info->regulator);
 		}
 		return err;
@@ -721,29 +3095,16 @@ static int ab8500_regulator_register(struct platform_device *pdev,
 	return 0;
 }
 
-static struct of_regulator_match ab8500_regulator_matches[] = {
-	{ .name	= "ab8500_ldo_aux1",    .driver_data = (void *) AB8500_LDO_AUX1, },
-	{ .name	= "ab8500_ldo_aux2",    .driver_data = (void *) AB8500_LDO_AUX2, },
-	{ .name	= "ab8500_ldo_aux3",    .driver_data = (void *) AB8500_LDO_AUX3, },
-	{ .name	= "ab8500_ldo_intcore", .driver_data = (void *) AB8500_LDO_INTCORE, },
-	{ .name	= "ab8500_ldo_tvout",   .driver_data = (void *) AB8500_LDO_TVOUT, },
-	{ .name = "ab8500_ldo_usb",     .driver_data = (void *) AB8500_LDO_USB, },
-	{ .name = "ab8500_ldo_audio",   .driver_data = (void *) AB8500_LDO_AUDIO, },
-	{ .name	= "ab8500_ldo_anamic1", .driver_data = (void *) AB8500_LDO_ANAMIC1, },
-	{ .name	= "ab8500_ldo_amamic2", .driver_data = (void *) AB8500_LDO_ANAMIC2, },
-	{ .name	= "ab8500_ldo_dmic",    .driver_data = (void *) AB8500_LDO_DMIC, },
-	{ .name	= "ab8500_ldo_ana",     .driver_data = (void *) AB8500_LDO_ANA, },
-};
-
 static int
-ab8500_regulator_of_probe(struct platform_device *pdev, struct device_node *np)
+ab8500_regulator_of_probe(struct platform_device *pdev,
+			  struct device_node *np)
 {
+	struct of_regulator_match *match = abx500_regulator.match;
 	int err, i;
 
-	for (i = 0; i < ARRAY_SIZE(ab8500_regulator_info); i++) {
+	for (i = 0; i < abx500_regulator.info_size; i++) {
 		err = ab8500_regulator_register(
-			pdev, ab8500_regulator_matches[i].init_data,
-			i, ab8500_regulator_matches[i].of_node);
+			pdev, match[i].init_data, i, match[i].of_node);
 		if (err)
 			return err;
 	}
@@ -754,14 +3115,22 @@ ab8500_regulator_of_probe(struct platform_device *pdev, struct device_node *np)
 static int ab8500_regulator_probe(struct platform_device *pdev)
 {
 	struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent);
-	struct ab8500_platform_data *pdata;
 	struct device_node *np = pdev->dev.of_node;
+	struct ab8500_platform_data *ppdata;
+	struct ab8500_regulator_platform_data *pdata;
 	int i, err;
 
+	if (!ab8500) {
+		dev_err(&pdev->dev, "null mfd parent\n");
+		return -EINVAL;
+	}
+
+	abx500_get_regulator_info(ab8500);
+
 	if (np) {
 		err = of_regulator_match(&pdev->dev, np,
-					ab8500_regulator_matches,
-					ARRAY_SIZE(ab8500_regulator_matches));
+					 abx500_regulator.match,
+					 abx500_regulator.match_size);
 		if (err < 0) {
 			dev_err(&pdev->dev,
 				"Error parsing regulator init data: %d\n", err);
@@ -772,44 +3141,56 @@ static int ab8500_regulator_probe(struct platform_device *pdev)
 		return err;
 	}
 
-	if (!ab8500) {
-		dev_err(&pdev->dev, "null mfd parent\n");
+	ppdata = dev_get_platdata(ab8500->dev);
+	if (!ppdata) {
+		dev_err(&pdev->dev, "null parent pdata\n");
 		return -EINVAL;
 	}
-	pdata = dev_get_platdata(ab8500->dev);
+
+	pdata = ppdata->regulator;
 	if (!pdata) {
 		dev_err(&pdev->dev, "null pdata\n");
 		return -EINVAL;
 	}
 
 	/* make sure the platform data has the correct size */
-	if (pdata->num_regulator != ARRAY_SIZE(ab8500_regulator_info)) {
+	if (pdata->num_regulator != abx500_regulator.info_size) {
 		dev_err(&pdev->dev, "Configuration error: size mismatch.\n");
 		return -EINVAL;
 	}
 
+	/* initialize debug (initial state is recorded with this call) */
+	err = ab8500_regulator_debug_init(pdev);
+	if (err)
+		return err;
+
 	/* initialize registers */
-	for (i = 0; i < pdata->num_regulator_reg_init; i++) {
-		int id, value;
+	for (i = 0; i < pdata->num_reg_init; i++) {
+		int id, mask, value;
 
-		id = pdata->regulator_reg_init[i].id;
-		value = pdata->regulator_reg_init[i].value;
+		id = pdata->reg_init[i].id;
+		mask = pdata->reg_init[i].mask;
+		value = pdata->reg_init[i].value;
 
 		/* check for configuration errors */
-		if (id >= AB8500_NUM_REGULATOR_REGISTERS) {
-			dev_err(&pdev->dev,
-				"Configuration error: id outside range.\n");
-			return -EINVAL;
-		}
+		BUG_ON(id >= abx500_regulator.init_size);
 
-		err = ab8500_regulator_init_registers(pdev, id, value);
+		err = ab8500_regulator_init_registers(pdev, id, mask, value);
 		if (err < 0)
 			return err;
 	}
 
+	if (!is_ab8505(ab8500)) {
+		/* register external regulators (before Vaux1, 2 and 3) */
+		err = ab8500_ext_regulator_init(pdev);
+		if (err)
+			return err;
+	}
+
 	/* register all regulators */
-	for (i = 0; i < ARRAY_SIZE(ab8500_regulator_info); i++) {
-		err = ab8500_regulator_register(pdev, &pdata->regulator[i], i, NULL);
+	for (i = 0; i < abx500_regulator.info_size; i++) {
+		err = ab8500_regulator_register(pdev, &pdata->regulator[i],
+						i, NULL);
 		if (err < 0)
 			return err;
 	}
@@ -819,11 +3200,12 @@ static int ab8500_regulator_probe(struct platform_device *pdev)
 
 static int ab8500_regulator_remove(struct platform_device *pdev)
 {
-	int i;
+	int i, err;
+	struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent);
 
-	for (i = 0; i < ARRAY_SIZE(ab8500_regulator_info); i++) {
+	for (i = 0; i < abx500_regulator.info_size; i++) {
 		struct ab8500_regulator_info *info = NULL;
-		info = &ab8500_regulator_info[i];
+		info = &abx500_regulator.info[i];
 
 		dev_vdbg(rdev_get_dev(info->regulator),
 			"%s-remove\n", info->desc.name);
@@ -831,6 +3213,18 @@ static int ab8500_regulator_remove(struct platform_device *pdev)
 		regulator_unregister(info->regulator);
 	}
 
+	if (!is_ab8505(ab8500)) {
+		/* remove external regulators (after Vaux1, 2 and 3) */
+		err = ab8500_ext_regulator_exit(pdev);
+		if (err)
+			return err;
+	}
+
+	/* remove regulator debug */
+	err = ab8500_regulator_debug_exit(pdev);
+	if (err)
+		return err;
+
 	return 0;
 }
 
@@ -863,5 +3257,7 @@ module_exit(ab8500_regulator_exit);
 
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Sundar Iyer <sundar.iyer@stericsson.com>");
+MODULE_AUTHOR("Bengt Jonsson <bengt.g.jonsson@stericsson.com>");
+MODULE_AUTHOR("Daniel Willerud <daniel.willerud@stericsson.com>");
 MODULE_DESCRIPTION("Regulator Driver for ST-Ericsson AB8500 Mixed-Sig PMIC");
 MODULE_ALIAS("platform:ab8500-regulator");
diff --git a/drivers/regulator/arizona-ldo1.c b/drivers/regulator/arizona-ldo1.c
index ed7beec..81d8681 100644
--- a/drivers/regulator/arizona-ldo1.c
+++ b/drivers/regulator/arizona-ldo1.c
@@ -131,7 +131,7 @@ static const struct regulator_desc arizona_ldo1_hc = {
 	.min_uV = 900000,
 	.uV_step = 50000,
 	.n_voltages = 8,
-	.enable_time = 500,
+	.enable_time = 1500,
 
 	.owner = THIS_MODULE,
 };
diff --git a/drivers/regulator/as3711-regulator.c b/drivers/regulator/as3711-regulator.c
index f0ba8c4..0539b3e 100644
--- a/drivers/regulator/as3711-regulator.c
+++ b/drivers/regulator/as3711-regulator.c
@@ -13,9 +13,11 @@
 #include <linux/init.h>
 #include <linux/mfd/as3711.h>
 #include <linux/module.h>
+#include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/regmap.h>
 #include <linux/regulator/driver.h>
+#include <linux/regulator/of_regulator.h>
 #include <linux/slab.h>
 
 struct as3711_regulator_info {
@@ -276,6 +278,60 @@ static struct as3711_regulator_info as3711_reg_info[] = {
 
 #define AS3711_REGULATOR_NUM ARRAY_SIZE(as3711_reg_info)
 
+static const char *as3711_regulator_of_names[AS3711_REGULATOR_NUM] = {
+	[AS3711_REGULATOR_SD_1] = "sd1",
+	[AS3711_REGULATOR_SD_2] = "sd2",
+	[AS3711_REGULATOR_SD_3] = "sd3",
+	[AS3711_REGULATOR_SD_4] = "sd4",
+	[AS3711_REGULATOR_LDO_1] = "ldo1",
+	[AS3711_REGULATOR_LDO_2] = "ldo2",
+	[AS3711_REGULATOR_LDO_3] = "ldo3",
+	[AS3711_REGULATOR_LDO_4] = "ldo4",
+	[AS3711_REGULATOR_LDO_5] = "ldo5",
+	[AS3711_REGULATOR_LDO_6] = "ldo6",
+	[AS3711_REGULATOR_LDO_7] = "ldo7",
+	[AS3711_REGULATOR_LDO_8] = "ldo8",
+};
+
+static int as3711_regulator_parse_dt(struct device *dev,
+				struct device_node **of_node, const int count)
+{
+	struct as3711_regulator_pdata *pdata = dev_get_platdata(dev);
+	struct device_node *regulators =
+		of_find_node_by_name(dev->parent->of_node, "regulators");
+	struct of_regulator_match *matches, *match;
+	int ret, i;
+
+	if (!regulators) {
+		dev_err(dev, "regulator node not found\n");
+		return -ENODEV;
+	}
+
+	matches = devm_kzalloc(dev, sizeof(*matches) * count, GFP_KERNEL);
+	if (!matches)
+		return -ENOMEM;
+
+	for (i = 0, match = matches; i < count; i++, match++) {
+		match->name = as3711_regulator_of_names[i];
+		match->driver_data = as3711_reg_info + i;
+	}
+
+	ret = of_regulator_match(dev->parent, regulators, matches, count);
+	of_node_put(regulators);
+	if (ret < 0) {
+		dev_err(dev, "Error parsing regulator init data: %d\n", ret);
+		return ret;
+	}
+
+	for (i = 0, match = matches; i < count; i++, match++)
+		if (match->of_node) {
+			pdata->init_data[i] = match->init_data;
+			of_node[i] = match->of_node;
+		}
+
+	return 0;
+}
+
 static int as3711_regulator_probe(struct platform_device *pdev)
 {
 	struct as3711_regulator_pdata *pdata = dev_get_platdata(&pdev->dev);
@@ -284,13 +340,24 @@ static int as3711_regulator_probe(struct platform_device *pdev)
 	struct regulator_config config = {.dev = &pdev->dev,};
 	struct as3711_regulator *reg = NULL;
 	struct as3711_regulator *regs;
+	struct device_node *of_node[AS3711_REGULATOR_NUM] = {};
 	struct regulator_dev *rdev;
 	struct as3711_regulator_info *ri;
 	int ret;
 	int id;
 
-	if (!pdata)
-		dev_dbg(&pdev->dev, "No platform data...\n");
+	if (!pdata) {
+		dev_err(&pdev->dev, "No platform data...\n");
+		return -ENODEV;
+	}
+
+	if (pdev->dev.parent->of_node) {
+		ret = as3711_regulator_parse_dt(&pdev->dev, of_node, AS3711_REGULATOR_NUM);
+		if (ret < 0) {
+			dev_err(&pdev->dev, "DT parsing failed: %d\n", ret);
+			return ret;
+		}
+	}
 
 	regs = devm_kzalloc(&pdev->dev, AS3711_REGULATOR_NUM *
 			sizeof(struct as3711_regulator), GFP_KERNEL);
@@ -300,7 +367,7 @@ static int as3711_regulator_probe(struct platform_device *pdev)
 	}
 
 	for (id = 0, ri = as3711_reg_info; id < AS3711_REGULATOR_NUM; ++id, ri++) {
-		reg_data = pdata ? pdata->init_data[id] : NULL;
+		reg_data = pdata->init_data[id];
 
 		/* No need to register if there is no regulator data */
 		if (!reg_data)
@@ -312,6 +379,7 @@ static int as3711_regulator_probe(struct platform_device *pdev)
 		config.init_data = reg_data;
 		config.driver_data = reg;
 		config.regmap = as3711->regmap;
+		config.of_node = of_node[id];
 
 		rdev = regulator_register(&ri->desc, &config);
 		if (IS_ERR(rdev)) {
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index e3661c2..be89ced 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -51,6 +51,7 @@
 static DEFINE_MUTEX(regulator_list_mutex);
 static LIST_HEAD(regulator_list);
 static LIST_HEAD(regulator_map_list);
+static LIST_HEAD(regulator_ena_gpio_list);
 static bool has_full_constraints;
 static bool board_wants_dummy_regulator;
 
@@ -69,6 +70,19 @@ struct regulator_map {
 };
 
 /*
+ * struct regulator_enable_gpio
+ *
+ * Management for shared enable GPIO pin
+ */
+struct regulator_enable_gpio {
+	struct list_head list;
+	int gpio;
+	u32 enable_count;	/* a number of enabled shared GPIO */
+	u32 request_count;	/* a number of requested shared GPIO */
+	unsigned int ena_gpio_invert:1;
+};
+
+/*
  * struct regulator
  *
  * One for each consumer device.
@@ -116,7 +130,7 @@ static const char *rdev_get_name(struct regulator_dev *rdev)
  * @supply: regulator supply name
  *
  * Extract the regulator device node corresponding to the supply name.
- * retruns the device node corresponding to the regulator if found, else
+ * returns the device node corresponding to the regulator if found, else
  * returns NULL.
  */
 static struct device_node *of_get_regulator(struct device *dev, const char *supply)
@@ -1456,6 +1470,101 @@ void devm_regulator_put(struct regulator *regulator)
 }
 EXPORT_SYMBOL_GPL(devm_regulator_put);
 
+/* Manage enable GPIO list. Same GPIO pin can be shared among regulators */
+static int regulator_ena_gpio_request(struct regulator_dev *rdev,
+				const struct regulator_config *config)
+{
+	struct regulator_enable_gpio *pin;
+	int ret;
+
+	list_for_each_entry(pin, &regulator_ena_gpio_list, list) {
+		if (pin->gpio == config->ena_gpio) {
+			rdev_dbg(rdev, "GPIO %d is already used\n",
+				config->ena_gpio);
+			goto update_ena_gpio_to_rdev;
+		}
+	}
+
+	ret = gpio_request_one(config->ena_gpio,
+				GPIOF_DIR_OUT | config->ena_gpio_flags,
+				rdev_get_name(rdev));
+	if (ret)
+		return ret;
+
+	pin = kzalloc(sizeof(struct regulator_enable_gpio), GFP_KERNEL);
+	if (pin == NULL) {
+		gpio_free(config->ena_gpio);
+		return -ENOMEM;
+	}
+
+	pin->gpio = config->ena_gpio;
+	pin->ena_gpio_invert = config->ena_gpio_invert;
+	list_add(&pin->list, &regulator_ena_gpio_list);
+
+update_ena_gpio_to_rdev:
+	pin->request_count++;
+	rdev->ena_pin = pin;
+	return 0;
+}
+
+static void regulator_ena_gpio_free(struct regulator_dev *rdev)
+{
+	struct regulator_enable_gpio *pin, *n;
+
+	if (!rdev->ena_pin)
+		return;
+
+	/* Free the GPIO only in case of no use */
+	list_for_each_entry_safe(pin, n, &regulator_ena_gpio_list, list) {
+		if (pin->gpio == rdev->ena_pin->gpio) {
+			if (pin->request_count <= 1) {
+				pin->request_count = 0;
+				gpio_free(pin->gpio);
+				list_del(&pin->list);
+				kfree(pin);
+			} else {
+				pin->request_count--;
+			}
+		}
+	}
+}
+
+/**
+ * Balance enable_count of each GPIO and actual GPIO pin control.
+ * GPIO is enabled in case of initial use. (enable_count is 0)
+ * GPIO is disabled when it is not shared any more. (enable_count <= 1)
+ */
+static int regulator_ena_gpio_ctrl(struct regulator_dev *rdev, bool enable)
+{
+	struct regulator_enable_gpio *pin = rdev->ena_pin;
+
+	if (!pin)
+		return -EINVAL;
+
+	if (enable) {
+		/* Enable GPIO at initial use */
+		if (pin->enable_count == 0)
+			gpio_set_value_cansleep(pin->gpio,
+						!pin->ena_gpio_invert);
+
+		pin->enable_count++;
+	} else {
+		if (pin->enable_count > 1) {
+			pin->enable_count--;
+			return 0;
+		}
+
+		/* Disable GPIO if not used */
+		if (pin->enable_count <= 1) {
+			gpio_set_value_cansleep(pin->gpio,
+						pin->ena_gpio_invert);
+			pin->enable_count = 0;
+		}
+	}
+
+	return 0;
+}
+
 static int _regulator_do_enable(struct regulator_dev *rdev)
 {
 	int ret, delay;
@@ -1471,9 +1580,10 @@ static int _regulator_do_enable(struct regulator_dev *rdev)
 
 	trace_regulator_enable(rdev_get_name(rdev));
 
-	if (rdev->ena_gpio) {
-		gpio_set_value_cansleep(rdev->ena_gpio,
-					!rdev->ena_gpio_invert);
+	if (rdev->ena_pin) {
+		ret = regulator_ena_gpio_ctrl(rdev, true);
+		if (ret < 0)
+			return ret;
 		rdev->ena_gpio_state = 1;
 	} else if (rdev->desc->ops->enable) {
 		ret = rdev->desc->ops->enable(rdev);
@@ -1575,9 +1685,10 @@ static int _regulator_do_disable(struct regulator_dev *rdev)
 
 	trace_regulator_disable(rdev_get_name(rdev));
 
-	if (rdev->ena_gpio) {
-		gpio_set_value_cansleep(rdev->ena_gpio,
-					rdev->ena_gpio_invert);
+	if (rdev->ena_pin) {
+		ret = regulator_ena_gpio_ctrl(rdev, false);
+		if (ret < 0)
+			return ret;
 		rdev->ena_gpio_state = 0;
 
 	} else if (rdev->desc->ops->disable) {
@@ -1794,7 +1905,10 @@ int regulator_is_enabled_regmap(struct regulator_dev *rdev)
 	if (ret != 0)
 		return ret;
 
-	return (val & rdev->desc->enable_mask) != 0;
+	if (rdev->desc->enable_is_inverted)
+		return (val & rdev->desc->enable_mask) == 0;
+	else
+		return (val & rdev->desc->enable_mask) != 0;
 }
 EXPORT_SYMBOL_GPL(regulator_is_enabled_regmap);
 
@@ -1809,9 +1923,15 @@ EXPORT_SYMBOL_GPL(regulator_is_enabled_regmap);
  */
 int regulator_enable_regmap(struct regulator_dev *rdev)
 {
+	unsigned int val;
+
+	if (rdev->desc->enable_is_inverted)
+		val = 0;
+	else
+		val = rdev->desc->enable_mask;
+
 	return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
-				  rdev->desc->enable_mask,
-				  rdev->desc->enable_mask);
+				  rdev->desc->enable_mask, val);
 }
 EXPORT_SYMBOL_GPL(regulator_enable_regmap);
 
@@ -1826,15 +1946,22 @@ EXPORT_SYMBOL_GPL(regulator_enable_regmap);
  */
 int regulator_disable_regmap(struct regulator_dev *rdev)
 {
+	unsigned int val;
+
+	if (rdev->desc->enable_is_inverted)
+		val = rdev->desc->enable_mask;
+	else
+		val = 0;
+
 	return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
-				  rdev->desc->enable_mask, 0);
+				  rdev->desc->enable_mask, val);
 }
 EXPORT_SYMBOL_GPL(regulator_disable_regmap);
 
 static int _regulator_is_enabled(struct regulator_dev *rdev)
 {
 	/* A GPIO control always takes precedence */
-	if (rdev->ena_gpio)
+	if (rdev->ena_pin)
 		return rdev->ena_gpio_state;
 
 	/* If we don't know then assume that the regulator is always on */
@@ -3237,7 +3364,7 @@ static int add_regulator_attributes(struct regulator_dev *rdev)
 		if (status < 0)
 			return status;
 	}
-	if (rdev->ena_gpio || ops->is_enabled) {
+	if (rdev->ena_pin || ops->is_enabled) {
 		status = device_create_file(dev, &dev_attr_state);
 		if (status < 0)
 			return status;
@@ -3439,22 +3566,17 @@ regulator_register(const struct regulator_desc *regulator_desc,
 	dev_set_drvdata(&rdev->dev, rdev);
 
 	if (config->ena_gpio && gpio_is_valid(config->ena_gpio)) {
-		ret = gpio_request_one(config->ena_gpio,
-				       GPIOF_DIR_OUT | config->ena_gpio_flags,
-				       rdev_get_name(rdev));
+		ret = regulator_ena_gpio_request(rdev, config);
 		if (ret != 0) {
 			rdev_err(rdev, "Failed to request enable GPIO%d: %d\n",
 				 config->ena_gpio, ret);
 			goto wash;
 		}
 
-		rdev->ena_gpio = config->ena_gpio;
-		rdev->ena_gpio_invert = config->ena_gpio_invert;
-
 		if (config->ena_gpio_flags & GPIOF_OUT_INIT_HIGH)
 			rdev->ena_gpio_state = 1;
 
-		if (rdev->ena_gpio_invert)
+		if (config->ena_gpio_invert)
 			rdev->ena_gpio_state = !rdev->ena_gpio_state;
 	}
 
@@ -3526,8 +3648,7 @@ unset_supplies:
 scrub:
 	if (rdev->supply)
 		_regulator_put(rdev->supply);
-	if (rdev->ena_gpio)
-		gpio_free(rdev->ena_gpio);
+	regulator_ena_gpio_free(rdev);
 	kfree(rdev->constraints);
 wash:
 	device_unregister(&rdev->dev);
@@ -3562,8 +3683,7 @@ void regulator_unregister(struct regulator_dev *rdev)
 	unset_regulator_supplies(rdev);
 	list_del(&rdev->list);
 	kfree(rdev->constraints);
-	if (rdev->ena_gpio)
-		gpio_free(rdev->ena_gpio);
+	regulator_ena_gpio_free(rdev);
 	device_unregister(&rdev->dev);
 	mutex_unlock(&regulator_list_mutex);
 }
diff --git a/drivers/regulator/dbx500-prcmu.h b/drivers/regulator/dbx500-prcmu.h
index e763883..c8e51ac 100644
--- a/drivers/regulator/dbx500-prcmu.h
+++ b/drivers/regulator/dbx500-prcmu.h
@@ -21,7 +21,6 @@
  * @is_enabled: status of the regulator
  * @epod_id: id for EPOD (power domain)
  * @is_ramret: RAM retention switch for EPOD (power domain)
- * @operating_point: operating point (only for vape, to be removed)
  *
  */
 struct dbx500_regulator_info {
@@ -32,7 +31,6 @@ struct dbx500_regulator_info {
 	u16 epod_id;
 	bool is_ramret;
 	bool exclude_from_power_state;
-	unsigned int operating_point;
 };
 
 void power_state_active_enable(void);
diff --git a/drivers/regulator/fan53555.c b/drivers/regulator/fan53555.c
index 9165b0c..f0e1ae5 100644
--- a/drivers/regulator/fan53555.c
+++ b/drivers/regulator/fan53555.c
@@ -219,9 +219,7 @@ static int fan53555_regulator_register(struct fan53555_device_info *di,
 	rdesc->owner = THIS_MODULE;
 
 	di->rdev = regulator_register(&di->desc, config);
-	if (IS_ERR(di->rdev))
-		return PTR_ERR(di->rdev);
-	return 0;
+	return PTR_RET(di->rdev);
 
 }
 
diff --git a/drivers/regulator/lp8788-ldo.c b/drivers/regulator/lp8788-ldo.c
index cd5a14a..0ce2c4c 100644
--- a/drivers/regulator/lp8788-ldo.c
+++ b/drivers/regulator/lp8788-ldo.c
@@ -156,68 +156,6 @@ static const int lp8788_aldo7_vtbl[] = {
 	1200000, 1300000, 1400000, 1500000, 1600000, 1700000, 1800000, 1800000,
 };
 
-static enum lp8788_ldo_id lp8788_dldo_id[] = {
-	DLDO1,
-	DLDO2,
-	DLDO3,
-	DLDO4,
-	DLDO5,
-	DLDO6,
-	DLDO7,
-	DLDO8,
-	DLDO9,
-	DLDO10,
-	DLDO11,
-	DLDO12,
-};
-
-static enum lp8788_ldo_id lp8788_aldo_id[] = {
-	ALDO1,
-	ALDO2,
-	ALDO3,
-	ALDO4,
-	ALDO5,
-	ALDO6,
-	ALDO7,
-	ALDO8,
-	ALDO9,
-	ALDO10,
-};
-
-static int lp8788_ldo_enable(struct regulator_dev *rdev)
-{
-	struct lp8788_ldo *ldo = rdev_get_drvdata(rdev);
-
-	if (ldo->en_pin) {
-		gpio_set_value(ldo->en_pin->gpio, ENABLE);
-		return 0;
-	} else {
-		return regulator_enable_regmap(rdev);
-	}
-}
-
-static int lp8788_ldo_disable(struct regulator_dev *rdev)
-{
-	struct lp8788_ldo *ldo = rdev_get_drvdata(rdev);
-
-	if (ldo->en_pin) {
-		gpio_set_value(ldo->en_pin->gpio, DISABLE);
-		return 0;
-	} else {
-		return regulator_disable_regmap(rdev);
-	}
-}
-
-static int lp8788_ldo_is_enabled(struct regulator_dev *rdev)
-{
-	struct lp8788_ldo *ldo = rdev_get_drvdata(rdev);
-
-	if (ldo->en_pin)
-		return gpio_get_value(ldo->en_pin->gpio) ? 1 : 0;
-	else
-		return regulator_is_enabled_regmap(rdev);
-}
-
 static int lp8788_ldo_enable_time(struct regulator_dev *rdev)
 {
 	struct lp8788_ldo *ldo = rdev_get_drvdata(rdev);
@@ -232,38 +170,21 @@ static int lp8788_ldo_enable_time(struct regulator_dev *rdev)
 	return ENABLE_TIME_USEC * val;
 }
 
-static int lp8788_ldo_fixed_get_voltage(struct regulator_dev *rdev)
-{
-	enum lp8788_ldo_id id = rdev_get_id(rdev);
-
-	switch (id) {
-	case ALDO2 ... ALDO5:
-		return 2850000;
-	case DLDO12:
-	case ALDO8 ... ALDO9:
-		return 2500000;
-	case ALDO10:
-		return 1100000;
-	default:
-		return -EINVAL;
-	}
-}
-
 static struct regulator_ops lp8788_ldo_voltage_table_ops = {
 	.list_voltage = regulator_list_voltage_table,
 	.set_voltage_sel = regulator_set_voltage_sel_regmap,
 	.get_voltage_sel = regulator_get_voltage_sel_regmap,
-	.enable = lp8788_ldo_enable,
-	.disable = lp8788_ldo_disable,
-	.is_enabled = lp8788_ldo_is_enabled,
+	.enable = regulator_enable_regmap,
+	.disable = regulator_disable_regmap,
+	.is_enabled = regulator_is_enabled_regmap,
 	.enable_time = lp8788_ldo_enable_time,
 };
 
 static struct regulator_ops lp8788_ldo_voltage_fixed_ops = {
-	.get_voltage = lp8788_ldo_fixed_get_voltage,
-	.enable = lp8788_ldo_enable,
-	.disable = lp8788_ldo_disable,
-	.is_enabled = lp8788_ldo_is_enabled,
+	.list_voltage = regulator_list_voltage_linear,
+	.enable = regulator_enable_regmap,
+	.disable = regulator_disable_regmap,
+	.is_enabled = regulator_is_enabled_regmap,
 	.enable_time = lp8788_ldo_enable_time,
 };
 
@@ -420,6 +341,7 @@ static struct regulator_desc lp8788_dldo_desc[] = {
 		.owner = THIS_MODULE,
 		.enable_reg = LP8788_EN_LDO_B,
 		.enable_mask = LP8788_EN_DLDO12_M,
+		.min_uV = 2500000,
 	},
 };
 
@@ -446,6 +368,7 @@ static struct regulator_desc lp8788_aldo_desc[] = {
 		.owner = THIS_MODULE,
 		.enable_reg = LP8788_EN_LDO_B,
 		.enable_mask = LP8788_EN_ALDO2_M,
+		.min_uV = 2850000,
 	},
 	{
 		.name = "aldo3",
@@ -456,6 +379,7 @@ static struct regulator_desc lp8788_aldo_desc[] = {
 		.owner = THIS_MODULE,
 		.enable_reg = LP8788_EN_LDO_B,
 		.enable_mask = LP8788_EN_ALDO3_M,
+		.min_uV = 2850000,
 	},
 	{
 		.name = "aldo4",
@@ -466,6 +390,7 @@ static struct regulator_desc lp8788_aldo_desc[] = {
 		.owner = THIS_MODULE,
 		.enable_reg = LP8788_EN_LDO_B,
 		.enable_mask = LP8788_EN_ALDO4_M,
+		.min_uV = 2850000,
 	},
 	{
 		.name = "aldo5",
@@ -476,6 +401,7 @@ static struct regulator_desc lp8788_aldo_desc[] = {
 		.owner = THIS_MODULE,
 		.enable_reg = LP8788_EN_LDO_C,
 		.enable_mask = LP8788_EN_ALDO5_M,
+		.min_uV = 2850000,
 	},
 	{
 		.name = "aldo6",
@@ -512,6 +438,7 @@ static struct regulator_desc lp8788_aldo_desc[] = {
 		.owner = THIS_MODULE,
 		.enable_reg = LP8788_EN_LDO_C,
 		.enable_mask = LP8788_EN_ALDO8_M,
+		.min_uV = 2500000,
 	},
 	{
 		.name = "aldo9",
@@ -522,6 +449,7 @@ static struct regulator_desc lp8788_aldo_desc[] = {
 		.owner = THIS_MODULE,
 		.enable_reg = LP8788_EN_LDO_C,
 		.enable_mask = LP8788_EN_ALDO9_M,
+		.min_uV = 2500000,
 	},
 	{
 		.name = "aldo10",
@@ -532,46 +460,14 @@ static struct regulator_desc lp8788_aldo_desc[] = {
 		.owner = THIS_MODULE,
 		.enable_reg = LP8788_EN_LDO_C,
 		.enable_mask = LP8788_EN_ALDO10_M,
+		.min_uV = 1100000,
 	},
 };
 
-static int lp8788_gpio_request_ldo_en(struct platform_device *pdev,
-				struct lp8788_ldo *ldo,
-				enum lp8788_ext_ldo_en_id id)
-{
-	struct device *dev = &pdev->dev;
-	struct lp8788_ldo_enable_pin *pin = ldo->en_pin;
-	int ret, gpio, pinstate;
-	char *name[] = {
-		[EN_ALDO1]   = "LP8788_EN_ALDO1",
-		[EN_ALDO234] = "LP8788_EN_ALDO234",
-		[EN_ALDO5]   = "LP8788_EN_ALDO5",
-		[EN_ALDO7]   = "LP8788_EN_ALDO7",
-		[EN_DLDO7]   = "LP8788_EN_DLDO7",
-		[EN_DLDO911] = "LP8788_EN_DLDO911",
-	};
-
-	gpio = pin->gpio;
-	if (!gpio_is_valid(gpio)) {
-		dev_err(dev, "invalid gpio: %d\n", gpio);
-		return -EINVAL;
-	}
-
-	pinstate = pin->init_state;
-	ret = devm_gpio_request_one(dev, gpio, pinstate, name[id]);
-	if (ret == -EBUSY) {
-		dev_warn(dev, "gpio%d already used\n", gpio);
-		return 0;
-	}
-
-	return ret;
-}
-
 static int lp8788_config_ldo_enable_mode(struct platform_device *pdev,
 					struct lp8788_ldo *ldo,
 					enum lp8788_ldo_id id)
 {
-	int ret;
 	struct lp8788 *lp = ldo->lp;
 	struct lp8788_platform_data *pdata = lp->pdata;
 	enum lp8788_ext_ldo_en_id enable_id;
@@ -613,14 +509,7 @@ static int lp8788_config_ldo_enable_mode(struct platform_device *pdev,
 		goto set_default_ldo_enable_mode;
 
 	ldo->en_pin = pdata->ldo_pin[enable_id];
-
-	ret = lp8788_gpio_request_ldo_en(pdev, ldo, enable_id);
-	if (ret) {
-		ldo->en_pin = NULL;
-		goto set_default_ldo_enable_mode;
-	}
-
-	return ret;
+	return 0;
 
 set_default_ldo_enable_mode:
 	return lp8788_update_bits(lp, LP8788_EN_SEL, en_mask[enable_id], 0);
@@ -640,10 +529,15 @@ static int lp8788_dldo_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	ldo->lp = lp;
-	ret = lp8788_config_ldo_enable_mode(pdev, ldo, lp8788_dldo_id[id]);
+	ret = lp8788_config_ldo_enable_mode(pdev, ldo, id);
 	if (ret)
 		return ret;
 
+	if (ldo->en_pin) {
+		cfg.ena_gpio = ldo->en_pin->gpio;
+		cfg.ena_gpio_flags = ldo->en_pin->init_state;
+	}
+
 	cfg.dev = pdev->dev.parent;
 	cfg.init_data = lp->pdata ? lp->pdata->dldo_data[id] : NULL;
 	cfg.driver_data = ldo;
@@ -696,10 +590,15 @@ static int lp8788_aldo_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	ldo->lp = lp;
-	ret = lp8788_config_ldo_enable_mode(pdev, ldo, lp8788_aldo_id[id]);
+	ret = lp8788_config_ldo_enable_mode(pdev, ldo, id + ALDO1);
 	if (ret)
 		return ret;
 
+	if (ldo->en_pin) {
+		cfg.ena_gpio = ldo->en_pin->gpio;
+		cfg.ena_gpio_flags = ldo->en_pin->init_state;
+	}
+
 	cfg.dev = pdev->dev.parent;
 	cfg.init_data = lp->pdata ? lp->pdata->aldo_data[id] : NULL;
 	cfg.driver_data = ldo;
diff --git a/drivers/regulator/max1586.c b/drivers/regulator/max1586.c
index 8c5a54f..dac0490 100644
--- a/drivers/regulator/max1586.c
+++ b/drivers/regulator/max1586.c
@@ -56,7 +56,7 @@ struct max1586_data {
  *   set V6 to either 0V, 1.8V, 2.5V, 3V depending on (x & 0x3)
  * As regulator framework doesn't accept voltages to be 0V, we use 1uV.
  */
-static int v6_voltages_uv[] = { 1, 1800000, 2500000, 3000000 };
+static const unsigned int v6_voltages_uv[] = { 1, 1800000, 2500000, 3000000 };
 
 /*
  * V3 voltage
diff --git a/drivers/regulator/max8649.c b/drivers/regulator/max8649.c
index 3ca1438..fdb67ff 100644
--- a/drivers/regulator/max8649.c
+++ b/drivers/regulator/max8649.c
@@ -60,36 +60,6 @@ struct max8649_regulator_info {
 	unsigned	ramp_down:1;
 };
 
-/* EN_PD means pulldown on EN input */
-static int max8649_enable(struct regulator_dev *rdev)
-{
-	struct max8649_regulator_info *info = rdev_get_drvdata(rdev);
-	return regmap_update_bits(info->regmap, MAX8649_CONTROL, MAX8649_EN_PD, 0);
-}
-
-/*
- * Applied internal pulldown resistor on EN input pin.
- * If pulldown EN pin outside, it would be better.
- */
-static int max8649_disable(struct regulator_dev *rdev)
-{
-	struct max8649_regulator_info *info = rdev_get_drvdata(rdev);
-	return regmap_update_bits(info->regmap, MAX8649_CONTROL, MAX8649_EN_PD,
-				MAX8649_EN_PD);
-}
-
-static int max8649_is_enabled(struct regulator_dev *rdev)
-{
-	struct max8649_regulator_info *info = rdev_get_drvdata(rdev);
-	unsigned int val;
-	int ret;
-
-	ret = regmap_read(info->regmap, MAX8649_CONTROL, &val);
-	if (ret != 0)
-		return ret;
-	return !((unsigned char)val & MAX8649_EN_PD);
-}
-
 static int max8649_enable_time(struct regulator_dev *rdev)
 {
 	struct max8649_regulator_info *info = rdev_get_drvdata(rdev);
@@ -151,9 +121,9 @@ static struct regulator_ops max8649_dcdc_ops = {
 	.get_voltage_sel = regulator_get_voltage_sel_regmap,
 	.list_voltage	= regulator_list_voltage_linear,
 	.map_voltage	= regulator_map_voltage_linear,
-	.enable		= max8649_enable,
-	.disable	= max8649_disable,
-	.is_enabled	= max8649_is_enabled,
+	.enable		= regulator_enable_regmap,
+	.disable	= regulator_disable_regmap,
+	.is_enabled	= regulator_is_enabled_regmap,
 	.enable_time	= max8649_enable_time,
 	.set_mode	= max8649_set_mode,
 	.get_mode	= max8649_get_mode,
@@ -169,6 +139,9 @@ static struct regulator_desc dcdc_desc = {
 	.vsel_mask	= MAX8649_VOL_MASK,
 	.min_uV		= MAX8649_DCDC_VMIN,
 	.uV_step	= MAX8649_DCDC_STEP,
+	.enable_reg	= MAX8649_CONTROL,
+	.enable_mask	= MAX8649_EN_PD,
+	.enable_is_inverted = true,
 };
 
 static struct regmap_config max8649_regmap_config = {
diff --git a/drivers/regulator/max8925-regulator.c b/drivers/regulator/max8925-regulator.c
index 0d5f64a..3597da8 100644
--- a/drivers/regulator/max8925-regulator.c
+++ b/drivers/regulator/max8925-regulator.c
@@ -246,7 +246,6 @@ static struct max8925_regulator_info max8925_regulator_info[] = {
 
 #ifdef CONFIG_OF
 static int max8925_regulator_dt_init(struct platform_device *pdev,
-				    struct max8925_regulator_info *info,
 				    struct regulator_config *config,
 				    int ridx)
 {
@@ -272,7 +271,7 @@ static int max8925_regulator_dt_init(struct platform_device *pdev,
 	return 0;
 }
 #else
-#define max8925_regulator_dt_init(w, x, y, z)	(-1)
+#define max8925_regulator_dt_init(x, y, z)	(-1)
 #endif
 
 static int max8925_regulator_probe(struct platform_device *pdev)
@@ -309,7 +308,7 @@ static int max8925_regulator_probe(struct platform_device *pdev)
 	config.dev = &pdev->dev;
 	config.driver_data = ri;
 
-	if (max8925_regulator_dt_init(pdev, ri, &config, regulator_idx))
+	if (max8925_regulator_dt_init(pdev, &config, regulator_idx))
 		if (pdata)
 			config.init_data = pdata;
 
diff --git a/drivers/regulator/max8998.c b/drivers/regulator/max8998.c
index b588f07..a57a1b1 100644
--- a/drivers/regulator/max8998.c
+++ b/drivers/regulator/max8998.c
@@ -665,14 +665,16 @@ static int max8998_pmic_probe(struct platform_device *pdev)
 	    gpio_is_valid(pdata->buck1_set2)) {
 		/* Check if SET1 is not equal to 0 */
 		if (!pdata->buck1_set1) {
-			printk(KERN_ERR "MAX8998 SET1 GPIO defined as 0 !\n");
+			dev_err(&pdev->dev,
+				"MAX8998 SET1 GPIO defined as 0 !\n");
 			WARN_ON(!pdata->buck1_set1);
 			ret = -EIO;
 			goto err_out;
 		}
 		/* Check if SET2 is not equal to 0 */
 		if (!pdata->buck1_set2) {
-			printk(KERN_ERR "MAX8998 SET2 GPIO defined as 0 !\n");
+			dev_err(&pdev->dev,
+				"MAX8998 SET2 GPIO defined as 0 !\n");
 			WARN_ON(!pdata->buck1_set2);
 			ret = -EIO;
 			goto err_out;
@@ -738,7 +740,8 @@ static int max8998_pmic_probe(struct platform_device *pdev)
 	if (gpio_is_valid(pdata->buck2_set3)) {
 		/* Check if SET3 is not equal to 0 */
 		if (!pdata->buck2_set3) {
-			printk(KERN_ERR "MAX8998 SET3 GPIO defined as 0 !\n");
+			dev_err(&pdev->dev,
+				"MAX8998 SET3 GPIO defined as 0 !\n");
 			WARN_ON(!pdata->buck2_set3);
 			ret = -EIO;
 			goto err_out;
diff --git a/drivers/regulator/palmas-regulator.c b/drivers/regulator/palmas-regulator.c
index 39cf146..7c54e31 100644
--- a/drivers/regulator/palmas-regulator.c
+++ b/drivers/regulator/palmas-regulator.c
@@ -1,7 +1,7 @@
 /*
  * Driver for Regulator part of Palmas PMIC Chips
  *
- * Copyright 2011-2012 Texas Instruments Inc.
+ * Copyright 2011-2013 Texas Instruments Inc.
  *
  * Author: Graeme Gregory <gg@slimlogic.co.uk>
  * Author: Ian Lartey <ian@slimlogic.co.uk>
@@ -29,6 +29,7 @@
 
 struct regs_info {
 	char	*name;
+	char	*sname;
 	u8	vsel_addr;
 	u8	ctrl_addr;
 	u8	tstep_addr;
@@ -37,110 +38,131 @@ struct regs_info {
 static const struct regs_info palmas_regs_info[] = {
 	{
 		.name		= "SMPS12",
+		.sname		= "smps1-in",
 		.vsel_addr	= PALMAS_SMPS12_VOLTAGE,
 		.ctrl_addr	= PALMAS_SMPS12_CTRL,
 		.tstep_addr	= PALMAS_SMPS12_TSTEP,
 	},
 	{
 		.name		= "SMPS123",
+		.sname		= "smps1-in",
 		.vsel_addr	= PALMAS_SMPS12_VOLTAGE,
 		.ctrl_addr	= PALMAS_SMPS12_CTRL,
 		.tstep_addr	= PALMAS_SMPS12_TSTEP,
 	},
 	{
 		.name		= "SMPS3",
+		.sname		= "smps3-in",
 		.vsel_addr	= PALMAS_SMPS3_VOLTAGE,
 		.ctrl_addr	= PALMAS_SMPS3_CTRL,
 	},
 	{
 		.name		= "SMPS45",
+		.sname		= "smps4-in",
 		.vsel_addr	= PALMAS_SMPS45_VOLTAGE,
 		.ctrl_addr	= PALMAS_SMPS45_CTRL,
 		.tstep_addr	= PALMAS_SMPS45_TSTEP,
 	},
 	{
 		.name		= "SMPS457",
+		.sname		= "smps4-in",
 		.vsel_addr	= PALMAS_SMPS45_VOLTAGE,
 		.ctrl_addr	= PALMAS_SMPS45_CTRL,
 		.tstep_addr	= PALMAS_SMPS45_TSTEP,
 	},
 	{
 		.name		= "SMPS6",
+		.sname		= "smps6-in",
 		.vsel_addr	= PALMAS_SMPS6_VOLTAGE,
 		.ctrl_addr	= PALMAS_SMPS6_CTRL,
 		.tstep_addr	= PALMAS_SMPS6_TSTEP,
 	},
 	{
 		.name		= "SMPS7",
+		.sname		= "smps7-in",
 		.vsel_addr	= PALMAS_SMPS7_VOLTAGE,
 		.ctrl_addr	= PALMAS_SMPS7_CTRL,
 	},
 	{
 		.name		= "SMPS8",
+		.sname		= "smps8-in",
 		.vsel_addr	= PALMAS_SMPS8_VOLTAGE,
 		.ctrl_addr	= PALMAS_SMPS8_CTRL,
 		.tstep_addr	= PALMAS_SMPS8_TSTEP,
 	},
 	{
 		.name		= "SMPS9",
+		.sname		= "smps9-in",
 		.vsel_addr	= PALMAS_SMPS9_VOLTAGE,
 		.ctrl_addr	= PALMAS_SMPS9_CTRL,
 	},
 	{
 		.name		= "SMPS10",
+		.sname		= "smps10-in",
 	},
 	{
 		.name		= "LDO1",
+		.sname		= "ldo1-in",
 		.vsel_addr	= PALMAS_LDO1_VOLTAGE,
 		.ctrl_addr	= PALMAS_LDO1_CTRL,
 	},
 	{
 		.name		= "LDO2",
+		.sname		= "ldo2-in",
 		.vsel_addr	= PALMAS_LDO2_VOLTAGE,
 		.ctrl_addr	= PALMAS_LDO2_CTRL,
 	},
 	{
 		.name		= "LDO3",
+		.sname		= "ldo3-in",
 		.vsel_addr	= PALMAS_LDO3_VOLTAGE,
 		.ctrl_addr	= PALMAS_LDO3_CTRL,
 	},
 	{
 		.name		= "LDO4",
+		.sname		= "ldo4-in",
 		.vsel_addr	= PALMAS_LDO4_VOLTAGE,
 		.ctrl_addr	= PALMAS_LDO4_CTRL,
 	},
 	{
 		.name		= "LDO5",
+		.sname		= "ldo5-in",
 		.vsel_addr	= PALMAS_LDO5_VOLTAGE,
 		.ctrl_addr	= PALMAS_LDO5_CTRL,
 	},
 	{
 		.name		= "LDO6",
+		.sname		= "ldo6-in",
 		.vsel_addr	= PALMAS_LDO6_VOLTAGE,
 		.ctrl_addr	= PALMAS_LDO6_CTRL,
 	},
 	{
 		.name		= "LDO7",
+		.sname		= "ldo7-in",
 		.vsel_addr	= PALMAS_LDO7_VOLTAGE,
 		.ctrl_addr	= PALMAS_LDO7_CTRL,
 	},
 	{
 		.name		= "LDO8",
+		.sname		= "ldo8-in",
 		.vsel_addr	= PALMAS_LDO8_VOLTAGE,
 		.ctrl_addr	= PALMAS_LDO8_CTRL,
 	},
 	{
 		.name		= "LDO9",
+		.sname		= "ldo9-in",
 		.vsel_addr	= PALMAS_LDO9_VOLTAGE,
 		.ctrl_addr	= PALMAS_LDO9_CTRL,
 	},
 	{
 		.name		= "LDOLN",
+		.sname		= "ldoln-in",
 		.vsel_addr	= PALMAS_LDOLN_VOLTAGE,
 		.ctrl_addr	= PALMAS_LDOLN_CTRL,
 	},
 	{
 		.name		= "LDOUSB",
+		.sname		= "ldousb-in",
 		.vsel_addr	= PALMAS_LDOUSB_VOLTAGE,
 		.ctrl_addr	= PALMAS_LDOUSB_CTRL,
 	},
@@ -553,18 +575,16 @@ static void palmas_dt_to_pdata(struct device *dev,
 		pdata->reg_init[idx] = devm_kzalloc(dev,
 				sizeof(struct palmas_reg_init), GFP_KERNEL);
 
-		ret = of_property_read_u32(palmas_matches[idx].of_node,
-				"ti,warm_reset", &prop);
-		if (!ret)
-			pdata->reg_init[idx]->warm_reset = prop;
+		pdata->reg_init[idx]->warm_reset =
+			of_property_read_bool(palmas_matches[idx].of_node,
+					     "ti,warm-reset");
 
-		ret = of_property_read_u32(palmas_matches[idx].of_node,
-				"ti,roof_floor", &prop);
-		if (!ret)
-			pdata->reg_init[idx]->roof_floor = prop;
+		pdata->reg_init[idx]->roof_floor =
+			of_property_read_bool(palmas_matches[idx].of_node,
+					      "ti,roof-floor");
 
 		ret = of_property_read_u32(palmas_matches[idx].of_node,
-				"ti,mode_sleep", &prop);
+				"ti,mode-sleep", &prop);
 		if (!ret)
 			pdata->reg_init[idx]->mode_sleep = prop;
 
@@ -573,19 +593,18 @@ static void palmas_dt_to_pdata(struct device *dev,
 		if (!ret)
 			pdata->reg_init[idx]->tstep = prop;
 
-		ret = of_property_read_u32(palmas_matches[idx].of_node,
-				"ti,vsel", &prop);
-		if (!ret)
-			pdata->reg_init[idx]->vsel = prop;
+		ret = of_property_read_bool(palmas_matches[idx].of_node,
+					    "ti,smps-range");
+		if (ret)
+			pdata->reg_init[idx]->vsel =
+				PALMAS_SMPS12_VOLTAGE_RANGE;
 	}
 
-	ret = of_property_read_u32(node, "ti,ldo6_vibrator", &prop);
-	if (!ret)
-		pdata->ldo6_vibrator = prop;
+	pdata->ldo6_vibrator = of_property_read_bool(node, "ti,ldo6-vibrator");
 }
 
 
-static int palmas_probe(struct platform_device *pdev)
+static int palmas_regulators_probe(struct platform_device *pdev)
 {
 	struct palmas *palmas = dev_get_drvdata(pdev->dev.parent);
 	struct palmas_pmic_platform_data *pdata = pdev->dev.platform_data;
@@ -713,6 +732,7 @@ static int palmas_probe(struct platform_device *pdev)
 		else
 			config.init_data = NULL;
 
+		pmic->desc[id].supply_name = palmas_regs_info[id].sname;
 		config.of_node = palmas_matches[id].of_node;
 
 		rdev = regulator_register(&pmic->desc[id], &config);
@@ -759,6 +779,7 @@ static int palmas_probe(struct platform_device *pdev)
 		else
 			config.init_data = NULL;
 
+		pmic->desc[id].supply_name = palmas_regs_info[id].sname;
 		config.of_node = palmas_matches[id].of_node;
 
 		rdev = regulator_register(&pmic->desc[id], &config);
@@ -794,7 +815,7 @@ err_unregister_regulator:
 	return ret;
 }
 
-static int palmas_remove(struct platform_device *pdev)
+static int palmas_regulators_remove(struct platform_device *pdev)
 {
 	struct palmas_pmic *pmic = platform_get_drvdata(pdev);
 	int id;
@@ -806,6 +827,12 @@ static int palmas_remove(struct platform_device *pdev)
 
 static struct of_device_id of_palmas_match_tbl[] = {
 	{ .compatible = "ti,palmas-pmic", },
+	{ .compatible = "ti,twl6035-pmic", },
+	{ .compatible = "ti,twl6036-pmic", },
+	{ .compatible = "ti,twl6037-pmic", },
+	{ .compatible = "ti,tps65913-pmic", },
+	{ .compatible = "ti,tps65914-pmic", },
+	{ .compatible = "ti,tps80036-pmic", },
 	{ /* end */ }
 };
 
@@ -815,8 +842,8 @@ static struct platform_driver palmas_driver = {
 		.of_match_table = of_palmas_match_tbl,
 		.owner = THIS_MODULE,
 	},
-	.probe = palmas_probe,
-	.remove = palmas_remove,
+	.probe = palmas_regulators_probe,
+	.remove = palmas_regulators_remove,
 };
 
 static int __init palmas_init(void)
diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c
index 8a83194..8e56198 100644
--- a/drivers/regulator/s5m8767.c
+++ b/drivers/regulator/s5m8767.c
@@ -549,7 +549,7 @@ static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev,
 
 	rmode = devm_kzalloc(&pdev->dev, sizeof(*rmode) *
 				pdata->num_regulators, GFP_KERNEL);
-	if (!rdata) {
+	if (!rmode) {
 		dev_err(iodev->dev,
 			"could not allocate memory for regulator mode\n");
 		return -ENOMEM;
diff --git a/drivers/regulator/tps6586x-regulator.c b/drivers/regulator/tps6586x-regulator.c
index e68382d..b813d21 100644
--- a/drivers/regulator/tps6586x-regulator.c
+++ b/drivers/regulator/tps6586x-regulator.c
@@ -245,7 +245,7 @@ static int tps6586x_regulator_set_slew_rate(struct platform_device *pdev,
 		reg = TPS6586X_SM1SL;
 		break;
 	default:
-		dev_warn(&pdev->dev, "Only SM0/SM1 can set slew rate\n");
+		dev_err(&pdev->dev, "Only SM0/SM1 can set slew rate\n");
 		return -EINVAL;
 	}
 
@@ -304,14 +304,12 @@ static struct tps6586x_platform_data *tps6586x_parse_regulator_dt(
 	}
 
 	err = of_regulator_match(&pdev->dev, regs, tps6586x_matches, num);
+	of_node_put(regs);
 	if (err < 0) {
 		dev_err(&pdev->dev, "Regulator match failed, e %d\n", err);
-		of_node_put(regs);
 		return NULL;
 	}
 
-	of_node_put(regs);
-
 	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
 	if (!pdata) {
 		dev_err(&pdev->dev, "Memory alloction failed\n");
diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
index cc1f7bf..2465c71 100644
--- a/drivers/remoteproc/Kconfig
+++ b/drivers/remoteproc/Kconfig
@@ -12,8 +12,9 @@ config OMAP_REMOTEPROC
 	depends on HAS_DMA
 	depends on ARCH_OMAP4
 	depends on OMAP_IOMMU
-	depends on OMAP_MBOX_FWK
 	select REMOTEPROC
+	select MAILBOX
+	select OMAP2PLUS_MBOX
 	select RPMSG
 	help
 	  Say y here to support OMAP's remote processors (dual M3
diff --git a/drivers/remoteproc/omap_remoteproc.c b/drivers/remoteproc/omap_remoteproc.c
index 0e396c1..b90beef 100644
--- a/drivers/remoteproc/omap_remoteproc.c
+++ b/drivers/remoteproc/omap_remoteproc.c
@@ -27,8 +27,8 @@
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
 #include <linux/remoteproc.h>
+#include <linux/mailbox.h>
 
-#include <plat/mailbox.h>
 #include <linux/platform_data/remoteproc-omap.h>
 
 #include "omap_remoteproc.h"
@@ -41,7 +41,7 @@
  * @rproc: rproc handle
  */
 struct omap_rproc {
-	struct omap_mbox *mbox;
+	struct mailbox *mbox;
 	struct notifier_block nb;
 	struct rproc *rproc;
 };
@@ -64,14 +64,15 @@ struct omap_rproc {
 static int omap_rproc_mbox_callback(struct notifier_block *this,
 					unsigned long index, void *data)
 {
-	mbox_msg_t msg = (mbox_msg_t) data;
 	struct omap_rproc *oproc = container_of(this, struct omap_rproc, nb);
 	struct device *dev = oproc->rproc->dev.parent;
+	struct mailbox_msg *msg = data;
 	const char *name = oproc->rproc->name;
+	u32 msg_data = (u32)msg->pdata;
 
-	dev_dbg(dev, "mbox msg: 0x%x\n", msg);
+	dev_dbg(dev, "mbox msg: 0x%x\n", msg_data);
 
-	switch (msg) {
+	switch (msg_data) {
 	case RP_MBOX_CRASH:
 		/* just log this for now. later, we'll also do recovery */
 		dev_err(dev, "omap rproc %s crashed\n", name);
@@ -81,8 +82,9 @@ static int omap_rproc_mbox_callback(struct notifier_block *this,
 		break;
 	default:
 		/* msg contains the index of the triggered vring */
-		if (rproc_vq_interrupt(oproc->rproc, msg) == IRQ_NONE)
-			dev_dbg(dev, "no message was found in vqid %d\n", msg);
+		if (rproc_vq_interrupt(oproc->rproc, msg_data) == IRQ_NONE)
+			dev_dbg(dev, "no message was found in vqid %d\n",
+								msg_data);
 	}
 
 	return NOTIFY_DONE;
@@ -93,12 +95,14 @@ static void omap_rproc_kick(struct rproc *rproc, int vqid)
 {
 	struct omap_rproc *oproc = rproc->priv;
 	struct device *dev = rproc->dev.parent;
+	struct mailbox_msg msg;
 	int ret;
 
 	/* send the index of the triggered virtqueue in the mailbox payload */
-	ret = omap_mbox_msg_send(oproc->mbox, vqid);
+	MAILBOX_FILL_MSG(msg, 0, vqid, 0);
+	ret = mailbox_msg_send(oproc->mbox, &msg);
 	if (ret)
-		dev_err(dev, "omap_mbox_msg_send failed: %d\n", ret);
+		dev_err(dev, "mailbox_msg_send failed: %d\n", ret);
 }
 
 /*
@@ -114,6 +118,7 @@ static int omap_rproc_start(struct rproc *rproc)
 	struct device *dev = rproc->dev.parent;
 	struct platform_device *pdev = to_platform_device(dev);
 	struct omap_rproc_pdata *pdata = pdev->dev.platform_data;
+	struct mailbox_msg msg;
 	int ret;
 
 	if (pdata->set_bootaddr)
@@ -122,10 +127,10 @@ static int omap_rproc_start(struct rproc *rproc)
 	oproc->nb.notifier_call = omap_rproc_mbox_callback;
 
 	/* every omap rproc is assigned a mailbox instance for messaging */
-	oproc->mbox = omap_mbox_get(pdata->mbox_name, &oproc->nb);
+	oproc->mbox = mailbox_get(pdata->mbox_name, &oproc->nb);
 	if (IS_ERR(oproc->mbox)) {
 		ret = PTR_ERR(oproc->mbox);
-		dev_err(dev, "omap_mbox_get failed: %d\n", ret);
+		dev_err(dev, "mailbox_get failed: %d\n", ret);
 		return ret;
 	}
 
@@ -136,9 +141,10 @@ static int omap_rproc_start(struct rproc *rproc)
 	 * Note that the reply will _not_ arrive immediately: this message
 	 * will wait in the mailbox fifo until the remote processor is booted.
 	 */
-	ret = omap_mbox_msg_send(oproc->mbox, RP_MBOX_ECHO_REQUEST);
+	MAILBOX_FILL_MSG(msg, 0, RP_MBOX_ECHO_REQUEST, 0);
+	ret = mailbox_msg_send(oproc->mbox, &msg);
 	if (ret) {
-		dev_err(dev, "omap_mbox_get failed: %d\n", ret);
+		dev_err(dev, "mailbox_get failed: %d\n", ret);
 		goto put_mbox;
 	}
 
@@ -151,7 +157,7 @@ static int omap_rproc_start(struct rproc *rproc)
 	return 0;
 
 put_mbox:
-	omap_mbox_put(oproc->mbox, &oproc->nb);
+	mailbox_put(oproc->mbox, &oproc->nb);
 	return ret;
 }
 
@@ -168,7 +174,7 @@ static int omap_rproc_stop(struct rproc *rproc)
 	if (ret)
 		return ret;
 
-	omap_mbox_put(oproc->mbox, &oproc->nb);
+	mailbox_put(oproc->mbox, &oproc->nb);
 
 	return 0;
 }
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
new file mode 100644
index 0000000..e728d36
--- /dev/null
+++ b/drivers/reset/Kconfig
@@ -0,0 +1,26 @@
+config ARCH_HAS_RESET_CONTROLLER
+	bool
+
+menuconfig RESET_CONTROLLER
+	bool "Reset Controller Support"
+	default y if ARCH_HAS_RESET_CONTROLLER
+	help
+	  Generic Reset Controller support.
+
+	  This framework is designed to abstract reset handling of devices
+	  via GPIOs or SoC-internal reset controller modules.
+
+	  If unsure, say no.
+
+if RESET_CONTROLLER
+
+config RESET_GPIO
+	tristate "GPIO reset controller support"
+	depends on GENERIC_GPIO
+	help
+	  This driver provides support for reset lines that are controlled
+	  directly by GPIOs.
+	  The delay between assertion and de-assertion of the reset signal
+	  can be configured.
+
+endif
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
new file mode 100644
index 0000000..b854f20
--- /dev/null
+++ b/drivers/reset/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_RESET_CONTROLLER) += core.o
+obj-$(CONFIG_RESET_GPIO) += gpio-reset.o
diff --git a/drivers/reset/core.c b/drivers/reset/core.c
new file mode 100644
index 0000000..a258277
--- /dev/null
+++ b/drivers/reset/core.c
@@ -0,0 +1,297 @@
+/*
+ * Reset Controller framework
+ *
+ * Copyright 2013 Philipp Zabel, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/err.h>
+#include <linux/export.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/reset.h>
+#include <linux/reset-controller.h>
+#include <linux/slab.h>
+
+static DEFINE_MUTEX(reset_controller_list_mutex);
+static LIST_HEAD(reset_controller_list);
+
+/**
+ * struct reset_control - a reset control
+ * @rcdev: a pointer to the reset controller device
+ *         this reset control belongs to
+ * @id: ID of the reset controller in the reset
+ *      controller device
+ */
+struct reset_control {
+	struct reset_controller_dev *rcdev;
+	struct device *dev;
+	unsigned int id;
+};
+
+/**
+ * of_reset_simple_xlate - translate reset_spec to the reset line number
+ * @rcdev: a pointer to the reset controller device
+ * @reset_spec: reset line specifier as found in the device tree
+ * @flags: a flags pointer to fill in (optional)
+ *
+ * This simple translation function should be used for reset controllers
+ * with 1:1 mapping, where reset lines can be indexed by number without gaps.
+ */
+int of_reset_simple_xlate(struct reset_controller_dev *rcdev,
+			  const struct of_phandle_args *reset_spec)
+{
+	if (WARN_ON(reset_spec->args_count != rcdev->of_reset_n_cells))
+		return -EINVAL;
+
+	if (reset_spec->args[0] >= rcdev->nr_resets)
+		return -EINVAL;
+
+	return reset_spec->args[0];
+}
+EXPORT_SYMBOL_GPL(of_reset_simple_xlate);
+
+/**
+ * reset_controller_register - register a reset controller device
+ * @rcdev: a pointer to the initialized reset controller device
+ */
+int reset_controller_register(struct reset_controller_dev *rcdev)
+{
+	if (!rcdev->of_xlate) {
+		rcdev->of_reset_n_cells = 1;
+		rcdev->of_xlate = of_reset_simple_xlate;
+	}
+
+	mutex_lock(&reset_controller_list_mutex);
+	list_add(&rcdev->list, &reset_controller_list);
+	mutex_unlock(&reset_controller_list_mutex);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(reset_controller_register);
+
+/**
+ * reset_controller_unregister - unregister a reset controller device
+ * @rcdev: a pointer to the reset controller device
+ */
+void reset_controller_unregister(struct reset_controller_dev *rcdev)
+{
+	mutex_lock(&reset_controller_list_mutex);
+	list_del(&rcdev->list);
+	mutex_unlock(&reset_controller_list_mutex);
+}
+EXPORT_SYMBOL_GPL(reset_controller_unregister);
+
+/**
+ * reset_control_reset - reset the controlled device
+ * @rstc: reset controller
+ */
+int reset_control_reset(struct reset_control *rstc)
+{
+	if (rstc->rcdev->ops->reset)
+		return rstc->rcdev->ops->reset(rstc->rcdev, rstc->id);
+
+	return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(reset_control_reset);
+
+/**
+ * reset_control_assert - asserts the reset line
+ * @rstc: reset controller
+ */
+int reset_control_assert(struct reset_control *rstc)
+{
+	if (rstc->rcdev->ops->assert)
+		return rstc->rcdev->ops->assert(rstc->rcdev, rstc->id);
+
+	return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(reset_control_assert);
+
+/**
+ * reset_control_deassert - deasserts the reset line
+ * @rstc: reset controller
+ */
+int reset_control_deassert(struct reset_control *rstc)
+{
+	if (rstc->rcdev->ops->deassert)
+		return rstc->rcdev->ops->deassert(rstc->rcdev, rstc->id);
+
+	return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(reset_control_deassert);
+
+/**
+ * reset_control_get - Lookup and obtain a reference to a reset controller.
+ * @dev: device to be reset by the controller
+ * @id: reset line name
+ *
+ * Returns a struct reset_control or IS_ERR() condition containing errno.
+ *
+ * Use of id names is optional.
+ */
+struct reset_control *reset_control_get(struct device *dev, const char *id)
+{
+	struct reset_control *rstc = ERR_PTR(-EPROBE_DEFER);
+	struct reset_controller_dev *r, *rcdev;
+	struct of_phandle_args args;
+	int index = 0;
+	int rstc_id;
+	int ret;
+
+	if (!dev)
+		return ERR_PTR(-EINVAL);
+
+	if (id)
+		index = of_property_match_string(dev->of_node,
+						 "reset-names", id);
+	ret = of_parse_phandle_with_args(dev->of_node, "resets", "#reset-cells",
+					 index, &args);
+	if (ret)
+		return ERR_PTR(ret);
+
+	mutex_lock(&reset_controller_list_mutex);
+	rcdev = NULL;
+	list_for_each_entry(r, &reset_controller_list, list) {
+		if (args.np == r->of_node) {
+			rcdev = r;
+			break;
+		}
+	}
+	of_node_put(args.np);
+
+	if (!rcdev) {
+		mutex_unlock(&reset_controller_list_mutex);
+		return ERR_PTR(-ENODEV);
+	}
+
+	rstc_id = rcdev->of_xlate(rcdev, &args);
+	if (rstc_id < 0) {
+		mutex_unlock(&reset_controller_list_mutex);
+		return ERR_PTR(rstc_id);
+	}
+
+	try_module_get(rcdev->owner);
+	mutex_unlock(&reset_controller_list_mutex);
+
+	rstc = kzalloc(sizeof(*rstc), GFP_KERNEL);
+	if (!rstc) {
+		module_put(rstc->rcdev->owner);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	rstc->dev = dev;
+	rstc->rcdev = rcdev;
+	rstc->id = rstc_id;
+
+	return rstc;
+}
+EXPORT_SYMBOL_GPL(reset_control_get);
+
+/**
+ * reset_control_put - free the reset controller
+ * @rstc: reset controller
+ */
+
+void reset_control_put(struct reset_control *rstc)
+{
+	if (IS_ERR(rstc))
+		return;
+
+	module_put(rstc->rcdev->owner);
+	kfree(rstc);
+}
+EXPORT_SYMBOL_GPL(reset_control_put);
+
+static void devm_reset_control_release(struct device *dev, void *res)
+{
+	reset_control_put(*(struct reset_control **)res);
+}
+
+/**
+ * devm_reset_control_get - resource managed reset_control_get()
+ * @dev: device to be reset by the controller
+ * @id: reset line name
+ *
+ * Managed reset_control_get(). For reset controllers returned from this
+ * function, reset_control_put() is called automatically on driver detach.
+ * See reset_control_get() for more information.
+ */
+struct reset_control *devm_reset_control_get(struct device *dev, const char *id)
+{
+	struct reset_control **ptr, *rstc;
+
+	ptr = devres_alloc(devm_reset_control_release, sizeof(*ptr),
+			   GFP_KERNEL);
+	if (!ptr)
+		return ERR_PTR(-ENOMEM);
+
+	rstc = reset_control_get(dev, id);
+	if (!IS_ERR(rstc)) {
+		*ptr = rstc;
+		devres_add(dev, ptr);
+	} else {
+		devres_free(ptr);
+	}
+
+	return rstc;
+}
+EXPORT_SYMBOL_GPL(devm_reset_control_get);
+
+static int devm_reset_control_match(struct device *dev, void *res, void *data)
+{
+	struct reset_control **rstc = res;
+	if (WARN_ON(!rstc || !*rstc))
+		return 0;
+	return *rstc == data;
+}
+
+/**
+ * devm_reset_control_put - resource managed reset_control_put()
+ * @rstc: reset controller to free
+ *
+ * Deallocate a reset control allocated withd devm_reset_control_get().
+ * This function will not need to be called normally, as devres will take
+ * care of freeing the resource.
+ */
+void devm_reset_control_put(struct reset_control *rstc)
+{
+	int ret;
+
+	ret = devres_release(rstc->dev, devm_reset_control_release,
+			     devm_reset_control_match, rstc);
+	if (ret)
+		WARN_ON(ret);
+}
+EXPORT_SYMBOL_GPL(devm_reset_control_put);
+
+/**
+ * device_reset - find reset controller associated with the device
+ *                and perform reset
+ * @dev: device to be reset by the controller
+ *
+ * Convenience wrapper for reset_control_get() and reset_control_reset().
+ * This is useful for the common case of devices with single, dedicated reset
+ * lines.
+ */
+int device_reset(struct device *dev)
+{
+	struct reset_control *rstc;
+	int ret;
+
+	rstc = reset_control_get(dev, NULL);
+	if (IS_ERR(rstc))
+		return PTR_ERR(rstc);
+
+	ret = reset_control_reset(rstc);
+
+	reset_control_put(rstc);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(device_reset);
diff --git a/drivers/reset/gpio-reset.c b/drivers/reset/gpio-reset.c
new file mode 100644
index 0000000..3e3c363
--- /dev/null
+++ b/drivers/reset/gpio-reset.c
@@ -0,0 +1,208 @@
+/*
+ * GPIO Reset Controller driver
+ *
+ * Copyright 2013 Philipp Zabel, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/delay.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/module.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/reset-controller.h>
+
+struct gpio_reset {
+	unsigned int gpio;
+	bool active_low;
+};
+
+struct gpio_reset_data {
+	struct reset_controller_dev rcdev;
+	/* these arrays contain a number of elements equal to rcdev.nr_resets */
+	struct gpio_reset *gpios;
+	u32 *delays_us;
+};
+
+static void __gpio_reset_set(struct reset_controller_dev *rcdev,
+		unsigned long gpio_idx, int asserted)
+{
+	struct gpio_reset_data *drvdata = container_of(rcdev,
+			struct gpio_reset_data, rcdev);
+	int value = asserted;
+
+	if (drvdata->gpios[gpio_idx].active_low)
+		value = !value;
+
+	gpio_set_value(drvdata->gpios[gpio_idx].gpio, value);
+}
+
+static int gpio_reset(struct reset_controller_dev *rcdev,
+		unsigned long gpio_idx)
+{
+	struct gpio_reset_data *drvdata = container_of(rcdev,
+			struct gpio_reset_data, rcdev);
+
+	if (gpio_idx >= rcdev->nr_resets)
+		return -EINVAL;
+
+	if (drvdata->delays_us == NULL)
+		return -ENOSYS;
+
+	__gpio_reset_set(rcdev, gpio_idx, 1);
+	udelay(drvdata->delays_us[gpio_idx]);
+	__gpio_reset_set(rcdev, gpio_idx, 0);
+
+	return 0;
+}
+
+static int gpio_reset_assert(struct reset_controller_dev *rcdev,
+		unsigned long gpio_idx)
+{
+	if (gpio_idx >= rcdev->nr_resets)
+		return -EINVAL;
+
+	__gpio_reset_set(rcdev, gpio_idx, 1);
+
+	return 0;
+}
+
+static int gpio_reset_deassert(struct reset_controller_dev *rcdev,
+		unsigned long gpio_idx)
+{
+	if (gpio_idx >= rcdev->nr_resets)
+		return -EINVAL;
+
+	__gpio_reset_set(rcdev, gpio_idx, 0);
+
+	return 0;
+}
+
+static struct reset_control_ops gpio_reset_ops = {
+	.reset = gpio_reset,
+	.assert = gpio_reset_assert,
+	.deassert = gpio_reset_deassert,
+};
+
+static int gpio_reset_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct gpio_reset_data *drvdata;
+	enum of_gpio_flags flags;
+	u32 *initially_in_reset;
+	int nr_gpios;
+	int ret;
+	int i;
+
+	drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL);
+	if (drvdata == NULL)
+		return -ENOMEM;
+
+	nr_gpios = of_gpio_named_count(np, "reset-gpios");
+	if (nr_gpios < 1)
+		return -EINVAL;
+
+	drvdata->gpios = devm_kzalloc(&pdev->dev, sizeof(struct gpio_reset) *
+			nr_gpios, GFP_KERNEL);
+	if (drvdata->gpios == NULL)
+		return -ENOMEM;
+
+	for (i = 0; i < nr_gpios; i++) {
+		drvdata->gpios[i].gpio = of_get_named_gpio_flags(np,
+				"reset-gpios", i, &flags);
+		if (drvdata->gpios[i].gpio == -EPROBE_DEFER)
+			return drvdata->gpios[i].gpio;
+		else if (drvdata->gpios[i].gpio < 0) {
+			dev_err(&pdev->dev, "invalid gpio for reset %d\n", i);
+			return drvdata->gpios[i].gpio;
+		}
+
+		drvdata->gpios[i].active_low = flags & OF_GPIO_ACTIVE_LOW;
+	}
+
+	if (of_find_property(np, "reset-delays", NULL)) {
+		drvdata->delays_us = devm_kzalloc(&pdev->dev, sizeof(u32) *
+				nr_gpios, GFP_KERNEL);
+		if (drvdata->delays_us == NULL)
+			return -ENOMEM;
+
+		ret = of_property_read_u32_array(np, "reset-delays",
+				drvdata->delays_us, nr_gpios);
+		if (ret < 0)
+			return ret;
+	}
+
+	initially_in_reset = devm_kzalloc(&pdev->dev, sizeof(u32) *
+			nr_gpios, GFP_KERNEL);
+	if (initially_in_reset == NULL)
+		return -ENOMEM;
+	if (of_find_property(np, "initially-in-reset", NULL)) {
+		ret = of_property_read_u32_array(np, "initially-in-reset",
+				initially_in_reset, nr_gpios);
+		if (ret < 0)
+			return ret;
+	}
+
+	for (i = 0; i < nr_gpios; i++) {
+		unsigned long gpio_flags = GPIOF_OUT_INIT_LOW;
+
+		if (drvdata->gpios[i].active_low ^ (!!initially_in_reset[i]))
+			gpio_flags = GPIOF_OUT_INIT_HIGH;
+
+		ret = devm_gpio_request_one(&pdev->dev, drvdata->gpios[i].gpio,
+				gpio_flags, NULL);
+		if (ret < 0) {
+			dev_err(&pdev->dev, "failed to request gpio %d for reset %d\n",
+					drvdata->gpios[i].gpio, i);
+			return ret;
+		}
+	}
+
+	devm_kfree(&pdev->dev, initially_in_reset);
+
+	drvdata->rcdev.of_node = np;
+	drvdata->rcdev.owner = THIS_MODULE;
+	drvdata->rcdev.nr_resets = nr_gpios;
+	drvdata->rcdev.ops = &gpio_reset_ops;
+	reset_controller_register(&drvdata->rcdev);
+
+	platform_set_drvdata(pdev, drvdata);
+
+	return 0;
+}
+
+static int gpio_reset_remove(struct platform_device *pdev)
+{
+	struct gpio_reset_data *drvdata = platform_get_drvdata(pdev);
+
+	reset_controller_unregister(&drvdata->rcdev);
+
+	return 0;
+}
+
+static struct of_device_id gpio_reset_dt_ids[] = {
+	{ .compatible = "gpio-reset" },
+	{ }
+};
+
+static struct platform_driver gpio_reset_driver = {
+	.probe = gpio_reset_probe,
+	.remove = gpio_reset_remove,
+	.driver = {
+		.name = "gpio-reset",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(gpio_reset_dt_ids),
+	},
+};
+
+module_platform_driver(gpio_reset_driver);
+
+MODULE_AUTHOR("Philipp Zabel <p.zabel@pengutronix.de>");
+MODULE_DESCRIPTION("gpio reset controller");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:gpio-reset");
+MODULE_DEVICE_TABLE(of, gpio_reset_dt_ids);
diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index a59684b..56fceaf 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -757,14 +757,14 @@ int rpmsg_send_offchannel_raw(struct rpmsg_channel *rpdev, u32 src, u32 dst,
 	mutex_lock(&vrp->tx_lock);
 
 	/* add message to the remote processor's virtqueue */
-	err = virtqueue_add_buf(vrp->svq, &sg, 1, 0, msg, GFP_KERNEL);
+	err = virtqueue_add_outbuf(vrp->svq, &sg, 1, msg, GFP_KERNEL);
 	if (err) {
 		/*
 		 * need to reclaim the buffer here, otherwise it's lost
 		 * (memory won't leak, but rpmsg won't use it again for TX).
 		 * this will wait for a buffer management overhaul.
 		 */
-		dev_err(dev, "virtqueue_add_buf failed: %d\n", err);
+		dev_err(dev, "virtqueue_add_outbuf failed: %d\n", err);
 		goto out;
 	}
 
@@ -839,7 +839,7 @@ static void rpmsg_recv_done(struct virtqueue *rvq)
 	sg_init_one(&sg, msg, RPMSG_BUF_SIZE);
 
 	/* add the buffer back to the remote processor's virtqueue */
-	err = virtqueue_add_buf(vrp->rvq, &sg, 0, 1, msg, GFP_KERNEL);
+	err = virtqueue_add_inbuf(vrp->rvq, &sg, 1, msg, GFP_KERNEL);
 	if (err < 0) {
 		dev_err(dev, "failed to add a virtqueue buffer: %d\n", err);
 		return;
@@ -951,8 +951,10 @@ static int rpmsg_probe(struct virtio_device *vdev)
 	bufs_va = dma_alloc_coherent(vdev->dev.parent->parent,
 				RPMSG_TOTAL_BUF_SPACE,
 				&vrp->bufs_dma, GFP_KERNEL);
-	if (!bufs_va)
+	if (!bufs_va) {
+		err = -ENOMEM;
 		goto vqs_del;
+	}
 
 	dev_dbg(&vdev->dev, "buffers: va %p, dma 0x%llx\n", bufs_va,
 					(unsigned long long)vrp->bufs_dma);
@@ -970,7 +972,7 @@ static int rpmsg_probe(struct virtio_device *vdev)
 
 		sg_init_one(&sg, cpu_addr, RPMSG_BUF_SIZE);
 
-		err = virtqueue_add_buf(vrp->rvq, &sg, 0, 1, cpu_addr,
+		err = virtqueue_add_inbuf(vrp->rvq, &sg, 1, cpu_addr,
 								GFP_KERNEL);
 		WARN_ON(err); /* sanity check; this can't really happen */
 	}
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c
index 9b742d3..6638540 100644
--- a/drivers/rtc/class.c
+++ b/drivers/rtc/class.c
@@ -259,6 +259,76 @@ void rtc_device_unregister(struct rtc_device *rtc)
 }
 EXPORT_SYMBOL_GPL(rtc_device_unregister);
 
+static void devm_rtc_device_release(struct device *dev, void *res)
+{
+	struct rtc_device *rtc = *(struct rtc_device **)res;
+
+	rtc_device_unregister(rtc);
+}
+
+static int devm_rtc_device_match(struct device *dev, void *res, void *data)
+{
+	struct rtc **r = res;
+
+	return *r == data;
+}
+
+/**
+ * devm_rtc_device_register - resource managed rtc_device_register()
+ * @dev: the device to register
+ * @name: the name of the device
+ * @ops: the rtc operations structure
+ * @owner: the module owner
+ *
+ * @return a struct rtc on success, or an ERR_PTR on error
+ *
+ * Managed rtc_device_register(). The rtc_device returned from this function
+ * are automatically freed on driver detach. See rtc_device_register()
+ * for more information.
+ */
+
+struct rtc_device *devm_rtc_device_register(struct device *dev,
+					const char *name,
+					const struct rtc_class_ops *ops,
+					struct module *owner)
+{
+	struct rtc_device **ptr, *rtc;
+
+	ptr = devres_alloc(devm_rtc_device_release, sizeof(*ptr), GFP_KERNEL);
+	if (!ptr)
+		return ERR_PTR(-ENOMEM);
+
+	rtc = rtc_device_register(name, dev, ops, owner);
+	if (!IS_ERR(rtc)) {
+		*ptr = rtc;
+		devres_add(dev, ptr);
+	} else {
+		devres_free(ptr);
+	}
+
+	return rtc;
+}
+EXPORT_SYMBOL_GPL(devm_rtc_device_register);
+
+/**
+ * devm_rtc_device_unregister - resource managed devm_rtc_device_unregister()
+ * @dev: the device to unregister
+ * @rtc: the RTC class device to unregister
+ *
+ * Deallocated a rtc allocated with devm_rtc_device_register(). Normally this
+ * function will not need to be called and the resource management code will
+ * ensure that the resource is freed.
+ */
+void devm_rtc_device_unregister(struct device *dev, struct rtc_device *rtc)
+{
+	int rc;
+
+	rc = devres_release(dev, devm_rtc_device_release,
+				devm_rtc_device_match, rtc);
+	WARN_ON(rc);
+}
+EXPORT_SYMBOL_GPL(devm_rtc_device_unregister);
+
 static int __init rtc_init(void)
 {
 	rtc_class = class_create(THIS_MODULE, "rtc");
diff --git a/drivers/rtc/rtc-88pm80x.c b/drivers/rtc/rtc-88pm80x.c
index 63b17eb..f3742f3 100644
--- a/drivers/rtc/rtc-88pm80x.c
+++ b/drivers/rtc/rtc-88pm80x.c
@@ -234,7 +234,7 @@ static const struct rtc_class_ops pm80x_rtc_ops = {
 	.alarm_irq_enable = pm80x_rtc_alarm_irq_enable,
 };
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int pm80x_rtc_suspend(struct device *dev)
 {
 	return pm80x_dev_suspend(dev);
@@ -312,7 +312,7 @@ static int pm80x_rtc_probe(struct platform_device *pdev)
 	}
 	rtc_tm_to_time(&tm, &ticks);
 
-	info->rtc_dev = rtc_device_register("88pm80x-rtc", &pdev->dev,
+	info->rtc_dev = devm_rtc_device_register(&pdev->dev, "88pm80x-rtc",
 					    &pm80x_rtc_ops, THIS_MODULE);
 	if (IS_ERR(info->rtc_dev)) {
 		ret = PTR_ERR(info->rtc_dev);
@@ -346,7 +346,6 @@ static int pm80x_rtc_remove(struct platform_device *pdev)
 {
 	struct pm80x_rtc_info *info = platform_get_drvdata(pdev);
 	platform_set_drvdata(pdev, NULL);
-	rtc_device_unregister(info->rtc_dev);
 	pm80x_free_irq(info->chip, info->irq, info);
 	return 0;
 }
diff --git a/drivers/rtc/rtc-ab3100.c b/drivers/rtc/rtc-ab3100.c
index 261a07e..47a4f2c 100644
--- a/drivers/rtc/rtc-ab3100.c
+++ b/drivers/rtc/rtc-ab3100.c
@@ -229,8 +229,8 @@ static int __init ab3100_rtc_probe(struct platform_device *pdev)
 		/* Ignore any error on this write */
 	}
 
-	rtc = rtc_device_register("ab3100-rtc", &pdev->dev, &ab3100_rtc_ops,
-				  THIS_MODULE);
+	rtc = devm_rtc_device_register(&pdev->dev, "ab3100-rtc",
+					&ab3100_rtc_ops, THIS_MODULE);
 	if (IS_ERR(rtc)) {
 		err = PTR_ERR(rtc);
 		return err;
@@ -242,9 +242,6 @@ static int __init ab3100_rtc_probe(struct platform_device *pdev)
 
 static int __exit ab3100_rtc_remove(struct platform_device *pdev)
 {
-	struct rtc_device *rtc = platform_get_drvdata(pdev);
-
-	rtc_device_unregister(rtc);
 	platform_set_drvdata(pdev, NULL);
 	return 0;
 }
@@ -257,19 +254,7 @@ static struct platform_driver ab3100_rtc_driver = {
 	.remove	 = __exit_p(ab3100_rtc_remove),
 };
 
-static int __init ab3100_rtc_init(void)
-{
-	return platform_driver_probe(&ab3100_rtc_driver,
-				     ab3100_rtc_probe);
-}
-
-static void __exit ab3100_rtc_exit(void)
-{
-	platform_driver_unregister(&ab3100_rtc_driver);
-}
-
-module_init(ab3100_rtc_init);
-module_exit(ab3100_rtc_exit);
+module_platform_driver_probe(ab3100_rtc_driver, ab3100_rtc_probe);
 
 MODULE_AUTHOR("Linus Walleij <linus.walleij@stericsson.com>");
 MODULE_DESCRIPTION("AB3100 RTC Driver");
diff --git a/drivers/rtc/rtc-at32ap700x.c b/drivers/rtc/rtc-at32ap700x.c
index 8dd0830..619c887 100644
--- a/drivers/rtc/rtc-at32ap700x.c
+++ b/drivers/rtc/rtc-at32ap700x.c
@@ -302,17 +302,7 @@ static struct platform_driver at32_rtc_driver = {
 	},
 };
 
-static int __init at32_rtc_init(void)
-{
-	return platform_driver_probe(&at32_rtc_driver, at32_rtc_probe);
-}
-module_init(at32_rtc_init);
-
-static void __exit at32_rtc_exit(void)
-{
-	platform_driver_unregister(&at32_rtc_driver);
-}
-module_exit(at32_rtc_exit);
+module_platform_driver_probe(at32_rtc_driver, at32_rtc_probe);
 
 MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>");
 MODULE_DESCRIPTION("Real time clock for AVR32 AT32AP700x");
diff --git a/drivers/rtc/rtc-at91rm9200.c b/drivers/rtc/rtc-at91rm9200.c
index 0a9f27e..c8c1532 100644
--- a/drivers/rtc/rtc-at91rm9200.c
+++ b/drivers/rtc/rtc-at91rm9200.c
@@ -345,7 +345,7 @@ static int __exit at91_rtc_remove(struct platform_device *pdev)
 	return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 
 /* AT91RM9200 RTC Power management control */
 
@@ -381,39 +381,20 @@ static int at91_rtc_resume(struct device *dev)
 	}
 	return 0;
 }
-
-static const struct dev_pm_ops at91_rtc_pm = {
-	.suspend =	at91_rtc_suspend,
-	.resume =	at91_rtc_resume,
-};
-
-#define at91_rtc_pm_ptr	&at91_rtc_pm
-
-#else
-#define at91_rtc_pm_ptr	NULL
 #endif
 
+static SIMPLE_DEV_PM_OPS(at91_rtc_pm_ops, at91_rtc_suspend, at91_rtc_resume);
+
 static struct platform_driver at91_rtc_driver = {
 	.remove		= __exit_p(at91_rtc_remove),
 	.driver		= {
 		.name	= "at91_rtc",
 		.owner	= THIS_MODULE,
-		.pm	= at91_rtc_pm_ptr,
+		.pm	= &at91_rtc_pm_ops,
 	},
 };
 
-static int __init at91_rtc_init(void)
-{
-	return platform_driver_probe(&at91_rtc_driver, at91_rtc_probe);
-}
-
-static void __exit at91_rtc_exit(void)
-{
-	platform_driver_unregister(&at91_rtc_driver);
-}
-
-module_init(at91_rtc_init);
-module_exit(at91_rtc_exit);
+module_platform_driver_probe(at91_rtc_driver, at91_rtc_probe);
 
 MODULE_AUTHOR("Rick Bronson");
 MODULE_DESCRIPTION("RTC driver for Atmel AT91RM9200");
diff --git a/drivers/rtc/rtc-au1xxx.c b/drivers/rtc/rtc-au1xxx.c
index b309da4..7995abc 100644
--- a/drivers/rtc/rtc-au1xxx.c
+++ b/drivers/rtc/rtc-au1xxx.c
@@ -101,7 +101,7 @@ static int au1xtoy_rtc_probe(struct platform_device *pdev)
 	while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S)
 		msleep(1);
 
-	rtcdev = rtc_device_register("rtc-au1xxx", &pdev->dev,
+	rtcdev = devm_rtc_device_register(&pdev->dev, "rtc-au1xxx",
 				     &au1xtoy_rtc_ops, THIS_MODULE);
 	if (IS_ERR(rtcdev)) {
 		ret = PTR_ERR(rtcdev);
@@ -118,9 +118,6 @@ out_err:
 
 static int au1xtoy_rtc_remove(struct platform_device *pdev)
 {
-	struct rtc_device *rtcdev = platform_get_drvdata(pdev);
-
-	rtc_device_unregister(rtcdev);
 	platform_set_drvdata(pdev, NULL);
 
 	return 0;
@@ -134,18 +131,7 @@ static struct platform_driver au1xrtc_driver = {
 	.remove		= au1xtoy_rtc_remove,
 };
 
-static int __init au1xtoy_rtc_init(void)
-{
-	return platform_driver_probe(&au1xrtc_driver, au1xtoy_rtc_probe);
-}
-
-static void __exit au1xtoy_rtc_exit(void)
-{
-	platform_driver_unregister(&au1xrtc_driver);
-}
-
-module_init(au1xtoy_rtc_init);
-module_exit(au1xtoy_rtc_exit);
+module_platform_driver_probe(au1xrtc_driver, au1xtoy_rtc_probe);
 
 MODULE_DESCRIPTION("Au1xxx TOY-counter-based RTC driver");
 MODULE_AUTHOR("Manuel Lauss <manuel.lauss@gmail.com>");
diff --git a/drivers/rtc/rtc-bq32k.c b/drivers/rtc/rtc-bq32k.c
index 036cb89..fea78bc 100644
--- a/drivers/rtc/rtc-bq32k.c
+++ b/drivers/rtc/rtc-bq32k.c
@@ -153,7 +153,7 @@ static int bq32k_probe(struct i2c_client *client,
 	if (error)
 		return error;
 
-	rtc = rtc_device_register(bq32k_driver.driver.name, &client->dev,
+	rtc = devm_rtc_device_register(&client->dev, bq32k_driver.driver.name,
 						&bq32k_rtc_ops, THIS_MODULE);
 	if (IS_ERR(rtc))
 		return PTR_ERR(rtc);
@@ -165,9 +165,6 @@ static int bq32k_probe(struct i2c_client *client,
 
 static int bq32k_remove(struct i2c_client *client)
 {
-	struct rtc_device *rtc = i2c_get_clientdata(client);
-
-	rtc_device_unregister(rtc);
 	return 0;
 }
 
diff --git a/drivers/rtc/rtc-coh901331.c b/drivers/rtc/rtc-coh901331.c
index 2d28ec1..bf0387f 100644
--- a/drivers/rtc/rtc-coh901331.c
+++ b/drivers/rtc/rtc-coh901331.c
@@ -155,7 +155,6 @@ static int __exit coh901331_remove(struct platform_device *pdev)
 	struct coh901331_port *rtap = dev_get_drvdata(&pdev->dev);
 
 	if (rtap) {
-		rtc_device_unregister(rtap->rtc);
 		clk_unprepare(rtap->clk);
 		platform_set_drvdata(pdev, NULL);
 	}
@@ -211,8 +210,8 @@ static int __init coh901331_probe(struct platform_device *pdev)
 	clk_disable(rtap->clk);
 
 	platform_set_drvdata(pdev, rtap);
-	rtap->rtc = rtc_device_register("coh901331", &pdev->dev, &coh901331_ops,
-					 THIS_MODULE);
+	rtap->rtc = devm_rtc_device_register(&pdev->dev, "coh901331",
+					&coh901331_ops, THIS_MODULE);
 	if (IS_ERR(rtap->rtc)) {
 		ret = PTR_ERR(rtap->rtc);
 		goto out_no_rtc;
@@ -287,18 +286,7 @@ static struct platform_driver coh901331_driver = {
 	.shutdown = coh901331_shutdown,
 };
 
-static int __init coh901331_init(void)
-{
-	return platform_driver_probe(&coh901331_driver, coh901331_probe);
-}
-
-static void __exit coh901331_exit(void)
-{
-	platform_driver_unregister(&coh901331_driver);
-}
-
-module_init(coh901331_init);
-module_exit(coh901331_exit);
+module_platform_driver_probe(coh901331_driver, coh901331_probe);
 
 MODULE_AUTHOR("Linus Walleij <linus.walleij@stericsson.com>");
 MODULE_DESCRIPTION("ST-Ericsson AB COH 901 331 RTC Driver");
diff --git a/drivers/rtc/rtc-da9052.c b/drivers/rtc/rtc-da9052.c
index 969abba..7286b27 100644
--- a/drivers/rtc/rtc-da9052.c
+++ b/drivers/rtc/rtc-da9052.c
@@ -247,7 +247,7 @@ static int da9052_rtc_probe(struct platform_device *pdev)
 		return ret;
 	}
 
-	rtc->rtc = rtc_device_register(pdev->name, &pdev->dev,
+	rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
 				       &da9052_rtc_ops, THIS_MODULE);
 	if (IS_ERR(rtc->rtc))
 		return PTR_ERR(rtc->rtc);
@@ -257,9 +257,6 @@ static int da9052_rtc_probe(struct platform_device *pdev)
 
 static int da9052_rtc_remove(struct platform_device *pdev)
 {
-	struct da9052_rtc *rtc = pdev->dev.platform_data;
-
-	rtc_device_unregister(rtc->rtc);
 	platform_set_drvdata(pdev, NULL);
 
 	return 0;
diff --git a/drivers/rtc/rtc-da9055.c b/drivers/rtc/rtc-da9055.c
index 8f0dcfe..73858ca 100644
--- a/drivers/rtc/rtc-da9055.c
+++ b/drivers/rtc/rtc-da9055.c
@@ -294,7 +294,7 @@ static int da9055_rtc_probe(struct platform_device *pdev)
 
 	device_init_wakeup(&pdev->dev, 1);
 
-	rtc->rtc = rtc_device_register(pdev->name, &pdev->dev,
+	rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
 					&da9055_rtc_ops, THIS_MODULE);
 	if (IS_ERR(rtc->rtc)) {
 		ret = PTR_ERR(rtc->rtc);
@@ -317,9 +317,6 @@ err_rtc:
 
 static int da9055_rtc_remove(struct platform_device *pdev)
 {
-	struct da9055_rtc *rtc = pdev->dev.platform_data;
-
-	rtc_device_unregister(rtc->rtc);
 	platform_set_drvdata(pdev, NULL);
 
 	return 0;
diff --git a/drivers/rtc/rtc-davinci.c b/drivers/rtc/rtc-davinci.c
index 56b7308..a55048c 100644
--- a/drivers/rtc/rtc-davinci.c
+++ b/drivers/rtc/rtc-davinci.c
@@ -523,7 +523,7 @@ static int __init davinci_rtc_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, davinci_rtc);
 
-	davinci_rtc->rtc = rtc_device_register(pdev->name, &pdev->dev,
+	davinci_rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
 				    &davinci_rtc_ops, THIS_MODULE);
 	if (IS_ERR(davinci_rtc->rtc)) {
 		ret = PTR_ERR(davinci_rtc->rtc);
@@ -543,7 +543,7 @@ static int __init davinci_rtc_probe(struct platform_device *pdev)
 			  0, "davinci_rtc", davinci_rtc);
 	if (ret < 0) {
 		dev_err(dev, "unable to register davinci RTC interrupt\n");
-		goto fail2;
+		goto fail1;
 	}
 
 	/* Enable interrupts */
@@ -557,14 +557,12 @@ static int __init davinci_rtc_probe(struct platform_device *pdev)
 
 	return 0;
 
-fail2:
-	rtc_device_unregister(davinci_rtc->rtc);
 fail1:
 	platform_set_drvdata(pdev, NULL);
 	return ret;
 }
 
-static int davinci_rtc_remove(struct platform_device *pdev)
+static int __exit davinci_rtc_remove(struct platform_device *pdev)
 {
 	struct davinci_rtc *davinci_rtc = platform_get_drvdata(pdev);
 
@@ -572,8 +570,6 @@ static int davinci_rtc_remove(struct platform_device *pdev)
 
 	rtcif_write(davinci_rtc, 0, PRTCIF_INTEN);
 
-	rtc_device_unregister(davinci_rtc->rtc);
-
 	platform_set_drvdata(pdev, NULL);
 
 	return 0;
@@ -581,24 +577,14 @@ static int davinci_rtc_remove(struct platform_device *pdev)
 
 static struct platform_driver davinci_rtc_driver = {
 	.probe		= davinci_rtc_probe,
-	.remove		= davinci_rtc_remove,
+	.remove		= __exit_p(davinci_rtc_remove),
 	.driver		= {
 		.name = "rtc_davinci",
 		.owner = THIS_MODULE,
 	},
 };
 
-static int __init rtc_init(void)
-{
-	return platform_driver_probe(&davinci_rtc_driver, davinci_rtc_probe);
-}
-module_init(rtc_init);
-
-static void __exit rtc_exit(void)
-{
-	platform_driver_unregister(&davinci_rtc_driver);
-}
-module_exit(rtc_exit);
+module_platform_driver_probe(davinci_rtc_driver, davinci_rtc_probe);
 
 MODULE_AUTHOR("Miguel Aguilar <miguel.aguilar@ridgerun.com>");
 MODULE_DESCRIPTION("Texas Instruments DaVinci PRTC Driver");
diff --git a/drivers/rtc/rtc-dm355evm.c b/drivers/rtc/rtc-dm355evm.c
index b2ed2c9..1e1ca63 100644
--- a/drivers/rtc/rtc-dm355evm.c
+++ b/drivers/rtc/rtc-dm355evm.c
@@ -127,8 +127,8 @@ static int dm355evm_rtc_probe(struct platform_device *pdev)
 {
 	struct rtc_device *rtc;
 
-	rtc = rtc_device_register(pdev->name,
-				  &pdev->dev, &dm355evm_rtc_ops, THIS_MODULE);
+	rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
+					&dm355evm_rtc_ops, THIS_MODULE);
 	if (IS_ERR(rtc)) {
 		dev_err(&pdev->dev, "can't register RTC device, err %ld\n",
 			PTR_ERR(rtc));
@@ -141,9 +141,6 @@ static int dm355evm_rtc_probe(struct platform_device *pdev)
 
 static int dm355evm_rtc_remove(struct platform_device *pdev)
 {
-	struct rtc_device *rtc = platform_get_drvdata(pdev);
-
-	rtc_device_unregister(rtc);
 	platform_set_drvdata(pdev, NULL);
 	return 0;
 }
diff --git a/drivers/rtc/rtc-ds1286.c b/drivers/rtc/rtc-ds1286.c
index d989412..d120cb8 100644
--- a/drivers/rtc/rtc-ds1286.c
+++ b/drivers/rtc/rtc-ds1286.c
@@ -270,7 +270,6 @@ static int ds1286_set_time(struct device *dev, struct rtc_time *tm)
 static int ds1286_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
 {
 	struct ds1286_priv *priv = dev_get_drvdata(dev);
-	unsigned char cmd;
 	unsigned long flags;
 
 	/*
@@ -281,7 +280,7 @@ static int ds1286_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
 	alm->time.tm_min = ds1286_rtc_read(priv, RTC_MINUTES_ALARM) & 0x7f;
 	alm->time.tm_hour = ds1286_rtc_read(priv, RTC_HOURS_ALARM)  & 0x1f;
 	alm->time.tm_wday = ds1286_rtc_read(priv, RTC_DAY_ALARM)    & 0x07;
-	cmd = ds1286_rtc_read(priv, RTC_CMD);
+	ds1286_rtc_read(priv, RTC_CMD);
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	alm->time.tm_min = bcd2bin(alm->time.tm_min);
diff --git a/drivers/rtc/rtc-ds1302.c b/drivers/rtc/rtc-ds1302.c
index fdbcdb2..d139543 100644
--- a/drivers/rtc/rtc-ds1302.c
+++ b/drivers/rtc/rtc-ds1302.c
@@ -224,7 +224,7 @@ static int __init ds1302_rtc_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
-	rtc = rtc_device_register("ds1302", &pdev->dev,
+	rtc = devm_rtc_device_register(&pdev->dev, "ds1302",
 					   &ds1302_rtc_ops, THIS_MODULE);
 	if (IS_ERR(rtc))
 		return PTR_ERR(rtc);
@@ -234,11 +234,8 @@ static int __init ds1302_rtc_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int ds1302_rtc_remove(struct platform_device *pdev)
+static int __exit ds1302_rtc_remove(struct platform_device *pdev)
 {
-	struct rtc_device *rtc = platform_get_drvdata(pdev);
-
-	rtc_device_unregister(rtc);
 	platform_set_drvdata(pdev, NULL);
 
 	return 0;
@@ -249,21 +246,10 @@ static struct platform_driver ds1302_platform_driver = {
 		.name	= DRV_NAME,
 		.owner	= THIS_MODULE,
 	},
-	.remove		= ds1302_rtc_remove,
+	.remove		= __exit_p(ds1302_rtc_remove),
 };
 
-static int __init ds1302_rtc_init(void)
-{
-	return platform_driver_probe(&ds1302_platform_driver, ds1302_rtc_probe);
-}
-
-static void __exit ds1302_rtc_exit(void)
-{
-	platform_driver_unregister(&ds1302_platform_driver);
-}
-
-module_init(ds1302_rtc_init);
-module_exit(ds1302_rtc_exit);
+module_platform_driver_probe(ds1302_platform_driver, ds1302_rtc_probe);
 
 MODULE_DESCRIPTION("Dallas DS1302 RTC driver");
 MODULE_VERSION(DRV_VERSION);
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index 970a236..b859d3c 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -4,6 +4,7 @@
  *  Copyright (C) 2005 James Chapman (ds1337 core)
  *  Copyright (C) 2006 David Brownell
  *  Copyright (C) 2009 Matthias Fuchs (rx8025 support)
+ *  Copyright (C) 2012 Bertrand Achard (nvram access fixes)
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -196,7 +197,7 @@ static s32 ds1307_read_block_data_once(const struct i2c_client *client,
 static s32 ds1307_read_block_data(const struct i2c_client *client, u8 command,
 				  u8 length, u8 *values)
 {
-	u8 oldvalues[I2C_SMBUS_BLOCK_MAX];
+	u8 oldvalues[255];
 	s32 ret;
 	int tries = 0;
 
@@ -222,7 +223,7 @@ static s32 ds1307_read_block_data(const struct i2c_client *client, u8 command,
 static s32 ds1307_write_block_data(const struct i2c_client *client, u8 command,
 				   u8 length, const u8 *values)
 {
-	u8 currvalues[I2C_SMBUS_BLOCK_MAX];
+	u8 currvalues[255];
 	int tries = 0;
 
 	dev_dbg(&client->dev, "ds1307_write_block_data (length=%d)\n", length);
@@ -250,6 +251,57 @@ static s32 ds1307_write_block_data(const struct i2c_client *client, u8 command,
 
 /*----------------------------------------------------------------------*/
 
+/* These RTC devices are not designed to be connected to a SMbus adapter.
+   SMbus limits block operations length to 32 bytes, whereas it's not
+   limited on I2C buses. As a result, accesses may exceed 32 bytes;
+   in that case, split them into smaller blocks */
+
+static s32 ds1307_native_smbus_write_block_data(const struct i2c_client *client,
+				u8 command, u8 length, const u8 *values)
+{
+	u8 suboffset = 0;
+
+	if (length <= I2C_SMBUS_BLOCK_MAX)
+		return i2c_smbus_write_i2c_block_data(client,
+					command, length, values);
+
+	while (suboffset < length) {
+		s32 retval = i2c_smbus_write_i2c_block_data(client,
+				command + suboffset,
+				min(I2C_SMBUS_BLOCK_MAX, length - suboffset),
+				values + suboffset);
+		if (retval < 0)
+			return retval;
+
+		suboffset += I2C_SMBUS_BLOCK_MAX;
+	}
+	return length;
+}
+
+static s32 ds1307_native_smbus_read_block_data(const struct i2c_client *client,
+				u8 command, u8 length, u8 *values)
+{
+	u8 suboffset = 0;
+
+	if (length <= I2C_SMBUS_BLOCK_MAX)
+		return i2c_smbus_read_i2c_block_data(client,
+					command, length, values);
+
+	while (suboffset < length) {
+		s32 retval = i2c_smbus_read_i2c_block_data(client,
+				command + suboffset,
+				min(I2C_SMBUS_BLOCK_MAX, length - suboffset),
+				values + suboffset);
+		if (retval < 0)
+			return retval;
+
+		suboffset += I2C_SMBUS_BLOCK_MAX;
+	}
+	return length;
+}
+
+/*----------------------------------------------------------------------*/
+
 /*
  * The IRQ logic includes a "real" handler running in IRQ context just
  * long enough to schedule this workqueue entry.   We need a task context
@@ -646,8 +698,8 @@ static int ds1307_probe(struct i2c_client *client,
 
 	buf = ds1307->regs;
 	if (i2c_check_functionality(adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) {
-		ds1307->read_block_data = i2c_smbus_read_i2c_block_data;
-		ds1307->write_block_data = i2c_smbus_write_i2c_block_data;
+		ds1307->read_block_data = ds1307_native_smbus_read_block_data;
+		ds1307->write_block_data = ds1307_native_smbus_write_block_data;
 	} else {
 		ds1307->read_block_data = ds1307_read_block_data;
 		ds1307->write_block_data = ds1307_write_block_data;
@@ -661,7 +713,7 @@ static int ds1307_probe(struct i2c_client *client,
 		tmp = ds1307->read_block_data(ds1307->client,
 				DS1337_REG_CONTROL, 2, buf);
 		if (tmp != 2) {
-			pr_debug("read error %d\n", tmp);
+			dev_dbg(&client->dev, "read error %d\n", tmp);
 			err = -EIO;
 			goto exit_free;
 		}
@@ -700,7 +752,7 @@ static int ds1307_probe(struct i2c_client *client,
 		tmp = i2c_smbus_read_i2c_block_data(ds1307->client,
 				RX8025_REG_CTRL1 << 4 | 0x08, 2, buf);
 		if (tmp != 2) {
-			pr_debug("read error %d\n", tmp);
+			dev_dbg(&client->dev, "read error %d\n", tmp);
 			err = -EIO;
 			goto exit_free;
 		}
@@ -744,7 +796,7 @@ static int ds1307_probe(struct i2c_client *client,
 			tmp = i2c_smbus_read_i2c_block_data(ds1307->client,
 					RX8025_REG_CTRL1 << 4 | 0x08, 2, buf);
 			if (tmp != 2) {
-				pr_debug("read error %d\n", tmp);
+				dev_dbg(&client->dev, "read error %d\n", tmp);
 				err = -EIO;
 				goto exit_free;
 			}
@@ -772,7 +824,7 @@ read_rtc:
 	/* read RTC registers */
 	tmp = ds1307->read_block_data(ds1307->client, ds1307->offset, 8, buf);
 	if (tmp != 8) {
-		pr_debug("read error %d\n", tmp);
+		dev_dbg(&client->dev, "read error %d\n", tmp);
 		err = -EIO;
 		goto exit_free;
 	}
@@ -814,7 +866,7 @@ read_rtc:
 
 		tmp = i2c_smbus_read_byte_data(client, DS1340_REG_FLAG);
 		if (tmp < 0) {
-			pr_debug("read error %d\n", tmp);
+			dev_dbg(&client->dev, "read error %d\n", tmp);
 			err = -EIO;
 			goto exit_free;
 		}
diff --git a/drivers/rtc/rtc-ds1374.c b/drivers/rtc/rtc-ds1374.c
index fef7686..67cd1e3 100644
--- a/drivers/rtc/rtc-ds1374.c
+++ b/drivers/rtc/rtc-ds1374.c
@@ -409,7 +409,7 @@ static int ds1374_remove(struct i2c_client *client)
 	return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int ds1374_suspend(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
@@ -427,19 +427,15 @@ static int ds1374_resume(struct device *dev)
 		disable_irq_wake(client->irq);
 	return 0;
 }
+#endif
 
 static SIMPLE_DEV_PM_OPS(ds1374_pm, ds1374_suspend, ds1374_resume);
 
-#define DS1374_PM (&ds1374_pm)
-#else
-#define DS1374_PM NULL
-#endif
-
 static struct i2c_driver ds1374_driver = {
 	.driver = {
 		.name = "rtc-ds1374",
 		.owner = THIS_MODULE,
-		.pm = DS1374_PM,
+		.pm = &ds1374_pm,
 	},
 	.probe = ds1374_probe,
 	.remove = ds1374_remove,
diff --git a/drivers/rtc/rtc-ds1511.c b/drivers/rtc/rtc-ds1511.c
index 6a3fcfe..6ce8a99 100644
--- a/drivers/rtc/rtc-ds1511.c
+++ b/drivers/rtc/rtc-ds1511.c
@@ -538,15 +538,14 @@ static int ds1511_rtc_probe(struct platform_device *pdev)
 		}
 	}
 
-	rtc = rtc_device_register(pdev->name, &pdev->dev, &ds1511_rtc_ops,
-		THIS_MODULE);
+	rtc = devm_rtc_device_register(&pdev->dev, pdev->name, &ds1511_rtc_ops,
+					THIS_MODULE);
 	if (IS_ERR(rtc))
 		return PTR_ERR(rtc);
 	pdata->rtc = rtc;
 
 	ret = sysfs_create_bin_file(&pdev->dev.kobj, &ds1511_nvram_attr);
-	if (ret)
-		rtc_device_unregister(pdata->rtc);
+
 	return ret;
 }
 
@@ -555,7 +554,6 @@ static int ds1511_rtc_remove(struct platform_device *pdev)
 	struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
 
 	sysfs_remove_bin_file(&pdev->dev.kobj, &ds1511_nvram_attr);
-	rtc_device_unregister(pdata->rtc);
 	if (pdata->irq > 0) {
 		/*
 		 * disable the alarm interrupt
diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c
index 25ce062..8c6c952 100644
--- a/drivers/rtc/rtc-ds1553.c
+++ b/drivers/rtc/rtc-ds1553.c
@@ -326,15 +326,14 @@ static int ds1553_rtc_probe(struct platform_device *pdev)
 		}
 	}
 
-	rtc = rtc_device_register(pdev->name, &pdev->dev,
+	rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
 				  &ds1553_rtc_ops, THIS_MODULE);
 	if (IS_ERR(rtc))
 		return PTR_ERR(rtc);
 	pdata->rtc = rtc;
 
 	ret = sysfs_create_bin_file(&pdev->dev.kobj, &ds1553_nvram_attr);
-	if (ret)
-		rtc_device_unregister(rtc);
+
 	return ret;
 }
 
@@ -343,7 +342,6 @@ static int ds1553_rtc_remove(struct platform_device *pdev)
 	struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
 
 	sysfs_remove_bin_file(&pdev->dev.kobj, &ds1553_nvram_attr);
-	rtc_device_unregister(pdata->rtc);
 	if (pdata->irq > 0)
 		writeb(0, pdata->ioaddr + RTC_INTERRUPTS);
 	return 0;
diff --git a/drivers/rtc/rtc-ds1672.c b/drivers/rtc/rtc-ds1672.c
index 45d65c0..3fc2a47 100644
--- a/drivers/rtc/rtc-ds1672.c
+++ b/drivers/rtc/rtc-ds1672.c
@@ -155,11 +155,6 @@ static const struct rtc_class_ops ds1672_rtc_ops = {
 
 static int ds1672_remove(struct i2c_client *client)
 {
-	struct rtc_device *rtc = i2c_get_clientdata(client);
-
-	if (rtc)
-		rtc_device_unregister(rtc);
-
 	return 0;
 }
 
@@ -177,7 +172,7 @@ static int ds1672_probe(struct i2c_client *client,
 
 	dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n");
 
-	rtc = rtc_device_register(ds1672_driver.driver.name, &client->dev,
+	rtc = devm_rtc_device_register(&client->dev, ds1672_driver.driver.name,
 				  &ds1672_rtc_ops, THIS_MODULE);
 
 	if (IS_ERR(rtc))
@@ -202,7 +197,6 @@ static int ds1672_probe(struct i2c_client *client,
 	return 0;
 
  exit_devreg:
-	rtc_device_unregister(rtc);
 	return err;
 }
 
diff --git a/drivers/rtc/rtc-ds1742.c b/drivers/rtc/rtc-ds1742.c
index 609c870..eccdc62 100644
--- a/drivers/rtc/rtc-ds1742.c
+++ b/drivers/rtc/rtc-ds1742.c
@@ -208,17 +208,14 @@ static int ds1742_rtc_probe(struct platform_device *pdev)
 
 	pdata->last_jiffies = jiffies;
 	platform_set_drvdata(pdev, pdata);
-	rtc = rtc_device_register(pdev->name, &pdev->dev,
+	rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
 				  &ds1742_rtc_ops, THIS_MODULE);
 	if (IS_ERR(rtc))
 		return PTR_ERR(rtc);
 	pdata->rtc = rtc;
 
 	ret = sysfs_create_bin_file(&pdev->dev.kobj, &pdata->nvram_attr);
-	if (ret) {
-		dev_err(&pdev->dev, "creating nvram file in sysfs failed\n");
-		rtc_device_unregister(rtc);
-	}
+
 	return ret;
 }
 
@@ -227,7 +224,6 @@ static int ds1742_rtc_remove(struct platform_device *pdev)
 	struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
 
 	sysfs_remove_bin_file(&pdev->dev.kobj, &pdata->nvram_attr);
-	rtc_device_unregister(pdata->rtc);
 	return 0;
 }
 
diff --git a/drivers/rtc/rtc-ds3234.c b/drivers/rtc/rtc-ds3234.c
index 7a4495e..a66efd4 100644
--- a/drivers/rtc/rtc-ds3234.c
+++ b/drivers/rtc/rtc-ds3234.c
@@ -146,8 +146,8 @@ static int ds3234_probe(struct spi_device *spi)
 	ds3234_get_reg(&spi->dev, DS3234_REG_CONT_STAT, &tmp);
 	dev_info(&spi->dev, "Ctrl/Stat Reg: 0x%02x\n", tmp);
 
-	rtc = rtc_device_register("ds3234",
-				&spi->dev, &ds3234_rtc_ops, THIS_MODULE);
+	rtc = devm_rtc_device_register(&spi->dev, "ds3234",
+				&ds3234_rtc_ops, THIS_MODULE);
 	if (IS_ERR(rtc))
 		return PTR_ERR(rtc);
 
@@ -158,9 +158,6 @@ static int ds3234_probe(struct spi_device *spi)
 
 static int ds3234_remove(struct spi_device *spi)
 {
-	struct rtc_device *rtc = spi_get_drvdata(spi);
-
-	rtc_device_unregister(rtc);
 	return 0;
 }
 
diff --git a/drivers/rtc/rtc-efi.c b/drivers/rtc/rtc-efi.c
index 1a0c37c..b3c8c0b 100644
--- a/drivers/rtc/rtc-efi.c
+++ b/drivers/rtc/rtc-efi.c
@@ -191,7 +191,7 @@ static int __init efi_rtc_probe(struct platform_device *dev)
 {
 	struct rtc_device *rtc;
 
-	rtc = rtc_device_register("rtc-efi", &dev->dev, &efi_rtc_ops,
+	rtc = devm_rtc_device_register(&dev->dev, "rtc-efi", &efi_rtc_ops,
 					THIS_MODULE);
 	if (IS_ERR(rtc))
 		return PTR_ERR(rtc);
@@ -203,10 +203,6 @@ static int __init efi_rtc_probe(struct platform_device *dev)
 
 static int __exit efi_rtc_remove(struct platform_device *dev)
 {
-	struct rtc_device *rtc = platform_get_drvdata(dev);
-
-	rtc_device_unregister(rtc);
-
 	return 0;
 }
 
@@ -218,18 +214,7 @@ static struct platform_driver efi_rtc_driver = {
 	.remove = __exit_p(efi_rtc_remove),
 };
 
-static int __init efi_rtc_init(void)
-{
-	return platform_driver_probe(&efi_rtc_driver, efi_rtc_probe);
-}
-
-static void __exit efi_rtc_exit(void)
-{
-	platform_driver_unregister(&efi_rtc_driver);
-}
-
-module_init(efi_rtc_init);
-module_exit(efi_rtc_exit);
+module_platform_driver_probe(efi_rtc_driver, efi_rtc_probe);
 
 MODULE_AUTHOR("dann frazier <dannf@hp.com>");
 MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-em3027.c b/drivers/rtc/rtc-em3027.c
index f6c24ce..3f9eb57 100644
--- a/drivers/rtc/rtc-em3027.c
+++ b/drivers/rtc/rtc-em3027.c
@@ -121,7 +121,7 @@ static int em3027_probe(struct i2c_client *client,
 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
 		return -ENODEV;
 
-	rtc = rtc_device_register(em3027_driver.driver.name, &client->dev,
+	rtc = devm_rtc_device_register(&client->dev, em3027_driver.driver.name,
 				  &em3027_rtc_ops, THIS_MODULE);
 	if (IS_ERR(rtc))
 		return PTR_ERR(rtc);
@@ -133,11 +133,6 @@ static int em3027_probe(struct i2c_client *client,
 
 static int em3027_remove(struct i2c_client *client)
 {
-	struct rtc_device *rtc = i2c_get_clientdata(client);
-
-	if (rtc)
-		rtc_device_unregister(rtc);
-
 	return 0;
 }
 
diff --git a/drivers/rtc/rtc-ep93xx.c b/drivers/rtc/rtc-ep93xx.c
index 1a4e5e4..5807b77 100644
--- a/drivers/rtc/rtc-ep93xx.c
+++ b/drivers/rtc/rtc-ep93xx.c
@@ -153,8 +153,8 @@ static int ep93xx_rtc_probe(struct platform_device *pdev)
 	pdev->dev.platform_data = ep93xx_rtc;
 	platform_set_drvdata(pdev, ep93xx_rtc);
 
-	ep93xx_rtc->rtc = rtc_device_register(pdev->name,
-				&pdev->dev, &ep93xx_rtc_ops, THIS_MODULE);
+	ep93xx_rtc->rtc = devm_rtc_device_register(&pdev->dev,
+				pdev->name, &ep93xx_rtc_ops, THIS_MODULE);
 	if (IS_ERR(ep93xx_rtc->rtc)) {
 		err = PTR_ERR(ep93xx_rtc->rtc);
 		goto exit;
@@ -162,12 +162,10 @@ static int ep93xx_rtc_probe(struct platform_device *pdev)
 
 	err = sysfs_create_group(&pdev->dev.kobj, &ep93xx_rtc_sysfs_files);
 	if (err)
-		goto fail;
+		goto exit;
 
 	return 0;
 
-fail:
-	rtc_device_unregister(ep93xx_rtc->rtc);
 exit:
 	platform_set_drvdata(pdev, NULL);
 	pdev->dev.platform_data = NULL;
@@ -176,11 +174,8 @@ exit:
 
 static int ep93xx_rtc_remove(struct platform_device *pdev)
 {
-	struct ep93xx_rtc *ep93xx_rtc = platform_get_drvdata(pdev);
-
 	sysfs_remove_group(&pdev->dev.kobj, &ep93xx_rtc_sysfs_files);
 	platform_set_drvdata(pdev, NULL);
-	rtc_device_unregister(ep93xx_rtc->rtc);
 	pdev->dev.platform_data = NULL;
 
 	return 0;
diff --git a/drivers/rtc/rtc-fm3130.c b/drivers/rtc/rtc-fm3130.c
index bff3cdc..4d4ad3f 100644
--- a/drivers/rtc/rtc-fm3130.c
+++ b/drivers/rtc/rtc-fm3130.c
@@ -395,7 +395,7 @@ static int fm3130_probe(struct i2c_client *client,
 
 	tmp = i2c_transfer(adapter, fm3130->msg, 4);
 	if (tmp != 4) {
-		pr_debug("read error %d\n", tmp);
+		dev_dbg(&client->dev, "read error %d\n", tmp);
 		err = -EIO;
 		goto exit_free;
 	}
diff --git a/drivers/rtc/rtc-generic.c b/drivers/rtc/rtc-generic.c
index 98322004..06279ce 100644
--- a/drivers/rtc/rtc-generic.c
+++ b/drivers/rtc/rtc-generic.c
@@ -38,8 +38,8 @@ static int __init generic_rtc_probe(struct platform_device *dev)
 {
 	struct rtc_device *rtc;
 
-	rtc = rtc_device_register("rtc-generic", &dev->dev, &generic_rtc_ops,
-				  THIS_MODULE);
+	rtc = devm_rtc_device_register(&dev->dev, "rtc-generic",
+					&generic_rtc_ops, THIS_MODULE);
 	if (IS_ERR(rtc))
 		return PTR_ERR(rtc);
 
@@ -50,10 +50,6 @@ static int __init generic_rtc_probe(struct platform_device *dev)
 
 static int __exit generic_rtc_remove(struct platform_device *dev)
 {
-	struct rtc_device *rtc = platform_get_drvdata(dev);
-
-	rtc_device_unregister(rtc);
-
 	return 0;
 }
 
@@ -65,18 +61,7 @@ static struct platform_driver generic_rtc_driver = {
 	.remove = __exit_p(generic_rtc_remove),
 };
 
-static int __init generic_rtc_init(void)
-{
-	return platform_driver_probe(&generic_rtc_driver, generic_rtc_probe);
-}
-
-static void __exit generic_rtc_fini(void)
-{
-	platform_driver_unregister(&generic_rtc_driver);
-}
-
-module_init(generic_rtc_init);
-module_exit(generic_rtc_fini);
+module_platform_driver_probe(generic_rtc_driver, generic_rtc_probe);
 
 MODULE_AUTHOR("Kyle McMartin <kyle@mcmartin.ca>");
 MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-hid-sensor-time.c b/drivers/rtc/rtc-hid-sensor-time.c
index 31c5728..6302450 100644
--- a/drivers/rtc/rtc-hid-sensor-time.c
+++ b/drivers/rtc/rtc-hid-sensor-time.c
@@ -255,8 +255,9 @@ static int hid_time_probe(struct platform_device *pdev)
 		return ret;
 	}
 
-	time_state->rtc = rtc_device_register("hid-sensor-time",
-				&pdev->dev, &hid_time_rtc_ops, THIS_MODULE);
+	time_state->rtc = devm_rtc_device_register(&pdev->dev,
+					"hid-sensor-time", &hid_time_rtc_ops,
+					THIS_MODULE);
 
 	if (IS_ERR(time_state->rtc)) {
 		dev_err(&pdev->dev, "rtc device register failed!\n");
@@ -269,9 +270,7 @@ static int hid_time_probe(struct platform_device *pdev)
 static int hid_time_remove(struct platform_device *pdev)
 {
 	struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
-	struct hid_time_state *time_state = platform_get_drvdata(pdev);
 
-	rtc_device_unregister(time_state->rtc);
 	sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_TIME);
 
 	return 0;
diff --git a/drivers/rtc/rtc-imxdi.c b/drivers/rtc/rtc-imxdi.c
index 82aad69..d3a8c8e 100644
--- a/drivers/rtc/rtc-imxdi.c
+++ b/drivers/rtc/rtc-imxdi.c
@@ -369,7 +369,7 @@ static void dryice_work(struct work_struct *work)
 /*
  * probe for dryice rtc device
  */
-static int dryice_rtc_probe(struct platform_device *pdev)
+static int __init dryice_rtc_probe(struct platform_device *pdev)
 {
 	struct resource *res;
 	struct imxdi_dev *imxdi;
@@ -464,7 +464,7 @@ static int dryice_rtc_probe(struct platform_device *pdev)
 	}
 
 	platform_set_drvdata(pdev, imxdi);
-	imxdi->rtc = rtc_device_register(pdev->name, &pdev->dev,
+	imxdi->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
 				  &dryice_rtc_ops, THIS_MODULE);
 	if (IS_ERR(imxdi->rtc)) {
 		rc = PTR_ERR(imxdi->rtc);
@@ -479,7 +479,7 @@ err:
 	return rc;
 }
 
-static int dryice_rtc_remove(struct platform_device *pdev)
+static int __exit dryice_rtc_remove(struct platform_device *pdev)
 {
 	struct imxdi_dev *imxdi = platform_get_drvdata(pdev);
 
@@ -488,8 +488,6 @@ static int dryice_rtc_remove(struct platform_device *pdev)
 	/* mask all interrupts */
 	__raw_writel(0, imxdi->ioaddr + DIER);
 
-	rtc_device_unregister(imxdi->rtc);
-
 	clk_disable_unprepare(imxdi->clk);
 
 	return 0;
@@ -510,21 +508,10 @@ static struct platform_driver dryice_rtc_driver = {
 		   .owner = THIS_MODULE,
 		   .of_match_table = of_match_ptr(dryice_dt_ids),
 		   },
-	.remove = dryice_rtc_remove,
+	.remove = __exit_p(dryice_rtc_remove),
 };
 
-static int __init dryice_rtc_init(void)
-{
-	return platform_driver_probe(&dryice_rtc_driver, dryice_rtc_probe);
-}
-
-static void __exit dryice_rtc_exit(void)
-{
-	platform_driver_unregister(&dryice_rtc_driver);
-}
-
-module_init(dryice_rtc_init);
-module_exit(dryice_rtc_exit);
+module_platform_driver_probe(dryice_rtc_driver, dryice_rtc_probe);
 
 MODULE_AUTHOR("Freescale Semiconductor, Inc.");
 MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>");
diff --git a/drivers/rtc/rtc-lp8788.c b/drivers/rtc/rtc-lp8788.c
index 9a46312..9853ac1 100644
--- a/drivers/rtc/rtc-lp8788.c
+++ b/drivers/rtc/rtc-lp8788.c
@@ -299,7 +299,7 @@ static int lp8788_rtc_probe(struct platform_device *pdev)
 
 	device_init_wakeup(dev, 1);
 
-	rtc->rdev = rtc_device_register("lp8788_rtc", dev,
+	rtc->rdev = devm_rtc_device_register(dev, "lp8788_rtc",
 					&lp8788_rtc_ops, THIS_MODULE);
 	if (IS_ERR(rtc->rdev)) {
 		dev_err(dev, "can not register rtc device\n");
@@ -314,9 +314,6 @@ static int lp8788_rtc_probe(struct platform_device *pdev)
 
 static int lp8788_rtc_remove(struct platform_device *pdev)
 {
-	struct lp8788_rtc *rtc = platform_get_drvdata(pdev);
-
-	rtc_device_unregister(rtc->rdev);
 	platform_set_drvdata(pdev, NULL);
 
 	return 0;
diff --git a/drivers/rtc/rtc-lpc32xx.c b/drivers/rtc/rtc-lpc32xx.c
index 40a5983..787550d 100644
--- a/drivers/rtc/rtc-lpc32xx.c
+++ b/drivers/rtc/rtc-lpc32xx.c
@@ -273,8 +273,8 @@ static int lpc32xx_rtc_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, rtc);
 
-	rtc->rtc = rtc_device_register(RTC_NAME, &pdev->dev, &lpc32xx_rtc_ops,
-		THIS_MODULE);
+	rtc->rtc = devm_rtc_device_register(&pdev->dev, RTC_NAME,
+					&lpc32xx_rtc_ops, THIS_MODULE);
 	if (IS_ERR(rtc->rtc)) {
 		dev_err(&pdev->dev, "Can't get RTC\n");
 		platform_set_drvdata(pdev, NULL);
@@ -307,7 +307,6 @@ static int lpc32xx_rtc_remove(struct platform_device *pdev)
 		device_init_wakeup(&pdev->dev, 0);
 
 	platform_set_drvdata(pdev, NULL);
-	rtc_device_unregister(rtc->rtc);
 
 	return 0;
 }
diff --git a/drivers/rtc/rtc-ls1x.c b/drivers/rtc/rtc-ls1x.c
index f59b634..db82f91 100644
--- a/drivers/rtc/rtc-ls1x.c
+++ b/drivers/rtc/rtc-ls1x.c
@@ -172,7 +172,7 @@ static int ls1x_rtc_probe(struct platform_device *pdev)
 	while (readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_TTS)
 		usleep_range(1000, 3000);
 
-	rtcdev = rtc_device_register("ls1x-rtc", &pdev->dev,
+	rtcdev = devm_rtc_device_register(&pdev->dev, "ls1x-rtc",
 					&ls1x_rtc_ops , THIS_MODULE);
 	if (IS_ERR(rtcdev)) {
 		ret = PTR_ERR(rtcdev);
@@ -187,9 +187,6 @@ err:
 
 static int ls1x_rtc_remove(struct platform_device *pdev)
 {
-	struct rtc_device *rtcdev = platform_get_drvdata(pdev);
-
-	rtc_device_unregister(rtcdev);
 	platform_set_drvdata(pdev, NULL);
 
 	return 0;
diff --git a/drivers/rtc/rtc-m41t93.c b/drivers/rtc/rtc-m41t93.c
index 4916968..cfc21a1 100644
--- a/drivers/rtc/rtc-m41t93.c
+++ b/drivers/rtc/rtc-m41t93.c
@@ -184,8 +184,8 @@ static int m41t93_probe(struct spi_device *spi)
 		return -ENODEV;
 	}
 
-	rtc = rtc_device_register(m41t93_driver.driver.name,
-		&spi->dev, &m41t93_rtc_ops, THIS_MODULE);
+	rtc = devm_rtc_device_register(&spi->dev, m41t93_driver.driver.name,
+					&m41t93_rtc_ops, THIS_MODULE);
 	if (IS_ERR(rtc))
 		return PTR_ERR(rtc);
 
@@ -197,11 +197,6 @@ static int m41t93_probe(struct spi_device *spi)
 
 static int m41t93_remove(struct spi_device *spi)
 {
-	struct rtc_device *rtc = spi_get_drvdata(spi);
-
-	if (rtc)
-		rtc_device_unregister(rtc);
-
 	return 0;
 }
 
diff --git a/drivers/rtc/rtc-m41t94.c b/drivers/rtc/rtc-m41t94.c
index 89266c6..cf655a9 100644
--- a/drivers/rtc/rtc-m41t94.c
+++ b/drivers/rtc/rtc-m41t94.c
@@ -124,8 +124,8 @@ static int m41t94_probe(struct spi_device *spi)
 		return res;
 	}
 
-	rtc = rtc_device_register(m41t94_driver.driver.name,
-		&spi->dev, &m41t94_rtc_ops, THIS_MODULE);
+	rtc = devm_rtc_device_register(&spi->dev, m41t94_driver.driver.name,
+					&m41t94_rtc_ops, THIS_MODULE);
 	if (IS_ERR(rtc))
 		return PTR_ERR(rtc);
 
@@ -136,11 +136,6 @@ static int m41t94_probe(struct spi_device *spi)
 
 static int m41t94_remove(struct spi_device *spi)
 {
-	struct rtc_device *rtc = spi_get_drvdata(spi);
-
-	if (rtc)
-		rtc_device_unregister(rtc);
-
 	return 0;
 }
 
diff --git a/drivers/rtc/rtc-m48t86.c b/drivers/rtc/rtc-m48t86.c
index 2ffbcac..33a91c4 100644
--- a/drivers/rtc/rtc-m48t86.c
+++ b/drivers/rtc/rtc-m48t86.c
@@ -148,8 +148,10 @@ static int m48t86_rtc_probe(struct platform_device *dev)
 {
 	unsigned char reg;
 	struct m48t86_ops *ops = dev->dev.platform_data;
-	struct rtc_device *rtc = rtc_device_register("m48t86",
-				&dev->dev, &m48t86_rtc_ops, THIS_MODULE);
+	struct rtc_device *rtc;
+
+	rtc = devm_rtc_device_register(&dev->dev, "m48t86",
+				&m48t86_rtc_ops, THIS_MODULE);
 
 	if (IS_ERR(rtc))
 		return PTR_ERR(rtc);
@@ -166,11 +168,6 @@ static int m48t86_rtc_probe(struct platform_device *dev)
 
 static int m48t86_rtc_remove(struct platform_device *dev)
 {
-	struct rtc_device *rtc = platform_get_drvdata(dev);
-
- 	if (rtc)
-		rtc_device_unregister(rtc);
-
 	platform_set_drvdata(dev, NULL);
 
 	return 0;
diff --git a/drivers/rtc/rtc-max6900.c b/drivers/rtc/rtc-max6900.c
index a00e332..8669d6d 100644
--- a/drivers/rtc/rtc-max6900.c
+++ b/drivers/rtc/rtc-max6900.c
@@ -214,11 +214,6 @@ static int max6900_rtc_set_time(struct device *dev, struct rtc_time *tm)
 
 static int max6900_remove(struct i2c_client *client)
 {
-	struct rtc_device *rtc = i2c_get_clientdata(client);
-
-	if (rtc)
-		rtc_device_unregister(rtc);
-
 	return 0;
 }
 
@@ -237,8 +232,8 @@ max6900_probe(struct i2c_client *client, const struct i2c_device_id *id)
 
 	dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n");
 
-	rtc = rtc_device_register(max6900_driver.driver.name,
-				  &client->dev, &max6900_rtc_ops, THIS_MODULE);
+	rtc = devm_rtc_device_register(&client->dev, max6900_driver.driver.name,
+					&max6900_rtc_ops, THIS_MODULE);
 	if (IS_ERR(rtc))
 		return PTR_ERR(rtc);
 
diff --git a/drivers/rtc/rtc-max6902.c b/drivers/rtc/rtc-max6902.c
index 7d0bf69..7e4491b 100644
--- a/drivers/rtc/rtc-max6902.c
+++ b/drivers/rtc/rtc-max6902.c
@@ -134,8 +134,8 @@ static int max6902_probe(struct spi_device *spi)
 	if (res != 0)
 		return res;
 
-	rtc = rtc_device_register("max6902",
-				&spi->dev, &max6902_rtc_ops, THIS_MODULE);
+	rtc = devm_rtc_device_register(&spi->dev, "max6902",
+				&max6902_rtc_ops, THIS_MODULE);
 	if (IS_ERR(rtc))
 		return PTR_ERR(rtc);
 
@@ -145,9 +145,6 @@ static int max6902_probe(struct spi_device *spi)
 
 static int max6902_remove(struct spi_device *spi)
 {
-	struct rtc_device *rtc = dev_get_drvdata(&spi->dev);
-
-	rtc_device_unregister(rtc);
 	return 0;
 }
 
diff --git a/drivers/rtc/rtc-max77686.c b/drivers/rtc/rtc-max77686.c
index 6b1337f..fb08b89 100644
--- a/drivers/rtc/rtc-max77686.c
+++ b/drivers/rtc/rtc-max77686.c
@@ -24,7 +24,7 @@
 
 /* RTC Control Register */
 #define BCD_EN_SHIFT			0
-#define BCD_EN_MASK				(1 << BCD_EN_SHIFT)
+#define BCD_EN_MASK			(1 << BCD_EN_SHIFT)
 #define MODEL24_SHIFT			1
 #define MODEL24_MASK			(1 << MODEL24_SHIFT)
 /* RTC Update Register1 */
@@ -33,12 +33,12 @@
 #define RTC_RBUDR_SHIFT			4
 #define RTC_RBUDR_MASK			(1 << RTC_RBUDR_SHIFT)
 /* WTSR and SMPL Register */
-#define WTSRT_SHIFT				0
-#define SMPLT_SHIFT				2
+#define WTSRT_SHIFT			0
+#define SMPLT_SHIFT			2
 #define WTSR_EN_SHIFT			6
 #define SMPL_EN_SHIFT			7
-#define WTSRT_MASK				(3 << WTSRT_SHIFT)
-#define SMPLT_MASK				(3 << SMPLT_SHIFT)
+#define WTSRT_MASK			(3 << WTSRT_SHIFT)
+#define SMPLT_MASK			(3 << SMPLT_SHIFT)
 #define WTSR_EN_MASK			(1 << WTSR_EN_SHIFT)
 #define SMPL_EN_MASK			(1 << SMPL_EN_SHIFT)
 /* RTC Hour register */
@@ -466,7 +466,7 @@ static void max77686_rtc_enable_smpl(struct max77686_rtc_info *info, bool enable
 
 	val = 0;
 	regmap_read(info->max77686->rtc_regmap, MAX77686_WTSR_SMPL_CNTL, &val);
-	pr_info("%s: WTSR_SMPL(0x%02x)\n", __func__, val);
+	dev_info(info->dev, "%s: WTSR_SMPL(0x%02x)\n", __func__, val);
 }
 #endif /* MAX77686_RTC_WTSR_SMPL */
 
@@ -505,7 +505,8 @@ static int max77686_rtc_probe(struct platform_device *pdev)
 
 	dev_info(&pdev->dev, "%s\n", __func__);
 
-	info = kzalloc(sizeof(struct max77686_rtc_info), GFP_KERNEL);
+	info = devm_kzalloc(&pdev->dev, sizeof(struct max77686_rtc_info),
+				GFP_KERNEL);
 	if (!info)
 		return -ENOMEM;
 
@@ -519,7 +520,6 @@ static int max77686_rtc_probe(struct platform_device *pdev)
 		ret = PTR_ERR(info->max77686->rtc_regmap);
 		dev_err(info->max77686->dev, "Failed to allocate register map: %d\n",
 				ret);
-		kfree(info);
 		return ret;
 	}
 	platform_set_drvdata(pdev, info);
@@ -538,8 +538,8 @@ static int max77686_rtc_probe(struct platform_device *pdev)
 
 	device_init_wakeup(&pdev->dev, 1);
 
-	info->rtc_dev = rtc_device_register("max77686-rtc", &pdev->dev,
-			&max77686_rtc_ops, THIS_MODULE);
+	info->rtc_dev = devm_rtc_device_register(&pdev->dev, "max77686-rtc",
+					&max77686_rtc_ops, THIS_MODULE);
 
 	if (IS_ERR(info->rtc_dev)) {
 		dev_info(&pdev->dev, "%s: fail\n", __func__);
@@ -551,36 +551,24 @@ static int max77686_rtc_probe(struct platform_device *pdev)
 		goto err_rtc;
 	}
 	virq = irq_create_mapping(max77686->irq_domain, MAX77686_RTCIRQ_RTCA1);
-	if (!virq)
+	if (!virq) {
+		ret = -ENXIO;
 		goto err_rtc;
+	}
 	info->virq = virq;
 
-	ret = request_threaded_irq(virq, NULL, max77686_rtc_alarm_irq, 0,
-			"rtc-alarm0", info);
-	if (ret < 0) {
+	ret = devm_request_threaded_irq(&pdev->dev, virq, NULL,
+				max77686_rtc_alarm_irq, 0, "rtc-alarm0", info);
+	if (ret < 0)
 		dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n",
 			info->virq, ret);
-		goto err_rtc;
-	}
 
-	goto out;
 err_rtc:
-	kfree(info);
-	return ret;
-out:
 	return ret;
 }
 
 static int max77686_rtc_remove(struct platform_device *pdev)
 {
-	struct max77686_rtc_info *info = platform_get_drvdata(pdev);
-
-	if (info) {
-		free_irq(info->virq, info);
-		rtc_device_unregister(info->rtc_dev);
-		kfree(info);
-	}
-
 	return 0;
 }
 
@@ -594,11 +582,14 @@ static void max77686_rtc_shutdown(struct platform_device *pdev)
 	for (i = 0; i < 3; i++) {
 		max77686_rtc_enable_wtsr(info, false);
 		regmap_read(info->max77686->rtc_regmap, MAX77686_WTSR_SMPL_CNTL, &val);
-		pr_info("%s: WTSR_SMPL reg(0x%02x)\n", __func__, val);
-		if (val & WTSR_EN_MASK)
-			pr_emerg("%s: fail to disable WTSR\n", __func__);
-		else {
-			pr_info("%s: success to disable WTSR\n", __func__);
+		dev_info(info->dev, "%s: WTSR_SMPL reg(0x%02x)\n", __func__,
+				val);
+		if (val & WTSR_EN_MASK) {
+			dev_emerg(info->dev, "%s: fail to disable WTSR\n",
+					__func__);
+		} else {
+			dev_info(info->dev, "%s: success to disable WTSR\n",
+					__func__);
 			break;
 		}
 	}
@@ -624,18 +615,8 @@ static struct platform_driver max77686_rtc_driver = {
 	.id_table	= rtc_id,
 };
 
-static int __init max77686_rtc_init(void)
-{
-	return platform_driver_register(&max77686_rtc_driver);
-}
-module_init(max77686_rtc_init);
-
-static void __exit max77686_rtc_exit(void)
-{
-	platform_driver_unregister(&max77686_rtc_driver);
-}
-module_exit(max77686_rtc_exit);
+module_platform_driver(max77686_rtc_driver);
 
 MODULE_DESCRIPTION("Maxim MAX77686 RTC driver");
-MODULE_AUTHOR("<woong.byun@samsung.com>");
+MODULE_AUTHOR("Chiwoong Byun <woong.byun@samsung.com>");
 MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-max8907.c b/drivers/rtc/rtc-max8907.c
index 31ca8fa..86afb79 100644
--- a/drivers/rtc/rtc-max8907.c
+++ b/drivers/rtc/rtc-max8907.c
@@ -190,7 +190,7 @@ static int max8907_rtc_probe(struct platform_device *pdev)
 	rtc->max8907 = max8907;
 	rtc->regmap = max8907->regmap_rtc;
 
-	rtc->rtc_dev = rtc_device_register("max8907-rtc", &pdev->dev,
+	rtc->rtc_dev = devm_rtc_device_register(&pdev->dev, "max8907-rtc",
 					&max8907_rtc_ops, THIS_MODULE);
 	if (IS_ERR(rtc->rtc_dev)) {
 		ret = PTR_ERR(rtc->rtc_dev);
@@ -200,33 +200,21 @@ static int max8907_rtc_probe(struct platform_device *pdev)
 
 	rtc->irq = regmap_irq_get_virq(max8907->irqc_rtc,
 				       MAX8907_IRQ_RTC_ALARM0);
-	if (rtc->irq < 0) {
-		ret = rtc->irq;
-		goto err_unregister;
-	}
+	if (rtc->irq < 0)
+		return rtc->irq;
 
 	ret = devm_request_threaded_irq(&pdev->dev, rtc->irq, NULL,
 				max8907_irq_handler,
 				IRQF_ONESHOT, "max8907-alarm0", rtc);
-	if (ret < 0) {
+	if (ret < 0)
 		dev_err(&pdev->dev, "Failed to request IRQ%d: %d\n",
 			rtc->irq, ret);
-		goto err_unregister;
-	}
 
-	return 0;
-
-err_unregister:
-	rtc_device_unregister(rtc->rtc_dev);
 	return ret;
 }
 
 static int max8907_rtc_remove(struct platform_device *pdev)
 {
-	struct max8907_rtc *rtc = platform_get_drvdata(pdev);
-
-	rtc_device_unregister(rtc->rtc_dev);
-
 	return 0;
 }
 
diff --git a/drivers/rtc/rtc-max8997.c b/drivers/rtc/rtc-max8997.c
index 00e505b..5693619 100644
--- a/drivers/rtc/rtc-max8997.c
+++ b/drivers/rtc/rtc-max8997.c
@@ -479,8 +479,8 @@ static int max8997_rtc_probe(struct platform_device *pdev)
 
 	device_init_wakeup(&pdev->dev, 1);
 
-	info->rtc_dev = rtc_device_register("max8997-rtc", &pdev->dev,
-			&max8997_rtc_ops, THIS_MODULE);
+	info->rtc_dev = devm_rtc_device_register(&pdev->dev, "max8997-rtc",
+					&max8997_rtc_ops, THIS_MODULE);
 
 	if (IS_ERR(info->rtc_dev)) {
 		ret = PTR_ERR(info->rtc_dev);
@@ -491,6 +491,7 @@ static int max8997_rtc_probe(struct platform_device *pdev)
 	virq = irq_create_mapping(max8997->irq_domain, MAX8997_PMICIRQ_RTCA1);
 	if (!virq) {
 		dev_err(&pdev->dev, "Failed to create mapping alarm IRQ\n");
+		ret = -ENXIO;
 		goto err_out;
 	}
 	info->virq = virq;
@@ -498,26 +499,16 @@ static int max8997_rtc_probe(struct platform_device *pdev)
 	ret = devm_request_threaded_irq(&pdev->dev, virq, NULL,
 				max8997_rtc_alarm_irq, 0,
 				"rtc-alarm0", info);
-	if (ret < 0) {
+	if (ret < 0)
 		dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n",
 			info->virq, ret);
-		goto err_out;
-	}
-
-	return ret;
 
 err_out:
-	rtc_device_unregister(info->rtc_dev);
 	return ret;
 }
 
 static int max8997_rtc_remove(struct platform_device *pdev)
 {
-	struct max8997_rtc_info *info = platform_get_drvdata(pdev);
-
-	if (info)
-		rtc_device_unregister(info->rtc_dev);
-
 	return 0;
 }
 
diff --git a/drivers/rtc/rtc-mc13xxx.c b/drivers/rtc/rtc-mc13xxx.c
index 2643d88..5391b15 100644
--- a/drivers/rtc/rtc-mc13xxx.c
+++ b/drivers/rtc/rtc-mc13xxx.c
@@ -420,17 +420,7 @@ static struct platform_driver mc13xxx_rtc_driver = {
 	},
 };
 
-static int __init mc13xxx_rtc_init(void)
-{
-	return platform_driver_probe(&mc13xxx_rtc_driver, &mc13xxx_rtc_probe);
-}
-module_init(mc13xxx_rtc_init);
-
-static void __exit mc13xxx_rtc_exit(void)
-{
-	platform_driver_unregister(&mc13xxx_rtc_driver);
-}
-module_exit(mc13xxx_rtc_exit);
+module_platform_driver_probe(mc13xxx_rtc_driver, &mc13xxx_rtc_probe);
 
 MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
 MODULE_DESCRIPTION("RTC driver for Freescale MC13XXX PMIC");
diff --git a/drivers/rtc/rtc-msm6242.c b/drivers/rtc/rtc-msm6242.c
index fcb113c..3ac1e8e 100644
--- a/drivers/rtc/rtc-msm6242.c
+++ b/drivers/rtc/rtc-msm6242.c
@@ -252,18 +252,7 @@ static struct platform_driver msm6242_rtc_driver = {
 	.remove	= __exit_p(msm6242_rtc_remove),
 };
 
-static int __init msm6242_rtc_init(void)
-{
-	return platform_driver_probe(&msm6242_rtc_driver, msm6242_rtc_probe);
-}
-
-static void __exit msm6242_rtc_fini(void)
-{
-	platform_driver_unregister(&msm6242_rtc_driver);
-}
-
-module_init(msm6242_rtc_init);
-module_exit(msm6242_rtc_fini);
+module_platform_driver_probe(msm6242_rtc_driver, msm6242_rtc_probe);
 
 MODULE_AUTHOR("Geert Uytterhoeven <geert@linux-m68k.org>");
 MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-mv.c b/drivers/rtc/rtc-mv.c
index 8f87fec..baab802 100644
--- a/drivers/rtc/rtc-mv.c
+++ b/drivers/rtc/rtc-mv.c
@@ -217,7 +217,7 @@ static const struct rtc_class_ops mv_rtc_alarm_ops = {
 	.alarm_irq_enable = mv_rtc_alarm_irq_enable,
 };
 
-static int mv_rtc_probe(struct platform_device *pdev)
+static int __init mv_rtc_probe(struct platform_device *pdev)
 {
 	struct resource *res;
 	struct rtc_plat_data *pdata;
@@ -272,12 +272,13 @@ static int mv_rtc_probe(struct platform_device *pdev)
 
 	if (pdata->irq >= 0) {
 		device_init_wakeup(&pdev->dev, 1);
-		pdata->rtc = rtc_device_register(pdev->name, &pdev->dev,
+		pdata->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
 						 &mv_rtc_alarm_ops,
 						 THIS_MODULE);
-	} else
-		pdata->rtc = rtc_device_register(pdev->name, &pdev->dev,
+	} else {
+		pdata->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
 						 &mv_rtc_ops, THIS_MODULE);
+	}
 	if (IS_ERR(pdata->rtc)) {
 		ret = PTR_ERR(pdata->rtc);
 		goto out;
@@ -308,7 +309,6 @@ static int __exit mv_rtc_remove(struct platform_device *pdev)
 	if (pdata->irq >= 0)
 		device_init_wakeup(&pdev->dev, 0);
 
-	rtc_device_unregister(pdata->rtc);
 	if (!IS_ERR(pdata->clk))
 		clk_disable_unprepare(pdata->clk);
 
@@ -331,18 +331,7 @@ static struct platform_driver mv_rtc_driver = {
 	},
 };
 
-static __init int mv_init(void)
-{
-	return platform_driver_probe(&mv_rtc_driver, mv_rtc_probe);
-}
-
-static __exit void mv_exit(void)
-{
-	platform_driver_unregister(&mv_rtc_driver);
-}
-
-module_init(mv_init);
-module_exit(mv_exit);
+module_platform_driver_probe(mv_rtc_driver, mv_rtc_probe);
 
 MODULE_AUTHOR("Saeed Bishara <saeed@marvell.com>");
 MODULE_DESCRIPTION("Marvell RTC driver");
diff --git a/drivers/rtc/rtc-mxc.c b/drivers/rtc/rtc-mxc.c
index 1c3ef72..9a3895b 100644
--- a/drivers/rtc/rtc-mxc.c
+++ b/drivers/rtc/rtc-mxc.c
@@ -439,7 +439,7 @@ static int mxc_rtc_probe(struct platform_device *pdev)
 	if (pdata->irq >=0)
 		device_init_wakeup(&pdev->dev, 1);
 
-	rtc = rtc_device_register(pdev->name, &pdev->dev, &mxc_rtc_ops,
+	rtc = devm_rtc_device_register(&pdev->dev, pdev->name, &mxc_rtc_ops,
 				  THIS_MODULE);
 	if (IS_ERR(rtc)) {
 		ret = PTR_ERR(rtc);
@@ -464,15 +464,13 @@ static int mxc_rtc_remove(struct platform_device *pdev)
 {
 	struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
 
-	rtc_device_unregister(pdata->rtc);
-
 	clk_disable_unprepare(pdata->clk);
 	platform_set_drvdata(pdev, NULL);
 
 	return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int mxc_rtc_suspend(struct device *dev)
 {
 	struct rtc_plat_data *pdata = dev_get_drvdata(dev);
@@ -492,19 +490,14 @@ static int mxc_rtc_resume(struct device *dev)
 
 	return 0;
 }
-
-static struct dev_pm_ops mxc_rtc_pm_ops = {
-	.suspend	= mxc_rtc_suspend,
-	.resume		= mxc_rtc_resume,
-};
 #endif
 
+static SIMPLE_DEV_PM_OPS(mxc_rtc_pm_ops, mxc_rtc_suspend, mxc_rtc_resume);
+
 static struct platform_driver mxc_rtc_driver = {
 	.driver = {
 		   .name	= "mxc_rtc",
-#ifdef CONFIG_PM
 		   .pm		= &mxc_rtc_pm_ops,
-#endif
 		   .owner	= THIS_MODULE,
 	},
 	.id_table = imx_rtc_devtype,
diff --git a/drivers/rtc/rtc-nuc900.c b/drivers/rtc/rtc-nuc900.c
index a636808..4d9525c 100644
--- a/drivers/rtc/rtc-nuc900.c
+++ b/drivers/rtc/rtc-nuc900.c
@@ -222,7 +222,7 @@ static struct rtc_class_ops nuc900_rtc_ops = {
 	.alarm_irq_enable = nuc900_alarm_irq_enable,
 };
 
-static int nuc900_rtc_probe(struct platform_device *pdev)
+static int __init nuc900_rtc_probe(struct platform_device *pdev)
 {
 	struct resource *res;
 	struct nuc900_rtc *nuc900_rtc;
@@ -284,7 +284,7 @@ fail1:	kfree(nuc900_rtc);
 	return err;
 }
 
-static int nuc900_rtc_remove(struct platform_device *pdev)
+static int __exit nuc900_rtc_remove(struct platform_device *pdev)
 {
 	struct nuc900_rtc *nuc900_rtc = platform_get_drvdata(pdev);
 	struct resource *res;
@@ -304,25 +304,14 @@ static int nuc900_rtc_remove(struct platform_device *pdev)
 }
 
 static struct platform_driver nuc900_rtc_driver = {
-	.remove		= nuc900_rtc_remove,
+	.remove		= __exit_p(nuc900_rtc_remove),
 	.driver		= {
 		.name	= "nuc900-rtc",
 		.owner	= THIS_MODULE,
 	},
 };
 
-static int __init nuc900_rtc_init(void)
-{
-	return platform_driver_probe(&nuc900_rtc_driver, nuc900_rtc_probe);
-}
-
-static void __exit nuc900_rtc_exit(void)
-{
-	platform_driver_unregister(&nuc900_rtc_driver);
-}
-
-module_init(nuc900_rtc_init);
-module_exit(nuc900_rtc_exit);
+module_platform_driver_probe(nuc900_rtc_driver, nuc900_rtc_probe);
 
 MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>");
 MODULE_DESCRIPTION("nuc910/nuc920 RTC driver");
diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c
index 6009714..a1f9d30 100644
--- a/drivers/rtc/rtc-omap.c
+++ b/drivers/rtc/rtc-omap.c
@@ -324,7 +324,7 @@ MODULE_DEVICE_TABLE(of, omap_rtc_of_match);
 
 static int __init omap_rtc_probe(struct platform_device *pdev)
 {
-	struct resource		*res, *mem;
+	struct resource		*res;
 	struct rtc_device	*rtc;
 	u8			reg, new_ctrl;
 	const struct platform_device_id *id_entry;
@@ -352,18 +352,9 @@ static int __init omap_rtc_probe(struct platform_device *pdev)
 		return -ENOENT;
 	}
 
-	mem = request_mem_region(res->start, resource_size(res), pdev->name);
-	if (!mem) {
-		pr_debug("%s: RTC registers at %08x are not free\n",
-			pdev->name, res->start);
-		return -EBUSY;
-	}
-
-	rtc_base = ioremap(res->start, resource_size(res));
-	if (!rtc_base) {
-		pr_debug("%s: RTC registers can't be mapped\n", pdev->name);
-		goto fail;
-	}
+	rtc_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(rtc_base))
+		return PTR_ERR(rtc_base);
 
 	/* Enable the clock/module so that we can access the registers */
 	pm_runtime_enable(&pdev->dev);
@@ -375,7 +366,7 @@ static int __init omap_rtc_probe(struct platform_device *pdev)
 		rtc_writel(KICK1_VALUE, OMAP_RTC_KICK1_REG);
 	}
 
-	rtc = rtc_device_register(pdev->name, &pdev->dev,
+	rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
 			&omap_rtc_ops, THIS_MODULE);
 	if (IS_ERR(rtc)) {
 		pr_debug("%s: can't register RTC device, err %ld\n",
@@ -383,7 +374,6 @@ static int __init omap_rtc_probe(struct platform_device *pdev)
 		goto fail0;
 	}
 	platform_set_drvdata(pdev, rtc);
-	dev_set_drvdata(&rtc->dev, mem);
 
 	/* clear pending irqs, and set 1/second periodic,
 	 * which we'll use instead of update irqs
@@ -401,18 +391,18 @@ static int __init omap_rtc_probe(struct platform_device *pdev)
 		rtc_write(OMAP_RTC_STATUS_ALARM, OMAP_RTC_STATUS_REG);
 
 	/* handle periodic and alarm irqs */
-	if (request_irq(omap_rtc_timer, rtc_irq, 0,
+	if (devm_request_irq(&pdev->dev, omap_rtc_timer, rtc_irq, 0,
 			dev_name(&rtc->dev), rtc)) {
 		pr_debug("%s: RTC timer interrupt IRQ%d already claimed\n",
 			pdev->name, omap_rtc_timer);
-		goto fail1;
+		goto fail0;
 	}
 	if ((omap_rtc_timer != omap_rtc_alarm) &&
-		(request_irq(omap_rtc_alarm, rtc_irq, 0,
+		(devm_request_irq(&pdev->dev, omap_rtc_alarm, rtc_irq, 0,
 			dev_name(&rtc->dev), rtc))) {
 		pr_debug("%s: RTC alarm interrupt IRQ%d already claimed\n",
 			pdev->name, omap_rtc_alarm);
-		goto fail2;
+		goto fail0;
 	}
 
 	/* On boards with split power, RTC_ON_NOFF won't reset the RTC */
@@ -446,25 +436,16 @@ static int __init omap_rtc_probe(struct platform_device *pdev)
 
 	return 0;
 
-fail2:
-	free_irq(omap_rtc_timer, rtc);
-fail1:
-	rtc_device_unregister(rtc);
 fail0:
 	if (id_entry && (id_entry->driver_data & OMAP_RTC_HAS_KICKER))
 		rtc_writel(0, OMAP_RTC_KICK0_REG);
 	pm_runtime_put_sync(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
-	iounmap(rtc_base);
-fail:
-	release_mem_region(mem->start, resource_size(mem));
 	return -EIO;
 }
 
 static int __exit omap_rtc_remove(struct platform_device *pdev)
 {
-	struct rtc_device	*rtc = platform_get_drvdata(pdev);
-	struct resource		*mem = dev_get_drvdata(&rtc->dev);
 	const struct platform_device_id *id_entry =
 				platform_get_device_id(pdev);
 
@@ -473,12 +454,6 @@ static int __exit omap_rtc_remove(struct platform_device *pdev)
 	/* leave rtc running, but disable irqs */
 	rtc_write(0, OMAP_RTC_INTERRUPTS_REG);
 
-	free_irq(omap_rtc_timer, rtc);
-
-	if (omap_rtc_timer != omap_rtc_alarm)
-		free_irq(omap_rtc_alarm, rtc);
-
-	rtc_device_unregister(rtc);
 	if (id_entry && (id_entry->driver_data & OMAP_RTC_HAS_KICKER))
 		rtc_writel(0, OMAP_RTC_KICK0_REG);
 
@@ -486,8 +461,6 @@ static int __exit omap_rtc_remove(struct platform_device *pdev)
 	pm_runtime_put_sync(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
 
-	iounmap(rtc_base);
-	release_mem_region(mem->start, resource_size(mem));
 	return 0;
 }
 
@@ -550,17 +523,7 @@ static struct platform_driver omap_rtc_driver = {
 	.id_table	= omap_rtc_devtype,
 };
 
-static int __init rtc_init(void)
-{
-	return platform_driver_probe(&omap_rtc_driver, omap_rtc_probe);
-}
-module_init(rtc_init);
-
-static void __exit rtc_exit(void)
-{
-	platform_driver_unregister(&omap_rtc_driver);
-}
-module_exit(rtc_exit);
+module_platform_driver_probe(omap_rtc_driver, omap_rtc_probe);
 
 MODULE_AUTHOR("George G. Davis (and others)");
 MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-palmas.c b/drivers/rtc/rtc-palmas.c
index 59c4298..50204d4 100644
--- a/drivers/rtc/rtc-palmas.c
+++ b/drivers/rtc/rtc-palmas.c
@@ -30,6 +30,7 @@
 #include <linux/kernel.h>
 #include <linux/mfd/palmas.h>
 #include <linux/module.h>
+#include <linux/of.h>
 #include <linux/rtc.h>
 #include <linux/types.h>
 #include <linux/platform_device.h>
@@ -264,7 +265,7 @@ static int palmas_rtc_probe(struct platform_device *pdev)
 
 	palmas_rtc->irq = platform_get_irq(pdev, 0);
 
-	palmas_rtc->rtc = rtc_device_register(pdev->name, &pdev->dev,
+	palmas_rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
 				&palmas_rtc_ops, THIS_MODULE);
 	if (IS_ERR(palmas_rtc->rtc)) {
 		ret = PTR_ERR(palmas_rtc->rtc);
@@ -272,14 +273,13 @@ static int palmas_rtc_probe(struct platform_device *pdev)
 		return ret;
 	}
 
-	ret = request_threaded_irq(palmas_rtc->irq, NULL,
+	ret = devm_request_threaded_irq(&pdev->dev, palmas_rtc->irq, NULL,
 			palmas_rtc_interrupt,
 			IRQF_TRIGGER_LOW | IRQF_ONESHOT |
 			IRQF_EARLY_RESUME,
 			dev_name(&pdev->dev), palmas_rtc);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "IRQ request failed, err = %d\n", ret);
-		rtc_device_unregister(palmas_rtc->rtc);
 		return ret;
 	}
 
@@ -289,11 +289,7 @@ static int palmas_rtc_probe(struct platform_device *pdev)
 
 static int palmas_rtc_remove(struct platform_device *pdev)
 {
-	struct palmas_rtc *palmas_rtc = platform_get_drvdata(pdev);
-
 	palmas_rtc_alarm_irq_enable(&pdev->dev, 0);
-	free_irq(palmas_rtc->irq, palmas_rtc);
-	rtc_device_unregister(palmas_rtc->rtc);
 	return 0;
 }
 
@@ -321,6 +317,14 @@ static const struct dev_pm_ops palmas_rtc_pm_ops = {
 	SET_SYSTEM_SLEEP_PM_OPS(palmas_rtc_suspend, palmas_rtc_resume)
 };
 
+#ifdef CONFIG_OF
+static struct of_device_id of_palmas_rtc_match[] = {
+	{ .compatible = "ti,palmas-rtc"},
+	{ },
+};
+MODULE_DEVICE_TABLE(of, of_palmas_rtc_match);
+#endif
+
 static struct platform_driver palmas_rtc_driver = {
 	.probe		= palmas_rtc_probe,
 	.remove		= palmas_rtc_remove,
@@ -328,6 +332,7 @@ static struct platform_driver palmas_rtc_driver = {
 		.owner	= THIS_MODULE,
 		.name	= "palmas-rtc",
 		.pm	= &palmas_rtc_pm_ops,
+		.of_match_table = of_match_ptr(of_palmas_rtc_match),
 	},
 };
 
diff --git a/drivers/rtc/rtc-pcap.c b/drivers/rtc/rtc-pcap.c
index e0019cd..ce09824 100644
--- a/drivers/rtc/rtc-pcap.c
+++ b/drivers/rtc/rtc-pcap.c
@@ -139,7 +139,7 @@ static const struct rtc_class_ops pcap_rtc_ops = {
 	.alarm_irq_enable = pcap_rtc_alarm_irq_enable,
 };
 
-static int pcap_rtc_probe(struct platform_device *pdev)
+static int __init pcap_rtc_probe(struct platform_device *pdev)
 {
 	struct pcap_rtc *pcap_rtc;
 	int timer_irq, alarm_irq;
@@ -183,7 +183,7 @@ fail_rtc:
 	return err;
 }
 
-static int pcap_rtc_remove(struct platform_device *pdev)
+static int __exit pcap_rtc_remove(struct platform_device *pdev)
 {
 	struct pcap_rtc *pcap_rtc = platform_get_drvdata(pdev);
 
@@ -196,25 +196,14 @@ static int pcap_rtc_remove(struct platform_device *pdev)
 }
 
 static struct platform_driver pcap_rtc_driver = {
-	.remove = pcap_rtc_remove,
+	.remove = __exit_p(pcap_rtc_remove),
 	.driver = {
 		.name  = "pcap-rtc",
 		.owner = THIS_MODULE,
 	},
 };
 
-static int __init rtc_pcap_init(void)
-{
-	return platform_driver_probe(&pcap_rtc_driver, pcap_rtc_probe);
-}
-
-static void __exit rtc_pcap_exit(void)
-{
-	platform_driver_unregister(&pcap_rtc_driver);
-}
-
-module_init(rtc_pcap_init);
-module_exit(rtc_pcap_exit);
+module_platform_driver_probe(pcap_rtc_driver, pcap_rtc_probe);
 
 MODULE_DESCRIPTION("Motorola pcap rtc driver");
 MODULE_AUTHOR("guiming zhuo <gmzhuo@gmail.com>");
diff --git a/drivers/rtc/rtc-pcf8523.c b/drivers/rtc/rtc-pcf8523.c
index 889e316..305c951 100644
--- a/drivers/rtc/rtc-pcf8523.c
+++ b/drivers/rtc/rtc-pcf8523.c
@@ -307,7 +307,7 @@ static int pcf8523_probe(struct i2c_client *client,
 	if (err < 0)
 		return err;
 
-	pcf->rtc = rtc_device_register(DRIVER_NAME, &client->dev,
+	pcf->rtc = devm_rtc_device_register(&client->dev, DRIVER_NAME,
 				       &pcf8523_rtc_ops, THIS_MODULE);
 	if (IS_ERR(pcf->rtc))
 		return PTR_ERR(pcf->rtc);
@@ -319,10 +319,6 @@ static int pcf8523_probe(struct i2c_client *client,
 
 static int pcf8523_remove(struct i2c_client *client)
 {
-	struct pcf8523 *pcf = i2c_get_clientdata(client);
-
-	rtc_device_unregister(pcf->rtc);
-
 	return 0;
 }
 
diff --git a/drivers/rtc/rtc-proc.c b/drivers/rtc/rtc-proc.c
index e96236a..ffa69e1 100644
--- a/drivers/rtc/rtc-proc.c
+++ b/drivers/rtc/rtc-proc.c
@@ -110,7 +110,7 @@ static int rtc_proc_show(struct seq_file *seq, void *offset)
 static int rtc_proc_open(struct inode *inode, struct file *file)
 {
 	int ret;
-	struct rtc_device *rtc = PDE(inode)->data;
+	struct rtc_device *rtc = PDE_DATA(inode);
 
 	if (!try_module_get(THIS_MODULE))
 		return -ENODEV;
diff --git a/drivers/rtc/rtc-ps3.c b/drivers/rtc/rtc-ps3.c
index 968133c..4bb825b 100644
--- a/drivers/rtc/rtc-ps3.c
+++ b/drivers/rtc/rtc-ps3.c
@@ -62,7 +62,7 @@ static int __init ps3_rtc_probe(struct platform_device *dev)
 {
 	struct rtc_device *rtc;
 
-	rtc = rtc_device_register("rtc-ps3", &dev->dev, &ps3_rtc_ops,
+	rtc = devm_rtc_device_register(&dev->dev, "rtc-ps3", &ps3_rtc_ops,
 				  THIS_MODULE);
 	if (IS_ERR(rtc))
 		return PTR_ERR(rtc);
@@ -73,7 +73,6 @@ static int __init ps3_rtc_probe(struct platform_device *dev)
 
 static int __exit ps3_rtc_remove(struct platform_device *dev)
 {
-	rtc_device_unregister(platform_get_drvdata(dev));
 	return 0;
 }
 
@@ -85,18 +84,7 @@ static struct platform_driver ps3_rtc_driver = {
 	.remove = __exit_p(ps3_rtc_remove),
 };
 
-static int __init ps3_rtc_init(void)
-{
-	return platform_driver_probe(&ps3_rtc_driver, ps3_rtc_probe);
-}
-
-static void __exit ps3_rtc_fini(void)
-{
-	platform_driver_unregister(&ps3_rtc_driver);
-}
-
-module_init(ps3_rtc_init);
-module_exit(ps3_rtc_fini);
+module_platform_driver_probe(ps3_rtc_driver, ps3_rtc_probe);
 
 MODULE_AUTHOR("Sony Corporation");
 MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-pxa.c b/drivers/rtc/rtc-pxa.c
index 03c85ee..a2c75c1 100644
--- a/drivers/rtc/rtc-pxa.c
+++ b/drivers/rtc/rtc-pxa.c
@@ -19,6 +19,7 @@
  *
  */
 
+#include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/module.h>
@@ -80,22 +81,29 @@
 #define RYAR1		0x1c
 #define RTCPICR		0x34
 #define PIAR		0x38
+#define PSBR_RTC	0x00
 
 #define rtc_readl(pxa_rtc, reg)	\
 	__raw_readl((pxa_rtc)->base + (reg))
 #define rtc_writel(pxa_rtc, reg, value)	\
 	__raw_writel((value), (pxa_rtc)->base + (reg))
+#define rtc_readl_psbr(pxa_rtc, reg)	\
+	__raw_readl((pxa_rtc)->base_psbr + (reg))
+#define rtc_writel_psbr(pxa_rtc, reg, value)	\
+	__raw_writel((value), (pxa_rtc)->base_psbr + (reg))
 
 struct pxa_rtc {
 	struct resource	*ress;
+	struct resource	*ress_psbr;
 	void __iomem		*base;
+	void __iomem		*base_psbr;
 	int			irq_1Hz;
 	int			irq_Alrm;
 	struct rtc_device	*rtc;
 	spinlock_t		lock;		/* Protects this structure */
 };
 
-
+static struct pxa_rtc *rtc_info;
 static u32 ryxr_calc(struct rtc_time *tm)
 {
 	return ((tm->tm_year + 1900) << RYxR_YEAR_S)
@@ -117,7 +125,7 @@ static void tm_calc(u32 rycr, u32 rdcr, struct rtc_time *tm)
 	tm->tm_year = ((rycr & RYxR_YEAR_MASK) >> RYxR_YEAR_S) - 1900;
 	tm->tm_mon = (((rycr & RYxR_MONTH_MASK) >> RYxR_MONTH_S)) - 1;
 	tm->tm_mday = (rycr & RYxR_DAY_MASK);
-	tm->tm_wday = ((rycr & RDxR_DOW_MASK) >> RDxR_DOW_S) - 1;
+	tm->tm_wday = ((rdcr & RDxR_DOW_MASK) >> RDxR_DOW_S) - 1;
 	tm->tm_hour = (rdcr & RDxR_HOUR_MASK) >> RDxR_HOUR_S;
 	tm->tm_min = (rdcr & RDxR_MIN_MASK) >> RDxR_MIN_S;
 	tm->tm_sec = rdcr & RDxR_SEC_MASK;
@@ -175,7 +183,6 @@ static irqreturn_t pxa_rtc_irq(int irq, void *dev_id)
 
 	/* enable back rtc interrupts */
 	rtc_writel(pxa_rtc, RTSR, rtsr & ~RTSR_TRIG_MASK);
-
 	spin_unlock(&pxa_rtc->lock);
 	return IRQ_HANDLED;
 }
@@ -250,12 +257,45 @@ static int pxa_rtc_read_time(struct device *dev, struct rtc_time *tm)
 static int pxa_rtc_set_time(struct device *dev, struct rtc_time *tm)
 {
 	struct pxa_rtc *pxa_rtc = dev_get_drvdata(dev);
-
+	/* sequence to wirte pxa rtc register RCNR RDCR RYCR is
+	*1. set PSBR[RWE] bit, take 2x32-khz to complete
+	*2. write to RTC register,take 2x32-khz to complete
+	*3. clear PSBR[RWE] bit,take 2x32-khz to complete
+	*/
+	if ((tm->tm_year < 70) || (tm->tm_year > 138))
+		return -EINVAL;
+	rtc_writel_psbr(rtc_info, PSBR_RTC, 0x01);
+	udelay(100);
 	rtc_writel(pxa_rtc, RYCR, ryxr_calc(tm));
 	rtc_writel(pxa_rtc, RDCR, rdxr_calc(tm));
+	udelay(100);
+	rtc_writel_psbr(rtc_info, PSBR_RTC, 0x00);
+	udelay(100);
+	pxa_rtc_read_time(dev, tm);
+	dev_info(dev, "tm.year = %d, tm.month = %d, tm.day = %d\n",
+			tm->tm_year + 1900, tm->tm_mon, tm->tm_mday);
+	return 0;
+}
 
+int pxa_rtc_sync_time(unsigned int ticks)
+{
+	/* sequence to wirte pxa rtc register RCNR RDCR RYCR is
+	*1. set PSBR[RWE] bit, take 2x32-khz to complete
+	*2. write to RTC register,take 2x32-khz to complete
+	*3. clear PSBR[RWE] bit,take 2x32-khz to complete
+	*/
+	struct rtc_time tm;
+	rtc_time_to_tm(ticks, &tm);
+	rtc_writel_psbr(rtc_info, PSBR_RTC, 0x01);
+	udelay(100);
+	rtc_writel(rtc_info, RYCR, ryxr_calc(&tm));
+	rtc_writel(rtc_info, RDCR, rdxr_calc(&tm));
+	udelay(100);
+	rtc_writel_psbr(rtc_info, PSBR_RTC, 0x00);
+	udelay(100);
 	return 0;
 }
+EXPORT_SYMBOL(pxa_rtc_sync_time);
 
 static int pxa_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 {
@@ -327,7 +367,7 @@ static int __init pxa_rtc_probe(struct platform_device *pdev)
 	pxa_rtc = kzalloc(sizeof(struct pxa_rtc), GFP_KERNEL);
 	if (!pxa_rtc)
 		return -ENOMEM;
-
+	rtc_info = pxa_rtc;
 	spin_lock_init(&pxa_rtc->lock);
 	platform_set_drvdata(pdev, pxa_rtc);
 
@@ -337,6 +377,11 @@ static int __init pxa_rtc_probe(struct platform_device *pdev)
 		dev_err(dev, "No I/O memory resource defined\n");
 		goto err_ress;
 	}
+	pxa_rtc->ress_psbr = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!pxa_rtc->ress_psbr) {
+		dev_err(dev, "No I/O memory resource defined\n");
+		goto err_ress;
+	}
 
 	pxa_rtc->irq_1Hz = platform_get_irq(pdev, 0);
 	if (pxa_rtc->irq_1Hz < 0) {
@@ -348,7 +393,6 @@ static int __init pxa_rtc_probe(struct platform_device *pdev)
 		dev_err(dev, "No alarm IRQ resource defined\n");
 		goto err_ress;
 	}
-	pxa_rtc_open(dev);
 	ret = -ENOMEM;
 	pxa_rtc->base = ioremap(pxa_rtc->ress->start,
 				resource_size(pxa_rtc->ress));
@@ -357,6 +401,12 @@ static int __init pxa_rtc_probe(struct platform_device *pdev)
 		goto err_map;
 	}
 
+	pxa_rtc->base_psbr = ioremap(pxa_rtc->ress_psbr->start,
+				resource_size(pxa_rtc->ress_psbr));
+	if (!pxa_rtc->base_psbr) {
+		dev_err(&pdev->dev, "Unable to map pxa RTC PSBR I/O memory\n");
+		goto err_map;
+	}
 	/*
 	 * If the clock divider is uninitialized then reset it to the
 	 * default value to get the 1Hz clock.
@@ -379,7 +429,7 @@ static int __init pxa_rtc_probe(struct platform_device *pdev)
 	}
 
 	device_init_wakeup(dev, 1);
-
+	pxa_rtc_open(dev);
 	return 0;
 
 err_rtc_reg:
@@ -416,7 +466,7 @@ static struct of_device_id pxa_rtc_dt_ids[] = {
 MODULE_DEVICE_TABLE(of, pxa_rtc_dt_ids);
 #endif
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int pxa_rtc_suspend(struct device *dev)
 {
 	struct pxa_rtc *pxa_rtc = dev_get_drvdata(dev);
@@ -434,36 +484,20 @@ static int pxa_rtc_resume(struct device *dev)
 		disable_irq_wake(pxa_rtc->irq_Alrm);
 	return 0;
 }
-
-static const struct dev_pm_ops pxa_rtc_pm_ops = {
-	.suspend	= pxa_rtc_suspend,
-	.resume		= pxa_rtc_resume,
-};
 #endif
 
+static SIMPLE_DEV_PM_OPS(pxa_rtc_pm_ops, pxa_rtc_suspend, pxa_rtc_resume);
+
 static struct platform_driver pxa_rtc_driver = {
 	.remove		= __exit_p(pxa_rtc_remove),
 	.driver		= {
 		.name	= "pxa-rtc",
 		.of_match_table = of_match_ptr(pxa_rtc_dt_ids),
-#ifdef CONFIG_PM
 		.pm	= &pxa_rtc_pm_ops,
-#endif
 	},
 };
 
-static int __init pxa_rtc_init(void)
-{
-	return platform_driver_probe(&pxa_rtc_driver, pxa_rtc_probe);
-}
-
-static void __exit pxa_rtc_exit(void)
-{
-	platform_driver_unregister(&pxa_rtc_driver);
-}
-
-module_init(pxa_rtc_init);
-module_exit(pxa_rtc_exit);
+module_platform_driver_probe(pxa_rtc_driver, pxa_rtc_probe);
 
 MODULE_AUTHOR("Robert Jarzmik <robert.jarzmik@free.fr>");
 MODULE_DESCRIPTION("PXA27x/PXA3xx Realtime Clock Driver (RTC)");
diff --git a/drivers/rtc/rtc-r9701.c b/drivers/rtc/rtc-r9701.c
index 7726f4a..0adf5b5 100644
--- a/drivers/rtc/rtc-r9701.c
+++ b/drivers/rtc/rtc-r9701.c
@@ -154,8 +154,8 @@ static int r9701_probe(struct spi_device *spi)
 		}
 	}
 
-	rtc = rtc_device_register("r9701",
-				&spi->dev, &r9701_rtc_ops, THIS_MODULE);
+	rtc = devm_rtc_device_register(&spi->dev, "r9701",
+				&r9701_rtc_ops, THIS_MODULE);
 	if (IS_ERR(rtc))
 		return PTR_ERR(rtc);
 
@@ -166,9 +166,6 @@ static int r9701_probe(struct spi_device *spi)
 
 static int r9701_remove(struct spi_device *spi)
 {
-	struct rtc_device *rtc = dev_get_drvdata(&spi->dev);
-
-	rtc_device_unregister(rtc);
 	return 0;
 }
 
diff --git a/drivers/rtc/rtc-rc5t583.c b/drivers/rtc/rtc-rc5t583.c
index eb3194d..8eabcf5 100644
--- a/drivers/rtc/rtc-rc5t583.c
+++ b/drivers/rtc/rtc-rc5t583.c
@@ -256,7 +256,7 @@ static int rc5t583_rtc_probe(struct platform_device *pdev)
 	}
 	device_init_wakeup(&pdev->dev, 1);
 
-	ricoh_rtc->rtc = rtc_device_register(pdev->name, &pdev->dev,
+	ricoh_rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
 		&rc5t583_rtc_ops, THIS_MODULE);
 	if (IS_ERR(ricoh_rtc->rtc)) {
 		ret = PTR_ERR(ricoh_rtc->rtc);
@@ -276,13 +276,10 @@ static int rc5t583_rtc_remove(struct platform_device *pdev)
 	struct rc5t583_rtc *rc5t583_rtc = dev_get_drvdata(&pdev->dev);
 
 	rc5t583_rtc_alarm_irq_enable(&rc5t583_rtc->rtc->dev, 0);
-
-	rtc_device_unregister(rc5t583_rtc->rtc);
 	return 0;
 }
 
 #ifdef CONFIG_PM_SLEEP
-
 static int rc5t583_rtc_suspend(struct device *dev)
 {
 	struct rc5t583 *rc5t583 = dev_get_drvdata(dev->parent);
@@ -304,24 +301,18 @@ static int rc5t583_rtc_resume(struct device *dev)
 	return regmap_write(rc5t583->regmap, RC5T583_RTC_CTL1,
 		rc5t583_rtc->irqen);
 }
-
-static const struct dev_pm_ops rc5t583_rtc_pm_ops = {
-	.suspend	= rc5t583_rtc_suspend,
-	.resume		= rc5t583_rtc_resume,
-};
-
-#define DEV_PM_OPS     (&rc5t583_rtc_pm_ops)
-#else
-#define DEV_PM_OPS     NULL
 #endif
 
+static SIMPLE_DEV_PM_OPS(rc5t583_rtc_pm_ops, rc5t583_rtc_suspend,
+			rc5t583_rtc_resume);
+
 static struct platform_driver rc5t583_rtc_driver = {
 	.probe		= rc5t583_rtc_probe,
 	.remove		= rc5t583_rtc_remove,
 	.driver		= {
 		.owner	= THIS_MODULE,
 		.name	= "rtc-rc5t583",
-		.pm	= DEV_PM_OPS,
+		.pm	= &rc5t583_rtc_pm_ops,
 	},
 };
 
diff --git a/drivers/rtc/rtc-rp5c01.c b/drivers/rtc/rtc-rp5c01.c
index 359da6d..d25d2f6 100644
--- a/drivers/rtc/rtc-rp5c01.c
+++ b/drivers/rtc/rtc-rp5c01.c
@@ -294,18 +294,7 @@ static struct platform_driver rp5c01_rtc_driver = {
 	.remove	= __exit_p(rp5c01_rtc_remove),
 };
 
-static int __init rp5c01_rtc_init(void)
-{
-	return platform_driver_probe(&rp5c01_rtc_driver, rp5c01_rtc_probe);
-}
-
-static void __exit rp5c01_rtc_fini(void)
-{
-	platform_driver_unregister(&rp5c01_rtc_driver);
-}
-
-module_init(rp5c01_rtc_init);
-module_exit(rp5c01_rtc_fini);
+module_platform_driver_probe(rp5c01_rtc_driver, rp5c01_rtc_probe);
 
 MODULE_AUTHOR("Geert Uytterhoeven <geert@linux-m68k.org>");
 MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-rs5c313.c b/drivers/rtc/rtc-rs5c313.c
index d98ea5b..8089fc6 100644
--- a/drivers/rtc/rtc-rs5c313.c
+++ b/drivers/rtc/rtc-rs5c313.c
@@ -367,7 +367,7 @@ static const struct rtc_class_ops rs5c313_rtc_ops = {
 
 static int rs5c313_rtc_probe(struct platform_device *pdev)
 {
-	struct rtc_device *rtc = rtc_device_register("rs5c313", &pdev->dev,
+	struct rtc_device *rtc = devm_rtc_device_register(&pdev->dev, "rs5c313",
 				&rs5c313_rtc_ops, THIS_MODULE);
 
 	if (IS_ERR(rtc))
@@ -380,10 +380,6 @@ static int rs5c313_rtc_probe(struct platform_device *pdev)
 
 static int rs5c313_rtc_remove(struct platform_device *pdev)
 {
-	struct rtc_device *rtc = platform_get_drvdata( pdev );
-
-	rtc_device_unregister(rtc);
-
 	return 0;
 }
 
diff --git a/drivers/rtc/rtc-rv3029c2.c b/drivers/rtc/rtc-rv3029c2.c
index f8ee8ad..5032c24 100644
--- a/drivers/rtc/rtc-rv3029c2.c
+++ b/drivers/rtc/rtc-rv3029c2.c
@@ -395,9 +395,8 @@ static int rv3029c2_probe(struct i2c_client *client,
 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_EMUL))
 		return -ENODEV;
 
-	rtc = rtc_device_register(client->name,
-				&client->dev, &rv3029c2_rtc_ops,
-				THIS_MODULE);
+	rtc = devm_rtc_device_register(&client->dev, client->name,
+					&rv3029c2_rtc_ops, THIS_MODULE);
 
 	if (IS_ERR(rtc))
 		return PTR_ERR(rtc);
@@ -407,23 +406,14 @@ static int rv3029c2_probe(struct i2c_client *client,
 	rc = rv3029c2_i2c_get_sr(client, buf);
 	if (rc < 0) {
 		dev_err(&client->dev, "reading status failed\n");
-		goto exit_unregister;
+		return rc;
 	}
 
 	return 0;
-
-exit_unregister:
-	rtc_device_unregister(rtc);
-
-	return rc;
 }
 
 static int rv3029c2_remove(struct i2c_client *client)
 {
-	struct rtc_device *rtc = i2c_get_clientdata(client);
-
-	rtc_device_unregister(rtc);
-
 	return 0;
 }
 
diff --git a/drivers/rtc/rtc-rx4581.c b/drivers/rtc/rtc-rx4581.c
index 599ec73..d1b88db 100644
--- a/drivers/rtc/rtc-rx4581.c
+++ b/drivers/rtc/rtc-rx4581.c
@@ -273,8 +273,8 @@ static int rx4581_probe(struct spi_device *spi)
 	if (res != 0)
 		return res;
 
-	rtc = rtc_device_register("rx4581",
-				&spi->dev, &rx4581_rtc_ops, THIS_MODULE);
+	rtc = devm_rtc_device_register(&spi->dev, "rx4581",
+				&rx4581_rtc_ops, THIS_MODULE);
 	if (IS_ERR(rtc))
 		return PTR_ERR(rtc);
 
@@ -284,9 +284,6 @@ static int rx4581_probe(struct spi_device *spi)
 
 static int rx4581_remove(struct spi_device *spi)
 {
-	struct rtc_device *rtc = dev_get_drvdata(&spi->dev);
-
-	rtc_device_unregister(rtc);
 	return 0;
 }
 
diff --git a/drivers/rtc/rtc-rx8581.c b/drivers/rtc/rtc-rx8581.c
index b0c2726..07f3037 100644
--- a/drivers/rtc/rtc-rx8581.c
+++ b/drivers/rtc/rtc-rx8581.c
@@ -240,8 +240,8 @@ static int rx8581_probe(struct i2c_client *client,
 
 	dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n");
 
-	rtc = rtc_device_register(rx8581_driver.driver.name,
-				&client->dev, &rx8581_rtc_ops, THIS_MODULE);
+	rtc = devm_rtc_device_register(&client->dev, rx8581_driver.driver.name,
+					&rx8581_rtc_ops, THIS_MODULE);
 
 	if (IS_ERR(rtc))
 		return PTR_ERR(rtc);
@@ -253,10 +253,6 @@ static int rx8581_probe(struct i2c_client *client,
 
 static int rx8581_remove(struct i2c_client *client)
 {
-	struct rtc_device *rtc = i2c_get_clientdata(client);
-
-	rtc_device_unregister(rtc);
-
 	return 0;
 }
 
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c
index fb994e9..653a4dc 100644
--- a/drivers/rtc/rtc-s3c.c
+++ b/drivers/rtc/rtc-s3c.c
@@ -51,7 +51,6 @@ static struct clk *rtc_clk;
 static void __iomem *s3c_rtc_base;
 static int s3c_rtc_alarmno = NO_IRQ;
 static int s3c_rtc_tickno  = NO_IRQ;
-static bool wake_en;
 static enum s3c_cpu_type s3c_rtc_cpu_type;
 
 static DEFINE_SPINLOCK(s3c_rtc_pie_lock);
@@ -423,10 +422,7 @@ static void s3c_rtc_enable(struct platform_device *pdev, int en)
 
 static int s3c_rtc_remove(struct platform_device *dev)
 {
-	struct rtc_device *rtc = platform_get_drvdata(dev);
-
 	platform_set_drvdata(dev, NULL);
-	rtc_device_unregister(rtc);
 
 	s3c_rtc_setaie(&dev->dev, 0);
 
@@ -511,7 +507,7 @@ static int s3c_rtc_probe(struct platform_device *pdev)
 
 	/* register RTC and exit */
 
-	rtc = rtc_device_register("s3c", &pdev->dev, &s3c_rtcops,
+	rtc = devm_rtc_device_register(&pdev->dev, "s3c", &s3c_rtcops,
 				  THIS_MODULE);
 
 	if (IS_ERR(rtc)) {
@@ -574,7 +570,6 @@ static int s3c_rtc_probe(struct platform_device *pdev)
 
  err_alarm_irq:
 	platform_set_drvdata(pdev, NULL);
-	rtc_device_unregister(rtc);
 
  err_nortc:
 	s3c_rtc_enable(pdev, 0);
@@ -583,14 +578,16 @@ static int s3c_rtc_probe(struct platform_device *pdev)
 	return ret;
 }
 
-#ifdef CONFIG_PM
-
+#ifdef CONFIG_PM_SLEEP
 /* RTC Power management control */
 
 static int ticnt_save, ticnt_en_save;
+static bool wake_en;
 
-static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state)
+static int s3c_rtc_suspend(struct device *dev)
 {
+	struct platform_device *pdev = to_platform_device(dev);
+
 	clk_enable(rtc_clk);
 	/* save TICNT for anyone using periodic interrupts */
 	ticnt_save = readb(s3c_rtc_base + S3C2410_TICNT);
@@ -600,19 +597,20 @@ static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state)
 	}
 	s3c_rtc_enable(pdev, 0);
 
-	if (device_may_wakeup(&pdev->dev) && !wake_en) {
+	if (device_may_wakeup(dev) && !wake_en) {
 		if (enable_irq_wake(s3c_rtc_alarmno) == 0)
 			wake_en = true;
 		else
-			dev_err(&pdev->dev, "enable_irq_wake failed\n");
+			dev_err(dev, "enable_irq_wake failed\n");
 	}
 	clk_disable(rtc_clk);
 
 	return 0;
 }
 
-static int s3c_rtc_resume(struct platform_device *pdev)
+static int s3c_rtc_resume(struct device *dev)
 {
+	struct platform_device *pdev = to_platform_device(dev);
 	unsigned int tmp;
 
 	clk_enable(rtc_clk);
@@ -623,7 +621,7 @@ static int s3c_rtc_resume(struct platform_device *pdev)
 		writew(tmp | ticnt_en_save, s3c_rtc_base + S3C2410_RTCCON);
 	}
 
-	if (device_may_wakeup(&pdev->dev) && wake_en) {
+	if (device_may_wakeup(dev) && wake_en) {
 		disable_irq_wake(s3c_rtc_alarmno);
 		wake_en = false;
 	}
@@ -631,11 +629,10 @@ static int s3c_rtc_resume(struct platform_device *pdev)
 
 	return 0;
 }
-#else
-#define s3c_rtc_suspend NULL
-#define s3c_rtc_resume  NULL
 #endif
 
+static SIMPLE_DEV_PM_OPS(s3c_rtc_pm_ops, s3c_rtc_suspend, s3c_rtc_resume);
+
 #ifdef CONFIG_OF
 static struct s3c_rtc_drv_data s3c_rtc_drv_data_array[] = {
 	[TYPE_S3C2410] = { TYPE_S3C2410 },
@@ -685,12 +682,11 @@ MODULE_DEVICE_TABLE(platform, s3c_rtc_driver_ids);
 static struct platform_driver s3c_rtc_driver = {
 	.probe		= s3c_rtc_probe,
 	.remove		= s3c_rtc_remove,
-	.suspend	= s3c_rtc_suspend,
-	.resume		= s3c_rtc_resume,
 	.id_table	= s3c_rtc_driver_ids,
 	.driver		= {
 		.name	= "s3c-rtc",
 		.owner	= THIS_MODULE,
+		.pm	= &s3c_rtc_pm_ops,
 		.of_match_table	= of_match_ptr(s3c_rtc_dt_match),
 	},
 };
diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c
index 5ec5036..7e0a088 100644
--- a/drivers/rtc/rtc-sa1100.c
+++ b/drivers/rtc/rtc-sa1100.c
@@ -327,7 +327,7 @@ static int sa1100_rtc_remove(struct platform_device *pdev)
 	return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int sa1100_rtc_suspend(struct device *dev)
 {
 	struct sa1100_rtc *info = dev_get_drvdata(dev);
@@ -343,13 +343,11 @@ static int sa1100_rtc_resume(struct device *dev)
 		disable_irq_wake(info->irq_alarm);
 	return 0;
 }
-
-static const struct dev_pm_ops sa1100_rtc_pm_ops = {
-	.suspend	= sa1100_rtc_suspend,
-	.resume		= sa1100_rtc_resume,
-};
 #endif
 
+static SIMPLE_DEV_PM_OPS(sa1100_rtc_pm_ops, sa1100_rtc_suspend,
+			sa1100_rtc_resume);
+
 #ifdef CONFIG_OF
 static struct of_device_id sa1100_rtc_dt_ids[] = {
 	{ .compatible = "mrvl,sa1100-rtc", },
@@ -364,9 +362,7 @@ static struct platform_driver sa1100_rtc_driver = {
 	.remove		= sa1100_rtc_remove,
 	.driver		= {
 		.name	= "sa1100-rtc",
-#ifdef CONFIG_PM
 		.pm	= &sa1100_rtc_pm_ops,
-#endif
 		.of_match_table = of_match_ptr(sa1100_rtc_dt_ids),
 	},
 };
diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c
index e55a763..8d5bd2e 100644
--- a/drivers/rtc/rtc-sh.c
+++ b/drivers/rtc/rtc-sh.c
@@ -790,6 +790,7 @@ static void sh_rtc_set_irq_wake(struct device *dev, int enabled)
 	}
 }
 
+#ifdef CONFIG_PM_SLEEP
 static int sh_rtc_suspend(struct device *dev)
 {
 	if (device_may_wakeup(dev))
@@ -805,33 +806,20 @@ static int sh_rtc_resume(struct device *dev)
 
 	return 0;
 }
+#endif
 
-static const struct dev_pm_ops sh_rtc_dev_pm_ops = {
-	.suspend = sh_rtc_suspend,
-	.resume = sh_rtc_resume,
-};
+static SIMPLE_DEV_PM_OPS(sh_rtc_pm_ops, sh_rtc_suspend, sh_rtc_resume);
 
 static struct platform_driver sh_rtc_platform_driver = {
 	.driver		= {
 		.name	= DRV_NAME,
 		.owner	= THIS_MODULE,
-		.pm	= &sh_rtc_dev_pm_ops,
+		.pm	= &sh_rtc_pm_ops,
 	},
 	.remove		= __exit_p(sh_rtc_remove),
 };
 
-static int __init sh_rtc_init(void)
-{
-	return platform_driver_probe(&sh_rtc_platform_driver, sh_rtc_probe);
-}
-
-static void __exit sh_rtc_exit(void)
-{
-	platform_driver_unregister(&sh_rtc_platform_driver);
-}
-
-module_init(sh_rtc_init);
-module_exit(sh_rtc_exit);
+module_platform_driver_probe(sh_rtc_platform_driver, sh_rtc_probe);
 
 MODULE_DESCRIPTION("SuperH on-chip RTC driver");
 MODULE_VERSION(DRV_VERSION);
diff --git a/drivers/rtc/rtc-snvs.c b/drivers/rtc/rtc-snvs.c
index f7d9070..b04f09a 100644
--- a/drivers/rtc/rtc-snvs.c
+++ b/drivers/rtc/rtc-snvs.c
@@ -283,7 +283,7 @@ static int snvs_rtc_probe(struct platform_device *pdev)
 		return ret;
 	}
 
-	data->rtc = rtc_device_register(pdev->name, &pdev->dev,
+	data->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
 					&snvs_rtc_ops, THIS_MODULE);
 	if (IS_ERR(data->rtc)) {
 		ret = PTR_ERR(data->rtc);
@@ -296,10 +296,6 @@ static int snvs_rtc_probe(struct platform_device *pdev)
 
 static int snvs_rtc_remove(struct platform_device *pdev)
 {
-	struct snvs_rtc_data *data = platform_get_drvdata(pdev);
-
-	rtc_device_unregister(data->rtc);
-
 	return 0;
 }
 
diff --git a/drivers/rtc/rtc-spear.c b/drivers/rtc/rtc-spear.c
index a18c319..db3ef61 100644
--- a/drivers/rtc/rtc-spear.c
+++ b/drivers/rtc/rtc-spear.c
@@ -400,8 +400,8 @@ static int spear_rtc_probe(struct platform_device *pdev)
 	spin_lock_init(&config->lock);
 	platform_set_drvdata(pdev, config);
 
-	config->rtc = rtc_device_register(pdev->name, &pdev->dev,
-			&spear_rtc_ops, THIS_MODULE);
+	config->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
+					&spear_rtc_ops, THIS_MODULE);
 	if (IS_ERR(config->rtc)) {
 		dev_err(&pdev->dev, "can't register RTC device, err %ld\n",
 				PTR_ERR(config->rtc));
@@ -427,7 +427,6 @@ static int spear_rtc_remove(struct platform_device *pdev)
 {
 	struct spear_rtc_config *config = platform_get_drvdata(pdev);
 
-	rtc_device_unregister(config->rtc);
 	spear_rtc_disable_interrupt(config);
 	clk_disable_unprepare(config->clk);
 	device_init_wakeup(&pdev->dev, 0);
diff --git a/drivers/rtc/rtc-starfire.c b/drivers/rtc/rtc-starfire.c
index 5be98bf..987b5ec 100644
--- a/drivers/rtc/rtc-starfire.c
+++ b/drivers/rtc/rtc-starfire.c
@@ -39,8 +39,10 @@ static const struct rtc_class_ops starfire_rtc_ops = {
 
 static int __init starfire_rtc_probe(struct platform_device *pdev)
 {
-	struct rtc_device *rtc = rtc_device_register("starfire", &pdev->dev,
-				     &starfire_rtc_ops, THIS_MODULE);
+	struct rtc_device *rtc;
+
+	rtc = devm_rtc_device_register(&pdev->dev, "starfire",
+				&starfire_rtc_ops, THIS_MODULE);
 	if (IS_ERR(rtc))
 		return PTR_ERR(rtc);
 
@@ -51,10 +53,6 @@ static int __init starfire_rtc_probe(struct platform_device *pdev)
 
 static int __exit starfire_rtc_remove(struct platform_device *pdev)
 {
-	struct rtc_device *rtc = platform_get_drvdata(pdev);
-
-	rtc_device_unregister(rtc);
-
 	return 0;
 }
 
@@ -66,15 +64,4 @@ static struct platform_driver starfire_rtc_driver = {
 	.remove		= __exit_p(starfire_rtc_remove),
 };
 
-static int __init starfire_rtc_init(void)
-{
-	return platform_driver_probe(&starfire_rtc_driver, starfire_rtc_probe);
-}
-
-static void __exit starfire_rtc_exit(void)
-{
-	platform_driver_unregister(&starfire_rtc_driver);
-}
-
-module_init(starfire_rtc_init);
-module_exit(starfire_rtc_exit);
+module_platform_driver_probe(starfire_rtc_driver, starfire_rtc_probe);
diff --git a/drivers/rtc/rtc-stk17ta8.c b/drivers/rtc/rtc-stk17ta8.c
index 7e4a6f6..af5e97e 100644
--- a/drivers/rtc/rtc-stk17ta8.c
+++ b/drivers/rtc/rtc-stk17ta8.c
@@ -336,14 +336,13 @@ static int stk17ta8_rtc_probe(struct platform_device *pdev)
 		}
 	}
 
-	pdata->rtc = rtc_device_register(pdev->name, &pdev->dev,
+	pdata->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
 				  &stk17ta8_rtc_ops, THIS_MODULE);
 	if (IS_ERR(pdata->rtc))
 		return PTR_ERR(pdata->rtc);
 
 	ret = sysfs_create_bin_file(&pdev->dev.kobj, &stk17ta8_nvram_attr);
-	if (ret)
-		rtc_device_unregister(pdata->rtc);
+
 	return ret;
 }
 
@@ -352,7 +351,6 @@ static int stk17ta8_rtc_remove(struct platform_device *pdev)
 	struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
 
 	sysfs_remove_bin_file(&pdev->dev.kobj, &stk17ta8_nvram_attr);
-	rtc_device_unregister(pdata->rtc);
 	if (pdata->irq > 0)
 		writeb(0, pdata->ioaddr + RTC_INTERRUPTS);
 	return 0;
diff --git a/drivers/rtc/rtc-stmp3xxx.c b/drivers/rtc/rtc-stmp3xxx.c
index 98f0d3c..67d2612 100644
--- a/drivers/rtc/rtc-stmp3xxx.c
+++ b/drivers/rtc/rtc-stmp3xxx.c
@@ -30,8 +30,6 @@
 #include <linux/stmp_device.h>
 #include <linux/stmp3xxx_rtc_wdt.h>
 
-#include <mach/common.h>
-
 #define STMP3XXX_RTC_CTRL			0x0
 #define STMP3XXX_RTC_CTRL_SET			0x4
 #define STMP3XXX_RTC_CTRL_CLR			0x8
@@ -271,7 +269,7 @@ static int stmp3xxx_rtc_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, rtc_data);
 
-	mxs_reset_block(rtc_data->io);
+	stmp_reset_block(rtc_data->io);
 	writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN |
 			STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN |
 			STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE,
@@ -319,7 +317,7 @@ static int stmp3xxx_rtc_resume(struct platform_device *dev)
 {
 	struct stmp3xxx_rtc_data *rtc_data = platform_get_drvdata(dev);
 
-	mxs_reset_block(rtc_data->io);
+	stmp_reset_block(rtc_data->io);
 	writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN |
 			STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN |
 			STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE,
diff --git a/drivers/rtc/rtc-sun4v.c b/drivers/rtc/rtc-sun4v.c
index 59b5c2d..ce42e5f 100644
--- a/drivers/rtc/rtc-sun4v.c
+++ b/drivers/rtc/rtc-sun4v.c
@@ -81,8 +81,10 @@ static const struct rtc_class_ops sun4v_rtc_ops = {
 
 static int __init sun4v_rtc_probe(struct platform_device *pdev)
 {
-	struct rtc_device *rtc = rtc_device_register("sun4v", &pdev->dev,
-				     &sun4v_rtc_ops, THIS_MODULE);
+	struct rtc_device *rtc;
+
+	rtc = devm_rtc_device_register(&pdev->dev, "sun4v",
+				&sun4v_rtc_ops, THIS_MODULE);
 	if (IS_ERR(rtc))
 		return PTR_ERR(rtc);
 
@@ -92,9 +94,6 @@ static int __init sun4v_rtc_probe(struct platform_device *pdev)
 
 static int __exit sun4v_rtc_remove(struct platform_device *pdev)
 {
-	struct rtc_device *rtc = platform_get_drvdata(pdev);
-
-	rtc_device_unregister(rtc);
 	return 0;
 }
 
@@ -106,18 +105,7 @@ static struct platform_driver sun4v_rtc_driver = {
 	.remove		= __exit_p(sun4v_rtc_remove),
 };
 
-static int __init sun4v_rtc_init(void)
-{
-	return platform_driver_probe(&sun4v_rtc_driver, sun4v_rtc_probe);
-}
-
-static void __exit sun4v_rtc_exit(void)
-{
-	platform_driver_unregister(&sun4v_rtc_driver);
-}
-
-module_init(sun4v_rtc_init);
-module_exit(sun4v_rtc_exit);
+module_platform_driver_probe(sun4v_rtc_driver, sun4v_rtc_probe);
 
 MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
 MODULE_DESCRIPTION("SUN4V RTC driver");
diff --git a/drivers/rtc/rtc-tegra.c b/drivers/rtc/rtc-tegra.c
index 7c03375..a34315d 100644
--- a/drivers/rtc/rtc-tegra.c
+++ b/drivers/rtc/rtc-tegra.c
@@ -26,6 +26,7 @@
 #include <linux/delay.h>
 #include <linux/rtc.h>
 #include <linux/platform_device.h>
+#include <linux/pm.h>
 
 /* set to 1 = busy every eight 32kHz clocks during copy of sec+msec to AHB */
 #define TEGRA_RTC_REG_BUSY			0x004
@@ -309,7 +310,7 @@ static const struct of_device_id tegra_rtc_dt_match[] = {
 };
 MODULE_DEVICE_TABLE(of, tegra_rtc_dt_match);
 
-static int tegra_rtc_probe(struct platform_device *pdev)
+static int __init tegra_rtc_probe(struct platform_device *pdev)
 {
 	struct tegra_rtc_info *info;
 	struct resource *res;
@@ -348,53 +349,35 @@ static int tegra_rtc_probe(struct platform_device *pdev)
 
 	device_init_wakeup(&pdev->dev, 1);
 
-	info->rtc_dev = rtc_device_register(
-		pdev->name, &pdev->dev, &tegra_rtc_ops, THIS_MODULE);
+	info->rtc_dev = devm_rtc_device_register(&pdev->dev,
+				dev_name(&pdev->dev), &tegra_rtc_ops,
+				THIS_MODULE);
 	if (IS_ERR(info->rtc_dev)) {
 		ret = PTR_ERR(info->rtc_dev);
-		info->rtc_dev = NULL;
-		dev_err(&pdev->dev,
-			"Unable to register device (err=%d).\n",
+		dev_err(&pdev->dev, "Unable to register device (err=%d).\n",
 			ret);
 		return ret;
 	}
 
 	ret = devm_request_irq(&pdev->dev, info->tegra_rtc_irq,
 			tegra_rtc_irq_handler, IRQF_TRIGGER_HIGH,
-			"rtc alarm", &pdev->dev);
+			dev_name(&pdev->dev), &pdev->dev);
 	if (ret) {
 		dev_err(&pdev->dev,
 			"Unable to request interrupt for device (err=%d).\n",
 			ret);
-		goto err_dev_unreg;
+		return ret;
 	}
 
 	dev_notice(&pdev->dev, "Tegra internal Real Time Clock\n");
 
 	return 0;
-
-err_dev_unreg:
-	rtc_device_unregister(info->rtc_dev);
-
-	return ret;
 }
 
-static int tegra_rtc_remove(struct platform_device *pdev)
+#ifdef CONFIG_PM_SLEEP
+static int tegra_rtc_suspend(struct device *dev)
 {
-	struct tegra_rtc_info *info = platform_get_drvdata(pdev);
-
-	rtc_device_unregister(info->rtc_dev);
-
-	platform_set_drvdata(pdev, NULL);
-
-	return 0;
-}
-
-#ifdef CONFIG_PM
-static int tegra_rtc_suspend(struct platform_device *pdev, pm_message_t state)
-{
-	struct device *dev = &pdev->dev;
-	struct tegra_rtc_info *info = platform_get_drvdata(pdev);
+	struct tegra_rtc_info *info = dev_get_drvdata(dev);
 
 	tegra_rtc_wait_while_busy(dev);
 
@@ -416,10 +399,9 @@ static int tegra_rtc_suspend(struct platform_device *pdev, pm_message_t state)
 	return 0;
 }
 
-static int tegra_rtc_resume(struct platform_device *pdev)
+static int tegra_rtc_resume(struct device *dev)
 {
-	struct device *dev = &pdev->dev;
-	struct tegra_rtc_info *info = platform_get_drvdata(pdev);
+	struct tegra_rtc_info *info = dev_get_drvdata(dev);
 
 	dev_vdbg(dev, "Resume (device_may_wakeup=%d)\n",
 		device_may_wakeup(dev));
@@ -431,6 +413,8 @@ static int tegra_rtc_resume(struct platform_device *pdev)
 }
 #endif
 
+static SIMPLE_DEV_PM_OPS(tegra_rtc_pm_ops, tegra_rtc_suspend, tegra_rtc_resume);
+
 static void tegra_rtc_shutdown(struct platform_device *pdev)
 {
 	dev_vdbg(&pdev->dev, "disabling interrupts.\n");
@@ -439,30 +423,16 @@ static void tegra_rtc_shutdown(struct platform_device *pdev)
 
 MODULE_ALIAS("platform:tegra_rtc");
 static struct platform_driver tegra_rtc_driver = {
-	.remove		= tegra_rtc_remove,
 	.shutdown	= tegra_rtc_shutdown,
 	.driver		= {
 		.name	= "tegra_rtc",
 		.owner	= THIS_MODULE,
 		.of_match_table = tegra_rtc_dt_match,
+		.pm	= &tegra_rtc_pm_ops,
 	},
-#ifdef CONFIG_PM
-	.suspend	= tegra_rtc_suspend,
-	.resume		= tegra_rtc_resume,
-#endif
 };
 
-static int __init tegra_rtc_init(void)
-{
-	return platform_driver_probe(&tegra_rtc_driver, tegra_rtc_probe);
-}
-module_init(tegra_rtc_init);
-
-static void __exit tegra_rtc_exit(void)
-{
-	platform_driver_unregister(&tegra_rtc_driver);
-}
-module_exit(tegra_rtc_exit);
+module_platform_driver_probe(tegra_rtc_driver, tegra_rtc_probe);
 
 MODULE_AUTHOR("Jon Mayo <jmayo@nvidia.com>");
 MODULE_DESCRIPTION("driver for Tegra internal RTC");
diff --git a/drivers/rtc/rtc-test.c b/drivers/rtc/rtc-test.c
index b92e0f6..7746e65 100644
--- a/drivers/rtc/rtc-test.c
+++ b/drivers/rtc/rtc-test.c
@@ -99,8 +99,10 @@ static DEVICE_ATTR(irq, S_IRUGO | S_IWUSR, test_irq_show, test_irq_store);
 static int test_probe(struct platform_device *plat_dev)
 {
 	int err;
-	struct rtc_device *rtc = rtc_device_register("test", &plat_dev->dev,
-						&test_rtc_ops, THIS_MODULE);
+	struct rtc_device *rtc;
+
+	rtc = devm_rtc_device_register(&plat_dev->dev, "test",
+				&test_rtc_ops, THIS_MODULE);
 	if (IS_ERR(rtc)) {
 		err = PTR_ERR(rtc);
 		return err;
@@ -115,15 +117,11 @@ static int test_probe(struct platform_device *plat_dev)
 	return 0;
 
 err:
-	rtc_device_unregister(rtc);
 	return err;
 }
 
 static int test_remove(struct platform_device *plat_dev)
 {
-	struct rtc_device *rtc = platform_get_drvdata(plat_dev);
-
-	rtc_device_unregister(rtc);
 	device_remove_file(&plat_dev->dev, &dev_attr_irq);
 
 	return 0;
diff --git a/drivers/rtc/rtc-tile.c b/drivers/rtc/rtc-tile.c
index 62db484..249b653 100644
--- a/drivers/rtc/rtc-tile.c
+++ b/drivers/rtc/rtc-tile.c
@@ -80,8 +80,8 @@ static int tile_rtc_probe(struct platform_device *dev)
 {
 	struct rtc_device *rtc;
 
-	rtc = rtc_device_register("tile",
-				  &dev->dev, &tile_rtc_ops, THIS_MODULE);
+	rtc = devm_rtc_device_register(&dev->dev, "tile",
+				&tile_rtc_ops, THIS_MODULE);
 
 	if (IS_ERR(rtc))
 		return PTR_ERR(rtc);
@@ -96,11 +96,6 @@ static int tile_rtc_probe(struct platform_device *dev)
  */
 static int tile_rtc_remove(struct platform_device *dev)
 {
-	struct rtc_device *rtc = platform_get_drvdata(dev);
-
-	if (rtc)
-		rtc_device_unregister(rtc);
-
 	platform_set_drvdata(dev, NULL);
 
 	return 0;
diff --git a/drivers/rtc/rtc-tps6586x.c b/drivers/rtc/rtc-tps6586x.c
index aab4e8c..459c2ff 100644
--- a/drivers/rtc/rtc-tps6586x.c
+++ b/drivers/rtc/rtc-tps6586x.c
@@ -274,7 +274,7 @@ static int tps6586x_rtc_probe(struct platform_device *pdev)
 	}
 
 	platform_set_drvdata(pdev, rtc);
-	rtc->rtc = rtc_device_register(dev_name(&pdev->dev), &pdev->dev,
+	rtc->rtc = devm_rtc_device_register(&pdev->dev, dev_name(&pdev->dev),
 				       &tps6586x_rtc_ops, THIS_MODULE);
 	if (IS_ERR(rtc->rtc)) {
 		ret = PTR_ERR(rtc->rtc);
@@ -289,15 +289,12 @@ static int tps6586x_rtc_probe(struct platform_device *pdev)
 	if (ret < 0) {
 		dev_err(&pdev->dev, "request IRQ(%d) failed with ret %d\n",
 				rtc->irq, ret);
-		goto fail_req_irq;
+		goto fail_rtc_register;
 	}
 	disable_irq(rtc->irq);
 	device_set_wakeup_capable(&pdev->dev, 1);
 	return 0;
 
-fail_req_irq:
-	rtc_device_unregister(rtc->rtc);
-
 fail_rtc_register:
 	tps6586x_update(tps_dev, RTC_CTRL, 0,
 		RTC_ENABLE | OSC_SRC_SEL | PRE_BYPASS | CL_SEL_MASK);
@@ -306,12 +303,10 @@ fail_rtc_register:
 
 static int tps6586x_rtc_remove(struct platform_device *pdev)
 {
-	struct tps6586x_rtc *rtc = platform_get_drvdata(pdev);
 	struct device *tps_dev = to_tps6586x_dev(&pdev->dev);
 
 	tps6586x_update(tps_dev, RTC_CTRL, 0,
 		RTC_ENABLE | OSC_SRC_SEL | PRE_BYPASS | CL_SEL_MASK);
-	rtc_device_unregister(rtc->rtc);
 	return 0;
 }
 
@@ -335,9 +330,8 @@ static int tps6586x_rtc_resume(struct device *dev)
 }
 #endif
 
-static const struct dev_pm_ops tps6586x_pm_ops = {
-	SET_SYSTEM_SLEEP_PM_OPS(tps6586x_rtc_suspend, tps6586x_rtc_resume)
-};
+static SIMPLE_DEV_PM_OPS(tps6586x_pm_ops, tps6586x_rtc_suspend,
+			tps6586x_rtc_resume);
 
 static struct platform_driver tps6586x_rtc_driver = {
 	.driver	= {
diff --git a/drivers/rtc/rtc-tps65910.c b/drivers/rtc/rtc-tps65910.c
index 8bd8115..a9caf04 100644
--- a/drivers/rtc/rtc-tps65910.c
+++ b/drivers/rtc/rtc-tps65910.c
@@ -263,7 +263,7 @@ static int tps65910_rtc_probe(struct platform_device *pdev)
 	if (irq <= 0) {
 		dev_warn(&pdev->dev, "Wake up is not possible as irq = %d\n",
 			irq);
-		return ret;
+		return -ENXIO;
 	}
 
 	ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
@@ -276,7 +276,7 @@ static int tps65910_rtc_probe(struct platform_device *pdev)
 	tps_rtc->irq = irq;
 	device_set_wakeup_capable(&pdev->dev, 1);
 
-	tps_rtc->rtc = rtc_device_register(pdev->name, &pdev->dev,
+	tps_rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
 		&tps65910_rtc_ops, THIS_MODULE);
 	if (IS_ERR(tps_rtc->rtc)) {
 		ret = PTR_ERR(tps_rtc->rtc);
@@ -295,12 +295,8 @@ static int tps65910_rtc_probe(struct platform_device *pdev)
  */
 static int tps65910_rtc_remove(struct platform_device *pdev)
 {
-	/* leave rtc running, but disable irqs */
-	struct tps65910_rtc *tps_rtc = platform_get_drvdata(pdev);
-
 	tps65910_rtc_alarm_irq_enable(&pdev->dev, 0);
 
-	rtc_device_unregister(tps_rtc->rtc);
 	return 0;
 }
 
@@ -324,9 +320,8 @@ static int tps65910_rtc_resume(struct device *dev)
 }
 #endif
 
-static const struct dev_pm_ops tps65910_rtc_pm_ops = {
-	SET_SYSTEM_SLEEP_PM_OPS(tps65910_rtc_suspend, tps65910_rtc_resume)
-};
+static SIMPLE_DEV_PM_OPS(tps65910_rtc_pm_ops, tps65910_rtc_suspend,
+			tps65910_rtc_resume);
 
 static struct platform_driver tps65910_rtc_driver = {
 	.probe		= tps65910_rtc_probe,
diff --git a/drivers/rtc/rtc-tps80031.c b/drivers/rtc/rtc-tps80031.c
index 9aaf8aa..72662ea 100644
--- a/drivers/rtc/rtc-tps80031.c
+++ b/drivers/rtc/rtc-tps80031.c
@@ -277,7 +277,7 @@ static int tps80031_rtc_probe(struct platform_device *pdev)
 		return ret;
 	}
 
-	rtc->rtc = rtc_device_register(pdev->name, &pdev->dev,
+	rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
 			       &tps80031_rtc_ops, THIS_MODULE);
 	if (IS_ERR(rtc->rtc)) {
 		ret = PTR_ERR(rtc->rtc);
@@ -292,7 +292,6 @@ static int tps80031_rtc_probe(struct platform_device *pdev)
 	if (ret < 0) {
 		dev_err(&pdev->dev, "request IRQ:%d failed, err = %d\n",
 			 rtc->irq, ret);
-		rtc_device_unregister(rtc->rtc);
 		return ret;
 	}
 	device_set_wakeup_capable(&pdev->dev, 1);
@@ -301,9 +300,6 @@ static int tps80031_rtc_probe(struct platform_device *pdev)
 
 static int tps80031_rtc_remove(struct platform_device *pdev)
 {
-	struct tps80031_rtc *rtc = platform_get_drvdata(pdev);
-
-	rtc_device_unregister(rtc->rtc);
 	return 0;
 }
 
@@ -327,9 +323,8 @@ static int tps80031_rtc_resume(struct device *dev)
 };
 #endif
 
-static const struct dev_pm_ops tps80031_pm_ops = {
-	SET_SYSTEM_SLEEP_PM_OPS(tps80031_rtc_suspend, tps80031_rtc_resume)
-};
+static SIMPLE_DEV_PM_OPS(tps80031_pm_ops, tps80031_rtc_suspend,
+			tps80031_rtc_resume);
 
 static struct platform_driver tps80031_rtc_driver = {
 	.driver	= {
diff --git a/drivers/rtc/rtc-tx4939.c b/drivers/rtc/rtc-tx4939.c
index a12bfac..f9a0677 100644
--- a/drivers/rtc/rtc-tx4939.c
+++ b/drivers/rtc/rtc-tx4939.c
@@ -268,14 +268,13 @@ static int __init tx4939_rtc_probe(struct platform_device *pdev)
 	if (devm_request_irq(&pdev->dev, irq, tx4939_rtc_interrupt,
 			     0, pdev->name, &pdev->dev) < 0)
 		return -EBUSY;
-	rtc = rtc_device_register(pdev->name, &pdev->dev,
+	rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
 				  &tx4939_rtc_ops, THIS_MODULE);
 	if (IS_ERR(rtc))
 		return PTR_ERR(rtc);
 	pdata->rtc = rtc;
 	ret = sysfs_create_bin_file(&pdev->dev.kobj, &tx4939_rtc_nvram_attr);
-	if (ret)
-		rtc_device_unregister(rtc);
+
 	return ret;
 }
 
@@ -284,7 +283,6 @@ static int __exit tx4939_rtc_remove(struct platform_device *pdev)
 	struct tx4939rtc_plat_data *pdata = platform_get_drvdata(pdev);
 
 	sysfs_remove_bin_file(&pdev->dev.kobj, &tx4939_rtc_nvram_attr);
-	rtc_device_unregister(pdata->rtc);
 	spin_lock_irq(&pdata->lock);
 	tx4939_rtc_cmd(pdata->rtcreg, TX4939_RTCCTL_COMMAND_NOP);
 	spin_unlock_irq(&pdata->lock);
@@ -299,18 +297,7 @@ static struct platform_driver tx4939_rtc_driver = {
 	},
 };
 
-static int __init tx4939rtc_init(void)
-{
-	return platform_driver_probe(&tx4939_rtc_driver, tx4939_rtc_probe);
-}
-
-static void __exit tx4939rtc_exit(void)
-{
-	platform_driver_unregister(&tx4939_rtc_driver);
-}
-
-module_init(tx4939rtc_init);
-module_exit(tx4939rtc_exit);
+module_platform_driver_probe(tx4939_rtc_driver, tx4939_rtc_probe);
 
 MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>");
 MODULE_DESCRIPTION("TX4939 internal RTC driver");
diff --git a/drivers/rtc/rtc-v3020.c b/drivers/rtc/rtc-v3020.c
index bca5d67..600798c 100644
--- a/drivers/rtc/rtc-v3020.c
+++ b/drivers/rtc/rtc-v3020.c
@@ -49,18 +49,13 @@ struct v3020_chip_ops {
 #define V3020_RD	2
 #define V3020_IO	3
 
-struct v3020_gpio {
-	const char *name;
-	unsigned int gpio;
-};
-
 struct v3020 {
 	/* MMIO access */
 	void __iomem *ioaddress;
 	int leftshift;
 
 	/* GPIO access */
-	struct v3020_gpio *gpio;
+	struct gpio *gpio;
 
 	struct v3020_chip_ops *ops;
 
@@ -107,48 +102,40 @@ static struct v3020_chip_ops v3020_mmio_ops = {
 	.write_bit	= v3020_mmio_write_bit,
 };
 
-static struct v3020_gpio v3020_gpio[] = {
-	{ "RTC CS", 0 },
-	{ "RTC WR", 0 },
-	{ "RTC RD", 0 },
-	{ "RTC IO", 0 },
+static struct gpio v3020_gpio[] = {
+	{ 0, GPIOF_OUT_INIT_HIGH, "RTC CS"},
+	{ 0, GPIOF_OUT_INIT_HIGH, "RTC WR"},
+	{ 0, GPIOF_OUT_INIT_HIGH, "RTC RD"},
+	{ 0, GPIOF_OUT_INIT_HIGH, "RTC IO"},
 };
 
 static int v3020_gpio_map(struct v3020 *chip, struct platform_device *pdev,
 			  struct v3020_platform_data *pdata)
 {
-	int i, err;
+	int err;
 
 	v3020_gpio[V3020_CS].gpio = pdata->gpio_cs;
 	v3020_gpio[V3020_WR].gpio = pdata->gpio_wr;
 	v3020_gpio[V3020_RD].gpio = pdata->gpio_rd;
 	v3020_gpio[V3020_IO].gpio = pdata->gpio_io;
 
-	for (i = 0; i < ARRAY_SIZE(v3020_gpio); i++) {
-		err = gpio_request(v3020_gpio[i].gpio, v3020_gpio[i].name);
-		if (err)
-			goto err_request;
-
-		gpio_direction_output(v3020_gpio[i].gpio, 1);
-	}
+	err = gpio_request_array(v3020_gpio, ARRAY_SIZE(v3020_gpio));
+	if (err)
+		goto err_request;
 
 	chip->gpio = v3020_gpio;
 
 	return 0;
 
 err_request:
-	while (--i >= 0)
-		gpio_free(v3020_gpio[i].gpio);
+	gpio_free_array(v3020_gpio, ARRAY_SIZE(v3020_gpio));
 
 	return err;
 }
 
 static void v3020_gpio_unmap(struct v3020 *chip)
 {
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(v3020_gpio); i++)
-		gpio_free(v3020_gpio[i].gpio);
+	gpio_free_array(v3020_gpio, ARRAY_SIZE(v3020_gpio));
 }
 
 static void v3020_gpio_write_bit(struct v3020 *chip, unsigned char bit)
diff --git a/drivers/rtc/rtc-vt8500.c b/drivers/rtc/rtc-vt8500.c
index a000bc0..d89efee 100644
--- a/drivers/rtc/rtc-vt8500.c
+++ b/drivers/rtc/rtc-vt8500.c
@@ -252,7 +252,7 @@ static int vt8500_rtc_probe(struct platform_device *pdev)
 	writel(VT8500_RTC_CR_ENABLE,
 	       vt8500_rtc->regbase + VT8500_RTC_CR);
 
-	vt8500_rtc->rtc = rtc_device_register("vt8500-rtc", &pdev->dev,
+	vt8500_rtc->rtc = devm_rtc_device_register(&pdev->dev, "vt8500-rtc",
 					      &vt8500_rtc_ops, THIS_MODULE);
 	if (IS_ERR(vt8500_rtc->rtc)) {
 		ret = PTR_ERR(vt8500_rtc->rtc);
@@ -266,13 +266,11 @@ static int vt8500_rtc_probe(struct platform_device *pdev)
 	if (ret < 0) {
 		dev_err(&pdev->dev, "can't get irq %i, err %d\n",
 			vt8500_rtc->irq_alarm, ret);
-		goto err_unreg;
+		goto err_return;
 	}
 
 	return 0;
 
-err_unreg:
-	rtc_device_unregister(vt8500_rtc->rtc);
 err_return:
 	return ret;
 }
@@ -281,8 +279,6 @@ static int vt8500_rtc_remove(struct platform_device *pdev)
 {
 	struct vt8500_rtc *vt8500_rtc = platform_get_drvdata(pdev);
 
-	rtc_device_unregister(vt8500_rtc->rtc);
-
 	/* Disable alarm matching */
 	writel(0, vt8500_rtc->regbase + VT8500_RTC_IS);
 
diff --git a/drivers/rtc/rtc-wm831x.c b/drivers/rtc/rtc-wm831x.c
index 2f0ac7b..8d65b94 100644
--- a/drivers/rtc/rtc-wm831x.c
+++ b/drivers/rtc/rtc-wm831x.c
@@ -436,7 +436,7 @@ static int wm831x_rtc_probe(struct platform_device *pdev)
 
 	device_init_wakeup(&pdev->dev, 1);
 
-	wm831x_rtc->rtc = rtc_device_register("wm831x", &pdev->dev,
+	wm831x_rtc->rtc = devm_rtc_device_register(&pdev->dev, "wm831x",
 					      &wm831x_rtc_ops, THIS_MODULE);
 	if (IS_ERR(wm831x_rtc->rtc)) {
 		ret = PTR_ERR(wm831x_rtc->rtc);
@@ -462,10 +462,6 @@ err:
 
 static int wm831x_rtc_remove(struct platform_device *pdev)
 {
-	struct wm831x_rtc *wm831x_rtc = platform_get_drvdata(pdev);
-
-	rtc_device_unregister(wm831x_rtc->rtc);
-
 	return 0;
 }
 
diff --git a/drivers/rtc/rtc-wm8350.c b/drivers/rtc/rtc-wm8350.c
index 8ad86ae..fa247de 100644
--- a/drivers/rtc/rtc-wm8350.c
+++ b/drivers/rtc/rtc-wm8350.c
@@ -339,7 +339,7 @@ static const struct rtc_class_ops wm8350_rtc_ops = {
 	.alarm_irq_enable = wm8350_rtc_alarm_irq_enable,
 };
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int wm8350_rtc_suspend(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
@@ -375,10 +375,6 @@ static int wm8350_rtc_resume(struct device *dev)
 
 	return 0;
 }
-
-#else
-#define wm8350_rtc_suspend NULL
-#define wm8350_rtc_resume NULL
 #endif
 
 static int wm8350_rtc_probe(struct platform_device *pdev)
@@ -439,8 +435,8 @@ static int wm8350_rtc_probe(struct platform_device *pdev)
 
 	device_init_wakeup(&pdev->dev, 1);
 
-	wm_rtc->rtc = rtc_device_register("wm8350", &pdev->dev,
-					  &wm8350_rtc_ops, THIS_MODULE);
+	wm_rtc->rtc = devm_rtc_device_register(&pdev->dev, "wm8350",
+					&wm8350_rtc_ops, THIS_MODULE);
 	if (IS_ERR(wm_rtc->rtc)) {
 		ret = PTR_ERR(wm_rtc->rtc);
 		dev_err(&pdev->dev, "failed to register RTC: %d\n", ret);
@@ -462,20 +458,15 @@ static int wm8350_rtc_probe(struct platform_device *pdev)
 static int wm8350_rtc_remove(struct platform_device *pdev)
 {
 	struct wm8350 *wm8350 = platform_get_drvdata(pdev);
-	struct wm8350_rtc *wm_rtc = &wm8350->rtc;
 
 	wm8350_free_irq(wm8350, WM8350_IRQ_RTC_SEC, wm8350);
 	wm8350_free_irq(wm8350, WM8350_IRQ_RTC_ALM, wm8350);
 
-	rtc_device_unregister(wm_rtc->rtc);
-
 	return 0;
 }
 
-static struct dev_pm_ops wm8350_rtc_pm_ops = {
-	.suspend = wm8350_rtc_suspend,
-	.resume = wm8350_rtc_resume,
-};
+static SIMPLE_DEV_PM_OPS(wm8350_rtc_pm_ops, wm8350_rtc_suspend,
+			wm8350_rtc_resume);
 
 static struct platform_driver wm8350_rtc_driver = {
 	.probe = wm8350_rtc_probe,
diff --git a/drivers/rtc/rtc-x1205.c b/drivers/rtc/rtc-x1205.c
index f36e59c..fa9b067 100644
--- a/drivers/rtc/rtc-x1205.c
+++ b/drivers/rtc/rtc-x1205.c
@@ -630,8 +630,8 @@ static int x1205_probe(struct i2c_client *client,
 
 	dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n");
 
-	rtc = rtc_device_register(x1205_driver.driver.name, &client->dev,
-				&x1205_rtc_ops, THIS_MODULE);
+	rtc = devm_rtc_device_register(&client->dev, x1205_driver.driver.name,
+					&x1205_rtc_ops, THIS_MODULE);
 
 	if (IS_ERR(rtc))
 		return PTR_ERR(rtc);
@@ -653,21 +653,13 @@ static int x1205_probe(struct i2c_client *client,
 
 	err = x1205_sysfs_register(&client->dev);
 	if (err)
-		goto exit_devreg;
+		return err;
 
 	return 0;
-
-exit_devreg:
-	rtc_device_unregister(rtc);
-
-	return err;
 }
 
 static int x1205_remove(struct i2c_client *client)
 {
-	struct rtc_device *rtc = i2c_get_clientdata(client);
-
-	rtc_device_unregister(rtc);
 	x1205_sysfs_unregister(&client->dev);
 	return 0;
 }
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c
index c196827..a71bb8a 100644
--- a/drivers/s390/block/dasd_devmap.c
+++ b/drivers/s390/block/dasd_devmap.c
@@ -410,8 +410,7 @@ dasd_add_busid(const char *bus_id, int features)
 	struct dasd_devmap *devmap, *new, *tmp;
 	int hash;
 
-	new = (struct dasd_devmap *)
-		kzalloc(sizeof(struct dasd_devmap), GFP_KERNEL);
+	new = kzalloc(sizeof(struct dasd_devmap), GFP_KERNEL);
 	if (!new)
 		return ERR_PTR(-ENOMEM);
 	spin_lock(&dasd_devmap_lock);
diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c
index b6ad0de..12d08b4 100644
--- a/drivers/s390/block/dcssblk.c
+++ b/drivers/s390/block/dcssblk.c
@@ -826,8 +826,7 @@ dcssblk_make_request(struct request_queue *q, struct bio *bio)
 	if ((bio->bi_sector & 7) != 0 || (bio->bi_size & 4095) != 0)
 		/* Request is not page-aligned. */
 		goto fail;
-	if (((bio->bi_size >> 9) + bio->bi_sector)
-			> get_capacity(bio->bi_bdev->bd_disk)) {
+	if (bio_end_sector(bio) > get_capacity(bio->bi_bdev->bd_disk)) {
 		/* Request beyond end of DCSS segment. */
 		goto fail;
 	}
diff --git a/drivers/s390/block/scm_blk.c b/drivers/s390/block/scm_blk.c
index 5ac9c93..e9b9c83 100644
--- a/drivers/s390/block/scm_blk.c
+++ b/drivers/s390/block/scm_blk.c
@@ -307,7 +307,7 @@ static void scm_blk_handle_error(struct scm_request *scmrq)
 	case EQC_WR_PROHIBIT:
 		spin_lock_irqsave(&bdev->lock, flags);
 		if (bdev->state != SCM_WR_PROHIBIT)
-			pr_info("%lu: Write access to the SCM increment is suspended\n",
+			pr_info("%lx: Write access to the SCM increment is suspended\n",
 				(unsigned long) bdev->scmdev->address);
 		bdev->state = SCM_WR_PROHIBIT;
 		spin_unlock_irqrestore(&bdev->lock, flags);
@@ -445,7 +445,7 @@ void scm_blk_set_available(struct scm_blk_dev *bdev)
 
 	spin_lock_irqsave(&bdev->lock, flags);
 	if (bdev->state == SCM_WR_PROHIBIT)
-		pr_info("%lu: Write access to the SCM increment is restored\n",
+		pr_info("%lx: Write access to the SCM increment is restored\n",
 			(unsigned long) bdev->scmdev->address);
 	bdev->state = SCM_OPER;
 	spin_unlock_irqrestore(&bdev->lock, flags);
@@ -463,12 +463,15 @@ static int __init scm_blk_init(void)
 		goto out;
 
 	scm_major = ret;
-	if (scm_alloc_rqs(nr_requests))
+	ret = scm_alloc_rqs(nr_requests);
+	if (ret)
 		goto out_unreg;
 
 	scm_debug = debug_register("scm_log", 16, 1, 16);
-	if (!scm_debug)
+	if (!scm_debug) {
+		ret = -ENOMEM;
 		goto out_free;
+	}
 
 	debug_register_view(scm_debug, &debug_hex_ascii_view);
 	debug_set_level(scm_debug, 2);
diff --git a/drivers/s390/block/scm_drv.c b/drivers/s390/block/scm_drv.c
index 5f6180d..c98cf52 100644
--- a/drivers/s390/block/scm_drv.c
+++ b/drivers/s390/block/scm_drv.c
@@ -19,7 +19,7 @@ static void scm_notify(struct scm_device *scmdev, enum scm_event event)
 
 	switch (event) {
 	case SCM_CHANGE:
-		pr_info("%lu: The capabilities of the SCM increment changed\n",
+		pr_info("%lx: The capabilities of the SCM increment changed\n",
 			(unsigned long) scmdev->address);
 		SCM_LOG(2, "State changed");
 		SCM_LOG_STATE(2, scmdev);
diff --git a/drivers/s390/char/monreader.c b/drivers/s390/char/monreader.c
index f4ff515..0da3ae3 100644
--- a/drivers/s390/char/monreader.c
+++ b/drivers/s390/char/monreader.c
@@ -174,8 +174,7 @@ static void mon_free_mem(struct mon_private *monpriv)
 	int i;
 
 	for (i = 0; i < MON_MSGLIM; i++)
-		if (monpriv->msg_array[i])
-			kfree(monpriv->msg_array[i]);
+		kfree(monpriv->msg_array[i]);
 	kfree(monpriv);
 }
 
diff --git a/drivers/s390/char/sclp_tty.c b/drivers/s390/char/sclp_tty.c
index 14b4cb8..7ed7a59 100644
--- a/drivers/s390/char/sclp_tty.c
+++ b/drivers/s390/char/sclp_tty.c
@@ -107,7 +107,6 @@ sclp_tty_write_room (struct tty_struct *tty)
 static void
 sclp_ttybuf_callback(struct sclp_buffer *buffer, int rc)
 {
-	struct tty_struct *tty;
 	unsigned long flags;
 	void *page;
 
@@ -125,12 +124,8 @@ sclp_ttybuf_callback(struct sclp_buffer *buffer, int rc)
 					    struct sclp_buffer, list);
 		spin_unlock_irqrestore(&sclp_tty_lock, flags);
 	} while (buffer && sclp_emit_buffer(buffer, sclp_ttybuf_callback));
-	/* check if the tty needs a wake up call */
-	tty = tty_port_tty_get(&sclp_port);
-	if (tty != NULL) {
-		tty_wakeup(tty);
-		tty_kref_put(tty);
-	}
+
+	tty_port_tty_wakeup(&sclp_port);
 }
 
 static inline void
diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c
index 6c92f62..5aaaa2e 100644
--- a/drivers/s390/char/sclp_vt220.c
+++ b/drivers/s390/char/sclp_vt220.c
@@ -114,7 +114,6 @@ static struct sclp_register sclp_vt220_register = {
 static void
 sclp_vt220_process_queue(struct sclp_vt220_request *request)
 {
-	struct tty_struct *tty;
 	unsigned long flags;
 	void *page;
 
@@ -139,12 +138,7 @@ sclp_vt220_process_queue(struct sclp_vt220_request *request)
 	} while (__sclp_vt220_emit(request));
 	if (request == NULL && sclp_vt220_flush_later)
 		sclp_vt220_emit_current();
-	/* Check if the tty needs a wake up call */
-	tty = tty_port_tty_get(&sclp_vt220_port);
-	if (tty) {
-		tty_wakeup(tty);
-		tty_kref_put(tty);
-	}
+	tty_port_tty_wakeup(&sclp_vt220_port);
 }
 
 #define SCLP_BUFFER_MAX_RETRY		1
diff --git a/drivers/s390/char/tty3270.c b/drivers/s390/char/tty3270.c
index b907dba..cee69da 100644
--- a/drivers/s390/char/tty3270.c
+++ b/drivers/s390/char/tty3270.c
@@ -915,7 +915,7 @@ static int tty3270_install(struct tty_driver *driver, struct tty_struct *tty)
 	int i, rc;
 
 	/* Check if the tty3270 is already there. */
-	view = raw3270_find_view(&tty3270_fn, tty->index);
+	view = raw3270_find_view(&tty3270_fn, tty->index + RAW3270_FIRSTMINOR);
 	if (!IS_ERR(view)) {
 		tp = container_of(view, struct tty3270, view);
 		tty->driver_data = tp;
@@ -927,15 +927,16 @@ static int tty3270_install(struct tty_driver *driver, struct tty_struct *tty)
 		tp->inattr = TF_INPUT;
 		return tty_port_install(&tp->port, driver, tty);
 	}
-	if (tty3270_max_index < tty->index)
-		tty3270_max_index = tty->index;
+	if (tty3270_max_index < tty->index + 1)
+		tty3270_max_index = tty->index + 1;
 
 	/* Allocate tty3270 structure on first open. */
 	tp = tty3270_alloc_view();
 	if (IS_ERR(tp))
 		return PTR_ERR(tp);
 
-	rc = raw3270_add_view(&tp->view, &tty3270_fn, tty->index);
+	rc = raw3270_add_view(&tp->view, &tty3270_fn,
+			      tty->index + RAW3270_FIRSTMINOR);
 	if (rc) {
 		tty3270_free_view(tp);
 		return rc;
@@ -1846,12 +1847,12 @@ static const struct tty_operations tty3270_ops = {
 
 void tty3270_create_cb(int minor)
 {
-	tty_register_device(tty3270_driver, minor, NULL);
+	tty_register_device(tty3270_driver, minor - RAW3270_FIRSTMINOR, NULL);
 }
 
 void tty3270_destroy_cb(int minor)
 {
-	tty_unregister_device(tty3270_driver, minor);
+	tty_unregister_device(tty3270_driver, minor - RAW3270_FIRSTMINOR);
 }
 
 struct raw3270_notifier tty3270_notifier =
@@ -1884,7 +1885,8 @@ static int __init tty3270_init(void)
 	driver->driver_name = "tty3270";
 	driver->name = "3270/tty";
 	driver->major = IBM_TTY3270_MAJOR;
-	driver->minor_start = 0;
+	driver->minor_start = RAW3270_FIRSTMINOR;
+	driver->name_base = RAW3270_FIRSTMINOR;
 	driver->type = TTY_DRIVER_TYPE_SYSTEM;
 	driver->subtype = SYSTEM_TYPE_TTY;
 	driver->init_termios = tty_std_termios;
diff --git a/drivers/s390/cio/chp.c b/drivers/s390/cio/chp.c
index 50ad5fd..21fabc6 100644
--- a/drivers/s390/cio/chp.c
+++ b/drivers/s390/cio/chp.c
@@ -377,6 +377,26 @@ static void chp_release(struct device *dev)
 }
 
 /**
+ * chp_update_desc - update channel-path description
+ * @chp - channel-path
+ *
+ * Update the channel-path description of the specified channel-path.
+ * Return zero on success, non-zero otherwise.
+ */
+int chp_update_desc(struct channel_path *chp)
+{
+	int rc;
+
+	rc = chsc_determine_base_channel_path_desc(chp->chpid, &chp->desc);
+	if (rc)
+		return rc;
+
+	rc = chsc_determine_fmt1_channel_path_desc(chp->chpid, &chp->desc_fmt1);
+
+	return rc;
+}
+
+/**
  * chp_new - register a new channel-path
  * @chpid - channel-path ID
  *
@@ -403,7 +423,7 @@ int chp_new(struct chp_id chpid)
 	mutex_init(&chp->lock);
 
 	/* Obtain channel path description and fill it in. */
-	ret = chsc_determine_base_channel_path_desc(chpid, &chp->desc);
+	ret = chp_update_desc(chp);
 	if (ret)
 		goto out_free;
 	if ((chp->desc.flags & 0x80) == 0) {
diff --git a/drivers/s390/cio/chp.h b/drivers/s390/cio/chp.h
index e1399db..9284b78 100644
--- a/drivers/s390/cio/chp.h
+++ b/drivers/s390/cio/chp.h
@@ -44,6 +44,7 @@ struct channel_path {
 	struct mutex lock; /* Serialize access to below members. */
 	int state;
 	struct channel_path_desc desc;
+	struct channel_path_desc_fmt1 desc_fmt1;
 	/* Channel-measurement related stuff: */
 	int cmg;
 	int shared;
@@ -62,6 +63,7 @@ int chp_is_registered(struct chp_id chpid);
 void *chp_get_chp_desc(struct chp_id chpid);
 void chp_remove_cmg_attr(struct channel_path *chp);
 int chp_add_cmg_attr(struct channel_path *chp);
+int chp_update_desc(struct channel_path *chp);
 int chp_new(struct chp_id chpid);
 void chp_cfg_schedule(struct chp_id chpid, int configure);
 void chp_cfg_cancel_deconfigure(struct chp_id chpid);
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
index e16c553..8ea7d9b 100644
--- a/drivers/s390/cio/chsc.c
+++ b/drivers/s390/cio/chsc.c
@@ -376,7 +376,7 @@ static void chsc_process_sei_chp_avail(struct chsc_sei_nt0_area *sei_area)
 			continue;
 		}
 		mutex_lock(&chp->lock);
-		chsc_determine_base_channel_path_desc(chpid, &chp->desc);
+		chp_update_desc(chp);
 		mutex_unlock(&chp->lock);
 	}
 }
@@ -631,8 +631,8 @@ int chsc_chp_vary(struct chp_id chpid, int on)
 	 * Redo PathVerification on the devices the chpid connects to
 	 */
 	if (on) {
-		/* Try to update the channel path descritor. */
-		chsc_determine_base_channel_path_desc(chpid, &chp->desc);
+		/* Try to update the channel path description. */
+		chp_update_desc(chp);
 		for_each_subchannel_staged(s390_subchannel_vary_chpid_on,
 					   __s390_vary_chpid_on, &chpid);
 	} else
@@ -825,9 +825,10 @@ int chsc_determine_fmt1_channel_path_desc(struct chp_id chpid,
 {
 	struct chsc_response_struct *chsc_resp;
 	struct chsc_scpd *scpd_area;
+	unsigned long flags;
 	int ret;
 
-	spin_lock_irq(&chsc_page_lock);
+	spin_lock_irqsave(&chsc_page_lock, flags);
 	scpd_area = chsc_page;
 	ret = chsc_determine_channel_path_desc(chpid, 0, 0, 1, 0, scpd_area);
 	if (ret)
@@ -835,7 +836,7 @@ int chsc_determine_fmt1_channel_path_desc(struct chp_id chpid,
 	chsc_resp = (void *)&scpd_area->response;
 	memcpy(desc, &chsc_resp->data, sizeof(*desc));
 out:
-	spin_unlock_irq(&chsc_page_lock);
+	spin_unlock_irqrestore(&chsc_page_lock, flags);
 	return ret;
 }
 
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index a239237..658d934 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -1065,9 +1065,8 @@ void channel_subsystem_reinit(void)
 	chsc_enable_facility(CHSC_SDA_OC_MSS);
 	chp_id_for_each(&chpid) {
 		chp = chpid_to_chp(chpid);
-		if (!chp)
-			continue;
-		chsc_determine_base_channel_path_desc(chpid, &chp->desc);
+		if (chp)
+			chp_update_desc(chp);
 	}
 }
 
diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c
index c77b6e0..4845d64 100644
--- a/drivers/s390/cio/device_ops.c
+++ b/drivers/s390/cio/device_ops.c
@@ -704,9 +704,9 @@ EXPORT_SYMBOL(ccw_device_tm_start_timeout);
 int ccw_device_get_mdc(struct ccw_device *cdev, u8 mask)
 {
 	struct subchannel *sch = to_subchannel(cdev->dev.parent);
-	struct channel_path_desc_fmt1 desc;
+	struct channel_path *chp;
 	struct chp_id chpid;
-	int mdc = 0, ret, i;
+	int mdc = 0, i;
 
 	/* Adjust requested path mask to excluded varied off paths. */
 	if (mask)
@@ -719,14 +719,20 @@ int ccw_device_get_mdc(struct ccw_device *cdev, u8 mask)
 		if (!(mask & (0x80 >> i)))
 			continue;
 		chpid.id = sch->schib.pmcw.chpid[i];
-		ret = chsc_determine_fmt1_channel_path_desc(chpid, &desc);
-		if (ret)
-			return ret;
-		if (!desc.f)
+		chp = chpid_to_chp(chpid);
+		if (!chp)
+			continue;
+
+		mutex_lock(&chp->lock);
+		if (!chp->desc_fmt1.f) {
+			mutex_unlock(&chp->lock);
 			return 0;
-		if (!desc.r)
+		}
+		if (!chp->desc_fmt1.r)
 			mdc = 1;
-		mdc = mdc ? min(mdc, (int)desc.mdc) : desc.mdc;
+		mdc = mdc ? min_t(int, mdc, chp->desc_fmt1.mdc) :
+			    chp->desc_fmt1.mdc;
+		mutex_unlock(&chp->lock);
 	}
 
 	return mdc;
diff --git a/drivers/s390/cio/idset.c b/drivers/s390/cio/idset.c
index 65d13e3..5a99908 100644
--- a/drivers/s390/cio/idset.c
+++ b/drivers/s390/cio/idset.c
@@ -17,7 +17,7 @@ struct idset {
 
 static inline unsigned long bitmap_size(int num_ssid, int num_id)
 {
-	return __BITOPS_WORDS(num_ssid * num_id) * sizeof(unsigned long);
+	return BITS_TO_LONGS(num_ssid * num_id) * sizeof(unsigned long);
 }
 
 static struct idset *idset_new(int num_ssid, int num_id)
diff --git a/drivers/s390/kvm/virtio_ccw.c b/drivers/s390/kvm/virtio_ccw.c
index 2029b6c..a0a9130 100644
--- a/drivers/s390/kvm/virtio_ccw.c
+++ b/drivers/s390/kvm/virtio_ccw.c
@@ -31,6 +31,7 @@
 #include <asm/irq.h>
 #include <asm/cio.h>
 #include <asm/ccwdev.h>
+#include <asm/virtio-ccw.h>
 
 /*
  * virtio related functions
@@ -77,12 +78,9 @@ struct virtio_ccw_vq_info {
 	void *queue;
 	struct vq_info_block *info_block;
 	struct list_head node;
+	long cookie;
 };
 
-#define KVM_VIRTIO_CCW_RING_ALIGN 4096
-
-#define KVM_S390_VIRTIO_CCW_NOTIFY 3
-
 #define CCW_CMD_SET_VQ 0x13
 #define CCW_CMD_VDEV_RESET 0x33
 #define CCW_CMD_SET_IND 0x43
@@ -145,15 +143,18 @@ static int ccw_io_helper(struct virtio_ccw_device *vcdev,
 }
 
 static inline long do_kvm_notify(struct subchannel_id schid,
-				 unsigned long queue_index)
+				 unsigned long queue_index,
+				 long cookie)
 {
 	register unsigned long __nr asm("1") = KVM_S390_VIRTIO_CCW_NOTIFY;
 	register struct subchannel_id __schid asm("2") = schid;
 	register unsigned long __index asm("3") = queue_index;
 	register long __rc asm("2");
+	register long __cookie asm("4") = cookie;
 
 	asm volatile ("diag 2,4,0x500\n"
-		      : "=d" (__rc) : "d" (__nr), "d" (__schid), "d" (__index)
+		      : "=d" (__rc) : "d" (__nr), "d" (__schid), "d" (__index),
+		      "d"(__cookie)
 		      : "memory", "cc");
 	return __rc;
 }
@@ -166,7 +167,7 @@ static void virtio_ccw_kvm_notify(struct virtqueue *vq)
 
 	vcdev = to_vc_device(info->vq->vdev);
 	ccw_device_get_schid(vcdev->cdev, &schid);
-	do_kvm_notify(schid, virtqueue_get_queue_index(vq));
+	info->cookie = do_kvm_notify(schid, vq->index, info->cookie);
 }
 
 static int virtio_ccw_read_vq_conf(struct virtio_ccw_device *vcdev,
@@ -188,7 +189,7 @@ static void virtio_ccw_del_vq(struct virtqueue *vq, struct ccw1 *ccw)
 	unsigned long flags;
 	unsigned long size;
 	int ret;
-	unsigned int index = virtqueue_get_queue_index(vq);
+	unsigned int index = vq->index;
 
 	/* Remove from our list. */
 	spin_lock_irqsave(&vcdev->lock, flags);
@@ -610,7 +611,7 @@ static struct virtqueue *virtio_ccw_vq_by_ind(struct virtio_ccw_device *vcdev,
 	vq = NULL;
 	spin_lock_irqsave(&vcdev->lock, flags);
 	list_for_each_entry(info, &vcdev->virtqueues, node) {
-		if (virtqueue_get_queue_index(info->vq) == index) {
+		if (info->vq->index == index) {
 			vq = info->vq;
 			break;
 		}
diff --git a/drivers/sbus/char/bbc_i2c.c b/drivers/sbus/char/bbc_i2c.c
index 1a9d1e3..c1441ed 100644
--- a/drivers/sbus/char/bbc_i2c.c
+++ b/drivers/sbus/char/bbc_i2c.c
@@ -282,7 +282,7 @@ static irqreturn_t bbc_i2c_interrupt(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-static void __init reset_one_i2c(struct bbc_i2c_bus *bp)
+static void reset_one_i2c(struct bbc_i2c_bus *bp)
 {
 	writeb(I2C_PCF_PIN, bp->i2c_control_regs + 0x0);
 	writeb(bp->own, bp->i2c_control_regs + 0x1);
@@ -291,7 +291,7 @@ static void __init reset_one_i2c(struct bbc_i2c_bus *bp)
 	writeb(I2C_PCF_IDLE, bp->i2c_control_regs + 0x0);
 }
 
-static struct bbc_i2c_bus * __init attach_one_i2c(struct platform_device *op, int index)
+static struct bbc_i2c_bus * attach_one_i2c(struct platform_device *op, int index)
 {
 	struct bbc_i2c_bus *bp;
 	struct device_node *dp;
diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c
index d7ca247..344d875 100644
--- a/drivers/scsi/BusLogic.c
+++ b/drivers/scsi/BusLogic.c
@@ -3201,26 +3201,30 @@ static int BusLogic_BIOSDiskParameters(struct scsi_device *sdev, struct block_de
   BugLogic_ProcDirectoryInfo implements /proc/scsi/BusLogic/<N>.
 */
 
-static int BusLogic_ProcDirectoryInfo(struct Scsi_Host *shost, char *ProcBuffer, char **StartPointer, off_t Offset, int BytesAvailable, int WriteFlag)
+static int BusLogic_write_info(struct Scsi_Host *shost, char *ProcBuffer, int BytesAvailable)
 {
 	struct BusLogic_HostAdapter *HostAdapter = (struct BusLogic_HostAdapter *) shost->hostdata;
 	struct BusLogic_TargetStatistics *TargetStatistics;
-	int TargetID, Length;
-	char *Buffer;
 
 	TargetStatistics = HostAdapter->TargetStatistics;
-	if (WriteFlag) {
-		HostAdapter->ExternalHostAdapterResets = 0;
-		HostAdapter->HostAdapterInternalErrors = 0;
-		memset(TargetStatistics, 0, BusLogic_MaxTargetDevices * sizeof(struct BusLogic_TargetStatistics));
-		return 0;
-	}
-	Buffer = HostAdapter->MessageBuffer;
-	Length = HostAdapter->MessageBufferLength;
-	Length += sprintf(&Buffer[Length], "\n\
+	HostAdapter->ExternalHostAdapterResets = 0;
+	HostAdapter->HostAdapterInternalErrors = 0;
+	memset(TargetStatistics, 0, BusLogic_MaxTargetDevices * sizeof(struct BusLogic_TargetStatistics));
+	return 0;
+}
+
+static int BusLogic_show_info(struct seq_file *m, struct Scsi_Host *shost)
+{
+	struct BusLogic_HostAdapter *HostAdapter = (struct BusLogic_HostAdapter *) shost->hostdata;
+	struct BusLogic_TargetStatistics *TargetStatistics;
+	int TargetID;
+
+	TargetStatistics = HostAdapter->TargetStatistics;
+	seq_write(m, HostAdapter->MessageBuffer, HostAdapter->MessageBufferLength);
+	seq_printf(m, "\n\
 Current Driver Queue Depth:	%d\n\
 Currently Allocated CCBs:	%d\n", HostAdapter->DriverQueueDepth, HostAdapter->AllocatedCCBs);
-	Length += sprintf(&Buffer[Length], "\n\n\
+	seq_printf(m, "\n\n\
 			   DATA TRANSFER STATISTICS\n\
 \n\
 Target	Tagged Queuing	Queue Depth  Active  Attempted	Completed\n\
@@ -3229,66 +3233,62 @@ Target	Tagged Queuing	Queue Depth  Active  Attempted	Completed\n\
 		struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[TargetID];
 		if (!TargetFlags->TargetExists)
 			continue;
-		Length += sprintf(&Buffer[Length], "  %2d	%s", TargetID, (TargetFlags->TaggedQueuingSupported ? (TargetFlags->TaggedQueuingActive ? "    Active" : (HostAdapter->TaggedQueuingPermitted & (1 << TargetID)
+		seq_printf(m, "  %2d	%s", TargetID, (TargetFlags->TaggedQueuingSupported ? (TargetFlags->TaggedQueuingActive ? "    Active" : (HostAdapter->TaggedQueuingPermitted & (1 << TargetID)
 																				    ? "  Permitted" : "   Disabled"))
 									  : "Not Supported"));
-		Length += sprintf(&Buffer[Length],
+		seq_printf(m,
 				  "	    %3d       %3u    %9u	%9u\n", HostAdapter->QueueDepth[TargetID], HostAdapter->ActiveCommands[TargetID], TargetStatistics[TargetID].CommandsAttempted, TargetStatistics[TargetID].CommandsCompleted);
 	}
-	Length += sprintf(&Buffer[Length], "\n\
+	seq_printf(m, "\n\
 Target  Read Commands  Write Commands   Total Bytes Read    Total Bytes Written\n\
 ======  =============  ==============  ===================  ===================\n");
 	for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) {
 		struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[TargetID];
 		if (!TargetFlags->TargetExists)
 			continue;
-		Length += sprintf(&Buffer[Length], "  %2d	  %9u	 %9u", TargetID, TargetStatistics[TargetID].ReadCommands, TargetStatistics[TargetID].WriteCommands);
+		seq_printf(m, "  %2d	  %9u	 %9u", TargetID, TargetStatistics[TargetID].ReadCommands, TargetStatistics[TargetID].WriteCommands);
 		if (TargetStatistics[TargetID].TotalBytesRead.Billions > 0)
-			Length += sprintf(&Buffer[Length], "     %9u%09u", TargetStatistics[TargetID].TotalBytesRead.Billions, TargetStatistics[TargetID].TotalBytesRead.Units);
+			seq_printf(m, "     %9u%09u", TargetStatistics[TargetID].TotalBytesRead.Billions, TargetStatistics[TargetID].TotalBytesRead.Units);
 		else
-			Length += sprintf(&Buffer[Length], "		%9u", TargetStatistics[TargetID].TotalBytesRead.Units);
+			seq_printf(m, "		%9u", TargetStatistics[TargetID].TotalBytesRead.Units);
 		if (TargetStatistics[TargetID].TotalBytesWritten.Billions > 0)
-			Length += sprintf(&Buffer[Length], "   %9u%09u\n", TargetStatistics[TargetID].TotalBytesWritten.Billions, TargetStatistics[TargetID].TotalBytesWritten.Units);
+			seq_printf(m, "   %9u%09u\n", TargetStatistics[TargetID].TotalBytesWritten.Billions, TargetStatistics[TargetID].TotalBytesWritten.Units);
 		else
-			Length += sprintf(&Buffer[Length], "	     %9u\n", TargetStatistics[TargetID].TotalBytesWritten.Units);
+			seq_printf(m, "	     %9u\n", TargetStatistics[TargetID].TotalBytesWritten.Units);
 	}
-	Length += sprintf(&Buffer[Length], "\n\
+	seq_printf(m, "\n\
 Target  Command    0-1KB      1-2KB      2-4KB      4-8KB     8-16KB\n\
 ======  =======  =========  =========  =========  =========  =========\n");
 	for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) {
 		struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[TargetID];
 		if (!TargetFlags->TargetExists)
 			continue;
-		Length +=
-		    sprintf(&Buffer[Length],
+		seq_printf(m,
 			    "  %2d	 Read	 %9u  %9u  %9u  %9u  %9u\n", TargetID,
 			    TargetStatistics[TargetID].ReadCommandSizeBuckets[0],
 			    TargetStatistics[TargetID].ReadCommandSizeBuckets[1], TargetStatistics[TargetID].ReadCommandSizeBuckets[2], TargetStatistics[TargetID].ReadCommandSizeBuckets[3], TargetStatistics[TargetID].ReadCommandSizeBuckets[4]);
-		Length +=
-		    sprintf(&Buffer[Length],
+		seq_printf(m,
 			    "  %2d	 Write	 %9u  %9u  %9u  %9u  %9u\n", TargetID,
 			    TargetStatistics[TargetID].WriteCommandSizeBuckets[0],
 			    TargetStatistics[TargetID].WriteCommandSizeBuckets[1], TargetStatistics[TargetID].WriteCommandSizeBuckets[2], TargetStatistics[TargetID].WriteCommandSizeBuckets[3], TargetStatistics[TargetID].WriteCommandSizeBuckets[4]);
 	}
-	Length += sprintf(&Buffer[Length], "\n\
+	seq_printf(m, "\n\
 Target  Command   16-32KB    32-64KB   64-128KB   128-256KB   256KB+\n\
 ======  =======  =========  =========  =========  =========  =========\n");
 	for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) {
 		struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[TargetID];
 		if (!TargetFlags->TargetExists)
 			continue;
-		Length +=
-		    sprintf(&Buffer[Length],
+		seq_printf(m,
 			    "  %2d	 Read	 %9u  %9u  %9u  %9u  %9u\n", TargetID,
 			    TargetStatistics[TargetID].ReadCommandSizeBuckets[5],
 			    TargetStatistics[TargetID].ReadCommandSizeBuckets[6], TargetStatistics[TargetID].ReadCommandSizeBuckets[7], TargetStatistics[TargetID].ReadCommandSizeBuckets[8], TargetStatistics[TargetID].ReadCommandSizeBuckets[9]);
-		Length +=
-		    sprintf(&Buffer[Length],
+		seq_printf(m,
 			    "  %2d	 Write	 %9u  %9u  %9u  %9u  %9u\n", TargetID,
 			    TargetStatistics[TargetID].WriteCommandSizeBuckets[5],
 			    TargetStatistics[TargetID].WriteCommandSizeBuckets[6], TargetStatistics[TargetID].WriteCommandSizeBuckets[7], TargetStatistics[TargetID].WriteCommandSizeBuckets[8], TargetStatistics[TargetID].WriteCommandSizeBuckets[9]);
 	}
-	Length += sprintf(&Buffer[Length], "\n\n\
+	seq_printf(m, "\n\n\
 			   ERROR RECOVERY STATISTICS\n\
 \n\
 	  Command Aborts      Bus Device Resets	  Host Adapter Resets\n\
@@ -3299,20 +3299,12 @@ Target	Requested Completed  Requested Completed  Requested Completed\n\
 		struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[TargetID];
 		if (!TargetFlags->TargetExists)
 			continue;
-		Length += sprintf(&Buffer[Length], "\
+		seq_printf(m, "\
   %2d	 %5d %5d %5d    %5d %5d %5d	   %5d %5d %5d\n", TargetID, TargetStatistics[TargetID].CommandAbortsRequested, TargetStatistics[TargetID].CommandAbortsAttempted, TargetStatistics[TargetID].CommandAbortsCompleted, TargetStatistics[TargetID].BusDeviceResetsRequested, TargetStatistics[TargetID].BusDeviceResetsAttempted, TargetStatistics[TargetID].BusDeviceResetsCompleted, TargetStatistics[TargetID].HostAdapterResetsRequested, TargetStatistics[TargetID].HostAdapterResetsAttempted, TargetStatistics[TargetID].HostAdapterResetsCompleted);
 	}
-	Length += sprintf(&Buffer[Length], "\nExternal Host Adapter Resets: %d\n", HostAdapter->ExternalHostAdapterResets);
-	Length += sprintf(&Buffer[Length], "Host Adapter Internal Errors: %d\n", HostAdapter->HostAdapterInternalErrors);
-	if (Length >= BusLogic_MessageBufferSize)
-		BusLogic_Error("Message Buffer length %d exceeds size %d\n", HostAdapter, Length, BusLogic_MessageBufferSize);
-	if ((Length -= Offset) <= 0)
-		return 0;
-	if (Length >= BytesAvailable)
-		Length = BytesAvailable;
-	memcpy(ProcBuffer, HostAdapter->MessageBuffer + Offset, Length);
-	*StartPointer = ProcBuffer;
-	return Length;
+	seq_printf(m, "\nExternal Host Adapter Resets: %d\n", HostAdapter->ExternalHostAdapterResets);
+	seq_printf(m, "Host Adapter Internal Errors: %d\n", HostAdapter->HostAdapterInternalErrors);
+	return 0;
 }
 
 
@@ -3566,7 +3558,8 @@ static int __init BusLogic_ParseDriverOptions(char *OptionsString)
 static struct scsi_host_template Bus_Logic_template = {
 	.module = THIS_MODULE,
 	.proc_name = "BusLogic",
-	.proc_info = BusLogic_ProcDirectoryInfo,
+	.write_info = BusLogic_write_info,
+	.show_info = BusLogic_show_info,
 	.name = "BusLogic",
 	.info = BusLogic_DriverInfo,
 	.queuecommand = BusLogic_QueueCommand,
diff --git a/drivers/scsi/BusLogic.h b/drivers/scsi/BusLogic.h
index 649fcb3..6c6c13c 100644
--- a/drivers/scsi/BusLogic.h
+++ b/drivers/scsi/BusLogic.h
@@ -1321,7 +1321,6 @@ static inline void BusLogic_IncrementSizeBucket(BusLogic_CommandSizeBuckets_T Co
 static const char *BusLogic_DriverInfo(struct Scsi_Host *);
 static int BusLogic_QueueCommand(struct Scsi_Host *h, struct scsi_cmnd *);
 static int BusLogic_BIOSDiskParameters(struct scsi_device *, struct block_device *, sector_t, int *);
-static int BusLogic_ProcDirectoryInfo(struct Scsi_Host *, char *, char **, off_t, int, int);
 static int BusLogic_SlaveConfigure(struct scsi_device *);
 static void BusLogic_QueueCompletedCCB(struct BusLogic_CCB *);
 static irqreturn_t BusLogic_InterruptHandler(int, void *);
diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c
index 450353e..1e9d6ad 100644
--- a/drivers/scsi/NCR5380.c
+++ b/drivers/scsi/NCR5380.c
@@ -695,33 +695,35 @@ static void NCR5380_print_status(struct Scsi_Host *instance)
  * Return the number of bytes read from or written
  */
 
+static int __maybe_unused NCR5380_write_info(struct Scsi_Host *instance,
+	char *buffer, int length)
+{
+#ifdef DTC_PUBLIC_RELEASE
+	dtc_wmaxi = dtc_maxi = 0;
+#endif
+#ifdef PAS16_PUBLIC_RELEASE
+	pas_wmaxi = pas_maxi = 0;
+#endif
+	return (-ENOSYS);	/* Currently this is a no-op */
+}
+
 #undef SPRINTF
-#define SPRINTF(args...) do { if(pos < buffer + length-80) pos += sprintf(pos, ## args); } while(0)
+#define SPRINTF(args...) seq_printf(m, ## args)
 static
-char *lprint_Scsi_Cmnd(Scsi_Cmnd * cmd, char *pos, char *buffer, int length);
+void lprint_Scsi_Cmnd(Scsi_Cmnd * cmd, struct seq_file *m);
 static
-char *lprint_command(unsigned char *cmd, char *pos, char *buffer, int len);
+void lprint_command(unsigned char *cmd, struct seq_file *m);
 static
-char *lprint_opcode(int opcode, char *pos, char *buffer, int length);
+void lprint_opcode(int opcode, struct seq_file *m);
 
-static int __maybe_unused NCR5380_proc_info(struct Scsi_Host *instance,
-	char *buffer, char **start, off_t offset, int length, int inout)
+static int __maybe_unused NCR5380_show_info(struct seq_file *m,
+	struct Scsi_Host *instance)
 {
-	char *pos = buffer;
 	struct NCR5380_hostdata *hostdata;
 	Scsi_Cmnd *ptr;
 
 	hostdata = (struct NCR5380_hostdata *) instance->hostdata;
 
-	if (inout) {		/* Has data been written to the file ? */
-#ifdef DTC_PUBLIC_RELEASE
-		dtc_wmaxi = dtc_maxi = 0;
-#endif
-#ifdef PAS16_PUBLIC_RELEASE
-		pas_wmaxi = pas_maxi = 0;
-#endif
-		return (-ENOSYS);	/* Currently this is a no-op */
-	}
 	SPRINTF("NCR5380 core release=%d.   ", NCR5380_PUBLIC_RELEASE);
 	if (((struct NCR5380_hostdata *) instance->hostdata)->flags & FLAG_NCR53C400)
 		SPRINTF("ncr53c400 release=%d.  ", NCR53C400_PUBLIC_RELEASE);
@@ -755,46 +757,37 @@ static int __maybe_unused NCR5380_proc_info(struct Scsi_Host *instance,
 	if (!hostdata->connected)
 		SPRINTF("scsi%d: no currently connected command\n", instance->host_no);
 	else
-		pos = lprint_Scsi_Cmnd((Scsi_Cmnd *) hostdata->connected, pos, buffer, length);
+		lprint_Scsi_Cmnd((Scsi_Cmnd *) hostdata->connected, m);
 	SPRINTF("scsi%d: issue_queue\n", instance->host_no);
 	for (ptr = (Scsi_Cmnd *) hostdata->issue_queue; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble)
-		pos = lprint_Scsi_Cmnd(ptr, pos, buffer, length);
+		lprint_Scsi_Cmnd(ptr, m);
 
 	SPRINTF("scsi%d: disconnected_queue\n", instance->host_no);
 	for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble)
-		pos = lprint_Scsi_Cmnd(ptr, pos, buffer, length);
+		lprint_Scsi_Cmnd(ptr, m);
 	spin_unlock_irq(instance->host_lock);
-	
-	*start = buffer;
-	if (pos - buffer < offset)
-		return 0;
-	else if (pos - buffer - offset < length)
-		return pos - buffer - offset;
-	return length;
+	return 0;
 }
 
-static char *lprint_Scsi_Cmnd(Scsi_Cmnd * cmd, char *pos, char *buffer, int length)
+static void lprint_Scsi_Cmnd(Scsi_Cmnd * cmd, struct seq_file *m)
 {
 	SPRINTF("scsi%d : destination target %d, lun %d\n", cmd->device->host->host_no, cmd->device->id, cmd->device->lun);
 	SPRINTF("        command = ");
-	pos = lprint_command(cmd->cmnd, pos, buffer, length);
-	return (pos);
+	lprint_command(cmd->cmnd, m);
 }
 
-static char *lprint_command(unsigned char *command, char *pos, char *buffer, int length)
+static void lprint_command(unsigned char *command, struct seq_file *m)
 {
 	int i, s;
-	pos = lprint_opcode(command[0], pos, buffer, length);
+	lprint_opcode(command[0], m);
 	for (i = 1, s = COMMAND_SIZE(command[0]); i < s; ++i)
 		SPRINTF("%02x ", command[i]);
 	SPRINTF("\n");
-	return (pos);
 }
 
-static char *lprint_opcode(int opcode, char *pos, char *buffer, int length)
+static void lprint_opcode(int opcode, struct seq_file *m)
 {
 	SPRINTF("%2d (0x%02x)", opcode, opcode);
-	return (pos);
 }
 
 
diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h
index fd40a32..14964d0 100644
--- a/drivers/scsi/NCR5380.h
+++ b/drivers/scsi/NCR5380.h
@@ -314,8 +314,10 @@ static void NCR5380_print(struct Scsi_Host *instance);
 static int NCR5380_abort(Scsi_Cmnd * cmd);
 static int NCR5380_bus_reset(Scsi_Cmnd * cmd);
 static int NCR5380_queue_command(struct Scsi_Host *, struct scsi_cmnd *);
-static int __maybe_unused NCR5380_proc_info(struct Scsi_Host *instance,
-	char *buffer, char **start, off_t offset, int length, int inout);
+static int __maybe_unused NCR5380_show_info(struct seq_file *,
+	struct Scsi_Host *);
+static int __maybe_unused NCR5380_write_info(struct Scsi_Host *instance,
+	char *buffer, int length);
 
 static void NCR5380_reselect(struct Scsi_Host *instance);
 static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag);
diff --git a/drivers/scsi/a2091.c b/drivers/scsi/a2091.c
index 3e09aa2..30fa38a 100644
--- a/drivers/scsi/a2091.c
+++ b/drivers/scsi/a2091.c
@@ -166,7 +166,8 @@ static int a2091_bus_reset(struct scsi_cmnd *cmd)
 static struct scsi_host_template a2091_scsi_template = {
 	.module			= THIS_MODULE,
 	.name			= "Commodore A2091/A590 SCSI",
-	.proc_info		= wd33c93_proc_info,
+	.show_info		= wd33c93_show_info,
+	.write_info		= wd33c93_write_info,
 	.proc_name		= "A2901",
 	.queuecommand		= wd33c93_queuecommand,
 	.eh_abort_handler	= wd33c93_abort,
diff --git a/drivers/scsi/a3000.c b/drivers/scsi/a3000.c
index e29fe0e..c487916 100644
--- a/drivers/scsi/a3000.c
+++ b/drivers/scsi/a3000.c
@@ -181,7 +181,8 @@ static int a3000_bus_reset(struct scsi_cmnd *cmd)
 static struct scsi_host_template amiga_a3000_scsi_template = {
 	.module			= THIS_MODULE,
 	.name			= "Amiga 3000 built-in SCSI",
-	.proc_info		= wd33c93_proc_info,
+	.show_info		= wd33c93_show_info,
+	.write_info		= wd33c93_write_info,
 	.proc_name		= "A3000",
 	.queuecommand		= wd33c93_queuecommand,
 	.eh_abort_handler	= wd33c93_abort,
diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c
index dcfaee6..c67e401 100644
--- a/drivers/scsi/advansys.c
+++ b/drivers/scsi/advansys.c
@@ -2178,22 +2178,6 @@ do { \
 
 #define ASC_INFO_SIZE           128	/* advansys_info() line size */
 
-#ifdef CONFIG_PROC_FS
-/* /proc/scsi/advansys/[0...] related definitions */
-#define ASC_PRTBUF_SIZE         2048
-#define ASC_PRTLINE_SIZE        160
-
-#define ASC_PRT_NEXT() \
-    if (cp) { \
-        totlen += len; \
-        leftlen -= len; \
-        if (leftlen == 0) { \
-            return totlen; \
-        } \
-        cp += len; \
-    }
-#endif /* CONFIG_PROC_FS */
-
 /* Asc Library return codes */
 #define ASC_TRUE        1
 #define ASC_FALSE       0
@@ -2384,7 +2368,6 @@ struct asc_board {
 	} eep_config;
 	ulong last_reset;	/* Saved last reset time */
 	/* /proc/scsi/advansys/[0...] */
-	char *prtbuf;		/* /proc print buffer */
 #ifdef ADVANSYS_STATS
 	struct asc_stats asc_stats;	/* Board statistics */
 #endif				/* ADVANSYS_STATS */
@@ -2875,64 +2858,21 @@ static const char *advansys_info(struct Scsi_Host *shost)
 }
 
 #ifdef CONFIG_PROC_FS
-/*
- * asc_prt_line()
- *
- * If 'cp' is NULL print to the console, otherwise print to a buffer.
- *
- * Return 0 if printing to the console, otherwise return the number of
- * bytes written to the buffer.
- *
- * Note: If any single line is greater than ASC_PRTLINE_SIZE bytes the stack
- * will be corrupted. 's[]' is defined to be ASC_PRTLINE_SIZE bytes.
- */
-static int asc_prt_line(char *buf, int buflen, char *fmt, ...)
-{
-	va_list args;
-	int ret;
-	char s[ASC_PRTLINE_SIZE];
-
-	va_start(args, fmt);
-	ret = vsprintf(s, fmt, args);
-	BUG_ON(ret >= ASC_PRTLINE_SIZE);
-	if (buf == NULL) {
-		(void)printk(s);
-		ret = 0;
-	} else {
-		ret = min(buflen, ret);
-		memcpy(buf, s, ret);
-	}
-	va_end(args);
-	return ret;
-}
 
 /*
  * asc_prt_board_devices()
  *
  * Print driver information for devices attached to the board.
- *
- * Note: no single line should be greater than ASC_PRTLINE_SIZE,
- * cf. asc_prt_line().
- *
- * Return the number of characters copied into 'cp'. No more than
- * 'cplen' characters will be copied to 'cp'.
  */
-static int asc_prt_board_devices(struct Scsi_Host *shost, char *cp, int cplen)
+static void asc_prt_board_devices(struct seq_file *m, struct Scsi_Host *shost)
 {
 	struct asc_board *boardp = shost_priv(shost);
-	int leftlen;
-	int totlen;
-	int len;
 	int chip_scsi_id;
 	int i;
 
-	leftlen = cplen;
-	totlen = len = 0;
-
-	len = asc_prt_line(cp, leftlen,
-			   "\nDevice Information for AdvanSys SCSI Host %d:\n",
-			   shost->host_no);
-	ASC_PRT_NEXT();
+	seq_printf(m,
+		   "\nDevice Information for AdvanSys SCSI Host %d:\n",
+		   shost->host_no);
 
 	if (ASC_NARROW_BOARD(boardp)) {
 		chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id;
@@ -2940,60 +2880,42 @@ static int asc_prt_board_devices(struct Scsi_Host *shost, char *cp, int cplen)
 		chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id;
 	}
 
-	len = asc_prt_line(cp, leftlen, "Target IDs Detected:");
-	ASC_PRT_NEXT();
+	seq_printf(m, "Target IDs Detected:");
 	for (i = 0; i <= ADV_MAX_TID; i++) {
-		if (boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) {
-			len = asc_prt_line(cp, leftlen, " %X,", i);
-			ASC_PRT_NEXT();
-		}
+		if (boardp->init_tidmask & ADV_TID_TO_TIDMASK(i))
+			seq_printf(m, " %X,", i);
 	}
-	len = asc_prt_line(cp, leftlen, " (%X=Host Adapter)\n", chip_scsi_id);
-	ASC_PRT_NEXT();
-
-	return totlen;
+	seq_printf(m, " (%X=Host Adapter)\n", chip_scsi_id);
 }
 
 /*
  * Display Wide Board BIOS Information.
  */
-static int asc_prt_adv_bios(struct Scsi_Host *shost, char *cp, int cplen)
+static void asc_prt_adv_bios(struct seq_file *m, struct Scsi_Host *shost)
 {
 	struct asc_board *boardp = shost_priv(shost);
-	int leftlen;
-	int totlen;
-	int len;
 	ushort major, minor, letter;
 
-	leftlen = cplen;
-	totlen = len = 0;
-
-	len = asc_prt_line(cp, leftlen, "\nROM BIOS Version: ");
-	ASC_PRT_NEXT();
+	seq_printf(m, "\nROM BIOS Version: ");
 
 	/*
 	 * If the BIOS saved a valid signature, then fill in
 	 * the BIOS code segment base address.
 	 */
 	if (boardp->bios_signature != 0x55AA) {
-		len = asc_prt_line(cp, leftlen, "Disabled or Pre-3.1\n");
-		ASC_PRT_NEXT();
-		len = asc_prt_line(cp, leftlen,
-				   "BIOS either disabled or Pre-3.1. If it is pre-3.1, then a newer version\n");
-		ASC_PRT_NEXT();
-		len = asc_prt_line(cp, leftlen,
-				   "can be found at the ConnectCom FTP site: ftp://ftp.connectcom.net/pub\n");
-		ASC_PRT_NEXT();
+		seq_printf(m, "Disabled or Pre-3.1\n");
+		seq_printf(m,
+			  "BIOS either disabled or Pre-3.1. If it is pre-3.1, then a newer version\n");
+		seq_printf(m,
+			  "can be found at the ConnectCom FTP site: ftp://ftp.connectcom.net/pub\n");
 	} else {
 		major = (boardp->bios_version >> 12) & 0xF;
 		minor = (boardp->bios_version >> 8) & 0xF;
 		letter = (boardp->bios_version & 0xFF);
 
-		len = asc_prt_line(cp, leftlen, "%d.%d%c\n",
+		seq_printf(m, "%d.%d%c\n",
 				   major, minor,
 				   letter >= 26 ? '?' : letter + 'A');
-		ASC_PRT_NEXT();
-
 		/*
 		 * Current available ROM BIOS release is 3.1I for UW
 		 * and 3.2I for U2W. This code doesn't differentiate
@@ -3001,16 +2923,12 @@ static int asc_prt_adv_bios(struct Scsi_Host *shost, char *cp, int cplen)
 		 */
 		if (major < 3 || (major <= 3 && minor < 1) ||
 		    (major <= 3 && minor <= 1 && letter < ('I' - 'A'))) {
-			len = asc_prt_line(cp, leftlen,
-					   "Newer version of ROM BIOS is available at the ConnectCom FTP site:\n");
-			ASC_PRT_NEXT();
-			len = asc_prt_line(cp, leftlen,
-					   "ftp://ftp.connectcom.net/pub\n");
-			ASC_PRT_NEXT();
+			seq_printf(m,
+				   "Newer version of ROM BIOS is available at the ConnectCom FTP site:\n");
+			seq_printf(m,
+				   "ftp://ftp.connectcom.net/pub\n");
 		}
 	}
-
-	return totlen;
 }
 
 /*
@@ -3115,20 +3033,11 @@ static int asc_get_eeprom_string(ushort *serialnum, uchar *cp)
  * asc_prt_asc_board_eeprom()
  *
  * Print board EEPROM configuration.
- *
- * Note: no single line should be greater than ASC_PRTLINE_SIZE,
- * cf. asc_prt_line().
- *
- * Return the number of characters copied into 'cp'. No more than
- * 'cplen' characters will be copied to 'cp'.
  */
-static int asc_prt_asc_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen)
+static void asc_prt_asc_board_eeprom(struct seq_file *m, struct Scsi_Host *shost)
 {
 	struct asc_board *boardp = shost_priv(shost);
 	ASC_DVC_VAR *asc_dvc_varp;
-	int leftlen;
-	int totlen;
-	int len;
 	ASCEEP_CONFIG *ep;
 	int i;
 #ifdef CONFIG_ISA
@@ -3139,129 +3048,75 @@ static int asc_prt_asc_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen
 	asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
 	ep = &boardp->eep_config.asc_eep;
 
-	leftlen = cplen;
-	totlen = len = 0;
-
-	len = asc_prt_line(cp, leftlen,
-			   "\nEEPROM Settings for AdvanSys SCSI Host %d:\n",
-			   shost->host_no);
-	ASC_PRT_NEXT();
+	seq_printf(m,
+		   "\nEEPROM Settings for AdvanSys SCSI Host %d:\n",
+		   shost->host_no);
 
 	if (asc_get_eeprom_string((ushort *)&ep->adapter_info[0], serialstr)
-	    == ASC_TRUE) {
-		len =
-		    asc_prt_line(cp, leftlen, " Serial Number: %s\n",
-				 serialstr);
-		ASC_PRT_NEXT();
-	} else {
-		if (ep->adapter_info[5] == 0xBB) {
-			len = asc_prt_line(cp, leftlen,
-					   " Default Settings Used for EEPROM-less Adapter.\n");
-			ASC_PRT_NEXT();
-		} else {
-			len = asc_prt_line(cp, leftlen,
-					   " Serial Number Signature Not Present.\n");
-			ASC_PRT_NEXT();
-		}
-	}
-
-	len = asc_prt_line(cp, leftlen,
-			   " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
-			   ASC_EEP_GET_CHIP_ID(ep), ep->max_total_qng,
-			   ep->max_tag_qng);
-	ASC_PRT_NEXT();
-
-	len = asc_prt_line(cp, leftlen,
-			   " cntl 0x%x, no_scam 0x%x\n", ep->cntl, ep->no_scam);
-	ASC_PRT_NEXT();
-
-	len = asc_prt_line(cp, leftlen, " Target ID:           ");
-	ASC_PRT_NEXT();
-	for (i = 0; i <= ASC_MAX_TID; i++) {
-		len = asc_prt_line(cp, leftlen, " %d", i);
-		ASC_PRT_NEXT();
-	}
-	len = asc_prt_line(cp, leftlen, "\n");
-	ASC_PRT_NEXT();
-
-	len = asc_prt_line(cp, leftlen, " Disconnects:         ");
-	ASC_PRT_NEXT();
-	for (i = 0; i <= ASC_MAX_TID; i++) {
-		len = asc_prt_line(cp, leftlen, " %c",
-				   (ep->
-				    disc_enable & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
-				   'N');
-		ASC_PRT_NEXT();
-	}
-	len = asc_prt_line(cp, leftlen, "\n");
-	ASC_PRT_NEXT();
-
-	len = asc_prt_line(cp, leftlen, " Command Queuing:     ");
-	ASC_PRT_NEXT();
-	for (i = 0; i <= ASC_MAX_TID; i++) {
-		len = asc_prt_line(cp, leftlen, " %c",
-				   (ep->
-				    use_cmd_qng & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
-				   'N');
-		ASC_PRT_NEXT();
-	}
-	len = asc_prt_line(cp, leftlen, "\n");
-	ASC_PRT_NEXT();
-
-	len = asc_prt_line(cp, leftlen, " Start Motor:         ");
-	ASC_PRT_NEXT();
-	for (i = 0; i <= ASC_MAX_TID; i++) {
-		len = asc_prt_line(cp, leftlen, " %c",
-				   (ep->
-				    start_motor & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
-				   'N');
-		ASC_PRT_NEXT();
-	}
-	len = asc_prt_line(cp, leftlen, "\n");
-	ASC_PRT_NEXT();
-
-	len = asc_prt_line(cp, leftlen, " Synchronous Transfer:");
-	ASC_PRT_NEXT();
-	for (i = 0; i <= ASC_MAX_TID; i++) {
-		len = asc_prt_line(cp, leftlen, " %c",
-				   (ep->
-				    init_sdtr & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
-				   'N');
-		ASC_PRT_NEXT();
-	}
-	len = asc_prt_line(cp, leftlen, "\n");
-	ASC_PRT_NEXT();
+	    == ASC_TRUE)
+		seq_printf(m, " Serial Number: %s\n", serialstr);
+	else if (ep->adapter_info[5] == 0xBB)
+		seq_printf(m,
+			   " Default Settings Used for EEPROM-less Adapter.\n");
+	else
+		seq_printf(m,
+			   " Serial Number Signature Not Present.\n");
+
+	seq_printf(m,
+		   " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
+		   ASC_EEP_GET_CHIP_ID(ep), ep->max_total_qng,
+		   ep->max_tag_qng);
+
+	seq_printf(m,
+		   " cntl 0x%x, no_scam 0x%x\n", ep->cntl, ep->no_scam);
+
+	seq_printf(m, " Target ID:           ");
+	for (i = 0; i <= ASC_MAX_TID; i++)
+		seq_printf(m, " %d", i);
+	seq_printf(m, "\n");
+
+	seq_printf(m, " Disconnects:         ");
+	for (i = 0; i <= ASC_MAX_TID; i++)
+		seq_printf(m, " %c",
+			   (ep->disc_enable & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
+	seq_printf(m, "\n");
+
+	seq_printf(m, " Command Queuing:     ");
+	for (i = 0; i <= ASC_MAX_TID; i++)
+		seq_printf(m, " %c",
+			   (ep->use_cmd_qng & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
+	seq_printf(m, "\n");
+
+	seq_printf(m, " Start Motor:         ");
+	for (i = 0; i <= ASC_MAX_TID; i++)
+		seq_printf(m, " %c",
+			   (ep->start_motor & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
+	seq_printf(m, "\n");
+
+	seq_printf(m, " Synchronous Transfer:");
+	for (i = 0; i <= ASC_MAX_TID; i++)
+		seq_printf(m, " %c",
+			   (ep->init_sdtr & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
+	seq_printf(m, "\n");
 
 #ifdef CONFIG_ISA
 	if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
-		len = asc_prt_line(cp, leftlen,
-				   " Host ISA DMA speed:   %d MB/S\n",
-				   isa_dma_speed[ASC_EEP_GET_DMA_SPD(ep)]);
-		ASC_PRT_NEXT();
+		seq_printf(m,
+			   " Host ISA DMA speed:   %d MB/S\n",
+			   isa_dma_speed[ASC_EEP_GET_DMA_SPD(ep)]);
 	}
 #endif /* CONFIG_ISA */
-
-	return totlen;
 }
 
 /*
  * asc_prt_adv_board_eeprom()
  *
  * Print board EEPROM configuration.
- *
- * Note: no single line should be greater than ASC_PRTLINE_SIZE,
- * cf. asc_prt_line().
- *
- * Return the number of characters copied into 'cp'. No more than
- * 'cplen' characters will be copied to 'cp'.
  */
-static int asc_prt_adv_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen)
+static void asc_prt_adv_board_eeprom(struct seq_file *m, struct Scsi_Host *shost)
 {
 	struct asc_board *boardp = shost_priv(shost);
 	ADV_DVC_VAR *adv_dvc_varp;
-	int leftlen;
-	int totlen;
-	int len;
 	int i;
 	char *termstr;
 	uchar serialstr[13];
@@ -3281,13 +3136,9 @@ static int asc_prt_adv_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen
 		ep_38C1600 = &boardp->eep_config.adv_38C1600_eep;
 	}
 
-	leftlen = cplen;
-	totlen = len = 0;
-
-	len = asc_prt_line(cp, leftlen,
-			   "\nEEPROM Settings for AdvanSys SCSI Host %d:\n",
-			   shost->host_no);
-	ASC_PRT_NEXT();
+	seq_printf(m,
+		   "\nEEPROM Settings for AdvanSys SCSI Host %d:\n",
+		   shost->host_no);
 
 	if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
 		wordp = &ep_3550->serial_number_word1;
@@ -3297,38 +3148,28 @@ static int asc_prt_adv_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen
 		wordp = &ep_38C1600->serial_number_word1;
 	}
 
-	if (asc_get_eeprom_string(wordp, serialstr) == ASC_TRUE) {
-		len =
-		    asc_prt_line(cp, leftlen, " Serial Number: %s\n",
-				 serialstr);
-		ASC_PRT_NEXT();
-	} else {
-		len = asc_prt_line(cp, leftlen,
-				   " Serial Number Signature Not Present.\n");
-		ASC_PRT_NEXT();
-	}
+	if (asc_get_eeprom_string(wordp, serialstr) == ASC_TRUE)
+		seq_printf(m, " Serial Number: %s\n", serialstr);
+	else
+		seq_printf(m, " Serial Number Signature Not Present.\n");
 
-	if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
-		len = asc_prt_line(cp, leftlen,
-				   " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
-				   ep_3550->adapter_scsi_id,
-				   ep_3550->max_host_qng, ep_3550->max_dvc_qng);
-		ASC_PRT_NEXT();
-	} else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
-		len = asc_prt_line(cp, leftlen,
-				   " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
-				   ep_38C0800->adapter_scsi_id,
-				   ep_38C0800->max_host_qng,
-				   ep_38C0800->max_dvc_qng);
-		ASC_PRT_NEXT();
-	} else {
-		len = asc_prt_line(cp, leftlen,
-				   " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
-				   ep_38C1600->adapter_scsi_id,
-				   ep_38C1600->max_host_qng,
-				   ep_38C1600->max_dvc_qng);
-		ASC_PRT_NEXT();
-	}
+	if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550)
+		seq_printf(m,
+			   " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
+			   ep_3550->adapter_scsi_id,
+			   ep_3550->max_host_qng, ep_3550->max_dvc_qng);
+	else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800)
+		seq_printf(m,
+			   " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
+			   ep_38C0800->adapter_scsi_id,
+			   ep_38C0800->max_host_qng,
+			   ep_38C0800->max_dvc_qng);
+	else
+		seq_printf(m,
+			   " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
+			   ep_38C1600->adapter_scsi_id,
+			   ep_38C1600->max_host_qng,
+			   ep_38C1600->max_dvc_qng);
 	if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
 		word = ep_3550->termination;
 	} else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
@@ -3352,34 +3193,26 @@ static int asc_prt_adv_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen
 		break;
 	}
 
-	if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
-		len = asc_prt_line(cp, leftlen,
-				   " termination: %u (%s), bios_ctrl: 0x%x\n",
-				   ep_3550->termination, termstr,
-				   ep_3550->bios_ctrl);
-		ASC_PRT_NEXT();
-	} else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
-		len = asc_prt_line(cp, leftlen,
-				   " termination: %u (%s), bios_ctrl: 0x%x\n",
-				   ep_38C0800->termination_lvd, termstr,
-				   ep_38C0800->bios_ctrl);
-		ASC_PRT_NEXT();
-	} else {
-		len = asc_prt_line(cp, leftlen,
-				   " termination: %u (%s), bios_ctrl: 0x%x\n",
-				   ep_38C1600->termination_lvd, termstr,
-				   ep_38C1600->bios_ctrl);
-		ASC_PRT_NEXT();
-	}
+	if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550)
+		seq_printf(m,
+			   " termination: %u (%s), bios_ctrl: 0x%x\n",
+			   ep_3550->termination, termstr,
+			   ep_3550->bios_ctrl);
+	else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800)
+		seq_printf(m,
+			   " termination: %u (%s), bios_ctrl: 0x%x\n",
+			   ep_38C0800->termination_lvd, termstr,
+			   ep_38C0800->bios_ctrl);
+	else
+		seq_printf(m,
+			   " termination: %u (%s), bios_ctrl: 0x%x\n",
+			   ep_38C1600->termination_lvd, termstr,
+			   ep_38C1600->bios_ctrl);
 
-	len = asc_prt_line(cp, leftlen, " Target ID:           ");
-	ASC_PRT_NEXT();
-	for (i = 0; i <= ADV_MAX_TID; i++) {
-		len = asc_prt_line(cp, leftlen, " %X", i);
-		ASC_PRT_NEXT();
-	}
-	len = asc_prt_line(cp, leftlen, "\n");
-	ASC_PRT_NEXT();
+	seq_printf(m, " Target ID:           ");
+	for (i = 0; i <= ADV_MAX_TID; i++)
+		seq_printf(m, " %X", i);
+	seq_printf(m, "\n");
 
 	if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
 		word = ep_3550->disc_enable;
@@ -3388,15 +3221,11 @@ static int asc_prt_adv_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen
 	} else {
 		word = ep_38C1600->disc_enable;
 	}
-	len = asc_prt_line(cp, leftlen, " Disconnects:         ");
-	ASC_PRT_NEXT();
-	for (i = 0; i <= ADV_MAX_TID; i++) {
-		len = asc_prt_line(cp, leftlen, " %c",
-				   (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
-		ASC_PRT_NEXT();
-	}
-	len = asc_prt_line(cp, leftlen, "\n");
-	ASC_PRT_NEXT();
+	seq_printf(m, " Disconnects:         ");
+	for (i = 0; i <= ADV_MAX_TID; i++)
+		seq_printf(m, " %c",
+			   (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
+	seq_printf(m, "\n");
 
 	if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
 		word = ep_3550->tagqng_able;
@@ -3405,15 +3234,11 @@ static int asc_prt_adv_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen
 	} else {
 		word = ep_38C1600->tagqng_able;
 	}
-	len = asc_prt_line(cp, leftlen, " Command Queuing:     ");
-	ASC_PRT_NEXT();
-	for (i = 0; i <= ADV_MAX_TID; i++) {
-		len = asc_prt_line(cp, leftlen, " %c",
-				   (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
-		ASC_PRT_NEXT();
-	}
-	len = asc_prt_line(cp, leftlen, "\n");
-	ASC_PRT_NEXT();
+	seq_printf(m, " Command Queuing:     ");
+	for (i = 0; i <= ADV_MAX_TID; i++)
+		seq_printf(m, " %c",
+			   (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
+	seq_printf(m, "\n");
 
 	if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
 		word = ep_3550->start_motor;
@@ -3422,42 +3247,28 @@ static int asc_prt_adv_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen
 	} else {
 		word = ep_38C1600->start_motor;
 	}
-	len = asc_prt_line(cp, leftlen, " Start Motor:         ");
-	ASC_PRT_NEXT();
-	for (i = 0; i <= ADV_MAX_TID; i++) {
-		len = asc_prt_line(cp, leftlen, " %c",
-				   (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
-		ASC_PRT_NEXT();
-	}
-	len = asc_prt_line(cp, leftlen, "\n");
-	ASC_PRT_NEXT();
+	seq_printf(m, " Start Motor:         ");
+	for (i = 0; i <= ADV_MAX_TID; i++)
+		seq_printf(m, " %c",
+			   (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
+	seq_printf(m, "\n");
 
 	if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
-		len = asc_prt_line(cp, leftlen, " Synchronous Transfer:");
-		ASC_PRT_NEXT();
-		for (i = 0; i <= ADV_MAX_TID; i++) {
-			len = asc_prt_line(cp, leftlen, " %c",
-					   (ep_3550->
-					    sdtr_able & ADV_TID_TO_TIDMASK(i)) ?
-					   'Y' : 'N');
-			ASC_PRT_NEXT();
-		}
-		len = asc_prt_line(cp, leftlen, "\n");
-		ASC_PRT_NEXT();
+		seq_printf(m, " Synchronous Transfer:");
+		for (i = 0; i <= ADV_MAX_TID; i++)
+			seq_printf(m, " %c",
+				   (ep_3550->sdtr_able & ADV_TID_TO_TIDMASK(i)) ?
+				   'Y' : 'N');
+		seq_printf(m, "\n");
 	}
 
 	if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
-		len = asc_prt_line(cp, leftlen, " Ultra Transfer:      ");
-		ASC_PRT_NEXT();
-		for (i = 0; i <= ADV_MAX_TID; i++) {
-			len = asc_prt_line(cp, leftlen, " %c",
-					   (ep_3550->
-					    ultra_able & ADV_TID_TO_TIDMASK(i))
-					   ? 'Y' : 'N');
-			ASC_PRT_NEXT();
-		}
-		len = asc_prt_line(cp, leftlen, "\n");
-		ASC_PRT_NEXT();
+		seq_printf(m, " Ultra Transfer:      ");
+		for (i = 0; i <= ADV_MAX_TID; i++)
+			seq_printf(m, " %c",
+				   (ep_3550->ultra_able & ADV_TID_TO_TIDMASK(i))
+				   ? 'Y' : 'N');
+		seq_printf(m, "\n");
 	}
 
 	if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
@@ -3467,21 +3278,16 @@ static int asc_prt_adv_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen
 	} else {
 		word = ep_38C1600->wdtr_able;
 	}
-	len = asc_prt_line(cp, leftlen, " Wide Transfer:       ");
-	ASC_PRT_NEXT();
-	for (i = 0; i <= ADV_MAX_TID; i++) {
-		len = asc_prt_line(cp, leftlen, " %c",
-				   (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
-		ASC_PRT_NEXT();
-	}
-	len = asc_prt_line(cp, leftlen, "\n");
-	ASC_PRT_NEXT();
+	seq_printf(m, " Wide Transfer:       ");
+	for (i = 0; i <= ADV_MAX_TID; i++)
+		seq_printf(m, " %c",
+			   (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
+	seq_printf(m, "\n");
 
 	if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800 ||
 	    adv_dvc_varp->chip_type == ADV_CHIP_ASC38C1600) {
-		len = asc_prt_line(cp, leftlen,
-				   " Synchronous Transfer Speed (Mhz):\n  ");
-		ASC_PRT_NEXT();
+		seq_printf(m,
+			   " Synchronous Transfer Speed (Mhz):\n  ");
 		for (i = 0; i <= ADV_MAX_TID; i++) {
 			char *speed_str;
 
@@ -3517,99 +3323,64 @@ static int asc_prt_adv_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen
 				speed_str = "Unk";
 				break;
 			}
-			len = asc_prt_line(cp, leftlen, "%X:%s ", i, speed_str);
-			ASC_PRT_NEXT();
-			if (i == 7) {
-				len = asc_prt_line(cp, leftlen, "\n  ");
-				ASC_PRT_NEXT();
-			}
+			seq_printf(m, "%X:%s ", i, speed_str);
+			if (i == 7)
+				seq_printf(m, "\n  ");
 			sdtr_speed >>= 4;
 		}
-		len = asc_prt_line(cp, leftlen, "\n");
-		ASC_PRT_NEXT();
+		seq_printf(m, "\n");
 	}
-
-	return totlen;
 }
 
 /*
  * asc_prt_driver_conf()
- *
- * Note: no single line should be greater than ASC_PRTLINE_SIZE,
- * cf. asc_prt_line().
- *
- * Return the number of characters copied into 'cp'. No more than
- * 'cplen' characters will be copied to 'cp'.
  */
-static int asc_prt_driver_conf(struct Scsi_Host *shost, char *cp, int cplen)
+static void asc_prt_driver_conf(struct seq_file *m, struct Scsi_Host *shost)
 {
 	struct asc_board *boardp = shost_priv(shost);
-	int leftlen;
-	int totlen;
-	int len;
 	int chip_scsi_id;
 
-	leftlen = cplen;
-	totlen = len = 0;
+	seq_printf(m,
+		"\nLinux Driver Configuration and Information for AdvanSys SCSI Host %d:\n",
+		shost->host_no);
 
-	len = asc_prt_line(cp, leftlen,
-			   "\nLinux Driver Configuration and Information for AdvanSys SCSI Host %d:\n",
-			   shost->host_no);
-	ASC_PRT_NEXT();
+	seq_printf(m,
+		   " host_busy %u, last_reset %lu, max_id %u, max_lun %u, max_channel %u\n",
+		   shost->host_busy, shost->last_reset, shost->max_id,
+		   shost->max_lun, shost->max_channel);
 
-	len = asc_prt_line(cp, leftlen,
-			   " host_busy %u, last_reset %u, max_id %u, max_lun %u, max_channel %u\n",
-			   shost->host_busy, shost->last_reset, shost->max_id,
-			   shost->max_lun, shost->max_channel);
-	ASC_PRT_NEXT();
+	seq_printf(m,
+		   " unique_id %d, can_queue %d, this_id %d, sg_tablesize %u, cmd_per_lun %u\n",
+		   shost->unique_id, shost->can_queue, shost->this_id,
+		   shost->sg_tablesize, shost->cmd_per_lun);
 
-	len = asc_prt_line(cp, leftlen,
-			   " unique_id %d, can_queue %d, this_id %d, sg_tablesize %u, cmd_per_lun %u\n",
-			   shost->unique_id, shost->can_queue, shost->this_id,
-			   shost->sg_tablesize, shost->cmd_per_lun);
-	ASC_PRT_NEXT();
+	seq_printf(m,
+		   " unchecked_isa_dma %d, use_clustering %d\n",
+		   shost->unchecked_isa_dma, shost->use_clustering);
 
-	len = asc_prt_line(cp, leftlen,
-			   " unchecked_isa_dma %d, use_clustering %d\n",
-			   shost->unchecked_isa_dma, shost->use_clustering);
-	ASC_PRT_NEXT();
+	seq_printf(m,
+		   " flags 0x%x, last_reset 0x%lx, jiffies 0x%lx, asc_n_io_port 0x%x\n",
+		   boardp->flags, boardp->last_reset, jiffies,
+		   boardp->asc_n_io_port);
 
-	len = asc_prt_line(cp, leftlen,
-			   " flags 0x%x, last_reset 0x%x, jiffies 0x%x, asc_n_io_port 0x%x\n",
-			   boardp->flags, boardp->last_reset, jiffies,
-			   boardp->asc_n_io_port);
-	ASC_PRT_NEXT();
-
-	len = asc_prt_line(cp, leftlen, " io_port 0x%x\n", shost->io_port);
-	ASC_PRT_NEXT();
+	seq_printf(m, " io_port 0x%lx\n", shost->io_port);
 
 	if (ASC_NARROW_BOARD(boardp)) {
 		chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id;
 	} else {
 		chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id;
 	}
-
-	return totlen;
 }
 
 /*
  * asc_prt_asc_board_info()
  *
  * Print dynamic board configuration information.
- *
- * Note: no single line should be greater than ASC_PRTLINE_SIZE,
- * cf. asc_prt_line().
- *
- * Return the number of characters copied into 'cp'. No more than
- * 'cplen' characters will be copied to 'cp'.
  */
-static int asc_prt_asc_board_info(struct Scsi_Host *shost, char *cp, int cplen)
+static void asc_prt_asc_board_info(struct seq_file *m, struct Scsi_Host *shost)
 {
 	struct asc_board *boardp = shost_priv(shost);
 	int chip_scsi_id;
-	int leftlen;
-	int totlen;
-	int len;
 	ASC_DVC_VAR *v;
 	ASC_DVC_CFG *c;
 	int i;
@@ -3619,105 +3390,79 @@ static int asc_prt_asc_board_info(struct Scsi_Host *shost, char *cp, int cplen)
 	c = &boardp->dvc_cfg.asc_dvc_cfg;
 	chip_scsi_id = c->chip_scsi_id;
 
-	leftlen = cplen;
-	totlen = len = 0;
+	seq_printf(m,
+		   "\nAsc Library Configuration and Statistics for AdvanSys SCSI Host %d:\n",
+		   shost->host_no);
 
-	len = asc_prt_line(cp, leftlen,
-			   "\nAsc Library Configuration and Statistics for AdvanSys SCSI Host %d:\n",
-			   shost->host_no);
-	ASC_PRT_NEXT();
-
-	len = asc_prt_line(cp, leftlen, " chip_version %u, mcode_date 0x%x, "
-			   "mcode_version 0x%x, err_code %u\n",
-			   c->chip_version, c->mcode_date, c->mcode_version,
-			   v->err_code);
-	ASC_PRT_NEXT();
+	seq_printf(m, " chip_version %u, mcode_date 0x%x, "
+		   "mcode_version 0x%x, err_code %u\n",
+		   c->chip_version, c->mcode_date, c->mcode_version,
+		   v->err_code);
 
 	/* Current number of commands waiting for the host. */
-	len = asc_prt_line(cp, leftlen,
-			   " Total Command Pending: %d\n", v->cur_total_qng);
-	ASC_PRT_NEXT();
+	seq_printf(m,
+		   " Total Command Pending: %d\n", v->cur_total_qng);
 
-	len = asc_prt_line(cp, leftlen, " Command Queuing:");
-	ASC_PRT_NEXT();
+	seq_printf(m, " Command Queuing:");
 	for (i = 0; i <= ASC_MAX_TID; i++) {
 		if ((chip_scsi_id == i) ||
 		    ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
 			continue;
 		}
-		len = asc_prt_line(cp, leftlen, " %X:%c",
-				   i,
-				   (v->
-				    use_tagged_qng & ADV_TID_TO_TIDMASK(i)) ?
-				   'Y' : 'N');
-		ASC_PRT_NEXT();
+		seq_printf(m, " %X:%c",
+			   i,
+			   (v->use_tagged_qng & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
 	}
-	len = asc_prt_line(cp, leftlen, "\n");
-	ASC_PRT_NEXT();
+	seq_printf(m, "\n");
 
 	/* Current number of commands waiting for a device. */
-	len = asc_prt_line(cp, leftlen, " Command Queue Pending:");
-	ASC_PRT_NEXT();
+	seq_printf(m, " Command Queue Pending:");
 	for (i = 0; i <= ASC_MAX_TID; i++) {
 		if ((chip_scsi_id == i) ||
 		    ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
 			continue;
 		}
-		len = asc_prt_line(cp, leftlen, " %X:%u", i, v->cur_dvc_qng[i]);
-		ASC_PRT_NEXT();
+		seq_printf(m, " %X:%u", i, v->cur_dvc_qng[i]);
 	}
-	len = asc_prt_line(cp, leftlen, "\n");
-	ASC_PRT_NEXT();
+	seq_printf(m, "\n");
 
 	/* Current limit on number of commands that can be sent to a device. */
-	len = asc_prt_line(cp, leftlen, " Command Queue Limit:");
-	ASC_PRT_NEXT();
+	seq_printf(m, " Command Queue Limit:");
 	for (i = 0; i <= ASC_MAX_TID; i++) {
 		if ((chip_scsi_id == i) ||
 		    ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
 			continue;
 		}
-		len = asc_prt_line(cp, leftlen, " %X:%u", i, v->max_dvc_qng[i]);
-		ASC_PRT_NEXT();
+		seq_printf(m, " %X:%u", i, v->max_dvc_qng[i]);
 	}
-	len = asc_prt_line(cp, leftlen, "\n");
-	ASC_PRT_NEXT();
+	seq_printf(m, "\n");
 
 	/* Indicate whether the device has returned queue full status. */
-	len = asc_prt_line(cp, leftlen, " Command Queue Full:");
-	ASC_PRT_NEXT();
+	seq_printf(m, " Command Queue Full:");
 	for (i = 0; i <= ASC_MAX_TID; i++) {
 		if ((chip_scsi_id == i) ||
 		    ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
 			continue;
 		}
-		if (boardp->queue_full & ADV_TID_TO_TIDMASK(i)) {
-			len = asc_prt_line(cp, leftlen, " %X:Y-%d",
-					   i, boardp->queue_full_cnt[i]);
-		} else {
-			len = asc_prt_line(cp, leftlen, " %X:N", i);
-		}
-		ASC_PRT_NEXT();
+		if (boardp->queue_full & ADV_TID_TO_TIDMASK(i))
+			seq_printf(m, " %X:Y-%d",
+				   i, boardp->queue_full_cnt[i]);
+		else
+			seq_printf(m, " %X:N", i);
 	}
-	len = asc_prt_line(cp, leftlen, "\n");
-	ASC_PRT_NEXT();
+	seq_printf(m, "\n");
 
-	len = asc_prt_line(cp, leftlen, " Synchronous Transfer:");
-	ASC_PRT_NEXT();
+	seq_printf(m, " Synchronous Transfer:");
 	for (i = 0; i <= ASC_MAX_TID; i++) {
 		if ((chip_scsi_id == i) ||
 		    ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
 			continue;
 		}
-		len = asc_prt_line(cp, leftlen, " %X:%c",
-				   i,
-				   (v->
-				    sdtr_done & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
-				   'N');
-		ASC_PRT_NEXT();
+		seq_printf(m, " %X:%c",
+			   i,
+			   (v->sdtr_done & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
 	}
-	len = asc_prt_line(cp, leftlen, "\n");
-	ASC_PRT_NEXT();
+	seq_printf(m, "\n");
 
 	for (i = 0; i <= ASC_MAX_TID; i++) {
 		uchar syn_period_ix;
@@ -3728,69 +3473,48 @@ static int asc_prt_asc_board_info(struct Scsi_Host *shost, char *cp, int cplen)
 			continue;
 		}
 
-		len = asc_prt_line(cp, leftlen, "  %X:", i);
-		ASC_PRT_NEXT();
+		seq_printf(m, "  %X:", i);
 
 		if ((boardp->sdtr_data[i] & ASC_SYN_MAX_OFFSET) == 0) {
-			len = asc_prt_line(cp, leftlen, " Asynchronous");
-			ASC_PRT_NEXT();
+			seq_printf(m, " Asynchronous");
 		} else {
 			syn_period_ix =
 			    (boardp->sdtr_data[i] >> 4) & (v->max_sdtr_index -
 							   1);
 
-			len = asc_prt_line(cp, leftlen,
-					   " Transfer Period Factor: %d (%d.%d Mhz),",
-					   v->sdtr_period_tbl[syn_period_ix],
-					   250 /
-					   v->sdtr_period_tbl[syn_period_ix],
-					   ASC_TENTHS(250,
-						      v->
-						      sdtr_period_tbl
-						      [syn_period_ix]));
-			ASC_PRT_NEXT();
+			seq_printf(m,
+				   " Transfer Period Factor: %d (%d.%d Mhz),",
+				   v->sdtr_period_tbl[syn_period_ix],
+				   250 / v->sdtr_period_tbl[syn_period_ix],
+				   ASC_TENTHS(250,
+					      v->sdtr_period_tbl[syn_period_ix]));
 
-			len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d",
-					   boardp->
-					   sdtr_data[i] & ASC_SYN_MAX_OFFSET);
-			ASC_PRT_NEXT();
+			seq_printf(m, " REQ/ACK Offset: %d",
+				   boardp->sdtr_data[i] & ASC_SYN_MAX_OFFSET);
 		}
 
 		if ((v->sdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
-			len = asc_prt_line(cp, leftlen, "*\n");
+			seq_printf(m, "*\n");
 			renegotiate = 1;
 		} else {
-			len = asc_prt_line(cp, leftlen, "\n");
+			seq_printf(m, "\n");
 		}
-		ASC_PRT_NEXT();
 	}
 
 	if (renegotiate) {
-		len = asc_prt_line(cp, leftlen,
-				   " * = Re-negotiation pending before next command.\n");
-		ASC_PRT_NEXT();
+		seq_printf(m,
+			   " * = Re-negotiation pending before next command.\n");
 	}
-
-	return totlen;
 }
 
 /*
  * asc_prt_adv_board_info()
  *
  * Print dynamic board configuration information.
- *
- * Note: no single line should be greater than ASC_PRTLINE_SIZE,
- * cf. asc_prt_line().
- *
- * Return the number of characters copied into 'cp'. No more than
- * 'cplen' characters will be copied to 'cp'.
  */
-static int asc_prt_adv_board_info(struct Scsi_Host *shost, char *cp, int cplen)
+static void asc_prt_adv_board_info(struct seq_file *m, struct Scsi_Host *shost)
 {
 	struct asc_board *boardp = shost_priv(shost);
-	int leftlen;
-	int totlen;
-	int len;
 	int i;
 	ADV_DVC_VAR *v;
 	ADV_DVC_CFG *c;
@@ -3809,47 +3533,35 @@ static int asc_prt_adv_board_info(struct Scsi_Host *shost, char *cp, int cplen)
 	iop_base = v->iop_base;
 	chip_scsi_id = v->chip_scsi_id;
 
-	leftlen = cplen;
-	totlen = len = 0;
-
-	len = asc_prt_line(cp, leftlen,
-			   "\nAdv Library Configuration and Statistics for AdvanSys SCSI Host %d:\n",
-			   shost->host_no);
-	ASC_PRT_NEXT();
+	seq_printf(m,
+		   "\nAdv Library Configuration and Statistics for AdvanSys SCSI Host %d:\n",
+		   shost->host_no);
 
-	len = asc_prt_line(cp, leftlen,
-			   " iop_base 0x%lx, cable_detect: %X, err_code %u\n",
-			   v->iop_base,
-			   AdvReadWordRegister(iop_base,
-					       IOPW_SCSI_CFG1) & CABLE_DETECT,
-			   v->err_code);
-	ASC_PRT_NEXT();
+	seq_printf(m,
+		   " iop_base 0x%lx, cable_detect: %X, err_code %u\n",
+		   (unsigned long)v->iop_base,
+		   AdvReadWordRegister(iop_base,IOPW_SCSI_CFG1) & CABLE_DETECT,
+		   v->err_code);
 
-	len = asc_prt_line(cp, leftlen, " chip_version %u, mcode_date 0x%x, "
-			   "mcode_version 0x%x\n", c->chip_version,
-			   c->mcode_date, c->mcode_version);
-	ASC_PRT_NEXT();
+	seq_printf(m, " chip_version %u, mcode_date 0x%x, "
+		   "mcode_version 0x%x\n", c->chip_version,
+		   c->mcode_date, c->mcode_version);
 
 	AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
-	len = asc_prt_line(cp, leftlen, " Queuing Enabled:");
-	ASC_PRT_NEXT();
+	seq_printf(m, " Queuing Enabled:");
 	for (i = 0; i <= ADV_MAX_TID; i++) {
 		if ((chip_scsi_id == i) ||
 		    ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
 			continue;
 		}
 
-		len = asc_prt_line(cp, leftlen, " %X:%c",
-				   i,
-				   (tagqng_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
-				   'N');
-		ASC_PRT_NEXT();
+		seq_printf(m, " %X:%c",
+			   i,
+			   (tagqng_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
 	}
-	len = asc_prt_line(cp, leftlen, "\n");
-	ASC_PRT_NEXT();
+	seq_printf(m, "\n");
 
-	len = asc_prt_line(cp, leftlen, " Queue Limit:");
-	ASC_PRT_NEXT();
+	seq_printf(m, " Queue Limit:");
 	for (i = 0; i <= ADV_MAX_TID; i++) {
 		if ((chip_scsi_id == i) ||
 		    ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
@@ -3859,14 +3571,11 @@ static int asc_prt_adv_board_info(struct Scsi_Host *shost, char *cp, int cplen)
 		AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + i,
 				lrambyte);
 
-		len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte);
-		ASC_PRT_NEXT();
+		seq_printf(m, " %X:%d", i, lrambyte);
 	}
-	len = asc_prt_line(cp, leftlen, "\n");
-	ASC_PRT_NEXT();
+	seq_printf(m, "\n");
 
-	len = asc_prt_line(cp, leftlen, " Command Pending:");
-	ASC_PRT_NEXT();
+	seq_printf(m, " Command Pending:");
 	for (i = 0; i <= ADV_MAX_TID; i++) {
 		if ((chip_scsi_id == i) ||
 		    ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
@@ -3876,33 +3585,26 @@ static int asc_prt_adv_board_info(struct Scsi_Host *shost, char *cp, int cplen)
 		AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_QUEUED_CMD + i,
 				lrambyte);
 
-		len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte);
-		ASC_PRT_NEXT();
+		seq_printf(m, " %X:%d", i, lrambyte);
 	}
-	len = asc_prt_line(cp, leftlen, "\n");
-	ASC_PRT_NEXT();
+	seq_printf(m, "\n");
 
 	AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
-	len = asc_prt_line(cp, leftlen, " Wide Enabled:");
-	ASC_PRT_NEXT();
+	seq_printf(m, " Wide Enabled:");
 	for (i = 0; i <= ADV_MAX_TID; i++) {
 		if ((chip_scsi_id == i) ||
 		    ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
 			continue;
 		}
 
-		len = asc_prt_line(cp, leftlen, " %X:%c",
-				   i,
-				   (wdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
-				   'N');
-		ASC_PRT_NEXT();
+		seq_printf(m, " %X:%c",
+			   i,
+			   (wdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
 	}
-	len = asc_prt_line(cp, leftlen, "\n");
-	ASC_PRT_NEXT();
+	seq_printf(m, "\n");
 
 	AdvReadWordLram(iop_base, ASC_MC_WDTR_DONE, wdtr_done);
-	len = asc_prt_line(cp, leftlen, " Transfer Bit Width:");
-	ASC_PRT_NEXT();
+	seq_printf(m, " Transfer Bit Width:");
 	for (i = 0; i <= ADV_MAX_TID; i++) {
 		if ((chip_scsi_id == i) ||
 		    ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
@@ -3913,37 +3615,30 @@ static int asc_prt_adv_board_info(struct Scsi_Host *shost, char *cp, int cplen)
 				ASC_MC_DEVICE_HSHK_CFG_TABLE + (2 * i),
 				lramword);
 
-		len = asc_prt_line(cp, leftlen, " %X:%d",
-				   i, (lramword & 0x8000) ? 16 : 8);
-		ASC_PRT_NEXT();
+		seq_printf(m, " %X:%d",
+			   i, (lramword & 0x8000) ? 16 : 8);
 
 		if ((wdtr_able & ADV_TID_TO_TIDMASK(i)) &&
 		    (wdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
-			len = asc_prt_line(cp, leftlen, "*");
-			ASC_PRT_NEXT();
+			seq_printf(m, "*");
 			renegotiate = 1;
 		}
 	}
-	len = asc_prt_line(cp, leftlen, "\n");
-	ASC_PRT_NEXT();
+	seq_printf(m, "\n");
 
 	AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
-	len = asc_prt_line(cp, leftlen, " Synchronous Enabled:");
-	ASC_PRT_NEXT();
+	seq_printf(m, " Synchronous Enabled:");
 	for (i = 0; i <= ADV_MAX_TID; i++) {
 		if ((chip_scsi_id == i) ||
 		    ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
 			continue;
 		}
 
-		len = asc_prt_line(cp, leftlen, " %X:%c",
-				   i,
-				   (sdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
-				   'N');
-		ASC_PRT_NEXT();
+		seq_printf(m, " %X:%c",
+			   i,
+			   (sdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
 	}
-	len = asc_prt_line(cp, leftlen, "\n");
-	ASC_PRT_NEXT();
+	seq_printf(m, "\n");
 
 	AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, sdtr_done);
 	for (i = 0; i <= ADV_MAX_TID; i++) {
@@ -3959,358 +3654,170 @@ static int asc_prt_adv_board_info(struct Scsi_Host *shost, char *cp, int cplen)
 			continue;
 		}
 
-		len = asc_prt_line(cp, leftlen, "  %X:", i);
-		ASC_PRT_NEXT();
+		seq_printf(m, "  %X:", i);
 
 		if ((lramword & 0x1F) == 0) {	/* Check for REQ/ACK Offset 0. */
-			len = asc_prt_line(cp, leftlen, " Asynchronous");
-			ASC_PRT_NEXT();
+			seq_printf(m, " Asynchronous");
 		} else {
-			len =
-			    asc_prt_line(cp, leftlen,
-					 " Transfer Period Factor: ");
-			ASC_PRT_NEXT();
+			seq_printf(m, " Transfer Period Factor: ");
 
 			if ((lramword & 0x1F00) == 0x1100) {	/* 80 Mhz */
-				len =
-				    asc_prt_line(cp, leftlen, "9 (80.0 Mhz),");
-				ASC_PRT_NEXT();
+				seq_printf(m, "9 (80.0 Mhz),");
 			} else if ((lramword & 0x1F00) == 0x1000) {	/* 40 Mhz */
-				len =
-				    asc_prt_line(cp, leftlen, "10 (40.0 Mhz),");
-				ASC_PRT_NEXT();
+				seq_printf(m, "10 (40.0 Mhz),");
 			} else {	/* 20 Mhz or below. */
 
 				period = (((lramword >> 8) * 25) + 50) / 4;
 
 				if (period == 0) {	/* Should never happen. */
-					len =
-					    asc_prt_line(cp, leftlen,
-							 "%d (? Mhz), ");
-					ASC_PRT_NEXT();
+					seq_printf(m, "%d (? Mhz), ", period);
 				} else {
-					len = asc_prt_line(cp, leftlen,
-							   "%d (%d.%d Mhz),",
-							   period, 250 / period,
-							   ASC_TENTHS(250,
-								      period));
-					ASC_PRT_NEXT();
+					seq_printf(m,
+						   "%d (%d.%d Mhz),",
+						   period, 250 / period,
+						   ASC_TENTHS(250, period));
 				}
 			}
 
-			len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d",
-					   lramword & 0x1F);
-			ASC_PRT_NEXT();
+			seq_printf(m, " REQ/ACK Offset: %d",
+				   lramword & 0x1F);
 		}
 
 		if ((sdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
-			len = asc_prt_line(cp, leftlen, "*\n");
+			seq_printf(m, "*\n");
 			renegotiate = 1;
 		} else {
-			len = asc_prt_line(cp, leftlen, "\n");
+			seq_printf(m, "\n");
 		}
-		ASC_PRT_NEXT();
 	}
 
 	if (renegotiate) {
-		len = asc_prt_line(cp, leftlen,
-				   " * = Re-negotiation pending before next command.\n");
-		ASC_PRT_NEXT();
+		seq_printf(m,
+			   " * = Re-negotiation pending before next command.\n");
 	}
-
-	return totlen;
-}
-
-/*
- * asc_proc_copy()
- *
- * Copy proc information to a read buffer taking into account the current
- * read offset in the file and the remaining space in the read buffer.
- */
-static int
-asc_proc_copy(off_t advoffset, off_t offset, char *curbuf, int leftlen,
-	      char *cp, int cplen)
-{
-	int cnt = 0;
-
-	ASC_DBG(2, "offset %d, advoffset %d, cplen %d\n",
-		 (unsigned)offset, (unsigned)advoffset, cplen);
-	if (offset <= advoffset) {
-		/* Read offset below current offset, copy everything. */
-		cnt = min(cplen, leftlen);
-		ASC_DBG(2, "curbuf 0x%lx, cp 0x%lx, cnt %d\n",
-			 (ulong)curbuf, (ulong)cp, cnt);
-		memcpy(curbuf, cp, cnt);
-	} else if (offset < advoffset + cplen) {
-		/* Read offset within current range, partial copy. */
-		cnt = (advoffset + cplen) - offset;
-		cp = (cp + cplen) - cnt;
-		cnt = min(cnt, leftlen);
-		ASC_DBG(2, "curbuf 0x%lx, cp 0x%lx, cnt %d\n",
-			 (ulong)curbuf, (ulong)cp, cnt);
-		memcpy(curbuf, cp, cnt);
-	}
-	return cnt;
 }
 
 #ifdef ADVANSYS_STATS
 /*
  * asc_prt_board_stats()
- *
- * Note: no single line should be greater than ASC_PRTLINE_SIZE,
- * cf. asc_prt_line().
- *
- * Return the number of characters copied into 'cp'. No more than
- * 'cplen' characters will be copied to 'cp'.
  */
-static int asc_prt_board_stats(struct Scsi_Host *shost, char *cp, int cplen)
+static void asc_prt_board_stats(struct seq_file *m, struct Scsi_Host *shost)
 {
 	struct asc_board *boardp = shost_priv(shost);
 	struct asc_stats *s = &boardp->asc_stats;
 
-	int leftlen = cplen;
-	int len, totlen = 0;
+	seq_printf(m,
+		   "\nLinux Driver Statistics for AdvanSys SCSI Host %d:\n",
+		   shost->host_no);
 
-	len = asc_prt_line(cp, leftlen,
-			   "\nLinux Driver Statistics for AdvanSys SCSI Host %d:\n",
-			   shost->host_no);
-	ASC_PRT_NEXT();
+	seq_printf(m,
+		   " queuecommand %u, reset %u, biosparam %u, interrupt %u\n",
+		   s->queuecommand, s->reset, s->biosparam,
+		   s->interrupt);
 
-	len = asc_prt_line(cp, leftlen,
-			   " queuecommand %lu, reset %lu, biosparam %lu, interrupt %lu\n",
-			   s->queuecommand, s->reset, s->biosparam,
-			   s->interrupt);
-	ASC_PRT_NEXT();
+	seq_printf(m,
+		   " callback %u, done %u, build_error %u, build_noreq %u, build_nosg %u\n",
+		   s->callback, s->done, s->build_error,
+		   s->adv_build_noreq, s->adv_build_nosg);
 
-	len = asc_prt_line(cp, leftlen,
-			   " callback %lu, done %lu, build_error %lu, build_noreq %lu, build_nosg %lu\n",
-			   s->callback, s->done, s->build_error,
-			   s->adv_build_noreq, s->adv_build_nosg);
-	ASC_PRT_NEXT();
-
-	len = asc_prt_line(cp, leftlen,
-			   " exe_noerror %lu, exe_busy %lu, exe_error %lu, exe_unknown %lu\n",
-			   s->exe_noerror, s->exe_busy, s->exe_error,
-			   s->exe_unknown);
-	ASC_PRT_NEXT();
+	seq_printf(m,
+		   " exe_noerror %u, exe_busy %u, exe_error %u, exe_unknown %u\n",
+		   s->exe_noerror, s->exe_busy, s->exe_error,
+		   s->exe_unknown);
 
 	/*
 	 * Display data transfer statistics.
 	 */
 	if (s->xfer_cnt > 0) {
-		len = asc_prt_line(cp, leftlen, " xfer_cnt %lu, xfer_elem %lu, ",
-				   s->xfer_cnt, s->xfer_elem);
-		ASC_PRT_NEXT();
+		seq_printf(m, " xfer_cnt %u, xfer_elem %u, ",
+			   s->xfer_cnt, s->xfer_elem);
 
-		len = asc_prt_line(cp, leftlen, "xfer_bytes %lu.%01lu kb\n",
-				   s->xfer_sect / 2, ASC_TENTHS(s->xfer_sect, 2));
-		ASC_PRT_NEXT();
+		seq_printf(m, "xfer_bytes %u.%01u kb\n",
+			   s->xfer_sect / 2, ASC_TENTHS(s->xfer_sect, 2));
 
 		/* Scatter gather transfer statistics */
-		len = asc_prt_line(cp, leftlen, " avg_num_elem %lu.%01lu, ",
-				   s->xfer_elem / s->xfer_cnt,
-				   ASC_TENTHS(s->xfer_elem, s->xfer_cnt));
-		ASC_PRT_NEXT();
+		seq_printf(m, " avg_num_elem %u.%01u, ",
+			   s->xfer_elem / s->xfer_cnt,
+			   ASC_TENTHS(s->xfer_elem, s->xfer_cnt));
 
-		len = asc_prt_line(cp, leftlen, "avg_elem_size %lu.%01lu kb, ",
-				   (s->xfer_sect / 2) / s->xfer_elem,
-				   ASC_TENTHS((s->xfer_sect / 2), s->xfer_elem));
-		ASC_PRT_NEXT();
+		seq_printf(m, "avg_elem_size %u.%01u kb, ",
+			   (s->xfer_sect / 2) / s->xfer_elem,
+			   ASC_TENTHS((s->xfer_sect / 2), s->xfer_elem));
 
-		len = asc_prt_line(cp, leftlen, "avg_xfer_size %lu.%01lu kb\n",
-				   (s->xfer_sect / 2) / s->xfer_cnt,
-				   ASC_TENTHS((s->xfer_sect / 2), s->xfer_cnt));
-		ASC_PRT_NEXT();
+		seq_printf(m, "avg_xfer_size %u.%01u kb\n",
+			   (s->xfer_sect / 2) / s->xfer_cnt,
+			   ASC_TENTHS((s->xfer_sect / 2), s->xfer_cnt));
 	}
-
-	return totlen;
 }
 #endif /* ADVANSYS_STATS */
 
 /*
- * advansys_proc_info() - /proc/scsi/advansys/{0,1,2,3,...}
+ * advansys_show_info() - /proc/scsi/advansys/{0,1,2,3,...}
  *
- * *buffer: I/O buffer
- * **start: if inout == FALSE pointer into buffer where user read should start
- * offset: current offset into a /proc/scsi/advansys/[0...] file
- * length: length of buffer
- * hostno: Scsi_Host host_no
- * inout: TRUE - user is writing; FALSE - user is reading
+ * m: seq_file to print into
+ * shost: Scsi_Host
  *
  * Return the number of bytes read from or written to a
  * /proc/scsi/advansys/[0...] file.
- *
- * Note: This function uses the per board buffer 'prtbuf' which is
- * allocated when the board is initialized in advansys_detect(). The
- * buffer is ASC_PRTBUF_SIZE bytes. The function asc_proc_copy() is
- * used to write to the buffer. The way asc_proc_copy() is written
- * if 'prtbuf' is too small it will not be overwritten. Instead the
- * user just won't get all the available statistics.
  */
 static int
-advansys_proc_info(struct Scsi_Host *shost, char *buffer, char **start,
-		   off_t offset, int length, int inout)
+advansys_show_info(struct seq_file *m, struct Scsi_Host *shost)
 {
 	struct asc_board *boardp = shost_priv(shost);
-	char *cp;
-	int cplen;
-	int cnt;
-	int totcnt;
-	int leftlen;
-	char *curbuf;
-	off_t advoffset;
 
 	ASC_DBG(1, "begin\n");
 
 	/*
-	 * User write not supported.
-	 */
-	if (inout == TRUE)
-		return -ENOSYS;
-
-	/*
 	 * User read of /proc/scsi/advansys/[0...] file.
 	 */
 
-	/* Copy read data starting at the beginning of the buffer. */
-	*start = buffer;
-	curbuf = buffer;
-	advoffset = 0;
-	totcnt = 0;
-	leftlen = length;
-
 	/*
 	 * Get board configuration information.
 	 *
 	 * advansys_info() returns the board string from its own static buffer.
 	 */
-	cp = (char *)advansys_info(shost);
-	strcat(cp, "\n");
-	cplen = strlen(cp);
 	/* Copy board information. */
-	cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
-	totcnt += cnt;
-	leftlen -= cnt;
-	if (leftlen == 0) {
-		ASC_DBG(1, "totcnt %d\n", totcnt);
-		return totcnt;
-	}
-	advoffset += cplen;
-	curbuf += cnt;
-
+	seq_printf(m, "%s\n", (char *)advansys_info(shost));
 	/*
 	 * Display Wide Board BIOS Information.
 	 */
-	if (!ASC_NARROW_BOARD(boardp)) {
-		cp = boardp->prtbuf;
-		cplen = asc_prt_adv_bios(shost, cp, ASC_PRTBUF_SIZE);
-		BUG_ON(cplen >= ASC_PRTBUF_SIZE);
-		cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp,
-				  cplen);
-		totcnt += cnt;
-		leftlen -= cnt;
-		if (leftlen == 0) {
-			ASC_DBG(1, "totcnt %d\n", totcnt);
-			return totcnt;
-		}
-		advoffset += cplen;
-		curbuf += cnt;
-	}
+	if (!ASC_NARROW_BOARD(boardp))
+		asc_prt_adv_bios(m, shost);
 
 	/*
 	 * Display driver information for each device attached to the board.
 	 */
-	cp = boardp->prtbuf;
-	cplen = asc_prt_board_devices(shost, cp, ASC_PRTBUF_SIZE);
-	BUG_ON(cplen >= ASC_PRTBUF_SIZE);
-	cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
-	totcnt += cnt;
-	leftlen -= cnt;
-	if (leftlen == 0) {
-		ASC_DBG(1, "totcnt %d\n", totcnt);
-		return totcnt;
-	}
-	advoffset += cplen;
-	curbuf += cnt;
+	asc_prt_board_devices(m, shost);
 
 	/*
 	 * Display EEPROM configuration for the board.
 	 */
-	cp = boardp->prtbuf;
-	if (ASC_NARROW_BOARD(boardp)) {
-		cplen = asc_prt_asc_board_eeprom(shost, cp, ASC_PRTBUF_SIZE);
-	} else {
-		cplen = asc_prt_adv_board_eeprom(shost, cp, ASC_PRTBUF_SIZE);
-	}
-	BUG_ON(cplen >= ASC_PRTBUF_SIZE);
-	cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
-	totcnt += cnt;
-	leftlen -= cnt;
-	if (leftlen == 0) {
-		ASC_DBG(1, "totcnt %d\n", totcnt);
-		return totcnt;
-	}
-	advoffset += cplen;
-	curbuf += cnt;
+	if (ASC_NARROW_BOARD(boardp))
+		asc_prt_asc_board_eeprom(m, shost);
+	else
+		asc_prt_adv_board_eeprom(m, shost);
 
 	/*
 	 * Display driver configuration and information for the board.
 	 */
-	cp = boardp->prtbuf;
-	cplen = asc_prt_driver_conf(shost, cp, ASC_PRTBUF_SIZE);
-	BUG_ON(cplen >= ASC_PRTBUF_SIZE);
-	cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
-	totcnt += cnt;
-	leftlen -= cnt;
-	if (leftlen == 0) {
-		ASC_DBG(1, "totcnt %d\n", totcnt);
-		return totcnt;
-	}
-	advoffset += cplen;
-	curbuf += cnt;
+	asc_prt_driver_conf(m, shost);
 
 #ifdef ADVANSYS_STATS
 	/*
 	 * Display driver statistics for the board.
 	 */
-	cp = boardp->prtbuf;
-	cplen = asc_prt_board_stats(shost, cp, ASC_PRTBUF_SIZE);
-	BUG_ON(cplen >= ASC_PRTBUF_SIZE);
-	cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
-	totcnt += cnt;
-	leftlen -= cnt;
-	if (leftlen == 0) {
-		ASC_DBG(1, "totcnt %d\n", totcnt);
-		return totcnt;
-	}
-	advoffset += cplen;
-	curbuf += cnt;
+	asc_prt_board_stats(m, shost);
 #endif /* ADVANSYS_STATS */
 
 	/*
 	 * Display Asc Library dynamic configuration information
 	 * for the board.
 	 */
-	cp = boardp->prtbuf;
-	if (ASC_NARROW_BOARD(boardp)) {
-		cplen = asc_prt_asc_board_info(shost, cp, ASC_PRTBUF_SIZE);
-	} else {
-		cplen = asc_prt_adv_board_info(shost, cp, ASC_PRTBUF_SIZE);
-	}
-	BUG_ON(cplen >= ASC_PRTBUF_SIZE);
-	cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
-	totcnt += cnt;
-	leftlen -= cnt;
-	if (leftlen == 0) {
-		ASC_DBG(1, "totcnt %d\n", totcnt);
-		return totcnt;
-	}
-	advoffset += cplen;
-	curbuf += cnt;
-
-	ASC_DBG(1, "totcnt %d\n", totcnt);
-
-	return totcnt;
+	if (ASC_NARROW_BOARD(boardp))
+		asc_prt_asc_board_info(m, shost);
+	else
+		asc_prt_adv_board_info(m, shost);
+	return 0;
 }
 #endif /* CONFIG_PROC_FS */
 
@@ -11743,7 +11250,7 @@ static int AdvInitGetConfig(struct pci_dev *pdev, struct Scsi_Host *shost)
 static struct scsi_host_template advansys_template = {
 	.proc_name = DRV_NAME,
 #ifdef CONFIG_PROC_FS
-	.proc_info = advansys_proc_info,
+	.show_info = advansys_show_info,
 #endif
 	.name = DRV_NAME,
 	.info = advansys_info,
@@ -11939,20 +11446,6 @@ static int advansys_board_found(struct Scsi_Host *shost, unsigned int iop,
 #endif /* CONFIG_PCI */
 	}
 
-#ifdef CONFIG_PROC_FS
-	/*
-	 * Allocate buffer for printing information from
-	 * /proc/scsi/advansys/[0...].
-	 */
-	boardp->prtbuf = kmalloc(ASC_PRTBUF_SIZE, GFP_KERNEL);
-	if (!boardp->prtbuf) {
-		shost_printk(KERN_ERR, shost, "kmalloc(%d) returned NULL\n",
-				ASC_PRTBUF_SIZE);
-		ret = -ENOMEM;
-		goto err_unmap;
-	}
-#endif /* CONFIG_PROC_FS */
-
 	if (ASC_NARROW_BOARD(boardp)) {
 		/*
 		 * Set the board bus type and PCI IRQ before
@@ -12010,7 +11503,7 @@ static int advansys_board_found(struct Scsi_Host *shost, unsigned int iop,
 	}
 
 	if (ret)
-		goto err_free_proc;
+		goto err_unmap;
 
 	/*
 	 * Save the EEPROM configuration so that it can be displayed
@@ -12055,7 +11548,7 @@ static int advansys_board_found(struct Scsi_Host *shost, unsigned int iop,
 		ASC_DBG(2, "AscInitSetConfig()\n");
 		ret = AscInitSetConfig(pdev, shost) ? -ENODEV : 0;
 		if (ret)
-			goto err_free_proc;
+			goto err_unmap;
 	} else {
 		ADVEEP_3550_CONFIG *ep_3550;
 		ADVEEP_38C0800_CONFIG *ep_38C0800;
@@ -12290,7 +11783,7 @@ static int advansys_board_found(struct Scsi_Host *shost, unsigned int iop,
 				shost_printk(KERN_ERR, shost, "request_dma() "
 						"%d failed %d\n",
 						shost->dma_channel, ret);
-				goto err_free_proc;
+				goto err_unmap;
 			}
 			AscEnableIsaDma(shost->dma_channel);
 		}
@@ -12371,8 +11864,6 @@ static int advansys_board_found(struct Scsi_Host *shost, unsigned int iop,
 	if (shost->dma_channel != NO_ISA_DMA)
 		free_dma(shost->dma_channel);
 #endif
- err_free_proc:
-	kfree(boardp->prtbuf);
  err_unmap:
 	if (boardp->ioremap_addr)
 		iounmap(boardp->ioremap_addr);
@@ -12406,7 +11897,6 @@ static int advansys_release(struct Scsi_Host *shost)
 		iounmap(board->ioremap_addr);
 		advansys_wide_free_mem(board);
 	}
-	kfree(board->prtbuf);
 	scsi_host_put(shost);
 	ASC_DBG(1, "end\n");
 	return 0;
diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c
index a284be1..3f7b6fe 100644
--- a/drivers/scsi/aha152x.c
+++ b/drivers/scsi/aha152x.c
@@ -2977,11 +2977,10 @@ static void show_queues(struct Scsi_Host *shpnt)
 }
 
 #undef SPRINTF
-#define SPRINTF(args...) pos += sprintf(pos, ## args)
+#define SPRINTF(args...) seq_printf(m, ##args)
 
-static int get_command(char *pos, Scsi_Cmnd * ptr)
+static void get_command(struct seq_file *m, Scsi_Cmnd * ptr)
 {
-	char *start = pos;
 	int i;
 
 	SPRINTF("%p: target=%d; lun=%d; cmnd=( ",
@@ -3011,13 +3010,10 @@ static int get_command(char *pos, Scsi_Cmnd * ptr)
 	if (ptr->SCp.phase & syncneg)
 		SPRINTF("syncneg|");
 	SPRINTF("; next=0x%p\n", SCNEXT(ptr));
-
-	return (pos - start);
 }
 
-static int get_ports(struct Scsi_Host *shpnt, char *pos)
+static void get_ports(struct seq_file *m, struct Scsi_Host *shpnt)
 {
-	char *start = pos;
 	int s;
 
 	SPRINTF("\n%s: %s(%s) ", CURRENT_SC ? "on bus" : "waiting", states[STATE].name, states[PREVSTATE].name);
@@ -3273,11 +3269,9 @@ static int get_ports(struct Scsi_Host *shpnt, char *pos)
 	if (s & ENREQINIT)
 		SPRINTF("ENREQINIT ");
 	SPRINTF(")\n");
-
-	return (pos - start);
 }
 
-static int aha152x_set_info(char *buffer, int length, struct Scsi_Host *shpnt)
+static int aha152x_set_info(struct Scsi_Host *shpnt, char *buffer, int length)
 {
 	if(!shpnt || !buffer || length<8 || strncmp("aha152x ", buffer, 8)!=0)
 		return -EINVAL;
@@ -3320,26 +3314,11 @@ static int aha152x_set_info(char *buffer, int length, struct Scsi_Host *shpnt)
 	return length;
 }
 
-#undef SPRINTF
-#define SPRINTF(args...) \
-	do { if(pos < buffer + length) pos += sprintf(pos, ## args); } while(0)
-
-static int aha152x_proc_info(struct Scsi_Host *shpnt, char *buffer, char **start,
-		      off_t offset, int length, int inout)
+static int aha152x_show_info(struct seq_file *m, struct Scsi_Host *shpnt)
 {
 	int i;
-	char *pos = buffer;
 	Scsi_Cmnd *ptr;
 	unsigned long flags;
-	int thislength;
-
-	DPRINTK(debug_procinfo, 
-	       KERN_DEBUG "aha152x_proc_info: buffer=%p offset=%ld length=%d hostno=%d inout=%d\n",
-	       buffer, offset, length, shpnt->host_no, inout);
-
-
-	if (inout)
-		return aha152x_set_info(buffer, length, shpnt);
 
 	SPRINTF(AHA152X_REVID "\n");
 
@@ -3392,25 +3371,25 @@ static int aha152x_proc_info(struct Scsi_Host *shpnt, char *buffer, char **start
 	if (ISSUE_SC) {
 		SPRINTF("not yet issued commands:\n");
 		for (ptr = ISSUE_SC; ptr; ptr = SCNEXT(ptr))
-			pos += get_command(pos, ptr);
+			get_command(m, ptr);
 	} else
 		SPRINTF("no not yet issued commands\n");
 	DO_UNLOCK(flags);
 
 	if (CURRENT_SC) {
 		SPRINTF("current command:\n");
-		pos += get_command(pos, CURRENT_SC);
+		get_command(m, CURRENT_SC);
 	} else
 		SPRINTF("no current command\n");
 
 	if (DISCONNECTED_SC) {
 		SPRINTF("disconnected commands:\n");
 		for (ptr = DISCONNECTED_SC; ptr; ptr = SCNEXT(ptr))
-			pos += get_command(pos, ptr);
+			get_command(m, ptr);
 	} else
 		SPRINTF("no disconnected commands\n");
 
-	pos += get_ports(shpnt, pos);
+	get_ports(m, shpnt);
 
 #if defined(AHA152X_STAT)
 	SPRINTF("statistics:\n"
@@ -3440,24 +3419,7 @@ static int aha152x_proc_info(struct Scsi_Host *shpnt, char *buffer, char **start
 			HOSTDATA(shpnt)->time[i]);
 	}
 #endif
-
-	DPRINTK(debug_procinfo, KERN_DEBUG "aha152x_proc_info: pos=%p\n", pos);
-
-	thislength = pos - (buffer + offset);
-	DPRINTK(debug_procinfo, KERN_DEBUG "aha152x_proc_info: length=%d thislength=%d\n", length, thislength);
-
-	if(thislength<0) {
-		DPRINTK(debug_procinfo, KERN_DEBUG "aha152x_proc_info: output too short\n");
-		*start = NULL;
-		return 0;
-	}
-
-	thislength = thislength<length ? thislength : length;
-
-	DPRINTK(debug_procinfo, KERN_DEBUG "aha152x_proc_info: return %d\n", thislength);
-
-	*start = buffer + offset;
-	return thislength < length ? thislength : length;
+	return 0;
 }
 
 static int aha152x_adjust_queue(struct scsi_device *device)
@@ -3470,7 +3432,8 @@ static struct scsi_host_template aha152x_driver_template = {
 	.module				= THIS_MODULE,
 	.name				= AHA152X_REVID,
 	.proc_name			= "aha152x",
-	.proc_info			= aha152x_proc_info,
+	.show_info			= aha152x_show_info,
+	.write_info			= aha152x_set_info,
 	.queuecommand			= aha152x_queue,
 	.eh_abort_handler		= aha152x_abort,
 	.eh_device_reset_handler	= aha152x_device_reset,
diff --git a/drivers/scsi/aha1740.c b/drivers/scsi/aha1740.c
index df775e6..5f31017 100644
--- a/drivers/scsi/aha1740.c
+++ b/drivers/scsi/aha1740.c
@@ -106,33 +106,14 @@ static inline dma_addr_t ecb_cpu_to_dma (struct Scsi_Host *host, void *cpu)
 	return hdata->ecb_dma_addr + offset;
 }
 
-static int aha1740_proc_info(struct Scsi_Host *shpnt, char *buffer,
-			     char **start, off_t offset,
-			     int length, int inout)
+static int aha1740_show_info(struct seq_file *m, struct Scsi_Host *shpnt)
 {
-	int len;
-	struct aha1740_hostdata *host;
-
-	if (inout)
-		return-ENOSYS;
-
-	host = HOSTDATA(shpnt);
-
-	len = sprintf(buffer, "aha174x at IO:%lx, IRQ %d, SLOT %d.\n"
+	struct aha1740_hostdata *host = HOSTDATA(shpnt);
+	seq_printf(m, "aha174x at IO:%lx, IRQ %d, SLOT %d.\n"
 		      "Extended translation %sabled.\n",
 		      shpnt->io_port, shpnt->irq, host->edev->slot,
 		      host->translation ? "en" : "dis");
-
-	if (offset > len) {
-		*start = buffer;
-		return 0;
-	}
-
-	*start = buffer + offset;
-	len -= offset;
-	if (len > length)
-		len = length;
-	return len;
+	return 0;
 }
 
 static int aha1740_makecode(unchar *sense, unchar *status)
@@ -556,7 +537,7 @@ static int aha1740_eh_abort_handler (Scsi_Cmnd *dummy)
 static struct scsi_host_template aha1740_template = {
 	.module           = THIS_MODULE,
 	.proc_name        = "aha1740",
-	.proc_info        = aha1740_proc_info,
+	.show_info        = aha1740_show_info,
 	.name             = "Adaptec 174x (EISA)",
 	.queuecommand     = aha1740_queuecommand,
 	.bios_param       = aha1740_biosparam,
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c
index 9328121..69d5c43 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.c
@@ -906,7 +906,8 @@ struct scsi_host_template aic79xx_driver_template = {
 	.module			= THIS_MODULE,
 	.name			= "aic79xx",
 	.proc_name		= "aic79xx",
-	.proc_info		= ahd_linux_proc_info,
+	.show_info		= ahd_linux_show_info,
+	.write_info	 	= ahd_proc_write_seeprom,
 	.info			= ahd_linux_info,
 	.queuecommand		= ahd_linux_queue,
 	.eh_abort_handler	= ahd_linux_abort,
@@ -1702,19 +1703,13 @@ ahd_send_async(struct ahd_softc *ahd, char channel,
 	switch (code) {
 	case AC_TRANSFER_NEG:
 	{
-		char	buf[80];
 		struct  scsi_target *starget;
-		struct	info_str info;
 		struct	ahd_initiator_tinfo *tinfo;
 		struct	ahd_tmode_tstate *tstate;
 		unsigned int target_ppr_options;
 
 		BUG_ON(target == CAM_TARGET_WILDCARD);
 
-		info.buffer = buf;
-		info.length = sizeof(buf);
-		info.offset = 0;
-		info.pos = 0;
 		tinfo = ahd_fetch_transinfo(ahd, channel, ahd->our_id,
 					    target, &tstate);
 
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.h b/drivers/scsi/aic7xxx/aic79xx_osm.h
index 28e4349..c58fa33 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.h
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.h
@@ -379,14 +379,6 @@ void ahd_insb(struct ahd_softc * ahd, long port,
 int		ahd_linux_register_host(struct ahd_softc *,
 					struct scsi_host_template *);
 
-/*************************** Pretty Printing **********************************/
-struct info_str {
-	char *buffer;
-	int length;
-	off_t offset;
-	int pos;
-};
-
 /******************************** Locking *************************************/
 static inline void
 ahd_lockinit(struct ahd_softc *ahd)
@@ -513,8 +505,8 @@ ahd_flush_device_writes(struct ahd_softc *ahd)
 }
 
 /**************************** Proc FS Support *********************************/
-int	ahd_linux_proc_info(struct Scsi_Host *, char *, char **,
-			    off_t, int, int);
+int	ahd_proc_write_seeprom(struct Scsi_Host *, char *, int);
+int	ahd_linux_show_info(struct seq_file *,struct Scsi_Host *);
 
 /*********************** Transaction Access Wrappers **************************/
 static inline void ahd_cmd_set_transaction_status(struct scsi_cmnd *, uint32_t);
diff --git a/drivers/scsi/aic7xxx/aic79xx_proc.c b/drivers/scsi/aic7xxx/aic79xx_proc.c
index 59c85d5..e9778b4 100644
--- a/drivers/scsi/aic7xxx/aic79xx_proc.c
+++ b/drivers/scsi/aic7xxx/aic79xx_proc.c
@@ -42,16 +42,12 @@
 #include "aic79xx_osm.h"
 #include "aic79xx_inline.h"
 
-static void	copy_mem_info(struct info_str *info, char *data, int len);
-static int	copy_info(struct info_str *info, char *fmt, ...);
 static void	ahd_dump_target_state(struct ahd_softc *ahd,
-				      struct info_str *info,
+				      struct seq_file *m,
 				      u_int our_id, char channel,
 				      u_int target_id);
-static void	ahd_dump_device_state(struct info_str *info,
+static void	ahd_dump_device_state(struct seq_file *m,
 				      struct scsi_device *sdev);
-static int	ahd_proc_write_seeprom(struct ahd_softc *ahd,
-				       char *buffer, int length);
 
 /*
  * Table of syncrates that don't follow the "divisible by 4"
@@ -93,58 +89,15 @@ ahd_calc_syncsrate(u_int period_factor)
 	return (10000000 / (period_factor * 4 * 10));
 }
 
-
-static void
-copy_mem_info(struct info_str *info, char *data, int len)
-{
-	if (info->pos + len > info->offset + info->length)
-		len = info->offset + info->length - info->pos;
-
-	if (info->pos + len < info->offset) {
-		info->pos += len;
-		return;
-	}
-
-	if (info->pos < info->offset) {
-		off_t partial;
-
-		partial = info->offset - info->pos;
-		data += partial;
-		info->pos += partial;
-		len  -= partial;
-	}
-
-	if (len > 0) {
-		memcpy(info->buffer, data, len);
-		info->pos += len;
-		info->buffer += len;
-	}
-}
-
-static int
-copy_info(struct info_str *info, char *fmt, ...)
-{
-	va_list args;
-	char buf[256];
-	int len;
-
-	va_start(args, fmt);
-	len = vsprintf(buf, fmt, args);
-	va_end(args);
-
-	copy_mem_info(info, buf, len);
-	return (len);
-}
-
 static void
-ahd_format_transinfo(struct info_str *info, struct ahd_transinfo *tinfo)
+ahd_format_transinfo(struct seq_file *m, struct ahd_transinfo *tinfo)
 {
 	u_int speed;
 	u_int freq;
 	u_int mb;
 
 	if (tinfo->period == AHD_PERIOD_UNKNOWN) {
-		copy_info(info, "Renegotiation Pending\n");
+		seq_printf(m, "Renegotiation Pending\n");
 		return;
 	}
         speed = 3300;
@@ -156,34 +109,34 @@ ahd_format_transinfo(struct info_str *info, struct ahd_transinfo *tinfo)
 	speed *= (0x01 << tinfo->width);
         mb = speed / 1000;
         if (mb > 0)
-		copy_info(info, "%d.%03dMB/s transfers", mb, speed % 1000);
+		seq_printf(m, "%d.%03dMB/s transfers", mb, speed % 1000);
         else
-		copy_info(info, "%dKB/s transfers", speed);
+		seq_printf(m, "%dKB/s transfers", speed);
 
 	if (freq != 0) {
 		int	printed_options;
 
 		printed_options = 0;
-		copy_info(info, " (%d.%03dMHz", freq / 1000, freq % 1000);
+		seq_printf(m, " (%d.%03dMHz", freq / 1000, freq % 1000);
 		if ((tinfo->ppr_options & MSG_EXT_PPR_RD_STRM) != 0) {
-			copy_info(info, " RDSTRM");
+			seq_printf(m, " RDSTRM");
 			printed_options++;
 		}
 		if ((tinfo->ppr_options & MSG_EXT_PPR_DT_REQ) != 0) {
-			copy_info(info, "%s", printed_options ? "|DT" : " DT");
+			seq_printf(m, "%s", printed_options ? "|DT" : " DT");
 			printed_options++;
 		}
 		if ((tinfo->ppr_options & MSG_EXT_PPR_IU_REQ) != 0) {
-			copy_info(info, "%s", printed_options ? "|IU" : " IU");
+			seq_printf(m, "%s", printed_options ? "|IU" : " IU");
 			printed_options++;
 		}
 		if ((tinfo->ppr_options & MSG_EXT_PPR_RTI) != 0) {
-			copy_info(info, "%s",
+			seq_printf(m, "%s",
 				  printed_options ? "|RTI" : " RTI");
 			printed_options++;
 		}
 		if ((tinfo->ppr_options & MSG_EXT_PPR_QAS_REQ) != 0) {
-			copy_info(info, "%s",
+			seq_printf(m, "%s",
 				  printed_options ? "|QAS" : " QAS");
 			printed_options++;
 		}
@@ -191,19 +144,19 @@ ahd_format_transinfo(struct info_str *info, struct ahd_transinfo *tinfo)
 
 	if (tinfo->width > 0) {
 		if (freq != 0) {
-			copy_info(info, ", ");
+			seq_printf(m, ", ");
 		} else {
-			copy_info(info, " (");
+			seq_printf(m, " (");
 		}
-		copy_info(info, "%dbit)", 8 * (0x01 << tinfo->width));
+		seq_printf(m, "%dbit)", 8 * (0x01 << tinfo->width));
 	} else if (freq != 0) {
-		copy_info(info, ")");
+		seq_printf(m, ")");
 	}
-	copy_info(info, "\n");
+	seq_printf(m, "\n");
 }
 
 static void
-ahd_dump_target_state(struct ahd_softc *ahd, struct info_str *info,
+ahd_dump_target_state(struct ahd_softc *ahd, struct seq_file *m,
 		      u_int our_id, char channel, u_int target_id)
 {
 	struct  scsi_target *starget;
@@ -213,17 +166,17 @@ ahd_dump_target_state(struct ahd_softc *ahd, struct info_str *info,
 
 	tinfo = ahd_fetch_transinfo(ahd, channel, our_id,
 				    target_id, &tstate);
-	copy_info(info, "Target %d Negotiation Settings\n", target_id);
-	copy_info(info, "\tUser: ");
-	ahd_format_transinfo(info, &tinfo->user);
+	seq_printf(m, "Target %d Negotiation Settings\n", target_id);
+	seq_printf(m, "\tUser: ");
+	ahd_format_transinfo(m, &tinfo->user);
 	starget = ahd->platform_data->starget[target_id];
 	if (starget == NULL)
 		return;
 
-	copy_info(info, "\tGoal: ");
-	ahd_format_transinfo(info, &tinfo->goal);
-	copy_info(info, "\tCurr: ");
-	ahd_format_transinfo(info, &tinfo->curr);
+	seq_printf(m, "\tGoal: ");
+	ahd_format_transinfo(m, &tinfo->goal);
+	seq_printf(m, "\tCurr: ");
+	ahd_format_transinfo(m, &tinfo->curr);
 
 	for (lun = 0; lun < AHD_NUM_LUNS; lun++) {
 		struct scsi_device *dev;
@@ -233,29 +186,30 @@ ahd_dump_target_state(struct ahd_softc *ahd, struct info_str *info,
 		if (dev == NULL)
 			continue;
 
-		ahd_dump_device_state(info, dev);
+		ahd_dump_device_state(m, dev);
 	}
 }
 
 static void
-ahd_dump_device_state(struct info_str *info, struct scsi_device *sdev)
+ahd_dump_device_state(struct seq_file *m, struct scsi_device *sdev)
 {
 	struct ahd_linux_device *dev = scsi_transport_device_data(sdev);
 
-	copy_info(info, "\tChannel %c Target %d Lun %d Settings\n",
+	seq_printf(m, "\tChannel %c Target %d Lun %d Settings\n",
 		  sdev->sdev_target->channel + 'A',
 		  sdev->sdev_target->id, sdev->lun);
 
-	copy_info(info, "\t\tCommands Queued %ld\n", dev->commands_issued);
-	copy_info(info, "\t\tCommands Active %d\n", dev->active);
-	copy_info(info, "\t\tCommand Openings %d\n", dev->openings);
-	copy_info(info, "\t\tMax Tagged Openings %d\n", dev->maxtags);
-	copy_info(info, "\t\tDevice Queue Frozen Count %d\n", dev->qfrozen);
+	seq_printf(m, "\t\tCommands Queued %ld\n", dev->commands_issued);
+	seq_printf(m, "\t\tCommands Active %d\n", dev->active);
+	seq_printf(m, "\t\tCommand Openings %d\n", dev->openings);
+	seq_printf(m, "\t\tMax Tagged Openings %d\n", dev->maxtags);
+	seq_printf(m, "\t\tDevice Queue Frozen Count %d\n", dev->qfrozen);
 }
 
-static int
-ahd_proc_write_seeprom(struct ahd_softc *ahd, char *buffer, int length)
+int
+ahd_proc_write_seeprom(struct Scsi_Host *shost, char *buffer, int length)
 {
+	struct	ahd_softc *ahd = *(struct ahd_softc **)shost->hostdata;
 	ahd_mode_state saved_modes;
 	int have_seeprom;
 	u_long s;
@@ -319,64 +273,45 @@ done:
  * Return information to handle /proc support for the driver.
  */
 int
-ahd_linux_proc_info(struct Scsi_Host *shost, char *buffer, char **start,
-		    off_t offset, int length, int inout)
+ahd_linux_show_info(struct seq_file *m, struct Scsi_Host *shost)
 {
 	struct	ahd_softc *ahd = *(struct ahd_softc **)shost->hostdata;
-	struct	info_str info;
 	char	ahd_info[256];
 	u_int	max_targ;
 	u_int	i;
-	int	retval;
 
-	 /* Has data been written to the file? */ 
-	if (inout == TRUE) {
-		retval = ahd_proc_write_seeprom(ahd, buffer, length);
-		goto done;
-	}
-
-	if (start)
-		*start = buffer;
-
-	info.buffer	= buffer;
-	info.length	= length;
-	info.offset	= offset;
-	info.pos	= 0;
-
-	copy_info(&info, "Adaptec AIC79xx driver version: %s\n",
+	seq_printf(m, "Adaptec AIC79xx driver version: %s\n",
 		  AIC79XX_DRIVER_VERSION);
-	copy_info(&info, "%s\n", ahd->description);
+	seq_printf(m, "%s\n", ahd->description);
 	ahd_controller_info(ahd, ahd_info);
-	copy_info(&info, "%s\n", ahd_info);
-	copy_info(&info, "Allocated SCBs: %d, SG List Length: %d\n\n",
+	seq_printf(m, "%s\n", ahd_info);
+	seq_printf(m, "Allocated SCBs: %d, SG List Length: %d\n\n",
 		  ahd->scb_data.numscbs, AHD_NSEG);
 
 	max_targ = 16;
 
 	if (ahd->seep_config == NULL)
-		copy_info(&info, "No Serial EEPROM\n");
+		seq_printf(m, "No Serial EEPROM\n");
 	else {
-		copy_info(&info, "Serial EEPROM:\n");
+		seq_printf(m, "Serial EEPROM:\n");
 		for (i = 0; i < sizeof(*ahd->seep_config)/2; i++) {
 			if (((i % 8) == 0) && (i != 0)) {
-				copy_info(&info, "\n");
+				seq_printf(m, "\n");
 			}
-			copy_info(&info, "0x%.4x ",
+			seq_printf(m, "0x%.4x ",
 				  ((uint16_t*)ahd->seep_config)[i]);
 		}
-		copy_info(&info, "\n");
+		seq_printf(m, "\n");
 	}
-	copy_info(&info, "\n");
+	seq_printf(m, "\n");
 
 	if ((ahd->features & AHD_WIDE) == 0)
 		max_targ = 8;
 
 	for (i = 0; i < max_targ; i++) {
 
-		ahd_dump_target_state(ahd, &info, ahd->our_id, 'A',
+		ahd_dump_target_state(ahd, m, ahd->our_id, 'A',
 				      /*target_id*/i);
 	}
-	retval = info.pos > info.offset ? info.pos - info.offset : 0;
-done:
-	return (retval);
+	return 0;
 }
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c
index 5a477cd..c0c6258 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c
@@ -803,7 +803,8 @@ struct scsi_host_template aic7xxx_driver_template = {
 	.module			= THIS_MODULE,
 	.name			= "aic7xxx",
 	.proc_name		= "aic7xxx",
-	.proc_info		= ahc_linux_proc_info,
+	.show_info		= ahc_linux_show_info,
+	.write_info		= ahc_proc_write_seeprom,
 	.info			= ahc_linux_info,
 	.queuecommand		= ahc_linux_queue,
 	.eh_abort_handler	= ahc_linux_abort,
@@ -1631,10 +1632,8 @@ ahc_send_async(struct ahc_softc *ahc, char channel,
 	switch (code) {
 	case AC_TRANSFER_NEG:
 	{
-		char	buf[80];
 		struct	scsi_target *starget;
 		struct	ahc_linux_target *targ;
-		struct	info_str info;
 		struct	ahc_initiator_tinfo *tinfo;
 		struct	ahc_tmode_tstate *tstate;
 		int	target_offset;
@@ -1642,10 +1641,6 @@ ahc_send_async(struct ahc_softc *ahc, char channel,
 
 		BUG_ON(target == CAM_TARGET_WILDCARD);
 
-		info.buffer = buf;
-		info.length = sizeof(buf);
-		info.offset = 0;
-		info.pos = 0;
 		tinfo = ahc_fetch_transinfo(ahc, channel,
 						channel == 'A' ? ahc->our_id
 							       : ahc->our_id_b,
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h
index bca0fb83..bc4cca9 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.h
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h
@@ -383,14 +383,6 @@ void ahc_insb(struct ahc_softc * ahc, long port,
 int		ahc_linux_register_host(struct ahc_softc *,
 					struct scsi_host_template *);
 
-/*************************** Pretty Printing **********************************/
-struct info_str {
-	char *buffer;
-	int length;
-	off_t offset;
-	int pos;
-};
-
 /******************************** Locking *************************************/
 /* Lock protecting internal data structures */
 
@@ -523,8 +515,8 @@ ahc_flush_device_writes(struct ahc_softc *ahc)
 }
 
 /**************************** Proc FS Support *********************************/
-int	ahc_linux_proc_info(struct Scsi_Host *, char *, char **,
-			    off_t, int, int);
+int	ahc_proc_write_seeprom(struct Scsi_Host *, char *, int);
+int	ahc_linux_show_info(struct seq_file *, struct Scsi_Host *);
 
 /*************************** Domain Validation ********************************/
 /*********************** Transaction Access Wrappers *************************/
diff --git a/drivers/scsi/aic7xxx/aic7xxx_proc.c b/drivers/scsi/aic7xxx/aic7xxx_proc.c
index f2525f8..383a3d1 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_proc.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_proc.c
@@ -43,16 +43,12 @@
 #include "aic7xxx_inline.h"
 #include "aic7xxx_93cx6.h"
 
-static void	copy_mem_info(struct info_str *info, char *data, int len);
-static int	copy_info(struct info_str *info, char *fmt, ...);
 static void	ahc_dump_target_state(struct ahc_softc *ahc,
-				      struct info_str *info,
+				      struct seq_file *m,
 				      u_int our_id, char channel,
 				      u_int target_id, u_int target_offset);
-static void	ahc_dump_device_state(struct info_str *info,
+static void	ahc_dump_device_state(struct seq_file *m,
 				      struct scsi_device *dev);
-static int	ahc_proc_write_seeprom(struct ahc_softc *ahc,
-				       char *buffer, int length);
 
 /*
  * Table of syncrates that don't follow the "divisible by 4"
@@ -94,51 +90,8 @@ ahc_calc_syncsrate(u_int period_factor)
 	return (10000000 / (period_factor * 4 * 10));
 }
 
-
-static void
-copy_mem_info(struct info_str *info, char *data, int len)
-{
-	if (info->pos + len > info->offset + info->length)
-		len = info->offset + info->length - info->pos;
-
-	if (info->pos + len < info->offset) {
-		info->pos += len;
-		return;
-	}
-
-	if (info->pos < info->offset) {
-		off_t partial;
-
-		partial = info->offset - info->pos;
-		data += partial;
-		info->pos += partial;
-		len  -= partial;
-	}
-
-	if (len > 0) {
-		memcpy(info->buffer, data, len);
-		info->pos += len;
-		info->buffer += len;
-	}
-}
-
-static int
-copy_info(struct info_str *info, char *fmt, ...)
-{
-	va_list args;
-	char buf[256];
-	int len;
-
-	va_start(args, fmt);
-	len = vsprintf(buf, fmt, args);
-	va_end(args);
-
-	copy_mem_info(info, buf, len);
-	return (len);
-}
-
 static void
-ahc_format_transinfo(struct info_str *info, struct ahc_transinfo *tinfo)
+ahc_format_transinfo(struct seq_file *m, struct ahc_transinfo *tinfo)
 {
 	u_int speed;
 	u_int freq;
@@ -153,12 +106,12 @@ ahc_format_transinfo(struct info_str *info, struct ahc_transinfo *tinfo)
 	speed *= (0x01 << tinfo->width);
         mb = speed / 1000;
         if (mb > 0)
-		copy_info(info, "%d.%03dMB/s transfers", mb, speed % 1000);
+		seq_printf(m, "%d.%03dMB/s transfers", mb, speed % 1000);
         else
-		copy_info(info, "%dKB/s transfers", speed);
+		seq_printf(m, "%dKB/s transfers", speed);
 
 	if (freq != 0) {
-		copy_info(info, " (%d.%03dMHz%s, offset %d",
+		seq_printf(m, " (%d.%03dMHz%s, offset %d",
 			 freq / 1000, freq % 1000,
 			 (tinfo->ppr_options & MSG_EXT_PPR_DT_REQ) != 0
 			 ? " DT" : "", tinfo->offset);
@@ -166,19 +119,19 @@ ahc_format_transinfo(struct info_str *info, struct ahc_transinfo *tinfo)
 
 	if (tinfo->width > 0) {
 		if (freq != 0) {
-			copy_info(info, ", ");
+			seq_printf(m, ", ");
 		} else {
-			copy_info(info, " (");
+			seq_printf(m, " (");
 		}
-		copy_info(info, "%dbit)", 8 * (0x01 << tinfo->width));
+		seq_printf(m, "%dbit)", 8 * (0x01 << tinfo->width));
 	} else if (freq != 0) {
-		copy_info(info, ")");
+		seq_printf(m, ")");
 	}
-	copy_info(info, "\n");
+	seq_printf(m, "\n");
 }
 
 static void
-ahc_dump_target_state(struct ahc_softc *ahc, struct info_str *info,
+ahc_dump_target_state(struct ahc_softc *ahc, struct seq_file *m,
 		      u_int our_id, char channel, u_int target_id,
 		      u_int target_offset)
 {
@@ -190,18 +143,18 @@ ahc_dump_target_state(struct ahc_softc *ahc, struct info_str *info,
 	tinfo = ahc_fetch_transinfo(ahc, channel, our_id,
 				    target_id, &tstate);
 	if ((ahc->features & AHC_TWIN) != 0)
-		copy_info(info, "Channel %c ", channel);
-	copy_info(info, "Target %d Negotiation Settings\n", target_id);
-	copy_info(info, "\tUser: ");
-	ahc_format_transinfo(info, &tinfo->user);
+		seq_printf(m, "Channel %c ", channel);
+	seq_printf(m, "Target %d Negotiation Settings\n", target_id);
+	seq_printf(m, "\tUser: ");
+	ahc_format_transinfo(m, &tinfo->user);
 	starget = ahc->platform_data->starget[target_offset];
 	if (!starget)
 		return;
 
-	copy_info(info, "\tGoal: ");
-	ahc_format_transinfo(info, &tinfo->goal);
-	copy_info(info, "\tCurr: ");
-	ahc_format_transinfo(info, &tinfo->curr);
+	seq_printf(m, "\tGoal: ");
+	ahc_format_transinfo(m, &tinfo->goal);
+	seq_printf(m, "\tCurr: ");
+	ahc_format_transinfo(m, &tinfo->curr);
 
 	for (lun = 0; lun < AHC_NUM_LUNS; lun++) {
 		struct scsi_device *sdev;
@@ -211,29 +164,30 @@ ahc_dump_target_state(struct ahc_softc *ahc, struct info_str *info,
 		if (sdev == NULL)
 			continue;
 
-		ahc_dump_device_state(info, sdev);
+		ahc_dump_device_state(m, sdev);
 	}
 }
 
 static void
-ahc_dump_device_state(struct info_str *info, struct scsi_device *sdev)
+ahc_dump_device_state(struct seq_file *m, struct scsi_device *sdev)
 {
 	struct ahc_linux_device *dev = scsi_transport_device_data(sdev);
 
-	copy_info(info, "\tChannel %c Target %d Lun %d Settings\n",
+	seq_printf(m, "\tChannel %c Target %d Lun %d Settings\n",
 		  sdev->sdev_target->channel + 'A',
 		  sdev->sdev_target->id, sdev->lun);
 
-	copy_info(info, "\t\tCommands Queued %ld\n", dev->commands_issued);
-	copy_info(info, "\t\tCommands Active %d\n", dev->active);
-	copy_info(info, "\t\tCommand Openings %d\n", dev->openings);
-	copy_info(info, "\t\tMax Tagged Openings %d\n", dev->maxtags);
-	copy_info(info, "\t\tDevice Queue Frozen Count %d\n", dev->qfrozen);
+	seq_printf(m, "\t\tCommands Queued %ld\n", dev->commands_issued);
+	seq_printf(m, "\t\tCommands Active %d\n", dev->active);
+	seq_printf(m, "\t\tCommand Openings %d\n", dev->openings);
+	seq_printf(m, "\t\tMax Tagged Openings %d\n", dev->maxtags);
+	seq_printf(m, "\t\tDevice Queue Frozen Count %d\n", dev->qfrozen);
 }
 
-static int
-ahc_proc_write_seeprom(struct ahc_softc *ahc, char *buffer, int length)
+int
+ahc_proc_write_seeprom(struct Scsi_Host *shost, char *buffer, int length)
 {
+	struct	ahc_softc *ahc = *(struct ahc_softc **)shost->hostdata;
 	struct seeprom_descriptor sd;
 	int have_seeprom;
 	u_long s;
@@ -332,53 +286,36 @@ done:
  * Return information to handle /proc support for the driver.
  */
 int
-ahc_linux_proc_info(struct Scsi_Host *shost, char *buffer, char **start,
-		    off_t offset, int length, int inout)
+ahc_linux_show_info(struct seq_file *m, struct Scsi_Host *shost)
 {
 	struct	ahc_softc *ahc = *(struct ahc_softc **)shost->hostdata;
-	struct	info_str info;
 	char	ahc_info[256];
 	u_int	max_targ;
 	u_int	i;
-	int	retval;
 
-	 /* Has data been written to the file? */ 
-	if (inout == TRUE) {
-		retval = ahc_proc_write_seeprom(ahc, buffer, length);
-		goto done;
-	}
-
-	if (start)
-		*start = buffer;
-
-	info.buffer	= buffer;
-	info.length	= length;
-	info.offset	= offset;
-	info.pos	= 0;
-
-	copy_info(&info, "Adaptec AIC7xxx driver version: %s\n",
+	seq_printf(m, "Adaptec AIC7xxx driver version: %s\n",
 		  AIC7XXX_DRIVER_VERSION);
-	copy_info(&info, "%s\n", ahc->description);
+	seq_printf(m, "%s\n", ahc->description);
 	ahc_controller_info(ahc, ahc_info);
-	copy_info(&info, "%s\n", ahc_info);
-	copy_info(&info, "Allocated SCBs: %d, SG List Length: %d\n\n",
+	seq_printf(m, "%s\n", ahc_info);
+	seq_printf(m, "Allocated SCBs: %d, SG List Length: %d\n\n",
 		  ahc->scb_data->numscbs, AHC_NSEG);
 
 
 	if (ahc->seep_config == NULL)
-		copy_info(&info, "No Serial EEPROM\n");
+		seq_printf(m, "No Serial EEPROM\n");
 	else {
-		copy_info(&info, "Serial EEPROM:\n");
+		seq_printf(m, "Serial EEPROM:\n");
 		for (i = 0; i < sizeof(*ahc->seep_config)/2; i++) {
 			if (((i % 8) == 0) && (i != 0)) {
-				copy_info(&info, "\n");
+				seq_printf(m, "\n");
 			}
-			copy_info(&info, "0x%.4x ",
+			seq_printf(m, "0x%.4x ",
 				  ((uint16_t*)ahc->seep_config)[i]);
 		}
-		copy_info(&info, "\n");
+		seq_printf(m, "\n");
 	}
-	copy_info(&info, "\n");
+	seq_printf(m, "\n");
 
 	max_targ = 16;
 	if ((ahc->features & (AHC_WIDE|AHC_TWIN)) == 0)
@@ -398,10 +335,8 @@ ahc_linux_proc_info(struct Scsi_Host *shost, char *buffer, char **start,
 			target_id = i % 8;
 		}
 
-		ahc_dump_target_state(ahc, &info, our_id,
+		ahc_dump_target_state(ahc, m, our_id,
 				      channel, target_id, i);
 	}
-	retval = info.pos > info.offset ? info.pos - info.offset : 0;
-done:
-	return (retval);
+	return 0;
 }
diff --git a/drivers/scsi/aic7xxx_old.c b/drivers/scsi/aic7xxx_old.c
index 5b212f0..33ec9c6 100644
--- a/drivers/scsi/aic7xxx_old.c
+++ b/drivers/scsi/aic7xxx_old.c
@@ -11108,7 +11108,7 @@ MODULE_VERSION(AIC7XXX_H_VERSION);
 
 
 static struct scsi_host_template driver_template = {
-	.proc_info		= aic7xxx_proc_info,
+	.show_info		= aic7xxx_show_info,
 	.detect			= aic7xxx_detect,
 	.release		= aic7xxx_release,
 	.info			= aic7xxx_info,	
diff --git a/drivers/scsi/aic7xxx_old/aic7xxx_proc.c b/drivers/scsi/aic7xxx_old/aic7xxx_proc.c
index b07e4f0..976f45c 100644
--- a/drivers/scsi/aic7xxx_old/aic7xxx_proc.c
+++ b/drivers/scsi/aic7xxx_old/aic7xxx_proc.c
@@ -30,62 +30,23 @@
  *-M*************************************************************************/
 
 
-#define	BLS	(&aic7xxx_buffer[size])
 #define HDRB \
 "               0 - 4K   4 - 16K   16 - 64K  64 - 256K  256K - 1M        1M+"
 
-#ifdef PROC_DEBUG
-extern int vsprintf(char *, const char *, va_list);
-
-static void
-proc_debug(const char *fmt, ...)
-{
-  va_list ap;
-  char buf[256];
-
-  va_start(ap, fmt);
-  vsprintf(buf, fmt, ap);
-  printk(buf);
-  va_end(ap);
-}
-#else /* PROC_DEBUG */
-#  define proc_debug(fmt, args...)
-#endif /* PROC_DEBUG */
-
-static int aic7xxx_buffer_size = 0;
-static char *aic7xxx_buffer = NULL;
-
 
 /*+F*************************************************************************
  * Function:
- *   aic7xxx_set_info
- *
- * Description:
- *   Set parameters for the driver from the /proc filesystem.
- *-F*************************************************************************/
-static int
-aic7xxx_set_info(char *buffer, int length, struct Scsi_Host *HBAptr)
-{
-  proc_debug("aic7xxx_set_info(): %s\n", buffer);
-  return (-ENOSYS);  /* Currently this is a no-op */
-}
-
-
-/*+F*************************************************************************
- * Function:
- *   aic7xxx_proc_info
+ *   aic7xxx_show_info
  *
  * Description:
  *   Return information to handle /proc support for the driver.
  *-F*************************************************************************/
 int
-aic7xxx_proc_info ( struct Scsi_Host *HBAptr, char *buffer, char **start, off_t offset, int length, 
-                    int inout)
+aic7xxx_show_info(struct seq_file *m, struct Scsi_Host *HBAptr)
 {
   struct aic7xxx_host *p;
   struct aic_dev_data *aic_dev;
   struct scsi_device *sdptr;
-  int    size = 0;
   unsigned char i;
   unsigned char tindex;
 
@@ -94,66 +55,21 @@ aic7xxx_proc_info ( struct Scsi_Host *HBAptr, char *buffer, char **start, off_t
 
   if (!p)
   {
-    size += sprintf(buffer, "Can't find adapter for host number %d\n", HBAptr->host_no);
-    if (size > length)
-    {
-      return (size);
-    }
-    else
-    {
-      return (length);
-    }
-  }
-
-  if (inout == TRUE) /* Has data been written to the file? */ 
-  {
-    return (aic7xxx_set_info(buffer, length, HBAptr));
+    seq_printf(m, "Can't find adapter for host number %d\n", HBAptr->host_no);
+    return 0;
   }
 
   p = (struct aic7xxx_host *) HBAptr->hostdata;
 
-  /*
-   * It takes roughly 1K of space to hold all relevant card info, not
-   * counting any proc stats, so we start out with a 1.5k buffer size and
-   * if proc_stats is defined, then we sweep the stats structure to see
-   * how many drives we will be printing out for and add 384 bytes per
-   * device with active stats.
-   *
-   * Hmmmm...that 1.5k seems to keep growing as items get added so they
-   * can be easily viewed for debugging purposes.  So, we bumped that
-   * 1.5k to 4k so we can quit having to bump it all the time.
-   */
-
-  size = 4096;
-  list_for_each_entry(aic_dev, &p->aic_devs, list)
-    size += 512;
-  if (aic7xxx_buffer_size != size)
-  {
-    if (aic7xxx_buffer != NULL) 
-    {
-      kfree(aic7xxx_buffer);
-      aic7xxx_buffer_size = 0;
-    }
-    aic7xxx_buffer = kmalloc(size, GFP_KERNEL);
-  }
-  if (aic7xxx_buffer == NULL)
-  {
-    size = sprintf(buffer, "AIC7xxx - kmalloc error at line %d\n",
-        __LINE__);
-    return size;
-  }
-  aic7xxx_buffer_size = size;
-
-  size = 0;
-  size += sprintf(BLS, "Adaptec AIC7xxx driver version: ");
-  size += sprintf(BLS, "%s/", AIC7XXX_C_VERSION);
-  size += sprintf(BLS, "%s", AIC7XXX_H_VERSION);
-  size += sprintf(BLS, "\n");
-  size += sprintf(BLS, "Adapter Configuration:\n");
-  size += sprintf(BLS, "           SCSI Adapter: %s\n",
+  seq_printf(m, "Adaptec AIC7xxx driver version: ");
+  seq_printf(m, "%s/", AIC7XXX_C_VERSION);
+  seq_printf(m, "%s", AIC7XXX_H_VERSION);
+  seq_printf(m, "\n");
+  seq_printf(m, "Adapter Configuration:\n");
+  seq_printf(m, "           SCSI Adapter: %s\n",
       board_names[p->board_name_index]);
   if (p->flags & AHC_TWIN)
-    size += sprintf(BLS, "                         Twin Channel Controller ");
+    seq_printf(m, "                         Twin Channel Controller ");
   else
   {
     char *channel = "";
@@ -184,86 +100,86 @@ aic7xxx_proc_info ( struct Scsi_Host *HBAptr, char *buffer, char **start, off_t
       ultra = "Ultra-2 LVD/SE ";
     else if (p->features & AHC_ULTRA)
       ultra = "Ultra ";
-    size += sprintf(BLS, "                           %s%sController%s ",
+    seq_printf(m, "                           %s%sController%s ",
       ultra, wide, channel);
   }
   switch(p->chip & ~AHC_CHIPID_MASK)
   {
     case AHC_VL:
-      size += sprintf(BLS, "at VLB slot %d\n", p->pci_device_fn);
+      seq_printf(m, "at VLB slot %d\n", p->pci_device_fn);
       break;
     case AHC_EISA:
-      size += sprintf(BLS, "at EISA slot %d\n", p->pci_device_fn);
+      seq_printf(m, "at EISA slot %d\n", p->pci_device_fn);
       break;
     default:
-      size += sprintf(BLS, "at PCI %d/%d/%d\n", p->pci_bus,
+      seq_printf(m, "at PCI %d/%d/%d\n", p->pci_bus,
         PCI_SLOT(p->pci_device_fn), PCI_FUNC(p->pci_device_fn));
       break;
   }
   if( !(p->maddr) )
   {
-    size += sprintf(BLS, "    Programmed I/O Base: %lx\n", p->base);
+    seq_printf(m, "    Programmed I/O Base: %lx\n", p->base);
   }
   else
   {
-    size += sprintf(BLS, "    PCI MMAPed I/O Base: 0x%lx\n", p->mbase);
+    seq_printf(m, "    PCI MMAPed I/O Base: 0x%lx\n", p->mbase);
   }
   if( (p->chip & (AHC_VL | AHC_EISA)) )
   {
-    size += sprintf(BLS, "    BIOS Memory Address: 0x%08x\n", p->bios_address);
+    seq_printf(m, "    BIOS Memory Address: 0x%08x\n", p->bios_address);
   }
-  size += sprintf(BLS, " Adapter SEEPROM Config: %s\n",
+  seq_printf(m, " Adapter SEEPROM Config: %s\n",
           (p->flags & AHC_SEEPROM_FOUND) ? "SEEPROM found and used." :
          ((p->flags & AHC_USEDEFAULTS) ? "SEEPROM not found, using defaults." :
            "SEEPROM not found, using leftover BIOS values.") );
-  size += sprintf(BLS, "      Adaptec SCSI BIOS: %s\n",
+  seq_printf(m, "      Adaptec SCSI BIOS: %s\n",
           (p->flags & AHC_BIOS_ENABLED) ? "Enabled" : "Disabled");
-  size += sprintf(BLS, "                    IRQ: %d\n", HBAptr->irq);
-  size += sprintf(BLS, "                   SCBs: Active %d, Max Active %d,\n",
+  seq_printf(m, "                    IRQ: %d\n", HBAptr->irq);
+  seq_printf(m, "                   SCBs: Active %d, Max Active %d,\n",
             p->activescbs, p->max_activescbs);
-  size += sprintf(BLS, "                         Allocated %d, HW %d, "
+  seq_printf(m, "                         Allocated %d, HW %d, "
             "Page %d\n", p->scb_data->numscbs, p->scb_data->maxhscbs,
             p->scb_data->maxscbs);
   if (p->flags & AHC_EXTERNAL_SRAM)
-    size += sprintf(BLS, "                         Using External SCB SRAM\n");
-  size += sprintf(BLS, "             Interrupts: %ld", p->isr_count);
+    seq_printf(m, "                         Using External SCB SRAM\n");
+  seq_printf(m, "             Interrupts: %ld", p->isr_count);
   if (p->chip & AHC_EISA)
   {
-    size += sprintf(BLS, " %s\n",
+    seq_printf(m, " %s\n",
         (p->pause & IRQMS) ? "(Level Sensitive)" : "(Edge Triggered)");
   }
   else
   {
-    size += sprintf(BLS, "\n");
+    seq_printf(m, "\n");
   }
-  size += sprintf(BLS, "      BIOS Control Word: 0x%04x\n",
+  seq_printf(m, "      BIOS Control Word: 0x%04x\n",
             p->bios_control);
-  size += sprintf(BLS, "   Adapter Control Word: 0x%04x\n",
+  seq_printf(m, "   Adapter Control Word: 0x%04x\n",
             p->adapter_control);
-  size += sprintf(BLS, "   Extended Translation: %sabled\n",
+  seq_printf(m, "   Extended Translation: %sabled\n",
       (p->flags & AHC_EXTEND_TRANS_A) ? "En" : "Dis");
-  size += sprintf(BLS, "Disconnect Enable Flags: 0x%04x\n", p->discenable);
+  seq_printf(m, "Disconnect Enable Flags: 0x%04x\n", p->discenable);
   if (p->features & (AHC_ULTRA | AHC_ULTRA2))
   {
-    size += sprintf(BLS, "     Ultra Enable Flags: 0x%04x\n", p->ultraenb);
+    seq_printf(m, "     Ultra Enable Flags: 0x%04x\n", p->ultraenb);
   }
-  size += sprintf(BLS, "Default Tag Queue Depth: %d\n", aic7xxx_default_queue_depth);
-  size += sprintf(BLS, "    Tagged Queue By Device array for aic7xxx host "
+  seq_printf(m, "Default Tag Queue Depth: %d\n", aic7xxx_default_queue_depth);
+  seq_printf(m, "    Tagged Queue By Device array for aic7xxx host "
                        "instance %d:\n", p->instance);
-  size += sprintf(BLS, "      {");
+  seq_printf(m, "      {");
   for(i=0; i < (MAX_TARGETS - 1); i++)
-    size += sprintf(BLS, "%d,",aic7xxx_tag_info[p->instance].tag_commands[i]);
-  size += sprintf(BLS, "%d}\n",aic7xxx_tag_info[p->instance].tag_commands[i]);
+    seq_printf(m, "%d,",aic7xxx_tag_info[p->instance].tag_commands[i]);
+  seq_printf(m, "%d}\n",aic7xxx_tag_info[p->instance].tag_commands[i]);
 
-  size += sprintf(BLS, "\n");
-  size += sprintf(BLS, "Statistics:\n\n");
+  seq_printf(m, "\n");
+  seq_printf(m, "Statistics:\n\n");
   list_for_each_entry(aic_dev, &p->aic_devs, list)
   {
     sdptr = aic_dev->SDptr;
     tindex = sdptr->channel << 3 | sdptr->id;
-    size += sprintf(BLS, "(scsi%d:%d:%d:%d)\n",
+    seq_printf(m, "(scsi%d:%d:%d:%d)\n",
         p->host_no, sdptr->channel, sdptr->id, sdptr->lun);
-    size += sprintf(BLS, "  Device using %s/%s",
+    seq_printf(m, "  Device using %s/%s",
           (aic_dev->cur.width == MSG_EXT_WDTR_BUS_16_BIT) ?
           "Wide" : "Narrow",
           (aic_dev->cur.offset != 0) ?
@@ -279,78 +195,59 @@ aic7xxx_proc_info ( struct Scsi_Host *HBAptr, char *buffer, char **start, off_t
       sync_rate = aic7xxx_find_syncrate(p, &period, 0, &options);
       if (sync_rate != NULL)
       {
-        size += sprintf(BLS, "%s MByte/sec, offset %d\n",
+        seq_printf(m, "%s MByte/sec, offset %d\n",
                         sync_rate->rate[rate],
                         aic_dev->cur.offset );
       }
       else
       {
-        size += sprintf(BLS, "3.3 MByte/sec, offset %d\n",
+        seq_printf(m, "3.3 MByte/sec, offset %d\n",
                         aic_dev->cur.offset );
       }
     }
-    size += sprintf(BLS, "  Transinfo settings: ");
-    size += sprintf(BLS, "current(%d/%d/%d/%d), ",
+    seq_printf(m, "  Transinfo settings: ");
+    seq_printf(m, "current(%d/%d/%d/%d), ",
                     aic_dev->cur.period,
                     aic_dev->cur.offset,
                     aic_dev->cur.width,
                     aic_dev->cur.options);
-    size += sprintf(BLS, "goal(%d/%d/%d/%d), ",
+    seq_printf(m, "goal(%d/%d/%d/%d), ",
                     aic_dev->goal.period,
                     aic_dev->goal.offset,
                     aic_dev->goal.width,
                     aic_dev->goal.options);
-    size += sprintf(BLS, "user(%d/%d/%d/%d)\n",
+    seq_printf(m, "user(%d/%d/%d/%d)\n",
                     p->user[tindex].period,
                     p->user[tindex].offset,
                     p->user[tindex].width,
                     p->user[tindex].options);
     if(sdptr->simple_tags)
     {
-      size += sprintf(BLS, "  Tagged Command Queueing Enabled, Ordered Tags %s, Depth %d/%d\n", sdptr->ordered_tags ? "Enabled" : "Disabled", sdptr->queue_depth, aic_dev->max_q_depth);
+      seq_printf(m, "  Tagged Command Queueing Enabled, Ordered Tags %s, Depth %d/%d\n", sdptr->ordered_tags ? "Enabled" : "Disabled", sdptr->queue_depth, aic_dev->max_q_depth);
     }
     if(aic_dev->barrier_total)
-      size += sprintf(BLS, "  Total transfers %ld:\n    (%ld/%ld/%ld/%ld reads/writes/REQ_BARRIER/Ordered Tags)\n",
+      seq_printf(m, "  Total transfers %ld:\n    (%ld/%ld/%ld/%ld reads/writes/REQ_BARRIER/Ordered Tags)\n",
         aic_dev->r_total+aic_dev->w_total, aic_dev->r_total, aic_dev->w_total,
         aic_dev->barrier_total, aic_dev->ordered_total);
     else
-      size += sprintf(BLS, "  Total transfers %ld:\n    (%ld/%ld reads/writes)\n",
+      seq_printf(m, "  Total transfers %ld:\n    (%ld/%ld reads/writes)\n",
         aic_dev->r_total+aic_dev->w_total, aic_dev->r_total, aic_dev->w_total);
-    size += sprintf(BLS, "%s\n", HDRB);
-    size += sprintf(BLS, "   Reads:");
+    seq_printf(m, "%s\n", HDRB);
+    seq_printf(m, "   Reads:");
     for (i = 0; i < ARRAY_SIZE(aic_dev->r_bins); i++)
     {
-      size += sprintf(BLS, " %10ld", aic_dev->r_bins[i]);
+      seq_printf(m, " %10ld", aic_dev->r_bins[i]);
     }
-    size += sprintf(BLS, "\n");
-    size += sprintf(BLS, "  Writes:");
+    seq_printf(m, "\n");
+    seq_printf(m, "  Writes:");
     for (i = 0; i < ARRAY_SIZE(aic_dev->w_bins); i++)
     {
-      size += sprintf(BLS, " %10ld", aic_dev->w_bins[i]);
+      seq_printf(m, " %10ld", aic_dev->w_bins[i]);
     }
-    size += sprintf(BLS, "\n");
-    size += sprintf(BLS, "\n\n");
-  }
-  if (size >= aic7xxx_buffer_size)
-  {
-    printk(KERN_WARNING "aic7xxx: Overflow in aic7xxx_proc.c\n");
-  }
-
-  if (offset > size - 1)
-  {
-    kfree(aic7xxx_buffer);
-    aic7xxx_buffer = NULL;
-    aic7xxx_buffer_size = length = 0;
-    *start = NULL;
+    seq_printf(m, "\n");
+    seq_printf(m, "\n\n");
   }
-  else
-  {
-    *start = buffer;
-    length = min_t(int, length, size - offset);
-    memcpy(buffer, &aic7xxx_buffer[offset], length);
-  }
-
-  return (length);
+  return 0;
 }
 
 /*
diff --git a/drivers/scsi/arm/acornscsi.c b/drivers/scsi/arm/acornscsi.c
index 3e1172a..09ba186 100644
--- a/drivers/scsi/arm/acornscsi.c
+++ b/drivers/scsi/arm/acornscsi.c
@@ -2836,20 +2836,15 @@ char *acornscsi_info(struct Scsi_Host *host)
     return string;
 }
 
-int acornscsi_proc_info(struct Scsi_Host *instance, char *buffer, char **start, off_t offset,
-			int length, int inout)
+static int acornscsi_show_info(struct seq_file *m, struct Scsi_Host *instance)
 {
-    int pos, begin = 0, devidx;
+    int devidx;
     struct scsi_device *scd;
     AS_Host *host;
-    char *p = buffer;
-
-    if (inout == 1)
-	return -EINVAL;
 
     host  = (AS_Host *)instance->hostdata;
     
-    p += sprintf(p, "AcornSCSI driver v%d.%d.%d"
+    seq_printf(m, "AcornSCSI driver v%d.%d.%d"
 #ifdef CONFIG_SCSI_ACORNSCSI_SYNC
     " SYNC"
 #endif
@@ -2864,14 +2859,14 @@ int acornscsi_proc_info(struct Scsi_Host *instance, char *buffer, char **start,
 #endif
 		"\n\n", VER_MAJOR, VER_MINOR, VER_PATCH);
 
-    p += sprintf(p,	"SBIC: WD33C93A  Address: %p    IRQ : %d\n",
+    seq_printf(m,	"SBIC: WD33C93A  Address: %p    IRQ : %d\n",
 			host->base + SBIC_REGIDX, host->scsi.irq);
 #ifdef USE_DMAC
-    p += sprintf(p,	"DMAC: uPC71071  Address: %p  IRQ : %d\n\n",
+    seq_printf(m,	"DMAC: uPC71071  Address: %p  IRQ : %d\n\n",
 			host->base + DMAC_OFFSET, host->scsi.irq);
 #endif
 
-    p += sprintf(p,	"Statistics:\n"
+    seq_printf(m,	"Statistics:\n"
 			"Queued commands: %-10u    Issued commands: %-10u\n"
 			"Done commands  : %-10u    Reads          : %-10u\n"
 			"Writes         : %-10u    Others         : %-10u\n"
@@ -2886,7 +2881,7 @@ int acornscsi_proc_info(struct Scsi_Host *instance, char *buffer, char **start,
     for (devidx = 0; devidx < 9; devidx ++) {
 	unsigned int statptr, prev;
 
-	p += sprintf(p, "\n%c:", devidx == 8 ? 'H' : ('0' + devidx));
+	seq_printf(m, "\n%c:", devidx == 8 ? 'H' : ('0' + devidx));
 	statptr = host->status_ptr[devidx] - 10;
 
 	if ((signed int)statptr < 0)
@@ -2896,7 +2891,7 @@ int acornscsi_proc_info(struct Scsi_Host *instance, char *buffer, char **start,
 
 	for (; statptr != host->status_ptr[devidx]; statptr = (statptr + 1) & (STATUS_BUFFER_SIZE - 1)) {
 	    if (host->status[devidx][statptr].when) {
-		p += sprintf(p, "%c%02X:%02X+%2ld",
+		seq_printf(m, "%c%02X:%02X+%2ld",
 			host->status[devidx][statptr].irq ? '-' : ' ',
 			host->status[devidx][statptr].ph,
 			host->status[devidx][statptr].ssr,
@@ -2907,51 +2902,32 @@ int acornscsi_proc_info(struct Scsi_Host *instance, char *buffer, char **start,
 	}
     }
 
-    p += sprintf(p, "\nAttached devices:\n");
+    seq_printf(m, "\nAttached devices:\n");
 
     shost_for_each_device(scd, instance) {
-	p += sprintf(p, "Device/Lun TaggedQ      Sync\n");
-	p += sprintf(p, "     %d/%d   ", scd->id, scd->lun);
+	seq_printf(m, "Device/Lun TaggedQ      Sync\n");
+	seq_printf(m, "     %d/%d   ", scd->id, scd->lun);
 	if (scd->tagged_supported)
-		p += sprintf(p, "%3sabled(%3d) ",
+		seq_printf(m, "%3sabled(%3d) ",
 			     scd->simple_tags ? "en" : "dis",
 			     scd->current_tag);
 	else
-		p += sprintf(p, "unsupported  ");
+		seq_printf(m, "unsupported  ");
 
 	if (host->device[scd->id].sync_xfer & 15)
-		p += sprintf(p, "offset %d, %d ns\n",
+		seq_printf(m, "offset %d, %d ns\n",
 			     host->device[scd->id].sync_xfer & 15,
 			     acornscsi_getperiod(host->device[scd->id].sync_xfer));
 	else
-		p += sprintf(p, "async\n");
+		seq_printf(m, "async\n");
 
-	pos = p - buffer;
-	if (pos + begin < offset) {
-	    begin += pos;
-	    p = buffer;
-	}
-	pos = p - buffer;
-	if (pos + begin > offset + length) {
-	    scsi_device_put(scd);
-	    break;
-	}
     }
-
-    pos = p - buffer;
-
-    *start = buffer + (offset - begin);
-    pos -= offset - begin;
-
-    if (pos > length)
-	pos = length;
-
-    return pos;
+    return 0;
 }
 
 static struct scsi_host_template acornscsi_template = {
 	.module			= THIS_MODULE,
-	.proc_info		= acornscsi_proc_info,
+	.show_info		= acornscsi_show_info,
 	.name			= "AcornSCSI",
 	.info			= acornscsi_info,
 	.queuecommand		= acornscsi_queuecmd,
diff --git a/drivers/scsi/arm/arxescsi.c b/drivers/scsi/arm/arxescsi.c
index 9274510..32d2321 100644
--- a/drivers/scsi/arm/arxescsi.c
+++ b/drivers/scsi/arm/arxescsi.c
@@ -220,47 +220,21 @@ static const char *arxescsi_info(struct Scsi_Host *host)
 	return string;
 }
 
-/*
- * Function: int arxescsi_proc_info(char *buffer, char **start, off_t offset,
- *					 int length, int host_no, int inout)
- * Purpose : Return information about the driver to a user process accessing
- *	     the /proc filesystem.
- * Params  : buffer - a buffer to write information to
- *	     start  - a pointer into this buffer set by this routine to the start
- *		      of the required information.
- *	     offset - offset into information that we have read up to.
- *	     length - length of buffer
- *	     host_no - host number to return information for
- *	     inout  - 0 for reading, 1 for writing.
- * Returns : length of data written to buffer.
- */
 static int
-arxescsi_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, int length,
-		   int inout)
+arxescsi_show_info(struct seq_file *m, struct Scsi_Host *host)
 {
 	struct arxescsi_info *info;
-	char *p = buffer;
-	int pos;
-
 	info = (struct arxescsi_info *)host->hostdata;
-	if (inout == 1)
-		return -EINVAL;
-
-	p += sprintf(p, "ARXE 16-bit SCSI driver v%s\n", VERSION);
-	p += fas216_print_host(&info->info, p);
-	p += fas216_print_stats(&info->info, p);
-	p += fas216_print_devices(&info->info, p);
-
-	*start = buffer + offset;
-	pos = p - buffer - offset;
-	if (pos > length)
-		pos = length;
 
-	return pos;
+	seq_printf(m, "ARXE 16-bit SCSI driver v%s\n", VERSION);
+	fas216_print_host(&info->info, m);
+	fas216_print_stats(&info->info, m);
+	fas216_print_devices(&info->info, m);
+	return 0;
 }
 
 static struct scsi_host_template arxescsi_template = {
-	.proc_info			= arxescsi_proc_info,
+	.show_info			= arxescsi_show_info,
 	.name				= "ARXE SCSI card",
 	.info				= arxescsi_info,
 	.queuecommand			= fas216_noqueue_command,
diff --git a/drivers/scsi/arm/cumana_1.c b/drivers/scsi/arm/cumana_1.c
index c93938b..b679778 100644
--- a/drivers/scsi/arm/cumana_1.c
+++ b/drivers/scsi/arm/cumana_1.c
@@ -30,7 +30,6 @@
 #define NCR5380_write(reg, value)	cumanascsi_write(_instance, reg, value)
 #define NCR5380_intr			cumanascsi_intr
 #define NCR5380_queue_command		cumanascsi_queue_command
-#define NCR5380_proc_info		cumanascsi_proc_info
 
 #define NCR5380_implementation_fields	\
 	unsigned ctrl;			\
diff --git a/drivers/scsi/arm/cumana_2.c b/drivers/scsi/arm/cumana_2.c
index e3bae93..58915f2 100644
--- a/drivers/scsi/arm/cumana_2.c
+++ b/drivers/scsi/arm/cumana_2.c
@@ -337,50 +337,25 @@ cumanascsi_2_set_proc_info(struct Scsi_Host *host, char *buffer, int length)
 	return ret;
 }
 
-/* Prototype: int cumanascsi_2_proc_info(char *buffer, char **start, off_t offset,
- *					 int length, int host_no, int inout)
- * Purpose  : Return information about the driver to a user process accessing
- *	      the /proc filesystem.
- * Params   : buffer - a buffer to write information to
- *	      start  - a pointer into this buffer set by this routine to the start
- *		       of the required information.
- *	      offset - offset into information that we have read up to.
- *	      length - length of buffer
- *	      host_no - host number to return information for
- *	      inout  - 0 for reading, 1 for writing.
- * Returns  : length of data written to buffer.
- */
-int cumanascsi_2_proc_info (struct Scsi_Host *host, char *buffer, char **start, off_t offset,
-			    int length, int inout)
+static int cumanascsi_2_show_info(struct seq_file *m, struct Scsi_Host *host)
 {
 	struct cumanascsi2_info *info;
-	char *p = buffer;
-	int pos;
-
-	if (inout == 1)
-		return cumanascsi_2_set_proc_info(host, buffer, length);
-
 	info = (struct cumanascsi2_info *)host->hostdata;
 
-	p += sprintf(p, "Cumana SCSI II driver v%s\n", VERSION);
-	p += fas216_print_host(&info->info, p);
-	p += sprintf(p, "Term    : o%s\n",
+	seq_printf(m, "Cumana SCSI II driver v%s\n", VERSION);
+	fas216_print_host(&info->info, m);
+	seq_printf(m, "Term    : o%s\n",
 			info->terms ? "n" : "ff");
 
-	p += fas216_print_stats(&info->info, p);
-	p += fas216_print_devices(&info->info, p);
-
-	*start = buffer + offset;
-	pos = p - buffer - offset;
-	if (pos > length)
-		pos = length;
-
-	return pos;
+	fas216_print_stats(&info->info, m);
+	fas216_print_devices(&info->info, m);
+	return 0;
 }
 
 static struct scsi_host_template cumanascsi2_template = {
 	.module				= THIS_MODULE,
-	.proc_info			= cumanascsi_2_proc_info,
+	.show_info			= cumanascsi_2_show_info,
+	.write_info			= cumanascsi_2_set_proc_info,
 	.name				= "Cumana SCSI II",
 	.info				= cumanascsi_2_info,
 	.queuecommand			= fas216_queue_command,
diff --git a/drivers/scsi/arm/eesox.c b/drivers/scsi/arm/eesox.c
index 8e36908..5bf3c0d 100644
--- a/drivers/scsi/arm/eesox.c
+++ b/drivers/scsi/arm/eesox.c
@@ -422,45 +422,20 @@ eesoxscsi_set_proc_info(struct Scsi_Host *host, char *buffer, int length)
 	return ret;
 }
 
-/* Prototype: int eesoxscsi_proc_info(char *buffer, char **start, off_t offset,
- *				      int length, int host_no, int inout)
- * Purpose  : Return information about the driver to a user process accessing
- *	      the /proc filesystem.
- * Params   : buffer - a buffer to write information to
- *	      start  - a pointer into this buffer set by this routine to the start
- *		       of the required information.
- *	      offset - offset into information that we have read up to.
- *	      length - length of buffer
- *	      host_no - host number to return information for
- *	      inout  - 0 for reading, 1 for writing.
- * Returns  : length of data written to buffer.
- */
-int eesoxscsi_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
-			    int length, int inout)
+static int eesoxscsi_show_info(struct seq_file *m, struct Scsi_Host *host)
 {
 	struct eesoxscsi_info *info;
-	char *p = buffer;
-	int pos;
-
-	if (inout == 1)
-		return eesoxscsi_set_proc_info(host, buffer, length);
 
 	info = (struct eesoxscsi_info *)host->hostdata;
 
-	p += sprintf(p, "EESOX SCSI driver v%s\n", VERSION);
-	p += fas216_print_host(&info->info, p);
-	p += sprintf(p, "Term    : o%s\n",
+	seq_printf(m, "EESOX SCSI driver v%s\n", VERSION);
+	fas216_print_host(&info->info, m);
+	seq_printf(m, "Term    : o%s\n",
 			info->control & EESOX_TERM_ENABLE ? "n" : "ff");
 
-	p += fas216_print_stats(&info->info, p);
-	p += fas216_print_devices(&info->info, p);
-
-	*start = buffer + offset;
-	pos = p - buffer - offset;
-	if (pos > length)
-		pos = length;
-
-	return pos;
+	fas216_print_stats(&info->info, m);
+	fas216_print_devices(&info->info, m);
+	return 0;
 }
 
 static ssize_t eesoxscsi_show_term(struct device *dev, struct device_attribute *attr, char *buf)
@@ -498,7 +473,8 @@ static DEVICE_ATTR(bus_term, S_IRUGO | S_IWUSR,
 
 static struct scsi_host_template eesox_template = {
 	.module				= THIS_MODULE,
-	.proc_info			= eesoxscsi_proc_info,
+	.show_info			= eesoxscsi_show_info,
+	.write_info			= eesoxscsi_set_proc_info,
 	.name				= "EESOX SCSI",
 	.info				= eesoxscsi_info,
 	.queuecommand			= fas216_queue_command,
diff --git a/drivers/scsi/arm/fas216.c b/drivers/scsi/arm/fas216.c
index 737554c..b46a6f6 100644
--- a/drivers/scsi/arm/fas216.c
+++ b/drivers/scsi/arm/fas216.c
@@ -2958,9 +2958,9 @@ void fas216_release(struct Scsi_Host *host)
 	queue_free(&info->queues.issue);
 }
 
-int fas216_print_host(FAS216_Info *info, char *buffer)
+void fas216_print_host(FAS216_Info *info, struct seq_file *m)
 {
-	return sprintf(buffer,
+	seq_printf(m,
 			"\n"
 			"Chip    : %s\n"
 			" Address: 0x%p\n"
@@ -2970,11 +2970,9 @@ int fas216_print_host(FAS216_Info *info, char *buffer)
 			info->scsi.irq, info->scsi.dma);
 }
 
-int fas216_print_stats(FAS216_Info *info, char *buffer)
+void fas216_print_stats(FAS216_Info *info, struct seq_file *m)
 {
-	char *p = buffer;
-
-	p += sprintf(p, "\n"
+	seq_printf(m, "\n"
 			"Command Statistics:\n"
 			" Queued     : %u\n"
 			" Issued     : %u\n"
@@ -2991,38 +2989,33 @@ int fas216_print_stats(FAS216_Info *info, char *buffer)
 			info->stats.writes,	 info->stats.miscs,
 			info->stats.disconnects, info->stats.aborts,
 			info->stats.bus_resets,	 info->stats.host_resets);
-
-	return p - buffer;
 }
 
-int fas216_print_devices(FAS216_Info *info, char *buffer)
+void fas216_print_devices(FAS216_Info *info, struct seq_file *m)
 {
 	struct fas216_device *dev;
 	struct scsi_device *scd;
-	char *p = buffer;
 
-	p += sprintf(p, "Device/Lun TaggedQ       Parity   Sync\n");
+	seq_printf(m, "Device/Lun TaggedQ       Parity   Sync\n");
 
 	shost_for_each_device(scd, info->host) {
 		dev = &info->device[scd->id];
-		p += sprintf(p, "     %d/%d   ", scd->id, scd->lun);
+		seq_printf(m, "     %d/%d   ", scd->id, scd->lun);
 		if (scd->tagged_supported)
-			p += sprintf(p, "%3sabled(%3d) ",
+			seq_printf(m, "%3sabled(%3d) ",
 				     scd->simple_tags ? "en" : "dis",
 				     scd->current_tag);
 		else
-			p += sprintf(p, "unsupported   ");
+			seq_printf(m, "unsupported   ");
 
-		p += sprintf(p, "%3sabled ", dev->parity_enabled ? "en" : "dis");
+		seq_printf(m, "%3sabled ", dev->parity_enabled ? "en" : "dis");
 
 		if (dev->sof)
-			p += sprintf(p, "offset %d, %d ns\n",
+			seq_printf(m, "offset %d, %d ns\n",
 				     dev->sof, dev->period * 4);
 		else
-			p += sprintf(p, "async\n");
+			seq_printf(m, "async\n");
 	}
-
-	return p - buffer;
 }
 
 EXPORT_SYMBOL(fas216_init);
diff --git a/drivers/scsi/arm/fas216.h b/drivers/scsi/arm/fas216.h
index df2e1b3..c57c16e 100644
--- a/drivers/scsi/arm/fas216.h
+++ b/drivers/scsi/arm/fas216.h
@@ -358,9 +358,9 @@ extern void fas216_remove (struct Scsi_Host *instance);
  */
 extern void fas216_release (struct Scsi_Host *instance);
 
-extern int fas216_print_host(FAS216_Info *info, char *buffer);
-extern int fas216_print_stats(FAS216_Info *info, char *buffer);
-extern int fas216_print_devices(FAS216_Info *info, char *buffer);
+extern void fas216_print_host(FAS216_Info *info, struct seq_file *m);
+extern void fas216_print_stats(FAS216_Info *info, struct seq_file *m);
+extern void fas216_print_devices(FAS216_Info *info, struct seq_file *m);
 
 /* Function: int fas216_eh_abort(struct scsi_cmnd *SCpnt)
  * Purpose : abort this command
diff --git a/drivers/scsi/arm/oak.c b/drivers/scsi/arm/oak.c
index 48facdc..4266eef 100644
--- a/drivers/scsi/arm/oak.c
+++ b/drivers/scsi/arm/oak.c
@@ -31,7 +31,8 @@
 #define NCR5380_write(reg, value)	writeb(value, _base + ((reg) << 2))
 #define NCR5380_intr			oakscsi_intr
 #define NCR5380_queue_command		oakscsi_queue_command
-#define NCR5380_proc_info		oakscsi_proc_info
+#define NCR5380_show_info		oakscsi_show_info
+#define NCR5380_write_info		oakscsi_write_info
 
 #define NCR5380_implementation_fields	\
 	void __iomem *base
@@ -115,7 +116,8 @@ printk("reading %p len %d\n", addr, len);
 
 static struct scsi_host_template oakscsi_template = {
 	.module			= THIS_MODULE,
-	.proc_info		= oakscsi_proc_info,
+	.show_info		= oakscsi_show_info,
+	.write_info		= oakscsi_write_info,
 	.name			= "Oak 16-bit SCSI",
 	.info			= oakscsi_info,
 	.queuecommand		= oakscsi_queue_command,
diff --git a/drivers/scsi/arm/powertec.c b/drivers/scsi/arm/powertec.c
index 246600b..abc9593 100644
--- a/drivers/scsi/arm/powertec.c
+++ b/drivers/scsi/arm/powertec.c
@@ -237,32 +237,20 @@ powertecscsi_set_proc_info(struct Scsi_Host *host, char *buffer, int length)
  *	      inout   - 0 for reading, 1 for writing.
  * Returns  : length of data written to buffer.
  */
-int powertecscsi_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
-			    int length, int inout)
+static int powertecscsi_show_info(struct seq_file *m, struct Scsi_Host *host)
 {
 	struct powertec_info *info;
-	char *p = buffer;
-	int pos;
-
-	if (inout == 1)
-		return powertecscsi_set_proc_info(host, buffer, length);
 
 	info = (struct powertec_info *)host->hostdata;
 
-	p += sprintf(p, "PowerTec SCSI driver v%s\n", VERSION);
-	p += fas216_print_host(&info->info, p);
-	p += sprintf(p, "Term    : o%s\n",
+	seq_printf(m, "PowerTec SCSI driver v%s\n", VERSION);
+	fas216_print_host(&info->info, m);
+	seq_printf(m, "Term    : o%s\n",
 			info->term_ctl ? "n" : "ff");
 
-	p += fas216_print_stats(&info->info, p);
-	p += fas216_print_devices(&info->info, p);
-
-	*start = buffer + offset;
-	pos = p - buffer - offset;
-	if (pos > length)
-		pos = length;
-
-	return pos;
+	fas216_print_stats(&info->info, m);
+	fas216_print_devices(&info->info, m);
+	return 0;
 }
 
 static ssize_t powertecscsi_show_term(struct device *dev, struct device_attribute *attr, char *buf)
@@ -291,7 +279,8 @@ static DEVICE_ATTR(bus_term, S_IRUGO | S_IWUSR,
 
 static struct scsi_host_template powertecscsi_template = {
 	.module				= THIS_MODULE,
-	.proc_info			= powertecscsi_proc_info,
+	.show_info			= powertecscsi_show_info,
+	.write_info			= powertecscsi_set_proc_info,
 	.name				= "PowerTec SCSI",
 	.info				= powertecscsi_info,
 	.queuecommand			= fas216_queue_command,
diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c
index 2db79b4..0f3cdbc 100644
--- a/drivers/scsi/atari_NCR5380.c
+++ b/drivers/scsi/atari_NCR5380.c
@@ -719,119 +719,94 @@ static void __init NCR5380_print_options(struct Scsi_Host *instance)
  * Inputs : instance, pointer to this instance.
  */
 
-static void NCR5380_print_status(struct Scsi_Host *instance)
+static void lprint_Scsi_Cmnd(Scsi_Cmnd *cmd)
 {
-	char *pr_bfr;
-	char *start;
-	int len;
-
-	NCR_PRINT(NDEBUG_ANY);
-	NCR_PRINT_PHASE(NDEBUG_ANY);
-
-	pr_bfr = (char *)__get_free_page(GFP_ATOMIC);
-	if (!pr_bfr) {
-		printk("NCR5380_print_status: no memory for print buffer\n");
-		return;
-	}
-	len = NCR5380_proc_info(instance, pr_bfr, &start, 0, PAGE_SIZE, 0);
-	pr_bfr[len] = 0;
-	printk("\n%s\n", pr_bfr);
-	free_page((unsigned long)pr_bfr);
+	int i, s;
+	unsigned char *command;
+	printk("scsi%d: destination target %d, lun %d\n",
+		H_NO(cmd), cmd->device->id, cmd->device->lun);
+	printk(KERN_CONT "        command = ");
+	command = cmd->cmnd;
+	printk(KERN_CONT "%2d (0x%02x)", command[0], command[0]);
+	for (i = 1, s = COMMAND_SIZE(command[0]); i < s; ++i)
+		printk(KERN_CONT " %02x", command[i]);
+	printk("\n");
 }
 
-
-/******************************************/
-/*
- * /proc/scsi/[dtc pas16 t128 generic]/[0-ASC_NUM_BOARD_SUPPORTED]
- *
- * *buffer: I/O buffer
- * **start: if inout == FALSE pointer into buffer where user read should start
- * offset: current offset
- * length: length of buffer
- * hostno: Scsi_Host host_no
- * inout: TRUE - user is writing; FALSE - user is reading
- *
- * Return the number of bytes read from or written
-*/
-
-#undef SPRINTF
-#define SPRINTF(fmt,args...)							\
-	do {									\
-		if (pos + strlen(fmt) + 20 /* slop */ < buffer + length)	\
-			pos += sprintf(pos, fmt , ## args);			\
-	} while(0)
-static char *lprint_Scsi_Cmnd(Scsi_Cmnd *cmd, char *pos, char *buffer, int length);
-
-static int NCR5380_proc_info(struct Scsi_Host *instance, char *buffer,
-			     char **start, off_t offset, int length, int inout)
+static void NCR5380_print_status(struct Scsi_Host *instance)
 {
-	char *pos = buffer;
 	struct NCR5380_hostdata *hostdata;
 	Scsi_Cmnd *ptr;
 	unsigned long flags;
-	off_t begin = 0;
-#define check_offset()					\
-	do {						\
-		if (pos - buffer < offset - begin) {	\
-			begin += pos - buffer;		\
-			pos = buffer;			\
-		}					\
-	} while (0)
+
+	NCR_PRINT(NDEBUG_ANY);
+	NCR_PRINT_PHASE(NDEBUG_ANY);
 
 	hostdata = (struct NCR5380_hostdata *)instance->hostdata;
 
-	if (inout)			/* Has data been written to the file ? */
-		return -ENOSYS;		/* Currently this is a no-op */
-	SPRINTF("NCR5380 core release=%d.\n", NCR5380_PUBLIC_RELEASE);
-	check_offset();
+	printk("\nNCR5380 core release=%d.\n", NCR5380_PUBLIC_RELEASE);
 	local_irq_save(flags);
-	SPRINTF("NCR5380: coroutine is%s running.\n",
+	printk("NCR5380: coroutine is%s running.\n",
 		main_running ? "" : "n't");
-	check_offset();
 	if (!hostdata->connected)
-		SPRINTF("scsi%d: no currently connected command\n", HOSTNO);
+		printk("scsi%d: no currently connected command\n", HOSTNO);
 	else
-		pos = lprint_Scsi_Cmnd((Scsi_Cmnd *) hostdata->connected,
-				       pos, buffer, length);
-	SPRINTF("scsi%d: issue_queue\n", HOSTNO);
-	check_offset();
-	for (ptr = (Scsi_Cmnd *)hostdata->issue_queue; ptr; ptr = NEXT(ptr)) {
-		pos = lprint_Scsi_Cmnd(ptr, pos, buffer, length);
-		check_offset();
-	}
+		lprint_Scsi_Cmnd((Scsi_Cmnd *) hostdata->connected);
+	printk("scsi%d: issue_queue\n", HOSTNO);
+	for (ptr = (Scsi_Cmnd *)hostdata->issue_queue; ptr; ptr = NEXT(ptr))
+		lprint_Scsi_Cmnd(ptr);
 
-	SPRINTF("scsi%d: disconnected_queue\n", HOSTNO);
-	check_offset();
+	printk("scsi%d: disconnected_queue\n", HOSTNO);
 	for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr;
-	     ptr = NEXT(ptr)) {
-		pos = lprint_Scsi_Cmnd(ptr, pos, buffer, length);
-		check_offset();
-	}
+	     ptr = NEXT(ptr))
+		lprint_Scsi_Cmnd(ptr);
 
 	local_irq_restore(flags);
-	*start = buffer + (offset - begin);
-	if (pos - buffer < offset - begin)
-		return 0;
-	else if (pos - buffer - (offset - begin) < length)
-		return pos - buffer - (offset - begin);
-	return length;
+	printk("\n");
 }
 
-static char *lprint_Scsi_Cmnd(Scsi_Cmnd *cmd, char *pos, char *buffer, int length)
+static void show_Scsi_Cmnd(Scsi_Cmnd *cmd, struct seq_file *m)
 {
 	int i, s;
 	unsigned char *command;
-	SPRINTF("scsi%d: destination target %d, lun %d\n",
+	seq_printf(m, "scsi%d: destination target %d, lun %d\n",
 		H_NO(cmd), cmd->device->id, cmd->device->lun);
-	SPRINTF("        command = ");
+	seq_printf(m, "        command = ");
 	command = cmd->cmnd;
-	SPRINTF("%2d (0x%02x)", command[0], command[0]);
+	seq_printf(m, "%2d (0x%02x)", command[0], command[0]);
 	for (i = 1, s = COMMAND_SIZE(command[0]); i < s; ++i)
-		SPRINTF(" %02x", command[i]);
-	SPRINTF("\n");
-	return pos;
+		seq_printf(m, " %02x", command[i]);
+	seq_printf(m, "\n");
 }
 
+static int NCR5380_show_info(struct seq_file *m, struct Scsi_Host *instance)
+{
+	struct NCR5380_hostdata *hostdata;
+	Scsi_Cmnd *ptr;
+	unsigned long flags;
+
+	hostdata = (struct NCR5380_hostdata *)instance->hostdata;
+
+	seq_printf(m, "NCR5380 core release=%d.\n", NCR5380_PUBLIC_RELEASE);
+	local_irq_save(flags);
+	seq_printf(m, "NCR5380: coroutine is%s running.\n",
+		main_running ? "" : "n't");
+	if (!hostdata->connected)
+		seq_printf(m, "scsi%d: no currently connected command\n", HOSTNO);
+	else
+		show_Scsi_Cmnd((Scsi_Cmnd *) hostdata->connected, m);
+	seq_printf(m, "scsi%d: issue_queue\n", HOSTNO);
+	for (ptr = (Scsi_Cmnd *)hostdata->issue_queue; ptr; ptr = NEXT(ptr))
+		show_Scsi_Cmnd(ptr, m);
+
+	seq_printf(m, "scsi%d: disconnected_queue\n", HOSTNO);
+	for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr;
+	     ptr = NEXT(ptr))
+		show_Scsi_Cmnd(ptr, m);
+
+	local_irq_restore(flags);
+	return 0;
+}
 
 /*
  * Function : void NCR5380_init (struct Scsi_Host *instance)
diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c
index df740cb..a3e6c8a 100644
--- a/drivers/scsi/atari_scsi.c
+++ b/drivers/scsi/atari_scsi.c
@@ -1100,7 +1100,7 @@ static void atari_scsi_falcon_reg_write(unsigned char reg, unsigned char value)
 #include "atari_NCR5380.c"
 
 static struct scsi_host_template driver_template = {
-	.proc_info		= atari_scsi_proc_info,
+	.show_info		= atari_scsi_show_info,
 	.name			= "Atari native SCSI",
 	.detect			= atari_scsi_detect,
 	.release		= atari_scsi_release,
diff --git a/drivers/scsi/atari_scsi.h b/drivers/scsi/atari_scsi.h
index bd52df7..11c624b 100644
--- a/drivers/scsi/atari_scsi.h
+++ b/drivers/scsi/atari_scsi.h
@@ -47,7 +47,7 @@
 #define NCR5380_intr atari_scsi_intr
 #define NCR5380_queue_command atari_scsi_queue_command
 #define NCR5380_abort atari_scsi_abort
-#define NCR5380_proc_info atari_scsi_proc_info
+#define NCR5380_show_info atari_scsi_show_info
 #define NCR5380_dma_read_setup(inst,d,c) atari_scsi_dma_setup (inst, d, c, 0)
 #define NCR5380_dma_write_setup(inst,d,c) atari_scsi_dma_setup (inst, d, c, 1)
 #define NCR5380_dma_residual(inst) atari_scsi_dma_residual( inst )
diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index cfc7304..15a629d 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -3099,38 +3099,14 @@ static const char *atp870u_info(struct Scsi_Host *notused)
 	return buffer;
 }
 
-#define BLS buffer + len + size
-static int atp870u_proc_info(struct Scsi_Host *HBAptr, char *buffer, 
-			     char **start, off_t offset, int length, int inout)
+static int atp870u_show_info(struct seq_file *m, struct Scsi_Host *HBAptr)
 {
-	static u8 buff[512];
-	int size = 0;
-	int len = 0;
-	off_t begin = 0;
-	off_t pos = 0;
-	
-	if (inout) 	
-		return -EINVAL;
-	if (offset == 0)
-		memset(buff, 0, sizeof(buff));
-	size += sprintf(BLS, "ACARD AEC-671X Driver Version: 2.6+ac\n");
-	len += size;
-	pos = begin + len;
-	size = 0;
-
-	size += sprintf(BLS, "\n");
-	size += sprintf(BLS, "Adapter Configuration:\n");
-	size += sprintf(BLS, "               Base IO: %#.4lx\n", HBAptr->io_port);
-	size += sprintf(BLS, "                   IRQ: %d\n", HBAptr->irq);
-	len += size;
-	pos = begin + len;
-	
-	*start = buffer + (offset - begin);	/* Start of wanted data */
-	len -= (offset - begin);	/* Start slop */
-	if (len > length) {
-		len = length;	/* Ending slop */
-	}
-	return (len);
+	seq_printf(m, "ACARD AEC-671X Driver Version: 2.6+ac\n");
+	seq_printf(m, "\n");
+	seq_printf(m, "Adapter Configuration:\n");
+	seq_printf(m, "               Base IO: %#.4lx\n", HBAptr->io_port);
+	seq_printf(m, "                   IRQ: %d\n", HBAptr->irq);
+	return 0;
 }
 
 
@@ -3177,7 +3153,7 @@ static struct scsi_host_template atp870u_template = {
      .module			= THIS_MODULE,
      .name              	= "atp870u"		/* name */,
      .proc_name			= "atp870u",
-     .proc_info			= atp870u_proc_info,
+     .show_info			= atp870u_show_info,
      .info              	= atp870u_info		/* info */,
      .queuecommand      	= atp870u_queuecommand	/* queuecommand */,
      .eh_abort_handler  	= atp870u_abort		/* abort */,
diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
index 2daf4b0..90bc7bd 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
@@ -940,6 +940,7 @@ static int bnx2fc_libfc_config(struct fc_lport *lport)
 	fc_exch_init(lport);
 	fc_rport_init(lport);
 	fc_disc_init(lport);
+	fc_disc_config(lport, lport);
 	return 0;
 }
 
@@ -2133,6 +2134,7 @@ static int _bnx2fc_create(struct net_device *netdev,
 	}
 
 	ctlr = bnx2fc_to_ctlr(interface);
+	cdev = fcoe_ctlr_to_ctlr_dev(ctlr);
 	interface->vlan_id = vlan_id;
 
 	interface->timer_work_queue =
@@ -2143,7 +2145,7 @@ static int _bnx2fc_create(struct net_device *netdev,
 		goto ifput_err;
 	}
 
-	lport = bnx2fc_if_create(interface, &interface->hba->pcidev->dev, 0);
+	lport = bnx2fc_if_create(interface, &cdev->dev, 0);
 	if (!lport) {
 		printk(KERN_ERR PFX "Failed to create interface (%s)\n",
 			netdev->name);
@@ -2159,8 +2161,6 @@ static int _bnx2fc_create(struct net_device *netdev,
 	/* Make this master N_port */
 	ctlr->lp = lport;
 
-	cdev = fcoe_ctlr_to_ctlr_dev(ctlr);
-
 	if (link_state == BNX2FC_CREATE_LINK_UP)
 		cdev->enabled = FCOE_CTLR_ENABLED;
 	else
diff --git a/drivers/scsi/csiostor/Makefile b/drivers/scsi/csiostor/Makefile
index b581966..913b9a9 100644
--- a/drivers/scsi/csiostor/Makefile
+++ b/drivers/scsi/csiostor/Makefile
@@ -8,4 +8,5 @@ ccflags-y += -I$(srctree)/drivers/net/ethernet/chelsio/cxgb4
 obj-$(CONFIG_SCSI_CHELSIO_FCOE) += csiostor.o
 
 csiostor-objs := csio_attr.o csio_init.o csio_lnode.o csio_scsi.o \
-		csio_hw.o csio_isr.o csio_mb.o csio_rnode.o csio_wr.o
+		csio_hw.o csio_hw_t4.o csio_hw_t5.o csio_isr.o \
+		csio_mb.o csio_rnode.o csio_wr.o
diff --git a/drivers/scsi/csiostor/csio_hw.c b/drivers/scsi/csiostor/csio_hw.c
index bdd78fb..a0b4c89 100644
--- a/drivers/scsi/csiostor/csio_hw.c
+++ b/drivers/scsi/csiostor/csio_hw.c
@@ -61,7 +61,7 @@ int csio_msi = 2;
 static int dev_num;
 
 /* FCoE Adapter types & its description */
-static const struct csio_adap_desc csio_fcoe_adapters[] = {
+static const struct csio_adap_desc csio_t4_fcoe_adapters[] = {
 	{"T440-Dbg 10G", "Chelsio T440-Dbg 10G [FCoE]"},
 	{"T420-CR 10G", "Chelsio T420-CR 10G [FCoE]"},
 	{"T422-CR 10G/1G", "Chelsio T422-CR 10G/1G [FCoE]"},
@@ -77,7 +77,38 @@ static const struct csio_adap_desc csio_fcoe_adapters[] = {
 	{"B404-BT 1G", "Chelsio B404-BT 1G [FCoE]"},
 	{"T480-CR 10G", "Chelsio T480-CR 10G [FCoE]"},
 	{"T440-LP-CR 10G", "Chelsio T440-LP-CR 10G [FCoE]"},
-	{"T4 FPGA", "Chelsio T4 FPGA [FCoE]"}
+	{"AMSTERDAM 10G", "Chelsio AMSTERDAM 10G [FCoE]"},
+	{"HUAWEI T480 10G", "Chelsio HUAWEI T480 10G [FCoE]"},
+	{"HUAWEI T440 10G", "Chelsio HUAWEI T440 10G [FCoE]"},
+	{"HUAWEI STG 10G", "Chelsio HUAWEI STG 10G [FCoE]"},
+	{"ACROMAG XAUI 10G", "Chelsio ACROMAG XAUI 10G [FCoE]"},
+	{"ACROMAG SFP+ 10G", "Chelsio ACROMAG SFP+ 10G [FCoE]"},
+	{"QUANTA SFP+ 10G", "Chelsio QUANTA SFP+ 10G [FCoE]"},
+	{"HUAWEI 10Gbase-T", "Chelsio HUAWEI 10Gbase-T [FCoE]"},
+	{"HUAWEI T4TOE 10G", "Chelsio HUAWEI T4TOE 10G [FCoE]"}
+};
+
+static const struct csio_adap_desc csio_t5_fcoe_adapters[] = {
+	{"T580-Dbg 10G", "Chelsio T580-Dbg 10G [FCoE]"},
+	{"T520-CR 10G", "Chelsio T520-CR 10G [FCoE]"},
+	{"T522-CR 10G/1G", "Chelsio T452-CR 10G/1G [FCoE]"},
+	{"T540-CR 10G", "Chelsio T540-CR 10G [FCoE]"},
+	{"T520-BCH 10G", "Chelsio T520-BCH 10G [FCoE]"},
+	{"T540-BCH 10G", "Chelsio T540-BCH 10G [FCoE]"},
+	{"T540-CH 10G", "Chelsio T540-CH 10G [FCoE]"},
+	{"T520-SO 10G", "Chelsio T520-SO 10G [FCoE]"},
+	{"T520-CX4 10G", "Chelsio T520-CX4 10G [FCoE]"},
+	{"T520-BT 10G", "Chelsio T520-BT 10G [FCoE]"},
+	{"T504-BT 1G", "Chelsio T504-BT 1G [FCoE]"},
+	{"B520-SR 10G", "Chelsio B520-SR 10G [FCoE]"},
+	{"B504-BT 1G", "Chelsio B504-BT 1G [FCoE]"},
+	{"T580-CR 10G", "Chelsio T580-CR 10G [FCoE]"},
+	{"T540-LP-CR 10G", "Chelsio T540-LP-CR 10G [FCoE]"},
+	{"AMSTERDAM 10G", "Chelsio AMSTERDAM 10G [FCoE]"},
+	{"T580-LP-CR 40G", "Chelsio T580-LP-CR 40G [FCoE]"},
+	{"T520-LL-CR 10G", "Chelsio T520-LL-CR 10G [FCoE]"},
+	{"T560-CR 40G", "Chelsio T560-CR 40G [FCoE]"},
+	{"T580-CR 40G", "Chelsio T580-CR 40G [FCoE]"}
 };
 
 static void csio_mgmtm_cleanup(struct csio_mgmtm *);
@@ -124,7 +155,7 @@ int csio_is_hw_removing(struct csio_hw *hw)
  *	at the time it indicated completion is stored there.  Returns 0 if the
  *	operation completes and	-EAGAIN	otherwise.
  */
-static int
+int
 csio_hw_wait_op_done_val(struct csio_hw *hw, int reg, uint32_t mask,
 			 int polarity, int attempts, int delay, uint32_t *valp)
 {
@@ -145,6 +176,24 @@ csio_hw_wait_op_done_val(struct csio_hw *hw, int reg, uint32_t mask,
 	}
 }
 
+/*
+ *	csio_hw_tp_wr_bits_indirect - set/clear bits in an indirect TP register
+ *	@hw: the adapter
+ *	@addr: the indirect TP register address
+ *	@mask: specifies the field within the register to modify
+ *	@val: new value for the field
+ *
+ *	Sets a field of an indirect TP register to the given value.
+ */
+void
+csio_hw_tp_wr_bits_indirect(struct csio_hw *hw, unsigned int addr,
+			unsigned int mask, unsigned int val)
+{
+	csio_wr_reg32(hw, addr, TP_PIO_ADDR);
+	val |= csio_rd_reg32(hw, TP_PIO_DATA) & ~mask;
+	csio_wr_reg32(hw, val, TP_PIO_DATA);
+}
+
 void
 csio_set_reg_field(struct csio_hw *hw, uint32_t reg, uint32_t mask,
 		   uint32_t value)
@@ -157,242 +206,22 @@ csio_set_reg_field(struct csio_hw *hw, uint32_t reg, uint32_t mask,
 
 }
 
-/*
- *	csio_hw_mc_read - read from MC through backdoor accesses
- *	@hw: the hw module
- *	@addr: address of first byte requested
- *	@data: 64 bytes of data containing the requested address
- *	@ecc: where to store the corresponding 64-bit ECC word
- *
- *	Read 64 bytes of data from MC starting at a 64-byte-aligned address
- *	that covers the requested address @addr.  If @parity is not %NULL it
- *	is assigned the 64-bit ECC word for the read data.
- */
-int
-csio_hw_mc_read(struct csio_hw *hw, uint32_t addr, __be32 *data,
-		uint64_t *ecc)
-{
-	int i;
-
-	if (csio_rd_reg32(hw, MC_BIST_CMD) & START_BIST)
-		return -EBUSY;
-	csio_wr_reg32(hw, addr & ~0x3fU, MC_BIST_CMD_ADDR);
-	csio_wr_reg32(hw, 64, MC_BIST_CMD_LEN);
-	csio_wr_reg32(hw, 0xc, MC_BIST_DATA_PATTERN);
-	csio_wr_reg32(hw, BIST_OPCODE(1) | START_BIST |  BIST_CMD_GAP(1),
-		      MC_BIST_CMD);
-	i = csio_hw_wait_op_done_val(hw, MC_BIST_CMD, START_BIST,
-		 0, 10, 1, NULL);
-	if (i)
-		return i;
-
-#define MC_DATA(i) MC_BIST_STATUS_REG(MC_BIST_STATUS_RDATA, i)
-
-	for (i = 15; i >= 0; i--)
-		*data++ = htonl(csio_rd_reg32(hw, MC_DATA(i)));
-	if (ecc)
-		*ecc = csio_rd_reg64(hw, MC_DATA(16));
-#undef MC_DATA
-	return 0;
-}
-
-/*
- *	csio_hw_edc_read - read from EDC through backdoor accesses
- *	@hw: the hw module
- *	@idx: which EDC to access
- *	@addr: address of first byte requested
- *	@data: 64 bytes of data containing the requested address
- *	@ecc: where to store the corresponding 64-bit ECC word
- *
- *	Read 64 bytes of data from EDC starting at a 64-byte-aligned address
- *	that covers the requested address @addr.  If @parity is not %NULL it
- *	is assigned the 64-bit ECC word for the read data.
- */
-int
-csio_hw_edc_read(struct csio_hw *hw, int idx, uint32_t addr, __be32 *data,
-		uint64_t *ecc)
-{
-	int i;
-
-	idx *= EDC_STRIDE;
-	if (csio_rd_reg32(hw, EDC_BIST_CMD + idx) & START_BIST)
-		return -EBUSY;
-	csio_wr_reg32(hw, addr & ~0x3fU, EDC_BIST_CMD_ADDR + idx);
-	csio_wr_reg32(hw, 64, EDC_BIST_CMD_LEN + idx);
-	csio_wr_reg32(hw, 0xc, EDC_BIST_DATA_PATTERN + idx);
-	csio_wr_reg32(hw, BIST_OPCODE(1) | BIST_CMD_GAP(1) | START_BIST,
-		     EDC_BIST_CMD + idx);
-	i = csio_hw_wait_op_done_val(hw, EDC_BIST_CMD + idx, START_BIST,
-		 0, 10, 1, NULL);
-	if (i)
-		return i;
-
-#define EDC_DATA(i) (EDC_BIST_STATUS_REG(EDC_BIST_STATUS_RDATA, i) + idx)
-
-	for (i = 15; i >= 0; i--)
-		*data++ = htonl(csio_rd_reg32(hw, EDC_DATA(i)));
-	if (ecc)
-		*ecc = csio_rd_reg64(hw, EDC_DATA(16));
-#undef EDC_DATA
-	return 0;
-}
-
-/*
- *      csio_mem_win_rw - read/write memory through PCIE memory window
- *      @hw: the adapter
- *      @addr: address of first byte requested
- *      @data: MEMWIN0_APERTURE bytes of data containing the requested address
- *      @dir: direction of transfer 1 => read, 0 => write
- *
- *      Read/write MEMWIN0_APERTURE bytes of data from MC starting at a
- *      MEMWIN0_APERTURE-byte-aligned address that covers the requested
- *      address @addr.
- */
-static int
-csio_mem_win_rw(struct csio_hw *hw, u32 addr, u32 *data, int dir)
-{
-	int i;
-
-	/*
-	 * Setup offset into PCIE memory window.  Address must be a
-	 * MEMWIN0_APERTURE-byte-aligned address.  (Read back MA register to
-	 * ensure that changes propagate before we attempt to use the new
-	 * values.)
-	 */
-	csio_wr_reg32(hw, addr & ~(MEMWIN0_APERTURE - 1),
-			PCIE_MEM_ACCESS_OFFSET);
-	csio_rd_reg32(hw, PCIE_MEM_ACCESS_OFFSET);
-
-	/* Collecting data 4 bytes at a time upto MEMWIN0_APERTURE */
-	for (i = 0; i < MEMWIN0_APERTURE; i = i + sizeof(__be32)) {
-		if (dir)
-			*data++ = csio_rd_reg32(hw, (MEMWIN0_BASE + i));
-		else
-			csio_wr_reg32(hw, *data++, (MEMWIN0_BASE + i));
-	}
-
-	return 0;
-}
-
-/*
- *      csio_memory_rw - read/write EDC 0, EDC 1 or MC via PCIE memory window
- *      @hw: the csio_hw
- *      @mtype: memory type: MEM_EDC0, MEM_EDC1 or MEM_MC
- *      @addr: address within indicated memory type
- *      @len: amount of memory to transfer
- *      @buf: host memory buffer
- *      @dir: direction of transfer 1 => read, 0 => write
- *
- *      Reads/writes an [almost] arbitrary memory region in the firmware: the
- *      firmware memory address, length and host buffer must be aligned on
- *      32-bit boudaries.  The memory is transferred as a raw byte sequence
- *      from/to the firmware's memory.  If this memory contains data
- *      structures which contain multi-byte integers, it's the callers
- *      responsibility to perform appropriate byte order conversions.
- */
-static int
-csio_memory_rw(struct csio_hw *hw, int mtype, u32 addr, u32 len,
-		uint32_t *buf, int dir)
-{
-	uint32_t pos, start, end, offset, memoffset;
-	int ret;
-	uint32_t *data;
-
-	/*
-	 * Argument sanity checks ...
-	 */
-	if ((addr & 0x3) || (len & 0x3))
-		return -EINVAL;
-
-	data = kzalloc(MEMWIN0_APERTURE, GFP_KERNEL);
-	if (!data)
-		return -ENOMEM;
-
-	/* Offset into the region of memory which is being accessed
-	 * MEM_EDC0 = 0
-	 * MEM_EDC1 = 1
-	 * MEM_MC   = 2
-	 */
-	memoffset = (mtype * (5 * 1024 * 1024));
-
-	/* Determine the PCIE_MEM_ACCESS_OFFSET */
-	addr = addr + memoffset;
-
-	/*
-	 * The underlaying EDC/MC read routines read MEMWIN0_APERTURE bytes
-	 * at a time so we need to round down the start and round up the end.
-	 * We'll start copying out of the first line at (addr - start) a word
-	 * at a time.
-	 */
-	start = addr & ~(MEMWIN0_APERTURE-1);
-	end = (addr + len + MEMWIN0_APERTURE-1) & ~(MEMWIN0_APERTURE-1);
-	offset = (addr - start)/sizeof(__be32);
-
-	for (pos = start; pos < end; pos += MEMWIN0_APERTURE, offset = 0) {
-		/*
-		 * If we're writing, copy the data from the caller's memory
-		 * buffer
-		 */
-		if (!dir) {
-			/*
-			 * If we're doing a partial write, then we need to do
-			 * a read-modify-write ...
-			 */
-			if (offset || len < MEMWIN0_APERTURE) {
-				ret = csio_mem_win_rw(hw, pos, data, 1);
-				if (ret) {
-					kfree(data);
-					return ret;
-				}
-			}
-			while (offset < (MEMWIN0_APERTURE/sizeof(__be32)) &&
-								len > 0) {
-				data[offset++] = *buf++;
-				len -= sizeof(__be32);
-			}
-		}
-
-		/*
-		 * Transfer a block of memory and bail if there's an error.
-		 */
-		ret = csio_mem_win_rw(hw, pos, data, dir);
-		if (ret) {
-			kfree(data);
-			return ret;
-		}
-
-		/*
-		 * If we're reading, copy the data into the caller's memory
-		 * buffer.
-		 */
-		if (dir)
-			while (offset < (MEMWIN0_APERTURE/sizeof(__be32)) &&
-								len > 0) {
-				*buf++ = data[offset++];
-				len -= sizeof(__be32);
-			}
-	}
-
-	kfree(data);
-
-	return 0;
-}
-
 static int
 csio_memory_write(struct csio_hw *hw, int mtype, u32 addr, u32 len, u32 *buf)
 {
-	return csio_memory_rw(hw, mtype, addr, len, buf, 0);
+	return hw->chip_ops->chip_memory_rw(hw, MEMWIN_CSIOSTOR, mtype,
+					    addr, len, buf, 0);
 }
 
 /*
  * EEPROM reads take a few tens of us while writes can take a bit over 5 ms.
  */
-#define EEPROM_MAX_RD_POLL 40
-#define EEPROM_MAX_WR_POLL 6
-#define EEPROM_STAT_ADDR   0x7bfc
-#define VPD_BASE           0x400
-#define VPD_BASE_OLD	   0
-#define VPD_LEN            512
+#define EEPROM_MAX_RD_POLL	40
+#define EEPROM_MAX_WR_POLL	6
+#define EEPROM_STAT_ADDR	0x7bfc
+#define VPD_BASE		0x400
+#define VPD_BASE_OLD		0
+#define VPD_LEN			1024
 #define VPD_INFO_FLD_HDR_SIZE	3
 
 /*
@@ -817,23 +646,6 @@ out:
 	return 0;
 }
 
-/*
- *	csio_hw_flash_cfg_addr - return the address of the flash
- *				configuration file
- *	@hw: the HW module
- *
- *	Return the address within the flash where the Firmware Configuration
- *	File is stored.
- */
-static unsigned int
-csio_hw_flash_cfg_addr(struct csio_hw *hw)
-{
-	if (hw->params.sf_size == 0x100000)
-		return FPGA_FLASH_CFG_OFFSET;
-	else
-		return FLASH_CFG_OFFSET;
-}
-
 static void
 csio_hw_print_fw_version(struct csio_hw *hw, char *str)
 {
@@ -898,13 +710,13 @@ csio_hw_check_fw_version(struct csio_hw *hw)
 	minor = FW_HDR_FW_VER_MINOR_GET(hw->fwrev);
 	micro = FW_HDR_FW_VER_MICRO_GET(hw->fwrev);
 
-	if (major != FW_VERSION_MAJOR) {            /* major mismatch - fail */
+	if (major != FW_VERSION_MAJOR(hw)) {	/* major mismatch - fail */
 		csio_err(hw, "card FW has major version %u, driver wants %u\n",
-			 major, FW_VERSION_MAJOR);
+			 major, FW_VERSION_MAJOR(hw));
 		return -EINVAL;
 	}
 
-	if (minor == FW_VERSION_MINOR && micro == FW_VERSION_MICRO)
+	if (minor == FW_VERSION_MINOR(hw) && micro == FW_VERSION_MICRO(hw))
 		return 0;        /* perfect match */
 
 	/* Minor/micro version mismatch */
@@ -1044,7 +856,7 @@ static void
 csio_set_pcie_completion_timeout(struct csio_hw *hw, u8 range)
 {
 	uint16_t val;
-	uint32_t pcie_cap;
+	int pcie_cap;
 
 	if (!csio_pci_capability(hw->pdev, PCI_CAP_ID_EXP, &pcie_cap)) {
 		pci_read_config_word(hw->pdev,
@@ -1056,84 +868,6 @@ csio_set_pcie_completion_timeout(struct csio_hw *hw, u8 range)
 	}
 }
 
-
-/*
- * Return the specified PCI-E Configuration Space register from our Physical
- * Function.  We try first via a Firmware LDST Command since we prefer to let
- * the firmware own all of these registers, but if that fails we go for it
- * directly ourselves.
- */
-static uint32_t
-csio_read_pcie_cfg4(struct csio_hw *hw, int reg)
-{
-	u32 val = 0;
-	struct csio_mb *mbp;
-	int rv;
-	struct fw_ldst_cmd *ldst_cmd;
-
-	mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
-	if (!mbp) {
-		CSIO_INC_STATS(hw, n_err_nomem);
-		pci_read_config_dword(hw->pdev, reg, &val);
-		return val;
-	}
-
-	csio_mb_ldst(hw, mbp, CSIO_MB_DEFAULT_TMO, reg);
-
-	rv = csio_mb_issue(hw, mbp);
-
-	/*
-	 * If the LDST Command suucceeded, exctract the returned register
-	 * value.  Otherwise read it directly ourself.
-	 */
-	if (rv == 0) {
-		ldst_cmd = (struct fw_ldst_cmd *)(mbp->mb);
-		val = ntohl(ldst_cmd->u.pcie.data[0]);
-	} else
-		pci_read_config_dword(hw->pdev, reg, &val);
-
-	mempool_free(mbp, hw->mb_mempool);
-
-	return val;
-} /* csio_read_pcie_cfg4 */
-
-static int
-csio_hw_set_mem_win(struct csio_hw *hw)
-{
-	u32 bar0;
-
-	/*
-	 * Truncation intentional: we only read the bottom 32-bits of the
-	 * 64-bit BAR0/BAR1 ...  We use the hardware backdoor mechanism to
-	 * read BAR0 instead of using pci_resource_start() because we could be
-	 * operating from within a Virtual Machine which is trapping our
-	 * accesses to our Configuration Space and we need to set up the PCI-E
-	 * Memory Window decoders with the actual addresses which will be
-	 * coming across the PCI-E link.
-	 */
-	bar0 = csio_read_pcie_cfg4(hw, PCI_BASE_ADDRESS_0);
-	bar0 &= PCI_BASE_ADDRESS_MEM_MASK;
-
-	/*
-	 * Set up memory window for accessing adapter memory ranges.  (Read
-	 * back MA register to ensure that changes propagate before we attempt
-	 * to use the new values.)
-	 */
-	csio_wr_reg32(hw, (bar0 + MEMWIN0_BASE) | BIR(0) |
-		WINDOW(ilog2(MEMWIN0_APERTURE) - 10),
-		PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, 0));
-	csio_wr_reg32(hw, (bar0 + MEMWIN1_BASE) | BIR(0) |
-		WINDOW(ilog2(MEMWIN1_APERTURE) - 10),
-		PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, 1));
-	csio_wr_reg32(hw, (bar0 + MEMWIN2_BASE) | BIR(0) |
-		WINDOW(ilog2(MEMWIN2_APERTURE) - 10),
-		PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, 2));
-	csio_rd_reg32(hw, PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, 2));
-	return 0;
-} /* csio_hw_set_mem_win */
-
-
-
 /*****************************************************************************/
 /* HW State machine assists                                                  */
 /*****************************************************************************/
@@ -1234,7 +968,9 @@ retry:
 		for (;;) {
 			uint32_t pcie_fw;
 
+			spin_unlock_irq(&hw->lock);
 			msleep(50);
+			spin_lock_irq(&hw->lock);
 			waiting -= 50;
 
 			/*
@@ -2121,9 +1857,9 @@ csio_hw_flash_config(struct csio_hw *hw, u32 *fw_cfg_param, char *path)
 	uint32_t *cfg_data;
 	int value_to_add = 0;
 
-	if (request_firmware(&cf, CSIO_CF_FNAME, dev) < 0) {
-		csio_err(hw, "could not find config file " CSIO_CF_FNAME
-			 ",err: %d\n", ret);
+	if (request_firmware(&cf, CSIO_CF_FNAME(hw), dev) < 0) {
+		csio_err(hw, "could not find config file %s, err: %d\n",
+			 CSIO_CF_FNAME(hw), ret);
 		return -ENOENT;
 	}
 
@@ -2147,9 +1883,24 @@ csio_hw_flash_config(struct csio_hw *hw, u32 *fw_cfg_param, char *path)
 
 	ret = csio_memory_write(hw, mtype, maddr,
 				cf->size + value_to_add, cfg_data);
+
+	if ((ret == 0) && (value_to_add != 0)) {
+		union {
+			u32 word;
+			char buf[4];
+		} last;
+		size_t size = cf->size & ~0x3;
+		int i;
+
+		last.word = cfg_data[size >> 2];
+		for (i = value_to_add; i < 4; i++)
+			last.buf[i] = 0;
+		ret = csio_memory_write(hw, mtype, maddr + size, 4, &last.word);
+	}
 	if (ret == 0) {
-		csio_info(hw, "config file upgraded to " CSIO_CF_FNAME "\n");
-		strncpy(path, "/lib/firmware/" CSIO_CF_FNAME, 64);
+		csio_info(hw, "config file upgraded to %s\n",
+			  CSIO_CF_FNAME(hw));
+		snprintf(path, 64, "%s%s", "/lib/firmware/", CSIO_CF_FNAME(hw));
 	}
 
 leave:
@@ -2179,7 +1930,7 @@ csio_hw_use_fwconfig(struct csio_hw *hw, int reset, u32 *fw_cfg_param)
 {
 	unsigned int mtype, maddr;
 	int rv;
-	uint32_t finiver, finicsum, cfcsum;
+	uint32_t finiver = 0, finicsum = 0, cfcsum = 0;
 	int using_flash;
 	char path[64];
 
@@ -2207,7 +1958,7 @@ csio_hw_use_fwconfig(struct csio_hw *hw, int reset, u32 *fw_cfg_param)
 			 * config file from flash.
 			 */
 			mtype = FW_MEMTYPE_CF_FLASH;
-			maddr = csio_hw_flash_cfg_addr(hw);
+			maddr = hw->chip_ops->chip_flash_cfg_addr(hw);
 			using_flash = 1;
 		} else {
 			/*
@@ -2346,30 +2097,32 @@ csio_hw_flash_fw(struct csio_hw *hw)
 	struct pci_dev *pci_dev = hw->pdev;
 	struct device *dev = &pci_dev->dev ;
 
-	if (request_firmware(&fw, CSIO_FW_FNAME, dev) < 0) {
-		csio_err(hw, "could not find firmware image " CSIO_FW_FNAME
-		",err: %d\n", ret);
+	if (request_firmware(&fw, CSIO_FW_FNAME(hw), dev) < 0) {
+		csio_err(hw, "could not find firmware image %s, err: %d\n",
+			 CSIO_FW_FNAME(hw), ret);
 		return -EINVAL;
 	}
 
 	hdr = (const struct fw_hdr *)fw->data;
 	fw_ver = ntohl(hdr->fw_ver);
-	if (FW_HDR_FW_VER_MAJOR_GET(fw_ver) != FW_VERSION_MAJOR)
+	if (FW_HDR_FW_VER_MAJOR_GET(fw_ver) != FW_VERSION_MAJOR(hw))
 		return -EINVAL;      /* wrong major version, won't do */
 
 	/*
 	 * If the flash FW is unusable or we found something newer, load it.
 	 */
-	if (FW_HDR_FW_VER_MAJOR_GET(hw->fwrev) != FW_VERSION_MAJOR ||
+	if (FW_HDR_FW_VER_MAJOR_GET(hw->fwrev) != FW_VERSION_MAJOR(hw) ||
 	    fw_ver > hw->fwrev) {
 		ret = csio_hw_fw_upgrade(hw, hw->pfn, fw->data, fw->size,
 				    /*force=*/false);
 		if (!ret)
-			csio_info(hw, "firmware upgraded to version %pI4 from "
-				  CSIO_FW_FNAME "\n", &hdr->fw_ver);
+			csio_info(hw,
+				  "firmware upgraded to version %pI4 from %s\n",
+				  &hdr->fw_ver, CSIO_FW_FNAME(hw));
 		else
 			csio_err(hw, "firmware upgrade failed! err=%d\n", ret);
-	}
+	} else
+		ret = -EINVAL;
 
 	release_firmware(fw);
 
@@ -2410,7 +2163,7 @@ csio_hw_configure(struct csio_hw *hw)
 	/* Set pci completion timeout value to 4 seconds. */
 	csio_set_pcie_completion_timeout(hw, 0xd);
 
-	csio_hw_set_mem_win(hw);
+	hw->chip_ops->chip_set_mem_win(hw, MEMWIN_CSIOSTOR);
 
 	rv = csio_hw_get_fw_version(hw, &hw->fwrev);
 	if (rv != 0)
@@ -2478,6 +2231,8 @@ csio_hw_configure(struct csio_hw *hw)
 	} else {
 		if (hw->fw_state == CSIO_DEV_STATE_INIT) {
 
+			hw->flags |= CSIO_HWF_USING_SOFT_PARAMS;
+
 			/* device parameters */
 			rv = csio_get_device_params(hw);
 			if (rv != 0)
@@ -2651,7 +2406,7 @@ csio_hw_intr_disable(struct csio_hw *hw)
 
 }
 
-static void
+void
 csio_hw_fatal_err(struct csio_hw *hw)
 {
 	csio_set_reg_field(hw, SGE_CONTROL, GLOBALENABLE, 0);
@@ -2990,14 +2745,6 @@ csio_hws_pcierr(struct csio_hw *hw, enum csio_hw_ev evt)
 /* END: HW SM                                                                */
 /*****************************************************************************/
 
-/* Slow path handlers */
-struct intr_info {
-	unsigned int mask;       /* bits to check in interrupt status */
-	const char *msg;         /* message to print or NULL */
-	short stat_idx;          /* stat counter to increment or -1 */
-	unsigned short fatal;    /* whether the condition reported is fatal */
-};
-
 /*
  *	csio_handle_intr_status - table driven interrupt handler
  *	@hw: HW instance
@@ -3011,7 +2758,7 @@ struct intr_info {
  *	by an entry specifying mask 0.  Returns the number of fatal interrupt
  *	conditions.
  */
-static int
+int
 csio_handle_intr_status(struct csio_hw *hw, unsigned int reg,
 				 const struct intr_info *acts)
 {
@@ -3038,80 +2785,6 @@ csio_handle_intr_status(struct csio_hw *hw, unsigned int reg,
 }
 
 /*
- * Interrupt handler for the PCIE module.
- */
-static void
-csio_pcie_intr_handler(struct csio_hw *hw)
-{
-	static struct intr_info sysbus_intr_info[] = {
-		{ RNPP, "RXNP array parity error", -1, 1 },
-		{ RPCP, "RXPC array parity error", -1, 1 },
-		{ RCIP, "RXCIF array parity error", -1, 1 },
-		{ RCCP, "Rx completions control array parity error", -1, 1 },
-		{ RFTP, "RXFT array parity error", -1, 1 },
-		{ 0, NULL, 0, 0 }
-	};
-	static struct intr_info pcie_port_intr_info[] = {
-		{ TPCP, "TXPC array parity error", -1, 1 },
-		{ TNPP, "TXNP array parity error", -1, 1 },
-		{ TFTP, "TXFT array parity error", -1, 1 },
-		{ TCAP, "TXCA array parity error", -1, 1 },
-		{ TCIP, "TXCIF array parity error", -1, 1 },
-		{ RCAP, "RXCA array parity error", -1, 1 },
-		{ OTDD, "outbound request TLP discarded", -1, 1 },
-		{ RDPE, "Rx data parity error", -1, 1 },
-		{ TDUE, "Tx uncorrectable data error", -1, 1 },
-		{ 0, NULL, 0, 0 }
-	};
-	static struct intr_info pcie_intr_info[] = {
-		{ MSIADDRLPERR, "MSI AddrL parity error", -1, 1 },
-		{ MSIADDRHPERR, "MSI AddrH parity error", -1, 1 },
-		{ MSIDATAPERR, "MSI data parity error", -1, 1 },
-		{ MSIXADDRLPERR, "MSI-X AddrL parity error", -1, 1 },
-		{ MSIXADDRHPERR, "MSI-X AddrH parity error", -1, 1 },
-		{ MSIXDATAPERR, "MSI-X data parity error", -1, 1 },
-		{ MSIXDIPERR, "MSI-X DI parity error", -1, 1 },
-		{ PIOCPLPERR, "PCI PIO completion FIFO parity error", -1, 1 },
-		{ PIOREQPERR, "PCI PIO request FIFO parity error", -1, 1 },
-		{ TARTAGPERR, "PCI PCI target tag FIFO parity error", -1, 1 },
-		{ CCNTPERR, "PCI CMD channel count parity error", -1, 1 },
-		{ CREQPERR, "PCI CMD channel request parity error", -1, 1 },
-		{ CRSPPERR, "PCI CMD channel response parity error", -1, 1 },
-		{ DCNTPERR, "PCI DMA channel count parity error", -1, 1 },
-		{ DREQPERR, "PCI DMA channel request parity error", -1, 1 },
-		{ DRSPPERR, "PCI DMA channel response parity error", -1, 1 },
-		{ HCNTPERR, "PCI HMA channel count parity error", -1, 1 },
-		{ HREQPERR, "PCI HMA channel request parity error", -1, 1 },
-		{ HRSPPERR, "PCI HMA channel response parity error", -1, 1 },
-		{ CFGSNPPERR, "PCI config snoop FIFO parity error", -1, 1 },
-		{ FIDPERR, "PCI FID parity error", -1, 1 },
-		{ INTXCLRPERR, "PCI INTx clear parity error", -1, 1 },
-		{ MATAGPERR, "PCI MA tag parity error", -1, 1 },
-		{ PIOTAGPERR, "PCI PIO tag parity error", -1, 1 },
-		{ RXCPLPERR, "PCI Rx completion parity error", -1, 1 },
-		{ RXWRPERR, "PCI Rx write parity error", -1, 1 },
-		{ RPLPERR, "PCI replay buffer parity error", -1, 1 },
-		{ PCIESINT, "PCI core secondary fault", -1, 1 },
-		{ PCIEPINT, "PCI core primary fault", -1, 1 },
-		{ UNXSPLCPLERR, "PCI unexpected split completion error", -1,
-		  0 },
-		{ 0, NULL, 0, 0 }
-	};
-
-	int fat;
-
-	fat = csio_handle_intr_status(hw,
-				    PCIE_CORE_UTL_SYSTEM_BUS_AGENT_STATUS,
-				    sysbus_intr_info) +
-	      csio_handle_intr_status(hw,
-				    PCIE_CORE_UTL_PCI_EXPRESS_PORT_STATUS,
-				    pcie_port_intr_info) +
-	      csio_handle_intr_status(hw, PCIE_INT_CAUSE, pcie_intr_info);
-	if (fat)
-		csio_hw_fatal_err(hw);
-}
-
-/*
  * TP interrupt handler.
  */
 static void csio_tp_intr_handler(struct csio_hw *hw)
@@ -3517,7 +3190,7 @@ static void csio_ncsi_intr_handler(struct csio_hw *hw)
  */
 static void csio_xgmac_intr_handler(struct csio_hw *hw, int port)
 {
-	uint32_t v = csio_rd_reg32(hw, PORT_REG(port, XGMAC_PORT_INT_CAUSE));
+	uint32_t v = csio_rd_reg32(hw, CSIO_MAC_INT_CAUSE_REG(hw, port));
 
 	v &= TXFIFO_PRTY_ERR | RXFIFO_PRTY_ERR;
 	if (!v)
@@ -3527,7 +3200,7 @@ static void csio_xgmac_intr_handler(struct csio_hw *hw, int port)
 		csio_fatal(hw, "XGMAC %d Tx FIFO parity error\n", port);
 	if (v & RXFIFO_PRTY_ERR)
 		csio_fatal(hw, "XGMAC %d Rx FIFO parity error\n", port);
-	csio_wr_reg32(hw, v, PORT_REG(port, XGMAC_PORT_INT_CAUSE));
+	csio_wr_reg32(hw, v, CSIO_MAC_INT_CAUSE_REG(hw, port));
 	csio_hw_fatal_err(hw);
 }
 
@@ -3596,7 +3269,7 @@ csio_hw_slow_intr_handler(struct csio_hw *hw)
 		csio_xgmac_intr_handler(hw, 3);
 
 	if (cause & PCIE)
-		csio_pcie_intr_handler(hw);
+		hw->chip_ops->chip_pcie_intr_handler(hw);
 
 	if (cause & MC)
 		csio_mem_intr_handler(hw, MEM_MC);
@@ -4262,6 +3935,7 @@ csio_hw_get_device_id(struct csio_hw *hw)
 			     &hw->params.pci.device_id);
 
 	csio_dev_id_cached(hw);
+	hw->chip_id = (hw->params.pci.device_id & CSIO_HW_CHIP_MASK);
 
 } /* csio_hw_get_device_id */
 
@@ -4280,19 +3954,21 @@ csio_hw_set_description(struct csio_hw *hw, uint16_t ven_id, uint16_t dev_id)
 		prot_type = (dev_id & CSIO_ASIC_DEVID_PROTO_MASK);
 		adap_type = (dev_id & CSIO_ASIC_DEVID_TYPE_MASK);
 
-		if (prot_type == CSIO_FPGA) {
+		if (prot_type == CSIO_T4_FCOE_ASIC) {
+			memcpy(hw->hw_ver,
+			       csio_t4_fcoe_adapters[adap_type].model_no, 16);
 			memcpy(hw->model_desc,
-				csio_fcoe_adapters[13].description, 32);
-		} else if (prot_type == CSIO_T4_FCOE_ASIC) {
+			       csio_t4_fcoe_adapters[adap_type].description,
+			       32);
+		} else if (prot_type == CSIO_T5_FCOE_ASIC) {
 			memcpy(hw->hw_ver,
-			       csio_fcoe_adapters[adap_type].model_no, 16);
+			       csio_t5_fcoe_adapters[adap_type].model_no, 16);
 			memcpy(hw->model_desc,
-				csio_fcoe_adapters[adap_type].description, 32);
+			       csio_t5_fcoe_adapters[adap_type].description,
+			       32);
 		} else {
 			char tempName[32] = "Chelsio FCoE Controller";
 			memcpy(hw->model_desc, tempName, 32);
-
-			CSIO_DB_ASSERT(0);
 		}
 	}
 } /* csio_hw_set_description */
@@ -4321,6 +3997,9 @@ csio_hw_init(struct csio_hw *hw)
 
 	strcpy(hw->name, CSIO_HW_NAME);
 
+	/* Initialize the HW chip ops with T4/T5 specific ops */
+	hw->chip_ops = csio_is_t4(hw->chip_id) ? &t4_ops : &t5_ops;
+
 	/* Set the model & its description */
 
 	ven_id = hw->params.pci.vendor_id;
diff --git a/drivers/scsi/csiostor/csio_hw.h b/drivers/scsi/csiostor/csio_hw.h
index 9edcca4..489fc09 100644
--- a/drivers/scsi/csiostor/csio_hw.h
+++ b/drivers/scsi/csiostor/csio_hw.h
@@ -48,6 +48,7 @@
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_transport_fc.h>
 
+#include "csio_hw_chip.h"
 #include "csio_wr.h"
 #include "csio_mb.h"
 #include "csio_scsi.h"
@@ -60,13 +61,6 @@
  */
 #define	FW_HOSTERROR			255
 
-#define CSIO_FW_FNAME		"cxgb4/t4fw.bin"
-#define CSIO_CF_FNAME		"cxgb4/t4-config.txt"
-
-#define FW_VERSION_MAJOR	1
-#define FW_VERSION_MINOR	2
-#define FW_VERSION_MICRO	8
-
 #define CSIO_HW_NAME		"Chelsio FCoE Adapter"
 #define CSIO_MAX_PFN		8
 #define CSIO_MAX_PPORTS		4
@@ -123,8 +117,6 @@ extern int csio_msi;
 #define CSIO_VENDOR_ID				0x1425
 #define CSIO_ASIC_DEVID_PROTO_MASK		0xFF00
 #define CSIO_ASIC_DEVID_TYPE_MASK		0x00FF
-#define CSIO_FPGA				0xA000
-#define CSIO_T4_FCOE_ASIC			0x4600
 
 #define CSIO_GLBL_INTR_MASK		(CIM | MPS | PL | PCIE | MC | EDC0 | \
 					 EDC1 | LE | TP | MA | PM_TX | PM_RX | \
@@ -207,17 +199,6 @@ enum {
 	SF_SIZE = SF_SEC_SIZE * 16,   /* serial flash size */
 };
 
-enum { MEM_EDC0, MEM_EDC1, MEM_MC };
-
-enum {
-	MEMWIN0_APERTURE = 2048,
-	MEMWIN0_BASE     = 0x1b800,
-	MEMWIN1_APERTURE = 32768,
-	MEMWIN1_BASE     = 0x28000,
-	MEMWIN2_APERTURE = 65536,
-	MEMWIN2_BASE     = 0x30000,
-};
-
 /* serial flash and firmware constants */
 enum {
 	SF_ATTEMPTS = 10,             /* max retries for SF operations */
@@ -239,9 +220,6 @@ enum {
 	FLASH_CFG_MAX_SIZE    = 0x10000 , /* max size of the flash config file*/
 	FLASH_CFG_OFFSET      = 0x1f0000,
 	FLASH_CFG_START_SEC   = FLASH_CFG_OFFSET / SF_SEC_SIZE,
-	FPGA_FLASH_CFG_OFFSET = 0xf0000 , /* if FPGA mode, then cfg file is
-					   * at 1MB - 64KB */
-	FPGA_FLASH_CFG_START_SEC  = FPGA_FLASH_CFG_OFFSET / SF_SEC_SIZE,
 };
 
 /*
@@ -259,6 +237,8 @@ enum {
 	FLASH_FW_START = FLASH_START(FLASH_FW_START_SEC),
 	FLASH_FW_MAX_SIZE = FLASH_MAX_SIZE(FLASH_FW_NSECS),
 
+	/* Location of Firmware Configuration File in FLASH. */
+	FLASH_CFG_START = FLASH_START(FLASH_CFG_START_SEC),
 };
 
 #undef FLASH_START
@@ -310,7 +290,7 @@ struct csio_adap_desc {
 struct pci_params {
 	uint16_t   vendor_id;
 	uint16_t   device_id;
-	uint32_t   vpd_cap_addr;
+	int        vpd_cap_addr;
 	uint16_t   speed;
 	uint8_t    width;
 };
@@ -513,6 +493,7 @@ struct csio_hw {
 	uint32_t		fwrev;
 	uint32_t		tp_vers;
 	char			chip_ver;
+	uint16_t		chip_id;		/* Tells T4/T5 chip */
 	uint32_t		cfg_finiver;
 	uint32_t		cfg_finicsum;
 	uint32_t		cfg_cfcsum;
@@ -556,6 +537,9 @@ struct csio_hw {
 							 */
 
 	struct csio_fcoe_res_info  fres_info;		/* Fcoe resource info */
+	struct csio_hw_chip_ops	*chip_ops;		/* T4/T5 Chip specific
+							 * Operations
+							 */
 
 	/* MSIX vectors */
 	struct csio_msix_entries msix_entries[CSIO_MAX_MSIX_VECS];
@@ -636,9 +620,16 @@ csio_us_to_core_ticks(struct csio_hw *hw, uint32_t us)
 #define csio_dbg(__hw, __fmt, ...)
 #endif
 
+int csio_hw_wait_op_done_val(struct csio_hw *, int, uint32_t, int,
+			     int, int, uint32_t *);
+void csio_hw_tp_wr_bits_indirect(struct csio_hw *, unsigned int,
+				 unsigned int, unsigned int);
 int csio_mgmt_req_lookup(struct csio_mgmtm *, struct csio_ioreq *);
 void csio_hw_intr_disable(struct csio_hw *);
-int csio_hw_slow_intr_handler(struct csio_hw *hw);
+int csio_hw_slow_intr_handler(struct csio_hw *);
+int csio_handle_intr_status(struct csio_hw *, unsigned int,
+			    const struct intr_info *);
+
 int csio_hw_start(struct csio_hw *);
 int csio_hw_stop(struct csio_hw *);
 int csio_hw_reset(struct csio_hw *);
@@ -647,19 +638,17 @@ int csio_is_hw_removing(struct csio_hw *);
 
 int csio_fwevtq_handler(struct csio_hw *);
 void csio_evtq_worker(struct work_struct *);
-int csio_enqueue_evt(struct csio_hw *hw, enum csio_evt type,
-				void *evt_msg, uint16_t len);
+int csio_enqueue_evt(struct csio_hw *, enum csio_evt, void *, uint16_t);
 void csio_evtq_flush(struct csio_hw *hw);
 
 int csio_request_irqs(struct csio_hw *);
 void csio_intr_enable(struct csio_hw *);
 void csio_intr_disable(struct csio_hw *, bool);
+void csio_hw_fatal_err(struct csio_hw *);
 
 struct csio_lnode *csio_lnode_alloc(struct csio_hw *);
 int csio_config_queues(struct csio_hw *);
 
-int csio_hw_mc_read(struct csio_hw *, uint32_t, __be32 *, uint64_t *);
-int csio_hw_edc_read(struct csio_hw *, int, uint32_t, __be32 *, uint64_t *);
 int csio_hw_init(struct csio_hw *);
 void csio_hw_exit(struct csio_hw *);
 #endif /* ifndef __CSIO_HW_H__ */
diff --git a/drivers/scsi/csiostor/csio_hw_chip.h b/drivers/scsi/csiostor/csio_hw_chip.h
new file mode 100644
index 0000000..bca0de6
--- /dev/null
+++ b/drivers/scsi/csiostor/csio_hw_chip.h
@@ -0,0 +1,175 @@
+/*
+ * This file is part of the Chelsio FCoE driver for Linux.
+ *
+ * Copyright (c) 2008-2013 Chelsio Communications, 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
+ * 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.
+ */
+
+#ifndef __CSIO_HW_CHIP_H__
+#define __CSIO_HW_CHIP_H__
+
+#include "csio_defs.h"
+
+/* FCoE device IDs for T4 */
+#define CSIO_DEVID_T440DBG_FCOE			0x4600
+#define CSIO_DEVID_T420CR_FCOE			0x4601
+#define CSIO_DEVID_T422CR_FCOE			0x4602
+#define CSIO_DEVID_T440CR_FCOE			0x4603
+#define CSIO_DEVID_T420BCH_FCOE			0x4604
+#define CSIO_DEVID_T440BCH_FCOE			0x4605
+#define CSIO_DEVID_T440CH_FCOE			0x4606
+#define CSIO_DEVID_T420SO_FCOE			0x4607
+#define CSIO_DEVID_T420CX_FCOE			0x4608
+#define CSIO_DEVID_T420BT_FCOE			0x4609
+#define CSIO_DEVID_T404BT_FCOE			0x460A
+#define CSIO_DEVID_B420_FCOE			0x460B
+#define CSIO_DEVID_B404_FCOE			0x460C
+#define CSIO_DEVID_T480CR_FCOE			0x460D
+#define CSIO_DEVID_T440LPCR_FCOE		0x460E
+#define CSIO_DEVID_AMSTERDAM_T4_FCOE		0x460F
+#define CSIO_DEVID_HUAWEI_T480_FCOE		0x4680
+#define CSIO_DEVID_HUAWEI_T440_FCOE		0x4681
+#define CSIO_DEVID_HUAWEI_STG310_FCOE		0x4682
+#define CSIO_DEVID_ACROMAG_XMC_XAUI		0x4683
+#define CSIO_DEVID_ACROMAG_XMC_SFP_FCOE		0x4684
+#define CSIO_DEVID_QUANTA_MEZZ_SFP_FCOE		0x4685
+#define CSIO_DEVID_HUAWEI_10GT_FCOE		0x4686
+#define CSIO_DEVID_HUAWEI_T440_TOE_FCOE		0x4687
+
+/* FCoE device IDs for T5 */
+#define CSIO_DEVID_T580DBG_FCOE			0x5600
+#define CSIO_DEVID_T520CR_FCOE			0x5601
+#define CSIO_DEVID_T522CR_FCOE			0x5602
+#define CSIO_DEVID_T540CR_FCOE			0x5603
+#define CSIO_DEVID_T520BCH_FCOE			0x5604
+#define CSIO_DEVID_T540BCH_FCOE			0x5605
+#define CSIO_DEVID_T540CH_FCOE			0x5606
+#define CSIO_DEVID_T520SO_FCOE			0x5607
+#define CSIO_DEVID_T520CX_FCOE			0x5608
+#define CSIO_DEVID_T520BT_FCOE			0x5609
+#define CSIO_DEVID_T504BT_FCOE			0x560A
+#define CSIO_DEVID_B520_FCOE			0x560B
+#define CSIO_DEVID_B504_FCOE			0x560C
+#define CSIO_DEVID_T580CR2_FCOE			0x560D
+#define CSIO_DEVID_T540LPCR_FCOE		0x560E
+#define CSIO_DEVID_AMSTERDAM_T5_FCOE		0x560F
+#define CSIO_DEVID_T580LPCR_FCOE		0x5610
+#define CSIO_DEVID_T520LLCR_FCOE		0x5611
+#define CSIO_DEVID_T560CR_FCOE			0x5612
+#define CSIO_DEVID_T580CR_FCOE			0x5613
+
+/* Define MACRO values */
+#define CSIO_HW_T4				0x4000
+#define CSIO_T4_FCOE_ASIC			0x4600
+#define CSIO_HW_T5				0x5000
+#define CSIO_T5_FCOE_ASIC			0x5600
+#define CSIO_HW_CHIP_MASK			0xF000
+#define T4_REGMAP_SIZE				(160 * 1024)
+#define T5_REGMAP_SIZE				(332 * 1024)
+#define FW_FNAME_T4				"cxgb4/t4fw.bin"
+#define FW_FNAME_T5				"cxgb4/t5fw.bin"
+#define FW_CFG_NAME_T4				"cxgb4/t4-config.txt"
+#define FW_CFG_NAME_T5				"cxgb4/t5-config.txt"
+
+/* Define static functions */
+static inline int csio_is_t4(uint16_t chip)
+{
+	return (chip == CSIO_HW_T4);
+}
+
+static inline int csio_is_t5(uint16_t chip)
+{
+	return (chip == CSIO_HW_T5);
+}
+
+/* Define MACRO DEFINITIONS */
+#define CSIO_DEVICE(devid, idx)						\
+	{ PCI_VENDOR_ID_CHELSIO, (devid), PCI_ANY_ID, PCI_ANY_ID, 0, 0, (idx) }
+
+#define CSIO_HW_PIDX(hw, index)						\
+	(csio_is_t4(hw->chip_id) ? (PIDX(index)) :			\
+					(PIDX_T5(index) | DBTYPE(1U)))
+
+#define CSIO_HW_LP_INT_THRESH(hw, val)					\
+	(csio_is_t4(hw->chip_id) ? (LP_INT_THRESH(val)) :		\
+					(V_LP_INT_THRESH_T5(val)))
+
+#define CSIO_HW_M_LP_INT_THRESH(hw)					\
+	(csio_is_t4(hw->chip_id) ? (LP_INT_THRESH_MASK) : (M_LP_INT_THRESH_T5))
+
+#define CSIO_MAC_INT_CAUSE_REG(hw, port)				\
+	(csio_is_t4(hw->chip_id) ? (PORT_REG(port, XGMAC_PORT_INT_CAUSE)) : \
+				(T5_PORT_REG(port, MAC_PORT_INT_CAUSE)))
+
+#define FW_VERSION_MAJOR(hw) (csio_is_t4(hw->chip_id) ? 1 : 0)
+#define FW_VERSION_MINOR(hw) (csio_is_t4(hw->chip_id) ? 2 : 0)
+#define FW_VERSION_MICRO(hw) (csio_is_t4(hw->chip_id) ? 8 : 0)
+
+#define CSIO_FW_FNAME(hw)						\
+	(csio_is_t4(hw->chip_id) ? FW_FNAME_T4 : FW_FNAME_T5)
+
+#define CSIO_CF_FNAME(hw)						\
+	(csio_is_t4(hw->chip_id) ? FW_CFG_NAME_T4 : FW_CFG_NAME_T5)
+
+/* Declare ENUMS */
+enum { MEM_EDC0, MEM_EDC1, MEM_MC, MEM_MC0 = MEM_MC, MEM_MC1 };
+
+enum {
+	MEMWIN_APERTURE = 2048,
+	MEMWIN_BASE     = 0x1b800,
+	MEMWIN_CSIOSTOR = 6,		/* PCI-e Memory Window access */
+};
+
+/* Slow path handlers */
+struct intr_info {
+	unsigned int mask;       /* bits to check in interrupt status */
+	const char *msg;         /* message to print or NULL */
+	short stat_idx;          /* stat counter to increment or -1 */
+	unsigned short fatal;    /* whether the condition reported is fatal */
+};
+
+/* T4/T5 Chip specific ops */
+struct csio_hw;
+struct csio_hw_chip_ops {
+	int (*chip_set_mem_win)(struct csio_hw *, uint32_t);
+	void (*chip_pcie_intr_handler)(struct csio_hw *);
+	uint32_t (*chip_flash_cfg_addr)(struct csio_hw *);
+	int (*chip_mc_read)(struct csio_hw *, int, uint32_t,
+					__be32 *, uint64_t *);
+	int (*chip_edc_read)(struct csio_hw *, int, uint32_t,
+					__be32 *, uint64_t *);
+	int (*chip_memory_rw)(struct csio_hw *, u32, int, u32,
+					u32, uint32_t *, int);
+	void (*chip_dfs_create_ext_mem)(struct csio_hw *);
+};
+
+extern struct csio_hw_chip_ops t4_ops;
+extern struct csio_hw_chip_ops t5_ops;
+
+#endif /* #ifndef __CSIO_HW_CHIP_H__ */
diff --git a/drivers/scsi/csiostor/csio_hw_t4.c b/drivers/scsi/csiostor/csio_hw_t4.c
new file mode 100644
index 0000000..89ecbac
--- /dev/null
+++ b/drivers/scsi/csiostor/csio_hw_t4.c
@@ -0,0 +1,403 @@
+/*
+ * This file is part of the Chelsio FCoE driver for Linux.
+ *
+ * Copyright (c) 2008-2013 Chelsio Communications, 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
+ * 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
+ *      - 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.
+ */
+
+#include "csio_hw.h"
+#include "csio_init.h"
+
+/*
+ * Return the specified PCI-E Configuration Space register from our Physical
+ * Function.  We try first via a Firmware LDST Command since we prefer to let
+ * the firmware own all of these registers, but if that fails we go for it
+ * directly ourselves.
+ */
+static uint32_t
+csio_t4_read_pcie_cfg4(struct csio_hw *hw, int reg)
+{
+	u32 val = 0;
+	struct csio_mb *mbp;
+	int rv;
+	struct fw_ldst_cmd *ldst_cmd;
+
+	mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
+	if (!mbp) {
+		CSIO_INC_STATS(hw, n_err_nomem);
+		pci_read_config_dword(hw->pdev, reg, &val);
+		return val;
+	}
+
+	csio_mb_ldst(hw, mbp, CSIO_MB_DEFAULT_TMO, reg);
+	rv = csio_mb_issue(hw, mbp);
+
+	/*
+	 * If the LDST Command suucceeded, exctract the returned register
+	 * value.  Otherwise read it directly ourself.
+	 */
+	if (rv == 0) {
+		ldst_cmd = (struct fw_ldst_cmd *)(mbp->mb);
+		val = ntohl(ldst_cmd->u.pcie.data[0]);
+	} else
+		pci_read_config_dword(hw->pdev, reg, &val);
+
+	mempool_free(mbp, hw->mb_mempool);
+
+	return val;
+}
+
+static int
+csio_t4_set_mem_win(struct csio_hw *hw, uint32_t win)
+{
+	u32 bar0;
+	u32 mem_win_base;
+
+	/*
+	 * Truncation intentional: we only read the bottom 32-bits of the
+	 * 64-bit BAR0/BAR1 ...  We use the hardware backdoor mechanism to
+	 * read BAR0 instead of using pci_resource_start() because we could be
+	 * operating from within a Virtual Machine which is trapping our
+	 * accesses to our Configuration Space and we need to set up the PCI-E
+	 * Memory Window decoders with the actual addresses which will be
+	 * coming across the PCI-E link.
+	 */
+	bar0 = csio_t4_read_pcie_cfg4(hw, PCI_BASE_ADDRESS_0);
+	bar0 &= PCI_BASE_ADDRESS_MEM_MASK;
+
+	mem_win_base = bar0 + MEMWIN_BASE;
+
+	/*
+	 * Set up memory window for accessing adapter memory ranges.  (Read
+	 * back MA register to ensure that changes propagate before we attempt
+	 * to use the new values.)
+	 */
+	csio_wr_reg32(hw, mem_win_base | BIR(0) |
+			  WINDOW(ilog2(MEMWIN_APERTURE) - 10),
+			  PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, win));
+	csio_rd_reg32(hw,
+		      PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, win));
+	return 0;
+}
+
+/*
+ * Interrupt handler for the PCIE module.
+ */
+static void
+csio_t4_pcie_intr_handler(struct csio_hw *hw)
+{
+	static struct intr_info sysbus_intr_info[] = {
+		{ RNPP, "RXNP array parity error", -1, 1 },
+		{ RPCP, "RXPC array parity error", -1, 1 },
+		{ RCIP, "RXCIF array parity error", -1, 1 },
+		{ RCCP, "Rx completions control array parity error", -1, 1 },
+		{ RFTP, "RXFT array parity error", -1, 1 },
+		{ 0, NULL, 0, 0 }
+	};
+	static struct intr_info pcie_port_intr_info[] = {
+		{ TPCP, "TXPC array parity error", -1, 1 },
+		{ TNPP, "TXNP array parity error", -1, 1 },
+		{ TFTP, "TXFT array parity error", -1, 1 },
+		{ TCAP, "TXCA array parity error", -1, 1 },
+		{ TCIP, "TXCIF array parity error", -1, 1 },
+		{ RCAP, "RXCA array parity error", -1, 1 },
+		{ OTDD, "outbound request TLP discarded", -1, 1 },
+		{ RDPE, "Rx data parity error", -1, 1 },
+		{ TDUE, "Tx uncorrectable data error", -1, 1 },
+		{ 0, NULL, 0, 0 }
+	};
+
+	static struct intr_info pcie_intr_info[] = {
+		{ MSIADDRLPERR, "MSI AddrL parity error", -1, 1 },
+		{ MSIADDRHPERR, "MSI AddrH parity error", -1, 1 },
+		{ MSIDATAPERR, "MSI data parity error", -1, 1 },
+		{ MSIXADDRLPERR, "MSI-X AddrL parity error", -1, 1 },
+		{ MSIXADDRHPERR, "MSI-X AddrH parity error", -1, 1 },
+		{ MSIXDATAPERR, "MSI-X data parity error", -1, 1 },
+		{ MSIXDIPERR, "MSI-X DI parity error", -1, 1 },
+		{ PIOCPLPERR, "PCI PIO completion FIFO parity error", -1, 1 },
+		{ PIOREQPERR, "PCI PIO request FIFO parity error", -1, 1 },
+		{ TARTAGPERR, "PCI PCI target tag FIFO parity error", -1, 1 },
+		{ CCNTPERR, "PCI CMD channel count parity error", -1, 1 },
+		{ CREQPERR, "PCI CMD channel request parity error", -1, 1 },
+		{ CRSPPERR, "PCI CMD channel response parity error", -1, 1 },
+		{ DCNTPERR, "PCI DMA channel count parity error", -1, 1 },
+		{ DREQPERR, "PCI DMA channel request parity error", -1, 1 },
+		{ DRSPPERR, "PCI DMA channel response parity error", -1, 1 },
+		{ HCNTPERR, "PCI HMA channel count parity error", -1, 1 },
+		{ HREQPERR, "PCI HMA channel request parity error", -1, 1 },
+		{ HRSPPERR, "PCI HMA channel response parity error", -1, 1 },
+		{ CFGSNPPERR, "PCI config snoop FIFO parity error", -1, 1 },
+		{ FIDPERR, "PCI FID parity error", -1, 1 },
+		{ INTXCLRPERR, "PCI INTx clear parity error", -1, 1 },
+		{ MATAGPERR, "PCI MA tag parity error", -1, 1 },
+		{ PIOTAGPERR, "PCI PIO tag parity error", -1, 1 },
+		{ RXCPLPERR, "PCI Rx completion parity error", -1, 1 },
+		{ RXWRPERR, "PCI Rx write parity error", -1, 1 },
+		{ RPLPERR, "PCI replay buffer parity error", -1, 1 },
+		{ PCIESINT, "PCI core secondary fault", -1, 1 },
+		{ PCIEPINT, "PCI core primary fault", -1, 1 },
+		{ UNXSPLCPLERR, "PCI unexpected split completion error", -1,
+		  0 },
+		{ 0, NULL, 0, 0 }
+	};
+
+	int fat;
+	fat = csio_handle_intr_status(hw,
+				      PCIE_CORE_UTL_SYSTEM_BUS_AGENT_STATUS,
+				      sysbus_intr_info) +
+	      csio_handle_intr_status(hw,
+				      PCIE_CORE_UTL_PCI_EXPRESS_PORT_STATUS,
+				      pcie_port_intr_info) +
+	      csio_handle_intr_status(hw, PCIE_INT_CAUSE, pcie_intr_info);
+	if (fat)
+		csio_hw_fatal_err(hw);
+}
+
+/*
+ * csio_t4_flash_cfg_addr - return the address of the flash configuration file
+ * @hw: the HW module
+ *
+ * Return the address within the flash where the Firmware Configuration
+ * File is stored.
+ */
+static unsigned int
+csio_t4_flash_cfg_addr(struct csio_hw *hw)
+{
+	return FLASH_CFG_OFFSET;
+}
+
+/*
+ *      csio_t4_mc_read - read from MC through backdoor accesses
+ *      @hw: the hw module
+ *      @idx: not used for T4 adapter
+ *      @addr: address of first byte requested
+ *      @data: 64 bytes of data containing the requested address
+ *      @ecc: where to store the corresponding 64-bit ECC word
+ *
+ *      Read 64 bytes of data from MC starting at a 64-byte-aligned address
+ *      that covers the requested address @addr.  If @parity is not %NULL it
+ *      is assigned the 64-bit ECC word for the read data.
+ */
+static int
+csio_t4_mc_read(struct csio_hw *hw, int idx, uint32_t addr, __be32 *data,
+		uint64_t *ecc)
+{
+	int i;
+
+	if (csio_rd_reg32(hw, MC_BIST_CMD) & START_BIST)
+		return -EBUSY;
+	csio_wr_reg32(hw, addr & ~0x3fU, MC_BIST_CMD_ADDR);
+	csio_wr_reg32(hw, 64, MC_BIST_CMD_LEN);
+	csio_wr_reg32(hw, 0xc, MC_BIST_DATA_PATTERN);
+	csio_wr_reg32(hw, BIST_OPCODE(1) | START_BIST | BIST_CMD_GAP(1),
+		      MC_BIST_CMD);
+	i = csio_hw_wait_op_done_val(hw, MC_BIST_CMD, START_BIST,
+				     0, 10, 1, NULL);
+	if (i)
+		return i;
+
+#define MC_DATA(i) MC_BIST_STATUS_REG(MC_BIST_STATUS_RDATA, i)
+
+	for (i = 15; i >= 0; i--)
+		*data++ = htonl(csio_rd_reg32(hw, MC_DATA(i)));
+	if (ecc)
+		*ecc = csio_rd_reg64(hw, MC_DATA(16));
+#undef MC_DATA
+	return 0;
+}
+
+/*
+ *      csio_t4_edc_read - read from EDC through backdoor accesses
+ *      @hw: the hw module
+ *      @idx: which EDC to access
+ *      @addr: address of first byte requested
+ *      @data: 64 bytes of data containing the requested address
+ *      @ecc: where to store the corresponding 64-bit ECC word
+ *
+ *      Read 64 bytes of data from EDC starting at a 64-byte-aligned address
+ *      that covers the requested address @addr.  If @parity is not %NULL it
+ *      is assigned the 64-bit ECC word for the read data.
+ */
+static int
+csio_t4_edc_read(struct csio_hw *hw, int idx, uint32_t addr, __be32 *data,
+		uint64_t *ecc)
+{
+	int i;
+
+	idx *= EDC_STRIDE;
+	if (csio_rd_reg32(hw, EDC_BIST_CMD + idx) & START_BIST)
+		return -EBUSY;
+	csio_wr_reg32(hw, addr & ~0x3fU, EDC_BIST_CMD_ADDR + idx);
+	csio_wr_reg32(hw, 64, EDC_BIST_CMD_LEN + idx);
+	csio_wr_reg32(hw, 0xc, EDC_BIST_DATA_PATTERN + idx);
+	csio_wr_reg32(hw, BIST_OPCODE(1) | BIST_CMD_GAP(1) | START_BIST,
+		      EDC_BIST_CMD + idx);
+	i = csio_hw_wait_op_done_val(hw, EDC_BIST_CMD + idx, START_BIST,
+				     0, 10, 1, NULL);
+	if (i)
+		return i;
+
+#define EDC_DATA(i) (EDC_BIST_STATUS_REG(EDC_BIST_STATUS_RDATA, i) + idx)
+
+	for (i = 15; i >= 0; i--)
+		*data++ = htonl(csio_rd_reg32(hw, EDC_DATA(i)));
+	if (ecc)
+		*ecc = csio_rd_reg64(hw, EDC_DATA(16));
+#undef EDC_DATA
+	return 0;
+}
+
+/*
+ * csio_t4_memory_rw - read/write EDC 0, EDC 1 or MC via PCIE memory window
+ * @hw: the csio_hw
+ * @win: PCI-E memory Window to use
+ * @mtype: memory type: MEM_EDC0, MEM_EDC1, MEM_MC0 (or MEM_MC) or MEM_MC1
+ * @addr: address within indicated memory type
+ * @len: amount of memory to transfer
+ * @buf: host memory buffer
+ * @dir: direction of transfer 1 => read, 0 => write
+ *
+ * Reads/writes an [almost] arbitrary memory region in the firmware: the
+ * firmware memory address, length and host buffer must be aligned on
+ * 32-bit boudaries.  The memory is transferred as a raw byte sequence
+ * from/to the firmware's memory.  If this memory contains data
+ * structures which contain multi-byte integers, it's the callers
+ * responsibility to perform appropriate byte order conversions.
+ */
+static int
+csio_t4_memory_rw(struct csio_hw *hw, u32 win, int mtype, u32 addr,
+		u32 len, uint32_t *buf, int dir)
+{
+	u32 pos, start, offset, memoffset, bar0;
+	u32 edc_size, mc_size, mem_reg, mem_aperture, mem_base;
+
+	/*
+	 * Argument sanity checks ...
+	 */
+	if ((addr & 0x3) || (len & 0x3))
+		return -EINVAL;
+
+	/* Offset into the region of memory which is being accessed
+	 * MEM_EDC0 = 0
+	 * MEM_EDC1 = 1
+	 * MEM_MC   = 2 -- T4
+	 */
+	edc_size  = EDRAM_SIZE_GET(csio_rd_reg32(hw, MA_EDRAM0_BAR));
+	if (mtype != MEM_MC1)
+		memoffset = (mtype * (edc_size * 1024 * 1024));
+	else {
+		mc_size = EXT_MEM_SIZE_GET(csio_rd_reg32(hw,
+							 MA_EXT_MEMORY_BAR));
+		memoffset = (MEM_MC0 * edc_size + mc_size) * 1024 * 1024;
+	}
+
+	/* Determine the PCIE_MEM_ACCESS_OFFSET */
+	addr = addr + memoffset;
+
+	/*
+	 * Each PCI-E Memory Window is programmed with a window size -- or
+	 * "aperture" -- which controls the granularity of its mapping onto
+	 * adapter memory.  We need to grab that aperture in order to know
+	 * how to use the specified window.  The window is also programmed
+	 * with the base address of the Memory Window in BAR0's address
+	 * space.  For T4 this is an absolute PCI-E Bus Address.  For T5
+	 * the address is relative to BAR0.
+	 */
+	mem_reg = csio_rd_reg32(hw,
+			PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, win));
+	mem_aperture = 1 << (WINDOW(mem_reg) + 10);
+	mem_base = GET_PCIEOFST(mem_reg) << 10;
+
+	bar0 = csio_t4_read_pcie_cfg4(hw, PCI_BASE_ADDRESS_0);
+	bar0 &= PCI_BASE_ADDRESS_MEM_MASK;
+	mem_base -= bar0;
+
+	start = addr & ~(mem_aperture-1);
+	offset = addr - start;
+
+	csio_dbg(hw, "csio_t4_memory_rw: mem_reg: 0x%x, mem_aperture: 0x%x\n",
+		 mem_reg, mem_aperture);
+	csio_dbg(hw, "csio_t4_memory_rw: mem_base: 0x%x, mem_offset: 0x%x\n",
+		 mem_base, memoffset);
+	csio_dbg(hw, "csio_t4_memory_rw: bar0: 0x%x, start:0x%x, offset:0x%x\n",
+		 bar0, start, offset);
+	csio_dbg(hw, "csio_t4_memory_rw: mtype: %d, addr: 0x%x, len: %d\n",
+		 mtype, addr, len);
+
+	for (pos = start; len > 0; pos += mem_aperture, offset = 0) {
+		/*
+		 * Move PCI-E Memory Window to our current transfer
+		 * position.  Read it back to ensure that changes propagate
+		 * before we attempt to use the new value.
+		 */
+		csio_wr_reg32(hw, pos,
+			PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_OFFSET, win));
+		csio_rd_reg32(hw,
+			PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_OFFSET, win));
+
+		while (offset < mem_aperture && len > 0) {
+			if (dir)
+				*buf++ = csio_rd_reg32(hw, mem_base + offset);
+			else
+				csio_wr_reg32(hw, *buf++, mem_base + offset);
+
+			offset += sizeof(__be32);
+			len -= sizeof(__be32);
+		}
+	}
+	return 0;
+}
+
+/*
+ * csio_t4_dfs_create_ext_mem - setup debugfs for MC to read the values
+ * @hw: the csio_hw
+ *
+ * This function creates files in the debugfs with external memory region MC.
+ */
+static void
+csio_t4_dfs_create_ext_mem(struct csio_hw *hw)
+{
+	u32 size;
+	int i = csio_rd_reg32(hw, MA_TARGET_MEM_ENABLE);
+	if (i & EXT_MEM_ENABLE) {
+		size = csio_rd_reg32(hw, MA_EXT_MEMORY_BAR);
+		csio_add_debugfs_mem(hw, "mc", MEM_MC,
+				     EXT_MEM_SIZE_GET(size));
+	}
+}
+
+/* T4 adapter specific function */
+struct csio_hw_chip_ops t4_ops = {
+	.chip_set_mem_win		= csio_t4_set_mem_win,
+	.chip_pcie_intr_handler		= csio_t4_pcie_intr_handler,
+	.chip_flash_cfg_addr		= csio_t4_flash_cfg_addr,
+	.chip_mc_read			= csio_t4_mc_read,
+	.chip_edc_read			= csio_t4_edc_read,
+	.chip_memory_rw			= csio_t4_memory_rw,
+	.chip_dfs_create_ext_mem	= csio_t4_dfs_create_ext_mem,
+};
diff --git a/drivers/scsi/csiostor/csio_hw_t5.c b/drivers/scsi/csiostor/csio_hw_t5.c
new file mode 100644
index 0000000..27745c1
--- /dev/null
+++ b/drivers/scsi/csiostor/csio_hw_t5.c
@@ -0,0 +1,397 @@
+/*
+ * This file is part of the Chelsio FCoE driver for Linux.
+ *
+ * Copyright (c) 2008-2013 Chelsio Communications, 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
+ * 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.
+ */
+
+#include "csio_hw.h"
+#include "csio_init.h"
+
+static int
+csio_t5_set_mem_win(struct csio_hw *hw, uint32_t win)
+{
+	u32 mem_win_base;
+	/*
+	 * Truncation intentional: we only read the bottom 32-bits of the
+	 * 64-bit BAR0/BAR1 ...  We use the hardware backdoor mechanism to
+	 * read BAR0 instead of using pci_resource_start() because we could be
+	 * operating from within a Virtual Machine which is trapping our
+	 * accesses to our Configuration Space and we need to set up the PCI-E
+	 * Memory Window decoders with the actual addresses which will be
+	 * coming across the PCI-E link.
+	 */
+
+	/* For T5, only relative offset inside the PCIe BAR is passed */
+	mem_win_base = MEMWIN_BASE;
+
+	/*
+	 * Set up memory window for accessing adapter memory ranges.  (Read
+	 * back MA register to ensure that changes propagate before we attempt
+	 * to use the new values.)
+	 */
+	csio_wr_reg32(hw, mem_win_base | BIR(0) |
+			  WINDOW(ilog2(MEMWIN_APERTURE) - 10),
+			  PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, win));
+	csio_rd_reg32(hw,
+		      PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, win));
+
+	return 0;
+}
+
+/*
+ * Interrupt handler for the PCIE module.
+ */
+static void
+csio_t5_pcie_intr_handler(struct csio_hw *hw)
+{
+	static struct intr_info sysbus_intr_info[] = {
+		{ RNPP, "RXNP array parity error", -1, 1 },
+		{ RPCP, "RXPC array parity error", -1, 1 },
+		{ RCIP, "RXCIF array parity error", -1, 1 },
+		{ RCCP, "Rx completions control array parity error", -1, 1 },
+		{ RFTP, "RXFT array parity error", -1, 1 },
+		{ 0, NULL, 0, 0 }
+	};
+	static struct intr_info pcie_port_intr_info[] = {
+		{ TPCP, "TXPC array parity error", -1, 1 },
+		{ TNPP, "TXNP array parity error", -1, 1 },
+		{ TFTP, "TXFT array parity error", -1, 1 },
+		{ TCAP, "TXCA array parity error", -1, 1 },
+		{ TCIP, "TXCIF array parity error", -1, 1 },
+		{ RCAP, "RXCA array parity error", -1, 1 },
+		{ OTDD, "outbound request TLP discarded", -1, 1 },
+		{ RDPE, "Rx data parity error", -1, 1 },
+		{ TDUE, "Tx uncorrectable data error", -1, 1 },
+		{ 0, NULL, 0, 0 }
+	};
+
+	static struct intr_info pcie_intr_info[] = {
+		{ MSTGRPPERR, "Master Response Read Queue parity error",
+		-1, 1 },
+		{ MSTTIMEOUTPERR, "Master Timeout FIFO parity error", -1, 1 },
+		{ MSIXSTIPERR, "MSI-X STI SRAM parity error", -1, 1 },
+		{ MSIXADDRLPERR, "MSI-X AddrL parity error", -1, 1 },
+		{ MSIXADDRHPERR, "MSI-X AddrH parity error", -1, 1 },
+		{ MSIXDATAPERR, "MSI-X data parity error", -1, 1 },
+		{ MSIXDIPERR, "MSI-X DI parity error", -1, 1 },
+		{ PIOCPLGRPPERR, "PCI PIO completion Group FIFO parity error",
+		-1, 1 },
+		{ PIOREQGRPPERR, "PCI PIO request Group FIFO parity error",
+		-1, 1 },
+		{ TARTAGPERR, "PCI PCI target tag FIFO parity error", -1, 1 },
+		{ MSTTAGQPERR, "PCI master tag queue parity error", -1, 1 },
+		{ CREQPERR, "PCI CMD channel request parity error", -1, 1 },
+		{ CRSPPERR, "PCI CMD channel response parity error", -1, 1 },
+		{ DREQWRPERR, "PCI DMA channel write request parity error",
+		-1, 1 },
+		{ DREQPERR, "PCI DMA channel request parity error", -1, 1 },
+		{ DRSPPERR, "PCI DMA channel response parity error", -1, 1 },
+		{ HREQWRPERR, "PCI HMA channel count parity error", -1, 1 },
+		{ HREQPERR, "PCI HMA channel request parity error", -1, 1 },
+		{ HRSPPERR, "PCI HMA channel response parity error", -1, 1 },
+		{ CFGSNPPERR, "PCI config snoop FIFO parity error", -1, 1 },
+		{ FIDPERR, "PCI FID parity error", -1, 1 },
+		{ VFIDPERR, "PCI INTx clear parity error", -1, 1 },
+		{ MAGRPPERR, "PCI MA group FIFO parity error", -1, 1 },
+		{ PIOTAGPERR, "PCI PIO tag parity error", -1, 1 },
+		{ IPRXHDRGRPPERR, "PCI IP Rx header group parity error",
+		-1, 1 },
+		{ IPRXDATAGRPPERR, "PCI IP Rx data group parity error",
+		-1, 1 },
+		{ RPLPERR, "PCI IP replay buffer parity error", -1, 1 },
+		{ IPSOTPERR, "PCI IP SOT buffer parity error", -1, 1 },
+		{ TRGT1GRPPERR, "PCI TRGT1 group FIFOs parity error", -1, 1 },
+		{ READRSPERR, "Outbound read error", -1, 0 },
+		{ 0, NULL, 0, 0 }
+	};
+
+	int fat;
+	fat = csio_handle_intr_status(hw,
+				      PCIE_CORE_UTL_SYSTEM_BUS_AGENT_STATUS,
+				      sysbus_intr_info) +
+	      csio_handle_intr_status(hw,
+				      PCIE_CORE_UTL_PCI_EXPRESS_PORT_STATUS,
+				      pcie_port_intr_info) +
+	      csio_handle_intr_status(hw, PCIE_INT_CAUSE, pcie_intr_info);
+	if (fat)
+		csio_hw_fatal_err(hw);
+}
+
+/*
+ * csio_t5_flash_cfg_addr - return the address of the flash configuration file
+ * @hw: the HW module
+ *
+ * Return the address within the flash where the Firmware Configuration
+ * File is stored.
+ */
+static unsigned int
+csio_t5_flash_cfg_addr(struct csio_hw *hw)
+{
+	return FLASH_CFG_START;
+}
+
+/*
+ *      csio_t5_mc_read - read from MC through backdoor accesses
+ *      @hw: the hw module
+ *      @idx: index to the register
+ *      @addr: address of first byte requested
+ *      @data: 64 bytes of data containing the requested address
+ *      @ecc: where to store the corresponding 64-bit ECC word
+ *
+ *      Read 64 bytes of data from MC starting at a 64-byte-aligned address
+ *      that covers the requested address @addr.  If @parity is not %NULL it
+ *      is assigned the 64-bit ECC word for the read data.
+ */
+static int
+csio_t5_mc_read(struct csio_hw *hw, int idx, uint32_t addr, __be32 *data,
+		uint64_t *ecc)
+{
+	int i;
+	uint32_t mc_bist_cmd_reg, mc_bist_cmd_addr_reg, mc_bist_cmd_len_reg;
+	uint32_t mc_bist_status_rdata_reg, mc_bist_data_pattern_reg;
+
+	mc_bist_cmd_reg = MC_REG(MC_P_BIST_CMD, idx);
+	mc_bist_cmd_addr_reg = MC_REG(MC_P_BIST_CMD_ADDR, idx);
+	mc_bist_cmd_len_reg = MC_REG(MC_P_BIST_CMD_LEN, idx);
+	mc_bist_status_rdata_reg = MC_REG(MC_P_BIST_STATUS_RDATA, idx);
+	mc_bist_data_pattern_reg = MC_REG(MC_P_BIST_DATA_PATTERN, idx);
+
+	if (csio_rd_reg32(hw, mc_bist_cmd_reg) & START_BIST)
+		return -EBUSY;
+	csio_wr_reg32(hw, addr & ~0x3fU, mc_bist_cmd_addr_reg);
+	csio_wr_reg32(hw, 64, mc_bist_cmd_len_reg);
+	csio_wr_reg32(hw, 0xc, mc_bist_data_pattern_reg);
+	csio_wr_reg32(hw, BIST_OPCODE(1) | START_BIST |  BIST_CMD_GAP(1),
+		      mc_bist_cmd_reg);
+	i = csio_hw_wait_op_done_val(hw, mc_bist_cmd_reg, START_BIST,
+				     0, 10, 1, NULL);
+	if (i)
+		return i;
+
+#define MC_DATA(i) MC_BIST_STATUS_REG(MC_BIST_STATUS_RDATA, i)
+
+	for (i = 15; i >= 0; i--)
+		*data++ = htonl(csio_rd_reg32(hw, MC_DATA(i)));
+	if (ecc)
+		*ecc = csio_rd_reg64(hw, MC_DATA(16));
+#undef MC_DATA
+	return 0;
+}
+
+/*
+ *      csio_t5_edc_read - read from EDC through backdoor accesses
+ *      @hw: the hw module
+ *      @idx: which EDC to access
+ *      @addr: address of first byte requested
+ *      @data: 64 bytes of data containing the requested address
+ *      @ecc: where to store the corresponding 64-bit ECC word
+ *
+ *      Read 64 bytes of data from EDC starting at a 64-byte-aligned address
+ *      that covers the requested address @addr.  If @parity is not %NULL it
+ *      is assigned the 64-bit ECC word for the read data.
+ */
+static int
+csio_t5_edc_read(struct csio_hw *hw, int idx, uint32_t addr, __be32 *data,
+		uint64_t *ecc)
+{
+	int i;
+	uint32_t edc_bist_cmd_reg, edc_bist_cmd_addr_reg, edc_bist_cmd_len_reg;
+	uint32_t edc_bist_cmd_data_pattern, edc_bist_status_rdata_reg;
+
+/*
+ * These macro are missing in t4_regs.h file.
+ */
+#define EDC_STRIDE_T5 (EDC_T51_BASE_ADDR - EDC_T50_BASE_ADDR)
+#define EDC_REG_T5(reg, idx) (reg + EDC_STRIDE_T5 * idx)
+
+	edc_bist_cmd_reg = EDC_REG_T5(EDC_H_BIST_CMD, idx);
+	edc_bist_cmd_addr_reg = EDC_REG_T5(EDC_H_BIST_CMD_ADDR, idx);
+	edc_bist_cmd_len_reg = EDC_REG_T5(EDC_H_BIST_CMD_LEN, idx);
+	edc_bist_cmd_data_pattern = EDC_REG_T5(EDC_H_BIST_DATA_PATTERN, idx);
+	edc_bist_status_rdata_reg = EDC_REG_T5(EDC_H_BIST_STATUS_RDATA, idx);
+#undef EDC_REG_T5
+#undef EDC_STRIDE_T5
+
+	if (csio_rd_reg32(hw, edc_bist_cmd_reg) & START_BIST)
+		return -EBUSY;
+	csio_wr_reg32(hw, addr & ~0x3fU, edc_bist_cmd_addr_reg);
+	csio_wr_reg32(hw, 64, edc_bist_cmd_len_reg);
+	csio_wr_reg32(hw, 0xc, edc_bist_cmd_data_pattern);
+	csio_wr_reg32(hw, BIST_OPCODE(1) | START_BIST |  BIST_CMD_GAP(1),
+		      edc_bist_cmd_reg);
+	i = csio_hw_wait_op_done_val(hw, edc_bist_cmd_reg, START_BIST,
+				     0, 10, 1, NULL);
+	if (i)
+		return i;
+
+#define EDC_DATA(i) (EDC_BIST_STATUS_REG(EDC_BIST_STATUS_RDATA, i) + idx)
+
+	for (i = 15; i >= 0; i--)
+		*data++ = htonl(csio_rd_reg32(hw, EDC_DATA(i)));
+	if (ecc)
+		*ecc = csio_rd_reg64(hw, EDC_DATA(16));
+#undef EDC_DATA
+	return 0;
+}
+
+/*
+ * csio_t5_memory_rw - read/write EDC 0, EDC 1 or MC via PCIE memory window
+ * @hw: the csio_hw
+ * @win: PCI-E memory Window to use
+ * @mtype: memory type: MEM_EDC0, MEM_EDC1, MEM_MC0 (or MEM_MC) or MEM_MC1
+ * @addr: address within indicated memory type
+ * @len: amount of memory to transfer
+ * @buf: host memory buffer
+ * @dir: direction of transfer 1 => read, 0 => write
+ *
+ * Reads/writes an [almost] arbitrary memory region in the firmware: the
+ * firmware memory address, length and host buffer must be aligned on
+ * 32-bit boudaries.  The memory is transferred as a raw byte sequence
+ * from/to the firmware's memory.  If this memory contains data
+ * structures which contain multi-byte integers, it's the callers
+ * responsibility to perform appropriate byte order conversions.
+ */
+static int
+csio_t5_memory_rw(struct csio_hw *hw, u32 win, int mtype, u32 addr,
+		u32 len, uint32_t *buf, int dir)
+{
+	u32 pos, start, offset, memoffset;
+	u32 edc_size, mc_size, win_pf, mem_reg, mem_aperture, mem_base;
+
+	/*
+	 * Argument sanity checks ...
+	 */
+	if ((addr & 0x3) || (len & 0x3))
+		return -EINVAL;
+
+	/* Offset into the region of memory which is being accessed
+	 * MEM_EDC0 = 0
+	 * MEM_EDC1 = 1
+	 * MEM_MC   = 2 -- T4
+	 * MEM_MC0  = 2 -- For T5
+	 * MEM_MC1  = 3 -- For T5
+	 */
+	edc_size  = EDRAM_SIZE_GET(csio_rd_reg32(hw, MA_EDRAM0_BAR));
+	if (mtype != MEM_MC1)
+		memoffset = (mtype * (edc_size * 1024 * 1024));
+	else {
+		mc_size = EXT_MEM_SIZE_GET(csio_rd_reg32(hw,
+							 MA_EXT_MEMORY_BAR));
+		memoffset = (MEM_MC0 * edc_size + mc_size) * 1024 * 1024;
+	}
+
+	/* Determine the PCIE_MEM_ACCESS_OFFSET */
+	addr = addr + memoffset;
+
+	/*
+	 * Each PCI-E Memory Window is programmed with a window size -- or
+	 * "aperture" -- which controls the granularity of its mapping onto
+	 * adapter memory.  We need to grab that aperture in order to know
+	 * how to use the specified window.  The window is also programmed
+	 * with the base address of the Memory Window in BAR0's address
+	 * space.  For T4 this is an absolute PCI-E Bus Address.  For T5
+	 * the address is relative to BAR0.
+	 */
+	mem_reg = csio_rd_reg32(hw,
+			PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, win));
+	mem_aperture = 1 << (WINDOW(mem_reg) + 10);
+	mem_base = GET_PCIEOFST(mem_reg) << 10;
+
+	start = addr & ~(mem_aperture-1);
+	offset = addr - start;
+	win_pf = V_PFNUM(hw->pfn);
+
+	csio_dbg(hw, "csio_t5_memory_rw: mem_reg: 0x%x, mem_aperture: 0x%x\n",
+		 mem_reg, mem_aperture);
+	csio_dbg(hw, "csio_t5_memory_rw: mem_base: 0x%x, mem_offset: 0x%x\n",
+		 mem_base, memoffset);
+	csio_dbg(hw, "csio_t5_memory_rw: start:0x%x, offset:0x%x, win_pf:%d\n",
+		 start, offset, win_pf);
+	csio_dbg(hw, "csio_t5_memory_rw: mtype: %d, addr: 0x%x, len: %d\n",
+		 mtype, addr, len);
+
+	for (pos = start; len > 0; pos += mem_aperture, offset = 0) {
+		/*
+		 * Move PCI-E Memory Window to our current transfer
+		 * position.  Read it back to ensure that changes propagate
+		 * before we attempt to use the new value.
+		 */
+		csio_wr_reg32(hw, pos | win_pf,
+			PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_OFFSET, win));
+		csio_rd_reg32(hw,
+			PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_OFFSET, win));
+
+		while (offset < mem_aperture && len > 0) {
+			if (dir)
+				*buf++ = csio_rd_reg32(hw, mem_base + offset);
+			else
+				csio_wr_reg32(hw, *buf++, mem_base + offset);
+
+			offset += sizeof(__be32);
+			len -= sizeof(__be32);
+		}
+	}
+	return 0;
+}
+
+/*
+ * csio_t5_dfs_create_ext_mem - setup debugfs for MC0 or MC1 to read the values
+ * @hw: the csio_hw
+ *
+ * This function creates files in the debugfs with external memory region
+ * MC0 & MC1.
+ */
+static void
+csio_t5_dfs_create_ext_mem(struct csio_hw *hw)
+{
+	u32 size;
+	int i = csio_rd_reg32(hw, MA_TARGET_MEM_ENABLE);
+	if (i & EXT_MEM_ENABLE) {
+		size = csio_rd_reg32(hw, MA_EXT_MEMORY_BAR);
+		csio_add_debugfs_mem(hw, "mc0", MEM_MC0,
+				     EXT_MEM_SIZE_GET(size));
+	}
+	if (i & EXT_MEM1_ENABLE) {
+		size = csio_rd_reg32(hw, MA_EXT_MEMORY1_BAR);
+		csio_add_debugfs_mem(hw, "mc1", MEM_MC1,
+				     EXT_MEM_SIZE_GET(size));
+	}
+}
+
+/* T5 adapter specific function */
+struct csio_hw_chip_ops t5_ops = {
+	.chip_set_mem_win		= csio_t5_set_mem_win,
+	.chip_pcie_intr_handler		= csio_t5_pcie_intr_handler,
+	.chip_flash_cfg_addr		= csio_t5_flash_cfg_addr,
+	.chip_mc_read			= csio_t5_mc_read,
+	.chip_edc_read			= csio_t5_edc_read,
+	.chip_memory_rw			= csio_t5_memory_rw,
+	.chip_dfs_create_ext_mem	= csio_t5_dfs_create_ext_mem,
+};
diff --git a/drivers/scsi/csiostor/csio_init.c b/drivers/scsi/csiostor/csio_init.c
index 0604b5f..00346fe 100644
--- a/drivers/scsi/csiostor/csio_init.c
+++ b/drivers/scsi/csiostor/csio_init.c
@@ -81,9 +81,11 @@ csio_mem_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
 		__be32 data[16];
 
 		if (mem == MEM_MC)
-			ret = csio_hw_mc_read(hw, pos, data, NULL);
+			ret = hw->chip_ops->chip_mc_read(hw, 0, pos,
+							 data, NULL);
 		else
-			ret = csio_hw_edc_read(hw, mem, pos, data, NULL);
+			ret = hw->chip_ops->chip_edc_read(hw, mem, pos,
+							  data, NULL);
 		if (ret)
 			return ret;
 
@@ -108,7 +110,7 @@ static const struct file_operations csio_mem_debugfs_fops = {
 	.llseek  = default_llseek,
 };
 
-static void csio_add_debugfs_mem(struct csio_hw *hw, const char *name,
+void csio_add_debugfs_mem(struct csio_hw *hw, const char *name,
 				 unsigned int idx, unsigned int size_mb)
 {
 	struct dentry *de;
@@ -131,9 +133,8 @@ static int csio_setup_debugfs(struct csio_hw *hw)
 		csio_add_debugfs_mem(hw, "edc0", MEM_EDC0, 5);
 	if (i & EDRAM1_ENABLE)
 		csio_add_debugfs_mem(hw, "edc1", MEM_EDC1, 5);
-	if (i & EXT_MEM_ENABLE)
-		csio_add_debugfs_mem(hw, "mc", MEM_MC,
-		      EXT_MEM_SIZE_GET(csio_rd_reg32(hw, MA_EXT_MEMORY_BAR)));
+
+	hw->chip_ops->chip_dfs_create_ext_mem(hw);
 	return 0;
 }
 
@@ -1169,7 +1170,7 @@ static struct pci_error_handlers csio_err_handler = {
 };
 
 static DEFINE_PCI_DEVICE_TABLE(csio_pci_tbl) = {
-	CSIO_DEVICE(CSIO_DEVID_T440DBG_FCOE, 0),	/* T440DBG FCOE */
+	CSIO_DEVICE(CSIO_DEVID_T440DBG_FCOE, 0),        /* T4 DEBUG FCOE */
 	CSIO_DEVICE(CSIO_DEVID_T420CR_FCOE, 0),		/* T420CR FCOE */
 	CSIO_DEVICE(CSIO_DEVID_T422CR_FCOE, 0),		/* T422CR FCOE */
 	CSIO_DEVICE(CSIO_DEVID_T440CR_FCOE, 0),		/* T440CR FCOE */
@@ -1184,8 +1185,34 @@ static DEFINE_PCI_DEVICE_TABLE(csio_pci_tbl) = {
 	CSIO_DEVICE(CSIO_DEVID_B404_FCOE, 0),		/* B404 FCOE */
 	CSIO_DEVICE(CSIO_DEVID_T480CR_FCOE, 0),		/* T480 CR FCOE */
 	CSIO_DEVICE(CSIO_DEVID_T440LPCR_FCOE, 0),	/* T440 LP-CR FCOE */
-	CSIO_DEVICE(CSIO_DEVID_PE10K, 0),		/* PE10K FCOE */
-	CSIO_DEVICE(CSIO_DEVID_PE10K_PF1, 0),	/* PE10K FCOE on PF1 */
+	CSIO_DEVICE(CSIO_DEVID_AMSTERDAM_T4_FCOE, 0),   /* AMSTERDAM T4 FCOE */
+	CSIO_DEVICE(CSIO_DEVID_HUAWEI_T480_FCOE, 0),    /* HUAWEI T480 FCOE */
+	CSIO_DEVICE(CSIO_DEVID_HUAWEI_T440_FCOE, 0),    /* HUAWEI T440 FCOE */
+	CSIO_DEVICE(CSIO_DEVID_HUAWEI_STG310_FCOE, 0),  /* HUAWEI STG FCOE */
+	CSIO_DEVICE(CSIO_DEVID_ACROMAG_XMC_XAUI, 0),    /* ACROMAG XAUI FCOE */
+	CSIO_DEVICE(CSIO_DEVID_QUANTA_MEZZ_SFP_FCOE, 0),/* QUANTA MEZZ FCOE */
+	CSIO_DEVICE(CSIO_DEVID_HUAWEI_10GT_FCOE, 0),    /* HUAWEI 10GT FCOE */
+	CSIO_DEVICE(CSIO_DEVID_HUAWEI_T440_TOE_FCOE, 0),/* HUAWEI T4 TOE FCOE */
+	CSIO_DEVICE(CSIO_DEVID_T580DBG_FCOE, 0),        /* T5 DEBUG FCOE */
+	CSIO_DEVICE(CSIO_DEVID_T520CR_FCOE, 0),         /* T520CR FCOE */
+	CSIO_DEVICE(CSIO_DEVID_T522CR_FCOE, 0),         /* T522CR FCOE */
+	CSIO_DEVICE(CSIO_DEVID_T540CR_FCOE, 0),         /* T540CR FCOE */
+	CSIO_DEVICE(CSIO_DEVID_T520BCH_FCOE, 0),        /* T520BCH FCOE */
+	CSIO_DEVICE(CSIO_DEVID_T540BCH_FCOE, 0),        /* T540BCH FCOE */
+	CSIO_DEVICE(CSIO_DEVID_T540CH_FCOE, 0),         /* T540CH FCOE */
+	CSIO_DEVICE(CSIO_DEVID_T520SO_FCOE, 0),         /* T520SO FCOE */
+	CSIO_DEVICE(CSIO_DEVID_T520CX_FCOE, 0),         /* T520CX FCOE */
+	CSIO_DEVICE(CSIO_DEVID_T520BT_FCOE, 0),         /* T520BT FCOE */
+	CSIO_DEVICE(CSIO_DEVID_T504BT_FCOE, 0),         /* T504BT FCOE */
+	CSIO_DEVICE(CSIO_DEVID_B520_FCOE, 0),           /* B520 FCOE */
+	CSIO_DEVICE(CSIO_DEVID_B504_FCOE, 0),           /* B504 FCOE */
+	CSIO_DEVICE(CSIO_DEVID_T580CR2_FCOE, 0),	/* T580 CR FCOE */
+	CSIO_DEVICE(CSIO_DEVID_T540LPCR_FCOE, 0),       /* T540 LP-CR FCOE */
+	CSIO_DEVICE(CSIO_DEVID_AMSTERDAM_T5_FCOE, 0),   /* AMSTERDAM T5 FCOE */
+	CSIO_DEVICE(CSIO_DEVID_T580LPCR_FCOE, 0),       /* T580 LP-CR FCOE */
+	CSIO_DEVICE(CSIO_DEVID_T520LLCR_FCOE, 0),       /* T520 LL-CR FCOE */
+	CSIO_DEVICE(CSIO_DEVID_T560CR_FCOE, 0),         /* T560 CR FCOE */
+	CSIO_DEVICE(CSIO_DEVID_T580CR_FCOE, 0),         /* T580 CR FCOE */
 	{ 0, 0, 0, 0, 0, 0, 0 }
 };
 
@@ -1259,4 +1286,5 @@ MODULE_DESCRIPTION(CSIO_DRV_DESC);
 MODULE_LICENSE(CSIO_DRV_LICENSE);
 MODULE_DEVICE_TABLE(pci, csio_pci_tbl);
 MODULE_VERSION(CSIO_DRV_VERSION);
-MODULE_FIRMWARE(CSIO_FW_FNAME);
+MODULE_FIRMWARE(FW_FNAME_T4);
+MODULE_FIRMWARE(FW_FNAME_T5);
diff --git a/drivers/scsi/csiostor/csio_init.h b/drivers/scsi/csiostor/csio_init.h
index 0838fd7..5cc5d31 100644
--- a/drivers/scsi/csiostor/csio_init.h
+++ b/drivers/scsi/csiostor/csio_init.h
@@ -52,31 +52,6 @@
 #define CSIO_DRV_DESC			"Chelsio FCoE driver"
 #define CSIO_DRV_VERSION		"1.0.0"
 
-#define CSIO_DEVICE(devid, idx)					\
-{ PCI_VENDOR_ID_CHELSIO, (devid), PCI_ANY_ID, PCI_ANY_ID, 0, 0, (idx) }
-
-#define CSIO_IS_T4_FPGA(_dev)		(((_dev) == CSIO_DEVID_PE10K) ||\
-					 ((_dev) == CSIO_DEVID_PE10K_PF1))
-
-/* FCoE device IDs */
-#define CSIO_DEVID_PE10K		0xA000
-#define CSIO_DEVID_PE10K_PF1		0xA001
-#define CSIO_DEVID_T440DBG_FCOE		0x4600
-#define CSIO_DEVID_T420CR_FCOE		0x4601
-#define CSIO_DEVID_T422CR_FCOE		0x4602
-#define CSIO_DEVID_T440CR_FCOE		0x4603
-#define CSIO_DEVID_T420BCH_FCOE		0x4604
-#define CSIO_DEVID_T440BCH_FCOE		0x4605
-#define CSIO_DEVID_T440CH_FCOE		0x4606
-#define CSIO_DEVID_T420SO_FCOE		0x4607
-#define CSIO_DEVID_T420CX_FCOE		0x4608
-#define CSIO_DEVID_T420BT_FCOE		0x4609
-#define CSIO_DEVID_T404BT_FCOE		0x460A
-#define CSIO_DEVID_B420_FCOE		0x460B
-#define CSIO_DEVID_B404_FCOE		0x460C
-#define CSIO_DEVID_T480CR_FCOE		0x460D
-#define CSIO_DEVID_T440LPCR_FCOE	0x460E
-
 extern struct fc_function_template csio_fc_transport_funcs;
 extern struct fc_function_template csio_fc_transport_vport_funcs;
 
@@ -100,6 +75,10 @@ struct csio_lnode *csio_shost_init(struct csio_hw *, struct device *, bool,
 void csio_shost_exit(struct csio_lnode *);
 void csio_lnodes_exit(struct csio_hw *, bool);
 
+/* DebugFS helper routines */
+void csio_add_debugfs_mem(struct csio_hw *, const char *,
+		unsigned int, unsigned int);
+
 static inline struct Scsi_Host *
 csio_ln_to_shost(struct csio_lnode *ln)
 {
diff --git a/drivers/scsi/csiostor/csio_lnode.h b/drivers/scsi/csiostor/csio_lnode.h
index 8d84988..0f9c041 100644
--- a/drivers/scsi/csiostor/csio_lnode.h
+++ b/drivers/scsi/csiostor/csio_lnode.h
@@ -114,7 +114,7 @@ struct csio_lnode_stats {
 	uint32_t	n_rnode_match;  /* matched rnode */
 	uint32_t	n_dev_loss_tmo; /* Device loss timeout */
 	uint32_t	n_fdmi_err;	/* fdmi err */
-	uint32_t	n_evt_fw[RSCN_DEV_LOST];	/* fw events */
+	uint32_t	n_evt_fw[PROTO_ERR_IMPL_LOGO];	/* fw events */
 	enum csio_ln_ev	n_evt_sm[CSIO_LNE_MAX_EVENT];	/* State m/c events */
 	uint32_t	n_rnode_alloc;	/* rnode allocated */
 	uint32_t	n_rnode_free;	/* rnode freed */
diff --git a/drivers/scsi/csiostor/csio_rnode.c b/drivers/scsi/csiostor/csio_rnode.c
index 51c6a38..e9c3b04 100644
--- a/drivers/scsi/csiostor/csio_rnode.c
+++ b/drivers/scsi/csiostor/csio_rnode.c
@@ -302,7 +302,7 @@ csio_confirm_rnode(struct csio_lnode *ln, uint32_t rdev_flowid,
 {
 	uint8_t rport_type;
 	struct csio_rnode *rn, *match_rn;
-	uint32_t vnp_flowid;
+	uint32_t vnp_flowid = 0;
 	__be32 *port_id;
 
 	port_id = (__be32 *)&rdevp->r_id[0];
@@ -350,6 +350,14 @@ csio_confirm_rnode(struct csio_lnode *ln, uint32_t rdev_flowid,
 			 * Else, go ahead and alloc a new rnode.
 			 */
 			if (!memcmp(csio_rn_wwpn(match_rn), rdevp->wwpn, 8)) {
+				if (rn == match_rn)
+					goto found_rnode;
+				csio_ln_dbg(ln,
+					    "nport_id:x%x and wwpn:%llx"
+					    " match for ssni:x%x\n",
+					    rn->nport_id,
+					    wwn_to_u64(rdevp->wwpn),
+					    rdev_flowid);
 				if (csio_is_rnode_ready(rn)) {
 					csio_ln_warn(ln,
 						     "rnode is already"
diff --git a/drivers/scsi/csiostor/csio_rnode.h b/drivers/scsi/csiostor/csio_rnode.h
index a3b434c..6594009 100644
--- a/drivers/scsi/csiostor/csio_rnode.h
+++ b/drivers/scsi/csiostor/csio_rnode.h
@@ -63,7 +63,7 @@ struct csio_rnode_stats {
 	uint32_t	n_err_nomem;	/* error nomem */
 	uint32_t	n_evt_unexp;	/* unexpected event */
 	uint32_t	n_evt_drop;	/* unexpected event */
-	uint32_t	n_evt_fw[RSCN_DEV_LOST];	/* fw events */
+	uint32_t	n_evt_fw[PROTO_ERR_IMPL_LOGO];	/* fw events */
 	enum csio_rn_ev	n_evt_sm[CSIO_RNFE_MAX_EVENT];	/* State m/c events */
 	uint32_t	n_lun_rst;	/* Number of resets of
 					 * of LUNs under this
diff --git a/drivers/scsi/csiostor/csio_wr.c b/drivers/scsi/csiostor/csio_wr.c
index c32df1b..4255ce2 100644
--- a/drivers/scsi/csiostor/csio_wr.c
+++ b/drivers/scsi/csiostor/csio_wr.c
@@ -85,8 +85,8 @@ csio_wr_ring_fldb(struct csio_hw *hw, struct csio_q *flq)
 	 */
 	if (flq->inc_idx >= 8) {
 		csio_wr_reg32(hw, DBPRIO(1) | QID(flq->un.fl.flid) |
-			      PIDX(flq->inc_idx / 8),
-			      MYPF_REG(SGE_PF_KDOORBELL));
+				  CSIO_HW_PIDX(hw, flq->inc_idx / 8),
+				  MYPF_REG(SGE_PF_KDOORBELL));
 		flq->inc_idx &= 7;
 	}
 }
@@ -989,7 +989,8 @@ csio_wr_issue(struct csio_hw *hw, int qidx, bool prio)
 	wmb();
 	/* Ring SGE Doorbell writing q->pidx into it */
 	csio_wr_reg32(hw, DBPRIO(prio) | QID(q->un.eq.physeqid) |
-		      PIDX(q->inc_idx), MYPF_REG(SGE_PF_KDOORBELL));
+			  CSIO_HW_PIDX(hw, q->inc_idx),
+			  MYPF_REG(SGE_PF_KDOORBELL));
 	q->inc_idx = 0;
 
 	return 0;
@@ -1331,20 +1332,30 @@ csio_wr_fixup_host_params(struct csio_hw *hw)
 
 	/* FL BUFFER SIZE#0 is Page size i,e already aligned to cache line */
 	csio_wr_reg32(hw, PAGE_SIZE, SGE_FL_BUFFER_SIZE0);
-	csio_wr_reg32(hw,
-		      (csio_rd_reg32(hw, SGE_FL_BUFFER_SIZE2) +
-		      sge->csio_fl_align - 1) & ~(sge->csio_fl_align - 1),
-		      SGE_FL_BUFFER_SIZE2);
-	csio_wr_reg32(hw,
-		      (csio_rd_reg32(hw, SGE_FL_BUFFER_SIZE3) +
-		      sge->csio_fl_align - 1) & ~(sge->csio_fl_align - 1),
-		      SGE_FL_BUFFER_SIZE3);
+
+	/*
+	 * If using hard params, the following will get set correctly
+	 * in csio_wr_set_sge().
+	 */
+	if (hw->flags & CSIO_HWF_USING_SOFT_PARAMS) {
+		csio_wr_reg32(hw,
+			(csio_rd_reg32(hw, SGE_FL_BUFFER_SIZE2) +
+			sge->csio_fl_align - 1) & ~(sge->csio_fl_align - 1),
+			SGE_FL_BUFFER_SIZE2);
+		csio_wr_reg32(hw,
+			(csio_rd_reg32(hw, SGE_FL_BUFFER_SIZE3) +
+			sge->csio_fl_align - 1) & ~(sge->csio_fl_align - 1),
+			SGE_FL_BUFFER_SIZE3);
+	}
 
 	csio_wr_reg32(hw, HPZ0(PAGE_SHIFT - 12), ULP_RX_TDDP_PSZ);
 
 	/* default value of rx_dma_offset of the NIC driver */
 	csio_set_reg_field(hw, SGE_CONTROL, PKTSHIFT_MASK,
 			   PKTSHIFT(CSIO_SGE_RX_DMA_OFFSET));
+
+	csio_hw_tp_wr_bits_indirect(hw, TP_INGRESS_CONFIG,
+				    CSUM_HAS_PSEUDO_HDR, 0);
 }
 
 static void
@@ -1460,18 +1471,21 @@ csio_wr_set_sge(struct csio_hw *hw)
 	 * and generate an interrupt when this occurs so we can recover.
 	 */
 	csio_set_reg_field(hw, SGE_DBFIFO_STATUS,
-			   HP_INT_THRESH(HP_INT_THRESH_MASK) |
-			   LP_INT_THRESH(LP_INT_THRESH_MASK),
-			   HP_INT_THRESH(CSIO_SGE_DBFIFO_INT_THRESH) |
-			   LP_INT_THRESH(CSIO_SGE_DBFIFO_INT_THRESH));
+		   HP_INT_THRESH(HP_INT_THRESH_MASK) |
+		   CSIO_HW_LP_INT_THRESH(hw, CSIO_HW_M_LP_INT_THRESH(hw)),
+		   HP_INT_THRESH(CSIO_SGE_DBFIFO_INT_THRESH) |
+		   CSIO_HW_LP_INT_THRESH(hw, CSIO_SGE_DBFIFO_INT_THRESH));
+
 	csio_set_reg_field(hw, SGE_DOORBELL_CONTROL, ENABLE_DROP,
 			   ENABLE_DROP);
 
 	/* SGE_FL_BUFFER_SIZE0 is set up by csio_wr_fixup_host_params(). */
 
 	CSIO_SET_FLBUF_SIZE(hw, 1, CSIO_SGE_FLBUF_SIZE1);
-	CSIO_SET_FLBUF_SIZE(hw, 2, CSIO_SGE_FLBUF_SIZE2);
-	CSIO_SET_FLBUF_SIZE(hw, 3, CSIO_SGE_FLBUF_SIZE3);
+	csio_wr_reg32(hw, (CSIO_SGE_FLBUF_SIZE2 + sge->csio_fl_align - 1)
+		      & ~(sge->csio_fl_align - 1), SGE_FL_BUFFER_SIZE2);
+	csio_wr_reg32(hw, (CSIO_SGE_FLBUF_SIZE3 + sge->csio_fl_align - 1)
+		      & ~(sge->csio_fl_align - 1), SGE_FL_BUFFER_SIZE3);
 	CSIO_SET_FLBUF_SIZE(hw, 4, CSIO_SGE_FLBUF_SIZE4);
 	CSIO_SET_FLBUF_SIZE(hw, 5, CSIO_SGE_FLBUF_SIZE5);
 	CSIO_SET_FLBUF_SIZE(hw, 6, CSIO_SGE_FLBUF_SIZE6);
@@ -1522,22 +1536,24 @@ void
 csio_wr_sge_init(struct csio_hw *hw)
 {
 	/*
-	 * If we are master:
+	 * If we are master and chip is not initialized:
 	 *    - If we plan to use the config file, we need to fixup some
 	 *      host specific registers, and read the rest of the SGE
 	 *      configuration.
 	 *    - If we dont plan to use the config file, we need to initialize
 	 *      SGE entirely, including fixing the host specific registers.
+	 * If we are master and chip is initialized, just read and work off of
+	 *	the already initialized SGE values.
 	 * If we arent the master, we are only allowed to read and work off of
 	 *      the already initialized SGE values.
 	 *
 	 * Therefore, before calling this function, we assume that the master-
-	 * ship of the card, and whether to use config file or not, have
-	 * already been decided. In other words, CSIO_HWF_USING_SOFT_PARAMS and
-	 * CSIO_HWF_MASTER should be set/unset.
+	 * ship of the card, state and whether to use config file or not, have
+	 * already been decided.
 	 */
 	if (csio_is_hw_master(hw)) {
-		csio_wr_fixup_host_params(hw);
+		if (hw->fw_state != CSIO_DEV_STATE_INIT)
+			csio_wr_fixup_host_params(hw);
 
 		if (hw->flags & CSIO_HWF_USING_SOFT_PARAMS)
 			csio_wr_get_sge(hw);
diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c
index fed486bf..694e13c 100644
--- a/drivers/scsi/dc395x.c
+++ b/drivers/scsi/dc395x.c
@@ -4616,26 +4616,21 @@ static void adapter_uninit(struct AdapterCtlBlk *acb)
 
 
 #undef SPRINTF
-#define SPRINTF(args...) pos += sprintf(pos, args)
+#define SPRINTF(args...) seq_printf(m,##args)
 
 #undef YESNO
 #define YESNO(YN) \
  if (YN) SPRINTF(" Yes ");\
  else SPRINTF(" No  ")
 
-static int dc395x_proc_info(struct Scsi_Host *host, char *buffer,
-		char **start, off_t offset, int length, int inout)
+static int dc395x_show_info(struct seq_file *m, struct Scsi_Host *host)
 {
 	struct AdapterCtlBlk *acb = (struct AdapterCtlBlk *)host->hostdata;
 	int spd, spd1;
-	char *pos = buffer;
 	struct DeviceCtlBlk *dcb;
 	unsigned long flags;
 	int dev;
 
-	if (inout)		/* Has data been written to the file ? */
-		return -EPERM;
-
 	SPRINTF(DC395X_BANNER " PCI SCSI Host Adapter\n");
 	SPRINTF(" Driver Version " DC395X_VERSION "\n");
 
@@ -4735,22 +4730,15 @@ static int dc395x_proc_info(struct Scsi_Host *host, char *buffer,
 		SPRINTF("END\n");
 	}
 
-	*start = buffer + offset;
 	DC395x_UNLOCK_IO(acb->scsi_host, flags);
-
-	if (pos - buffer < offset)
-		return 0;
-	else if (pos - buffer - offset < length)
-		return pos - buffer - offset;
-	else
-		return length;
+	return 0;
 }
 
 
 static struct scsi_host_template dc395x_driver_template = {
 	.module                 = THIS_MODULE,
 	.proc_name              = DC395X_NAME,
-	.proc_info              = dc395x_proc_info,
+	.show_info              = dc395x_show_info,
 	.name                   = DC395X_BANNER " " DC395X_VERSION,
 	.queuecommand           = dc395x_queue_command,
 	.bios_param             = dc395x_bios_param,
diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c
index b6e2700..19e1b42 100644
--- a/drivers/scsi/dpt_i2o.c
+++ b/drivers/scsi/dpt_i2o.c
@@ -553,36 +553,14 @@ static const char *adpt_info(struct Scsi_Host *host)
 	return (char *) (pHba->detail);
 }
 
-static int adpt_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
-		  int length, int inout)
+static int adpt_show_info(struct seq_file *m, struct Scsi_Host *host)
 {
 	struct adpt_device* d;
 	int id;
 	int chan;
-	int len = 0;
-	int begin = 0;
-	int pos = 0;
 	adpt_hba* pHba;
 	int unit;
 
-	*start = buffer;
-	if (inout == TRUE) {
-		/*
-		 * The user has done a write and wants us to take the
-		 * data in the buffer and do something with it.
-		 * proc_scsiwrite calls us with inout = 1
-		 *
-		 * Read data from buffer (writing to us) - NOT SUPPORTED
-		 */
-		return -EINVAL;
-	}
-
-	/*
-	 * inout = 0 means the user has done a read and wants information
-	 * returned, so we write information about the cards into the buffer
-	 * proc_scsiread() calls us with inout = 0
-	 */
-
 	// Find HBA (host bus adapter) we are looking for
 	mutex_lock(&adpt_configuration_lock);
 	for (pHba = hba_chain; pHba; pHba = pHba->next) {
@@ -596,86 +574,30 @@ static int adpt_proc_info(struct Scsi_Host *host, char *buffer, char **start, of
 	}
 	host = pHba->host;
 
-	len  = sprintf(buffer    , "Adaptec I2O RAID Driver Version: %s\n\n", DPT_I2O_VERSION);
-	len += sprintf(buffer+len, "%s\n", pHba->detail);
-	len += sprintf(buffer+len, "SCSI Host=scsi%d  Control Node=/dev/%s  irq=%d\n", 
+	seq_printf(m, "Adaptec I2O RAID Driver Version: %s\n\n", DPT_I2O_VERSION);
+	seq_printf(m, "%s\n", pHba->detail);
+	seq_printf(m, "SCSI Host=scsi%d  Control Node=/dev/%s  irq=%d\n", 
 			pHba->host->host_no, pHba->name, host->irq);
-	len += sprintf(buffer+len, "\tpost fifo size  = %d\n\treply fifo size = %d\n\tsg table size   = %d\n\n",
+	seq_printf(m, "\tpost fifo size  = %d\n\treply fifo size = %d\n\tsg table size   = %d\n\n",
 			host->can_queue, (int) pHba->reply_fifo_size , host->sg_tablesize);
 
-	pos = begin + len;
-
-	/* CHECKPOINT */
-	if(pos > offset + length) {
-		goto stop_output;
-	}
-	if(pos <= offset) {
-		/*
-		 * If we haven't even written to where we last left
-		 * off (the last time we were called), reset the 
-		 * beginning pointer.
-		 */
-		len = 0;
-		begin = pos;
-	}
-	len +=  sprintf(buffer+len, "Devices:\n");
+	seq_printf(m, "Devices:\n");
 	for(chan = 0; chan < MAX_CHANNEL; chan++) {
 		for(id = 0; id < MAX_ID; id++) {
 			d = pHba->channel[chan].device[id];
-			while(d){
-				len += sprintf(buffer+len,"\t%-24.24s", d->pScsi_dev->vendor);
-				len += sprintf(buffer+len," Rev: %-8.8s\n", d->pScsi_dev->rev);
-				pos = begin + len;
-
-
-				/* CHECKPOINT */
-				if(pos > offset + length) {
-					goto stop_output;
-				}
-				if(pos <= offset) {
-					len = 0;
-					begin = pos;
-				}
+			while(d) {
+				seq_printf(m,"\t%-24.24s", d->pScsi_dev->vendor);
+				seq_printf(m," Rev: %-8.8s\n", d->pScsi_dev->rev);
 
 				unit = d->pI2o_dev->lct_data.tid;
-				len += sprintf(buffer+len, "\tTID=%d, (Channel=%d, Target=%d, Lun=%d)  (%s)\n\n",
+				seq_printf(m, "\tTID=%d, (Channel=%d, Target=%d, Lun=%d)  (%s)\n\n",
 					       unit, (int)d->scsi_channel, (int)d->scsi_id, (int)d->scsi_lun,
 					       scsi_device_online(d->pScsi_dev)? "online":"offline"); 
-				pos = begin + len;
-
-				/* CHECKPOINT */
-				if(pos > offset + length) {
-					goto stop_output;
-				}
-				if(pos <= offset) {
-					len = 0;
-					begin = pos;
-				}
-
 				d = d->next_lun;
 			}
 		}
 	}
-
-	/*
-	 * begin is where we last checked our position with regards to offset
-	 * begin is always less than offset.  len is relative to begin.  It
-	 * is the number of bytes written past begin
-	 *
-	 */
-stop_output:
-	/* stop the output and calculate the correct length */
-	*(buffer + len) = '\0';
-
-	*start = buffer + (offset - begin);	/* Start of wanted data */
-	len -= (offset - begin);
-	if(len > length) {
-		len = length;
-	} else if(len < 0){
-		len = 0;
-		**start = '\0';
-	}
-	return len;
+	return 0;
 }
 
 /*
@@ -3639,7 +3561,7 @@ static struct scsi_host_template driver_template = {
 	.module			= THIS_MODULE,
 	.name			= "dpt_i2o",
 	.proc_name		= "dpt_i2o",
-	.proc_info		= adpt_proc_info,
+	.show_info		= adpt_show_info,
 	.info			= adpt_info,
 	.queuecommand		= adpt_queue,
 	.eh_abort_handler	= adpt_abort,
diff --git a/drivers/scsi/dtc.c b/drivers/scsi/dtc.c
index 4b11bb0..d01f016 100644
--- a/drivers/scsi/dtc.c
+++ b/drivers/scsi/dtc.c
@@ -216,7 +216,8 @@ static int __init dtc_detect(struct scsi_host_template * tpnt)
 	int sig, count;
 
 	tpnt->proc_name = "dtc3x80";
-	tpnt->proc_info = &dtc_proc_info;
+	tpnt->show_info = dtc_show_info;
+	tpnt->write_info = dtc_write_info;
 
 	for (count = 0; current_override < NO_OVERRIDES; ++current_override) {
 		addr = 0;
diff --git a/drivers/scsi/dtc.h b/drivers/scsi/dtc.h
index cdc6212..92d7cfc 100644
--- a/drivers/scsi/dtc.h
+++ b/drivers/scsi/dtc.h
@@ -88,7 +88,8 @@ static int dtc_bus_reset(Scsi_Cmnd *);
 #define NCR5380_queue_command		dtc_queue_command
 #define NCR5380_abort			dtc_abort
 #define NCR5380_bus_reset		dtc_bus_reset
-#define NCR5380_proc_info		dtc_proc_info 
+#define NCR5380_show_info		dtc_show_info 
+#define NCR5380_write_info		dtc_write_info 
 
 /* 15 12 11 10
    1001 1100 0000 0000 */
diff --git a/drivers/scsi/eata_pio.c b/drivers/scsi/eata_pio.c
index d5f8362..356def4 100644
--- a/drivers/scsi/eata_pio.c
+++ b/drivers/scsi/eata_pio.c
@@ -92,58 +92,22 @@ static unsigned long queue_counter;
 
 static struct scsi_host_template driver_template;
 
-/*
- * eata_proc_info
- * inout : decides on the direction of the dataflow and the meaning of the 
- *         variables
- * buffer: If inout==FALSE data is being written to it else read from it
- * *start: If inout==FALSE start of the valid data in the buffer
- * offset: If inout==FALSE offset from the beginning of the imaginary file 
- *         from which we start writing into the buffer
- * length: If inout==FALSE max number of bytes to be written into the buffer 
- *         else number of bytes in the buffer
- */
-static int eata_pio_proc_info(struct Scsi_Host *shost, char *buffer, char **start, off_t offset,
-			      int length, int rw)
+static int eata_pio_show_info(struct seq_file *m, struct Scsi_Host *shost)
 {
-	int len = 0;
-	off_t begin = 0, pos = 0;
-
-	if (rw)
-		return -ENOSYS;
-
-	len += sprintf(buffer+len, "EATA (Extended Attachment) PIO driver version: "
+	seq_printf(m, "EATA (Extended Attachment) PIO driver version: "
 		   "%d.%d%s\n",VER_MAJOR, VER_MINOR, VER_SUB);
-	len += sprintf(buffer + len, "queued commands:     %10ld\n"
+	seq_printf(m, "queued commands:     %10ld\n"
 		   "processed interrupts:%10ld\n", queue_counter, int_counter);
-	len += sprintf(buffer + len, "\nscsi%-2d: HBA %.10s\n",
+	seq_printf(m, "\nscsi%-2d: HBA %.10s\n",
 		   shost->host_no, SD(shost)->name);
-	len += sprintf(buffer + len, "Firmware revision: v%s\n",
+	seq_printf(m, "Firmware revision: v%s\n",
 		   SD(shost)->revision);
-	len += sprintf(buffer + len, "IO: PIO\n");
-	len += sprintf(buffer + len, "Base IO : %#.4x\n", (u32) shost->base);
-	len += sprintf(buffer + len, "Host Bus: %s\n",
+	seq_printf(m, "IO: PIO\n");
+	seq_printf(m, "Base IO : %#.4x\n", (u32) shost->base);
+	seq_printf(m, "Host Bus: %s\n",
 		   (SD(shost)->bustype == 'P')?"PCI ":
 		   (SD(shost)->bustype == 'E')?"EISA":"ISA ");
-    
-	pos = begin + len;
-    
-	if (pos < offset) {
-		len = 0;
-		begin = pos;
-	}
-	if (pos > offset + length)
-		goto stop_output;
-    
-stop_output:
-	DBG(DBG_PROC, printk("2pos: %ld offset: %ld len: %d\n", pos, offset, len));
-	*start = buffer + (offset - begin);   /* Start of wanted data */
-	len -= (offset - begin);            /* Start slop */
-	if (len > length)
-		len = length;               /* Ending slop */
-	DBG(DBG_PROC, printk("3pos: %ld offset: %ld len: %d\n", pos, offset, len));
-    
-	return len;
+	return 0;
 }
 
 static int eata_pio_release(struct Scsi_Host *sh)
@@ -985,7 +949,7 @@ static int eata_pio_detect(struct scsi_host_template *tpnt)
 static struct scsi_host_template driver_template = {
 	.proc_name		= "eata_pio",
 	.name              	= "EATA (Extended Attachment) PIO driver",
-	.proc_info         	= eata_pio_proc_info,
+	.show_info         	= eata_pio_show_info,
 	.detect            	= eata_pio_detect,
 	.release           	= eata_pio_release,
 	.queuecommand      	= eata_pio_queue,
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index b5d92fc..9bfdc9a 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -490,7 +490,6 @@ static void fcoe_interface_cleanup(struct fcoe_interface *fcoe)
 {
 	struct net_device *netdev = fcoe->netdev;
 	struct fcoe_ctlr *fip = fcoe_to_ctlr(fcoe);
-	struct fcoe_ctlr_device *ctlr_dev = fcoe_ctlr_to_ctlr_dev(fip);
 
 	rtnl_lock();
 	if (!fcoe->removed)
@@ -501,7 +500,6 @@ static void fcoe_interface_cleanup(struct fcoe_interface *fcoe)
 	/* tear-down the FCoE controller */
 	fcoe_ctlr_destroy(fip);
 	scsi_host_put(fip->lp->host);
-	fcoe_ctlr_device_delete(ctlr_dev);
 	dev_put(netdev);
 	module_put(THIS_MODULE);
 }
@@ -2194,6 +2192,8 @@ out_nodev:
  */
 static void fcoe_destroy_work(struct work_struct *work)
 {
+	struct fcoe_ctlr_device *cdev;
+	struct fcoe_ctlr *ctlr;
 	struct fcoe_port *port;
 	struct fcoe_interface *fcoe;
 	struct Scsi_Host *shost;
@@ -2224,10 +2224,15 @@ static void fcoe_destroy_work(struct work_struct *work)
 	mutex_lock(&fcoe_config_mutex);
 
 	fcoe = port->priv;
+	ctlr = fcoe_to_ctlr(fcoe);
+	cdev = fcoe_ctlr_to_ctlr_dev(ctlr);
+
 	fcoe_if_destroy(port->lport);
 	fcoe_interface_cleanup(fcoe);
 
 	mutex_unlock(&fcoe_config_mutex);
+
+	fcoe_ctlr_device_delete(cdev);
 }
 
 /**
@@ -2335,7 +2340,9 @@ static int _fcoe_create(struct net_device *netdev, enum fip_state fip_mode,
 		rc = -EIO;
 		rtnl_unlock();
 		fcoe_interface_cleanup(fcoe);
-		goto out_nortnl;
+		mutex_unlock(&fcoe_config_mutex);
+		fcoe_ctlr_device_delete(ctlr_dev);
+		goto out;
 	}
 
 	/* Make this the "master" N_Port */
@@ -2375,8 +2382,8 @@ static int _fcoe_create(struct net_device *netdev, enum fip_state fip_mode,
 
 out_nodev:
 	rtnl_unlock();
-out_nortnl:
 	mutex_unlock(&fcoe_config_mutex);
+out:
 	return rc;
 }
 
diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c
index 08c3bc3..cd743c5 100644
--- a/drivers/scsi/fcoe/fcoe_ctlr.c
+++ b/drivers/scsi/fcoe/fcoe_ctlr.c
@@ -2161,7 +2161,7 @@ static void fcoe_ctlr_vn_restart(struct fcoe_ctlr *fip)
 
 	if (fip->probe_tries < FIP_VN_RLIM_COUNT) {
 		fip->probe_tries++;
-		wait = random32() % FIP_VN_PROBE_WAIT;
+		wait = prandom_u32() % FIP_VN_PROBE_WAIT;
 	} else
 		wait = FIP_VN_RLIM_INT;
 	mod_timer(&fip->timer, jiffies + msecs_to_jiffies(wait));
@@ -2794,7 +2794,7 @@ static void fcoe_ctlr_vn_timeout(struct fcoe_ctlr *fip)
 					  fcoe_all_vn2vn, 0);
 			fip->port_ka_time = jiffies +
 				 msecs_to_jiffies(FIP_VN_BEACON_INT +
-					(random32() % FIP_VN_BEACON_FUZZ));
+					(prandom_u32() % FIP_VN_BEACON_FUZZ));
 		}
 		if (time_before(fip->port_ka_time, next_time))
 			next_time = fip->port_ka_time;
@@ -2815,6 +2815,47 @@ unlock:
 }
 
 /**
+ * fcoe_ctlr_mode_set() - Set or reset the ctlr's mode
+ * @lport: The local port to be (re)configured
+ * @fip:   The FCoE controller whose mode is changing
+ * @fip_mode: The new fip mode
+ *
+ * Note that the we shouldn't be changing the libfc discovery settings
+ * (fc_disc_config) while an lport is going through the libfc state
+ * machine. The mode can only be changed when a fcoe_ctlr device is
+ * disabled, so that should ensure that this routine is only called
+ * when nothing is happening.
+ */
+void fcoe_ctlr_mode_set(struct fc_lport *lport, struct fcoe_ctlr *fip,
+			enum fip_state fip_mode)
+{
+	void *priv;
+
+	WARN_ON(lport->state != LPORT_ST_RESET &&
+		lport->state != LPORT_ST_DISABLED);
+
+	if (fip_mode == FIP_MODE_VN2VN) {
+		lport->rport_priv_size = sizeof(struct fcoe_rport);
+		lport->point_to_multipoint = 1;
+		lport->tt.disc_recv_req = fcoe_ctlr_disc_recv;
+		lport->tt.disc_start = fcoe_ctlr_disc_start;
+		lport->tt.disc_stop = fcoe_ctlr_disc_stop;
+		lport->tt.disc_stop_final = fcoe_ctlr_disc_stop_final;
+		priv = fip;
+	} else {
+		lport->rport_priv_size = 0;
+		lport->point_to_multipoint = 0;
+		lport->tt.disc_recv_req = NULL;
+		lport->tt.disc_start = NULL;
+		lport->tt.disc_stop = NULL;
+		lport->tt.disc_stop_final = NULL;
+		priv = lport;
+	}
+
+	fc_disc_config(lport, priv);
+}
+
+/**
  * fcoe_libfc_config() - Sets up libfc related properties for local port
  * @lport:    The local port to configure libfc for
  * @fip:      The FCoE controller in use by the local port
@@ -2833,21 +2874,9 @@ int fcoe_libfc_config(struct fc_lport *lport, struct fcoe_ctlr *fip,
 	fc_exch_init(lport);
 	fc_elsct_init(lport);
 	fc_lport_init(lport);
-	if (fip->mode == FIP_MODE_VN2VN)
-		lport->rport_priv_size = sizeof(struct fcoe_rport);
 	fc_rport_init(lport);
-	if (fip->mode == FIP_MODE_VN2VN) {
-		lport->point_to_multipoint = 1;
-		lport->tt.disc_recv_req = fcoe_ctlr_disc_recv;
-		lport->tt.disc_start = fcoe_ctlr_disc_start;
-		lport->tt.disc_stop = fcoe_ctlr_disc_stop;
-		lport->tt.disc_stop_final = fcoe_ctlr_disc_stop_final;
-		mutex_init(&lport->disc.disc_mutex);
-		INIT_LIST_HEAD(&lport->disc.rports);
-		lport->disc.priv = fip;
-	} else {
-		fc_disc_init(lport);
-	}
+	fc_disc_init(lport);
+	fcoe_ctlr_mode_set(lport, fip, fip->mode);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(fcoe_libfc_config);
@@ -2875,6 +2904,7 @@ EXPORT_SYMBOL(fcoe_fcf_get_selected);
 void fcoe_ctlr_set_fip_mode(struct fcoe_ctlr_device *ctlr_dev)
 {
 	struct fcoe_ctlr *ctlr = fcoe_ctlr_device_priv(ctlr_dev);
+	struct fc_lport *lport = ctlr->lp;
 
 	mutex_lock(&ctlr->ctlr_mutex);
 	switch (ctlr_dev->mode) {
@@ -2888,5 +2918,7 @@ void fcoe_ctlr_set_fip_mode(struct fcoe_ctlr_device *ctlr_dev)
 	}
 
 	mutex_unlock(&ctlr->ctlr_mutex);
+
+	fcoe_ctlr_mode_set(lport, ctlr, ctlr->mode);
 }
 EXPORT_SYMBOL(fcoe_ctlr_set_fip_mode);
diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c
index 5041f92..5cec6c6 100644
--- a/drivers/scsi/g_NCR5380.c
+++ b/drivers/scsi/g_NCR5380.c
@@ -745,42 +745,36 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src,
  
 #include "NCR5380.c"
 
-#define PRINTP(x) len += sprintf(buffer+len, x)
+#define PRINTP(x) seq_printf(m, x)
 #define ANDP ,
 
-static int sprint_opcode(char *buffer, int len, int opcode)
+static void sprint_opcode(struct seq_file *m, int opcode)
 {
-	int start = len;
 	PRINTP("0x%02x " ANDP opcode);
-	return len - start;
 }
 
-static int sprint_command(char *buffer, int len, unsigned char *command)
+static void sprint_command(struct seq_file *m, unsigned char *command)
 {
-	int i, s, start = len;
-	len += sprint_opcode(buffer, len, command[0]);
+	int i, s;
+	sprint_opcode(m, command[0]);
 	for (i = 1, s = COMMAND_SIZE(command[0]); i < s; ++i)
 		PRINTP("%02x " ANDP command[i]);
 	PRINTP("\n");
-	return len - start;
 }
 
 /**
  *	sprintf_Scsi_Cmnd	-	print a scsi command
- *	@buffer: buffr to print into
- *	@len: buffer length
+ *	@m: seq_fil to print into
  *	@cmd: SCSI command block
  *	
  *	Print out the target and command data in hex
  */
 
-static int sprint_Scsi_Cmnd(char *buffer, int len, Scsi_Cmnd * cmd)
+static void sprint_Scsi_Cmnd(struct seq_file *m, Scsi_Cmnd * cmd)
 {
-	int start = len;
 	PRINTP("host number %d destination target %d, lun %d\n" ANDP cmd->device->host->host_no ANDP cmd->device->id ANDP cmd->device->lun);
 	PRINTP("        command = ");
-	len += sprint_command(buffer, len, cmd->cmnd);
-	return len - start;
+	sprint_command(m, cmd->cmnd);
 }
 
 /**
@@ -800,9 +794,8 @@ static int sprint_Scsi_Cmnd(char *buffer, int len, Scsi_Cmnd * cmd)
  *	Locks: global cli/lock for queue walk
  */
  
-static int generic_NCR5380_proc_info(struct Scsi_Host *scsi_ptr, char *buffer, char **start, off_t offset, int length, int inout)
+static int generic_NCR5380_show_info(struct seq_file *m, struct Scsi_Host *scsi_ptr)
 {
-	int len = 0;
 	NCR5380_local_declare();
 	unsigned long flags;
 	unsigned char status;
@@ -853,16 +846,16 @@ static int generic_NCR5380_proc_info(struct Scsi_Host *scsi_ptr, char *buffer, c
 		PRINTP("  T:%d %s " ANDP dev->id ANDP scsi_device_type(dev->type));
 		for (i = 0; i < 8; i++)
 			if (dev->vendor[i] >= 0x20)
-				*(buffer + (len++)) = dev->vendor[i];
-		*(buffer + (len++)) = ' ';
+				seq_putc(m, dev->vendor[i]);
+		seq_putc(m, ' ');
 		for (i = 0; i < 16; i++)
 			if (dev->model[i] >= 0x20)
-				*(buffer + (len++)) = dev->model[i];
-		*(buffer + (len++)) = ' ';
+				seq_putc(m, dev->model[i]);
+		seq_putc(m, ' ');
 		for (i = 0; i < 4; i++)
 			if (dev->rev[i] >= 0x20)
-				*(buffer + (len++)) = dev->rev[i];
-		*(buffer + (len++)) = ' ';
+				seq_putc(m, dev->rev[i]);
+		seq_putc(m, ' ');
 
 		PRINTP("\n%10ld kb read    in %5ld secs" ANDP br / 1024 ANDP tr);
 		if (tr)
@@ -886,32 +879,28 @@ static int generic_NCR5380_proc_info(struct Scsi_Host *scsi_ptr, char *buffer, c
 	if (!hostdata->connected) {
 		PRINTP("No currently connected command\n");
 	} else {
-		len += sprint_Scsi_Cmnd(buffer, len, (Scsi_Cmnd *) hostdata->connected);
+		sprint_Scsi_Cmnd(m, (Scsi_Cmnd *) hostdata->connected);
 	}
 
 	PRINTP("issue_queue\n");
 
 	for (ptr = (Scsi_Cmnd *) hostdata->issue_queue; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble)
-		len += sprint_Scsi_Cmnd(buffer, len, ptr);
+		sprint_Scsi_Cmnd(m, ptr);
 
 	PRINTP("disconnected_queue\n");
 
 	for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble)
-		len += sprint_Scsi_Cmnd(buffer, len, ptr);
+		sprint_Scsi_Cmnd(m, ptr);
 
-	*start = buffer + offset;
-	len -= offset;
-	if (len > length)
-		len = length;
 	spin_unlock_irqrestore(scsi_ptr->host_lock, flags);
-	return len;
+	return 0;
 }
 
 #undef PRINTP
 #undef ANDP
 
 static struct scsi_host_template driver_template = {
-	.proc_info      	= generic_NCR5380_proc_info,
+	.show_info      	= generic_NCR5380_show_info,
 	.name           	= "Generic NCR5380/NCR53C400 Scsi Driver",
 	.detect         	= generic_NCR5380_detect,
 	.release        	= generic_NCR5380_release_resources,
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
index 59bceac..6d55b4e 100644
--- a/drivers/scsi/gdth.c
+++ b/drivers/scsi/gdth.c
@@ -4676,7 +4676,8 @@ static struct scsi_host_template gdth_template = {
         .eh_bus_reset_handler   = gdth_eh_bus_reset,
         .slave_configure        = gdth_slave_configure,
         .bios_param             = gdth_bios_param,
-        .proc_info              = gdth_proc_info,
+        .show_info              = gdth_show_info,
+        .write_info             = gdth_set_info,
 	.eh_timed_out		= gdth_timed_out,
         .proc_name              = "gdth",
         .can_queue              = GDTH_MAXCMDS,
diff --git a/drivers/scsi/gdth.h b/drivers/scsi/gdth.h
index fbf6f0f..3fd8b83 100644
--- a/drivers/scsi/gdth.h
+++ b/drivers/scsi/gdth.h
@@ -1007,6 +1007,7 @@ typedef struct {
 
 /* function prototyping */
 
-int gdth_proc_info(struct Scsi_Host *, char *,char **,off_t,int,int);
+int gdth_show_info(struct seq_file *, struct Scsi_Host *);
+int gdth_set_info(struct Scsi_Host *, char *, int);
 
 #endif
diff --git a/drivers/scsi/gdth_proc.c b/drivers/scsi/gdth_proc.c
index 6527543..9fb6326 100644
--- a/drivers/scsi/gdth_proc.c
+++ b/drivers/scsi/gdth_proc.c
@@ -5,23 +5,9 @@
 #include <linux/completion.h>
 #include <linux/slab.h>
 
-int gdth_proc_info(struct Scsi_Host *host, char *buffer,char **start,off_t offset,int length,   
-                   int inout)
+int gdth_set_info(struct Scsi_Host *host, char *buffer, int length)
 {
     gdth_ha_str *ha = shost_priv(host);
-
-    TRACE2(("gdth_proc_info() length %d offs %d inout %d\n",
-            length,(int)offset,inout));
-
-    if (inout)
-        return(gdth_set_info(buffer,length,host,ha));
-    else
-        return(gdth_get_info(buffer,start,offset,length,host,ha));
-}
-
-static int gdth_set_info(char *buffer,int length,struct Scsi_Host *host,
-                         gdth_ha_str *ha)
-{
     int ret_val = -EINVAL;
 
     TRACE2(("gdth_set_info() ha %d\n",ha->hanum,));
@@ -149,12 +135,10 @@ static int gdth_set_asc_info(struct Scsi_Host *host, char *buffer,
     return(-EINVAL);
 }
 
-static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
-                         struct Scsi_Host *host, gdth_ha_str *ha)
+int gdth_show_info(struct seq_file *m, struct Scsi_Host *host)
 {
-    int size = 0,len = 0;
+    gdth_ha_str *ha = shost_priv(host);
     int hlen;
-    off_t begin = 0,pos = 0;
     int id, i, j, k, sec, flag;
     int no_mdrv = 0, drv_no, is_mirr;
     u32 cnt;
@@ -189,8 +173,7 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
     /* request is i.e. "cat /proc/scsi/gdth/0" */ 
     /* format: %-15s\t%-10s\t%-15s\t%s */
     /* driver parameters */
-    size = sprintf(buffer+len,"Driver Parameters:\n");
-    len += size;  pos = begin + len;
+    seq_printf(m, "Driver Parameters:\n");
     if (reserve_list[0] == 0xff)
         strcpy(hrec, "--");
     else {
@@ -201,69 +184,50 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
             hlen += snprintf(hrec + hlen , 161 - hlen, ",%d", reserve_list[i]);
         }
     }
-    size = sprintf(buffer+len,
+    seq_printf(m,
                    " reserve_mode: \t%d         \treserve_list:  \t%s\n",
                    reserve_mode, hrec);
-    len += size;  pos = begin + len;
-    size = sprintf(buffer+len,
+    seq_printf(m,
                    " max_ids:      \t%-3d       \thdr_channel:   \t%d\n",
                    max_ids, hdr_channel);
-    len += size;  pos = begin + len;
 
     /* controller information */
-    size = sprintf(buffer+len,"\nDisk Array Controller Information:\n");
-    len += size;  pos = begin + len;
-    strcpy(hrec, ha->binfo.type_string);
-    size = sprintf(buffer+len,
+    seq_printf(m,"\nDisk Array Controller Information:\n");
+    seq_printf(m,
                    " Number:       \t%d         \tName:          \t%s\n",
-                   ha->hanum, hrec);
-    len += size;  pos = begin + len;
+                   ha->hanum, ha->binfo.type_string);
 
+    seq_printf(m,
+                   " Driver Ver.:  \t%-10s\tFirmware Ver.: \t",
+                   GDTH_VERSION_STR);
     if (ha->more_proc)
-        sprintf(hrec, "%d.%02d.%02d-%c%03X", 
+        seq_printf(m, "%d.%02d.%02d-%c%03X\n", 
                 (u8)(ha->binfo.upd_fw_ver>>24),
                 (u8)(ha->binfo.upd_fw_ver>>16),
                 (u8)(ha->binfo.upd_fw_ver),
                 ha->bfeat.raid ? 'R':'N',
                 ha->binfo.upd_revision);
     else
-        sprintf(hrec, "%d.%02d", (u8)(ha->cpar.version>>8),
+        seq_printf(m, "%d.%02d\n", (u8)(ha->cpar.version>>8),
                 (u8)(ha->cpar.version));
-
-    size = sprintf(buffer+len,
-                   " Driver Ver.:  \t%-10s\tFirmware Ver.: \t%s\n",
-                   GDTH_VERSION_STR, hrec);
-    len += size;  pos = begin + len;
  
-    if (ha->more_proc) {
+    if (ha->more_proc)
         /* more information: 1. about controller */
-        size = sprintf(buffer+len,
+        seq_printf(m,
                        " Serial No.:   \t0x%8X\tCache RAM size:\t%d KB\n",
                        ha->binfo.ser_no, ha->binfo.memsize / 1024);
-        len += size;  pos = begin + len;
-    }
 
 #ifdef GDTH_DMA_STATISTICS
     /* controller statistics */
-    size = sprintf(buffer+len,"\nController Statistics:\n");
-    len += size;  pos = begin + len;
-    size = sprintf(buffer+len,
+    seq_printf(m,"\nController Statistics:\n");
+    seq_printf(m,
                    " 32-bit DMA buffer:\t%lu\t64-bit DMA buffer:\t%lu\n",
                    ha->dma32_cnt, ha->dma64_cnt);
-    len += size;  pos = begin + len;
 #endif
 
-    if (pos < offset) {
-        len = 0;
-        begin = pos;
-    }
-    if (pos > offset + length)
-        goto stop_output;
-
     if (ha->more_proc) {
         /* more information: 2. about physical devices */
-        size = sprintf(buffer+len,"\nPhysical Devices:");
-        len += size;  pos = begin + len;
+        seq_printf(m, "\nPhysical Devices:");
         flag = FALSE;
             
         buf = gdth_ioctl_alloc(ha, GDTH_SCRATCH, FALSE, &paddr);
@@ -309,21 +273,19 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
                     strncpy(hrec+8,pdi->product,16);
                     strncpy(hrec+24,pdi->revision,4);
                     hrec[28] = 0;
-                    size = sprintf(buffer+len,
+                    seq_printf(m,
                                    "\n Chn/ID/LUN:   \t%c/%02d/%d    \tName:          \t%s\n",
                                    'A'+i,pdi->target_id,pdi->lun,hrec);
-                    len += size;  pos = begin + len;
                     flag = TRUE;
                     pdi->no_ldrive &= 0xffff;
                     if (pdi->no_ldrive == 0xffff)
                         strcpy(hrec,"--");
                     else
                         sprintf(hrec,"%d",pdi->no_ldrive);
-                    size = sprintf(buffer+len,
+                    seq_printf(m,
                                    " Capacity [MB]:\t%-6d    \tTo Log. Drive: \t%s\n",
                                    pdi->blkcnt/(1024*1024/pdi->blksize),
                                    hrec);
-                    len += size;  pos = begin + len;
                 } else {
                     pdi->devtype = 0xff;
                 }
@@ -333,11 +295,10 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
                     for (k = 0; k < pds->count; ++k) {
                         if (pds->list[k].tid == pdi->target_id &&
                             pds->list[k].lun == pdi->lun) {
-                            size = sprintf(buffer+len,
+                            seq_printf(m,
                                            " Retries:      \t%-6d    \tReassigns:     \t%d\n",
                                            pds->list[k].retries,
                                            pds->list[k].reassigns);
-                            len += size;  pos = begin + len;
                             break;
                         }
                     }
@@ -355,32 +316,20 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
                     pdef->sddc_type = 0x08;
 
                     if (gdth_execute(host, gdtcmd, cmnd, 30, NULL) == S_OK) {
-                        size = sprintf(buffer+len,
+                        seq_printf(m,
                                        " Grown Defects:\t%d\n",
                                        pdef->sddc_cnt);
-                        len += size;  pos = begin + len;
                     }
                 }
-                if (pos < offset) {
-                    len = 0;
-                    begin = pos;
-                }
-		if (pos > offset + length) {
-		    gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr);
-                    goto stop_output;
-		}
             }
         }
         gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr);
 
-        if (!flag) {
-            size = sprintf(buffer+len, "\n --\n");
-            len += size;  pos = begin + len;
-        }
+        if (!flag)
+            seq_printf(m, "\n --\n");
 
         /* 3. about logical drives */
-        size = sprintf(buffer+len,"\nLogical Drives:");
-        len += size;  pos = begin + len;
+        seq_printf(m,"\nLogical Drives:");
         flag = FALSE;
 
         buf = gdth_ioctl_alloc(ha, GDTH_SCRATCH, FALSE, &paddr);
@@ -418,10 +367,9 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
                 }
                     
                 if (drv_no == i) {
-                    size = sprintf(buffer+len,
+                    seq_printf(m,
                                    "\n Number:       \t%-2d        \tStatus:        \t%s\n",
                                    drv_no, hrec);
-                    len += size;  pos = begin + len;
                     flag = TRUE;
                     no_mdrv = pcdi->cd_ldcnt;
                     if (no_mdrv > 1 || pcdi->ld_slave != -1) {
@@ -436,61 +384,37 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
                     } else {
                         strcpy(hrec, "???");
                     }
-                    size = sprintf(buffer+len,
+                    seq_printf(m,
                                    " Capacity [MB]:\t%-6d    \tType:          \t%s\n",
                                    pcdi->ld_blkcnt/(1024*1024/pcdi->ld_blksize),
                                    hrec);
-                    len += size;  pos = begin + len;
                 } else {
-                    size = sprintf(buffer+len,
+                    seq_printf(m,
                                    " Slave Number: \t%-2d        \tStatus:        \t%s\n",
                                    drv_no & 0x7fff, hrec);
-                    len += size;  pos = begin + len;
                 }
                 drv_no = pcdi->ld_slave;
-                if (pos < offset) {
-                    len = 0;
-                    begin = pos;
-                }
-		if (pos > offset + length) {
-		    gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr);
-                    goto stop_output;
-		}
             } while (drv_no != -1);
              
-            if (is_mirr) {
-                size = sprintf(buffer+len,
+            if (is_mirr)
+                seq_printf(m,
                                " Missing Drv.: \t%-2d        \tInvalid Drv.:  \t%d\n",
                                no_mdrv - j - k, k);
-                len += size;  pos = begin + len;
-            }
-              
+
             if (!ha->hdr[i].is_arraydrv)
                 strcpy(hrec, "--");
             else
                 sprintf(hrec, "%d", ha->hdr[i].master_no);
-            size = sprintf(buffer+len,
+            seq_printf(m,
                            " To Array Drv.:\t%s\n", hrec);
-            len += size;  pos = begin + len;
-            if (pos < offset) {
-                len = 0;
-                begin = pos;
-            }
-	    if (pos > offset + length) {
-		gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr);
-                goto stop_output;
-	    }
         }       
         gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr);
         
-        if (!flag) {
-            size = sprintf(buffer+len, "\n --\n");
-            len += size;  pos = begin + len;
-        }   
+        if (!flag)
+            seq_printf(m, "\n --\n");
 
         /* 4. about array drives */
-        size = sprintf(buffer+len,"\nArray Drives:");
-        len += size;  pos = begin + len;
+        seq_printf(m,"\nArray Drives:");
         flag = FALSE;
 
         buf = gdth_ioctl_alloc(ha, GDTH_SCRATCH, FALSE, &paddr);
@@ -525,10 +449,9 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
                     strcat(hrec, "/expand");
                 else if (pai->ai_ext_state & 0x1)
                     strcat(hrec, "/patch");
-                size = sprintf(buffer+len,
+                seq_printf(m,
                                "\n Number:       \t%-2d        \tStatus:        \t%s\n",
                                i,hrec);
-                len += size;  pos = begin + len;
                 flag = TRUE;
 
                 if (pai->ai_type == 0)
@@ -539,31 +462,19 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
                     strcpy(hrec, "RAID-5");
                 else 
                     strcpy(hrec, "RAID-10");
-                size = sprintf(buffer+len,
+                seq_printf(m,
                                " Capacity [MB]:\t%-6d    \tType:          \t%s\n",
                                pai->ai_size/(1024*1024/pai->ai_secsize),
                                hrec);
-                len += size;  pos = begin + len;
-                if (pos < offset) {
-                    len = 0;
-                    begin = pos;
-                }
-		if (pos > offset + length) {
-		    gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr);
-                    goto stop_output;
-		}
             }
         }
         gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr);
         
-        if (!flag) {
-            size = sprintf(buffer+len, "\n --\n");
-            len += size;  pos = begin + len;
-        }
+        if (!flag)
+            seq_printf(m, "\n --\n");
 
         /* 5. about host drives */
-        size = sprintf(buffer+len,"\nHost Drives:");
-        len += size;  pos = begin + len;
+        seq_printf(m,"\nHost Drives:");
         flag = FALSE;
 
         buf = gdth_ioctl_alloc(ha, sizeof(gdth_hget_str), FALSE, &paddr);
@@ -605,33 +516,22 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
             if (!(ha->hdr[i].present))
                 continue;
               
-            size = sprintf(buffer+len,
+            seq_printf(m,
                            "\n Number:       \t%-2d        \tArr/Log. Drive:\t%d\n",
                            i, ha->hdr[i].ldr_no);
-            len += size;  pos = begin + len;
             flag = TRUE;
 
-            size = sprintf(buffer+len,
+            seq_printf(m,
                            " Capacity [MB]:\t%-6d    \tStart Sector:  \t%d\n",
                            (u32)(ha->hdr[i].size/2048), ha->hdr[i].start_sec);
-            len += size;  pos = begin + len;
-            if (pos < offset) {
-                len = 0;
-                begin = pos;
-            }
-            if (pos > offset + length)
-                goto stop_output;
         }
         
-        if (!flag) {
-            size = sprintf(buffer+len, "\n --\n");
-            len += size;  pos = begin + len;
-        }
+        if (!flag)
+            seq_printf(m, "\n --\n");
     }
 
     /* controller events */
-    size = sprintf(buffer+len,"\nController Events:\n");
-    len += size;  pos = begin + len;
+    seq_printf(m,"\nController Events:\n");
 
     for (id = -1;;) {
         id = gdth_read_event(ha, id, estr);
@@ -643,29 +543,14 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
             do_gettimeofday(&tv);
             sec = (int)(tv.tv_sec - estr->first_stamp);
             if (sec < 0) sec = 0;
-            size = sprintf(buffer+len," date- %02d:%02d:%02d\t%s\n",
+            seq_printf(m," date- %02d:%02d:%02d\t%s\n",
                            sec/3600, sec%3600/60, sec%60, hrec);
-            len += size;  pos = begin + len;
-            if (pos < offset) {
-                len = 0;
-                begin = pos;
-            }
-            if (pos > offset + length)
-                goto stop_output;
         }
         if (id == -1)
             break;
     }
-
 stop_output:
-    *start = buffer +(offset-begin);
-    len -= (offset-begin);
-    if (len > length)
-        len = length;
-    TRACE2(("get_info() len %d pos %d begin %d offset %d length %d size %d\n",
-            len,(int)pos,(int)begin,(int)offset,length,size));
-    rc = len;
-
+    rc = 0;
 free_fail:
     kfree(gdtcmd);
     kfree(estr);
diff --git a/drivers/scsi/gdth_proc.h b/drivers/scsi/gdth_proc.h
index dab15f5..aaa6181 100644
--- a/drivers/scsi/gdth_proc.h
+++ b/drivers/scsi/gdth_proc.h
@@ -8,11 +8,6 @@
 int gdth_execute(struct Scsi_Host *shost, gdth_cmd_str *gdtcmd, char *cmnd,
                  int timeout, u32 *info);
 
-static int gdth_set_info(char *buffer,int length,struct Scsi_Host *host,
-                         gdth_ha_str *ha);
-static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
-                         struct Scsi_Host *host, gdth_ha_str *ha);
-
 static int gdth_set_asc_info(struct Scsi_Host *host, char *buffer,
                              int length, gdth_ha_str *ha);
 
diff --git a/drivers/scsi/gvp11.c b/drivers/scsi/gvp11.c
index dbe4cc6..2203ac2 100644
--- a/drivers/scsi/gvp11.c
+++ b/drivers/scsi/gvp11.c
@@ -191,7 +191,8 @@ static int gvp11_bus_reset(struct scsi_cmnd *cmd)
 static struct scsi_host_template gvp11_scsi_template = {
 	.module			= THIS_MODULE,
 	.name			= "GVP Series II SCSI",
-	.proc_info		= wd33c93_proc_info,
+	.show_info		= wd33c93_show_info,
+	.write_info		= wd33c93_write_info,
 	.proc_name		= "GVP11",
 	.queuecommand		= wd33c93_queuecommand,
 	.eh_abort_handler	= wd33c93_abort,
diff --git a/drivers/scsi/imm.c b/drivers/scsi/imm.c
index 26cd9d1..89a8266 100644
--- a/drivers/scsi/imm.c
+++ b/drivers/scsi/imm.c
@@ -121,45 +121,26 @@ static inline void imm_pb_release(imm_struct *dev)
  * testing...
  * Also gives a method to use a script to obtain optimum timings (TODO)
  */
-static inline int imm_proc_write(imm_struct *dev, char *buffer, int length)
+static int imm_write_info(struct Scsi_Host *host, char *buffer, int length)
 {
-	unsigned long x;
+	imm_struct *dev = imm_dev(host);
 
 	if ((length > 5) && (strncmp(buffer, "mode=", 5) == 0)) {
-		x = simple_strtoul(buffer + 5, NULL, 0);
-		dev->mode = x;
+		dev->mode = simple_strtoul(buffer + 5, NULL, 0);
 		return length;
 	}
 	printk("imm /proc: invalid variable\n");
-	return (-EINVAL);
+	return -EINVAL;
 }
 
-static int imm_proc_info(struct Scsi_Host *host, char *buffer, char **start,
-			off_t offset, int length, int inout)
+static int imm_show_info(struct seq_file *m, struct Scsi_Host *host)
 {
 	imm_struct *dev = imm_dev(host);
-	int len = 0;
-
-	if (inout)
-		return imm_proc_write(dev, buffer, length);
-
-	len += sprintf(buffer + len, "Version : %s\n", IMM_VERSION);
-	len +=
-	    sprintf(buffer + len, "Parport : %s\n",
-		    dev->dev->port->name);
-	len +=
-	    sprintf(buffer + len, "Mode    : %s\n",
-		    IMM_MODE_STRING[dev->mode]);
 
-	/* Request for beyond end of buffer */
-	if (offset > len)
-		return 0;
-
-	*start = buffer + offset;
-	len -= offset;
-	if (len > length)
-		len = length;
-	return len;
+	seq_printf(m, "Version : %s\n", IMM_VERSION);
+	seq_printf(m, "Parport : %s\n", dev->dev->port->name);
+	seq_printf(m, "Mode    : %s\n", IMM_MODE_STRING[dev->mode]);
+	return 0;
 }
 
 #if IMM_DEBUG > 0
@@ -1118,7 +1099,8 @@ static int imm_adjust_queue(struct scsi_device *device)
 static struct scsi_host_template imm_template = {
 	.module			= THIS_MODULE,
 	.proc_name		= "imm",
-	.proc_info		= imm_proc_info,
+	.show_info		= imm_show_info,
+	.write_info		= imm_write_info,
 	.name			= "Iomega VPI2 (imm) interface",
 	.queuecommand		= imm_queuecommand,
 	.eh_abort_handler	= imm_abort,
diff --git a/drivers/scsi/in2000.c b/drivers/scsi/in2000.c
index deb5b6d..bf02821 100644
--- a/drivers/scsi/in2000.c
+++ b/drivers/scsi/in2000.c
@@ -2166,152 +2166,117 @@ static int in2000_biosparam(struct scsi_device *sdev, struct block_device *bdev,
 }
 
 
-static int in2000_proc_info(struct Scsi_Host *instance, char *buf, char **start, off_t off, int len, int in)
+static int in2000_write_info(struct Scsi_Host *instance, char *buf, int len)
 {
 
 #ifdef PROC_INTERFACE
 
 	char *bp;
-	char tbuf[128];
-	unsigned long flags;
 	struct IN2000_hostdata *hd;
-	Scsi_Cmnd *cmd;
 	int x, i;
-	static int stop = 0;
 
 	hd = (struct IN2000_hostdata *) instance->hostdata;
 
-/* If 'in' is TRUE we need to _read_ the proc file. We accept the following
- * keywords (same format as command-line, but only ONE per read):
- *    debug
- *    disconnect
- *    period
- *    resync
- *    proc
- */
-
-	if (in) {
-		buf[len] = '\0';
-		bp = buf;
-		if (!strncmp(bp, "debug:", 6)) {
-			bp += 6;
-			hd->args = simple_strtoul(bp, NULL, 0) & DB_MASK;
-		} else if (!strncmp(bp, "disconnect:", 11)) {
-			bp += 11;
-			x = simple_strtoul(bp, NULL, 0);
-			if (x < DIS_NEVER || x > DIS_ALWAYS)
-				x = DIS_ADAPTIVE;
-			hd->disconnect = x;
-		} else if (!strncmp(bp, "period:", 7)) {
-			bp += 7;
-			x = simple_strtoul(bp, NULL, 0);
-			hd->default_sx_per = sx_table[round_period((unsigned int) x)].period_ns;
-		} else if (!strncmp(bp, "resync:", 7)) {
-			bp += 7;
-			x = simple_strtoul(bp, NULL, 0);
-			for (i = 0; i < 7; i++)
-				if (x & (1 << i))
-					hd->sync_stat[i] = SS_UNSET;
-		} else if (!strncmp(bp, "proc:", 5)) {
-			bp += 5;
-			hd->proc = simple_strtoul(bp, NULL, 0);
-		} else if (!strncmp(bp, "level2:", 7)) {
-			bp += 7;
-			hd->level2 = simple_strtoul(bp, NULL, 0);
-		}
-		return len;
+	buf[len] = '\0';
+	bp = buf;
+	if (!strncmp(bp, "debug:", 6)) {
+		bp += 6;
+		hd->args = simple_strtoul(bp, NULL, 0) & DB_MASK;
+	} else if (!strncmp(bp, "disconnect:", 11)) {
+		bp += 11;
+		x = simple_strtoul(bp, NULL, 0);
+		if (x < DIS_NEVER || x > DIS_ALWAYS)
+			x = DIS_ADAPTIVE;
+		hd->disconnect = x;
+	} else if (!strncmp(bp, "period:", 7)) {
+		bp += 7;
+		x = simple_strtoul(bp, NULL, 0);
+		hd->default_sx_per = sx_table[round_period((unsigned int) x)].period_ns;
+	} else if (!strncmp(bp, "resync:", 7)) {
+		bp += 7;
+		x = simple_strtoul(bp, NULL, 0);
+		for (i = 0; i < 7; i++)
+			if (x & (1 << i))
+				hd->sync_stat[i] = SS_UNSET;
+	} else if (!strncmp(bp, "proc:", 5)) {
+		bp += 5;
+		hd->proc = simple_strtoul(bp, NULL, 0);
+	} else if (!strncmp(bp, "level2:", 7)) {
+		bp += 7;
+		hd->level2 = simple_strtoul(bp, NULL, 0);
 	}
+#endif
+	return len;
+}
+
+static int in2000_show_info(struct seq_file *m, struct Scsi_Host *instance)
+{
+
+#ifdef PROC_INTERFACE
+	unsigned long flags;
+	struct IN2000_hostdata *hd;
+	Scsi_Cmnd *cmd;
+	int x;
+
+	hd = (struct IN2000_hostdata *) instance->hostdata;
 
 	spin_lock_irqsave(instance->host_lock, flags);
-	bp = buf;
-	*bp = '\0';
-	if (hd->proc & PR_VERSION) {
-		sprintf(tbuf, "\nVersion %s - %s.", IN2000_VERSION, IN2000_DATE);
-		strcat(bp, tbuf);
-	}
+	if (hd->proc & PR_VERSION)
+		seq_printf(m, "\nVersion %s - %s.", IN2000_VERSION, IN2000_DATE);
+
 	if (hd->proc & PR_INFO) {
-		sprintf(tbuf, "\ndip_switch=%02x: irq=%d io=%02x floppy=%s sync/DOS5=%s", (hd->dip_switch & 0x7f), instance->irq, hd->io_base, (hd->dip_switch & 0x40) ? "Yes" : "No", (hd->dip_switch & 0x20) ? "Yes" : "No");
-		strcat(bp, tbuf);
-		strcat(bp, "\nsync_xfer[] =       ");
-		for (x = 0; x < 7; x++) {
-			sprintf(tbuf, "\t%02x", hd->sync_xfer[x]);
-			strcat(bp, tbuf);
-		}
-		strcat(bp, "\nsync_stat[] =       ");
-		for (x = 0; x < 7; x++) {
-			sprintf(tbuf, "\t%02x", hd->sync_stat[x]);
-			strcat(bp, tbuf);
-		}
+		seq_printf(m, "\ndip_switch=%02x: irq=%d io=%02x floppy=%s sync/DOS5=%s", (hd->dip_switch & 0x7f), instance->irq, hd->io_base, (hd->dip_switch & 0x40) ? "Yes" : "No", (hd->dip_switch & 0x20) ? "Yes" : "No");
+		seq_printf(m, "\nsync_xfer[] =       ");
+		for (x = 0; x < 7; x++)
+			seq_printf(m, "\t%02x", hd->sync_xfer[x]);
+		seq_printf(m, "\nsync_stat[] =       ");
+		for (x = 0; x < 7; x++)
+			seq_printf(m, "\t%02x", hd->sync_stat[x]);
 	}
 #ifdef PROC_STATISTICS
 	if (hd->proc & PR_STATISTICS) {
-		strcat(bp, "\ncommands issued:    ");
-		for (x = 0; x < 7; x++) {
-			sprintf(tbuf, "\t%ld", hd->cmd_cnt[x]);
-			strcat(bp, tbuf);
-		}
-		strcat(bp, "\ndisconnects allowed:");
-		for (x = 0; x < 7; x++) {
-			sprintf(tbuf, "\t%ld", hd->disc_allowed_cnt[x]);
-			strcat(bp, tbuf);
-		}
-		strcat(bp, "\ndisconnects done:   ");
-		for (x = 0; x < 7; x++) {
-			sprintf(tbuf, "\t%ld", hd->disc_done_cnt[x]);
-			strcat(bp, tbuf);
-		}
-		sprintf(tbuf, "\ninterrupts:      \t%ld", hd->int_cnt);
-		strcat(bp, tbuf);
+		seq_printf(m, "\ncommands issued:    ");
+		for (x = 0; x < 7; x++)
+			seq_printf(m, "\t%ld", hd->cmd_cnt[x]);
+		seq_printf(m, "\ndisconnects allowed:");
+		for (x = 0; x < 7; x++)
+			seq_printf(m, "\t%ld", hd->disc_allowed_cnt[x]);
+		seq_printf(m, "\ndisconnects done:   ");
+		for (x = 0; x < 7; x++)
+			seq_printf(m, "\t%ld", hd->disc_done_cnt[x]);
+		seq_printf(m, "\ninterrupts:      \t%ld", hd->int_cnt);
 	}
 #endif
 	if (hd->proc & PR_CONNECTED) {
-		strcat(bp, "\nconnected:     ");
+		seq_printf(m, "\nconnected:     ");
 		if (hd->connected) {
 			cmd = (Scsi_Cmnd *) hd->connected;
-			sprintf(tbuf, " %d:%d(%02x)", cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
-			strcat(bp, tbuf);
+			seq_printf(m, " %d:%d(%02x)", cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
 		}
 	}
 	if (hd->proc & PR_INPUTQ) {
-		strcat(bp, "\ninput_Q:       ");
+		seq_printf(m, "\ninput_Q:       ");
 		cmd = (Scsi_Cmnd *) hd->input_Q;
 		while (cmd) {
-			sprintf(tbuf, " %d:%d(%02x)", cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
-			strcat(bp, tbuf);
+			seq_printf(m, " %d:%d(%02x)", cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
 			cmd = (Scsi_Cmnd *) cmd->host_scribble;
 		}
 	}
 	if (hd->proc & PR_DISCQ) {
-		strcat(bp, "\ndisconnected_Q:");
+		seq_printf(m, "\ndisconnected_Q:");
 		cmd = (Scsi_Cmnd *) hd->disconnected_Q;
 		while (cmd) {
-			sprintf(tbuf, " %d:%d(%02x)", cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
-			strcat(bp, tbuf);
+			seq_printf(m, " %d:%d(%02x)", cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
 			cmd = (Scsi_Cmnd *) cmd->host_scribble;
 		}
 	}
 	if (hd->proc & PR_TEST) {
 		;		/* insert your own custom function here */
 	}
-	strcat(bp, "\n");
+	seq_printf(m, "\n");
 	spin_unlock_irqrestore(instance->host_lock, flags);
-	*start = buf;
-	if (stop) {
-		stop = 0;
-		return 0;	/* return 0 to signal end-of-file */
-	}
-	if (off > 0x40000)	/* ALWAYS stop after 256k bytes have been read */
-		stop = 1;
-	if (hd->proc & PR_STOP)	/* stop every other time */
-		stop = 1;
-	return strlen(bp);
-
-#else				/* PROC_INTERFACE */
-
-	return 0;
-
 #endif				/* PROC_INTERFACE */
-
+	return 0;
 }
 
 MODULE_LICENSE("GPL");
@@ -2319,7 +2284,8 @@ MODULE_LICENSE("GPL");
 
 static struct scsi_host_template driver_template = {
 	.proc_name       		= "in2000",
-	.proc_info       		= in2000_proc_info,
+	.write_info       		= in2000_write_info,
+	.show_info       		= in2000_show_info,
 	.name            		= "Always IN2000",
 	.detect          		= in2000_detect, 
 	.release			= in2000_release,
diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c
index 9aa86a3..8d5ea8a 100644
--- a/drivers/scsi/ips.c
+++ b/drivers/scsi/ips.c
@@ -326,10 +326,9 @@ static void ips_scmd_buf_write(struct scsi_cmnd * scmd, void *data,
 static void ips_scmd_buf_read(struct scsi_cmnd * scmd, void *data,
 			      unsigned int count);
 
-static int ips_proc_info(struct Scsi_Host *, char *, char **, off_t, int, int);
-static int ips_host_info(ips_ha_t *, char *, off_t, int);
-static void copy_mem_info(IPS_INFOSTR *, char *, int);
-static int copy_info(IPS_INFOSTR *, char *, ...);
+static int ips_write_info(struct Scsi_Host *, char *, int);
+static int ips_show_info(struct seq_file *, struct Scsi_Host *);
+static int ips_host_info(ips_ha_t *, struct seq_file *);
 static int ips_abort_init(ips_ha_t * ha, int index);
 static int ips_init_phase2(int index);
 
@@ -367,7 +366,8 @@ static struct scsi_host_template ips_driver_template = {
 	.eh_abort_handler	= ips_eh_abort,
 	.eh_host_reset_handler	= ips_eh_reset,
 	.proc_name		= "ips",
-	.proc_info		= ips_proc_info,
+	.show_info		= ips_show_info,
+	.write_info		= ips_write_info,
 	.slave_configure	= ips_slave_configure,
 	.bios_param		= ips_biosparam,
 	.this_id		= -1,
@@ -1433,25 +1433,12 @@ ips_info(struct Scsi_Host *SH)
 	return (bp);
 }
 
-/****************************************************************************/
-/*                                                                          */
-/* Routine Name: ips_proc_info                                              */
-/*                                                                          */
-/* Routine Description:                                                     */
-/*                                                                          */
-/*   The passthru interface for the driver                                  */
-/*                                                                          */
-/****************************************************************************/
 static int
-ips_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
-	      int length, int func)
+ips_write_info(struct Scsi_Host *host, char *buffer, int length)
 {
 	int i;
-	int ret;
 	ips_ha_t *ha = NULL;
 
-	METHOD_TRACE("ips_proc_info", 1);
-
 	/* Find our host structure */
 	for (i = 0; i < ips_next_controller; i++) {
 		if (ips_sh[i]) {
@@ -1465,18 +1452,29 @@ ips_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
 	if (!ha)
 		return (-EINVAL);
 
-	if (func) {
-		/* write */
-		return (0);
-	} else {
-		/* read */
-		if (start)
-			*start = buffer;
+	return 0;
+}
 
-		ret = ips_host_info(ha, buffer, offset, length);
+static int
+ips_show_info(struct seq_file *m, struct Scsi_Host *host)
+{
+	int i;
+	ips_ha_t *ha = NULL;
 
-		return (ret);
+	/* Find our host structure */
+	for (i = 0; i < ips_next_controller; i++) {
+		if (ips_sh[i]) {
+			if (ips_sh[i] == host) {
+				ha = (ips_ha_t *) ips_sh[i]->hostdata;
+				break;
+			}
+		}
 	}
+
+	if (!ha)
+		return (-EINVAL);
+
+	return ips_host_info(ha, m);
 }
 
 /*--------------------------------------------------------------------------*/
@@ -2035,183 +2033,113 @@ ips_cleanup_passthru(ips_ha_t * ha, ips_scb_t * scb)
 /*                                                                          */
 /****************************************************************************/
 static int
-ips_host_info(ips_ha_t * ha, char *ptr, off_t offset, int len)
+ips_host_info(ips_ha_t *ha, struct seq_file *m)
 {
-	IPS_INFOSTR info;
-
 	METHOD_TRACE("ips_host_info", 1);
 
-	info.buffer = ptr;
-	info.length = len;
-	info.offset = offset;
-	info.pos = 0;
-	info.localpos = 0;
-
-	copy_info(&info, "\nIBM ServeRAID General Information:\n\n");
+	seq_printf(m, "\nIBM ServeRAID General Information:\n\n");
 
 	if ((le32_to_cpu(ha->nvram->signature) == IPS_NVRAM_P5_SIG) &&
 	    (le16_to_cpu(ha->nvram->adapter_type) != 0))
-		copy_info(&info, "\tController Type                   : %s\n",
+		seq_printf(m, "\tController Type                   : %s\n",
 			  ips_adapter_name[ha->ad_type - 1]);
 	else
-		copy_info(&info,
+		seq_printf(m,
 			  "\tController Type                   : Unknown\n");
 
 	if (ha->io_addr)
-		copy_info(&info,
-			  "\tIO region                         : 0x%lx (%d bytes)\n",
+		seq_printf(m,
+			  "\tIO region                         : 0x%x (%d bytes)\n",
 			  ha->io_addr, ha->io_len);
 
 	if (ha->mem_addr) {
-		copy_info(&info,
-			  "\tMemory region                     : 0x%lx (%d bytes)\n",
+		seq_printf(m,
+			  "\tMemory region                     : 0x%x (%d bytes)\n",
 			  ha->mem_addr, ha->mem_len);
-		copy_info(&info,
+		seq_printf(m,
 			  "\tShared memory address             : 0x%lx\n",
-			  ha->mem_ptr);
+			  (unsigned long)ha->mem_ptr);
 	}
 
-	copy_info(&info, "\tIRQ number                        : %d\n", ha->pcidev->irq);
+	seq_printf(m, "\tIRQ number                        : %d\n", ha->pcidev->irq);
 
     /* For the Next 3 lines Check for Binary 0 at the end and don't include it if it's there. */
     /* That keeps everything happy for "text" operations on the proc file.                    */
 
 	if (le32_to_cpu(ha->nvram->signature) == IPS_NVRAM_P5_SIG) {
 	if (ha->nvram->bios_low[3] == 0) {
-            copy_info(&info,
-			          "\tBIOS Version                      : %c%c%c%c%c%c%c\n",
-			          ha->nvram->bios_high[0], ha->nvram->bios_high[1],
-			          ha->nvram->bios_high[2], ha->nvram->bios_high[3],
-			          ha->nvram->bios_low[0], ha->nvram->bios_low[1],
-			          ha->nvram->bios_low[2]);
+		seq_printf(m,
+			  "\tBIOS Version                      : %c%c%c%c%c%c%c\n",
+			  ha->nvram->bios_high[0], ha->nvram->bios_high[1],
+			  ha->nvram->bios_high[2], ha->nvram->bios_high[3],
+			  ha->nvram->bios_low[0], ha->nvram->bios_low[1],
+			  ha->nvram->bios_low[2]);
 
         } else {
-		    copy_info(&info,
-			          "\tBIOS Version                      : %c%c%c%c%c%c%c%c\n",
-			          ha->nvram->bios_high[0], ha->nvram->bios_high[1],
-			          ha->nvram->bios_high[2], ha->nvram->bios_high[3],
-			          ha->nvram->bios_low[0], ha->nvram->bios_low[1],
-			          ha->nvram->bios_low[2], ha->nvram->bios_low[3]);
+		seq_printf(m,
+			  "\tBIOS Version                      : %c%c%c%c%c%c%c%c\n",
+			  ha->nvram->bios_high[0], ha->nvram->bios_high[1],
+			  ha->nvram->bios_high[2], ha->nvram->bios_high[3],
+			  ha->nvram->bios_low[0], ha->nvram->bios_low[1],
+			  ha->nvram->bios_low[2], ha->nvram->bios_low[3]);
         }
 
     }
 
     if (ha->enq->CodeBlkVersion[7] == 0) {
-        copy_info(&info,
-		          "\tFirmware Version                  : %c%c%c%c%c%c%c\n",
-		          ha->enq->CodeBlkVersion[0], ha->enq->CodeBlkVersion[1],
-		          ha->enq->CodeBlkVersion[2], ha->enq->CodeBlkVersion[3],
-		          ha->enq->CodeBlkVersion[4], ha->enq->CodeBlkVersion[5],
-		          ha->enq->CodeBlkVersion[6]);
+        seq_printf(m,
+		  "\tFirmware Version                  : %c%c%c%c%c%c%c\n",
+		  ha->enq->CodeBlkVersion[0], ha->enq->CodeBlkVersion[1],
+		  ha->enq->CodeBlkVersion[2], ha->enq->CodeBlkVersion[3],
+		  ha->enq->CodeBlkVersion[4], ha->enq->CodeBlkVersion[5],
+		  ha->enq->CodeBlkVersion[6]);
     } else {
-        copy_info(&info,
-		          "\tFirmware Version                  : %c%c%c%c%c%c%c%c\n",
-		          ha->enq->CodeBlkVersion[0], ha->enq->CodeBlkVersion[1],
-		          ha->enq->CodeBlkVersion[2], ha->enq->CodeBlkVersion[3],
-		          ha->enq->CodeBlkVersion[4], ha->enq->CodeBlkVersion[5],
-		          ha->enq->CodeBlkVersion[6], ha->enq->CodeBlkVersion[7]);
+	seq_printf(m,
+		  "\tFirmware Version                  : %c%c%c%c%c%c%c%c\n",
+		  ha->enq->CodeBlkVersion[0], ha->enq->CodeBlkVersion[1],
+		  ha->enq->CodeBlkVersion[2], ha->enq->CodeBlkVersion[3],
+		  ha->enq->CodeBlkVersion[4], ha->enq->CodeBlkVersion[5],
+		  ha->enq->CodeBlkVersion[6], ha->enq->CodeBlkVersion[7]);
     }
 
     if (ha->enq->BootBlkVersion[7] == 0) {
-        copy_info(&info,
-		          "\tBoot Block Version                : %c%c%c%c%c%c%c\n",
-		          ha->enq->BootBlkVersion[0], ha->enq->BootBlkVersion[1],
-		          ha->enq->BootBlkVersion[2], ha->enq->BootBlkVersion[3],
-		          ha->enq->BootBlkVersion[4], ha->enq->BootBlkVersion[5],
-		          ha->enq->BootBlkVersion[6]);
+        seq_printf(m,
+		  "\tBoot Block Version                : %c%c%c%c%c%c%c\n",
+		  ha->enq->BootBlkVersion[0], ha->enq->BootBlkVersion[1],
+		  ha->enq->BootBlkVersion[2], ha->enq->BootBlkVersion[3],
+		  ha->enq->BootBlkVersion[4], ha->enq->BootBlkVersion[5],
+		  ha->enq->BootBlkVersion[6]);
     } else {
-        copy_info(&info,
-		          "\tBoot Block Version                : %c%c%c%c%c%c%c%c\n",
-		          ha->enq->BootBlkVersion[0], ha->enq->BootBlkVersion[1],
-		          ha->enq->BootBlkVersion[2], ha->enq->BootBlkVersion[3],
-		          ha->enq->BootBlkVersion[4], ha->enq->BootBlkVersion[5],
-		          ha->enq->BootBlkVersion[6], ha->enq->BootBlkVersion[7]);
+        seq_printf(m,
+		  "\tBoot Block Version                : %c%c%c%c%c%c%c%c\n",
+		  ha->enq->BootBlkVersion[0], ha->enq->BootBlkVersion[1],
+		  ha->enq->BootBlkVersion[2], ha->enq->BootBlkVersion[3],
+		  ha->enq->BootBlkVersion[4], ha->enq->BootBlkVersion[5],
+		  ha->enq->BootBlkVersion[6], ha->enq->BootBlkVersion[7]);
     }
 
-	copy_info(&info, "\tDriver Version                    : %s%s\n",
+	seq_printf(m, "\tDriver Version                    : %s%s\n",
 		  IPS_VERSION_HIGH, IPS_VERSION_LOW);
 
-	copy_info(&info, "\tDriver Build                      : %d\n",
+	seq_printf(m, "\tDriver Build                      : %d\n",
 		  IPS_BUILD_IDENT);
 
-	copy_info(&info, "\tMax Physical Devices              : %d\n",
+	seq_printf(m, "\tMax Physical Devices              : %d\n",
 		  ha->enq->ucMaxPhysicalDevices);
-	copy_info(&info, "\tMax Active Commands               : %d\n",
+	seq_printf(m, "\tMax Active Commands               : %d\n",
 		  ha->max_cmds);
-	copy_info(&info, "\tCurrent Queued Commands           : %d\n",
+	seq_printf(m, "\tCurrent Queued Commands           : %d\n",
 		  ha->scb_waitlist.count);
-	copy_info(&info, "\tCurrent Active Commands           : %d\n",
+	seq_printf(m, "\tCurrent Active Commands           : %d\n",
 		  ha->scb_activelist.count - ha->num_ioctl);
-	copy_info(&info, "\tCurrent Queued PT Commands        : %d\n",
+	seq_printf(m, "\tCurrent Queued PT Commands        : %d\n",
 		  ha->copp_waitlist.count);
-	copy_info(&info, "\tCurrent Active PT Commands        : %d\n",
+	seq_printf(m, "\tCurrent Active PT Commands        : %d\n",
 		  ha->num_ioctl);
 
-	copy_info(&info, "\n");
-
-	return (info.localpos);
-}
-
-/****************************************************************************/
-/*                                                                          */
-/* Routine Name: copy_mem_info                                              */
-/*                                                                          */
-/* Routine Description:                                                     */
-/*                                                                          */
-/*   Copy data into an IPS_INFOSTR structure                                */
-/*                                                                          */
-/****************************************************************************/
-static void
-copy_mem_info(IPS_INFOSTR * info, char *data, int len)
-{
-	METHOD_TRACE("copy_mem_info", 1);
-
-	if (info->pos + len < info->offset) {
-		info->pos += len;
-		return;
-	}
-
-	if (info->pos < info->offset) {
-		data += (info->offset - info->pos);
-		len -= (info->offset - info->pos);
-		info->pos += (info->offset - info->pos);
-	}
-
-	if (info->localpos + len > info->length)
-		len = info->length - info->localpos;
+	seq_printf(m, "\n");
 
-	if (len > 0) {
-		memcpy(info->buffer + info->localpos, data, len);
-		info->pos += len;
-		info->localpos += len;
-	}
-}
-
-/****************************************************************************/
-/*                                                                          */
-/* Routine Name: copy_info                                                  */
-/*                                                                          */
-/* Routine Description:                                                     */
-/*                                                                          */
-/*   printf style wrapper for an info structure                             */
-/*                                                                          */
-/****************************************************************************/
-static int
-copy_info(IPS_INFOSTR * info, char *fmt, ...)
-{
-	va_list args;
-	char buf[128];
-	int len;
-
-	METHOD_TRACE("copy_info", 1);
-
-	va_start(args, fmt);
-	len = vsprintf(buf, fmt, args);
-	va_end(args);
-
-	copy_mem_info(info, buf, len);
-
-	return (len);
+	return 0;
 }
 
 /****************************************************************************/
diff --git a/drivers/scsi/ips.h b/drivers/scsi/ips.h
index f2df059..45b9566 100644
--- a/drivers/scsi/ips.h
+++ b/drivers/scsi/ips.h
@@ -416,7 +416,6 @@
    /*
     * Scsi_Host Template
     */
-   static int ips_proc_info(struct Scsi_Host *, char *, char **, off_t, int, int);
    static int ips_biosparam(struct scsi_device *sdev, struct block_device *bdev,
 		sector_t capacity, int geom[]);
    static int ips_slave_configure(struct scsi_device *SDptr);
@@ -959,14 +958,6 @@ typedef union {
    IPS_ENH_SG_LIST  *enh_list;
 } IPS_SG_LIST;
 
-typedef struct _IPS_INFOSTR {
-   char *buffer;
-   int   length;
-   int   offset;
-   int   pos;
-   int   localpos;
-} IPS_INFOSTR;
-
 typedef struct {
    char *option_name;
    int  *option_flag;
diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c
index 8e561e6..880a906 100644
--- a/drivers/scsi/libfc/fc_disc.c
+++ b/drivers/scsi/libfc/fc_disc.c
@@ -712,12 +712,13 @@ static void fc_disc_stop_final(struct fc_lport *lport)
 }
 
 /**
- * fc_disc_init() - Initialize the discovery layer for a local port
- * @lport: The local port that needs the discovery layer to be initialized
+ * fc_disc_config() - Configure the discovery layer for a local port
+ * @lport: The local port that needs the discovery layer to be configured
+ * @priv: Private data structre for users of the discovery layer
  */
-int fc_disc_init(struct fc_lport *lport)
+void fc_disc_config(struct fc_lport *lport, void *priv)
 {
-	struct fc_disc *disc;
+	struct fc_disc *disc = &lport->disc;
 
 	if (!lport->tt.disc_start)
 		lport->tt.disc_start = fc_disc_start;
@@ -732,12 +733,21 @@ int fc_disc_init(struct fc_lport *lport)
 		lport->tt.disc_recv_req = fc_disc_recv_req;
 
 	disc = &lport->disc;
+
+	disc->priv = priv;
+}
+EXPORT_SYMBOL(fc_disc_config);
+
+/**
+ * fc_disc_init() - Initialize the discovery layer for a local port
+ * @lport: The local port that needs the discovery layer to be initialized
+ */
+void fc_disc_init(struct fc_lport *lport)
+{
+	struct fc_disc *disc = &lport->disc;
+
 	INIT_DELAYED_WORK(&disc->disc_work, fc_disc_timeout);
 	mutex_init(&disc->disc_mutex);
 	INIT_LIST_HEAD(&disc->rports);
-
-	disc->priv = lport;
-
-	return 0;
 }
 EXPORT_SYMBOL(fc_disc_init);
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index aec2e0d..7af7767 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -2151,10 +2151,10 @@ int sas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
 	}
 
 	/* do we need to support multiple segments? */
-	if (req->bio->bi_vcnt > 1 || rsp->bio->bi_vcnt > 1) {
+	if (bio_segments(req->bio) > 1 || bio_segments(rsp->bio) > 1) {
 		printk("%s: multiple segments req %u %u, rsp %u %u\n",
-		       __func__, req->bio->bi_vcnt, blk_rq_bytes(req),
-		       rsp->bio->bi_vcnt, blk_rq_bytes(rsp));
+		       __func__, bio_segments(req->bio), blk_rq_bytes(req),
+		       bio_segments(rsp->bio), blk_rq_bytes(rsp));
 		return -EINVAL;
 	}
 
diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c
index 32d5683..f5d1064 100644
--- a/drivers/scsi/lpfc/lpfc_bsg.c
+++ b/drivers/scsi/lpfc/lpfc_bsg.c
@@ -4741,7 +4741,7 @@ lpfc_bsg_mbox_cmd(struct fc_bsg_job *job)
 	if (job->request_len <
 	    sizeof(struct fc_bsg_request) + sizeof(struct dfc_mbox_req)) {
 		lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
-				"2737 Mix-and-match backward compability "
+				"2737 Mix-and-match backward compatibility "
 				"between MBOX_REQ old size:%d and "
 				"new request size:%d\n",
 				(int)(job->request_len -
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index d7096ad..bfda184 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -1732,7 +1732,7 @@ lpfc_check_pending_fcoe_event(struct lpfc_hba *phba, uint8_t unreg_fcf)
  * use through a sequence of @fcf_cnt eligible FCF records with equal
  * probability. To perform integer manunipulation of random numbers with
  * size unit32_t, the lower 16 bits of the 32-bit random number returned
- * from random32() are taken as the random random number generated.
+ * from prandom_u32() are taken as the random random number generated.
  *
  * Returns true when outcome is for the newly read FCF record should be
  * chosen; otherwise, return false when outcome is for keeping the previously
@@ -1744,7 +1744,7 @@ lpfc_sli4_new_fcf_random_select(struct lpfc_hba *phba, uint32_t fcf_cnt)
 	uint32_t rand_num;
 
 	/* Get 16-bit uniform random number */
-	rand_num = (0xFFFF & random32());
+	rand_num = 0xFFFF & prandom_u32();
 
 	/* Decision with probability 1/fcf_cnt */
 	if ((fcf_cnt * rand_num) < 0xFFFF)
@@ -2380,7 +2380,7 @@ lpfc_mbx_cmpl_fcf_scan_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
 		phba->fcf.eligible_fcf_cnt = 1;
 		/* Seeding the random number generator for random selection */
 		seed = (uint32_t)(0xFFFFFFFF & jiffies);
-		srandom32(seed);
+		prandom_seed(seed);
 	}
 	spin_unlock_irq(&phba->hbalock);
 	goto read_next_fcf;
diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c
index 24828b5..8580757 100644
--- a/drivers/scsi/mac_scsi.c
+++ b/drivers/scsi/mac_scsi.c
@@ -561,7 +561,8 @@ static int macscsi_pwrite (struct Scsi_Host *instance,
 
 static struct scsi_host_template driver_template = {
 	.proc_name			= "Mac5380",
-	.proc_info			= macscsi_proc_info,
+	.show_info			= macscsi_show_info,
+	.write_info			= macscsi_write_info,
 	.name				= "Macintosh NCR5380 SCSI",
 	.detect				= macscsi_detect,
 	.release			= macscsi_release,
diff --git a/drivers/scsi/mac_scsi.h b/drivers/scsi/mac_scsi.h
index d26e331..7dc62fc 100644
--- a/drivers/scsi/mac_scsi.h
+++ b/drivers/scsi/mac_scsi.h
@@ -72,7 +72,8 @@
 #define NCR5380_queue_command macscsi_queue_command
 #define NCR5380_abort macscsi_abort
 #define NCR5380_bus_reset macscsi_bus_reset
-#define NCR5380_proc_info macscsi_proc_info
+#define NCR5380_show_info macscsi_show_info
+#define NCR5380_write_info macscsi_write_info
 
 #define BOARD_NORMAL	0
 #define BOARD_NCR53C400	1
diff --git a/drivers/scsi/mpt2sas/mpt2sas_transport.c b/drivers/scsi/mpt2sas/mpt2sas_transport.c
index 8c2ffbe..193e7ae 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_transport.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_transport.c
@@ -1939,7 +1939,7 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
 	ioc->transport_cmds.status = MPT2_CMD_PENDING;
 
 	/* Check if the request is split across multiple segments */
-	if (req->bio->bi_vcnt > 1) {
+	if (bio_segments(req->bio) > 1) {
 		u32 offset = 0;
 
 		/* Allocate memory and copy the request */
@@ -1971,7 +1971,7 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
 
 	/* Check if the response needs to be populated across
 	 * multiple segments */
-	if (rsp->bio->bi_vcnt > 1) {
+	if (bio_segments(rsp->bio) > 1) {
 		pci_addr_in = pci_alloc_consistent(ioc->pdev, blk_rq_bytes(rsp),
 		    &pci_dma_in);
 		if (!pci_addr_in) {
@@ -2038,7 +2038,7 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
 	sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
 	    MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC);
 	sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
-	if (req->bio->bi_vcnt > 1) {
+	if (bio_segments(req->bio) > 1) {
 		ioc->base_add_sg_single(psge, sgl_flags |
 		    (blk_rq_bytes(req) - 4), pci_dma_out);
 	} else {
@@ -2054,7 +2054,7 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
 	    MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
 	    MPI2_SGE_FLAGS_END_OF_LIST);
 	sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
-	if (rsp->bio->bi_vcnt > 1) {
+	if (bio_segments(rsp->bio) > 1) {
 		ioc->base_add_sg_single(psge, sgl_flags |
 		    (blk_rq_bytes(rsp) + 4), pci_dma_in);
 	} else {
@@ -2099,7 +2099,7 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
 		    le16_to_cpu(mpi_reply->ResponseDataLength);
 		/* check if the resp needs to be copied from the allocated
 		 * pci mem */
-		if (rsp->bio->bi_vcnt > 1) {
+		if (bio_segments(rsp->bio) > 1) {
 			u32 offset = 0;
 			u32 bytes_to_copy =
 			    le16_to_cpu(mpi_reply->ResponseDataLength);
diff --git a/drivers/scsi/mpt3sas/mpt3sas_config.c b/drivers/scsi/mpt3sas/mpt3sas_config.c
index 1df9ed4..4db0c7a 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_config.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_config.c
@@ -148,7 +148,7 @@ _config_display_some_debug(struct MPT3SAS_ADAPTER *ioc, u16 smid,
 			desc = "raid_config";
 			break;
 		case MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING:
-			desc = "driver_mappping";
+			desc = "driver_mapping";
 			break;
 		}
 		break;
diff --git a/drivers/scsi/mvme147.c b/drivers/scsi/mvme147.c
index c29d0db..e7f6661 100644
--- a/drivers/scsi/mvme147.c
+++ b/drivers/scsi/mvme147.c
@@ -76,7 +76,8 @@ int mvme147_detect(struct scsi_host_template *tpnt)
 	called++;
 
 	tpnt->proc_name = "MVME147";
-	tpnt->proc_info = &wd33c93_proc_info;
+	tpnt->show_info = wd33c93_show_info,
+	tpnt->write_info = wd33c93_write_info,
 
 	instance = scsi_register(tpnt, sizeof(struct WD33C93_hostdata));
 	if (!instance)
diff --git a/drivers/scsi/nsp32.c b/drivers/scsi/nsp32.c
index 1cc0c1c..1e3879d 100644
--- a/drivers/scsi/nsp32.c
+++ b/drivers/scsi/nsp32.c
@@ -192,7 +192,7 @@ static int  __init init_nsp32  (void);
 static void __exit exit_nsp32  (void);
 
 /* struct struct scsi_host_template */
-static int         nsp32_proc_info   (struct Scsi_Host *, char *, char **, off_t, int, int);
+static int         nsp32_show_info   (struct seq_file *, struct Scsi_Host *);
 
 static int         nsp32_detect      (struct pci_dev *pdev);
 static int         nsp32_queuecommand(struct Scsi_Host *, struct scsi_cmnd *);
@@ -268,7 +268,7 @@ static void nsp32_dmessage(const char *, int, int,    char *, ...);
 static struct scsi_host_template nsp32_template = {
 	.proc_name			= "nsp32",
 	.name				= "Workbit NinjaSCSI-32Bi/UDE",
-	.proc_info			= nsp32_proc_info,
+	.show_info			= nsp32_show_info,
 	.info				= nsp32_info,
 	.queuecommand			= nsp32_queuecommand,
 	.can_queue			= 1,
@@ -1442,19 +1442,10 @@ static irqreturn_t do_nsp32_isr(int irq, void *dev_id)
 }
 
 #undef SPRINTF
-#define SPRINTF(args...) \
-	do { \
-		if(length > (pos - buffer)) { \
-			pos += snprintf(pos, length - (pos - buffer) + 1, ## args); \
-			nsp32_dbg(NSP32_DEBUG_PROC, "buffer=0x%p pos=0x%p length=%d %d\n", buffer, pos, length,  length - (pos - buffer));\
-		} \
-	} while(0)
-
-static int nsp32_proc_info(struct Scsi_Host *host, char *buffer, char **start,
-			   off_t offset, int length, int inout)
+#define SPRINTF(args...) seq_printf(m, ##args)
+
+static int nsp32_show_info(struct seq_file *m, struct Scsi_Host *host)
 {
-	char             *pos = buffer;
-	int               thislength;
 	unsigned long     flags;
 	nsp32_hw_data    *data;
 	int               hostno;
@@ -1463,11 +1454,6 @@ static int nsp32_proc_info(struct Scsi_Host *host, char *buffer, char **start,
 	int               id, speed;
 	long              model;
 
-	/* Write is not supported, just return. */
-	if (inout == TRUE) {
-		return -EINVAL;
-	}
-
 	hostno = host->host_no;
 	data = (nsp32_hw_data *)host->hostdata;
 	base = host->io_port;
@@ -1527,20 +1513,7 @@ static int nsp32_proc_info(struct Scsi_Host *host, char *buffer, char **start,
 		}
 		SPRINTF("\n");
 	}
-
-
-	thislength = pos - (buffer + offset);
-
-	if(thislength < 0) {
-		*start = NULL;
-                return 0;
-        }
-
-
-	thislength = min(thislength, length);
-	*start = buffer + offset;
-
-	return thislength;
+	return 0;
 }
 #undef SPRINTF
 
diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
index d8293f2..aa66361 100644
--- a/drivers/scsi/osd/osd_initiator.c
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -1049,7 +1049,7 @@ static struct bio *_create_sg_bios(struct osd_request *or,
 
 	bio = bio_kmalloc(GFP_KERNEL, numentries);
 	if (unlikely(!bio)) {
-		OSD_DEBUG("Faild to allocate BIO size=%u\n", numentries);
+		OSD_DEBUG("Failed to allocate BIO size=%u\n", numentries);
 		return ERR_PTR(-ENOMEM);
 	}
 
diff --git a/drivers/scsi/pas16.c b/drivers/scsi/pas16.c
index 2f72c98..62f1a60 100644
--- a/drivers/scsi/pas16.c
+++ b/drivers/scsi/pas16.c
@@ -388,7 +388,8 @@ int __init pas16_detect(struct scsi_host_template * tpnt)
     int  count;
 
     tpnt->proc_name = "pas16";
-    tpnt->proc_info = &pas16_proc_info;
+    tpnt->show_info = pas16_show_info;
+    tpnt->write_info = pas16_write_info;
 
     if (pas16_addr != 0) {
 	overrides[0].io_port = pas16_addr;
diff --git a/drivers/scsi/pas16.h b/drivers/scsi/pas16.h
index a04281c..3721342 100644
--- a/drivers/scsi/pas16.h
+++ b/drivers/scsi/pas16.h
@@ -163,7 +163,8 @@ static int pas16_bus_reset(Scsi_Cmnd *);
 #define NCR5380_queue_command pas16_queue_command
 #define NCR5380_abort pas16_abort
 #define NCR5380_bus_reset pas16_bus_reset
-#define NCR5380_proc_info pas16_proc_info
+#define NCR5380_show_info pas16_show_info
+#define NCR5380_write_info pas16_write_info
 
 /* 15 14 12 10 7 5 3 
    1101 0100 1010 1000 */
diff --git a/drivers/scsi/pcmcia/aha152x_stub.c b/drivers/scsi/pcmcia/aha152x_stub.c
index 7d1609f..df82a34 100644
--- a/drivers/scsi/pcmcia/aha152x_stub.c
+++ b/drivers/scsi/pcmcia/aha152x_stub.c
@@ -220,16 +220,4 @@ static struct pcmcia_driver aha152x_cs_driver = {
 	.id_table       = aha152x_ids,
 	.resume		= aha152x_resume,
 };
-
-static int __init init_aha152x_cs(void)
-{
-	return pcmcia_register_driver(&aha152x_cs_driver);
-}
-
-static void __exit exit_aha152x_cs(void)
-{
-	pcmcia_unregister_driver(&aha152x_cs_driver);
-}
-
-module_init(init_aha152x_cs);
-module_exit(exit_aha152x_cs);
+module_pcmcia_driver(aha152x_cs_driver);
diff --git a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c
index 714b248..ba84769 100644
--- a/drivers/scsi/pcmcia/fdomain_stub.c
+++ b/drivers/scsi/pcmcia/fdomain_stub.c
@@ -194,16 +194,4 @@ static struct pcmcia_driver fdomain_cs_driver = {
 	.id_table       = fdomain_ids,
 	.resume		= fdomain_resume,
 };
-
-static int __init init_fdomain_cs(void)
-{
-	return pcmcia_register_driver(&fdomain_cs_driver);
-}
-
-static void __exit exit_fdomain_cs(void)
-{
-	pcmcia_unregister_driver(&fdomain_cs_driver);
-}
-
-module_init(init_fdomain_cs);
-module_exit(exit_fdomain_cs);
+module_pcmcia_driver(fdomain_cs_driver);
diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c
index b61a753..79f8eb4 100644
--- a/drivers/scsi/pcmcia/nsp_cs.c
+++ b/drivers/scsi/pcmcia/nsp_cs.c
@@ -76,7 +76,7 @@ MODULE_PARM_DESC(free_ports, "Release IO ports after configuration? (default: 0
 
 static struct scsi_host_template nsp_driver_template = {
 	.proc_name	         = "nsp_cs",
-	.proc_info		 = nsp_proc_info,
+	.show_info		 = nsp_show_info,
 	.name			 = "WorkBit NinjaSCSI-3/32Bi(16bit)",
 	.info			 = nsp_info,
 	.queuecommand		 = nsp_queuecommand,
@@ -1365,33 +1365,19 @@ static const char *nsp_info(struct Scsi_Host *shpnt)
 }
 
 #undef SPRINTF
-#define SPRINTF(args...) \
-        do { \
-		if(length > (pos - buffer)) { \
-			pos += snprintf(pos, length - (pos - buffer) + 1, ## args); \
-			nsp_dbg(NSP_DEBUG_PROC, "buffer=0x%p pos=0x%p length=%d %d\n", buffer, pos, length,  length - (pos - buffer));\
-		} \
-	} while(0)
-
-static int nsp_proc_info(struct Scsi_Host *host, char *buffer, char **start,
-			 off_t offset, int length, int inout)
+#define SPRINTF(args...) seq_printf(m, ##args)
+
+static int nsp_show_info(struct seq_file *m, struct Scsi_Host *host)
 {
 	int id;
-	char *pos = buffer;
-	int thislength;
 	int speed;
 	unsigned long flags;
 	nsp_hw_data *data;
 	int hostno;
 
-	if (inout) {
-		return -EINVAL;
-	}
-
 	hostno = host->host_no;
 	data = (nsp_hw_data *)host->hostdata;
 
-
 	SPRINTF("NinjaSCSI status\n\n");
 	SPRINTF("Driver version:        $Revision: 1.23 $\n");
 	SPRINTF("SCSI host No.:         %d\n",          hostno);
@@ -1458,19 +1444,7 @@ static int nsp_proc_info(struct Scsi_Host *host, char *buffer, char **start,
 		}
 		SPRINTF("\n");
 	}
-
-	thislength = pos - (buffer + offset);
-
-	if(thislength < 0) {
-		*start = NULL;
-                return 0;
-        }
-
-
-	thislength = min(thislength, length);
-	*start = buffer + offset;
-
-	return thislength;
+	return 0;
 }
 #undef SPRINTF
 
@@ -1773,19 +1747,4 @@ static struct pcmcia_driver nsp_driver = {
 	.suspend	= nsp_cs_suspend,
 	.resume		= nsp_cs_resume,
 };
-
-static int __init nsp_cs_init(void)
-{
-	return pcmcia_register_driver(&nsp_driver);
-}
-
-static void __exit nsp_cs_exit(void)
-{
-	pcmcia_unregister_driver(&nsp_driver);
-}
-
-
-module_init(nsp_cs_init)
-module_exit(nsp_cs_exit)
-
-/* end */
+module_pcmcia_driver(nsp_driver);
diff --git a/drivers/scsi/pcmcia/nsp_cs.h b/drivers/scsi/pcmcia/nsp_cs.h
index 7fc9a9d..afd64f0 100644
--- a/drivers/scsi/pcmcia/nsp_cs.h
+++ b/drivers/scsi/pcmcia/nsp_cs.h
@@ -292,13 +292,8 @@ static int        nsp_cs_config (struct pcmcia_device *link);
 /* Linux SCSI subsystem specific functions */
 static struct Scsi_Host *nsp_detect     (struct scsi_host_template *sht);
 static const  char      *nsp_info       (struct Scsi_Host *shpnt);
-static        int        nsp_proc_info  (
-	                                 struct Scsi_Host *host,
-					 char   *buffer,
-					 char  **start,
-					 off_t   offset,
-					 int     length,
-					 int     inout);
+static        int        nsp_show_info  (struct seq_file *m,
+	                                 struct Scsi_Host *host);
 static int nsp_queuecommand(struct Scsi_Host *h, struct scsi_cmnd *SCpnt);
 
 /* Error handler */
diff --git a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c
index bcaf89f..8d4fdc2 100644
--- a/drivers/scsi/pcmcia/qlogic_stub.c
+++ b/drivers/scsi/pcmcia/qlogic_stub.c
@@ -300,19 +300,8 @@ static struct pcmcia_driver qlogic_cs_driver = {
 	.id_table       = qlogic_ids,
 	.resume		= qlogic_resume,
 };
-
-static int __init init_qlogic_cs(void)
-{
-	return pcmcia_register_driver(&qlogic_cs_driver);
-}
-
-static void __exit exit_qlogic_cs(void)
-{
-	pcmcia_unregister_driver(&qlogic_cs_driver);
-}
+module_pcmcia_driver(qlogic_cs_driver);
 
 MODULE_AUTHOR("Tom Zerucha, Michael Griffith");
 MODULE_DESCRIPTION("Driver for the PCMCIA Qlogic FAS SCSI controllers");
 MODULE_LICENSE("GPL");
-module_init(init_qlogic_cs);
-module_exit(exit_qlogic_cs);
diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c
index f5b5273..55b0b2b 100644
--- a/drivers/scsi/pcmcia/sym53c500_cs.c
+++ b/drivers/scsi/pcmcia/sym53c500_cs.c
@@ -881,18 +881,4 @@ static struct pcmcia_driver sym53c500_cs_driver = {
 	.id_table       = sym53c500_ids,
 	.resume		= sym53c500_resume,
 };
-
-static int __init
-init_sym53c500_cs(void)
-{
-	return pcmcia_register_driver(&sym53c500_cs_driver);
-}
-
-static void __exit
-exit_sym53c500_cs(void)
-{
-	pcmcia_unregister_driver(&sym53c500_cs_driver);
-}
-
-module_init(init_sym53c500_cs);
-module_exit(exit_sym53c500_cs);
+module_pcmcia_driver(sym53c500_cs_driver);
diff --git a/drivers/scsi/ppa.c b/drivers/scsi/ppa.c
index d164c96..1db8b26 100644
--- a/drivers/scsi/ppa.c
+++ b/drivers/scsi/ppa.c
@@ -118,8 +118,9 @@ static inline void ppa_pb_release(ppa_struct *dev)
  * Also gives a method to use a script to obtain optimum timings (TODO)
  */
 
-static inline int ppa_proc_write(ppa_struct *dev, char *buffer, int length)
+static inline int ppa_write_info(struct Scsi_Host *host, char *buffer, int length)
 {
+	ppa_struct *dev = ppa_dev(host);
 	unsigned long x;
 
 	if ((length > 5) && (strncmp(buffer, "mode=", 5) == 0)) {
@@ -137,35 +138,17 @@ static inline int ppa_proc_write(ppa_struct *dev, char *buffer, int length)
 	return -EINVAL;
 }
 
-static int ppa_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, int length, int inout)
+static int ppa_show_info(struct seq_file *m, struct Scsi_Host *host)
 {
-	int len = 0;
 	ppa_struct *dev = ppa_dev(host);
 
-	if (inout)
-		return ppa_proc_write(dev, buffer, length);
-
-	len += sprintf(buffer + len, "Version : %s\n", PPA_VERSION);
-	len +=
-	    sprintf(buffer + len, "Parport : %s\n",
-		    dev->dev->port->name);
-	len +=
-	    sprintf(buffer + len, "Mode    : %s\n",
-		    PPA_MODE_STRING[dev->mode]);
+	seq_printf(m, "Version : %s\n", PPA_VERSION);
+	seq_printf(m, "Parport : %s\n", dev->dev->port->name);
+	seq_printf(m, "Mode    : %s\n", PPA_MODE_STRING[dev->mode]);
 #if PPA_DEBUG > 0
-	len +=
-	    sprintf(buffer + len, "recon_tmo : %lu\n", dev->recon_tmo);
+	seq_printf(m, "recon_tmo : %lu\n", dev->recon_tmo);
 #endif
-
-	/* Request for beyond end of buffer */
-	if (offset > length)
-		return 0;
-
-	*start = buffer + offset;
-	len -= offset;
-	if (len > length)
-		len = length;
-	return len;
+	return 0;
 }
 
 static int device_check(ppa_struct *dev);
@@ -981,7 +964,8 @@ static int ppa_adjust_queue(struct scsi_device *device)
 static struct scsi_host_template ppa_template = {
 	.module			= THIS_MODULE,
 	.proc_name		= "ppa",
-	.proc_info		= ppa_proc_info,
+	.show_info		= ppa_show_info,
+	.write_info		= ppa_write_info,
 	.name			= "Iomega VPI0 (ppa) interface",
 	.queuecommand		= ppa_queuecommand,
 	.eh_abort_handler	= ppa_abort,
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index 1d82eef..e44d47e 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -1939,10 +1939,13 @@ qla24xx_vport_delete(struct fc_vport *fc_vport)
 	}
 
 	/* No pending activities shall be there on the vha now */
-	if (ql2xextended_error_logging & ql_dbg_user)
-		msleep(random32()%10);  /* Just to see if something falls on
-					* the net we have placed below */
-
+	if (ql2xextended_error_logging & ql_dbg_user) {
+		/*
+		 * Just to see if something falls on the net we have placed
+		 * below
+		 */
+		msleep(prandom_u32() % 10);
+	}
 	BUG_ON(atomic_read(&vha->vref_count));
 
 	qla2x00_free_fcports(vha);
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index 61b5d8c..fcdc223 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -2585,25 +2585,6 @@ static void qlt_do_ctio_completion(struct scsi_qla_host *vha, uint32_t handle,
 	ha->tgt.tgt_ops->free_cmd(cmd);
 }
 
-/* ha->hardware_lock supposed to be held on entry */
-/* called via callback from qla2xxx */
-void qlt_ctio_completion(struct scsi_qla_host *vha, uint32_t handle)
-{
-	struct qla_hw_data *ha = vha->hw;
-	struct qla_tgt *tgt = ha->tgt.qla_tgt;
-
-	if (likely(tgt == NULL)) {
-		ql_dbg(ql_dbg_tgt, vha, 0xe021,
-		    "CTIO, but target mode not enabled"
-		    " (ha %d %p handle %#x)", vha->vp_idx, ha, handle);
-		return;
-	}
-
-	tgt->irq_cmd_count++;
-	qlt_do_ctio_completion(vha, handle, CTIO_SUCCESS, NULL);
-	tgt->irq_cmd_count--;
-}
-
 static inline int qlt_get_fcp_task_attr(struct scsi_qla_host *vha,
 	uint8_t task_codes)
 {
diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h
index ff9ccb9..b33e411 100644
--- a/drivers/scsi/qla2xxx/qla_target.h
+++ b/drivers/scsi/qla2xxx/qla_target.h
@@ -980,7 +980,6 @@ extern int qlt_xmit_response(struct qla_tgt_cmd *, int, uint8_t);
 extern void qlt_xmit_tm_rsp(struct qla_tgt_mgmt_cmd *);
 extern void qlt_free_mcmd(struct qla_tgt_mgmt_cmd *);
 extern void qlt_free_cmd(struct qla_tgt_cmd *cmd);
-extern void qlt_ctio_completion(struct scsi_qla_host *, uint32_t);
 extern void qlt_async_event(uint16_t, struct scsi_qla_host *, uint16_t *);
 extern void qlt_enable_vha(struct scsi_qla_host *);
 extern void qlt_vport_create(struct scsi_qla_host *, struct qla_hw_data *);
diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c
index 71d3d23..9299400 100644
--- a/drivers/scsi/qla4xxx/ql4_nx.c
+++ b/drivers/scsi/qla4xxx/ql4_nx.c
@@ -2089,7 +2089,7 @@ static int qla4_8xxx_minidump_process_rdmem(struct scsi_qla_host *ha,
 
 	if (r_addr & 0xf) {
 		DEBUG2(ql4_printk(KERN_INFO, ha,
-				  "[%s]: Read addr 0x%x not 16 bytes alligned\n",
+				  "[%s]: Read addr 0x%x not 16 bytes aligned\n",
 				  __func__, r_addr));
 		return QLA_ERROR;
 	}
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 5cda11c..5add6f4 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -2823,31 +2823,27 @@ static const char * scsi_debug_info(struct Scsi_Host * shp)
 /* scsi_debug_proc_info
  * Used if the driver currently has no own support for /proc/scsi
  */
-static int scsi_debug_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
-				int length, int inout)
+static int scsi_debug_write_info(struct Scsi_Host *host, char *buffer, int length)
 {
-	int len, pos, begin;
-	int orig_length;
+	char arr[16];
+	int opts;
+	int minLen = length > 15 ? 15 : length;
 
-	orig_length = length;
-
-	if (inout == 1) {
-		char arr[16];
-		int minLen = length > 15 ? 15 : length;
+	if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
+		return -EACCES;
+	memcpy(arr, buffer, minLen);
+	arr[minLen] = '\0';
+	if (1 != sscanf(arr, "%d", &opts))
+		return -EINVAL;
+	scsi_debug_opts = opts;
+	if (scsi_debug_every_nth != 0)
+		scsi_debug_cmnd_count = 0;
+	return length;
+}
 
-		if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
-			return -EACCES;
-		memcpy(arr, buffer, minLen);
-		arr[minLen] = '\0';
-		if (1 != sscanf(arr, "%d", &pos))
-			return -EINVAL;
-		scsi_debug_opts = pos;
-		if (scsi_debug_every_nth != 0)
-                        scsi_debug_cmnd_count = 0;
-		return length;
-	}
-	begin = 0;
-	pos = len = sprintf(buffer, "scsi_debug adapter driver, version "
+static int scsi_debug_show_info(struct seq_file *m, struct Scsi_Host *host)
+{
+	seq_printf(m, "scsi_debug adapter driver, version "
 	    "%s [%s]\n"
 	    "num_tgts=%d, shared (ram) size=%d MB, opts=0x%x, "
 	    "every_nth=%d(curr:%d)\n"
@@ -2862,15 +2858,7 @@ static int scsi_debug_proc_info(struct Scsi_Host *host, char *buffer, char **sta
 	    scsi_debug_sector_size, sdebug_cylinders_per, sdebug_heads,
 	    sdebug_sectors_per, num_aborts, num_dev_resets, num_bus_resets,
 	    num_host_resets, dix_reads, dix_writes, dif_errors);
-	if (pos < offset) {
-		len = 0;
-		begin = pos;
-	}
-	*start = buffer + (offset - begin);	/* Start of wanted data */
-	len -= (offset - begin);
-	if (len > length)
-		len = length;
-	return len;
+	return 0;
 }
 
 static ssize_t sdebug_delay_show(struct device_driver * ddp, char * buf)
@@ -3957,7 +3945,8 @@ write:
 static DEF_SCSI_QCMD(scsi_debug_queuecommand)
 
 static struct scsi_host_template sdebug_driver_template = {
-	.proc_info =		scsi_debug_proc_info,
+	.show_info =		scsi_debug_show_info,
+	.write_info =		scsi_debug_write_info,
 	.proc_name =		sdebug_proc_name,
 	.name =			"SCSI DEBUG",
 	.info =			scsi_debug_info,
diff --git a/drivers/scsi/scsi_netlink.c b/drivers/scsi/scsi_netlink.c
index 65123a2..fe30ea9 100644
--- a/drivers/scsi/scsi_netlink.c
+++ b/drivers/scsi/scsi_netlink.c
@@ -50,7 +50,7 @@ scsi_nl_rcv_msg(struct sk_buff *skb)
 	u32 rlen;
 	int err, tport;
 
-	while (skb->len >= NLMSG_SPACE(0)) {
+	while (skb->len >= NLMSG_HDRLEN) {
 		err = 0;
 
 		nlh = nlmsg_hdr(skb);
@@ -70,7 +70,7 @@ scsi_nl_rcv_msg(struct sk_buff *skb)
 			goto next_msg;
 		}
 
-		hdr = NLMSG_DATA(nlh);
+		hdr = nlmsg_data(nlh);
 		if ((hdr->version != SCSI_NL_VERSION) ||
 		    (hdr->magic != SCSI_NL_MAGIC)) {
 			err = -EPROTOTYPE;
diff --git a/drivers/scsi/scsi_proc.c b/drivers/scsi/scsi_proc.c
index ad747dc..db66357 100644
--- a/drivers/scsi/scsi_proc.c
+++ b/drivers/scsi/scsi_proc.c
@@ -45,58 +45,50 @@ static struct proc_dir_entry *proc_scsi;
 /* Protect sht->present and sht->proc_dir */
 static DEFINE_MUTEX(global_host_template_mutex);
 
-/**
- * proc_scsi_read - handle read from /proc by calling host's proc_info() command
- * @buffer: passed to proc_info
- * @start: passed to proc_info
- * @offset: passed to proc_info
- * @length: passed to proc_info
- * @eof: returns whether length read was less than requested
- * @data: pointer to a &struct Scsi_Host
- */
-
-static int proc_scsi_read(char *buffer, char **start, off_t offset,
-			  int length, int *eof, void *data)
-{
-	struct Scsi_Host *shost = data;
-	int n;
-
-	n = shost->hostt->proc_info(shost, buffer, start, offset, length, 0);
-	*eof = (n < length);
-
-	return n;
-}
-
-/**
- * proc_scsi_write_proc - Handle write to /proc by calling host's proc_info()
- * @file: not used
- * @buf: source of data to write.
- * @count: number of bytes (at most PROC_BLOCK_SIZE) to write.
- * @data: pointer to &struct Scsi_Host
- */
-static int proc_scsi_write_proc(struct file *file, const char __user *buf,
-                           unsigned long count, void *data)
+static ssize_t proc_scsi_host_write(struct file *file, const char __user *buf,
+                           size_t count, loff_t *ppos)
 {
-	struct Scsi_Host *shost = data;
+	struct Scsi_Host *shost = PDE_DATA(file_inode(file));
 	ssize_t ret = -ENOMEM;
 	char *page;
-	char *start;
     
 	if (count > PROC_BLOCK_SIZE)
 		return -EOVERFLOW;
 
+	if (!shost->hostt->write_info)
+		return -EINVAL;
+
 	page = (char *)__get_free_page(GFP_KERNEL);
 	if (page) {
 		ret = -EFAULT;
 		if (copy_from_user(page, buf, count))
 			goto out;
-		ret = shost->hostt->proc_info(shost, page, &start, 0, count, 1);
+		ret = shost->hostt->write_info(shost, page, count);
 	}
 out:
 	free_page((unsigned long)page);
 	return ret;
 }
 
+static int proc_scsi_show(struct seq_file *m, void *v)
+{
+	struct Scsi_Host *shost = m->private;
+	return shost->hostt->show_info(m, shost);
+}
+
+static int proc_scsi_host_open(struct inode *inode, struct file *file)
+{
+	return single_open_size(file, proc_scsi_show, PDE_DATA(inode),
+				4 * PAGE_SIZE);
+}
+
+static const struct file_operations proc_scsi_fops = {
+	.open = proc_scsi_host_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.write = proc_scsi_host_write
+};
+
 /**
  * scsi_proc_hostdir_add - Create directory in /proc for a scsi host
  * @sht: owner of this directory
@@ -106,7 +98,7 @@ out:
 
 void scsi_proc_hostdir_add(struct scsi_host_template *sht)
 {
-	if (!sht->proc_info)
+	if (!sht->show_info)
 		return;
 
 	mutex_lock(&global_host_template_mutex);
@@ -125,7 +117,7 @@ void scsi_proc_hostdir_add(struct scsi_host_template *sht)
  */
 void scsi_proc_hostdir_rm(struct scsi_host_template *sht)
 {
-	if (!sht->proc_info)
+	if (!sht->show_info)
 		return;
 
 	mutex_lock(&global_host_template_mutex);
@@ -151,16 +143,12 @@ void scsi_proc_host_add(struct Scsi_Host *shost)
 		return;
 
 	sprintf(name,"%d", shost->host_no);
-	p = create_proc_read_entry(name, S_IFREG | S_IRUGO | S_IWUSR,
-			sht->proc_dir, proc_scsi_read, shost);
-	if (!p) {
+	p = proc_create_data(name, S_IRUGO | S_IWUSR,
+		sht->proc_dir, &proc_scsi_fops, shost);
+	if (!p)
 		printk(KERN_ERR "%s: Failed to register host %d in"
 		       "%s\n", __func__, shost->host_no,
 		       sht->proc_name);
-		return;
-	} 
-
-	p->write_proc = proc_scsi_write_proc;
 }
 
 /**
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index e894ca7..e106c27 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -35,7 +35,6 @@
 #include <scsi/scsi_transport.h>
 #include <scsi/scsi_transport_fc.h>
 #include <scsi/scsi_cmnd.h>
-#include <linux/netlink.h>
 #include <net/netlink.h>
 #include <scsi/scsi_netlink_fc.h>
 #include <scsi/scsi_bsg_fc.h>
@@ -534,7 +533,7 @@ fc_host_post_event(struct Scsi_Host *shost, u32 event_number,
 	struct nlmsghdr	*nlh;
 	struct fc_nl_event *event;
 	const char *name;
-	u32 len, skblen;
+	u32 len;
 	int err;
 
 	if (!scsi_nl_sock) {
@@ -543,21 +542,19 @@ fc_host_post_event(struct Scsi_Host *shost, u32 event_number,
 	}
 
 	len = FC_NL_MSGALIGN(sizeof(*event));
-	skblen = NLMSG_SPACE(len);
 
-	skb = alloc_skb(skblen, GFP_KERNEL);
+	skb = nlmsg_new(len, GFP_KERNEL);
 	if (!skb) {
 		err = -ENOBUFS;
 		goto send_fail;
 	}
 
-	nlh = nlmsg_put(skb, 0, 0, SCSI_TRANSPORT_MSG,
-				skblen - sizeof(*nlh), 0);
+	nlh = nlmsg_put(skb, 0, 0, SCSI_TRANSPORT_MSG, len, 0);
 	if (!nlh) {
 		err = -ENOBUFS;
 		goto send_fail_skb;
 	}
-	event = NLMSG_DATA(nlh);
+	event = nlmsg_data(nlh);
 
 	INIT_SCSI_NL_HDR(&event->snlh, SCSI_NL_TRANSPORT_FC,
 				FC_NL_ASYNC_EVENT, len);
@@ -604,7 +601,7 @@ fc_host_post_vendor_event(struct Scsi_Host *shost, u32 event_number,
 	struct sk_buff *skb;
 	struct nlmsghdr	*nlh;
 	struct fc_nl_event *event;
-	u32 len, skblen;
+	u32 len;
 	int err;
 
 	if (!scsi_nl_sock) {
@@ -613,21 +610,19 @@ fc_host_post_vendor_event(struct Scsi_Host *shost, u32 event_number,
 	}
 
 	len = FC_NL_MSGALIGN(sizeof(*event) + data_len);
-	skblen = NLMSG_SPACE(len);
 
-	skb = alloc_skb(skblen, GFP_KERNEL);
+	skb = nlmsg_new(len, GFP_KERNEL);
 	if (!skb) {
 		err = -ENOBUFS;
 		goto send_vendor_fail;
 	}
 
-	nlh = nlmsg_put(skb, 0, 0, SCSI_TRANSPORT_MSG,
-				skblen - sizeof(*nlh), 0);
+	nlh = nlmsg_put(skb, 0, 0, SCSI_TRANSPORT_MSG, len, 0);
 	if (!nlh) {
 		err = -ENOBUFS;
 		goto send_vendor_fail_skb;
 	}
-	event = NLMSG_DATA(nlh);
+	event = nlmsg_data(nlh);
 
 	INIT_SCSI_NL_HDR(&event->snlh, SCSI_NL_TRANSPORT_FC,
 				FC_NL_ASYNC_EVENT, len);
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index 0a74b97..2e38165 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -1344,8 +1344,8 @@ int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr,
 	struct iscsi_uevent *ev;
 	char *pdu;
 	struct iscsi_internal *priv;
-	int len = NLMSG_SPACE(sizeof(*ev) + sizeof(struct iscsi_hdr) +
-			      data_size);
+	int len = nlmsg_total_size(sizeof(*ev) + sizeof(struct iscsi_hdr) +
+				   data_size);
 
 	priv = iscsi_if_transport_lookup(conn->transport);
 	if (!priv)
@@ -1360,7 +1360,7 @@ int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr,
 	}
 
 	nlh = __nlmsg_put(skb, 0, 0, 0, (len - sizeof(*nlh)), 0);
-	ev = NLMSG_DATA(nlh);
+	ev = nlmsg_data(nlh);
 	memset(ev, 0, sizeof(*ev));
 	ev->transport_handle = iscsi_handle(conn->transport);
 	ev->type = ISCSI_KEVENT_RECV_PDU;
@@ -1381,7 +1381,7 @@ int iscsi_offload_mesg(struct Scsi_Host *shost,
 	struct nlmsghdr	*nlh;
 	struct sk_buff *skb;
 	struct iscsi_uevent *ev;
-	int len = NLMSG_SPACE(sizeof(*ev) + data_size);
+	int len = nlmsg_total_size(sizeof(*ev) + data_size);
 
 	skb = alloc_skb(len, GFP_ATOMIC);
 	if (!skb) {
@@ -1390,7 +1390,7 @@ int iscsi_offload_mesg(struct Scsi_Host *shost,
 	}
 
 	nlh = __nlmsg_put(skb, 0, 0, 0, (len - sizeof(*nlh)), 0);
-	ev = NLMSG_DATA(nlh);
+	ev = nlmsg_data(nlh);
 	memset(ev, 0, sizeof(*ev));
 	ev->type = type;
 	ev->transport_handle = iscsi_handle(transport);
@@ -1415,7 +1415,7 @@ void iscsi_conn_error_event(struct iscsi_cls_conn *conn, enum iscsi_err error)
 	struct sk_buff	*skb;
 	struct iscsi_uevent *ev;
 	struct iscsi_internal *priv;
-	int len = NLMSG_SPACE(sizeof(*ev));
+	int len = nlmsg_total_size(sizeof(*ev));
 
 	priv = iscsi_if_transport_lookup(conn->transport);
 	if (!priv)
@@ -1429,7 +1429,7 @@ void iscsi_conn_error_event(struct iscsi_cls_conn *conn, enum iscsi_err error)
 	}
 
 	nlh = __nlmsg_put(skb, 0, 0, 0, (len - sizeof(*nlh)), 0);
-	ev = NLMSG_DATA(nlh);
+	ev = nlmsg_data(nlh);
 	ev->transport_handle = iscsi_handle(conn->transport);
 	ev->type = ISCSI_KEVENT_CONN_ERROR;
 	ev->r.connerror.error = error;
@@ -1450,7 +1450,7 @@ void iscsi_conn_login_event(struct iscsi_cls_conn *conn,
 	struct sk_buff  *skb;
 	struct iscsi_uevent *ev;
 	struct iscsi_internal *priv;
-	int len = NLMSG_SPACE(sizeof(*ev));
+	int len = nlmsg_total_size(sizeof(*ev));
 
 	priv = iscsi_if_transport_lookup(conn->transport);
 	if (!priv)
@@ -1464,7 +1464,7 @@ void iscsi_conn_login_event(struct iscsi_cls_conn *conn,
 	}
 
 	nlh = __nlmsg_put(skb, 0, 0, 0, (len - sizeof(*nlh)), 0);
-	ev = NLMSG_DATA(nlh);
+	ev = nlmsg_data(nlh);
 	ev->transport_handle = iscsi_handle(conn->transport);
 	ev->type = ISCSI_KEVENT_CONN_LOGIN_STATE;
 	ev->r.conn_login.state = state;
@@ -1484,7 +1484,7 @@ void iscsi_post_host_event(uint32_t host_no, struct iscsi_transport *transport,
 	struct nlmsghdr *nlh;
 	struct sk_buff *skb;
 	struct iscsi_uevent *ev;
-	int len = NLMSG_SPACE(sizeof(*ev) + data_size);
+	int len = nlmsg_total_size(sizeof(*ev) + data_size);
 
 	skb = alloc_skb(len, GFP_NOIO);
 	if (!skb) {
@@ -1494,7 +1494,7 @@ void iscsi_post_host_event(uint32_t host_no, struct iscsi_transport *transport,
 	}
 
 	nlh = __nlmsg_put(skb, 0, 0, 0, (len - sizeof(*nlh)), 0);
-	ev = NLMSG_DATA(nlh);
+	ev = nlmsg_data(nlh);
 	ev->transport_handle = iscsi_handle(transport);
 	ev->type = ISCSI_KEVENT_HOST_EVENT;
 	ev->r.host_event.host_no = host_no;
@@ -1515,7 +1515,7 @@ void iscsi_ping_comp_event(uint32_t host_no, struct iscsi_transport *transport,
 	struct nlmsghdr *nlh;
 	struct sk_buff *skb;
 	struct iscsi_uevent *ev;
-	int len = NLMSG_SPACE(sizeof(*ev) + data_size);
+	int len = nlmsg_total_size(sizeof(*ev) + data_size);
 
 	skb = alloc_skb(len, GFP_NOIO);
 	if (!skb) {
@@ -1524,7 +1524,7 @@ void iscsi_ping_comp_event(uint32_t host_no, struct iscsi_transport *transport,
 	}
 
 	nlh = __nlmsg_put(skb, 0, 0, 0, (len - sizeof(*nlh)), 0);
-	ev = NLMSG_DATA(nlh);
+	ev = nlmsg_data(nlh);
 	ev->transport_handle = iscsi_handle(transport);
 	ev->type = ISCSI_KEVENT_PING_COMP;
 	ev->r.ping_comp.host_no = host_no;
@@ -1543,7 +1543,7 @@ iscsi_if_send_reply(uint32_t group, int seq, int type, int done, int multi,
 {
 	struct sk_buff	*skb;
 	struct nlmsghdr	*nlh;
-	int len = NLMSG_SPACE(size);
+	int len = nlmsg_total_size(size);
 	int flags = multi ? NLM_F_MULTI : 0;
 	int t = done ? NLMSG_DONE : type;
 
@@ -1555,24 +1555,24 @@ iscsi_if_send_reply(uint32_t group, int seq, int type, int done, int multi,
 
 	nlh = __nlmsg_put(skb, 0, 0, t, (len - sizeof(*nlh)), 0);
 	nlh->nlmsg_flags = flags;
-	memcpy(NLMSG_DATA(nlh), payload, size);
+	memcpy(nlmsg_data(nlh), payload, size);
 	return iscsi_multicast_skb(skb, group, GFP_ATOMIC);
 }
 
 static int
 iscsi_if_get_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh)
 {
-	struct iscsi_uevent *ev = NLMSG_DATA(nlh);
+	struct iscsi_uevent *ev = nlmsg_data(nlh);
 	struct iscsi_stats *stats;
 	struct sk_buff *skbstat;
 	struct iscsi_cls_conn *conn;
 	struct nlmsghdr	*nlhstat;
 	struct iscsi_uevent *evstat;
 	struct iscsi_internal *priv;
-	int len = NLMSG_SPACE(sizeof(*ev) +
-			      sizeof(struct iscsi_stats) +
-			      sizeof(struct iscsi_stats_custom) *
-			      ISCSI_STATS_CUSTOM_MAX);
+	int len = nlmsg_total_size(sizeof(*ev) +
+				   sizeof(struct iscsi_stats) +
+				   sizeof(struct iscsi_stats_custom) *
+				   ISCSI_STATS_CUSTOM_MAX);
 	int err = 0;
 
 	priv = iscsi_if_transport_lookup(transport);
@@ -1595,7 +1595,7 @@ iscsi_if_get_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh)
 
 		nlhstat = __nlmsg_put(skbstat, 0, 0, 0,
 				      (len - sizeof(*nlhstat)), 0);
-		evstat = NLMSG_DATA(nlhstat);
+		evstat = nlmsg_data(nlhstat);
 		memset(evstat, 0, sizeof(*evstat));
 		evstat->transport_handle = iscsi_handle(conn->transport);
 		evstat->type = nlh->nlmsg_type;
@@ -1608,12 +1608,12 @@ iscsi_if_get_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh)
 		memset(stats, 0, sizeof(*stats));
 
 		transport->get_stats(conn, stats);
-		actual_size = NLMSG_SPACE(sizeof(struct iscsi_uevent) +
-					  sizeof(struct iscsi_stats) +
-					  sizeof(struct iscsi_stats_custom) *
-					  stats->custom_length);
+		actual_size = nlmsg_total_size(sizeof(struct iscsi_uevent) +
+					       sizeof(struct iscsi_stats) +
+					       sizeof(struct iscsi_stats_custom) *
+					       stats->custom_length);
 		actual_size -= sizeof(*nlhstat);
-		actual_size = NLMSG_LENGTH(actual_size);
+		actual_size = nlmsg_msg_size(actual_size);
 		skb_trim(skbstat, NLMSG_ALIGN(actual_size));
 		nlhstat->nlmsg_len = actual_size;
 
@@ -1637,7 +1637,7 @@ int iscsi_session_event(struct iscsi_cls_session *session,
 	struct iscsi_uevent *ev;
 	struct sk_buff  *skb;
 	struct nlmsghdr *nlh;
-	int rc, len = NLMSG_SPACE(sizeof(*ev));
+	int rc, len = nlmsg_total_size(sizeof(*ev));
 
 	priv = iscsi_if_transport_lookup(session->transport);
 	if (!priv)
@@ -1653,7 +1653,7 @@ int iscsi_session_event(struct iscsi_cls_session *session,
 	}
 
 	nlh = __nlmsg_put(skb, 0, 0, 0, (len - sizeof(*nlh)), 0);
-	ev = NLMSG_DATA(nlh);
+	ev = nlmsg_data(nlh);
 	ev->transport_handle = iscsi_handle(session->transport);
 
 	ev->type = event;
@@ -2005,7 +2005,7 @@ iscsi_send_ping(struct iscsi_transport *transport, struct iscsi_uevent *ev)
 static int
 iscsi_get_chap(struct iscsi_transport *transport, struct nlmsghdr *nlh)
 {
-	struct iscsi_uevent *ev = NLMSG_DATA(nlh);
+	struct iscsi_uevent *ev = nlmsg_data(nlh);
 	struct Scsi_Host *shost = NULL;
 	struct iscsi_chap_rec *chap_rec;
 	struct iscsi_internal *priv;
@@ -2024,7 +2024,7 @@ iscsi_get_chap(struct iscsi_transport *transport, struct nlmsghdr *nlh)
 		return -EINVAL;
 
 	chap_buf_size = (ev->u.get_chap.num_entries * sizeof(*chap_rec));
-	len = NLMSG_SPACE(sizeof(*ev) + chap_buf_size);
+	len = nlmsg_total_size(sizeof(*ev) + chap_buf_size);
 
 	shost = scsi_host_lookup(ev->u.get_chap.host_no);
 	if (!shost) {
@@ -2045,7 +2045,7 @@ iscsi_get_chap(struct iscsi_transport *transport, struct nlmsghdr *nlh)
 
 		nlhchap = __nlmsg_put(skbchap, 0, 0, 0,
 				      (len - sizeof(*nlhchap)), 0);
-		evchap = NLMSG_DATA(nlhchap);
+		evchap = nlmsg_data(nlhchap);
 		memset(evchap, 0, sizeof(*evchap));
 		evchap->transport_handle = iscsi_handle(transport);
 		evchap->type = nlh->nlmsg_type;
@@ -2058,7 +2058,7 @@ iscsi_get_chap(struct iscsi_transport *transport, struct nlmsghdr *nlh)
 		err = transport->get_chap(shost, ev->u.get_chap.chap_tbl_idx,
 				    &evchap->u.get_chap.num_entries, buf);
 
-		actual_size = NLMSG_SPACE(sizeof(*ev) + chap_buf_size);
+		actual_size = nlmsg_total_size(sizeof(*ev) + chap_buf_size);
 		skb_trim(skbchap, NLMSG_ALIGN(actual_size));
 		nlhchap->nlmsg_len = actual_size;
 
@@ -2096,7 +2096,7 @@ static int
 iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
 {
 	int err = 0;
-	struct iscsi_uevent *ev = NLMSG_DATA(nlh);
+	struct iscsi_uevent *ev = nlmsg_data(nlh);
 	struct iscsi_transport *transport = NULL;
 	struct iscsi_internal *priv;
 	struct iscsi_cls_session *session;
@@ -2263,7 +2263,7 @@ static void
 iscsi_if_rx(struct sk_buff *skb)
 {
 	mutex_lock(&rx_queue_mutex);
-	while (skb->len >= NLMSG_SPACE(0)) {
+	while (skb->len >= NLMSG_HDRLEN) {
 		int err;
 		uint32_t rlen;
 		struct nlmsghdr	*nlh;
@@ -2276,7 +2276,7 @@ iscsi_if_rx(struct sk_buff *skb)
 			break;
 		}
 
-		ev = NLMSG_DATA(nlh);
+		ev = nlmsg_data(nlh);
 		rlen = NLMSG_ALIGN(nlh->nlmsg_len);
 		if (rlen > skb->len)
 			rlen = skb->len;
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 9f0c465..df5e961 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -35,6 +35,7 @@ static int sg_version_num = 30534;	/* 2 digits for each component */
 #include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/mm.h>
+#include <linux/aio.h>
 #include <linux/errno.h>
 #include <linux/mtio.h>
 #include <linux/ioctl.h>
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c
index 5995682..bac55f7 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.c
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.c
@@ -1171,112 +1171,36 @@ printk("sym_user_command: data=%ld\n", uc->data);
 #endif	/* SYM_LINUX_USER_COMMAND_SUPPORT */
 
 
-#ifdef SYM_LINUX_USER_INFO_SUPPORT
-/*
- *  Informations through the proc file system.
- */
-struct info_str {
-	char *buffer;
-	int length;
-	int offset;
-	int pos;
-};
-
-static void copy_mem_info(struct info_str *info, char *data, int len)
-{
-	if (info->pos + len > info->length)
-		len = info->length - info->pos;
-
-	if (info->pos + len < info->offset) {
-		info->pos += len;
-		return;
-	}
-	if (info->pos < info->offset) {
-		data += (info->offset - info->pos);
-		len  -= (info->offset - info->pos);
-	}
-
-	if (len > 0) {
-		memcpy(info->buffer + info->pos, data, len);
-		info->pos += len;
-	}
-}
-
-static int copy_info(struct info_str *info, char *fmt, ...)
-{
-	va_list args;
-	char buf[81];
-	int len;
-
-	va_start(args, fmt);
-	len = vsprintf(buf, fmt, args);
-	va_end(args);
-
-	copy_mem_info(info, buf, len);
-	return len;
-}
-
 /*
  *  Copy formatted information into the input buffer.
  */
-static int sym_host_info(struct Scsi_Host *shost, char *ptr, off_t offset, int len)
+static int sym_show_info(struct seq_file *m, struct Scsi_Host *shost)
 {
+#ifdef SYM_LINUX_USER_INFO_SUPPORT
 	struct sym_data *sym_data = shost_priv(shost);
 	struct pci_dev *pdev = sym_data->pdev;
 	struct sym_hcb *np = sym_data->ncb;
-	struct info_str info;
-
-	info.buffer	= ptr;
-	info.length	= len;
-	info.offset	= offset;
-	info.pos	= 0;
 
-	copy_info(&info, "Chip " NAME53C "%s, device id 0x%x, "
-			 "revision id 0x%x\n", np->s.chip_name,
-			 pdev->device, pdev->revision);
-	copy_info(&info, "At PCI address %s, IRQ %u\n",
+	seq_printf(m, "Chip " NAME53C "%s, device id 0x%x, "
+		 "revision id 0x%x\n", np->s.chip_name,
+		 pdev->device, pdev->revision);
+	seq_printf(m, "At PCI address %s, IRQ %u\n",
 			 pci_name(pdev), pdev->irq);
-	copy_info(&info, "Min. period factor %d, %s SCSI BUS%s\n",
-			 (int) (np->minsync_dt ? np->minsync_dt : np->minsync),
-			 np->maxwide ? "Wide" : "Narrow",
-			 np->minsync_dt ? ", DT capable" : "");
+	seq_printf(m, "Min. period factor %d, %s SCSI BUS%s\n",
+		 (int) (np->minsync_dt ? np->minsync_dt : np->minsync),
+		 np->maxwide ? "Wide" : "Narrow",
+		 np->minsync_dt ? ", DT capable" : "");
 
-	copy_info(&info, "Max. started commands %d, "
-			 "max. commands per LUN %d\n",
-			 SYM_CONF_MAX_START, SYM_CONF_MAX_TAG);
+	seq_printf(m, "Max. started commands %d, "
+		 "max. commands per LUN %d\n",
+		 SYM_CONF_MAX_START, SYM_CONF_MAX_TAG);
 
-	return info.pos > info.offset? info.pos - info.offset : 0;
-}
-#endif /* SYM_LINUX_USER_INFO_SUPPORT */
-
-/*
- *  Entry point of the scsi proc fs of the driver.
- *  - func = 0 means read  (returns adapter infos)
- *  - func = 1 means write (not yet merget from sym53c8xx)
- */
-static int sym53c8xx_proc_info(struct Scsi_Host *shost, char *buffer,
-			char **start, off_t offset, int length, int func)
-{
-	int retv;
-
-	if (func) {
-#ifdef	SYM_LINUX_USER_COMMAND_SUPPORT
-		retv = sym_user_command(shost, buffer, length);
-#else
-		retv = -EINVAL;
-#endif
-	} else {
-		if (start)
-			*start = buffer;
-#ifdef SYM_LINUX_USER_INFO_SUPPORT
-		retv = sym_host_info(shost, buffer, offset, length);
+	return 0;
 #else
-		retv = -EINVAL;
-#endif
-	}
-
-	return retv;
+	return -EINVAL;
+#endif /* SYM_LINUX_USER_INFO_SUPPORT */
 }
+
 #endif /* SYM_LINUX_PROC_INFO_SUPPORT */
 
 /*
@@ -1742,7 +1666,10 @@ static struct scsi_host_template sym2_template = {
 	.use_clustering		= ENABLE_CLUSTERING,
 	.max_sectors		= 0xFFFF,
 #ifdef SYM_LINUX_PROC_INFO_SUPPORT
-	.proc_info		= sym53c8xx_proc_info,
+	.show_info		= sym_show_info,
+#ifdef	SYM_LINUX_USER_COMMAND_SUPPORT
+	.write_info		= sym_user_command,
+#endif
 	.proc_name		= NAME53C8XX,
 #endif
 };
diff --git a/drivers/scsi/t128.c b/drivers/scsi/t128.c
index d672d97..f1e4b41 100644
--- a/drivers/scsi/t128.c
+++ b/drivers/scsi/t128.c
@@ -201,7 +201,8 @@ int __init t128_detect(struct scsi_host_template * tpnt){
     int sig, count;
 
     tpnt->proc_name = "t128";
-    tpnt->proc_info = &t128_proc_info;
+    tpnt->show_info = t128_show_info;
+    tpnt->write_info = t128_write_info;
 
     for (count = 0; current_override < NO_OVERRIDES; ++current_override) {
 	base = 0;
diff --git a/drivers/scsi/t128.h b/drivers/scsi/t128.h
index ada1115..1df82c28 100644
--- a/drivers/scsi/t128.h
+++ b/drivers/scsi/t128.h
@@ -140,7 +140,8 @@ static int t128_bus_reset(struct scsi_cmnd *);
 #define NCR5380_queue_command t128_queue_command
 #define NCR5380_abort t128_abort
 #define NCR5380_bus_reset t128_bus_reset
-#define NCR5380_proc_info t128_proc_info
+#define NCR5380_show_info t128_show_info
+#define NCR5380_write_info t128_write_info
 
 /* 15 14 12 10 7 5 3
    1101 0100 1010 1000 */
diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c
index 3449a1f..b53ba9e 100644
--- a/drivers/scsi/virtio_scsi.c
+++ b/drivers/scsi/virtio_scsi.c
@@ -13,6 +13,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/mempool.h>
@@ -59,11 +61,8 @@ struct virtio_scsi_vq {
 
 /* Per-target queue state */
 struct virtio_scsi_target_state {
-	/* Protects sg.  Lock hierarchy is tgt_lock -> vq_lock.  */
+	/* Never held at the same time as vq_lock.  */
 	spinlock_t tgt_lock;
-
-	/* For sglist construction when adding commands to the virtqueue.  */
-	struct scatterlist sg[];
 };
 
 /* Driver instance state */
@@ -223,8 +222,8 @@ static int virtscsi_kick_event(struct virtio_scsi *vscsi,
 
 	spin_lock_irqsave(&vscsi->event_vq.vq_lock, flags);
 
-	err = virtqueue_add_buf(vscsi->event_vq.vq, &sg, 0, 1, event_node,
-				GFP_ATOMIC);
+	err = virtqueue_add_inbuf(vscsi->event_vq.vq, &sg, 1, event_node,
+				  GFP_ATOMIC);
 	if (!err)
 		virtqueue_kick(vscsi->event_vq.vq);
 
@@ -351,75 +350,61 @@ static void virtscsi_event_done(struct virtqueue *vq)
 	spin_unlock_irqrestore(&vscsi->event_vq.vq_lock, flags);
 };
 
-static void virtscsi_map_sgl(struct scatterlist *sg, unsigned int *p_idx,
-			     struct scsi_data_buffer *sdb)
-{
-	struct sg_table *table = &sdb->table;
-	struct scatterlist *sg_elem;
-	unsigned int idx = *p_idx;
-	int i;
-
-	for_each_sg(table->sgl, sg_elem, table->nents, i)
-		sg[idx++] = *sg_elem;
-
-	*p_idx = idx;
-}
-
 /**
- * virtscsi_map_cmd - map a scsi_cmd to a virtqueue scatterlist
- * @vscsi	: virtio_scsi state
+ * virtscsi_add_cmd - add a virtio_scsi_cmd to a virtqueue
+ * @vq		: the struct virtqueue we're talking about
  * @cmd		: command structure
- * @out_num	: number of read-only elements
- * @in_num	: number of write-only elements
  * @req_size	: size of the request buffer
  * @resp_size	: size of the response buffer
- *
- * Called with tgt_lock held.
+ * @gfp	: flags to use for memory allocations
  */
-static void virtscsi_map_cmd(struct virtio_scsi_target_state *tgt,
-			     struct virtio_scsi_cmd *cmd,
-			     unsigned *out_num, unsigned *in_num,
-			     size_t req_size, size_t resp_size)
+static int virtscsi_add_cmd(struct virtqueue *vq,
+			    struct virtio_scsi_cmd *cmd,
+			    size_t req_size, size_t resp_size, gfp_t gfp)
 {
 	struct scsi_cmnd *sc = cmd->sc;
-	struct scatterlist *sg = tgt->sg;
-	unsigned int idx = 0;
+	struct scatterlist *sgs[4], req, resp;
+	struct sg_table *out, *in;
+	unsigned out_num = 0, in_num = 0;
+
+	out = in = NULL;
+
+	if (sc && sc->sc_data_direction != DMA_NONE) {
+		if (sc->sc_data_direction != DMA_FROM_DEVICE)
+			out = &scsi_out(sc)->table;
+		if (sc->sc_data_direction != DMA_TO_DEVICE)
+			in = &scsi_in(sc)->table;
+	}
 
 	/* Request header.  */
-	sg_set_buf(&sg[idx++], &cmd->req, req_size);
+	sg_init_one(&req, &cmd->req, req_size);
+	sgs[out_num++] = &req;
 
 	/* Data-out buffer.  */
-	if (sc && sc->sc_data_direction != DMA_FROM_DEVICE)
-		virtscsi_map_sgl(sg, &idx, scsi_out(sc));
-
-	*out_num = idx;
+	if (out)
+		sgs[out_num++] = out->sgl;
 
 	/* Response header.  */
-	sg_set_buf(&sg[idx++], &cmd->resp, resp_size);
+	sg_init_one(&resp, &cmd->resp, resp_size);
+	sgs[out_num + in_num++] = &resp;
 
 	/* Data-in buffer */
-	if (sc && sc->sc_data_direction != DMA_TO_DEVICE)
-		virtscsi_map_sgl(sg, &idx, scsi_in(sc));
+	if (in)
+		sgs[out_num + in_num++] = in->sgl;
 
-	*in_num = idx - *out_num;
+	return virtqueue_add_sgs(vq, sgs, out_num, in_num, cmd, gfp);
 }
 
-static int virtscsi_kick_cmd(struct virtio_scsi_target_state *tgt,
-			     struct virtio_scsi_vq *vq,
+static int virtscsi_kick_cmd(struct virtio_scsi_vq *vq,
 			     struct virtio_scsi_cmd *cmd,
 			     size_t req_size, size_t resp_size, gfp_t gfp)
 {
-	unsigned int out_num, in_num;
 	unsigned long flags;
 	int err;
 	bool needs_kick = false;
 
-	spin_lock_irqsave(&tgt->tgt_lock, flags);
-	virtscsi_map_cmd(tgt, cmd, &out_num, &in_num, req_size, resp_size);
-
-	spin_lock(&vq->vq_lock);
-	err = virtqueue_add_buf(vq->vq, tgt->sg, out_num, in_num, cmd, gfp);
-	spin_unlock(&tgt->tgt_lock);
+	spin_lock_irqsave(&vq->vq_lock, flags);
+	err = virtscsi_add_cmd(vq->vq, cmd, req_size, resp_size, gfp);
 	if (!err)
 		needs_kick = virtqueue_kick_prepare(vq->vq);
 
@@ -433,7 +418,6 @@ static int virtscsi_kick_cmd(struct virtio_scsi_target_state *tgt,
 static int virtscsi_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *sc)
 {
 	struct virtio_scsi *vscsi = shost_priv(sh);
-	struct virtio_scsi_target_state *tgt = vscsi->tgt[sc->device->id];
 	struct virtio_scsi_cmd *cmd;
 	int ret;
 
@@ -467,7 +451,7 @@ static int virtscsi_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *sc)
 	BUG_ON(sc->cmd_len > VIRTIO_SCSI_CDB_SIZE);
 	memcpy(cmd->req.cmd.cdb, sc->cmnd, sc->cmd_len);
 
-	if (virtscsi_kick_cmd(tgt, &vscsi->req_vq, cmd,
+	if (virtscsi_kick_cmd(&vscsi->req_vq, cmd,
 			      sizeof cmd->req.cmd, sizeof cmd->resp.cmd,
 			      GFP_ATOMIC) == 0)
 		ret = 0;
@@ -481,11 +465,10 @@ out:
 static int virtscsi_tmf(struct virtio_scsi *vscsi, struct virtio_scsi_cmd *cmd)
 {
 	DECLARE_COMPLETION_ONSTACK(comp);
-	struct virtio_scsi_target_state *tgt = vscsi->tgt[cmd->sc->device->id];
 	int ret = FAILED;
 
 	cmd->comp = &comp;
-	if (virtscsi_kick_cmd(tgt, &vscsi->ctrl_vq, cmd,
+	if (virtscsi_kick_cmd(&vscsi->ctrl_vq, cmd,
 			      sizeof cmd->req.tmf, sizeof cmd->resp.tmf,
 			      GFP_NOIO) < 0)
 		goto out;
@@ -586,20 +569,16 @@ static void virtscsi_init_vq(struct virtio_scsi_vq *virtscsi_vq,
 }
 
 static struct virtio_scsi_target_state *virtscsi_alloc_tgt(
-	struct virtio_device *vdev, int sg_elems)
+	struct virtio_device *vdev)
 {
 	struct virtio_scsi_target_state *tgt;
 	gfp_t gfp_mask = GFP_KERNEL;
 
-	/* We need extra sg elements at head and tail.  */
-	tgt = kmalloc(sizeof(*tgt) + sizeof(tgt->sg[0]) * (sg_elems + 2),
-		      gfp_mask);
-
+	tgt = kmalloc(sizeof(*tgt), gfp_mask);
 	if (!tgt)
 		return NULL;
 
 	spin_lock_init(&tgt->tgt_lock);
-	sg_init_table(tgt->sg, sg_elems + 2);
 	return tgt;
 }
 
@@ -633,7 +612,7 @@ static int virtscsi_init(struct virtio_device *vdev,
 {
 	int err;
 	struct virtqueue *vqs[3];
-	u32 i, sg_elems;
+	u32 i;
 
 	vq_callback_t *callbacks[] = {
 		virtscsi_ctrl_done,
@@ -661,11 +640,8 @@ static int virtscsi_init(struct virtio_device *vdev,
 	if (virtio_has_feature(vdev, VIRTIO_SCSI_F_HOTPLUG))
 		virtscsi_kick_event_all(vscsi);
 
-	/* We need to know how many segments before we allocate.  */
-	sg_elems = virtscsi_config_get(vdev, seg_max) ?: 1;
-
 	for (i = 0; i < num_targets; i++) {
-		vscsi->tgt[i] = virtscsi_alloc_tgt(vdev, sg_elems);
+		vscsi->tgt[i] = virtscsi_alloc_tgt(vdev);
 		if (!vscsi->tgt[i]) {
 			err = -ENOMEM;
 			goto out;
@@ -794,8 +770,7 @@ static int __init init(void)
 
 	virtscsi_cmd_cache = KMEM_CACHE(virtio_scsi_cmd, 0);
 	if (!virtscsi_cmd_cache) {
-		printk(KERN_ERR "kmem_cache_create() for "
-				"virtscsi_cmd_cache failed\n");
+		pr_err("kmem_cache_create() for virtscsi_cmd_cache failed\n");
 		goto error;
 	}
 
@@ -804,8 +779,7 @@ static int __init init(void)
 		mempool_create_slab_pool(VIRTIO_SCSI_MEMPOOL_SZ,
 					 virtscsi_cmd_cache);
 	if (!virtscsi_cmd_pool) {
-		printk(KERN_ERR "mempool_create() for"
-				"virtscsi_cmd_pool failed\n");
+		pr_err("mempool_create() for virtscsi_cmd_pool failed\n");
 		goto error;
 	}
 	ret = register_virtio_driver(&virtio_scsi_driver);
diff --git a/drivers/scsi/wd33c93.c b/drivers/scsi/wd33c93.c
index c0ee4ea..41883a8 100644
--- a/drivers/scsi/wd33c93.c
+++ b/drivers/scsi/wd33c93.c
@@ -2054,22 +2054,16 @@ wd33c93_init(struct Scsi_Host *instance, const wd33c93_regs regs,
 	printk("           Version %s - %s\n", WD33C93_VERSION, WD33C93_DATE);
 }
 
-int
-wd33c93_proc_info(struct Scsi_Host *instance, char *buf, char **start, off_t off, int len, int in)
+int wd33c93_write_info(struct Scsi_Host *instance, char *buf, int len)
 {
-
 #ifdef PROC_INTERFACE
-
 	char *bp;
-	char tbuf[128];
 	struct WD33C93_hostdata *hd;
-	struct scsi_cmnd *cmd;
 	int x;
-	static int stop = 0;
 
 	hd = (struct WD33C93_hostdata *) instance->hostdata;
 
-/* If 'in' is TRUE we need to _read_ the proc file. We accept the following
+/* We accept the following
  * keywords (same format as command-line, but arguments are not optional):
  *    debug
  *    disconnect
@@ -2083,145 +2077,124 @@ wd33c93_proc_info(struct Scsi_Host *instance, char *buf, char **start, off_t off
  *    nosync
  */
 
-	if (in) {
-		buf[len] = '\0';
-		for (bp = buf; *bp; ) {
-			while (',' == *bp || ' ' == *bp)
-				++bp;
-		if (!strncmp(bp, "debug:", 6)) {
-				hd->args = simple_strtoul(bp+6, &bp, 0) & DB_MASK;
-		} else if (!strncmp(bp, "disconnect:", 11)) {
-				x = simple_strtoul(bp+11, &bp, 0);
-			if (x < DIS_NEVER || x > DIS_ALWAYS)
-				x = DIS_ADAPTIVE;
-			hd->disconnect = x;
-		} else if (!strncmp(bp, "period:", 7)) {
+	buf[len] = '\0';
+	for (bp = buf; *bp; ) {
+		while (',' == *bp || ' ' == *bp)
+			++bp;
+	if (!strncmp(bp, "debug:", 6)) {
+			hd->args = simple_strtoul(bp+6, &bp, 0) & DB_MASK;
+	} else if (!strncmp(bp, "disconnect:", 11)) {
+			x = simple_strtoul(bp+11, &bp, 0);
+		if (x < DIS_NEVER || x > DIS_ALWAYS)
+			x = DIS_ADAPTIVE;
+		hd->disconnect = x;
+	} else if (!strncmp(bp, "period:", 7)) {
+		x = simple_strtoul(bp+7, &bp, 0);
+		hd->default_sx_per =
+			hd->sx_table[round_period((unsigned int) x,
+						  hd->sx_table)].period_ns;
+	} else if (!strncmp(bp, "resync:", 7)) {
+			set_resync(hd, (int)simple_strtoul(bp+7, &bp, 0));
+	} else if (!strncmp(bp, "proc:", 5)) {
+			hd->proc = simple_strtoul(bp+5, &bp, 0);
+	} else if (!strncmp(bp, "nodma:", 6)) {
+			hd->no_dma = simple_strtoul(bp+6, &bp, 0);
+	} else if (!strncmp(bp, "level2:", 7)) {
+			hd->level2 = simple_strtoul(bp+7, &bp, 0);
+		} else if (!strncmp(bp, "burst:", 6)) {
+			hd->dma_mode =
+				simple_strtol(bp+6, &bp, 0) ? CTRL_BURST:CTRL_DMA;
+		} else if (!strncmp(bp, "fast:", 5)) {
+			x = !!simple_strtol(bp+5, &bp, 0);
+			if (x != hd->fast)
+				set_resync(hd, 0xff);
+			hd->fast = x;
+		} else if (!strncmp(bp, "nosync:", 7)) {
 			x = simple_strtoul(bp+7, &bp, 0);
-			hd->default_sx_per =
-				hd->sx_table[round_period((unsigned int) x,
-							  hd->sx_table)].period_ns;
-		} else if (!strncmp(bp, "resync:", 7)) {
-				set_resync(hd, (int)simple_strtoul(bp+7, &bp, 0));
-		} else if (!strncmp(bp, "proc:", 5)) {
-				hd->proc = simple_strtoul(bp+5, &bp, 0);
-		} else if (!strncmp(bp, "nodma:", 6)) {
-				hd->no_dma = simple_strtoul(bp+6, &bp, 0);
-		} else if (!strncmp(bp, "level2:", 7)) {
-				hd->level2 = simple_strtoul(bp+7, &bp, 0);
-			} else if (!strncmp(bp, "burst:", 6)) {
-				hd->dma_mode =
-					simple_strtol(bp+6, &bp, 0) ? CTRL_BURST:CTRL_DMA;
-			} else if (!strncmp(bp, "fast:", 5)) {
-				x = !!simple_strtol(bp+5, &bp, 0);
-				if (x != hd->fast)
-					set_resync(hd, 0xff);
-				hd->fast = x;
-			} else if (!strncmp(bp, "nosync:", 7)) {
-				x = simple_strtoul(bp+7, &bp, 0);
-				set_resync(hd, x ^ hd->no_sync);
-				hd->no_sync = x;
-			} else {
-				break; /* unknown keyword,syntax-error,... */
-			}
+			set_resync(hd, x ^ hd->no_sync);
+			hd->no_sync = x;
+		} else {
+			break; /* unknown keyword,syntax-error,... */
 		}
-		return len;
 	}
+	return len;
+#else
+	return 0;
+#endif
+}
+
+int
+wd33c93_show_info(struct seq_file *m, struct Scsi_Host *instance)
+{
+#ifdef PROC_INTERFACE
+	struct WD33C93_hostdata *hd;
+	struct scsi_cmnd *cmd;
+	int x;
+
+	hd = (struct WD33C93_hostdata *) instance->hostdata;
 
 	spin_lock_irq(&hd->lock);
-	bp = buf;
-	*bp = '\0';
-	if (hd->proc & PR_VERSION) {
-		sprintf(tbuf, "\nVersion %s - %s.",
+	if (hd->proc & PR_VERSION)
+		seq_printf(m, "\nVersion %s - %s.",
 			WD33C93_VERSION, WD33C93_DATE);
-		strcat(bp, tbuf);
-	}
+
 	if (hd->proc & PR_INFO) {
-		sprintf(tbuf, "\nclock_freq=%02x no_sync=%02x no_dma=%d"
+		seq_printf(m, "\nclock_freq=%02x no_sync=%02x no_dma=%d"
 			" dma_mode=%02x fast=%d",
 			hd->clock_freq, hd->no_sync, hd->no_dma, hd->dma_mode, hd->fast);
-		strcat(bp, tbuf);
-		strcat(bp, "\nsync_xfer[] =       ");
-		for (x = 0; x < 7; x++) {
-			sprintf(tbuf, "\t%02x", hd->sync_xfer[x]);
-			strcat(bp, tbuf);
-		}
-		strcat(bp, "\nsync_stat[] =       ");
-		for (x = 0; x < 7; x++) {
-			sprintf(tbuf, "\t%02x", hd->sync_stat[x]);
-			strcat(bp, tbuf);
-		}
+		seq_printf(m, "\nsync_xfer[] =       ");
+		for (x = 0; x < 7; x++)
+			seq_printf(m, "\t%02x", hd->sync_xfer[x]);
+		seq_printf(m, "\nsync_stat[] =       ");
+		for (x = 0; x < 7; x++)
+			seq_printf(m, "\t%02x", hd->sync_stat[x]);
 	}
 #ifdef PROC_STATISTICS
 	if (hd->proc & PR_STATISTICS) {
-		strcat(bp, "\ncommands issued:    ");
-		for (x = 0; x < 7; x++) {
-			sprintf(tbuf, "\t%ld", hd->cmd_cnt[x]);
-			strcat(bp, tbuf);
-		}
-		strcat(bp, "\ndisconnects allowed:");
-		for (x = 0; x < 7; x++) {
-			sprintf(tbuf, "\t%ld", hd->disc_allowed_cnt[x]);
-			strcat(bp, tbuf);
-		}
-		strcat(bp, "\ndisconnects done:   ");
-		for (x = 0; x < 7; x++) {
-			sprintf(tbuf, "\t%ld", hd->disc_done_cnt[x]);
-			strcat(bp, tbuf);
-		}
-		sprintf(tbuf,
+		seq_printf(m, "\ncommands issued:    ");
+		for (x = 0; x < 7; x++)
+			seq_printf(m, "\t%ld", hd->cmd_cnt[x]);
+		seq_printf(m, "\ndisconnects allowed:");
+		for (x = 0; x < 7; x++)
+			seq_printf(m, "\t%ld", hd->disc_allowed_cnt[x]);
+		seq_printf(m, "\ndisconnects done:   ");
+		for (x = 0; x < 7; x++)
+			seq_printf(m, "\t%ld", hd->disc_done_cnt[x]);
+		seq_printf(m,
 			"\ninterrupts: %ld, DATA_PHASE ints: %ld DMA, %ld PIO",
 			hd->int_cnt, hd->dma_cnt, hd->pio_cnt);
-		strcat(bp, tbuf);
 	}
 #endif
 	if (hd->proc & PR_CONNECTED) {
-		strcat(bp, "\nconnected:     ");
+		seq_printf(m, "\nconnected:     ");
 		if (hd->connected) {
 			cmd = (struct scsi_cmnd *) hd->connected;
-			sprintf(tbuf, " %d:%d(%02x)",
+			seq_printf(m, " %d:%d(%02x)",
 				cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
-			strcat(bp, tbuf);
 		}
 	}
 	if (hd->proc & PR_INPUTQ) {
-		strcat(bp, "\ninput_Q:       ");
+		seq_printf(m, "\ninput_Q:       ");
 		cmd = (struct scsi_cmnd *) hd->input_Q;
 		while (cmd) {
-			sprintf(tbuf, " %d:%d(%02x)",
+			seq_printf(m, " %d:%d(%02x)",
 				cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
-			strcat(bp, tbuf);
 			cmd = (struct scsi_cmnd *) cmd->host_scribble;
 		}
 	}
 	if (hd->proc & PR_DISCQ) {
-		strcat(bp, "\ndisconnected_Q:");
+		seq_printf(m, "\ndisconnected_Q:");
 		cmd = (struct scsi_cmnd *) hd->disconnected_Q;
 		while (cmd) {
-			sprintf(tbuf, " %d:%d(%02x)",
+			seq_printf(m, " %d:%d(%02x)",
 				cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
-			strcat(bp, tbuf);
 			cmd = (struct scsi_cmnd *) cmd->host_scribble;
 		}
 	}
-	strcat(bp, "\n");
+	seq_printf(m, "\n");
 	spin_unlock_irq(&hd->lock);
-	*start = buf;
-	if (stop) {
-		stop = 0;
-		return 0;
-	}
-	if (off > 0x40000)	/* ALWAYS stop after 256k bytes have been read */
-		stop = 1;
-	if (hd->proc & PR_STOP)	/* stop every other time */
-		stop = 1;
-	return strlen(bp);
-
-#else				/* PROC_INTERFACE */
-
-	return 0;
-
 #endif				/* PROC_INTERFACE */
-
+	return 0;
 }
 
 EXPORT_SYMBOL(wd33c93_host_reset);
@@ -2229,4 +2202,5 @@ EXPORT_SYMBOL(wd33c93_init);
 EXPORT_SYMBOL(wd33c93_abort);
 EXPORT_SYMBOL(wd33c93_queuecommand);
 EXPORT_SYMBOL(wd33c93_intr);
-EXPORT_SYMBOL(wd33c93_proc_info);
+EXPORT_SYMBOL(wd33c93_show_info);
+EXPORT_SYMBOL(wd33c93_write_info);
diff --git a/drivers/scsi/wd33c93.h b/drivers/scsi/wd33c93.h
index 3b463d7..08abe50 100644
--- a/drivers/scsi/wd33c93.h
+++ b/drivers/scsi/wd33c93.h
@@ -345,7 +345,8 @@ void wd33c93_init (struct Scsi_Host *instance, const wd33c93_regs regs,
 int wd33c93_abort (struct scsi_cmnd *cmd);
 int wd33c93_queuecommand (struct Scsi_Host *h, struct scsi_cmnd *cmd);
 void wd33c93_intr (struct Scsi_Host *instance);
-int wd33c93_proc_info(struct Scsi_Host *, char *, char **, off_t, int, int);
+int wd33c93_show_info(struct seq_file *, struct Scsi_Host *);
+int wd33c93_write_info(struct Scsi_Host *, char *, int);
 int wd33c93_host_reset (struct scsi_cmnd *);
 
 #endif /* WD33C93_H */
diff --git a/drivers/scsi/wd7000.c b/drivers/scsi/wd7000.c
index d89a5df..f9a6e4b 100644
--- a/drivers/scsi/wd7000.c
+++ b/drivers/scsi/wd7000.c
@@ -1296,9 +1296,9 @@ static void wd7000_revision(Adapter * host)
 
 
 #undef SPRINTF
-#define SPRINTF(args...) { if (pos < (buffer + length)) pos += sprintf (pos, ## args); }
+#define SPRINTF(args...) { seq_printf(m, ## args); }
 
-static int wd7000_set_info(char *buffer, int length, struct Scsi_Host *host)
+static int wd7000_set_info(struct Scsi_Host *host, char *buffer, int length)
 {
 	dprintk("Buffer = <%.*s>, length = %d\n", length, buffer, length);
 
@@ -1310,22 +1310,15 @@ static int wd7000_set_info(char *buffer, int length, struct Scsi_Host *host)
 }
 
 
-static int wd7000_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, int length,  int inout)
+static int wd7000_show_info(struct seq_file *m, struct Scsi_Host *host)
 {
 	Adapter *adapter = (Adapter *)host->hostdata;
 	unsigned long flags;
-	char *pos = buffer;
 #ifdef WD7000_DEBUG
 	Mailbox *ogmbs, *icmbs;
 	short count;
 #endif
 
-	/*
-	 * Has data been written to the file ?
-	 */
-	if (inout)
-		return (wd7000_set_info(buffer, length, host));
-
 	spin_lock_irqsave(host->host_lock, flags);
 	SPRINTF("Host scsi%d: Western Digital WD-7000 (rev %d.%d)\n", host->host_no, adapter->rev1, adapter->rev2);
 	SPRINTF("  IO base:      0x%x\n", adapter->iobase);
@@ -1368,17 +1361,7 @@ static int wd7000_proc_info(struct Scsi_Host *host, char *buffer, char **start,
 
 	spin_unlock_irqrestore(host->host_lock, flags);
 
-	/*
-	 * Calculate start of next buffer, and return value.
-	 */
-	*start = buffer + offset;
-
-	if ((pos - buffer) < offset)
-		return (0);
-	else if ((pos - buffer - offset) < length)
-		return (pos - buffer - offset);
-	else
-		return (length);
+	return 0;
 }
 
 
@@ -1413,7 +1396,8 @@ static __init int wd7000_detect(struct scsi_host_template *tpnt)
 	for (i = 0; i < NUM_CONFIGS; biosptr[i++] = -1);
 
 	tpnt->proc_name = "wd7000";
-	tpnt->proc_info = &wd7000_proc_info;
+	tpnt->show_info = &wd7000_show_info;
+	tpnt->write_info = wd7000_set_info;
 
 	/*
 	 * Set up SCB free list, which is shared by all adapters
@@ -1658,7 +1642,8 @@ MODULE_LICENSE("GPL");
 
 static struct scsi_host_template driver_template = {
 	.proc_name		= "wd7000",
-	.proc_info		= wd7000_proc_info,
+	.show_info		= wd7000_show_info,
+	.write_info		= wd7000_set_info,
 	.name			= "Western Digital WD-7000",
 	.detect			= wd7000_detect,
 	.release		= wd7000_release,
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index f80eee7..1cc4105 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -55,6 +55,7 @@ comment "SPI Master Controller Drivers"
 
 config SPI_ALTERA
 	tristate "Altera SPI Controller"
+	depends on GENERIC_HARDIRQS
 	select SPI_BITBANG
 	help
 	  This is the driver for the Altera SPI Controller.
@@ -74,6 +75,17 @@ config SPI_ATMEL
 	  This selects a driver for the Atmel SPI Controller, present on
 	  many AT32 (AVR32) and AT91 (ARM) chips.
 
+config SPI_BCM2835
+	tristate "BCM2835 SPI controller"
+	depends on ARCH_BCM2835
+	help
+	  This selects a driver for the Broadcom BCM2835 SPI master.
+
+	  The BCM2835 contains two types of SPI master controller; the
+	  "universal SPI master", and the regular SPI controller. This driver
+	  is for the regular SPI controller. Slave mode operation is not also
+	  not supported.
+
 config SPI_BFIN5XX
 	tristate "SPI controller driver for ADI Blackfin5xx"
 	depends on BLACKFIN
@@ -310,7 +322,7 @@ config SPI_PXA2XX_DMA
 
 config SPI_PXA2XX
 	tristate "PXA2xx SSP SPI master"
-	depends on ARCH_PXA || PCI || ACPI
+	depends on (ARCH_PXA || PCI || ACPI) && GENERIC_HARDIRQS
 	select PXA_SSP if ARCH_PXA
 	help
 	  This enables using a PXA2xx or Sodaville SSP port as a SPI master
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index e53c309..3ce1d08 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -14,6 +14,7 @@ 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_BCM2835)		+= spi-bcm2835.o
 obj-$(CONFIG_SPI_BCM63XX)		+= spi-bcm63xx.o
 obj-$(CONFIG_SPI_BFIN5XX)		+= spi-bfin5xx.o
 obj-$(CONFIG_SPI_BFIN_SPORT)		+= spi-bfin-sport.o
diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c
index 656d137..ab2ed75 100644
--- a/drivers/spi/spi-atmel.c
+++ b/drivers/spi/spi-atmel.c
@@ -22,9 +22,8 @@
 #include <linux/platform_data/atmel.h>
 #include <linux/of.h>
 
-#include <asm/io.h>
-#include <asm/gpio.h>
-#include <mach/cpu.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
 
 /* SPI register offsets */
 #define SPI_CR					0x0000
@@ -39,6 +38,7 @@
 #define SPI_CSR1				0x0034
 #define SPI_CSR2				0x0038
 #define SPI_CSR3				0x003c
+#define SPI_VERSION				0x00fc
 #define SPI_RPR					0x0100
 #define SPI_RCR					0x0104
 #define SPI_TPR					0x0108
@@ -71,6 +71,8 @@
 #define SPI_FDIV_SIZE				1
 #define SPI_MODFDIS_OFFSET			4
 #define SPI_MODFDIS_SIZE			1
+#define SPI_WDRBT_OFFSET			5
+#define SPI_WDRBT_SIZE				1
 #define SPI_LLB_OFFSET				7
 #define SPI_LLB_SIZE				1
 #define SPI_PCS_OFFSET				16
@@ -180,6 +182,11 @@
 #define spi_writel(port,reg,value) \
 	__raw_writel((value), (port)->regs + SPI_##reg)
 
+struct atmel_spi_caps {
+	bool	is_spi2;
+	bool	has_wdrbt;
+	bool	has_dma_support;
+};
 
 /*
  * The core SPI transfer engine just talks to a register bank to set up
@@ -201,9 +208,12 @@ struct atmel_spi {
 	unsigned long		current_remaining_bytes;
 	struct spi_transfer	*next_transfer;
 	unsigned long		next_remaining_bytes;
+	int			done_status;
 
 	void			*buffer;
 	dma_addr_t		buffer_dma;
+
+	struct atmel_spi_caps	caps;
 };
 
 /* Controller-specific per-slave state */
@@ -222,14 +232,10 @@ struct atmel_spi_device {
  *  - 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)
+static bool atmel_spi_is_v2(struct atmel_spi *as)
 {
-	return !cpu_is_at91rm9200();
+	return as->caps.is_spi2;
 }
 
 /*
@@ -250,11 +256,6 @@ static bool atmel_spi_is_v2(void)
  * 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)
@@ -263,15 +264,24 @@ static void cs_activate(struct atmel_spi *as, struct spi_device *spi)
 	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.
+	if (atmel_spi_is_v2(as)) {
+		spi_writel(as, CSR0 + 4 * spi->chip_select, asd->csr);
+		/* For the low SPI version, there is a issue that PDC transfer
+		 * on CS1,2,3 needs SPI_CSR0.BITS config as SPI_CSR1,2,3.BITS
 		 */
 		spi_writel(as, CSR0, asd->csr);
-		spi_writel(as, MR, SPI_BF(PCS, 0x0e) | SPI_BIT(MODFDIS)
-				| SPI_BIT(MSTR));
+		if (as->caps.has_wdrbt) {
+			spi_writel(as, MR,
+					SPI_BF(PCS, ~(0x01 << spi->chip_select))
+					| SPI_BIT(WDRBT)
+					| SPI_BIT(MODFDIS)
+					| SPI_BIT(MSTR));
+		} else {
+			spi_writel(as, MR,
+					SPI_BF(PCS, ~(0x01 << spi->chip_select))
+					| SPI_BIT(MODFDIS)
+					| SPI_BIT(MSTR));
+		}
 		mr = spi_readl(as, MR);
 		gpio_set_value(asd->npcs_pin, active);
 	} else {
@@ -318,7 +328,7 @@ static void cs_deactivate(struct atmel_spi *as, struct spi_device *spi)
 			asd->npcs_pin, active ? " (low)" : "",
 			mr);
 
-	if (atmel_spi_is_v2() || spi->chip_select != 0)
+	if (atmel_spi_is_v2(as) || spi->chip_select != 0)
 		gpio_set_value(asd->npcs_pin, !active);
 }
 
@@ -544,15 +554,15 @@ static void atmel_spi_dma_unmap_xfer(struct spi_master *master,
 
 static void
 atmel_spi_msg_done(struct spi_master *master, struct atmel_spi *as,
-		struct spi_message *msg, int status, int stay)
+		struct spi_message *msg, int stay)
 {
-	if (!stay || status < 0)
+	if (!stay || as->done_status < 0)
 		cs_deactivate(as, msg->spi);
 	else
 		as->stay = msg->spi;
 
 	list_del(&msg->queue);
-	msg->status = status;
+	msg->status = as->done_status;
 
 	dev_dbg(master->dev.parent,
 		"xfer complete: %u bytes transferred\n",
@@ -564,6 +574,7 @@ atmel_spi_msg_done(struct spi_master *master, struct atmel_spi *as,
 
 	as->current_transfer = NULL;
 	as->next_transfer = NULL;
+	as->done_status = 0;
 
 	/* continue if needed */
 	if (list_empty(&as->queue) || as->stopping)
@@ -641,7 +652,8 @@ atmel_spi_interrupt(int irq, void *dev_id)
 		/* Clear any overrun happening while cleaning up */
 		spi_readl(as, SR);
 
-		atmel_spi_msg_done(master, as, msg, -EIO, 0);
+		as->done_status = -EIO;
+		atmel_spi_msg_done(master, as, msg, 0);
 	} else if (pending & (SPI_BIT(RXBUFF) | SPI_BIT(ENDRX))) {
 		ret = IRQ_HANDLED;
 
@@ -659,7 +671,7 @@ atmel_spi_interrupt(int irq, void *dev_id)
 
 			if (atmel_spi_xfer_is_last(msg, xfer)) {
 				/* report completed message */
-				atmel_spi_msg_done(master, as, msg, 0,
+				atmel_spi_msg_done(master, as, msg,
 						xfer->cs_change);
 			} else {
 				if (xfer->cs_change) {
@@ -719,7 +731,7 @@ static int atmel_spi_setup(struct spi_device *spi)
 	}
 
 	/* see notes above re chipselect */
-	if (!atmel_spi_is_v2()
+	if (!atmel_spi_is_v2(as)
 			&& spi->chip_select == 0
 			&& (spi->mode & SPI_CS_HIGH)) {
 		dev_dbg(&spi->dev, "setup: can't be active-high\n");
@@ -728,7 +740,7 @@ static int atmel_spi_setup(struct spi_device *spi)
 
 	/* v1 chips start out at half the peripheral bus speed. */
 	bus_hz = clk_get_rate(as->clk);
-	if (!atmel_spi_is_v2())
+	if (!atmel_spi_is_v2(as))
 		bus_hz /= 2;
 
 	if (spi->max_speed_hz) {
@@ -804,7 +816,7 @@ static int atmel_spi_setup(struct spi_device *spi)
 		"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())
+	if (!atmel_spi_is_v2(as))
 		spi_writel(as, CSR0 + 4 * spi->chip_select, csr);
 
 	return 0;
@@ -910,6 +922,23 @@ static void atmel_spi_cleanup(struct spi_device *spi)
 	kfree(asd);
 }
 
+static inline unsigned int atmel_get_version(struct atmel_spi *as)
+{
+	return spi_readl(as, VERSION) & 0x00000fff;
+}
+
+static void atmel_get_caps(struct atmel_spi *as)
+{
+	unsigned int version;
+
+	version = atmel_get_version(as);
+	dev_info(&as->pdev->dev, "version: 0x%x\n", version);
+
+	as->caps.is_spi2 = version > 0x121;
+	as->caps.has_wdrbt = version >= 0x210;
+	as->caps.has_dma_support = version >= 0x212;
+}
+
 /*-------------------------------------------------------------------------*/
 
 static int atmel_spi_probe(struct platform_device *pdev)
@@ -970,6 +999,8 @@ static int atmel_spi_probe(struct platform_device *pdev)
 	as->irq = irq;
 	as->clk = clk;
 
+	atmel_get_caps(as);
+
 	ret = request_irq(irq, atmel_spi_interrupt, 0,
 			dev_name(&pdev->dev), master);
 	if (ret)
@@ -979,7 +1010,12 @@ static int atmel_spi_probe(struct platform_device *pdev)
 	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));
+	if (as->caps.has_wdrbt) {
+		spi_writel(as, MR, SPI_BIT(WDRBT) | SPI_BIT(MODFDIS)
+				| SPI_BIT(MSTR));
+	} else {
+		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));
 
@@ -1014,6 +1050,7 @@ static int 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;
+	struct spi_transfer	*xfer;
 
 	/* reset the hardware and block queue progress */
 	spin_lock_irq(&as->lock);
@@ -1025,9 +1062,10 @@ static int atmel_spi_remove(struct platform_device *pdev)
 
 	/* 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...
-		 */
+		list_for_each_entry(xfer, &msg->transfers, transfer_list) {
+			if (!msg->is_dma_mapped)
+				atmel_spi_dma_unmap_xfer(master, xfer);
+		}
 		msg->status = -ESHUTDOWN;
 		msg->complete(msg->context);
 	}
diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c
new file mode 100644
index 0000000..89c0b50
--- /dev/null
+++ b/drivers/spi/spi-bcm2835.c
@@ -0,0 +1,422 @@
+/*
+ * Driver for Broadcom BCM2835 SPI Controllers
+ *
+ * Copyright (C) 2012 Chris Boot
+ * Copyright (C) 2013 Stephen Warren
+ *
+ * This driver is inspired by:
+ * spi-ath79.c, Copyright (C) 2009-2011 Gabor Juhos <juhosg@openwrt.org>
+ * spi-atmel.c, 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 as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You 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/clk.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_device.h>
+#include <linux/spi/spi.h>
+
+/* SPI register offsets */
+#define BCM2835_SPI_CS			0x00
+#define BCM2835_SPI_FIFO		0x04
+#define BCM2835_SPI_CLK			0x08
+#define BCM2835_SPI_DLEN		0x0c
+#define BCM2835_SPI_LTOH		0x10
+#define BCM2835_SPI_DC			0x14
+
+/* Bitfields in CS */
+#define BCM2835_SPI_CS_LEN_LONG		0x02000000
+#define BCM2835_SPI_CS_DMA_LEN		0x01000000
+#define BCM2835_SPI_CS_CSPOL2		0x00800000
+#define BCM2835_SPI_CS_CSPOL1		0x00400000
+#define BCM2835_SPI_CS_CSPOL0		0x00200000
+#define BCM2835_SPI_CS_RXF		0x00100000
+#define BCM2835_SPI_CS_RXR		0x00080000
+#define BCM2835_SPI_CS_TXD		0x00040000
+#define BCM2835_SPI_CS_RXD		0x00020000
+#define BCM2835_SPI_CS_DONE		0x00010000
+#define BCM2835_SPI_CS_LEN		0x00002000
+#define BCM2835_SPI_CS_REN		0x00001000
+#define BCM2835_SPI_CS_ADCS		0x00000800
+#define BCM2835_SPI_CS_INTR		0x00000400
+#define BCM2835_SPI_CS_INTD		0x00000200
+#define BCM2835_SPI_CS_DMAEN		0x00000100
+#define BCM2835_SPI_CS_TA		0x00000080
+#define BCM2835_SPI_CS_CSPOL		0x00000040
+#define BCM2835_SPI_CS_CLEAR_RX		0x00000020
+#define BCM2835_SPI_CS_CLEAR_TX		0x00000010
+#define BCM2835_SPI_CS_CPOL		0x00000008
+#define BCM2835_SPI_CS_CPHA		0x00000004
+#define BCM2835_SPI_CS_CS_10		0x00000002
+#define BCM2835_SPI_CS_CS_01		0x00000001
+
+#define BCM2835_SPI_TIMEOUT_MS	30000
+#define BCM2835_SPI_MODE_BITS	(SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_NO_CS)
+
+#define DRV_NAME	"spi-bcm2835"
+
+struct bcm2835_spi {
+	void __iomem *regs;
+	struct clk *clk;
+	int irq;
+	struct completion done;
+	const u8 *tx_buf;
+	u8 *rx_buf;
+	int len;
+};
+
+static inline u32 bcm2835_rd(struct bcm2835_spi *bs, unsigned reg)
+{
+	return readl(bs->regs + reg);
+}
+
+static inline void bcm2835_wr(struct bcm2835_spi *bs, unsigned reg, u32 val)
+{
+	writel(val, bs->regs + reg);
+}
+
+static inline void bcm2835_rd_fifo(struct bcm2835_spi *bs, int len)
+{
+	u8 byte;
+
+	while (len--) {
+		byte = bcm2835_rd(bs, BCM2835_SPI_FIFO);
+		if (bs->rx_buf)
+			*bs->rx_buf++ = byte;
+	}
+}
+
+static inline void bcm2835_wr_fifo(struct bcm2835_spi *bs, int len)
+{
+	u8 byte;
+
+	if (len > bs->len)
+		len = bs->len;
+
+	while (len--) {
+		byte = bs->tx_buf ? *bs->tx_buf++ : 0;
+		bcm2835_wr(bs, BCM2835_SPI_FIFO, byte);
+		bs->len--;
+	}
+}
+
+static irqreturn_t bcm2835_spi_interrupt(int irq, void *dev_id)
+{
+	struct spi_master *master = dev_id;
+	struct bcm2835_spi *bs = spi_master_get_devdata(master);
+	u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS);
+
+	/*
+	 * RXR - RX needs Reading. This means 12 (or more) bytes have been
+	 * transmitted and hence 12 (or more) bytes have been received.
+	 *
+	 * The FIFO is 16-bytes deep. We check for this interrupt to keep the
+	 * FIFO full; we have a 4-byte-time buffer for IRQ latency. We check
+	 * this before DONE (TX empty) just in case we delayed processing this
+	 * interrupt for some reason.
+	 *
+	 * We only check for this case if we have more bytes to TX; at the end
+	 * of the transfer, we ignore this pipelining optimization, and let
+	 * bcm2835_spi_finish_transfer() drain the RX FIFO.
+	 */
+	if (bs->len && (cs & BCM2835_SPI_CS_RXR)) {
+		/* Read 12 bytes of data */
+		bcm2835_rd_fifo(bs, 12);
+
+		/* Write up to 12 bytes */
+		bcm2835_wr_fifo(bs, 12);
+
+		/*
+		 * We must have written something to the TX FIFO due to the
+		 * bs->len check above, so cannot be DONE. Hence, return
+		 * early. Note that DONE could also be set if we serviced an
+		 * RXR interrupt really late.
+		 */
+		return IRQ_HANDLED;
+	}
+
+	/*
+	 * DONE - TX empty. This occurs when we first enable the transfer
+	 * since we do not pre-fill the TX FIFO. At any other time, given that
+	 * we refill the TX FIFO above based on RXR, and hence ignore DONE if
+	 * RXR is set, DONE really does mean end-of-transfer.
+	 */
+	if (cs & BCM2835_SPI_CS_DONE) {
+		if (bs->len) { /* First interrupt in a transfer */
+			bcm2835_wr_fifo(bs, 16);
+		} else { /* Transfer complete */
+			/* Disable SPI interrupts */
+			cs &= ~(BCM2835_SPI_CS_INTR | BCM2835_SPI_CS_INTD);
+			bcm2835_wr(bs, BCM2835_SPI_CS, cs);
+
+			/*
+			 * Wake up bcm2835_spi_transfer_one(), which will call
+			 * bcm2835_spi_finish_transfer(), to drain the RX FIFO.
+			 */
+			complete(&bs->done);
+		}
+
+		return IRQ_HANDLED;
+	}
+
+	return IRQ_NONE;
+}
+
+static int bcm2835_spi_start_transfer(struct spi_device *spi,
+		struct spi_transfer *tfr)
+{
+	struct bcm2835_spi *bs = spi_master_get_devdata(spi->master);
+	unsigned long spi_hz, clk_hz, cdiv;
+	u32 cs = BCM2835_SPI_CS_INTR | BCM2835_SPI_CS_INTD | BCM2835_SPI_CS_TA;
+
+	spi_hz = tfr->speed_hz;
+	clk_hz = clk_get_rate(bs->clk);
+
+	if (spi_hz >= clk_hz / 2) {
+		cdiv = 2; /* clk_hz/2 is the fastest we can go */
+	} else if (spi_hz) {
+		/* CDIV must be a power of two */
+		cdiv = roundup_pow_of_two(DIV_ROUND_UP(clk_hz, spi_hz));
+
+		if (cdiv >= 65536)
+			cdiv = 0; /* 0 is the slowest we can go */
+	} else
+		cdiv = 0; /* 0 is the slowest we can go */
+
+	if (spi->mode & SPI_CPOL)
+		cs |= BCM2835_SPI_CS_CPOL;
+	if (spi->mode & SPI_CPHA)
+		cs |= BCM2835_SPI_CS_CPHA;
+
+	if (!(spi->mode & SPI_NO_CS)) {
+		if (spi->mode & SPI_CS_HIGH) {
+			cs |= BCM2835_SPI_CS_CSPOL;
+			cs |= BCM2835_SPI_CS_CSPOL0 << spi->chip_select;
+		}
+
+		cs |= spi->chip_select;
+	}
+
+	INIT_COMPLETION(bs->done);
+	bs->tx_buf = tfr->tx_buf;
+	bs->rx_buf = tfr->rx_buf;
+	bs->len = tfr->len;
+
+	bcm2835_wr(bs, BCM2835_SPI_CLK, cdiv);
+	/*
+	 * Enable the HW block. This will immediately trigger a DONE (TX
+	 * empty) interrupt, upon which we will fill the TX FIFO with the
+	 * first TX bytes. Pre-filling the TX FIFO here to avoid the
+	 * interrupt doesn't work:-(
+	 */
+	bcm2835_wr(bs, BCM2835_SPI_CS, cs);
+
+	return 0;
+}
+
+static int bcm2835_spi_finish_transfer(struct spi_device *spi,
+		struct spi_transfer *tfr, bool cs_change)
+{
+	struct bcm2835_spi *bs = spi_master_get_devdata(spi->master);
+	u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS);
+
+	/* Drain RX FIFO */
+	while (cs & BCM2835_SPI_CS_RXD) {
+		bcm2835_rd_fifo(bs, 1);
+		cs = bcm2835_rd(bs, BCM2835_SPI_CS);
+	}
+
+	if (tfr->delay_usecs)
+		udelay(tfr->delay_usecs);
+
+	if (cs_change)
+		/* Clear TA flag */
+		bcm2835_wr(bs, BCM2835_SPI_CS, cs & ~BCM2835_SPI_CS_TA);
+
+	return 0;
+}
+
+static int bcm2835_spi_transfer_one(struct spi_master *master,
+		struct spi_message *mesg)
+{
+	struct bcm2835_spi *bs = spi_master_get_devdata(master);
+	struct spi_transfer *tfr;
+	struct spi_device *spi = mesg->spi;
+	int err = 0;
+	unsigned int timeout;
+	bool cs_change;
+
+	list_for_each_entry(tfr, &mesg->transfers, transfer_list) {
+		err = bcm2835_spi_start_transfer(spi, tfr);
+		if (err)
+			goto out;
+
+		timeout = wait_for_completion_timeout(&bs->done,
+				msecs_to_jiffies(BCM2835_SPI_TIMEOUT_MS));
+		if (!timeout) {
+			err = -ETIMEDOUT;
+			goto out;
+		}
+
+		cs_change = tfr->cs_change ||
+			list_is_last(&tfr->transfer_list, &mesg->transfers);
+
+		err = bcm2835_spi_finish_transfer(spi, tfr, cs_change);
+		if (err)
+			goto out;
+
+		mesg->actual_length += (tfr->len - bs->len);
+	}
+
+out:
+	/* Clear FIFOs, and disable the HW block */
+	bcm2835_wr(bs, BCM2835_SPI_CS,
+		   BCM2835_SPI_CS_CLEAR_RX | BCM2835_SPI_CS_CLEAR_TX);
+	mesg->status = err;
+	spi_finalize_current_message(master);
+
+	return 0;
+}
+
+static int bcm2835_spi_probe(struct platform_device *pdev)
+{
+	struct spi_master *master;
+	struct bcm2835_spi *bs;
+	struct resource *res;
+	int err;
+
+	master = spi_alloc_master(&pdev->dev, sizeof(*bs));
+	if (!master) {
+		dev_err(&pdev->dev, "spi_alloc_master() failed\n");
+		return -ENOMEM;
+	}
+
+	platform_set_drvdata(pdev, master);
+
+	master->mode_bits = BCM2835_SPI_MODE_BITS;
+	master->bits_per_word_mask = BIT(8 - 1);
+	master->bus_num = -1;
+	master->num_chipselect = 3;
+	master->transfer_one_message = bcm2835_spi_transfer_one;
+	master->dev.of_node = pdev->dev.of_node;
+
+	bs = spi_master_get_devdata(master);
+
+	init_completion(&bs->done);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "could not get memory resource\n");
+		err = -ENODEV;
+		goto out_master_put;
+	}
+
+	bs->regs = devm_request_and_ioremap(&pdev->dev, res);
+	if (!bs->regs) {
+		dev_err(&pdev->dev, "could not request/map memory region\n");
+		err = -ENODEV;
+		goto out_master_put;
+	}
+
+	bs->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(bs->clk)) {
+		err = PTR_ERR(bs->clk);
+		dev_err(&pdev->dev, "could not get clk: %d\n", err);
+		goto out_master_put;
+	}
+
+	bs->irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
+	if (bs->irq <= 0) {
+		dev_err(&pdev->dev, "could not get IRQ: %d\n", bs->irq);
+		err = bs->irq ? bs->irq : -ENODEV;
+		goto out_master_put;
+	}
+
+	clk_prepare_enable(bs->clk);
+
+	err = request_irq(bs->irq, bcm2835_spi_interrupt, 0,
+			dev_name(&pdev->dev), master);
+	if (err) {
+		dev_err(&pdev->dev, "could not request IRQ: %d\n", err);
+		goto out_clk_disable;
+	}
+
+	/* initialise the hardware */
+	bcm2835_wr(bs, BCM2835_SPI_CS,
+		   BCM2835_SPI_CS_CLEAR_RX | BCM2835_SPI_CS_CLEAR_TX);
+
+	err = spi_register_master(master);
+	if (err) {
+		dev_err(&pdev->dev, "could not register SPI master: %d\n", err);
+		goto out_free_irq;
+	}
+
+	return 0;
+
+out_free_irq:
+	free_irq(bs->irq, master);
+out_clk_disable:
+	clk_disable_unprepare(bs->clk);
+out_master_put:
+	spi_master_put(master);
+	return err;
+}
+
+static int bcm2835_spi_remove(struct platform_device *pdev)
+{
+	struct spi_master *master = platform_get_drvdata(pdev);
+	struct bcm2835_spi *bs = spi_master_get_devdata(master);
+
+	free_irq(bs->irq, master);
+	spi_unregister_master(master);
+
+	/* Clear FIFOs, and disable the HW block */
+	bcm2835_wr(bs, BCM2835_SPI_CS,
+		   BCM2835_SPI_CS_CLEAR_RX | BCM2835_SPI_CS_CLEAR_TX);
+
+	clk_disable_unprepare(bs->clk);
+	spi_master_put(master);
+
+	return 0;
+}
+
+static const struct of_device_id bcm2835_spi_match[] = {
+	{ .compatible = "brcm,bcm2835-spi", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, bcm2835_spi_match);
+
+static struct platform_driver bcm2835_spi_driver = {
+	.driver		= {
+		.name		= DRV_NAME,
+		.owner		= THIS_MODULE,
+		.of_match_table	= bcm2835_spi_match,
+	},
+	.probe		= bcm2835_spi_probe,
+	.remove		= bcm2835_spi_remove,
+};
+module_platform_driver(bcm2835_spi_driver);
+
+MODULE_DESCRIPTION("SPI controller driver for Broadcom BCM2835");
+MODULE_AUTHOR("Chris Boot <bootc@bootc.net>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c
index 9578af7..973099b 100644
--- a/drivers/spi/spi-bcm63xx.c
+++ b/drivers/spi/spi-bcm63xx.c
@@ -93,40 +93,16 @@ static const unsigned bcm63xx_spi_freq_table[SPI_CLK_MASK][2] = {
 	{   391000, SPI_CLK_0_391MHZ }
 };
 
-static int bcm63xx_spi_check_transfer(struct spi_device *spi,
-					struct spi_transfer *t)
-{
-	u8 bits_per_word;
-
-	bits_per_word = (t) ? t->bits_per_word : spi->bits_per_word;
-	if (bits_per_word != 8) {
-		dev_err(&spi->dev, "%s, unsupported bits_per_word=%d\n",
-			__func__, bits_per_word);
-		return -EINVAL;
-	}
-
-	if (spi->chip_select > spi->master->num_chipselect) {
-		dev_err(&spi->dev, "%s, unsupported slave %d\n",
-			__func__, spi->chip_select);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
 static void bcm63xx_spi_setup_transfer(struct spi_device *spi,
 				      struct spi_transfer *t)
 {
 	struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master);
-	u32 hz;
 	u8 clk_cfg, reg;
 	int i;
 
-	hz = (t) ? t->speed_hz : spi->max_speed_hz;
-
 	/* Find the closest clock configuration */
 	for (i = 0; i < SPI_CLK_MASK; i++) {
-		if (hz >= bcm63xx_spi_freq_table[i][0]) {
+		if (t->speed_hz >= bcm63xx_spi_freq_table[i][0]) {
 			clk_cfg = bcm63xx_spi_freq_table[i][1];
 			break;
 		}
@@ -143,7 +119,7 @@ static void bcm63xx_spi_setup_transfer(struct spi_device *spi,
 
 	bcm_spi_writeb(bs, reg, SPI_CLK_CFG);
 	dev_dbg(&spi->dev, "Setting clock register to %02x (hz %d)\n",
-		clk_cfg, hz);
+		clk_cfg, t->speed_hz);
 }
 
 /* the spi->mode bits understood by this driver: */
@@ -151,23 +127,12 @@ static void bcm63xx_spi_setup_transfer(struct spi_device *spi,
 
 static int bcm63xx_spi_setup(struct spi_device *spi)
 {
-	struct bcm63xx_spi *bs;
-	int ret;
-
-	bs = spi_master_get_devdata(spi->master);
-
-	if (!spi->bits_per_word)
-		spi->bits_per_word = 8;
-
-	if (spi->mode & ~MODEBITS) {
-		dev_err(&spi->dev, "%s, unsupported mode bits %x\n",
-			__func__, spi->mode & ~MODEBITS);
+	if (spi->bits_per_word != 8) {
+		dev_err(&spi->dev, "%s, unsupported bits_per_word=%d\n",
+			__func__, spi->bits_per_word);
 		return -EINVAL;
 	}
 
-	dev_dbg(&spi->dev, "%s, mode %d, %u bits/w, %u nsec/bit\n",
-		__func__, spi->mode & MODEBITS, spi->bits_per_word, 0);
-
 	return 0;
 }
 
@@ -313,9 +278,12 @@ static int bcm63xx_spi_transfer_one(struct spi_master *master,
 	 * full-duplex transfers.
 	 */
 	list_for_each_entry(t, &m->transfers, transfer_list) {
-		status = bcm63xx_spi_check_transfer(spi, t);
-		if (status < 0)
+		if (t->bits_per_word != 8) {
+			dev_err(&spi->dev, "%s, unsupported bits_per_word=%d\n",
+				__func__, t->bits_per_word);
+			status = -EINVAL;
 			goto exit;
+		}
 
 		if (!first)
 			first = t;
@@ -444,18 +412,9 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, master);
 	bs->pdev = pdev;
 
-	if (!devm_request_mem_region(&pdev->dev, r->start,
-					resource_size(r), PFX)) {
-		dev_err(dev, "iomem request failed\n");
-		ret = -ENXIO;
-		goto out_err;
-	}
-
-	bs->regs = devm_ioremap_nocache(&pdev->dev, r->start,
-							resource_size(r));
-	if (!bs->regs) {
-		dev_err(dev, "unable to ioremap regs\n");
-		ret = -ENOMEM;
+	bs->regs = devm_ioremap_resource(&pdev->dev, r);
+	if (IS_ERR(bs->regs)) {
+		ret = PTR_ERR(bs->regs);
 		goto out_err;
 	}
 
@@ -490,11 +449,11 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
 	default:
 		dev_err(dev, "unsupported MSG_CTL width: %d\n",
 			 bs->msg_ctl_width);
-		goto out_clk_disable;
+		goto out_err;
 	}
 
 	/* Initialize hardware */
-	clk_enable(bs->clk);
+	clk_prepare_enable(bs->clk);
 	bcm_spi_writeb(bs, SPI_INTR_CLEAR_ALL, SPI_INT_STATUS);
 
 	/* register and we are done */
@@ -510,7 +469,7 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
 	return 0;
 
 out_clk_disable:
-	clk_disable(clk);
+	clk_disable_unprepare(clk);
 out_err:
 	platform_set_drvdata(pdev, NULL);
 	spi_master_put(master);
@@ -531,7 +490,7 @@ static int bcm63xx_spi_remove(struct platform_device *pdev)
 	bcm_spi_writeb(bs, 0, SPI_INT_MASK);
 
 	/* HW shutdown */
-	clk_disable(bs->clk);
+	clk_disable_unprepare(bs->clk);
 	clk_put(bs->clk);
 
 	platform_set_drvdata(pdev, 0);
@@ -550,7 +509,7 @@ static int bcm63xx_spi_suspend(struct device *dev)
 
 	spi_master_suspend(master);
 
-	clk_disable(bs->clk);
+	clk_disable_unprepare(bs->clk);
 
 	return 0;
 }
@@ -561,7 +520,7 @@ static int bcm63xx_spi_resume(struct device *dev)
 			platform_get_drvdata(to_platform_device(dev));
 	struct bcm63xx_spi *bs = spi_master_get_devdata(master);
 
-	clk_enable(bs->clk);
+	clk_prepare_enable(bs->clk);
 
 	spi_master_resume(master);
 
diff --git a/drivers/spi/spi-fsl-spi.c b/drivers/spi/spi-fsl-spi.c
index 086a9ee..1985ba3 100644
--- a/drivers/spi/spi-fsl-spi.c
+++ b/drivers/spi/spi-fsl-spi.c
@@ -1134,9 +1134,7 @@ static int plat_mpc8xxx_spi_probe(struct platform_device *pdev)
 		return -EINVAL;
 
 	master = fsl_spi_probe(&pdev->dev, mem, irq);
-	if (IS_ERR(master))
-		return PTR_ERR(master);
-	return 0;
+	return PTR_RET(master);
 }
 
 static int plat_mpc8xxx_spi_remove(struct platform_device *pdev)
diff --git a/drivers/spi/spi-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c
index 89480b2..3e490ee 100644
--- a/drivers/spi/spi-mpc512x-psc.c
+++ b/drivers/spi/spi-mpc512x-psc.c
@@ -164,7 +164,7 @@ static int mpc512x_psc_spi_transfer_rxtx(struct spi_device *spi,
 
 		for (i = count; i > 0; i--) {
 			data = tx_buf ? *tx_buf++ : 0;
-			if (len == EOFBYTE)
+			if (len == EOFBYTE && t->cs_change)
 				setbits32(&fifo->txcmd, MPC512x_PSC_FIFO_EOF);
 			out_8(&fifo->txdata_8, data);
 			len--;
diff --git a/drivers/spi/spi-mxs.c b/drivers/spi/spi-mxs.c
index 22a0af0..8498276 100644
--- a/drivers/spi/spi-mxs.c
+++ b/drivers/spi/spi-mxs.c
@@ -490,21 +490,6 @@ static int mxs_spi_transfer_one(struct spi_master *master,
 	return status;
 }
 
-static bool mxs_ssp_dma_filter(struct dma_chan *chan, void *param)
-{
-	struct mxs_ssp *ssp = param;
-
-	if (!mxs_dma_is_apbh(chan))
-		return false;
-
-	if (chan->chan_id != ssp->dma_channel)
-		return false;
-
-	chan->private = &ssp->dma_data;
-
-	return true;
-}
-
 static const struct of_device_id mxs_spi_dt_ids[] = {
 	{ .compatible = "fsl,imx23-spi", .data = (void *) IMX23_SSP, },
 	{ .compatible = "fsl,imx28-spi", .data = (void *) IMX28_SSP, },
@@ -520,13 +505,12 @@ static int mxs_spi_probe(struct platform_device *pdev)
 	struct spi_master *master;
 	struct mxs_spi *spi;
 	struct mxs_ssp *ssp;
-	struct resource *iores, *dmares;
+	struct resource *iores;
 	struct pinctrl *pinctrl;
 	struct clk *clk;
 	void __iomem *base;
-	int devid, dma_channel, clk_freq;
-	int ret = 0, irq_err, irq_dma;
-	dma_cap_mask_t mask;
+	int devid, clk_freq;
+	int ret = 0, irq_err;
 
 	/*
 	 * Default clock speed for the SPI core. 160MHz seems to
@@ -537,8 +521,7 @@ static int mxs_spi_probe(struct platform_device *pdev)
 
 	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	irq_err = platform_get_irq(pdev, 0);
-	irq_dma = platform_get_irq(pdev, 1);
-	if (!iores || irq_err < 0 || irq_dma < 0)
+	if (!iores || irq_err < 0)
 		return -EINVAL;
 
 	base = devm_ioremap_resource(&pdev->dev, iores);
@@ -553,32 +536,11 @@ static int mxs_spi_probe(struct platform_device *pdev)
 	if (IS_ERR(clk))
 		return PTR_ERR(clk);
 
-	if (np) {
-		devid = (enum mxs_ssp_id) of_id->data;
-		/*
-		 * TODO: This is a temporary solution and should be changed
-		 * to use generic DMA binding later when the helpers get in.
-		 */
-		ret = of_property_read_u32(np, "fsl,ssp-dma-channel",
-					   &dma_channel);
-		if (ret) {
-			dev_err(&pdev->dev,
-				"Failed to get DMA channel\n");
-			return -EINVAL;
-		}
-
-		ret = of_property_read_u32(np, "clock-frequency",
-					   &clk_freq);
-		if (ret)
-			clk_freq = clk_freq_default;
-	} else {
-		dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0);
-		if (!dmares)
-			return -EINVAL;
-		devid = pdev->id_entry->driver_data;
-		dma_channel = dmares->start;
+	devid = (enum mxs_ssp_id) of_id->data;
+	ret = of_property_read_u32(np, "clock-frequency",
+				   &clk_freq);
+	if (ret)
 		clk_freq = clk_freq_default;
-	}
 
 	master = spi_alloc_master(&pdev->dev, sizeof(*spi));
 	if (!master)
@@ -597,7 +559,6 @@ static int mxs_spi_probe(struct platform_device *pdev)
 	ssp->clk = clk;
 	ssp->base = base;
 	ssp->devid = devid;
-	ssp->dma_channel = dma_channel;
 
 	init_completion(&spi->c);
 
@@ -606,12 +567,10 @@ static int mxs_spi_probe(struct platform_device *pdev)
 	if (ret)
 		goto out_master_free;
 
-	dma_cap_zero(mask);
-	dma_cap_set(DMA_SLAVE, mask);
-	ssp->dma_data.chan_irq = irq_dma;
-	ssp->dmach = dma_request_channel(mask, mxs_ssp_dma_filter, ssp);
+	ssp->dmach = dma_request_slave_channel(&pdev->dev, "rx-tx");
 	if (!ssp->dmach) {
 		dev_err(ssp->dev, "Failed to request DMA\n");
+		ret = -ENODEV;
 		goto out_master_free;
 	}
 
diff --git a/drivers/spi/spi-oc-tiny.c b/drivers/spi/spi-oc-tiny.c
index cb2e284..e60a776 100644
--- a/drivers/spi/spi-oc-tiny.c
+++ b/drivers/spi/spi-oc-tiny.c
@@ -393,8 +393,6 @@ static const struct of_device_id tiny_spi_match[] = {
 	{},
 };
 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 = {
@@ -404,7 +402,7 @@ static struct platform_driver tiny_spi_driver = {
 		.name = DRV_NAME,
 		.owner = THIS_MODULE,
 		.pm = NULL,
-		.of_match_table = tiny_spi_match,
+		.of_match_table = of_match_ptr(tiny_spi_match),
 	},
 };
 module_platform_driver(tiny_spi_driver);
diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c
index 893c3d7..61eef47 100644
--- a/drivers/spi/spi-omap2-mcspi.c
+++ b/drivers/spi/spi-omap2-mcspi.c
@@ -285,8 +285,12 @@ static int mcspi_wait_for_reg_bit(void __iomem *reg, unsigned long bit)
 
 	timeout = jiffies + msecs_to_jiffies(1000);
 	while (!(__raw_readl(reg) & bit)) {
-		if (time_after(jiffies, timeout))
-			return -1;
+		if (time_after(jiffies, timeout)) {
+			if (!(__raw_readl(reg) & bit))
+				return -ETIMEDOUT;
+			else
+				return 0;
+		}
 		cpu_relax();
 	}
 	return 0;
diff --git a/drivers/spi/spi-pxa2xx-pci.c b/drivers/spi/spi-pxa2xx-pci.c
index 364964d..74bc187 100644
--- a/drivers/spi/spi-pxa2xx-pci.c
+++ b/drivers/spi/spi-pxa2xx-pci.c
@@ -22,7 +22,7 @@ static int ce4100_spi_probe(struct pci_dev *dev,
 		return ret;
 
 	ret = pcim_iomap_regions(dev, 1 << 0, "PXA2xx SPI");
-	if (!ret)
+	if (ret)
 		return ret;
 
 	memset(&spi_pdata, 0, sizeof(spi_pdata));
@@ -47,8 +47,8 @@ static int ce4100_spi_probe(struct pci_dev *dev,
 	pi.size_data = sizeof(spi_pdata);
 
 	pdev = platform_device_register_full(&pi);
-	if (!pdev)
-		return -ENOMEM;
+	if (IS_ERR(pdev))
+		return PTR_ERR(pdev);
 
 	pci_set_drvdata(dev, pdev);
 
diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c
index 90b27a3..1c2208c 100644
--- a/drivers/spi/spi-pxa2xx.c
+++ b/drivers/spi/spi-pxa2xx.c
@@ -68,6 +68,7 @@ MODULE_ALIAS("platform:pxa2xx-spi");
 #define LPSS_TX_HITHRESH_DFLT	224
 
 /* Offset from drv_data->lpss_base */
+#define SSP_REG			0x0c
 #define SPI_CS_CONTROL		0x18
 #define SPI_CS_CONTROL_SW_MODE	BIT(0)
 #define SPI_CS_CONTROL_CS_HIGH	BIT(1)
@@ -138,6 +139,10 @@ detection_done:
 	/* Enable software chip select control */
 	value = SPI_CS_CONTROL_SW_MODE | SPI_CS_CONTROL_CS_HIGH;
 	__lpss_ssp_write_priv(drv_data, SPI_CS_CONTROL, value);
+
+	/* Enable multiblock DMA transfers */
+	if (drv_data->master_info->enable_dma)
+		__lpss_ssp_write_priv(drv_data, SSP_REG, 1);
 }
 
 static void lpss_ssp_cs_control(struct driver_data *drv_data, bool enable)
@@ -1168,7 +1173,6 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
 
 	master->dev.parent = &pdev->dev;
 	master->dev.of_node = pdev->dev.of_node;
-	ACPI_HANDLE_SET(&master->dev, ACPI_HANDLE(&pdev->dev));
 	/* the spi->mode bits understood by this driver: */
 	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP;
 
diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c
index e862ab8..682b1e7 100644
--- a/drivers/spi/spi-s3c64xx.c
+++ b/drivers/spi/spi-s3c64xx.c
@@ -817,7 +817,6 @@ static int s3c64xx_spi_unprepare_transfer(struct spi_master *spi)
 }
 
 static struct s3c64xx_spi_csinfo *s3c64xx_get_slave_ctrldata(
-				struct s3c64xx_spi_driver_data *sdd,
 				struct spi_device *spi)
 {
 	struct s3c64xx_spi_csinfo *cs;
@@ -874,7 +873,7 @@ static int s3c64xx_spi_setup(struct spi_device *spi)
 
 	sdd = spi_master_get_devdata(spi->master);
 	if (!cs && spi->dev.of_node) {
-		cs = s3c64xx_get_slave_ctrldata(sdd, spi);
+		cs = s3c64xx_get_slave_ctrldata(spi);
 		spi->controller_data = cs;
 	}
 
@@ -912,15 +911,6 @@ static int s3c64xx_spi_setup(struct spi_device *spi)
 
 	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;
-	}
-
 	pm_runtime_get_sync(&sdd->pdev->dev);
 
 	/* Check if we can provide the requested rate */
@@ -994,25 +984,30 @@ static irqreturn_t s3c64xx_spi_irq(int irq, void *data)
 {
 	struct s3c64xx_spi_driver_data *sdd = data;
 	struct spi_master *spi = sdd->master;
-	unsigned int val;
-
-	val = readl(sdd->regs + S3C64XX_SPI_PENDING_CLR);
-
-	val &= S3C64XX_SPI_PND_RX_OVERRUN_CLR |
-		S3C64XX_SPI_PND_RX_UNDERRUN_CLR |
-		S3C64XX_SPI_PND_TX_OVERRUN_CLR |
-		S3C64XX_SPI_PND_TX_UNDERRUN_CLR;
+	unsigned int val, clr = 0;
 
-	writel(val, sdd->regs + S3C64XX_SPI_PENDING_CLR);
+	val = readl(sdd->regs + S3C64XX_SPI_STATUS);
 
-	if (val & S3C64XX_SPI_PND_RX_OVERRUN_CLR)
+	if (val & S3C64XX_SPI_ST_RX_OVERRUN_ERR) {
+		clr = S3C64XX_SPI_PND_RX_OVERRUN_CLR;
 		dev_err(&spi->dev, "RX overrun\n");
-	if (val & S3C64XX_SPI_PND_RX_UNDERRUN_CLR)
+	}
+	if (val & S3C64XX_SPI_ST_RX_UNDERRUN_ERR) {
+		clr |= S3C64XX_SPI_PND_RX_UNDERRUN_CLR;
 		dev_err(&spi->dev, "RX underrun\n");
-	if (val & S3C64XX_SPI_PND_TX_OVERRUN_CLR)
+	}
+	if (val & S3C64XX_SPI_ST_TX_OVERRUN_ERR) {
+		clr |= S3C64XX_SPI_PND_TX_OVERRUN_CLR;
 		dev_err(&spi->dev, "TX overrun\n");
-	if (val & S3C64XX_SPI_PND_TX_UNDERRUN_CLR)
+	}
+	if (val & S3C64XX_SPI_ST_TX_UNDERRUN_ERR) {
+		clr |= S3C64XX_SPI_PND_TX_UNDERRUN_CLR;
 		dev_err(&spi->dev, "TX underrun\n");
+	}
+
+	/* Clear the pending irq by setting and then clearing it */
+	writel(clr, sdd->regs + S3C64XX_SPI_PENDING_CLR);
+	writel(0, sdd->regs + S3C64XX_SPI_PENDING_CLR);
 
 	return IRQ_HANDLED;
 }
@@ -1036,9 +1031,13 @@ static void s3c64xx_spi_hwinit(struct s3c64xx_spi_driver_data *sdd, int channel)
 	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);
+	/* Clear any irq pending bits, should set and clear the bits */
+	val = S3C64XX_SPI_PND_RX_OVERRUN_CLR |
+		S3C64XX_SPI_PND_RX_UNDERRUN_CLR |
+		S3C64XX_SPI_PND_TX_OVERRUN_CLR |
+		S3C64XX_SPI_PND_TX_UNDERRUN_CLR;
+	writel(val, regs + S3C64XX_SPI_PENDING_CLR);
+	writel(0, regs + S3C64XX_SPI_PENDING_CLR);
 
 	writel(0, regs + S3C64XX_SPI_SWAP_CFG);
 
@@ -1238,6 +1237,7 @@ static int s3c64xx_spi_probe(struct platform_device *pdev)
 	master->unprepare_transfer_hardware = s3c64xx_spi_unprepare_transfer;
 	master->num_chipselect = sci->num_cs;
 	master->dma_alignment = 8;
+	master->bits_per_word_mask = BIT(32 - 1) | BIT(16 - 1) | BIT(8 - 1);
 	/* the spi->mode bits understood by this driver: */
 	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
 
@@ -1358,7 +1358,7 @@ static int s3c64xx_spi_remove(struct platform_device *pdev)
 	return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int s3c64xx_spi_suspend(struct device *dev)
 {
 	struct spi_master *master = dev_get_drvdata(dev);
@@ -1399,7 +1399,7 @@ static int s3c64xx_spi_resume(struct device *dev)
 
 	return 0;
 }
-#endif /* CONFIG_PM */
+#endif /* CONFIG_PM_SLEEP */
 
 #ifdef CONFIG_PM_RUNTIME
 static int s3c64xx_spi_runtime_suspend(struct device *dev)
diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c
index 8b40d08..2bc5a6b 100644
--- a/drivers/spi/spi-sh-msiof.c
+++ b/drivers/spi/spi-sh-msiof.c
@@ -764,8 +764,6 @@ static const struct of_device_id sh_msiof_match[] = {
 	{},
 };
 MODULE_DEVICE_TABLE(of, sh_msiof_match);
-#else
-#define sh_msiof_match NULL
 #endif
 
 static struct dev_pm_ops sh_msiof_spi_dev_pm_ops = {
@@ -780,7 +778,7 @@ static struct platform_driver sh_msiof_spi_drv = {
 		.name		= "spi_sh_msiof",
 		.owner		= THIS_MODULE,
 		.pm		= &sh_msiof_spi_dev_pm_ops,
-		.of_match_table = sh_msiof_match,
+		.of_match_table = of_match_ptr(sh_msiof_match),
 	},
 };
 module_platform_driver(sh_msiof_spi_drv);
diff --git a/drivers/spi/spi-tegra20-slink.c b/drivers/spi/spi-tegra20-slink.c
index b8698b3..17224f0 100644
--- a/drivers/spi/spi-tegra20-slink.c
+++ b/drivers/spi/spi-tegra20-slink.c
@@ -375,9 +375,6 @@ static unsigned int tegra_slink_read_rx_fifo_to_client_rxbuf(
 		tspi->cur_rx_pos += tspi->curr_dma_words * tspi->bytes_per_word;
 		read_words += tspi->curr_dma_words;
 	} else {
-		unsigned int bits_per_word;
-
-		bits_per_word = t->bits_per_word;
 		for (count = 0; count < rx_full_count; count++) {
 			x = tegra_slink_readl(tspi, SLINK_RX_FIFO);
 			for (i = 0; (i < tspi->bytes_per_word); i++)
@@ -858,21 +855,6 @@ static int tegra_slink_setup(struct spi_device *spi)
 	return 0;
 }
 
-static int tegra_slink_prepare_transfer(struct spi_master *master)
-{
-	struct tegra_slink_data *tspi = spi_master_get_devdata(master);
-
-	return pm_runtime_get_sync(tspi->dev);
-}
-
-static int tegra_slink_unprepare_transfer(struct spi_master *master)
-{
-	struct tegra_slink_data *tspi = spi_master_get_devdata(master);
-
-	pm_runtime_put(tspi->dev);
-	return 0;
-}
-
 static int tegra_slink_transfer_one_message(struct spi_master *master,
 			struct spi_message *msg)
 {
@@ -885,6 +867,12 @@ static int tegra_slink_transfer_one_message(struct spi_master *master,
 
 	msg->status = 0;
 	msg->actual_length = 0;
+	ret = pm_runtime_get_sync(tspi->dev);
+	if (ret < 0) {
+		dev_err(tspi->dev, "runtime get failed: %d\n", ret);
+		goto done;
+	}
+
 	single_xfer = list_is_singular(&msg->transfers);
 	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
 		INIT_COMPLETION(tspi->xfer_completion);
@@ -921,6 +909,8 @@ static int tegra_slink_transfer_one_message(struct spi_master *master,
 exit:
 	tegra_slink_writel(tspi, tspi->def_command_reg, SLINK_COMMAND);
 	tegra_slink_writel(tspi, tspi->def_command2_reg, SLINK_COMMAND2);
+	pm_runtime_put(tspi->dev);
+done:
 	msg->status = ret;
 	spi_finalize_current_message(master);
 	return ret;
@@ -1148,9 +1138,7 @@ static int tegra_slink_probe(struct platform_device *pdev)
 	/* the spi->mode bits understood by this driver: */
 	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
 	master->setup = tegra_slink_setup;
-	master->prepare_transfer_hardware = tegra_slink_prepare_transfer;
 	master->transfer_one_message = tegra_slink_transfer_one_message;
-	master->unprepare_transfer_hardware = tegra_slink_unprepare_transfer;
 	master->num_chipselect = MAX_CHIP_SELECT;
 	master->bus_num = -1;
 
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index f996c60..163fd80 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -543,17 +543,16 @@ static void spi_pump_messages(struct kthread_work *work)
 	/* Lock queue and check for queue work */
 	spin_lock_irqsave(&master->queue_lock, flags);
 	if (list_empty(&master->queue) || !master->running) {
-		if (master->busy && master->unprepare_transfer_hardware) {
-			ret = master->unprepare_transfer_hardware(master);
-			if (ret) {
-				spin_unlock_irqrestore(&master->queue_lock, flags);
-				dev_err(&master->dev,
-					"failed to unprepare transfer hardware\n");
-				return;
-			}
+		if (!master->busy) {
+			spin_unlock_irqrestore(&master->queue_lock, flags);
+			return;
 		}
 		master->busy = false;
 		spin_unlock_irqrestore(&master->queue_lock, flags);
+		if (master->unprepare_transfer_hardware &&
+		    master->unprepare_transfer_hardware(master))
+			dev_err(&master->dev,
+				"failed to unprepare transfer hardware\n");
 		return;
 	}
 
@@ -984,7 +983,7 @@ static void acpi_register_spi_devices(struct spi_master *master)
 	acpi_status status;
 	acpi_handle handle;
 
-	handle = ACPI_HANDLE(&master->dev);
+	handle = ACPI_HANDLE(master->dev.parent);
 	if (!handle)
 		return;
 
@@ -1377,6 +1376,14 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message)
 			xfer->bits_per_word = spi->bits_per_word;
 		if (!xfer->speed_hz)
 			xfer->speed_hz = spi->max_speed_hz;
+		if (master->bits_per_word_mask) {
+			/* Only 32 bits fit in the mask */
+			if (xfer->bits_per_word > 32)
+				return -EINVAL;
+			if (!(master->bits_per_word_mask &
+					BIT(xfer->bits_per_word - 1)))
+				return -EINVAL;
+		}
 	}
 
 	message->spi = spi;
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
index 2e0655d..911e9e0 100644
--- a/drivers/spi/spidev.c
+++ b/drivers/spi/spidev.c
@@ -603,7 +603,7 @@ static int spidev_probe(struct spi_device *spi)
 		dev = device_create(spidev_class, &spi->dev, spidev->devt,
 				    spidev, "spidev%d.%d",
 				    spi->master->bus_num, spi->chip_select);
-		status = IS_ERR(dev) ? PTR_ERR(dev) : 0;
+		status = PTR_RET(dev);
 	} else {
 		dev_dbg(&spi->dev, "no minor number available!\n");
 		status = -ENODEV;
diff --git a/drivers/ssb/driver_chipcommon.c b/drivers/ssb/driver_chipcommon.c
index 71098a7..7cb7d2c 100644
--- a/drivers/ssb/driver_chipcommon.c
+++ b/drivers/ssb/driver_chipcommon.c
@@ -354,7 +354,7 @@ void ssb_chipcommon_init(struct ssb_chipcommon *cc)
 
 	if (cc->dev->id.revision >= 11)
 		cc->status = chipco_read32(cc, SSB_CHIPCO_CHIPSTAT);
-	ssb_dprintk(KERN_INFO PFX "chipcommon status is 0x%x\n", cc->status);
+	ssb_dbg("chipcommon status is 0x%x\n", cc->status);
 
 	if (cc->dev->id.revision >= 20) {
 		chipco_write32(cc, SSB_CHIPCO_GPIOPULLUP, 0);
diff --git a/drivers/ssb/driver_chipcommon_pmu.c b/drivers/ssb/driver_chipcommon_pmu.c
index 4c0f6d8..791da2c 100644
--- a/drivers/ssb/driver_chipcommon_pmu.c
+++ b/drivers/ssb/driver_chipcommon_pmu.c
@@ -110,8 +110,8 @@ static void ssb_pmu0_pllinit_r0(struct ssb_chipcommon *cc,
 		return;
 	}
 
-	ssb_printk(KERN_INFO PFX "Programming PLL to %u.%03u MHz\n",
-		   (crystalfreq / 1000), (crystalfreq % 1000));
+	ssb_info("Programming PLL to %u.%03u MHz\n",
+		 crystalfreq / 1000, crystalfreq % 1000);
 
 	/* First turn the PLL off. */
 	switch (bus->chip_id) {
@@ -138,7 +138,7 @@ static void ssb_pmu0_pllinit_r0(struct ssb_chipcommon *cc,
 	}
 	tmp = chipco_read32(cc, SSB_CHIPCO_CLKCTLST);
 	if (tmp & SSB_CHIPCO_CLKCTLST_HAVEHT)
-		ssb_printk(KERN_EMERG PFX "Failed to turn the PLL off!\n");
+		ssb_emerg("Failed to turn the PLL off!\n");
 
 	/* Set PDIV in PLL control 0. */
 	pllctl = ssb_chipco_pll_read(cc, SSB_PMU0_PLLCTL0);
@@ -249,8 +249,8 @@ static void ssb_pmu1_pllinit_r0(struct ssb_chipcommon *cc,
 		return;
 	}
 
-	ssb_printk(KERN_INFO PFX "Programming PLL to %u.%03u MHz\n",
-		   (crystalfreq / 1000), (crystalfreq % 1000));
+	ssb_info("Programming PLL to %u.%03u MHz\n",
+		 crystalfreq / 1000, crystalfreq % 1000);
 
 	/* First turn the PLL off. */
 	switch (bus->chip_id) {
@@ -275,7 +275,7 @@ static void ssb_pmu1_pllinit_r0(struct ssb_chipcommon *cc,
 	}
 	tmp = chipco_read32(cc, SSB_CHIPCO_CLKCTLST);
 	if (tmp & SSB_CHIPCO_CLKCTLST_HAVEHT)
-		ssb_printk(KERN_EMERG PFX "Failed to turn the PLL off!\n");
+		ssb_emerg("Failed to turn the PLL off!\n");
 
 	/* Set p1div and p2div. */
 	pllctl = ssb_chipco_pll_read(cc, SSB_PMU1_PLLCTL0);
@@ -349,9 +349,8 @@ static void ssb_pmu_pll_init(struct ssb_chipcommon *cc)
 	case 43222:
 		break;
 	default:
-		ssb_printk(KERN_ERR PFX
-			   "ERROR: PLL init unknown for device %04X\n",
-			   bus->chip_id);
+		ssb_err("ERROR: PLL init unknown for device %04X\n",
+			bus->chip_id);
 	}
 }
 
@@ -472,9 +471,8 @@ static void ssb_pmu_resources_init(struct ssb_chipcommon *cc)
 		max_msk = 0xFFFFF;
 		break;
 	default:
-		ssb_printk(KERN_ERR PFX
-			   "ERROR: PMU resource config unknown for device %04X\n",
-			   bus->chip_id);
+		ssb_err("ERROR: PMU resource config unknown for device %04X\n",
+			bus->chip_id);
 	}
 
 	if (updown_tab) {
@@ -526,8 +524,8 @@ void ssb_pmu_init(struct ssb_chipcommon *cc)
 	pmucap = chipco_read32(cc, SSB_CHIPCO_PMU_CAP);
 	cc->pmu.rev = (pmucap & SSB_CHIPCO_PMU_CAP_REVISION);
 
-	ssb_dprintk(KERN_DEBUG PFX "Found rev %u PMU (capabilities 0x%08X)\n",
-		    cc->pmu.rev, pmucap);
+	ssb_dbg("Found rev %u PMU (capabilities 0x%08X)\n",
+		cc->pmu.rev, pmucap);
 
 	if (cc->pmu.rev == 1)
 		chipco_mask32(cc, SSB_CHIPCO_PMU_CTL,
@@ -638,9 +636,8 @@ u32 ssb_pmu_get_alp_clock(struct ssb_chipcommon *cc)
 	case 0x5354:
 		ssb_pmu_get_alp_clock_clk0(cc);
 	default:
-		ssb_printk(KERN_ERR PFX
-			   "ERROR: PMU alp clock unknown for device %04X\n",
-			   bus->chip_id);
+		ssb_err("ERROR: PMU alp clock unknown for device %04X\n",
+			bus->chip_id);
 		return 0;
 	}
 }
@@ -654,9 +651,8 @@ u32 ssb_pmu_get_cpu_clock(struct ssb_chipcommon *cc)
 		/* 5354 chip uses a non programmable PLL of frequency 240MHz */
 		return 240000000;
 	default:
-		ssb_printk(KERN_ERR PFX
-			   "ERROR: PMU cpu clock unknown for device %04X\n",
-			   bus->chip_id);
+		ssb_err("ERROR: PMU cpu clock unknown for device %04X\n",
+			bus->chip_id);
 		return 0;
 	}
 }
@@ -669,9 +665,8 @@ u32 ssb_pmu_get_controlclock(struct ssb_chipcommon *cc)
 	case 0x5354:
 		return 120000000;
 	default:
-		ssb_printk(KERN_ERR PFX
-			   "ERROR: PMU controlclock unknown for device %04X\n",
-			   bus->chip_id);
+		ssb_err("ERROR: PMU controlclock unknown for device %04X\n",
+			bus->chip_id);
 		return 0;
 	}
 }
diff --git a/drivers/ssb/driver_mipscore.c b/drivers/ssb/driver_mipscore.c
index 33b37da..0907706 100644
--- a/drivers/ssb/driver_mipscore.c
+++ b/drivers/ssb/driver_mipscore.c
@@ -18,7 +18,7 @@
 
 #include "ssb_private.h"
 
-static const char *part_probes[] = { "bcm47xxpart", NULL };
+static const char * const part_probes[] = { "bcm47xxpart", NULL };
 
 static struct physmap_flash_data ssb_pflash_data = {
 	.part_probe_types	= part_probes,
@@ -167,21 +167,22 @@ static void set_irq(struct ssb_device *dev, unsigned int irq)
 		irqflag |= (ipsflag & ~ipsflag_irq_mask[irq]);
 		ssb_write32(mdev, SSB_IPSFLAG, irqflag);
 	}
-	ssb_dprintk(KERN_INFO PFX
-		    "set_irq: core 0x%04x, irq %d => %d\n",
-		    dev->id.coreid, oldirq+2, irq+2);
+	ssb_dbg("set_irq: core 0x%04x, irq %d => %d\n",
+		dev->id.coreid, oldirq+2, irq+2);
 }
 
 static void print_irq(struct ssb_device *dev, unsigned int irq)
 {
-	int i;
 	static const char *irq_name[] = {"2(S)", "3", "4", "5", "6", "D", "I"};
-	ssb_dprintk(KERN_INFO PFX
-		"core 0x%04x, irq :", dev->id.coreid);
-	for (i = 0; i <= 6; i++) {
-		ssb_dprintk(" %s%s", irq_name[i], i==irq?"*":" ");
-	}
-	ssb_dprintk("\n");
+	ssb_dbg("core 0x%04x, irq : %s%s %s%s %s%s %s%s %s%s %s%s %s%s\n",
+		dev->id.coreid,
+		irq_name[0], irq == 0 ? "*" : " ",
+		irq_name[1], irq == 1 ? "*" : " ",
+		irq_name[2], irq == 2 ? "*" : " ",
+		irq_name[3], irq == 3 ? "*" : " ",
+		irq_name[4], irq == 4 ? "*" : " ",
+		irq_name[5], irq == 5 ? "*" : " ",
+		irq_name[6], irq == 6 ? "*" : " ");
 }
 
 static void dump_irq(struct ssb_bus *bus)
@@ -286,7 +287,7 @@ void ssb_mipscore_init(struct ssb_mipscore *mcore)
 	if (!mcore->dev)
 		return; /* We don't have a MIPS core */
 
-	ssb_dprintk(KERN_INFO PFX "Initializing MIPS core...\n");
+	ssb_dbg("Initializing MIPS core...\n");
 
 	bus = mcore->dev->bus;
 	hz = ssb_clockspeed(bus);
@@ -334,7 +335,7 @@ void ssb_mipscore_init(struct ssb_mipscore *mcore)
 			break;
 		}
 	}
-	ssb_dprintk(KERN_INFO PFX "after irq reconfiguration\n");
+	ssb_dbg("after irq reconfiguration\n");
 	dump_irq(bus);
 
 	ssb_mips_serial_init(mcore);
diff --git a/drivers/ssb/driver_pcicore.c b/drivers/ssb/driver_pcicore.c
index 59801d2..d75b72b 100644
--- a/drivers/ssb/driver_pcicore.c
+++ b/drivers/ssb/driver_pcicore.c
@@ -263,8 +263,7 @@ int ssb_pcicore_plat_dev_init(struct pci_dev *d)
 		return -ENODEV;
 	}
 
-	ssb_printk(KERN_INFO "PCI: Fixing up device %s\n",
-		   pci_name(d));
+	ssb_info("PCI: Fixing up device %s\n", pci_name(d));
 
 	/* Fix up interrupt lines */
 	d->irq = ssb_mips_irq(extpci_core->dev) + 2;
@@ -285,12 +284,12 @@ static void ssb_pcicore_fixup_pcibridge(struct pci_dev *dev)
 	if (dev->bus->number != 0 || PCI_SLOT(dev->devfn) != 0)
 		return;
 
-	ssb_printk(KERN_INFO "PCI: Fixing up bridge %s\n", pci_name(dev));
+	ssb_info("PCI: Fixing up bridge %s\n", pci_name(dev));
 
 	/* Enable PCI bridge bus mastering and memory space */
 	pci_set_master(dev);
 	if (pcibios_enable_device(dev, ~0) < 0) {
-		ssb_printk(KERN_ERR "PCI: SSB bridge enable failed\n");
+		ssb_err("PCI: SSB bridge enable failed\n");
 		return;
 	}
 
@@ -299,8 +298,8 @@ static void ssb_pcicore_fixup_pcibridge(struct pci_dev *dev)
 
 	/* Make sure our latency is high enough to handle the devices behind us */
 	lat = 168;
-	ssb_printk(KERN_INFO "PCI: Fixing latency timer of device %s to %u\n",
-		   pci_name(dev), lat);
+	ssb_info("PCI: Fixing latency timer of device %s to %u\n",
+		 pci_name(dev), lat);
 	pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
 }
 DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, ssb_pcicore_fixup_pcibridge);
@@ -323,7 +322,7 @@ static void ssb_pcicore_init_hostmode(struct ssb_pcicore *pc)
 		return;
 	extpci_core = pc;
 
-	ssb_dprintk(KERN_INFO PFX "PCIcore in host mode found\n");
+	ssb_dbg("PCIcore in host mode found\n");
 	/* Reset devices on the external PCI bus */
 	val = SSB_PCICORE_CTL_RST_OE;
 	val |= SSB_PCICORE_CTL_CLK_OE;
@@ -338,7 +337,7 @@ static void ssb_pcicore_init_hostmode(struct ssb_pcicore *pc)
 	udelay(1); /* Assertion time demanded by the PCI standard */
 
 	if (pc->dev->bus->has_cardbus_slot) {
-		ssb_dprintk(KERN_INFO PFX "CardBus slot detected\n");
+		ssb_dbg("CardBus slot detected\n");
 		pc->cardbusmode = 1;
 		/* GPIO 1 resets the bridge */
 		ssb_gpio_out(pc->dev->bus, 1, 1);
diff --git a/drivers/ssb/embedded.c b/drivers/ssb/embedded.c
index bb18d76..55e1011 100644
--- a/drivers/ssb/embedded.c
+++ b/drivers/ssb/embedded.c
@@ -57,9 +57,8 @@ int ssb_watchdog_register(struct ssb_bus *bus)
 					     bus->busnumber, &wdt,
 					     sizeof(wdt));
 	if (IS_ERR(pdev)) {
-		ssb_dprintk(KERN_INFO PFX
-			    "can not register watchdog device, err: %li\n",
-			    PTR_ERR(pdev));
+		ssb_dbg("can not register watchdog device, err: %li\n",
+			PTR_ERR(pdev));
 		return PTR_ERR(pdev);
 	}
 
diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c
index 3b645b8..812775a 100644
--- a/drivers/ssb/main.c
+++ b/drivers/ssb/main.c
@@ -275,8 +275,8 @@ int ssb_devices_thaw(struct ssb_freeze_context *ctx)
 
 		err = sdrv->probe(sdev, &sdev->id);
 		if (err) {
-			ssb_printk(KERN_ERR PFX "Failed to thaw device %s\n",
-				   dev_name(sdev->dev));
+			ssb_err("Failed to thaw device %s\n",
+				dev_name(sdev->dev));
 			result = err;
 		}
 		ssb_device_put(sdev);
@@ -447,10 +447,9 @@ void ssb_bus_unregister(struct ssb_bus *bus)
 
 	err = ssb_gpio_unregister(bus);
 	if (err == -EBUSY)
-		ssb_dprintk(KERN_ERR PFX "Some GPIOs are still in use.\n");
+		ssb_dbg("Some GPIOs are still in use\n");
 	else if (err)
-		ssb_dprintk(KERN_ERR PFX
-			    "Can not unregister GPIO driver: %i\n", err);
+		ssb_dbg("Can not unregister GPIO driver: %i\n", err);
 
 	ssb_buses_lock();
 	ssb_devices_unregister(bus);
@@ -497,8 +496,7 @@ static int ssb_devices_register(struct ssb_bus *bus)
 
 		devwrap = kzalloc(sizeof(*devwrap), GFP_KERNEL);
 		if (!devwrap) {
-			ssb_printk(KERN_ERR PFX
-				   "Could not allocate device\n");
+			ssb_err("Could not allocate device\n");
 			err = -ENOMEM;
 			goto error;
 		}
@@ -537,9 +535,7 @@ static int ssb_devices_register(struct ssb_bus *bus)
 		sdev->dev = dev;
 		err = device_register(dev);
 		if (err) {
-			ssb_printk(KERN_ERR PFX
-				   "Could not register %s\n",
-				   dev_name(dev));
+			ssb_err("Could not register %s\n", dev_name(dev));
 			/* Set dev to NULL to not unregister
 			 * dev on error unwinding. */
 			sdev->dev = NULL;
@@ -825,10 +821,9 @@ static int ssb_bus_register(struct ssb_bus *bus,
 	ssb_mipscore_init(&bus->mipscore);
 	err = ssb_gpio_init(bus);
 	if (err == -ENOTSUPP)
-		ssb_dprintk(KERN_DEBUG PFX "GPIO driver not activated\n");
+		ssb_dbg("GPIO driver not activated\n");
 	else if (err)
-		ssb_dprintk(KERN_ERR PFX
-			   "Error registering GPIO driver: %i\n", err);
+		ssb_dbg("Error registering GPIO driver: %i\n", err);
 	err = ssb_fetch_invariants(bus, get_invariants);
 	if (err) {
 		ssb_bus_may_powerdown(bus);
@@ -878,11 +873,11 @@ int ssb_bus_pcibus_register(struct ssb_bus *bus, struct pci_dev *host_pci)
 
 	err = ssb_bus_register(bus, ssb_pci_get_invariants, 0);
 	if (!err) {
-		ssb_printk(KERN_INFO PFX "Sonics Silicon Backplane found on "
-			   "PCI device %s\n", dev_name(&host_pci->dev));
+		ssb_info("Sonics Silicon Backplane found on PCI device %s\n",
+			 dev_name(&host_pci->dev));
 	} else {
-		ssb_printk(KERN_ERR PFX "Failed to register PCI version"
-			   " of SSB with error %d\n", err);
+		ssb_err("Failed to register PCI version of SSB with error %d\n",
+			err);
 	}
 
 	return err;
@@ -903,8 +898,8 @@ int ssb_bus_pcmciabus_register(struct ssb_bus *bus,
 
 	err = ssb_bus_register(bus, ssb_pcmcia_get_invariants, baseaddr);
 	if (!err) {
-		ssb_printk(KERN_INFO PFX "Sonics Silicon Backplane found on "
-			   "PCMCIA device %s\n", pcmcia_dev->devname);
+		ssb_info("Sonics Silicon Backplane found on PCMCIA device %s\n",
+			 pcmcia_dev->devname);
 	}
 
 	return err;
@@ -925,8 +920,8 @@ int ssb_bus_sdiobus_register(struct ssb_bus *bus, struct sdio_func *func,
 
 	err = ssb_bus_register(bus, ssb_sdio_get_invariants, ~0);
 	if (!err) {
-		ssb_printk(KERN_INFO PFX "Sonics Silicon Backplane found on "
-			   "SDIO device %s\n", sdio_func_id(func));
+		ssb_info("Sonics Silicon Backplane found on SDIO device %s\n",
+			 sdio_func_id(func));
 	}
 
 	return err;
@@ -944,8 +939,8 @@ int ssb_bus_ssbbus_register(struct ssb_bus *bus, unsigned long baseaddr,
 
 	err = ssb_bus_register(bus, get_invariants, baseaddr);
 	if (!err) {
-		ssb_printk(KERN_INFO PFX "Sonics Silicon Backplane found at "
-			   "address 0x%08lX\n", baseaddr);
+		ssb_info("Sonics Silicon Backplane found at address 0x%08lX\n",
+			 baseaddr);
 	}
 
 	return err;
@@ -1339,7 +1334,7 @@ out:
 #endif
 	return err;
 error:
-	ssb_printk(KERN_ERR PFX "Bus powerdown failed\n");
+	ssb_err("Bus powerdown failed\n");
 	goto out;
 }
 EXPORT_SYMBOL(ssb_bus_may_powerdown);
@@ -1362,7 +1357,7 @@ int ssb_bus_powerup(struct ssb_bus *bus, bool dynamic_pctl)
 
 	return 0;
 error:
-	ssb_printk(KERN_ERR PFX "Bus powerup failed\n");
+	ssb_err("Bus powerup failed\n");
 	return err;
 }
 EXPORT_SYMBOL(ssb_bus_powerup);
@@ -1470,15 +1465,13 @@ static int __init ssb_modinit(void)
 
 	err = b43_pci_ssb_bridge_init();
 	if (err) {
-		ssb_printk(KERN_ERR "Broadcom 43xx PCI-SSB-bridge "
-			   "initialization failed\n");
+		ssb_err("Broadcom 43xx PCI-SSB-bridge initialization failed\n");
 		/* don't fail SSB init because of this */
 		err = 0;
 	}
 	err = ssb_gige_init();
 	if (err) {
-		ssb_printk(KERN_ERR "SSB Broadcom Gigabit Ethernet "
-			   "driver initialization failed\n");
+		ssb_err("SSB Broadcom Gigabit Ethernet driver initialization failed\n");
 		/* don't fail SSB init because of this */
 		err = 0;
 	}
diff --git a/drivers/ssb/pci.c b/drivers/ssb/pci.c
index e9d9496..a8dc95e 100644
--- a/drivers/ssb/pci.c
+++ b/drivers/ssb/pci.c
@@ -56,7 +56,7 @@ int ssb_pci_switch_coreidx(struct ssb_bus *bus, u8 coreidx)
 	}
 	return 0;
 error:
-	ssb_printk(KERN_ERR PFX "Failed to switch to core %u\n", coreidx);
+	ssb_err("Failed to switch to core %u\n", coreidx);
 	return -ENODEV;
 }
 
@@ -67,10 +67,9 @@ int ssb_pci_switch_core(struct ssb_bus *bus,
 	unsigned long flags;
 
 #if SSB_VERBOSE_PCICORESWITCH_DEBUG
-	ssb_printk(KERN_INFO PFX
-		   "Switching to %s core, index %d\n",
-		   ssb_core_name(dev->id.coreid),
-		   dev->core_index);
+	ssb_info("Switching to %s core, index %d\n",
+		 ssb_core_name(dev->id.coreid),
+		 dev->core_index);
 #endif
 
 	spin_lock_irqsave(&bus->bar_lock, flags);
@@ -231,6 +230,15 @@ static inline u8 ssb_crc8(u8 crc, u8 data)
 	return t[crc ^ data];
 }
 
+static void sprom_get_mac(char *mac, const u16 *in)
+{
+	int i;
+	for (i = 0; i < 3; i++) {
+		*mac++ = in[i] >> 8;
+		*mac++ = in[i];
+	}
+}
+
 static u8 ssb_sprom_crc(const u16 *sprom, u16 size)
 {
 	int word;
@@ -278,7 +286,7 @@ static int sprom_do_write(struct ssb_bus *bus, const u16 *sprom)
 	u32 spromctl;
 	u16 size = bus->sprom_size;
 
-	ssb_printk(KERN_NOTICE PFX "Writing SPROM. Do NOT turn off the power! Please stand by...\n");
+	ssb_notice("Writing SPROM. Do NOT turn off the power! Please stand by...\n");
 	err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl);
 	if (err)
 		goto err_ctlreg;
@@ -286,17 +294,17 @@ static int sprom_do_write(struct ssb_bus *bus, const u16 *sprom)
 	err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl);
 	if (err)
 		goto err_ctlreg;
-	ssb_printk(KERN_NOTICE PFX "[ 0%%");
+	ssb_notice("[ 0%%");
 	msleep(500);
 	for (i = 0; i < size; i++) {
 		if (i == size / 4)
-			ssb_printk("25%%");
+			ssb_cont("25%%");
 		else if (i == size / 2)
-			ssb_printk("50%%");
+			ssb_cont("50%%");
 		else if (i == (size * 3) / 4)
-			ssb_printk("75%%");
+			ssb_cont("75%%");
 		else if (i % 2)
-			ssb_printk(".");
+			ssb_cont(".");
 		writew(sprom[i], bus->mmio + bus->sprom_offset + (i * 2));
 		mmiowb();
 		msleep(20);
@@ -309,12 +317,12 @@ static int sprom_do_write(struct ssb_bus *bus, const u16 *sprom)
 	if (err)
 		goto err_ctlreg;
 	msleep(500);
-	ssb_printk("100%% ]\n");
-	ssb_printk(KERN_NOTICE PFX "SPROM written.\n");
+	ssb_cont("100%% ]\n");
+	ssb_notice("SPROM written\n");
 
 	return 0;
 err_ctlreg:
-	ssb_printk(KERN_ERR PFX "Could not access SPROM control register.\n");
+	ssb_err("Could not access SPROM control register.\n");
 	return err;
 }
 
@@ -339,10 +347,23 @@ static s8 r123_extract_antgain(u8 sprom_revision, const u16 *in,
 	return (s8)gain;
 }
 
+static void sprom_extract_r23(struct ssb_sprom *out, const u16 *in)
+{
+	SPEX(boardflags_hi, SSB_SPROM2_BFLHI, 0xFFFF, 0);
+	SPEX(opo, SSB_SPROM2_OPO, SSB_SPROM2_OPO_VALUE, 0);
+	SPEX(pa1lob0, SSB_SPROM2_PA1LOB0, 0xFFFF, 0);
+	SPEX(pa1lob1, SSB_SPROM2_PA1LOB1, 0xFFFF, 0);
+	SPEX(pa1lob2, SSB_SPROM2_PA1LOB2, 0xFFFF, 0);
+	SPEX(pa1hib0, SSB_SPROM2_PA1HIB0, 0xFFFF, 0);
+	SPEX(pa1hib1, SSB_SPROM2_PA1HIB1, 0xFFFF, 0);
+	SPEX(pa1hib2, SSB_SPROM2_PA1HIB2, 0xFFFF, 0);
+	SPEX(maxpwr_ah, SSB_SPROM2_MAXP_A, SSB_SPROM2_MAXP_A_HI, 0);
+	SPEX(maxpwr_al, SSB_SPROM2_MAXP_A, SSB_SPROM2_MAXP_A_LO,
+	     SSB_SPROM2_MAXP_A_LO_SHIFT);
+}
+
 static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in)
 {
-	int i;
-	u16 v;
 	u16 loc[3];
 
 	if (out->revision == 3)			/* rev 3 moved MAC */
@@ -352,19 +373,10 @@ static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in)
 		loc[1] = SSB_SPROM1_ET0MAC;
 		loc[2] = SSB_SPROM1_ET1MAC;
 	}
-	for (i = 0; i < 3; i++) {
-		v = in[SPOFF(loc[0]) + i];
-		*(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
-	}
+	sprom_get_mac(out->il0mac, &in[SPOFF(loc[0])]);
 	if (out->revision < 3) { 	/* only rev 1-2 have et0, et1 */
-		for (i = 0; i < 3; i++) {
-			v = in[SPOFF(loc[1]) + i];
-			*(((__be16 *)out->et0mac) + i) = cpu_to_be16(v);
-		}
-		for (i = 0; i < 3; i++) {
-			v = in[SPOFF(loc[2]) + i];
-			*(((__be16 *)out->et1mac) + i) = cpu_to_be16(v);
-		}
+		sprom_get_mac(out->et0mac, &in[SPOFF(loc[1])]);
+		sprom_get_mac(out->et1mac, &in[SPOFF(loc[2])]);
 	}
 	SPEX(et0phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0A, 0);
 	SPEX(et1phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1A,
@@ -372,6 +384,7 @@ static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in)
 	SPEX(et0mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0M, 14);
 	SPEX(et1mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1M, 15);
 	SPEX(board_rev, SSB_SPROM1_BINF, SSB_SPROM1_BINF_BREV, 0);
+	SPEX(board_type, SSB_SPROM1_SPID, 0xFFFF, 0);
 	if (out->revision == 1)
 		SPEX(country_code, SSB_SPROM1_BINF, SSB_SPROM1_BINF_CCODE,
 		     SSB_SPROM1_BINF_CCODE_SHIFT);
@@ -398,8 +411,7 @@ static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in)
 	     SSB_SPROM1_ITSSI_A_SHIFT);
 	SPEX(itssi_bg, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_BG, 0);
 	SPEX(boardflags_lo, SSB_SPROM1_BFLLO, 0xFFFF, 0);
-	if (out->revision >= 2)
-		SPEX(boardflags_hi, SSB_SPROM2_BFLHI, 0xFFFF, 0);
+
 	SPEX(alpha2[0], SSB_SPROM1_CCODE, 0xff00, 8);
 	SPEX(alpha2[1], SSB_SPROM1_CCODE, 0x00ff, 0);
 
@@ -410,6 +422,8 @@ static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in)
 	out->antenna_gain.a1 = r123_extract_antgain(out->revision, in,
 						    SSB_SPROM1_AGAIN_A,
 						    SSB_SPROM1_AGAIN_A_SHIFT);
+	if (out->revision >= 2)
+		sprom_extract_r23(out, in);
 }
 
 /* Revs 4 5 and 8 have partially shared layout */
@@ -454,23 +468,20 @@ static void sprom_extract_r458(struct ssb_sprom *out, const u16 *in)
 
 static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in)
 {
-	int i;
-	u16 v;
 	u16 il0mac_offset;
 
 	if (out->revision == 4)
 		il0mac_offset = SSB_SPROM4_IL0MAC;
 	else
 		il0mac_offset = SSB_SPROM5_IL0MAC;
-	/* extract the MAC address */
-	for (i = 0; i < 3; i++) {
-		v = in[SPOFF(il0mac_offset) + i];
-		*(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
-	}
+
+	sprom_get_mac(out->il0mac, &in[SPOFF(il0mac_offset)]);
+
 	SPEX(et0phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET0A, 0);
 	SPEX(et1phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET1A,
 	     SSB_SPROM4_ETHPHY_ET1A_SHIFT);
 	SPEX(board_rev, SSB_SPROM4_BOARDREV, 0xFFFF, 0);
+	SPEX(board_type, SSB_SPROM1_SPID, 0xFFFF, 0);
 	if (out->revision == 4) {
 		SPEX(alpha2[0], SSB_SPROM4_CCODE, 0xff00, 8);
 		SPEX(alpha2[1], SSB_SPROM4_CCODE, 0x00ff, 0);
@@ -530,7 +541,7 @@ static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in)
 static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in)
 {
 	int i;
-	u16 v, o;
+	u16 o;
 	u16 pwr_info_offset[] = {
 		SSB_SROM8_PWR_INFO_CORE0, SSB_SROM8_PWR_INFO_CORE1,
 		SSB_SROM8_PWR_INFO_CORE2, SSB_SROM8_PWR_INFO_CORE3
@@ -539,11 +550,10 @@ static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in)
 			ARRAY_SIZE(out->core_pwr_info));
 
 	/* extract the MAC address */
-	for (i = 0; i < 3; i++) {
-		v = in[SPOFF(SSB_SPROM8_IL0MAC) + i];
-		*(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
-	}
+	sprom_get_mac(out->il0mac, &in[SPOFF(SSB_SPROM8_IL0MAC)]);
+
 	SPEX(board_rev, SSB_SPROM8_BOARDREV, 0xFFFF, 0);
+	SPEX(board_type, SSB_SPROM1_SPID, 0xFFFF, 0);
 	SPEX(alpha2[0], SSB_SPROM8_CCODE, 0xff00, 8);
 	SPEX(alpha2[1], SSB_SPROM8_CCODE, 0x00ff, 0);
 	SPEX(boardflags_lo, SSB_SPROM8_BFLLO, 0xFFFF, 0);
@@ -743,7 +753,7 @@ static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out,
 	memset(out, 0, sizeof(*out));
 
 	out->revision = in[size - 1] & 0x00FF;
-	ssb_dprintk(KERN_DEBUG PFX "SPROM revision %d detected.\n", out->revision);
+	ssb_dbg("SPROM revision %d detected\n", out->revision);
 	memset(out->et0mac, 0xFF, 6);		/* preset et0 and et1 mac */
 	memset(out->et1mac, 0xFF, 6);
 
@@ -752,7 +762,7 @@ static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out,
 		 * number stored in the SPROM.
 		 * Always extract r1. */
 		out->revision = 1;
-		ssb_dprintk(KERN_DEBUG PFX "SPROM treated as revision %d\n", out->revision);
+		ssb_dbg("SPROM treated as revision %d\n", out->revision);
 	}
 
 	switch (out->revision) {
@@ -769,9 +779,8 @@ static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out,
 		sprom_extract_r8(out, in);
 		break;
 	default:
-		ssb_printk(KERN_WARNING PFX "Unsupported SPROM"
-			   " revision %d detected. Will extract"
-			   " v1\n", out->revision);
+		ssb_warn("Unsupported SPROM revision %d detected. Will extract v1\n",
+			 out->revision);
 		out->revision = 1;
 		sprom_extract_r123(out, in);
 	}
@@ -791,7 +800,7 @@ static int ssb_pci_sprom_get(struct ssb_bus *bus,
 	u16 *buf;
 
 	if (!ssb_is_sprom_available(bus)) {
-		ssb_printk(KERN_ERR PFX "No SPROM available!\n");
+		ssb_err("No SPROM available!\n");
 		return -ENODEV;
 	}
 	if (bus->chipco.dev) {	/* can be unavailable! */
@@ -810,7 +819,7 @@ static int ssb_pci_sprom_get(struct ssb_bus *bus,
 	} else {
 		bus->sprom_offset = SSB_SPROM_BASE1;
 	}
-	ssb_dprintk(KERN_INFO PFX "SPROM offset is 0x%x\n", bus->sprom_offset);
+	ssb_dbg("SPROM offset is 0x%x\n", bus->sprom_offset);
 
 	buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL);
 	if (!buf)
@@ -835,18 +844,15 @@ static int ssb_pci_sprom_get(struct ssb_bus *bus,
 			 * available for this device in some other storage */
 			err = ssb_fill_sprom_with_fallback(bus, sprom);
 			if (err) {
-				ssb_printk(KERN_WARNING PFX "WARNING: Using"
-					   " fallback SPROM failed (err %d)\n",
-					   err);
+				ssb_warn("WARNING: Using fallback SPROM failed (err %d)\n",
+					 err);
 			} else {
-				ssb_dprintk(KERN_DEBUG PFX "Using SPROM"
-					    " revision %d provided by"
-					    " platform.\n", sprom->revision);
+				ssb_dbg("Using SPROM revision %d provided by platform\n",
+					sprom->revision);
 				err = 0;
 				goto out_free;
 			}
-			ssb_printk(KERN_WARNING PFX "WARNING: Invalid"
-				   " SPROM CRC (corrupt SPROM)\n");
+			ssb_warn("WARNING: Invalid SPROM CRC (corrupt SPROM)\n");
 		}
 	}
 	err = sprom_extract(bus, sprom, buf, bus->sprom_size);
diff --git a/drivers/ssb/pcmcia.c b/drivers/ssb/pcmcia.c
index fbafed5..b413e01 100644
--- a/drivers/ssb/pcmcia.c
+++ b/drivers/ssb/pcmcia.c
@@ -143,7 +143,7 @@ int ssb_pcmcia_switch_coreidx(struct ssb_bus *bus,
 
 	return 0;
 error:
-	ssb_printk(KERN_ERR PFX "Failed to switch to core %u\n", coreidx);
+	ssb_err("Failed to switch to core %u\n", coreidx);
 	return err;
 }
 
@@ -153,10 +153,9 @@ int ssb_pcmcia_switch_core(struct ssb_bus *bus,
 	int err;
 
 #if SSB_VERBOSE_PCMCIACORESWITCH_DEBUG
-	ssb_printk(KERN_INFO PFX
-		   "Switching to %s core, index %d\n",
-		   ssb_core_name(dev->id.coreid),
-		   dev->core_index);
+	ssb_info("Switching to %s core, index %d\n",
+		 ssb_core_name(dev->id.coreid),
+		 dev->core_index);
 #endif
 
 	err = ssb_pcmcia_switch_coreidx(bus, dev->core_index);
@@ -192,7 +191,7 @@ int ssb_pcmcia_switch_segment(struct ssb_bus *bus, u8 seg)
 
 	return 0;
 error:
-	ssb_printk(KERN_ERR PFX "Failed to switch pcmcia segment\n");
+	ssb_err("Failed to switch pcmcia segment\n");
 	return err;
 }
 
@@ -549,44 +548,39 @@ static int ssb_pcmcia_sprom_write_all(struct ssb_bus *bus, const u16 *sprom)
 	bool failed = 0;
 	size_t size = SSB_PCMCIA_SPROM_SIZE;
 
-	ssb_printk(KERN_NOTICE PFX
-		   "Writing SPROM. Do NOT turn off the power! "
-		   "Please stand by...\n");
+	ssb_notice("Writing SPROM. Do NOT turn off the power! Please stand by...\n");
 	err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_WRITEEN);
 	if (err) {
-		ssb_printk(KERN_NOTICE PFX
-			   "Could not enable SPROM write access.\n");
+		ssb_notice("Could not enable SPROM write access\n");
 		return -EBUSY;
 	}
-	ssb_printk(KERN_NOTICE PFX "[ 0%%");
+	ssb_notice("[ 0%%");
 	msleep(500);
 	for (i = 0; i < size; i++) {
 		if (i == size / 4)
-			ssb_printk("25%%");
+			ssb_cont("25%%");
 		else if (i == size / 2)
-			ssb_printk("50%%");
+			ssb_cont("50%%");
 		else if (i == (size * 3) / 4)
-			ssb_printk("75%%");
+			ssb_cont("75%%");
 		else if (i % 2)
-			ssb_printk(".");
+			ssb_cont(".");
 		err = ssb_pcmcia_sprom_write(bus, i, sprom[i]);
 		if (err) {
-			ssb_printk(KERN_NOTICE PFX
-				   "Failed to write to SPROM.\n");
+			ssb_notice("Failed to write to SPROM\n");
 			failed = 1;
 			break;
 		}
 	}
 	err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_WRITEDIS);
 	if (err) {
-		ssb_printk(KERN_NOTICE PFX
-			   "Could not disable SPROM write access.\n");
+		ssb_notice("Could not disable SPROM write access\n");
 		failed = 1;
 	}
 	msleep(500);
 	if (!failed) {
-		ssb_printk("100%% ]\n");
-		ssb_printk(KERN_NOTICE PFX "SPROM written.\n");
+		ssb_cont("100%% ]\n");
+		ssb_notice("SPROM written\n");
 	}
 
 	return failed ? -EBUSY : 0;
@@ -700,7 +694,7 @@ static int ssb_pcmcia_do_get_invariants(struct pcmcia_device *p_dev,
 	return -ENOSPC; /* continue with next entry */
 
 error:
-	ssb_printk(KERN_ERR PFX
+	ssb_err(
 		   "PCMCIA: Failed to fetch device invariants: %s\n",
 		   error_description);
 	return -ENODEV;
@@ -722,7 +716,7 @@ int ssb_pcmcia_get_invariants(struct ssb_bus *bus,
 	res = pcmcia_loop_tuple(bus->host_pcmcia, CISTPL_FUNCE,
 				ssb_pcmcia_get_mac, sprom);
 	if (res != 0) {
-		ssb_printk(KERN_ERR PFX
+		ssb_err(
 			"PCMCIA: Failed to fetch MAC address\n");
 		return -ENODEV;
 	}
@@ -733,7 +727,7 @@ int ssb_pcmcia_get_invariants(struct ssb_bus *bus,
 	if ((res == 0) || (res == -ENOSPC))
 		return 0;
 
-	ssb_printk(KERN_ERR PFX
+	ssb_err(
 			"PCMCIA: Failed to fetch device invariants\n");
 	return -ENODEV;
 }
@@ -843,6 +837,6 @@ int ssb_pcmcia_init(struct ssb_bus *bus)
 
 	return 0;
 error:
-	ssb_printk(KERN_ERR PFX "Failed to initialize PCMCIA host device\n");
+	ssb_err("Failed to initialize PCMCIA host device\n");
 	return err;
 }
diff --git a/drivers/ssb/scan.c b/drivers/ssb/scan.c
index ab4627c..b9429df 100644
--- a/drivers/ssb/scan.c
+++ b/drivers/ssb/scan.c
@@ -125,8 +125,7 @@ static u16 pcidev_to_chipid(struct pci_dev *pci_dev)
 		chipid_fallback = 0x4401;
 		break;
 	default:
-		ssb_printk(KERN_ERR PFX
-			   "PCI-ID not in fallback list\n");
+		ssb_err("PCI-ID not in fallback list\n");
 	}
 
 	return chipid_fallback;
@@ -152,8 +151,7 @@ static u8 chipid_to_nrcores(u16 chipid)
 	case 0x4704:
 		return 9;
 	default:
-		ssb_printk(KERN_ERR PFX
-			   "CHIPID not in nrcores fallback list\n");
+		ssb_err("CHIPID not in nrcores fallback list\n");
 	}
 
 	return 1;
@@ -320,15 +318,13 @@ int ssb_bus_scan(struct ssb_bus *bus,
 			bus->chip_package = 0;
 		}
 	}
-	ssb_printk(KERN_INFO PFX "Found chip with id 0x%04X, rev 0x%02X and "
-		   "package 0x%02X\n", bus->chip_id, bus->chip_rev,
-		   bus->chip_package);
+	ssb_info("Found chip with id 0x%04X, rev 0x%02X and package 0x%02X\n",
+		 bus->chip_id, bus->chip_rev, bus->chip_package);
 	if (!bus->nr_devices)
 		bus->nr_devices = chipid_to_nrcores(bus->chip_id);
 	if (bus->nr_devices > ARRAY_SIZE(bus->devices)) {
-		ssb_printk(KERN_ERR PFX
-			   "More than %d ssb cores found (%d)\n",
-			   SSB_MAX_NR_CORES, bus->nr_devices);
+		ssb_err("More than %d ssb cores found (%d)\n",
+			SSB_MAX_NR_CORES, bus->nr_devices);
 		goto err_unmap;
 	}
 	if (bus->bustype == SSB_BUSTYPE_SSB) {
@@ -370,8 +366,7 @@ int ssb_bus_scan(struct ssb_bus *bus,
 			nr_80211_cores++;
 			if (nr_80211_cores > 1) {
 				if (!we_support_multiple_80211_cores(bus)) {
-					ssb_dprintk(KERN_INFO PFX "Ignoring additional "
-						    "802.11 core\n");
+					ssb_dbg("Ignoring additional 802.11 core\n");
 					continue;
 				}
 			}
@@ -379,8 +374,7 @@ int ssb_bus_scan(struct ssb_bus *bus,
 		case SSB_DEV_EXTIF:
 #ifdef CONFIG_SSB_DRIVER_EXTIF
 			if (bus->extif.dev) {
-				ssb_printk(KERN_WARNING PFX
-					   "WARNING: Multiple EXTIFs found\n");
+				ssb_warn("WARNING: Multiple EXTIFs found\n");
 				break;
 			}
 			bus->extif.dev = dev;
@@ -388,8 +382,7 @@ int ssb_bus_scan(struct ssb_bus *bus,
 			break;
 		case SSB_DEV_CHIPCOMMON:
 			if (bus->chipco.dev) {
-				ssb_printk(KERN_WARNING PFX
-					   "WARNING: Multiple ChipCommon found\n");
+				ssb_warn("WARNING: Multiple ChipCommon found\n");
 				break;
 			}
 			bus->chipco.dev = dev;
@@ -398,8 +391,7 @@ int ssb_bus_scan(struct ssb_bus *bus,
 		case SSB_DEV_MIPS_3302:
 #ifdef CONFIG_SSB_DRIVER_MIPS
 			if (bus->mipscore.dev) {
-				ssb_printk(KERN_WARNING PFX
-					   "WARNING: Multiple MIPS cores found\n");
+				ssb_warn("WARNING: Multiple MIPS cores found\n");
 				break;
 			}
 			bus->mipscore.dev = dev;
@@ -420,8 +412,7 @@ int ssb_bus_scan(struct ssb_bus *bus,
 				}
 			}
 			if (bus->pcicore.dev) {
-				ssb_printk(KERN_WARNING PFX
-					   "WARNING: Multiple PCI(E) cores found\n");
+				ssb_warn("WARNING: Multiple PCI(E) cores found\n");
 				break;
 			}
 			bus->pcicore.dev = dev;
diff --git a/drivers/ssb/sprom.c b/drivers/ssb/sprom.c
index 80d366f..a3b2364 100644
--- a/drivers/ssb/sprom.c
+++ b/drivers/ssb/sprom.c
@@ -127,13 +127,13 @@ ssize_t ssb_attr_sprom_store(struct ssb_bus *bus,
 		goto out_kfree;
 	err = ssb_devices_freeze(bus, &freeze);
 	if (err) {
-		ssb_printk(KERN_ERR PFX "SPROM write: Could not freeze all devices\n");
+		ssb_err("SPROM write: Could not freeze all devices\n");
 		goto out_unlock;
 	}
 	res = sprom_write(bus, sprom);
 	err = ssb_devices_thaw(&freeze);
 	if (err)
-		ssb_printk(KERN_ERR PFX "SPROM write: Could not thaw all devices\n");
+		ssb_err("SPROM write: Could not thaw all devices\n");
 out_unlock:
 	mutex_unlock(&bus->sprom_mutex);
 out_kfree:
diff --git a/drivers/ssb/ssb_private.h b/drivers/ssb/ssb_private.h
index 466171b..4671f17 100644
--- a/drivers/ssb/ssb_private.h
+++ b/drivers/ssb/ssb_private.h
@@ -9,16 +9,27 @@
 #define PFX	"ssb: "
 
 #ifdef CONFIG_SSB_SILENT
-# define ssb_printk(fmt, x...)	do { /* nothing */ } while (0)
+# define ssb_printk(fmt, ...)					\
+	do { if (0) printk(fmt, ##__VA_ARGS__); } while (0)
 #else
-# define ssb_printk		printk
+# define ssb_printk(fmt, ...)					\
+	printk(fmt, ##__VA_ARGS__)
 #endif /* CONFIG_SSB_SILENT */
 
+#define ssb_emerg(fmt, ...)	ssb_printk(KERN_EMERG PFX fmt, ##__VA_ARGS__)
+#define ssb_err(fmt, ...)	ssb_printk(KERN_ERR PFX fmt, ##__VA_ARGS__)
+#define ssb_warn(fmt, ...)	ssb_printk(KERN_WARNING PFX fmt, ##__VA_ARGS__)
+#define ssb_notice(fmt, ...)	ssb_printk(KERN_NOTICE PFX fmt, ##__VA_ARGS__)
+#define ssb_info(fmt, ...)	ssb_printk(KERN_INFO PFX fmt, ##__VA_ARGS__)
+#define ssb_cont(fmt, ...)	ssb_printk(KERN_CONT fmt, ##__VA_ARGS__)
+
 /* dprintk: Debugging printk; vanishes for non-debug compilation */
 #ifdef CONFIG_SSB_DEBUG
-# define ssb_dprintk(fmt, x...)	ssb_printk(fmt , ##x)
+# define ssb_dbg(fmt, ...)					\
+	ssb_printk(KERN_DEBUG PFX fmt, ##__VA_ARGS__)
 #else
-# define ssb_dprintk(fmt, x...)	do { /* nothing */ } while (0)
+# define ssb_dbg(fmt, ...)					\
+	do { if (0) printk(KERN_DEBUG PFX fmt, ##__VA_ARGS__); } while (0)
 #endif
 
 #ifdef CONFIG_SSB_DEBUG
diff --git a/drivers/ssbi/Kconfig b/drivers/ssbi/Kconfig
new file mode 100644
index 0000000..1ae4040
--- /dev/null
+++ b/drivers/ssbi/Kconfig
@@ -0,0 +1,16 @@
+#
+# SSBI bus support
+#
+
+menu "Qualcomm MSM SSBI bus support"
+
+config SSBI
+	tristate "Qualcomm Single-wire Serial Bus Interface (SSBI)"
+	help
+	  If you say yes to this option, support will be included for the
+	  built-in SSBI interface on Qualcomm MSM family processors.
+
+	  This is required for communicating with Qualcomm PMICs and
+	  other devices that have the SSBI interface.
+
+endmenu
diff --git a/drivers/ssbi/Makefile b/drivers/ssbi/Makefile
new file mode 100644
index 0000000..38fb70c
--- /dev/null
+++ b/drivers/ssbi/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_SSBI) += ssbi.o
diff --git a/drivers/ssbi/ssbi.c b/drivers/ssbi/ssbi.c
new file mode 100644
index 0000000..f32da02
--- /dev/null
+++ b/drivers/ssbi/ssbi.c
@@ -0,0 +1,379 @@
+/* Copyright (c) 2009-2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2010, Google Inc.
+ *
+ * Original authors: Code Aurora Forum
+ *
+ * Author: Dima Zavin <dima@android.com>
+ *  - Largely rewritten from original to not be an i2c 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 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.
+ */
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/ssbi.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+
+/* SSBI 2.0 controller registers */
+#define SSBI2_CMD			0x0008
+#define SSBI2_RD			0x0010
+#define SSBI2_STATUS			0x0014
+#define SSBI2_MODE2			0x001C
+
+/* SSBI_CMD fields */
+#define SSBI_CMD_RDWRN			(1 << 24)
+
+/* SSBI_STATUS fields */
+#define SSBI_STATUS_RD_READY		(1 << 2)
+#define SSBI_STATUS_READY		(1 << 1)
+#define SSBI_STATUS_MCHN_BUSY		(1 << 0)
+
+/* SSBI_MODE2 fields */
+#define SSBI_MODE2_REG_ADDR_15_8_SHFT	0x04
+#define SSBI_MODE2_REG_ADDR_15_8_MASK	(0x7f << SSBI_MODE2_REG_ADDR_15_8_SHFT)
+
+#define SET_SSBI_MODE2_REG_ADDR_15_8(MD, AD) \
+	(((MD) & 0x0F) | ((((AD) >> 8) << SSBI_MODE2_REG_ADDR_15_8_SHFT) & \
+	SSBI_MODE2_REG_ADDR_15_8_MASK))
+
+/* SSBI PMIC Arbiter command registers */
+#define SSBI_PA_CMD			0x0000
+#define SSBI_PA_RD_STATUS		0x0004
+
+/* SSBI_PA_CMD fields */
+#define SSBI_PA_CMD_RDWRN		(1 << 24)
+#define SSBI_PA_CMD_ADDR_MASK		0x7fff /* REG_ADDR_7_0, REG_ADDR_8_14*/
+
+/* SSBI_PA_RD_STATUS fields */
+#define SSBI_PA_RD_STATUS_TRANS_DONE	(1 << 27)
+#define SSBI_PA_RD_STATUS_TRANS_DENIED	(1 << 26)
+
+#define SSBI_TIMEOUT_US			100
+
+struct ssbi {
+	struct device		*slave;
+	void __iomem		*base;
+	spinlock_t		lock;
+	enum ssbi_controller_type controller_type;
+	int (*read)(struct ssbi *, u16 addr, u8 *buf, int len);
+	int (*write)(struct ssbi *, u16 addr, u8 *buf, int len);
+};
+
+#define to_ssbi(dev)	platform_get_drvdata(to_platform_device(dev))
+
+static inline u32 ssbi_readl(struct ssbi *ssbi, u32 reg)
+{
+	return readl(ssbi->base + reg);
+}
+
+static inline void ssbi_writel(struct ssbi *ssbi, u32 val, u32 reg)
+{
+	writel(val, ssbi->base + reg);
+}
+
+/*
+ * Via private exchange with one of the original authors, the hardware
+ * should generally finish a transaction in about 5us.  The worst
+ * case, is when using the arbiter and both other CPUs have just
+ * started trying to use the SSBI bus will result in a time of about
+ * 20us.  It should never take longer than this.
+ *
+ * As such, this wait merely spins, with a udelay.
+ */
+static int ssbi_wait_mask(struct ssbi *ssbi, u32 set_mask, u32 clr_mask)
+{
+	u32 timeout = SSBI_TIMEOUT_US;
+	u32 val;
+
+	while (timeout--) {
+		val = ssbi_readl(ssbi, SSBI2_STATUS);
+		if (((val & set_mask) == set_mask) && ((val & clr_mask) == 0))
+			return 0;
+		udelay(1);
+	}
+
+	return -ETIMEDOUT;
+}
+
+static int
+ssbi_read_bytes(struct ssbi *ssbi, u16 addr, u8 *buf, int len)
+{
+	u32 cmd = SSBI_CMD_RDWRN | ((addr & 0xff) << 16);
+	int ret = 0;
+
+	if (ssbi->controller_type == MSM_SBI_CTRL_SSBI2) {
+		u32 mode2 = ssbi_readl(ssbi, SSBI2_MODE2);
+		mode2 = SET_SSBI_MODE2_REG_ADDR_15_8(mode2, addr);
+		ssbi_writel(ssbi, mode2, SSBI2_MODE2);
+	}
+
+	while (len) {
+		ret = ssbi_wait_mask(ssbi, SSBI_STATUS_READY, 0);
+		if (ret)
+			goto err;
+
+		ssbi_writel(ssbi, cmd, SSBI2_CMD);
+		ret = ssbi_wait_mask(ssbi, SSBI_STATUS_RD_READY, 0);
+		if (ret)
+			goto err;
+		*buf++ = ssbi_readl(ssbi, SSBI2_RD) & 0xff;
+		len--;
+	}
+
+err:
+	return ret;
+}
+
+static int
+ssbi_write_bytes(struct ssbi *ssbi, u16 addr, u8 *buf, int len)
+{
+	int ret = 0;
+
+	if (ssbi->controller_type == MSM_SBI_CTRL_SSBI2) {
+		u32 mode2 = ssbi_readl(ssbi, SSBI2_MODE2);
+		mode2 = SET_SSBI_MODE2_REG_ADDR_15_8(mode2, addr);
+		ssbi_writel(ssbi, mode2, SSBI2_MODE2);
+	}
+
+	while (len) {
+		ret = ssbi_wait_mask(ssbi, SSBI_STATUS_READY, 0);
+		if (ret)
+			goto err;
+
+		ssbi_writel(ssbi, ((addr & 0xff) << 16) | *buf, SSBI2_CMD);
+		ret = ssbi_wait_mask(ssbi, 0, SSBI_STATUS_MCHN_BUSY);
+		if (ret)
+			goto err;
+		buf++;
+		len--;
+	}
+
+err:
+	return ret;
+}
+
+/*
+ * See ssbi_wait_mask for an explanation of the time and the
+ * busywait.
+ */
+static inline int
+ssbi_pa_transfer(struct ssbi *ssbi, u32 cmd, u8 *data)
+{
+	u32 timeout = SSBI_TIMEOUT_US;
+	u32 rd_status = 0;
+
+	ssbi_writel(ssbi, cmd, SSBI_PA_CMD);
+
+	while (timeout--) {
+		rd_status = ssbi_readl(ssbi, SSBI_PA_RD_STATUS);
+
+		if (rd_status & SSBI_PA_RD_STATUS_TRANS_DENIED)
+			return -EPERM;
+
+		if (rd_status & SSBI_PA_RD_STATUS_TRANS_DONE) {
+			if (data)
+				*data = rd_status & 0xff;
+			return 0;
+		}
+		udelay(1);
+	}
+
+	return -ETIMEDOUT;
+}
+
+static int
+ssbi_pa_read_bytes(struct ssbi *ssbi, u16 addr, u8 *buf, int len)
+{
+	u32 cmd;
+	int ret = 0;
+
+	cmd = SSBI_PA_CMD_RDWRN | (addr & SSBI_PA_CMD_ADDR_MASK) << 8;
+
+	while (len) {
+		ret = ssbi_pa_transfer(ssbi, cmd, buf);
+		if (ret)
+			goto err;
+		buf++;
+		len--;
+	}
+
+err:
+	return ret;
+}
+
+static int
+ssbi_pa_write_bytes(struct ssbi *ssbi, u16 addr, u8 *buf, int len)
+{
+	u32 cmd;
+	int ret = 0;
+
+	while (len) {
+		cmd = (addr & SSBI_PA_CMD_ADDR_MASK) << 8 | *buf;
+		ret = ssbi_pa_transfer(ssbi, cmd, NULL);
+		if (ret)
+			goto err;
+		buf++;
+		len--;
+	}
+
+err:
+	return ret;
+}
+
+int ssbi_read(struct device *dev, u16 addr, u8 *buf, int len)
+{
+	struct ssbi *ssbi = to_ssbi(dev);
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&ssbi->lock, flags);
+	ret = ssbi->read(ssbi, addr, buf, len);
+	spin_unlock_irqrestore(&ssbi->lock, flags);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(ssbi_read);
+
+int ssbi_write(struct device *dev, u16 addr, u8 *buf, int len)
+{
+	struct ssbi *ssbi = to_ssbi(dev);
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&ssbi->lock, flags);
+	ret = ssbi->write(ssbi, addr, buf, len);
+	spin_unlock_irqrestore(&ssbi->lock, flags);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(ssbi_write);
+
+static int ssbi_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct resource *mem_res;
+	struct ssbi *ssbi;
+	int ret = 0;
+	const char *type;
+
+	ssbi = kzalloc(sizeof(struct ssbi), GFP_KERNEL);
+	if (!ssbi) {
+		pr_err("can not allocate ssbi_data\n");
+		return -ENOMEM;
+	}
+
+	mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem_res) {
+		pr_err("missing mem resource\n");
+		ret = -EINVAL;
+		goto err_get_mem_res;
+	}
+
+	ssbi->base = ioremap(mem_res->start, resource_size(mem_res));
+	if (!ssbi->base) {
+		pr_err("ioremap of 0x%p failed\n", (void *)mem_res->start);
+		ret = -EINVAL;
+		goto err_ioremap;
+	}
+	platform_set_drvdata(pdev, ssbi);
+
+	type = of_get_property(np, "qcom,controller-type", NULL);
+	if (type == NULL) {
+		pr_err("Missing qcom,controller-type property\n");
+		ret = -EINVAL;
+		goto err_ssbi_controller;
+	}
+	dev_info(&pdev->dev, "SSBI controller type: '%s'\n", type);
+	if (strcmp(type, "ssbi") == 0)
+		ssbi->controller_type = MSM_SBI_CTRL_SSBI;
+	else if (strcmp(type, "ssbi2") == 0)
+		ssbi->controller_type = MSM_SBI_CTRL_SSBI2;
+	else if (strcmp(type, "pmic-arbiter") == 0)
+		ssbi->controller_type = MSM_SBI_CTRL_PMIC_ARBITER;
+	else {
+		pr_err("Unknown qcom,controller-type\n");
+		ret = -EINVAL;
+		goto err_ssbi_controller;
+	}
+
+	if (ssbi->controller_type == MSM_SBI_CTRL_PMIC_ARBITER) {
+		ssbi->read = ssbi_pa_read_bytes;
+		ssbi->write = ssbi_pa_write_bytes;
+	} else {
+		ssbi->read = ssbi_read_bytes;
+		ssbi->write = ssbi_write_bytes;
+	}
+
+	spin_lock_init(&ssbi->lock);
+
+	ret = of_platform_populate(np, NULL, NULL, &pdev->dev);
+	if (ret)
+		goto err_ssbi_controller;
+
+	return 0;
+
+err_ssbi_controller:
+	platform_set_drvdata(pdev, NULL);
+	iounmap(ssbi->base);
+err_ioremap:
+err_get_mem_res:
+	kfree(ssbi);
+	return ret;
+}
+
+static int ssbi_remove(struct platform_device *pdev)
+{
+	struct ssbi *ssbi = platform_get_drvdata(pdev);
+
+	platform_set_drvdata(pdev, NULL);
+	iounmap(ssbi->base);
+	kfree(ssbi);
+	return 0;
+}
+
+static struct of_device_id ssbi_match_table[] = {
+	{ .compatible = "qcom,ssbi" },
+	{}
+};
+
+static struct platform_driver ssbi_driver = {
+	.probe		= ssbi_probe,
+	.remove		= ssbi_remove,
+	.driver		= {
+		.name	= "ssbi",
+		.owner	= THIS_MODULE,
+		.of_match_table = ssbi_match_table,
+	},
+};
+
+static int __init ssbi_init(void)
+{
+	return platform_driver_register(&ssbi_driver);
+}
+module_init(ssbi_init);
+
+static void __exit ssbi_exit(void)
+{
+	platform_driver_unregister(&ssbi_driver);
+}
+module_exit(ssbi_exit)
+
+MODULE_LICENSE("GPL v2");
+MODULE_VERSION("1.0");
+MODULE_ALIAS("platform:ssbi");
+MODULE_AUTHOR("Dima Zavin <dima@android.com>");
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index 093f10c..5e62d00 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -116,13 +116,11 @@ source "drivers/staging/android/Kconfig"
 
 source "drivers/staging/ozwpan/Kconfig"
 
-source "drivers/staging/ccg/Kconfig"
-
 source "drivers/staging/gdm72xx/Kconfig"
 
 source "drivers/staging/csr/Kconfig"
 
-source "drivers/staging/omap-thermal/Kconfig"
+source "drivers/staging/ti-soc-thermal/Kconfig"
 
 source "drivers/staging/silicom/Kconfig"
 
@@ -140,4 +138,8 @@ source "drivers/staging/zcache/Kconfig"
 
 source "drivers/staging/goldfish/Kconfig"
 
+source "drivers/staging/netlogic/Kconfig"
+
+source "drivers/staging/dwc2/Kconfig"
+
 endif # STAGING
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index fa41b04..b6d15ec 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -23,6 +23,7 @@ obj-$(CONFIG_RTS5139)		+= rts5139/
 obj-$(CONFIG_TRANZPORT)		+= frontier/
 obj-$(CONFIG_IDE_PHISON)	+= phison/
 obj-$(CONFIG_LINE6_USB)		+= line6/
+obj-$(CONFIG_NETLOGIC_XLR_NET)	+= netlogic/
 obj-$(CONFIG_USB_SERIAL_QUATECH2)	+= serqt_usb2/
 obj-$(CONFIG_OCTEON_ETHERNET)	+= octeon/
 obj-$(CONFIG_VT6655)		+= vt6655/
@@ -50,10 +51,9 @@ obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4)	+= ste_rmi4/
 obj-$(CONFIG_MFD_NVEC)		+= nvec/
 obj-$(CONFIG_ANDROID)		+= android/
 obj-$(CONFIG_USB_WPAN_HCD)	+= ozwpan/
-obj-$(CONFIG_USB_G_CCG)		+= ccg/
 obj-$(CONFIG_WIMAX_GDM72XX)	+= gdm72xx/
 obj-$(CONFIG_CSR_WIFI)		+= csr/
-obj-$(CONFIG_OMAP_BANDGAP)	+= omap-thermal/
+obj-$(CONFIG_TI_SOC_THERMAL)	+= ti-soc-thermal/
 obj-$(CONFIG_NET_VENDOR_SILICOM)	+= silicom/
 obj-$(CONFIG_CED1401)		+= ced1401/
 obj-$(CONFIG_DRM_IMX)		+= imx-drm/
@@ -62,3 +62,4 @@ obj-$(CONFIG_SB105X)		+= sb105x/
 obj-$(CONFIG_FIREWIRE_SERIAL)	+= fwserial/
 obj-$(CONFIG_ZCACHE)		+= zcache/
 obj-$(CONFIG_GOLDFISH)		+= goldfish/
+obj-$(CONFIG_USB_DWC2)		+= dwc2/
diff --git a/drivers/staging/android/Kconfig b/drivers/staging/android/Kconfig
index 465a28c..9f61d46 100644
--- a/drivers/staging/android/Kconfig
+++ b/drivers/staging/android/Kconfig
@@ -22,7 +22,7 @@ config ANDROID_BINDER_IPC
 config ASHMEM
 	bool "Enable the Anonymous Shared Memory Subsystem"
 	default n
-	depends on SHMEM || TINY_SHMEM
+	depends on SHMEM
 	---help---
 	  The ashmem subsystem is a new shared memory allocator, similar to
 	  POSIX SHM but with different behavior and sporting a simpler
@@ -72,6 +72,33 @@ config ANDROID_INTF_ALARM_DEV
 	  elapsed realtime, and a non-wakeup alarm on the monotonic clock.
 	  Also exports the alarm interface to user-space.
 
+config SYNC
+	bool "Synchronization framework"
+	default n
+	select ANON_INODES
+	help
+	  This option enables the framework for synchronization between multiple
+	  drivers.  Sync implementations can take advantage of hardware
+	  synchronization built into devices like GPUs.
+
+config SW_SYNC
+	bool "Software synchronization objects"
+	default n
+	depends on SYNC
+	help
+	  A sync object driver that uses a 32bit counter to coordinate
+	  syncrhronization.  Useful when there is no hardware primitive backing
+	  the synchronization.
+
+config SW_SYNC_USER
+	bool "Userspace API for SW_SYNC"
+	default n
+	depends on SW_SYNC
+	help
+	  Provides a user space API to the sw sync object.
+	  *WARNING* improper use of this can result in deadlocking kernel
+	  drivers from userspace.
+
 endif # if ANDROID
 
 endmenu
diff --git a/drivers/staging/android/Makefile b/drivers/staging/android/Makefile
index b35a631..c136299 100644
--- a/drivers/staging/android/Makefile
+++ b/drivers/staging/android/Makefile
@@ -7,3 +7,5 @@ obj-$(CONFIG_ANDROID_TIMED_OUTPUT)	+= timed_output.o
 obj-$(CONFIG_ANDROID_TIMED_GPIO)	+= timed_gpio.o
 obj-$(CONFIG_ANDROID_LOW_MEMORY_KILLER)	+= lowmemorykiller.o
 obj-$(CONFIG_ANDROID_INTF_ALARM_DEV)	+= alarm-dev.o
+obj-$(CONFIG_SYNC)			+= sync.o
+obj-$(CONFIG_SW_SYNC)			+= sw_sync.o
diff --git a/drivers/staging/android/ashmem.c b/drivers/staging/android/ashmem.c
index 634b9ae..e681bdd 100644
--- a/drivers/staging/android/ashmem.c
+++ b/drivers/staging/android/ashmem.c
@@ -414,20 +414,29 @@ out:
 static int set_name(struct ashmem_area *asma, void __user *name)
 {
 	int ret = 0;
+	char local_name[ASHMEM_NAME_LEN];
 
-	mutex_lock(&ashmem_mutex);
+	/*
+	 * Holding the ashmem_mutex while doing a copy_from_user might cause
+	 * an data abort which would try to access mmap_sem. If another
+	 * thread has invoked ashmem_mmap then it will be holding the
+	 * semaphore and will be waiting for ashmem_mutex, there by leading to
+	 * deadlock. We'll release the mutex  and take the name to a local
+	 * variable that does not need protection and later copy the local
+	 * variable to the structure member with lock held.
+	 */
+	if (copy_from_user(local_name, name, ASHMEM_NAME_LEN))
+		return -EFAULT;
 
+	mutex_lock(&ashmem_mutex);
 	/* cannot change an existing mapping's name */
 	if (unlikely(asma->file)) {
 		ret = -EINVAL;
 		goto out;
 	}
-
-	if (unlikely(copy_from_user(asma->name + ASHMEM_NAME_PREFIX_LEN,
-				    name, ASHMEM_NAME_LEN)))
-		ret = -EFAULT;
+	memcpy(asma->name + ASHMEM_NAME_PREFIX_LEN,
+		local_name, ASHMEM_NAME_LEN);
 	asma->name[ASHMEM_FULL_NAME_LEN-1] = '\0';
-
 out:
 	mutex_unlock(&ashmem_mutex);
 
@@ -437,26 +446,36 @@ out:
 static int get_name(struct ashmem_area *asma, void __user *name)
 {
 	int ret = 0;
+	size_t len;
+	/*
+	 * Have a local variable to which we'll copy the content
+	 * from asma with the lock held. Later we can copy this to the user
+	 * space safely without holding any locks. So even if we proceed to
+	 * wait for mmap_sem, it won't lead to deadlock.
+	 */
+	char local_name[ASHMEM_NAME_LEN];
 
 	mutex_lock(&ashmem_mutex);
 	if (asma->name[ASHMEM_NAME_PREFIX_LEN] != '\0') {
-		size_t len;
 
 		/*
 		 * Copying only `len', instead of ASHMEM_NAME_LEN, bytes
 		 * prevents us from revealing one user's stack to another.
 		 */
 		len = strlen(asma->name + ASHMEM_NAME_PREFIX_LEN) + 1;
-		if (unlikely(copy_to_user(name,
-				asma->name + ASHMEM_NAME_PREFIX_LEN, len)))
-			ret = -EFAULT;
+		memcpy(local_name, asma->name + ASHMEM_NAME_PREFIX_LEN, len);
 	} else {
-		if (unlikely(copy_to_user(name, ASHMEM_NAME_DEF,
-					  sizeof(ASHMEM_NAME_DEF))))
-			ret = -EFAULT;
+		len = sizeof(ASHMEM_NAME_DEF);
+		memcpy(local_name, ASHMEM_NAME_DEF, len);
 	}
 	mutex_unlock(&ashmem_mutex);
 
+	/*
+	 * Now we are just copying from the stack variable to userland
+	 * No lock held
+	 */
+	if (unlikely(copy_to_user(name, local_name, len)))
+		ret = -EFAULT;
 	return ret;
 }
 
@@ -683,6 +702,23 @@ static long ashmem_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 	return ret;
 }
 
+/* support of 32bit userspace on 64bit platforms */
+#ifdef CONFIG_COMPAT
+static long compat_ashmem_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+
+	switch (cmd) {
+	case COMPAT_ASHMEM_SET_SIZE:
+		cmd = ASHMEM_SET_SIZE;
+		break;
+	case COMPAT_ASHMEM_SET_PROT_MASK:
+		cmd = ASHMEM_SET_PROT_MASK;
+		break;
+	}
+	return ashmem_ioctl(file, cmd, arg);
+}
+#endif
+
 static const struct file_operations ashmem_fops = {
 	.owner = THIS_MODULE,
 	.open = ashmem_open,
@@ -691,7 +727,9 @@ static const struct file_operations ashmem_fops = {
 	.llseek = ashmem_llseek,
 	.mmap = ashmem_mmap,
 	.unlocked_ioctl = ashmem_ioctl,
-	.compat_ioctl = ashmem_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl = compat_ashmem_ioctl,
+#endif
 };
 
 static struct miscdevice ashmem_misc = {
diff --git a/drivers/staging/android/ashmem.h b/drivers/staging/android/ashmem.h
index 1976b10..8dc0f0d 100644
--- a/drivers/staging/android/ashmem.h
+++ b/drivers/staging/android/ashmem.h
@@ -14,6 +14,7 @@
 
 #include <linux/limits.h>
 #include <linux/ioctl.h>
+#include <linux/compat.h>
 
 #define ASHMEM_NAME_LEN		256
 
@@ -45,4 +46,10 @@ struct ashmem_pin {
 #define ASHMEM_GET_PIN_STATUS	_IO(__ASHMEMIOC, 9)
 #define ASHMEM_PURGE_ALL_CACHES	_IO(__ASHMEMIOC, 10)
 
+/* support of 32bit userspace on 64bit platforms */
+#ifdef CONFIG_COMPAT
+#define COMPAT_ASHMEM_SET_SIZE		_IOW(__ASHMEMIOC, 3, compat_size_t)
+#define COMPAT_ASHMEM_SET_PROT_MASK	_IOW(__ASHMEMIOC, 5, unsigned int)
+#endif
+
 #endif	/* _LINUX_ASHMEM_H */
diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c
index 24456a0..1567ac2 100644
--- a/drivers/staging/android/binder.c
+++ b/drivers/staging/android/binder.c
@@ -2878,82 +2878,109 @@ static int binder_release(struct inode *nodp, struct file *filp)
 	return 0;
 }
 
+static int binder_node_release(struct binder_node *node, int refs)
+{
+	struct binder_ref *ref;
+	int death = 0;
+
+	list_del_init(&node->work.entry);
+	binder_release_work(&node->async_todo);
+
+	if (hlist_empty(&node->refs)) {
+		kfree(node);
+		binder_stats_deleted(BINDER_STAT_NODE);
+
+		return refs;
+	}
+
+	node->proc = NULL;
+	node->local_strong_refs = 0;
+	node->local_weak_refs = 0;
+	hlist_add_head(&node->dead_node, &binder_dead_nodes);
+
+	hlist_for_each_entry(ref, &node->refs, node_entry) {
+		refs++;
+
+		if (!ref->death)
+			goto out;
+
+		death++;
+
+		if (list_empty(&ref->death->work.entry)) {
+			ref->death->work.type = BINDER_WORK_DEAD_BINDER;
+			list_add_tail(&ref->death->work.entry,
+				      &ref->proc->todo);
+			wake_up_interruptible(&ref->proc->wait);
+		} else
+			BUG();
+	}
+
+out:
+	binder_debug(BINDER_DEBUG_DEAD_BINDER,
+		     "node %d now dead, refs %d, death %d\n",
+		     node->debug_id, refs, death);
+
+	return refs;
+}
+
 static void binder_deferred_release(struct binder_proc *proc)
 {
 	struct binder_transaction *t;
 	struct rb_node *n;
-	int threads, nodes, incoming_refs, outgoing_refs, buffers, active_transactions, page_count;
+	int threads, nodes, incoming_refs, outgoing_refs, buffers,
+		active_transactions, page_count;
 
 	BUG_ON(proc->vma);
 	BUG_ON(proc->files);
 
 	hlist_del(&proc->proc_node);
+
 	if (binder_context_mgr_node && binder_context_mgr_node->proc == proc) {
 		binder_debug(BINDER_DEBUG_DEAD_BINDER,
-			     "binder_release: %d context_mgr_node gone\n",
-			     proc->pid);
+			     "%s: %d context_mgr_node gone\n",
+			     __func__, proc->pid);
 		binder_context_mgr_node = NULL;
 	}
 
 	threads = 0;
 	active_transactions = 0;
 	while ((n = rb_first(&proc->threads))) {
-		struct binder_thread *thread = rb_entry(n, struct binder_thread, rb_node);
+		struct binder_thread *thread;
+
+		thread = rb_entry(n, struct binder_thread, rb_node);
 		threads++;
 		active_transactions += binder_free_thread(proc, thread);
 	}
+
 	nodes = 0;
 	incoming_refs = 0;
 	while ((n = rb_first(&proc->nodes))) {
-		struct binder_node *node = rb_entry(n, struct binder_node, rb_node);
+		struct binder_node *node;
 
+		node = rb_entry(n, struct binder_node, rb_node);
 		nodes++;
 		rb_erase(&node->rb_node, &proc->nodes);
-		list_del_init(&node->work.entry);
-		binder_release_work(&node->async_todo);
-		if (hlist_empty(&node->refs)) {
-			kfree(node);
-			binder_stats_deleted(BINDER_STAT_NODE);
-		} else {
-			struct binder_ref *ref;
-			int death = 0;
-
-			node->proc = NULL;
-			node->local_strong_refs = 0;
-			node->local_weak_refs = 0;
-			hlist_add_head(&node->dead_node, &binder_dead_nodes);
-
-			hlist_for_each_entry(ref, &node->refs, node_entry) {
-				incoming_refs++;
-				if (ref->death) {
-					death++;
-					if (list_empty(&ref->death->work.entry)) {
-						ref->death->work.type = BINDER_WORK_DEAD_BINDER;
-						list_add_tail(&ref->death->work.entry, &ref->proc->todo);
-						wake_up_interruptible(&ref->proc->wait);
-					} else
-						BUG();
-				}
-			}
-			binder_debug(BINDER_DEBUG_DEAD_BINDER,
-				     "node %d now dead, refs %d, death %d\n",
-				      node->debug_id, incoming_refs, death);
-		}
+		incoming_refs = binder_node_release(node, incoming_refs);
 	}
+
 	outgoing_refs = 0;
 	while ((n = rb_first(&proc->refs_by_desc))) {
-		struct binder_ref *ref = rb_entry(n, struct binder_ref,
-						  rb_node_desc);
+		struct binder_ref *ref;
+
+		ref = rb_entry(n, struct binder_ref, rb_node_desc);
 		outgoing_refs++;
 		binder_delete_ref(ref);
 	}
+
 	binder_release_work(&proc->todo);
 	binder_release_work(&proc->delivered_death);
-	buffers = 0;
 
+	buffers = 0;
 	while ((n = rb_first(&proc->allocated_buffers))) {
-		struct binder_buffer *buffer = rb_entry(n, struct binder_buffer,
-							rb_node);
+		struct binder_buffer *buffer;
+
+		buffer = rb_entry(n, struct binder_buffer, rb_node);
+
 		t = buffer->transaction;
 		if (t) {
 			t->buffer = NULL;
@@ -2962,6 +2989,7 @@ static void binder_deferred_release(struct binder_proc *proc)
 			       proc->pid, t->debug_id);
 			/*BUG();*/
 		}
+
 		binder_free_buf(proc, buffer);
 		buffers++;
 	}
@@ -2971,18 +2999,20 @@ static void binder_deferred_release(struct binder_proc *proc)
 	page_count = 0;
 	if (proc->pages) {
 		int i;
+
 		for (i = 0; i < proc->buffer_size / PAGE_SIZE; i++) {
-			if (proc->pages[i]) {
-				void *page_addr = proc->buffer + i * PAGE_SIZE;
-				binder_debug(BINDER_DEBUG_BUFFER_ALLOC,
-					     "binder_release: %d: page %d at %p not freed\n",
-					     proc->pid, i,
-					     page_addr);
-				unmap_kernel_range((unsigned long)page_addr,
-					PAGE_SIZE);
-				__free_page(proc->pages[i]);
-				page_count++;
-			}
+			void *page_addr;
+
+			if (!proc->pages[i])
+				continue;
+
+			page_addr = proc->buffer + i * PAGE_SIZE;
+			binder_debug(BINDER_DEBUG_BUFFER_ALLOC,
+				     "%s: %d: page %d at %p not freed\n",
+				     __func__, proc->pid, i, page_addr);
+			unmap_kernel_range((unsigned long)page_addr, PAGE_SIZE);
+			__free_page(proc->pages[i]);
+			page_count++;
 		}
 		kfree(proc->pages);
 		vfree(proc->buffer);
@@ -2991,9 +3021,9 @@ static void binder_deferred_release(struct binder_proc *proc)
 	put_task_struct(proc->tsk);
 
 	binder_debug(BINDER_DEBUG_OPEN_CLOSE,
-		     "binder_release: %d threads %d, nodes %d (ref %d), refs %d, active transactions %d, buffers %d, pages %d\n",
-		     proc->pid, threads, nodes, incoming_refs, outgoing_refs,
-		     active_transactions, buffers, page_count);
+		     "%s: %d threads %d, nodes %d (ref %d), refs %d, active transactions %d, buffers %d, pages %d\n",
+		     __func__, proc->pid, threads, nodes, incoming_refs,
+		     outgoing_refs, active_transactions, buffers, page_count);
 
 	kfree(proc);
 }
diff --git a/drivers/staging/android/logger.c b/drivers/staging/android/logger.c
index dbc63cb..b040200 100644
--- a/drivers/staging/android/logger.c
+++ b/drivers/staging/android/logger.c
@@ -28,6 +28,7 @@
 #include <linux/slab.h>
 #include <linux/time.h>
 #include <linux/vmalloc.h>
+#include <linux/aio.h>
 #include "logger.h"
 
 #include <asm/ioctls.h>
@@ -68,6 +69,8 @@ static LIST_HEAD(log_list);
  * @log:	The associated log
  * @list:	The associated entry in @logger_log's list
  * @r_off:	The current read head offset.
+ * @r_all:	Reader can read all entries
+ * @r_ver:	Reader ABI version
  *
  * This object lives from open to release, so we don't need additional
  * reference counting. The structure is protected by log->mutex.
@@ -76,6 +79,8 @@ struct logger_reader {
 	struct logger_log	*log;
 	struct list_head	list;
 	size_t			r_off;
+	bool			r_all;
+	int			r_ver;
 };
 
 /* logger_offset - returns index 'n' into the log via (optimized) modulus */
@@ -109,8 +114,29 @@ static inline struct logger_log *file_get_log(struct file *file)
 }
 
 /*
- * get_entry_len - Grabs the length of the payload of the next entry starting
- * from 'off'.
+ * get_entry_header - returns a pointer to the logger_entry header within
+ * 'log' starting at offset 'off'. A temporary logger_entry 'scratch' must
+ * be provided. Typically the return value will be a pointer within
+ * 'logger->buf'.  However, a pointer to 'scratch' may be returned if
+ * the log entry spans the end and beginning of the circular buffer.
+ */
+static struct logger_entry *get_entry_header(struct logger_log *log,
+		size_t off, struct logger_entry *scratch)
+{
+	size_t len = min(sizeof(struct logger_entry), log->size - off);
+	if (len != sizeof(struct logger_entry)) {
+		memcpy(((void *) scratch), log->buffer + off, len);
+		memcpy(((void *) scratch) + len, log->buffer,
+			sizeof(struct logger_entry) - len);
+		return scratch;
+	}
+
+	return (struct logger_entry *) (log->buffer + off);
+}
+
+/*
+ * get_entry_msg_len - Grabs the length of the message of the entry
+ * starting from from 'off'.
  *
  * An entry length is 2 bytes (16 bits) in host endian order.
  * In the log, the length does not include the size of the log entry structure.
@@ -118,20 +144,45 @@ static inline struct logger_log *file_get_log(struct file *file)
  *
  * Caller needs to hold log->mutex.
  */
-static __u32 get_entry_len(struct logger_log *log, size_t off)
+static __u32 get_entry_msg_len(struct logger_log *log, size_t off)
 {
-	__u16 val;
+	struct logger_entry scratch;
+	struct logger_entry *entry;
 
-	/* copy 2 bytes from buffer, in memcpy order, */
-	/* handling possible wrap at end of buffer */
+	entry = get_entry_header(log, off, &scratch);
+	return entry->len;
+}
 
-	((__u8 *)&val)[0] = log->buffer[off];
-	if (likely(off+1 < log->size))
-		((__u8 *)&val)[1] = log->buffer[off+1];
+static size_t get_user_hdr_len(int ver)
+{
+	if (ver < 2)
+		return sizeof(struct user_logger_entry_compat);
 	else
-		((__u8 *)&val)[1] = log->buffer[0];
+		return sizeof(struct logger_entry);
+}
 
-	return sizeof(struct logger_entry) + val;
+static ssize_t copy_header_to_user(int ver, struct logger_entry *entry,
+					 char __user *buf)
+{
+	void *hdr;
+	size_t hdr_len;
+	struct user_logger_entry_compat v1;
+
+	if (ver < 2) {
+		v1.len      = entry->len;
+		v1.__pad    = 0;
+		v1.pid      = entry->pid;
+		v1.tid      = entry->tid;
+		v1.sec      = entry->sec;
+		v1.nsec     = entry->nsec;
+		hdr         = &v1;
+		hdr_len     = sizeof(struct user_logger_entry_compat);
+	} else {
+		hdr         = entry;
+		hdr_len     = sizeof(struct logger_entry);
+	}
+
+	return copy_to_user(buf, hdr, hdr_len);
 }
 
 /*
@@ -145,15 +196,31 @@ static ssize_t do_read_log_to_user(struct logger_log *log,
 				   char __user *buf,
 				   size_t count)
 {
+	struct logger_entry scratch;
+	struct logger_entry *entry;
 	size_t len;
+	size_t msg_start;
 
 	/*
-	 * We read from the log in two disjoint operations. First, we read from
-	 * the current read head offset up to 'count' bytes or to the end of
+	 * First, copy the header to userspace, using the version of
+	 * the header requested
+	 */
+	entry = get_entry_header(log, reader->r_off, &scratch);
+	if (copy_header_to_user(reader->r_ver, entry, buf))
+		return -EFAULT;
+
+	count -= get_user_hdr_len(reader->r_ver);
+	buf += get_user_hdr_len(reader->r_ver);
+	msg_start = logger_offset(log,
+		reader->r_off + sizeof(struct logger_entry));
+
+	/*
+	 * We read from the msg in two disjoint operations. First, we read from
+	 * the current msg head offset up to 'count' bytes or to the end of
 	 * the log, whichever comes first.
 	 */
-	len = min(count, log->size - reader->r_off);
-	if (copy_to_user(buf, log->buffer + reader->r_off, len))
+	len = min(count, log->size - msg_start);
+	if (copy_to_user(buf, log->buffer + msg_start, len))
 		return -EFAULT;
 
 	/*
@@ -164,9 +231,34 @@ static ssize_t do_read_log_to_user(struct logger_log *log,
 		if (copy_to_user(buf + len, log->buffer, count - len))
 			return -EFAULT;
 
-	reader->r_off = logger_offset(log, reader->r_off + count);
+	reader->r_off = logger_offset(log, reader->r_off +
+		sizeof(struct logger_entry) + count);
 
-	return count;
+	return count + get_user_hdr_len(reader->r_ver);
+}
+
+/*
+ * get_next_entry_by_uid - Starting at 'off', returns an offset into
+ * 'log->buffer' which contains the first entry readable by 'euid'
+ */
+static size_t get_next_entry_by_uid(struct logger_log *log,
+		size_t off, uid_t euid)
+{
+	while (off != log->w_off) {
+		struct logger_entry *entry;
+		struct logger_entry scratch;
+		size_t next_len;
+
+		entry = get_entry_header(log, off, &scratch);
+
+		if (entry->euid == euid)
+			return off;
+
+		next_len = sizeof(struct logger_entry) + entry->len;
+		off = logger_offset(log, off + next_len);
+	}
+
+	return off;
 }
 
 /*
@@ -178,7 +270,7 @@ static ssize_t do_read_log_to_user(struct logger_log *log,
  *	- If there are no log entries to read, blocks until log is written to
  *	- Atomically reads exactly one log entry
  *
- * Optimal read size is LOGGER_ENTRY_MAX_LEN. Will set errno to EINVAL if read
+ * Will set errno to EINVAL if read
  * buffer is insufficient to hold next entry.
  */
 static ssize_t logger_read(struct file *file, char __user *buf,
@@ -219,6 +311,10 @@ start:
 
 	mutex_lock(&log->mutex);
 
+	if (!reader->r_all)
+		reader->r_off = get_next_entry_by_uid(log,
+			reader->r_off, current_euid());
+
 	/* is there still something to read or did we race? */
 	if (unlikely(log->w_off == reader->r_off)) {
 		mutex_unlock(&log->mutex);
@@ -226,7 +322,8 @@ start:
 	}
 
 	/* get the size of the next entry */
-	ret = get_entry_len(log, reader->r_off);
+	ret = get_user_hdr_len(reader->r_ver) +
+		get_entry_msg_len(log, reader->r_off);
 	if (count < ret) {
 		ret = -EINVAL;
 		goto out;
@@ -252,7 +349,8 @@ static size_t get_next_entry(struct logger_log *log, size_t off, size_t len)
 	size_t count = 0;
 
 	do {
-		size_t nr = get_entry_len(log, off);
+		size_t nr = sizeof(struct logger_entry) +
+			get_entry_msg_len(log, off);
 		off = logger_offset(log, off + nr);
 		count += nr;
 	} while (count < len);
@@ -382,7 +480,9 @@ static ssize_t logger_aio_write(struct kiocb *iocb, const struct iovec *iov,
 	header.tid = current->pid;
 	header.sec = now.tv_sec;
 	header.nsec = now.tv_nsec;
+	header.euid = current_euid();
 	header.len = min_t(size_t, iocb->ki_left, LOGGER_ENTRY_MAX_PAYLOAD);
+	header.hdr_size = sizeof(struct logger_entry);
 
 	/* null writes succeed, return zero */
 	if (unlikely(!header.len))
@@ -463,6 +563,10 @@ static int logger_open(struct inode *inode, struct file *file)
 			return -ENOMEM;
 
 		reader->log = log;
+		reader->r_ver = 1;
+		reader->r_all = in_egroup_p(inode->i_gid) ||
+			capable(CAP_SYSLOG);
+
 		INIT_LIST_HEAD(&reader->list);
 
 		mutex_lock(&log->mutex);
@@ -522,6 +626,10 @@ static unsigned int logger_poll(struct file *file, poll_table *wait)
 	poll_wait(file, &log->wq, wait);
 
 	mutex_lock(&log->mutex);
+	if (!reader->r_all)
+		reader->r_off = get_next_entry_by_uid(log,
+			reader->r_off, current_euid());
+
 	if (log->w_off != reader->r_off)
 		ret |= POLLIN | POLLRDNORM;
 	mutex_unlock(&log->mutex);
@@ -529,11 +637,25 @@ static unsigned int logger_poll(struct file *file, poll_table *wait)
 	return ret;
 }
 
+static long logger_set_version(struct logger_reader *reader, void __user *arg)
+{
+	int version;
+	if (copy_from_user(&version, arg, sizeof(int)))
+		return -EFAULT;
+
+	if ((version < 1) || (version > 2))
+		return -EINVAL;
+
+	reader->r_ver = version;
+	return 0;
+}
+
 static long logger_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
 	struct logger_log *log = file_get_log(file);
 	struct logger_reader *reader;
-	long ret = -ENOTTY;
+	long ret = -EINVAL;
+	void __user *argp = (void __user *) arg;
 
 	mutex_lock(&log->mutex);
 
@@ -558,8 +680,14 @@ static long logger_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 			break;
 		}
 		reader = file->private_data;
+
+		if (!reader->r_all)
+			reader->r_off = get_next_entry_by_uid(log,
+				reader->r_off, current_euid());
+
 		if (log->w_off != reader->r_off)
-			ret = get_entry_len(log, reader->r_off);
+			ret = get_user_hdr_len(reader->r_ver) +
+				get_entry_msg_len(log, reader->r_off);
 		else
 			ret = 0;
 		break;
@@ -568,11 +696,32 @@ static long logger_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 			ret = -EBADF;
 			break;
 		}
+		if (!(in_egroup_p(file->f_dentry->d_inode->i_gid) ||
+				capable(CAP_SYSLOG))) {
+			ret = -EPERM;
+			break;
+		}
 		list_for_each_entry(reader, &log->readers, list)
 			reader->r_off = log->w_off;
 		log->head = log->w_off;
 		ret = 0;
 		break;
+	case LOGGER_GET_VERSION:
+		if (!(file->f_mode & FMODE_READ)) {
+			ret = -EBADF;
+			break;
+		}
+		reader = file->private_data;
+		ret = reader->r_ver;
+		break;
+	case LOGGER_SET_VERSION:
+		if (!(file->f_mode & FMODE_READ)) {
+			ret = -EBADF;
+			break;
+		}
+		reader = file->private_data;
+		ret = logger_set_version(reader, argp);
+		break;
 	}
 
 	mutex_unlock(&log->mutex);
@@ -592,8 +741,8 @@ static const struct file_operations logger_fops = {
 };
 
 /*
- * Log size must be a power of two, greater than LOGGER_ENTRY_MAX_LEN,
- * and less than LONG_MAX minus LOGGER_ENTRY_MAX_LEN.
+ * Log size must must be a power of two, and greater than
+ * (LOGGER_ENTRY_MAX_PAYLOAD + sizeof(struct logger_entry)).
  */
 static int __init create_log(char *log_name, int size)
 {
diff --git a/drivers/staging/android/logger.h b/drivers/staging/android/logger.h
index 9b929a8..cc6bbd9 100644
--- a/drivers/staging/android/logger.h
+++ b/drivers/staging/android/logger.h
@@ -21,7 +21,7 @@
 #include <linux/ioctl.h>
 
 /**
- * struct logger_entry - defines a single entry that is given to a logger
+ * struct user_logger_entry_compat - defines a single entry that is given to a logger
  * @len:	The length of the payload
  * @__pad:	Two bytes of padding that appear to be required
  * @pid:	The generating process' process ID
@@ -29,8 +29,12 @@
  * @sec:	The number of seconds that have elapsed since the Epoch
  * @nsec:	The number of nanoseconds that have elapsed since @sec
  * @msg:	The message that is to be logged
+ *
+ * The userspace structure for version 1 of the logger_entry ABI.
+ * This structure is returned to userspace unless the caller requests
+ * an upgrade to a newer ABI version.
  */
-struct logger_entry {
+struct user_logger_entry_compat {
 	__u16		len;
 	__u16		__pad;
 	__s32		pid;
@@ -40,14 +44,38 @@ struct logger_entry {
 	char		msg[0];
 };
 
+/**
+ * struct logger_entry - defines a single entry that is given to a logger
+ * @len:	The length of the payload
+ * @hdr_size:	sizeof(struct logger_entry_v2)
+ * @pid:	The generating process' process ID
+ * @tid:	The generating process' thread ID
+ * @sec:	The number of seconds that have elapsed since the Epoch
+ * @nsec:	The number of nanoseconds that have elapsed since @sec
+ * @euid:	Effective UID of logger
+ * @msg:	The message that is to be logged
+ *
+ * The structure for version 2 of the logger_entry ABI.
+ * This structure is returned to userspace if ioctl(LOGGER_SET_VERSION)
+ * is called with version >= 2
+ */
+struct logger_entry {
+	__u16		len;
+	__u16		hdr_size;
+	__s32		pid;
+	__s32		tid;
+	__s32		sec;
+	__s32		nsec;
+	uid_t		euid;
+	char		msg[0];
+};
+
 #define LOGGER_LOG_RADIO	"log_radio"	/* radio-related messages */
 #define LOGGER_LOG_EVENTS	"log_events"	/* system/hardware events */
 #define LOGGER_LOG_SYSTEM	"log_system"	/* system/framework messages */
 #define LOGGER_LOG_MAIN		"log_main"	/* everything else */
 
-#define LOGGER_ENTRY_MAX_LEN		(4*1024)
-#define LOGGER_ENTRY_MAX_PAYLOAD	\
-	(LOGGER_ENTRY_MAX_LEN - sizeof(struct logger_entry))
+#define LOGGER_ENTRY_MAX_PAYLOAD	4076
 
 #define __LOGGERIO	0xAE
 
@@ -55,5 +83,7 @@ struct logger_entry {
 #define LOGGER_GET_LOG_LEN		_IO(__LOGGERIO, 2) /* used log len */
 #define LOGGER_GET_NEXT_ENTRY_LEN	_IO(__LOGGERIO, 3) /* next entry len */
 #define LOGGER_FLUSH_LOG		_IO(__LOGGERIO, 4) /* flush log */
+#define LOGGER_GET_VERSION		_IO(__LOGGERIO, 5) /* abi version */
+#define LOGGER_SET_VERSION		_IO(__LOGGERIO, 6) /* abi version */
 
 #endif /* _LINUX_LOGGER_H */
diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c
index 3b91b0f..fe74494 100644
--- a/drivers/staging/android/lowmemorykiller.c
+++ b/drivers/staging/android/lowmemorykiller.c
@@ -30,16 +30,19 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/oom.h>
 #include <linux/sched.h>
+#include <linux/swap.h>
 #include <linux/rcupdate.h>
 #include <linux/profile.h>
 #include <linux/notifier.h>
 
-static uint32_t lowmem_debug_level = 2;
+static uint32_t lowmem_debug_level = 1;
 static short lowmem_adj[6] = {
 	0,
 	1,
@@ -60,7 +63,7 @@ static unsigned long lowmem_deathpending_timeout;
 #define lowmem_print(level, x...)			\
 	do {						\
 		if (lowmem_debug_level >= (level))	\
-			printk(x);			\
+			pr_info(x);			\
 	} while (0)
 
 static int lowmem_shrink(struct shrinker *s, struct shrink_control *sc)
@@ -74,7 +77,7 @@ static int lowmem_shrink(struct shrinker *s, struct shrink_control *sc)
 	int selected_tasksize = 0;
 	short selected_oom_score_adj;
 	int array_size = ARRAY_SIZE(lowmem_adj);
-	int other_free = global_page_state(NR_FREE_PAGES);
+	int other_free = global_page_state(NR_FREE_PAGES) - totalreserve_pages;
 	int other_file = global_page_state(NR_FILE_PAGES) -
 						global_page_state(NR_SHMEM);
 
diff --git a/drivers/staging/android/sw_sync.c b/drivers/staging/android/sw_sync.c
new file mode 100644
index 0000000..4928f93
--- /dev/null
+++ b/drivers/staging/android/sw_sync.c
@@ -0,0 +1,264 @@
+/*
+ * drivers/base/sw_sync.c
+ *
+ * Copyright (C) 2012 Google, 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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/export.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/syscalls.h>
+#include <linux/uaccess.h>
+
+#include "sw_sync.h"
+
+static int sw_sync_cmp(u32 a, u32 b)
+{
+	if (a == b)
+		return 0;
+
+	return ((s32)a - (s32)b) < 0 ? -1 : 1;
+}
+
+struct sync_pt *sw_sync_pt_create(struct sw_sync_timeline *obj, u32 value)
+{
+	struct sw_sync_pt *pt;
+
+	pt = (struct sw_sync_pt *)
+		sync_pt_create(&obj->obj, sizeof(struct sw_sync_pt));
+
+	pt->value = value;
+
+	return (struct sync_pt *)pt;
+}
+EXPORT_SYMBOL(sw_sync_pt_create);
+
+static struct sync_pt *sw_sync_pt_dup(struct sync_pt *sync_pt)
+{
+	struct sw_sync_pt *pt = (struct sw_sync_pt *) sync_pt;
+	struct sw_sync_timeline *obj =
+		(struct sw_sync_timeline *)sync_pt->parent;
+
+	return (struct sync_pt *) sw_sync_pt_create(obj, pt->value);
+}
+
+static int sw_sync_pt_has_signaled(struct sync_pt *sync_pt)
+{
+	struct sw_sync_pt *pt = (struct sw_sync_pt *)sync_pt;
+	struct sw_sync_timeline *obj =
+		(struct sw_sync_timeline *)sync_pt->parent;
+
+	return sw_sync_cmp(obj->value, pt->value) >= 0;
+}
+
+static int sw_sync_pt_compare(struct sync_pt *a, struct sync_pt *b)
+{
+	struct sw_sync_pt *pt_a = (struct sw_sync_pt *)a;
+	struct sw_sync_pt *pt_b = (struct sw_sync_pt *)b;
+
+	return sw_sync_cmp(pt_a->value, pt_b->value);
+}
+
+static int sw_sync_fill_driver_data(struct sync_pt *sync_pt,
+				    void *data, int size)
+{
+	struct sw_sync_pt *pt = (struct sw_sync_pt *)sync_pt;
+
+	if (size < sizeof(pt->value))
+		return -ENOMEM;
+
+	memcpy(data, &pt->value, sizeof(pt->value));
+
+	return sizeof(pt->value);
+}
+
+static void sw_sync_timeline_value_str(struct sync_timeline *sync_timeline,
+				       char *str, int size)
+{
+	struct sw_sync_timeline *timeline =
+		(struct sw_sync_timeline *)sync_timeline;
+	snprintf(str, size, "%d", timeline->value);
+}
+
+static void sw_sync_pt_value_str(struct sync_pt *sync_pt,
+				       char *str, int size)
+{
+	struct sw_sync_pt *pt = (struct sw_sync_pt *)sync_pt;
+	snprintf(str, size, "%d", pt->value);
+}
+
+static struct sync_timeline_ops sw_sync_timeline_ops = {
+	.driver_name = "sw_sync",
+	.dup = sw_sync_pt_dup,
+	.has_signaled = sw_sync_pt_has_signaled,
+	.compare = sw_sync_pt_compare,
+	.fill_driver_data = sw_sync_fill_driver_data,
+	.timeline_value_str = sw_sync_timeline_value_str,
+	.pt_value_str = sw_sync_pt_value_str,
+};
+
+
+struct sw_sync_timeline *sw_sync_timeline_create(const char *name)
+{
+	struct sw_sync_timeline *obj = (struct sw_sync_timeline *)
+		sync_timeline_create(&sw_sync_timeline_ops,
+				     sizeof(struct sw_sync_timeline),
+				     name);
+
+	return obj;
+}
+EXPORT_SYMBOL(sw_sync_timeline_create);
+
+void sw_sync_timeline_inc(struct sw_sync_timeline *obj, u32 inc)
+{
+	obj->value += inc;
+
+	sync_timeline_signal(&obj->obj);
+}
+EXPORT_SYMBOL(sw_sync_timeline_inc);
+
+#ifdef CONFIG_SW_SYNC_USER
+/* *WARNING*
+ *
+ * improper use of this can result in deadlocking kernel drivers from userspace.
+ */
+
+/* opening sw_sync create a new sync obj */
+static int sw_sync_open(struct inode *inode, struct file *file)
+{
+	struct sw_sync_timeline *obj;
+	char task_comm[TASK_COMM_LEN];
+
+	get_task_comm(task_comm, current);
+
+	obj = sw_sync_timeline_create(task_comm);
+	if (obj == NULL)
+		return -ENOMEM;
+
+	file->private_data = obj;
+
+	return 0;
+}
+
+static int sw_sync_release(struct inode *inode, struct file *file)
+{
+	struct sw_sync_timeline *obj = file->private_data;
+	sync_timeline_destroy(&obj->obj);
+	return 0;
+}
+
+static long sw_sync_ioctl_create_fence(struct sw_sync_timeline *obj, unsigned long arg)
+{
+	int fd = get_unused_fd();
+	int err;
+	struct sync_pt *pt;
+	struct sync_fence *fence;
+	struct sw_sync_create_fence_data data;
+
+	if (fd < 0)
+		return fd;
+
+	if (copy_from_user(&data, (void __user *)arg, sizeof(data))) {
+		err = -EFAULT;
+		goto err;
+	}
+
+	pt = sw_sync_pt_create(obj, data.value);
+	if (pt == NULL) {
+		err = -ENOMEM;
+		goto err;
+	}
+
+	data.name[sizeof(data.name) - 1] = '\0';
+	fence = sync_fence_create(data.name, pt);
+	if (fence == NULL) {
+		sync_pt_free(pt);
+		err = -ENOMEM;
+		goto err;
+	}
+
+	data.fence = fd;
+	if (copy_to_user((void __user *)arg, &data, sizeof(data))) {
+		sync_fence_put(fence);
+		err = -EFAULT;
+		goto err;
+	}
+
+	sync_fence_install(fence, fd);
+
+	return 0;
+
+err:
+	put_unused_fd(fd);
+	return err;
+}
+
+static long sw_sync_ioctl_inc(struct sw_sync_timeline *obj, unsigned long arg)
+{
+	u32 value;
+
+	if (copy_from_user(&value, (void __user *)arg, sizeof(value)))
+		return -EFAULT;
+
+	sw_sync_timeline_inc(obj, value);
+
+	return 0;
+}
+
+static long sw_sync_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct sw_sync_timeline *obj = file->private_data;
+
+	switch (cmd) {
+	case SW_SYNC_IOC_CREATE_FENCE:
+		return sw_sync_ioctl_create_fence(obj, arg);
+
+	case SW_SYNC_IOC_INC:
+		return sw_sync_ioctl_inc(obj, arg);
+
+	default:
+		return -ENOTTY;
+	}
+}
+
+static const struct file_operations sw_sync_fops = {
+	.owner = THIS_MODULE,
+	.open = sw_sync_open,
+	.release = sw_sync_release,
+	.unlocked_ioctl = sw_sync_ioctl,
+	.compat_ioctl = sw_sync_ioctl,
+};
+
+static struct miscdevice sw_sync_dev = {
+	.minor	= MISC_DYNAMIC_MINOR,
+	.name	= "sw_sync",
+	.fops	= &sw_sync_fops,
+};
+
+static int __init sw_sync_device_init(void)
+{
+	return misc_register(&sw_sync_dev);
+}
+
+static void __exit sw_sync_device_remove(void)
+{
+	misc_deregister(&sw_sync_dev);
+}
+
+module_init(sw_sync_device_init);
+module_exit(sw_sync_device_remove);
+
+#endif /* CONFIG_SW_SYNC_USER */
diff --git a/drivers/staging/android/sw_sync.h b/drivers/staging/android/sw_sync.h
new file mode 100644
index 0000000..585040b
--- /dev/null
+++ b/drivers/staging/android/sw_sync.h
@@ -0,0 +1,58 @@
+/*
+ * include/linux/sw_sync.h
+ *
+ * Copyright (C) 2012 Google, 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 _LINUX_SW_SYNC_H
+#define _LINUX_SW_SYNC_H
+
+#include <linux/types.h>
+
+#ifdef __KERNEL__
+
+#include "sync.h"
+
+struct sw_sync_timeline {
+	struct	sync_timeline	obj;
+
+	u32			value;
+};
+
+struct sw_sync_pt {
+	struct sync_pt		pt;
+
+	u32			value;
+};
+
+struct sw_sync_timeline *sw_sync_timeline_create(const char *name);
+void sw_sync_timeline_inc(struct sw_sync_timeline *obj, u32 inc);
+
+struct sync_pt *sw_sync_pt_create(struct sw_sync_timeline *obj, u32 value);
+
+#endif /* __KERNEL __ */
+
+struct sw_sync_create_fence_data {
+	__u32	value;
+	char	name[32];
+	__s32	fence; /* fd of new fence */
+};
+
+#define SW_SYNC_IOC_MAGIC	'W'
+
+#define SW_SYNC_IOC_CREATE_FENCE	_IOWR(SW_SYNC_IOC_MAGIC, 0,\
+		struct sw_sync_create_fence_data)
+#define SW_SYNC_IOC_INC			_IOW(SW_SYNC_IOC_MAGIC, 1, __u32)
+
+
+#endif /* _LINUX_SW_SYNC_H */
diff --git a/drivers/staging/android/sync.c b/drivers/staging/android/sync.c
new file mode 100644
index 0000000..3893a35
--- /dev/null
+++ b/drivers/staging/android/sync.c
@@ -0,0 +1,1017 @@
+/*
+ * drivers/base/sync.c
+ *
+ * Copyright (C) 2012 Google, 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.
+ *
+ */
+
+#include <linux/debugfs.h>
+#include <linux/export.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/poll.h>
+#include <linux/sched.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/anon_inodes.h>
+
+#include "sync.h"
+
+#define CREATE_TRACE_POINTS
+#include "trace/sync.h"
+
+static void sync_fence_signal_pt(struct sync_pt *pt);
+static int _sync_pt_has_signaled(struct sync_pt *pt);
+static void sync_fence_free(struct kref *kref);
+static void sync_dump(void);
+
+static LIST_HEAD(sync_timeline_list_head);
+static DEFINE_SPINLOCK(sync_timeline_list_lock);
+
+static LIST_HEAD(sync_fence_list_head);
+static DEFINE_SPINLOCK(sync_fence_list_lock);
+
+struct sync_timeline *sync_timeline_create(const struct sync_timeline_ops *ops,
+					   int size, const char *name)
+{
+	struct sync_timeline *obj;
+	unsigned long flags;
+
+	if (size < sizeof(struct sync_timeline))
+		return NULL;
+
+	obj = kzalloc(size, GFP_KERNEL);
+	if (obj == NULL)
+		return NULL;
+
+	kref_init(&obj->kref);
+	obj->ops = ops;
+	strlcpy(obj->name, name, sizeof(obj->name));
+
+	INIT_LIST_HEAD(&obj->child_list_head);
+	spin_lock_init(&obj->child_list_lock);
+
+	INIT_LIST_HEAD(&obj->active_list_head);
+	spin_lock_init(&obj->active_list_lock);
+
+	spin_lock_irqsave(&sync_timeline_list_lock, flags);
+	list_add_tail(&obj->sync_timeline_list, &sync_timeline_list_head);
+	spin_unlock_irqrestore(&sync_timeline_list_lock, flags);
+
+	return obj;
+}
+EXPORT_SYMBOL(sync_timeline_create);
+
+static void sync_timeline_free(struct kref *kref)
+{
+	struct sync_timeline *obj =
+		container_of(kref, struct sync_timeline, kref);
+	unsigned long flags;
+
+	if (obj->ops->release_obj)
+		obj->ops->release_obj(obj);
+
+	spin_lock_irqsave(&sync_timeline_list_lock, flags);
+	list_del(&obj->sync_timeline_list);
+	spin_unlock_irqrestore(&sync_timeline_list_lock, flags);
+
+	kfree(obj);
+}
+
+void sync_timeline_destroy(struct sync_timeline *obj)
+{
+	obj->destroyed = true;
+
+	/*
+	 * If this is not the last reference, signal any children
+	 * that their parent is going away.
+	 */
+
+	if (!kref_put(&obj->kref, sync_timeline_free))
+		sync_timeline_signal(obj);
+}
+EXPORT_SYMBOL(sync_timeline_destroy);
+
+static void sync_timeline_add_pt(struct sync_timeline *obj, struct sync_pt *pt)
+{
+	unsigned long flags;
+
+	pt->parent = obj;
+
+	spin_lock_irqsave(&obj->child_list_lock, flags);
+	list_add_tail(&pt->child_list, &obj->child_list_head);
+	spin_unlock_irqrestore(&obj->child_list_lock, flags);
+}
+
+static void sync_timeline_remove_pt(struct sync_pt *pt)
+{
+	struct sync_timeline *obj = pt->parent;
+	unsigned long flags;
+
+	spin_lock_irqsave(&obj->active_list_lock, flags);
+	if (!list_empty(&pt->active_list))
+		list_del_init(&pt->active_list);
+	spin_unlock_irqrestore(&obj->active_list_lock, flags);
+
+	spin_lock_irqsave(&obj->child_list_lock, flags);
+	if (!list_empty(&pt->child_list)) {
+		list_del_init(&pt->child_list);
+	}
+	spin_unlock_irqrestore(&obj->child_list_lock, flags);
+}
+
+void sync_timeline_signal(struct sync_timeline *obj)
+{
+	unsigned long flags;
+	LIST_HEAD(signaled_pts);
+	struct list_head *pos, *n;
+
+	trace_sync_timeline(obj);
+
+	spin_lock_irqsave(&obj->active_list_lock, flags);
+
+	list_for_each_safe(pos, n, &obj->active_list_head) {
+		struct sync_pt *pt =
+			container_of(pos, struct sync_pt, active_list);
+
+		if (_sync_pt_has_signaled(pt)) {
+			list_del_init(pos);
+			list_add(&pt->signaled_list, &signaled_pts);
+			kref_get(&pt->fence->kref);
+		}
+	}
+
+	spin_unlock_irqrestore(&obj->active_list_lock, flags);
+
+	list_for_each_safe(pos, n, &signaled_pts) {
+		struct sync_pt *pt =
+			container_of(pos, struct sync_pt, signaled_list);
+
+		list_del_init(pos);
+		sync_fence_signal_pt(pt);
+		kref_put(&pt->fence->kref, sync_fence_free);
+	}
+}
+EXPORT_SYMBOL(sync_timeline_signal);
+
+struct sync_pt *sync_pt_create(struct sync_timeline *parent, int size)
+{
+	struct sync_pt *pt;
+
+	if (size < sizeof(struct sync_pt))
+		return NULL;
+
+	pt = kzalloc(size, GFP_KERNEL);
+	if (pt == NULL)
+		return NULL;
+
+	INIT_LIST_HEAD(&pt->active_list);
+	kref_get(&parent->kref);
+	sync_timeline_add_pt(parent, pt);
+
+	return pt;
+}
+EXPORT_SYMBOL(sync_pt_create);
+
+void sync_pt_free(struct sync_pt *pt)
+{
+	if (pt->parent->ops->free_pt)
+		pt->parent->ops->free_pt(pt);
+
+	sync_timeline_remove_pt(pt);
+
+	kref_put(&pt->parent->kref, sync_timeline_free);
+
+	kfree(pt);
+}
+EXPORT_SYMBOL(sync_pt_free);
+
+/* call with pt->parent->active_list_lock held */
+static int _sync_pt_has_signaled(struct sync_pt *pt)
+{
+	int old_status = pt->status;
+
+	if (!pt->status)
+		pt->status = pt->parent->ops->has_signaled(pt);
+
+	if (!pt->status && pt->parent->destroyed)
+		pt->status = -ENOENT;
+
+	if (pt->status != old_status)
+		pt->timestamp = ktime_get();
+
+	return pt->status;
+}
+
+static struct sync_pt *sync_pt_dup(struct sync_pt *pt)
+{
+	return pt->parent->ops->dup(pt);
+}
+
+/* Adds a sync pt to the active queue.  Called when added to a fence */
+static void sync_pt_activate(struct sync_pt *pt)
+{
+	struct sync_timeline *obj = pt->parent;
+	unsigned long flags;
+	int err;
+
+	spin_lock_irqsave(&obj->active_list_lock, flags);
+
+	err = _sync_pt_has_signaled(pt);
+	if (err != 0)
+		goto out;
+
+	list_add_tail(&pt->active_list, &obj->active_list_head);
+
+out:
+	spin_unlock_irqrestore(&obj->active_list_lock, flags);
+}
+
+static int sync_fence_release(struct inode *inode, struct file *file);
+static unsigned int sync_fence_poll(struct file *file, poll_table *wait);
+static long sync_fence_ioctl(struct file *file, unsigned int cmd,
+			     unsigned long arg);
+
+
+static const struct file_operations sync_fence_fops = {
+	.release = sync_fence_release,
+	.poll = sync_fence_poll,
+	.unlocked_ioctl = sync_fence_ioctl,
+	.compat_ioctl = sync_fence_ioctl,
+};
+
+static struct sync_fence *sync_fence_alloc(const char *name)
+{
+	struct sync_fence *fence;
+	unsigned long flags;
+
+	fence = kzalloc(sizeof(struct sync_fence), GFP_KERNEL);
+	if (fence == NULL)
+		return NULL;
+
+	fence->file = anon_inode_getfile("sync_fence", &sync_fence_fops,
+					 fence, 0);
+	if (IS_ERR(fence->file))
+		goto err;
+
+	kref_init(&fence->kref);
+	strlcpy(fence->name, name, sizeof(fence->name));
+
+	INIT_LIST_HEAD(&fence->pt_list_head);
+	INIT_LIST_HEAD(&fence->waiter_list_head);
+	spin_lock_init(&fence->waiter_list_lock);
+
+	init_waitqueue_head(&fence->wq);
+
+	spin_lock_irqsave(&sync_fence_list_lock, flags);
+	list_add_tail(&fence->sync_fence_list, &sync_fence_list_head);
+	spin_unlock_irqrestore(&sync_fence_list_lock, flags);
+
+	return fence;
+
+err:
+	kfree(fence);
+	return NULL;
+}
+
+/* TODO: implement a create which takes more that one sync_pt */
+struct sync_fence *sync_fence_create(const char *name, struct sync_pt *pt)
+{
+	struct sync_fence *fence;
+
+	if (pt->fence)
+		return NULL;
+
+	fence = sync_fence_alloc(name);
+	if (fence == NULL)
+		return NULL;
+
+	pt->fence = fence;
+	list_add(&pt->pt_list, &fence->pt_list_head);
+	sync_pt_activate(pt);
+
+	/*
+	 * signal the fence in case pt was activated before
+	 * sync_pt_activate(pt) was called
+	 */
+	sync_fence_signal_pt(pt);
+
+	return fence;
+}
+EXPORT_SYMBOL(sync_fence_create);
+
+static int sync_fence_copy_pts(struct sync_fence *dst, struct sync_fence *src)
+{
+	struct list_head *pos;
+
+	list_for_each(pos, &src->pt_list_head) {
+		struct sync_pt *orig_pt =
+			container_of(pos, struct sync_pt, pt_list);
+		struct sync_pt *new_pt = sync_pt_dup(orig_pt);
+
+		if (new_pt == NULL)
+			return -ENOMEM;
+
+		new_pt->fence = dst;
+		list_add(&new_pt->pt_list, &dst->pt_list_head);
+	}
+
+	return 0;
+}
+
+static int sync_fence_merge_pts(struct sync_fence *dst, struct sync_fence *src)
+{
+	struct list_head *src_pos, *dst_pos, *n;
+
+	list_for_each(src_pos, &src->pt_list_head) {
+		struct sync_pt *src_pt =
+			container_of(src_pos, struct sync_pt, pt_list);
+		bool collapsed = false;
+
+		list_for_each_safe(dst_pos, n, &dst->pt_list_head) {
+			struct sync_pt *dst_pt =
+				container_of(dst_pos, struct sync_pt, pt_list);
+			/* collapse two sync_pts on the same timeline
+			 * to a single sync_pt that will signal at
+			 * the later of the two
+			 */
+			if (dst_pt->parent == src_pt->parent) {
+				if (dst_pt->parent->ops->compare(dst_pt, src_pt)
+						 == -1) {
+					struct sync_pt *new_pt =
+						sync_pt_dup(src_pt);
+					if (new_pt == NULL)
+						return -ENOMEM;
+
+					new_pt->fence = dst;
+					list_replace(&dst_pt->pt_list,
+						     &new_pt->pt_list);
+					sync_pt_free(dst_pt);
+				}
+				collapsed = true;
+				break;
+			}
+		}
+
+		if (!collapsed) {
+			struct sync_pt *new_pt = sync_pt_dup(src_pt);
+
+			if (new_pt == NULL)
+				return -ENOMEM;
+
+			new_pt->fence = dst;
+			list_add(&new_pt->pt_list, &dst->pt_list_head);
+		}
+	}
+
+	return 0;
+}
+
+static void sync_fence_detach_pts(struct sync_fence *fence)
+{
+	struct list_head *pos, *n;
+
+	list_for_each_safe(pos, n, &fence->pt_list_head) {
+		struct sync_pt *pt = container_of(pos, struct sync_pt, pt_list);
+		sync_timeline_remove_pt(pt);
+	}
+}
+
+static void sync_fence_free_pts(struct sync_fence *fence)
+{
+	struct list_head *pos, *n;
+
+	list_for_each_safe(pos, n, &fence->pt_list_head) {
+		struct sync_pt *pt = container_of(pos, struct sync_pt, pt_list);
+		sync_pt_free(pt);
+	}
+}
+
+struct sync_fence *sync_fence_fdget(int fd)
+{
+	struct file *file = fget(fd);
+
+	if (file == NULL)
+		return NULL;
+
+	if (file->f_op != &sync_fence_fops)
+		goto err;
+
+	return file->private_data;
+
+err:
+	fput(file);
+	return NULL;
+}
+EXPORT_SYMBOL(sync_fence_fdget);
+
+void sync_fence_put(struct sync_fence *fence)
+{
+	fput(fence->file);
+}
+EXPORT_SYMBOL(sync_fence_put);
+
+void sync_fence_install(struct sync_fence *fence, int fd)
+{
+	fd_install(fd, fence->file);
+}
+EXPORT_SYMBOL(sync_fence_install);
+
+static int sync_fence_get_status(struct sync_fence *fence)
+{
+	struct list_head *pos;
+	int status = 1;
+
+	list_for_each(pos, &fence->pt_list_head) {
+		struct sync_pt *pt = container_of(pos, struct sync_pt, pt_list);
+		int pt_status = pt->status;
+
+		if (pt_status < 0) {
+			status = pt_status;
+			break;
+		} else if (status == 1) {
+			status = pt_status;
+		}
+	}
+
+	return status;
+}
+
+struct sync_fence *sync_fence_merge(const char *name,
+				    struct sync_fence *a, struct sync_fence *b)
+{
+	struct sync_fence *fence;
+	struct list_head *pos;
+	int err;
+
+	fence = sync_fence_alloc(name);
+	if (fence == NULL)
+		return NULL;
+
+	err = sync_fence_copy_pts(fence, a);
+	if (err < 0)
+		goto err;
+
+	err = sync_fence_merge_pts(fence, b);
+	if (err < 0)
+		goto err;
+
+	list_for_each(pos, &fence->pt_list_head) {
+		struct sync_pt *pt =
+			container_of(pos, struct sync_pt, pt_list);
+		sync_pt_activate(pt);
+	}
+
+	/*
+	 * signal the fence in case one of it's pts were activated before
+	 * they were activated
+	 */
+	sync_fence_signal_pt(list_first_entry(&fence->pt_list_head,
+					      struct sync_pt,
+					      pt_list));
+
+	return fence;
+err:
+	sync_fence_free_pts(fence);
+	kfree(fence);
+	return NULL;
+}
+EXPORT_SYMBOL(sync_fence_merge);
+
+static void sync_fence_signal_pt(struct sync_pt *pt)
+{
+	LIST_HEAD(signaled_waiters);
+	struct sync_fence *fence = pt->fence;
+	struct list_head *pos;
+	struct list_head *n;
+	unsigned long flags;
+	int status;
+
+	status = sync_fence_get_status(fence);
+
+	spin_lock_irqsave(&fence->waiter_list_lock, flags);
+	/*
+	 * this should protect against two threads racing on the signaled
+	 * false -> true transition
+	 */
+	if (status && !fence->status) {
+		list_for_each_safe(pos, n, &fence->waiter_list_head)
+			list_move(pos, &signaled_waiters);
+
+		fence->status = status;
+	} else {
+		status = 0;
+	}
+	spin_unlock_irqrestore(&fence->waiter_list_lock, flags);
+
+	if (status) {
+		list_for_each_safe(pos, n, &signaled_waiters) {
+			struct sync_fence_waiter *waiter =
+				container_of(pos, struct sync_fence_waiter,
+					     waiter_list);
+
+			list_del(pos);
+			waiter->callback(fence, waiter);
+		}
+		wake_up(&fence->wq);
+	}
+}
+
+int sync_fence_wait_async(struct sync_fence *fence,
+			  struct sync_fence_waiter *waiter)
+{
+	unsigned long flags;
+	int err = 0;
+
+	spin_lock_irqsave(&fence->waiter_list_lock, flags);
+
+	if (fence->status) {
+		err = fence->status;
+		goto out;
+	}
+
+	list_add_tail(&waiter->waiter_list, &fence->waiter_list_head);
+out:
+	spin_unlock_irqrestore(&fence->waiter_list_lock, flags);
+
+	return err;
+}
+EXPORT_SYMBOL(sync_fence_wait_async);
+
+int sync_fence_cancel_async(struct sync_fence *fence,
+			     struct sync_fence_waiter *waiter)
+{
+	struct list_head *pos;
+	struct list_head *n;
+	unsigned long flags;
+	int ret = -ENOENT;
+
+	spin_lock_irqsave(&fence->waiter_list_lock, flags);
+	/*
+	 * Make sure waiter is still in waiter_list because it is possible for
+	 * the waiter to be removed from the list while the callback is still
+	 * pending.
+	 */
+	list_for_each_safe(pos, n, &fence->waiter_list_head) {
+		struct sync_fence_waiter *list_waiter =
+			container_of(pos, struct sync_fence_waiter,
+				     waiter_list);
+		if (list_waiter == waiter) {
+			list_del(pos);
+			ret = 0;
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&fence->waiter_list_lock, flags);
+	return ret;
+}
+EXPORT_SYMBOL(sync_fence_cancel_async);
+
+static bool sync_fence_check(struct sync_fence *fence)
+{
+	/*
+	 * Make sure that reads to fence->status are ordered with the
+	 * wait queue event triggering
+	 */
+	smp_rmb();
+	return fence->status != 0;
+}
+
+int sync_fence_wait(struct sync_fence *fence, long timeout)
+{
+	int err = 0;
+	struct sync_pt *pt;
+
+	trace_sync_wait(fence, 1);
+	list_for_each_entry(pt, &fence->pt_list_head, pt_list)
+		trace_sync_pt(pt);
+
+	if (timeout > 0) {
+		timeout = msecs_to_jiffies(timeout);
+		err = wait_event_interruptible_timeout(fence->wq,
+						       sync_fence_check(fence),
+						       timeout);
+	} else if (timeout < 0) {
+		err = wait_event_interruptible(fence->wq,
+					       sync_fence_check(fence));
+	}
+	trace_sync_wait(fence, 0);
+
+	if (err < 0)
+		return err;
+
+	if (fence->status < 0) {
+		pr_info("fence error %d on [%p]\n", fence->status, fence);
+		sync_dump();
+		return fence->status;
+	}
+
+	if (fence->status == 0) {
+		if (timeout > 0) {
+			pr_info("fence timeout on [%p] after %dms\n", fence,
+				jiffies_to_msecs(timeout));
+			sync_dump();
+		}
+		return -ETIME;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(sync_fence_wait);
+
+static void sync_fence_free(struct kref *kref)
+{
+	struct sync_fence *fence = container_of(kref, struct sync_fence, kref);
+
+	sync_fence_free_pts(fence);
+
+	kfree(fence);
+}
+
+static int sync_fence_release(struct inode *inode, struct file *file)
+{
+	struct sync_fence *fence = file->private_data;
+	unsigned long flags;
+
+	/*
+	 * We need to remove all ways to access this fence before droping
+	 * our ref.
+	 *
+	 * start with its membership in the global fence list
+	 */
+	spin_lock_irqsave(&sync_fence_list_lock, flags);
+	list_del(&fence->sync_fence_list);
+	spin_unlock_irqrestore(&sync_fence_list_lock, flags);
+
+	/*
+	 * remove its pts from their parents so that sync_timeline_signal()
+	 * can't reference the fence.
+	 */
+	sync_fence_detach_pts(fence);
+
+	kref_put(&fence->kref, sync_fence_free);
+
+	return 0;
+}
+
+static unsigned int sync_fence_poll(struct file *file, poll_table *wait)
+{
+	struct sync_fence *fence = file->private_data;
+
+	poll_wait(file, &fence->wq, wait);
+
+	/*
+	 * Make sure that reads to fence->status are ordered with the
+	 * wait queue event triggering
+	 */
+	smp_rmb();
+
+	if (fence->status == 1)
+		return POLLIN;
+	else if (fence->status < 0)
+		return POLLERR;
+	else
+		return 0;
+}
+
+static long sync_fence_ioctl_wait(struct sync_fence *fence, unsigned long arg)
+{
+	__s32 value;
+
+	if (copy_from_user(&value, (void __user *)arg, sizeof(value)))
+		return -EFAULT;
+
+	return sync_fence_wait(fence, value);
+}
+
+static long sync_fence_ioctl_merge(struct sync_fence *fence, unsigned long arg)
+{
+	int fd = get_unused_fd();
+	int err;
+	struct sync_fence *fence2, *fence3;
+	struct sync_merge_data data;
+
+	if (fd < 0)
+		return fd;
+
+	if (copy_from_user(&data, (void __user *)arg, sizeof(data))) {
+		err = -EFAULT;
+		goto err_put_fd;
+	}
+
+	fence2 = sync_fence_fdget(data.fd2);
+	if (fence2 == NULL) {
+		err = -ENOENT;
+		goto err_put_fd;
+	}
+
+	data.name[sizeof(data.name) - 1] = '\0';
+	fence3 = sync_fence_merge(data.name, fence, fence2);
+	if (fence3 == NULL) {
+		err = -ENOMEM;
+		goto err_put_fence2;
+	}
+
+	data.fence = fd;
+	if (copy_to_user((void __user *)arg, &data, sizeof(data))) {
+		err = -EFAULT;
+		goto err_put_fence3;
+	}
+
+	sync_fence_install(fence3, fd);
+	sync_fence_put(fence2);
+	return 0;
+
+err_put_fence3:
+	sync_fence_put(fence3);
+
+err_put_fence2:
+	sync_fence_put(fence2);
+
+err_put_fd:
+	put_unused_fd(fd);
+	return err;
+}
+
+static int sync_fill_pt_info(struct sync_pt *pt, void *data, int size)
+{
+	struct sync_pt_info *info = data;
+	int ret;
+
+	if (size < sizeof(struct sync_pt_info))
+		return -ENOMEM;
+
+	info->len = sizeof(struct sync_pt_info);
+
+	if (pt->parent->ops->fill_driver_data) {
+		ret = pt->parent->ops->fill_driver_data(pt, info->driver_data,
+							size - sizeof(*info));
+		if (ret < 0)
+			return ret;
+
+		info->len += ret;
+	}
+
+	strlcpy(info->obj_name, pt->parent->name, sizeof(info->obj_name));
+	strlcpy(info->driver_name, pt->parent->ops->driver_name,
+		sizeof(info->driver_name));
+	info->status = pt->status;
+	info->timestamp_ns = ktime_to_ns(pt->timestamp);
+
+	return info->len;
+}
+
+static long sync_fence_ioctl_fence_info(struct sync_fence *fence,
+					unsigned long arg)
+{
+	struct sync_fence_info_data *data;
+	struct list_head *pos;
+	__u32 size;
+	__u32 len = 0;
+	int ret;
+
+	if (copy_from_user(&size, (void __user *)arg, sizeof(size)))
+		return -EFAULT;
+
+	if (size < sizeof(struct sync_fence_info_data))
+		return -EINVAL;
+
+	if (size > 4096)
+		size = 4096;
+
+	data = kzalloc(size, GFP_KERNEL);
+	if (data == NULL)
+		return -ENOMEM;
+
+	strlcpy(data->name, fence->name, sizeof(data->name));
+	data->status = fence->status;
+	len = sizeof(struct sync_fence_info_data);
+
+	list_for_each(pos, &fence->pt_list_head) {
+		struct sync_pt *pt =
+			container_of(pos, struct sync_pt, pt_list);
+
+		ret = sync_fill_pt_info(pt, (u8 *)data + len, size - len);
+
+		if (ret < 0)
+			goto out;
+
+		len += ret;
+	}
+
+	data->len = len;
+
+	if (copy_to_user((void __user *)arg, data, len))
+		ret = -EFAULT;
+	else
+		ret = 0;
+
+out:
+	kfree(data);
+
+	return ret;
+}
+
+static long sync_fence_ioctl(struct file *file, unsigned int cmd,
+			     unsigned long arg)
+{
+	struct sync_fence *fence = file->private_data;
+	switch (cmd) {
+	case SYNC_IOC_WAIT:
+		return sync_fence_ioctl_wait(fence, arg);
+
+	case SYNC_IOC_MERGE:
+		return sync_fence_ioctl_merge(fence, arg);
+
+	case SYNC_IOC_FENCE_INFO:
+		return sync_fence_ioctl_fence_info(fence, arg);
+
+	default:
+		return -ENOTTY;
+	}
+}
+
+#ifdef CONFIG_DEBUG_FS
+static const char *sync_status_str(int status)
+{
+	if (status > 0)
+		return "signaled";
+	else if (status == 0)
+		return "active";
+	else
+		return "error";
+}
+
+static void sync_print_pt(struct seq_file *s, struct sync_pt *pt, bool fence)
+{
+	int status = pt->status;
+	seq_printf(s, "  %s%spt %s",
+		   fence ? pt->parent->name : "",
+		   fence ? "_" : "",
+		   sync_status_str(status));
+	if (pt->status) {
+		struct timeval tv = ktime_to_timeval(pt->timestamp);
+		seq_printf(s, "@%ld.%06ld", tv.tv_sec, tv.tv_usec);
+	}
+
+	if (pt->parent->ops->timeline_value_str &&
+	    pt->parent->ops->pt_value_str) {
+		char value[64];
+		pt->parent->ops->pt_value_str(pt, value, sizeof(value));
+		seq_printf(s, ": %s", value);
+		if (fence) {
+			pt->parent->ops->timeline_value_str(pt->parent, value,
+						    sizeof(value));
+			seq_printf(s, " / %s", value);
+		}
+	} else if (pt->parent->ops->print_pt) {
+		seq_printf(s, ": ");
+		pt->parent->ops->print_pt(s, pt);
+	}
+
+	seq_printf(s, "\n");
+}
+
+static void sync_print_obj(struct seq_file *s, struct sync_timeline *obj)
+{
+	struct list_head *pos;
+	unsigned long flags;
+
+	seq_printf(s, "%s %s", obj->name, obj->ops->driver_name);
+
+	if (obj->ops->timeline_value_str) {
+		char value[64];
+		obj->ops->timeline_value_str(obj, value, sizeof(value));
+		seq_printf(s, ": %s", value);
+	} else if (obj->ops->print_obj) {
+		seq_printf(s, ": ");
+		obj->ops->print_obj(s, obj);
+	}
+
+	seq_printf(s, "\n");
+
+	spin_lock_irqsave(&obj->child_list_lock, flags);
+	list_for_each(pos, &obj->child_list_head) {
+		struct sync_pt *pt =
+			container_of(pos, struct sync_pt, child_list);
+		sync_print_pt(s, pt, false);
+	}
+	spin_unlock_irqrestore(&obj->child_list_lock, flags);
+}
+
+static void sync_print_fence(struct seq_file *s, struct sync_fence *fence)
+{
+	struct list_head *pos;
+	unsigned long flags;
+
+	seq_printf(s, "[%p] %s: %s\n", fence, fence->name,
+		   sync_status_str(fence->status));
+
+	list_for_each(pos, &fence->pt_list_head) {
+		struct sync_pt *pt =
+			container_of(pos, struct sync_pt, pt_list);
+		sync_print_pt(s, pt, true);
+	}
+
+	spin_lock_irqsave(&fence->waiter_list_lock, flags);
+	list_for_each(pos, &fence->waiter_list_head) {
+		struct sync_fence_waiter *waiter =
+			container_of(pos, struct sync_fence_waiter,
+				     waiter_list);
+
+		seq_printf(s, "waiter %pF\n", waiter->callback);
+	}
+	spin_unlock_irqrestore(&fence->waiter_list_lock, flags);
+}
+
+static int sync_debugfs_show(struct seq_file *s, void *unused)
+{
+	unsigned long flags;
+	struct list_head *pos;
+
+	seq_printf(s, "objs:\n--------------\n");
+
+	spin_lock_irqsave(&sync_timeline_list_lock, flags);
+	list_for_each(pos, &sync_timeline_list_head) {
+		struct sync_timeline *obj =
+			container_of(pos, struct sync_timeline,
+				     sync_timeline_list);
+
+		sync_print_obj(s, obj);
+		seq_printf(s, "\n");
+	}
+	spin_unlock_irqrestore(&sync_timeline_list_lock, flags);
+
+	seq_printf(s, "fences:\n--------------\n");
+
+	spin_lock_irqsave(&sync_fence_list_lock, flags);
+	list_for_each(pos, &sync_fence_list_head) {
+		struct sync_fence *fence =
+			container_of(pos, struct sync_fence, sync_fence_list);
+
+		sync_print_fence(s, fence);
+		seq_printf(s, "\n");
+	}
+	spin_unlock_irqrestore(&sync_fence_list_lock, flags);
+	return 0;
+}
+
+static int sync_debugfs_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, sync_debugfs_show, inode->i_private);
+}
+
+static const struct file_operations sync_debugfs_fops = {
+	.open           = sync_debugfs_open,
+	.read           = seq_read,
+	.llseek         = seq_lseek,
+	.release        = single_release,
+};
+
+static __init int sync_debugfs_init(void)
+{
+	debugfs_create_file("sync", S_IRUGO, NULL, NULL, &sync_debugfs_fops);
+	return 0;
+}
+late_initcall(sync_debugfs_init);
+
+#define DUMP_CHUNK 256
+static char sync_dump_buf[64 * 1024];
+void sync_dump(void)
+{
+	struct seq_file s = {
+		.buf = sync_dump_buf,
+		.size = sizeof(sync_dump_buf) - 1,
+	};
+	int i;
+
+	sync_debugfs_show(&s, NULL);
+
+	for (i = 0; i < s.count; i += DUMP_CHUNK) {
+		if ((s.count - i) > DUMP_CHUNK) {
+			char c = s.buf[i + DUMP_CHUNK];
+			s.buf[i + DUMP_CHUNK] = 0;
+			pr_cont("%s", s.buf + i);
+			s.buf[i + DUMP_CHUNK] = c;
+		} else {
+			s.buf[s.count] = 0;
+			pr_cont("%s", s.buf + i);
+		}
+	}
+}
+#else
+static void sync_dump(void)
+{
+}
+#endif
diff --git a/drivers/staging/android/sync.h b/drivers/staging/android/sync.h
new file mode 100644
index 0000000..38ea986
--- /dev/null
+++ b/drivers/staging/android/sync.h
@@ -0,0 +1,426 @@
+/*
+ * include/linux/sync.h
+ *
+ * Copyright (C) 2012 Google, Inc.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 _LINUX_SYNC_H
+#define _LINUX_SYNC_H
+
+#include <linux/types.h>
+#ifdef __KERNEL__
+
+#include <linux/kref.h>
+#include <linux/ktime.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/wait.h>
+
+struct sync_timeline;
+struct sync_pt;
+struct sync_fence;
+
+/**
+ * struct sync_timeline_ops - sync object implementation ops
+ * @driver_name:	name of the implentation
+ * @dup:		duplicate a sync_pt
+ * @has_signaled:	returns:
+ *			  1 if pt has signaled
+ *			  0 if pt has not signaled
+ *			 <0 on error
+ * @compare:		returns:
+ *			  1 if b will signal before a
+ *			  0 if a and b will signal at the same time
+ *			 -1 if a will signabl before b
+ * @free_pt:		called before sync_pt is freed
+ * @release_obj:	called before sync_timeline is freed
+ * @print_obj:		deprecated
+ * @print_pt:		deprecated
+ * @fill_driver_data:	write implmentation specific driver data to data.
+ *			  should return an error if there is not enough room
+ *			  as specified by size.  This information is returned
+ *			  to userspace by SYNC_IOC_FENCE_INFO.
+ * @timeline_value_str: fill str with the value of the sync_timeline's counter
+ * @pt_value_str:	fill str with the value of the sync_pt
+ */
+struct sync_timeline_ops {
+	const char *driver_name;
+
+	/* required */
+	struct sync_pt *(*dup)(struct sync_pt *pt);
+
+	/* required */
+	int (*has_signaled)(struct sync_pt *pt);
+
+	/* required */
+	int (*compare)(struct sync_pt *a, struct sync_pt *b);
+
+	/* optional */
+	void (*free_pt)(struct sync_pt *sync_pt);
+
+	/* optional */
+	void (*release_obj)(struct sync_timeline *sync_timeline);
+
+	/* deprecated */
+	void (*print_obj)(struct seq_file *s,
+			  struct sync_timeline *sync_timeline);
+
+	/* deprecated */
+	void (*print_pt)(struct seq_file *s, struct sync_pt *sync_pt);
+
+	/* optional */
+	int (*fill_driver_data)(struct sync_pt *syncpt, void *data, int size);
+
+	/* optional */
+	void (*timeline_value_str)(struct sync_timeline *timeline, char *str,
+				   int size);
+
+	/* optional */
+	void (*pt_value_str)(struct sync_pt *pt, char *str, int size);
+};
+
+/**
+ * struct sync_timeline - sync object
+ * @kref:		reference count on fence.
+ * @ops:		ops that define the implementaiton of the sync_timeline
+ * @name:		name of the sync_timeline. Useful for debugging
+ * @destoryed:		set when sync_timeline is destroyed
+ * @child_list_head:	list of children sync_pts for this sync_timeline
+ * @child_list_lock:	lock protecting @child_list_head, destroyed, and
+ *			  sync_pt.status
+ * @active_list_head:	list of active (unsignaled/errored) sync_pts
+ * @sync_timeline_list:	membership in global sync_timeline_list
+ */
+struct sync_timeline {
+	struct kref		kref;
+	const struct sync_timeline_ops	*ops;
+	char			name[32];
+
+	/* protected by child_list_lock */
+	bool			destroyed;
+
+	struct list_head	child_list_head;
+	spinlock_t		child_list_lock;
+
+	struct list_head	active_list_head;
+	spinlock_t		active_list_lock;
+
+	struct list_head	sync_timeline_list;
+};
+
+/**
+ * struct sync_pt - sync point
+ * @parent:		sync_timeline to which this sync_pt belongs
+ * @child_list:		membership in sync_timeline.child_list_head
+ * @active_list:	membership in sync_timeline.active_list_head
+ * @signaled_list:	membership in temorary signaled_list on stack
+ * @fence:		sync_fence to which the sync_pt belongs
+ * @pt_list:		membership in sync_fence.pt_list_head
+ * @status:		1: signaled, 0:active, <0: error
+ * @timestamp:		time which sync_pt status transitioned from active to
+ *			  singaled or error.
+ */
+struct sync_pt {
+	struct sync_timeline		*parent;
+	struct list_head	child_list;
+
+	struct list_head	active_list;
+	struct list_head	signaled_list;
+
+	struct sync_fence	*fence;
+	struct list_head	pt_list;
+
+	/* protected by parent->active_list_lock */
+	int			status;
+
+	ktime_t			timestamp;
+};
+
+/**
+ * struct sync_fence - sync fence
+ * @file:		file representing this fence
+ * @kref:		referenace count on fence.
+ * @name:		name of sync_fence.  Useful for debugging
+ * @pt_list_head:	list of sync_pts in ths fence.  immutable once fence
+ *			  is created
+ * @waiter_list_head:	list of asynchronous waiters on this fence
+ * @waiter_list_lock:	lock protecting @waiter_list_head and @status
+ * @status:		1: signaled, 0:active, <0: error
+ *
+ * @wq:			wait queue for fence signaling
+ * @sync_fence_list:	membership in global fence list
+ */
+struct sync_fence {
+	struct file		*file;
+	struct kref		kref;
+	char			name[32];
+
+	/* this list is immutable once the fence is created */
+	struct list_head	pt_list_head;
+
+	struct list_head	waiter_list_head;
+	spinlock_t		waiter_list_lock; /* also protects status */
+	int			status;
+
+	wait_queue_head_t	wq;
+
+	struct list_head	sync_fence_list;
+};
+
+struct sync_fence_waiter;
+typedef void (*sync_callback_t)(struct sync_fence *fence,
+				struct sync_fence_waiter *waiter);
+
+/**
+ * struct sync_fence_waiter - metadata for asynchronous waiter on a fence
+ * @waiter_list:	membership in sync_fence.waiter_list_head
+ * @callback:		function pointer to call when fence signals
+ * @callback_data:	pointer to pass to @callback
+ */
+struct sync_fence_waiter {
+	struct list_head	waiter_list;
+
+	sync_callback_t		callback;
+};
+
+static inline void sync_fence_waiter_init(struct sync_fence_waiter *waiter,
+					  sync_callback_t callback)
+{
+	waiter->callback = callback;
+}
+
+/*
+ * API for sync_timeline implementers
+ */
+
+/**
+ * sync_timeline_create() - creates a sync object
+ * @ops:	specifies the implemention ops for the object
+ * @size:	size to allocate for this obj
+ * @name:	sync_timeline name
+ *
+ * Creates a new sync_timeline which will use the implemetation specified by
+ * @ops.  @size bytes will be allocated allowing for implemntation specific
+ * data to be kept after the generic sync_timeline stuct.
+ */
+struct sync_timeline *sync_timeline_create(const struct sync_timeline_ops *ops,
+					   int size, const char *name);
+
+/**
+ * sync_timeline_destory() - destorys a sync object
+ * @obj:	sync_timeline to destroy
+ *
+ * A sync implemntation should call this when the @obj is going away
+ * (i.e. module unload.)  @obj won't actually be freed until all its childern
+ * sync_pts are freed.
+ */
+void sync_timeline_destroy(struct sync_timeline *obj);
+
+/**
+ * sync_timeline_signal() - signal a status change on a sync_timeline
+ * @obj:	sync_timeline to signal
+ *
+ * A sync implemntation should call this any time one of it's sync_pts
+ * has signaled or has an error condition.
+ */
+void sync_timeline_signal(struct sync_timeline *obj);
+
+/**
+ * sync_pt_create() - creates a sync pt
+ * @parent:	sync_pt's parent sync_timeline
+ * @size:	size to allocate for this pt
+ *
+ * Creates a new sync_pt as a chiled of @parent.  @size bytes will be
+ * allocated allowing for implemntation specific data to be kept after
+ * the generic sync_timeline struct.
+ */
+struct sync_pt *sync_pt_create(struct sync_timeline *parent, int size);
+
+/**
+ * sync_pt_free() - frees a sync pt
+ * @pt:		sync_pt to free
+ *
+ * This should only be called on sync_pts which have been created but
+ * not added to a fence.
+ */
+void sync_pt_free(struct sync_pt *pt);
+
+/**
+ * sync_fence_create() - creates a sync fence
+ * @name:	name of fence to create
+ * @pt:		sync_pt to add to the fence
+ *
+ * Creates a fence containg @pt.  Once this is called, the fence takes
+ * ownership of @pt.
+ */
+struct sync_fence *sync_fence_create(const char *name, struct sync_pt *pt);
+
+/*
+ * API for sync_fence consumers
+ */
+
+/**
+ * sync_fence_merge() - merge two fences
+ * @name:	name of new fence
+ * @a:		fence a
+ * @b:		fence b
+ *
+ * Creates a new fence which contains copies of all the sync_pts in both
+ * @a and @b.  @a and @b remain valid, independent fences.
+ */
+struct sync_fence *sync_fence_merge(const char *name,
+				    struct sync_fence *a, struct sync_fence *b);
+
+/**
+ * sync_fence_fdget() - get a fence from an fd
+ * @fd:		fd referencing a fence
+ *
+ * Ensures @fd references a valid fence, increments the refcount of the backing
+ * file, and returns the fence.
+ */
+struct sync_fence *sync_fence_fdget(int fd);
+
+/**
+ * sync_fence_put() - puts a refernnce of a sync fence
+ * @fence:	fence to put
+ *
+ * Puts a reference on @fence.  If this is the last reference, the fence and
+ * all it's sync_pts will be freed
+ */
+void sync_fence_put(struct sync_fence *fence);
+
+/**
+ * sync_fence_install() - installs a fence into a file descriptor
+ * @fence:	fence to instal
+ * @fd:		file descriptor in which to install the fence
+ *
+ * Installs @fence into @fd.  @fd's should be acquired through get_unused_fd().
+ */
+void sync_fence_install(struct sync_fence *fence, int fd);
+
+/**
+ * sync_fence_wait_async() - registers and async wait on the fence
+ * @fence:		fence to wait on
+ * @waiter:		waiter callback struck
+ *
+ * Returns 1 if @fence has already signaled.
+ *
+ * Registers a callback to be called when @fence signals or has an error.
+ * @waiter should be initialized with sync_fence_waiter_init().
+ */
+int sync_fence_wait_async(struct sync_fence *fence,
+			  struct sync_fence_waiter *waiter);
+
+/**
+ * sync_fence_cancel_async() - cancels an async wait
+ * @fence:		fence to wait on
+ * @waiter:		waiter callback struck
+ *
+ * returns 0 if waiter was removed from fence's async waiter list.
+ * returns -ENOENT if waiter was not found on fence's async waiter list.
+ *
+ * Cancels a previously registered async wait.  Will fail gracefully if
+ * @waiter was never registered or if @fence has already signaled @waiter.
+ */
+int sync_fence_cancel_async(struct sync_fence *fence,
+			    struct sync_fence_waiter *waiter);
+
+/**
+ * sync_fence_wait() - wait on fence
+ * @fence:	fence to wait on
+ * @tiemout:	timeout in ms
+ *
+ * Wait for @fence to be signaled or have an error.  Waits indefinitely
+ * if @timeout < 0
+ */
+int sync_fence_wait(struct sync_fence *fence, long timeout);
+
+#endif /* __KERNEL__ */
+
+/**
+ * struct sync_merge_data - data passed to merge ioctl
+ * @fd2:	file descriptor of second fence
+ * @name:	name of new fence
+ * @fence:	returns the fd of the new fence to userspace
+ */
+struct sync_merge_data {
+	__s32	fd2; /* fd of second fence */
+	char	name[32]; /* name of new fence */
+	__s32	fence; /* fd on newly created fence */
+};
+
+/**
+ * struct sync_pt_info - detailed sync_pt information
+ * @len:		length of sync_pt_info including any driver_data
+ * @obj_name:		name of parent sync_timeline
+ * @driver_name:	name of driver implmenting the parent
+ * @status:		status of the sync_pt 0:active 1:signaled <0:error
+ * @timestamp_ns:	timestamp of status change in nanoseconds
+ * @driver_data:	any driver dependant data
+ */
+struct sync_pt_info {
+	__u32	len;
+	char	obj_name[32];
+	char	driver_name[32];
+	__s32	status;
+	__u64	timestamp_ns;
+
+	__u8	driver_data[0];
+};
+
+/**
+ * struct sync_fence_info_data - data returned from fence info ioctl
+ * @len:	ioctl caller writes the size of the buffer its passing in.
+ *		ioctl returns length of sync_fence_data reutnred to userspace
+ *		including pt_info.
+ * @name:	name of fence
+ * @status:	status of fence. 1: signaled 0:active <0:error
+ * @pt_info:	a sync_pt_info struct for every sync_pt in the fence
+ */
+struct sync_fence_info_data {
+	__u32	len;
+	char	name[32];
+	__s32	status;
+
+	__u8	pt_info[0];
+};
+
+#define SYNC_IOC_MAGIC		'>'
+
+/**
+ * DOC: SYNC_IOC_WAIT - wait for a fence to signal
+ *
+ * pass timeout in milliseconds.  Waits indefinitely timeout < 0.
+ */
+#define SYNC_IOC_WAIT		_IOW(SYNC_IOC_MAGIC, 0, __s32)
+
+/**
+ * DOC: SYNC_IOC_MERGE - merge two fences
+ *
+ * Takes a struct sync_merge_data.  Creates a new fence containing copies of
+ * the sync_pts in both the calling fd and sync_merge_data.fd2.  Returns the
+ * new fence's fd in sync_merge_data.fence
+ */
+#define SYNC_IOC_MERGE		_IOWR(SYNC_IOC_MAGIC, 1, struct sync_merge_data)
+
+/**
+ * DOC: SYNC_IOC_FENCE_INFO - get detailed information on a fence
+ *
+ * Takes a struct sync_fence_info_data with extra space allocated for pt_info.
+ * Caller should write the size of the buffer into len.  On return, len is
+ * updated to reflect the total size of the sync_fence_info_data including
+ * pt_info.
+ *
+ * pt_info is a buffer containing sync_pt_infos for every sync_pt in the fence.
+ * To itterate over the sync_pt_infos, use the sync_pt_info.len field.
+ */
+#define SYNC_IOC_FENCE_INFO	_IOWR(SYNC_IOC_MAGIC, 2,\
+	struct sync_fence_info_data)
+
+#endif /* _LINUX_SYNC_H */
diff --git a/drivers/staging/android/trace/sync.h b/drivers/staging/android/trace/sync.h
new file mode 100644
index 0000000..9546235
--- /dev/null
+++ b/drivers/staging/android/trace/sync.h
@@ -0,0 +1,82 @@
+#undef TRACE_SYSTEM
+#define TRACE_INCLUDE_PATH ../../drivers/staging/android/trace
+#define TRACE_SYSTEM sync
+
+#if !defined(_TRACE_SYNC_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_SYNC_H
+
+#include "../sync.h"
+#include <linux/tracepoint.h>
+
+TRACE_EVENT(sync_timeline,
+	TP_PROTO(struct sync_timeline *timeline),
+
+	TP_ARGS(timeline),
+
+	TP_STRUCT__entry(
+			__string(name, timeline->name)
+			__array(char, value, 32)
+	),
+
+	TP_fast_assign(
+			__assign_str(name, timeline->name);
+			if (timeline->ops->timeline_value_str) {
+				timeline->ops->timeline_value_str(timeline,
+							__entry->value,
+							sizeof(__entry->value));
+			} else {
+				__entry->value[0] = '\0';
+			}
+	),
+
+	TP_printk("name=%s value=%s", __get_str(name), __entry->value)
+);
+
+TRACE_EVENT(sync_wait,
+	TP_PROTO(struct sync_fence *fence, int begin),
+
+	TP_ARGS(fence, begin),
+
+	TP_STRUCT__entry(
+			__string(name, fence->name)
+			__field(s32, status)
+			__field(u32, begin)
+	),
+
+	TP_fast_assign(
+			__assign_str(name, fence->name);
+			__entry->status = fence->status;
+			__entry->begin = begin;
+	),
+
+	TP_printk("%s name=%s state=%d", __entry->begin ? "begin" : "end",
+			__get_str(name), __entry->status)
+);
+
+TRACE_EVENT(sync_pt,
+	TP_PROTO(struct sync_pt *pt),
+
+	TP_ARGS(pt),
+
+	TP_STRUCT__entry(
+		__string(timeline, pt->parent->name)
+		__array(char, value, 32)
+	),
+
+	TP_fast_assign(
+		__assign_str(timeline, pt->parent->name);
+		if (pt->parent->ops->pt_value_str) {
+			pt->parent->ops->pt_value_str(pt, __entry->value,
+							sizeof(__entry->value));
+		} else {
+			__entry->value[0] = '\0';
+		}
+	),
+
+	TP_printk("name=%s value=%s", __get_str(timeline), __entry->value)
+);
+
+#endif /* if !defined(_TRACE_SYNC_H) || defined(TRACE_HEADER_MULTI_READ) */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/drivers/staging/bcm/Bcmchar.c b/drivers/staging/bcm/Bcmchar.c
index 491e2bf..35641e5 100644
--- a/drivers/staging/bcm/Bcmchar.c
+++ b/drivers/staging/bcm/Bcmchar.c
@@ -1148,8 +1148,8 @@ cntrlEnd:
 
 		if (((ULONG)pBulkBuffer->Register & 0x0F000000) != 0x0F000000 ||
 			((ULONG)pBulkBuffer->Register & 0x3)) {
-			kfree(pvBuffer);
 			BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "WRM Done On invalid Address : %x Access Denied.\n", (int)pBulkBuffer->Register);
+			kfree(pvBuffer);
 			Status = -EINVAL;
 			break;
 		}
diff --git a/drivers/staging/bcm/InterfaceDld.c b/drivers/staging/bcm/InterfaceDld.c
index 64ea6ed..348ad75 100644
--- a/drivers/staging/bcm/InterfaceDld.c
+++ b/drivers/staging/bcm/InterfaceDld.c
@@ -205,30 +205,6 @@ static int bcm_download_config_file(struct bcm_mini_adapter *Adapter, struct bcm
 	return retval;
 }
 
-static int bcm_compare_buff_contents(unsigned char *readbackbuff, unsigned char *buff, unsigned int len)
-{
-	int retval = STATUS_SUCCESS;
-	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
-	if ((len-sizeof(unsigned int)) < 4) {
-		if (memcmp(readbackbuff , buff, len))
-			retval = -EINVAL;
-	} else {
-		len -= 4;
-
-		while (len) {
-			if (*(unsigned int *)&readbackbuff[len] != *(unsigned int *)&buff[len]) {
-				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Firmware Download is not proper");
-				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Val from Binary %x, Val From Read Back %x ", *(unsigned int *)&buff[len], *(unsigned int*)&readbackbuff[len]);
-				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "len =%x!!!", len);
-				retval = -EINVAL;
-				break;
-			}
-			len -= 4;
-		}
-	}
-	return retval;
-}
-
 int bcm_ioctl_fw_download(struct bcm_mini_adapter *Adapter, struct bcm_firmware_info *psFwInfo)
 {
 	int retval = STATUS_SUCCESS;
@@ -321,9 +297,11 @@ static INT buffRdbkVerify(struct bcm_mini_adapter *Adapter, PUCHAR mappedbuffer,
 			break;
 		}
 
-		retval = bcm_compare_buff_contents(readbackbuff, mappedbuffer, len);
-		if (STATUS_SUCCESS != retval)
-			break;
+		if (memcmp(readbackbuff, mappedbuffer, len) != 0) {
+			pr_err("%s() failed.  The firmware doesn't match what was written",
+			       __func__);
+			retval = -EIO;
+		}
 
 		u32StartingAddress += len;
 		u32FirmwareLength -= len;
diff --git a/drivers/staging/bcm/PHSModule.c b/drivers/staging/bcm/PHSModule.c
index 7028bc9..af5d22f 100644
--- a/drivers/staging/bcm/PHSModule.c
+++ b/drivers/staging/bcm/PHSModule.c
@@ -1,263 +1,238 @@
 #include "headers.h"
 
-static UINT CreateSFToClassifierRuleMapping(B_UINT16 uiVcid,B_UINT16  uiClsId, struct bcm_phs_table *psServiceFlowTable, struct bcm_phs_rule *psPhsRule, B_UINT8 u8AssociatedPHSI);
+static UINT CreateSFToClassifierRuleMapping(B_UINT16 uiVcid, B_UINT16 uiClsId, struct bcm_phs_table *psServiceFlowTable, struct bcm_phs_rule *psPhsRule, B_UINT8 u8AssociatedPHSI);
 
-static UINT CreateClassiferToPHSRuleMapping(B_UINT16 uiVcid,B_UINT16  uiClsId, struct bcm_phs_entry *pstServiceFlowEntry, struct bcm_phs_rule *psPhsRule, B_UINT8 u8AssociatedPHSI);
+static UINT CreateClassiferToPHSRuleMapping(B_UINT16 uiVcid, B_UINT16  uiClsId, struct bcm_phs_entry *pstServiceFlowEntry, struct bcm_phs_rule *psPhsRule, B_UINT8 u8AssociatedPHSI);
 
-static UINT CreateClassifierPHSRule(B_UINT16  uiClsId, struct bcm_phs_classifier_table *psaClassifiertable, struct bcm_phs_rule *psPhsRule, enum bcm_phs_classifier_context eClsContext,B_UINT8 u8AssociatedPHSI);
+static UINT CreateClassifierPHSRule(B_UINT16  uiClsId, struct bcm_phs_classifier_table *psaClassifiertable, struct bcm_phs_rule *psPhsRule, enum bcm_phs_classifier_context eClsContext, B_UINT8 u8AssociatedPHSI);
 
-static UINT UpdateClassifierPHSRule(B_UINT16  uiClsId, struct bcm_phs_classifier_entry *pstClassifierEntry, struct bcm_phs_classifier_table *psaClassifiertable, struct bcm_phs_rule *psPhsRule, B_UINT8 u8AssociatedPHSI);
+static UINT UpdateClassifierPHSRule(B_UINT16 uiClsId, struct bcm_phs_classifier_entry *pstClassifierEntry, struct bcm_phs_classifier_table *psaClassifiertable, struct bcm_phs_rule *psPhsRule, B_UINT8 u8AssociatedPHSI);
 
 static BOOLEAN ValidatePHSRuleComplete(struct bcm_phs_rule *psPhsRule);
 
-static BOOLEAN DerefPhsRule(B_UINT16  uiClsId, struct bcm_phs_classifier_table *psaClassifiertable, struct bcm_phs_rule *pstPhsRule);
+static BOOLEAN DerefPhsRule(B_UINT16 uiClsId, struct bcm_phs_classifier_table *psaClassifiertable, struct bcm_phs_rule *pstPhsRule);
 
-static UINT GetClassifierEntry(struct bcm_phs_classifier_table *pstClassifierTable,B_UINT32 uiClsid, enum bcm_phs_classifier_context eClsContext, struct bcm_phs_classifier_entry **ppstClassifierEntry);
+static UINT GetClassifierEntry(struct bcm_phs_classifier_table *pstClassifierTable, B_UINT32 uiClsid, enum bcm_phs_classifier_context eClsContext, struct bcm_phs_classifier_entry **ppstClassifierEntry);
 
-static UINT GetPhsRuleEntry(struct bcm_phs_classifier_table *pstClassifierTable,B_UINT32 uiPHSI, enum bcm_phs_classifier_context eClsContext, struct bcm_phs_rule **ppstPhsRule);
+static UINT GetPhsRuleEntry(struct bcm_phs_classifier_table *pstClassifierTable, B_UINT32 uiPHSI, enum bcm_phs_classifier_context eClsContext, struct bcm_phs_rule **ppstPhsRule);
 
 static void free_phs_serviceflow_rules(struct bcm_phs_table *psServiceFlowRulesTable);
 
 static int phs_compress(struct bcm_phs_rule *phs_members, unsigned char *in_buf,
-						unsigned char *out_buf,unsigned int *header_size,UINT *new_header_size );
+			unsigned char *out_buf, unsigned int *header_size, UINT *new_header_size);
 
+static int verify_suppress_phsf(unsigned char *in_buffer, unsigned char *out_buffer,
+				unsigned char *phsf, unsigned char *phsm, unsigned int phss, unsigned int phsv, UINT *new_header_size);
 
-static int verify_suppress_phsf(unsigned char *in_buffer,unsigned char *out_buffer,
-								unsigned char *phsf,unsigned char *phsm,unsigned int phss,unsigned int phsv,UINT *new_header_size );
-
-static int phs_decompress(unsigned char *in_buf,unsigned char *out_buf,\
-						  struct bcm_phs_rule *phs_rules, UINT *header_size);
-
-
-static ULONG PhsCompress(void* pvContext,
-				  B_UINT16 uiVcid,
-				  B_UINT16 uiClsId,
-				  void *pvInputBuffer,
-				  void *pvOutputBuffer,
-				  UINT *pOldHeaderSize,
-				  UINT *pNewHeaderSize );
-
-static ULONG PhsDeCompress(void* pvContext,
-				  B_UINT16 uiVcid,
-				  void *pvInputBuffer,
-				  void *pvOutputBuffer,
-				  UINT *pInHeaderSize,
-				  UINT *pOutHeaderSize);
+static int phs_decompress(unsigned char *in_buf, unsigned char *out_buf,
+			struct bcm_phs_rule *phs_rules, UINT *header_size);
 
+static ULONG PhsCompress(void *pvContext,
+			B_UINT16 uiVcid,
+			B_UINT16 uiClsId,
+			void *pvInputBuffer,
+			void *pvOutputBuffer,
+			UINT *pOldHeaderSize,
+			UINT *pNewHeaderSize);
 
+static ULONG PhsDeCompress(void *pvContext,
+			B_UINT16 uiVcid,
+			void *pvInputBuffer,
+			void *pvOutputBuffer,
+			UINT *pInHeaderSize,
+			UINT *pOutHeaderSize);
 
 #define IN
 #define OUT
 
 /*
-Function:				PHSTransmit
-
-Description:			This routine handle PHS(Payload Header Suppression for Tx path.
-					It extracts a fragment of the NDIS_PACKET containing the header
-					to be suppressed. It then suppresses the header by invoking PHS exported compress routine.
-					The header data after suppression is copied back to the NDIS_PACKET.
-
-
-Input parameters:		IN struct bcm_mini_adapter *Adapter         - Miniport Adapter Context
-						IN Packet 				- NDIS packet containing data to be transmitted
-						IN USHORT Vcid        - vcid pertaining to connection on which the packet is being sent.Used to
-										        identify PHS rule to be applied.
-						B_UINT16 uiClassifierRuleID - Classifier Rule ID
-						BOOLEAN bHeaderSuppressionEnabled - indicates if header suprression is enabled for SF.
-
-Return:					STATUS_SUCCESS - If the send was successful.
-						Other  - If an error occurred.
-*/
+ * Function: PHSTransmit
+ * Description:	This routine handle PHS(Payload Header Suppression for Tx path.
+ *	It extracts a fragment of the NDIS_PACKET containing the header
+ *	to be suppressed. It then suppresses the header by invoking PHS exported compress routine.
+ *	The header data after suppression is copied back to the NDIS_PACKET.
+ *
+ * Input parameters: IN struct bcm_mini_adapter *Adapter         - Miniport Adapter Context
+ *	IN Packet - NDIS packet containing data to be transmitted
+ *	IN USHORT Vcid - vcid pertaining to connection on which the packet is being sent.Used to
+ *		identify PHS rule to be applied.
+ *	B_UINT16 uiClassifierRuleID - Classifier Rule ID
+ *	BOOLEAN bHeaderSuppressionEnabled - indicates if header suprression is enabled for SF.
+ *
+ * Return:	STATUS_SUCCESS - If the send was successful.
+ *	Other  - If an error occurred.
+ */
 
 int PHSTransmit(struct bcm_mini_adapter *Adapter,
-					 struct sk_buff	**pPacket,
-					 USHORT Vcid,
-					 B_UINT16 uiClassifierRuleID,
-					 BOOLEAN bHeaderSuppressionEnabled,
-					 UINT *PacketLen,
-					 UCHAR bEthCSSupport)
+		struct sk_buff **pPacket,
+		USHORT Vcid,
+		B_UINT16 uiClassifierRuleID,
+		BOOLEAN bHeaderSuppressionEnabled,
+		UINT *PacketLen,
+		UCHAR bEthCSSupport)
 {
-
-	//PHS Sepcific
-	UINT    unPHSPktHdrBytesCopied = 0;
-	UINT	unPhsOldHdrSize = 0;
-	UINT	unPHSNewPktHeaderLen = 0;
+	/* PHS Sepcific */
+	UINT unPHSPktHdrBytesCopied = 0;
+	UINT unPhsOldHdrSize = 0;
+	UINT unPHSNewPktHeaderLen = 0;
 	/* Pointer to PHS IN Hdr Buffer */
-	PUCHAR pucPHSPktHdrInBuf =
-				Adapter->stPhsTxContextInfo.ucaHdrSuppressionInBuf;
+	PUCHAR pucPHSPktHdrInBuf = Adapter->stPhsTxContextInfo.ucaHdrSuppressionInBuf;
 	/* Pointer to PHS OUT Hdr Buffer */
-	PUCHAR  pucPHSPktHdrOutBuf =
-					Adapter->stPhsTxContextInfo.ucaHdrSuppressionOutBuf;
-	UINT       usPacketType;
-	UINT       BytesToRemove=0;
-	BOOLEAN  bPHSI = 0;
+	PUCHAR pucPHSPktHdrOutBuf = Adapter->stPhsTxContextInfo.ucaHdrSuppressionOutBuf;
+	UINT usPacketType;
+	UINT BytesToRemove = 0;
+	BOOLEAN bPHSI = 0;
 	LONG ulPhsStatus = 0;
-	UINT 	numBytesCompressed = 0;
+	UINT numBytesCompressed = 0;
 	struct sk_buff *newPacket = NULL;
 	struct sk_buff *Packet = *pPacket;
 
-	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "In PHSTransmit");
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "In PHSTransmit");
 
-	if(!bEthCSSupport)
-		BytesToRemove=ETH_HLEN;
+	if (!bEthCSSupport)
+		BytesToRemove = ETH_HLEN;
 	/*
-		Accumulate the header upto the size we support suppression
-		from NDIS packet
-	*/
-
-	usPacketType=((struct ethhdr *)(Packet->data))->h_proto;
+	 * Accumulate the header upto the size we support suppression
+	 * from NDIS packet
+	 */
 
+	usPacketType = ((struct ethhdr *)(Packet->data))->h_proto;
 
 	pucPHSPktHdrInBuf = Packet->data + BytesToRemove;
-	//considering data after ethernet header
-	if((*PacketLen - BytesToRemove) < MAX_PHS_LENGTHS)
-	{
-
+	/* considering data after ethernet header */
+	if ((*PacketLen - BytesToRemove) < MAX_PHS_LENGTHS)
 		unPHSPktHdrBytesCopied = (*PacketLen - BytesToRemove);
-	}
 	else
-	{
 		unPHSPktHdrBytesCopied = MAX_PHS_LENGTHS;
-	}
 
-	if( (unPHSPktHdrBytesCopied > 0 ) &&
-		(unPHSPktHdrBytesCopied <= MAX_PHS_LENGTHS))
-	{
-
-
-		// Step 2 Suppress Header using PHS and fill into intermediate ucaPHSPktHdrOutBuf.
-	// Suppress only if IP Header and PHS Enabled For the Service Flow
-		if(((usPacketType == ETHERNET_FRAMETYPE_IPV4) ||
-			(usPacketType == ETHERNET_FRAMETYPE_IPV6)) &&
-			(bHeaderSuppressionEnabled))
-		{
-				BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nTrying to PHS Compress Using Classifier rule 0x%X",uiClassifierRuleID);
-
-
-				unPHSNewPktHeaderLen = unPHSPktHdrBytesCopied;
-				ulPhsStatus = PhsCompress(&Adapter->stBCMPhsContext,
-					Vcid,
-					uiClassifierRuleID,
-					pucPHSPktHdrInBuf,
-					pucPHSPktHdrOutBuf,
-					&unPhsOldHdrSize,
-					&unPHSNewPktHeaderLen);
-				BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nPHS Old header Size : %d New Header Size  %d\n",unPhsOldHdrSize,unPHSNewPktHeaderLen);
-
-				if(unPHSNewPktHeaderLen == unPhsOldHdrSize)
-				{
-					if(  ulPhsStatus == STATUS_PHS_COMPRESSED)
-							bPHSI = *pucPHSPktHdrOutBuf;
-					ulPhsStatus = STATUS_PHS_NOCOMPRESSION;
-				}
-
-				if(  ulPhsStatus == STATUS_PHS_COMPRESSED)
-				{
-					BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"PHS Sending packet Compressed");
+	if ((unPHSPktHdrBytesCopied > 0) &&
+		(unPHSPktHdrBytesCopied <= MAX_PHS_LENGTHS)) {
 
-					if(skb_cloned(Packet))
-					{
-						newPacket = skb_copy(Packet, GFP_ATOMIC);
+		/*
+		 * Step 2 Suppress Header using PHS and fill into intermediate ucaPHSPktHdrOutBuf.
+		 * Suppress only if IP Header and PHS Enabled For the Service Flow
+		 */
+		if (((usPacketType == ETHERNET_FRAMETYPE_IPV4) ||
+				(usPacketType == ETHERNET_FRAMETYPE_IPV6)) &&
+			(bHeaderSuppressionEnabled)) {
+
+			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "\nTrying to PHS Compress Using Classifier rule 0x%X", uiClassifierRuleID);
+			unPHSNewPktHeaderLen = unPHSPktHdrBytesCopied;
+			ulPhsStatus = PhsCompress(&Adapter->stBCMPhsContext,
+						Vcid,
+						uiClassifierRuleID,
+						pucPHSPktHdrInBuf,
+						pucPHSPktHdrOutBuf,
+						&unPhsOldHdrSize,
+						&unPHSNewPktHeaderLen);
+			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "\nPHS Old header Size : %d New Header Size  %d\n", unPhsOldHdrSize, unPHSNewPktHeaderLen);
+
+			if (unPHSNewPktHeaderLen == unPhsOldHdrSize) {
+
+				if (ulPhsStatus == STATUS_PHS_COMPRESSED)
+					bPHSI = *pucPHSPktHdrOutBuf;
+
+				ulPhsStatus = STATUS_PHS_NOCOMPRESSION;
+			}
 
-						if(newPacket == NULL)
-							return STATUS_FAILURE;
+			if (ulPhsStatus == STATUS_PHS_COMPRESSED) {
 
-						dev_kfree_skb(Packet);
-						*pPacket = Packet = newPacket;
-						pucPHSPktHdrInBuf = Packet->data  + BytesToRemove;
-					}
+				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "PHS Sending packet Compressed");
 
-					numBytesCompressed = unPhsOldHdrSize - (unPHSNewPktHeaderLen+PHSI_LEN);
+				if (skb_cloned(Packet)) {
+					newPacket = skb_copy(Packet, GFP_ATOMIC);
 
-					memcpy(pucPHSPktHdrInBuf + numBytesCompressed, pucPHSPktHdrOutBuf, unPHSNewPktHeaderLen + PHSI_LEN);
-					memcpy(Packet->data + numBytesCompressed, Packet->data, BytesToRemove);
-					skb_pull(Packet, numBytesCompressed);
+					if (newPacket == NULL)
+						return STATUS_FAILURE;
 
-					return STATUS_SUCCESS;
+					dev_kfree_skb(Packet);
+					*pPacket = Packet = newPacket;
+					pucPHSPktHdrInBuf = Packet->data  + BytesToRemove;
 				}
 
-				else
-				{
-					//if one byte headroom is not available, increase it through skb_cow
-					if(!(skb_headroom(Packet) > 0))
-					{
-						if(skb_cow(Packet, 1))
-						{
-							BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "SKB Cow Failed\n");
-							return STATUS_FAILURE;
-						}
-					}
-					skb_push(Packet, 1);
+				numBytesCompressed = unPhsOldHdrSize - (unPHSNewPktHeaderLen + PHSI_LEN);
 
-					// CAUTION: The MAC Header is getting corrupted here for IP CS - can be saved by copying 14 Bytes.  not needed .... hence corrupting it.
-					*(Packet->data + BytesToRemove) = bPHSI;
-					return STATUS_SUCCESS;
-			}
-		}
-		else
-		{
-			if(!bHeaderSuppressionEnabled)
-			{
-				BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nHeader Suppression Disabled For SF: No PHS\n");
+				memcpy(pucPHSPktHdrInBuf + numBytesCompressed, pucPHSPktHdrOutBuf, unPHSNewPktHeaderLen + PHSI_LEN);
+				memcpy(Packet->data + numBytesCompressed, Packet->data, BytesToRemove);
+				skb_pull(Packet, numBytesCompressed);
+
+				return STATUS_SUCCESS;
+			} else {
+				/* if one byte headroom is not available, increase it through skb_cow */
+				if (!(skb_headroom(Packet) > 0)) {
+
+					if (skb_cow(Packet, 1)) {
+						BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "SKB Cow Failed\n");
+						return STATUS_FAILURE;
+					}
+				}
+				skb_push(Packet, 1);
+
+				/*
+				 * CAUTION: The MAC Header is getting corrupted
+				 * here for IP CS - can be saved by copying 14
+				 * Bytes.  not needed .... hence corrupting it.
+				 */
+				*(Packet->data + BytesToRemove) = bPHSI;
+				return STATUS_SUCCESS;
 			}
+		} else {
+
+			if (!bHeaderSuppressionEnabled)
+				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "\nHeader Suppression Disabled For SF: No PHS\n");
 
 			return STATUS_SUCCESS;
 		}
 	}
 
-	//BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"PHSTransmit : Dumping data packet After PHS");
+	/* BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"PHSTransmit : Dumping data packet After PHS"); */
 	return STATUS_SUCCESS;
 }
 
 int PHSReceive(struct bcm_mini_adapter *Adapter,
-					USHORT usVcid,
-					struct sk_buff *packet,
-					UINT *punPacketLen,
-					UCHAR *pucEthernetHdr,
-					UINT	bHeaderSuppressionEnabled)
+	USHORT usVcid,
+	struct sk_buff *packet,
+	UINT *punPacketLen,
+	UCHAR *pucEthernetHdr,
+	UINT bHeaderSuppressionEnabled)
 {
-	u32   nStandardPktHdrLen            		= 0;
-	u32   nTotalsuppressedPktHdrBytes  = 0;
-	int     ulPhsStatus 		= 0;
-	PUCHAR pucInBuff = NULL ;
+	u32 nStandardPktHdrLen = 0;
+	u32 nTotalsuppressedPktHdrBytes = 0;
+	int ulPhsStatus	= 0;
+	PUCHAR pucInBuff = NULL;
 	UINT TotalBytesAdded = 0;
-	if(!bHeaderSuppressionEnabled)
-	{
-		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"\nPhs Disabled for incoming packet");
+
+	if (!bHeaderSuppressionEnabled) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE, DBG_LVL_ALL, "\nPhs Disabled for incoming packet");
 		return ulPhsStatus;
 	}
 
 	pucInBuff = packet->data;
 
-	//Restore  PHS suppressed header
+	/* Restore PHS suppressed header */
 	nStandardPktHdrLen = packet->len;
 	ulPhsStatus = PhsDeCompress(&Adapter->stBCMPhsContext,
-		usVcid,
-		pucInBuff,
-		Adapter->ucaPHSPktRestoreBuf,
-		&nTotalsuppressedPktHdrBytes,
-		&nStandardPktHdrLen);
+				usVcid,
+				pucInBuff,
+				Adapter->ucaPHSPktRestoreBuf,
+				&nTotalsuppressedPktHdrBytes,
+				&nStandardPktHdrLen);
 
-	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"\nSuppressed PktHdrLen : 0x%x Restored PktHdrLen : 0x%x",
-					nTotalsuppressedPktHdrBytes,nStandardPktHdrLen);
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE, DBG_LVL_ALL, "\nSuppressed PktHdrLen : 0x%x Restored PktHdrLen : 0x%x",
+			nTotalsuppressedPktHdrBytes, nStandardPktHdrLen);
 
-	if(ulPhsStatus != STATUS_PHS_COMPRESSED)
-	{
+	if (ulPhsStatus != STATUS_PHS_COMPRESSED) {
 		skb_pull(packet, 1);
 		return STATUS_SUCCESS;
-	}
-	else
-	{
+	} else {
 		TotalBytesAdded = nStandardPktHdrLen - nTotalsuppressedPktHdrBytes - PHSI_LEN;
-		if(TotalBytesAdded)
-		{
-			if(skb_headroom(packet) >= (SKB_RESERVE_ETHERNET_HEADER + TotalBytesAdded))
+
+		if (TotalBytesAdded) {
+			if (skb_headroom(packet) >= (SKB_RESERVE_ETHERNET_HEADER + TotalBytesAdded))
 				skb_push(packet, TotalBytesAdded);
-			else
-			{
-				if(skb_cow(packet, skb_headroom(packet) + TotalBytesAdded))
-				{
-					BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "cow failed in receive\n");
+			else {
+				if (skb_cow(packet, skb_headroom(packet) + TotalBytesAdded)) {
+					BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "cow failed in receive\n");
 					return STATUS_FAILURE;
 				}
 
@@ -271,90 +246,80 @@ int PHSReceive(struct bcm_mini_adapter *Adapter,
 	return STATUS_SUCCESS;
 }
 
-void DumpFullPacket(UCHAR *pBuf,UINT nPktLen)
+void DumpFullPacket(UCHAR *pBuf, UINT nPktLen)
 {
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
-    BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,"Dumping Data Packet");
-    BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,pBuf,nPktLen);
+
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Dumping Data Packet");
+	BCM_DEBUG_PRINT_BUFFER(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, pBuf, nPktLen);
 }
 
-//-----------------------------------------------------------------------------
-// Procedure:   phs_init
-//
-// Description: This routine is responsible for allocating memory for classifier and
-// PHS rules.
-//
-// Arguments:
-// pPhsdeviceExtension - ptr to Device extension containing PHS Classifier rules and PHS Rules , RX, TX buffer etc
-//
-// Returns:
-// TRUE(1)	-If allocation of memory was success full.
-// FALSE	-If allocation of memory fails.
-//-----------------------------------------------------------------------------
+/*
+ * Procedure:   phs_init
+ *
+ * Description: This routine is responsible for allocating memory for classifier and
+ * PHS rules.
+ *
+ * Arguments:
+ * pPhsdeviceExtension - ptr to Device extension containing PHS Classifier rules and PHS Rules , RX, TX buffer etc
+ *
+ * Returns:
+ * TRUE(1)	-If allocation of memory was successful.
+ * FALSE	-If allocation of memory fails.
+ */
 int phs_init(struct bcm_phs_extension *pPhsdeviceExtension, struct bcm_mini_adapter *Adapter)
 {
 	int i;
 	struct bcm_phs_table *pstServiceFlowTable;
-    BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nPHS:phs_init function ");
 
-	if(pPhsdeviceExtension->pstServiceFlowPhsRulesTable)
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nPHS:phs_init function");
+
+	if (pPhsdeviceExtension->pstServiceFlowPhsRulesTable)
 		return -EINVAL;
 
-	pPhsdeviceExtension->pstServiceFlowPhsRulesTable =
-		kzalloc(sizeof(struct bcm_phs_table), GFP_KERNEL);
+	pPhsdeviceExtension->pstServiceFlowPhsRulesTable = kzalloc(sizeof(struct bcm_phs_table), GFP_KERNEL);
 
-    if(!pPhsdeviceExtension->pstServiceFlowPhsRulesTable)
-	{
-		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAllocation ServiceFlowPhsRulesTable failed");
+	if (!pPhsdeviceExtension->pstServiceFlowPhsRulesTable) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAllocation ServiceFlowPhsRulesTable failed");
 		return -ENOMEM;
 	}
 
 	pstServiceFlowTable = pPhsdeviceExtension->pstServiceFlowPhsRulesTable;
-	for(i=0;i<MAX_SERVICEFLOWS;i++)
-	{
+	for (i = 0; i < MAX_SERVICEFLOWS; i++) {
 		struct bcm_phs_entry sServiceFlow = pstServiceFlowTable->stSFList[i];
 		sServiceFlow.pstClassifierTable = kzalloc(sizeof(struct bcm_phs_classifier_table), GFP_KERNEL);
-		if(!sServiceFlow.pstClassifierTable)
-		{
-			BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAllocation failed");
-			free_phs_serviceflow_rules(pPhsdeviceExtension->
-                pstServiceFlowPhsRulesTable);
+		if (!sServiceFlow.pstClassifierTable) {
+			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAllocation failed");
+			free_phs_serviceflow_rules(pPhsdeviceExtension->pstServiceFlowPhsRulesTable);
 			pPhsdeviceExtension->pstServiceFlowPhsRulesTable = NULL;
 			return -ENOMEM;
 		}
 	}
 
 	pPhsdeviceExtension->CompressedTxBuffer = kmalloc(PHS_BUFFER_SIZE, GFP_KERNEL);
-
-    if(pPhsdeviceExtension->CompressedTxBuffer == NULL)
-	{
-		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAllocation failed");
+	if (pPhsdeviceExtension->CompressedTxBuffer == NULL) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAllocation failed");
 		free_phs_serviceflow_rules(pPhsdeviceExtension->pstServiceFlowPhsRulesTable);
 		pPhsdeviceExtension->pstServiceFlowPhsRulesTable = NULL;
 		return -ENOMEM;
 	}
 
-    pPhsdeviceExtension->UnCompressedRxBuffer = kmalloc(PHS_BUFFER_SIZE, GFP_KERNEL);
-	if(pPhsdeviceExtension->UnCompressedRxBuffer == NULL)
-	{
-		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAllocation failed");
+	pPhsdeviceExtension->UnCompressedRxBuffer = kmalloc(PHS_BUFFER_SIZE, GFP_KERNEL);
+	if (pPhsdeviceExtension->UnCompressedRxBuffer == NULL) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAllocation failed");
 		kfree(pPhsdeviceExtension->CompressedTxBuffer);
 		free_phs_serviceflow_rules(pPhsdeviceExtension->pstServiceFlowPhsRulesTable);
 		pPhsdeviceExtension->pstServiceFlowPhsRulesTable = NULL;
 		return -ENOMEM;
 	}
 
-
-
-	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\n phs_init Successful");
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\n phs_init Successful");
 	return STATUS_SUCCESS;
 }
 
-
 int PhsCleanup(IN struct bcm_phs_extension *pPHSDeviceExt)
 {
-	if(pPHSDeviceExt->pstServiceFlowPhsRulesTable)
-	{
+	if (pPHSDeviceExt->pstServiceFlowPhsRulesTable) {
 		free_phs_serviceflow_rules(pPHSDeviceExt->pstServiceFlowPhsRulesTable);
 		pPHSDeviceExt->pstServiceFlowPhsRulesTable = NULL;
 	}
@@ -368,200 +333,173 @@ int PhsCleanup(IN struct bcm_phs_extension *pPHSDeviceExt)
 	return 0;
 }
 
-
-
-//PHS functions
-/*++
-PhsUpdateClassifierRule
-
-Routine Description:
-    Exported function to add or modify a PHS Rule.
-
-Arguments:
-	IN void* pvContext - PHS Driver Specific Context
-	IN B_UINT16 uiVcid    - The Service Flow ID for which the PHS rule applies
-	IN B_UINT16  uiClsId   - The Classifier ID within the Service Flow for which the PHS rule applies.
-	IN struct bcm_phs_rule *psPhsRule - The PHS Rule strcuture to be added to the PHS Rule table.
-
-Return Value:
-
-    0 if successful,
-    >0 Error.
-
---*/
-ULONG PhsUpdateClassifierRule(IN void* pvContext,
-								IN B_UINT16  uiVcid ,
-								IN B_UINT16  uiClsId   ,
-								IN struct bcm_phs_rule *psPhsRule,
-								IN B_UINT8  u8AssociatedPHSI)
+/*
+ * PHS functions
+ * PhsUpdateClassifierRule
+ *
+ * Routine Description:
+ *   Exported function to add or modify a PHS Rule.
+ *
+ * Arguments:
+ *	IN void* pvContext - PHS Driver Specific Context
+ *	IN B_UINT16 uiVcid    - The Service Flow ID for which the PHS rule applies
+ *	IN B_UINT16  uiClsId   - The Classifier ID within the Service Flow for which the PHS rule applies.
+ *	IN struct bcm_phs_rule *psPhsRule - The PHS Rule strcuture to be added to the PHS Rule table.
+ *
+ * Return Value:
+ *
+ * 0 if successful,
+ * >0 Error.
+ */
+ULONG PhsUpdateClassifierRule(IN void *pvContext,
+			IN B_UINT16 uiVcid ,
+			IN B_UINT16 uiClsId   ,
+			IN struct bcm_phs_rule *psPhsRule,
+			IN B_UINT8 u8AssociatedPHSI)
 {
-	ULONG lStatus =0;
-	UINT nSFIndex =0 ;
+	ULONG lStatus = 0;
+	UINT nSFIndex = 0;
 	struct bcm_phs_entry *pstServiceFlowEntry = NULL;
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
+	struct bcm_phs_extension *pDeviceExtension = (struct bcm_phs_extension *)pvContext;
 
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "PHS With Corr2 Changes\n");
 
-
-	struct bcm_phs_extension *pDeviceExtension= (struct bcm_phs_extension *)pvContext;
-
-	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,"PHS With Corr2 Changes \n");
-
-	if(pDeviceExtension == NULL)
-	{
-		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,"Invalid Device Extension\n");
+	if (pDeviceExtension == NULL) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "Invalid Device Extension\n");
 		return ERR_PHS_INVALID_DEVICE_EXETENSION;
 	}
 
-
-	if(u8AssociatedPHSI == 0)
-	{
+	if (u8AssociatedPHSI == 0)
 		return ERR_PHS_INVALID_PHS_RULE;
-	}
 
 	/* Retrieve the SFID Entry Index for requested Service Flow */
-
 	nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable,
-	                uiVcid,&pstServiceFlowEntry);
+				uiVcid, &pstServiceFlowEntry);
 
-    if(nSFIndex == PHS_INVALID_TABLE_INDEX)
-	{
+	if (nSFIndex == PHS_INVALID_TABLE_INDEX) {
 		/* This is a new SF. Create a mapping entry for this */
 		lStatus = CreateSFToClassifierRuleMapping(uiVcid, uiClsId,
-		      pDeviceExtension->pstServiceFlowPhsRulesTable, psPhsRule, u8AssociatedPHSI);
+							pDeviceExtension->pstServiceFlowPhsRulesTable, psPhsRule, u8AssociatedPHSI);
 		return lStatus;
 	}
 
 	/* SF already Exists Add PHS Rule to existing SF */
-  	lStatus = CreateClassiferToPHSRuleMapping(uiVcid, uiClsId,
-  	          pstServiceFlowEntry, psPhsRule, u8AssociatedPHSI);
+	lStatus = CreateClassiferToPHSRuleMapping(uiVcid, uiClsId,
+						pstServiceFlowEntry, psPhsRule, u8AssociatedPHSI);
 
-    return lStatus;
+	return lStatus;
 }
 
-/*++
-PhsDeletePHSRule
-
-Routine Description:
-   Deletes the specified phs Rule within Vcid
-
-Arguments:
-	IN void* pvContext - PHS Driver Specific Context
-	IN B_UINT16  uiVcid    - The Service Flow ID for which the PHS rule applies
-	IN B_UINT8  u8PHSI   - the PHS Index identifying PHS rule to be deleted.
-
-Return Value:
-
-    0 if successful,
-    >0 Error.
-
---*/
-
-ULONG PhsDeletePHSRule(IN void* pvContext,IN B_UINT16 uiVcid,IN B_UINT8 u8PHSI)
+/*
+ * PhsDeletePHSRule
+ *
+ * Routine Description:
+ *   Deletes the specified phs Rule within Vcid
+ *
+ * Arguments:
+ *	IN void* pvContext - PHS Driver Specific Context
+ *	IN B_UINT16  uiVcid    - The Service Flow ID for which the PHS rule applies
+ *	IN B_UINT8  u8PHSI   - the PHS Index identifying PHS rule to be deleted.
+ *
+ * Return Value:
+ *
+ * 0 if successful,
+ * >0 Error.
+ */
+ULONG PhsDeletePHSRule(IN void *pvContext, IN B_UINT16 uiVcid, IN B_UINT8 u8PHSI)
 {
-	ULONG lStatus =0;
-	UINT nSFIndex =0, nClsidIndex =0 ;
+	ULONG lStatus = 0;
+	UINT nSFIndex = 0, nClsidIndex = 0;
 	struct bcm_phs_entry *pstServiceFlowEntry = NULL;
 	struct bcm_phs_classifier_table *pstClassifierRulesTable = NULL;
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
+	struct bcm_phs_extension *pDeviceExtension = (struct bcm_phs_extension *)pvContext;
 
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "======>\n");
 
-	struct bcm_phs_extension *pDeviceExtension= (struct bcm_phs_extension *)pvContext;
+	if (pDeviceExtension) {
+		/* Retrieve the SFID Entry Index for requested Service Flow */
+		nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable, uiVcid, &pstServiceFlowEntry);
 
-	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "======>\n");
-
-	if(pDeviceExtension)
-	{
-
-		//Retrieve the SFID Entry Index for requested Service Flow
-		nSFIndex = GetServiceFlowEntry(pDeviceExtension
-		      ->pstServiceFlowPhsRulesTable,uiVcid,&pstServiceFlowEntry);
-
-       if(nSFIndex == PHS_INVALID_TABLE_INDEX)
-		{
-			BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "SFID Match Failed\n");
+		if (nSFIndex == PHS_INVALID_TABLE_INDEX) {
+			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "SFID Match Failed\n");
 			return ERR_SF_MATCH_FAIL;
 		}
 
-		pstClassifierRulesTable=pstServiceFlowEntry->pstClassifierTable;
-		if(pstClassifierRulesTable)
-		{
-			for(nClsidIndex=0;nClsidIndex<MAX_PHSRULE_PER_SF;nClsidIndex++)
-			{
-				if(pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].bUsed && pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule)
-				{
-					if(pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8PHSI == u8PHSI)					{
-						if(pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt)
+		pstClassifierRulesTable = pstServiceFlowEntry->pstClassifierTable;
+		if (pstClassifierRulesTable) {
+			for (nClsidIndex = 0; nClsidIndex < MAX_PHSRULE_PER_SF; nClsidIndex++) {
+				if (pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].bUsed && pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule) {
+					if (pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8PHSI == u8PHSI) {
+
+						if (pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt)
 							pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt--;
-						if(0 == pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt)
+
+						if (0 == pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt)
 							kfree(pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule);
+
 						memset(&pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex], 0,
 							sizeof(struct bcm_phs_classifier_entry));
 					}
 				}
 			}
 		}
-
 	}
 	return lStatus;
 }
 
-/*++
-PhsDeleteClassifierRule
-
-Routine Description:
-    Exported function to Delete a PHS Rule for the SFID,CLSID Pair.
-
-Arguments:
-	IN void* pvContext - PHS Driver Specific Context
-	IN B_UINT16  uiVcid    - The Service Flow ID for which the PHS rule applies
-	IN B_UINT16  uiClsId   - The Classifier ID within the Service Flow for which the PHS rule applies.
-
-Return Value:
-
-    0 if successful,
-    >0 Error.
-
---*/
-ULONG PhsDeleteClassifierRule(IN void* pvContext,IN B_UINT16 uiVcid ,IN B_UINT16  uiClsId)
+/*
+ * PhsDeleteClassifierRule
+ *
+ * Routine Description:
+ *    Exported function to Delete a PHS Rule for the SFID,CLSID Pair.
+ *
+ * Arguments:
+ *	IN void* pvContext - PHS Driver Specific Context
+ *	IN B_UINT16  uiVcid    - The Service Flow ID for which the PHS rule applies
+ *	IN B_UINT16  uiClsId   - The Classifier ID within the Service Flow for which the PHS rule applies.
+ *
+ * Return Value:
+ *
+ * 0 if successful,
+ * >0 Error.
+ */
+ULONG PhsDeleteClassifierRule(IN void *pvContext, IN B_UINT16 uiVcid, IN B_UINT16 uiClsId)
 {
-	ULONG lStatus =0;
-	UINT nSFIndex =0, nClsidIndex =0 ;
+	ULONG lStatus = 0;
+	UINT nSFIndex = 0, nClsidIndex = 0;
 	struct bcm_phs_entry *pstServiceFlowEntry = NULL;
 	struct bcm_phs_classifier_entry *pstClassifierEntry = NULL;
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
-	struct bcm_phs_extension *pDeviceExtension= (struct bcm_phs_extension *)pvContext;
-
-	if(pDeviceExtension)
-	{
-		//Retrieve the SFID Entry Index for requested Service Flow
-		nSFIndex = GetServiceFlowEntry(pDeviceExtension
-		      ->pstServiceFlowPhsRulesTable, uiVcid, &pstServiceFlowEntry);
-		if(nSFIndex == PHS_INVALID_TABLE_INDEX)
-		{
-			BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,"SFID Match Failed\n");
+	struct bcm_phs_extension *pDeviceExtension = (struct bcm_phs_extension *)pvContext;
+
+	if (pDeviceExtension) {
+		/* Retrieve the SFID Entry Index for requested Service Flow */
+		nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable, uiVcid, &pstServiceFlowEntry);
+		if (nSFIndex == PHS_INVALID_TABLE_INDEX) {
+			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "SFID Match Failed\n");
 			return ERR_SF_MATCH_FAIL;
 		}
 
 		nClsidIndex = GetClassifierEntry(pstServiceFlowEntry->pstClassifierTable,
-                  uiClsId, eActiveClassifierRuleContext, &pstClassifierEntry);
-		if((nClsidIndex != PHS_INVALID_TABLE_INDEX) && (!pstClassifierEntry->bUnclassifiedPHSRule))
-		{
-			if(pstClassifierEntry->pstPhsRule)
-			{
-				if(pstClassifierEntry->pstPhsRule->u8RefCnt)
-				pstClassifierEntry->pstPhsRule->u8RefCnt--;
-				if(0==pstClassifierEntry->pstPhsRule->u8RefCnt)
-					kfree(pstClassifierEntry->pstPhsRule);
+						uiClsId, eActiveClassifierRuleContext, &pstClassifierEntry);
 
+		if ((nClsidIndex != PHS_INVALID_TABLE_INDEX) && (!pstClassifierEntry->bUnclassifiedPHSRule)) {
+			if (pstClassifierEntry->pstPhsRule) {
+				if (pstClassifierEntry->pstPhsRule->u8RefCnt)
+					pstClassifierEntry->pstPhsRule->u8RefCnt--;
+
+				if (0 == pstClassifierEntry->pstPhsRule->u8RefCnt)
+					kfree(pstClassifierEntry->pstPhsRule);
 			}
 			memset(pstClassifierEntry, 0, sizeof(struct bcm_phs_classifier_entry));
 		}
 
 		nClsidIndex = GetClassifierEntry(pstServiceFlowEntry->pstClassifierTable,
-                    uiClsId,eOldClassifierRuleContext,&pstClassifierEntry);
+						uiClsId, eOldClassifierRuleContext, &pstClassifierEntry);
 
-	   if((nClsidIndex != PHS_INVALID_TABLE_INDEX) && (!pstClassifierEntry->bUnclassifiedPHSRule))
-		{
+		if ((nClsidIndex != PHS_INVALID_TABLE_INDEX) && (!pstClassifierEntry->bUnclassifiedPHSRule)) {
 			kfree(pstClassifierEntry->pstPhsRule);
 			memset(pstClassifierEntry, 0, sizeof(struct bcm_phs_classifier_entry));
 		}
@@ -569,261 +507,223 @@ ULONG PhsDeleteClassifierRule(IN void* pvContext,IN B_UINT16 uiVcid ,IN B_UINT16
 	return lStatus;
 }
 
-/*++
-PhsDeleteSFRules
-
-Routine Description:
-    Exported function to Delete a all PHS Rules for the SFID.
-
-Arguments:
-	IN void* pvContext - PHS Driver Specific Context
-	IN B_UINT16 uiVcid   - The Service Flow ID for which the PHS rules need to be deleted
-
-Return Value:
-
-    0 if successful,
-    >0 Error.
-
---*/
-ULONG PhsDeleteSFRules(IN void* pvContext,IN B_UINT16 uiVcid)
+/*
+ * PhsDeleteSFRules
+ *
+ * Routine Description:
+ *    Exported function to Delete a all PHS Rules for the SFID.
+ *
+ * Arguments:
+ *	IN void* pvContext - PHS Driver Specific Context
+ *	IN B_UINT16 uiVcid   - The Service Flow ID for which the PHS rules need to be deleted
+ *
+ * Return Value:
+ *
+ * 0 if successful,
+ * >0 Error.
+ */
+ULONG PhsDeleteSFRules(IN void *pvContext, IN B_UINT16 uiVcid)
 {
-
-	ULONG lStatus =0;
-	UINT nSFIndex =0, nClsidIndex =0  ;
+	ULONG lStatus = 0;
+	UINT nSFIndex = 0, nClsidIndex = 0;
 	struct bcm_phs_entry *pstServiceFlowEntry = NULL;
 	struct bcm_phs_classifier_table *pstClassifierRulesTable = NULL;
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
-	struct bcm_phs_extension *pDeviceExtension= (struct bcm_phs_extension *)pvContext;
-    BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,"====> \n");
+	struct bcm_phs_extension *pDeviceExtension = (struct bcm_phs_extension *)pvContext;
+
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "====>\n");
 
-	if(pDeviceExtension)
-	{
-		//Retrieve the SFID Entry Index for requested Service Flow
+	if (pDeviceExtension) {
+		/* Retrieve the SFID Entry Index for requested Service Flow */
 		nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable,
-		                  uiVcid,&pstServiceFlowEntry);
-		if(nSFIndex == PHS_INVALID_TABLE_INDEX)
-		{
-			BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "SFID Match Failed\n");
+					uiVcid, &pstServiceFlowEntry);
+		if (nSFIndex == PHS_INVALID_TABLE_INDEX) {
+			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "SFID Match Failed\n");
 			return ERR_SF_MATCH_FAIL;
 		}
 
-		pstClassifierRulesTable=pstServiceFlowEntry->pstClassifierTable;
-		if(pstClassifierRulesTable)
-		{
-			for(nClsidIndex=0;nClsidIndex<MAX_PHSRULE_PER_SF;nClsidIndex++)
-			{
-				if(pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule)
-				{
-					if(pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex]
-                                                        .pstPhsRule->u8RefCnt)
-						pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex]
-						                                    .pstPhsRule->u8RefCnt--;
-					if(0==pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex]
-                                                          .pstPhsRule->u8RefCnt)
+		pstClassifierRulesTable = pstServiceFlowEntry->pstClassifierTable;
+		if (pstClassifierRulesTable) {
+			for (nClsidIndex = 0; nClsidIndex < MAX_PHSRULE_PER_SF; nClsidIndex++) {
+				if (pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule) {
+
+					if (pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt)
+						pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt--;
+
+					if (0 == pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt)
 						kfree(pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule);
-					    pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex]
-                                        .pstPhsRule = NULL;
+
+					pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule = NULL;
 				}
 				memset(&pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex], 0, sizeof(struct bcm_phs_classifier_entry));
-				if(pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex].pstPhsRule)
-				{
-					if(pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex]
-                                        .pstPhsRule->u8RefCnt)
-						pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex]
-						                  .pstPhsRule->u8RefCnt--;
-					if(0 == pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex]
-                                        .pstPhsRule->u8RefCnt)
-						kfree(pstClassifierRulesTable
-						      ->stOldPhsRulesList[nClsidIndex].pstPhsRule);
-					pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex]
-                              .pstPhsRule = NULL;
+				if (pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex].pstPhsRule) {
+
+					if (pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt)
+						pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt--;
+
+					if (0 == pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt)
+						kfree(pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex].pstPhsRule);
+
+					pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex].pstPhsRule = NULL;
 				}
 				memset(&pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex], 0, sizeof(struct bcm_phs_classifier_entry));
 			}
 		}
 		pstServiceFlowEntry->bUsed = FALSE;
 		pstServiceFlowEntry->uiVcid = 0;
-
 	}
 
 	return lStatus;
 }
 
-
-/*++
-PhsCompress
-
-Routine Description:
-    Exported function to compress the data using PHS.
-
-Arguments:
-	IN void* pvContext - PHS Driver Specific Context.
-	IN B_UINT16 uiVcid    - The Service Flow ID to which current packet header compression applies.
-	IN UINT  uiClsId   - The Classifier ID to which current packet header compression applies.
-	IN void *pvInputBuffer - The Input buffer containg packet header data
-	IN void *pvOutputBuffer - The output buffer returned by this function after PHS
-	IN UINT *pOldHeaderSize  - The actual size of the header before PHS
-	IN UINT *pNewHeaderSize - The new size of the header after applying PHS
-
-Return Value:
-
-    0 if successful,
-    >0 Error.
-
---*/
-ULONG PhsCompress(IN void* pvContext,
-				  IN B_UINT16 uiVcid,
-				  IN B_UINT16 uiClsId,
-				  IN void *pvInputBuffer,
-				  OUT void *pvOutputBuffer,
-				  OUT UINT *pOldHeaderSize,
-				  OUT UINT *pNewHeaderSize )
+/*
+ * PhsCompress
+ *
+ * Routine Description:
+ *    Exported function to compress the data using PHS.
+ *
+ * Arguments:
+ *	IN void* pvContext - PHS Driver Specific Context.
+ *	IN B_UINT16 uiVcid    - The Service Flow ID to which current packet header compression applies.
+ *	IN UINT  uiClsId   - The Classifier ID to which current packet header compression applies.
+ *	IN void *pvInputBuffer - The Input buffer containg packet header data
+ *	IN void *pvOutputBuffer - The output buffer returned by this function after PHS
+ *	IN UINT *pOldHeaderSize  - The actual size of the header before PHS
+ *	IN UINT *pNewHeaderSize - The new size of the header after applying PHS
+ *
+ * Return Value:
+ *
+ * 0 if successful,
+ * >0 Error.
+ */
+ULONG PhsCompress(IN void *pvContext,
+		IN B_UINT16 uiVcid,
+		IN B_UINT16 uiClsId,
+		IN void *pvInputBuffer,
+		OUT void *pvOutputBuffer,
+		OUT UINT *pOldHeaderSize,
+		OUT UINT *pNewHeaderSize)
 {
-	UINT nSFIndex =0, nClsidIndex =0  ;
+	UINT nSFIndex = 0, nClsidIndex = 0;
 	struct bcm_phs_entry *pstServiceFlowEntry = NULL;
 	struct bcm_phs_classifier_entry *pstClassifierEntry = NULL;
 	struct bcm_phs_rule *pstPhsRule = NULL;
-	ULONG lStatus =0;
+	ULONG lStatus = 0;
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
+	struct bcm_phs_extension *pDeviceExtension = (struct bcm_phs_extension *)pvContext;
 
-
-
-	struct bcm_phs_extension *pDeviceExtension= (struct bcm_phs_extension *)pvContext;
-
-
-	if(pDeviceExtension == NULL)
-	{
-		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"Invalid Device Extension\n");
-		lStatus =  STATUS_PHS_NOCOMPRESSION ;
+	if (pDeviceExtension == NULL) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "Invalid Device Extension\n");
+		lStatus = STATUS_PHS_NOCOMPRESSION;
 		return lStatus;
-
 	}
 
-	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"Suppressing header \n");
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "Suppressing header\n");
 
-
-	//Retrieve the SFID Entry Index for requested Service Flow
+	/* Retrieve the SFID Entry Index for requested Service Flow */
 	nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable,
-	                  uiVcid,&pstServiceFlowEntry);
-	if(nSFIndex == PHS_INVALID_TABLE_INDEX)
-	{
-		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"SFID Match Failed\n");
-		lStatus =  STATUS_PHS_NOCOMPRESSION ;
+				uiVcid, &pstServiceFlowEntry);
+	if (nSFIndex == PHS_INVALID_TABLE_INDEX) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "SFID Match Failed\n");
+		lStatus = STATUS_PHS_NOCOMPRESSION;
 		return lStatus;
 	}
 
 	nClsidIndex = GetClassifierEntry(pstServiceFlowEntry->pstClassifierTable,
-                uiClsId,eActiveClassifierRuleContext,&pstClassifierEntry);
+					uiClsId, eActiveClassifierRuleContext, &pstClassifierEntry);
 
-    if(nClsidIndex == PHS_INVALID_TABLE_INDEX)
-	{
-		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"No PHS Rule Defined For Classifier\n");
-		lStatus =  STATUS_PHS_NOCOMPRESSION ;
+	if (nClsidIndex == PHS_INVALID_TABLE_INDEX) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "No PHS Rule Defined For Classifier\n");
+		lStatus =  STATUS_PHS_NOCOMPRESSION;
 		return lStatus;
 	}
 
-
-	//get rule from SF id,Cls ID pair and proceed
-	pstPhsRule =  pstClassifierEntry->pstPhsRule;
-
-	if(!ValidatePHSRuleComplete(pstPhsRule))
-	{
-		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,"PHS Rule Defined For Classifier But Not Complete\n");
-		lStatus =  STATUS_PHS_NOCOMPRESSION ;
+	/* get rule from SF id,Cls ID pair and proceed */
+	pstPhsRule = pstClassifierEntry->pstPhsRule;
+	if (!ValidatePHSRuleComplete(pstPhsRule)) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "PHS Rule Defined For Classifier But Not Complete\n");
+		lStatus = STATUS_PHS_NOCOMPRESSION;
 		return lStatus;
 	}
 
-	//Compress Packet
-	lStatus = phs_compress(pstPhsRule,(PUCHAR)pvInputBuffer,
-	      (PUCHAR)pvOutputBuffer, pOldHeaderSize,pNewHeaderSize);
+	/* Compress Packet */
+	lStatus = phs_compress(pstPhsRule, (PUCHAR)pvInputBuffer,
+			(PUCHAR)pvOutputBuffer, pOldHeaderSize, pNewHeaderSize);
 
-	if(lStatus == STATUS_PHS_COMPRESSED)
-	{
+	if (lStatus == STATUS_PHS_COMPRESSED) {
 		pstPhsRule->PHSModifiedBytes += *pOldHeaderSize - *pNewHeaderSize - 1;
 		pstPhsRule->PHSModifiedNumPackets++;
-	}
-	else
+	} else
 		pstPhsRule->PHSErrorNumPackets++;
 
 	return lStatus;
 }
 
-/*++
-PhsDeCompress
-
-Routine Description:
-    Exported function to restore the packet header in Rx path.
-
-Arguments:
-	IN void* pvContext - PHS Driver Specific Context.
-	IN B_UINT16 uiVcid    - The Service Flow ID to which current packet header restoration applies.
-	IN  void *pvInputBuffer - The Input buffer containg suppressed packet header data
-	OUT void *pvOutputBuffer - The output buffer returned by this function after restoration
-	OUT UINT *pHeaderSize   - The packet header size after restoration is returned in this parameter.
-
-Return Value:
-
-    0 if successful,
-    >0 Error.
-
---*/
-ULONG PhsDeCompress(IN void* pvContext,
-				  IN B_UINT16 uiVcid,
-				  IN void *pvInputBuffer,
-				  OUT void *pvOutputBuffer,
-				  OUT UINT *pInHeaderSize,
-				  OUT UINT *pOutHeaderSize )
+/*
+ * PhsDeCompress
+ *
+ * Routine Description:
+ *    Exported function to restore the packet header in Rx path.
+ *
+ * Arguments:
+ *	IN void* pvContext - PHS Driver Specific Context.
+ *	IN B_UINT16 uiVcid    - The Service Flow ID to which current packet header restoration applies.
+ *	IN  void *pvInputBuffer - The Input buffer containg suppressed packet header data
+ *	OUT void *pvOutputBuffer - The output buffer returned by this function after restoration
+ *	OUT UINT *pHeaderSize   - The packet header size after restoration is returned in this parameter.
+ *
+ * Return Value:
+ *
+ * 0 if successful,
+ * >0 Error.
+ */
+ULONG PhsDeCompress(IN void *pvContext,
+		IN B_UINT16 uiVcid,
+		IN void *pvInputBuffer,
+		OUT void *pvOutputBuffer,
+		OUT UINT *pInHeaderSize,
+		OUT UINT *pOutHeaderSize)
 {
-	UINT nSFIndex =0, nPhsRuleIndex =0 ;
+	UINT nSFIndex = 0, nPhsRuleIndex = 0;
 	struct bcm_phs_entry *pstServiceFlowEntry = NULL;
 	struct bcm_phs_rule *pstPhsRule = NULL;
 	UINT phsi;
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
-	struct bcm_phs_extension *pDeviceExtension=
-        (struct bcm_phs_extension *)pvContext;
+	struct bcm_phs_extension *pDeviceExtension = (struct bcm_phs_extension *)pvContext;
 
 	*pInHeaderSize = 0;
-
-	if(pDeviceExtension == NULL)
-	{
-		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"Invalid Device Extension\n");
+	if (pDeviceExtension == NULL) {
+		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_RECEIVE,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_RECEIVE,DBG_LVL_ALL,"PHSI To Be Used For restore : %x\n",phsi);
-    if(phsi == UNCOMPRESSED_PACKET )
-	{
+	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;
-	}
 
-	//Retrieve the SFID Entry Index for requested Service Flow
+	/* Retrieve the SFID Entry Index for requested Service Flow */
 	nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable,
-	      uiVcid,&pstServiceFlowEntry);
-	if(nSFIndex == PHS_INVALID_TABLE_INDEX)
-	{
-		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"SFID Match Failed During Lookup\n");
+				uiVcid, &pstServiceFlowEntry);
+	if (nSFIndex == PHS_INVALID_TABLE_INDEX) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE, DBG_LVL_ALL, "SFID Match Failed During Lookup\n");
 		return ERR_SF_MATCH_FAIL;
 	}
 
-	nPhsRuleIndex = GetPhsRuleEntry(pstServiceFlowEntry->pstClassifierTable,phsi,
-          eActiveClassifierRuleContext,&pstPhsRule);
-	if(nPhsRuleIndex == PHS_INVALID_TABLE_INDEX)
-	{
-		//Phs Rule does not exist in  active rules table. Lets try in the old rules table.
+	nPhsRuleIndex = GetPhsRuleEntry(pstServiceFlowEntry->pstClassifierTable, phsi,
+					eActiveClassifierRuleContext, &pstPhsRule);
+	if (nPhsRuleIndex == PHS_INVALID_TABLE_INDEX) {
+		/* Phs Rule does not exist in  active rules table. Lets try in the old rules table. */
 		nPhsRuleIndex = GetPhsRuleEntry(pstServiceFlowEntry->pstClassifierTable,
-		      phsi,eOldClassifierRuleContext,&pstPhsRule);
-		if(nPhsRuleIndex == PHS_INVALID_TABLE_INDEX)
-		{
+						phsi, eOldClassifierRuleContext, &pstPhsRule);
+		if (nPhsRuleIndex == PHS_INVALID_TABLE_INDEX)
 			return ERR_PHSRULE_MATCH_FAIL;
-		}
-
 	}
 
 	*pInHeaderSize = phs_decompress((PUCHAR)pvInputBuffer,
-            (PUCHAR)pvOutputBuffer,pstPhsRule,pOutHeaderSize);
+					(PUCHAR)pvOutputBuffer, pstPhsRule, pOutHeaderSize);
 
 	pstPhsRule->PHSModifiedBytes += *pOutHeaderSize - *pInHeaderSize - 1;
 
@@ -831,112 +731,94 @@ ULONG PhsDeCompress(IN void* pvContext,
 	return STATUS_PHS_COMPRESSED;
 }
 
-
-//-----------------------------------------------------------------------------
-// Procedure:   free_phs_serviceflow_rules
-//
-// Description: This routine is responsible for freeing memory allocated for PHS rules.
-//
-// Arguments:
-// rules	- ptr to S_SERVICEFLOW_TABLE structure.
-//
-// Returns:
-// Does not return any value.
-//-----------------------------------------------------------------------------
-
+/*
+ * Procedure:   free_phs_serviceflow_rules
+ *
+ * Description: This routine is responsible for freeing memory allocated for PHS rules.
+ *
+ * Arguments:
+ * rules	- ptr to S_SERVICEFLOW_TABLE structure.
+ *
+ * Returns:
+ * Does not return any value.
+ */
 static void free_phs_serviceflow_rules(struct bcm_phs_table *psServiceFlowRulesTable)
 {
-	int i,j;
+	int i, j;
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
 
-	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "=======>\n");
-    if(psServiceFlowRulesTable)
-	{
-		for(i=0;i<MAX_SERVICEFLOWS;i++)
-		{
-			struct bcm_phs_entry stServiceFlowEntry =
-                psServiceFlowRulesTable->stSFList[i];
-			struct bcm_phs_classifier_table *pstClassifierRulesTable =
-                stServiceFlowEntry.pstClassifierTable;
-
-			if(pstClassifierRulesTable)
-			{
-				for(j=0;j<MAX_PHSRULE_PER_SF;j++)
-				{
-					if(pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule)
-					{
-						if(pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule
-                                                                                        ->u8RefCnt)
-							pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule
-  							                                                ->u8RefCnt--;
-						if(0==pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule
-                                                                ->u8RefCnt)
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "=======>\n");
+
+	if (psServiceFlowRulesTable) {
+		for (i = 0; i < MAX_SERVICEFLOWS; i++) {
+			struct bcm_phs_entry stServiceFlowEntry = psServiceFlowRulesTable->stSFList[i];
+			struct bcm_phs_classifier_table *pstClassifierRulesTable = stServiceFlowEntry.pstClassifierTable;
+
+			if (pstClassifierRulesTable) {
+				for (j = 0; j < MAX_PHSRULE_PER_SF; j++) {
+					if (pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule) {
+
+						if (pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule->u8RefCnt)
+							pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule->u8RefCnt--;
+
+						if (0 == pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule->u8RefCnt)
 							kfree(pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule);
+
 						pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule = NULL;
 					}
-					if(pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule)
-					{
-						if(pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule
-                                                                ->u8RefCnt)
-							pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule
-							                                          ->u8RefCnt--;
-						if(0==pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule
-                                                                      ->u8RefCnt)
+
+					if (pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule) {
+
+						if (pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule->u8RefCnt)
+							pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule->u8RefCnt--;
+
+						if (0 == pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule->u8RefCnt)
 							kfree(pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule);
+
 						pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule = NULL;
 					}
 				}
 				kfree(pstClassifierRulesTable);
-			    stServiceFlowEntry.pstClassifierTable = pstClassifierRulesTable = NULL;
+				stServiceFlowEntry.pstClassifierTable = pstClassifierRulesTable = NULL;
 			}
 		}
 	}
 
-    kfree(psServiceFlowRulesTable);
-    psServiceFlowRulesTable = NULL;
+	kfree(psServiceFlowRulesTable);
+	psServiceFlowRulesTable = NULL;
 }
 
-
-
 static BOOLEAN ValidatePHSRuleComplete(IN struct bcm_phs_rule *psPhsRule)
 {
-	if(psPhsRule)
-	{
-		if(!psPhsRule->u8PHSI)
-		{
-			// PHSI is not valid
+	if (psPhsRule) {
+		if (!psPhsRule->u8PHSI) {
+			/* PHSI is not valid */
 			return FALSE;
 		}
 
-		if(!psPhsRule->u8PHSS)
-		{
-			//PHSS Is Undefined
+		if (!psPhsRule->u8PHSS) {
+			/* PHSS Is Undefined */
 			return FALSE;
 		}
 
-		//Check if PHSF is defines for the PHS Rule
-		if(!psPhsRule->u8PHSFLength) // If any part of PHSF is valid then Rule contains valid PHSF
-		{
+		/* Check if PHSF is defines for the PHS Rule */
+		if (!psPhsRule->u8PHSFLength) /* If any part of PHSF is valid then Rule contains valid PHSF */
 			return FALSE;
-		}
+
 		return TRUE;
-	}
-	else
-	{
+	} else
 		return FALSE;
-	}
 }
 
 UINT GetServiceFlowEntry(IN struct bcm_phs_table *psServiceFlowTable,
-    IN B_UINT16 uiVcid, struct bcm_phs_entry **ppstServiceFlowEntry)
+			IN B_UINT16 uiVcid,
+			struct bcm_phs_entry **ppstServiceFlowEntry)
 {
-	int  i;
-	for(i=0;i<MAX_SERVICEFLOWS;i++)
-	{
-		if(psServiceFlowTable->stSFList[i].bUsed)
-		{
-			if(psServiceFlowTable->stSFList[i].uiVcid == uiVcid)
-			{
+	int i;
+
+	for (i = 0; i < MAX_SERVICEFLOWS; i++) {
+		if (psServiceFlowTable->stSFList[i].bUsed) {
+			if (psServiceFlowTable->stSFList[i].uiVcid == uiVcid) {
 				*ppstServiceFlowEntry = &psServiceFlowTable->stSFList[i];
 				return i;
 			}
@@ -947,34 +829,26 @@ UINT GetServiceFlowEntry(IN struct bcm_phs_table *psServiceFlowTable,
 	return PHS_INVALID_TABLE_INDEX;
 }
 
-
 UINT GetClassifierEntry(IN struct bcm_phs_classifier_table *pstClassifierTable,
-        IN B_UINT32 uiClsid, enum bcm_phs_classifier_context eClsContext,
-        OUT struct bcm_phs_classifier_entry **ppstClassifierEntry)
+			IN B_UINT32 uiClsid, enum bcm_phs_classifier_context eClsContext,
+			OUT struct bcm_phs_classifier_entry **ppstClassifierEntry)
 {
 	int  i;
 	struct bcm_phs_classifier_entry *psClassifierRules = NULL;
-	for(i=0;i<MAX_PHSRULE_PER_SF;i++)
-	{
 
-		if(eClsContext == eActiveClassifierRuleContext)
-		{
+	for (i = 0; i < MAX_PHSRULE_PER_SF; i++) {
+
+		if (eClsContext == eActiveClassifierRuleContext)
 			psClassifierRules = &pstClassifierTable->stActivePhsRulesList[i];
-		}
 		else
-		{
 			psClassifierRules = &pstClassifierTable->stOldPhsRulesList[i];
-		}
 
-		if(psClassifierRules->bUsed)
-		{
-			if(psClassifierRules->uiClassifierRuleId == uiClsid)
-			{
+		if (psClassifierRules->bUsed) {
+			if (psClassifierRules->uiClassifierRuleId == uiClsid) {
 				*ppstClassifierEntry = psClassifierRules;
 				return i;
 			}
 		}
-
 	}
 
 	*ppstClassifierEntry = NULL;
@@ -982,254 +856,227 @@ UINT GetClassifierEntry(IN struct bcm_phs_classifier_table *pstClassifierTable,
 }
 
 static UINT GetPhsRuleEntry(IN struct bcm_phs_classifier_table *pstClassifierTable,
-			    IN B_UINT32 uiPHSI, enum bcm_phs_classifier_context eClsContext,
-			    OUT struct bcm_phs_rule **ppstPhsRule)
+			IN B_UINT32 uiPHSI, enum bcm_phs_classifier_context eClsContext,
+			OUT struct bcm_phs_rule **ppstPhsRule)
 {
 	int  i;
 	struct bcm_phs_classifier_entry *pstClassifierRule = NULL;
-	for(i=0;i<MAX_PHSRULE_PER_SF;i++)
-	{
-		if(eClsContext == eActiveClassifierRuleContext)
-		{
+
+	for (i = 0; i < MAX_PHSRULE_PER_SF; i++) {
+		if (eClsContext == eActiveClassifierRuleContext)
 			pstClassifierRule = &pstClassifierTable->stActivePhsRulesList[i];
-		}
 		else
-		{
 			pstClassifierRule = &pstClassifierTable->stOldPhsRulesList[i];
-		}
-		if(pstClassifierRule->bUsed)
-		{
-			if(pstClassifierRule->u8PHSI == uiPHSI)
-			{
+
+		if (pstClassifierRule->bUsed) {
+			if (pstClassifierRule->u8PHSI == uiPHSI) {
 				*ppstPhsRule = pstClassifierRule->pstPhsRule;
 				return i;
 			}
 		}
-
 	}
 
 	*ppstPhsRule = NULL;
 	return PHS_INVALID_TABLE_INDEX;
 }
 
-UINT CreateSFToClassifierRuleMapping(IN B_UINT16 uiVcid,IN B_UINT16  uiClsId,
-                      IN struct bcm_phs_table *psServiceFlowTable, struct bcm_phs_rule *psPhsRule,
-                      B_UINT8 u8AssociatedPHSI)
+UINT CreateSFToClassifierRuleMapping(IN B_UINT16 uiVcid, IN B_UINT16  uiClsId,
+				IN struct bcm_phs_table *psServiceFlowTable,
+				struct bcm_phs_rule *psPhsRule,
+				B_UINT8 u8AssociatedPHSI)
 {
-
 	struct bcm_phs_classifier_table *psaClassifiertable = NULL;
 	UINT uiStatus = 0;
 	int iSfIndex;
-	BOOLEAN bFreeEntryFound =FALSE;
-	//Check for a free entry in SFID table
-	for(iSfIndex=0;iSfIndex < MAX_SERVICEFLOWS;iSfIndex++)
-	{
-		if(!psServiceFlowTable->stSFList[iSfIndex].bUsed)
-		{
+	BOOLEAN bFreeEntryFound = FALSE;
+
+	/* Check for a free entry in SFID table */
+	for (iSfIndex = 0; iSfIndex < MAX_SERVICEFLOWS; iSfIndex++) {
+		if (!psServiceFlowTable->stSFList[iSfIndex].bUsed) {
 			bFreeEntryFound = TRUE;
 			break;
 		}
 	}
 
-	if(!bFreeEntryFound)
+	if (!bFreeEntryFound)
 		return ERR_SFTABLE_FULL;
 
-
 	psaClassifiertable = psServiceFlowTable->stSFList[iSfIndex].pstClassifierTable;
-	uiStatus = CreateClassifierPHSRule(uiClsId,psaClassifiertable,psPhsRule,
-	                      eActiveClassifierRuleContext,u8AssociatedPHSI);
-	if(uiStatus == PHS_SUCCESS)
-	{
-		//Add entry at free index to the SF
+	uiStatus = CreateClassifierPHSRule(uiClsId, psaClassifiertable, psPhsRule,
+					eActiveClassifierRuleContext, u8AssociatedPHSI);
+	if (uiStatus == PHS_SUCCESS) {
+		/* Add entry at free index to the SF */
 		psServiceFlowTable->stSFList[iSfIndex].bUsed = TRUE;
 		psServiceFlowTable->stSFList[iSfIndex].uiVcid = uiVcid;
 	}
 
 	return uiStatus;
-
 }
 
 UINT CreateClassiferToPHSRuleMapping(IN B_UINT16 uiVcid,
-            IN B_UINT16  uiClsId,IN struct bcm_phs_entry *pstServiceFlowEntry,
-              struct bcm_phs_rule *psPhsRule, B_UINT8 u8AssociatedPHSI)
+				IN B_UINT16 uiClsId,
+				IN struct bcm_phs_entry *pstServiceFlowEntry,
+				struct bcm_phs_rule *psPhsRule,
+				B_UINT8 u8AssociatedPHSI)
 {
 	struct bcm_phs_classifier_entry *pstClassifierEntry = NULL;
-	UINT uiStatus =PHS_SUCCESS;
+	UINT uiStatus = PHS_SUCCESS;
 	UINT nClassifierIndex = 0;
 	struct bcm_phs_classifier_table *psaClassifiertable = NULL;
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
-    psaClassifiertable = pstServiceFlowEntry->pstClassifierTable;
 
-	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "==>");
+	psaClassifiertable = pstServiceFlowEntry->pstClassifierTable;
+
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "==>");
 
 	/* Check if the supplied Classifier already exists */
-	nClassifierIndex =GetClassifierEntry(
-	            pstServiceFlowEntry->pstClassifierTable,uiClsId,
-	            eActiveClassifierRuleContext,&pstClassifierEntry);
-	if(nClassifierIndex == PHS_INVALID_TABLE_INDEX)
-	{
+	nClassifierIndex = GetClassifierEntry(
+		pstServiceFlowEntry->pstClassifierTable,
+		uiClsId,
+		eActiveClassifierRuleContext,
+		&pstClassifierEntry);
+
+	if (nClassifierIndex == PHS_INVALID_TABLE_INDEX) {
 		/*
-		    The Classifier doesn't exist. So its a new classifier being added.
-		     Add new entry to associate PHS Rule to the Classifier
-		*/
+		 * The Classifier doesn't exist. So its a new classifier being added.
+		 * Add new entry to associate PHS Rule to the Classifier
+		 */
 
-		uiStatus = CreateClassifierPHSRule(uiClsId,psaClassifiertable,
-		    psPhsRule,eActiveClassifierRuleContext,u8AssociatedPHSI);
+		uiStatus = CreateClassifierPHSRule(uiClsId, psaClassifiertable,
+						psPhsRule,
+						eActiveClassifierRuleContext,
+						u8AssociatedPHSI);
 		return uiStatus;
 	}
 
 	/*
-	  The Classifier exists.The PHS Rule for this classifier
-	  is being modified
-	  */
-	if(pstClassifierEntry->u8PHSI == psPhsRule->u8PHSI)
-	{
-		if(pstClassifierEntry->pstPhsRule == NULL)
+	 * The Classifier exists.The PHS Rule for this classifier
+	 * is being modified
+	 */
+
+	if (pstClassifierEntry->u8PHSI == psPhsRule->u8PHSI) {
+		if (pstClassifierEntry->pstPhsRule == NULL)
 			return ERR_PHS_INVALID_PHS_RULE;
 
 		/*
-		    This rule already exists if any fields are changed for this PHS
-		    rule update them.
+		 * This rule already exists if any fields are changed for this PHS
+		 * rule update them.
 		 */
-		 /* If any part of PHSF is valid then we update PHSF */
-		if(psPhsRule->u8PHSFLength)
-		{
-			//update PHSF
+		/* If any part of PHSF is valid then we update PHSF */
+		if (psPhsRule->u8PHSFLength) {
+			/* update PHSF */
 			memcpy(pstClassifierEntry->pstPhsRule->u8PHSF,
-			    psPhsRule->u8PHSF , MAX_PHS_LENGTHS);
+				psPhsRule->u8PHSF, MAX_PHS_LENGTHS);
 		}
-		if(psPhsRule->u8PHSFLength)
-		{
-			//update PHSFLen
-			pstClassifierEntry->pstPhsRule->u8PHSFLength =
-			    psPhsRule->u8PHSFLength;
+
+		if (psPhsRule->u8PHSFLength) {
+			/* update PHSFLen */
+			pstClassifierEntry->pstPhsRule->u8PHSFLength = psPhsRule->u8PHSFLength;
 		}
-		if(psPhsRule->u8PHSMLength)
-		{
-			//update PHSM
+
+		if (psPhsRule->u8PHSMLength) {
+			/* update PHSM */
 			memcpy(pstClassifierEntry->pstPhsRule->u8PHSM,
-			    psPhsRule->u8PHSM, MAX_PHS_LENGTHS);
+				psPhsRule->u8PHSM, MAX_PHS_LENGTHS);
 		}
-		if(psPhsRule->u8PHSMLength)
-		{
-			//update PHSM Len
+
+		if (psPhsRule->u8PHSMLength) {
+			/* update PHSM Len */
 			pstClassifierEntry->pstPhsRule->u8PHSMLength =
-			    psPhsRule->u8PHSMLength;
+				psPhsRule->u8PHSMLength;
 		}
-		if(psPhsRule->u8PHSS)
-		{
-			//update PHSS
+
+		if (psPhsRule->u8PHSS) {
+			/* update PHSS */
 			pstClassifierEntry->pstPhsRule->u8PHSS = psPhsRule->u8PHSS;
 		}
 
-		//update PHSV
+		/* update PHSV */
 		pstClassifierEntry->pstPhsRule->u8PHSV = psPhsRule->u8PHSV;
-
+	} else {
+		/* A new rule is being set for this classifier. */
+		uiStatus = UpdateClassifierPHSRule(uiClsId, pstClassifierEntry,
+						psaClassifiertable, psPhsRule, u8AssociatedPHSI);
 	}
-	else
-	{
-		/*
-		  A new rule is being set for this classifier.
-		*/
-		uiStatus=UpdateClassifierPHSRule( uiClsId,  pstClassifierEntry,
-		      psaClassifiertable,  psPhsRule, u8AssociatedPHSI);
-	}
-
-
 
 	return uiStatus;
 }
 
 static UINT CreateClassifierPHSRule(IN B_UINT16  uiClsId,
-    struct bcm_phs_classifier_table *psaClassifiertable, struct bcm_phs_rule *psPhsRule,
-    enum bcm_phs_classifier_context eClsContext,B_UINT8 u8AssociatedPHSI)
+				struct bcm_phs_classifier_table *psaClassifiertable,
+				struct bcm_phs_rule *psPhsRule,
+				enum bcm_phs_classifier_context eClsContext,
+				B_UINT8 u8AssociatedPHSI)
 {
 	UINT iClassifierIndex = 0;
 	BOOLEAN bFreeEntryFound = FALSE;
 	struct bcm_phs_classifier_entry *psClassifierRules = NULL;
 	UINT nStatus = PHS_SUCCESS;
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
-	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,"Inside CreateClassifierPHSRule");
-    if(psaClassifiertable == NULL)
-	{
+
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "Inside CreateClassifierPHSRule");
+
+	if (psaClassifiertable == NULL)
 		return ERR_INVALID_CLASSIFIERTABLE_FOR_SF;
-	}
 
-	if(eClsContext == eOldClassifierRuleContext)
-	{
-		/* If An Old Entry for this classifier ID already exists in the
-		    old rules table replace it. */
+	if (eClsContext == eOldClassifierRuleContext) {
+		/*
+		 * If An Old Entry for this classifier ID already exists in the
+		 * old rules table replace it.
+		 */
 
 		iClassifierIndex =
-		GetClassifierEntry(psaClassifiertable, uiClsId,
-		            eClsContext,&psClassifierRules);
-		if(iClassifierIndex != PHS_INVALID_TABLE_INDEX)
-		{
+			GetClassifierEntry(psaClassifiertable, uiClsId,
+					eClsContext, &psClassifierRules);
+
+		if (iClassifierIndex != PHS_INVALID_TABLE_INDEX) {
 			/*
-			    The Classifier already exists in the old rules table
-		        Lets replace the old classifier with the new one.
-			*/
+			 * The Classifier already exists in the old rules table
+			 * Lets replace the old classifier with the new one.
+			 */
 			bFreeEntryFound = TRUE;
 		}
 	}
 
-	if(!bFreeEntryFound)
-	{
-		/*
-		  Continue to search for a free location to add the rule
-		*/
-		for(iClassifierIndex = 0; iClassifierIndex <
-            MAX_PHSRULE_PER_SF; iClassifierIndex++)
-		{
-			if(eClsContext == eActiveClassifierRuleContext)
-			{
-				psClassifierRules =
-              &psaClassifiertable->stActivePhsRulesList[iClassifierIndex];
-			}
+	if (!bFreeEntryFound) {
+		/* Continue to search for a free location to add the rule */
+		for (iClassifierIndex = 0; iClassifierIndex <
+			     MAX_PHSRULE_PER_SF; iClassifierIndex++) {
+			if (eClsContext == eActiveClassifierRuleContext)
+				psClassifierRules = &psaClassifiertable->stActivePhsRulesList[iClassifierIndex];
 			else
-			{
-				psClassifierRules =
-                &psaClassifiertable->stOldPhsRulesList[iClassifierIndex];
-			}
+				psClassifierRules = &psaClassifiertable->stOldPhsRulesList[iClassifierIndex];
 
-			if(!psClassifierRules->bUsed)
-			{
+			if (!psClassifierRules->bUsed) {
 				bFreeEntryFound = TRUE;
 				break;
 			}
 		}
 	}
 
-	if(!bFreeEntryFound)
-	{
-		if(eClsContext == eActiveClassifierRuleContext)
-		{
+	if (!bFreeEntryFound) {
+
+		if (eClsContext == eActiveClassifierRuleContext)
 			return ERR_CLSASSIFIER_TABLE_FULL;
-		}
-		else
-		{
-			//Lets replace the oldest rule if we are looking in old Rule table
-			if(psaClassifiertable->uiOldestPhsRuleIndex >=
-                MAX_PHSRULE_PER_SF)
-			{
-				psaClassifiertable->uiOldestPhsRuleIndex =0;
-			}
+		else {
+			/* Lets replace the oldest rule if we are looking in old Rule table */
+			if (psaClassifiertable->uiOldestPhsRuleIndex >= MAX_PHSRULE_PER_SF)
+				psaClassifiertable->uiOldestPhsRuleIndex = 0;
 
 			iClassifierIndex = psaClassifiertable->uiOldestPhsRuleIndex;
-			psClassifierRules =
-              &psaClassifiertable->stOldPhsRulesList[iClassifierIndex];
+			psClassifierRules = &psaClassifiertable->stOldPhsRulesList[iClassifierIndex];
 
-          (psaClassifiertable->uiOldestPhsRuleIndex)++;
+			(psaClassifiertable->uiOldestPhsRuleIndex)++;
 		}
 	}
 
-	if(eClsContext == eOldClassifierRuleContext)
-	{
-		if(psClassifierRules->pstPhsRule == NULL)
-		{
-			psClassifierRules->pstPhsRule = kmalloc(sizeof(struct bcm_phs_rule),GFP_KERNEL);
+	if (eClsContext == eOldClassifierRuleContext) {
+
+		if (psClassifierRules->pstPhsRule == NULL) {
 
-          if(NULL == psClassifierRules->pstPhsRule)
+			psClassifierRules->pstPhsRule = kmalloc(sizeof(struct bcm_phs_rule), GFP_KERNEL);
+
+			if (NULL == psClassifierRules->pstPhsRule)
 				return ERR_PHSRULE_MEMALLOC_FAIL;
 		}
 
@@ -1238,70 +1085,62 @@ static UINT CreateClassifierPHSRule(IN B_UINT16  uiClsId,
 		psClassifierRules->u8PHSI = psPhsRule->u8PHSI;
 		psClassifierRules->bUnclassifiedPHSRule = psPhsRule->bUnclassifiedPHSRule;
 
-        /* Update The PHS rule */
-		memcpy(psClassifierRules->pstPhsRule,
-		    psPhsRule, sizeof(struct bcm_phs_rule));
-	}
-	else
-	{
-		nStatus = UpdateClassifierPHSRule(uiClsId,psClassifierRules,
-            psaClassifiertable,psPhsRule,u8AssociatedPHSI);
-	}
+		/* Update The PHS rule */
+		memcpy(psClassifierRules->pstPhsRule, psPhsRule, sizeof(struct bcm_phs_rule));
+	} else
+		nStatus = UpdateClassifierPHSRule(uiClsId, psClassifierRules,
+						psaClassifiertable, psPhsRule, u8AssociatedPHSI);
+
 	return nStatus;
 }
 
-
 static UINT UpdateClassifierPHSRule(IN B_UINT16  uiClsId,
-      IN struct bcm_phs_classifier_entry *pstClassifierEntry,
-      struct bcm_phs_classifier_table *psaClassifiertable, struct bcm_phs_rule *psPhsRule,
-      B_UINT8 u8AssociatedPHSI)
+				IN struct bcm_phs_classifier_entry *pstClassifierEntry,
+				struct bcm_phs_classifier_table *psaClassifiertable,
+				struct bcm_phs_rule *psPhsRule,
+				B_UINT8 u8AssociatedPHSI)
 {
 	struct bcm_phs_rule *pstAddPhsRule = NULL;
-	UINT              nPhsRuleIndex = 0;
-	BOOLEAN       bPHSRuleOrphaned = FALSE;
+	UINT nPhsRuleIndex = 0;
+	BOOLEAN bPHSRuleOrphaned = FALSE;
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
-	psPhsRule->u8RefCnt =0;
-
-	/* Step 1 Deref Any Exisiting PHS Rule in this classifier Entry*/
-	bPHSRuleOrphaned = DerefPhsRule( uiClsId, psaClassifiertable,
-	    pstClassifierEntry->pstPhsRule);
-
-	//Step 2 Search if there is a PHS Rule with u8AssociatedPHSI in Classifier table for this SF
-	nPhsRuleIndex =GetPhsRuleEntry(psaClassifiertable,u8AssociatedPHSI,
-	    eActiveClassifierRuleContext, &pstAddPhsRule);
-	if(PHS_INVALID_TABLE_INDEX == nPhsRuleIndex)
-	{
-		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAdding New PHSRuleEntry For Classifier");
-
-		if(psPhsRule->u8PHSI == 0)
-		{
-			BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nError PHSI is Zero\n");
+
+	psPhsRule->u8RefCnt = 0;
+
+	/* Step 1 Deref Any Exisiting PHS Rule in this classifier Entry */
+	bPHSRuleOrphaned = DerefPhsRule(uiClsId, psaClassifiertable,
+					pstClassifierEntry->pstPhsRule);
+
+	/* Step 2 Search if there is a PHS Rule with u8AssociatedPHSI in Classifier table for this SF */
+	nPhsRuleIndex = GetPhsRuleEntry(psaClassifiertable, u8AssociatedPHSI,
+					eActiveClassifierRuleContext, &pstAddPhsRule);
+	if (PHS_INVALID_TABLE_INDEX == nPhsRuleIndex) {
+
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAdding New PHSRuleEntry For Classifier");
+
+		if (psPhsRule->u8PHSI == 0) {
+			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nError PHSI is Zero\n");
 			return ERR_PHS_INVALID_PHS_RULE;
 		}
-		//Step 2.a PHS Rule Does Not Exist .Create New PHS Rule for uiClsId
-		if(FALSE == bPHSRuleOrphaned)
-		{
+
+		/* Step 2.a PHS Rule Does Not Exist .Create New PHS Rule for uiClsId */
+		if (FALSE == bPHSRuleOrphaned) {
+
 			pstClassifierEntry->pstPhsRule = kmalloc(sizeof(struct bcm_phs_rule), GFP_KERNEL);
-			if(NULL == pstClassifierEntry->pstPhsRule)
-			{
+			if (NULL == pstClassifierEntry->pstPhsRule)
 				return ERR_PHSRULE_MEMALLOC_FAIL;
-			}
 		}
 		memcpy(pstClassifierEntry->pstPhsRule, psPhsRule, sizeof(struct bcm_phs_rule));
-
-	}
-	else
-	{
-		//Step 2.b PHS Rule  Exists Tie uiClsId with the existing PHS Rule
-		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nTying Classifier to Existing PHS Rule");
-		if(bPHSRuleOrphaned)
-		{
+	} else {
+		/* Step 2.b PHS Rule  Exists Tie uiClsId with the existing PHS Rule */
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nTying Classifier to Existing PHS Rule");
+		if (bPHSRuleOrphaned) {
 			kfree(pstClassifierEntry->pstPhsRule);
 			pstClassifierEntry->pstPhsRule = NULL;
 		}
 		pstClassifierEntry->pstPhsRule = pstAddPhsRule;
-
 	}
+
 	pstClassifierEntry->bUsed = TRUE;
 	pstClassifierEntry->u8PHSI = pstClassifierEntry->pstPhsRule->u8PHSI;
 	pstClassifierEntry->uiClassifierRuleId = uiClsId;
@@ -1309,79 +1148,74 @@ static UINT UpdateClassifierPHSRule(IN B_UINT16  uiClsId,
 	pstClassifierEntry->bUnclassifiedPHSRule = pstClassifierEntry->pstPhsRule->bUnclassifiedPHSRule;
 
 	return PHS_SUCCESS;
-
 }
 
 static BOOLEAN DerefPhsRule(IN B_UINT16  uiClsId, struct bcm_phs_classifier_table *psaClassifiertable, struct bcm_phs_rule *pstPhsRule)
 {
-	if(pstPhsRule==NULL)
+	if (pstPhsRule == NULL)
 		return FALSE;
-	if(pstPhsRule->u8RefCnt)
+
+	if (pstPhsRule->u8RefCnt)
 		pstPhsRule->u8RefCnt--;
-	if(0==pstPhsRule->u8RefCnt)
-	{
-		/*if(pstPhsRule->u8PHSI)
-		//Store the currently active rule into the old rules list
-		CreateClassifierPHSRule(uiClsId,psaClassifiertable,pstPhsRule,eOldClassifierRuleContext,pstPhsRule->u8PHSI);*/
+
+	if (0 == pstPhsRule->u8RefCnt) {
+		/*
+		 * if(pstPhsRule->u8PHSI)
+		 * Store the currently active rule into the old rules list
+		 * CreateClassifierPHSRule(uiClsId,psaClassifiertable,pstPhsRule,eOldClassifierRuleContext,pstPhsRule->u8PHSI);
+		 */
 		return TRUE;
-	}
-	else
-	{
+	} else
 		return FALSE;
-	}
 }
 
 void DumpPhsRules(struct bcm_phs_extension *pDeviceExtension)
 {
-	int i,j,k,l;
+	int i, j, k, l;
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
-    BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\n Dumping PHS Rules : \n");
-	for(i=0;i<MAX_SERVICEFLOWS;i++)
-	{
+
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\n Dumping PHS Rules :\n");
+
+	for (i = 0; i < MAX_SERVICEFLOWS; i++) {
+
 		struct bcm_phs_entry stServFlowEntry =
-				pDeviceExtension->pstServiceFlowPhsRulesTable->stSFList[i];
-		if(stServFlowEntry.bUsed)
-		{
-			for(j=0;j<MAX_PHSRULE_PER_SF;j++)
-			{
-				for(l=0;l<2;l++)
-				{
+			pDeviceExtension->pstServiceFlowPhsRulesTable->stSFList[i];
+		if (stServFlowEntry.bUsed) {
+
+			for (j = 0; j < MAX_PHSRULE_PER_SF; j++) {
+
+				for (l = 0; l < 2; l++) {
 					struct bcm_phs_classifier_entry stClsEntry;
-					if(l==0)
-					{
+
+					if (l == 0) {
 						stClsEntry = stServFlowEntry.pstClassifierTable->stActivePhsRulesList[j];
-						if(stClsEntry.bUsed)
-							BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n Active PHS Rule : \n");
-					}
-					else
-					{
+						if (stClsEntry.bUsed)
+							BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n Active PHS Rule :\n");
+					} else {
 						stClsEntry = stServFlowEntry.pstClassifierTable->stOldPhsRulesList[j];
-						if(stClsEntry.bUsed)
-							BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n Old PHS Rule : \n");
+						if (stClsEntry.bUsed)
+							BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n Old PHS Rule :\n");
 					}
-					if(stClsEntry.bUsed)
-					{
-
-						BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\n VCID  : %#X",stServFlowEntry.uiVcid);
-						BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n ClassifierID  : %#X",stClsEntry.uiClassifierRuleId);
-						BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSRuleID  : %#X",stClsEntry.u8PHSI);
-						BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n****************PHS Rule********************\n");
-						BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSI  : %#X",stClsEntry.pstPhsRule->u8PHSI);
-						BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSFLength : %#X ",stClsEntry.pstPhsRule->u8PHSFLength);
-						BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSF : ");
-						for(k=0;k<stClsEntry.pstPhsRule->u8PHSFLength;k++)
-						{
-							BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "%#X  ",stClsEntry.pstPhsRule->u8PHSF[k]);
-						}
-						BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSMLength  : %#X",stClsEntry.pstPhsRule->u8PHSMLength);
-						BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSM :");
-						for(k=0;k<stClsEntry.pstPhsRule->u8PHSMLength;k++)
-						{
-							BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "%#X  ",stClsEntry.pstPhsRule->u8PHSM[k]);
-						}
-						BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSS : %#X ",stClsEntry.pstPhsRule->u8PHSS);
-						BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSV  : %#X",stClsEntry.pstPhsRule->u8PHSV);
-						BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\n********************************************\n");
+
+					if (stClsEntry.bUsed) {
+						BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\n VCID  : %#X", stServFlowEntry.uiVcid);
+						BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n ClassifierID  : %#X", stClsEntry.uiClassifierRuleId);
+						BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSRuleID  : %#X", stClsEntry.u8PHSI);
+						BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n****************PHS Rule********************\n");
+						BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSI  : %#X", stClsEntry.pstPhsRule->u8PHSI);
+						BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSFLength : %#X ", stClsEntry.pstPhsRule->u8PHSFLength);
+						BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSF : ");
+
+						for (k = 0 ; k < stClsEntry.pstPhsRule->u8PHSFLength; k++)
+							BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "%#X  ", stClsEntry.pstPhsRule->u8PHSF[k]);
+						BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSMLength  : %#X", stClsEntry.pstPhsRule->u8PHSMLength);
+						BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSM :");
+
+						for (k = 0; k < stClsEntry.pstPhsRule->u8PHSMLength; k++)
+							BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "%#X  ", stClsEntry.pstPhsRule->u8PHSM[k]);
+						BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSS : %#X ", stClsEntry.pstPhsRule->u8PHSS);
+						BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSV  : %#X", stClsEntry.pstPhsRule->u8PHSV);
+						BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\n********************************************\n");
 					}
 				}
 			}
@@ -1389,66 +1223,69 @@ void DumpPhsRules(struct bcm_phs_extension *pDeviceExtension)
 	}
 }
 
-
-//-----------------------------------------------------------------------------
-// Procedure:   phs_decompress
-//
-// Description: This routine restores the static fields within the packet.
-//
-// Arguments:
-//	in_buf			- ptr to incoming packet buffer.
-//	out_buf			- ptr to output buffer where the suppressed header is copied.
-//	decomp_phs_rules - ptr to PHS rule.
-//	header_size		- ptr to field which holds the phss or phsf_length.
-//
-// Returns:
-//	size -The number of bytes of dynamic fields present with in the incoming packet
-//			header.
-//	0	-If PHS rule is NULL.If PHSI is 0 indicateing packet as uncompressed.
-//-----------------------------------------------------------------------------
-
-int phs_decompress(unsigned char *in_buf,unsigned char *out_buf,
-		struct bcm_phs_rule *decomp_phs_rules, UINT *header_size)
+/*
+ * Procedure:   phs_decompress
+ *
+ * Description: This routine restores the static fields within the packet.
+ *
+ * Arguments:
+ *	in_buf			- ptr to incoming packet buffer.
+ *	out_buf			- ptr to output buffer where the suppressed header is copied.
+ *	decomp_phs_rules - ptr to PHS rule.
+ *	header_size		- ptr to field which holds the phss or phsf_length.
+ *
+ * Returns:
+ *	size -The number of bytes of dynamic fields present with in the incoming packet
+ *			header.
+ *	0	-If PHS rule is NULL.If PHSI is 0 indicateing packet as uncompressed.
+ */
+int phs_decompress(unsigned char *in_buf,
+		unsigned char *out_buf,
+		struct bcm_phs_rule *decomp_phs_rules,
+		UINT *header_size)
 {
-	int phss,size=0;
+	int phss, size = 0;
 	struct bcm_phs_rule *tmp_memb;
-	int bit,i=0;
-	unsigned char *phsf,*phsm;
-	int in_buf_len = *header_size-1;
+	int bit, i = 0;
+	unsigned char *phsf, *phsm;
+	int in_buf_len = *header_size - 1;
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
+
 	in_buf++;
-    BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,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 ))
+	if ((decomp_phs_rules == NULL))
 		return 0;
 
-
 	tmp_memb = decomp_phs_rules;
-	//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;
-	phsm         = tmp_memb->u8PHSM;
-
-	if(phss > MAX_PHS_LENGTHS)
+	/*
+	 * 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;
+	phsm = tmp_memb->u8PHSM;
+
+	if (phss > MAX_PHS_LENGTHS)
 		phss = MAX_PHS_LENGTHS;
-	//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);
 
-		if(bit == SUPPRESS)
-		{
+	/*
+	 * 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);
+
+		if (bit == SUPPRESS) {
 			*out_buf = *phsf;
-			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
-		{
+			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_RECEIVE,DBG_LVL_ALL,"\nDECOMP:In phss  %d input %d ouput %d",
-            phss,*in_buf,*out_buf);
+			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++;
 		}
@@ -1456,156 +1293,159 @@ int phs_decompress(unsigned char *in_buf,unsigned char *out_buf,
 		phsf++;
 		phss--;
 		i++;
-		*header_size=*header_size + 1;
+		*header_size = *header_size + 1;
 
-		if(i > MAX_NO_BIT)
-		{
-			i=0;
+		if (i > MAX_NO_BIT) {
+			i = 0;
 			phsm++;
 		}
 	}
+
 	return size;
 }
 
-
-
-
-//-----------------------------------------------------------------------------
-// Procedure:   phs_compress
-//
-// Description: This routine suppresses the static fields within the packet.Before
-// that it will verify the fields to be suppressed with the corresponding fields in the
-// phsf. For verification it checks the phsv field of PHS rule. If set and verification
-// succeeds it suppresses the field.If any one static field is found different none of
-// the static fields are suppressed then the packet is sent as uncompressed packet with
-// phsi=0.
-//
-// Arguments:
-//	phs_rule - ptr to PHS rule.
-//	in_buf		- ptr to incoming packet buffer.
-//	out_buf		- ptr to output buffer where the suppressed header is copied.
-//	header_size	- ptr to field which holds the phss.
-//
-// Returns:
-//	size-The number of bytes copied into the output buffer i.e dynamic fields
-//	0	-If PHS rule is NULL.If PHSV field is not set.If the verification fails.
-//-----------------------------------------------------------------------------
-static int phs_compress(struct bcm_phs_rule *phs_rule, unsigned char *in_buf
-			,unsigned char *out_buf,UINT *header_size,UINT *new_header_size)
+/*
+ * Procedure:   phs_compress
+ *
+ * Description: This routine suppresses the static fields within the packet.Before
+ * that it will verify the fields to be suppressed with the corresponding fields in the
+ * phsf. For verification it checks the phsv field of PHS rule. If set and verification
+ * succeeds it suppresses the field.If any one static field is found different none of
+ * the static fields are suppressed then the packet is sent as uncompressed packet with
+ * phsi=0.
+ *
+ * Arguments:
+ *	phs_rule - ptr to PHS rule.
+ *	in_buf		- ptr to incoming packet buffer.
+ *	out_buf		- ptr to output buffer where the suppressed header is copied.
+ *	header_size	- ptr to field which holds the phss.
+ *
+ * Returns:
+ *	size-The number of bytes copied into the output buffer i.e dynamic fields
+ *	0	-If PHS rule is NULL.If PHSV field is not set.If the verification fails.
+ */
+static int phs_compress(struct bcm_phs_rule *phs_rule,
+			unsigned char *in_buf,
+			unsigned char *out_buf,
+			UINT *header_size,
+			UINT *new_header_size)
 {
 	unsigned char *old_addr = out_buf;
 	int suppress = 0;
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
-    if(phs_rule == NULL)
-	{
-		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nphs_compress(): phs_rule null!");
+
+	if (phs_rule == NULL) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "\nphs_compress(): phs_rule null!");
 		*out_buf = ZERO_PHSI;
 		return STATUS_PHS_NOCOMPRESSION;
 	}
 
-
-	if(phs_rule->u8PHSS <= *new_header_size)
-	{
+	if (phs_rule->u8PHSS <= *new_header_size)
 		*header_size = phs_rule->u8PHSS;
-	}
 	else
-	{
 		*header_size = *new_header_size;
-	}
-	//To copy PHSI
+
+	/* To copy PHSI */
 	out_buf++;
-	suppress = verify_suppress_phsf(in_buf,out_buf,phs_rule->u8PHSF,
-        phs_rule->u8PHSM, phs_rule->u8PHSS, phs_rule->u8PHSV,new_header_size);
+	suppress = verify_suppress_phsf(in_buf, out_buf, phs_rule->u8PHSF,
+					phs_rule->u8PHSM, phs_rule->u8PHSS,
+					phs_rule->u8PHSV, new_header_size);
 
-	if(suppress == STATUS_PHS_COMPRESSED)
-	{
+	if (suppress == STATUS_PHS_COMPRESSED) {
 		*old_addr = (unsigned char)phs_rule->u8PHSI;
-		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nCOMP:In phs_compress phsi %d",phs_rule->u8PHSI);
-	}
-	else
-	{
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "\nCOMP:In phs_compress phsi %d", phs_rule->u8PHSI);
+	} else {
 		*old_addr = ZERO_PHSI;
-		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nCOMP:In phs_compress PHSV Verification failed");
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "\nCOMP:In phs_compress PHSV Verification failed");
 	}
+
 	return suppress;
 }
 
-
-//-----------------------------------------------------------------------------
-// Procedure:	verify_suppress_phsf
-//
-// Description: This routine verifies the fields of the packet and if all the
-// static fields are equal it adds the phsi of that PHS rule.If any static
-// field differs it woun't suppress any field.
-//
-// Arguments:
-// rules_set	- ptr to classifier_rules.
-// in_buffer	- ptr to incoming packet buffer.
-// out_buffer	- ptr to output buffer where the suppressed header is copied.
-// phsf			- ptr to phsf.
-// phsm			- ptr to phsm.
-// phss			- variable holding phss.
-//
-// Returns:
-//	size-The number of bytes copied into the output buffer i.e dynamic fields.
-//	0	-Packet has failed the verification.
-//-----------------------------------------------------------------------------
-
-static int verify_suppress_phsf(unsigned char *in_buffer,unsigned char *out_buffer,
-				unsigned char *phsf,unsigned char *phsm,unsigned int phss,
-				unsigned int phsv,UINT* new_header_size)
+/*
+ * Procedure:	verify_suppress_phsf
+ *
+ * Description: This routine verifies the fields of the packet and if all the
+ * static fields are equal it adds the phsi of that PHS rule.If any static
+ * field differs it woun't suppress any field.
+ *
+ * Arguments:
+ * rules_set	- ptr to classifier_rules.
+ * in_buffer	- ptr to incoming packet buffer.
+ * out_buffer	- ptr to output buffer where the suppressed header is copied.
+ * phsf			- ptr to phsf.
+ * phsm			- ptr to phsm.
+ * phss			- variable holding phss.
+ *
+ * Returns:
+ *	size-The number of bytes copied into the output buffer i.e dynamic fields.
+ *	0	-Packet has failed the verification.
+ */
+static int verify_suppress_phsf(unsigned char *in_buffer,
+				unsigned char *out_buffer,
+				unsigned char *phsf,
+				unsigned char *phsm,
+				unsigned int phss,
+				unsigned int phsv,
+				UINT *new_header_size)
 {
-	unsigned int size=0;
-	int bit,i=0;
+	unsigned int size = 0;
+	int bit, i = 0;
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
-    BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nCOMP:In verify_phsf PHSM - 0x%X",*phsm);
 
-
-	if(phss>(*new_header_size))
-	{
-		phss=*new_header_size;
-	}
-	while(phss > 0)
-	{
-		bit = ((*phsm << i)& SUPPRESS);
-		if(bit == SUPPRESS)
-		{
-
-			if(*in_buffer != *phsf)
-			{
-				if(phsv == VERIFY)
-				{
-					BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nCOMP:In verify_phsf failed for field  %d buf  %d phsf %d",phss,*in_buffer,*phsf);
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "\nCOMP:In verify_phsf PHSM - 0x%X", *phsm);
+
+	if (phss > (*new_header_size))
+		phss = *new_header_size;
+
+	while (phss > 0) {
+		bit = ((*phsm << i) & SUPPRESS);
+		if (bit == SUPPRESS) {
+			if (*in_buffer != *phsf) {
+				if (phsv == VERIFY) {
+					BCM_DEBUG_PRINT(Adapter,
+							DBG_TYPE_OTHERS,
+							PHS_SEND,
+							DBG_LVL_ALL,
+							"\nCOMP:In verify_phsf failed for field  %d buf  %d phsf %d",
+							phss,
+							*in_buffer,
+							*phsf);
 					return STATUS_PHS_NOCOMPRESSION;
 				}
-			}
-			else
-				BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nCOMP:In verify_phsf success for field  %d buf  %d phsf %d",phss,*in_buffer,*phsf);
-		}
-		else
-		{
+			} else
+				BCM_DEBUG_PRINT(Adapter,
+						DBG_TYPE_OTHERS,
+						PHS_SEND,
+						DBG_LVL_ALL,
+						"\nCOMP:In verify_phsf success for field  %d buf  %d phsf %d",
+						phss,
+						*in_buffer,
+						*phsf);
+		} else {
 			*out_buffer = *in_buffer;
-			BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nCOMP:In copying_header input %d  out %d",*in_buffer,*out_buffer);
+			BCM_DEBUG_PRINT(Adapter,
+					DBG_TYPE_OTHERS,
+					PHS_SEND,
+					DBG_LVL_ALL,
+					"\nCOMP:In copying_header input %d  out %d",
+					*in_buffer,
+					*out_buffer);
 			out_buffer++;
 			size++;
 		}
+
 		in_buffer++;
 		phsf++;
 		phss--;
 		i++;
-		if(i > MAX_NO_BIT)
-		{
-			i=0;
+
+		if (i > MAX_NO_BIT) {
+			i = 0;
 			phsm++;
 		}
 	}
-	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nCOMP:In verify_phsf success");
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "\nCOMP:In verify_phsf success");
 	*new_header_size = size;
 	return STATUS_PHS_COMPRESSED;
 }
-
-
-
-
-
-
diff --git a/drivers/staging/bcm/nvm.c b/drivers/staging/bcm/nvm.c
index e6152f4..bea1330 100644
--- a/drivers/staging/bcm/nvm.c
+++ b/drivers/staging/bcm/nvm.c
@@ -2228,20 +2228,20 @@ int BcmAllocFlashCSStructure(struct bcm_mini_adapter *psAdapter)
 		BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_PRINTK, 0, 0, "Adapter structure point is NULL");
 		return -EINVAL;
 	}
-	psAdapter->psFlashCSInfo = (struct bcm_flash_cs_info *)kzalloc(sizeof(struct bcm_flash_cs_info), GFP_KERNEL);
+	psAdapter->psFlashCSInfo = kzalloc(sizeof(struct bcm_flash_cs_info), GFP_KERNEL);
 	if (psAdapter->psFlashCSInfo == NULL) {
 		BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_PRINTK, 0, 0, "Can't Allocate memory for Flash 1.x");
 		return -ENOMEM;
 	}
 
-	psAdapter->psFlash2xCSInfo = (struct bcm_flash2x_cs_info *)kzalloc(sizeof(struct bcm_flash2x_cs_info), GFP_KERNEL);
+	psAdapter->psFlash2xCSInfo = kzalloc(sizeof(struct bcm_flash2x_cs_info), GFP_KERNEL);
 	if (!psAdapter->psFlash2xCSInfo) {
 		BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_PRINTK, 0, 0, "Can't Allocate memory for Flash 2.x");
 		kfree(psAdapter->psFlashCSInfo);
 		return -ENOMEM;
 	}
 
-	psAdapter->psFlash2xVendorInfo = (struct bcm_flash2x_vendor_info *)kzalloc(sizeof(struct bcm_flash2x_vendor_info), GFP_KERNEL);
+	psAdapter->psFlash2xVendorInfo = kzalloc(sizeof(struct bcm_flash2x_vendor_info), GFP_KERNEL);
 	if (!psAdapter->psFlash2xVendorInfo) {
 		BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_PRINTK, 0, 0, "Can't Allocate Vendor Info Memory for Flash 2.x");
 		kfree(psAdapter->psFlashCSInfo);
@@ -4074,7 +4074,7 @@ int BcmCopySection(struct bcm_mini_adapter *Adapter,
 	else
 		BuffSize = numOfBytes;
 
-	pBuff = (PCHAR)kzalloc(BuffSize, GFP_KERNEL);
+	pBuff = kzalloc(BuffSize, GFP_KERNEL);
 	if (!pBuff) {
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Memory allocation failed.. ");
 		return -ENOMEM;
@@ -4154,7 +4154,7 @@ int SaveHeaderIfPresent(struct bcm_mini_adapter *Adapter, PUCHAR pBuff, unsigned
 	}
 	/* If Header is present overwrite passed buffer with this */
 	if (bHasHeader && (Adapter->bHeaderChangeAllowed == FALSE)) {
-		pTempBuff = (PUCHAR)kzalloc(HeaderSizeToProtect, GFP_KERNEL);
+		pTempBuff = kzalloc(HeaderSizeToProtect, GFP_KERNEL);
 		if (!pTempBuff) {
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Memory allocation failed");
 			return -ENOMEM;
@@ -4563,7 +4563,7 @@ static int CorruptDSDSig(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_sect
 		}
 	}
 
-	pBuff = (PUCHAR)kzalloc(MAX_RW_SIZE, GFP_KERNEL);
+	pBuff = kzalloc(MAX_RW_SIZE, GFP_KERNEL);
 	if (!pBuff) {
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Can't allocate memorey");
 		return -ENOMEM;
@@ -4622,7 +4622,7 @@ static int CorruptISOSig(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_sect
 		return SECTOR_IS_NOT_WRITABLE;
 	}
 
-	pBuff = (PUCHAR)kzalloc(MAX_RW_SIZE, GFP_KERNEL);
+	pBuff = kzalloc(MAX_RW_SIZE, GFP_KERNEL);
 	if (!pBuff) {
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Can't allocate memorey");
 		return -ENOMEM;
diff --git a/drivers/staging/ccg/Kconfig b/drivers/staging/ccg/Kconfig
deleted file mode 100644
index 7ed5bc6..0000000
--- a/drivers/staging/ccg/Kconfig
+++ /dev/null
@@ -1,25 +0,0 @@
-if USB_GADGET
-
-config USB_G_CCG
-	tristate "Configurable Composite Gadget (STAGING)"
-	depends on STAGING && BLOCK && NET && !USB_ZERO && !USB_ZERO_HNPTEST && !USB_AUDIO && !GADGET_UAC1 && !USB_ETH && !USB_ETH_RNDIS && !USB_ETH_EEM && !USB_G_NCM && !USB_GADGETFS && !USB_FUNCTIONFS && !USB_FUNCTIONFS_ETH && !USB_FUNCTIONFS_RNDIS && !USB_FUNCTIONFS_GENERIC && !USB_FILE_STORAGE && !USB_FILE_STORAGE_TEST && !USB_MASS_STORAGE && !USB_G_SERIAL && !USB_MIDI_GADGET && !USB_G_PRINTER && !USB_CDC_COMPOSITE && !USB_G_NOKIA && !USB_G_ACM_MS && !USB_G_MULTI && !USB_G_MULTI_RNDIS && !USB_G_MULTI_CDC && !USB_G_HID && !USB_G_DBGP && !USB_G_WEBCAM && TTY
-	help
-	  The Configurable Composite Gadget supports multiple USB
-	  functions: acm, mass storage, rndis and FunctionFS.
-	  Each function can be configured and enabled/disabled
-	  dynamically from userspace through a sysfs interface.
-
-	  In order to compile this (either as a module or built-in),
-	  "USB Gadget Drivers" and anything under it must not be
-	  selected compiled-in in
-	  Device Drivers->USB Support->USB Gadget Support.
-	  However, you can say "M" there, if you do, the
-	  Configurable Composite Gadget can be compiled "M" only
-	  or not at all.
-
-	  BIG FAT NOTE: DON'T RELY ON THIS USERINTERFACE HERE! AS PART
-	  OF THE REWORK DONE HERE WILL BE A NEW USER INTERFACE WITHOUT ANY
-	  COMPATIBILITY TO THIS SYSFS INTERFACE HERE. BE AWARE OF THIS
-	  BEFORE SELECTING THIS.
-
-endif # USB_GADGET
diff --git a/drivers/staging/ccg/Makefile b/drivers/staging/ccg/Makefile
deleted file mode 100644
index 814fa9d..0000000
--- a/drivers/staging/ccg/Makefile
+++ /dev/null
@@ -1,2 +0,0 @@
-g_ccg-y				:= ccg.o
-obj-$(CONFIG_USB_G_CCG)		+= g_ccg.o
diff --git a/drivers/staging/ccg/TODO b/drivers/staging/ccg/TODO
deleted file mode 100644
index 18612fe..0000000
--- a/drivers/staging/ccg/TODO
+++ /dev/null
@@ -1,6 +0,0 @@
-TODO:
-	- change configuration interface from sysfs to configfs
-
-Please send patches to Greg Kroah-Hartmann <gregkh@linuxfoundation.org>,
-Andrzej Pietrasiewicz <andrzej.p@samsung.com>, and
-Cc: Mike Lockwood <lockwood@android.com>
diff --git a/drivers/staging/ccg/ccg.c b/drivers/staging/ccg/ccg.c
deleted file mode 100644
index ffc5f73..0000000
--- a/drivers/staging/ccg/ccg.c
+++ /dev/null
@@ -1,1292 +0,0 @@
-/*
- * Configurable Composite Gadget
- *
- * Initially contributed as "Android Composite Gdaget" by:
- *
- * Copyright (C) 2008 Google, Inc.
- * Author: Mike Lockwood <lockwood@android.com>
- *         Benoit Goby <benoit@android.com>
- *
- * Tailoring it to become a generic Configurable Composite Gadget is
- *
- * Copyright (C) 2012 Samsung Electronics
- * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.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/module.h>
-#include <linux/fs.h>
-#include <linux/delay.h>
-#include <linux/kernel.h>
-#include <linux/utsname.h>
-#include <linux/platform_device.h>
-
-#include <linux/usb/ch9.h>
-#include "composite.h"
-#include <linux/usb/gadget.h>
-
-#include "gadget_chips.h"
-
-/*
- * Kbuild is not very cooperative with respect to linking separately
- * compiled library objects into one module.  So for now we won't use
- * separate compilation ... ensuring init/exit sections work to shrink
- * the runtime footprint, and giving us at least some parts of what
- * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
- */
-#include "usbstring.c"
-#include "config.c"
-#include "epautoconf.c"
-#include "composite.c"
-
-#include "f_mass_storage.c"
-#include "u_serial.c"
-#include "f_acm.c"
-#define USB_ETH_RNDIS y
-#include "f_rndis.c"
-#include "rndis.c"
-#include "u_ether.c"
-#include "f_fs.c"
-
-MODULE_AUTHOR("Mike Lockwood, Andrzej Pietrasiewicz");
-MODULE_DESCRIPTION("Configurable Composite USB Gadget");
-MODULE_LICENSE("GPL");
-MODULE_VERSION("1.0");
-
-static const char longname[] = "Configurable Composite Gadget";
-
-/* Default vendor and product IDs, overridden by userspace */
-#define VENDOR_ID		0x1d6b /* Linux Foundation */
-#define PRODUCT_ID		0x0107
-#define GFS_MAX_DEVS		10
-
-struct ccg_usb_function {
-	char *name;
-	void *config;
-
-	struct device *dev;
-	char *dev_name;
-	struct device_attribute **attributes;
-
-	/* for ccg_dev.enabled_functions */
-	struct list_head enabled_list;
-
-	/* Optional: initialization during gadget bind */
-	int (*init)(struct ccg_usb_function *, struct usb_composite_dev *);
-	/* Optional: cleanup during gadget unbind */
-	void (*cleanup)(struct ccg_usb_function *);
-
-	int (*bind_config)(struct ccg_usb_function *,
-			   struct usb_configuration *);
-
-	/* Optional: called when the configuration is removed */
-	void (*unbind_config)(struct ccg_usb_function *,
-			      struct usb_configuration *);
-	/* Optional: handle ctrl requests before the device is configured */
-	int (*ctrlrequest)(struct ccg_usb_function *,
-			   struct usb_composite_dev *,
-			   const struct usb_ctrlrequest *);
-};
-
-struct ffs_obj {
-	const char *name;
-	bool mounted;
-	bool desc_ready;
-	bool used;
-	struct ffs_data *ffs_data;
-};
-
-struct ccg_dev {
-	struct ccg_usb_function **functions;
-	struct list_head enabled_functions;
-	struct usb_composite_dev *cdev;
-	struct device *dev;
-
-	bool enabled;
-	struct mutex mutex;
-	bool connected;
-	bool sw_connected;
-	struct work_struct work;
-
-	unsigned int max_func_num;
-	unsigned int func_num;
-	struct ffs_obj ffs_tab[GFS_MAX_DEVS];
-};
-
-static struct class *ccg_class;
-static struct ccg_dev *_ccg_dev;
-static int ccg_bind_config(struct usb_configuration *c);
-static void ccg_unbind_config(struct usb_configuration *c);
-
-static char func_names_buf[256];
-
-static struct usb_device_descriptor device_desc = {
-	.bLength              = sizeof(device_desc),
-	.bDescriptorType      = USB_DT_DEVICE,
-	.bcdUSB               = __constant_cpu_to_le16(0x0200),
-	.bDeviceClass         = USB_CLASS_PER_INTERFACE,
-	.idVendor             = __constant_cpu_to_le16(VENDOR_ID),
-	.idProduct            = __constant_cpu_to_le16(PRODUCT_ID),
-	.bcdDevice            = __constant_cpu_to_le16(0xffff),
-	.bNumConfigurations   = 1,
-};
-
-static struct usb_configuration ccg_config_driver = {
-	.label		= "ccg",
-	.unbind		= ccg_unbind_config,
-	.bConfigurationValue = 1,
-	.bmAttributes	= USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
-	.bMaxPower	= 0xFA, /* 500ma */
-};
-
-static void ccg_work(struct work_struct *data)
-{
-	struct ccg_dev *dev = container_of(data, struct ccg_dev, work);
-	struct usb_composite_dev *cdev = dev->cdev;
-	static char *disconnected[2] = { "USB_STATE=DISCONNECTED", NULL };
-	static char *connected[2]    = { "USB_STATE=CONNECTED", NULL };
-	static char *configured[2]   = { "USB_STATE=CONFIGURED", NULL };
-	char **uevent_envp = NULL;
-	unsigned long flags;
-
-	spin_lock_irqsave(&cdev->lock, flags);
-	if (cdev->config)
-		uevent_envp = configured;
-	else if (dev->connected != dev->sw_connected)
-		uevent_envp = dev->connected ? connected : disconnected;
-	dev->sw_connected = dev->connected;
-	spin_unlock_irqrestore(&cdev->lock, flags);
-
-	if (uevent_envp) {
-		kobject_uevent_env(&dev->dev->kobj, KOBJ_CHANGE, uevent_envp);
-		pr_info("%s: sent uevent %s\n", __func__, uevent_envp[0]);
-	} else {
-		pr_info("%s: did not send uevent (%d %d %p)\n", __func__,
-			 dev->connected, dev->sw_connected, cdev->config);
-	}
-}
-
-
-/*-------------------------------------------------------------------------*/
-/* Supported functions initialization */
-
-static struct ffs_obj *functionfs_find_dev(struct ccg_dev *dev,
-					   const char *dev_name)
-{
-	int i;
-
-	for (i = 0; i < dev->max_func_num; i++)
-		if (strcmp(dev->ffs_tab[i].name, dev_name) == 0)
-			return &dev->ffs_tab[i];
-
-	return NULL;
-}
-
-static bool functionfs_all_ready(struct ccg_dev *dev)
-{
-	int i;
-
-	for (i = 0; i < dev->max_func_num; i++)
-		if (dev->ffs_tab[i].used && !dev->ffs_tab[i].desc_ready)
-			return false;
-
-	return true;
-}
-
-static int functionfs_ready_callback(struct ffs_data *ffs)
-{
-	struct ffs_obj *ffs_obj;
-	int ret;
-
-	mutex_lock(&_ccg_dev->mutex);
-
-	ffs_obj = ffs->private_data;
-	if (!ffs_obj) {
-		ret = -EINVAL;
-		goto done;
-	}
-	if (WARN_ON(ffs_obj->desc_ready)) {
-		ret = -EBUSY;
-		goto done;
-	}
-	ffs_obj->ffs_data = ffs;
-
-	if (functionfs_all_ready(_ccg_dev)) {
-		ret = -EBUSY;
-		goto done;
-	}
-	ffs_obj->desc_ready = true;
-
-done:
-	mutex_unlock(&_ccg_dev->mutex);
-	return ret;
-}
-
-static void reset_usb(struct ccg_dev *dev)
-{
-	/* Cancel pending control requests */
-	usb_ep_dequeue(dev->cdev->gadget->ep0, dev->cdev->req);
-	usb_remove_config(dev->cdev, &ccg_config_driver);
-	dev->enabled = false;
-	usb_gadget_disconnect(dev->cdev->gadget);
-}
-
-static void functionfs_closed_callback(struct ffs_data *ffs)
-{
-	struct ffs_obj *ffs_obj;
-
-	mutex_lock(&_ccg_dev->mutex);
-
-	ffs_obj = ffs->private_data;
-	if (!ffs_obj)
-		goto done;
-
-	ffs_obj->desc_ready = false;
-
-	if (_ccg_dev->enabled)
-		reset_usb(_ccg_dev);
-
-done:
-	mutex_unlock(&_ccg_dev->mutex);
-}
-
-static void *functionfs_acquire_dev_callback(const char *dev_name)
-{
-	struct ffs_obj *ffs_dev;
-
-	mutex_lock(&_ccg_dev->mutex);
-
-	ffs_dev = functionfs_find_dev(_ccg_dev, dev_name);
-	if (!ffs_dev) {
-		ffs_dev = ERR_PTR(-ENODEV);
-		goto done;
-	}
-
-	if (ffs_dev->mounted) {
-		ffs_dev = ERR_PTR(-EBUSY);
-		goto done;
-	}
-	ffs_dev->mounted = true;
-
-done:
-	mutex_unlock(&_ccg_dev->mutex);
-	return ffs_dev;
-}
-
-static void functionfs_release_dev_callback(struct ffs_data *ffs_data)
-{
-	struct ffs_obj *ffs_dev;
-
-	mutex_lock(&_ccg_dev->mutex);
-
-	ffs_dev = ffs_data->private_data;
-	if (ffs_dev)
-		ffs_dev->mounted = false;
-
-	mutex_unlock(&_ccg_dev->mutex);
-}
-
-static int functionfs_function_init(struct ccg_usb_function *f,
-				struct usb_composite_dev *cdev)
-{
-	return functionfs_init();
-}
-
-static void functionfs_function_cleanup(struct ccg_usb_function *f)
-{
-	functionfs_cleanup();
-}
-
-static int functionfs_function_bind_config(struct ccg_usb_function *f,
-					   struct usb_configuration *c)
-{
-	struct ccg_dev *dev = _ccg_dev;
-	int i, ret;
-
-	for (i = dev->max_func_num; i--; ) {
-		if (!dev->ffs_tab[i].used)
-			continue;
-		ret = functionfs_bind(dev->ffs_tab[i].ffs_data, c->cdev);
-		if (unlikely(ret < 0)) {
-			while (++i < dev->max_func_num)
-				functionfs_unbind(dev->ffs_tab[i].ffs_data);
-			return ret;
-		}
-	}
-
-	for (i = dev->max_func_num; i--; ) {
-		if (!dev->ffs_tab[i].used)
-			continue;
-		ret = functionfs_bind_config(c->cdev, c,
-					     dev->ffs_tab[i].ffs_data);
-		if (unlikely(ret < 0))
-			return ret;
-	}
-
-	return 0;
-}
-
-static void functionfs_function_unbind_config(struct ccg_usb_function *f,
-					      struct usb_configuration *c)
-{
-	struct ccg_dev *dev = _ccg_dev;
-	int i;
-
-	for (i = dev->max_func_num; i--; )
-		if (dev->ffs_tab[i].ffs_data)
-			functionfs_unbind(dev->ffs_tab[i].ffs_data);
-}
-
-static ssize_t functionfs_user_functions_show(struct device *_dev,
-					      struct device_attribute *attr,
-					      char *buf)
-{
-	struct ccg_dev *dev = _ccg_dev;
-	char *buff = buf;
-	int i;
-
-	mutex_lock(&dev->mutex);
-
-	for (i = 0; i < dev->max_func_num; i++)
-		buff += snprintf(buff, PAGE_SIZE + buf - buff, "%s,",
-				 dev->ffs_tab[i].name);
-
-	mutex_unlock(&dev->mutex);
-
-	if (buff != buf)
-		*(buff - 1) = '\n';
-	return buff - buf;
-}
-
-static ssize_t functionfs_user_functions_store(struct device *_dev,
-					       struct device_attribute *attr,
-					       const char *buff, size_t size)
-{
-	struct ccg_dev *dev = _ccg_dev;
-	char *name, *b;
-	ssize_t ret = size;
-	int i;
-
-	buff = skip_spaces(buff);
-	if (!*buff)
-		return -EINVAL;
-
-	mutex_lock(&dev->mutex);
-
-	if (dev->enabled) {
-		ret = -EBUSY;
-		goto end;
-	}
-
-	for (i = 0; i < dev->max_func_num; i++)
-		if (dev->ffs_tab[i].mounted) {
-			ret = -EBUSY;
-			goto end;
-		}
-
-	strlcpy(func_names_buf, buff, sizeof(func_names_buf));
-	b = strim(func_names_buf);
-
-	/* replace the list of functions */
-	dev->max_func_num = 0;
-	while (b) {
-		name = strsep(&b, ",");
-		if (dev->max_func_num == GFS_MAX_DEVS) {
-			ret = -ENOSPC;
-			goto end;
-		}
-		if (functionfs_find_dev(dev, name)) {
-			ret = -EEXIST;
-			continue;
-		}
-		dev->ffs_tab[dev->max_func_num++].name = name;
-	}
-
-end:
-	mutex_unlock(&dev->mutex);
-	return ret;
-}
-
-static DEVICE_ATTR(user_functions, S_IRUGO | S_IWUSR,
-		   functionfs_user_functions_show,
-		   functionfs_user_functions_store);
-
-static ssize_t functionfs_max_user_functions_show(struct device *_dev,
-						  struct device_attribute *attr,
-						  char *buf)
-{
-	return sprintf(buf, "%d", GFS_MAX_DEVS);
-}
-
-static DEVICE_ATTR(max_user_functions, S_IRUGO,
-		   functionfs_max_user_functions_show, NULL);
-
-static struct device_attribute *functionfs_function_attributes[] = {
-	&dev_attr_user_functions,
-	&dev_attr_max_user_functions,
-	NULL
-};
-
-static struct ccg_usb_function functionfs_function = {
-	.name		= "fs",
-	.init		= functionfs_function_init,
-	.cleanup	= functionfs_function_cleanup,
-	.bind_config	= functionfs_function_bind_config,
-	.unbind_config  = functionfs_function_unbind_config,
-	.attributes	= functionfs_function_attributes,
-};
-
-#define MAX_ACM_INSTANCES 4
-struct acm_function_config {
-	int instances;
-};
-
-static int
-acm_function_init(struct ccg_usb_function *f, struct usb_composite_dev *cdev)
-{
-	f->config = kzalloc(sizeof(struct acm_function_config), GFP_KERNEL);
-	if (!f->config)
-		return -ENOMEM;
-
-	return gserial_setup(cdev->gadget, MAX_ACM_INSTANCES);
-}
-
-static void acm_function_cleanup(struct ccg_usb_function *f)
-{
-	gserial_cleanup();
-	kfree(f->config);
-	f->config = NULL;
-}
-
-static int
-acm_function_bind_config(struct ccg_usb_function *f,
-		struct usb_configuration *c)
-{
-	int i;
-	int ret = 0;
-	struct acm_function_config *config = f->config;
-
-	for (i = 0; i < config->instances; i++) {
-		ret = acm_bind_config(c, i);
-		if (ret) {
-			pr_err("Could not bind acm%u config\n", i);
-			break;
-		}
-	}
-
-	return ret;
-}
-
-static ssize_t acm_instances_show(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct ccg_usb_function *f = dev_get_drvdata(dev);
-	struct acm_function_config *config = f->config;
-	return sprintf(buf, "%d\n", config->instances);
-}
-
-static ssize_t acm_instances_store(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t size)
-{
-	struct ccg_usb_function *f = dev_get_drvdata(dev);
-	struct acm_function_config *config = f->config;
-	int value;
-	int ret = 0;
-
-	ret = kstrtoint(buf, 10, &value);
-	if (ret)
-		return ret;
-
-	if (value > MAX_ACM_INSTANCES)
-		return -EINVAL;
-
-	config->instances = value;
-
-	return size;
-}
-
-static DEVICE_ATTR(instances, S_IRUGO | S_IWUSR, acm_instances_show,
-						 acm_instances_store);
-static struct device_attribute *acm_function_attributes[] = {
-	&dev_attr_instances,
-	NULL
-};
-
-static struct ccg_usb_function acm_function = {
-	.name		= "acm",
-	.init		= acm_function_init,
-	.cleanup	= acm_function_cleanup,
-	.bind_config	= acm_function_bind_config,
-	.attributes	= acm_function_attributes,
-};
-
-struct rndis_function_config {
-	u8      ethaddr[ETH_ALEN];
-	u32     vendorID;
-	char	manufacturer[256];
-	/* "Wireless" RNDIS; auto-detected by Windows */
-	bool	wceis;
-};
-
-static int rndis_function_init(struct ccg_usb_function *f,
-			       struct usb_composite_dev *cdev)
-{
-	f->config = kzalloc(sizeof(struct rndis_function_config), GFP_KERNEL);
-	if (!f->config)
-		return -ENOMEM;
-	return 0;
-}
-
-static void rndis_function_cleanup(struct ccg_usb_function *f)
-{
-	kfree(f->config);
-	f->config = NULL;
-}
-
-static int rndis_function_bind_config(struct ccg_usb_function *f,
-				      struct usb_configuration *c)
-{
-	int ret;
-	struct rndis_function_config *rndis = f->config;
-
-	if (!rndis) {
-		pr_err("%s: rndis_pdata\n", __func__);
-		return -1;
-	}
-
-	pr_info("%s MAC: %pM\n", __func__, rndis->ethaddr);
-
-	ret = gether_setup_name(c->cdev->gadget, rndis->ethaddr, "rndis");
-	if (ret) {
-		pr_err("%s: gether_setup failed\n", __func__);
-		return ret;
-	}
-
-	if (rndis->wceis) {
-		/* "Wireless" RNDIS; auto-detected by Windows */
-		rndis_iad_descriptor.bFunctionClass =
-						USB_CLASS_WIRELESS_CONTROLLER;
-		rndis_iad_descriptor.bFunctionSubClass = 0x01;
-		rndis_iad_descriptor.bFunctionProtocol = 0x03;
-		rndis_control_intf.bInterfaceClass =
-						USB_CLASS_WIRELESS_CONTROLLER;
-		rndis_control_intf.bInterfaceSubClass =	 0x01;
-		rndis_control_intf.bInterfaceProtocol =	 0x03;
-	}
-
-	return rndis_bind_config_vendor(c, rndis->ethaddr, rndis->vendorID,
-					   rndis->manufacturer);
-}
-
-static void rndis_function_unbind_config(struct ccg_usb_function *f,
-						struct usb_configuration *c)
-{
-	gether_cleanup();
-}
-
-static ssize_t rndis_manufacturer_show(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct ccg_usb_function *f = dev_get_drvdata(dev);
-	struct rndis_function_config *config = f->config;
-	return sprintf(buf, "%s\n", config->manufacturer);
-}
-
-static ssize_t rndis_manufacturer_store(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t size)
-{
-	struct ccg_usb_function *f = dev_get_drvdata(dev);
-	struct rndis_function_config *config = f->config;
-
-	if (size >= sizeof(config->manufacturer))
-		return -EINVAL;
-	memcpy(config->manufacturer, buf, size);
-	config->manufacturer[size] = 0;
-
-	return size;
-}
-
-static DEVICE_ATTR(manufacturer, S_IRUGO | S_IWUSR, rndis_manufacturer_show,
-						    rndis_manufacturer_store);
-
-static ssize_t rndis_wceis_show(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct ccg_usb_function *f = dev_get_drvdata(dev);
-	struct rndis_function_config *config = f->config;
-	return sprintf(buf, "%d\n", config->wceis);
-}
-
-static ssize_t rndis_wceis_store(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t size)
-{
-	struct ccg_usb_function *f = dev_get_drvdata(dev);
-	struct rndis_function_config *config = f->config;
-	int value;
-	int ret;
-
-	ret = kstrtoint(buf, 10, &value);
-	if (ret)
-		return ret;
-
-	config->wceis = value;
-
-	return size;
-}
-
-static DEVICE_ATTR(wceis, S_IRUGO | S_IWUSR, rndis_wceis_show,
-					     rndis_wceis_store);
-
-static ssize_t rndis_ethaddr_show(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct ccg_usb_function *f = dev_get_drvdata(dev);
-	struct rndis_function_config *rndis = f->config;
-	return sprintf(buf, "%pM\n", rndis->ethaddr);
-}
-
-static ssize_t rndis_ethaddr_store(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t size)
-{
-	struct ccg_usb_function *f = dev_get_drvdata(dev);
-	struct rndis_function_config *rndis = f->config;
-	unsigned char tmp[6];
-
-	if (sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
-		   tmp + 0, tmp + 1, tmp + 2, tmp + 3, tmp + 4, tmp + 5) !=
-	    ETH_ALEN)
-		return -EINVAL;
-
-	memcpy(rndis->ethaddr, tmp, ETH_ALEN);
-
-	return ETH_ALEN;
-
-}
-
-static DEVICE_ATTR(ethaddr, S_IRUGO | S_IWUSR, rndis_ethaddr_show,
-					       rndis_ethaddr_store);
-
-static ssize_t rndis_vendorID_show(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct ccg_usb_function *f = dev_get_drvdata(dev);
-	struct rndis_function_config *config = f->config;
-	return sprintf(buf, "%04x\n", config->vendorID);
-}
-
-static ssize_t rndis_vendorID_store(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t size)
-{
-	struct ccg_usb_function *f = dev_get_drvdata(dev);
-	struct rndis_function_config *config = f->config;
-	int value;
-	int ret;
-
-	ret = kstrtou32(buf, 16, &value);
-	if (ret)
-		return ret;
-
-	config->vendorID = value;
-
-	return size;
-}
-
-static DEVICE_ATTR(vendorID, S_IRUGO | S_IWUSR, rndis_vendorID_show,
-						rndis_vendorID_store);
-
-static struct device_attribute *rndis_function_attributes[] = {
-	&dev_attr_manufacturer,
-	&dev_attr_wceis,
-	&dev_attr_ethaddr,
-	&dev_attr_vendorID,
-	NULL
-};
-
-static struct ccg_usb_function rndis_function = {
-	.name		= "rndis",
-	.init		= rndis_function_init,
-	.cleanup	= rndis_function_cleanup,
-	.bind_config	= rndis_function_bind_config,
-	.unbind_config	= rndis_function_unbind_config,
-	.attributes	= rndis_function_attributes,
-};
-
-static int mass_storage_function_init(struct ccg_usb_function *f,
-					struct usb_composite_dev *cdev)
-{
-	struct fsg_config fsg;
-	struct fsg_common *common;
-	int err;
-
-	memset(&fsg, 0, sizeof(fsg));
-	fsg.nluns = 1;
-	fsg.luns[0].removable = 1;
-	fsg.vendor_name = iManufacturer;
-	fsg.product_name = iProduct;
-
-	common = fsg_common_init(NULL, cdev, &fsg);
-	if (IS_ERR(common))
-		return PTR_ERR(common);
-
-	err = sysfs_create_link(&f->dev->kobj,
-				&common->luns[0].dev.kobj,
-				"lun");
-	if (err) {
-		fsg_common_put(common);
-		return err;
-	}
-
-	f->config = common;
-	return 0;
-}
-
-static void mass_storage_function_cleanup(struct ccg_usb_function *f)
-{
-	fsg_common_put(f->config);
-	f->config = NULL;
-}
-
-static int mass_storage_function_bind_config(struct ccg_usb_function *f,
-					     struct usb_configuration *c)
-{
-	struct fsg_common *common = f->config;
-	return fsg_bind_config(c->cdev, c, common);
-}
-
-static struct ccg_usb_function mass_storage_function = {
-	.name		= "mass_storage",
-	.init		= mass_storage_function_init,
-	.cleanup	= mass_storage_function_cleanup,
-	.bind_config	= mass_storage_function_bind_config,
-};
-
-static struct ccg_usb_function *supported_functions[] = {
-	&functionfs_function,
-	&acm_function,
-	&rndis_function,
-	&mass_storage_function,
-	NULL
-};
-
-
-static int ccg_init_functions(struct ccg_usb_function **functions,
-				  struct usb_composite_dev *cdev)
-{
-	struct ccg_dev *dev = _ccg_dev;
-	struct ccg_usb_function *f;
-	struct device_attribute **attrs;
-	struct device_attribute *attr;
-	int err;
-	int index = 0;
-
-	for (; (f = *functions++); index++) {
-		f->dev_name = kasprintf(GFP_KERNEL, "f_%s", f->name);
-		if (!f->dev_name) {
-			pr_err("%s: Failed to alloc name %s", __func__,
-			       f->name);
-			err = -ENOMEM;
-			goto err_alloc;
-		}
-		f->dev = device_create(ccg_class, dev->dev,
-				MKDEV(0, index), f, f->dev_name);
-		if (IS_ERR(f->dev)) {
-			pr_err("%s: Failed to create dev %s", __func__,
-							f->dev_name);
-			err = PTR_ERR(f->dev);
-			f->dev = NULL;
-			goto err_create;
-		}
-
-		if (f->init) {
-			err = f->init(f, cdev);
-			if (err) {
-				pr_err("%s: Failed to init %s", __func__,
-								f->name);
-				goto err_out;
-			}
-		}
-
-		attrs = f->attributes;
-		if (attrs) {
-			while ((attr = *attrs++) && !err)
-				err = device_create_file(f->dev, attr);
-		}
-		if (err) {
-			pr_err("%s: Failed to create function %s attributes",
-					__func__, f->name);
-			goto err_uninit;
-		}
-	}
-	return 0;
-
-err_uninit:
-	if (f->cleanup)
-		f->cleanup(f);
-err_out:
-	device_destroy(ccg_class, f->dev->devt);
-	f->dev = NULL;
-err_create:
-	kfree(f->dev_name);
-err_alloc:
-	return err;
-}
-
-static void ccg_cleanup_functions(struct ccg_usb_function **functions)
-{
-	struct ccg_usb_function *f;
-
-	while (*functions) {
-		f = *functions++;
-
-		if (f->dev) {
-			if (f->cleanup)
-				f->cleanup(f);
-			device_destroy(ccg_class, f->dev->devt);
-			kfree(f->dev_name);
-		}
-	}
-}
-
-static int ccg_bind_enabled_functions(struct ccg_dev *dev,
-				      struct usb_configuration *c)
-{
-	struct ccg_usb_function *f;
-	int ret;
-
-	list_for_each_entry(f, &dev->enabled_functions, enabled_list) {
-		ret = f->bind_config(f, c);
-		if (ret) {
-			pr_err("%s: %s failed", __func__, f->name);
-			return ret;
-		}
-	}
-	return 0;
-}
-
-static void ccg_unbind_enabled_functions(struct ccg_dev *dev,
-					 struct usb_configuration *c)
-{
-	struct ccg_usb_function *f;
-
-	list_for_each_entry(f, &dev->enabled_functions, enabled_list)
-		if (f->unbind_config)
-			f->unbind_config(f, c);
-}
-
-static int ccg_enable_function(struct ccg_dev *dev, char *name)
-{
-	struct ccg_usb_function **functions = dev->functions;
-	struct ccg_usb_function *f;
-	while ((f = *functions++)) {
-		if (!strcmp(name, f->name)) {
-			list_add_tail(&f->enabled_list,
-						&dev->enabled_functions);
-			return 0;
-		}
-	}
-	return -EINVAL;
-}
-
-/*-------------------------------------------------------------------------*/
-/* /sys/class/ccg_usb/ccg%d/ interface */
-
-static ssize_t
-functions_show(struct device *pdev, struct device_attribute *attr, char *buf)
-{
-	struct ccg_dev *dev = dev_get_drvdata(pdev);
-	struct ccg_usb_function *f;
-	char *buff = buf;
-	int i;
-
-	mutex_lock(&dev->mutex);
-
-	list_for_each_entry(f, &dev->enabled_functions, enabled_list)
-		buff += sprintf(buff, "%s,", f->name);
-	for (i = 0; i < dev->max_func_num; i++)
-		if (dev->ffs_tab[i].used)
-			buff += sprintf(buff, "%s", dev->ffs_tab[i].name);
-
-	mutex_unlock(&dev->mutex);
-
-	if (buff != buf)
-		*(buff-1) = '\n';
-	return buff - buf;
-}
-
-static ssize_t
-functions_store(struct device *pdev, struct device_attribute *attr,
-			       const char *buff, size_t size)
-{
-	struct ccg_dev *dev = dev_get_drvdata(pdev);
-	char *name;
-	char buf[256], *b;
-	int err, i;
-	bool functionfs_enabled;
-
-	buff = skip_spaces(buff);
-	if (!*buff)
-		return -EINVAL;
-
-	mutex_lock(&dev->mutex);
-
-	if (dev->enabled) {
-		mutex_unlock(&dev->mutex);
-		return -EBUSY;
-	}
-
-	INIT_LIST_HEAD(&dev->enabled_functions);
-	functionfs_enabled = false;
-	for (i = 0; i < dev->max_func_num; i++)
-		dev->ffs_tab[i].used = false;
-
-	strlcpy(buf, buff, sizeof(buf));
-	b = strim(buf);
-
-	while (b) {
-		struct ffs_obj *user_func;
-
-		name = strsep(&b, ",");
-		/* handle FunctionFS implicitly */
-		if (!strcmp(name, functionfs_function.name)) {
-			pr_err("ccg_usb: Cannot explicitly enable '%s'", name);
-			continue;
-		}
-		user_func = functionfs_find_dev(dev, name);
-		if (user_func)
-			name = functionfs_function.name;
-		err = 0;
-		if (!user_func || !functionfs_enabled)
-			err = ccg_enable_function(dev, name);
-		if (err)
-			pr_err("ccg_usb: Cannot enable '%s'", name);
-		else if (user_func) {
-			user_func->used = true;
-			dev->func_num++;
-			functionfs_enabled = true;
-		}
-	}
-
-	mutex_unlock(&dev->mutex);
-
-	return size;
-}
-
-static ssize_t enable_show(struct device *pdev, struct device_attribute *attr,
-			   char *buf)
-{
-	struct ccg_dev *dev = dev_get_drvdata(pdev);
-	return sprintf(buf, "%d\n", dev->enabled);
-}
-
-static ssize_t enable_store(struct device *pdev, struct device_attribute *attr,
-			    const char *buff, size_t size)
-{
-	struct ccg_dev *dev = dev_get_drvdata(pdev);
-	struct usb_composite_dev *cdev = dev->cdev;
-	int enabled = 0;
-
-	mutex_lock(&dev->mutex);
-	sscanf(buff, "%d", &enabled);
-	if (enabled && dev->func_num && !functionfs_all_ready(dev)) {
-		mutex_unlock(&dev->mutex);
-		return -ENODEV;
-	}
-
-	if (enabled && !dev->enabled) {
-		int ret;
-
-		cdev->next_string_id = 0;
-		/*
-		 * Update values in composite driver's copy of
-		 * device descriptor.
-		 */
-		cdev->desc.bDeviceClass = device_desc.bDeviceClass;
-		cdev->desc.bDeviceSubClass = device_desc.bDeviceSubClass;
-		cdev->desc.bDeviceProtocol = device_desc.bDeviceProtocol;
-		cdev->desc.idVendor = idVendor;
-		cdev->desc.idProduct = idProduct;
-		cdev->desc.bcdDevice = bcdDevice;
-
-		usb_add_config(cdev, &ccg_config_driver, ccg_bind_config);
-		dev->enabled = true;
-		ret = usb_gadget_connect(cdev->gadget);
-		if (ret) {
-			dev->enabled = false;
-			usb_remove_config(cdev, &ccg_config_driver);
-		}
-	} else if (!enabled && dev->enabled) {
-		reset_usb(dev);
-	} else {
-		pr_err("ccg_usb: already %s\n",
-			dev->enabled ? "enabled" : "disabled");
-	}
-
-	mutex_unlock(&dev->mutex);
-	return size;
-}
-
-static ssize_t state_show(struct device *pdev, struct device_attribute *attr,
-			   char *buf)
-{
-	struct ccg_dev *dev = dev_get_drvdata(pdev);
-	struct usb_composite_dev *cdev = dev->cdev;
-	char *state = "DISCONNECTED";
-	unsigned long flags;
-
-	if (!cdev)
-		goto out;
-
-	spin_lock_irqsave(&cdev->lock, flags);
-	if (cdev->config)
-		state = "CONFIGURED";
-	else if (dev->connected)
-		state = "CONNECTED";
-	spin_unlock_irqrestore(&cdev->lock, flags);
-out:
-	return sprintf(buf, "%s\n", state);
-}
-
-#define DESCRIPTOR_ATTR(field, format_string)				\
-static ssize_t								\
-field ## _show(struct device *dev, struct device_attribute *attr,	\
-		char *buf)						\
-{									\
-	return sprintf(buf, format_string, device_desc.field);		\
-}									\
-static ssize_t								\
-field ## _store(struct device *dev, struct device_attribute *attr,	\
-		const char *buf, size_t size)				\
-{									\
-	int value;							\
-	if (sscanf(buf, format_string, &value) == 1) {			\
-		device_desc.field = value;				\
-		return size;						\
-	}								\
-	return -1;							\
-}									\
-static DEVICE_ATTR(field, S_IRUGO | S_IWUSR, field ## _show, field ## _store);
-
-DESCRIPTOR_ATTR(bDeviceClass, "%d\n")
-DESCRIPTOR_ATTR(bDeviceSubClass, "%d\n")
-DESCRIPTOR_ATTR(bDeviceProtocol, "%d\n")
-
-static DEVICE_ATTR(functions, S_IRUGO | S_IWUSR, functions_show,
-						 functions_store);
-static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, enable_show, enable_store);
-static DEVICE_ATTR(state, S_IRUGO, state_show, NULL);
-
-static struct device_attribute *ccg_usb_attributes[] = {
-	&dev_attr_bDeviceClass,
-	&dev_attr_bDeviceSubClass,
-	&dev_attr_bDeviceProtocol,
-	&dev_attr_functions,
-	&dev_attr_enable,
-	&dev_attr_state,
-	NULL
-};
-
-/*-------------------------------------------------------------------------*/
-/* Composite driver */
-
-static int ccg_bind_config(struct usb_configuration *c)
-{
-	struct ccg_dev *dev = _ccg_dev;
-	return ccg_bind_enabled_functions(dev, c);
-}
-
-static void ccg_unbind_config(struct usb_configuration *c)
-{
-	struct ccg_dev *dev = _ccg_dev;
-
-	ccg_unbind_enabled_functions(dev, c);
-
-	usb_ep_autoconfig_reset(dev->cdev->gadget);
-}
-
-static int ccg_bind(struct usb_composite_dev *cdev)
-{
-	struct ccg_dev *dev = _ccg_dev;
-	struct usb_gadget	*gadget = cdev->gadget;
-	int			gcnum, ret;
-
-	/*
-	 * Start disconnected. Userspace will connect the gadget once
-	 * it is done configuring the functions.
-	 */
-	usb_gadget_disconnect(gadget);
-
-	ret = ccg_init_functions(dev->functions, cdev);
-	if (ret)
-		return ret;
-
-	gcnum = usb_gadget_controller_number(gadget);
-	if (gcnum >= 0)
-		device_desc.bcdDevice = cpu_to_le16(0x0200 + gcnum);
-	else {
-		pr_warn("%s: controller '%s' not recognized\n",
-			longname, gadget->name);
-		device_desc.bcdDevice = __constant_cpu_to_le16(0x9999);
-	}
-
-	usb_gadget_set_selfpowered(gadget);
-	dev->cdev = cdev;
-
-	return 0;
-}
-
-static int ccg_usb_unbind(struct usb_composite_dev *cdev)
-{
-	struct ccg_dev *dev = _ccg_dev;
-
-	cancel_work_sync(&dev->work);
-	ccg_cleanup_functions(dev->functions);
-	return 0;
-}
-
-static struct usb_composite_driver ccg_usb_driver = {
-	.name		= "configurable_usb",
-	.dev		= &device_desc,
-	.bind		= ccg_bind,
-	.unbind		= ccg_usb_unbind,
-	.needs_serial	= true,
-	.iManufacturer	= "Linux Foundation",
-	.iProduct	= longname,
-	.iSerialNumber	= "1234567890123456",
-};
-
-static int ccg_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *c)
-{
-	struct ccg_dev		*dev = _ccg_dev;
-	struct usb_composite_dev	*cdev = get_gadget_data(gadget);
-	struct usb_request		*req = cdev->req;
-	struct ccg_usb_function	*f;
-	int value = -EOPNOTSUPP;
-	unsigned long flags;
-
-	req->zero = 0;
-	req->complete = composite_setup_complete;
-	req->length = 0;
-	gadget->ep0->driver_data = cdev;
-
-	list_for_each_entry(f, &dev->enabled_functions, enabled_list) {
-		if (f->ctrlrequest) {
-			value = f->ctrlrequest(f, cdev, c);
-			if (value >= 0)
-				break;
-		}
-	}
-
-	if (value < 0)
-		value = composite_setup(gadget, c);
-
-	spin_lock_irqsave(&cdev->lock, flags);
-	if (!dev->connected) {
-		dev->connected = 1;
-		schedule_work(&dev->work);
-	} else if (c->bRequest == USB_REQ_SET_CONFIGURATION &&
-						cdev->config) {
-		schedule_work(&dev->work);
-	}
-	spin_unlock_irqrestore(&cdev->lock, flags);
-
-	return value;
-}
-
-static void ccg_disconnect(struct usb_gadget *gadget)
-{
-	struct ccg_dev *dev = _ccg_dev;
-	struct usb_composite_dev *cdev = get_gadget_data(gadget);
-	unsigned long flags;
-
-	composite_disconnect(gadget);
-
-	spin_lock_irqsave(&cdev->lock, flags);
-	dev->connected = 0;
-	schedule_work(&dev->work);
-	spin_unlock_irqrestore(&cdev->lock, flags);
-}
-
-static int ccg_create_device(struct ccg_dev *dev)
-{
-	struct device_attribute **attrs = ccg_usb_attributes;
-	struct device_attribute *attr;
-	int err;
-
-	dev->dev = device_create(ccg_class, NULL, MKDEV(0, 0), NULL, "ccg0");
-	if (IS_ERR(dev->dev))
-		return PTR_ERR(dev->dev);
-
-	dev_set_drvdata(dev->dev, dev);
-
-	while ((attr = *attrs++)) {
-		err = device_create_file(dev->dev, attr);
-		if (err) {
-			device_destroy(ccg_class, dev->dev->devt);
-			return err;
-		}
-	}
-	return 0;
-}
-
-
-static int __init ccg_init(void)
-{
-	struct ccg_dev *dev;
-	int err;
-
-	ccg_class = class_create(THIS_MODULE, "ccg_usb");
-	if (IS_ERR(ccg_class))
-		return PTR_ERR(ccg_class);
-
-	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-	if (!dev) {
-		class_destroy(ccg_class);
-		return -ENOMEM;
-	}
-
-	dev->functions = supported_functions;
-	INIT_LIST_HEAD(&dev->enabled_functions);
-	INIT_WORK(&dev->work, ccg_work);
-	mutex_init(&dev->mutex);
-
-	err = ccg_create_device(dev);
-	if (err) {
-		class_destroy(ccg_class);
-		kfree(dev);
-		return err;
-	}
-
-	_ccg_dev = dev;
-
-	/* Override composite driver functions */
-	composite_driver.setup = ccg_setup;
-	composite_driver.disconnect = ccg_disconnect;
-
-	err = usb_composite_probe(&ccg_usb_driver);
-	if (err) {
-		class_destroy(ccg_class);
-		kfree(dev);
-	}
-
-	return err;
-}
-module_init(ccg_init);
-
-static void __exit ccg_exit(void)
-{
-	usb_composite_unregister(&ccg_usb_driver);
-	class_destroy(ccg_class);
-	kfree(_ccg_dev);
-	_ccg_dev = NULL;
-}
-module_exit(ccg_exit);
diff --git a/drivers/staging/ccg/composite.c b/drivers/staging/ccg/composite.c
deleted file mode 100644
index 228b457..0000000
--- a/drivers/staging/ccg/composite.c
+++ /dev/null
@@ -1,1688 +0,0 @@
-/*
- * composite.c - infrastructure for Composite USB Gadgets
- *
- * Copyright (C) 2006-2008 David Brownell
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-/* #define VERBOSE_DEBUG */
-
-#include <linux/kallsyms.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/device.h>
-#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
- * from one or more "function" drivers, one or more "configuration"
- * objects, and a "usb_composite_driver" by gluing them together along
- * with the relevant device-wide data.
- */
-
-/* big enough to hold our biggest descriptor */
-#define USB_BUFSIZ	1024
-
-static struct usb_composite_driver *composite;
-
-/* Some systems will need runtime overrides for the  product identifiers
- * published in the device descriptor, either numbers or strings or both.
- * String parameters are in UTF-8 (superset of ASCII's 7 bit characters).
- */
-
-static ushort idVendor;
-module_param(idVendor, ushort, 0644);
-MODULE_PARM_DESC(idVendor, "USB Vendor ID");
-
-static ushort idProduct;
-module_param(idProduct, ushort, 0644);
-MODULE_PARM_DESC(idProduct, "USB Product ID");
-
-static ushort bcdDevice;
-module_param(bcdDevice, ushort, 0644);
-MODULE_PARM_DESC(bcdDevice, "USB Device version (BCD)");
-
-static char *iManufacturer;
-module_param(iManufacturer, charp, 0644);
-MODULE_PARM_DESC(iManufacturer, "USB Manufacturer string");
-
-static char *iProduct;
-module_param(iProduct, charp, 0644);
-MODULE_PARM_DESC(iProduct, "USB Product string");
-
-static char *iSerialNumber;
-module_param(iSerialNumber, charp, 0644);
-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_composite_dev	*cdev = get_gadget_data(g);
-	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 = usb_endpoint_maxp(chosen_desc);
-	_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_ISOC:
-			/* mult: bits 1:0 of bmAttributes */
-			_ep->mult = comp_desc->bmAttributes & 0x3;
-		case USB_ENDPOINT_XFER_BULK:
-		case USB_ENDPOINT_XFER_INT:
-			_ep->maxburst = comp_desc->bMaxBurst + 1;
-			break;
-		default:
-			if (comp_desc->bMaxBurst != 0)
-				ERROR(cdev, "ep0 bMaxBurst must be 0\n");
-			_ep->maxburst = 1;
-			break;
-		}
-	}
-	return 0;
-}
-
-/**
- * usb_add_function() - add a function to a configuration
- * @config: the configuration
- * @function: the function being added
- * Context: single threaded during gadget setup
- *
- * After initialization, each configuration must have one or more
- * functions added to it.  Adding a function involves calling its @bind()
- * method to allocate resources such as interface and string identifiers
- * and endpoints.
- *
- * This function returns the value of the function's bind(), which is
- * zero for success else a negative errno value.
- */
-int usb_add_function(struct usb_configuration *config,
-		struct usb_function *function)
-{
-	int	value = -EINVAL;
-
-	DBG(config->cdev, "adding '%s'/%p to config '%s'/%p\n",
-			function->name, function,
-			config->label, config);
-
-	if (!function->set_alt || !function->disable)
-		goto done;
-
-	function->config = config;
-	list_add_tail(&function->list, &config->functions);
-
-	/* REVISIT *require* function->bind? */
-	if (function->bind) {
-		value = function->bind(config, function);
-		if (value < 0) {
-			list_del(&function->list);
-			function->config = NULL;
-		}
-	} else
-		value = 0;
-
-	/* We allow configurations that don't work at both speeds.
-	 * If we run into a lowspeed Linux system, treat it the same
-	 * as full speed ... it's the function drivers that will need
-	 * to avoid bulk and ISO transfers.
-	 */
-	if (!config->fullspeed && function->descriptors)
-		config->fullspeed = true;
-	if (!config->highspeed && function->hs_descriptors)
-		config->highspeed = true;
-	if (!config->superspeed && function->ss_descriptors)
-		config->superspeed = true;
-
-done:
-	if (value)
-		DBG(config->cdev, "adding '%s'/%p --> %d\n",
-				function->name, function, value);
-	return value;
-}
-
-/**
- * usb_function_deactivate - prevent function and gadget enumeration
- * @function: the function that isn't yet ready to respond
- *
- * Blocks response of the gadget driver to host enumeration by
- * preventing the data line pullup from being activated.  This is
- * normally called during @bind() processing to change from the
- * initial "ready to respond" state, or when a required resource
- * becomes available.
- *
- * For example, drivers that serve as a passthrough to a userspace
- * daemon can block enumeration unless that daemon (such as an OBEX,
- * MTP, or print server) is ready to handle host requests.
- *
- * Not all systems support software control of their USB peripheral
- * data pullups.
- *
- * Returns zero on success, else negative errno.
- */
-int usb_function_deactivate(struct usb_function *function)
-{
-	struct usb_composite_dev	*cdev = function->config->cdev;
-	unsigned long			flags;
-	int				status = 0;
-
-	spin_lock_irqsave(&cdev->lock, flags);
-
-	if (cdev->deactivations == 0)
-		status = usb_gadget_disconnect(cdev->gadget);
-	if (status == 0)
-		cdev->deactivations++;
-
-	spin_unlock_irqrestore(&cdev->lock, flags);
-	return status;
-}
-
-/**
- * usb_function_activate - allow function and gadget enumeration
- * @function: function on which usb_function_activate() was called
- *
- * Reverses effect of usb_function_deactivate().  If no more functions
- * are delaying their activation, the gadget driver will respond to
- * host enumeration procedures.
- *
- * Returns zero on success, else negative errno.
- */
-int usb_function_activate(struct usb_function *function)
-{
-	struct usb_composite_dev	*cdev = function->config->cdev;
-	unsigned long			flags;
-	int				status = 0;
-
-	spin_lock_irqsave(&cdev->lock, flags);
-
-	if (WARN_ON(cdev->deactivations == 0))
-		status = -EINVAL;
-	else {
-		cdev->deactivations--;
-		if (cdev->deactivations == 0)
-			status = usb_gadget_connect(cdev->gadget);
-	}
-
-	spin_unlock_irqrestore(&cdev->lock, flags);
-	return status;
-}
-
-/**
- * usb_interface_id() - allocate an unused interface ID
- * @config: configuration associated with the interface
- * @function: function handling the interface
- * Context: single threaded during gadget setup
- *
- * usb_interface_id() is called from usb_function.bind() callbacks to
- * allocate new interface IDs.  The function driver will then store that
- * ID in interface, association, CDC union, and other descriptors.  It
- * will also handle any control requests targeted at that interface,
- * particularly changing its altsetting via set_alt().  There may
- * also be class-specific or vendor-specific requests to handle.
- *
- * All interface identifier should be allocated using this routine, to
- * ensure that for example different functions don't wrongly assign
- * different meanings to the same identifier.  Note that since interface
- * identifiers are configuration-specific, functions used in more than
- * one configuration (or more than once in a given configuration) need
- * multiple versions of the relevant descriptors.
- *
- * Returns the interface ID which was allocated; or -ENODEV if no
- * more interface IDs can be allocated.
- */
-int usb_interface_id(struct usb_configuration *config,
-		struct usb_function *function)
-{
-	unsigned id = config->next_interface_id;
-
-	if (id < MAX_CONFIG_INTERFACES) {
-		config->interface[id] = function;
-		config->next_interface_id = id + 1;
-		return id;
-	}
-	return -ENODEV;
-}
-
-static int config_buf(struct usb_configuration *config,
-		enum usb_device_speed speed, void *buf, u8 type)
-{
-	struct usb_config_descriptor	*c = buf;
-	void				*next = buf + USB_DT_CONFIG_SIZE;
-	int				len = USB_BUFSIZ - USB_DT_CONFIG_SIZE;
-	struct usb_function		*f;
-	int				status;
-
-	/* write the config descriptor */
-	c = buf;
-	c->bLength = USB_DT_CONFIG_SIZE;
-	c->bDescriptorType = type;
-	/* wTotalLength is written later */
-	c->bNumInterfaces = config->next_interface_id;
-	c->bConfigurationValue = config->bConfigurationValue;
-	c->iConfiguration = config->iConfiguration;
-	c->bmAttributes = USB_CONFIG_ATT_ONE | config->bmAttributes;
-	c->bMaxPower = config->bMaxPower ? : (CONFIG_USB_GADGET_VBUS_DRAW / 2);
-
-	/* There may be e.g. OTG descriptors */
-	if (config->descriptors) {
-		status = usb_descriptor_fillbuf(next, len,
-				config->descriptors);
-		if (status < 0)
-			return status;
-		len -= status;
-		next += status;
-	}
-
-	/* add each function's descriptors */
-	list_for_each_entry(f, &config->functions, list) {
-		struct usb_descriptor_header **descriptors;
-
-		switch (speed) {
-		case USB_SPEED_SUPER:
-			descriptors = f->ss_descriptors;
-			break;
-		case USB_SPEED_HIGH:
-			descriptors = f->hs_descriptors;
-			break;
-		default:
-			descriptors = f->descriptors;
-		}
-
-		if (!descriptors)
-			continue;
-		status = usb_descriptor_fillbuf(next, len,
-			(const struct usb_descriptor_header **) descriptors);
-		if (status < 0)
-			return status;
-		len -= status;
-		next += status;
-	}
-
-	len = next - buf;
-	c->wTotalLength = cpu_to_le16(len);
-	return len;
-}
-
-static int config_desc(struct usb_composite_dev *cdev, unsigned w_value)
-{
-	struct usb_gadget		*gadget = cdev->gadget;
-	struct usb_configuration	*c;
-	u8				type = w_value >> 8;
-	enum usb_device_speed		speed = USB_SPEED_UNKNOWN;
-
-	if (gadget->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)
-			hs = !hs;
-		if (hs)
-			speed = USB_SPEED_HIGH;
-
-	}
-
-	/* This is a lookup by config *INDEX* */
-	w_value &= 0xff;
-	list_for_each_entry(c, &cdev->configs, list) {
-		/* ignore configs that won't work at this speed */
-		switch (speed) {
-		case USB_SPEED_SUPER:
-			if (!c->superspeed)
-				continue;
-			break;
-		case USB_SPEED_HIGH:
-			if (!c->highspeed)
-				continue;
-			break;
-		default:
-			if (!c->fullspeed)
-				continue;
-		}
-
-		if (w_value == 0)
-			return config_buf(c, speed, cdev->req->buf, type);
-		w_value--;
-	}
-	return -EINVAL;
-}
-
-static int count_configs(struct usb_composite_dev *cdev, unsigned type)
-{
-	struct usb_gadget		*gadget = cdev->gadget;
-	struct usb_configuration	*c;
-	unsigned			count = 0;
-	int				hs = 0;
-	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 (ss) {
-			if (!c->superspeed)
-				continue;
-		} else if (hs) {
-			if (!c->highspeed)
-				continue;
-		} else {
-			if (!c->fullspeed)
-				continue;
-		}
-		count++;
-	}
-	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_DEFAULT_U1_DEV_EXIT_LAT;
-		dcd_config_params.bU2DevExitLat =
-			cpu_to_le16(USB_DEFAULT_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;
-
-	qual->bLength = sizeof(*qual);
-	qual->bDescriptorType = USB_DT_DEVICE_QUALIFIER;
-	/* POLICY: same bcdUSB and device type info at both speeds */
-	qual->bcdUSB = cdev->desc.bcdUSB;
-	qual->bDeviceClass = cdev->desc.bDeviceClass;
-	qual->bDeviceSubClass = cdev->desc.bDeviceSubClass;
-	qual->bDeviceProtocol = cdev->desc.bDeviceProtocol;
-	/* ASSUME same EP0 fifo size at both speeds */
-	qual->bMaxPacketSize0 = cdev->gadget->ep0->maxpacket;
-	qual->bNumConfigurations = count_configs(cdev, USB_DT_DEVICE_QUALIFIER);
-	qual->bRESERVED = 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void reset_config(struct usb_composite_dev *cdev)
-{
-	struct usb_function		*f;
-
-	DBG(cdev, "reset config\n");
-
-	list_for_each_entry(f, &cdev->config->functions, list) {
-		if (f->disable)
-			f->disable(f);
-
-		bitmap_zero(f->endpoints, 32);
-	}
-	cdev->config = NULL;
-}
-
-static int set_config(struct usb_composite_dev *cdev,
-		const struct usb_ctrlrequest *ctrl, unsigned number)
-{
-	struct usb_gadget	*gadget = cdev->gadget;
-	struct usb_configuration *c = NULL;
-	int			result = -EINVAL;
-	unsigned		power = gadget_is_otg(gadget) ? 8 : 100;
-	int			tmp;
-
-	if (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 { /* Zero configuration value - need to reset the config */
-		if (cdev->config)
-			reset_config(cdev);
-		result = 0;
-	}
-
-	INFO(cdev, "%s config #%d: %s\n",
-	     usb_speed_string(gadget->speed),
-	     number, c ? c->label : "unconfigured");
-
-	if (!c)
-		goto done;
-
-	cdev->config = c;
-
-	/* Initialize all interfaces by setting them to altsetting zero. */
-	for (tmp = 0; tmp < MAX_CONFIG_INTERFACES; tmp++) {
-		struct usb_function	*f = c->interface[tmp];
-		struct usb_descriptor_header **descriptors;
-
-		if (!f)
-			break;
-
-		/*
-		 * Record which endpoints are used by the function. This is used
-		 * to dispatch control requests targeted at that endpoint to the
-		 * function's setup callback instead of the current
-		 * configuration's setup callback.
-		 */
-		switch (gadget->speed) {
-		case USB_SPEED_SUPER:
-			descriptors = f->ss_descriptors;
-			break;
-		case USB_SPEED_HIGH:
-			descriptors = f->hs_descriptors;
-			break;
-		default:
-			descriptors = f->descriptors;
-		}
-
-		for (; *descriptors; ++descriptors) {
-			struct usb_endpoint_descriptor *ep;
-			int addr;
-
-			if ((*descriptors)->bDescriptorType != USB_DT_ENDPOINT)
-				continue;
-
-			ep = (struct usb_endpoint_descriptor *)*descriptors;
-			addr = ((ep->bEndpointAddress & 0x80) >> 3)
-			     |  (ep->bEndpointAddress & 0x0f);
-			set_bit(addr, f->endpoints);
-		}
-
-		result = f->set_alt(f, tmp, 0);
-		if (result < 0) {
-			DBG(cdev, "interface %d (%s/%p) alt 0 --> %d\n",
-					tmp, f->name, f, result);
-
-			reset_config(cdev);
-			goto done;
-		}
-
-		if (result == USB_GADGET_DELAYED_STATUS) {
-			DBG(cdev,
-			 "%s: interface %d (%s) requested delayed status\n",
-					__func__, tmp, f->name);
-			cdev->delayed_status++;
-			DBG(cdev, "delayed_status count %d\n",
-					cdev->delayed_status);
-		}
-	}
-
-	/* when we return, be sure our power usage is valid */
-	power = c->bMaxPower ? (2 * c->bMaxPower) : CONFIG_USB_GADGET_VBUS_DRAW;
-done:
-	usb_gadget_vbus_draw(gadget, power);
-	if (result >= 0 && cdev->delayed_status)
-		result = USB_GADGET_DELAYED_STATUS;
-	return result;
-}
-
-/**
- * usb_add_config() - add a configuration to a device.
- * @cdev: wraps the USB gadget
- * @config: the configuration, with bConfigurationValue assigned
- * @bind: the configuration's bind function
- * Context: single threaded during gadget setup
- *
- * One of the main tasks of a composite @bind() routine is to
- * add each of the configurations it supports, using this routine.
- *
- * This function returns the value of the configuration's @bind(), which
- * is zero for success else a negative errno value.  Binding configurations
- * assigns global resources including string IDs, and per-configuration
- * resources such as interface IDs and endpoints.
- */
-int usb_add_config(struct usb_composite_dev *cdev,
-		struct usb_configuration *config,
-		int (*bind)(struct usb_configuration *))
-{
-	int				status = -EINVAL;
-	struct usb_configuration	*c;
-
-	DBG(cdev, "adding config #%u '%s'/%p\n",
-			config->bConfigurationValue,
-			config->label, config);
-
-	if (!config->bConfigurationValue || !bind)
-		goto done;
-
-	/* Prevent duplicate configuration identifiers */
-	list_for_each_entry(c, &cdev->configs, list) {
-		if (c->bConfigurationValue == config->bConfigurationValue) {
-			status = -EBUSY;
-			goto done;
-		}
-	}
-
-	config->cdev = cdev;
-	list_add_tail(&config->list, &cdev->configs);
-
-	INIT_LIST_HEAD(&config->functions);
-	config->next_interface_id = 0;
-	memset(config->interface, 0, sizeof(config->interface));
-
-	status = bind(config);
-	if (status < 0) {
-		while (!list_empty(&config->functions)) {
-			struct usb_function		*f;
-
-			f = list_first_entry(&config->functions,
-					struct usb_function, list);
-			list_del(&f->list);
-			if (f->unbind) {
-				DBG(cdev, "unbind function '%s'/%p\n",
-					f->name, f);
-				f->unbind(config, f);
-				/* may free memory for "f" */
-			}
-		}
-		list_del(&config->list);
-		config->cdev = NULL;
-	} else {
-		unsigned	i;
-
-		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)
-					? " full"
-					: " full/low")
-				: "");
-
-		for (i = 0; i < MAX_CONFIG_INTERFACES; i++) {
-			struct usb_function	*f = config->interface[i];
-
-			if (!f)
-				continue;
-			DBG(cdev, "  interface %d = %s/%p\n",
-				i, f->name, f);
-		}
-	}
-
-	/* set_alt(), or next bind(), sets up
-	 * ep->driver_data as needed.
-	 */
-	usb_ep_autoconfig_reset(cdev->gadget);
-
-done:
-	if (status)
-		DBG(cdev, "added config '%s'/%u --> %d\n", config->label,
-				config->bConfigurationValue, status);
-	return status;
-}
-
-static void remove_config(struct usb_composite_dev *cdev,
-			      struct usb_configuration *config)
-{
-	while (!list_empty(&config->functions)) {
-		struct usb_function		*f;
-
-		f = list_first_entry(&config->functions,
-				struct usb_function, list);
-		list_del(&f->list);
-		if (f->unbind) {
-			DBG(cdev, "unbind function '%s'/%p\n", f->name, f);
-			f->unbind(config, f);
-			/* may free memory for "f" */
-		}
-	}
-	list_del(&config->list);
-	if (config->unbind) {
-		DBG(cdev, "unbind config '%s'/%p\n", config->label, config);
-		config->unbind(config);
-			/* may free memory for "c" */
-	}
-}
-
-/**
- * usb_remove_config() - remove a configuration from a device.
- * @cdev: wraps the USB gadget
- * @config: the configuration
- *
- * Drivers must call usb_gadget_disconnect before calling this function
- * to disconnect the device from the host and make sure the host will not
- * try to enumerate the device while we are changing the config list.
- */
-void usb_remove_config(struct usb_composite_dev *cdev,
-		      struct usb_configuration *config)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&cdev->lock, flags);
-
-	if (cdev->config == config)
-		reset_config(cdev);
-
-	spin_unlock_irqrestore(&cdev->lock, flags);
-
-	remove_config(cdev, config);
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* We support strings in multiple languages ... string descriptor zero
- * says which languages are supported.  The typical case will be that
- * only one language (probably English) is used, with I18N handled on
- * the host side.
- */
-
-static void collect_langs(struct usb_gadget_strings **sp, __le16 *buf)
-{
-	const struct usb_gadget_strings	*s;
-	__le16				language;
-	__le16				*tmp;
-
-	while (*sp) {
-		s = *sp;
-		language = cpu_to_le16(s->language);
-		for (tmp = buf; *tmp && tmp < &buf[126]; tmp++) {
-			if (*tmp == language)
-				goto repeat;
-		}
-		*tmp++ = language;
-repeat:
-		sp++;
-	}
-}
-
-static int lookup_string(
-	struct usb_gadget_strings	**sp,
-	void				*buf,
-	u16				language,
-	int				id
-)
-{
-	struct usb_gadget_strings	*s;
-	int				value;
-
-	while (*sp) {
-		s = *sp++;
-		if (s->language != language)
-			continue;
-		value = usb_gadget_get_string(s, id, buf);
-		if (value > 0)
-			return value;
-	}
-	return -EINVAL;
-}
-
-static int get_string(struct usb_composite_dev *cdev,
-		void *buf, u16 language, int id)
-{
-	struct usb_configuration	*c;
-	struct usb_function		*f;
-	int				len;
-	const char			*str;
-
-	/* Yes, not only is USB's I18N support probably more than most
-	 * folk will ever care about ... also, it's all supported here.
-	 * (Except for UTF8 support for Unicode's "Astral Planes".)
-	 */
-
-	/* 0 == report all available language codes */
-	if (id == 0) {
-		struct usb_string_descriptor	*s = buf;
-		struct usb_gadget_strings	**sp;
-
-		memset(s, 0, 256);
-		s->bDescriptorType = USB_DT_STRING;
-
-		sp = composite->strings;
-		if (sp)
-			collect_langs(sp, s->wData);
-
-		list_for_each_entry(c, &cdev->configs, list) {
-			sp = c->strings;
-			if (sp)
-				collect_langs(sp, s->wData);
-
-			list_for_each_entry(f, &c->functions, list) {
-				sp = f->strings;
-				if (sp)
-					collect_langs(sp, s->wData);
-			}
-		}
-
-		for (len = 0; len <= 126 && s->wData[len]; len++)
-			continue;
-		if (!len)
-			return -EINVAL;
-
-		s->bLength = 2 * (len + 1);
-		return s->bLength;
-	}
-
-	/* Otherwise, look up and return a specified string.  First
-	 * check if the string has not been overridden.
-	 */
-	if (cdev->manufacturer_override == id)
-		str = iManufacturer ?: composite->iManufacturer ?:
-			composite_manufacturer;
-	else if (cdev->product_override == id)
-		str = iProduct ?: composite->iProduct;
-	else if (cdev->serial_override == id)
-		str = iSerialNumber ?: composite->iSerialNumber;
-	else
-		str = NULL;
-	if (str) {
-		struct usb_gadget_strings strings = {
-			.language = language,
-			.strings  = &(struct usb_string) { 0xff, str }
-		};
-		return usb_gadget_get_string(&strings, 0xff, buf);
-	}
-
-	/* String IDs are device-scoped, so we look up each string
-	 * table we're told about.  These lookups are infrequent;
-	 * simpler-is-better here.
-	 */
-	if (composite->strings) {
-		len = lookup_string(composite->strings, buf, language, id);
-		if (len > 0)
-			return len;
-	}
-	list_for_each_entry(c, &cdev->configs, list) {
-		if (c->strings) {
-			len = lookup_string(c->strings, buf, language, id);
-			if (len > 0)
-				return len;
-		}
-		list_for_each_entry(f, &c->functions, list) {
-			if (!f->strings)
-				continue;
-			len = lookup_string(f->strings, buf, language, id);
-			if (len > 0)
-				return len;
-		}
-	}
-	return -EINVAL;
-}
-
-/**
- * usb_string_id() - allocate an unused string ID
- * @cdev: the device whose string descriptor IDs are being allocated
- * Context: single threaded during gadget setup
- *
- * @usb_string_id() is called from bind() callbacks to allocate
- * string IDs.  Drivers for functions, configurations, or gadgets will
- * then store that ID in the appropriate descriptors and string table.
- *
- * All string identifier should be allocated using this,
- * @usb_string_ids_tab() or @usb_string_ids_n() routine, to ensure
- * that for example different functions don't wrongly assign different
- * meanings to the same identifier.
- */
-int usb_string_id(struct usb_composite_dev *cdev)
-{
-	if (cdev->next_string_id < 254) {
-		/* string id 0 is reserved by USB spec for list of
-		 * supported languages */
-		/* 255 reserved as well? -- mina86 */
-		cdev->next_string_id++;
-		return cdev->next_string_id;
-	}
-	return -ENODEV;
-}
-
-/**
- * usb_string_ids() - allocate unused string IDs in batch
- * @cdev: the device whose string descriptor IDs are being allocated
- * @str: an array of usb_string objects to assign numbers to
- * Context: single threaded during gadget setup
- *
- * @usb_string_ids() is called from bind() callbacks to allocate
- * string IDs.  Drivers for functions, configurations, or gadgets will
- * then copy IDs from the string table to the appropriate descriptors
- * and string table for other languages.
- *
- * All string identifier should be allocated using this,
- * @usb_string_id() or @usb_string_ids_n() routine, to ensure that for
- * example different functions don't wrongly assign different meanings
- * to the same identifier.
- */
-int usb_string_ids_tab(struct usb_composite_dev *cdev, struct usb_string *str)
-{
-	int next = cdev->next_string_id;
-
-	for (; str->s; ++str) {
-		if (unlikely(next >= 254))
-			return -ENODEV;
-		str->id = ++next;
-	}
-
-	cdev->next_string_id = next;
-
-	return 0;
-}
-
-/**
- * usb_string_ids_n() - allocate unused string IDs in batch
- * @c: the device whose string descriptor IDs are being allocated
- * @n: number of string IDs to allocate
- * Context: single threaded during gadget setup
- *
- * Returns the first requested ID.  This ID and next @n-1 IDs are now
- * valid IDs.  At least provided that @n is non-zero because if it
- * is, returns last requested ID which is now very useful information.
- *
- * @usb_string_ids_n() is called from bind() callbacks to allocate
- * string IDs.  Drivers for functions, configurations, or gadgets will
- * then store that ID in the appropriate descriptors and string table.
- *
- * All string identifier should be allocated using this,
- * @usb_string_id() or @usb_string_ids_n() routine, to ensure that for
- * example different functions don't wrongly assign different meanings
- * to the same identifier.
- */
-int usb_string_ids_n(struct usb_composite_dev *c, unsigned n)
-{
-	unsigned next = c->next_string_id;
-	if (unlikely(n > 254 || (unsigned)next + n > 254))
-		return -ENODEV;
-	c->next_string_id += n;
-	return next + 1;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static void composite_setup_complete(struct usb_ep *ep, struct usb_request *req)
-{
-	if (req->status || req->actual != req->length)
-		DBG((struct usb_composite_dev *) ep->driver_data,
-				"setup complete --> %d, %d/%d\n",
-				req->status, req->actual, req->length);
-}
-
-/*
- * The setup() callback implements all the ep0 functionality that's
- * not handled lower down, in hardware or the hardware driver(like
- * device and endpoint feature flags, and their status).  It's all
- * housekeeping for the gadget function we're implementing.  Most of
- * the work is in config and function specific setup.
- */
-static int
-composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
-{
-	struct usb_composite_dev	*cdev = get_gadget_data(gadget);
-	struct usb_request		*req = cdev->req;
-	int				value = -EOPNOTSUPP;
-	int				status = 0;
-	u16				w_index = le16_to_cpu(ctrl->wIndex);
-	u8				intf = w_index & 0xFF;
-	u16				w_value = le16_to_cpu(ctrl->wValue);
-	u16				w_length = le16_to_cpu(ctrl->wLength);
-	struct usb_function		*f = NULL;
-	u8				endp;
-
-	/* partial re-init of the response message; the function or the
-	 * gadget might need to intercept e.g. a control-OUT completion
-	 * when we delegate to it.
-	 */
-	req->zero = 0;
-	req->complete = composite_setup_complete;
-	req->length = 0;
-	gadget->ep0->driver_data = cdev;
-
-	switch (ctrl->bRequest) {
-
-	/* we handle all standard USB descriptors */
-	case USB_REQ_GET_DESCRIPTOR:
-		if (ctrl->bRequestType != USB_DIR_IN)
-			goto unknown;
-		switch (w_value >> 8) {
-
-		case USB_DT_DEVICE:
-			cdev->desc.bNumConfigurations =
-				count_configs(cdev, USB_DT_DEVICE);
-			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);
-					cdev->desc.bMaxPacketSize0 = 9;
-				} 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) ||
-			    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) ||
-			    gadget->speed >= USB_SPEED_SUPER)
-				break;
-			/* FALLTHROUGH */
-		case USB_DT_CONFIG:
-			value = config_desc(cdev, w_value);
-			if (value >= 0)
-				value = min(w_length, (u16) value);
-			break;
-		case USB_DT_STRING:
-			value = get_string(cdev, req->buf,
-					w_index, w_value & 0xff);
-			if (value >= 0)
-				value = min(w_length, (u16) value);
-			break;
-		case USB_DT_BOS:
-			if (gadget_is_superspeed(gadget)) {
-				value = bos_desc(cdev);
-				value = min(w_length, (u16) value);
-			}
-			break;
-		}
-		break;
-
-	/* any number of configs can work */
-	case USB_REQ_SET_CONFIGURATION:
-		if (ctrl->bRequestType != 0)
-			goto unknown;
-		if (gadget_is_otg(gadget)) {
-			if (gadget->a_hnp_support)
-				DBG(cdev, "HNP available\n");
-			else if (gadget->a_alt_hnp_support)
-				DBG(cdev, "HNP on another port\n");
-			else
-				VDBG(cdev, "HNP inactive\n");
-		}
-		spin_lock(&cdev->lock);
-		value = set_config(cdev, ctrl, w_value);
-		spin_unlock(&cdev->lock);
-		break;
-	case USB_REQ_GET_CONFIGURATION:
-		if (ctrl->bRequestType != USB_DIR_IN)
-			goto unknown;
-		if (cdev->config)
-			*(u8 *)req->buf = cdev->config->bConfigurationValue;
-		else
-			*(u8 *)req->buf = 0;
-		value = min(w_length, (u16) 1);
-		break;
-
-	/* function drivers must handle get/set altsetting; if there's
-	 * no get() method, we know only altsetting zero works.
-	 */
-	case USB_REQ_SET_INTERFACE:
-		if (ctrl->bRequestType != USB_RECIP_INTERFACE)
-			goto unknown;
-		if (!cdev->config || intf >= MAX_CONFIG_INTERFACES)
-			break;
-		f = cdev->config->interface[intf];
-		if (!f)
-			break;
-		if (w_value && !f->set_alt)
-			break;
-		value = f->set_alt(f, w_index, w_value);
-		if (value == USB_GADGET_DELAYED_STATUS) {
-			DBG(cdev,
-			 "%s: interface %d (%s) requested delayed status\n",
-					__func__, intf, f->name);
-			cdev->delayed_status++;
-			DBG(cdev, "delayed_status count %d\n",
-					cdev->delayed_status);
-		}
-		break;
-	case USB_REQ_GET_INTERFACE:
-		if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE))
-			goto unknown;
-		if (!cdev->config || intf >= MAX_CONFIG_INTERFACES)
-			break;
-		f = cdev->config->interface[intf];
-		if (!f)
-			break;
-		/* lots of interfaces only need altsetting zero... */
-		value = f->get_alt ? f->get_alt(f, w_index) : 0;
-		if (value < 0)
-			break;
-		*((u8 *)req->buf) = value;
-		value = min(w_length, (u16) 1);
-		break;
-
-	/*
-	 * 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,
-			"non-core control req%02x.%02x v%04x i%04x l%d\n",
-			ctrl->bRequestType, ctrl->bRequest,
-			w_value, w_index, w_length);
-
-		/* functions always handle their interfaces and endpoints...
-		 * punt other recipients (other, WUSB, ...) to the current
-		 * configuration code.
-		 *
-		 * REVISIT it could make sense to let the composite device
-		 * take such requests too, if that's ever needed:  to work
-		 * in config 0, etc.
-		 */
-		switch (ctrl->bRequestType & USB_RECIP_MASK) {
-		case USB_RECIP_INTERFACE:
-			if (!cdev->config || intf >= MAX_CONFIG_INTERFACES)
-				break;
-			f = cdev->config->interface[intf];
-			break;
-
-		case USB_RECIP_ENDPOINT:
-			endp = ((w_index & 0x80) >> 3) | (w_index & 0x0f);
-			list_for_each_entry(f, &cdev->config->functions, list) {
-				if (test_bit(endp, f->endpoints))
-					break;
-			}
-			if (&f->list == &cdev->config->functions)
-				f = NULL;
-			break;
-		}
-
-		if (f && f->setup)
-			value = f->setup(f, ctrl);
-		else {
-			struct usb_configuration	*c;
-
-			c = cdev->config;
-			if (c && c->setup)
-				value = c->setup(c, ctrl);
-		}
-
-		goto done;
-	}
-
-	/* respond with data transfer before status phase? */
-	if (value >= 0 && value != USB_GADGET_DELAYED_STATUS) {
-		req->length = value;
-		req->zero = value < w_length;
-		value = usb_ep_queue(gadget->ep0, req, GFP_ATOMIC);
-		if (value < 0) {
-			DBG(cdev, "ep_queue --> %d\n", value);
-			req->status = 0;
-			composite_setup_complete(gadget->ep0, req);
-		}
-	} else if (value == USB_GADGET_DELAYED_STATUS && w_length != 0) {
-		WARN(cdev,
-			"%s: Delayed status not supported for w_length != 0",
-			__func__);
-	}
-
-done:
-	/* device either stalls (value < 0) or reports success */
-	return value;
-}
-
-static void composite_disconnect(struct usb_gadget *gadget)
-{
-	struct usb_composite_dev	*cdev = get_gadget_data(gadget);
-	unsigned long			flags;
-
-	/* REVISIT:  should we have config and device level
-	 * disconnect callbacks?
-	 */
-	spin_lock_irqsave(&cdev->lock, flags);
-	if (cdev->config)
-		reset_config(cdev);
-	if (composite->disconnect)
-		composite->disconnect(cdev);
-	spin_unlock_irqrestore(&cdev->lock, flags);
-}
-
-/*-------------------------------------------------------------------------*/
-
-static ssize_t composite_show_suspended(struct device *dev,
-					struct device_attribute *attr,
-					char *buf)
-{
-	struct usb_gadget *gadget = dev_to_usb_gadget(dev);
-	struct usb_composite_dev *cdev = get_gadget_data(gadget);
-
-	return sprintf(buf, "%d\n", cdev->suspended);
-}
-
-static DEVICE_ATTR(suspended, 0444, composite_show_suspended, NULL);
-
-static void
-composite_unbind(struct usb_gadget *gadget)
-{
-	struct usb_composite_dev	*cdev = get_gadget_data(gadget);
-
-	/* composite_disconnect() must already have been called
-	 * by the underlying peripheral controller driver!
-	 * so there's no i/o concurrency that could affect the
-	 * state protected by cdev->lock.
-	 */
-	WARN_ON(cdev->config);
-
-	while (!list_empty(&cdev->configs)) {
-		struct usb_configuration	*c;
-		c = list_first_entry(&cdev->configs,
-				struct usb_configuration, list);
-		remove_config(cdev, c);
-	}
-	if (composite->unbind)
-		composite->unbind(cdev);
-
-	if (cdev->req) {
-		kfree(cdev->req->buf);
-		usb_ep_free_request(gadget->ep0, cdev->req);
-	}
-	device_remove_file(&gadget->dev, &dev_attr_suspended);
-	kfree(cdev);
-	set_gadget_data(gadget, NULL);
-	composite = NULL;
-}
-
-static u8 override_id(struct usb_composite_dev *cdev, u8 *desc)
-{
-	if (!*desc) {
-		int ret = usb_string_id(cdev);
-		if (unlikely(ret < 0))
-			WARNING(cdev, "failed to override string ID\n");
-		else
-			*desc = ret;
-	}
-
-	return *desc;
-}
-
-static int composite_bind(struct usb_gadget *gadget,
-		struct usb_gadget_driver *driver)
-{
-	struct usb_composite_dev	*cdev;
-	int				status = -ENOMEM;
-
-	cdev = kzalloc(sizeof *cdev, GFP_KERNEL);
-	if (!cdev)
-		return status;
-
-	spin_lock_init(&cdev->lock);
-	cdev->gadget = gadget;
-	set_gadget_data(gadget, cdev);
-	INIT_LIST_HEAD(&cdev->configs);
-
-	/* preallocate control response and buffer */
-	cdev->req = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL);
-	if (!cdev->req)
-		goto fail;
-	cdev->req->buf = kmalloc(USB_BUFSIZ, GFP_KERNEL);
-	if (!cdev->req->buf)
-		goto fail;
-	cdev->req->complete = composite_setup_complete;
-	gadget->ep0->driver_data = cdev;
-
-	cdev->bufsiz = USB_BUFSIZ;
-	cdev->driver = composite;
-
-	/*
-	 * As per USB compliance update, a device that is actively drawing
-	 * more than 100mA from USB must report itself as bus-powered in
-	 * the GetStatus(DEVICE) call.
-	 */
-	if (CONFIG_USB_GADGET_VBUS_DRAW <= USB_SELF_POWER_VBUS_MAX_DRAW)
-		usb_gadget_set_selfpowered(gadget);
-
-	/* interface and string IDs start at zero via kzalloc.
-	 * we force endpoints to start unassigned; few controller
-	 * drivers will zero ep->driver_data.
-	 */
-	usb_ep_autoconfig_reset(cdev->gadget);
-
-	/* composite gadget needs to assign strings for whole device (like
-	 * serial number), register function drivers, potentially update
-	 * power state and consumption, etc
-	 */
-	status = composite->bind(cdev);
-	if (status < 0)
-		goto fail;
-
-	cdev->desc = *composite->dev;
-
-	/* standardized runtime overrides for device ID data */
-	if (idVendor)
-		cdev->desc.idVendor = cpu_to_le16(idVendor);
-	else
-		idVendor = le16_to_cpu(cdev->desc.idVendor);
-	if (idProduct)
-		cdev->desc.idProduct = cpu_to_le16(idProduct);
-	else
-		idProduct = le16_to_cpu(cdev->desc.idProduct);
-	if (bcdDevice)
-		cdev->desc.bcdDevice = cpu_to_le16(bcdDevice);
-	else
-		bcdDevice = le16_to_cpu(cdev->desc.bcdDevice);
-
-	/* string overrides */
-	if (iManufacturer || !cdev->desc.iManufacturer) {
-		if (!iManufacturer && !composite->iManufacturer &&
-		    !*composite_manufacturer)
-			snprintf(composite_manufacturer,
-				 sizeof composite_manufacturer,
-				 "%s %s with %s",
-				 init_utsname()->sysname,
-				 init_utsname()->release,
-				 gadget->name);
-
-		cdev->manufacturer_override =
-			override_id(cdev, &cdev->desc.iManufacturer);
-	}
-
-	if (iProduct || (!cdev->desc.iProduct && composite->iProduct))
-		cdev->product_override =
-			override_id(cdev, &cdev->desc.iProduct);
-
-	if (iSerialNumber ||
-	    (!cdev->desc.iSerialNumber && composite->iSerialNumber))
-		cdev->serial_override =
-			override_id(cdev, &cdev->desc.iSerialNumber);
-
-	/* has userspace failed to provide a serial number? */
-	if (composite->needs_serial && !cdev->desc.iSerialNumber)
-		WARNING(cdev, "userspace failed to provide iSerialNumber\n");
-
-	/* finish up */
-	status = device_create_file(&gadget->dev, &dev_attr_suspended);
-	if (status)
-		goto fail;
-
-	INFO(cdev, "%s ready\n", composite->name);
-	return 0;
-
-fail:
-	composite_unbind(gadget);
-	return status;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void
-composite_suspend(struct usb_gadget *gadget)
-{
-	struct usb_composite_dev	*cdev = get_gadget_data(gadget);
-	struct usb_function		*f;
-
-	/* REVISIT:  should we have config level
-	 * suspend/resume callbacks?
-	 */
-	DBG(cdev, "suspend\n");
-	if (cdev->config) {
-		list_for_each_entry(f, &cdev->config->functions, list) {
-			if (f->suspend)
-				f->suspend(f);
-		}
-	}
-	if (composite->suspend)
-		composite->suspend(cdev);
-
-	cdev->suspended = 1;
-
-	usb_gadget_vbus_draw(gadget, 2);
-}
-
-static void
-composite_resume(struct usb_gadget *gadget)
-{
-	struct usb_composite_dev	*cdev = get_gadget_data(gadget);
-	struct usb_function		*f;
-	u8				maxpower;
-
-	/* REVISIT:  should we have config level
-	 * suspend/resume callbacks?
-	 */
-	DBG(cdev, "resume\n");
-	if (composite->resume)
-		composite->resume(cdev);
-	if (cdev->config) {
-		list_for_each_entry(f, &cdev->config->functions, list) {
-			if (f->resume)
-				f->resume(f);
-		}
-
-		maxpower = cdev->config->bMaxPower;
-
-		usb_gadget_vbus_draw(gadget, maxpower ?
-			(2 * maxpower) : CONFIG_USB_GADGET_VBUS_DRAW);
-	}
-
-	cdev->suspended = 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static struct usb_gadget_driver composite_driver = {
-	.bind		= composite_bind,
-	.unbind		= composite_unbind,
-
-	.setup		= composite_setup,
-	.disconnect	= composite_disconnect,
-
-	.suspend	= composite_suspend,
-	.resume		= composite_resume,
-
-	.driver	= {
-		.owner		= THIS_MODULE,
-	},
-};
-
-/**
- * usb_composite_probe() - register a composite driver
- * @driver: the driver to register
- * @bind: the callback used to allocate resources that are shared across the
- *	whole device, such as string IDs, and add its configurations using
- *	@usb_add_config().  This may fail by returning a negative errno
- *	value; it should return zero on successful initialization.
- * Context: single threaded during gadget setup
- *
- * This function is used to register drivers using the composite driver
- * framework.  The return value is zero, or a negative errno value.
- * Those values normally come from the driver's @bind method, which does
- * all the work of setting up the driver to match the hardware.
- *
- * On successful return, the gadget is ready to respond to requests from
- * the host, unless one of its components invokes usb_gadget_disconnect()
- * while it was binding.  That would usually be done in order to wait for
- * some userspace participation.
- */
-int usb_composite_probe(struct usb_composite_driver *driver)
-{
-	if (!driver || !driver->dev || composite || !driver->bind)
-		return -EINVAL;
-
-	if (!driver->name)
-		driver->name = "composite";
-	if (!driver->iProduct)
-		driver->iProduct = driver->name;
-	composite_driver.function =  (char *) driver->name;
-	composite_driver.driver.name = driver->name;
-	composite_driver.max_speed = driver->max_speed;
-	composite = driver;
-
-	return usb_gadget_probe_driver(&composite_driver);
-}
-
-/**
- * usb_composite_unregister() - unregister a composite driver
- * @driver: the driver to unregister
- *
- * This function is used to unregister drivers using the composite
- * driver framework.
- */
-void usb_composite_unregister(struct usb_composite_driver *driver)
-{
-	if (composite != driver)
-		return;
-	usb_gadget_unregister_driver(&composite_driver);
-}
-
-/**
- * usb_composite_setup_continue() - Continue with the control transfer
- * @cdev: the composite device who's control transfer was kept waiting
- *
- * This function must be called by the USB function driver to continue
- * with the control transfer's data/status stage in case it had requested to
- * delay the data/status stages. A USB function's setup handler (e.g. set_alt())
- * can request the composite framework to delay the setup request's data/status
- * stages by returning USB_GADGET_DELAYED_STATUS.
- */
-void usb_composite_setup_continue(struct usb_composite_dev *cdev)
-{
-	int			value;
-	struct usb_request	*req = cdev->req;
-	unsigned long		flags;
-
-	DBG(cdev, "%s\n", __func__);
-	spin_lock_irqsave(&cdev->lock, flags);
-
-	if (cdev->delayed_status == 0) {
-		WARN(cdev, "%s: Unexpected call\n", __func__);
-
-	} else if (--cdev->delayed_status == 0) {
-		DBG(cdev, "%s: Completing delayed status\n", __func__);
-		req->length = 0;
-		value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);
-		if (value < 0) {
-			DBG(cdev, "ep_queue --> %d\n", value);
-			req->status = 0;
-			composite_setup_complete(cdev->gadget->ep0, req);
-		}
-	}
-
-	spin_unlock_irqrestore(&cdev->lock, flags);
-}
-
diff --git a/drivers/staging/ccg/composite.h b/drivers/staging/ccg/composite.h
deleted file mode 100644
index 19a5adf..0000000
--- a/drivers/staging/ccg/composite.h
+++ /dev/null
@@ -1,395 +0,0 @@
-/*
- * composite.h -- framework for usb gadgets which are composite devices
- *
- * Copyright (C) 2006-2008 David Brownell
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#ifndef	__LINUX_USB_COMPOSITE_H
-#define	__LINUX_USB_COMPOSITE_H
-
-/*
- * This framework is an optional layer on top of the USB Gadget interface,
- * making it easier to build (a) Composite devices, supporting multiple
- * functions within any single configuration, and (b) Multi-configuration
- * devices, also supporting multiple functions but without necessarily
- * having more than one function per configuration.
- *
- * Example:  a device with a single configuration supporting both network
- * link and mass storage functions is a composite device.  Those functions
- * might alternatively be packaged in individual configurations, but in
- * the composite model the host can use both functions at the same time.
- */
-
-#include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
-
-/*
- * USB function drivers should return USB_GADGET_DELAYED_STATUS if they
- * wish to delay the data/status stages of the control transfer till they
- * are ready. The control transfer will then be kept from completing till
- * all the function drivers that requested for USB_GADGET_DELAYED_STAUS
- * invoke usb_composite_setup_continue().
- */
-#define USB_GADGET_DELAYED_STATUS       0x7fff	/* Impossibly large value */
-
-struct usb_configuration;
-
-/**
- * struct usb_function - describes one function of a configuration
- * @name: For diagnostics, identifies the function.
- * @strings: tables of strings, keyed by identifiers assigned during bind()
- *	and by language IDs provided in control requests
- * @descriptors: Table of full (or low) speed descriptors, using interface and
- *	string identifiers assigned during @bind().  If this pointer is null,
- *	the function will not be available at full speed (or at low speed).
- * @hs_descriptors: Table of high speed descriptors, using interface and
- *	string identifiers assigned during @bind().  If this pointer is null,
- *	the function will not be available at high speed.
- * @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
- *	available resources including string and interface identifiers used
- *	in interface or class descriptors; endpoints; I/O buffers; and so on.
- * @unbind: Reverses @bind; called as a side effect of unregistering the
- *	driver which added this function.
- * @set_alt: (REQUIRED) Reconfigures altsettings; function drivers may
- *	initialize usb_ep.driver data at this time (when it is used).
- *	Note that setting an interface to its current altsetting resets
- *	interface state, and that all interfaces have a disabled state.
- * @get_alt: Returns the active altsetting.  If this is not provided,
- *	then only altsetting zero is supported.
- * @disable: (REQUIRED) Indicates the function should be disabled.  Reasons
- *	include host resetting or reconfiguring the gadget, and disconnection.
- * @setup: Used for interface-specific control requests.
- * @suspend: Notifies functions when the host stops sending USB traffic.
- * @resume: Notifies functions when the host restarts USB traffic.
- * @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
- * associated by @usb_add_function() with a one configuration; that function
- * causes @bind() to be called so resources can be allocated as part of
- * setting up a gadget driver.  Those resources include endpoints, which
- * should be allocated using @usb_ep_autoconfig().
- *
- * To support dual speed operation, a function driver provides descriptors
- * for both high and full speed operation.  Except in rare cases that don't
- * involve bulk endpoints, each speed needs different endpoint descriptors.
- *
- * Function drivers choose their own strategies for managing instance data.
- * The simplest strategy just declares it "static', which means the function
- * can only be activated once.  If the function needs to be exposed in more
- * than one configuration at a given speed, it needs to support multiple
- * usb_function structures (one for each configuration).
- *
- * A more complex strategy might encapsulate a @usb_function structure inside
- * a driver-specific instance structure to allows multiple activations.  An
- * example of multiple activations might be a CDC ACM function that supports
- * two or more distinct instances within the same configuration, providing
- * several independent logical data links to a USB host.
- */
-struct usb_function {
-	const char			*name;
-	struct usb_gadget_strings	**strings;
-	struct usb_descriptor_header	**descriptors;
-	struct usb_descriptor_header	**hs_descriptors;
-	struct usb_descriptor_header	**ss_descriptors;
-
-	struct usb_configuration	*config;
-
-	/* REVISIT:  bind() functions can be marked __init, which
-	 * makes trouble for section mismatch analysis.  See if
-	 * we can't restructure things to avoid mismatching.
-	 * Related:  unbind() may kfree() but bind() won't...
-	 */
-
-	/* configuration management:  bind/unbind */
-	int			(*bind)(struct usb_configuration *,
-					struct usb_function *);
-	void			(*unbind)(struct usb_configuration *,
-					struct usb_function *);
-
-	/* runtime state management */
-	int			(*set_alt)(struct usb_function *,
-					unsigned interface, unsigned alt);
-	int			(*get_alt)(struct usb_function *,
-					unsigned interface);
-	void			(*disable)(struct usb_function *);
-	int			(*setup)(struct usb_function *,
-					const struct usb_ctrlrequest *);
-	void			(*suspend)(struct usb_function *);
-	void			(*resume)(struct usb_function *);
-
-	/* 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;
-	DECLARE_BITMAP(endpoints, 32);
-};
-
-int usb_add_function(struct usb_configuration *, struct usb_function *);
-
-int usb_function_deactivate(struct usb_function *);
-int usb_function_activate(struct usb_function *);
-
-int usb_interface_id(struct usb_configuration *, struct usb_function *);
-
-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 */
-
-/**
- * struct usb_configuration - represents one gadget configuration
- * @label: For diagnostics, describes the configuration.
- * @strings: Tables of strings, keyed by identifiers assigned during @bind()
- *	and by language IDs provided in control requests.
- * @descriptors: Table of descriptors preceding all function descriptors.
- *	Examples include OTG and vendor-specific descriptors.
- * @unbind: Reverses @bind; called as a side effect of unregistering the
- *	driver which added this configuration.
- * @setup: Used to delegate control requests that aren't handled by standard
- *	device infrastructure or directed at a specific interface.
- * @bConfigurationValue: Copied into configuration descriptor.
- * @iConfiguration: Copied into configuration descriptor.
- * @bmAttributes: Copied into configuration descriptor.
- * @bMaxPower: Copied into configuration descriptor.
- * @cdev: assigned by @usb_add_config() before calling @bind(); this is
- *	the device associated with this configuration.
- *
- * Configurations are building blocks for gadget drivers structured around
- * function drivers.  Simple USB gadgets require only one function and one
- * configuration, and handle dual-speed hardware by always providing the same
- * functionality.  Slightly more complex gadgets may have more than one
- * single-function configuration at a given speed; or have configurations
- * that only work at one speed.
- *
- * Composite devices are, by definition, ones with configurations which
- * include more than one function.
- *
- * The lifecycle of a usb_configuration includes allocation, initialization
- * of the fields described above, and calling @usb_add_config() to set up
- * internal data and bind it to a specific device.  The configuration's
- * @bind() method is then used to initialize all the functions and then
- * call @usb_add_function() for them.
- *
- * Those functions would normally be independent of each other, but that's
- * not mandatory.  CDC WMC devices are an example where functions often
- * depend on other functions, with some functions subsidiary to others.
- * Such interdependency may be managed in any way, so long as all of the
- * descriptors complete by the time the composite driver returns from
- * its bind() routine.
- */
-struct usb_configuration {
-	const char			*label;
-	struct usb_gadget_strings	**strings;
-	const struct usb_descriptor_header **descriptors;
-
-	/* REVISIT:  bind() functions can be marked __init, which
-	 * makes trouble for section mismatch analysis.  See if
-	 * we can't restructure things to avoid mismatching...
-	 */
-
-	/* configuration management: unbind/setup */
-	void			(*unbind)(struct usb_configuration *);
-	int			(*setup)(struct usb_configuration *,
-					const struct usb_ctrlrequest *);
-
-	/* fields in the config descriptor */
-	u8			bConfigurationValue;
-	u8			iConfiguration;
-	u8			bmAttributes;
-	u8			bMaxPower;
-
-	struct usb_composite_dev	*cdev;
-
-	/* private: */
-	/* internals */
-	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];
-};
-
-int usb_add_config(struct usb_composite_dev *,
-		struct usb_configuration *,
-		int (*)(struct usb_configuration *));
-
-void usb_remove_config(struct usb_composite_dev *,
-		struct usb_configuration *);
-
-/**
- * struct usb_composite_driver - groups configurations into a gadget
- * @name: For diagnostics, identifies the driver.
- * @iProduct: Used as iProduct override if @dev->iProduct is not set.
- *	If NULL value of @name is taken.
- * @iManufacturer: Used as iManufacturer override if @dev->iManufacturer is
- *	not set. If NULL a default "<system> <release> with <udc>" value
- *	will be used.
- * @iSerialNumber: Used as iSerialNumber override if @dev->iSerialNumber is
- *	not set.
- * @dev: Template descriptor for the device, including default device
- *	identifiers.
- * @strings: tables of strings, keyed by identifiers assigned during @bind
- *	and language IDs provided in control requests
- * @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.
- * @bind: (REQUIRED) Used to allocate resources that are shared across the
- *	whole device, such as string IDs, and add its configurations using
- *	@usb_add_config(). This may fail by returning a negative errno
- *	value; it should return zero on successful initialization.
- * @unbind: Reverses @bind; called as a side effect of unregistering
- *	this driver.
- * @disconnect: optional driver disconnect method
- * @suspend: Notifies when the host stops sending USB traffic,
- *	after function notifications
- * @resume: Notifies configuration when the host restarts USB traffic,
- *	before function notifications
- *
- * Devices default to reporting self powered operation.  Devices which rely
- * on bus powered operation should report this in their @bind method.
- *
- * Before returning from @bind, various fields in the template descriptor
- * may be overridden.  These include the idVendor/idProduct/bcdDevice values
- * normally to bind the appropriate host side driver, and the three strings
- * (iManufacturer, iProduct, iSerialNumber) normally used to provide user
- * meaningful device identifiers.  (The strings will not be defined unless
- * they are defined in @dev and @strings.)  The correct ep0 maxpacket size
- * is also reported, as defined by the underlying controller driver.
- */
-struct usb_composite_driver {
-	const char				*name;
-	const char				*iProduct;
-	const char				*iManufacturer;
-	const char				*iSerialNumber;
-	const struct usb_device_descriptor	*dev;
-	struct usb_gadget_strings		**strings;
-	enum usb_device_speed			max_speed;
-	unsigned		needs_serial:1;
-
-	int			(*bind)(struct usb_composite_dev *cdev);
-	int			(*unbind)(struct usb_composite_dev *);
-
-	void			(*disconnect)(struct usb_composite_dev *);
-
-	/* global suspend hooks */
-	void			(*suspend)(struct usb_composite_dev *);
-	void			(*resume)(struct usb_composite_dev *);
-};
-
-extern int usb_composite_probe(struct usb_composite_driver *driver);
-extern void usb_composite_unregister(struct usb_composite_driver *driver);
-extern void usb_composite_setup_continue(struct usb_composite_dev *cdev);
-
-
-/**
- * struct usb_composite_device - represents one composite usb gadget
- * @gadget: read-only, abstracts the gadget's usb peripheral controller
- * @req: used for control responses; buffer is pre-allocated
- * @bufsiz: size of buffer pre-allocated in @req
- * @config: the currently active configuration
- *
- * One of these devices is allocated and initialized before the
- * associated device driver's bind() is called.
- *
- * OPEN ISSUE:  it appears that some WUSB devices will need to be
- * built by combining a normal (wired) gadget with a wireless one.
- * This revision of the gadget framework should probably try to make
- * sure doing that won't hurt too much.
- *
- * One notion for how to handle Wireless USB devices involves:
- * (a) a second gadget here, discovery mechanism TBD, but likely
- *     needing separate "register/unregister WUSB gadget" calls;
- * (b) updates to usb_gadget to include flags "is it wireless",
- *     "is it wired", plus (presumably in a wrapper structure)
- *     bandgroup and PHY info;
- * (c) presumably a wireless_ep wrapping a usb_ep, and reporting
- *     wireless-specific parameters like maxburst and maxsequence;
- * (d) configurations that are specific to wireless links;
- * (e) function drivers that understand wireless configs and will
- *     support wireless for (additional) function instances;
- * (f) a function to support association setup (like CBAF), not
- *     necessarily requiring a wireless adapter;
- * (g) composite device setup that can create one or more wireless
- *     configs, including appropriate association setup support;
- * (h) more, TBD.
- */
-struct usb_composite_dev {
-	struct usb_gadget		*gadget;
-	struct usb_request		*req;
-	unsigned			bufsiz;
-
-	struct usb_configuration	*config;
-
-	/* private: */
-	/* internals */
-	unsigned int			suspended:1;
-	struct usb_device_descriptor	desc;
-	struct list_head		configs;
-	struct usb_composite_driver	*driver;
-	u8				next_string_id;
-	u8				manufacturer_override;
-	u8				product_override;
-	u8				serial_override;
-
-	/* the gadget driver won't enable the data pullup
-	 * while the deactivation count is nonzero.
-	 */
-	unsigned			deactivations;
-
-	/* the composite driver won't complete the control transfer's
-	 * data/status stages till delayed_status is zero.
-	 */
-	int				delayed_status;
-
-	/* protects deactivations and delayed_status counts*/
-	spinlock_t			lock;
-};
-
-extern int usb_string_id(struct usb_composite_dev *c);
-extern int usb_string_ids_tab(struct usb_composite_dev *c,
-			      struct usb_string *str);
-extern int usb_string_ids_n(struct usb_composite_dev *c, unsigned n);
-
-
-/* messaging utils */
-#define DBG(d, fmt, args...) \
-	dev_dbg(&(d)->gadget->dev , fmt , ## args)
-#define VDBG(d, fmt, args...) \
-	dev_vdbg(&(d)->gadget->dev , fmt , ## args)
-#define ERROR(d, fmt, args...) \
-	dev_err(&(d)->gadget->dev , fmt , ## args)
-#define WARNING(d, fmt, args...) \
-	dev_warn(&(d)->gadget->dev , fmt , ## args)
-#define INFO(d, fmt, args...) \
-	dev_info(&(d)->gadget->dev , fmt , ## args)
-
-#endif	/* __LINUX_USB_COMPOSITE_H */
diff --git a/drivers/staging/ccg/config.c b/drivers/staging/ccg/config.c
deleted file mode 100644
index 7542a72..0000000
--- a/drivers/staging/ccg/config.c
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * usb/gadget/config.c -- simplify building config descriptors
- *
- * 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.
- */
-
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/string.h>
-#include <linux/device.h>
-
-#include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
-
-
-/**
- * usb_descriptor_fillbuf - fill buffer with descriptors
- * @buf: Buffer to be filled
- * @buflen: Size of buf
- * @src: Array of descriptor pointers, terminated by null pointer.
- *
- * Copies descriptors into the buffer, returning the length or a
- * negative error code if they can't all be copied.  Useful when
- * assembling descriptors for an associated set of interfaces used
- * as part of configuring a composite device; or in other cases where
- * sets of descriptors need to be marshaled.
- */
-int
-usb_descriptor_fillbuf(void *buf, unsigned buflen,
-		const struct usb_descriptor_header **src)
-{
-	u8	*dest = buf;
-
-	if (!src)
-		return -EINVAL;
-
-	/* fill buffer from src[] until null descriptor ptr */
-	for (; NULL != *src; src++) {
-		unsigned		len = (*src)->bLength;
-
-		if (len > buflen)
-			return -EINVAL;
-		memcpy(dest, *src, len);
-		buflen -= len;
-		dest += len;
-	}
-	return dest - (u8 *)buf;
-}
-
-
-/**
- * usb_gadget_config_buf - builts a complete configuration descriptor
- * @config: Header for the descriptor, including characteristics such
- *	as power requirements and number of interfaces.
- * @desc: Null-terminated vector of pointers to the descriptors (interface,
- *	endpoint, etc) defining all functions in this device configuration.
- * @buf: Buffer for the resulting configuration descriptor.
- * @length: Length of buffer.  If this is not big enough to hold the
- *	entire configuration descriptor, an error code will be returned.
- *
- * This copies descriptors into the response buffer, building a descriptor
- * for that configuration.  It returns the buffer length or a negative
- * status code.  The config.wTotalLength field is set to match the length
- * of the result, but other descriptor fields (including power usage and
- * interface count) must be set by the caller.
- *
- * Gadget drivers could use this when constructing a config descriptor
- * in response to USB_REQ_GET_DESCRIPTOR.  They will need to patch the
- * resulting bDescriptorType value if USB_DT_OTHER_SPEED_CONFIG is needed.
- */
-int usb_gadget_config_buf(
-	const struct usb_config_descriptor	*config,
-	void					*buf,
-	unsigned				length,
-	const struct usb_descriptor_header	**desc
-)
-{
-	struct usb_config_descriptor		*cp = buf;
-	int					len;
-
-	/* config descriptor first */
-	if (length < USB_DT_CONFIG_SIZE || !desc)
-		return -EINVAL;
-	*cp = *config;
-
-	/* then interface/endpoint/class/vendor/... */
-	len = usb_descriptor_fillbuf(USB_DT_CONFIG_SIZE + (u8*)buf,
-			length - USB_DT_CONFIG_SIZE, desc);
-	if (len < 0)
-		return len;
-	len += USB_DT_CONFIG_SIZE;
-	if (len > 0xffff)
-		return -EINVAL;
-
-	/* patch up the config descriptor */
-	cp->bLength = USB_DT_CONFIG_SIZE;
-	cp->bDescriptorType = USB_DT_CONFIG;
-	cp->wTotalLength = cpu_to_le16(len);
-	cp->bmAttributes |= USB_CONFIG_ATT_ONE;
-	return len;
-}
-
-/**
- * usb_copy_descriptors - copy a vector of USB descriptors
- * @src: null-terminated vector to copy
- * Context: initialization code, which may sleep
- *
- * This makes a copy of a vector of USB descriptors.  Its primary use
- * is to support usb_function objects which can have multiple copies,
- * each needing different descriptors.  Functions may have static
- * tables of descriptors, which are used as templates and customized
- * with identifiers (for interfaces, strings, endpoints, and more)
- * as needed by a given function instance.
- */
-struct usb_descriptor_header **
-usb_copy_descriptors(struct usb_descriptor_header **src)
-{
-	struct usb_descriptor_header **tmp;
-	unsigned bytes;
-	unsigned n_desc;
-	void *mem;
-	struct usb_descriptor_header **ret;
-
-	/* count descriptors and their sizes; then add vector size */
-	for (bytes = 0, n_desc = 0, tmp = src; *tmp; tmp++, n_desc++)
-		bytes += (*tmp)->bLength;
-	bytes += (n_desc + 1) * sizeof(*tmp);
-
-	mem = kmalloc(bytes, GFP_KERNEL);
-	if (!mem)
-		return NULL;
-
-	/* fill in pointers starting at "tmp",
-	 * to descriptors copied starting at "mem";
-	 * and return "ret"
-	 */
-	tmp = mem;
-	ret = mem;
-	mem += (n_desc + 1) * sizeof(*tmp);
-	while (*src) {
-		memcpy(mem, *src, (*src)->bLength);
-		*tmp = mem;
-		tmp++;
-		mem += (*src)->bLength;
-		src++;
-	}
-	*tmp = NULL;
-
-	return ret;
-}
-
diff --git a/drivers/staging/ccg/epautoconf.c b/drivers/staging/ccg/epautoconf.c
deleted file mode 100644
index 51f3d42..0000000
--- a/drivers/staging/ccg/epautoconf.c
+++ /dev/null
@@ -1,393 +0,0 @@
-/*
- * epautoconf.c -- endpoint autoconfiguration for usb gadget drivers
- *
- * Copyright (C) 2004 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.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/device.h>
-
-#include <linux/ctype.h>
-#include <linux/string.h>
-
-#include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
-
-#include "gadget_chips.h"
-
-
-/* we must assign addresses for configurable endpoints (like net2280) */
-static unsigned epnum;
-
-// #define MANY_ENDPOINTS
-#ifdef MANY_ENDPOINTS
-/* more than 15 configurable endpoints */
-static unsigned in_epnum;
-#endif
-
-
-/*
- * This should work with endpoints from controller drivers sharing the
- * same endpoint naming convention.  By example:
- *
- *	- ep1, ep2, ... address is fixed, not direction or type
- *	- ep1in, ep2out, ... address and direction are fixed, not type
- *	- ep1-bulk, ep2-bulk, ... address and type are fixed, not direction
- *	- ep1in-bulk, ep2out-iso, ... all three are fixed
- *	- ep-* ... no functionality restrictions
- *
- * Type suffixes are "-bulk", "-iso", or "-int".  Numbers are decimal.
- * Less common restrictions are implied by gadget_is_*().
- *
- * NOTE:  each endpoint is unidirectional, as specified by its USB
- * descriptor; and isn't specific to a configuration or altsetting.
- */
-static int
-ep_matches (
-	struct usb_gadget		*gadget,
-	struct usb_ep			*ep,
-	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;
-
-	/* only support ep0 for portable CONTROL traffic */
-	type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
-	if (USB_ENDPOINT_XFER_CONTROL == type)
-		return 0;
-
-	/* some other naming convention */
-	if ('e' != ep->name[0])
-		return 0;
-
-	/* type-restriction:  "-iso", "-bulk", or "-int".
-	 * direction-restriction:  "in", "out".
-	 */
-	if ('-' != ep->name[2]) {
-		tmp = strrchr (ep->name, '-');
-		if (tmp) {
-			switch (type) {
-			case USB_ENDPOINT_XFER_INT:
-				/* bulk endpoints handle interrupt transfers,
-				 * except the toggle-quirky iso-synch kind
-				 */
-				if ('s' == tmp[2])	// == "-iso"
-					return 0;
-				/* for now, avoid PXA "interrupt-in";
-				 * it's documented as never using DATA1.
-				 */
-				if (gadget_is_pxa (gadget)
-						&& 'i' == tmp [1])
-					return 0;
-				break;
-			case USB_ENDPOINT_XFER_BULK:
-				if ('b' != tmp[1])	// != "-bulk"
-					return 0;
-				break;
-			case USB_ENDPOINT_XFER_ISOC:
-				if ('s' != tmp[2])	// != "-iso"
-					return 0;
-			}
-		} else {
-			tmp = ep->name + strlen (ep->name);
-		}
-
-		/* direction-restriction:  "..in-..", "out-.." */
-		tmp--;
-		if (!isdigit (*tmp)) {
-			if (desc->bEndpointAddress & USB_DIR_IN) {
-				if ('n' != *tmp)
-					return 0;
-			} else {
-				if ('t' != *tmp)
-					return 0;
-			}
-		}
-	}
-
-	/*
-	 * 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 && gadget->max_speed >= USB_SPEED_SUPER) {
-			num_req_streams = ep_comp->bmAttributes & 0x1f;
-			if (num_req_streams > ep->max_streams)
-				return 0;
-		}
-
-	}
-
-	/*
-	 * If the protocol driver hasn't yet decided on wMaxPacketSize
-	 * and wants to know the maximum possible, provide the info.
-	 */
-	if (desc->wMaxPacketSize == 0)
-		desc->wMaxPacketSize = cpu_to_le16(ep->maxpacket);
-
-	/* endpoint maxpacket size is an input parameter, except for bulk
-	 * where it's an output parameter representing the full speed limit.
-	 * the usb spec fixes high speed bulk maxpacket at 512 bytes.
-	 */
-	max = 0x7ff & usb_endpoint_maxp(desc);
-	switch (type) {
-	case USB_ENDPOINT_XFER_INT:
-		/* INT:  limit 64 bytes full speed, 1024 high/super speed */
-		if (!gadget_is_dualspeed(gadget) && max > 64)
-			return 0;
-		/* FALLTHROUGH */
-
-	case USB_ENDPOINT_XFER_ISOC:
-		/* ISO:  limit 1023 bytes full speed, 1024 high/super speed */
-		if (ep->maxpacket < max)
-			return 0;
-		if (!gadget_is_dualspeed(gadget) && max > 1023)
-			return 0;
-
-		/* BOTH:  "high bandwidth" works only at high speed */
-		if ((desc->wMaxPacketSize & cpu_to_le16(3<<11))) {
-			if (!gadget_is_dualspeed(gadget))
-				return 0;
-			/* configure your hardware with enough buffering!! */
-		}
-		break;
-	}
-
-	/* MATCH!! */
-
-	/* report address */
-	desc->bEndpointAddress &= USB_DIR_IN;
-	if (isdigit (ep->name [2])) {
-		u8	num = simple_strtoul (&ep->name [2], NULL, 10);
-		desc->bEndpointAddress |= num;
-#ifdef	MANY_ENDPOINTS
-	} else if (desc->bEndpointAddress & USB_DIR_IN) {
-		if (++in_epnum > 15)
-			return 0;
-		desc->bEndpointAddress = USB_DIR_IN | in_epnum;
-#endif
-	} else {
-		if (++epnum > 15)
-			return 0;
-		desc->bEndpointAddress |= epnum;
-	}
-
-	/* report (variable) full speed bulk maxpacket */
-	if ((USB_ENDPOINT_XFER_BULK == type) && !ep_comp) {
-		int size = ep->maxpacket;
-
-		/* min() doesn't work on bitfields with gcc-3.5 */
-		if (size > 64)
-			size = 64;
-		desc->wMaxPacketSize = cpu_to_le16(size);
-	}
-	ep->address = desc->bEndpointAddress;
-	return 1;
-}
-
-static struct usb_ep *
-find_ep (struct usb_gadget *gadget, const char *name)
-{
-	struct usb_ep	*ep;
-
-	list_for_each_entry (ep, &gadget->ep_list, ep_list) {
-		if (0 == strcmp (ep->name, name))
-			return ep;
-	}
-	return NULL;
-}
-
-/**
- * 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.
- * @ep_comp: Endpoint companion descriptor, with the required
- *    number of streams. Will be modified when the chosen EP
- *    supports a different number of streams.
- *
- * 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.
- *
- * 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 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_ss(
-	struct usb_gadget		*gadget,
-	struct usb_endpoint_descriptor	*desc,
-	struct usb_ss_ep_comp_descriptor *ep_comp
-)
-{
-	struct usb_ep	*ep;
-	u8		type;
-
-	type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
-
-	/* First, apply chip-specific "best usage" knowledge.
-	 * This might make a good usb_gadget_ops hook ...
-	 */
-	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, ep_comp))
-			goto found_ep;
-		ep = find_ep (gadget, "ep-f");
-		if (ep && ep_matches(gadget, ep, desc, ep_comp))
-			goto found_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_comp))
-				goto found_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_comp))
-				goto found_ep;
-		}
-
-#ifdef CONFIG_BLACKFIN
-	} else if (gadget_is_musbhdrc(gadget)) {
-		if ((USB_ENDPOINT_XFER_BULK == type) ||
-		    (USB_ENDPOINT_XFER_ISOC == type)) {
-			if (USB_DIR_IN & desc->bEndpointAddress)
-				ep = find_ep (gadget, "ep5in");
-			else
-				ep = find_ep (gadget, "ep6out");
-		} else if (USB_ENDPOINT_XFER_INT == type) {
-			if (USB_DIR_IN & desc->bEndpointAddress)
-				ep = find_ep(gadget, "ep1in");
-			else
-				ep = find_ep(gadget, "ep2out");
-		} else
-			ep = NULL;
-		if (ep && ep_matches(gadget, ep, desc, ep_comp))
-			goto found_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, ep_comp))
-			goto found_ep;
-	}
-
-	/* Fail */
-	return NULL;
-found_ep:
-	ep->desc = NULL;
-	ep->comp_desc = NULL;
-	return ep;
-}
-
-/**
- * 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
- *
- * Use this for devices where one configuration may need to assign
- * endpoint resources very differently from the next one.  It clears
- * state such as ep->driver_data and the record of assigned endpoints
- * used by usb_ep_autoconfig().
- */
-void usb_ep_autoconfig_reset (struct usb_gadget *gadget)
-{
-	struct usb_ep	*ep;
-
-	list_for_each_entry (ep, &gadget->ep_list, ep_list) {
-		ep->driver_data = NULL;
-	}
-#ifdef	MANY_ENDPOINTS
-	in_epnum = 0;
-#endif
-	epnum = 0;
-}
-
diff --git a/drivers/staging/ccg/f_acm.c b/drivers/staging/ccg/f_acm.c
deleted file mode 100644
index d672250a..0000000
--- a/drivers/staging/ccg/f_acm.c
+++ /dev/null
@@ -1,814 +0,0 @@
-/*
- * f_acm.c -- USB CDC serial (ACM) function driver
- *
- * Copyright (C) 2003 Al Borchers (alborchers@steinerpoint.com)
- * Copyright (C) 2008 by David Brownell
- * Copyright (C) 2008 by Nokia Corporation
- * Copyright (C) 2009 by Samsung Electronics
- * Author: Michal Nazarewicz (mina86@mina86.com)
- *
- * This software is distributed under the terms of the GNU General
- * Public License ("GPL") as published by the Free Software Foundation,
- * either version 2 of that License or (at your option) any later version.
- */
-
-/* #define VERBOSE_DEBUG */
-
-#include <linux/slab.h>
-#include <linux/kernel.h>
-#include <linux/device.h>
-
-#include "u_serial.h"
-#include "gadget_chips.h"
-
-
-/*
- * This CDC ACM function support just wraps control functions and
- * notifications around the generic serial-over-usb code.
- *
- * Because CDC ACM is standardized by the USB-IF, many host operating
- * systems have drivers for it.  Accordingly, ACM is the preferred
- * interop solution for serial-port type connections.  The control
- * models are often not necessary, and in any case don't do much in
- * this bare-bones implementation.
- *
- * Note that even MS-Windows has some support for ACM.  However, that
- * support is somewhat broken because when you use ACM in a composite
- * device, having multiple interfaces confuses the poor OS.  It doesn't
- * seem to understand CDC Union descriptors.  The new "association"
- * descriptors (roughly equivalent to CDC Unions) may sometimes help.
- */
-
-struct f_acm {
-	struct gserial			port;
-	u8				ctrl_id, data_id;
-	u8				port_num;
-
-	u8				pending;
-
-	/* lock is mostly for pending and notify_req ... they get accessed
-	 * by callbacks both from tty (open/close/break) under its spinlock,
-	 * and notify_req.complete() which can't use that lock.
-	 */
-	spinlock_t			lock;
-
-	struct usb_ep			*notify;
-	struct usb_request		*notify_req;
-
-	struct usb_cdc_line_coding	port_line_coding;	/* 8-N-1 etc */
-
-	/* SetControlLineState request -- CDC 1.1 section 6.2.14 (INPUT) */
-	u16				port_handshake_bits;
-#define ACM_CTRL_RTS	(1 << 1)	/* unused with full duplex */
-#define ACM_CTRL_DTR	(1 << 0)	/* host is ready for data r/w */
-
-	/* SerialState notification -- CDC 1.1 section 6.3.5 (OUTPUT) */
-	u16				serial_state;
-#define ACM_CTRL_OVERRUN	(1 << 6)
-#define ACM_CTRL_PARITY		(1 << 5)
-#define ACM_CTRL_FRAMING	(1 << 4)
-#define ACM_CTRL_RI		(1 << 3)
-#define ACM_CTRL_BRK		(1 << 2)
-#define ACM_CTRL_DSR		(1 << 1)
-#define ACM_CTRL_DCD		(1 << 0)
-};
-
-static inline struct f_acm *func_to_acm(struct usb_function *f)
-{
-	return container_of(f, struct f_acm, port.func);
-}
-
-static inline struct f_acm *port_to_acm(struct gserial *p)
-{
-	return container_of(p, struct f_acm, port);
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* notification endpoint uses smallish and infrequent fixed-size messages */
-
-#define GS_LOG2_NOTIFY_INTERVAL		5	/* 1 << 5 == 32 msec */
-#define GS_NOTIFY_MAXPACKET		10	/* notification + 2 bytes */
-
-/* interface and class descriptors: */
-
-static struct usb_interface_assoc_descriptor
-acm_iad_descriptor = {
-	.bLength =		sizeof acm_iad_descriptor,
-	.bDescriptorType =	USB_DT_INTERFACE_ASSOCIATION,
-
-	/* .bFirstInterface =	DYNAMIC, */
-	.bInterfaceCount = 	2,	// control + data
-	.bFunctionClass =	USB_CLASS_COMM,
-	.bFunctionSubClass =	USB_CDC_SUBCLASS_ACM,
-	.bFunctionProtocol =	USB_CDC_ACM_PROTO_AT_V25TER,
-	/* .iFunction =		DYNAMIC */
-};
-
-
-static struct usb_interface_descriptor acm_control_interface_desc = {
-	.bLength =		USB_DT_INTERFACE_SIZE,
-	.bDescriptorType =	USB_DT_INTERFACE,
-	/* .bInterfaceNumber = DYNAMIC */
-	.bNumEndpoints =	1,
-	.bInterfaceClass =	USB_CLASS_COMM,
-	.bInterfaceSubClass =	USB_CDC_SUBCLASS_ACM,
-	.bInterfaceProtocol =	USB_CDC_ACM_PROTO_AT_V25TER,
-	/* .iInterface = DYNAMIC */
-};
-
-static struct usb_interface_descriptor acm_data_interface_desc = {
-	.bLength =		USB_DT_INTERFACE_SIZE,
-	.bDescriptorType =	USB_DT_INTERFACE,
-	/* .bInterfaceNumber = DYNAMIC */
-	.bNumEndpoints =	2,
-	.bInterfaceClass =	USB_CLASS_CDC_DATA,
-	.bInterfaceSubClass =	0,
-	.bInterfaceProtocol =	0,
-	/* .iInterface = DYNAMIC */
-};
-
-static struct usb_cdc_header_desc acm_header_desc = {
-	.bLength =		sizeof(acm_header_desc),
-	.bDescriptorType =	USB_DT_CS_INTERFACE,
-	.bDescriptorSubType =	USB_CDC_HEADER_TYPE,
-	.bcdCDC =		cpu_to_le16(0x0110),
-};
-
-static struct usb_cdc_call_mgmt_descriptor
-acm_call_mgmt_descriptor = {
-	.bLength =		sizeof(acm_call_mgmt_descriptor),
-	.bDescriptorType =	USB_DT_CS_INTERFACE,
-	.bDescriptorSubType =	USB_CDC_CALL_MANAGEMENT_TYPE,
-	.bmCapabilities =	0,
-	/* .bDataInterface = DYNAMIC */
-};
-
-static struct usb_cdc_acm_descriptor acm_descriptor = {
-	.bLength =		sizeof(acm_descriptor),
-	.bDescriptorType =	USB_DT_CS_INTERFACE,
-	.bDescriptorSubType =	USB_CDC_ACM_TYPE,
-	.bmCapabilities =	USB_CDC_CAP_LINE,
-};
-
-static struct usb_cdc_union_desc acm_union_desc = {
-	.bLength =		sizeof(acm_union_desc),
-	.bDescriptorType =	USB_DT_CS_INTERFACE,
-	.bDescriptorSubType =	USB_CDC_UNION_TYPE,
-	/* .bMasterInterface0 =	DYNAMIC */
-	/* .bSlaveInterface0 =	DYNAMIC */
-};
-
-/* full speed support: */
-
-static struct usb_endpoint_descriptor acm_fs_notify_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-	.bEndpointAddress =	USB_DIR_IN,
-	.bmAttributes =		USB_ENDPOINT_XFER_INT,
-	.wMaxPacketSize =	cpu_to_le16(GS_NOTIFY_MAXPACKET),
-	.bInterval =		1 << GS_LOG2_NOTIFY_INTERVAL,
-};
-
-static struct usb_endpoint_descriptor acm_fs_in_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-	.bEndpointAddress =	USB_DIR_IN,
-	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-};
-
-static struct usb_endpoint_descriptor acm_fs_out_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-	.bEndpointAddress =	USB_DIR_OUT,
-	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-};
-
-static struct usb_descriptor_header *acm_fs_function[] = {
-	(struct usb_descriptor_header *) &acm_iad_descriptor,
-	(struct usb_descriptor_header *) &acm_control_interface_desc,
-	(struct usb_descriptor_header *) &acm_header_desc,
-	(struct usb_descriptor_header *) &acm_call_mgmt_descriptor,
-	(struct usb_descriptor_header *) &acm_descriptor,
-	(struct usb_descriptor_header *) &acm_union_desc,
-	(struct usb_descriptor_header *) &acm_fs_notify_desc,
-	(struct usb_descriptor_header *) &acm_data_interface_desc,
-	(struct usb_descriptor_header *) &acm_fs_in_desc,
-	(struct usb_descriptor_header *) &acm_fs_out_desc,
-	NULL,
-};
-
-/* high speed support: */
-
-static struct usb_endpoint_descriptor acm_hs_notify_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-	.bEndpointAddress =	USB_DIR_IN,
-	.bmAttributes =		USB_ENDPOINT_XFER_INT,
-	.wMaxPacketSize =	cpu_to_le16(GS_NOTIFY_MAXPACKET),
-	.bInterval =		GS_LOG2_NOTIFY_INTERVAL+4,
-};
-
-static struct usb_endpoint_descriptor acm_hs_in_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	cpu_to_le16(512),
-};
-
-static struct usb_endpoint_descriptor acm_hs_out_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	cpu_to_le16(512),
-};
-
-static struct usb_descriptor_header *acm_hs_function[] = {
-	(struct usb_descriptor_header *) &acm_iad_descriptor,
-	(struct usb_descriptor_header *) &acm_control_interface_desc,
-	(struct usb_descriptor_header *) &acm_header_desc,
-	(struct usb_descriptor_header *) &acm_call_mgmt_descriptor,
-	(struct usb_descriptor_header *) &acm_descriptor,
-	(struct usb_descriptor_header *) &acm_union_desc,
-	(struct usb_descriptor_header *) &acm_hs_notify_desc,
-	(struct usb_descriptor_header *) &acm_data_interface_desc,
-	(struct usb_descriptor_header *) &acm_hs_in_desc,
-	(struct usb_descriptor_header *) &acm_hs_out_desc,
-	NULL,
-};
-
-static struct usb_endpoint_descriptor acm_ss_in_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	cpu_to_le16(1024),
-};
-
-static struct usb_endpoint_descriptor acm_ss_out_desc = {
-	.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 acm_ss_bulk_comp_desc = {
-	.bLength =              sizeof acm_ss_bulk_comp_desc,
-	.bDescriptorType =      USB_DT_SS_ENDPOINT_COMP,
-};
-
-static struct usb_descriptor_header *acm_ss_function[] = {
-	(struct usb_descriptor_header *) &acm_iad_descriptor,
-	(struct usb_descriptor_header *) &acm_control_interface_desc,
-	(struct usb_descriptor_header *) &acm_header_desc,
-	(struct usb_descriptor_header *) &acm_call_mgmt_descriptor,
-	(struct usb_descriptor_header *) &acm_descriptor,
-	(struct usb_descriptor_header *) &acm_union_desc,
-	(struct usb_descriptor_header *) &acm_hs_notify_desc,
-	(struct usb_descriptor_header *) &acm_ss_bulk_comp_desc,
-	(struct usb_descriptor_header *) &acm_data_interface_desc,
-	(struct usb_descriptor_header *) &acm_ss_in_desc,
-	(struct usb_descriptor_header *) &acm_ss_bulk_comp_desc,
-	(struct usb_descriptor_header *) &acm_ss_out_desc,
-	(struct usb_descriptor_header *) &acm_ss_bulk_comp_desc,
-	NULL,
-};
-
-/* string descriptors: */
-
-#define ACM_CTRL_IDX	0
-#define ACM_DATA_IDX	1
-#define ACM_IAD_IDX	2
-
-/* static strings, in UTF-8 */
-static struct usb_string acm_string_defs[] = {
-	[ACM_CTRL_IDX].s = "CDC Abstract Control Model (ACM)",
-	[ACM_DATA_IDX].s = "CDC ACM Data",
-	[ACM_IAD_IDX ].s = "CDC Serial",
-	{  /* ZEROES END LIST */ },
-};
-
-static struct usb_gadget_strings acm_string_table = {
-	.language =		0x0409,	/* en-us */
-	.strings =		acm_string_defs,
-};
-
-static struct usb_gadget_strings *acm_strings[] = {
-	&acm_string_table,
-	NULL,
-};
-
-/*-------------------------------------------------------------------------*/
-
-/* ACM control ... data handling is delegated to tty library code.
- * The main task of this function is to activate and deactivate
- * that code based on device state; track parameters like line
- * speed, handshake state, and so on; and issue notifications.
- */
-
-static void acm_complete_set_line_coding(struct usb_ep *ep,
-		struct usb_request *req)
-{
-	struct f_acm	*acm = ep->driver_data;
-	struct usb_composite_dev *cdev = acm->port.func.config->cdev;
-
-	if (req->status != 0) {
-		DBG(cdev, "acm ttyGS%d completion, err %d\n",
-				acm->port_num, req->status);
-		return;
-	}
-
-	/* normal completion */
-	if (req->actual != sizeof(acm->port_line_coding)) {
-		DBG(cdev, "acm ttyGS%d short resp, len %d\n",
-				acm->port_num, req->actual);
-		usb_ep_set_halt(ep);
-	} else {
-		struct usb_cdc_line_coding	*value = req->buf;
-
-		/* REVISIT:  we currently just remember this data.
-		 * If we change that, (a) validate it first, then
-		 * (b) update whatever hardware needs updating,
-		 * (c) worry about locking.  This is information on
-		 * the order of 9600-8-N-1 ... most of which means
-		 * nothing unless we control a real RS232 line.
-		 */
-		acm->port_line_coding = *value;
-	}
-}
-
-static int acm_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
-{
-	struct f_acm		*acm = func_to_acm(f);
-	struct usb_composite_dev *cdev = f->config->cdev;
-	struct usb_request	*req = cdev->req;
-	int			value = -EOPNOTSUPP;
-	u16			w_index = le16_to_cpu(ctrl->wIndex);
-	u16			w_value = le16_to_cpu(ctrl->wValue);
-	u16			w_length = le16_to_cpu(ctrl->wLength);
-
-	/* composite driver infrastructure handles everything except
-	 * CDC class messages; interface activation uses set_alt().
-	 *
-	 * Note CDC spec table 4 lists the ACM request profile.  It requires
-	 * encapsulated command support ... we don't handle any, and respond
-	 * to them by stalling.  Options include get/set/clear comm features
-	 * (not that useful) and SEND_BREAK.
-	 */
-	switch ((ctrl->bRequestType << 8) | ctrl->bRequest) {
-
-	/* SET_LINE_CODING ... just read and save what the host sends */
-	case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
-			| USB_CDC_REQ_SET_LINE_CODING:
-		if (w_length != sizeof(struct usb_cdc_line_coding)
-				|| w_index != acm->ctrl_id)
-			goto invalid;
-
-		value = w_length;
-		cdev->gadget->ep0->driver_data = acm;
-		req->complete = acm_complete_set_line_coding;
-		break;
-
-	/* GET_LINE_CODING ... return what host sent, or initial value */
-	case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
-			| USB_CDC_REQ_GET_LINE_CODING:
-		if (w_index != acm->ctrl_id)
-			goto invalid;
-
-		value = min_t(unsigned, w_length,
-				sizeof(struct usb_cdc_line_coding));
-		memcpy(req->buf, &acm->port_line_coding, value);
-		break;
-
-	/* SET_CONTROL_LINE_STATE ... save what the host sent */
-	case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
-			| USB_CDC_REQ_SET_CONTROL_LINE_STATE:
-		if (w_index != acm->ctrl_id)
-			goto invalid;
-
-		value = 0;
-
-		/* FIXME we should not allow data to flow until the
-		 * host sets the ACM_CTRL_DTR bit; and when it clears
-		 * that bit, we should return to that no-flow state.
-		 */
-		acm->port_handshake_bits = w_value;
-		break;
-
-	default:
-invalid:
-		VDBG(cdev, "invalid control req%02x.%02x v%04x i%04x l%d\n",
-			ctrl->bRequestType, ctrl->bRequest,
-			w_value, w_index, w_length);
-	}
-
-	/* respond with data transfer or status phase? */
-	if (value >= 0) {
-		DBG(cdev, "acm ttyGS%d req%02x.%02x v%04x i%04x l%d\n",
-			acm->port_num, ctrl->bRequestType, ctrl->bRequest,
-			w_value, w_index, w_length);
-		req->zero = 0;
-		req->length = value;
-		value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);
-		if (value < 0)
-			ERROR(cdev, "acm response on ttyGS%d, err %d\n",
-					acm->port_num, value);
-	}
-
-	/* device either stalls (value < 0) or reports success */
-	return value;
-}
-
-static int acm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
-{
-	struct f_acm		*acm = func_to_acm(f);
-	struct usb_composite_dev *cdev = f->config->cdev;
-
-	/* we know alt == 0, so this is an activation or a reset */
-
-	if (intf == acm->ctrl_id) {
-		if (acm->notify->driver_data) {
-			VDBG(cdev, "reset acm control interface %d\n", intf);
-			usb_ep_disable(acm->notify);
-		} else {
-			VDBG(cdev, "init acm ctrl interface %d\n", intf);
-			if (config_ep_by_speed(cdev->gadget, f, acm->notify))
-				return -EINVAL;
-		}
-		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);
-		}
-		if (!acm->port.in->desc || !acm->port.out->desc) {
-			DBG(cdev, "activate acm ttyGS%d\n", acm->port_num);
-			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);
-
-	} else
-		return -EINVAL;
-
-	return 0;
-}
-
-static void acm_disable(struct usb_function *f)
-{
-	struct f_acm	*acm = func_to_acm(f);
-	struct usb_composite_dev *cdev = f->config->cdev;
-
-	DBG(cdev, "acm ttyGS%d deactivated\n", acm->port_num);
-	gserial_disconnect(&acm->port);
-	usb_ep_disable(acm->notify);
-	acm->notify->driver_data = NULL;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/**
- * acm_cdc_notify - issue CDC notification to host
- * @acm: wraps host to be notified
- * @type: notification type
- * @value: Refer to cdc specs, wValue field.
- * @data: data to be sent
- * @length: size of data
- * Context: irqs blocked, acm->lock held, acm_notify_req non-null
- *
- * Returns zero on success or a negative errno.
- *
- * See section 6.3.5 of the CDC 1.1 specification for information
- * about the only notification we issue:  SerialState change.
- */
-static int acm_cdc_notify(struct f_acm *acm, u8 type, u16 value,
-		void *data, unsigned length)
-{
-	struct usb_ep			*ep = acm->notify;
-	struct usb_request		*req;
-	struct usb_cdc_notification	*notify;
-	const unsigned			len = sizeof(*notify) + length;
-	void				*buf;
-	int				status;
-
-	req = acm->notify_req;
-	acm->notify_req = NULL;
-	acm->pending = false;
-
-	req->length = len;
-	notify = req->buf;
-	buf = notify + 1;
-
-	notify->bmRequestType = USB_DIR_IN | USB_TYPE_CLASS
-			| USB_RECIP_INTERFACE;
-	notify->bNotificationType = type;
-	notify->wValue = cpu_to_le16(value);
-	notify->wIndex = cpu_to_le16(acm->ctrl_id);
-	notify->wLength = cpu_to_le16(length);
-	memcpy(buf, data, length);
-
-	/* ep_queue() can complete immediately if it fills the fifo... */
-	spin_unlock(&acm->lock);
-	status = usb_ep_queue(ep, req, GFP_ATOMIC);
-	spin_lock(&acm->lock);
-
-	if (status < 0) {
-		ERROR(acm->port.func.config->cdev,
-				"acm ttyGS%d can't notify serial state, %d\n",
-				acm->port_num, status);
-		acm->notify_req = req;
-	}
-
-	return status;
-}
-
-static int acm_notify_serial_state(struct f_acm *acm)
-{
-	struct usb_composite_dev *cdev = acm->port.func.config->cdev;
-	int			status;
-
-	spin_lock(&acm->lock);
-	if (acm->notify_req) {
-		DBG(cdev, "acm ttyGS%d serial state %04x\n",
-				acm->port_num, acm->serial_state);
-		status = acm_cdc_notify(acm, USB_CDC_NOTIFY_SERIAL_STATE,
-				0, &acm->serial_state, sizeof(acm->serial_state));
-	} else {
-		acm->pending = true;
-		status = 0;
-	}
-	spin_unlock(&acm->lock);
-	return status;
-}
-
-static void acm_cdc_notify_complete(struct usb_ep *ep, struct usb_request *req)
-{
-	struct f_acm		*acm = req->context;
-	u8			doit = false;
-
-	/* on this call path we do NOT hold the port spinlock,
-	 * which is why ACM needs its own spinlock
-	 */
-	spin_lock(&acm->lock);
-	if (req->status != -ESHUTDOWN)
-		doit = acm->pending;
-	acm->notify_req = req;
-	spin_unlock(&acm->lock);
-
-	if (doit)
-		acm_notify_serial_state(acm);
-}
-
-/* connect == the TTY link is open */
-
-static void acm_connect(struct gserial *port)
-{
-	struct f_acm		*acm = port_to_acm(port);
-
-	acm->serial_state |= ACM_CTRL_DSR | ACM_CTRL_DCD;
-	acm_notify_serial_state(acm);
-}
-
-static void acm_disconnect(struct gserial *port)
-{
-	struct f_acm		*acm = port_to_acm(port);
-
-	acm->serial_state &= ~(ACM_CTRL_DSR | ACM_CTRL_DCD);
-	acm_notify_serial_state(acm);
-}
-
-static int acm_send_break(struct gserial *port, int duration)
-{
-	struct f_acm		*acm = port_to_acm(port);
-	u16			state;
-
-	state = acm->serial_state;
-	state &= ~ACM_CTRL_BRK;
-	if (duration)
-		state |= ACM_CTRL_BRK;
-
-	acm->serial_state = state;
-	return acm_notify_serial_state(acm);
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* ACM function driver setup/binding */
-static int
-acm_bind(struct usb_configuration *c, struct usb_function *f)
-{
-	struct usb_composite_dev *cdev = c->cdev;
-	struct f_acm		*acm = func_to_acm(f);
-	int			status;
-	struct usb_ep		*ep;
-
-	/* allocate instance-specific interface IDs, and patch descriptors */
-	status = usb_interface_id(c, f);
-	if (status < 0)
-		goto fail;
-	acm->ctrl_id = status;
-	acm_iad_descriptor.bFirstInterface = status;
-
-	acm_control_interface_desc.bInterfaceNumber = status;
-	acm_union_desc .bMasterInterface0 = status;
-
-	status = usb_interface_id(c, f);
-	if (status < 0)
-		goto fail;
-	acm->data_id = status;
-
-	acm_data_interface_desc.bInterfaceNumber = status;
-	acm_union_desc.bSlaveInterface0 = status;
-	acm_call_mgmt_descriptor.bDataInterface = status;
-
-	status = -ENODEV;
-
-	/* allocate instance-specific endpoints */
-	ep = usb_ep_autoconfig(cdev->gadget, &acm_fs_in_desc);
-	if (!ep)
-		goto fail;
-	acm->port.in = ep;
-	ep->driver_data = cdev;	/* claim */
-
-	ep = usb_ep_autoconfig(cdev->gadget, &acm_fs_out_desc);
-	if (!ep)
-		goto fail;
-	acm->port.out = ep;
-	ep->driver_data = cdev;	/* claim */
-
-	ep = usb_ep_autoconfig(cdev->gadget, &acm_fs_notify_desc);
-	if (!ep)
-		goto fail;
-	acm->notify = ep;
-	ep->driver_data = cdev;	/* claim */
-
-	/* allocate notification */
-	acm->notify_req = gs_alloc_req(ep,
-			sizeof(struct usb_cdc_notification) + 2,
-			GFP_KERNEL);
-	if (!acm->notify_req)
-		goto fail;
-
-	acm->notify_req->complete = acm_cdc_notify_complete;
-	acm->notify_req->context = acm;
-
-	/* copy descriptors */
-	f->descriptors = usb_copy_descriptors(acm_fs_function);
-	if (!f->descriptors)
-		goto fail;
-
-	/* support all relevant hardware speeds... we expect that when
-	 * hardware is dual speed, all bulk-capable endpoints work at
-	 * both speeds
-	 */
-	if (gadget_is_dualspeed(c->cdev->gadget)) {
-		acm_hs_in_desc.bEndpointAddress =
-				acm_fs_in_desc.bEndpointAddress;
-		acm_hs_out_desc.bEndpointAddress =
-				acm_fs_out_desc.bEndpointAddress;
-		acm_hs_notify_desc.bEndpointAddress =
-				acm_fs_notify_desc.bEndpointAddress;
-
-		/* copy descriptors */
-		f->hs_descriptors = usb_copy_descriptors(acm_hs_function);
-	}
-	if (gadget_is_superspeed(c->cdev->gadget)) {
-		acm_ss_in_desc.bEndpointAddress =
-			acm_fs_in_desc.bEndpointAddress;
-		acm_ss_out_desc.bEndpointAddress =
-			acm_fs_out_desc.bEndpointAddress;
-
-		/* copy descriptors, and track endpoint copies */
-		f->ss_descriptors = usb_copy_descriptors(acm_ss_function);
-		if (!f->ss_descriptors)
-			goto fail;
-	}
-
-	DBG(cdev, "acm ttyGS%d: %s speed IN/%s OUT/%s NOTIFY/%s\n",
-			acm->port_num,
-			gadget_is_superspeed(c->cdev->gadget) ? "super" :
-			gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
-			acm->port.in->name, acm->port.out->name,
-			acm->notify->name);
-	return 0;
-
-fail:
-	if (acm->notify_req)
-		gs_free_req(acm->notify, acm->notify_req);
-
-	/* we might as well release our claims on endpoints */
-	if (acm->notify)
-		acm->notify->driver_data = NULL;
-	if (acm->port.out)
-		acm->port.out->driver_data = NULL;
-	if (acm->port.in)
-		acm->port.in->driver_data = NULL;
-
-	ERROR(cdev, "%s/%p: can't bind, err %d\n", f->name, f, status);
-
-	return status;
-}
-
-static void
-acm_unbind(struct usb_configuration *c, struct usb_function *f)
-{
-	struct f_acm		*acm = func_to_acm(f);
-
-	if (gadget_is_dualspeed(c->cdev->gadget))
-		usb_free_descriptors(f->hs_descriptors);
-	if (gadget_is_superspeed(c->cdev->gadget))
-		usb_free_descriptors(f->ss_descriptors);
-	usb_free_descriptors(f->descriptors);
-	gs_free_req(acm->notify, acm->notify_req);
-	kfree(acm);
-}
-
-/* Some controllers can't support CDC ACM ... */
-static inline bool can_support_cdc(struct usb_configuration *c)
-{
-	/* everything else is *probably* fine ... */
-	return true;
-}
-
-/**
- * acm_bind_config - add a CDC ACM function to a configuration
- * @c: the configuration to support the CDC ACM instance
- * @port_num: /dev/ttyGS* port this interface will use
- * Context: single threaded during gadget setup
- *
- * Returns zero on success, else negative errno.
- *
- * Caller must have called @gserial_setup() with enough ports to
- * handle all the ones it binds.  Caller is also responsible
- * for calling @gserial_cleanup() before module unload.
- */
-int acm_bind_config(struct usb_configuration *c, u8 port_num)
-{
-	struct f_acm	*acm;
-	int		status;
-
-	if (!can_support_cdc(c))
-		return -EINVAL;
-
-	/* REVISIT might want instance-specific strings to help
-	 * distinguish instances ...
-	 */
-
-	/* maybe allocate device-global string IDs, and patch descriptors */
-	if (acm_string_defs[ACM_CTRL_IDX].id == 0) {
-		status = usb_string_id(c->cdev);
-		if (status < 0)
-			return status;
-		acm_string_defs[ACM_CTRL_IDX].id = status;
-
-		acm_control_interface_desc.iInterface = status;
-
-		status = usb_string_id(c->cdev);
-		if (status < 0)
-			return status;
-		acm_string_defs[ACM_DATA_IDX].id = status;
-
-		acm_data_interface_desc.iInterface = status;
-
-		status = usb_string_id(c->cdev);
-		if (status < 0)
-			return status;
-		acm_string_defs[ACM_IAD_IDX].id = status;
-
-		acm_iad_descriptor.iFunction = status;
-	}
-
-	/* allocate and initialize one new instance */
-	acm = kzalloc(sizeof *acm, GFP_KERNEL);
-	if (!acm)
-		return -ENOMEM;
-
-	spin_lock_init(&acm->lock);
-
-	acm->port_num = port_num;
-
-	acm->port.connect = acm_connect;
-	acm->port.disconnect = acm_disconnect;
-	acm->port.send_break = acm_send_break;
-
-	acm->port.func.name = "acm";
-	acm->port.func.strings = acm_strings;
-	/* descriptors are per-instance copies */
-	acm->port.func.bind = acm_bind;
-	acm->port.func.unbind = acm_unbind;
-	acm->port.func.set_alt = acm_set_alt;
-	acm->port.func.setup = acm_setup;
-	acm->port.func.disable = acm_disable;
-
-	status = usb_add_function(c, &acm->port.func);
-	if (status)
-		kfree(acm);
-	return status;
-}
diff --git a/drivers/staging/ccg/f_fs.c b/drivers/staging/ccg/f_fs.c
deleted file mode 100644
index f6373da..0000000
--- a/drivers/staging/ccg/f_fs.c
+++ /dev/null
@@ -1,2456 +0,0 @@
-/*
- * f_fs.c -- user mode file system API for USB composite function controllers
- *
- * Copyright (C) 2010 Samsung Electronics
- * Author: Michal Nazarewicz <mina86@mina86.com>
- *
- * Based on inode.c (GadgetFS) which was:
- * Copyright (C) 2003-2004 David Brownell
- * Copyright (C) 2003 Agilent 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.
- */
-
-
-/* #define DEBUG */
-/* #define VERBOSE_DEBUG */
-
-#include <linux/blkdev.h>
-#include <linux/pagemap.h>
-#include <linux/export.h>
-#include <linux/hid.h>
-#include <asm/unaligned.h>
-
-#include <linux/usb/composite.h>
-#include <linux/usb/functionfs.h>
-
-
-#define FUNCTIONFS_MAGIC	0xa647361 /* Chosen by a honest dice roll ;) */
-
-
-/* Debugging ****************************************************************/
-
-#ifdef VERBOSE_DEBUG
-#  define pr_vdebug pr_debug
-#  define ffs_dump_mem(prefix, ptr, len) \
-	print_hex_dump_bytes(pr_fmt(prefix ": "), DUMP_PREFIX_NONE, ptr, len)
-#else
-#  define pr_vdebug(...)                 do { } while (0)
-#  define ffs_dump_mem(prefix, ptr, len) do { } while (0)
-#endif /* VERBOSE_DEBUG */
-
-#define ENTER()    pr_vdebug("%s()\n", __func__)
-
-
-/* The data structure and setup file ****************************************/
-
-enum ffs_state {
-	/*
-	 * Waiting for descriptors and strings.
-	 *
-	 * In this state no open(2), read(2) or write(2) on epfiles
-	 * may succeed (which should not be the problem as there
-	 * should be no such files opened in the first place).
-	 */
-	FFS_READ_DESCRIPTORS,
-	FFS_READ_STRINGS,
-
-	/*
-	 * We've got descriptors and strings.  We are or have called
-	 * functionfs_ready_callback().  functionfs_bind() may have
-	 * been called but we don't know.
-	 *
-	 * This is the only state in which operations on epfiles may
-	 * succeed.
-	 */
-	FFS_ACTIVE,
-
-	/*
-	 * All endpoints have been closed.  This state is also set if
-	 * we encounter an unrecoverable error.  The only
-	 * unrecoverable error is situation when after reading strings
-	 * from user space we fail to initialise epfiles or
-	 * functionfs_ready_callback() returns with error (<0).
-	 *
-	 * In this state no open(2), read(2) or write(2) (both on ep0
-	 * as well as epfile) may succeed (at this point epfiles are
-	 * unlinked and all closed so this is not a problem; ep0 is
-	 * also closed but ep0 file exists and so open(2) on ep0 must
-	 * fail).
-	 */
-	FFS_CLOSING
-};
-
-
-enum ffs_setup_state {
-	/* There is no setup request pending. */
-	FFS_NO_SETUP,
-	/*
-	 * User has read events and there was a setup request event
-	 * there.  The next read/write on ep0 will handle the
-	 * request.
-	 */
-	FFS_SETUP_PENDING,
-	/*
-	 * There was event pending but before user space handled it
-	 * some other event was introduced which canceled existing
-	 * setup.  If this state is set read/write on ep0 return
-	 * -EIDRM.  This state is only set when adding event.
-	 */
-	FFS_SETUP_CANCELED
-};
-
-
-
-struct ffs_epfile;
-struct ffs_function;
-
-struct ffs_data {
-	struct usb_gadget		*gadget;
-
-	/*
-	 * Protect access read/write operations, only one read/write
-	 * at a time.  As a consequence protects ep0req and company.
-	 * While setup request is being processed (queued) this is
-	 * held.
-	 */
-	struct mutex			mutex;
-
-	/*
-	 * Protect access to endpoint related structures (basically
-	 * usb_ep_queue(), usb_ep_dequeue(), etc. calls) except for
-	 * endpoint zero.
-	 */
-	spinlock_t			eps_lock;
-
-	/*
-	 * XXX REVISIT do we need our own request? Since we are not
-	 * handling setup requests immediately user space may be so
-	 * slow that another setup will be sent to the gadget but this
-	 * time not to us but another function and then there could be
-	 * a race.  Is that the case? Or maybe we can use cdev->req
-	 * after all, maybe we just need some spinlock for that?
-	 */
-	struct usb_request		*ep0req;		/* P: mutex */
-	struct completion		ep0req_completion;	/* P: mutex */
-	int				ep0req_status;		/* P: mutex */
-
-	/* reference counter */
-	atomic_t			ref;
-	/* how many files are opened (EP0 and others) */
-	atomic_t			opened;
-
-	/* EP0 state */
-	enum ffs_state			state;
-
-	/*
-	 * Possible transitions:
-	 * + FFS_NO_SETUP       -> FFS_SETUP_PENDING  -- P: ev.waitq.lock
-	 *               happens only in ep0 read which is P: mutex
-	 * + FFS_SETUP_PENDING  -> FFS_NO_SETUP       -- P: ev.waitq.lock
-	 *               happens only in ep0 i/o  which is P: mutex
-	 * + FFS_SETUP_PENDING  -> FFS_SETUP_CANCELED -- P: ev.waitq.lock
-	 * + FFS_SETUP_CANCELED -> FFS_NO_SETUP       -- cmpxchg
-	 */
-	enum ffs_setup_state		setup_state;
-
-#define FFS_SETUP_STATE(ffs)					\
-	((enum ffs_setup_state)cmpxchg(&(ffs)->setup_state,	\
-				       FFS_SETUP_CANCELED, FFS_NO_SETUP))
-
-	/* Events & such. */
-	struct {
-		u8				types[4];
-		unsigned short			count;
-		/* XXX REVISIT need to update it in some places, or do we? */
-		unsigned short			can_stall;
-		struct usb_ctrlrequest		setup;
-
-		wait_queue_head_t		waitq;
-	} ev; /* the whole structure, P: ev.waitq.lock */
-
-	/* Flags */
-	unsigned long			flags;
-#define FFS_FL_CALL_CLOSED_CALLBACK 0
-#define FFS_FL_BOUND                1
-
-	/* Active function */
-	struct ffs_function		*func;
-
-	/*
-	 * Device name, write once when file system is mounted.
-	 * Intended for user to read if she wants.
-	 */
-	const char			*dev_name;
-	/* Private data for our user (ie. gadget).  Managed by user. */
-	void				*private_data;
-
-	/* filled by __ffs_data_got_descs() */
-	/*
-	 * Real descriptors are 16 bytes after raw_descs (so you need
-	 * to skip 16 bytes (ie. ffs->raw_descs + 16) to get to the
-	 * first full speed descriptor).  raw_descs_length and
-	 * raw_fs_descs_length do not have those 16 bytes added.
-	 */
-	const void			*raw_descs;
-	unsigned			raw_descs_length;
-	unsigned			raw_fs_descs_length;
-	unsigned			fs_descs_count;
-	unsigned			hs_descs_count;
-
-	unsigned short			strings_count;
-	unsigned short			interfaces_count;
-	unsigned short			eps_count;
-	unsigned short			_pad1;
-
-	/* filled by __ffs_data_got_strings() */
-	/* ids in stringtabs are set in functionfs_bind() */
-	const void			*raw_strings;
-	struct usb_gadget_strings	**stringtabs;
-
-	/*
-	 * File system's super block, write once when file system is
-	 * mounted.
-	 */
-	struct super_block		*sb;
-
-	/* File permissions, written once when fs is mounted */
-	struct ffs_file_perms {
-		umode_t				mode;
-		uid_t				uid;
-		gid_t				gid;
-	}				file_perms;
-
-	/*
-	 * The endpoint files, filled by ffs_epfiles_create(),
-	 * destroyed by ffs_epfiles_destroy().
-	 */
-	struct ffs_epfile		*epfiles;
-};
-
-/* Reference counter handling */
-static void ffs_data_get(struct ffs_data *ffs);
-static void ffs_data_put(struct ffs_data *ffs);
-/* Creates new ffs_data object. */
-static struct ffs_data *__must_check ffs_data_new(void) __attribute__((malloc));
-
-/* Opened counter handling. */
-static void ffs_data_opened(struct ffs_data *ffs);
-static void ffs_data_closed(struct ffs_data *ffs);
-
-/* Called with ffs->mutex held; take over ownership of data. */
-static int __must_check
-__ffs_data_got_descs(struct ffs_data *ffs, char *data, size_t len);
-static int __must_check
-__ffs_data_got_strings(struct ffs_data *ffs, char *data, size_t len);
-
-
-/* The function structure ***************************************************/
-
-struct ffs_ep;
-
-struct ffs_function {
-	struct usb_configuration	*conf;
-	struct usb_gadget		*gadget;
-	struct ffs_data			*ffs;
-
-	struct ffs_ep			*eps;
-	u8				eps_revmap[16];
-	short				*interfaces_nums;
-
-	struct usb_function		function;
-};
-
-
-static struct ffs_function *ffs_func_from_usb(struct usb_function *f)
-{
-	return container_of(f, struct ffs_function, function);
-}
-
-static void ffs_func_free(struct ffs_function *func);
-
-static void ffs_func_eps_disable(struct ffs_function *func);
-static int __must_check ffs_func_eps_enable(struct ffs_function *func);
-
-static int ffs_func_bind(struct usb_configuration *,
-			 struct usb_function *);
-static void ffs_func_unbind(struct usb_configuration *,
-			    struct usb_function *);
-static int ffs_func_set_alt(struct usb_function *, unsigned, unsigned);
-static void ffs_func_disable(struct usb_function *);
-static int ffs_func_setup(struct usb_function *,
-			  const struct usb_ctrlrequest *);
-static void ffs_func_suspend(struct usb_function *);
-static void ffs_func_resume(struct usb_function *);
-
-
-static int ffs_func_revmap_ep(struct ffs_function *func, u8 num);
-static int ffs_func_revmap_intf(struct ffs_function *func, u8 intf);
-
-
-/* The endpoints structures *************************************************/
-
-struct ffs_ep {
-	struct usb_ep			*ep;	/* P: ffs->eps_lock */
-	struct usb_request		*req;	/* P: epfile->mutex */
-
-	/* [0]: full speed, [1]: high speed */
-	struct usb_endpoint_descriptor	*descs[2];
-
-	u8				num;
-
-	int				status;	/* P: epfile->mutex */
-};
-
-struct ffs_epfile {
-	/* Protects ep->ep and ep->req. */
-	struct mutex			mutex;
-	wait_queue_head_t		wait;
-
-	struct ffs_data			*ffs;
-	struct ffs_ep			*ep;	/* P: ffs->eps_lock */
-
-	struct dentry			*dentry;
-
-	char				name[5];
-
-	unsigned char			in;	/* P: ffs->eps_lock */
-	unsigned char			isoc;	/* P: ffs->eps_lock */
-
-	unsigned char			_pad;
-};
-
-static int  __must_check ffs_epfiles_create(struct ffs_data *ffs);
-static void ffs_epfiles_destroy(struct ffs_epfile *epfiles, unsigned count);
-
-static struct inode *__must_check
-ffs_sb_create_file(struct super_block *sb, const char *name, void *data,
-		   const struct file_operations *fops,
-		   struct dentry **dentry_p);
-
-
-/* Misc helper functions ****************************************************/
-
-static int ffs_mutex_lock(struct mutex *mutex, unsigned nonblock)
-	__attribute__((warn_unused_result, nonnull));
-static char *ffs_prepare_buffer(const char * __user buf, size_t len)
-	__attribute__((warn_unused_result, nonnull));
-
-
-/* Control file aka ep0 *****************************************************/
-
-static void ffs_ep0_complete(struct usb_ep *ep, struct usb_request *req)
-{
-	struct ffs_data *ffs = req->context;
-
-	complete_all(&ffs->ep0req_completion);
-}
-
-static int __ffs_ep0_queue_wait(struct ffs_data *ffs, char *data, size_t len)
-{
-	struct usb_request *req = ffs->ep0req;
-	int ret;
-
-	req->zero     = len < le16_to_cpu(ffs->ev.setup.wLength);
-
-	spin_unlock_irq(&ffs->ev.waitq.lock);
-
-	req->buf      = data;
-	req->length   = len;
-
-	/*
-	 * UDC layer requires to provide a buffer even for ZLP, but should
-	 * not use it at all. Let's provide some poisoned pointer to catch
-	 * possible bug in the driver.
-	 */
-	if (req->buf == NULL)
-		req->buf = (void *)0xDEADBABE;
-
-	INIT_COMPLETION(ffs->ep0req_completion);
-
-	ret = usb_ep_queue(ffs->gadget->ep0, req, GFP_ATOMIC);
-	if (unlikely(ret < 0))
-		return ret;
-
-	ret = wait_for_completion_interruptible(&ffs->ep0req_completion);
-	if (unlikely(ret)) {
-		usb_ep_dequeue(ffs->gadget->ep0, req);
-		return -EINTR;
-	}
-
-	ffs->setup_state = FFS_NO_SETUP;
-	return ffs->ep0req_status;
-}
-
-static int __ffs_ep0_stall(struct ffs_data *ffs)
-{
-	if (ffs->ev.can_stall) {
-		pr_vdebug("ep0 stall\n");
-		usb_ep_set_halt(ffs->gadget->ep0);
-		ffs->setup_state = FFS_NO_SETUP;
-		return -EL2HLT;
-	} else {
-		pr_debug("bogus ep0 stall!\n");
-		return -ESRCH;
-	}
-}
-
-static ssize_t ffs_ep0_write(struct file *file, const char __user *buf,
-			     size_t len, loff_t *ptr)
-{
-	struct ffs_data *ffs = file->private_data;
-	ssize_t ret;
-	char *data;
-
-	ENTER();
-
-	/* Fast check if setup was canceled */
-	if (FFS_SETUP_STATE(ffs) == FFS_SETUP_CANCELED)
-		return -EIDRM;
-
-	/* Acquire mutex */
-	ret = ffs_mutex_lock(&ffs->mutex, file->f_flags & O_NONBLOCK);
-	if (unlikely(ret < 0))
-		return ret;
-
-	/* Check state */
-	switch (ffs->state) {
-	case FFS_READ_DESCRIPTORS:
-	case FFS_READ_STRINGS:
-		/* Copy data */
-		if (unlikely(len < 16)) {
-			ret = -EINVAL;
-			break;
-		}
-
-		data = ffs_prepare_buffer(buf, len);
-		if (IS_ERR(data)) {
-			ret = PTR_ERR(data);
-			break;
-		}
-
-		/* Handle data */
-		if (ffs->state == FFS_READ_DESCRIPTORS) {
-			pr_info("read descriptors\n");
-			ret = __ffs_data_got_descs(ffs, data, len);
-			if (unlikely(ret < 0))
-				break;
-
-			ffs->state = FFS_READ_STRINGS;
-			ret = len;
-		} else {
-			pr_info("read strings\n");
-			ret = __ffs_data_got_strings(ffs, data, len);
-			if (unlikely(ret < 0))
-				break;
-
-			ret = ffs_epfiles_create(ffs);
-			if (unlikely(ret)) {
-				ffs->state = FFS_CLOSING;
-				break;
-			}
-
-			ffs->state = FFS_ACTIVE;
-			mutex_unlock(&ffs->mutex);
-
-			ret = functionfs_ready_callback(ffs);
-			if (unlikely(ret < 0)) {
-				ffs->state = FFS_CLOSING;
-				return ret;
-			}
-
-			set_bit(FFS_FL_CALL_CLOSED_CALLBACK, &ffs->flags);
-			return len;
-		}
-		break;
-
-	case FFS_ACTIVE:
-		data = NULL;
-		/*
-		 * We're called from user space, we can use _irq
-		 * rather then _irqsave
-		 */
-		spin_lock_irq(&ffs->ev.waitq.lock);
-		switch (FFS_SETUP_STATE(ffs)) {
-		case FFS_SETUP_CANCELED:
-			ret = -EIDRM;
-			goto done_spin;
-
-		case FFS_NO_SETUP:
-			ret = -ESRCH;
-			goto done_spin;
-
-		case FFS_SETUP_PENDING:
-			break;
-		}
-
-		/* FFS_SETUP_PENDING */
-		if (!(ffs->ev.setup.bRequestType & USB_DIR_IN)) {
-			spin_unlock_irq(&ffs->ev.waitq.lock);
-			ret = __ffs_ep0_stall(ffs);
-			break;
-		}
-
-		/* FFS_SETUP_PENDING and not stall */
-		len = min(len, (size_t)le16_to_cpu(ffs->ev.setup.wLength));
-
-		spin_unlock_irq(&ffs->ev.waitq.lock);
-
-		data = ffs_prepare_buffer(buf, len);
-		if (IS_ERR(data)) {
-			ret = PTR_ERR(data);
-			break;
-		}
-
-		spin_lock_irq(&ffs->ev.waitq.lock);
-
-		/*
-		 * We are guaranteed to be still in FFS_ACTIVE state
-		 * but the state of setup could have changed from
-		 * FFS_SETUP_PENDING to FFS_SETUP_CANCELED so we need
-		 * to check for that.  If that happened we copied data
-		 * from user space in vain but it's unlikely.
-		 *
-		 * For sure we are not in FFS_NO_SETUP since this is
-		 * the only place FFS_SETUP_PENDING -> FFS_NO_SETUP
-		 * transition can be performed and it's protected by
-		 * mutex.
-		 */
-		if (FFS_SETUP_STATE(ffs) == FFS_SETUP_CANCELED) {
-			ret = -EIDRM;
-done_spin:
-			spin_unlock_irq(&ffs->ev.waitq.lock);
-		} else {
-			/* unlocks spinlock */
-			ret = __ffs_ep0_queue_wait(ffs, data, len);
-		}
-		kfree(data);
-		break;
-
-	default:
-		ret = -EBADFD;
-		break;
-	}
-
-	mutex_unlock(&ffs->mutex);
-	return ret;
-}
-
-static ssize_t __ffs_ep0_read_events(struct ffs_data *ffs, char __user *buf,
-				     size_t n)
-{
-	/*
-	 * We are holding ffs->ev.waitq.lock and ffs->mutex and we need
-	 * to release them.
-	 */
-	struct usb_functionfs_event events[n];
-	unsigned i = 0;
-
-	memset(events, 0, sizeof events);
-
-	do {
-		events[i].type = ffs->ev.types[i];
-		if (events[i].type == FUNCTIONFS_SETUP) {
-			events[i].u.setup = ffs->ev.setup;
-			ffs->setup_state = FFS_SETUP_PENDING;
-		}
-	} while (++i < n);
-
-	if (n < ffs->ev.count) {
-		ffs->ev.count -= n;
-		memmove(ffs->ev.types, ffs->ev.types + n,
-			ffs->ev.count * sizeof *ffs->ev.types);
-	} else {
-		ffs->ev.count = 0;
-	}
-
-	spin_unlock_irq(&ffs->ev.waitq.lock);
-	mutex_unlock(&ffs->mutex);
-
-	return unlikely(__copy_to_user(buf, events, sizeof events))
-		? -EFAULT : sizeof events;
-}
-
-static ssize_t ffs_ep0_read(struct file *file, char __user *buf,
-			    size_t len, loff_t *ptr)
-{
-	struct ffs_data *ffs = file->private_data;
-	char *data = NULL;
-	size_t n;
-	int ret;
-
-	ENTER();
-
-	/* Fast check if setup was canceled */
-	if (FFS_SETUP_STATE(ffs) == FFS_SETUP_CANCELED)
-		return -EIDRM;
-
-	/* Acquire mutex */
-	ret = ffs_mutex_lock(&ffs->mutex, file->f_flags & O_NONBLOCK);
-	if (unlikely(ret < 0))
-		return ret;
-
-	/* Check state */
-	if (ffs->state != FFS_ACTIVE) {
-		ret = -EBADFD;
-		goto done_mutex;
-	}
-
-	/*
-	 * We're called from user space, we can use _irq rather then
-	 * _irqsave
-	 */
-	spin_lock_irq(&ffs->ev.waitq.lock);
-
-	switch (FFS_SETUP_STATE(ffs)) {
-	case FFS_SETUP_CANCELED:
-		ret = -EIDRM;
-		break;
-
-	case FFS_NO_SETUP:
-		n = len / sizeof(struct usb_functionfs_event);
-		if (unlikely(!n)) {
-			ret = -EINVAL;
-			break;
-		}
-
-		if ((file->f_flags & O_NONBLOCK) && !ffs->ev.count) {
-			ret = -EAGAIN;
-			break;
-		}
-
-		if (wait_event_interruptible_exclusive_locked_irq(ffs->ev.waitq,
-							ffs->ev.count)) {
-			ret = -EINTR;
-			break;
-		}
-
-		return __ffs_ep0_read_events(ffs, buf,
-					     min(n, (size_t)ffs->ev.count));
-
-	case FFS_SETUP_PENDING:
-		if (ffs->ev.setup.bRequestType & USB_DIR_IN) {
-			spin_unlock_irq(&ffs->ev.waitq.lock);
-			ret = __ffs_ep0_stall(ffs);
-			goto done_mutex;
-		}
-
-		len = min(len, (size_t)le16_to_cpu(ffs->ev.setup.wLength));
-
-		spin_unlock_irq(&ffs->ev.waitq.lock);
-
-		if (likely(len)) {
-			data = kmalloc(len, GFP_KERNEL);
-			if (unlikely(!data)) {
-				ret = -ENOMEM;
-				goto done_mutex;
-			}
-		}
-
-		spin_lock_irq(&ffs->ev.waitq.lock);
-
-		/* See ffs_ep0_write() */
-		if (FFS_SETUP_STATE(ffs) == FFS_SETUP_CANCELED) {
-			ret = -EIDRM;
-			break;
-		}
-
-		/* unlocks spinlock */
-		ret = __ffs_ep0_queue_wait(ffs, data, len);
-		if (likely(ret > 0) && unlikely(__copy_to_user(buf, data, len)))
-			ret = -EFAULT;
-		goto done_mutex;
-
-	default:
-		ret = -EBADFD;
-		break;
-	}
-
-	spin_unlock_irq(&ffs->ev.waitq.lock);
-done_mutex:
-	mutex_unlock(&ffs->mutex);
-	kfree(data);
-	return ret;
-}
-
-static int ffs_ep0_open(struct inode *inode, struct file *file)
-{
-	struct ffs_data *ffs = inode->i_private;
-
-	ENTER();
-
-	if (unlikely(ffs->state == FFS_CLOSING))
-		return -EBUSY;
-
-	file->private_data = ffs;
-	ffs_data_opened(ffs);
-
-	return 0;
-}
-
-static int ffs_ep0_release(struct inode *inode, struct file *file)
-{
-	struct ffs_data *ffs = file->private_data;
-
-	ENTER();
-
-	ffs_data_closed(ffs);
-
-	return 0;
-}
-
-static long ffs_ep0_ioctl(struct file *file, unsigned code, unsigned long value)
-{
-	struct ffs_data *ffs = file->private_data;
-	struct usb_gadget *gadget = ffs->gadget;
-	long ret;
-
-	ENTER();
-
-	if (code == FUNCTIONFS_INTERFACE_REVMAP) {
-		struct ffs_function *func = ffs->func;
-		ret = func ? ffs_func_revmap_intf(func, value) : -ENODEV;
-	} else if (gadget && gadget->ops->ioctl) {
-		ret = gadget->ops->ioctl(gadget, code, value);
-	} else {
-		ret = -ENOTTY;
-	}
-
-	return ret;
-}
-
-static const struct file_operations ffs_ep0_operations = {
-	.owner =	THIS_MODULE,
-	.llseek =	no_llseek,
-
-	.open =		ffs_ep0_open,
-	.write =	ffs_ep0_write,
-	.read =		ffs_ep0_read,
-	.release =	ffs_ep0_release,
-	.unlocked_ioctl =	ffs_ep0_ioctl,
-};
-
-
-/* "Normal" endpoints operations ********************************************/
-
-static void ffs_epfile_io_complete(struct usb_ep *_ep, struct usb_request *req)
-{
-	ENTER();
-	if (likely(req->context)) {
-		struct ffs_ep *ep = _ep->driver_data;
-		ep->status = req->status ? req->status : req->actual;
-		complete(req->context);
-	}
-}
-
-static ssize_t ffs_epfile_io(struct file *file,
-			     char __user *buf, size_t len, int read)
-{
-	struct ffs_epfile *epfile = file->private_data;
-	struct ffs_ep *ep;
-	char *data = NULL;
-	ssize_t ret;
-	int halt;
-
-	goto first_try;
-	do {
-		spin_unlock_irq(&epfile->ffs->eps_lock);
-		mutex_unlock(&epfile->mutex);
-
-first_try:
-		/* Are we still active? */
-		if (WARN_ON(epfile->ffs->state != FFS_ACTIVE)) {
-			ret = -ENODEV;
-			goto error;
-		}
-
-		/* Wait for endpoint to be enabled */
-		ep = epfile->ep;
-		if (!ep) {
-			if (file->f_flags & O_NONBLOCK) {
-				ret = -EAGAIN;
-				goto error;
-			}
-
-			if (wait_event_interruptible(epfile->wait,
-						     (ep = epfile->ep))) {
-				ret = -EINTR;
-				goto error;
-			}
-		}
-
-		/* Do we halt? */
-		halt = !read == !epfile->in;
-		if (halt && epfile->isoc) {
-			ret = -EINVAL;
-			goto error;
-		}
-
-		/* Allocate & copy */
-		if (!halt && !data) {
-			data = kzalloc(len, GFP_KERNEL);
-			if (unlikely(!data))
-				return -ENOMEM;
-
-			if (!read &&
-			    unlikely(__copy_from_user(data, buf, len))) {
-				ret = -EFAULT;
-				goto error;
-			}
-		}
-
-		/* We will be using request */
-		ret = ffs_mutex_lock(&epfile->mutex,
-				     file->f_flags & O_NONBLOCK);
-		if (unlikely(ret))
-			goto error;
-
-		/*
-		 * We're called from user space, we can use _irq rather then
-		 * _irqsave
-		 */
-		spin_lock_irq(&epfile->ffs->eps_lock);
-
-		/*
-		 * While we were acquiring mutex endpoint got disabled
-		 * or changed?
-		 */
-	} while (unlikely(epfile->ep != ep));
-
-	/* Halt */
-	if (unlikely(halt)) {
-		if (likely(epfile->ep == ep) && !WARN_ON(!ep->ep))
-			usb_ep_set_halt(ep->ep);
-		spin_unlock_irq(&epfile->ffs->eps_lock);
-		ret = -EBADMSG;
-	} else {
-		/* Fire the request */
-		DECLARE_COMPLETION_ONSTACK(done);
-
-		struct usb_request *req = ep->req;
-		req->context  = &done;
-		req->complete = ffs_epfile_io_complete;
-		req->buf      = data;
-		req->length   = len;
-
-		ret = usb_ep_queue(ep->ep, req, GFP_ATOMIC);
-
-		spin_unlock_irq(&epfile->ffs->eps_lock);
-
-		if (unlikely(ret < 0)) {
-			/* nop */
-		} else if (unlikely(wait_for_completion_interruptible(&done))) {
-			ret = -EINTR;
-			usb_ep_dequeue(ep->ep, req);
-		} else {
-			ret = ep->status;
-			if (read && ret > 0 &&
-			    unlikely(copy_to_user(buf, data, ret)))
-				ret = -EFAULT;
-		}
-	}
-
-	mutex_unlock(&epfile->mutex);
-error:
-	kfree(data);
-	return ret;
-}
-
-static ssize_t
-ffs_epfile_write(struct file *file, const char __user *buf, size_t len,
-		 loff_t *ptr)
-{
-	ENTER();
-
-	return ffs_epfile_io(file, (char __user *)buf, len, 0);
-}
-
-static ssize_t
-ffs_epfile_read(struct file *file, char __user *buf, size_t len, loff_t *ptr)
-{
-	ENTER();
-
-	return ffs_epfile_io(file, buf, len, 1);
-}
-
-static int
-ffs_epfile_open(struct inode *inode, struct file *file)
-{
-	struct ffs_epfile *epfile = inode->i_private;
-
-	ENTER();
-
-	if (WARN_ON(epfile->ffs->state != FFS_ACTIVE))
-		return -ENODEV;
-
-	file->private_data = epfile;
-	ffs_data_opened(epfile->ffs);
-
-	return 0;
-}
-
-static int
-ffs_epfile_release(struct inode *inode, struct file *file)
-{
-	struct ffs_epfile *epfile = inode->i_private;
-
-	ENTER();
-
-	ffs_data_closed(epfile->ffs);
-
-	return 0;
-}
-
-static long ffs_epfile_ioctl(struct file *file, unsigned code,
-			     unsigned long value)
-{
-	struct ffs_epfile *epfile = file->private_data;
-	int ret;
-
-	ENTER();
-
-	if (WARN_ON(epfile->ffs->state != FFS_ACTIVE))
-		return -ENODEV;
-
-	spin_lock_irq(&epfile->ffs->eps_lock);
-	if (likely(epfile->ep)) {
-		switch (code) {
-		case FUNCTIONFS_FIFO_STATUS:
-			ret = usb_ep_fifo_status(epfile->ep->ep);
-			break;
-		case FUNCTIONFS_FIFO_FLUSH:
-			usb_ep_fifo_flush(epfile->ep->ep);
-			ret = 0;
-			break;
-		case FUNCTIONFS_CLEAR_HALT:
-			ret = usb_ep_clear_halt(epfile->ep->ep);
-			break;
-		case FUNCTIONFS_ENDPOINT_REVMAP:
-			ret = epfile->ep->num;
-			break;
-		default:
-			ret = -ENOTTY;
-		}
-	} else {
-		ret = -ENODEV;
-	}
-	spin_unlock_irq(&epfile->ffs->eps_lock);
-
-	return ret;
-}
-
-static const struct file_operations ffs_epfile_operations = {
-	.owner =	THIS_MODULE,
-	.llseek =	no_llseek,
-
-	.open =		ffs_epfile_open,
-	.write =	ffs_epfile_write,
-	.read =		ffs_epfile_read,
-	.release =	ffs_epfile_release,
-	.unlocked_ioctl =	ffs_epfile_ioctl,
-};
-
-
-/* File system and super block operations ***********************************/
-
-/*
- * Mounting the file system creates a controller file, used first for
- * function configuration then later for event monitoring.
- */
-
-static struct inode *__must_check
-ffs_sb_make_inode(struct super_block *sb, void *data,
-		  const struct file_operations *fops,
-		  const struct inode_operations *iops,
-		  struct ffs_file_perms *perms)
-{
-	struct inode *inode;
-
-	ENTER();
-
-	inode = new_inode(sb);
-
-	if (likely(inode)) {
-		struct timespec current_time = CURRENT_TIME;
-
-		inode->i_ino	 = get_next_ino();
-		inode->i_mode    = perms->mode;
-		inode->i_uid     = perms->uid;
-		inode->i_gid     = perms->gid;
-		inode->i_atime   = current_time;
-		inode->i_mtime   = current_time;
-		inode->i_ctime   = current_time;
-		inode->i_private = data;
-		if (fops)
-			inode->i_fop = fops;
-		if (iops)
-			inode->i_op  = iops;
-	}
-
-	return inode;
-}
-
-/* Create "regular" file */
-static struct inode *ffs_sb_create_file(struct super_block *sb,
-					const char *name, void *data,
-					const struct file_operations *fops,
-					struct dentry **dentry_p)
-{
-	struct ffs_data	*ffs = sb->s_fs_info;
-	struct dentry	*dentry;
-	struct inode	*inode;
-
-	ENTER();
-
-	dentry = d_alloc_name(sb->s_root, name);
-	if (unlikely(!dentry))
-		return NULL;
-
-	inode = ffs_sb_make_inode(sb, data, fops, NULL, &ffs->file_perms);
-	if (unlikely(!inode)) {
-		dput(dentry);
-		return NULL;
-	}
-
-	d_add(dentry, inode);
-	if (dentry_p)
-		*dentry_p = dentry;
-
-	return inode;
-}
-
-/* Super block */
-static const struct super_operations ffs_sb_operations = {
-	.statfs =	simple_statfs,
-	.drop_inode =	generic_delete_inode,
-};
-
-struct ffs_sb_fill_data {
-	struct ffs_file_perms perms;
-	umode_t root_mode;
-	const char *dev_name;
-	union {
-		/* set by ffs_fs_mount(), read by ffs_sb_fill() */
-		void *private_data;
-		/* set by ffs_sb_fill(), read by ffs_fs_mount */
-		struct ffs_data *ffs_data;
-	};
-};
-
-static int ffs_sb_fill(struct super_block *sb, void *_data, int silent)
-{
-	struct ffs_sb_fill_data *data = _data;
-	struct inode	*inode;
-	struct ffs_data	*ffs;
-
-	ENTER();
-
-	/* Initialise data */
-	ffs = ffs_data_new();
-	if (unlikely(!ffs))
-		goto Enomem;
-
-	ffs->sb              = sb;
-	ffs->dev_name        = kstrdup(data->dev_name, GFP_KERNEL);
-	if (unlikely(!ffs->dev_name))
-		goto Enomem;
-	ffs->file_perms      = data->perms;
-	ffs->private_data    = data->private_data;
-
-	/* used by the caller of this function */
-	data->ffs_data       = ffs;
-
-	sb->s_fs_info        = ffs;
-	sb->s_blocksize      = PAGE_CACHE_SIZE;
-	sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
-	sb->s_magic          = FUNCTIONFS_MAGIC;
-	sb->s_op             = &ffs_sb_operations;
-	sb->s_time_gran      = 1;
-
-	/* Root inode */
-	data->perms.mode = data->root_mode;
-	inode = ffs_sb_make_inode(sb, NULL,
-				  &simple_dir_operations,
-				  &simple_dir_inode_operations,
-				  &data->perms);
-	sb->s_root = d_make_root(inode);
-	if (unlikely(!sb->s_root))
-		goto Enomem;
-
-	/* EP0 file */
-	if (unlikely(!ffs_sb_create_file(sb, "ep0", ffs,
-					 &ffs_ep0_operations, NULL)))
-		goto Enomem;
-
-	return 0;
-
-Enomem:
-	return -ENOMEM;
-}
-
-static int ffs_fs_parse_opts(struct ffs_sb_fill_data *data, char *opts)
-{
-	ENTER();
-
-	if (!opts || !*opts)
-		return 0;
-
-	for (;;) {
-		char *end, *eq, *comma;
-		unsigned long value;
-
-		/* Option limit */
-		comma = strchr(opts, ',');
-		if (comma)
-			*comma = 0;
-
-		/* Value limit */
-		eq = strchr(opts, '=');
-		if (unlikely(!eq)) {
-			pr_err("'=' missing in %s\n", opts);
-			return -EINVAL;
-		}
-		*eq = 0;
-
-		/* Parse value */
-		value = simple_strtoul(eq + 1, &end, 0);
-		if (unlikely(*end != ',' && *end != 0)) {
-			pr_err("%s: invalid value: %s\n", opts, eq + 1);
-			return -EINVAL;
-		}
-
-		/* Interpret option */
-		switch (eq - opts) {
-		case 5:
-			if (!memcmp(opts, "rmode", 5))
-				data->root_mode  = (value & 0555) | S_IFDIR;
-			else if (!memcmp(opts, "fmode", 5))
-				data->perms.mode = (value & 0666) | S_IFREG;
-			else
-				goto invalid;
-			break;
-
-		case 4:
-			if (!memcmp(opts, "mode", 4)) {
-				data->root_mode  = (value & 0555) | S_IFDIR;
-				data->perms.mode = (value & 0666) | S_IFREG;
-			} else {
-				goto invalid;
-			}
-			break;
-
-		case 3:
-			if (!memcmp(opts, "uid", 3))
-				data->perms.uid = value;
-			else if (!memcmp(opts, "gid", 3))
-				data->perms.gid = value;
-			else
-				goto invalid;
-			break;
-
-		default:
-invalid:
-			pr_err("%s: invalid option\n", opts);
-			return -EINVAL;
-		}
-
-		/* Next iteration */
-		if (!comma)
-			break;
-		opts = comma + 1;
-	}
-
-	return 0;
-}
-
-/* "mount -t functionfs dev_name /dev/function" ends up here */
-
-static struct dentry *
-ffs_fs_mount(struct file_system_type *t, int flags,
-	      const char *dev_name, void *opts)
-{
-	struct ffs_sb_fill_data data = {
-		.perms = {
-			.mode = S_IFREG | 0600,
-			.uid = 0,
-			.gid = 0
-		},
-		.root_mode = S_IFDIR | 0500,
-	};
-	struct dentry *rv;
-	int ret;
-	void *ffs_dev;
-
-	ENTER();
-
-	ret = ffs_fs_parse_opts(&data, opts);
-	if (unlikely(ret < 0))
-		return ERR_PTR(ret);
-
-	ffs_dev = functionfs_acquire_dev_callback(dev_name);
-	if (IS_ERR(ffs_dev))
-		return ffs_dev;
-
-	data.dev_name = dev_name;
-	data.private_data = ffs_dev;
-	rv = mount_nodev(t, flags, &data, ffs_sb_fill);
-
-	/* data.ffs_data is set by ffs_sb_fill */
-	if (IS_ERR(rv))
-		functionfs_release_dev_callback(data.ffs_data);
-
-	return rv;
-}
-
-static void
-ffs_fs_kill_sb(struct super_block *sb)
-{
-	ENTER();
-
-	kill_litter_super(sb);
-	if (sb->s_fs_info) {
-		functionfs_release_dev_callback(sb->s_fs_info);
-		ffs_data_put(sb->s_fs_info);
-	}
-}
-
-static struct file_system_type ffs_fs_type = {
-	.owner		= THIS_MODULE,
-	.name		= "functionfs",
-	.mount		= ffs_fs_mount,
-	.kill_sb	= ffs_fs_kill_sb,
-};
-MODULE_ALIAS_FS("functionfs");
-
-
-/* Driver's main init/cleanup functions *************************************/
-
-static int functionfs_init(void)
-{
-	int ret;
-
-	ENTER();
-
-	ret = register_filesystem(&ffs_fs_type);
-	if (likely(!ret))
-		pr_info("file system registered\n");
-	else
-		pr_err("failed registering file system (%d)\n", ret);
-
-	return ret;
-}
-
-static void functionfs_cleanup(void)
-{
-	ENTER();
-
-	pr_info("unloading\n");
-	unregister_filesystem(&ffs_fs_type);
-}
-
-
-/* ffs_data and ffs_function construction and destruction code **************/
-
-static void ffs_data_clear(struct ffs_data *ffs);
-static void ffs_data_reset(struct ffs_data *ffs);
-
-static void ffs_data_get(struct ffs_data *ffs)
-{
-	ENTER();
-
-	atomic_inc(&ffs->ref);
-}
-
-static void ffs_data_opened(struct ffs_data *ffs)
-{
-	ENTER();
-
-	atomic_inc(&ffs->ref);
-	atomic_inc(&ffs->opened);
-}
-
-static void ffs_data_put(struct ffs_data *ffs)
-{
-	ENTER();
-
-	if (unlikely(atomic_dec_and_test(&ffs->ref))) {
-		pr_info("%s(): freeing\n", __func__);
-		ffs_data_clear(ffs);
-		BUG_ON(waitqueue_active(&ffs->ev.waitq) ||
-		       waitqueue_active(&ffs->ep0req_completion.wait));
-		kfree(ffs->dev_name);
-		kfree(ffs);
-	}
-}
-
-static void ffs_data_closed(struct ffs_data *ffs)
-{
-	ENTER();
-
-	if (atomic_dec_and_test(&ffs->opened)) {
-		ffs->state = FFS_CLOSING;
-		ffs_data_reset(ffs);
-	}
-
-	ffs_data_put(ffs);
-}
-
-static struct ffs_data *ffs_data_new(void)
-{
-	struct ffs_data *ffs = kzalloc(sizeof *ffs, GFP_KERNEL);
-	if (unlikely(!ffs))
-		return 0;
-
-	ENTER();
-
-	atomic_set(&ffs->ref, 1);
-	atomic_set(&ffs->opened, 0);
-	ffs->state = FFS_READ_DESCRIPTORS;
-	mutex_init(&ffs->mutex);
-	spin_lock_init(&ffs->eps_lock);
-	init_waitqueue_head(&ffs->ev.waitq);
-	init_completion(&ffs->ep0req_completion);
-
-	/* XXX REVISIT need to update it in some places, or do we? */
-	ffs->ev.can_stall = 1;
-
-	return ffs;
-}
-
-static void ffs_data_clear(struct ffs_data *ffs)
-{
-	ENTER();
-
-	if (test_and_clear_bit(FFS_FL_CALL_CLOSED_CALLBACK, &ffs->flags))
-		functionfs_closed_callback(ffs);
-
-	BUG_ON(ffs->gadget);
-
-	if (ffs->epfiles)
-		ffs_epfiles_destroy(ffs->epfiles, ffs->eps_count);
-
-	kfree(ffs->raw_descs);
-	kfree(ffs->raw_strings);
-	kfree(ffs->stringtabs);
-}
-
-static void ffs_data_reset(struct ffs_data *ffs)
-{
-	ENTER();
-
-	ffs_data_clear(ffs);
-
-	ffs->epfiles = NULL;
-	ffs->raw_descs = NULL;
-	ffs->raw_strings = NULL;
-	ffs->stringtabs = NULL;
-
-	ffs->raw_descs_length = 0;
-	ffs->raw_fs_descs_length = 0;
-	ffs->fs_descs_count = 0;
-	ffs->hs_descs_count = 0;
-
-	ffs->strings_count = 0;
-	ffs->interfaces_count = 0;
-	ffs->eps_count = 0;
-
-	ffs->ev.count = 0;
-
-	ffs->state = FFS_READ_DESCRIPTORS;
-	ffs->setup_state = FFS_NO_SETUP;
-	ffs->flags = 0;
-}
-
-
-static int functionfs_bind(struct ffs_data *ffs, struct usb_composite_dev *cdev)
-{
-	struct usb_gadget_strings **lang;
-	int first_id;
-
-	ENTER();
-
-	if (WARN_ON(ffs->state != FFS_ACTIVE
-		 || test_and_set_bit(FFS_FL_BOUND, &ffs->flags)))
-		return -EBADFD;
-
-	first_id = usb_string_ids_n(cdev, ffs->strings_count);
-	if (unlikely(first_id < 0))
-		return first_id;
-
-	ffs->ep0req = usb_ep_alloc_request(cdev->gadget->ep0, GFP_KERNEL);
-	if (unlikely(!ffs->ep0req))
-		return -ENOMEM;
-	ffs->ep0req->complete = ffs_ep0_complete;
-	ffs->ep0req->context = ffs;
-
-	lang = ffs->stringtabs;
-	for (lang = ffs->stringtabs; *lang; ++lang) {
-		struct usb_string *str = (*lang)->strings;
-		int id = first_id;
-		for (; str->s; ++id, ++str)
-			str->id = id;
-	}
-
-	ffs->gadget = cdev->gadget;
-	ffs_data_get(ffs);
-	return 0;
-}
-
-static void functionfs_unbind(struct ffs_data *ffs)
-{
-	ENTER();
-
-	if (!WARN_ON(!ffs->gadget)) {
-		usb_ep_free_request(ffs->gadget->ep0, ffs->ep0req);
-		ffs->ep0req = NULL;
-		ffs->gadget = NULL;
-		ffs_data_put(ffs);
-		clear_bit(FFS_FL_BOUND, &ffs->flags);
-	}
-}
-
-static int ffs_epfiles_create(struct ffs_data *ffs)
-{
-	struct ffs_epfile *epfile, *epfiles;
-	unsigned i, count;
-
-	ENTER();
-
-	count = ffs->eps_count;
-	epfiles = kcalloc(count, sizeof(*epfiles), GFP_KERNEL);
-	if (!epfiles)
-		return -ENOMEM;
-
-	epfile = epfiles;
-	for (i = 1; i <= count; ++i, ++epfile) {
-		epfile->ffs = ffs;
-		mutex_init(&epfile->mutex);
-		init_waitqueue_head(&epfile->wait);
-		sprintf(epfiles->name, "ep%u",  i);
-		if (!unlikely(ffs_sb_create_file(ffs->sb, epfiles->name, epfile,
-						 &ffs_epfile_operations,
-						 &epfile->dentry))) {
-			ffs_epfiles_destroy(epfiles, i - 1);
-			return -ENOMEM;
-		}
-	}
-
-	ffs->epfiles = epfiles;
-	return 0;
-}
-
-static void ffs_epfiles_destroy(struct ffs_epfile *epfiles, unsigned count)
-{
-	struct ffs_epfile *epfile = epfiles;
-
-	ENTER();
-
-	for (; count; --count, ++epfile) {
-		BUG_ON(mutex_is_locked(&epfile->mutex) ||
-		       waitqueue_active(&epfile->wait));
-		if (epfile->dentry) {
-			d_delete(epfile->dentry);
-			dput(epfile->dentry);
-			epfile->dentry = NULL;
-		}
-	}
-
-	kfree(epfiles);
-}
-
-static int functionfs_bind_config(struct usb_composite_dev *cdev,
-				  struct usb_configuration *c,
-				  struct ffs_data *ffs)
-{
-	struct ffs_function *func;
-	int ret;
-
-	ENTER();
-
-	func = kzalloc(sizeof *func, GFP_KERNEL);
-	if (unlikely(!func))
-		return -ENOMEM;
-
-	func->function.name    = "Function FS Gadget";
-	func->function.strings = ffs->stringtabs;
-
-	func->function.bind    = ffs_func_bind;
-	func->function.unbind  = ffs_func_unbind;
-	func->function.set_alt = ffs_func_set_alt;
-	func->function.disable = ffs_func_disable;
-	func->function.setup   = ffs_func_setup;
-	func->function.suspend = ffs_func_suspend;
-	func->function.resume  = ffs_func_resume;
-
-	func->conf   = c;
-	func->gadget = cdev->gadget;
-	func->ffs = ffs;
-	ffs_data_get(ffs);
-
-	ret = usb_add_function(c, &func->function);
-	if (unlikely(ret))
-		ffs_func_free(func);
-
-	return ret;
-}
-
-static void ffs_func_free(struct ffs_function *func)
-{
-	struct ffs_ep *ep         = func->eps;
-	unsigned count            = func->ffs->eps_count;
-	unsigned long flags;
-
-	ENTER();
-
-	/* cleanup after autoconfig */
-	spin_lock_irqsave(&func->ffs->eps_lock, flags);
-	do {
-		if (ep->ep && ep->req)
-			usb_ep_free_request(ep->ep, ep->req);
-		ep->req = NULL;
-		++ep;
-	} while (--count);
-	spin_unlock_irqrestore(&func->ffs->eps_lock, flags);
-
-	ffs_data_put(func->ffs);
-
-	kfree(func->eps);
-	/*
-	 * eps and interfaces_nums are allocated in the same chunk so
-	 * only one free is required.  Descriptors are also allocated
-	 * in the same chunk.
-	 */
-
-	kfree(func);
-}
-
-static void ffs_func_eps_disable(struct ffs_function *func)
-{
-	struct ffs_ep *ep         = func->eps;
-	struct ffs_epfile *epfile = func->ffs->epfiles;
-	unsigned count            = func->ffs->eps_count;
-	unsigned long flags;
-
-	spin_lock_irqsave(&func->ffs->eps_lock, flags);
-	do {
-		/* pending requests get nuked */
-		if (likely(ep->ep))
-			usb_ep_disable(ep->ep);
-		epfile->ep = NULL;
-
-		++ep;
-		++epfile;
-	} while (--count);
-	spin_unlock_irqrestore(&func->ffs->eps_lock, flags);
-}
-
-static int ffs_func_eps_enable(struct ffs_function *func)
-{
-	struct ffs_data *ffs      = func->ffs;
-	struct ffs_ep *ep         = func->eps;
-	struct ffs_epfile *epfile = ffs->epfiles;
-	unsigned count            = ffs->eps_count;
-	unsigned long flags;
-	int ret = 0;
-
-	spin_lock_irqsave(&func->ffs->eps_lock, flags);
-	do {
-		struct usb_endpoint_descriptor *ds;
-		ds = ep->descs[ep->descs[1] ? 1 : 0];
-
-		ep->ep->driver_data = ep;
-		ep->ep->desc = ds;
-		ret = usb_ep_enable(ep->ep);
-		if (likely(!ret)) {
-			epfile->ep = ep;
-			epfile->in = usb_endpoint_dir_in(ds);
-			epfile->isoc = usb_endpoint_xfer_isoc(ds);
-		} else {
-			break;
-		}
-
-		wake_up(&epfile->wait);
-
-		++ep;
-		++epfile;
-	} while (--count);
-	spin_unlock_irqrestore(&func->ffs->eps_lock, flags);
-
-	return ret;
-}
-
-
-/* Parsing and building descriptors and strings *****************************/
-
-/*
- * This validates if data pointed by data is a valid USB descriptor as
- * well as record how many interfaces, endpoints and strings are
- * required by given configuration.  Returns address after the
- * descriptor or NULL if data is invalid.
- */
-
-enum ffs_entity_type {
-	FFS_DESCRIPTOR, FFS_INTERFACE, FFS_STRING, FFS_ENDPOINT
-};
-
-typedef int (*ffs_entity_callback)(enum ffs_entity_type entity,
-				   u8 *valuep,
-				   struct usb_descriptor_header *desc,
-				   void *priv);
-
-static int __must_check ffs_do_desc(char *data, unsigned len,
-				    ffs_entity_callback entity, void *priv)
-{
-	struct usb_descriptor_header *_ds = (void *)data;
-	u8 length;
-	int ret;
-
-	ENTER();
-
-	/* At least two bytes are required: length and type */
-	if (len < 2) {
-		pr_vdebug("descriptor too short\n");
-		return -EINVAL;
-	}
-
-	/* If we have at least as many bytes as the descriptor takes? */
-	length = _ds->bLength;
-	if (len < length) {
-		pr_vdebug("descriptor longer then available data\n");
-		return -EINVAL;
-	}
-
-#define __entity_check_INTERFACE(val)  1
-#define __entity_check_STRING(val)     (val)
-#define __entity_check_ENDPOINT(val)   ((val) & USB_ENDPOINT_NUMBER_MASK)
-#define __entity(type, val) do {					\
-		pr_vdebug("entity " #type "(%02x)\n", (val));		\
-		if (unlikely(!__entity_check_ ##type(val))) {		\
-			pr_vdebug("invalid entity's value\n");		\
-			return -EINVAL;					\
-		}							\
-		ret = entity(FFS_ ##type, &val, _ds, priv);		\
-		if (unlikely(ret < 0)) {				\
-			pr_debug("entity " #type "(%02x); ret = %d\n",	\
-				 (val), ret);				\
-			return ret;					\
-		}							\
-	} while (0)
-
-	/* Parse descriptor depending on type. */
-	switch (_ds->bDescriptorType) {
-	case USB_DT_DEVICE:
-	case USB_DT_CONFIG:
-	case USB_DT_STRING:
-	case USB_DT_DEVICE_QUALIFIER:
-		/* function can't have any of those */
-		pr_vdebug("descriptor reserved for gadget: %d\n",
-		      _ds->bDescriptorType);
-		return -EINVAL;
-
-	case USB_DT_INTERFACE: {
-		struct usb_interface_descriptor *ds = (void *)_ds;
-		pr_vdebug("interface descriptor\n");
-		if (length != sizeof *ds)
-			goto inv_length;
-
-		__entity(INTERFACE, ds->bInterfaceNumber);
-		if (ds->iInterface)
-			__entity(STRING, ds->iInterface);
-	}
-		break;
-
-	case USB_DT_ENDPOINT: {
-		struct usb_endpoint_descriptor *ds = (void *)_ds;
-		pr_vdebug("endpoint descriptor\n");
-		if (length != USB_DT_ENDPOINT_SIZE &&
-		    length != USB_DT_ENDPOINT_AUDIO_SIZE)
-			goto inv_length;
-		__entity(ENDPOINT, ds->bEndpointAddress);
-	}
-		break;
-
-	case HID_DT_HID:
-		pr_vdebug("hid descriptor\n");
-		if (length != sizeof(struct hid_descriptor))
-			goto inv_length;
-		break;
-
-	case USB_DT_OTG:
-		if (length != sizeof(struct usb_otg_descriptor))
-			goto inv_length;
-		break;
-
-	case USB_DT_INTERFACE_ASSOCIATION: {
-		struct usb_interface_assoc_descriptor *ds = (void *)_ds;
-		pr_vdebug("interface association descriptor\n");
-		if (length != sizeof *ds)
-			goto inv_length;
-		if (ds->iFunction)
-			__entity(STRING, ds->iFunction);
-	}
-		break;
-
-	case USB_DT_OTHER_SPEED_CONFIG:
-	case USB_DT_INTERFACE_POWER:
-	case USB_DT_DEBUG:
-	case USB_DT_SECURITY:
-	case USB_DT_CS_RADIO_CONTROL:
-		/* TODO */
-		pr_vdebug("unimplemented descriptor: %d\n", _ds->bDescriptorType);
-		return -EINVAL;
-
-	default:
-		/* We should never be here */
-		pr_vdebug("unknown descriptor: %d\n", _ds->bDescriptorType);
-		return -EINVAL;
-
-inv_length:
-		pr_vdebug("invalid length: %d (descriptor %d)\n",
-			  _ds->bLength, _ds->bDescriptorType);
-		return -EINVAL;
-	}
-
-#undef __entity
-#undef __entity_check_DESCRIPTOR
-#undef __entity_check_INTERFACE
-#undef __entity_check_STRING
-#undef __entity_check_ENDPOINT
-
-	return length;
-}
-
-static int __must_check ffs_do_descs(unsigned count, char *data, unsigned len,
-				     ffs_entity_callback entity, void *priv)
-{
-	const unsigned _len = len;
-	unsigned long num = 0;
-
-	ENTER();
-
-	for (;;) {
-		int ret;
-
-		if (num == count)
-			data = NULL;
-
-		/* Record "descriptor" entity */
-		ret = entity(FFS_DESCRIPTOR, (u8 *)num, (void *)data, priv);
-		if (unlikely(ret < 0)) {
-			pr_debug("entity DESCRIPTOR(%02lx); ret = %d\n",
-				 num, ret);
-			return ret;
-		}
-
-		if (!data)
-			return _len - len;
-
-		ret = ffs_do_desc(data, len, entity, priv);
-		if (unlikely(ret < 0)) {
-			pr_debug("%s returns %d\n", __func__, ret);
-			return ret;
-		}
-
-		len -= ret;
-		data += ret;
-		++num;
-	}
-}
-
-static int __ffs_data_do_entity(enum ffs_entity_type type,
-				u8 *valuep, struct usb_descriptor_header *desc,
-				void *priv)
-{
-	struct ffs_data *ffs = priv;
-
-	ENTER();
-
-	switch (type) {
-	case FFS_DESCRIPTOR:
-		break;
-
-	case FFS_INTERFACE:
-		/*
-		 * Interfaces are indexed from zero so if we
-		 * encountered interface "n" then there are at least
-		 * "n+1" interfaces.
-		 */
-		if (*valuep >= ffs->interfaces_count)
-			ffs->interfaces_count = *valuep + 1;
-		break;
-
-	case FFS_STRING:
-		/*
-		 * Strings are indexed from 1 (0 is magic ;) reserved
-		 * for languages list or some such)
-		 */
-		if (*valuep > ffs->strings_count)
-			ffs->strings_count = *valuep;
-		break;
-
-	case FFS_ENDPOINT:
-		/* Endpoints are indexed from 1 as well. */
-		if ((*valuep & USB_ENDPOINT_NUMBER_MASK) > ffs->eps_count)
-			ffs->eps_count = (*valuep & USB_ENDPOINT_NUMBER_MASK);
-		break;
-	}
-
-	return 0;
-}
-
-static int __ffs_data_got_descs(struct ffs_data *ffs,
-				char *const _data, size_t len)
-{
-	unsigned fs_count, hs_count;
-	int fs_len, ret = -EINVAL;
-	char *data = _data;
-
-	ENTER();
-
-	if (unlikely(get_unaligned_le32(data) != FUNCTIONFS_DESCRIPTORS_MAGIC ||
-		     get_unaligned_le32(data + 4) != len))
-		goto error;
-	fs_count = get_unaligned_le32(data +  8);
-	hs_count = get_unaligned_le32(data + 12);
-
-	if (!fs_count && !hs_count)
-		goto einval;
-
-	data += 16;
-	len  -= 16;
-
-	if (likely(fs_count)) {
-		fs_len = ffs_do_descs(fs_count, data, len,
-				      __ffs_data_do_entity, ffs);
-		if (unlikely(fs_len < 0)) {
-			ret = fs_len;
-			goto error;
-		}
-
-		data += fs_len;
-		len  -= fs_len;
-	} else {
-		fs_len = 0;
-	}
-
-	if (likely(hs_count)) {
-		ret = ffs_do_descs(hs_count, data, len,
-				   __ffs_data_do_entity, ffs);
-		if (unlikely(ret < 0))
-			goto error;
-	} else {
-		ret = 0;
-	}
-
-	if (unlikely(len != ret))
-		goto einval;
-
-	ffs->raw_fs_descs_length = fs_len;
-	ffs->raw_descs_length    = fs_len + ret;
-	ffs->raw_descs           = _data;
-	ffs->fs_descs_count      = fs_count;
-	ffs->hs_descs_count      = hs_count;
-
-	return 0;
-
-einval:
-	ret = -EINVAL;
-error:
-	kfree(_data);
-	return ret;
-}
-
-static int __ffs_data_got_strings(struct ffs_data *ffs,
-				  char *const _data, size_t len)
-{
-	u32 str_count, needed_count, lang_count;
-	struct usb_gadget_strings **stringtabs, *t;
-	struct usb_string *strings, *s;
-	const char *data = _data;
-
-	ENTER();
-
-	if (unlikely(get_unaligned_le32(data) != FUNCTIONFS_STRINGS_MAGIC ||
-		     get_unaligned_le32(data + 4) != len))
-		goto error;
-	str_count  = get_unaligned_le32(data + 8);
-	lang_count = get_unaligned_le32(data + 12);
-
-	/* if one is zero the other must be zero */
-	if (unlikely(!str_count != !lang_count))
-		goto error;
-
-	/* Do we have at least as many strings as descriptors need? */
-	needed_count = ffs->strings_count;
-	if (unlikely(str_count < needed_count))
-		goto error;
-
-	/*
-	 * If we don't need any strings just return and free all
-	 * memory.
-	 */
-	if (!needed_count) {
-		kfree(_data);
-		return 0;
-	}
-
-	/* Allocate everything in one chunk so there's less maintenance. */
-	{
-		struct {
-			struct usb_gadget_strings *stringtabs[lang_count + 1];
-			struct usb_gadget_strings stringtab[lang_count];
-			struct usb_string strings[lang_count*(needed_count+1)];
-		} *d;
-		unsigned i = 0;
-
-		d = kmalloc(sizeof *d, GFP_KERNEL);
-		if (unlikely(!d)) {
-			kfree(_data);
-			return -ENOMEM;
-		}
-
-		stringtabs = d->stringtabs;
-		t = d->stringtab;
-		i = lang_count;
-		do {
-			*stringtabs++ = t++;
-		} while (--i);
-		*stringtabs = NULL;
-
-		stringtabs = d->stringtabs;
-		t = d->stringtab;
-		s = d->strings;
-		strings = s;
-	}
-
-	/* For each language */
-	data += 16;
-	len -= 16;
-
-	do { /* lang_count > 0 so we can use do-while */
-		unsigned needed = needed_count;
-
-		if (unlikely(len < 3))
-			goto error_free;
-		t->language = get_unaligned_le16(data);
-		t->strings  = s;
-		++t;
-
-		data += 2;
-		len -= 2;
-
-		/* For each string */
-		do { /* str_count > 0 so we can use do-while */
-			size_t length = strnlen(data, len);
-
-			if (unlikely(length == len))
-				goto error_free;
-
-			/*
-			 * User may provide more strings then we need,
-			 * if that's the case we simply ignore the
-			 * rest
-			 */
-			if (likely(needed)) {
-				/*
-				 * s->id will be set while adding
-				 * function to configuration so for
-				 * now just leave garbage here.
-				 */
-				s->s = data;
-				--needed;
-				++s;
-			}
-
-			data += length + 1;
-			len -= length + 1;
-		} while (--str_count);
-
-		s->id = 0;   /* terminator */
-		s->s = NULL;
-		++s;
-
-	} while (--lang_count);
-
-	/* Some garbage left? */
-	if (unlikely(len))
-		goto error_free;
-
-	/* Done! */
-	ffs->stringtabs = stringtabs;
-	ffs->raw_strings = _data;
-
-	return 0;
-
-error_free:
-	kfree(stringtabs);
-error:
-	kfree(_data);
-	return -EINVAL;
-}
-
-
-/* Events handling and management *******************************************/
-
-static void __ffs_event_add(struct ffs_data *ffs,
-			    enum usb_functionfs_event_type type)
-{
-	enum usb_functionfs_event_type rem_type1, rem_type2 = type;
-	int neg = 0;
-
-	/*
-	 * Abort any unhandled setup
-	 *
-	 * We do not need to worry about some cmpxchg() changing value
-	 * of ffs->setup_state without holding the lock because when
-	 * state is FFS_SETUP_PENDING cmpxchg() in several places in
-	 * the source does nothing.
-	 */
-	if (ffs->setup_state == FFS_SETUP_PENDING)
-		ffs->setup_state = FFS_SETUP_CANCELED;
-
-	switch (type) {
-	case FUNCTIONFS_RESUME:
-		rem_type2 = FUNCTIONFS_SUSPEND;
-		/* FALL THROUGH */
-	case FUNCTIONFS_SUSPEND:
-	case FUNCTIONFS_SETUP:
-		rem_type1 = type;
-		/* Discard all similar events */
-		break;
-
-	case FUNCTIONFS_BIND:
-	case FUNCTIONFS_UNBIND:
-	case FUNCTIONFS_DISABLE:
-	case FUNCTIONFS_ENABLE:
-		/* Discard everything other then power management. */
-		rem_type1 = FUNCTIONFS_SUSPEND;
-		rem_type2 = FUNCTIONFS_RESUME;
-		neg = 1;
-		break;
-
-	default:
-		BUG();
-	}
-
-	{
-		u8 *ev  = ffs->ev.types, *out = ev;
-		unsigned n = ffs->ev.count;
-		for (; n; --n, ++ev)
-			if ((*ev == rem_type1 || *ev == rem_type2) == neg)
-				*out++ = *ev;
-			else
-				pr_vdebug("purging event %d\n", *ev);
-		ffs->ev.count = out - ffs->ev.types;
-	}
-
-	pr_vdebug("adding event %d\n", type);
-	ffs->ev.types[ffs->ev.count++] = type;
-	wake_up_locked(&ffs->ev.waitq);
-}
-
-static void ffs_event_add(struct ffs_data *ffs,
-			  enum usb_functionfs_event_type type)
-{
-	unsigned long flags;
-	spin_lock_irqsave(&ffs->ev.waitq.lock, flags);
-	__ffs_event_add(ffs, type);
-	spin_unlock_irqrestore(&ffs->ev.waitq.lock, flags);
-}
-
-
-/* Bind/unbind USB function hooks *******************************************/
-
-static int __ffs_func_bind_do_descs(enum ffs_entity_type type, u8 *valuep,
-				    struct usb_descriptor_header *desc,
-				    void *priv)
-{
-	struct usb_endpoint_descriptor *ds = (void *)desc;
-	struct ffs_function *func = priv;
-	struct ffs_ep *ffs_ep;
-
-	/*
-	 * If hs_descriptors is not NULL then we are reading hs
-	 * descriptors now
-	 */
-	const int isHS = func->function.hs_descriptors != NULL;
-	unsigned idx;
-
-	if (type != FFS_DESCRIPTOR)
-		return 0;
-
-	if (isHS)
-		func->function.hs_descriptors[(long)valuep] = desc;
-	else
-		func->function.descriptors[(long)valuep]    = desc;
-
-	if (!desc || desc->bDescriptorType != USB_DT_ENDPOINT)
-		return 0;
-
-	idx = (ds->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK) - 1;
-	ffs_ep = func->eps + idx;
-
-	if (unlikely(ffs_ep->descs[isHS])) {
-		pr_vdebug("two %sspeed descriptors for EP %d\n",
-			  isHS ? "high" : "full",
-			  ds->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
-		return -EINVAL;
-	}
-	ffs_ep->descs[isHS] = ds;
-
-	ffs_dump_mem(": Original  ep desc", ds, ds->bLength);
-	if (ffs_ep->ep) {
-		ds->bEndpointAddress = ffs_ep->descs[0]->bEndpointAddress;
-		if (!ds->wMaxPacketSize)
-			ds->wMaxPacketSize = ffs_ep->descs[0]->wMaxPacketSize;
-	} else {
-		struct usb_request *req;
-		struct usb_ep *ep;
-
-		pr_vdebug("autoconfig\n");
-		ep = usb_ep_autoconfig(func->gadget, ds);
-		if (unlikely(!ep))
-			return -ENOTSUPP;
-		ep->driver_data = func->eps + idx;
-
-		req = usb_ep_alloc_request(ep, GFP_KERNEL);
-		if (unlikely(!req))
-			return -ENOMEM;
-
-		ffs_ep->ep  = ep;
-		ffs_ep->req = req;
-		func->eps_revmap[ds->bEndpointAddress &
-				 USB_ENDPOINT_NUMBER_MASK] = idx + 1;
-	}
-	ffs_dump_mem(": Rewritten ep desc", ds, ds->bLength);
-
-	return 0;
-}
-
-static int __ffs_func_bind_do_nums(enum ffs_entity_type type, u8 *valuep,
-				   struct usb_descriptor_header *desc,
-				   void *priv)
-{
-	struct ffs_function *func = priv;
-	unsigned idx;
-	u8 newValue;
-
-	switch (type) {
-	default:
-	case FFS_DESCRIPTOR:
-		/* Handled in previous pass by __ffs_func_bind_do_descs() */
-		return 0;
-
-	case FFS_INTERFACE:
-		idx = *valuep;
-		if (func->interfaces_nums[idx] < 0) {
-			int id = usb_interface_id(func->conf, &func->function);
-			if (unlikely(id < 0))
-				return id;
-			func->interfaces_nums[idx] = id;
-		}
-		newValue = func->interfaces_nums[idx];
-		break;
-
-	case FFS_STRING:
-		/* String' IDs are allocated when fsf_data is bound to cdev */
-		newValue = func->ffs->stringtabs[0]->strings[*valuep - 1].id;
-		break;
-
-	case FFS_ENDPOINT:
-		/*
-		 * USB_DT_ENDPOINT are handled in
-		 * __ffs_func_bind_do_descs().
-		 */
-		if (desc->bDescriptorType == USB_DT_ENDPOINT)
-			return 0;
-
-		idx = (*valuep & USB_ENDPOINT_NUMBER_MASK) - 1;
-		if (unlikely(!func->eps[idx].ep))
-			return -EINVAL;
-
-		{
-			struct usb_endpoint_descriptor **descs;
-			descs = func->eps[idx].descs;
-			newValue = descs[descs[0] ? 0 : 1]->bEndpointAddress;
-		}
-		break;
-	}
-
-	pr_vdebug("%02x -> %02x\n", *valuep, newValue);
-	*valuep = newValue;
-	return 0;
-}
-
-static int ffs_func_bind(struct usb_configuration *c,
-			 struct usb_function *f)
-{
-	struct ffs_function *func = ffs_func_from_usb(f);
-	struct ffs_data *ffs = func->ffs;
-
-	const int full = !!func->ffs->fs_descs_count;
-	const int high = gadget_is_dualspeed(func->gadget) &&
-		func->ffs->hs_descs_count;
-
-	int ret;
-
-	/* Make it a single chunk, less management later on */
-	struct {
-		struct ffs_ep eps[ffs->eps_count];
-		struct usb_descriptor_header
-			*fs_descs[full ? ffs->fs_descs_count + 1 : 0];
-		struct usb_descriptor_header
-			*hs_descs[high ? ffs->hs_descs_count + 1 : 0];
-		short inums[ffs->interfaces_count];
-		char raw_descs[high ? ffs->raw_descs_length
-				    : ffs->raw_fs_descs_length];
-	} *data;
-
-	ENTER();
-
-	/* Only high speed but not supported by gadget? */
-	if (unlikely(!(full | high)))
-		return -ENOTSUPP;
-
-	/* Allocate */
-	data = kmalloc(sizeof *data, GFP_KERNEL);
-	if (unlikely(!data))
-		return -ENOMEM;
-
-	/* Zero */
-	memset(data->eps, 0, sizeof data->eps);
-	memcpy(data->raw_descs, ffs->raw_descs + 16, sizeof data->raw_descs);
-	memset(data->inums, 0xff, sizeof data->inums);
-	for (ret = ffs->eps_count; ret; --ret)
-		data->eps[ret].num = -1;
-
-	/* Save pointers */
-	func->eps             = data->eps;
-	func->interfaces_nums = data->inums;
-
-	/*
-	 * Go through all the endpoint descriptors and allocate
-	 * endpoints first, so that later we can rewrite the endpoint
-	 * numbers without worrying that it may be described later on.
-	 */
-	if (likely(full)) {
-		func->function.descriptors = data->fs_descs;
-		ret = ffs_do_descs(ffs->fs_descs_count,
-				   data->raw_descs,
-				   sizeof data->raw_descs,
-				   __ffs_func_bind_do_descs, func);
-		if (unlikely(ret < 0))
-			goto error;
-	} else {
-		ret = 0;
-	}
-
-	if (likely(high)) {
-		func->function.hs_descriptors = data->hs_descs;
-		ret = ffs_do_descs(ffs->hs_descs_count,
-				   data->raw_descs + ret,
-				   (sizeof data->raw_descs) - ret,
-				   __ffs_func_bind_do_descs, func);
-	}
-
-	/*
-	 * Now handle interface numbers allocation and interface and
-	 * endpoint numbers rewriting.  We can do that in one go
-	 * now.
-	 */
-	ret = ffs_do_descs(ffs->fs_descs_count +
-			   (high ? ffs->hs_descs_count : 0),
-			   data->raw_descs, sizeof data->raw_descs,
-			   __ffs_func_bind_do_nums, func);
-	if (unlikely(ret < 0))
-		goto error;
-
-	/* And we're done */
-	ffs_event_add(ffs, FUNCTIONFS_BIND);
-	return 0;
-
-error:
-	/* XXX Do we need to release all claimed endpoints here? */
-	return ret;
-}
-
-
-/* Other USB function hooks *************************************************/
-
-static void ffs_func_unbind(struct usb_configuration *c,
-			    struct usb_function *f)
-{
-	struct ffs_function *func = ffs_func_from_usb(f);
-	struct ffs_data *ffs = func->ffs;
-
-	ENTER();
-
-	if (ffs->func == func) {
-		ffs_func_eps_disable(func);
-		ffs->func = NULL;
-	}
-
-	ffs_event_add(ffs, FUNCTIONFS_UNBIND);
-
-	ffs_func_free(func);
-}
-
-static int ffs_func_set_alt(struct usb_function *f,
-			    unsigned interface, unsigned alt)
-{
-	struct ffs_function *func = ffs_func_from_usb(f);
-	struct ffs_data *ffs = func->ffs;
-	int ret = 0, intf;
-
-	if (alt != (unsigned)-1) {
-		intf = ffs_func_revmap_intf(func, interface);
-		if (unlikely(intf < 0))
-			return intf;
-	}
-
-	if (ffs->func)
-		ffs_func_eps_disable(ffs->func);
-
-	if (ffs->state != FFS_ACTIVE)
-		return -ENODEV;
-
-	if (alt == (unsigned)-1) {
-		ffs->func = NULL;
-		ffs_event_add(ffs, FUNCTIONFS_DISABLE);
-		return 0;
-	}
-
-	ffs->func = func;
-	ret = ffs_func_eps_enable(func);
-	if (likely(ret >= 0))
-		ffs_event_add(ffs, FUNCTIONFS_ENABLE);
-	return ret;
-}
-
-static void ffs_func_disable(struct usb_function *f)
-{
-	ffs_func_set_alt(f, 0, (unsigned)-1);
-}
-
-static int ffs_func_setup(struct usb_function *f,
-			  const struct usb_ctrlrequest *creq)
-{
-	struct ffs_function *func = ffs_func_from_usb(f);
-	struct ffs_data *ffs = func->ffs;
-	unsigned long flags;
-	int ret;
-
-	ENTER();
-
-	pr_vdebug("creq->bRequestType = %02x\n", creq->bRequestType);
-	pr_vdebug("creq->bRequest     = %02x\n", creq->bRequest);
-	pr_vdebug("creq->wValue       = %04x\n", le16_to_cpu(creq->wValue));
-	pr_vdebug("creq->wIndex       = %04x\n", le16_to_cpu(creq->wIndex));
-	pr_vdebug("creq->wLength      = %04x\n", le16_to_cpu(creq->wLength));
-
-	/*
-	 * Most requests directed to interface go through here
-	 * (notable exceptions are set/get interface) so we need to
-	 * handle them.  All other either handled by composite or
-	 * passed to usb_configuration->setup() (if one is set).  No
-	 * matter, we will handle requests directed to endpoint here
-	 * as well (as it's straightforward) but what to do with any
-	 * other request?
-	 */
-	if (ffs->state != FFS_ACTIVE)
-		return -ENODEV;
-
-	switch (creq->bRequestType & USB_RECIP_MASK) {
-	case USB_RECIP_INTERFACE:
-		ret = ffs_func_revmap_intf(func, le16_to_cpu(creq->wIndex));
-		if (unlikely(ret < 0))
-			return ret;
-		break;
-
-	case USB_RECIP_ENDPOINT:
-		ret = ffs_func_revmap_ep(func, le16_to_cpu(creq->wIndex));
-		if (unlikely(ret < 0))
-			return ret;
-		break;
-
-	default:
-		return -EOPNOTSUPP;
-	}
-
-	spin_lock_irqsave(&ffs->ev.waitq.lock, flags);
-	ffs->ev.setup = *creq;
-	ffs->ev.setup.wIndex = cpu_to_le16(ret);
-	__ffs_event_add(ffs, FUNCTIONFS_SETUP);
-	spin_unlock_irqrestore(&ffs->ev.waitq.lock, flags);
-
-	return 0;
-}
-
-static void ffs_func_suspend(struct usb_function *f)
-{
-	ENTER();
-	ffs_event_add(ffs_func_from_usb(f)->ffs, FUNCTIONFS_SUSPEND);
-}
-
-static void ffs_func_resume(struct usb_function *f)
-{
-	ENTER();
-	ffs_event_add(ffs_func_from_usb(f)->ffs, FUNCTIONFS_RESUME);
-}
-
-
-/* Endpoint and interface numbers reverse mapping ***************************/
-
-static int ffs_func_revmap_ep(struct ffs_function *func, u8 num)
-{
-	num = func->eps_revmap[num & USB_ENDPOINT_NUMBER_MASK];
-	return num ? num : -EDOM;
-}
-
-static int ffs_func_revmap_intf(struct ffs_function *func, u8 intf)
-{
-	short *nums = func->interfaces_nums;
-	unsigned count = func->ffs->interfaces_count;
-
-	for (; count; --count, ++nums) {
-		if (*nums >= 0 && *nums == intf)
-			return nums - func->interfaces_nums;
-	}
-
-	return -EDOM;
-}
-
-
-/* Misc helper functions ****************************************************/
-
-static int ffs_mutex_lock(struct mutex *mutex, unsigned nonblock)
-{
-	return nonblock
-		? likely(mutex_trylock(mutex)) ? 0 : -EAGAIN
-		: mutex_lock_interruptible(mutex);
-}
-
-static char *ffs_prepare_buffer(const char * __user buf, size_t len)
-{
-	char *data;
-
-	if (unlikely(!len))
-		return NULL;
-
-	data = kmalloc(len, GFP_KERNEL);
-	if (unlikely(!data))
-		return ERR_PTR(-ENOMEM);
-
-	if (unlikely(__copy_from_user(data, buf, len))) {
-		kfree(data);
-		return ERR_PTR(-EFAULT);
-	}
-
-	pr_vdebug("Buffer from user space:\n");
-	ffs_dump_mem("", data, len);
-
-	return data;
-}
diff --git a/drivers/staging/ccg/f_mass_storage.c b/drivers/staging/ccg/f_mass_storage.c
deleted file mode 100644
index 20bc2b4..0000000
--- a/drivers/staging/ccg/f_mass_storage.c
+++ /dev/null
@@ -1,3135 +0,0 @@
-/*
- * f_mass_storage.c -- Mass Storage USB Composite Function
- *
- * Copyright (C) 2003-2008 Alan Stern
- * Copyright (C) 2009 Samsung Electronics
- *                    Author: Michal Nazarewicz <mina86@mina86.com>
- * 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, this list of conditions, and the following disclaimer,
- *    without modification.
- * 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 names of the above-listed copyright holders may not 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 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.
- */
-
-/*
- * The Mass Storage Function acts as a USB Mass Storage device,
- * appearing to the host as a disk drive or as a CD-ROM drive.  In
- * addition to providing an example of a genuinely useful composite
- * function for a USB device, it also illustrates a technique of
- * double-buffering for increased throughput.
- *
- * For more information about MSF and in particular its module
- * parameters and sysfs interface read the
- * <Documentation/usb/mass-storage.txt> file.
- */
-
-/*
- * MSF is configured by specifying a fsg_config structure.  It has the
- * following fields:
- *
- *	nluns		Number of LUNs function have (anywhere from 1
- *				to FSG_MAX_LUNS which is 8).
- *	luns		An array of LUN configuration values.  This
- *				should be filled for each LUN that
- *				function will include (ie. for "nluns"
- *				LUNs).  Each element of the array has
- *				the following fields:
- *	->filename	The path to the backing file for the LUN.
- *				Required if LUN is not marked as
- *				removable.
- *	->ro		Flag specifying access to the LUN shall be
- *				read-only.  This is implied if CD-ROM
- *				emulation is enabled as well as when
- *				it was impossible to open "filename"
- *				in R/W mode.
- *	->removable	Flag specifying that LUN shall be indicated as
- *				being removable.
- *	->cdrom		Flag specifying that LUN shall be reported as
- *				being a CD-ROM.
- *	->nofua		Flag specifying that FUA flag in SCSI WRITE(10,12)
- *				commands for this LUN shall be ignored.
- *
- *	vendor_name
- *	product_name
- *	release		Information used as a reply to INQUIRY
- *				request.  To use default set to NULL,
- *				NULL, 0xffff respectively.  The first
- *				field should be 8 and the second 16
- *				characters or less.
- *
- *	can_stall	Set to permit function to halt bulk endpoints.
- *				Disabled on some USB devices known not
- *				to work correctly.  You should set it
- *				to true.
- *
- * If "removable" is not set for a LUN then a backing file must be
- * specified.  If it is set, then NULL filename means the LUN's medium
- * is not loaded (an empty string as "filename" in the fsg_config
- * structure causes error).  The CD-ROM emulation includes a single
- * data track and no audio tracks; hence there need be only one
- * backing file per LUN.
- *
- * This function is heavily based on "File-backed Storage Gadget" by
- * Alan Stern which in turn is heavily based on "Gadget Zero" by David
- * Brownell.  The driver's SCSI command interface was based on the
- * "Information technology - Small Computer System Interface - 2"
- * document from X3T9.2 Project 375D, Revision 10L, 7-SEP-93,
- * available at <http://www.t10.org/ftp/t10/drafts/s2/s2-r10l.pdf>.
- * The single exception is opcode 0x23 (READ FORMAT CAPACITIES), which
- * was based on the "Universal Serial Bus Mass Storage Class UFI
- * Command Specification" document, Revision 1.0, December 14, 1998,
- * available at
- * <http://www.usb.org/developers/devclass_docs/usbmass-ufi10.pdf>.
- */
-
-/*
- *				Driver Design
- *
- * The MSF is fairly straightforward.  There is a main kernel
- * thread that handles most of the work.  Interrupt routines field
- * callbacks from the controller driver: bulk- and interrupt-request
- * completion notifications, endpoint-0 events, and disconnect events.
- * Completion events are passed to the main thread by wakeup calls.  Many
- * ep0 requests are handled at interrupt time, but SetInterface,
- * SetConfiguration, and device reset requests are forwarded to the
- * thread in the form of "exceptions" using SIGUSR1 signals (since they
- * should interrupt any ongoing file I/O operations).
- *
- * The thread's main routine implements the standard command/data/status
- * parts of a SCSI interaction.  It and its subroutines are full of tests
- * for pending signals/exceptions -- all this polling is necessary since
- * the kernel has no setjmp/longjmp equivalents.  (Maybe this is an
- * indication that the driver really wants to be running in userspace.)
- * An important point is that so long as the thread is alive it keeps an
- * open reference to the backing file.  This will prevent unmounting
- * the backing file's underlying filesystem and could cause problems
- * during system shutdown, for example.  To prevent such problems, the
- * thread catches INT, TERM, and KILL signals and converts them into
- * an EXIT exception.
- *
- * In normal operation the main thread is started during the gadget's
- * fsg_bind() callback and stopped during fsg_unbind().  But it can
- * also exit when it receives a signal, and there's no point leaving
- * the gadget running when the thread is dead.  As of this moment, MSF
- * provides no way to deregister the gadget when thread dies -- maybe
- * a callback functions is needed.
- *
- * To provide maximum throughput, the driver uses a circular pipeline of
- * buffer heads (struct fsg_buffhd).  In principle the pipeline can be
- * arbitrarily long; in practice the benefits don't justify having more
- * than 2 stages (i.e., double buffering).  But it helps to think of the
- * pipeline as being a long one.  Each buffer head contains a bulk-in and
- * a bulk-out request pointer (since the buffer can be used for both
- * output and input -- directions always are given from the host's
- * point of view) as well as a pointer to the buffer and various state
- * variables.
- *
- * Use of the pipeline follows a simple protocol.  There is a variable
- * (fsg->next_buffhd_to_fill) that points to the next buffer head to use.
- * At any time that buffer head may still be in use from an earlier
- * request, so each buffer head has a state variable indicating whether
- * it is EMPTY, FULL, or BUSY.  Typical use involves waiting for the
- * buffer head to be EMPTY, filling the buffer either by file I/O or by
- * USB I/O (during which the buffer head is BUSY), and marking the buffer
- * head FULL when the I/O is complete.  Then the buffer will be emptied
- * (again possibly by USB I/O, during which it is marked BUSY) and
- * finally marked EMPTY again (possibly by a completion routine).
- *
- * A module parameter tells the driver to avoid stalling the bulk
- * endpoints wherever the transport specification allows.  This is
- * necessary for some UDCs like the SuperH, which cannot reliably clear a
- * halt on a bulk endpoint.  However, under certain circumstances the
- * Bulk-only specification requires a stall.  In such cases the driver
- * will halt the endpoint and set a flag indicating that it should clear
- * the halt in software during the next device reset.  Hopefully this
- * will permit everything to work correctly.  Furthermore, although the
- * specification allows the bulk-out endpoint to halt when the host sends
- * too much data, implementing this would cause an unavoidable race.
- * The driver will always use the "no-stall" approach for OUT transfers.
- *
- * One subtle point concerns sending status-stage responses for ep0
- * requests.  Some of these requests, such as device reset, can involve
- * interrupting an ongoing file I/O operation, which might take an
- * arbitrarily long time.  During that delay the host might give up on
- * the original ep0 request and issue a new one.  When that happens the
- * driver should not notify the host about completion of the original
- * request, as the host will no longer be waiting for it.  So the driver
- * assigns to each ep0 request a unique tag, and it keeps track of the
- * tag value of the request associated with a long-running exception
- * (device-reset, interface-change, or configuration-change).  When the
- * exception handler is finished, the status-stage response is submitted
- * only if the current ep0 request tag is equal to the exception request
- * tag.  Thus only the most recently received ep0 request will get a
- * status-stage response.
- *
- * Warning: This driver source file is too long.  It ought to be split up
- * into a header file plus about 3 separate .c files, to handle the details
- * of the Gadget, USB Mass Storage, and SCSI protocols.
- */
-
-
-/* #define VERBOSE_DEBUG */
-/* #define DUMP_MSGS */
-
-#include <linux/blkdev.h>
-#include <linux/completion.h>
-#include <linux/dcache.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/fcntl.h>
-#include <linux/file.h>
-#include <linux/fs.h>
-#include <linux/kref.h>
-#include <linux/kthread.h>
-#include <linux/limits.h>
-#include <linux/rwsem.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/string.h>
-#include <linux/freezer.h>
-#include <linux/utsname.h>
-
-#include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
-#include <linux/usb/composite.h>
-
-#include "gadget_chips.h"
-
-
-/*------------------------------------------------------------------------*/
-
-#define FSG_DRIVER_DESC		"Mass Storage Function"
-#define FSG_DRIVER_VERSION	"2009/09/11"
-
-static const char fsg_string_interface[] = "Mass Storage";
-
-#define FSG_NO_DEVICE_STRINGS    1
-#define FSG_NO_OTG               1
-#define FSG_NO_INTR_EP           1
-
-#include "storage_common.c"
-
-
-/*-------------------------------------------------------------------------*/
-
-struct fsg_dev;
-struct fsg_common;
-
-/* FSF callback functions */
-struct fsg_operations {
-	/*
-	 * Callback function to call when thread exits.  If no
-	 * callback is set or it returns value lower then zero MSF
-	 * will force eject all LUNs it operates on (including those
-	 * marked as non-removable or with prevent_medium_removal flag
-	 * set).
-	 */
-	int (*thread_exits)(struct fsg_common *common);
-
-	/*
-	 * Called prior to ejection.  Negative return means error,
-	 * zero means to continue with ejection, positive means not to
-	 * eject.
-	 */
-	int (*pre_eject)(struct fsg_common *common,
-			 struct fsg_lun *lun, int num);
-	/*
-	 * Called after ejection.  Negative return means error, zero
-	 * or positive is just a success.
-	 */
-	int (*post_eject)(struct fsg_common *common,
-			  struct fsg_lun *lun, int num);
-};
-
-/* Data shared by all the FSG instances. */
-struct fsg_common {
-	struct usb_gadget	*gadget;
-	struct usb_composite_dev *cdev;
-	struct fsg_dev		*fsg, *new_fsg;
-	wait_queue_head_t	fsg_wait;
-
-	/* filesem protects: backing files in use */
-	struct rw_semaphore	filesem;
-
-	/* lock protects: state, all the req_busy's */
-	spinlock_t		lock;
-
-	struct usb_ep		*ep0;		/* Copy of gadget->ep0 */
-	struct usb_request	*ep0req;	/* Copy of cdev->req */
-	unsigned int		ep0_req_tag;
-
-	struct fsg_buffhd	*next_buffhd_to_fill;
-	struct fsg_buffhd	*next_buffhd_to_drain;
-	struct fsg_buffhd	*buffhds;
-
-	int			cmnd_size;
-	u8			cmnd[MAX_COMMAND_SIZE];
-
-	unsigned int		nluns;
-	unsigned int		lun;
-	struct fsg_lun		*luns;
-	struct fsg_lun		*curlun;
-
-	unsigned int		bulk_out_maxpacket;
-	enum fsg_state		state;		/* For exception handling */
-	unsigned int		exception_req_tag;
-
-	enum data_direction	data_dir;
-	u32			data_size;
-	u32			data_size_from_cmnd;
-	u32			tag;
-	u32			residue;
-	u32			usb_amount_left;
-
-	unsigned int		can_stall:1;
-	unsigned int		free_storage_on_release:1;
-	unsigned int		phase_error:1;
-	unsigned int		short_packet_received:1;
-	unsigned int		bad_lun_okay:1;
-	unsigned int		running:1;
-
-	int			thread_wakeup_needed;
-	struct completion	thread_notifier;
-	struct task_struct	*thread_task;
-
-	/* Callback functions. */
-	const struct fsg_operations	*ops;
-	/* Gadget's private data. */
-	void			*private_data;
-
-	/*
-	 * Vendor (8 chars), product (16 chars), release (4
-	 * hexadecimal digits) and NUL byte
-	 */
-	char inquiry_string[8 + 16 + 4 + 1];
-
-	struct kref		ref;
-};
-
-struct fsg_config {
-	unsigned nluns;
-	struct fsg_lun_config {
-		const char *filename;
-		char ro;
-		char removable;
-		char cdrom;
-		char nofua;
-	} luns[FSG_MAX_LUNS];
-
-	/* Callback functions. */
-	const struct fsg_operations	*ops;
-	/* Gadget's private data. */
-	void			*private_data;
-
-	const char *vendor_name;		/*  8 characters or less */
-	const char *product_name;		/* 16 characters or less */
-	u16 release;
-
-	char			can_stall;
-};
-
-struct fsg_dev {
-	struct usb_function	function;
-	struct usb_gadget	*gadget;	/* Copy of cdev->gadget */
-	struct fsg_common	*common;
-
-	u16			interface_number;
-
-	unsigned int		bulk_in_enabled:1;
-	unsigned int		bulk_out_enabled:1;
-
-	unsigned long		atomic_bitflags;
-#define IGNORE_BULK_OUT		0
-
-	struct usb_ep		*bulk_in;
-	struct usb_ep		*bulk_out;
-};
-
-static inline int __fsg_is_set(struct fsg_common *common,
-			       const char *func, unsigned line)
-{
-	if (common->fsg)
-		return 1;
-	ERROR(common, "common->fsg is NULL in %s at %u\n", func, line);
-	WARN_ON(1);
-	return 0;
-}
-
-#define fsg_is_set(common) likely(__fsg_is_set(common, __func__, __LINE__))
-
-static inline struct fsg_dev *fsg_from_func(struct usb_function *f)
-{
-	return container_of(f, struct fsg_dev, function);
-}
-
-typedef void (*fsg_routine_t)(struct fsg_dev *);
-
-static int exception_in_progress(struct fsg_common *common)
-{
-	return common->state > FSG_STATE_IDLE;
-}
-
-/* Make bulk-out requests be divisible by the maxpacket size */
-static void set_bulk_out_req_length(struct fsg_common *common,
-				    struct fsg_buffhd *bh, unsigned int length)
-{
-	unsigned int	rem;
-
-	bh->bulk_out_intended_length = length;
-	rem = length % common->bulk_out_maxpacket;
-	if (rem > 0)
-		length += common->bulk_out_maxpacket - rem;
-	bh->outreq->length = length;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static int fsg_set_halt(struct fsg_dev *fsg, struct usb_ep *ep)
-{
-	const char	*name;
-
-	if (ep == fsg->bulk_in)
-		name = "bulk-in";
-	else if (ep == fsg->bulk_out)
-		name = "bulk-out";
-	else
-		name = ep->name;
-	DBG(fsg, "%s set halt\n", name);
-	return usb_ep_set_halt(ep);
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/* These routines may be called in process context or in_irq */
-
-/* Caller must hold fsg->lock */
-static void wakeup_thread(struct fsg_common *common)
-{
-	/* Tell the main thread that something has happened */
-	common->thread_wakeup_needed = 1;
-	if (common->thread_task)
-		wake_up_process(common->thread_task);
-}
-
-static void raise_exception(struct fsg_common *common, enum fsg_state new_state)
-{
-	unsigned long		flags;
-
-	/*
-	 * Do nothing if a higher-priority exception is already in progress.
-	 * If a lower-or-equal priority exception is in progress, preempt it
-	 * and notify the main thread by sending it a signal.
-	 */
-	spin_lock_irqsave(&common->lock, flags);
-	if (common->state <= new_state) {
-		common->exception_req_tag = common->ep0_req_tag;
-		common->state = new_state;
-		if (common->thread_task)
-			send_sig_info(SIGUSR1, SEND_SIG_FORCED,
-				      common->thread_task);
-	}
-	spin_unlock_irqrestore(&common->lock, flags);
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static int ep0_queue(struct fsg_common *common)
-{
-	int	rc;
-
-	rc = usb_ep_queue(common->ep0, common->ep0req, GFP_ATOMIC);
-	common->ep0->driver_data = common;
-	if (rc != 0 && rc != -ESHUTDOWN) {
-		/* We can't do much more than wait for a reset */
-		WARNING(common, "error in submission: %s --> %d\n",
-			common->ep0->name, rc);
-	}
-	return rc;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/* Completion handlers. These always run in_irq. */
-
-static void bulk_in_complete(struct usb_ep *ep, struct usb_request *req)
-{
-	struct fsg_common	*common = ep->driver_data;
-	struct fsg_buffhd	*bh = req->context;
-
-	if (req->status || req->actual != req->length)
-		DBG(common, "%s --> %d, %u/%u\n", __func__,
-		    req->status, req->actual, req->length);
-	if (req->status == -ECONNRESET)		/* Request was cancelled */
-		usb_ep_fifo_flush(ep);
-
-	/* Hold the lock while we update the request and buffer states */
-	smp_wmb();
-	spin_lock(&common->lock);
-	bh->inreq_busy = 0;
-	bh->state = BUF_STATE_EMPTY;
-	wakeup_thread(common);
-	spin_unlock(&common->lock);
-}
-
-static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req)
-{
-	struct fsg_common	*common = ep->driver_data;
-	struct fsg_buffhd	*bh = req->context;
-
-	dump_msg(common, "bulk-out", req->buf, req->actual);
-	if (req->status || req->actual != bh->bulk_out_intended_length)
-		DBG(common, "%s --> %d, %u/%u\n", __func__,
-		    req->status, req->actual, bh->bulk_out_intended_length);
-	if (req->status == -ECONNRESET)		/* Request was cancelled */
-		usb_ep_fifo_flush(ep);
-
-	/* Hold the lock while we update the request and buffer states */
-	smp_wmb();
-	spin_lock(&common->lock);
-	bh->outreq_busy = 0;
-	bh->state = BUF_STATE_FULL;
-	wakeup_thread(common);
-	spin_unlock(&common->lock);
-}
-
-static int fsg_setup(struct usb_function *f,
-		     const struct usb_ctrlrequest *ctrl)
-{
-	struct fsg_dev		*fsg = fsg_from_func(f);
-	struct usb_request	*req = fsg->common->ep0req;
-	u16			w_index = le16_to_cpu(ctrl->wIndex);
-	u16			w_value = le16_to_cpu(ctrl->wValue);
-	u16			w_length = le16_to_cpu(ctrl->wLength);
-
-	if (!fsg_is_set(fsg->common))
-		return -EOPNOTSUPP;
-
-	++fsg->common->ep0_req_tag;	/* Record arrival of a new request */
-	req->context = NULL;
-	req->length = 0;
-	dump_msg(fsg, "ep0-setup", (u8 *) ctrl, sizeof(*ctrl));
-
-	switch (ctrl->bRequest) {
-
-	case US_BULK_RESET_REQUEST:
-		if (ctrl->bRequestType !=
-		    (USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE))
-			break;
-		if (w_index != fsg->interface_number || w_value != 0 ||
-				w_length != 0)
-			return -EDOM;
-
-		/*
-		 * Raise an exception to stop the current operation
-		 * and reinitialize our state.
-		 */
-		DBG(fsg, "bulk reset request\n");
-		raise_exception(fsg->common, FSG_STATE_RESET);
-		return DELAYED_STATUS;
-
-	case US_BULK_GET_MAX_LUN:
-		if (ctrl->bRequestType !=
-		    (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE))
-			break;
-		if (w_index != fsg->interface_number || w_value != 0 ||
-				w_length != 1)
-			return -EDOM;
-		VDBG(fsg, "get max LUN\n");
-		*(u8 *)req->buf = fsg->common->nluns - 1;
-
-		/* Respond with data/status */
-		req->length = min((u16)1, w_length);
-		return ep0_queue(fsg->common);
-	}
-
-	VDBG(fsg,
-	     "unknown class-specific control req %02x.%02x v%04x i%04x l%u\n",
-	     ctrl->bRequestType, ctrl->bRequest,
-	     le16_to_cpu(ctrl->wValue), w_index, w_length);
-	return -EOPNOTSUPP;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/* All the following routines run in process context */
-
-/* Use this for bulk or interrupt transfers, not ep0 */
-static void start_transfer(struct fsg_dev *fsg, struct usb_ep *ep,
-			   struct usb_request *req, int *pbusy,
-			   enum fsg_buffer_state *state)
-{
-	int	rc;
-
-	if (ep == fsg->bulk_in)
-		dump_msg(fsg, "bulk-in", req->buf, req->length);
-
-	spin_lock_irq(&fsg->common->lock);
-	*pbusy = 1;
-	*state = BUF_STATE_BUSY;
-	spin_unlock_irq(&fsg->common->lock);
-	rc = usb_ep_queue(ep, req, GFP_KERNEL);
-	if (rc != 0) {
-		*pbusy = 0;
-		*state = BUF_STATE_EMPTY;
-
-		/* We can't do much more than wait for a reset */
-
-		/*
-		 * Note: currently the net2280 driver fails zero-length
-		 * submissions if DMA is enabled.
-		 */
-		if (rc != -ESHUTDOWN &&
-		    !(rc == -EOPNOTSUPP && req->length == 0))
-			WARNING(fsg, "error in submission: %s --> %d\n",
-				ep->name, rc);
-	}
-}
-
-static bool start_in_transfer(struct fsg_common *common, struct fsg_buffhd *bh)
-{
-	if (!fsg_is_set(common))
-		return false;
-	start_transfer(common->fsg, common->fsg->bulk_in,
-		       bh->inreq, &bh->inreq_busy, &bh->state);
-	return true;
-}
-
-static bool start_out_transfer(struct fsg_common *common, struct fsg_buffhd *bh)
-{
-	if (!fsg_is_set(common))
-		return false;
-	start_transfer(common->fsg, common->fsg->bulk_out,
-		       bh->outreq, &bh->outreq_busy, &bh->state);
-	return true;
-}
-
-static int sleep_thread(struct fsg_common *common)
-{
-	int	rc = 0;
-
-	/* Wait until a signal arrives or we are woken up */
-	for (;;) {
-		try_to_freeze();
-		set_current_state(TASK_INTERRUPTIBLE);
-		if (signal_pending(current)) {
-			rc = -EINTR;
-			break;
-		}
-		if (common->thread_wakeup_needed)
-			break;
-		schedule();
-	}
-	__set_current_state(TASK_RUNNING);
-	common->thread_wakeup_needed = 0;
-	return rc;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static int do_read(struct fsg_common *common)
-{
-	struct fsg_lun		*curlun = common->curlun;
-	u32			lba;
-	struct fsg_buffhd	*bh;
-	int			rc;
-	u32			amount_left;
-	loff_t			file_offset, file_offset_tmp;
-	unsigned int		amount;
-	ssize_t			nread;
-
-	/*
-	 * Get the starting Logical Block Address and check that it's
-	 * not too big.
-	 */
-	if (common->cmnd[0] == READ_6)
-		lba = get_unaligned_be24(&common->cmnd[1]);
-	else {
-		lba = get_unaligned_be32(&common->cmnd[2]);
-
-		/*
-		 * We allow DPO (Disable Page Out = don't save data in the
-		 * cache) and FUA (Force Unit Access = don't read from the
-		 * cache), but we don't implement them.
-		 */
-		if ((common->cmnd[1] & ~0x18) != 0) {
-			curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
-			return -EINVAL;
-		}
-	}
-	if (lba >= curlun->num_sectors) {
-		curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
-		return -EINVAL;
-	}
-	file_offset = ((loff_t) lba) << curlun->blkbits;
-
-	/* Carry out the file reads */
-	amount_left = common->data_size_from_cmnd;
-	if (unlikely(amount_left == 0))
-		return -EIO;		/* No default reply */
-
-	for (;;) {
-		/*
-		 * Figure out how much we need to read:
-		 * Try to read the remaining amount.
-		 * But don't read more than the buffer size.
-		 * And don't try to read past the end of the file.
-		 */
-		amount = min(amount_left, FSG_BUFLEN);
-		amount = min((loff_t)amount,
-			     curlun->file_length - file_offset);
-
-		/* Wait for the next buffer to become available */
-		bh = common->next_buffhd_to_fill;
-		while (bh->state != BUF_STATE_EMPTY) {
-			rc = sleep_thread(common);
-			if (rc)
-				return rc;
-		}
-
-		/*
-		 * If we were asked to read past the end of file,
-		 * end with an empty buffer.
-		 */
-		if (amount == 0) {
-			curlun->sense_data =
-					SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
-			curlun->sense_data_info =
-					file_offset >> curlun->blkbits;
-			curlun->info_valid = 1;
-			bh->inreq->length = 0;
-			bh->state = BUF_STATE_FULL;
-			break;
-		}
-
-		/* Perform the read */
-		file_offset_tmp = file_offset;
-		nread = vfs_read(curlun->filp,
-				 (char __user *)bh->buf,
-				 amount, &file_offset_tmp);
-		VLDBG(curlun, "file read %u @ %llu -> %d\n", amount,
-		      (unsigned long long)file_offset, (int)nread);
-		if (signal_pending(current))
-			return -EINTR;
-
-		if (nread < 0) {
-			LDBG(curlun, "error in file read: %d\n", (int)nread);
-			nread = 0;
-		} else if (nread < amount) {
-			LDBG(curlun, "partial file read: %d/%u\n",
-			     (int)nread, amount);
-			nread = round_down(nread, curlun->blksize);
-		}
-		file_offset  += nread;
-		amount_left  -= nread;
-		common->residue -= nread;
-
-		/*
-		 * Except at the end of the transfer, nread will be
-		 * equal to the buffer size, which is divisible by the
-		 * bulk-in maxpacket size.
-		 */
-		bh->inreq->length = nread;
-		bh->state = BUF_STATE_FULL;
-
-		/* If an error occurred, report it and its position */
-		if (nread < amount) {
-			curlun->sense_data = SS_UNRECOVERED_READ_ERROR;
-			curlun->sense_data_info =
-					file_offset >> curlun->blkbits;
-			curlun->info_valid = 1;
-			break;
-		}
-
-		if (amount_left == 0)
-			break;		/* No more left to read */
-
-		/* Send this buffer and go read some more */
-		bh->inreq->zero = 0;
-		if (!start_in_transfer(common, bh))
-			/* Don't know what to do if common->fsg is NULL */
-			return -EIO;
-		common->next_buffhd_to_fill = bh->next;
-	}
-
-	return -EIO;		/* No default reply */
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static int do_write(struct fsg_common *common)
-{
-	struct fsg_lun		*curlun = common->curlun;
-	u32			lba;
-	struct fsg_buffhd	*bh;
-	int			get_some_more;
-	u32			amount_left_to_req, amount_left_to_write;
-	loff_t			usb_offset, file_offset, file_offset_tmp;
-	unsigned int		amount;
-	ssize_t			nwritten;
-	int			rc;
-
-	if (curlun->ro) {
-		curlun->sense_data = SS_WRITE_PROTECTED;
-		return -EINVAL;
-	}
-	spin_lock(&curlun->filp->f_lock);
-	curlun->filp->f_flags &= ~O_SYNC;	/* Default is not to wait */
-	spin_unlock(&curlun->filp->f_lock);
-
-	/*
-	 * Get the starting Logical Block Address and check that it's
-	 * not too big
-	 */
-	if (common->cmnd[0] == WRITE_6)
-		lba = get_unaligned_be24(&common->cmnd[1]);
-	else {
-		lba = get_unaligned_be32(&common->cmnd[2]);
-
-		/*
-		 * We allow DPO (Disable Page Out = don't save data in the
-		 * cache) and FUA (Force Unit Access = write directly to the
-		 * medium).  We don't implement DPO; we implement FUA by
-		 * performing synchronous output.
-		 */
-		if (common->cmnd[1] & ~0x18) {
-			curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
-			return -EINVAL;
-		}
-		if (!curlun->nofua && (common->cmnd[1] & 0x08)) { /* FUA */
-			spin_lock(&curlun->filp->f_lock);
-			curlun->filp->f_flags |= O_SYNC;
-			spin_unlock(&curlun->filp->f_lock);
-		}
-	}
-	if (lba >= curlun->num_sectors) {
-		curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
-		return -EINVAL;
-	}
-
-	/* Carry out the file writes */
-	get_some_more = 1;
-	file_offset = usb_offset = ((loff_t) lba) << curlun->blkbits;
-	amount_left_to_req = common->data_size_from_cmnd;
-	amount_left_to_write = common->data_size_from_cmnd;
-
-	while (amount_left_to_write > 0) {
-
-		/* Queue a request for more data from the host */
-		bh = common->next_buffhd_to_fill;
-		if (bh->state == BUF_STATE_EMPTY && get_some_more) {
-
-			/*
-			 * Figure out how much we want to get:
-			 * Try to get the remaining amount,
-			 * but not more than the buffer size.
-			 */
-			amount = min(amount_left_to_req, FSG_BUFLEN);
-
-			/* Beyond the end of the backing file? */
-			if (usb_offset >= curlun->file_length) {
-				get_some_more = 0;
-				curlun->sense_data =
-					SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
-				curlun->sense_data_info =
-					usb_offset >> curlun->blkbits;
-				curlun->info_valid = 1;
-				continue;
-			}
-
-			/* Get the next buffer */
-			usb_offset += amount;
-			common->usb_amount_left -= amount;
-			amount_left_to_req -= amount;
-			if (amount_left_to_req == 0)
-				get_some_more = 0;
-
-			/*
-			 * Except at the end of the transfer, amount will be
-			 * equal to the buffer size, which is divisible by
-			 * the bulk-out maxpacket size.
-			 */
-			set_bulk_out_req_length(common, bh, amount);
-			if (!start_out_transfer(common, bh))
-				/* Dunno what to do if common->fsg is NULL */
-				return -EIO;
-			common->next_buffhd_to_fill = bh->next;
-			continue;
-		}
-
-		/* Write the received data to the backing file */
-		bh = common->next_buffhd_to_drain;
-		if (bh->state == BUF_STATE_EMPTY && !get_some_more)
-			break;			/* We stopped early */
-		if (bh->state == BUF_STATE_FULL) {
-			smp_rmb();
-			common->next_buffhd_to_drain = bh->next;
-			bh->state = BUF_STATE_EMPTY;
-
-			/* Did something go wrong with the transfer? */
-			if (bh->outreq->status != 0) {
-				curlun->sense_data = SS_COMMUNICATION_FAILURE;
-				curlun->sense_data_info =
-					file_offset >> curlun->blkbits;
-				curlun->info_valid = 1;
-				break;
-			}
-
-			amount = bh->outreq->actual;
-			if (curlun->file_length - file_offset < amount) {
-				LERROR(curlun,
-				       "write %u @ %llu beyond end %llu\n",
-				       amount, (unsigned long long)file_offset,
-				       (unsigned long long)curlun->file_length);
-				amount = curlun->file_length - file_offset;
-			}
-
-			/* Don't accept excess data.  The spec doesn't say
-			 * what to do in this case.  We'll ignore the error.
-			 */
-			amount = min(amount, bh->bulk_out_intended_length);
-
-			/* Don't write a partial block */
-			amount = round_down(amount, curlun->blksize);
-			if (amount == 0)
-				goto empty_write;
-
-			/* Perform the write */
-			file_offset_tmp = file_offset;
-			nwritten = vfs_write(curlun->filp,
-					     (char __user *)bh->buf,
-					     amount, &file_offset_tmp);
-			VLDBG(curlun, "file write %u @ %llu -> %d\n", amount,
-			      (unsigned long long)file_offset, (int)nwritten);
-			if (signal_pending(current))
-				return -EINTR;		/* Interrupted! */
-
-			if (nwritten < 0) {
-				LDBG(curlun, "error in file write: %d\n",
-				     (int)nwritten);
-				nwritten = 0;
-			} else if (nwritten < amount) {
-				LDBG(curlun, "partial file write: %d/%u\n",
-				     (int)nwritten, amount);
-				nwritten = round_down(nwritten, curlun->blksize);
-			}
-			file_offset += nwritten;
-			amount_left_to_write -= nwritten;
-			common->residue -= nwritten;
-
-			/* If an error occurred, report it and its position */
-			if (nwritten < amount) {
-				curlun->sense_data = SS_WRITE_ERROR;
-				curlun->sense_data_info =
-					file_offset >> curlun->blkbits;
-				curlun->info_valid = 1;
-				break;
-			}
-
- empty_write:
-			/* Did the host decide to stop early? */
-			if (bh->outreq->actual < bh->bulk_out_intended_length) {
-				common->short_packet_received = 1;
-				break;
-			}
-			continue;
-		}
-
-		/* Wait for something to happen */
-		rc = sleep_thread(common);
-		if (rc)
-			return rc;
-	}
-
-	return -EIO;		/* No default reply */
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static int do_synchronize_cache(struct fsg_common *common)
-{
-	struct fsg_lun	*curlun = common->curlun;
-	int		rc;
-
-	/* We ignore the requested LBA and write out all file's
-	 * dirty data buffers. */
-	rc = fsg_lun_fsync_sub(curlun);
-	if (rc)
-		curlun->sense_data = SS_WRITE_ERROR;
-	return 0;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static void invalidate_sub(struct fsg_lun *curlun)
-{
-	struct file	*filp = curlun->filp;
-	struct inode	*inode = file_inode(filp);
-	unsigned long	rc;
-
-	rc = invalidate_mapping_pages(inode->i_mapping, 0, -1);
-	VLDBG(curlun, "invalidate_mapping_pages -> %ld\n", rc);
-}
-
-static int do_verify(struct fsg_common *common)
-{
-	struct fsg_lun		*curlun = common->curlun;
-	u32			lba;
-	u32			verification_length;
-	struct fsg_buffhd	*bh = common->next_buffhd_to_fill;
-	loff_t			file_offset, file_offset_tmp;
-	u32			amount_left;
-	unsigned int		amount;
-	ssize_t			nread;
-
-	/*
-	 * Get the starting Logical Block Address and check that it's
-	 * not too big.
-	 */
-	lba = get_unaligned_be32(&common->cmnd[2]);
-	if (lba >= curlun->num_sectors) {
-		curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
-		return -EINVAL;
-	}
-
-	/*
-	 * We allow DPO (Disable Page Out = don't save data in the
-	 * cache) but we don't implement it.
-	 */
-	if (common->cmnd[1] & ~0x10) {
-		curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
-		return -EINVAL;
-	}
-
-	verification_length = get_unaligned_be16(&common->cmnd[7]);
-	if (unlikely(verification_length == 0))
-		return -EIO;		/* No default reply */
-
-	/* Prepare to carry out the file verify */
-	amount_left = verification_length << curlun->blkbits;
-	file_offset = ((loff_t) lba) << curlun->blkbits;
-
-	/* Write out all the dirty buffers before invalidating them */
-	fsg_lun_fsync_sub(curlun);
-	if (signal_pending(current))
-		return -EINTR;
-
-	invalidate_sub(curlun);
-	if (signal_pending(current))
-		return -EINTR;
-
-	/* Just try to read the requested blocks */
-	while (amount_left > 0) {
-		/*
-		 * Figure out how much we need to read:
-		 * Try to read the remaining amount, but not more than
-		 * the buffer size.
-		 * And don't try to read past the end of the file.
-		 */
-		amount = min(amount_left, FSG_BUFLEN);
-		amount = min((loff_t)amount,
-			     curlun->file_length - file_offset);
-		if (amount == 0) {
-			curlun->sense_data =
-					SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
-			curlun->sense_data_info =
-				file_offset >> curlun->blkbits;
-			curlun->info_valid = 1;
-			break;
-		}
-
-		/* Perform the read */
-		file_offset_tmp = file_offset;
-		nread = vfs_read(curlun->filp,
-				(char __user *) bh->buf,
-				amount, &file_offset_tmp);
-		VLDBG(curlun, "file read %u @ %llu -> %d\n", amount,
-				(unsigned long long) file_offset,
-				(int) nread);
-		if (signal_pending(current))
-			return -EINTR;
-
-		if (nread < 0) {
-			LDBG(curlun, "error in file verify: %d\n", (int)nread);
-			nread = 0;
-		} else if (nread < amount) {
-			LDBG(curlun, "partial file verify: %d/%u\n",
-			     (int)nread, amount);
-			nread = round_down(nread, curlun->blksize);
-		}
-		if (nread == 0) {
-			curlun->sense_data = SS_UNRECOVERED_READ_ERROR;
-			curlun->sense_data_info =
-				file_offset >> curlun->blkbits;
-			curlun->info_valid = 1;
-			break;
-		}
-		file_offset += nread;
-		amount_left -= nread;
-	}
-	return 0;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static int do_inquiry(struct fsg_common *common, struct fsg_buffhd *bh)
-{
-	struct fsg_lun *curlun = common->curlun;
-	u8	*buf = (u8 *) bh->buf;
-
-	if (!curlun) {		/* Unsupported LUNs are okay */
-		common->bad_lun_okay = 1;
-		memset(buf, 0, 36);
-		buf[0] = 0x7f;		/* Unsupported, no device-type */
-		buf[4] = 31;		/* Additional length */
-		return 36;
-	}
-
-	buf[0] = curlun->cdrom ? TYPE_ROM : TYPE_DISK;
-	buf[1] = curlun->removable ? 0x80 : 0;
-	buf[2] = 2;		/* ANSI SCSI level 2 */
-	buf[3] = 2;		/* SCSI-2 INQUIRY data format */
-	buf[4] = 31;		/* Additional length */
-	buf[5] = 0;		/* No special options */
-	buf[6] = 0;
-	buf[7] = 0;
-	memcpy(buf + 8, common->inquiry_string, sizeof common->inquiry_string);
-	return 36;
-}
-
-static int do_request_sense(struct fsg_common *common, struct fsg_buffhd *bh)
-{
-	struct fsg_lun	*curlun = common->curlun;
-	u8		*buf = (u8 *) bh->buf;
-	u32		sd, sdinfo;
-	int		valid;
-
-	/*
-	 * From the SCSI-2 spec., section 7.9 (Unit attention condition):
-	 *
-	 * If a REQUEST SENSE command is received from an initiator
-	 * with a pending unit attention condition (before the target
-	 * generates the contingent allegiance condition), then the
-	 * target shall either:
-	 *   a) report any pending sense data and preserve the unit
-	 *	attention condition on the logical unit, or,
-	 *   b) report the unit attention condition, may discard any
-	 *	pending sense data, and clear the unit attention
-	 *	condition on the logical unit for that initiator.
-	 *
-	 * FSG normally uses option a); enable this code to use option b).
-	 */
-#if 0
-	if (curlun && curlun->unit_attention_data != SS_NO_SENSE) {
-		curlun->sense_data = curlun->unit_attention_data;
-		curlun->unit_attention_data = SS_NO_SENSE;
-	}
-#endif
-
-	if (!curlun) {		/* Unsupported LUNs are okay */
-		common->bad_lun_okay = 1;
-		sd = SS_LOGICAL_UNIT_NOT_SUPPORTED;
-		sdinfo = 0;
-		valid = 0;
-	} else {
-		sd = curlun->sense_data;
-		sdinfo = curlun->sense_data_info;
-		valid = curlun->info_valid << 7;
-		curlun->sense_data = SS_NO_SENSE;
-		curlun->sense_data_info = 0;
-		curlun->info_valid = 0;
-	}
-
-	memset(buf, 0, 18);
-	buf[0] = valid | 0x70;			/* Valid, current error */
-	buf[2] = SK(sd);
-	put_unaligned_be32(sdinfo, &buf[3]);	/* Sense information */
-	buf[7] = 18 - 8;			/* Additional sense length */
-	buf[12] = ASC(sd);
-	buf[13] = ASCQ(sd);
-	return 18;
-}
-
-static int do_read_capacity(struct fsg_common *common, struct fsg_buffhd *bh)
-{
-	struct fsg_lun	*curlun = common->curlun;
-	u32		lba = get_unaligned_be32(&common->cmnd[2]);
-	int		pmi = common->cmnd[8];
-	u8		*buf = (u8 *)bh->buf;
-
-	/* Check the PMI and LBA fields */
-	if (pmi > 1 || (pmi == 0 && lba != 0)) {
-		curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
-		return -EINVAL;
-	}
-
-	put_unaligned_be32(curlun->num_sectors - 1, &buf[0]);
-						/* Max logical block */
-	put_unaligned_be32(curlun->blksize, &buf[4]);/* Block length */
-	return 8;
-}
-
-static int do_read_header(struct fsg_common *common, struct fsg_buffhd *bh)
-{
-	struct fsg_lun	*curlun = common->curlun;
-	int		msf = common->cmnd[1] & 0x02;
-	u32		lba = get_unaligned_be32(&common->cmnd[2]);
-	u8		*buf = (u8 *)bh->buf;
-
-	if (common->cmnd[1] & ~0x02) {		/* Mask away MSF */
-		curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
-		return -EINVAL;
-	}
-	if (lba >= curlun->num_sectors) {
-		curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
-		return -EINVAL;
-	}
-
-	memset(buf, 0, 8);
-	buf[0] = 0x01;		/* 2048 bytes of user data, rest is EC */
-	store_cdrom_address(&buf[4], msf, lba);
-	return 8;
-}
-
-static int do_read_toc(struct fsg_common *common, struct fsg_buffhd *bh)
-{
-	struct fsg_lun	*curlun = common->curlun;
-	int		msf = common->cmnd[1] & 0x02;
-	int		start_track = common->cmnd[6];
-	u8		*buf = (u8 *)bh->buf;
-
-	if ((common->cmnd[1] & ~0x02) != 0 ||	/* Mask away MSF */
-			start_track > 1) {
-		curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
-		return -EINVAL;
-	}
-
-	memset(buf, 0, 20);
-	buf[1] = (20-2);		/* TOC data length */
-	buf[2] = 1;			/* First track number */
-	buf[3] = 1;			/* Last track number */
-	buf[5] = 0x16;			/* Data track, copying allowed */
-	buf[6] = 0x01;			/* Only track is number 1 */
-	store_cdrom_address(&buf[8], msf, 0);
-
-	buf[13] = 0x16;			/* Lead-out track is data */
-	buf[14] = 0xAA;			/* Lead-out track number */
-	store_cdrom_address(&buf[16], msf, curlun->num_sectors);
-	return 20;
-}
-
-static int do_mode_sense(struct fsg_common *common, struct fsg_buffhd *bh)
-{
-	struct fsg_lun	*curlun = common->curlun;
-	int		mscmnd = common->cmnd[0];
-	u8		*buf = (u8 *) bh->buf;
-	u8		*buf0 = buf;
-	int		pc, page_code;
-	int		changeable_values, all_pages;
-	int		valid_page = 0;
-	int		len, limit;
-
-	if ((common->cmnd[1] & ~0x08) != 0) {	/* Mask away DBD */
-		curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
-		return -EINVAL;
-	}
-	pc = common->cmnd[2] >> 6;
-	page_code = common->cmnd[2] & 0x3f;
-	if (pc == 3) {
-		curlun->sense_data = SS_SAVING_PARAMETERS_NOT_SUPPORTED;
-		return -EINVAL;
-	}
-	changeable_values = (pc == 1);
-	all_pages = (page_code == 0x3f);
-
-	/*
-	 * Write the mode parameter header.  Fixed values are: default
-	 * medium type, no cache control (DPOFUA), and no block descriptors.
-	 * The only variable value is the WriteProtect bit.  We will fill in
-	 * the mode data length later.
-	 */
-	memset(buf, 0, 8);
-	if (mscmnd == MODE_SENSE) {
-		buf[2] = (curlun->ro ? 0x80 : 0x00);		/* WP, DPOFUA */
-		buf += 4;
-		limit = 255;
-	} else {			/* MODE_SENSE_10 */
-		buf[3] = (curlun->ro ? 0x80 : 0x00);		/* WP, DPOFUA */
-		buf += 8;
-		limit = 65535;		/* Should really be FSG_BUFLEN */
-	}
-
-	/* No block descriptors */
-
-	/*
-	 * The mode pages, in numerical order.  The only page we support
-	 * is the Caching page.
-	 */
-	if (page_code == 0x08 || all_pages) {
-		valid_page = 1;
-		buf[0] = 0x08;		/* Page code */
-		buf[1] = 10;		/* Page length */
-		memset(buf+2, 0, 10);	/* None of the fields are changeable */
-
-		if (!changeable_values) {
-			buf[2] = 0x04;	/* Write cache enable, */
-					/* Read cache not disabled */
-					/* No cache retention priorities */
-			put_unaligned_be16(0xffff, &buf[4]);
-					/* Don't disable prefetch */
-					/* Minimum prefetch = 0 */
-			put_unaligned_be16(0xffff, &buf[8]);
-					/* Maximum prefetch */
-			put_unaligned_be16(0xffff, &buf[10]);
-					/* Maximum prefetch ceiling */
-		}
-		buf += 12;
-	}
-
-	/*
-	 * Check that a valid page was requested and the mode data length
-	 * isn't too long.
-	 */
-	len = buf - buf0;
-	if (!valid_page || len > limit) {
-		curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
-		return -EINVAL;
-	}
-
-	/*  Store the mode data length */
-	if (mscmnd == MODE_SENSE)
-		buf0[0] = len - 1;
-	else
-		put_unaligned_be16(len - 2, buf0);
-	return len;
-}
-
-static int do_start_stop(struct fsg_common *common)
-{
-	struct fsg_lun	*curlun = common->curlun;
-	int		loej, start;
-
-	if (!curlun) {
-		return -EINVAL;
-	} else if (!curlun->removable) {
-		curlun->sense_data = SS_INVALID_COMMAND;
-		return -EINVAL;
-	} else if ((common->cmnd[1] & ~0x01) != 0 || /* Mask away Immed */
-		   (common->cmnd[4] & ~0x03) != 0) { /* Mask LoEj, Start */
-		curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
-		return -EINVAL;
-	}
-
-	loej  = common->cmnd[4] & 0x02;
-	start = common->cmnd[4] & 0x01;
-
-	/*
-	 * Our emulation doesn't support mounting; the medium is
-	 * available for use as soon as it is loaded.
-	 */
-	if (start) {
-		if (!fsg_lun_is_open(curlun)) {
-			curlun->sense_data = SS_MEDIUM_NOT_PRESENT;
-			return -EINVAL;
-		}
-		return 0;
-	}
-
-	/* Are we allowed to unload the media? */
-	if (curlun->prevent_medium_removal) {
-		LDBG(curlun, "unload attempt prevented\n");
-		curlun->sense_data = SS_MEDIUM_REMOVAL_PREVENTED;
-		return -EINVAL;
-	}
-
-	if (!loej)
-		return 0;
-
-	/* Simulate an unload/eject */
-	if (common->ops && common->ops->pre_eject) {
-		int r = common->ops->pre_eject(common, curlun,
-					       curlun - common->luns);
-		if (unlikely(r < 0))
-			return r;
-		else if (r)
-			return 0;
-	}
-
-	up_read(&common->filesem);
-	down_write(&common->filesem);
-	fsg_lun_close(curlun);
-	up_write(&common->filesem);
-	down_read(&common->filesem);
-
-	return common->ops && common->ops->post_eject
-		? min(0, common->ops->post_eject(common, curlun,
-						 curlun - common->luns))
-		: 0;
-}
-
-static int do_prevent_allow(struct fsg_common *common)
-{
-	struct fsg_lun	*curlun = common->curlun;
-	int		prevent;
-
-	if (!common->curlun) {
-		return -EINVAL;
-	} else if (!common->curlun->removable) {
-		common->curlun->sense_data = SS_INVALID_COMMAND;
-		return -EINVAL;
-	}
-
-	prevent = common->cmnd[4] & 0x01;
-	if ((common->cmnd[4] & ~0x01) != 0) {	/* Mask away Prevent */
-		curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
-		return -EINVAL;
-	}
-
-	if (curlun->prevent_medium_removal && !prevent)
-		fsg_lun_fsync_sub(curlun);
-	curlun->prevent_medium_removal = prevent;
-	return 0;
-}
-
-static int do_read_format_capacities(struct fsg_common *common,
-			struct fsg_buffhd *bh)
-{
-	struct fsg_lun	*curlun = common->curlun;
-	u8		*buf = (u8 *) bh->buf;
-
-	buf[0] = buf[1] = buf[2] = 0;
-	buf[3] = 8;	/* Only the Current/Maximum Capacity Descriptor */
-	buf += 4;
-
-	put_unaligned_be32(curlun->num_sectors, &buf[0]);
-						/* Number of blocks */
-	put_unaligned_be32(curlun->blksize, &buf[4]);/* Block length */
-	buf[4] = 0x02;				/* Current capacity */
-	return 12;
-}
-
-static int do_mode_select(struct fsg_common *common, struct fsg_buffhd *bh)
-{
-	struct fsg_lun	*curlun = common->curlun;
-
-	/* We don't support MODE SELECT */
-	if (curlun)
-		curlun->sense_data = SS_INVALID_COMMAND;
-	return -EINVAL;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static int halt_bulk_in_endpoint(struct fsg_dev *fsg)
-{
-	int	rc;
-
-	rc = fsg_set_halt(fsg, fsg->bulk_in);
-	if (rc == -EAGAIN)
-		VDBG(fsg, "delayed bulk-in endpoint halt\n");
-	while (rc != 0) {
-		if (rc != -EAGAIN) {
-			WARNING(fsg, "usb_ep_set_halt -> %d\n", rc);
-			rc = 0;
-			break;
-		}
-
-		/* Wait for a short time and then try again */
-		if (msleep_interruptible(100) != 0)
-			return -EINTR;
-		rc = usb_ep_set_halt(fsg->bulk_in);
-	}
-	return rc;
-}
-
-static int wedge_bulk_in_endpoint(struct fsg_dev *fsg)
-{
-	int	rc;
-
-	DBG(fsg, "bulk-in set wedge\n");
-	rc = usb_ep_set_wedge(fsg->bulk_in);
-	if (rc == -EAGAIN)
-		VDBG(fsg, "delayed bulk-in endpoint wedge\n");
-	while (rc != 0) {
-		if (rc != -EAGAIN) {
-			WARNING(fsg, "usb_ep_set_wedge -> %d\n", rc);
-			rc = 0;
-			break;
-		}
-
-		/* Wait for a short time and then try again */
-		if (msleep_interruptible(100) != 0)
-			return -EINTR;
-		rc = usb_ep_set_wedge(fsg->bulk_in);
-	}
-	return rc;
-}
-
-static int throw_away_data(struct fsg_common *common)
-{
-	struct fsg_buffhd	*bh;
-	u32			amount;
-	int			rc;
-
-	for (bh = common->next_buffhd_to_drain;
-	     bh->state != BUF_STATE_EMPTY || common->usb_amount_left > 0;
-	     bh = common->next_buffhd_to_drain) {
-
-		/* Throw away the data in a filled buffer */
-		if (bh->state == BUF_STATE_FULL) {
-			smp_rmb();
-			bh->state = BUF_STATE_EMPTY;
-			common->next_buffhd_to_drain = bh->next;
-
-			/* A short packet or an error ends everything */
-			if (bh->outreq->actual < bh->bulk_out_intended_length ||
-			    bh->outreq->status != 0) {
-				raise_exception(common,
-						FSG_STATE_ABORT_BULK_OUT);
-				return -EINTR;
-			}
-			continue;
-		}
-
-		/* Try to submit another request if we need one */
-		bh = common->next_buffhd_to_fill;
-		if (bh->state == BUF_STATE_EMPTY
-		 && common->usb_amount_left > 0) {
-			amount = min(common->usb_amount_left, FSG_BUFLEN);
-
-			/*
-			 * Except at the end of the transfer, amount will be
-			 * equal to the buffer size, which is divisible by
-			 * the bulk-out maxpacket size.
-			 */
-			set_bulk_out_req_length(common, bh, amount);
-			if (!start_out_transfer(common, bh))
-				/* Dunno what to do if common->fsg is NULL */
-				return -EIO;
-			common->next_buffhd_to_fill = bh->next;
-			common->usb_amount_left -= amount;
-			continue;
-		}
-
-		/* Otherwise wait for something to happen */
-		rc = sleep_thread(common);
-		if (rc)
-			return rc;
-	}
-	return 0;
-}
-
-static int finish_reply(struct fsg_common *common)
-{
-	struct fsg_buffhd	*bh = common->next_buffhd_to_fill;
-	int			rc = 0;
-
-	switch (common->data_dir) {
-	case DATA_DIR_NONE:
-		break;			/* Nothing to send */
-
-	/*
-	 * If we don't know whether the host wants to read or write,
-	 * this must be CB or CBI with an unknown command.  We mustn't
-	 * try to send or receive any data.  So stall both bulk pipes
-	 * if we can and wait for a reset.
-	 */
-	case DATA_DIR_UNKNOWN:
-		if (!common->can_stall) {
-			/* Nothing */
-		} else if (fsg_is_set(common)) {
-			fsg_set_halt(common->fsg, common->fsg->bulk_out);
-			rc = halt_bulk_in_endpoint(common->fsg);
-		} else {
-			/* Don't know what to do if common->fsg is NULL */
-			rc = -EIO;
-		}
-		break;
-
-	/* All but the last buffer of data must have already been sent */
-	case DATA_DIR_TO_HOST:
-		if (common->data_size == 0) {
-			/* Nothing to send */
-
-		/* Don't know what to do if common->fsg is NULL */
-		} else if (!fsg_is_set(common)) {
-			rc = -EIO;
-
-		/* If there's no residue, simply send the last buffer */
-		} else if (common->residue == 0) {
-			bh->inreq->zero = 0;
-			if (!start_in_transfer(common, bh))
-				return -EIO;
-			common->next_buffhd_to_fill = bh->next;
-
-		/*
-		 * For Bulk-only, mark the end of the data with a short
-		 * packet.  If we are allowed to stall, halt the bulk-in
-		 * endpoint.  (Note: This violates the Bulk-Only Transport
-		 * specification, which requires us to pad the data if we
-		 * don't halt the endpoint.  Presumably nobody will mind.)
-		 */
-		} else {
-			bh->inreq->zero = 1;
-			if (!start_in_transfer(common, bh))
-				rc = -EIO;
-			common->next_buffhd_to_fill = bh->next;
-			if (common->can_stall)
-				rc = halt_bulk_in_endpoint(common->fsg);
-		}
-		break;
-
-	/*
-	 * We have processed all we want from the data the host has sent.
-	 * There may still be outstanding bulk-out requests.
-	 */
-	case DATA_DIR_FROM_HOST:
-		if (common->residue == 0) {
-			/* Nothing to receive */
-
-		/* Did the host stop sending unexpectedly early? */
-		} else if (common->short_packet_received) {
-			raise_exception(common, FSG_STATE_ABORT_BULK_OUT);
-			rc = -EINTR;
-
-		/*
-		 * We haven't processed all the incoming data.  Even though
-		 * we may be allowed to stall, doing so would cause a race.
-		 * The controller may already have ACK'ed all the remaining
-		 * bulk-out packets, in which case the host wouldn't see a
-		 * STALL.  Not realizing the endpoint was halted, it wouldn't
-		 * clear the halt -- leading to problems later on.
-		 */
-#if 0
-		} else if (common->can_stall) {
-			if (fsg_is_set(common))
-				fsg_set_halt(common->fsg,
-					     common->fsg->bulk_out);
-			raise_exception(common, FSG_STATE_ABORT_BULK_OUT);
-			rc = -EINTR;
-#endif
-
-		/*
-		 * We can't stall.  Read in the excess data and throw it
-		 * all away.
-		 */
-		} else {
-			rc = throw_away_data(common);
-		}
-		break;
-	}
-	return rc;
-}
-
-static int send_status(struct fsg_common *common)
-{
-	struct fsg_lun		*curlun = common->curlun;
-	struct fsg_buffhd	*bh;
-	struct bulk_cs_wrap	*csw;
-	int			rc;
-	u8			status = US_BULK_STAT_OK;
-	u32			sd, sdinfo = 0;
-
-	/* Wait for the next buffer to become available */
-	bh = common->next_buffhd_to_fill;
-	while (bh->state != BUF_STATE_EMPTY) {
-		rc = sleep_thread(common);
-		if (rc)
-			return rc;
-	}
-
-	if (curlun) {
-		sd = curlun->sense_data;
-		sdinfo = curlun->sense_data_info;
-	} else if (common->bad_lun_okay)
-		sd = SS_NO_SENSE;
-	else
-		sd = SS_LOGICAL_UNIT_NOT_SUPPORTED;
-
-	if (common->phase_error) {
-		DBG(common, "sending phase-error status\n");
-		status = US_BULK_STAT_PHASE;
-		sd = SS_INVALID_COMMAND;
-	} else if (sd != SS_NO_SENSE) {
-		DBG(common, "sending command-failure status\n");
-		status = US_BULK_STAT_FAIL;
-		VDBG(common, "  sense data: SK x%02x, ASC x%02x, ASCQ x%02x;"
-				"  info x%x\n",
-				SK(sd), ASC(sd), ASCQ(sd), sdinfo);
-	}
-
-	/* Store and send the Bulk-only CSW */
-	csw = (void *)bh->buf;
-
-	csw->Signature = cpu_to_le32(US_BULK_CS_SIGN);
-	csw->Tag = common->tag;
-	csw->Residue = cpu_to_le32(common->residue);
-	csw->Status = status;
-
-	bh->inreq->length = US_BULK_CS_WRAP_LEN;
-	bh->inreq->zero = 0;
-	if (!start_in_transfer(common, bh))
-		/* Don't know what to do if common->fsg is NULL */
-		return -EIO;
-
-	common->next_buffhd_to_fill = bh->next;
-	return 0;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * Check whether the command is properly formed and whether its data size
- * and direction agree with the values we already have.
- */
-static int check_command(struct fsg_common *common, int cmnd_size,
-			 enum data_direction data_dir, unsigned int mask,
-			 int needs_medium, const char *name)
-{
-	int			i;
-	int			lun = common->cmnd[1] >> 5;
-	static const char	dirletter[4] = {'u', 'o', 'i', 'n'};
-	char			hdlen[20];
-	struct fsg_lun		*curlun;
-
-	hdlen[0] = 0;
-	if (common->data_dir != DATA_DIR_UNKNOWN)
-		sprintf(hdlen, ", H%c=%u", dirletter[(int) common->data_dir],
-			common->data_size);
-	VDBG(common, "SCSI command: %s;  Dc=%d, D%c=%u;  Hc=%d%s\n",
-	     name, cmnd_size, dirletter[(int) data_dir],
-	     common->data_size_from_cmnd, common->cmnd_size, hdlen);
-
-	/*
-	 * We can't reply at all until we know the correct data direction
-	 * and size.
-	 */
-	if (common->data_size_from_cmnd == 0)
-		data_dir = DATA_DIR_NONE;
-	if (common->data_size < common->data_size_from_cmnd) {
-		/*
-		 * Host data size < Device data size is a phase error.
-		 * Carry out the command, but only transfer as much as
-		 * we are allowed.
-		 */
-		common->data_size_from_cmnd = common->data_size;
-		common->phase_error = 1;
-	}
-	common->residue = common->data_size;
-	common->usb_amount_left = common->data_size;
-
-	/* Conflicting data directions is a phase error */
-	if (common->data_dir != data_dir && common->data_size_from_cmnd > 0) {
-		common->phase_error = 1;
-		return -EINVAL;
-	}
-
-	/* Verify the length of the command itself */
-	if (cmnd_size != common->cmnd_size) {
-
-		/*
-		 * Special case workaround: There are plenty of buggy SCSI
-		 * implementations. Many have issues with cbw->Length
-		 * field passing a wrong command size. For those cases we
-		 * always try to work around the problem by using the length
-		 * sent by the host side provided it is at least as large
-		 * as the correct command length.
-		 * Examples of such cases would be MS-Windows, which issues
-		 * REQUEST SENSE with cbw->Length == 12 where it should
-		 * be 6, and xbox360 issuing INQUIRY, TEST UNIT READY and
-		 * REQUEST SENSE with cbw->Length == 10 where it should
-		 * be 6 as well.
-		 */
-		if (cmnd_size <= common->cmnd_size) {
-			DBG(common, "%s is buggy! Expected length %d "
-			    "but we got %d\n", name,
-			    cmnd_size, common->cmnd_size);
-			cmnd_size = common->cmnd_size;
-		} else {
-			common->phase_error = 1;
-			return -EINVAL;
-		}
-	}
-
-	/* Check that the LUN values are consistent */
-	if (common->lun != lun)
-		DBG(common, "using LUN %d from CBW, not LUN %d from CDB\n",
-		    common->lun, lun);
-
-	/* Check the LUN */
-	curlun = common->curlun;
-	if (curlun) {
-		if (common->cmnd[0] != REQUEST_SENSE) {
-			curlun->sense_data = SS_NO_SENSE;
-			curlun->sense_data_info = 0;
-			curlun->info_valid = 0;
-		}
-	} else {
-		common->bad_lun_okay = 0;
-
-		/*
-		 * INQUIRY and REQUEST SENSE commands are explicitly allowed
-		 * to use unsupported LUNs; all others may not.
-		 */
-		if (common->cmnd[0] != INQUIRY &&
-		    common->cmnd[0] != REQUEST_SENSE) {
-			DBG(common, "unsupported LUN %d\n", common->lun);
-			return -EINVAL;
-		}
-	}
-
-	/*
-	 * If a unit attention condition exists, only INQUIRY and
-	 * REQUEST SENSE commands are allowed; anything else must fail.
-	 */
-	if (curlun && curlun->unit_attention_data != SS_NO_SENSE &&
-	    common->cmnd[0] != INQUIRY &&
-	    common->cmnd[0] != REQUEST_SENSE) {
-		curlun->sense_data = curlun->unit_attention_data;
-		curlun->unit_attention_data = SS_NO_SENSE;
-		return -EINVAL;
-	}
-
-	/* Check that only command bytes listed in the mask are non-zero */
-	common->cmnd[1] &= 0x1f;			/* Mask away the LUN */
-	for (i = 1; i < cmnd_size; ++i) {
-		if (common->cmnd[i] && !(mask & (1 << i))) {
-			if (curlun)
-				curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
-			return -EINVAL;
-		}
-	}
-
-	/* If the medium isn't mounted and the command needs to access
-	 * it, return an error. */
-	if (curlun && !fsg_lun_is_open(curlun) && needs_medium) {
-		curlun->sense_data = SS_MEDIUM_NOT_PRESENT;
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-/* wrapper of check_command for data size in blocks handling */
-static int check_command_size_in_blocks(struct fsg_common *common,
-		int cmnd_size, enum data_direction data_dir,
-		unsigned int mask, int needs_medium, const char *name)
-{
-	if (common->curlun)
-		common->data_size_from_cmnd <<= common->curlun->blkbits;
-	return check_command(common, cmnd_size, data_dir,
-			mask, needs_medium, name);
-}
-
-static int do_scsi_command(struct fsg_common *common)
-{
-	struct fsg_buffhd	*bh;
-	int			rc;
-	int			reply = -EINVAL;
-	int			i;
-	static char		unknown[16];
-
-	dump_cdb(common);
-
-	/* Wait for the next buffer to become available for data or status */
-	bh = common->next_buffhd_to_fill;
-	common->next_buffhd_to_drain = bh;
-	while (bh->state != BUF_STATE_EMPTY) {
-		rc = sleep_thread(common);
-		if (rc)
-			return rc;
-	}
-	common->phase_error = 0;
-	common->short_packet_received = 0;
-
-	down_read(&common->filesem);	/* We're using the backing file */
-	switch (common->cmnd[0]) {
-
-	case INQUIRY:
-		common->data_size_from_cmnd = common->cmnd[4];
-		reply = check_command(common, 6, DATA_DIR_TO_HOST,
-				      (1<<4), 0,
-				      "INQUIRY");
-		if (reply == 0)
-			reply = do_inquiry(common, bh);
-		break;
-
-	case MODE_SELECT:
-		common->data_size_from_cmnd = common->cmnd[4];
-		reply = check_command(common, 6, DATA_DIR_FROM_HOST,
-				      (1<<1) | (1<<4), 0,
-				      "MODE SELECT(6)");
-		if (reply == 0)
-			reply = do_mode_select(common, bh);
-		break;
-
-	case MODE_SELECT_10:
-		common->data_size_from_cmnd =
-			get_unaligned_be16(&common->cmnd[7]);
-		reply = check_command(common, 10, DATA_DIR_FROM_HOST,
-				      (1<<1) | (3<<7), 0,
-				      "MODE SELECT(10)");
-		if (reply == 0)
-			reply = do_mode_select(common, bh);
-		break;
-
-	case MODE_SENSE:
-		common->data_size_from_cmnd = common->cmnd[4];
-		reply = check_command(common, 6, DATA_DIR_TO_HOST,
-				      (1<<1) | (1<<2) | (1<<4), 0,
-				      "MODE SENSE(6)");
-		if (reply == 0)
-			reply = do_mode_sense(common, bh);
-		break;
-
-	case MODE_SENSE_10:
-		common->data_size_from_cmnd =
-			get_unaligned_be16(&common->cmnd[7]);
-		reply = check_command(common, 10, DATA_DIR_TO_HOST,
-				      (1<<1) | (1<<2) | (3<<7), 0,
-				      "MODE SENSE(10)");
-		if (reply == 0)
-			reply = do_mode_sense(common, bh);
-		break;
-
-	case ALLOW_MEDIUM_REMOVAL:
-		common->data_size_from_cmnd = 0;
-		reply = check_command(common, 6, DATA_DIR_NONE,
-				      (1<<4), 0,
-				      "PREVENT-ALLOW MEDIUM REMOVAL");
-		if (reply == 0)
-			reply = do_prevent_allow(common);
-		break;
-
-	case READ_6:
-		i = common->cmnd[4];
-		common->data_size_from_cmnd = (i == 0) ? 256 : i;
-		reply = check_command_size_in_blocks(common, 6,
-				      DATA_DIR_TO_HOST,
-				      (7<<1) | (1<<4), 1,
-				      "READ(6)");
-		if (reply == 0)
-			reply = do_read(common);
-		break;
-
-	case READ_10:
-		common->data_size_from_cmnd =
-				get_unaligned_be16(&common->cmnd[7]);
-		reply = check_command_size_in_blocks(common, 10,
-				      DATA_DIR_TO_HOST,
-				      (1<<1) | (0xf<<2) | (3<<7), 1,
-				      "READ(10)");
-		if (reply == 0)
-			reply = do_read(common);
-		break;
-
-	case READ_12:
-		common->data_size_from_cmnd =
-				get_unaligned_be32(&common->cmnd[6]);
-		reply = check_command_size_in_blocks(common, 12,
-				      DATA_DIR_TO_HOST,
-				      (1<<1) | (0xf<<2) | (0xf<<6), 1,
-				      "READ(12)");
-		if (reply == 0)
-			reply = do_read(common);
-		break;
-
-	case READ_CAPACITY:
-		common->data_size_from_cmnd = 8;
-		reply = check_command(common, 10, DATA_DIR_TO_HOST,
-				      (0xf<<2) | (1<<8), 1,
-				      "READ CAPACITY");
-		if (reply == 0)
-			reply = do_read_capacity(common, bh);
-		break;
-
-	case READ_HEADER:
-		if (!common->curlun || !common->curlun->cdrom)
-			goto unknown_cmnd;
-		common->data_size_from_cmnd =
-			get_unaligned_be16(&common->cmnd[7]);
-		reply = check_command(common, 10, DATA_DIR_TO_HOST,
-				      (3<<7) | (0x1f<<1), 1,
-				      "READ HEADER");
-		if (reply == 0)
-			reply = do_read_header(common, bh);
-		break;
-
-	case READ_TOC:
-		if (!common->curlun || !common->curlun->cdrom)
-			goto unknown_cmnd;
-		common->data_size_from_cmnd =
-			get_unaligned_be16(&common->cmnd[7]);
-		reply = check_command(common, 10, DATA_DIR_TO_HOST,
-				      (7<<6) | (1<<1), 1,
-				      "READ TOC");
-		if (reply == 0)
-			reply = do_read_toc(common, bh);
-		break;
-
-	case READ_FORMAT_CAPACITIES:
-		common->data_size_from_cmnd =
-			get_unaligned_be16(&common->cmnd[7]);
-		reply = check_command(common, 10, DATA_DIR_TO_HOST,
-				      (3<<7), 1,
-				      "READ FORMAT CAPACITIES");
-		if (reply == 0)
-			reply = do_read_format_capacities(common, bh);
-		break;
-
-	case REQUEST_SENSE:
-		common->data_size_from_cmnd = common->cmnd[4];
-		reply = check_command(common, 6, DATA_DIR_TO_HOST,
-				      (1<<4), 0,
-				      "REQUEST SENSE");
-		if (reply == 0)
-			reply = do_request_sense(common, bh);
-		break;
-
-	case START_STOP:
-		common->data_size_from_cmnd = 0;
-		reply = check_command(common, 6, DATA_DIR_NONE,
-				      (1<<1) | (1<<4), 0,
-				      "START-STOP UNIT");
-		if (reply == 0)
-			reply = do_start_stop(common);
-		break;
-
-	case SYNCHRONIZE_CACHE:
-		common->data_size_from_cmnd = 0;
-		reply = check_command(common, 10, DATA_DIR_NONE,
-				      (0xf<<2) | (3<<7), 1,
-				      "SYNCHRONIZE CACHE");
-		if (reply == 0)
-			reply = do_synchronize_cache(common);
-		break;
-
-	case TEST_UNIT_READY:
-		common->data_size_from_cmnd = 0;
-		reply = check_command(common, 6, DATA_DIR_NONE,
-				0, 1,
-				"TEST UNIT READY");
-		break;
-
-	/*
-	 * Although optional, this command is used by MS-Windows.  We
-	 * support a minimal version: BytChk must be 0.
-	 */
-	case VERIFY:
-		common->data_size_from_cmnd = 0;
-		reply = check_command(common, 10, DATA_DIR_NONE,
-				      (1<<1) | (0xf<<2) | (3<<7), 1,
-				      "VERIFY");
-		if (reply == 0)
-			reply = do_verify(common);
-		break;
-
-	case WRITE_6:
-		i = common->cmnd[4];
-		common->data_size_from_cmnd = (i == 0) ? 256 : i;
-		reply = check_command_size_in_blocks(common, 6,
-				      DATA_DIR_FROM_HOST,
-				      (7<<1) | (1<<4), 1,
-				      "WRITE(6)");
-		if (reply == 0)
-			reply = do_write(common);
-		break;
-
-	case WRITE_10:
-		common->data_size_from_cmnd =
-				get_unaligned_be16(&common->cmnd[7]);
-		reply = check_command_size_in_blocks(common, 10,
-				      DATA_DIR_FROM_HOST,
-				      (1<<1) | (0xf<<2) | (3<<7), 1,
-				      "WRITE(10)");
-		if (reply == 0)
-			reply = do_write(common);
-		break;
-
-	case WRITE_12:
-		common->data_size_from_cmnd =
-				get_unaligned_be32(&common->cmnd[6]);
-		reply = check_command_size_in_blocks(common, 12,
-				      DATA_DIR_FROM_HOST,
-				      (1<<1) | (0xf<<2) | (0xf<<6), 1,
-				      "WRITE(12)");
-		if (reply == 0)
-			reply = do_write(common);
-		break;
-
-	/*
-	 * Some mandatory commands that we recognize but don't implement.
-	 * They don't mean much in this setting.  It's left as an exercise
-	 * for anyone interested to implement RESERVE and RELEASE in terms
-	 * of Posix locks.
-	 */
-	case FORMAT_UNIT:
-	case RELEASE:
-	case RESERVE:
-	case SEND_DIAGNOSTIC:
-		/* Fall through */
-
-	default:
-unknown_cmnd:
-		common->data_size_from_cmnd = 0;
-		sprintf(unknown, "Unknown x%02x", common->cmnd[0]);
-		reply = check_command(common, common->cmnd_size,
-				      DATA_DIR_UNKNOWN, ~0, 0, unknown);
-		if (reply == 0) {
-			common->curlun->sense_data = SS_INVALID_COMMAND;
-			reply = -EINVAL;
-		}
-		break;
-	}
-	up_read(&common->filesem);
-
-	if (reply == -EINTR || signal_pending(current))
-		return -EINTR;
-
-	/* Set up the single reply buffer for finish_reply() */
-	if (reply == -EINVAL)
-		reply = 0;		/* Error reply length */
-	if (reply >= 0 && common->data_dir == DATA_DIR_TO_HOST) {
-		reply = min((u32)reply, common->data_size_from_cmnd);
-		bh->inreq->length = reply;
-		bh->state = BUF_STATE_FULL;
-		common->residue -= reply;
-	}				/* Otherwise it's already set */
-
-	return 0;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh)
-{
-	struct usb_request	*req = bh->outreq;
-	struct bulk_cb_wrap	*cbw = req->buf;
-	struct fsg_common	*common = fsg->common;
-
-	/* Was this a real packet?  Should it be ignored? */
-	if (req->status || test_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags))
-		return -EINVAL;
-
-	/* Is the CBW valid? */
-	if (req->actual != US_BULK_CB_WRAP_LEN ||
-			cbw->Signature != cpu_to_le32(
-				US_BULK_CB_SIGN)) {
-		DBG(fsg, "invalid CBW: len %u sig 0x%x\n",
-				req->actual,
-				le32_to_cpu(cbw->Signature));
-
-		/*
-		 * The Bulk-only spec says we MUST stall the IN endpoint
-		 * (6.6.1), so it's unavoidable.  It also says we must
-		 * retain this state until the next reset, but there's
-		 * no way to tell the controller driver it should ignore
-		 * Clear-Feature(HALT) requests.
-		 *
-		 * We aren't required to halt the OUT endpoint; instead
-		 * we can simply accept and discard any data received
-		 * until the next reset.
-		 */
-		wedge_bulk_in_endpoint(fsg);
-		set_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags);
-		return -EINVAL;
-	}
-
-	/* Is the CBW meaningful? */
-	if (cbw->Lun >= FSG_MAX_LUNS || cbw->Flags & ~US_BULK_FLAG_IN ||
-			cbw->Length <= 0 || cbw->Length > MAX_COMMAND_SIZE) {
-		DBG(fsg, "non-meaningful CBW: lun = %u, flags = 0x%x, "
-				"cmdlen %u\n",
-				cbw->Lun, cbw->Flags, cbw->Length);
-
-		/*
-		 * We can do anything we want here, so let's stall the
-		 * bulk pipes if we are allowed to.
-		 */
-		if (common->can_stall) {
-			fsg_set_halt(fsg, fsg->bulk_out);
-			halt_bulk_in_endpoint(fsg);
-		}
-		return -EINVAL;
-	}
-
-	/* Save the command for later */
-	common->cmnd_size = cbw->Length;
-	memcpy(common->cmnd, cbw->CDB, common->cmnd_size);
-	if (cbw->Flags & US_BULK_FLAG_IN)
-		common->data_dir = DATA_DIR_TO_HOST;
-	else
-		common->data_dir = DATA_DIR_FROM_HOST;
-	common->data_size = le32_to_cpu(cbw->DataTransferLength);
-	if (common->data_size == 0)
-		common->data_dir = DATA_DIR_NONE;
-	common->lun = cbw->Lun;
-	if (common->lun >= 0 && common->lun < common->nluns)
-		common->curlun = &common->luns[common->lun];
-	else
-		common->curlun = NULL;
-	common->tag = cbw->Tag;
-	return 0;
-}
-
-static int get_next_command(struct fsg_common *common)
-{
-	struct fsg_buffhd	*bh;
-	int			rc = 0;
-
-	/* Wait for the next buffer to become available */
-	bh = common->next_buffhd_to_fill;
-	while (bh->state != BUF_STATE_EMPTY) {
-		rc = sleep_thread(common);
-		if (rc)
-			return rc;
-	}
-
-	/* Queue a request to read a Bulk-only CBW */
-	set_bulk_out_req_length(common, bh, US_BULK_CB_WRAP_LEN);
-	if (!start_out_transfer(common, bh))
-		/* Don't know what to do if common->fsg is NULL */
-		return -EIO;
-
-	/*
-	 * We will drain the buffer in software, which means we
-	 * can reuse it for the next filling.  No need to advance
-	 * next_buffhd_to_fill.
-	 */
-
-	/* Wait for the CBW to arrive */
-	while (bh->state != BUF_STATE_FULL) {
-		rc = sleep_thread(common);
-		if (rc)
-			return rc;
-	}
-	smp_rmb();
-	rc = fsg_is_set(common) ? received_cbw(common->fsg, bh) : -EIO;
-	bh->state = BUF_STATE_EMPTY;
-
-	return rc;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static int alloc_request(struct fsg_common *common, struct usb_ep *ep,
-		struct usb_request **preq)
-{
-	*preq = usb_ep_alloc_request(ep, GFP_ATOMIC);
-	if (*preq)
-		return 0;
-	ERROR(common, "can't allocate request for %s\n", ep->name);
-	return -ENOMEM;
-}
-
-/* Reset interface setting and re-init endpoint state (toggle etc). */
-static int do_set_interface(struct fsg_common *common, struct fsg_dev *new_fsg)
-{
-	struct fsg_dev *fsg;
-	int i, rc = 0;
-
-	if (common->running)
-		DBG(common, "reset interface\n");
-
-reset:
-	/* Deallocate the requests */
-	if (common->fsg) {
-		fsg = common->fsg;
-
-		for (i = 0; i < fsg_num_buffers; ++i) {
-			struct fsg_buffhd *bh = &common->buffhds[i];
-
-			if (bh->inreq) {
-				usb_ep_free_request(fsg->bulk_in, bh->inreq);
-				bh->inreq = NULL;
-			}
-			if (bh->outreq) {
-				usb_ep_free_request(fsg->bulk_out, bh->outreq);
-				bh->outreq = NULL;
-			}
-		}
-
-		/* Disable the endpoints */
-		if (fsg->bulk_in_enabled) {
-			usb_ep_disable(fsg->bulk_in);
-			fsg->bulk_in_enabled = 0;
-		}
-		if (fsg->bulk_out_enabled) {
-			usb_ep_disable(fsg->bulk_out);
-			fsg->bulk_out_enabled = 0;
-		}
-
-		common->fsg = NULL;
-		wake_up(&common->fsg_wait);
-	}
-
-	common->running = 0;
-	if (!new_fsg || rc)
-		return rc;
-
-	common->fsg = new_fsg;
-	fsg = common->fsg;
-
-	/* Enable the endpoints */
-	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;
-
-	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 = usb_endpoint_maxp(fsg->bulk_out->desc);
-	clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags);
-
-	/* Allocate the requests */
-	for (i = 0; i < fsg_num_buffers; ++i) {
-		struct fsg_buffhd	*bh = &common->buffhds[i];
-
-		rc = alloc_request(common, fsg->bulk_in, &bh->inreq);
-		if (rc)
-			goto reset;
-		rc = alloc_request(common, fsg->bulk_out, &bh->outreq);
-		if (rc)
-			goto reset;
-		bh->inreq->buf = bh->outreq->buf = bh->buf;
-		bh->inreq->context = bh->outreq->context = bh;
-		bh->inreq->complete = bulk_in_complete;
-		bh->outreq->complete = bulk_out_complete;
-	}
-
-	common->running = 1;
-	for (i = 0; i < common->nluns; ++i)
-		common->luns[i].unit_attention_data = SS_RESET_OCCURRED;
-	return rc;
-}
-
-
-/****************************** ALT CONFIGS ******************************/
-
-static int fsg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
-{
-	struct fsg_dev *fsg = fsg_from_func(f);
-	fsg->common->new_fsg = fsg;
-	raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE);
-	return USB_GADGET_DELAYED_STATUS;
-}
-
-static void fsg_disable(struct usb_function *f)
-{
-	struct fsg_dev *fsg = fsg_from_func(f);
-	fsg->common->new_fsg = NULL;
-	raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE);
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static void handle_exception(struct fsg_common *common)
-{
-	siginfo_t		info;
-	int			i;
-	struct fsg_buffhd	*bh;
-	enum fsg_state		old_state;
-	struct fsg_lun		*curlun;
-	unsigned int		exception_req_tag;
-
-	/*
-	 * Clear the existing signals.  Anything but SIGUSR1 is converted
-	 * into a high-priority EXIT exception.
-	 */
-	for (;;) {
-		int sig =
-			dequeue_signal_lock(current, &current->blocked, &info);
-		if (!sig)
-			break;
-		if (sig != SIGUSR1) {
-			if (common->state < FSG_STATE_EXIT)
-				DBG(common, "Main thread exiting on signal\n");
-			raise_exception(common, FSG_STATE_EXIT);
-		}
-	}
-
-	/* Cancel all the pending transfers */
-	if (likely(common->fsg)) {
-		for (i = 0; i < fsg_num_buffers; ++i) {
-			bh = &common->buffhds[i];
-			if (bh->inreq_busy)
-				usb_ep_dequeue(common->fsg->bulk_in, bh->inreq);
-			if (bh->outreq_busy)
-				usb_ep_dequeue(common->fsg->bulk_out,
-					       bh->outreq);
-		}
-
-		/* Wait until everything is idle */
-		for (;;) {
-			int num_active = 0;
-			for (i = 0; i < fsg_num_buffers; ++i) {
-				bh = &common->buffhds[i];
-				num_active += bh->inreq_busy + bh->outreq_busy;
-			}
-			if (num_active == 0)
-				break;
-			if (sleep_thread(common))
-				return;
-		}
-
-		/* Clear out the controller's fifos */
-		if (common->fsg->bulk_in_enabled)
-			usb_ep_fifo_flush(common->fsg->bulk_in);
-		if (common->fsg->bulk_out_enabled)
-			usb_ep_fifo_flush(common->fsg->bulk_out);
-	}
-
-	/*
-	 * Reset the I/O buffer states and pointers, the SCSI
-	 * state, and the exception.  Then invoke the handler.
-	 */
-	spin_lock_irq(&common->lock);
-
-	for (i = 0; i < fsg_num_buffers; ++i) {
-		bh = &common->buffhds[i];
-		bh->state = BUF_STATE_EMPTY;
-	}
-	common->next_buffhd_to_fill = &common->buffhds[0];
-	common->next_buffhd_to_drain = &common->buffhds[0];
-	exception_req_tag = common->exception_req_tag;
-	old_state = common->state;
-
-	if (old_state == FSG_STATE_ABORT_BULK_OUT)
-		common->state = FSG_STATE_STATUS_PHASE;
-	else {
-		for (i = 0; i < common->nluns; ++i) {
-			curlun = &common->luns[i];
-			curlun->prevent_medium_removal = 0;
-			curlun->sense_data = SS_NO_SENSE;
-			curlun->unit_attention_data = SS_NO_SENSE;
-			curlun->sense_data_info = 0;
-			curlun->info_valid = 0;
-		}
-		common->state = FSG_STATE_IDLE;
-	}
-	spin_unlock_irq(&common->lock);
-
-	/* Carry out any extra actions required for the exception */
-	switch (old_state) {
-	case FSG_STATE_ABORT_BULK_OUT:
-		send_status(common);
-		spin_lock_irq(&common->lock);
-		if (common->state == FSG_STATE_STATUS_PHASE)
-			common->state = FSG_STATE_IDLE;
-		spin_unlock_irq(&common->lock);
-		break;
-
-	case FSG_STATE_RESET:
-		/*
-		 * In case we were forced against our will to halt a
-		 * bulk endpoint, clear the halt now.  (The SuperH UDC
-		 * requires this.)
-		 */
-		if (!fsg_is_set(common))
-			break;
-		if (test_and_clear_bit(IGNORE_BULK_OUT,
-				       &common->fsg->atomic_bitflags))
-			usb_ep_clear_halt(common->fsg->bulk_in);
-
-		if (common->ep0_req_tag == exception_req_tag)
-			ep0_queue(common);	/* Complete the status stage */
-
-		/*
-		 * Technically this should go here, but it would only be
-		 * a waste of time.  Ditto for the INTERFACE_CHANGE and
-		 * CONFIG_CHANGE cases.
-		 */
-		/* for (i = 0; i < common->nluns; ++i) */
-		/*	common->luns[i].unit_attention_data = */
-		/*		SS_RESET_OCCURRED;  */
-		break;
-
-	case FSG_STATE_CONFIG_CHANGE:
-		do_set_interface(common, common->new_fsg);
-		if (common->new_fsg)
-			usb_composite_setup_continue(common->cdev);
-		break;
-
-	case FSG_STATE_EXIT:
-	case FSG_STATE_TERMINATED:
-		do_set_interface(common, NULL);		/* Free resources */
-		spin_lock_irq(&common->lock);
-		common->state = FSG_STATE_TERMINATED;	/* Stop the thread */
-		spin_unlock_irq(&common->lock);
-		break;
-
-	case FSG_STATE_INTERFACE_CHANGE:
-	case FSG_STATE_DISCONNECT:
-	case FSG_STATE_COMMAND_PHASE:
-	case FSG_STATE_DATA_PHASE:
-	case FSG_STATE_STATUS_PHASE:
-	case FSG_STATE_IDLE:
-		break;
-	}
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static int fsg_main_thread(void *common_)
-{
-	struct fsg_common	*common = common_;
-
-	/*
-	 * Allow the thread to be killed by a signal, but set the signal mask
-	 * to block everything but INT, TERM, KILL, and USR1.
-	 */
-	allow_signal(SIGINT);
-	allow_signal(SIGTERM);
-	allow_signal(SIGKILL);
-	allow_signal(SIGUSR1);
-
-	/* Allow the thread to be frozen */
-	set_freezable();
-
-	/*
-	 * Arrange for userspace references to be interpreted as kernel
-	 * pointers.  That way we can pass a kernel pointer to a routine
-	 * that expects a __user pointer and it will work okay.
-	 */
-	set_fs(get_ds());
-
-	/* The main loop */
-	while (common->state != FSG_STATE_TERMINATED) {
-		if (exception_in_progress(common) || signal_pending(current)) {
-			handle_exception(common);
-			continue;
-		}
-
-		if (!common->running) {
-			sleep_thread(common);
-			continue;
-		}
-
-		if (get_next_command(common))
-			continue;
-
-		spin_lock_irq(&common->lock);
-		if (!exception_in_progress(common))
-			common->state = FSG_STATE_DATA_PHASE;
-		spin_unlock_irq(&common->lock);
-
-		if (do_scsi_command(common) || finish_reply(common))
-			continue;
-
-		spin_lock_irq(&common->lock);
-		if (!exception_in_progress(common))
-			common->state = FSG_STATE_STATUS_PHASE;
-		spin_unlock_irq(&common->lock);
-
-		if (send_status(common))
-			continue;
-
-		spin_lock_irq(&common->lock);
-		if (!exception_in_progress(common))
-			common->state = FSG_STATE_IDLE;
-		spin_unlock_irq(&common->lock);
-	}
-
-	spin_lock_irq(&common->lock);
-	common->thread_task = NULL;
-	spin_unlock_irq(&common->lock);
-
-	if (!common->ops || !common->ops->thread_exits
-	 || common->ops->thread_exits(common) < 0) {
-		struct fsg_lun *curlun = common->luns;
-		unsigned i = common->nluns;
-
-		down_write(&common->filesem);
-		for (; i--; ++curlun) {
-			if (!fsg_lun_is_open(curlun))
-				continue;
-
-			fsg_lun_close(curlun);
-			curlun->unit_attention_data = SS_MEDIUM_NOT_PRESENT;
-		}
-		up_write(&common->filesem);
-	}
-
-	/* Let fsg_unbind() know the thread has exited */
-	complete_and_exit(&common->thread_notifier, 0);
-}
-
-
-/*************************** DEVICE ATTRIBUTES ***************************/
-
-static DEVICE_ATTR(ro, 0644, fsg_show_ro, fsg_store_ro);
-static DEVICE_ATTR(nofua, 0644, fsg_show_nofua, fsg_store_nofua);
-static DEVICE_ATTR(file, 0644, fsg_show_file, fsg_store_file);
-
-static struct device_attribute dev_attr_ro_cdrom =
-	__ATTR(ro, 0444, fsg_show_ro, NULL);
-static struct device_attribute dev_attr_file_nonremovable =
-	__ATTR(file, 0444, fsg_show_file, NULL);
-
-
-/****************************** FSG COMMON ******************************/
-
-static void fsg_common_release(struct kref *ref);
-
-static void fsg_lun_release(struct device *dev)
-{
-	/* Nothing needs to be done */
-}
-
-static inline void fsg_common_get(struct fsg_common *common)
-{
-	kref_get(&common->ref);
-}
-
-static inline void fsg_common_put(struct fsg_common *common)
-{
-	kref_put(&common->ref, fsg_common_release);
-}
-
-static struct fsg_common *fsg_common_init(struct fsg_common *common,
-					  struct usb_composite_dev *cdev,
-					  struct fsg_config *cfg)
-{
-	struct usb_gadget *gadget = cdev->gadget;
-	struct fsg_buffhd *bh;
-	struct fsg_lun *curlun;
-	struct fsg_lun_config *lcfg;
-	int nluns, i, rc;
-	char *pathbuf;
-
-	rc = fsg_num_buffers_validate();
-	if (rc != 0)
-		return ERR_PTR(rc);
-
-	/* Find out how many LUNs there should be */
-	nluns = cfg->nluns;
-	if (nluns < 1 || nluns > FSG_MAX_LUNS) {
-		dev_err(&gadget->dev, "invalid number of LUNs: %u\n", nluns);
-		return ERR_PTR(-EINVAL);
-	}
-
-	/* Allocate? */
-	if (!common) {
-		common = kzalloc(sizeof *common, GFP_KERNEL);
-		if (!common)
-			return ERR_PTR(-ENOMEM);
-		common->free_storage_on_release = 1;
-	} else {
-		memset(common, 0, sizeof *common);
-		common->free_storage_on_release = 0;
-	}
-
-	common->buffhds = kcalloc(fsg_num_buffers,
-				  sizeof *(common->buffhds), GFP_KERNEL);
-	if (!common->buffhds) {
-		if (common->free_storage_on_release)
-			kfree(common);
-		return ERR_PTR(-ENOMEM);
-	}
-
-	common->ops = cfg->ops;
-	common->private_data = cfg->private_data;
-
-	common->gadget = gadget;
-	common->ep0 = gadget->ep0;
-	common->ep0req = cdev->req;
-	common->cdev = cdev;
-
-	/* Maybe allocate device-global string IDs, and patch descriptors */
-	if (fsg_strings[FSG_STRING_INTERFACE].id == 0) {
-		rc = usb_string_id(cdev);
-		if (unlikely(rc < 0))
-			goto error_release;
-		fsg_strings[FSG_STRING_INTERFACE].id = rc;
-		fsg_intf_desc.iInterface = rc;
-	}
-
-	/*
-	 * Create the LUNs, open their backing files, and register the
-	 * LUN devices in sysfs.
-	 */
-	curlun = kcalloc(nluns, sizeof(*curlun), GFP_KERNEL);
-	if (unlikely(!curlun)) {
-		rc = -ENOMEM;
-		goto error_release;
-	}
-	common->luns = curlun;
-
-	init_rwsem(&common->filesem);
-
-	for (i = 0, lcfg = cfg->luns; i < nluns; ++i, ++curlun, ++lcfg) {
-		curlun->cdrom = !!lcfg->cdrom;
-		curlun->ro = lcfg->cdrom || lcfg->ro;
-		curlun->initially_ro = curlun->ro;
-		curlun->removable = lcfg->removable;
-		curlun->dev.release = fsg_lun_release;
-		curlun->dev.parent = &gadget->dev;
-		/* curlun->dev.driver = &fsg_driver.driver; XXX */
-		dev_set_drvdata(&curlun->dev, &common->filesem);
-		dev_set_name(&curlun->dev, "lun%d", i);
-
-		rc = device_register(&curlun->dev);
-		if (rc) {
-			INFO(common, "failed to register LUN%d: %d\n", i, rc);
-			common->nluns = i;
-			put_device(&curlun->dev);
-			goto error_release;
-		}
-
-		rc = device_create_file(&curlun->dev,
-					curlun->cdrom
-				      ? &dev_attr_ro_cdrom
-				      : &dev_attr_ro);
-		if (rc)
-			goto error_luns;
-		rc = device_create_file(&curlun->dev,
-					curlun->removable
-				      ? &dev_attr_file
-				      : &dev_attr_file_nonremovable);
-		if (rc)
-			goto error_luns;
-		rc = device_create_file(&curlun->dev, &dev_attr_nofua);
-		if (rc)
-			goto error_luns;
-
-		if (lcfg->filename) {
-			rc = fsg_lun_open(curlun, lcfg->filename);
-			if (rc)
-				goto error_luns;
-		} else if (!curlun->removable) {
-			ERROR(common, "no file given for LUN%d\n", i);
-			rc = -EINVAL;
-			goto error_luns;
-		}
-	}
-	common->nluns = nluns;
-
-	/* Data buffers cyclic list */
-	bh = common->buffhds;
-	i = fsg_num_buffers;
-	goto buffhds_first_it;
-	do {
-		bh->next = bh + 1;
-		++bh;
-buffhds_first_it:
-		bh->buf = kmalloc(FSG_BUFLEN, GFP_KERNEL);
-		if (unlikely(!bh->buf)) {
-			rc = -ENOMEM;
-			goto error_release;
-		}
-	} while (--i);
-	bh->next = common->buffhds;
-
-	/* Prepare inquiryString */
-	if (cfg->release != 0xffff) {
-		i = cfg->release;
-	} else {
-		i = usb_gadget_controller_number(gadget);
-		if (i >= 0) {
-			i = 0x0300 + i;
-		} else {
-			WARNING(common, "controller '%s' not recognized\n",
-				gadget->name);
-			i = 0x0399;
-		}
-	}
-	snprintf(common->inquiry_string, sizeof common->inquiry_string,
-		 "%-8s%-16s%04x", cfg->vendor_name ?: "Linux",
-		 /* Assume product name dependent on the first LUN */
-		 cfg->product_name ?: (common->luns->cdrom
-				     ? "File-Stor Gadget"
-				     : "File-CD Gadget"),
-		 i);
-
-	/*
-	 * Some peripheral controllers are known not to be able to
-	 * halt bulk endpoints correctly.  If one of them is present,
-	 * disable stalls.
-	 */
-	common->can_stall = cfg->can_stall &&
-		!(gadget_is_at91(common->gadget));
-
-	spin_lock_init(&common->lock);
-	kref_init(&common->ref);
-
-	/* Tell the thread to start working */
-	common->thread_task =
-		kthread_create(fsg_main_thread, common, "file-storage");
-	if (IS_ERR(common->thread_task)) {
-		rc = PTR_ERR(common->thread_task);
-		goto error_release;
-	}
-	init_completion(&common->thread_notifier);
-	init_waitqueue_head(&common->fsg_wait);
-
-	/* Information */
-	INFO(common, FSG_DRIVER_DESC ", version: " FSG_DRIVER_VERSION "\n");
-	INFO(common, "Number of LUNs=%d\n", common->nluns);
-
-	pathbuf = kmalloc(PATH_MAX, GFP_KERNEL);
-	for (i = 0, nluns = common->nluns, curlun = common->luns;
-	     i < nluns;
-	     ++curlun, ++i) {
-		char *p = "(no medium)";
-		if (fsg_lun_is_open(curlun)) {
-			p = "(error)";
-			if (pathbuf) {
-				p = d_path(&curlun->filp->f_path,
-					   pathbuf, PATH_MAX);
-				if (IS_ERR(p))
-					p = "(error)";
-			}
-		}
-		LINFO(curlun, "LUN: %s%s%sfile: %s\n",
-		      curlun->removable ? "removable " : "",
-		      curlun->ro ? "read only " : "",
-		      curlun->cdrom ? "CD-ROM " : "",
-		      p);
-	}
-	kfree(pathbuf);
-
-	DBG(common, "I/O thread pid: %d\n", task_pid_nr(common->thread_task));
-
-	wake_up_process(common->thread_task);
-
-	return common;
-
-error_luns:
-	common->nluns = i + 1;
-error_release:
-	common->state = FSG_STATE_TERMINATED;	/* The thread is dead */
-	/* Call fsg_common_release() directly, ref might be not initialised. */
-	fsg_common_release(&common->ref);
-	return ERR_PTR(rc);
-}
-
-static void fsg_common_release(struct kref *ref)
-{
-	struct fsg_common *common = container_of(ref, struct fsg_common, ref);
-
-	/* If the thread isn't already dead, tell it to exit now */
-	if (common->state != FSG_STATE_TERMINATED) {
-		raise_exception(common, FSG_STATE_EXIT);
-		wait_for_completion(&common->thread_notifier);
-	}
-
-	if (likely(common->luns)) {
-		struct fsg_lun *lun = common->luns;
-		unsigned i = common->nluns;
-
-		/* In error recovery common->nluns may be zero. */
-		for (; i; --i, ++lun) {
-			device_remove_file(&lun->dev, &dev_attr_nofua);
-			device_remove_file(&lun->dev,
-					   lun->cdrom
-					 ? &dev_attr_ro_cdrom
-					 : &dev_attr_ro);
-			device_remove_file(&lun->dev,
-					   lun->removable
-					 ? &dev_attr_file
-					 : &dev_attr_file_nonremovable);
-			fsg_lun_close(lun);
-			device_unregister(&lun->dev);
-		}
-
-		kfree(common->luns);
-	}
-
-	{
-		struct fsg_buffhd *bh = common->buffhds;
-		unsigned i = fsg_num_buffers;
-		do {
-			kfree(bh->buf);
-		} while (++bh, --i);
-	}
-
-	kfree(common->buffhds);
-	if (common->free_storage_on_release)
-		kfree(common);
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static void fsg_unbind(struct usb_configuration *c, struct usb_function *f)
-{
-	struct fsg_dev		*fsg = fsg_from_func(f);
-	struct fsg_common	*common = fsg->common;
-
-	DBG(fsg, "unbind\n");
-	if (fsg->common->fsg == fsg) {
-		fsg->common->new_fsg = NULL;
-		raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE);
-		/* FIXME: make interruptible or killable somehow? */
-		wait_event(common->fsg_wait, common->fsg != fsg);
-	}
-
-	fsg_common_put(common);
-	usb_free_descriptors(fsg->function.descriptors);
-	usb_free_descriptors(fsg->function.hs_descriptors);
-	usb_free_descriptors(fsg->function.ss_descriptors);
-	kfree(fsg);
-}
-
-static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
-{
-	struct fsg_dev		*fsg = fsg_from_func(f);
-	struct usb_gadget	*gadget = c->cdev->gadget;
-	int			i;
-	struct usb_ep		*ep;
-
-	fsg->gadget = gadget;
-
-	/* New interface */
-	i = usb_interface_id(c, f);
-	if (i < 0)
-		return i;
-	fsg_intf_desc.bInterfaceNumber = i;
-	fsg->interface_number = i;
-
-	/* Find all the endpoints we will use */
-	ep = usb_ep_autoconfig(gadget, &fsg_fs_bulk_in_desc);
-	if (!ep)
-		goto autoconf_fail;
-	ep->driver_data = fsg->common;	/* claim the endpoint */
-	fsg->bulk_in = ep;
-
-	ep = usb_ep_autoconfig(gadget, &fsg_fs_bulk_out_desc);
-	if (!ep)
-		goto autoconf_fail;
-	ep->driver_data = fsg->common;	/* claim the endpoint */
-	fsg->bulk_out = ep;
-
-	/* Copy descriptors */
-	f->descriptors = usb_copy_descriptors(fsg_fs_function);
-	if (unlikely(!f->descriptors))
-		return -ENOMEM;
-
-	if (gadget_is_dualspeed(gadget)) {
-		/* Assume endpoint addresses are the same for both speeds */
-		fsg_hs_bulk_in_desc.bEndpointAddress =
-			fsg_fs_bulk_in_desc.bEndpointAddress;
-		fsg_hs_bulk_out_desc.bEndpointAddress =
-			fsg_fs_bulk_out_desc.bEndpointAddress;
-		f->hs_descriptors = usb_copy_descriptors(fsg_hs_function);
-		if (unlikely(!f->hs_descriptors)) {
-			usb_free_descriptors(f->descriptors);
-			return -ENOMEM;
-		}
-	}
-
-	if (gadget_is_superspeed(gadget)) {
-		unsigned	max_burst;
-
-		/* Calculate bMaxBurst, we know packet size is 1024 */
-		max_burst = min_t(unsigned, FSG_BUFLEN / 1024, 15);
-
-		fsg_ss_bulk_in_desc.bEndpointAddress =
-			fsg_fs_bulk_in_desc.bEndpointAddress;
-		fsg_ss_bulk_in_comp_desc.bMaxBurst = max_burst;
-
-		fsg_ss_bulk_out_desc.bEndpointAddress =
-			fsg_fs_bulk_out_desc.bEndpointAddress;
-		fsg_ss_bulk_out_comp_desc.bMaxBurst = max_burst;
-
-		f->ss_descriptors = usb_copy_descriptors(fsg_ss_function);
-		if (unlikely(!f->ss_descriptors)) {
-			usb_free_descriptors(f->hs_descriptors);
-			usb_free_descriptors(f->descriptors);
-			return -ENOMEM;
-		}
-	}
-
-	return 0;
-
-autoconf_fail:
-	ERROR(fsg, "unable to autoconfigure all endpoints\n");
-	return -ENOTSUPP;
-}
-
-
-/****************************** ADD FUNCTION ******************************/
-
-static struct usb_gadget_strings *fsg_strings_array[] = {
-	&fsg_stringtab,
-	NULL,
-};
-
-static int fsg_bind_config(struct usb_composite_dev *cdev,
-			   struct usb_configuration *c,
-			   struct fsg_common *common)
-{
-	struct fsg_dev *fsg;
-	int rc;
-
-	fsg = kzalloc(sizeof *fsg, GFP_KERNEL);
-	if (unlikely(!fsg))
-		return -ENOMEM;
-
-	fsg->function.name        = FSG_DRIVER_DESC;
-	fsg->function.strings     = fsg_strings_array;
-	fsg->function.bind        = fsg_bind;
-	fsg->function.unbind      = fsg_unbind;
-	fsg->function.setup       = fsg_setup;
-	fsg->function.set_alt     = fsg_set_alt;
-	fsg->function.disable     = fsg_disable;
-
-	fsg->common               = common;
-	/*
-	 * Our caller holds a reference to common structure so we
-	 * don't have to be worry about it being freed until we return
-	 * from this function.  So instead of incrementing counter now
-	 * and decrement in error recovery we increment it only when
-	 * call to usb_add_function() was successful.
-	 */
-
-	rc = usb_add_function(c, &fsg->function);
-	if (unlikely(rc))
-		kfree(fsg);
-	else
-		fsg_common_get(fsg->common);
-	return rc;
-}
-
-
-/************************* Module parameters *************************/
-
-struct fsg_module_parameters {
-	char		*file[FSG_MAX_LUNS];
-	bool		ro[FSG_MAX_LUNS];
-	bool		removable[FSG_MAX_LUNS];
-	bool		cdrom[FSG_MAX_LUNS];
-	bool		nofua[FSG_MAX_LUNS];
-
-	unsigned int	file_count, ro_count, removable_count, cdrom_count;
-	unsigned int	nofua_count;
-	unsigned int	luns;	/* nluns */
-	bool		stall;	/* can_stall */
-};
-
-#define _FSG_MODULE_PARAM_ARRAY(prefix, params, name, type, desc)	\
-	module_param_array_named(prefix ## name, params.name, type,	\
-				 &prefix ## params.name ## _count,	\
-				 S_IRUGO);				\
-	MODULE_PARM_DESC(prefix ## name, desc)
-
-#define _FSG_MODULE_PARAM(prefix, params, name, type, desc)		\
-	module_param_named(prefix ## name, params.name, type,		\
-			   S_IRUGO);					\
-	MODULE_PARM_DESC(prefix ## name, desc)
-
-#define FSG_MODULE_PARAMETERS(prefix, params)				\
-	_FSG_MODULE_PARAM_ARRAY(prefix, params, file, charp,		\
-				"names of backing files or devices");	\
-	_FSG_MODULE_PARAM_ARRAY(prefix, params, ro, bool,		\
-				"true to force read-only");		\
-	_FSG_MODULE_PARAM_ARRAY(prefix, params, removable, bool,	\
-				"true to simulate removable media");	\
-	_FSG_MODULE_PARAM_ARRAY(prefix, params, cdrom, bool,		\
-				"true to simulate CD-ROM instead of disk"); \
-	_FSG_MODULE_PARAM_ARRAY(prefix, params, nofua, bool,		\
-				"true to ignore SCSI WRITE(10,12) FUA bit"); \
-	_FSG_MODULE_PARAM(prefix, params, luns, uint,			\
-			  "number of LUNs");				\
-	_FSG_MODULE_PARAM(prefix, params, stall, bool,			\
-			  "false to prevent bulk stalls")
-
-static void
-fsg_config_from_params(struct fsg_config *cfg,
-		       const struct fsg_module_parameters *params)
-{
-	struct fsg_lun_config *lun;
-	unsigned i;
-
-	/* Configure LUNs */
-	cfg->nluns =
-		min(params->luns ?: (params->file_count ?: 1u),
-		    (unsigned)FSG_MAX_LUNS);
-	for (i = 0, lun = cfg->luns; i < cfg->nluns; ++i, ++lun) {
-		lun->ro = !!params->ro[i];
-		lun->cdrom = !!params->cdrom[i];
-		lun->removable = !!params->removable[i];
-		lun->filename =
-			params->file_count > i && params->file[i][0]
-			? params->file[i]
-			: 0;
-	}
-
-	/* Let MSF use defaults */
-	cfg->vendor_name = 0;
-	cfg->product_name = 0;
-	cfg->release = 0xffff;
-
-	cfg->ops = NULL;
-	cfg->private_data = NULL;
-
-	/* Finalise */
-	cfg->can_stall = params->stall;
-}
-
-static inline struct fsg_common *
-fsg_common_from_params(struct fsg_common *common,
-		       struct usb_composite_dev *cdev,
-		       const struct fsg_module_parameters *params)
-	__attribute__((unused));
-static inline struct fsg_common *
-fsg_common_from_params(struct fsg_common *common,
-		       struct usb_composite_dev *cdev,
-		       const struct fsg_module_parameters *params)
-{
-	struct fsg_config cfg;
-	fsg_config_from_params(&cfg, params);
-	return fsg_common_init(common, cdev, &cfg);
-}
diff --git a/drivers/staging/ccg/f_rndis.c b/drivers/staging/ccg/f_rndis.c
deleted file mode 100644
index b1681e4..0000000
--- a/drivers/staging/ccg/f_rndis.c
+++ /dev/null
@@ -1,918 +0,0 @@
-/*
- * f_rndis.c -- RNDIS link function driver
- *
- * Copyright (C) 2003-2005,2008 David Brownell
- * Copyright (C) 2003-2004 Robert Schwebel, Benedikt Spranger
- * Copyright (C) 2008 Nokia Corporation
- * Copyright (C) 2009 Samsung Electronics
- *                    Author: Michal Nazarewicz (mina86@mina86.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 VERBOSE_DEBUG */
-
-#include <linux/slab.h>
-#include <linux/kernel.h>
-#include <linux/device.h>
-#include <linux/etherdevice.h>
-
-#include <linux/atomic.h>
-
-#include "u_ether.h"
-#include "rndis.h"
-
-
-/*
- * This function is an RNDIS Ethernet port -- a Microsoft protocol that's
- * been promoted instead of the standard CDC Ethernet.  The published RNDIS
- * spec is ambiguous, incomplete, and needlessly complex.  Variants such as
- * ActiveSync have even worse status in terms of specification.
- *
- * In short:  it's a protocol controlled by (and for) Microsoft, not for an
- * Open ecosystem or markets.  Linux supports it *only* because Microsoft
- * doesn't support the CDC Ethernet standard.
- *
- * The RNDIS data transfer model is complex, with multiple Ethernet packets
- * per USB message, and out of band data.  The control model is built around
- * what's essentially an "RNDIS RPC" protocol.  It's all wrapped in a CDC ACM
- * (modem, not Ethernet) veneer, with those ACM descriptors being entirely
- * useless (they're ignored).  RNDIS expects to be the only function in its
- * configuration, so it's no real help if you need composite devices; and
- * it expects to be the first configuration too.
- *
- * There is a single technical advantage of RNDIS over CDC Ethernet, if you
- * discount the fluff that its RPC can be made to deliver: it doesn't need
- * a NOP altsetting for the data interface.  That lets it work on some of the
- * "so smart it's stupid" hardware which takes over configuration changes
- * from the software, and adds restrictions like "no altsettings".
- *
- * Unfortunately MSFT's RNDIS drivers are buggy.  They hang or oops, and
- * have all sorts of contrary-to-specification oddities that can prevent
- * them from working sanely.  Since bugfixes (or accurate specs, letting
- * Linux work around those bugs) are unlikely to ever come from MSFT, you
- * may want to avoid using RNDIS on purely operational grounds.
- *
- * Omissions from the RNDIS 1.0 specification include:
- *
- *   - Power management ... references data that's scattered around lots
- *     of other documentation, which is incorrect/incomplete there too.
- *
- *   - There are various undocumented protocol requirements, like the need
- *     to send garbage in some control-OUT messages.
- *
- *   - MS-Windows drivers sometimes emit undocumented requests.
- */
-
-struct f_rndis {
-	struct gether			port;
-	u8				ctrl_id, data_id;
-	u8				ethaddr[ETH_ALEN];
-	u32				vendorID;
-	const char			*manufacturer;
-	int				config;
-
-	struct usb_ep			*notify;
-	struct usb_request		*notify_req;
-	atomic_t			notify_count;
-};
-
-static inline struct f_rndis *func_to_rndis(struct usb_function *f)
-{
-	return container_of(f, struct f_rndis, port.func);
-}
-
-/* peak (theoretical) bulk transfer rate in bits-per-second */
-static unsigned int bitrate(struct usb_gadget *g)
-{
-	if (gadget_is_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;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/*
- */
-
-#define LOG2_STATUS_INTERVAL_MSEC	5	/* 1 << 5 == 32 msec */
-#define STATUS_BYTECOUNT		8	/* 8 bytes data */
-
-
-/* interface descriptor: */
-
-static struct usb_interface_descriptor rndis_control_intf = {
-	.bLength =		sizeof rndis_control_intf,
-	.bDescriptorType =	USB_DT_INTERFACE,
-
-	/* .bInterfaceNumber = DYNAMIC */
-	/* status endpoint is optional; this could be patched later */
-	.bNumEndpoints =	1,
-	.bInterfaceClass =	USB_CLASS_COMM,
-	.bInterfaceSubClass =   USB_CDC_SUBCLASS_ACM,
-	.bInterfaceProtocol =   USB_CDC_ACM_PROTO_VENDOR,
-	/* .iInterface = DYNAMIC */
-};
-
-static struct usb_cdc_header_desc header_desc = {
-	.bLength =		sizeof header_desc,
-	.bDescriptorType =	USB_DT_CS_INTERFACE,
-	.bDescriptorSubType =	USB_CDC_HEADER_TYPE,
-
-	.bcdCDC =		cpu_to_le16(0x0110),
-};
-
-static struct usb_cdc_call_mgmt_descriptor call_mgmt_descriptor = {
-	.bLength =		sizeof call_mgmt_descriptor,
-	.bDescriptorType =	USB_DT_CS_INTERFACE,
-	.bDescriptorSubType =	USB_CDC_CALL_MANAGEMENT_TYPE,
-
-	.bmCapabilities =	0x00,
-	.bDataInterface =	0x01,
-};
-
-static struct usb_cdc_acm_descriptor rndis_acm_descriptor = {
-	.bLength =		sizeof rndis_acm_descriptor,
-	.bDescriptorType =	USB_DT_CS_INTERFACE,
-	.bDescriptorSubType =	USB_CDC_ACM_TYPE,
-
-	.bmCapabilities =	0x00,
-};
-
-static struct usb_cdc_union_desc rndis_union_desc = {
-	.bLength =		sizeof(rndis_union_desc),
-	.bDescriptorType =	USB_DT_CS_INTERFACE,
-	.bDescriptorSubType =	USB_CDC_UNION_TYPE,
-	/* .bMasterInterface0 =	DYNAMIC */
-	/* .bSlaveInterface0 =	DYNAMIC */
-};
-
-/* the data interface has two bulk endpoints */
-
-static struct usb_interface_descriptor rndis_data_intf = {
-	.bLength =		sizeof rndis_data_intf,
-	.bDescriptorType =	USB_DT_INTERFACE,
-
-	/* .bInterfaceNumber = DYNAMIC */
-	.bNumEndpoints =	2,
-	.bInterfaceClass =	USB_CLASS_CDC_DATA,
-	.bInterfaceSubClass =	0,
-	.bInterfaceProtocol =	0,
-	/* .iInterface = DYNAMIC */
-};
-
-
-static struct usb_interface_assoc_descriptor
-rndis_iad_descriptor = {
-	.bLength =		sizeof rndis_iad_descriptor,
-	.bDescriptorType =	USB_DT_INTERFACE_ASSOCIATION,
-
-	.bFirstInterface =	0, /* XXX, hardcoded */
-	.bInterfaceCount = 	2,	// control + data
-	.bFunctionClass =	USB_CLASS_COMM,
-	.bFunctionSubClass =	USB_CDC_SUBCLASS_ETHERNET,
-	.bFunctionProtocol =	USB_CDC_PROTO_NONE,
-	/* .iFunction = DYNAMIC */
-};
-
-/* full speed support: */
-
-static struct usb_endpoint_descriptor fs_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 =		1 << LOG2_STATUS_INTERVAL_MSEC,
-};
-
-static struct usb_endpoint_descriptor fs_in_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-
-	.bEndpointAddress =	USB_DIR_IN,
-	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-};
-
-static struct usb_endpoint_descriptor fs_out_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-
-	.bEndpointAddress =	USB_DIR_OUT,
-	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-};
-
-static struct usb_descriptor_header *eth_fs_function[] = {
-	(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 *) &fs_notify_desc,
-
-	/* data interface has no altsetting */
-	(struct usb_descriptor_header *) &rndis_data_intf,
-	(struct usb_descriptor_header *) &fs_in_desc,
-	(struct usb_descriptor_header *) &fs_out_desc,
-	NULL,
-};
-
-/* high speed support: */
-
-static struct usb_endpoint_descriptor hs_notify_desc = {
-	.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_endpoint_descriptor hs_in_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-
-	.bEndpointAddress =	USB_DIR_IN,
-	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	cpu_to_le16(512),
-};
-
-static struct usb_endpoint_descriptor hs_out_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-
-	.bEndpointAddress =	USB_DIR_OUT,
-	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	cpu_to_le16(512),
-};
-
-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,
-	(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 *) &hs_notify_desc,
-
-	/* data interface has no altsetting */
-	(struct usb_descriptor_header *) &rndis_data_intf,
-	(struct usb_descriptor_header *) &hs_in_desc,
-	(struct usb_descriptor_header *) &hs_out_desc,
-	NULL,
-};
-
-/* 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[] = {
-	[0].s = "RNDIS Communications Control",
-	[1].s = "RNDIS Ethernet Data",
-	[2].s = "RNDIS",
-	{  } /* end of list */
-};
-
-static struct usb_gadget_strings rndis_string_table = {
-	.language =		0x0409,	/* en-us */
-	.strings =		rndis_string_defs,
-};
-
-static struct usb_gadget_strings *rndis_strings[] = {
-	&rndis_string_table,
-	NULL,
-};
-
-/*-------------------------------------------------------------------------*/
-
-static struct sk_buff *rndis_add_header(struct gether *port,
-					struct sk_buff *skb)
-{
-	struct sk_buff *skb2;
-
-	skb2 = skb_realloc_headroom(skb, sizeof(struct rndis_packet_msg_type));
-	if (skb2)
-		rndis_add_hdr(skb2);
-
-	dev_kfree_skb_any(skb);
-	return skb2;
-}
-
-static void rndis_response_available(void *_rndis)
-{
-	struct f_rndis			*rndis = _rndis;
-	struct usb_request		*req = rndis->notify_req;
-	struct usb_composite_dev	*cdev = rndis->port.func.config->cdev;
-	__le32				*data = req->buf;
-	int				status;
-
-	if (atomic_inc_return(&rndis->notify_count) != 1)
-		return;
-
-	/* Send RNDIS RESPONSE_AVAILABLE notification; a
-	 * USB_CDC_NOTIFY_RESPONSE_AVAILABLE "should" work too
-	 *
-	 * This is the only notification defined by RNDIS.
-	 */
-	data[0] = cpu_to_le32(1);
-	data[1] = cpu_to_le32(0);
-
-	status = usb_ep_queue(rndis->notify, req, GFP_ATOMIC);
-	if (status) {
-		atomic_dec(&rndis->notify_count);
-		DBG(cdev, "notify/0 --> %d\n", status);
-	}
-}
-
-static void rndis_response_complete(struct usb_ep *ep, struct usb_request *req)
-{
-	struct f_rndis			*rndis = req->context;
-	struct usb_composite_dev	*cdev = rndis->port.func.config->cdev;
-	int				status = req->status;
-
-	/* after TX:
-	 *  - USB_CDC_GET_ENCAPSULATED_RESPONSE (ep0/control)
-	 *  - RNDIS_RESPONSE_AVAILABLE (status/irq)
-	 */
-	switch (status) {
-	case -ECONNRESET:
-	case -ESHUTDOWN:
-		/* connection gone */
-		atomic_set(&rndis->notify_count, 0);
-		break;
-	default:
-		DBG(cdev, "RNDIS %s response error %d, %d/%d\n",
-			ep->name, status,
-			req->actual, req->length);
-		/* FALLTHROUGH */
-	case 0:
-		if (ep != rndis->notify)
-			break;
-
-		/* handle multiple pending RNDIS_RESPONSE_AVAILABLE
-		 * notifications by resending until we're done
-		 */
-		if (atomic_dec_and_test(&rndis->notify_count))
-			break;
-		status = usb_ep_queue(rndis->notify, req, GFP_ATOMIC);
-		if (status) {
-			atomic_dec(&rndis->notify_count);
-			DBG(cdev, "notify/1 --> %d\n", status);
-		}
-		break;
-	}
-}
-
-static void rndis_command_complete(struct usb_ep *ep, struct usb_request *req)
-{
-	struct f_rndis			*rndis = req->context;
-	struct usb_composite_dev	*cdev = rndis->port.func.config->cdev;
-	int				status;
-
-	/* received RNDIS command from USB_CDC_SEND_ENCAPSULATED_COMMAND */
-//	spin_lock(&dev->lock);
-	status = rndis_msg_parser(rndis->config, (u8 *) req->buf);
-	if (status < 0)
-		ERROR(cdev, "RNDIS command error %d, %d/%d\n",
-			status, req->actual, req->length);
-//	spin_unlock(&dev->lock);
-}
-
-static int
-rndis_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
-{
-	struct f_rndis		*rndis = func_to_rndis(f);
-	struct usb_composite_dev *cdev = f->config->cdev;
-	struct usb_request	*req = cdev->req;
-	int			value = -EOPNOTSUPP;
-	u16			w_index = le16_to_cpu(ctrl->wIndex);
-	u16			w_value = le16_to_cpu(ctrl->wValue);
-	u16			w_length = le16_to_cpu(ctrl->wLength);
-
-	/* composite driver infrastructure handles everything except
-	 * CDC class messages; interface activation uses set_alt().
-	 */
-	switch ((ctrl->bRequestType << 8) | ctrl->bRequest) {
-
-	/* RNDIS uses the CDC command encapsulation mechanism to implement
-	 * an RPC scheme, with much getting/setting of attributes by OID.
-	 */
-	case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
-			| USB_CDC_SEND_ENCAPSULATED_COMMAND:
-		if (w_value || w_index != rndis->ctrl_id)
-			goto invalid;
-		/* read the request; process it later */
-		value = w_length;
-		req->complete = rndis_command_complete;
-		req->context = rndis;
-		/* later, rndis_response_available() sends a notification */
-		break;
-
-	case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
-			| USB_CDC_GET_ENCAPSULATED_RESPONSE:
-		if (w_value || w_index != rndis->ctrl_id)
-			goto invalid;
-		else {
-			u8 *buf;
-			u32 n;
-
-			/* return the result */
-			buf = rndis_get_next_response(rndis->config, &n);
-			if (buf) {
-				memcpy(req->buf, buf, n);
-				req->complete = rndis_response_complete;
-				req->context = rndis;
-				rndis_free_response(rndis->config, buf);
-				value = n;
-			}
-			/* else stalls ... spec says to avoid that */
-		}
-		break;
-
-	default:
-invalid:
-		VDBG(cdev, "invalid control req%02x.%02x v%04x i%04x l%d\n",
-			ctrl->bRequestType, ctrl->bRequest,
-			w_value, w_index, w_length);
-	}
-
-	/* respond with data transfer or status phase? */
-	if (value >= 0) {
-		DBG(cdev, "rndis req%02x.%02x v%04x i%04x l%d\n",
-			ctrl->bRequestType, ctrl->bRequest,
-			w_value, w_index, w_length);
-		req->zero = (value < w_length);
-		req->length = value;
-		value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);
-		if (value < 0)
-			ERROR(cdev, "rndis response on err %d\n", value);
-	}
-
-	/* device either stalls (value < 0) or reports success */
-	return value;
-}
-
-
-static int rndis_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
-{
-	struct f_rndis		*rndis = func_to_rndis(f);
-	struct usb_composite_dev *cdev = f->config->cdev;
-
-	/* we know alt == 0 */
-
-	if (intf == rndis->ctrl_id) {
-		if (rndis->notify->driver_data) {
-			VDBG(cdev, "reset rndis control %d\n", intf);
-			usb_ep_disable(rndis->notify);
-		}
-		if (!rndis->notify->desc) {
-			VDBG(cdev, "init rndis ctrl %d\n", intf);
-			if (config_ep_by_speed(cdev->gadget, f, rndis->notify))
-				goto fail;
-		}
-		usb_ep_enable(rndis->notify);
-		rndis->notify->driver_data = rndis;
-
-	} else if (intf == rndis->data_id) {
-		struct net_device	*net;
-
-		if (rndis->port.in_ep->driver_data) {
-			DBG(cdev, "reset rndis\n");
-			gether_disconnect(&rndis->port);
-		}
-
-		if (!rndis->port.in_ep->desc || !rndis->port.out_ep->desc) {
-			DBG(cdev, "init rndis\n");
-			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. */
-		rndis->port.is_zlp_ok = false;
-
-		/* RNDIS should be in the "RNDIS uninitialized" state,
-		 * either never activated or after rndis_uninit().
-		 *
-		 * We don't want data to flow here until a nonzero packet
-		 * filter is set, at which point it enters "RNDIS data
-		 * initialized" state ... but we do want the endpoints
-		 * to be activated.  It's a strange little state.
-		 *
-		 * REVISIT the RNDIS gadget code has done this wrong for a
-		 * very long time.  We need another call to the link layer
-		 * code -- gether_updown(...bool) maybe -- to do it right.
-		 */
-		rndis->port.cdc_filter = 0;
-
-		DBG(cdev, "RNDIS RX/TX early activation ... \n");
-		net = gether_connect(&rndis->port);
-		if (IS_ERR(net))
-			return PTR_ERR(net);
-
-		rndis_set_param_dev(rndis->config, net,
-				&rndis->port.cdc_filter);
-	} else
-		goto fail;
-
-	return 0;
-fail:
-	return -EINVAL;
-}
-
-static void rndis_disable(struct usb_function *f)
-{
-	struct f_rndis		*rndis = func_to_rndis(f);
-	struct usb_composite_dev *cdev = f->config->cdev;
-
-	if (!rndis->notify->driver_data)
-		return;
-
-	DBG(cdev, "rndis deactivated\n");
-
-	rndis_uninit(rndis->config);
-	gether_disconnect(&rndis->port);
-
-	usb_ep_disable(rndis->notify);
-	rndis->notify->driver_data = NULL;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * This isn't quite the same mechanism as CDC Ethernet, since the
- * notification scheme passes less data, but the same set of link
- * states must be tested.  A key difference is that altsettings are
- * not used to tell whether the link should send packets or not.
- */
-
-static void rndis_open(struct gether *geth)
-{
-	struct f_rndis		*rndis = func_to_rndis(&geth->func);
-	struct usb_composite_dev *cdev = geth->func.config->cdev;
-
-	DBG(cdev, "%s\n", __func__);
-
-	rndis_set_param_medium(rndis->config, RNDIS_MEDIUM_802_3,
-				bitrate(cdev->gadget) / 100);
-	rndis_signal_connect(rndis->config);
-}
-
-static void rndis_close(struct gether *geth)
-{
-	struct f_rndis		*rndis = func_to_rndis(&geth->func);
-
-	DBG(geth->func.config->cdev, "%s\n", __func__);
-
-	rndis_set_param_medium(rndis->config, RNDIS_MEDIUM_802_3, 0);
-	rndis_signal_disconnect(rndis->config);
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* ethernet function driver setup/binding */
-
-static int
-rndis_bind(struct usb_configuration *c, struct usb_function *f)
-{
-	struct usb_composite_dev *cdev = c->cdev;
-	struct f_rndis		*rndis = func_to_rndis(f);
-	int			status;
-	struct usb_ep		*ep;
-
-	/* allocate instance-specific interface IDs */
-	status = usb_interface_id(c, f);
-	if (status < 0)
-		goto fail;
-	rndis->ctrl_id = status;
-	rndis_iad_descriptor.bFirstInterface = status;
-
-	rndis_control_intf.bInterfaceNumber = status;
-	rndis_union_desc.bMasterInterface0 = status;
-
-	status = usb_interface_id(c, f);
-	if (status < 0)
-		goto fail;
-	rndis->data_id = status;
-
-	rndis_data_intf.bInterfaceNumber = status;
-	rndis_union_desc.bSlaveInterface0 = status;
-
-	status = -ENODEV;
-
-	/* allocate instance-specific endpoints */
-	ep = usb_ep_autoconfig(cdev->gadget, &fs_in_desc);
-	if (!ep)
-		goto fail;
-	rndis->port.in_ep = ep;
-	ep->driver_data = cdev;	/* claim */
-
-	ep = usb_ep_autoconfig(cdev->gadget, &fs_out_desc);
-	if (!ep)
-		goto fail;
-	rndis->port.out_ep = ep;
-	ep->driver_data = cdev;	/* claim */
-
-	/* NOTE:  a status/notification endpoint is, strictly speaking,
-	 * optional.  We don't treat it that way though!  It's simpler,
-	 * and some newer profiles don't treat it as optional.
-	 */
-	ep = usb_ep_autoconfig(cdev->gadget, &fs_notify_desc);
-	if (!ep)
-		goto fail;
-	rndis->notify = ep;
-	ep->driver_data = cdev;	/* claim */
-
-	status = -ENOMEM;
-
-	/* allocate notification request and buffer */
-	rndis->notify_req = usb_ep_alloc_request(ep, GFP_KERNEL);
-	if (!rndis->notify_req)
-		goto fail;
-	rndis->notify_req->buf = kmalloc(STATUS_BYTECOUNT, GFP_KERNEL);
-	if (!rndis->notify_req->buf)
-		goto fail;
-	rndis->notify_req->length = STATUS_BYTECOUNT;
-	rndis->notify_req->context = rndis;
-	rndis->notify_req->complete = rndis_response_complete;
-
-	/* copy descriptors, and track endpoint copies */
-	f->descriptors = usb_copy_descriptors(eth_fs_function);
-	if (!f->descriptors)
-		goto fail;
-
-	/* support all relevant hardware speeds... we expect that when
-	 * hardware is dual speed, all bulk-capable endpoints work at
-	 * both speeds
-	 */
-	if (gadget_is_dualspeed(c->cdev->gadget)) {
-		hs_in_desc.bEndpointAddress =
-				fs_in_desc.bEndpointAddress;
-		hs_out_desc.bEndpointAddress =
-				fs_out_desc.bEndpointAddress;
-		hs_notify_desc.bEndpointAddress =
-				fs_notify_desc.bEndpointAddress;
-
-		/* copy descriptors, and track endpoint copies */
-		f->hs_descriptors = usb_copy_descriptors(eth_hs_function);
-		if (!f->hs_descriptors)
-			goto fail;
-	}
-
-	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;
-	rndis->port.close = rndis_close;
-
-	status = rndis_register(rndis_response_available, rndis);
-	if (status < 0)
-		goto fail;
-	rndis->config = status;
-
-	rndis_set_param_medium(rndis->config, RNDIS_MEDIUM_802_3, 0);
-	rndis_set_host_mac(rndis->config, rndis->ethaddr);
-
-	if (rndis->manufacturer && rndis->vendorID &&
-			rndis_set_param_vendor(rndis->config, rndis->vendorID,
-					       rndis->manufacturer))
-		goto fail;
-
-	/* NOTE:  all that is done without knowing or caring about
-	 * the network link ... which is unavailable to this code
-	 * until we're activated via set_alt().
-	 */
-
-	DBG(cdev, "RNDIS: %s speed IN/%s OUT/%s NOTIFY/%s\n",
-			gadget_is_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)
-		usb_free_descriptors(f->descriptors);
-
-	if (rndis->notify_req) {
-		kfree(rndis->notify_req->buf);
-		usb_ep_free_request(rndis->notify, rndis->notify_req);
-	}
-
-	/* we might as well release our claims on endpoints */
-	if (rndis->notify)
-		rndis->notify->driver_data = NULL;
-	if (rndis->port.out_ep->desc)
-		rndis->port.out_ep->driver_data = NULL;
-	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);
-
-	return status;
-}
-
-static void
-rndis_unbind(struct usb_configuration *c, struct usb_function *f)
-{
-	struct f_rndis		*rndis = func_to_rndis(f);
-
-	rndis_deregister(rndis->config);
-	rndis_exit();
-	rndis_string_defs[0].id = 0;
-
-	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);
-
-	kfree(rndis->notify_req->buf);
-	usb_ep_free_request(rndis->notify, rndis->notify_req);
-
-	kfree(rndis);
-}
-
-/* Some controllers can't support RNDIS ... */
-static inline bool can_support_rndis(struct usb_configuration *c)
-{
-	/* everything else is *presumably* fine */
-	return true;
-}
-
-int
-rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
-				u32 vendorID, const char *manufacturer)
-{
-	struct f_rndis	*rndis;
-	int		status;
-
-	if (!can_support_rndis(c) || !ethaddr)
-		return -EINVAL;
-
-	/* maybe allocate device-global string IDs */
-	if (rndis_string_defs[0].id == 0) {
-
-		/* ... and setup RNDIS itself */
-		status = rndis_init();
-		if (status < 0)
-			return status;
-
-		/* control interface label */
-		status = usb_string_id(c->cdev);
-		if (status < 0)
-			return status;
-		rndis_string_defs[0].id = status;
-		rndis_control_intf.iInterface = status;
-
-		/* data interface label */
-		status = usb_string_id(c->cdev);
-		if (status < 0)
-			return status;
-		rndis_string_defs[1].id = status;
-		rndis_data_intf.iInterface = status;
-
-		/* IAD iFunction label */
-		status = usb_string_id(c->cdev);
-		if (status < 0)
-			return status;
-		rndis_string_defs[2].id = status;
-		rndis_iad_descriptor.iFunction = status;
-	}
-
-	/* allocate and initialize one new instance */
-	status = -ENOMEM;
-	rndis = kzalloc(sizeof *rndis, GFP_KERNEL);
-	if (!rndis)
-		goto fail;
-
-	memcpy(rndis->ethaddr, ethaddr, ETH_ALEN);
-	rndis->vendorID = vendorID;
-	rndis->manufacturer = manufacturer;
-
-	/* RNDIS activates when the host changes this filter */
-	rndis->port.cdc_filter = 0;
-
-	/* RNDIS has special (and complex) framing */
-	rndis->port.header_len = sizeof(struct rndis_packet_msg_type);
-	rndis->port.wrap = rndis_add_header;
-	rndis->port.unwrap = rndis_rm_hdr;
-
-	rndis->port.func.name = "rndis";
-	rndis->port.func.strings = rndis_strings;
-	/* descriptors are per-instance copies */
-	rndis->port.func.bind = rndis_bind;
-	rndis->port.func.unbind = rndis_unbind;
-	rndis->port.func.set_alt = rndis_set_alt;
-	rndis->port.func.setup = rndis_setup;
-	rndis->port.func.disable = rndis_disable;
-
-	status = usb_add_function(c, &rndis->port.func);
-	if (status) {
-		kfree(rndis);
-fail:
-		rndis_exit();
-	}
-	return status;
-}
diff --git a/drivers/staging/ccg/gadget_chips.h b/drivers/staging/ccg/gadget_chips.h
deleted file mode 100644
index 0ccca58..0000000
--- a/drivers/staging/ccg/gadget_chips.h
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * USB device controllers have lots of quirks.  Use these macros in
- * gadget drivers or other code that needs to deal with them, and which
- * autoconfigures instead of using early binding to the hardware.
- *
- * This SHOULD eventually work like the ARM mach_is_*() stuff, driven by
- * some config file that gets updated as new hardware is supported.
- * (And avoiding all runtime comparisons in typical one-choice configs!)
- *
- * NOTE:  some of these controller drivers may not be available yet.
- * Some are available on 2.4 kernels; several are available, but not
- * yet pushed in the 2.6 mainline tree.
- */
-
-#ifndef __GADGET_CHIPS_H
-#define __GADGET_CHIPS_H
-
-/*
- * 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_bcm63xx(g)		(!strcmp("bcm63xx_udc", (g)->name))
-#define gadget_is_ci13xxx_msm(g)	(!strcmp("ci13xxx_msm", (g)->name))
-#define gadget_is_ci13xxx_pci(g)	(!strcmp("ci13xxx_pci", (g)->name))
-#define gadget_is_dummy(g)		(!strcmp("dummy_udc", (g)->name))
-#define gadget_is_dwc3(g)		(!strcmp("dwc3-gadget", (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_lpc32xx(g)		(!strcmp("lpc32xx_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
- * @gadget: the controller being driven
- *
- * Return a 2-digit BCD value associated with the peripheral controller,
- * suitable for use as part of a bcdDevice value, or a negative error code.
- *
- * NOTE:  this convention is purely optional, and has no meaning in terms of
- * any USB specification.  If you want to use a different convention in your
- * gadget driver firmware -- maybe a more formal revision ID -- feel free.
- *
- * Hosts see these bcdDevice numbers, and are allowed (but not encouraged!)
- * to change their behavior accordingly.  For example it might help avoiding
- * some chip bug.
- */
-static inline int usb_gadget_controller_number(struct usb_gadget *gadget)
-{
-	if (gadget_is_net2280(gadget))
-		return 0x01;
-	else if (gadget_is_dummy(gadget))
-		return 0x02;
-	else if (gadget_is_pxa(gadget))
-		return 0x03;
-	else if (gadget_is_goku(gadget))
-		return 0x06;
-	else if (gadget_is_omap(gadget))
-		return 0x08;
-	else if (gadget_is_pxa27x(gadget))
-		return 0x11;
-	else if (gadget_is_s3c2410(gadget))
-		return 0x12;
-	else if (gadget_is_at91(gadget))
-		return 0x13;
-	else if (gadget_is_imx(gadget))
-		return 0x14;
-	else if (gadget_is_musbhdrc(gadget))
-		return 0x16;
-	else if (gadget_is_atmel_usba(gadget))
-		return 0x18;
-	else if (gadget_is_fsl_usb2(gadget))
-		return 0x19;
-	else if (gadget_is_amd5536udc(gadget))
-		return 0x20;
-	else if (gadget_is_m66592(gadget))
-		return 0x21;
-	else if (gadget_is_fsl_qe(gadget))
-		return 0x22;
-	else if (gadget_is_ci13xxx_pci(gadget))
-		return 0x23;
-	else if (gadget_is_langwell(gadget))
-		return 0x24;
-	else if (gadget_is_r8a66597(gadget))
-		return 0x25;
-	else if (gadget_is_s3c_hsotg(gadget))
-		return 0x26;
-	else if (gadget_is_pch(gadget))
-		return 0x27;
-	else if (gadget_is_ci13xxx_msm(gadget))
-		return 0x28;
-	else if (gadget_is_renesas_usbhs(gadget))
-		return 0x29;
-	else if (gadget_is_s3c_hsudc(gadget))
-		return 0x30;
-	else if (gadget_is_net2272(gadget))
-		return 0x31;
-	else if (gadget_is_dwc3(gadget))
-		return 0x32;
-	else if (gadget_is_lpc32xx(gadget))
-		return 0x33;
-	else if (gadget_is_bcm63xx(gadget))
-		return 0x34;
-
-	return -ENOENT;
-}
-
-
-/**
- * gadget_supports_altsettings - return true if altsettings work
- * @gadget: the gadget in question
- */
-static inline bool gadget_supports_altsettings(struct usb_gadget *gadget)
-{
-	/* PXA 21x/25x/26x has no altsettings at all */
-	if (gadget_is_pxa(gadget))
-		return false;
-
-	/* PXA 27x and 3xx have *broken* altsetting support */
-	if (gadget_is_pxa27x(gadget))
-		return false;
-
-	/* Everything else is *presumably* fine ... */
-	return true;
-}
-
-#endif /* __GADGET_CHIPS_H */
diff --git a/drivers/staging/ccg/ndis.h b/drivers/staging/ccg/ndis.h
deleted file mode 100644
index a19f72d..0000000
--- a/drivers/staging/ccg/ndis.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * ndis.h
- *
- * ntddndis.h modified by Benedikt Spranger <b.spranger@pengutronix.de>
- *
- * Thanks to the cygwin development team,
- * espacially to Casper S. Hornstrup <chorns@users.sourceforge.net>
- *
- * THIS SOFTWARE IS NOT COPYRIGHTED
- *
- * This source code is offered for use in the public domain. You may
- * use, modify or distribute it freely.
- */
-
-#ifndef _LINUX_NDIS_H
-#define _LINUX_NDIS_H
-
-enum NDIS_DEVICE_POWER_STATE {
-	NdisDeviceStateUnspecified = 0,
-	NdisDeviceStateD0,
-	NdisDeviceStateD1,
-	NdisDeviceStateD2,
-	NdisDeviceStateD3,
-	NdisDeviceStateMaximum
-};
-
-struct NDIS_PM_WAKE_UP_CAPABILITIES {
-	enum NDIS_DEVICE_POWER_STATE  MinMagicPacketWakeUp;
-	enum NDIS_DEVICE_POWER_STATE  MinPatternWakeUp;
-	enum NDIS_DEVICE_POWER_STATE  MinLinkChangeWakeUp;
-};
-
-struct NDIS_PNP_CAPABILITIES {
-	__le32					Flags;
-	struct NDIS_PM_WAKE_UP_CAPABILITIES	WakeUpCapabilities;
-};
-
-struct NDIS_PM_PACKET_PATTERN {
-	__le32	Priority;
-	__le32	Reserved;
-	__le32	MaskSize;
-	__le32	PatternOffset;
-	__le32	PatternSize;
-	__le32	PatternFlags;
-};
-
-#endif /* _LINUX_NDIS_H */
diff --git a/drivers/staging/ccg/rndis.c b/drivers/staging/ccg/rndis.c
deleted file mode 100644
index d9297ee..0000000
--- a/drivers/staging/ccg/rndis.c
+++ /dev/null
@@ -1,1175 +0,0 @@
-/*
- * RNDIS MSG parser
- *
- * Authors:	Benedikt Spranger, Pengutronix
- *		Robert Schwebel, 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 software was originally developed in conformance with
- *		Microsoft's Remote NDIS Specification License Agreement.
- *
- * 03/12/2004 Kai-Uwe Bloem <linux-development@auerswald.de>
- *		Fixed message length bug in init_response
- *
- * 03/25/2004 Kai-Uwe Bloem <linux-development@auerswald.de>
- *		Fixed rndis_rm_hdr length bug.
- *
- * Copyright (C) 2004 by David Brownell
- *		updates to merge with Linux 2.6, better match RNDIS spec
- */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/list.h>
-#include <linux/proc_fs.h>
-#include <linux/slab.h>
-#include <linux/seq_file.h>
-#include <linux/netdevice.h>
-
-#include <asm/io.h>
-#include <asm/byteorder.h>
-#include <asm/unaligned.h>
-
-
-#undef	VERBOSE_DEBUG
-
-#include "rndis.h"
-
-
-/* The driver for your USB chip needs to support ep0 OUT to work with
- * RNDIS, plus all three CDC Ethernet endpoints (interrupt not optional).
- *
- * Windows hosts need an INF file like Documentation/usb/linux.inf
- * and will be happier if you provide the host_addr module parameter.
- */
-
-#if 0
-static int rndis_debug = 0;
-module_param (rndis_debug, int, 0);
-MODULE_PARM_DESC (rndis_debug, "enable debugging");
-#else
-#define rndis_debug		0
-#endif
-
-#define RNDIS_MAX_CONFIGS	1
-
-
-static rndis_params rndis_per_dev_params[RNDIS_MAX_CONFIGS];
-
-/* Driver Version */
-static const __le32 rndis_driver_version = cpu_to_le32(1);
-
-/* Function Prototypes */
-static rndis_resp_t *rndis_add_response(int configNr, u32 length);
-
-
-/* supported OIDs */
-static const u32 oid_supported_list[] =
-{
-	/* the general stuff */
-	RNDIS_OID_GEN_SUPPORTED_LIST,
-	RNDIS_OID_GEN_HARDWARE_STATUS,
-	RNDIS_OID_GEN_MEDIA_SUPPORTED,
-	RNDIS_OID_GEN_MEDIA_IN_USE,
-	RNDIS_OID_GEN_MAXIMUM_FRAME_SIZE,
-	RNDIS_OID_GEN_LINK_SPEED,
-	RNDIS_OID_GEN_TRANSMIT_BLOCK_SIZE,
-	RNDIS_OID_GEN_RECEIVE_BLOCK_SIZE,
-	RNDIS_OID_GEN_VENDOR_ID,
-	RNDIS_OID_GEN_VENDOR_DESCRIPTION,
-	RNDIS_OID_GEN_VENDOR_DRIVER_VERSION,
-	RNDIS_OID_GEN_CURRENT_PACKET_FILTER,
-	RNDIS_OID_GEN_MAXIMUM_TOTAL_SIZE,
-	RNDIS_OID_GEN_MEDIA_CONNECT_STATUS,
-	RNDIS_OID_GEN_PHYSICAL_MEDIUM,
-
-	/* the statistical stuff */
-	RNDIS_OID_GEN_XMIT_OK,
-	RNDIS_OID_GEN_RCV_OK,
-	RNDIS_OID_GEN_XMIT_ERROR,
-	RNDIS_OID_GEN_RCV_ERROR,
-	RNDIS_OID_GEN_RCV_NO_BUFFER,
-#ifdef	RNDIS_OPTIONAL_STATS
-	RNDIS_OID_GEN_DIRECTED_BYTES_XMIT,
-	RNDIS_OID_GEN_DIRECTED_FRAMES_XMIT,
-	RNDIS_OID_GEN_MULTICAST_BYTES_XMIT,
-	RNDIS_OID_GEN_MULTICAST_FRAMES_XMIT,
-	RNDIS_OID_GEN_BROADCAST_BYTES_XMIT,
-	RNDIS_OID_GEN_BROADCAST_FRAMES_XMIT,
-	RNDIS_OID_GEN_DIRECTED_BYTES_RCV,
-	RNDIS_OID_GEN_DIRECTED_FRAMES_RCV,
-	RNDIS_OID_GEN_MULTICAST_BYTES_RCV,
-	RNDIS_OID_GEN_MULTICAST_FRAMES_RCV,
-	RNDIS_OID_GEN_BROADCAST_BYTES_RCV,
-	RNDIS_OID_GEN_BROADCAST_FRAMES_RCV,
-	RNDIS_OID_GEN_RCV_CRC_ERROR,
-	RNDIS_OID_GEN_TRANSMIT_QUEUE_LENGTH,
-#endif	/* RNDIS_OPTIONAL_STATS */
-
-	/* mandatory 802.3 */
-	/* the general stuff */
-	RNDIS_OID_802_3_PERMANENT_ADDRESS,
-	RNDIS_OID_802_3_CURRENT_ADDRESS,
-	RNDIS_OID_802_3_MULTICAST_LIST,
-	RNDIS_OID_802_3_MAC_OPTIONS,
-	RNDIS_OID_802_3_MAXIMUM_LIST_SIZE,
-
-	/* the statistical stuff */
-	RNDIS_OID_802_3_RCV_ERROR_ALIGNMENT,
-	RNDIS_OID_802_3_XMIT_ONE_COLLISION,
-	RNDIS_OID_802_3_XMIT_MORE_COLLISIONS,
-#ifdef	RNDIS_OPTIONAL_STATS
-	RNDIS_OID_802_3_XMIT_DEFERRED,
-	RNDIS_OID_802_3_XMIT_MAX_COLLISIONS,
-	RNDIS_OID_802_3_RCV_OVERRUN,
-	RNDIS_OID_802_3_XMIT_UNDERRUN,
-	RNDIS_OID_802_3_XMIT_HEARTBEAT_FAILURE,
-	RNDIS_OID_802_3_XMIT_TIMES_CRS_LOST,
-	RNDIS_OID_802_3_XMIT_LATE_COLLISIONS,
-#endif	/* RNDIS_OPTIONAL_STATS */
-
-#ifdef	RNDIS_PM
-	/* PM and wakeup are "mandatory" for USB, but the RNDIS specs
-	 * don't say what they mean ... and the NDIS specs are often
-	 * confusing and/or ambiguous in this context.  (That is, more
-	 * so than their specs for the other OIDs.)
-	 *
-	 * FIXME someone who knows what these should do, please
-	 * implement them!
-	 */
-
-	/* power management */
-	OID_PNP_CAPABILITIES,
-	OID_PNP_QUERY_POWER,
-	OID_PNP_SET_POWER,
-
-#ifdef	RNDIS_WAKEUP
-	/* wake up host */
-	OID_PNP_ENABLE_WAKE_UP,
-	OID_PNP_ADD_WAKE_UP_PATTERN,
-	OID_PNP_REMOVE_WAKE_UP_PATTERN,
-#endif	/* RNDIS_WAKEUP */
-#endif	/* RNDIS_PM */
-};
-
-
-/* NDIS Functions */
-static int gen_ndis_query_resp(int configNr, u32 OID, u8 *buf,
-			       unsigned buf_len, rndis_resp_t *r)
-{
-	int retval = -ENOTSUPP;
-	u32 length = 4;	/* usually */
-	__le32 *outbuf;
-	int i, count;
-	rndis_query_cmplt_type *resp;
-	struct net_device *net;
-	struct rtnl_link_stats64 temp;
-	const struct rtnl_link_stats64 *stats;
-
-	if (!r) return -ENOMEM;
-	resp = (rndis_query_cmplt_type *)r->buf;
-
-	if (!resp) return -ENOMEM;
-
-	if (buf_len && rndis_debug > 1) {
-		pr_debug("query OID %08x value, len %d:\n", OID, buf_len);
-		for (i = 0; i < buf_len; i += 16) {
-			pr_debug("%03d: %08x %08x %08x %08x\n", i,
-				get_unaligned_le32(&buf[i]),
-				get_unaligned_le32(&buf[i + 4]),
-				get_unaligned_le32(&buf[i + 8]),
-				get_unaligned_le32(&buf[i + 12]));
-		}
-	}
-
-	/* response goes here, right after the header */
-	outbuf = (__le32 *)&resp[1];
-	resp->InformationBufferOffset = cpu_to_le32(16);
-
-	net = rndis_per_dev_params[configNr].dev;
-	stats = dev_get_stats(net, &temp);
-
-	switch (OID) {
-
-	/* general oids (table 4-1) */
-
-	/* mandatory */
-	case RNDIS_OID_GEN_SUPPORTED_LIST:
-		pr_debug("%s: RNDIS_OID_GEN_SUPPORTED_LIST\n", __func__);
-		length = sizeof(oid_supported_list);
-		count  = length / sizeof(u32);
-		for (i = 0; i < count; i++)
-			outbuf[i] = cpu_to_le32(oid_supported_list[i]);
-		retval = 0;
-		break;
-
-	/* mandatory */
-	case RNDIS_OID_GEN_HARDWARE_STATUS:
-		pr_debug("%s: RNDIS_OID_GEN_HARDWARE_STATUS\n", __func__);
-		/* Bogus question!
-		 * Hardware must be ready to receive high level protocols.
-		 * BTW:
-		 * reddite ergo quae sunt Caesaris Caesari
-		 * et quae sunt Dei Deo!
-		 */
-		*outbuf = cpu_to_le32(0);
-		retval = 0;
-		break;
-
-	/* mandatory */
-	case RNDIS_OID_GEN_MEDIA_SUPPORTED:
-		pr_debug("%s: RNDIS_OID_GEN_MEDIA_SUPPORTED\n", __func__);
-		*outbuf = cpu_to_le32(rndis_per_dev_params[configNr].medium);
-		retval = 0;
-		break;
-
-	/* mandatory */
-	case RNDIS_OID_GEN_MEDIA_IN_USE:
-		pr_debug("%s: RNDIS_OID_GEN_MEDIA_IN_USE\n", __func__);
-		/* one medium, one transport... (maybe you do it better) */
-		*outbuf = cpu_to_le32(rndis_per_dev_params[configNr].medium);
-		retval = 0;
-		break;
-
-	/* mandatory */
-	case RNDIS_OID_GEN_MAXIMUM_FRAME_SIZE:
-		pr_debug("%s: RNDIS_OID_GEN_MAXIMUM_FRAME_SIZE\n", __func__);
-		if (rndis_per_dev_params[configNr].dev) {
-			*outbuf = cpu_to_le32(
-				rndis_per_dev_params[configNr].dev->mtu);
-			retval = 0;
-		}
-		break;
-
-	/* mandatory */
-	case RNDIS_OID_GEN_LINK_SPEED:
-		if (rndis_debug > 1)
-			pr_debug("%s: RNDIS_OID_GEN_LINK_SPEED\n", __func__);
-		if (rndis_per_dev_params[configNr].media_state
-				== RNDIS_MEDIA_STATE_DISCONNECTED)
-			*outbuf = cpu_to_le32(0);
-		else
-			*outbuf = cpu_to_le32(
-				rndis_per_dev_params[configNr].speed);
-		retval = 0;
-		break;
-
-	/* mandatory */
-	case RNDIS_OID_GEN_TRANSMIT_BLOCK_SIZE:
-		pr_debug("%s: RNDIS_OID_GEN_TRANSMIT_BLOCK_SIZE\n", __func__);
-		if (rndis_per_dev_params[configNr].dev) {
-			*outbuf = cpu_to_le32(
-				rndis_per_dev_params[configNr].dev->mtu);
-			retval = 0;
-		}
-		break;
-
-	/* mandatory */
-	case RNDIS_OID_GEN_RECEIVE_BLOCK_SIZE:
-		pr_debug("%s: RNDIS_OID_GEN_RECEIVE_BLOCK_SIZE\n", __func__);
-		if (rndis_per_dev_params[configNr].dev) {
-			*outbuf = cpu_to_le32(
-				rndis_per_dev_params[configNr].dev->mtu);
-			retval = 0;
-		}
-		break;
-
-	/* mandatory */
-	case RNDIS_OID_GEN_VENDOR_ID:
-		pr_debug("%s: RNDIS_OID_GEN_VENDOR_ID\n", __func__);
-		*outbuf = cpu_to_le32(
-			rndis_per_dev_params[configNr].vendorID);
-		retval = 0;
-		break;
-
-	/* mandatory */
-	case RNDIS_OID_GEN_VENDOR_DESCRIPTION:
-		pr_debug("%s: RNDIS_OID_GEN_VENDOR_DESCRIPTION\n", __func__);
-		if (rndis_per_dev_params[configNr].vendorDescr) {
-			length = strlen(rndis_per_dev_params[configNr].
-					vendorDescr);
-			memcpy(outbuf,
-				rndis_per_dev_params[configNr].vendorDescr,
-				length);
-		} else {
-			outbuf[0] = 0;
-		}
-		retval = 0;
-		break;
-
-	case RNDIS_OID_GEN_VENDOR_DRIVER_VERSION:
-		pr_debug("%s: RNDIS_OID_GEN_VENDOR_DRIVER_VERSION\n", __func__);
-		/* Created as LE */
-		*outbuf = rndis_driver_version;
-		retval = 0;
-		break;
-
-	/* mandatory */
-	case RNDIS_OID_GEN_CURRENT_PACKET_FILTER:
-		pr_debug("%s: RNDIS_OID_GEN_CURRENT_PACKET_FILTER\n", __func__);
-		*outbuf = cpu_to_le32(*rndis_per_dev_params[configNr].filter);
-		retval = 0;
-		break;
-
-	/* mandatory */
-	case RNDIS_OID_GEN_MAXIMUM_TOTAL_SIZE:
-		pr_debug("%s: RNDIS_OID_GEN_MAXIMUM_TOTAL_SIZE\n", __func__);
-		*outbuf = cpu_to_le32(RNDIS_MAX_TOTAL_SIZE);
-		retval = 0;
-		break;
-
-	/* mandatory */
-	case RNDIS_OID_GEN_MEDIA_CONNECT_STATUS:
-		if (rndis_debug > 1)
-			pr_debug("%s: RNDIS_OID_GEN_MEDIA_CONNECT_STATUS\n", __func__);
-		*outbuf = cpu_to_le32(rndis_per_dev_params[configNr]
-						.media_state);
-		retval = 0;
-		break;
-
-	case RNDIS_OID_GEN_PHYSICAL_MEDIUM:
-		pr_debug("%s: RNDIS_OID_GEN_PHYSICAL_MEDIUM\n", __func__);
-		*outbuf = cpu_to_le32(0);
-		retval = 0;
-		break;
-
-	/* The RNDIS specification is incomplete/wrong.   Some versions
-	 * of MS-Windows expect OIDs that aren't specified there.  Other
-	 * versions emit undefined RNDIS messages. DOCUMENT ALL THESE!
-	 */
-	case RNDIS_OID_GEN_MAC_OPTIONS:		/* from WinME */
-		pr_debug("%s: RNDIS_OID_GEN_MAC_OPTIONS\n", __func__);
-		*outbuf = cpu_to_le32(
-			  RNDIS_MAC_OPTION_RECEIVE_SERIALIZED
-			| RNDIS_MAC_OPTION_FULL_DUPLEX);
-		retval = 0;
-		break;
-
-	/* statistics OIDs (table 4-2) */
-
-	/* mandatory */
-	case RNDIS_OID_GEN_XMIT_OK:
-		if (rndis_debug > 1)
-			pr_debug("%s: RNDIS_OID_GEN_XMIT_OK\n", __func__);
-		if (stats) {
-			*outbuf = cpu_to_le32(stats->tx_packets
-				- stats->tx_errors - stats->tx_dropped);
-			retval = 0;
-		}
-		break;
-
-	/* mandatory */
-	case RNDIS_OID_GEN_RCV_OK:
-		if (rndis_debug > 1)
-			pr_debug("%s: RNDIS_OID_GEN_RCV_OK\n", __func__);
-		if (stats) {
-			*outbuf = cpu_to_le32(stats->rx_packets
-				- stats->rx_errors - stats->rx_dropped);
-			retval = 0;
-		}
-		break;
-
-	/* mandatory */
-	case RNDIS_OID_GEN_XMIT_ERROR:
-		if (rndis_debug > 1)
-			pr_debug("%s: RNDIS_OID_GEN_XMIT_ERROR\n", __func__);
-		if (stats) {
-			*outbuf = cpu_to_le32(stats->tx_errors);
-			retval = 0;
-		}
-		break;
-
-	/* mandatory */
-	case RNDIS_OID_GEN_RCV_ERROR:
-		if (rndis_debug > 1)
-			pr_debug("%s: RNDIS_OID_GEN_RCV_ERROR\n", __func__);
-		if (stats) {
-			*outbuf = cpu_to_le32(stats->rx_errors);
-			retval = 0;
-		}
-		break;
-
-	/* mandatory */
-	case RNDIS_OID_GEN_RCV_NO_BUFFER:
-		pr_debug("%s: RNDIS_OID_GEN_RCV_NO_BUFFER\n", __func__);
-		if (stats) {
-			*outbuf = cpu_to_le32(stats->rx_dropped);
-			retval = 0;
-		}
-		break;
-
-	/* ieee802.3 OIDs (table 4-3) */
-
-	/* mandatory */
-	case RNDIS_OID_802_3_PERMANENT_ADDRESS:
-		pr_debug("%s: RNDIS_OID_802_3_PERMANENT_ADDRESS\n", __func__);
-		if (rndis_per_dev_params[configNr].dev) {
-			length = ETH_ALEN;
-			memcpy(outbuf,
-				rndis_per_dev_params[configNr].host_mac,
-				length);
-			retval = 0;
-		}
-		break;
-
-	/* mandatory */
-	case RNDIS_OID_802_3_CURRENT_ADDRESS:
-		pr_debug("%s: RNDIS_OID_802_3_CURRENT_ADDRESS\n", __func__);
-		if (rndis_per_dev_params[configNr].dev) {
-			length = ETH_ALEN;
-			memcpy(outbuf,
-				rndis_per_dev_params [configNr].host_mac,
-				length);
-			retval = 0;
-		}
-		break;
-
-	/* mandatory */
-	case RNDIS_OID_802_3_MULTICAST_LIST:
-		pr_debug("%s: RNDIS_OID_802_3_MULTICAST_LIST\n", __func__);
-		/* Multicast base address only */
-		*outbuf = cpu_to_le32(0xE0000000);
-		retval = 0;
-		break;
-
-	/* mandatory */
-	case RNDIS_OID_802_3_MAXIMUM_LIST_SIZE:
-		pr_debug("%s: RNDIS_OID_802_3_MAXIMUM_LIST_SIZE\n", __func__);
-		/* Multicast base address only */
-		*outbuf = cpu_to_le32(1);
-		retval = 0;
-		break;
-
-	case RNDIS_OID_802_3_MAC_OPTIONS:
-		pr_debug("%s: RNDIS_OID_802_3_MAC_OPTIONS\n", __func__);
-		*outbuf = cpu_to_le32(0);
-		retval = 0;
-		break;
-
-	/* ieee802.3 statistics OIDs (table 4-4) */
-
-	/* mandatory */
-	case RNDIS_OID_802_3_RCV_ERROR_ALIGNMENT:
-		pr_debug("%s: RNDIS_OID_802_3_RCV_ERROR_ALIGNMENT\n", __func__);
-		if (stats) {
-			*outbuf = cpu_to_le32(stats->rx_frame_errors);
-			retval = 0;
-		}
-		break;
-
-	/* mandatory */
-	case RNDIS_OID_802_3_XMIT_ONE_COLLISION:
-		pr_debug("%s: RNDIS_OID_802_3_XMIT_ONE_COLLISION\n", __func__);
-		*outbuf = cpu_to_le32(0);
-		retval = 0;
-		break;
-
-	/* mandatory */
-	case RNDIS_OID_802_3_XMIT_MORE_COLLISIONS:
-		pr_debug("%s: RNDIS_OID_802_3_XMIT_MORE_COLLISIONS\n", __func__);
-		*outbuf = cpu_to_le32(0);
-		retval = 0;
-		break;
-
-	default:
-		pr_warning("%s: query unknown OID 0x%08X\n",
-			 __func__, OID);
-	}
-	if (retval < 0)
-		length = 0;
-
-	resp->InformationBufferLength = cpu_to_le32(length);
-	r->length = length + sizeof(*resp);
-	resp->MessageLength = cpu_to_le32(r->length);
-	return retval;
-}
-
-static int gen_ndis_set_resp(u8 configNr, u32 OID, u8 *buf, u32 buf_len,
-			     rndis_resp_t *r)
-{
-	rndis_set_cmplt_type *resp;
-	int i, retval = -ENOTSUPP;
-	struct rndis_params *params;
-
-	if (!r)
-		return -ENOMEM;
-	resp = (rndis_set_cmplt_type *)r->buf;
-	if (!resp)
-		return -ENOMEM;
-
-	if (buf_len && rndis_debug > 1) {
-		pr_debug("set OID %08x value, len %d:\n", OID, buf_len);
-		for (i = 0; i < buf_len; i += 16) {
-			pr_debug("%03d: %08x %08x %08x %08x\n", i,
-				get_unaligned_le32(&buf[i]),
-				get_unaligned_le32(&buf[i + 4]),
-				get_unaligned_le32(&buf[i + 8]),
-				get_unaligned_le32(&buf[i + 12]));
-		}
-	}
-
-	params = &rndis_per_dev_params[configNr];
-	switch (OID) {
-	case RNDIS_OID_GEN_CURRENT_PACKET_FILTER:
-
-		/* these NDIS_PACKET_TYPE_* bitflags are shared with
-		 * cdc_filter; it's not RNDIS-specific
-		 * NDIS_PACKET_TYPE_x == USB_CDC_PACKET_TYPE_x for x in:
-		 *	PROMISCUOUS, DIRECTED,
-		 *	MULTICAST, ALL_MULTICAST, BROADCAST
-		 */
-		*params->filter = (u16)get_unaligned_le32(buf);
-		pr_debug("%s: RNDIS_OID_GEN_CURRENT_PACKET_FILTER %08x\n",
-			__func__, *params->filter);
-
-		/* this call has a significant side effect:  it's
-		 * what makes the packet flow start and stop, like
-		 * activating the CDC Ethernet altsetting.
-		 */
-		retval = 0;
-		if (*params->filter) {
-			params->state = RNDIS_DATA_INITIALIZED;
-			netif_carrier_on(params->dev);
-			if (netif_running(params->dev))
-				netif_wake_queue(params->dev);
-		} else {
-			params->state = RNDIS_INITIALIZED;
-			netif_carrier_off(params->dev);
-			netif_stop_queue(params->dev);
-		}
-		break;
-
-	case RNDIS_OID_802_3_MULTICAST_LIST:
-		/* I think we can ignore this */
-		pr_debug("%s: RNDIS_OID_802_3_MULTICAST_LIST\n", __func__);
-		retval = 0;
-		break;
-
-	default:
-		pr_warning("%s: set unknown OID 0x%08X, size %d\n",
-			 __func__, OID, buf_len);
-	}
-
-	return retval;
-}
-
-/*
- * Response Functions
- */
-
-static int rndis_init_response(int configNr, rndis_init_msg_type *buf)
-{
-	rndis_init_cmplt_type *resp;
-	rndis_resp_t *r;
-	struct rndis_params *params = rndis_per_dev_params + configNr;
-
-	if (!params->dev)
-		return -ENOTSUPP;
-
-	r = rndis_add_response(configNr, sizeof(rndis_init_cmplt_type));
-	if (!r)
-		return -ENOMEM;
-	resp = (rndis_init_cmplt_type *)r->buf;
-
-	resp->MessageType = cpu_to_le32(RNDIS_MSG_INIT_C);
-	resp->MessageLength = cpu_to_le32(52);
-	resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
-	resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS);
-	resp->MajorVersion = cpu_to_le32(RNDIS_MAJOR_VERSION);
-	resp->MinorVersion = cpu_to_le32(RNDIS_MINOR_VERSION);
-	resp->DeviceFlags = cpu_to_le32(RNDIS_DF_CONNECTIONLESS);
-	resp->Medium = cpu_to_le32(RNDIS_MEDIUM_802_3);
-	resp->MaxPacketsPerTransfer = cpu_to_le32(1);
-	resp->MaxTransferSize = cpu_to_le32(
-		  params->dev->mtu
-		+ sizeof(struct ethhdr)
-		+ sizeof(struct rndis_packet_msg_type)
-		+ 22);
-	resp->PacketAlignmentFactor = cpu_to_le32(0);
-	resp->AFListOffset = cpu_to_le32(0);
-	resp->AFListSize = cpu_to_le32(0);
-
-	params->resp_avail(params->v);
-	return 0;
-}
-
-static int rndis_query_response(int configNr, rndis_query_msg_type *buf)
-{
-	rndis_query_cmplt_type *resp;
-	rndis_resp_t *r;
-	struct rndis_params *params = rndis_per_dev_params + configNr;
-
-	/* pr_debug("%s: OID = %08X\n", __func__, cpu_to_le32(buf->OID)); */
-	if (!params->dev)
-		return -ENOTSUPP;
-
-	/*
-	 * we need more memory:
-	 * gen_ndis_query_resp expects enough space for
-	 * rndis_query_cmplt_type followed by data.
-	 * oid_supported_list is the largest data reply
-	 */
-	r = rndis_add_response(configNr,
-		sizeof(oid_supported_list) + sizeof(rndis_query_cmplt_type));
-	if (!r)
-		return -ENOMEM;
-	resp = (rndis_query_cmplt_type *)r->buf;
-
-	resp->MessageType = cpu_to_le32(RNDIS_MSG_QUERY_C);
-	resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
-
-	if (gen_ndis_query_resp(configNr, le32_to_cpu(buf->OID),
-			le32_to_cpu(buf->InformationBufferOffset)
-					+ 8 + (u8 *)buf,
-			le32_to_cpu(buf->InformationBufferLength),
-			r)) {
-		/* OID not supported */
-		resp->Status = cpu_to_le32(RNDIS_STATUS_NOT_SUPPORTED);
-		resp->MessageLength = cpu_to_le32(sizeof *resp);
-		resp->InformationBufferLength = cpu_to_le32(0);
-		resp->InformationBufferOffset = cpu_to_le32(0);
-	} else
-		resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS);
-
-	params->resp_avail(params->v);
-	return 0;
-}
-
-static int rndis_set_response(int configNr, rndis_set_msg_type *buf)
-{
-	u32 BufLength, BufOffset;
-	rndis_set_cmplt_type *resp;
-	rndis_resp_t *r;
-	struct rndis_params *params = rndis_per_dev_params + configNr;
-
-	r = rndis_add_response(configNr, sizeof(rndis_set_cmplt_type));
-	if (!r)
-		return -ENOMEM;
-	resp = (rndis_set_cmplt_type *)r->buf;
-
-	BufLength = le32_to_cpu(buf->InformationBufferLength);
-	BufOffset = le32_to_cpu(buf->InformationBufferOffset);
-
-#ifdef	VERBOSE_DEBUG
-	pr_debug("%s: Length: %d\n", __func__, BufLength);
-	pr_debug("%s: Offset: %d\n", __func__, BufOffset);
-	pr_debug("%s: InfoBuffer: ", __func__);
-
-	for (i = 0; i < BufLength; i++) {
-		pr_debug("%02x ", *(((u8 *) buf) + i + 8 + BufOffset));
-	}
-
-	pr_debug("\n");
-#endif
-
-	resp->MessageType = cpu_to_le32(RNDIS_MSG_SET_C);
-	resp->MessageLength = cpu_to_le32(16);
-	resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
-	if (gen_ndis_set_resp(configNr, le32_to_cpu(buf->OID),
-			((u8 *)buf) + 8 + BufOffset, BufLength, r))
-		resp->Status = cpu_to_le32(RNDIS_STATUS_NOT_SUPPORTED);
-	else
-		resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS);
-
-	params->resp_avail(params->v);
-	return 0;
-}
-
-static int rndis_reset_response(int configNr, rndis_reset_msg_type *buf)
-{
-	rndis_reset_cmplt_type *resp;
-	rndis_resp_t *r;
-	struct rndis_params *params = rndis_per_dev_params + configNr;
-
-	r = rndis_add_response(configNr, sizeof(rndis_reset_cmplt_type));
-	if (!r)
-		return -ENOMEM;
-	resp = (rndis_reset_cmplt_type *)r->buf;
-
-	resp->MessageType = cpu_to_le32(RNDIS_MSG_RESET_C);
-	resp->MessageLength = cpu_to_le32(16);
-	resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS);
-	/* resent information */
-	resp->AddressingReset = cpu_to_le32(1);
-
-	params->resp_avail(params->v);
-	return 0;
-}
-
-static int rndis_keepalive_response(int configNr,
-				    rndis_keepalive_msg_type *buf)
-{
-	rndis_keepalive_cmplt_type *resp;
-	rndis_resp_t *r;
-	struct rndis_params *params = rndis_per_dev_params + configNr;
-
-	/* host "should" check only in RNDIS_DATA_INITIALIZED state */
-
-	r = rndis_add_response(configNr, sizeof(rndis_keepalive_cmplt_type));
-	if (!r)
-		return -ENOMEM;
-	resp = (rndis_keepalive_cmplt_type *)r->buf;
-
-	resp->MessageType = cpu_to_le32(RNDIS_MSG_KEEPALIVE_C);
-	resp->MessageLength = cpu_to_le32(16);
-	resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
-	resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS);
-
-	params->resp_avail(params->v);
-	return 0;
-}
-
-
-/*
- * Device to Host Comunication
- */
-static int rndis_indicate_status_msg(int configNr, u32 status)
-{
-	rndis_indicate_status_msg_type *resp;
-	rndis_resp_t *r;
-	struct rndis_params *params = rndis_per_dev_params + configNr;
-
-	if (params->state == RNDIS_UNINITIALIZED)
-		return -ENOTSUPP;
-
-	r = rndis_add_response(configNr,
-				sizeof(rndis_indicate_status_msg_type));
-	if (!r)
-		return -ENOMEM;
-	resp = (rndis_indicate_status_msg_type *)r->buf;
-
-	resp->MessageType = cpu_to_le32(RNDIS_MSG_INDICATE);
-	resp->MessageLength = cpu_to_le32(20);
-	resp->Status = cpu_to_le32(status);
-	resp->StatusBufferLength = cpu_to_le32(0);
-	resp->StatusBufferOffset = cpu_to_le32(0);
-
-	params->resp_avail(params->v);
-	return 0;
-}
-
-int rndis_signal_connect(int configNr)
-{
-	rndis_per_dev_params[configNr].media_state
-			= RNDIS_MEDIA_STATE_CONNECTED;
-	return rndis_indicate_status_msg(configNr,
-					  RNDIS_STATUS_MEDIA_CONNECT);
-}
-
-int rndis_signal_disconnect(int configNr)
-{
-	rndis_per_dev_params[configNr].media_state
-			= RNDIS_MEDIA_STATE_DISCONNECTED;
-	return rndis_indicate_status_msg(configNr,
-					  RNDIS_STATUS_MEDIA_DISCONNECT);
-}
-
-void rndis_uninit(int configNr)
-{
-	u8 *buf;
-	u32 length;
-
-	if (configNr >= RNDIS_MAX_CONFIGS)
-		return;
-	rndis_per_dev_params[configNr].state = RNDIS_UNINITIALIZED;
-
-	/* drain the response queue */
-	while ((buf = rndis_get_next_response(configNr, &length)))
-		rndis_free_response(configNr, buf);
-}
-
-void rndis_set_host_mac(int configNr, const u8 *addr)
-{
-	rndis_per_dev_params[configNr].host_mac = addr;
-}
-
-/*
- * Message Parser
- */
-int rndis_msg_parser(u8 configNr, u8 *buf)
-{
-	u32 MsgType, MsgLength;
-	__le32 *tmp;
-	struct rndis_params *params;
-
-	if (!buf)
-		return -ENOMEM;
-
-	tmp = (__le32 *)buf;
-	MsgType   = get_unaligned_le32(tmp++);
-	MsgLength = get_unaligned_le32(tmp++);
-
-	if (configNr >= RNDIS_MAX_CONFIGS)
-		return -ENOTSUPP;
-	params = &rndis_per_dev_params[configNr];
-
-	/* NOTE: RNDIS is *EXTREMELY* chatty ... Windows constantly polls for
-	 * rx/tx statistics and link status, in addition to KEEPALIVE traffic
-	 * and normal HC level polling to see if there's any IN traffic.
-	 */
-
-	/* For USB: responses may take up to 10 seconds */
-	switch (MsgType) {
-	case RNDIS_MSG_INIT:
-		pr_debug("%s: RNDIS_MSG_INIT\n",
-			__func__);
-		params->state = RNDIS_INITIALIZED;
-		return rndis_init_response(configNr,
-					(rndis_init_msg_type *)buf);
-
-	case RNDIS_MSG_HALT:
-		pr_debug("%s: RNDIS_MSG_HALT\n",
-			__func__);
-		params->state = RNDIS_UNINITIALIZED;
-		if (params->dev) {
-			netif_carrier_off(params->dev);
-			netif_stop_queue(params->dev);
-		}
-		return 0;
-
-	case RNDIS_MSG_QUERY:
-		return rndis_query_response(configNr,
-					(rndis_query_msg_type *)buf);
-
-	case RNDIS_MSG_SET:
-		return rndis_set_response(configNr,
-					(rndis_set_msg_type *)buf);
-
-	case RNDIS_MSG_RESET:
-		pr_debug("%s: RNDIS_MSG_RESET\n",
-			__func__);
-		return rndis_reset_response(configNr,
-					(rndis_reset_msg_type *)buf);
-
-	case RNDIS_MSG_KEEPALIVE:
-		/* For USB: host does this every 5 seconds */
-		if (rndis_debug > 1)
-			pr_debug("%s: RNDIS_MSG_KEEPALIVE\n",
-				__func__);
-		return rndis_keepalive_response(configNr,
-						 (rndis_keepalive_msg_type *)
-						 buf);
-
-	default:
-		/* At least Windows XP emits some undefined RNDIS messages.
-		 * In one case those messages seemed to relate to the host
-		 * suspending itself.
-		 */
-		pr_warning("%s: unknown RNDIS message 0x%08X len %d\n",
-			__func__, MsgType, MsgLength);
-		print_hex_dump_bytes(__func__, DUMP_PREFIX_OFFSET,
-				     buf, MsgLength);
-		break;
-	}
-
-	return -ENOTSUPP;
-}
-
-int rndis_register(void (*resp_avail)(void *v), void *v)
-{
-	u8 i;
-
-	if (!resp_avail)
-		return -EINVAL;
-
-	for (i = 0; i < RNDIS_MAX_CONFIGS; i++) {
-		if (!rndis_per_dev_params[i].used) {
-			rndis_per_dev_params[i].used = 1;
-			rndis_per_dev_params[i].resp_avail = resp_avail;
-			rndis_per_dev_params[i].v = v;
-			pr_debug("%s: configNr = %d\n", __func__, i);
-			return i;
-		}
-	}
-	pr_debug("failed\n");
-
-	return -ENODEV;
-}
-
-void rndis_deregister(int configNr)
-{
-	pr_debug("%s:\n", __func__);
-
-	if (configNr >= RNDIS_MAX_CONFIGS) return;
-	rndis_per_dev_params[configNr].used = 0;
-}
-
-int rndis_set_param_dev(u8 configNr, struct net_device *dev, u16 *cdc_filter)
-{
-	pr_debug("%s:\n", __func__);
-	if (!dev)
-		return -EINVAL;
-	if (configNr >= RNDIS_MAX_CONFIGS) return -1;
-
-	rndis_per_dev_params[configNr].dev = dev;
-	rndis_per_dev_params[configNr].filter = cdc_filter;
-
-	return 0;
-}
-
-int rndis_set_param_vendor(u8 configNr, u32 vendorID, const char *vendorDescr)
-{
-	pr_debug("%s:\n", __func__);
-	if (!vendorDescr) return -1;
-	if (configNr >= RNDIS_MAX_CONFIGS) return -1;
-
-	rndis_per_dev_params[configNr].vendorID = vendorID;
-	rndis_per_dev_params[configNr].vendorDescr = vendorDescr;
-
-	return 0;
-}
-
-int rndis_set_param_medium(u8 configNr, u32 medium, u32 speed)
-{
-	pr_debug("%s: %u %u\n", __func__, medium, speed);
-	if (configNr >= RNDIS_MAX_CONFIGS) return -1;
-
-	rndis_per_dev_params[configNr].medium = medium;
-	rndis_per_dev_params[configNr].speed = speed;
-
-	return 0;
-}
-
-void rndis_add_hdr(struct sk_buff *skb)
-{
-	struct rndis_packet_msg_type *header;
-
-	if (!skb)
-		return;
-	header = (void *)skb_push(skb, sizeof(*header));
-	memset(header, 0, sizeof *header);
-	header->MessageType = cpu_to_le32(RNDIS_MSG_PACKET);
-	header->MessageLength = cpu_to_le32(skb->len);
-	header->DataOffset = cpu_to_le32(36);
-	header->DataLength = cpu_to_le32(skb->len - sizeof(*header));
-}
-
-void rndis_free_response(int configNr, u8 *buf)
-{
-	rndis_resp_t *r;
-	struct list_head *act, *tmp;
-
-	list_for_each_safe(act, tmp,
-			&(rndis_per_dev_params[configNr].resp_queue))
-	{
-		r = list_entry(act, rndis_resp_t, list);
-		if (r && r->buf == buf) {
-			list_del(&r->list);
-			kfree(r);
-		}
-	}
-}
-
-u8 *rndis_get_next_response(int configNr, u32 *length)
-{
-	rndis_resp_t *r;
-	struct list_head *act, *tmp;
-
-	if (!length) return NULL;
-
-	list_for_each_safe(act, tmp,
-			&(rndis_per_dev_params[configNr].resp_queue))
-	{
-		r = list_entry(act, rndis_resp_t, list);
-		if (!r->send) {
-			r->send = 1;
-			*length = r->length;
-			return r->buf;
-		}
-	}
-
-	return NULL;
-}
-
-static rndis_resp_t *rndis_add_response(int configNr, u32 length)
-{
-	rndis_resp_t *r;
-
-	/* NOTE: this gets copied into ether.c USB_BUFSIZ bytes ... */
-	r = kmalloc(sizeof(rndis_resp_t) + length, GFP_ATOMIC);
-	if (!r) return NULL;
-
-	r->buf = (u8 *)(r + 1);
-	r->length = length;
-	r->send = 0;
-
-	list_add_tail(&r->list,
-		&(rndis_per_dev_params[configNr].resp_queue));
-	return r;
-}
-
-int rndis_rm_hdr(struct gether *port,
-			struct sk_buff *skb,
-			struct sk_buff_head *list)
-{
-	/* tmp points to a struct rndis_packet_msg_type */
-	__le32 *tmp = (void *)skb->data;
-
-	/* MessageType, MessageLength */
-	if (cpu_to_le32(RNDIS_MSG_PACKET)
-			!= get_unaligned(tmp++)) {
-		dev_kfree_skb_any(skb);
-		return -EINVAL;
-	}
-	tmp++;
-
-	/* DataOffset, DataLength */
-	if (!skb_pull(skb, get_unaligned_le32(tmp++) + 8)) {
-		dev_kfree_skb_any(skb);
-		return -EOVERFLOW;
-	}
-	skb_trim(skb, get_unaligned_le32(tmp++));
-
-	skb_queue_tail(list, skb);
-	return 0;
-}
-
-#ifdef CONFIG_USB_GADGET_DEBUG_FILES
-
-static int rndis_proc_show(struct seq_file *m, void *v)
-{
-	rndis_params *param = m->private;
-
-	seq_printf(m,
-			 "Config Nr. %d\n"
-			 "used      : %s\n"
-			 "state     : %s\n"
-			 "medium    : 0x%08X\n"
-			 "speed     : %d\n"
-			 "cable     : %s\n"
-			 "vendor ID : 0x%08X\n"
-			 "vendor    : %s\n",
-			 param->confignr, (param->used) ? "y" : "n",
-			 ({ char *s = "?";
-			 switch (param->state) {
-			 case RNDIS_UNINITIALIZED:
-				s = "RNDIS_UNINITIALIZED"; break;
-			 case RNDIS_INITIALIZED:
-				s = "RNDIS_INITIALIZED"; break;
-			 case RNDIS_DATA_INITIALIZED:
-				s = "RNDIS_DATA_INITIALIZED"; break;
-			}; s; }),
-			 param->medium,
-			 (param->media_state) ? 0 : param->speed*100,
-			 (param->media_state) ? "disconnected" : "connected",
-			 param->vendorID, param->vendorDescr);
-	return 0;
-}
-
-static ssize_t rndis_proc_write(struct file *file, const char __user *buffer,
-				size_t count, loff_t *ppos)
-{
-	rndis_params *p = PDE(file_inode(file))->data;
-	u32 speed = 0;
-	int i, fl_speed = 0;
-
-	for (i = 0; i < count; i++) {
-		char c;
-		if (get_user(c, buffer))
-			return -EFAULT;
-		switch (c) {
-		case '0':
-		case '1':
-		case '2':
-		case '3':
-		case '4':
-		case '5':
-		case '6':
-		case '7':
-		case '8':
-		case '9':
-			fl_speed = 1;
-			speed = speed * 10 + c - '0';
-			break;
-		case 'C':
-		case 'c':
-			rndis_signal_connect(p->confignr);
-			break;
-		case 'D':
-		case 'd':
-			rndis_signal_disconnect(p->confignr);
-			break;
-		default:
-			if (fl_speed) p->speed = speed;
-			else pr_debug("%c is not valid\n", c);
-			break;
-		}
-
-		buffer++;
-	}
-
-	return count;
-}
-
-static int rndis_proc_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, rndis_proc_show, PDE(inode)->data);
-}
-
-static const struct file_operations rndis_proc_fops = {
-	.owner		= THIS_MODULE,
-	.open		= rndis_proc_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-	.write		= rndis_proc_write,
-};
-
-#define	NAME_TEMPLATE "driver/rndis-%03d"
-
-static struct proc_dir_entry *rndis_connect_state [RNDIS_MAX_CONFIGS];
-
-#endif /* CONFIG_USB_GADGET_DEBUG_FILES */
-
-
-int rndis_init(void)
-{
-	u8 i;
-
-	for (i = 0; i < RNDIS_MAX_CONFIGS; i++) {
-#ifdef	CONFIG_USB_GADGET_DEBUG_FILES
-		char name [20];
-
-		sprintf(name, NAME_TEMPLATE, i);
-		rndis_connect_state[i] = proc_create_data(name, 0660, NULL,
-					&rndis_proc_fops,
-					(void *)(rndis_per_dev_params + i));
-		if (!rndis_connect_state[i]) {
-			pr_debug("%s: remove entries", __func__);
-			while (i) {
-				sprintf(name, NAME_TEMPLATE, --i);
-				remove_proc_entry(name, NULL);
-			}
-			pr_debug("\n");
-			return -EIO;
-		}
-#endif
-		rndis_per_dev_params[i].confignr = i;
-		rndis_per_dev_params[i].used = 0;
-		rndis_per_dev_params[i].state = RNDIS_UNINITIALIZED;
-		rndis_per_dev_params[i].media_state
-				= RNDIS_MEDIA_STATE_DISCONNECTED;
-		INIT_LIST_HEAD(&(rndis_per_dev_params[i].resp_queue));
-	}
-
-	return 0;
-}
-
-void rndis_exit(void)
-{
-#ifdef CONFIG_USB_GADGET_DEBUG_FILES
-	u8 i;
-	char name[20];
-
-	for (i = 0; i < RNDIS_MAX_CONFIGS; i++) {
-		sprintf(name, NAME_TEMPLATE, i);
-		remove_proc_entry(name, NULL);
-	}
-#endif
-}
diff --git a/drivers/staging/ccg/rndis.h b/drivers/staging/ccg/rndis.h
deleted file mode 100644
index 0647f2f..0000000
--- a/drivers/staging/ccg/rndis.h
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * RNDIS	Definitions for Remote NDIS
- *
- * Authors:	Benedikt Spranger, Pengutronix
- *		Robert Schwebel, 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 software was originally developed in conformance with
- *		Microsoft's Remote NDIS Specification License Agreement.
- */
-
-#ifndef _LINUX_RNDIS_H
-#define _LINUX_RNDIS_H
-
-#include <linux/rndis.h>
-#include "ndis.h"
-
-#define RNDIS_MAXIMUM_FRAME_SIZE	1518
-#define RNDIS_MAX_TOTAL_SIZE		1558
-
-typedef struct rndis_init_msg_type
-{
-	__le32	MessageType;
-	__le32	MessageLength;
-	__le32	RequestID;
-	__le32	MajorVersion;
-	__le32	MinorVersion;
-	__le32	MaxTransferSize;
-} rndis_init_msg_type;
-
-typedef struct rndis_init_cmplt_type
-{
-	__le32	MessageType;
-	__le32	MessageLength;
-	__le32	RequestID;
-	__le32	Status;
-	__le32	MajorVersion;
-	__le32	MinorVersion;
-	__le32	DeviceFlags;
-	__le32	Medium;
-	__le32	MaxPacketsPerTransfer;
-	__le32	MaxTransferSize;
-	__le32	PacketAlignmentFactor;
-	__le32	AFListOffset;
-	__le32	AFListSize;
-} rndis_init_cmplt_type;
-
-typedef struct rndis_halt_msg_type
-{
-	__le32	MessageType;
-	__le32	MessageLength;
-	__le32	RequestID;
-} rndis_halt_msg_type;
-
-typedef struct rndis_query_msg_type
-{
-	__le32	MessageType;
-	__le32	MessageLength;
-	__le32	RequestID;
-	__le32	OID;
-	__le32	InformationBufferLength;
-	__le32	InformationBufferOffset;
-	__le32	DeviceVcHandle;
-} rndis_query_msg_type;
-
-typedef struct rndis_query_cmplt_type
-{
-	__le32	MessageType;
-	__le32	MessageLength;
-	__le32	RequestID;
-	__le32	Status;
-	__le32	InformationBufferLength;
-	__le32	InformationBufferOffset;
-} rndis_query_cmplt_type;
-
-typedef struct rndis_set_msg_type
-{
-	__le32	MessageType;
-	__le32	MessageLength;
-	__le32	RequestID;
-	__le32	OID;
-	__le32	InformationBufferLength;
-	__le32	InformationBufferOffset;
-	__le32	DeviceVcHandle;
-} rndis_set_msg_type;
-
-typedef struct rndis_set_cmplt_type
-{
-	__le32	MessageType;
-	__le32	MessageLength;
-	__le32	RequestID;
-	__le32	Status;
-} rndis_set_cmplt_type;
-
-typedef struct rndis_reset_msg_type
-{
-	__le32	MessageType;
-	__le32	MessageLength;
-	__le32	Reserved;
-} rndis_reset_msg_type;
-
-typedef struct rndis_reset_cmplt_type
-{
-	__le32	MessageType;
-	__le32	MessageLength;
-	__le32	Status;
-	__le32	AddressingReset;
-} rndis_reset_cmplt_type;
-
-typedef struct rndis_indicate_status_msg_type
-{
-	__le32	MessageType;
-	__le32	MessageLength;
-	__le32	Status;
-	__le32	StatusBufferLength;
-	__le32	StatusBufferOffset;
-} rndis_indicate_status_msg_type;
-
-typedef struct rndis_keepalive_msg_type
-{
-	__le32	MessageType;
-	__le32	MessageLength;
-	__le32	RequestID;
-} rndis_keepalive_msg_type;
-
-typedef struct rndis_keepalive_cmplt_type
-{
-	__le32	MessageType;
-	__le32	MessageLength;
-	__le32	RequestID;
-	__le32	Status;
-} rndis_keepalive_cmplt_type;
-
-struct rndis_packet_msg_type
-{
-	__le32	MessageType;
-	__le32	MessageLength;
-	__le32	DataOffset;
-	__le32	DataLength;
-	__le32	OOBDataOffset;
-	__le32	OOBDataLength;
-	__le32	NumOOBDataElements;
-	__le32	PerPacketInfoOffset;
-	__le32	PerPacketInfoLength;
-	__le32	VcHandle;
-	__le32	Reserved;
-} __attribute__ ((packed));
-
-struct rndis_config_parameter
-{
-	__le32	ParameterNameOffset;
-	__le32	ParameterNameLength;
-	__le32	ParameterType;
-	__le32	ParameterValueOffset;
-	__le32	ParameterValueLength;
-};
-
-/* implementation specific */
-enum rndis_state
-{
-	RNDIS_UNINITIALIZED,
-	RNDIS_INITIALIZED,
-	RNDIS_DATA_INITIALIZED,
-};
-
-typedef struct rndis_resp_t
-{
-	struct list_head	list;
-	u8			*buf;
-	u32			length;
-	int			send;
-} rndis_resp_t;
-
-typedef struct rndis_params
-{
-	u8			confignr;
-	u8			used;
-	u16			saved_filter;
-	enum rndis_state	state;
-	u32			medium;
-	u32			speed;
-	u32			media_state;
-
-	const u8		*host_mac;
-	u16			*filter;
-	struct net_device	*dev;
-
-	u32			vendorID;
-	const char		*vendorDescr;
-	void			(*resp_avail)(void *v);
-	void			*v;
-	struct list_head	resp_queue;
-} rndis_params;
-
-/* RNDIS Message parser and other useless functions */
-int  rndis_msg_parser (u8 configNr, u8 *buf);
-int  rndis_register(void (*resp_avail)(void *v), void *v);
-void rndis_deregister (int configNr);
-int  rndis_set_param_dev (u8 configNr, struct net_device *dev,
-			 u16 *cdc_filter);
-int  rndis_set_param_vendor (u8 configNr, u32 vendorID,
-			    const char *vendorDescr);
-int  rndis_set_param_medium (u8 configNr, u32 medium, u32 speed);
-void rndis_add_hdr (struct sk_buff *skb);
-int rndis_rm_hdr(struct gether *port, struct sk_buff *skb,
-			struct sk_buff_head *list);
-u8   *rndis_get_next_response (int configNr, u32 *length);
-void rndis_free_response (int configNr, u8 *buf);
-
-void rndis_uninit (int configNr);
-int  rndis_signal_connect (int configNr);
-int  rndis_signal_disconnect (int configNr);
-int  rndis_state (int configNr);
-extern void rndis_set_host_mac (int configNr, const u8 *addr);
-
-int rndis_init(void);
-void rndis_exit (void);
-
-#endif  /* _LINUX_RNDIS_H */
diff --git a/drivers/staging/ccg/storage_common.c b/drivers/staging/ccg/storage_common.c
deleted file mode 100644
index abb01ac..0000000
--- a/drivers/staging/ccg/storage_common.c
+++ /dev/null
@@ -1,893 +0,0 @@
-/*
- * storage_common.c -- Common definitions for mass storage functionality
- *
- * Copyright (C) 2003-2008 Alan Stern
- * Copyeight (C) 2009 Samsung Electronics
- * Author: Michal Nazarewicz (mina86@mina86.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 file requires the following identifiers used in USB strings to
- * be defined (each of type pointer to char):
- *  - fsg_string_manufacturer -- name of the manufacturer
- *  - fsg_string_product      -- name of the product
- *  - fsg_string_config       -- name of the configuration
- *  - fsg_string_interface    -- name of the interface
- * The first four are only needed when FSG_DESCRIPTORS_DEVICE_STRINGS
- * macro is defined prior to including this file.
- */
-
-/*
- * When FSG_NO_INTR_EP is defined fsg_fs_intr_in_desc and
- * fsg_hs_intr_in_desc objects as well as
- * FSG_FS_FUNCTION_PRE_EP_ENTRIES and FSG_HS_FUNCTION_PRE_EP_ENTRIES
- * macros are not defined.
- *
- * When FSG_NO_DEVICE_STRINGS is defined FSG_STRING_MANUFACTURER,
- * FSG_STRING_PRODUCT, FSG_STRING_SERIAL and FSG_STRING_CONFIG are not
- * defined (as well as corresponding entries in string tables are
- * missing) and FSG_STRING_INTERFACE has value of zero.
- *
- * When FSG_NO_OTG is defined fsg_otg_desc won't be defined.
- */
-
-/*
- * When USB_GADGET_DEBUG_FILES is defined the module param num_buffers
- * sets the number of pipeline buffers (length of the fsg_buffhd array).
- * The valid range of num_buffers is: num >= 2 && num <= 4.
- */
-
-
-#include <linux/usb/storage.h>
-#include <scsi/scsi.h>
-#include <asm/unaligned.h>
-
-
-/*
- * Thanks to NetChip Technologies for donating this product ID.
- *
- * DO NOT REUSE THESE IDs with any other driver!!  Ever!!
- * Instead:  allocate your own, using normal USB-IF procedures.
- */
-#define FSG_VENDOR_ID	0x0525	/* NetChip */
-#define FSG_PRODUCT_ID	0xa4a5	/* Linux-USB File-backed Storage Gadget */
-
-
-/*-------------------------------------------------------------------------*/
-
-
-#ifndef DEBUG
-#undef VERBOSE_DEBUG
-#undef DUMP_MSGS
-#endif /* !DEBUG */
-
-#ifdef VERBOSE_DEBUG
-#define VLDBG	LDBG
-#else
-#define VLDBG(lun, fmt, args...) do { } while (0)
-#endif /* VERBOSE_DEBUG */
-
-#define LDBG(lun, fmt, args...)   dev_dbg (&(lun)->dev, fmt, ## args)
-#define LERROR(lun, fmt, args...) dev_err (&(lun)->dev, fmt, ## args)
-#define LWARN(lun, fmt, args...)  dev_warn(&(lun)->dev, fmt, ## args)
-#define LINFO(lun, fmt, args...)  dev_info(&(lun)->dev, fmt, ## args)
-
-/*
- * Keep those macros in sync with those in
- * include/linux/usb/composite.h or else GCC will complain.  If they
- * are identical (the same names of arguments, white spaces in the
- * same places) GCC will allow redefinition otherwise (even if some
- * white space is removed or added) warning will be issued.
- *
- * Those macros are needed here because File Storage Gadget does not
- * include the composite.h header.  For composite gadgets those macros
- * are redundant since composite.h is included any way.
- *
- * One could check whether those macros are already defined (which
- * would indicate composite.h had been included) or not (which would
- * indicate we were in FSG) but this is not done because a warning is
- * desired if definitions here differ from the ones in composite.h.
- *
- * We want the definitions to match and be the same in File Storage
- * Gadget as well as Mass Storage Function (and so composite gadgets
- * using MSF).  If someone changes them in composite.h it will produce
- * a warning in this file when building MSF.
- */
-#define DBG(d, fmt, args...)     dev_dbg(&(d)->gadget->dev , fmt , ## args)
-#define VDBG(d, fmt, args...)    dev_vdbg(&(d)->gadget->dev , fmt , ## args)
-#define ERROR(d, fmt, args...)   dev_err(&(d)->gadget->dev , fmt , ## args)
-#define WARNING(d, fmt, args...) dev_warn(&(d)->gadget->dev , fmt , ## args)
-#define INFO(d, fmt, args...)    dev_info(&(d)->gadget->dev , fmt , ## args)
-
-
-
-#ifdef DUMP_MSGS
-
-#  define dump_msg(fsg, /* const char * */ label,			\
-		   /* const u8 * */ buf, /* unsigned */ length) do {	\
-	if (length < 512) {						\
-		DBG(fsg, "%s, length %u:\n", label, length);		\
-		print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET,	\
-			       16, 1, buf, length, 0);			\
-	}								\
-} while (0)
-
-#  define dump_cdb(fsg) do { } while (0)
-
-#else
-
-#  define dump_msg(fsg, /* const char * */ label, \
-		   /* const u8 * */ buf, /* unsigned */ length) do { } while (0)
-
-#  ifdef VERBOSE_DEBUG
-
-#    define dump_cdb(fsg)						\
-	print_hex_dump(KERN_DEBUG, "SCSI CDB: ", DUMP_PREFIX_NONE,	\
-		       16, 1, (fsg)->cmnd, (fsg)->cmnd_size, 0)		\
-
-#  else
-
-#    define dump_cdb(fsg) do { } while (0)
-
-#  endif /* VERBOSE_DEBUG */
-
-#endif /* DUMP_MSGS */
-
-/*-------------------------------------------------------------------------*/
-
-/* CBI Interrupt data structure */
-struct interrupt_data {
-	u8	bType;
-	u8	bValue;
-};
-
-#define CBI_INTERRUPT_DATA_LEN		2
-
-/* CBI Accept Device-Specific Command request */
-#define USB_CBI_ADSC_REQUEST		0x00
-
-
-/* Length of a SCSI Command Data Block */
-#define MAX_COMMAND_SIZE	16
-
-/* SCSI Sense Key/Additional Sense Code/ASC Qualifier values */
-#define SS_NO_SENSE				0
-#define SS_COMMUNICATION_FAILURE		0x040800
-#define SS_INVALID_COMMAND			0x052000
-#define SS_INVALID_FIELD_IN_CDB			0x052400
-#define SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE	0x052100
-#define SS_LOGICAL_UNIT_NOT_SUPPORTED		0x052500
-#define SS_MEDIUM_NOT_PRESENT			0x023a00
-#define SS_MEDIUM_REMOVAL_PREVENTED		0x055302
-#define SS_NOT_READY_TO_READY_TRANSITION	0x062800
-#define SS_RESET_OCCURRED			0x062900
-#define SS_SAVING_PARAMETERS_NOT_SUPPORTED	0x053900
-#define SS_UNRECOVERED_READ_ERROR		0x031100
-#define SS_WRITE_ERROR				0x030c02
-#define SS_WRITE_PROTECTED			0x072700
-
-#define SK(x)		((u8) ((x) >> 16))	/* Sense Key byte, etc. */
-#define ASC(x)		((u8) ((x) >> 8))
-#define ASCQ(x)		((u8) (x))
-
-
-/*-------------------------------------------------------------------------*/
-
-
-struct fsg_lun {
-	struct file	*filp;
-	loff_t		file_length;
-	loff_t		num_sectors;
-
-	unsigned int	initially_ro:1;
-	unsigned int	ro:1;
-	unsigned int	removable:1;
-	unsigned int	cdrom:1;
-	unsigned int	prevent_medium_removal:1;
-	unsigned int	registered:1;
-	unsigned int	info_valid:1;
-	unsigned int	nofua:1;
-
-	u32		sense_data;
-	u32		sense_data_info;
-	u32		unit_attention_data;
-
-	unsigned int	blkbits;	/* Bits of logical block size of bound block device */
-	unsigned int	blksize;	/* logical block size of bound block device */
-	struct device	dev;
-};
-
-#define fsg_lun_is_open(curlun)	((curlun)->filp != NULL)
-
-static struct fsg_lun *fsg_lun_from_dev(struct device *dev)
-{
-	return container_of(dev, struct fsg_lun, dev);
-}
-
-
-/* Big enough to hold our biggest descriptor */
-#define EP0_BUFSIZE	256
-#define DELAYED_STATUS	(EP0_BUFSIZE + 999)	/* An impossibly large value */
-
-#ifdef CONFIG_USB_GADGET_DEBUG_FILES
-
-static unsigned int fsg_num_buffers = CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS;
-module_param_named(num_buffers, fsg_num_buffers, uint, S_IRUGO);
-MODULE_PARM_DESC(num_buffers, "Number of pipeline buffers");
-
-#else
-
-/*
- * Number of buffers we will use.
- * 2 is usually enough for good buffering pipeline
- */
-#define fsg_num_buffers	CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS
-
-#endif /* CONFIG_USB_DEBUG */
-
-/* check if fsg_num_buffers is within a valid range */
-static inline int fsg_num_buffers_validate(void)
-{
-	if (fsg_num_buffers >= 2 && fsg_num_buffers <= 4)
-		return 0;
-	pr_err("fsg_num_buffers %u is out of range (%d to %d)\n",
-	       fsg_num_buffers, 2 ,4);
-	return -EINVAL;
-}
-
-/* Default size of buffer length. */
-#define FSG_BUFLEN	((u32)16384)
-
-/* Maximal number of LUNs supported in mass storage function */
-#define FSG_MAX_LUNS	8
-
-enum fsg_buffer_state {
-	BUF_STATE_EMPTY = 0,
-	BUF_STATE_FULL,
-	BUF_STATE_BUSY
-};
-
-struct fsg_buffhd {
-	void				*buf;
-	enum fsg_buffer_state		state;
-	struct fsg_buffhd		*next;
-
-	/*
-	 * The NetChip 2280 is faster, and handles some protocol faults
-	 * better, if we don't submit any short bulk-out read requests.
-	 * So we will record the intended request length here.
-	 */
-	unsigned int			bulk_out_intended_length;
-
-	struct usb_request		*inreq;
-	int				inreq_busy;
-	struct usb_request		*outreq;
-	int				outreq_busy;
-};
-
-enum fsg_state {
-	/* This one isn't used anywhere */
-	FSG_STATE_COMMAND_PHASE = -10,
-	FSG_STATE_DATA_PHASE,
-	FSG_STATE_STATUS_PHASE,
-
-	FSG_STATE_IDLE = 0,
-	FSG_STATE_ABORT_BULK_OUT,
-	FSG_STATE_RESET,
-	FSG_STATE_INTERFACE_CHANGE,
-	FSG_STATE_CONFIG_CHANGE,
-	FSG_STATE_DISCONNECT,
-	FSG_STATE_EXIT,
-	FSG_STATE_TERMINATED
-};
-
-enum data_direction {
-	DATA_DIR_UNKNOWN = 0,
-	DATA_DIR_FROM_HOST,
-	DATA_DIR_TO_HOST,
-	DATA_DIR_NONE
-};
-
-
-/*-------------------------------------------------------------------------*/
-
-
-static inline u32 get_unaligned_be24(u8 *buf)
-{
-	return 0xffffff & (u32) get_unaligned_be32(buf - 1);
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-
-enum {
-#ifndef FSG_NO_DEVICE_STRINGS
-	FSG_STRING_MANUFACTURER	= 1,
-	FSG_STRING_PRODUCT,
-	FSG_STRING_SERIAL,
-	FSG_STRING_CONFIG,
-#endif
-	FSG_STRING_INTERFACE
-};
-
-
-#ifndef FSG_NO_OTG
-static struct usb_otg_descriptor
-fsg_otg_desc = {
-	.bLength =		sizeof fsg_otg_desc,
-	.bDescriptorType =	USB_DT_OTG,
-
-	.bmAttributes =		USB_OTG_SRP,
-};
-#endif
-
-/* There is only one interface. */
-
-static struct usb_interface_descriptor
-fsg_intf_desc = {
-	.bLength =		sizeof fsg_intf_desc,
-	.bDescriptorType =	USB_DT_INTERFACE,
-
-	.bNumEndpoints =	2,		/* Adjusted during fsg_bind() */
-	.bInterfaceClass =	USB_CLASS_MASS_STORAGE,
-	.bInterfaceSubClass =	USB_SC_SCSI,	/* Adjusted during fsg_bind() */
-	.bInterfaceProtocol =	USB_PR_BULK,	/* Adjusted during fsg_bind() */
-	.iInterface =		FSG_STRING_INTERFACE,
-};
-
-/*
- * Three full-speed endpoint descriptors: bulk-in, bulk-out, and
- * interrupt-in.
- */
-
-static struct usb_endpoint_descriptor
-fsg_fs_bulk_in_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-
-	.bEndpointAddress =	USB_DIR_IN,
-	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	/* wMaxPacketSize set by autoconfiguration */
-};
-
-static struct usb_endpoint_descriptor
-fsg_fs_bulk_out_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-
-	.bEndpointAddress =	USB_DIR_OUT,
-	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	/* wMaxPacketSize set by autoconfiguration */
-};
-
-#ifndef FSG_NO_INTR_EP
-
-static struct usb_endpoint_descriptor
-fsg_fs_intr_in_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-
-	.bEndpointAddress =	USB_DIR_IN,
-	.bmAttributes =		USB_ENDPOINT_XFER_INT,
-	.wMaxPacketSize =	cpu_to_le16(2),
-	.bInterval =		32,	/* frames -> 32 ms */
-};
-
-#ifndef FSG_NO_OTG
-#  define FSG_FS_FUNCTION_PRE_EP_ENTRIES	2
-#else
-#  define FSG_FS_FUNCTION_PRE_EP_ENTRIES	1
-#endif
-
-#endif
-
-static struct usb_descriptor_header *fsg_fs_function[] = {
-#ifndef FSG_NO_OTG
-	(struct usb_descriptor_header *) &fsg_otg_desc,
-#endif
-	(struct usb_descriptor_header *) &fsg_intf_desc,
-	(struct usb_descriptor_header *) &fsg_fs_bulk_in_desc,
-	(struct usb_descriptor_header *) &fsg_fs_bulk_out_desc,
-#ifndef FSG_NO_INTR_EP
-	(struct usb_descriptor_header *) &fsg_fs_intr_in_desc,
-#endif
-	NULL,
-};
-
-
-/*
- * USB 2.0 devices need to expose both high speed and full speed
- * descriptors, unless they only run at full speed.
- *
- * That means alternate endpoint descriptors (bigger packets)
- * and a "device qualifier" ... plus more construction options
- * for the configuration descriptor.
- */
-static struct usb_endpoint_descriptor
-fsg_hs_bulk_in_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-
-	/* bEndpointAddress copied from fs_bulk_in_desc during fsg_bind() */
-	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	cpu_to_le16(512),
-};
-
-static struct usb_endpoint_descriptor
-fsg_hs_bulk_out_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-
-	/* bEndpointAddress copied from fs_bulk_out_desc during fsg_bind() */
-	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	cpu_to_le16(512),
-	.bInterval =		1,	/* NAK every 1 uframe */
-};
-
-#ifndef FSG_NO_INTR_EP
-
-static struct usb_endpoint_descriptor
-fsg_hs_intr_in_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-
-	/* bEndpointAddress copied from fs_intr_in_desc during fsg_bind() */
-	.bmAttributes =		USB_ENDPOINT_XFER_INT,
-	.wMaxPacketSize =	cpu_to_le16(2),
-	.bInterval =		9,	/* 2**(9-1) = 256 uframes -> 32 ms */
-};
-
-#ifndef FSG_NO_OTG
-#  define FSG_HS_FUNCTION_PRE_EP_ENTRIES	2
-#else
-#  define FSG_HS_FUNCTION_PRE_EP_ENTRIES	1
-#endif
-
-#endif
-
-static struct usb_descriptor_header *fsg_hs_function[] = {
-#ifndef FSG_NO_OTG
-	(struct usb_descriptor_header *) &fsg_otg_desc,
-#endif
-	(struct usb_descriptor_header *) &fsg_intf_desc,
-	(struct usb_descriptor_header *) &fsg_hs_bulk_in_desc,
-	(struct usb_descriptor_header *) &fsg_hs_bulk_out_desc,
-#ifndef FSG_NO_INTR_EP
-	(struct usb_descriptor_header *) &fsg_hs_intr_in_desc,
-#endif
-	NULL,
-};
-
-static struct usb_endpoint_descriptor
-fsg_ss_bulk_in_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-
-	/* bEndpointAddress copied from fs_bulk_in_desc during fsg_bind() */
-	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	cpu_to_le16(1024),
-};
-
-static struct usb_ss_ep_comp_descriptor fsg_ss_bulk_in_comp_desc = {
-	.bLength =		sizeof(fsg_ss_bulk_in_comp_desc),
-	.bDescriptorType =	USB_DT_SS_ENDPOINT_COMP,
-
-	/*.bMaxBurst =		DYNAMIC, */
-};
-
-static struct usb_endpoint_descriptor
-fsg_ss_bulk_out_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-
-	/* bEndpointAddress copied from fs_bulk_out_desc during fsg_bind() */
-	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	cpu_to_le16(1024),
-};
-
-static struct usb_ss_ep_comp_descriptor fsg_ss_bulk_out_comp_desc = {
-	.bLength =		sizeof(fsg_ss_bulk_in_comp_desc),
-	.bDescriptorType =	USB_DT_SS_ENDPOINT_COMP,
-
-	/*.bMaxBurst =		DYNAMIC, */
-};
-
-#ifndef FSG_NO_INTR_EP
-
-static struct usb_endpoint_descriptor
-fsg_ss_intr_in_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-
-	/* bEndpointAddress copied from fs_intr_in_desc during fsg_bind() */
-	.bmAttributes =		USB_ENDPOINT_XFER_INT,
-	.wMaxPacketSize =	cpu_to_le16(2),
-	.bInterval =		9,	/* 2**(9-1) = 256 uframes -> 32 ms */
-};
-
-static struct usb_ss_ep_comp_descriptor fsg_ss_intr_in_comp_desc = {
-	.bLength =		sizeof(fsg_ss_bulk_in_comp_desc),
-	.bDescriptorType =	USB_DT_SS_ENDPOINT_COMP,
-
-	.wBytesPerInterval =	cpu_to_le16(2),
-};
-
-#ifndef FSG_NO_OTG
-#  define FSG_SS_FUNCTION_PRE_EP_ENTRIES	2
-#else
-#  define FSG_SS_FUNCTION_PRE_EP_ENTRIES	1
-#endif
-
-#endif
-
-static __maybe_unused struct usb_ext_cap_descriptor fsg_ext_cap_desc = {
-	.bLength =		USB_DT_USB_EXT_CAP_SIZE,
-	.bDescriptorType =	USB_DT_DEVICE_CAPABILITY,
-	.bDevCapabilityType =	USB_CAP_TYPE_EXT,
-
-	.bmAttributes =		cpu_to_le32(USB_LPM_SUPPORT),
-};
-
-static __maybe_unused struct usb_ss_cap_descriptor fsg_ss_cap_desc = {
-	.bLength =		USB_DT_USB_SS_CAP_SIZE,
-	.bDescriptorType =	USB_DT_DEVICE_CAPABILITY,
-	.bDevCapabilityType =	USB_SS_CAP_TYPE,
-
-	/* .bmAttributes = LTM is not supported yet */
-
-	.wSpeedSupported =	cpu_to_le16(USB_LOW_SPEED_OPERATION
-		| USB_FULL_SPEED_OPERATION
-		| USB_HIGH_SPEED_OPERATION
-		| USB_5GBPS_OPERATION),
-	.bFunctionalitySupport = USB_LOW_SPEED_OPERATION,
-	.bU1devExitLat =	USB_DEFAULT_U1_DEV_EXIT_LAT,
-	.bU2DevExitLat =	cpu_to_le16(USB_DEFAULT_U2_DEV_EXIT_LAT),
-};
-
-static __maybe_unused struct usb_bos_descriptor fsg_bos_desc = {
-	.bLength =		USB_DT_BOS_SIZE,
-	.bDescriptorType =	USB_DT_BOS,
-
-	.wTotalLength =		cpu_to_le16(USB_DT_BOS_SIZE
-				+ USB_DT_USB_EXT_CAP_SIZE
-				+ USB_DT_USB_SS_CAP_SIZE),
-
-	.bNumDeviceCaps =	2,
-};
-
-static struct usb_descriptor_header *fsg_ss_function[] = {
-#ifndef FSG_NO_OTG
-	(struct usb_descriptor_header *) &fsg_otg_desc,
-#endif
-	(struct usb_descriptor_header *) &fsg_intf_desc,
-	(struct usb_descriptor_header *) &fsg_ss_bulk_in_desc,
-	(struct usb_descriptor_header *) &fsg_ss_bulk_in_comp_desc,
-	(struct usb_descriptor_header *) &fsg_ss_bulk_out_desc,
-	(struct usb_descriptor_header *) &fsg_ss_bulk_out_comp_desc,
-#ifndef FSG_NO_INTR_EP
-	(struct usb_descriptor_header *) &fsg_ss_intr_in_desc,
-	(struct usb_descriptor_header *) &fsg_ss_intr_in_comp_desc,
-#endif
-	NULL,
-};
-
-/* Maxpacket and other transfer characteristics vary by speed. */
-static __maybe_unused struct usb_endpoint_descriptor *
-fsg_ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *fs,
-		struct usb_endpoint_descriptor *hs,
-		struct usb_endpoint_descriptor *ss)
-{
-	if (gadget_is_superspeed(g) && g->speed == USB_SPEED_SUPER)
-		return ss;
-	else if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
-		return hs;
-	return fs;
-}
-
-
-/* Static strings, in UTF-8 (for simplicity we use only ASCII characters) */
-static struct usb_string		fsg_strings[] = {
-#ifndef FSG_NO_DEVICE_STRINGS
-	{FSG_STRING_MANUFACTURER,	fsg_string_manufacturer},
-	{FSG_STRING_PRODUCT,		fsg_string_product},
-	{FSG_STRING_SERIAL,		""},
-	{FSG_STRING_CONFIG,		fsg_string_config},
-#endif
-	{FSG_STRING_INTERFACE,		fsg_string_interface},
-	{}
-};
-
-static struct usb_gadget_strings	fsg_stringtab = {
-	.language	= 0x0409,		/* en-us */
-	.strings	= fsg_strings,
-};
-
-
- /*-------------------------------------------------------------------------*/
-
-/*
- * If the next two routines are called while the gadget is registered,
- * the caller must own fsg->filesem for writing.
- */
-
-static void fsg_lun_close(struct fsg_lun *curlun)
-{
-	if (curlun->filp) {
-		LDBG(curlun, "close backing file\n");
-		fput(curlun->filp);
-		curlun->filp = NULL;
-	}
-}
-
-
-static int fsg_lun_open(struct fsg_lun *curlun, const char *filename)
-{
-	int				ro;
-	struct file			*filp = NULL;
-	int				rc = -EINVAL;
-	struct inode			*inode = NULL;
-	loff_t				size;
-	loff_t				num_sectors;
-	loff_t				min_sectors;
-	unsigned int			blkbits;
-	unsigned int			blksize;
-
-	/* R/W if we can, R/O if we must */
-	ro = curlun->initially_ro;
-	if (!ro) {
-		filp = filp_open(filename, O_RDWR | O_LARGEFILE, 0);
-		if (PTR_ERR(filp) == -EROFS || PTR_ERR(filp) == -EACCES)
-			ro = 1;
-	}
-	if (ro)
-		filp = filp_open(filename, O_RDONLY | O_LARGEFILE, 0);
-	if (IS_ERR(filp)) {
-		LINFO(curlun, "unable to open backing file: %s\n", filename);
-		return PTR_ERR(filp);
-	}
-
-	if (!(filp->f_mode & FMODE_WRITE))
-		ro = 1;
-
-	inode = file_inode(filp);
-	if ((!S_ISREG(inode->i_mode) && !S_ISBLK(inode->i_mode))) {
-		LINFO(curlun, "invalid file type: %s\n", filename);
-		goto out;
-	}
-
-	/*
-	 * If we can't read the file, it's no good.
-	 * If we can't write the file, use it read-only.
-	 */
-	if (!(filp->f_op->read || filp->f_op->aio_read)) {
-		LINFO(curlun, "file not readable: %s\n", filename);
-		goto out;
-	}
-	if (!(filp->f_op->write || filp->f_op->aio_write))
-		ro = 1;
-
-	size = i_size_read(inode->i_mapping->host);
-	if (size < 0) {
-		LINFO(curlun, "unable to find file size: %s\n", filename);
-		rc = (int) size;
-		goto out;
-	}
-
-	if (curlun->cdrom) {
-		blksize = 2048;
-		blkbits = 11;
-	} else if (inode->i_bdev) {
-		blksize = bdev_logical_block_size(inode->i_bdev);
-		blkbits = blksize_bits(blksize);
-	} else {
-		blksize = 512;
-		blkbits = 9;
-	}
-
-	num_sectors = size >> blkbits; /* File size in logic-block-size blocks */
-	min_sectors = 1;
-	if (curlun->cdrom) {
-		min_sectors = 300;	/* Smallest track is 300 frames */
-		if (num_sectors >= 256*60*75) {
-			num_sectors = 256*60*75 - 1;
-			LINFO(curlun, "file too big: %s\n", filename);
-			LINFO(curlun, "using only first %d blocks\n",
-					(int) num_sectors);
-		}
-	}
-	if (num_sectors < min_sectors) {
-		LINFO(curlun, "file too small: %s\n", filename);
-		rc = -ETOOSMALL;
-		goto out;
-	}
-
-	if (fsg_lun_is_open(curlun))
-		fsg_lun_close(curlun);
-
-	curlun->blksize = blksize;
-	curlun->blkbits = blkbits;
-	curlun->ro = ro;
-	curlun->filp = filp;
-	curlun->file_length = size;
-	curlun->num_sectors = num_sectors;
-	LDBG(curlun, "open backing file: %s\n", filename);
-	return 0;
-
-out:
-	fput(filp);
-	return rc;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * Sync the file data, don't bother with the metadata.
- * This code was copied from fs/buffer.c:sys_fdatasync().
- */
-static int fsg_lun_fsync_sub(struct fsg_lun *curlun)
-{
-	struct file	*filp = curlun->filp;
-
-	if (curlun->ro || !filp)
-		return 0;
-	return vfs_fsync(filp, 1);
-}
-
-static void store_cdrom_address(u8 *dest, int msf, u32 addr)
-{
-	if (msf) {
-		/* Convert to Minutes-Seconds-Frames */
-		addr >>= 2;		/* Convert to 2048-byte frames */
-		addr += 2*75;		/* Lead-in occupies 2 seconds */
-		dest[3] = addr % 75;	/* Frames */
-		addr /= 75;
-		dest[2] = addr % 60;	/* Seconds */
-		addr /= 60;
-		dest[1] = addr;		/* Minutes */
-		dest[0] = 0;		/* Reserved */
-	} else {
-		/* Absolute sector */
-		put_unaligned_be32(addr, dest);
-	}
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-
-static ssize_t fsg_show_ro(struct device *dev, struct device_attribute *attr,
-			   char *buf)
-{
-	struct fsg_lun	*curlun = fsg_lun_from_dev(dev);
-
-	return sprintf(buf, "%d\n", fsg_lun_is_open(curlun)
-				  ? curlun->ro
-				  : curlun->initially_ro);
-}
-
-static ssize_t fsg_show_nofua(struct device *dev, struct device_attribute *attr,
-			      char *buf)
-{
-	struct fsg_lun	*curlun = fsg_lun_from_dev(dev);
-
-	return sprintf(buf, "%u\n", curlun->nofua);
-}
-
-static ssize_t fsg_show_file(struct device *dev, struct device_attribute *attr,
-			     char *buf)
-{
-	struct fsg_lun	*curlun = fsg_lun_from_dev(dev);
-	struct rw_semaphore	*filesem = dev_get_drvdata(dev);
-	char		*p;
-	ssize_t		rc;
-
-	down_read(filesem);
-	if (fsg_lun_is_open(curlun)) {	/* Get the complete pathname */
-		p = d_path(&curlun->filp->f_path, buf, PAGE_SIZE - 1);
-		if (IS_ERR(p))
-			rc = PTR_ERR(p);
-		else {
-			rc = strlen(p);
-			memmove(buf, p, rc);
-			buf[rc] = '\n';		/* Add a newline */
-			buf[++rc] = 0;
-		}
-	} else {				/* No file, return 0 bytes */
-		*buf = 0;
-		rc = 0;
-	}
-	up_read(filesem);
-	return rc;
-}
-
-
-static ssize_t fsg_store_ro(struct device *dev, struct device_attribute *attr,
-			    const char *buf, size_t count)
-{
-	ssize_t		rc;
-	struct fsg_lun	*curlun = fsg_lun_from_dev(dev);
-	struct rw_semaphore	*filesem = dev_get_drvdata(dev);
-	unsigned	ro;
-
-	rc = kstrtouint(buf, 2, &ro);
-	if (rc)
-		return rc;
-
-	/*
-	 * Allow the write-enable status to change only while the
-	 * backing file is closed.
-	 */
-	down_read(filesem);
-	if (fsg_lun_is_open(curlun)) {
-		LDBG(curlun, "read-only status change prevented\n");
-		rc = -EBUSY;
-	} else {
-		curlun->ro = ro;
-		curlun->initially_ro = ro;
-		LDBG(curlun, "read-only status set to %d\n", curlun->ro);
-		rc = count;
-	}
-	up_read(filesem);
-	return rc;
-}
-
-static ssize_t fsg_store_nofua(struct device *dev,
-			       struct device_attribute *attr,
-			       const char *buf, size_t count)
-{
-	struct fsg_lun	*curlun = fsg_lun_from_dev(dev);
-	unsigned	nofua;
-	int		ret;
-
-	ret = kstrtouint(buf, 2, &nofua);
-	if (ret)
-		return ret;
-
-	/* Sync data when switching from async mode to sync */
-	if (!nofua && curlun->nofua)
-		fsg_lun_fsync_sub(curlun);
-
-	curlun->nofua = nofua;
-
-	return count;
-}
-
-static ssize_t fsg_store_file(struct device *dev, struct device_attribute *attr,
-			      const char *buf, size_t count)
-{
-	struct fsg_lun	*curlun = fsg_lun_from_dev(dev);
-	struct rw_semaphore	*filesem = dev_get_drvdata(dev);
-	int		rc = 0;
-
-	if (curlun->prevent_medium_removal && fsg_lun_is_open(curlun)) {
-		LDBG(curlun, "eject attempt prevented\n");
-		return -EBUSY;				/* "Door is locked" */
-	}
-
-	/* Remove a trailing newline */
-	if (count > 0 && buf[count-1] == '\n')
-		((char *) buf)[count-1] = 0;		/* Ugh! */
-
-	/* Load new medium */
-	down_write(filesem);
-	if (count > 0 && buf[0]) {
-		/* fsg_lun_open() will close existing file if any. */
-		rc = fsg_lun_open(curlun, buf);
-		if (rc == 0)
-			curlun->unit_attention_data =
-					SS_NOT_READY_TO_READY_TRANSITION;
-	} else if (fsg_lun_is_open(curlun)) {
-		fsg_lun_close(curlun);
-		curlun->unit_attention_data = SS_MEDIUM_NOT_PRESENT;
-	}
-	up_write(filesem);
-	return (rc < 0 ? rc : count);
-}
diff --git a/drivers/staging/ccg/sysfs-class-ccg_usb b/drivers/staging/ccg/sysfs-class-ccg_usb
deleted file mode 100644
index dd12a33..0000000
--- a/drivers/staging/ccg/sysfs-class-ccg_usb
+++ /dev/null
@@ -1,158 +0,0 @@
-What:		/sys/class/ccg_usb
-Date:		May 2012
-KernelVersion:	3.4
-Contact:	linux-usb@vger.kernel.org
-Description:
-		The ccg_usb/ class subdirectory belongs to ccg
-		USB gadget.
-
-What:		/sys/class/ccg_usb/ccgX
-Date:		May 2012
-KernelVersion:	3.4
-Contact:	linux-usb@vger.kernel.org
-Description:
-		The /sys/class/ccg_usb/ccg{0,1,2,3...} class
-		subdirectories correspond to each ccg gadget device;
-		at the time of this writing there is only ccg0 and it
-		represents the ccg gadget.
-
-What:		/sys/class/ccg_usb/ccgX/functions
-Date:		May 2012
-KernelVersion:	3.4
-Contact:	linux-usb@vger.kernel.org
-Description:
-		A comma-separated list of USB function names to be activated
-		in this ccg gadget. It includes both the functions provided
-		in-kernel by the ccg gadget and the functions provided from
-		userspace through FunctionFS.
-
-What:		/sys/class/ccg_usb/ccgX/enable
-Date:		May 2012
-KernelVersion:	3.4
-Contact:	linux-usb@vger.kernel.org
-Description:
-		A flag activating/deactivating the ccg usb gadget.
-
-What:		/sys/class/ccg_usb/ccgX/state
-Date:		May 2012
-KernelVersion:	3.4
-Contact:	linux-usb@vger.kernel.org
-Description:
-		Configurable usb gadget state:
-
-		DISCONNECTED
-		CONNECTED
-		CONFIGURED
-
-What:		/sys/class/ccg_usb/ccgX/f_acm/
-Date:		May 2012
-KernelVersion:	3.4
-Contact:	linux-usb@vger.kernel.org
-Description:
-		The /sys/class/ccg_usb/ccgX/f_acm subdirectory
-		corresponds to the gadget's USB CDC serial (ACM) function
-		driver.
-
-What:		/sys/class/ccg_usb/ccgX/f_acm/instances
-Date:		May 2012
-KernelVersion:	3.4
-Contact:	linux-usb@vger.kernel.org
-Description:
-		Maximum number of the /dev/ttyGS<X> interface the driver uses.
-
-What:		/sys/class/ccg_usb/ccgX/f_fs
-Date:		May 2012
-KernelVersion:	3.4
-Contact:	linux-usb@vger.kernel.org
-Description:
-		The /sys/class/ccg_usb/ccgX/f_fs subdirectory
-		corresponds to the gadget's FunctionFS driver.
-
-What:		/sys/class/ccg_usb/ccgX/f_fs/user_functions
-Date:		May 2012
-KernelVersion:	3.4
-Contact:	linux-usb@vger.kernel.org
-Description:
-		A comma-separeted list of USB function names to be supported
-		from userspace. No other userspace FunctionFS functions can
-		be supported than listed here. However, the actual activation
-		of these functions is still done through
-		/sys/class/ccg_usb/ccgX/functions, where it is possible
-		to specify any subset (including maximum and empty) of
-		/sys/class/ccg_usb/ccgX/f_fs/user_functions.
-
-What:		/sys/class/ccg_usb/ccgX/f_fs/max_user_functions
-Date:		May 2012
-KernelVersion:	3.4
-Contact:	linux-usb@vger.kernel.org
-Description:
-		Maximum number of USB functions to be supported from userspace.
-
-What:		/sys/class/ccg_usb/ccgX/f_rndis
-Date:		May 2012
-KernelVersion:	3.4
-Contact:	linux-usb@vger.kernel.org
-Description:
-		The /sys/class/ccg_usb/ccgX/f_rndis subdirectory
-		corresponds to the gadget's RNDIS driver.
-
-What:		/sys/class/ccg_usb/ccgX/f_rndis/manufacturer
-Date:		May 2012
-KernelVersion:	3.4
-Contact:	linux-usb@vger.kernel.org
-Description:
-		RNDIS Ethernet port manufacturer string.
-
-What:		/sys/class/ccg_usb/ccgX/f_rndis/wceis
-Date:		May 2012
-KernelVersion:	3.4
-Contact:	linux-usb@vger.kernel.org
-Description:
-		RNDIS Ethernet port wireless flag.
-
-What:		/sys/class/ccg_usb/ccgX/f_rndis/ethaddr
-Date:		May 2012
-KernelVersion:	3.4
-Contact:	linux-usb@vger.kernel.org
-Description:
-		RNDIS Ethernet port Ethernet address.
-
-What:		/sys/class/ccg_usb/ccgX/f_rndis/vendorID
-Date:		May 2012
-KernelVersion:	3.4
-Contact:	linux-usb@vger.kernel.org
-Description:
-		RNDIS Ethernet port vendor ID.
-
-What:		/sys/class/ccg_usb/ccgX/f_mass_storage
-Date:		May 2012
-KernelVersion:	3.4
-Contact:	linux-usb@vger.kernel.org
-Description:
-		The /sys/class/ccg_usb/ccgX/f_mass_storage subdirectory
-		corresponds to the gadget's USB mass storage driver.
-
-What:		/sys/class/ccg_usb/ccgX/f_mass_storage/lun
-Date:		May 2012
-KernelVersion:	3.4
-Contact:	linux-usb@vger.kernel.org
-Description:
-		The /sys/class/ccg_usb/ccgX/f_mass_storage/lun
-		subdirectory corresponds to the gadget's USB mass storage
-		driver and its underlying storage.
-
-What:		/sys/class/ccg_usb/ccgX/f_mass_storage/lun
-Date:		May 2012
-KernelVersion:	3.4
-Contact:	linux-usb@vger.kernel.org
-Description:
-		The /sys/class/ccg_usb/ccgX/f_mass_storage/lun
-		subdirectory corresponds to the gadget's USB mass storage
-		driver and its underlying storage.
-
-What:		/sys/class/ccg_usb/ccgX/f_mass_storage/lun/file
-Date:		May 2012
-KernelVersion:	3.4
-Contact:	linux-usb@vger.kernel.org
-Description:
-		Gadget's USB mass storage underlying file.
diff --git a/drivers/staging/ccg/u_ether.c b/drivers/staging/ccg/u_ether.c
deleted file mode 100644
index fed7886..0000000
--- a/drivers/staging/ccg/u_ether.c
+++ /dev/null
@@ -1,986 +0,0 @@
-/*
- * u_ether.c -- Ethernet-over-USB link layer utilities for Gadget stack
- *
- * Copyright (C) 2003-2005,2008 David Brownell
- * Copyright (C) 2003-2004 Robert Schwebel, Benedikt Spranger
- * Copyright (C) 2008 Nokia Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-/* #define VERBOSE_DEBUG */
-
-#include <linux/kernel.h>
-#include <linux/gfp.h>
-#include <linux/device.h>
-#include <linux/ctype.h>
-#include <linux/etherdevice.h>
-#include <linux/ethtool.h>
-
-#include "u_ether.h"
-
-
-/*
- * This component encapsulates the Ethernet link glue needed to provide
- * one (!) network link through the USB gadget stack, normally "usb0".
- *
- * The control and data models are handled by the function driver which
- * connects to this code; such as CDC Ethernet (ECM or EEM),
- * "CDC Subset", or RNDIS.  That includes all descriptor and endpoint
- * management.
- *
- * Link level addressing is handled by this component using module
- * parameters; if no such parameters are provided, random link level
- * addresses are used.  Each end of the link uses one address.  The
- * host end address is exported in various ways, and is often recorded
- * in configuration databases.
- *
- * The driver which assembles each configuration using such a link is
- * responsible for ensuring that each configuration includes at most one
- * instance of is network link.  (The network layer provides ways for
- * this single "physical" link to be used by multiple virtual links.)
- */
-
-#define UETH__VERSION	"29-May-2008"
-
-struct eth_dev {
-	/* lock is held while accessing port_usb
-	 * or updating its backlink port_usb->ioport
-	 */
-	spinlock_t		lock;
-	struct gether		*port_usb;
-
-	struct net_device	*net;
-	struct usb_gadget	*gadget;
-
-	spinlock_t		req_lock;	/* guard {rx,tx}_reqs */
-	struct list_head	tx_reqs, rx_reqs;
-	atomic_t		tx_qlen;
-
-	struct sk_buff_head	rx_frames;
-
-	unsigned		header_len;
-	struct sk_buff		*(*wrap)(struct gether *, struct sk_buff *skb);
-	int			(*unwrap)(struct gether *,
-						struct sk_buff *skb,
-						struct sk_buff_head *list);
-
-	struct work_struct	work;
-
-	unsigned long		todo;
-#define	WORK_RX_MEMORY		0
-
-	bool			zlp;
-	u8			host_mac[ETH_ALEN];
-};
-
-/*-------------------------------------------------------------------------*/
-
-#define RX_EXTRA	20	/* bytes guarding against rx overflows */
-
-#define DEFAULT_QLEN	2	/* double buffering by default */
-
-static unsigned qmult = 5;
-module_param(qmult, uint, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(qmult, "queue length multiplier at high/super speed");
-
-/* 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 ||
-					    gadget->speed == USB_SPEED_SUPER))
-		return qmult * DEFAULT_QLEN;
-	else
-		return DEFAULT_QLEN;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* REVISIT there must be a better way than having two sets
- * of debug calls ...
- */
-
-#undef DBG
-#undef VDBG
-#undef ERROR
-#undef INFO
-
-#define xprintk(d, level, fmt, args...) \
-	printk(level "%s: " fmt , (d)->net->name , ## args)
-
-#ifdef DEBUG
-#undef DEBUG
-#define DBG(dev, fmt, args...) \
-	xprintk(dev , KERN_DEBUG , fmt , ## args)
-#else
-#define DBG(dev, fmt, args...) \
-	do { } while (0)
-#endif /* DEBUG */
-
-#ifdef VERBOSE_DEBUG
-#define VDBG	DBG
-#else
-#define VDBG(dev, fmt, args...) \
-	do { } while (0)
-#endif /* DEBUG */
-
-#define ERROR(dev, fmt, args...) \
-	xprintk(dev , KERN_ERR , fmt , ## args)
-#define INFO(dev, fmt, args...) \
-	xprintk(dev , KERN_INFO , fmt , ## args)
-
-/*-------------------------------------------------------------------------*/
-
-/* NETWORK DRIVER HOOKUP (to the layer above this driver) */
-
-static int ueth_change_mtu(struct net_device *net, int new_mtu)
-{
-	struct eth_dev	*dev = netdev_priv(net);
-	unsigned long	flags;
-	int		status = 0;
-
-	/* don't change MTU on "live" link (peer won't know) */
-	spin_lock_irqsave(&dev->lock, flags);
-	if (dev->port_usb)
-		status = -EBUSY;
-	else if (new_mtu <= ETH_HLEN || new_mtu > ETH_FRAME_LEN)
-		status = -ERANGE;
-	else
-		net->mtu = new_mtu;
-	spin_unlock_irqrestore(&dev->lock, flags);
-
-	return status;
-}
-
-static void eth_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *p)
-{
-	struct eth_dev *dev = netdev_priv(net);
-
-	strlcpy(p->driver, "g_ether", sizeof(p->driver));
-	strlcpy(p->version, UETH__VERSION, sizeof(p->version));
-	strlcpy(p->fw_version, dev->gadget->name, sizeof(p->fw_version));
-	strlcpy(p->bus_info, dev_name(&dev->gadget->dev), sizeof(p->bus_info));
-}
-
-/* REVISIT can also support:
- *   - WOL (by tracking suspends and issuing remote wakeup)
- *   - msglevel (implies updated messaging)
- *   - ... probably more ethtool ops
- */
-
-static const struct ethtool_ops ops = {
-	.get_drvinfo = eth_get_drvinfo,
-	.get_link = ethtool_op_get_link,
-};
-
-static void defer_kevent(struct eth_dev *dev, int flag)
-{
-	if (test_and_set_bit(flag, &dev->todo))
-		return;
-	if (!schedule_work(&dev->work))
-		ERROR(dev, "kevent %d may have been dropped\n", flag);
-	else
-		DBG(dev, "kevent %d scheduled\n", flag);
-}
-
-static void rx_complete(struct usb_ep *ep, struct usb_request *req);
-
-static int
-rx_submit(struct eth_dev *dev, struct usb_request *req, gfp_t gfp_flags)
-{
-	struct sk_buff	*skb;
-	int		retval = -ENOMEM;
-	size_t		size = 0;
-	struct usb_ep	*out;
-	unsigned long	flags;
-
-	spin_lock_irqsave(&dev->lock, flags);
-	if (dev->port_usb)
-		out = dev->port_usb->out_ep;
-	else
-		out = NULL;
-	spin_unlock_irqrestore(&dev->lock, flags);
-
-	if (!out)
-		return -ENOTCONN;
-
-
-	/* Padding up to RX_EXTRA handles minor disagreements with host.
-	 * Normally we use the USB "terminate on short read" convention;
-	 * so allow up to (N*maxpacket), since that memory is normally
-	 * already allocated.  Some hardware doesn't deal well with short
-	 * reads (e.g. DMA must be N*maxpacket), so for now don't trim a
-	 * byte off the end (to force hardware errors on overflow).
-	 *
-	 * RNDIS uses internal framing, and explicitly allows senders to
-	 * pad to end-of-packet.  That's potentially nice for speed, but
-	 * means receivers can't recover lost synch on their own (because
-	 * new packets don't only start after a short RX).
-	 */
-	size += sizeof(struct ethhdr) + dev->net->mtu + RX_EXTRA;
-	size += dev->port_usb->header_len;
-	size += out->maxpacket - 1;
-	size -= size % out->maxpacket;
-
-	if (dev->port_usb->is_fixed)
-		size = max_t(size_t, size, dev->port_usb->fixed_out_len);
-
-	skb = alloc_skb(size + NET_IP_ALIGN, gfp_flags);
-	if (skb == NULL) {
-		DBG(dev, "no rx skb\n");
-		goto enomem;
-	}
-
-	/* Some platforms perform better when IP packets are aligned,
-	 * but on at least one, checksumming fails otherwise.  Note:
-	 * RNDIS headers involve variable numbers of LE32 values.
-	 */
-	skb_reserve(skb, NET_IP_ALIGN);
-
-	req->buf = skb->data;
-	req->length = size;
-	req->complete = rx_complete;
-	req->context = skb;
-
-	retval = usb_ep_queue(out, req, gfp_flags);
-	if (retval == -ENOMEM)
-enomem:
-		defer_kevent(dev, WORK_RX_MEMORY);
-	if (retval) {
-		DBG(dev, "rx submit --> %d\n", retval);
-		if (skb)
-			dev_kfree_skb_any(skb);
-		spin_lock_irqsave(&dev->req_lock, flags);
-		list_add(&req->list, &dev->rx_reqs);
-		spin_unlock_irqrestore(&dev->req_lock, flags);
-	}
-	return retval;
-}
-
-static void rx_complete(struct usb_ep *ep, struct usb_request *req)
-{
-	struct sk_buff	*skb = req->context, *skb2;
-	struct eth_dev	*dev = ep->driver_data;
-	int		status = req->status;
-
-	switch (status) {
-
-	/* normal completion */
-	case 0:
-		skb_put(skb, req->actual);
-
-		if (dev->unwrap) {
-			unsigned long	flags;
-
-			spin_lock_irqsave(&dev->lock, flags);
-			if (dev->port_usb) {
-				status = dev->unwrap(dev->port_usb,
-							skb,
-							&dev->rx_frames);
-			} else {
-				dev_kfree_skb_any(skb);
-				status = -ENOTCONN;
-			}
-			spin_unlock_irqrestore(&dev->lock, flags);
-		} else {
-			skb_queue_tail(&dev->rx_frames, skb);
-		}
-		skb = NULL;
-
-		skb2 = skb_dequeue(&dev->rx_frames);
-		while (skb2) {
-			if (status < 0
-					|| ETH_HLEN > skb2->len
-					|| skb2->len > ETH_FRAME_LEN) {
-				dev->net->stats.rx_errors++;
-				dev->net->stats.rx_length_errors++;
-				DBG(dev, "rx length %d\n", skb2->len);
-				dev_kfree_skb_any(skb2);
-				goto next_frame;
-			}
-			skb2->protocol = eth_type_trans(skb2, dev->net);
-			dev->net->stats.rx_packets++;
-			dev->net->stats.rx_bytes += skb2->len;
-
-			/* no buffer copies needed, unless hardware can't
-			 * use skb buffers.
-			 */
-			status = netif_rx(skb2);
-next_frame:
-			skb2 = skb_dequeue(&dev->rx_frames);
-		}
-		break;
-
-	/* software-driven interface shutdown */
-	case -ECONNRESET:		/* unlink */
-	case -ESHUTDOWN:		/* disconnect etc */
-		VDBG(dev, "rx shutdown, code %d\n", status);
-		goto quiesce;
-
-	/* for hardware automagic (such as pxa) */
-	case -ECONNABORTED:		/* endpoint reset */
-		DBG(dev, "rx %s reset\n", ep->name);
-		defer_kevent(dev, WORK_RX_MEMORY);
-quiesce:
-		dev_kfree_skb_any(skb);
-		goto clean;
-
-	/* data overrun */
-	case -EOVERFLOW:
-		dev->net->stats.rx_over_errors++;
-		/* FALLTHROUGH */
-
-	default:
-		dev->net->stats.rx_errors++;
-		DBG(dev, "rx status %d\n", status);
-		break;
-	}
-
-	if (skb)
-		dev_kfree_skb_any(skb);
-	if (!netif_running(dev->net)) {
-clean:
-		spin_lock(&dev->req_lock);
-		list_add(&req->list, &dev->rx_reqs);
-		spin_unlock(&dev->req_lock);
-		req = NULL;
-	}
-	if (req)
-		rx_submit(dev, req, GFP_ATOMIC);
-}
-
-static int prealloc(struct list_head *list, struct usb_ep *ep, unsigned n)
-{
-	unsigned		i;
-	struct usb_request	*req;
-
-	if (!n)
-		return -ENOMEM;
-
-	/* queue/recycle up to N requests */
-	i = n;
-	list_for_each_entry(req, list, list) {
-		if (i-- == 0)
-			goto extra;
-	}
-	while (i--) {
-		req = usb_ep_alloc_request(ep, GFP_ATOMIC);
-		if (!req)
-			return list_empty(list) ? -ENOMEM : 0;
-		list_add(&req->list, list);
-	}
-	return 0;
-
-extra:
-	/* free extras */
-	for (;;) {
-		struct list_head	*next;
-
-		next = req->list.next;
-		list_del(&req->list);
-		usb_ep_free_request(ep, req);
-
-		if (next == list)
-			break;
-
-		req = container_of(next, struct usb_request, list);
-	}
-	return 0;
-}
-
-static int alloc_requests(struct eth_dev *dev, struct gether *link, unsigned n)
-{
-	int	status;
-
-	spin_lock(&dev->req_lock);
-	status = prealloc(&dev->tx_reqs, link->in_ep, n);
-	if (status < 0)
-		goto fail;
-	status = prealloc(&dev->rx_reqs, link->out_ep, n);
-	if (status < 0)
-		goto fail;
-	goto done;
-fail:
-	DBG(dev, "can't alloc requests\n");
-done:
-	spin_unlock(&dev->req_lock);
-	return status;
-}
-
-static void rx_fill(struct eth_dev *dev, gfp_t gfp_flags)
-{
-	struct usb_request	*req;
-	unsigned long		flags;
-
-	/* fill unused rxq slots with some skb */
-	spin_lock_irqsave(&dev->req_lock, flags);
-	while (!list_empty(&dev->rx_reqs)) {
-		req = container_of(dev->rx_reqs.next,
-				struct usb_request, list);
-		list_del_init(&req->list);
-		spin_unlock_irqrestore(&dev->req_lock, flags);
-
-		if (rx_submit(dev, req, gfp_flags) < 0) {
-			defer_kevent(dev, WORK_RX_MEMORY);
-			return;
-		}
-
-		spin_lock_irqsave(&dev->req_lock, flags);
-	}
-	spin_unlock_irqrestore(&dev->req_lock, flags);
-}
-
-static void eth_work(struct work_struct *work)
-{
-	struct eth_dev	*dev = container_of(work, struct eth_dev, work);
-
-	if (test_and_clear_bit(WORK_RX_MEMORY, &dev->todo)) {
-		if (netif_running(dev->net))
-			rx_fill(dev, GFP_KERNEL);
-	}
-
-	if (dev->todo)
-		DBG(dev, "work done, flags = 0x%lx\n", dev->todo);
-}
-
-static void tx_complete(struct usb_ep *ep, struct usb_request *req)
-{
-	struct sk_buff	*skb = req->context;
-	struct eth_dev	*dev = ep->driver_data;
-
-	switch (req->status) {
-	default:
-		dev->net->stats.tx_errors++;
-		VDBG(dev, "tx err %d\n", req->status);
-		/* FALLTHROUGH */
-	case -ECONNRESET:		/* unlink */
-	case -ESHUTDOWN:		/* disconnect etc */
-		break;
-	case 0:
-		dev->net->stats.tx_bytes += skb->len;
-	}
-	dev->net->stats.tx_packets++;
-
-	spin_lock(&dev->req_lock);
-	list_add(&req->list, &dev->tx_reqs);
-	spin_unlock(&dev->req_lock);
-	dev_kfree_skb_any(skb);
-
-	atomic_dec(&dev->tx_qlen);
-	if (netif_carrier_ok(dev->net))
-		netif_wake_queue(dev->net);
-}
-
-static inline int is_promisc(u16 cdc_filter)
-{
-	return cdc_filter & USB_CDC_PACKET_TYPE_PROMISCUOUS;
-}
-
-static netdev_tx_t eth_start_xmit(struct sk_buff *skb,
-					struct net_device *net)
-{
-	struct eth_dev		*dev = netdev_priv(net);
-	int			length = skb->len;
-	int			retval;
-	struct usb_request	*req = NULL;
-	unsigned long		flags;
-	struct usb_ep		*in;
-	u16			cdc_filter;
-
-	spin_lock_irqsave(&dev->lock, flags);
-	if (dev->port_usb) {
-		in = dev->port_usb->in_ep;
-		cdc_filter = dev->port_usb->cdc_filter;
-	} else {
-		in = NULL;
-		cdc_filter = 0;
-	}
-	spin_unlock_irqrestore(&dev->lock, flags);
-
-	if (!in) {
-		dev_kfree_skb_any(skb);
-		return NETDEV_TX_OK;
-	}
-
-	/* apply outgoing CDC or RNDIS filters */
-	if (!is_promisc(cdc_filter)) {
-		u8		*dest = skb->data;
-
-		if (is_multicast_ether_addr(dest)) {
-			u16	type;
-
-			/* ignores USB_CDC_PACKET_TYPE_MULTICAST and host
-			 * SET_ETHERNET_MULTICAST_FILTERS requests
-			 */
-			if (is_broadcast_ether_addr(dest))
-				type = USB_CDC_PACKET_TYPE_BROADCAST;
-			else
-				type = USB_CDC_PACKET_TYPE_ALL_MULTICAST;
-			if (!(cdc_filter & type)) {
-				dev_kfree_skb_any(skb);
-				return NETDEV_TX_OK;
-			}
-		}
-		/* ignores USB_CDC_PACKET_TYPE_DIRECTED */
-	}
-
-	spin_lock_irqsave(&dev->req_lock, flags);
-	/*
-	 * this freelist can be empty if an interrupt triggered disconnect()
-	 * and reconfigured the gadget (shutting down this queue) after the
-	 * network stack decided to xmit but before we got the spinlock.
-	 */
-	if (list_empty(&dev->tx_reqs)) {
-		spin_unlock_irqrestore(&dev->req_lock, flags);
-		return NETDEV_TX_BUSY;
-	}
-
-	req = container_of(dev->tx_reqs.next, struct usb_request, list);
-	list_del(&req->list);
-
-	/* temporarily stop TX queue when the freelist empties */
-	if (list_empty(&dev->tx_reqs))
-		netif_stop_queue(net);
-	spin_unlock_irqrestore(&dev->req_lock, flags);
-
-	/* no buffer copies needed, unless the network stack did it
-	 * or the hardware can't use skb buffers.
-	 * or there's not enough space for extra headers we need
-	 */
-	if (dev->wrap) {
-		unsigned long	flags;
-
-		spin_lock_irqsave(&dev->lock, flags);
-		if (dev->port_usb)
-			skb = dev->wrap(dev->port_usb, skb);
-		spin_unlock_irqrestore(&dev->lock, flags);
-		if (!skb)
-			goto drop;
-
-		length = skb->len;
-	}
-	req->buf = skb->data;
-	req->context = skb;
-	req->complete = tx_complete;
-
-	/* NCM requires no zlp if transfer is dwNtbInMaxSize */
-	if (dev->port_usb->is_fixed &&
-	    length == dev->port_usb->fixed_in_len &&
-	    (length % in->maxpacket) == 0)
-		req->zero = 0;
-	else
-		req->zero = 1;
-
-	/* use zlp framing on tx for strict CDC-Ether conformance,
-	 * though any robust network rx path ignores extra padding.
-	 * and some hardware doesn't like to write zlps.
-	 */
-	if (req->zero && !dev->zlp && (length % in->maxpacket) == 0)
-		length++;
-
-	req->length = length;
-
-	/* throttle high/super speed IRQ rate back slightly */
-	if (gadget_is_dualspeed(dev->gadget))
-		req->no_interrupt = (dev->gadget->speed == USB_SPEED_HIGH ||
-				     dev->gadget->speed == USB_SPEED_SUPER)
-			? ((atomic_read(&dev->tx_qlen) % qmult) != 0)
-			: 0;
-
-	retval = usb_ep_queue(in, req, GFP_ATOMIC);
-	switch (retval) {
-	default:
-		DBG(dev, "tx queue err %d\n", retval);
-		break;
-	case 0:
-		net->trans_start = jiffies;
-		atomic_inc(&dev->tx_qlen);
-	}
-
-	if (retval) {
-		dev_kfree_skb_any(skb);
-drop:
-		dev->net->stats.tx_dropped++;
-		spin_lock_irqsave(&dev->req_lock, flags);
-		if (list_empty(&dev->tx_reqs))
-			netif_start_queue(net);
-		list_add(&req->list, &dev->tx_reqs);
-		spin_unlock_irqrestore(&dev->req_lock, flags);
-	}
-	return NETDEV_TX_OK;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void eth_start(struct eth_dev *dev, gfp_t gfp_flags)
-{
-	DBG(dev, "%s\n", __func__);
-
-	/* fill the rx queue */
-	rx_fill(dev, gfp_flags);
-
-	/* and open the tx floodgates */
-	atomic_set(&dev->tx_qlen, 0);
-	netif_wake_queue(dev->net);
-}
-
-static int eth_open(struct net_device *net)
-{
-	struct eth_dev	*dev = netdev_priv(net);
-	struct gether	*link;
-
-	DBG(dev, "%s\n", __func__);
-	if (netif_carrier_ok(dev->net))
-		eth_start(dev, GFP_KERNEL);
-
-	spin_lock_irq(&dev->lock);
-	link = dev->port_usb;
-	if (link && link->open)
-		link->open(link);
-	spin_unlock_irq(&dev->lock);
-
-	return 0;
-}
-
-static int eth_stop(struct net_device *net)
-{
-	struct eth_dev	*dev = netdev_priv(net);
-	unsigned long	flags;
-
-	VDBG(dev, "%s\n", __func__);
-	netif_stop_queue(net);
-
-	DBG(dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld\n",
-		dev->net->stats.rx_packets, dev->net->stats.tx_packets,
-		dev->net->stats.rx_errors, dev->net->stats.tx_errors
-		);
-
-	/* ensure there are no more active requests */
-	spin_lock_irqsave(&dev->lock, flags);
-	if (dev->port_usb) {
-		struct gether	*link = dev->port_usb;
-
-		if (link->close)
-			link->close(link);
-
-		/* NOTE:  we have no abort-queue primitive we could use
-		 * to cancel all pending I/O.  Instead, we disable then
-		 * reenable the endpoints ... this idiom may leave toggle
-		 * wrong, but that's a self-correcting error.
-		 *
-		 * REVISIT:  we *COULD* just let the transfers complete at
-		 * their own pace; the network stack can handle old packets.
-		 * For the moment we leave this here, since it works.
-		 */
-		usb_ep_disable(link->in_ep);
-		usb_ep_disable(link->out_ep);
-		if (netif_carrier_ok(net)) {
-			DBG(dev, "host still using in/out endpoints\n");
-			usb_ep_enable(link->in_ep);
-			usb_ep_enable(link->out_ep);
-		}
-	}
-	spin_unlock_irqrestore(&dev->lock, flags);
-
-	return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* initial value, changed by "ifconfig usb0 hw ether xx:xx:xx:xx:xx:xx" */
-static char *dev_addr;
-module_param(dev_addr, charp, S_IRUGO);
-MODULE_PARM_DESC(dev_addr, "Device Ethernet Address");
-
-/* this address is invisible to ifconfig */
-static char *host_addr;
-module_param(host_addr, charp, S_IRUGO);
-MODULE_PARM_DESC(host_addr, "Host Ethernet Address");
-
-static int get_ether_addr(const char *str, u8 *dev_addr)
-{
-	if (str) {
-		unsigned	i;
-
-		for (i = 0; i < 6; i++) {
-			unsigned char num;
-
-			if ((*str == '.') || (*str == ':'))
-				str++;
-			num = hex_to_bin(*str++) << 4;
-			num |= hex_to_bin(*str++);
-			dev_addr [i] = num;
-		}
-		if (is_valid_ether_addr(dev_addr))
-			return 0;
-	}
-	eth_random_addr(dev_addr);
-	return 1;
-}
-
-static struct eth_dev *the_dev;
-
-static const struct net_device_ops eth_netdev_ops = {
-	.ndo_open		= eth_open,
-	.ndo_stop		= eth_stop,
-	.ndo_start_xmit		= eth_start_xmit,
-	.ndo_change_mtu		= ueth_change_mtu,
-	.ndo_set_mac_address 	= eth_mac_addr,
-	.ndo_validate_addr	= eth_validate_addr,
-};
-
-static struct device_type gadget_type = {
-	.name	= "gadget",
-};
-
-/**
- * gether_setup_name - initialize one ethernet-over-usb link
- * @g: gadget to associated with these links
- * @ethaddr: NULL, or a buffer in which the ethernet address of the
- *	host side of the link is recorded
- * @netname: name for network device (for example, "usb")
- * Context: may sleep
- *
- * This sets up the single network link that may be exported by a
- * gadget driver using this framework.  The link layer addresses are
- * set up using module parameters.
- *
- * Returns negative errno, or zero on success
- */
-int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
-		const char *netname)
-{
-	struct eth_dev		*dev;
-	struct net_device	*net;
-	int			status;
-
-	if (the_dev)
-		return -EBUSY;
-
-	net = alloc_etherdev(sizeof *dev);
-	if (!net)
-		return -ENOMEM;
-
-	dev = netdev_priv(net);
-	spin_lock_init(&dev->lock);
-	spin_lock_init(&dev->req_lock);
-	INIT_WORK(&dev->work, eth_work);
-	INIT_LIST_HEAD(&dev->tx_reqs);
-	INIT_LIST_HEAD(&dev->rx_reqs);
-
-	skb_queue_head_init(&dev->rx_frames);
-
-	/* network device setup */
-	dev->net = net;
-	snprintf(net->name, sizeof(net->name), "%s%%d", netname);
-
-	if (get_ether_addr(dev_addr, net->dev_addr))
-		dev_warn(&g->dev,
-			"using random %s ethernet address\n", "self");
-	if (get_ether_addr(host_addr, dev->host_mac))
-		dev_warn(&g->dev,
-			"using random %s ethernet address\n", "host");
-
-	if (ethaddr)
-		memcpy(ethaddr, dev->host_mac, ETH_ALEN);
-
-	net->netdev_ops = &eth_netdev_ops;
-
-	SET_ETHTOOL_OPS(net, &ops);
-
-	dev->gadget = g;
-	SET_NETDEV_DEV(net, &g->dev);
-	SET_NETDEV_DEVTYPE(net, &gadget_type);
-
-	status = register_netdev(net);
-	if (status < 0) {
-		dev_dbg(&g->dev, "register_netdev failed, %d\n", status);
-		free_netdev(net);
-	} else {
-		INFO(dev, "MAC %pM\n", net->dev_addr);
-		INFO(dev, "HOST MAC %pM\n", dev->host_mac);
-
-		the_dev = dev;
-
-		/* two kinds of host-initiated state changes:
-		 *  - iff DATA transfer is active, carrier is "on"
-		 *  - tx queueing enabled if open *and* carrier is "on"
-		 */
-		netif_carrier_off(net);
-	}
-
-	return status;
-}
-
-/**
- * gether_cleanup - remove Ethernet-over-USB device
- * Context: may sleep
- *
- * This is called to free all resources allocated by @gether_setup().
- */
-void gether_cleanup(void)
-{
-	if (!the_dev)
-		return;
-
-	unregister_netdev(the_dev->net);
-	flush_work(&the_dev->work);
-	free_netdev(the_dev->net);
-
-	the_dev = NULL;
-}
-
-
-/**
- * gether_connect - notify network layer that USB link is active
- * @link: the USB link, set up with endpoints, descriptors matching
- *	current device speed, and any framing wrapper(s) set up.
- * Context: irqs blocked
- *
- * This is called to activate endpoints and let the network layer know
- * the connection is active ("carrier detect").  It may cause the I/O
- * queues to open and start letting network packets flow, but will in
- * any case activate the endpoints so that they respond properly to the
- * USB host.
- *
- * Verify net_device pointer returned using IS_ERR().  If it doesn't
- * indicate some error code (negative errno), ep->driver_data values
- * have been overwritten.
- */
-struct net_device *gether_connect(struct gether *link)
-{
-	struct eth_dev		*dev = the_dev;
-	int			result = 0;
-
-	if (!dev)
-		return ERR_PTR(-EINVAL);
-
-	link->in_ep->driver_data = dev;
-	result = usb_ep_enable(link->in_ep);
-	if (result != 0) {
-		DBG(dev, "enable %s --> %d\n",
-			link->in_ep->name, result);
-		goto fail0;
-	}
-
-	link->out_ep->driver_data = dev;
-	result = usb_ep_enable(link->out_ep);
-	if (result != 0) {
-		DBG(dev, "enable %s --> %d\n",
-			link->out_ep->name, result);
-		goto fail1;
-	}
-
-	if (result == 0)
-		result = alloc_requests(dev, link, qlen(dev->gadget));
-
-	if (result == 0) {
-		dev->zlp = link->is_zlp_ok;
-		DBG(dev, "qlen %d\n", qlen(dev->gadget));
-
-		dev->header_len = link->header_len;
-		dev->unwrap = link->unwrap;
-		dev->wrap = link->wrap;
-
-		spin_lock(&dev->lock);
-		dev->port_usb = link;
-		link->ioport = dev;
-		if (netif_running(dev->net)) {
-			if (link->open)
-				link->open(link);
-		} else {
-			if (link->close)
-				link->close(link);
-		}
-		spin_unlock(&dev->lock);
-
-		netif_carrier_on(dev->net);
-		if (netif_running(dev->net))
-			eth_start(dev, GFP_ATOMIC);
-
-	/* on error, disable any endpoints  */
-	} else {
-		(void) usb_ep_disable(link->out_ep);
-fail1:
-		(void) usb_ep_disable(link->in_ep);
-	}
-fail0:
-	/* caller is responsible for cleanup on error */
-	if (result < 0)
-		return ERR_PTR(result);
-	return dev->net;
-}
-
-/**
- * gether_disconnect - notify network layer that USB link is inactive
- * @link: the USB link, on which gether_connect() was called
- * Context: irqs blocked
- *
- * This is called to deactivate endpoints and let the network layer know
- * the connection went inactive ("no carrier").
- *
- * On return, the state is as if gether_connect() had never been called.
- * The endpoints are inactive, and accordingly without active USB I/O.
- * Pointers to endpoint descriptors and endpoint private data are nulled.
- */
-void gether_disconnect(struct gether *link)
-{
-	struct eth_dev		*dev = link->ioport;
-	struct usb_request	*req;
-
-	WARN_ON(!dev);
-	if (!dev)
-		return;
-
-	DBG(dev, "%s\n", __func__);
-
-	netif_stop_queue(dev->net);
-	netif_carrier_off(dev->net);
-
-	/* disable endpoints, forcing (synchronous) completion
-	 * of all pending i/o.  then free the request objects
-	 * and forget about the endpoints.
-	 */
-	usb_ep_disable(link->in_ep);
-	spin_lock(&dev->req_lock);
-	while (!list_empty(&dev->tx_reqs)) {
-		req = container_of(dev->tx_reqs.next,
-					struct usb_request, list);
-		list_del(&req->list);
-
-		spin_unlock(&dev->req_lock);
-		usb_ep_free_request(link->in_ep, req);
-		spin_lock(&dev->req_lock);
-	}
-	spin_unlock(&dev->req_lock);
-	link->in_ep->driver_data = NULL;
-	link->in_ep->desc = NULL;
-
-	usb_ep_disable(link->out_ep);
-	spin_lock(&dev->req_lock);
-	while (!list_empty(&dev->rx_reqs)) {
-		req = container_of(dev->rx_reqs.next,
-					struct usb_request, list);
-		list_del(&req->list);
-
-		spin_unlock(&dev->req_lock);
-		usb_ep_free_request(link->out_ep, req);
-		spin_lock(&dev->req_lock);
-	}
-	spin_unlock(&dev->req_lock);
-	link->out_ep->driver_data = NULL;
-	link->out_ep->desc = NULL;
-
-	/* finish forgetting about this USB link episode */
-	dev->header_len = 0;
-	dev->unwrap = NULL;
-	dev->wrap = NULL;
-
-	spin_lock(&dev->lock);
-	dev->port_usb = NULL;
-	link->ioport = NULL;
-	spin_unlock(&dev->lock);
-}
diff --git a/drivers/staging/ccg/u_ether.h b/drivers/staging/ccg/u_ether.h
deleted file mode 100644
index 6f4a162..0000000
--- a/drivers/staging/ccg/u_ether.h
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * u_ether.h -- interface to USB gadget "ethernet link" utilities
- *
- * Copyright (C) 2003-2005,2008 David Brownell
- * Copyright (C) 2003-2004 Robert Schwebel, Benedikt Spranger
- * Copyright (C) 2008 Nokia Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __U_ETHER_H
-#define __U_ETHER_H
-
-#include <linux/err.h>
-#include <linux/if_ether.h>
-#include <linux/usb/composite.h>
-#include <linux/usb/cdc.h>
-
-#include "gadget_chips.h"
-
-
-/*
- * This represents the USB side of an "ethernet" link, managed by a USB
- * function which provides control and (maybe) framing.  Two functions
- * in different configurations could share the same ethernet link/netdev,
- * using different host interaction models.
- *
- * There is a current limitation that only one instance of this link may
- * be present in any given configuration.  When that's a problem, network
- * layer facilities can be used to package multiple logical links on this
- * single "physical" one.
- */
-struct gether {
-	struct usb_function		func;
-
-	/* updated by gether_{connect,disconnect} */
-	struct eth_dev			*ioport;
-
-	/* endpoints handle full and/or high speeds */
-	struct usb_ep			*in_ep;
-	struct usb_ep			*out_ep;
-
-	bool				is_zlp_ok;
-
-	u16				cdc_filter;
-
-	/* hooks for added framing, as needed for RNDIS and EEM. */
-	u32				header_len;
-	/* NCM requires fixed size bundles */
-	bool				is_fixed;
-	u32				fixed_out_len;
-	u32				fixed_in_len;
-	struct sk_buff			*(*wrap)(struct gether *port,
-						struct sk_buff *skb);
-	int				(*unwrap)(struct gether *port,
-						struct sk_buff *skb,
-						struct sk_buff_head *list);
-
-	/* called on network open/close */
-	void				(*open)(struct gether *);
-	void				(*close)(struct gether *);
-};
-
-#define	DEFAULT_FILTER	(USB_CDC_PACKET_TYPE_BROADCAST \
-			|USB_CDC_PACKET_TYPE_ALL_MULTICAST \
-			|USB_CDC_PACKET_TYPE_PROMISCUOUS \
-			|USB_CDC_PACKET_TYPE_DIRECTED)
-
-/* variant of gether_setup that allows customizing network device name */
-int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
-		const char *netname);
-
-/* netdev setup/teardown as directed by the gadget driver */
-/* gether_setup - initialize one ethernet-over-usb link
- * @g: gadget to associated with these links
- * @ethaddr: NULL, or a buffer in which the ethernet address of the
- *	host side of the link is recorded
- * Context: may sleep
- *
- * This sets up the single network link that may be exported by a
- * gadget driver using this framework.  The link layer addresses are
- * set up using module parameters.
- *
- * Returns negative errno, or zero on success
- */
-static inline int gether_setup(struct usb_gadget *g, u8 ethaddr[ETH_ALEN])
-{
-	return gether_setup_name(g, ethaddr, "usb");
-}
-
-void gether_cleanup(void);
-
-/* connect/disconnect is handled by individual functions */
-struct net_device *gether_connect(struct gether *);
-void gether_disconnect(struct gether *);
-
-/* Some controllers can't support CDC Ethernet (ECM) ... */
-static inline bool can_support_ecm(struct usb_gadget *gadget)
-{
-	if (!gadget_supports_altsettings(gadget))
-		return false;
-
-	/* Everything else is *presumably* fine ... but this is a bit
-	 * chancy, so be **CERTAIN** there are no hardware issues with
-	 * your controller.  Add it above if it can't handle CDC.
-	 */
-	return true;
-}
-
-/* each configuration may bind one instance of an ethernet link */
-int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]);
-int ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]);
-int ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]);
-int eem_bind_config(struct usb_configuration *c);
-
-#ifdef USB_ETH_RNDIS
-
-int rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
-				u32 vendorID, const char *manufacturer);
-
-#else
-
-static inline int
-rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
-				u32 vendorID, const char *manufacturer)
-{
-	return 0;
-}
-
-#endif
-
-/**
- * rndis_bind_config - add RNDIS network link to a configuration
- * @c: the configuration to support the network link
- * @ethaddr: a buffer in which the ethernet address of the host side
- *	side of the link was recorded
- * Context: single threaded during gadget setup
- *
- * Returns zero on success, else negative errno.
- *
- * Caller must have called @gether_setup().  Caller is also responsible
- * for calling @gether_cleanup() before module unload.
- */
-static inline int rndis_bind_config(struct usb_configuration *c,
-				    u8 ethaddr[ETH_ALEN])
-{
-	return rndis_bind_config_vendor(c, ethaddr, 0, NULL);
-}
-
-
-#endif /* __U_ETHER_H */
diff --git a/drivers/staging/ccg/u_serial.c b/drivers/staging/ccg/u_serial.c
deleted file mode 100644
index b10947a..0000000
--- a/drivers/staging/ccg/u_serial.c
+++ /dev/null
@@ -1,1339 +0,0 @@
-/*
- * u_serial.c - utilities for USB gadget "serial port"/TTY support
- *
- * Copyright (C) 2003 Al Borchers (alborchers@steinerpoint.com)
- * Copyright (C) 2008 David Brownell
- * Copyright (C) 2008 by Nokia Corporation
- *
- * This code also borrows from usbserial.c, which is
- * Copyright (C) 1999 - 2002 Greg Kroah-Hartman (greg@kroah.com)
- * Copyright (C) 2000 Peter Berger (pberger@brimson.com)
- * Copyright (C) 2000 Al Borchers (alborchers@steinerpoint.com)
- *
- * This software is distributed under the terms of the GNU General
- * Public License ("GPL") as published by the Free Software Foundation,
- * either version 2 of that License or (at your option) any later version.
- */
-
-/* #define VERBOSE_DEBUG */
-
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/device.h>
-#include <linux/delay.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/slab.h>
-#include <linux/export.h>
-
-#include "u_serial.h"
-
-
-/*
- * This component encapsulates the TTY layer glue needed to provide basic
- * "serial port" functionality through the USB gadget stack.  Each such
- * port is exposed through a /dev/ttyGS* node.
- *
- * After initialization (gserial_setup), these TTY port devices stay
- * available until they are removed (gserial_cleanup).  Each one may be
- * connected to a USB function (gserial_connect), or disconnected (with
- * gserial_disconnect) when the USB host issues a config change event.
- * Data can only flow when the port is connected to the host.
- *
- * A given TTY port can be made available in multiple configurations.
- * For example, each one might expose a ttyGS0 node which provides a
- * login application.  In one case that might use CDC ACM interface 0,
- * while another configuration might use interface 3 for that.  The
- * work to handle that (including descriptor management) is not part
- * of this component.
- *
- * Configurations may expose more than one TTY port.  For example, if
- * ttyGS0 provides login service, then ttyGS1 might provide dialer access
- * for a telephone or fax link.  And ttyGS2 might be something that just
- * needs a simple byte stream interface for some messaging protocol that
- * is managed in userspace ... OBEX, PTP, and MTP have been mentioned.
- */
-
-#define PREFIX	"ttyGS"
-
-/*
- * gserial is the lifecycle interface, used by USB functions
- * gs_port is the I/O nexus, used by the tty driver
- * tty_struct links to the tty/filesystem framework
- *
- * gserial <---> gs_port ... links will be null when the USB link is
- * inactive; managed by gserial_{connect,disconnect}().  each gserial
- * instance can wrap its own USB control protocol.
- *	gserial->ioport == usb_ep->driver_data ... gs_port
- *	gs_port->port_usb ... gserial
- *
- * gs_port <---> tty_struct ... links will be null when the TTY file
- * isn't opened; managed by gs_open()/gs_close()
- *	gserial->port_tty ... tty_struct
- *	tty_struct->driver_data ... gserial
- */
-
-/* RX and TX queues can buffer QUEUE_SIZE packets before they hit the
- * next layer of buffering.  For TX that's a circular buffer; for RX
- * consider it a NOP.  A third layer is provided by the TTY code.
- */
-#define QUEUE_SIZE		16
-#define WRITE_BUF_SIZE		8192		/* TX only */
-
-/* circular buffer */
-struct gs_buf {
-	unsigned		buf_size;
-	char			*buf_buf;
-	char			*buf_get;
-	char			*buf_put;
-};
-
-/*
- * The port structure holds info for each port, one for each minor number
- * (and thus for each /dev/ node).
- */
-struct gs_port {
-	struct tty_port		port;
-	spinlock_t		port_lock;	/* guard port_* access */
-
-	struct gserial		*port_usb;
-
-	bool			openclose;	/* open/close in progress */
-	u8			port_num;
-
-	struct list_head	read_pool;
-	int read_started;
-	int read_allocated;
-	struct list_head	read_queue;
-	unsigned		n_read;
-	struct tasklet_struct	push;
-
-	struct list_head	write_pool;
-	int write_started;
-	int write_allocated;
-	struct gs_buf		port_write_buf;
-	wait_queue_head_t	drain_wait;	/* wait while writes drain */
-
-	/* REVISIT this state ... */
-	struct usb_cdc_line_coding port_line_coding;	/* 8-N-1 etc */
-};
-
-/* increase N_PORTS if you need more */
-#define N_PORTS		4
-static struct portmaster {
-	struct mutex	lock;			/* protect open/close */
-	struct gs_port	*port;
-} ports[N_PORTS];
-static unsigned	n_ports;
-
-#define GS_CLOSE_TIMEOUT		15		/* seconds */
-
-
-
-#ifdef VERBOSE_DEBUG
-#define pr_vdebug(fmt, arg...) \
-	pr_debug(fmt, ##arg)
-#else
-#define pr_vdebug(fmt, arg...) \
-	({ if (0) pr_debug(fmt, ##arg); })
-#endif
-
-/*-------------------------------------------------------------------------*/
-
-/* Circular Buffer */
-
-/*
- * gs_buf_alloc
- *
- * Allocate a circular buffer and all associated memory.
- */
-static int gs_buf_alloc(struct gs_buf *gb, unsigned size)
-{
-	gb->buf_buf = kmalloc(size, GFP_KERNEL);
-	if (gb->buf_buf == NULL)
-		return -ENOMEM;
-
-	gb->buf_size = size;
-	gb->buf_put = gb->buf_buf;
-	gb->buf_get = gb->buf_buf;
-
-	return 0;
-}
-
-/*
- * gs_buf_free
- *
- * Free the buffer and all associated memory.
- */
-static void gs_buf_free(struct gs_buf *gb)
-{
-	kfree(gb->buf_buf);
-	gb->buf_buf = NULL;
-}
-
-/*
- * gs_buf_clear
- *
- * Clear out all data in the circular buffer.
- */
-static void gs_buf_clear(struct gs_buf *gb)
-{
-	gb->buf_get = gb->buf_put;
-	/* equivalent to a get of all data available */
-}
-
-/*
- * gs_buf_data_avail
- *
- * Return the number of bytes of data written into the circular
- * buffer.
- */
-static unsigned gs_buf_data_avail(struct gs_buf *gb)
-{
-	return (gb->buf_size + gb->buf_put - gb->buf_get) % gb->buf_size;
-}
-
-/*
- * gs_buf_space_avail
- *
- * Return the number of bytes of space available in the circular
- * buffer.
- */
-static unsigned gs_buf_space_avail(struct gs_buf *gb)
-{
-	return (gb->buf_size + gb->buf_get - gb->buf_put - 1) % gb->buf_size;
-}
-
-/*
- * gs_buf_put
- *
- * Copy data data from a user buffer and put it into the circular buffer.
- * Restrict to the amount of space available.
- *
- * Return the number of bytes copied.
- */
-static unsigned
-gs_buf_put(struct gs_buf *gb, const char *buf, unsigned count)
-{
-	unsigned len;
-
-	len  = gs_buf_space_avail(gb);
-	if (count > len)
-		count = len;
-
-	if (count == 0)
-		return 0;
-
-	len = gb->buf_buf + gb->buf_size - gb->buf_put;
-	if (count > len) {
-		memcpy(gb->buf_put, buf, len);
-		memcpy(gb->buf_buf, buf+len, count - len);
-		gb->buf_put = gb->buf_buf + count - len;
-	} else {
-		memcpy(gb->buf_put, buf, count);
-		if (count < len)
-			gb->buf_put += count;
-		else /* count == len */
-			gb->buf_put = gb->buf_buf;
-	}
-
-	return count;
-}
-
-/*
- * gs_buf_get
- *
- * Get data from the circular buffer and copy to the given buffer.
- * Restrict to the amount of data available.
- *
- * Return the number of bytes copied.
- */
-static unsigned
-gs_buf_get(struct gs_buf *gb, char *buf, unsigned count)
-{
-	unsigned len;
-
-	len = gs_buf_data_avail(gb);
-	if (count > len)
-		count = len;
-
-	if (count == 0)
-		return 0;
-
-	len = gb->buf_buf + gb->buf_size - gb->buf_get;
-	if (count > len) {
-		memcpy(buf, gb->buf_get, len);
-		memcpy(buf+len, gb->buf_buf, count - len);
-		gb->buf_get = gb->buf_buf + count - len;
-	} else {
-		memcpy(buf, gb->buf_get, count);
-		if (count < len)
-			gb->buf_get += count;
-		else /* count == len */
-			gb->buf_get = gb->buf_buf;
-	}
-
-	return count;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* I/O glue between TTY (upper) and USB function (lower) driver layers */
-
-/*
- * gs_alloc_req
- *
- * Allocate a usb_request and its buffer.  Returns a pointer to the
- * usb_request or NULL if there is an error.
- */
-struct usb_request *
-gs_alloc_req(struct usb_ep *ep, unsigned len, gfp_t kmalloc_flags)
-{
-	struct usb_request *req;
-
-	req = usb_ep_alloc_request(ep, kmalloc_flags);
-
-	if (req != NULL) {
-		req->length = len;
-		req->buf = kmalloc(len, kmalloc_flags);
-		if (req->buf == NULL) {
-			usb_ep_free_request(ep, req);
-			return NULL;
-		}
-	}
-
-	return req;
-}
-
-/*
- * gs_free_req
- *
- * Free a usb_request and its buffer.
- */
-void gs_free_req(struct usb_ep *ep, struct usb_request *req)
-{
-	kfree(req->buf);
-	usb_ep_free_request(ep, req);
-}
-
-/*
- * gs_send_packet
- *
- * If there is data to send, a packet is built in the given
- * buffer and the size is returned.  If there is no data to
- * send, 0 is returned.
- *
- * Called with port_lock held.
- */
-static unsigned
-gs_send_packet(struct gs_port *port, char *packet, unsigned size)
-{
-	unsigned len;
-
-	len = gs_buf_data_avail(&port->port_write_buf);
-	if (len < size)
-		size = len;
-	if (size != 0)
-		size = gs_buf_get(&port->port_write_buf, packet, size);
-	return size;
-}
-
-/*
- * gs_start_tx
- *
- * This function finds available write requests, calls
- * gs_send_packet to fill these packets with data, and
- * continues until either there are no more write requests
- * available or no more data to send.  This function is
- * run whenever data arrives or write requests are available.
- *
- * Context: caller owns port_lock; port_usb is non-null.
- */
-static int gs_start_tx(struct gs_port *port)
-/*
-__releases(&port->port_lock)
-__acquires(&port->port_lock)
-*/
-{
-	struct list_head	*pool = &port->write_pool;
-	struct usb_ep		*in = port->port_usb->in;
-	int			status = 0;
-	bool			do_tty_wake = false;
-
-	while (!list_empty(pool)) {
-		struct usb_request	*req;
-		int			len;
-
-		if (port->write_started >= QUEUE_SIZE)
-			break;
-
-		req = list_entry(pool->next, struct usb_request, list);
-		len = gs_send_packet(port, req->buf, in->maxpacket);
-		if (len == 0) {
-			wake_up_interruptible(&port->drain_wait);
-			break;
-		}
-		do_tty_wake = true;
-
-		req->length = len;
-		list_del(&req->list);
-		req->zero = (gs_buf_data_avail(&port->port_write_buf) == 0);
-
-		pr_vdebug(PREFIX "%d: tx len=%d, 0x%02x 0x%02x 0x%02x ...\n",
-				port->port_num, len, *((u8 *)req->buf),
-				*((u8 *)req->buf+1), *((u8 *)req->buf+2));
-
-		/* Drop lock while we call out of driver; completions
-		 * could be issued while we do so.  Disconnection may
-		 * happen too; maybe immediately before we queue this!
-		 *
-		 * NOTE that we may keep sending data for a while after
-		 * the TTY closed (dev->ioport->port_tty is NULL).
-		 */
-		spin_unlock(&port->port_lock);
-		status = usb_ep_queue(in, req, GFP_ATOMIC);
-		spin_lock(&port->port_lock);
-
-		if (status) {
-			pr_debug("%s: %s %s err %d\n",
-					__func__, "queue", in->name, status);
-			list_add(&req->list, pool);
-			break;
-		}
-
-		port->write_started++;
-
-		/* abort immediately after disconnect */
-		if (!port->port_usb)
-			break;
-	}
-
-	if (do_tty_wake && port->port.tty)
-		tty_wakeup(port->port.tty);
-	return status;
-}
-
-/*
- * Context: caller owns port_lock, and port_usb is set
- */
-static unsigned gs_start_rx(struct gs_port *port)
-/*
-__releases(&port->port_lock)
-__acquires(&port->port_lock)
-*/
-{
-	struct list_head	*pool = &port->read_pool;
-	struct usb_ep		*out = port->port_usb->out;
-
-	while (!list_empty(pool)) {
-		struct usb_request	*req;
-		int			status;
-		struct tty_struct	*tty;
-
-		/* no more rx if closed */
-		tty = port->port.tty;
-		if (!tty)
-			break;
-
-		if (port->read_started >= QUEUE_SIZE)
-			break;
-
-		req = list_entry(pool->next, struct usb_request, list);
-		list_del(&req->list);
-		req->length = out->maxpacket;
-
-		/* drop lock while we call out; the controller driver
-		 * may need to call us back (e.g. for disconnect)
-		 */
-		spin_unlock(&port->port_lock);
-		status = usb_ep_queue(out, req, GFP_ATOMIC);
-		spin_lock(&port->port_lock);
-
-		if (status) {
-			pr_debug("%s: %s %s err %d\n",
-					__func__, "queue", out->name, status);
-			list_add(&req->list, pool);
-			break;
-		}
-		port->read_started++;
-
-		/* abort immediately after disconnect */
-		if (!port->port_usb)
-			break;
-	}
-	return port->read_started;
-}
-
-/*
- * RX tasklet takes data out of the RX queue and hands it up to the TTY
- * layer until it refuses to take any more data (or is throttled back).
- * Then it issues reads for any further data.
- *
- * If the RX queue becomes full enough that no usb_request is queued,
- * the OUT endpoint may begin NAKing as soon as its FIFO fills up.
- * So QUEUE_SIZE packets plus however many the FIFO holds (usually two)
- * can be buffered before the TTY layer's buffers (currently 64 KB).
- */
-static void gs_rx_push(unsigned long _port)
-{
-	struct gs_port		*port = (void *)_port;
-	struct tty_struct	*tty;
-	struct list_head	*queue = &port->read_queue;
-	bool			disconnect = false;
-	bool			do_push = false;
-
-	/* hand any queued data to the tty */
-	spin_lock_irq(&port->port_lock);
-	tty = port->port.tty;
-	while (!list_empty(queue)) {
-		struct usb_request	*req;
-
-		req = list_first_entry(queue, struct usb_request, list);
-
-		/* leave data queued if tty was rx throttled */
-		if (tty && test_bit(TTY_THROTTLED, &tty->flags))
-			break;
-
-		switch (req->status) {
-		case -ESHUTDOWN:
-			disconnect = true;
-			pr_vdebug(PREFIX "%d: shutdown\n", port->port_num);
-			break;
-
-		default:
-			/* presumably a transient fault */
-			pr_warning(PREFIX "%d: unexpected RX status %d\n",
-					port->port_num, req->status);
-			/* FALLTHROUGH */
-		case 0:
-			/* normal completion */
-			break;
-		}
-
-		/* push data to (open) tty */
-		if (req->actual) {
-			char		*packet = req->buf;
-			unsigned	size = req->actual;
-			unsigned	n;
-			int		count;
-
-			/* we may have pushed part of this packet already... */
-			n = port->n_read;
-			if (n) {
-				packet += n;
-				size -= n;
-			}
-
-			count = tty_insert_flip_string(&port->port, packet, size);
-			if (count)
-				do_push = true;
-			if (count != size) {
-				/* stop pushing; TTY layer can't handle more */
-				port->n_read += count;
-				pr_vdebug(PREFIX "%d: rx block %d/%d\n",
-						port->port_num,
-						count, req->actual);
-				break;
-			}
-			port->n_read = 0;
-		}
-		list_move(&req->list, &port->read_pool);
-		port->read_started--;
-	}
-
-	/* Push from tty to ldisc; without low_latency set this is handled by
-	 * a workqueue, so we won't get callbacks and can hold port_lock
-	 */
-	if (do_push)
-		tty_flip_buffer_push(&port->port);
-
-
-	/* We want our data queue to become empty ASAP, keeping data
-	 * in the tty and ldisc (not here).  If we couldn't push any
-	 * this time around, there may be trouble unless there's an
-	 * implicit tty_unthrottle() call on its way...
-	 *
-	 * REVISIT we should probably add a timer to keep the tasklet
-	 * from starving ... but it's not clear that case ever happens.
-	 */
-	if (!list_empty(queue) && tty) {
-		if (!test_bit(TTY_THROTTLED, &tty->flags)) {
-			if (do_push)
-				tasklet_schedule(&port->push);
-			else
-				pr_warning(PREFIX "%d: RX not scheduled?\n",
-					port->port_num);
-		}
-	}
-
-	/* If we're still connected, refill the USB RX queue. */
-	if (!disconnect && port->port_usb)
-		gs_start_rx(port);
-
-	spin_unlock_irq(&port->port_lock);
-}
-
-static void gs_read_complete(struct usb_ep *ep, struct usb_request *req)
-{
-	struct gs_port	*port = ep->driver_data;
-
-	/* Queue all received data until the tty layer is ready for it. */
-	spin_lock(&port->port_lock);
-	list_add_tail(&req->list, &port->read_queue);
-	tasklet_schedule(&port->push);
-	spin_unlock(&port->port_lock);
-}
-
-static void gs_write_complete(struct usb_ep *ep, struct usb_request *req)
-{
-	struct gs_port	*port = ep->driver_data;
-
-	spin_lock(&port->port_lock);
-	list_add(&req->list, &port->write_pool);
-	port->write_started--;
-
-	switch (req->status) {
-	default:
-		/* presumably a transient fault */
-		pr_warning("%s: unexpected %s status %d\n",
-				__func__, ep->name, req->status);
-		/* FALL THROUGH */
-	case 0:
-		/* normal completion */
-		gs_start_tx(port);
-		break;
-
-	case -ESHUTDOWN:
-		/* disconnect */
-		pr_vdebug("%s: %s shutdown\n", __func__, ep->name);
-		break;
-	}
-
-	spin_unlock(&port->port_lock);
-}
-
-static void gs_free_requests(struct usb_ep *ep, struct list_head *head,
-							 int *allocated)
-{
-	struct usb_request	*req;
-
-	while (!list_empty(head)) {
-		req = list_entry(head->next, struct usb_request, list);
-		list_del(&req->list);
-		gs_free_req(ep, req);
-		if (allocated)
-			(*allocated)--;
-	}
-}
-
-static int gs_alloc_requests(struct usb_ep *ep, struct list_head *head,
-		void (*fn)(struct usb_ep *, struct usb_request *),
-		int *allocated)
-{
-	int			i;
-	struct usb_request	*req;
-	int n = allocated ? QUEUE_SIZE - *allocated : QUEUE_SIZE;
-
-	/* Pre-allocate up to QUEUE_SIZE transfers, but if we can't
-	 * do quite that many this time, don't fail ... we just won't
-	 * be as speedy as we might otherwise be.
-	 */
-	for (i = 0; i < n; i++) {
-		req = gs_alloc_req(ep, ep->maxpacket, GFP_ATOMIC);
-		if (!req)
-			return list_empty(head) ? -ENOMEM : 0;
-		req->complete = fn;
-		list_add_tail(&req->list, head);
-		if (allocated)
-			(*allocated)++;
-	}
-	return 0;
-}
-
-/**
- * gs_start_io - start USB I/O streams
- * @dev: encapsulates endpoints to use
- * Context: holding port_lock; port_tty and port_usb are non-null
- *
- * We only start I/O when something is connected to both sides of
- * this port.  If nothing is listening on the host side, we may
- * be pointlessly filling up our TX buffers and FIFO.
- */
-static int gs_start_io(struct gs_port *port)
-{
-	struct list_head	*head = &port->read_pool;
-	struct usb_ep		*ep = port->port_usb->out;
-	int			status;
-	unsigned		started;
-
-	/* Allocate RX and TX I/O buffers.  We can't easily do this much
-	 * earlier (with GFP_KERNEL) because the requests are coupled to
-	 * endpoints, as are the packet sizes we'll be using.  Different
-	 * configurations may use different endpoints with a given port;
-	 * and high speed vs full speed changes packet sizes too.
-	 */
-	status = gs_alloc_requests(ep, head, gs_read_complete,
-		&port->read_allocated);
-	if (status)
-		return status;
-
-	status = gs_alloc_requests(port->port_usb->in, &port->write_pool,
-			gs_write_complete, &port->write_allocated);
-	if (status) {
-		gs_free_requests(ep, head, &port->read_allocated);
-		return status;
-	}
-
-	/* queue read requests */
-	port->n_read = 0;
-	started = gs_start_rx(port);
-
-	/* unblock any pending writes into our circular buffer */
-	if (started) {
-		tty_wakeup(port->port.tty);
-	} else {
-		gs_free_requests(ep, head, &port->read_allocated);
-		gs_free_requests(port->port_usb->in, &port->write_pool,
-			&port->write_allocated);
-		status = -EIO;
-	}
-
-	return status;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* TTY Driver */
-
-/*
- * gs_open sets up the link between a gs_port and its associated TTY.
- * That link is broken *only* by TTY close(), and all driver methods
- * know that.
- */
-static int gs_open(struct tty_struct *tty, struct file *file)
-{
-	int		port_num = tty->index;
-	struct gs_port	*port;
-	int		status;
-
-	do {
-		mutex_lock(&ports[port_num].lock);
-		port = ports[port_num].port;
-		if (!port)
-			status = -ENODEV;
-		else {
-			spin_lock_irq(&port->port_lock);
-
-			/* already open?  Great. */
-			if (port->port.count) {
-				status = 0;
-				port->port.count++;
-
-			/* currently opening/closing? wait ... */
-			} else if (port->openclose) {
-				status = -EBUSY;
-
-			/* ... else we do the work */
-			} else {
-				status = -EAGAIN;
-				port->openclose = true;
-			}
-			spin_unlock_irq(&port->port_lock);
-		}
-		mutex_unlock(&ports[port_num].lock);
-
-		switch (status) {
-		default:
-			/* fully handled */
-			return status;
-		case -EAGAIN:
-			/* must do the work */
-			break;
-		case -EBUSY:
-			/* wait for EAGAIN task to finish */
-			msleep(1);
-			/* REVISIT could have a waitchannel here, if
-			 * concurrent open performance is important
-			 */
-			break;
-		}
-	} while (status != -EAGAIN);
-
-	/* Do the "real open" */
-	spin_lock_irq(&port->port_lock);
-
-	/* allocate circular buffer on first open */
-	if (port->port_write_buf.buf_buf == NULL) {
-
-		spin_unlock_irq(&port->port_lock);
-		status = gs_buf_alloc(&port->port_write_buf, WRITE_BUF_SIZE);
-		spin_lock_irq(&port->port_lock);
-
-		if (status) {
-			pr_debug("gs_open: ttyGS%d (%p,%p) no buffer\n",
-				port->port_num, tty, file);
-			port->openclose = false;
-			goto exit_unlock_port;
-		}
-	}
-
-	/* REVISIT if REMOVED (ports[].port NULL), abort the open
-	 * to let rmmod work faster (but this way isn't wrong).
-	 */
-
-	/* REVISIT maybe wait for "carrier detect" */
-
-	tty->driver_data = port;
-	port->port.tty = tty;
-
-	port->port.count = 1;
-	port->openclose = false;
-
-	/* if connected, start the I/O stream */
-	if (port->port_usb) {
-		struct gserial	*gser = port->port_usb;
-
-		pr_debug("gs_open: start ttyGS%d\n", port->port_num);
-		gs_start_io(port);
-
-		if (gser->connect)
-			gser->connect(gser);
-	}
-
-	pr_debug("gs_open: ttyGS%d (%p,%p)\n", port->port_num, tty, file);
-
-	status = 0;
-
-exit_unlock_port:
-	spin_unlock_irq(&port->port_lock);
-	return status;
-}
-
-static int gs_writes_finished(struct gs_port *p)
-{
-	int cond;
-
-	/* return true on disconnect or empty buffer */
-	spin_lock_irq(&p->port_lock);
-	cond = (p->port_usb == NULL) || !gs_buf_data_avail(&p->port_write_buf);
-	spin_unlock_irq(&p->port_lock);
-
-	return cond;
-}
-
-static void gs_close(struct tty_struct *tty, struct file *file)
-{
-	struct gs_port *port = tty->driver_data;
-	struct gserial	*gser;
-
-	spin_lock_irq(&port->port_lock);
-
-	if (port->port.count != 1) {
-		if (port->port.count == 0)
-			WARN_ON(1);
-		else
-			--port->port.count;
-		goto exit;
-	}
-
-	pr_debug("gs_close: ttyGS%d (%p,%p) ...\n", port->port_num, tty, file);
-
-	/* mark port as closing but in use; we can drop port lock
-	 * and sleep if necessary
-	 */
-	port->openclose = true;
-	port->port.count = 0;
-
-	gser = port->port_usb;
-	if (gser && gser->disconnect)
-		gser->disconnect(gser);
-
-	/* wait for circular write buffer to drain, disconnect, or at
-	 * most GS_CLOSE_TIMEOUT seconds; then discard the rest
-	 */
-	if (gs_buf_data_avail(&port->port_write_buf) > 0 && gser) {
-		spin_unlock_irq(&port->port_lock);
-		wait_event_interruptible_timeout(port->drain_wait,
-					gs_writes_finished(port),
-					GS_CLOSE_TIMEOUT * HZ);
-		spin_lock_irq(&port->port_lock);
-		gser = port->port_usb;
-	}
-
-	/* Iff we're disconnected, there can be no I/O in flight so it's
-	 * ok to free the circular buffer; else just scrub it.  And don't
-	 * let the push tasklet fire again until we're re-opened.
-	 */
-	if (gser == NULL)
-		gs_buf_free(&port->port_write_buf);
-	else
-		gs_buf_clear(&port->port_write_buf);
-
-	tty->driver_data = NULL;
-	port->port.tty = NULL;
-
-	port->openclose = false;
-
-	pr_debug("gs_close: ttyGS%d (%p,%p) done!\n",
-			port->port_num, tty, file);
-
-	wake_up_interruptible(&port->port.close_wait);
-exit:
-	spin_unlock_irq(&port->port_lock);
-}
-
-static int gs_write(struct tty_struct *tty, const unsigned char *buf, int count)
-{
-	struct gs_port	*port = tty->driver_data;
-	unsigned long	flags;
-	int		status;
-
-	pr_vdebug("gs_write: ttyGS%d (%p) writing %d bytes\n",
-			port->port_num, tty, count);
-
-	spin_lock_irqsave(&port->port_lock, flags);
-	if (count)
-		count = gs_buf_put(&port->port_write_buf, buf, count);
-	/* treat count == 0 as flush_chars() */
-	if (port->port_usb)
-		status = gs_start_tx(port);
-	spin_unlock_irqrestore(&port->port_lock, flags);
-
-	return count;
-}
-
-static int gs_put_char(struct tty_struct *tty, unsigned char ch)
-{
-	struct gs_port	*port = tty->driver_data;
-	unsigned long	flags;
-	int		status;
-
-	pr_vdebug("gs_put_char: (%d,%p) char=0x%x, called from %pf\n",
-		port->port_num, tty, ch, __builtin_return_address(0));
-
-	spin_lock_irqsave(&port->port_lock, flags);
-	status = gs_buf_put(&port->port_write_buf, &ch, 1);
-	spin_unlock_irqrestore(&port->port_lock, flags);
-
-	return status;
-}
-
-static void gs_flush_chars(struct tty_struct *tty)
-{
-	struct gs_port	*port = tty->driver_data;
-	unsigned long	flags;
-
-	pr_vdebug("gs_flush_chars: (%d,%p)\n", port->port_num, tty);
-
-	spin_lock_irqsave(&port->port_lock, flags);
-	if (port->port_usb)
-		gs_start_tx(port);
-	spin_unlock_irqrestore(&port->port_lock, flags);
-}
-
-static int gs_write_room(struct tty_struct *tty)
-{
-	struct gs_port	*port = tty->driver_data;
-	unsigned long	flags;
-	int		room = 0;
-
-	spin_lock_irqsave(&port->port_lock, flags);
-	if (port->port_usb)
-		room = gs_buf_space_avail(&port->port_write_buf);
-	spin_unlock_irqrestore(&port->port_lock, flags);
-
-	pr_vdebug("gs_write_room: (%d,%p) room=%d\n",
-		port->port_num, tty, room);
-
-	return room;
-}
-
-static int gs_chars_in_buffer(struct tty_struct *tty)
-{
-	struct gs_port	*port = tty->driver_data;
-	unsigned long	flags;
-	int		chars = 0;
-
-	spin_lock_irqsave(&port->port_lock, flags);
-	chars = gs_buf_data_avail(&port->port_write_buf);
-	spin_unlock_irqrestore(&port->port_lock, flags);
-
-	pr_vdebug("gs_chars_in_buffer: (%d,%p) chars=%d\n",
-		port->port_num, tty, chars);
-
-	return chars;
-}
-
-/* undo side effects of setting TTY_THROTTLED */
-static void gs_unthrottle(struct tty_struct *tty)
-{
-	struct gs_port		*port = tty->driver_data;
-	unsigned long		flags;
-
-	spin_lock_irqsave(&port->port_lock, flags);
-	if (port->port_usb) {
-		/* Kickstart read queue processing.  We don't do xon/xoff,
-		 * rts/cts, or other handshaking with the host, but if the
-		 * read queue backs up enough we'll be NAKing OUT packets.
-		 */
-		tasklet_schedule(&port->push);
-		pr_vdebug(PREFIX "%d: unthrottle\n", port->port_num);
-	}
-	spin_unlock_irqrestore(&port->port_lock, flags);
-}
-
-static int gs_break_ctl(struct tty_struct *tty, int duration)
-{
-	struct gs_port	*port = tty->driver_data;
-	int		status = 0;
-	struct gserial	*gser;
-
-	pr_vdebug("gs_break_ctl: ttyGS%d, send break (%d) \n",
-			port->port_num, duration);
-
-	spin_lock_irq(&port->port_lock);
-	gser = port->port_usb;
-	if (gser && gser->send_break)
-		status = gser->send_break(gser, duration);
-	spin_unlock_irq(&port->port_lock);
-
-	return status;
-}
-
-static const struct tty_operations gs_tty_ops = {
-	.open =			gs_open,
-	.close =		gs_close,
-	.write =		gs_write,
-	.put_char =		gs_put_char,
-	.flush_chars =		gs_flush_chars,
-	.write_room =		gs_write_room,
-	.chars_in_buffer =	gs_chars_in_buffer,
-	.unthrottle =		gs_unthrottle,
-	.break_ctl =		gs_break_ctl,
-};
-
-/*-------------------------------------------------------------------------*/
-
-static struct tty_driver *gs_tty_driver;
-
-static int
-gs_port_alloc(unsigned port_num, struct usb_cdc_line_coding *coding)
-{
-	struct gs_port	*port;
-
-	port = kzalloc(sizeof(struct gs_port), GFP_KERNEL);
-	if (port == NULL)
-		return -ENOMEM;
-
-	tty_port_init(&port->port);
-	spin_lock_init(&port->port_lock);
-	init_waitqueue_head(&port->drain_wait);
-
-	tasklet_init(&port->push, gs_rx_push, (unsigned long) port);
-
-	INIT_LIST_HEAD(&port->read_pool);
-	INIT_LIST_HEAD(&port->read_queue);
-	INIT_LIST_HEAD(&port->write_pool);
-
-	port->port_num = port_num;
-	port->port_line_coding = *coding;
-
-	ports[port_num].port = port;
-
-	return 0;
-}
-
-/**
- * gserial_setup - initialize TTY driver for one or more ports
- * @g: gadget to associate with these ports
- * @count: how many ports to support
- * Context: may sleep
- *
- * The TTY stack needs to know in advance how many devices it should
- * plan to manage.  Use this call to set up the ports you will be
- * exporting through USB.  Later, connect them to functions based
- * on what configuration is activated by the USB host; and disconnect
- * them as appropriate.
- *
- * An example would be a two-configuration device in which both
- * configurations expose port 0, but through different functions.
- * One configuration could even expose port 1 while the other
- * one doesn't.
- *
- * Returns negative errno or zero.
- */
-int gserial_setup(struct usb_gadget *g, unsigned count)
-{
-	unsigned			i;
-	struct usb_cdc_line_coding	coding;
-	int				status;
-
-	if (count == 0 || count > N_PORTS)
-		return -EINVAL;
-
-	gs_tty_driver = alloc_tty_driver(count);
-	if (!gs_tty_driver)
-		return -ENOMEM;
-
-	gs_tty_driver->driver_name = "g_serial";
-	gs_tty_driver->name = PREFIX;
-	/* uses dynamically assigned dev_t values */
-
-	gs_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
-	gs_tty_driver->subtype = SERIAL_TYPE_NORMAL;
-	gs_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
-	gs_tty_driver->init_termios = tty_std_termios;
-
-	/* 9600-8-N-1 ... matches defaults expected by "usbser.sys" on
-	 * MS-Windows.  Otherwise, most of these flags shouldn't affect
-	 * anything unless we were to actually hook up to a serial line.
-	 */
-	gs_tty_driver->init_termios.c_cflag =
-			B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	gs_tty_driver->init_termios.c_ispeed = 9600;
-	gs_tty_driver->init_termios.c_ospeed = 9600;
-
-	coding.dwDTERate = cpu_to_le32(9600);
-	coding.bCharFormat = 8;
-	coding.bParityType = USB_CDC_NO_PARITY;
-	coding.bDataBits = USB_CDC_1_STOP_BITS;
-
-	tty_set_operations(gs_tty_driver, &gs_tty_ops);
-
-	/* make devices be openable */
-	for (i = 0; i < count; i++) {
-		mutex_init(&ports[i].lock);
-		status = gs_port_alloc(i, &coding);
-		if (status) {
-			count = i;
-			goto fail;
-		}
-	}
-	n_ports = count;
-
-	/* export the driver ... */
-	status = tty_register_driver(gs_tty_driver);
-	if (status) {
-		pr_err("%s: cannot register, err %d\n",
-				__func__, status);
-		goto fail;
-	}
-
-	/* ... and sysfs class devices, so mdev/udev make /dev/ttyGS* */
-	for (i = 0; i < count; i++) {
-		struct device	*tty_dev;
-
-		tty_dev = tty_register_device(gs_tty_driver, i, &g->dev);
-		if (IS_ERR(tty_dev))
-			pr_warning("%s: no classdev for port %d, err %ld\n",
-				__func__, i, PTR_ERR(tty_dev));
-	}
-
-	pr_debug("%s: registered %d ttyGS* device%s\n", __func__,
-			count, (count == 1) ? "" : "s");
-
-	return status;
-fail:
-	while (count--) {
-		tty_port_destroy(&ports[count].port->port);
-		kfree(ports[count].port);
-	}
-	put_tty_driver(gs_tty_driver);
-	gs_tty_driver = NULL;
-	return status;
-}
-
-static int gs_closed(struct gs_port *port)
-{
-	int cond;
-
-	spin_lock_irq(&port->port_lock);
-	cond = (port->port.count == 0) && !port->openclose;
-	spin_unlock_irq(&port->port_lock);
-	return cond;
-}
-
-/**
- * gserial_cleanup - remove TTY-over-USB driver and devices
- * Context: may sleep
- *
- * This is called to free all resources allocated by @gserial_setup().
- * Accordingly, it may need to wait until some open /dev/ files have
- * closed.
- *
- * The caller must have issued @gserial_disconnect() for any ports
- * that had previously been connected, so that there is never any
- * I/O pending when it's called.
- */
-void gserial_cleanup(void)
-{
-	unsigned	i;
-	struct gs_port	*port;
-
-	if (!gs_tty_driver)
-		return;
-
-	/* start sysfs and /dev/ttyGS* node removal */
-	for (i = 0; i < n_ports; i++)
-		tty_unregister_device(gs_tty_driver, i);
-
-	for (i = 0; i < n_ports; i++) {
-		/* prevent new opens */
-		mutex_lock(&ports[i].lock);
-		port = ports[i].port;
-		ports[i].port = NULL;
-		mutex_unlock(&ports[i].lock);
-
-		tasklet_kill(&port->push);
-
-		/* wait for old opens to finish */
-		wait_event(port->port.close_wait, gs_closed(port));
-
-		WARN_ON(port->port_usb != NULL);
-
-		tty_port_destroy(&port->port);
-		kfree(port);
-	}
-	n_ports = 0;
-
-	tty_unregister_driver(gs_tty_driver);
-	put_tty_driver(gs_tty_driver);
-	gs_tty_driver = NULL;
-
-	pr_debug("%s: cleaned up ttyGS* support\n", __func__);
-}
-
-/**
- * gserial_connect - notify TTY I/O glue that USB link is active
- * @gser: the function, set up with endpoints and descriptors
- * @port_num: which port is active
- * Context: any (usually from irq)
- *
- * This is called activate endpoints and let the TTY layer know that
- * the connection is active ... not unlike "carrier detect".  It won't
- * necessarily start I/O queues; unless the TTY is held open by any
- * task, there would be no point.  However, the endpoints will be
- * activated so the USB host can perform I/O, subject to basic USB
- * hardware flow control.
- *
- * Caller needs to have set up the endpoints and USB function in @dev
- * before calling this, as well as the appropriate (speed-specific)
- * endpoint descriptors, and also have set up the TTY driver by calling
- * @gserial_setup().
- *
- * Returns negative errno or zero.
- * On success, ep->driver_data will be overwritten.
- */
-int gserial_connect(struct gserial *gser, u8 port_num)
-{
-	struct gs_port	*port;
-	unsigned long	flags;
-	int		status;
-
-	if (!gs_tty_driver || port_num >= n_ports)
-		return -ENXIO;
-
-	/* we "know" gserial_cleanup() hasn't been called */
-	port = ports[port_num].port;
-
-	/* activate the endpoints */
-	status = usb_ep_enable(gser->in);
-	if (status < 0)
-		return status;
-	gser->in->driver_data = port;
-
-	status = usb_ep_enable(gser->out);
-	if (status < 0)
-		goto fail_out;
-	gser->out->driver_data = port;
-
-	/* then tell the tty glue that I/O can work */
-	spin_lock_irqsave(&port->port_lock, flags);
-	gser->ioport = port;
-	port->port_usb = gser;
-
-	/* REVISIT unclear how best to handle this state...
-	 * we don't really couple it with the Linux TTY.
-	 */
-	gser->port_line_coding = port->port_line_coding;
-
-	/* REVISIT if waiting on "carrier detect", signal. */
-
-	/* if it's already open, start I/O ... and notify the serial
-	 * protocol about open/close status (connect/disconnect).
-	 */
-	if (port->port.count) {
-		pr_debug("gserial_connect: start ttyGS%d\n", port->port_num);
-		gs_start_io(port);
-		if (gser->connect)
-			gser->connect(gser);
-	} else {
-		if (gser->disconnect)
-			gser->disconnect(gser);
-	}
-
-	spin_unlock_irqrestore(&port->port_lock, flags);
-
-	return status;
-
-fail_out:
-	usb_ep_disable(gser->in);
-	gser->in->driver_data = NULL;
-	return status;
-}
-
-/**
- * gserial_disconnect - notify TTY I/O glue that USB link is inactive
- * @gser: the function, on which gserial_connect() was called
- * Context: any (usually from irq)
- *
- * This is called to deactivate endpoints and let the TTY layer know
- * that the connection went inactive ... not unlike "hangup".
- *
- * On return, the state is as if gserial_connect() had never been called;
- * there is no active USB I/O on these endpoints.
- */
-void gserial_disconnect(struct gserial *gser)
-{
-	struct gs_port	*port = gser->ioport;
-	unsigned long	flags;
-
-	if (!port)
-		return;
-
-	/* tell the TTY glue not to do I/O here any more */
-	spin_lock_irqsave(&port->port_lock, flags);
-
-	/* REVISIT as above: how best to track this? */
-	port->port_line_coding = gser->port_line_coding;
-
-	port->port_usb = NULL;
-	gser->ioport = NULL;
-	if (port->port.count > 0 || port->openclose) {
-		wake_up_interruptible(&port->drain_wait);
-		if (port->port.tty)
-			tty_hangup(port->port.tty);
-	}
-	spin_unlock_irqrestore(&port->port_lock, flags);
-
-	/* disable endpoints, aborting down any active I/O */
-	usb_ep_disable(gser->out);
-	gser->out->driver_data = NULL;
-
-	usb_ep_disable(gser->in);
-	gser->in->driver_data = NULL;
-
-	/* finally, free any unused/unusable I/O buffers */
-	spin_lock_irqsave(&port->port_lock, flags);
-	if (port->port.count == 0 && !port->openclose)
-		gs_buf_free(&port->port_write_buf);
-	gs_free_requests(gser->out, &port->read_pool, NULL);
-	gs_free_requests(gser->out, &port->read_queue, NULL);
-	gs_free_requests(gser->in, &port->write_pool, NULL);
-
-	port->read_allocated = port->read_started =
-		port->write_allocated = port->write_started = 0;
-
-	spin_unlock_irqrestore(&port->port_lock, flags);
-}
diff --git a/drivers/staging/ccg/u_serial.h b/drivers/staging/ccg/u_serial.h
deleted file mode 100644
index 9b0fe64..0000000
--- a/drivers/staging/ccg/u_serial.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * u_serial.h - interface to USB gadget "serial port"/TTY utilities
- *
- * Copyright (C) 2008 David Brownell
- * Copyright (C) 2008 by Nokia Corporation
- *
- * This software is distributed under the terms of the GNU General
- * Public License ("GPL") as published by the Free Software Foundation,
- * either version 2 of that License or (at your option) any later version.
- */
-
-#ifndef __U_SERIAL_H
-#define __U_SERIAL_H
-
-#include <linux/usb/composite.h>
-#include <linux/usb/cdc.h>
-
-/*
- * One non-multiplexed "serial" I/O port ... there can be several of these
- * on any given USB peripheral device, if it provides enough endpoints.
- *
- * The "u_serial" utility component exists to do one thing:  manage TTY
- * style I/O using the USB peripheral endpoints listed here, including
- * hookups to sysfs and /dev for each logical "tty" device.
- *
- * REVISIT at least ACM could support tiocmget() if needed.
- *
- * REVISIT someday, allow multiplexing several TTYs over these endpoints.
- */
-struct gserial {
-	struct usb_function		func;
-
-	/* port is managed by gserial_{connect,disconnect} */
-	struct gs_port			*ioport;
-
-	struct usb_ep			*in;
-	struct usb_ep			*out;
-
-	/* REVISIT avoid this CDC-ACM support harder ... */
-	struct usb_cdc_line_coding port_line_coding;	/* 9600-8-N-1 etc */
-
-	/* notification callbacks */
-	void (*connect)(struct gserial *p);
-	void (*disconnect)(struct gserial *p);
-	int (*send_break)(struct gserial *p, int duration);
-};
-
-/* utilities to allocate/free request and buffer */
-struct usb_request *gs_alloc_req(struct usb_ep *ep, unsigned len, gfp_t flags);
-void gs_free_req(struct usb_ep *, struct usb_request *req);
-
-/* port setup/teardown is handled by gadget driver */
-int gserial_setup(struct usb_gadget *g, unsigned n_ports);
-void gserial_cleanup(void);
-
-/* connect/disconnect is handled by individual functions */
-int gserial_connect(struct gserial *, u8 port_num);
-void gserial_disconnect(struct gserial *);
-
-/* functions are bound to configurations by a config or gadget driver */
-int acm_bind_config(struct usb_configuration *c, u8 port_num);
-int gser_bind_config(struct usb_configuration *c, u8 port_num);
-int obex_bind_config(struct usb_configuration *c, u8 port_num);
-
-#endif /* __U_SERIAL_H */
diff --git a/drivers/staging/ccg/usbstring.c b/drivers/staging/ccg/usbstring.c
deleted file mode 100644
index 4d25b90..0000000
--- a/drivers/staging/ccg/usbstring.c
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2003 David Brownell
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/string.h>
-#include <linux/device.h>
-#include <linux/init.h>
-#include <linux/nls.h>
-
-#include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
-
-
-/**
- * usb_gadget_get_string - fill out a string descriptor 
- * @table: of c strings encoded using UTF-8
- * @id: string id, from low byte of wValue in get string descriptor
- * @buf: at least 256 bytes, must be 16-bit aligned
- *
- * Finds the UTF-8 string matching the ID, and converts it into a
- * string descriptor in utf16-le.
- * Returns length of descriptor (always even) or negative errno
- *
- * If your driver needs stings in multiple languages, you'll probably
- * "switch (wIndex) { ... }"  in your ep0 string descriptor logic,
- * using this routine after choosing which set of UTF-8 strings to use.
- * Note that US-ASCII is a strict subset of UTF-8; any string bytes with
- * the eighth bit set will be multibyte UTF-8 characters, not ISO-8859/1
- * characters (which are also widely used in C strings).
- */
-int
-usb_gadget_get_string (struct usb_gadget_strings *table, int id, u8 *buf)
-{
-	struct usb_string	*s;
-	int			len;
-
-	/* descriptor 0 has the language id */
-	if (id == 0) {
-		buf [0] = 4;
-		buf [1] = USB_DT_STRING;
-		buf [2] = (u8) table->language;
-		buf [3] = (u8) (table->language >> 8);
-		return 4;
-	}
-	for (s = table->strings; s && s->s; s++)
-		if (s->id == id)
-			break;
-
-	/* unrecognized: stall. */
-	if (!s || !s->s)
-		return -EINVAL;
-
-	/* string descriptors have length, tag, then UTF16-LE text */
-	len = min ((size_t) 126, strlen (s->s));
-	len = utf8s_to_utf16s(s->s, len, UTF16_LITTLE_ENDIAN,
-			(wchar_t *) &buf[2], 126);
-	if (len < 0)
-		return -EINVAL;
-	buf [0] = (len + 1) * 2;
-	buf [1] = USB_DT_STRING;
-	return buf [0];
-}
-
diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig
index 1967852..67993c0 100644
--- a/drivers/staging/comedi/Kconfig
+++ b/drivers/staging/comedi/Kconfig
@@ -728,6 +728,16 @@ config COMEDI_ADV_PCI1723
 	  To compile this driver as a module, choose M here: the module will be
 	  called adv_pci1723.
 
+config COMEDI_ADV_PCI1724
+	tristate "Advantech PCI-1724U support"
+	---help---
+	  Enable support for Advantech PCI-1724U cards.  These are 32-channel
+	  analog output cards with voltage and current loop output ranges and
+	  14-bit resolution.
+
+	  To compile this driver as a module, choose M here: the module will be
+	  called adv_pci1724.
+
 config COMEDI_ADV_PCI_DIO
 	tristate "Advantech PCI DIO card support"
 	select COMEDI_8255
@@ -748,7 +758,7 @@ config COMEDI_AMPLC_DIO200_PCI
 	  and PCIe296 DIO boards.
 
 	  To compile this driver as a module, choose M here: the module will be
-	  called amplc_dio200.
+	  called amplc_dio200_pci.
 
 config COMEDI_AMPLC_PC236_PCI
 	tristate "Amplicon PCI236 DIO board support"
@@ -983,7 +993,7 @@ config COMEDI_NI_660X
 	select COMEDI_NI_TIOCMD
 	---help---
 	  Enable support for National Instruments PCI-6601 (ni_660x), PCI-6602,
-	  PXI-6602 and PXI-6608.
+	  PXI-6602, PXI-6608 and PXI-6624.
 
 	  To compile this driver as a module, choose M here: the module will be
 	  called ni_660x.
diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
index e336b28..6bcbb52 100644
--- a/drivers/staging/comedi/comedi_fops.c
+++ b/drivers/staging/comedi/comedi_fops.c
@@ -2067,12 +2067,12 @@ static int comedi_open(struct inode *inode, struct file *file)
 	/* This is slightly hacky, but we want module autoloading
 	 * to work for root.
 	 * case: user opens device, attached -> ok
-	 * case: user opens device, unattached, in_request_module=0 -> autoload
-	 * case: user opens device, unattached, in_request_module=1 -> fail
+	 * case: user opens device, unattached, !in_request_module -> autoload
+	 * case: user opens device, unattached, in_request_module -> fail
 	 * case: root opens device, attached -> ok
-	 * case: root opens device, unattached, in_request_module=1 -> ok
+	 * case: root opens device, unattached, in_request_module -> ok
 	 *   (typically called from modprobe)
-	 * case: root opens device, unattached, in_request_module=0 -> autoload
+	 * case: root opens device, unattached, !in_request_module -> autoload
 	 *
 	 * The last could be changed to "-> ok", which would deny root
 	 * autoloading.
@@ -2088,7 +2088,7 @@ static int comedi_open(struct inode *inode, struct file *file)
 	if (capable(CAP_NET_ADMIN) && dev->in_request_module)
 		goto ok;
 
-	dev->in_request_module = 1;
+	dev->in_request_module = true;
 
 #ifdef CONFIG_KMOD
 	mutex_unlock(&dev->mutex);
@@ -2096,7 +2096,7 @@ static int comedi_open(struct inode *inode, struct file *file)
 	mutex_lock(&dev->mutex);
 #endif
 
-	dev->in_request_module = 0;
+	dev->in_request_module = false;
 
 	if (!dev->attached && !capable(CAP_NET_ADMIN)) {
 		DPRINTK("not attached and not CAP_NET_ADMIN\n");
diff --git a/drivers/staging/comedi/comedi_pci.c b/drivers/staging/comedi/comedi_pci.c
index 37d2e46..6f3cdf8 100644
--- a/drivers/staging/comedi/comedi_pci.c
+++ b/drivers/staging/comedi/comedi_pci.c
@@ -36,20 +36,27 @@ EXPORT_SYMBOL_GPL(comedi_to_pci_dev);
 
 /**
  * comedi_pci_enable() - Enable the PCI device and request the regions.
- * @pcidev: pci_dev struct
- * @res_name: name for the requested reqource
+ * @dev: comedi_device struct
  */
-int comedi_pci_enable(struct pci_dev *pcidev, const char *res_name)
+int comedi_pci_enable(struct comedi_device *dev)
 {
+	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
 	int rc;
 
+	if (!pcidev)
+		return -ENODEV;
+
 	rc = pci_enable_device(pcidev);
 	if (rc < 0)
 		return rc;
 
-	rc = pci_request_regions(pcidev, res_name);
+	rc = pci_request_regions(pcidev, dev->board_name
+						? dev->board_name
+						: dev->driver->driver_name);
 	if (rc < 0)
 		pci_disable_device(pcidev);
+	else
+		dev->ioenabled = true;
 
 	return rc;
 }
@@ -57,14 +64,17 @@ EXPORT_SYMBOL_GPL(comedi_pci_enable);
 
 /**
  * comedi_pci_disable() - Release the regions and disable the PCI device.
- * @pcidev: pci_dev struct
- *
- * This must be matched with a previous successful call to comedi_pci_enable().
+ * @dev: comedi_device struct
  */
-void comedi_pci_disable(struct pci_dev *pcidev)
+void comedi_pci_disable(struct comedi_device *dev)
 {
-	pci_release_regions(pcidev);
-	pci_disable_device(pcidev);
+	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+
+	if (pcidev && dev->ioenabled) {
+		pci_release_regions(pcidev);
+		pci_disable_device(pcidev);
+	}
+	dev->ioenabled = false;
 }
 EXPORT_SYMBOL_GPL(comedi_pci_disable);
 
@@ -72,13 +82,15 @@ EXPORT_SYMBOL_GPL(comedi_pci_disable);
  * comedi_pci_auto_config() - Configure/probe a comedi PCI driver.
  * @pcidev: pci_dev struct
  * @driver: comedi_driver struct
+ * @context: driver specific data, passed to comedi_auto_config()
  *
  * Typically called from the pci_driver (*probe) function.
  */
 int comedi_pci_auto_config(struct pci_dev *pcidev,
-			   struct comedi_driver *driver)
+			   struct comedi_driver *driver,
+			   unsigned long context)
 {
-	return comedi_auto_config(&pcidev->dev, driver, 0);
+	return comedi_auto_config(&pcidev->dev, driver, context);
 }
 EXPORT_SYMBOL_GPL(comedi_pci_auto_config);
 
diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h
index f3a990b..9c8662a 100644
--- a/drivers/staging/comedi/comedidev.h
+++ b/drivers/staging/comedi/comedidev.h
@@ -207,10 +207,11 @@ struct comedi_device {
 
 	const char *board_name;
 	const void *board_ptr;
-	int attached;
+	bool attached:1;
+	bool in_request_module:1;
+	bool ioenabled:1;
 	spinlock_t spinlock;
 	struct mutex mutex;
-	int in_request_module;
 
 	int n_subdevices;
 	struct comedi_subdevice *subdevices;
@@ -384,10 +385,11 @@ struct pci_driver;
 
 struct pci_dev *comedi_to_pci_dev(struct comedi_device *);
 
-int comedi_pci_enable(struct pci_dev *, const char *);
-void comedi_pci_disable(struct pci_dev *);
+int comedi_pci_enable(struct comedi_device *);
+void comedi_pci_disable(struct comedi_device *);
 
-int comedi_pci_auto_config(struct pci_dev *, struct comedi_driver *);
+int comedi_pci_auto_config(struct pci_dev *, struct comedi_driver *,
+			   unsigned long context);
 void comedi_pci_auto_unconfig(struct pci_dev *);
 
 int comedi_pci_driver_register(struct comedi_driver *, struct pci_driver *);
@@ -420,12 +422,12 @@ static inline struct pci_dev *comedi_to_pci_dev(struct comedi_device *dev)
 	return NULL;
 }
 
-static inline int comedi_pci_enable(struct pci_dev *dev, const char *name)
+static inline int comedi_pci_enable(struct comedi_device *dev)
 {
 	return -ENOSYS;
 }
 
-static inline void comedi_pci_disable(struct pci_dev *dev)
+static inline void comedi_pci_disable(struct comedi_device *dev)
 {
 }
 
diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c
index 64be7c5..4724f27 100644
--- a/drivers/staging/comedi/drivers.c
+++ b/drivers/staging/comedi/drivers.c
@@ -110,6 +110,7 @@ static void cleanup_device(struct comedi_device *dev)
 	dev->board_name = NULL;
 	dev->board_ptr = NULL;
 	dev->iobase = 0;
+	dev->ioenabled = false;
 	dev->irq = 0;
 	dev->read_subdev = NULL;
 	dev->write_subdev = NULL;
@@ -120,7 +121,7 @@ static void cleanup_device(struct comedi_device *dev)
 
 static void __comedi_device_detach(struct comedi_device *dev)
 {
-	dev->attached = 0;
+	dev->attached = false;
 	if (dev->driver)
 		dev->driver->detach(dev);
 	else
@@ -290,7 +291,7 @@ static int comedi_device_postconfig(struct comedi_device *dev)
 		dev->board_name = "BUG";
 	}
 	smp_wmb();
-	dev->attached = 1;
+	dev->attached = true;
 	return 0;
 }
 
diff --git a/drivers/staging/comedi/drivers/8255_pci.c b/drivers/staging/comedi/drivers/8255_pci.c
index 0ae356a..808460b 100644
--- a/drivers/staging/comedi/drivers/8255_pci.c
+++ b/drivers/staging/comedi/drivers/8255_pci.c
@@ -60,124 +60,104 @@ Configuration Options: not applicable, uses PCI auto config
 
 #include "8255.h"
 
-/*
- * PCI Device ID's supported by this driver
- */
-#define PCI_DEVICE_ID_ADLINK_PCI7224	0x7224
-#define PCI_DEVICE_ID_ADLINK_PCI7248	0x7248
-#define PCI_DEVICE_ID_ADLINK_PCI7296	0x7296
-
-#define PCI_DEVICE_ID_CB_PCIDIO48H	0x000b
-#define PCI_DEVICE_ID_CB_PCIDIO24H	0x0014
-#define PCI_DEVICE_ID_CB_PCIDIO96H	0x0017
-#define PCI_DEVICE_ID_CB_PCIDIO24	0x0028
-
-#define PCI_DEVICE_ID_NI_PCIDIO96	0x0160
-#define PCI_DEVICE_ID_NI_PCI6503	0x0400
-#define PCI_DEVICE_ID_NI_PCI6503B	0x1250
-#define PCI_DEVICE_ID_NI_PXI6508	0x13c0
-#define PCI_DEVICE_ID_NI_PCIDIO96B	0x1630
-#define PCI_DEVICE_ID_NI_PCI6503X	0x17d0
-#define PCI_DEVICE_ID_NI_PXI_6503	0x1800
+enum pci_8255_boardid {
+	BOARD_ADLINK_PCI7224,
+	BOARD_ADLINK_PCI7248,
+	BOARD_ADLINK_PCI7296,
+	BOARD_CB_PCIDIO24,
+	BOARD_CB_PCIDIO24H,
+	BOARD_CB_PCIDIO48H,
+	BOARD_CB_PCIDIO96H,
+	BOARD_NI_PCIDIO96,
+	BOARD_NI_PCIDIO96B,
+	BOARD_NI_PXI6508,
+	BOARD_NI_PCI6503,
+	BOARD_NI_PCI6503B,
+	BOARD_NI_PCI6503X,
+	BOARD_NI_PXI_6503,
+};
 
 struct pci_8255_boardinfo {
 	const char *name;
-	unsigned short vendor;
-	unsigned short device;
 	int dio_badr;
 	int is_mmio;
 	int n_8255;
 };
 
 static const struct pci_8255_boardinfo pci_8255_boards[] = {
-	{
+	[BOARD_ADLINK_PCI7224] = {
 		.name		= "adl_pci-7224",
-		.vendor		= PCI_VENDOR_ID_ADLINK,
-		.device		= PCI_DEVICE_ID_ADLINK_PCI7224,
 		.dio_badr	= 2,
 		.n_8255		= 1,
-	}, {
+	},
+	[BOARD_ADLINK_PCI7248] = {
 		.name		= "adl_pci-7248",
-		.vendor		= PCI_VENDOR_ID_ADLINK,
-		.device		= PCI_DEVICE_ID_ADLINK_PCI7248,
 		.dio_badr	= 2,
 		.n_8255		= 2,
-	}, {
+	},
+	[BOARD_ADLINK_PCI7296] = {
 		.name		= "adl_pci-7296",
-		.vendor		= PCI_VENDOR_ID_ADLINK,
-		.device		= PCI_DEVICE_ID_ADLINK_PCI7296,
 		.dio_badr	= 2,
 		.n_8255		= 4,
-	}, {
+	},
+	[BOARD_CB_PCIDIO24] = {
 		.name		= "cb_pci-dio24",
-		.vendor		= PCI_VENDOR_ID_CB,
-		.device		= PCI_DEVICE_ID_CB_PCIDIO24,
 		.dio_badr	= 2,
 		.n_8255		= 1,
-	}, {
+	},
+	[BOARD_CB_PCIDIO24H] = {
 		.name		= "cb_pci-dio24h",
-		.vendor		= PCI_VENDOR_ID_CB,
-		.device		= PCI_DEVICE_ID_CB_PCIDIO24H,
 		.dio_badr	= 2,
 		.n_8255		= 1,
-	}, {
+	},
+	[BOARD_CB_PCIDIO48H] = {
 		.name		= "cb_pci-dio48h",
-		.vendor		= PCI_VENDOR_ID_CB,
-		.device		= PCI_DEVICE_ID_CB_PCIDIO48H,
 		.dio_badr	= 1,
 		.n_8255		= 2,
-	}, {
+	},
+	[BOARD_CB_PCIDIO96H] = {
 		.name		= "cb_pci-dio96h",
-		.vendor		= PCI_VENDOR_ID_CB,
-		.device		= PCI_DEVICE_ID_CB_PCIDIO96H,
 		.dio_badr	= 2,
 		.n_8255		= 4,
-	}, {
+	},
+	[BOARD_NI_PCIDIO96] = {
 		.name		= "ni_pci-dio-96",
-		.vendor		= PCI_VENDOR_ID_NI,
-		.device		= PCI_DEVICE_ID_NI_PCIDIO96,
 		.dio_badr	= 1,
 		.is_mmio	= 1,
 		.n_8255		= 4,
-	}, {
+	},
+	[BOARD_NI_PCIDIO96B] = {
 		.name		= "ni_pci-dio-96b",
-		.vendor		= PCI_VENDOR_ID_NI,
-		.device		= PCI_DEVICE_ID_NI_PCIDIO96B,
 		.dio_badr	= 1,
 		.is_mmio	= 1,
 		.n_8255		= 4,
-	}, {
+	},
+	[BOARD_NI_PXI6508] = {
 		.name		= "ni_pxi-6508",
-		.vendor		= PCI_VENDOR_ID_NI,
-		.device		= PCI_DEVICE_ID_NI_PXI6508,
 		.dio_badr	= 1,
 		.is_mmio	= 1,
 		.n_8255		= 4,
-	}, {
+	},
+	[BOARD_NI_PCI6503] = {
 		.name		= "ni_pci-6503",
-		.vendor		= PCI_VENDOR_ID_NI,
-		.device		= PCI_DEVICE_ID_NI_PCI6503,
 		.dio_badr	= 1,
 		.is_mmio	= 1,
 		.n_8255		= 1,
-	}, {
+	},
+	[BOARD_NI_PCI6503B] = {
 		.name		= "ni_pci-6503b",
-		.vendor		= PCI_VENDOR_ID_NI,
-		.device		= PCI_DEVICE_ID_NI_PCI6503B,
 		.dio_badr	= 1,
 		.is_mmio	= 1,
 		.n_8255		= 1,
-	}, {
+	},
+	[BOARD_NI_PCI6503X] = {
 		.name		= "ni_pci-6503x",
-		.vendor		= PCI_VENDOR_ID_NI,
-		.device		= PCI_DEVICE_ID_NI_PCI6503X,
 		.dio_badr	= 1,
 		.is_mmio	= 1,
 		.n_8255		= 1,
-	}, {
+	},
+	[BOARD_NI_PXI_6503] = {
 		.name		= "ni_pxi-6503",
-		.vendor		= PCI_VENDOR_ID_NI,
-		.device		= PCI_DEVICE_ID_NI_PXI_6503,
 		.dio_badr	= 1,
 		.is_mmio	= 1,
 		.n_8255		= 1,
@@ -200,26 +180,11 @@ static int pci_8255_mmio(int dir, int port, int data, unsigned long iobase)
 	}
 }
 
-static const void *pci_8255_find_boardinfo(struct comedi_device *dev,
-					      struct pci_dev *pcidev)
-{
-	const struct pci_8255_boardinfo *board;
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(pci_8255_boards); i++) {
-		board = &pci_8255_boards[i];
-		if (pcidev->vendor == board->vendor &&
-		    pcidev->device == board->device)
-			return board;
-	}
-	return NULL;
-}
-
 static int pci_8255_auto_attach(struct comedi_device *dev,
-					  unsigned long context_unused)
+				unsigned long context)
 {
 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-	const struct pci_8255_boardinfo *board;
+	const struct pci_8255_boardinfo *board = NULL;
 	struct pci_8255_private *devpriv;
 	struct comedi_subdevice *s;
 	resource_size_t iobase;
@@ -227,7 +192,8 @@ static int pci_8255_auto_attach(struct comedi_device *dev,
 	int ret;
 	int i;
 
-	board = pci_8255_find_boardinfo(dev, pcidev);
+	if (context < ARRAY_SIZE(pci_8255_boards))
+		board = &pci_8255_boards[context];
 	if (!board)
 		return -ENODEV;
 	dev->board_ptr = board;
@@ -238,7 +204,7 @@ static int pci_8255_auto_attach(struct comedi_device *dev,
 		return -ENOMEM;
 	dev->private = devpriv;
 
-	ret = comedi_pci_enable(pcidev, dev->board_name);
+	ret = comedi_pci_enable(dev);
 	if (ret)
 		return ret;
 	iobase = pci_resource_start(pcidev, board->dio_badr);
@@ -281,7 +247,6 @@ static int pci_8255_auto_attach(struct comedi_device *dev,
 
 static void pci_8255_detach(struct comedi_device *dev)
 {
-	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
 	const struct pci_8255_boardinfo *board = comedi_board(dev);
 	struct pci_8255_private *devpriv = dev->private;
 	struct comedi_subdevice *s;
@@ -295,12 +260,9 @@ static void pci_8255_detach(struct comedi_device *dev)
 			subdev_8255_cleanup(dev, s);
 		}
 	}
-	if (pcidev) {
-		if (devpriv->mmio_base)
-			iounmap(devpriv->mmio_base);
-		if (dev->iobase)
-			comedi_pci_disable(pcidev);
-	}
+	if (devpriv->mmio_base)
+		iounmap(devpriv->mmio_base);
+	comedi_pci_disable(dev);
 }
 
 static struct comedi_driver pci_8255_driver = {
@@ -311,26 +273,26 @@ static struct comedi_driver pci_8255_driver = {
 };
 
 static int pci_8255_pci_probe(struct pci_dev *dev,
-					const struct pci_device_id *ent)
+			      const struct pci_device_id *id)
 {
-	return comedi_pci_auto_config(dev, &pci_8255_driver);
+	return comedi_pci_auto_config(dev, &pci_8255_driver, id->driver_data);
 }
 
 static DEFINE_PCI_DEVICE_TABLE(pci_8255_pci_table) = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_ADLINK_PCI7224) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_ADLINK_PCI7248) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_ADLINK_PCI7296) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_CB, PCI_DEVICE_ID_CB_PCIDIO24) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_CB, PCI_DEVICE_ID_CB_PCIDIO24H) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_CB, PCI_DEVICE_ID_CB_PCIDIO48H) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_CB, PCI_DEVICE_ID_CB_PCIDIO96H) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCIDIO96) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCIDIO96B) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI6508) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI6503) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI6503B) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI6503X) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI_6503) },
+	{ PCI_VDEVICE(ADLINK, 0x7224), BOARD_ADLINK_PCI7224 },
+	{ PCI_VDEVICE(ADLINK, 0x7248), BOARD_ADLINK_PCI7248 },
+	{ PCI_VDEVICE(ADLINK, 0x7296), BOARD_ADLINK_PCI7296 },
+	{ PCI_VDEVICE(CB, 0x0028), BOARD_CB_PCIDIO24 },
+	{ PCI_VDEVICE(CB, 0x0014), BOARD_CB_PCIDIO24H },
+	{ PCI_VDEVICE(CB, 0x000b), BOARD_CB_PCIDIO48H },
+	{ PCI_VDEVICE(CB, 0x0017), BOARD_CB_PCIDIO96H },
+	{ PCI_VDEVICE(NI, 0x0160), BOARD_NI_PCIDIO96 },
+	{ PCI_VDEVICE(NI, 0x1630), BOARD_NI_PCIDIO96B },
+	{ PCI_VDEVICE(NI, 0x13c0), BOARD_NI_PXI6508 },
+	{ PCI_VDEVICE(NI, 0x0400), BOARD_NI_PCI6503 },
+	{ PCI_VDEVICE(NI, 0x1250), BOARD_NI_PCI6503B },
+	{ PCI_VDEVICE(NI, 0x17d0), BOARD_NI_PCI6503X },
+	{ PCI_VDEVICE(NI, 0x1800), BOARD_NI_PXI_6503 },
 	{ 0 }
 };
 MODULE_DEVICE_TABLE(pci, pci_8255_pci_table);
diff --git a/drivers/staging/comedi/drivers/Makefile b/drivers/staging/comedi/drivers/Makefile
index 315e836..4857d46 100644
--- a/drivers/staging/comedi/drivers/Makefile
+++ b/drivers/staging/comedi/drivers/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_COMEDI_SKEL)		+= skel.o
 
 # Comedi ISA drivers
 obj-$(CONFIG_COMEDI_ACL7225B)		+= acl7225b.o
+obj-$(CONFIG_COMEDI_AMPLC_DIO200_ISA)	+= amplc_dio200.o
 obj-$(CONFIG_COMEDI_PCL711)		+= pcl711.o
 obj-$(CONFIG_COMEDI_PCL724)		+= pcl724.o
 obj-$(CONFIG_COMEDI_PCL725)		+= pcl725.o
@@ -75,8 +76,9 @@ obj-$(CONFIG_COMEDI_ADL_PCI9111)	+= adl_pci9111.o
 obj-$(CONFIG_COMEDI_ADL_PCI9118)	+= adl_pci9118.o
 obj-$(CONFIG_COMEDI_ADV_PCI1710)	+= adv_pci1710.o
 obj-$(CONFIG_COMEDI_ADV_PCI1723)	+= adv_pci1723.o
+obj-$(CONFIG_COMEDI_ADV_PCI1724)	+= adv_pci1724.o
 obj-$(CONFIG_COMEDI_ADV_PCI_DIO)	+= adv_pci_dio.o
-obj-$(CONFIG_COMEDI_AMPLC_DIO200)	+= amplc_dio200.o
+obj-$(CONFIG_COMEDI_AMPLC_DIO200_PCI)	+= amplc_dio200_pci.o
 obj-$(CONFIG_COMEDI_AMPLC_PC236)	+= amplc_pc236.o
 obj-$(CONFIG_COMEDI_AMPLC_PC263)	+= amplc_pc263.o
 obj-$(CONFIG_COMEDI_AMPLC_PCI224)	+= amplc_pci224.o
@@ -133,5 +135,6 @@ obj-$(CONFIG_COMEDI_NI_TIOCMD)		+= ni_tiocmd.o
 obj-$(CONFIG_COMEDI_NI_LABPC)		+= ni_labpc.o
 
 obj-$(CONFIG_COMEDI_8255)		+= 8255.o
+obj-$(CONFIG_COMEDI_AMPLC_DIO200)	+= amplc_dio200_common.o
 obj-$(CONFIG_COMEDI_DAS08)		+= das08.o
 obj-$(CONFIG_COMEDI_FC)			+= comedi_fc.o
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
index 1e05732..97e7eec 100644
--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
+++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
@@ -704,9 +704,9 @@ static int i_APCI1710_InsnReadSSIValue(struct comedi_device *dev,
 |                                        unsigned char *_   pb_ChannelStatus)          |
 +----------------------------------------------------------------------------+
 | Task              :
-					(0) Set the digital output from selected SSI moule         |
+					(0) Set the digital output from selected SSI module         |
 |                     (b_ModuleNbr) ON
-                    (1) Set the digital output from selected SSI moule         |
+                    (1) Set the digital output from selected SSI module         |
 |                     (b_ModuleNbr) OFF
 					(2)Read the status from selected SSI digital input        |
 |                     (b_InputChannel)
diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.c b/drivers/staging/comedi/drivers/addi-data/addi_common.c
index 1051fa5..cb9b590 100644
--- a/drivers/staging/comedi/drivers/addi-data/addi_common.c
+++ b/drivers/staging/comedi/drivers/addi-data/addi_common.c
@@ -84,37 +84,16 @@ static int i_ADDI_Reset(struct comedi_device *dev)
 	return 0;
 }
 
-static const void *addi_find_boardinfo(struct comedi_device *dev,
-				       struct pci_dev *pcidev)
-{
-	const void *p = dev->driver->board_name;
-	const struct addi_board *this_board;
-	int i;
-
-	for (i = 0; i < dev->driver->num_names; i++) {
-		this_board = p;
-		if (this_board->i_VendorId == pcidev->vendor &&
-		    this_board->i_DeviceId == pcidev->device)
-			return this_board;
-		p += dev->driver->offset;
-	}
-	return NULL;
-}
-
 static int addi_auto_attach(struct comedi_device *dev,
 				      unsigned long context_unused)
 {
 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-	const struct addi_board *this_board;
+	const struct addi_board *this_board = comedi_board(dev);
 	struct addi_private *devpriv;
 	struct comedi_subdevice *s;
 	int ret, n_subdevices;
 	unsigned int dw_Dummy;
 
-	this_board = addi_find_boardinfo(dev, pcidev);
-	if (!this_board)
-		return -ENODEV;
-	dev->board_ptr = this_board;
 	dev->board_name = this_board->pc_DriverName;
 
 	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
@@ -122,7 +101,7 @@ static int addi_auto_attach(struct comedi_device *dev,
 		return -ENOMEM;
 	dev->private = devpriv;
 
-	ret = comedi_pci_enable(pcidev, dev->board_name);
+	ret = comedi_pci_enable(dev);
 	if (ret)
 		return ret;
 
@@ -338,7 +317,6 @@ static int addi_auto_attach(struct comedi_device *dev,
 
 static void i_ADDI_Detach(struct comedi_device *dev)
 {
-	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
 	struct addi_private *devpriv = dev->private;
 
 	if (devpriv) {
@@ -349,8 +327,5 @@ static void i_ADDI_Detach(struct comedi_device *dev)
 		if (devpriv->dw_AiBase)
 			iounmap(devpriv->dw_AiBase);
 	}
-	if (pcidev) {
-		if (dev->iobase)
-			comedi_pci_disable(pcidev);
-	}
+	comedi_pci_disable(dev);
 }
diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.h b/drivers/staging/comedi/drivers/addi-data/addi_common.h
index 6d8b29f94..19da977 100644
--- a/drivers/staging/comedi/drivers/addi-data/addi_common.h
+++ b/drivers/staging/comedi/drivers/addi-data/addi_common.h
@@ -45,8 +45,6 @@
 /* structure for the boardtype */
 struct addi_board {
 	const char *pc_DriverName;	/*  driver name */
-	int i_VendorId;		/* PCI vendor a device ID of card */
-	int i_DeviceId;
 	int i_IorangeBase0;
 	int i_IorangeBase1;
 	int i_IorangeBase2;	/*   base 2 range */
diff --git a/drivers/staging/comedi/drivers/addi_apci_035.c b/drivers/staging/comedi/drivers/addi_apci_035.c
index 5a53e58..2f4e294 100644
--- a/drivers/staging/comedi/drivers/addi_apci_035.c
+++ b/drivers/staging/comedi/drivers/addi_apci_035.c
@@ -15,8 +15,6 @@
 static const struct addi_board apci035_boardtypes[] = {
 	{
 		.pc_DriverName		= "apci035",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
-		.i_DeviceId		= 0x0300,
 		.i_IorangeBase0		= 127,
 		.i_IorangeBase1		= APCI035_ADDRESS_RANGE,
 		.i_PCIEeprom		= 1,
@@ -39,20 +37,25 @@ static const struct addi_board apci035_boardtypes[] = {
 	},
 };
 
+static int apci035_auto_attach(struct comedi_device *dev,
+			       unsigned long context)
+{
+	dev->board_ptr = &apci035_boardtypes[0];
+
+	return addi_auto_attach(dev, context);
+}
+
 static struct comedi_driver apci035_driver = {
 	.driver_name	= "addi_apci_035",
 	.module		= THIS_MODULE,
-	.auto_attach	= addi_auto_attach,
+	.auto_attach	= apci035_auto_attach,
 	.detach		= i_ADDI_Detach,
-	.num_names	= ARRAY_SIZE(apci035_boardtypes),
-	.board_name	= &apci035_boardtypes[0].pc_DriverName,
-	.offset		= sizeof(struct addi_board),
 };
 
 static int apci035_pci_probe(struct pci_dev *dev,
-				       const struct pci_device_id *ent)
+			     const struct pci_device_id *id)
 {
-	return comedi_pci_auto_config(dev, &apci035_driver);
+	return comedi_pci_auto_config(dev, &apci035_driver, id->driver_data);
 }
 
 static DEFINE_PCI_DEVICE_TABLE(apci035_pci_table) = {
diff --git a/drivers/staging/comedi/drivers/addi_apci_1032.c b/drivers/staging/comedi/drivers/addi_apci_1032.c
index c0d0429..3d32448 100644
--- a/drivers/staging/comedi/drivers/addi_apci_1032.c
+++ b/drivers/staging/comedi/drivers/addi_apci_1032.c
@@ -303,7 +303,7 @@ static int apci1032_auto_attach(struct comedi_device *dev,
 		return -ENOMEM;
 	dev->private = devpriv;
 
-	ret = comedi_pci_enable(pcidev, dev->board_name);
+	ret = comedi_pci_enable(dev);
 	if (ret)
 		return ret;
 
@@ -353,16 +353,11 @@ static int apci1032_auto_attach(struct comedi_device *dev,
 
 static void apci1032_detach(struct comedi_device *dev)
 {
-	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-
 	if (dev->iobase)
 		apci1032_reset(dev);
 	if (dev->irq)
 		free_irq(dev->irq, dev);
-	if (pcidev) {
-		if (dev->iobase)
-			comedi_pci_disable(pcidev);
-	}
+	comedi_pci_disable(dev);
 }
 
 static struct comedi_driver apci1032_driver = {
@@ -373,9 +368,9 @@ static struct comedi_driver apci1032_driver = {
 };
 
 static int apci1032_pci_probe(struct pci_dev *dev,
-					const struct pci_device_id *ent)
+			      const struct pci_device_id *id)
 {
-	return comedi_pci_auto_config(dev, &apci1032_driver);
+	return comedi_pci_auto_config(dev, &apci1032_driver, id->driver_data);
 }
 
 static DEFINE_PCI_DEVICE_TABLE(apci1032_pci_table) = {
diff --git a/drivers/staging/comedi/drivers/addi_apci_1500.c b/drivers/staging/comedi/drivers/addi_apci_1500.c
index 9c2f8ee..1170e76 100644
--- a/drivers/staging/comedi/drivers/addi_apci_1500.c
+++ b/drivers/staging/comedi/drivers/addi_apci_1500.c
@@ -13,8 +13,6 @@
 static const struct addi_board apci1500_boardtypes[] = {
 	{
 		.pc_DriverName		= "apci1500",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA_OLD,
-		.i_DeviceId		= 0x80fc,
 		.i_IorangeBase0		= 128,
 		.i_IorangeBase1		= APCI1500_ADDRESS_RANGE,
 		.i_IorangeBase2		= 4,
@@ -39,20 +37,25 @@ static const struct addi_board apci1500_boardtypes[] = {
 	},
 };
 
+static int apci1500_auto_attach(struct comedi_device *dev,
+				unsigned long context)
+{
+	dev->board_ptr = &apci1500_boardtypes[0];
+
+	return addi_auto_attach(dev, context);
+}
+
 static struct comedi_driver apci1500_driver = {
 	.driver_name	= "addi_apci_1500",
 	.module		= THIS_MODULE,
-	.auto_attach	= addi_auto_attach,
+	.auto_attach	= apci1500_auto_attach,
 	.detach		= i_ADDI_Detach,
-	.num_names	= ARRAY_SIZE(apci1500_boardtypes),
-	.board_name	= &apci1500_boardtypes[0].pc_DriverName,
-	.offset		= sizeof(struct addi_board),
 };
 
 static int apci1500_pci_probe(struct pci_dev *dev,
-					const struct pci_device_id *ent)
+			      const struct pci_device_id *id)
 {
-	return comedi_pci_auto_config(dev, &apci1500_driver);
+	return comedi_pci_auto_config(dev, &apci1500_driver, id->driver_data);
 }
 
 static DEFINE_PCI_DEVICE_TABLE(apci1500_pci_table) = {
diff --git a/drivers/staging/comedi/drivers/addi_apci_1516.c b/drivers/staging/comedi/drivers/addi_apci_1516.c
index 69e3996..e66ff4e 100644
--- a/drivers/staging/comedi/drivers/addi_apci_1516.c
+++ b/drivers/staging/comedi/drivers/addi_apci_1516.c
@@ -36,13 +36,6 @@
 #include "comedi_fc.h"
 
 /*
- * PCI device ids supported by this driver
- */
-#define PCI_DEVICE_ID_APCI1016		0x1000
-#define PCI_DEVICE_ID_APCI1516		0x1001
-#define PCI_DEVICE_ID_APCI2016		0x1002
-
-/*
  * PCI bar 1 I/O Register map - Digital input/output
  */
 #define APCI1516_DI_REG			0x00
@@ -53,28 +46,32 @@
  */
 #define APCI1516_WDOG_REG		0x00
 
+enum apci1516_boardid {
+	BOARD_APCI1016,
+	BOARD_APCI1516,
+	BOARD_APCI2016,
+};
+
 struct apci1516_boardinfo {
 	const char *name;
-	unsigned short device;
 	int di_nchan;
 	int do_nchan;
 	int has_wdog;
 };
 
 static const struct apci1516_boardinfo apci1516_boardtypes[] = {
-	{
+	[BOARD_APCI1016] = {
 		.name		= "apci1016",
-		.device		= PCI_DEVICE_ID_APCI1016,
 		.di_nchan	= 16,
-	}, {
+	},
+	[BOARD_APCI1516] = {
 		.name		= "apci1516",
-		.device		= PCI_DEVICE_ID_APCI1516,
 		.di_nchan	= 8,
 		.do_nchan	= 8,
 		.has_wdog	= 1,
-	}, {
+	},
+	[BOARD_APCI2016] = {
 		.name		= "apci2016",
-		.device		= PCI_DEVICE_ID_APCI2016,
 		.do_nchan	= 16,
 		.has_wdog	= 1,
 	},
@@ -130,30 +127,17 @@ static int apci1516_reset(struct comedi_device *dev)
 	return 0;
 }
 
-static const void *apci1516_find_boardinfo(struct comedi_device *dev,
-					   struct pci_dev *pcidev)
-{
-	const struct apci1516_boardinfo *this_board;
-	int i;
-
-	for (i = 0; i < dev->driver->num_names; i++) {
-		this_board = &apci1516_boardtypes[i];
-		if (this_board->device == pcidev->device)
-			return this_board;
-	}
-	return NULL;
-}
-
 static int apci1516_auto_attach(struct comedi_device *dev,
-					  unsigned long context_unused)
+				unsigned long context)
 {
 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-	const struct apci1516_boardinfo *this_board;
+	const struct apci1516_boardinfo *this_board = NULL;
 	struct apci1516_private *devpriv;
 	struct comedi_subdevice *s;
 	int ret;
 
-	this_board = apci1516_find_boardinfo(dev, pcidev);
+	if (context < ARRAY_SIZE(apci1516_boardtypes))
+		this_board = &apci1516_boardtypes[context];
 	if (!this_board)
 		return -ENODEV;
 	dev->board_ptr = this_board;
@@ -164,7 +148,7 @@ static int apci1516_auto_attach(struct comedi_device *dev,
 		return -ENOMEM;
 	dev->private = devpriv;
 
-	ret = comedi_pci_enable(pcidev, dev->board_name);
+	ret = comedi_pci_enable(dev);
 	if (ret)
 		return ret;
 
@@ -217,14 +201,11 @@ static int apci1516_auto_attach(struct comedi_device *dev,
 
 static void apci1516_detach(struct comedi_device *dev)
 {
-	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-
 	if (dev->iobase)
 		apci1516_reset(dev);
 	if (dev->subdevices)
 		addi_watchdog_cleanup(&dev->subdevices[2]);
-	if (dev->iobase)
-		comedi_pci_disable(pcidev);
+	comedi_pci_disable(dev);
 }
 
 static struct comedi_driver apci1516_driver = {
@@ -235,15 +216,15 @@ static struct comedi_driver apci1516_driver = {
 };
 
 static int apci1516_pci_probe(struct pci_dev *dev,
-					const struct pci_device_id *ent)
+			      const struct pci_device_id *id)
 {
-	return comedi_pci_auto_config(dev, &apci1516_driver);
+	return comedi_pci_auto_config(dev, &apci1516_driver, id->driver_data);
 }
 
 static DEFINE_PCI_DEVICE_TABLE(apci1516_pci_table) = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, PCI_DEVICE_ID_APCI1016) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, PCI_DEVICE_ID_APCI1516) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, PCI_DEVICE_ID_APCI2016) },
+	{ PCI_VDEVICE(ADDIDATA, 0x1000), BOARD_APCI1016 },
+	{ PCI_VDEVICE(ADDIDATA, 0x1001), BOARD_APCI1516 },
+	{ PCI_VDEVICE(ADDIDATA, 0x1002), BOARD_APCI2016 },
 	{ 0 }
 };
 MODULE_DEVICE_TABLE(pci, apci1516_pci_table);
diff --git a/drivers/staging/comedi/drivers/addi_apci_1564.c b/drivers/staging/comedi/drivers/addi_apci_1564.c
index ddea64d..8de7b48 100644
--- a/drivers/staging/comedi/drivers/addi_apci_1564.c
+++ b/drivers/staging/comedi/drivers/addi_apci_1564.c
@@ -13,8 +13,6 @@
 static const struct addi_board apci1564_boardtypes[] = {
 	{
 		.pc_DriverName		= "apci1564",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
-		.i_DeviceId		= 0x1006,
 		.i_IorangeBase0		= 128,
 		.i_IorangeBase1		= APCI1564_ADDRESS_RANGE,
 		.i_PCIEeprom		= ADDIDATA_EEPROM,
@@ -36,20 +34,25 @@ static const struct addi_board apci1564_boardtypes[] = {
 	},
 };
 
+static int apci1564_auto_attach(struct comedi_device *dev,
+				unsigned long context)
+{
+	dev->board_ptr = &apci1564_boardtypes[0];
+
+	return addi_auto_attach(dev, context);
+}
+
 static struct comedi_driver apci1564_driver = {
 	.driver_name	= "addi_apci_1564",
 	.module		= THIS_MODULE,
-	.auto_attach	= addi_auto_attach,
+	.auto_attach	= apci1564_auto_attach,
 	.detach		= i_ADDI_Detach,
-	.num_names	= ARRAY_SIZE(apci1564_boardtypes),
-	.board_name	= &apci1564_boardtypes[0].pc_DriverName,
-	.offset		= sizeof(struct addi_board),
 };
 
 static int apci1564_pci_probe(struct pci_dev *dev,
-					const struct pci_device_id *ent)
+			      const struct pci_device_id *id)
 {
-	return comedi_pci_auto_config(dev, &apci1564_driver);
+	return comedi_pci_auto_config(dev, &apci1564_driver, id->driver_data);
 }
 
 static DEFINE_PCI_DEVICE_TABLE(apci1564_pci_table) = {
diff --git a/drivers/staging/comedi/drivers/addi_apci_16xx.c b/drivers/staging/comedi/drivers/addi_apci_16xx.c
index e51f800..4c6a9b5 100644
--- a/drivers/staging/comedi/drivers/addi_apci_16xx.c
+++ b/drivers/staging/comedi/drivers/addi_apci_16xx.c
@@ -34,35 +34,29 @@
 #include "../comedidev.h"
 
 /*
- * PCI device ids supported by this driver
- */
-#define PCI_DEVICE_ID_APCI1648		0x1009
-#define PCI_DEVICE_ID_APCI1696		0x100a
-
-/*
  * Register I/O map
  */
 #define APCI16XX_IN_REG(x)		(((x) * 4) + 0x08)
 #define APCI16XX_OUT_REG(x)		(((x) * 4) + 0x14)
 #define APCI16XX_DIR_REG(x)		(((x) * 4) + 0x20)
 
+enum apci16xx_boardid {
+	BOARD_APCI1648,
+	BOARD_APCI1696,
+};
+
 struct apci16xx_boardinfo {
 	const char *name;
-	unsigned short vendor;
-	unsigned short device;
 	int n_chan;
 };
 
 static const struct apci16xx_boardinfo apci16xx_boardtypes[] = {
-	{
+	[BOARD_APCI1648] = {
 		.name		= "apci1648",
-		.vendor		= PCI_VENDOR_ID_ADDIDATA,
-		.device		= PCI_DEVICE_ID_APCI1648,
 		.n_chan		= 48,		/* 2 subdevices */
-	}, {
+	},
+	[BOARD_APCI1696] = {
 		.name		= "apci1696",
-		.vendor		= PCI_VENDOR_ID_ADDIDATA,
-		.device		= PCI_DEVICE_ID_APCI1696,
 		.n_chan		= 96,		/* 3 subdevices */
 	},
 };
@@ -130,39 +124,25 @@ static int apci16xx_dio_insn_bits(struct comedi_device *dev,
 	return insn->n;
 }
 
-static const void *apci16xx_find_boardinfo(struct comedi_device *dev,
-					   struct pci_dev *pcidev)
-{
-	const struct apci16xx_boardinfo *board;
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(apci16xx_boardtypes); i++) {
-		board = &apci16xx_boardtypes[i];
-		if (board->vendor == pcidev->vendor &&
-		    board->device == pcidev->device)
-			return board;
-	}
-	return NULL;
-}
-
 static int apci16xx_auto_attach(struct comedi_device *dev,
-				unsigned long context_unused)
+				unsigned long context)
 {
 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-	const struct apci16xx_boardinfo *board;
+	const struct apci16xx_boardinfo *board = NULL;
 	struct comedi_subdevice *s;
 	unsigned int n_subdevs;
 	unsigned int last;
 	int i;
 	int ret;
 
-	board = apci16xx_find_boardinfo(dev, pcidev);
+	if (context < ARRAY_SIZE(apci16xx_boardtypes))
+		board = &apci16xx_boardtypes[context];
 	if (!board)
 		return -ENODEV;
 	dev->board_ptr = board;
 	dev->board_name = board->name;
 
-	ret = comedi_pci_enable(pcidev, dev->board_name);
+	ret = comedi_pci_enable(dev);
 	if (ret)
 		return ret;
 
@@ -204,35 +184,22 @@ static int apci16xx_auto_attach(struct comedi_device *dev,
 	return 0;
 }
 
-static void apci16xx_detach(struct comedi_device *dev)
-{
-	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-
-	if (pcidev) {
-		if (dev->iobase)
-			comedi_pci_disable(pcidev);
-	}
-}
-
 static struct comedi_driver apci16xx_driver = {
 	.driver_name	= "addi_apci_16xx",
 	.module		= THIS_MODULE,
 	.auto_attach	= apci16xx_auto_attach,
-	.detach		= apci16xx_detach,
-	.num_names	= ARRAY_SIZE(apci16xx_boardtypes),
-	.board_name	= &apci16xx_boardtypes[0].name,
-	.offset		= sizeof(struct apci16xx_boardinfo),
+	.detach		= comedi_pci_disable,
 };
 
 static int apci16xx_pci_probe(struct pci_dev *dev,
-					const struct pci_device_id *ent)
+			      const struct pci_device_id *id)
 {
-	return comedi_pci_auto_config(dev, &apci16xx_driver);
+	return comedi_pci_auto_config(dev, &apci16xx_driver, id->driver_data);
 }
 
 static DEFINE_PCI_DEVICE_TABLE(apci16xx_pci_table) = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, PCI_DEVICE_ID_APCI1648) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, PCI_DEVICE_ID_APCI1696) },
+	{ PCI_VDEVICE(ADDIDATA, 0x1009), BOARD_APCI1648 },
+	{ PCI_VDEVICE(ADDIDATA, 0x100a), BOARD_APCI1696 },
 	{ 0 }
 };
 MODULE_DEVICE_TABLE(pci, apci16xx_pci_table);
diff --git a/drivers/staging/comedi/drivers/addi_apci_1710.c b/drivers/staging/comedi/drivers/addi_apci_1710.c
index e83e829..3640c50 100644
--- a/drivers/staging/comedi/drivers/addi_apci_1710.c
+++ b/drivers/staging/comedi/drivers/addi_apci_1710.c
@@ -21,72 +21,31 @@ static void fpu_end(void)
 #include "addi-data/addi_eeprom.c"
 #include "addi-data/hwdrv_APCI1710.c"
 
-static const struct addi_board apci1710_boardtypes[] = {
-	{
-		.pc_DriverName		= "apci1710",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA_OLD,
-		.i_DeviceId		= APCI1710_BOARD_DEVICE_ID,
-		.interrupt		= v_APCI1710_Interrupt,
-	},
-};
-
 static irqreturn_t v_ADDI_Interrupt(int irq, void *d)
 {
-	struct comedi_device *dev = d;
-	const struct addi_board *this_board = comedi_board(dev);
-
-	this_board->interrupt(irq, d);
+	v_APCI1710_Interrupt(irq, d);
 	return IRQ_RETVAL(1);
 }
 
-static const void *apci1710_find_boardinfo(struct comedi_device *dev,
-					   struct pci_dev *pcidev)
-{
-	const struct addi_board *this_board;
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(apci1710_boardtypes); i++) {
-		this_board = &apci1710_boardtypes[i];
-		if (this_board->i_VendorId == pcidev->vendor &&
-		    this_board->i_DeviceId == pcidev->device)
-			return this_board;
-	}
-	return NULL;
-}
-
 static int apci1710_auto_attach(struct comedi_device *dev,
 					  unsigned long context_unused)
 {
 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-	const struct addi_board *this_board;
 	struct addi_private *devpriv;
 	struct comedi_subdevice *s;
 	int ret;
 
-	this_board = apci1710_find_boardinfo(dev, pcidev);
-	if (!this_board)
-		return -ENODEV;
-	dev->board_ptr = this_board;
-	dev->board_name = this_board->pc_DriverName;
+	dev->board_name = dev->driver->driver_name;
 
 	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
 	if (!devpriv)
 		return -ENOMEM;
 	dev->private = devpriv;
 
-	ret = comedi_pci_enable(pcidev, dev->board_name);
+	ret = comedi_pci_enable(dev);
 	if (ret)
 		return ret;
-
-	if (this_board->i_IorangeBase1)
-		dev->iobase = pci_resource_start(pcidev, 1);
-	else
-		dev->iobase = pci_resource_start(pcidev, 0);
-
-	devpriv->iobase = dev->iobase;
-	devpriv->i_IobaseAmcc = pci_resource_start(pcidev, 0);
-	devpriv->i_IobaseAddon = pci_resource_start(pcidev, 2);
-	devpriv->i_IobaseReserved = pci_resource_start(pcidev, 3);
+	devpriv->s_BoardInfos.ui_Address = pci_resource_start(pcidev, 2);
 
 	if (pcidev->irq > 0) {
 		ret = request_irq(pcidev->irq, v_ADDI_Interrupt, IRQF_SHARED,
@@ -97,24 +56,17 @@ static int apci1710_auto_attach(struct comedi_device *dev,
 
 	i_ADDI_AttachPCI1710(dev);
 
-	devpriv->s_BoardInfos.ui_Address = pci_resource_start(pcidev, 2);
-
 	i_APCI1710_Reset(dev);
 	return 0;
 }
 
 static void apci1710_detach(struct comedi_device *dev)
 {
-	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-
 	if (dev->iobase)
 		i_APCI1710_Reset(dev);
 	if (dev->irq)
 		free_irq(dev->irq, dev);
-	if (pcidev) {
-		if (dev->iobase)
-			comedi_pci_disable(pcidev);
-	}
+	comedi_pci_disable(dev);
 }
 
 static struct comedi_driver apci1710_driver = {
@@ -125,9 +77,9 @@ static struct comedi_driver apci1710_driver = {
 };
 
 static int apci1710_pci_probe(struct pci_dev *dev,
-					const struct pci_device_id *ent)
+			      const struct pci_device_id *id)
 {
-	return comedi_pci_auto_config(dev, &apci1710_driver);
+	return comedi_pci_auto_config(dev, &apci1710_driver, id->driver_data);
 }
 
 static DEFINE_PCI_DEVICE_TABLE(apci1710_pci_table) = {
diff --git a/drivers/staging/comedi/drivers/addi_apci_2032.c b/drivers/staging/comedi/drivers/addi_apci_2032.c
index 9ce1d26..59e092e 100644
--- a/drivers/staging/comedi/drivers/addi_apci_2032.c
+++ b/drivers/staging/comedi/drivers/addi_apci_2032.c
@@ -289,7 +289,7 @@ static int apci2032_auto_attach(struct comedi_device *dev,
 
 	dev->board_name = dev->driver->driver_name;
 
-	ret = comedi_pci_enable(pcidev, dev->board_name);
+	ret = comedi_pci_enable(dev);
 	if (ret)
 		return ret;
 	dev->iobase = pci_resource_start(pcidev, 1);
@@ -350,8 +350,6 @@ static int apci2032_auto_attach(struct comedi_device *dev,
 
 static void apci2032_detach(struct comedi_device *dev)
 {
-	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-
 	if (dev->iobase)
 		apci2032_reset(dev);
 	if (dev->irq)
@@ -360,10 +358,7 @@ static void apci2032_detach(struct comedi_device *dev)
 		kfree(dev->read_subdev->private);
 	if (dev->subdevices)
 		addi_watchdog_cleanup(&dev->subdevices[1]);
-	if (pcidev) {
-		if (dev->iobase)
-			comedi_pci_disable(pcidev);
-	}
+	comedi_pci_disable(dev);
 }
 
 static struct comedi_driver apci2032_driver = {
@@ -374,9 +369,9 @@ static struct comedi_driver apci2032_driver = {
 };
 
 static int apci2032_pci_probe(struct pci_dev *dev,
-					const struct pci_device_id *ent)
+			      const struct pci_device_id *id)
 {
-	return comedi_pci_auto_config(dev, &apci2032_driver);
+	return comedi_pci_auto_config(dev, &apci2032_driver, id->driver_data);
 }
 
 static DEFINE_PCI_DEVICE_TABLE(apci2032_pci_table) = {
diff --git a/drivers/staging/comedi/drivers/addi_apci_2200.c b/drivers/staging/comedi/drivers/addi_apci_2200.c
index b1c4226..0953f65a 100644
--- a/drivers/staging/comedi/drivers/addi_apci_2200.c
+++ b/drivers/staging/comedi/drivers/addi_apci_2200.c
@@ -90,7 +90,7 @@ static int apci2200_auto_attach(struct comedi_device *dev,
 
 	dev->board_name = dev->driver->driver_name;
 
-	ret = comedi_pci_enable(pcidev, dev->board_name);
+	ret = comedi_pci_enable(dev);
 	if (ret)
 		return ret;
 
@@ -130,16 +130,11 @@ static int apci2200_auto_attach(struct comedi_device *dev,
 
 static void apci2200_detach(struct comedi_device *dev)
 {
-	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-
 	if (dev->iobase)
 		apci2200_reset(dev);
 	if (dev->subdevices)
 		addi_watchdog_cleanup(&dev->subdevices[2]);
-	if (pcidev) {
-		if (dev->iobase)
-			comedi_pci_disable(pcidev);
-	}
+	comedi_pci_disable(dev);
 }
 
 static struct comedi_driver apci2200_driver = {
@@ -150,9 +145,9 @@ static struct comedi_driver apci2200_driver = {
 };
 
 static int apci2200_pci_probe(struct pci_dev *dev,
-					const struct pci_device_id *ent)
+			      const struct pci_device_id *id)
 {
-	return comedi_pci_auto_config(dev, &apci2200_driver);
+	return comedi_pci_auto_config(dev, &apci2200_driver, id->driver_data);
 }
 
 static DEFINE_PCI_DEVICE_TABLE(apci2200_pci_table) = {
diff --git a/drivers/staging/comedi/drivers/addi_apci_3120.c b/drivers/staging/comedi/drivers/addi_apci_3120.c
index 917234d..1c5ac16 100644
--- a/drivers/staging/comedi/drivers/addi_apci_3120.c
+++ b/drivers/staging/comedi/drivers/addi_apci_3120.c
@@ -8,11 +8,14 @@
 
 #include "addi-data/hwdrv_apci3120.c"
 
+enum apci3120_boardid {
+	BOARD_APCI3120,
+	BOARD_APCI3001,
+};
+
 static const struct addi_board apci3120_boardtypes[] = {
-	{
+	[BOARD_APCI3120] = {
 		.pc_DriverName		= "apci3120",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA_OLD,
-		.i_DeviceId		= 0x818D,
 		.i_NbrAiChannel		= 16,
 		.i_NbrAiChannelDiff	= 8,
 		.i_AiChannelList	= 16,
@@ -23,10 +26,9 @@ static const struct addi_board apci3120_boardtypes[] = {
 		.i_NbrDoChannel		= 4,
 		.i_DoMaxdata		= 0x0f,
 		.interrupt		= v_APCI3120_Interrupt,
-	}, {
+	},
+	[BOARD_APCI3001] = {
 		.pc_DriverName		= "apci3001",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA_OLD,
-		.i_DeviceId		= 0x828D,
 		.i_NbrAiChannel		= 16,
 		.i_NbrAiChannelDiff	= 8,
 		.i_AiChannelList	= 16,
@@ -47,31 +49,17 @@ static irqreturn_t v_ADDI_Interrupt(int irq, void *d)
 	return IRQ_RETVAL(1);
 }
 
-static const void *apci3120_find_boardinfo(struct comedi_device *dev,
-					   struct pci_dev *pcidev)
-{
-	const struct addi_board *this_board;
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(apci3120_boardtypes); i++) {
-		this_board = &apci3120_boardtypes[i];
-		if (this_board->i_VendorId == pcidev->vendor &&
-		    this_board->i_DeviceId == pcidev->device)
-			return this_board;
-	}
-	return NULL;
-}
-
 static int apci3120_auto_attach(struct comedi_device *dev,
-					  unsigned long context_unused)
+				unsigned long context)
 {
 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-	const struct addi_board *this_board;
+	const struct addi_board *this_board = NULL;
 	struct addi_private *devpriv;
 	struct comedi_subdevice *s;
 	int ret, pages, i;
 
-	this_board = apci3120_find_boardinfo(dev, pcidev);
+	if (context < ARRAY_SIZE(apci3120_boardtypes))
+		this_board = &apci3120_boardtypes[context];
 	if (!this_board)
 		return -ENODEV;
 	dev->board_ptr = this_board;
@@ -82,7 +70,7 @@ static int apci3120_auto_attach(struct comedi_device *dev,
 		return -ENOMEM;
 	dev->private = devpriv;
 
-	ret = comedi_pci_enable(pcidev, dev->board_name);
+	ret = comedi_pci_enable(dev);
 	if (ret)
 		return ret;
 	pci_set_master(pcidev);
@@ -215,7 +203,6 @@ static int apci3120_auto_attach(struct comedi_device *dev,
 
 static void apci3120_detach(struct comedi_device *dev)
 {
-	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
 	struct addi_private *devpriv = dev->private;
 
 	if (devpriv) {
@@ -234,10 +221,7 @@ static void apci3120_detach(struct comedi_device *dev)
 				devpriv->ui_DmaBufferPages[1]);
 		}
 	}
-	if (pcidev) {
-		if (dev->iobase)
-			comedi_pci_disable(pcidev);
-	}
+	comedi_pci_disable(dev);
 }
 
 static struct comedi_driver apci3120_driver = {
@@ -248,14 +232,14 @@ static struct comedi_driver apci3120_driver = {
 };
 
 static int apci3120_pci_probe(struct pci_dev *dev,
-					const struct pci_device_id *ent)
+			      const struct pci_device_id *id)
 {
-	return comedi_pci_auto_config(dev, &apci3120_driver);
+	return comedi_pci_auto_config(dev, &apci3120_driver, id->driver_data);
 }
 
 static DEFINE_PCI_DEVICE_TABLE(apci3120_pci_table) = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA_OLD, 0x818d) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA_OLD, 0x828d) },
+	{ PCI_VDEVICE(ADDIDATA_OLD, 0x818d), BOARD_APCI3120 },
+	{ PCI_VDEVICE(ADDIDATA_OLD, 0x828d), BOARD_APCI3001 },
 	{ 0 }
 };
 MODULE_DEVICE_TABLE(pci, apci3120_pci_table);
diff --git a/drivers/staging/comedi/drivers/addi_apci_3200.c b/drivers/staging/comedi/drivers/addi_apci_3200.c
index 90ee4f8..4b492a0 100644
--- a/drivers/staging/comedi/drivers/addi_apci_3200.c
+++ b/drivers/staging/comedi/drivers/addi_apci_3200.c
@@ -22,11 +22,14 @@ static void fpu_end(void)
 #include "addi-data/hwdrv_apci3200.c"
 #include "addi-data/addi_common.c"
 
+enum apci3200_boardid {
+	BOARD_APCI3200,
+	BOARD_APCI3300,
+};
+
 static const struct addi_board apci3200_boardtypes[] = {
-	{
+	[BOARD_APCI3200] = {
 		.pc_DriverName		= "apci3200",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
-		.i_DeviceId		= 0x3000,
 		.i_IorangeBase0		= 128,
 		.i_IorangeBase1		= 256,
 		.i_IorangeBase2		= 4,
@@ -53,10 +56,9 @@ static const struct addi_board apci3200_boardtypes[] = {
 		.ai_cancel		= i_APCI3200_StopCyclicAcquisition,
 		.di_bits		= apci3200_di_insn_bits,
 		.do_bits		= apci3200_do_insn_bits,
-	}, {
+	},
+	[BOARD_APCI3300] = {
 		.pc_DriverName		= "apci3300",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
-		.i_DeviceId		= 0x3007,
 		.i_IorangeBase0		= 128,
 		.i_IorangeBase1		= 256,
 		.i_IorangeBase2		= 4,
@@ -85,29 +87,40 @@ static const struct addi_board apci3200_boardtypes[] = {
 	},
 };
 
-static DEFINE_PCI_DEVICE_TABLE(apci3200_pci_table) = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3000) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3007) },
-	{ 0 }
-};
-MODULE_DEVICE_TABLE(pci, apci3200_pci_table);
+static int apci3200_auto_attach(struct comedi_device *dev,
+				unsigned long context)
+{
+	const struct addi_board *board = NULL;
+
+	if (context < ARRAY_SIZE(apci3200_boardtypes))
+		board = &apci3200_boardtypes[context];
+	if (!board)
+		return -ENODEV;
+	dev->board_ptr = board;
+
+	return addi_auto_attach(dev, context);
+}
 
 static struct comedi_driver apci3200_driver = {
 	.driver_name	= "addi_apci_3200",
 	.module		= THIS_MODULE,
-	.auto_attach	= addi_auto_attach,
+	.auto_attach	= apci3200_auto_attach,
 	.detach		= i_ADDI_Detach,
-	.num_names	= ARRAY_SIZE(apci3200_boardtypes),
-	.board_name	= &apci3200_boardtypes[0].pc_DriverName,
-	.offset		= sizeof(struct addi_board),
 };
 
 static int apci3200_pci_probe(struct pci_dev *dev,
-					const struct pci_device_id *ent)
+			      const struct pci_device_id *id)
 {
-	return comedi_pci_auto_config(dev, &apci3200_driver);
+	return comedi_pci_auto_config(dev, &apci3200_driver, id->driver_data);
 }
 
+static DEFINE_PCI_DEVICE_TABLE(apci3200_pci_table) = {
+	{ PCI_VDEVICE(ADDIDATA, 0x3000), BOARD_APCI3200 },
+	{ PCI_VDEVICE(ADDIDATA, 0x3007), BOARD_APCI3300 },
+	{ 0 }
+};
+MODULE_DEVICE_TABLE(pci, apci3200_pci_table);
+
 static struct pci_driver apci3200_pci_driver = {
 	.name		= "addi_apci_3200",
 	.id_table	= apci3200_pci_table,
diff --git a/drivers/staging/comedi/drivers/addi_apci_3501.c b/drivers/staging/comedi/drivers/addi_apci_3501.c
index 786fcaf..75a36e36 100644
--- a/drivers/staging/comedi/drivers/addi_apci_3501.c
+++ b/drivers/staging/comedi/drivers/addi_apci_3501.c
@@ -346,7 +346,7 @@ static int apci3501_auto_attach(struct comedi_device *dev,
 		return -ENOMEM;
 	dev->private = devpriv;
 
-	ret = comedi_pci_enable(pcidev, dev->board_name);
+	ret = comedi_pci_enable(dev);
 	if (ret)
 		return ret;
 
@@ -423,16 +423,11 @@ static int apci3501_auto_attach(struct comedi_device *dev,
 
 static void apci3501_detach(struct comedi_device *dev)
 {
-	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-
 	if (dev->iobase)
 		apci3501_reset(dev);
 	if (dev->irq)
 		free_irq(dev->irq, dev);
-	if (pcidev) {
-		if (dev->iobase)
-			comedi_pci_disable(pcidev);
-	}
+	comedi_pci_disable(dev);
 }
 
 static struct comedi_driver apci3501_driver = {
@@ -443,9 +438,9 @@ static struct comedi_driver apci3501_driver = {
 };
 
 static int apci3501_pci_probe(struct pci_dev *dev,
-					const struct pci_device_id *ent)
+			      const struct pci_device_id *id)
 {
-	return comedi_pci_auto_config(dev, &apci3501_driver);
+	return comedi_pci_auto_config(dev, &apci3501_driver, id->driver_data);
 }
 
 static DEFINE_PCI_DEVICE_TABLE(apci3501_pci_table) = {
diff --git a/drivers/staging/comedi/drivers/addi_apci_3xxx.c b/drivers/staging/comedi/drivers/addi_apci_3xxx.c
index 09d4b21..1afc62c 100644
--- a/drivers/staging/comedi/drivers/addi_apci_3xxx.c
+++ b/drivers/staging/comedi/drivers/addi_apci_3xxx.c
@@ -10,11 +10,37 @@
 #include "addi-data/hwdrv_apci3xxx.c"
 #include "addi-data/addi_common.c"
 
+enum apci3xxx_boardid {
+	BOARD_APCI3000_16,
+	BOARD_APCI3000_8,
+	BOARD_APCI3000_4,
+	BOARD_APCI3006_16,
+	BOARD_APCI3006_8,
+	BOARD_APCI3006_4,
+	BOARD_APCI3010_16,
+	BOARD_APCI3010_8,
+	BOARD_APCI3010_4,
+	BOARD_APCI3016_16,
+	BOARD_APCI3016_8,
+	BOARD_APCI3016_4,
+	BOARD_APCI3100_16_4,
+	BOARD_APCI3100_8_4,
+	BOARD_APCI3106_16_4,
+	BOARD_APCI3106_8_4,
+	BOARD_APCI3110_16_4,
+	BOARD_APCI3110_8_4,
+	BOARD_APCI3116_16_4,
+	BOARD_APCI3116_8_4,
+	BOARD_APCI3003,
+	BOARD_APCI3002_16,
+	BOARD_APCI3002_8,
+	BOARD_APCI3002_4,
+	BOARD_APCI3500,
+};
+
 static const struct addi_board apci3xxx_boardtypes[] = {
-	{
+	[BOARD_APCI3000_16] = {
 		.pc_DriverName		= "apci3000-16",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
-		.i_DeviceId		= 0x3010,
 		.i_IorangeBase0		= 256,
 		.i_IorangeBase1		= 256,
 		.i_IorangeBase2		= 256,
@@ -37,10 +63,9 @@ static const struct addi_board apci3xxx_boardtypes[] = {
 		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
 		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
 		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
-	}, {
+	},
+	[BOARD_APCI3000_8] = {
 		.pc_DriverName		= "apci3000-8",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
-		.i_DeviceId		= 0x300F,
 		.i_IorangeBase0		= 256,
 		.i_IorangeBase1		= 256,
 		.i_IorangeBase2		= 256,
@@ -63,10 +88,9 @@ static const struct addi_board apci3xxx_boardtypes[] = {
 		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
 		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
 		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
-	}, {
+	},
+	[BOARD_APCI3000_4] = {
 		.pc_DriverName		= "apci3000-4",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
-		.i_DeviceId		= 0x300E,
 		.i_IorangeBase0		= 256,
 		.i_IorangeBase1		= 256,
 		.i_IorangeBase2		= 256,
@@ -89,10 +113,9 @@ static const struct addi_board apci3xxx_boardtypes[] = {
 		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
 		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
 		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
-	}, {
+	},
+	[BOARD_APCI3006_16] = {
 		.pc_DriverName		= "apci3006-16",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
-		.i_DeviceId		= 0x3013,
 		.i_IorangeBase0		= 256,
 		.i_IorangeBase1		= 256,
 		.i_IorangeBase2		= 256,
@@ -115,10 +138,9 @@ static const struct addi_board apci3xxx_boardtypes[] = {
 		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
 		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
 		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
-	}, {
+	},
+	[BOARD_APCI3006_8] = {
 		.pc_DriverName		= "apci3006-8",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
-		.i_DeviceId		= 0x3014,
 		.i_IorangeBase0		= 256,
 		.i_IorangeBase1		= 256,
 		.i_IorangeBase2		= 256,
@@ -141,10 +163,9 @@ static const struct addi_board apci3xxx_boardtypes[] = {
 		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
 		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
 		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
-	}, {
+	},
+	[BOARD_APCI3006_4] = {
 		.pc_DriverName		= "apci3006-4",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
-		.i_DeviceId		= 0x3015,
 		.i_IorangeBase0		= 256,
 		.i_IorangeBase1		= 256,
 		.i_IorangeBase2		= 256,
@@ -167,10 +188,9 @@ static const struct addi_board apci3xxx_boardtypes[] = {
 		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
 		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
 		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
-	}, {
+	},
+	[BOARD_APCI3010_16] = {
 		.pc_DriverName		= "apci3010-16",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
-		.i_DeviceId		= 0x3016,
 		.i_IorangeBase0		= 256,
 		.i_IorangeBase1		= 256,
 		.i_IorangeBase2		= 256,
@@ -198,10 +218,9 @@ static const struct addi_board apci3xxx_boardtypes[] = {
 		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
 		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
 		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
-	}, {
+	},
+	[BOARD_APCI3010_8] = {
 		.pc_DriverName		= "apci3010-8",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
-		.i_DeviceId		= 0x3017,
 		.i_IorangeBase0		= 256,
 		.i_IorangeBase1		= 256,
 		.i_IorangeBase2		= 256,
@@ -229,10 +248,9 @@ static const struct addi_board apci3xxx_boardtypes[] = {
 		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
 		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
 		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
-	}, {
+	},
+	[BOARD_APCI3010_4] = {
 		.pc_DriverName		= "apci3010-4",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
-		.i_DeviceId		= 0x3018,
 		.i_IorangeBase0		= 256,
 		.i_IorangeBase1		= 256,
 		.i_IorangeBase2		= 256,
@@ -260,10 +278,9 @@ static const struct addi_board apci3xxx_boardtypes[] = {
 		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
 		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
 		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
-	}, {
+	},
+	[BOARD_APCI3016_16] = {
 		.pc_DriverName		= "apci3016-16",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
-		.i_DeviceId		= 0x3019,
 		.i_IorangeBase0		= 256,
 		.i_IorangeBase1		= 256,
 		.i_IorangeBase2		= 256,
@@ -291,10 +308,9 @@ static const struct addi_board apci3xxx_boardtypes[] = {
 		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
 		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
 		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
-	}, {
+	},
+	[BOARD_APCI3016_8] = {
 		.pc_DriverName		= "apci3016-8",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
-		.i_DeviceId		= 0x301A,
 		.i_IorangeBase0		= 256,
 		.i_IorangeBase1		= 256,
 		.i_IorangeBase2		= 256,
@@ -322,10 +338,9 @@ static const struct addi_board apci3xxx_boardtypes[] = {
 		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
 		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
 		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
-	}, {
+	},
+	[BOARD_APCI3016_4] = {
 		.pc_DriverName		= "apci3016-4",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
-		.i_DeviceId		= 0x301B,
 		.i_IorangeBase0		= 256,
 		.i_IorangeBase1		= 256,
 		.i_IorangeBase2		= 256,
@@ -353,10 +368,9 @@ static const struct addi_board apci3xxx_boardtypes[] = {
 		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
 		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
 		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
-	}, {
+	},
+	[BOARD_APCI3100_16_4] = {
 		.pc_DriverName		= "apci3100-16-4",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
-		.i_DeviceId		= 0x301C,
 		.i_IorangeBase0		= 256,
 		.i_IorangeBase1		= 256,
 		.i_IorangeBase2		= 256,
@@ -383,10 +397,9 @@ static const struct addi_board apci3xxx_boardtypes[] = {
 		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
 		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
 		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
-	}, {
+	},
+	[BOARD_APCI3100_8_4] = {
 		.pc_DriverName		= "apci3100-8-4",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
-		.i_DeviceId		= 0x301D,
 		.i_IorangeBase0		= 256,
 		.i_IorangeBase1		= 256,
 		.i_IorangeBase2		= 256,
@@ -413,10 +426,9 @@ static const struct addi_board apci3xxx_boardtypes[] = {
 		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
 		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
 		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
-	}, {
+	},
+	[BOARD_APCI3106_16_4] = {
 		.pc_DriverName		= "apci3106-16-4",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
-		.i_DeviceId		= 0x301E,
 		.i_IorangeBase0		= 256,
 		.i_IorangeBase1		= 256,
 		.i_IorangeBase2		= 256,
@@ -443,10 +455,9 @@ static const struct addi_board apci3xxx_boardtypes[] = {
 		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
 		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
 		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
-	}, {
+	},
+	[BOARD_APCI3106_8_4] = {
 		.pc_DriverName		= "apci3106-8-4",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
-		.i_DeviceId		= 0x301F,
 		.i_IorangeBase0		= 256,
 		.i_IorangeBase1		= 256,
 		.i_IorangeBase2		= 256,
@@ -473,10 +484,9 @@ static const struct addi_board apci3xxx_boardtypes[] = {
 		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
 		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
 		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
-	}, {
+	},
+	[BOARD_APCI3110_16_4] = {
 		.pc_DriverName		= "apci3110-16-4",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
-		.i_DeviceId		= 0x3020,
 		.i_IorangeBase0		= 256,
 		.i_IorangeBase1		= 256,
 		.i_IorangeBase2		= 256,
@@ -508,10 +518,9 @@ static const struct addi_board apci3xxx_boardtypes[] = {
 		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
 		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
 		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
-	}, {
+	},
+	[BOARD_APCI3110_8_4] = {
 		.pc_DriverName		= "apci3110-8-4",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
-		.i_DeviceId		= 0x3021,
 		.i_IorangeBase0		= 256,
 		.i_IorangeBase1		= 256,
 		.i_IorangeBase2		= 256,
@@ -543,10 +552,9 @@ static const struct addi_board apci3xxx_boardtypes[] = {
 		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
 		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
 		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
-	}, {
+	},
+	[BOARD_APCI3116_16_4] = {
 		.pc_DriverName		= "apci3116-16-4",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
-		.i_DeviceId		= 0x3022,
 		.i_IorangeBase0		= 256,
 		.i_IorangeBase1		= 256,
 		.i_IorangeBase2		= 256,
@@ -578,10 +586,9 @@ static const struct addi_board apci3xxx_boardtypes[] = {
 		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
 		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
 		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
-	}, {
+	},
+	[BOARD_APCI3116_8_4] = {
 		.pc_DriverName		= "apci3116-8-4",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
-		.i_DeviceId		= 0x3023,
 		.i_IorangeBase0		= 256,
 		.i_IorangeBase1		= 256,
 		.i_IorangeBase2		= 256,
@@ -613,10 +620,9 @@ static const struct addi_board apci3xxx_boardtypes[] = {
 		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
 		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
 		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
-	}, {
+	},
+	[BOARD_APCI3003] = {
 		.pc_DriverName		= "apci3003",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
-		.i_DeviceId		= 0x300B,
 		.i_IorangeBase0		= 256,
 		.i_IorangeBase1		= 256,
 		.i_IorangeBase2		= 256,
@@ -638,10 +644,9 @@ static const struct addi_board apci3xxx_boardtypes[] = {
 		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
 		.di_bits		= apci3xxx_di_insn_bits,
 		.do_bits		= apci3xxx_do_insn_bits,
-	}, {
+	},
+	[BOARD_APCI3002_16] = {
 		.pc_DriverName		= "apci3002-16",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
-		.i_DeviceId		= 0x3002,
 		.i_IorangeBase0		= 256,
 		.i_IorangeBase1		= 256,
 		.i_IorangeBase2		= 256,
@@ -663,10 +668,9 @@ static const struct addi_board apci3xxx_boardtypes[] = {
 		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
 		.di_bits		= apci3xxx_di_insn_bits,
 		.do_bits		= apci3xxx_do_insn_bits,
-	}, {
+	},
+	[BOARD_APCI3002_8] = {
 		.pc_DriverName		= "apci3002-8",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
-		.i_DeviceId		= 0x3003,
 		.i_IorangeBase0		= 256,
 		.i_IorangeBase1		= 256,
 		.i_IorangeBase2		= 256,
@@ -688,10 +692,9 @@ static const struct addi_board apci3xxx_boardtypes[] = {
 		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
 		.di_bits		= apci3xxx_di_insn_bits,
 		.do_bits		= apci3xxx_do_insn_bits,
-	}, {
+	},
+	[BOARD_APCI3002_4] = {
 		.pc_DriverName		= "apci3002-4",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
-		.i_DeviceId		= 0x3004,
 		.i_IorangeBase0		= 256,
 		.i_IorangeBase1		= 256,
 		.i_IorangeBase2		= 256,
@@ -713,10 +716,9 @@ static const struct addi_board apci3xxx_boardtypes[] = {
 		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
 		.di_bits		= apci3xxx_di_insn_bits,
 		.do_bits		= apci3xxx_do_insn_bits,
-	}, {
+	},
+	[BOARD_APCI3500] = {
 		.pc_DriverName		= "apci3500",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
-		.i_DeviceId		= 0x3024,
 		.i_IorangeBase0		= 256,
 		.i_IorangeBase1		= 256,
 		.i_IorangeBase2		= 256,
@@ -737,48 +739,59 @@ static const struct addi_board apci3xxx_boardtypes[] = {
 	},
 };
 
+static int apci3xxx_auto_attach(struct comedi_device *dev,
+				unsigned long context)
+{
+	const struct addi_board *board = NULL;
+
+	if (context < ARRAY_SIZE(apci3xxx_boardtypes))
+		board = &apci3xxx_boardtypes[context];
+	if (!board)
+		return -ENODEV;
+	dev->board_ptr = board;
+
+	return addi_auto_attach(dev, context);
+}
+
 static struct comedi_driver apci3xxx_driver = {
 	.driver_name	= "addi_apci_3xxx",
 	.module		= THIS_MODULE,
-	.auto_attach	= addi_auto_attach,
+	.auto_attach	= apci3xxx_auto_attach,
 	.detach		= i_ADDI_Detach,
-	.num_names	= ARRAY_SIZE(apci3xxx_boardtypes),
-	.board_name	= &apci3xxx_boardtypes[0].pc_DriverName,
-	.offset		= sizeof(struct addi_board),
 };
 
 static int apci3xxx_pci_probe(struct pci_dev *dev,
-					const struct pci_device_id *ent)
+			      const struct pci_device_id *id)
 {
-	return comedi_pci_auto_config(dev, &apci3xxx_driver);
+	return comedi_pci_auto_config(dev, &apci3xxx_driver, id->driver_data);
 }
 
 static DEFINE_PCI_DEVICE_TABLE(apci3xxx_pci_table) = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3010) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x300f) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x300e) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3013) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3014) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3015) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3016) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3017) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3018) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3019) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x301a) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x301b) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x301c) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x301d) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x301e) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x301f) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3020) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3021) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3022) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3023) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x300B) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3002) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3003) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3004) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3024) },
+	{ PCI_VDEVICE(ADDIDATA, 0x3010), BOARD_APCI3000_16 },
+	{ PCI_VDEVICE(ADDIDATA, 0x300f), BOARD_APCI3000_8 },
+	{ PCI_VDEVICE(ADDIDATA, 0x300e), BOARD_APCI3000_4 },
+	{ PCI_VDEVICE(ADDIDATA, 0x3013), BOARD_APCI3006_16 },
+	{ PCI_VDEVICE(ADDIDATA, 0x3014), BOARD_APCI3006_8 },
+	{ PCI_VDEVICE(ADDIDATA, 0x3015), BOARD_APCI3006_4 },
+	{ PCI_VDEVICE(ADDIDATA, 0x3016), BOARD_APCI3010_16 },
+	{ PCI_VDEVICE(ADDIDATA, 0x3017), BOARD_APCI3010_8 },
+	{ PCI_VDEVICE(ADDIDATA, 0x3018), BOARD_APCI3010_4 },
+	{ PCI_VDEVICE(ADDIDATA, 0x3019), BOARD_APCI3016_16 },
+	{ PCI_VDEVICE(ADDIDATA, 0x301a), BOARD_APCI3016_8 },
+	{ PCI_VDEVICE(ADDIDATA, 0x301b), BOARD_APCI3016_4 },
+	{ PCI_VDEVICE(ADDIDATA, 0x301c), BOARD_APCI3100_16_4 },
+	{ PCI_VDEVICE(ADDIDATA, 0x301d), BOARD_APCI3100_8_4 },
+	{ PCI_VDEVICE(ADDIDATA, 0x301e), BOARD_APCI3106_16_4 },
+	{ PCI_VDEVICE(ADDIDATA, 0x301f), BOARD_APCI3106_8_4 },
+	{ PCI_VDEVICE(ADDIDATA, 0x3020), BOARD_APCI3110_16_4 },
+	{ PCI_VDEVICE(ADDIDATA, 0x3021), BOARD_APCI3110_8_4 },
+	{ PCI_VDEVICE(ADDIDATA, 0x3022), BOARD_APCI3116_16_4 },
+	{ PCI_VDEVICE(ADDIDATA, 0x3023), BOARD_APCI3116_8_4 },
+	{ PCI_VDEVICE(ADDIDATA, 0x300B), BOARD_APCI3003 },
+	{ PCI_VDEVICE(ADDIDATA, 0x3002), BOARD_APCI3002_16 },
+	{ PCI_VDEVICE(ADDIDATA, 0x3003), BOARD_APCI3002_8 },
+	{ PCI_VDEVICE(ADDIDATA, 0x3004), BOARD_APCI3002_4 },
+	{ PCI_VDEVICE(ADDIDATA, 0x3024), BOARD_APCI3500 },
 	{ 0 }
 };
 MODULE_DEVICE_TABLE(pci, apci3xxx_pci_table);
diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c
index 7b3e3316..8a438ff 100644
--- a/drivers/staging/comedi/drivers/adl_pci6208.c
+++ b/drivers/staging/comedi/drivers/adl_pci6208.c
@@ -47,12 +47,6 @@ References:
 #include "../comedidev.h"
 
 /*
- * ADLINK PCI Device ID's supported by this driver
- */
-#define PCI_DEVICE_ID_PCI6208		0x6208
-#define PCI_DEVICE_ID_PCI6216		0x6216
-
-/*
  * PCI-6208/6216-GL register map
  */
 #define PCI6208_AO_CONTROL(x)		(0x00 + (2 * (x)))
@@ -66,20 +60,23 @@ References:
 
 #define PCI6208_MAX_AO_CHANNELS		16
 
+enum pci6208_boardid {
+	BOARD_PCI6208,
+	BOARD_PCI6216,
+};
+
 struct pci6208_board {
 	const char *name;
-	unsigned short dev_id;
 	int ao_chans;
 };
 
 static const struct pci6208_board pci6208_boards[] = {
-	{
+	[BOARD_PCI6208] = {
 		.name		= "adl_pci6208",
-		.dev_id		= PCI_DEVICE_ID_PCI6208,
 		.ao_chans	= 8,
-	}, {
+	},
+	[BOARD_PCI6216] = {
 		.name		= "adl_pci6216",
-		.dev_id		= PCI_DEVICE_ID_PCI6216,
 		.ao_chans	= 16,
 	},
 };
@@ -162,31 +159,18 @@ static int pci6208_do_insn_bits(struct comedi_device *dev,
 	return insn->n;
 }
 
-static const void *pci6208_find_boardinfo(struct comedi_device *dev,
-					  struct pci_dev *pcidev)
-{
-	const struct pci6208_board *boardinfo;
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(pci6208_boards); i++) {
-		boardinfo = &pci6208_boards[i];
-		if (boardinfo->dev_id == pcidev->device)
-			return boardinfo;
-	}
-	return NULL;
-}
-
 static int pci6208_auto_attach(struct comedi_device *dev,
-					 unsigned long context_unused)
+			       unsigned long context)
 {
 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-	const struct pci6208_board *boardinfo;
+	const struct pci6208_board *boardinfo = NULL;
 	struct pci6208_private *devpriv;
 	struct comedi_subdevice *s;
 	unsigned int val;
 	int ret;
 
-	boardinfo = pci6208_find_boardinfo(dev, pcidev);
+	if (context < ARRAY_SIZE(pci6208_boards))
+		boardinfo = &pci6208_boards[context];
 	if (!boardinfo)
 		return -ENODEV;
 	dev->board_ptr = boardinfo;
@@ -197,7 +181,7 @@ static int pci6208_auto_attach(struct comedi_device *dev,
 		return -ENOMEM;
 	dev->private = devpriv;
 
-	ret = comedi_pci_enable(pcidev, dev->board_name);
+	ret = comedi_pci_enable(dev);
 	if (ret)
 		return ret;
 	dev->iobase = pci_resource_start(pcidev, 2);
@@ -249,32 +233,23 @@ static int pci6208_auto_attach(struct comedi_device *dev,
 	return 0;
 }
 
-static void pci6208_detach(struct comedi_device *dev)
-{
-	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-
-	if (pcidev) {
-		if (dev->iobase)
-			comedi_pci_disable(pcidev);
-	}
-}
-
 static struct comedi_driver adl_pci6208_driver = {
 	.driver_name	= "adl_pci6208",
 	.module		= THIS_MODULE,
 	.auto_attach	= pci6208_auto_attach,
-	.detach		= pci6208_detach,
+	.detach		= comedi_pci_disable,
 };
 
 static int adl_pci6208_pci_probe(struct pci_dev *dev,
-					   const struct pci_device_id *ent)
+				 const struct pci_device_id *id)
 {
-	return comedi_pci_auto_config(dev, &adl_pci6208_driver);
+	return comedi_pci_auto_config(dev, &adl_pci6208_driver,
+				      id->driver_data);
 }
 
 static DEFINE_PCI_DEVICE_TABLE(adl_pci6208_pci_table) = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI6208) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI6216) },
+	{ PCI_VDEVICE(ADLINK, 0x6208), BOARD_PCI6208 },
+	{ PCI_VDEVICE(ADLINK, 0x6216), BOARD_PCI6216 },
 	{ 0 }
 };
 MODULE_DEVICE_TABLE(pci, adl_pci6208_pci_table);
diff --git a/drivers/staging/comedi/drivers/adl_pci7x3x.c b/drivers/staging/comedi/drivers/adl_pci7x3x.c
index f27f48e..e396074 100644
--- a/drivers/staging/comedi/drivers/adl_pci7x3x.c
+++ b/drivers/staging/comedi/drivers/adl_pci7x3x.c
@@ -53,60 +53,57 @@ Configuration Options: not applicable, uses comedi PCI auto config
 #include "../comedidev.h"
 
 /*
- * PCI Device ID's supported by this driver
- */
-#define PCI_DEVICE_ID_PCI7230	0x7230
-#define PCI_DEVICE_ID_PCI7233	0x7233
-#define PCI_DEVICE_ID_PCI7234	0x7234
-#define PCI_DEVICE_ID_PCI7432	0x7432
-#define PCI_DEVICE_ID_PCI7433	0x7433
-#define PCI_DEVICE_ID_PCI7434	0x7434
-
-/*
  * Register I/O map (32-bit access only)
  */
 #define PCI7X3X_DIO_REG		0x00
 #define PCI743X_DIO_REG		0x04
 
+enum apci1516_boardid {
+	BOARD_PCI7230,
+	BOARD_PCI7233,
+	BOARD_PCI7234,
+	BOARD_PCI7432,
+	BOARD_PCI7433,
+	BOARD_PCI7434,
+};
+
 struct adl_pci7x3x_boardinfo {
 	const char *name;
-	unsigned short device;
 	int nsubdevs;
 	int di_nchan;
 	int do_nchan;
 };
 
 static const struct adl_pci7x3x_boardinfo adl_pci7x3x_boards[] = {
-	{
+	[BOARD_PCI7230] = {
 		.name		= "adl_pci7230",
-		.device		= PCI_DEVICE_ID_PCI7230,
 		.nsubdevs	= 2,
 		.di_nchan	= 16,
 		.do_nchan	= 16,
-	}, {
+	},
+	[BOARD_PCI7233] = {
 		.name		= "adl_pci7233",
-		.device		= PCI_DEVICE_ID_PCI7233,
 		.nsubdevs	= 1,
 		.di_nchan	= 32,
-	}, {
+	},
+	[BOARD_PCI7234] = {
 		.name		= "adl_pci7234",
-		.device		= PCI_DEVICE_ID_PCI7234,
 		.nsubdevs	= 1,
 		.do_nchan	= 32,
-	}, {
+	},
+	[BOARD_PCI7432] = {
 		.name		= "adl_pci7432",
-		.device		= PCI_DEVICE_ID_PCI7432,
 		.nsubdevs	= 2,
 		.di_nchan	= 32,
 		.do_nchan	= 32,
-	}, {
+	},
+	[BOARD_PCI7433] = {
 		.name		= "adl_pci7433",
-		.device		= PCI_DEVICE_ID_PCI7433,
 		.nsubdevs	= 2,
 		.di_nchan	= 64,
-	}, {
+	},
+	[BOARD_PCI7434] = {
 		.name		= "adl_pci7434",
-		.device		= PCI_DEVICE_ID_PCI7434,
 		.nsubdevs	= 2,
 		.do_nchan	= 64,
 	}
@@ -150,37 +147,24 @@ static int adl_pci7x3x_di_insn_bits(struct comedi_device *dev,
 	return insn->n;
 }
 
-static const void *adl_pci7x3x_find_boardinfo(struct comedi_device *dev,
-					      struct pci_dev *pcidev)
-{
-	const struct adl_pci7x3x_boardinfo *board;
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(adl_pci7x3x_boards); i++) {
-		board = &adl_pci7x3x_boards[i];
-		if (pcidev->device == board->device)
-			return board;
-	}
-	return NULL;
-}
-
 static int adl_pci7x3x_auto_attach(struct comedi_device *dev,
-					     unsigned long context_unused)
+				   unsigned long context)
 {
 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-	const struct adl_pci7x3x_boardinfo *board;
+	const struct adl_pci7x3x_boardinfo *board = NULL;
 	struct comedi_subdevice *s;
 	int subdev;
 	int nchan;
 	int ret;
 
-	board = adl_pci7x3x_find_boardinfo(dev, pcidev);
+	if (context < ARRAY_SIZE(adl_pci7x3x_boards))
+		board = &adl_pci7x3x_boards[context];
 	if (!board)
 		return -ENODEV;
 	dev->board_ptr = board;
 	dev->board_name = board->name;
 
-	ret = comedi_pci_enable(pcidev, dev->board_name);
+	ret = comedi_pci_enable(dev);
 	if (ret)
 		return ret;
 	dev->iobase = pci_resource_start(pcidev, 2);
@@ -275,36 +259,27 @@ static int adl_pci7x3x_auto_attach(struct comedi_device *dev,
 	return 0;
 }
 
-static void adl_pci7x3x_detach(struct comedi_device *dev)
-{
-	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-
-	if (pcidev) {
-		if (dev->iobase)
-			comedi_pci_disable(pcidev);
-	}
-}
-
 static struct comedi_driver adl_pci7x3x_driver = {
 	.driver_name	= "adl_pci7x3x",
 	.module		= THIS_MODULE,
 	.auto_attach	= adl_pci7x3x_auto_attach,
-	.detach		= adl_pci7x3x_detach,
+	.detach		= comedi_pci_disable,
 };
 
 static int adl_pci7x3x_pci_probe(struct pci_dev *dev,
-					   const struct pci_device_id *ent)
+				 const struct pci_device_id *id)
 {
-	return comedi_pci_auto_config(dev, &adl_pci7x3x_driver);
+	return comedi_pci_auto_config(dev, &adl_pci7x3x_driver,
+				      id->driver_data);
 }
 
 static DEFINE_PCI_DEVICE_TABLE(adl_pci7x3x_pci_table) = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7230) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7233) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7234) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7432) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7433) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7434) },
+	{ PCI_VDEVICE(ADLINK, 0x7230), BOARD_PCI7230 },
+	{ PCI_VDEVICE(ADLINK, 0x7233), BOARD_PCI7233 },
+	{ PCI_VDEVICE(ADLINK, 0x7234), BOARD_PCI7234 },
+	{ PCI_VDEVICE(ADLINK, 0x7432), BOARD_PCI7432 },
+	{ PCI_VDEVICE(ADLINK, 0x7433), BOARD_PCI7433 },
+	{ PCI_VDEVICE(ADLINK, 0x7434), BOARD_PCI7434 },
 	{ 0 }
 };
 MODULE_DEVICE_TABLE(pci, adl_pci7x3x_pci_table);
diff --git a/drivers/staging/comedi/drivers/adl_pci8164.c b/drivers/staging/comedi/drivers/adl_pci8164.c
index d06b83f..469a51d 100644
--- a/drivers/staging/comedi/drivers/adl_pci8164.c
+++ b/drivers/staging/comedi/drivers/adl_pci8164.c
@@ -1,217 +1,74 @@
 /*
-    comedi/drivers/adl_pci8164.c
-
-    Hardware comedi driver fot PCI-8164 Adlink card
-    Copyright (C) 2004 Michel Lachine <mike@mikelachaine.ca>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You 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.
+ * comedi/drivers/adl_pci8164.c
+ *
+ * Hardware comedi driver for PCI-8164 Adlink card
+ * Copyright (C) 2004 Michel Lachine <mike@mikelachaine.ca>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You 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: adl_pci8164
-Description: Driver for the Adlink PCI-8164 4 Axes Motion Control board
-Devices: [ADLink] PCI-8164 (adl_pci8164)
-Author: Michel Lachaine <mike@mikelachaine.ca>
-Status: experimental
-Updated: Mon, 14 Apr 2008 15:10:32 +0100
-
-Configuration Options: not applicable, uses PCI auto config
-*/
+ * Driver: adl_pci8164
+ * Description: Driver for the Adlink PCI-8164 4 Axes Motion Control board
+ * Devices: (ADLink) PCI-8164 [adl_pci8164]
+ * Author: Michel Lachaine <mike@mikelachaine.ca>
+ * Status: experimental
+ * Updated: Mon, 14 Apr 2008 15:10:32 +0100
+ *
+ * Configuration Options: not applicable, uses PCI auto config
+ */
 
 #include <linux/kernel.h>
 #include <linux/pci.h>
-#include <linux/delay.h>
 
 #include "../comedidev.h"
-#include "comedi_fc.h"
-#include "8253.h"
-
-#define PCI8164_AXIS_X  0x00
-#define PCI8164_AXIS_Y  0x08
-#define PCI8164_AXIS_Z  0x10
-#define PCI8164_AXIS_U  0x18
-
-#define PCI8164_MSTS	0x00
-#define PCI8164_SSTS    0x02
-#define PCI8164_BUF0    0x04
-#define PCI8164_BUF1    0x06
-
-#define PCI8164_CMD     0x00
-#define PCI8164_OTP     0x02
-
-#define PCI_DEVICE_ID_PCI8164 0x8164
-
-/*
- all the read commands are the same except for the addition a constant
- * const to the data for inw()
- */
-static void adl_pci8164_insn_read(struct comedi_device *dev,
-				  struct comedi_subdevice *s,
-				  struct comedi_insn *insn,
-				  unsigned int *data,
-				  char *action, unsigned short offset)
-{
-	int axis, axis_reg;
-	char axisname;
-
-	axis = CR_CHAN(insn->chanspec);
-
-	switch (axis) {
-	case 0:
-		axis_reg = PCI8164_AXIS_X;
-		axisname = 'X';
-		break;
-	case 1:
-		axis_reg = PCI8164_AXIS_Y;
-		axisname = 'Y';
-		break;
-	case 2:
-		axis_reg = PCI8164_AXIS_Z;
-		axisname = 'Z';
-		break;
-	case 3:
-		axis_reg = PCI8164_AXIS_U;
-		axisname = 'U';
-		break;
-	default:
-		axis_reg = PCI8164_AXIS_X;
-		axisname = 'X';
-	}
-
-	data[0] = inw(dev->iobase + axis_reg + offset);
-	dev_dbg(dev->class_dev,
-		"pci8164 %s read -> %04X:%04X on axis %c\n",
-		action, data[0], data[1], axisname);
-}
-
-static int adl_pci8164_insn_read_msts(struct comedi_device *dev,
-				      struct comedi_subdevice *s,
-				      struct comedi_insn *insn,
-				      unsigned int *data)
-{
-	adl_pci8164_insn_read(dev, s, insn, data, "MSTS", PCI8164_MSTS);
-	return 2;
-}
-
-static int adl_pci8164_insn_read_ssts(struct comedi_device *dev,
-				      struct comedi_subdevice *s,
-				      struct comedi_insn *insn,
-				      unsigned int *data)
-{
-	adl_pci8164_insn_read(dev, s, insn, data, "SSTS", PCI8164_SSTS);
-	return 2;
-}
-
-static int adl_pci8164_insn_read_buf0(struct comedi_device *dev,
-				      struct comedi_subdevice *s,
-				      struct comedi_insn *insn,
-				      unsigned int *data)
-{
-	adl_pci8164_insn_read(dev, s, insn, data, "BUF0", PCI8164_BUF0);
-	return 2;
-}
 
-static int adl_pci8164_insn_read_buf1(struct comedi_device *dev,
-				      struct comedi_subdevice *s,
-				      struct comedi_insn *insn,
-				      unsigned int *data)
-{
-	adl_pci8164_insn_read(dev, s, insn, data, "BUF1", PCI8164_BUF1);
-	return 2;
-}
+#define PCI8164_AXIS(x)		((x) * 0x08)
+#define PCI8164_CMD_MSTS_REG	0x00
+#define PCI8164_OTP_SSTS_REG	0x02
+#define PCI8164_BUF0_REG	0x04
+#define PCI8164_BUF1_REG	0x06
 
-/*
- all the write commands are the same except for the addition a constant
- * const to the data for outw()
- */
-static void adl_pci8164_insn_out(struct comedi_device *dev,
+static int adl_pci8164_insn_read(struct comedi_device *dev,
 				 struct comedi_subdevice *s,
 				 struct comedi_insn *insn,
-				 unsigned int *data,
-				 char *action, unsigned short offset)
+				 unsigned int *data)
 {
-	unsigned int axis, axis_reg;
-
-	char axisname;
+	unsigned long offset = (unsigned long)s->private;
+	unsigned int chan = CR_CHAN(insn->chanspec);
+	int i;
 
-	axis = CR_CHAN(insn->chanspec);
-
-	switch (axis) {
-	case 0:
-		axis_reg = PCI8164_AXIS_X;
-		axisname = 'X';
-		break;
-	case 1:
-		axis_reg = PCI8164_AXIS_Y;
-		axisname = 'Y';
-		break;
-	case 2:
-		axis_reg = PCI8164_AXIS_Z;
-		axisname = 'Z';
-		break;
-	case 3:
-		axis_reg = PCI8164_AXIS_U;
-		axisname = 'U';
-		break;
-	default:
-		axis_reg = PCI8164_AXIS_X;
-		axisname = 'X';
-	}
-
-	outw(data[0], dev->iobase + axis_reg + offset);
-
-	dev_dbg(dev->class_dev,
-		"pci8164 %s write -> %04X:%04X on axis %c\n",
-		action, data[0], data[1], axisname);
+	for (i = 0; i < insn->n; i++)
+		data[i] = inw(dev->iobase + PCI8164_AXIS(chan) + offset);
 
+	return insn->n;
 }
 
-static int adl_pci8164_insn_write_cmd(struct comedi_device *dev,
-				      struct comedi_subdevice *s,
-				      struct comedi_insn *insn,
-				      unsigned int *data)
-{
-	adl_pci8164_insn_out(dev, s, insn, data, "CMD", PCI8164_CMD);
-	return 2;
-}
-
-static int adl_pci8164_insn_write_otp(struct comedi_device *dev,
-				      struct comedi_subdevice *s,
-				      struct comedi_insn *insn,
-				      unsigned int *data)
+static int adl_pci8164_insn_write(struct comedi_device *dev,
+				  struct comedi_subdevice *s,
+				  struct comedi_insn *insn,
+				  unsigned int *data)
 {
-	adl_pci8164_insn_out(dev, s, insn, data, "OTP", PCI8164_OTP);
-	return 2;
-}
+	unsigned long offset = (unsigned long)s->private;
+	unsigned int chan = CR_CHAN(insn->chanspec);
+	int i;
 
-static int adl_pci8164_insn_write_buf0(struct comedi_device *dev,
-				       struct comedi_subdevice *s,
-				       struct comedi_insn *insn,
-				       unsigned int *data)
-{
-	adl_pci8164_insn_out(dev, s, insn, data, "BUF0", PCI8164_BUF0);
-	return 2;
-}
+	for (i = 0; i < insn->n; i++)
+		outw(data[i], dev->iobase + PCI8164_AXIS(chan) + offset);
 
-static int adl_pci8164_insn_write_buf1(struct comedi_device *dev,
-				       struct comedi_subdevice *s,
-				       struct comedi_insn *insn,
-				       unsigned int *data)
-{
-	adl_pci8164_insn_out(dev, s, insn, data, "BUF1", PCI8164_BUF1);
-	return 2;
+	return insn->n;
 }
 
 static int adl_pci8164_auto_attach(struct comedi_device *dev,
@@ -223,7 +80,7 @@ static int adl_pci8164_auto_attach(struct comedi_device *dev,
 
 	dev->board_name = dev->driver->driver_name;
 
-	ret = comedi_pci_enable(pcidev, dev->board_name);
+	ret = comedi_pci_enable(dev);
 	if (ret)
 		return ret;
 	dev->iobase = pci_resource_start(pcidev, 2);
@@ -232,77 +89,70 @@ static int adl_pci8164_auto_attach(struct comedi_device *dev,
 	if (ret)
 		return ret;
 
+	/* read MSTS register / write CMD register for each axis (channel) */
 	s = &dev->subdevices[0];
-	s->type = COMEDI_SUBD_PROC;
-	s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
-	s->n_chan = 4;
-	s->maxdata = 0xffff;
-	s->len_chanlist = 4;
-	/* s->range_table = &range_axis; */
-	s->insn_read = adl_pci8164_insn_read_msts;
-	s->insn_write = adl_pci8164_insn_write_cmd;
-
+	s->type		= COMEDI_SUBD_PROC;
+	s->subdev_flags	= SDF_READABLE | SDF_WRITABLE;
+	s->n_chan	= 4;
+	s->maxdata	= 0xffff;
+	s->len_chanlist	= 4;
+	s->insn_read	= adl_pci8164_insn_read;
+	s->insn_write	= adl_pci8164_insn_write;
+	s->private	= (void *)PCI8164_CMD_MSTS_REG;
+
+	/* read SSTS register / write OTP register for each axis (channel) */
 	s = &dev->subdevices[1];
-	s->type = COMEDI_SUBD_PROC;
-	s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
-	s->n_chan = 4;
-	s->maxdata = 0xffff;
-	s->len_chanlist = 4;
-	/* s->range_table = &range_axis; */
-	s->insn_read = adl_pci8164_insn_read_ssts;
-	s->insn_write = adl_pci8164_insn_write_otp;
-
+	s->type		= COMEDI_SUBD_PROC;
+	s->subdev_flags	= SDF_READABLE | SDF_WRITABLE;
+	s->n_chan	= 4;
+	s->maxdata	= 0xffff;
+	s->len_chanlist	= 4;
+	s->insn_read	= adl_pci8164_insn_read;
+	s->insn_write	= adl_pci8164_insn_write;
+	s->private	= (void *)PCI8164_OTP_SSTS_REG;
+
+	/* read/write BUF0 register for each axis (channel) */
 	s = &dev->subdevices[2];
-	s->type = COMEDI_SUBD_PROC;
-	s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
-	s->n_chan = 4;
-	s->maxdata = 0xffff;
-	s->len_chanlist = 4;
-	/* s->range_table = &range_axis; */
-	s->insn_read = adl_pci8164_insn_read_buf0;
-	s->insn_write = adl_pci8164_insn_write_buf0;
-
+	s->type		= COMEDI_SUBD_PROC;
+	s->subdev_flags	= SDF_READABLE | SDF_WRITABLE;
+	s->n_chan	= 4;
+	s->maxdata	= 0xffff;
+	s->len_chanlist	= 4;
+	s->insn_read	= adl_pci8164_insn_read;
+	s->insn_write	= adl_pci8164_insn_write;
+	s->private	= (void *)PCI8164_BUF0_REG;
+
+	/* read/write BUF1 register for each axis (channel) */
 	s = &dev->subdevices[3];
-	s->type = COMEDI_SUBD_PROC;
-	s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
-	s->n_chan = 4;
-	s->maxdata = 0xffff;
-	s->len_chanlist = 4;
-	/* s->range_table = &range_axis; */
-	s->insn_read = adl_pci8164_insn_read_buf1;
-	s->insn_write = adl_pci8164_insn_write_buf1;
-
-	dev_info(dev->class_dev, "%s attached\n", dev->board_name);
+	s->type		= COMEDI_SUBD_PROC;
+	s->subdev_flags	= SDF_READABLE | SDF_WRITABLE;
+	s->n_chan	= 4;
+	s->maxdata	= 0xffff;
+	s->len_chanlist	= 4;
+	s->insn_read	= adl_pci8164_insn_read;
+	s->insn_write	= adl_pci8164_insn_write;
+	s->private	= (void *)PCI8164_BUF1_REG;
 
 	return 0;
 }
 
-static void adl_pci8164_detach(struct comedi_device *dev)
-{
-	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-
-	if (pcidev) {
-		if (dev->iobase)
-			comedi_pci_disable(pcidev);
-	}
-}
-
 static struct comedi_driver adl_pci8164_driver = {
 	.driver_name	= "adl_pci8164",
 	.module		= THIS_MODULE,
 	.auto_attach	= adl_pci8164_auto_attach,
-	.detach		= adl_pci8164_detach,
+	.detach		= comedi_pci_disable,
 };
 
 static int adl_pci8164_pci_probe(struct pci_dev *dev,
-					   const struct pci_device_id *ent)
+				 const struct pci_device_id *id)
 {
-	return comedi_pci_auto_config(dev, &adl_pci8164_driver);
+	return comedi_pci_auto_config(dev, &adl_pci8164_driver,
+				      id->driver_data);
 }
 
 static DEFINE_PCI_DEVICE_TABLE(adl_pci8164_pci_table) = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI8164) },
-	{0}
+	{ PCI_DEVICE(PCI_VENDOR_ID_ADLINK, 0x8164) },
+	{ 0 }
 };
 MODULE_DEVICE_TABLE(pci, adl_pci8164_pci_table);
 
diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c
index eeb10ec..9c27e98 100644
--- a/drivers/staging/comedi/drivers/adl_pci9111.c
+++ b/drivers/staging/comedi/drivers/adl_pci9111.c
@@ -872,7 +872,7 @@ static int pci9111_auto_attach(struct comedi_device *dev,
 		return -ENOMEM;
 	dev->private = dev_private;
 
-	ret = comedi_pci_enable(pcidev, dev->board_name);
+	ret = comedi_pci_enable(dev);
 	if (ret)
 		return ret;
 	dev_private->lcr_io_base = pci_resource_start(pcidev, 1);
@@ -939,16 +939,11 @@ static int pci9111_auto_attach(struct comedi_device *dev,
 
 static void pci9111_detach(struct comedi_device *dev)
 {
-	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-
 	if (dev->iobase)
 		pci9111_reset(dev);
 	if (dev->irq != 0)
 		free_irq(dev->irq, dev);
-	if (pcidev) {
-		if (dev->iobase)
-			comedi_pci_disable(pcidev);
-	}
+	comedi_pci_disable(dev);
 }
 
 static struct comedi_driver adl_pci9111_driver = {
@@ -959,9 +954,10 @@ static struct comedi_driver adl_pci9111_driver = {
 };
 
 static int pci9111_pci_probe(struct pci_dev *dev,
-				       const struct pci_device_id *ent)
+			     const struct pci_device_id *id)
 {
-	return comedi_pci_auto_config(dev, &adl_pci9111_driver);
+	return comedi_pci_auto_config(dev, &adl_pci9111_driver,
+				      id->driver_data);
 }
 
 static DEFINE_PCI_DEVICE_TABLE(pci9111_pci_table) = {
diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c
index 4dbac74..cb4ef2d 100644
--- a/drivers/staging/comedi/drivers/adl_pci9118.c
+++ b/drivers/staging/comedi/drivers/adl_pci9118.c
@@ -1970,12 +1970,9 @@ static int pci9118_common_attach(struct comedi_device *dev, int disable_irq,
 	u16 u16w;
 
 	dev->board_name = this_board->name;
-	ret = comedi_pci_enable(pcidev, dev->board_name);
-	if (ret) {
-		dev_err(dev->class_dev,
-			"cannot enable PCI device %s\n", pci_name(pcidev));
+	ret = comedi_pci_enable(dev);
+	if (ret)
 		return ret;
-	}
 	if (master)
 		pci_set_master(pcidev);
 
@@ -2202,12 +2199,9 @@ static void pci9118_detach(struct comedi_device *dev)
 			free_pages((unsigned long)devpriv->dmabuf_virt[1],
 				   devpriv->dmabuf_pages[1]);
 	}
-	if (pcidev) {
-		if (dev->iobase)
-			comedi_pci_disable(pcidev);
-
+	comedi_pci_disable(dev);
+	if (pcidev)
 		pci_dev_put(pcidev);
-	}
 }
 
 static struct comedi_driver adl_pci9118_driver = {
@@ -2222,9 +2216,10 @@ static struct comedi_driver adl_pci9118_driver = {
 };
 
 static int adl_pci9118_pci_probe(struct pci_dev *dev,
-					   const struct pci_device_id *ent)
+				 const struct pci_device_id *id)
 {
-	return comedi_pci_auto_config(dev, &adl_pci9118_driver);
+	return comedi_pci_auto_config(dev, &adl_pci9118_driver,
+				      id->driver_data);
 }
 
 static DEFINE_PCI_DEVICE_TABLE(adl_pci9118_pci_table) = {
diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c
index 3d788c7..f847bbc 100644
--- a/drivers/staging/comedi/drivers/adv_pci1710.c
+++ b/drivers/staging/comedi/drivers/adv_pci1710.c
@@ -59,9 +59,6 @@ Configuration options:
 #define TYPE_PCI1713	2
 #define TYPE_PCI1720	3
 
-#define IORANGE_171x	32
-#define IORANGE_1720	16
-
 #define PCI171x_AD_DATA	 0	/* R:   A/D data */
 #define PCI171x_SOFTTRG	 0	/* W:   soft trigger for A/D */
 #define PCI171x_RANGE	 2	/* W:   A/D gain/range register */
@@ -178,10 +175,17 @@ static const struct comedi_lrange range_pci171x_da = { 2, {
 							   }
 };
 
+enum pci1710_boardid {
+	BOARD_PCI1710,
+	BOARD_PCI1710HG,
+	BOARD_PCI1711,
+	BOARD_PCI1713,
+	BOARD_PCI1720,
+	BOARD_PCI1731,
+};
+
 struct boardtype {
 	const char *name;	/*  board name */
-	int device_id;
-	int iorange;		/*  I/O range len */
 	char have_irq;		/*  1=card support IRQ */
 	char cardtype;		/*  0=1710& co. 2=1713, ... */
 	int n_aichan;		/*  num of A/D chans */
@@ -200,10 +204,8 @@ struct boardtype {
 };
 
 static const struct boardtype boardtypes[] = {
-	{
+	[BOARD_PCI1710] = {
 		.name		= "pci1710",
-		.device_id	= 0x1710,
-		.iorange	= IORANGE_171x,
 		.have_irq	= 1,
 		.cardtype	= TYPE_PCI171X,
 		.n_aichan	= 16,
@@ -219,10 +221,9 @@ static const struct boardtype boardtypes[] = {
 		.rangelist_ao	= &range_pci171x_da,
 		.ai_ns_min	= 10000,
 		.fifo_half_size	= 2048,
-	}, {
+	},
+	[BOARD_PCI1710HG] = {
 		.name		= "pci1710hg",
-		.device_id	= 0x1710,
-		.iorange	= IORANGE_171x,
 		.have_irq	= 1,
 		.cardtype	= TYPE_PCI171X,
 		.n_aichan	= 16,
@@ -238,10 +239,9 @@ static const struct boardtype boardtypes[] = {
 		.rangelist_ao	= &range_pci171x_da,
 		.ai_ns_min	= 10000,
 		.fifo_half_size	= 2048,
-	}, {
+	},
+	[BOARD_PCI1711] = {
 		.name		= "pci1711",
-		.device_id	= 0x1711,
-		.iorange	= IORANGE_171x,
 		.have_irq	= 1,
 		.cardtype	= TYPE_PCI171X,
 		.n_aichan	= 16,
@@ -256,10 +256,9 @@ static const struct boardtype boardtypes[] = {
 		.rangelist_ao	= &range_pci171x_da,
 		.ai_ns_min	= 10000,
 		.fifo_half_size	= 512,
-	}, {
+	},
+	[BOARD_PCI1713] = {
 		.name		= "pci1713",
-		.device_id	= 0x1713,
-		.iorange	= IORANGE_171x,
 		.have_irq	= 1,
 		.cardtype	= TYPE_PCI1713,
 		.n_aichan	= 32,
@@ -269,18 +268,16 @@ static const struct boardtype boardtypes[] = {
 		.rangecode_ai	= range_codes_pci1710_3,
 		.ai_ns_min	= 10000,
 		.fifo_half_size	= 2048,
-	}, {
+	},
+	[BOARD_PCI1720] = {
 		.name		= "pci1720",
-		.device_id	= 0x1720,
-		.iorange	= IORANGE_1720,
 		.cardtype	= TYPE_PCI1720,
 		.n_aochan	= 4,
 		.ao_maxdata	= 0x0fff,
 		.rangelist_ao	= &range_pci1720,
-	}, {
+	},
+	[BOARD_PCI1731] = {
 		.name		= "pci1731",
-		.device_id	= 0x1731,
-		.iorange	= IORANGE_171x,
 		.have_irq	= 1,
 		.cardtype	= TYPE_PCI171X,
 		.n_aichan	= 16,
@@ -307,7 +304,7 @@ struct pci1710_private {
 	unsigned int ai_et_CntrlReg;
 	unsigned int ai_et_MuxVal;
 	unsigned int ai_et_div1, ai_et_div2;
-	unsigned int act_chanlist[32];	/*  list of scaned channel */
+	unsigned int act_chanlist[32];	/*  list of scanned channel */
 	unsigned char act_chanlist_len;	/*  len of scanlist */
 	unsigned char act_chanlist_pos;	/*  actual position in MUX list */
 	unsigned char da_ranges;	/*  copy of D/A outpit range register */
@@ -334,7 +331,7 @@ static const unsigned int muxonechan[] = {
 
 /*
 ==============================================================================
- Check if channel list from user is builded correctly
+ Check if channel list from user is built correctly
  If it's ok, then program scan/gain logic.
  This works for all cards.
 */
@@ -1220,30 +1217,17 @@ static int pci1710_reset(struct comedi_device *dev)
 	}
 }
 
-static const void *pci1710_find_boardinfo(struct comedi_device *dev,
-					  struct pci_dev *pcidev)
-{
-	const struct boardtype *this_board;
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(boardtypes); i++) {
-		this_board = &boardtypes[i];
-		if (pcidev->device == this_board->device_id)
-			return this_board;
-	}
-	return NULL;
-}
-
 static int pci1710_auto_attach(struct comedi_device *dev,
-					 unsigned long context_unused)
+			       unsigned long context)
 {
 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-	const struct boardtype *this_board;
+	const struct boardtype *this_board = NULL;
 	struct pci1710_private *devpriv;
 	struct comedi_subdevice *s;
 	int ret, subdev, n_subdevices;
 
-	this_board = pci1710_find_boardinfo(dev, pcidev);
+	if (context < ARRAY_SIZE(boardtypes))
+		this_board = &boardtypes[context];
 	if (!this_board)
 		return -ENODEV;
 	dev->board_ptr = this_board;
@@ -1254,7 +1238,7 @@ static int pci1710_auto_attach(struct comedi_device *dev,
 		return -ENOMEM;
 	dev->private = devpriv;
 
-	ret = comedi_pci_enable(pcidev, dev->board_name);
+	ret = comedi_pci_enable(dev);
 	if (ret)
 		return ret;
 	dev->iobase = pci_resource_start(pcidev, 2);
@@ -1378,16 +1362,11 @@ static int pci1710_auto_attach(struct comedi_device *dev,
 
 static void pci1710_detach(struct comedi_device *dev)
 {
-	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-
 	if (dev->iobase)
 		pci1710_reset(dev);
 	if (dev->irq)
 		free_irq(dev->irq, dev);
-	if (pcidev) {
-		if (dev->iobase)
-			comedi_pci_disable(pcidev);
-	}
+	comedi_pci_disable(dev);
 }
 
 static struct comedi_driver adv_pci1710_driver = {
@@ -1398,17 +1377,68 @@ static struct comedi_driver adv_pci1710_driver = {
 };
 
 static int adv_pci1710_pci_probe(struct pci_dev *dev,
-					   const struct pci_device_id *ent)
+				 const struct pci_device_id *id)
 {
-	return comedi_pci_auto_config(dev, &adv_pci1710_driver);
+	return comedi_pci_auto_config(dev, &adv_pci1710_driver,
+				      id->driver_data);
 }
 
 static DEFINE_PCI_DEVICE_TABLE(adv_pci1710_pci_table) = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1710) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1711) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1713) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1720) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1731) },
+	{
+		PCI_DEVICE_SUB(PCI_VENDOR_ID_ADVANTECH, 0x1710,
+			       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050),
+		.driver_data = BOARD_PCI1710,
+	}, {
+		PCI_DEVICE_SUB(PCI_VENDOR_ID_ADVANTECH, 0x1710,
+			       PCI_VENDOR_ID_ADVANTECH, 0x0000),
+		.driver_data = BOARD_PCI1710,
+	}, {
+		PCI_DEVICE_SUB(PCI_VENDOR_ID_ADVANTECH, 0x1710,
+			       PCI_VENDOR_ID_ADVANTECH, 0xb100),
+		.driver_data = BOARD_PCI1710,
+	}, {
+		PCI_DEVICE_SUB(PCI_VENDOR_ID_ADVANTECH, 0x1710,
+			       PCI_VENDOR_ID_ADVANTECH, 0xb200),
+		.driver_data = BOARD_PCI1710,
+	}, {
+		PCI_DEVICE_SUB(PCI_VENDOR_ID_ADVANTECH, 0x1710,
+			       PCI_VENDOR_ID_ADVANTECH, 0xc100),
+		.driver_data = BOARD_PCI1710,
+	}, {
+		PCI_DEVICE_SUB(PCI_VENDOR_ID_ADVANTECH, 0x1710,
+			       PCI_VENDOR_ID_ADVANTECH, 0xc200),
+		.driver_data = BOARD_PCI1710,
+	}, {
+		PCI_DEVICE_SUB(PCI_VENDOR_ID_ADVANTECH, 0x1710, 0x1000, 0xd100),
+		.driver_data = BOARD_PCI1710,
+	}, {
+		PCI_DEVICE_SUB(PCI_VENDOR_ID_ADVANTECH, 0x1710,
+			       PCI_VENDOR_ID_ADVANTECH, 0x0002),
+		.driver_data = BOARD_PCI1710HG,
+	}, {
+		PCI_DEVICE_SUB(PCI_VENDOR_ID_ADVANTECH, 0x1710,
+			       PCI_VENDOR_ID_ADVANTECH, 0xb102),
+		.driver_data = BOARD_PCI1710HG,
+	}, {
+		PCI_DEVICE_SUB(PCI_VENDOR_ID_ADVANTECH, 0x1710,
+			       PCI_VENDOR_ID_ADVANTECH, 0xb202),
+		.driver_data = BOARD_PCI1710HG,
+	}, {
+		PCI_DEVICE_SUB(PCI_VENDOR_ID_ADVANTECH, 0x1710,
+			       PCI_VENDOR_ID_ADVANTECH, 0xc102),
+		.driver_data = BOARD_PCI1710HG,
+	}, {
+		PCI_DEVICE_SUB(PCI_VENDOR_ID_ADVANTECH, 0x1710,
+			       PCI_VENDOR_ID_ADVANTECH, 0xc202),
+		.driver_data = BOARD_PCI1710HG,
+	}, {
+		PCI_DEVICE_SUB(PCI_VENDOR_ID_ADVANTECH, 0x1710, 0x1000, 0xd102),
+		.driver_data = BOARD_PCI1710HG,
+	},
+	{ PCI_VDEVICE(ADVANTECH, 0x1711), BOARD_PCI1711 },
+	{ PCI_VDEVICE(ADVANTECH, 0x1713), BOARD_PCI1713 },
+	{ PCI_VDEVICE(ADVANTECH, 0x1720), BOARD_PCI1720 },
+	{ PCI_VDEVICE(ADVANTECH, 0x1731), BOARD_PCI1731 },
 	{ 0 }
 };
 MODULE_DEVICE_TABLE(pci, adv_pci1710_pci_table);
diff --git a/drivers/staging/comedi/drivers/adv_pci1723.c b/drivers/staging/comedi/drivers/adv_pci1723.c
index 02ce55a..9e81e58 100644
--- a/drivers/staging/comedi/drivers/adv_pci1723.c
+++ b/drivers/staging/comedi/drivers/adv_pci1723.c
@@ -249,7 +249,7 @@ static int pci1723_auto_attach(struct comedi_device *dev,
 		return -ENOMEM;
 	dev->private = devpriv;
 
-	ret = comedi_pci_enable(pcidev, dev->board_name);
+	ret = comedi_pci_enable(dev);
 	if (ret)
 		return ret;
 	dev->iobase = pci_resource_start(pcidev, 2);
@@ -306,14 +306,9 @@ static int pci1723_auto_attach(struct comedi_device *dev,
 
 static void pci1723_detach(struct comedi_device *dev)
 {
-	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-
-	if (pcidev) {
-		if (dev->iobase) {
-			pci1723_reset(dev);
-			comedi_pci_disable(pcidev);
-		}
-	}
+	if (dev->iobase)
+		pci1723_reset(dev);
+	comedi_pci_disable(dev);
 }
 
 static struct comedi_driver adv_pci1723_driver = {
@@ -324,9 +319,10 @@ static struct comedi_driver adv_pci1723_driver = {
 };
 
 static int adv_pci1723_pci_probe(struct pci_dev *dev,
-					   const struct pci_device_id *ent)
+				 const struct pci_device_id *id)
 {
-	return comedi_pci_auto_config(dev, &adv_pci1723_driver);
+	return comedi_pci_auto_config(dev, &adv_pci1723_driver,
+				      id->driver_data);
 }
 
 static DEFINE_PCI_DEVICE_TABLE(adv_pci1723_pci_table) = {
diff --git a/drivers/staging/comedi/drivers/adv_pci1724.c b/drivers/staging/comedi/drivers/adv_pci1724.c
new file mode 100644
index 0000000..a33929e
--- /dev/null
+++ b/drivers/staging/comedi/drivers/adv_pci1724.c
@@ -0,0 +1,411 @@
+/*
+    comedi/drivers/adv_pci1724.c
+    This is a driver for the Advantech PCI-1724U card.
+
+    Author:  Frank Mori Hess <fmh6jj@gmail.com>
+    Copyright (C) 2013 GnuBIO Inc
+
+    COMEDI - Linux Control and Measurement Device Interface
+    Copyright (C) 1997-8 David A. Schleef <ds@schleef.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.
+
+************************************************************************/
+
+/*
+
+Driver: adv_1724
+Description: Advantech PCI-1724U
+Author: Frank Mori Hess <fmh6jj@gmail.com>
+Status: works
+Updated: 2013-02-09
+Devices: [Advantech] PCI-1724U (adv_pci1724)
+
+Subdevice 0 is the analog output.
+Subdevice 1 is the offset calibration for the analog output.
+Subdevice 2 is the gain calibration for the analog output.
+
+The calibration offset and gains have quite a large effect
+on the analog output, so it is possible to adjust the analog output to
+have an output range significantly different from the board's
+nominal output ranges.  For a calibrated +/- 10V range, the analog
+output's offset will be set somewhere near mid-range (0x2000) and its
+gain will be near maximum (0x3fff).
+
+There is really no difference between the board's documented 0-20mA
+versus 4-20mA output ranges.  To pick one or the other is simply a matter
+of adjusting the offset and gain calibration until the board outputs in
+the desired range.
+
+Configuration options:
+   None
+
+Manual configuration of comedi devices is not supported by this driver;
+supported PCI devices are configured as comedi devices automatically.
+
+*/
+
+#include <linux/pci.h>
+
+#include "../comedidev.h"
+
+#define PCI_VENDOR_ID_ADVANTECH	0x13fe
+
+#define NUM_AO_CHANNELS 32
+
+/* register offsets */
+enum board_registers {
+	DAC_CONTROL_REG = 0x0,
+	SYNC_OUTPUT_REG = 0x4,
+	EEPROM_CONTROL_REG = 0x8,
+	SYNC_OUTPUT_TRIGGER_REG = 0xc,
+	BOARD_ID_REG = 0x10
+};
+
+/* bit definitions for registers */
+enum dac_control_contents {
+	DAC_DATA_MASK = 0x3fff,
+	DAC_DESTINATION_MASK = 0xc000,
+	DAC_NORMAL_MODE = 0xc000,
+	DAC_OFFSET_MODE = 0x8000,
+	DAC_GAIN_MODE = 0x4000,
+	DAC_CHANNEL_SELECT_MASK = 0xf0000,
+	DAC_GROUP_SELECT_MASK = 0xf00000
+};
+
+static uint32_t dac_data_bits(uint16_t dac_data)
+{
+	return dac_data & DAC_DATA_MASK;
+}
+
+static uint32_t dac_channel_select_bits(unsigned channel)
+{
+	return (channel << 16) & DAC_CHANNEL_SELECT_MASK;
+}
+
+static uint32_t dac_group_select_bits(unsigned group)
+{
+	return (1 << (20 + group)) & DAC_GROUP_SELECT_MASK;
+}
+
+static uint32_t dac_channel_and_group_select_bits(unsigned comedi_channel)
+{
+	return dac_channel_select_bits(comedi_channel % 8) |
+		dac_group_select_bits(comedi_channel / 8);
+}
+
+enum sync_output_contents {
+	SYNC_MODE = 0x1,
+	DAC_BUSY = 0x2, /* dac state machine is not ready */
+};
+
+enum sync_output_trigger_contents {
+	SYNC_TRIGGER_BITS = 0x0 /* any value works */
+};
+
+enum board_id_contents {
+	BOARD_ID_MASK = 0xf
+};
+
+static const struct comedi_lrange ao_ranges_1724 = { 4,
+	{
+		BIP_RANGE(10),
+		RANGE_mA(0, 20),
+		RANGE_mA(4, 20),
+		RANGE_unitless(0, 1)
+	}
+};
+
+static const struct comedi_lrange *const ao_range_list_1724[NUM_AO_CHANNELS] = {
+	[0 ... NUM_AO_CHANNELS - 1] = &ao_ranges_1724,
+};
+
+/* this structure is for data unique to this hardware driver. */
+struct adv_pci1724_private {
+	int ao_value[NUM_AO_CHANNELS];
+	int offset_value[NUM_AO_CHANNELS];
+	int gain_value[NUM_AO_CHANNELS];
+};
+
+static int wait_for_dac_idle(struct comedi_device *dev)
+{
+	static const int timeout = 10000;
+	int i;
+
+	for (i = 0; i < timeout; ++i) {
+		if ((inl(dev->iobase + SYNC_OUTPUT_REG) & DAC_BUSY) == 0)
+			break;
+		udelay(1);
+	}
+	if (i == timeout) {
+		comedi_error(dev, "Timed out waiting for dac to become idle.");
+		return -EIO;
+	}
+	return 0;
+}
+
+static int set_dac(struct comedi_device *dev, unsigned mode, unsigned channel,
+		   unsigned data)
+{
+	int retval;
+	unsigned control_bits;
+
+	retval = wait_for_dac_idle(dev);
+	if (retval < 0)
+		return retval;
+
+	control_bits = mode;
+	control_bits |= dac_channel_and_group_select_bits(channel);
+	control_bits |= dac_data_bits(data);
+	outl(control_bits, dev->iobase + DAC_CONTROL_REG);
+	return 0;
+}
+
+static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
+		    struct comedi_insn *insn, unsigned int *data)
+{
+	struct adv_pci1724_private *devpriv = dev->private;
+	int channel = CR_CHAN(insn->chanspec);
+	int retval;
+	int i;
+
+	/* turn off synchronous mode */
+	outl(0, dev->iobase + SYNC_OUTPUT_REG);
+
+	for (i = 0; i < insn->n; ++i) {
+		retval = set_dac(dev, DAC_NORMAL_MODE, channel, data[i]);
+		if (retval < 0)
+			return retval;
+		devpriv->ao_value[channel] = data[i];
+	}
+	return insn->n;
+}
+
+static int ao_readback_insn(struct comedi_device *dev,
+			    struct comedi_subdevice *s,
+			    struct comedi_insn *insn, unsigned int *data)
+{
+	struct adv_pci1724_private *devpriv = dev->private;
+	int channel = CR_CHAN(insn->chanspec);
+	int i;
+
+	if (devpriv->ao_value[channel] < 0) {
+		comedi_error(dev,
+			     "Cannot read back channels which have not yet been written to.");
+		return -EIO;
+	}
+	for (i = 0; i < insn->n; i++)
+		data[i] = devpriv->ao_value[channel];
+
+	return insn->n;
+}
+
+static int offset_write_insn(struct comedi_device *dev,
+			     struct comedi_subdevice *s,
+			     struct comedi_insn *insn, unsigned int *data)
+{
+	struct adv_pci1724_private *devpriv = dev->private;
+	int channel = CR_CHAN(insn->chanspec);
+	int retval;
+	int i;
+
+	/* turn off synchronous mode */
+	outl(0, dev->iobase + SYNC_OUTPUT_REG);
+
+	for (i = 0; i < insn->n; ++i) {
+		retval = set_dac(dev, DAC_OFFSET_MODE, channel, data[i]);
+		if (retval < 0)
+			return retval;
+		devpriv->offset_value[channel] = data[i];
+	}
+
+	return insn->n;
+}
+
+static int offset_read_insn(struct comedi_device *dev,
+			    struct comedi_subdevice *s,
+			    struct comedi_insn *insn, unsigned int *data)
+{
+	struct adv_pci1724_private *devpriv = dev->private;
+	unsigned int channel = CR_CHAN(insn->chanspec);
+	int i;
+
+	if (devpriv->offset_value[channel] < 0) {
+		comedi_error(dev,
+			     "Cannot read back channels which have not yet been written to.");
+		return -EIO;
+	}
+	for (i = 0; i < insn->n; i++)
+		data[i] = devpriv->offset_value[channel];
+
+	return insn->n;
+}
+
+static int gain_write_insn(struct comedi_device *dev,
+			   struct comedi_subdevice *s,
+			   struct comedi_insn *insn, unsigned int *data)
+{
+	struct adv_pci1724_private *devpriv = dev->private;
+	int channel = CR_CHAN(insn->chanspec);
+	int retval;
+	int i;
+
+	/* turn off synchronous mode */
+	outl(0, dev->iobase + SYNC_OUTPUT_REG);
+
+	for (i = 0; i < insn->n; ++i) {
+		retval = set_dac(dev, DAC_GAIN_MODE, channel, data[i]);
+		if (retval < 0)
+			return retval;
+		devpriv->gain_value[channel] = data[i];
+	}
+
+	return insn->n;
+}
+
+static int gain_read_insn(struct comedi_device *dev,
+			  struct comedi_subdevice *s, struct comedi_insn *insn,
+			  unsigned int *data)
+{
+	struct adv_pci1724_private *devpriv = dev->private;
+	unsigned int channel = CR_CHAN(insn->chanspec);
+	int i;
+
+	if (devpriv->gain_value[channel] < 0) {
+		comedi_error(dev,
+			     "Cannot read back channels which have not yet been written to.");
+		return -EIO;
+	}
+	for (i = 0; i < insn->n; i++)
+		data[i] = devpriv->gain_value[channel];
+
+	return insn->n;
+}
+
+/* Allocate and initialize the subdevice structures.
+ */
+static int setup_subdevices(struct comedi_device *dev)
+{
+	struct comedi_subdevice *s;
+	int ret;
+
+	ret = comedi_alloc_subdevices(dev, 3);
+	if (ret)
+		return ret;
+
+	/* analog output subdevice */
+	s = &dev->subdevices[0];
+	s->type = COMEDI_SUBD_AO;
+	s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_GROUND;
+	s->n_chan = NUM_AO_CHANNELS;
+	s->maxdata = 0x3fff;
+	s->range_table_list = ao_range_list_1724;
+	s->insn_read = ao_readback_insn;
+	s->insn_write = ao_winsn;
+
+	/* offset calibration */
+	s = &dev->subdevices[1];
+	s->type = COMEDI_SUBD_CALIB;
+	s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
+	s->n_chan = NUM_AO_CHANNELS;
+	s->insn_read = offset_read_insn;
+	s->insn_write = offset_write_insn;
+	s->maxdata = 0x3fff;
+
+	/* gain calibration */
+	s = &dev->subdevices[2];
+	s->type = COMEDI_SUBD_CALIB;
+	s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
+	s->n_chan = NUM_AO_CHANNELS;
+	s->insn_read = gain_read_insn;
+	s->insn_write = gain_write_insn;
+	s->maxdata = 0x3fff;
+
+	return 0;
+}
+
+static int adv_pci1724_auto_attach(struct comedi_device *dev,
+				   unsigned long context_unused)
+{
+	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+	struct adv_pci1724_private *devpriv;
+	int i;
+	int retval;
+	unsigned int board_id;
+
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
+
+	/* init software copies of output values to indicate we don't know
+	 * what the output value is since it has never been written. */
+	for (i = 0; i < NUM_AO_CHANNELS; ++i) {
+		devpriv->ao_value[i] = -1;
+		devpriv->offset_value[i] = -1;
+		devpriv->gain_value[i] = -1;
+	}
+
+	dev->board_name = dev->driver->driver_name;
+
+	retval = comedi_pci_enable(dev);
+	if (retval)
+		return retval;
+
+	dev->iobase = pci_resource_start(pcidev, 2);
+	board_id = inl(dev->iobase + BOARD_ID_REG) & BOARD_ID_MASK;
+	dev_info(dev->class_dev, "board id: %d\n", board_id);
+
+	retval = setup_subdevices(dev);
+	if (retval < 0)
+		return retval;
+
+	dev_info(dev->class_dev, "%s (pci %s) attached, board id: %u\n",
+		 dev->board_name, pci_name(pcidev), board_id);
+	return 0;
+}
+
+static struct comedi_driver adv_pci1724_driver = {
+	.driver_name = "adv_pci1724",
+	.module = THIS_MODULE,
+	.auto_attach = adv_pci1724_auto_attach,
+	.detach = comedi_pci_disable,
+};
+
+static int adv_pci1724_pci_probe(struct pci_dev *dev,
+				 const struct pci_device_id *id)
+{
+	return comedi_pci_auto_config(dev, &adv_pci1724_driver,
+				      id->driver_data);
+}
+
+static DEFINE_PCI_DEVICE_TABLE(adv_pci1724_pci_table) = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1724) },
+	{ 0 }
+};
+MODULE_DEVICE_TABLE(pci, adv_pci1724_pci_table);
+
+static struct pci_driver adv_pci1724_pci_driver = {
+	.name = "adv_pci1724",
+	.id_table = adv_pci1724_pci_table,
+	.probe = adv_pci1724_pci_probe,
+	.remove = comedi_pci_auto_unconfig,
+};
+
+module_comedi_pci_driver(adv_pci1724_driver, adv_pci1724_pci_driver);
+
+MODULE_AUTHOR("Frank Mori Hess <fmh6jj@gmail.com>");
+MODULE_DESCRIPTION("Advantech PCI-1724U Comedi driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/adv_pci_dio.c b/drivers/staging/comedi/drivers/adv_pci_dio.c
index 338c43e..e98ddcc 100644
--- a/drivers/staging/comedi/drivers/adv_pci_dio.c
+++ b/drivers/staging/comedi/drivers/adv_pci_dio.c
@@ -236,8 +236,6 @@ struct diosubd_data {
 
 struct dio_boardtype {
 	const char *name;	/*  board name */
-	int vendor_id;		/*  vendor/device PCI ID */
-	int device_id;
 	int main_pci_region;	/*  main I/O PCI region */
 	enum hw_cards_id cardtype;
 	int nsubdevs;
@@ -250,10 +248,8 @@ struct dio_boardtype {
 };
 
 static const struct dio_boardtype boardtypes[] = {
-	{
+	[TYPE_PCI1730] = {
 		.name		= "pci1730",
-		.vendor_id	= PCI_VENDOR_ID_ADVANTECH,
-		.device_id	= 0x1730,
 		.main_pci_region = PCIDIO_MAINREG,
 		.cardtype	= TYPE_PCI1730,
 		.nsubdevs	= 5,
@@ -263,30 +259,27 @@ static const struct dio_boardtype boardtypes[] = {
 		.sdo[1]		= { 16, PCI1730_IDO, 2, 0, },
 		.boardid	= { 4, PCI173x_BOARDID, 1, SDF_INTERNAL, },
 		.io_access	= IO_8b,
-	}, {
+	},
+	[TYPE_PCI1733] = {
 		.name		= "pci1733",
-		.vendor_id	= PCI_VENDOR_ID_ADVANTECH,
-		.device_id	= 0x1733,
 		.main_pci_region = PCIDIO_MAINREG,
 		.cardtype	= TYPE_PCI1733,
 		.nsubdevs	= 2,
 		.sdi[1]		= { 32, PCI1733_IDI, 4, 0, },
 		.boardid	= { 4, PCI173x_BOARDID, 1, SDF_INTERNAL, },
 		.io_access	= IO_8b,
-	}, {
+	},
+	[TYPE_PCI1734] = {
 		.name		= "pci1734",
-		.vendor_id	= PCI_VENDOR_ID_ADVANTECH,
-		.device_id	= 0x1734,
 		.main_pci_region = PCIDIO_MAINREG,
 		.cardtype	= TYPE_PCI1734,
 		.nsubdevs	= 2,
 		.sdo[1]		= { 32, PCI1734_IDO, 4, 0, },
 		.boardid	= { 4, PCI173x_BOARDID, 1, SDF_INTERNAL, },
 		.io_access	= IO_8b,
-	}, {
+	},
+	[TYPE_PCI1735] = {
 		.name		= "pci1735",
-		.vendor_id	= PCI_VENDOR_ID_ADVANTECH,
-		.device_id	= 0x1735,
 		.main_pci_region = PCIDIO_MAINREG,
 		.cardtype	= TYPE_PCI1735,
 		.nsubdevs	= 4,
@@ -295,10 +288,9 @@ static const struct dio_boardtype boardtypes[] = {
 		.boardid	= { 4, PCI1735_BOARDID, 1, SDF_INTERNAL, },
 		.s8254[0]	= { 3, PCI1735_C8254, 1, 0, },
 		.io_access	= IO_8b,
-	}, {
+	},
+	[TYPE_PCI1736] = {
 		.name		= "pci1736",
-		.vendor_id	= PCI_VENDOR_ID_ADVANTECH,
-		.device_id	= 0x1736,
 		.main_pci_region = PCI1736_MAINREG,
 		.cardtype	= TYPE_PCI1736,
 		.nsubdevs	= 3,
@@ -306,39 +298,35 @@ static const struct dio_boardtype boardtypes[] = {
 		.sdo[1]		= { 16, PCI1736_IDO, 2, 0, },
 		.boardid	= { 4, PCI1736_BOARDID, 1, SDF_INTERNAL, },
 		.io_access	= IO_8b,
-	}, {
+	},
+	[TYPE_PCI1739] = {
 		.name		= "pci1739",
-		.vendor_id	= PCI_VENDOR_ID_ADVANTECH,
-		.device_id	= 0x1739,
 		.main_pci_region = PCIDIO_MAINREG,
 		.cardtype	= TYPE_PCI1739,
 		.nsubdevs	= 2,
 		.sdio[0]	= { 48, PCI1739_DIO, 2, 0, },
 		.io_access	= IO_8b,
-	}, {
+	},
+	[TYPE_PCI1750] = {
 		.name		= "pci1750",
-		.vendor_id	= PCI_VENDOR_ID_ADVANTECH,
-		.device_id	= 0x1750,
 		.main_pci_region = PCIDIO_MAINREG,
 		.cardtype	= TYPE_PCI1750,
 		.nsubdevs	= 2,
 		.sdi[1]		= { 16, PCI1750_IDI, 2, 0, },
 		.sdo[1]		= { 16, PCI1750_IDO, 2, 0, },
 		.io_access	= IO_8b,
-	}, {
+	},
+	[TYPE_PCI1751] = {
 		.name		= "pci1751",
-		.vendor_id	= PCI_VENDOR_ID_ADVANTECH,
-		.device_id	= 0x1751,
 		.main_pci_region = PCIDIO_MAINREG,
 		.cardtype	= TYPE_PCI1751,
 		.nsubdevs	= 3,
 		.sdio[0]	= { 48, PCI1751_DIO, 2, 0, },
 		.s8254[0]	= { 3, PCI1751_CNT, 1, 0, },
 		.io_access	= IO_8b,
-	}, {
+	},
+	[TYPE_PCI1752] = {
 		.name		= "pci1752",
-		.vendor_id	= PCI_VENDOR_ID_ADVANTECH,
-		.device_id	= 0x1752,
 		.main_pci_region = PCIDIO_MAINREG,
 		.cardtype	= TYPE_PCI1752,
 		.nsubdevs	= 3,
@@ -346,29 +334,26 @@ static const struct dio_boardtype boardtypes[] = {
 		.sdo[1]		= { 32, PCI1752_IDO2, 2, 0, },
 		.boardid	= { 4, PCI175x_BOARDID, 1, SDF_INTERNAL, },
 		.io_access	= IO_16b,
-	}, {
+	},
+	[TYPE_PCI1753] = {
 		.name		= "pci1753",
-		.vendor_id	= PCI_VENDOR_ID_ADVANTECH,
-		.device_id	= 0x1753,
 		.main_pci_region = PCIDIO_MAINREG,
 		.cardtype	= TYPE_PCI1753,
 		.nsubdevs	= 4,
 		.sdio[0]	= { 96, PCI1753_DIO, 4, 0, },
 		.io_access	= IO_8b,
-	}, {
+	},
+	[TYPE_PCI1753E] = {
 		.name		= "pci1753e",
-		.vendor_id	= PCI_VENDOR_ID_ADVANTECH,
-		.device_id	= 0x1753,
 		.main_pci_region = PCIDIO_MAINREG,
 		.cardtype	= TYPE_PCI1753E,
 		.nsubdevs	= 8,
 		.sdio[0]	= { 96, PCI1753_DIO, 4, 0, },
 		.sdio[1]	= { 96, PCI1753E_DIO, 4, 0, },
 		.io_access	= IO_8b,
-	}, {
+	},
+	[TYPE_PCI1754] = {
 		.name		= "pci1754",
-		.vendor_id	= PCI_VENDOR_ID_ADVANTECH,
-		.device_id	= 0x1754,
 		.main_pci_region = PCIDIO_MAINREG,
 		.cardtype	= TYPE_PCI1754,
 		.nsubdevs	= 3,
@@ -376,10 +361,9 @@ static const struct dio_boardtype boardtypes[] = {
 		.sdi[1]		= { 32, PCI1754_IDI2, 2, 0, },
 		.boardid	= { 4, PCI175x_BOARDID, 1, SDF_INTERNAL, },
 		.io_access	= IO_16b,
-	}, {
+	},
+	[TYPE_PCI1756] = {
 		.name		= "pci1756",
-		.vendor_id	= PCI_VENDOR_ID_ADVANTECH,
-		.device_id	= 0x1756,
 		.main_pci_region = PCIDIO_MAINREG,
 		.cardtype	= TYPE_PCI1756,
 		.nsubdevs	= 3,
@@ -387,19 +371,17 @@ static const struct dio_boardtype boardtypes[] = {
 		.sdo[1]		= { 32, PCI1756_IDO, 2, 0, },
 		.boardid	= { 4, PCI175x_BOARDID, 1, SDF_INTERNAL, },
 		.io_access	= IO_16b,
-	}, {
+	},
+	[TYPE_PCI1760] = {
 		/* This card has its own 'attach' */
 		.name		= "pci1760",
-		.vendor_id	= PCI_VENDOR_ID_ADVANTECH,
-		.device_id	= 0x1760,
 		.main_pci_region = 0,
 		.cardtype	= TYPE_PCI1760,
 		.nsubdevs	= 4,
 		.io_access	= IO_8b,
-	}, {
+	},
+	[TYPE_PCI1762] = {
 		.name		= "pci1762",
-		.vendor_id	= PCI_VENDOR_ID_ADVANTECH,
-		.device_id	= 0x1762,
 		.main_pci_region = PCIDIO_MAINREG,
 		.cardtype	= TYPE_PCI1762,
 		.nsubdevs	= 3,
@@ -1076,31 +1058,50 @@ static int pci_dio_add_8254(struct comedi_device *dev,
 	return 0;
 }
 
-static const void *pci_dio_find_boardinfo(struct comedi_device *dev,
-					  struct pci_dev *pcidev)
+static unsigned long pci_dio_override_cardtype(struct pci_dev *pcidev,
+					       unsigned long cardtype)
 {
-	const struct dio_boardtype *this_board;
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(boardtypes); ++i) {
-		this_board = &boardtypes[i];
-		if (this_board->vendor_id == pcidev->vendor &&
-		    this_board->device_id == pcidev->device)
-			return this_board;
+	/*
+	 * Change cardtype from TYPE_PCI1753 to TYPE_PCI1753E if expansion
+	 * board available.  Need to enable PCI device and request the main
+	 * registers PCI BAR temporarily to perform the test.
+	 */
+	if (cardtype != TYPE_PCI1753)
+		return cardtype;
+	if (pci_enable_device(pcidev) < 0)
+		return cardtype;
+	if (pci_request_region(pcidev, PCIDIO_MAINREG, "adv_pci_dio") == 0) {
+		/*
+		 * This test is based on Advantech's "advdaq" driver source
+		 * (which declares its module licence as "GPL" although the
+		 * driver source does not include a "COPYING" file).
+		 */
+		unsigned long reg =
+			pci_resource_start(pcidev, PCIDIO_MAINREG) + 53;
+
+		outb(0x05, reg);
+		if ((inb(reg) & 0x07) == 0x02) {
+			outb(0x02, reg);
+			if ((inb(reg) & 0x07) == 0x05)
+				cardtype = TYPE_PCI1753E;
+		}
+		pci_release_region(pcidev, PCIDIO_MAINREG);
 	}
-	return NULL;
+	pci_disable_device(pcidev);
+	return cardtype;
 }
 
 static int pci_dio_auto_attach(struct comedi_device *dev,
-					 unsigned long context_unused)
+			       unsigned long context)
 {
 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-	const struct dio_boardtype *this_board;
+	const struct dio_boardtype *this_board = NULL;
 	struct pci_dio_private *devpriv;
 	struct comedi_subdevice *s;
 	int ret, subdev, i, j;
 
-	this_board = pci_dio_find_boardinfo(dev, pcidev);
+	if (context < ARRAY_SIZE(boardtypes))
+		this_board = &boardtypes[context];
 	if (!this_board)
 		return -ENODEV;
 	dev->board_ptr = this_board;
@@ -1111,7 +1112,7 @@ static int pci_dio_auto_attach(struct comedi_device *dev,
 		return -ENOMEM;
 	dev->private = devpriv;
 
-	ret = comedi_pci_enable(pcidev, dev->board_name);
+	ret = comedi_pci_enable(dev);
 	if (ret)
 		return ret;
 	dev->iobase = pci_resource_start(pcidev, this_board->main_pci_region);
@@ -1172,7 +1173,6 @@ static int pci_dio_auto_attach(struct comedi_device *dev,
 static void pci_dio_detach(struct comedi_device *dev)
 {
 	struct pci_dio_private *devpriv = dev->private;
-	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
 	struct comedi_subdevice *s;
 	int i;
 
@@ -1188,10 +1188,7 @@ static void pci_dio_detach(struct comedi_device *dev)
 			s->private = NULL;
 		}
 	}
-	if (pcidev) {
-		if (dev->iobase)
-			comedi_pci_disable(pcidev);
-	}
+	comedi_pci_disable(dev);
 }
 
 static struct comedi_driver adv_pci_dio_driver = {
@@ -1202,26 +1199,29 @@ static struct comedi_driver adv_pci_dio_driver = {
 };
 
 static int adv_pci_dio_pci_probe(struct pci_dev *dev,
-					   const struct pci_device_id *ent)
+				 const struct pci_device_id *id)
 {
-	return comedi_pci_auto_config(dev, &adv_pci_dio_driver);
+	unsigned long cardtype;
+
+	cardtype = pci_dio_override_cardtype(dev, id->driver_data);
+	return comedi_pci_auto_config(dev, &adv_pci_dio_driver, cardtype);
 }
 
 static DEFINE_PCI_DEVICE_TABLE(adv_pci_dio_pci_table) = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1730) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1733) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1734) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1735) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1736) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1739) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1750) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1751) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1752) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1753) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1754) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1756) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1760) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1762) },
+	{ PCI_VDEVICE(ADVANTECH, 0x1730), TYPE_PCI1730 },
+	{ PCI_VDEVICE(ADVANTECH, 0x1733), TYPE_PCI1733 },
+	{ PCI_VDEVICE(ADVANTECH, 0x1734), TYPE_PCI1734 },
+	{ PCI_VDEVICE(ADVANTECH, 0x1735), TYPE_PCI1735 },
+	{ PCI_VDEVICE(ADVANTECH, 0x1736), TYPE_PCI1736 },
+	{ PCI_VDEVICE(ADVANTECH, 0x1739), TYPE_PCI1739 },
+	{ PCI_VDEVICE(ADVANTECH, 0x1750), TYPE_PCI1750 },
+	{ PCI_VDEVICE(ADVANTECH, 0x1751), TYPE_PCI1751 },
+	{ PCI_VDEVICE(ADVANTECH, 0x1752), TYPE_PCI1752 },
+	{ PCI_VDEVICE(ADVANTECH, 0x1753), TYPE_PCI1753 },
+	{ PCI_VDEVICE(ADVANTECH, 0x1754), TYPE_PCI1754 },
+	{ PCI_VDEVICE(ADVANTECH, 0x1756), TYPE_PCI1756 },
+	{ PCI_VDEVICE(ADVANTECH, 0x1760), TYPE_PCI1760 },
+	{ PCI_VDEVICE(ADVANTECH, 0x1762), TYPE_PCI1762 },
 	{ 0 }
 };
 MODULE_DEVICE_TABLE(pci, adv_pci_dio_pci_table);
diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c
index 7c53dea..1a562e8 100644
--- a/drivers/staging/comedi/drivers/amplc_dio200.c
+++ b/drivers/staging/comedi/drivers/amplc_dio200.c
@@ -1,10 +1,9 @@
 /*
     comedi/drivers/amplc_dio200.c
-    Driver for Amplicon PC272E and PCI272 DIO boards.
-    (Support for other boards in Amplicon 200 series may be added at
-    a later date, e.g. PCI215.)
 
-    Copyright (C) 2005 MEV Ltd. <http://www.mev.co.uk/>
+    Driver for Amplicon PC212E, PC214E, PC215E, PC218E, PC272E.
+
+    Copyright (C) 2005-2013 MEV Ltd. <http://www.mev.co.uk/>
 
     COMEDI - Linux Control and Measurement Device Interface
     Copyright (C) 1998,2000 David A. Schleef <ds@schleef.org>
@@ -26,26 +25,23 @@
 */
 /*
  * Driver: amplc_dio200
- * Description: Amplicon 200 Series Digital I/O
+ * Description: Amplicon 200 Series ISA Digital I/O
  * Author: Ian Abbott <abbotti@mev.co.uk>
  * Devices: [Amplicon] PC212E (pc212e), PC214E (pc214e), PC215E (pc215e),
- *   PCI215 (pci215), PCIe215 (pcie215), PC218E (pc218e), PCIe236 (pcie236),
- *   PC272E (pc272e), PCI272 (pci272), PCIe296 (pcie296)
- * Updated: Wed, 24 Oct 2012 16:22:34 +0100
+ *   PC218E (pc218e), PC272E (pc272e)
+ * Updated: Mon, 18 Mar 2013 14:40:41 +0000
+ *
  * Status: works
  *
- * Configuration options - PC212E, PC214E, PC215E, PC218E, PC272E:
+ * Configuration options:
  *   [0] - I/O port base address
  *   [1] - IRQ (optional, but commands won't work without it)
  *
- * Manual configuration of PCI(e) cards is not supported; they are configured
- * automatically.
- *
  * Passing a zero for an option is the same as leaving it unspecified.
  *
  * SUBDEVICES
  *
- *                     PC212E         PC214E      PC215E/PCI215
+ *                     PC212E         PC214E         PC215E
  *                  -------------  -------------  -------------
  *   Subdevices           6              4              5
  *    0                 PPI-X          PPI-X          PPI-X
@@ -55,29 +51,16 @@
  *    4                 CTR-Z2                      INTERRUPT
  *    5               INTERRUPT
  *
- *                     PCIe215        PC218E         PCIe236
- *                  -------------  -------------  -------------
- *   Subdevices           8              7              8
- *    0                 PPI-X          CTR-X1         PPI-X
- *    1                 UNUSED         CTR-X2         UNUSED
- *    2                 PPI-Y          CTR-Y1         UNUSED
- *    3                 UNUSED         CTR-Y2         UNUSED
- *    4                 CTR-Z1         CTR-Z1         CTR-Z1
- *    5                 CTR-Z2         CTR-Z2         CTR-Z2
- *    6                 TIMER        INTERRUPT        TIMER
- *    7               INTERRUPT                     INTERRUPT
- *
- *                  PC272E/PCI272     PCIe296
+ *                     PC218E         PC272E
  *                  -------------  -------------
- *   Subdevices           4              8
- *    0                 PPI-X          PPI-X1
- *    1                 PPI-Y          PPI-X2
- *    2                 PPI-Z          PPI-Y1
- *    3               INTERRUPT        PPI-Y2
- *    4                                CTR-Z1
- *    5                                CTR-Z2
- *    6                                TIMER
- *    7                              INTERRUPT
+ *   Subdevices           7              4
+ *    0                 CTR-X1         PPI-X
+ *    1                 CTR-X2         PPI-Y
+ *    2                 CTR-Y1         PPI-Z
+ *    3                 CTR-Y2       INTERRUPT
+ *    4                 CTR-Z1
+ *    5                 CTR-Z2
+ *    6               INTERRUPT
  *
  * Each PPI is a 8255 chip providing 24 DIO channels.  The DIO channels
  * are configurable as inputs or outputs in four groups:
@@ -120,14 +103,6 @@
  *         the SK1 connector.  This pin is shared by all three counter
  *         channels on the chip.
  *
- *     For the PCIe boards, clock sources in the range 0 to 31 are allowed
- *     and the following additional clock sources are defined:
- *
- *       8.  HIGH logic level.
- *       9.  LOW logic level.
- *      10.  "Pattern present" signal.
- *      11.  Internal 20 MHz clock.
- *
  *   INSN_CONFIG_GET_CLOCK_SRC.  Returns the counter channel's current
  *     clock source in data[1].  For internal clock sources, data[2] is set
  *     to the period in ns.
@@ -149,27 +124,6 @@
  *       6.  Reserved.
  *       7.  Reserved.
  *
- *     For the PCIe boards, gate sources in the range 0 to 31 are allowed;
- *     the following additional clock sources and clock sources 6 and 7 are
- *     (re)defined:
- *
- *       6.  /GAT n, negated version of the counter channel's dedicated
- *         GAT input (negated version of gate source 2).
- *       7.  OUT n-2, the non-inverted output of counter channel n-2
- *         (negated version of gate source 3).
- *       8.  "Pattern present" signal, HIGH while pattern present.
- *       9.  "Pattern occurred" latched signal, latches HIGH when pattern
- *         occurs.
- *      10.  "Pattern gone away" latched signal, latches LOW when pattern
- *         goes away after it occurred.
- *      11.  Negated "pattern present" signal, LOW while pattern present
- *         (negated version of gate source 8).
- *      12.  Negated "pattern occurred" latched signal, latches LOW when
- *         pattern occurs (negated version of gate source 9).
- *      13.  Negated "pattern gone away" latched signal, latches LOW when
- *         pattern goes away after it occurred (negated version of gate
- *         source 10).
- *
  *   INSN_CONFIG_GET_GATE_SRC.  Returns the counter channel's current gate
  *     source in data[2].
  *
@@ -186,8 +140,6 @@
  *   3.  The counter subdevices are connected in a ring, so the highest
  *   counter subdevice precedes the lowest.
  *
- * The 'TIMER' subdevice is a free-running 32-bit timer subdevice.
- *
  * The 'INTERRUPT' subdevice pretends to be a digital input subdevice.  The
  * digital inputs come from the interrupt status register.  The number of
  * channels matches the number of interrupt sources.  The PC214E does not
@@ -196,7 +148,7 @@
  *
  * INTERRUPT SOURCES
  *
- *                     PC212E         PC214E      PC215E/PCI215
+ *                     PC212E         PC214E         PC215E
  *                  -------------  -------------  -------------
  *   Sources              6              1              6
  *    0               PPI-X-C0       JUMPER-J5      PPI-X-C0
@@ -206,25 +158,15 @@
  *    4              CTR-Z1-OUT1                   CTR-Z1-OUT1
  *    5              CTR-Z2-OUT1                   CTR-Z2-OUT1
  *
- *                     PCIe215        PC218E         PCIe236
- *                  -------------  -------------  -------------
- *   Sources              6              6              6
- *    0               PPI-X-C0      CTR-X1-OUT1     PPI-X-C0
- *    1               PPI-X-C3      CTR-X2-OUT1     PPI-X-C3
- *    2               PPI-Y-C0      CTR-Y1-OUT1      unused
- *    3               PPI-Y-C3      CTR-Y2-OUT1      unused
- *    4              CTR-Z1-OUT1    CTR-Z1-OUT1    CTR-Z1-OUT1
- *    5              CTR-Z2-OUT1    CTR-Z2-OUT1    CTR-Z2-OUT1
- *
- *                  PC272E/PCI272     PCIe296
+ *                     PC218E         PC272E
  *                  -------------  -------------
  *   Sources              6              6
- *    0               PPI-X-C0       PPI-X1-C0
- *    1               PPI-X-C3       PPI-X1-C3
- *    2               PPI-Y-C0       PPI-Y1-C0
- *    3               PPI-Y-C3       PPI-Y1-C3
- *    4               PPI-Z-C0      CTR-Z1-OUT1
- *    5               PPI-Z-C3      CTR-Z2-OUT1
+ *    0              CTR-X1-OUT1     PPI-X-C0
+ *    1              CTR-X2-OUT1     PPI-X-C3
+ *    2              CTR-Y1-OUT1     PPI-Y-C0
+ *    3              CTR-Y2-OUT1     PPI-Y-C3
+ *    4              CTR-Z1-OUT1     PPI-Z-C0
+ *    5              CTR-Z2-OUT1     PPI-Z-C3
  *
  * When an interrupt source is enabled in the interrupt source enable
  * register, a rising edge on the source signal latches the corresponding
@@ -232,14 +174,11 @@
  *
  * When the interrupt status register value as a whole (actually, just the
  * 6 least significant bits) goes from zero to non-zero, the board will
- * generate an interrupt.  For level-triggered hardware interrupts (PCI
- * card), the interrupt will remain asserted until the interrupt status
- * register is cleared to zero.  For edge-triggered hardware interrupts
- * (ISA card), no further interrupts will occur until the interrupt status
- * register is cleared to zero.  To clear a bit to zero in the interrupt
- * status register, the corresponding interrupt source must be disabled
- * in the interrupt source enable register (there is no separate interrupt
- * clear register).
+ * generate an interrupt.  No further interrupts will occur until the
+ * interrupt status register is cleared to zero.  To clear a bit to zero in
+ * the interrupt status register, the corresponding interrupt source must
+ * be disabled in the interrupt source enable register (there is no
+ * separate interrupt clear register).
  *
  * The PC214E does not have an interrupt source enable register or an
  * interrupt status register; its 'INTERRUPT' subdevice has a single
@@ -258,492 +197,77 @@
  * order they appear in the channel list.
  */
 
-#include <linux/pci.h>
-#include <linux/interrupt.h>
 #include <linux/slab.h>
 
 #include "../comedidev.h"
 
-#include "comedi_fc.h"
-#include "8253.h"
-
-#define DIO200_DRIVER_NAME	"amplc_dio200"
-
-#define DO_ISA	IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_ISA)
-#define DO_PCI	IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_PCI)
-
-/* PCI IDs */
-#define PCI_DEVICE_ID_AMPLICON_PCI272 0x000a
-#define PCI_DEVICE_ID_AMPLICON_PCI215 0x000b
-#define PCI_DEVICE_ID_AMPLICON_PCIE236 0x0011
-#define PCI_DEVICE_ID_AMPLICON_PCIE215 0x0012
-#define PCI_DEVICE_ID_AMPLICON_PCIE296 0x0014
-
-/* 8255 control register bits */
-#define CR_C_LO_IO	0x01
-#define CR_B_IO		0x02
-#define CR_B_MODE	0x04
-#define CR_C_HI_IO	0x08
-#define CR_A_IO		0x10
-#define CR_A_MODE(a)	((a)<<5)
-#define CR_CW		0x80
-
-/* 200 series registers */
-#define DIO200_IO_SIZE		0x20
-#define DIO200_PCIE_IO_SIZE	0x4000
-#define DIO200_XCLK_SCE		0x18	/* Group X clock selection register */
-#define DIO200_YCLK_SCE		0x19	/* Group Y clock selection register */
-#define DIO200_ZCLK_SCE		0x1a	/* Group Z clock selection register */
-#define DIO200_XGAT_SCE		0x1b	/* Group X gate selection register */
-#define DIO200_YGAT_SCE		0x1c	/* Group Y gate selection register */
-#define DIO200_ZGAT_SCE		0x1d	/* Group Z gate selection register */
-#define DIO200_INT_SCE		0x1e	/* Interrupt enable/status register */
-/* Extra registers for new PCIe boards */
-#define DIO200_ENHANCE		0x20	/* 1 to enable enhanced features */
-#define DIO200_VERSION		0x24	/* Hardware version register */
-#define DIO200_TS_CONFIG	0x600	/* Timestamp timer config register */
-#define DIO200_TS_COUNT		0x602	/* Timestamp timer count register */
-
-/*
- * Functions for constructing value for DIO_200_?CLK_SCE and
- * DIO_200_?GAT_SCE registers:
- *
- * 'which' is: 0 for CTR-X1, CTR-Y1, CTR-Z1; 1 for CTR-X2, CTR-Y2 or CTR-Z2.
- * 'chan' is the channel: 0, 1 or 2.
- * 'source' is the signal source: 0 to 7, or 0 to 31 for "enhanced" boards.
- */
-static unsigned char clk_gat_sce(unsigned int which, unsigned int chan,
-				 unsigned int source)
-{
-	return (which << 5) | (chan << 3) |
-	       ((source & 030) << 3) | (source & 007);
-}
-
-static unsigned char clk_sce(unsigned int which, unsigned int chan,
-			     unsigned int source)
-{
-	return clk_gat_sce(which, chan, source);
-}
-
-static unsigned char gat_sce(unsigned int which, unsigned int chan,
-			     unsigned int source)
-{
-	return clk_gat_sce(which, chan, source);
-}
-
-/*
- * Periods of the internal clock sources in nanoseconds.
- */
-static const unsigned int clock_period[32] = {
-	[1] = 100,		/* 10 MHz */
-	[2] = 1000,		/* 1 MHz */
-	[3] = 10000,		/* 100 kHz */
-	[4] = 100000,		/* 10 kHz */
-	[5] = 1000000,		/* 1 kHz */
-	[11] = 50,		/* 20 MHz (enhanced boards) */
-	/* clock sources 12 and later reserved for enhanced boards */
-};
-
-/*
- * Timestamp timer configuration register (for new PCIe boards).
- */
-#define TS_CONFIG_RESET		0x100	/* Reset counter to zero. */
-#define TS_CONFIG_CLK_SRC_MASK	0x0FF	/* Clock source. */
-#define TS_CONFIG_MAX_CLK_SRC	2	/* Maximum clock source value. */
-
-/*
- * Periods of the timestamp timer clock sources in nanoseconds.
- */
-static const unsigned int ts_clock_period[TS_CONFIG_MAX_CLK_SRC + 1] = {
-	1,			/* 1 nanosecond (but with 20 ns granularity). */
-	1000,			/* 1 microsecond. */
-	1000000,		/* 1 millisecond. */
-};
-
-/*
- * Register region.
- */
-enum dio200_regtype { no_regtype = 0, io_regtype, mmio_regtype };
-struct dio200_region {
-	union {
-		unsigned long iobase;		/* I/O base address */
-		unsigned char __iomem *membase;	/* mapped MMIO base address */
-	} u;
-	enum dio200_regtype regtype;
-};
+#include "amplc_dio200.h"
 
 /*
  * Board descriptions.
  */
-
-enum dio200_bustype { isa_bustype, pci_bustype };
-
-enum dio200_model {
-	pc212e_model,
-	pc214e_model,
-	pc215e_model, pci215_model, pcie215_model,
-	pc218e_model,
-	pcie236_model,
-	pc272e_model, pci272_model,
-	pcie296_model,
-};
-
-enum dio200_layout_idx {
-#if DO_ISA
-	pc212_layout,
-	pc214_layout,
-#endif
-	pc215_layout,
-#if DO_ISA
-	pc218_layout,
-#endif
-	pc272_layout,
-#if DO_PCI
-	pcie215_layout,
-	pcie236_layout,
-	pcie296_layout,
-#endif
-};
-
-struct dio200_board {
-	const char *name;
-	unsigned short devid;
-	enum dio200_bustype bustype;
-	enum dio200_model model;
-	enum dio200_layout_idx layout;
-	unsigned char mainbar;
-	unsigned char mainshift;
-	unsigned int mainsize;
-};
-
-static const struct dio200_board dio200_boards[] = {
-#if DO_ISA
-	{
-	 .name = "pc212e",
-	 .bustype = isa_bustype,
-	 .model = pc212e_model,
-	 .layout = pc212_layout,
-	 .mainsize = DIO200_IO_SIZE,
-	 },
-	{
-	 .name = "pc214e",
-	 .bustype = isa_bustype,
-	 .model = pc214e_model,
-	 .layout = pc214_layout,
-	 .mainsize = DIO200_IO_SIZE,
-	 },
-	{
-	 .name = "pc215e",
-	 .bustype = isa_bustype,
-	 .model = pc215e_model,
-	 .layout = pc215_layout,
-	 .mainsize = DIO200_IO_SIZE,
-	 },
-	{
-	 .name = "pc218e",
-	 .bustype = isa_bustype,
-	 .model = pc218e_model,
-	 .layout = pc218_layout,
-	 .mainsize = DIO200_IO_SIZE,
-	 },
+static const struct dio200_board dio200_isa_boards[] = {
 	{
-	 .name = "pc272e",
-	 .bustype = isa_bustype,
-	 .model = pc272e_model,
-	 .layout = pc272_layout,
-	 .mainsize = DIO200_IO_SIZE,
-	 },
-#endif
-#if DO_PCI
+		.name = "pc212e",
+		.bustype = isa_bustype,
+		.mainsize = DIO200_IO_SIZE,
+		.layout = {
+			.n_subdevs = 6,
+			.sdtype = {sd_8255, sd_8254, sd_8254, sd_8254, sd_8254,
+				   sd_intr},
+			.sdinfo = {0x00, 0x08, 0x0C, 0x10, 0x14, 0x3F},
+			.has_int_sce = true,
+			.has_clk_gat_sce = true,
+		},
+	},
 	{
-	 .name = "pci215",
-	 .devid = PCI_DEVICE_ID_AMPLICON_PCI215,
-	 .bustype = pci_bustype,
-	 .model = pci215_model,
-	 .layout = pc215_layout,
-	 .mainbar = 2,
-	 .mainsize = DIO200_IO_SIZE,
-	 },
+		.name = "pc214e",
+		.bustype = isa_bustype,
+		.mainsize = DIO200_IO_SIZE,
+		.layout = {
+			.n_subdevs = 4,
+			.sdtype = {sd_8255, sd_8255, sd_8254, sd_intr},
+			.sdinfo = {0x00, 0x08, 0x10, 0x01},
+		},
+	},
 	{
-	 .name = "pci272",
-	 .devid = PCI_DEVICE_ID_AMPLICON_PCI272,
-	 .bustype = pci_bustype,
-	 .model = pci272_model,
-	 .layout = pc272_layout,
-	 .mainbar = 2,
-	 .mainsize = DIO200_IO_SIZE,
-	 },
+		.name = "pc215e",
+		.bustype = isa_bustype,
+		.mainsize = DIO200_IO_SIZE,
+		.layout = {
+			.n_subdevs = 5,
+			.sdtype = {sd_8255, sd_8255, sd_8254, sd_8254, sd_intr},
+			.sdinfo = {0x00, 0x08, 0x10, 0x14, 0x3F},
+			.has_int_sce = true,
+			.has_clk_gat_sce = true,
+		},
+	},
 	{
-	 .name = "pcie215",
-	 .devid = PCI_DEVICE_ID_AMPLICON_PCIE215,
-	 .bustype = pci_bustype,
-	 .model = pcie215_model,
-	 .layout = pcie215_layout,
-	 .mainbar = 1,
-	 .mainshift = 3,
-	 .mainsize = DIO200_PCIE_IO_SIZE,
-	 },
+		.name = "pc218e",
+		.bustype = isa_bustype,
+		.mainsize = DIO200_IO_SIZE,
+		.layout = {
+			.n_subdevs = 7,
+			.sdtype = {sd_8254, sd_8254, sd_8255, sd_8254, sd_8254,
+				   sd_intr},
+			.sdinfo = {0x00, 0x04, 0x08, 0x0C, 0x10, 0x14, 0x3F},
+			.has_int_sce = true,
+			.has_clk_gat_sce = true,
+		},
+	},
 	{
-	 .name = "pcie236",
-	 .devid = PCI_DEVICE_ID_AMPLICON_PCIE236,
-	 .bustype = pci_bustype,
-	 .model = pcie236_model,
-	 .layout = pcie236_layout,
-	 .mainbar = 1,
-	 .mainshift = 3,
-	 .mainsize = DIO200_PCIE_IO_SIZE,
-	 },
-	{
-	 .name = "pcie296",
-	 .devid = PCI_DEVICE_ID_AMPLICON_PCIE296,
-	 .bustype = pci_bustype,
-	 .model = pcie296_model,
-	 .layout = pcie296_layout,
-	 .mainbar = 1,
-	 .mainshift = 3,
-	 .mainsize = DIO200_PCIE_IO_SIZE,
-	 },
-#endif
-};
-
-/*
- * Layout descriptions - some ISA and PCI board descriptions share the same
- * layout.
- */
-
-enum dio200_sdtype { sd_none, sd_intr, sd_8255, sd_8254, sd_timer };
-
-#define DIO200_MAX_SUBDEVS	8
-#define DIO200_MAX_ISNS		6
-
-struct dio200_layout {
-	unsigned short n_subdevs;	/* number of subdevices */
-	unsigned char sdtype[DIO200_MAX_SUBDEVS];	/* enum dio200_sdtype */
-	unsigned char sdinfo[DIO200_MAX_SUBDEVS];	/* depends on sdtype */
-	char has_int_sce;	/* has interrupt enable/status register */
-	char has_clk_gat_sce;	/* has clock/gate selection registers */
-	char has_enhancements;	/* has enhanced features */
-};
-
-static const struct dio200_layout dio200_layouts[] = {
-#if DO_ISA
-	[pc212_layout] = {
-			  .n_subdevs = 6,
-			  .sdtype = {sd_8255, sd_8254, sd_8254, sd_8254,
-				     sd_8254,
-				     sd_intr},
-			  .sdinfo = {0x00, 0x08, 0x0C, 0x10, 0x14,
-				     0x3F},
-			  .has_int_sce = 1,
-			  .has_clk_gat_sce = 1,
-			  },
-	[pc214_layout] = {
-			  .n_subdevs = 4,
-			  .sdtype = {sd_8255, sd_8255, sd_8254,
-				     sd_intr},
-			  .sdinfo = {0x00, 0x08, 0x10, 0x01},
-			  .has_int_sce = 0,
-			  .has_clk_gat_sce = 0,
-			  },
-#endif
-	[pc215_layout] = {
-			  .n_subdevs = 5,
-			  .sdtype = {sd_8255, sd_8255, sd_8254,
-				     sd_8254,
-				     sd_intr},
-			  .sdinfo = {0x00, 0x08, 0x10, 0x14, 0x3F},
-			  .has_int_sce = 1,
-			  .has_clk_gat_sce = 1,
-			  },
-#if DO_ISA
-	[pc218_layout] = {
-			  .n_subdevs = 7,
-			  .sdtype = {sd_8254, sd_8254, sd_8255, sd_8254,
-				     sd_8254,
-				     sd_intr},
-			  .sdinfo = {0x00, 0x04, 0x08, 0x0C, 0x10,
-				     0x14,
-				     0x3F},
-			  .has_int_sce = 1,
-			  .has_clk_gat_sce = 1,
-			  },
-#endif
-	[pc272_layout] = {
-			  .n_subdevs = 4,
-			  .sdtype = {sd_8255, sd_8255, sd_8255,
-				     sd_intr},
-			  .sdinfo = {0x00, 0x08, 0x10, 0x3F},
-			  .has_int_sce = 1,
-			  .has_clk_gat_sce = 0,
-			  },
-#if DO_PCI
-	[pcie215_layout] = {
-			  .n_subdevs = 8,
-			  .sdtype = {sd_8255, sd_none, sd_8255, sd_none,
-				     sd_8254, sd_8254, sd_timer, sd_intr},
-			  .sdinfo = {0x00, 0x00, 0x08, 0x00,
-				     0x10, 0x14, 0x00, 0x3F},
-			  .has_int_sce = 1,
-			  .has_clk_gat_sce = 1,
-			  .has_enhancements = 1,
-			  },
-	[pcie236_layout] = {
-			  .n_subdevs = 8,
-			  .sdtype = {sd_8255, sd_none, sd_none, sd_none,
-				     sd_8254, sd_8254, sd_timer, sd_intr},
-			  .sdinfo = {0x00, 0x00, 0x00, 0x00,
-				     0x10, 0x14, 0x00, 0x3F},
-			  .has_int_sce = 1,
-			  .has_clk_gat_sce = 1,
-			  .has_enhancements = 1,
-			  },
-	[pcie296_layout] = {
-			  .n_subdevs = 8,
-			  .sdtype = {sd_8255, sd_8255, sd_8255, sd_8255,
-				     sd_8254, sd_8254, sd_timer, sd_intr},
-			  .sdinfo = {0x00, 0x04, 0x08, 0x0C,
-				     0x10, 0x14, 0x00, 0x3F},
-			  .has_int_sce = 1,
-			  .has_clk_gat_sce = 1,
-			  .has_enhancements = 1,
-			  },
-#endif
-};
-
-/* this structure is for data unique to this hardware driver.  If
-   several hardware drivers keep similar information in this structure,
-   feel free to suggest moving the variable to the struct comedi_device struct.
- */
-struct dio200_private {
-	struct dio200_region io;	/* Register region */
-	int intr_sd;
-};
-
-struct dio200_subdev_8254 {
-	unsigned int ofs;		/* Counter base offset */
-	unsigned int clk_sce_ofs;	/* CLK_SCE base address */
-	unsigned int gat_sce_ofs;	/* GAT_SCE base address */
-	int which;			/* Bit 5 of CLK_SCE or GAT_SCE */
-	unsigned int clock_src[3];	/* Current clock sources */
-	unsigned int gate_src[3];	/* Current gate sources */
-	spinlock_t spinlock;
+		.name = "pc272e",
+		.bustype = isa_bustype,
+		.mainsize = DIO200_IO_SIZE,
+		.layout = {
+			.n_subdevs = 4,
+			.sdtype = {sd_8255, sd_8255, sd_8255, sd_intr},
+			.sdinfo = {0x00, 0x08, 0x10, 0x3F},
+			.has_int_sce = true,
+		},
+	},
 };
 
-struct dio200_subdev_8255 {
-	unsigned int ofs;		/* DIO base offset */
-};
-
-struct dio200_subdev_intr {
-	unsigned int ofs;
-	spinlock_t spinlock;
-	int active;
-	unsigned int valid_isns;
-	unsigned int enabled_isns;
-	unsigned int stopcount;
-	int continuous;
-};
-
-static inline const struct dio200_layout *
-dio200_board_layout(const struct dio200_board *board)
-{
-	return &dio200_layouts[board->layout];
-}
-
-static inline const struct dio200_layout *
-dio200_dev_layout(struct comedi_device *dev)
-{
-	return dio200_board_layout(comedi_board(dev));
-}
-
-static inline bool is_pci_board(const struct dio200_board *board)
-{
-	return DO_PCI && board->bustype == pci_bustype;
-}
-
-static inline bool is_isa_board(const struct dio200_board *board)
-{
-	return DO_ISA && board->bustype == isa_bustype;
-}
-
-/*
- * Read 8-bit register.
- */
-static unsigned char dio200_read8(struct comedi_device *dev,
-				  unsigned int offset)
-{
-	const struct dio200_board *thisboard = comedi_board(dev);
-	struct dio200_private *devpriv = dev->private;
-
-	offset <<= thisboard->mainshift;
-	if (devpriv->io.regtype == io_regtype)
-		return inb(devpriv->io.u.iobase + offset);
-	else
-		return readb(devpriv->io.u.membase + offset);
-}
-
-/*
- * Write 8-bit register.
- */
-static void dio200_write8(struct comedi_device *dev, unsigned int offset,
-			  unsigned char val)
-{
-	const struct dio200_board *thisboard = comedi_board(dev);
-	struct dio200_private *devpriv = dev->private;
-
-	offset <<= thisboard->mainshift;
-	if (devpriv->io.regtype == io_regtype)
-		outb(val, devpriv->io.u.iobase + offset);
-	else
-		writeb(val, devpriv->io.u.membase + offset);
-}
-
-/*
- * Read 32-bit register.
- */
-static unsigned int dio200_read32(struct comedi_device *dev,
-				  unsigned int offset)
-{
-	const struct dio200_board *thisboard = comedi_board(dev);
-	struct dio200_private *devpriv = dev->private;
-
-	offset <<= thisboard->mainshift;
-	if (devpriv->io.regtype == io_regtype)
-		return inl(devpriv->io.u.iobase + offset);
-	else
-		return readl(devpriv->io.u.membase + offset);
-}
-
-/*
- * Write 32-bit register.
- */
-static void dio200_write32(struct comedi_device *dev, unsigned int offset,
-			   unsigned int val)
-{
-	const struct dio200_board *thisboard = comedi_board(dev);
-	struct dio200_private *devpriv = dev->private;
-
-	offset <<= thisboard->mainshift;
-	if (devpriv->io.regtype == io_regtype)
-		outl(val, devpriv->io.u.iobase + offset);
-	else
-		writel(val, devpriv->io.u.membase + offset);
-}
-
-/*
- * This function looks for a board matching the supplied PCI device.
- */
-static const struct dio200_board *
-dio200_find_pci_board(struct pci_dev *pci_dev)
-{
-	unsigned int i;
-
-	for (i = 0; i < ARRAY_SIZE(dio200_boards); i++)
-		if (is_pci_board(&dio200_boards[i]) &&
-		    pci_dev->device == dio200_boards[i].devid)
-			return &dio200_boards[i];
-	return NULL;
-}
-
 /*
  * This function checks and requests an I/O region, reporting an error
  * if there is a conflict.
@@ -752,7 +276,7 @@ static int
 dio200_request_region(struct comedi_device *dev,
 		      unsigned long from, unsigned long extent)
 {
-	if (!from || !request_region(from, extent, DIO200_DRIVER_NAME)) {
+	if (!from || !request_region(from, extent, dev->board_name)) {
 		dev_err(dev->class_dev, "I/O port conflict (%#lx,%lu)!\n",
 			from, extent);
 		return -EIO;
@@ -760,1333 +284,56 @@ dio200_request_region(struct comedi_device *dev,
 	return 0;
 }
 
-/*
- * 'insn_bits' function for an 'INTERRUPT' subdevice.
- */
-static int
-dio200_subdev_intr_insn_bits(struct comedi_device *dev,
-			     struct comedi_subdevice *s,
-			     struct comedi_insn *insn, unsigned int *data)
-{
-	const struct dio200_layout *layout = dio200_dev_layout(dev);
-	struct dio200_subdev_intr *subpriv = s->private;
-
-	if (layout->has_int_sce) {
-		/* Just read the interrupt status register.  */
-		data[1] = dio200_read8(dev, subpriv->ofs) & subpriv->valid_isns;
-	} else {
-		/* No interrupt status register. */
-		data[0] = 0;
-	}
-
-	return insn->n;
-}
-
-/*
- * Called to stop acquisition for an 'INTERRUPT' subdevice.
- */
-static void dio200_stop_intr(struct comedi_device *dev,
-			     struct comedi_subdevice *s)
-{
-	const struct dio200_layout *layout = dio200_dev_layout(dev);
-	struct dio200_subdev_intr *subpriv = s->private;
-
-	subpriv->active = 0;
-	subpriv->enabled_isns = 0;
-	if (layout->has_int_sce)
-		dio200_write8(dev, subpriv->ofs, 0);
-}
-
-/*
- * Called to start acquisition for an 'INTERRUPT' subdevice.
- */
-static int dio200_start_intr(struct comedi_device *dev,
-			     struct comedi_subdevice *s)
-{
-	unsigned int n;
-	unsigned isn_bits;
-	const struct dio200_layout *layout = dio200_dev_layout(dev);
-	struct dio200_subdev_intr *subpriv = s->private;
-	struct comedi_cmd *cmd = &s->async->cmd;
-	int retval = 0;
-
-	if (!subpriv->continuous && subpriv->stopcount == 0) {
-		/* An empty acquisition! */
-		s->async->events |= COMEDI_CB_EOA;
-		subpriv->active = 0;
-		retval = 1;
-	} else {
-		/* Determine interrupt sources to enable. */
-		isn_bits = 0;
-		if (cmd->chanlist) {
-			for (n = 0; n < cmd->chanlist_len; n++)
-				isn_bits |= (1U << CR_CHAN(cmd->chanlist[n]));
-		}
-		isn_bits &= subpriv->valid_isns;
-		/* Enable interrupt sources. */
-		subpriv->enabled_isns = isn_bits;
-		if (layout->has_int_sce)
-			dio200_write8(dev, subpriv->ofs, isn_bits);
-	}
-
-	return retval;
-}
-
-/*
- * Internal trigger function to start acquisition for an 'INTERRUPT' subdevice.
- */
-static int
-dio200_inttrig_start_intr(struct comedi_device *dev, struct comedi_subdevice *s,
-			  unsigned int trignum)
-{
-	struct dio200_subdev_intr *subpriv;
-	unsigned long flags;
-	int event = 0;
-
-	if (trignum != 0)
-		return -EINVAL;
-
-	subpriv = s->private;
-
-	spin_lock_irqsave(&subpriv->spinlock, flags);
-	s->async->inttrig = NULL;
-	if (subpriv->active)
-		event = dio200_start_intr(dev, s);
-
-	spin_unlock_irqrestore(&subpriv->spinlock, flags);
-
-	if (event)
-		comedi_event(dev, s);
-
-	return 1;
-}
-
-/*
- * This is called from the interrupt service routine to handle a read
- * scan on an 'INTERRUPT' subdevice.
- */
-static int dio200_handle_read_intr(struct comedi_device *dev,
-				   struct comedi_subdevice *s)
-{
-	const struct dio200_layout *layout = dio200_dev_layout(dev);
-	struct dio200_subdev_intr *subpriv = s->private;
-	unsigned triggered;
-	unsigned intstat;
-	unsigned cur_enabled;
-	unsigned int oldevents;
-	unsigned long flags;
-
-	triggered = 0;
-
-	spin_lock_irqsave(&subpriv->spinlock, flags);
-	oldevents = s->async->events;
-	if (layout->has_int_sce) {
-		/*
-		 * Collect interrupt sources that have triggered and disable
-		 * them temporarily.  Loop around until no extra interrupt
-		 * sources have triggered, at which point, the valid part of
-		 * the interrupt status register will read zero, clearing the
-		 * cause of the interrupt.
-		 *
-		 * Mask off interrupt sources already seen to avoid infinite
-		 * loop in case of misconfiguration.
-		 */
-		cur_enabled = subpriv->enabled_isns;
-		while ((intstat = (dio200_read8(dev, subpriv->ofs) &
-				   subpriv->valid_isns & ~triggered)) != 0) {
-			triggered |= intstat;
-			cur_enabled &= ~triggered;
-			dio200_write8(dev, subpriv->ofs, cur_enabled);
-		}
-	} else {
-		/*
-		 * No interrupt status register.  Assume the single interrupt
-		 * source has triggered.
-		 */
-		triggered = subpriv->enabled_isns;
-	}
-
-	if (triggered) {
-		/*
-		 * Some interrupt sources have triggered and have been
-		 * temporarily disabled to clear the cause of the interrupt.
-		 *
-		 * Reenable them NOW to minimize the time they are disabled.
-		 */
-		cur_enabled = subpriv->enabled_isns;
-		if (layout->has_int_sce)
-			dio200_write8(dev, subpriv->ofs, cur_enabled);
-
-		if (subpriv->active) {
-			/*
-			 * The command is still active.
-			 *
-			 * Ignore interrupt sources that the command isn't
-			 * interested in (just in case there's a race
-			 * condition).
-			 */
-			if (triggered & subpriv->enabled_isns) {
-				/* Collect scan data. */
-				short val;
-				unsigned int n, ch, len;
-
-				val = 0;
-				len = s->async->cmd.chanlist_len;
-				for (n = 0; n < len; n++) {
-					ch = CR_CHAN(s->async->cmd.chanlist[n]);
-					if (triggered & (1U << ch))
-						val |= (1U << n);
-				}
-				/* Write the scan to the buffer. */
-				if (comedi_buf_put(s->async, val)) {
-					s->async->events |= (COMEDI_CB_BLOCK |
-							     COMEDI_CB_EOS);
-				} else {
-					/* Error!  Stop acquisition.  */
-					dio200_stop_intr(dev, s);
-					s->async->events |= COMEDI_CB_ERROR
-					    | COMEDI_CB_OVERFLOW;
-					comedi_error(dev, "buffer overflow");
-				}
-
-				/* Check for end of acquisition. */
-				if (!subpriv->continuous) {
-					/* stop_src == TRIG_COUNT */
-					if (subpriv->stopcount > 0) {
-						subpriv->stopcount--;
-						if (subpriv->stopcount == 0) {
-							s->async->events |=
-							    COMEDI_CB_EOA;
-							dio200_stop_intr(dev,
-									 s);
-						}
-					}
-				}
-			}
-		}
-	}
-	spin_unlock_irqrestore(&subpriv->spinlock, flags);
-
-	if (oldevents != s->async->events)
-		comedi_event(dev, s);
-
-	return (triggered != 0);
-}
-
-/*
- * 'cancel' function for an 'INTERRUPT' subdevice.
- */
-static int dio200_subdev_intr_cancel(struct comedi_device *dev,
-				     struct comedi_subdevice *s)
-{
-	struct dio200_subdev_intr *subpriv = s->private;
-	unsigned long flags;
-
-	spin_lock_irqsave(&subpriv->spinlock, flags);
-	if (subpriv->active)
-		dio200_stop_intr(dev, s);
-
-	spin_unlock_irqrestore(&subpriv->spinlock, flags);
-
-	return 0;
-}
-
-/*
- * 'do_cmdtest' function for an 'INTERRUPT' subdevice.
- */
-static int
-dio200_subdev_intr_cmdtest(struct comedi_device *dev,
-			   struct comedi_subdevice *s, struct comedi_cmd *cmd)
-{
-	int err = 0;
-
-	/* Step 1 : check if triggers are trivially valid */
-
-	err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
-	err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT);
-	err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
-	err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-	err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
-
-	if (err)
-		return 1;
-
-	/* Step 2a : make sure trigger sources are unique */
-
-	err |= cfc_check_trigger_is_unique(cmd->start_src);
-	err |= cfc_check_trigger_is_unique(cmd->stop_src);
-
-	/* Step 2b : and mutually compatible */
-
-	if (err)
-		return 2;
-
-	/* Step 3: check if arguments are trivially valid */
-
-	err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
-	err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
-	err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
-	err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
-
-	switch (cmd->stop_src) {
-	case TRIG_COUNT:
-		/* any count allowed */
-		break;
-	case TRIG_NONE:
-		err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
-		break;
-	default:
-		break;
-	}
-
-	if (err)
-		return 3;
-
-	/* step 4: fix up any arguments */
-
-	/* if (err) return 4; */
-
-	return 0;
-}
-
-/*
- * 'do_cmd' function for an 'INTERRUPT' subdevice.
- */
-static int dio200_subdev_intr_cmd(struct comedi_device *dev,
-				  struct comedi_subdevice *s)
-{
-	struct comedi_cmd *cmd = &s->async->cmd;
-	struct dio200_subdev_intr *subpriv = s->private;
-	unsigned long flags;
-	int event = 0;
-
-	spin_lock_irqsave(&subpriv->spinlock, flags);
-	subpriv->active = 1;
-
-	/* Set up end of acquisition. */
-	switch (cmd->stop_src) {
-	case TRIG_COUNT:
-		subpriv->continuous = 0;
-		subpriv->stopcount = cmd->stop_arg;
-		break;
-	default:
-		/* TRIG_NONE */
-		subpriv->continuous = 1;
-		subpriv->stopcount = 0;
-		break;
-	}
-
-	/* Set up start of acquisition. */
-	switch (cmd->start_src) {
-	case TRIG_INT:
-		s->async->inttrig = dio200_inttrig_start_intr;
-		break;
-	default:
-		/* TRIG_NOW */
-		event = dio200_start_intr(dev, s);
-		break;
-	}
-	spin_unlock_irqrestore(&subpriv->spinlock, flags);
-
-	if (event)
-		comedi_event(dev, s);
-
-	return 0;
-}
-
-/*
- * This function initializes an 'INTERRUPT' subdevice.
- */
-static int
-dio200_subdev_intr_init(struct comedi_device *dev, struct comedi_subdevice *s,
-			unsigned int offset, unsigned valid_isns)
-{
-	const struct dio200_layout *layout = dio200_dev_layout(dev);
-	struct dio200_subdev_intr *subpriv;
-
-	subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL);
-	if (!subpriv)
-		return -ENOMEM;
-
-	subpriv->ofs = offset;
-	subpriv->valid_isns = valid_isns;
-	spin_lock_init(&subpriv->spinlock);
-
-	if (layout->has_int_sce)
-		/* Disable interrupt sources. */
-		dio200_write8(dev, subpriv->ofs, 0);
-
-	s->private = subpriv;
-	s->type = COMEDI_SUBD_DI;
-	s->subdev_flags = SDF_READABLE | SDF_CMD_READ;
-	if (layout->has_int_sce) {
-		s->n_chan = DIO200_MAX_ISNS;
-		s->len_chanlist = DIO200_MAX_ISNS;
-	} else {
-		/* No interrupt source register.  Support single channel. */
-		s->n_chan = 1;
-		s->len_chanlist = 1;
-	}
-	s->range_table = &range_digital;
-	s->maxdata = 1;
-	s->insn_bits = dio200_subdev_intr_insn_bits;
-	s->do_cmdtest = dio200_subdev_intr_cmdtest;
-	s->do_cmd = dio200_subdev_intr_cmd;
-	s->cancel = dio200_subdev_intr_cancel;
-
-	return 0;
-}
-
-/*
- * This function cleans up an 'INTERRUPT' subdevice.
- */
-static void
-dio200_subdev_intr_cleanup(struct comedi_device *dev,
-			   struct comedi_subdevice *s)
-{
-	struct dio200_subdev_intr *subpriv = s->private;
-	kfree(subpriv);
-}
-
-/*
- * Interrupt service routine.
- */
-static irqreturn_t dio200_interrupt(int irq, void *d)
-{
-	struct comedi_device *dev = d;
-	struct dio200_private *devpriv = dev->private;
-	struct comedi_subdevice *s;
-	int handled;
-
-	if (!dev->attached)
-		return IRQ_NONE;
-
-	if (devpriv->intr_sd >= 0) {
-		s = &dev->subdevices[devpriv->intr_sd];
-		handled = dio200_handle_read_intr(dev, s);
-	} else {
-		handled = 0;
-	}
-
-	return IRQ_RETVAL(handled);
-}
-
-/*
- * Read an '8254' counter subdevice channel.
- */
-static unsigned int
-dio200_subdev_8254_read_chan(struct comedi_device *dev,
-			     struct comedi_subdevice *s, unsigned int chan)
-{
-	struct dio200_subdev_8254 *subpriv = s->private;
-	unsigned int val;
-
-	/* latch counter */
-	val = chan << 6;
-	dio200_write8(dev, subpriv->ofs + i8254_control_reg, val);
-	/* read lsb, msb */
-	val = dio200_read8(dev, subpriv->ofs + chan);
-	val += dio200_read8(dev, subpriv->ofs + chan) << 8;
-	return val;
-}
-
-/*
- * Write an '8254' subdevice channel.
- */
-static void
-dio200_subdev_8254_write_chan(struct comedi_device *dev,
-			      struct comedi_subdevice *s, unsigned int chan,
-			      unsigned int count)
-{
-	struct dio200_subdev_8254 *subpriv = s->private;
-
-	/* write lsb, msb */
-	dio200_write8(dev, subpriv->ofs + chan, count & 0xff);
-	dio200_write8(dev, subpriv->ofs + chan, (count >> 8) & 0xff);
-}
-
-/*
- * Set mode of an '8254' subdevice channel.
- */
-static void
-dio200_subdev_8254_set_mode(struct comedi_device *dev,
-			    struct comedi_subdevice *s, unsigned int chan,
-			    unsigned int mode)
-{
-	struct dio200_subdev_8254 *subpriv = s->private;
-	unsigned int byte;
-
-	byte = chan << 6;
-	byte |= 0x30;		/* access order: lsb, msb */
-	byte |= (mode & 0xf);	/* counter mode and BCD|binary */
-	dio200_write8(dev, subpriv->ofs + i8254_control_reg, byte);
-}
-
-/*
- * Read status byte of an '8254' counter subdevice channel.
- */
-static unsigned int
-dio200_subdev_8254_status(struct comedi_device *dev,
-			  struct comedi_subdevice *s, unsigned int chan)
-{
-	struct dio200_subdev_8254 *subpriv = s->private;
-
-	/* latch status */
-	dio200_write8(dev, subpriv->ofs + i8254_control_reg,
-		      0xe0 | (2 << chan));
-	/* read status */
-	return dio200_read8(dev, subpriv->ofs + chan);
-}
-
-/*
- * Handle 'insn_read' for an '8254' counter subdevice.
- */
-static int
-dio200_subdev_8254_read(struct comedi_device *dev, struct comedi_subdevice *s,
-			struct comedi_insn *insn, unsigned int *data)
-{
-	struct dio200_subdev_8254 *subpriv = s->private;
-	int chan = CR_CHAN(insn->chanspec);
-	unsigned int n;
-	unsigned long flags;
-
-	for (n = 0; n < insn->n; n++) {
-		spin_lock_irqsave(&subpriv->spinlock, flags);
-		data[n] = dio200_subdev_8254_read_chan(dev, s, chan);
-		spin_unlock_irqrestore(&subpriv->spinlock, flags);
-	}
-	return insn->n;
-}
-
-/*
- * Handle 'insn_write' for an '8254' counter subdevice.
- */
-static int
-dio200_subdev_8254_write(struct comedi_device *dev, struct comedi_subdevice *s,
-			 struct comedi_insn *insn, unsigned int *data)
-{
-	struct dio200_subdev_8254 *subpriv = s->private;
-	int chan = CR_CHAN(insn->chanspec);
-	unsigned int n;
-	unsigned long flags;
-
-	for (n = 0; n < insn->n; n++) {
-		spin_lock_irqsave(&subpriv->spinlock, flags);
-		dio200_subdev_8254_write_chan(dev, s, chan, data[n]);
-		spin_unlock_irqrestore(&subpriv->spinlock, flags);
-	}
-	return insn->n;
-}
-
-/*
- * Set gate source for an '8254' counter subdevice channel.
- */
-static int
-dio200_subdev_8254_set_gate_src(struct comedi_device *dev,
-				struct comedi_subdevice *s,
-				unsigned int counter_number,
-				unsigned int gate_src)
-{
-	const struct dio200_layout *layout = dio200_dev_layout(dev);
-	struct dio200_subdev_8254 *subpriv = s->private;
-	unsigned char byte;
-
-	if (!layout->has_clk_gat_sce)
-		return -1;
-	if (counter_number > 2)
-		return -1;
-	if (gate_src > (layout->has_enhancements ? 31 : 7))
-		return -1;
-
-	subpriv->gate_src[counter_number] = gate_src;
-	byte = gat_sce(subpriv->which, counter_number, gate_src);
-	dio200_write8(dev, subpriv->gat_sce_ofs, byte);
-
-	return 0;
-}
-
-/*
- * Get gate source for an '8254' counter subdevice channel.
- */
-static int
-dio200_subdev_8254_get_gate_src(struct comedi_device *dev,
-				struct comedi_subdevice *s,
-				unsigned int counter_number)
-{
-	const struct dio200_layout *layout = dio200_dev_layout(dev);
-	struct dio200_subdev_8254 *subpriv = s->private;
-
-	if (!layout->has_clk_gat_sce)
-		return -1;
-	if (counter_number > 2)
-		return -1;
-
-	return subpriv->gate_src[counter_number];
-}
-
-/*
- * Set clock source for an '8254' counter subdevice channel.
- */
-static int
-dio200_subdev_8254_set_clock_src(struct comedi_device *dev,
-				 struct comedi_subdevice *s,
-				 unsigned int counter_number,
-				 unsigned int clock_src)
-{
-	const struct dio200_layout *layout = dio200_dev_layout(dev);
-	struct dio200_subdev_8254 *subpriv = s->private;
-	unsigned char byte;
-
-	if (!layout->has_clk_gat_sce)
-		return -1;
-	if (counter_number > 2)
-		return -1;
-	if (clock_src > (layout->has_enhancements ? 31 : 7))
-		return -1;
-
-	subpriv->clock_src[counter_number] = clock_src;
-	byte = clk_sce(subpriv->which, counter_number, clock_src);
-	dio200_write8(dev, subpriv->clk_sce_ofs, byte);
-
-	return 0;
-}
-
-/*
- * Get clock source for an '8254' counter subdevice channel.
- */
-static int
-dio200_subdev_8254_get_clock_src(struct comedi_device *dev,
-				 struct comedi_subdevice *s,
-				 unsigned int counter_number,
-				 unsigned int *period_ns)
-{
-	const struct dio200_layout *layout = dio200_dev_layout(dev);
-	struct dio200_subdev_8254 *subpriv = s->private;
-	unsigned clock_src;
-
-	if (!layout->has_clk_gat_sce)
-		return -1;
-	if (counter_number > 2)
-		return -1;
-
-	clock_src = subpriv->clock_src[counter_number];
-	*period_ns = clock_period[clock_src];
-	return clock_src;
-}
-
-/*
- * Handle 'insn_config' for an '8254' counter subdevice.
- */
-static int
-dio200_subdev_8254_config(struct comedi_device *dev, struct comedi_subdevice *s,
-			  struct comedi_insn *insn, unsigned int *data)
-{
-	struct dio200_subdev_8254 *subpriv = s->private;
-	int ret = 0;
-	int chan = CR_CHAN(insn->chanspec);
-	unsigned long flags;
-
-	spin_lock_irqsave(&subpriv->spinlock, flags);
-	switch (data[0]) {
-	case INSN_CONFIG_SET_COUNTER_MODE:
-		if (data[1] > (I8254_MODE5 | I8254_BINARY))
-			ret = -EINVAL;
-		else
-			dio200_subdev_8254_set_mode(dev, s, chan, data[1]);
-		break;
-	case INSN_CONFIG_8254_READ_STATUS:
-		data[1] = dio200_subdev_8254_status(dev, s, chan);
-		break;
-	case INSN_CONFIG_SET_GATE_SRC:
-		ret = dio200_subdev_8254_set_gate_src(dev, s, chan, data[2]);
-		if (ret < 0)
-			ret = -EINVAL;
-		break;
-	case INSN_CONFIG_GET_GATE_SRC:
-		ret = dio200_subdev_8254_get_gate_src(dev, s, chan);
-		if (ret < 0) {
-			ret = -EINVAL;
-			break;
-		}
-		data[2] = ret;
-		break;
-	case INSN_CONFIG_SET_CLOCK_SRC:
-		ret = dio200_subdev_8254_set_clock_src(dev, s, chan, data[1]);
-		if (ret < 0)
-			ret = -EINVAL;
-		break;
-	case INSN_CONFIG_GET_CLOCK_SRC:
-		ret = dio200_subdev_8254_get_clock_src(dev, s, chan, &data[2]);
-		if (ret < 0) {
-			ret = -EINVAL;
-			break;
-		}
-		data[1] = ret;
-		break;
-	default:
-		ret = -EINVAL;
-		break;
-	}
-	spin_unlock_irqrestore(&subpriv->spinlock, flags);
-	return ret < 0 ? ret : insn->n;
-}
-
-/*
- * This function initializes an '8254' counter subdevice.
- */
-static int
-dio200_subdev_8254_init(struct comedi_device *dev, struct comedi_subdevice *s,
-			unsigned int offset)
-{
-	const struct dio200_layout *layout = dio200_dev_layout(dev);
-	struct dio200_subdev_8254 *subpriv;
-	unsigned int chan;
-
-	subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL);
-	if (!subpriv)
-		return -ENOMEM;
-
-	s->private = subpriv;
-	s->type = COMEDI_SUBD_COUNTER;
-	s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
-	s->n_chan = 3;
-	s->maxdata = 0xFFFF;
-	s->insn_read = dio200_subdev_8254_read;
-	s->insn_write = dio200_subdev_8254_write;
-	s->insn_config = dio200_subdev_8254_config;
-
-	spin_lock_init(&subpriv->spinlock);
-	subpriv->ofs = offset;
-	if (layout->has_clk_gat_sce) {
-		/* Derive CLK_SCE and GAT_SCE register offsets from
-		 * 8254 offset. */
-		subpriv->clk_sce_ofs = DIO200_XCLK_SCE + (offset >> 3);
-		subpriv->gat_sce_ofs = DIO200_XGAT_SCE + (offset >> 3);
-		subpriv->which = (offset >> 2) & 1;
-	}
-
-	/* Initialize channels. */
-	for (chan = 0; chan < 3; chan++) {
-		dio200_subdev_8254_set_mode(dev, s, chan,
-					    I8254_MODE0 | I8254_BINARY);
-		if (layout->has_clk_gat_sce) {
-			/* Gate source 0 is VCC (logic 1). */
-			dio200_subdev_8254_set_gate_src(dev, s, chan, 0);
-			/* Clock source 0 is the dedicated clock input. */
-			dio200_subdev_8254_set_clock_src(dev, s, chan, 0);
-		}
-	}
-
-	return 0;
-}
-
-/*
- * This function cleans up an '8254' counter subdevice.
- */
-static void
-dio200_subdev_8254_cleanup(struct comedi_device *dev,
-			   struct comedi_subdevice *s)
-{
-	struct dio200_subdev_intr *subpriv = s->private;
-	kfree(subpriv);
-}
-
-/*
- * This function sets I/O directions for an '8255' DIO subdevice.
- */
-static void dio200_subdev_8255_set_dir(struct comedi_device *dev,
-				       struct comedi_subdevice *s)
-{
-	struct dio200_subdev_8255 *subpriv = s->private;
-	int config;
-
-	config = CR_CW;
-	/* 1 in io_bits indicates output, 1 in config indicates input */
-	if (!(s->io_bits & 0x0000ff))
-		config |= CR_A_IO;
-	if (!(s->io_bits & 0x00ff00))
-		config |= CR_B_IO;
-	if (!(s->io_bits & 0x0f0000))
-		config |= CR_C_LO_IO;
-	if (!(s->io_bits & 0xf00000))
-		config |= CR_C_HI_IO;
-	dio200_write8(dev, subpriv->ofs + 3, config);
-}
-
-/*
- * Handle 'insn_bits' for an '8255' DIO subdevice.
- */
-static int dio200_subdev_8255_bits(struct comedi_device *dev,
-				   struct comedi_subdevice *s,
-				   struct comedi_insn *insn, unsigned int *data)
-{
-	struct dio200_subdev_8255 *subpriv = s->private;
-
-	if (data[0]) {
-		s->state &= ~data[0];
-		s->state |= (data[0] & data[1]);
-		if (data[0] & 0xff)
-			dio200_write8(dev, subpriv->ofs, s->state & 0xff);
-		if (data[0] & 0xff00)
-			dio200_write8(dev, subpriv->ofs + 1,
-				      (s->state >> 8) & 0xff);
-		if (data[0] & 0xff0000)
-			dio200_write8(dev, subpriv->ofs + 2,
-				      (s->state >> 16) & 0xff);
-	}
-	data[1] = dio200_read8(dev, subpriv->ofs);
-	data[1] |= dio200_read8(dev, subpriv->ofs + 1) << 8;
-	data[1] |= dio200_read8(dev, subpriv->ofs + 2) << 16;
-	return 2;
-}
-
-/*
- * Handle 'insn_config' for an '8255' DIO subdevice.
- */
-static int dio200_subdev_8255_config(struct comedi_device *dev,
-				     struct comedi_subdevice *s,
-				     struct comedi_insn *insn,
-				     unsigned int *data)
-{
-	unsigned int mask;
-	unsigned int bits;
-
-	mask = 1 << CR_CHAN(insn->chanspec);
-	if (mask & 0x0000ff)
-		bits = 0x0000ff;
-	else if (mask & 0x00ff00)
-		bits = 0x00ff00;
-	else if (mask & 0x0f0000)
-		bits = 0x0f0000;
-	else
-		bits = 0xf00000;
-	switch (data[0]) {
-	case INSN_CONFIG_DIO_INPUT:
-		s->io_bits &= ~bits;
-		break;
-	case INSN_CONFIG_DIO_OUTPUT:
-		s->io_bits |= bits;
-		break;
-	case INSN_CONFIG_DIO_QUERY:
-		data[1] = (s->io_bits & bits) ? COMEDI_OUTPUT : COMEDI_INPUT;
-		return insn->n;
-		break;
-	default:
-		return -EINVAL;
-	}
-	dio200_subdev_8255_set_dir(dev, s);
-	return 1;
-}
-
-/*
- * This function initializes an '8255' DIO subdevice.
- *
- * offset is the offset to the 8255 chip.
- */
-static int dio200_subdev_8255_init(struct comedi_device *dev,
-				   struct comedi_subdevice *s,
-				   unsigned int offset)
-{
-	struct dio200_subdev_8255 *subpriv;
-
-	subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL);
-	if (!subpriv)
-		return -ENOMEM;
-	subpriv->ofs = offset;
-	s->private = subpriv;
-	s->type = COMEDI_SUBD_DIO;
-	s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
-	s->n_chan = 24;
-	s->range_table = &range_digital;
-	s->maxdata = 1;
-	s->insn_bits = dio200_subdev_8255_bits;
-	s->insn_config = dio200_subdev_8255_config;
-	s->state = 0;
-	s->io_bits = 0;
-	dio200_subdev_8255_set_dir(dev, s);
-	return 0;
-}
-
-/*
- * This function cleans up an '8255' DIO subdevice.
- */
-static void dio200_subdev_8255_cleanup(struct comedi_device *dev,
-				       struct comedi_subdevice *s)
-{
-	struct dio200_subdev_8255 *subpriv = s->private;
-
-	kfree(subpriv);
-}
-
-/*
- * Handle 'insn_read' for a timer subdevice.
- */
-static int dio200_subdev_timer_read(struct comedi_device *dev,
-				    struct comedi_subdevice *s,
-				    struct comedi_insn *insn,
-				    unsigned int *data)
-{
-	unsigned int n;
-
-	for (n = 0; n < insn->n; n++)
-		data[n] = dio200_read32(dev, DIO200_TS_COUNT);
-	return n;
-}
-
-/*
- * Reset timer subdevice.
- */
-static void dio200_subdev_timer_reset(struct comedi_device *dev,
-				      struct comedi_subdevice *s)
-{
-	unsigned int clock;
-
-	clock = dio200_read32(dev, DIO200_TS_CONFIG) & TS_CONFIG_CLK_SRC_MASK;
-	dio200_write32(dev, DIO200_TS_CONFIG, clock | TS_CONFIG_RESET);
-	dio200_write32(dev, DIO200_TS_CONFIG, clock);
-}
-
-/*
- * Get timer subdevice clock source and period.
- */
-static void dio200_subdev_timer_get_clock_src(struct comedi_device *dev,
-					      struct comedi_subdevice *s,
-					      unsigned int *src,
-					      unsigned int *period)
-{
-	unsigned int clk;
-
-	clk = dio200_read32(dev, DIO200_TS_CONFIG) & TS_CONFIG_CLK_SRC_MASK;
-	*src = clk;
-	*period = (clk < ARRAY_SIZE(ts_clock_period)) ?
-		  ts_clock_period[clk] : 0;
-}
-
-/*
- * Set timer subdevice clock source.
- */
-static int dio200_subdev_timer_set_clock_src(struct comedi_device *dev,
-					     struct comedi_subdevice *s,
-					     unsigned int src)
-{
-	if (src > TS_CONFIG_MAX_CLK_SRC)
-		return -EINVAL;
-	dio200_write32(dev, DIO200_TS_CONFIG, src);
-	return 0;
-}
-
-/*
- * Handle 'insn_config' for a timer subdevice.
- */
-static int dio200_subdev_timer_config(struct comedi_device *dev,
-				      struct comedi_subdevice *s,
-				      struct comedi_insn *insn,
-				      unsigned int *data)
-{
-	int ret = 0;
-
-	switch (data[0]) {
-	case INSN_CONFIG_RESET:
-		dio200_subdev_timer_reset(dev, s);
-		break;
-	case INSN_CONFIG_SET_CLOCK_SRC:
-		ret = dio200_subdev_timer_set_clock_src(dev, s, data[1]);
-		if (ret < 0)
-			ret = -EINVAL;
-		break;
-	case INSN_CONFIG_GET_CLOCK_SRC:
-		dio200_subdev_timer_get_clock_src(dev, s, &data[1], &data[2]);
-		break;
-	default:
-		ret = -EINVAL;
-		break;
-	}
-	return ret < 0 ? ret : insn->n;
-}
-
-/*
- * This function initializes a timer subdevice.
- *
- * Uses the timestamp timer registers.  There is only one timestamp timer.
- */
-static int dio200_subdev_timer_init(struct comedi_device *dev,
-				    struct comedi_subdevice *s)
-{
-	s->type = COMEDI_SUBD_TIMER;
-	s->subdev_flags = SDF_READABLE | SDF_LSAMPL;
-	s->n_chan = 1;
-	s->maxdata = 0xFFFFFFFF;
-	s->insn_read = dio200_subdev_timer_read;
-	s->insn_config = dio200_subdev_timer_config;
-	return 0;
-}
-
-/*
- * This function cleans up a timer subdevice.
- */
-static void dio200_subdev_timer_cleanup(struct comedi_device *dev,
-					struct comedi_subdevice *s)
-{
-	/* Nothing to do. */
-}
-
-/*
- * This function does some special set-up for the PCIe boards
- * PCIe215, PCIe236, PCIe296.
- */
-static int dio200_pcie_board_setup(struct comedi_device *dev)
-{
-	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-	void __iomem *brbase;
-	resource_size_t brlen;
-
-	/*
-	 * The board uses Altera Cyclone IV with PCI-Express hard IP.
-	 * The FPGA configuration has the PCI-Express Avalon-MM Bridge
-	 * Control registers in PCI BAR 0, offset 0, and the length of
-	 * these registers is 0x4000.
-	 *
-	 * We need to write 0x80 to the "Avalon-MM to PCI-Express Interrupt
-	 * Enable" register at offset 0x50 to allow generation of PCIe
-	 * interrupts when RXmlrq_i is asserted in the SOPC Builder system.
-	 */
-	brlen = pci_resource_len(pcidev, 0);
-	if (brlen < 0x4000 ||
-			!(pci_resource_flags(pcidev, 0) & IORESOURCE_MEM)) {
-		dev_err(dev->class_dev, "error! bad PCI region!\n");
-		return -EINVAL;
-	}
-	brbase = ioremap_nocache(pci_resource_start(pcidev, 0), brlen);
-	if (!brbase) {
-		dev_err(dev->class_dev, "error! failed to map registers!\n");
-		return -ENOMEM;
-	}
-	writel(0x80, brbase + 0x50);
-	iounmap(brbase);
-	/* Enable "enhanced" features of board. */
-	dio200_write8(dev, DIO200_ENHANCE, 1);
-	return 0;
-}
-
-static void dio200_report_attach(struct comedi_device *dev, unsigned int irq)
-{
-	const struct dio200_board *thisboard = comedi_board(dev);
-	struct dio200_private *devpriv = dev->private;
-	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-	char tmpbuf[60];
-	int tmplen;
-
-	if (is_isa_board(thisboard))
-		tmplen = scnprintf(tmpbuf, sizeof(tmpbuf),
-				   "(base %#lx) ", devpriv->io.u.iobase);
-	else if (is_pci_board(thisboard))
-		tmplen = scnprintf(tmpbuf, sizeof(tmpbuf),
-				   "(pci %s) ", pci_name(pcidev));
-	else
-		tmplen = 0;
-	if (irq)
-		tmplen += scnprintf(&tmpbuf[tmplen], sizeof(tmpbuf) - tmplen,
-				    "(irq %u%s) ", irq,
-				    (dev->irq ? "" : " UNAVAILABLE"));
-	else
-		tmplen += scnprintf(&tmpbuf[tmplen], sizeof(tmpbuf) - tmplen,
-				    "(no irq) ");
-	dev_info(dev->class_dev, "%s %sattached\n", dev->board_name, tmpbuf);
-}
-
-static int dio200_common_attach(struct comedi_device *dev, unsigned int irq,
-				unsigned long req_irq_flags)
-{
-	const struct dio200_board *thisboard = comedi_board(dev);
-	struct dio200_private *devpriv = dev->private;
-	const struct dio200_layout *layout = dio200_board_layout(thisboard);
-	struct comedi_subdevice *s;
-	int sdx;
-	unsigned int n;
-	int ret;
-
-	devpriv->intr_sd = -1;
-	dev->board_name = thisboard->name;
-
-	ret = comedi_alloc_subdevices(dev, layout->n_subdevs);
-	if (ret)
-		return ret;
-
-	for (n = 0; n < dev->n_subdevices; n++) {
-		s = &dev->subdevices[n];
-		switch (layout->sdtype[n]) {
-		case sd_8254:
-			/* counter subdevice (8254) */
-			ret = dio200_subdev_8254_init(dev, s,
-						      layout->sdinfo[n]);
-			if (ret < 0)
-				return ret;
-			break;
-		case sd_8255:
-			/* digital i/o subdevice (8255) */
-			ret = dio200_subdev_8255_init(dev, s,
-						      layout->sdinfo[n]);
-			if (ret < 0)
-				return ret;
-			break;
-		case sd_intr:
-			/* 'INTERRUPT' subdevice */
-			if (irq) {
-				ret = dio200_subdev_intr_init(dev, s,
-							      DIO200_INT_SCE,
-							      layout->sdinfo[n]
-							     );
-				if (ret < 0)
-					return ret;
-				devpriv->intr_sd = n;
-			} else {
-				s->type = COMEDI_SUBD_UNUSED;
-			}
-			break;
-		case sd_timer:
-			/* Only on PCIe boards. */
-			if (DO_PCI) {
-				ret = dio200_subdev_timer_init(dev, s);
-				if (ret < 0)
-					return ret;
-			} else {
-				s->type = COMEDI_SUBD_UNUSED;
-			}
-			break;
-		default:
-			s->type = COMEDI_SUBD_UNUSED;
-			break;
-		}
-	}
-	sdx = devpriv->intr_sd;
-	if (sdx >= 0 && sdx < dev->n_subdevices)
-		dev->read_subdev = &dev->subdevices[sdx];
-	if (irq) {
-		if (request_irq(irq, dio200_interrupt, req_irq_flags,
-				DIO200_DRIVER_NAME, dev) >= 0) {
-			dev->irq = irq;
-		} else {
-			dev_warn(dev->class_dev,
-				 "warning! irq %u unavailable!\n", irq);
-		}
-	}
-	dio200_report_attach(dev, irq);
-	return 1;
-}
-
-/*
- * Attach is called by the Comedi core to configure the driver
- * for a particular board.  If you specified a board_name array
- * in the driver structure, dev->board_ptr contains that
- * address.
- */
 static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
 	const struct dio200_board *thisboard = comedi_board(dev);
 	struct dio200_private *devpriv;
+	unsigned long iobase;
+	unsigned int irq;
 	int ret;
 
-	dev_info(dev->class_dev, DIO200_DRIVER_NAME ": attach\n");
-
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
-	if (!devpriv)
-		return -ENOMEM;
-	dev->private = devpriv;
-
-	/* Process options and reserve resources according to bus type. */
-	if (is_isa_board(thisboard)) {
-		unsigned long iobase;
-		unsigned int irq;
-
-		iobase = it->options[0];
-		irq = it->options[1];
-		ret = dio200_request_region(dev, iobase, thisboard->mainsize);
-		if (ret < 0)
-			return ret;
-		devpriv->io.u.iobase = iobase;
-		devpriv->io.regtype = io_regtype;
-		return dio200_common_attach(dev, irq, 0);
-	} else if (is_pci_board(thisboard)) {
-		dev_err(dev->class_dev,
-			"Manual configuration of PCI board '%s' is not supported\n",
-			thisboard->name);
-		return -EIO;
-	} else {
-		dev_err(dev->class_dev, DIO200_DRIVER_NAME
-			": BUG! cannot determine board type!\n");
-		return -EINVAL;
-	}
-}
-
-/*
- * The auto_attach hook is called at PCI probe time via
- * comedi_pci_auto_config().  dev->board_ptr is NULL on entry.
- * There should be a board entry matching the supplied PCI device.
- */
-static int dio200_auto_attach(struct comedi_device *dev,
-					unsigned long context_unused)
-{
-	struct pci_dev *pci_dev = comedi_to_pci_dev(dev);
-	const struct dio200_board *thisboard;
-	struct dio200_private *devpriv;
-	resource_size_t base, len;
-	unsigned int bar;
-	int ret;
-
-	if (!DO_PCI)
-		return -EINVAL;
-
-	dev_info(dev->class_dev, DIO200_DRIVER_NAME ": attach pci %s\n",
-		 pci_name(pci_dev));
+	dev->board_name = thisboard->name;
+	iobase = it->options[0];
+	irq = it->options[1];
+	dev_info(dev->class_dev, "%s: attach %s 0x%lX,%u\n",
+		 dev->driver->driver_name, dev->board_name, iobase, irq);
 
 	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
 	if (!devpriv)
 		return -ENOMEM;
 	dev->private = devpriv;
 
-	dev->board_ptr = dio200_find_pci_board(pci_dev);
-	if (dev->board_ptr == NULL) {
-		dev_err(dev->class_dev, "BUG! cannot determine board type!\n");
-		return -EINVAL;
-	}
-	thisboard = comedi_board(dev);
-	ret = comedi_pci_enable(pci_dev, DIO200_DRIVER_NAME);
-	if (ret < 0) {
-		dev_err(dev->class_dev,
-			"error! cannot enable PCI device and request regions!\n");
+	ret = dio200_request_region(dev, iobase, thisboard->mainsize);
+	if (ret < 0)
 		return ret;
-	}
-	bar = thisboard->mainbar;
-	base = pci_resource_start(pci_dev, bar);
-	len = pci_resource_len(pci_dev, bar);
-	if (len < thisboard->mainsize) {
-		dev_err(dev->class_dev, "error! PCI region size too small!\n");
-		return -EINVAL;
-	}
-	if ((pci_resource_flags(pci_dev, bar) & IORESOURCE_MEM) != 0) {
-		devpriv->io.u.membase = ioremap_nocache(base, len);
-		if (!devpriv->io.u.membase) {
-			dev_err(dev->class_dev,
-				"error! cannot remap registers\n");
-			return -ENOMEM;
-		}
-		devpriv->io.regtype = mmio_regtype;
-	} else {
-		devpriv->io.u.iobase = (unsigned long)base;
-		devpriv->io.regtype = io_regtype;
-	}
-	switch (thisboard->model) {
-	case pcie215_model:
-	case pcie236_model:
-	case pcie296_model:
-		ret = dio200_pcie_board_setup(dev);
-		if (ret < 0)
-			return ret;
-		break;
-	default:
-		break;
-	}
-	return dio200_common_attach(dev, pci_dev->irq, IRQF_SHARED);
+	devpriv->io.u.iobase = iobase;
+	devpriv->io.regtype = io_regtype;
+	return amplc_dio200_common_attach(dev, irq, 0);
 }
 
 static void dio200_detach(struct comedi_device *dev)
 {
 	const struct dio200_board *thisboard = comedi_board(dev);
 	struct dio200_private *devpriv = dev->private;
-	const struct dio200_layout *layout;
-	unsigned n;
 
 	if (!thisboard || !devpriv)
 		return;
-	if (dev->irq)
-		free_irq(dev->irq, dev);
-	if (dev->subdevices) {
-		layout = dio200_board_layout(thisboard);
-		for (n = 0; n < dev->n_subdevices; n++) {
-			struct comedi_subdevice *s = &dev->subdevices[n];
-			switch (layout->sdtype[n]) {
-			case sd_8254:
-				dio200_subdev_8254_cleanup(dev, s);
-				break;
-			case sd_8255:
-				dio200_subdev_8255_cleanup(dev, s);
-				break;
-			case sd_intr:
-				dio200_subdev_intr_cleanup(dev, s);
-				break;
-			case sd_timer:
-				/* Only on PCIe boards. */
-				if (DO_PCI)
-					dio200_subdev_timer_cleanup(dev, s);
-				break;
-			default:
-				break;
-			}
-		}
-	}
-	if (is_isa_board(thisboard)) {
-		if (devpriv->io.regtype == io_regtype)
-			release_region(devpriv->io.u.iobase,
-				       thisboard->mainsize);
-	} else if (is_pci_board(thisboard)) {
-		struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-		if (pcidev) {
-			if (devpriv->io.regtype != no_regtype) {
-				if (devpriv->io.regtype == mmio_regtype)
-					iounmap(devpriv->io.u.membase);
-				comedi_pci_disable(pcidev);
-			}
-		}
-	}
+	amplc_dio200_common_detach(dev);
+	if (devpriv->io.regtype == io_regtype)
+		release_region(devpriv->io.u.iobase, thisboard->mainsize);
 }
 
-/*
- * The struct comedi_driver structure tells the Comedi core module
- * which functions to call to configure/deconfigure (attach/detach)
- * the board, and also about the kernel module that contains
- * the device code.
- */
 static struct comedi_driver amplc_dio200_driver = {
-	.driver_name = DIO200_DRIVER_NAME,
+	.driver_name = "amplc_dio200",
 	.module = THIS_MODULE,
 	.attach = dio200_attach,
-	.auto_attach = dio200_auto_attach,
 	.detach = dio200_detach,
-	.board_name = &dio200_boards[0].name,
+	.board_name = &dio200_isa_boards[0].name,
 	.offset = sizeof(struct dio200_board),
-	.num_names = ARRAY_SIZE(dio200_boards),
-};
-
-#if DO_PCI
-static DEFINE_PCI_DEVICE_TABLE(dio200_pci_table) = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI215) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI272) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCIE236) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCIE215) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCIE296) },
-	{0}
-};
-
-MODULE_DEVICE_TABLE(pci, dio200_pci_table);
-
-static int amplc_dio200_pci_probe(struct pci_dev *dev,
-						   const struct pci_device_id
-						   *ent)
-{
-	return comedi_pci_auto_config(dev, &amplc_dio200_driver);
-}
-
-static struct pci_driver amplc_dio200_pci_driver = {
-	.name = DIO200_DRIVER_NAME,
-	.id_table = dio200_pci_table,
-	.probe = &amplc_dio200_pci_probe,
-	.remove		= comedi_pci_auto_unconfig,
+	.num_names = ARRAY_SIZE(dio200_isa_boards),
 };
-module_comedi_pci_driver(amplc_dio200_driver, amplc_dio200_pci_driver);
-#else
 module_comedi_driver(amplc_dio200_driver);
-#endif
 
 MODULE_AUTHOR("Comedi http://www.comedi.org");
-MODULE_DESCRIPTION("Comedi low-level driver");
+MODULE_DESCRIPTION("Comedi driver for Amplicon 200 Series ISA DIO boards");
 MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/amplc_dio200.h b/drivers/staging/comedi/drivers/amplc_dio200.h
new file mode 100644
index 0000000..cf2e726
--- /dev/null
+++ b/drivers/staging/comedi/drivers/amplc_dio200.h
@@ -0,0 +1,95 @@
+/*
+    comedi/drivers/amplc_dio.h
+
+    Header for amplc_dio200.c, amplc_dio200_common.c and
+    amplc_dio200_pci.c.
+
+    Copyright (C) 2005-2013 MEV Ltd. <http://www.mev.co.uk/>
+
+    COMEDI - Linux Control and Measurement Device Interface
+    Copyright (C) 1998,2000 David A. Schleef <ds@schleef.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.
+
+*/
+
+#ifndef AMPLC_DIO200_H_INCLUDED
+#define AMPLC_DIO200_H_INCLUDED
+
+/* 200 series register area sizes */
+#define DIO200_IO_SIZE		0x20
+#define DIO200_PCIE_IO_SIZE	0x4000
+
+/*
+ * Register region.
+ */
+enum dio200_regtype { no_regtype = 0, io_regtype, mmio_regtype };
+struct dio200_region {
+	union {
+		unsigned long iobase;		/* I/O base address */
+		unsigned char __iomem *membase;	/* mapped MMIO base address */
+	} u;
+	enum dio200_regtype regtype;
+};
+
+/*
+ * Subdevice types.
+ */
+enum dio200_sdtype { sd_none, sd_intr, sd_8255, sd_8254, sd_timer };
+
+#define DIO200_MAX_SUBDEVS	8
+#define DIO200_MAX_ISNS		6
+
+/*
+ * Board descriptions.
+ */
+
+struct dio200_layout {
+	unsigned short n_subdevs;	/* number of subdevices */
+	unsigned char sdtype[DIO200_MAX_SUBDEVS];	/* enum dio200_sdtype */
+	unsigned char sdinfo[DIO200_MAX_SUBDEVS];	/* depends on sdtype */
+	bool has_int_sce:1;		/* has interrupt enable/status reg */
+	bool has_clk_gat_sce:1;		/* has clock/gate selection registers */
+	bool has_enhancements:1;	/* has enhanced features */
+};
+
+enum dio200_bustype { isa_bustype, pci_bustype };
+
+struct dio200_board {
+	const char *name;
+	struct dio200_layout layout;
+	enum dio200_bustype bustype;
+	unsigned char mainbar;
+	unsigned char mainshift;
+	unsigned int mainsize;
+};
+
+/*
+ * Comedi device private data.
+ */
+struct dio200_private {
+	struct dio200_region io;	/* Register region */
+	int intr_sd;
+};
+
+int amplc_dio200_common_attach(struct comedi_device *dev, unsigned int irq,
+			       unsigned long req_irq_flags);
+
+void amplc_dio200_common_detach(struct comedi_device *dev);
+
+/* Used by initialization of PCIe boards. */
+void amplc_dio200_set_enhance(struct comedi_device *dev, unsigned char val);
+
+#endif
diff --git a/drivers/staging/comedi/drivers/amplc_dio200_common.c b/drivers/staging/comedi/drivers/amplc_dio200_common.c
new file mode 100644
index 0000000..04a798e
--- /dev/null
+++ b/drivers/staging/comedi/drivers/amplc_dio200_common.c
@@ -0,0 +1,1320 @@
+/*
+    comedi/drivers/amplc_dio200_common.c
+
+    Common support code for "amplc_dio200" and "amplc_dio200_pci".
+
+    Copyright (C) 2005-2013 MEV Ltd. <http://www.mev.co.uk/>
+
+    COMEDI - Linux Control and Measurement Device Interface
+    Copyright (C) 1998,2000 David A. Schleef <ds@schleef.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/interrupt.h>
+#include <linux/slab.h>
+
+#include "../comedidev.h"
+
+#include "amplc_dio200.h"
+#include "comedi_fc.h"
+#include "8253.h"
+
+/* 8255 control register bits */
+#define CR_C_LO_IO	0x01
+#define CR_B_IO		0x02
+#define CR_B_MODE	0x04
+#define CR_C_HI_IO	0x08
+#define CR_A_IO		0x10
+#define CR_A_MODE(a)	((a)<<5)
+#define CR_CW		0x80
+
+/* 200 series registers */
+#define DIO200_IO_SIZE		0x20
+#define DIO200_PCIE_IO_SIZE	0x4000
+#define DIO200_XCLK_SCE		0x18	/* Group X clock selection register */
+#define DIO200_YCLK_SCE		0x19	/* Group Y clock selection register */
+#define DIO200_ZCLK_SCE		0x1a	/* Group Z clock selection register */
+#define DIO200_XGAT_SCE		0x1b	/* Group X gate selection register */
+#define DIO200_YGAT_SCE		0x1c	/* Group Y gate selection register */
+#define DIO200_ZGAT_SCE		0x1d	/* Group Z gate selection register */
+#define DIO200_INT_SCE		0x1e	/* Interrupt enable/status register */
+/* Extra registers for new PCIe boards */
+#define DIO200_ENHANCE		0x20	/* 1 to enable enhanced features */
+#define DIO200_VERSION		0x24	/* Hardware version register */
+#define DIO200_TS_CONFIG	0x600	/* Timestamp timer config register */
+#define DIO200_TS_COUNT		0x602	/* Timestamp timer count register */
+
+/*
+ * Functions for constructing value for DIO_200_?CLK_SCE and
+ * DIO_200_?GAT_SCE registers:
+ *
+ * 'which' is: 0 for CTR-X1, CTR-Y1, CTR-Z1; 1 for CTR-X2, CTR-Y2 or CTR-Z2.
+ * 'chan' is the channel: 0, 1 or 2.
+ * 'source' is the signal source: 0 to 7, or 0 to 31 for "enhanced" boards.
+ */
+static unsigned char clk_gat_sce(unsigned int which, unsigned int chan,
+				 unsigned int source)
+{
+	return (which << 5) | (chan << 3) |
+	       ((source & 030) << 3) | (source & 007);
+}
+
+static unsigned char clk_sce(unsigned int which, unsigned int chan,
+			     unsigned int source)
+{
+	return clk_gat_sce(which, chan, source);
+}
+
+static unsigned char gat_sce(unsigned int which, unsigned int chan,
+			     unsigned int source)
+{
+	return clk_gat_sce(which, chan, source);
+}
+
+/*
+ * Periods of the internal clock sources in nanoseconds.
+ */
+static const unsigned int clock_period[32] = {
+	[1] = 100,		/* 10 MHz */
+	[2] = 1000,		/* 1 MHz */
+	[3] = 10000,		/* 100 kHz */
+	[4] = 100000,		/* 10 kHz */
+	[5] = 1000000,		/* 1 kHz */
+	[11] = 50,		/* 20 MHz (enhanced boards) */
+	/* clock sources 12 and later reserved for enhanced boards */
+};
+
+/*
+ * Timestamp timer configuration register (for new PCIe boards).
+ */
+#define TS_CONFIG_RESET		0x100	/* Reset counter to zero. */
+#define TS_CONFIG_CLK_SRC_MASK	0x0FF	/* Clock source. */
+#define TS_CONFIG_MAX_CLK_SRC	2	/* Maximum clock source value. */
+
+/*
+ * Periods of the timestamp timer clock sources in nanoseconds.
+ */
+static const unsigned int ts_clock_period[TS_CONFIG_MAX_CLK_SRC + 1] = {
+	1,			/* 1 nanosecond (but with 20 ns granularity). */
+	1000,			/* 1 microsecond. */
+	1000000,		/* 1 millisecond. */
+};
+
+struct dio200_subdev_8254 {
+	unsigned int ofs;		/* Counter base offset */
+	unsigned int clk_sce_ofs;	/* CLK_SCE base address */
+	unsigned int gat_sce_ofs;	/* GAT_SCE base address */
+	int which;			/* Bit 5 of CLK_SCE or GAT_SCE */
+	unsigned int clock_src[3];	/* Current clock sources */
+	unsigned int gate_src[3];	/* Current gate sources */
+	spinlock_t spinlock;
+};
+
+struct dio200_subdev_8255 {
+	unsigned int ofs;		/* DIO base offset */
+};
+
+struct dio200_subdev_intr {
+	spinlock_t spinlock;
+	unsigned int ofs;
+	unsigned int valid_isns;
+	unsigned int enabled_isns;
+	unsigned int stopcount;
+	bool active:1;
+	bool continuous:1;
+};
+
+static inline const struct dio200_layout *
+dio200_board_layout(const struct dio200_board *board)
+{
+	return &board->layout;
+}
+
+static inline const struct dio200_layout *
+dio200_dev_layout(struct comedi_device *dev)
+{
+	return dio200_board_layout(comedi_board(dev));
+}
+
+/*
+ * Read 8-bit register.
+ */
+static unsigned char dio200_read8(struct comedi_device *dev,
+				  unsigned int offset)
+{
+	const struct dio200_board *thisboard = comedi_board(dev);
+	struct dio200_private *devpriv = dev->private;
+
+	offset <<= thisboard->mainshift;
+	if (devpriv->io.regtype == io_regtype)
+		return inb(devpriv->io.u.iobase + offset);
+	else
+		return readb(devpriv->io.u.membase + offset);
+}
+
+/*
+ * Write 8-bit register.
+ */
+static void dio200_write8(struct comedi_device *dev, unsigned int offset,
+			  unsigned char val)
+{
+	const struct dio200_board *thisboard = comedi_board(dev);
+	struct dio200_private *devpriv = dev->private;
+
+	offset <<= thisboard->mainshift;
+	if (devpriv->io.regtype == io_regtype)
+		outb(val, devpriv->io.u.iobase + offset);
+	else
+		writeb(val, devpriv->io.u.membase + offset);
+}
+
+/*
+ * Read 32-bit register.
+ */
+static unsigned int dio200_read32(struct comedi_device *dev,
+				  unsigned int offset)
+{
+	const struct dio200_board *thisboard = comedi_board(dev);
+	struct dio200_private *devpriv = dev->private;
+
+	offset <<= thisboard->mainshift;
+	if (devpriv->io.regtype == io_regtype)
+		return inl(devpriv->io.u.iobase + offset);
+	else
+		return readl(devpriv->io.u.membase + offset);
+}
+
+/*
+ * Write 32-bit register.
+ */
+static void dio200_write32(struct comedi_device *dev, unsigned int offset,
+			   unsigned int val)
+{
+	const struct dio200_board *thisboard = comedi_board(dev);
+	struct dio200_private *devpriv = dev->private;
+
+	offset <<= thisboard->mainshift;
+	if (devpriv->io.regtype == io_regtype)
+		outl(val, devpriv->io.u.iobase + offset);
+	else
+		writel(val, devpriv->io.u.membase + offset);
+}
+
+/*
+ * 'insn_bits' function for an 'INTERRUPT' subdevice.
+ */
+static int
+dio200_subdev_intr_insn_bits(struct comedi_device *dev,
+			     struct comedi_subdevice *s,
+			     struct comedi_insn *insn, unsigned int *data)
+{
+	const struct dio200_layout *layout = dio200_dev_layout(dev);
+	struct dio200_subdev_intr *subpriv = s->private;
+
+	if (layout->has_int_sce) {
+		/* Just read the interrupt status register.  */
+		data[1] = dio200_read8(dev, subpriv->ofs) & subpriv->valid_isns;
+	} else {
+		/* No interrupt status register. */
+		data[0] = 0;
+	}
+
+	return insn->n;
+}
+
+/*
+ * Called to stop acquisition for an 'INTERRUPT' subdevice.
+ */
+static void dio200_stop_intr(struct comedi_device *dev,
+			     struct comedi_subdevice *s)
+{
+	const struct dio200_layout *layout = dio200_dev_layout(dev);
+	struct dio200_subdev_intr *subpriv = s->private;
+
+	subpriv->active = false;
+	subpriv->enabled_isns = 0;
+	if (layout->has_int_sce)
+		dio200_write8(dev, subpriv->ofs, 0);
+}
+
+/*
+ * Called to start acquisition for an 'INTERRUPT' subdevice.
+ */
+static int dio200_start_intr(struct comedi_device *dev,
+			     struct comedi_subdevice *s)
+{
+	unsigned int n;
+	unsigned isn_bits;
+	const struct dio200_layout *layout = dio200_dev_layout(dev);
+	struct dio200_subdev_intr *subpriv = s->private;
+	struct comedi_cmd *cmd = &s->async->cmd;
+	int retval = 0;
+
+	if (!subpriv->continuous && subpriv->stopcount == 0) {
+		/* An empty acquisition! */
+		s->async->events |= COMEDI_CB_EOA;
+		subpriv->active = false;
+		retval = 1;
+	} else {
+		/* Determine interrupt sources to enable. */
+		isn_bits = 0;
+		if (cmd->chanlist) {
+			for (n = 0; n < cmd->chanlist_len; n++)
+				isn_bits |= (1U << CR_CHAN(cmd->chanlist[n]));
+		}
+		isn_bits &= subpriv->valid_isns;
+		/* Enable interrupt sources. */
+		subpriv->enabled_isns = isn_bits;
+		if (layout->has_int_sce)
+			dio200_write8(dev, subpriv->ofs, isn_bits);
+	}
+
+	return retval;
+}
+
+/*
+ * Internal trigger function to start acquisition for an 'INTERRUPT' subdevice.
+ */
+static int
+dio200_inttrig_start_intr(struct comedi_device *dev, struct comedi_subdevice *s,
+			  unsigned int trignum)
+{
+	struct dio200_subdev_intr *subpriv;
+	unsigned long flags;
+	int event = 0;
+
+	if (trignum != 0)
+		return -EINVAL;
+
+	subpriv = s->private;
+
+	spin_lock_irqsave(&subpriv->spinlock, flags);
+	s->async->inttrig = NULL;
+	if (subpriv->active)
+		event = dio200_start_intr(dev, s);
+
+	spin_unlock_irqrestore(&subpriv->spinlock, flags);
+
+	if (event)
+		comedi_event(dev, s);
+
+	return 1;
+}
+
+static void dio200_read_scan_intr(struct comedi_device *dev,
+				  struct comedi_subdevice *s,
+				  unsigned int triggered)
+{
+	struct dio200_subdev_intr *subpriv = s->private;
+	unsigned short val;
+	unsigned int n, ch, len;
+
+	val = 0;
+	len = s->async->cmd.chanlist_len;
+	for (n = 0; n < len; n++) {
+		ch = CR_CHAN(s->async->cmd.chanlist[n]);
+		if (triggered & (1U << ch))
+			val |= (1U << n);
+	}
+	/* Write the scan to the buffer. */
+	if (comedi_buf_put(s->async, val)) {
+		s->async->events |= (COMEDI_CB_BLOCK | COMEDI_CB_EOS);
+	} else {
+		/* Error!  Stop acquisition.  */
+		dio200_stop_intr(dev, s);
+		s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW;
+		comedi_error(dev, "buffer overflow");
+	}
+
+	/* Check for end of acquisition. */
+	if (!subpriv->continuous) {
+		/* stop_src == TRIG_COUNT */
+		if (subpriv->stopcount > 0) {
+			subpriv->stopcount--;
+			if (subpriv->stopcount == 0) {
+				s->async->events |= COMEDI_CB_EOA;
+				dio200_stop_intr(dev, s);
+			}
+		}
+	}
+}
+
+/*
+ * This is called from the interrupt service routine to handle a read
+ * scan on an 'INTERRUPT' subdevice.
+ */
+static int dio200_handle_read_intr(struct comedi_device *dev,
+				   struct comedi_subdevice *s)
+{
+	const struct dio200_layout *layout = dio200_dev_layout(dev);
+	struct dio200_subdev_intr *subpriv = s->private;
+	unsigned triggered;
+	unsigned intstat;
+	unsigned cur_enabled;
+	unsigned int oldevents;
+	unsigned long flags;
+
+	triggered = 0;
+
+	spin_lock_irqsave(&subpriv->spinlock, flags);
+	oldevents = s->async->events;
+	if (layout->has_int_sce) {
+		/*
+		 * Collect interrupt sources that have triggered and disable
+		 * them temporarily.  Loop around until no extra interrupt
+		 * sources have triggered, at which point, the valid part of
+		 * the interrupt status register will read zero, clearing the
+		 * cause of the interrupt.
+		 *
+		 * Mask off interrupt sources already seen to avoid infinite
+		 * loop in case of misconfiguration.
+		 */
+		cur_enabled = subpriv->enabled_isns;
+		while ((intstat = (dio200_read8(dev, subpriv->ofs) &
+				   subpriv->valid_isns & ~triggered)) != 0) {
+			triggered |= intstat;
+			cur_enabled &= ~triggered;
+			dio200_write8(dev, subpriv->ofs, cur_enabled);
+		}
+	} else {
+		/*
+		 * No interrupt status register.  Assume the single interrupt
+		 * source has triggered.
+		 */
+		triggered = subpriv->enabled_isns;
+	}
+
+	if (triggered) {
+		/*
+		 * Some interrupt sources have triggered and have been
+		 * temporarily disabled to clear the cause of the interrupt.
+		 *
+		 * Reenable them NOW to minimize the time they are disabled.
+		 */
+		cur_enabled = subpriv->enabled_isns;
+		if (layout->has_int_sce)
+			dio200_write8(dev, subpriv->ofs, cur_enabled);
+
+		if (subpriv->active) {
+			/*
+			 * The command is still active.
+			 *
+			 * Ignore interrupt sources that the command isn't
+			 * interested in (just in case there's a race
+			 * condition).
+			 */
+			if (triggered & subpriv->enabled_isns)
+				/* Collect scan data. */
+				dio200_read_scan_intr(dev, s, triggered);
+		}
+	}
+	spin_unlock_irqrestore(&subpriv->spinlock, flags);
+
+	if (oldevents != s->async->events)
+		comedi_event(dev, s);
+
+	return (triggered != 0);
+}
+
+/*
+ * 'cancel' function for an 'INTERRUPT' subdevice.
+ */
+static int dio200_subdev_intr_cancel(struct comedi_device *dev,
+				     struct comedi_subdevice *s)
+{
+	struct dio200_subdev_intr *subpriv = s->private;
+	unsigned long flags;
+
+	spin_lock_irqsave(&subpriv->spinlock, flags);
+	if (subpriv->active)
+		dio200_stop_intr(dev, s);
+
+	spin_unlock_irqrestore(&subpriv->spinlock, flags);
+
+	return 0;
+}
+
+/*
+ * 'do_cmdtest' function for an 'INTERRUPT' subdevice.
+ */
+static int
+dio200_subdev_intr_cmdtest(struct comedi_device *dev,
+			   struct comedi_subdevice *s, struct comedi_cmd *cmd)
+{
+	int err = 0;
+
+	/* Step 1 : check if triggers are trivially valid */
+
+	err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
+	err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT);
+	err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
+	err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+	err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
+
+	if (err)
+		return 1;
+
+	/* Step 2a : make sure trigger sources are unique */
+
+	err |= cfc_check_trigger_is_unique(cmd->start_src);
+	err |= cfc_check_trigger_is_unique(cmd->stop_src);
+
+	/* Step 2b : and mutually compatible */
+
+	if (err)
+		return 2;
+
+	/* Step 3: check if arguments are trivially valid */
+
+	err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+	err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
+	err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
+	err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+
+	switch (cmd->stop_src) {
+	case TRIG_COUNT:
+		/* any count allowed */
+		break;
+	case TRIG_NONE:
+		err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+		break;
+	default:
+		break;
+	}
+
+	if (err)
+		return 3;
+
+	/* step 4: fix up any arguments */
+
+	/* if (err) return 4; */
+
+	return 0;
+}
+
+/*
+ * 'do_cmd' function for an 'INTERRUPT' subdevice.
+ */
+static int dio200_subdev_intr_cmd(struct comedi_device *dev,
+				  struct comedi_subdevice *s)
+{
+	struct comedi_cmd *cmd = &s->async->cmd;
+	struct dio200_subdev_intr *subpriv = s->private;
+	unsigned long flags;
+	int event = 0;
+
+	spin_lock_irqsave(&subpriv->spinlock, flags);
+	subpriv->active = 1;
+
+	/* Set up end of acquisition. */
+	switch (cmd->stop_src) {
+	case TRIG_COUNT:
+		subpriv->continuous = false;
+		subpriv->stopcount = cmd->stop_arg;
+		break;
+	default:
+		/* TRIG_NONE */
+		subpriv->continuous = true;
+		subpriv->stopcount = 0;
+		break;
+	}
+
+	/* Set up start of acquisition. */
+	switch (cmd->start_src) {
+	case TRIG_INT:
+		s->async->inttrig = dio200_inttrig_start_intr;
+		break;
+	default:
+		/* TRIG_NOW */
+		event = dio200_start_intr(dev, s);
+		break;
+	}
+	spin_unlock_irqrestore(&subpriv->spinlock, flags);
+
+	if (event)
+		comedi_event(dev, s);
+
+	return 0;
+}
+
+/*
+ * This function initializes an 'INTERRUPT' subdevice.
+ */
+static int
+dio200_subdev_intr_init(struct comedi_device *dev, struct comedi_subdevice *s,
+			unsigned int offset, unsigned valid_isns)
+{
+	const struct dio200_layout *layout = dio200_dev_layout(dev);
+	struct dio200_subdev_intr *subpriv;
+
+	subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL);
+	if (!subpriv)
+		return -ENOMEM;
+
+	subpriv->ofs = offset;
+	subpriv->valid_isns = valid_isns;
+	spin_lock_init(&subpriv->spinlock);
+
+	if (layout->has_int_sce)
+		/* Disable interrupt sources. */
+		dio200_write8(dev, subpriv->ofs, 0);
+
+	s->private = subpriv;
+	s->type = COMEDI_SUBD_DI;
+	s->subdev_flags = SDF_READABLE | SDF_CMD_READ;
+	if (layout->has_int_sce) {
+		s->n_chan = DIO200_MAX_ISNS;
+		s->len_chanlist = DIO200_MAX_ISNS;
+	} else {
+		/* No interrupt source register.  Support single channel. */
+		s->n_chan = 1;
+		s->len_chanlist = 1;
+	}
+	s->range_table = &range_digital;
+	s->maxdata = 1;
+	s->insn_bits = dio200_subdev_intr_insn_bits;
+	s->do_cmdtest = dio200_subdev_intr_cmdtest;
+	s->do_cmd = dio200_subdev_intr_cmd;
+	s->cancel = dio200_subdev_intr_cancel;
+
+	return 0;
+}
+
+/*
+ * This function cleans up an 'INTERRUPT' subdevice.
+ */
+static void
+dio200_subdev_intr_cleanup(struct comedi_device *dev,
+			   struct comedi_subdevice *s)
+{
+	struct dio200_subdev_intr *subpriv = s->private;
+	kfree(subpriv);
+}
+
+/*
+ * Interrupt service routine.
+ */
+static irqreturn_t dio200_interrupt(int irq, void *d)
+{
+	struct comedi_device *dev = d;
+	struct dio200_private *devpriv = dev->private;
+	struct comedi_subdevice *s;
+	int handled;
+
+	if (!dev->attached)
+		return IRQ_NONE;
+
+	if (devpriv->intr_sd >= 0) {
+		s = &dev->subdevices[devpriv->intr_sd];
+		handled = dio200_handle_read_intr(dev, s);
+	} else {
+		handled = 0;
+	}
+
+	return IRQ_RETVAL(handled);
+}
+
+/*
+ * Read an '8254' counter subdevice channel.
+ */
+static unsigned int
+dio200_subdev_8254_read_chan(struct comedi_device *dev,
+			     struct comedi_subdevice *s, unsigned int chan)
+{
+	struct dio200_subdev_8254 *subpriv = s->private;
+	unsigned int val;
+
+	/* latch counter */
+	val = chan << 6;
+	dio200_write8(dev, subpriv->ofs + i8254_control_reg, val);
+	/* read lsb, msb */
+	val = dio200_read8(dev, subpriv->ofs + chan);
+	val += dio200_read8(dev, subpriv->ofs + chan) << 8;
+	return val;
+}
+
+/*
+ * Write an '8254' subdevice channel.
+ */
+static void
+dio200_subdev_8254_write_chan(struct comedi_device *dev,
+			      struct comedi_subdevice *s, unsigned int chan,
+			      unsigned int count)
+{
+	struct dio200_subdev_8254 *subpriv = s->private;
+
+	/* write lsb, msb */
+	dio200_write8(dev, subpriv->ofs + chan, count & 0xff);
+	dio200_write8(dev, subpriv->ofs + chan, (count >> 8) & 0xff);
+}
+
+/*
+ * Set mode of an '8254' subdevice channel.
+ */
+static void
+dio200_subdev_8254_set_mode(struct comedi_device *dev,
+			    struct comedi_subdevice *s, unsigned int chan,
+			    unsigned int mode)
+{
+	struct dio200_subdev_8254 *subpriv = s->private;
+	unsigned int byte;
+
+	byte = chan << 6;
+	byte |= 0x30;		/* access order: lsb, msb */
+	byte |= (mode & 0xf);	/* counter mode and BCD|binary */
+	dio200_write8(dev, subpriv->ofs + i8254_control_reg, byte);
+}
+
+/*
+ * Read status byte of an '8254' counter subdevice channel.
+ */
+static unsigned int
+dio200_subdev_8254_status(struct comedi_device *dev,
+			  struct comedi_subdevice *s, unsigned int chan)
+{
+	struct dio200_subdev_8254 *subpriv = s->private;
+
+	/* latch status */
+	dio200_write8(dev, subpriv->ofs + i8254_control_reg,
+		      0xe0 | (2 << chan));
+	/* read status */
+	return dio200_read8(dev, subpriv->ofs + chan);
+}
+
+/*
+ * Handle 'insn_read' for an '8254' counter subdevice.
+ */
+static int
+dio200_subdev_8254_read(struct comedi_device *dev, struct comedi_subdevice *s,
+			struct comedi_insn *insn, unsigned int *data)
+{
+	struct dio200_subdev_8254 *subpriv = s->private;
+	int chan = CR_CHAN(insn->chanspec);
+	unsigned int n;
+	unsigned long flags;
+
+	for (n = 0; n < insn->n; n++) {
+		spin_lock_irqsave(&subpriv->spinlock, flags);
+		data[n] = dio200_subdev_8254_read_chan(dev, s, chan);
+		spin_unlock_irqrestore(&subpriv->spinlock, flags);
+	}
+	return insn->n;
+}
+
+/*
+ * Handle 'insn_write' for an '8254' counter subdevice.
+ */
+static int
+dio200_subdev_8254_write(struct comedi_device *dev, struct comedi_subdevice *s,
+			 struct comedi_insn *insn, unsigned int *data)
+{
+	struct dio200_subdev_8254 *subpriv = s->private;
+	int chan = CR_CHAN(insn->chanspec);
+	unsigned int n;
+	unsigned long flags;
+
+	for (n = 0; n < insn->n; n++) {
+		spin_lock_irqsave(&subpriv->spinlock, flags);
+		dio200_subdev_8254_write_chan(dev, s, chan, data[n]);
+		spin_unlock_irqrestore(&subpriv->spinlock, flags);
+	}
+	return insn->n;
+}
+
+/*
+ * Set gate source for an '8254' counter subdevice channel.
+ */
+static int
+dio200_subdev_8254_set_gate_src(struct comedi_device *dev,
+				struct comedi_subdevice *s,
+				unsigned int counter_number,
+				unsigned int gate_src)
+{
+	const struct dio200_layout *layout = dio200_dev_layout(dev);
+	struct dio200_subdev_8254 *subpriv = s->private;
+	unsigned char byte;
+
+	if (!layout->has_clk_gat_sce)
+		return -1;
+	if (counter_number > 2)
+		return -1;
+	if (gate_src > (layout->has_enhancements ? 31 : 7))
+		return -1;
+
+	subpriv->gate_src[counter_number] = gate_src;
+	byte = gat_sce(subpriv->which, counter_number, gate_src);
+	dio200_write8(dev, subpriv->gat_sce_ofs, byte);
+
+	return 0;
+}
+
+/*
+ * Get gate source for an '8254' counter subdevice channel.
+ */
+static int
+dio200_subdev_8254_get_gate_src(struct comedi_device *dev,
+				struct comedi_subdevice *s,
+				unsigned int counter_number)
+{
+	const struct dio200_layout *layout = dio200_dev_layout(dev);
+	struct dio200_subdev_8254 *subpriv = s->private;
+
+	if (!layout->has_clk_gat_sce)
+		return -1;
+	if (counter_number > 2)
+		return -1;
+
+	return subpriv->gate_src[counter_number];
+}
+
+/*
+ * Set clock source for an '8254' counter subdevice channel.
+ */
+static int
+dio200_subdev_8254_set_clock_src(struct comedi_device *dev,
+				 struct comedi_subdevice *s,
+				 unsigned int counter_number,
+				 unsigned int clock_src)
+{
+	const struct dio200_layout *layout = dio200_dev_layout(dev);
+	struct dio200_subdev_8254 *subpriv = s->private;
+	unsigned char byte;
+
+	if (!layout->has_clk_gat_sce)
+		return -1;
+	if (counter_number > 2)
+		return -1;
+	if (clock_src > (layout->has_enhancements ? 31 : 7))
+		return -1;
+
+	subpriv->clock_src[counter_number] = clock_src;
+	byte = clk_sce(subpriv->which, counter_number, clock_src);
+	dio200_write8(dev, subpriv->clk_sce_ofs, byte);
+
+	return 0;
+}
+
+/*
+ * Get clock source for an '8254' counter subdevice channel.
+ */
+static int
+dio200_subdev_8254_get_clock_src(struct comedi_device *dev,
+				 struct comedi_subdevice *s,
+				 unsigned int counter_number,
+				 unsigned int *period_ns)
+{
+	const struct dio200_layout *layout = dio200_dev_layout(dev);
+	struct dio200_subdev_8254 *subpriv = s->private;
+	unsigned clock_src;
+
+	if (!layout->has_clk_gat_sce)
+		return -1;
+	if (counter_number > 2)
+		return -1;
+
+	clock_src = subpriv->clock_src[counter_number];
+	*period_ns = clock_period[clock_src];
+	return clock_src;
+}
+
+/*
+ * Handle 'insn_config' for an '8254' counter subdevice.
+ */
+static int
+dio200_subdev_8254_config(struct comedi_device *dev, struct comedi_subdevice *s,
+			  struct comedi_insn *insn, unsigned int *data)
+{
+	struct dio200_subdev_8254 *subpriv = s->private;
+	int ret = 0;
+	int chan = CR_CHAN(insn->chanspec);
+	unsigned long flags;
+
+	spin_lock_irqsave(&subpriv->spinlock, flags);
+	switch (data[0]) {
+	case INSN_CONFIG_SET_COUNTER_MODE:
+		if (data[1] > (I8254_MODE5 | I8254_BINARY))
+			ret = -EINVAL;
+		else
+			dio200_subdev_8254_set_mode(dev, s, chan, data[1]);
+		break;
+	case INSN_CONFIG_8254_READ_STATUS:
+		data[1] = dio200_subdev_8254_status(dev, s, chan);
+		break;
+	case INSN_CONFIG_SET_GATE_SRC:
+		ret = dio200_subdev_8254_set_gate_src(dev, s, chan, data[2]);
+		if (ret < 0)
+			ret = -EINVAL;
+		break;
+	case INSN_CONFIG_GET_GATE_SRC:
+		ret = dio200_subdev_8254_get_gate_src(dev, s, chan);
+		if (ret < 0) {
+			ret = -EINVAL;
+			break;
+		}
+		data[2] = ret;
+		break;
+	case INSN_CONFIG_SET_CLOCK_SRC:
+		ret = dio200_subdev_8254_set_clock_src(dev, s, chan, data[1]);
+		if (ret < 0)
+			ret = -EINVAL;
+		break;
+	case INSN_CONFIG_GET_CLOCK_SRC:
+		ret = dio200_subdev_8254_get_clock_src(dev, s, chan, &data[2]);
+		if (ret < 0) {
+			ret = -EINVAL;
+			break;
+		}
+		data[1] = ret;
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+	spin_unlock_irqrestore(&subpriv->spinlock, flags);
+	return ret < 0 ? ret : insn->n;
+}
+
+/*
+ * This function initializes an '8254' counter subdevice.
+ */
+static int
+dio200_subdev_8254_init(struct comedi_device *dev, struct comedi_subdevice *s,
+			unsigned int offset)
+{
+	const struct dio200_layout *layout = dio200_dev_layout(dev);
+	struct dio200_subdev_8254 *subpriv;
+	unsigned int chan;
+
+	subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL);
+	if (!subpriv)
+		return -ENOMEM;
+
+	s->private = subpriv;
+	s->type = COMEDI_SUBD_COUNTER;
+	s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
+	s->n_chan = 3;
+	s->maxdata = 0xFFFF;
+	s->insn_read = dio200_subdev_8254_read;
+	s->insn_write = dio200_subdev_8254_write;
+	s->insn_config = dio200_subdev_8254_config;
+
+	spin_lock_init(&subpriv->spinlock);
+	subpriv->ofs = offset;
+	if (layout->has_clk_gat_sce) {
+		/* Derive CLK_SCE and GAT_SCE register offsets from
+		 * 8254 offset. */
+		subpriv->clk_sce_ofs = DIO200_XCLK_SCE + (offset >> 3);
+		subpriv->gat_sce_ofs = DIO200_XGAT_SCE + (offset >> 3);
+		subpriv->which = (offset >> 2) & 1;
+	}
+
+	/* Initialize channels. */
+	for (chan = 0; chan < 3; chan++) {
+		dio200_subdev_8254_set_mode(dev, s, chan,
+					    I8254_MODE0 | I8254_BINARY);
+		if (layout->has_clk_gat_sce) {
+			/* Gate source 0 is VCC (logic 1). */
+			dio200_subdev_8254_set_gate_src(dev, s, chan, 0);
+			/* Clock source 0 is the dedicated clock input. */
+			dio200_subdev_8254_set_clock_src(dev, s, chan, 0);
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * This function cleans up an '8254' counter subdevice.
+ */
+static void
+dio200_subdev_8254_cleanup(struct comedi_device *dev,
+			   struct comedi_subdevice *s)
+{
+	struct dio200_subdev_intr *subpriv = s->private;
+	kfree(subpriv);
+}
+
+/*
+ * This function sets I/O directions for an '8255' DIO subdevice.
+ */
+static void dio200_subdev_8255_set_dir(struct comedi_device *dev,
+				       struct comedi_subdevice *s)
+{
+	struct dio200_subdev_8255 *subpriv = s->private;
+	int config;
+
+	config = CR_CW;
+	/* 1 in io_bits indicates output, 1 in config indicates input */
+	if (!(s->io_bits & 0x0000ff))
+		config |= CR_A_IO;
+	if (!(s->io_bits & 0x00ff00))
+		config |= CR_B_IO;
+	if (!(s->io_bits & 0x0f0000))
+		config |= CR_C_LO_IO;
+	if (!(s->io_bits & 0xf00000))
+		config |= CR_C_HI_IO;
+	dio200_write8(dev, subpriv->ofs + 3, config);
+}
+
+/*
+ * Handle 'insn_bits' for an '8255' DIO subdevice.
+ */
+static int dio200_subdev_8255_bits(struct comedi_device *dev,
+				   struct comedi_subdevice *s,
+				   struct comedi_insn *insn, unsigned int *data)
+{
+	struct dio200_subdev_8255 *subpriv = s->private;
+
+	if (data[0]) {
+		s->state &= ~data[0];
+		s->state |= (data[0] & data[1]);
+		if (data[0] & 0xff)
+			dio200_write8(dev, subpriv->ofs, s->state & 0xff);
+		if (data[0] & 0xff00)
+			dio200_write8(dev, subpriv->ofs + 1,
+				      (s->state >> 8) & 0xff);
+		if (data[0] & 0xff0000)
+			dio200_write8(dev, subpriv->ofs + 2,
+				      (s->state >> 16) & 0xff);
+	}
+	data[1] = dio200_read8(dev, subpriv->ofs);
+	data[1] |= dio200_read8(dev, subpriv->ofs + 1) << 8;
+	data[1] |= dio200_read8(dev, subpriv->ofs + 2) << 16;
+	return 2;
+}
+
+/*
+ * Handle 'insn_config' for an '8255' DIO subdevice.
+ */
+static int dio200_subdev_8255_config(struct comedi_device *dev,
+				     struct comedi_subdevice *s,
+				     struct comedi_insn *insn,
+				     unsigned int *data)
+{
+	unsigned int mask;
+	unsigned int bits;
+
+	mask = 1 << CR_CHAN(insn->chanspec);
+	if (mask & 0x0000ff)
+		bits = 0x0000ff;
+	else if (mask & 0x00ff00)
+		bits = 0x00ff00;
+	else if (mask & 0x0f0000)
+		bits = 0x0f0000;
+	else
+		bits = 0xf00000;
+	switch (data[0]) {
+	case INSN_CONFIG_DIO_INPUT:
+		s->io_bits &= ~bits;
+		break;
+	case INSN_CONFIG_DIO_OUTPUT:
+		s->io_bits |= bits;
+		break;
+	case INSN_CONFIG_DIO_QUERY:
+		data[1] = (s->io_bits & bits) ? COMEDI_OUTPUT : COMEDI_INPUT;
+		return insn->n;
+		break;
+	default:
+		return -EINVAL;
+	}
+	dio200_subdev_8255_set_dir(dev, s);
+	return 1;
+}
+
+/*
+ * This function initializes an '8255' DIO subdevice.
+ *
+ * offset is the offset to the 8255 chip.
+ */
+static int dio200_subdev_8255_init(struct comedi_device *dev,
+				   struct comedi_subdevice *s,
+				   unsigned int offset)
+{
+	struct dio200_subdev_8255 *subpriv;
+
+	subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL);
+	if (!subpriv)
+		return -ENOMEM;
+	subpriv->ofs = offset;
+	s->private = subpriv;
+	s->type = COMEDI_SUBD_DIO;
+	s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
+	s->n_chan = 24;
+	s->range_table = &range_digital;
+	s->maxdata = 1;
+	s->insn_bits = dio200_subdev_8255_bits;
+	s->insn_config = dio200_subdev_8255_config;
+	s->state = 0;
+	s->io_bits = 0;
+	dio200_subdev_8255_set_dir(dev, s);
+	return 0;
+}
+
+/*
+ * This function cleans up an '8255' DIO subdevice.
+ */
+static void dio200_subdev_8255_cleanup(struct comedi_device *dev,
+				       struct comedi_subdevice *s)
+{
+	struct dio200_subdev_8255 *subpriv = s->private;
+
+	kfree(subpriv);
+}
+
+/*
+ * Handle 'insn_read' for a timer subdevice.
+ */
+static int dio200_subdev_timer_read(struct comedi_device *dev,
+				    struct comedi_subdevice *s,
+				    struct comedi_insn *insn,
+				    unsigned int *data)
+{
+	unsigned int n;
+
+	for (n = 0; n < insn->n; n++)
+		data[n] = dio200_read32(dev, DIO200_TS_COUNT);
+	return n;
+}
+
+/*
+ * Reset timer subdevice.
+ */
+static void dio200_subdev_timer_reset(struct comedi_device *dev,
+				      struct comedi_subdevice *s)
+{
+	unsigned int clock;
+
+	clock = dio200_read32(dev, DIO200_TS_CONFIG) & TS_CONFIG_CLK_SRC_MASK;
+	dio200_write32(dev, DIO200_TS_CONFIG, clock | TS_CONFIG_RESET);
+	dio200_write32(dev, DIO200_TS_CONFIG, clock);
+}
+
+/*
+ * Get timer subdevice clock source and period.
+ */
+static void dio200_subdev_timer_get_clock_src(struct comedi_device *dev,
+					      struct comedi_subdevice *s,
+					      unsigned int *src,
+					      unsigned int *period)
+{
+	unsigned int clk;
+
+	clk = dio200_read32(dev, DIO200_TS_CONFIG) & TS_CONFIG_CLK_SRC_MASK;
+	*src = clk;
+	*period = (clk < ARRAY_SIZE(ts_clock_period)) ?
+		  ts_clock_period[clk] : 0;
+}
+
+/*
+ * Set timer subdevice clock source.
+ */
+static int dio200_subdev_timer_set_clock_src(struct comedi_device *dev,
+					     struct comedi_subdevice *s,
+					     unsigned int src)
+{
+	if (src > TS_CONFIG_MAX_CLK_SRC)
+		return -EINVAL;
+	dio200_write32(dev, DIO200_TS_CONFIG, src);
+	return 0;
+}
+
+/*
+ * Handle 'insn_config' for a timer subdevice.
+ */
+static int dio200_subdev_timer_config(struct comedi_device *dev,
+				      struct comedi_subdevice *s,
+				      struct comedi_insn *insn,
+				      unsigned int *data)
+{
+	int ret = 0;
+
+	switch (data[0]) {
+	case INSN_CONFIG_RESET:
+		dio200_subdev_timer_reset(dev, s);
+		break;
+	case INSN_CONFIG_SET_CLOCK_SRC:
+		ret = dio200_subdev_timer_set_clock_src(dev, s, data[1]);
+		if (ret < 0)
+			ret = -EINVAL;
+		break;
+	case INSN_CONFIG_GET_CLOCK_SRC:
+		dio200_subdev_timer_get_clock_src(dev, s, &data[1], &data[2]);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+	return ret < 0 ? ret : insn->n;
+}
+
+/*
+ * This function initializes a timer subdevice.
+ *
+ * Uses the timestamp timer registers.  There is only one timestamp timer.
+ */
+static int dio200_subdev_timer_init(struct comedi_device *dev,
+				    struct comedi_subdevice *s)
+{
+	s->type = COMEDI_SUBD_TIMER;
+	s->subdev_flags = SDF_READABLE | SDF_LSAMPL;
+	s->n_chan = 1;
+	s->maxdata = 0xFFFFFFFF;
+	s->insn_read = dio200_subdev_timer_read;
+	s->insn_config = dio200_subdev_timer_config;
+	return 0;
+}
+
+/*
+ * This function cleans up a timer subdevice.
+ */
+static void dio200_subdev_timer_cleanup(struct comedi_device *dev,
+					struct comedi_subdevice *s)
+{
+	/* Nothing to do. */
+}
+
+void amplc_dio200_set_enhance(struct comedi_device *dev, unsigned char val)
+{
+	dio200_write8(dev, DIO200_ENHANCE, val);
+}
+EXPORT_SYMBOL_GPL(amplc_dio200_set_enhance);
+
+int amplc_dio200_common_attach(struct comedi_device *dev, unsigned int irq,
+			       unsigned long req_irq_flags)
+{
+	const struct dio200_board *thisboard = comedi_board(dev);
+	struct dio200_private *devpriv = dev->private;
+	const struct dio200_layout *layout = dio200_board_layout(thisboard);
+	struct comedi_subdevice *s;
+	int sdx;
+	unsigned int n;
+	int ret;
+
+	devpriv->intr_sd = -1;
+
+	ret = comedi_alloc_subdevices(dev, layout->n_subdevs);
+	if (ret)
+		return ret;
+
+	for (n = 0; n < dev->n_subdevices; n++) {
+		s = &dev->subdevices[n];
+		switch (layout->sdtype[n]) {
+		case sd_8254:
+			/* counter subdevice (8254) */
+			ret = dio200_subdev_8254_init(dev, s,
+						      layout->sdinfo[n]);
+			if (ret < 0)
+				return ret;
+			break;
+		case sd_8255:
+			/* digital i/o subdevice (8255) */
+			ret = dio200_subdev_8255_init(dev, s,
+						      layout->sdinfo[n]);
+			if (ret < 0)
+				return ret;
+			break;
+		case sd_intr:
+			/* 'INTERRUPT' subdevice */
+			if (irq) {
+				ret = dio200_subdev_intr_init(dev, s,
+							      DIO200_INT_SCE,
+							      layout->sdinfo[n]
+							     );
+				if (ret < 0)
+					return ret;
+				devpriv->intr_sd = n;
+			} else {
+				s->type = COMEDI_SUBD_UNUSED;
+			}
+			break;
+		case sd_timer:
+			ret = dio200_subdev_timer_init(dev, s);
+			if (ret < 0)
+				return ret;
+			break;
+		default:
+			s->type = COMEDI_SUBD_UNUSED;
+			break;
+		}
+	}
+	sdx = devpriv->intr_sd;
+	if (sdx >= 0 && sdx < dev->n_subdevices)
+		dev->read_subdev = &dev->subdevices[sdx];
+	if (irq) {
+		if (request_irq(irq, dio200_interrupt, req_irq_flags,
+				dev->board_name, dev) >= 0) {
+			dev->irq = irq;
+		} else {
+			dev_warn(dev->class_dev,
+				 "warning! irq %u unavailable!\n", irq);
+		}
+	}
+	dev_info(dev->class_dev, "attached\n");
+	return 0;
+}
+EXPORT_SYMBOL_GPL(amplc_dio200_common_attach);
+
+void amplc_dio200_common_detach(struct comedi_device *dev)
+{
+	const struct dio200_board *thisboard = comedi_board(dev);
+	struct dio200_private *devpriv = dev->private;
+	const struct dio200_layout *layout;
+	unsigned n;
+
+	if (!thisboard || !devpriv)
+		return;
+	if (dev->irq)
+		free_irq(dev->irq, dev);
+	if (dev->subdevices) {
+		layout = dio200_board_layout(thisboard);
+		for (n = 0; n < dev->n_subdevices; n++) {
+			struct comedi_subdevice *s = &dev->subdevices[n];
+			switch (layout->sdtype[n]) {
+			case sd_8254:
+				dio200_subdev_8254_cleanup(dev, s);
+				break;
+			case sd_8255:
+				dio200_subdev_8255_cleanup(dev, s);
+				break;
+			case sd_intr:
+				dio200_subdev_intr_cleanup(dev, s);
+				break;
+			case sd_timer:
+				dio200_subdev_timer_cleanup(dev, s);
+				break;
+			default:
+				break;
+			}
+		}
+	}
+}
+EXPORT_SYMBOL_GPL(amplc_dio200_common_detach);
+
+static int __init amplc_dio200_common_init(void)
+{
+	return 0;
+}
+module_init(amplc_dio200_common_init);
+
+static void __exit amplc_dio200_common_exit(void)
+{
+}
+module_exit(amplc_dio200_common_exit);
+
+MODULE_AUTHOR("Comedi http://www.comedi.org");
+MODULE_DESCRIPTION("Comedi helper for amplc_dio200 and amplc_dio200_pci");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/amplc_dio200_pci.c b/drivers/staging/comedi/drivers/amplc_dio200_pci.c
new file mode 100644
index 0000000..232620c
--- /dev/null
+++ b/drivers/staging/comedi/drivers/amplc_dio200_pci.c
@@ -0,0 +1,492 @@
+/* comedi/drivers/amplc_dio200_pci.c
+
+    Driver for Amplicon PCI215, PCI272, PCIe215, PCIe236, PCIe296.
+
+    Copyright (C) 2005-2013 MEV Ltd. <http://www.mev.co.uk/>
+
+    COMEDI - Linux Control and Measurement Device Interface
+    Copyright (C) 1998,2000 David A. Schleef <ds@schleef.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.
+
+*/
+/*
+ * Driver: amplc_dio200_pci
+ * Description: Amplicon 200 Series PCI Digital I/O
+ * Author: Ian Abbott <abbotti@mev.co.uk>
+ * Devices: [Amplicon] PCI215 (amplc_dio200_pci), PCIe215, PCIe236,
+ *   PCI272, PCIe296
+ * Updated: Mon, 18 Mar 2013 15:03:50 +0000
+ * Status: works
+ *
+ * Configuration options:
+ *   none
+ *
+ * Manual configuration of PCI(e) cards is not supported; they are configured
+ * automatically.
+ *
+ * SUBDEVICES
+ *
+ *                     PCI215         PCIe215        PCIe236
+ *                  -------------  -------------  -------------
+ *   Subdevices           5              8              8
+ *    0                 PPI-X          PPI-X          PPI-X
+ *    1                 PPI-Y          UNUSED         UNUSED
+ *    2                 CTR-Z1         PPI-Y          UNUSED
+ *    3                 CTR-Z2         UNUSED         UNUSED
+ *    4               INTERRUPT        CTR-Z1         CTR-Z1
+ *    5                                CTR-Z2         CTR-Z2
+ *    6                                TIMER          TIMER
+ *    7                              INTERRUPT      INTERRUPT
+ *
+ *
+ *                     PCI272         PCIe296
+ *                  -------------  -------------
+ *   Subdevices           4              8
+ *    0                 PPI-X          PPI-X1
+ *    1                 PPI-Y          PPI-X2
+ *    2                 PPI-Z          PPI-Y1
+ *    3               INTERRUPT        PPI-Y2
+ *    4                                CTR-Z1
+ *    5                                CTR-Z2
+ *    6                                TIMER
+ *    7                              INTERRUPT
+ *
+ * Each PPI is a 8255 chip providing 24 DIO channels.  The DIO channels
+ * are configurable as inputs or outputs in four groups:
+ *
+ *   Port A  - channels  0 to  7
+ *   Port B  - channels  8 to 15
+ *   Port CL - channels 16 to 19
+ *   Port CH - channels 20 to 23
+ *
+ * Only mode 0 of the 8255 chips is supported.
+ *
+ * Each CTR is a 8254 chip providing 3 16-bit counter channels.  Each
+ * channel is configured individually with INSN_CONFIG instructions.  The
+ * specific type of configuration instruction is specified in data[0].
+ * Some configuration instructions expect an additional parameter in
+ * data[1]; others return a value in data[1].  The following configuration
+ * instructions are supported:
+ *
+ *   INSN_CONFIG_SET_COUNTER_MODE.  Sets the counter channel's mode and
+ *     BCD/binary setting specified in data[1].
+ *
+ *   INSN_CONFIG_8254_READ_STATUS.  Reads the status register value for the
+ *     counter channel into data[1].
+ *
+ *   INSN_CONFIG_SET_CLOCK_SRC.  Sets the counter channel's clock source as
+ *     specified in data[1] (this is a hardware-specific value).  Not
+ *     supported on PC214E.  For the other boards, valid clock sources are
+ *     0 to 7 as follows:
+ *
+ *       0.  CLK n, the counter channel's dedicated CLK input from the SK1
+ *         connector.  (N.B. for other values, the counter channel's CLKn
+ *         pin on the SK1 connector is an output!)
+ *       1.  Internal 10 MHz clock.
+ *       2.  Internal 1 MHz clock.
+ *       3.  Internal 100 kHz clock.
+ *       4.  Internal 10 kHz clock.
+ *       5.  Internal 1 kHz clock.
+ *       6.  OUT n-1, the output of counter channel n-1 (see note 1 below).
+ *       7.  Ext Clock, the counter chip's dedicated Ext Clock input from
+ *         the SK1 connector.  This pin is shared by all three counter
+ *         channels on the chip.
+ *
+ *     For the PCIe boards, clock sources in the range 0 to 31 are allowed
+ *     and the following additional clock sources are defined:
+ *
+ *       8.  HIGH logic level.
+ *       9.  LOW logic level.
+ *      10.  "Pattern present" signal.
+ *      11.  Internal 20 MHz clock.
+ *
+ *   INSN_CONFIG_GET_CLOCK_SRC.  Returns the counter channel's current
+ *     clock source in data[1].  For internal clock sources, data[2] is set
+ *     to the period in ns.
+ *
+ *   INSN_CONFIG_SET_GATE_SRC.  Sets the counter channel's gate source as
+ *     specified in data[2] (this is a hardware-specific value).  Not
+ *     supported on PC214E.  For the other boards, valid gate sources are 0
+ *     to 7 as follows:
+ *
+ *       0.  VCC (internal +5V d.c.), i.e. gate permanently enabled.
+ *       1.  GND (internal 0V d.c.), i.e. gate permanently disabled.
+ *       2.  GAT n, the counter channel's dedicated GAT input from the SK1
+ *         connector.  (N.B. for other values, the counter channel's GATn
+ *         pin on the SK1 connector is an output!)
+ *       3.  /OUT n-2, the inverted output of counter channel n-2 (see note
+ *         2 below).
+ *       4.  Reserved.
+ *       5.  Reserved.
+ *       6.  Reserved.
+ *       7.  Reserved.
+ *
+ *     For the PCIe boards, gate sources in the range 0 to 31 are allowed;
+ *     the following additional clock sources and clock sources 6 and 7 are
+ *     (re)defined:
+ *
+ *       6.  /GAT n, negated version of the counter channel's dedicated
+ *         GAT input (negated version of gate source 2).
+ *       7.  OUT n-2, the non-inverted output of counter channel n-2
+ *         (negated version of gate source 3).
+ *       8.  "Pattern present" signal, HIGH while pattern present.
+ *       9.  "Pattern occurred" latched signal, latches HIGH when pattern
+ *         occurs.
+ *      10.  "Pattern gone away" latched signal, latches LOW when pattern
+ *         goes away after it occurred.
+ *      11.  Negated "pattern present" signal, LOW while pattern present
+ *         (negated version of gate source 8).
+ *      12.  Negated "pattern occurred" latched signal, latches LOW when
+ *         pattern occurs (negated version of gate source 9).
+ *      13.  Negated "pattern gone away" latched signal, latches LOW when
+ *         pattern goes away after it occurred (negated version of gate
+ *         source 10).
+ *
+ *   INSN_CONFIG_GET_GATE_SRC.  Returns the counter channel's current gate
+ *     source in data[2].
+ *
+ * Clock and gate interconnection notes:
+ *
+ *   1.  Clock source OUT n-1 is the output of the preceding channel on the
+ *   same counter subdevice if n > 0, or the output of channel 2 on the
+ *   preceding counter subdevice (see note 3) if n = 0.
+ *
+ *   2.  Gate source /OUT n-2 is the inverted output of channel 0 on the
+ *   same counter subdevice if n = 2, or the inverted output of channel n+1
+ *   on the preceding counter subdevice (see note 3) if n < 2.
+ *
+ *   3.  The counter subdevices are connected in a ring, so the highest
+ *   counter subdevice precedes the lowest.
+ *
+ * The 'TIMER' subdevice is a free-running 32-bit timer subdevice.
+ *
+ * The 'INTERRUPT' subdevice pretends to be a digital input subdevice.  The
+ * digital inputs come from the interrupt status register.  The number of
+ * channels matches the number of interrupt sources.  The PC214E does not
+ * have an interrupt status register; see notes on 'INTERRUPT SOURCES'
+ * below.
+ *
+ * INTERRUPT SOURCES
+ *
+ *                     PCI215         PCIe215        PCIe236
+ *                  -------------  -------------  -------------
+ *   Sources              6              6              6
+ *    0               PPI-X-C0       PPI-X-C0       PPI-X-C0
+ *    1               PPI-X-C3       PPI-X-C3       PPI-X-C3
+ *    2               PPI-Y-C0       PPI-Y-C0        unused
+ *    3               PPI-Y-C3       PPI-Y-C3        unused
+ *    4              CTR-Z1-OUT1    CTR-Z1-OUT1    CTR-Z1-OUT1
+ *    5              CTR-Z2-OUT1    CTR-Z2-OUT1    CTR-Z2-OUT1
+ *
+ *                     PCI272         PCIe296
+ *                  -------------  -------------
+ *   Sources              6              6
+ *    0               PPI-X-C0       PPI-X1-C0
+ *    1               PPI-X-C3       PPI-X1-C3
+ *    2               PPI-Y-C0       PPI-Y1-C0
+ *    3               PPI-Y-C3       PPI-Y1-C3
+ *    4               PPI-Z-C0      CTR-Z1-OUT1
+ *    5               PPI-Z-C3      CTR-Z2-OUT1
+ *
+ * When an interrupt source is enabled in the interrupt source enable
+ * register, a rising edge on the source signal latches the corresponding
+ * bit to 1 in the interrupt status register.
+ *
+ * When the interrupt status register value as a whole (actually, just the
+ * 6 least significant bits) goes from zero to non-zero, the board will
+ * generate an interrupt.  The interrupt will remain asserted until the
+ * interrupt status register is cleared to zero.  To clear a bit to zero in
+ * the interrupt status register, the corresponding interrupt source must
+ * be disabled in the interrupt source enable register (there is no
+ * separate interrupt clear register).
+ *
+ * COMMANDS
+ *
+ * The driver supports a read streaming acquisition command on the
+ * 'INTERRUPT' subdevice.  The channel list selects the interrupt sources
+ * to be enabled.  All channels will be sampled together (convert_src ==
+ * TRIG_NOW).  The scan begins a short time after the hardware interrupt
+ * occurs, subject to interrupt latencies (scan_begin_src == TRIG_EXT,
+ * scan_begin_arg == 0).  The value read from the interrupt status register
+ * is packed into a short value, one bit per requested channel, in the
+ * order they appear in the channel list.
+ */
+
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+
+#include "../comedidev.h"
+
+#include "amplc_dio200.h"
+
+/* PCI IDs */
+#define PCI_DEVICE_ID_AMPLICON_PCI272 0x000a
+#define PCI_DEVICE_ID_AMPLICON_PCI215 0x000b
+#define PCI_DEVICE_ID_AMPLICON_PCIE236 0x0011
+#define PCI_DEVICE_ID_AMPLICON_PCIE215 0x0012
+#define PCI_DEVICE_ID_AMPLICON_PCIE296 0x0014
+
+/*
+ * Board descriptions.
+ */
+
+enum dio200_pci_model {
+	pci215_model,
+	pci272_model,
+	pcie215_model,
+	pcie236_model,
+	pcie296_model
+};
+
+static const struct dio200_board dio200_pci_boards[] = {
+	[pci215_model] = {
+		.name = "pci215",
+		.bustype = pci_bustype,
+		.mainbar = 2,
+		.mainsize = DIO200_IO_SIZE,
+		.layout = {
+			.n_subdevs = 5,
+			.sdtype = {sd_8255, sd_8255, sd_8254, sd_8254, sd_intr},
+			.sdinfo = {0x00, 0x08, 0x10, 0x14, 0x3F},
+			.has_int_sce = true,
+			.has_clk_gat_sce = true,
+		},
+	},
+	[pci272_model] = {
+		.name = "pci272",
+		.bustype = pci_bustype,
+		.mainbar = 2,
+		.mainsize = DIO200_IO_SIZE,
+		.layout = {
+			.n_subdevs = 4,
+			.sdtype = {sd_8255, sd_8255, sd_8255, sd_intr},
+			.sdinfo = {0x00, 0x08, 0x10, 0x3F},
+			.has_int_sce = true,
+		},
+	},
+	[pcie215_model] = {
+		.name = "pcie215",
+		.bustype = pci_bustype,
+		.mainbar = 1,
+		.mainshift = 3,
+		.mainsize = DIO200_PCIE_IO_SIZE,
+		.layout = {
+			.n_subdevs = 8,
+			.sdtype = {sd_8255, sd_none, sd_8255, sd_none,
+				   sd_8254, sd_8254, sd_timer, sd_intr},
+			.sdinfo = {0x00, 0x00, 0x08, 0x00,
+				   0x10, 0x14, 0x00, 0x3F},
+			.has_int_sce = true,
+			.has_clk_gat_sce = true,
+			.has_enhancements = true,
+		},
+	},
+	[pcie236_model] = {
+		.name = "pcie236",
+		.bustype = pci_bustype,
+		.mainbar = 1,
+		.mainshift = 3,
+		.mainsize = DIO200_PCIE_IO_SIZE,
+		.layout = {
+			.n_subdevs = 8,
+			.sdtype = {sd_8255, sd_none, sd_none, sd_none,
+				   sd_8254, sd_8254, sd_timer, sd_intr},
+			.sdinfo = {0x00, 0x00, 0x00, 0x00,
+				   0x10, 0x14, 0x00, 0x3F},
+			.has_int_sce = true,
+			.has_clk_gat_sce = true,
+			.has_enhancements = true,
+		},
+	},
+	[pcie296_model] = {
+		.name = "pcie296",
+		.bustype = pci_bustype,
+		.mainbar = 1,
+		.mainshift = 3,
+		.mainsize = DIO200_PCIE_IO_SIZE,
+		.layout = {
+			.n_subdevs = 8,
+			.sdtype = {sd_8255, sd_8255, sd_8255, sd_8255,
+				   sd_8254, sd_8254, sd_timer, sd_intr},
+			.sdinfo = {0x00, 0x04, 0x08, 0x0C,
+				   0x10, 0x14, 0x00, 0x3F},
+			.has_int_sce = true,
+			.has_clk_gat_sce = true,
+			.has_enhancements = true,
+		},
+	},
+};
+
+/*
+ * This function does some special set-up for the PCIe boards
+ * PCIe215, PCIe236, PCIe296.
+ */
+static int dio200_pcie_board_setup(struct comedi_device *dev)
+{
+	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+	void __iomem *brbase;
+	resource_size_t brlen;
+
+	/*
+	 * The board uses Altera Cyclone IV with PCI-Express hard IP.
+	 * The FPGA configuration has the PCI-Express Avalon-MM Bridge
+	 * Control registers in PCI BAR 0, offset 0, and the length of
+	 * these registers is 0x4000.
+	 *
+	 * We need to write 0x80 to the "Avalon-MM to PCI-Express Interrupt
+	 * Enable" register at offset 0x50 to allow generation of PCIe
+	 * interrupts when RXmlrq_i is asserted in the SOPC Builder system.
+	 */
+	brlen = pci_resource_len(pcidev, 0);
+	if (brlen < 0x4000 ||
+			!(pci_resource_flags(pcidev, 0) & IORESOURCE_MEM)) {
+		dev_err(dev->class_dev, "error! bad PCI region!\n");
+		return -EINVAL;
+	}
+	brbase = ioremap_nocache(pci_resource_start(pcidev, 0), brlen);
+	if (!brbase) {
+		dev_err(dev->class_dev, "error! failed to map registers!\n");
+		return -ENOMEM;
+	}
+	writel(0x80, brbase + 0x50);
+	iounmap(brbase);
+	/* Enable "enhanced" features of board. */
+	amplc_dio200_set_enhance(dev, 1);
+	return 0;
+}
+
+static int dio200_pci_auto_attach(struct comedi_device *dev,
+				  unsigned long context_model)
+{
+	struct pci_dev *pci_dev = comedi_to_pci_dev(dev);
+	const struct dio200_board *thisboard = NULL;
+	struct dio200_private *devpriv;
+	resource_size_t base, len;
+	unsigned int bar;
+	int ret;
+
+	if (context_model < ARRAY_SIZE(dio200_pci_boards))
+		thisboard = &dio200_pci_boards[context_model];
+	if (!thisboard)
+		return -EINVAL;
+	dev->board_ptr = thisboard;
+	dev->board_name = thisboard->name;
+
+	dev_info(dev->class_dev, "%s: attach pci %s (%s)\n",
+		 dev->driver->driver_name, pci_name(pci_dev), dev->board_name);
+
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
+
+	ret = comedi_pci_enable(dev);
+	if (ret)
+		return ret;
+
+	bar = thisboard->mainbar;
+	base = pci_resource_start(pci_dev, bar);
+	len = pci_resource_len(pci_dev, bar);
+	if (len < thisboard->mainsize) {
+		dev_err(dev->class_dev, "error! PCI region size too small!\n");
+		return -EINVAL;
+	}
+	if (pci_resource_flags(pci_dev, bar) & IORESOURCE_MEM) {
+		devpriv->io.u.membase = ioremap_nocache(base, len);
+		if (!devpriv->io.u.membase) {
+			dev_err(dev->class_dev,
+				"error! cannot remap registers\n");
+			return -ENOMEM;
+		}
+		devpriv->io.regtype = mmio_regtype;
+	} else {
+		devpriv->io.u.iobase = (unsigned long)base;
+		devpriv->io.regtype = io_regtype;
+	}
+	switch (context_model) {
+	case pcie215_model:
+	case pcie236_model:
+	case pcie296_model:
+		ret = dio200_pcie_board_setup(dev);
+		if (ret < 0)
+			return ret;
+		break;
+	default:
+		break;
+	}
+	return amplc_dio200_common_attach(dev, pci_dev->irq, IRQF_SHARED);
+}
+
+static void dio200_pci_detach(struct comedi_device *dev)
+{
+	const struct dio200_board *thisboard = comedi_board(dev);
+	struct dio200_private *devpriv = dev->private;
+
+	if (!thisboard || !devpriv)
+		return;
+	amplc_dio200_common_detach(dev);
+	if (devpriv->io.regtype == mmio_regtype)
+		iounmap(devpriv->io.u.membase);
+	comedi_pci_disable(dev);
+}
+
+static struct comedi_driver dio200_pci_comedi_driver = {
+	.driver_name = "amplc_dio200_pci",
+	.module = THIS_MODULE,
+	.auto_attach = dio200_pci_auto_attach,
+	.detach = dio200_pci_detach,
+};
+
+static DEFINE_PCI_DEVICE_TABLE(dio200_pci_table) = {
+	{
+		PCI_VDEVICE(AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI215),
+		pci215_model
+	}, {
+		PCI_VDEVICE(AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI272),
+		pci272_model
+	}, {
+		PCI_VDEVICE(AMPLICON, PCI_DEVICE_ID_AMPLICON_PCIE236),
+		pcie236_model
+	}, {
+		PCI_VDEVICE(AMPLICON, PCI_DEVICE_ID_AMPLICON_PCIE215),
+		pcie215_model
+	}, {
+		PCI_VDEVICE(AMPLICON, PCI_DEVICE_ID_AMPLICON_PCIE296),
+		pcie296_model
+	},
+	{0}
+};
+
+MODULE_DEVICE_TABLE(pci, dio200_pci_table);
+
+static int dio200_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+	return comedi_pci_auto_config(dev, &dio200_pci_comedi_driver,
+				      id->driver_data);
+}
+
+static struct pci_driver dio200_pci_pci_driver = {
+	.name = "amplc_dio200_pci",
+	.id_table = dio200_pci_table,
+	.probe = dio200_pci_probe,
+	.remove	= comedi_pci_auto_unconfig,
+};
+module_comedi_pci_driver(dio200_pci_comedi_driver, dio200_pci_pci_driver);
+
+MODULE_AUTHOR("Comedi http://www.comedi.org");
+MODULE_DESCRIPTION("Comedi driver for Amplicon 200 Series PCI(e) DIO boards");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c
index 479e10f..4507f92 100644
--- a/drivers/staging/comedi/drivers/amplc_pc236.c
+++ b/drivers/staging/comedi/drivers/amplc_pc236.c
@@ -470,12 +470,10 @@ static int pc236_pci_common_attach(struct comedi_device *dev,
 
 	comedi_set_hw_dev(dev, &pci_dev->dev);
 
-	ret = comedi_pci_enable(pci_dev, PC236_DRIVER_NAME);
-	if (ret < 0) {
-		dev_err(dev->class_dev,
-			"error! cannot enable PCI device and request regions!\n");
+	ret = comedi_pci_enable(dev);
+	if (ret)
 		return ret;
-	}
+
 	devpriv->lcr_iobase = pci_resource_start(pci_dev, 1);
 	iobase = pci_resource_start(pci_dev, 2);
 	return pc236_common_attach(dev, iobase, pci_dev->irq, IRQF_SHARED);
@@ -576,11 +574,9 @@ static void pc236_detach(struct comedi_device *dev)
 			release_region(dev->iobase, PC236_IO_SIZE);
 	} else if (is_pci_board(thisboard)) {
 		struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-		if (pcidev) {
-			if (dev->iobase)
-				comedi_pci_disable(pcidev);
+		comedi_pci_disable(dev);
+		if (pcidev)
 			pci_dev_put(pcidev);
-		}
 	}
 }
 
@@ -610,9 +606,10 @@ static DEFINE_PCI_DEVICE_TABLE(pc236_pci_table) = {
 MODULE_DEVICE_TABLE(pci, pc236_pci_table);
 
 static int amplc_pc236_pci_probe(struct pci_dev *dev,
-					   const struct pci_device_id *ent)
+				 const struct pci_device_id *id)
 {
-	return comedi_pci_auto_config(dev, &amplc_pc236_driver);
+	return comedi_pci_auto_config(dev, &amplc_pc236_driver,
+				      id->driver_data);
 }
 
 static struct pci_driver amplc_pc236_pci_driver = {
diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c
index 11c1f47..b844943 100644
--- a/drivers/staging/comedi/drivers/amplc_pc263.c
+++ b/drivers/staging/comedi/drivers/amplc_pc263.c
@@ -249,13 +249,11 @@ static int pc263_pci_common_attach(struct comedi_device *dev,
 
 	comedi_set_hw_dev(dev, &pci_dev->dev);
 
-	ret = comedi_pci_enable(pci_dev, PC263_DRIVER_NAME);
-	if (ret < 0) {
-		dev_err(dev->class_dev,
-			"error! cannot enable PCI device and request regions!\n");
+	ret = comedi_pci_enable(dev);
+	if (ret)
 		return ret;
-	}
 	iobase = pci_resource_start(pci_dev, 2);
+
 	return pc263_common_attach(dev, iobase);
 }
 
@@ -335,11 +333,9 @@ static void pc263_detach(struct comedi_device *dev)
 			release_region(dev->iobase, PC263_IO_SIZE);
 	} else if (is_pci_board(thisboard)) {
 		struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-		if (pcidev) {
-			if (dev->iobase)
-				comedi_pci_disable(pcidev);
+		comedi_pci_disable(dev);
+		if (pcidev)
 			pci_dev_put(pcidev);
-		}
 	}
 }
 
@@ -368,10 +364,10 @@ static DEFINE_PCI_DEVICE_TABLE(pc263_pci_table) = {
 MODULE_DEVICE_TABLE(pci, pc263_pci_table);
 
 static int amplc_pc263_pci_probe(struct pci_dev *dev,
-						  const struct pci_device_id
-						  *ent)
+				 const struct pci_device_id *id)
 {
-	return comedi_pci_auto_config(dev, &amplc_pc263_driver);
+	return comedi_pci_auto_config(dev, &amplc_pc263_driver,
+				      id->driver_data);
 }
 
 static struct pci_driver amplc_pc263_pci_driver = {
diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c
index c9da4cd..4d7eab9 100644
--- a/drivers/staging/comedi/drivers/amplc_pci224.c
+++ b/drivers/staging/comedi/drivers/amplc_pci224.c
@@ -1280,13 +1280,10 @@ static int pci224_attach_common(struct comedi_device *dev,
 
 	comedi_set_hw_dev(dev, &pci_dev->dev);
 
-	ret = comedi_pci_enable(pci_dev, DRIVER_NAME);
-	if (ret < 0) {
-		dev_err(dev->class_dev,
-			"error! cannot enable PCI device and request regions!\n"
-			);
+	ret = comedi_pci_enable(dev);
+	if (ret)
 		return ret;
-	}
+
 	spin_lock_init(&devpriv->ao_spinlock);
 
 	devpriv->iobase1 = pci_resource_start(pci_dev, 2);
@@ -1488,11 +1485,9 @@ static void pci224_detach(struct comedi_device *dev)
 		kfree(devpriv->ao_scan_vals);
 		kfree(devpriv->ao_scan_order);
 	}
-	if (pcidev) {
-		if (dev->iobase)
-			comedi_pci_disable(pcidev);
+	comedi_pci_disable(dev);
+	if (pcidev)
 		pci_dev_put(pcidev);
-	}
 }
 
 static struct comedi_driver amplc_pci224_driver = {
@@ -1507,10 +1502,10 @@ static struct comedi_driver amplc_pci224_driver = {
 };
 
 static int amplc_pci224_pci_probe(struct pci_dev *dev,
-						   const struct pci_device_id
-						   *ent)
+				  const struct pci_device_id *id)
 {
-	return comedi_pci_auto_config(dev, &amplc_pci224_driver);
+	return comedi_pci_auto_config(dev, &amplc_pci224_driver,
+				      id->driver_data);
 }
 
 static DEFINE_PCI_DEVICE_TABLE(amplc_pci224_pci_table) = {
diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c
index e2244c6..b6e4af4 100644
--- a/drivers/staging/comedi/drivers/amplc_pci230.c
+++ b/drivers/staging/comedi/drivers/amplc_pci230.c
@@ -2645,12 +2645,11 @@ static int pci230_attach_common(struct comedi_device *dev,
 	comedi_set_hw_dev(dev, &pci_dev->dev);
 
 	dev->board_name = thisboard->name;
-	/* Enable PCI device and reserve I/O spaces. */
-	if (comedi_pci_enable(pci_dev, "amplc_pci230") < 0) {
-		dev_err(dev->class_dev,
-			"failed to enable PCI device and request regions\n");
-		return -EIO;
-	}
+
+	rc = comedi_pci_enable(dev);
+	if (rc)
+		return rc;
+
 	/* Read base addresses of the PCI230's two I/O regions from PCI
 	 * configuration register. */
 	iobase1 = pci_resource_start(pci_dev, 2);
@@ -2840,11 +2839,9 @@ static void pci230_detach(struct comedi_device *dev)
 		subdev_8255_cleanup(dev, &dev->subdevices[2]);
 	if (dev->irq)
 		free_irq(dev->irq, dev);
-	if (pcidev) {
-		if (dev->iobase)
-			comedi_pci_disable(pcidev);
+	comedi_pci_disable(dev);
+	if (pcidev)
 		pci_dev_put(pcidev);
-	}
 }
 
 static struct comedi_driver amplc_pci230_driver = {
@@ -2859,9 +2856,10 @@ static struct comedi_driver amplc_pci230_driver = {
 };
 
 static int amplc_pci230_pci_probe(struct pci_dev *dev,
-					    const struct pci_device_id *ent)
+				  const struct pci_device_id *id)
 {
-	return comedi_pci_auto_config(dev, &amplc_pci230_driver);
+	return comedi_pci_auto_config(dev, &amplc_pci230_driver,
+				      id->driver_data);
 }
 
 static DEFINE_PCI_DEVICE_TABLE(amplc_pci230_pci_table) = {
diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c
index 79c7211..cdbeb08 100644
--- a/drivers/staging/comedi/drivers/cb_pcidas.c
+++ b/drivers/staging/comedi/drivers/cb_pcidas.c
@@ -231,9 +231,19 @@ enum trimpot_model {
 	AD8402,
 };
 
+enum cb_pcidas_boardid {
+	BOARD_PCIDAS1602_16,
+	BOARD_PCIDAS1200,
+	BOARD_PCIDAS1602_12,
+	BOARD_PCIDAS1200_JR,
+	BOARD_PCIDAS1602_16_JR,
+	BOARD_PCIDAS1000,
+	BOARD_PCIDAS1001,
+	BOARD_PCIDAS1002,
+};
+
 struct cb_pcidas_board {
 	const char *name;
-	unsigned short device_id;
 	int ai_nchan;		/*  Inputs in single-ended mode */
 	int ai_bits;		/*  analog input resolution */
 	int ai_speed;		/*  fastest conversion period in ns */
@@ -248,9 +258,8 @@ struct cb_pcidas_board {
 };
 
 static const struct cb_pcidas_board cb_pcidas_boards[] = {
-	{
+	[BOARD_PCIDAS1602_16] = {
 		.name		= "pci-das1602/16",
-		.device_id	= 0x1,
 		.ai_nchan	= 16,
 		.ai_bits	= 16,
 		.ai_speed	= 5000,
@@ -262,9 +271,9 @@ static const struct cb_pcidas_board cb_pcidas_boards[] = {
 		.trimpot	= AD8402,
 		.has_dac08	= 1,
 		.is_1602	= 1,
-	}, {
+	},
+	[BOARD_PCIDAS1200] = {
 		.name		= "pci-das1200",
-		.device_id	= 0xF,
 		.ai_nchan	= 16,
 		.ai_bits	= 12,
 		.ai_speed	= 3200,
@@ -272,9 +281,9 @@ static const struct cb_pcidas_board cb_pcidas_boards[] = {
 		.fifo_size	= 1024,
 		.ranges		= &cb_pcidas_ranges,
 		.trimpot	= AD7376,
-	}, {
+	},
+	[BOARD_PCIDAS1602_12] = {
 		.name		= "pci-das1602/12",
-		.device_id	= 0x10,
 		.ai_nchan	= 16,
 		.ai_bits	= 12,
 		.ai_speed	= 3200,
@@ -285,18 +294,18 @@ static const struct cb_pcidas_board cb_pcidas_boards[] = {
 		.ranges		= &cb_pcidas_ranges,
 		.trimpot	= AD7376,
 		.is_1602	= 1,
-	}, {
+	},
+	[BOARD_PCIDAS1200_JR] = {
 		.name		= "pci-das1200/jr",
-		.device_id	= 0x19,
 		.ai_nchan	= 16,
 		.ai_bits	= 12,
 		.ai_speed	= 3200,
 		.fifo_size	= 1024,
 		.ranges		= &cb_pcidas_ranges,
 		.trimpot	= AD7376,
-	}, {
+	},
+	[BOARD_PCIDAS1602_16_JR] = {
 		.name		= "pci-das1602/16/jr",
-		.device_id	= 0x1C,
 		.ai_nchan	= 16,
 		.ai_bits	= 16,
 		.ai_speed	= 5000,
@@ -305,18 +314,18 @@ static const struct cb_pcidas_board cb_pcidas_boards[] = {
 		.trimpot	= AD8402,
 		.has_dac08	= 1,
 		.is_1602	= 1,
-	}, {
+	},
+	[BOARD_PCIDAS1000] = {
 		.name		= "pci-das1000",
-		.device_id	= 0x4C,
 		.ai_nchan	= 16,
 		.ai_bits	= 12,
 		.ai_speed	= 4000,
 		.fifo_size	= 1024,
 		.ranges		= &cb_pcidas_ranges,
 		.trimpot	= AD7376,
-	}, {
+	},
+	[BOARD_PCIDAS1001] = {
 		.name		= "pci-das1001",
-		.device_id	= 0x1a,
 		.ai_nchan	= 16,
 		.ai_bits	= 12,
 		.ai_speed	= 6800,
@@ -324,9 +333,9 @@ static const struct cb_pcidas_board cb_pcidas_boards[] = {
 		.fifo_size	= 1024,
 		.ranges		= &cb_pcidas_alt_ranges,
 		.trimpot	= AD7376,
-	}, {
+	},
+	[BOARD_PCIDAS1002] = {
 		.name		= "pci-das1002",
-		.device_id	= 0x1b,
 		.ai_nchan	= 16,
 		.ai_bits	= 12,
 		.ai_speed	= 6800,
@@ -1332,7 +1341,7 @@ static irqreturn_t cb_pcidas_interrupt(int irq, void *d)
 	static const int timeout = 10000;
 	unsigned long flags;
 
-	if (dev->attached == 0)
+	if (!dev->attached)
 		return IRQ_NONE;
 
 	async = s->async;
@@ -1424,31 +1433,18 @@ static irqreturn_t cb_pcidas_interrupt(int irq, void *d)
 	return IRQ_HANDLED;
 }
 
-static const void *cb_pcidas_find_boardinfo(struct comedi_device *dev,
-					    struct pci_dev *pcidev)
-{
-	const struct cb_pcidas_board *thisboard;
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(cb_pcidas_boards); i++) {
-		thisboard = &cb_pcidas_boards[i];
-		if (thisboard->device_id == pcidev->device)
-			return thisboard;
-	}
-	return NULL;
-}
-
 static int cb_pcidas_auto_attach(struct comedi_device *dev,
-					   unsigned long context_unused)
+				 unsigned long context)
 {
 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-	const struct cb_pcidas_board *thisboard;
+	const struct cb_pcidas_board *thisboard = NULL;
 	struct cb_pcidas_private *devpriv;
 	struct comedi_subdevice *s;
 	int i;
 	int ret;
 
-	thisboard = cb_pcidas_find_boardinfo(dev, pcidev);
+	if (context < ARRAY_SIZE(cb_pcidas_boards))
+		thisboard = &cb_pcidas_boards[context];
 	if (!thisboard)
 		return -ENODEV;
 	dev->board_ptr  = thisboard;
@@ -1459,7 +1455,7 @@ static int cb_pcidas_auto_attach(struct comedi_device *dev,
 		return -ENOMEM;
 	dev->private = devpriv;
 
-	ret = comedi_pci_enable(pcidev, dev->board_name);
+	ret = comedi_pci_enable(dev);
 	if (ret)
 		return ret;
 
@@ -1603,7 +1599,6 @@ static int cb_pcidas_auto_attach(struct comedi_device *dev,
 static void cb_pcidas_detach(struct comedi_device *dev)
 {
 	struct cb_pcidas_private *devpriv = dev->private;
-	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
 
 	if (devpriv) {
 		if (devpriv->s5933_config) {
@@ -1615,10 +1610,7 @@ static void cb_pcidas_detach(struct comedi_device *dev)
 		free_irq(dev->irq, dev);
 	if (dev->subdevices)
 		subdev_8255_cleanup(dev, &dev->subdevices[2]);
-	if (pcidev) {
-		if (devpriv->s5933_config)
-			comedi_pci_disable(pcidev);
-	}
+	comedi_pci_disable(dev);
 }
 
 static struct comedi_driver cb_pcidas_driver = {
@@ -1629,20 +1621,21 @@ static struct comedi_driver cb_pcidas_driver = {
 };
 
 static int cb_pcidas_pci_probe(struct pci_dev *dev,
-					 const struct pci_device_id *ent)
+			       const struct pci_device_id *id)
 {
-	return comedi_pci_auto_config(dev, &cb_pcidas_driver);
+	return comedi_pci_auto_config(dev, &cb_pcidas_driver,
+				      id->driver_data);
 }
 
 static DEFINE_PCI_DEVICE_TABLE(cb_pcidas_pci_table) = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0001) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x000f) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0010) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0019) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x001c) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x004c) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x001a) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x001b) },
+	{ PCI_VDEVICE(CB, 0x0001), BOARD_PCIDAS1602_16 },
+	{ PCI_VDEVICE(CB, 0x000f), BOARD_PCIDAS1200 },
+	{ PCI_VDEVICE(CB, 0x0010), BOARD_PCIDAS1602_12 },
+	{ PCI_VDEVICE(CB, 0x0019), BOARD_PCIDAS1200_JR },
+	{ PCI_VDEVICE(CB, 0x001c), BOARD_PCIDAS1602_16_JR },
+	{ PCI_VDEVICE(CB, 0x004c), BOARD_PCIDAS1000 },
+	{ PCI_VDEVICE(CB, 0x001a), BOARD_PCIDAS1001 },
+	{ PCI_VDEVICE(CB, 0x001b), BOARD_PCIDAS1002 },
 	{ 0 }
 };
 MODULE_DEVICE_TABLE(pci, cb_pcidas_pci_table);
diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c
index 9f3112c..6988f5b 100644
--- a/drivers/staging/comedi/drivers/cb_pcidas64.c
+++ b/drivers/staging/comedi/drivers/cb_pcidas64.c
@@ -593,9 +593,39 @@ struct hw_fifo_info {
 	uint16_t fifo_size_reg_mask;
 };
 
+enum pcidas64_boardid {
+	BOARD_PCIDAS6402_16,
+	BOARD_PCIDAS6402_12,
+	BOARD_PCIDAS64_M1_16,
+	BOARD_PCIDAS64_M2_16,
+	BOARD_PCIDAS64_M3_16,
+	BOARD_PCIDAS6013,
+	BOARD_PCIDAS6014,
+	BOARD_PCIDAS6023,
+	BOARD_PCIDAS6025,
+	BOARD_PCIDAS6030,
+	BOARD_PCIDAS6031,
+	BOARD_PCIDAS6032,
+	BOARD_PCIDAS6033,
+	BOARD_PCIDAS6034,
+	BOARD_PCIDAS6035,
+	BOARD_PCIDAS6036,
+	BOARD_PCIDAS6040,
+	BOARD_PCIDAS6052,
+	BOARD_PCIDAS6070,
+	BOARD_PCIDAS6071,
+	BOARD_PCIDAS4020_12,
+	BOARD_PCIDAS6402_16_JR,
+	BOARD_PCIDAS64_M1_16_JR,
+	BOARD_PCIDAS64_M2_16_JR,
+	BOARD_PCIDAS64_M3_16_JR,
+	BOARD_PCIDAS64_M1_14,
+	BOARD_PCIDAS64_M2_14,
+	BOARD_PCIDAS64_M3_14,
+};
+
 struct pcidas64_board {
 	const char *name;
-	int device_id;		/*  pci device id */
 	int ai_se_chans;	/*  number of ai inputs in single-ended mode */
 	int ai_bits;		/*  analog input resolution */
 	int ai_speed;		/*  fastest conversion period in ns */
@@ -648,421 +678,397 @@ static inline unsigned int ai_dma_ring_count(const struct pcidas64_board *board)
 static const int bytes_in_sample = 2;
 
 static const struct pcidas64_board pcidas64_boards[] = {
-	{
-	 .name = "pci-das6402/16",
-	 .device_id = 0x1d,
-	 .ai_se_chans = 64,
-	 .ai_bits = 16,
-	 .ai_speed = 5000,
-	 .ao_nchan = 2,
-	 .ao_bits = 16,
-	 .ao_scan_speed = 10000,
-	 .layout = LAYOUT_64XX,
-	 .ai_range_table = &ai_ranges_64xx,
-	 .ao_range_table = &ao_ranges_64xx,
-	 .ao_range_code = ao_range_code_64xx,
-	 .ai_fifo = &ai_fifo_64xx,
-	 .has_8255 = 1,
-	 },
-	{
-	 .name = "pci-das6402/12",	/*  XXX check */
-	 .device_id = 0x1e,
-	 .ai_se_chans = 64,
-	 .ai_bits = 12,
-	 .ai_speed = 5000,
-	 .ao_nchan = 2,
-	 .ao_bits = 12,
-	 .ao_scan_speed = 10000,
-	 .layout = LAYOUT_64XX,
-	 .ai_range_table = &ai_ranges_64xx,
-	 .ao_range_table = &ao_ranges_64xx,
-	 .ao_range_code = ao_range_code_64xx,
-	 .ai_fifo = &ai_fifo_64xx,
-	 .has_8255 = 1,
-	 },
-	{
-	 .name = "pci-das64/m1/16",
-	 .device_id = 0x35,
-	 .ai_se_chans = 64,
-	 .ai_bits = 16,
-	 .ai_speed = 1000,
-	 .ao_nchan = 2,
-	 .ao_bits = 16,
-	 .ao_scan_speed = 10000,
-	 .layout = LAYOUT_64XX,
-	 .ai_range_table = &ai_ranges_64xx,
-	 .ao_range_table = &ao_ranges_64xx,
-	 .ao_range_code = ao_range_code_64xx,
-	 .ai_fifo = &ai_fifo_64xx,
-	 .has_8255 = 1,
-	 },
-	{
-	 .name = "pci-das64/m2/16",
-	 .device_id = 0x36,
-	 .ai_se_chans = 64,
-	 .ai_bits = 16,
-	 .ai_speed = 500,
-	 .ao_nchan = 2,
-	 .ao_bits = 16,
-	 .ao_scan_speed = 10000,
-	 .layout = LAYOUT_64XX,
-	 .ai_range_table = &ai_ranges_64xx,
-	 .ao_range_table = &ao_ranges_64xx,
-	 .ao_range_code = ao_range_code_64xx,
-	 .ai_fifo = &ai_fifo_64xx,
-	 .has_8255 = 1,
-	 },
-	{
-	 .name = "pci-das64/m3/16",
-	 .device_id = 0x37,
-	 .ai_se_chans = 64,
-	 .ai_bits = 16,
-	 .ai_speed = 333,
-	 .ao_nchan = 2,
-	 .ao_bits = 16,
-	 .ao_scan_speed = 10000,
-	 .layout = LAYOUT_64XX,
-	 .ai_range_table = &ai_ranges_64xx,
-	 .ao_range_table = &ao_ranges_64xx,
-	 .ao_range_code = ao_range_code_64xx,
-	 .ai_fifo = &ai_fifo_64xx,
-	 .has_8255 = 1,
-	 },
-	{
-	 .name = "pci-das6013",
-	 .device_id = 0x78,
-	 .ai_se_chans = 16,
-	 .ai_bits = 16,
-	 .ai_speed = 5000,
-	 .ao_nchan = 0,
-	 .ao_bits = 16,
-	 .layout = LAYOUT_60XX,
-	 .ai_range_table = &ai_ranges_60xx,
-	 .ao_range_table = &ao_ranges_60xx,
-	 .ao_range_code = ao_range_code_60xx,
-	 .ai_fifo = &ai_fifo_60xx,
-	 .has_8255 = 0,
-	 },
-	{
-	 .name = "pci-das6014",
-	 .device_id = 0x79,
-	 .ai_se_chans = 16,
-	 .ai_bits = 16,
-	 .ai_speed = 5000,
-	 .ao_nchan = 2,
-	 .ao_bits = 16,
-	 .ao_scan_speed = 100000,
-	 .layout = LAYOUT_60XX,
-	 .ai_range_table = &ai_ranges_60xx,
-	 .ao_range_table = &ao_ranges_60xx,
-	 .ao_range_code = ao_range_code_60xx,
-	 .ai_fifo = &ai_fifo_60xx,
-	 .has_8255 = 0,
-	 },
-	{
-	 .name = "pci-das6023",
-	 .device_id = 0x5d,
-	 .ai_se_chans = 16,
-	 .ai_bits = 12,
-	 .ai_speed = 5000,
-	 .ao_nchan = 0,
-	 .ao_scan_speed = 100000,
-	 .layout = LAYOUT_60XX,
-	 .ai_range_table = &ai_ranges_60xx,
-	 .ao_range_table = &ao_ranges_60xx,
-	 .ao_range_code = ao_range_code_60xx,
-	 .ai_fifo = &ai_fifo_60xx,
-	 .has_8255 = 1,
-	 },
-	{
-	 .name = "pci-das6025",
-	 .device_id = 0x5e,
-	 .ai_se_chans = 16,
-	 .ai_bits = 12,
-	 .ai_speed = 5000,
-	 .ao_nchan = 2,
-	 .ao_bits = 12,
-	 .ao_scan_speed = 100000,
-	 .layout = LAYOUT_60XX,
-	 .ai_range_table = &ai_ranges_60xx,
-	 .ao_range_table = &ao_ranges_60xx,
-	 .ao_range_code = ao_range_code_60xx,
-	 .ai_fifo = &ai_fifo_60xx,
-	 .has_8255 = 1,
-	 },
-	{
-	 .name = "pci-das6030",
-	 .device_id = 0x5f,
-	 .ai_se_chans = 16,
-	 .ai_bits = 16,
-	 .ai_speed = 10000,
-	 .ao_nchan = 2,
-	 .ao_bits = 16,
-	 .ao_scan_speed = 10000,
-	 .layout = LAYOUT_60XX,
-	 .ai_range_table = &ai_ranges_6030,
-	 .ao_range_table = &ao_ranges_6030,
-	 .ao_range_code = ao_range_code_6030,
-	 .ai_fifo = &ai_fifo_60xx,
-	 .has_8255 = 0,
-	 },
-	{
-	 .name = "pci-das6031",
-	 .device_id = 0x60,
-	 .ai_se_chans = 64,
-	 .ai_bits = 16,
-	 .ai_speed = 10000,
-	 .ao_nchan = 2,
-	 .ao_bits = 16,
-	 .ao_scan_speed = 10000,
-	 .layout = LAYOUT_60XX,
-	 .ai_range_table = &ai_ranges_6030,
-	 .ao_range_table = &ao_ranges_6030,
-	 .ao_range_code = ao_range_code_6030,
-	 .ai_fifo = &ai_fifo_60xx,
-	 .has_8255 = 0,
-	 },
-	{
-	 .name = "pci-das6032",
-	 .device_id = 0x61,
-	 .ai_se_chans = 16,
-	 .ai_bits = 16,
-	 .ai_speed = 10000,
-	 .ao_nchan = 0,
-	 .layout = LAYOUT_60XX,
-	 .ai_range_table = &ai_ranges_6030,
-	 .ai_fifo = &ai_fifo_60xx,
-	 .has_8255 = 0,
-	 },
-	{
-	 .name = "pci-das6033",
-	 .device_id = 0x62,
-	 .ai_se_chans = 64,
-	 .ai_bits = 16,
-	 .ai_speed = 10000,
-	 .ao_nchan = 0,
-	 .layout = LAYOUT_60XX,
-	 .ai_range_table = &ai_ranges_6030,
-	 .ai_fifo = &ai_fifo_60xx,
-	 .has_8255 = 0,
-	 },
-	{
-	 .name = "pci-das6034",
-	 .device_id = 0x63,
-	 .ai_se_chans = 16,
-	 .ai_bits = 16,
-	 .ai_speed = 5000,
-	 .ao_nchan = 0,
-	 .ao_scan_speed = 0,
-	 .layout = LAYOUT_60XX,
-	 .ai_range_table = &ai_ranges_60xx,
-	 .ai_fifo = &ai_fifo_60xx,
-	 .has_8255 = 0,
-	 },
-	{
-	 .name = "pci-das6035",
-	 .device_id = 0x64,
-	 .ai_se_chans = 16,
-	 .ai_bits = 16,
-	 .ai_speed = 5000,
-	 .ao_nchan = 2,
-	 .ao_bits = 12,
-	 .ao_scan_speed = 100000,
-	 .layout = LAYOUT_60XX,
-	 .ai_range_table = &ai_ranges_60xx,
-	 .ao_range_table = &ao_ranges_60xx,
-	 .ao_range_code = ao_range_code_60xx,
-	 .ai_fifo = &ai_fifo_60xx,
-	 .has_8255 = 0,
-	 },
-	{
-	 .name = "pci-das6036",
-	 .device_id = 0x6f,
-	 .ai_se_chans = 16,
-	 .ai_bits = 16,
-	 .ai_speed = 5000,
-	 .ao_nchan = 2,
-	 .ao_bits = 16,
-	 .ao_scan_speed = 100000,
-	 .layout = LAYOUT_60XX,
-	 .ai_range_table = &ai_ranges_60xx,
-	 .ao_range_table = &ao_ranges_60xx,
-	 .ao_range_code = ao_range_code_60xx,
-	 .ai_fifo = &ai_fifo_60xx,
-	 .has_8255 = 0,
-	 },
-	{
-	 .name = "pci-das6040",
-	 .device_id = 0x65,
-	 .ai_se_chans = 16,
-	 .ai_bits = 12,
-	 .ai_speed = 2000,
-	 .ao_nchan = 2,
-	 .ao_bits = 12,
-	 .ao_scan_speed = 1000,
-	 .layout = LAYOUT_60XX,
-	 .ai_range_table = &ai_ranges_6052,
-	 .ao_range_table = &ao_ranges_6030,
-	 .ao_range_code = ao_range_code_6030,
-	 .ai_fifo = &ai_fifo_60xx,
-	 .has_8255 = 0,
-	 },
-	{
-	 .name = "pci-das6052",
-	 .device_id = 0x66,
-	 .ai_se_chans = 16,
-	 .ai_bits = 16,
-	 .ai_speed = 3333,
-	 .ao_nchan = 2,
-	 .ao_bits = 16,
-	 .ao_scan_speed = 3333,
-	 .layout = LAYOUT_60XX,
-	 .ai_range_table = &ai_ranges_6052,
-	 .ao_range_table = &ao_ranges_6030,
-	 .ao_range_code = ao_range_code_6030,
-	 .ai_fifo = &ai_fifo_60xx,
-	 .has_8255 = 0,
-	 },
-	{
-	 .name = "pci-das6070",
-	 .device_id = 0x67,
-	 .ai_se_chans = 16,
-	 .ai_bits = 12,
-	 .ai_speed = 800,
-	 .ao_nchan = 2,
-	 .ao_bits = 12,
-	 .ao_scan_speed = 1000,
-	 .layout = LAYOUT_60XX,
-	 .ai_range_table = &ai_ranges_6052,
-	 .ao_range_table = &ao_ranges_6030,
-	 .ao_range_code = ao_range_code_6030,
-	 .ai_fifo = &ai_fifo_60xx,
-	 .has_8255 = 0,
-	 },
-	{
-	 .name = "pci-das6071",
-	 .device_id = 0x68,
-	 .ai_se_chans = 64,
-	 .ai_bits = 12,
-	 .ai_speed = 800,
-	 .ao_nchan = 2,
-	 .ao_bits = 12,
-	 .ao_scan_speed = 1000,
-	 .layout = LAYOUT_60XX,
-	 .ai_range_table = &ai_ranges_6052,
-	 .ao_range_table = &ao_ranges_6030,
-	 .ao_range_code = ao_range_code_6030,
-	 .ai_fifo = &ai_fifo_60xx,
-	 .has_8255 = 0,
-	 },
-	{
-	 .name = "pci-das4020/12",
-	 .device_id = 0x52,
-	 .ai_se_chans = 4,
-	 .ai_bits = 12,
-	 .ai_speed = 50,
-	 .ao_bits = 12,
-	 .ao_nchan = 2,
-	 .ao_scan_speed = 0,	/*  no hardware pacing on ao */
-	 .layout = LAYOUT_4020,
-	 .ai_range_table = &ai_ranges_4020,
-	 .ao_range_table = &ao_ranges_4020,
-	 .ao_range_code = ao_range_code_4020,
-	 .ai_fifo = &ai_fifo_4020,
-	 .has_8255 = 1,
-	 },
+	[BOARD_PCIDAS6402_16] = {
+		.name		= "pci-das6402/16",
+		.ai_se_chans	= 64,
+		.ai_bits	= 16,
+		.ai_speed	= 5000,
+		.ao_nchan	= 2,
+		.ao_bits	= 16,
+		.ao_scan_speed	= 10000,
+		.layout		= LAYOUT_64XX,
+		.ai_range_table	= &ai_ranges_64xx,
+		.ao_range_table	= &ao_ranges_64xx,
+		.ao_range_code	= ao_range_code_64xx,
+		.ai_fifo	= &ai_fifo_64xx,
+		.has_8255	= 1,
+	},
+	[BOARD_PCIDAS6402_12] = {
+		.name		= "pci-das6402/12",	/*  XXX check */
+		.ai_se_chans	= 64,
+		.ai_bits	= 12,
+		.ai_speed	= 5000,
+		.ao_nchan	= 2,
+		.ao_bits	= 12,
+		.ao_scan_speed	= 10000,
+		.layout		= LAYOUT_64XX,
+		.ai_range_table	= &ai_ranges_64xx,
+		.ao_range_table	= &ao_ranges_64xx,
+		.ao_range_code	= ao_range_code_64xx,
+		.ai_fifo	= &ai_fifo_64xx,
+		.has_8255	= 1,
+	},
+	[BOARD_PCIDAS64_M1_16] = {
+		.name		= "pci-das64/m1/16",
+		.ai_se_chans	= 64,
+		.ai_bits	= 16,
+		.ai_speed	= 1000,
+		.ao_nchan	= 2,
+		.ao_bits	= 16,
+		.ao_scan_speed	= 10000,
+		.layout		= LAYOUT_64XX,
+		.ai_range_table	= &ai_ranges_64xx,
+		.ao_range_table	= &ao_ranges_64xx,
+		.ao_range_code	= ao_range_code_64xx,
+		.ai_fifo	= &ai_fifo_64xx,
+		.has_8255	= 1,
+	},
+	[BOARD_PCIDAS64_M2_16] = {
+		.name = "pci-das64/m2/16",
+		.ai_se_chans	= 64,
+		.ai_bits	= 16,
+		.ai_speed	= 500,
+		.ao_nchan	= 2,
+		.ao_bits	= 16,
+		.ao_scan_speed	= 10000,
+		.layout		= LAYOUT_64XX,
+		.ai_range_table	= &ai_ranges_64xx,
+		.ao_range_table	= &ao_ranges_64xx,
+		.ao_range_code	= ao_range_code_64xx,
+		.ai_fifo	= &ai_fifo_64xx,
+		.has_8255	= 1,
+	},
+	[BOARD_PCIDAS64_M3_16] = {
+		.name		= "pci-das64/m3/16",
+		.ai_se_chans	= 64,
+		.ai_bits	= 16,
+		.ai_speed	= 333,
+		.ao_nchan	= 2,
+		.ao_bits	= 16,
+		.ao_scan_speed	= 10000,
+		.layout		= LAYOUT_64XX,
+		.ai_range_table	= &ai_ranges_64xx,
+		.ao_range_table	= &ao_ranges_64xx,
+		.ao_range_code	= ao_range_code_64xx,
+		.ai_fifo	= &ai_fifo_64xx,
+		.has_8255	= 1,
+	},
+	[BOARD_PCIDAS6013] = {
+		.name		= "pci-das6013",
+		.ai_se_chans	= 16,
+		.ai_bits	= 16,
+		.ai_speed	= 5000,
+		.ao_nchan	= 0,
+		.ao_bits	= 16,
+		.layout		= LAYOUT_60XX,
+		.ai_range_table	= &ai_ranges_60xx,
+		.ao_range_table	= &ao_ranges_60xx,
+		.ao_range_code	= ao_range_code_60xx,
+		.ai_fifo	= &ai_fifo_60xx,
+		.has_8255	= 0,
+	},
+	[BOARD_PCIDAS6014] = {
+		.name		= "pci-das6014",
+		.ai_se_chans	= 16,
+		.ai_bits	= 16,
+		.ai_speed	= 5000,
+		.ao_nchan	= 2,
+		.ao_bits	= 16,
+		.ao_scan_speed	= 100000,
+		.layout		= LAYOUT_60XX,
+		.ai_range_table	= &ai_ranges_60xx,
+		.ao_range_table	= &ao_ranges_60xx,
+		.ao_range_code	= ao_range_code_60xx,
+		.ai_fifo	= &ai_fifo_60xx,
+		.has_8255	= 0,
+	},
+	[BOARD_PCIDAS6023] = {
+		.name		= "pci-das6023",
+		.ai_se_chans	= 16,
+		.ai_bits	= 12,
+		.ai_speed	= 5000,
+		.ao_nchan	= 0,
+		.ao_scan_speed	= 100000,
+		.layout		= LAYOUT_60XX,
+		.ai_range_table	= &ai_ranges_60xx,
+		.ao_range_table	= &ao_ranges_60xx,
+		.ao_range_code	= ao_range_code_60xx,
+		.ai_fifo	= &ai_fifo_60xx,
+		.has_8255	= 1,
+	},
+	[BOARD_PCIDAS6025] = {
+		.name		= "pci-das6025",
+		.ai_se_chans	= 16,
+		.ai_bits	= 12,
+		.ai_speed	= 5000,
+		.ao_nchan	= 2,
+		.ao_bits	= 12,
+		.ao_scan_speed	= 100000,
+		.layout		= LAYOUT_60XX,
+		.ai_range_table	= &ai_ranges_60xx,
+		.ao_range_table	= &ao_ranges_60xx,
+		.ao_range_code	= ao_range_code_60xx,
+		.ai_fifo	= &ai_fifo_60xx,
+		.has_8255	= 1,
+	},
+	[BOARD_PCIDAS6030] = {
+		.name		= "pci-das6030",
+		.ai_se_chans	= 16,
+		.ai_bits	= 16,
+		.ai_speed	= 10000,
+		.ao_nchan	= 2,
+		.ao_bits	= 16,
+		.ao_scan_speed	= 10000,
+		.layout		= LAYOUT_60XX,
+		.ai_range_table	= &ai_ranges_6030,
+		.ao_range_table	= &ao_ranges_6030,
+		.ao_range_code	= ao_range_code_6030,
+		.ai_fifo	= &ai_fifo_60xx,
+		.has_8255	= 0,
+	},
+	[BOARD_PCIDAS6031] = {
+		.name		= "pci-das6031",
+		.ai_se_chans	= 64,
+		.ai_bits	= 16,
+		.ai_speed	= 10000,
+		.ao_nchan	= 2,
+		.ao_bits	= 16,
+		.ao_scan_speed	= 10000,
+		.layout		= LAYOUT_60XX,
+		.ai_range_table	= &ai_ranges_6030,
+		.ao_range_table	= &ao_ranges_6030,
+		.ao_range_code	= ao_range_code_6030,
+		.ai_fifo	= &ai_fifo_60xx,
+		.has_8255	= 0,
+	},
+	[BOARD_PCIDAS6032] = {
+		.name		= "pci-das6032",
+		.ai_se_chans	= 16,
+		.ai_bits	= 16,
+		.ai_speed	= 10000,
+		.ao_nchan	= 0,
+		.layout		= LAYOUT_60XX,
+		.ai_range_table	= &ai_ranges_6030,
+		.ai_fifo	= &ai_fifo_60xx,
+		.has_8255	= 0,
+	},
+	[BOARD_PCIDAS6033] = {
+		.name		= "pci-das6033",
+		.ai_se_chans	= 64,
+		.ai_bits	= 16,
+		.ai_speed	= 10000,
+		.ao_nchan	= 0,
+		.layout		= LAYOUT_60XX,
+		.ai_range_table	= &ai_ranges_6030,
+		.ai_fifo	= &ai_fifo_60xx,
+		.has_8255	= 0,
+	},
+	[BOARD_PCIDAS6034] = {
+		.name		= "pci-das6034",
+		.ai_se_chans	= 16,
+		.ai_bits	= 16,
+		.ai_speed	= 5000,
+		.ao_nchan	= 0,
+		.ao_scan_speed	= 0,
+		.layout		= LAYOUT_60XX,
+		.ai_range_table	= &ai_ranges_60xx,
+		.ai_fifo	= &ai_fifo_60xx,
+		.has_8255	= 0,
+	},
+	[BOARD_PCIDAS6035] = {
+		.name		= "pci-das6035",
+		.ai_se_chans	= 16,
+		.ai_bits	= 16,
+		.ai_speed	= 5000,
+		.ao_nchan	= 2,
+		.ao_bits	= 12,
+		.ao_scan_speed	= 100000,
+		.layout		= LAYOUT_60XX,
+		.ai_range_table	= &ai_ranges_60xx,
+		.ao_range_table	= &ao_ranges_60xx,
+		.ao_range_code	= ao_range_code_60xx,
+		.ai_fifo	= &ai_fifo_60xx,
+		.has_8255	= 0,
+	},
+	[BOARD_PCIDAS6036] = {
+		.name		= "pci-das6036",
+		.ai_se_chans	= 16,
+		.ai_bits	= 16,
+		.ai_speed	= 5000,
+		.ao_nchan	= 2,
+		.ao_bits	= 16,
+		.ao_scan_speed	= 100000,
+		.layout		= LAYOUT_60XX,
+		.ai_range_table	= &ai_ranges_60xx,
+		.ao_range_table	= &ao_ranges_60xx,
+		.ao_range_code	= ao_range_code_60xx,
+		.ai_fifo	= &ai_fifo_60xx,
+		.has_8255	= 0,
+	},
+	[BOARD_PCIDAS6040] = {
+		.name		= "pci-das6040",
+		.ai_se_chans	= 16,
+		.ai_bits	= 12,
+		.ai_speed	= 2000,
+		.ao_nchan	= 2,
+		.ao_bits	= 12,
+		.ao_scan_speed	= 1000,
+		.layout		= LAYOUT_60XX,
+		.ai_range_table	= &ai_ranges_6052,
+		.ao_range_table	= &ao_ranges_6030,
+		.ao_range_code	= ao_range_code_6030,
+		.ai_fifo	= &ai_fifo_60xx,
+		.has_8255	= 0,
+	},
+	[BOARD_PCIDAS6052] = {
+		.name		= "pci-das6052",
+		.ai_se_chans	= 16,
+		.ai_bits	= 16,
+		.ai_speed	= 3333,
+		.ao_nchan	= 2,
+		.ao_bits	= 16,
+		.ao_scan_speed	= 3333,
+		.layout		= LAYOUT_60XX,
+		.ai_range_table	= &ai_ranges_6052,
+		.ao_range_table	= &ao_ranges_6030,
+		.ao_range_code	= ao_range_code_6030,
+		.ai_fifo	= &ai_fifo_60xx,
+		.has_8255	= 0,
+	},
+	[BOARD_PCIDAS6070] = {
+		.name		= "pci-das6070",
+		.ai_se_chans	= 16,
+		.ai_bits	= 12,
+		.ai_speed	= 800,
+		.ao_nchan	= 2,
+		.ao_bits	= 12,
+		.ao_scan_speed	= 1000,
+		.layout		= LAYOUT_60XX,
+		.ai_range_table	= &ai_ranges_6052,
+		.ao_range_table	= &ao_ranges_6030,
+		.ao_range_code	= ao_range_code_6030,
+		.ai_fifo	= &ai_fifo_60xx,
+		.has_8255	= 0,
+	},
+	[BOARD_PCIDAS6071] = {
+		.name		= "pci-das6071",
+		.ai_se_chans	= 64,
+		.ai_bits	= 12,
+		.ai_speed	= 800,
+		.ao_nchan	= 2,
+		.ao_bits	= 12,
+		.ao_scan_speed	= 1000,
+		.layout		= LAYOUT_60XX,
+		.ai_range_table	= &ai_ranges_6052,
+		.ao_range_table	= &ao_ranges_6030,
+		.ao_range_code	= ao_range_code_6030,
+		.ai_fifo	= &ai_fifo_60xx,
+		.has_8255	= 0,
+	},
+	[BOARD_PCIDAS4020_12] = {
+		.name		= "pci-das4020/12",
+		.ai_se_chans	= 4,
+		.ai_bits	= 12,
+		.ai_speed	= 50,
+		.ao_bits	= 12,
+		.ao_nchan	= 2,
+		.ao_scan_speed	= 0,	/*  no hardware pacing on ao */
+		.layout		= LAYOUT_4020,
+		.ai_range_table	= &ai_ranges_4020,
+		.ao_range_table	= &ao_ranges_4020,
+		.ao_range_code	= ao_range_code_4020,
+		.ai_fifo	= &ai_fifo_4020,
+		.has_8255	= 1,
+	},
 #if 0
-	{
-	 .name = "pci-das6402/16/jr",
-	 .device_id = 0		/*  XXX, */
-	 .ai_se_chans = 64,
-	 .ai_bits = 16,
-	 .ai_speed = 5000,
-	 .ao_nchan = 0,
-	 .ao_scan_speed = 10000,
-	 .layout = LAYOUT_64XX,
-	 .ai_range_table = &ai_ranges_64xx,
-	 .ai_fifo = ai_fifo_64xx,
-	 .has_8255 = 1,
-	 },
-	{
-	 .name = "pci-das64/m1/16/jr",
-	 .device_id = 0		/*  XXX, */
-	 .ai_se_chans = 64,
-	 .ai_bits = 16,
-	 .ai_speed = 1000,
-	 .ao_nchan = 0,
-	 .ao_scan_speed = 10000,
-	 .layout = LAYOUT_64XX,
-	 .ai_range_table = &ai_ranges_64xx,
-	 .ai_fifo = ai_fifo_64xx,
-	 .has_8255 = 1,
-	 },
-	{
-	 .name = "pci-das64/m2/16/jr",
-	 .device_id = 0		/*  XXX, */
-	 .ai_se_chans = 64,
-	 .ai_bits = 16,
-	 .ai_speed = 500,
-	 .ao_nchan = 0,
-	 .ao_scan_speed = 10000,
-	 .layout = LAYOUT_64XX,
-	 .ai_range_table = &ai_ranges_64xx,
-	 .ai_fifo = ai_fifo_64xx,
-	 .has_8255 = 1,
-	 },
-	{
-	 .name = "pci-das64/m3/16/jr",
-	 .device_id = 0		/*  XXX, */
-	 .ai_se_chans = 64,
-	 .ai_bits = 16,
-	 .ai_speed = 333,
-	 .ao_nchan = 0,
-	 .ao_scan_speed = 10000,
-	 .layout = LAYOUT_64XX,
-	 .ai_range_table = &ai_ranges_64xx,
-	 .ai_fifo = ai_fifo_64xx,
-	 .has_8255 = 1,
-	 },
-	{
-	 .name = "pci-das64/m1/14",
-	 .device_id = 0,	/*  XXX */
-	 .ai_se_chans = 64,
-	 .ai_bits = 14,
-	 .ai_speed = 1000,
-	 .ao_nchan = 2,
-	 .ao_scan_speed = 10000,
-	 .layout = LAYOUT_64XX,
-	 .ai_range_table = &ai_ranges_64xx,
-	 .ai_fifo = ai_fifo_64xx,
-	 .has_8255 = 1,
-	 },
-	{
-	 .name = "pci-das64/m2/14",
-	 .device_id = 0,	/*  XXX */
-	 .ai_se_chans = 64,
-	 .ai_bits = 14,
-	 .ai_speed = 500,
-	 .ao_nchan = 2,
-	 .ao_scan_speed = 10000,
-	 .layout = LAYOUT_64XX,
-	 .ai_range_table = &ai_ranges_64xx,
-	 .ai_fifo = ai_fifo_64xx,
-	 .has_8255 = 1,
-	 },
-	{
-	 .name = "pci-das64/m3/14",
-	 .device_id = 0,	/*  XXX */
-	 .ai_se_chans = 64,
-	 .ai_bits = 14,
-	 .ai_speed = 333,
-	 .ao_nchan = 2,
-	 .ao_scan_speed = 10000,
-	 .layout = LAYOUT_64XX,
-	 .ai_range_table = &ai_ranges_64xx,
-	 .ai_fifo = ai_fifo_64xx,
-	 .has_8255 = 1,
-	 },
+	/*
+	 * The device id for these boards is unknown
+	 */
+
+	[BOARD_PCIDAS6402_16_JR] = {
+		.name		= "pci-das6402/16/jr",
+		.ai_se_chans	= 64,
+		.ai_bits	= 16,
+		.ai_speed	= 5000,
+		.ao_nchan	= 0,
+		.ao_scan_speed	= 10000,
+		.layout		= LAYOUT_64XX,
+		.ai_range_table	= &ai_ranges_64xx,
+		.ai_fifo	= ai_fifo_64xx,
+		.has_8255	= 1,
+	},
+	[BOARD_PCIDAS64_M1_16_JR] = {
+		.name		= "pci-das64/m1/16/jr",
+		.ai_se_chans	= 64,
+		.ai_bits	= 16,
+		.ai_speed	= 1000,
+		.ao_nchan	= 0,
+		.ao_scan_speed	= 10000,
+		.layout		= LAYOUT_64XX,
+		.ai_range_table	= &ai_ranges_64xx,
+		.ai_fifo	= ai_fifo_64xx,
+		.has_8255	= 1,
+	},
+	[BOARD_PCIDAS64_M2_16_JR] = {
+		.name = "pci-das64/m2/16/jr",
+		.ai_se_chans	= 64,
+		.ai_bits	= 16,
+		.ai_speed	= 500,
+		.ao_nchan	= 0,
+		.ao_scan_speed	= 10000,
+		.layout		= LAYOUT_64XX,
+		.ai_range_table	= &ai_ranges_64xx,
+		.ai_fifo	= ai_fifo_64xx,
+		.has_8255	= 1,
+	},
+	[BOARD_PCIDAS64_M3_16_JR] = {
+		.name		= "pci-das64/m3/16/jr",
+		.ai_se_chans	= 64,
+		.ai_bits	= 16,
+		.ai_speed	= 333,
+		.ao_nchan	= 0,
+		.ao_scan_speed	= 10000,
+		.layout		= LAYOUT_64XX,
+		.ai_range_table	= &ai_ranges_64xx,
+		.ai_fifo	= ai_fifo_64xx,
+		.has_8255	= 1,
+	},
+	[BOARD_PCIDAS64_M1_14] = {
+		.name		= "pci-das64/m1/14",
+		.ai_se_chans	= 64,
+		.ai_bits	= 14,
+		.ai_speed	= 1000,
+		.ao_nchan	= 2,
+		.ao_scan_speed	= 10000,
+		.layout		= LAYOUT_64XX,
+		.ai_range_table	= &ai_ranges_64xx,
+		.ai_fifo	= ai_fifo_64xx,
+		.has_8255	= 1,
+	},
+	[BOARD_PCIDAS64_M2_14] = {
+		.name		= "pci-das64/m2/14",
+		.ai_se_chans	= 64,
+		.ai_bits	= 14,
+		.ai_speed	= 500,
+		.ao_nchan	= 2,
+		.ao_scan_speed	= 10000,
+		.layout		= LAYOUT_64XX,
+		.ai_range_table	= &ai_ranges_64xx,
+		.ai_fifo	= ai_fifo_64xx,
+		.has_8255	= 1,
+	},
+	[BOARD_PCIDAS64_M3_14] = {
+		.name		= "pci-das64/m3/14",
+		.ai_se_chans	= 64,
+		.ai_bits	= 14,
+		.ai_speed	= 333,
+		.ao_nchan	= 2,
+		.ao_scan_speed	= 10000,
+		.layout		= LAYOUT_64XX,
+		.ai_range_table	= &ai_ranges_64xx,
+		.ai_fifo	= ai_fifo_64xx,
+		.has_8255	= 1,
+	},
 #endif
 };
 
@@ -1523,7 +1529,7 @@ static int alloc_and_init_dma_members(struct comedi_device *dev)
 	struct pcidas64_private *devpriv = dev->private;
 	int i;
 
-	/*  alocate pci dma buffers */
+	/*  allocate pci dma buffers */
 	for (i = 0; i < ai_dma_ring_count(thisboard); i++) {
 		devpriv->ai_buffer[i] =
 			pci_alloc_consistent(pcidev, DMA_BUFFER_SIZE,
@@ -3107,7 +3113,7 @@ static irqreturn_t handle_interrupt(int irq, void *d)
 	/* an interrupt before all the postconfig stuff gets done could
 	 * cause a NULL dereference if we continue through the
 	 * interrupt handler */
-	if (dev->attached == 0) {
+	if (!dev->attached) {
 		DEBUG_PRINT("premature interrupt, ignoring\n");
 		return IRQ_HANDLED;
 	}
@@ -4033,45 +4039,29 @@ static int setup_subdevices(struct comedi_device *dev)
 	return 0;
 }
 
-static const struct pcidas64_board
-*cb_pcidas64_find_pci_board(struct pci_dev *pcidev)
-{
-	unsigned int i;
-
-	for (i = 0; i < ARRAY_SIZE(pcidas64_boards); i++)
-		if (pcidev->device == pcidas64_boards[i].device_id)
-			return &pcidas64_boards[i];
-	return NULL;
-}
-
 static int auto_attach(struct comedi_device *dev,
-				 unsigned long context_unused)
+		       unsigned long context)
 {
-	const struct pcidas64_board *thisboard;
-	struct pcidas64_private *devpriv;
 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+	const struct pcidas64_board *thisboard = NULL;
+	struct pcidas64_private *devpriv;
 	uint32_t local_range, local_decode;
 	int retval;
 
-	dev->board_ptr = cb_pcidas64_find_pci_board(pcidev);
-	if (!dev->board_ptr) {
-		dev_err(dev->class_dev,
-			"cb_pcidas64: does not support pci %s\n",
-			pci_name(pcidev));
-		return -EINVAL;
-	}
-	thisboard = comedi_board(dev);
+	if (context < ARRAY_SIZE(pcidas64_boards))
+		thisboard = &pcidas64_boards[context];
+	if (!thisboard)
+		return -ENODEV;
+	dev->board_ptr = thisboard;
 
 	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
 	if (!devpriv)
 		return -ENOMEM;
 	dev->private = devpriv;
 
-	if (comedi_pci_enable(pcidev, dev->driver->driver_name)) {
-		dev_warn(dev->class_dev,
-			 "failed to enable PCI device and request regions\n");
-		return -EIO;
-	}
+	retval = comedi_pci_enable(dev);
+	if (retval)
+		return retval;
 	pci_set_master(pcidev);
 
 	/* Initialize dev->board_name */
@@ -4202,10 +4192,7 @@ static void detach(struct comedi_device *dev)
 	}
 	if (dev->subdevices)
 		subdev_8255_cleanup(dev, &dev->subdevices[4]);
-	if (pcidev) {
-		if (dev->iobase)
-			comedi_pci_disable(pcidev);
-	}
+	comedi_pci_disable(dev);
 }
 
 static struct comedi_driver cb_pcidas64_driver = {
@@ -4216,31 +4203,34 @@ static struct comedi_driver cb_pcidas64_driver = {
 };
 
 static int cb_pcidas64_pci_probe(struct pci_dev *dev,
-					   const struct pci_device_id *ent)
+				 const struct pci_device_id *id)
 {
-	return comedi_pci_auto_config(dev, &cb_pcidas64_driver);
+	return comedi_pci_auto_config(dev, &cb_pcidas64_driver,
+				      id->driver_data);
 }
 
 static DEFINE_PCI_DEVICE_TABLE(cb_pcidas64_pci_table) = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x001d) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x001e) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0035) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0036) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0037) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0052) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x005d) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x005e) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x005f) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0061) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0062) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0063) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0064) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0066) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0067) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0068) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x006f) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0078) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0079) },
+	{ PCI_VDEVICE(CB, 0x001d), BOARD_PCIDAS6402_16 },
+	{ PCI_VDEVICE(CB, 0x001e), BOARD_PCIDAS6402_12 },
+	{ PCI_VDEVICE(CB, 0x0035), BOARD_PCIDAS64_M1_16 },
+	{ PCI_VDEVICE(CB, 0x0036), BOARD_PCIDAS64_M2_16 },
+	{ PCI_VDEVICE(CB, 0x0037), BOARD_PCIDAS64_M3_16 },
+	{ PCI_VDEVICE(CB, 0x0052), BOARD_PCIDAS4020_12 },
+	{ PCI_VDEVICE(CB, 0x005d), BOARD_PCIDAS6023 },
+	{ PCI_VDEVICE(CB, 0x005e), BOARD_PCIDAS6025 },
+	{ PCI_VDEVICE(CB, 0x005f), BOARD_PCIDAS6030 },
+	{ PCI_VDEVICE(CB, 0x0060), BOARD_PCIDAS6031 },
+	{ PCI_VDEVICE(CB, 0x0061), BOARD_PCIDAS6032 },
+	{ PCI_VDEVICE(CB, 0x0062), BOARD_PCIDAS6033 },
+	{ PCI_VDEVICE(CB, 0x0063), BOARD_PCIDAS6034 },
+	{ PCI_VDEVICE(CB, 0x0064), BOARD_PCIDAS6035 },
+	{ PCI_VDEVICE(CB, 0x0065), BOARD_PCIDAS6040 },
+	{ PCI_VDEVICE(CB, 0x0066), BOARD_PCIDAS6052 },
+	{ PCI_VDEVICE(CB, 0x0067), BOARD_PCIDAS6070 },
+	{ PCI_VDEVICE(CB, 0x0068), BOARD_PCIDAS6071 },
+	{ PCI_VDEVICE(CB, 0x006f), BOARD_PCIDAS6036 },
+	{ PCI_VDEVICE(CB, 0x0078), BOARD_PCIDAS6013 },
+	{ PCI_VDEVICE(CB, 0x0079), BOARD_PCIDAS6014 },
 	{ 0 }
 };
 MODULE_DEVICE_TABLE(pci, cb_pcidas64_pci_table);
diff --git a/drivers/staging/comedi/drivers/cb_pcidda.c b/drivers/staging/comedi/drivers/cb_pcidda.c
index e2cadc7..2da6bd6 100644
--- a/drivers/staging/comedi/drivers/cb_pcidda.c
+++ b/drivers/staging/comedi/drivers/cb_pcidda.c
@@ -48,16 +48,6 @@
 #include "comedi_fc.h"
 #include "8255.h"
 
-/*
- * ComputerBoards PCI Device ID's supported by this driver
- */
-#define PCI_DEVICE_ID_DDA02_12		0x0020
-#define PCI_DEVICE_ID_DDA04_12		0x0021
-#define PCI_DEVICE_ID_DDA08_12		0x0022
-#define PCI_DEVICE_ID_DDA02_16		0x0023
-#define PCI_DEVICE_ID_DDA04_16		0x0024
-#define PCI_DEVICE_ID_DDA08_16		0x0025
-
 #define EEPROM_SIZE	128	/*  number of entries in eeprom */
 /* maximum number of ao channels for supported boards */
 #define MAX_AO_CHANNELS 8
@@ -118,42 +108,49 @@ static const struct comedi_lrange cb_pcidda_ranges = {
 	}
 };
 
+enum cb_pcidda_boardid {
+	BOARD_DDA02_12,
+	BOARD_DDA04_12,
+	BOARD_DDA08_12,
+	BOARD_DDA02_16,
+	BOARD_DDA04_16,
+	BOARD_DDA08_16,
+};
+
 struct cb_pcidda_board {
 	const char *name;
-	unsigned short device_id;
 	int ao_chans;
 	int ao_bits;
 };
 
 static const struct cb_pcidda_board cb_pcidda_boards[] = {
-	{
+	[BOARD_DDA02_12] = {
 		.name		= "pci-dda02/12",
-		.device_id	= PCI_DEVICE_ID_DDA02_12,
 		.ao_chans	= 2,
 		.ao_bits	= 12,
-	}, {
+	},
+	[BOARD_DDA04_12] = {
 		.name		= "pci-dda04/12",
-		.device_id	= PCI_DEVICE_ID_DDA04_12,
 		.ao_chans	= 4,
 		.ao_bits	= 12,
-	}, {
+	},
+	[BOARD_DDA08_12] = {
 		.name		= "pci-dda08/12",
-		.device_id	= PCI_DEVICE_ID_DDA08_12,
 		.ao_chans	= 8,
 		.ao_bits	= 12,
-	}, {
+	},
+	[BOARD_DDA02_16] = {
 		.name		= "pci-dda02/16",
-		.device_id	= PCI_DEVICE_ID_DDA02_16,
 		.ao_chans	= 2,
 		.ao_bits	= 16,
-	}, {
+	},
+	[BOARD_DDA04_16] = {
 		.name		= "pci-dda04/16",
-		.device_id	= PCI_DEVICE_ID_DDA04_16,
 		.ao_chans	= 4,
 		.ao_bits	= 16,
-	}, {
+	},
+	[BOARD_DDA08_16] = {
 		.name		= "pci-dda08/16",
-		.device_id	= PCI_DEVICE_ID_DDA08_16,
 		.ao_chans	= 8,
 		.ao_bits	= 16,
 	},
@@ -337,32 +334,19 @@ static int cb_pcidda_ao_insn_write(struct comedi_device *dev,
 	return insn->n;
 }
 
-static const void *cb_pcidda_find_boardinfo(struct comedi_device *dev,
-					    struct pci_dev *pcidev)
-{
-	const struct cb_pcidda_board *thisboard;
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(cb_pcidda_boards); i++) {
-		thisboard = &cb_pcidda_boards[i];
-		if (thisboard->device_id != pcidev->device)
-			return thisboard;
-	}
-	return NULL;
-}
-
 static int cb_pcidda_auto_attach(struct comedi_device *dev,
-					   unsigned long context_unused)
+				 unsigned long context)
 {
 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-	const struct cb_pcidda_board *thisboard;
+	const struct cb_pcidda_board *thisboard = NULL;
 	struct cb_pcidda_private *devpriv;
 	struct comedi_subdevice *s;
 	unsigned long iobase_8255;
 	int i;
 	int ret;
 
-	thisboard = cb_pcidda_find_boardinfo(dev, pcidev);
+	if (context < ARRAY_SIZE(cb_pcidda_boards))
+		thisboard = &cb_pcidda_boards[context];
 	if (!thisboard)
 		return -ENODEV;
 	dev->board_ptr = thisboard;
@@ -373,7 +357,7 @@ static int cb_pcidda_auto_attach(struct comedi_device *dev,
 		return -ENOMEM;
 	dev->private = devpriv;
 
-	ret = comedi_pci_enable(pcidev, dev->board_name);
+	ret = comedi_pci_enable(dev);
 	if (ret)
 		return ret;
 	dev->iobase = pci_resource_start(pcidev, 3);
@@ -415,16 +399,11 @@ static int cb_pcidda_auto_attach(struct comedi_device *dev,
 
 static void cb_pcidda_detach(struct comedi_device *dev)
 {
-	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-
 	if (dev->subdevices) {
 		subdev_8255_cleanup(dev, &dev->subdevices[1]);
 		subdev_8255_cleanup(dev, &dev->subdevices[2]);
 	}
-	if (pcidev) {
-		if (dev->iobase)
-			comedi_pci_disable(pcidev);
-	}
+	comedi_pci_disable(dev);
 }
 
 static struct comedi_driver cb_pcidda_driver = {
@@ -435,18 +414,19 @@ static struct comedi_driver cb_pcidda_driver = {
 };
 
 static int cb_pcidda_pci_probe(struct pci_dev *dev,
-					 const struct pci_device_id *ent)
+			       const struct pci_device_id *id)
 {
-	return comedi_pci_auto_config(dev, &cb_pcidda_driver);
+	return comedi_pci_auto_config(dev, &cb_pcidda_driver,
+				      id->driver_data);
 }
 
 static DEFINE_PCI_DEVICE_TABLE(cb_pcidda_pci_table) = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_CB, PCI_DEVICE_ID_DDA02_12) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_CB, PCI_DEVICE_ID_DDA04_12) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_CB, PCI_DEVICE_ID_DDA08_12) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_CB, PCI_DEVICE_ID_DDA02_16) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_CB, PCI_DEVICE_ID_DDA04_16) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_CB, PCI_DEVICE_ID_DDA08_16) },
+	{ PCI_VDEVICE(CB, 0x0020), BOARD_DDA02_12 },
+	{ PCI_VDEVICE(CB, 0x0021), BOARD_DDA04_12 },
+	{ PCI_VDEVICE(CB, 0x0022), BOARD_DDA08_12 },
+	{ PCI_VDEVICE(CB, 0x0023), BOARD_DDA02_16 },
+	{ PCI_VDEVICE(CB, 0x0024), BOARD_DDA04_16 },
+	{ PCI_VDEVICE(CB, 0x0025), BOARD_DDA08_16 },
 	{ 0 }
 };
 MODULE_DEVICE_TABLE(pci, cb_pcidda_pci_table);
diff --git a/drivers/staging/comedi/drivers/cb_pcimdas.c b/drivers/staging/comedi/drivers/cb_pcimdas.c
index aae063c..f6d99a3 100644
--- a/drivers/staging/comedi/drivers/cb_pcimdas.c
+++ b/drivers/staging/comedi/drivers/cb_pcimdas.c
@@ -222,7 +222,7 @@ static int cb_pcimdas_auto_attach(struct comedi_device *dev,
 		return -ENOMEM;
 	dev->private = devpriv;
 
-	ret = comedi_pci_enable(pcidev, dev->board_name);
+	ret = comedi_pci_enable(dev);
 	if (ret)
 		return ret;
 
@@ -277,14 +277,9 @@ static int cb_pcimdas_auto_attach(struct comedi_device *dev,
 
 static void cb_pcimdas_detach(struct comedi_device *dev)
 {
-	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-
 	if (dev->irq)
 		free_irq(dev->irq, dev);
-	if (pcidev) {
-		if (dev->iobase)
-			comedi_pci_disable(pcidev);
-	}
+	comedi_pci_disable(dev);
 }
 
 static struct comedi_driver cb_pcimdas_driver = {
@@ -295,9 +290,10 @@ static struct comedi_driver cb_pcimdas_driver = {
 };
 
 static int cb_pcimdas_pci_probe(struct pci_dev *dev,
-					  const struct pci_device_id *ent)
+				const struct pci_device_id *id)
 {
-	return comedi_pci_auto_config(dev, &cb_pcimdas_driver);
+	return comedi_pci_auto_config(dev, &cb_pcimdas_driver,
+				      id->driver_data);
 }
 
 static DEFINE_PCI_DEVICE_TABLE(cb_pcimdas_pci_table) = {
diff --git a/drivers/staging/comedi/drivers/cb_pcimdda.c b/drivers/staging/comedi/drivers/cb_pcimdda.c
index 63cfbaf..d00f7f6 100644
--- a/drivers/staging/comedi/drivers/cb_pcimdda.c
+++ b/drivers/staging/comedi/drivers/cb_pcimdda.c
@@ -168,7 +168,7 @@ static int cb_pcimdda_auto_attach(struct comedi_device *dev,
 		return -ENOMEM;
 	dev->private = devpriv;
 
-	ret = comedi_pci_enable(pcidev, dev->board_name);
+	ret = comedi_pci_enable(dev);
 	if (ret)
 		return ret;
 	dev->iobase = pci_resource_start(pcidev, 3);
@@ -201,14 +201,9 @@ static int cb_pcimdda_auto_attach(struct comedi_device *dev,
 
 static void cb_pcimdda_detach(struct comedi_device *dev)
 {
-	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-
 	if (dev->subdevices)
 		subdev_8255_cleanup(dev, &dev->subdevices[1]);
-	if (pcidev) {
-		if (dev->iobase)
-			comedi_pci_disable(pcidev);
-	}
+	comedi_pci_disable(dev);
 }
 
 static struct comedi_driver cb_pcimdda_driver = {
@@ -219,9 +214,10 @@ static struct comedi_driver cb_pcimdda_driver = {
 };
 
 static int cb_pcimdda_pci_probe(struct pci_dev *dev,
-					  const struct pci_device_id *ent)
+				const struct pci_device_id *id)
 {
-	return comedi_pci_auto_config(dev, &cb_pcimdda_driver);
+	return comedi_pci_auto_config(dev, &cb_pcimdda_driver,
+				      id->driver_data);
 }
 
 static DEFINE_PCI_DEVICE_TABLE(cb_pcimdda_pci_table) = {
diff --git a/drivers/staging/comedi/drivers/contec_pci_dio.c b/drivers/staging/comedi/drivers/contec_pci_dio.c
index 182dea6..da0be62 100644
--- a/drivers/staging/comedi/drivers/contec_pci_dio.c
+++ b/drivers/staging/comedi/drivers/contec_pci_dio.c
@@ -79,7 +79,7 @@ static int contec_auto_attach(struct comedi_device *dev,
 
 	dev->board_name = dev->driver->driver_name;
 
-	ret = comedi_pci_enable(pcidev, dev->board_name);
+	ret = comedi_pci_enable(dev);
 	if (ret)
 		return ret;
 	dev->iobase = pci_resource_start(pcidev, 0);
@@ -109,27 +109,18 @@ static int contec_auto_attach(struct comedi_device *dev,
 	return 0;
 }
 
-static void contec_detach(struct comedi_device *dev)
-{
-	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-
-	if (pcidev) {
-		if (dev->iobase)
-			comedi_pci_disable(pcidev);
-	}
-}
-
 static struct comedi_driver contec_pci_dio_driver = {
 	.driver_name	= "contec_pci_dio",
 	.module		= THIS_MODULE,
 	.auto_attach	= contec_auto_attach,
-	.detach		= contec_detach,
+	.detach		= comedi_pci_disable,
 };
 
 static int contec_pci_dio_pci_probe(struct pci_dev *dev,
-					      const struct pci_device_id *ent)
+				    const struct pci_device_id *id)
 {
-	return comedi_pci_auto_config(dev, &contec_pci_dio_driver);
+	return comedi_pci_auto_config(dev, &contec_pci_dio_driver,
+				      id->driver_data);
 }
 
 static DEFINE_PCI_DEVICE_TABLE(contec_pci_dio_pci_table) = {
diff --git a/drivers/staging/comedi/drivers/daqboard2000.c b/drivers/staging/comedi/drivers/daqboard2000.c
index 50b450f..a0ec8bd 100644
--- a/drivers/staging/comedi/drivers/daqboard2000.c
+++ b/drivers/staging/comedi/drivers/daqboard2000.c
@@ -709,10 +709,9 @@ static int daqboard2000_auto_attach(struct comedi_device *dev,
 		return -ENOMEM;
 	dev->private = devpriv;
 
-	result = comedi_pci_enable(pcidev, dev->driver->driver_name);
-	if (result < 0)
+	result = comedi_pci_enable(dev);
+	if (result)
 		return result;
-	dev->iobase = 1;	/* the "detach" needs this */
 
 	devpriv->plx = ioremap(pci_resource_start(pcidev, 0),
 			       pci_resource_len(pcidev, 0));
@@ -767,7 +766,6 @@ static int daqboard2000_auto_attach(struct comedi_device *dev,
 
 static void daqboard2000_detach(struct comedi_device *dev)
 {
-	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
 	struct daqboard2000_private *devpriv = dev->private;
 
 	if (dev->subdevices)
@@ -780,11 +778,7 @@ static void daqboard2000_detach(struct comedi_device *dev)
 		if (devpriv->plx)
 			iounmap(devpriv->plx);
 	}
-	if (pcidev) {
-		if (dev->iobase)
-			comedi_pci_disable(pcidev);
-		pci_dev_put(pcidev);
-	}
+	comedi_pci_disable(dev);
 }
 
 static struct comedi_driver daqboard2000_driver = {
@@ -795,9 +789,10 @@ static struct comedi_driver daqboard2000_driver = {
 };
 
 static int daqboard2000_pci_probe(struct pci_dev *dev,
-					    const struct pci_device_id *ent)
+				  const struct pci_device_id *id)
 {
-	return comedi_pci_auto_config(dev, &daqboard2000_driver);
+	return comedi_pci_auto_config(dev, &daqboard2000_driver,
+				      id->driver_data);
 }
 
 static DEFINE_PCI_DEVICE_TABLE(daqboard2000_pci_table) = {
diff --git a/drivers/staging/comedi/drivers/das08.h b/drivers/staging/comedi/drivers/das08.h
index b102ad4..89bb8d6 100644
--- a/drivers/staging/comedi/drivers/das08.h
+++ b/drivers/staging/comedi/drivers/das08.h
@@ -32,7 +32,6 @@ enum das08_lrange { das08_pg_none, das08_bipolar5, das08_pgh, das08_pgl,
 
 struct das08_board_struct {
 	const char *name;
-	unsigned int id;	/*  id for pci/pcmcia boards */
 	bool is_jr;		/* true for 'JR' boards */
 	unsigned int ai_nbits;
 	enum das08_lrange ai_pg;
diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c
index cfeebe4..d9f3e92 100644
--- a/drivers/staging/comedi/drivers/das08_cs.c
+++ b/drivers/staging/comedi/drivers/das08_cs.c
@@ -59,7 +59,6 @@ Command support does not exist, but could be added for this board.
 static const struct das08_board_struct das08_cs_boards[] = {
 	{
 		.name		= "pcm-das08",
-		.id		= 0x0,	/*  XXX */
 		.ai_nbits	= 12,
 		.ai_pg		= das08_bipolar5,
 		.ai_encoding	= das08_pcm_encode12,
diff --git a/drivers/staging/comedi/drivers/das08_pci.c b/drivers/staging/comedi/drivers/das08_pci.c
index c405876..53fa943 100644
--- a/drivers/staging/comedi/drivers/das08_pci.c
+++ b/drivers/staging/comedi/drivers/das08_pci.c
@@ -46,7 +46,6 @@
 static const struct das08_board_struct das08_pci_boards[] = {
 	{
 		.name		= "pci-das08",
-		.id		= PCI_DEVICE_ID_PCIDAS08,
 		.ai_nbits	= 12,
 		.ai_pg		= das08_bipolar5,
 		.ai_encoding	= das08_encode12,
@@ -72,7 +71,7 @@ static int das08_pci_auto_attach(struct comedi_device *dev,
 	/* The das08 driver needs the board_ptr */
 	dev->board_ptr = &das08_pci_boards[0];
 
-	ret = comedi_pci_enable(pdev, dev->driver->driver_name);
+	ret = comedi_pci_enable(dev);
 	if (ret)
 		return ret;
 	dev->iobase = pci_resource_start(pdev, 2);
@@ -82,11 +81,8 @@ static int das08_pci_auto_attach(struct comedi_device *dev,
 
 static void das08_pci_detach(struct comedi_device *dev)
 {
-	struct pci_dev *pdev = comedi_to_pci_dev(dev);
-
 	das08_common_detach(dev);
-	if (dev->iobase)
-		comedi_pci_disable(pdev);
+	comedi_pci_disable(dev);
 }
 
 static struct comedi_driver das08_pci_comedi_driver = {
@@ -97,9 +93,10 @@ static struct comedi_driver das08_pci_comedi_driver = {
 };
 
 static int das08_pci_probe(struct pci_dev *dev,
-			   const struct pci_device_id *ent)
+			   const struct pci_device_id *id)
 {
-	return comedi_pci_auto_config(dev, &das08_pci_comedi_driver);
+	return comedi_pci_auto_config(dev, &das08_pci_comedi_driver,
+				      id->driver_data);
 }
 
 static DEFINE_PCI_DEVICE_TABLE(das08_pci_table) = {
diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c
index f238a1f..caeaee8 100644
--- a/drivers/staging/comedi/drivers/das16.c
+++ b/drivers/staging/comedi/drivers/das16.c
@@ -876,7 +876,7 @@ static void das16_interrupt(struct comedi_device *dev)
 	int num_bytes, residue;
 	int buffer_index;
 
-	if (dev->attached == 0) {
+	if (!dev->attached) {
 		comedi_error(dev, "premature interrupt");
 		return;
 	}
diff --git a/drivers/staging/comedi/drivers/das16m1.c b/drivers/staging/comedi/drivers/das16m1.c
index b0a861a..7ba8fc7 100644
--- a/drivers/staging/comedi/drivers/das16m1.c
+++ b/drivers/staging/comedi/drivers/das16m1.c
@@ -499,7 +499,7 @@ static irqreturn_t das16m1_interrupt(int irq, void *d)
 	int status;
 	struct comedi_device *dev = d;
 
-	if (dev->attached == 0) {
+	if (!dev->attached) {
 		comedi_error(dev, "premature interrupt");
 		return IRQ_HANDLED;
 	}
diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c
index 7900f95..d01e140 100644
--- a/drivers/staging/comedi/drivers/das1800.c
+++ b/drivers/staging/comedi/drivers/das1800.c
@@ -731,7 +731,7 @@ static irqreturn_t das1800_interrupt(int irq, void *d)
 	struct comedi_device *dev = d;
 	unsigned int status;
 
-	if (dev->attached == 0) {
+	if (!dev->attached) {
 		comedi_error(dev, "premature interrupt");
 		return IRQ_HANDLED;
 	}
diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c
index 3ce499f..909656b 100644
--- a/drivers/staging/comedi/drivers/dt3000.c
+++ b/drivers/staging/comedi/drivers/dt3000.c
@@ -63,17 +63,6 @@ AO commands are not supported.
 
 #include "comedi_fc.h"
 
-/*
- * PCI device id's supported by this driver
- */
-#define PCI_DEVICE_ID_DT3001		0x0022
-#define PCI_DEVICE_ID_DT3002		0x0023
-#define PCI_DEVICE_ID_DT3003		0x0024
-#define PCI_DEVICE_ID_DT3004		0x0025
-#define PCI_DEVICE_ID_DT3005		0x0026
-#define PCI_DEVICE_ID_DT3001_PGL	0x0027
-#define PCI_DEVICE_ID_DT3003_PGL	0x0028
-
 static const struct comedi_lrange range_dt3000_ai = {
 	4, {
 		BIP_RANGE(10),
@@ -92,9 +81,18 @@ static const struct comedi_lrange range_dt3000_ai_pgl = {
 	}
 };
 
+enum dt3k_boardid {
+	BOARD_DT3001,
+	BOARD_DT3001_PGL,
+	BOARD_DT3002,
+	BOARD_DT3003,
+	BOARD_DT3003_PGL,
+	BOARD_DT3004,
+	BOARD_DT3005,
+};
+
 struct dt3k_boardtype {
 	const char *name;
-	unsigned int device_id;
 	int adchan;
 	int adbits;
 	int ai_speed;
@@ -104,61 +102,60 @@ struct dt3k_boardtype {
 };
 
 static const struct dt3k_boardtype dt3k_boardtypes[] = {
-	{
+	[BOARD_DT3001] = {
 		.name		= "dt3001",
-		.device_id	= PCI_DEVICE_ID_DT3001,
 		.adchan		= 16,
 		.adbits		= 12,
 		.adrange	= &range_dt3000_ai,
 		.ai_speed	= 3000,
 		.dachan		= 2,
 		.dabits		= 12,
-	}, {
+	},
+	[BOARD_DT3001_PGL] = {
 		.name		= "dt3001-pgl",
-		.device_id	= PCI_DEVICE_ID_DT3001_PGL,
 		.adchan		= 16,
 		.adbits		= 12,
 		.adrange	= &range_dt3000_ai_pgl,
 		.ai_speed	= 3000,
 		.dachan		= 2,
 		.dabits		= 12,
-	}, {
+	},
+	[BOARD_DT3002] = {
 		.name		= "dt3002",
-		.device_id	= PCI_DEVICE_ID_DT3002,
 		.adchan		= 32,
 		.adbits		= 12,
 		.adrange	= &range_dt3000_ai,
 		.ai_speed	= 3000,
-	}, {
+	},
+	[BOARD_DT3003] = {
 		.name		= "dt3003",
-		.device_id	= PCI_DEVICE_ID_DT3003,
 		.adchan		= 64,
 		.adbits		= 12,
 		.adrange	= &range_dt3000_ai,
 		.ai_speed	= 3000,
 		.dachan		= 2,
 		.dabits		= 12,
-	}, {
+	},
+	[BOARD_DT3003_PGL] = {
 		.name		= "dt3003-pgl",
-		.device_id	= PCI_DEVICE_ID_DT3003_PGL,
 		.adchan		= 64,
 		.adbits		= 12,
 		.adrange	= &range_dt3000_ai_pgl,
 		.ai_speed	= 3000,
 		.dachan		= 2,
 		.dabits		= 12,
-	}, {
+	},
+	[BOARD_DT3004] = {
 		.name		= "dt3004",
-		.device_id	= PCI_DEVICE_ID_DT3004,
 		.adchan		= 16,
 		.adbits		= 16,
 		.adrange	= &range_dt3000_ai,
 		.ai_speed	= 10000,
 		.dachan		= 2,
 		.dabits		= 12,
-	}, {
+	},
+	[BOARD_DT3005] = {
 		.name		= "dt3005",	/* a.k.a. 3004-200 */
-		.device_id 	= PCI_DEVICE_ID_DT3005,
 		.adchan		= 16,
 		.adbits		= 16,
 		.adrange	= &range_dt3000_ai,
@@ -716,31 +713,18 @@ static int dt3k_mem_insn_read(struct comedi_device *dev,
 	return i;
 }
 
-static const void *dt3000_find_boardinfo(struct comedi_device *dev,
-					 struct pci_dev *pcidev)
-{
-	const struct dt3k_boardtype *this_board;
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(dt3k_boardtypes); i++) {
-		this_board = &dt3k_boardtypes[i];
-		if (this_board->device_id == pcidev->device)
-			return this_board;
-	}
-	return NULL;
-}
-
 static int dt3000_auto_attach(struct comedi_device *dev,
-					unsigned long context_unused)
+			      unsigned long context)
 {
 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-	const struct dt3k_boardtype *this_board;
+	const struct dt3k_boardtype *this_board = NULL;
 	struct dt3k_private *devpriv;
 	struct comedi_subdevice *s;
 	resource_size_t pci_base;
 	int ret = 0;
 
-	this_board = dt3000_find_boardinfo(dev, pcidev);
+	if (context < ARRAY_SIZE(dt3k_boardtypes))
+		this_board = &dt3k_boardtypes[context];
 	if (!this_board)
 		return -ENODEV;
 	dev->board_ptr = this_board;
@@ -751,10 +735,9 @@ static int dt3000_auto_attach(struct comedi_device *dev,
 		return -ENOMEM;
 	dev->private = devpriv;
 
-	ret = comedi_pci_enable(pcidev, dev->board_name);
+	ret = comedi_pci_enable(dev);
 	if (ret < 0)
 		return ret;
-	dev->iobase = 1;	/* the "detach" needs this */
 
 	pci_base  = pci_resource_start(pcidev, 0);
 	devpriv->io_addr = ioremap(pci_base, DT3000_SIZE);
@@ -830,7 +813,6 @@ static int dt3000_auto_attach(struct comedi_device *dev,
 
 static void dt3000_detach(struct comedi_device *dev)
 {
-	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
 	struct dt3k_private *devpriv = dev->private;
 
 	if (dev->irq)
@@ -839,10 +821,7 @@ static void dt3000_detach(struct comedi_device *dev)
 		if (devpriv->io_addr)
 			iounmap(devpriv->io_addr);
 	}
-	if (pcidev) {
-		if (dev->iobase)
-			comedi_pci_disable(pcidev);
-	}
+	comedi_pci_disable(dev);
 }
 
 static struct comedi_driver dt3000_driver = {
@@ -853,19 +832,19 @@ static struct comedi_driver dt3000_driver = {
 };
 
 static int dt3000_pci_probe(struct pci_dev *dev,
-				      const struct pci_device_id *ent)
+			    const struct pci_device_id *id)
 {
-	return comedi_pci_auto_config(dev, &dt3000_driver);
+	return comedi_pci_auto_config(dev, &dt3000_driver, id->driver_data);
 }
 
 static DEFINE_PCI_DEVICE_TABLE(dt3000_pci_table) = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_DT, PCI_DEVICE_ID_DT3001) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_DT, PCI_DEVICE_ID_DT3001_PGL) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_DT, PCI_DEVICE_ID_DT3002) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_DT, PCI_DEVICE_ID_DT3003) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_DT, PCI_DEVICE_ID_DT3003_PGL) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_DT, PCI_DEVICE_ID_DT3004) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_DT, PCI_DEVICE_ID_DT3005) },
+	{ PCI_VDEVICE(DT, 0x0022), BOARD_DT3001 },
+	{ PCI_VDEVICE(DT, 0x0023), BOARD_DT3002 },
+	{ PCI_VDEVICE(DT, 0x0024), BOARD_DT3003 },
+	{ PCI_VDEVICE(DT, 0x0025), BOARD_DT3004 },
+	{ PCI_VDEVICE(DT, 0x0026), BOARD_DT3005 },
+	{ PCI_VDEVICE(DT, 0x0027), BOARD_DT3001_PGL },
+	{ PCI_VDEVICE(DT, 0x0028), BOARD_DT3003_PGL },
 	{ 0 }
 };
 MODULE_DEVICE_TABLE(pci, dt3000_pci_table);
diff --git a/drivers/staging/comedi/drivers/dyna_pci10xx.c b/drivers/staging/comedi/drivers/dyna_pci10xx.c
index decc17f..17f9ec2a 100644
--- a/drivers/staging/comedi/drivers/dyna_pci10xx.c
+++ b/drivers/staging/comedi/drivers/dyna_pci10xx.c
@@ -194,7 +194,7 @@ static int dyna_pci10xx_auto_attach(struct comedi_device *dev,
 		return -ENOMEM;
 	dev->private = devpriv;
 
-	ret = comedi_pci_enable(pcidev, dev->board_name);
+	ret = comedi_pci_enable(dev);
 	if (ret)
 		return ret;
 	dev->iobase = pci_resource_start(pcidev, 2);
@@ -254,15 +254,11 @@ static int dyna_pci10xx_auto_attach(struct comedi_device *dev,
 
 static void dyna_pci10xx_detach(struct comedi_device *dev)
 {
-	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
 	struct dyna_pci10xx_private *devpriv = dev->private;
 
 	if (devpriv)
 		mutex_destroy(&devpriv->mutex);
-	if (pcidev) {
-		if (dev->iobase)
-			comedi_pci_disable(pcidev);
-	}
+	comedi_pci_disable(dev);
 }
 
 static struct comedi_driver dyna_pci10xx_driver = {
@@ -273,9 +269,10 @@ static struct comedi_driver dyna_pci10xx_driver = {
 };
 
 static int dyna_pci10xx_pci_probe(struct pci_dev *dev,
-					    const struct pci_device_id *ent)
+				  const struct pci_device_id *id)
 {
-	return comedi_pci_auto_config(dev, &dyna_pci10xx_driver);
+	return comedi_pci_auto_config(dev, &dyna_pci10xx_driver,
+				      id->driver_data);
 }
 
 static DEFINE_PCI_DEVICE_TABLE(dyna_pci10xx_pci_table) = {
diff --git a/drivers/staging/comedi/drivers/gsc_hpdi.c b/drivers/staging/comedi/drivers/gsc_hpdi.c
index b60c975..ba44d03 100644
--- a/drivers/staging/comedi/drivers/gsc_hpdi.c
+++ b/drivers/staging/comedi/drivers/gsc_hpdi.c
@@ -499,12 +499,9 @@ static int hpdi_auto_attach(struct comedi_device *dev,
 		return -ENOMEM;
 	dev->private = devpriv;
 
-	if (comedi_pci_enable(pcidev, dev->board_name)) {
-		dev_warn(dev->class_dev,
-			 "failed enable PCI device and request regions\n");
-		return -EIO;
-	}
-	dev->iobase = 1;	/* the "detach" needs this */
+	retval = comedi_pci_enable(dev);
+	if (retval)
+		return retval;
 	pci_set_master(pcidev);
 
 	devpriv->plx9080_iobase =
@@ -596,9 +593,8 @@ static void hpdi_detach(struct comedi_device *dev)
 					    NUM_DMA_DESCRIPTORS,
 					    devpriv->dma_desc,
 					    devpriv->dma_desc_phys_addr);
-		if (dev->iobase)
-			comedi_pci_disable(pcidev);
 	}
+	comedi_pci_disable(dev);
 }
 
 static int dio_config_block_size(struct comedi_device *dev, unsigned int *data)
@@ -943,9 +939,9 @@ static struct comedi_driver gsc_hpdi_driver = {
 };
 
 static int gsc_hpdi_pci_probe(struct pci_dev *dev,
-					const struct pci_device_id *ent)
+			      const struct pci_device_id *id)
 {
-	return comedi_pci_auto_config(dev, &gsc_hpdi_driver);
+	return comedi_pci_auto_config(dev, &gsc_hpdi_driver, id->driver_data);
 }
 
 static DEFINE_PCI_DEVICE_TABLE(gsc_hpdi_pci_table) = {
diff --git a/drivers/staging/comedi/drivers/icp_multi.c b/drivers/staging/comedi/drivers/icp_multi.c
index 1e08f91..f29a797 100644
--- a/drivers/staging/comedi/drivers/icp_multi.c
+++ b/drivers/staging/comedi/drivers/icp_multi.c
@@ -120,7 +120,7 @@ struct icp_multi_private {
 	unsigned int DacCmdStatus;	/*  DAC Command/Status register */
 	unsigned int IntEnable;	/*  Interrupt Enable register */
 	unsigned int IntStatus;	/*  Interrupt Status register */
-	unsigned int act_chanlist[32];	/*  list of scaned channel */
+	unsigned int act_chanlist[32];	/*  list of scanned channel */
 	unsigned char act_chanlist_len;	/*  len of scanlist */
 	unsigned char act_chanlist_pos;	/*  actual position in MUX list */
 	unsigned int *ai_chanlist;	/*  actaul chanlist */
@@ -510,7 +510,7 @@ static int icp_multi_auto_attach(struct comedi_device *dev,
 		return -ENOMEM;
 	dev->private = devpriv;
 
-	ret = comedi_pci_enable(pcidev, dev->board_name);
+	ret = comedi_pci_enable(dev);
 	if (ret)
 		return ret;
 	iobase = pci_resource_start(pcidev, 2);
@@ -594,7 +594,6 @@ static int icp_multi_auto_attach(struct comedi_device *dev,
 
 static void icp_multi_detach(struct comedi_device *dev)
 {
-	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
 	struct icp_multi_private *devpriv = dev->private;
 
 	if (devpriv)
@@ -604,10 +603,7 @@ static void icp_multi_detach(struct comedi_device *dev)
 		free_irq(dev->irq, dev);
 	if (devpriv && devpriv->io_addr)
 		iounmap(devpriv->io_addr);
-	if (pcidev) {
-		if (dev->iobase)
-			comedi_pci_disable(pcidev);
-	}
+	comedi_pci_disable(dev);
 }
 
 static struct comedi_driver icp_multi_driver = {
@@ -618,9 +614,9 @@ static struct comedi_driver icp_multi_driver = {
 };
 
 static int icp_multi_pci_probe(struct pci_dev *dev,
-					   const struct pci_device_id *ent)
+			       const struct pci_device_id *id)
 {
-	return comedi_pci_auto_config(dev, &icp_multi_driver);
+	return comedi_pci_auto_config(dev, &icp_multi_driver, id->driver_data);
 }
 
 static DEFINE_PCI_DEVICE_TABLE(icp_multi_pci_table) = {
diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c
index 17ba75e..f21ebb5 100644
--- a/drivers/staging/comedi/drivers/jr3_pci.c
+++ b/drivers/staging/comedi/drivers/jr3_pci.c
@@ -702,11 +702,10 @@ static int jr3_pci_auto_attach(struct comedi_device *dev,
 	}
 	dev->board_name = "jr3_pci";
 
-	result = comedi_pci_enable(pcidev, "jr3_pci");
-	if (result < 0)
+	result = comedi_pci_enable(dev);
+	if (result)
 		return result;
 
-	dev->iobase = 1;	/* the "detach" needs this */
 	devpriv->iobase = ioremap(pci_resource_start(pcidev, 0),
 				  offsetof(struct jr3_t,
 					   channel[devpriv->n_channels]));
@@ -816,7 +815,6 @@ static int jr3_pci_auto_attach(struct comedi_device *dev,
 static void jr3_pci_detach(struct comedi_device *dev)
 {
 	int i;
-	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
 	struct jr3_pci_dev_private *devpriv = dev->private;
 
 	if (devpriv) {
@@ -828,9 +826,8 @@ static void jr3_pci_detach(struct comedi_device *dev)
 		}
 		if (devpriv->iobase)
 			iounmap(devpriv->iobase);
-		if (dev->iobase)
-			comedi_pci_disable(pcidev);
 	}
+	comedi_pci_disable(dev);
 }
 
 static struct comedi_driver jr3_pci_driver = {
@@ -841,9 +838,9 @@ static struct comedi_driver jr3_pci_driver = {
 };
 
 static int jr3_pci_pci_probe(struct pci_dev *dev,
-				       const struct pci_device_id *ent)
+			     const struct pci_device_id *id)
 {
-	return comedi_pci_auto_config(dev, &jr3_pci_driver);
+	return comedi_pci_auto_config(dev, &jr3_pci_driver, id->driver_data);
 }
 
 static DEFINE_PCI_DEVICE_TABLE(jr3_pci_pci_table) = {
diff --git a/drivers/staging/comedi/drivers/ke_counter.c b/drivers/staging/comedi/drivers/ke_counter.c
index 8c09c02..bca29e5 100644
--- a/drivers/staging/comedi/drivers/ke_counter.c
+++ b/drivers/staging/comedi/drivers/ke_counter.c
@@ -98,7 +98,7 @@ static int cnt_auto_attach(struct comedi_device *dev,
 
 	dev->board_name = dev->driver->driver_name;
 
-	ret = comedi_pci_enable(pcidev, dev->board_name);
+	ret = comedi_pci_enable(dev);
 	if (ret)
 		return ret;
 	dev->iobase = pci_resource_start(pcidev, 0);
@@ -131,27 +131,18 @@ static int cnt_auto_attach(struct comedi_device *dev,
 	return 0;
 }
 
-static void cnt_detach(struct comedi_device *dev)
-{
-	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-
-	if (pcidev) {
-		if (dev->iobase)
-			comedi_pci_disable(pcidev);
-	}
-}
-
 static struct comedi_driver ke_counter_driver = {
 	.driver_name	= "ke_counter",
 	.module		= THIS_MODULE,
 	.auto_attach	= cnt_auto_attach,
-	.detach		= cnt_detach,
+	.detach		= comedi_pci_disable,
 };
 
 static int ke_counter_pci_probe(struct pci_dev *dev,
-					  const struct pci_device_id *ent)
+				const struct pci_device_id *id)
 {
-	return comedi_pci_auto_config(dev, &ke_counter_driver);
+	return comedi_pci_auto_config(dev, &ke_counter_driver,
+				      id->driver_data);
 }
 
 static DEFINE_PCI_DEVICE_TABLE(ke_counter_pci_table) = {
diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c
index b766bb9..e415db2 100644
--- a/drivers/staging/comedi/drivers/me4000.c
+++ b/drivers/staging/comedi/drivers/me4000.c
@@ -61,20 +61,6 @@ broken.
 #include "me4000_fw.h"
 #endif
 
-#define PCI_DEVICE_ID_MEILHAUS_ME4650	0x4650
-#define PCI_DEVICE_ID_MEILHAUS_ME4660	0x4660
-#define PCI_DEVICE_ID_MEILHAUS_ME4660I	0x4661
-#define PCI_DEVICE_ID_MEILHAUS_ME4660S	0x4662
-#define PCI_DEVICE_ID_MEILHAUS_ME4660IS	0x4663
-#define PCI_DEVICE_ID_MEILHAUS_ME4670	0x4670
-#define PCI_DEVICE_ID_MEILHAUS_ME4670I	0x4671
-#define PCI_DEVICE_ID_MEILHAUS_ME4670S	0x4672
-#define PCI_DEVICE_ID_MEILHAUS_ME4670IS	0x4673
-#define PCI_DEVICE_ID_MEILHAUS_ME4680	0x4680
-#define PCI_DEVICE_ID_MEILHAUS_ME4680I	0x4681
-#define PCI_DEVICE_ID_MEILHAUS_ME4680S	0x4682
-#define PCI_DEVICE_ID_MEILHAUS_ME4680IS	0x4683
-
 /*
  * ME4000 Register map and bit defines
  */
@@ -220,9 +206,24 @@ struct me4000_info {
 	unsigned int ao_readback[4];
 };
 
+enum me4000_boardid {
+	BOARD_ME4650,
+	BOARD_ME4660,
+	BOARD_ME4660I,
+	BOARD_ME4660S,
+	BOARD_ME4660IS,
+	BOARD_ME4670,
+	BOARD_ME4670I,
+	BOARD_ME4670S,
+	BOARD_ME4670IS,
+	BOARD_ME4680,
+	BOARD_ME4680I,
+	BOARD_ME4680S,
+	BOARD_ME4680IS,
+};
+
 struct me4000_board {
 	const char *name;
-	unsigned short device_id;
 	int ao_nchan;
 	int ao_fifo;
 	int ai_nchan;
@@ -234,62 +235,61 @@ struct me4000_board {
 };
 
 static const struct me4000_board me4000_boards[] = {
-	{
+	[BOARD_ME4650] = {
 		.name		= "ME-4650",
-		.device_id	= PCI_DEVICE_ID_MEILHAUS_ME4650,
 		.ai_nchan	= 16,
 		.dio_nchan	= 32,
-	}, {
+	},
+	[BOARD_ME4660] = {
 		.name		= "ME-4660",
-		.device_id	= PCI_DEVICE_ID_MEILHAUS_ME4660,
 		.ai_nchan	= 32,
 		.ai_diff_nchan	= 16,
 		.dio_nchan	= 32,
 		.has_counter	= 1,
-	}, {
+	},
+	[BOARD_ME4660I] = {
 		.name		= "ME-4660i",
-		.device_id	= PCI_DEVICE_ID_MEILHAUS_ME4660I,
 		.ai_nchan	= 32,
 		.ai_diff_nchan	= 16,
 		.dio_nchan	= 32,
 		.has_counter	= 1,
-	}, {
+	},
+	[BOARD_ME4660S] = {
 		.name		= "ME-4660s",
-		.device_id	= PCI_DEVICE_ID_MEILHAUS_ME4660S,
 		.ai_nchan	= 32,
 		.ai_diff_nchan	= 16,
 		.ai_sh_nchan	= 8,
 		.dio_nchan	= 32,
 		.has_counter	= 1,
-	}, {
+	},
+	[BOARD_ME4660IS] = {
 		.name		= "ME-4660is",
-		.device_id	= PCI_DEVICE_ID_MEILHAUS_ME4660IS,
 		.ai_nchan	= 32,
 		.ai_diff_nchan	= 16,
 		.ai_sh_nchan	= 8,
 		.dio_nchan	= 32,
 		.has_counter	= 1,
-	}, {
+	},
+	[BOARD_ME4670] = {
 		.name		= "ME-4670",
-		.device_id	= PCI_DEVICE_ID_MEILHAUS_ME4670,
 		.ao_nchan	= 4,
 		.ai_nchan	= 32,
 		.ai_diff_nchan	= 16,
 		.ex_trig_analog	= 1,
 		.dio_nchan	= 32,
 		.has_counter	= 1,
-	}, {
+	},
+	[BOARD_ME4670I] = {
 		.name		= "ME-4670i",
-		.device_id	= PCI_DEVICE_ID_MEILHAUS_ME4670I,
 		.ao_nchan	= 4,
 		.ai_nchan	= 32,
 		.ai_diff_nchan	= 16,
 		.ex_trig_analog	= 1,
 		.dio_nchan	= 32,
 		.has_counter	= 1,
-	}, {
+	},
+	[BOARD_ME4670S] = {
 		.name		= "ME-4670s",
-		.device_id	= PCI_DEVICE_ID_MEILHAUS_ME4670S,
 		.ao_nchan	= 4,
 		.ai_nchan	= 32,
 		.ai_diff_nchan	= 16,
@@ -297,9 +297,9 @@ static const struct me4000_board me4000_boards[] = {
 		.ex_trig_analog	= 1,
 		.dio_nchan	= 32,
 		.has_counter	= 1,
-	}, {
+	},
+	[BOARD_ME4670IS] = {
 		.name		= "ME-4670is",
-		.device_id	= PCI_DEVICE_ID_MEILHAUS_ME4670IS,
 		.ao_nchan	= 4,
 		.ai_nchan	= 32,
 		.ai_diff_nchan	= 16,
@@ -307,9 +307,9 @@ static const struct me4000_board me4000_boards[] = {
 		.ex_trig_analog	= 1,
 		.dio_nchan	= 32,
 		.has_counter	= 1,
-	}, {
+	},
+	[BOARD_ME4680] = {
 		.name		= "ME-4680",
-		.device_id	= PCI_DEVICE_ID_MEILHAUS_ME4680,
 		.ao_nchan	= 4,
 		.ao_fifo	= 4,
 		.ai_nchan	= 32,
@@ -317,9 +317,9 @@ static const struct me4000_board me4000_boards[] = {
 		.ex_trig_analog	= 1,
 		.dio_nchan	= 32,
 		.has_counter	= 1,
-	}, {
+	},
+	[BOARD_ME4680I] = {
 		.name		= "ME-4680i",
-		.device_id	= PCI_DEVICE_ID_MEILHAUS_ME4680I,
 		.ao_nchan	= 4,
 		.ao_fifo	= 4,
 		.ai_nchan	= 32,
@@ -327,9 +327,9 @@ static const struct me4000_board me4000_boards[] = {
 		.ex_trig_analog	= 1,
 		.dio_nchan	= 32,
 		.has_counter	= 1,
-	}, {
+	},
+	[BOARD_ME4680S] = {
 		.name		= "ME-4680s",
-		.device_id	= PCI_DEVICE_ID_MEILHAUS_ME4680S,
 		.ao_nchan	= 4,
 		.ao_fifo	= 4,
 		.ai_nchan	= 32,
@@ -338,9 +338,9 @@ static const struct me4000_board me4000_boards[] = {
 		.ex_trig_analog	= 1,
 		.dio_nchan	= 32,
 		.has_counter	= 1,
-	}, {
+	},
+	[BOARD_ME4680IS] = {
 		.name		= "ME-4680is",
-		.device_id	= PCI_DEVICE_ID_MEILHAUS_ME4680IS,
 		.ao_nchan	= 4,
 		.ao_fifo	= 4,
 		.ai_nchan	= 32,
@@ -1550,30 +1550,17 @@ static int me4000_cnt_insn_write(struct comedi_device *dev,
 	return 1;
 }
 
-static const void *me4000_find_boardinfo(struct comedi_device *dev,
-					 struct pci_dev *pcidev)
-{
-	const struct me4000_board *thisboard;
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(me4000_boards); i++) {
-		thisboard = &me4000_boards[i];
-		if (thisboard->device_id == pcidev->device)
-			return thisboard;
-	}
-	return NULL;
-}
-
 static int me4000_auto_attach(struct comedi_device *dev,
-					unsigned long context_unused)
+			      unsigned long context)
 {
 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-	const struct me4000_board *thisboard;
+	const struct me4000_board *thisboard = NULL;
 	struct me4000_info *info;
 	struct comedi_subdevice *s;
 	int result;
 
-	thisboard = me4000_find_boardinfo(dev, pcidev);
+	if (context < ARRAY_SIZE(me4000_boards))
+		thisboard = &me4000_boards[context];
 	if (!thisboard)
 		return -ENODEV;
 	dev->board_ptr = thisboard;
@@ -1584,7 +1571,7 @@ static int me4000_auto_attach(struct comedi_device *dev,
 		return -ENOMEM;
 	dev->private = info;
 
-	result = comedi_pci_enable(pcidev, dev->board_name);
+	result = comedi_pci_enable(dev);
 	if (result)
 		return result;
 
@@ -1710,16 +1697,11 @@ static int me4000_auto_attach(struct comedi_device *dev,
 
 static void me4000_detach(struct comedi_device *dev)
 {
-	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-
 	if (dev->irq)
 		free_irq(dev->irq, dev);
-	if (pcidev) {
-		if (dev->iobase) {
-			me4000_reset(dev);
-			comedi_pci_disable(pcidev);
-		}
-	}
+	if (dev->iobase)
+		me4000_reset(dev);
+	comedi_pci_disable(dev);
 }
 
 static struct comedi_driver me4000_driver = {
@@ -1730,26 +1712,26 @@ static struct comedi_driver me4000_driver = {
 };
 
 static int me4000_pci_probe(struct pci_dev *dev,
-				      const struct pci_device_id *ent)
+			    const struct pci_device_id *id)
 {
-	return comedi_pci_auto_config(dev, &me4000_driver);
+	return comedi_pci_auto_config(dev, &me4000_driver, id->driver_data);
 }
 
 static DEFINE_PCI_DEVICE_TABLE(me4000_pci_table) = {
-	{PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4650)},
-	{PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4660)},
-	{PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4660I)},
-	{PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4660S)},
-	{PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4660IS)},
-	{PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670)},
-	{PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670I)},
-	{PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670S)},
-	{PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670IS)},
-	{PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680)},
-	{PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680I)},
-	{PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680S)},
-	{PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680IS)},
-	{0}
+	{ PCI_VDEVICE(MEILHAUS, 0x4650), BOARD_ME4650 },
+	{ PCI_VDEVICE(MEILHAUS, 0x4660), BOARD_ME4660 },
+	{ PCI_VDEVICE(MEILHAUS, 0x4661), BOARD_ME4660I },
+	{ PCI_VDEVICE(MEILHAUS, 0x4662), BOARD_ME4660S },
+	{ PCI_VDEVICE(MEILHAUS, 0x4663), BOARD_ME4660IS },
+	{ PCI_VDEVICE(MEILHAUS, 0x4670), BOARD_ME4670 },
+	{ PCI_VDEVICE(MEILHAUS, 0x4671), BOARD_ME4670I },
+	{ PCI_VDEVICE(MEILHAUS, 0x4672), BOARD_ME4670S },
+	{ PCI_VDEVICE(MEILHAUS, 0x4673), BOARD_ME4670IS },
+	{ PCI_VDEVICE(MEILHAUS, 0x4680), BOARD_ME4680 },
+	{ PCI_VDEVICE(MEILHAUS, 0x4681), BOARD_ME4680I },
+	{ PCI_VDEVICE(MEILHAUS, 0x4682), BOARD_ME4680S },
+	{ PCI_VDEVICE(MEILHAUS, 0x4683), BOARD_ME4680IS },
+	{ 0 }
 };
 MODULE_DEVICE_TABLE(pci, me4000_pci_table);
 
diff --git a/drivers/staging/comedi/drivers/me_daq.c b/drivers/staging/comedi/drivers/me_daq.c
index 06490eb..5df4f55 100644
--- a/drivers/staging/comedi/drivers/me_daq.c
+++ b/drivers/staging/comedi/drivers/me_daq.c
@@ -43,9 +43,6 @@
 
 #define ME2600_FIRMWARE		"me2600_firmware.bin"
 
-#define ME2000_DEVICE_ID	0x2000
-#define ME2600_DEVICE_ID	0x2600
-
 #define PLX_INTCSR		0x4C	/* PLX interrupt status register */
 #define XILINX_DOWNLOAD_RESET	0x42	/* Xilinx registers */
 
@@ -149,21 +146,26 @@ static const struct comedi_lrange me_ao_range = {
 	}
 };
 
+enum me_boardid {
+	BOARD_ME2600,
+	BOARD_ME2000,
+};
+
 struct me_board {
 	const char *name;
-	int device_id;
+	int needs_firmware;
 	int has_ao;
 };
 
 static const struct me_board me_boards[] = {
-	{
+	[BOARD_ME2600] = {
 		.name		= "me-2600i",
-		.device_id	= ME2600_DEVICE_ID,
+		.needs_firmware	= 1,
 		.has_ao		= 1,
-	}, {
+	},
+	[BOARD_ME2000] = {
 		.name		= "me-2000i",
-		.device_id	= ME2000_DEVICE_ID,
-	}
+	},
 };
 
 struct me_private_data {
@@ -426,7 +428,7 @@ static int me2600_xilinx_download(struct comedi_device *dev,
 
 	/*
 	 * Loop for writing firmware byte by byte to xilinx
-	 * Firmware data start at offfset 16
+	 * Firmware data start at offset 16
 	 */
 	for (i = 0; i < file_length; i++)
 		writeb((data[16 + i] & 0xff),
@@ -488,30 +490,17 @@ static int me_reset(struct comedi_device *dev)
 	return 0;
 }
 
-static const void *me_find_boardinfo(struct comedi_device *dev,
-				     struct pci_dev *pcidev)
-{
-	const struct me_board *board;
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(me_boards); i++) {
-		board = &me_boards[i];
-		if (board->device_id == pcidev->device)
-			return board;
-	}
-	return NULL;
-}
-
 static int me_auto_attach(struct comedi_device *dev,
-				    unsigned long context_unused)
+			  unsigned long context)
 {
 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-	const struct me_board *board;
+	const struct me_board *board = NULL;
 	struct me_private_data *dev_private;
 	struct comedi_subdevice *s;
 	int ret;
 
-	board = me_find_boardinfo(dev, pcidev);
+	if (context < ARRAY_SIZE(me_boards))
+		board = &me_boards[context];
 	if (!board)
 		return -ENODEV;
 	dev->board_ptr = board;
@@ -522,10 +511,9 @@ static int me_auto_attach(struct comedi_device *dev,
 		return -ENOMEM;
 	dev->private = dev_private;
 
-	ret = comedi_pci_enable(pcidev, dev->board_name);
+	ret = comedi_pci_enable(dev);
 	if (ret)
 		return ret;
-	dev->iobase = 1;	/* detach needs this */
 
 	dev_private->plx_regbase = ioremap(pci_resource_start(pcidev, 0),
 					   pci_resource_len(pcidev, 0));
@@ -538,7 +526,7 @@ static int me_auto_attach(struct comedi_device *dev,
 		return -ENOMEM;
 
 	/* Download firmware and reset card */
-	if (board->device_id == ME2600_DEVICE_ID) {
+	if (board->needs_firmware) {
 		ret = me2600_upload_firmware(dev);
 		if (ret < 0)
 			return ret;
@@ -591,7 +579,6 @@ static int me_auto_attach(struct comedi_device *dev,
 
 static void me_detach(struct comedi_device *dev)
 {
-	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
 	struct me_private_data *dev_private = dev->private;
 
 	if (dev_private) {
@@ -602,10 +589,7 @@ static void me_detach(struct comedi_device *dev)
 		if (dev_private->plx_regbase)
 			iounmap(dev_private->plx_regbase);
 	}
-	if (pcidev) {
-		if (dev->iobase)
-			comedi_pci_disable(pcidev);
-	}
+	comedi_pci_disable(dev);
 }
 
 static struct comedi_driver me_daq_driver = {
@@ -616,14 +600,14 @@ static struct comedi_driver me_daq_driver = {
 };
 
 static int me_daq_pci_probe(struct pci_dev *dev,
-				      const struct pci_device_id *ent)
+			    const struct pci_device_id *id)
 {
-	return comedi_pci_auto_config(dev, &me_daq_driver);
+	return comedi_pci_auto_config(dev, &me_daq_driver, id->driver_data);
 }
 
 static DEFINE_PCI_DEVICE_TABLE(me_daq_pci_table) = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, ME2600_DEVICE_ID) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, ME2000_DEVICE_ID) },
+	{ PCI_VDEVICE(MEILHAUS, 0x2600), BOARD_ME2600 },
+	{ PCI_VDEVICE(MEILHAUS, 0x2000), BOARD_ME2000 },
 	{ 0 }
 };
 MODULE_DEVICE_TABLE(pci, me_daq_pci_table);
diff --git a/drivers/staging/comedi/drivers/mite.c b/drivers/staging/comedi/drivers/mite.c
index be2c15f..9a45662 100644
--- a/drivers/staging/comedi/drivers/mite.c
+++ b/drivers/staging/comedi/drivers/mite.c
@@ -109,11 +109,6 @@ int mite_setup2(struct mite_struct *mite, unsigned use_iodwbsr_1)
 	u32 csigr_bits;
 	unsigned unknown_dma_burst_bits;
 
-	if (comedi_pci_enable(mite->pcidev, "mite")) {
-		dev_err(&mite->pcidev->dev,
-			"error enabling mite and requesting io regions\n");
-		return -EIO;
-	}
 	pci_set_master(mite->pcidev);
 
 	addr = pci_resource_start(mite->pcidev, 0);
@@ -208,10 +203,8 @@ void mite_unsetup(struct mite_struct *mite)
 		iounmap(mite->daq_io_addr);
 		mite->daq_io_addr = NULL;
 	}
-	if (mite->mite_phys_addr) {
-		comedi_pci_disable(mite->pcidev);
+	if (mite->mite_phys_addr)
 		mite->mite_phys_addr = 0;
-	}
 }
 EXPORT_SYMBOL(mite_unsetup);
 
diff --git a/drivers/staging/comedi/drivers/ni_6527.c b/drivers/staging/comedi/drivers/ni_6527.c
index bcd4df2..d10f777 100644
--- a/drivers/staging/comedi/drivers/ni_6527.c
+++ b/drivers/staging/comedi/drivers/ni_6527.c
@@ -81,33 +81,24 @@ Updated: Sat, 25 Jan 2003 13:24:40 -0800
 #define Rising_Edge_Detection_Enable(x)		(0x018+(x))
 #define Falling_Edge_Detection_Enable(x)	(0x020+(x))
 
-struct ni6527_board {
+enum ni6527_boardid {
+	BOARD_PCI6527,
+	BOARD_PXI6527,
+};
 
-	int dev_id;
+struct ni6527_board {
 	const char *name;
 };
 
 static const struct ni6527_board ni6527_boards[] = {
-	{
-	 .dev_id = 0x2b20,
-	 .name = "pci-6527",
-	 },
-	{
-	 .dev_id = 0x2b10,
-	 .name = "pxi-6527",
-	 },
-};
-
-#define this_board ((const struct ni6527_board *)dev->board_ptr)
-
-static DEFINE_PCI_DEVICE_TABLE(ni6527_pci_table) = {
-	{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2b10)},
-	{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2b20)},
-	{0}
+	[BOARD_PCI6527] = {
+		.name		= "pci-6527",
+	},
+	[BOARD_PXI6527] = {
+		.name		= "pxi-6527",
+	},
 };
 
-MODULE_DEVICE_TABLE(pci, ni6527_pci_table);
-
 struct ni6527_private {
 	struct mite_struct *mite;
 	unsigned int filter_interval;
@@ -329,37 +320,31 @@ static int ni6527_intr_insn_config(struct comedi_device *dev,
 	return 2;
 }
 
-static const struct ni6527_board *
-ni6527_find_boardinfo(struct pci_dev *pcidev)
-{
-	unsigned int dev_id = pcidev->device;
-	unsigned int n;
-
-	for (n = 0; n < ARRAY_SIZE(ni6527_boards); n++) {
-		const struct ni6527_board *board = &ni6527_boards[n];
-		if (board->dev_id == dev_id)
-			return board;
-	}
-	return NULL;
-}
-
 static int ni6527_auto_attach(struct comedi_device *dev,
-					unsigned long context_unused)
+			      unsigned long context)
 {
 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+	const struct ni6527_board *board = NULL;
 	struct ni6527_private *devpriv;
 	struct comedi_subdevice *s;
 	int ret;
 
+	if (context < ARRAY_SIZE(ni6527_boards))
+		board = &ni6527_boards[context];
+	if (!board)
+		return -ENODEV;
+	dev->board_ptr = board;
+	dev->board_name = board->name;
+
+	ret = comedi_pci_enable(dev);
+	if (ret)
+		return ret;
+
 	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
 	if (!devpriv)
 		return -ENOMEM;
 	dev->private = devpriv;
 
-	dev->board_ptr = ni6527_find_boardinfo(pcidev);
-	if (!dev->board_ptr)
-		return -ENODEV;
-
 	devpriv->mite = mite_alloc(pcidev);
 	if (!devpriv->mite)
 		return -ENOMEM;
@@ -370,7 +355,6 @@ static int ni6527_auto_attach(struct comedi_device *dev,
 		return ret;
 	}
 
-	dev->board_name = this_board->name;
 	dev_info(dev->class_dev, "board: %s, ID=0x%02x\n", dev->board_name,
 		 readb(devpriv->mite->daq_io_addr + ID_Register));
 
@@ -439,6 +423,7 @@ static void ni6527_detach(struct comedi_device *dev)
 		mite_unsetup(devpriv->mite);
 		mite_free(devpriv->mite);
 	}
+	comedi_pci_disable(dev);
 }
 
 static struct comedi_driver ni6527_driver = {
@@ -449,15 +434,22 @@ static struct comedi_driver ni6527_driver = {
 };
 
 static int ni6527_pci_probe(struct pci_dev *dev,
-				      const struct pci_device_id *ent)
+			    const struct pci_device_id *id)
 {
-	return comedi_pci_auto_config(dev, &ni6527_driver);
+	return comedi_pci_auto_config(dev, &ni6527_driver, id->driver_data);
 }
 
+static DEFINE_PCI_DEVICE_TABLE(ni6527_pci_table) = {
+	{ PCI_VDEVICE(NI, 0x2b10), BOARD_PXI6527 },
+	{ PCI_VDEVICE(NI, 0x2b20), BOARD_PCI6527 },
+	{ 0 }
+};
+MODULE_DEVICE_TABLE(pci, ni6527_pci_table);
+
 static struct pci_driver ni6527_pci_driver = {
-	.name = DRIVER_NAME,
-	.id_table = ni6527_pci_table,
-	.probe = ni6527_pci_probe,
+	.name		= DRIVER_NAME,
+	.id_table	= ni6527_pci_table,
+	.probe		= ni6527_pci_probe,
 	.remove		= comedi_pci_auto_unconfig,
 };
 module_comedi_pci_driver(ni6527_driver, ni6527_pci_driver);
diff --git a/drivers/staging/comedi/drivers/ni_65xx.c b/drivers/staging/comedi/drivers/ni_65xx.c
index bfa790e..013392c 100644
--- a/drivers/staging/comedi/drivers/ni_65xx.c
+++ b/drivers/staging/comedi/drivers/ni_65xx.c
@@ -112,8 +112,32 @@ static inline unsigned Filter_Enable(unsigned port)
 #define OverflowIntEnable		0x02
 #define EdgeIntEnable			0x01
 
+enum ni_65xx_boardid {
+	BOARD_PCI6509,
+	BOARD_PXI6509,
+	BOARD_PCI6510,
+	BOARD_PCI6511,
+	BOARD_PXI6511,
+	BOARD_PCI6512,
+	BOARD_PXI6512,
+	BOARD_PCI6513,
+	BOARD_PXI6513,
+	BOARD_PCI6514,
+	BOARD_PXI6514,
+	BOARD_PCI6515,
+	BOARD_PXI6515,
+	BOARD_PCI6516,
+	BOARD_PCI6517,
+	BOARD_PCI6518,
+	BOARD_PCI6519,
+	BOARD_PCI6520,
+	BOARD_PCI6521,
+	BOARD_PXI6521,
+	BOARD_PCI6528,
+	BOARD_PXI6528,
+};
+
 struct ni_65xx_board {
-	int dev_id;
 	const char *name;
 	unsigned num_dio_ports;
 	unsigned num_di_ports;
@@ -122,130 +146,117 @@ struct ni_65xx_board {
 };
 
 static const struct ni_65xx_board ni_65xx_boards[] = {
-	{
-	 .dev_id = 0x7085,
-	 .name = "pci-6509",
-	 .num_dio_ports = 12,
-	 .invert_outputs = 0},
-	{
-	 .dev_id = 0x1710,
-	 .name = "pxi-6509",
-	 .num_dio_ports = 12,
-	 .invert_outputs = 0},
-	{
-	 .dev_id = 0x7124,
-	 .name = "pci-6510",
-	 .num_di_ports = 4},
-	{
-	 .dev_id = 0x70c3,
-	 .name = "pci-6511",
-	 .num_di_ports = 8},
-	{
-	 .dev_id = 0x70d3,
-	 .name = "pxi-6511",
-	 .num_di_ports = 8},
-	{
-	 .dev_id = 0x70cc,
-	 .name = "pci-6512",
-	 .num_do_ports = 8},
-	{
-	 .dev_id = 0x70d2,
-	 .name = "pxi-6512",
-	 .num_do_ports = 8},
-	{
-	 .dev_id = 0x70c8,
-	 .name = "pci-6513",
-	 .num_do_ports = 8,
-	 .invert_outputs = 1},
-	{
-	 .dev_id = 0x70d1,
-	 .name = "pxi-6513",
-	 .num_do_ports = 8,
-	 .invert_outputs = 1},
-	{
-	 .dev_id = 0x7088,
-	 .name = "pci-6514",
-	 .num_di_ports = 4,
-	 .num_do_ports = 4,
-	 .invert_outputs = 1},
-	{
-	 .dev_id = 0x70CD,
-	 .name = "pxi-6514",
-	 .num_di_ports = 4,
-	 .num_do_ports = 4,
-	 .invert_outputs = 1},
-	{
-	 .dev_id = 0x7087,
-	 .name = "pci-6515",
-	 .num_di_ports = 4,
-	 .num_do_ports = 4,
-	 .invert_outputs = 1},
-	{
-	 .dev_id = 0x70c9,
-	 .name = "pxi-6515",
-	 .num_di_ports = 4,
-	 .num_do_ports = 4,
-	 .invert_outputs = 1},
-	{
-	 .dev_id = 0x7125,
-	 .name = "pci-6516",
-	 .num_do_ports = 4,
-	 .invert_outputs = 1},
-	{
-	 .dev_id = 0x7126,
-	 .name = "pci-6517",
-	 .num_do_ports = 4,
-	 .invert_outputs = 1},
-	{
-	 .dev_id = 0x7127,
-	 .name = "pci-6518",
-	 .num_di_ports = 2,
-	 .num_do_ports = 2,
-	 .invert_outputs = 1},
-	{
-	 .dev_id = 0x7128,
-	 .name = "pci-6519",
-	 .num_di_ports = 2,
-	 .num_do_ports = 2,
-	 .invert_outputs = 1},
-	{
-	 .dev_id = 0x71c5,
-	 .name = "pci-6520",
-	 .num_di_ports = 1,
-	 .num_do_ports = 1,
-	 },
-	{
-	 .dev_id = 0x718b,
-	 .name = "pci-6521",
-	 .num_di_ports = 1,
-	 .num_do_ports = 1,
-	 },
-	{
-	 .dev_id = 0x718c,
-	 .name = "pxi-6521",
-	 .num_di_ports = 1,
-	 .num_do_ports = 1,
-	 },
-	{
-	 .dev_id = 0x70a9,
-	 .name = "pci-6528",
-	 .num_di_ports = 3,
-	 .num_do_ports = 3,
-	 },
-	{
-	 .dev_id = 0x7086,
-	 .name = "pxi-6528",
-	 .num_di_ports = 3,
-	 .num_do_ports = 3,
-	 },
+	[BOARD_PCI6509] = {
+		.name		= "pci-6509",
+		.num_dio_ports	= 12,
+	},
+	[BOARD_PXI6509] = {
+		.name		= "pxi-6509",
+		.num_dio_ports	= 12,
+	},
+	[BOARD_PCI6510] = {
+		.name		= "pci-6510",
+		.num_di_ports	= 4,
+	},
+	[BOARD_PCI6511] = {
+		.name		= "pci-6511",
+		.num_di_ports	= 8,
+	},
+	[BOARD_PXI6511] = {
+		.name		= "pxi-6511",
+		.num_di_ports	= 8,
+	},
+	[BOARD_PCI6512] = {
+		.name		= "pci-6512",
+		.num_do_ports	= 8,
+	},
+	[BOARD_PXI6512] = {
+		.name		= "pxi-6512",
+		.num_do_ports	= 8,
+	},
+	[BOARD_PCI6513] = {
+		.name		= "pci-6513",
+		.num_do_ports	= 8,
+		.invert_outputs	= 1,
+	},
+	[BOARD_PXI6513] = {
+		.name		= "pxi-6513",
+		.num_do_ports	= 8,
+		.invert_outputs	= 1,
+	},
+	[BOARD_PCI6514] = {
+		.name		= "pci-6514",
+		.num_di_ports	= 4,
+		.num_do_ports	= 4,
+		.invert_outputs	= 1,
+	},
+	[BOARD_PXI6514] = {
+		.name		= "pxi-6514",
+		.num_di_ports	= 4,
+		.num_do_ports	= 4,
+		.invert_outputs	= 1,
+	},
+	[BOARD_PCI6515] = {
+		.name		= "pci-6515",
+		.num_di_ports	= 4,
+		.num_do_ports	= 4,
+		.invert_outputs	= 1,
+	},
+	[BOARD_PXI6515] = {
+		.name		= "pxi-6515",
+		.num_di_ports	= 4,
+		.num_do_ports	= 4,
+		.invert_outputs	= 1,
+	},
+	[BOARD_PCI6516] = {
+		.name		= "pci-6516",
+		.num_do_ports	= 4,
+		.invert_outputs	= 1,
+	},
+	[BOARD_PCI6517] = {
+		.name		= "pci-6517",
+		.num_do_ports	= 4,
+		.invert_outputs	= 1,
+	},
+	[BOARD_PCI6518] = {
+		.name		= "pci-6518",
+		.num_di_ports	= 2,
+		.num_do_ports	= 2,
+		.invert_outputs	= 1,
+	},
+	[BOARD_PCI6519] = {
+		.name		= "pci-6519",
+		.num_di_ports	= 2,
+		.num_do_ports	= 2,
+		.invert_outputs	= 1,
+	},
+	[BOARD_PCI6520] = {
+		.name		= "pci-6520",
+		.num_di_ports	= 1,
+		.num_do_ports	= 1,
+	},
+	[BOARD_PCI6521] = {
+		.name		= "pci-6521",
+		.num_di_ports	= 1,
+		.num_do_ports	= 1,
+	},
+	[BOARD_PXI6521] = {
+		.name		= "pxi-6521",
+		.num_di_ports	= 1,
+		.num_do_ports	= 1,
+	},
+	[BOARD_PCI6528] = {
+		.name		= "pci-6528",
+		.num_di_ports	= 3,
+		.num_do_ports	= 3,
+	},
+	[BOARD_PXI6528] = {
+		.name		= "pxi-6528",
+		.num_di_ports	= 3,
+		.num_do_ports	= 3,
+	},
 };
 
-#define n_ni_65xx_boards ARRAY_SIZE(ni_65xx_boards)
-static inline const struct ni_65xx_board *board(struct comedi_device *dev)
-{
-	return dev->board_ptr;
-}
-
 static inline unsigned ni_65xx_port_by_channel(unsigned channel)
 {
 	return channel / ni_65xx_channels_per_port;
@@ -257,34 +268,6 @@ static inline unsigned ni_65xx_total_num_ports(const struct ni_65xx_board
 	return board->num_dio_ports + board->num_di_ports + board->num_do_ports;
 }
 
-static DEFINE_PCI_DEVICE_TABLE(ni_65xx_pci_table) = {
-	{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1710)},
-	{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x7085)},
-	{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x7086)},
-	{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x7087)},
-	{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x7088)},
-	{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70a9)},
-	{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70c3)},
-	{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70c8)},
-	{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70c9)},
-	{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70cc)},
-	{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70CD)},
-	{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70d1)},
-	{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70d2)},
-	{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70d3)},
-	{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x7124)},
-	{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x7125)},
-	{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x7126)},
-	{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x7127)},
-	{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x7128)},
-	{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x718b)},
-	{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x718c)},
-	{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x71c5)},
-	{0}
-};
-
-MODULE_DEVICE_TABLE(pci, ni_65xx_pci_table);
-
 struct ni_65xx_private {
 	struct mite_struct *mite;
 	unsigned int filter_interval;
@@ -398,6 +381,7 @@ static int ni_65xx_dio_insn_bits(struct comedi_device *dev,
 				 struct comedi_subdevice *s,
 				 struct comedi_insn *insn, unsigned int *data)
 {
+	const struct ni_65xx_board *board = comedi_board(dev);
 	struct ni_65xx_private *devpriv = dev->private;
 	unsigned base_bitfield_channel;
 	const unsigned max_ports_per_bitfield = 5;
@@ -413,7 +397,7 @@ static int ni_65xx_dio_insn_bits(struct comedi_device *dev,
 		unsigned base_port_channel;
 		unsigned port_mask, port_data, port_read_bits;
 		int bitshift;
-		if (port >= ni_65xx_total_num_ports(board(dev)))
+		if (port >= ni_65xx_total_num_ports(board))
 			break;
 		base_port_channel = port_offset * ni_65xx_channels_per_port;
 		port_mask = data[0];
@@ -436,7 +420,7 @@ static int ni_65xx_dio_insn_bits(struct comedi_device *dev,
 			devpriv->output_bits[port] |=
 			    port_data & port_mask;
 			bits = devpriv->output_bits[port];
-			if (board(dev)->invert_outputs)
+			if (board->invert_outputs)
 				bits = ~bits;
 			writeb(bits,
 			       devpriv->mite->daq_io_addr +
@@ -444,7 +428,7 @@ static int ni_65xx_dio_insn_bits(struct comedi_device *dev,
 		}
 		port_read_bits =
 		    readb(devpriv->mite->daq_io_addr + Port_Data(port));
-		if (s->type == COMEDI_SUBD_DO && board(dev)->invert_outputs) {
+		if (s->type == COMEDI_SUBD_DO && board->invert_outputs) {
 			/* Outputs inverted, so invert value read back from
 			 * DO subdevice.  (Does not apply to boards with DIO
 			 * subdevice.) */
@@ -599,38 +583,32 @@ static int ni_65xx_intr_insn_config(struct comedi_device *dev,
 	return 2;
 }
 
-static const struct ni_65xx_board *
-ni_65xx_find_boardinfo(struct pci_dev *pcidev)
-{
-	unsigned int dev_id = pcidev->device;
-	unsigned int n;
-
-	for (n = 0; n < ARRAY_SIZE(ni_65xx_boards); n++) {
-		const struct ni_65xx_board *board = &ni_65xx_boards[n];
-		if (board->dev_id == dev_id)
-			return board;
-	}
-	return NULL;
-}
-
 static int ni_65xx_auto_attach(struct comedi_device *dev,
-					 unsigned long context_unused)
+			       unsigned long context)
 {
 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+	const struct ni_65xx_board *board = NULL;
 	struct ni_65xx_private *devpriv;
 	struct comedi_subdevice *s;
 	unsigned i;
 	int ret;
 
+	if (context < ARRAY_SIZE(ni_65xx_boards))
+		board = &ni_65xx_boards[context];
+	if (!board)
+		return -ENODEV;
+	dev->board_ptr = board;
+	dev->board_name = board->name;
+
+	ret = comedi_pci_enable(dev);
+	if (ret)
+		return ret;
+
 	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
 	if (!devpriv)
 		return -ENOMEM;
 	dev->private = devpriv;
 
-	dev->board_ptr = ni_65xx_find_boardinfo(pcidev);
-	if (!dev->board_ptr)
-		return -ENODEV;
-
 	devpriv->mite = mite_alloc(pcidev);
 	if (!devpriv->mite)
 		return -ENOMEM;
@@ -641,7 +619,6 @@ static int ni_65xx_auto_attach(struct comedi_device *dev,
 		return ret;
 	}
 
-	dev->board_name = board(dev)->name;
 	dev->irq = mite_irq(devpriv->mite);
 	dev_info(dev->class_dev, "board: %s, ID=0x%02x", dev->board_name,
 	       readb(devpriv->mite->daq_io_addr + ID_Register));
@@ -651,11 +628,11 @@ static int ni_65xx_auto_attach(struct comedi_device *dev,
 		return ret;
 
 	s = &dev->subdevices[0];
-	if (board(dev)->num_di_ports) {
+	if (board->num_di_ports) {
 		s->type = COMEDI_SUBD_DI;
 		s->subdev_flags = SDF_READABLE;
 		s->n_chan =
-		    board(dev)->num_di_ports * ni_65xx_channels_per_port;
+		    board->num_di_ports * ni_65xx_channels_per_port;
 		s->range_table = &range_digital;
 		s->maxdata = 1;
 		s->insn_config = ni_65xx_dio_insn_config;
@@ -669,28 +646,28 @@ static int ni_65xx_auto_attach(struct comedi_device *dev,
 	}
 
 	s = &dev->subdevices[1];
-	if (board(dev)->num_do_ports) {
+	if (board->num_do_ports) {
 		s->type = COMEDI_SUBD_DO;
 		s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
 		s->n_chan =
-		    board(dev)->num_do_ports * ni_65xx_channels_per_port;
+		    board->num_do_ports * ni_65xx_channels_per_port;
 		s->range_table = &range_digital;
 		s->maxdata = 1;
 		s->insn_bits = ni_65xx_dio_insn_bits;
 		s->private = ni_65xx_alloc_subdevice_private();
 		if (s->private == NULL)
 			return -ENOMEM;
-		sprivate(s)->base_port = board(dev)->num_di_ports;
+		sprivate(s)->base_port = board->num_di_ports;
 	} else {
 		s->type = COMEDI_SUBD_UNUSED;
 	}
 
 	s = &dev->subdevices[2];
-	if (board(dev)->num_dio_ports) {
+	if (board->num_dio_ports) {
 		s->type = COMEDI_SUBD_DIO;
 		s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
 		s->n_chan =
-		    board(dev)->num_dio_ports * ni_65xx_channels_per_port;
+		    board->num_dio_ports * ni_65xx_channels_per_port;
 		s->range_table = &range_digital;
 		s->maxdata = 1;
 		s->insn_config = ni_65xx_dio_insn_config;
@@ -699,7 +676,7 @@ static int ni_65xx_auto_attach(struct comedi_device *dev,
 		if (s->private == NULL)
 			return -ENOMEM;
 		sprivate(s)->base_port = 0;
-		for (i = 0; i < board(dev)->num_dio_ports; ++i) {
+		for (i = 0; i < board->num_dio_ports; ++i) {
 			/*  configure all ports for input */
 			writeb(0x1,
 			       devpriv->mite->daq_io_addr +
@@ -722,10 +699,10 @@ static int ni_65xx_auto_attach(struct comedi_device *dev,
 	s->insn_bits = ni_65xx_intr_insn_bits;
 	s->insn_config = ni_65xx_intr_insn_config;
 
-	for (i = 0; i < ni_65xx_total_num_ports(board(dev)); ++i) {
+	for (i = 0; i < ni_65xx_total_num_ports(board); ++i) {
 		writeb(0x00,
 		       devpriv->mite->daq_io_addr + Filter_Enable(i));
-		if (board(dev)->invert_outputs)
+		if (board->invert_outputs)
 			writeb(0x01,
 			       devpriv->mite->daq_io_addr + Port_Data(i));
 		else
@@ -775,6 +752,7 @@ static void ni_65xx_detach(struct comedi_device *dev)
 			mite_free(devpriv->mite);
 		}
 	}
+	comedi_pci_disable(dev);
 }
 
 static struct comedi_driver ni_65xx_driver = {
@@ -785,15 +763,42 @@ static struct comedi_driver ni_65xx_driver = {
 };
 
 static int ni_65xx_pci_probe(struct pci_dev *dev,
-				       const struct pci_device_id *ent)
+			     const struct pci_device_id *id)
 {
-	return comedi_pci_auto_config(dev, &ni_65xx_driver);
+	return comedi_pci_auto_config(dev, &ni_65xx_driver, id->driver_data);
 }
 
+static DEFINE_PCI_DEVICE_TABLE(ni_65xx_pci_table) = {
+	{ PCI_VDEVICE(NI, 0x1710), BOARD_PXI6509 },
+	{ PCI_VDEVICE(NI, 0x7085), BOARD_PCI6509 },
+	{ PCI_VDEVICE(NI, 0x7086), BOARD_PXI6528 },
+	{ PCI_VDEVICE(NI, 0x7087), BOARD_PCI6515 },
+	{ PCI_VDEVICE(NI, 0x7088), BOARD_PCI6514 },
+	{ PCI_VDEVICE(NI, 0x70a9), BOARD_PCI6528 },
+	{ PCI_VDEVICE(NI, 0x70c3), BOARD_PCI6511 },
+	{ PCI_VDEVICE(NI, 0x70c8), BOARD_PCI6513 },
+	{ PCI_VDEVICE(NI, 0x70c9), BOARD_PXI6515 },
+	{ PCI_VDEVICE(NI, 0x70cc), BOARD_PCI6512 },
+	{ PCI_VDEVICE(NI, 0x70cd), BOARD_PXI6514 },
+	{ PCI_VDEVICE(NI, 0x70d1), BOARD_PXI6513 },
+	{ PCI_VDEVICE(NI, 0x70d2), BOARD_PXI6512 },
+	{ PCI_VDEVICE(NI, 0x70d3), BOARD_PXI6511 },
+	{ PCI_VDEVICE(NI, 0x7124), BOARD_PCI6510 },
+	{ PCI_VDEVICE(NI, 0x7125), BOARD_PCI6516 },
+	{ PCI_VDEVICE(NI, 0x7126), BOARD_PCI6517 },
+	{ PCI_VDEVICE(NI, 0x7127), BOARD_PCI6518 },
+	{ PCI_VDEVICE(NI, 0x7128), BOARD_PCI6519 },
+	{ PCI_VDEVICE(NI, 0x718b), BOARD_PCI6521 },
+	{ PCI_VDEVICE(NI, 0x718c), BOARD_PXI6521 },
+	{ PCI_VDEVICE(NI, 0x71c5), BOARD_PCI6520 },
+	{ 0 }
+};
+MODULE_DEVICE_TABLE(pci, ni_65xx_pci_table);
+
 static struct pci_driver ni_65xx_pci_driver = {
-	.name = "ni_65xx",
-	.id_table = ni_65xx_pci_table,
-	.probe = ni_65xx_pci_probe,
+	.name		= "ni_65xx",
+	.id_table	= ni_65xx_pci_table,
+	.probe		= ni_65xx_pci_probe,
 	.remove		= comedi_pci_auto_unconfig,
 };
 module_comedi_pci_driver(ni_65xx_driver, ni_65xx_pci_driver);
diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c
index e46dd7a..5cdda7f 100644
--- a/drivers/staging/comedi/drivers/ni_660x.c
+++ b/drivers/staging/comedi/drivers/ni_660x.c
@@ -18,27 +18,25 @@
 */
 
 /*
-Driver: ni_660x
-Description: National Instruments 660x counter/timer boards
-Devices:
-[National Instruments] PCI-6601 (ni_660x), PCI-6602, PXI-6602,
-	PXI-6608
-Author: J.P. Mellor <jpmellor@rose-hulman.edu>,
-	Herman.Bruyninckx@mech.kuleuven.ac.be,
-	Wim.Meeussen@mech.kuleuven.ac.be,
-	Klaas.Gadeyne@mech.kuleuven.ac.be,
-	Frank Mori Hess <fmhess@users.sourceforge.net>
-Updated: Thu Oct 18 12:56:06 EDT 2007
-Status: experimental
-
-Encoders work.  PulseGeneration (both single pulse and pulse train)
-works. Buffered commands work for input but not output.
-
-References:
-DAQ 660x Register-Level Programmer Manual  (NI 370505A-01)
-DAQ 6601/6602 User Manual (NI 322137B-01)
-
-*/
+ * Driver: ni_660x
+ * Description: National Instruments 660x counter/timer boards
+ * Devices: [National Instruments] PCI-6601 (ni_660x), PCI-6602, PXI-6602,
+ *   PXI-6608, PXI-6624
+ * Author: J.P. Mellor <jpmellor@rose-hulman.edu>,
+ *   Herman.Bruyninckx@mech.kuleuven.ac.be,
+ *   Wim.Meeussen@mech.kuleuven.ac.be,
+ *   Klaas.Gadeyne@mech.kuleuven.ac.be,
+ *   Frank Mori Hess <fmhess@users.sourceforge.net>
+ * Updated: Fri, 15 Mar 2013 10:47:56 +0000
+ * Status: experimental
+ *
+ * Encoders work.  PulseGeneration (both single pulse and pulse train)
+ * works.  Buffered commands work for input but not output.
+ * 
+ * References:
+ * DAQ 660x Register-Level Programmer Manual  (NI 370505A-01)
+ * DAQ 6601/6602 User Manual (NI 322137B-01)
+ */
 
 #include <linux/pci.h>
 #include <linux/interrupt.h>
@@ -389,34 +387,40 @@ enum global_interrupt_config_register_bits {
 /* First chip is at base-address + 0x00, etc. */
 static const unsigned GPCT_OFFSET[2] = { 0x0, 0x800 };
 
-/* Board description*/
+enum ni_660x_boardid {
+	BOARD_PCI6601,
+	BOARD_PCI6602,
+	BOARD_PXI6602,
+	BOARD_PXI6608,
+	BOARD_PXI6624
+};
+
 struct ni_660x_board {
-	unsigned short dev_id;	/* `lspci` will show you this */
 	const char *name;
 	unsigned n_chips;	/* total number of TIO chips */
 };
 
 static const struct ni_660x_board ni_660x_boards[] = {
-	{
-	 .dev_id = 0x2c60,
-	 .name = "PCI-6601",
-	 .n_chips = 1,
-	 },
-	{
-	 .dev_id = 0x1310,
-	 .name = "PCI-6602",
-	 .n_chips = 2,
-	 },
-	{
-	 .dev_id = 0x1360,
-	 .name = "PXI-6602",
-	 .n_chips = 2,
-	 },
-	{
-	 .dev_id = 0x2cc0,
-	 .name = "PXI-6608",
-	 .n_chips = 2,
-	 },
+	[BOARD_PCI6601] = {
+		.name		= "PCI-6601",
+		.n_chips	= 1,
+	},
+	[BOARD_PCI6602] = {
+		.name		= "PCI-6602",
+		.n_chips	= 2,
+	},
+	[BOARD_PXI6602] = {
+		.name		= "PXI-6602",
+		.n_chips	= 2,
+	},
+	[BOARD_PXI6608] = {
+		.name		= "PXI-6608",
+		.n_chips	= 2,
+	},
+	[BOARD_PXI6624] = {
+		.name		= "PXI-6624",
+		.n_chips	= 2,
+	},
 };
 
 #define NI_660X_MAX_NUM_CHIPS 2
@@ -883,7 +887,7 @@ static irqreturn_t ni_660x_interrupt(int irq, void *d)
 	unsigned i;
 	unsigned long flags;
 
-	if (dev->attached == 0)
+	if (!dev->attached)
 		return IRQ_NONE;
 	/* lock to avoid race with comedi_poll */
 	spin_lock_irqsave(&devpriv->interrupt_lock, flags);
@@ -974,20 +978,6 @@ static void ni_660x_free_mite_rings(struct comedi_device *dev)
 	}
 }
 
-static const struct ni_660x_board *
-ni_660x_find_boardinfo(struct pci_dev *pcidev)
-{
-	unsigned int dev_id = pcidev->device;
-	unsigned int n;
-
-	for (n = 0; n < ARRAY_SIZE(ni_660x_boards); n++) {
-		const struct ni_660x_board *board = &ni_660x_boards[n];
-		if (board->dev_id == dev_id)
-			return board;
-	}
-	return NULL;
-}
-
 static int
 ni_660x_GPCT_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
 		   struct comedi_insn *insn, unsigned int *data)
@@ -1170,32 +1160,36 @@ static int ni_660x_dio_insn_config(struct comedi_device *dev,
 }
 
 static int ni_660x_auto_attach(struct comedi_device *dev,
-					 unsigned long context_unused)
+			       unsigned long context)
 {
 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-	const struct ni_660x_board *board;
+	const struct ni_660x_board *board = NULL;
 	struct ni_660x_private *devpriv;
 	struct comedi_subdevice *s;
 	int ret;
 	unsigned i;
 	unsigned global_interrupt_config_bits;
 
+	if (context < ARRAY_SIZE(ni_660x_boards))
+		board = &ni_660x_boards[context];
+	if (!board)
+		return -ENODEV;
+	dev->board_ptr = board;
+	dev->board_name = board->name;
+
+	ret = comedi_pci_enable(dev);
+	if (ret)
+		return ret;
+
 	ret = ni_660x_allocate_private(dev);
 	if (ret < 0)
 		return ret;
 	devpriv = dev->private;
 
-	dev->board_ptr = ni_660x_find_boardinfo(pcidev);
-	if (!dev->board_ptr)
-		return -ENODEV;
-	board = comedi_board(dev);
-
 	devpriv->mite = mite_alloc(pcidev);
 	if (!devpriv->mite)
 		return -ENOMEM;
 
-	dev->board_name = board->name;
-
 	ret = mite_setup2(devpriv->mite, 1);
 	if (ret < 0) {
 		dev_warn(dev->class_dev, "error setting up mite\n");
@@ -1315,6 +1309,7 @@ static void ni_660x_detach(struct comedi_device *dev)
 			mite_free(devpriv->mite);
 		}
 	}
+	comedi_pci_disable(dev);
 }
 
 static struct comedi_driver ni_660x_driver = {
@@ -1325,17 +1320,18 @@ static struct comedi_driver ni_660x_driver = {
 };
 
 static int ni_660x_pci_probe(struct pci_dev *dev,
-				       const struct pci_device_id *ent)
+			     const struct pci_device_id *id)
 {
-	return comedi_pci_auto_config(dev, &ni_660x_driver);
+	return comedi_pci_auto_config(dev, &ni_660x_driver, id->driver_data);
 }
 
 static DEFINE_PCI_DEVICE_TABLE(ni_660x_pci_table) = {
-	{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2c60)},
-	{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1310)},
-	{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1360)},
-	{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2cc0)},
-	{0}
+	{ PCI_VDEVICE(NI, 0x1310), BOARD_PCI6602 },
+	{ PCI_VDEVICE(NI, 0x1360), BOARD_PXI6602 },
+	{ PCI_VDEVICE(NI, 0x2c60), BOARD_PCI6601 },
+	{ PCI_VDEVICE(NI, 0x2cc0), BOARD_PXI6608 },
+	{ PCI_VDEVICE(NI, 0x1e40), BOARD_PXI6624 },
+	{ 0 }
 };
 MODULE_DEVICE_TABLE(pci, ni_660x_pci_table);
 
diff --git a/drivers/staging/comedi/drivers/ni_670x.c b/drivers/staging/comedi/drivers/ni_670x.c
index 2faf86c..e9d4862 100644
--- a/drivers/staging/comedi/drivers/ni_670x.c
+++ b/drivers/staging/comedi/drivers/ni_670x.c
@@ -60,26 +60,28 @@ Commands are not supported.
 #define	MISC_STATUS_OFFSET		0x14
 #define	MISC_CONTROL_OFFSET		0x14
 
-/* Board description*/
+enum ni_670x_boardid {
+	BOARD_PCI6703,
+	BOARD_PXI6704,
+	BOARD_PCI6704,
+};
 
 struct ni_670x_board {
 	const char *name;
-	unsigned short dev_id;
 	unsigned short ao_chans;
 };
 
 static const struct ni_670x_board ni_670x_boards[] = {
-	{
+	[BOARD_PCI6703] = {
 		.name		= "PCI-6703",
-		.dev_id		= 0x2c90,
 		.ao_chans	= 16,
-	}, {
+	},
+	[BOARD_PXI6704] = {
 		.name		= "PXI-6704",
-		.dev_id		= 0x1920,
 		.ao_chans	= 32,
-	}, {
+	},
+	[BOARD_PCI6704] = {
 		.name		= "PCI-6704",
-		.dev_id		= 0x1290,
 		.ao_chans	= 32,
 	},
 };
@@ -189,49 +191,41 @@ static int ni_670x_dio_insn_config(struct comedi_device *dev,
 	return insn->n;
 }
 
-static const struct ni_670x_board *
-ni_670x_find_boardinfo(struct pci_dev *pcidev)
-{
-	unsigned int dev_id = pcidev->device;
-	unsigned int n;
-
-	for (n = 0; n < ARRAY_SIZE(ni_670x_boards); n++) {
-		const struct ni_670x_board *board = &ni_670x_boards[n];
-		if (board->dev_id == dev_id)
-			return board;
-	}
-	return NULL;
-}
-
 static int ni_670x_auto_attach(struct comedi_device *dev,
-					 unsigned long context_unused)
+			       unsigned long context)
 {
 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-	const struct ni_670x_board *thisboard;
+	const struct ni_670x_board *thisboard = NULL;
 	struct ni_670x_private *devpriv;
 	struct comedi_subdevice *s;
 	int ret;
 	int i;
 
+	if (context < ARRAY_SIZE(ni_670x_boards))
+		thisboard = &ni_670x_boards[context];
+	if (!thisboard)
+		return -ENODEV;
+	dev->board_ptr = thisboard;
+	dev->board_name = thisboard->name;
+
+	ret = comedi_pci_enable(dev);
+	if (ret)
+		return ret;
+
 	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
 	if (!devpriv)
 		return -ENOMEM;
 	dev->private = devpriv;
 
-	dev->board_ptr = ni_670x_find_boardinfo(pcidev);
-	if (!dev->board_ptr)
-		return -ENODEV;
 	devpriv->mite = mite_alloc(pcidev);
 	if (!devpriv->mite)
 		return -ENOMEM;
-	thisboard = comedi_board(dev);
 
 	ret = mite_setup(devpriv->mite);
 	if (ret < 0) {
 		dev_warn(dev->class_dev, "error setting up mite\n");
 		return ret;
 	}
-	dev->board_name = thisboard->name;
 
 	ret = comedi_alloc_subdevices(dev, 2);
 	if (ret)
@@ -296,6 +290,7 @@ static void ni_670x_detach(struct comedi_device *dev)
 		mite_unsetup(devpriv->mite);
 		mite_free(devpriv->mite);
 	}
+	comedi_pci_disable(dev);
 }
 
 static struct comedi_driver ni_670x_driver = {
@@ -306,14 +301,15 @@ static struct comedi_driver ni_670x_driver = {
 };
 
 static int ni_670x_pci_probe(struct pci_dev *dev,
-				       const struct pci_device_id *ent)
+			     const struct pci_device_id *id)
 {
-	return comedi_pci_auto_config(dev, &ni_670x_driver);
+	return comedi_pci_auto_config(dev, &ni_670x_driver, id->driver_data);
 }
 
 static DEFINE_PCI_DEVICE_TABLE(ni_670x_pci_table) = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2c90) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1920) },
+	{ PCI_VDEVICE(NI, 0x1290), BOARD_PCI6704 },
+	{ PCI_VDEVICE(NI, 0x1920), BOARD_PXI6704 },
+	{ PCI_VDEVICE(NI, 0x2c90), BOARD_PCI6703 },
 	{ 0 }
 };
 MODULE_DEVICE_TABLE(pci, ni_670x_pci_table);
diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c
index 06de25b..2a4a7a4 100644
--- a/drivers/staging/comedi/drivers/ni_at_a2150.c
+++ b/drivers/staging/comedi/drivers/ni_at_a2150.c
@@ -204,7 +204,7 @@ static irqreturn_t a2150_interrupt(int irq, void *d)
 	short dpnt;
 	static const int sample_size = sizeof(devpriv->dma_buffer[0]);
 
-	if (dev->attached == 0) {
+	if (!dev->attached) {
 		comedi_error(dev, "premature interrupt");
 		return IRQ_HANDLED;
 	}
diff --git a/drivers/staging/comedi/drivers/ni_atmio.c b/drivers/staging/comedi/drivers/ni_atmio.c
index 2cc2996..37372a1 100644
--- a/drivers/staging/comedi/drivers/ni_atmio.c
+++ b/drivers/staging/comedi/drivers/ni_atmio.c
@@ -350,7 +350,7 @@ static int ni_isapnp_find_board(struct pnp_dev **dev)
 	struct pnp_dev *isapnp_dev = NULL;
 	int i;
 
-	for (i = 0; i < n_ni_boards; i++) {
+	for (i = 0; i < ARRAY_SIZE(ni_boards); i++) {
 		isapnp_dev = pnp_find_dev(NULL,
 					  ISAPNP_VENDOR('N', 'I', 'C'),
 					  ISAPNP_FUNCTION(ni_boards[i].
@@ -377,7 +377,7 @@ static int ni_isapnp_find_board(struct pnp_dev **dev)
 		}
 		break;
 	}
-	if (i == n_ni_boards)
+	if (i == ARRAY_SIZE(ni_boards))
 		return -ENODEV;
 	*dev = isapnp_dev;
 	return 0;
@@ -388,7 +388,7 @@ static int ni_getboardtype(struct comedi_device *dev)
 	int device_id = ni_read_eeprom(dev, 511);
 	int i;
 
-	for (i = 0; i < n_ni_boards; i++) {
+	for (i = 0; i < ARRAY_SIZE(ni_boards); i++) {
 		if (ni_boards[i].device_id == device_id)
 			return i;
 
@@ -406,6 +406,7 @@ static int ni_getboardtype(struct comedi_device *dev)
 static int ni_atmio_attach(struct comedi_device *dev,
 			   struct comedi_devconfig *it)
 {
+	const struct ni_board_struct *boardtype;
 	struct ni_private *devpriv;
 	struct pnp_dev *isapnp_dev;
 	int ret;
@@ -466,9 +467,10 @@ static int ni_atmio_attach(struct comedi_device *dev,
 		return -EIO;
 
 	dev->board_ptr = ni_boards + board;
+	boardtype = comedi_board(dev);
 
-	printk(" %s", boardtype.name);
-	dev->board_name = boardtype.name;
+	printk(" %s", boardtype->name);
+	dev->board_name = boardtype->name;
 
 	/* irq stuff */
 
diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c
index f957b88..22f8d45 100644
--- a/drivers/staging/comedi/drivers/ni_labpc.c
+++ b/drivers/staging/comedi/drivers/ni_labpc.c
@@ -1,77 +1,70 @@
 /*
-    comedi/drivers/ni_labpc.c
-    Driver for National Instruments Lab-PC series boards and compatibles
-    Copyright (C) 2001, 2002, 2003 Frank Mori Hess <fmhess@users.sourceforge.net>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You 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: ni_labpc
-Description: National Instruments Lab-PC (& compatibles)
-Author: Frank Mori Hess <fmhess@users.sourceforge.net>
-Devices: [National Instruments] Lab-PC-1200 (labpc-1200),
-  Lab-PC-1200AI (labpc-1200ai), Lab-PC+ (lab-pc+), PCI-1200 (ni_labpc)
-Status: works
-
-Tested with lab-pc-1200.  For the older Lab-PC+, not all input ranges
-and analog references will work, the available ranges/arefs will
-depend on how you have configured the jumpers on your board
-(see your owner's manual).
-
-Kernel-level ISA plug-and-play support for the lab-pc-1200
-boards has not
-yet been added to the driver, mainly due to the fact that
-I don't know the device id numbers.  If you have one
-of these boards,
-please file a bug report at http://comedi.org/ 
-so I can get the necessary information from you.
-
-The 1200 series boards have onboard calibration dacs for correcting
-analog input/output offsets and gains.  The proper settings for these
-caldacs are stored on the board's eeprom.  To read the caldac values
-from the eeprom and store them into a file that can be then be used by
-comedilib, use the comedi_calibrate program.
-
-Configuration options - ISA boards:
-  [0] - I/O port base address
-  [1] - IRQ (optional, required for timed or externally triggered conversions)
-  [2] - DMA channel (optional)
-
-Configuration options - PCI boards:
-  [0] - bus (optional)
-  [1] - slot (optional)
-
-The Lab-pc+ has quirky chanlist requirements
-when scanning multiple channels.  Multiple channel scan
-sequence must start at highest channel, then decrement down to
-channel 0.  The rest of the cards can scan down like lab-pc+ or scan
-up from channel zero.  Chanlists consisting of all one channel
-are also legal, and allow you to pace conversions in bursts.
-
-*/
+ * comedi/drivers/ni_labpc.c
+ * Driver for National Instruments Lab-PC series boards and compatibles
+ * Copyright (C) 2001-2003 Frank Mori Hess <fmhess@users.sourceforge.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You 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.
+ */
 
 /*
-
-NI manuals:
-341309a (labpc-1200 register manual)
-340914a (pci-1200)
-320502b (lab-pc+)
-
-*/
+ * Driver: ni_labpc
+ * Description: National Instruments Lab-PC (& compatibles)
+ * Devices: (National Instruments) Lab-PC-1200 [lab-pc-1200]
+ *	    (National Instruments) Lab-PC-1200AI [lab-pc-1200ai]
+ *	    (National Instruments) Lab-PC+ [lab-pc+]
+ *	    (National Instruments) PCI-1200 [pci-1200]
+ * Author: Frank Mori Hess <fmhess@users.sourceforge.net>
+ * Status: works
+ *
+ * Configuration options - ISA boards:
+ *   [0] - I/O port base address
+ *   [1] - IRQ (optional, required for timed or externally triggered
+ *		conversions)
+ *   [2] - DMA channel (optional)
+ *
+ * Configuration options - PCI boards:
+ *    not applicable, uses PCI auto config
+ *
+ * Tested with lab-pc-1200.  For the older Lab-PC+, not all input
+ * ranges and analog references will work, the available ranges/arefs
+ * will depend on how you have configured the jumpers on your board
+ * (see your owner's manual).
+ *
+ * Kernel-level ISA plug-and-play support for the lab-pc-1200 boards
+ * has not yet been added to the driver, mainly due to the fact that
+ * I don't know the device id numbers. If you have one of these boards,
+ * please file a bug report at http://comedi.org/ so I can get the
+ * necessary information from you.
+ *
+ * The 1200 series boards have onboard calibration dacs for correcting
+ * analog input/output offsets and gains. The proper settings for these
+ * caldacs are stored on the board's eeprom. To read the caldac values
+ * from the eeprom and store them into a file that can be then be used
+ * by comedilib, use the comedi_calibrate program.
+ *
+ * The Lab-pc+ has quirky chanlist requirements when scanning multiple
+ * channels. Multiple channel scan sequence must start at highest channel,
+ * then decrement down to channel 0. The rest of the cards can scan down
+ * like lab-pc+ or scan up from channel zero. Chanlists consisting of all
+ * one channel are also legal, and allow you to pace conversions in bursts.
+ *
+ * NI manuals:
+ * 341309a (labpc-1200 register manual)
+ * 340914a (pci-1200)
+ * 320502b (lab-pc+)
+ */
 
 #include <linux/pci.h>
 #include <linux/interrupt.h>
@@ -89,124 +82,76 @@ NI manuals:
 #include "comedi_fc.h"
 #include "ni_labpc.h"
 
-#define DRV_NAME "ni_labpc"
-
-/* size of io region used by board */
-#define LABPC_SIZE           32
-/* 2 MHz master clock */
-#define LABPC_TIMER_BASE            500
-
-/* Registers for the lab-pc+ */
-
-/* write-only registers */
-#define COMMAND1_REG	0x0
-#define   ADC_GAIN_MASK	(0x7 << 4)
-#define   ADC_CHAN_BITS(x)	((x) & 0x7)
-/* enables multi channel scans */
-#define   ADC_SCAN_EN_BIT	0x80
-#define COMMAND2_REG	0x1
-/* enable pretriggering (used in conjunction with SWTRIG) */
-#define   PRETRIG_BIT	0x1
-/* enable paced conversions on external trigger */
-#define   HWTRIG_BIT	0x2
-/* enable paced conversions */
-#define   SWTRIG_BIT	0x4
-/* use two cascaded counters for pacing */
-#define   CASCADE_BIT	0x8
-#define   DAC_PACED_BIT(channel)	(0x40 << ((channel) & 0x1))
-#define COMMAND3_REG	0x2
-/* enable dma transfers */
-#define   DMA_EN_BIT	0x1
-/* enable interrupts for 8255 */
-#define   DIO_INTR_EN_BIT	0x2
-/* enable dma terminal count interrupt */
-#define   DMATC_INTR_EN_BIT	0x4
-/* enable timer interrupt */
-#define   TIMER_INTR_EN_BIT	0x8
-/* enable error interrupt */
-#define   ERR_INTR_EN_BIT	0x10
-/* enable fifo not empty interrupt */
-#define   ADC_FNE_INTR_EN_BIT	0x20
-#define ADC_CONVERT_REG	0x3
-#define DAC_LSB_REG(channel)	(0x4 + 2 * ((channel) & 0x1))
-#define DAC_MSB_REG(channel)	(0x5 + 2 * ((channel) & 0x1))
-#define ADC_CLEAR_REG	0x8
-#define DMATC_CLEAR_REG	0xa
-#define TIMER_CLEAR_REG	0xc
-/* 1200 boards only */
-#define COMMAND6_REG	0xe
-/* select ground or common-mode reference */
-#define   ADC_COMMON_BIT	0x1
-/*  adc unipolar */
-#define   ADC_UNIP_BIT	0x2
-/*  dac unipolar */
-#define   DAC_UNIP_BIT(channel)	(0x4 << ((channel) & 0x1))
-/* enable fifo half full interrupt */
-#define   ADC_FHF_INTR_EN_BIT	0x20
-/* enable interrupt on end of hardware count */
-#define   A1_INTR_EN_BIT	0x40
-/* scan up from channel zero instead of down to zero */
-#define   ADC_SCAN_UP_BIT 0x80
-#define COMMAND4_REG	0xf
-/* enables 'interval' scanning */
-#define   INTERVAL_SCAN_EN_BIT	0x1
-/* enables external signal on counter b1 output to trigger scan */
-#define   EXT_SCAN_EN_BIT	0x2
-/* chooses direction (output or input) for EXTCONV* line */
-#define   EXT_CONVERT_OUT_BIT	0x4
-/* chooses differential inputs for adc (in conjunction with board jumper) */
-#define   ADC_DIFF_BIT	0x8
-#define   EXT_CONVERT_DISABLE_BIT	0x10
-/* 1200 boards only, calibration stuff */
-#define COMMAND5_REG	0x1c
-/* enable eeprom for write */
-#define   EEPROM_WRITE_UNPROTECT_BIT	0x4
-/* enable dithering */
-#define   DITHER_EN_BIT	0x8
-/* load calibration dac */
-#define   CALDAC_LOAD_BIT	0x10
-/* serial clock - rising edge writes, falling edge reads */
-#define   SCLOCK_BIT	0x20
-/* serial data bit for writing to eeprom or calibration dacs */
-#define   SDATA_BIT	0x40
-/* enable eeprom for read/write */
-#define   EEPROM_EN_BIT	0x80
-#define INTERVAL_COUNT_REG	0x1e
-#define INTERVAL_LOAD_REG	0x1f
-#define   INTERVAL_LOAD_BITS	0x1
-
-/* read-only registers */
-#define STATUS1_REG	0x0
-/* data is available in fifo */
-#define   DATA_AVAIL_BIT	0x1
-/* overrun has occurred */
-#define   OVERRUN_BIT	0x2
-/* fifo overflow */
-#define   OVERFLOW_BIT	0x4
-/* timer interrupt has occurred */
-#define   TIMER_BIT	0x8
-/* dma terminal count has occurred */
-#define   DMATC_BIT	0x10
-/* external trigger has occurred */
-#define   EXT_TRIG_BIT	0x40
-/* 1200 boards only */
-#define STATUS2_REG	0x1d
-/* programmable eeprom serial output */
-#define   EEPROM_OUT_BIT	0x1
-/* counter A1 terminal count */
-#define   A1_TC_BIT	0x2
-/* fifo not half full */
-#define   FNHF_BIT	0x4
-#define ADC_FIFO_REG	0xa
-
-#define DIO_BASE_REG	0x10
-#define COUNTER_A_BASE_REG	0x14
-#define COUNTER_A_CONTROL_REG	(COUNTER_A_BASE_REG + 0x3)
-/* check modes put conversion pacer output in harmless state (a0 mode 2) */
-#define   INIT_A0_BITS	0x14
-/* put hardware conversion counter output in harmless state (a1 mode 0) */
-#define   INIT_A1_BITS	0x70
-#define COUNTER_B_BASE_REG	0x18
+/*
+ * Register map (all registers are 8-bit)
+ */
+#define STAT1_REG		0x00	/* R: Status 1 reg */
+#define STAT1_DAVAIL		(1 << 0)
+#define STAT1_OVERRUN		(1 << 1)
+#define STAT1_OVERFLOW		(1 << 2)
+#define STAT1_CNTINT		(1 << 3)
+#define STAT1_GATA0		(1 << 5)
+#define STAT1_EXTGATA0		(1 << 6)
+#define CMD1_REG		0x00	/* W: Command 1 reg */
+#define CMD1_MA(x)		(((x) & 0x7) << 0)
+#define CMD1_TWOSCMP		(1 << 3)
+#define CMD1_GAIN_MASK		(7 << 4)
+#define CMD1_SCANEN		(1 << 7)
+#define CMD2_REG		0x01	/* W: Command 2 reg */
+#define CMD2_PRETRIG		(1 << 0)
+#define CMD2_HWTRIG		(1 << 1)
+#define CMD2_SWTRIG		(1 << 2)
+#define CMD2_TBSEL		(1 << 3)
+#define CMD2_2SDAC0		(1 << 4)
+#define CMD2_2SDAC1		(1 << 5)
+#define CMD2_LDAC(x)		(1 << (6 + (x)))
+#define CMD3_REG		0x02	/* W: Command 3 reg */
+#define CMD3_DMAEN		(1 << 0)
+#define CMD3_DIOINTEN		(1 << 1)
+#define CMD3_DMATCINTEN		(1 << 2)
+#define CMD3_CNTINTEN		(1 << 3)
+#define CMD3_ERRINTEN		(1 << 4)
+#define CMD3_FIFOINTEN		(1 << 5)
+#define ADC_START_CONVERT_REG	0x03	/* W: Start Convert reg */
+#define DAC_LSB_REG(x)		(0x04 + 2 * (x)) /* W: DAC0/1 LSB reg */
+#define DAC_MSB_REG(x)		(0x05 + 2 * (x)) /* W: DAC0/1 MSB reg */
+#define ADC_FIFO_CLEAR_REG	0x08	/* W: A/D FIFO Clear reg */
+#define ADC_FIFO_REG		0x0a	/* R: A/D FIFO reg */
+#define DMATC_CLEAR_REG		0x0a	/* W: DMA Interrupt Clear reg */
+#define TIMER_CLEAR_REG		0x0c	/* W: Timer Interrupt Clear reg */
+#define CMD6_REG		0x0e	/* W: Command 6 reg */
+#define CMD6_NRSE		(1 << 0)
+#define CMD6_ADCUNI		(1 << 1)
+#define CMD6_DACUNI(x)		(1 << (2 + (x)))
+#define CMD6_HFINTEN		(1 << 5)
+#define CMD6_DQINTEN		(1 << 6)
+#define CMD6_SCANUP		(1 << 7)
+#define CMD4_REG		0x0f	/* W: Command 3 reg */
+#define CMD4_INTSCAN		(1 << 0)
+#define CMD4_EOIRCV		(1 << 1)
+#define CMD4_ECLKDRV		(1 << 2)
+#define CMD4_SEDIFF		(1 << 3)
+#define CMD4_ECLKRCV		(1 << 4)
+#define DIO_BASE_REG		0x10	/* R/W: 8255 DIO base reg */
+#define COUNTER_A_BASE_REG	0x14	/* R/W: 8253 Counter A base reg */
+#define COUNTER_B_BASE_REG	0x18	/* R/W: 8253 Counter B base reg */
+#define CMD5_REG		0x1c	/* W: Command 5 reg */
+#define CMD5_WRTPRT		(1 << 2)
+#define CMD5_DITHEREN		(1 << 3)
+#define CMD5_CALDACLD		(1 << 4)
+#define CMD5_SCLK		(1 << 5)
+#define CMD5_SDATA		(1 << 6)
+#define CMD5_EEPROMCS		(1 << 7)
+#define STAT2_REG		0x1d	/* R: Status 2 reg */
+#define STAT2_PROMOUT		(1 << 0)
+#define STAT2_OUTA1		(1 << 1)
+#define STAT2_FIFONHF		(1 << 2)
+#define INTERVAL_COUNT_REG	0x1e	/* W: Interval Counter Data reg */
+#define INTERVAL_STROBE_REG	0x1f	/* W: Interval Counter Strobe reg */
+
+#define LABPC_SIZE		0x20	/* size of ISA io region */
+#define LABPC_TIMER_BASE	500	/* 2 MHz master clock */
+#define LABPC_ADC_TIMEOUT	1000
 
 enum scan_mode {
 	MODE_SINGLE_CHAN,
@@ -215,187 +160,63 @@ enum scan_mode {
 	MODE_MULT_CHAN_DOWN,
 };
 
-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);
-static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
-static int labpc_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
-			  struct comedi_insn *insn, unsigned int *data);
-static int labpc_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
-			  struct comedi_insn *insn, unsigned int *data);
-static int labpc_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
-			  struct comedi_insn *insn, unsigned int *data);
-static int labpc_calib_read_insn(struct comedi_device *dev,
-				 struct comedi_subdevice *s,
-				 struct comedi_insn *insn, unsigned int *data);
-static int labpc_calib_write_insn(struct comedi_device *dev,
-				  struct comedi_subdevice *s,
-				  struct comedi_insn *insn, unsigned int *data);
-static int labpc_eeprom_read_insn(struct comedi_device *dev,
-				  struct comedi_subdevice *s,
-				  struct comedi_insn *insn, unsigned int *data);
-static int labpc_eeprom_write_insn(struct comedi_device *dev,
-				   struct comedi_subdevice *s,
-				   struct comedi_insn *insn,
-				   unsigned int *data);
-static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd,
-			     enum scan_mode scan_mode);
-#ifdef CONFIG_ISA_DMA_API
-static unsigned int labpc_suggest_transfer_size(const struct comedi_cmd *cmd);
-#endif
-static int labpc_dio_mem_callback(int dir, int port, int data,
-				  unsigned long arg);
-static void labpc_serial_out(struct comedi_device *dev, unsigned int value,
-			     unsigned int num_bits);
-static unsigned int labpc_serial_in(struct comedi_device *dev);
-static unsigned int labpc_eeprom_read(struct comedi_device *dev,
-				      unsigned int address);
-static unsigned int labpc_eeprom_read_status(struct comedi_device *dev);
-static int labpc_eeprom_write(struct comedi_device *dev,
-				       unsigned int address,
-				       unsigned int value);
-static void write_caldac(struct comedi_device *dev, unsigned int channel,
-			 unsigned int value);
-
-/* analog input ranges */
-#define NUM_LABPC_PLUS_AI_RANGES 16
-/* indicates unipolar ranges */
-static const int labpc_plus_is_unipolar[NUM_LABPC_PLUS_AI_RANGES] = {
-	0,
-	0,
-	0,
-	0,
-	0,
-	0,
-	0,
-	0,
-	1,
-	1,
-	1,
-	1,
-	1,
-	1,
-	1,
-	1,
-};
-
-/* map range index to gain bits */
-static const int labpc_plus_ai_gain_bits[NUM_LABPC_PLUS_AI_RANGES] = {
-	0x00,
-	0x10,
-	0x20,
-	0x30,
-	0x40,
-	0x50,
-	0x60,
-	0x70,
-	0x00,
-	0x10,
-	0x20,
-	0x30,
-	0x40,
-	0x50,
-	0x60,
-	0x70,
+static const int labpc_plus_ai_gain_bits[] = {
+	0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
+	0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
 };
 
 static const struct comedi_lrange range_labpc_plus_ai = {
-	NUM_LABPC_PLUS_AI_RANGES,
-	{
-	 BIP_RANGE(5),
-	 BIP_RANGE(4),
-	 BIP_RANGE(2.5),
-	 BIP_RANGE(1),
-	 BIP_RANGE(0.5),
-	 BIP_RANGE(0.25),
-	 BIP_RANGE(0.1),
-	 BIP_RANGE(0.05),
-	 UNI_RANGE(10),
-	 UNI_RANGE(8),
-	 UNI_RANGE(5),
-	 UNI_RANGE(2),
-	 UNI_RANGE(1),
-	 UNI_RANGE(0.5),
-	 UNI_RANGE(0.2),
-	 UNI_RANGE(0.1),
-	 }
+	16, {
+		BIP_RANGE(5),
+		BIP_RANGE(4),
+		BIP_RANGE(2.5),
+		BIP_RANGE(1),
+		BIP_RANGE(0.5),
+		BIP_RANGE(0.25),
+		BIP_RANGE(0.1),
+		BIP_RANGE(0.05),
+		UNI_RANGE(10),
+		UNI_RANGE(8),
+		UNI_RANGE(5),
+		UNI_RANGE(2),
+		UNI_RANGE(1),
+		UNI_RANGE(0.5),
+		UNI_RANGE(0.2),
+		UNI_RANGE(0.1)
+	}
 };
 
-#define NUM_LABPC_1200_AI_RANGES 14
-/* indicates unipolar ranges */
-const int labpc_1200_is_unipolar[NUM_LABPC_1200_AI_RANGES] = {
-	0,
-	0,
-	0,
-	0,
-	0,
-	0,
-	0,
-	1,
-	1,
-	1,
-	1,
-	1,
-	1,
-	1,
-};
-EXPORT_SYMBOL_GPL(labpc_1200_is_unipolar);
-
-/* map range index to gain bits */
-const int labpc_1200_ai_gain_bits[NUM_LABPC_1200_AI_RANGES] = {
-	0x00,
-	0x20,
-	0x30,
-	0x40,
-	0x50,
-	0x60,
-	0x70,
-	0x00,
-	0x20,
-	0x30,
-	0x40,
-	0x50,
-	0x60,
-	0x70,
+const int labpc_1200_ai_gain_bits[] = {
+	0x00, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
+	0x00, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
 };
 EXPORT_SYMBOL_GPL(labpc_1200_ai_gain_bits);
 
 const struct comedi_lrange range_labpc_1200_ai = {
-	NUM_LABPC_1200_AI_RANGES,
-	{
-	 BIP_RANGE(5),
-	 BIP_RANGE(2.5),
-	 BIP_RANGE(1),
-	 BIP_RANGE(0.5),
-	 BIP_RANGE(0.25),
-	 BIP_RANGE(0.1),
-	 BIP_RANGE(0.05),
-	 UNI_RANGE(10),
-	 UNI_RANGE(5),
-	 UNI_RANGE(2),
-	 UNI_RANGE(1),
-	 UNI_RANGE(0.5),
-	 UNI_RANGE(0.2),
-	 UNI_RANGE(0.1),
-	 }
+	14, {
+		BIP_RANGE(5),
+		BIP_RANGE(2.5),
+		BIP_RANGE(1),
+		BIP_RANGE(0.5),
+		BIP_RANGE(0.25),
+		BIP_RANGE(0.1),
+		BIP_RANGE(0.05),
+		UNI_RANGE(10),
+		UNI_RANGE(5),
+		UNI_RANGE(2),
+		UNI_RANGE(1),
+		UNI_RANGE(0.5),
+		UNI_RANGE(0.2),
+		UNI_RANGE(0.1)
+	}
 };
 EXPORT_SYMBOL_GPL(range_labpc_1200_ai);
 
-/* analog output ranges */
-#define AO_RANGE_IS_UNIPOLAR 0x1
 static const struct comedi_lrange range_labpc_ao = {
-	2,
-	{
-	 BIP_RANGE(5),
-	 UNI_RANGE(10),
-	 }
+	2, {
+		BIP_RANGE(5),
+		UNI_RANGE(10)
+	}
 };
 
 /* functions that do inb/outb and readb/writeb so we can use
@@ -420,421 +241,440 @@ static inline void labpc_writeb(unsigned int byte, unsigned long address)
 	writeb(byte, (void __iomem *)address);
 }
 
-static const struct labpc_board_struct labpc_boards[] = {
-	{
-	 .name = "lab-pc-1200",
-	 .ai_speed = 10000,
-	 .bustype = isa_bustype,
-	 .register_layout = labpc_1200_layout,
-	 .has_ao = 1,
-	 .ai_range_table = &range_labpc_1200_ai,
-	 .ai_range_code = labpc_1200_ai_gain_bits,
-	 .ai_range_is_unipolar = labpc_1200_is_unipolar,
-	 .ai_scan_up = 1,
-	 .memory_mapped_io = 0,
-	 },
+static const struct labpc_boardinfo labpc_boards[] = {
 	{
-	 .name = "lab-pc-1200ai",
-	 .ai_speed = 10000,
-	 .bustype = isa_bustype,
-	 .register_layout = labpc_1200_layout,
-	 .has_ao = 0,
-	 .ai_range_table = &range_labpc_1200_ai,
-	 .ai_range_code = labpc_1200_ai_gain_bits,
-	 .ai_range_is_unipolar = labpc_1200_is_unipolar,
-	 .ai_scan_up = 1,
-	 .memory_mapped_io = 0,
-	 },
-	{
-	 .name = "lab-pc+",
-	 .ai_speed = 12000,
-	 .bustype = isa_bustype,
-	 .register_layout = labpc_plus_layout,
-	 .has_ao = 1,
-	 .ai_range_table = &range_labpc_plus_ai,
-	 .ai_range_code = labpc_plus_ai_gain_bits,
-	 .ai_range_is_unipolar = labpc_plus_is_unipolar,
-	 .ai_scan_up = 0,
-	 .memory_mapped_io = 0,
-	 },
+		.name			= "lab-pc-1200",
+		.ai_speed		= 10000,
+		.bustype		= isa_bustype,
+		.register_layout	= labpc_1200_layout,
+		.has_ao			= 1,
+		.ai_range_table		= &range_labpc_1200_ai,
+		.ai_range_code		= labpc_1200_ai_gain_bits,
+		.ai_scan_up		= 1,
+	}, {
+		.name			= "lab-pc-1200ai",
+		.ai_speed		= 10000,
+		.bustype		= isa_bustype,
+		.register_layout	= labpc_1200_layout,
+		.ai_range_table		= &range_labpc_1200_ai,
+		.ai_range_code		= labpc_1200_ai_gain_bits,
+		.ai_scan_up		= 1,
+	}, {
+		.name			= "lab-pc+",
+		.ai_speed		= 12000,
+		.bustype		= isa_bustype,
+		.register_layout	= labpc_plus_layout,
+		.has_ao			= 1,
+		.ai_range_table		= &range_labpc_plus_ai,
+		.ai_range_code		= labpc_plus_ai_gain_bits,
+	},
 #ifdef CONFIG_COMEDI_PCI_DRIVERS
 	{
-	 .name = "pci-1200",
-	 .device_id = 0x161,
-	 .ai_speed = 10000,
-	 .bustype = pci_bustype,
-	 .register_layout = labpc_1200_layout,
-	 .has_ao = 1,
-	 .ai_range_table = &range_labpc_1200_ai,
-	 .ai_range_code = labpc_1200_ai_gain_bits,
-	 .ai_range_is_unipolar = labpc_1200_is_unipolar,
-	 .ai_scan_up = 1,
-	 .memory_mapped_io = 1,
-	 },
-/* dummy entry so pci board works when comedi_config is passed driver name */
-	{
-	 .name = DRV_NAME,
-	 .bustype = pci_bustype,
-	 },
+		.name			= "pci-1200",
+		.device_id		= 0x161,
+		.ai_speed		= 10000,
+		.bustype		= pci_bustype,
+		.register_layout	= labpc_1200_layout,
+		.has_ao			= 1,
+		.ai_range_table		= &range_labpc_1200_ai,
+		.ai_range_code		= labpc_1200_ai_gain_bits,
+		.ai_scan_up		= 1,
+		.has_mmio		= 1,
+	},
 #endif
 };
 
-/*
- * Useful for shorthand access to the particular board structure
- */
-#define thisboard ((struct labpc_board_struct *)dev->board_ptr)
-
 /* size in bytes of dma buffer */
 static const int dma_buffer_size = 0xff00;
 /* 2 bytes per sample */
 static const int sample_size = 2;
 
-static inline int labpc_counter_load(struct comedi_device *dev,
-				     unsigned long base_address,
-				     unsigned int counter_number,
-				     unsigned int count, unsigned int mode)
+static int labpc_counter_load(struct comedi_device *dev,
+			      unsigned long base_address,
+			      unsigned int counter_number,
+			      unsigned int count, unsigned int mode)
 {
-	if (thisboard->memory_mapped_io)
+	const struct labpc_boardinfo *board = comedi_board(dev);
+
+	if (board->has_mmio)
 		return i8254_mm_load((void __iomem *)base_address, 0,
 				     counter_number, count, mode);
 	else
 		return i8254_load(base_address, 0, counter_number, count, mode);
 }
 
-int labpc_common_attach(struct comedi_device *dev, unsigned long iobase,
-			unsigned int irq, unsigned int dma_chan)
+static int labpc_counter_set_mode(struct comedi_device *dev,
+				  unsigned long base_address,
+				  unsigned int counter_number,
+				  unsigned int mode)
 {
-	struct labpc_private *devpriv = dev->private;
-	struct comedi_subdevice *s;
-	int i;
-	unsigned long isr_flags;
-#ifdef CONFIG_ISA_DMA_API
-	unsigned long dma_flags;
-#endif
-	short lsb, msb;
-	int ret;
-
-	dev_info(dev->class_dev, "ni_labpc: %s\n", thisboard->name);
-	if (iobase == 0) {
-		dev_err(dev->class_dev, "io base address is zero!\n");
-		return -EINVAL;
-	}
-	/*  request io regions for isa boards */
-	if (thisboard->bustype == isa_bustype) {
-		/* check if io addresses are available */
-		if (!request_region(iobase, LABPC_SIZE, DRV_NAME)) {
-			dev_err(dev->class_dev, "I/O port conflict\n");
-			return -EIO;
-		}
-	}
-	dev->iobase = iobase;
-
-	if (thisboard->memory_mapped_io) {
-		devpriv->read_byte = labpc_readb;
-		devpriv->write_byte = labpc_writeb;
-	} else {
-		devpriv->read_byte = labpc_inb;
-		devpriv->write_byte = labpc_outb;
-	}
-	/* initialize board's command registers */
-	devpriv->write_byte(devpriv->command1_bits, dev->iobase + COMMAND1_REG);
-	devpriv->write_byte(devpriv->command2_bits, dev->iobase + COMMAND2_REG);
-	devpriv->write_byte(devpriv->command3_bits, dev->iobase + COMMAND3_REG);
-	devpriv->write_byte(devpriv->command4_bits, dev->iobase + COMMAND4_REG);
-	if (thisboard->register_layout == labpc_1200_layout) {
-		devpriv->write_byte(devpriv->command5_bits,
-				    dev->iobase + COMMAND5_REG);
-		devpriv->write_byte(devpriv->command6_bits,
-				    dev->iobase + COMMAND6_REG);
-	}
-
-	/* grab our IRQ */
-	if (irq) {
-		isr_flags = 0;
-		if (thisboard->bustype == pci_bustype
-		    || thisboard->bustype == pcmcia_bustype)
-			isr_flags |= IRQF_SHARED;
-		if (request_irq(irq, labpc_interrupt, isr_flags,
-				DRV_NAME, dev)) {
-			dev_err(dev->class_dev, "unable to allocate irq %u\n",
-				irq);
-			return -EINVAL;
-		}
-	}
-	dev->irq = irq;
-
-#ifdef CONFIG_ISA_DMA_API
-	/* grab dma channel */
-	if (dma_chan > 3) {
-		dev_err(dev->class_dev, "invalid dma channel %u\n", dma_chan);
-		return -EINVAL;
-	} else if (dma_chan) {
-		/* allocate dma buffer */
-		devpriv->dma_buffer = kmalloc(dma_buffer_size,
-					      GFP_KERNEL | GFP_DMA);
-		if (devpriv->dma_buffer == NULL)
-			return -ENOMEM;
-
-		if (request_dma(dma_chan, DRV_NAME)) {
-			dev_err(dev->class_dev,
-				"failed to allocate dma channel %u\n",
-				dma_chan);
-			return -EINVAL;
-		}
-		devpriv->dma_chan = dma_chan;
-		dma_flags = claim_dma_lock();
-		disable_dma(devpriv->dma_chan);
-		set_dma_mode(devpriv->dma_chan, DMA_MODE_READ);
-		release_dma_lock(dma_flags);
-	}
-#endif
-
-	dev->board_name = thisboard->name;
-
-	ret = comedi_alloc_subdevices(dev, 5);
-	if (ret)
-		return ret;
-
-	/* analog input subdevice */
-	s = &dev->subdevices[0];
-	dev->read_subdev = s;
-	s->type = COMEDI_SUBD_AI;
-	s->subdev_flags =
-	    SDF_READABLE | SDF_GROUND | SDF_COMMON | SDF_DIFF | SDF_CMD_READ;
-	s->n_chan = 8;
-	s->len_chanlist = 8;
-	s->maxdata = (1 << 12) - 1;	/* 12 bit resolution */
-	s->range_table = thisboard->ai_range_table;
-	s->do_cmd = labpc_ai_cmd;
-	s->do_cmdtest = labpc_ai_cmdtest;
-	s->insn_read = labpc_ai_rinsn;
-	s->cancel = labpc_cancel;
-
-	/* analog output */
-	s = &dev->subdevices[1];
-	if (thisboard->has_ao) {
-		/*
-		 * Could provide command support, except it only has a
-		 * one sample hardware buffer for analog output and no
-		 * underrun flag.
-		 */
-		s->type = COMEDI_SUBD_AO;
-		s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_GROUND;
-		s->n_chan = NUM_AO_CHAN;
-		s->maxdata = (1 << 12) - 1;	/*  12 bit resolution */
-		s->range_table = &range_labpc_ao;
-		s->insn_read = labpc_ao_rinsn;
-		s->insn_write = labpc_ao_winsn;
-		/* initialize analog outputs to a known value */
-		for (i = 0; i < s->n_chan; i++) {
-			devpriv->ao_value[i] = s->maxdata / 2;
-			lsb = devpriv->ao_value[i] & 0xff;
-			msb = (devpriv->ao_value[i] >> 8) & 0xff;
-			devpriv->write_byte(lsb, dev->iobase + DAC_LSB_REG(i));
-			devpriv->write_byte(msb, dev->iobase + DAC_MSB_REG(i));
-		}
-	} else {
-		s->type = COMEDI_SUBD_UNUSED;
-	}
+	const struct labpc_boardinfo *board = comedi_board(dev);
 
-	/* 8255 dio */
-	s = &dev->subdevices[2];
-	/*  if board uses io memory we have to give a custom callback
-	 * function to the 8255 driver */
-	if (thisboard->memory_mapped_io)
-		subdev_8255_init(dev, s, labpc_dio_mem_callback,
-				 (unsigned long)(dev->iobase + DIO_BASE_REG));
+	if (board->has_mmio)
+		return i8254_mm_set_mode((void __iomem *)base_address, 0,
+					 counter_number, mode);
 	else
-		subdev_8255_init(dev, s, NULL, dev->iobase + DIO_BASE_REG);
+		return i8254_set_mode(base_address, 0, counter_number, mode);
+}
 
-	/*  calibration subdevices for boards that have one */
-	s = &dev->subdevices[3];
-	if (thisboard->register_layout == labpc_1200_layout) {
-		s->type = COMEDI_SUBD_CALIB;
-		s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
-		s->n_chan = 16;
-		s->maxdata = 0xff;
-		s->insn_read = labpc_calib_read_insn;
-		s->insn_write = labpc_calib_write_insn;
+static bool labpc_range_is_unipolar(struct comedi_subdevice *s,
+				    unsigned int range)
+{
+	return s->range_table->range[range].min >= 0;
+}
 
-		for (i = 0; i < s->n_chan; i++)
-			write_caldac(dev, i, s->maxdata / 2);
-	} else
-		s->type = COMEDI_SUBD_UNUSED;
+static int labpc_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+{
+	struct labpc_private *devpriv = dev->private;
+	unsigned long flags;
 
-	/* EEPROM */
-	s = &dev->subdevices[4];
-	if (thisboard->register_layout == labpc_1200_layout) {
-		s->type = COMEDI_SUBD_MEMORY;
-		s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
-		s->n_chan = EEPROM_SIZE;
-		s->maxdata = 0xff;
-		s->insn_read = labpc_eeprom_read_insn;
-		s->insn_write = labpc_eeprom_write_insn;
-
-		for (i = 0; i < EEPROM_SIZE; i++)
-			devpriv->eeprom_data[i] = labpc_eeprom_read(dev, i);
-	} else
-		s->type = COMEDI_SUBD_UNUSED;
+	spin_lock_irqsave(&dev->spinlock, flags);
+	devpriv->cmd2 &= ~(CMD2_SWTRIG | CMD2_HWTRIG | CMD2_PRETRIG);
+	devpriv->write_byte(devpriv->cmd2, dev->iobase + CMD2_REG);
+	spin_unlock_irqrestore(&dev->spinlock, flags);
+
+	devpriv->cmd3 = 0;
+	devpriv->write_byte(devpriv->cmd3, dev->iobase + CMD3_REG);
 
 	return 0;
 }
-EXPORT_SYMBOL_GPL(labpc_common_attach);
 
-static const struct labpc_board_struct *
-labpc_pci_find_boardinfo(struct pci_dev *pcidev)
+static void labpc_ai_set_chan_and_gain(struct comedi_device *dev,
+				       enum scan_mode mode,
+				       unsigned int chan,
+				       unsigned int range,
+				       unsigned int aref)
 {
-	unsigned int device_id = pcidev->device;
-	unsigned int n;
+	const struct labpc_boardinfo *board = comedi_board(dev);
+	struct labpc_private *devpriv = dev->private;
 
-	for (n = 0; n < ARRAY_SIZE(labpc_boards); n++) {
-		const struct labpc_board_struct *board = &labpc_boards[n];
-		if (board->bustype == pci_bustype &&
-		    board->device_id == device_id)
-			return board;
-	}
-	return NULL;
+	/* munge channel bits for differential/scan disabled mode */
+	if ((mode == MODE_SINGLE_CHAN || mode == MODE_SINGLE_CHAN_INTERVAL) &&
+	    aref == AREF_DIFF)
+		chan *= 2;
+	devpriv->cmd1 = CMD1_MA(chan);
+	devpriv->cmd1 |= board->ai_range_code[range];
+
+	devpriv->write_byte(devpriv->cmd1, dev->iobase + CMD1_REG);
 }
 
-static int labpc_auto_attach(struct comedi_device *dev,
-				       unsigned long context_unused)
+static void labpc_setup_cmd6_reg(struct comedi_device *dev,
+				 struct comedi_subdevice *s,
+				 enum scan_mode mode,
+				 enum transfer_type xfer,
+				 unsigned int range,
+				 unsigned int aref,
+				 bool ena_intr)
 {
-	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-	struct labpc_private *devpriv;
-	unsigned long iobase;
-	unsigned int irq;
-	int ret;
+	const struct labpc_boardinfo *board = comedi_board(dev);
+	struct labpc_private *devpriv = dev->private;
 
-	if (!IS_ENABLED(CONFIG_COMEDI_PCI_DRIVERS))
-		return -ENODEV;
+	if (board->register_layout != labpc_1200_layout)
+		return;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
-	if (!devpriv)
-		return -ENOMEM;
-	dev->private = devpriv;
+	/* reference inputs to ground or common? */
+	if (aref != AREF_GROUND)
+		devpriv->cmd6 |= CMD6_NRSE;
+	else
+		devpriv->cmd6 &= ~CMD6_NRSE;
 
-	dev->board_ptr = labpc_pci_find_boardinfo(pcidev);
-	if (!dev->board_ptr)
-		return -ENODEV;
-	devpriv->mite = mite_alloc(pcidev);
-	if (!devpriv->mite)
-		return -ENOMEM;
-	ret = mite_setup(devpriv->mite);
-	if (ret < 0)
-		return ret;
-	iobase = (unsigned long)devpriv->mite->daq_io_addr;
-	irq = mite_irq(devpriv->mite);
-	return labpc_common_attach(dev, iobase, irq, 0);
-}
+	/* bipolar or unipolar range? */
+	if (labpc_range_is_unipolar(s, range))
+		devpriv->cmd6 |= CMD6_ADCUNI;
+	else
+		devpriv->cmd6 &= ~CMD6_ADCUNI;
 
-static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it)
-{
-	struct labpc_private *devpriv;
-	unsigned long iobase = 0;
-	unsigned int irq = 0;
-	unsigned int dma_chan = 0;
+	/*  interrupt on fifo half full? */
+	if (xfer == fifo_half_full_transfer)
+		devpriv->cmd6 |= CMD6_HFINTEN;
+	else
+		devpriv->cmd6 &= ~CMD6_HFINTEN;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
-	if (!devpriv)
-		return -ENOMEM;
-	dev->private = devpriv;
+	/* enable interrupt on counter a1 terminal count? */
+	if (ena_intr)
+		devpriv->cmd6 |= CMD6_DQINTEN;
+	else
+		devpriv->cmd6 &= ~CMD6_DQINTEN;
 
-	/* 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
-		dev_err(dev->class_dev,
-			"ni_labpc driver has not been built with ISA DMA support.\n");
-		return -EINVAL;
-#endif
-		break;
-	case pci_bustype:
-#ifdef CONFIG_COMEDI_PCI_DRIVERS
-		dev_err(dev->class_dev,
-			"manual configuration of PCI board '%s' is not supported\n",
-			thisboard->name);
-		return -EINVAL;
-#else
-		dev_err(dev->class_dev,
-			"ni_labpc driver has not been built with PCI support.\n");
-		return -EINVAL;
-#endif
-		break;
-	default:
-		dev_err(dev->class_dev,
-			"ni_labpc: bug! couldn't determine board type\n");
-		return -EINVAL;
-		break;
-	}
+	/* are we scanning up or down through channels? */
+	if (mode == MODE_MULT_CHAN_UP)
+		devpriv->cmd6 |= CMD6_SCANUP;
+	else
+		devpriv->cmd6 &= ~CMD6_SCANUP;
 
-	return labpc_common_attach(dev, iobase, irq, dma_chan);
+	devpriv->write_byte(devpriv->cmd6, dev->iobase + CMD6_REG);
 }
 
-void labpc_common_detach(struct comedi_device *dev)
+static unsigned int labpc_read_adc_fifo(struct comedi_device *dev)
 {
 	struct labpc_private *devpriv = dev->private;
-	struct comedi_subdevice *s;
+	unsigned int lsb = devpriv->read_byte(dev->iobase + ADC_FIFO_REG);
+	unsigned int msb = devpriv->read_byte(dev->iobase + ADC_FIFO_REG);
 
-	if (!thisboard)
-		return;
-	if (dev->subdevices) {
-		s = &dev->subdevices[2];
-		subdev_8255_cleanup(dev, s);
-	}
-#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)
-		release_region(dev->iobase, LABPC_SIZE);
-#ifdef CONFIG_COMEDI_PCI_DRIVERS
-	if (devpriv->mite) {
-		mite_unsetup(devpriv->mite);
-		mite_free(devpriv->mite);
-	}
-#endif
-};
-EXPORT_SYMBOL_GPL(labpc_common_detach);
+	return (msb << 8) | lsb;
+}
 
-static void labpc_clear_adc_fifo(const struct comedi_device *dev)
+static void labpc_clear_adc_fifo(struct comedi_device *dev)
 {
 	struct labpc_private *devpriv = dev->private;
 
-	devpriv->write_byte(0x1, dev->iobase + ADC_CLEAR_REG);
-	devpriv->read_byte(dev->iobase + ADC_FIFO_REG);
-	devpriv->read_byte(dev->iobase + ADC_FIFO_REG);
+	devpriv->write_byte(0x1, dev->iobase + ADC_FIFO_CLEAR_REG);
+	labpc_read_adc_fifo(dev);
 }
 
-static int labpc_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+static int labpc_ai_wait_for_data(struct comedi_device *dev,
+				  int timeout)
 {
 	struct labpc_private *devpriv = dev->private;
-	unsigned long flags;
-
-	spin_lock_irqsave(&dev->spinlock, flags);
-	devpriv->command2_bits &= ~SWTRIG_BIT & ~HWTRIG_BIT & ~PRETRIG_BIT;
-	devpriv->write_byte(devpriv->command2_bits, dev->iobase + COMMAND2_REG);
-	spin_unlock_irqrestore(&dev->spinlock, flags);
-
-	devpriv->command3_bits = 0;
-	devpriv->write_byte(devpriv->command3_bits, dev->iobase + COMMAND3_REG);
+	int i;
 
-	return 0;
+	for (i = 0; i < timeout; i++) {
+		devpriv->stat1 = devpriv->read_byte(dev->iobase + STAT1_REG);
+		if (devpriv->stat1 & STAT1_DAVAIL)
+			return 0;
+		udelay(1);
+	}
+	return -ETIME;
 }
 
-static enum scan_mode labpc_ai_scan_mode(const struct comedi_cmd *cmd)
+static int labpc_ai_insn_read(struct comedi_device *dev,
+			      struct comedi_subdevice *s,
+			      struct comedi_insn *insn,
+			      unsigned int *data)
 {
-	if (cmd->chanlist_len == 1)
-		return MODE_SINGLE_CHAN;
-
-	/* chanlist may be NULL during cmdtest. */
+	struct labpc_private *devpriv = dev->private;
+	unsigned int chan = CR_CHAN(insn->chanspec);
+	unsigned int range = CR_RANGE(insn->chanspec);
+	unsigned int aref = CR_AREF(insn->chanspec);
+	int ret;
+	int i;
+
+	/* disable timed conversions, interrupt generation and dma */
+	labpc_cancel(dev, s);
+
+	labpc_ai_set_chan_and_gain(dev, MODE_SINGLE_CHAN, chan, range, aref);
+
+	labpc_setup_cmd6_reg(dev, s, MODE_SINGLE_CHAN, fifo_not_empty_transfer,
+			     range, aref, false);
+
+	/* setup cmd4 register */
+	devpriv->cmd4 = 0;
+	devpriv->cmd4 |= CMD4_ECLKRCV;
+	/* single-ended/differential */
+	if (aref == AREF_DIFF)
+		devpriv->cmd4 |= CMD4_SEDIFF;
+	devpriv->write_byte(devpriv->cmd4, dev->iobase + CMD4_REG);
+
+	/* initialize pacer counter to prevent any problems */
+	ret = labpc_counter_set_mode(dev, dev->iobase + COUNTER_A_BASE_REG,
+				     0, I8254_MODE2);
+	if (ret)
+		return ret;
+
+	labpc_clear_adc_fifo(dev);
+
+	for (i = 0; i < insn->n; i++) {
+		/* trigger conversion */
+		devpriv->write_byte(0x1, dev->iobase + ADC_START_CONVERT_REG);
+
+		ret = labpc_ai_wait_for_data(dev, LABPC_ADC_TIMEOUT);
+		if (ret)
+			return ret;
+
+		data[i] = labpc_read_adc_fifo(dev);
+	}
+
+	return insn->n;
+}
+
+#ifdef CONFIG_ISA_DMA_API
+/* utility function that suggests a dma transfer size in bytes */
+static unsigned int labpc_suggest_transfer_size(const struct comedi_cmd *cmd)
+{
+	unsigned int size;
+	unsigned int freq;
+
+	if (cmd->convert_src == TRIG_TIMER)
+		freq = 1000000000 / cmd->convert_arg;
+	/* return some default value */
+	else
+		freq = 0xffffffff;
+
+	/* make buffer fill in no more than 1/3 second */
+	size = (freq / 3) * sample_size;
+
+	/* set a minimum and maximum size allowed */
+	if (size > dma_buffer_size)
+		size = dma_buffer_size - dma_buffer_size % sample_size;
+	else if (size < sample_size)
+		size = sample_size;
+
+	return size;
+}
+#endif
+
+static bool labpc_use_continuous_mode(const struct comedi_cmd *cmd,
+				      enum scan_mode mode)
+{
+	if (mode == MODE_SINGLE_CHAN || cmd->scan_begin_src == TRIG_FOLLOW)
+		return true;
+
+	return false;
+}
+
+static unsigned int labpc_ai_convert_period(const struct comedi_cmd *cmd,
+					    enum scan_mode mode)
+{
+	if (cmd->convert_src != TRIG_TIMER)
+		return 0;
+
+	if (mode == MODE_SINGLE_CHAN && cmd->scan_begin_src == TRIG_TIMER)
+		return cmd->scan_begin_arg;
+
+	return cmd->convert_arg;
+}
+
+static void labpc_set_ai_convert_period(struct comedi_cmd *cmd,
+					enum scan_mode mode, unsigned int ns)
+{
+	if (cmd->convert_src != TRIG_TIMER)
+		return;
+
+	if (mode == MODE_SINGLE_CHAN &&
+	    cmd->scan_begin_src == TRIG_TIMER) {
+		cmd->scan_begin_arg = ns;
+		if (cmd->convert_arg > cmd->scan_begin_arg)
+			cmd->convert_arg = cmd->scan_begin_arg;
+	} else
+		cmd->convert_arg = ns;
+}
+
+static unsigned int labpc_ai_scan_period(const struct comedi_cmd *cmd,
+					enum scan_mode mode)
+{
+	if (cmd->scan_begin_src != TRIG_TIMER)
+		return 0;
+
+	if (mode == MODE_SINGLE_CHAN && cmd->convert_src == TRIG_TIMER)
+		return 0;
+
+	return cmd->scan_begin_arg;
+}
+
+static void labpc_set_ai_scan_period(struct comedi_cmd *cmd,
+				     enum scan_mode mode, unsigned int ns)
+{
+	if (cmd->scan_begin_src != TRIG_TIMER)
+		return;
+
+	if (mode == MODE_SINGLE_CHAN && cmd->convert_src == TRIG_TIMER)
+		return;
+
+	cmd->scan_begin_arg = ns;
+}
+
+/* figures out what counter values to use based on command */
+static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd,
+			     enum scan_mode mode)
+{
+	struct labpc_private *devpriv = dev->private;
+	/* max value for 16 bit counter in mode 2 */
+	const int max_counter_value = 0x10000;
+	/* min value for 16 bit counter in mode 2 */
+	const int min_counter_value = 2;
+	unsigned int base_period;
+	unsigned int scan_period;
+	unsigned int convert_period;
+
+	/*
+	 * if both convert and scan triggers are TRIG_TIMER, then they
+	 * both rely on counter b0
+	 */
+	convert_period = labpc_ai_convert_period(cmd, mode);
+	scan_period = labpc_ai_scan_period(cmd, mode);
+	if (convert_period && scan_period) {
+		/*
+		 * pick the lowest b0 divisor value we can (for maximum input
+		 * clock speed on convert and scan counters)
+		 */
+		devpriv->divisor_b0 = (scan_period - 1) /
+		    (LABPC_TIMER_BASE * max_counter_value) + 1;
+		if (devpriv->divisor_b0 < min_counter_value)
+			devpriv->divisor_b0 = min_counter_value;
+		if (devpriv->divisor_b0 > max_counter_value)
+			devpriv->divisor_b0 = max_counter_value;
+
+		base_period = LABPC_TIMER_BASE * devpriv->divisor_b0;
+
+		/*  set a0 for conversion frequency and b1 for scan frequency */
+		switch (cmd->flags & TRIG_ROUND_MASK) {
+		default:
+		case TRIG_ROUND_NEAREST:
+			devpriv->divisor_a0 =
+			    (convert_period + (base_period / 2)) / base_period;
+			devpriv->divisor_b1 =
+			    (scan_period + (base_period / 2)) / base_period;
+			break;
+		case TRIG_ROUND_UP:
+			devpriv->divisor_a0 =
+			    (convert_period + (base_period - 1)) / base_period;
+			devpriv->divisor_b1 =
+			    (scan_period + (base_period - 1)) / base_period;
+			break;
+		case TRIG_ROUND_DOWN:
+			devpriv->divisor_a0 = convert_period / base_period;
+			devpriv->divisor_b1 = scan_period / base_period;
+			break;
+		}
+		/*  make sure a0 and b1 values are acceptable */
+		if (devpriv->divisor_a0 < min_counter_value)
+			devpriv->divisor_a0 = min_counter_value;
+		if (devpriv->divisor_a0 > max_counter_value)
+			devpriv->divisor_a0 = max_counter_value;
+		if (devpriv->divisor_b1 < min_counter_value)
+			devpriv->divisor_b1 = min_counter_value;
+		if (devpriv->divisor_b1 > max_counter_value)
+			devpriv->divisor_b1 = max_counter_value;
+		/*  write corrected timings to command */
+		labpc_set_ai_convert_period(cmd, mode,
+					    base_period * devpriv->divisor_a0);
+		labpc_set_ai_scan_period(cmd, mode,
+					 base_period * devpriv->divisor_b1);
+		/*
+		 * if only one TRIG_TIMER is used, we can employ the generic
+		 * cascaded timing functions
+		 */
+	} else if (scan_period) {
+		/*
+		 * calculate cascaded counter values
+		 * that give desired scan timing
+		 */
+		i8253_cascade_ns_to_timer_2div(LABPC_TIMER_BASE,
+					       &(devpriv->divisor_b1),
+					       &(devpriv->divisor_b0),
+					       &scan_period,
+					       cmd->flags & TRIG_ROUND_MASK);
+		labpc_set_ai_scan_period(cmd, mode, scan_period);
+	} else if (convert_period) {
+		/*
+		 * calculate cascaded counter values
+		 * that give desired conversion timing
+		 */
+		i8253_cascade_ns_to_timer_2div(LABPC_TIMER_BASE,
+					       &(devpriv->divisor_a0),
+					       &(devpriv->divisor_b0),
+					       &convert_period,
+					       cmd->flags & TRIG_ROUND_MASK);
+		labpc_set_ai_convert_period(cmd, mode, convert_period);
+	}
+}
+
+static enum scan_mode labpc_ai_scan_mode(const struct comedi_cmd *cmd)
+{
+	if (cmd->chanlist_len == 1)
+		return MODE_SINGLE_CHAN;
+
+	/* chanlist may be NULL during cmdtest. */
 	if (cmd->chanlist == NULL)
 		return MODE_MULT_CHAN_UP;
 
@@ -923,101 +763,39 @@ static int labpc_ai_chanlist_invalid(const struct comedi_device *dev,
 	return 0;
 }
 
-static int labpc_use_continuous_mode(const struct comedi_cmd *cmd,
-				     enum scan_mode mode)
+static int labpc_ai_cmdtest(struct comedi_device *dev,
+			    struct comedi_subdevice *s, struct comedi_cmd *cmd)
 {
-	if (mode == MODE_SINGLE_CHAN)
-		return 1;
+	const struct labpc_boardinfo *board = comedi_board(dev);
+	int err = 0;
+	int tmp, tmp2;
+	unsigned int stop_mask;
+	enum scan_mode mode;
 
-	if (cmd->scan_begin_src == TRIG_FOLLOW)
-		return 1;
+	/* Step 1 : check if triggers are trivially valid */
 
-	return 0;
-}
+	err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
+	err |= cfc_check_trigger_src(&cmd->scan_begin_src,
+					TRIG_TIMER | TRIG_FOLLOW | TRIG_EXT);
+	err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER | TRIG_EXT);
+	err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
 
-static unsigned int labpc_ai_convert_period(const struct comedi_cmd *cmd,
-					    enum scan_mode mode)
-{
-	if (cmd->convert_src != TRIG_TIMER)
-		return 0;
+	stop_mask = TRIG_COUNT | TRIG_NONE;
+	if (board->register_layout == labpc_1200_layout)
+		stop_mask |= TRIG_EXT;
+	err |= cfc_check_trigger_src(&cmd->stop_src, stop_mask);
 
-	if (mode == MODE_SINGLE_CHAN && cmd->scan_begin_src == TRIG_TIMER)
-		return cmd->scan_begin_arg;
+	if (err)
+		return 1;
 
-	return cmd->convert_arg;
-}
+	/* Step 2a : make sure trigger sources are unique */
 
-static void labpc_set_ai_convert_period(struct comedi_cmd *cmd,
-					enum scan_mode mode, unsigned int ns)
-{
-	if (cmd->convert_src != TRIG_TIMER)
-		return;
+	err |= cfc_check_trigger_is_unique(cmd->start_src);
+	err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
+	err |= cfc_check_trigger_is_unique(cmd->convert_src);
+	err |= cfc_check_trigger_is_unique(cmd->stop_src);
 
-	if (mode == MODE_SINGLE_CHAN &&
-	    cmd->scan_begin_src == TRIG_TIMER) {
-		cmd->scan_begin_arg = ns;
-		if (cmd->convert_arg > cmd->scan_begin_arg)
-			cmd->convert_arg = cmd->scan_begin_arg;
-	} else
-		cmd->convert_arg = ns;
-}
-
-static unsigned int labpc_ai_scan_period(const struct comedi_cmd *cmd,
-					enum scan_mode mode)
-{
-	if (cmd->scan_begin_src != TRIG_TIMER)
-		return 0;
-
-	if (mode == MODE_SINGLE_CHAN && cmd->convert_src == TRIG_TIMER)
-		return 0;
-
-	return cmd->scan_begin_arg;
-}
-
-static void labpc_set_ai_scan_period(struct comedi_cmd *cmd,
-				     enum scan_mode mode, unsigned int ns)
-{
-	if (cmd->scan_begin_src != TRIG_TIMER)
-		return;
-
-	if (mode == MODE_SINGLE_CHAN && cmd->convert_src == TRIG_TIMER)
-		return;
-
-	cmd->scan_begin_arg = ns;
-}
-
-static int labpc_ai_cmdtest(struct comedi_device *dev,
-			    struct comedi_subdevice *s, struct comedi_cmd *cmd)
-{
-	int err = 0;
-	int tmp, tmp2;
-	unsigned int stop_mask;
-	enum scan_mode mode;
-
-	/* Step 1 : check if triggers are trivially valid */
-
-	err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
-	err |= cfc_check_trigger_src(&cmd->scan_begin_src,
-					TRIG_TIMER | TRIG_FOLLOW | TRIG_EXT);
-	err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER | TRIG_EXT);
-	err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-
-	stop_mask = TRIG_COUNT | TRIG_NONE;
-	if (thisboard->register_layout == labpc_1200_layout)
-		stop_mask |= TRIG_EXT;
-	err |= cfc_check_trigger_src(&cmd->stop_src, stop_mask);
-
-	if (err)
-		return 1;
-
-	/* Step 2a : make sure trigger sources are unique */
-
-	err |= cfc_check_trigger_is_unique(cmd->start_src);
-	err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
-	err |= cfc_check_trigger_is_unique(cmd->convert_src);
-	err |= cfc_check_trigger_is_unique(cmd->stop_src);
-
-	/* Step 2b : and mutually compatible */
+	/* Step 2b : and mutually compatible */
 
 	/* can't have external stop and start triggers at once */
 	if (cmd->start_src == TRIG_EXT && cmd->stop_src == TRIG_EXT)
@@ -1037,7 +815,7 @@ static int labpc_ai_cmdtest(struct comedi_device *dev,
 
 	if (cmd->convert_src == TRIG_TIMER)
 		err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
-						 thisboard->ai_speed);
+						 board->ai_speed);
 
 	/* make sure scan timing is not too fast */
 	if (cmd->scan_begin_src == TRIG_TIMER) {
@@ -1045,7 +823,7 @@ static int labpc_ai_cmdtest(struct comedi_device *dev,
 			err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
 					cmd->convert_arg * cmd->chanlist_len);
 		err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
-				thisboard->ai_speed * cmd->chanlist_len);
+				board->ai_speed * cmd->chanlist_len);
 	}
 
 	switch (cmd->stop_src) {
@@ -1086,34 +864,23 @@ static int labpc_ai_cmdtest(struct comedi_device *dev,
 
 static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+	const struct labpc_boardinfo *board = comedi_board(dev);
 	struct labpc_private *devpriv = dev->private;
-	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;
+	enum scan_mode mode = labpc_ai_scan_mode(cmd);
+	unsigned int chanspec = (mode == MODE_MULT_CHAN_UP)
+				? cmd->chanlist[cmd->chanlist_len - 1]
+				: cmd->chanlist[0];
+	unsigned int chan = CR_CHAN(chanspec);
+	unsigned int range = CR_RANGE(chanspec);
+	unsigned int aref = CR_AREF(chanspec);
 	enum transfer_type xfer;
-	enum scan_mode mode;
 	unsigned long flags;
-
-	if (!dev->irq) {
-		comedi_error(dev, "no irq assigned, cannot perform command");
-		return -1;
-	}
-
-	range = CR_RANGE(cmd->chanlist[0]);
-	aref = CR_AREF(cmd->chanlist[0]);
+	int ret;
 
 	/* make sure board is disabled before setting up acquisition */
-	spin_lock_irqsave(&dev->spinlock, flags);
-	devpriv->command2_bits &= ~SWTRIG_BIT & ~HWTRIG_BIT & ~PRETRIG_BIT;
-	devpriv->write_byte(devpriv->command2_bits, dev->iobase + COMMAND2_REG);
-	spin_unlock_irqrestore(&dev->spinlock, flags);
-
-	devpriv->command3_bits = 0;
-	devpriv->write_byte(devpriv->command3_bits, dev->iobase + COMMAND3_REG);
+	labpc_cancel(dev, s);
 
 	/*  initialize software conversion count */
 	if (cmd->stop_src == TRIG_COUNT)
@@ -1126,17 +893,17 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 		 * (pc+ manual says this is minimum allowed) using mode 0
 		 */
 		ret = labpc_counter_load(dev, dev->iobase + COUNTER_A_BASE_REG,
-					 1, 3, 0);
-		if (ret < 0) {
-			comedi_error(dev, "error loading counter a1");
-			return -1;
-		}
-	} else			/*
-				 * otherwise, just put a1 in mode 0
-				 * with no count to set its output low
-				 */
-		devpriv->write_byte(INIT_A1_BITS,
-				    dev->iobase + COUNTER_A_CONTROL_REG);
+					 1, 3, I8254_MODE0);
+	} else	{
+		/* just put counter a1 in mode 0 to set its output low */
+		ret = labpc_counter_set_mode(dev,
+					     dev->iobase + COUNTER_A_BASE_REG,
+					     1, I8254_MODE0);
+	}
+	if (ret) {
+		comedi_error(dev, "error loading counter a1");
+		return ret;
+	}
 
 #ifdef CONFIG_ISA_DMA_API
 	/*  figure out what method we will use to transfer data */
@@ -1147,12 +914,12 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 		 */
 	    (cmd->flags & (TRIG_WAKE_EOS | TRIG_RT)) == 0 &&
 	    /*  only available on the isa boards */
-	    thisboard->bustype == isa_bustype) {
+	    board->bustype == isa_bustype) {
 		xfer = isa_dma_transfer;
 		/* pc-plus has no fifo-half full interrupt */
 	} else
 #endif
-	if (thisboard->register_layout == labpc_1200_layout &&
+	if (board->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 */
@@ -1161,76 +928,34 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 	} else
 		xfer = fifo_not_empty_transfer;
 	devpriv->current_transfer = xfer;
-	mode = labpc_ai_scan_mode(cmd);
 
-	/*  setup command6 register for 1200 boards */
-	if (thisboard->register_layout == labpc_1200_layout) {
-		/*  reference inputs to ground or common? */
-		if (aref != AREF_GROUND)
-			devpriv->command6_bits |= ADC_COMMON_BIT;
-		else
-			devpriv->command6_bits &= ~ADC_COMMON_BIT;
-		/*  bipolar or unipolar range? */
-		if (thisboard->ai_range_is_unipolar[range])
-			devpriv->command6_bits |= ADC_UNIP_BIT;
-		else
-			devpriv->command6_bits &= ~ADC_UNIP_BIT;
-		/*  interrupt on fifo half full? */
-		if (xfer == fifo_half_full_transfer)
-			devpriv->command6_bits |= ADC_FHF_INTR_EN_BIT;
-		else
-			devpriv->command6_bits &= ~ADC_FHF_INTR_EN_BIT;
-		/*  enable interrupt on counter a1 terminal count? */
-		if (cmd->stop_src == TRIG_EXT)
-			devpriv->command6_bits |= A1_INTR_EN_BIT;
-		else
-			devpriv->command6_bits &= ~A1_INTR_EN_BIT;
-		/*  are we scanning up or down through channels? */
-		if (mode == MODE_MULT_CHAN_UP)
-			devpriv->command6_bits |= ADC_SCAN_UP_BIT;
-		else
-			devpriv->command6_bits &= ~ADC_SCAN_UP_BIT;
-		/*  write to register */
-		devpriv->write_byte(devpriv->command6_bits,
-				    dev->iobase + COMMAND6_REG);
-	}
+	labpc_ai_set_chan_and_gain(dev, mode, chan, range, aref);
+
+	labpc_setup_cmd6_reg(dev, s, mode, xfer, range, aref,
+			     (cmd->stop_src == TRIG_EXT));
 
-	/* setup channel list, etc (command1 register) */
-	devpriv->command1_bits = 0;
-	if (mode == MODE_MULT_CHAN_UP)
-		channel = CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1]);
-	else
-		channel = CR_CHAN(cmd->chanlist[0]);
-	/* munge channel bits for differential / scan disabled mode */
-	if ((mode == MODE_SINGLE_CHAN || mode == MODE_SINGLE_CHAN_INTERVAL) &&
-	    aref == AREF_DIFF)
-		channel *= 2;
-	devpriv->command1_bits |= ADC_CHAN_BITS(channel);
-	devpriv->command1_bits |= thisboard->ai_range_code[range];
-	devpriv->write_byte(devpriv->command1_bits, dev->iobase + COMMAND1_REG);
 	/* manual says to set scan enable bit on second pass */
 	if (mode == MODE_MULT_CHAN_UP || mode == MODE_MULT_CHAN_DOWN) {
-		devpriv->command1_bits |= ADC_SCAN_EN_BIT;
+		devpriv->cmd1 |= CMD1_SCANEN;
 		/* need a brief delay before enabling scan, or scan
 		 * list will get screwed when you switch
 		 * between scan up to scan down mode - dunno why */
 		udelay(1);
-		devpriv->write_byte(devpriv->command1_bits,
-				    dev->iobase + COMMAND1_REG);
+		devpriv->write_byte(devpriv->cmd1, dev->iobase + CMD1_REG);
 	}
 
 	devpriv->write_byte(cmd->chanlist_len,
 			    dev->iobase + INTERVAL_COUNT_REG);
 	/*  load count */
-	devpriv->write_byte(INTERVAL_LOAD_BITS,
-			    dev->iobase + INTERVAL_LOAD_REG);
+	devpriv->write_byte(0x1, dev->iobase + INTERVAL_STROBE_REG);
 
-	if (cmd->convert_src == TRIG_TIMER || cmd->scan_begin_src == TRIG_TIMER) {
+	if (cmd->convert_src == TRIG_TIMER ||
+	    cmd->scan_begin_src == TRIG_TIMER) {
 		/*  set up pacing */
 		labpc_adc_timing(dev, cmd, mode);
 		/*  load counter b0 in mode 3 */
 		ret = labpc_counter_load(dev, dev->iobase + COUNTER_B_BASE_REG,
-					 0, devpriv->divisor_b0, 3);
+					 0, devpriv->divisor_b0, I8254_MODE3);
 		if (ret < 0) {
 			comedi_error(dev, "error loading counter b0");
 			return -1;
@@ -1240,20 +965,23 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 	if (labpc_ai_convert_period(cmd, mode)) {
 		/*  load counter a0 in mode 2 */
 		ret = labpc_counter_load(dev, dev->iobase + COUNTER_A_BASE_REG,
-					 0, devpriv->divisor_a0, 2);
-		if (ret < 0) {
-			comedi_error(dev, "error loading counter a0");
-			return -1;
-		}
-	} else
-		devpriv->write_byte(INIT_A0_BITS,
-				    dev->iobase + COUNTER_A_CONTROL_REG);
+					 0, devpriv->divisor_a0, I8254_MODE2);
+	} else {
+		/* initialize pacer counter to prevent any problems */
+		ret = labpc_counter_set_mode(dev,
+					     dev->iobase + COUNTER_A_BASE_REG,
+					     0, I8254_MODE2);
+	}
+	if (ret) {
+		comedi_error(dev, "error loading counter a0");
+		return ret;
+	}
 
 	/*  set up scan pacing */
 	if (labpc_ai_scan_period(cmd, mode)) {
 		/*  load counter b1 in mode 2 */
 		ret = labpc_counter_load(dev, dev->iobase + COUNTER_B_BASE_REG,
-					 1, devpriv->divisor_b1, 2);
+					 1, devpriv->divisor_b1, I8254_MODE2);
 		if (ret < 0) {
 			comedi_error(dev, "error loading counter b1");
 			return -1;
@@ -1265,6 +993,8 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 #ifdef CONFIG_ISA_DMA_API
 	/*  set up dma transfer */
 	if (xfer == isa_dma_transfer) {
+		unsigned long irq_flags;
+
 		irq_flags = claim_dma_lock();
 		disable_dma(devpriv->dma_chan);
 		/* clear flip-flop to make sure 2-byte registers for
@@ -1283,197 +1013,54 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 		enable_dma(devpriv->dma_chan);
 		release_dma_lock(irq_flags);
 		/*  enable board's dma */
-		devpriv->command3_bits |= DMA_EN_BIT | DMATC_INTR_EN_BIT;
+		devpriv->cmd3 |= (CMD3_DMAEN | CMD3_DMATCINTEN);
 	} else
-		devpriv->command3_bits &= ~DMA_EN_BIT & ~DMATC_INTR_EN_BIT;
+		devpriv->cmd3 &= ~(CMD3_DMAEN | CMD3_DMATCINTEN);
 #endif
 
 	/*  enable error interrupts */
-	devpriv->command3_bits |= ERR_INTR_EN_BIT;
+	devpriv->cmd3 |= CMD3_ERRINTEN;
 	/*  enable fifo not empty interrupt? */
 	if (xfer == fifo_not_empty_transfer)
-		devpriv->command3_bits |= ADC_FNE_INTR_EN_BIT;
+		devpriv->cmd3 |= CMD3_FIFOINTEN;
 	else
-		devpriv->command3_bits &= ~ADC_FNE_INTR_EN_BIT;
-	devpriv->write_byte(devpriv->command3_bits, dev->iobase + COMMAND3_REG);
+		devpriv->cmd3 &= ~CMD3_FIFOINTEN;
+	devpriv->write_byte(devpriv->cmd3, dev->iobase + CMD3_REG);
 
-	/*  setup any external triggering/pacing (command4 register) */
-	devpriv->command4_bits = 0;
+	/*  setup any external triggering/pacing (cmd4 register) */
+	devpriv->cmd4 = 0;
 	if (cmd->convert_src != TRIG_EXT)
-		devpriv->command4_bits |= EXT_CONVERT_DISABLE_BIT;
+		devpriv->cmd4 |= CMD4_ECLKRCV;
 	/* XXX should discard first scan when using interval scanning
 	 * since manual says it is not synced with scan clock */
-	if (labpc_use_continuous_mode(cmd, mode) == 0) {
-		devpriv->command4_bits |= INTERVAL_SCAN_EN_BIT;
+	if (!labpc_use_continuous_mode(cmd, mode)) {
+		devpriv->cmd4 |= CMD4_INTSCAN;
 		if (cmd->scan_begin_src == TRIG_EXT)
-			devpriv->command4_bits |= EXT_SCAN_EN_BIT;
+			devpriv->cmd4 |= CMD4_EOIRCV;
 	}
 	/*  single-ended/differential */
 	if (aref == AREF_DIFF)
-		devpriv->command4_bits |= ADC_DIFF_BIT;
-	devpriv->write_byte(devpriv->command4_bits, dev->iobase + COMMAND4_REG);
+		devpriv->cmd4 |= CMD4_SEDIFF;
+	devpriv->write_byte(devpriv->cmd4, dev->iobase + CMD4_REG);
 
 	/*  startup acquisition */
 
-	/*  command2 reg */
-	/*  use 2 cascaded counters for pacing */
 	spin_lock_irqsave(&dev->spinlock, flags);
-	devpriv->command2_bits |= CASCADE_BIT;
-	switch (cmd->start_src) {
-	case TRIG_EXT:
-		devpriv->command2_bits |= HWTRIG_BIT;
-		devpriv->command2_bits &= ~PRETRIG_BIT & ~SWTRIG_BIT;
-		break;
-	case TRIG_NOW:
-		devpriv->command2_bits |= SWTRIG_BIT;
-		devpriv->command2_bits &= ~PRETRIG_BIT & ~HWTRIG_BIT;
-		break;
-	default:
-		comedi_error(dev, "bug with start_src");
-		spin_unlock_irqrestore(&dev->spinlock, flags);
-		return -1;
-		break;
-	}
-	switch (cmd->stop_src) {
-	case TRIG_EXT:
-		devpriv->command2_bits |= HWTRIG_BIT | PRETRIG_BIT;
-		break;
-	case TRIG_COUNT:
-	case TRIG_NONE:
-		break;
-	default:
-		comedi_error(dev, "bug with stop_src");
-		spin_unlock_irqrestore(&dev->spinlock, flags);
-		return -1;
-	}
-	devpriv->write_byte(devpriv->command2_bits, dev->iobase + COMMAND2_REG);
-	spin_unlock_irqrestore(&dev->spinlock, flags);
-
-	return 0;
-}
-
-/* interrupt service routine */
-static irqreturn_t labpc_interrupt(int irq, void *d)
-{
-	struct comedi_device *dev = d;
-	struct labpc_private *devpriv = dev->private;
-	struct comedi_subdevice *s = dev->read_subdev;
-	struct comedi_async *async;
-	struct comedi_cmd *cmd;
-
-	if (dev->attached == 0) {
-		comedi_error(dev, "premature interrupt");
-		return IRQ_HANDLED;
-	}
-
-	async = s->async;
-	cmd = &async->cmd;
-	async->events = 0;
-
-	/* read board status */
-	devpriv->status1_bits = devpriv->read_byte(dev->iobase + STATUS1_REG);
-	if (thisboard->register_layout == labpc_1200_layout)
-		devpriv->status2_bits =
-		    devpriv->read_byte(dev->iobase + STATUS2_REG);
-
-	if ((devpriv->status1_bits & (DMATC_BIT | TIMER_BIT | OVERFLOW_BIT |
-				      OVERRUN_BIT | DATA_AVAIL_BIT)) == 0
-	    && (devpriv->status2_bits & A1_TC_BIT) == 0
-	    && (devpriv->status2_bits & FNHF_BIT)) {
-		return IRQ_NONE;
-	}
-
-	if (devpriv->status1_bits & OVERRUN_BIT) {
-		/* clear error interrupt */
-		devpriv->write_byte(0x1, dev->iobase + ADC_CLEAR_REG);
-		async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
-		comedi_event(dev, s);
-		comedi_error(dev, "overrun");
-		return IRQ_HANDLED;
-	}
-
-#ifdef CONFIG_ISA_DMA_API
-	if (devpriv->current_transfer == isa_dma_transfer) {
-		/*
-		 * if a dma terminal count of external stop trigger
-		 * has occurred
-		 */
-		if (devpriv->status1_bits & DMATC_BIT ||
-		    (thisboard->register_layout == labpc_1200_layout
-		     && devpriv->status2_bits & A1_TC_BIT)) {
-			handle_isa_dma(dev);
-		}
-	} else
-#endif
-		labpc_drain_fifo(dev);
-
-	if (devpriv->status1_bits & TIMER_BIT) {
-		comedi_error(dev, "handled timer interrupt?");
-		/*  clear it */
-		devpriv->write_byte(0x1, dev->iobase + TIMER_CLEAR_REG);
-	}
-
-	if (devpriv->status1_bits & OVERFLOW_BIT) {
-		/*  clear error interrupt */
-		devpriv->write_byte(0x1, dev->iobase + ADC_CLEAR_REG);
-		async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
-		comedi_event(dev, s);
-		comedi_error(dev, "overflow");
-		return IRQ_HANDLED;
-	}
-	/*  handle external stop trigger */
-	if (cmd->stop_src == TRIG_EXT) {
-		if (devpriv->status2_bits & A1_TC_BIT) {
-			labpc_drain_dregs(dev);
-			labpc_cancel(dev, s);
-			async->events |= COMEDI_CB_EOA;
-		}
-	}
 
-	/* TRIG_COUNT end of acquisition */
-	if (cmd->stop_src == TRIG_COUNT) {
-		if (devpriv->count == 0) {
-			labpc_cancel(dev, s);
-			async->events |= COMEDI_CB_EOA;
-		}
-	}
-
-	comedi_event(dev, s);
-	return IRQ_HANDLED;
-}
+	/* use 2 cascaded counters for pacing */
+	devpriv->cmd2 |= CMD2_TBSEL;
 
-/* read all available samples from ai fifo */
-static int labpc_drain_fifo(struct comedi_device *dev)
-{
-	struct labpc_private *devpriv = dev->private;
-	unsigned int lsb, msb;
-	short data;
-	struct comedi_async *async = dev->read_subdev->async;
-	const int timeout = 10000;
-	unsigned int i;
+	devpriv->cmd2 &= ~(CMD2_SWTRIG | CMD2_HWTRIG | CMD2_PRETRIG);
+	if (cmd->start_src == TRIG_EXT)
+		devpriv->cmd2 |= CMD2_HWTRIG;
+	else
+		devpriv->cmd2 |= CMD2_SWTRIG;
+	if (cmd->stop_src == TRIG_EXT)
+		devpriv->cmd2 |= (CMD2_HWTRIG | CMD2_PRETRIG);
 
-	devpriv->status1_bits = devpriv->read_byte(dev->iobase + STATUS1_REG);
+	devpriv->write_byte(devpriv->cmd2, dev->iobase + CMD2_REG);
 
-	for (i = 0; (devpriv->status1_bits & DATA_AVAIL_BIT) && i < timeout;
-	     i++) {
-		/*  quit if we have all the data we want */
-		if (async->cmd.stop_src == TRIG_COUNT) {
-			if (devpriv->count == 0)
-				break;
-			devpriv->count--;
-		}
-		lsb = devpriv->read_byte(dev->iobase + ADC_FIFO_REG);
-		msb = devpriv->read_byte(dev->iobase + ADC_FIFO_REG);
-		data = (msb << 8) | lsb;
-		cfc_write_to_buffer(dev->read_subdev, data);
-		devpriv->status1_bits =
-		    devpriv->read_byte(dev->iobase + STATUS1_REG);
-	}
-	if (i == timeout) {
-		comedi_error(dev, "ai timeout, fifo never empties");
-		async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
-		return -1;
-	}
+	spin_unlock_irqrestore(&dev->spinlock, flags);
 
 	return 0;
 }
@@ -1489,7 +1076,7 @@ static void labpc_drain_dma(struct comedi_device *dev)
 	unsigned int max_points, num_points, residue, leftover;
 	int i;
 
-	status = devpriv->status1_bits;
+	status = devpriv->stat1;
 
 	flags = claim_dma_lock();
 	disable_dma(devpriv->dma_chan);
@@ -1546,6 +1133,38 @@ static void handle_isa_dma(struct comedi_device *dev)
 }
 #endif
 
+/* read all available samples from ai fifo */
+static int labpc_drain_fifo(struct comedi_device *dev)
+{
+	struct labpc_private *devpriv = dev->private;
+	short data;
+	struct comedi_async *async = dev->read_subdev->async;
+	const int timeout = 10000;
+	unsigned int i;
+
+	devpriv->stat1 = devpriv->read_byte(dev->iobase + STAT1_REG);
+
+	for (i = 0; (devpriv->stat1 & STAT1_DAVAIL) && i < timeout;
+	     i++) {
+		/*  quit if we have all the data we want */
+		if (async->cmd.stop_src == TRIG_COUNT) {
+			if (devpriv->count == 0)
+				break;
+			devpriv->count--;
+		}
+		data = labpc_read_adc_fifo(dev);
+		cfc_write_to_buffer(dev->read_subdev, data);
+		devpriv->stat1 = devpriv->read_byte(dev->iobase + STAT1_REG);
+	}
+	if (i == timeout) {
+		comedi_error(dev, "ai timeout, fifo never empties");
+		async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
+		return -1;
+	}
+
+	return 0;
+}
+
 /* 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)
@@ -1560,99 +1179,102 @@ static void labpc_drain_dregs(struct comedi_device *dev)
 	labpc_drain_fifo(dev);
 }
 
-static int labpc_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
-			  struct comedi_insn *insn, unsigned int *data)
+/* interrupt service routine */
+static irqreturn_t labpc_interrupt(int irq, void *d)
 {
+	struct comedi_device *dev = d;
+	const struct labpc_boardinfo *board = comedi_board(dev);
 	struct labpc_private *devpriv = dev->private;
-	int i, n;
-	int chan, range;
-	int lsb, msb;
-	int timeout = 1000;
-	unsigned long flags;
+	struct comedi_subdevice *s = dev->read_subdev;
+	struct comedi_async *async;
+	struct comedi_cmd *cmd;
 
-	/*  disable timed conversions */
-	spin_lock_irqsave(&dev->spinlock, flags);
-	devpriv->command2_bits &= ~SWTRIG_BIT & ~HWTRIG_BIT & ~PRETRIG_BIT;
-	devpriv->write_byte(devpriv->command2_bits, dev->iobase + COMMAND2_REG);
-	spin_unlock_irqrestore(&dev->spinlock, flags);
+	if (!dev->attached) {
+		comedi_error(dev, "premature interrupt");
+		return IRQ_HANDLED;
+	}
 
-	/*  disable interrupt generation and dma */
-	devpriv->command3_bits = 0;
-	devpriv->write_byte(devpriv->command3_bits, dev->iobase + COMMAND3_REG);
+	async = s->async;
+	cmd = &async->cmd;
+	async->events = 0;
 
-	/* set gain and channel */
-	devpriv->command1_bits = 0;
-	chan = CR_CHAN(insn->chanspec);
-	range = CR_RANGE(insn->chanspec);
-	devpriv->command1_bits |= thisboard->ai_range_code[range];
-	/* munge channel bits for differential/scan disabled mode */
-	if (CR_AREF(insn->chanspec) == AREF_DIFF)
-		chan *= 2;
-	devpriv->command1_bits |= ADC_CHAN_BITS(chan);
-	devpriv->write_byte(devpriv->command1_bits, dev->iobase + COMMAND1_REG);
-
-	/* setup command6 register for 1200 boards */
-	if (thisboard->register_layout == labpc_1200_layout) {
-		/*  reference inputs to ground or common? */
-		if (CR_AREF(insn->chanspec) != AREF_GROUND)
-			devpriv->command6_bits |= ADC_COMMON_BIT;
-		else
-			devpriv->command6_bits &= ~ADC_COMMON_BIT;
-		/* bipolar or unipolar range? */
-		if (thisboard->ai_range_is_unipolar[range])
-			devpriv->command6_bits |= ADC_UNIP_BIT;
-		else
-			devpriv->command6_bits &= ~ADC_UNIP_BIT;
-		/* don't interrupt on fifo half full */
-		devpriv->command6_bits &= ~ADC_FHF_INTR_EN_BIT;
-		/* don't enable interrupt on counter a1 terminal count? */
-		devpriv->command6_bits &= ~A1_INTR_EN_BIT;
-		/* write to register */
-		devpriv->write_byte(devpriv->command6_bits,
-				    dev->iobase + COMMAND6_REG);
+	/* read board status */
+	devpriv->stat1 = devpriv->read_byte(dev->iobase + STAT1_REG);
+	if (board->register_layout == labpc_1200_layout)
+		devpriv->stat2 = devpriv->read_byte(dev->iobase + STAT2_REG);
+
+	if ((devpriv->stat1 & (STAT1_GATA0 | STAT1_CNTINT | STAT1_OVERFLOW |
+			       STAT1_OVERRUN | STAT1_DAVAIL)) == 0
+	    && (devpriv->stat2 & STAT2_OUTA1) == 0
+	    && (devpriv->stat2 & STAT2_FIFONHF)) {
+		return IRQ_NONE;
 	}
-	/* setup command4 register */
-	devpriv->command4_bits = 0;
-	devpriv->command4_bits |= EXT_CONVERT_DISABLE_BIT;
-	/* single-ended/differential */
-	if (CR_AREF(insn->chanspec) == AREF_DIFF)
-		devpriv->command4_bits |= ADC_DIFF_BIT;
-	devpriv->write_byte(devpriv->command4_bits, dev->iobase + COMMAND4_REG);
 
-	/*
-	 * initialize pacer counter output to make sure it doesn't
-	 * cause any problems
-	 */
-	devpriv->write_byte(INIT_A0_BITS, dev->iobase + COUNTER_A_CONTROL_REG);
+	if (devpriv->stat1 & STAT1_OVERRUN) {
+		/* clear error interrupt */
+		devpriv->write_byte(0x1, dev->iobase + ADC_FIFO_CLEAR_REG);
+		async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
+		comedi_event(dev, s);
+		comedi_error(dev, "overrun");
+		return IRQ_HANDLED;
+	}
 
-	labpc_clear_adc_fifo(dev);
+#ifdef CONFIG_ISA_DMA_API
+	if (devpriv->current_transfer == isa_dma_transfer) {
+		/*
+		 * if a dma terminal count of external stop trigger
+		 * has occurred
+		 */
+		if (devpriv->stat1 & STAT1_GATA0 ||
+		    (board->register_layout == labpc_1200_layout
+		     && devpriv->stat2 & STAT2_OUTA1)) {
+			handle_isa_dma(dev);
+		}
+	} else
+#endif
+		labpc_drain_fifo(dev);
 
-	for (n = 0; n < insn->n; n++) {
-		/* trigger conversion */
-		devpriv->write_byte(0x1, dev->iobase + ADC_CONVERT_REG);
+	if (devpriv->stat1 & STAT1_CNTINT) {
+		comedi_error(dev, "handled timer interrupt?");
+		/*  clear it */
+		devpriv->write_byte(0x1, dev->iobase + TIMER_CLEAR_REG);
+	}
 
-		for (i = 0; i < timeout; i++) {
-			if (devpriv->read_byte(dev->iobase +
-					       STATUS1_REG) & DATA_AVAIL_BIT)
-				break;
-			udelay(1);
+	if (devpriv->stat1 & STAT1_OVERFLOW) {
+		/*  clear error interrupt */
+		devpriv->write_byte(0x1, dev->iobase + ADC_FIFO_CLEAR_REG);
+		async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
+		comedi_event(dev, s);
+		comedi_error(dev, "overflow");
+		return IRQ_HANDLED;
+	}
+	/*  handle external stop trigger */
+	if (cmd->stop_src == TRIG_EXT) {
+		if (devpriv->stat2 & STAT2_OUTA1) {
+			labpc_drain_dregs(dev);
+			labpc_cancel(dev, s);
+			async->events |= COMEDI_CB_EOA;
 		}
-		if (i == timeout) {
-			comedi_error(dev, "timeout");
-			return -ETIME;
+	}
+
+	/* TRIG_COUNT end of acquisition */
+	if (cmd->stop_src == TRIG_COUNT) {
+		if (devpriv->count == 0) {
+			labpc_cancel(dev, s);
+			async->events |= COMEDI_CB_EOA;
 		}
-		lsb = devpriv->read_byte(dev->iobase + ADC_FIFO_REG);
-		msb = devpriv->read_byte(dev->iobase + ADC_FIFO_REG);
-		data[n] = (msb << 8) | lsb;
 	}
 
-	return n;
+	comedi_event(dev, s);
+	return IRQ_HANDLED;
 }
 
-/* analog output insn */
-static int labpc_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
-			  struct comedi_insn *insn, unsigned int *data)
+static int labpc_ao_insn_write(struct comedi_device *dev,
+			       struct comedi_subdevice *s,
+			       struct comedi_insn *insn,
+			       unsigned int *data)
 {
+	const struct labpc_boardinfo *board = comedi_board(dev);
 	struct labpc_private *devpriv = dev->private;
 	int channel, range;
 	unsigned long flags;
@@ -1664,20 +1286,19 @@ static int labpc_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
 	/* note: hardware bug in daqcard-1200 means pacing cannot
 	 * be independently enabled/disabled for its the two channels */
 	spin_lock_irqsave(&dev->spinlock, flags);
-	devpriv->command2_bits &= ~DAC_PACED_BIT(channel);
-	devpriv->write_byte(devpriv->command2_bits, dev->iobase + COMMAND2_REG);
+	devpriv->cmd2 &= ~CMD2_LDAC(channel);
+	devpriv->write_byte(devpriv->cmd2, dev->iobase + CMD2_REG);
 	spin_unlock_irqrestore(&dev->spinlock, flags);
 
 	/* set range */
-	if (thisboard->register_layout == labpc_1200_layout) {
+	if (board->register_layout == labpc_1200_layout) {
 		range = CR_RANGE(insn->chanspec);
-		if (range & AO_RANGE_IS_UNIPOLAR)
-			devpriv->command6_bits |= DAC_UNIP_BIT(channel);
+		if (labpc_range_is_unipolar(s, range))
+			devpriv->cmd6 |= CMD6_DACUNI(channel);
 		else
-			devpriv->command6_bits &= ~DAC_UNIP_BIT(channel);
+			devpriv->cmd6 &= ~CMD6_DACUNI(channel);
 		/*  write to register */
-		devpriv->write_byte(devpriv->command6_bits,
-				    dev->iobase + COMMAND6_REG);
+		devpriv->write_byte(devpriv->cmd6, dev->iobase + CMD6_REG);
 	}
 	/* send data */
 	lsb = data[0] & 0xff;
@@ -1691,9 +1312,10 @@ static int labpc_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
 	return 1;
 }
 
-/* analog output readback insn */
-static int labpc_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
-			  struct comedi_insn *insn, unsigned int *data)
+static int labpc_ao_insn_read(struct comedi_device *dev,
+			      struct comedi_subdevice *s,
+			      struct comedi_insn *insn,
+			      unsigned int *data)
 {
 	struct labpc_private *devpriv = dev->private;
 
@@ -1702,183 +1324,7 @@ static int labpc_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
 	return 1;
 }
 
-static int labpc_calib_read_insn(struct comedi_device *dev,
-				 struct comedi_subdevice *s,
-				 struct comedi_insn *insn, unsigned int *data)
-{
-	struct labpc_private *devpriv = dev->private;
-
-	data[0] = devpriv->caldac[CR_CHAN(insn->chanspec)];
-
-	return 1;
-}
-
-static int labpc_calib_write_insn(struct comedi_device *dev,
-				  struct comedi_subdevice *s,
-				  struct comedi_insn *insn, unsigned int *data)
-{
-	int channel = CR_CHAN(insn->chanspec);
-
-	write_caldac(dev, channel, data[0]);
-	return 1;
-}
-
-static int labpc_eeprom_read_insn(struct comedi_device *dev,
-				  struct comedi_subdevice *s,
-				  struct comedi_insn *insn, unsigned int *data)
-{
-	struct labpc_private *devpriv = dev->private;
-
-	data[0] = devpriv->eeprom_data[CR_CHAN(insn->chanspec)];
-
-	return 1;
-}
-
-static int labpc_eeprom_write_insn(struct comedi_device *dev,
-				   struct comedi_subdevice *s,
-				   struct comedi_insn *insn, unsigned int *data)
-{
-	int channel = CR_CHAN(insn->chanspec);
-	int ret;
-
-	/*  only allow writes to user area of eeprom */
-	if (channel < 16 || channel > 127) {
-		dev_dbg(dev->class_dev,
-			"eeprom writes are only allowed to channels 16 through 127 (the pointer and user areas)\n");
-		return -EINVAL;
-	}
-
-	ret = labpc_eeprom_write(dev, channel, data[0]);
-	if (ret < 0)
-		return ret;
-
-	return 1;
-}
-
-#ifdef CONFIG_ISA_DMA_API
-/* utility function that suggests a dma transfer size in bytes */
-static unsigned int labpc_suggest_transfer_size(const struct comedi_cmd *cmd)
-{
-	unsigned int size;
-	unsigned int freq;
-
-	if (cmd->convert_src == TRIG_TIMER)
-		freq = 1000000000 / cmd->convert_arg;
-	/* return some default value */
-	else
-		freq = 0xffffffff;
-
-	/* make buffer fill in no more than 1/3 second */
-	size = (freq / 3) * sample_size;
-
-	/* set a minimum and maximum size allowed */
-	if (size > dma_buffer_size)
-		size = dma_buffer_size - dma_buffer_size % sample_size;
-	else if (size < sample_size)
-		size = sample_size;
-
-	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,
-			     enum scan_mode mode)
-{
-	struct labpc_private *devpriv = dev->private;
-	/* max value for 16 bit counter in mode 2 */
-	const int max_counter_value = 0x10000;
-	/* min value for 16 bit counter in mode 2 */
-	const int min_counter_value = 2;
-	unsigned int base_period;
-	unsigned int scan_period;
-	unsigned int convert_period;
-
-	/*
-	 * if both convert and scan triggers are TRIG_TIMER, then they
-	 * both rely on counter b0
-	 */
-	convert_period = labpc_ai_convert_period(cmd, mode);
-	scan_period = labpc_ai_scan_period(cmd, mode);
-	if (convert_period && scan_period) {
-		/*
-		 * pick the lowest b0 divisor value we can (for maximum input
-		 * clock speed on convert and scan counters)
-		 */
-		devpriv->divisor_b0 = (scan_period - 1) /
-		    (LABPC_TIMER_BASE * max_counter_value) + 1;
-		if (devpriv->divisor_b0 < min_counter_value)
-			devpriv->divisor_b0 = min_counter_value;
-		if (devpriv->divisor_b0 > max_counter_value)
-			devpriv->divisor_b0 = max_counter_value;
-
-		base_period = LABPC_TIMER_BASE * devpriv->divisor_b0;
-
-		/*  set a0 for conversion frequency and b1 for scan frequency */
-		switch (cmd->flags & TRIG_ROUND_MASK) {
-		default:
-		case TRIG_ROUND_NEAREST:
-			devpriv->divisor_a0 =
-			    (convert_period + (base_period / 2)) / base_period;
-			devpriv->divisor_b1 =
-			    (scan_period + (base_period / 2)) / base_period;
-			break;
-		case TRIG_ROUND_UP:
-			devpriv->divisor_a0 =
-			    (convert_period + (base_period - 1)) / base_period;
-			devpriv->divisor_b1 =
-			    (scan_period + (base_period - 1)) / base_period;
-			break;
-		case TRIG_ROUND_DOWN:
-			devpriv->divisor_a0 = convert_period / base_period;
-			devpriv->divisor_b1 = scan_period / base_period;
-			break;
-		}
-		/*  make sure a0 and b1 values are acceptable */
-		if (devpriv->divisor_a0 < min_counter_value)
-			devpriv->divisor_a0 = min_counter_value;
-		if (devpriv->divisor_a0 > max_counter_value)
-			devpriv->divisor_a0 = max_counter_value;
-		if (devpriv->divisor_b1 < min_counter_value)
-			devpriv->divisor_b1 = min_counter_value;
-		if (devpriv->divisor_b1 > max_counter_value)
-			devpriv->divisor_b1 = max_counter_value;
-		/*  write corrected timings to command */
-		labpc_set_ai_convert_period(cmd, mode,
-					    base_period * devpriv->divisor_a0);
-		labpc_set_ai_scan_period(cmd, mode,
-					 base_period * devpriv->divisor_b1);
-		/*
-		 * if only one TRIG_TIMER is used, we can employ the generic
-		 * cascaded timing functions
-		 */
-	} else if (scan_period) {
-		/*
-		 * calculate cascaded counter values
-		 * that give desired scan timing
-		 */
-		i8253_cascade_ns_to_timer_2div(LABPC_TIMER_BASE,
-					       &(devpriv->divisor_b1),
-					       &(devpriv->divisor_b0),
-					       &scan_period,
-					       cmd->flags & TRIG_ROUND_MASK);
-		labpc_set_ai_scan_period(cmd, mode, scan_period);
-	} else if (convert_period) {
-		/*
-		 * calculate cascaded counter values
-		 * that give desired conversion timing
-		 */
-		i8253_cascade_ns_to_timer_2div(LABPC_TIMER_BASE,
-					       &(devpriv->divisor_a0),
-					       &(devpriv->divisor_b0),
-					       &convert_period,
-					       cmd->flags & TRIG_ROUND_MASK);
-		labpc_set_ai_convert_period(cmd, mode, convert_period);
-	}
-}
-
-static int labpc_dio_mem_callback(int dir, int port, int data,
-				  unsigned long iobase)
+static int labpc_8255_mmio(int dir, int port, int data, unsigned long iobase)
 {
 	if (dir) {
 		writeb(data, (void __iomem *)(iobase + port));
@@ -1897,20 +1343,18 @@ static void labpc_serial_out(struct comedi_device *dev, unsigned int value,
 
 	for (i = 1; i <= value_width; i++) {
 		/*  clear serial clock */
-		devpriv->command5_bits &= ~SCLOCK_BIT;
+		devpriv->cmd5 &= ~CMD5_SCLK;
 		/*  send bits most significant bit first */
 		if (value & (1 << (value_width - i)))
-			devpriv->command5_bits |= SDATA_BIT;
+			devpriv->cmd5 |= CMD5_SDATA;
 		else
-			devpriv->command5_bits &= ~SDATA_BIT;
+			devpriv->cmd5 &= ~CMD5_SDATA;
 		udelay(1);
-		devpriv->write_byte(devpriv->command5_bits,
-				    dev->iobase + COMMAND5_REG);
+		devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG);
 		/*  set clock to load bit */
-		devpriv->command5_bits |= SCLOCK_BIT;
+		devpriv->cmd5 |= CMD5_SCLK;
 		udelay(1);
-		devpriv->write_byte(devpriv->command5_bits,
-				    dev->iobase + COMMAND5_REG);
+		devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG);
 	}
 }
 
@@ -1924,20 +1368,17 @@ static unsigned int labpc_serial_in(struct comedi_device *dev)
 
 	for (i = 1; i <= value_width; i++) {
 		/*  set serial clock */
-		devpriv->command5_bits |= SCLOCK_BIT;
+		devpriv->cmd5 |= CMD5_SCLK;
 		udelay(1);
-		devpriv->write_byte(devpriv->command5_bits,
-				    dev->iobase + COMMAND5_REG);
+		devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG);
 		/*  clear clock bit */
-		devpriv->command5_bits &= ~SCLOCK_BIT;
+		devpriv->cmd5 &= ~CMD5_SCLK;
 		udelay(1);
-		devpriv->write_byte(devpriv->command5_bits,
-				    dev->iobase + COMMAND5_REG);
+		devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG);
 		/*  read bits most significant bit first */
 		udelay(1);
-		devpriv->status2_bits =
-		    devpriv->read_byte(dev->iobase + STATUS2_REG);
-		if (devpriv->status2_bits & EEPROM_OUT_BIT)
+		devpriv->stat2 = devpriv->read_byte(dev->iobase + STAT2_REG);
+		if (devpriv->stat2 & STAT2_PROMOUT)
 			value |= 1 << (value_width - i);
 	}
 
@@ -1955,12 +1396,12 @@ static unsigned int labpc_eeprom_read(struct comedi_device *dev,
 	const int write_length = 8;
 
 	/*  enable read/write to eeprom */
-	devpriv->command5_bits &= ~EEPROM_EN_BIT;
+	devpriv->cmd5 &= ~CMD5_EEPROMCS;
 	udelay(1);
-	devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG);
-	devpriv->command5_bits |= EEPROM_EN_BIT | EEPROM_WRITE_UNPROTECT_BIT;
+	devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG);
+	devpriv->cmd5 |= (CMD5_EEPROMCS | CMD5_WRTPRT);
 	udelay(1);
-	devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG);
+	devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG);
 
 	/*  send read instruction */
 	labpc_serial_out(dev, read_instruction, write_length);
@@ -1970,9 +1411,37 @@ static unsigned int labpc_eeprom_read(struct comedi_device *dev,
 	value = labpc_serial_in(dev);
 
 	/*  disable read/write to eeprom */
-	devpriv->command5_bits &= ~EEPROM_EN_BIT & ~EEPROM_WRITE_UNPROTECT_BIT;
+	devpriv->cmd5 &= ~(CMD5_EEPROMCS | CMD5_WRTPRT);
 	udelay(1);
-	devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG);
+	devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG);
+
+	return value;
+}
+
+static unsigned int labpc_eeprom_read_status(struct comedi_device *dev)
+{
+	struct labpc_private *devpriv = dev->private;
+	unsigned int value;
+	const int read_status_instruction = 0x5;
+	const int write_length = 8;	/*  8 bit write lengths to eeprom */
+
+	/*  enable read/write to eeprom */
+	devpriv->cmd5 &= ~CMD5_EEPROMCS;
+	udelay(1);
+	devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG);
+	devpriv->cmd5 |= (CMD5_EEPROMCS | CMD5_WRTPRT);
+	udelay(1);
+	devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG);
+
+	/*  send read status instruction */
+	labpc_serial_out(dev, read_status_instruction, write_length);
+	/*  read result */
+	value = labpc_serial_in(dev);
+
+	/*  disable read/write to eeprom */
+	devpriv->cmd5 &= ~(CMD5_EEPROMCS | CMD5_WRTPRT);
+	udelay(1);
+	devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG);
 
 	return value;
 }
@@ -2002,68 +1471,40 @@ static int labpc_eeprom_write(struct comedi_device *dev,
 	devpriv->eeprom_data[address] = value;
 
 	/*  enable read/write to eeprom */
-	devpriv->command5_bits &= ~EEPROM_EN_BIT;
+	devpriv->cmd5 &= ~CMD5_EEPROMCS;
 	udelay(1);
-	devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG);
-	devpriv->command5_bits |= EEPROM_EN_BIT | EEPROM_WRITE_UNPROTECT_BIT;
+	devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG);
+	devpriv->cmd5 |= (CMD5_EEPROMCS | CMD5_WRTPRT);
 	udelay(1);
-	devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG);
+	devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG);
 
 	/*  send write_enable instruction */
 	labpc_serial_out(dev, write_enable_instruction, write_length);
-	devpriv->command5_bits &= ~EEPROM_EN_BIT;
+	devpriv->cmd5 &= ~CMD5_EEPROMCS;
 	udelay(1);
-	devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG);
+	devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG);
 
 	/*  send write instruction */
-	devpriv->command5_bits |= EEPROM_EN_BIT;
+	devpriv->cmd5 |= CMD5_EEPROMCS;
 	udelay(1);
-	devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG);
+	devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG);
 	labpc_serial_out(dev, write_instruction, write_length);
 	/*  send 8 bit address to write to */
 	labpc_serial_out(dev, address, write_length);
 	/*  write value */
 	labpc_serial_out(dev, value, write_length);
-	devpriv->command5_bits &= ~EEPROM_EN_BIT;
+	devpriv->cmd5 &= ~CMD5_EEPROMCS;
 	udelay(1);
-	devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG);
+	devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG);
 
 	/*  disable read/write to eeprom */
-	devpriv->command5_bits &= ~EEPROM_EN_BIT & ~EEPROM_WRITE_UNPROTECT_BIT;
+	devpriv->cmd5 &= ~(CMD5_EEPROMCS | CMD5_WRTPRT);
 	udelay(1);
-	devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG);
+	devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG);
 
 	return 0;
 }
 
-static unsigned int labpc_eeprom_read_status(struct comedi_device *dev)
-{
-	struct labpc_private *devpriv = dev->private;
-	unsigned int value;
-	const int read_status_instruction = 0x5;
-	const int write_length = 8;	/*  8 bit write lengths to eeprom */
-
-	/*  enable read/write to eeprom */
-	devpriv->command5_bits &= ~EEPROM_EN_BIT;
-	udelay(1);
-	devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG);
-	devpriv->command5_bits |= EEPROM_EN_BIT | EEPROM_WRITE_UNPROTECT_BIT;
-	udelay(1);
-	devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG);
-
-	/*  send read status instruction */
-	labpc_serial_out(dev, read_status_instruction, write_length);
-	/*  read result */
-	value = labpc_serial_in(dev);
-
-	/*  disable read/write to eeprom */
-	devpriv->command5_bits &= ~EEPROM_EN_BIT & ~EEPROM_WRITE_UNPROTECT_BIT;
-	udelay(1);
-	devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG);
-
-	return value;
-}
-
 /* writes to 8 bit calibration dacs */
 static void write_caldac(struct comedi_device *dev, unsigned int channel,
 			 unsigned int value)
@@ -2075,10 +1516,9 @@ static void write_caldac(struct comedi_device *dev, unsigned int channel,
 	devpriv->caldac[channel] = value;
 
 	/*  clear caldac load bit and make sure we don't write to eeprom */
-	devpriv->command5_bits &=
-	    ~CALDAC_LOAD_BIT & ~EEPROM_EN_BIT & ~EEPROM_WRITE_UNPROTECT_BIT;
+	devpriv->cmd5 &= ~(CMD5_CALDACLD | CMD5_EEPROMCS | CMD5_WRTPRT);
 	udelay(1);
-	devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG);
+	devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG);
 
 	/*  write 4 bit channel */
 	labpc_serial_out(dev, channel, 4);
@@ -2086,42 +1526,403 @@ static void write_caldac(struct comedi_device *dev, unsigned int channel,
 	labpc_serial_out(dev, value, 8);
 
 	/*  set and clear caldac bit to load caldac value */
-	devpriv->command5_bits |= CALDAC_LOAD_BIT;
+	devpriv->cmd5 |= CMD5_CALDACLD;
 	udelay(1);
-	devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG);
-	devpriv->command5_bits &= ~CALDAC_LOAD_BIT;
+	devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG);
+	devpriv->cmd5 &= ~CMD5_CALDACLD;
 	udelay(1);
-	devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG);
+	devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG);
+}
+
+static int labpc_calib_insn_write(struct comedi_device *dev,
+				  struct comedi_subdevice *s,
+				  struct comedi_insn *insn,
+				  unsigned int *data)
+{
+	unsigned int chan = CR_CHAN(insn->chanspec);
+
+	/*
+	 * Only write the last data value to the caldac. Preceding
+	 * data would be overwritten anyway.
+	 */
+	if (insn->n > 0)
+		write_caldac(dev, chan, data[insn->n - 1]);
+
+	return insn->n;
+}
+
+static int labpc_calib_insn_read(struct comedi_device *dev,
+				 struct comedi_subdevice *s,
+				 struct comedi_insn *insn,
+				 unsigned int *data)
+{
+	struct labpc_private *devpriv = dev->private;
+	unsigned int chan = CR_CHAN(insn->chanspec);
+	int i;
+
+	for (i = 0; i < insn->n; i++)
+		data[i] = devpriv->caldac[chan];
+
+	return insn->n;
+}
+
+static int labpc_eeprom_insn_write(struct comedi_device *dev,
+				   struct comedi_subdevice *s,
+				   struct comedi_insn *insn,
+				   unsigned int *data)
+{
+	unsigned int chan = CR_CHAN(insn->chanspec);
+	int ret;
+
+	/* only allow writes to user area of eeprom */
+	if (chan < 16 || chan > 127)
+		return -EINVAL;
+
+	/*
+	 * Only write the last data value to the eeprom. Preceding
+	 * data would be overwritten anyway.
+	 */
+	if (insn->n > 0) {
+		ret = labpc_eeprom_write(dev, chan, data[insn->n - 1]);
+		if (ret)
+			return ret;
+	}
+
+	return insn->n;
+}
+
+static int labpc_eeprom_insn_read(struct comedi_device *dev,
+				  struct comedi_subdevice *s,
+				  struct comedi_insn *insn,
+				  unsigned int *data)
+{
+	struct labpc_private *devpriv = dev->private;
+	unsigned int chan = CR_CHAN(insn->chanspec);
+	int i;
+
+	for (i = 0; i < insn->n; i++)
+		data[i] = devpriv->eeprom_data[chan];
+
+	return insn->n;
 }
 
+int labpc_common_attach(struct comedi_device *dev, unsigned long iobase,
+			unsigned int irq, unsigned int dma_chan)
+{
+	const struct labpc_boardinfo *board = comedi_board(dev);
+	struct labpc_private *devpriv = dev->private;
+	struct comedi_subdevice *s;
+	unsigned long isr_flags;
+	int ret;
+	int i;
+
+	dev->board_name = board->name;
+
+	if (iobase == 0)
+		return -EINVAL;
+	if (board->bustype == isa_bustype) {
+		if (!request_region(iobase, LABPC_SIZE, dev->board_name))
+			return -EIO;
+	}
+	dev->iobase = iobase;
+
+	if (board->has_mmio) {
+		devpriv->read_byte = labpc_readb;
+		devpriv->write_byte = labpc_writeb;
+	} else {
+		devpriv->read_byte = labpc_inb;
+		devpriv->write_byte = labpc_outb;
+	}
+
+	/* initialize board's command registers */
+	devpriv->write_byte(devpriv->cmd1, dev->iobase + CMD1_REG);
+	devpriv->write_byte(devpriv->cmd2, dev->iobase + CMD2_REG);
+	devpriv->write_byte(devpriv->cmd3, dev->iobase + CMD3_REG);
+	devpriv->write_byte(devpriv->cmd4, dev->iobase + CMD4_REG);
+	if (board->register_layout == labpc_1200_layout) {
+		devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG);
+		devpriv->write_byte(devpriv->cmd6, dev->iobase + CMD6_REG);
+	}
+
+	if (irq) {
+		isr_flags = 0;
+		if (board->bustype == pci_bustype ||
+		    board->bustype == pcmcia_bustype)
+			isr_flags |= IRQF_SHARED;
+		ret = request_irq(irq, labpc_interrupt, isr_flags,
+				  dev->board_name, dev);
+		if (ret == 0)
+			dev->irq = irq;
+	}
+
+#ifdef CONFIG_ISA_DMA_API
+	if (dev->irq && (dma_chan == 1 || dma_chan == 3)) {
+		devpriv->dma_buffer = kmalloc(dma_buffer_size,
+					      GFP_KERNEL | GFP_DMA);
+		if (devpriv->dma_buffer) {
+			ret = request_dma(dma_chan, dev->board_name);
+			if (ret == 0) {
+				unsigned long dma_flags;
+
+				devpriv->dma_chan = dma_chan;
+				dma_flags = claim_dma_lock();
+				disable_dma(devpriv->dma_chan);
+				set_dma_mode(devpriv->dma_chan, DMA_MODE_READ);
+				release_dma_lock(dma_flags);
+			} else {
+				kfree(devpriv->dma_buffer);
+			}
+		}
+	}
+#endif
+
+	ret = comedi_alloc_subdevices(dev, 5);
+	if (ret)
+		return ret;
+
+	/* analog input subdevice */
+	s = &dev->subdevices[0];
+	s->type		= COMEDI_SUBD_AI;
+	s->subdev_flags	= SDF_READABLE | SDF_GROUND | SDF_COMMON | SDF_DIFF;
+	s->n_chan	= 8;
+	s->len_chanlist	= 8;
+	s->maxdata	= 0x0fff;
+	s->range_table	= board->ai_range_table;
+	s->insn_read	= labpc_ai_insn_read;
+	if (dev->irq) {
+		dev->read_subdev = s;
+		s->subdev_flags	|= SDF_CMD_READ;
+		s->do_cmd	= labpc_ai_cmd;
+		s->do_cmdtest	= labpc_ai_cmdtest;
+		s->cancel	= labpc_cancel;
+	}
+
+	/* analog output */
+	s = &dev->subdevices[1];
+	if (board->has_ao) {
+		s->type		= COMEDI_SUBD_AO;
+		s->subdev_flags	= SDF_READABLE | SDF_WRITABLE | SDF_GROUND;
+		s->n_chan	= NUM_AO_CHAN;
+		s->maxdata	= 0x0fff;
+		s->range_table	= &range_labpc_ao;
+		s->insn_read	= labpc_ao_insn_read;
+		s->insn_write	= labpc_ao_insn_write;
+
+		/* initialize analog outputs to a known value */
+		for (i = 0; i < s->n_chan; i++) {
+			short lsb, msb;
+
+			devpriv->ao_value[i] = s->maxdata / 2;
+			lsb = devpriv->ao_value[i] & 0xff;
+			msb = (devpriv->ao_value[i] >> 8) & 0xff;
+			devpriv->write_byte(lsb, dev->iobase + DAC_LSB_REG(i));
+			devpriv->write_byte(msb, dev->iobase + DAC_MSB_REG(i));
+		}
+	} else {
+		s->type		= COMEDI_SUBD_UNUSED;
+	}
+
+	/* 8255 dio */
+	s = &dev->subdevices[2];
+	ret = subdev_8255_init(dev, s,
+			       (board->has_mmio) ? labpc_8255_mmio : NULL,
+			       dev->iobase + DIO_BASE_REG);
+	if (ret)
+		return ret;
+
+	/*  calibration subdevices for boards that have one */
+	s = &dev->subdevices[3];
+	if (board->register_layout == labpc_1200_layout) {
+		s->type		= COMEDI_SUBD_CALIB;
+		s->subdev_flags	= SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
+		s->n_chan	= 16;
+		s->maxdata	= 0xff;
+		s->insn_read	= labpc_calib_insn_read;
+		s->insn_write	= labpc_calib_insn_write;
+
+		for (i = 0; i < s->n_chan; i++)
+			write_caldac(dev, i, s->maxdata / 2);
+	} else
+		s->type		= COMEDI_SUBD_UNUSED;
+
+	/* EEPROM */
+	s = &dev->subdevices[4];
+	if (board->register_layout == labpc_1200_layout) {
+		s->type		= COMEDI_SUBD_MEMORY;
+		s->subdev_flags	= SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
+		s->n_chan	= EEPROM_SIZE;
+		s->maxdata	= 0xff;
+		s->insn_read	= labpc_eeprom_insn_read;
+		s->insn_write	= labpc_eeprom_insn_write;
+
+		for (i = 0; i < s->n_chan; i++)
+			devpriv->eeprom_data[i] = labpc_eeprom_read(dev, i);
+	} else
+		s->type		= COMEDI_SUBD_UNUSED;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(labpc_common_attach);
+
+static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+{
+	const struct labpc_boardinfo *board = comedi_board(dev);
+	struct labpc_private *devpriv;
+	unsigned long iobase = 0;
+	unsigned int irq = 0;
+	unsigned int dma_chan = 0;
+
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
+
+	/* get base address, irq etc. based on bustype */
+	switch (board->bustype) {
+	case isa_bustype:
+#ifdef CONFIG_ISA_DMA_API
+		iobase = it->options[0];
+		irq = it->options[1];
+		dma_chan = it->options[2];
+#else
+		dev_err(dev->class_dev,
+			"ni_labpc driver has not been built with ISA DMA support.\n");
+		return -EINVAL;
+#endif
+		break;
+	case pci_bustype:
+#ifdef CONFIG_COMEDI_PCI_DRIVERS
+		dev_err(dev->class_dev,
+			"manual configuration of PCI board '%s' is not supported\n",
+			board->name);
+		return -EINVAL;
+#else
+		dev_err(dev->class_dev,
+			"ni_labpc driver has not been built with PCI support.\n");
+		return -EINVAL;
+#endif
+		break;
+	default:
+		dev_err(dev->class_dev,
+			"ni_labpc: bug! couldn't determine board type\n");
+		return -EINVAL;
+		break;
+	}
+
+	return labpc_common_attach(dev, iobase, irq, dma_chan);
+}
+
+static const struct labpc_boardinfo *
+labpc_pci_find_boardinfo(struct pci_dev *pcidev)
+{
+	unsigned int device_id = pcidev->device;
+	unsigned int n;
+
+	for (n = 0; n < ARRAY_SIZE(labpc_boards); n++) {
+		const struct labpc_boardinfo *board = &labpc_boards[n];
+		if (board->bustype == pci_bustype &&
+		    board->device_id == device_id)
+			return board;
+	}
+	return NULL;
+}
+
+static int labpc_auto_attach(struct comedi_device *dev,
+				       unsigned long context_unused)
+{
+	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+	struct labpc_private *devpriv;
+	unsigned long iobase;
+	unsigned int irq;
+	int ret;
+
+	if (!IS_ENABLED(CONFIG_COMEDI_PCI_DRIVERS))
+		return -ENODEV;
+
+	ret = comedi_pci_enable(dev);
+	if (ret)
+		return ret;
+
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
+
+	dev->board_ptr = labpc_pci_find_boardinfo(pcidev);
+	if (!dev->board_ptr)
+		return -ENODEV;
+	devpriv->mite = mite_alloc(pcidev);
+	if (!devpriv->mite)
+		return -ENOMEM;
+	ret = mite_setup(devpriv->mite);
+	if (ret < 0)
+		return ret;
+	iobase = (unsigned long)devpriv->mite->daq_io_addr;
+	irq = mite_irq(devpriv->mite);
+	return labpc_common_attach(dev, iobase, irq, 0);
+}
+
+void labpc_common_detach(struct comedi_device *dev)
+{
+	const struct labpc_boardinfo *board = comedi_board(dev);
+	struct labpc_private *devpriv = dev->private;
+	struct comedi_subdevice *s;
+
+	if (!board)
+		return;
+	if (dev->subdevices) {
+		s = &dev->subdevices[2];
+		subdev_8255_cleanup(dev, s);
+	}
+#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 (board->bustype == isa_bustype && dev->iobase)
+		release_region(dev->iobase, LABPC_SIZE);
+#ifdef CONFIG_COMEDI_PCI_DRIVERS
+	if (devpriv->mite) {
+		mite_unsetup(devpriv->mite);
+		mite_free(devpriv->mite);
+	}
+	if (board->bustype == pci_bustype)
+		comedi_pci_disable(dev);
+#endif
+}
+EXPORT_SYMBOL_GPL(labpc_common_detach);
+
 static struct comedi_driver labpc_driver = {
-	.driver_name = DRV_NAME,
-	.module = THIS_MODULE,
-	.attach = labpc_attach,
-	.auto_attach = labpc_auto_attach,
-	.detach = labpc_common_detach,
-	.num_names = ARRAY_SIZE(labpc_boards),
-	.board_name = &labpc_boards[0].name,
-	.offset = sizeof(struct labpc_board_struct),
+	.driver_name	= "ni_labpc",
+	.module		= THIS_MODULE,
+	.attach		= labpc_attach,
+	.auto_attach	= labpc_auto_attach,
+	.detach		= labpc_common_detach,
+	.num_names	= ARRAY_SIZE(labpc_boards),
+	.board_name	= &labpc_boards[0].name,
+	.offset		= sizeof(struct labpc_boardinfo),
 };
 
 #ifdef CONFIG_COMEDI_PCI_DRIVERS
 static DEFINE_PCI_DEVICE_TABLE(labpc_pci_table) = {
-	{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x161)},
-	{0}
+	{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x161) },
+	{ 0 }
 };
 MODULE_DEVICE_TABLE(pci, labpc_pci_table);
 
 static int labpc_pci_probe(struct pci_dev *dev,
-				     const struct pci_device_id *ent)
+			   const struct pci_device_id *id)
 {
-	return comedi_pci_auto_config(dev, &labpc_driver);
+	return comedi_pci_auto_config(dev, &labpc_driver, id->driver_data);
 }
 
 static struct pci_driver labpc_pci_driver = {
-	.name = DRV_NAME,
-	.id_table = labpc_pci_table,
-	.probe = labpc_pci_probe,
+	.name		= "ni_labpc",
+	.id_table	= labpc_pci_table,
+	.probe		= labpc_pci_probe,
 	.remove		= comedi_pci_auto_unconfig,
 };
 module_comedi_pci_driver(labpc_driver, labpc_pci_driver);
diff --git a/drivers/staging/comedi/drivers/ni_labpc.h b/drivers/staging/comedi/drivers/ni_labpc.h
index e052ed3..0bf2ca1 100644
--- a/drivers/staging/comedi/drivers/ni_labpc.h
+++ b/drivers/staging/comedi/drivers/ni_labpc.h
@@ -33,7 +33,7 @@ enum transfer_type { fifo_not_empty_transfer, fifo_half_full_transfer,
 	isa_dma_transfer
 };
 
-struct labpc_board_struct {
+struct labpc_boardinfo {
 	const char *name;
 	int device_id;		/*  device id for pci and pcmcia boards */
 	int ai_speed;		/*  maximum input speed in nanoseconds */
@@ -44,31 +44,30 @@ struct labpc_board_struct {
 	int has_ao;		/*  has analog output true/false */
 	const struct comedi_lrange *ai_range_table;
 	const int *ai_range_code;
-	const int *ai_range_is_unipolar;
 
 	/*  board can auto scan up in ai channels, not just down */
 	unsigned ai_scan_up:1;
 
 	/* uses memory mapped io instead of ioports */
-	unsigned memory_mapped_io:1;
+	unsigned has_mmio:1;
 };
 
 struct labpc_private {
 	struct mite_struct *mite;	/*  for mite chip on pci-1200 */
 	/*  number of data points left to be taken */
-	volatile unsigned long long count;
+	unsigned long long count;
 	/*  software copy of analog output values */
 	unsigned int ao_value[NUM_AO_CHAN];
 	/*  software copys of bits written to command registers */
-	volatile unsigned int command1_bits;
-	volatile unsigned int command2_bits;
-	volatile unsigned int command3_bits;
-	volatile unsigned int command4_bits;
-	volatile unsigned int command5_bits;
-	volatile unsigned int command6_bits;
+	unsigned int cmd1;
+	unsigned int cmd2;
+	unsigned int cmd3;
+	unsigned int cmd4;
+	unsigned int cmd5;
+	unsigned int cmd6;
 	/*  store last read of board status registers */
-	volatile unsigned int status1_bits;
-	volatile unsigned int status2_bits;
+	unsigned int stat1;
+	unsigned int stat2;
 	/*
 	 * value to load into board's counter a0 (conversion pacing) for timed
 	 * conversions
@@ -105,7 +104,6 @@ int labpc_common_attach(struct comedi_device *dev, unsigned long iobase,
 			unsigned int irq, unsigned int dma);
 void labpc_common_detach(struct comedi_device *dev);
 
-extern const int labpc_1200_is_unipolar[];
 extern const int labpc_1200_ai_gain_bits[];
 extern const struct comedi_lrange range_labpc_1200_ai;
 
diff --git a/drivers/staging/comedi/drivers/ni_labpc_cs.c b/drivers/staging/comedi/drivers/ni_labpc_cs.c
index be7d141..4e1deed 100644
--- a/drivers/staging/comedi/drivers/ni_labpc_cs.c
+++ b/drivers/staging/comedi/drivers/ni_labpc_cs.c
@@ -73,7 +73,7 @@ NI manuals:
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
 
-static const struct labpc_board_struct labpc_cs_boards[] = {
+static const struct labpc_boardinfo labpc_cs_boards[] = {
 	{
 		.name			= "daqcard-1200",
 		.device_id		= 0x103,
@@ -83,7 +83,6 @@ static const struct labpc_board_struct labpc_cs_boards[] = {
 		.has_ao			= 1,
 		.ai_range_table		= &range_labpc_1200_ai,
 		.ai_range_code		= labpc_1200_ai_gain_bits,
-		.ai_range_is_unipolar	= labpc_1200_is_unipolar,
 	},
 };
 
diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c
index b740359..ca52b75 100644
--- a/drivers/staging/comedi/drivers/ni_mio_common.c
+++ b/drivers/staging/comedi/drivers/ni_mio_common.c
@@ -696,9 +696,10 @@ static void ni_release_cdo_mite_channel(struct comedi_device *dev)
 static void ni_e_series_enable_second_irq(struct comedi_device *dev,
 					  unsigned gpct_index, short enable)
 {
+	const struct ni_board_struct *board = comedi_board(dev);
 	struct ni_private *devpriv = dev->private;
 
-	if (boardtype.reg_type & ni_reg_m_series_mask)
+	if (board->reg_type & ni_reg_m_series_mask)
 		return;
 	switch (gpct_index) {
 	case 0:
@@ -728,16 +729,17 @@ static void ni_e_series_enable_second_irq(struct comedi_device *dev,
 
 static void ni_clear_ai_fifo(struct comedi_device *dev)
 {
+	const struct ni_board_struct *board = comedi_board(dev);
 	struct ni_private *devpriv = dev->private;
 
-	if (boardtype.reg_type == ni_reg_6143) {
+	if (board->reg_type == ni_reg_6143) {
 		/*  Flush the 6143 data FIFO */
 		ni_writel(0x10, AIFIFO_Control_6143);	/*  Flush fifo */
 		ni_writel(0x00, AIFIFO_Control_6143);	/*  Flush fifo */
 		while (ni_readl(AIFIFO_Status_6143) & 0x10) ;	/*  Wait for complete */
 	} else {
 		devpriv->stc_writew(dev, 1, ADC_FIFO_Clear);
-		if (boardtype.reg_type == ni_reg_625x) {
+		if (board->reg_type == ni_reg_625x) {
 			ni_writeb(0, M_Offset_Static_AI_Control(0));
 			ni_writeb(1, M_Offset_Static_AI_Control(0));
 #if 0
@@ -845,7 +847,7 @@ static irqreturn_t ni_E_interrupt(int irq, void *d)
 	struct mite_struct *mite = devpriv->mite;
 #endif
 
-	if (dev->attached == 0)
+	if (!dev->attached)
 		return IRQ_NONE;
 	smp_mb();		/*  make sure dev->attached is checked before handler does anything else. */
 
@@ -1292,6 +1294,7 @@ static void ni_mio_print_status_b(int status)
 static void ni_ao_fifo_load(struct comedi_device *dev,
 			    struct comedi_subdevice *s, int n)
 {
+	const struct ni_board_struct *board = comedi_board(dev);
 	struct comedi_async *async = s->async;
 	struct comedi_cmd *cmd = &async->cmd;
 	int chan;
@@ -1309,10 +1312,10 @@ static void ni_ao_fifo_load(struct comedi_device *dev,
 
 		range = CR_RANGE(cmd->chanlist[chan]);
 
-		if (boardtype.reg_type & ni_reg_6xxx_mask) {
+		if (board->reg_type & ni_reg_6xxx_mask) {
 			packed_data = d & 0xffff;
 			/* 6711 only has 16 bit wide ao fifo */
-			if (boardtype.reg_type != ni_reg_6711) {
+			if (board->reg_type != ni_reg_6711) {
 				err &= comedi_buf_get(async, &d);
 				if (err == 0)
 					break;
@@ -1352,6 +1355,7 @@ static void ni_ao_fifo_load(struct comedi_device *dev,
 static int ni_ao_fifo_half_empty(struct comedi_device *dev,
 				 struct comedi_subdevice *s)
 {
+	const struct ni_board_struct *board = comedi_board(dev);
 	int n;
 
 	n = comedi_buf_read_n_available(s->async);
@@ -1361,8 +1365,8 @@ static int ni_ao_fifo_half_empty(struct comedi_device *dev,
 	}
 
 	n /= sizeof(short);
-	if (n > boardtype.ao_fifo_depth / 2)
-		n = boardtype.ao_fifo_depth / 2;
+	if (n > board->ao_fifo_depth / 2)
+		n = board->ao_fifo_depth / 2;
 
 	ni_ao_fifo_load(dev, s, n);
 
@@ -1374,12 +1378,13 @@ static int ni_ao_fifo_half_empty(struct comedi_device *dev,
 static int ni_ao_prep_fifo(struct comedi_device *dev,
 			   struct comedi_subdevice *s)
 {
+	const struct ni_board_struct *board = comedi_board(dev);
 	struct ni_private *devpriv = dev->private;
 	int n;
 
 	/* reset fifo */
 	devpriv->stc_writew(dev, 1, DAC_FIFO_Clear);
-	if (boardtype.reg_type & ni_reg_6xxx_mask)
+	if (board->reg_type & ni_reg_6xxx_mask)
 		ni_ao_win_outl(dev, 0x6, AO_FIFO_Offset_Load_611x);
 
 	/* load some data */
@@ -1388,8 +1393,8 @@ static int ni_ao_prep_fifo(struct comedi_device *dev,
 		return 0;
 
 	n /= sizeof(short);
-	if (n > boardtype.ao_fifo_depth)
-		n = boardtype.ao_fifo_depth;
+	if (n > board->ao_fifo_depth)
+		n = board->ao_fifo_depth;
 
 	ni_ao_fifo_load(dev, s, n);
 
@@ -1399,11 +1404,12 @@ static int ni_ao_prep_fifo(struct comedi_device *dev,
 static void ni_ai_fifo_read(struct comedi_device *dev,
 			    struct comedi_subdevice *s, int n)
 {
+	const struct ni_board_struct *board = comedi_board(dev);
 	struct ni_private *devpriv = dev->private;
 	struct comedi_async *async = s->async;
 	int i;
 
-	if (boardtype.reg_type == ni_reg_611x) {
+	if (board->reg_type == ni_reg_611x) {
 		short data[2];
 		u32 dl;
 
@@ -1420,7 +1426,7 @@ static void ni_ai_fifo_read(struct comedi_device *dev,
 			data[0] = dl & 0xffff;
 			cfc_write_to_buffer(s, data[0]);
 		}
-	} else if (boardtype.reg_type == ni_reg_6143) {
+	} else if (board->reg_type == ni_reg_6143) {
 		short data[2];
 		u32 dl;
 
@@ -1458,10 +1464,11 @@ static void ni_ai_fifo_read(struct comedi_device *dev,
 
 static void ni_handle_fifo_half_full(struct comedi_device *dev)
 {
-	int n;
+	const struct ni_board_struct *board = comedi_board(dev);
 	struct comedi_subdevice *s = &dev->subdevices[NI_AI_SUBDEV];
+	int n;
 
-	n = boardtype.ai_fifo_depth / 2;
+	n = board->ai_fifo_depth / 2;
 
 	ni_ai_fifo_read(dev, s, n);
 }
@@ -1508,6 +1515,7 @@ static int ni_ai_drain_dma(struct comedi_device *dev)
 */
 static void ni_handle_fifo_dregs(struct comedi_device *dev)
 {
+	const struct ni_board_struct *board = comedi_board(dev);
 	struct ni_private *devpriv = dev->private;
 	struct comedi_subdevice *s = &dev->subdevices[NI_AI_SUBDEV];
 	short data[2];
@@ -1515,7 +1523,7 @@ static void ni_handle_fifo_dregs(struct comedi_device *dev)
 	short fifo_empty;
 	int i;
 
-	if (boardtype.reg_type == ni_reg_611x) {
+	if (board->reg_type == ni_reg_611x) {
 		while ((devpriv->stc_readw(dev,
 					   AI_Status_1_Register) &
 			AI_FIFO_Empty_St) == 0) {
@@ -1526,7 +1534,7 @@ static void ni_handle_fifo_dregs(struct comedi_device *dev)
 			data[1] = (dl & 0xffff);
 			cfc_write_array_to_buffer(s, data, sizeof(data));
 		}
-	} else if (boardtype.reg_type == ni_reg_6143) {
+	} else if (board->reg_type == ni_reg_6143) {
 		i = 0;
 		while (ni_readl(AIFIFO_Status_6143) & 0x04) {
 			dl = ni_readl(AIFIFO_Data_6143);
@@ -1573,12 +1581,13 @@ static void ni_handle_fifo_dregs(struct comedi_device *dev)
 
 static void get_last_sample_611x(struct comedi_device *dev)
 {
+	const struct ni_board_struct *board = comedi_board(dev);
 	struct ni_private *devpriv __maybe_unused = dev->private;
 	struct comedi_subdevice *s = &dev->subdevices[NI_AI_SUBDEV];
 	short data;
 	u32 dl;
 
-	if (boardtype.reg_type != ni_reg_611x)
+	if (board->reg_type != ni_reg_611x)
 		return;
 
 	/* Check if there's a single sample stuck in the FIFO */
@@ -1591,12 +1600,13 @@ static void get_last_sample_611x(struct comedi_device *dev)
 
 static void get_last_sample_6143(struct comedi_device *dev)
 {
+	const struct ni_board_struct *board = comedi_board(dev);
 	struct ni_private *devpriv __maybe_unused = dev->private;
 	struct comedi_subdevice *s = &dev->subdevices[NI_AI_SUBDEV];
 	short data;
 	u32 dl;
 
-	if (boardtype.reg_type != ni_reg_6143)
+	if (board->reg_type != ni_reg_6143)
 		return;
 
 	/* Check if there's a single sample stuck in the FIFO */
@@ -1641,6 +1651,7 @@ static void ni_ai_munge(struct comedi_device *dev, struct comedi_subdevice *s,
 
 static int ni_ai_setup_MITE_dma(struct comedi_device *dev)
 {
+	const struct ni_board_struct *board = comedi_board(dev);
 	struct ni_private *devpriv = dev->private;
 	struct comedi_subdevice *s = &dev->subdevices[NI_AI_SUBDEV];
 	int retval;
@@ -1660,7 +1671,7 @@ static int ni_ai_setup_MITE_dma(struct comedi_device *dev)
 		return -EIO;
 	}
 
-	switch (boardtype.reg_type) {
+	switch (board->reg_type) {
 	case ni_reg_611x:
 	case ni_reg_6143:
 		mite_prep_dma(devpriv->ai_mite_chan, 32, 16);
@@ -1681,6 +1692,7 @@ static int ni_ai_setup_MITE_dma(struct comedi_device *dev)
 
 static int ni_ao_setup_MITE_dma(struct comedi_device *dev)
 {
+	const struct ni_board_struct *board = comedi_board(dev);
 	struct ni_private *devpriv = dev->private;
 	struct comedi_subdevice *s = &dev->subdevices[NI_AO_SUBDEV];
 	int retval;
@@ -1695,7 +1707,7 @@ static int ni_ao_setup_MITE_dma(struct comedi_device *dev)
 
 	spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
 	if (devpriv->ao_mite_chan) {
-		if (boardtype.reg_type & (ni_reg_611x | ni_reg_6713)) {
+		if (board->reg_type & (ni_reg_611x | ni_reg_6713)) {
 			mite_prep_dma(devpriv->ao_mite_chan, 32, 32);
 		} else {
 			/* doing 32 instead of 16 bit wide transfers from memory
@@ -1720,6 +1732,7 @@ static int ni_ao_setup_MITE_dma(struct comedi_device *dev)
 
 static int ni_ai_reset(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+	const struct ni_board_struct *board = comedi_board(dev);
 	struct ni_private *devpriv = dev->private;
 
 	ni_release_ai_mite_channel(dev);
@@ -1735,7 +1748,7 @@ static int ni_ai_reset(struct comedi_device *dev, struct comedi_subdevice *s)
 
 	ni_clear_ai_fifo(dev);
 
-	if (boardtype.reg_type != ni_reg_6143)
+	if (board->reg_type != ni_reg_6143)
 		ni_writeb(0, Misc_Command);
 
 	devpriv->stc_writew(dev, AI_Disarm, AI_Command_1_Register);	/* reset pulses */
@@ -1746,7 +1759,7 @@ static int ni_ai_reset(struct comedi_device *dev, struct comedi_subdevice *s)
 	devpriv->stc_writew(dev, 0x0000, AI_Mode_2_Register);
 	/* generate FIFO interrupts on non-empty */
 	devpriv->stc_writew(dev, (0 << 6) | 0x0000, AI_Mode_3_Register);
-	if (boardtype.reg_type == ni_reg_611x) {
+	if (board->reg_type == ni_reg_611x) {
 		devpriv->stc_writew(dev, AI_SHIFTIN_Pulse_Width |
 				    AI_SOC_Polarity |
 				    AI_LOCALMUX_CLK_Pulse_Width,
@@ -1759,7 +1772,7 @@ static int ni_ai_reset(struct comedi_device *dev, struct comedi_subdevice *s)
 				    AI_CONVERT_Output_Select
 				    (AI_CONVERT_Output_Enable_High),
 				    AI_Output_Control_Register);
-	} else if (boardtype.reg_type == ni_reg_6143) {
+	} else if (board->reg_type == ni_reg_6143) {
 		devpriv->stc_writew(dev, AI_SHIFTIN_Pulse_Width |
 				    AI_SOC_Polarity |
 				    AI_LOCALMUX_CLK_Pulse_Width,
@@ -1784,7 +1797,7 @@ static int ni_ai_reset(struct comedi_device *dev, struct comedi_subdevice *s)
 		    AI_EXTMUX_CLK_Output_Select(0) |
 		    AI_LOCALMUX_CLK_Output_Select(2) |
 		    AI_SC_TC_Output_Select(3);
-		if (boardtype.reg_type == ni_reg_622x)
+		if (board->reg_type == ni_reg_622x)
 			ai_output_control_bits |=
 			    AI_CONVERT_Output_Select
 			    (AI_CONVERT_Output_Enable_High);
@@ -1832,9 +1845,10 @@ static int ni_ai_insn_read(struct comedi_device *dev,
 			   struct comedi_subdevice *s, struct comedi_insn *insn,
 			   unsigned int *data)
 {
+	const struct ni_board_struct *board = comedi_board(dev);
 	struct ni_private *devpriv = dev->private;
 	int i, n;
-	const unsigned int mask = (1 << boardtype.adbits) - 1;
+	const unsigned int mask = (1 << board->adbits) - 1;
 	unsigned signbits;
 	unsigned short d;
 	unsigned long dl;
@@ -1844,7 +1858,7 @@ static int ni_ai_insn_read(struct comedi_device *dev,
 	ni_clear_ai_fifo(dev);
 
 	signbits = devpriv->ai_offset[0];
-	if (boardtype.reg_type == ni_reg_611x) {
+	if (board->reg_type == ni_reg_611x) {
 		for (n = 0; n < num_adc_stages_611x; n++) {
 			devpriv->stc_writew(dev, AI_CONVERT_Pulse,
 					    AI_Command_1_Register);
@@ -1877,7 +1891,7 @@ static int ni_ai_insn_read(struct comedi_device *dev,
 			d += signbits;
 			data[n] = d;
 		}
-	} else if (boardtype.reg_type == ni_reg_6143) {
+	} else if (board->reg_type == ni_reg_6143) {
 		for (n = 0; n < insn->n; n++) {
 			devpriv->stc_writew(dev, AI_CONVERT_Pulse,
 					    AI_Command_1_Register);
@@ -1913,7 +1927,7 @@ static int ni_ai_insn_read(struct comedi_device *dev,
 				    ("ni_mio_common: timeout in ni_ai_insn_read\n");
 				return -ETIME;
 			}
-			if (boardtype.reg_type & ni_reg_m_series_mask) {
+			if (board->reg_type & ni_reg_m_series_mask) {
 				data[n] =
 				    ni_readl(M_Offset_AI_FIFO_Data) & mask;
 			} else {
@@ -1948,6 +1962,7 @@ static void ni_m_series_load_channelgain_list(struct comedi_device *dev,
 					      unsigned int n_chan,
 					      unsigned int *list)
 {
+	const struct ni_board_struct *board = comedi_board(dev);
 	struct ni_private *devpriv = dev->private;
 	unsigned int chan, range, aref;
 	unsigned int i;
@@ -1957,12 +1972,12 @@ static void ni_m_series_load_channelgain_list(struct comedi_device *dev,
 
 	devpriv->stc_writew(dev, 1, Configuration_Memory_Clear);
 
-/* offset = 1 << (boardtype.adbits - 1); */
+/* offset = 1 << (board->adbits - 1); */
 	if ((list[0] & CR_ALT_SOURCE)) {
 		unsigned bypass_bits;
 		chan = CR_CHAN(list[0]);
 		range = CR_RANGE(list[0]);
-		range_code = ni_gainlkup[boardtype.gainlkup][range];
+		range_code = ni_gainlkup[board->gainlkup][range];
 		dither = ((list[0] & CR_ALT_FILTER) != 0);
 		bypass_bits = MSeries_AI_Bypass_Config_FIFO_Bit;
 		bypass_bits |= chan;
@@ -1989,7 +2004,7 @@ static void ni_m_series_load_channelgain_list(struct comedi_device *dev,
 		range = CR_RANGE(list[i]);
 		dither = ((list[i] & CR_ALT_FILTER) != 0);
 
-		range_code = ni_gainlkup[boardtype.gainlkup][range];
+		range_code = ni_gainlkup[board->gainlkup][range];
 		devpriv->ai_offset[i] = offset;
 		switch (aref) {
 		case AREF_DIFF:
@@ -2009,7 +2024,7 @@ static void ni_m_series_load_channelgain_list(struct comedi_device *dev,
 		}
 		config_bits |= MSeries_AI_Config_Channel_Bits(chan);
 		config_bits |=
-		    MSeries_AI_Config_Bank_Bits(boardtype.reg_type, chan);
+		    MSeries_AI_Config_Bank_Bits(board->reg_type, chan);
 		config_bits |= MSeries_AI_Config_Gain_Bits(range_code);
 		if (i == n_chan - 1)
 			config_bits |= MSeries_AI_Config_Last_Channel_Bit;
@@ -2054,6 +2069,7 @@ static void ni_m_series_load_channelgain_list(struct comedi_device *dev,
 static void ni_load_channelgain_list(struct comedi_device *dev,
 				     unsigned int n_chan, unsigned int *list)
 {
+	const struct ni_board_struct *board = comedi_board(dev);
 	struct ni_private *devpriv = dev->private;
 	unsigned int chan, range, aref;
 	unsigned int i;
@@ -2061,12 +2077,12 @@ static void ni_load_channelgain_list(struct comedi_device *dev,
 	unsigned offset;
 	unsigned int dither;
 
-	if (boardtype.reg_type & ni_reg_m_series_mask) {
+	if (board->reg_type & ni_reg_m_series_mask) {
 		ni_m_series_load_channelgain_list(dev, n_chan, list);
 		return;
 	}
-	if (n_chan == 1 && (boardtype.reg_type != ni_reg_611x)
-	    && (boardtype.reg_type != ni_reg_6143)) {
+	if (n_chan == 1 && (board->reg_type != ni_reg_611x)
+	    && (board->reg_type != ni_reg_6143)) {
 		if (devpriv->changain_state
 		    && devpriv->changain_spec == list[0]) {
 			/*  ready to go. */
@@ -2081,7 +2097,7 @@ static void ni_load_channelgain_list(struct comedi_device *dev,
 	devpriv->stc_writew(dev, 1, Configuration_Memory_Clear);
 
 	/*  Set up Calibration mode if required */
-	if (boardtype.reg_type == ni_reg_6143) {
+	if (board->reg_type == ni_reg_6143) {
 		if ((list[0] & CR_ALT_SOURCE)
 		    && !devpriv->ai_calib_source_enabled) {
 			/*  Strobe Relay enable bit */
@@ -2105,9 +2121,9 @@ static void ni_load_channelgain_list(struct comedi_device *dev,
 		}
 	}
 
-	offset = 1 << (boardtype.adbits - 1);
+	offset = 1 << (board->adbits - 1);
 	for (i = 0; i < n_chan; i++) {
-		if ((boardtype.reg_type != ni_reg_6143)
+		if ((board->reg_type != ni_reg_6143)
 		    && (list[i] & CR_ALT_SOURCE)) {
 			chan = devpriv->ai_calib_source;
 		} else {
@@ -2118,21 +2134,21 @@ static void ni_load_channelgain_list(struct comedi_device *dev,
 		dither = ((list[i] & CR_ALT_FILTER) != 0);
 
 		/* fix the external/internal range differences */
-		range = ni_gainlkup[boardtype.gainlkup][range];
-		if (boardtype.reg_type == ni_reg_611x)
+		range = ni_gainlkup[board->gainlkup][range];
+		if (board->reg_type == ni_reg_611x)
 			devpriv->ai_offset[i] = offset;
 		else
 			devpriv->ai_offset[i] = (range & 0x100) ? 0 : offset;
 
 		hi = 0;
 		if ((list[i] & CR_ALT_SOURCE)) {
-			if (boardtype.reg_type == ni_reg_611x)
+			if (board->reg_type == ni_reg_611x)
 				ni_writew(CR_CHAN(list[i]) & 0x0003,
 					  Calibration_Channel_Select_611x);
 		} else {
-			if (boardtype.reg_type == ni_reg_611x)
+			if (board->reg_type == ni_reg_611x)
 				aref = AREF_DIFF;
-			else if (boardtype.reg_type == ni_reg_6143)
+			else if (board->reg_type == ni_reg_6143)
 				aref = AREF_OTHER;
 			switch (aref) {
 			case AREF_DIFF:
@@ -2152,7 +2168,7 @@ static void ni_load_channelgain_list(struct comedi_device *dev,
 
 		ni_writew(hi, Configuration_Memory_High);
 
-		if (boardtype.reg_type != ni_reg_6143) {
+		if (board->reg_type != ni_reg_6143) {
 			lo = range;
 			if (i == n_chan - 1)
 				lo |= AI_LAST_CHANNEL;
@@ -2164,8 +2180,8 @@ static void ni_load_channelgain_list(struct comedi_device *dev,
 	}
 
 	/* prime the channel/gain list */
-	if ((boardtype.reg_type != ni_reg_611x)
-	    && (boardtype.reg_type != ni_reg_6143)) {
+	if ((board->reg_type != ni_reg_611x)
+	    && (board->reg_type != ni_reg_6143)) {
 		ni_prime_channelgain_list(dev);
 	}
 }
@@ -2201,22 +2217,25 @@ static unsigned ni_timer_to_ns(const struct comedi_device *dev, int timer)
 static unsigned ni_min_ai_scan_period_ns(struct comedi_device *dev,
 					 unsigned num_channels)
 {
-	switch (boardtype.reg_type) {
+	const struct ni_board_struct *board = comedi_board(dev);
+
+	switch (board->reg_type) {
 	case ni_reg_611x:
 	case ni_reg_6143:
 		/*  simultaneously-sampled inputs */
-		return boardtype.ai_speed;
+		return board->ai_speed;
 		break;
 	default:
 		/*  multiplexed inputs */
 		break;
 	}
-	return boardtype.ai_speed * num_channels;
+	return board->ai_speed * num_channels;
 }
 
 static int ni_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 			 struct comedi_cmd *cmd)
 {
+	const struct ni_board_struct *board = comedi_board(dev);
 	struct ni_private *devpriv = dev->private;
 	int err = 0;
 	int tmp;
@@ -2233,8 +2252,8 @@ static int ni_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 					TRIG_TIMER | TRIG_EXT);
 
 	sources = TRIG_TIMER | TRIG_EXT;
-	if (boardtype.reg_type == ni_reg_611x ||
-	    boardtype.reg_type == ni_reg_6143)
+	if (board->reg_type == ni_reg_611x ||
+	    board->reg_type == ni_reg_6143)
 		sources |= TRIG_NOW;
 	err |= cfc_check_trigger_src(&cmd->convert_src, sources);
 
@@ -2289,12 +2308,12 @@ static int ni_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 	}
 
 	if (cmd->convert_src == TRIG_TIMER) {
-		if ((boardtype.reg_type == ni_reg_611x)
-		    || (boardtype.reg_type == ni_reg_6143)) {
+		if ((board->reg_type == ni_reg_611x)
+		    || (board->reg_type == ni_reg_6143)) {
 			err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
 		} else {
 			err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
-							 boardtype.ai_speed);
+							 board->ai_speed);
 			err |= cfc_check_trigger_arg_max(&cmd->convert_arg,
 						devpriv->clock_ns * 0xffff);
 		}
@@ -2315,7 +2334,7 @@ static int ni_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 	if (cmd->stop_src == TRIG_COUNT) {
 		unsigned int max_count = 0x01000000;
 
-		if (boardtype.reg_type == ni_reg_611x)
+		if (board->reg_type == ni_reg_611x)
 			max_count -= num_adc_stages_611x;
 		err |= cfc_check_trigger_arg_max(&cmd->stop_arg, max_count);
 		err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
@@ -2341,8 +2360,8 @@ static int ni_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 			err++;
 	}
 	if (cmd->convert_src == TRIG_TIMER) {
-		if ((boardtype.reg_type != ni_reg_611x)
-		    && (boardtype.reg_type != ni_reg_6143)) {
+		if ((board->reg_type != ni_reg_611x)
+		    && (board->reg_type != ni_reg_6143)) {
 			tmp = cmd->convert_arg;
 			cmd->convert_arg =
 			    ni_timer_to_ns(dev, ni_ns_to_timer(dev,
@@ -2370,6 +2389,7 @@ static int ni_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 
 static int ni_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+	const struct ni_board_struct *board = comedi_board(dev);
 	struct ni_private *devpriv = dev->private;
 	const struct comedi_cmd *cmd = &s->async->cmd;
 	int timer;
@@ -2426,8 +2446,8 @@ static int ni_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 	mode2 &= ~AI_SC_Reload_Mode;
 	devpriv->stc_writew(dev, mode2, AI_Mode_2_Register);
 
-	if (cmd->chanlist_len == 1 || (boardtype.reg_type == ni_reg_611x)
-	    || (boardtype.reg_type == ni_reg_6143)) {
+	if (cmd->chanlist_len == 1 || (board->reg_type == ni_reg_611x)
+	    || (board->reg_type == ni_reg_6143)) {
 		start_stop_select |= AI_STOP_Polarity;
 		start_stop_select |= AI_STOP_Select(31);	/*  logic low */
 		start_stop_select |= AI_STOP_Sync;
@@ -2442,7 +2462,7 @@ static int ni_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 	case TRIG_COUNT:
 		stop_count = cmd->stop_arg - 1;
 
-		if (boardtype.reg_type == ni_reg_611x) {
+		if (board->reg_type == ni_reg_611x) {
 			/*  have to take 3 stage adc pipeline into account */
 			stop_count += num_adc_stages_611x;
 		}
@@ -2698,6 +2718,7 @@ static int ni_ai_insn_config(struct comedi_device *dev,
 			     struct comedi_subdevice *s,
 			     struct comedi_insn *insn, unsigned int *data)
 {
+	const struct ni_board_struct *board = comedi_board(dev);
 	struct ni_private *devpriv = dev->private;
 
 	if (insn->n < 1)
@@ -2707,7 +2728,7 @@ static int ni_ai_insn_config(struct comedi_device *dev,
 	case INSN_CONFIG_ANALOG_TRIG:
 		return ni_ai_config_analog_trig(dev, s, insn, data);
 	case INSN_CONFIG_ALT_SOURCE:
-		if (boardtype.reg_type & ni_reg_m_series_mask) {
+		if (board->reg_type & ni_reg_m_series_mask) {
 			if (data[1] & ~(MSeries_AI_Bypass_Cal_Sel_Pos_Mask |
 					MSeries_AI_Bypass_Cal_Sel_Neg_Mask |
 					MSeries_AI_Bypass_Mode_Mux_Mask |
@@ -2715,7 +2736,7 @@ static int ni_ai_insn_config(struct comedi_device *dev,
 				return -EINVAL;
 			}
 			devpriv->ai_calib_source = data[1];
-		} else if (boardtype.reg_type == ni_reg_6143) {
+		} else if (board->reg_type == ni_reg_6143) {
 			unsigned int calib_source;
 
 			calib_source = data[1] & 0xf;
@@ -2735,7 +2756,7 @@ static int ni_ai_insn_config(struct comedi_device *dev,
 			if (calib_source >= 8)
 				return -EINVAL;
 			devpriv->ai_calib_source = calib_source;
-			if (boardtype.reg_type == ni_reg_611x) {
+			if (board->reg_type == ni_reg_611x) {
 				ni_writeb(calib_source_adjust,
 					  Cal_Gain_Select_611x);
 			}
@@ -2753,6 +2774,7 @@ static int ni_ai_config_analog_trig(struct comedi_device *dev,
 				    struct comedi_insn *insn,
 				    unsigned int *data)
 {
+	const struct ni_board_struct *board = comedi_board(dev);
 	struct ni_private *devpriv = dev->private;
 	unsigned int a, b, modebits;
 	int err = 0;
@@ -2761,14 +2783,14 @@ static int ni_ai_config_analog_trig(struct comedi_device *dev,
 	 * data[2] is analog line
 	 * data[3] is set level
 	 * data[4] is reset level */
-	if (!boardtype.has_analog_trig)
+	if (!board->has_analog_trig)
 		return -EINVAL;
 	if ((data[1] & 0xffff0000) != COMEDI_EV_SCAN_BEGIN) {
 		data[1] &= (COMEDI_EV_SCAN_BEGIN | 0xffff);
 		err++;
 	}
-	if (data[2] >= boardtype.n_adchan) {
-		data[2] = boardtype.n_adchan - 1;
+	if (data[2] >= board->n_adchan) {
+		data[2] = board->n_adchan - 1;
 		err++;
 	}
 	if (data[3] > 255) {	/* a */
@@ -2852,6 +2874,7 @@ static void ni_ao_munge(struct comedi_device *dev, struct comedi_subdevice *s,
 			void *data, unsigned int num_bytes,
 			unsigned int chan_index)
 {
+	const struct ni_board_struct *board = comedi_board(dev);
 	struct comedi_async *async = s->async;
 	unsigned int range;
 	unsigned int i;
@@ -2859,10 +2882,10 @@ static void ni_ao_munge(struct comedi_device *dev, struct comedi_subdevice *s,
 	unsigned int length = num_bytes / sizeof(short);
 	short *array = data;
 
-	offset = 1 << (boardtype.aobits - 1);
+	offset = 1 << (board->aobits - 1);
 	for (i = 0; i < length; i++) {
 		range = CR_RANGE(async->cmd.chanlist[chan_index]);
-		if (boardtype.ao_unipolar == 0 || (range & 1) == 0)
+		if (board->ao_unipolar == 0 || (range & 1) == 0)
 			array[i] -= offset;
 #ifdef PCIDMA
 		array[i] = cpu_to_le16(array[i]);
@@ -2877,6 +2900,7 @@ static int ni_m_series_ao_config_chanlist(struct comedi_device *dev,
 					  unsigned int chanspec[],
 					  unsigned int n_chans, int timed)
 {
+	const struct ni_board_struct *board = comedi_board(dev);
 	struct ni_private *devpriv = dev->private;
 	unsigned int range;
 	unsigned int chan;
@@ -2885,7 +2909,7 @@ static int ni_m_series_ao_config_chanlist(struct comedi_device *dev,
 	int invert = 0;
 
 	if (timed) {
-		for (i = 0; i < boardtype.n_aochan; ++i) {
+		for (i = 0; i < board->n_aochan; ++i) {
 			devpriv->ao_conf[i] &= ~MSeries_AO_Update_Timed_Bit;
 			ni_writeb(devpriv->ao_conf[i],
 				  M_Offset_AO_Config_Bank(i));
@@ -2949,6 +2973,7 @@ static int ni_old_ao_config_chanlist(struct comedi_device *dev,
 				     unsigned int chanspec[],
 				     unsigned int n_chans)
 {
+	const struct ni_board_struct *board = comedi_board(dev);
 	struct ni_private *devpriv = dev->private;
 	unsigned int range;
 	unsigned int chan;
@@ -2961,10 +2986,10 @@ static int ni_old_ao_config_chanlist(struct comedi_device *dev,
 		range = CR_RANGE(chanspec[i]);
 		conf = AO_Channel(chan);
 
-		if (boardtype.ao_unipolar) {
+		if (board->ao_unipolar) {
 			if ((range & 1) == 0) {
 				conf |= AO_Bipolar;
-				invert = (1 << (boardtype.aobits - 1));
+				invert = (1 << (board->aobits - 1));
 			} else {
 				invert = 0;
 			}
@@ -2972,7 +2997,7 @@ static int ni_old_ao_config_chanlist(struct comedi_device *dev,
 				conf |= AO_Ext_Ref;
 		} else {
 			conf |= AO_Bipolar;
-			invert = (1 << (boardtype.aobits - 1));
+			invert = (1 << (board->aobits - 1));
 		}
 
 		/* not all boards can deglitch, but this shouldn't hurt */
@@ -2995,7 +3020,9 @@ static int ni_ao_config_chanlist(struct comedi_device *dev,
 				 unsigned int chanspec[], unsigned int n_chans,
 				 int timed)
 {
-	if (boardtype.reg_type & ni_reg_m_series_mask)
+	const struct ni_board_struct *board = comedi_board(dev);
+
+	if (board->reg_type & ni_reg_m_series_mask)
 		return ni_m_series_ao_config_chanlist(dev, s, chanspec, n_chans,
 						      timed);
 	else
@@ -3017,6 +3044,7 @@ static int ni_ao_insn_write(struct comedi_device *dev,
 			    struct comedi_subdevice *s,
 			    struct comedi_insn *insn, unsigned int *data)
 {
+	const struct ni_board_struct *board = comedi_board(dev);
 	struct ni_private *devpriv = dev->private;
 	unsigned int chan = CR_CHAN(insn->chanspec);
 	unsigned int invert;
@@ -3025,7 +3053,7 @@ static int ni_ao_insn_write(struct comedi_device *dev,
 
 	devpriv->ao[chan] = data[0];
 
-	if (boardtype.reg_type & ni_reg_m_series_mask) {
+	if (board->reg_type & ni_reg_m_series_mask) {
 		ni_writew(data[0], M_Offset_DAC_Direct_Data(chan));
 	} else
 		ni_writew(data[0] ^ invert,
@@ -3038,12 +3066,13 @@ static int ni_ao_insn_write_671x(struct comedi_device *dev,
 				 struct comedi_subdevice *s,
 				 struct comedi_insn *insn, unsigned int *data)
 {
+	const struct ni_board_struct *board = comedi_board(dev);
 	struct ni_private *devpriv = dev->private;
 	unsigned int chan = CR_CHAN(insn->chanspec);
 	unsigned int invert;
 
 	ao_win_out(1 << chan, AO_Immediate_671x);
-	invert = 1 << (boardtype.aobits - 1);
+	invert = 1 << (board->aobits - 1);
 
 	ni_ao_config_chanlist(dev, s, &insn->chanspec, 1, 0);
 
@@ -3057,13 +3086,14 @@ static int ni_ao_insn_config(struct comedi_device *dev,
 			     struct comedi_subdevice *s,
 			     struct comedi_insn *insn, unsigned int *data)
 {
+	const struct ni_board_struct *board = comedi_board(dev);
 	struct ni_private *devpriv = dev->private;
 
 	switch (data[0]) {
 	case INSN_CONFIG_GET_HARDWARE_BUFFER_SIZE:
 		switch (data[1]) {
 		case COMEDI_OUTPUT:
-			data[2] = 1 + boardtype.ao_fifo_depth * sizeof(short);
+			data[2] = 1 + board->ao_fifo_depth * sizeof(short);
 			if (devpriv->mite)
 				data[2] += devpriv->mite->fifo_size;
 			break;
@@ -3085,6 +3115,7 @@ static int ni_ao_insn_config(struct comedi_device *dev,
 static int ni_ao_inttrig(struct comedi_device *dev, struct comedi_subdevice *s,
 			 unsigned int trignum)
 {
+	const struct ni_board_struct *board __maybe_unused = comedi_board(dev);
 	struct ni_private *devpriv = dev->private;
 	int ret;
 	int interrupt_b_bits;
@@ -3104,7 +3135,7 @@ static int ni_ao_inttrig(struct comedi_device *dev, struct comedi_subdevice *s,
 	interrupt_b_bits = AO_Error_Interrupt_Enable;
 #ifdef PCIDMA
 	devpriv->stc_writew(dev, 1, DAC_FIFO_Clear);
-	if (boardtype.reg_type & ni_reg_6xxx_mask)
+	if (board->reg_type & ni_reg_6xxx_mask)
 		ni_ao_win_outl(dev, 0x6, AO_FIFO_Offset_Load_611x);
 	ret = ni_ao_setup_MITE_dma(dev);
 	if (ret)
@@ -3155,6 +3186,7 @@ static int ni_ao_inttrig(struct comedi_device *dev, struct comedi_subdevice *s,
 
 static int ni_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+	const struct ni_board_struct *board = comedi_board(dev);
 	struct ni_private *devpriv = dev->private;
 	const struct comedi_cmd *cmd = &s->async->cmd;
 	int bits;
@@ -3170,7 +3202,7 @@ static int ni_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 
 	devpriv->stc_writew(dev, AO_Disarm, AO_Command_1_Register);
 
-	if (boardtype.reg_type & ni_reg_6xxx_mask) {
+	if (board->reg_type & ni_reg_6xxx_mask) {
 		ao_win_out(CLEAR_WG, AO_Misc_611x);
 
 		bits = 0;
@@ -3233,7 +3265,7 @@ static int ni_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 	devpriv->stc_writew(dev, devpriv->ao_mode2, AO_Mode_2_Register);
 	switch (cmd->stop_src) {
 	case TRIG_COUNT:
-		if (boardtype.reg_type & ni_reg_m_series_mask) {
+		if (board->reg_type & ni_reg_m_series_mask) {
 			/*  this is how the NI example code does it for m-series boards, verified correct with 6259 */
 			devpriv->stc_writel(dev, cmd->stop_arg - 1,
 					    AO_UC_Load_A_Register);
@@ -3301,8 +3333,8 @@ static int ni_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 		unsigned bits;
 		devpriv->ao_mode1 &= ~AO_Multiple_Channels;
 		bits = AO_UPDATE_Output_Select(AO_Update_Output_High_Z);
-		if (boardtype.
-		    reg_type & (ni_reg_m_series_mask | ni_reg_6xxx_mask)) {
+		if (board->reg_type &
+		    (ni_reg_m_series_mask | ni_reg_6xxx_mask)) {
 			bits |= AO_Number_Of_Channels(0);
 		} else {
 			bits |=
@@ -3329,14 +3361,14 @@ static int ni_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 
 	bits = AO_BC_Source_Select | AO_UPDATE_Pulse_Width |
 	    AO_TMRDACWR_Pulse_Width;
-	if (boardtype.ao_fifo_depth)
+	if (board->ao_fifo_depth)
 		bits |= AO_FIFO_Enable;
 	else
 		bits |= AO_DMA_PIO_Control;
 #if 0
 	/* F Hess: windows driver does not set AO_Number_Of_DAC_Packages bit for 6281,
 	   verified with bus analyzer. */
-	if (boardtype.reg_type & ni_reg_m_series_mask)
+	if (board->reg_type & ni_reg_m_series_mask)
 		bits |= AO_Number_Of_DAC_Packages;
 #endif
 	devpriv->stc_writew(dev, bits, AO_Personal_Register);
@@ -3360,6 +3392,7 @@ static int ni_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 static int ni_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 			 struct comedi_cmd *cmd)
 {
+	const struct ni_board_struct *board = comedi_board(dev);
 	struct ni_private *devpriv = dev->private;
 	int err = 0;
 	int tmp;
@@ -3407,7 +3440,7 @@ static int ni_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 
 	if (cmd->scan_begin_src == TRIG_TIMER) {
 		err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
-						 boardtype.ao_speed);
+						 board->ao_speed);
 		err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg,
 						 devpriv->clock_ns * 0xffffff);
 	}
@@ -3448,6 +3481,7 @@ static int ni_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 
 static int ni_ao_reset(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+	const struct ni_board_struct *board = comedi_board(dev);
 	struct ni_private *devpriv = dev->private;
 
 	/* devpriv->ao0p=0x0000; */
@@ -3475,7 +3509,7 @@ static int ni_ao_reset(struct comedi_device *dev, struct comedi_subdevice *s)
 	devpriv->stc_writew(dev, devpriv->ao_mode1, AO_Mode_1_Register);
 	devpriv->ao_mode2 = 0;
 	devpriv->stc_writew(dev, devpriv->ao_mode2, AO_Mode_2_Register);
-	if (boardtype.reg_type & ni_reg_m_series_mask)
+	if (board->reg_type & ni_reg_m_series_mask)
 		devpriv->ao_mode3 = AO_Last_Gate_Disable;
 	else
 		devpriv->ao_mode3 = 0;
@@ -3483,7 +3517,7 @@ static int ni_ao_reset(struct comedi_device *dev, struct comedi_subdevice *s)
 	devpriv->ao_trigger_select = 0;
 	devpriv->stc_writew(dev, devpriv->ao_trigger_select,
 			    AO_Trigger_Select_Register);
-	if (boardtype.reg_type & ni_reg_6xxx_mask) {
+	if (board->reg_type & ni_reg_6xxx_mask) {
 		unsigned immediate_bits = 0;
 		unsigned i;
 		for (i = 0; i < s->n_chan; ++i) {
@@ -3784,6 +3818,7 @@ static int ni_cdio_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
 
 static void handle_cdio_interrupt(struct comedi_device *dev)
 {
+	const struct ni_board_struct *board = comedi_board(dev);
 	struct ni_private *devpriv __maybe_unused = dev->private;
 	unsigned cdio_status;
 	struct comedi_subdevice *s = &dev->subdevices[NI_DIO_SUBDEV];
@@ -3791,7 +3826,7 @@ static void handle_cdio_interrupt(struct comedi_device *dev)
 	unsigned long flags;
 #endif
 
-	if ((boardtype.reg_type & ni_reg_m_series_mask) == 0) {
+	if ((board->reg_type & ni_reg_m_series_mask) == 0) {
 		return;
 	}
 #ifdef PCIDMA
@@ -4038,6 +4073,7 @@ static int ni_serial_sw_readwrite8(struct comedi_device *dev,
 
 static void mio_common_detach(struct comedi_device *dev)
 {
+	const struct ni_board_struct *board = comedi_board(dev);
 	struct ni_private *devpriv = dev->private;
 	struct comedi_subdevice *s;
 
@@ -4046,7 +4082,7 @@ static void mio_common_detach(struct comedi_device *dev)
 			ni_gpct_device_destroy(devpriv->counter_dev);
 		}
 	}
-	if (dev->subdevices && boardtype.has_8255) {
+	if (dev->subdevices && board->has_8255) {
 		s = &dev->subdevices[NI_8255_DIO_SUBDEV];
 		subdev_8255_cleanup(dev, s);
 	}
@@ -4355,14 +4391,15 @@ static int ni_alloc_private(struct comedi_device *dev)
 
 static int ni_E_init(struct comedi_device *dev)
 {
+	const struct ni_board_struct *board = comedi_board(dev);
 	struct ni_private *devpriv = dev->private;
 	struct comedi_subdevice *s;
 	unsigned j;
 	enum ni_gpct_variant counter_variant;
 	int ret;
 
-	if (boardtype.n_aochan > MAX_N_AO_CHAN) {
-		printk("bug! boardtype.n_aochan > MAX_N_AO_CHAN\n");
+	if (board->n_aochan > MAX_N_AO_CHAN) {
+		printk("bug! n_aochan > MAX_N_AO_CHAN\n");
 		return -EINVAL;
 	}
 
@@ -4374,20 +4411,20 @@ static int ni_E_init(struct comedi_device *dev)
 
 	s = &dev->subdevices[NI_AI_SUBDEV];
 	dev->read_subdev = s;
-	if (boardtype.n_adchan) {
+	if (board->n_adchan) {
 		s->type = COMEDI_SUBD_AI;
 		s->subdev_flags =
 		    SDF_READABLE | SDF_DIFF | SDF_DITHER | SDF_CMD_READ;
-		if (boardtype.reg_type != ni_reg_611x)
+		if (board->reg_type != ni_reg_611x)
 			s->subdev_flags |= SDF_GROUND | SDF_COMMON | SDF_OTHER;
-		if (boardtype.adbits > 16)
+		if (board->adbits > 16)
 			s->subdev_flags |= SDF_LSAMPL;
-		if (boardtype.reg_type & ni_reg_m_series_mask)
+		if (board->reg_type & ni_reg_m_series_mask)
 			s->subdev_flags |= SDF_SOFT_CALIBRATED;
-		s->n_chan = boardtype.n_adchan;
+		s->n_chan = board->n_adchan;
 		s->len_chanlist = 512;
-		s->maxdata = (1 << boardtype.adbits) - 1;
-		s->range_table = ni_range_lkup[boardtype.gainlkup];
+		s->maxdata = (1 << board->adbits) - 1;
+		s->range_table = ni_range_lkup[board->gainlkup];
 		s->insn_read = &ni_ai_insn_read;
 		s->insn_config = &ni_ai_insn_config;
 		s->do_cmdtest = &ni_ai_cmdtest;
@@ -4405,40 +4442,40 @@ static int ni_E_init(struct comedi_device *dev)
 	/* analog output subdevice */
 
 	s = &dev->subdevices[NI_AO_SUBDEV];
-	if (boardtype.n_aochan) {
+	if (board->n_aochan) {
 		s->type = COMEDI_SUBD_AO;
 		s->subdev_flags = SDF_WRITABLE | SDF_DEGLITCH | SDF_GROUND;
-		if (boardtype.reg_type & ni_reg_m_series_mask)
+		if (board->reg_type & ni_reg_m_series_mask)
 			s->subdev_flags |= SDF_SOFT_CALIBRATED;
-		s->n_chan = boardtype.n_aochan;
-		s->maxdata = (1 << boardtype.aobits) - 1;
-		s->range_table = boardtype.ao_range_table;
+		s->n_chan = board->n_aochan;
+		s->maxdata = (1 << board->aobits) - 1;
+		s->range_table = board->ao_range_table;
 		s->insn_read = &ni_ao_insn_read;
-		if (boardtype.reg_type & ni_reg_6xxx_mask) {
+		if (board->reg_type & ni_reg_6xxx_mask) {
 			s->insn_write = &ni_ao_insn_write_671x;
 		} else {
 			s->insn_write = &ni_ao_insn_write;
 		}
 		s->insn_config = &ni_ao_insn_config;
 #ifdef PCIDMA
-		if (boardtype.n_aochan) {
+		if (board->n_aochan) {
 			s->async_dma_dir = DMA_TO_DEVICE;
 #else
-		if (boardtype.ao_fifo_depth) {
+		if (board->ao_fifo_depth) {
 #endif
 			dev->write_subdev = s;
 			s->subdev_flags |= SDF_CMD_WRITE;
 			s->do_cmd = &ni_ao_cmd;
 			s->do_cmdtest = &ni_ao_cmdtest;
-			s->len_chanlist = boardtype.n_aochan;
-			if ((boardtype.reg_type & ni_reg_m_series_mask) == 0)
+			s->len_chanlist = board->n_aochan;
+			if ((board->reg_type & ni_reg_m_series_mask) == 0)
 				s->munge = ni_ao_munge;
 		}
 		s->cancel = &ni_ao_reset;
 	} else {
 		s->type = COMEDI_SUBD_UNUSED;
 	}
-	if ((boardtype.reg_type & ni_reg_67xx_mask))
+	if ((board->reg_type & ni_reg_67xx_mask))
 		init_ao_67xx(dev, s);
 
 	/* digital i/o subdevice */
@@ -4449,8 +4486,8 @@ static int ni_E_init(struct comedi_device *dev)
 	s->maxdata = 1;
 	s->io_bits = 0;		/* all bits input */
 	s->range_table = &range_digital;
-	s->n_chan = boardtype.num_p0_dio_channels;
-	if (boardtype.reg_type & ni_reg_m_series_mask) {
+	s->n_chan = board->num_p0_dio_channels;
+	if (board->reg_type & ni_reg_m_series_mask) {
 		s->subdev_flags |=
 		    SDF_LSAMPL | SDF_CMD_WRITE /* | SDF_CMD_READ */ ;
 		s->insn_bits = &ni_m_series_dio_insn_bits;
@@ -4472,7 +4509,7 @@ static int ni_E_init(struct comedi_device *dev)
 
 	/* 8255 device */
 	s = &dev->subdevices[NI_8255_DIO_SUBDEV];
-	if (boardtype.has_8255) {
+	if (board->has_8255) {
 		subdev_8255_init(dev, s, ni_8255_callback, (unsigned long)dev);
 	} else {
 		s->type = COMEDI_SUBD_UNUSED;
@@ -4485,14 +4522,14 @@ static int ni_E_init(struct comedi_device *dev)
 	/* calibration subdevice -- ai and ao */
 	s = &dev->subdevices[NI_CALIBRATION_SUBDEV];
 	s->type = COMEDI_SUBD_CALIB;
-	if (boardtype.reg_type & ni_reg_m_series_mask) {
+	if (board->reg_type & ni_reg_m_series_mask) {
 		/*  internal PWM analog output used for AI nonlinearity calibration */
 		s->subdev_flags = SDF_INTERNAL;
 		s->insn_config = &ni_m_series_pwm_config;
 		s->n_chan = 1;
 		s->maxdata = 0;
 		ni_writel(0x0, M_Offset_Cal_PWM);
-	} else if (boardtype.reg_type == ni_reg_6143) {
+	} else if (board->reg_type == ni_reg_6143) {
 		/*  internal PWM analog output used for AI nonlinearity calibration */
 		s->subdev_flags = SDF_INTERNAL;
 		s->insn_config = &ni_6143_pwm_config;
@@ -4510,7 +4547,7 @@ static int ni_E_init(struct comedi_device *dev)
 	s->type = COMEDI_SUBD_MEMORY;
 	s->subdev_flags = SDF_READABLE | SDF_INTERNAL;
 	s->maxdata = 0xff;
-	if (boardtype.reg_type & ni_reg_m_series_mask) {
+	if (board->reg_type & ni_reg_m_series_mask) {
 		s->n_chan = M_SERIES_EEPROM_SIZE;
 		s->insn_read = &ni_m_series_eeprom_insn_read;
 	} else {
@@ -4522,7 +4559,7 @@ static int ni_E_init(struct comedi_device *dev)
 	s = &dev->subdevices[NI_PFI_DIO_SUBDEV];
 	s->type = COMEDI_SUBD_DIO;
 	s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
-	if (boardtype.reg_type & ni_reg_m_series_mask) {
+	if (board->reg_type & ni_reg_m_series_mask) {
 		unsigned i;
 		s->n_chan = 16;
 		ni_writew(s->state, M_Offset_PFI_DO);
@@ -4534,7 +4571,7 @@ static int ni_E_init(struct comedi_device *dev)
 		s->n_chan = 10;
 	}
 	s->maxdata = 1;
-	if (boardtype.reg_type & ni_reg_m_series_mask) {
+	if (board->reg_type & ni_reg_m_series_mask) {
 		s->insn_bits = &ni_pfi_insn_bits;
 	}
 	s->insn_config = &ni_pfi_insn_config;
@@ -4542,11 +4579,11 @@ static int ni_E_init(struct comedi_device *dev)
 
 	/* cs5529 calibration adc */
 	s = &dev->subdevices[NI_CS5529_CALIBRATION_SUBDEV];
-	if (boardtype.reg_type & ni_reg_67xx_mask) {
+	if (board->reg_type & ni_reg_67xx_mask) {
 		s->type = COMEDI_SUBD_AI;
 		s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_INTERNAL;
 		/*  one channel for each analog output channel */
-		s->n_chan = boardtype.n_aochan;
+		s->n_chan = board->n_aochan;
 		s->maxdata = (1 << 16) - 1;
 		s->range_table = &range_unknown;	/* XXX */
 		s->insn_read = cs5529_ai_insn_read;
@@ -4576,7 +4613,7 @@ static int ni_E_init(struct comedi_device *dev)
 	s->insn_config = ni_rtsi_insn_config;
 	ni_rtsi_init(dev);
 
-	if (boardtype.reg_type & ni_reg_m_series_mask) {
+	if (board->reg_type & ni_reg_m_series_mask) {
 		counter_variant = ni_gpct_variant_m_series;
 	} else {
 		counter_variant = ni_gpct_variant_e_series;
@@ -4594,7 +4631,7 @@ static int ni_E_init(struct comedi_device *dev)
 		    SDF_READABLE | SDF_WRITABLE | SDF_LSAMPL | SDF_CMD_READ
 		    /* | SDF_CMD_WRITE */ ;
 		s->n_chan = 3;
-		if (boardtype.reg_type & ni_reg_m_series_mask)
+		if (board->reg_type & ni_reg_m_series_mask)
 			s->maxdata = 0xffffffff;
 		else
 			s->maxdata = 0xffffff;
@@ -4626,7 +4663,7 @@ static int ni_E_init(struct comedi_device *dev)
 	/* ai configuration */
 	s = &dev->subdevices[NI_AI_SUBDEV];
 	ni_ai_reset(dev, s);
-	if ((boardtype.reg_type & ni_reg_6xxx_mask) == 0) {
+	if ((board->reg_type & ni_reg_6xxx_mask) == 0) {
 		/*  BEAM is this needed for PCI-6143 ?? */
 		devpriv->clock_and_fout =
 		    Slow_Internal_Time_Divide_By_2 |
@@ -4663,11 +4700,11 @@ static int ni_E_init(struct comedi_device *dev)
 	ni_writeb(devpriv->ai_ao_select_reg, AI_AO_Select);
 	ni_writeb(devpriv->g0_g1_select_reg, G0_G1_Select);
 
-	if (boardtype.reg_type & ni_reg_6xxx_mask) {
+	if (board->reg_type & ni_reg_6xxx_mask) {
 		ni_writeb(0, Magic_611x);
-	} else if (boardtype.reg_type & ni_reg_m_series_mask) {
+	} else if (board->reg_type & ni_reg_m_series_mask) {
 		int channel;
-		for (channel = 0; channel < boardtype.n_aochan; ++channel) {
+		for (channel = 0; channel < board->n_aochan; ++channel) {
 			ni_writeb(0xf, M_Offset_AO_Waveform_Order(channel));
 			ni_writeb(0x0,
 				  M_Offset_AO_Reference_Attenuation(channel));
@@ -4938,6 +4975,7 @@ static struct caldac_struct caldacs[] = {
 
 static void caldac_setup(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+	const struct ni_board_struct *board = comedi_board(dev);
 	struct ni_private *devpriv = dev->private;
 	int i, j;
 	int n_dacs;
@@ -4947,12 +4985,12 @@ static void caldac_setup(struct comedi_device *dev, struct comedi_subdevice *s)
 	int type;
 	int chan;
 
-	type = boardtype.caldac[0];
+	type = board->caldac[0];
 	if (type == caldac_none)
 		return;
 	n_bits = caldacs[type].n_bits;
 	for (i = 0; i < 3; i++) {
-		type = boardtype.caldac[i];
+		type = board->caldac[i];
 		if (type == caldac_none)
 			break;
 		if (caldacs[type].n_bits != n_bits)
@@ -4971,7 +5009,7 @@ static void caldac_setup(struct comedi_device *dev, struct comedi_subdevice *s)
 		s->maxdata_list = maxdata_list = devpriv->caldac_maxdata_list;
 		chan = 0;
 		for (i = 0; i < n_dacs; i++) {
-			type = boardtype.caldac[i];
+			type = board->caldac[i];
 			for (j = 0; j < caldacs[type].n_chans; j++) {
 				maxdata_list[chan] =
 				    (1 << caldacs[type].n_bits) - 1;
@@ -4982,7 +5020,7 @@ static void caldac_setup(struct comedi_device *dev, struct comedi_subdevice *s)
 		for (chan = 0; chan < s->n_chan; chan++)
 			ni_write_caldac(dev, i, s->maxdata_list[i] / 2);
 	} else {
-		type = boardtype.caldac[0];
+		type = board->caldac[0];
 		s->maxdata = (1 << caldacs[type].n_bits) - 1;
 
 		for (chan = 0; chan < s->n_chan; chan++)
@@ -4992,6 +5030,7 @@ static void caldac_setup(struct comedi_device *dev, struct comedi_subdevice *s)
 
 static void ni_write_caldac(struct comedi_device *dev, int addr, int val)
 {
+	const struct ni_board_struct *board = comedi_board(dev);
 	struct ni_private *devpriv = dev->private;
 	unsigned int loadbit = 0, bits = 0, bit, bitstring = 0;
 	int i;
@@ -5003,7 +5042,7 @@ static void ni_write_caldac(struct comedi_device *dev, int addr, int val)
 	devpriv->caldacs[addr] = val;
 
 	for (i = 0; i < 3; i++) {
-		type = boardtype.caldac[i];
+		type = board->caldac[i];
 		if (type == caldac_none)
 			break;
 		if (addr < caldacs[type].n_chans) {
@@ -5275,7 +5314,9 @@ static int ni_old_set_pfi_routing(struct comedi_device *dev, unsigned chan,
 static int ni_set_pfi_routing(struct comedi_device *dev, unsigned chan,
 			      unsigned source)
 {
-	if (boardtype.reg_type & ni_reg_m_series_mask)
+	const struct ni_board_struct *board = comedi_board(dev);
+
+	if (board->reg_type & ni_reg_m_series_mask)
 		return ni_m_series_set_pfi_routing(dev, chan, source);
 	else
 		return ni_old_set_pfi_routing(dev, chan, source);
@@ -5336,7 +5377,9 @@ static unsigned ni_old_get_pfi_routing(struct comedi_device *dev, unsigned chan)
 
 static unsigned ni_get_pfi_routing(struct comedi_device *dev, unsigned chan)
 {
-	if (boardtype.reg_type & ni_reg_m_series_mask)
+	const struct ni_board_struct *board = comedi_board(dev);
+
+	if (board->reg_type & ni_reg_m_series_mask)
 		return ni_m_series_get_pfi_routing(dev, chan);
 	else
 		return ni_old_get_pfi_routing(dev, chan);
@@ -5345,10 +5388,11 @@ static unsigned ni_get_pfi_routing(struct comedi_device *dev, unsigned chan)
 static int ni_config_filter(struct comedi_device *dev, unsigned pfi_channel,
 			    enum ni_pfi_filter_select filter)
 {
+	const struct ni_board_struct *board = comedi_board(dev);
 	struct ni_private *devpriv __maybe_unused = dev->private;
 	unsigned bits;
 
-	if ((boardtype.reg_type & ni_reg_m_series_mask) == 0) {
+	if ((board->reg_type & ni_reg_m_series_mask) == 0) {
 		return -ENOTSUPP;
 	}
 	bits = ni_readl(M_Offset_PFI_Filter);
@@ -5362,9 +5406,10 @@ static int ni_pfi_insn_bits(struct comedi_device *dev,
 			    struct comedi_subdevice *s,
 			    struct comedi_insn *insn, unsigned int *data)
 {
+	const struct ni_board_struct *board = comedi_board(dev);
 	struct ni_private *devpriv __maybe_unused = dev->private;
 
-	if ((boardtype.reg_type & ni_reg_m_series_mask) == 0) {
+	if ((board->reg_type & ni_reg_m_series_mask) == 0) {
 		return -ENOTSUPP;
 	}
 	if (data[0]) {
@@ -5423,6 +5468,7 @@ static int ni_pfi_insn_config(struct comedi_device *dev,
  */
 static void ni_rtsi_init(struct comedi_device *dev)
 {
+	const struct ni_board_struct *board = comedi_board(dev);
 	struct ni_private *devpriv = dev->private;
 
 	/*  Initialises the RTSI bus signal switch to a default state */
@@ -5449,7 +5495,7 @@ static void ni_rtsi_init(struct comedi_device *dev)
 	    RTSI_Trig_Output_Bits(5,
 				  NI_RTSI_OUTPUT_G_SRC0) |
 	    RTSI_Trig_Output_Bits(6, NI_RTSI_OUTPUT_G_GATE0);
-	if (boardtype.reg_type & ni_reg_m_series_mask)
+	if (board->reg_type & ni_reg_m_series_mask)
 		devpriv->rtsi_trig_b_output_reg |=
 		    RTSI_Trig_Output_Bits(7, NI_RTSI_OUTPUT_RTSI_OSC);
 	devpriv->stc_writew(dev, devpriv->rtsi_trig_b_output_reg,
@@ -5517,7 +5563,9 @@ static int ni_mseries_get_pll_parameters(unsigned reference_period_ns,
 
 static inline unsigned num_configurable_rtsi_channels(struct comedi_device *dev)
 {
-	if (boardtype.reg_type & ni_reg_m_series_mask)
+	const struct ni_board_struct *board = comedi_board(dev);
+
+	if (board->reg_type & ni_reg_m_series_mask)
 		return 8;
 	else
 		return 7;
@@ -5629,6 +5677,7 @@ static int ni_mseries_set_pll_master_clock(struct comedi_device *dev,
 static int ni_set_master_clock(struct comedi_device *dev, unsigned source,
 			       unsigned period_ns)
 {
+	const struct ni_board_struct *board = comedi_board(dev);
 	struct ni_private *devpriv = dev->private;
 
 	if (source == NI_MIO_INTERNAL_CLOCK) {
@@ -5636,7 +5685,7 @@ static int ni_set_master_clock(struct comedi_device *dev, unsigned source,
 		devpriv->stc_writew(dev, devpriv->rtsi_trig_direction_reg,
 				    RTSI_Trig_Direction_Register);
 		devpriv->clock_ns = TIMEBASE_1_NS;
-		if (boardtype.reg_type & ni_reg_m_series_mask) {
+		if (board->reg_type & ni_reg_m_series_mask) {
 			devpriv->clock_and_fout2 &=
 			    ~(MSeries_Timebase1_Select_Bit |
 			      MSeries_Timebase3_Select_Bit);
@@ -5646,7 +5695,7 @@ static int ni_set_master_clock(struct comedi_device *dev, unsigned source,
 		}
 		devpriv->clock_source = source;
 	} else {
-		if (boardtype.reg_type & ni_reg_m_series_mask) {
+		if (board->reg_type & ni_reg_m_series_mask) {
 			return ni_mseries_set_pll_master_clock(dev, source,
 							       period_ns);
 		} else {
@@ -5676,6 +5725,8 @@ static int ni_set_master_clock(struct comedi_device *dev, unsigned source,
 static int ni_valid_rtsi_output_source(struct comedi_device *dev, unsigned chan,
 				       unsigned source)
 {
+	const struct ni_board_struct *board = comedi_board(dev);
+
 	if (chan >= num_configurable_rtsi_channels(dev)) {
 		if (chan == old_RTSI_clock_channel) {
 			if (source == NI_RTSI_OUTPUT_RTSI_OSC)
@@ -5702,7 +5753,7 @@ static int ni_valid_rtsi_output_source(struct comedi_device *dev, unsigned chan,
 		return 1;
 		break;
 	case NI_RTSI_OUTPUT_RTSI_OSC:
-		if (boardtype.reg_type & ni_reg_m_series_mask)
+		if (board->reg_type & ni_reg_m_series_mask)
 			return 1;
 		else
 			return 0;
@@ -5758,6 +5809,7 @@ static int ni_rtsi_insn_config(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
 			       struct comedi_insn *insn, unsigned int *data)
 {
+	const struct ni_board_struct *board = comedi_board(dev);
 	struct ni_private *devpriv = dev->private;
 	unsigned int chan = CR_CHAN(insn->chanspec);
 
@@ -5766,9 +5818,7 @@ static int ni_rtsi_insn_config(struct comedi_device *dev,
 		if (chan < num_configurable_rtsi_channels(dev)) {
 			devpriv->rtsi_trig_direction_reg |=
 			    RTSI_Output_Bit(chan,
-					    (boardtype.
-					     reg_type & ni_reg_m_series_mask) !=
-					    0);
+				(board->reg_type & ni_reg_m_series_mask) != 0);
 		} else if (chan == old_RTSI_clock_channel) {
 			devpriv->rtsi_trig_direction_reg |=
 			    Drive_RTSI_Clock_Bit;
@@ -5780,9 +5830,7 @@ static int ni_rtsi_insn_config(struct comedi_device *dev,
 		if (chan < num_configurable_rtsi_channels(dev)) {
 			devpriv->rtsi_trig_direction_reg &=
 			    ~RTSI_Output_Bit(chan,
-					     (boardtype.
-					      reg_type & ni_reg_m_series_mask)
-					     != 0);
+				(board->reg_type & ni_reg_m_series_mask) != 0);
 		} else if (chan == old_RTSI_clock_channel) {
 			devpriv->rtsi_trig_direction_reg &=
 			    ~Drive_RTSI_Clock_Bit;
@@ -5795,10 +5843,9 @@ static int ni_rtsi_insn_config(struct comedi_device *dev,
 			data[1] =
 			    (devpriv->rtsi_trig_direction_reg &
 			     RTSI_Output_Bit(chan,
-					     (boardtype.reg_type &
-					      ni_reg_m_series_mask)
-					     != 0)) ? INSN_CONFIG_DIO_OUTPUT :
-			    INSN_CONFIG_DIO_INPUT;
+				(board->reg_type & ni_reg_m_series_mask) != 0))
+				? INSN_CONFIG_DIO_OUTPUT
+				: INSN_CONFIG_DIO_INPUT;
 		} else if (chan == old_RTSI_clock_channel) {
 			data[1] =
 			    (devpriv->rtsi_trig_direction_reg &
diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c
index 0a00260..b5f340c 100644
--- a/drivers/staging/comedi/drivers/ni_pcidio.c
+++ b/drivers/staging/comedi/drivers/ni_pcidio.c
@@ -280,29 +280,30 @@ enum FPGA_Control_Bits {
 static int ni_pcidio_cancel(struct comedi_device *dev,
 			    struct comedi_subdevice *s);
 
+enum nidio_boardid {
+	BOARD_PCIDIO_32HS,
+	BOARD_PXI6533,
+	BOARD_PCI6534,
+};
+
 struct nidio_board {
-	int dev_id;
 	const char *name;
 	unsigned int uses_firmware:1;
 };
 
 static const struct nidio_board nidio_boards[] = {
-	{
-		.dev_id		= 0x1150,
+	[BOARD_PCIDIO_32HS] = {
 		.name		= "pci-dio-32hs",
-	}, {
-		.dev_id		= 0x1320,
+	},
+	[BOARD_PXI6533] = {
 		.name		= "pxi-6533",
-	}, {
-		.dev_id		= 0x12b0,
+	},
+	[BOARD_PCI6534] = {
 		.name		= "pci-6534",
 		.uses_firmware	= 1,
 	},
 };
 
-#define n_nidio_boards ARRAY_SIZE(nidio_boards)
-#define this_board ((const struct nidio_board *)dev->board_ptr)
-
 struct nidio96_private {
 	struct mite_struct *mite;
 	int boardtype;
@@ -419,7 +420,7 @@ static irqreturn_t nidio_interrupt(int irq, void *d)
 	unsigned int m_status = 0;
 
 	/* interrupcions parasites */
-	if (dev->attached == 0) {
+	if (!dev->attached) {
 		/* assume it's from another card */
 		return IRQ_NONE;
 	}
@@ -1094,29 +1095,27 @@ static int pci_6534_upload_firmware(struct comedi_device *dev)
 	return ret;
 }
 
-static const struct nidio_board *
-nidio_find_boardinfo(struct pci_dev *pcidev)
-{
-	unsigned int dev_id = pcidev->device;
-	unsigned int n;
-
-	for (n = 0; n < ARRAY_SIZE(nidio_boards); n++) {
-		const struct nidio_board *board = &nidio_boards[n];
-		if (board->dev_id == dev_id)
-			return board;
-	}
-	return NULL;
-}
-
 static int nidio_auto_attach(struct comedi_device *dev,
-				       unsigned long context_unused)
+			     unsigned long context)
 {
 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+	const struct nidio_board *board = NULL;
 	struct nidio96_private *devpriv;
 	struct comedi_subdevice *s;
 	int ret;
 	unsigned int irq;
 
+	if (context < ARRAY_SIZE(nidio_boards))
+		board = &nidio_boards[context];
+	if (!board)
+		return -ENODEV;
+	dev->board_ptr = board;
+	dev->board_name = board->name;
+
+	ret = comedi_pci_enable(dev);
+	if (ret)
+		return ret;
+
 	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
 	if (!devpriv)
 		return -ENOMEM;
@@ -1124,9 +1123,6 @@ static int nidio_auto_attach(struct comedi_device *dev,
 
 	spin_lock_init(&devpriv->mite_channel_lock);
 
-	dev->board_ptr = nidio_find_boardinfo(pcidev);
-	if (!dev->board_ptr)
-		return -ENODEV;
 	devpriv->mite = mite_alloc(pcidev);
 	if (!devpriv->mite)
 		return -ENOMEM;
@@ -1141,9 +1137,8 @@ static int nidio_auto_attach(struct comedi_device *dev,
 	if (devpriv->di_mite_ring == NULL)
 		return -ENOMEM;
 
-	dev->board_name = this_board->name;
 	irq = mite_irq(devpriv->mite);
-	if (this_board->uses_firmware) {
+	if (board->uses_firmware) {
 		ret = pci_6534_upload_firmware(dev);
 		if (ret < 0)
 			return ret;
@@ -1211,6 +1206,7 @@ static void nidio_detach(struct comedi_device *dev)
 			mite_free(devpriv->mite);
 		}
 	}
+	comedi_pci_disable(dev);
 }
 
 static struct comedi_driver ni_pcidio_driver = {
@@ -1221,15 +1217,15 @@ static struct comedi_driver ni_pcidio_driver = {
 };
 
 static int ni_pcidio_pci_probe(struct pci_dev *dev,
-					 const struct pci_device_id *ent)
+			       const struct pci_device_id *id)
 {
-	return comedi_pci_auto_config(dev, &ni_pcidio_driver);
+	return comedi_pci_auto_config(dev, &ni_pcidio_driver, id->driver_data);
 }
 
 static DEFINE_PCI_DEVICE_TABLE(ni_pcidio_pci_table) = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1150) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1320) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x12b0) },
+	{ PCI_VDEVICE(NI, 0x1150), BOARD_PCIDIO_32HS },
+	{ PCI_VDEVICE(NI, 0x12b0), BOARD_PCI6534 },
+	{ PCI_VDEVICE(NI, 0x1320), BOARD_PXI6533 },
 	{ 0 }
 };
 MODULE_DEVICE_TABLE(pci, ni_pcidio_pci_table);
diff --git a/drivers/staging/comedi/drivers/ni_pcimio.c b/drivers/staging/comedi/drivers/ni_pcimio.c
index 98b43f2..bc83df5 100644
--- a/drivers/staging/comedi/drivers/ni_pcimio.c
+++ b/drivers/staging/comedi/drivers/ni_pcimio.c
@@ -111,7 +111,6 @@ Bugs:
 */
 
 #include <linux/delay.h>
-#include <linux/delay.h>
 
 #include "../comedidev.h"
 
@@ -163,1031 +162,894 @@ static const struct comedi_lrange range_ni_M_622x_ao = { 1, {
 							     }
 };
 
+enum ni_pcimio_boardid {
+	BOARD_PCIMIO_16XE_50,
+	BOARD_PCIMIO_16XE_10,
+	BOARD_PCI6014,
+	BOARD_PXI6030E,
+	BOARD_PCIMIO_16E_1,
+	BOARD_PCIMIO_16E_4,
+	BOARD_PXI6040E,
+	BOARD_PCI6031E,
+	BOARD_PCI6032E,
+	BOARD_PCI6033E,
+	BOARD_PCI6071E,
+	BOARD_PCI6023E,
+	BOARD_PCI6024E,
+	BOARD_PCI6025E,
+	BOARD_PXI6025E,
+	BOARD_PCI6034E,
+	BOARD_PCI6035E,
+	BOARD_PCI6052E,
+	BOARD_PCI6110,
+	BOARD_PCI6111,
+	/* BOARD_PCI6115, */
+	/* BOARD_PXI6115, */
+	BOARD_PCI6711,
+	BOARD_PXI6711,
+	BOARD_PCI6713,
+	BOARD_PXI6713,
+	BOARD_PCI6731,
+	/* BOARD_PXI6731, */
+	BOARD_PCI6733,
+	BOARD_PXI6733,
+	BOARD_PXI6071E,
+	BOARD_PXI6070E,
+	BOARD_PXI6052E,
+	BOARD_PXI6031E,
+	BOARD_PCI6036E,
+	BOARD_PCI6220,
+	BOARD_PCI6221,
+	BOARD_PCI6221_37PIN,
+	BOARD_PCI6224,
+	BOARD_PXI6224,
+	BOARD_PCI6225,
+	BOARD_PXI6225,
+	BOARD_PCI6229,
+	BOARD_PCI6250,
+	BOARD_PCI6251,
+	BOARD_PCIE6251,
+	BOARD_PXIE6251,
+	BOARD_PCI6254,
+	BOARD_PCI6259,
+	BOARD_PCIE6259,
+	BOARD_PCI6280,
+	BOARD_PCI6281,
+	BOARD_PXI6281,
+	BOARD_PCI6284,
+	BOARD_PCI6289,
+	BOARD_PCI6143,
+	BOARD_PXI6143,
+};
+
 static const struct ni_board_struct ni_boards[] = {
-	{
-	 .device_id = 0x0162,	/*  NI also says 0x1620.  typo? */
-	 .name = "pci-mio-16xe-50",
-	 .n_adchan = 16,
-	 .adbits = 16,
-	 .ai_fifo_depth = 2048,
-	 .alwaysdither = 1,
-	 .gainlkup = ai_gain_8,
-	 .ai_speed = 50000,
-	 .n_aochan = 2,
-	 .aobits = 12,
-	 .ao_fifo_depth = 0,
-	 .ao_range_table = &range_bipolar10,
-	 .ao_unipolar = 0,
-	 .ao_speed = 50000,
-	 .num_p0_dio_channels = 8,
-	 .caldac = {dac8800, dac8043},
-	 .has_8255 = 0,
-	 },
-	{
-	 .device_id = 0x1170,
-	 .name = "pci-mio-16xe-10",	/*  aka pci-6030E */
-	 .n_adchan = 16,
-	 .adbits = 16,
-	 .ai_fifo_depth = 512,
-	 .alwaysdither = 1,
-	 .gainlkup = ai_gain_14,
-	 .ai_speed = 10000,
-	 .n_aochan = 2,
-	 .aobits = 16,
-	 .ao_fifo_depth = 2048,
-	 .ao_range_table = &range_ni_E_ao_ext,
-	 .ao_unipolar = 1,
-	 .ao_speed = 10000,
-	 .num_p0_dio_channels = 8,
-	 .caldac = {dac8800, dac8043, ad8522},
-	 .has_8255 = 0,
-	 },
-	{
-	 .device_id = 0x28c0,
-	 .name = "pci-6014",
-	 .n_adchan = 16,
-	 .adbits = 16,
-	 .ai_fifo_depth = 512,
-	 .alwaysdither = 1,
-	 .gainlkup = ai_gain_4,
-	 .ai_speed = 5000,
-	 .n_aochan = 2,
-	 .aobits = 16,
-	 .ao_fifo_depth = 0,
-	 .ao_range_table = &range_bipolar10,
-	 .ao_unipolar = 0,
-	 .ao_speed = 100000,
-	 .num_p0_dio_channels = 8,
-	 .caldac = {ad8804_debug},
-	 .has_8255 = 0,
-	 },
-	{
-	 .device_id = 0x11d0,
-	 .name = "pxi-6030e",
-	 .n_adchan = 16,
-	 .adbits = 16,
-	 .ai_fifo_depth = 512,
-	 .alwaysdither = 1,
-	 .gainlkup = ai_gain_14,
-	 .ai_speed = 10000,
-	 .n_aochan = 2,
-	 .aobits = 16,
-	 .ao_fifo_depth = 2048,
-	 .ao_range_table = &range_ni_E_ao_ext,
-	 .ao_unipolar = 1,
-	 .ao_speed = 10000,
-	 .num_p0_dio_channels = 8,
-	 .caldac = {dac8800, dac8043, ad8522},
-	 .has_8255 = 0,
-	 },
-	{
-	 .device_id = 0x1180,
-	 .name = "pci-mio-16e-1",	/* aka pci-6070e */
-	 .n_adchan = 16,
-	 .adbits = 12,
-	 .ai_fifo_depth = 512,
-	 .alwaysdither = 0,
-	 .gainlkup = ai_gain_16,
-	 .ai_speed = 800,
-	 .n_aochan = 2,
-	 .aobits = 12,
-	 .ao_fifo_depth = 2048,
-	 .ao_range_table = &range_ni_E_ao_ext,
-	 .ao_unipolar = 1,
-	 .ao_speed = 1000,
-	 .num_p0_dio_channels = 8,
-	 .caldac = {mb88341},
-	 .has_8255 = 0,
-	 },
-	{
-	 .device_id = 0x1190,
-	 .name = "pci-mio-16e-4",	/* aka pci-6040e */
-	 .n_adchan = 16,
-	 .adbits = 12,
-	 .ai_fifo_depth = 512,
-	 .alwaysdither = 0,
-	 .gainlkup = ai_gain_16,
-	 /*      .Note = there have been reported problems with full speed
-	  * on this board */
-	 .ai_speed = 2000,
-	 .n_aochan = 2,
-	 .aobits = 12,
-	 .ao_fifo_depth = 512,
-	 .ao_range_table = &range_ni_E_ao_ext,
-	 .ao_unipolar = 1,
-	 .ao_speed = 1000,
-	 .num_p0_dio_channels = 8,
-	 .caldac = {ad8804_debug},	/*  doc says mb88341 */
-	 .has_8255 = 0,
-	 },
-	{
-	 .device_id = 0x11c0,
-	 .name = "pxi-6040e",
-	 .n_adchan = 16,
-	 .adbits = 12,
-	 .ai_fifo_depth = 512,
-	 .alwaysdither = 0,
-	 .gainlkup = ai_gain_16,
-	 .ai_speed = 2000,
-	 .n_aochan = 2,
-	 .aobits = 12,
-	 .ao_fifo_depth = 512,
-	 .ao_range_table = &range_ni_E_ao_ext,
-	 .ao_unipolar = 1,
-	 .ao_speed = 1000,
-	 .num_p0_dio_channels = 8,
-	 .caldac = {mb88341},
-	 .has_8255 = 0,
-	 },
-
-	{
-	 .device_id = 0x1330,
-	 .name = "pci-6031e",
-	 .n_adchan = 64,
-	 .adbits = 16,
-	 .ai_fifo_depth = 512,
-	 .alwaysdither = 1,
-	 .gainlkup = ai_gain_14,
-	 .ai_speed = 10000,
-	 .n_aochan = 2,
-	 .aobits = 16,
-	 .ao_fifo_depth = 2048,
-	 .ao_range_table = &range_ni_E_ao_ext,
-	 .ao_unipolar = 1,
-	 .ao_speed = 10000,
-	 .num_p0_dio_channels = 8,
-	 .caldac = {dac8800, dac8043, ad8522},
-	 .has_8255 = 0,
-	 },
-	{
-	 .device_id = 0x1270,
-	 .name = "pci-6032e",
-	 .n_adchan = 16,
-	 .adbits = 16,
-	 .ai_fifo_depth = 512,
-	 .alwaysdither = 1,
-	 .gainlkup = ai_gain_14,
-	 .ai_speed = 10000,
-	 .n_aochan = 0,
-	 .aobits = 0,
-	 .ao_fifo_depth = 0,
-	 .ao_unipolar = 0,
-	 .num_p0_dio_channels = 8,
-	 .caldac = {dac8800, dac8043, ad8522},
-	 .has_8255 = 0,
-	 },
-	{
-	 .device_id = 0x1340,
-	 .name = "pci-6033e",
-	 .n_adchan = 64,
-	 .adbits = 16,
-	 .ai_fifo_depth = 512,
-	 .alwaysdither = 1,
-	 .gainlkup = ai_gain_14,
-	 .ai_speed = 10000,
-	 .n_aochan = 0,
-	 .aobits = 0,
-	 .ao_fifo_depth = 0,
-	 .ao_unipolar = 0,
-	 .num_p0_dio_channels = 8,
-	 .caldac = {dac8800, dac8043, ad8522},
-	 .has_8255 = 0,
-	 },
-	{
-	 .device_id = 0x1350,
-	 .name = "pci-6071e",
-	 .n_adchan = 64,
-	 .adbits = 12,
-	 .ai_fifo_depth = 512,
-	 .alwaysdither = 1,
-	 .gainlkup = ai_gain_16,
-	 .ai_speed = 800,
-	 .n_aochan = 2,
-	 .aobits = 12,
-	 .ao_fifo_depth = 2048,
-	 .ao_range_table = &range_ni_E_ao_ext,
-	 .ao_unipolar = 1,
-	 .ao_speed = 1000,
-	 .num_p0_dio_channels = 8,
-	 .caldac = {ad8804_debug},
-	 .has_8255 = 0,
-	 },
-	{
-	 .device_id = 0x2a60,
-	 .name = "pci-6023e",
-	 .n_adchan = 16,
-	 .adbits = 12,
-	 .ai_fifo_depth = 512,
-	 .alwaysdither = 0,
-	 .gainlkup = ai_gain_4,
-	 .ai_speed = 5000,
-	 .n_aochan = 0,
-	 .aobits = 0,
-	 .ao_unipolar = 0,
-	 .num_p0_dio_channels = 8,
-	 .caldac = {ad8804_debug},	/* manual is wrong */
-	 .has_8255 = 0,
-	 },
-	{
-	 .device_id = 0x2a70,
-	 .name = "pci-6024e",
-	 .n_adchan = 16,
-	 .adbits = 12,
-	 .ai_fifo_depth = 512,
-	 .alwaysdither = 0,
-	 .gainlkup = ai_gain_4,
-	 .ai_speed = 5000,
-	 .n_aochan = 2,
-	 .aobits = 12,
-	 .ao_fifo_depth = 0,
-	 .ao_range_table = &range_bipolar10,
-	 .ao_unipolar = 0,
-	 .ao_speed = 100000,
-	 .num_p0_dio_channels = 8,
-	 .caldac = {ad8804_debug},	/* manual is wrong */
-	 .has_8255 = 0,
-	 },
-	{
-	 .device_id = 0x2a80,
-	 .name = "pci-6025e",
-	 .n_adchan = 16,
-	 .adbits = 12,
-	 .ai_fifo_depth = 512,
-	 .alwaysdither = 0,
-	 .gainlkup = ai_gain_4,
-	 .ai_speed = 5000,
-	 .n_aochan = 2,
-	 .aobits = 12,
-	 .ao_fifo_depth = 0,
-	 .ao_range_table = &range_bipolar10,
-	 .ao_unipolar = 0,
-	 .ao_speed = 100000,
-	 .num_p0_dio_channels = 8,
-	 .caldac = {ad8804_debug},	/* manual is wrong */
-	 .has_8255 = 1,
-	 },
-	{
-	 .device_id = 0x2ab0,
-	 .name = "pxi-6025e",
-	 .n_adchan = 16,
-	 .adbits = 12,
-	 .ai_fifo_depth = 512,
-	 .alwaysdither = 0,
-	 .gainlkup = ai_gain_4,
-	 .ai_speed = 5000,
-	 .n_aochan = 2,
-	 .aobits = 12,
-	 .ao_fifo_depth = 0,
-	 .ao_range_table = &range_ni_E_ao_ext,
-	 .ao_unipolar = 1,
-	 .ao_speed = 100000,
-	 .num_p0_dio_channels = 8,
-	 .caldac = {ad8804_debug},	/* manual is wrong */
-	 .has_8255 = 1,
-	 },
-
-	{
-	 .device_id = 0x2ca0,
-	 .name = "pci-6034e",
-	 .n_adchan = 16,
-	 .adbits = 16,
-	 .ai_fifo_depth = 512,
-	 .alwaysdither = 1,
-	 .gainlkup = ai_gain_4,
-	 .ai_speed = 5000,
-	 .n_aochan = 0,
-	 .aobits = 0,
-	 .ao_fifo_depth = 0,
-	 .ao_unipolar = 0,
-	 .num_p0_dio_channels = 8,
-	 .caldac = {ad8804_debug},
-	 .has_8255 = 0,
-	 },
-	{
-	 .device_id = 0x2c80,
-	 .name = "pci-6035e",
-	 .n_adchan = 16,
-	 .adbits = 16,
-	 .ai_fifo_depth = 512,
-	 .alwaysdither = 1,
-	 .gainlkup = ai_gain_4,
-	 .ai_speed = 5000,
-	 .n_aochan = 2,
-	 .aobits = 12,
-	 .ao_fifo_depth = 0,
-	 .ao_range_table = &range_bipolar10,
-	 .ao_unipolar = 0,
-	 .ao_speed = 100000,
-	 .num_p0_dio_channels = 8,
-	 .caldac = {ad8804_debug},
-	 .has_8255 = 0,
-	 },
-	{
-	 .device_id = 0x18b0,
-	 .name = "pci-6052e",
-	 .n_adchan = 16,
-	 .adbits = 16,
-	 .ai_fifo_depth = 512,
-	 .alwaysdither = 1,
-	 .gainlkup = ai_gain_16,
-	 .ai_speed = 3000,
-	 .n_aochan = 2,
-	 .aobits = 16,
-	 .ao_unipolar = 1,
-	 .ao_fifo_depth = 2048,
-	 .ao_range_table = &range_ni_E_ao_ext,
-	 .ao_speed = 3000,
-	 .num_p0_dio_channels = 8,
-	 .caldac = {ad8804_debug, ad8804_debug, ad8522},	/* manual is wrong */
-	 },
-	{.device_id = 0x14e0,
-	 .name = "pci-6110",
-	 .n_adchan = 4,
-	 .adbits = 12,
-	 .ai_fifo_depth = 8192,
-	 .alwaysdither = 0,
-	 .gainlkup = ai_gain_611x,
-	 .ai_speed = 200,
-	 .n_aochan = 2,
-	 .aobits = 16,
-	 .reg_type = ni_reg_611x,
-	 .ao_range_table = &range_bipolar10,
-	 .ao_unipolar = 0,
-	 .ao_fifo_depth = 2048,
-	 .ao_speed = 250,
-	 .num_p0_dio_channels = 8,
-	 .caldac = {ad8804, ad8804},
-	 },
-	{
-	 .device_id = 0x14f0,
-	 .name = "pci-6111",
-	 .n_adchan = 2,
-	 .adbits = 12,
-	 .ai_fifo_depth = 8192,
-	 .alwaysdither = 0,
-	 .gainlkup = ai_gain_611x,
-	 .ai_speed = 200,
-	 .n_aochan = 2,
-	 .aobits = 16,
-	 .reg_type = ni_reg_611x,
-	 .ao_range_table = &range_bipolar10,
-	 .ao_unipolar = 0,
-	 .ao_fifo_depth = 2048,
-	 .ao_speed = 250,
-	 .num_p0_dio_channels = 8,
-	 .caldac = {ad8804, ad8804},
-	 },
+	[BOARD_PCIMIO_16XE_50] = {
+		.name		= "pci-mio-16xe-50",
+		.n_adchan	= 16,
+		.adbits		= 16,
+		.ai_fifo_depth	= 2048,
+		.alwaysdither	= 1,
+		.gainlkup	= ai_gain_8,
+		.ai_speed	= 50000,
+		.n_aochan	= 2,
+		.aobits		= 12,
+		.ao_range_table	= &range_bipolar10,
+		.ao_speed	= 50000,
+		.num_p0_dio_channels = 8,
+		.caldac		= { dac8800, dac8043 },
+	},
+	[BOARD_PCIMIO_16XE_10] = {
+		.name		= "pci-mio-16xe-10",	/*  aka pci-6030E */
+		.n_adchan	= 16,
+		.adbits		= 16,
+		.ai_fifo_depth	= 512,
+		.alwaysdither	= 1,
+		.gainlkup	= ai_gain_14,
+		.ai_speed	= 10000,
+		.n_aochan	= 2,
+		.aobits		= 16,
+		.ao_fifo_depth	= 2048,
+		.ao_range_table	= &range_ni_E_ao_ext,
+		.ao_unipolar	= 1,
+		.ao_speed	= 10000,
+		.num_p0_dio_channels = 8,
+		.caldac		= { dac8800, dac8043, ad8522 },
+	},
+	[BOARD_PCI6014] = {
+		.name		= "pci-6014",
+		.n_adchan	= 16,
+		.adbits		= 16,
+		.ai_fifo_depth	= 512,
+		.alwaysdither	= 1,
+		.gainlkup	= ai_gain_4,
+		.ai_speed	= 5000,
+		.n_aochan	= 2,
+		.aobits		= 16,
+		.ao_range_table	= &range_bipolar10,
+		.ao_speed	= 100000,
+		.num_p0_dio_channels = 8,
+		.caldac		= { ad8804_debug },
+	},
+	[BOARD_PXI6030E] = {
+		.name		= "pxi-6030e",
+		.n_adchan	= 16,
+		.adbits		= 16,
+		.ai_fifo_depth	= 512,
+		.alwaysdither	= 1,
+		.gainlkup	= ai_gain_14,
+		.ai_speed	= 10000,
+		.n_aochan	= 2,
+		.aobits		= 16,
+		.ao_fifo_depth	= 2048,
+		.ao_range_table	= &range_ni_E_ao_ext,
+		.ao_unipolar	= 1,
+		.ao_speed	= 10000,
+		.num_p0_dio_channels = 8,
+		.caldac		= { dac8800, dac8043, ad8522 },
+	},
+	[BOARD_PCIMIO_16E_1] = {
+		.name		= "pci-mio-16e-1",	/* aka pci-6070e */
+		.n_adchan	= 16,
+		.adbits		= 12,
+		.ai_fifo_depth	= 512,
+		.gainlkup	= ai_gain_16,
+		.ai_speed	= 800,
+		.n_aochan	= 2,
+		.aobits		= 12,
+		.ao_fifo_depth	= 2048,
+		.ao_range_table	= &range_ni_E_ao_ext,
+		.ao_unipolar	= 1,
+		.ao_speed	= 1000,
+		.num_p0_dio_channels = 8,
+		.caldac		= { mb88341 },
+	},
+	[BOARD_PCIMIO_16E_4] = {
+		.name		= "pci-mio-16e-4",	/* aka pci-6040e */
+		.n_adchan	= 16,
+		.adbits		= 12,
+		.ai_fifo_depth	= 512,
+		.gainlkup	= ai_gain_16,
+		/*
+		 * there have been reported problems with
+		 * full speed on this board
+		 */
+		.ai_speed	= 2000,
+		.n_aochan	= 2,
+		.aobits		= 12,
+		.ao_fifo_depth	= 512,
+		.ao_range_table	= &range_ni_E_ao_ext,
+		.ao_unipolar	= 1,
+		.ao_speed	= 1000,
+		.num_p0_dio_channels = 8,
+		.caldac		= { ad8804_debug },	/* doc says mb88341 */
+	},
+	[BOARD_PXI6040E] = {
+		.name		= "pxi-6040e",
+		.n_adchan	= 16,
+		.adbits		= 12,
+		.ai_fifo_depth	= 512,
+		.gainlkup	= ai_gain_16,
+		.ai_speed	= 2000,
+		.n_aochan	= 2,
+		.aobits		= 12,
+		.ao_fifo_depth	= 512,
+		.ao_range_table	= &range_ni_E_ao_ext,
+		.ao_unipolar	= 1,
+		.ao_speed	= 1000,
+		.num_p0_dio_channels = 8,
+		.caldac		= { mb88341 },
+	},
+	[BOARD_PCI6031E] = {
+		.name		= "pci-6031e",
+		.n_adchan	= 64,
+		.adbits		= 16,
+		.ai_fifo_depth	= 512,
+		.alwaysdither	= 1,
+		.gainlkup	= ai_gain_14,
+		.ai_speed	= 10000,
+		.n_aochan	= 2,
+		.aobits		= 16,
+		.ao_fifo_depth	= 2048,
+		.ao_range_table	= &range_ni_E_ao_ext,
+		.ao_unipolar	= 1,
+		.ao_speed	= 10000,
+		.num_p0_dio_channels = 8,
+		.caldac		= { dac8800, dac8043, ad8522 },
+	},
+	[BOARD_PCI6032E] = {
+		.name		= "pci-6032e",
+		.n_adchan	= 16,
+		.adbits		= 16,
+		.ai_fifo_depth	= 512,
+		.alwaysdither	= 1,
+		.gainlkup	= ai_gain_14,
+		.ai_speed	= 10000,
+		.num_p0_dio_channels = 8,
+		.caldac		= { dac8800, dac8043, ad8522 },
+	},
+	[BOARD_PCI6033E] = {
+		.name		= "pci-6033e",
+		.n_adchan	= 64,
+		.adbits		= 16,
+		.ai_fifo_depth	= 512,
+		.alwaysdither	= 1,
+		.gainlkup	= ai_gain_14,
+		.ai_speed	= 10000,
+		.num_p0_dio_channels = 8,
+		.caldac		= { dac8800, dac8043, ad8522 },
+	},
+	[BOARD_PCI6071E] = {
+		.name		= "pci-6071e",
+		.n_adchan	= 64,
+		.adbits		= 12,
+		.ai_fifo_depth	= 512,
+		.alwaysdither	= 1,
+		.gainlkup	= ai_gain_16,
+		.ai_speed	= 800,
+		.n_aochan	= 2,
+		.aobits		= 12,
+		.ao_fifo_depth	= 2048,
+		.ao_range_table	= &range_ni_E_ao_ext,
+		.ao_unipolar	= 1,
+		.ao_speed	= 1000,
+		.num_p0_dio_channels = 8,
+		.caldac		= { ad8804_debug },
+	},
+	[BOARD_PCI6023E] = {
+		.name		= "pci-6023e",
+		.n_adchan	= 16,
+		.adbits		= 12,
+		.ai_fifo_depth	= 512,
+		.gainlkup	= ai_gain_4,
+		.ai_speed	= 5000,
+		.num_p0_dio_channels = 8,
+		.caldac		= { ad8804_debug },	/* manual is wrong */
+	},
+	[BOARD_PCI6024E] = {
+		.name		= "pci-6024e",
+		.n_adchan	= 16,
+		.adbits		= 12,
+		.ai_fifo_depth	= 512,
+		.gainlkup	= ai_gain_4,
+		.ai_speed	= 5000,
+		.n_aochan	= 2,
+		.aobits		= 12,
+		.ao_range_table	= &range_bipolar10,
+		.ao_speed	= 100000,
+		.num_p0_dio_channels = 8,
+		.caldac		= { ad8804_debug },	/* manual is wrong */
+	},
+	[BOARD_PCI6025E] = {
+		.name		= "pci-6025e",
+		.n_adchan	= 16,
+		.adbits		= 12,
+		.ai_fifo_depth	= 512,
+		.gainlkup	= ai_gain_4,
+		.ai_speed	= 5000,
+		.n_aochan	= 2,
+		.aobits		= 12,
+		.ao_range_table	= &range_bipolar10,
+		.ao_speed	= 100000,
+		.num_p0_dio_channels = 8,
+		.caldac		= { ad8804_debug },	/* manual is wrong */
+		.has_8255	= 1,
+	},
+	[BOARD_PXI6025E] = {
+		.name		= "pxi-6025e",
+		.n_adchan	= 16,
+		.adbits		= 12,
+		.ai_fifo_depth	= 512,
+		.gainlkup	= ai_gain_4,
+		.ai_speed	= 5000,
+		.n_aochan	= 2,
+		.aobits		= 12,
+		.ao_range_table	= &range_ni_E_ao_ext,
+		.ao_unipolar	= 1,
+		.ao_speed	= 100000,
+		.num_p0_dio_channels = 8,
+		.caldac		= { ad8804_debug },	/* manual is wrong */
+		.has_8255	= 1,
+	},
+	[BOARD_PCI6034E] = {
+		.name		= "pci-6034e",
+		.n_adchan	= 16,
+		.adbits		= 16,
+		.ai_fifo_depth	= 512,
+		.alwaysdither	= 1,
+		.gainlkup	= ai_gain_4,
+		.ai_speed	= 5000,
+		.num_p0_dio_channels = 8,
+		.caldac		= { ad8804_debug },
+	},
+	[BOARD_PCI6035E] = {
+		.name		= "pci-6035e",
+		.n_adchan	= 16,
+		.adbits		= 16,
+		.ai_fifo_depth	= 512,
+		.alwaysdither	= 1,
+		.gainlkup	= ai_gain_4,
+		.ai_speed	= 5000,
+		.n_aochan	= 2,
+		.aobits		= 12,
+		.ao_range_table	= &range_bipolar10,
+		.ao_speed	= 100000,
+		.num_p0_dio_channels = 8,
+		.caldac		= { ad8804_debug },
+	},
+	[BOARD_PCI6052E] = {
+		.name		= "pci-6052e",
+		.n_adchan	= 16,
+		.adbits		= 16,
+		.ai_fifo_depth	= 512,
+		.alwaysdither	= 1,
+		.gainlkup	= ai_gain_16,
+		.ai_speed	= 3000,
+		.n_aochan	= 2,
+		.aobits		= 16,
+		.ao_unipolar	= 1,
+		.ao_fifo_depth	= 2048,
+		.ao_range_table	= &range_ni_E_ao_ext,
+		.ao_speed	= 3000,
+		.num_p0_dio_channels = 8,
+		/* manual is wrong */
+		.caldac		= { ad8804_debug, ad8804_debug, ad8522 },
+	},
+	[BOARD_PCI6110] = {
+		.name		= "pci-6110",
+		.n_adchan	= 4,
+		.adbits		= 12,
+		.ai_fifo_depth	= 8192,
+		.alwaysdither	= 0,
+		.gainlkup	= ai_gain_611x,
+		.ai_speed	= 200,
+		.n_aochan	= 2,
+		.aobits		= 16,
+		.reg_type	= ni_reg_611x,
+		.ao_range_table	= &range_bipolar10,
+		.ao_fifo_depth	= 2048,
+		.ao_speed	= 250,
+		.num_p0_dio_channels = 8,
+		.caldac		= { ad8804, ad8804 },
+	},
+	[BOARD_PCI6111] = {
+		.name		= "pci-6111",
+		.n_adchan	= 2,
+		.adbits		= 12,
+		.ai_fifo_depth	= 8192,
+		.gainlkup	= ai_gain_611x,
+		.ai_speed	= 200,
+		.n_aochan	= 2,
+		.aobits		= 16,
+		.reg_type	= ni_reg_611x,
+		.ao_range_table	= &range_bipolar10,
+		.ao_fifo_depth	= 2048,
+		.ao_speed	= 250,
+		.num_p0_dio_channels = 8,
+		.caldac		= { ad8804, ad8804 },
+	},
 #if 0
 	/* The 6115 boards probably need their own driver */
-	{
-	 .device_id = 0x2ed0,
-	 .name = "pci-6115",
-	 .n_adchan = 4,
-	 .adbits = 12,
-	 .ai_fifo_depth = 8192,
-	 .alwaysdither = 0,
-	 .gainlkup = ai_gain_611x,
-	 .ai_speed = 100,
-	 .n_aochan = 2,
-	 .aobits = 16,
-	 .ao_671x = 1,
-	 .ao_unipolar = 0,
-	 .ao_fifo_depth = 2048,
-	 .ao_speed = 250,
-	 .num_p0_dio_channels = 8,
-	 .reg_611x = 1,
-	 .caldac = {ad8804_debug, ad8804_debug, ad8804_debug},	/* XXX */
-	 },
+	[BOARD_PCI6115] = {	/* .device_id = 0x2ed0, */
+		.name		= "pci-6115",
+		.n_adchan	= 4,
+		.adbits		= 12,
+		.ai_fifo_depth	= 8192,
+		.gainlkup	= ai_gain_611x,
+		.ai_speed	= 100,
+		.n_aochan	= 2,
+		.aobits		= 16,
+		.ao_671x	= 1,
+		.ao_fifo_depth	= 2048,
+		.ao_speed	= 250,
+		.num_p0_dio_channels = 8,
+		.reg_611x	= 1,
+		/* XXX */
+		.caldac		= { ad8804_debug, ad8804_debug, ad8804_debug },
+	},
 #endif
 #if 0
-	{
-	 .device_id = 0x0000,
-	 .name = "pxi-6115",
-	 .n_adchan = 4,
-	 .adbits = 12,
-	 .ai_fifo_depth = 8192,
-	 .alwaysdither = 0,
-	 .gainlkup = ai_gain_611x,
-	 .ai_speed = 100,
-	 .n_aochan = 2,
-	 .aobits = 16,
-	 .ao_671x = 1,
-	 .ao_unipolar = 0,
-	 .ao_fifo_depth = 2048,
-	 .ao_speed = 250,
-	 .reg_611x = 1,
-	 .num_p0_dio_channels = 8,
-	 caldac = {ad8804_debug, ad8804_debug, ad8804_debug},	/* XXX */
-	 },
+	[BOARD_PXI6115] = {	/* .device_id = ????, */
+		.name		= "pxi-6115",
+		.n_adchan	= 4,
+		.adbits		= 12,
+		.ai_fifo_depth	= 8192,
+		.gainlkup	= ai_gain_611x,
+		.ai_speed	= 100,
+		.n_aochan	= 2,
+		.aobits		= 16,
+		.ao_671x	= 1,
+		.ao_fifo_depth	= 2048,
+		.ao_speed	= 250,
+		.reg_611x	= 1,
+		.num_p0_dio_channels = 8,
+		/* XXX */
+		.caldac		= { ad8804_debug, ad8804_debug, ad8804_debug },
+	},
 #endif
-	{
-	 .device_id = 0x1880,
-	 .name = "pci-6711",
-	 .n_adchan = 0,		/* no analog input */
-	 .n_aochan = 4,
-	 .aobits = 12,
-	 .ao_unipolar = 0,
-	 .ao_fifo_depth = 16384,
-	 /* data sheet says 8192, but fifo really holds 16384 samples */
-	 .ao_range_table = &range_bipolar10,
-	 .ao_speed = 1000,
-	 .num_p0_dio_channels = 8,
-	 .reg_type = ni_reg_6711,
-	 .caldac = {ad8804_debug},
-	 },
-	{
-	 .device_id = 0x2b90,
-	 .name = "pxi-6711",
-	 .n_adchan = 0,		/* no analog input */
-	 .n_aochan = 4,
-	 .aobits = 12,
-	 .ao_unipolar = 0,
-	 .ao_fifo_depth = 16384,
-	 .ao_range_table = &range_bipolar10,
-	 .ao_speed = 1000,
-	 .num_p0_dio_channels = 8,
-	 .reg_type = ni_reg_6711,
-	 .caldac = {ad8804_debug},
-	 },
-	{
-	 .device_id = 0x1870,
-	 .name = "pci-6713",
-	 .n_adchan = 0,		/* no analog input */
-	 .n_aochan = 8,
-	 .aobits = 12,
-	 .ao_unipolar = 0,
-	 .ao_fifo_depth = 16384,
-	 .ao_range_table = &range_bipolar10,
-	 .ao_speed = 1000,
-	 .num_p0_dio_channels = 8,
-	 .reg_type = ni_reg_6713,
-	 .caldac = {ad8804_debug, ad8804_debug},
-	 },
-	{
-	 .device_id = 0x2b80,
-	 .name = "pxi-6713",
-	 .n_adchan = 0,		/* no analog input */
-	 .n_aochan = 8,
-	 .aobits = 12,
-	 .ao_unipolar = 0,
-	 .ao_fifo_depth = 16384,
-	 .ao_range_table = &range_bipolar10,
-	 .ao_speed = 1000,
-	 .num_p0_dio_channels = 8,
-	 .reg_type = ni_reg_6713,
-	 .caldac = {ad8804_debug, ad8804_debug},
-	 },
-	{
-	 .device_id = 0x2430,
-	 .name = "pci-6731",
-	 .n_adchan = 0,		/* no analog input */
-	 .n_aochan = 4,
-	 .aobits = 16,
-	 .ao_unipolar = 0,
-	 .ao_fifo_depth = 8192,
-	 .ao_range_table = &range_bipolar10,
-	 .ao_speed = 1000,
-	 .num_p0_dio_channels = 8,
-	 .reg_type = ni_reg_6711,
-	 .caldac = {ad8804_debug},
-	 },
-#if 0				/* need device ids */
-	{
-	 .device_id = 0x0,
-	 .name = "pxi-6731",
-	 .n_adchan = 0,		/* no analog input */
-	 .n_aochan = 4,
-	 .aobits = 16,
-	 .ao_unipolar = 0,
-	 .ao_fifo_depth = 8192,
-	 .ao_range_table = &range_bipolar10,
-	 .num_p0_dio_channels = 8,
-	 .reg_type = ni_reg_6711,
-	 .caldac = {ad8804_debug},
-	 },
+	[BOARD_PCI6711] = {
+		.name = "pci-6711",
+		.n_aochan	= 4,
+		.aobits		= 12,
+		/* data sheet says 8192, but fifo really holds 16384 samples */
+		.ao_fifo_depth	= 16384,
+		.ao_range_table	= &range_bipolar10,
+		.ao_speed	= 1000,
+		.num_p0_dio_channels = 8,
+		.reg_type	= ni_reg_6711,
+		.caldac		= { ad8804_debug },
+	},
+	[BOARD_PXI6711] = {
+		.name		= "pxi-6711",
+		.n_aochan	= 4,
+		.aobits		= 12,
+		.ao_fifo_depth	= 16384,
+		.ao_range_table	= &range_bipolar10,
+		.ao_speed	= 1000,
+		.num_p0_dio_channels = 8,
+		.reg_type	= ni_reg_6711,
+		.caldac		= { ad8804_debug },
+	},
+	[BOARD_PCI6713] = {
+		.name		= "pci-6713",
+		.n_aochan	= 8,
+		.aobits		= 12,
+		.ao_fifo_depth	= 16384,
+		.ao_range_table	= &range_bipolar10,
+		.ao_speed	= 1000,
+		.num_p0_dio_channels = 8,
+		.reg_type	= ni_reg_6713,
+		.caldac		= { ad8804_debug, ad8804_debug },
+	},
+	[BOARD_PXI6713] = {
+		.name		= "pxi-6713",
+		.n_aochan	= 8,
+		.aobits		= 12,
+		.ao_fifo_depth	= 16384,
+		.ao_range_table	= &range_bipolar10,
+		.ao_speed	= 1000,
+		.num_p0_dio_channels = 8,
+		.reg_type	= ni_reg_6713,
+		.caldac		= { ad8804_debug, ad8804_debug },
+	},
+	[BOARD_PCI6731] = {
+		.name		= "pci-6731",
+		.n_aochan	= 4,
+		.aobits		= 16,
+		.ao_fifo_depth	= 8192,
+		.ao_range_table	= &range_bipolar10,
+		.ao_speed	= 1000,
+		.num_p0_dio_channels = 8,
+		.reg_type	= ni_reg_6711,
+		.caldac		= { ad8804_debug },
+	},
+#if 0
+	[BOARD_PXI6731] = {	/* .device_id = ????, */
+		.name		= "pxi-6731",
+		.n_aochan	= 4,
+		.aobits		= 16,
+		.ao_fifo_depth	= 8192,
+		.ao_range_table	= &range_bipolar10,
+		.num_p0_dio_channels = 8,
+		.reg_type	= ni_reg_6711,
+		.caldac		= { ad8804_debug },
+	},
 #endif
-	{
-	 .device_id = 0x2410,
-	 .name = "pci-6733",
-	 .n_adchan = 0,		/* no analog input */
-	 .n_aochan = 8,
-	 .aobits = 16,
-	 .ao_unipolar = 0,
-	 .ao_fifo_depth = 16384,
-	 .ao_range_table = &range_bipolar10,
-	 .ao_speed = 1000,
-	 .num_p0_dio_channels = 8,
-	 .reg_type = ni_reg_6713,
-	 .caldac = {ad8804_debug, ad8804_debug},
-	 },
-	{
-	 .device_id = 0x2420,
-	 .name = "pxi-6733",
-	 .n_adchan = 0,		/* no analog input */
-	 .n_aochan = 8,
-	 .aobits = 16,
-	 .ao_unipolar = 0,
-	 .ao_fifo_depth = 16384,
-	 .ao_range_table = &range_bipolar10,
-	 .ao_speed = 1000,
-	 .num_p0_dio_channels = 8,
-	 .reg_type = ni_reg_6713,
-	 .caldac = {ad8804_debug, ad8804_debug},
-	 },
-	{
-	 .device_id = 0x15b0,
-	 .name = "pxi-6071e",
-	 .n_adchan = 64,
-	 .adbits = 12,
-	 .ai_fifo_depth = 512,
-	 .alwaysdither = 1,
-	 .gainlkup = ai_gain_16,
-	 .ai_speed = 800,
-	 .n_aochan = 2,
-	 .aobits = 12,
-	 .ao_fifo_depth = 2048,
-	 .ao_range_table = &range_ni_E_ao_ext,
-	 .ao_unipolar = 1,
-	 .ao_speed = 1000,
-	 .num_p0_dio_channels = 8,
-	 .caldac = {ad8804_debug},
-	 .has_8255 = 0,
-	 },
-	{
-	 .device_id = 0x11b0,
-	 .name = "pxi-6070e",
-	 .n_adchan = 16,
-	 .adbits = 12,
-	 .ai_fifo_depth = 512,
-	 .alwaysdither = 1,
-	 .gainlkup = ai_gain_16,
-	 .ai_speed = 800,
-	 .n_aochan = 2,
-	 .aobits = 12,
-	 .ao_fifo_depth = 2048,
-	 .ao_range_table = &range_ni_E_ao_ext,
-	 .ao_unipolar = 1,
-	 .ao_speed = 1000,
-	 .num_p0_dio_channels = 8,
-	 .caldac = {ad8804_debug},
-	 .has_8255 = 0,
-	 },
-	{
-	 .device_id = 0x18c0,
-	 .name = "pxi-6052e",
-	 .n_adchan = 16,
-	 .adbits = 16,
-	 .ai_fifo_depth = 512,
-	 .alwaysdither = 1,
-	 .gainlkup = ai_gain_16,
-	 .ai_speed = 3000,
-	 .n_aochan = 2,
-	 .aobits = 16,
-	 .ao_unipolar = 1,
-	 .ao_fifo_depth = 2048,
-	 .ao_range_table = &range_ni_E_ao_ext,
-	 .ao_speed = 3000,
-	 .num_p0_dio_channels = 8,
-	 .caldac = {mb88341, mb88341, ad8522},
-	 },
-	{
-	 .device_id = 0x1580,
-	 .name = "pxi-6031e",
-	 .n_adchan = 64,
-	 .adbits = 16,
-	 .ai_fifo_depth = 512,
-	 .alwaysdither = 1,
-	 .gainlkup = ai_gain_14,
-	 .ai_speed = 10000,
-	 .n_aochan = 2,
-	 .aobits = 16,
-	 .ao_fifo_depth = 2048,
-	 .ao_range_table = &range_ni_E_ao_ext,
-	 .ao_unipolar = 1,
-	 .ao_speed = 10000,
-	 .num_p0_dio_channels = 8,
-	 .caldac = {dac8800, dac8043, ad8522},
-	 },
-	{
-	 .device_id = 0x2890,
-	 .name = "pci-6036e",
-	 .n_adchan = 16,
-	 .adbits = 16,
-	 .ai_fifo_depth = 512,
-	 .alwaysdither = 1,
-	 .gainlkup = ai_gain_4,
-	 .ai_speed = 5000,
-	 .n_aochan = 2,
-	 .aobits = 16,
-	 .ao_fifo_depth = 0,
-	 .ao_range_table = &range_bipolar10,
-	 .ao_unipolar = 0,
-	 .ao_speed = 100000,
-	 .num_p0_dio_channels = 8,
-	 .caldac = {ad8804_debug},
-	 .has_8255 = 0,
-	 },
-	{
-	 .device_id = 0x70b0,
-	 .name = "pci-6220",
-	 .n_adchan = 16,
-	 .adbits = 16,
-	 .ai_fifo_depth = 512,
-	 /*      .FIXME = guess */
-	 .gainlkup = ai_gain_622x,
-	 .ai_speed = 4000,
-	 .n_aochan = 0,
-	 .aobits = 0,
-	 .ao_fifo_depth = 0,
-	 .num_p0_dio_channels = 8,
-	 .reg_type = ni_reg_622x,
-	 .ao_unipolar = 0,
-	 .caldac = {caldac_none},
-	 .has_8255 = 0,
-	 },
-	{
-	 .device_id = 0x70af,
-	 .name = "pci-6221",
-	 .n_adchan = 16,
-	 .adbits = 16,
-	 .ai_fifo_depth = 4095,
-	 .gainlkup = ai_gain_622x,
-	 .ai_speed = 4000,
-	 .n_aochan = 2,
-	 .aobits = 16,
-	 .ao_fifo_depth = 8191,
-	 .ao_range_table = &range_ni_M_622x_ao,
-	 .reg_type = ni_reg_622x,
-	 .ao_unipolar = 0,
-	 .ao_speed = 1200,
-	 .num_p0_dio_channels = 8,
-	 .caldac = {caldac_none},
-	 .has_8255 = 0,
-	 },
-	{
-	 .device_id = 0x71bc,
-	 .name = "pci-6221_37pin",
-	 .n_adchan = 16,
-	 .adbits = 16,
-	 .ai_fifo_depth = 4095,
-	 .gainlkup = ai_gain_622x,
-	 .ai_speed = 4000,
-	 .n_aochan = 2,
-	 .aobits = 16,
-	 .ao_fifo_depth = 8191,
-	 .ao_range_table = &range_ni_M_622x_ao,
-	 .reg_type = ni_reg_622x,
-	 .ao_unipolar = 0,
-	 .ao_speed = 1200,
-	 .num_p0_dio_channels = 8,
-	 .caldac = {caldac_none},
-	 .has_8255 = 0,
-	 },
-	{
-	 .device_id = 0x70f2,
-	 .name = "pci-6224",
-	 .n_adchan = 32,
-	 .adbits = 16,
-	 .ai_fifo_depth = 4095,
-	 .gainlkup = ai_gain_622x,
-	 .ai_speed = 4000,
-	 .n_aochan = 0,
-	 .aobits = 0,
-	 .ao_fifo_depth = 0,
-	 .reg_type = ni_reg_622x,
-	 .ao_unipolar = 0,
-	 .num_p0_dio_channels = 32,
-	 .caldac = {caldac_none},
-	 .has_8255 = 0,
-	 },
-	{
-	 .device_id = 0x70f3,
-	 .name = "pxi-6224",
-	 .n_adchan = 32,
-	 .adbits = 16,
-	 .ai_fifo_depth = 4095,
-	 .gainlkup = ai_gain_622x,
-	 .ai_speed = 4000,
-	 .n_aochan = 0,
-	 .aobits = 0,
-	 .ao_fifo_depth = 0,
-	 .reg_type = ni_reg_622x,
-	 .ao_unipolar = 0,
-	 .num_p0_dio_channels = 32,
-	 .caldac = {caldac_none},
-	 .has_8255 = 0,
-	 },
-	{
-	 .device_id = 0x716c,
-	 .name = "pci-6225",
-	 .n_adchan = 80,
-	 .adbits = 16,
-	 .ai_fifo_depth = 4095,
-	 .gainlkup = ai_gain_622x,
-	 .ai_speed = 4000,
-	 .n_aochan = 2,
-	 .aobits = 16,
-	 .ao_fifo_depth = 8191,
-	 .ao_range_table = &range_ni_M_622x_ao,
-	 .reg_type = ni_reg_622x,
-	 .ao_unipolar = 0,
-	 .ao_speed = 1200,
-	 .num_p0_dio_channels = 32,
-	 .caldac = {caldac_none},
-	 .has_8255 = 0,
-	 },
-	{
-	 .device_id = 0x716d,
-	 .name = "pxi-6225",
-	 .n_adchan = 80,
-	 .adbits = 16,
-	 .ai_fifo_depth = 4095,
-	 .gainlkup = ai_gain_622x,
-	 .ai_speed = 4000,
-	 .n_aochan = 2,
-	 .aobits = 16,
-	 .ao_fifo_depth = 8191,
-	 .ao_range_table = &range_ni_M_622x_ao,
-	 .reg_type = ni_reg_622x,
-	 .ao_unipolar = 0,
-	 .ao_speed = 1200,
-	 .num_p0_dio_channels = 32,
-	 .caldac = {caldac_none},
-	 .has_8255 = 0,
+	[BOARD_PCI6733] = {
+		.name		= "pci-6733",
+		.n_aochan	= 8,
+		.aobits		= 16,
+		.ao_fifo_depth	= 16384,
+		.ao_range_table	= &range_bipolar10,
+		.ao_speed	= 1000,
+		.num_p0_dio_channels = 8,
+		.reg_type	= ni_reg_6713,
+		.caldac		= { ad8804_debug, ad8804_debug },
+	},
+	[BOARD_PXI6733] = {
+		.name		= "pxi-6733",
+		.n_aochan	= 8,
+		.aobits		= 16,
+		.ao_fifo_depth	= 16384,
+		.ao_range_table	= &range_bipolar10,
+		.ao_speed	= 1000,
+		.num_p0_dio_channels = 8,
+		.reg_type	= ni_reg_6713,
+		.caldac		= { ad8804_debug, ad8804_debug },
+	},
+	[BOARD_PXI6071E] = {
+		.name		= "pxi-6071e",
+		.n_adchan	= 64,
+		.adbits		= 12,
+		.ai_fifo_depth	= 512,
+		.alwaysdither	= 1,
+		.gainlkup	= ai_gain_16,
+		.ai_speed	= 800,
+		.n_aochan	= 2,
+		.aobits		= 12,
+		.ao_fifo_depth	= 2048,
+		.ao_range_table	= &range_ni_E_ao_ext,
+		.ao_unipolar	= 1,
+		.ao_speed	= 1000,
+		.num_p0_dio_channels = 8,
+		.caldac		= { ad8804_debug },
+	},
+	[BOARD_PXI6070E] = {
+		.name		= "pxi-6070e",
+		.n_adchan	= 16,
+		.adbits		= 12,
+		.ai_fifo_depth	= 512,
+		.alwaysdither	= 1,
+		.gainlkup	= ai_gain_16,
+		.ai_speed	= 800,
+		.n_aochan	= 2,
+		.aobits		= 12,
+		.ao_fifo_depth	= 2048,
+		.ao_range_table	= &range_ni_E_ao_ext,
+		.ao_unipolar	= 1,
+		.ao_speed	= 1000,
+		.num_p0_dio_channels = 8,
+		.caldac		= { ad8804_debug },
+	},
+	[BOARD_PXI6052E] = {
+		.name		= "pxi-6052e",
+		.n_adchan	= 16,
+		.adbits		= 16,
+		.ai_fifo_depth	= 512,
+		.alwaysdither	= 1,
+		.gainlkup	= ai_gain_16,
+		.ai_speed	= 3000,
+		.n_aochan	= 2,
+		.aobits		= 16,
+		.ao_unipolar	= 1,
+		.ao_fifo_depth	= 2048,
+		.ao_range_table	= &range_ni_E_ao_ext,
+		.ao_speed	= 3000,
+		.num_p0_dio_channels = 8,
+		.caldac		= { mb88341, mb88341, ad8522 },
+	},
+	[BOARD_PXI6031E] = {
+		.name		= "pxi-6031e",
+		.n_adchan	= 64,
+		.adbits		= 16,
+		.ai_fifo_depth	= 512,
+		.alwaysdither	= 1,
+		.gainlkup	= ai_gain_14,
+		.ai_speed	= 10000,
+		.n_aochan	= 2,
+		.aobits		= 16,
+		.ao_fifo_depth	= 2048,
+		.ao_range_table	= &range_ni_E_ao_ext,
+		.ao_unipolar	= 1,
+		.ao_speed	= 10000,
+		.num_p0_dio_channels = 8,
+		.caldac		= { dac8800, dac8043, ad8522 },
+	},
+	[BOARD_PCI6036E] = {
+		.name = "pci-6036e",
+		.n_adchan	= 16,
+		.adbits		= 16,
+		.ai_fifo_depth	= 512,
+		.alwaysdither	= 1,
+		.gainlkup	= ai_gain_4,
+		.ai_speed	= 5000,
+		.n_aochan	= 2,
+		.aobits		= 16,
+		.ao_range_table	= &range_bipolar10,
+		.ao_speed	= 100000,
+		.num_p0_dio_channels = 8,
+		.caldac		= { ad8804_debug },
+	},
+	[BOARD_PCI6220] = {
+		.name		= "pci-6220",
+		.n_adchan	= 16,
+		.adbits		= 16,
+		.ai_fifo_depth	= 512,		/* FIXME: guess */
+		.gainlkup	= ai_gain_622x,
+		.ai_speed	= 4000,
+		.num_p0_dio_channels = 8,
+		.reg_type	= ni_reg_622x,
+		.caldac		= { caldac_none },
+	},
+	[BOARD_PCI6221] = {
+		.name		= "pci-6221",
+		.n_adchan	= 16,
+		.adbits		= 16,
+		.ai_fifo_depth	= 4095,
+		.gainlkup	= ai_gain_622x,
+		.ai_speed	= 4000,
+		.n_aochan	= 2,
+		.aobits		= 16,
+		.ao_fifo_depth	= 8191,
+		.ao_range_table	= &range_ni_M_622x_ao,
+		.reg_type	= ni_reg_622x,
+		.ao_speed	= 1200,
+		.num_p0_dio_channels = 8,
+		.caldac		= { caldac_none },
+	},
+	[BOARD_PCI6221_37PIN] = {
+		.name		= "pci-6221_37pin",
+		.n_adchan	= 16,
+		.adbits		= 16,
+		.ai_fifo_depth	= 4095,
+		.gainlkup	= ai_gain_622x,
+		.ai_speed	= 4000,
+		.n_aochan	= 2,
+		.aobits		= 16,
+		.ao_fifo_depth	= 8191,
+		.ao_range_table	= &range_ni_M_622x_ao,
+		.reg_type	= ni_reg_622x,
+		.ao_speed	= 1200,
+		.num_p0_dio_channels = 8,
+		.caldac		= { caldac_none },
+	},
+	[BOARD_PCI6224] = {
+		.name		= "pci-6224",
+		.n_adchan	= 32,
+		.adbits		= 16,
+		.ai_fifo_depth	= 4095,
+		.gainlkup	= ai_gain_622x,
+		.ai_speed	= 4000,
+		.reg_type	= ni_reg_622x,
+		.num_p0_dio_channels = 32,
+		.caldac		= { caldac_none },
+	},
+	[BOARD_PXI6224] = {
+		.name		= "pxi-6224",
+		.n_adchan	= 32,
+		.adbits		= 16,
+		.ai_fifo_depth	= 4095,
+		.gainlkup	= ai_gain_622x,
+		.ai_speed	= 4000,
+		.reg_type	= ni_reg_622x,
+		.num_p0_dio_channels = 32,
+		.caldac		= { caldac_none },
+	},
+	[BOARD_PCI6225] = {
+		.name		= "pci-6225",
+		.n_adchan	= 80,
+		.adbits		= 16,
+		.ai_fifo_depth	= 4095,
+		.gainlkup	= ai_gain_622x,
+		.ai_speed	= 4000,
+		.n_aochan	= 2,
+		.aobits		= 16,
+		.ao_fifo_depth	= 8191,
+		.ao_range_table	= &range_ni_M_622x_ao,
+		.reg_type	= ni_reg_622x,
+		.ao_speed	= 1200,
+		.num_p0_dio_channels = 32,
+		.caldac		= { caldac_none },
+	},
+	[BOARD_PXI6225] = {
+		.name		= "pxi-6225",
+		.n_adchan	= 80,
+		.adbits		= 16,
+		.ai_fifo_depth	= 4095,
+		.gainlkup	= ai_gain_622x,
+		.ai_speed	= 4000,
+		.n_aochan	= 2,
+		.aobits		= 16,
+		.ao_fifo_depth	= 8191,
+		.ao_range_table	= &range_ni_M_622x_ao,
+		.reg_type	= ni_reg_622x,
+		.ao_speed	= 1200,
+		.num_p0_dio_channels = 32,
+		.caldac		= { caldac_none },
+	},
+	[BOARD_PCI6229] = {
+		.name		= "pci-6229",
+		.n_adchan	= 32,
+		.adbits		= 16,
+		.ai_fifo_depth	= 4095,
+		.gainlkup	= ai_gain_622x,
+		.ai_speed	= 4000,
+		.n_aochan	= 4,
+		.aobits		= 16,
+		.ao_fifo_depth	= 8191,
+		.ao_range_table	= &range_ni_M_622x_ao,
+		.reg_type	= ni_reg_622x,
+		.ao_speed	= 1200,
+		.num_p0_dio_channels = 32,
+		.caldac		= { caldac_none },
+	},
+	[BOARD_PCI6250] = {
+		.name		= "pci-6250",
+		.n_adchan	= 16,
+		.adbits		= 16,
+		.ai_fifo_depth	= 4095,
+		.gainlkup	= ai_gain_628x,
+		.ai_speed	= 800,
+		.reg_type	= ni_reg_625x,
+		.num_p0_dio_channels = 8,
+		.caldac		= { caldac_none },
+	},
+	[BOARD_PCI6251] = {
+		.name		= "pci-6251",
+		.n_adchan	= 16,
+		.adbits		= 16,
+		.ai_fifo_depth	= 4095,
+		.gainlkup	= ai_gain_628x,
+		.ai_speed	= 800,
+		.n_aochan	= 2,
+		.aobits		= 16,
+		.ao_fifo_depth	= 8191,
+		.ao_range_table	= &range_ni_M_625x_ao,
+		.reg_type	= ni_reg_625x,
+		.ao_speed	= 350,
+		.num_p0_dio_channels = 8,
+		.caldac		= { caldac_none },
+	},
+	[BOARD_PCIE6251] = {
+		.name		= "pcie-6251",
+		.n_adchan	= 16,
+		.adbits		= 16,
+		.ai_fifo_depth	= 4095,
+		.gainlkup	= ai_gain_628x,
+		.ai_speed	= 800,
+		.n_aochan	= 2,
+		.aobits		= 16,
+		.ao_fifo_depth	= 8191,
+		.ao_range_table	= &range_ni_M_625x_ao,
+		.reg_type	= ni_reg_625x,
+		.ao_speed	= 350,
+		.num_p0_dio_channels = 8,
+		.caldac		= { caldac_none },
+	},
+	[BOARD_PXIE6251] = {
+		.name		= "pxie-6251",
+		.n_adchan	= 16,
+		.adbits		= 16,
+		.ai_fifo_depth	= 4095,
+		.gainlkup	= ai_gain_628x,
+		.ai_speed	= 800,
+		.n_aochan	= 2,
+		.aobits		= 16,
+		.ao_fifo_depth	= 8191,
+		.ao_range_table	= &range_ni_M_625x_ao,
+		.reg_type	= ni_reg_625x,
+		.ao_speed	= 350,
+		.num_p0_dio_channels = 8,
+		.caldac		= { caldac_none },
+	},
+	[BOARD_PCI6254] = {
+		.name		= "pci-6254",
+		.n_adchan	= 32,
+		.adbits		= 16,
+		.ai_fifo_depth	= 4095,
+		.gainlkup	= ai_gain_628x,
+		.ai_speed	= 800,
+		.reg_type	= ni_reg_625x,
+		.num_p0_dio_channels = 32,
+		.caldac		= { caldac_none },
+	},
+	[BOARD_PCI6259] = {
+		.name		= "pci-6259",
+		.n_adchan	= 32,
+		.adbits		= 16,
+		.ai_fifo_depth	= 4095,
+		.gainlkup	= ai_gain_628x,
+		.ai_speed	= 800,
+		.n_aochan	= 4,
+		.aobits		= 16,
+		.ao_fifo_depth	= 8191,
+		.ao_range_table	= &range_ni_M_625x_ao,
+		.reg_type	= ni_reg_625x,
+		.ao_speed	= 350,
+		.num_p0_dio_channels = 32,
+		.caldac		= { caldac_none },
+	},
+	[BOARD_PCIE6259] = {
+		.name		= "pcie-6259",
+		.n_adchan	= 32,
+		.adbits		= 16,
+		.ai_fifo_depth	= 4095,
+		.gainlkup	= ai_gain_628x,
+		.ai_speed	= 800,
+		.n_aochan	= 4,
+		.aobits		= 16,
+		.ao_fifo_depth	= 8191,
+		.ao_range_table	= &range_ni_M_625x_ao,
+		.reg_type	= ni_reg_625x,
+		.ao_speed	= 350,
+		.num_p0_dio_channels = 32,
+		.caldac		= { caldac_none },
+	},
+	[BOARD_PCI6280] = {
+		.name		= "pci-6280",
+		.n_adchan	= 16,
+		.adbits		= 18,
+		.ai_fifo_depth	= 2047,
+		.gainlkup	= ai_gain_628x,
+		.ai_speed	= 1600,
+		.ao_fifo_depth	= 8191,
+		.reg_type	= ni_reg_628x,
+		.num_p0_dio_channels = 8,
+		.caldac		= { caldac_none },
+	},
+	[BOARD_PCI6281] = {
+		.name		= "pci-6281",
+		.n_adchan	= 16,
+		.adbits		= 18,
+		.ai_fifo_depth	= 2047,
+		.gainlkup	= ai_gain_628x,
+		.ai_speed	= 1600,
+		.n_aochan	= 2,
+		.aobits		= 16,
+		.ao_fifo_depth	= 8191,
+		.ao_range_table = &range_ni_M_628x_ao,
+		.reg_type	= ni_reg_628x,
+		.ao_unipolar	= 1,
+		.ao_speed	= 350,
+		.num_p0_dio_channels = 8,
+		.caldac		= { caldac_none },
+	},
+	[BOARD_PXI6281] = {
+		.name		= "pxi-6281",
+		.n_adchan	= 16,
+		.adbits		= 18,
+		.ai_fifo_depth	= 2047,
+		.gainlkup	= ai_gain_628x,
+		.ai_speed	= 1600,
+		.n_aochan	= 2,
+		.aobits		= 16,
+		.ao_fifo_depth	= 8191,
+		.ao_range_table	= &range_ni_M_628x_ao,
+		.reg_type	= ni_reg_628x,
+		.ao_unipolar	= 1,
+		.ao_speed	= 350,
+		.num_p0_dio_channels = 8,
+		.caldac		= { caldac_none },
+	},
+	[BOARD_PCI6284] = {
+		.name		= "pci-6284",
+		.n_adchan	= 32,
+		.adbits		= 18,
+		.ai_fifo_depth	= 2047,
+		.gainlkup	= ai_gain_628x,
+		.ai_speed	= 1600,
+		.reg_type	= ni_reg_628x,
+		.num_p0_dio_channels = 32,
+		.caldac		= { caldac_none },
+	},
+	[BOARD_PCI6289] = {
+		.name		= "pci-6289",
+		.n_adchan	= 32,
+		.adbits		= 18,
+		.ai_fifo_depth	= 2047,
+		.gainlkup	= ai_gain_628x,
+		.ai_speed	= 1600,
+		.n_aochan	= 4,
+		.aobits		= 16,
+		.ao_fifo_depth	= 8191,
+		.ao_range_table	= &range_ni_M_628x_ao,
+		.reg_type	= ni_reg_628x,
+		.ao_unipolar	= 1,
+		.ao_speed	= 350,
+		.num_p0_dio_channels = 32,
+		.caldac		= { caldac_none },
+	},
+	[BOARD_PCI6143] = {
+		.name		= "pci-6143",
+		.n_adchan	= 8,
+		.adbits		= 16,
+		.ai_fifo_depth	= 1024,
+		.gainlkup	= ai_gain_6143,
+		.ai_speed	= 4000,
+		.reg_type	= ni_reg_6143,
+		.num_p0_dio_channels = 8,
+		.caldac		= { ad8804_debug, ad8804_debug },
+	},
+	[BOARD_PXI6143] = {
+		.name		= "pxi-6143",
+		.n_adchan	= 8,
+		.adbits		= 16,
+		.ai_fifo_depth	= 1024,
+		.gainlkup	= ai_gain_6143,
+		.ai_speed	= 4000,
+		.reg_type	= ni_reg_6143,
+		.num_p0_dio_channels = 8,
+		.caldac		= { ad8804_debug, ad8804_debug },
 	},
-	{
-	 .device_id = 0x70aa,
-	 .name = "pci-6229",
-	 .n_adchan = 32,
-	 .adbits = 16,
-	 .ai_fifo_depth = 4095,
-	 .gainlkup = ai_gain_622x,
-	 .ai_speed = 4000,
-	 .n_aochan = 4,
-	 .aobits = 16,
-	 .ao_fifo_depth = 8191,
-	 .ao_range_table = &range_ni_M_622x_ao,
-	 .reg_type = ni_reg_622x,
-	 .ao_unipolar = 0,
-	 .ao_speed = 1200,
-	 .num_p0_dio_channels = 32,
-	 .caldac = {caldac_none},
-	 .has_8255 = 0,
-	 },
-	{
-	 .device_id = 0x70b4,
-	 .name = "pci-6250",
-	 .n_adchan = 16,
-	 .adbits = 16,
-	 .ai_fifo_depth = 4095,
-	 .gainlkup = ai_gain_628x,
-	 .ai_speed = 800,
-	 .n_aochan = 0,
-	 .aobits = 0,
-	 .ao_fifo_depth = 0,
-	 .reg_type = ni_reg_625x,
-	 .ao_unipolar = 0,
-	 .num_p0_dio_channels = 8,
-	 .caldac = {caldac_none},
-	 .has_8255 = 0,
-	 },
-	{
-	 .device_id = 0x70b8,
-	 .name = "pci-6251",
-	 .n_adchan = 16,
-	 .adbits = 16,
-	 .ai_fifo_depth = 4095,
-	 .gainlkup = ai_gain_628x,
-	 .ai_speed = 800,
-	 .n_aochan = 2,
-	 .aobits = 16,
-	 .ao_fifo_depth = 8191,
-	 .ao_range_table = &range_ni_M_625x_ao,
-	 .reg_type = ni_reg_625x,
-	 .ao_unipolar = 0,
-	 .ao_speed = 350,
-	 .num_p0_dio_channels = 8,
-	 .caldac = {caldac_none},
-	 .has_8255 = 0,
-	 },
-	{
-	 .device_id = 0x717d,
-	 .name = "pcie-6251",
-	 .n_adchan = 16,
-	 .adbits = 16,
-	 .ai_fifo_depth = 4095,
-	 .gainlkup = ai_gain_628x,
-	 .ai_speed = 800,
-	 .n_aochan = 2,
-	 .aobits = 16,
-	 .ao_fifo_depth = 8191,
-	 .ao_range_table = &range_ni_M_625x_ao,
-	 .reg_type = ni_reg_625x,
-	 .ao_unipolar = 0,
-	 .ao_speed = 350,
-	 .num_p0_dio_channels = 8,
-	 .caldac = {caldac_none},
-	 .has_8255 = 0,
-	 },
-	{
-	 .device_id = 0x72e8,
-	 .name = "pxie-6251",
-	 .n_adchan = 16,
-	 .adbits = 16,
-	 .ai_fifo_depth = 4095,
-	 .gainlkup = ai_gain_628x,
-	 .ai_speed = 800,
-	 .n_aochan = 2,
-	 .aobits = 16,
-	 .ao_fifo_depth = 8191,
-	 .ao_range_table = &range_ni_M_625x_ao,
-	 .reg_type = ni_reg_625x,
-	 .ao_unipolar = 0,
-	 .ao_speed = 350,
-	 .num_p0_dio_channels = 8,
-	 .caldac = {caldac_none},
-	 .has_8255 = 0,
-	 },
-	{
-	 .device_id = 0x70b7,
-	 .name = "pci-6254",
-	 .n_adchan = 32,
-	 .adbits = 16,
-	 .ai_fifo_depth = 4095,
-	 .gainlkup = ai_gain_628x,
-	 .ai_speed = 800,
-	 .n_aochan = 0,
-	 .aobits = 0,
-	 .ao_fifo_depth = 0,
-	 .reg_type = ni_reg_625x,
-	 .ao_unipolar = 0,
-	 .num_p0_dio_channels = 32,
-	 .caldac = {caldac_none},
-	 .has_8255 = 0,
-	 },
-	{
-	 .device_id = 0x70ab,
-	 .name = "pci-6259",
-	 .n_adchan = 32,
-	 .adbits = 16,
-	 .ai_fifo_depth = 4095,
-	 .gainlkup = ai_gain_628x,
-	 .ai_speed = 800,
-	 .n_aochan = 4,
-	 .aobits = 16,
-	 .ao_fifo_depth = 8191,
-	 .ao_range_table = &range_ni_M_625x_ao,
-	 .reg_type = ni_reg_625x,
-	 .ao_unipolar = 0,
-	 .ao_speed = 350,
-	 .num_p0_dio_channels = 32,
-	 .caldac = {caldac_none},
-	 .has_8255 = 0,
-	 },
-	{
-	 .device_id = 0x717f,
-	 .name = "pcie-6259",
-	 .n_adchan = 32,
-	 .adbits = 16,
-	 .ai_fifo_depth = 4095,
-	 .gainlkup = ai_gain_628x,
-	 .ai_speed = 800,
-	 .n_aochan = 4,
-	 .aobits = 16,
-	 .ao_fifo_depth = 8191,
-	 .ao_range_table = &range_ni_M_625x_ao,
-	 .reg_type = ni_reg_625x,
-	 .ao_unipolar = 0,
-	 .ao_speed = 350,
-	 .num_p0_dio_channels = 32,
-	 .caldac = {caldac_none},
-	 .has_8255 = 0,
-	 },
-	{
-	 .device_id = 0x70b6,
-	 .name = "pci-6280",
-	 .n_adchan = 16,
-	 .adbits = 18,
-	 .ai_fifo_depth = 2047,
-	 .gainlkup = ai_gain_628x,
-	 .ai_speed = 1600,
-	 .n_aochan = 0,
-	 .aobits = 0,
-	 .ao_fifo_depth = 8191,
-	 .reg_type = ni_reg_628x,
-	 .ao_unipolar = 0,
-	 .num_p0_dio_channels = 8,
-	 .caldac = {caldac_none},
-	 .has_8255 = 0,
-	 },
-	{
-	 .device_id = 0x70bd,
-	 .name = "pci-6281",
-	 .n_adchan = 16,
-	 .adbits = 18,
-	 .ai_fifo_depth = 2047,
-	 .gainlkup = ai_gain_628x,
-	 .ai_speed = 1600,
-	 .n_aochan = 2,
-	 .aobits = 16,
-	 .ao_fifo_depth = 8191,
-	 .ao_range_table = &range_ni_M_628x_ao,
-	 .reg_type = ni_reg_628x,
-	 .ao_unipolar = 1,
-	 .ao_speed = 350,
-	 .num_p0_dio_channels = 8,
-	 .caldac = {caldac_none},
-	 .has_8255 = 0,
-	 },
-	{
-	 .device_id = 0x70bf,
-	 .name = "pxi-6281",
-	 .n_adchan = 16,
-	 .adbits = 18,
-	 .ai_fifo_depth = 2047,
-	 .gainlkup = ai_gain_628x,
-	 .ai_speed = 1600,
-	 .n_aochan = 2,
-	 .aobits = 16,
-	 .ao_fifo_depth = 8191,
-	 .ao_range_table = &range_ni_M_628x_ao,
-	 .reg_type = ni_reg_628x,
-	 .ao_unipolar = 1,
-	 .ao_speed = 350,
-	 .num_p0_dio_channels = 8,
-	 .caldac = {caldac_none},
-	 .has_8255 = 0,
-	 },
-	{
-	 .device_id = 0x70bc,
-	 .name = "pci-6284",
-	 .n_adchan = 32,
-	 .adbits = 18,
-	 .ai_fifo_depth = 2047,
-	 .gainlkup = ai_gain_628x,
-	 .ai_speed = 1600,
-	 .n_aochan = 0,
-	 .aobits = 0,
-	 .ao_fifo_depth = 0,
-	 .reg_type = ni_reg_628x,
-	 .ao_unipolar = 0,
-	 .num_p0_dio_channels = 32,
-	 .caldac = {caldac_none},
-	 .has_8255 = 0,
-	 },
-	{
-	 .device_id = 0x70ac,
-	 .name = "pci-6289",
-	 .n_adchan = 32,
-	 .adbits = 18,
-	 .ai_fifo_depth = 2047,
-	 .gainlkup = ai_gain_628x,
-	 .ai_speed = 1600,
-	 .n_aochan = 4,
-	 .aobits = 16,
-	 .ao_fifo_depth = 8191,
-	 .ao_range_table = &range_ni_M_628x_ao,
-	 .reg_type = ni_reg_628x,
-	 .ao_unipolar = 1,
-	 .ao_speed = 350,
-	 .num_p0_dio_channels = 32,
-	 .caldac = {caldac_none},
-	 .has_8255 = 0,
-	 },
-	{
-	 .device_id = 0x70C0,
-	 .name = "pci-6143",
-	 .n_adchan = 8,
-	 .adbits = 16,
-	 .ai_fifo_depth = 1024,
-	 .alwaysdither = 0,
-	 .gainlkup = ai_gain_6143,
-	 .ai_speed = 4000,
-	 .n_aochan = 0,
-	 .aobits = 0,
-	 .reg_type = ni_reg_6143,
-	 .ao_unipolar = 0,
-	 .ao_fifo_depth = 0,
-	 .num_p0_dio_channels = 8,
-	 .caldac = {ad8804_debug, ad8804_debug},
-	 },
-	{
-	 .device_id = 0x710D,
-	 .name = "pxi-6143",
-	 .n_adchan = 8,
-	 .adbits = 16,
-	 .ai_fifo_depth = 1024,
-	 .alwaysdither = 0,
-	 .gainlkup = ai_gain_6143,
-	 .ai_speed = 4000,
-	 .n_aochan = 0,
-	 .aobits = 0,
-	 .reg_type = ni_reg_6143,
-	 .ao_unipolar = 0,
-	 .ao_fifo_depth = 0,
-	 .num_p0_dio_channels = 8,
-	 .caldac = {ad8804_debug, ad8804_debug},
-	 },
 };
 
 struct ni_private {
@@ -1569,6 +1431,7 @@ static void m_series_init_eeprom_buffer(struct comedi_device *dev)
 
 static void init_6143(struct comedi_device *dev)
 {
+	const struct ni_board_struct *board = comedi_board(dev);
 	struct ni_private *devpriv = dev->private;
 
 	/*  Disable interrupts */
@@ -1579,7 +1442,8 @@ static void init_6143(struct comedi_device *dev)
 	ni_writeb(0x80, PipelineDelay_6143);	/*  Set EOCMode, ADCMode and pipelinedelay */
 	ni_writeb(0x00, EOC_Set_6143);	/*  Set EOC Delay */
 
-	ni_writel(boardtype.ai_fifo_depth / 2, AIFIFO_Flag_6143);	/*  Set the FIFO half full level */
+	/* Set the FIFO half full level */
+	ni_writel(board->ai_fifo_depth / 2, AIFIFO_Flag_6143);
 
 	/*  Strobe Relay disable bit */
 	devpriv->ai_calib_source_enabled = 0;
@@ -1606,48 +1470,38 @@ static void pcimio_detach(struct comedi_device *dev)
 			mite_free(devpriv->mite);
 		}
 	}
-}
-
-static const struct ni_board_struct *
-pcimio_find_boardinfo(struct pci_dev *pcidev)
-{
-	unsigned int device_id = pcidev->device;
-	unsigned int n;
-
-	for (n = 0; n < ARRAY_SIZE(ni_boards); n++) {
-		const struct ni_board_struct *board = &ni_boards[n];
-		if (board->device_id == device_id)
-			return board;
-	}
-	return NULL;
+	comedi_pci_disable(dev);
 }
 
 static int pcimio_auto_attach(struct comedi_device *dev,
-					unsigned long context_unused)
+			      unsigned long context)
 {
 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+	const struct ni_board_struct *board = NULL;
 	struct ni_private *devpriv;
 	int ret;
 
-	dev_info(dev->class_dev, "ni_pcimio: attach %s\n", pci_name(pcidev));
+	if (context < ARRAY_SIZE(ni_boards))
+		board = &ni_boards[context];
+	if (!board)
+		return -ENODEV;
+	dev->board_ptr = board;
+	dev->board_name = board->name;
+
+	ret = comedi_pci_enable(dev);
+	if (ret)
+		return ret;
 
 	ret = ni_alloc_private(dev);
 	if (ret)
 		return ret;
 	devpriv = dev->private;
 
-	dev->board_ptr = pcimio_find_boardinfo(pcidev);
-	if (!dev->board_ptr)
-		return -ENODEV;
-
 	devpriv->mite = mite_alloc(pcidev);
 	if (!devpriv->mite)
 		return -ENOMEM;
 
-	dev_dbg(dev->class_dev, "%s\n", boardtype.name);
-	dev->board_name = boardtype.name;
-
-	if (boardtype.reg_type & ni_reg_m_series_mask) {
+	if (board->reg_type & ni_reg_m_series_mask) {
 		devpriv->stc_writew = &m_series_stc_writew;
 		devpriv->stc_readw = &m_series_stc_readw;
 		devpriv->stc_writel = &m_series_stc_writel;
@@ -1681,9 +1535,9 @@ static int pcimio_auto_attach(struct comedi_device *dev,
 	if (devpriv->gpct_mite_ring[1] == NULL)
 		return -ENOMEM;
 
-	if (boardtype.reg_type & ni_reg_m_series_mask)
+	if (board->reg_type & ni_reg_m_series_mask)
 		m_series_init_eeprom_buffer(dev);
-	if (boardtype.reg_type == ni_reg_6143)
+	if (board->reg_type == ni_reg_6143)
 		init_6143(dev);
 
 	dev->irq = mite_irq(devpriv->mite);
@@ -1788,65 +1642,66 @@ static struct comedi_driver ni_pcimio_driver = {
 };
 
 static int ni_pcimio_pci_probe(struct pci_dev *dev,
-					 const struct pci_device_id *ent)
+			       const struct pci_device_id *id)
 {
-	return comedi_pci_auto_config(dev, &ni_pcimio_driver);
+	return comedi_pci_auto_config(dev, &ni_pcimio_driver, id->driver_data);
 }
 
 static DEFINE_PCI_DEVICE_TABLE(ni_pcimio_pci_table) = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x0162) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1170) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1180) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1190) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x11b0) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x11c0) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x11d0) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1270) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1330) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1340) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1350) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x14e0) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x14f0) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1580) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x15b0) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1880) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1870) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x18b0) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x18c0) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2410) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2420) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2430) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2890) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x28c0) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2a60) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2a70) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2a80) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2ab0) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2b80) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2b90) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2c80) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2ca0) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70aa) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70ab) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70ac) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70af) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70b0) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70b4) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70b6) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70b7) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70b8) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70bc) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70bd) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70bf) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70c0) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70f2) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x710d) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x716c) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x716d) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x717f) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x71bc) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x717d) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x72e8) },
+	{ PCI_VDEVICE(NI, 0x0162), BOARD_PCIMIO_16XE_50 },	/* 0x1620? */
+	{ PCI_VDEVICE(NI, 0x1170), BOARD_PCIMIO_16XE_10 },
+	{ PCI_VDEVICE(NI, 0x1180), BOARD_PCIMIO_16E_1 },
+	{ PCI_VDEVICE(NI, 0x1190), BOARD_PCIMIO_16E_4 },
+	{ PCI_VDEVICE(NI, 0x11b0), BOARD_PXI6070E },
+	{ PCI_VDEVICE(NI, 0x11c0), BOARD_PXI6040E },
+	{ PCI_VDEVICE(NI, 0x11d0), BOARD_PXI6030E },
+	{ PCI_VDEVICE(NI, 0x1270), BOARD_PCI6032E },
+	{ PCI_VDEVICE(NI, 0x1330), BOARD_PCI6031E },
+	{ PCI_VDEVICE(NI, 0x1340), BOARD_PCI6033E },
+	{ PCI_VDEVICE(NI, 0x1350), BOARD_PCI6071E },
+	{ PCI_VDEVICE(NI, 0x14e0), BOARD_PCI6110 },
+	{ PCI_VDEVICE(NI, 0x14f0), BOARD_PCI6111 },
+	{ PCI_VDEVICE(NI, 0x1580), BOARD_PXI6031E },
+	{ PCI_VDEVICE(NI, 0x15b0), BOARD_PXI6071E },
+	{ PCI_VDEVICE(NI, 0x1880), BOARD_PCI6711 },
+	{ PCI_VDEVICE(NI, 0x1870), BOARD_PCI6713 },
+	{ PCI_VDEVICE(NI, 0x18b0), BOARD_PCI6052E },
+	{ PCI_VDEVICE(NI, 0x18c0), BOARD_PXI6052E },
+	{ PCI_VDEVICE(NI, 0x2410), BOARD_PCI6733 },
+	{ PCI_VDEVICE(NI, 0x2420), BOARD_PXI6733 },
+	{ PCI_VDEVICE(NI, 0x2430), BOARD_PCI6731 },
+	{ PCI_VDEVICE(NI, 0x2890), BOARD_PCI6036E },
+	{ PCI_VDEVICE(NI, 0x28c0), BOARD_PCI6014 },
+	{ PCI_VDEVICE(NI, 0x2a60), BOARD_PCI6023E },
+	{ PCI_VDEVICE(NI, 0x2a70), BOARD_PCI6024E },
+	{ PCI_VDEVICE(NI, 0x2a80), BOARD_PCI6025E },
+	{ PCI_VDEVICE(NI, 0x2ab0), BOARD_PXI6025E },
+	{ PCI_VDEVICE(NI, 0x2b80), BOARD_PXI6713 },
+	{ PCI_VDEVICE(NI, 0x2b90), BOARD_PXI6711 },
+	{ PCI_VDEVICE(NI, 0x2c80), BOARD_PCI6035E },
+	{ PCI_VDEVICE(NI, 0x2ca0), BOARD_PCI6034E },
+	{ PCI_VDEVICE(NI, 0x70aa), BOARD_PCI6229 },
+	{ PCI_VDEVICE(NI, 0x70ab), BOARD_PCI6259 },
+	{ PCI_VDEVICE(NI, 0x70ac), BOARD_PCI6289 },
+	{ PCI_VDEVICE(NI, 0x70af), BOARD_PCI6221 },
+	{ PCI_VDEVICE(NI, 0x70b0), BOARD_PCI6220 },
+	{ PCI_VDEVICE(NI, 0x70b4), BOARD_PCI6250 },
+	{ PCI_VDEVICE(NI, 0x70b6), BOARD_PCI6280 },
+	{ PCI_VDEVICE(NI, 0x70b7), BOARD_PCI6254 },
+	{ PCI_VDEVICE(NI, 0x70b8), BOARD_PCI6251 },
+	{ PCI_VDEVICE(NI, 0x70bc), BOARD_PCI6284 },
+	{ PCI_VDEVICE(NI, 0x70bd), BOARD_PCI6281 },
+	{ PCI_VDEVICE(NI, 0x70bf), BOARD_PXI6281 },
+	{ PCI_VDEVICE(NI, 0x70c0), BOARD_PCI6143 },
+	{ PCI_VDEVICE(NI, 0x70f2), BOARD_PCI6224 },
+	{ PCI_VDEVICE(NI, 0x70f3), BOARD_PXI6224 },
+	{ PCI_VDEVICE(NI, 0x710d), BOARD_PXI6143 },
+	{ PCI_VDEVICE(NI, 0x716c), BOARD_PCI6225 },
+	{ PCI_VDEVICE(NI, 0x716d), BOARD_PXI6225 },
+	{ PCI_VDEVICE(NI, 0x717f), BOARD_PCIE6259 },
+	{ PCI_VDEVICE(NI, 0x71bc), BOARD_PCI6221_37PIN },
+	{ PCI_VDEVICE(NI, 0x717d), BOARD_PCIE6251 },
+	{ PCI_VDEVICE(NI, 0x72e8), BOARD_PXIE6251 },
 	{ 0 }
 };
 MODULE_DEVICE_TABLE(pci, ni_pcimio_pci_table);
diff --git a/drivers/staging/comedi/drivers/ni_stc.h b/drivers/staging/comedi/drivers/ni_stc.h
index 504ea71..0a613c0 100644
--- a/drivers/staging/comedi/drivers/ni_stc.h
+++ b/drivers/staging/comedi/drivers/ni_stc.h
@@ -1421,10 +1421,6 @@ struct ni_board_struct {
 	enum caldac_enum caldac[3];
 };
 
-#define n_ni_boards  (sizeof(ni_boards)/sizeof(struct ni_board_struct))
-
-#define boardtype (*(struct ni_board_struct *)dev->board_ptr)
-
 #define MAX_N_AO_CHAN 8
 #define NUM_GPCT 2
 
diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c
index f625fda..ebd9e47 100644
--- a/drivers/staging/comedi/drivers/pcl816.c
+++ b/drivers/staging/comedi/drivers/pcl816.c
@@ -837,7 +837,7 @@ start_pacer(struct comedi_device *dev, int mode, unsigned int divisor1,
 
 /*
 ==============================================================================
- Check if channel list from user is builded correctly
+ Check if channel list from user is built correctly
  If it's ok, then return non-zero length of repeated segment of channel list
 */
 static int
diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c
index 6a5c914..30a1728 100644
--- a/drivers/staging/comedi/drivers/rtd520.c
+++ b/drivers/staging/comedi/drivers/rtd520.c
@@ -1,105 +1,103 @@
 /*
-    comedi/drivers/rtd520.c
-    Comedi driver for Real Time Devices (RTD) PCI4520/DM7520
-
-    COMEDI - Linux Control and Measurement Device Interface
-    Copyright (C) 2001 David A. Schleef <ds@schleef.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.
+ * comedi/drivers/rtd520.c
+ * Comedi driver for Real Time Devices (RTD) PCI4520/DM7520
+ *
+ * COMEDI - Linux Control and Measurement Device Interface
+ * Copyright (C) 2001 David A. Schleef <ds@schleef.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.
+ */
 
-    You 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: rtd520
-Description: Real Time Devices PCI4520/DM7520
-Author: Dan Christian
-Devices: [Real Time Devices] DM7520HR-1 (rtd520), DM7520HR-8,
-  PCI4520, PCI4520-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.
-  [1] - PCI slot of device (optional)
-*/
 /*
-    Created by Dan Christian, NASA Ames Research Center.
-
-    The PCI4520 is a PCI card.  The DM7520 is a PC/104-plus card.
-    Both have:
-    8/16 12 bit ADC with FIFO and channel gain table
-    8 bits high speed digital out (for external MUX) (or 8 in or 8 out)
-    8 bits high speed digital in with FIFO and interrupt on change (or 8 IO)
-    2 12 bit DACs with FIFOs
-    2 bits output
-    2 bits input
-    bus mastering DMA
-    timers: ADC sample, pacer, burst, about, delay, DA1, DA2
-    sample counter
-    3 user timer/counters (8254)
-    external interrupt
-
-    The DM7520 has slightly fewer features (fewer gain steps).
-
-    These boards can support external multiplexors and multi-board
-    synchronization, but this driver doesn't support that.
-
-    Board docs: http://www.rtdusa.com/PC104/DM/analog%20IO/dm7520.htm
-    Data sheet: http://www.rtdusa.com/pdf/dm7520.pdf
-    Example source: http://www.rtdusa.com/examples/dm/dm7520.zip
-    Call them and ask for the register level manual.
-    PCI chip: http://www.plxtech.com/products/io/pci9080
-
-    Notes:
-    This board is memory mapped.  There is some IO stuff, but it isn't needed.
-
-    I use a pretty loose naming style within the driver (rtd_blah).
-    All externally visible names should be rtd520_blah.
-    I use camelCase for structures (and inside them).
-    I may also use upper CamelCase for function names (old habit).
-
-    This board is somewhat related to the RTD PCI4400 board.
-
-    I borrowed heavily from the ni_mio_common, ni_atmio16d, mite, and
-    das1800, since they have the best documented code.  Driver
-    cb_pcidas64.c uses the same DMA controller.
-
-    As far as I can tell, the About interrupt doesn't work if Sample is
-    also enabled.  It turns out that About really isn't needed, since
-    we always count down samples read.
-
-    There was some timer/counter code, but it didn't follow the right API.
-
-*/
+ * Driver: rtd520
+ * Description: Real Time Devices PCI4520/DM7520
+ * Devices: (Real Time Devices) DM7520HR-1 [DM7520]
+ *	    (Real Time Devices) DM7520HR-8 [DM7520]
+ *	    (Real Time Devices) PCI4520 [PCI4520]
+ *	    (Real Time Devices) PCI4520-8 [PCI4520]
+ * Author: Dan Christian
+ * Status: Works. Only tested on DM7520-8. Not SMP safe.
+ *
+ * Configuration options: not applicable, uses PCI auto config
+ */
 
 /*
-  driver status:
-
-  Analog-In supports instruction and command mode.
-
-  With DMA, you can sample at 1.15Mhz with 70% idle on a 400Mhz K6-2
-  (single channel, 64K read buffer).  I get random system lockups when
-  using DMA with ALI-15xx based systems.  I haven't been able to test
-  any other chipsets.  The lockups happen soon after the start of an
-  acquistion, not in the middle of a long run.
-
-  Without DMA, you can do 620Khz sampling with 20% idle on a 400Mhz K6-2
-  (with a 256K read buffer).
-
-  Digital-IO and Analog-Out only support instruction mode.
+ * Created by Dan Christian, NASA Ames Research Center.
+ *
+ * The PCI4520 is a PCI card. The DM7520 is a PC/104-plus card.
+ * Both have:
+ *   8/16 12 bit ADC with FIFO and channel gain table
+ *   8 bits high speed digital out (for external MUX) (or 8 in or 8 out)
+ *   8 bits high speed digital in with FIFO and interrupt on change (or 8 IO)
+ *   2 12 bit DACs with FIFOs
+ *   2 bits output
+ *   2 bits input
+ *   bus mastering DMA
+ *   timers: ADC sample, pacer, burst, about, delay, DA1, DA2
+ *   sample counter
+ *   3 user timer/counters (8254)
+ *   external interrupt
+ *
+ * The DM7520 has slightly fewer features (fewer gain steps).
+ *
+ * These boards can support external multiplexors and multi-board
+ * synchronization, but this driver doesn't support that.
+ *
+ * Board docs: http://www.rtdusa.com/PC104/DM/analog%20IO/dm7520.htm
+ * Data sheet: http://www.rtdusa.com/pdf/dm7520.pdf
+ * Example source: http://www.rtdusa.com/examples/dm/dm7520.zip
+ * Call them and ask for the register level manual.
+ * PCI chip: http://www.plxtech.com/products/io/pci9080
+ *
+ * Notes:
+ * This board is memory mapped. There is some IO stuff, but it isn't needed.
+ *
+ * I use a pretty loose naming style within the driver (rtd_blah).
+ * All externally visible names should be rtd520_blah.
+ * I use camelCase for structures (and inside them).
+ * I may also use upper CamelCase for function names (old habit).
+ *
+ * This board is somewhat related to the RTD PCI4400 board.
+ *
+ * I borrowed heavily from the ni_mio_common, ni_atmio16d, mite, and
+ * das1800, since they have the best documented code. Driver cb_pcidas64.c
+ * uses the same DMA controller.
+ *
+ * As far as I can tell, the About interrupt doesn't work if Sample is
+ * also enabled. It turns out that About really isn't needed, since
+ * we always count down samples read.
+ *
+ * There was some timer/counter code, but it didn't follow the right API.
+ */
 
-*/
+/*
+ * driver status:
+ *
+ * Analog-In supports instruction and command mode.
+ *
+ * With DMA, you can sample at 1.15Mhz with 70% idle on a 400Mhz K6-2
+ * (single channel, 64K read buffer). I get random system lockups when
+ * using DMA with ALI-15xx based systems. I haven't been able to test
+ * any other chipsets. The lockups happen soon after the start of an
+ * acquistion, not in the middle of a long run.
+ *
+ * Without DMA, you can do 620Khz sampling with 20% idle on a 400Mhz K6-2
+ * (with a 256K read buffer).
+ *
+ * Digital-IO and Analog-Out only support instruction mode.
+ */
 
 #include <linux/pci.h>
 #include <linux/delay.h>
@@ -108,9 +106,123 @@ Configuration options:
 #include "../comedidev.h"
 
 #include "comedi_fc.h"
-#include "rtd520.h"
 #include "plx9080.h"
 
+/*
+ * Local Address Space 0 Offsets
+ */
+#define LAS0_USER_IO		0x0008	/* User I/O */
+#define LAS0_ADC		0x0010	/* FIFO Status/Software A/D Start */
+#define FS_DAC1_NOT_EMPTY	(1 << 0)	/* DAC1 FIFO not empty */
+#define FS_DAC1_HEMPTY		(1 << 1)	/* DAC1 FIFO half empty */
+#define FS_DAC1_NOT_FULL	(1 << 2)	/* DAC1 FIFO not full */
+#define FS_DAC2_NOT_EMPTY	(1 << 4)	/* DAC2 FIFO not empty */
+#define FS_DAC2_HEMPTY		(1 << 5)	/* DAC2 FIFO half empty */
+#define FS_DAC2_NOT_FULL	(1 << 6)	/* DAC2 FIFO not full */
+#define FS_ADC_NOT_EMPTY	(1 << 8)	/* ADC FIFO not empty */
+#define FS_ADC_HEMPTY		(1 << 9)	/* ADC FIFO half empty */
+#define FS_ADC_NOT_FULL		(1 << 10)	/* ADC FIFO not full */
+#define FS_DIN_NOT_EMPTY	(1 << 12)	/* DIN FIFO not empty */
+#define FS_DIN_HEMPTY		(1 << 13)	/* DIN FIFO half empty */
+#define FS_DIN_NOT_FULL		(1 << 14)	/* DIN FIFO not full */
+#define LAS0_DAC1		0x0014	/* Software D/A1 Update (w) */
+#define LAS0_DAC2		0x0018	/* Software D/A2 Update (w) */
+#define LAS0_DAC		0x0024	/* Software Simultaneous Update (w) */
+#define LAS0_PACER		0x0028	/* Software Pacer Start/Stop */
+#define LAS0_TIMER		0x002c	/* Timer Status/HDIN Software Trig. */
+#define LAS0_IT			0x0030	/* Interrupt Status/Enable */
+#define IRQM_ADC_FIFO_WRITE	(1 << 0)	/* ADC FIFO Write */
+#define IRQM_CGT_RESET		(1 << 1)	/* Reset CGT */
+#define IRQM_CGT_PAUSE		(1 << 3)	/* Pause CGT */
+#define IRQM_ADC_ABOUT_CNT	(1 << 4)	/* About Counter out */
+#define IRQM_ADC_DELAY_CNT	(1 << 5)	/* Delay Counter out */
+#define IRQM_ADC_SAMPLE_CNT	(1 << 6)	/* ADC Sample Counter */
+#define IRQM_DAC1_UCNT		(1 << 7)	/* DAC1 Update Counter */
+#define IRQM_DAC2_UCNT		(1 << 8)	/* DAC2 Update Counter */
+#define IRQM_UTC1		(1 << 9)	/* User TC1 out */
+#define IRQM_UTC1_INV		(1 << 10)	/* User TC1 out, inverted */
+#define IRQM_UTC2		(1 << 11)	/* User TC2 out */
+#define IRQM_DIGITAL_IT		(1 << 12)	/* Digital Interrupt */
+#define IRQM_EXTERNAL_IT	(1 << 13)	/* External Interrupt */
+#define IRQM_ETRIG_RISING	(1 << 14)	/* Ext Trigger rising-edge */
+#define IRQM_ETRIG_FALLING	(1 << 15)	/* Ext Trigger falling-edge */
+#define LAS0_CLEAR		0x0034	/* Clear/Set Interrupt Clear Mask */
+#define LAS0_OVERRUN		0x0038	/* Pending interrupts/Clear Overrun */
+#define LAS0_PCLK		0x0040	/* Pacer Clock (24bit) */
+#define LAS0_BCLK		0x0044	/* Burst Clock (10bit) */
+#define LAS0_ADC_SCNT		0x0048	/* A/D Sample counter (10bit) */
+#define LAS0_DAC1_UCNT		0x004c	/* D/A1 Update counter (10 bit) */
+#define LAS0_DAC2_UCNT		0x0050	/* D/A2 Update counter (10 bit) */
+#define LAS0_DCNT		0x0054	/* Delay counter (16 bit) */
+#define LAS0_ACNT		0x0058	/* About counter (16 bit) */
+#define LAS0_DAC_CLK		0x005c	/* DAC clock (16bit) */
+#define LAS0_UTC0		0x0060	/* 8254 TC Counter 0 */
+#define LAS0_UTC1		0x0064	/* 8254 TC Counter 1 */
+#define LAS0_UTC2		0x0068	/* 8254 TC Counter 2 */
+#define LAS0_UTC_CTRL		0x006c	/* 8254 TC Control */
+#define LAS0_DIO0		0x0070	/* Digital I/O Port 0 */
+#define LAS0_DIO1		0x0074	/* Digital I/O Port 1 */
+#define LAS0_DIO0_CTRL		0x0078	/* Digital I/O Control */
+#define LAS0_DIO_STATUS		0x007c	/* Digital I/O Status */
+#define LAS0_BOARD_RESET	0x0100	/* Board reset */
+#define LAS0_DMA0_SRC		0x0104	/* DMA 0 Sources select */
+#define LAS0_DMA1_SRC		0x0108	/* DMA 1 Sources select */
+#define LAS0_ADC_CONVERSION	0x010c	/* A/D Conversion Signal select */
+#define LAS0_BURST_START	0x0110	/* Burst Clock Start Trigger select */
+#define LAS0_PACER_START	0x0114	/* Pacer Clock Start Trigger select */
+#define LAS0_PACER_STOP		0x0118	/* Pacer Clock Stop Trigger select */
+#define LAS0_ACNT_STOP_ENABLE	0x011c	/* About Counter Stop Enable */
+#define LAS0_PACER_REPEAT	0x0120	/* Pacer Start Trigger Mode select */
+#define LAS0_DIN_START		0x0124	/* HiSpd DI Sampling Signal select */
+#define LAS0_DIN_FIFO_CLEAR	0x0128	/* Digital Input FIFO Clear */
+#define LAS0_ADC_FIFO_CLEAR	0x012c	/* A/D FIFO Clear */
+#define LAS0_CGT_WRITE		0x0130	/* Channel Gain Table Write */
+#define LAS0_CGL_WRITE		0x0134	/* Channel Gain Latch Write */
+#define LAS0_CG_DATA		0x0138	/* Digital Table Write */
+#define LAS0_CGT_ENABLE		0x013c	/* Channel Gain Table Enable */
+#define LAS0_CG_ENABLE		0x0140	/* Digital Table Enable */
+#define LAS0_CGT_PAUSE		0x0144	/* Table Pause Enable */
+#define LAS0_CGT_RESET		0x0148	/* Reset Channel Gain Table */
+#define LAS0_CGT_CLEAR		0x014c	/* Clear Channel Gain Table */
+#define LAS0_DAC1_CTRL		0x0150	/* D/A1 output type/range */
+#define LAS0_DAC1_SRC		0x0154	/* D/A1 update source */
+#define LAS0_DAC1_CYCLE		0x0158	/* D/A1 cycle mode */
+#define LAS0_DAC1_RESET		0x015c	/* D/A1 FIFO reset */
+#define LAS0_DAC1_FIFO_CLEAR	0x0160	/* D/A1 FIFO clear */
+#define LAS0_DAC2_CTRL		0x0164	/* D/A2 output type/range */
+#define LAS0_DAC2_SRC		0x0168	/* D/A2 update source */
+#define LAS0_DAC2_CYCLE		0x016c	/* D/A2 cycle mode */
+#define LAS0_DAC2_RESET		0x0170	/* D/A2 FIFO reset */
+#define LAS0_DAC2_FIFO_CLEAR	0x0174	/* D/A2 FIFO clear */
+#define LAS0_ADC_SCNT_SRC	0x0178	/* A/D Sample Counter Source select */
+#define LAS0_PACER_SELECT	0x0180	/* Pacer Clock select */
+#define LAS0_SBUS0_SRC		0x0184	/* SyncBus 0 Source select */
+#define LAS0_SBUS0_ENABLE	0x0188	/* SyncBus 0 enable */
+#define LAS0_SBUS1_SRC		0x018c	/* SyncBus 1 Source select */
+#define LAS0_SBUS1_ENABLE	0x0190	/* SyncBus 1 enable */
+#define LAS0_SBUS2_SRC		0x0198	/* SyncBus 2 Source select */
+#define LAS0_SBUS2_ENABLE	0x019c	/* SyncBus 2 enable */
+#define LAS0_ETRG_POLARITY	0x01a4	/* Ext. Trigger polarity select */
+#define LAS0_EINT_POLARITY	0x01a8	/* Ext. Interrupt polarity select */
+#define LAS0_UTC0_CLOCK		0x01ac	/* UTC0 Clock select */
+#define LAS0_UTC0_GATE		0x01b0	/* UTC0 Gate select */
+#define LAS0_UTC1_CLOCK		0x01b4	/* UTC1 Clock select */
+#define LAS0_UTC1_GATE		0x01b8	/* UTC1 Gate select */
+#define LAS0_UTC2_CLOCK		0x01bc	/* UTC2 Clock select */
+#define LAS0_UTC2_GATE		0x01c0	/* UTC2 Gate select */
+#define LAS0_UOUT0_SELECT	0x01c4	/* User Output 0 source select */
+#define LAS0_UOUT1_SELECT	0x01c8	/* User Output 1 source select */
+#define LAS0_DMA0_RESET		0x01cc	/* DMA0 Request state machine reset */
+#define LAS0_DMA1_RESET		0x01d0	/* DMA1 Request state machine reset */
+
+/*
+ * Local Address Space 1 Offsets
+ */
+#define LAS1_ADC_FIFO		0x0000	/* A/D FIFO (16bit) */
+#define LAS1_HDIO_FIFO		0x0004	/* HiSpd DI FIFO (16bit) */
+#define LAS1_DAC1_FIFO		0x0008	/* D/A1 FIFO (16bit) */
+#define LAS1_DAC2_FIFO		0x000c	/* D/A2 FIFO (16bit) */
+
 /*======================================================================
   Driver specific stuff (tunable)
 ======================================================================*/
@@ -249,61 +361,48 @@ static const struct comedi_lrange rtd_ao_range = {
 	}
 };
 
-struct rtdBoard {
+enum rtd_boardid {
+	BOARD_DM7520,
+	BOARD_PCI4520,
+};
+
+struct rtd_boardinfo {
 	const char *name;
-	int device_id;
-	int range10Start;	/* start of +-10V range */
-	int rangeUniStart;	/* start of +10V range */
+	int range_bip10;	/* start of +-10V range */
+	int range_uni10;	/* start of +10V range */
 	const struct comedi_lrange *ai_range;
 };
 
-static const struct rtdBoard rtd520Boards[] = {
-	{
+static const struct rtd_boardinfo rtd520Boards[] = {
+	[BOARD_DM7520] = {
 		.name		= "DM7520",
-		.device_id	= 0x7520,
-		.range10Start	= 6,
-		.rangeUniStart	= 12,
+		.range_bip10	= 6,
+		.range_uni10	= 12,
 		.ai_range	= &rtd_ai_7520_range,
-	}, {
+	},
+	[BOARD_PCI4520] = {
 		.name		= "PCI4520",
-		.device_id	= 0x4520,
-		.range10Start	= 8,
-		.rangeUniStart	= 16,
+		.range_bip10	= 8,
+		.range_uni10	= 16,
 		.ai_range	= &rtd_ai_4520_range,
 	},
 };
 
-/*
-   This structure is for data unique to this hardware driver.
-   This is also unique for each board in the system.
-*/
-struct rtdPrivate {
+struct rtd_private {
 	/* memory mapped board structures */
 	void __iomem *las0;
 	void __iomem *las1;
 	void __iomem *lcfg;
 
-	long aiCount;		/* total transfer size (samples) */
-	int transCount;		/* # to transfer data. 0->1/2FIFO */
+	long ai_count;		/* total transfer size (samples) */
+	int xfer_count;		/* # to transfer data. 0->1/2FIFO */
 	int flags;		/* flag event modes */
 
-	/* channel list info */
-	/* chanBipolar tracks whether a channel is bipolar (and needs +2048) */
-	unsigned char chanBipolar[RTD_MAX_CHANLIST / 8];	/* bit array */
+	unsigned char chan_is_bipolar[RTD_MAX_CHANLIST / 8];	/* bit array */
 
-	/* read back data */
-	unsigned int aoValue[2];	/* Used for AO read back */
+	unsigned int ao_readback[2];
 
-	/* timer gate (when enabled) */
-	u8 utcGate[4];		/* 1 extra allows simple range check */
-
-	/* shadow registers affect other registers, but can't be read back */
-	/* The macros below update these on writes */
-	u16 intMask;		/* interrupt mask */
-	u16 intClearMask;	/* interrupt clear mask */
-	u8 utcCtrl[4];		/* crtl mode for 3 utc + read back */
-	u8 dioStatus;		/* could be read back (dio0Ctrl) */
-	unsigned fifoLen;
+	unsigned fifosz;
 };
 
 /* bit defines for "flags" */
@@ -365,36 +464,34 @@ static int rtd_ns_to_timer(unsigned int *ns, int round_mode)
 /*
   Convert a single comedi channel-gain entry to a RTD520 table entry
 */
-static unsigned short rtdConvertChanGain(struct comedi_device *dev,
-					 unsigned int comediChan, int chanIndex)
-{				/* index in channel list */
-	const struct rtdBoard *thisboard = comedi_board(dev);
-	struct rtdPrivate *devpriv = dev->private;
-	unsigned int chan, range, aref;
+static unsigned short rtd_convert_chan_gain(struct comedi_device *dev,
+					    unsigned int chanspec, int index)
+{
+	const struct rtd_boardinfo *board = comedi_board(dev);
+	struct rtd_private *devpriv = dev->private;
+	unsigned int chan = CR_CHAN(chanspec);
+	unsigned int range = CR_RANGE(chanspec);
+	unsigned int aref = CR_AREF(chanspec);
 	unsigned short r = 0;
 
-	chan = CR_CHAN(comediChan);
-	range = CR_RANGE(comediChan);
-	aref = CR_AREF(comediChan);
-
 	r |= chan & 0xf;
 
 	/* Note: we also setup the channel list bipolar flag array */
-	if (range < thisboard->range10Start) {
+	if (range < board->range_bip10) {
 		/* +-5 range */
 		r |= 0x000;
 		r |= (range & 0x7) << 4;
-		CHAN_ARRAY_SET(devpriv->chanBipolar, chanIndex);
-	} else if (range < thisboard->rangeUniStart) {
+		CHAN_ARRAY_SET(devpriv->chan_is_bipolar, index);
+	} else if (range < board->range_uni10) {
 		/* +-10 range */
 		r |= 0x100;
-		r |= ((range - thisboard->range10Start) & 0x7) << 4;
-		CHAN_ARRAY_SET(devpriv->chanBipolar, chanIndex);
+		r |= ((range - board->range_bip10) & 0x7) << 4;
+		CHAN_ARRAY_SET(devpriv->chan_is_bipolar, index);
 	} else {
 		/* +10 range */
 		r |= 0x200;
-		r |= ((range - thisboard->rangeUniStart) & 0x7) << 4;
-		CHAN_ARRAY_CLEAR(devpriv->chanBipolar, chanIndex);
+		r |= ((range - board->range_uni10) & 0x7) << 4;
+		CHAN_ARRAY_CLEAR(devpriv->chan_is_bipolar, index);
 	}
 
 	switch (aref) {
@@ -423,7 +520,7 @@ static unsigned short rtdConvertChanGain(struct comedi_device *dev,
 static void rtd_load_channelgain_list(struct comedi_device *dev,
 				      unsigned int n_chan, unsigned int *list)
 {
-	struct rtdPrivate *devpriv = dev->private;
+	struct rtd_private *devpriv = dev->private;
 
 	if (n_chan > 1) {	/* setup channel gain table */
 		int ii;
@@ -431,12 +528,12 @@ static void rtd_load_channelgain_list(struct comedi_device *dev,
 		writel(0, devpriv->las0 + LAS0_CGT_CLEAR);
 		writel(1, devpriv->las0 + LAS0_CGT_ENABLE);
 		for (ii = 0; ii < n_chan; ii++) {
-			writel(rtdConvertChanGain(dev, list[ii], ii),
+			writel(rtd_convert_chan_gain(dev, list[ii], ii),
 				devpriv->las0 + LAS0_CGT_WRITE);
 		}
 	} else {		/* just use the channel gain latch */
 		writel(0, devpriv->las0 + LAS0_CGT_ENABLE);
-		writel(rtdConvertChanGain(dev, list[0], 0),
+		writel(rtd_convert_chan_gain(dev, list[0], 0),
 			devpriv->las0 + LAS0_CGL_WRITE);
 	}
 }
@@ -445,7 +542,7 @@ static void rtd_load_channelgain_list(struct comedi_device *dev,
 empty status flag clears */
 static int rtd520_probe_fifo_depth(struct comedi_device *dev)
 {
-	struct rtdPrivate *devpriv = dev->private;
+	struct rtd_private *devpriv = dev->private;
 	unsigned int chanspec = CR_PACK(0, 0, AREF_GROUND);
 	unsigned i;
 	static const unsigned limit = 0x2000;
@@ -493,7 +590,7 @@ static int rtd_ai_rinsn(struct comedi_device *dev,
 			struct comedi_subdevice *s, struct comedi_insn *insn,
 			unsigned int *data)
 {
-	struct rtdPrivate *devpriv = dev->private;
+	struct rtd_private *devpriv = dev->private;
 	int n, ii;
 	int stat;
 
@@ -525,7 +622,7 @@ static int rtd_ai_rinsn(struct comedi_device *dev,
 		d = readw(devpriv->las1 + LAS1_ADC_FIFO);
 		/*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))
+		if (CHAN_ARRAY_TEST(devpriv->chan_is_bipolar, 0))
 			/* convert to comedi unsigned data */
 			data[n] = d + 2048;
 		else
@@ -545,21 +642,22 @@ static int rtd_ai_rinsn(struct comedi_device *dev,
 static int ai_read_n(struct comedi_device *dev, struct comedi_subdevice *s,
 		     int count)
 {
-	struct rtdPrivate *devpriv = dev->private;
+	struct rtd_private *devpriv = dev->private;
 	int ii;
 
 	for (ii = 0; ii < count; ii++) {
 		short sample;
 		s16 d;
 
-		if (0 == devpriv->aiCount) {	/* done */
+		if (0 == devpriv->ai_count) {	/* done */
 			d = readw(devpriv->las1 + LAS1_ADC_FIFO);
 			continue;
 		}
 
 		d = readw(devpriv->las1 + LAS1_ADC_FIFO);
 		d = d >> 3;	/* low 3 bits are marker lines */
-		if (CHAN_ARRAY_TEST(devpriv->chanBipolar, s->async->cur_chan)) {
+		if (CHAN_ARRAY_TEST(devpriv->chan_is_bipolar,
+				    s->async->cur_chan)) {
 			/* convert to comedi unsigned data */
 			sample = d + 2048;
 		} else
@@ -568,8 +666,8 @@ static int ai_read_n(struct comedi_device *dev, struct comedi_subdevice *s,
 		if (!comedi_buf_put(s->async, sample))
 			return -1;
 
-		if (devpriv->aiCount > 0)	/* < 0, means read forever */
-			devpriv->aiCount--;
+		if (devpriv->ai_count > 0)	/* < 0, means read forever */
+			devpriv->ai_count--;
 	}
 	return 0;
 }
@@ -579,18 +677,19 @@ static int ai_read_n(struct comedi_device *dev, struct comedi_subdevice *s,
 */
 static int ai_read_dregs(struct comedi_device *dev, struct comedi_subdevice *s)
 {
-	struct rtdPrivate *devpriv = dev->private;
+	struct rtd_private *devpriv = dev->private;
 
 	while (readl(devpriv->las0 + LAS0_ADC) & FS_ADC_NOT_EMPTY) {
 		short sample;
 		s16 d = readw(devpriv->las1 + LAS1_ADC_FIFO);
 
-		if (0 == devpriv->aiCount) {	/* done */
+		if (0 == devpriv->ai_count) {	/* done */
 			continue;	/* read rest */
 		}
 
 		d = d >> 3;	/* low 3 bits are marker lines */
-		if (CHAN_ARRAY_TEST(devpriv->chanBipolar, s->async->cur_chan)) {
+		if (CHAN_ARRAY_TEST(devpriv->chan_is_bipolar,
+				    s->async->cur_chan)) {
 			/* convert to comedi unsigned data */
 			sample = d + 2048;
 		} else
@@ -599,8 +698,8 @@ static int ai_read_dregs(struct comedi_device *dev, struct comedi_subdevice *s)
 		if (!comedi_buf_put(s->async, sample))
 			return -1;
 
-		if (devpriv->aiCount > 0)	/* < 0, means read forever */
-			devpriv->aiCount--;
+		if (devpriv->ai_count > 0)	/* < 0, means read forever */
+			devpriv->ai_count--;
 	}
 	return 0;
 }
@@ -611,23 +710,22 @@ static int ai_read_dregs(struct comedi_device *dev, struct comedi_subdevice *s)
   This is a "slow handler";  other interrupts may be active.
   The data conversion may someday happen in a "bottom half".
 */
-static irqreturn_t rtd_interrupt(int irq,	/* interrupt number (ignored) */
-				 void *d)
-{				/* our data *//* cpu context (ignored) */
+static irqreturn_t rtd_interrupt(int irq, void *d)
+{
 	struct comedi_device *dev = d;
 	struct comedi_subdevice *s = &dev->subdevices[0];
-	struct rtdPrivate *devpriv = dev->private;
+	struct rtd_private *devpriv = dev->private;
 	u32 overrun;
 	u16 status;
-	u16 fifoStatus;
+	u16 fifo_status;
 
 	if (!dev->attached)
 		return IRQ_NONE;
 
-	fifoStatus = readl(devpriv->las0 + LAS0_ADC);
+	fifo_status = readl(devpriv->las0 + LAS0_ADC);
 	/* check for FIFO full, this automatically halts the ADC! */
-	if (!(fifoStatus & FS_ADC_NOT_FULL))	/* 0 -> full */
-		goto abortTransfer;
+	if (!(fifo_status & FS_ADC_NOT_FULL))	/* 0 -> full */
+		goto xfer_abort;
 
 	status = readw(devpriv->las0 + LAS0_IT);
 	/* if interrupt was not caused by our board, or handled above */
@@ -641,23 +739,23 @@ static irqreturn_t rtd_interrupt(int irq,	/* interrupt number (ignored) */
 		 * finished, we must handle the possibility that there is
 		 * no data here
 		 */
-		if (!(fifoStatus & FS_ADC_HEMPTY)) {
+		if (!(fifo_status & FS_ADC_HEMPTY)) {
 			/* FIFO half full */
-			if (ai_read_n(dev, s, devpriv->fifoLen / 2) < 0)
-				goto abortTransfer;
+			if (ai_read_n(dev, s, devpriv->fifosz / 2) < 0)
+				goto xfer_abort;
 
-			if (0 == devpriv->aiCount)
-				goto transferDone;
+			if (0 == devpriv->ai_count)
+				goto xfer_done;
 
 			comedi_event(dev, s);
-		} else if (devpriv->transCount > 0) {
-			if (fifoStatus & FS_ADC_NOT_EMPTY) {
+		} else if (devpriv->xfer_count > 0) {
+			if (fifo_status & FS_ADC_NOT_EMPTY) {
 				/* FIFO not empty */
-				if (ai_read_n(dev, s, devpriv->transCount) < 0)
-					goto abortTransfer;
+				if (ai_read_n(dev, s, devpriv->xfer_count) < 0)
+					goto xfer_abort;
 
-				if (0 == devpriv->aiCount)
-					goto transferDone;
+				if (0 == devpriv->ai_count)
+					goto xfer_done;
 
 				comedi_event(dev, s);
 			}
@@ -666,30 +764,28 @@ static irqreturn_t rtd_interrupt(int irq,	/* interrupt number (ignored) */
 
 	overrun = readl(devpriv->las0 + LAS0_OVERRUN) & 0xffff;
 	if (overrun)
-		goto abortTransfer;
+		goto xfer_abort;
 
 	/* clear the interrupt */
-	devpriv->intClearMask = status;
-	writew(devpriv->intClearMask, devpriv->las0 + LAS0_CLEAR);
+	writew(status, devpriv->las0 + LAS0_CLEAR);
 	readw(devpriv->las0 + LAS0_CLEAR);
 	return IRQ_HANDLED;
 
-abortTransfer:
+xfer_abort:
 	writel(0, devpriv->las0 + LAS0_ADC_FIFO_CLEAR);
 	s->async->events |= COMEDI_CB_ERROR;
-	devpriv->aiCount = 0;	/* stop and don't transfer any more */
-	/* fall into transferDone */
+	devpriv->ai_count = 0;	/* stop and don't transfer any more */
+	/* fall into xfer_done */
 
-transferDone:
+xfer_done:
 	/* pacer stop source: SOFTWARE */
 	writel(0, devpriv->las0 + LAS0_PACER_STOP);
 	writel(0, devpriv->las0 + LAS0_PACER);	/* stop pacer */
 	writel(0, devpriv->las0 + LAS0_ADC_CONVERSION);
-	devpriv->intMask = 0;
-	writew(devpriv->intMask, devpriv->las0 + LAS0_IT);
+	writew(0, devpriv->las0 + LAS0_IT);
 
-	if (devpriv->aiCount > 0) {	/* there shouldn't be anything left */
-		fifoStatus = readl(devpriv->las0 + LAS0_ADC);
+	if (devpriv->ai_count > 0) {	/* there shouldn't be anything left */
+		fifo_status = readl(devpriv->las0 + LAS0_ADC);
 		ai_read_dregs(dev, s);	/* read anything left in FIFO */
 	}
 
@@ -698,11 +794,10 @@ transferDone:
 
 	/* clear the interrupt */
 	status = readw(devpriv->las0 + LAS0_IT);
-	devpriv->intClearMask = status;
-	writew(devpriv->intClearMask, devpriv->las0 + LAS0_CLEAR);
+	writew(status, devpriv->las0 + LAS0_CLEAR);
 	readw(devpriv->las0 + LAS0_CLEAR);
 
-	fifoStatus = readl(devpriv->las0 + LAS0_ADC);
+	fifo_status = readl(devpriv->las0 + LAS0_ADC);
 	overrun = readl(devpriv->las0 + LAS0_OVERRUN) & 0xffff;
 
 	return IRQ_HANDLED;
@@ -875,7 +970,7 @@ static int rtd_ai_cmdtest(struct comedi_device *dev,
 */
 static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
-	struct rtdPrivate *devpriv = dev->private;
+	struct rtd_private *devpriv = dev->private;
 	struct comedi_cmd *cmd = &s->async->cmd;
 	int timer;
 
@@ -884,8 +979,7 @@ static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 	writel(0, devpriv->las0 + LAS0_PACER_STOP);
 	writel(0, devpriv->las0 + LAS0_PACER);	/* stop pacer */
 	writel(0, devpriv->las0 + LAS0_ADC_CONVERSION);
-	devpriv->intMask = 0;
-	writew(devpriv->intMask, devpriv->las0 + LAS0_IT);
+	writew(0, devpriv->las0 + LAS0_IT);
 	writel(0, devpriv->las0 + LAS0_ADC_FIFO_CLEAR);
 	writel(0, devpriv->las0 + LAS0_OVERRUN);
 
@@ -907,7 +1001,7 @@ static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 		/* ADC conversion trigger source: PACER */
 		writel(1, devpriv->las0 + LAS0_ADC_CONVERSION);
 	}
-	writel((devpriv->fifoLen / 2 - 1) & 0xffff, devpriv->las0 + LAS0_ACNT);
+	writel((devpriv->fifosz / 2 - 1) & 0xffff, devpriv->las0 + LAS0_ACNT);
 
 	if (TRIG_TIMER == cmd->scan_begin_src) {
 		/* scan_begin_arg is in nanoseconds */
@@ -918,37 +1012,36 @@ static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 			 * the application is responsible for doing the
 			 * right thing
 			 */
-			devpriv->transCount = cmd->chanlist_len;
+			devpriv->xfer_count = cmd->chanlist_len;
 			devpriv->flags |= SEND_EOS;
 		} else {
 			/* arrange to transfer data periodically */
-			devpriv->transCount
-			    =
+			devpriv->xfer_count =
 			    (TRANS_TARGET_PERIOD * cmd->chanlist_len) /
 			    cmd->scan_begin_arg;
-			if (devpriv->transCount < cmd->chanlist_len) {
+			if (devpriv->xfer_count < cmd->chanlist_len) {
 				/* transfer after each scan (and avoid 0) */
-				devpriv->transCount = cmd->chanlist_len;
+				devpriv->xfer_count = cmd->chanlist_len;
 			} else {	/* make a multiple of scan length */
-				devpriv->transCount =
-				    (devpriv->transCount +
+				devpriv->xfer_count =
+				    (devpriv->xfer_count +
 				     cmd->chanlist_len - 1)
 				    / cmd->chanlist_len;
-				devpriv->transCount *= cmd->chanlist_len;
+				devpriv->xfer_count *= cmd->chanlist_len;
 			}
 			devpriv->flags |= SEND_EOS;
 		}
-		if (devpriv->transCount >= (devpriv->fifoLen / 2)) {
+		if (devpriv->xfer_count >= (devpriv->fifosz / 2)) {
 			/* out of counter range, use 1/2 fifo instead */
-			devpriv->transCount = 0;
+			devpriv->xfer_count = 0;
 			devpriv->flags &= ~SEND_EOS;
 		} else {
 			/* interrupt for each transfer */
-			writel((devpriv->transCount - 1) & 0xffff,
+			writel((devpriv->xfer_count - 1) & 0xffff,
 				devpriv->las0 + LAS0_ACNT);
 		}
 	} else {		/* unknown timing, just use 1/2 FIFO */
-		devpriv->transCount = 0;
+		devpriv->xfer_count = 0;
 		devpriv->flags &= ~SEND_EOS;
 	}
 	/* pacer clock source: INTERNAL 8MHz */
@@ -961,15 +1054,15 @@ static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 	/* First, setup when to stop */
 	switch (cmd->stop_src) {
 	case TRIG_COUNT:	/* stop after N scans */
-		devpriv->aiCount = cmd->stop_arg * cmd->chanlist_len;
-		if ((devpriv->transCount > 0)
-		    && (devpriv->transCount > devpriv->aiCount)) {
-			devpriv->transCount = devpriv->aiCount;
+		devpriv->ai_count = cmd->stop_arg * cmd->chanlist_len;
+		if ((devpriv->xfer_count > 0)
+		    && (devpriv->xfer_count > devpriv->ai_count)) {
+			devpriv->xfer_count = devpriv->ai_count;
 		}
 		break;
 
 	case TRIG_NONE:	/* stop when cancel is called */
-		devpriv->aiCount = -1;	/* read forever */
+		devpriv->ai_count = -1;	/* read forever */
 		break;
 	}
 
@@ -1011,17 +1104,14 @@ static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 
 	/* This doesn't seem to work.  There is no way to clear an interrupt
 	   that the priority controller has queued! */
-	devpriv->intClearMask = ~0;
-	writew(devpriv->intClearMask, devpriv->las0 + LAS0_CLEAR);
+	writew(~0, devpriv->las0 + LAS0_CLEAR);
 	readw(devpriv->las0 + LAS0_CLEAR);
 
 	/* TODO: allow multiple interrupt sources */
-	if (devpriv->transCount > 0) {	/* transfer every N samples */
-		devpriv->intMask = IRQM_ADC_ABOUT_CNT;
-		writew(devpriv->intMask, devpriv->las0 + LAS0_IT);
+	if (devpriv->xfer_count > 0) {	/* transfer every N samples */
+		writew(IRQM_ADC_ABOUT_CNT, devpriv->las0 + LAS0_IT);
 	} else {		/* 1/2 FIFO transfers */
-		devpriv->intMask = IRQM_ADC_ABOUT_CNT;
-		writew(devpriv->intMask, devpriv->las0 + LAS0_IT);
+		writew(IRQM_ADC_ABOUT_CNT, devpriv->las0 + LAS0_IT);
 	}
 
 	/* BUG: start_src is ASSUMED to be TRIG_NOW */
@@ -1035,7 +1125,7 @@ static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 */
 static int rtd_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
 {
-	struct rtdPrivate *devpriv = dev->private;
+	struct rtd_private *devpriv = dev->private;
 	u32 overrun;
 	u16 status;
 
@@ -1043,9 +1133,8 @@ static int rtd_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
 	writel(0, devpriv->las0 + LAS0_PACER_STOP);
 	writel(0, devpriv->las0 + LAS0_PACER);	/* stop pacer */
 	writel(0, devpriv->las0 + LAS0_ADC_CONVERSION);
-	devpriv->intMask = 0;
-	writew(devpriv->intMask, devpriv->las0 + LAS0_IT);
-	devpriv->aiCount = 0;	/* stop and don't transfer any more */
+	writew(0, devpriv->las0 + LAS0_IT);
+	devpriv->ai_count = 0;	/* stop and don't transfer any more */
 	status = readw(devpriv->las0 + LAS0_IT);
 	overrun = readl(devpriv->las0 + LAS0_OVERRUN) & 0xffff;
 	return 0;
@@ -1058,7 +1147,7 @@ static int rtd_ao_winsn(struct comedi_device *dev,
 			struct comedi_subdevice *s, struct comedi_insn *insn,
 			unsigned int *data)
 {
-	struct rtdPrivate *devpriv = dev->private;
+	struct rtd_private *devpriv = dev->private;
 	int i;
 	int chan = CR_CHAN(insn->chanspec);
 	int range = CR_RANGE(insn->chanspec);
@@ -1090,7 +1179,7 @@ static int rtd_ao_winsn(struct comedi_device *dev,
 		writew(0, devpriv->las0 +
 			((chan == 0) ? LAS0_DAC1 : LAS0_DAC2));
 
-		devpriv->aoValue[chan] = data[i];	/* save for read back */
+		devpriv->ao_readback[chan] = data[i];
 
 		for (ii = 0; ii < RTD_DAC_TIMEOUT; ++ii) {
 			stat = readl(devpriv->las0 + LAS0_ADC);
@@ -1114,73 +1203,56 @@ static int rtd_ao_rinsn(struct comedi_device *dev,
 			struct comedi_subdevice *s, struct comedi_insn *insn,
 			unsigned int *data)
 {
-	struct rtdPrivate *devpriv = dev->private;
+	struct rtd_private *devpriv = dev->private;
 	int i;
 	int chan = CR_CHAN(insn->chanspec);
 
 	for (i = 0; i < insn->n; i++)
-		data[i] = devpriv->aoValue[chan];
+		data[i] = devpriv->ao_readback[chan];
 
 
 	return i;
 }
 
-/*
-   Write a masked set of bits and the read back the port.
-   We track what the bits should be (i.e. we don't read the port first).
-
-   DIO devices are slightly special.  Although it is possible to
- * implement the insn_read/insn_write interface, it is much more
- * useful to applications if you implement the insn_bits interface.
- * This allows packed reading/writing of the DIO channels.  The
- * comedi core can convert between insn_bits and insn_read/write
- */
 static int rtd_dio_insn_bits(struct comedi_device *dev,
 			     struct comedi_subdevice *s,
-			     struct comedi_insn *insn, unsigned int *data)
+			     struct comedi_insn *insn,
+			     unsigned int *data)
 {
-	struct rtdPrivate *devpriv = dev->private;
+	struct rtd_private *devpriv = dev->private;
+	unsigned int mask = data[0];
+	unsigned int bits = data[1];
 
-	/* The insn data is a mask in data[0] and the new data
-	 * in data[1], each channel cooresponding to a bit. */
-	if (data[0]) {
-		s->state &= ~data[0];
-		s->state |= data[0] & data[1];
+	if (mask) {
+		s->state &= ~mask;
+		s->state |= (bits & mask);
 
-		/* Write out the new digital output lines */
 		writew(s->state & 0xff, devpriv->las0 + LAS0_DIO0);
 	}
-	/* on return, data[1] contains the value of the digital
-	 * input lines. */
+
 	data[1] = readw(devpriv->las0 + LAS0_DIO0) & 0xff;
 
 	return insn->n;
 }
 
-/*
-  Configure one bit on a IO port as Input or Output (hence the name :-).
-*/
 static int rtd_dio_insn_config(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
-			       struct comedi_insn *insn, unsigned int *data)
+			       struct comedi_insn *insn,
+			       unsigned int *data)
 {
-	struct rtdPrivate *devpriv = dev->private;
-	int chan = CR_CHAN(insn->chanspec);
+	struct rtd_private *devpriv = dev->private;
+	unsigned int chan = CR_CHAN(insn->chanspec);
+	unsigned int mask = 1 << chan;
 
-	/* The input or output configuration of each digital line is
-	 * configured by a special insn_config instruction.  chanspec
-	 * contains the channel to be changed, and data[0] contains the
-	 * value COMEDI_INPUT or COMEDI_OUTPUT. */
 	switch (data[0]) {
 	case INSN_CONFIG_DIO_OUTPUT:
-		s->io_bits |= 1 << chan;	/* 1 means Out */
+		s->io_bits |= mask;
 		break;
 	case INSN_CONFIG_DIO_INPUT:
-		s->io_bits &= ~(1 << chan);
+		s->io_bits &= ~mask;
 		break;
 	case INSN_CONFIG_DIO_QUERY:
-		data[1] =
-		    (s->io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
+		data[1] = (s->io_bits & mask) ? COMEDI_OUTPUT : COMEDI_INPUT;
 		return insn->n;
 		break;
 	default:
@@ -1188,30 +1260,30 @@ static int rtd_dio_insn_config(struct comedi_device *dev,
 	}
 
 	/* TODO support digital match interrupts and strobes */
-	devpriv->dioStatus = 0x01;	/* set direction */
-	writew(devpriv->dioStatus, devpriv->las0 + LAS0_DIO_STATUS);
+
+	/* set direction */
+	writew(0x01, devpriv->las0 + LAS0_DIO_STATUS);
 	writew(s->io_bits & 0xff, devpriv->las0 + LAS0_DIO0_CTRL);
-	devpriv->dioStatus = 0x00;	/* clear interrupts */
-	writew(devpriv->dioStatus, devpriv->las0 + LAS0_DIO_STATUS);
+
+	/* clear interrupts */
+	writew(0x00, devpriv->las0 + LAS0_DIO_STATUS);
 
 	/* port1 can only be all input or all output */
 
 	/* there are also 2 user input lines and 2 user output lines */
 
-	return 1;
+	return insn->n;
 }
 
 static void rtd_reset(struct comedi_device *dev)
 {
-	struct rtdPrivate *devpriv = dev->private;
+	struct rtd_private *devpriv = dev->private;
 
 	writel(0, devpriv->las0 + LAS0_BOARD_RESET);
 	udelay(100);		/* needed? */
-	writel(0, devpriv->lcfg + LCFG_ITCSR);
-	devpriv->intMask = 0;
-	writew(devpriv->intMask, devpriv->las0 + LAS0_IT);
-	devpriv->intClearMask = ~0;
-	writew(devpriv->intClearMask, devpriv->las0 + LAS0_CLEAR);
+	writel(0, devpriv->lcfg + PLX_INTRCS_REG);
+	writew(0, devpriv->las0 + LAS0_IT);
+	writew(~0, devpriv->las0 + LAS0_CLEAR);
 	readw(devpriv->las0 + LAS0_CLEAR);
 }
 
@@ -1221,7 +1293,7 @@ static void rtd_reset(struct comedi_device *dev)
  */
 static void rtd_init_board(struct comedi_device *dev)
 {
-	struct rtdPrivate *devpriv = dev->private;
+	struct rtd_private *devpriv = dev->private;
 
 	rtd_reset(dev);
 
@@ -1231,16 +1303,11 @@ static void rtd_init_board(struct comedi_device *dev)
 	writel(0, devpriv->las0 + LAS0_DAC1_RESET);
 	writel(0, devpriv->las0 + LAS0_DAC2_RESET);
 	/* clear digital IO fifo */
-	devpriv->dioStatus = 0;
-	writew(devpriv->dioStatus, devpriv->las0 + LAS0_DIO_STATUS);
-	devpriv->utcCtrl[0] = (0 << 6) | 0x30;
-	devpriv->utcCtrl[1] = (1 << 6) | 0x30;
-	devpriv->utcCtrl[2] = (2 << 6) | 0x30;
-	devpriv->utcCtrl[3] = (3 << 6) | 0x00;
-	writeb(devpriv->utcCtrl[0], devpriv->las0 + LAS0_UTC_CTRL);
-	writeb(devpriv->utcCtrl[1], devpriv->las0 + LAS0_UTC_CTRL);
-	writeb(devpriv->utcCtrl[2], devpriv->las0 + LAS0_UTC_CTRL);
-	writeb(devpriv->utcCtrl[3], devpriv->las0 + LAS0_UTC_CTRL);
+	writew(0, devpriv->las0 + LAS0_DIO_STATUS);
+	writeb((0 << 6) | 0x30, devpriv->las0 + LAS0_UTC_CTRL);
+	writeb((1 << 6) | 0x30, devpriv->las0 + LAS0_UTC_CTRL);
+	writeb((2 << 6) | 0x30, devpriv->las0 + LAS0_UTC_CTRL);
+	writeb((3 << 6) | 0x00, devpriv->las0 + LAS0_UTC_CTRL);
 	/* TODO: set user out source ??? */
 }
 
@@ -1259,51 +1326,34 @@ static void rtd_pci_latency_quirk(struct comedi_device *dev,
 	}
 }
 
-static const void *rtd_find_boardinfo(struct comedi_device *dev,
-				      struct pci_dev *pcidev)
-{
-	const struct rtdBoard *thisboard;
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(rtd520Boards); i++) {
-		thisboard = &rtd520Boards[i];
-		if (pcidev->device == thisboard->device_id)
-			return thisboard;
-	}
-	return NULL;
-}
-
 static int rtd_auto_attach(struct comedi_device *dev,
-				     unsigned long context_unused)
+			   unsigned long context)
 {
 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-	const struct rtdBoard *thisboard;
-	struct rtdPrivate *devpriv;
+	const struct rtd_boardinfo *board = NULL;
+	struct rtd_private *devpriv;
 	struct comedi_subdevice *s;
 	int ret;
 
-	thisboard = rtd_find_boardinfo(dev, pcidev);
-	if (!thisboard)
+	if (context < ARRAY_SIZE(rtd520Boards))
+		board = &rtd520Boards[context];
+	if (!board)
 		return -ENODEV;
-	dev->board_ptr = thisboard;
-	dev->board_name = thisboard->name;
+	dev->board_ptr = board;
+	dev->board_name = board->name;
 
 	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
 	if (!devpriv)
 		return -ENOMEM;
 	dev->private = devpriv;
 
-	ret = comedi_pci_enable(pcidev, dev->board_name);
+	ret = comedi_pci_enable(dev);
 	if (ret)
 		return ret;
-	dev->iobase = 1;	/* the "detach" needs this */
-
-	devpriv->las0 = ioremap_nocache(pci_resource_start(pcidev, 2),
-					pci_resource_len(pcidev, 2));
-	devpriv->las1 = ioremap_nocache(pci_resource_start(pcidev, 3),
-					pci_resource_len(pcidev, 3));
-	devpriv->lcfg = ioremap_nocache(pci_resource_start(pcidev, 0),
-					pci_resource_len(pcidev, 0));
+
+	devpriv->las0 = pci_ioremap_bar(pcidev, 2);
+	devpriv->las1 = pci_ioremap_bar(pcidev, 3);
+	devpriv->lcfg = pci_ioremap_bar(pcidev, 0);
 	if (!devpriv->las0 || !devpriv->las1 || !devpriv->lcfg)
 		return -ENOMEM;
 
@@ -1326,7 +1376,7 @@ static int rtd_auto_attach(struct comedi_device *dev,
 	s->subdev_flags	= SDF_READABLE | SDF_GROUND | SDF_COMMON | SDF_DIFF;
 	s->n_chan	= 16;
 	s->maxdata	= 0x0fff;
-	s->range_table	= thisboard->ai_range;
+	s->range_table	= board->ai_range;
 	s->len_chanlist	= RTD_MAX_CHANLIST;
 	s->insn_read	= rtd_ai_rinsn;
 	if (dev->irq) {
@@ -1370,10 +1420,10 @@ static int rtd_auto_attach(struct comedi_device *dev,
 	ret = rtd520_probe_fifo_depth(dev);
 	if (ret < 0)
 		return ret;
-	devpriv->fifoLen = ret;
+	devpriv->fifosz = ret;
 
 	if (dev->irq)
-		writel(ICS_PIE | ICS_PLIE, devpriv->lcfg + LCFG_ITCSR);
+		writel(ICS_PIE | ICS_PLIE, devpriv->lcfg + PLX_INTRCS_REG);
 
 	dev_info(dev->class_dev, "%s attached\n", dev->board_name);
 
@@ -1382,17 +1432,16 @@ static int rtd_auto_attach(struct comedi_device *dev,
 
 static void rtd_detach(struct comedi_device *dev)
 {
-	struct rtdPrivate *devpriv = dev->private;
-	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+	struct rtd_private *devpriv = dev->private;
 
 	if (devpriv) {
 		/* Shut down any board ops by resetting it */
 		if (devpriv->las0 && devpriv->lcfg)
 			rtd_reset(dev);
 		if (dev->irq) {
-			writel(readl(devpriv->lcfg + LCFG_ITCSR) &
+			writel(readl(devpriv->lcfg + PLX_INTRCS_REG) &
 				~(ICS_PLIE | ICS_DMA0_E | ICS_DMA1_E),
-				devpriv->lcfg + LCFG_ITCSR);
+				devpriv->lcfg + PLX_INTRCS_REG);
 			free_irq(dev->irq, dev);
 		}
 		if (devpriv->las0)
@@ -1402,10 +1451,7 @@ static void rtd_detach(struct comedi_device *dev)
 		if (devpriv->lcfg)
 			iounmap(devpriv->lcfg);
 	}
-	if (pcidev) {
-		if (dev->iobase)
-			comedi_pci_disable(pcidev);
-	}
+	comedi_pci_disable(dev);
 }
 
 static struct comedi_driver rtd520_driver = {
@@ -1416,14 +1462,14 @@ static struct comedi_driver rtd520_driver = {
 };
 
 static int rtd520_pci_probe(struct pci_dev *dev,
-				      const struct pci_device_id *ent)
+			    const struct pci_device_id *id)
 {
-	return comedi_pci_auto_config(dev, &rtd520_driver);
+	return comedi_pci_auto_config(dev, &rtd520_driver, id->driver_data);
 }
 
 static DEFINE_PCI_DEVICE_TABLE(rtd520_pci_table) = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_RTD, 0x7520) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_RTD, 0x4520) },
+	{ PCI_VDEVICE(RTD, 0x7520), BOARD_DM7520 },
+	{ PCI_VDEVICE(RTD, 0x4520), BOARD_PCI4520 },
 	{ 0 }
 };
 MODULE_DEVICE_TABLE(pci, rtd520_pci_table);
diff --git a/drivers/staging/comedi/drivers/rtd520.h b/drivers/staging/comedi/drivers/rtd520.h
deleted file mode 100644
index 25188a5..0000000
--- a/drivers/staging/comedi/drivers/rtd520.h
+++ /dev/null
@@ -1,381 +0,0 @@
-/*
-    comedi/drivers/rtd520.h
-    Comedi driver defines for Real Time Devices (RTD) PCI4520/DM7520
-
-    COMEDI - Linux Control and Measurement Device Interface
-    Copyright (C) 2001 David A. Schleef <ds@schleef.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.
-*/
-
-/*
-    Created by Dan Christian, NASA Ames Research Center.
-    See board notes in rtd520.c
-*/
-
-/*
- * Local Address Space 0 Offsets
- */
-#define LAS0_USER_IO		0x0008	/* User I/O */
-#define LAS0_ADC		0x0010	/* FIFO Status/Software A/D Start */
-#define LAS0_DAC1		0x0014	/* Software D/A1 Update (w) */
-#define LAS0_DAC2		0x0018	/* Software D/A2 Update (w) */
-#define LAS0_DAC		0x0024	/* Software Simultaneous Update (w) */
-#define LAS0_PACER		0x0028	/* Software Pacer Start/Stop */
-#define LAS0_TIMER		0x002c	/* Timer Status/HDIN Software Trig. */
-#define LAS0_IT			0x0030	/* Interrupt Status/Enable */
-#define LAS0_CLEAR		0x0034	/* Clear/Set Interrupt Clear Mask */
-#define LAS0_OVERRUN		0x0038	/* Pending interrupts/Clear Overrun */
-#define LAS0_PCLK		0x0040	/* Pacer Clock (24bit) */
-#define LAS0_BCLK		0x0044	/* Burst Clock (10bit) */
-#define LAS0_ADC_SCNT		0x0048	/* A/D Sample counter (10bit) */
-#define LAS0_DAC1_UCNT		0x004c	/* D/A1 Update counter (10 bit) */
-#define LAS0_DAC2_UCNT		0x0050	/* D/A2 Update counter (10 bit) */
-#define LAS0_DCNT		0x0054	/* Delay counter (16 bit) */
-#define LAS0_ACNT		0x0058	/* About counter (16 bit) */
-#define LAS0_DAC_CLK		0x005c	/* DAC clock (16bit) */
-#define LAS0_UTC0		0x0060	/* 8254 TC Counter 0 */
-#define LAS0_UTC1		0x0064	/* 8254 TC Counter 1 */
-#define LAS0_UTC2		0x0068	/* 8254 TC Counter 2 */
-#define LAS0_UTC_CTRL		0x006c	/* 8254 TC Control */
-#define LAS0_DIO0		0x0070	/* Digital I/O Port 0 */
-#define LAS0_DIO1		0x0074	/* Digital I/O Port 1 */
-#define LAS0_DIO0_CTRL		0x0078	/* Digital I/O Control */
-#define LAS0_DIO_STATUS		0x007c	/* Digital I/O Status */
-#define LAS0_BOARD_RESET	0x0100	/* Board reset */
-#define LAS0_DMA0_SRC		0x0104	/* DMA 0 Sources select */
-#define LAS0_DMA1_SRC		0x0108	/* DMA 1 Sources select */
-#define LAS0_ADC_CONVERSION	0x010c	/* A/D Conversion Signal select */
-#define LAS0_BURST_START	0x0110	/* Burst Clock Start Trigger select */
-#define LAS0_PACER_START	0x0114	/* Pacer Clock Start Trigger select */
-#define LAS0_PACER_STOP		0x0118	/* Pacer Clock Stop Trigger select */
-#define LAS0_ACNT_STOP_ENABLE	0x011c	/* About Counter Stop Enable */
-#define LAS0_PACER_REPEAT	0x0120	/* Pacer Start Trigger Mode select */
-#define LAS0_DIN_START		0x0124	/* HiSpd DI Sampling Signal select */
-#define LAS0_DIN_FIFO_CLEAR	0x0128	/* Digital Input FIFO Clear */
-#define LAS0_ADC_FIFO_CLEAR	0x012c	/* A/D FIFO Clear */
-#define LAS0_CGT_WRITE		0x0130	/* Channel Gain Table Write */
-#define LAS0_CGL_WRITE		0x0134	/* Channel Gain Latch Write */
-#define LAS0_CG_DATA		0x0138	/* Digital Table Write */
-#define LAS0_CGT_ENABLE		0x013c	/* Channel Gain Table Enable */
-#define LAS0_CG_ENABLE		0x0140	/* Digital Table Enable */
-#define LAS0_CGT_PAUSE		0x0144	/* Table Pause Enable */
-#define LAS0_CGT_RESET		0x0148	/* Reset Channel Gain Table */
-#define LAS0_CGT_CLEAR		0x014c	/* Clear Channel Gain Table */
-#define LAS0_DAC1_CTRL		0x0150	/* D/A1 output type/range */
-#define LAS0_DAC1_SRC		0x0154	/* D/A1 update source */
-#define LAS0_DAC1_CYCLE		0x0158	/* D/A1 cycle mode */
-#define LAS0_DAC1_RESET		0x015c	/* D/A1 FIFO reset */
-#define LAS0_DAC1_FIFO_CLEAR	0x0160	/* D/A1 FIFO clear */
-#define LAS0_DAC2_CTRL		0x0164	/* D/A2 output type/range */
-#define LAS0_DAC2_SRC		0x0168	/* D/A2 update source */
-#define LAS0_DAC2_CYCLE		0x016c	/* D/A2 cycle mode */
-#define LAS0_DAC2_RESET		0x0170	/* D/A2 FIFO reset */
-#define LAS0_DAC2_FIFO_CLEAR	0x0174	/* D/A2 FIFO clear */
-#define LAS0_ADC_SCNT_SRC	0x0178	/* A/D Sample Counter Source select */
-#define LAS0_PACER_SELECT	0x0180	/* Pacer Clock select */
-#define LAS0_SBUS0_SRC		0x0184	/* SyncBus 0 Source select */
-#define LAS0_SBUS0_ENABLE	0x0188	/* SyncBus 0 enable */
-#define LAS0_SBUS1_SRC		0x018c	/* SyncBus 1 Source select */
-#define LAS0_SBUS1_ENABLE	0x0190	/* SyncBus 1 enable */
-#define LAS0_SBUS2_SRC		0x0198	/* SyncBus 2 Source select */
-#define LAS0_SBUS2_ENABLE	0x019c	/* SyncBus 2 enable */
-#define LAS0_ETRG_POLARITY	0x01a4	/* Ext. Trigger polarity select */
-#define LAS0_EINT_POLARITY	0x01a8	/* Ext. Interrupt polarity select */
-#define LAS0_UTC0_CLOCK		0x01ac	/* UTC0 Clock select */
-#define LAS0_UTC0_GATE		0x01b0	/* UTC0 Gate select */
-#define LAS0_UTC1_CLOCK		0x01b4	/* UTC1 Clock select */
-#define LAS0_UTC1_GATE		0x01b8	/* UTC1 Gate select */
-#define LAS0_UTC2_CLOCK		0x01bc	/* UTC2 Clock select */
-#define LAS0_UTC2_GATE		0x01c0	/* UTC2 Gate select */
-#define LAS0_UOUT0_SELECT	0x01c4	/* User Output 0 source select */
-#define LAS0_UOUT1_SELECT	0x01c8	/* User Output 1 source select */
-#define LAS0_DMA0_RESET		0x01cc	/* DMA0 Request state machine reset */
-#define LAS0_DMA1_RESET		0x01d0	/* DMA1 Request state machine reset */
-
-/*
- * Local Address Space 1 Offsets
- */
-#define LAS1_ADC_FIFO		0x0000	/* A/D FIFO (16bit) */
-#define LAS1_HDIO_FIFO		0x0004	/* HiSpd DI FIFO (16bit) */
-#define LAS1_DAC1_FIFO		0x0008	/* D/A1 FIFO (16bit) */
-#define LAS1_DAC2_FIFO		0x000c	/* D/A2 FIFO (16bit) */
-
-/*
- * PLX 9080 local config & runtime registers
- */
-#define LCFG_ITCSR		0x0068	/* Interrupt Control/Status */
-#define LCFG_DMAMODE0		0x0080	/* DMA0 Mode */
-#define LCFG_DMAPADR0		0x0084	/* DMA0 PCI Address */
-#define LCFG_DMALADR0		0x0088	/* DMA0 Local Address */
-#define LCFG_DMASIZ0		0x008c	/* DMA0 Transfer Size (Bytes) */
-#define LCFG_DMADPR0		0x0090	/* DMA0 Descriptor Pointer */
-#define LCFG_DMAMODE1		0x0094	/* DMA1 Mode */
-#define LCFG_DMAPADR1		0x0098	/* DMA1 PCI Address */
-#define LCFG_DMALADR1		0x009c	/* DMA1 Local Address */
-#define LCFG_DMASIZ1		0x00a0	/* DMA1 Transfer Size (Bytes) */
-#define LCFG_DMADPR1		0x00a4	/* DMA1 Descriptor Pointer */
-#define LCFG_DMACSR0		0x00a8	/* DMA0 Command/Status */
-#define LCFG_DMACSR1		0x00a9	/* DMA0 Command/Status */
-#define LCFG_DMAARB		0x00ac	/* DMA Arbitration */
-#define LCFG_DMATHR		0x00b0	/* DMA Threshold */
-
-/*  FIFO Status Word Bits (RtdFifoStatus) */
-#define FS_DAC1_NOT_EMPTY	(1 << 0)  /* DAC1 FIFO not empty */
-#define FS_DAC1_HEMPTY		(1 << 1)  /* DAC1 FIFO half empty */
-#define FS_DAC1_NOT_FULL	(1 << 2)  /* DAC1 FIFO not full */
-#define FS_DAC2_NOT_EMPTY	(1 << 4)  /* DAC2 FIFO not empty */
-#define FS_DAC2_HEMPTY		(1 << 5)  /* DAC2 FIFO half empty */
-#define FS_DAC2_NOT_FULL	(1 << 6)  /* DAC2 FIFO not full */
-#define FS_ADC_NOT_EMPTY	(1 << 8)  /* ADC FIFO not empty */
-#define FS_ADC_HEMPTY		(1 << 9)  /* ADC FIFO half empty */
-#define FS_ADC_NOT_FULL		(1 << 10) /* ADC FIFO not full */
-#define FS_DIN_NOT_EMPTY	(1 << 12) /* DIN FIFO not empty */
-#define FS_DIN_HEMPTY		(1 << 13) /* DIN FIFO half empty */
-#define FS_DIN_NOT_FULL		(1 << 14) /* DIN FIFO not full */
-
-/*  Timer Status Word Bits (GetTimerStatus) */
-#define TS_PCLK_GATE		(1 << 0)  /* Pacer Clock Gate enabled */
-#define TS_BCLK_GATE		(1 << 1)  /* Burst Clock Gate running */
-#define TS_DCNT_GATE		(1 << 2)  /* Pacer Clock Delayed Start Trig. */
-#define TS_ACNT_GATE		(1 << 3)  /* Pacer Clock About Trig. */
-#define TS_PCLK_RUN		(1 << 4)  /* Pacer Clock Shutdown Flag */
-
-/*  External Trigger polarity select */
-/*  External Interrupt polarity select */
-#define POL_POSITIVE         0x0	/*  positive edge */
-#define POL_NEGATIVE         0x1	/*  negative edge */
-
-/*  User Output Signal select (SetUout0Source, SetUout1Source) */
-#define UOUT_ADC                0x0	/*  A/D Conversion Signal */
-#define UOUT_DAC1               0x1	/*  D/A1 Update */
-#define UOUT_DAC2               0x2	/*  D/A2 Update */
-#define UOUT_SOFTWARE           0x3	/*  Software Programmable */
-
-/*  Pacer clock select (SetPacerSource) */
-#define PCLK_INTERNAL           1	/*  Internal Pacer Clock */
-#define PCLK_EXTERNAL           0	/*  External Pacer Clock */
-
-/*  A/D Sample Counter Sources (SetAdcntSource, SetupSampleCounter) */
-#define ADC_SCNT_CGT_RESET         0x0	/*  needs restart with StartPacer */
-#define ADC_SCNT_FIFO_WRITE        0x1
-
-/*  A/D Conversion Signal Select (for SetConversionSelect) */
-#define ADC_START_SOFTWARE         0x0	/*  Software A/D Start */
-#define ADC_START_PCLK             0x1	/*  Pacer Clock (Ext. Int. see Func.509) */
-#define ADC_START_BCLK             0x2	/*  Burst Clock */
-#define ADC_START_DIGITAL_IT       0x3	/*  Digital Interrupt */
-#define ADC_START_DAC1_MARKER1     0x4	/*  D/A 1 Data Marker 1 */
-#define ADC_START_DAC2_MARKER1     0x5	/*  D/A 2 Data Marker 1 */
-#define ADC_START_SBUS0            0x6	/*  SyncBus 0 */
-#define ADC_START_SBUS1            0x7	/*  SyncBus 1 */
-#define ADC_START_SBUS2            0x8	/*  SyncBus 2 */
-
-/*  Burst Clock start trigger select (SetBurstStart) */
-#define BCLK_START_SOFTWARE        0x0	/*  Software A/D Start (StartBurst) */
-#define BCLK_START_PCLK            0x1	/*  Pacer Clock */
-#define BCLK_START_ETRIG           0x2	/*  External Trigger */
-#define BCLK_START_DIGITAL_IT      0x3	/*  Digital Interrupt */
-#define BCLK_START_SBUS0           0x4	/*  SyncBus 0 */
-#define BCLK_START_SBUS1           0x5	/*  SyncBus 1 */
-#define BCLK_START_SBUS2           0x6	/*  SyncBus 2 */
-
-/*  Pacer Clock start trigger select (SetPacerStart) */
-#define PCLK_START_SOFTWARE        0x0	/*  Software Pacer Start (StartPacer) */
-#define PCLK_START_ETRIG           0x1	/*  External trigger */
-#define PCLK_START_DIGITAL_IT      0x2	/*  Digital interrupt */
-#define PCLK_START_UTC2            0x3	/*  User TC 2 out */
-#define PCLK_START_SBUS0           0x4	/*  SyncBus 0 */
-#define PCLK_START_SBUS1           0x5	/*  SyncBus 1 */
-#define PCLK_START_SBUS2           0x6	/*  SyncBus 2 */
-#define PCLK_START_D_SOFTWARE      0x8	/*  Delayed Software Pacer Start */
-#define PCLK_START_D_ETRIG         0x9	/*  Delayed external trigger */
-#define PCLK_START_D_DIGITAL_IT    0xA	/*  Delayed digital interrupt */
-#define PCLK_START_D_UTC2          0xB	/*  Delayed User TC 2 out */
-#define PCLK_START_D_SBUS0         0xC	/*  Delayed SyncBus 0 */
-#define PCLK_START_D_SBUS1         0xD	/*  Delayed SyncBus 1 */
-#define PCLK_START_D_SBUS2         0xE	/*  Delayed SyncBus 2 */
-#define PCLK_START_ETRIG_GATED     0xF	/*  External Trigger Gated controlled mode */
-
-/*  Pacer Clock Stop Trigger select (SetPacerStop) */
-#define PCLK_STOP_SOFTWARE         0x0	/*  Software Pacer Stop (StopPacer) */
-#define PCLK_STOP_ETRIG            0x1	/*  External Trigger */
-#define PCLK_STOP_DIGITAL_IT       0x2	/*  Digital Interrupt */
-#define PCLK_STOP_ACNT             0x3	/*  About Counter */
-#define PCLK_STOP_UTC2             0x4	/*  User TC2 out */
-#define PCLK_STOP_SBUS0            0x5	/*  SyncBus 0 */
-#define PCLK_STOP_SBUS1            0x6	/*  SyncBus 1 */
-#define PCLK_STOP_SBUS2            0x7	/*  SyncBus 2 */
-#define PCLK_STOP_A_SOFTWARE       0x8	/*  About Software Pacer Stop */
-#define PCLK_STOP_A_ETRIG          0x9	/*  About External Trigger */
-#define PCLK_STOP_A_DIGITAL_IT     0xA	/*  About Digital Interrupt */
-#define PCLK_STOP_A_UTC2           0xC	/*  About User TC2 out */
-#define PCLK_STOP_A_SBUS0          0xD	/*  About SyncBus 0 */
-#define PCLK_STOP_A_SBUS1          0xE	/*  About SyncBus 1 */
-#define PCLK_STOP_A_SBUS2          0xF	/*  About SyncBus 2 */
-
-/*  About Counter Stop Enable */
-#define ACNT_STOP                  0x0	/*  stop enable */
-#define ACNT_NO_STOP               0x1	/*  stop disabled */
-
-/*  DAC update source (SetDAC1Start & SetDAC2Start) */
-#define DAC_START_SOFTWARE         0x0	/*  Software Update */
-#define DAC_START_CGT              0x1	/*  CGT controlled Update */
-#define DAC_START_DAC_CLK          0x2	/*  D/A Clock */
-#define DAC_START_EPCLK            0x3	/*  External Pacer Clock */
-#define DAC_START_SBUS0            0x4	/*  SyncBus 0 */
-#define DAC_START_SBUS1            0x5	/*  SyncBus 1 */
-#define DAC_START_SBUS2            0x6	/*  SyncBus 2 */
-
-/*  DAC Cycle Mode (SetDAC1Cycle, SetDAC2Cycle, SetupDAC) */
-#define DAC_CYCLE_SINGLE           0x0	/*  not cycle */
-#define DAC_CYCLE_MULTI            0x1	/*  cycle */
-
-/*  8254 Operation Modes (Set8254Mode, SetupTimerCounter) */
-#define M8254_EVENT_COUNTER        0	/*  Event Counter */
-#define M8254_HW_ONE_SHOT          1	/*  Hardware-Retriggerable One-Shot */
-#define M8254_RATE_GENERATOR       2	/*  Rate Generator */
-#define M8254_SQUARE_WAVE          3	/*  Square Wave Mode */
-#define M8254_SW_STROBE            4	/*  Software Triggered Strobe */
-#define M8254_HW_STROBE            5	/*  Hardware Triggered Strobe (Retriggerable) */
-
-/*  User Timer/Counter 0 Clock Select (SetUtc0Clock) */
-#define CUTC0_8MHZ                 0x0	/*  8MHz */
-#define CUTC0_EXT_TC_CLOCK1        0x1	/*  Ext. TC Clock 1 */
-#define CUTC0_EXT_TC_CLOCK2        0x2	/*  Ext. TC Clock 2 */
-#define CUTC0_EXT_PCLK             0x3	/*  Ext. Pacer Clock */
-
-/*  User Timer/Counter 1 Clock Select (SetUtc1Clock) */
-#define CUTC1_8MHZ                 0x0	/*  8MHz */
-#define CUTC1_EXT_TC_CLOCK1        0x1	/*  Ext. TC Clock 1 */
-#define CUTC1_EXT_TC_CLOCK2        0x2	/*  Ext. TC Clock 2 */
-#define CUTC1_EXT_PCLK             0x3	/*  Ext. Pacer Clock */
-#define CUTC1_UTC0_OUT             0x4	/*  User Timer/Counter 0 out */
-#define CUTC1_DIN_SIGNAL           0x5	/*  High-Speed Digital Input   Sampling signal */
-
-/*  User Timer/Counter 2 Clock Select (SetUtc2Clock) */
-#define CUTC2_8MHZ                 0x0	/*  8MHz */
-#define CUTC2_EXT_TC_CLOCK1        0x1	/*  Ext. TC Clock 1 */
-#define CUTC2_EXT_TC_CLOCK2        0x2	/*  Ext. TC Clock 2 */
-#define CUTC2_EXT_PCLK             0x3	/*  Ext. Pacer Clock */
-#define CUTC2_UTC1_OUT             0x4	/*  User Timer/Counter 1 out */
-
-/*  User Timer/Counter 0 Gate Select (SetUtc0Gate) */
-#define GUTC0_NOT_GATED            0x0	/*  Not gated */
-#define GUTC0_GATED                0x1	/*  Gated */
-#define GUTC0_EXT_TC_GATE1         0x2	/*  Ext. TC Gate 1 */
-#define GUTC0_EXT_TC_GATE2         0x3	/*  Ext. TC Gate 2 */
-
-/*  User Timer/Counter 1 Gate Select (SetUtc1Gate) */
-#define GUTC1_NOT_GATED            0x0	/*  Not gated */
-#define GUTC1_GATED                0x1	/*  Gated */
-#define GUTC1_EXT_TC_GATE1         0x2	/*  Ext. TC Gate 1 */
-#define GUTC1_EXT_TC_GATE2         0x3	/*  Ext. TC Gate 2 */
-#define GUTC1_UTC0_OUT             0x4	/*  User Timer/Counter 0 out */
-
-/*  User Timer/Counter 2 Gate Select (SetUtc2Gate) */
-#define GUTC2_NOT_GATED            0x0	/*  Not gated */
-#define GUTC2_GATED                0x1	/*  Gated */
-#define GUTC2_EXT_TC_GATE1         0x2	/*  Ext. TC Gate 1 */
-#define GUTC2_EXT_TC_GATE2         0x3	/*  Ext. TC Gate 2 */
-#define GUTC2_UTC1_OUT             0x4	/*  User Timer/Counter 1 out */
-
-/*  Interrupt Source Masks (SetITMask, ClearITMask, GetITStatus) */
-#define IRQM_ADC_FIFO_WRITE        0x0001	/*  ADC FIFO Write */
-#define IRQM_CGT_RESET             0x0002	/*  Reset CGT */
-#define IRQM_CGT_PAUSE             0x0008	/*  Pause CGT */
-#define IRQM_ADC_ABOUT_CNT         0x0010	/*  About Counter out */
-#define IRQM_ADC_DELAY_CNT         0x0020	/*  Delay Counter out */
-#define IRQM_ADC_SAMPLE_CNT	   0x0040	/*  ADC Sample Counter */
-#define IRQM_DAC1_UCNT             0x0080	/*  DAC1 Update Counter */
-#define IRQM_DAC2_UCNT             0x0100	/*  DAC2 Update Counter */
-#define IRQM_UTC1                  0x0200	/*  User TC1 out */
-#define IRQM_UTC1_INV              0x0400	/*  User TC1 out, inverted */
-#define IRQM_UTC2                  0x0800	/*  User TC2 out */
-#define IRQM_DIGITAL_IT            0x1000	/*  Digital Interrupt */
-#define IRQM_EXTERNAL_IT           0x2000	/*  External Interrupt */
-#define IRQM_ETRIG_RISING          0x4000	/*  External Trigger rising-edge */
-#define IRQM_ETRIG_FALLING         0x8000	/*  External Trigger falling-edge */
-
-/*  DMA Request Sources (LAS0) */
-#define DMAS_DISABLED              0x0	/*  DMA Disabled */
-#define DMAS_ADC_SCNT              0x1	/*  ADC Sample Counter */
-#define DMAS_DAC1_UCNT             0x2	/*  D/A1 Update Counter */
-#define DMAS_DAC2_UCNT             0x3	/*  D/A2 Update Counter */
-#define DMAS_UTC1                  0x4	/*  User TC1 out */
-#define DMAS_ADFIFO_HALF_FULL      0x8	/*  A/D FIFO half full */
-#define DMAS_DAC1_FIFO_HALF_EMPTY  0x9	/*  D/A1 FIFO half empty */
-#define DMAS_DAC2_FIFO_HALF_EMPTY  0xA	/*  D/A2 FIFO half empty */
-
-/*  DMA Local Addresses   (0x40000000+LAS1 offset) */
-#define DMALADDR_ADC       0x40000000	/*  A/D FIFO */
-#define DMALADDR_HDIN      0x40000004	/*  High Speed Digital Input FIFO */
-#define DMALADDR_DAC1      0x40000008	/*  D/A1 FIFO */
-#define DMALADDR_DAC2      0x4000000C	/*  D/A2 FIFO */
-
-/*  Port 0 compare modes (SetDIO0CompareMode) */
-#define DIO_MODE_EVENT     0	/*  Event Mode */
-#define DIO_MODE_MATCH     1	/*  Match Mode */
-
-/*  Digital Table Enable (Port 1 disable) */
-#define DTBL_DISABLE       0	/*  Enable Digital Table */
-#define DTBL_ENABLE        1	/*  Disable Digital Table */
-
-/*  Sampling Signal for High Speed Digital Input (SetHdinStart) */
-#define HDIN_SOFTWARE      0x0	/*  Software Trigger */
-#define HDIN_ADC           0x1	/*  A/D Conversion Signal */
-#define HDIN_UTC0          0x2	/*  User TC out 0 */
-#define HDIN_UTC1          0x3	/*  User TC out 1 */
-#define HDIN_UTC2          0x4	/*  User TC out 2 */
-#define HDIN_EPCLK         0x5	/*  External Pacer Clock */
-#define HDIN_ETRG          0x6	/*  External Trigger */
-
-/*  Channel Gain Table / Channel Gain Latch */
-#define CSC_LATCH          0	/*  Channel Gain Latch mode */
-#define CSC_CGT            1	/*  Channel Gain Table mode */
-
-/*  Channel Gain Table Pause Enable */
-#define CGT_PAUSE_DISABLE  0	/*  Channel Gain Table Pause Disable */
-#define CGT_PAUSE_ENABLE   1	/*  Channel Gain Table Pause Enable */
-
-/*  DAC output type/range (p63) */
-#define AOUT_UNIP5         0	/*  0..+5 Volt */
-#define AOUT_UNIP10        1	/*  0..+10 Volt */
-#define AOUT_BIP5          2	/*  -5..+5 Volt */
-#define AOUT_BIP10         3	/*  -10..+10 Volt */
-
-/*  Ghannel Gain Table field definitions (p61) */
-/*  Gain */
-#define GAIN1              0
-#define GAIN2              1
-#define GAIN4              2
-#define GAIN8              3
-#define GAIN16             4
-#define GAIN32             5
-#define GAIN64             6
-#define GAIN128            7
-
-/*  Input range/polarity */
-#define AIN_BIP5           0	/*  -5..+5 Volt */
-#define AIN_BIP10          1	/*  -10..+10 Volt */
-#define AIN_UNIP10         2	/*  0..+10 Volt */
-
-/*  non referenced single ended select bit */
-#define NRSE_AGND          0	/*  AGND referenced SE input */
-#define NRSE_AINS          1	/*  AIN SENSE referenced SE input */
-
-/*  single ended vs differential */
-#define GND_SE		0	/*  Single-Ended */
-#define GND_DIFF	1	/*  Differential */
diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c
index 71a73ec..02f9406 100644
--- a/drivers/staging/comedi/drivers/s626.c
+++ b/drivers/staging/comedi/drivers/s626.c
@@ -80,7 +80,7 @@ INSN_CONFIG instructions:
 #define PCI_SUBDEVICE_ID_S626 0x0272
 
 struct s626_private {
-	void __iomem *base_addr;
+	void __iomem *mmio;
 	uint8_t ai_cmd_running;	/*  ai_cmd is running */
 	uint8_t ai_continous;	/*  continous acquisition */
 	int ai_sample_count;	/*  number of samples to acquire */
@@ -106,64 +106,6 @@ struct s626_private {
 	unsigned int ao_readback[S626_DAC_CHANNELS];
 };
 
-struct dio_private {
-	uint16_t RDDIn;
-	uint16_t WRDOut;
-	uint16_t RDEdgSel;
-	uint16_t WREdgSel;
-	uint16_t RDCapSel;
-	uint16_t WRCapSel;
-	uint16_t RDCapFlg;
-	uint16_t RDIntSel;
-	uint16_t WRIntSel;
-};
-
-static struct dio_private dio_private_A = {
-	.RDDIn = LP_RDDINA,
-	.WRDOut = LP_WRDOUTA,
-	.RDEdgSel = LP_RDEDGSELA,
-	.WREdgSel = LP_WREDGSELA,
-	.RDCapSel = LP_RDCAPSELA,
-	.WRCapSel = LP_WRCAPSELA,
-	.RDCapFlg = LP_RDCAPFLGA,
-	.RDIntSel = LP_RDINTSELA,
-	.WRIntSel = LP_WRINTSELA,
-};
-
-static struct dio_private dio_private_B = {
-	.RDDIn = LP_RDDINB,
-	.WRDOut = LP_WRDOUTB,
-	.RDEdgSel = LP_RDEDGSELB,
-	.WREdgSel = LP_WREDGSELB,
-	.RDCapSel = LP_RDCAPSELB,
-	.WRCapSel = LP_WRCAPSELB,
-	.RDCapFlg = LP_RDCAPFLGB,
-	.RDIntSel = LP_RDINTSELB,
-	.WRIntSel = LP_WRINTSELB,
-};
-
-static struct dio_private dio_private_C = {
-	.RDDIn = LP_RDDINC,
-	.WRDOut = LP_WRDOUTC,
-	.RDEdgSel = LP_RDEDGSELC,
-	.WREdgSel = LP_WREDGSELC,
-	.RDCapSel = LP_RDCAPSELC,
-	.WRCapSel = LP_WRCAPSELC,
-	.RDCapFlg = LP_RDCAPFLGC,
-	.RDIntSel = LP_RDINTSELC,
-	.WRIntSel = LP_WRINTSELC,
-};
-
-/* to group dio devices (48 bits mask and data are not allowed ???)
-static struct dio_private *dio_private_word[]={
-  &dio_private_A,
-  &dio_private_B,
-  &dio_private_C,
-};
-*/
-
-#define diopriv ((struct dio_private *)s->private)
-
 /*  COUNTER OBJECT ------------------------------------------------ */
 struct enc_private {
 	/*  Pointers to functions that differ for A and B counters: */
@@ -195,37 +137,53 @@ struct enc_private {
 /*  Translation table to map IntSrc into equivalent RDMISC2 event flag  bits. */
 /* static const uint16_t EventBits[][4] = { EVBITS(0), EVBITS(1), EVBITS(2), EVBITS(3), EVBITS(4), EVBITS(5) }; */
 
-/*  enab/disable a function or test status bit(s) that are accessed */
-/*  through Main Control Registers 1 or 2. */
-#define MC_ENABLE(REGADRS, CTRLWORD)	writel(((uint32_t)(CTRLWORD) << 16) | (uint32_t)(CTRLWORD), devpriv->base_addr+(REGADRS))
+/*
+ * Enable/disable a function or test status bit(s) that are accessed
+ * through Main Control Registers 1 or 2.
+ */
+static void s626_mc_enable(struct comedi_device *dev,
+			   unsigned int cmd, unsigned int reg)
+{
+	struct s626_private *devpriv = dev->private;
+	unsigned int val = (cmd << 16) | cmd;
 
-#define MC_DISABLE(REGADRS, CTRLWORD)	writel((uint32_t)(CTRLWORD) << 16 , devpriv->base_addr+(REGADRS))
+	writel(val, devpriv->mmio + reg);
+}
 
-#define MC_TEST(REGADRS, CTRLWORD)	((readl(devpriv->base_addr+(REGADRS)) & CTRLWORD) != 0)
+static void s626_mc_disable(struct comedi_device *dev,
+			    unsigned int cmd, unsigned int reg)
+{
+	struct s626_private *devpriv = dev->private;
 
-/* #define WR7146(REGARDS,CTRLWORD)
-    writel(CTRLWORD,(uint32_t)(devpriv->base_addr+(REGARDS))) */
-#define WR7146(REGARDS, CTRLWORD) writel(CTRLWORD, devpriv->base_addr+(REGARDS))
+	writel(cmd << 16 , devpriv->mmio + reg);
+}
 
-/* #define RR7146(REGARDS)
-    readl((uint32_t)(devpriv->base_addr+(REGARDS))) */
-#define RR7146(REGARDS)		readl(devpriv->base_addr+(REGARDS))
+static bool s626_mc_test(struct comedi_device *dev,
+			 unsigned int cmd, unsigned int reg)
+{
+	struct s626_private *devpriv = dev->private;
+	unsigned int val;
+
+	val = readl(devpriv->mmio + reg);
+
+	return (val & cmd) ? true : false;
+}
 
 #define BUGFIX_STREG(REGADRS)   (REGADRS - 4)
 
 /*  Write a time slot control record to TSL2. */
 #define VECTPORT(VECTNUM)		(P_TSL2 + ((VECTNUM) << 2))
-#define SETVECT(VECTNUM, VECTVAL)	WR7146(VECTPORT(VECTNUM), (VECTVAL))
 
 /*  Code macros used for constructing I2C command bytes. */
 #define I2C_B2(ATTR, VAL)	(((ATTR) << 6) | ((VAL) << 24))
 #define I2C_B1(ATTR, VAL)	(((ATTR) << 4) | ((VAL) << 16))
 #define I2C_B0(ATTR, VAL)	(((ATTR) << 2) | ((VAL) <<  8))
 
-static const struct comedi_lrange s626_range_table = { 2, {
-							   RANGE(-5, 5),
-							   RANGE(-10, 10),
-							   }
+static const struct comedi_lrange s626_range_table = {
+	2, {
+		BIP_RANGE(5),
+		BIP_RANGE(10),
+	}
 };
 
 /*  Execute a DEBI transfer.  This must be called from within a */
@@ -234,16 +192,18 @@ static void DEBItransfer(struct comedi_device *dev)
 {
 	struct s626_private *devpriv = dev->private;
 
-	/*  Initiate upload of shadow RAM to DEBI control register. */
-	MC_ENABLE(P_MC2, MC2_UPLD_DEBI);
+	/* Initiate upload of shadow RAM to DEBI control register */
+	s626_mc_enable(dev, MC2_UPLD_DEBI, P_MC2);
 
-	/*  Wait for completion of upload from shadow RAM to DEBI control */
-	/*  register. */
-	while (!MC_TEST(P_MC2, MC2_UPLD_DEBI))
+	/*
+	 * Wait for completion of upload from shadow RAM to
+	 * DEBI control register.
+	 */
+	while (!s626_mc_test(dev, MC2_UPLD_DEBI, P_MC2))
 		;
 
-	/*  Wait until DEBI transfer is done. */
-	while (RR7146(P_PSR) & PSR_DEBI_S)
+	/* Wait until DEBI transfer is done */
+	while (readl(devpriv->mmio + P_PSR) & PSR_DEBI_S)
 		;
 }
 
@@ -252,19 +212,14 @@ static void DEBItransfer(struct comedi_device *dev)
 static uint16_t DEBIread(struct comedi_device *dev, uint16_t addr)
 {
 	struct s626_private *devpriv = dev->private;
-	uint16_t retval;
 
-	/*  Set up DEBI control register value in shadow RAM. */
-	WR7146(P_DEBICMD, DEBI_CMD_RDWORD | addr);
+	/* Set up DEBI control register value in shadow RAM */
+	writel(DEBI_CMD_RDWORD | addr, devpriv->mmio + P_DEBICMD);
 
 	/*  Execute the DEBI transfer. */
 	DEBItransfer(dev);
 
-	/*  Fetch target register value. */
-	retval = (uint16_t) RR7146(P_DEBIAD);
-
-	/*  Return register value. */
-	return retval;
+	return readl(devpriv->mmio + P_DEBIAD);
 }
 
 /*  Write a value to a gate array register. */
@@ -272,9 +227,9 @@ static void DEBIwrite(struct comedi_device *dev, uint16_t addr, uint16_t wdata)
 {
 	struct s626_private *devpriv = dev->private;
 
-	/*  Set up DEBI control register value in shadow RAM. */
-	WR7146(P_DEBICMD, DEBI_CMD_WRWORD | addr);
-	WR7146(P_DEBIAD, wdata);
+	/* Set up DEBI control register value in shadow RAM */
+	writel(DEBI_CMD_WRWORD | addr, devpriv->mmio + P_DEBICMD);
+	writel(wdata, devpriv->mmio + P_DEBIAD);
 
 	/*  Execute the DEBI transfer. */
 	DEBItransfer(dev);
@@ -284,23 +239,22 @@ static void DEBIwrite(struct comedi_device *dev, uint16_t addr, uint16_t wdata)
  * specifies bits that are to be preserved, wdata is new value to be
  * or'd with the masked original.
  */
-static void DEBIreplace(struct comedi_device *dev, uint16_t addr, uint16_t mask,
-			uint16_t wdata)
+static void DEBIreplace(struct comedi_device *dev, unsigned int addr,
+			unsigned int mask, unsigned int wdata)
 {
 	struct s626_private *devpriv = dev->private;
+	unsigned int val;
 
-	/*  Copy target gate array register into P_DEBIAD register. */
-	WR7146(P_DEBICMD, DEBI_CMD_RDWORD | addr);
-	/* Set up DEBI control reg value in shadow RAM. */
-	DEBItransfer(dev);	/*  Execute the DEBI Read transfer. */
-
-	/*  Write back the modified image. */
-	WR7146(P_DEBICMD, DEBI_CMD_WRWORD | addr);
-	/* Set up DEBI control reg value in shadow  RAM. */
+	addr &= 0xffff;
+	writel(DEBI_CMD_RDWORD | addr, devpriv->mmio + P_DEBICMD);
+	DEBItransfer(dev);
 
-	WR7146(P_DEBIAD, wdata | ((uint16_t) RR7146(P_DEBIAD) & mask));
-	/* Modify the register image. */
-	DEBItransfer(dev);	/*  Execute the DEBI Write transfer. */
+	writel(DEBI_CMD_WRWORD | addr, devpriv->mmio + P_DEBICMD);
+	val = readl(devpriv->mmio + P_DEBIAD);
+	val &= mask;
+	val |= wdata;
+	writel(val & 0xffff, devpriv->mmio + P_DEBIAD);
+	DEBItransfer(dev);
 }
 
 /* **************  EEPROM ACCESS FUNCTIONS  ************** */
@@ -308,31 +262,32 @@ static void DEBIreplace(struct comedi_device *dev, uint16_t addr, uint16_t mask,
 static uint32_t I2Chandshake(struct comedi_device *dev, uint32_t val)
 {
 	struct s626_private *devpriv = dev->private;
+	unsigned int ctrl;
 
-	/*  Write I2C command to I2C Transfer Control shadow register. */
-	WR7146(P_I2CCTRL, val);
-
-	/*  Upload I2C shadow registers into working registers and wait for */
-	/*  upload confirmation. */
-
-	MC_ENABLE(P_MC2, MC2_UPLD_IIC);
-	while (!MC_TEST(P_MC2, MC2_UPLD_IIC))
-		;
+	/* Write I2C command to I2C Transfer Control shadow register */
+	writel(val, devpriv->mmio + P_I2CCTRL);
 
-	/*  Wait until I2C bus transfer is finished or an error occurs. */
-	while ((RR7146(P_I2CCTRL) & (I2C_BUSY | I2C_ERR)) == I2C_BUSY)
+	/*
+	 * Upload I2C shadow registers into working registers and
+	 * wait for upload confirmation.
+	 */
+	s626_mc_enable(dev, MC2_UPLD_IIC, P_MC2);
+	while (!s626_mc_test(dev, MC2_UPLD_IIC, P_MC2))
 		;
 
-	/*  Return non-zero if I2C error occurred. */
-	return RR7146(P_I2CCTRL) & I2C_ERR;
+	/* Wait until I2C bus transfer is finished or an error occurs */
+	do {
+		ctrl = readl(devpriv->mmio + P_I2CCTRL);
+	} while ((ctrl & (I2C_BUSY | I2C_ERR)) == I2C_BUSY);
 
+	/* Return non-zero if I2C error occurred */
+	return ctrl & I2C_ERR;
 }
 
 /*  Read uint8_t from EEPROM. */
 static uint8_t I2Cread(struct comedi_device *dev, uint8_t addr)
 {
 	struct s626_private *devpriv = dev->private;
-	uint8_t rtnval;
 
 	/*  Send EEPROM target address. */
 	if (I2Chandshake(dev, I2C_B2(I2C_ATTRSTART, I2CW)
@@ -360,9 +315,8 @@ static uint8_t I2Cread(struct comedi_device *dev, uint8_t addr)
 		/*  Abort function and declare error if handshake failed. */
 		return 0;
 	}
-	/*  Return copy of EEPROM value. */
-	rtnval = (uint8_t) (RR7146(P_I2CCTRL) >> 16);
-	return rtnval;
+
+	return (readl(devpriv->mmio + P_I2CCTRL) >> 16) & 0xff;
 }
 
 /* ***********  DAC FUNCTIONS *********** */
@@ -402,23 +356,25 @@ static void SendDAC(struct comedi_device *dev, uint32_t val)
 
 	/* Copy DAC setpoint value to DAC's output DMA buffer. */
 
-	/* WR7146( (uint32_t)devpriv->pDacWBuf, val ); */
+	/* writel(val, devpriv->mmio + (uint32_t)devpriv->pDacWBuf); */
 	*devpriv->pDacWBuf = val;
 
-	/* enab the output DMA transfer.  This will cause the DMAC to copy
-	 * the DAC's data value to A2's output FIFO.  The DMA transfer will
+	/*
+	 * Enable the output DMA transfer. This will cause the DMAC to copy
+	 * the DAC's data value to A2's output FIFO. The DMA transfer will
 	 * then immediately terminate because the protection address is
 	 * reached upon transfer of the first DWORD value.
 	 */
-	MC_ENABLE(P_MC1, MC1_A2OUT);
+	s626_mc_enable(dev, MC1_A2OUT, P_MC1);
 
 	/*  While the DMA transfer is executing ... */
 
-	/* Reset Audio2 output FIFO's underflow flag (along with any other
-	 * FIFO underflow/overflow flags).  When set, this flag will
-	 * indicate that we have emerged from slot 0.
+	/*
+	 * Reset Audio2 output FIFO's underflow flag (along with any
+	 * other FIFO underflow/overflow flags). When set, this flag
+	 * will indicate that we have emerged from slot 0.
 	 */
-	WR7146(P_ISR, ISR_AFOU);
+	writel(ISR_AFOU, devpriv->mmio + P_ISR);
 
 	/* Wait for the DMA transfer to finish so that there will be data
 	 * available in the FIFO when time slot 1 tries to transfer a DWORD
@@ -426,7 +382,7 @@ static void SendDAC(struct comedi_device *dev, uint32_t val)
 	 * Done by polling the DMAC enable flag; this flag is automatically
 	 * cleared when the transfer has finished.
 	 */
-	while ((RR7146(P_MC1) & MC1_A2OUT) != 0)
+	while (readl(devpriv->mmio + P_MC1) & MC1_A2OUT)
 		;
 
 	/* START THE OUTPUT STREAM TO THE TARGET DAC -------------------- */
@@ -436,7 +392,7 @@ static void SendDAC(struct comedi_device *dev, uint32_t val)
 	 * will be shifted in and stored in FB_BUFFER2 for end-of-slot-list
 	 * detection.
 	 */
-	SETVECT(0, XSD2 | RSD3 | SIB_A2);
+	writel(XSD2 | RSD3 | SIB_A2, devpriv->mmio + VECTPORT(0));
 
 	/* Wait for slot 1 to execute to ensure that the Packet will be
 	 * transmitted.  This is detected by polling the Audio2 output FIFO
@@ -444,7 +400,7 @@ static void SendDAC(struct comedi_device *dev, uint32_t val)
 	 * finished transferring the DAC's data DWORD from the output FIFO
 	 * to the output buffer register.
 	 */
-	while ((RR7146(P_SSR) & SSR_AF2_OUT) == 0)
+	while (!(readl(devpriv->mmio + P_SSR) & SSR_AF2_OUT))
 		;
 
 	/* Set up to trap execution at slot 0 when the TSL sequencer cycles
@@ -453,7 +409,8 @@ static void SendDAC(struct comedi_device *dev, uint32_t val)
 	 * stored in the last byte to be shifted out of the FIFO's DWORD
 	 * buffer register.
 	 */
-	SETVECT(0, XSD2 | XFIFO_2 | RSD2 | SIB_A2 | EOS);
+	writel(XSD2 | XFIFO_2 | RSD2 | SIB_A2 | EOS,
+	       devpriv->mmio + VECTPORT(0));
 
 	/* WAIT FOR THE TRANSACTION TO FINISH ----------------------- */
 
@@ -474,14 +431,14 @@ static void SendDAC(struct comedi_device *dev, uint32_t val)
 	 *    we test for the FB_BUFFER2 MSB contents to be equal to 0xFF.  If
 	 *    the TSL has not yet finished executing slot 5 ...
 	 */
-	if ((RR7146(P_FB_BUFFER2) & 0xFF000000) != 0) {
+	if (readl(devpriv->mmio + P_FB_BUFFER2) & 0xff000000) {
 		/* The trap was set on time and we are still executing somewhere
 		 * in slots 2-5, so we now wait for slot 0 to execute and trap
 		 * TSL execution.  This is detected when FB_BUFFER2 MSB changes
 		 * from 0xFF to 0x00, which slot 0 causes to happen by shifting
 		 * out/in on SD2 the 0x00 that is always referenced by slot 5.
 		 */
-		while ((RR7146(P_FB_BUFFER2) & 0xFF000000) != 0)
+		while (readl(devpriv->mmio + P_FB_BUFFER2) & 0xff000000)
 			;
 	}
 	/* Either (1) we were too late setting the slot 0 trap; the TSL
@@ -492,13 +449,13 @@ static void SendDAC(struct comedi_device *dev, uint32_t val)
 	 * In order to do this, we reprogram slot 0 so that it will shift in
 	 * SD3, which is driven only by a pull-up resistor.
 	 */
-	SETVECT(0, RSD3 | SIB_A2 | EOS);
+	writel(RSD3 | SIB_A2 | EOS, devpriv->mmio + VECTPORT(0));
 
 	/* Wait for slot 0 to execute, at which time the TSL is setup for
 	 * the next DAC write.  This is detected when FB_BUFFER2 MSB changes
 	 * from 0x00 to 0xFF.
 	 */
-	while ((RR7146(P_FB_BUFFER2) & 0xFF000000) == 0)
+	while (!(readl(devpriv->mmio + P_FB_BUFFER2) & 0xff000000))
 		;
 }
 
@@ -532,16 +489,16 @@ static void SetDAC(struct comedi_device *dev, uint16_t chan, short dacdata)
 	 * disables gating for the DAC clock and all DAC chip selects.
 	 */
 
+	/* Choose DAC chip select to be asserted */
 	WSImage = (chan & 2) ? WS1 : WS2;
-	/* Choose DAC chip select to be asserted. */
-	SETVECT(2, XSD2 | XFIFO_1 | WSImage);
-	/* Slot 2: Transmit high data byte to target DAC. */
-	SETVECT(3, XSD2 | XFIFO_0 | WSImage);
-	/* Slot 3: Transmit low data byte to target DAC. */
-	SETVECT(4, XSD2 | XFIFO_3 | WS3);
+	/* Slot 2: Transmit high data byte to target DAC */
+	writel(XSD2 | XFIFO_1 | WSImage, devpriv->mmio + VECTPORT(2));
+	/* Slot 3: Transmit low data byte to target DAC */
+	writel(XSD2 | XFIFO_0 | WSImage, devpriv->mmio + VECTPORT(3));
 	/* Slot 4: Transmit to non-existent TrimDac channel to keep clock */
-	SETVECT(5, XSD2 | XFIFO_2 | WS3 | EOS);
-	/* Slot 5: running after writing target DAC's low data byte. */
+	writel(XSD2 | XFIFO_3 | WS3, devpriv->mmio + VECTPORT(4));
+	/* Slot 5: running after writing target DAC's low data byte */
+	writel(XSD2 | XFIFO_2 | WS3 | EOS, devpriv->mmio + VECTPORT(5));
 
 	/*  Construct and transmit target DAC's serial packet:
 	 * ( A10D DDDD ),( DDDD DDDD ),( 0x0F ),( 0x00 ) where A is chan<0>,
@@ -577,14 +534,14 @@ static void WriteTrimDAC(struct comedi_device *dev, uint8_t LogicalChan,
 	 * can be detected.
 	 */
 
-	SETVECT(2, XSD2 | XFIFO_1 | WS3);
-	/* Slot 2: Send high uint8_t to target TrimDac. */
-	SETVECT(3, XSD2 | XFIFO_0 | WS3);
-	/* Slot 3: Send low uint8_t to target TrimDac. */
-	SETVECT(4, XSD2 | XFIFO_3 | WS1);
-	/* Slot 4: Send NOP high uint8_t to DAC0 to keep clock running. */
-	SETVECT(5, XSD2 | XFIFO_2 | WS1 | EOS);
-	/* Slot 5: Send NOP low  uint8_t to DAC0. */
+	/* Slot 2: Send high uint8_t to target TrimDac */
+	writel(XSD2 | XFIFO_1 | WS3, devpriv->mmio + VECTPORT(2));
+	/* Slot 3: Send low uint8_t to target TrimDac */
+	writel(XSD2 | XFIFO_0 | WS3, devpriv->mmio + VECTPORT(3));
+	/* Slot 4: Send NOP high uint8_t to DAC0 to keep clock running */
+	writel(XSD2 | XFIFO_3 | WS1, devpriv->mmio + VECTPORT(4));
+	/* Slot 5: Send NOP low  uint8_t to DAC0 */
+	writel(XSD2 | XFIFO_2 | WS1 | EOS, devpriv->mmio + VECTPORT(5));
 
 	/* Construct and transmit target DAC's serial packet:
 	 * ( 0000 AAAA ), ( DDDD DDDD ),( 0x00 ),( 0x00 ) where A<3:0> is the
@@ -638,8 +595,8 @@ static void SetLatchSource(struct comedi_device *dev, struct enc_private *k,
 			   uint16_t value)
 {
 	DEBIreplace(dev, k->MyCRB,
-		    (uint16_t) (~(CRBMSK_INTCTRL | CRBMSK_LATCHSRC)),
-		    (uint16_t) (value << CRBBIT_LATCHSRC));
+		    ~(CRBMSK_INTCTRL | CRBMSK_LATCHSRC),
+		    value << CRBBIT_LATCHSRC);
 }
 
 /*  Write value into counter preload register. */
@@ -670,43 +627,24 @@ static unsigned int s626_ai_reg_to_uint(int data)
 
 static int s626_dio_set_irq(struct comedi_device *dev, unsigned int chan)
 {
-	unsigned int group;
-	unsigned int bitmask;
+	unsigned int group = chan / 16;
+	unsigned int mask = 1 << (chan - (16 * group));
 	unsigned int status;
 
-	/* select dio bank */
-	group = chan / 16;
-	bitmask = 1 << (chan - (16 * group));
-
 	/* set channel to capture positive edge */
-	status = DEBIread(dev,
-			  ((struct dio_private *)(dev->subdevices + 2 +
-						  group)->private)->RDEdgSel);
-	DEBIwrite(dev,
-		  ((struct dio_private *)(dev->subdevices + 2 +
-					  group)->private)->WREdgSel,
-		  bitmask | status);
+	status = DEBIread(dev, LP_RDEDGSEL(group));
+	DEBIwrite(dev, LP_WREDGSEL(group), mask | status);
 
 	/* enable interrupt on selected channel */
-	status = DEBIread(dev,
-			  ((struct dio_private *)(dev->subdevices + 2 +
-						  group)->private)->RDIntSel);
-	DEBIwrite(dev,
-		  ((struct dio_private *)(dev->subdevices + 2 +
-					  group)->private)->WRIntSel,
-		  bitmask | status);
+	status = DEBIread(dev, LP_RDINTSEL(group));
+	DEBIwrite(dev, LP_WRINTSEL(group), mask | status);
 
 	/* enable edge capture write command */
 	DEBIwrite(dev, LP_MISC1, MISC1_EDCAP);
 
 	/* enable edge capture on selected channel */
-	status = DEBIread(dev,
-			  ((struct dio_private *)(dev->subdevices + 2 +
-						  group)->private)->RDCapSel);
-	DEBIwrite(dev,
-		  ((struct dio_private *)(dev->subdevices + 2 +
-					  group)->private)->WRCapSel,
-		  bitmask | status);
+	status = DEBIread(dev, LP_RDCAPSEL(group));
+	DEBIwrite(dev, LP_WRCAPSEL(group), mask | status);
 
 	return 0;
 }
@@ -718,9 +656,7 @@ static int s626_dio_reset_irq(struct comedi_device *dev, unsigned int group,
 	DEBIwrite(dev, LP_MISC1, MISC1_NOEDCAP);
 
 	/* enable edge capture on selected channel */
-	DEBIwrite(dev,
-		  ((struct dio_private *)(dev->subdevices + 2 +
-					  group)->private)->WRCapSel, mask);
+	DEBIwrite(dev, LP_WRCAPSEL(group), mask);
 
 	return 0;
 }
@@ -732,244 +668,249 @@ static int s626_dio_clear_irq(struct comedi_device *dev)
 	/* disable edge capture write command */
 	DEBIwrite(dev, LP_MISC1, MISC1_NOEDCAP);
 
-	for (group = 0; group < S626_DIO_BANKS; group++) {
-		/* clear pending events and interrupt */
-		DEBIwrite(dev,
-			  ((struct dio_private *)(dev->subdevices + 2 +
-						  group)->private)->WRCapSel,
-			  0xffff);
-	}
+	/* clear all dio pending events and interrupt */
+	for (group = 0; group < S626_DIO_BANKS; group++)
+		DEBIwrite(dev, LP_WRCAPSEL(group), 0xffff);
 
 	return 0;
 }
 
-static irqreturn_t s626_irq_handler(int irq, void *d)
+static void handle_dio_interrupt(struct comedi_device *dev,
+				 uint16_t irqbit, uint8_t group)
 {
-	struct comedi_device *dev = d;
 	struct s626_private *devpriv = dev->private;
-	struct comedi_subdevice *s;
-	struct comedi_cmd *cmd;
-	struct enc_private *k;
-	unsigned long flags;
-	int32_t *readaddr;
-	uint32_t irqtype, irqstatus;
-	int i = 0;
-	short tempdata;
-	uint8_t group;
-	uint16_t irqbit;
+	struct comedi_subdevice *s = dev->read_subdev;
+	struct comedi_cmd *cmd = &s->async->cmd;
 
-	if (dev->attached == 0)
-		return IRQ_NONE;
-	/*  lock to avoid race with comedi_poll */
-	spin_lock_irqsave(&dev->spinlock, flags);
+	s626_dio_reset_irq(dev, group, irqbit);
 
-	/* save interrupt enable register state */
-	irqstatus = readl(devpriv->base_addr + P_IER);
+	if (devpriv->ai_cmd_running) {
+		/* check if interrupt is an ai acquisition start trigger */
+		if ((irqbit >> (cmd->start_arg - (16 * group))) == 1 &&
+		    cmd->start_src == TRIG_EXT) {
+			/* Start executing the RPS program */
+			s626_mc_enable(dev, MC1_ERPS1, P_MC1);
+
+			if (cmd->scan_begin_src == TRIG_EXT)
+				s626_dio_set_irq(dev, cmd->scan_begin_arg);
+		}
+		if ((irqbit >> (cmd->scan_begin_arg - (16 * group))) == 1 &&
+		    cmd->scan_begin_src == TRIG_EXT) {
+			/* Trigger ADC scan loop start */
+			s626_mc_enable(dev, MC2_ADC_RPS, P_MC2);
 
-	/* read interrupt type */
-	irqtype = readl(devpriv->base_addr + P_ISR);
+			if (cmd->convert_src == TRIG_EXT) {
+				devpriv->ai_convert_count = cmd->chanlist_len;
 
-	/* disable master interrupt */
-	writel(0, devpriv->base_addr + P_IER);
+				s626_dio_set_irq(dev, cmd->convert_arg);
+			}
 
-	/* clear interrupt */
-	writel(irqtype, devpriv->base_addr + P_ISR);
+			if (cmd->convert_src == TRIG_TIMER) {
+				struct enc_private *k = &encpriv[5];
 
-	switch (irqtype) {
-	case IRQ_RPS1:		/*  end_of_scan occurs */
-		/*  manage ai subdevice */
-		s = dev->subdevices;
-		cmd = &(s->async->cmd);
+				devpriv->ai_convert_count = cmd->chanlist_len;
+				k->SetEnable(dev, k, CLKENAB_ALWAYS);
+			}
+		}
+		if ((irqbit >> (cmd->convert_arg - (16 * group))) == 1 &&
+		    cmd->convert_src == TRIG_EXT) {
+			/* Trigger ADC scan loop start */
+			s626_mc_enable(dev, MC2_ADC_RPS, P_MC2);
+
+			devpriv->ai_convert_count--;
+			if (devpriv->ai_convert_count > 0)
+				s626_dio_set_irq(dev, cmd->convert_arg);
+		}
+	}
+}
 
-		/* Init ptr to DMA buffer that holds new ADC data.  We skip the
-		 * first uint16_t in the buffer because it contains junk data from
-		 * the final ADC of the previous poll list scan.
-		 */
-		readaddr = (int32_t *) devpriv->ANABuf.LogicalBase + 1;
-
-		/*  get the data and hand it over to comedi */
-		for (i = 0; i < (s->async->cmd.chanlist_len); i++) {
-			/*  Convert ADC data to 16-bit integer values and copy to application */
-			/*  buffer. */
-			tempdata = s626_ai_reg_to_uint((int)*readaddr);
-			readaddr++;
-
-			/* put data into read buffer */
-			/*  comedi_buf_put(s->async, tempdata); */
-			if (cfc_write_to_buffer(s, tempdata) == 0)
-				printk
-				    ("s626_irq_handler: cfc_write_to_buffer error!\n");
+static void check_dio_interrupts(struct comedi_device *dev)
+{
+	uint16_t irqbit;
+	uint8_t group;
+
+	for (group = 0; group < S626_DIO_BANKS; group++) {
+		irqbit = 0;
+		/* read interrupt type */
+		irqbit = DEBIread(dev, LP_RDCAPFLG(group));
+
+		/* check if interrupt is generated from dio channels */
+		if (irqbit) {
+			handle_dio_interrupt(dev, irqbit, group);
+			return;
 		}
+	}
+}
 
-		/* end of scan occurs */
-		s->async->events |= COMEDI_CB_EOS;
+static void check_counter_interrupts(struct comedi_device *dev)
+{
+	struct s626_private *devpriv = dev->private;
+	struct comedi_subdevice *s = dev->read_subdev;
+	struct comedi_async *async = s->async;
+	struct comedi_cmd *cmd = &async->cmd;
+	struct enc_private *k;
+	uint16_t irqbit;
 
-		if (!(devpriv->ai_continous))
-			devpriv->ai_sample_count--;
-		if (devpriv->ai_sample_count <= 0) {
-			devpriv->ai_cmd_running = 0;
+	/* read interrupt type */
+	irqbit = DEBIread(dev, LP_RDMISC2);
 
-			/*  Stop RPS program. */
-			MC_DISABLE(P_MC1, MC1_ERPS1);
+	/* check interrupt on counters */
+	if (irqbit & IRQ_COINT1A) {
+		k = &encpriv[0];
 
-			/* send end of acquisition */
-			s->async->events |= COMEDI_CB_EOA;
+		/* clear interrupt capture flag */
+		k->ResetCapFlags(dev, k);
+	}
+	if (irqbit & IRQ_COINT2A) {
+		k = &encpriv[1];
 
-			/* disable master interrupt */
-			irqstatus = 0;
-		}
+		/* clear interrupt capture flag */
+		k->ResetCapFlags(dev, k);
+	}
+	if (irqbit & IRQ_COINT3A) {
+		k = &encpriv[2];
 
-		if (devpriv->ai_cmd_running && cmd->scan_begin_src == TRIG_EXT)
-			s626_dio_set_irq(dev, cmd->scan_begin_arg);
-		/*  tell comedi that data is there */
-		comedi_event(dev, s);
-		break;
-	case IRQ_GPIO3:	/* check dio and conter interrupt */
-		/*  manage ai subdevice */
-		s = dev->subdevices;
-		cmd = &(s->async->cmd);
+		/* clear interrupt capture flag */
+		k->ResetCapFlags(dev, k);
+	}
+	if (irqbit & IRQ_COINT1B) {
+		k = &encpriv[3];
 
-		/* s626_dio_clear_irq(dev); */
+		/* clear interrupt capture flag */
+		k->ResetCapFlags(dev, k);
+	}
+	if (irqbit & IRQ_COINT2B) {
+		k = &encpriv[4];
+
+		/* clear interrupt capture flag */
+		k->ResetCapFlags(dev, k);
+
+		if (devpriv->ai_convert_count > 0) {
+			devpriv->ai_convert_count--;
+			if (devpriv->ai_convert_count == 0)
+				k->SetEnable(dev, k, CLKENAB_INDEX);
 
-		for (group = 0; group < S626_DIO_BANKS; group++) {
-			irqbit = 0;
-			/* read interrupt type */
-			irqbit = DEBIread(dev,
-					  ((struct dio_private *)(dev->
-								  subdevices +
-								  2 +
-								  group)->
-					   private)->RDCapFlg);
-
-			/* check if interrupt is generated from dio channels */
-			if (irqbit) {
-				s626_dio_reset_irq(dev, group, irqbit);
-				if (devpriv->ai_cmd_running) {
-					/* check if interrupt is an ai acquisition start trigger */
-					if ((irqbit >> (cmd->start_arg -
-							(16 * group)))
-					    == 1 && cmd->start_src == TRIG_EXT) {
-						/*  Start executing the RPS program. */
-						MC_ENABLE(P_MC1, MC1_ERPS1);
-
-						if (cmd->scan_begin_src ==
-						    TRIG_EXT) {
-							s626_dio_set_irq(dev,
-									 cmd->scan_begin_arg);
-						}
-					}
-					if ((irqbit >> (cmd->scan_begin_arg -
-							(16 * group)))
-					    == 1
-					    && cmd->scan_begin_src ==
-					    TRIG_EXT) {
-						/*  Trigger ADC scan loop start by setting RPS Signal 0. */
-						MC_ENABLE(P_MC2, MC2_ADC_RPS);
-
-						if (cmd->convert_src ==
-						    TRIG_EXT) {
-							devpriv->ai_convert_count
-							    = cmd->chanlist_len;
-
-							s626_dio_set_irq(dev,
-									 cmd->convert_arg);
-						}
-
-						if (cmd->convert_src ==
-						    TRIG_TIMER) {
-							k = &encpriv[5];
-							devpriv->ai_convert_count
-							    = cmd->chanlist_len;
-							k->SetEnable(dev, k,
-								     CLKENAB_ALWAYS);
-						}
-					}
-					if ((irqbit >> (cmd->convert_arg -
-							(16 * group)))
-					    == 1
-					    && cmd->convert_src == TRIG_EXT) {
-						/*  Trigger ADC scan loop start by setting RPS Signal 0. */
-						MC_ENABLE(P_MC2, MC2_ADC_RPS);
-
-						devpriv->ai_convert_count--;
-
-						if (devpriv->ai_convert_count >
-						    0) {
-							s626_dio_set_irq(dev,
-									 cmd->convert_arg);
-						}
-					}
-				}
-				break;
+			if (cmd->convert_src == TRIG_TIMER) {
+				/* Trigger ADC scan loop start */
+				s626_mc_enable(dev, MC2_ADC_RPS, P_MC2);
 			}
 		}
+	}
+	if (irqbit & IRQ_COINT3B) {
+		k = &encpriv[5];
 
-		/* read interrupt type */
-		irqbit = DEBIread(dev, LP_RDMISC2);
-
-		/* check interrupt on counters */
-		if (irqbit & IRQ_COINT1A) {
-			k = &encpriv[0];
+		/* clear interrupt capture flag */
+		k->ResetCapFlags(dev, k);
 
-			/* clear interrupt capture flag */
-			k->ResetCapFlags(dev, k);
+		if (cmd->scan_begin_src == TRIG_TIMER) {
+			/* Trigger ADC scan loop start */
+			s626_mc_enable(dev, MC2_ADC_RPS, P_MC2);
 		}
-		if (irqbit & IRQ_COINT2A) {
-			k = &encpriv[1];
 
-			/* clear interrupt capture flag */
-			k->ResetCapFlags(dev, k);
+		if (cmd->convert_src == TRIG_TIMER) {
+			k = &encpriv[4];
+			devpriv->ai_convert_count = cmd->chanlist_len;
+			k->SetEnable(dev, k, CLKENAB_ALWAYS);
 		}
-		if (irqbit & IRQ_COINT3A) {
-			k = &encpriv[2];
+	}
+}
 
-			/* clear interrupt capture flag */
-			k->ResetCapFlags(dev, k);
-		}
-		if (irqbit & IRQ_COINT1B) {
-			k = &encpriv[3];
+static bool handle_eos_interrupt(struct comedi_device *dev)
+{
+	struct s626_private *devpriv = dev->private;
+	struct comedi_subdevice *s = dev->read_subdev;
+	struct comedi_async *async = s->async;
+	struct comedi_cmd *cmd = &async->cmd;
+	/*
+	 * Init ptr to DMA buffer that holds new ADC data.  We skip the
+	 * first uint16_t in the buffer because it contains junk data
+	 * from the final ADC of the previous poll list scan.
+	 */
+	int32_t *readaddr = (int32_t *)devpriv->ANABuf.LogicalBase + 1;
+	bool finished = false;
+	int i;
 
-			/* clear interrupt capture flag */
-			k->ResetCapFlags(dev, k);
-		}
-		if (irqbit & IRQ_COINT2B) {
-			k = &encpriv[4];
+	/* get the data and hand it over to comedi */
+	for (i = 0; i < cmd->chanlist_len; i++) {
+		short tempdata;
 
-			/* clear interrupt capture flag */
-			k->ResetCapFlags(dev, k);
+		/*
+		 * Convert ADC data to 16-bit integer values and copy
+		 * to application buffer.
+		 */
+		tempdata = s626_ai_reg_to_uint((int)*readaddr);
+		readaddr++;
 
-			if (devpriv->ai_convert_count > 0) {
-				devpriv->ai_convert_count--;
-				if (devpriv->ai_convert_count == 0)
-					k->SetEnable(dev, k, CLKENAB_INDEX);
+		/* put data into read buffer */
+		/* comedi_buf_put(async, tempdata); */
+		cfc_write_to_buffer(s, tempdata);
+	}
 
-				if (cmd->convert_src == TRIG_TIMER) {
-					/*  Trigger ADC scan loop start by setting RPS Signal 0. */
-					MC_ENABLE(P_MC2, MC2_ADC_RPS);
-				}
-			}
-		}
-		if (irqbit & IRQ_COINT3B) {
-			k = &encpriv[5];
+	/* end of scan occurs */
+	async->events |= COMEDI_CB_EOS;
 
-			/* clear interrupt capture flag */
-			k->ResetCapFlags(dev, k);
+	if (!devpriv->ai_continous)
+		devpriv->ai_sample_count--;
+	if (devpriv->ai_sample_count <= 0) {
+		devpriv->ai_cmd_running = 0;
 
-			if (cmd->scan_begin_src == TRIG_TIMER) {
-				/*  Trigger ADC scan loop start by setting RPS Signal 0. */
-				MC_ENABLE(P_MC2, MC2_ADC_RPS);
-			}
+		/* Stop RPS program */
+		s626_mc_disable(dev, MC1_ERPS1, P_MC1);
 
-			if (cmd->convert_src == TRIG_TIMER) {
-				k = &encpriv[4];
-				devpriv->ai_convert_count = cmd->chanlist_len;
-				k->SetEnable(dev, k, CLKENAB_ALWAYS);
-			}
-		}
+		/* send end of acquisition */
+		async->events |= COMEDI_CB_EOA;
+
+		/* disable master interrupt */
+		finished = true;
+	}
+
+	if (devpriv->ai_cmd_running && cmd->scan_begin_src == TRIG_EXT)
+		s626_dio_set_irq(dev, cmd->scan_begin_arg);
+
+	/* tell comedi that data is there */
+	comedi_event(dev, s);
+
+	return finished;
+}
+
+static irqreturn_t s626_irq_handler(int irq, void *d)
+{
+	struct comedi_device *dev = d;
+	struct s626_private *devpriv = dev->private;
+	unsigned long flags;
+	uint32_t irqtype, irqstatus;
+
+	if (!dev->attached)
+		return IRQ_NONE;
+	/*  lock to avoid race with comedi_poll */
+	spin_lock_irqsave(&dev->spinlock, flags);
+
+	/* save interrupt enable register state */
+	irqstatus = readl(devpriv->mmio + P_IER);
+
+	/* read interrupt type */
+	irqtype = readl(devpriv->mmio + P_ISR);
+
+	/* disable master interrupt */
+	writel(0, devpriv->mmio + P_IER);
+
+	/* clear interrupt */
+	writel(irqtype, devpriv->mmio + P_ISR);
+
+	switch (irqtype) {
+	case IRQ_RPS1:		/*  end_of_scan occurs */
+		if (handle_eos_interrupt(dev))
+			irqstatus = 0;
+		break;
+	case IRQ_GPIO3:	/* check dio and conter interrupt */
+		/* s626_dio_clear_irq(dev); */
+		check_dio_interrupts(dev);
+		check_counter_interrupts(dev);
+		break;
 	}
 
 	/* enable interrupt */
-	writel(irqstatus, devpriv->base_addr + P_IER);
+	writel(irqstatus, devpriv->mmio + P_IER);
 
 	spin_unlock_irqrestore(&dev->spinlock, flags);
 	return IRQ_HANDLED;
@@ -988,14 +929,15 @@ static void ResetADC(struct comedi_device *dev, uint8_t *ppl)
 	uint32_t LocalPPL;
 	struct comedi_cmd *cmd = &(dev->subdevices->async->cmd);
 
-	/*  Stop RPS program in case it is currently running. */
-	MC_DISABLE(P_MC1, MC1_ERPS1);
+	/* Stop RPS program in case it is currently running */
+	s626_mc_disable(dev, MC1_ERPS1, P_MC1);
 
 	/*  Set starting logical address to write RPS commands. */
 	pRPS = (uint32_t *) devpriv->RPSBuf.LogicalBase;
 
-	/*  Initialize RPS instruction pointer. */
-	WR7146(P_RPSADDR1, (uint32_t) devpriv->RPSBuf.PhysicalBase);
+	/* Initialize RPS instruction pointer */
+	writel((uint32_t)devpriv->RPSBuf.PhysicalBase,
+	       devpriv->mmio + P_RPSADDR1);
 
 	/*  Construct RPS program in RPSBuf DMA buffer */
 
@@ -1165,41 +1107,42 @@ static void ResetADC(struct comedi_device *dev, uint8_t *ppl)
 	/*  End of RPS program build */
 }
 
-/* TO COMPLETE, IF NECESSARY */
-static int s626_ai_insn_config(struct comedi_device *dev,
-			       struct comedi_subdevice *s,
-			       struct comedi_insn *insn, unsigned int *data)
+#ifdef unused_code
+static int s626_ai_rinsn(struct comedi_device *dev,
+			 struct comedi_subdevice *s,
+			 struct comedi_insn *insn,
+			 unsigned int *data)
 {
+	struct s626_private *devpriv = dev->private;
+	register uint8_t i;
+	register int32_t *readaddr;
 
-	return -EINVAL;
-}
-
-/* static int s626_ai_rinsn(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data) */
-/* { */
-/*   struct s626_private *devpriv = dev->private; */
-/*   register uint8_t	i; */
-/*   register int32_t	*readaddr; */
-
-/*   Trigger ADC scan loop start by setting RPS Signal 0. */
-/*   MC_ENABLE( P_MC2, MC2_ADC_RPS ); */
+	/* Trigger ADC scan loop start */
+	s626_mc_enable(dev, MC2_ADC_RPS, P_MC2);
 
-/*   Wait until ADC scan loop is finished (RPS Signal 0 reset). */
-/*   while ( MC_TEST( P_MC2, MC2_ADC_RPS ) ); */
+	/* Wait until ADC scan loop is finished (RPS Signal 0 reset) */
+	while (s626_mc_test(dev, MC2_ADC_RPS, P_MC2))
+		;
 
-/* Init ptr to DMA buffer that holds new ADC data.  We skip the
- * first uint16_t in the buffer because it contains junk data from
- * the final ADC of the previous poll list scan.
- */
-/*   readaddr = (uint32_t *)devpriv->ANABuf.LogicalBase + 1; */
+	/*
+	 * Init ptr to DMA buffer that holds new ADC data.  We skip the
+	 * first uint16_t in the buffer because it contains junk data from
+	 * the final ADC of the previous poll list scan.
+	 */
+	readaddr = (uint32_t *)devpriv->ANABuf.LogicalBase + 1;
 
-/*  Convert ADC data to 16-bit integer values and copy to application buffer. */
-/*   for ( i = 0; i < devpriv->AdcItems; i++ ) { */
-/*     *data = s626_ai_reg_to_uint( *readaddr++ ); */
-/*     data++; */
-/*   } */
+	/*
+	 * Convert ADC data to 16-bit integer values and
+	 * copy to application buffer.
+	 */
+	for (i = 0; i < devpriv->AdcItems; i++) {
+		*data = s626_ai_reg_to_uint(*readaddr++);
+		data++;
+	}
 
-/*   return i; */
-/* } */
+	return i;
+}
+#endif
 
 static int s626_ai_insn_read(struct comedi_device *dev,
 			     struct comedi_subdevice *s,
@@ -1210,14 +1153,9 @@ static int s626_ai_insn_read(struct comedi_device *dev,
 	uint16_t range = CR_RANGE(insn->chanspec);
 	uint16_t AdcSpec = 0;
 	uint32_t GpioImage;
+	int tmp;
 	int n;
 
-	/* interrupt call test  */
-/*   writel(IRQ_GPIO3,devpriv->base_addr+P_PSR); */
-	/* Writing a logical 1 into any of the RPS_PSR bits causes the
-	 * corresponding interrupt to be generated if enabled
-	 */
-
 	/* Convert application's ADC specification into form
 	 *  appropriate for register programming.
 	 */
@@ -1237,27 +1175,29 @@ static int s626_ai_insn_read(struct comedi_device *dev,
 		/*  Delay 10 microseconds for analog input settling. */
 		udelay(10);
 
-		/*  Start ADC by pulsing GPIO1 low. */
-		GpioImage = RR7146(P_GPIO);
-		/*  Assert ADC Start command */
-		WR7146(P_GPIO, GpioImage & ~GPIO1_HI);
-		/*    and stretch it out. */
-		WR7146(P_GPIO, GpioImage & ~GPIO1_HI);
-		WR7146(P_GPIO, GpioImage & ~GPIO1_HI);
-		/*  Negate ADC Start command. */
-		WR7146(P_GPIO, GpioImage | GPIO1_HI);
+		/* Start ADC by pulsing GPIO1 low */
+		GpioImage = readl(devpriv->mmio + P_GPIO);
+		/* Assert ADC Start command */
+		writel(GpioImage & ~GPIO1_HI, devpriv->mmio + P_GPIO);
+		/* and stretch it out */
+		writel(GpioImage & ~GPIO1_HI, devpriv->mmio + P_GPIO);
+		writel(GpioImage & ~GPIO1_HI, devpriv->mmio + P_GPIO);
+		/* Negate ADC Start command */
+		writel(GpioImage | GPIO1_HI, devpriv->mmio + P_GPIO);
 
 		/*  Wait for ADC to complete (GPIO2 is asserted high when */
 		/*  ADC not busy) and for data from previous conversion to */
 		/*  shift into FB BUFFER 1 register. */
 
-		/*  Wait for ADC done. */
-		while (!(RR7146(P_PSR) & PSR_GPIO2))
+		/* Wait for ADC done */
+		while (!(readl(devpriv->mmio + P_PSR) & PSR_GPIO2))
 			;
 
-		/*  Fetch ADC data. */
-		if (n != 0)
-			data[n - 1] = s626_ai_reg_to_uint(RR7146(P_FB_BUFFER1));
+		/* Fetch ADC data */
+		if (n != 0) {
+			tmp = readl(devpriv->mmio + P_FB_BUFFER1);
+			data[n - 1] = s626_ai_reg_to_uint(tmp);
+		}
 
 		/* Allow the ADC to stabilize for 4 microseconds before
 		 * starting the next (final) conversion.  This delay is
@@ -1272,27 +1212,28 @@ static int s626_ai_insn_read(struct comedi_device *dev,
 
 	/* Start a dummy conversion to cause the data from the
 	 * previous conversion to be shifted in. */
-	GpioImage = RR7146(P_GPIO);
-
+	GpioImage = readl(devpriv->mmio + P_GPIO);
 	/* Assert ADC Start command */
-	WR7146(P_GPIO, GpioImage & ~GPIO1_HI);
-	/*    and stretch it out. */
-	WR7146(P_GPIO, GpioImage & ~GPIO1_HI);
-	WR7146(P_GPIO, GpioImage & ~GPIO1_HI);
-	/*  Negate ADC Start command. */
-	WR7146(P_GPIO, GpioImage | GPIO1_HI);
+	writel(GpioImage & ~GPIO1_HI, devpriv->mmio + P_GPIO);
+	/* and stretch it out */
+	writel(GpioImage & ~GPIO1_HI, devpriv->mmio + P_GPIO);
+	writel(GpioImage & ~GPIO1_HI, devpriv->mmio + P_GPIO);
+	/* Negate ADC Start command */
+	writel(GpioImage | GPIO1_HI, devpriv->mmio + P_GPIO);
 
 	/*  Wait for the data to arrive in FB BUFFER 1 register. */
 
-	/*  Wait for ADC done. */
-	while (!(RR7146(P_PSR) & PSR_GPIO2))
+	/* Wait for ADC done */
+	while (!(readl(devpriv->mmio + P_PSR) & PSR_GPIO2))
 		;
 
 	/*  Fetch ADC data from audio interface's input shift register. */
 
-	/*  Fetch ADC data. */
-	if (n != 0)
-		data[n - 1] = s626_ai_reg_to_uint(RR7146(P_FB_BUFFER1));
+	/* Fetch ADC data */
+	if (n != 0) {
+		tmp = readl(devpriv->mmio + P_FB_BUFFER1);
+		data[n - 1] = s626_ai_reg_to_uint(tmp);
+	}
 
 	return n;
 }
@@ -1317,13 +1258,11 @@ static int s626_ai_load_polllist(uint8_t *ppl, struct comedi_cmd *cmd)
 static int s626_ai_inttrig(struct comedi_device *dev,
 			   struct comedi_subdevice *s, unsigned int trignum)
 {
-	struct s626_private *devpriv = dev->private;
-
 	if (trignum != 0)
 		return -EINVAL;
 
-	/*  Start executing the RPS program. */
-	MC_ENABLE(P_MC1, MC1_ERPS1);
+	/* Start executing the RPS program */
+	s626_mc_enable(dev, MC1_ERPS1, P_MC1);
 
 	s->async->inttrig = NULL;
 
@@ -1407,10 +1346,10 @@ static int s626_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 		return -EBUSY;
 	}
 	/* disable interrupt */
-	writel(0, devpriv->base_addr + P_IER);
+	writel(0, devpriv->mmio + P_IER);
 
 	/* clear interrupt request */
-	writel(IRQ_RPS1 | IRQ_GPIO3, devpriv->base_addr + P_ISR);
+	writel(IRQ_RPS1 | IRQ_GPIO3, devpriv->mmio + P_ISR);
 
 	/* clear any pending interrupt */
 	s626_dio_clear_irq(dev);
@@ -1491,11 +1430,11 @@ static int s626_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 
 	switch (cmd->start_src) {
 	case TRIG_NOW:
-		/*  Trigger ADC scan loop start by setting RPS Signal 0. */
-		/*  MC_ENABLE( P_MC2, MC2_ADC_RPS ); */
+		/* Trigger ADC scan loop start */
+		/* s626_mc_enable(dev, MC2_ADC_RPS, P_MC2); */
 
-		/*  Start executing the RPS program. */
-		MC_ENABLE(P_MC1, MC1_ERPS1);
+		/* Start executing the RPS program */
+		s626_mc_enable(dev, MC1_ERPS1, P_MC1);
 
 		s->async->inttrig = NULL;
 		break;
@@ -1511,7 +1450,7 @@ static int s626_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 	}
 
 	/* enable interrupt */
-	writel(IRQ_GPIO3 | IRQ_RPS1, devpriv->base_addr + P_IER);
+	writel(IRQ_GPIO3 | IRQ_RPS1, devpriv->mmio + P_IER);
 
 	return 0;
 }
@@ -1628,11 +1567,11 @@ static int s626_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
 {
 	struct s626_private *devpriv = dev->private;
 
-	/*  Stop RPS program in case it is currently running. */
-	MC_DISABLE(P_MC1, MC1_ERPS1);
+	/* Stop RPS program in case it is currently running */
+	s626_mc_disable(dev, MC1_ERPS1, P_MC1);
 
 	/* disable master interrupt */
-	writel(0, devpriv->base_addr + P_IER);
+	writel(0, devpriv->mmio + P_IER);
 
 	devpriv->ai_cmd_running = 0;
 
@@ -1679,84 +1618,74 @@ static int s626_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
 static void s626_dio_init(struct comedi_device *dev)
 {
 	uint16_t group;
-	struct comedi_subdevice *s;
 
 	/*  Prepare to treat writes to WRCapSel as capture disables. */
 	DEBIwrite(dev, LP_MISC1, MISC1_NOEDCAP);
 
 	/*  For each group of sixteen channels ... */
 	for (group = 0; group < S626_DIO_BANKS; group++) {
-		s = dev->subdevices + 2 + group;
-		DEBIwrite(dev, diopriv->WRIntSel, 0);	/*  Disable all interrupts. */
-		DEBIwrite(dev, diopriv->WRCapSel, 0xFFFF);	/*  Disable all event */
-		/*  captures. */
-		DEBIwrite(dev, diopriv->WREdgSel, 0);	/*  Init all DIOs to */
-		/*  default edge */
-		/*  polarity. */
-		DEBIwrite(dev, diopriv->WRDOut, 0);	/*  Program all outputs */
-		/*  to inactive state. */
+		/* Disable all interrupts */
+		DEBIwrite(dev, LP_WRINTSEL(group), 0);
+		/* Disable all event captures */
+		DEBIwrite(dev, LP_WRCAPSEL(group), 0xffff);
+		/* Init all DIOs to default edge polarity */
+		DEBIwrite(dev, LP_WREDGSEL(group), 0);
+		/* Program all outputs to inactive state */
+		DEBIwrite(dev, LP_WRDOUT(group), 0);
 	}
 }
 
-/* DIO devices are slightly special.  Although it is possible to
- * implement the insn_read/insn_write interface, it is much more
- * useful to applications if you implement the insn_bits interface.
- * This allows packed reading/writing of the DIO channels.  The comedi
- * core can convert between insn_bits and insn_read/write */
-
 static int s626_dio_insn_bits(struct comedi_device *dev,
 			      struct comedi_subdevice *s,
-			      struct comedi_insn *insn, unsigned int *data)
+			      struct comedi_insn *insn,
+			      unsigned int *data)
 {
-	/*
-	 * The insn data consists of a mask in data[0] and the new data in
-	 * data[1]. The mask defines which bits we are concerning about.
-	 * The new data must be anded with the mask.  Each channel
-	 * corresponds to a bit.
-	 */
-	if (data[0]) {
-		/* Check if requested ports are configured for output */
-		if ((s->io_bits & data[0]) != data[0])
-			return -EIO;
+	unsigned long group = (unsigned long)s->private;
+	unsigned long mask = data[0];
+	unsigned long bits = data[1];
 
-		s->state &= ~data[0];
-		s->state |= data[0] & data[1];
+	if (mask) {
+		/* Check if requested channels are configured for output */
+		if ((s->io_bits & mask) != mask)
+			return -EIO;
 
-		/* Write out the new digital output lines */
+		s->state &= ~mask;
+		s->state |= (bits & mask);
 
-		DEBIwrite(dev, diopriv->WRDOut, s->state);
+		DEBIwrite(dev, LP_WRDOUT(group), s->state);
 	}
-	data[1] = DEBIread(dev, diopriv->RDDIn);
+	data[1] = DEBIread(dev, LP_RDDIN(group));
 
 	return insn->n;
 }
 
 static int s626_dio_insn_config(struct comedi_device *dev,
 				struct comedi_subdevice *s,
-				struct comedi_insn *insn, unsigned int *data)
+				struct comedi_insn *insn,
+				unsigned int *data)
 {
+	unsigned long group = (unsigned long)s->private;
+	unsigned int chan = CR_CHAN(insn->chanspec);
+	unsigned int mask = 1 << chan;
 
 	switch (data[0]) {
 	case INSN_CONFIG_DIO_QUERY:
-		data[1] =
-		    (s->
-		     io_bits & (1 << CR_CHAN(insn->chanspec))) ? COMEDI_OUTPUT :
-		    COMEDI_INPUT;
+		data[1] = (s->io_bits & mask) ? COMEDI_OUTPUT : COMEDI_INPUT;
 		return insn->n;
 		break;
 	case COMEDI_INPUT:
-		s->io_bits &= ~(1 << CR_CHAN(insn->chanspec));
+		s->io_bits &= ~mask;
 		break;
 	case COMEDI_OUTPUT:
-		s->io_bits |= 1 << CR_CHAN(insn->chanspec);
+		s->io_bits |= mask;
 		break;
 	default:
 		return -EINVAL;
 		break;
 	}
-	DEBIwrite(dev, diopriv->WRDOut, s->io_bits);
+	DEBIwrite(dev, LP_WRDOUT(group), s->io_bits);
 
-	return 1;
+	return insn->n;
 }
 
 /* Now this function initializes the value of the counter (data[0])
@@ -1861,13 +1790,13 @@ static void CloseDMAB(struct comedi_device *dev, struct bufferDMA *pdma,
 
 static void ResetCapFlags_A(struct comedi_device *dev, struct enc_private *k)
 {
-	DEBIreplace(dev, k->MyCRB, (uint16_t) (~CRBMSK_INTCTRL),
+	DEBIreplace(dev, k->MyCRB, ~CRBMSK_INTCTRL,
 		    CRBMSK_INTRESETCMD | CRBMSK_INTRESET_A);
 }
 
 static void ResetCapFlags_B(struct comedi_device *dev, struct enc_private *k)
 {
-	DEBIreplace(dev, k->MyCRB, (uint16_t) (~CRBMSK_INTCTRL),
+	DEBIreplace(dev, k->MyCRB, ~CRBMSK_INTCTRL,
 		    CRBMSK_INTRESETCMD | CRBMSK_INTRESET_B);
 }
 
@@ -2012,8 +1941,7 @@ static void SetMode_A(struct comedi_device *dev, struct enc_private *k,
 	/*  While retaining CounterB and LatchSrc configurations, program the */
 	/*  new counter operating mode. */
 	DEBIreplace(dev, k->MyCRA, CRAMSK_INDXSRC_B | CRAMSK_CLKSRC_B, cra);
-	DEBIreplace(dev, k->MyCRB,
-		    (uint16_t) (~(CRBMSK_INTCTRL | CRBMSK_CLKENAB_A)), crb);
+	DEBIreplace(dev, k->MyCRB, ~(CRBMSK_INTCTRL | CRBMSK_CLKENAB_A), crb);
 }
 
 static void SetMode_B(struct comedi_device *dev, struct enc_private *k,
@@ -2074,8 +2002,7 @@ static void SetMode_B(struct comedi_device *dev, struct enc_private *k,
 
 	/*  While retaining CounterA and LatchSrc configurations, program the */
 	/*  new counter operating mode. */
-	DEBIreplace(dev, k->MyCRA,
-		    (uint16_t) (~(CRAMSK_INDXSRC_B | CRAMSK_CLKSRC_B)), cra);
+	DEBIreplace(dev, k->MyCRA, ~(CRAMSK_INDXSRC_B | CRAMSK_CLKSRC_B), cra);
 	DEBIreplace(dev, k->MyCRB, CRBMSK_CLKENAB_A | CRBMSK_LATCHSRC, crb);
 }
 
@@ -2084,17 +2011,15 @@ static void SetMode_B(struct comedi_device *dev, struct enc_private *k,
 static void SetEnable_A(struct comedi_device *dev, struct enc_private *k,
 			uint16_t enab)
 {
-	DEBIreplace(dev, k->MyCRB,
-		    (uint16_t) (~(CRBMSK_INTCTRL | CRBMSK_CLKENAB_A)),
-		    (uint16_t) (enab << CRBBIT_CLKENAB_A));
+	DEBIreplace(dev, k->MyCRB, ~(CRBMSK_INTCTRL | CRBMSK_CLKENAB_A),
+		    enab << CRBBIT_CLKENAB_A);
 }
 
 static void SetEnable_B(struct comedi_device *dev, struct enc_private *k,
 			uint16_t enab)
 {
-	DEBIreplace(dev, k->MyCRB,
-		    (uint16_t) (~(CRBMSK_INTCTRL | CRBMSK_CLKENAB_B)),
-		    (uint16_t) (enab << CRBBIT_CLKENAB_B));
+	DEBIreplace(dev, k->MyCRB, ~(CRBMSK_INTCTRL | CRBMSK_CLKENAB_B),
+		    enab << CRBBIT_CLKENAB_B);
 }
 
 static uint16_t GetEnable_A(struct comedi_device *dev, struct enc_private *k)
@@ -2123,16 +2048,15 @@ static uint16_t GetEnable_B(struct comedi_device *dev, struct enc_private *k)
 static void SetLoadTrig_A(struct comedi_device *dev, struct enc_private *k,
 			  uint16_t Trig)
 {
-	DEBIreplace(dev, k->MyCRA, (uint16_t) (~CRAMSK_LOADSRC_A),
-		    (uint16_t) (Trig << CRABIT_LOADSRC_A));
+	DEBIreplace(dev, k->MyCRA, ~CRAMSK_LOADSRC_A,
+		    Trig << CRABIT_LOADSRC_A);
 }
 
 static void SetLoadTrig_B(struct comedi_device *dev, struct enc_private *k,
 			  uint16_t Trig)
 {
-	DEBIreplace(dev, k->MyCRB,
-		    (uint16_t) (~(CRBMSK_LOADSRC_B | CRBMSK_INTCTRL)),
-		    (uint16_t) (Trig << CRBBIT_LOADSRC_B));
+	DEBIreplace(dev, k->MyCRB, ~(CRBMSK_LOADSRC_B | CRBMSK_INTCTRL),
+		    Trig << CRBBIT_LOADSRC_B);
 }
 
 static uint16_t GetLoadTrig_A(struct comedi_device *dev, struct enc_private *k)
@@ -2156,12 +2080,12 @@ static void SetIntSrc_A(struct comedi_device *dev, struct enc_private *k,
 	struct s626_private *devpriv = dev->private;
 
 	/*  Reset any pending counter overflow or index captures. */
-	DEBIreplace(dev, k->MyCRB, (uint16_t) (~CRBMSK_INTCTRL),
+	DEBIreplace(dev, k->MyCRB, ~CRBMSK_INTCTRL,
 		    CRBMSK_INTRESETCMD | CRBMSK_INTRESET_A);
 
 	/*  Program counter interrupt source. */
 	DEBIreplace(dev, k->MyCRA, ~CRAMSK_INTSRC_A,
-		    (uint16_t) (IntSource << CRABIT_INTSRC_A));
+		    IntSource << CRABIT_INTSRC_A);
 
 	/*  Update MISC2 interrupt enable mask. */
 	devpriv->CounterIntEnabs =
@@ -2430,7 +2354,7 @@ static void s626_initialize(struct comedi_device *dev)
 	int i;
 
 	/* Enable DEBI and audio pins, enable I2C interface */
-	MC_ENABLE(P_MC1, MC1_DEBI | MC1_AUDIO | MC1_I2C);
+	s626_mc_enable(dev, MC1_DEBI | MC1_AUDIO | MC1_I2C, P_MC1);
 
 	/*
 	 *  Configure DEBI operating mode
@@ -2440,15 +2364,16 @@ static void s626_initialize(struct comedi_device *dev)
 	 *   Set up byte lane steering
 	 *   Intel-compatible local bus (DEBI never times out)
 	 */
-	WR7146(P_DEBICFG, DEBI_CFG_SLAVE16 |
-			  (DEBI_TOUT << DEBI_CFG_TOUT_BIT) |
-			  DEBI_SWAP | DEBI_CFG_INTEL);
+	writel(DEBI_CFG_SLAVE16 |
+	       (DEBI_TOUT << DEBI_CFG_TOUT_BIT) |
+	       DEBI_SWAP | DEBI_CFG_INTEL,
+	       devpriv->mmio + P_DEBICFG);
 
 	/* Disable MMU paging */
-	WR7146(P_DEBIPAGE, DEBI_PAGE_DISABLE);
+	writel(DEBI_PAGE_DISABLE, devpriv->mmio + P_DEBIPAGE);
 
 	/* Init GPIO so that ADC Start* is negated */
-	WR7146(P_GPIO, GPIO_BASE | GPIO1_HI);
+	writel(GPIO_BASE | GPIO1_HI, devpriv->mmio + P_GPIO);
 
 	/* I2C device address for onboard eeprom (revb) */
 	devpriv->I2CAdrs = 0xA0;
@@ -2457,9 +2382,9 @@ static void s626_initialize(struct comedi_device *dev)
 	 * Issue an I2C ABORT command to halt any I2C
 	 * operation in progress and reset BUSY flag.
 	 */
-	WR7146(P_I2CSTAT, I2C_CLKSEL | I2C_ABORT);
-	MC_ENABLE(P_MC2, MC2_UPLD_IIC);
-	while ((RR7146(P_MC2) & MC2_UPLD_IIC) == 0)
+	writel(I2C_CLKSEL | I2C_ABORT, devpriv->mmio + P_I2CSTAT);
+	s626_mc_enable(dev, MC2_UPLD_IIC, P_MC2);
+	while (!(readl(devpriv->mmio + P_MC2) & MC2_UPLD_IIC))
 		;
 
 	/*
@@ -2467,9 +2392,9 @@ static void s626_initialize(struct comedi_device *dev)
 	 * reg twice to reset all  I2C error flags.
 	 */
 	for (i = 0; i < 2; i++) {
-		WR7146(P_I2CSTAT, I2C_CLKSEL);
-		MC_ENABLE(P_MC2, MC2_UPLD_IIC);
-		while (!MC_TEST(P_MC2, MC2_UPLD_IIC))
+		writel(I2C_CLKSEL, devpriv->mmio + P_I2CSTAT);
+		s626_mc_enable(dev, MC2_UPLD_IIC, P_MC2);
+		while (!s626_mc_test(dev, MC2_UPLD_IIC, P_MC2))
 			;
 	}
 
@@ -2479,7 +2404,7 @@ static void s626_initialize(struct comedi_device *dev)
 	 * DAC data setup times are satisfied, enable DAC serial
 	 * clock out.
 	 */
-	WR7146(P_ACON2, ACON2_INIT);
+	writel(ACON2_INIT, devpriv->mmio + P_ACON2);
 
 	/*
 	 * Set up TSL1 slot list, which is used to control the
@@ -2487,22 +2412,23 @@ static void s626_initialize(struct comedi_device *dev)
 	 * SIB_A1  = store data uint8_t at next available location
 	 * in FB BUFFER1 register.
 	 */
-	WR7146(P_TSL1, RSD1 | SIB_A1);
-	WR7146(P_TSL1 + 4, RSD1 | SIB_A1 | EOS);
+	writel(RSD1 | SIB_A1, devpriv->mmio + P_TSL1);
+	writel(RSD1 | SIB_A1 | EOS, devpriv->mmio + P_TSL1 + 4);
 
 	/* Enable TSL1 slot list so that it executes all the time */
-	WR7146(P_ACON1, ACON1_ADCSTART);
+	writel(ACON1_ADCSTART, devpriv->mmio + P_ACON1);
 
 	/*
 	 * Initialize RPS registers used for ADC
 	 */
 
 	/* Physical start of RPS program */
-	WR7146(P_RPSADDR1, (uint32_t)devpriv->RPSBuf.PhysicalBase);
+	writel((uint32_t)devpriv->RPSBuf.PhysicalBase,
+	       devpriv->mmio + P_RPSADDR1);
 	/* RPS program performs no explicit mem writes */
-	WR7146(P_RPSPAGE1, 0);
+	writel(0, devpriv->mmio + P_RPSPAGE1);
 	/* Disable RPS timeouts */
-	WR7146(P_RPS1_TOUT, 0);
+	writel(0, devpriv->mmio + P_RPS1_TOUT);
 
 #if 0
 	/*
@@ -2558,7 +2484,7 @@ static void s626_initialize(struct comedi_device *dev)
 	 *   burst length = 1 DWORD
 	 *   threshold = 1 DWORD.
 	 */
-	WR7146(P_PCI_BT_A, 0);
+	writel(0, devpriv->mmio + P_PCI_BT_A);
 
 	/*
 	 * Init Audio2's output DMA physical addresses.  The protection
@@ -2568,8 +2494,9 @@ static void s626_initialize(struct comedi_device *dev)
 	 */
 	pPhysBuf = devpriv->ANABuf.PhysicalBase +
 		   (DAC_WDMABUF_OS * sizeof(uint32_t));
-	WR7146(P_BASEA2_OUT, (uint32_t) pPhysBuf);
-	WR7146(P_PROTA2_OUT, (uint32_t) (pPhysBuf + sizeof(uint32_t)));
+	writel((uint32_t)pPhysBuf, devpriv->mmio + P_BASEA2_OUT);
+	writel((uint32_t)(pPhysBuf + sizeof(uint32_t)),
+	       devpriv->mmio + P_PROTA2_OUT);
 
 	/*
 	 * Cache Audio2's output DMA buffer logical address.  This is
@@ -2584,7 +2511,7 @@ static void s626_initialize(struct comedi_device *dev)
 	 * DMAC will automatically halt and its PCI address pointer
 	 * will be reset when the protection address is reached.
 	 */
-	WR7146(P_PAGEA2_OUT, 8);
+	writel(8, devpriv->mmio + P_PAGEA2_OUT);
 
 	/*
 	 * Initialize time slot list 2 (TSL2), which is used to control
@@ -2599,7 +2526,7 @@ static void s626_initialize(struct comedi_device *dev)
 	 */
 
 	/* Slot 0: Trap TSL execution, shift 0xFF into FB_BUFFER2 */
-	SETVECT(0, XSD2 | RSD3 | SIB_A2 | EOS);
+	writel(XSD2 | RSD3 | SIB_A2 | EOS, devpriv->mmio + VECTPORT(0));
 
 	/*
 	 * Initialize slot 1, which is constant.  Slot 1 causes a
@@ -2611,10 +2538,10 @@ static void s626_initialize(struct comedi_device *dev)
 	 */
 
 	/* Slot 1: Fetch DWORD from Audio2's output FIFO */
-	SETVECT(1, LF_A2);
+	writel(LF_A2, devpriv->mmio + VECTPORT(1));
 
 	/* Start DAC's audio interface (TSL2) running */
-	WR7146(P_ACON1, ACON1_DACSTART);
+	writel(ACON1_DACSTART, devpriv->mmio + P_ACON1);
 
 	/*
 	 * Init Trim DACs to calibrated values.  Do it twice because the
@@ -2653,9 +2580,6 @@ static void s626_initialize(struct comedi_device *dev)
 
 	/* Initialize the digital I/O subsystem */
 	s626_dio_init(dev);
-
-	/* enable interrupt test */
-	/* writel(IRQ_GPIO3 | IRQ_RPS1, devpriv->base_addr + P_IER); */
 }
 
 static int s626_auto_attach(struct comedi_device *dev,
@@ -2673,21 +2597,20 @@ static int s626_auto_attach(struct comedi_device *dev,
 		return -ENOMEM;
 	dev->private = devpriv;
 
-	ret = comedi_pci_enable(pcidev, dev->board_name);
+	ret = comedi_pci_enable(dev);
 	if (ret)
 		return ret;
-	dev->iobase = 1;	/* detach needs this */
 
-	devpriv->base_addr = ioremap(pci_resource_start(pcidev, 0),
-				     pci_resource_len(pcidev, 0));
-	if (!devpriv->base_addr)
+	devpriv->mmio = ioremap(pci_resource_start(pcidev, 0),
+				pci_resource_len(pcidev, 0));
+	if (!devpriv->mmio)
 		return -ENOMEM;
 
 	/* disable master interrupt */
-	writel(0, devpriv->base_addr + P_IER);
+	writel(0, devpriv->mmio + P_IER);
 
 	/* soft reset */
-	writel(MC1_SOFT_RESET, devpriv->base_addr + P_MC1);
+	writel(MC1_SOFT_RESET, devpriv->mmio + P_MC1);
 
 	/* DMA FIXME DMA// */
 
@@ -2707,79 +2630,79 @@ static int s626_auto_attach(struct comedi_device *dev,
 	if (ret)
 		return ret;
 
-	s = dev->subdevices + 0;
+	s = &dev->subdevices[0];
 	/* analog input subdevice */
-	dev->read_subdev = s;
-	/* we support single-ended (ground) and differential */
-	s->type = COMEDI_SUBD_AI;
-	s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_CMD_READ;
-	s->n_chan = S626_ADC_CHANNELS;
-	s->maxdata = (0xffff >> 2);
-	s->range_table = &s626_range_table;
-	s->len_chanlist = S626_ADC_CHANNELS;
-	s->insn_config = s626_ai_insn_config;
-	s->insn_read = s626_ai_insn_read;
-	s->do_cmd = s626_ai_cmd;
-	s->do_cmdtest = s626_ai_cmdtest;
-	s->cancel = s626_ai_cancel;
-
-	s = dev->subdevices + 1;
+	s->type		= COMEDI_SUBD_AI;
+	s->subdev_flags	= SDF_READABLE | SDF_DIFF | SDF_CMD_READ;
+	s->n_chan	= S626_ADC_CHANNELS;
+	s->maxdata	= 0x3fff;
+	s->range_table	= &s626_range_table;
+	s->len_chanlist	= S626_ADC_CHANNELS;
+	s->insn_read	= s626_ai_insn_read;
+	if (dev->irq) {
+		dev->read_subdev = s;
+		s->do_cmd	= s626_ai_cmd;
+		s->do_cmdtest	= s626_ai_cmdtest;
+		s->cancel	= s626_ai_cancel;
+	}
+
+	s = &dev->subdevices[1];
 	/* analog output subdevice */
-	s->type = COMEDI_SUBD_AO;
-	s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
-	s->n_chan = S626_DAC_CHANNELS;
-	s->maxdata = (0x3fff);
-	s->range_table = &range_bipolar10;
-	s->insn_write = s626_ao_winsn;
-	s->insn_read = s626_ao_rinsn;
-
-	s = dev->subdevices + 2;
+	s->type		= COMEDI_SUBD_AO;
+	s->subdev_flags	= SDF_WRITABLE | SDF_READABLE;
+	s->n_chan	= S626_DAC_CHANNELS;
+	s->maxdata	= 0x3fff;
+	s->range_table	= &range_bipolar10;
+	s->insn_write	= s626_ao_winsn;
+	s->insn_read	= s626_ao_rinsn;
+
+	s = &dev->subdevices[2];
 	/* digital I/O subdevice */
-	s->type = COMEDI_SUBD_DIO;
-	s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
-	s->n_chan = 16;
-	s->maxdata = 1;
-	s->io_bits = 0xffff;
-	s->private = &dio_private_A;
-	s->range_table = &range_digital;
-	s->insn_config = s626_dio_insn_config;
-	s->insn_bits = s626_dio_insn_bits;
-
-	s = dev->subdevices + 3;
+	s->type		= COMEDI_SUBD_DIO;
+	s->subdev_flags	= SDF_WRITABLE | SDF_READABLE;
+	s->n_chan	= 16;
+	s->maxdata	= 1;
+	s->io_bits	= 0xffff;
+	s->private	= (void *)0;	/* DIO group 0 */
+	s->range_table	= &range_digital;
+	s->insn_config	= s626_dio_insn_config;
+	s->insn_bits	= s626_dio_insn_bits;
+
+	s = &dev->subdevices[3];
 	/* digital I/O subdevice */
-	s->type = COMEDI_SUBD_DIO;
-	s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
-	s->n_chan = 16;
-	s->maxdata = 1;
-	s->io_bits = 0xffff;
-	s->private = &dio_private_B;
-	s->range_table = &range_digital;
-	s->insn_config = s626_dio_insn_config;
-	s->insn_bits = s626_dio_insn_bits;
-
-	s = dev->subdevices + 4;
+	s->type		= COMEDI_SUBD_DIO;
+	s->subdev_flags	= SDF_WRITABLE | SDF_READABLE;
+	s->n_chan	= 16;
+	s->maxdata	= 1;
+	s->io_bits	= 0xffff;
+	s->private	= (void *)1;	/* DIO group 1 */
+	s->range_table	= &range_digital;
+	s->insn_config	= s626_dio_insn_config;
+	s->insn_bits	= s626_dio_insn_bits;
+
+	s = &dev->subdevices[4];
 	/* digital I/O subdevice */
-	s->type = COMEDI_SUBD_DIO;
-	s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
-	s->n_chan = 16;
-	s->maxdata = 1;
-	s->io_bits = 0xffff;
-	s->private = &dio_private_C;
-	s->range_table = &range_digital;
-	s->insn_config = s626_dio_insn_config;
-	s->insn_bits = s626_dio_insn_bits;
-
-	s = dev->subdevices + 5;
+	s->type		= COMEDI_SUBD_DIO;
+	s->subdev_flags	= SDF_WRITABLE | SDF_READABLE;
+	s->n_chan	= 16;
+	s->maxdata	= 1;
+	s->io_bits	= 0xffff;
+	s->private	= (void *)2;	/* DIO group 2 */
+	s->range_table	= &range_digital;
+	s->insn_config 	= s626_dio_insn_config;
+	s->insn_bits	= s626_dio_insn_bits;
+
+	s = &dev->subdevices[5];
 	/* encoder (counter) subdevice */
-	s->type = COMEDI_SUBD_COUNTER;
-	s->subdev_flags = SDF_WRITABLE | SDF_READABLE | SDF_LSAMPL;
-	s->n_chan = S626_ENCODER_CHANNELS;
-	s->private = enc_private_data;
-	s->insn_config = s626_enc_insn_config;
-	s->insn_read = s626_enc_insn_read;
-	s->insn_write = s626_enc_insn_write;
-	s->maxdata = 0xffffff;
-	s->range_table = &range_unknown;
+	s->type		= COMEDI_SUBD_COUNTER;
+	s->subdev_flags	= SDF_WRITABLE | SDF_READABLE | SDF_LSAMPL;
+	s->n_chan	= S626_ENCODER_CHANNELS;
+	s->maxdata	= 0xffffff;
+	s->private	= enc_private_data;
+	s->range_table	= &range_unknown;
+	s->insn_config	= s626_enc_insn_config;
+	s->insn_read	= s626_enc_insn_read;
+	s->insn_write	= s626_enc_insn_write;
 
 	s626_initialize(dev);
 
@@ -2790,24 +2713,26 @@ static int s626_auto_attach(struct comedi_device *dev,
 
 static void s626_detach(struct comedi_device *dev)
 {
-	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
 	struct s626_private *devpriv = dev->private;
 
 	if (devpriv) {
 		/* stop ai_command */
 		devpriv->ai_cmd_running = 0;
 
-		if (devpriv->base_addr) {
+		if (devpriv->mmio) {
 			/* interrupt mask */
-			WR7146(P_IER, 0);	/*  Disable master interrupt. */
-			WR7146(P_ISR, IRQ_GPIO3 | IRQ_RPS1);	/*  Clear board's IRQ status flag. */
+			/* Disable master interrupt */
+			writel(0, devpriv->mmio + P_IER);
+			/* Clear board's IRQ status flag */
+			writel(IRQ_GPIO3 | IRQ_RPS1,
+			       devpriv->mmio + P_ISR);
 
 			/*  Disable the watchdog timer and battery charger. */
 			WriteMISC2(dev, 0);
 
-			/*  Close all interfaces on 7146 device. */
-			WR7146(P_MC1, MC1_SHUTDOWN);
-			WR7146(P_ACON1, ACON1_BASE);
+			/* Close all interfaces on 7146 device */
+			writel(MC1_SHUTDOWN, devpriv->mmio + P_MC1);
+			writel(ACON1_BASE, devpriv->mmio + P_ACON1);
 
 			CloseDMAB(dev, &devpriv->RPSBuf, DMABUF_SIZE);
 			CloseDMAB(dev, &devpriv->ANABuf, DMABUF_SIZE);
@@ -2815,13 +2740,10 @@ static void s626_detach(struct comedi_device *dev)
 
 		if (dev->irq)
 			free_irq(dev->irq, dev);
-		if (devpriv->base_addr)
-			iounmap(devpriv->base_addr);
-	}
-	if (pcidev) {
-		if (dev->iobase)
-			comedi_pci_disable(pcidev);
+		if (devpriv->mmio)
+			iounmap(devpriv->mmio);
 	}
+	comedi_pci_disable(dev);
 }
 
 static struct comedi_driver s626_driver = {
@@ -2832,9 +2754,9 @@ static struct comedi_driver s626_driver = {
 };
 
 static int s626_pci_probe(struct pci_dev *dev,
-				    const struct pci_device_id *ent)
+			  const struct pci_device_id *id)
 {
-	return comedi_pci_auto_config(dev, &s626_driver);
+	return comedi_pci_auto_config(dev, &s626_driver, id->driver_data);
 }
 
 /*
diff --git a/drivers/staging/comedi/drivers/s626.h b/drivers/staging/comedi/drivers/s626.h
index ff4b3a5..99cd57b 100644
--- a/drivers/staging/comedi/drivers/s626.h
+++ b/drivers/staging/comedi/drivers/s626.h
@@ -267,36 +267,17 @@
 #define LP_DACPOL		0x0082	/*   Write DAC polarity. */
 #define LP_GSEL			0x0084	/*   Write ADC gain. */
 #define LP_ISEL			0x0086	/*   Write ADC channel select. */
-/*  Digital I/O (write only): */
-#define LP_WRINTSELA		0x0042	/*   Write A interrupt enable. */
-#define LP_WREDGSELA		0x0044	/*   Write A edge selection. */
-#define LP_WRCAPSELA		0x0046	/*   Write A capture enable. */
-#define LP_WRDOUTA		0x0048	/*   Write A digital output. */
-#define LP_WRINTSELB		0x0052	/*   Write B interrupt enable. */
-#define LP_WREDGSELB		0x0054	/*   Write B edge selection. */
-#define LP_WRCAPSELB		0x0056	/*   Write B capture enable. */
-#define LP_WRDOUTB		0x0058	/*   Write B digital output. */
-#define LP_WRINTSELC		0x0062	/*   Write C interrupt enable. */
-#define LP_WREDGSELC		0x0064	/*   Write C edge selection. */
-#define LP_WRCAPSELC		0x0066	/*   Write C capture enable. */
-#define LP_WRDOUTC		0x0068	/*   Write C digital output. */
-
-/*  Digital I/O (read only): */
-#define LP_RDDINA		0x0040	/*   Read digital input. */
-#define LP_RDCAPFLGA		0x0048	/*   Read edges captured. */
-#define LP_RDINTSELA		0x004A	/*   Read interrupt enable register. */
-#define LP_RDEDGSELA		0x004C	/*   Read edge selection register. */
-#define LP_RDCAPSELA		0x004E	/*   Read capture enable register. */
-#define LP_RDDINB		0x0050	/*   Read digital input. */
-#define LP_RDCAPFLGB		0x0058	/*   Read edges captured. */
-#define LP_RDINTSELB		0x005A	/*   Read interrupt enable register. */
-#define LP_RDEDGSELB		0x005C	/*   Read edge selection register. */
-#define LP_RDCAPSELB		0x005E	/*   Read capture enable register. */
-#define LP_RDDINC		0x0060	/*   Read digital input. */
-#define LP_RDCAPFLGC		0x0068	/*   Read edges captured. */
-#define LP_RDINTSELC		0x006A	/*   Read interrupt enable register. */
-#define LP_RDEDGSELC		0x006C	/*   Read edge selection register. */
-#define LP_RDCAPSELC		0x006E	/*   Read capture enable register. */
+
+/* Digital I/O registers */
+#define LP_RDDIN(x)		(0x0040 + (x) * 0x10)	/* R: digital input */
+#define LP_WRINTSEL(x)		(0x0042 + (x) * 0x10)	/* W: int enable */
+#define LP_WREDGSEL(x)		(0x0044 + (x) * 0x10)	/* W: edge selection */
+#define LP_WRCAPSEL(x)		(0x0046 + (x) * 0x10)	/* W: capture enable */
+#define LP_RDCAPFLG(x)		(0x0048 + (x) * 0x10)	/* R: edges captured */
+#define LP_WRDOUT(x)		(0x0048 + (x) * 0x10)	/* W: digital output */
+#define LP_RDINTSEL(x)		(0x004a + (x) * 0x10)	/* R: int enable */
+#define LP_RDEDGSEL(x)		(0x004c + (x) * 0x10)	/* R: edge selection */
+#define LP_RDCAPSEL(x)		(0x004e + (x) * 0x10)	/* R: capture enable */
 
 /*  Counter Registers (read/write): */
 #define LP_CR0A			0x0000	/*   0A setup register. */
@@ -661,27 +642,27 @@
 
 /*  Bit field masks for CRA and CRB. */
 
-#define CRAMSK_INDXSRC_B	((uint16_t)(3 << CRABIT_INDXSRC_B))
-#define CRAMSK_CLKSRC_B		((uint16_t)(3 << CRABIT_CLKSRC_B))
-#define CRAMSK_INDXPOL_A	((uint16_t)(1 << CRABIT_INDXPOL_A))
-#define CRAMSK_LOADSRC_A	((uint16_t)(3 << CRABIT_LOADSRC_A))
-#define CRAMSK_CLKMULT_A	((uint16_t)(3 << CRABIT_CLKMULT_A))
-#define CRAMSK_INTSRC_A		((uint16_t)(3 << CRABIT_INTSRC_A))
-#define CRAMSK_CLKPOL_A		((uint16_t)(3 << CRABIT_CLKPOL_A))
-#define CRAMSK_INDXSRC_A	((uint16_t)(3 << CRABIT_INDXSRC_A))
-#define CRAMSK_CLKSRC_A		((uint16_t)(3 << CRABIT_CLKSRC_A))
-
-#define CRBMSK_INTRESETCMD	((uint16_t)(1 << CRBBIT_INTRESETCMD))
-#define CRBMSK_INTRESET_B	((uint16_t)(1 << CRBBIT_INTRESET_B))
-#define CRBMSK_INTRESET_A	((uint16_t)(1 << CRBBIT_INTRESET_A))
-#define CRBMSK_CLKENAB_A	((uint16_t)(1 << CRBBIT_CLKENAB_A))
-#define CRBMSK_INTSRC_B		((uint16_t)(3 << CRBBIT_INTSRC_B))
-#define CRBMSK_LATCHSRC		((uint16_t)(3 << CRBBIT_LATCHSRC))
-#define CRBMSK_LOADSRC_B	((uint16_t)(3 << CRBBIT_LOADSRC_B))
-#define CRBMSK_CLKMULT_B	((uint16_t)(3 << CRBBIT_CLKMULT_B))
-#define CRBMSK_CLKENAB_B	((uint16_t)(1 << CRBBIT_CLKENAB_B))
-#define CRBMSK_INDXPOL_B	((uint16_t)(1 << CRBBIT_INDXPOL_B))
-#define CRBMSK_CLKPOL_B		((uint16_t)(1 << CRBBIT_CLKPOL_B))
+#define CRAMSK_INDXSRC_B	(3 << CRABIT_INDXSRC_B)
+#define CRAMSK_CLKSRC_B		(3 << CRABIT_CLKSRC_B)
+#define CRAMSK_INDXPOL_A	(1 << CRABIT_INDXPOL_A)
+#define CRAMSK_LOADSRC_A	(3 << CRABIT_LOADSRC_A)
+#define CRAMSK_CLKMULT_A	(3 << CRABIT_CLKMULT_A)
+#define CRAMSK_INTSRC_A		(3 << CRABIT_INTSRC_A)
+#define CRAMSK_CLKPOL_A		(3 << CRABIT_CLKPOL_A)
+#define CRAMSK_INDXSRC_A	(3 << CRABIT_INDXSRC_A)
+#define CRAMSK_CLKSRC_A		(3 << CRABIT_CLKSRC_A)
+
+#define CRBMSK_INTRESETCMD	(1 << CRBBIT_INTRESETCMD)
+#define CRBMSK_INTRESET_B	(1 << CRBBIT_INTRESET_B)
+#define CRBMSK_INTRESET_A	(1 << CRBBIT_INTRESET_A)
+#define CRBMSK_CLKENAB_A	(1 << CRBBIT_CLKENAB_A)
+#define CRBMSK_INTSRC_B		(3 << CRBBIT_INTSRC_B)
+#define CRBMSK_LATCHSRC		(3 << CRBBIT_LATCHSRC)
+#define CRBMSK_LOADSRC_B	(3 << CRBBIT_LOADSRC_B)
+#define CRBMSK_CLKMULT_B	(3 << CRBBIT_CLKMULT_B)
+#define CRBMSK_CLKENAB_B	(1 << CRBBIT_CLKENAB_B)
+#define CRBMSK_INDXPOL_B	(1 << CRBBIT_INDXPOL_B)
+#define CRBMSK_CLKPOL_B		(1 << CRBBIT_CLKPOL_B)
 
 #define CRBMSK_INTCTRL		(CRBMSK_INTRESETCMD | CRBMSK_INTRESET_A | CRBMSK_INTRESET_B)	/*  Interrupt reset control bits. */
 
@@ -699,15 +680,15 @@
 
 /*  Bit field masks for standardized SETUP structure. */
 
-#define STDMSK_INTSRC		((uint16_t)(3 << STDBIT_INTSRC))
-#define STDMSK_LATCHSRC		((uint16_t)(3 << STDBIT_LATCHSRC))
-#define STDMSK_LOADSRC		((uint16_t)(3 << STDBIT_LOADSRC))
-#define STDMSK_INDXSRC		((uint16_t)(1 << STDBIT_INDXSRC))
-#define STDMSK_INDXPOL		((uint16_t)(1 << STDBIT_INDXPOL))
-#define STDMSK_CLKSRC		((uint16_t)(3 << STDBIT_CLKSRC))
-#define STDMSK_CLKPOL		((uint16_t)(1 << STDBIT_CLKPOL))
-#define STDMSK_CLKMULT		((uint16_t)(3 << STDBIT_CLKMULT))
-#define STDMSK_CLKENAB		((uint16_t)(1 << STDBIT_CLKENAB))
+#define STDMSK_INTSRC		(3 << STDBIT_INTSRC)
+#define STDMSK_LATCHSRC		(3 << STDBIT_LATCHSRC)
+#define STDMSK_LOADSRC		(3 << STDBIT_LOADSRC)
+#define STDMSK_INDXSRC		(1 << STDBIT_INDXSRC)
+#define STDMSK_INDXPOL		(1 << STDBIT_INDXPOL)
+#define STDMSK_CLKSRC		(3 << STDBIT_CLKSRC)
+#define STDMSK_CLKPOL		(1 << STDBIT_CLKPOL)
+#define STDMSK_CLKMULT		(3 << STDBIT_CLKMULT)
+#define STDMSK_CLKENAB		(1 << STDBIT_CLKENAB)
 
 struct bufferDMA {
 	dma_addr_t PhysicalBase;
diff --git a/drivers/staging/comedi/drivers/skel.c b/drivers/staging/comedi/drivers/skel.c
index cb83f6a..6fb7d5d 100644
--- a/drivers/staging/comedi/drivers/skel.c
+++ b/drivers/staging/comedi/drivers/skel.c
@@ -90,29 +90,30 @@ Configuration Options:
  * boards in this way is optional, and completely driver-dependent.
  * Some drivers use arrays such as this, other do not.
  */
+enum skel_boardid {
+	BOARD_SKEL100,
+	BOARD_SKEL200,
+};
+
 struct skel_board {
 	const char *name;
-	unsigned int devid;
 	int ai_chans;
 	int ai_bits;
 	int have_dio;
 };
 
 static const struct skel_board skel_boards[] = {
-	{
-	 .name = "skel-100",
-	 .devid = 0x100,
-	 .ai_chans = 16,
-	 .ai_bits = 12,
-	 .have_dio = 1,
-	 },
-	{
-	 .name = "skel-200",
-	 .devid = 0x200,
-	 .ai_chans = 8,
-	 .ai_bits = 16,
-	 .have_dio = 0,
-	 },
+	[BOARD_SKEL100] = {
+		.name		= "skel-100",
+		.ai_chans	= 16,
+		.ai_bits	= 12,
+		.have_dio	= 1,
+	},
+	[BOARD_SKEL200] = {
+		.name		= "skel-200",
+		.ai_chans	= 8,
+		.ai_bits	= 16,
+	},
 };
 
 /* this structure is for data unique to this hardware driver.  If
@@ -394,22 +395,6 @@ static int skel_dio_insn_config(struct comedi_device *dev,
 	return insn->n;
 }
 
-static const struct skel_board *skel_find_pci_board(struct pci_dev *pcidev)
-{
-	unsigned int i;
-
-/*
- * This example code assumes all the entries in skel_boards[] are PCI boards
- * and all use the same PCI vendor ID.  If skel_boards[] contains a mixture
- * of PCI and non-PCI boards, this loop should skip over the non-PCI boards.
- */
-	for (i = 0; i < ARRAY_SIZE(skel_boards); i++)
-		if (/* skel_boards[i].bustype == pci_bustype && */
-		    pcidev->device == skel_boards[i].devid)
-			return &skel_boards[i];
-	return NULL;
-}
-
 /*
  * Handle common part of skel_attach() and skel_auto_attach().
  */
@@ -541,16 +526,13 @@ static int skel_attach(struct comedi_device *dev, struct comedi_devconfig *it)
  * comedi_usb_auto_config(), etc.) to handle devices that can be attached
  * to the Comedi core automatically without the COMEDI_DEVCONFIG ioctl.
  *
- * The context parameter is usually unused, but if the driver called
- * comedi_auto_config() directly instead of the comedi_pci_auto_config()
- * wrapper function, this will be a copy of the context passed to
- * comedi_auto_config().
+ * The context parameter is driver dependent.
  */
 static int skel_auto_attach(struct comedi_device *dev,
-				      unsigned long context)
+			    unsigned long context)
 {
 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-	const struct skel_board *thisboard;
+	const struct skel_board *thisboard = NULL;
 	struct skel_private *devpriv;
 	int ret;
 
@@ -558,12 +540,18 @@ static int skel_auto_attach(struct comedi_device *dev,
 	if (!IS_ENABLED(CONFIG_COMEDI_PCI_DRIVERS))
 		return -EINVAL;
 
-	/* Find a matching board in skel_boards[]. */
-	thisboard = skel_find_pci_board(pcidev);
-	if (!thisboard) {
-		dev_err(dev->class_dev, "BUG! cannot determine board type!\n");
-		return -EINVAL;
-	}
+	/*
+	 * In this example, the _auto_attach is for a PCI device.
+	 *
+	 * The 'context' passed to this function is the id->driver_data
+	 * associated with the PCI device found in the id_table during
+	 * the modprobe. This 'context' is the index of the entry in
+	 * skel_boards[i] that contains the boardinfo for the PCI device.
+	 */
+	if (context < ARRAY_SIZE(skel_boards))
+		thisboard = &skel_boards[context];
+	if (!thisboard)
+		return -ENODEV;
 
 	/*
 	 * Point the struct comedi_device to the matching board info
@@ -579,7 +567,7 @@ static int skel_auto_attach(struct comedi_device *dev,
 	dev->private = devpriv;
 
 	/* Enable the PCI device. */
-	ret = comedi_pci_enable(pcidev, dev->board_name);
+	ret = comedi_pci_enable(dev);
 	if (ret)
 		return ret;
 
@@ -618,7 +606,6 @@ static void skel_detach(struct comedi_device *dev)
 {
 	const struct skel_board *thisboard = comedi_board(dev);
 	struct skel_private *devpriv = dev->private;
-	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
 
 	if (!thisboard || !devpriv)
 		return;
@@ -638,8 +625,7 @@ static void skel_detach(struct comedi_device *dev)
 		 * If PCI device enabled by _auto_attach() (or _attach()),
 		 * disable it here.
 		 */
-		if (pcidev && dev->iobase)
-			comedi_pci_disable(pcidev);
+		comedi_pci_disable(dev);
 	} else {
 		/*
 		 * ISA board
@@ -689,28 +675,33 @@ static struct comedi_driver skel_driver = {
 
 #ifdef CONFIG_COMEDI_PCI_DRIVERS
 
-/* This is used by modprobe to translate PCI IDs to drivers.  Should
- * only be used for PCI and ISA-PnP devices */
-/* Please add your PCI vendor ID to comedidev.h, and it will be forwarded
- * upstream. */
-#define PCI_VENDOR_ID_SKEL 0xdafe
+static int skel_pci_probe(struct pci_dev *dev,
+			  const struct pci_device_id *id)
+{
+	return comedi_pci_auto_config(dev, &skel_driver, id->driver_data);
+}
+
+/*
+ * Please add your PCI vendor ID to comedidev.h, and it will
+ * be forwarded upstream.
+ */
+#define PCI_VENDOR_ID_SKEL	0xdafe
+
+/*
+ * This is used by modprobe to translate PCI IDs to drivers.
+ * Should only be used for PCI and ISA-PnP devices
+ */
 static DEFINE_PCI_DEVICE_TABLE(skel_pci_table) = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_SKEL, 0x0100) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_SKEL, 0x0200) },
+	{ PCI_VDEVICE(SKEL, 0x0100), BOARD_SKEL100 },
+	{ PCI_VDEVICE(SKEL, 0x0200), BOARD_SKEL200 },
 	{ 0 }
 };
 MODULE_DEVICE_TABLE(pci, skel_pci_table);
 
-static int skel_pci_probe(struct pci_dev *dev,
-					   const struct pci_device_id *ent)
-{
-	return comedi_pci_auto_config(dev, &skel_driver);
-}
-
 static struct pci_driver skel_pci_driver = {
-	.name = "dummy",
-	.id_table = skel_pci_table,
-	.probe = &skel_pci_probe,
+	.name		= "dummy",
+	.id_table	= skel_pci_table,
+	.probe		= skel_pci_probe,
 	.remove		= comedi_pci_auto_unconfig,
 };
 module_comedi_pci_driver(skel_driver, skel_pci_driver);
diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c
index 6aac1f6..148ecfc 100644
--- a/drivers/staging/comedi/drivers/usbdux.c
+++ b/drivers/staging/comedi/drivers/usbdux.c
@@ -56,7 +56,7 @@ sampling rate. If you sample two channels you get 4kHz and so on.
  *       functions firmware upload is by fxload and no longer by comedi (due to
  *       enumeration)
  * 0.97: USB IDs received, adjusted table
- * 0.98: SMP, locking, memroy alloc: moved all usb memory alloc
+ * 0.98: SMP, locking, memory alloc: moved all usb memory alloc
  *       to the usb subsystem and moved all comedi related memory
  *       alloc to comedi.
  *       | kernel | registration | usbdux-usb | usbdux-comedi | comedi |
@@ -250,26 +250,26 @@ struct usbduxsub {
 	/* pointer to the usb-device */
 	struct usb_device *usbdev;
 	/* actual number of in-buffers */
-	int numOfInBuffers;
+	int num_in_buffers;
 	/* actual number of out-buffers */
-	int numOfOutBuffers;
+	int num_out_buffers;
 	/* ISO-transfer handling: buffers */
-	struct urb **urbIn;
-	struct urb **urbOut;
+	struct urb **urb_in;
+	struct urb **urb_out;
 	/* pwm-transfer handling */
-	struct urb *urbPwm;
+	struct urb *urb_pwm;
 	/* PWM period */
-	unsigned int pwmPeriod;
+	unsigned int pwm_period;
 	/* PWM internal delay for the GPIF in the FX2 */
-	int8_t pwmDelay;
+	int8_t pwn_delay;
 	/* size of the PWM buffer which holds the bit pattern */
-	int sizePwmBuf;
+	int size_pwm_buf;
 	/* input buffer for the ISO-transfer */
-	int16_t *inBuffer;
+	int16_t *in_buffer;
 	/* input buffer for single insn */
-	int16_t *insnBuffer;
+	int16_t *insn_buffer;
 	/* output buffer for single DA outputs */
-	int16_t *outBuffer;
+	int16_t *out_buffer;
 	/* interface number */
 	int ifnum;
 	/* interface structure in 2.6 */
@@ -319,17 +319,17 @@ static DEFINE_SEMAPHORE(start_stop_sem);
  * Stops the data acquision
  * It should be safe to call this function from any context
  */
-static int usbduxsub_unlink_InURBs(struct usbduxsub *usbduxsub_tmp)
+static int usbduxsub_unlink_inurbs(struct usbduxsub *usbduxsub_tmp)
 {
 	int i = 0;
 	int err = 0;
 
-	if (usbduxsub_tmp && usbduxsub_tmp->urbIn) {
-		for (i = 0; i < usbduxsub_tmp->numOfInBuffers; i++) {
-			if (usbduxsub_tmp->urbIn[i]) {
+	if (usbduxsub_tmp && usbduxsub_tmp->urb_in) {
+		for (i = 0; i < usbduxsub_tmp->num_in_buffers; i++) {
+			if (usbduxsub_tmp->urb_in[i]) {
 				/* We wait here until all transfers have been
 				 * cancelled. */
-				usb_kill_urb(usbduxsub_tmp->urbIn[i]);
+				usb_kill_urb(usbduxsub_tmp->urb_in[i]);
 			}
 			dev_dbg(&usbduxsub_tmp->interface->dev,
 				"comedi: usbdux: unlinked InURB %d, err=%d\n",
@@ -356,7 +356,7 @@ static int usbdux_ai_stop(struct usbduxsub *this_usbduxsub, int do_unlink)
 
 	if (do_unlink) {
 		/* stop aquistion */
-		ret = usbduxsub_unlink_InURBs(this_usbduxsub);
+		ret = usbduxsub_unlink_inurbs(this_usbduxsub);
 	}
 
 	this_usbduxsub->ai_cmd_running = 0;
@@ -394,7 +394,7 @@ static int usbdux_ai_cancel(struct comedi_device *dev,
 }
 
 /* analogue IN - interrupt service routine */
-static void usbduxsub_ai_IsocIrq(struct urb *urb)
+static void usbduxsub_ai_isoc_irq(struct urb *urb)
 {
 	int i, err, n;
 	struct usbduxsub *this_usbduxsub;
@@ -412,7 +412,7 @@ static void usbduxsub_ai_IsocIrq(struct urb *urb)
 	switch (urb->status) {
 	case 0:
 		/* copy the result in the transfer buffer */
-		memcpy(this_usbduxsub->inBuffer,
+		memcpy(this_usbduxsub->in_buffer,
 		       urb->transfer_buffer, SIZEINBUF);
 		break;
 	case -EILSEQ:
@@ -517,11 +517,11 @@ static void usbduxsub_ai_IsocIrq(struct urb *urb)
 		if (CR_RANGE(s->async->cmd.chanlist[i]) <= 1) {
 			err = comedi_buf_put
 			    (s->async,
-			     le16_to_cpu(this_usbduxsub->inBuffer[i]) ^ 0x800);
+			     le16_to_cpu(this_usbduxsub->in_buffer[i]) ^ 0x800);
 		} else {
 			err = comedi_buf_put
 			    (s->async,
-			     le16_to_cpu(this_usbduxsub->inBuffer[i]));
+			     le16_to_cpu(this_usbduxsub->in_buffer[i]));
 		}
 		if (unlikely(err == 0)) {
 			/* buffer overflow */
@@ -534,15 +534,15 @@ static void usbduxsub_ai_IsocIrq(struct urb *urb)
 	comedi_event(this_usbduxsub->comedidev, s);
 }
 
-static int usbduxsub_unlink_OutURBs(struct usbduxsub *usbduxsub_tmp)
+static int usbduxsub_unlink_outurbs(struct usbduxsub *usbduxsub_tmp)
 {
 	int i = 0;
 	int err = 0;
 
-	if (usbduxsub_tmp && usbduxsub_tmp->urbOut) {
-		for (i = 0; i < usbduxsub_tmp->numOfOutBuffers; i++) {
-			if (usbduxsub_tmp->urbOut[i])
-				usb_kill_urb(usbduxsub_tmp->urbOut[i]);
+	if (usbduxsub_tmp && usbduxsub_tmp->urb_out) {
+		for (i = 0; i < usbduxsub_tmp->num_out_buffers; i++) {
+			if (usbduxsub_tmp->urb_out[i])
+				usb_kill_urb(usbduxsub_tmp->urb_out[i]);
 
 			dev_dbg(&usbduxsub_tmp->interface->dev,
 				"comedi: usbdux: unlinked OutURB %d: res=%d\n",
@@ -564,7 +564,7 @@ static int usbdux_ao_stop(struct usbduxsub *this_usbduxsub, int do_unlink)
 	dev_dbg(&this_usbduxsub->interface->dev, "comedi: usbdux_ao_cancel\n");
 
 	if (do_unlink)
-		ret = usbduxsub_unlink_OutURBs(this_usbduxsub);
+		ret = usbduxsub_unlink_outurbs(this_usbduxsub);
 
 	this_usbduxsub->ao_cmd_running = 0;
 
@@ -593,7 +593,7 @@ static int usbdux_ao_cancel(struct comedi_device *dev,
 	return res;
 }
 
-static void usbduxsub_ao_IsocIrq(struct urb *urb)
+static void usbduxsub_ao_isoc_irq(struct urb *urb)
 {
 	int i, ret;
 	int8_t *datap;
@@ -798,7 +798,7 @@ static int usbduxsub_stop(struct usbduxsub *usbduxsub)
 
 static int usbduxsub_upload(struct usbduxsub *usbduxsub,
 			    uint8_t *local_transfer_buffer,
-			    unsigned int startAddr, unsigned int len)
+			    unsigned int start_addr, unsigned int len)
 {
 	int errcode;
 
@@ -809,7 +809,7 @@ static int usbduxsub_upload(struct usbduxsub *usbduxsub,
 				  /* bmRequestType */
 				  VENDOR_DIR_OUT,
 				  /* value */
-				  startAddr,
+				  start_addr,
 				  /* index */
 				  0x0000,
 				  /* our local safe buffer */
@@ -828,24 +828,24 @@ static int usbduxsub_upload(struct usbduxsub *usbduxsub,
 
 #define FIRMWARE_MAX_LEN 0x2000
 
-static int firmwareUpload(struct usbduxsub *usbduxsub,
-			  const u8 *firmwareBinary, int sizeFirmware)
+static int firmware_upload(struct usbduxsub *usbduxsub,
+			  const u8 *firmware_binary, int size_firmware)
 {
 	int ret;
-	uint8_t *fwBuf;
+	uint8_t *fw_buf;
 
-	if (!firmwareBinary)
+	if (!firmware_binary)
 		return 0;
 
-	if (sizeFirmware > FIRMWARE_MAX_LEN) {
+	if (size_firmware > FIRMWARE_MAX_LEN) {
 		dev_err(&usbduxsub->interface->dev,
 			"usbdux firmware binary it too large for FX2.\n");
 		return -ENOMEM;
 	}
 
 	/* we generate a local buffer for the firmware */
-	fwBuf = kmemdup(firmwareBinary, sizeFirmware, GFP_KERNEL);
-	if (!fwBuf) {
+	fw_buf = kmemdup(firmware_binary, size_firmware, GFP_KERNEL);
+	if (!fw_buf) {
 		dev_err(&usbduxsub->interface->dev,
 			"comedi_: mem alloc for firmware failed\n");
 		return -ENOMEM;
@@ -855,81 +855,81 @@ static int firmwareUpload(struct usbduxsub *usbduxsub,
 	if (ret < 0) {
 		dev_err(&usbduxsub->interface->dev,
 			"comedi_: can not stop firmware\n");
-		kfree(fwBuf);
+		kfree(fw_buf);
 		return ret;
 	}
 
-	ret = usbduxsub_upload(usbduxsub, fwBuf, 0, sizeFirmware);
+	ret = usbduxsub_upload(usbduxsub, fw_buf, 0, size_firmware);
 	if (ret < 0) {
 		dev_err(&usbduxsub->interface->dev,
 			"comedi_: firmware upload failed\n");
-		kfree(fwBuf);
+		kfree(fw_buf);
 		return ret;
 	}
 	ret = usbduxsub_start(usbduxsub);
 	if (ret < 0) {
 		dev_err(&usbduxsub->interface->dev,
 			"comedi_: can not start firmware\n");
-		kfree(fwBuf);
+		kfree(fw_buf);
 		return ret;
 	}
-	kfree(fwBuf);
+	kfree(fw_buf);
 	return 0;
 }
 
-static int usbduxsub_submit_InURBs(struct usbduxsub *usbduxsub)
+static int usbduxsub_submit_inurbs(struct usbduxsub *usbduxsub)
 {
-	int i, errFlag;
+	int i, err_flag;
 
 	if (!usbduxsub)
 		return -EFAULT;
 
 	/* Submit all URBs and start the transfer on the bus */
-	for (i = 0; i < usbduxsub->numOfInBuffers; i++) {
+	for (i = 0; i < usbduxsub->num_in_buffers; i++) {
 		/* in case of a resubmission after an unlink... */
-		usbduxsub->urbIn[i]->interval = usbduxsub->ai_interval;
-		usbduxsub->urbIn[i]->context = usbduxsub->comedidev;
-		usbduxsub->urbIn[i]->dev = usbduxsub->usbdev;
-		usbduxsub->urbIn[i]->status = 0;
-		usbduxsub->urbIn[i]->transfer_flags = URB_ISO_ASAP;
+		usbduxsub->urb_in[i]->interval = usbduxsub->ai_interval;
+		usbduxsub->urb_in[i]->context = usbduxsub->comedidev;
+		usbduxsub->urb_in[i]->dev = usbduxsub->usbdev;
+		usbduxsub->urb_in[i]->status = 0;
+		usbduxsub->urb_in[i]->transfer_flags = URB_ISO_ASAP;
 		dev_dbg(&usbduxsub->interface->dev,
 			"comedi%d: submitting in-urb[%d]: %p,%p intv=%d\n",
 			usbduxsub->comedidev->minor, i,
-			(usbduxsub->urbIn[i]->context),
-			(usbduxsub->urbIn[i]->dev),
-			(usbduxsub->urbIn[i]->interval));
-		errFlag = usb_submit_urb(usbduxsub->urbIn[i], GFP_ATOMIC);
-		if (errFlag) {
+			(usbduxsub->urb_in[i]->context),
+			(usbduxsub->urb_in[i]->dev),
+			(usbduxsub->urb_in[i]->interval));
+		err_flag = usb_submit_urb(usbduxsub->urb_in[i], GFP_ATOMIC);
+		if (err_flag) {
 			dev_err(&usbduxsub->interface->dev,
 				"comedi_: ai: usb_submit_urb(%d) error %d\n",
-				i, errFlag);
-			return errFlag;
+				i, err_flag);
+			return err_flag;
 		}
 	}
 	return 0;
 }
 
-static int usbduxsub_submit_OutURBs(struct usbduxsub *usbduxsub)
+static int usbduxsub_submit_outurbs(struct usbduxsub *usbduxsub)
 {
-	int i, errFlag;
+	int i, err_flag;
 
 	if (!usbduxsub)
 		return -EFAULT;
 
-	for (i = 0; i < usbduxsub->numOfOutBuffers; i++) {
+	for (i = 0; i < usbduxsub->num_out_buffers; i++) {
 		dev_dbg(&usbduxsub->interface->dev,
 			"comedi_: submitting out-urb[%d]\n", i);
 		/* in case of a resubmission after an unlink... */
-		usbduxsub->urbOut[i]->context = usbduxsub->comedidev;
-		usbduxsub->urbOut[i]->dev = usbduxsub->usbdev;
-		usbduxsub->urbOut[i]->status = 0;
-		usbduxsub->urbOut[i]->transfer_flags = URB_ISO_ASAP;
-		errFlag = usb_submit_urb(usbduxsub->urbOut[i], GFP_ATOMIC);
-		if (errFlag) {
+		usbduxsub->urb_out[i]->context = usbduxsub->comedidev;
+		usbduxsub->urb_out[i]->dev = usbduxsub->usbdev;
+		usbduxsub->urb_out[i]->status = 0;
+		usbduxsub->urb_out[i]->transfer_flags = URB_ISO_ASAP;
+		err_flag = usb_submit_urb(usbduxsub->urb_out[i], GFP_ATOMIC);
+		if (err_flag) {
 			dev_err(&usbduxsub->interface->dev,
 				"comedi_: ao: usb_submit_urb(%d) error %d\n",
-				i, errFlag);
-			return errFlag;
+				i, err_flag);
+			return err_flag;
 		}
 	}
 	return 0;
@@ -940,7 +940,7 @@ static int usbdux_ai_cmdtest(struct comedi_device *dev,
 {
 	struct usbduxsub *this_usbduxsub = dev->private;
 	int err = 0, i;
-	unsigned int tmpTimer;
+	unsigned int tmp_timer;
 
 	if (!(this_usbduxsub->probed))
 		return -ENODEV;
@@ -990,7 +990,7 @@ static int usbdux_ai_cmdtest(struct comedi_device *dev,
 							 1000000 / 8 * i);
 			/* now calc the real sampling rate with all the
 			 * rounding errors */
-			tmpTimer =
+			tmp_timer =
 			    ((unsigned int)(cmd->scan_begin_arg / 125000)) *
 			    125000;
 		} else {
@@ -1001,11 +1001,11 @@ static int usbdux_ai_cmdtest(struct comedi_device *dev,
 			/*
 			 * calc the real sampling rate with the rounding errors
 			 */
-			tmpTimer = ((unsigned int)(cmd->scan_begin_arg /
+			tmp_timer = ((unsigned int)(cmd->scan_begin_arg /
 						   1000000)) * 1000000;
 		}
 		err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg,
-						tmpTimer);
+						tmp_timer);
 	}
 
 	err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
@@ -1081,7 +1081,7 @@ static int receive_dux_commands(struct usbduxsub *this_usbduxsub, int command)
 		result = usb_bulk_msg(this_usbduxsub->usbdev,
 				      usb_rcvbulkpipe(this_usbduxsub->usbdev,
 						      COMMAND_IN_EP),
-				      this_usbduxsub->insnBuffer, SIZEINSNBUF,
+				      this_usbduxsub->insn_buffer, SIZEINSNBUF,
 				      &nrec, BULK_TIMEOUT);
 		if (result < 0) {
 			dev_err(&this_usbduxsub->interface->dev, "comedi%d: "
@@ -1089,7 +1089,7 @@ static int receive_dux_commands(struct usbduxsub *this_usbduxsub, int command)
 				"\n", this_usbduxsub->comedidev->minor, result);
 			return result;
 		}
-		if (le16_to_cpu(this_usbduxsub->insnBuffer[0]) == command)
+		if (le16_to_cpu(this_usbduxsub->insn_buffer[0]) == command)
 			return result;
 	}
 	/* this is only reached if the data has been requested a couple of
@@ -1097,7 +1097,7 @@ static int receive_dux_commands(struct usbduxsub *this_usbduxsub, int command)
 	dev_err(&this_usbduxsub->interface->dev, "comedi%d: insn: "
 		"wrong data returned from firmware: want cmd %d, got cmd %d.\n",
 		this_usbduxsub->comedidev->minor, command,
-		le16_to_cpu(this_usbduxsub->insnBuffer[0]));
+		le16_to_cpu(this_usbduxsub->insn_buffer[0]));
 	return -EFAULT;
 }
 
@@ -1126,7 +1126,7 @@ static int usbdux_ai_inttrig(struct comedi_device *dev,
 	}
 	if (!(this_usbduxsub->ai_cmd_running)) {
 		this_usbduxsub->ai_cmd_running = 1;
-		ret = usbduxsub_submit_InURBs(this_usbduxsub);
+		ret = usbduxsub_submit_inurbs(this_usbduxsub);
 		if (ret < 0) {
 			dev_err(&this_usbduxsub->interface->dev,
 				"comedi%d: usbdux_ai_inttrig: "
@@ -1243,7 +1243,7 @@ static int usbdux_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 	if (cmd->start_src == TRIG_NOW) {
 		/* enable this acquisition operation */
 		this_usbduxsub->ai_cmd_running = 1;
-		ret = usbduxsub_submit_InURBs(this_usbduxsub);
+		ret = usbduxsub_submit_inurbs(this_usbduxsub);
 		if (ret < 0) {
 			this_usbduxsub->ai_cmd_running = 0;
 			/* fixme: unlink here?? */
@@ -1311,7 +1311,7 @@ static int usbdux_ai_insn_read(struct comedi_device *dev,
 			up(&this_usbduxsub->sem);
 			return 0;
 		}
-		one = le16_to_cpu(this_usbduxsub->insnBuffer[1]);
+		one = le16_to_cpu(this_usbduxsub->insn_buffer[1]);
 		if (CR_RANGE(insn->chanspec) <= 1)
 			one = one ^ 0x800;
 
@@ -1341,7 +1341,7 @@ static int usbdux_ao_insn_read(struct comedi_device *dev,
 		return -ENODEV;
 	}
 	for (i = 0; i < insn->n; i++)
-		data[i] = this_usbduxsub->outBuffer[chan];
+		data[i] = this_usbduxsub->out_buffer[chan];
 
 	up(&this_usbduxsub->sem);
 	return i;
@@ -1384,7 +1384,7 @@ static int usbdux_ao_insn_write(struct comedi_device *dev,
 		/* one 16 bit value */
 		*((int16_t *) (this_usbduxsub->dux_commands + 2)) =
 		    cpu_to_le16(data[i]);
-		this_usbduxsub->outBuffer[chan] = data[i];
+		this_usbduxsub->out_buffer[chan] = data[i];
 		/* channel number */
 		this_usbduxsub->dux_commands[4] = (chan << 6);
 		err = send_dux_commands(this_usbduxsub, SENDDACOMMANDS);
@@ -1421,7 +1421,7 @@ static int usbdux_ao_inttrig(struct comedi_device *dev,
 	}
 	if (!(this_usbduxsub->ao_cmd_running)) {
 		this_usbduxsub->ao_cmd_running = 1;
-		ret = usbduxsub_submit_OutURBs(this_usbduxsub);
+		ret = usbduxsub_submit_outurbs(this_usbduxsub);
 		if (ret < 0) {
 			dev_err(&this_usbduxsub->interface->dev,
 				"comedi%d: usbdux_ao_inttrig: submitURB: "
@@ -1616,7 +1616,7 @@ static int usbdux_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 	if (cmd->start_src == TRIG_NOW) {
 		/* enable this acquisition operation */
 		this_usbduxsub->ao_cmd_running = 1;
-		ret = usbduxsub_submit_OutURBs(this_usbduxsub);
+		ret = usbduxsub_submit_outurbs(this_usbduxsub);
 		if (ret < 0) {
 			this_usbduxsub->ao_cmd_running = 0;
 			/* fixme: unlink here?? */
@@ -1704,7 +1704,7 @@ static int usbdux_dio_insn_bits(struct comedi_device *dev,
 		return err;
 	}
 
-	data[1] = le16_to_cpu(this_usbduxsub->insnBuffer[1]);
+	data[1] = le16_to_cpu(this_usbduxsub->insn_buffer[1]);
 	up(&this_usbduxsub->sem);
 	return insn->n;
 }
@@ -1740,7 +1740,7 @@ static int usbdux_counter_read(struct comedi_device *dev,
 		return err;
 	}
 
-	data[0] = le16_to_cpu(this_usbduxsub->insnBuffer[chan + 1]);
+	data[0] = le16_to_cpu(this_usbduxsub->insn_buffer[chan + 1]);
 	up(&this_usbduxsub->sem);
 	return 1;
 }
@@ -1787,13 +1787,13 @@ static int usbdux_counter_config(struct comedi_device *dev,
 /***********************************/
 /* PWM */
 
-static int usbduxsub_unlink_PwmURBs(struct usbduxsub *usbduxsub_tmp)
+static int usbduxsub_unlink_pwm_urbs(struct usbduxsub *usbduxsub_tmp)
 {
 	int err = 0;
 
-	if (usbduxsub_tmp && usbduxsub_tmp->urbPwm) {
-		if (usbduxsub_tmp->urbPwm)
-			usb_kill_urb(usbduxsub_tmp->urbPwm);
+	if (usbduxsub_tmp && usbduxsub_tmp->urb_pwm) {
+		if (usbduxsub_tmp->urb_pwm)
+			usb_kill_urb(usbduxsub_tmp->urb_pwm);
 		dev_dbg(&usbduxsub_tmp->interface->dev,
 			"comedi: unlinked PwmURB: res=%d\n", err);
 	}
@@ -1812,7 +1812,7 @@ static int usbdux_pwm_stop(struct usbduxsub *this_usbduxsub, int do_unlink)
 
 	dev_dbg(&this_usbduxsub->interface->dev, "comedi: %s\n", __func__);
 	if (do_unlink)
-		ret = usbduxsub_unlink_PwmURBs(this_usbduxsub);
+		ret = usbduxsub_unlink_pwm_urbs(this_usbduxsub);
 
 	this_usbduxsub->pwm_cmd_running = 0;
 
@@ -1885,7 +1885,7 @@ static void usbduxsub_pwm_irq(struct urb *urb)
 	if (!(this_usbduxsub->pwm_cmd_running))
 		return;
 
-	urb->transfer_buffer_length = this_usbduxsub->sizePwmBuf;
+	urb->transfer_buffer_length = this_usbduxsub->size_pwm_buf;
 	urb->dev = this_usbduxsub->usbdev;
 	urb->status = 0;
 	if (this_usbduxsub->pwm_cmd_running) {
@@ -1905,9 +1905,9 @@ static void usbduxsub_pwm_irq(struct urb *urb)
 	}
 }
 
-static int usbduxsub_submit_PwmURBs(struct usbduxsub *usbduxsub)
+static int usbduxsub_submit_pwm_urbs(struct usbduxsub *usbduxsub)
 {
-	int errFlag;
+	int err_flag;
 
 	if (!usbduxsub)
 		return -EFAULT;
@@ -1915,19 +1915,19 @@ static int usbduxsub_submit_PwmURBs(struct usbduxsub *usbduxsub)
 	dev_dbg(&usbduxsub->interface->dev, "comedi_: submitting pwm-urb\n");
 
 	/* in case of a resubmission after an unlink... */
-	usb_fill_bulk_urb(usbduxsub->urbPwm,
+	usb_fill_bulk_urb(usbduxsub->urb_pwm,
 			  usbduxsub->usbdev,
 			  usb_sndbulkpipe(usbduxsub->usbdev, PWM_EP),
-			  usbduxsub->urbPwm->transfer_buffer,
-			  usbduxsub->sizePwmBuf, usbduxsub_pwm_irq,
+			  usbduxsub->urb_pwm->transfer_buffer,
+			  usbduxsub->size_pwm_buf, usbduxsub_pwm_irq,
 			  usbduxsub->comedidev);
 
-	errFlag = usb_submit_urb(usbduxsub->urbPwm, GFP_ATOMIC);
-	if (errFlag) {
+	err_flag = usb_submit_urb(usbduxsub->urb_pwm, GFP_ATOMIC);
+	if (err_flag) {
 		dev_err(&usbduxsub->interface->dev,
 			"comedi_: usbdux: pwm: usb_submit_urb error %d\n",
-			errFlag);
-		return errFlag;
+			err_flag);
+		return err_flag;
 	}
 	return 0;
 }
@@ -1952,8 +1952,8 @@ static int usbdux_pwm_period(struct comedi_device *dev,
 			return -EAGAIN;
 		}
 	}
-	this_usbduxsub->pwmDelay = fx2delay;
-	this_usbduxsub->pwmPeriod = period;
+	this_usbduxsub->pwn_delay = fx2delay;
+	this_usbduxsub->pwm_period = period;
 	dev_dbg(&this_usbduxsub->interface->dev, "%s: frequ=%d, period=%d\n",
 		__func__, period, fx2delay);
 	return 0;
@@ -1974,17 +1974,17 @@ static int usbdux_pwm_start(struct comedi_device *dev,
 		return 0;
 	}
 
-	this_usbduxsub->dux_commands[1] = ((int8_t) this_usbduxsub->pwmDelay);
+	this_usbduxsub->dux_commands[1] = ((int8_t) this_usbduxsub->pwn_delay);
 	ret = send_dux_commands(this_usbduxsub, SENDPWMON);
 	if (ret < 0)
 		return ret;
 
 	/* initialise the buffer */
-	for (i = 0; i < this_usbduxsub->sizePwmBuf; i++)
-		((char *)(this_usbduxsub->urbPwm->transfer_buffer))[i] = 0;
+	for (i = 0; i < this_usbduxsub->size_pwm_buf; i++)
+		((char *)(this_usbduxsub->urb_pwm->transfer_buffer))[i] = 0;
 
 	this_usbduxsub->pwm_cmd_running = 1;
-	ret = usbduxsub_submit_PwmURBs(this_usbduxsub);
+	ret = usbduxsub_submit_pwm_urbs(this_usbduxsub);
 	if (ret < 0) {
 		this_usbduxsub->pwm_cmd_running = 0;
 		return ret;
@@ -1999,7 +1999,7 @@ static int usbdux_pwm_pattern(struct comedi_device *dev,
 {
 	struct usbduxsub *this_usbduxsub = dev->private;
 	int i, szbuf;
-	char *pBuf;
+	char *p_buf;
 	char pwm_mask;
 	char sgn_mask;
 	char c;
@@ -2013,10 +2013,10 @@ static int usbdux_pwm_pattern(struct comedi_device *dev,
 	sgn_mask = (16 << channel);
 	/* this is the buffer which will be filled with the with bit */
 	/* pattern for one period */
-	szbuf = this_usbduxsub->sizePwmBuf;
-	pBuf = (char *)(this_usbduxsub->urbPwm->transfer_buffer);
+	szbuf = this_usbduxsub->size_pwm_buf;
+	p_buf = (char *)(this_usbduxsub->urb_pwm->transfer_buffer);
 	for (i = 0; i < szbuf; i++) {
-		c = *pBuf;
+		c = *p_buf;
 		/* reset bits */
 		c = c & (~pwm_mask);
 		/* set the bit as long as the index is lower than the value */
@@ -2030,7 +2030,7 @@ static int usbdux_pwm_pattern(struct comedi_device *dev,
 			/* negative value */
 			c = c | sgn_mask;
 		}
-		*(pBuf++) = c;
+		*(p_buf++) = c;
 	}
 	return 1;
 }
@@ -2102,7 +2102,7 @@ static int usbdux_pwm_config(struct comedi_device *dev,
 			"comedi%d: %s: setting period\n", dev->minor, __func__);
 		return usbdux_pwm_period(dev, s, data[1]);
 	case INSN_CONFIG_PWM_GET_PERIOD:
-		data[1] = this_usbduxsub->pwmPeriod;
+		data[1] = this_usbduxsub->pwm_period;
 		return 0;
 	case INSN_CONFIG_PWM_SET_H_BRIDGE:
 		/* value in the first byte and the sign in the second for a
@@ -2138,55 +2138,55 @@ static void tidy_up(struct usbduxsub *usbduxsub_tmp)
 
 	usbduxsub_tmp->probed = 0;
 
-	if (usbduxsub_tmp->urbIn) {
+	if (usbduxsub_tmp->urb_in) {
 		if (usbduxsub_tmp->ai_cmd_running) {
 			usbduxsub_tmp->ai_cmd_running = 0;
-			usbduxsub_unlink_InURBs(usbduxsub_tmp);
+			usbduxsub_unlink_inurbs(usbduxsub_tmp);
 		}
-		for (i = 0; i < usbduxsub_tmp->numOfInBuffers; i++) {
-			kfree(usbduxsub_tmp->urbIn[i]->transfer_buffer);
-			usbduxsub_tmp->urbIn[i]->transfer_buffer = NULL;
-			usb_kill_urb(usbduxsub_tmp->urbIn[i]);
-			usb_free_urb(usbduxsub_tmp->urbIn[i]);
-			usbduxsub_tmp->urbIn[i] = NULL;
+		for (i = 0; i < usbduxsub_tmp->num_in_buffers; i++) {
+			kfree(usbduxsub_tmp->urb_in[i]->transfer_buffer);
+			usbduxsub_tmp->urb_in[i]->transfer_buffer = NULL;
+			usb_kill_urb(usbduxsub_tmp->urb_in[i]);
+			usb_free_urb(usbduxsub_tmp->urb_in[i]);
+			usbduxsub_tmp->urb_in[i] = NULL;
 		}
-		kfree(usbduxsub_tmp->urbIn);
-		usbduxsub_tmp->urbIn = NULL;
+		kfree(usbduxsub_tmp->urb_in);
+		usbduxsub_tmp->urb_in = NULL;
 	}
-	if (usbduxsub_tmp->urbOut) {
+	if (usbduxsub_tmp->urb_out) {
 		if (usbduxsub_tmp->ao_cmd_running) {
 			usbduxsub_tmp->ao_cmd_running = 0;
-			usbduxsub_unlink_OutURBs(usbduxsub_tmp);
+			usbduxsub_unlink_outurbs(usbduxsub_tmp);
 		}
-		for (i = 0; i < usbduxsub_tmp->numOfOutBuffers; i++) {
-			kfree(usbduxsub_tmp->urbOut[i]->transfer_buffer);
-			usbduxsub_tmp->urbOut[i]->transfer_buffer = NULL;
-			if (usbduxsub_tmp->urbOut[i]) {
-				usb_kill_urb(usbduxsub_tmp->urbOut[i]);
-				usb_free_urb(usbduxsub_tmp->urbOut[i]);
-				usbduxsub_tmp->urbOut[i] = NULL;
+		for (i = 0; i < usbduxsub_tmp->num_out_buffers; i++) {
+			kfree(usbduxsub_tmp->urb_out[i]->transfer_buffer);
+			usbduxsub_tmp->urb_out[i]->transfer_buffer = NULL;
+			if (usbduxsub_tmp->urb_out[i]) {
+				usb_kill_urb(usbduxsub_tmp->urb_out[i]);
+				usb_free_urb(usbduxsub_tmp->urb_out[i]);
+				usbduxsub_tmp->urb_out[i] = NULL;
 			}
 		}
-		kfree(usbduxsub_tmp->urbOut);
-		usbduxsub_tmp->urbOut = NULL;
+		kfree(usbduxsub_tmp->urb_out);
+		usbduxsub_tmp->urb_out = NULL;
 	}
-	if (usbduxsub_tmp->urbPwm) {
+	if (usbduxsub_tmp->urb_pwm) {
 		if (usbduxsub_tmp->pwm_cmd_running) {
 			usbduxsub_tmp->pwm_cmd_running = 0;
-			usbduxsub_unlink_PwmURBs(usbduxsub_tmp);
+			usbduxsub_unlink_pwm_urbs(usbduxsub_tmp);
 		}
-		kfree(usbduxsub_tmp->urbPwm->transfer_buffer);
-		usbduxsub_tmp->urbPwm->transfer_buffer = NULL;
-		usb_kill_urb(usbduxsub_tmp->urbPwm);
-		usb_free_urb(usbduxsub_tmp->urbPwm);
-		usbduxsub_tmp->urbPwm = NULL;
-	}
-	kfree(usbduxsub_tmp->inBuffer);
-	usbduxsub_tmp->inBuffer = NULL;
-	kfree(usbduxsub_tmp->insnBuffer);
-	usbduxsub_tmp->insnBuffer = NULL;
-	kfree(usbduxsub_tmp->outBuffer);
-	usbduxsub_tmp->outBuffer = NULL;
+		kfree(usbduxsub_tmp->urb_pwm->transfer_buffer);
+		usbduxsub_tmp->urb_pwm->transfer_buffer = NULL;
+		usb_kill_urb(usbduxsub_tmp->urb_pwm);
+		usb_free_urb(usbduxsub_tmp->urb_pwm);
+		usbduxsub_tmp->urb_pwm = NULL;
+	}
+	kfree(usbduxsub_tmp->in_buffer);
+	usbduxsub_tmp->in_buffer = NULL;
+	kfree(usbduxsub_tmp->insn_buffer);
+	usbduxsub_tmp->insn_buffer = NULL;
+	kfree(usbduxsub_tmp->out_buffer);
+	usbduxsub_tmp->out_buffer = NULL;
 	kfree(usbduxsub_tmp->dac_commands);
 	usbduxsub_tmp->dac_commands = NULL;
 	kfree(usbduxsub_tmp->dux_commands);
@@ -2309,7 +2309,7 @@ static int usbdux_attach_common(struct comedi_device *dev,
 		s->subdev_flags = SDF_WRITABLE | SDF_PWM_HBRIDGE;
 		s->n_chan = 8;
 		/* this defines the max duty cycle resolution */
-		s->maxdata = udev->sizePwmBuf;
+		s->maxdata = udev->size_pwm_buf;
 		s->insn_write = usbdux_pwm_write;
 		s->insn_read = usbdux_pwm_read;
 		s->insn_config = usbdux_pwm_config;
@@ -2388,7 +2388,7 @@ static void usbdux_firmware_request_complete_handler(const struct firmware *fw,
 	 * we need to upload the firmware here because fw will be
 	 * freed once we've left this function
 	 */
-	ret = firmwareUpload(usbduxsub_tmp, fw->data, fw->size);
+	ret = firmware_upload(usbduxsub_tmp, fw->data, fw->size);
 
 	if (ret) {
 		dev_err(&uinterf->dev,
@@ -2464,22 +2464,22 @@ static int usbdux_usb_probe(struct usb_interface *uinterf,
 		return -ENOMEM;
 	}
 	/* create space for the in buffer and set it to zero */
-	usbduxsub[index].inBuffer = kzalloc(SIZEINBUF, GFP_KERNEL);
-	if (!(usbduxsub[index].inBuffer)) {
+	usbduxsub[index].in_buffer = kzalloc(SIZEINBUF, GFP_KERNEL);
+	if (!(usbduxsub[index].in_buffer)) {
 		tidy_up(&(usbduxsub[index]));
 		up(&start_stop_sem);
 		return -ENOMEM;
 	}
 	/* create space of the instruction buffer */
-	usbduxsub[index].insnBuffer = kzalloc(SIZEINSNBUF, GFP_KERNEL);
-	if (!(usbduxsub[index].insnBuffer)) {
+	usbduxsub[index].insn_buffer = kzalloc(SIZEINSNBUF, GFP_KERNEL);
+	if (!(usbduxsub[index].insn_buffer)) {
 		tidy_up(&(usbduxsub[index]));
 		up(&start_stop_sem);
 		return -ENOMEM;
 	}
 	/* create space for the outbuffer */
-	usbduxsub[index].outBuffer = kzalloc(SIZEOUTBUF, GFP_KERNEL);
-	if (!(usbduxsub[index].outBuffer)) {
+	usbduxsub[index].out_buffer = kzalloc(SIZEOUTBUF, GFP_KERNEL);
+	if (!(usbduxsub[index].out_buffer)) {
 		tidy_up(&(usbduxsub[index]));
 		up(&start_stop_sem);
 		return -ENOMEM;
@@ -2496,124 +2496,124 @@ static int usbdux_usb_probe(struct usb_interface *uinterf,
 		return -ENODEV;
 	}
 	if (usbduxsub[index].high_speed)
-		usbduxsub[index].numOfInBuffers = NUMOFINBUFFERSHIGH;
+		usbduxsub[index].num_in_buffers = NUMOFINBUFFERSHIGH;
 	else
-		usbduxsub[index].numOfInBuffers = NUMOFINBUFFERSFULL;
+		usbduxsub[index].num_in_buffers = NUMOFINBUFFERSFULL;
 
-	usbduxsub[index].urbIn =
-		kcalloc(usbduxsub[index].numOfInBuffers, sizeof(struct urb *),
+	usbduxsub[index].urb_in =
+		kcalloc(usbduxsub[index].num_in_buffers, sizeof(struct urb *),
 			GFP_KERNEL);
-	if (!(usbduxsub[index].urbIn)) {
+	if (!(usbduxsub[index].urb_in)) {
 		tidy_up(&(usbduxsub[index]));
 		up(&start_stop_sem);
 		return -ENOMEM;
 	}
-	for (i = 0; i < usbduxsub[index].numOfInBuffers; i++) {
+	for (i = 0; i < usbduxsub[index].num_in_buffers; i++) {
 		/* one frame: 1ms */
-		usbduxsub[index].urbIn[i] = usb_alloc_urb(1, GFP_KERNEL);
-		if (usbduxsub[index].urbIn[i] == NULL) {
+		usbduxsub[index].urb_in[i] = usb_alloc_urb(1, GFP_KERNEL);
+		if (usbduxsub[index].urb_in[i] == NULL) {
 			dev_err(dev, "comedi_: usbdux%d: "
 				"Could not alloc. urb(%d)\n", index, i);
 			tidy_up(&(usbduxsub[index]));
 			up(&start_stop_sem);
 			return -ENOMEM;
 		}
-		usbduxsub[index].urbIn[i]->dev = usbduxsub[index].usbdev;
+		usbduxsub[index].urb_in[i]->dev = usbduxsub[index].usbdev;
 		/* will be filled later with a pointer to the comedi-device */
 		/* and ONLY then the urb should be submitted */
-		usbduxsub[index].urbIn[i]->context = NULL;
-		usbduxsub[index].urbIn[i]->pipe =
+		usbduxsub[index].urb_in[i]->context = NULL;
+		usbduxsub[index].urb_in[i]->pipe =
 		    usb_rcvisocpipe(usbduxsub[index].usbdev, ISOINEP);
-		usbduxsub[index].urbIn[i]->transfer_flags = URB_ISO_ASAP;
-		usbduxsub[index].urbIn[i]->transfer_buffer =
+		usbduxsub[index].urb_in[i]->transfer_flags = URB_ISO_ASAP;
+		usbduxsub[index].urb_in[i]->transfer_buffer =
 		    kzalloc(SIZEINBUF, GFP_KERNEL);
-		if (!(usbduxsub[index].urbIn[i]->transfer_buffer)) {
+		if (!(usbduxsub[index].urb_in[i]->transfer_buffer)) {
 			tidy_up(&(usbduxsub[index]));
 			up(&start_stop_sem);
 			return -ENOMEM;
 		}
-		usbduxsub[index].urbIn[i]->complete = usbduxsub_ai_IsocIrq;
-		usbduxsub[index].urbIn[i]->number_of_packets = 1;
-		usbduxsub[index].urbIn[i]->transfer_buffer_length = SIZEINBUF;
-		usbduxsub[index].urbIn[i]->iso_frame_desc[0].offset = 0;
-		usbduxsub[index].urbIn[i]->iso_frame_desc[0].length = SIZEINBUF;
+		usbduxsub[index].urb_in[i]->complete = usbduxsub_ai_isoc_irq;
+		usbduxsub[index].urb_in[i]->number_of_packets = 1;
+		usbduxsub[index].urb_in[i]->transfer_buffer_length = SIZEINBUF;
+		usbduxsub[index].urb_in[i]->iso_frame_desc[0].offset = 0;
+		usbduxsub[index].urb_in[i]->iso_frame_desc[0].length = SIZEINBUF;
 	}
 
 	/* out */
 	if (usbduxsub[index].high_speed)
-		usbduxsub[index].numOfOutBuffers = NUMOFOUTBUFFERSHIGH;
+		usbduxsub[index].num_out_buffers = NUMOFOUTBUFFERSHIGH;
 	else
-		usbduxsub[index].numOfOutBuffers = NUMOFOUTBUFFERSFULL;
+		usbduxsub[index].num_out_buffers = NUMOFOUTBUFFERSFULL;
 
-	usbduxsub[index].urbOut =
-		kcalloc(usbduxsub[index].numOfOutBuffers, sizeof(struct urb *),
+	usbduxsub[index].urb_out =
+		kcalloc(usbduxsub[index].num_out_buffers, sizeof(struct urb *),
 			GFP_KERNEL);
-	if (!(usbduxsub[index].urbOut)) {
+	if (!(usbduxsub[index].urb_out)) {
 		tidy_up(&(usbduxsub[index]));
 		up(&start_stop_sem);
 		return -ENOMEM;
 	}
-	for (i = 0; i < usbduxsub[index].numOfOutBuffers; i++) {
+	for (i = 0; i < usbduxsub[index].num_out_buffers; i++) {
 		/* one frame: 1ms */
-		usbduxsub[index].urbOut[i] = usb_alloc_urb(1, GFP_KERNEL);
-		if (usbduxsub[index].urbOut[i] == NULL) {
+		usbduxsub[index].urb_out[i] = usb_alloc_urb(1, GFP_KERNEL);
+		if (usbduxsub[index].urb_out[i] == NULL) {
 			dev_err(dev, "comedi_: usbdux%d: "
 				"Could not alloc. urb(%d)\n", index, i);
 			tidy_up(&(usbduxsub[index]));
 			up(&start_stop_sem);
 			return -ENOMEM;
 		}
-		usbduxsub[index].urbOut[i]->dev = usbduxsub[index].usbdev;
+		usbduxsub[index].urb_out[i]->dev = usbduxsub[index].usbdev;
 		/* will be filled later with a pointer to the comedi-device */
 		/* and ONLY then the urb should be submitted */
-		usbduxsub[index].urbOut[i]->context = NULL;
-		usbduxsub[index].urbOut[i]->pipe =
+		usbduxsub[index].urb_out[i]->context = NULL;
+		usbduxsub[index].urb_out[i]->pipe =
 		    usb_sndisocpipe(usbduxsub[index].usbdev, ISOOUTEP);
-		usbduxsub[index].urbOut[i]->transfer_flags = URB_ISO_ASAP;
-		usbduxsub[index].urbOut[i]->transfer_buffer =
+		usbduxsub[index].urb_out[i]->transfer_flags = URB_ISO_ASAP;
+		usbduxsub[index].urb_out[i]->transfer_buffer =
 		    kzalloc(SIZEOUTBUF, GFP_KERNEL);
-		if (!(usbduxsub[index].urbOut[i]->transfer_buffer)) {
+		if (!(usbduxsub[index].urb_out[i]->transfer_buffer)) {
 			tidy_up(&(usbduxsub[index]));
 			up(&start_stop_sem);
 			return -ENOMEM;
 		}
-		usbduxsub[index].urbOut[i]->complete = usbduxsub_ao_IsocIrq;
-		usbduxsub[index].urbOut[i]->number_of_packets = 1;
-		usbduxsub[index].urbOut[i]->transfer_buffer_length = SIZEOUTBUF;
-		usbduxsub[index].urbOut[i]->iso_frame_desc[0].offset = 0;
-		usbduxsub[index].urbOut[i]->iso_frame_desc[0].length =
+		usbduxsub[index].urb_out[i]->complete = usbduxsub_ao_isoc_irq;
+		usbduxsub[index].urb_out[i]->number_of_packets = 1;
+		usbduxsub[index].urb_out[i]->transfer_buffer_length = SIZEOUTBUF;
+		usbduxsub[index].urb_out[i]->iso_frame_desc[0].offset = 0;
+		usbduxsub[index].urb_out[i]->iso_frame_desc[0].length =
 		    SIZEOUTBUF;
 		if (usbduxsub[index].high_speed) {
 			/* uframes */
-			usbduxsub[index].urbOut[i]->interval = 8;
+			usbduxsub[index].urb_out[i]->interval = 8;
 		} else {
 			/* frames */
-			usbduxsub[index].urbOut[i]->interval = 1;
+			usbduxsub[index].urb_out[i]->interval = 1;
 		}
 	}
 
 	/* pwm */
 	if (usbduxsub[index].high_speed) {
 		/* max bulk ep size in high speed */
-		usbduxsub[index].sizePwmBuf = 512;
-		usbduxsub[index].urbPwm = usb_alloc_urb(0, GFP_KERNEL);
-		if (usbduxsub[index].urbPwm == NULL) {
+		usbduxsub[index].size_pwm_buf = 512;
+		usbduxsub[index].urb_pwm = usb_alloc_urb(0, GFP_KERNEL);
+		if (usbduxsub[index].urb_pwm == NULL) {
 			dev_err(dev, "comedi_: usbdux%d: "
 				"Could not alloc. pwm urb\n", index);
 			tidy_up(&(usbduxsub[index]));
 			up(&start_stop_sem);
 			return -ENOMEM;
 		}
-		usbduxsub[index].urbPwm->transfer_buffer =
-		    kzalloc(usbduxsub[index].sizePwmBuf, GFP_KERNEL);
-		if (!(usbduxsub[index].urbPwm->transfer_buffer)) {
+		usbduxsub[index].urb_pwm->transfer_buffer =
+		    kzalloc(usbduxsub[index].size_pwm_buf, GFP_KERNEL);
+		if (!(usbduxsub[index].urb_pwm->transfer_buffer)) {
 			tidy_up(&(usbduxsub[index]));
 			up(&start_stop_sem);
 			return -ENOMEM;
 		}
 	} else {
-		usbduxsub[index].urbPwm = NULL;
-		usbduxsub[index].sizePwmBuf = 0;
+		usbduxsub[index].urb_pwm = NULL;
+		usbduxsub[index].size_pwm_buf = 0;
 	}
 
 	usbduxsub[index].ai_cmd_running = 0;
diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c
index a728c8f..656135e 100644
--- a/drivers/staging/comedi/drivers/usbduxsigma.c
+++ b/drivers/staging/comedi/drivers/usbduxsigma.c
@@ -1376,7 +1376,7 @@ static int usbdux_getstatusinfo(struct comedi_device *dev, int chan)
 
 	/* 32 bits big endian from the A/D converter */
 	one = be32_to_cpu(*((int32_t *)((this_usbduxsub->insnBuffer)+1)));
-	/* mask out the staus byte */
+	/* mask out the status byte */
 	one = one & 0x00ffffff;
 	one = one ^ 0x00800000;
 
diff --git a/drivers/staging/comedi/proc.c b/drivers/staging/comedi/proc.c
index 362c214..f01e0cc 100644
--- a/drivers/staging/comedi/proc.c
+++ b/drivers/staging/comedi/proc.c
@@ -80,11 +80,8 @@ static int comedi_read(char *buf, char **start, off_t offset, int len,
 
 void comedi_proc_init(void)
 {
-	struct proc_dir_entry *comedi_proc;
-
-	comedi_proc = create_proc_entry("comedi", S_IFREG | S_IRUGO, NULL);
-	if (comedi_proc)
-		comedi_proc->read_proc = comedi_read;
+	create_proc_read_entry("comedi", S_IFREG | S_IRUGO, NULL,
+				comedi_read, NULL);
 }
 
 void comedi_proc_cleanup(void)
diff --git a/drivers/staging/csr/csr_time.c b/drivers/staging/csr/csr_time.c
index f3f4a9c..01179e4 100644
--- a/drivers/staging/csr/csr_time.c
+++ b/drivers/staging/csr/csr_time.c
@@ -1,10 +1,10 @@
 /*****************************************************************************
 
-            (c) Cambridge Silicon Radio Limited 2010
-            All rights reserved and confidential information of CSR
+	(c) Cambridge Silicon Radio Limited 2010
+	All rights reserved and confidential information of CSR
 
-            Refer to LICENSE.txt included with this source for details
-            on the license terms.
+	Refer to LICENSE.txt included with this source for details
+	on the license terms.
 
 *****************************************************************************/
 
diff --git a/drivers/staging/csr/csr_wifi_fsm.h b/drivers/staging/csr/csr_wifi_fsm.h
index fde1508..fc5c5aa 100644
--- a/drivers/staging/csr/csr_wifi_fsm.h
+++ b/drivers/staging/csr/csr_wifi_fsm.h
@@ -70,7 +70,7 @@ extern CsrWifiFsmContext* CsrWifiFsmInit(void *applicationContext, void *externa
  *   This function is used to free any dynamic resources allocated for the
  *   given context by CsrWifiFsmInit().
  *   The FSM's reset function is called to cleanup any fsm specific memory
- *   The reset funtion does NOT need to free the fsm data pointer as
+ *   The reset function does NOT need to free the fsm data pointer as
  *   CsrWifiFsmShutdown() will do it.
  *   the FSM's init function is call again to reinitialise the FSM context.
  *   CsrWifiFsmReset() should NEVER be called when CsrWifiFsmExecute() is running.
@@ -91,7 +91,7 @@ extern void CsrWifiFsmReset(CsrWifiFsmContext *context);
  *   given context by CsrWifiFsmInit(), prior to complete termination of
  *   the program.
  *   The FSM's reset function is called to cleanup any fsm specific memory.
- *   The reset funtion does NOT need to free the fsm data pointer as
+ *   The reset function does NOT need to free the fsm data pointer as
  *   CsrWifiFsmShutdown() will do it.
  *   CsrWifiFsmShutdown() should NEVER be called when CsrWifiFsmExecute() is running.
  *
@@ -203,7 +203,7 @@ extern void CsrWifiFsmFastForward(CsrWifiFsmContext *context, u16 ms);
  *   shift the current time of day by ms amount
  *
  * @par Description
- *   usefull to speed up tests where time needs to pass
+ *   useful to speed up tests where time needs to pass
  *
  * @param[in]    context  : FSM context
  * @param[in]    ms       : ms to adjust time by
diff --git a/drivers/staging/csr/csr_wifi_hip_card_sdio.c b/drivers/staging/csr/csr_wifi_hip_card_sdio.c
index 25cabf32..d542532 100644
--- a/drivers/staging/csr/csr_wifi_hip_card_sdio.c
+++ b/drivers/staging/csr/csr_wifi_hip_card_sdio.c
@@ -559,7 +559,7 @@ static void _build_sdio_config_data(sdio_config_data_t *cfg_data,
  *      padding bytes. Every read from this memory has to be transformed in
  *      host (cpu specific) format, before it is stored in driver's parameters
  *      or/and structures. Athough unifi_card_read16() and unifi_read32() do perform
- *      the convertion internally, unifi_readn() does not.
+ *      the conversion internally, unifi_readn() does not.
  * ---------------------------------------------------------------------------
  */
 static CsrResult card_hw_init(card_t *card)
@@ -1332,7 +1332,7 @@ static CsrResult card_access_panic(card_t *card)
     s32 i;
     CsrResult r, sr;
 
-    /* A chip version of zero means that the version never got succesfully read
+    /* A chip version of zero means that the version never got successfully read
      * during reset. In this case give up because it will not be possible to
      * verify the chip version.
      */
@@ -2446,7 +2446,7 @@ static CsrResult unifi_prepare_hw(card_t *card)
 
     if (old_state == UNIFI_HOST_STATE_TORPID)
     {
-        /* Ensure the initial clock rate is set; if a reset occured when the chip was
+        /* Ensure the initial clock rate is set; if a reset occurred when the chip was
          * TORPID, unifi_set_host_state() may have raised it to MAX.
          */
         csrResult = CsrSdioMaxBusClockFrequencySet(card->sdio_if, UNIFI_SDIO_CLOCK_INIT_HZ);
@@ -2567,7 +2567,7 @@ static CsrResult unifi_reset_hardware(card_t *card)
     csrResult = CsrSdioHardReset(card->sdio_if);
     if (csrResult == CSR_RESULT_SUCCESS)
     {
-        unifi_info(card->ospriv, "CsrSdioHardReset succeeded on reseting UniFi\n");
+        unifi_info(card->ospriv, "CsrSdioHardReset succeeded on resetting UniFi\n");
         r = unifi_prepare_hw(card);
         if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE)
         {
diff --git a/drivers/staging/csr/csr_wifi_hip_card_sdio_intr.c b/drivers/staging/csr/csr_wifi_hip_card_sdio_intr.c
index 97f645c..cfe186e 100644
--- a/drivers/staging/csr/csr_wifi_hip_card_sdio_intr.c
+++ b/drivers/staging/csr/csr_wifi_hip_card_sdio_intr.c
@@ -883,7 +883,7 @@ static CsrResult handle_host_protocol(card_t *card, u8 *processed_something)
     r = read_to_host_signals(card, &done);
     if (r != CSR_RESULT_SUCCESS)
     {
-        unifi_error(card->ospriv, "Error occured reading to-host signals\n");
+        unifi_error(card->ospriv, "Error occurred reading to-host signals\n");
         return r;
     }
     if (done > 0)
@@ -899,7 +899,7 @@ static CsrResult handle_host_protocol(card_t *card, u8 *processed_something)
     r = process_to_host_signals(card, &done);
     if (r != CSR_RESULT_SUCCESS)
     {
-        unifi_error(card->ospriv, "Error occured processing to-host signals\n");
+        unifi_error(card->ospriv, "Error occurred processing to-host signals\n");
         return r;
     }
 
@@ -908,7 +908,7 @@ static CsrResult handle_host_protocol(card_t *card, u8 *processed_something)
     r = process_fh_cmd_queue(card, &done);
     if (r != CSR_RESULT_SUCCESS)
     {
-        unifi_error(card->ospriv, "Error occured processing from-host signals\n");
+        unifi_error(card->ospriv, "Error occurred processing from-host signals\n");
         return r;
     }
     if (done > 0)
@@ -919,7 +919,7 @@ static CsrResult handle_host_protocol(card_t *card, u8 *processed_something)
     r = process_fh_traffic_queue(card, &done);
     if (r != CSR_RESULT_SUCCESS)
     {
-        unifi_error(card->ospriv, "Error occured processing from-host data signals\n");
+        unifi_error(card->ospriv, "Error occurred processing from-host data signals\n");
         return r;
     }
     if (done > 0)
@@ -1953,7 +1953,7 @@ static CsrResult check_fh_sig_slots(card_t *card, u16 needed, s32 *space_fh)
  *      in the from-host queue using the wire-format structures, as they arrive.
  *      All other requests are stored in the from-host queue using the host
  *      (cpu specific) structures. We use the is_packed member of the card_signal_t
- *      structure that describes the queue to make the distiction.
+ *      structure that describes the queue to make the distinction.
  * ---------------------------------------------------------------------------
  */
 static CsrResult process_fh_cmd_queue(card_t *card, s32 *processed)
diff --git a/drivers/staging/csr/csr_wifi_hip_chiphelper.h b/drivers/staging/csr/csr_wifi_hip_chiphelper.h
index b6b67ee..09b3aef 100644
--- a/drivers/staging/csr/csr_wifi_hip_chiphelper.h
+++ b/drivers/staging/csr/csr_wifi_hip_chiphelper.h
@@ -354,7 +354,7 @@ CHIP_HELPER_LIST(C_DEC)
     map that is part of the window and the size is the number of
     visible words.
 
-    Some of the windows have thier lowest portion covered by
+    Some of the windows have their lowest portion covered by
     registers.  For these windows address is the first address
     after the registers and size is the siave excluding the part
     covered by registers.
@@ -375,7 +375,7 @@ CHIP_HELPER_LIST(C_DEC)
     will be needed if the device is being booted from cold.  These
     register writes enable the clocks and setup the PLL to a basic
     working state.  SPI access might be unreliable until these writes
-    have occured (And they may take mulitple goes).
+    have occurred (And they may take mulitple goes).
 */
 /*  HostResetSequence
 
diff --git a/drivers/staging/csr/csr_wifi_hip_unifi.h b/drivers/staging/csr/csr_wifi_hip_unifi.h
index c2a2231..1160a0e 100644
--- a/drivers/staging/csr/csr_wifi_hip_unifi.h
+++ b/drivers/staging/csr/csr_wifi_hip_unifi.h
@@ -117,9 +117,9 @@ typedef enum
     UNIFI_TRAFFIC_Q_BE,
     UNIFI_TRAFFIC_Q_VI,
     UNIFI_TRAFFIC_Q_VO,
-    UNIFI_TRAFFIC_Q_EAPOL,    /* Non existant in HIP */
-    UNIFI_TRAFFIC_Q_MAX,      /* Non existant */
-    UNIFI_TRAFFIC_Q_MLME      /* Non existant */
+    UNIFI_TRAFFIC_Q_EAPOL,    /* Non existent in HIP */
+    UNIFI_TRAFFIC_Q_MAX,      /* Non existent */
+    UNIFI_TRAFFIC_Q_MLME      /* Non existent */
 } unifi_TrafficQueue;
 
 /*
@@ -263,7 +263,7 @@ card_t* unifi_alloc_card(CsrSdioFunction *sdiopriv, void *ospriv);
  *
  * @return \b 0 if UniFi is initialized.
  *
- * @return \b -CSR_EIO if an I/O error occured while initializing UniFi
+ * @return \b -CSR_EIO if an I/O error occurred while initializing UniFi
  *
  * @return \b -CSR_ENODEV if the card is no longer present.
  *
@@ -311,7 +311,7 @@ void unifi_cancel_pending_signals(card_t *card);
  *
  * @return \b 0 signal is sent.
  *
- * @return \b -CSR_EIO if an error occured while sending the signal
+ * @return \b -CSR_EIO if an error occurred while sending the signal
  *
  * @return \b -CSR_ENODEV if the card is no longer present.
  *
@@ -361,7 +361,7 @@ void unifi_card_info(card_t *card, card_info_t *card_info);
  *
  * @return \b 0 if the check was performed.
  *
- * @return \b -CSR_EIO if an error occured while checking the status.
+ * @return \b -CSR_EIO if an error occurred while checking the status.
  *
  * @return \b -CSR_ENODEV if the card is no longer present.
  *
@@ -383,11 +383,11 @@ CsrResult unifi_check_io_status(card_t *card, s32 *status);
  * is required. If unifi_bh() is called before the timeout expires,
  * the caller must pass in the remaining time.
  *
- * @return \b 0 if no error occured.
+ * @return \b 0 if no error occurred.
  *
  * @return \b -CSR_ENODEV if the card is no longer present.
  *
- * @return \b -CSR_E* if an error occured while running the bottom half.
+ * @return \b -CSR_E* if an error occurred while running the bottom half.
  *
  * @ingroup upperedge
  */
@@ -439,7 +439,7 @@ enum unifi_periodic_wake_mode
  *
  * @param periodic_wake_mode the Periodic Wake Mode.
  *
- * @return \b 0 if no error occured.
+ * @return \b 0 if no error occurred.
  *
  * @return \b -CSR_E* if the request failed.
  *
@@ -458,7 +458,7 @@ CsrResult unifi_configure_low_power_mode(card_t                       *card,
  *
  * @param card the HIP core lib API context.
  *
- * @return \b 0 if no error occured.
+ * @return \b 0 if no error occurred.
  *
  * @return \b -CSR_ENODEV if the card is no longer present.
  *
diff --git a/drivers/staging/csr/drv.c b/drivers/staging/csr/drv.c
index 3bd52fd..5520d65 100644
--- a/drivers/staging/csr/drv.c
+++ b/drivers/staging/csr/drv.c
@@ -1815,7 +1815,7 @@ udi_log_event(ul_client_t *pcli,
     }
 
     /* Allocate log structure plus actual signal. */
-    logptr = (udi_log_t *)kmalloc(sizeof(udi_log_t) + total_len, GFP_KERNEL);
+    logptr = kmalloc(sizeof(udi_log_t) + total_len, GFP_KERNEL);
 
     if (logptr == NULL) {
         printk(KERN_ERR
@@ -1890,7 +1890,7 @@ uf_sme_queue_message(unifi_priv_t *priv, u8 *buffer, int length)
     }
 
     /* Allocate log structure plus actual signal. */
-    logptr = (udi_log_t *)kmalloc(sizeof(udi_log_t) + length, GFP_ATOMIC);
+    logptr = kmalloc(sizeof(udi_log_t) + length, GFP_ATOMIC);
     if (logptr == NULL) {
         unifi_error(priv, "Failed to allocate %d bytes for an SME message\n",
                     sizeof(udi_log_t) + length);
diff --git a/drivers/staging/csr/netdev.c b/drivers/staging/csr/netdev.c
index 7dad26f..a0177d9 100644
--- a/drivers/staging/csr/netdev.c
+++ b/drivers/staging/csr/netdev.c
@@ -2365,7 +2365,7 @@ unifi_rx(unifi_priv_t *priv, CSR_SIGNAL *signal, bulk_data_param_t *bulkdata)
         rx_buffered_packets_t *rx_q_item;
         struct list_head *rx_list;
 
-        rx_q_item = (rx_buffered_packets_t *)kmalloc(sizeof(rx_buffered_packets_t),
+        rx_q_item = kmalloc(sizeof(rx_buffered_packets_t),
                 GFP_KERNEL);
         if (rx_q_item == NULL) {
             unifi_error(priv, "%s: Failed to allocate %d bytes for rx packet record\n",
diff --git a/drivers/staging/csr/sdio_mmc.c b/drivers/staging/csr/sdio_mmc.c
index b6a16de..30271d3 100644
--- a/drivers/staging/csr/sdio_mmc.c
+++ b/drivers/staging/csr/sdio_mmc.c
@@ -1031,8 +1031,7 @@ uf_glue_sdio_probe(struct sdio_func *func,
            sdio_func_id(func), instance);
 
     /* Allocate context */
-    sdio_ctx = (CsrSdioFunction *)kmalloc(sizeof(CsrSdioFunction),
-                                          GFP_KERNEL);
+    sdio_ctx = kmalloc(sizeof(CsrSdioFunction), GFP_KERNEL);
     if (sdio_ctx == NULL) {
         sdio_release_host(func);
         return -ENOMEM;
diff --git a/drivers/staging/csr/sme_native.c b/drivers/staging/csr/sme_native.c
index 525fe1b..ca55249 100644
--- a/drivers/staging/csr/sme_native.c
+++ b/drivers/staging/csr/sme_native.c
@@ -273,7 +273,7 @@ sme_native_log_event(ul_client_t *pcli,
     }
 
     /* Allocate log structure plus actual signal. */
-    logptr = (udi_log_t *)kmalloc(sizeof(udi_log_t) + total_len, GFP_KERNEL);
+    logptr = kmalloc(sizeof(udi_log_t) + total_len, GFP_KERNEL);
 
     if (logptr == NULL) {
         unifi_error(priv,
diff --git a/drivers/staging/csr/sme_wext.c b/drivers/staging/csr/sme_wext.c
index 5e06a38..4129a643 100644
--- a/drivers/staging/csr/sme_wext.c
+++ b/drivers/staging/csr/sme_wext.c
@@ -1273,7 +1273,6 @@ unifi_siwscan(struct net_device *dev, struct iw_request_info *info,
 {
     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
     unifi_priv_t *priv = interfacePriv->privPtr;
-    int scantype;
     int r;
     CsrWifiSsid scan_ssid;
     unsigned char *channel_list = NULL;
@@ -1293,8 +1292,6 @@ unifi_siwscan(struct net_device *dev, struct iw_request_info *info,
     }
 
 
-    scantype = UNIFI_SCAN_ACTIVE;
-
 #if WIRELESS_EXT > 17
     /* Providing a valid channel list will force an active scan */
     if (req) {
diff --git a/drivers/staging/csr/unifi_pdu_processing.c b/drivers/staging/csr/unifi_pdu_processing.c
index 95efc36..f9b421b 100644
--- a/drivers/staging/csr/unifi_pdu_processing.c
+++ b/drivers/staging/csr/unifi_pdu_processing.c
@@ -403,7 +403,7 @@ CsrResult enque_tx_data_pdu(unifi_priv_t *priv, bulk_data_param_t *bulkdata,
 
 
 
-    tx_q_item = (tx_buffered_packets_t *)kmalloc(sizeof(tx_buffered_packets_t), GFP_ATOMIC);
+    tx_q_item = kmalloc(sizeof(tx_buffered_packets_t), GFP_ATOMIC);
     if (tx_q_item == NULL) {
         unifi_error(priv,
                 "Failed to allocate %d bytes for tx packet record\n",
@@ -1468,7 +1468,7 @@ static int update_macheader(unifi_priv_t *priv, struct sk_buff *skb,
             }
     }
 
-    /* prepare the complete skb, by pushing the MAC header to the begining of the skb->data */
+    /* prepare the complete skb, by pushing the MAC header to the beginning of the skb->data */
     unifi_trace(priv, UDBG5, "updated Mac Header: %d \n",macHeaderLengthInBytes);
     memcpy(bufPtr, macHeaderBuf, macHeaderLengthInBytes);
 
@@ -1546,7 +1546,7 @@ uf_ap_process_data_pdu(unifi_priv_t *priv, struct sk_buff *skb,
         return -1;
     }
 
-    /* fetch the destination record from staion record database */
+    /* fetch the destination record from station record database */
     dstStaInfo = CsrWifiRouterCtrlGetStationRecordFromPeerMacAddress(priv, ehdr->h_dest, interfaceTag);
 
     /* AP mode processing, & if packet is unicast */
@@ -1878,13 +1878,13 @@ CsrResult uf_process_ma_packet_req(unifi_priv_t *priv,
         }
         else if ((pktType == CSR_WIFI_MULTICAST_PDU) && (!status))
         {
-            /* If broadcast Tim is set && queuing is successfull, then only update TIM */
+            /* If broadcast Tim is set && queuing is successful, then only update TIM */
             spin_lock_irqsave(&priv->staRecord_lock,lock_flags);
             interfacePriv->noOfbroadcastPktQueued++;
             spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags);
         }
     }
-    /* If broadcast Tim is set && queuing is successfull, then only update TIM */
+    /* If broadcast Tim is set && queuing is successful, then only update TIM */
     if(setBcTim && !status) {
         unifi_trace(priv, UDBG3, "tim set due to broadcast pkt\n");
         if (!interfacePriv->bcTimSetReqPendingFlag)
@@ -1995,7 +1995,7 @@ s8 uf_get_protection_bit_from_interfacemode(unifi_priv_t *priv, u16 interfaceTag
                      */
                     protection = interfacePriv->protect;
                 } else {
-                    /* fetch the destination record from staion record database */
+                    /* fetch the destination record from station record database */
                     dstStaInfo = CsrWifiRouterCtrlGetStationRecordFromPeerMacAddress(priv, daddr, interfaceTag);
                     if (!dstStaInfo) {
                         unifi_trace(priv, UDBG3, "peer not found in station record in send_ma_pkt_request\n");
@@ -3170,7 +3170,7 @@ void uf_process_ps_poll(unifi_priv_t *priv,u8* sa,u8* da,u8 pmBit,u16 interfaceT
         /*Send Data From Management Frames*/
         /* Priority orders for delivering the buffered packets are
          * 1. Deliver the Management frames if there
-         * 2. Other access catagory frames which are non deliver enable including UNIFI_TRAFFIC_Q_VO
+         * 2. Other access category frames which are non deliver enable including UNIFI_TRAFFIC_Q_VO
          * priority is from VO->BK
          */
 
@@ -3282,7 +3282,7 @@ void add_to_send_cfm_list(unifi_priv_t * priv,
 {
     tx_buffered_packets_t *send_cfm_list_item = NULL;
 
-    send_cfm_list_item = (tx_buffered_packets_t *) kmalloc(sizeof(tx_buffered_packets_t), GFP_ATOMIC);
+    send_cfm_list_item = kmalloc(sizeof(tx_buffered_packets_t), GFP_ATOMIC);
 
     if(send_cfm_list_item == NULL){
         unifi_warning(priv, "%s: Failed to allocate memory for new list item \n");
@@ -3439,7 +3439,7 @@ CsrWifiRouterCtrlStaInfo_t *CsrWifiRouterCtrlGetStationRecordFromPeerMacAddress(
 
     interfacePriv = priv->interfacePriv[interfaceTag];
 
-    /* disable the preemption untill station record is fetched */
+    /* disable the preemption until station record is fetched */
     spin_lock_irqsave(&priv->staRecord_lock,lock_flags);
 
     for (i = 0; i < UNIFI_MAX_CONNECTIONS; i++) {
@@ -3665,7 +3665,7 @@ void update_eosp_to_head_of_broadcast_list_head(unifi_priv_t *priv,u16 interface
     if (interfacePriv->noOfbroadcastPktQueued) {
 
         /* Update the EOSP to the HEAD of b/c list
-         * beacuse we have received any mgmt packet so it should not hold for long time
+         * because we have received any mgmt packet so it should not hold for long time
          * peer may time out.
          */
         spin_lock_irqsave(&priv->tx_q_lock,lock_flags);
diff --git a/drivers/staging/dgrp/dgrp_common.c b/drivers/staging/dgrp/dgrp_common.c
index 3553998..9a9b456 100644
--- a/drivers/staging/dgrp/dgrp_common.c
+++ b/drivers/staging/dgrp/dgrp_common.c
@@ -167,34 +167,3 @@ void dgrp_carrier(struct ch_struct *ch)
 		ch->ch_flag &= ~CH_PHYS_CD;
 
 }
-
-/**
- * dgrp_chk_perm() -- check permissions for net device
- * @inode: pointer to inode structure for the net communication device
- * @op: operation to be tested
- *
- * The file permissions and ownerships are tested to determine whether
- * the operation "op" is permitted on the file pointed to by the inode.
- * Returns 0 if the operation is permitted, -EACCESS otherwise
- */
-int dgrp_chk_perm(int mode, int op)
-{
-	if (!uid_eq(GLOBAL_ROOT_UID, current_euid()))
-		mode >>= 6;
-	else if (in_egroup_p(GLOBAL_ROOT_GID))
-		mode >>= 3;
-
-	if ((mode & op & 0007) == op)
-		return 0;
-
-	if (capable(CAP_SYS_ADMIN))
-		return 0;
-
-	return -EACCES;
-}
-
-/* dgrp_chk_perm wrapper for permission call in struct inode_operations */
-int dgrp_inode_permission(struct inode *inode, int op)
-{
-	return dgrp_chk_perm(inode->i_mode, op);
-}
diff --git a/drivers/staging/dgrp/dgrp_common.h b/drivers/staging/dgrp/dgrp_common.h
index 0583fe9..076dd6b 100644
--- a/drivers/staging/dgrp/dgrp_common.h
+++ b/drivers/staging/dgrp/dgrp_common.h
@@ -49,20 +49,20 @@ extern struct dgrp_poll_data dgrp_poll_data;
 extern void dgrp_poll_handler(unsigned long arg);
 
 /* from dgrp_mon_ops.c */
-extern void dgrp_register_mon_hook(struct proc_dir_entry *de);
+extern const struct file_operations dgrp_mon_ops;
 
 /* from dgrp_tty.c */
 extern int dgrp_tty_init(struct nd_struct *nd);
 extern void dgrp_tty_uninit(struct nd_struct *nd);
 
 /* from dgrp_ports_ops.c */
-extern void dgrp_register_ports_hook(struct proc_dir_entry *de);
+extern const struct file_operations dgrp_ports_ops;
 
 /* from dgrp_net_ops.c */
-extern void dgrp_register_net_hook(struct proc_dir_entry *de);
+extern const struct file_operations dgrp_net_ops;
 
 /* from dgrp_dpa_ops.c */
-extern void dgrp_register_dpa_hook(struct proc_dir_entry *de);
+extern const struct file_operations dgrp_dpa_ops;
 extern void dgrp_dpa_data(struct nd_struct *, int, u8 *, int);
 
 /* from dgrp_sysfs.c */
@@ -76,61 +76,6 @@ extern void dgrp_create_tty_sysfs(struct un_struct *un, struct device *c);
 extern void dgrp_remove_tty_sysfs(struct device *c);
 
 /* from dgrp_specproc.c */
-/*
- *  The list of DGRP entries with r/w capabilities.  These
- *  magic numbers are used for identification purposes.
- */
-enum {
-	DGRP_CONFIG = 1,	/* Configure portservers */
-	DGRP_NETDIR = 2,	/* Directory for "net" devices */
-	DGRP_MONDIR = 3,	/* Directory for "mon" devices */
-	DGRP_PORTSDIR = 4,	/* Directory for "ports" devices */
-	DGRP_INFO = 5,		/* Get info. about the running module */
-	DGRP_NODEINFO = 6,	/* Get info. about the configured nodes */
-	DGRP_DPADIR = 7,	/* Directory for the "dpa" devices */
-};
-
-/*
- *  Directions for proc handlers
- */
-enum {
-	INBOUND = 1,		/* Data being written to kernel */
-	OUTBOUND = 2,		/* Data being read from the kernel */
-};
-
-/**
- * dgrp_proc_entry: structure for dgrp proc dirs
- * @id: ID number associated with this particular entry.  Should be
- *    unique across all of DGRP.
- * @name: text name associated with the /proc entry
- * @mode: file access permisssions for the /proc entry
- * @child: pointer to table describing a subdirectory for this entry
- * @de: pointer to directory entry for this object once registered.  Used
- *    to grab the handle of the object for unregistration
- * @excl_sem: semaphore to provide exclusive to struct
- * @excl_cnt: counter of current accesses
- *
- *  Each entry in a DGRP proc directory is described with a
- *  dgrp_proc_entry structure.  A collection of these
- *  entries (in an array) represents the members associated
- *  with a particular /proc directory, and is referred to
- *  as a table.  All tables are terminated by an entry with
- *  zeros for every member.
- */
-struct dgrp_proc_entry {
-	int                  id;          /* Integer identifier */
-	const char        *name;          /* ASCII identifier */
-	mode_t             mode;          /* File access permissions */
-	struct dgrp_proc_entry *child;    /* Child pointer */
-
-	/* file ops to use, pass NULL to use default */
-	struct file_operations *proc_file_ops;
-
-	struct proc_dir_entry *de;        /* proc entry pointer */
-	struct semaphore   excl_sem;      /* Protects exclusive access var */
-	int                excl_cnt;      /* Counts number of curr accesses */
-};
-
 extern void dgrp_unregister_proc(void);
 extern void dgrp_register_proc(void);
 
@@ -144,8 +89,6 @@ extern void dgrp_register_proc(void);
  *-----------------------------------------------------------------------*/
 
 void dgrp_carrier(struct ch_struct *ch);
-extern int dgrp_inode_permission(struct inode *inode, int op);
-extern int dgrp_chk_perm(int mode, int op);
 
 
 /*
diff --git a/drivers/staging/dgrp/dgrp_dpa_ops.c b/drivers/staging/dgrp/dgrp_dpa_ops.c
index 021cca4..43209c1 100644
--- a/drivers/staging/dgrp/dgrp_dpa_ops.c
+++ b/drivers/staging/dgrp/dgrp_dpa_ops.c
@@ -52,7 +52,7 @@ static long dgrp_dpa_ioctl(struct file *file, unsigned int cmd,
 			   unsigned long arg);
 static unsigned int dgrp_dpa_select(struct file *, struct poll_table_struct *);
 
-static const struct file_operations dpa_ops = {
+const struct file_operations dgrp_dpa_ops = {
 	.owner   =  THIS_MODULE,
 	.read    =  dgrp_dpa_read,
 	.poll    =  dgrp_dpa_select,
@@ -61,12 +61,6 @@ static const struct file_operations dpa_ops = {
 	.release =  dgrp_dpa_release,
 };
 
-static struct inode_operations dpa_inode_ops = {
-	.permission = dgrp_inode_permission
-};
-
-
-
 struct digi_node {
 	uint	nd_state;		/* Node state: 1 = up, 0 = down. */
 	uint	nd_chan_count;		/* Number of channels found */
@@ -111,17 +105,6 @@ struct digi_debug {
 #define DIGI_SETDEBUG      (('d'<<8) | 247)	/* set debug info */
 
 
-void dgrp_register_dpa_hook(struct proc_dir_entry *de)
-{
-	struct nd_struct *node = de->data;
-
-	de->proc_iops = &dpa_inode_ops;
-	de->proc_fops = &dpa_ops;
-
-	node->nd_dpa_de = de;
-	spin_lock_init(&node->nd_dpa_lock);
-}
-
 /*
  * dgrp_dpa_open -- open the DPA device for a particular PortServer
  */
@@ -130,8 +113,6 @@ static int dgrp_dpa_open(struct inode *inode, struct file *file)
 	struct nd_struct *nd;
 	int rtn = 0;
 
-	struct proc_dir_entry *de;
-
 	rtn = try_module_get(THIS_MODULE);
 	if (!rtn)
 		return -ENXIO;
@@ -154,12 +135,7 @@ static int dgrp_dpa_open(struct inode *inode, struct file *file)
 	/*
 	 *  Get the node pointer, and fail if it doesn't exist.
 	 */
-	de = PDE(inode);
-	if (!de) {
-		rtn = -ENXIO;
-		goto done;
-	}
-	nd = (struct nd_struct *)de->data;
+	nd = PDE_DATA(inode);
 	if (!nd) {
 		rtn = -ENXIO;
 		goto done;
diff --git a/drivers/staging/dgrp/dgrp_mon_ops.c b/drivers/staging/dgrp/dgrp_mon_ops.c
index 4792d05..6edbbf0 100644
--- a/drivers/staging/dgrp/dgrp_mon_ops.c
+++ b/drivers/staging/dgrp/dgrp_mon_ops.c
@@ -49,7 +49,7 @@ static ssize_t dgrp_mon_read(struct file *, char __user *, size_t, loff_t *);
 static long dgrp_mon_ioctl(struct file *file, unsigned int cmd,
 			   unsigned long arg);
 
-static const struct file_operations mon_ops = {
+const struct file_operations dgrp_mon_ops = {
 	.owner   = THIS_MODULE,
 	.read    = dgrp_mon_read,
 	.unlocked_ioctl = dgrp_mon_ioctl,
@@ -57,20 +57,6 @@ static const struct file_operations mon_ops = {
 	.release = dgrp_mon_release,
 };
 
-static struct inode_operations mon_inode_ops = {
-	.permission = dgrp_inode_permission
-};
-
-void dgrp_register_mon_hook(struct proc_dir_entry *de)
-{
-	struct nd_struct *node = de->data;
-
-	de->proc_iops = &mon_inode_ops;
-	de->proc_fops = &mon_ops;
-	node->nd_mon_de = de;
-	sema_init(&node->nd_mon_semaphore, 1);
-}
-
 /**
  * dgrp_mon_open() -- open /proc/dgrp/ports device for a PortServer
  * @inode: struct inode *
@@ -81,7 +67,6 @@ void dgrp_register_mon_hook(struct proc_dir_entry *de)
 static int dgrp_mon_open(struct inode *inode, struct file *file)
 {
 	struct nd_struct *nd;
-	struct proc_dir_entry *de;
 	struct timeval tv;
 	uint32_t time;
 	u8 *buf;
@@ -109,13 +94,7 @@ static int dgrp_mon_open(struct inode *inode, struct file *file)
 	/*
 	 *  Get the node pointer, and fail if it doesn't exist.
 	 */
-	de = PDE(inode);
-	if (!de) {
-		rtn = -ENXIO;
-		goto done;
-	}
-
-	nd = (struct nd_struct *)de->data;
+	nd = PDE_DATA(inode);
 	if (!nd) {
 		rtn = -ENXIO;
 		goto done;
diff --git a/drivers/staging/dgrp/dgrp_net_ops.c b/drivers/staging/dgrp/dgrp_net_ops.c
index e6018823..db3e3c7 100644
--- a/drivers/staging/dgrp/dgrp_net_ops.c
+++ b/drivers/staging/dgrp/dgrp_net_ops.c
@@ -72,7 +72,7 @@ static long dgrp_net_ioctl(struct file *file, unsigned int cmd,
 static unsigned int dgrp_net_select(struct file *file,
 				    struct poll_table_struct *table);
 
-static const struct file_operations net_ops = {
+const struct file_operations dgrp_net_ops = {
 	.owner   =  THIS_MODULE,
 	.read    =  dgrp_net_read,
 	.write   =  dgrp_net_write,
@@ -82,23 +82,6 @@ static const struct file_operations net_ops = {
 	.release =  dgrp_net_release,
 };
 
-static struct inode_operations net_inode_ops = {
-	.permission = dgrp_inode_permission
-};
-
-void dgrp_register_net_hook(struct proc_dir_entry *de)
-{
-	struct nd_struct *node = de->data;
-
-	de->proc_iops = &net_inode_ops;
-	de->proc_fops = &net_ops;
-	node->nd_net_de = de;
-	sema_init(&node->nd_net_semaphore, 1);
-	node->nd_state = NS_CLOSED;
-	dgrp_create_node_class_sysfs_files(node);
-}
-
-
 /**
  * dgrp_dump() -- prints memory for debugging purposes.
  * @mem: Memory location which should be printed to the console
@@ -801,7 +784,6 @@ out_err:
 static int dgrp_net_open(struct inode *inode, struct file *file)
 {
 	struct nd_struct *nd;
-	struct proc_dir_entry *de;
 	ulong  lock_flags;
 	int rtn;
 
@@ -825,13 +807,7 @@ static int dgrp_net_open(struct inode *inode, struct file *file)
 	/*
 	 *  Get the node pointer, and fail if it doesn't exist.
 	 */
-	de = PDE(inode);
-	if (!de) {
-		rtn = -ENXIO;
-		goto done;
-	}
-
-	nd = (struct nd_struct *) de->data;
+	nd = PDE_DATA(inode);
 	if (!nd) {
 		rtn = -ENXIO;
 		goto done;
@@ -3405,7 +3381,7 @@ static long dgrp_net_ioctl(struct file *file, unsigned int cmd,
 		if (size != sizeof(struct link_struct))
 			return -EINVAL;
 
-		if (copy_from_user((void *)(&link), (void __user *) arg, size))
+		if (copy_from_user(&link, (void __user *)arg, size))
 			return -EFAULT;
 
 		if (link.lk_fast_rate < 9600)
diff --git a/drivers/staging/dgrp/dgrp_ports_ops.c b/drivers/staging/dgrp/dgrp_ports_ops.c
index cd1fc20..4ce0308 100644
--- a/drivers/staging/dgrp/dgrp_ports_ops.c
+++ b/drivers/staging/dgrp/dgrp_ports_ops.c
@@ -47,7 +47,7 @@
 /* File operation declarations */
 static int dgrp_ports_open(struct inode *, struct file *);
 
-static const struct file_operations ports_ops = {
+const struct file_operations dgrp_ports_ops = {
 	.owner   = THIS_MODULE,
 	.open    = dgrp_ports_open,
 	.read    = seq_read,
@@ -55,20 +55,6 @@ static const struct file_operations ports_ops = {
 	.release = seq_release
 };
 
-static struct inode_operations ports_inode_ops = {
-	.permission = dgrp_inode_permission
-};
-
-
-void dgrp_register_ports_hook(struct proc_dir_entry *de)
-{
-	struct nd_struct *node = de->data;
-
-	de->proc_iops = &ports_inode_ops;
-	de->proc_fops = &ports_ops;
-	node->nd_ports_de = de;
-}
-
 static void *dgrp_ports_seq_start(struct seq_file *seq, loff_t *pos)
 {
 	if (*pos == 0)
@@ -163,7 +149,7 @@ static int dgrp_ports_open(struct inode *inode, struct file *file)
 	rtn = seq_open(file, &ports_seq_ops);
 	if (!rtn) {
 		seq = file->private_data;
-		seq->private = PDE(inode)->data;
+		seq->private = PDE_DATA(inode);
 	}
 
 	return rtn;
diff --git a/drivers/staging/dgrp/dgrp_specproc.c b/drivers/staging/dgrp/dgrp_specproc.c
index 73f287f..99c993b 100644
--- a/drivers/staging/dgrp/dgrp_specproc.c
+++ b/drivers/staging/dgrp/dgrp_specproc.c
@@ -44,43 +44,17 @@
 
 #include "dgrp_common.h"
 
-static struct dgrp_proc_entry dgrp_table[];
 static struct proc_dir_entry *dgrp_proc_dir_entry;
 
 static int dgrp_add_id(long id);
 static int dgrp_remove_nd(struct nd_struct *nd);
-static void unregister_dgrp_device(struct proc_dir_entry *de);
-static void register_dgrp_device(struct nd_struct *node,
+static struct proc_dir_entry *add_proc_file(struct nd_struct *node,
 				 struct proc_dir_entry *root,
-				 void (*register_hook)(struct proc_dir_entry *de));
+				 const struct file_operations *fops);
 
 /* File operation declarations */
-static int dgrp_gen_proc_open(struct inode *, struct file *);
-static int dgrp_gen_proc_close(struct inode *, struct file *);
 static int parse_write_config(char *);
 
-
-static const struct file_operations dgrp_proc_file_ops = {
-	.owner   = THIS_MODULE,
-	.open    = dgrp_gen_proc_open,
-	.release = dgrp_gen_proc_close,
-};
-
-static struct inode_operations proc_inode_ops = {
-	.permission = dgrp_inode_permission
-};
-
-
-static void register_proc_table(struct dgrp_proc_entry *,
-				struct proc_dir_entry *);
-static void unregister_proc_table(struct dgrp_proc_entry *,
-				  struct proc_dir_entry *);
-
-static struct dgrp_proc_entry dgrp_net_table[];
-static struct dgrp_proc_entry dgrp_mon_table[];
-static struct dgrp_proc_entry dgrp_ports_table[];
-static struct dgrp_proc_entry dgrp_dpa_table[];
-
 static ssize_t dgrp_config_proc_write(struct file *file,
 				      const char __user *buffer,
 				      size_t count, loff_t *pos);
@@ -114,71 +88,25 @@ static struct file_operations nodeinfo_proc_file_ops = {
 	.release = seq_release,
 };
 
-static struct dgrp_proc_entry dgrp_table[] = {
-	{
-		.id = DGRP_CONFIG,
-		.name = "config",
-		.mode = 0644,
-		.proc_file_ops = &config_proc_file_ops,
-	},
-	{
-		.id = DGRP_INFO,
-		.name = "info",
-		.mode = 0644,
-		.proc_file_ops = &info_proc_file_ops,
-	},
-	{
-		.id = DGRP_NODEINFO,
-		.name = "nodeinfo",
-		.mode = 0644,
-		.proc_file_ops = &nodeinfo_proc_file_ops,
-	},
-	{
-		.id = DGRP_NETDIR,
-		.name = "net",
-		.mode = 0500,
-		.child = dgrp_net_table
-	},
-	{
-		.id = DGRP_MONDIR,
-		.name = "mon",
-		.mode = 0500,
-		.child = dgrp_mon_table
-	},
-	{
-		.id = DGRP_PORTSDIR,
-		.name = "ports",
-		.mode = 0500,
-		.child = dgrp_ports_table
-	},
-	{
-		.id = DGRP_DPADIR,
-		.name = "dpa",
-		.mode = 0500,
-		.child = dgrp_dpa_table
-	}
-};
-
 static struct proc_dir_entry *net_entry_pointer;
 static struct proc_dir_entry *mon_entry_pointer;
 static struct proc_dir_entry *dpa_entry_pointer;
 static struct proc_dir_entry *ports_entry_pointer;
 
-static struct dgrp_proc_entry dgrp_net_table[] = {
-	{0}
-};
-
-static struct dgrp_proc_entry dgrp_mon_table[] = {
-	{0}
-};
-
-static struct dgrp_proc_entry dgrp_ports_table[] = {
-	{0}
-};
-
-static struct dgrp_proc_entry dgrp_dpa_table[] = {
-	{0}
-};
+static void remove_files(struct nd_struct *nd)
+{
+	char buf[3];
+	ID_TO_CHAR(nd->nd_ID, buf);
+	dgrp_remove_node_class_sysfs_files(nd);
+	if (nd->nd_net_de)
+		remove_proc_entry(buf, net_entry_pointer);
+	if (nd->nd_mon_de)
+		remove_proc_entry(buf, mon_entry_pointer);
+	if (nd->nd_dpa_de)
+		remove_proc_entry(buf, dpa_entry_pointer);
+	if (nd->nd_ports_de)
+		remove_proc_entry(buf, ports_entry_pointer);
+}
 
 void dgrp_unregister_proc(void)
 {
@@ -188,12 +116,19 @@ void dgrp_unregister_proc(void)
 	ports_entry_pointer = NULL;
 
 	if (dgrp_proc_dir_entry) {
-		unregister_proc_table(dgrp_table, dgrp_proc_dir_entry);
-		remove_proc_entry(dgrp_proc_dir_entry->name,
-				  dgrp_proc_dir_entry->parent);
+		struct nd_struct *nd;
+		list_for_each_entry(nd, &nd_struct_list, list)
+			remove_files(nd);
+		remove_proc_entry("dgrp/config", NULL);
+		remove_proc_entry("dgrp/info", NULL);
+		remove_proc_entry("dgrp/nodeinfo", NULL);
+		remove_proc_entry("dgrp/net", NULL);
+		remove_proc_entry("dgrp/mon", NULL);
+		remove_proc_entry("dgrp/dpa", NULL);
+		remove_proc_entry("dgrp/ports", NULL);
+		remove_proc_entry("dgrp", NULL);
 		dgrp_proc_dir_entry = NULL;
 	}
-
 }
 
 void dgrp_register_proc(void)
@@ -201,209 +136,16 @@ void dgrp_register_proc(void)
 	/*
 	 *	Register /proc/dgrp
 	 */
-	dgrp_proc_dir_entry = proc_create("dgrp", S_IFDIR, NULL,
-					  &dgrp_proc_file_ops);
-	register_proc_table(dgrp_table, dgrp_proc_dir_entry);
-}
-
-/*
- * /proc/sys support
- */
-static int dgrp_proc_match(int len, const char *name, struct proc_dir_entry *de)
-{
-	if (!de || !de->low_ino)
-		return 0;
-	if (de->namelen != len)
-		return 0;
-	return !memcmp(name, de->name, len);
-}
-
-
-/*
- *  Scan the entries in table and add them all to /proc at the position
- *  referred to by "root"
- */
-static void register_proc_table(struct dgrp_proc_entry *table,
-				struct proc_dir_entry *root)
-{
-	struct proc_dir_entry *de;
-	int len;
-	mode_t mode;
-
-	if (table == NULL)
+	dgrp_proc_dir_entry = proc_mkdir("dgrp", NULL);
+	if (!dgrp_proc_dir_entry)
 		return;
-	if (root == NULL)
-		return;
-
-	for (; table->id; table++) {
-		/* Can't do anything without a proc name. */
-		if (!table->name)
-			continue;
-
-		/* Maybe we can't do anything with it... */
-		if (!table->proc_file_ops &&
-		    !table->child) {
-			pr_warn("dgrp: Can't register %s\n",
-				table->name);
-			continue;
-		}
-
-		len = strlen(table->name);
-		mode = table->mode;
-
-		de = NULL;
-		if (!table->child)
-			mode |= S_IFREG;
-		else {
-			mode |= S_IFDIR;
-			for (de = root->subdir; de; de = de->next) {
-				if (dgrp_proc_match(len, table->name, de))
-					break;
-			}
-			/* If the subdir exists already, de is non-NULL */
-		}
-
-		if (!de) {
-			de = create_proc_entry(table->name, mode, root);
-			if (!de)
-				continue;
-			de->data = (void *) table;
-			if (!table->child) {
-				de->proc_iops = &proc_inode_ops;
-				if (table->proc_file_ops)
-					de->proc_fops = table->proc_file_ops;
-				else
-					de->proc_fops = &dgrp_proc_file_ops;
-			}
-		}
-		table->de = de;
-		if (de->mode & S_IFDIR)
-			register_proc_table(table->child, de);
-
-		if (table->id == DGRP_NETDIR)
-			net_entry_pointer = de;
-
-		if (table->id == DGRP_MONDIR)
-			mon_entry_pointer = de;
-
-		if (table->id == DGRP_DPADIR)
-			dpa_entry_pointer = de;
-
-		if (table->id == DGRP_PORTSDIR)
-			ports_entry_pointer = de;
-	}
-}
-
-/*
- * Unregister a /proc sysctl table and any subdirectories.
- */
-static void unregister_proc_table(struct dgrp_proc_entry *table,
-				  struct proc_dir_entry *root)
-{
-	struct proc_dir_entry *de;
-	struct nd_struct *tmp;
-
-	if (table == NULL)
-		return;
-
-	list_for_each_entry(tmp, &nd_struct_list, list) {
-		if ((table == dgrp_net_table) && (tmp->nd_net_de)) {
-			unregister_dgrp_device(tmp->nd_net_de);
-			dgrp_remove_node_class_sysfs_files(tmp);
-		}
-
-		if ((table == dgrp_mon_table) && (tmp->nd_mon_de))
-			unregister_dgrp_device(tmp->nd_mon_de);
-
-		if ((table == dgrp_dpa_table) && (tmp->nd_dpa_de))
-			unregister_dgrp_device(tmp->nd_dpa_de);
-
-		if ((table == dgrp_ports_table) && (tmp->nd_ports_de))
-			unregister_dgrp_device(tmp->nd_ports_de);
-	}
-
-	for (; table->id; table++) {
-		de = table->de;
-
-		if (!de)
-			continue;
-		if (de->mode & S_IFDIR) {
-			if (!table->child) {
-				pr_alert("dgrp: malformed sysctl tree on free\n");
-				continue;
-			}
-			unregister_proc_table(table->child, de);
-
-	/* Don't unregister directories which still have entries */
-			if (de->subdir)
-				continue;
-		}
-
-		/* Don't unregister proc entries that are still being used.. */
-		if ((atomic_read(&de->count)) != 1) {
-			pr_alert("proc entry %s in use, not removing\n",
-				de->name);
-			continue;
-		}
-
-		remove_proc_entry(de->name, de->parent);
-		table->de = NULL;
-	}
-}
-
-static int dgrp_gen_proc_open(struct inode *inode, struct file *file)
-{
-	struct proc_dir_entry *de;
-	struct dgrp_proc_entry *entry;
-	int ret = 0;
-
-	de = (struct proc_dir_entry *) PDE(file_inode(file));
-	if (!de || !de->data) {
-		ret = -ENXIO;
-		goto done;
-	}
-
-	entry = (struct dgrp_proc_entry *) de->data;
-	if (!entry) {
-		ret = -ENXIO;
-		goto done;
-	}
-
-	down(&entry->excl_sem);
-
-	if (entry->excl_cnt)
-		ret = -EBUSY;
-	else
-		entry->excl_cnt++;
-
-	up(&entry->excl_sem);
-
-done:
-	return ret;
-}
-
-static int dgrp_gen_proc_close(struct inode *inode, struct file *file)
-{
-	struct proc_dir_entry *de;
-	struct dgrp_proc_entry *entry;
-
-	de = (struct proc_dir_entry *) PDE(file_inode(file));
-	if (!de || !de->data)
-		goto done;
-
-	entry = (struct dgrp_proc_entry *) de->data;
-	if (!entry)
-		goto done;
-
-	down(&entry->excl_sem);
-
-	if (entry->excl_cnt)
-		entry->excl_cnt = 0;
-
-	up(&entry->excl_sem);
-
-done:
-	return 0;
+	proc_create("dgrp/config", 0644, NULL, &config_proc_file_ops);
+	proc_create("dgrp/info", 0644, NULL, &info_proc_file_ops);
+	proc_create("dgrp/nodeinfo", 0644, NULL, &nodeinfo_proc_file_ops);
+	net_entry_pointer = proc_mkdir_mode("dgrp/net", 0500, NULL);
+	mon_entry_pointer = proc_mkdir_mode("dgrp/mon", 0500, NULL);
+	dpa_entry_pointer = proc_mkdir_mode("dgrp/dpa", 0500, NULL);
+	ports_entry_pointer = proc_mkdir_mode("dgrp/ports", 0500, NULL);
 }
 
 static void *dgrp_config_proc_start(struct seq_file *m, loff_t *pos)
@@ -734,6 +476,10 @@ static int dgrp_add_id(long id)
 	init_waitqueue_head(&nd->nd_tx_waitq);
 	init_waitqueue_head(&nd->nd_mon_wqueue);
 	init_waitqueue_head(&nd->nd_dpa_wqueue);
+	sema_init(&nd->nd_mon_semaphore, 1);
+	sema_init(&nd->nd_net_semaphore, 1);
+	spin_lock_init(&nd->nd_dpa_lock);
+	nd->nd_state = NS_CLOSED;
 	for (i = 0; i < SEQ_MAX; i++)
 		init_waitqueue_head(&nd->nd_seq_wque[i]);
 
@@ -748,12 +494,12 @@ static int dgrp_add_id(long id)
 	if (ret)
 		goto error_out;
 
-	register_dgrp_device(nd, net_entry_pointer, dgrp_register_net_hook);
-	register_dgrp_device(nd, mon_entry_pointer, dgrp_register_mon_hook);
-	register_dgrp_device(nd, dpa_entry_pointer, dgrp_register_dpa_hook);
-	register_dgrp_device(nd, ports_entry_pointer,
-			      dgrp_register_ports_hook);
-
+	dgrp_create_node_class_sysfs_files(nd);
+	nd->nd_net_de = add_proc_file(nd, net_entry_pointer, &dgrp_net_ops);
+	nd->nd_mon_de = add_proc_file(nd, mon_entry_pointer, &dgrp_mon_ops);
+	nd->nd_dpa_de = add_proc_file(nd, dpa_entry_pointer, &dgrp_dpa_ops);
+	nd->nd_ports_de = add_proc_file(nd, ports_entry_pointer,
+					&dgrp_ports_ops);
 	return 0;
 
 	/* FIXME this guy should free the tty driver stored in nd and destroy
@@ -772,16 +518,7 @@ static int dgrp_remove_nd(struct nd_struct *nd)
 	if (nd->nd_tty_ref_cnt)
 		return -EBUSY;
 
-	if (nd->nd_net_de) {
-		unregister_dgrp_device(nd->nd_net_de);
-		dgrp_remove_node_class_sysfs_files(nd);
-	}
-
-	unregister_dgrp_device(nd->nd_mon_de);
-
-	unregister_dgrp_device(nd->nd_ports_de);
-
-	unregister_dgrp_device(nd->nd_dpa_de);
+	remove_files(nd);
 
 	dgrp_tty_uninit(nd);
 
@@ -793,38 +530,11 @@ static int dgrp_remove_nd(struct nd_struct *nd)
 	return 0;
 }
 
-static void register_dgrp_device(struct nd_struct *node,
+static struct proc_dir_entry *add_proc_file(struct nd_struct *node,
 				 struct proc_dir_entry *root,
-				 void (*register_hook)(struct proc_dir_entry *de))
+				 const struct file_operations *fops)
 {
 	char buf[3];
-	struct proc_dir_entry *de;
-
 	ID_TO_CHAR(node->nd_ID, buf);
-
-	de = create_proc_entry(buf, 0600 | S_IFREG, root);
-	if (!de)
-		return;
-
-	de->data = (void *) node;
-
-	if (register_hook)
-		register_hook(de);
-
-}
-
-static void unregister_dgrp_device(struct proc_dir_entry *de)
-{
-	if (!de)
-		return;
-
-	/* Don't unregister proc entries that are still being used.. */
-	if ((atomic_read(&de->count)) != 1) {
-		pr_alert("%s - proc entry %s in use. Not removing.\n",
-			 __func__, de->name);
-		return;
-	}
-
-	remove_proc_entry(de->name, de->parent);
-	de = NULL;
+	return proc_create_data(buf, 0600, root, fops, node);
 }
diff --git a/drivers/staging/dwc2/Kconfig b/drivers/staging/dwc2/Kconfig
new file mode 100644
index 0000000..bc4cdfe
--- /dev/null
+++ b/drivers/staging/dwc2/Kconfig
@@ -0,0 +1,42 @@
+config USB_DWC2
+	tristate "DesignWare USB2 DRD Core Support"
+	depends on USB
+	depends on VIRT_TO_BUS
+	select USB_OTG_UTILS
+	help
+	  Say Y or M here if your system has a Dual Role HighSpeed
+	  USB controller based on the DesignWare HSOTG IP Core.
+
+	  If you choose to build this driver as dynamically linked
+	  modules, the core module will be called dwc2.ko, and the
+	  PCI bus interface module (if you have a PCI bus system)
+	  will be called dwc2_pci.ko.
+
+	  NOTE: This driver at present only implements the Host mode
+	  of the controller. The existing s3c-hsotg driver supports
+	  Peripheral mode, but only for the Samsung S3C platforms.
+	  There are plans to merge the s3c-hsotg driver with this
+	  driver in the near future to create a dual-role driver.
+
+if USB_DWC2
+
+config USB_DWC2_DEBUG
+	bool "Enable Debugging Messages"
+	help
+	  Say Y here to enable debugging messages in the DWC2 Driver.
+
+config USB_DWC2_VERBOSE
+	bool "Enable Verbose Debugging Messages"
+	depends on USB_DWC2_DEBUG
+	help
+	  Say Y here to enable verbose debugging messages in the DWC2 Driver.
+	  WARNING: Enabling this will quickly fill your message log.
+	  If in doubt, say N.
+
+config USB_DWC2_TRACK_MISSED_SOFS
+	bool "Enable Missed SOF Tracking"
+	help
+	  Say Y here to enable logging of missed SOF events to the dmesg log.
+	  If in doubt, say N.
+
+endif
diff --git a/drivers/staging/dwc2/Makefile b/drivers/staging/dwc2/Makefile
new file mode 100644
index 0000000..6dccf46
--- /dev/null
+++ b/drivers/staging/dwc2/Makefile
@@ -0,0 +1,23 @@
+ccflags-$(CONFIG_USB_DWC2_DEBUG)	+= -DDEBUG
+ccflags-$(CONFIG_USB_DWC2_VERBOSE)	+= -DVERBOSE_DEBUG
+
+obj-$(CONFIG_USB_DWC2)			+= dwc2.o
+
+dwc2-y					+= core.o core_intr.o
+
+# NOTE: This driver at present only implements the Host mode
+# of the controller. The existing s3c-hsotg driver supports
+# Peripheral mode, but only for the Samsung S3C platforms.
+# There are plans to merge the s3c-hsotg driver with this
+# driver in the near future to create a dual-role driver. Once
+# that is done, Host mode will become an optional feature that
+# is selected with a config option.
+
+dwc2-y					+= hcd.o hcd_intr.o
+dwc2-y					+= hcd_queue.o hcd_ddma.o
+
+ifneq ($(CONFIG_PCI),)
+	obj-$(CONFIG_USB_DWC2)		+= dwc2_pci.o
+endif
+
+dwc2_pci-y				+= pci.o
diff --git a/drivers/staging/dwc2/core.c b/drivers/staging/dwc2/core.c
new file mode 100644
index 0000000..f695a9b0
--- /dev/null
+++ b/drivers/staging/dwc2/core.c
@@ -0,0 +1,2678 @@
+/*
+ * core.c - DesignWare HS OTG Controller common routines
+ *
+ * Copyright (C) 2004-2013 Synopsys, Inc.
+ *
+ * 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, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 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 names of the above-listed copyright holders may not 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 the License, or (at your option) any
+ * later version.
+ *
+ * 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.
+ */
+
+/*
+ * The Core code provides basic services for accessing and managing the
+ * DWC_otg hardware. These services are used by both the Host Controller
+ * Driver and the Peripheral Controller Driver.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+
+#include <linux/usb/hcd.h>
+#include <linux/usb/ch11.h>
+
+#include "core.h"
+#include "hcd.h"
+
+/**
+ * dwc2_enable_common_interrupts() - Initializes the commmon interrupts,
+ * used in both device and host modes
+ *
+ * @hsotg: Programming view of the DWC_otg controller
+ */
+static void dwc2_enable_common_interrupts(struct dwc2_hsotg *hsotg)
+{
+	u32 intmsk;
+
+	/* Clear any pending OTG Interrupts */
+	writel(0xffffffff, hsotg->regs + GOTGINT);
+
+	/* Clear any pending interrupts */
+	writel(0xffffffff, hsotg->regs + GINTSTS);
+
+	/* Enable the interrupts in the GINTMSK */
+	intmsk = GINTSTS_MODEMIS | GINTSTS_OTGINT;
+
+	if (hsotg->core_params->dma_enable <= 0)
+		intmsk |= GINTSTS_RXFLVL;
+
+	intmsk |= GINTSTS_CONIDSTSCHNG | GINTSTS_WKUPINT | GINTSTS_USBSUSP |
+		  GINTSTS_SESSREQINT;
+
+	writel(intmsk, hsotg->regs + GINTMSK);
+}
+
+/*
+ * Initializes the FSLSPClkSel field of the HCFG register depending on the
+ * PHY type
+ */
+static void dwc2_init_fs_ls_pclk_sel(struct dwc2_hsotg *hsotg)
+{
+	u32 hs_phy_type = hsotg->hwcfg2 & GHWCFG2_HS_PHY_TYPE_MASK;
+	u32 fs_phy_type = hsotg->hwcfg2 & GHWCFG2_FS_PHY_TYPE_MASK;
+	u32 hcfg, val;
+
+	if ((hs_phy_type == GHWCFG2_HS_PHY_TYPE_ULPI &&
+	     fs_phy_type == GHWCFG2_FS_PHY_TYPE_DEDICATED &&
+	     hsotg->core_params->ulpi_fs_ls > 0) ||
+	    hsotg->core_params->phy_type == DWC2_PHY_TYPE_PARAM_FS) {
+		/* Full speed PHY */
+		val = HCFG_FSLSPCLKSEL_48_MHZ;
+	} else {
+		/* High speed PHY running at full speed or high speed */
+		val = HCFG_FSLSPCLKSEL_30_60_MHZ;
+	}
+
+	dev_dbg(hsotg->dev, "Initializing HCFG.FSLSPClkSel to %08x\n", val);
+	hcfg = readl(hsotg->regs + HCFG);
+	hcfg &= ~HCFG_FSLSPCLKSEL_MASK;
+	hcfg |= val;
+	writel(hcfg, hsotg->regs + HCFG);
+}
+
+/*
+ * Do core a soft reset of the core.  Be careful with this because it
+ * resets all the internal state machines of the core.
+ */
+static void dwc2_core_reset(struct dwc2_hsotg *hsotg)
+{
+	u32 greset;
+	int count = 0;
+
+	dev_vdbg(hsotg->dev, "%s()\n", __func__);
+
+	/* Wait for AHB master IDLE state */
+	do {
+		usleep_range(20000, 40000);
+		greset = readl(hsotg->regs + GRSTCTL);
+		if (++count > 50) {
+			dev_warn(hsotg->dev,
+				 "%s() HANG! AHB Idle GRSTCTL=%0x\n",
+				 __func__, greset);
+			return;
+		}
+	} while (!(greset & GRSTCTL_AHBIDLE));
+
+	/* Core Soft Reset */
+	count = 0;
+	greset |= GRSTCTL_CSFTRST;
+	writel(greset, hsotg->regs + GRSTCTL);
+	do {
+		usleep_range(20000, 40000);
+		greset = readl(hsotg->regs + GRSTCTL);
+		if (++count > 50) {
+			dev_warn(hsotg->dev,
+				 "%s() HANG! Soft Reset GRSTCTL=%0x\n",
+				 __func__, greset);
+			break;
+		}
+	} while (greset & GRSTCTL_CSFTRST);
+
+	/*
+	 * NOTE: This long sleep is _very_ important, otherwise the core will
+	 * not stay in host mode after a connector ID change!
+	 */
+	usleep_range(150000, 200000);
+}
+
+static void dwc2_fs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
+{
+	u32 usbcfg, i2cctl;
+
+	/*
+	 * core_init() is now called on every switch so only call the
+	 * following for the first time through
+	 */
+	if (select_phy) {
+		dev_dbg(hsotg->dev, "FS PHY selected\n");
+		usbcfg = readl(hsotg->regs + GUSBCFG);
+		usbcfg |= GUSBCFG_PHYSEL;
+		writel(usbcfg, hsotg->regs + GUSBCFG);
+
+		/* Reset after a PHY select */
+		dwc2_core_reset(hsotg);
+	}
+
+	/*
+	 * Program DCFG.DevSpd or HCFG.FSLSPclkSel to 48Mhz in FS. Also
+	 * do this on HNP Dev/Host mode switches (done in dev_init and
+	 * host_init).
+	 */
+	if (dwc2_is_host_mode(hsotg))
+		dwc2_init_fs_ls_pclk_sel(hsotg);
+
+	if (hsotg->core_params->i2c_enable > 0) {
+		dev_dbg(hsotg->dev, "FS PHY enabling I2C\n");
+
+		/* Program GUSBCFG.OtgUtmiFsSel to I2C */
+		usbcfg = readl(hsotg->regs + GUSBCFG);
+		usbcfg |= GUSBCFG_OTG_UTMI_FS_SEL;
+		writel(usbcfg, hsotg->regs + GUSBCFG);
+
+		/* Program GI2CCTL.I2CEn */
+		i2cctl = readl(hsotg->regs + GI2CCTL);
+		i2cctl &= ~GI2CCTL_I2CDEVADDR_MASK;
+		i2cctl |= 1 << GI2CCTL_I2CDEVADDR_SHIFT;
+		i2cctl &= ~GI2CCTL_I2CEN;
+		writel(i2cctl, hsotg->regs + GI2CCTL);
+		i2cctl |= GI2CCTL_I2CEN;
+		writel(i2cctl, hsotg->regs + GI2CCTL);
+	}
+}
+
+static void dwc2_hs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
+{
+	u32 usbcfg;
+
+	if (!select_phy)
+		return;
+
+	usbcfg = readl(hsotg->regs + GUSBCFG);
+
+	/*
+	 * HS PHY parameters. These parameters are preserved during soft reset
+	 * so only program the first time. Do a soft reset immediately after
+	 * setting phyif.
+	 */
+	switch (hsotg->core_params->phy_type) {
+	case DWC2_PHY_TYPE_PARAM_ULPI:
+		/* ULPI interface */
+		dev_dbg(hsotg->dev, "HS ULPI PHY selected\n");
+		usbcfg |= GUSBCFG_ULPI_UTMI_SEL;
+		usbcfg &= ~(GUSBCFG_PHYIF16 | GUSBCFG_DDRSEL);
+		if (hsotg->core_params->phy_ulpi_ddr > 0)
+			usbcfg |= GUSBCFG_DDRSEL;
+		break;
+	case DWC2_PHY_TYPE_PARAM_UTMI:
+		/* UTMI+ interface */
+		dev_dbg(hsotg->dev, "HS UTMI+ PHY selected\n");
+		usbcfg &= ~(GUSBCFG_ULPI_UTMI_SEL | GUSBCFG_PHYIF16);
+		if (hsotg->core_params->phy_utmi_width == 16)
+			usbcfg |= GUSBCFG_PHYIF16;
+		break;
+	default:
+		dev_err(hsotg->dev, "FS PHY selected at HS!\n");
+		break;
+	}
+
+	writel(usbcfg, hsotg->regs + GUSBCFG);
+
+	/* Reset after setting the PHY parameters */
+	dwc2_core_reset(hsotg);
+}
+
+static void dwc2_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
+{
+	u32 usbcfg, hs_phy_type, fs_phy_type;
+
+	if (hsotg->core_params->speed == DWC2_SPEED_PARAM_FULL &&
+	    hsotg->core_params->phy_type == DWC2_PHY_TYPE_PARAM_FS) {
+		/* If FS mode with FS PHY */
+		dwc2_fs_phy_init(hsotg, select_phy);
+	} else {
+		/* High speed PHY */
+		dwc2_hs_phy_init(hsotg, select_phy);
+	}
+
+	hs_phy_type = hsotg->hwcfg2 & GHWCFG2_HS_PHY_TYPE_MASK;
+	fs_phy_type = hsotg->hwcfg2 & GHWCFG2_FS_PHY_TYPE_MASK;
+
+	if (hs_phy_type == GHWCFG2_HS_PHY_TYPE_ULPI &&
+	    fs_phy_type == GHWCFG2_FS_PHY_TYPE_DEDICATED &&
+	    hsotg->core_params->ulpi_fs_ls > 0) {
+		dev_dbg(hsotg->dev, "Setting ULPI FSLS\n");
+		usbcfg = readl(hsotg->regs + GUSBCFG);
+		usbcfg |= GUSBCFG_ULPI_FS_LS;
+		usbcfg |= GUSBCFG_ULPI_CLK_SUSP_M;
+		writel(usbcfg, hsotg->regs + GUSBCFG);
+	} else {
+		usbcfg = readl(hsotg->regs + GUSBCFG);
+		usbcfg &= ~GUSBCFG_ULPI_FS_LS;
+		usbcfg &= ~GUSBCFG_ULPI_CLK_SUSP_M;
+		writel(usbcfg, hsotg->regs + GUSBCFG);
+	}
+}
+
+static int dwc2_gahbcfg_init(struct dwc2_hsotg *hsotg)
+{
+	u32 ahbcfg = 0;
+
+	switch (hsotg->hwcfg2 & GHWCFG2_ARCHITECTURE_MASK) {
+	case GHWCFG2_EXT_DMA_ARCH:
+		dev_err(hsotg->dev, "External DMA Mode not supported\n");
+		return -EINVAL;
+
+	case GHWCFG2_INT_DMA_ARCH:
+		dev_dbg(hsotg->dev, "Internal DMA Mode\n");
+		/*
+		 * Old value was GAHBCFG_HBSTLEN_INCR - done for
+		 * Host mode ISOC in issue fix - vahrama
+		 */
+		ahbcfg |= GAHBCFG_HBSTLEN_INCR4;
+		break;
+
+	case GHWCFG2_SLAVE_ONLY_ARCH:
+	default:
+		dev_dbg(hsotg->dev, "Slave Only Mode\n");
+		break;
+	}
+
+	dev_dbg(hsotg->dev, "dma_enable:%d dma_desc_enable:%d\n",
+		hsotg->core_params->dma_enable,
+		hsotg->core_params->dma_desc_enable);
+
+	if (hsotg->core_params->dma_enable > 0) {
+		if (hsotg->core_params->dma_desc_enable > 0)
+			dev_dbg(hsotg->dev, "Using Descriptor DMA mode\n");
+		else
+			dev_dbg(hsotg->dev, "Using Buffer DMA mode\n");
+	} else {
+		dev_dbg(hsotg->dev, "Using Slave mode\n");
+		hsotg->core_params->dma_desc_enable = 0;
+	}
+
+	if (hsotg->core_params->ahb_single > 0)
+		ahbcfg |= GAHBCFG_AHB_SINGLE;
+
+	if (hsotg->core_params->dma_enable > 0)
+		ahbcfg |= GAHBCFG_DMA_EN;
+
+	writel(ahbcfg, hsotg->regs + GAHBCFG);
+
+	return 0;
+}
+
+static void dwc2_gusbcfg_init(struct dwc2_hsotg *hsotg)
+{
+	u32 usbcfg;
+
+	usbcfg = readl(hsotg->regs + GUSBCFG);
+	usbcfg &= ~(GUSBCFG_HNPCAP | GUSBCFG_SRPCAP);
+
+	switch (hsotg->hwcfg2 & GHWCFG2_OP_MODE_MASK) {
+	case GHWCFG2_OP_MODE_HNP_SRP_CAPABLE:
+		if (hsotg->core_params->otg_cap ==
+				DWC2_CAP_PARAM_HNP_SRP_CAPABLE)
+			usbcfg |= GUSBCFG_HNPCAP;
+		if (hsotg->core_params->otg_cap !=
+				DWC2_CAP_PARAM_NO_HNP_SRP_CAPABLE)
+			usbcfg |= GUSBCFG_SRPCAP;
+		break;
+
+	case GHWCFG2_OP_MODE_SRP_ONLY_CAPABLE:
+	case GHWCFG2_OP_MODE_SRP_CAPABLE_DEVICE:
+	case GHWCFG2_OP_MODE_SRP_CAPABLE_HOST:
+		if (hsotg->core_params->otg_cap !=
+				DWC2_CAP_PARAM_NO_HNP_SRP_CAPABLE)
+			usbcfg |= GUSBCFG_SRPCAP;
+		break;
+
+	case GHWCFG2_OP_MODE_NO_HNP_SRP_CAPABLE:
+	case GHWCFG2_OP_MODE_NO_SRP_CAPABLE_DEVICE:
+	case GHWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST:
+	default:
+		break;
+	}
+
+	writel(usbcfg, hsotg->regs + GUSBCFG);
+}
+
+/**
+ * dwc2_core_init() - Initializes the DWC_otg controller registers and
+ * prepares the core for device mode or host mode operation
+ *
+ * @hsotg:      Programming view of the DWC_otg controller
+ * @select_phy: If true then also set the Phy type
+ */
+int dwc2_core_init(struct dwc2_hsotg *hsotg, bool select_phy)
+{
+	u32 usbcfg, otgctl;
+	int retval;
+
+	dev_dbg(hsotg->dev, "%s(%p)\n", __func__, hsotg);
+
+	usbcfg = readl(hsotg->regs + GUSBCFG);
+
+	/* Set ULPI External VBUS bit if needed */
+	usbcfg &= ~GUSBCFG_ULPI_EXT_VBUS_DRV;
+	if (hsotg->core_params->phy_ulpi_ext_vbus ==
+				DWC2_PHY_ULPI_EXTERNAL_VBUS)
+		usbcfg |= GUSBCFG_ULPI_EXT_VBUS_DRV;
+
+	/* Set external TS Dline pulsing bit if needed */
+	usbcfg &= ~GUSBCFG_TERMSELDLPULSE;
+	if (hsotg->core_params->ts_dline > 0)
+		usbcfg |= GUSBCFG_TERMSELDLPULSE;
+
+	writel(usbcfg, hsotg->regs + GUSBCFG);
+
+	/* Reset the Controller */
+	dwc2_core_reset(hsotg);
+
+	dev_dbg(hsotg->dev, "num_dev_perio_in_ep=%d\n",
+		hsotg->hwcfg4 >> GHWCFG4_NUM_DEV_PERIO_IN_EP_SHIFT &
+		GHWCFG4_NUM_DEV_PERIO_IN_EP_MASK >>
+				GHWCFG4_NUM_DEV_PERIO_IN_EP_SHIFT);
+
+	hsotg->total_fifo_size = hsotg->hwcfg3 >> GHWCFG3_DFIFO_DEPTH_SHIFT &
+			GHWCFG3_DFIFO_DEPTH_MASK >> GHWCFG3_DFIFO_DEPTH_SHIFT;
+	hsotg->rx_fifo_size = readl(hsotg->regs + GRXFSIZ);
+	hsotg->nperio_tx_fifo_size =
+			readl(hsotg->regs + GNPTXFSIZ) >> 16 & 0xffff;
+
+	dev_dbg(hsotg->dev, "Total FIFO SZ=%d\n", hsotg->total_fifo_size);
+	dev_dbg(hsotg->dev, "RxFIFO SZ=%d\n", hsotg->rx_fifo_size);
+	dev_dbg(hsotg->dev, "NP TxFIFO SZ=%d\n", hsotg->nperio_tx_fifo_size);
+
+	/*
+	 * This needs to happen in FS mode before any other programming occurs
+	 */
+	dwc2_phy_init(hsotg, select_phy);
+
+	/* Program the GAHBCFG Register */
+	retval = dwc2_gahbcfg_init(hsotg);
+	if (retval)
+		return retval;
+
+	/* Program the GUSBCFG register */
+	dwc2_gusbcfg_init(hsotg);
+
+	/* Program the GOTGCTL register */
+	otgctl = readl(hsotg->regs + GOTGCTL);
+	otgctl &= ~GOTGCTL_OTGVER;
+	if (hsotg->core_params->otg_ver > 0)
+		otgctl |= GOTGCTL_OTGVER;
+	writel(otgctl, hsotg->regs + GOTGCTL);
+	dev_dbg(hsotg->dev, "OTG VER PARAM: %d\n", hsotg->core_params->otg_ver);
+
+	/* Clear the SRP success bit for FS-I2c */
+	hsotg->srp_success = 0;
+
+	/* Enable common interrupts */
+	dwc2_enable_common_interrupts(hsotg);
+
+	/*
+	 * Do device or host intialization based on mode during PCD and
+	 * HCD initialization
+	 */
+	if (dwc2_is_host_mode(hsotg)) {
+		dev_dbg(hsotg->dev, "Host Mode\n");
+		hsotg->op_state = OTG_STATE_A_HOST;
+	} else {
+		dev_dbg(hsotg->dev, "Device Mode\n");
+		hsotg->op_state = OTG_STATE_B_PERIPHERAL;
+	}
+
+	return 0;
+}
+
+/**
+ * dwc2_enable_host_interrupts() - Enables the Host mode interrupts
+ *
+ * @hsotg: Programming view of DWC_otg controller
+ */
+void dwc2_enable_host_interrupts(struct dwc2_hsotg *hsotg)
+{
+	u32 intmsk;
+
+	dev_dbg(hsotg->dev, "%s()\n", __func__);
+
+	/* Disable all interrupts */
+	writel(0, hsotg->regs + GINTMSK);
+	writel(0, hsotg->regs + HAINTMSK);
+
+	/* Clear any pending interrupts */
+	writel(0xffffffff, hsotg->regs + GINTSTS);
+
+	/* Enable the common interrupts */
+	dwc2_enable_common_interrupts(hsotg);
+
+	/* Enable host mode interrupts without disturbing common interrupts */
+	intmsk = readl(hsotg->regs + GINTMSK);
+	intmsk |= GINTSTS_DISCONNINT | GINTSTS_PRTINT | GINTSTS_HCHINT;
+	writel(intmsk, hsotg->regs + GINTMSK);
+}
+
+/**
+ * dwc2_disable_host_interrupts() - Disables the Host Mode interrupts
+ *
+ * @hsotg: Programming view of DWC_otg controller
+ */
+void dwc2_disable_host_interrupts(struct dwc2_hsotg *hsotg)
+{
+	u32 intmsk = readl(hsotg->regs + GINTMSK);
+
+	/* Disable host mode interrupts without disturbing common interrupts */
+	intmsk &= ~(GINTSTS_SOF | GINTSTS_PRTINT | GINTSTS_HCHINT |
+		    GINTSTS_PTXFEMP | GINTSTS_NPTXFEMP);
+	writel(intmsk, hsotg->regs + GINTMSK);
+}
+
+static void dwc2_config_fifos(struct dwc2_hsotg *hsotg)
+{
+	struct dwc2_core_params *params = hsotg->core_params;
+	u32 rxfsiz, nptxfsiz, ptxfsiz, hptxfsiz, dfifocfg;
+
+	if (!(hsotg->hwcfg2 & GHWCFG2_DYNAMIC_FIFO) ||
+	    !params->enable_dynamic_fifo)
+		return;
+
+	dev_dbg(hsotg->dev, "Total FIFO Size=%d\n", hsotg->total_fifo_size);
+	dev_dbg(hsotg->dev, "Rx FIFO Size=%d\n", params->host_rx_fifo_size);
+	dev_dbg(hsotg->dev, "NP Tx FIFO Size=%d\n",
+		params->host_nperio_tx_fifo_size);
+	dev_dbg(hsotg->dev, "P Tx FIFO Size=%d\n",
+		params->host_perio_tx_fifo_size);
+
+	/* Rx FIFO */
+	dev_dbg(hsotg->dev, "initial grxfsiz=%08x\n",
+		readl(hsotg->regs + GRXFSIZ));
+	writel(params->host_rx_fifo_size, hsotg->regs + GRXFSIZ);
+	dev_dbg(hsotg->dev, "new grxfsiz=%08x\n", readl(hsotg->regs + GRXFSIZ));
+
+	/* Non-periodic Tx FIFO */
+	dev_dbg(hsotg->dev, "initial gnptxfsiz=%08x\n",
+		readl(hsotg->regs + GNPTXFSIZ));
+	nptxfsiz = params->host_nperio_tx_fifo_size <<
+		   FIFOSIZE_DEPTH_SHIFT & FIFOSIZE_DEPTH_MASK;
+	nptxfsiz |= params->host_rx_fifo_size <<
+		    FIFOSIZE_STARTADDR_SHIFT & FIFOSIZE_STARTADDR_MASK;
+	writel(nptxfsiz, hsotg->regs + GNPTXFSIZ);
+	dev_dbg(hsotg->dev, "new gnptxfsiz=%08x\n",
+		readl(hsotg->regs + GNPTXFSIZ));
+
+	/* Periodic Tx FIFO */
+	dev_dbg(hsotg->dev, "initial hptxfsiz=%08x\n",
+		readl(hsotg->regs + HPTXFSIZ));
+	ptxfsiz = params->host_perio_tx_fifo_size <<
+		  FIFOSIZE_DEPTH_SHIFT & FIFOSIZE_DEPTH_MASK;
+	ptxfsiz |= (params->host_rx_fifo_size +
+		    params->host_nperio_tx_fifo_size) <<
+		   FIFOSIZE_STARTADDR_SHIFT & FIFOSIZE_STARTADDR_MASK;
+	writel(ptxfsiz, hsotg->regs + HPTXFSIZ);
+	dev_dbg(hsotg->dev, "new hptxfsiz=%08x\n",
+		readl(hsotg->regs + HPTXFSIZ));
+
+	if (hsotg->core_params->en_multiple_tx_fifo > 0 &&
+	    hsotg->snpsid <= DWC2_CORE_REV_2_94a) {
+		/*
+		 * Global DFIFOCFG calculation for Host mode -
+		 * include RxFIFO, NPTXFIFO and HPTXFIFO
+		 */
+		dfifocfg = readl(hsotg->regs + GDFIFOCFG);
+		rxfsiz = readl(hsotg->regs + GRXFSIZ) & 0x0000ffff;
+		nptxfsiz = readl(hsotg->regs + GNPTXFSIZ) >> 16 & 0xffff;
+		hptxfsiz = readl(hsotg->regs + HPTXFSIZ) >> 16 & 0xffff;
+		dfifocfg &= ~GDFIFOCFG_EPINFOBASE_MASK;
+		dfifocfg |= (rxfsiz + nptxfsiz + hptxfsiz) <<
+			    GDFIFOCFG_EPINFOBASE_SHIFT &
+			    GDFIFOCFG_EPINFOBASE_MASK;
+		writel(dfifocfg, hsotg->regs + GDFIFOCFG);
+	}
+}
+
+/**
+ * dwc2_core_host_init() - Initializes the DWC_otg controller registers for
+ * Host mode
+ *
+ * @hsotg: Programming view of DWC_otg controller
+ *
+ * This function flushes the Tx and Rx FIFOs and flushes any entries in the
+ * request queues. Host channels are reset to ensure that they are ready for
+ * performing transfers.
+ */
+void dwc2_core_host_init(struct dwc2_hsotg *hsotg)
+{
+	u32 hcfg, hfir, otgctl;
+
+	dev_dbg(hsotg->dev, "%s(%p)\n", __func__, hsotg);
+
+	/* Restart the Phy Clock */
+	writel(0, hsotg->regs + PCGCTL);
+
+	/* Initialize Host Configuration Register */
+	dwc2_init_fs_ls_pclk_sel(hsotg);
+	if (hsotg->core_params->speed == DWC2_SPEED_PARAM_FULL) {
+		hcfg = readl(hsotg->regs + HCFG);
+		hcfg |= HCFG_FSLSSUPP;
+		writel(hcfg, hsotg->regs + HCFG);
+	}
+
+	/*
+	 * This bit allows dynamic reloading of the HFIR register during
+	 * runtime. This bit needs to be programmed during inital configuration
+	 * and its value must not be changed during runtime.
+	 */
+	if (hsotg->core_params->reload_ctl > 0) {
+		hfir = readl(hsotg->regs + HFIR);
+		hfir |= HFIR_RLDCTRL;
+		writel(hfir, hsotg->regs + HFIR);
+	}
+
+	if (hsotg->core_params->dma_desc_enable > 0) {
+		u32 op_mode = hsotg->hwcfg2 & GHWCFG2_OP_MODE_MASK;
+
+		if (hsotg->snpsid < DWC2_CORE_REV_2_90a ||
+		    !(hsotg->hwcfg4 & GHWCFG4_DESC_DMA) ||
+		    op_mode == GHWCFG2_OP_MODE_SRP_CAPABLE_DEVICE ||
+		    op_mode == GHWCFG2_OP_MODE_NO_SRP_CAPABLE_DEVICE ||
+		    op_mode == GHWCFG2_OP_MODE_UNDEFINED) {
+			dev_err(hsotg->dev,
+				"Hardware does not support descriptor DMA mode -\n");
+			dev_err(hsotg->dev,
+				"falling back to buffer DMA mode.\n");
+			hsotg->core_params->dma_desc_enable = 0;
+		} else {
+			hcfg = readl(hsotg->regs + HCFG);
+			hcfg |= HCFG_DESCDMA;
+			writel(hcfg, hsotg->regs + HCFG);
+		}
+	}
+
+	/* Configure data FIFO sizes */
+	dwc2_config_fifos(hsotg);
+
+	/* TODO - check this */
+	/* Clear Host Set HNP Enable in the OTG Control Register */
+	otgctl = readl(hsotg->regs + GOTGCTL);
+	otgctl &= ~GOTGCTL_HSTSETHNPEN;
+	writel(otgctl, hsotg->regs + GOTGCTL);
+
+	/* Make sure the FIFOs are flushed */
+	dwc2_flush_tx_fifo(hsotg, 0x10 /* all TX FIFOs */);
+	dwc2_flush_rx_fifo(hsotg);
+
+	/* Clear Host Set HNP Enable in the OTG Control Register */
+	otgctl = readl(hsotg->regs + GOTGCTL);
+	otgctl &= ~GOTGCTL_HSTSETHNPEN;
+	writel(otgctl, hsotg->regs + GOTGCTL);
+
+	if (hsotg->core_params->dma_desc_enable <= 0) {
+		int num_channels, i;
+		u32 hcchar;
+
+		/* Flush out any leftover queued requests */
+		num_channels = hsotg->core_params->host_channels;
+		for (i = 0; i < num_channels; i++) {
+			hcchar = readl(hsotg->regs + HCCHAR(i));
+			hcchar &= ~HCCHAR_CHENA;
+			hcchar |= HCCHAR_CHDIS;
+			hcchar &= ~HCCHAR_EPDIR;
+			writel(hcchar, hsotg->regs + HCCHAR(i));
+		}
+
+		/* Halt all channels to put them into a known state */
+		for (i = 0; i < num_channels; i++) {
+			int count = 0;
+
+			hcchar = readl(hsotg->regs + HCCHAR(i));
+			hcchar |= HCCHAR_CHENA | HCCHAR_CHDIS;
+			hcchar &= ~HCCHAR_EPDIR;
+			writel(hcchar, hsotg->regs + HCCHAR(i));
+			dev_dbg(hsotg->dev, "%s: Halt channel %d\n",
+				__func__, i);
+			do {
+				hcchar = readl(hsotg->regs + HCCHAR(i));
+				if (++count > 1000) {
+					dev_err(hsotg->dev,
+						"Unable to clear enable on channel %d\n",
+						i);
+					break;
+				}
+				udelay(1);
+			} while (hcchar & HCCHAR_CHENA);
+		}
+	}
+
+	/* Turn on the vbus power */
+	dev_dbg(hsotg->dev, "Init: Port Power? op_state=%d\n", hsotg->op_state);
+	if (hsotg->op_state == OTG_STATE_A_HOST) {
+		u32 hprt0 = dwc2_read_hprt0(hsotg);
+
+		dev_dbg(hsotg->dev, "Init: Power Port (%d)\n",
+			!!(hprt0 & HPRT0_PWR));
+		if (!(hprt0 & HPRT0_PWR)) {
+			hprt0 |= HPRT0_PWR;
+			writel(hprt0, hsotg->regs + HPRT0);
+		}
+	}
+
+	dwc2_enable_host_interrupts(hsotg);
+}
+
+static void dwc2_hc_enable_slave_ints(struct dwc2_hsotg *hsotg,
+				      struct dwc2_host_chan *chan)
+{
+	u32 hcintmsk = HCINTMSK_CHHLTD;
+
+	switch (chan->ep_type) {
+	case USB_ENDPOINT_XFER_CONTROL:
+	case USB_ENDPOINT_XFER_BULK:
+		dev_vdbg(hsotg->dev, "control/bulk\n");
+		hcintmsk |= HCINTMSK_XFERCOMPL;
+		hcintmsk |= HCINTMSK_STALL;
+		hcintmsk |= HCINTMSK_XACTERR;
+		hcintmsk |= HCINTMSK_DATATGLERR;
+		if (chan->ep_is_in) {
+			hcintmsk |= HCINTMSK_BBLERR;
+		} else {
+			hcintmsk |= HCINTMSK_NAK;
+			hcintmsk |= HCINTMSK_NYET;
+			if (chan->do_ping)
+				hcintmsk |= HCINTMSK_ACK;
+		}
+
+		if (chan->do_split) {
+			hcintmsk |= HCINTMSK_NAK;
+			if (chan->complete_split)
+				hcintmsk |= HCINTMSK_NYET;
+			else
+				hcintmsk |= HCINTMSK_ACK;
+		}
+
+		if (chan->error_state)
+			hcintmsk |= HCINTMSK_ACK;
+		break;
+
+	case USB_ENDPOINT_XFER_INT:
+		dev_vdbg(hsotg->dev, "intr\n");
+		hcintmsk |= HCINTMSK_XFERCOMPL;
+		hcintmsk |= HCINTMSK_NAK;
+		hcintmsk |= HCINTMSK_STALL;
+		hcintmsk |= HCINTMSK_XACTERR;
+		hcintmsk |= HCINTMSK_DATATGLERR;
+		hcintmsk |= HCINTMSK_FRMOVRUN;
+
+		if (chan->ep_is_in)
+			hcintmsk |= HCINTMSK_BBLERR;
+		if (chan->error_state)
+			hcintmsk |= HCINTMSK_ACK;
+		if (chan->do_split) {
+			if (chan->complete_split)
+				hcintmsk |= HCINTMSK_NYET;
+			else
+				hcintmsk |= HCINTMSK_ACK;
+		}
+		break;
+
+	case USB_ENDPOINT_XFER_ISOC:
+		dev_vdbg(hsotg->dev, "isoc\n");
+		hcintmsk |= HCINTMSK_XFERCOMPL;
+		hcintmsk |= HCINTMSK_FRMOVRUN;
+		hcintmsk |= HCINTMSK_ACK;
+
+		if (chan->ep_is_in) {
+			hcintmsk |= HCINTMSK_XACTERR;
+			hcintmsk |= HCINTMSK_BBLERR;
+		}
+		break;
+	default:
+		dev_err(hsotg->dev, "## Unknown EP type ##\n");
+		break;
+	}
+
+	writel(hcintmsk, hsotg->regs + HCINTMSK(chan->hc_num));
+	dev_vdbg(hsotg->dev, "set HCINTMSK to %08x\n", hcintmsk);
+}
+
+static void dwc2_hc_enable_dma_ints(struct dwc2_hsotg *hsotg,
+				    struct dwc2_host_chan *chan)
+{
+	u32 hcintmsk = HCINTMSK_CHHLTD;
+
+	/*
+	 * For Descriptor DMA mode core halts the channel on AHB error.
+	 * Interrupt is not required.
+	 */
+	if (hsotg->core_params->dma_desc_enable <= 0) {
+		dev_vdbg(hsotg->dev, "desc DMA disabled\n");
+		hcintmsk |= HCINTMSK_AHBERR;
+	} else {
+		dev_vdbg(hsotg->dev, "desc DMA enabled\n");
+		if (chan->ep_type == USB_ENDPOINT_XFER_ISOC)
+			hcintmsk |= HCINTMSK_XFERCOMPL;
+	}
+
+	if (chan->error_state && !chan->do_split &&
+	    chan->ep_type != USB_ENDPOINT_XFER_ISOC) {
+		dev_vdbg(hsotg->dev, "setting ACK\n");
+		hcintmsk |= HCINTMSK_ACK;
+		if (chan->ep_is_in) {
+			hcintmsk |= HCINTMSK_DATATGLERR;
+			if (chan->ep_type != USB_ENDPOINT_XFER_INT)
+				hcintmsk |= HCINTMSK_NAK;
+		}
+	}
+
+	writel(hcintmsk, hsotg->regs + HCINTMSK(chan->hc_num));
+	dev_vdbg(hsotg->dev, "set HCINTMSK to %08x\n", hcintmsk);
+}
+
+static void dwc2_hc_enable_ints(struct dwc2_hsotg *hsotg,
+				struct dwc2_host_chan *chan)
+{
+	u32 intmsk;
+
+	if (hsotg->core_params->dma_enable > 0) {
+		dev_vdbg(hsotg->dev, "DMA enabled\n");
+		dwc2_hc_enable_dma_ints(hsotg, chan);
+	} else {
+		dev_vdbg(hsotg->dev, "DMA disabled\n");
+		dwc2_hc_enable_slave_ints(hsotg, chan);
+	}
+
+	/* Enable the top level host channel interrupt */
+	intmsk = readl(hsotg->regs + HAINTMSK);
+	intmsk |= 1 << chan->hc_num;
+	writel(intmsk, hsotg->regs + HAINTMSK);
+	dev_vdbg(hsotg->dev, "set HAINTMSK to %08x\n", intmsk);
+
+	/* Make sure host channel interrupts are enabled */
+	intmsk = readl(hsotg->regs + GINTMSK);
+	intmsk |= GINTSTS_HCHINT;
+	writel(intmsk, hsotg->regs + GINTMSK);
+	dev_vdbg(hsotg->dev, "set GINTMSK to %08x\n", intmsk);
+}
+
+/**
+ * dwc2_hc_init() - Prepares a host channel for transferring packets to/from
+ * a specific endpoint
+ *
+ * @hsotg: Programming view of DWC_otg controller
+ * @chan:  Information needed to initialize the host channel
+ *
+ * The HCCHARn register is set up with the characteristics specified in chan.
+ * Host channel interrupts that may need to be serviced while this transfer is
+ * in progress are enabled.
+ */
+void dwc2_hc_init(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan)
+{
+	u8 hc_num = chan->hc_num;
+	u32 hcintmsk;
+	u32 hcchar;
+	u32 hcsplt = 0;
+
+	dev_vdbg(hsotg->dev, "%s()\n", __func__);
+
+	/* Clear old interrupt conditions for this host channel */
+	hcintmsk = 0xffffffff;
+	hcintmsk &= ~HCINTMSK_RESERVED14_31;
+	writel(hcintmsk, hsotg->regs + HCINT(hc_num));
+
+	/* Enable channel interrupts required for this transfer */
+	dwc2_hc_enable_ints(hsotg, chan);
+
+	/*
+	 * Program the HCCHARn register with the endpoint characteristics for
+	 * the current transfer
+	 */
+	hcchar = chan->dev_addr << HCCHAR_DEVADDR_SHIFT & HCCHAR_DEVADDR_MASK;
+	hcchar |= chan->ep_num << HCCHAR_EPNUM_SHIFT & HCCHAR_EPNUM_MASK;
+	if (chan->ep_is_in)
+		hcchar |= HCCHAR_EPDIR;
+	if (chan->speed == USB_SPEED_LOW)
+		hcchar |= HCCHAR_LSPDDEV;
+	hcchar |= chan->ep_type << HCCHAR_EPTYPE_SHIFT & HCCHAR_EPTYPE_MASK;
+	hcchar |= chan->max_packet << HCCHAR_MPS_SHIFT & HCCHAR_MPS_MASK;
+	writel(hcchar, hsotg->regs + HCCHAR(hc_num));
+	dev_vdbg(hsotg->dev, "set HCCHAR(%d) to %08x\n", hc_num, hcchar);
+
+	dev_vdbg(hsotg->dev, "%s: Channel %d\n", __func__, hc_num);
+	dev_vdbg(hsotg->dev, "	 Dev Addr: %d\n",
+		 hcchar >> HCCHAR_DEVADDR_SHIFT &
+		 HCCHAR_DEVADDR_MASK >> HCCHAR_DEVADDR_SHIFT);
+	dev_vdbg(hsotg->dev, "	 Ep Num: %d\n",
+		 hcchar >> HCCHAR_EPNUM_SHIFT &
+		 HCCHAR_EPNUM_MASK >> HCCHAR_EPNUM_SHIFT);
+	dev_vdbg(hsotg->dev, "	 Is In: %d\n", !!(hcchar & HCCHAR_EPDIR));
+	dev_vdbg(hsotg->dev, "	 Is Low Speed: %d\n",
+		 !!(hcchar & HCCHAR_LSPDDEV));
+	dev_vdbg(hsotg->dev, "	 Ep Type: %d\n",
+		 hcchar >> HCCHAR_EPTYPE_SHIFT &
+		 HCCHAR_EPTYPE_MASK >> HCCHAR_EPTYPE_SHIFT);
+	dev_vdbg(hsotg->dev, "	 Max Pkt: %d\n",
+		 hcchar >> HCCHAR_MPS_SHIFT &
+		 HCCHAR_MPS_MASK >> HCCHAR_MPS_SHIFT);
+	dev_vdbg(hsotg->dev, "	 Multi Cnt: %d\n",
+		 hcchar >> HCCHAR_MULTICNT_SHIFT &
+		 HCCHAR_MULTICNT_MASK >> HCCHAR_MULTICNT_SHIFT);
+
+	/* Program the HCSPLT register for SPLITs */
+	if (chan->do_split) {
+		dev_vdbg(hsotg->dev, "Programming HC %d with split --> %s\n",
+			 hc_num, chan->complete_split ? "CSPLIT" : "SSPLIT");
+		if (chan->complete_split)
+			hcsplt |= HCSPLT_COMPSPLT;
+		hcsplt |= chan->xact_pos << HCSPLT_XACTPOS_SHIFT &
+			  HCSPLT_XACTPOS_MASK;
+		hcsplt |= chan->hub_addr << HCSPLT_HUBADDR_SHIFT &
+			  HCSPLT_HUBADDR_MASK;
+		hcsplt |= chan->hub_port << HCSPLT_PRTADDR_SHIFT &
+			  HCSPLT_PRTADDR_MASK;
+		dev_vdbg(hsotg->dev, "	  comp split %d\n",
+			 chan->complete_split);
+		dev_vdbg(hsotg->dev, "	  xact pos %d\n", chan->xact_pos);
+		dev_vdbg(hsotg->dev, "	  hub addr %d\n", chan->hub_addr);
+		dev_vdbg(hsotg->dev, "	  hub port %d\n", chan->hub_port);
+		dev_vdbg(hsotg->dev, "	  is_in %d\n", chan->ep_is_in);
+		dev_vdbg(hsotg->dev, "	  Max Pkt %d\n",
+			 hcchar >> HCCHAR_MPS_SHIFT &
+			 HCCHAR_MPS_MASK >> HCCHAR_MPS_SHIFT);
+		dev_vdbg(hsotg->dev, "	  xferlen %d\n", chan->xfer_len);
+	}
+
+	writel(hcsplt, hsotg->regs + HCSPLT(hc_num));
+}
+
+/**
+ * dwc2_hc_halt() - Attempts to halt a host channel
+ *
+ * @hsotg:       Controller register interface
+ * @chan:        Host channel to halt
+ * @halt_status: Reason for halting the channel
+ *
+ * This function should only be called in Slave mode or to abort a transfer in
+ * either Slave mode or DMA mode. Under normal circumstances in DMA mode, the
+ * controller halts the channel when the transfer is complete or a condition
+ * occurs that requires application intervention.
+ *
+ * In slave mode, checks for a free request queue entry, then sets the Channel
+ * Enable and Channel Disable bits of the Host Channel Characteristics
+ * register of the specified channel to intiate the halt. If there is no free
+ * request queue entry, sets only the Channel Disable bit of the HCCHARn
+ * register to flush requests for this channel. In the latter case, sets a
+ * flag to indicate that the host channel needs to be halted when a request
+ * queue slot is open.
+ *
+ * In DMA mode, always sets the Channel Enable and Channel Disable bits of the
+ * HCCHARn register. The controller ensures there is space in the request
+ * queue before submitting the halt request.
+ *
+ * Some time may elapse before the core flushes any posted requests for this
+ * host channel and halts. The Channel Halted interrupt handler completes the
+ * deactivation of the host channel.
+ */
+void dwc2_hc_halt(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan,
+		  enum dwc2_halt_status halt_status)
+{
+	u32 nptxsts, hptxsts, hcchar;
+
+	dev_vdbg(hsotg->dev, "%s()\n", __func__);
+	if (halt_status == DWC2_HC_XFER_NO_HALT_STATUS)
+		dev_err(hsotg->dev, "!!! halt_status = %d !!!\n", halt_status);
+
+	if (halt_status == DWC2_HC_XFER_URB_DEQUEUE ||
+	    halt_status == DWC2_HC_XFER_AHB_ERR) {
+		/*
+		 * Disable all channel interrupts except Ch Halted. The QTD
+		 * and QH state associated with this transfer has been cleared
+		 * (in the case of URB_DEQUEUE), so the channel needs to be
+		 * shut down carefully to prevent crashes.
+		 */
+		u32 hcintmsk = HCINTMSK_CHHLTD;
+
+		dev_vdbg(hsotg->dev, "dequeue/error\n");
+		writel(hcintmsk, hsotg->regs + HCINTMSK(chan->hc_num));
+
+		/*
+		 * Make sure no other interrupts besides halt are currently
+		 * pending. Handling another interrupt could cause a crash due
+		 * to the QTD and QH state.
+		 */
+		writel(~hcintmsk, hsotg->regs + HCINT(chan->hc_num));
+
+		/*
+		 * Make sure the halt status is set to URB_DEQUEUE or AHB_ERR
+		 * even if the channel was already halted for some other
+		 * reason
+		 */
+		chan->halt_status = halt_status;
+
+		hcchar = readl(hsotg->regs + HCCHAR(chan->hc_num));
+		if (!(hcchar & HCCHAR_CHENA)) {
+			/*
+			 * The channel is either already halted or it hasn't
+			 * started yet. In DMA mode, the transfer may halt if
+			 * it finishes normally or a condition occurs that
+			 * requires driver intervention. Don't want to halt
+			 * the channel again. In either Slave or DMA mode,
+			 * it's possible that the transfer has been assigned
+			 * to a channel, but not started yet when an URB is
+			 * dequeued. Don't want to halt a channel that hasn't
+			 * started yet.
+			 */
+			return;
+		}
+	}
+	if (chan->halt_pending) {
+		/*
+		 * A halt has already been issued for this channel. This might
+		 * happen when a transfer is aborted by a higher level in
+		 * the stack.
+		 */
+		dev_vdbg(hsotg->dev,
+			 "*** %s: Channel %d, chan->halt_pending already set ***\n",
+			 __func__, chan->hc_num);
+		return;
+	}
+
+	hcchar = readl(hsotg->regs + HCCHAR(chan->hc_num));
+
+	/* No need to set the bit in DDMA for disabling the channel */
+	/* TODO check it everywhere channel is disabled */
+	if (hsotg->core_params->dma_desc_enable <= 0) {
+		dev_vdbg(hsotg->dev, "desc DMA disabled\n");
+		hcchar |= HCCHAR_CHENA;
+	} else {
+		dev_dbg(hsotg->dev, "desc DMA enabled\n");
+	}
+	hcchar |= HCCHAR_CHDIS;
+
+	if (hsotg->core_params->dma_enable <= 0) {
+		dev_vdbg(hsotg->dev, "DMA not enabled\n");
+		hcchar |= HCCHAR_CHENA;
+
+		/* Check for space in the request queue to issue the halt */
+		if (chan->ep_type == USB_ENDPOINT_XFER_CONTROL ||
+		    chan->ep_type == USB_ENDPOINT_XFER_BULK) {
+			dev_vdbg(hsotg->dev, "control/bulk\n");
+			nptxsts = readl(hsotg->regs + GNPTXSTS);
+			if ((nptxsts & TXSTS_QSPCAVAIL_MASK) == 0) {
+				dev_vdbg(hsotg->dev, "Disabling channel\n");
+				hcchar &= ~HCCHAR_CHENA;
+			}
+		} else {
+			dev_vdbg(hsotg->dev, "isoc/intr\n");
+			hptxsts = readl(hsotg->regs + HPTXSTS);
+			if ((hptxsts & TXSTS_QSPCAVAIL_MASK) == 0 ||
+			    hsotg->queuing_high_bandwidth) {
+				dev_vdbg(hsotg->dev, "Disabling channel\n");
+				hcchar &= ~HCCHAR_CHENA;
+			}
+		}
+	} else {
+		dev_vdbg(hsotg->dev, "DMA enabled\n");
+	}
+
+	writel(hcchar, hsotg->regs + HCCHAR(chan->hc_num));
+	chan->halt_status = halt_status;
+
+	if (hcchar & HCCHAR_CHENA) {
+		dev_vdbg(hsotg->dev, "Channel enabled\n");
+		chan->halt_pending = 1;
+		chan->halt_on_queue = 0;
+	} else {
+		dev_vdbg(hsotg->dev, "Channel disabled\n");
+		chan->halt_on_queue = 1;
+	}
+
+	dev_vdbg(hsotg->dev, "%s: Channel %d\n", __func__, chan->hc_num);
+	dev_vdbg(hsotg->dev, "	 hcchar: 0x%08x\n", hcchar);
+	dev_vdbg(hsotg->dev, "	 halt_pending: %d\n", chan->halt_pending);
+	dev_vdbg(hsotg->dev, "	 halt_on_queue: %d\n", chan->halt_on_queue);
+	dev_vdbg(hsotg->dev, "	 halt_status: %d\n", chan->halt_status);
+}
+
+/**
+ * dwc2_hc_cleanup() - Clears the transfer state for a host channel
+ *
+ * @hsotg: Programming view of DWC_otg controller
+ * @chan:  Identifies the host channel to clean up
+ *
+ * This function is normally called after a transfer is done and the host
+ * channel is being released
+ */
+void dwc2_hc_cleanup(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan)
+{
+	u32 hcintmsk;
+
+	chan->xfer_started = 0;
+
+	/*
+	 * Clear channel interrupt enables and any unhandled channel interrupt
+	 * conditions
+	 */
+	writel(0, hsotg->regs + HCINTMSK(chan->hc_num));
+	hcintmsk = 0xffffffff;
+	hcintmsk &= ~HCINTMSK_RESERVED14_31;
+	writel(hcintmsk, hsotg->regs + HCINT(chan->hc_num));
+}
+
+/**
+ * dwc2_hc_set_even_odd_frame() - Sets the channel property that indicates in
+ * which frame a periodic transfer should occur
+ *
+ * @hsotg:  Programming view of DWC_otg controller
+ * @chan:   Identifies the host channel to set up and its properties
+ * @hcchar: Current value of the HCCHAR register for the specified host channel
+ *
+ * This function has no effect on non-periodic transfers
+ */
+static void dwc2_hc_set_even_odd_frame(struct dwc2_hsotg *hsotg,
+				       struct dwc2_host_chan *chan, u32 *hcchar)
+{
+	u32 hfnum, frnum;
+
+	if (chan->ep_type == USB_ENDPOINT_XFER_INT ||
+	    chan->ep_type == USB_ENDPOINT_XFER_ISOC) {
+		hfnum = readl(hsotg->regs + HFNUM);
+		frnum = hfnum >> HFNUM_FRNUM_SHIFT &
+			HFNUM_FRNUM_MASK >> HFNUM_FRNUM_SHIFT;
+
+		/* 1 if _next_ frame is odd, 0 if it's even */
+		if (frnum & 0x1)
+			*hcchar |= HCCHAR_ODDFRM;
+	}
+}
+
+static void dwc2_set_pid_isoc(struct dwc2_host_chan *chan)
+{
+	/* Set up the initial PID for the transfer */
+	if (chan->speed == USB_SPEED_HIGH) {
+		if (chan->ep_is_in) {
+			if (chan->multi_count == 1)
+				chan->data_pid_start = DWC2_HC_PID_DATA0;
+			else if (chan->multi_count == 2)
+				chan->data_pid_start = DWC2_HC_PID_DATA1;
+			else
+				chan->data_pid_start = DWC2_HC_PID_DATA2;
+		} else {
+			if (chan->multi_count == 1)
+				chan->data_pid_start = DWC2_HC_PID_DATA0;
+			else
+				chan->data_pid_start = DWC2_HC_PID_MDATA;
+		}
+	} else {
+		chan->data_pid_start = DWC2_HC_PID_DATA0;
+	}
+}
+
+/**
+ * dwc2_hc_write_packet() - Writes a packet into the Tx FIFO associated with
+ * the Host Channel
+ *
+ * @hsotg: Programming view of DWC_otg controller
+ * @chan:  Information needed to initialize the host channel
+ *
+ * This function should only be called in Slave mode. For a channel associated
+ * with a non-periodic EP, the non-periodic Tx FIFO is written. For a channel
+ * associated with a periodic EP, the periodic Tx FIFO is written.
+ *
+ * Upon return the xfer_buf and xfer_count fields in chan are incremented by
+ * the number of bytes written to the Tx FIFO.
+ */
+static void dwc2_hc_write_packet(struct dwc2_hsotg *hsotg,
+				 struct dwc2_host_chan *chan)
+{
+	u32 i;
+	u32 remaining_count;
+	u32 byte_count;
+	u32 dword_count;
+	u32 __iomem *data_fifo;
+	u32 *data_buf = (u32 *)chan->xfer_buf;
+
+	dev_vdbg(hsotg->dev, "%s()\n", __func__);
+
+	data_fifo = (u32 __iomem *)(hsotg->regs + HCFIFO(chan->hc_num));
+
+	remaining_count = chan->xfer_len - chan->xfer_count;
+	if (remaining_count > chan->max_packet)
+		byte_count = chan->max_packet;
+	else
+		byte_count = remaining_count;
+
+	dword_count = (byte_count + 3) / 4;
+
+	if (((unsigned long)data_buf & 0x3) == 0) {
+		/* xfer_buf is DWORD aligned */
+		for (i = 0; i < dword_count; i++, data_buf++)
+			writel(*data_buf, data_fifo);
+	} else {
+		/* xfer_buf is not DWORD aligned */
+		for (i = 0; i < dword_count; i++, data_buf++) {
+			u32 data = data_buf[0] | data_buf[1] << 8 |
+				   data_buf[2] << 16 | data_buf[3] << 24;
+			writel(data, data_fifo);
+		}
+	}
+
+	chan->xfer_count += byte_count;
+	chan->xfer_buf += byte_count;
+}
+
+/**
+ * dwc2_hc_start_transfer() - Does the setup for a data transfer for a host
+ * channel and starts the transfer
+ *
+ * @hsotg: Programming view of DWC_otg controller
+ * @chan:  Information needed to initialize the host channel. The xfer_len value
+ *         may be reduced to accommodate the max widths of the XferSize and
+ *         PktCnt fields in the HCTSIZn register. The multi_count value may be
+ *         changed to reflect the final xfer_len value.
+ *
+ * This function may be called in either Slave mode or DMA mode. In Slave mode,
+ * the caller must ensure that there is sufficient space in the request queue
+ * and Tx Data FIFO.
+ *
+ * For an OUT transfer in Slave mode, it loads a data packet into the
+ * appropriate FIFO. If necessary, additional data packets are loaded in the
+ * Host ISR.
+ *
+ * For an IN transfer in Slave mode, a data packet is requested. The data
+ * packets are unloaded from the Rx FIFO in the Host ISR. If necessary,
+ * additional data packets are requested in the Host ISR.
+ *
+ * For a PING transfer in Slave mode, the Do Ping bit is set in the HCTSIZ
+ * register along with a packet count of 1 and the channel is enabled. This
+ * causes a single PING transaction to occur. Other fields in HCTSIZ are
+ * simply set to 0 since no data transfer occurs in this case.
+ *
+ * For a PING transfer in DMA mode, the HCTSIZ register is initialized with
+ * all the information required to perform the subsequent data transfer. In
+ * addition, the Do Ping bit is set in the HCTSIZ register. In this case, the
+ * controller performs the entire PING protocol, then starts the data
+ * transfer.
+ */
+void dwc2_hc_start_transfer(struct dwc2_hsotg *hsotg,
+			    struct dwc2_host_chan *chan)
+{
+	u32 max_hc_xfer_size = hsotg->core_params->max_transfer_size;
+	u16 max_hc_pkt_count = hsotg->core_params->max_packet_count;
+	u32 hcchar;
+	u32 hctsiz = 0;
+	u16 num_packets;
+
+	dev_vdbg(hsotg->dev, "%s()\n", __func__);
+
+	if (chan->do_ping) {
+		if (hsotg->core_params->dma_enable <= 0) {
+			dev_vdbg(hsotg->dev, "ping, no DMA\n");
+			dwc2_hc_do_ping(hsotg, chan);
+			chan->xfer_started = 1;
+			return;
+		} else {
+			dev_vdbg(hsotg->dev, "ping, DMA\n");
+			hctsiz |= TSIZ_DOPNG;
+		}
+	}
+
+	if (chan->do_split) {
+		dev_vdbg(hsotg->dev, "split\n");
+		num_packets = 1;
+
+		if (chan->complete_split && !chan->ep_is_in)
+			/*
+			 * For CSPLIT OUT Transfer, set the size to 0 so the
+			 * core doesn't expect any data written to the FIFO
+			 */
+			chan->xfer_len = 0;
+		else if (chan->ep_is_in || chan->xfer_len > chan->max_packet)
+			chan->xfer_len = chan->max_packet;
+		else if (!chan->ep_is_in && chan->xfer_len > 188)
+			chan->xfer_len = 188;
+
+		hctsiz |= chan->xfer_len << TSIZ_XFERSIZE_SHIFT &
+			  TSIZ_XFERSIZE_MASK;
+	} else {
+		dev_vdbg(hsotg->dev, "no split\n");
+		/*
+		 * Ensure that the transfer length and packet count will fit
+		 * in the widths allocated for them in the HCTSIZn register
+		 */
+		if (chan->ep_type == USB_ENDPOINT_XFER_INT ||
+		    chan->ep_type == USB_ENDPOINT_XFER_ISOC) {
+			/*
+			 * Make sure the transfer size is no larger than one
+			 * (micro)frame's worth of data. (A check was done
+			 * when the periodic transfer was accepted to ensure
+			 * that a (micro)frame's worth of data can be
+			 * programmed into a channel.)
+			 */
+			u32 max_periodic_len =
+				chan->multi_count * chan->max_packet;
+
+			if (chan->xfer_len > max_periodic_len)
+				chan->xfer_len = max_periodic_len;
+		} else if (chan->xfer_len > max_hc_xfer_size) {
+			/*
+			 * Make sure that xfer_len is a multiple of max packet
+			 * size
+			 */
+			chan->xfer_len =
+				max_hc_xfer_size - chan->max_packet + 1;
+		}
+
+		if (chan->xfer_len > 0) {
+			num_packets = (chan->xfer_len + chan->max_packet - 1) /
+					chan->max_packet;
+			if (num_packets > max_hc_pkt_count) {
+				num_packets = max_hc_pkt_count;
+				chan->xfer_len = num_packets * chan->max_packet;
+			}
+		} else {
+			/* Need 1 packet for transfer length of 0 */
+			num_packets = 1;
+		}
+
+		if (chan->ep_is_in)
+			/*
+			 * Always program an integral # of max packets for IN
+			 * transfers
+			 */
+			chan->xfer_len = num_packets * chan->max_packet;
+
+		if (chan->ep_type == USB_ENDPOINT_XFER_INT ||
+		    chan->ep_type == USB_ENDPOINT_XFER_ISOC)
+			/*
+			 * Make sure that the multi_count field matches the
+			 * actual transfer length
+			 */
+			chan->multi_count = num_packets;
+
+		if (chan->ep_type == USB_ENDPOINT_XFER_ISOC)
+			dwc2_set_pid_isoc(chan);
+
+		hctsiz |= chan->xfer_len << TSIZ_XFERSIZE_SHIFT &
+			  TSIZ_XFERSIZE_MASK;
+	}
+
+	chan->start_pkt_count = num_packets;
+	hctsiz |= num_packets << TSIZ_PKTCNT_SHIFT & TSIZ_PKTCNT_MASK;
+	hctsiz |= chan->data_pid_start << TSIZ_SC_MC_PID_SHIFT &
+		  TSIZ_SC_MC_PID_MASK;
+	writel(hctsiz, hsotg->regs + HCTSIZ(chan->hc_num));
+	dev_vdbg(hsotg->dev, "Wrote %08x to HCTSIZ(%d)\n",
+		 hctsiz, chan->hc_num);
+
+	dev_vdbg(hsotg->dev, "%s: Channel %d\n", __func__, chan->hc_num);
+	dev_vdbg(hsotg->dev, "	 Xfer Size: %d\n",
+		 hctsiz >> TSIZ_XFERSIZE_SHIFT &
+		 TSIZ_XFERSIZE_MASK >> TSIZ_XFERSIZE_SHIFT);
+	dev_vdbg(hsotg->dev, "	 Num Pkts: %d\n",
+		 hctsiz >> TSIZ_PKTCNT_SHIFT &
+		 TSIZ_PKTCNT_MASK >> TSIZ_PKTCNT_SHIFT);
+	dev_vdbg(hsotg->dev, "	 Start PID: %d\n",
+		 hctsiz >> TSIZ_SC_MC_PID_SHIFT &
+		 TSIZ_SC_MC_PID_MASK >> TSIZ_SC_MC_PID_SHIFT);
+
+	if (hsotg->core_params->dma_enable > 0) {
+		dma_addr_t dma_addr;
+
+		if (chan->align_buf) {
+			dev_vdbg(hsotg->dev, "align_buf\n");
+			dma_addr = chan->align_buf;
+		} else {
+			dma_addr = chan->xfer_dma;
+		}
+		writel((u32)dma_addr, hsotg->regs + HCDMA(chan->hc_num));
+		dev_vdbg(hsotg->dev, "Wrote %08lx to HCDMA(%d)\n",
+			 (unsigned long)dma_addr, chan->hc_num);
+	}
+
+	/* Start the split */
+	if (chan->do_split) {
+		u32 hcsplt = readl(hsotg->regs + HCSPLT(chan->hc_num));
+
+		hcsplt |= HCSPLT_SPLTENA;
+		writel(hcsplt, hsotg->regs + HCSPLT(chan->hc_num));
+	}
+
+	hcchar = readl(hsotg->regs + HCCHAR(chan->hc_num));
+	hcchar &= ~HCCHAR_MULTICNT_MASK;
+	hcchar |= chan->multi_count << HCCHAR_MULTICNT_SHIFT &
+		  HCCHAR_MULTICNT_MASK;
+	dwc2_hc_set_even_odd_frame(hsotg, chan, &hcchar);
+
+	if (hcchar & HCCHAR_CHDIS)
+		dev_warn(hsotg->dev,
+			 "%s: chdis set, channel %d, hcchar 0x%08x\n",
+			 __func__, chan->hc_num, hcchar);
+
+	/* Set host channel enable after all other setup is complete */
+	hcchar |= HCCHAR_CHENA;
+	hcchar &= ~HCCHAR_CHDIS;
+
+	dev_vdbg(hsotg->dev, "	 Multi Cnt: %d\n",
+		 hcchar >> HCCHAR_MULTICNT_SHIFT &
+		 HCCHAR_MULTICNT_MASK >> HCCHAR_MULTICNT_SHIFT);
+
+	writel(hcchar, hsotg->regs + HCCHAR(chan->hc_num));
+	dev_vdbg(hsotg->dev, "Wrote %08x to HCCHAR(%d)\n", hcchar,
+		 chan->hc_num);
+
+	chan->xfer_started = 1;
+	chan->requests++;
+
+	if (hsotg->core_params->dma_enable <= 0 &&
+	    !chan->ep_is_in && chan->xfer_len > 0)
+		/* Load OUT packet into the appropriate Tx FIFO */
+		dwc2_hc_write_packet(hsotg, chan);
+}
+
+/**
+ * dwc2_hc_start_transfer_ddma() - Does the setup for a data transfer for a
+ * host channel and starts the transfer in Descriptor DMA mode
+ *
+ * @hsotg: Programming view of DWC_otg controller
+ * @chan:  Information needed to initialize the host channel
+ *
+ * Initializes HCTSIZ register. For a PING transfer the Do Ping bit is set.
+ * Sets PID and NTD values. For periodic transfers initializes SCHED_INFO field
+ * with micro-frame bitmap.
+ *
+ * Initializes HCDMA register with descriptor list address and CTD value then
+ * starts the transfer via enabling the channel.
+ */
+void dwc2_hc_start_transfer_ddma(struct dwc2_hsotg *hsotg,
+				 struct dwc2_host_chan *chan)
+{
+	u32 hcchar;
+	u32 hc_dma;
+	u32 hctsiz = 0;
+
+	if (chan->do_ping)
+		hctsiz |= TSIZ_DOPNG;
+
+	if (chan->ep_type == USB_ENDPOINT_XFER_ISOC)
+		dwc2_set_pid_isoc(chan);
+
+	/* Packet Count and Xfer Size are not used in Descriptor DMA mode */
+	hctsiz |= chan->data_pid_start << TSIZ_SC_MC_PID_SHIFT &
+		  TSIZ_SC_MC_PID_MASK;
+
+	/* 0 - 1 descriptor, 1 - 2 descriptors, etc */
+	hctsiz |= (chan->ntd - 1) << TSIZ_NTD_SHIFT & TSIZ_NTD_MASK;
+
+	/* Non-zero only for high-speed interrupt endpoints */
+	hctsiz |= chan->schinfo << TSIZ_SCHINFO_SHIFT & TSIZ_SCHINFO_MASK;
+
+	dev_vdbg(hsotg->dev, "%s: Channel %d\n", __func__, chan->hc_num);
+	dev_vdbg(hsotg->dev, "	 Start PID: %d\n", chan->data_pid_start);
+	dev_vdbg(hsotg->dev, "	 NTD: %d\n", chan->ntd - 1);
+
+	writel(hctsiz, hsotg->regs + HCTSIZ(chan->hc_num));
+
+	hc_dma = (u32)chan->desc_list_addr & HCDMA_DMA_ADDR_MASK;
+
+	/* Always start from first descriptor */
+	hc_dma &= ~HCDMA_CTD_MASK;
+	writel(hc_dma, hsotg->regs + HCDMA(chan->hc_num));
+	dev_vdbg(hsotg->dev, "Wrote %08x to HCDMA(%d)\n", hc_dma, chan->hc_num);
+
+	hcchar = readl(hsotg->regs + HCCHAR(chan->hc_num));
+	hcchar &= ~HCCHAR_MULTICNT_MASK;
+	hcchar |= chan->multi_count << HCCHAR_MULTICNT_SHIFT &
+		  HCCHAR_MULTICNT_MASK;
+
+	if (hcchar & HCCHAR_CHDIS)
+		dev_warn(hsotg->dev,
+			 "%s: chdis set, channel %d, hcchar 0x%08x\n",
+			 __func__, chan->hc_num, hcchar);
+
+	/* Set host channel enable after all other setup is complete */
+	hcchar |= HCCHAR_CHENA;
+	hcchar &= ~HCCHAR_CHDIS;
+
+	dev_vdbg(hsotg->dev, "	 Multi Cnt: %d\n",
+		 hcchar >> HCCHAR_MULTICNT_SHIFT &
+		 HCCHAR_MULTICNT_MASK >> HCCHAR_MULTICNT_SHIFT);
+
+	writel(hcchar, hsotg->regs + HCCHAR(chan->hc_num));
+	dev_vdbg(hsotg->dev, "Wrote %08x to HCCHAR(%d)\n", hcchar,
+		 chan->hc_num);
+
+	chan->xfer_started = 1;
+	chan->requests++;
+}
+
+/**
+ * dwc2_hc_continue_transfer() - Continues a data transfer that was started by
+ * a previous call to dwc2_hc_start_transfer()
+ *
+ * @hsotg: Programming view of DWC_otg controller
+ * @chan:  Information needed to initialize the host channel
+ *
+ * The caller must ensure there is sufficient space in the request queue and Tx
+ * Data FIFO. This function should only be called in Slave mode. In DMA mode,
+ * the controller acts autonomously to complete transfers programmed to a host
+ * channel.
+ *
+ * For an OUT transfer, a new data packet is loaded into the appropriate FIFO
+ * if there is any data remaining to be queued. For an IN transfer, another
+ * data packet is always requested. For the SETUP phase of a control transfer,
+ * this function does nothing.
+ *
+ * Return: 1 if a new request is queued, 0 if no more requests are required
+ * for this transfer
+ */
+int dwc2_hc_continue_transfer(struct dwc2_hsotg *hsotg,
+			      struct dwc2_host_chan *chan)
+{
+	dev_vdbg(hsotg->dev, "%s: Channel %d\n", __func__, chan->hc_num);
+
+	if (chan->do_split)
+		/* SPLITs always queue just once per channel */
+		return 0;
+
+	if (chan->data_pid_start == DWC2_HC_PID_SETUP)
+		/* SETUPs are queued only once since they can't be NAK'd */
+		return 0;
+
+	if (chan->ep_is_in) {
+		/*
+		 * Always queue another request for other IN transfers. If
+		 * back-to-back INs are issued and NAKs are received for both,
+		 * the driver may still be processing the first NAK when the
+		 * second NAK is received. When the interrupt handler clears
+		 * the NAK interrupt for the first NAK, the second NAK will
+		 * not be seen. So we can't depend on the NAK interrupt
+		 * handler to requeue a NAK'd request. Instead, IN requests
+		 * are issued each time this function is called. When the
+		 * transfer completes, the extra requests for the channel will
+		 * be flushed.
+		 */
+		u32 hcchar = readl(hsotg->regs + HCCHAR(chan->hc_num));
+
+		dwc2_hc_set_even_odd_frame(hsotg, chan, &hcchar);
+		hcchar |= HCCHAR_CHENA;
+		hcchar &= ~HCCHAR_CHDIS;
+		dev_vdbg(hsotg->dev, "	 IN xfer: hcchar = 0x%08x\n", hcchar);
+		writel(hcchar, hsotg->regs + HCCHAR(chan->hc_num));
+		chan->requests++;
+		return 1;
+	}
+
+	/* OUT transfers */
+
+	if (chan->xfer_count < chan->xfer_len) {
+		if (chan->ep_type == USB_ENDPOINT_XFER_INT ||
+		    chan->ep_type == USB_ENDPOINT_XFER_ISOC) {
+			u32 hcchar = readl(hsotg->regs +
+					   HCCHAR(chan->hc_num));
+
+			dwc2_hc_set_even_odd_frame(hsotg, chan,
+						   &hcchar);
+		}
+
+		/* Load OUT packet into the appropriate Tx FIFO */
+		dwc2_hc_write_packet(hsotg, chan);
+		chan->requests++;
+		return 1;
+	}
+
+	return 0;
+}
+
+/**
+ * dwc2_hc_do_ping() - Starts a PING transfer
+ *
+ * @hsotg: Programming view of DWC_otg controller
+ * @chan:  Information needed to initialize the host channel
+ *
+ * This function should only be called in Slave mode. The Do Ping bit is set in
+ * the HCTSIZ register, then the channel is enabled.
+ */
+void dwc2_hc_do_ping(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan)
+{
+	u32 hcchar;
+	u32 hctsiz;
+
+	dev_vdbg(hsotg->dev, "%s: Channel %d\n", __func__, chan->hc_num);
+
+	hctsiz = TSIZ_DOPNG;
+	hctsiz |= 1 << TSIZ_PKTCNT_SHIFT;
+	writel(hctsiz, hsotg->regs + HCTSIZ(chan->hc_num));
+
+	hcchar = readl(hsotg->regs + HCCHAR(chan->hc_num));
+	hcchar |= HCCHAR_CHENA;
+	hcchar &= ~HCCHAR_CHDIS;
+	writel(hcchar, hsotg->regs + HCCHAR(chan->hc_num));
+}
+
+/**
+ * dwc2_calc_frame_interval() - Calculates the correct frame Interval value for
+ * the HFIR register according to PHY type and speed
+ *
+ * @hsotg: Programming view of DWC_otg controller
+ *
+ * NOTE: The caller can modify the value of the HFIR register only after the
+ * Port Enable bit of the Host Port Control and Status register (HPRT.EnaPort)
+ * has been set
+ */
+u32 dwc2_calc_frame_interval(struct dwc2_hsotg *hsotg)
+{
+	u32 usbcfg;
+	u32 hwcfg2;
+	u32 hprt0;
+	int clock = 60;	/* default value */
+
+	usbcfg = readl(hsotg->regs + GUSBCFG);
+	hwcfg2 = readl(hsotg->regs + GHWCFG2);
+	hprt0 = readl(hsotg->regs + HPRT0);
+
+	if (!(usbcfg & GUSBCFG_PHYSEL) && (usbcfg & GUSBCFG_ULPI_UTMI_SEL) &&
+	    !(usbcfg & GUSBCFG_PHYIF16))
+		clock = 60;
+	if ((usbcfg & GUSBCFG_PHYSEL) && (hwcfg2 & GHWCFG2_FS_PHY_TYPE_MASK) ==
+	    GHWCFG2_FS_PHY_TYPE_SHARED_ULPI)
+		clock = 48;
+	if (!(usbcfg & GUSBCFG_PHY_LP_CLK_SEL) && !(usbcfg & GUSBCFG_PHYSEL) &&
+	    !(usbcfg & GUSBCFG_ULPI_UTMI_SEL) && (usbcfg & GUSBCFG_PHYIF16))
+		clock = 30;
+	if (!(usbcfg & GUSBCFG_PHY_LP_CLK_SEL) && !(usbcfg & GUSBCFG_PHYSEL) &&
+	    !(usbcfg & GUSBCFG_ULPI_UTMI_SEL) && !(usbcfg & GUSBCFG_PHYIF16))
+		clock = 60;
+	if ((usbcfg & GUSBCFG_PHY_LP_CLK_SEL) && !(usbcfg & GUSBCFG_PHYSEL) &&
+	    !(usbcfg & GUSBCFG_ULPI_UTMI_SEL) && (usbcfg & GUSBCFG_PHYIF16))
+		clock = 48;
+	if ((usbcfg & GUSBCFG_PHYSEL) && !(usbcfg & GUSBCFG_PHYIF16) &&
+	    (hwcfg2 & GHWCFG2_FS_PHY_TYPE_MASK) ==
+	    GHWCFG2_FS_PHY_TYPE_SHARED_UTMI)
+		clock = 48;
+	if ((usbcfg & GUSBCFG_PHYSEL) && (hwcfg2 & GHWCFG2_FS_PHY_TYPE_MASK) ==
+	    GHWCFG2_FS_PHY_TYPE_DEDICATED)
+		clock = 48;
+
+	if ((hprt0 & HPRT0_SPD_MASK) == 0)
+		/* High speed case */
+		return 125 * clock;
+	else
+		/* FS/LS case */
+		return 1000 * clock;
+}
+
+/**
+ * dwc2_read_packet() - Reads a packet from the Rx FIFO into the destination
+ * buffer
+ *
+ * @core_if: Programming view of DWC_otg controller
+ * @dest:    Destination buffer for the packet
+ * @bytes:   Number of bytes to copy to the destination
+ */
+void dwc2_read_packet(struct dwc2_hsotg *hsotg, u8 *dest, u16 bytes)
+{
+	u32 __iomem *fifo = hsotg->regs + HCFIFO(0);
+	u32 *data_buf = (u32 *)dest;
+	int word_count = (bytes + 3) / 4;
+	int i;
+
+	/*
+	 * Todo: Account for the case where dest is not dword aligned. This
+	 * requires reading data from the FIFO into a u32 temp buffer, then
+	 * moving it into the data buffer.
+	 */
+
+	dev_vdbg(hsotg->dev, "%s(%p,%p,%d)\n", __func__, hsotg, dest, bytes);
+
+	for (i = 0; i < word_count; i++, data_buf++)
+		*data_buf = readl(fifo);
+}
+
+/**
+ * dwc2_dump_host_registers() - Prints the host registers
+ *
+ * @hsotg: Programming view of DWC_otg controller
+ *
+ * NOTE: This function will be removed once the peripheral controller code
+ * is integrated and the driver is stable
+ */
+void dwc2_dump_host_registers(struct dwc2_hsotg *hsotg)
+{
+#ifdef DEBUG
+	u32 __iomem *addr;
+	int i;
+
+	dev_dbg(hsotg->dev, "Host Global Registers\n");
+	addr = hsotg->regs + HCFG;
+	dev_dbg(hsotg->dev, "HCFG	 @0x%08lX : 0x%08X\n",
+		(unsigned long)addr, readl(addr));
+	addr = hsotg->regs + HFIR;
+	dev_dbg(hsotg->dev, "HFIR	 @0x%08lX : 0x%08X\n",
+		(unsigned long)addr, readl(addr));
+	addr = hsotg->regs + HFNUM;
+	dev_dbg(hsotg->dev, "HFNUM	 @0x%08lX : 0x%08X\n",
+		(unsigned long)addr, readl(addr));
+	addr = hsotg->regs + HPTXSTS;
+	dev_dbg(hsotg->dev, "HPTXSTS	 @0x%08lX : 0x%08X\n",
+		(unsigned long)addr, readl(addr));
+	addr = hsotg->regs + HAINT;
+	dev_dbg(hsotg->dev, "HAINT	 @0x%08lX : 0x%08X\n",
+		(unsigned long)addr, readl(addr));
+	addr = hsotg->regs + HAINTMSK;
+	dev_dbg(hsotg->dev, "HAINTMSK	 @0x%08lX : 0x%08X\n",
+		(unsigned long)addr, readl(addr));
+	if (hsotg->core_params->dma_desc_enable > 0) {
+		addr = hsotg->regs + HFLBADDR;
+		dev_dbg(hsotg->dev, "HFLBADDR @0x%08lX : 0x%08X\n",
+			(unsigned long)addr, readl(addr));
+	}
+
+	addr = hsotg->regs + HPRT0;
+	dev_dbg(hsotg->dev, "HPRT0	 @0x%08lX : 0x%08X\n",
+		(unsigned long)addr, readl(addr));
+
+	for (i = 0; i < hsotg->core_params->host_channels; i++) {
+		dev_dbg(hsotg->dev, "Host Channel %d Specific Registers\n", i);
+		addr = hsotg->regs + HCCHAR(i);
+		dev_dbg(hsotg->dev, "HCCHAR	 @0x%08lX : 0x%08X\n",
+			(unsigned long)addr, readl(addr));
+		addr = hsotg->regs + HCSPLT(i);
+		dev_dbg(hsotg->dev, "HCSPLT	 @0x%08lX : 0x%08X\n",
+			(unsigned long)addr, readl(addr));
+		addr = hsotg->regs + HCINT(i);
+		dev_dbg(hsotg->dev, "HCINT	 @0x%08lX : 0x%08X\n",
+			(unsigned long)addr, readl(addr));
+		addr = hsotg->regs + HCINTMSK(i);
+		dev_dbg(hsotg->dev, "HCINTMSK	 @0x%08lX : 0x%08X\n",
+			(unsigned long)addr, readl(addr));
+		addr = hsotg->regs + HCTSIZ(i);
+		dev_dbg(hsotg->dev, "HCTSIZ	 @0x%08lX : 0x%08X\n",
+			(unsigned long)addr, readl(addr));
+		addr = hsotg->regs + HCDMA(i);
+		dev_dbg(hsotg->dev, "HCDMA	 @0x%08lX : 0x%08X\n",
+			(unsigned long)addr, readl(addr));
+		if (hsotg->core_params->dma_desc_enable > 0) {
+			addr = hsotg->regs + HCDMAB(i);
+			dev_dbg(hsotg->dev, "HCDMAB	 @0x%08lX : 0x%08X\n",
+				(unsigned long)addr, readl(addr));
+		}
+	}
+#endif
+}
+
+/**
+ * dwc2_dump_global_registers() - Prints the core global registers
+ *
+ * @hsotg: Programming view of DWC_otg controller
+ *
+ * NOTE: This function will be removed once the peripheral controller code
+ * is integrated and the driver is stable
+ */
+void dwc2_dump_global_registers(struct dwc2_hsotg *hsotg)
+{
+#ifdef DEBUG
+	u32 __iomem *addr;
+	int i, ep_num;
+	char *txfsiz;
+
+	dev_dbg(hsotg->dev, "Core Global Registers\n");
+	addr = hsotg->regs + GOTGCTL;
+	dev_dbg(hsotg->dev, "GOTGCTL	 @0x%08lX : 0x%08X\n",
+		(unsigned long)addr, readl(addr));
+	addr = hsotg->regs + GOTGINT;
+	dev_dbg(hsotg->dev, "GOTGINT	 @0x%08lX : 0x%08X\n",
+		(unsigned long)addr, readl(addr));
+	addr = hsotg->regs + GAHBCFG;
+	dev_dbg(hsotg->dev, "GAHBCFG	 @0x%08lX : 0x%08X\n",
+		(unsigned long)addr, readl(addr));
+	addr = hsotg->regs + GUSBCFG;
+	dev_dbg(hsotg->dev, "GUSBCFG	 @0x%08lX : 0x%08X\n",
+		(unsigned long)addr, readl(addr));
+	addr = hsotg->regs + GRSTCTL;
+	dev_dbg(hsotg->dev, "GRSTCTL	 @0x%08lX : 0x%08X\n",
+		(unsigned long)addr, readl(addr));
+	addr = hsotg->regs + GINTSTS;
+	dev_dbg(hsotg->dev, "GINTSTS	 @0x%08lX : 0x%08X\n",
+		(unsigned long)addr, readl(addr));
+	addr = hsotg->regs + GINTMSK;
+	dev_dbg(hsotg->dev, "GINTMSK	 @0x%08lX : 0x%08X\n",
+		(unsigned long)addr, readl(addr));
+	addr = hsotg->regs + GRXSTSR;
+	dev_dbg(hsotg->dev, "GRXSTSR	 @0x%08lX : 0x%08X\n",
+		(unsigned long)addr, readl(addr));
+	addr = hsotg->regs + GRXFSIZ;
+	dev_dbg(hsotg->dev, "GRXFSIZ	 @0x%08lX : 0x%08X\n",
+		(unsigned long)addr, readl(addr));
+	addr = hsotg->regs + GNPTXFSIZ;
+	dev_dbg(hsotg->dev, "GNPTXFSIZ	 @0x%08lX : 0x%08X\n",
+		(unsigned long)addr, readl(addr));
+	addr = hsotg->regs + GNPTXSTS;
+	dev_dbg(hsotg->dev, "GNPTXSTS	 @0x%08lX : 0x%08X\n",
+		(unsigned long)addr, readl(addr));
+	addr = hsotg->regs + GI2CCTL;
+	dev_dbg(hsotg->dev, "GI2CCTL	 @0x%08lX : 0x%08X\n",
+		(unsigned long)addr, readl(addr));
+	addr = hsotg->regs + GPVNDCTL;
+	dev_dbg(hsotg->dev, "GPVNDCTL	 @0x%08lX : 0x%08X\n",
+		(unsigned long)addr, readl(addr));
+	addr = hsotg->regs + GGPIO;
+	dev_dbg(hsotg->dev, "GGPIO	 @0x%08lX : 0x%08X\n",
+		(unsigned long)addr, readl(addr));
+	addr = hsotg->regs + GUID;
+	dev_dbg(hsotg->dev, "GUID	 @0x%08lX : 0x%08X\n",
+		(unsigned long)addr, readl(addr));
+	addr = hsotg->regs + GSNPSID;
+	dev_dbg(hsotg->dev, "GSNPSID	 @0x%08lX : 0x%08X\n",
+		(unsigned long)addr, readl(addr));
+	addr = hsotg->regs + GHWCFG1;
+	dev_dbg(hsotg->dev, "GHWCFG1	 @0x%08lX : 0x%08X\n",
+		(unsigned long)addr, readl(addr));
+	addr = hsotg->regs + GHWCFG2;
+	dev_dbg(hsotg->dev, "GHWCFG2	 @0x%08lX : 0x%08X\n",
+		(unsigned long)addr, readl(addr));
+	addr = hsotg->regs + GHWCFG3;
+	dev_dbg(hsotg->dev, "GHWCFG3	 @0x%08lX : 0x%08X\n",
+		(unsigned long)addr, readl(addr));
+	addr = hsotg->regs + GHWCFG4;
+	dev_dbg(hsotg->dev, "GHWCFG4	 @0x%08lX : 0x%08X\n",
+		(unsigned long)addr, readl(addr));
+	addr = hsotg->regs + GLPMCFG;
+	dev_dbg(hsotg->dev, "GLPMCFG	 @0x%08lX : 0x%08X\n",
+		(unsigned long)addr, readl(addr));
+	addr = hsotg->regs + GPWRDN;
+	dev_dbg(hsotg->dev, "GPWRDN	 @0x%08lX : 0x%08X\n",
+		(unsigned long)addr, readl(addr));
+	addr = hsotg->regs + GDFIFOCFG;
+	dev_dbg(hsotg->dev, "GDFIFOCFG	 @0x%08lX : 0x%08X\n",
+		(unsigned long)addr, readl(addr));
+	addr = hsotg->regs + HPTXFSIZ;
+	dev_dbg(hsotg->dev, "HPTXFSIZ	 @0x%08lX : 0x%08X\n",
+		(unsigned long)addr, readl(addr));
+
+	if (hsotg->core_params->en_multiple_tx_fifo <= 0) {
+		ep_num = hsotg->hwcfg4 >> GHWCFG4_NUM_DEV_PERIO_IN_EP_SHIFT &
+			 GHWCFG4_NUM_DEV_PERIO_IN_EP_MASK >>
+					 GHWCFG4_NUM_DEV_PERIO_IN_EP_SHIFT;
+		txfsiz = "DPTXFSIZ";
+	} else {
+		ep_num = hsotg->hwcfg4 >> GHWCFG4_NUM_IN_EPS_SHIFT &
+			 GHWCFG4_NUM_IN_EPS_MASK >> GHWCFG4_NUM_IN_EPS_SHIFT;
+		txfsiz = "DIENPTXF";
+	}
+
+	for (i = 0; i < ep_num; i++) {
+		addr = hsotg->regs + DPTXFSIZN(i + 1);
+		dev_dbg(hsotg->dev, "%s[%d] @0x%08lX : 0x%08X\n", txfsiz, i + 1,
+			(unsigned long)addr, readl(addr));
+	}
+
+	addr = hsotg->regs + PCGCTL;
+	dev_dbg(hsotg->dev, "PCGCTL	 @0x%08lX : 0x%08X\n",
+		(unsigned long)addr, readl(addr));
+#endif
+}
+
+/**
+ * dwc2_flush_tx_fifo() - Flushes a Tx FIFO
+ *
+ * @hsotg: Programming view of DWC_otg controller
+ * @num:   Tx FIFO to flush
+ */
+void dwc2_flush_tx_fifo(struct dwc2_hsotg *hsotg, const int num)
+{
+	u32 greset;
+	int count = 0;
+
+	dev_vdbg(hsotg->dev, "Flush Tx FIFO %d\n", num);
+
+	greset = GRSTCTL_TXFFLSH;
+	greset |= num << GRSTCTL_TXFNUM_SHIFT & GRSTCTL_TXFNUM_MASK;
+	writel(greset, hsotg->regs + GRSTCTL);
+
+	do {
+		greset = readl(hsotg->regs + GRSTCTL);
+		if (++count > 10000) {
+			dev_warn(hsotg->dev,
+				 "%s() HANG! GRSTCTL=%0x GNPTXSTS=0x%08x\n",
+				 __func__, greset,
+				 readl(hsotg->regs + GNPTXSTS));
+			break;
+		}
+		udelay(1);
+	} while (greset & GRSTCTL_TXFFLSH);
+
+	/* Wait for at least 3 PHY Clocks */
+	udelay(1);
+}
+
+/**
+ * dwc2_flush_rx_fifo() - Flushes the Rx FIFO
+ *
+ * @hsotg: Programming view of DWC_otg controller
+ */
+void dwc2_flush_rx_fifo(struct dwc2_hsotg *hsotg)
+{
+	u32 greset;
+	int count = 0;
+
+	dev_vdbg(hsotg->dev, "%s()\n", __func__);
+
+	greset = GRSTCTL_RXFFLSH;
+	writel(greset, hsotg->regs + GRSTCTL);
+
+	do {
+		greset = readl(hsotg->regs + GRSTCTL);
+		if (++count > 10000) {
+			dev_warn(hsotg->dev, "%s() HANG! GRSTCTL=%0x\n",
+				 __func__, greset);
+			break;
+		}
+		udelay(1);
+	} while (greset & GRSTCTL_RXFFLSH);
+
+	/* Wait for at least 3 PHY Clocks */
+	udelay(1);
+}
+
+#define DWC2_PARAM_TEST(a, b, c)	((a) < (b) || (a) > (c))
+
+/* Parameter access functions */
+int dwc2_set_param_otg_cap(struct dwc2_hsotg *hsotg, int val)
+{
+	int valid = 1;
+	int retval = 0;
+	u32 op_mode;
+
+	op_mode = hsotg->hwcfg2 & GHWCFG2_OP_MODE_MASK;
+
+	switch (val) {
+	case DWC2_CAP_PARAM_HNP_SRP_CAPABLE:
+		if (op_mode != GHWCFG2_OP_MODE_HNP_SRP_CAPABLE)
+			valid = 0;
+		break;
+	case DWC2_CAP_PARAM_SRP_ONLY_CAPABLE:
+		switch (op_mode) {
+		case GHWCFG2_OP_MODE_HNP_SRP_CAPABLE:
+		case GHWCFG2_OP_MODE_SRP_ONLY_CAPABLE:
+		case GHWCFG2_OP_MODE_SRP_CAPABLE_DEVICE:
+		case GHWCFG2_OP_MODE_SRP_CAPABLE_HOST:
+			break;
+		default:
+			valid = 0;
+			break;
+		}
+		break;
+	case DWC2_CAP_PARAM_NO_HNP_SRP_CAPABLE:
+		/* always valid */
+		break;
+	default:
+		valid = 0;
+		break;
+	}
+
+	if (!valid) {
+		if (val >= 0)
+			dev_err(hsotg->dev,
+				"%d invalid for otg_cap parameter. Check HW configuration.\n",
+				val);
+		switch (op_mode) {
+		case GHWCFG2_OP_MODE_HNP_SRP_CAPABLE:
+			val = DWC2_CAP_PARAM_HNP_SRP_CAPABLE;
+			break;
+		case GHWCFG2_OP_MODE_SRP_ONLY_CAPABLE:
+		case GHWCFG2_OP_MODE_SRP_CAPABLE_DEVICE:
+		case GHWCFG2_OP_MODE_SRP_CAPABLE_HOST:
+			val = DWC2_CAP_PARAM_SRP_ONLY_CAPABLE;
+			break;
+		default:
+			val = DWC2_CAP_PARAM_NO_HNP_SRP_CAPABLE;
+			break;
+		}
+		dev_dbg(hsotg->dev, "Setting otg_cap to %d\n", val);
+		retval = -EINVAL;
+	}
+
+	hsotg->core_params->otg_cap = val;
+	return retval;
+}
+
+int dwc2_set_param_dma_enable(struct dwc2_hsotg *hsotg, int val)
+{
+	int valid = 1;
+	int retval = 0;
+
+	if (val > 0 && (hsotg->hwcfg2 & GHWCFG2_ARCHITECTURE_MASK) ==
+	    GHWCFG2_SLAVE_ONLY_ARCH)
+		valid = 0;
+	if (val < 0)
+		valid = 0;
+
+	if (!valid) {
+		if (val >= 0)
+			dev_err(hsotg->dev,
+				"%d invalid for dma_enable parameter. Check HW configuration.\n",
+				val);
+		val = (hsotg->hwcfg2 & GHWCFG2_ARCHITECTURE_MASK) !=
+			GHWCFG2_SLAVE_ONLY_ARCH;
+		dev_dbg(hsotg->dev, "Setting dma_enable to %d\n", val);
+		retval = -EINVAL;
+	}
+
+	hsotg->core_params->dma_enable = val;
+	return retval;
+}
+
+int dwc2_set_param_dma_desc_enable(struct dwc2_hsotg *hsotg, int val)
+{
+	int valid = 1;
+	int retval = 0;
+
+	if (val > 0 && (hsotg->core_params->dma_enable <= 0 ||
+			!(hsotg->hwcfg4 & GHWCFG4_DESC_DMA)))
+		valid = 0;
+	if (val < 0)
+		valid = 0;
+
+	if (!valid) {
+		if (val >= 0)
+			dev_err(hsotg->dev,
+				"%d invalid for dma_desc_enable parameter. Check HW configuration.\n",
+				val);
+		val = (hsotg->core_params->dma_enable > 0 &&
+			(hsotg->hwcfg4 & GHWCFG4_DESC_DMA));
+		dev_dbg(hsotg->dev, "Setting dma_desc_enable to %d\n", val);
+		retval = -EINVAL;
+	}
+
+	hsotg->core_params->dma_desc_enable = val;
+	return retval;
+}
+
+int dwc2_set_param_host_support_fs_ls_low_power(struct dwc2_hsotg *hsotg,
+						int val)
+{
+	int retval = 0;
+
+	if (DWC2_PARAM_TEST(val, 0, 1)) {
+		if (val >= 0) {
+			dev_err(hsotg->dev,
+				"Wrong value for host_support_fs_low_power\n");
+			dev_err(hsotg->dev,
+				"host_support_fs_low_power must be 0 or 1\n");
+		}
+		val = 0;
+		dev_dbg(hsotg->dev,
+			"Setting host_support_fs_low_power to %d\n", val);
+		retval = -EINVAL;
+	}
+
+	hsotg->core_params->host_support_fs_ls_low_power = val;
+	return retval;
+}
+
+int dwc2_set_param_enable_dynamic_fifo(struct dwc2_hsotg *hsotg, int val)
+{
+	int valid = 1;
+	int retval = 0;
+
+	if (val > 0 && !(hsotg->hwcfg2 & GHWCFG2_DYNAMIC_FIFO))
+		valid = 0;
+	if (val < 0)
+		valid = 0;
+
+	if (!valid) {
+		if (val >= 0)
+			dev_err(hsotg->dev,
+				"%d invalid for enable_dynamic_fifo parameter. Check HW configuration.\n",
+				val);
+		val = !!(hsotg->hwcfg2 & GHWCFG2_DYNAMIC_FIFO);
+		dev_dbg(hsotg->dev, "Setting enable_dynamic_fifo to %d\n", val);
+		retval = -EINVAL;
+	}
+
+	hsotg->core_params->enable_dynamic_fifo = val;
+	return retval;
+}
+
+int dwc2_set_param_host_rx_fifo_size(struct dwc2_hsotg *hsotg, int val)
+{
+	int valid = 1;
+	int retval = 0;
+
+	if (val < 16 || val > readl(hsotg->regs + GRXFSIZ))
+		valid = 0;
+
+	if (!valid) {
+		if (val >= 0)
+			dev_err(hsotg->dev,
+				"%d invalid for host_rx_fifo_size. Check HW configuration.\n",
+				val);
+		val = readl(hsotg->regs + GRXFSIZ);
+		dev_dbg(hsotg->dev, "Setting host_rx_fifo_size to %d\n", val);
+		retval = -EINVAL;
+	}
+
+	hsotg->core_params->host_rx_fifo_size = val;
+	return retval;
+}
+
+int dwc2_set_param_host_nperio_tx_fifo_size(struct dwc2_hsotg *hsotg, int val)
+{
+	int valid = 1;
+	int retval = 0;
+
+	if (val < 16 || val > (readl(hsotg->regs + GNPTXFSIZ) >> 16 & 0xffff))
+		valid = 0;
+
+	if (!valid) {
+		if (val >= 0)
+			dev_err(hsotg->dev,
+				"%d invalid for host_nperio_tx_fifo_size. Check HW configuration.\n",
+				val);
+		val = readl(hsotg->regs + GNPTXFSIZ) >> 16 & 0xffff;
+		dev_dbg(hsotg->dev, "Setting host_nperio_tx_fifo_size to %d\n",
+			val);
+		retval = -EINVAL;
+	}
+
+	hsotg->core_params->host_nperio_tx_fifo_size = val;
+	return retval;
+}
+
+int dwc2_set_param_host_perio_tx_fifo_size(struct dwc2_hsotg *hsotg, int val)
+{
+	int valid = 1;
+	int retval = 0;
+
+	if (val < 16 || val > (hsotg->hptxfsiz >> 16))
+		valid = 0;
+
+	if (!valid) {
+		if (val >= 0)
+			dev_err(hsotg->dev,
+				"%d invalid for host_perio_tx_fifo_size. Check HW configuration.\n",
+				val);
+		val = hsotg->hptxfsiz >> 16;
+		dev_dbg(hsotg->dev, "Setting host_perio_tx_fifo_size to %d\n",
+			val);
+		retval = -EINVAL;
+	}
+
+	hsotg->core_params->host_perio_tx_fifo_size = val;
+	return retval;
+}
+
+int dwc2_set_param_max_transfer_size(struct dwc2_hsotg *hsotg, int val)
+{
+	int valid = 1;
+	int retval = 0;
+	int width = hsotg->hwcfg3 >> GHWCFG3_XFER_SIZE_CNTR_WIDTH_SHIFT &
+		    GHWCFG3_XFER_SIZE_CNTR_WIDTH_MASK >>
+				GHWCFG3_XFER_SIZE_CNTR_WIDTH_SHIFT;
+
+	if (val < 2047 || val >= (1 << (width + 11)))
+		valid = 0;
+
+	if (!valid) {
+		if (val >= 0)
+			dev_err(hsotg->dev,
+				"%d invalid for max_transfer_size. Check HW configuration.\n",
+				val);
+		val = (1 << (width + 11)) - 1;
+		dev_dbg(hsotg->dev, "Setting max_transfer_size to %d\n", val);
+		retval = -EINVAL;
+	}
+
+	hsotg->core_params->max_transfer_size = val;
+	return retval;
+}
+
+int dwc2_set_param_max_packet_count(struct dwc2_hsotg *hsotg, int val)
+{
+	int valid = 1;
+	int retval = 0;
+	int width = hsotg->hwcfg3 >> GHWCFG3_PACKET_SIZE_CNTR_WIDTH_SHIFT &
+		    GHWCFG3_PACKET_SIZE_CNTR_WIDTH_MASK >>
+				GHWCFG3_PACKET_SIZE_CNTR_WIDTH_SHIFT;
+
+	if (val < 15 || val > (1 << (width + 4)))
+		valid = 0;
+
+	if (!valid) {
+		if (val >= 0)
+			dev_err(hsotg->dev,
+				"%d invalid for max_packet_count. Check HW configuration.\n",
+				val);
+		val = (1 << (width + 4)) - 1;
+		dev_dbg(hsotg->dev, "Setting max_packet_count to %d\n", val);
+		retval = -EINVAL;
+	}
+
+	hsotg->core_params->max_packet_count = val;
+	return retval;
+}
+
+int dwc2_set_param_host_channels(struct dwc2_hsotg *hsotg, int val)
+{
+	int valid = 1;
+	int retval = 0;
+	int num_chan = hsotg->hwcfg2 >> GHWCFG2_NUM_HOST_CHAN_SHIFT &
+		GHWCFG2_NUM_HOST_CHAN_MASK >> GHWCFG2_NUM_HOST_CHAN_SHIFT;
+
+	if (val < 1 || val > num_chan + 1)
+		valid = 0;
+
+	if (!valid) {
+		if (val >= 0)
+			dev_err(hsotg->dev,
+				"%d invalid for host_channels. Check HW configuration.\n",
+				val);
+		val = num_chan + 1;
+		dev_dbg(hsotg->dev, "Setting host_channels to %d\n", val);
+		retval = -EINVAL;
+	}
+
+	hsotg->core_params->host_channels = val;
+	return retval;
+}
+
+int dwc2_set_param_phy_type(struct dwc2_hsotg *hsotg, int val)
+{
+#ifndef NO_FS_PHY_HW_CHECKS
+	int valid = 0;
+	u32 hs_phy_type;
+	u32 fs_phy_type;
+#endif
+	int retval = 0;
+
+	if (DWC2_PARAM_TEST(val, DWC2_PHY_TYPE_PARAM_FS,
+			    DWC2_PHY_TYPE_PARAM_ULPI)) {
+		if (val >= 0) {
+			dev_err(hsotg->dev, "Wrong value for phy_type\n");
+			dev_err(hsotg->dev, "phy_type must be 0, 1 or 2\n");
+		}
+
+#ifndef NO_FS_PHY_HW_CHECKS
+		valid = 0;
+#else
+		val = 0;
+		dev_dbg(hsotg->dev, "Setting phy_type to %d\n", val);
+		retval = -EINVAL;
+#endif
+	}
+
+#ifndef NO_FS_PHY_HW_CHECKS
+	hs_phy_type = hsotg->hwcfg2 & GHWCFG2_HS_PHY_TYPE_MASK;
+	fs_phy_type = hsotg->hwcfg2 & GHWCFG2_FS_PHY_TYPE_MASK;
+
+	if (val == DWC2_PHY_TYPE_PARAM_UTMI &&
+	    (hs_phy_type == GHWCFG2_HS_PHY_TYPE_UTMI ||
+	     hs_phy_type == GHWCFG2_HS_PHY_TYPE_UTMI_ULPI))
+		valid = 1;
+	else if (val == DWC2_PHY_TYPE_PARAM_ULPI &&
+		 (hs_phy_type == GHWCFG2_HS_PHY_TYPE_ULPI ||
+		  hs_phy_type == GHWCFG2_HS_PHY_TYPE_UTMI_ULPI))
+		valid = 1;
+	else if (val == DWC2_PHY_TYPE_PARAM_FS &&
+		 fs_phy_type == GHWCFG2_FS_PHY_TYPE_DEDICATED)
+		valid = 1;
+
+	if (!valid) {
+		if (val >= 0)
+			dev_err(hsotg->dev,
+				"%d invalid for phy_type. Check HW configuration.\n",
+				val);
+		val = 0;
+		if (hs_phy_type != GHWCFG2_HS_PHY_TYPE_NOT_SUPPORTED) {
+			if (hs_phy_type == GHWCFG2_HS_PHY_TYPE_UTMI ||
+			    hs_phy_type == GHWCFG2_HS_PHY_TYPE_UTMI_ULPI)
+				val = DWC2_PHY_TYPE_PARAM_UTMI;
+			else
+				val = DWC2_PHY_TYPE_PARAM_ULPI;
+		}
+		dev_dbg(hsotg->dev, "Setting phy_type to %d\n", val);
+		retval = -EINVAL;
+	}
+#endif
+
+	hsotg->core_params->phy_type = val;
+	return retval;
+}
+
+static int dwc2_get_param_phy_type(struct dwc2_hsotg *hsotg)
+{
+	return hsotg->core_params->phy_type;
+}
+
+int dwc2_set_param_speed(struct dwc2_hsotg *hsotg, int val)
+{
+	int valid = 1;
+	int retval = 0;
+
+	if (DWC2_PARAM_TEST(val, 0, 1)) {
+		if (val >= 0) {
+			dev_err(hsotg->dev, "Wrong value for speed parameter\n");
+			dev_err(hsotg->dev, "max_speed parameter must be 0 or 1\n");
+		}
+		valid = 0;
+	}
+
+	if (val == 0 && dwc2_get_param_phy_type(hsotg) ==
+					DWC2_PHY_TYPE_PARAM_FS)
+		valid = 0;
+
+	if (!valid) {
+		if (val >= 0)
+			dev_err(hsotg->dev,
+				"%d invalid for speed parameter. Check HW configuration.\n",
+				val);
+		val = dwc2_get_param_phy_type(hsotg) == DWC2_PHY_TYPE_PARAM_FS ?
+				1 : 0;
+		dev_dbg(hsotg->dev, "Setting speed to %d\n", val);
+		retval = -EINVAL;
+	}
+
+	hsotg->core_params->speed = val;
+	return retval;
+}
+
+int dwc2_set_param_host_ls_low_power_phy_clk(struct dwc2_hsotg *hsotg, int val)
+{
+	int valid = 1;
+	int retval = 0;
+
+	if (DWC2_PARAM_TEST(val, DWC2_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ,
+			    DWC2_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ)) {
+		if (val >= 0) {
+			dev_err(hsotg->dev,
+				"Wrong value for host_ls_low_power_phy_clk parameter\n");
+			dev_err(hsotg->dev,
+				"host_ls_low_power_phy_clk must be 0 or 1\n");
+		}
+		valid = 0;
+	}
+
+	if (val == DWC2_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ &&
+	    dwc2_get_param_phy_type(hsotg) == DWC2_PHY_TYPE_PARAM_FS)
+		valid = 0;
+
+	if (!valid) {
+		if (val >= 0)
+			dev_err(hsotg->dev,
+				"%d invalid for host_ls_low_power_phy_clk. Check HW configuration.\n",
+				val);
+		val = dwc2_get_param_phy_type(hsotg) == DWC2_PHY_TYPE_PARAM_FS
+			? DWC2_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ
+			: DWC2_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ;
+		dev_dbg(hsotg->dev, "Setting host_ls_low_power_phy_clk to %d\n",
+			val);
+		retval = -EINVAL;
+	}
+
+	hsotg->core_params->host_ls_low_power_phy_clk = val;
+	return retval;
+}
+
+int dwc2_set_param_phy_ulpi_ddr(struct dwc2_hsotg *hsotg, int val)
+{
+	int retval = 0;
+
+	if (DWC2_PARAM_TEST(val, 0, 1)) {
+		if (val >= 0) {
+			dev_err(hsotg->dev, "Wrong value for phy_ulpi_ddr\n");
+			dev_err(hsotg->dev, "phy_upli_ddr must be 0 or 1\n");
+		}
+		val = 0;
+		dev_dbg(hsotg->dev, "Setting phy_upli_ddr to %d\n", val);
+		retval = -EINVAL;
+	}
+
+	hsotg->core_params->phy_ulpi_ddr = val;
+	return retval;
+}
+
+int dwc2_set_param_phy_ulpi_ext_vbus(struct dwc2_hsotg *hsotg, int val)
+{
+	int retval = 0;
+
+	if (DWC2_PARAM_TEST(val, 0, 1)) {
+		if (val >= 0) {
+			dev_err(hsotg->dev,
+				"Wrong value for phy_ulpi_ext_vbus\n");
+			dev_err(hsotg->dev,
+				"phy_ulpi_ext_vbus must be 0 or 1\n");
+		}
+		val = 0;
+		dev_dbg(hsotg->dev, "Setting phy_ulpi_ext_vbus to %d\n", val);
+		retval = -EINVAL;
+	}
+
+	hsotg->core_params->phy_ulpi_ext_vbus = val;
+	return retval;
+}
+
+int dwc2_set_param_phy_utmi_width(struct dwc2_hsotg *hsotg, int val)
+{
+	int retval = 0;
+
+	if (DWC2_PARAM_TEST(val, 8, 8) && DWC2_PARAM_TEST(val, 16, 16)) {
+		if (val >= 0) {
+			dev_err(hsotg->dev, "Wrong value for phy_utmi_width\n");
+			dev_err(hsotg->dev, "phy_utmi_width must be 8 or 16\n");
+		}
+		val = 8;
+		dev_dbg(hsotg->dev, "Setting phy_utmi_width to %d\n", val);
+		retval = -EINVAL;
+	}
+
+	hsotg->core_params->phy_utmi_width = val;
+	return retval;
+}
+
+int dwc2_set_param_ulpi_fs_ls(struct dwc2_hsotg *hsotg, int val)
+{
+	int retval = 0;
+
+	if (DWC2_PARAM_TEST(val, 0, 1)) {
+		if (val >= 0) {
+			dev_err(hsotg->dev, "Wrong value for ulpi_fs_ls\n");
+			dev_err(hsotg->dev, "ulpi_fs_ls must be 0 or 1\n");
+		}
+		val = 0;
+		dev_dbg(hsotg->dev, "Setting ulpi_fs_ls to %d\n", val);
+		retval = -EINVAL;
+	}
+
+	hsotg->core_params->ulpi_fs_ls = val;
+	return retval;
+}
+
+int dwc2_set_param_ts_dline(struct dwc2_hsotg *hsotg, int val)
+{
+	int retval = 0;
+
+	if (DWC2_PARAM_TEST(val, 0, 1)) {
+		if (val >= 0) {
+			dev_err(hsotg->dev, "Wrong value for ts_dline\n");
+			dev_err(hsotg->dev, "ts_dline must be 0 or 1\n");
+		}
+		val = 0;
+		dev_dbg(hsotg->dev, "Setting ts_dline to %d\n", val);
+		retval = -EINVAL;
+	}
+
+	hsotg->core_params->ts_dline = val;
+	return retval;
+}
+
+int dwc2_set_param_i2c_enable(struct dwc2_hsotg *hsotg, int val)
+{
+#ifndef NO_FS_PHY_HW_CHECKS
+	int valid = 1;
+#endif
+	int retval = 0;
+
+	if (DWC2_PARAM_TEST(val, 0, 1)) {
+		if (val >= 0) {
+			dev_err(hsotg->dev, "Wrong value for i2c_enable\n");
+			dev_err(hsotg->dev, "i2c_enable must be 0 or 1\n");
+		}
+
+#ifndef NO_FS_PHY_HW_CHECKS
+		valid = 0;
+#else
+		val = 0;
+		dev_dbg(hsotg->dev, "Setting i2c_enable to %d\n", val);
+		retval = -EINVAL;
+#endif
+	}
+
+#ifndef NO_FS_PHY_HW_CHECKS
+	if (val == 1 && !(hsotg->hwcfg3 & GHWCFG3_I2C))
+		valid = 0;
+
+	if (!valid) {
+		if (val >= 0)
+			dev_err(hsotg->dev,
+				"%d invalid for i2c_enable. Check HW configuration.\n",
+				val);
+		val = !!(hsotg->hwcfg3 & GHWCFG3_I2C);
+		dev_dbg(hsotg->dev, "Setting i2c_enable to %d\n", val);
+		retval = -EINVAL;
+	}
+#endif
+
+	hsotg->core_params->i2c_enable = val;
+	return retval;
+}
+
+int dwc2_set_param_en_multiple_tx_fifo(struct dwc2_hsotg *hsotg, int val)
+{
+	int valid = 1;
+	int retval = 0;
+
+	if (DWC2_PARAM_TEST(val, 0, 1)) {
+		if (val >= 0) {
+			dev_err(hsotg->dev,
+				"Wrong value for en_multiple_tx_fifo,\n");
+			dev_err(hsotg->dev,
+				"en_multiple_tx_fifo must be 0 or 1\n");
+		}
+		valid = 0;
+	}
+
+	if (val == 1 && !(hsotg->hwcfg4 & GHWCFG4_DED_FIFO_EN))
+		valid = 0;
+
+	if (!valid) {
+		if (val >= 0)
+			dev_err(hsotg->dev,
+				"%d invalid for parameter en_multiple_tx_fifo. Check HW configuration.\n",
+				val);
+		val = !!(hsotg->hwcfg4 & GHWCFG4_DED_FIFO_EN);
+		dev_dbg(hsotg->dev, "Setting en_multiple_tx_fifo to %d\n", val);
+		retval = -EINVAL;
+	}
+
+	hsotg->core_params->en_multiple_tx_fifo = val;
+	return retval;
+}
+
+int dwc2_set_param_reload_ctl(struct dwc2_hsotg *hsotg, int val)
+{
+	int valid = 1;
+	int retval = 0;
+
+	if (DWC2_PARAM_TEST(val, 0, 1)) {
+		if (val >= 0) {
+			dev_err(hsotg->dev,
+				"'%d' invalid for parameter reload_ctl\n", val);
+			dev_err(hsotg->dev, "reload_ctl must be 0 or 1\n");
+		}
+		valid = 0;
+	}
+
+	if (val == 1 && hsotg->snpsid < DWC2_CORE_REV_2_92a)
+		valid = 0;
+
+	if (!valid) {
+		if (val >= 0)
+			dev_err(hsotg->dev,
+				"%d invalid for parameter reload_ctl. Check HW configuration.\n",
+				val);
+		val = hsotg->snpsid >= DWC2_CORE_REV_2_92a;
+		dev_dbg(hsotg->dev, "Setting reload_ctl to %d\n", val);
+		retval = -EINVAL;
+	}
+
+	hsotg->core_params->reload_ctl = val;
+	return retval;
+}
+
+int dwc2_set_param_ahb_single(struct dwc2_hsotg *hsotg, int val)
+{
+	int valid = 1;
+	int retval = 0;
+
+	if (DWC2_PARAM_TEST(val, 0, 1)) {
+		if (val >= 0) {
+			dev_err(hsotg->dev,
+				"'%d' invalid for parameter ahb_single\n", val);
+			dev_err(hsotg->dev, "ahb_single must be 0 or 1\n");
+		}
+		valid = 0;
+	}
+
+	if (val > 0 && hsotg->snpsid < DWC2_CORE_REV_2_94a)
+		valid = 0;
+
+	if (!valid) {
+		if (val >= 0)
+			dev_err(hsotg->dev,
+				"%d invalid for parameter ahb_single. Check HW configuration.\n",
+				val);
+		val = 0;
+		dev_dbg(hsotg->dev, "Setting ahb_single to %d\n", val);
+		retval = -EINVAL;
+	}
+
+	hsotg->core_params->ahb_single = val;
+	return retval;
+}
+
+int dwc2_set_param_otg_ver(struct dwc2_hsotg *hsotg, int val)
+{
+	int retval = 0;
+
+	if (DWC2_PARAM_TEST(val, 0, 1)) {
+		if (val >= 0) {
+			dev_err(hsotg->dev,
+				"'%d' invalid for parameter otg_ver\n", val);
+			dev_err(hsotg->dev,
+				"otg_ver must be 0 (for OTG 1.3 support) or 1 (for OTG 2.0 support)\n");
+		}
+		val = 0;
+		dev_dbg(hsotg->dev, "Setting otg_ver to %d\n", val);
+		retval = -EINVAL;
+	}
+
+	hsotg->core_params->otg_ver = val;
+	return retval;
+}
+
+/*
+ * This function is called during module intialization to pass module parameters
+ * for the DWC_otg core. It returns non-0 if any parameters are invalid.
+ */
+int dwc2_set_parameters(struct dwc2_hsotg *hsotg,
+			struct dwc2_core_params *params)
+{
+	int retval = 0;
+
+	dev_dbg(hsotg->dev, "%s()\n", __func__);
+
+	retval |= dwc2_set_param_otg_cap(hsotg, params->otg_cap);
+	retval |= dwc2_set_param_dma_enable(hsotg, params->dma_enable);
+	retval |= dwc2_set_param_dma_desc_enable(hsotg,
+						 params->dma_desc_enable);
+	retval |= dwc2_set_param_host_support_fs_ls_low_power(hsotg,
+			params->host_support_fs_ls_low_power);
+	retval |= dwc2_set_param_enable_dynamic_fifo(hsotg,
+			params->enable_dynamic_fifo);
+	retval |= dwc2_set_param_host_rx_fifo_size(hsotg,
+			params->host_rx_fifo_size);
+	retval |= dwc2_set_param_host_nperio_tx_fifo_size(hsotg,
+			params->host_nperio_tx_fifo_size);
+	retval |= dwc2_set_param_host_perio_tx_fifo_size(hsotg,
+			params->host_perio_tx_fifo_size);
+	retval |= dwc2_set_param_max_transfer_size(hsotg,
+			params->max_transfer_size);
+	retval |= dwc2_set_param_max_packet_count(hsotg,
+			params->max_packet_count);
+	retval |= dwc2_set_param_host_channels(hsotg, params->host_channels);
+	retval |= dwc2_set_param_phy_type(hsotg, params->phy_type);
+	retval |= dwc2_set_param_speed(hsotg, params->speed);
+	retval |= dwc2_set_param_host_ls_low_power_phy_clk(hsotg,
+			params->host_ls_low_power_phy_clk);
+	retval |= dwc2_set_param_phy_ulpi_ddr(hsotg, params->phy_ulpi_ddr);
+	retval |= dwc2_set_param_phy_ulpi_ext_vbus(hsotg,
+			params->phy_ulpi_ext_vbus);
+	retval |= dwc2_set_param_phy_utmi_width(hsotg, params->phy_utmi_width);
+	retval |= dwc2_set_param_ulpi_fs_ls(hsotg, params->ulpi_fs_ls);
+	retval |= dwc2_set_param_ts_dline(hsotg, params->ts_dline);
+	retval |= dwc2_set_param_i2c_enable(hsotg, params->i2c_enable);
+	retval |= dwc2_set_param_en_multiple_tx_fifo(hsotg,
+			params->en_multiple_tx_fifo);
+	retval |= dwc2_set_param_reload_ctl(hsotg, params->reload_ctl);
+	retval |= dwc2_set_param_ahb_single(hsotg, params->ahb_single);
+	retval |= dwc2_set_param_otg_ver(hsotg, params->otg_ver);
+
+	return retval;
+}
+
+u16 dwc2_get_otg_version(struct dwc2_hsotg *hsotg)
+{
+	return (u16)(hsotg->core_params->otg_ver == 1 ? 0x0200 : 0x0103);
+}
+
+int dwc2_check_core_status(struct dwc2_hsotg *hsotg)
+{
+	if (readl(hsotg->regs + GSNPSID) == 0xffffffff)
+		return -1;
+	else
+		return 0;
+}
+
+/**
+ * dwc2_enable_global_interrupts() - Enables the controller's Global
+ * Interrupt in the AHB Config register
+ *
+ * @hsotg: Programming view of DWC_otg controller
+ */
+void dwc2_enable_global_interrupts(struct dwc2_hsotg *hsotg)
+{
+	u32 ahbcfg = readl(hsotg->regs + GAHBCFG);
+
+	ahbcfg |= GAHBCFG_GLBL_INTR_EN;
+	writel(ahbcfg, hsotg->regs + GAHBCFG);
+}
+
+/**
+ * dwc2_disable_global_interrupts() - Disables the controller's Global
+ * Interrupt in the AHB Config register
+ *
+ * @hsotg: Programming view of DWC_otg controller
+ */
+void dwc2_disable_global_interrupts(struct dwc2_hsotg *hsotg)
+{
+	u32 ahbcfg = readl(hsotg->regs + GAHBCFG);
+
+	ahbcfg &= ~GAHBCFG_GLBL_INTR_EN;
+	writel(ahbcfg, hsotg->regs + GAHBCFG);
+}
+
+MODULE_DESCRIPTION("DESIGNWARE HS OTG Core");
+MODULE_AUTHOR("Synopsys, Inc.");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/staging/dwc2/core.h b/drivers/staging/dwc2/core.h
new file mode 100644
index 0000000..f8ee04b
--- /dev/null
+++ b/drivers/staging/dwc2/core.h
@@ -0,0 +1,658 @@
+/*
+ * core.h - DesignWare HS OTG Controller common declarations
+ *
+ * Copyright (C) 2004-2013 Synopsys, Inc.
+ *
+ * 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, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 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 names of the above-listed copyright holders may not 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 the License, or (at your option) any
+ * later version.
+ *
+ * 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 __DWC2_CORE_H__
+#define __DWC2_CORE_H__
+
+#include <linux/usb/phy.h>
+#include "hw.h"
+
+#ifdef DWC2_LOG_WRITES
+static inline void do_write(u32 value, void *addr)
+{
+	writel(value, addr);
+	pr_info("INFO:: wrote %08x to %p\n", value, addr);
+}
+
+#undef writel
+#define writel(v, a)	do_write(v, a)
+#endif
+
+/* Maximum number of Endpoints/HostChannels */
+#define MAX_EPS_CHANNELS	16
+
+struct dwc2_hsotg;
+struct dwc2_host_chan;
+
+/* Device States */
+enum dwc2_lx_state {
+	DWC2_L0,	/* On state */
+	DWC2_L1,	/* LPM sleep state */
+	DWC2_L2,	/* USB suspend state */
+	DWC2_L3,	/* Off state */
+};
+
+/**
+ * struct dwc2_core_params - Parameters for configuring the core
+ *
+ * @otg_cap:            Specifies the OTG capabilities. The driver will
+ *                      automatically detect the value for this parameter if
+ *                      none is specified.
+ *                       0 - HNP and SRP capable (default)
+ *                       1 - SRP Only capable
+ *                       2 - No HNP/SRP capable
+ * @dma_enable:         Specifies whether to use slave or DMA mode for accessing
+ *                      the data FIFOs. The driver will automatically detect the
+ *                      value for this parameter if none is specified.
+ *                       0 - Slave
+ *                       1 - DMA (default, if available)
+ * @dma_desc_enable:    When DMA mode is enabled, specifies whether to use
+ *                      address DMA mode or descriptor DMA mode for accessing
+ *                      the data FIFOs. The driver will automatically detect the
+ *                      value for this if none is specified.
+ *                       0 - Address DMA
+ *                       1 - Descriptor DMA (default, if available)
+ * @speed:              Specifies the maximum speed of operation in host and
+ *                      device mode. The actual speed depends on the speed of
+ *                      the attached device and the value of phy_type.
+ *                       0 - High Speed (default)
+ *                       1 - Full Speed
+ * @host_support_fs_ls_low_power: Specifies whether low power mode is supported
+ *                      when attached to a Full Speed or Low Speed device in
+ *                      host mode.
+ *                       0 - Don't support low power mode (default)
+ *                       1 - Support low power mode
+ * @host_ls_low_power_phy_clk: Specifies the PHY clock rate in low power mode
+ *                      when connected to a Low Speed device in host mode. This
+ *                      parameter is applicable only if
+ *                      host_support_fs_ls_low_power is enabled. If phy_type is
+ *                      set to FS then defaults to 6 MHZ otherwise 48 MHZ.
+ *                       0 - 48 MHz
+ *                       1 - 6 MHz
+ * @enable_dynamic_fifo: 0 - Use coreConsultant-specified FIFO size parameters
+ *                       1 - Allow dynamic FIFO sizing (default)
+ * @host_rx_fifo_size:  Number of 4-byte words in the Rx FIFO in host mode when
+ *                      dynamic FIFO sizing is enabled
+ *                       16 to 32768 (default 1024)
+ * @host_nperio_tx_fifo_size: Number of 4-byte words in the non-periodic Tx FIFO
+ *                      in host mode when dynamic FIFO sizing is enabled
+ *                       16 to 32768 (default 1024)
+ * @host_perio_tx_fifo_size: Number of 4-byte words in the periodic Tx FIFO in
+ *                      host mode when dynamic FIFO sizing is enabled
+ *                       16 to 32768 (default 1024)
+ * @max_transfer_size:  The maximum transfer size supported, in bytes
+ *                       2047 to 65,535 (default 65,535)
+ * @max_packet_count:   The maximum number of packets in a transfer
+ *                       15 to 511 (default 511)
+ * @host_channels:      The number of host channel registers to use
+ *                       1 to 16 (default 12)
+ * @phy_type:           Specifies the type of PHY interface to use. By default,
+ *                      the driver will automatically detect the phy_type.
+ * @phy_utmi_width:     Specifies the UTMI+ Data Width (in bits). This parameter
+ *                      is applicable for a phy_type of UTMI+ or ULPI. (For a
+ *                      ULPI phy_type, this parameter indicates the data width
+ *                      between the MAC and the ULPI Wrapper.) Also, this
+ *                      parameter is applicable only if the OTG_HSPHY_WIDTH cC
+ *                      parameter was set to "8 and 16 bits", meaning that the
+ *                      core has been configured to work at either data path
+ *                      width.
+ *                       8 or 16 (default 16)
+ * @phy_ulpi_ddr:       Specifies whether the ULPI operates at double or single
+ *                      data rate. This parameter is only applicable if phy_type
+ *                      is ULPI.
+ *                       0 - single data rate ULPI interface with 8 bit wide
+ *                           data bus (default)
+ *                       1 - double data rate ULPI interface with 4 bit wide
+ *                           data bus
+ * @phy_ulpi_ext_vbus:  For a ULPI phy, specifies whether to use the internal or
+ *                      external supply to drive the VBus
+ * @i2c_enable:         Specifies whether to use the I2Cinterface for a full
+ *                      speed PHY. This parameter is only applicable if phy_type
+ *                      is FS.
+ *                       0 - No (default)
+ *                       1 - Yes
+ * @ulpi_fs_ls:         True to make ULPI phy operate in FS/LS mode only
+ * @ts_dline:           True to enable Term Select Dline pulsing
+ * @en_multiple_tx_fifo: Specifies whether dedicated per-endpoint transmit FIFOs
+ *                      are enabled
+ * @reload_ctl:         True to allow dynamic reloading of HFIR register during
+ *                      runtime
+ * @ahb_single:         This bit enables SINGLE transfers for remainder data in
+ *                      a transfer for DMA mode of operation.
+ *                       0 - remainder data will be sent using INCR burst size
+ *                       1 - remainder data will be sent using SINGLE burst size
+ * @otg_ver:            OTG version supported
+ *                       0 - 1.3
+ *                       1 - 2.0
+ *
+ * The following parameters may be specified when starting the module. These
+ * parameters define how the DWC_otg controller should be configured.
+ */
+struct dwc2_core_params {
+	int otg_cap;
+	int otg_ver;
+	int dma_enable;
+	int dma_desc_enable;
+	int speed;
+	int enable_dynamic_fifo;
+	int en_multiple_tx_fifo;
+	int host_rx_fifo_size;
+	int host_nperio_tx_fifo_size;
+	int host_perio_tx_fifo_size;
+	int max_transfer_size;
+	int max_packet_count;
+	int host_channels;
+	int phy_type;
+	int phy_utmi_width;
+	int phy_ulpi_ddr;
+	int phy_ulpi_ext_vbus;
+	int i2c_enable;
+	int ulpi_fs_ls;
+	int host_support_fs_ls_low_power;
+	int host_ls_low_power_phy_clk;
+	int ts_dline;
+	int reload_ctl;
+	int ahb_single;
+};
+
+/**
+ * struct dwc2_hsotg - Holds the state of the driver, including the non-periodic
+ * and periodic schedules
+ *
+ * @dev:                The struct device pointer
+ * @regs:		Pointer to controller regs
+ * @core_params:        Parameters that define how the core should be configured
+ * @hwcfg1:             Hardware Configuration - stored here for convenience
+ * @hwcfg2:             Hardware Configuration - stored here for convenience
+ * @hwcfg3:             Hardware Configuration - stored here for convenience
+ * @hwcfg4:             Hardware Configuration - stored here for convenience
+ * @hptxfsiz:           Hardware Configuration - stored here for convenience
+ * @snpsid:             Value from SNPSID register
+ * @total_fifo_size:    Total internal RAM for FIFOs (bytes)
+ * @rx_fifo_size:       Size of Rx FIFO (bytes)
+ * @nperio_tx_fifo_size: Size of Non-periodic Tx FIFO (Bytes)
+ * @op_state:           The operational State, during transitions (a_host=>
+ *                      a_peripheral and b_device=>b_host) this may not match
+ *                      the core, but allows the software to determine
+ *                      transitions
+ * @queuing_high_bandwidth: True if multiple packets of a high-bandwidth
+ *                      transfer are in process of being queued
+ * @srp_success:        Stores status of SRP request in the case of a FS PHY
+ *                      with an I2C interface
+ * @wq_otg:             Workqueue object used for handling of some interrupts
+ * @wf_otg:             Work object for handling Connector ID Status Change
+ *                      interrupt
+ * @wkp_timer:          Timer object for handling Wakeup Detected interrupt
+ * @lx_state:           Lx state of connected device
+ * @flags:              Flags for handling root port state changes
+ * @non_periodic_sched_inactive: Inactive QHs in the non-periodic schedule.
+ *                      Transfers associated with these QHs are not currently
+ *                      assigned to a host channel.
+ * @non_periodic_sched_active: Active QHs in the non-periodic schedule.
+ *                      Transfers associated with these QHs are currently
+ *                      assigned to a host channel.
+ * @non_periodic_qh_ptr: Pointer to next QH to process in the active
+ *                      non-periodic schedule
+ * @periodic_sched_inactive: Inactive QHs in the periodic schedule. This is a
+ *                      list of QHs for periodic transfers that are _not_
+ *                      scheduled for the next frame. Each QH in the list has an
+ *                      interval counter that determines when it needs to be
+ *                      scheduled for execution. This scheduling mechanism
+ *                      allows only a simple calculation for periodic bandwidth
+ *                      used (i.e. must assume that all periodic transfers may
+ *                      need to execute in the same frame). However, it greatly
+ *                      simplifies scheduling and should be sufficient for the
+ *                      vast majority of OTG hosts, which need to connect to a
+ *                      small number of peripherals at one time. Items move from
+ *                      this list to periodic_sched_ready when the QH interval
+ *                      counter is 0 at SOF.
+ * @periodic_sched_ready:  List of periodic QHs that are ready for execution in
+ *                      the next frame, but have not yet been assigned to host
+ *                      channels. Items move from this list to
+ *                      periodic_sched_assigned as host channels become
+ *                      available during the current frame.
+ * @periodic_sched_assigned: List of periodic QHs to be executed in the next
+ *                      frame that are assigned to host channels. Items move
+ *                      from this list to periodic_sched_queued as the
+ *                      transactions for the QH are queued to the DWC_otg
+ *                      controller.
+ * @periodic_sched_queued: List of periodic QHs that have been queued for
+ *                      execution. Items move from this list to either
+ *                      periodic_sched_inactive or periodic_sched_ready when the
+ *                      channel associated with the transfer is released. If the
+ *                      interval for the QH is 1, the item moves to
+ *                      periodic_sched_ready because it must be rescheduled for
+ *                      the next frame. Otherwise, the item moves to
+ *                      periodic_sched_inactive.
+ * @periodic_usecs:     Total bandwidth claimed so far for periodic transfers.
+ *                      This value is in microseconds per (micro)frame. The
+ *                      assumption is that all periodic transfers may occur in
+ *                      the same (micro)frame.
+ * @frame_number:       Frame number read from the core at SOF. The value ranges
+ *                      from 0 to HFNUM_MAX_FRNUM.
+ * @periodic_qh_count:  Count of periodic QHs, if using several eps. Used for
+ *                      SOF enable/disable.
+ * @free_hc_list:       Free host channels in the controller. This is a list of
+ *                      struct dwc2_host_chan items.
+ * @periodic_channels:  Number of host channels assigned to periodic transfers.
+ *                      Currently assuming that there is a dedicated host
+ *                      channel for each periodic transaction and at least one
+ *                      host channel is available for non-periodic transactions.
+ * @non_periodic_channels: Number of host channels assigned to non-periodic
+ *                      transfers
+ * @hc_ptr_array:       Array of pointers to the host channel descriptors.
+ *                      Allows accessing a host channel descriptor given the
+ *                      host channel number. This is useful in interrupt
+ *                      handlers.
+ * @status_buf:         Buffer used for data received during the status phase of
+ *                      a control transfer.
+ * @status_buf_dma:     DMA address for status_buf
+ * @start_work:         Delayed work for handling host A-cable connection
+ * @reset_work:         Delayed work for handling a port reset
+ * @lock:               Spinlock that protects all the driver data structures
+ * @priv:               Stores a pointer to the struct usb_hcd
+ * @otg_port:           OTG port number
+ * @frame_list:         Frame list
+ * @frame_list_dma:     Frame list DMA address
+ */
+struct dwc2_hsotg {
+	struct device *dev;
+	void __iomem *regs;
+	struct dwc2_core_params *core_params;
+	u32 hwcfg1;
+	u32 hwcfg2;
+	u32 hwcfg3;
+	u32 hwcfg4;
+	u32 hptxfsiz;
+	u32 snpsid;
+	u16 total_fifo_size;
+	u16 rx_fifo_size;
+	u16 nperio_tx_fifo_size;
+	enum usb_otg_state op_state;
+
+	unsigned int queuing_high_bandwidth:1;
+	unsigned int srp_success:1;
+
+	struct workqueue_struct *wq_otg;
+	struct work_struct wf_otg;
+	struct timer_list wkp_timer;
+	enum dwc2_lx_state lx_state;
+
+	union dwc2_hcd_internal_flags {
+		u32 d32;
+		struct {
+			unsigned port_connect_status_change:1;
+			unsigned port_connect_status:1;
+			unsigned port_reset_change:1;
+			unsigned port_enable_change:1;
+			unsigned port_suspend_change:1;
+			unsigned port_over_current_change:1;
+			unsigned port_l1_change:1;
+			unsigned reserved:26;
+		} b;
+	} flags;
+
+	struct list_head non_periodic_sched_inactive;
+	struct list_head non_periodic_sched_active;
+	struct list_head *non_periodic_qh_ptr;
+	struct list_head periodic_sched_inactive;
+	struct list_head periodic_sched_ready;
+	struct list_head periodic_sched_assigned;
+	struct list_head periodic_sched_queued;
+	u16 periodic_usecs;
+	u16 frame_number;
+	u16 periodic_qh_count;
+
+#ifdef CONFIG_USB_DWC2_TRACK_MISSED_SOFS
+#define FRAME_NUM_ARRAY_SIZE 1000
+	u16 last_frame_num;
+	u16 *frame_num_array;
+	u16 *last_frame_num_array;
+	int frame_num_idx;
+	int dumped_frame_num_array;
+#endif
+
+	struct list_head free_hc_list;
+	int periodic_channels;
+	int non_periodic_channels;
+	struct dwc2_host_chan *hc_ptr_array[MAX_EPS_CHANNELS];
+	u8 *status_buf;
+	dma_addr_t status_buf_dma;
+#define DWC2_HCD_STATUS_BUF_SIZE 64
+
+	struct delayed_work start_work;
+	struct delayed_work reset_work;
+	spinlock_t lock;
+	void *priv;
+	u8 otg_port;
+	u32 *frame_list;
+	dma_addr_t frame_list_dma;
+
+	/* DWC OTG HW Release versions */
+#define DWC2_CORE_REV_2_71a	0x4f54271a
+#define DWC2_CORE_REV_2_90a	0x4f54290a
+#define DWC2_CORE_REV_2_92a	0x4f54292a
+#define DWC2_CORE_REV_2_94a	0x4f54294a
+#define DWC2_CORE_REV_3_00a	0x4f54300a
+
+#ifdef DEBUG
+	u32 frrem_samples;
+	u64 frrem_accum;
+
+	u32 hfnum_7_samples_a;
+	u64 hfnum_7_frrem_accum_a;
+	u32 hfnum_0_samples_a;
+	u64 hfnum_0_frrem_accum_a;
+	u32 hfnum_other_samples_a;
+	u64 hfnum_other_frrem_accum_a;
+
+	u32 hfnum_7_samples_b;
+	u64 hfnum_7_frrem_accum_b;
+	u32 hfnum_0_samples_b;
+	u64 hfnum_0_frrem_accum_b;
+	u32 hfnum_other_samples_b;
+	u64 hfnum_other_frrem_accum_b;
+#endif
+};
+
+/* Reasons for halting a host channel */
+enum dwc2_halt_status {
+	DWC2_HC_XFER_NO_HALT_STATUS,
+	DWC2_HC_XFER_COMPLETE,
+	DWC2_HC_XFER_URB_COMPLETE,
+	DWC2_HC_XFER_ACK,
+	DWC2_HC_XFER_NAK,
+	DWC2_HC_XFER_NYET,
+	DWC2_HC_XFER_STALL,
+	DWC2_HC_XFER_XACT_ERR,
+	DWC2_HC_XFER_FRAME_OVERRUN,
+	DWC2_HC_XFER_BABBLE_ERR,
+	DWC2_HC_XFER_DATA_TOGGLE_ERR,
+	DWC2_HC_XFER_AHB_ERR,
+	DWC2_HC_XFER_PERIODIC_INCOMPLETE,
+	DWC2_HC_XFER_URB_DEQUEUE,
+};
+
+/*
+ * The following functions support initialization of the core driver component
+ * and the DWC_otg controller
+ */
+extern void dwc2_core_host_init(struct dwc2_hsotg *hsotg);
+
+/*
+ * Host core Functions.
+ * The following functions support managing the DWC_otg controller in host
+ * mode.
+ */
+extern void dwc2_hc_init(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan);
+extern void dwc2_hc_halt(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan,
+			 enum dwc2_halt_status halt_status);
+extern void dwc2_hc_cleanup(struct dwc2_hsotg *hsotg,
+			    struct dwc2_host_chan *chan);
+extern void dwc2_hc_start_transfer(struct dwc2_hsotg *hsotg,
+				   struct dwc2_host_chan *chan);
+extern void dwc2_hc_start_transfer_ddma(struct dwc2_hsotg *hsotg,
+					struct dwc2_host_chan *chan);
+extern int dwc2_hc_continue_transfer(struct dwc2_hsotg *hsotg,
+				     struct dwc2_host_chan *chan);
+extern void dwc2_hc_do_ping(struct dwc2_hsotg *hsotg,
+			    struct dwc2_host_chan *chan);
+extern void dwc2_enable_host_interrupts(struct dwc2_hsotg *hsotg);
+extern void dwc2_disable_host_interrupts(struct dwc2_hsotg *hsotg);
+
+extern u32 dwc2_calc_frame_interval(struct dwc2_hsotg *hsotg);
+extern int dwc2_check_core_status(struct dwc2_hsotg *hsotg);
+
+/*
+ * Common core Functions.
+ * The following functions support managing the DWC_otg controller in either
+ * device or host mode.
+ */
+extern void dwc2_read_packet(struct dwc2_hsotg *hsotg, u8 *dest, u16 bytes);
+extern void dwc2_flush_tx_fifo(struct dwc2_hsotg *hsotg, const int num);
+extern void dwc2_flush_rx_fifo(struct dwc2_hsotg *hsotg);
+
+extern int dwc2_core_init(struct dwc2_hsotg *hsotg, bool select_phy);
+extern void dwc2_enable_global_interrupts(struct dwc2_hsotg *hcd);
+extern void dwc2_disable_global_interrupts(struct dwc2_hsotg *hcd);
+
+/* This function should be called on every hardware interrupt. */
+extern irqreturn_t dwc2_handle_common_intr(int irq, void *dev);
+
+/* OTG Core Parameters */
+
+/*
+ * Specifies the OTG capabilities. The driver will automatically
+ * detect the value for this parameter if none is specified.
+ * 0 - HNP and SRP capable (default)
+ * 1 - SRP Only capable
+ * 2 - No HNP/SRP capable
+ */
+extern int dwc2_set_param_otg_cap(struct dwc2_hsotg *hsotg, int val);
+#define DWC2_CAP_PARAM_HNP_SRP_CAPABLE		0
+#define DWC2_CAP_PARAM_SRP_ONLY_CAPABLE		1
+#define DWC2_CAP_PARAM_NO_HNP_SRP_CAPABLE	2
+
+/*
+ * Specifies whether to use slave or DMA mode for accessing the data
+ * FIFOs. The driver will automatically detect the value for this
+ * parameter if none is specified.
+ * 0 - Slave
+ * 1 - DMA (default, if available)
+ */
+extern int dwc2_set_param_dma_enable(struct dwc2_hsotg *hsotg, int val);
+
+/*
+ * When DMA mode is enabled specifies whether to use
+ * address DMA or DMA Descritor mode for accessing the data
+ * FIFOs in device mode. The driver will automatically detect
+ * the value for this parameter if none is specified.
+ * 0 - address DMA
+ * 1 - DMA Descriptor(default, if available)
+ */
+extern int dwc2_set_param_dma_desc_enable(struct dwc2_hsotg *hsotg, int val);
+
+/*
+ * Specifies the maximum speed of operation in host and device mode.
+ * The actual speed depends on the speed of the attached device and
+ * the value of phy_type. The actual speed depends on the speed of the
+ * attached device.
+ * 0 - High Speed (default)
+ * 1 - Full Speed
+ */
+extern int dwc2_set_param_speed(struct dwc2_hsotg *hsotg, int val);
+#define DWC2_SPEED_PARAM_HIGH	0
+#define DWC2_SPEED_PARAM_FULL	1
+
+/*
+ * Specifies whether low power mode is supported when attached
+ * to a Full Speed or Low Speed device in host mode.
+ *
+ * 0 - Don't support low power mode (default)
+ * 1 - Support low power mode
+ */
+extern int dwc2_set_param_host_support_fs_ls_low_power(struct dwc2_hsotg *hsotg,
+						       int val);
+
+/*
+ * Specifies the PHY clock rate in low power mode when connected to a
+ * Low Speed device in host mode. This parameter is applicable only if
+ * HOST_SUPPORT_FS_LS_LOW_POWER is enabled. If PHY_TYPE is set to FS
+ * then defaults to 6 MHZ otherwise 48 MHZ.
+ *
+ * 0 - 48 MHz
+ * 1 - 6 MHz
+ */
+extern int dwc2_set_param_host_ls_low_power_phy_clk(struct dwc2_hsotg *hsotg,
+						    int val);
+#define DWC2_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ	0
+#define DWC2_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ	1
+
+/*
+ * 0 - Use cC FIFO size parameters
+ * 1 - Allow dynamic FIFO sizing (default)
+ */
+extern int dwc2_set_param_enable_dynamic_fifo(struct dwc2_hsotg *hsotg,
+					      int val);
+
+/*
+ * Number of 4-byte words in the Rx FIFO in host mode when dynamic
+ * FIFO sizing is enabled.
+ * 16 to 32768 (default 1024)
+ */
+extern int dwc2_set_param_host_rx_fifo_size(struct dwc2_hsotg *hsotg, int val);
+
+/*
+ * Number of 4-byte words in the non-periodic Tx FIFO in host mode
+ * when Dynamic FIFO sizing is enabled in the core.
+ * 16 to 32768 (default 256)
+ */
+extern int dwc2_set_param_host_nperio_tx_fifo_size(struct dwc2_hsotg *hsotg,
+						   int val);
+
+/*
+ * Number of 4-byte words in the host periodic Tx FIFO when dynamic
+ * FIFO sizing is enabled.
+ * 16 to 32768 (default 256)
+ */
+extern int dwc2_set_param_host_perio_tx_fifo_size(struct dwc2_hsotg *hsotg,
+						  int val);
+
+/*
+ * The maximum transfer size supported in bytes.
+ * 2047 to 65,535  (default 65,535)
+ */
+extern int dwc2_set_param_max_transfer_size(struct dwc2_hsotg *hsotg, int val);
+
+/*
+ * The maximum number of packets in a transfer.
+ * 15 to 511  (default 511)
+ */
+extern int dwc2_set_param_max_packet_count(struct dwc2_hsotg *hsotg, int val);
+
+/*
+ * The number of host channel registers to use.
+ * 1 to 16 (default 11)
+ * Note: The FPGA configuration supports a maximum of 11 host channels.
+ */
+extern int dwc2_set_param_host_channels(struct dwc2_hsotg *hsotg, int val);
+
+/*
+ * Specifies the type of PHY interface to use. By default, the driver
+ * will automatically detect the phy_type.
+ *
+ * 0 - Full Speed PHY
+ * 1 - UTMI+ (default)
+ * 2 - ULPI
+ */
+extern int dwc2_set_param_phy_type(struct dwc2_hsotg *hsotg, int val);
+#define DWC2_PHY_TYPE_PARAM_FS		0
+#define DWC2_PHY_TYPE_PARAM_UTMI	1
+#define DWC2_PHY_TYPE_PARAM_ULPI	2
+
+/*
+ * Specifies the UTMI+ Data Width. This parameter is
+ * applicable for a PHY_TYPE of UTMI+ or ULPI. (For a ULPI
+ * PHY_TYPE, this parameter indicates the data width between
+ * the MAC and the ULPI Wrapper.) Also, this parameter is
+ * applicable only if the OTG_HSPHY_WIDTH cC parameter was set
+ * to "8 and 16 bits", meaning that the core has been
+ * configured to work at either data path width.
+ *
+ * 8 or 16 bits (default 16)
+ */
+extern int dwc2_set_param_phy_utmi_width(struct dwc2_hsotg *hsotg, int val);
+
+/*
+ * Specifies whether the ULPI operates at double or single
+ * data rate. This parameter is only applicable if PHY_TYPE is
+ * ULPI.
+ *
+ * 0 - single data rate ULPI interface with 8 bit wide data
+ * bus (default)
+ * 1 - double data rate ULPI interface with 4 bit wide data
+ * bus
+ */
+extern int dwc2_set_param_phy_ulpi_ddr(struct dwc2_hsotg *hsotg, int val);
+
+/*
+ * Specifies whether to use the internal or external supply to
+ * drive the vbus with a ULPI phy.
+ */
+extern int dwc2_set_param_phy_ulpi_ext_vbus(struct dwc2_hsotg *hsotg, int val);
+#define DWC2_PHY_ULPI_INTERNAL_VBUS	0
+#define DWC2_PHY_ULPI_EXTERNAL_VBUS	1
+
+/*
+ * Specifies whether to use the I2Cinterface for full speed PHY. This
+ * parameter is only applicable if PHY_TYPE is FS.
+ * 0 - No (default)
+ * 1 - Yes
+ */
+extern int dwc2_set_param_i2c_enable(struct dwc2_hsotg *hsotg, int val);
+
+extern int dwc2_set_param_ulpi_fs_ls(struct dwc2_hsotg *hsotg, int val);
+
+extern int dwc2_set_param_ts_dline(struct dwc2_hsotg *hsotg, int val);
+
+/*
+ * Specifies whether dedicated transmit FIFOs are
+ * enabled for non periodic IN endpoints in device mode
+ * 0 - No
+ * 1 - Yes
+ */
+extern int dwc2_set_param_en_multiple_tx_fifo(struct dwc2_hsotg *hsotg,
+					      int val);
+
+extern int dwc2_set_param_reload_ctl(struct dwc2_hsotg *hsotg, int val);
+
+extern int dwc2_set_param_ahb_single(struct dwc2_hsotg *hsotg, int val);
+
+extern int dwc2_set_param_otg_ver(struct dwc2_hsotg *hsotg, int val);
+
+/*
+ * Dump core registers and SPRAM
+ */
+extern void dwc2_dump_dev_registers(struct dwc2_hsotg *hsotg);
+extern void dwc2_dump_host_registers(struct dwc2_hsotg *hsotg);
+extern void dwc2_dump_global_registers(struct dwc2_hsotg *hsotg);
+
+/*
+ * Return OTG version - either 1.3 or 2.0
+ */
+extern u16 dwc2_get_otg_version(struct dwc2_hsotg *hsotg);
+
+#endif /* __DWC2_CORE_H__ */
diff --git a/drivers/staging/dwc2/core_intr.c b/drivers/staging/dwc2/core_intr.c
new file mode 100644
index 0000000..44c0166
--- /dev/null
+++ b/drivers/staging/dwc2/core_intr.c
@@ -0,0 +1,505 @@
+/*
+ * core_intr.c - DesignWare HS OTG Controller common interrupt handling
+ *
+ * Copyright (C) 2004-2013 Synopsys, Inc.
+ *
+ * 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, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 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 names of the above-listed copyright holders may not 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 the License, or (at your option) any
+ * later version.
+ *
+ * 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.
+ */
+
+/*
+ * This file contains the common interrupt handlers
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+
+#include <linux/usb/hcd.h>
+#include <linux/usb/ch11.h>
+
+#include "core.h"
+#include "hcd.h"
+
+static const char *dwc2_op_state_str(struct dwc2_hsotg *hsotg)
+{
+#ifdef DEBUG
+	switch (hsotg->op_state) {
+	case OTG_STATE_A_HOST:
+		return "a_host";
+	case OTG_STATE_A_SUSPEND:
+		return "a_suspend";
+	case OTG_STATE_A_PERIPHERAL:
+		return "a_peripheral";
+	case OTG_STATE_B_PERIPHERAL:
+		return "b_peripheral";
+	case OTG_STATE_B_HOST:
+		return "b_host";
+	default:
+		return "unknown";
+	}
+#else
+	return "";
+#endif
+}
+
+/**
+ * dwc2_handle_mode_mismatch_intr() - Logs a mode mismatch warning message
+ *
+ * @hsotg: Programming view of DWC_otg controller
+ */
+static void dwc2_handle_mode_mismatch_intr(struct dwc2_hsotg *hsotg)
+{
+	dev_warn(hsotg->dev, "Mode Mismatch Interrupt: currently in %s mode\n",
+		 dwc2_is_host_mode(hsotg) ? "Host" : "Device");
+
+	/* Clear interrupt */
+	writel(GINTSTS_MODEMIS, hsotg->regs + GINTSTS);
+}
+
+/**
+ * dwc2_handle_otg_intr() - Handles the OTG Interrupts. It reads the OTG
+ * Interrupt Register (GOTGINT) to determine what interrupt has occurred.
+ *
+ * @hsotg: Programming view of DWC_otg controller
+ */
+static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg)
+{
+	u32 gotgint;
+	u32 gotgctl;
+	u32 gintmsk;
+
+	gotgint = readl(hsotg->regs + GOTGINT);
+	gotgctl = readl(hsotg->regs + GOTGCTL);
+	dev_dbg(hsotg->dev, "++OTG Interrupt gotgint=%0x [%s]\n", gotgint,
+		dwc2_op_state_str(hsotg));
+
+	if (gotgint & GOTGINT_SES_END_DET) {
+		dev_dbg(hsotg->dev,
+			" ++OTG Interrupt: Session End Detected++ (%s)\n",
+			dwc2_op_state_str(hsotg));
+		gotgctl = readl(hsotg->regs + GOTGCTL);
+
+		if (hsotg->op_state == OTG_STATE_B_HOST) {
+			hsotg->op_state = OTG_STATE_B_PERIPHERAL;
+		} else {
+			/*
+			 * If not B_HOST and Device HNP still set, HNP did
+			 * not succeed!
+			 */
+			if (gotgctl & GOTGCTL_DEVHNPEN) {
+				dev_dbg(hsotg->dev, "Session End Detected\n");
+				dev_err(hsotg->dev,
+					"Device Not Connected/Responding!\n");
+			}
+
+			/*
+			 * If Session End Detected the B-Cable has been
+			 * disconnected
+			 */
+			/* Reset to a clean state */
+			hsotg->lx_state = DWC2_L0;
+		}
+
+		gotgctl = readl(hsotg->regs + GOTGCTL);
+		gotgctl &= ~GOTGCTL_DEVHNPEN;
+		writel(gotgctl, hsotg->regs + GOTGCTL);
+	}
+
+	if (gotgint & GOTGINT_SES_REQ_SUC_STS_CHNG) {
+		dev_dbg(hsotg->dev,
+			" ++OTG Interrupt: Session Request Success Status Change++\n");
+		gotgctl = readl(hsotg->regs + GOTGCTL);
+		if (gotgctl & GOTGCTL_SESREQSCS) {
+			if (hsotg->core_params->phy_type ==
+					DWC2_PHY_TYPE_PARAM_FS
+			    && hsotg->core_params->i2c_enable > 0) {
+				hsotg->srp_success = 1;
+			} else {
+				/* Clear Session Request */
+				gotgctl = readl(hsotg->regs + GOTGCTL);
+				gotgctl &= ~GOTGCTL_SESREQ;
+				writel(gotgctl, hsotg->regs + GOTGCTL);
+			}
+		}
+	}
+
+	if (gotgint & GOTGINT_HST_NEG_SUC_STS_CHNG) {
+		/*
+		 * Print statements during the HNP interrupt handling
+		 * can cause it to fail
+		 */
+		gotgctl = readl(hsotg->regs + GOTGCTL);
+		/*
+		 * WA for 3.00a- HW is not setting cur_mode, even sometimes
+		 * this does not help
+		 */
+		if (hsotg->snpsid >= DWC2_CORE_REV_3_00a)
+			udelay(100);
+		if (gotgctl & GOTGCTL_HSTNEGSCS) {
+			if (dwc2_is_host_mode(hsotg)) {
+				hsotg->op_state = OTG_STATE_B_HOST;
+				/*
+				 * Need to disable SOF interrupt immediately.
+				 * When switching from device to host, the PCD
+				 * interrupt handler won't handle the interrupt
+				 * if host mode is already set. The HCD
+				 * interrupt handler won't get called if the
+				 * HCD state is HALT. This means that the
+				 * interrupt does not get handled and Linux
+				 * complains loudly.
+				 */
+				gintmsk = readl(hsotg->regs + GINTMSK);
+				gintmsk &= ~GINTSTS_SOF;
+				writel(gintmsk, hsotg->regs + GINTMSK);
+
+				/*
+				 * Call callback function with spin lock
+				 * released
+				 */
+				spin_unlock(&hsotg->lock);
+
+				/* Initialize the Core for Host mode */
+				dwc2_hcd_start(hsotg);
+				spin_lock(&hsotg->lock);
+				hsotg->op_state = OTG_STATE_B_HOST;
+			}
+		} else {
+			gotgctl = readl(hsotg->regs + GOTGCTL);
+			gotgctl &= ~(GOTGCTL_HNPREQ | GOTGCTL_DEVHNPEN);
+			writel(gotgctl, hsotg->regs + GOTGCTL);
+			dev_dbg(hsotg->dev, "HNP Failed\n");
+			dev_err(hsotg->dev,
+				"Device Not Connected/Responding\n");
+		}
+	}
+
+	if (gotgint & GOTGINT_HST_NEG_DET) {
+		/*
+		 * The disconnect interrupt is set at the same time as
+		 * Host Negotiation Detected. During the mode switch all
+		 * interrupts are cleared so the disconnect interrupt
+		 * handler will not get executed.
+		 */
+		dev_dbg(hsotg->dev,
+			" ++OTG Interrupt: Host Negotiation Detected++ (%s)\n",
+			(dwc2_is_host_mode(hsotg) ? "Host" : "Device"));
+		if (dwc2_is_device_mode(hsotg)) {
+			dev_dbg(hsotg->dev, "a_suspend->a_peripheral (%d)\n",
+				hsotg->op_state);
+			spin_unlock(&hsotg->lock);
+			dwc2_hcd_disconnect(hsotg);
+			spin_lock(&hsotg->lock);
+			hsotg->op_state = OTG_STATE_A_PERIPHERAL;
+		} else {
+			/* Need to disable SOF interrupt immediately */
+			gintmsk = readl(hsotg->regs + GINTMSK);
+			gintmsk &= ~GINTSTS_SOF;
+			writel(gintmsk, hsotg->regs + GINTMSK);
+			spin_unlock(&hsotg->lock);
+			dwc2_hcd_start(hsotg);
+			spin_lock(&hsotg->lock);
+			hsotg->op_state = OTG_STATE_A_HOST;
+		}
+	}
+
+	if (gotgint & GOTGINT_A_DEV_TOUT_CHG)
+		dev_dbg(hsotg->dev,
+			" ++OTG Interrupt: A-Device Timeout Change++\n");
+	if (gotgint & GOTGINT_DBNCE_DONE)
+		dev_dbg(hsotg->dev, " ++OTG Interrupt: Debounce Done++\n");
+
+	/* Clear GOTGINT */
+	writel(gotgint, hsotg->regs + GOTGINT);
+}
+
+/**
+ * dwc2_handle_conn_id_status_change_intr() - Handles the Connector ID Status
+ * Change Interrupt
+ *
+ * @hsotg: Programming view of DWC_otg controller
+ *
+ * Reads the OTG Interrupt Register (GOTCTL) to determine whether this is a
+ * Device to Host Mode transition or a Host to Device Mode transition. This only
+ * occurs when the cable is connected/removed from the PHY connector.
+ */
+static void dwc2_handle_conn_id_status_change_intr(struct dwc2_hsotg *hsotg)
+{
+	u32 gintmsk = readl(hsotg->regs + GINTMSK);
+
+	/* Need to disable SOF interrupt immediately */
+	gintmsk &= ~GINTSTS_SOF;
+	writel(gintmsk, hsotg->regs + GINTMSK);
+
+	dev_dbg(hsotg->dev, " ++Connector ID Status Change Interrupt++  (%s)\n",
+		dwc2_is_host_mode(hsotg) ? "Host" : "Device");
+
+	/*
+	 * Need to schedule a work, as there are possible DELAY function calls.
+	 * Release lock before scheduling workq as it holds spinlock during
+	 * scheduling.
+	 */
+	spin_unlock(&hsotg->lock);
+	queue_work(hsotg->wq_otg, &hsotg->wf_otg);
+	spin_lock(&hsotg->lock);
+
+	/* Clear interrupt */
+	writel(GINTSTS_CONIDSTSCHNG, hsotg->regs + GINTSTS);
+}
+
+/**
+ * dwc2_handle_session_req_intr() - This interrupt indicates that a device is
+ * initiating the Session Request Protocol to request the host to turn on bus
+ * power so a new session can begin
+ *
+ * @hsotg: Programming view of DWC_otg controller
+ *
+ * This handler responds by turning on bus power. If the DWC_otg controller is
+ * in low power mode, this handler brings the controller out of low power mode
+ * before turning on bus power.
+ */
+static void dwc2_handle_session_req_intr(struct dwc2_hsotg *hsotg)
+{
+	dev_dbg(hsotg->dev, "++Session Request Interrupt++\n");
+
+	/* Clear interrupt */
+	writel(GINTSTS_SESSREQINT, hsotg->regs + GINTSTS);
+}
+
+/*
+ * This interrupt indicates that the DWC_otg controller has detected a
+ * resume or remote wakeup sequence. If the DWC_otg controller is in
+ * low power mode, the handler must brings the controller out of low
+ * power mode. The controller automatically begins resume signaling.
+ * The handler schedules a time to stop resume signaling.
+ */
+static void dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg *hsotg)
+{
+	dev_dbg(hsotg->dev, "++Resume or Remote Wakeup Detected Interrupt++\n");
+	dev_dbg(hsotg->dev, "%s lxstate = %d\n", __func__, hsotg->lx_state);
+
+	if (dwc2_is_device_mode(hsotg)) {
+		dev_dbg(hsotg->dev, "DSTS=0x%0x\n", readl(hsotg->regs + DSTS));
+		if (hsotg->lx_state == DWC2_L2) {
+			u32 dctl = readl(hsotg->regs + DCTL);
+
+			/* Clear Remote Wakeup Signaling */
+			dctl &= ~DCTL_RMTWKUPSIG;
+			writel(dctl, hsotg->regs + DCTL);
+		}
+		/* Change to L0 state */
+		hsotg->lx_state = DWC2_L0;
+	} else {
+		if (hsotg->lx_state != DWC2_L1) {
+			u32 pcgcctl = readl(hsotg->regs + PCGCTL);
+
+			/* Restart the Phy Clock */
+			pcgcctl &= ~PCGCTL_STOPPCLK;
+			writel(pcgcctl, hsotg->regs + PCGCTL);
+			mod_timer(&hsotg->wkp_timer,
+				  jiffies + msecs_to_jiffies(71));
+		} else {
+			/* Change to L0 state */
+			hsotg->lx_state = DWC2_L0;
+		}
+	}
+
+	/* Clear interrupt */
+	writel(GINTSTS_WKUPINT, hsotg->regs + GINTSTS);
+}
+
+/*
+ * This interrupt indicates that a device has been disconnected from the
+ * root port
+ */
+static void dwc2_handle_disconnect_intr(struct dwc2_hsotg *hsotg)
+{
+	dev_dbg(hsotg->dev, "++Disconnect Detected Interrupt++ (%s) %s\n",
+		dwc2_is_host_mode(hsotg) ? "Host" : "Device",
+		dwc2_op_state_str(hsotg));
+
+	/* Change to L3 (OFF) state */
+	hsotg->lx_state = DWC2_L3;
+
+	writel(GINTSTS_DISCONNINT, hsotg->regs + GINTSTS);
+}
+
+/*
+ * This interrupt indicates that SUSPEND state has been detected on the USB.
+ *
+ * For HNP the USB Suspend interrupt signals the change from "a_peripheral"
+ * to "a_host".
+ *
+ * When power management is enabled the core will be put in low power mode.
+ */
+static void dwc2_handle_usb_suspend_intr(struct dwc2_hsotg *hsotg)
+{
+	u32 dsts;
+
+	dev_dbg(hsotg->dev, "USB SUSPEND\n");
+
+	if (dwc2_is_device_mode(hsotg)) {
+		/*
+		 * Check the Device status register to determine if the Suspend
+		 * state is active
+		 */
+		dsts = readl(hsotg->regs + DSTS);
+		dev_dbg(hsotg->dev, "DSTS=0x%0x\n", dsts);
+		dev_dbg(hsotg->dev,
+			"DSTS.Suspend Status=%d HWCFG4.Power Optimize=%d\n",
+			!!(dsts & DSTS_SUSPSTS),
+			!!(hsotg->hwcfg4 & GHWCFG4_POWER_OPTIMIZ));
+	} else {
+		if (hsotg->op_state == OTG_STATE_A_PERIPHERAL) {
+			dev_dbg(hsotg->dev, "a_peripheral->a_host\n");
+
+			/* Clear the a_peripheral flag, back to a_host */
+			spin_unlock(&hsotg->lock);
+			dwc2_hcd_start(hsotg);
+			spin_lock(&hsotg->lock);
+			hsotg->op_state = OTG_STATE_A_HOST;
+		}
+	}
+
+	/* Change to L2 (suspend) state */
+	hsotg->lx_state = DWC2_L2;
+
+	/* Clear interrupt */
+	writel(GINTSTS_USBSUSP, hsotg->regs + GINTSTS);
+}
+
+#define GINTMSK_COMMON	(GINTSTS_WKUPINT | GINTSTS_SESSREQINT |		\
+			 GINTSTS_CONIDSTSCHNG | GINTSTS_OTGINT |	\
+			 GINTSTS_MODEMIS | GINTSTS_DISCONNINT |		\
+			 GINTSTS_USBSUSP | GINTSTS_RESTOREDONE |	\
+			 GINTSTS_PRTINT)
+
+/*
+ * This function returns the Core Interrupt register
+ */
+static u32 dwc2_read_common_intr(struct dwc2_hsotg *hsotg)
+{
+	u32 gintsts;
+	u32 gintmsk;
+	u32 gahbcfg;
+	u32 gintmsk_common = GINTMSK_COMMON;
+
+	gintsts = readl(hsotg->regs + GINTSTS);
+	gintmsk = readl(hsotg->regs + GINTMSK);
+	gahbcfg = readl(hsotg->regs + GAHBCFG);
+
+#ifdef DEBUG
+	/* If any common interrupts set */
+	if (gintsts & gintmsk_common)
+		dev_dbg(hsotg->dev, "gintsts=%08x  gintmsk=%08x\n",
+			gintsts, gintmsk);
+#endif
+
+	if (gahbcfg & GAHBCFG_GLBL_INTR_EN)
+		return gintsts & gintmsk & gintmsk_common;
+	else
+		return 0;
+}
+
+/*
+ * Common interrupt handler
+ *
+ * The common interrupts are those that occur in both Host and Device mode.
+ * This handler handles the following interrupts:
+ * - Mode Mismatch Interrupt
+ * - OTG Interrupt
+ * - Connector ID Status Change Interrupt
+ * - Disconnect Interrupt
+ * - Session Request Interrupt
+ * - Resume / Remote Wakeup Detected Interrupt
+ * - Suspend Interrupt
+ */
+irqreturn_t dwc2_handle_common_intr(int irq, void *dev)
+{
+	struct dwc2_hsotg *hsotg = dev;
+	u32 gintsts;
+	int retval = 0;
+
+	if (dwc2_check_core_status(hsotg) < 0) {
+		dev_warn(hsotg->dev, "Controller is disconnected");
+		goto out;
+	}
+
+	spin_lock(&hsotg->lock);
+
+	gintsts = dwc2_read_common_intr(hsotg);
+	if (gintsts & ~GINTSTS_PRTINT)
+		retval = 1;
+
+	if (gintsts & GINTSTS_MODEMIS)
+		dwc2_handle_mode_mismatch_intr(hsotg);
+	if (gintsts & GINTSTS_OTGINT)
+		dwc2_handle_otg_intr(hsotg);
+	if (gintsts & GINTSTS_CONIDSTSCHNG)
+		dwc2_handle_conn_id_status_change_intr(hsotg);
+	if (gintsts & GINTSTS_DISCONNINT)
+		dwc2_handle_disconnect_intr(hsotg);
+	if (gintsts & GINTSTS_SESSREQINT)
+		dwc2_handle_session_req_intr(hsotg);
+	if (gintsts & GINTSTS_WKUPINT)
+		dwc2_handle_wakeup_detected_intr(hsotg);
+	if (gintsts & GINTSTS_USBSUSP)
+		dwc2_handle_usb_suspend_intr(hsotg);
+
+	if (gintsts & GINTSTS_RESTOREDONE) {
+		gintsts = GINTSTS_RESTOREDONE;
+		writel(gintsts, hsotg->regs + GINTSTS);
+		dev_dbg(hsotg->dev, " --Restore done interrupt received--\n");
+	}
+
+	if (gintsts & GINTSTS_PRTINT) {
+		/*
+		 * The port interrupt occurs while in device mode with HPRT0
+		 * Port Enable/Disable
+		 */
+		if (dwc2_is_device_mode(hsotg)) {
+			dev_dbg(hsotg->dev,
+				" --Port interrupt received in Device mode--\n");
+			gintsts = GINTSTS_PRTINT;
+			writel(gintsts, hsotg->regs + GINTSTS);
+			retval = 1;
+		}
+	}
+
+	spin_unlock(&hsotg->lock);
+out:
+	return IRQ_RETVAL(retval);
+}
+EXPORT_SYMBOL_GPL(dwc2_handle_common_intr);
diff --git a/drivers/staging/dwc2/hcd.c b/drivers/staging/dwc2/hcd.c
new file mode 100644
index 0000000..91ff504
--- /dev/null
+++ b/drivers/staging/dwc2/hcd.c
@@ -0,0 +1,2962 @@
+/*
+ * hcd.c - DesignWare HS OTG Controller host-mode routines
+ *
+ * Copyright (C) 2004-2013 Synopsys, Inc.
+ *
+ * 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, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 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 names of the above-listed copyright holders may not 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 the License, or (at your option) any
+ * later version.
+ *
+ * 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.
+ */
+
+/*
+ * This file contains the core HCD code, and implements the Linux hc_driver
+ * API
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+
+#include <linux/usb/hcd.h>
+#include <linux/usb/ch11.h>
+
+#include "core.h"
+#include "hcd.h"
+
+/**
+ * dwc2_dump_channel_info() - Prints the state of a host channel
+ *
+ * @hsotg: Programming view of DWC_otg controller
+ * @chan:  Pointer to the channel to dump
+ *
+ * Must be called with interrupt disabled and spinlock held
+ *
+ * NOTE: This function will be removed once the peripheral controller code
+ * is integrated and the driver is stable
+ */
+static void dwc2_dump_channel_info(struct dwc2_hsotg *hsotg,
+				   struct dwc2_host_chan *chan)
+{
+#ifdef VERBOSE_DEBUG
+	int num_channels = hsotg->core_params->host_channels;
+	struct dwc2_qh *qh;
+	u32 hcchar;
+	u32 hcsplt;
+	u32 hctsiz;
+	u32 hc_dma;
+	int i;
+
+	if (chan == NULL)
+		return;
+
+	hcchar = readl(hsotg->regs + HCCHAR(chan->hc_num));
+	hcsplt = readl(hsotg->regs + HCSPLT(chan->hc_num));
+	hctsiz = readl(hsotg->regs + HCTSIZ(chan->hc_num));
+	hc_dma = readl(hsotg->regs + HCDMA(chan->hc_num));
+
+	dev_dbg(hsotg->dev, "  Assigned to channel %p:\n", chan);
+	dev_dbg(hsotg->dev, "    hcchar 0x%08x, hcsplt 0x%08x\n",
+		hcchar, hcsplt);
+	dev_dbg(hsotg->dev, "    hctsiz 0x%08x, hc_dma 0x%08x\n",
+		hctsiz, hc_dma);
+	dev_dbg(hsotg->dev, "    dev_addr: %d, ep_num: %d, ep_is_in: %d\n",
+		chan->dev_addr, chan->ep_num, chan->ep_is_in);
+	dev_dbg(hsotg->dev, "    ep_type: %d\n", chan->ep_type);
+	dev_dbg(hsotg->dev, "    max_packet: %d\n", chan->max_packet);
+	dev_dbg(hsotg->dev, "    data_pid_start: %d\n", chan->data_pid_start);
+	dev_dbg(hsotg->dev, "    xfer_started: %d\n", chan->xfer_started);
+	dev_dbg(hsotg->dev, "    halt_status: %d\n", chan->halt_status);
+	dev_dbg(hsotg->dev, "    xfer_buf: %p\n", chan->xfer_buf);
+	dev_dbg(hsotg->dev, "    xfer_dma: %08lx\n",
+		(unsigned long)chan->xfer_dma);
+	dev_dbg(hsotg->dev, "    xfer_len: %d\n", chan->xfer_len);
+	dev_dbg(hsotg->dev, "    qh: %p\n", chan->qh);
+	dev_dbg(hsotg->dev, "  NP inactive sched:\n");
+	list_for_each_entry(qh, &hsotg->non_periodic_sched_inactive,
+			    qh_list_entry)
+		dev_dbg(hsotg->dev, "    %p\n", qh);
+	dev_dbg(hsotg->dev, "  NP active sched:\n");
+	list_for_each_entry(qh, &hsotg->non_periodic_sched_active,
+			    qh_list_entry)
+		dev_dbg(hsotg->dev, "    %p\n", qh);
+	dev_dbg(hsotg->dev, "  Channels:\n");
+	for (i = 0; i < num_channels; i++) {
+		struct dwc2_host_chan *chan = hsotg->hc_ptr_array[i];
+
+		dev_dbg(hsotg->dev, "    %2d: %p\n", i, chan);
+	}
+#endif /* VERBOSE_DEBUG */
+}
+
+/*
+ * Processes all the URBs in a single list of QHs. Completes them with
+ * -ETIMEDOUT and frees the QTD.
+ *
+ * Must be called with interrupt disabled and spinlock held
+ */
+static void dwc2_kill_urbs_in_qh_list(struct dwc2_hsotg *hsotg,
+				      struct list_head *qh_list)
+{
+	struct dwc2_qh *qh, *qh_tmp;
+	struct dwc2_qtd *qtd, *qtd_tmp;
+
+	list_for_each_entry_safe(qh, qh_tmp, qh_list, qh_list_entry) {
+		list_for_each_entry_safe(qtd, qtd_tmp, &qh->qtd_list,
+					 qtd_list_entry) {
+			if (qtd->urb != NULL) {
+				dwc2_host_complete(hsotg, qtd->urb->priv,
+						   qtd->urb, -ETIMEDOUT);
+				dwc2_hcd_qtd_unlink_and_free(hsotg, qtd, qh);
+			}
+		}
+	}
+}
+
+static void dwc2_qh_list_free(struct dwc2_hsotg *hsotg,
+			      struct list_head *qh_list)
+{
+	struct dwc2_qtd *qtd, *qtd_tmp;
+	struct dwc2_qh *qh, *qh_tmp;
+	unsigned long flags;
+
+	if (!qh_list->next)
+		/* The list hasn't been initialized yet */
+		return;
+
+	spin_lock_irqsave(&hsotg->lock, flags);
+
+	/* Ensure there are no QTDs or URBs left */
+	dwc2_kill_urbs_in_qh_list(hsotg, qh_list);
+
+	list_for_each_entry_safe(qh, qh_tmp, qh_list, qh_list_entry) {
+		dwc2_hcd_qh_unlink(hsotg, qh);
+
+		/* Free each QTD in the QH's QTD list */
+		list_for_each_entry_safe(qtd, qtd_tmp, &qh->qtd_list,
+					 qtd_list_entry)
+			dwc2_hcd_qtd_unlink_and_free(hsotg, qtd, qh);
+
+		spin_unlock_irqrestore(&hsotg->lock, flags);
+		dwc2_hcd_qh_free(hsotg, qh);
+		spin_lock_irqsave(&hsotg->lock, flags);
+	}
+
+	spin_unlock_irqrestore(&hsotg->lock, flags);
+}
+
+/*
+ * Responds with an error status of -ETIMEDOUT to all URBs in the non-periodic
+ * and periodic schedules. The QTD associated with each URB is removed from
+ * the schedule and freed. This function may be called when a disconnect is
+ * detected or when the HCD is being stopped.
+ *
+ * Must be called with interrupt disabled and spinlock held
+ */
+static void dwc2_kill_all_urbs(struct dwc2_hsotg *hsotg)
+{
+	dwc2_kill_urbs_in_qh_list(hsotg, &hsotg->non_periodic_sched_inactive);
+	dwc2_kill_urbs_in_qh_list(hsotg, &hsotg->non_periodic_sched_active);
+	dwc2_kill_urbs_in_qh_list(hsotg, &hsotg->periodic_sched_inactive);
+	dwc2_kill_urbs_in_qh_list(hsotg, &hsotg->periodic_sched_ready);
+	dwc2_kill_urbs_in_qh_list(hsotg, &hsotg->periodic_sched_assigned);
+	dwc2_kill_urbs_in_qh_list(hsotg, &hsotg->periodic_sched_queued);
+}
+
+/**
+ * dwc2_hcd_start() - Starts the HCD when switching to Host mode
+ *
+ * @hsotg: Pointer to struct dwc2_hsotg
+ */
+void dwc2_hcd_start(struct dwc2_hsotg *hsotg)
+{
+	u32 hprt0;
+
+	if (hsotg->op_state == OTG_STATE_B_HOST) {
+		/*
+		 * Reset the port. During a HNP mode switch the reset
+		 * needs to occur within 1ms and have a duration of at
+		 * least 50ms.
+		 */
+		hprt0 = dwc2_read_hprt0(hsotg);
+		hprt0 |= HPRT0_RST;
+		writel(hprt0, hsotg->regs + HPRT0);
+	}
+
+	queue_delayed_work(hsotg->wq_otg, &hsotg->start_work,
+			   msecs_to_jiffies(50));
+}
+
+/* Must be called with interrupt disabled and spinlock held */
+static void dwc2_hcd_cleanup_channels(struct dwc2_hsotg *hsotg)
+{
+	int num_channels = hsotg->core_params->host_channels;
+	struct dwc2_host_chan *channel;
+	u32 hcchar;
+	int i;
+
+	if (hsotg->core_params->dma_enable <= 0) {
+		/* Flush out any channel requests in slave mode */
+		for (i = 0; i < num_channels; i++) {
+			channel = hsotg->hc_ptr_array[i];
+			if (!list_empty(&channel->hc_list_entry))
+				continue;
+			hcchar = readl(hsotg->regs + HCCHAR(i));
+			if (hcchar & HCCHAR_CHENA) {
+				hcchar &= ~(HCCHAR_CHENA | HCCHAR_EPDIR);
+				hcchar |= HCCHAR_CHDIS;
+				writel(hcchar, hsotg->regs + HCCHAR(i));
+			}
+		}
+	}
+
+	for (i = 0; i < num_channels; i++) {
+		channel = hsotg->hc_ptr_array[i];
+		if (!list_empty(&channel->hc_list_entry))
+			continue;
+		hcchar = readl(hsotg->regs + HCCHAR(i));
+		if (hcchar & HCCHAR_CHENA) {
+			/* Halt the channel */
+			hcchar |= HCCHAR_CHDIS;
+			writel(hcchar, hsotg->regs + HCCHAR(i));
+		}
+
+		dwc2_hc_cleanup(hsotg, channel);
+		list_add_tail(&channel->hc_list_entry, &hsotg->free_hc_list);
+		/*
+		 * Added for Descriptor DMA to prevent channel double cleanup in
+		 * release_channel_ddma(), which is called from ep_disable when
+		 * device disconnects
+		 */
+		channel->qh = NULL;
+	}
+}
+
+/**
+ * dwc2_hcd_disconnect() - Handles disconnect of the HCD
+ *
+ * @hsotg: Pointer to struct dwc2_hsotg
+ *
+ * Must be called with interrupt disabled and spinlock held
+ */
+void dwc2_hcd_disconnect(struct dwc2_hsotg *hsotg)
+{
+	u32 intr;
+
+	/* Set status flags for the hub driver */
+	hsotg->flags.b.port_connect_status_change = 1;
+	hsotg->flags.b.port_connect_status = 0;
+
+	/*
+	 * Shutdown any transfers in process by clearing the Tx FIFO Empty
+	 * interrupt mask and status bits and disabling subsequent host
+	 * channel interrupts.
+	 */
+	intr = readl(hsotg->regs + GINTMSK);
+	intr &= ~(GINTSTS_NPTXFEMP | GINTSTS_PTXFEMP | GINTSTS_HCHINT);
+	writel(intr, hsotg->regs + GINTMSK);
+	intr = GINTSTS_NPTXFEMP | GINTSTS_PTXFEMP | GINTSTS_HCHINT;
+	writel(intr, hsotg->regs + GINTSTS);
+
+	/*
+	 * Turn off the vbus power only if the core has transitioned to device
+	 * mode. If still in host mode, need to keep power on to detect a
+	 * reconnection.
+	 */
+	if (dwc2_is_device_mode(hsotg)) {
+		if (hsotg->op_state != OTG_STATE_A_SUSPEND) {
+			dev_dbg(hsotg->dev, "Disconnect: PortPower off\n");
+			writel(0, hsotg->regs + HPRT0);
+		}
+
+		dwc2_disable_host_interrupts(hsotg);
+	}
+
+	/* Respond with an error status to all URBs in the schedule */
+	dwc2_kill_all_urbs(hsotg);
+
+	if (dwc2_is_host_mode(hsotg))
+		/* Clean up any host channels that were in use */
+		dwc2_hcd_cleanup_channels(hsotg);
+
+	dwc2_host_disconnect(hsotg);
+}
+
+/**
+ * dwc2_hcd_rem_wakeup() - Handles Remote Wakeup
+ *
+ * @hsotg: Pointer to struct dwc2_hsotg
+ */
+static void dwc2_hcd_rem_wakeup(struct dwc2_hsotg *hsotg)
+{
+	if (hsotg->lx_state == DWC2_L2)
+		hsotg->flags.b.port_suspend_change = 1;
+	else
+		hsotg->flags.b.port_l1_change = 1;
+}
+
+/**
+ * dwc2_hcd_stop() - Halts the DWC_otg host mode operations in a clean manner
+ *
+ * @hsotg: Pointer to struct dwc2_hsotg
+ *
+ * Must be called with interrupt disabled and spinlock held
+ */
+void dwc2_hcd_stop(struct dwc2_hsotg *hsotg)
+{
+	dev_dbg(hsotg->dev, "DWC OTG HCD STOP\n");
+
+	/*
+	 * The root hub should be disconnected before this function is called.
+	 * The disconnect will clear the QTD lists (via ..._hcd_urb_dequeue)
+	 * and the QH lists (via ..._hcd_endpoint_disable).
+	 */
+
+	/* Turn off all host-specific interrupts */
+	dwc2_disable_host_interrupts(hsotg);
+
+	/* Turn off the vbus power */
+	dev_dbg(hsotg->dev, "PortPower off\n");
+	writel(0, hsotg->regs + HPRT0);
+}
+
+static int dwc2_hcd_urb_enqueue(struct dwc2_hsotg *hsotg,
+				struct dwc2_hcd_urb *urb, void **ep_handle,
+				gfp_t mem_flags)
+{
+	struct dwc2_qtd *qtd;
+	unsigned long flags;
+	u32 intr_mask;
+	int retval;
+
+	if (!hsotg->flags.b.port_connect_status) {
+		/* No longer connected */
+		dev_err(hsotg->dev, "Not connected\n");
+		return -ENODEV;
+	}
+
+	qtd = kzalloc(sizeof(*qtd), mem_flags);
+	if (!qtd)
+		return -ENOMEM;
+
+	dwc2_hcd_qtd_init(qtd, urb);
+	retval = dwc2_hcd_qtd_add(hsotg, qtd, (struct dwc2_qh **)ep_handle,
+				  mem_flags);
+	if (retval < 0) {
+		dev_err(hsotg->dev,
+			"DWC OTG HCD URB Enqueue failed adding QTD. Error status %d\n",
+			retval);
+		kfree(qtd);
+		return retval;
+	}
+
+	intr_mask = readl(hsotg->regs + GINTMSK);
+	if (!(intr_mask & GINTSTS_SOF) && retval == 0) {
+		enum dwc2_transaction_type tr_type;
+
+		if (qtd->qh->ep_type == USB_ENDPOINT_XFER_BULK &&
+		    !(qtd->urb->flags & URB_GIVEBACK_ASAP))
+			/*
+			 * Do not schedule SG transactions until qtd has
+			 * URB_GIVEBACK_ASAP set
+			 */
+			return 0;
+
+		spin_lock_irqsave(&hsotg->lock, flags);
+		tr_type = dwc2_hcd_select_transactions(hsotg);
+		if (tr_type != DWC2_TRANSACTION_NONE)
+			dwc2_hcd_queue_transactions(hsotg, tr_type);
+		spin_unlock_irqrestore(&hsotg->lock, flags);
+	}
+
+	return retval;
+}
+
+/* Must be called with interrupt disabled and spinlock held */
+static int dwc2_hcd_urb_dequeue(struct dwc2_hsotg *hsotg,
+				struct dwc2_hcd_urb *urb)
+{
+	struct dwc2_qh *qh;
+	struct dwc2_qtd *urb_qtd;
+
+	urb_qtd = urb->qtd;
+	if (!urb_qtd) {
+		dev_dbg(hsotg->dev, "## Urb QTD is NULL ##\n");
+		return -EINVAL;
+	}
+
+	qh = urb_qtd->qh;
+	if (!qh) {
+		dev_dbg(hsotg->dev, "## Urb QTD QH is NULL ##\n");
+		return -EINVAL;
+	}
+
+	if (urb_qtd->in_process && qh->channel) {
+		dwc2_dump_channel_info(hsotg, qh->channel);
+
+		/* The QTD is in process (it has been assigned to a channel) */
+		if (hsotg->flags.b.port_connect_status)
+			/*
+			 * If still connected (i.e. in host mode), halt the
+			 * channel so it can be used for other transfers. If
+			 * no longer connected, the host registers can't be
+			 * written to halt the channel since the core is in
+			 * device mode.
+			 */
+			dwc2_hc_halt(hsotg, qh->channel,
+				     DWC2_HC_XFER_URB_DEQUEUE);
+	}
+
+	/*
+	 * Free the QTD and clean up the associated QH. Leave the QH in the
+	 * schedule if it has any remaining QTDs.
+	 */
+	if (hsotg->core_params->dma_desc_enable <= 0) {
+		u8 in_process = urb_qtd->in_process;
+
+		dwc2_hcd_qtd_unlink_and_free(hsotg, urb_qtd, qh);
+		if (in_process) {
+			dwc2_hcd_qh_deactivate(hsotg, qh, 0);
+			qh->channel = NULL;
+		} else if (list_empty(&qh->qtd_list)) {
+			dwc2_hcd_qh_unlink(hsotg, qh);
+		}
+	} else {
+		dwc2_hcd_qtd_unlink_and_free(hsotg, urb_qtd, qh);
+	}
+
+	return 0;
+}
+
+/* Must NOT be called with interrupt disabled or spinlock held */
+static int dwc2_hcd_endpoint_disable(struct dwc2_hsotg *hsotg,
+				     struct usb_host_endpoint *ep, int retry)
+{
+	struct dwc2_qtd *qtd, *qtd_tmp;
+	struct dwc2_qh *qh;
+	unsigned long flags;
+	int rc;
+
+	spin_lock_irqsave(&hsotg->lock, flags);
+
+	qh = ep->hcpriv;
+	if (!qh) {
+		rc = -EINVAL;
+		goto err;
+	}
+
+	while (!list_empty(&qh->qtd_list) && retry--) {
+		if (retry == 0) {
+			dev_err(hsotg->dev,
+				"## timeout in dwc2_hcd_endpoint_disable() ##\n");
+			rc = -EBUSY;
+			goto err;
+		}
+
+		spin_unlock_irqrestore(&hsotg->lock, flags);
+		usleep_range(20000, 40000);
+		spin_lock_irqsave(&hsotg->lock, flags);
+		qh = ep->hcpriv;
+		if (!qh) {
+			rc = -EINVAL;
+			goto err;
+		}
+	}
+
+	dwc2_hcd_qh_unlink(hsotg, qh);
+
+	/* Free each QTD in the QH's QTD list */
+	list_for_each_entry_safe(qtd, qtd_tmp, &qh->qtd_list, qtd_list_entry)
+		dwc2_hcd_qtd_unlink_and_free(hsotg, qtd, qh);
+
+	ep->hcpriv = NULL;
+	spin_unlock_irqrestore(&hsotg->lock, flags);
+	dwc2_hcd_qh_free(hsotg, qh);
+
+	return 0;
+
+err:
+	ep->hcpriv = NULL;
+	spin_unlock_irqrestore(&hsotg->lock, flags);
+
+	return rc;
+}
+
+/* Must be called with interrupt disabled and spinlock held */
+static int dwc2_hcd_endpoint_reset(struct dwc2_hsotg *hsotg,
+				   struct usb_host_endpoint *ep)
+{
+	struct dwc2_qh *qh = ep->hcpriv;
+
+	if (!qh)
+		return -EINVAL;
+
+	qh->data_toggle = DWC2_HC_PID_DATA0;
+
+	return 0;
+}
+
+/*
+ * Initializes dynamic portions of the DWC_otg HCD state
+ *
+ * Must be called with interrupt disabled and spinlock held
+ */
+static void dwc2_hcd_reinit(struct dwc2_hsotg *hsotg)
+{
+	struct dwc2_host_chan *chan, *chan_tmp;
+	int num_channels;
+	int i;
+
+	hsotg->flags.d32 = 0;
+
+	hsotg->non_periodic_qh_ptr = &hsotg->non_periodic_sched_active;
+	hsotg->non_periodic_channels = 0;
+	hsotg->periodic_channels = 0;
+
+	/*
+	 * Put all channels in the free channel list and clean up channel
+	 * states
+	 */
+	list_for_each_entry_safe(chan, chan_tmp, &hsotg->free_hc_list,
+				 hc_list_entry)
+		list_del_init(&chan->hc_list_entry);
+
+	num_channels = hsotg->core_params->host_channels;
+	for (i = 0; i < num_channels; i++) {
+		chan = hsotg->hc_ptr_array[i];
+		list_add_tail(&chan->hc_list_entry, &hsotg->free_hc_list);
+		dwc2_hc_cleanup(hsotg, chan);
+	}
+
+	/* Initialize the DWC core for host mode operation */
+	dwc2_core_host_init(hsotg);
+}
+
+static void dwc2_hc_init_split(struct dwc2_hsotg *hsotg,
+			       struct dwc2_host_chan *chan,
+			       struct dwc2_qtd *qtd, struct dwc2_hcd_urb *urb)
+{
+	int hub_addr, hub_port;
+
+	chan->do_split = 1;
+	chan->xact_pos = qtd->isoc_split_pos;
+	chan->complete_split = qtd->complete_split;
+	dwc2_host_hub_info(hsotg, urb->priv, &hub_addr, &hub_port);
+	chan->hub_addr = (u8)hub_addr;
+	chan->hub_port = (u8)hub_port;
+}
+
+static void *dwc2_hc_init_xfer(struct dwc2_hsotg *hsotg,
+			       struct dwc2_host_chan *chan,
+			       struct dwc2_qtd *qtd, void *bufptr)
+{
+	struct dwc2_hcd_urb *urb = qtd->urb;
+	struct dwc2_hcd_iso_packet_desc *frame_desc;
+
+	switch (dwc2_hcd_get_pipe_type(&urb->pipe_info)) {
+	case USB_ENDPOINT_XFER_CONTROL:
+		chan->ep_type = USB_ENDPOINT_XFER_CONTROL;
+
+		switch (qtd->control_phase) {
+		case DWC2_CONTROL_SETUP:
+			dev_vdbg(hsotg->dev, "  Control setup transaction\n");
+			chan->do_ping = 0;
+			chan->ep_is_in = 0;
+			chan->data_pid_start = DWC2_HC_PID_SETUP;
+			if (hsotg->core_params->dma_enable > 0)
+				chan->xfer_dma = urb->setup_dma;
+			else
+				chan->xfer_buf = urb->setup_packet;
+			chan->xfer_len = 8;
+			bufptr = NULL;
+			break;
+
+		case DWC2_CONTROL_DATA:
+			dev_vdbg(hsotg->dev, "  Control data transaction\n");
+			chan->data_pid_start = qtd->data_toggle;
+			break;
+
+		case DWC2_CONTROL_STATUS:
+			/*
+			 * Direction is opposite of data direction or IN if no
+			 * data
+			 */
+			dev_vdbg(hsotg->dev, "  Control status transaction\n");
+			if (urb->length == 0)
+				chan->ep_is_in = 1;
+			else
+				chan->ep_is_in =
+					dwc2_hcd_is_pipe_out(&urb->pipe_info);
+			if (chan->ep_is_in)
+				chan->do_ping = 0;
+			chan->data_pid_start = DWC2_HC_PID_DATA1;
+			chan->xfer_len = 0;
+			if (hsotg->core_params->dma_enable > 0)
+				chan->xfer_dma = hsotg->status_buf_dma;
+			else
+				chan->xfer_buf = hsotg->status_buf;
+			bufptr = NULL;
+			break;
+		}
+		break;
+
+	case USB_ENDPOINT_XFER_BULK:
+		chan->ep_type = USB_ENDPOINT_XFER_BULK;
+		break;
+
+	case USB_ENDPOINT_XFER_INT:
+		chan->ep_type = USB_ENDPOINT_XFER_INT;
+		break;
+
+	case USB_ENDPOINT_XFER_ISOC:
+		chan->ep_type = USB_ENDPOINT_XFER_ISOC;
+		if (hsotg->core_params->dma_desc_enable > 0)
+			break;
+
+		frame_desc = &urb->iso_descs[qtd->isoc_frame_index];
+		frame_desc->status = 0;
+
+		if (hsotg->core_params->dma_enable > 0) {
+			chan->xfer_dma = urb->dma;
+			chan->xfer_dma += frame_desc->offset +
+					qtd->isoc_split_offset;
+		} else {
+			chan->xfer_buf = urb->buf;
+			chan->xfer_buf += frame_desc->offset +
+					qtd->isoc_split_offset;
+		}
+
+		chan->xfer_len = frame_desc->length - qtd->isoc_split_offset;
+
+		/* For non-dword aligned buffers */
+		if (hsotg->core_params->dma_enable > 0 &&
+		    (chan->xfer_dma & 0x3))
+			bufptr = (u8 *)urb->buf + frame_desc->offset +
+					qtd->isoc_split_offset;
+		else
+			bufptr = NULL;
+
+		if (chan->xact_pos == DWC2_HCSPLT_XACTPOS_ALL) {
+			if (chan->xfer_len <= 188)
+				chan->xact_pos = DWC2_HCSPLT_XACTPOS_ALL;
+			else
+				chan->xact_pos = DWC2_HCSPLT_XACTPOS_BEGIN;
+		}
+		break;
+	}
+
+	return bufptr;
+}
+
+static int dwc2_hc_setup_align_buf(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh,
+				   struct dwc2_host_chan *chan, void *bufptr)
+{
+	u32 buf_size;
+
+	if (chan->ep_type != USB_ENDPOINT_XFER_ISOC)
+		buf_size = hsotg->core_params->max_transfer_size;
+	else
+		buf_size = 4096;
+
+	if (!qh->dw_align_buf) {
+		qh->dw_align_buf = dma_alloc_coherent(hsotg->dev, buf_size,
+						      &qh->dw_align_buf_dma,
+						      GFP_ATOMIC);
+		if (!qh->dw_align_buf)
+			return -ENOMEM;
+	}
+
+	if (!chan->ep_is_in && chan->xfer_len) {
+		dma_sync_single_for_cpu(hsotg->dev, chan->xfer_dma, buf_size,
+					DMA_TO_DEVICE);
+		memcpy(qh->dw_align_buf, bufptr, chan->xfer_len);
+		dma_sync_single_for_device(hsotg->dev, chan->xfer_dma, buf_size,
+					   DMA_TO_DEVICE);
+	}
+
+	chan->align_buf = qh->dw_align_buf_dma;
+	return 0;
+}
+
+/**
+ * dwc2_assign_and_init_hc() - Assigns transactions from a QTD to a free host
+ * channel and initializes the host channel to perform the transactions. The
+ * host channel is removed from the free list.
+ *
+ * @hsotg: The HCD state structure
+ * @qh:    Transactions from the first QTD for this QH are selected and assigned
+ *         to a free host channel
+ */
+static void dwc2_assign_and_init_hc(struct dwc2_hsotg *hsotg,
+				    struct dwc2_qh *qh)
+{
+	struct dwc2_host_chan *chan;
+	struct dwc2_hcd_urb *urb;
+	struct dwc2_qtd *qtd;
+	void *bufptr = NULL;
+
+	dev_vdbg(hsotg->dev, "%s(%p,%p)\n", __func__, hsotg, qh);
+
+	if (list_empty(&qh->qtd_list)) {
+		dev_dbg(hsotg->dev, "No QTDs in QH list\n");
+		return;
+	}
+
+	if (list_empty(&hsotg->free_hc_list)) {
+		dev_dbg(hsotg->dev, "No free channel to assign\n");
+		return;
+	}
+
+	chan = list_first_entry(&hsotg->free_hc_list, struct dwc2_host_chan,
+				hc_list_entry);
+
+	/* Remove the host channel from the free list */
+	list_del_init(&chan->hc_list_entry);
+
+	qtd = list_first_entry(&qh->qtd_list, struct dwc2_qtd, qtd_list_entry);
+	urb = qtd->urb;
+	qh->channel = chan;
+	qtd->in_process = 1;
+
+	/*
+	 * Use usb_pipedevice to determine device address. This address is
+	 * 0 before the SET_ADDRESS command and the correct address afterward.
+	 */
+	chan->dev_addr = dwc2_hcd_get_dev_addr(&urb->pipe_info);
+	chan->ep_num = dwc2_hcd_get_ep_num(&urb->pipe_info);
+	chan->speed = qh->dev_speed;
+	chan->max_packet = dwc2_max_packet(qh->maxp);
+
+	chan->xfer_started = 0;
+	chan->halt_status = DWC2_HC_XFER_NO_HALT_STATUS;
+	chan->error_state = (qtd->error_count > 0);
+	chan->halt_on_queue = 0;
+	chan->halt_pending = 0;
+	chan->requests = 0;
+
+	/*
+	 * The following values may be modified in the transfer type section
+	 * below. The xfer_len value may be reduced when the transfer is
+	 * started to accommodate the max widths of the XferSize and PktCnt
+	 * fields in the HCTSIZn register.
+	 */
+
+	chan->ep_is_in = (dwc2_hcd_is_pipe_in(&urb->pipe_info) != 0);
+	if (chan->ep_is_in)
+		chan->do_ping = 0;
+	else
+		chan->do_ping = qh->ping_state;
+
+	chan->data_pid_start = qh->data_toggle;
+	chan->multi_count = 1;
+
+	if (hsotg->core_params->dma_enable > 0) {
+		chan->xfer_dma = urb->dma + urb->actual_length;
+
+		/* For non-dword aligned case */
+		if (hsotg->core_params->dma_desc_enable <= 0 &&
+		    (chan->xfer_dma & 0x3))
+			bufptr = (u8 *)urb->buf + urb->actual_length;
+	} else {
+		chan->xfer_buf = (u8 *)urb->buf + urb->actual_length;
+	}
+
+	chan->xfer_len = urb->length - urb->actual_length;
+	chan->xfer_count = 0;
+
+	/* Set the split attributes if required */
+	if (qh->do_split)
+		dwc2_hc_init_split(hsotg, chan, qtd, urb);
+	else
+		chan->do_split = 0;
+
+	/* Set the transfer attributes */
+	bufptr = dwc2_hc_init_xfer(hsotg, chan, qtd, bufptr);
+
+	/* Non DWORD-aligned buffer case */
+	if (bufptr) {
+		dev_vdbg(hsotg->dev, "Non-aligned buffer\n");
+		if (dwc2_hc_setup_align_buf(hsotg, qh, chan, bufptr)) {
+			dev_err(hsotg->dev,
+				"%s: Failed to allocate memory to handle non-dword aligned buffer\n",
+				__func__);
+			/* Add channel back to free list */
+			chan->align_buf = 0;
+			chan->multi_count = 0;
+			list_add_tail(&chan->hc_list_entry,
+				      &hsotg->free_hc_list);
+			qtd->in_process = 0;
+			qh->channel = NULL;
+			return;
+		}
+	} else {
+		chan->align_buf = 0;
+	}
+
+	if (chan->ep_type == USB_ENDPOINT_XFER_INT ||
+	    chan->ep_type == USB_ENDPOINT_XFER_ISOC)
+		/*
+		 * This value may be modified when the transfer is started
+		 * to reflect the actual transfer length
+		 */
+		chan->multi_count = dwc2_hb_mult(qh->maxp);
+
+	if (hsotg->core_params->dma_desc_enable > 0)
+		chan->desc_list_addr = qh->desc_list_dma;
+
+	dwc2_hc_init(hsotg, chan);
+	chan->qh = qh;
+}
+
+/**
+ * dwc2_hcd_select_transactions() - Selects transactions from the HCD transfer
+ * schedule and assigns them to available host channels. Called from the HCD
+ * interrupt handler functions.
+ *
+ * @hsotg: The HCD state structure
+ *
+ * Return: The types of new transactions that were assigned to host channels
+ */
+enum dwc2_transaction_type dwc2_hcd_select_transactions(
+		struct dwc2_hsotg *hsotg)
+{
+	enum dwc2_transaction_type ret_val = DWC2_TRANSACTION_NONE;
+	struct list_head *qh_ptr;
+	struct dwc2_qh *qh;
+	int num_channels;
+
+#ifdef DWC2_DEBUG_SOF
+	dev_vdbg(hsotg->dev, "  Select Transactions\n");
+#endif
+
+	/* Process entries in the periodic ready list */
+	qh_ptr = hsotg->periodic_sched_ready.next;
+	while (qh_ptr != &hsotg->periodic_sched_ready) {
+		if (list_empty(&hsotg->free_hc_list))
+			break;
+		qh = list_entry(qh_ptr, struct dwc2_qh, qh_list_entry);
+		dwc2_assign_and_init_hc(hsotg, qh);
+
+		/*
+		 * Move the QH from the periodic ready schedule to the
+		 * periodic assigned schedule
+		 */
+		qh_ptr = qh_ptr->next;
+		list_move(&qh->qh_list_entry, &hsotg->periodic_sched_assigned);
+		ret_val = DWC2_TRANSACTION_PERIODIC;
+	}
+
+	/*
+	 * Process entries in the inactive portion of the non-periodic
+	 * schedule. Some free host channels may not be used if they are
+	 * reserved for periodic transfers.
+	 */
+	num_channels = hsotg->core_params->host_channels;
+	qh_ptr = hsotg->non_periodic_sched_inactive.next;
+	while (qh_ptr != &hsotg->non_periodic_sched_inactive) {
+		if (hsotg->non_periodic_channels >= num_channels -
+						hsotg->periodic_channels)
+			break;
+		if (list_empty(&hsotg->free_hc_list))
+			break;
+		qh = list_entry(qh_ptr, struct dwc2_qh, qh_list_entry);
+		dwc2_assign_and_init_hc(hsotg, qh);
+
+		/*
+		 * Move the QH from the non-periodic inactive schedule to the
+		 * non-periodic active schedule
+		 */
+		qh_ptr = qh_ptr->next;
+		list_move(&qh->qh_list_entry,
+			  &hsotg->non_periodic_sched_active);
+
+		if (ret_val == DWC2_TRANSACTION_NONE)
+			ret_val = DWC2_TRANSACTION_NON_PERIODIC;
+		else
+			ret_val = DWC2_TRANSACTION_ALL;
+
+		hsotg->non_periodic_channels++;
+	}
+
+	return ret_val;
+}
+
+/**
+ * dwc2_queue_transaction() - Attempts to queue a single transaction request for
+ * a host channel associated with either a periodic or non-periodic transfer
+ *
+ * @hsotg: The HCD state structure
+ * @chan:  Host channel descriptor associated with either a periodic or
+ *         non-periodic transfer
+ * @fifo_dwords_avail: Number of DWORDs available in the periodic Tx FIFO
+ *                     for periodic transfers or the non-periodic Tx FIFO
+ *                     for non-periodic transfers
+ *
+ * Return: 1 if a request is queued and more requests may be needed to
+ * complete the transfer, 0 if no more requests are required for this
+ * transfer, -1 if there is insufficient space in the Tx FIFO
+ *
+ * This function assumes that there is space available in the appropriate
+ * request queue. For an OUT transfer or SETUP transaction in Slave mode,
+ * it checks whether space is available in the appropriate Tx FIFO.
+ *
+ * Must be called with interrupt disabled and spinlock held
+ */
+static int dwc2_queue_transaction(struct dwc2_hsotg *hsotg,
+				  struct dwc2_host_chan *chan,
+				  u16 fifo_dwords_avail)
+{
+	int retval = 0;
+
+	if (hsotg->core_params->dma_enable > 0) {
+		if (hsotg->core_params->dma_desc_enable > 0) {
+			if (!chan->xfer_started ||
+			    chan->ep_type == USB_ENDPOINT_XFER_ISOC) {
+				dwc2_hcd_start_xfer_ddma(hsotg, chan->qh);
+				chan->qh->ping_state = 0;
+			}
+		} else if (!chan->xfer_started) {
+			dwc2_hc_start_transfer(hsotg, chan);
+			chan->qh->ping_state = 0;
+		}
+	} else if (chan->halt_pending) {
+		/* Don't queue a request if the channel has been halted */
+	} else if (chan->halt_on_queue) {
+		dwc2_hc_halt(hsotg, chan, chan->halt_status);
+	} else if (chan->do_ping) {
+		if (!chan->xfer_started)
+			dwc2_hc_start_transfer(hsotg, chan);
+	} else if (!chan->ep_is_in ||
+		   chan->data_pid_start == DWC2_HC_PID_SETUP) {
+		if ((fifo_dwords_avail * 4) >= chan->max_packet) {
+			if (!chan->xfer_started) {
+				dwc2_hc_start_transfer(hsotg, chan);
+				retval = 1;
+			} else {
+				retval = dwc2_hc_continue_transfer(hsotg, chan);
+			}
+		} else {
+			retval = -1;
+		}
+	} else {
+		if (!chan->xfer_started) {
+			dwc2_hc_start_transfer(hsotg, chan);
+			retval = 1;
+		} else {
+			retval = dwc2_hc_continue_transfer(hsotg, chan);
+		}
+	}
+
+	return retval;
+}
+
+/*
+ * Processes periodic channels for the next frame and queues transactions for
+ * these channels to the DWC_otg controller. After queueing transactions, the
+ * Periodic Tx FIFO Empty interrupt is enabled if there are more transactions
+ * to queue as Periodic Tx FIFO or request queue space becomes available.
+ * Otherwise, the Periodic Tx FIFO Empty interrupt is disabled.
+ *
+ * Must be called with interrupt disabled and spinlock held
+ */
+static void dwc2_process_periodic_channels(struct dwc2_hsotg *hsotg)
+{
+	struct list_head *qh_ptr;
+	struct dwc2_qh *qh;
+	u32 tx_status;
+	u32 fspcavail;
+	u32 gintmsk;
+	int status;
+	int no_queue_space = 0;
+	int no_fifo_space = 0;
+	u32 qspcavail;
+
+	dev_vdbg(hsotg->dev, "Queue periodic transactions\n");
+
+	tx_status = readl(hsotg->regs + HPTXSTS);
+	qspcavail = tx_status >> TXSTS_QSPCAVAIL_SHIFT &
+		    TXSTS_QSPCAVAIL_MASK >> TXSTS_QSPCAVAIL_SHIFT;
+	fspcavail = tx_status >> TXSTS_FSPCAVAIL_SHIFT &
+		    TXSTS_FSPCAVAIL_MASK >> TXSTS_FSPCAVAIL_SHIFT;
+	dev_vdbg(hsotg->dev, "  P Tx Req Queue Space Avail (before queue): %d\n",
+		 qspcavail);
+	dev_vdbg(hsotg->dev, "  P Tx FIFO Space Avail (before queue): %d\n",
+		 fspcavail);
+
+	qh_ptr = hsotg->periodic_sched_assigned.next;
+	while (qh_ptr != &hsotg->periodic_sched_assigned) {
+		tx_status = readl(hsotg->regs + HPTXSTS);
+		if ((tx_status & TXSTS_QSPCAVAIL_MASK) == 0) {
+			no_queue_space = 1;
+			break;
+		}
+
+		qh = list_entry(qh_ptr, struct dwc2_qh, qh_list_entry);
+		if (!qh->channel) {
+			qh_ptr = qh_ptr->next;
+			continue;
+		}
+
+		/* Make sure EP's TT buffer is clean before queueing qtds */
+		if (qh->tt_buffer_dirty) {
+			qh_ptr = qh_ptr->next;
+			continue;
+		}
+
+		/*
+		 * Set a flag if we're queuing high-bandwidth in slave mode.
+		 * The flag prevents any halts to get into the request queue in
+		 * the middle of multiple high-bandwidth packets getting queued.
+		 */
+		if (hsotg->core_params->dma_enable <= 0 &&
+				qh->channel->multi_count > 1)
+			hsotg->queuing_high_bandwidth = 1;
+
+		fspcavail = tx_status >> TXSTS_FSPCAVAIL_SHIFT &
+			    TXSTS_FSPCAVAIL_MASK >> TXSTS_FSPCAVAIL_SHIFT;
+		status = dwc2_queue_transaction(hsotg, qh->channel, fspcavail);
+		if (status < 0) {
+			no_fifo_space = 1;
+			break;
+		}
+
+		/*
+		 * In Slave mode, stay on the current transfer until there is
+		 * nothing more to do or the high-bandwidth request count is
+		 * reached. In DMA mode, only need to queue one request. The
+		 * controller automatically handles multiple packets for
+		 * high-bandwidth transfers.
+		 */
+		if (hsotg->core_params->dma_enable > 0 || status == 0 ||
+		    qh->channel->requests == qh->channel->multi_count) {
+			qh_ptr = qh_ptr->next;
+			/*
+			 * Move the QH from the periodic assigned schedule to
+			 * the periodic queued schedule
+			 */
+			list_move(&qh->qh_list_entry,
+				  &hsotg->periodic_sched_queued);
+
+			/* done queuing high bandwidth */
+			hsotg->queuing_high_bandwidth = 0;
+		}
+	}
+
+	if (hsotg->core_params->dma_enable <= 0) {
+		tx_status = readl(hsotg->regs + HPTXSTS);
+		qspcavail = tx_status >> TXSTS_QSPCAVAIL_SHIFT &
+			    TXSTS_QSPCAVAIL_MASK >> TXSTS_QSPCAVAIL_SHIFT;
+		fspcavail = tx_status >> TXSTS_FSPCAVAIL_SHIFT &
+			    TXSTS_FSPCAVAIL_MASK >> TXSTS_FSPCAVAIL_SHIFT;
+		dev_vdbg(hsotg->dev,
+			 "  P Tx Req Queue Space Avail (after queue): %d\n",
+			 qspcavail);
+		dev_vdbg(hsotg->dev,
+			 "  P Tx FIFO Space Avail (after queue): %d\n",
+			 fspcavail);
+
+		if (!list_empty(&hsotg->periodic_sched_assigned) ||
+		    no_queue_space || no_fifo_space) {
+			/*
+			 * May need to queue more transactions as the request
+			 * queue or Tx FIFO empties. Enable the periodic Tx
+			 * FIFO empty interrupt. (Always use the half-empty
+			 * level to ensure that new requests are loaded as
+			 * soon as possible.)
+			 */
+			gintmsk = readl(hsotg->regs + GINTMSK);
+			gintmsk |= GINTSTS_PTXFEMP;
+			writel(gintmsk, hsotg->regs + GINTMSK);
+		} else {
+			/*
+			 * Disable the Tx FIFO empty interrupt since there are
+			 * no more transactions that need to be queued right
+			 * now. This function is called from interrupt
+			 * handlers to queue more transactions as transfer
+			 * states change.
+			 */
+			gintmsk = readl(hsotg->regs + GINTMSK);
+			gintmsk &= ~GINTSTS_PTXFEMP;
+			writel(gintmsk, hsotg->regs + GINTMSK);
+		}
+	}
+}
+
+/*
+ * Processes active non-periodic channels and queues transactions for these
+ * channels to the DWC_otg controller. After queueing transactions, the NP Tx
+ * FIFO Empty interrupt is enabled if there are more transactions to queue as
+ * NP Tx FIFO or request queue space becomes available. Otherwise, the NP Tx
+ * FIFO Empty interrupt is disabled.
+ *
+ * Must be called with interrupt disabled and spinlock held
+ */
+static void dwc2_process_non_periodic_channels(struct dwc2_hsotg *hsotg)
+{
+	struct list_head *orig_qh_ptr;
+	struct dwc2_qh *qh;
+	u32 tx_status;
+	u32 qspcavail;
+	u32 fspcavail;
+	u32 gintmsk;
+	int status;
+	int no_queue_space = 0;
+	int no_fifo_space = 0;
+	int more_to_do = 0;
+
+	dev_vdbg(hsotg->dev, "Queue non-periodic transactions\n");
+
+	tx_status = readl(hsotg->regs + GNPTXSTS);
+	qspcavail = tx_status >> TXSTS_QSPCAVAIL_SHIFT &
+		    TXSTS_QSPCAVAIL_MASK >> TXSTS_QSPCAVAIL_SHIFT;
+	fspcavail = tx_status >> TXSTS_FSPCAVAIL_SHIFT &
+		    TXSTS_FSPCAVAIL_MASK >> TXSTS_FSPCAVAIL_SHIFT;
+	dev_vdbg(hsotg->dev, "  NP Tx Req Queue Space Avail (before queue): %d\n",
+		 qspcavail);
+	dev_vdbg(hsotg->dev, "  NP Tx FIFO Space Avail (before queue): %d\n",
+		 fspcavail);
+
+	/*
+	 * Keep track of the starting point. Skip over the start-of-list
+	 * entry.
+	 */
+	if (hsotg->non_periodic_qh_ptr == &hsotg->non_periodic_sched_active)
+		hsotg->non_periodic_qh_ptr = hsotg->non_periodic_qh_ptr->next;
+	orig_qh_ptr = hsotg->non_periodic_qh_ptr;
+
+	/*
+	 * Process once through the active list or until no more space is
+	 * available in the request queue or the Tx FIFO
+	 */
+	do {
+		tx_status = readl(hsotg->regs + GNPTXSTS);
+		qspcavail = tx_status >> TXSTS_QSPCAVAIL_SHIFT &
+			    TXSTS_QSPCAVAIL_MASK >> TXSTS_QSPCAVAIL_SHIFT;
+		if (hsotg->core_params->dma_enable <= 0 && qspcavail == 0) {
+			no_queue_space = 1;
+			break;
+		}
+
+		qh = list_entry(hsotg->non_periodic_qh_ptr, struct dwc2_qh,
+				qh_list_entry);
+		if (!qh->channel)
+			goto next;
+
+		/* Make sure EP's TT buffer is clean before queueing qtds */
+		if (qh->tt_buffer_dirty)
+			goto next;
+
+		fspcavail = tx_status >> TXSTS_FSPCAVAIL_SHIFT &
+			    TXSTS_FSPCAVAIL_MASK >> TXSTS_FSPCAVAIL_SHIFT;
+		status = dwc2_queue_transaction(hsotg, qh->channel, fspcavail);
+
+		if (status > 0) {
+			more_to_do = 1;
+		} else if (status < 0) {
+			no_fifo_space = 1;
+			break;
+		}
+next:
+		/* Advance to next QH, skipping start-of-list entry */
+		hsotg->non_periodic_qh_ptr = hsotg->non_periodic_qh_ptr->next;
+		if (hsotg->non_periodic_qh_ptr ==
+				&hsotg->non_periodic_sched_active)
+			hsotg->non_periodic_qh_ptr =
+					hsotg->non_periodic_qh_ptr->next;
+	} while (hsotg->non_periodic_qh_ptr != orig_qh_ptr);
+
+	if (hsotg->core_params->dma_enable <= 0) {
+		tx_status = readl(hsotg->regs + GNPTXSTS);
+		qspcavail = tx_status >> TXSTS_QSPCAVAIL_SHIFT &
+			    TXSTS_QSPCAVAIL_MASK >> TXSTS_QSPCAVAIL_SHIFT;
+		fspcavail = tx_status >> TXSTS_FSPCAVAIL_SHIFT &
+			    TXSTS_FSPCAVAIL_MASK >> TXSTS_FSPCAVAIL_SHIFT;
+		dev_vdbg(hsotg->dev,
+			 "  NP Tx Req Queue Space Avail (after queue): %d\n",
+			 qspcavail);
+		dev_vdbg(hsotg->dev,
+			 "  NP Tx FIFO Space Avail (after queue): %d\n",
+			 fspcavail);
+
+		if (more_to_do || no_queue_space || no_fifo_space) {
+			/*
+			 * May need to queue more transactions as the request
+			 * queue or Tx FIFO empties. Enable the non-periodic
+			 * Tx FIFO empty interrupt. (Always use the half-empty
+			 * level to ensure that new requests are loaded as
+			 * soon as possible.)
+			 */
+			gintmsk = readl(hsotg->regs + GINTMSK);
+			gintmsk |= GINTSTS_NPTXFEMP;
+			writel(gintmsk, hsotg->regs + GINTMSK);
+		} else {
+			/*
+			 * Disable the Tx FIFO empty interrupt since there are
+			 * no more transactions that need to be queued right
+			 * now. This function is called from interrupt
+			 * handlers to queue more transactions as transfer
+			 * states change.
+			 */
+			gintmsk = readl(hsotg->regs + GINTMSK);
+			gintmsk &= ~GINTSTS_NPTXFEMP;
+			writel(gintmsk, hsotg->regs + GINTMSK);
+		}
+	}
+}
+
+/**
+ * dwc2_hcd_queue_transactions() - Processes the currently active host channels
+ * and queues transactions for these channels to the DWC_otg controller. Called
+ * from the HCD interrupt handler functions.
+ *
+ * @hsotg:   The HCD state structure
+ * @tr_type: The type(s) of transactions to queue (non-periodic, periodic,
+ *           or both)
+ *
+ * Must be called with interrupt disabled and spinlock held
+ */
+void dwc2_hcd_queue_transactions(struct dwc2_hsotg *hsotg,
+				 enum dwc2_transaction_type tr_type)
+{
+#ifdef DWC2_DEBUG_SOF
+	dev_vdbg(hsotg->dev, "Queue Transactions\n");
+#endif
+	/* Process host channels associated with periodic transfers */
+	if ((tr_type == DWC2_TRANSACTION_PERIODIC ||
+	     tr_type == DWC2_TRANSACTION_ALL) &&
+	    !list_empty(&hsotg->periodic_sched_assigned))
+		dwc2_process_periodic_channels(hsotg);
+
+	/* Process host channels associated with non-periodic transfers */
+	if (tr_type == DWC2_TRANSACTION_NON_PERIODIC ||
+	    tr_type == DWC2_TRANSACTION_ALL) {
+		if (!list_empty(&hsotg->non_periodic_sched_active)) {
+			dwc2_process_non_periodic_channels(hsotg);
+		} else {
+			/*
+			 * Ensure NP Tx FIFO empty interrupt is disabled when
+			 * there are no non-periodic transfers to process
+			 */
+			u32 gintmsk = readl(hsotg->regs + GINTMSK);
+
+			gintmsk &= ~GINTSTS_NPTXFEMP;
+			writel(gintmsk, hsotg->regs + GINTMSK);
+		}
+	}
+}
+
+static void dwc2_conn_id_status_change(struct work_struct *work)
+{
+	struct dwc2_hsotg *hsotg = container_of(work, struct dwc2_hsotg,
+						wf_otg);
+	u32 count = 0;
+	u32 gotgctl;
+
+	dev_dbg(hsotg->dev, "%s()\n", __func__);
+
+	gotgctl = readl(hsotg->regs + GOTGCTL);
+	dev_dbg(hsotg->dev, "gotgctl=%0x\n", gotgctl);
+	dev_dbg(hsotg->dev, "gotgctl.b.conidsts=%d\n",
+		!!(gotgctl & GOTGCTL_CONID_B));
+
+	/* B-Device connector (Device Mode) */
+	if (gotgctl & GOTGCTL_CONID_B) {
+		/* Wait for switch to device mode */
+		dev_dbg(hsotg->dev, "connId B\n");
+		while (!dwc2_is_device_mode(hsotg)) {
+			dev_info(hsotg->dev,
+				 "Waiting for Peripheral Mode, Mode=%s\n",
+				 dwc2_is_host_mode(hsotg) ? "Host" :
+				 "Peripheral");
+			usleep_range(20000, 40000);
+			if (++count > 250)
+				break;
+		}
+		if (count > 250)
+			dev_err(hsotg->dev,
+				"Connection id status change timed out");
+		hsotg->op_state = OTG_STATE_B_PERIPHERAL;
+		dwc2_core_init(hsotg, false);
+		dwc2_enable_global_interrupts(hsotg);
+	} else {
+		/* A-Device connector (Host Mode) */
+		dev_dbg(hsotg->dev, "connId A\n");
+		while (!dwc2_is_host_mode(hsotg)) {
+			dev_info(hsotg->dev, "Waiting for Host Mode, Mode=%s\n",
+				 dwc2_is_host_mode(hsotg) ?
+				 "Host" : "Peripheral");
+			usleep_range(20000, 40000);
+			if (++count > 250)
+				break;
+		}
+		if (count > 250)
+			dev_err(hsotg->dev,
+				"Connection id status change timed out");
+		hsotg->op_state = OTG_STATE_A_HOST;
+
+		/* Initialize the Core for Host mode */
+		dwc2_core_init(hsotg, false);
+		dwc2_enable_global_interrupts(hsotg);
+		dwc2_hcd_start(hsotg);
+	}
+}
+
+static void dwc2_wakeup_detected(unsigned long data)
+{
+	struct dwc2_hsotg *hsotg = (struct dwc2_hsotg *)data;
+	u32 hprt0;
+
+	dev_dbg(hsotg->dev, "%s()\n", __func__);
+
+	/*
+	 * Clear the Resume after 70ms. (Need 20 ms minimum. Use 70 ms
+	 * so that OPT tests pass with all PHYs.)
+	 */
+	hprt0 = dwc2_read_hprt0(hsotg);
+	dev_dbg(hsotg->dev, "Resume: HPRT0=%0x\n", hprt0);
+	hprt0 &= ~HPRT0_RES;
+	writel(hprt0, hsotg->regs + HPRT0);
+	dev_dbg(hsotg->dev, "Clear Resume: HPRT0=%0x\n",
+		readl(hsotg->regs + HPRT0));
+
+	dwc2_hcd_rem_wakeup(hsotg);
+
+	/* Change to L0 state */
+	hsotg->lx_state = DWC2_L0;
+}
+
+static int dwc2_host_is_b_hnp_enabled(struct dwc2_hsotg *hsotg)
+{
+	struct usb_hcd *hcd = dwc2_hsotg_to_hcd(hsotg);
+
+	return hcd->self.b_hnp_enable;
+}
+
+/* Must NOT be called with interrupt disabled or spinlock held */
+static void dwc2_port_suspend(struct dwc2_hsotg *hsotg, u16 windex)
+{
+	unsigned long flags;
+	u32 hprt0;
+	u32 pcgctl;
+	u32 gotgctl;
+
+	dev_dbg(hsotg->dev, "%s()\n", __func__);
+
+	spin_lock_irqsave(&hsotg->lock, flags);
+
+	if (windex == hsotg->otg_port && dwc2_host_is_b_hnp_enabled(hsotg)) {
+		gotgctl = readl(hsotg->regs + GOTGCTL);
+		gotgctl |= GOTGCTL_HSTSETHNPEN;
+		writel(gotgctl, hsotg->regs + GOTGCTL);
+		hsotg->op_state = OTG_STATE_A_SUSPEND;
+	}
+
+	hprt0 = dwc2_read_hprt0(hsotg);
+	hprt0 |= HPRT0_SUSP;
+	writel(hprt0, hsotg->regs + HPRT0);
+
+	/* Update lx_state */
+	hsotg->lx_state = DWC2_L2;
+
+	/* Suspend the Phy Clock */
+	pcgctl = readl(hsotg->regs + PCGCTL);
+	pcgctl |= PCGCTL_STOPPCLK;
+	writel(pcgctl, hsotg->regs + PCGCTL);
+	udelay(10);
+
+	/* For HNP the bus must be suspended for at least 200ms */
+	if (dwc2_host_is_b_hnp_enabled(hsotg)) {
+		pcgctl = readl(hsotg->regs + PCGCTL);
+		pcgctl &= ~PCGCTL_STOPPCLK;
+		writel(pcgctl, hsotg->regs + PCGCTL);
+
+		spin_unlock_irqrestore(&hsotg->lock, flags);
+
+		usleep_range(200000, 250000);
+	} else {
+		spin_unlock_irqrestore(&hsotg->lock, flags);
+	}
+}
+
+/* Handles hub class-specific requests */
+static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq,
+				u16 wvalue, u16 windex, char *buf, u16 wlength)
+{
+	struct usb_hub_descriptor *hub_desc;
+	int retval = 0;
+	u32 hprt0;
+	u32 port_status;
+	u32 speed;
+	u32 pcgctl;
+
+	switch (typereq) {
+	case ClearHubFeature:
+		dev_dbg(hsotg->dev, "ClearHubFeature %1xh\n", wvalue);
+
+		switch (wvalue) {
+		case C_HUB_LOCAL_POWER:
+		case C_HUB_OVER_CURRENT:
+			/* Nothing required here */
+			break;
+
+		default:
+			retval = -EINVAL;
+			dev_err(hsotg->dev,
+				"ClearHubFeature request %1xh unknown\n",
+				wvalue);
+		}
+		break;
+
+	case ClearPortFeature:
+		if (wvalue != USB_PORT_FEAT_L1)
+			if (!windex || windex > 1)
+				goto error;
+		switch (wvalue) {
+		case USB_PORT_FEAT_ENABLE:
+			dev_dbg(hsotg->dev,
+				"ClearPortFeature USB_PORT_FEAT_ENABLE\n");
+			hprt0 = dwc2_read_hprt0(hsotg);
+			hprt0 |= HPRT0_ENA;
+			writel(hprt0, hsotg->regs + HPRT0);
+			break;
+
+		case USB_PORT_FEAT_SUSPEND:
+			dev_dbg(hsotg->dev,
+				"ClearPortFeature USB_PORT_FEAT_SUSPEND\n");
+			writel(0, hsotg->regs + PCGCTL);
+			usleep_range(20000, 40000);
+
+			hprt0 = dwc2_read_hprt0(hsotg);
+			hprt0 |= HPRT0_RES;
+			writel(hprt0, hsotg->regs + HPRT0);
+			hprt0 &= ~HPRT0_SUSP;
+			usleep_range(100000, 150000);
+
+			hprt0 &= ~HPRT0_RES;
+			writel(hprt0, hsotg->regs + HPRT0);
+			break;
+
+		case USB_PORT_FEAT_POWER:
+			dev_dbg(hsotg->dev,
+				"ClearPortFeature USB_PORT_FEAT_POWER\n");
+			hprt0 = dwc2_read_hprt0(hsotg);
+			hprt0 &= ~HPRT0_PWR;
+			writel(hprt0, hsotg->regs + HPRT0);
+			break;
+
+		case USB_PORT_FEAT_INDICATOR:
+			dev_dbg(hsotg->dev,
+				"ClearPortFeature USB_PORT_FEAT_INDICATOR\n");
+			/* Port indicator not supported */
+			break;
+
+		case USB_PORT_FEAT_C_CONNECTION:
+			/*
+			 * Clears driver's internal Connect Status Change flag
+			 */
+			dev_dbg(hsotg->dev,
+				"ClearPortFeature USB_PORT_FEAT_C_CONNECTION\n");
+			hsotg->flags.b.port_connect_status_change = 0;
+			break;
+
+		case USB_PORT_FEAT_C_RESET:
+			/* Clears driver's internal Port Reset Change flag */
+			dev_dbg(hsotg->dev,
+				"ClearPortFeature USB_PORT_FEAT_C_RESET\n");
+			hsotg->flags.b.port_reset_change = 0;
+			break;
+
+		case USB_PORT_FEAT_C_ENABLE:
+			/*
+			 * Clears the driver's internal Port Enable/Disable
+			 * Change flag
+			 */
+			dev_dbg(hsotg->dev,
+				"ClearPortFeature USB_PORT_FEAT_C_ENABLE\n");
+			hsotg->flags.b.port_enable_change = 0;
+			break;
+
+		case USB_PORT_FEAT_C_SUSPEND:
+			/*
+			 * Clears the driver's internal Port Suspend Change
+			 * flag, which is set when resume signaling on the host
+			 * port is complete
+			 */
+			dev_dbg(hsotg->dev,
+				"ClearPortFeature USB_PORT_FEAT_C_SUSPEND\n");
+			hsotg->flags.b.port_suspend_change = 0;
+			break;
+
+		case USB_PORT_FEAT_C_PORT_L1:
+			dev_dbg(hsotg->dev,
+				"ClearPortFeature USB_PORT_FEAT_C_PORT_L1\n");
+			hsotg->flags.b.port_l1_change = 0;
+			break;
+
+		case USB_PORT_FEAT_C_OVER_CURRENT:
+			dev_dbg(hsotg->dev,
+				"ClearPortFeature USB_PORT_FEAT_C_OVER_CURRENT\n");
+			hsotg->flags.b.port_over_current_change = 0;
+			break;
+
+		default:
+			retval = -EINVAL;
+			dev_err(hsotg->dev,
+				"ClearPortFeature request %1xh unknown or unsupported\n",
+				wvalue);
+		}
+		break;
+
+	case GetHubDescriptor:
+		dev_dbg(hsotg->dev, "GetHubDescriptor\n");
+		hub_desc = (struct usb_hub_descriptor *)buf;
+		hub_desc->bDescLength = 9;
+		hub_desc->bDescriptorType = 0x29;
+		hub_desc->bNbrPorts = 1;
+		hub_desc->wHubCharacteristics = cpu_to_le16(0x08);
+		hub_desc->bPwrOn2PwrGood = 1;
+		hub_desc->bHubContrCurrent = 0;
+		hub_desc->u.hs.DeviceRemovable[0] = 0;
+		hub_desc->u.hs.DeviceRemovable[1] = 0xff;
+		break;
+
+	case GetHubStatus:
+		dev_dbg(hsotg->dev, "GetHubStatus\n");
+		memset(buf, 0, 4);
+		break;
+
+	case GetPortStatus:
+		dev_dbg(hsotg->dev,
+			"GetPortStatus wIndex=0x%04x flags=0x%08x\n", windex,
+			hsotg->flags.d32);
+		if (!windex || windex > 1)
+			goto error;
+
+		port_status = 0;
+		if (hsotg->flags.b.port_connect_status_change)
+			port_status |= USB_PORT_STAT_C_CONNECTION << 16;
+		if (hsotg->flags.b.port_enable_change)
+			port_status |= USB_PORT_STAT_C_ENABLE << 16;
+		if (hsotg->flags.b.port_suspend_change)
+			port_status |= USB_PORT_STAT_C_SUSPEND << 16;
+		if (hsotg->flags.b.port_l1_change)
+			port_status |= USB_PORT_STAT_C_L1 << 16;
+		if (hsotg->flags.b.port_reset_change)
+			port_status |= USB_PORT_STAT_C_RESET << 16;
+		if (hsotg->flags.b.port_over_current_change) {
+			dev_warn(hsotg->dev, "Overcurrent change detected\n");
+			port_status |= USB_PORT_STAT_C_OVERCURRENT << 16;
+		}
+
+		if (!hsotg->flags.b.port_connect_status) {
+			/*
+			 * The port is disconnected, which means the core is
+			 * either in device mode or it soon will be. Just
+			 * return 0's for the remainder of the port status
+			 * since the port register can't be read if the core
+			 * is in device mode.
+			 */
+			*(__le32 *)buf = cpu_to_le32(port_status);
+			break;
+		}
+
+		hprt0 = readl(hsotg->regs + HPRT0);
+		dev_dbg(hsotg->dev, "  HPRT0: 0x%08x\n", hprt0);
+
+		if (hprt0 & HPRT0_CONNSTS)
+			port_status |= USB_PORT_STAT_CONNECTION;
+		if (hprt0 & HPRT0_ENA)
+			port_status |= USB_PORT_STAT_ENABLE;
+		if (hprt0 & HPRT0_SUSP)
+			port_status |= USB_PORT_STAT_SUSPEND;
+		if (hprt0 & HPRT0_OVRCURRACT)
+			port_status |= USB_PORT_STAT_OVERCURRENT;
+		if (hprt0 & HPRT0_RST)
+			port_status |= USB_PORT_STAT_RESET;
+		if (hprt0 & HPRT0_PWR)
+			port_status |= USB_PORT_STAT_POWER;
+
+		speed = hprt0 & HPRT0_SPD_MASK;
+		if (speed == HPRT0_SPD_HIGH_SPEED)
+			port_status |= USB_PORT_STAT_HIGH_SPEED;
+		else if (speed == HPRT0_SPD_LOW_SPEED)
+			port_status |= USB_PORT_STAT_LOW_SPEED;
+
+		if (hprt0 & HPRT0_TSTCTL_MASK)
+			port_status |= USB_PORT_STAT_TEST;
+		/* USB_PORT_FEAT_INDICATOR unsupported always 0 */
+
+		dev_dbg(hsotg->dev, "port_status=%08x\n", port_status);
+		*(__le32 *)buf = cpu_to_le32(port_status);
+		break;
+
+	case SetHubFeature:
+		dev_dbg(hsotg->dev, "SetHubFeature\n");
+		/* No HUB features supported */
+		break;
+
+	case SetPortFeature:
+		dev_dbg(hsotg->dev, "SetPortFeature\n");
+		if (wvalue != USB_PORT_FEAT_TEST && (!windex || windex > 1))
+			goto error;
+
+		if (!hsotg->flags.b.port_connect_status) {
+			/*
+			 * The port is disconnected, which means the core is
+			 * either in device mode or it soon will be. Just
+			 * return without doing anything since the port
+			 * register can't be written if the core is in device
+			 * mode.
+			 */
+			break;
+		}
+
+		switch (wvalue) {
+		case USB_PORT_FEAT_SUSPEND:
+			dev_dbg(hsotg->dev,
+				"SetPortFeature - USB_PORT_FEAT_SUSPEND\n");
+			if (windex != hsotg->otg_port)
+				goto error;
+			dwc2_port_suspend(hsotg, windex);
+			break;
+
+		case USB_PORT_FEAT_POWER:
+			dev_dbg(hsotg->dev,
+				"SetPortFeature - USB_PORT_FEAT_POWER\n");
+			hprt0 = dwc2_read_hprt0(hsotg);
+			hprt0 |= HPRT0_PWR;
+			writel(hprt0, hsotg->regs + HPRT0);
+			break;
+
+		case USB_PORT_FEAT_RESET:
+			hprt0 = dwc2_read_hprt0(hsotg);
+			dev_dbg(hsotg->dev,
+				"SetPortFeature - USB_PORT_FEAT_RESET\n");
+			pcgctl = readl(hsotg->regs + PCGCTL);
+			pcgctl &= ~(PCGCTL_ENBL_SLEEP_GATING | PCGCTL_STOPPCLK);
+			writel(pcgctl, hsotg->regs + PCGCTL);
+			/* ??? Original driver does this */
+			writel(0, hsotg->regs + PCGCTL);
+
+			hprt0 = dwc2_read_hprt0(hsotg);
+			/* Clear suspend bit if resetting from suspend state */
+			hprt0 &= ~HPRT0_SUSP;
+
+			/*
+			 * When B-Host the Port reset bit is set in the Start
+			 * HCD Callback function, so that the reset is started
+			 * within 1ms of the HNP success interrupt
+			 */
+			if (!dwc2_hcd_is_b_host(hsotg)) {
+				hprt0 |= HPRT0_PWR | HPRT0_RST;
+				dev_dbg(hsotg->dev,
+					"In host mode, hprt0=%08x\n", hprt0);
+				writel(hprt0, hsotg->regs + HPRT0);
+			}
+
+			/* Clear reset bit in 10ms (FS/LS) or 50ms (HS) */
+			usleep_range(50000, 70000);
+			hprt0 &= ~HPRT0_RST;
+			writel(hprt0, hsotg->regs + HPRT0);
+			hsotg->lx_state = DWC2_L0; /* Now back to On state */
+			break;
+
+		case USB_PORT_FEAT_INDICATOR:
+			dev_dbg(hsotg->dev,
+				"SetPortFeature - USB_PORT_FEAT_INDICATOR\n");
+			/* Not supported */
+			break;
+
+		default:
+			retval = -EINVAL;
+			dev_err(hsotg->dev,
+				"SetPortFeature %1xh unknown or unsupported\n",
+				wvalue);
+			break;
+		}
+		break;
+
+	default:
+error:
+		retval = -EINVAL;
+		dev_dbg(hsotg->dev,
+			"Unknown hub control request: %1xh wIndex: %1xh wValue: %1xh\n",
+			typereq, windex, wvalue);
+		break;
+	}
+
+	return retval;
+}
+
+static int dwc2_hcd_is_status_changed(struct dwc2_hsotg *hsotg, int port)
+{
+	int retval;
+
+	dev_vdbg(hsotg->dev, "%s()\n", __func__);
+
+	if (port != 1)
+		return -EINVAL;
+
+	retval = (hsotg->flags.b.port_connect_status_change ||
+		  hsotg->flags.b.port_reset_change ||
+		  hsotg->flags.b.port_enable_change ||
+		  hsotg->flags.b.port_suspend_change ||
+		  hsotg->flags.b.port_over_current_change);
+
+	if (retval) {
+		dev_dbg(hsotg->dev,
+			"DWC OTG HCD HUB STATUS DATA: Root port status changed\n");
+		dev_dbg(hsotg->dev, "  port_connect_status_change: %d\n",
+			hsotg->flags.b.port_connect_status_change);
+		dev_dbg(hsotg->dev, "  port_reset_change: %d\n",
+			hsotg->flags.b.port_reset_change);
+		dev_dbg(hsotg->dev, "  port_enable_change: %d\n",
+			hsotg->flags.b.port_enable_change);
+		dev_dbg(hsotg->dev, "  port_suspend_change: %d\n",
+			hsotg->flags.b.port_suspend_change);
+		dev_dbg(hsotg->dev, "  port_over_current_change: %d\n",
+			hsotg->flags.b.port_over_current_change);
+	}
+
+	return retval;
+}
+
+int dwc2_hcd_get_frame_number(struct dwc2_hsotg *hsotg)
+{
+	u32 hfnum = readl(hsotg->regs + HFNUM);
+
+#ifdef DWC2_DEBUG_SOF
+	dev_vdbg(hsotg->dev, "DWC OTG HCD GET FRAME NUMBER %d\n",
+		 hfnum >> HFNUM_FRNUM_SHIFT &
+		 HFNUM_FRNUM_MASK >> HFNUM_FRNUM_SHIFT);
+#endif
+	return hfnum >> HFNUM_FRNUM_SHIFT &
+	       HFNUM_FRNUM_MASK >> HFNUM_FRNUM_SHIFT;
+}
+
+int dwc2_hcd_is_b_host(struct dwc2_hsotg *hsotg)
+{
+	return (hsotg->op_state == OTG_STATE_B_HOST);
+}
+
+static struct dwc2_hcd_urb *dwc2_hcd_urb_alloc(struct dwc2_hsotg *hsotg,
+					       int iso_desc_count,
+					       gfp_t mem_flags)
+{
+	struct dwc2_hcd_urb *urb;
+	u32 size = sizeof(*urb) + iso_desc_count *
+		   sizeof(struct dwc2_hcd_iso_packet_desc);
+
+	urb = kzalloc(size, mem_flags);
+	if (urb)
+		urb->packet_count = iso_desc_count;
+	return urb;
+}
+
+static void dwc2_hcd_urb_set_pipeinfo(struct dwc2_hsotg *hsotg,
+				      struct dwc2_hcd_urb *urb, u8 dev_addr,
+				      u8 ep_num, u8 ep_type, u8 ep_dir, u16 mps)
+{
+	dev_vdbg(hsotg->dev,
+		 "addr=%d, ep_num=%d, ep_dir=%1x, ep_type=%1x, mps=%d\n",
+		 dev_addr, ep_num, ep_dir, ep_type, mps);
+	urb->pipe_info.dev_addr = dev_addr;
+	urb->pipe_info.ep_num = ep_num;
+	urb->pipe_info.pipe_type = ep_type;
+	urb->pipe_info.pipe_dir = ep_dir;
+	urb->pipe_info.mps = mps;
+}
+
+/*
+ * NOTE: This function will be removed once the peripheral controller code
+ * is integrated and the driver is stable
+ */
+void dwc2_hcd_dump_state(struct dwc2_hsotg *hsotg)
+{
+#ifdef DEBUG
+	struct dwc2_host_chan *chan;
+	struct dwc2_hcd_urb *urb;
+	struct dwc2_qtd *qtd;
+	int num_channels;
+	u32 np_tx_status;
+	u32 p_tx_status;
+	int i;
+
+	num_channels = hsotg->core_params->host_channels;
+	dev_dbg(hsotg->dev, "\n");
+	dev_dbg(hsotg->dev,
+		"************************************************************\n");
+	dev_dbg(hsotg->dev, "HCD State:\n");
+	dev_dbg(hsotg->dev, "  Num channels: %d\n", num_channels);
+
+	for (i = 0; i < num_channels; i++) {
+		chan = hsotg->hc_ptr_array[i];
+		dev_dbg(hsotg->dev, "  Channel %d:\n", i);
+		dev_dbg(hsotg->dev,
+			"    dev_addr: %d, ep_num: %d, ep_is_in: %d\n",
+			chan->dev_addr, chan->ep_num, chan->ep_is_in);
+		dev_dbg(hsotg->dev, "    speed: %d\n", chan->speed);
+		dev_dbg(hsotg->dev, "    ep_type: %d\n", chan->ep_type);
+		dev_dbg(hsotg->dev, "    max_packet: %d\n", chan->max_packet);
+		dev_dbg(hsotg->dev, "    data_pid_start: %d\n",
+			chan->data_pid_start);
+		dev_dbg(hsotg->dev, "    multi_count: %d\n", chan->multi_count);
+		dev_dbg(hsotg->dev, "    xfer_started: %d\n",
+			chan->xfer_started);
+		dev_dbg(hsotg->dev, "    xfer_buf: %p\n", chan->xfer_buf);
+		dev_dbg(hsotg->dev, "    xfer_dma: %08lx\n",
+			(unsigned long)chan->xfer_dma);
+		dev_dbg(hsotg->dev, "    xfer_len: %d\n", chan->xfer_len);
+		dev_dbg(hsotg->dev, "    xfer_count: %d\n", chan->xfer_count);
+		dev_dbg(hsotg->dev, "    halt_on_queue: %d\n",
+			chan->halt_on_queue);
+		dev_dbg(hsotg->dev, "    halt_pending: %d\n",
+			chan->halt_pending);
+		dev_dbg(hsotg->dev, "    halt_status: %d\n", chan->halt_status);
+		dev_dbg(hsotg->dev, "    do_split: %d\n", chan->do_split);
+		dev_dbg(hsotg->dev, "    complete_split: %d\n",
+			chan->complete_split);
+		dev_dbg(hsotg->dev, "    hub_addr: %d\n", chan->hub_addr);
+		dev_dbg(hsotg->dev, "    hub_port: %d\n", chan->hub_port);
+		dev_dbg(hsotg->dev, "    xact_pos: %d\n", chan->xact_pos);
+		dev_dbg(hsotg->dev, "    requests: %d\n", chan->requests);
+		dev_dbg(hsotg->dev, "    qh: %p\n", chan->qh);
+
+		if (chan->xfer_started) {
+			u32 hfnum, hcchar, hctsiz, hcint, hcintmsk;
+
+			hfnum = readl(hsotg->regs + HFNUM);
+			hcchar = readl(hsotg->regs + HCCHAR(i));
+			hctsiz = readl(hsotg->regs + HCTSIZ(i));
+			hcint = readl(hsotg->regs + HCINT(i));
+			hcintmsk = readl(hsotg->regs + HCINTMSK(i));
+			dev_dbg(hsotg->dev, "    hfnum: 0x%08x\n", hfnum);
+			dev_dbg(hsotg->dev, "    hcchar: 0x%08x\n", hcchar);
+			dev_dbg(hsotg->dev, "    hctsiz: 0x%08x\n", hctsiz);
+			dev_dbg(hsotg->dev, "    hcint: 0x%08x\n", hcint);
+			dev_dbg(hsotg->dev, "    hcintmsk: 0x%08x\n", hcintmsk);
+		}
+
+		if (!(chan->xfer_started && chan->qh))
+			continue;
+
+		list_for_each_entry(qtd, &chan->qh->qtd_list, qtd_list_entry) {
+			if (!qtd->in_process)
+				break;
+			urb = qtd->urb;
+			dev_dbg(hsotg->dev, "    URB Info:\n");
+			dev_dbg(hsotg->dev, "      qtd: %p, urb: %p\n",
+				qtd, urb);
+			if (urb) {
+				dev_dbg(hsotg->dev,
+					"      Dev: %d, EP: %d %s\n",
+					dwc2_hcd_get_dev_addr(&urb->pipe_info),
+					dwc2_hcd_get_ep_num(&urb->pipe_info),
+					dwc2_hcd_is_pipe_in(&urb->pipe_info) ?
+					"IN" : "OUT");
+				dev_dbg(hsotg->dev,
+					"      Max packet size: %d\n",
+					dwc2_hcd_get_mps(&urb->pipe_info));
+				dev_dbg(hsotg->dev,
+					"      transfer_buffer: %p\n",
+					urb->buf);
+				dev_dbg(hsotg->dev,
+					"      transfer_dma: %08lx\n",
+					(unsigned long)urb->dma);
+				dev_dbg(hsotg->dev,
+					"      transfer_buffer_length: %d\n",
+					urb->length);
+				dev_dbg(hsotg->dev, "      actual_length: %d\n",
+					urb->actual_length);
+			}
+		}
+	}
+
+	dev_dbg(hsotg->dev, "  non_periodic_channels: %d\n",
+		hsotg->non_periodic_channels);
+	dev_dbg(hsotg->dev, "  periodic_channels: %d\n",
+		hsotg->periodic_channels);
+	dev_dbg(hsotg->dev, "  periodic_usecs: %d\n", hsotg->periodic_usecs);
+	np_tx_status = readl(hsotg->regs + GNPTXSTS);
+	dev_dbg(hsotg->dev, "  NP Tx Req Queue Space Avail: %d\n",
+		np_tx_status >> TXSTS_QSPCAVAIL_SHIFT &
+		TXSTS_QSPCAVAIL_MASK >> TXSTS_QSPCAVAIL_SHIFT);
+	dev_dbg(hsotg->dev, "  NP Tx FIFO Space Avail: %d\n",
+		np_tx_status >> TXSTS_FSPCAVAIL_SHIFT &
+		TXSTS_FSPCAVAIL_MASK >> TXSTS_FSPCAVAIL_SHIFT);
+	p_tx_status = readl(hsotg->regs + HPTXSTS);
+	dev_dbg(hsotg->dev, "  P Tx Req Queue Space Avail: %d\n",
+		p_tx_status >> TXSTS_QSPCAVAIL_SHIFT &
+		TXSTS_QSPCAVAIL_MASK >> TXSTS_QSPCAVAIL_SHIFT);
+	dev_dbg(hsotg->dev, "  P Tx FIFO Space Avail: %d\n",
+		p_tx_status >> TXSTS_FSPCAVAIL_SHIFT &
+		TXSTS_FSPCAVAIL_MASK >> TXSTS_FSPCAVAIL_SHIFT);
+	dwc2_hcd_dump_frrem(hsotg);
+	dwc2_dump_global_registers(hsotg);
+	dwc2_dump_host_registers(hsotg);
+	dev_dbg(hsotg->dev,
+		"************************************************************\n");
+	dev_dbg(hsotg->dev, "\n");
+#endif
+}
+
+/*
+ * NOTE: This function will be removed once the peripheral controller code
+ * is integrated and the driver is stable
+ */
+void dwc2_hcd_dump_frrem(struct dwc2_hsotg *hsotg)
+{
+#ifdef DWC2_DUMP_FRREM
+	dev_dbg(hsotg->dev, "Frame remaining at SOF:\n");
+	dev_dbg(hsotg->dev, "  samples %u, accum %llu, avg %llu\n",
+		hsotg->frrem_samples, hsotg->frrem_accum,
+		hsotg->frrem_samples > 0 ?
+		hsotg->frrem_accum / hsotg->frrem_samples : 0);
+	dev_dbg(hsotg->dev, "\n");
+	dev_dbg(hsotg->dev, "Frame remaining at start_transfer (uframe 7):\n");
+	dev_dbg(hsotg->dev, "  samples %u, accum %llu, avg %llu\n",
+		hsotg->hfnum_7_samples,
+		hsotg->hfnum_7_frrem_accum,
+		hsotg->hfnum_7_samples > 0 ?
+		hsotg->hfnum_7_frrem_accum / hsotg->hfnum_7_samples : 0);
+	dev_dbg(hsotg->dev, "Frame remaining at start_transfer (uframe 0):\n");
+	dev_dbg(hsotg->dev, "  samples %u, accum %llu, avg %llu\n",
+		hsotg->hfnum_0_samples,
+		hsotg->hfnum_0_frrem_accum,
+		hsotg->hfnum_0_samples > 0 ?
+		hsotg->hfnum_0_frrem_accum / hsotg->hfnum_0_samples : 0);
+	dev_dbg(hsotg->dev, "Frame remaining at start_transfer (uframe 1-6):\n");
+	dev_dbg(hsotg->dev, "  samples %u, accum %llu, avg %llu\n",
+		hsotg->hfnum_other_samples,
+		hsotg->hfnum_other_frrem_accum,
+		hsotg->hfnum_other_samples > 0 ?
+		hsotg->hfnum_other_frrem_accum / hsotg->hfnum_other_samples :
+		0);
+	dev_dbg(hsotg->dev, "\n");
+	dev_dbg(hsotg->dev, "Frame remaining at sample point A (uframe 7):\n");
+	dev_dbg(hsotg->dev, "  samples %u, accum %llu, avg %llu\n",
+		hsotg->hfnum_7_samples_a, hsotg->hfnum_7_frrem_accum_a,
+		hsotg->hfnum_7_samples_a > 0 ?
+		hsotg->hfnum_7_frrem_accum_a / hsotg->hfnum_7_samples_a : 0);
+	dev_dbg(hsotg->dev, "Frame remaining at sample point A (uframe 0):\n");
+	dev_dbg(hsotg->dev, "  samples %u, accum %llu, avg %llu\n",
+		hsotg->hfnum_0_samples_a, hsotg->hfnum_0_frrem_accum_a,
+		hsotg->hfnum_0_samples_a > 0 ?
+		hsotg->hfnum_0_frrem_accum_a / hsotg->hfnum_0_samples_a : 0);
+	dev_dbg(hsotg->dev, "Frame remaining at sample point A (uframe 1-6):\n");
+	dev_dbg(hsotg->dev, "  samples %u, accum %llu, avg %llu\n",
+		hsotg->hfnum_other_samples_a, hsotg->hfnum_other_frrem_accum_a,
+		hsotg->hfnum_other_samples_a > 0 ?
+		hsotg->hfnum_other_frrem_accum_a / hsotg->hfnum_other_samples_a
+		: 0);
+	dev_dbg(hsotg->dev, "\n");
+	dev_dbg(hsotg->dev, "Frame remaining at sample point B (uframe 7):\n");
+	dev_dbg(hsotg->dev, "  samples %u, accum %llu, avg %llu\n",
+		hsotg->hfnum_7_samples_b, hsotg->hfnum_7_frrem_accum_b,
+		hsotg->hfnum_7_samples_b > 0 ?
+		hsotg->hfnum_7_frrem_accum_b / hsotg->hfnum_7_samples_b : 0);
+	dev_dbg(hsotg->dev, "Frame remaining at sample point B (uframe 0):\n");
+	dev_dbg(hsotg->dev, "  samples %u, accum %llu, avg %llu\n",
+		hsotg->hfnum_0_samples_b, hsotg->hfnum_0_frrem_accum_b,
+		(hsotg->hfnum_0_samples_b > 0) ?
+		hsotg->hfnum_0_frrem_accum_b / hsotg->hfnum_0_samples_b : 0);
+	dev_dbg(hsotg->dev, "Frame remaining at sample point B (uframe 1-6):\n");
+	dev_dbg(hsotg->dev, "  samples %u, accum %llu, avg %llu\n",
+		hsotg->hfnum_other_samples_b, hsotg->hfnum_other_frrem_accum_b,
+		(hsotg->hfnum_other_samples_b > 0) ?
+		hsotg->hfnum_other_frrem_accum_b / hsotg->hfnum_other_samples_b
+		: 0);
+#endif
+}
+
+struct wrapper_priv_data {
+	struct dwc2_hsotg *hsotg;
+};
+
+/* Gets the dwc2_hsotg from a usb_hcd */
+static struct dwc2_hsotg *dwc2_hcd_to_hsotg(struct usb_hcd *hcd)
+{
+	struct wrapper_priv_data *p;
+
+	p = (struct wrapper_priv_data *) &hcd->hcd_priv;
+	return p->hsotg;
+}
+
+static int _dwc2_hcd_start(struct usb_hcd *hcd);
+
+void dwc2_host_start(struct dwc2_hsotg *hsotg)
+{
+	struct usb_hcd *hcd = dwc2_hsotg_to_hcd(hsotg);
+
+	hcd->self.is_b_host = dwc2_hcd_is_b_host(hsotg);
+	_dwc2_hcd_start(hcd);
+}
+
+void dwc2_host_disconnect(struct dwc2_hsotg *hsotg)
+{
+	struct usb_hcd *hcd = dwc2_hsotg_to_hcd(hsotg);
+
+	hcd->self.is_b_host = 0;
+}
+
+void dwc2_host_hub_info(struct dwc2_hsotg *hsotg, void *context, int *hub_addr,
+			int *hub_port)
+{
+	struct urb *urb = context;
+
+	if (urb->dev->tt)
+		*hub_addr = urb->dev->tt->hub->devnum;
+	else
+		*hub_addr = 0;
+	*hub_port = urb->dev->ttport;
+}
+
+int dwc2_host_get_speed(struct dwc2_hsotg *hsotg, void *context)
+{
+	struct urb *urb = context;
+
+	return urb->dev->speed;
+}
+
+static void dwc2_allocate_bus_bandwidth(struct usb_hcd *hcd, u16 bw,
+					struct urb *urb)
+{
+	struct usb_bus *bus = hcd_to_bus(hcd);
+
+	if (urb->interval)
+		bus->bandwidth_allocated += bw / urb->interval;
+	if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS)
+		bus->bandwidth_isoc_reqs++;
+	else
+		bus->bandwidth_int_reqs++;
+}
+
+static void dwc2_free_bus_bandwidth(struct usb_hcd *hcd, u16 bw,
+				    struct urb *urb)
+{
+	struct usb_bus *bus = hcd_to_bus(hcd);
+
+	if (urb->interval)
+		bus->bandwidth_allocated -= bw / urb->interval;
+	if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS)
+		bus->bandwidth_isoc_reqs--;
+	else
+		bus->bandwidth_int_reqs--;
+}
+
+/*
+ * Sets the final status of an URB and returns it to the upper layer. Any
+ * required cleanup of the URB is performed.
+ *
+ * Must be called with interrupt disabled and spinlock held
+ */
+void dwc2_host_complete(struct dwc2_hsotg *hsotg, void *context,
+			struct dwc2_hcd_urb *dwc2_urb, int status)
+{
+	struct urb *urb = context;
+	int i;
+
+	if (!urb) {
+		dev_dbg(hsotg->dev, "## %s: context is NULL ##\n", __func__);
+		return;
+	}
+
+	if (!dwc2_urb) {
+		dev_dbg(hsotg->dev, "## %s: dwc2_urb is NULL ##\n", __func__);
+		return;
+	}
+
+	urb->actual_length = dwc2_hcd_urb_get_actual_length(dwc2_urb);
+
+	dev_vdbg(hsotg->dev,
+		 "%s: urb %p device %d ep %d-%s status %d actual %d\n",
+		 __func__, urb, usb_pipedevice(urb->pipe),
+		 usb_pipeendpoint(urb->pipe),
+		 usb_pipein(urb->pipe) ? "IN" : "OUT", status,
+		 urb->actual_length);
+
+	if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
+		for (i = 0; i < urb->number_of_packets; i++)
+			dev_vdbg(hsotg->dev, " ISO Desc %d status %d\n",
+				 i, urb->iso_frame_desc[i].status);
+	}
+
+	if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
+		urb->error_count = dwc2_hcd_urb_get_error_count(dwc2_urb);
+		for (i = 0; i < urb->number_of_packets; ++i) {
+			urb->iso_frame_desc[i].actual_length =
+				dwc2_hcd_urb_get_iso_desc_actual_length(
+						dwc2_urb, i);
+			urb->iso_frame_desc[i].status =
+				dwc2_hcd_urb_get_iso_desc_status(dwc2_urb, i);
+		}
+	}
+
+	urb->status = status;
+	urb->hcpriv = NULL;
+	if (!status) {
+		if ((urb->transfer_flags & URB_SHORT_NOT_OK) &&
+		    urb->actual_length < urb->transfer_buffer_length)
+			urb->status = -EREMOTEIO;
+	}
+
+	if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS ||
+	    usb_pipetype(urb->pipe) == PIPE_INTERRUPT) {
+		struct usb_host_endpoint *ep = urb->ep;
+
+		if (ep)
+			dwc2_free_bus_bandwidth(dwc2_hsotg_to_hcd(hsotg),
+					dwc2_hcd_get_ep_bandwidth(hsotg, ep),
+					urb);
+	}
+
+	kfree(dwc2_urb);
+
+	spin_unlock(&hsotg->lock);
+	usb_hcd_giveback_urb(dwc2_hsotg_to_hcd(hsotg), urb, status);
+	spin_lock(&hsotg->lock);
+}
+
+/*
+ * Work queue function for starting the HCD when A-Cable is connected
+ */
+static void dwc2_hcd_start_func(struct work_struct *work)
+{
+	struct dwc2_hsotg *hsotg = container_of(work, struct dwc2_hsotg,
+						start_work.work);
+
+	dev_dbg(hsotg->dev, "%s() %p\n", __func__, hsotg);
+	dwc2_host_start(hsotg);
+}
+
+/*
+ * Reset work queue function
+ */
+static void dwc2_hcd_reset_func(struct work_struct *work)
+{
+	struct dwc2_hsotg *hsotg = container_of(work, struct dwc2_hsotg,
+						reset_work.work);
+	u32 hprt0;
+
+	dev_dbg(hsotg->dev, "USB RESET function called\n");
+	hprt0 = dwc2_read_hprt0(hsotg);
+	hprt0 &= ~HPRT0_RST;
+	writel(hprt0, hsotg->regs + HPRT0);
+	hsotg->flags.b.port_reset_change = 1;
+}
+
+/*
+ * =========================================================================
+ *  Linux HC Driver Functions
+ * =========================================================================
+ */
+
+/*
+ * Initializes the DWC_otg controller and its root hub and prepares it for host
+ * mode operation. Activates the root port. Returns 0 on success and a negative
+ * error code on failure.
+ */
+static int _dwc2_hcd_start(struct usb_hcd *hcd)
+{
+	struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd);
+	struct usb_bus *bus = hcd_to_bus(hcd);
+	unsigned long flags;
+
+	dev_dbg(hsotg->dev, "DWC OTG HCD START\n");
+
+	spin_lock_irqsave(&hsotg->lock, flags);
+
+	hcd->state = HC_STATE_RUNNING;
+
+	if (dwc2_is_device_mode(hsotg)) {
+		spin_unlock_irqrestore(&hsotg->lock, flags);
+		return 0;	/* why 0 ?? */
+	}
+
+	dwc2_hcd_reinit(hsotg);
+
+	/* Initialize and connect root hub if one is not already attached */
+	if (bus->root_hub) {
+		dev_dbg(hsotg->dev, "DWC OTG HCD Has Root Hub\n");
+		/* Inform the HUB driver to resume */
+		usb_hcd_resume_root_hub(hcd);
+	}
+
+	spin_unlock_irqrestore(&hsotg->lock, flags);
+	return 0;
+}
+
+/*
+ * Halts the DWC_otg host mode operations in a clean manner. USB transfers are
+ * stopped.
+ */
+static void _dwc2_hcd_stop(struct usb_hcd *hcd)
+{
+	struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd);
+	unsigned long flags;
+
+	spin_lock_irqsave(&hsotg->lock, flags);
+	dwc2_hcd_stop(hsotg);
+	spin_unlock_irqrestore(&hsotg->lock, flags);
+
+	usleep_range(1000, 3000);
+}
+
+/* Returns the current frame number */
+static int _dwc2_hcd_get_frame_number(struct usb_hcd *hcd)
+{
+	struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd);
+
+	return dwc2_hcd_get_frame_number(hsotg);
+}
+
+static void dwc2_dump_urb_info(struct usb_hcd *hcd, struct urb *urb,
+			       char *fn_name)
+{
+#ifdef VERBOSE_DEBUG
+	struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd);
+	char *pipetype;
+	char *speed;
+
+	dev_vdbg(hsotg->dev, "%s, urb %p\n", fn_name, urb);
+	dev_vdbg(hsotg->dev, "  Device address: %d\n",
+		 usb_pipedevice(urb->pipe));
+	dev_vdbg(hsotg->dev, "  Endpoint: %d, %s\n",
+		 usb_pipeendpoint(urb->pipe),
+		 usb_pipein(urb->pipe) ? "IN" : "OUT");
+
+	switch (usb_pipetype(urb->pipe)) {
+	case PIPE_CONTROL:
+		pipetype = "CONTROL";
+		break;
+	case PIPE_BULK:
+		pipetype = "BULK";
+		break;
+	case PIPE_INTERRUPT:
+		pipetype = "INTERRUPT";
+		break;
+	case PIPE_ISOCHRONOUS:
+		pipetype = "ISOCHRONOUS";
+		break;
+	default:
+		pipetype = "UNKNOWN";
+		break;
+	}
+
+	dev_vdbg(hsotg->dev, "  Endpoint type: %s %s (%s)\n", pipetype,
+		 usb_urb_dir_in(urb) ? "IN" : "OUT", usb_pipein(urb->pipe) ?
+		 "IN" : "OUT");
+
+	switch (urb->dev->speed) {
+	case USB_SPEED_HIGH:
+		speed = "HIGH";
+		break;
+	case USB_SPEED_FULL:
+		speed = "FULL";
+		break;
+	case USB_SPEED_LOW:
+		speed = "LOW";
+		break;
+	default:
+		speed = "UNKNOWN";
+		break;
+	}
+
+	dev_vdbg(hsotg->dev, "  Speed: %s\n", speed);
+	dev_vdbg(hsotg->dev, "  Max packet size: %d\n",
+		 usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)));
+	dev_vdbg(hsotg->dev, "  Data buffer length: %d\n",
+		 urb->transfer_buffer_length);
+	dev_vdbg(hsotg->dev, "  Transfer buffer: %p, Transfer DMA: %08lx\n",
+		 urb->transfer_buffer, (unsigned long)urb->transfer_dma);
+	dev_vdbg(hsotg->dev, "  Setup buffer: %p, Setup DMA: %08lx\n",
+		 urb->setup_packet, (unsigned long)urb->setup_dma);
+	dev_vdbg(hsotg->dev, "  Interval: %d\n", urb->interval);
+
+	if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
+		int i;
+
+		for (i = 0; i < urb->number_of_packets; i++) {
+			dev_vdbg(hsotg->dev, "  ISO Desc %d:\n", i);
+			dev_vdbg(hsotg->dev, "    offset: %d, length %d\n",
+				 urb->iso_frame_desc[i].offset,
+				 urb->iso_frame_desc[i].length);
+		}
+	}
+#endif
+}
+
+/*
+ * Starts processing a USB transfer request specified by a USB Request Block
+ * (URB). mem_flags indicates the type of memory allocation to use while
+ * processing this URB.
+ */
+static int _dwc2_hcd_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
+				 gfp_t mem_flags)
+{
+	struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd);
+	struct usb_host_endpoint *ep = urb->ep;
+	struct dwc2_hcd_urb *dwc2_urb;
+	int i;
+	int alloc_bandwidth = 0;
+	int retval = 0;
+	u8 ep_type = 0;
+	u32 tflags = 0;
+	void *buf;
+	unsigned long flags;
+
+	dev_vdbg(hsotg->dev, "DWC OTG HCD URB Enqueue\n");
+	dwc2_dump_urb_info(hcd, urb, "urb_enqueue");
+
+	if (ep == NULL)
+		return -EINVAL;
+
+	if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS ||
+	    usb_pipetype(urb->pipe) == PIPE_INTERRUPT) {
+		spin_lock_irqsave(&hsotg->lock, flags);
+		if (!dwc2_hcd_is_bandwidth_allocated(hsotg, ep))
+			alloc_bandwidth = 1;
+		spin_unlock_irqrestore(&hsotg->lock, flags);
+	}
+
+	switch (usb_pipetype(urb->pipe)) {
+	case PIPE_CONTROL:
+		ep_type = USB_ENDPOINT_XFER_CONTROL;
+		break;
+	case PIPE_ISOCHRONOUS:
+		ep_type = USB_ENDPOINT_XFER_ISOC;
+		break;
+	case PIPE_BULK:
+		ep_type = USB_ENDPOINT_XFER_BULK;
+		break;
+	case PIPE_INTERRUPT:
+		ep_type = USB_ENDPOINT_XFER_INT;
+		break;
+	default:
+		dev_warn(hsotg->dev, "Wrong ep type\n");
+	}
+
+	dwc2_urb = dwc2_hcd_urb_alloc(hsotg, urb->number_of_packets,
+				      mem_flags);
+	if (!dwc2_urb)
+		return -ENOMEM;
+
+	dwc2_hcd_urb_set_pipeinfo(hsotg, dwc2_urb, usb_pipedevice(urb->pipe),
+				  usb_pipeendpoint(urb->pipe), ep_type,
+				  usb_pipein(urb->pipe),
+				  usb_maxpacket(urb->dev, urb->pipe,
+						!(usb_pipein(urb->pipe))));
+
+	buf = urb->transfer_buffer;
+	if (hcd->self.uses_dma) {
+		/*
+		 * Calculate virtual address from physical address, because
+		 * some class driver may not fill transfer_buffer.
+		 * In Buffer DMA mode virtual address is used, when handling
+		 * non-DWORD aligned buffers.
+		 */
+		buf = bus_to_virt(urb->transfer_dma);
+	}
+
+	if (!(urb->transfer_flags & URB_NO_INTERRUPT))
+		tflags |= URB_GIVEBACK_ASAP;
+	if (urb->transfer_flags & URB_ZERO_PACKET)
+		tflags |= URB_SEND_ZERO_PACKET;
+
+	dwc2_urb->priv = urb;
+	dwc2_urb->buf = buf;
+	dwc2_urb->dma = urb->transfer_dma;
+	dwc2_urb->length = urb->transfer_buffer_length;
+	dwc2_urb->setup_packet = urb->setup_packet;
+	dwc2_urb->setup_dma = urb->setup_dma;
+	dwc2_urb->flags = tflags;
+	dwc2_urb->interval = urb->interval;
+	dwc2_urb->status = -EINPROGRESS;
+
+	for (i = 0; i < urb->number_of_packets; ++i)
+		dwc2_hcd_urb_set_iso_desc_params(dwc2_urb, i,
+						 urb->iso_frame_desc[i].offset,
+						 urb->iso_frame_desc[i].length);
+
+	urb->hcpriv = dwc2_urb;
+	retval = dwc2_hcd_urb_enqueue(hsotg, dwc2_urb, &ep->hcpriv,
+				      mem_flags);
+	if (retval) {
+		urb->hcpriv = NULL;
+		kfree(dwc2_urb);
+	} else {
+		if (alloc_bandwidth) {
+			spin_lock_irqsave(&hsotg->lock, flags);
+			dwc2_allocate_bus_bandwidth(hcd,
+					dwc2_hcd_get_ep_bandwidth(hsotg, ep),
+					urb);
+			spin_unlock_irqrestore(&hsotg->lock, flags);
+		}
+	}
+
+	return retval;
+}
+
+/*
+ * Aborts/cancels a USB transfer request. Always returns 0 to indicate success.
+ */
+static int _dwc2_hcd_urb_dequeue(struct usb_hcd *hcd, struct urb *urb,
+				 int status)
+{
+	struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd);
+	int rc = 0;
+	unsigned long flags;
+
+	dev_dbg(hsotg->dev, "DWC OTG HCD URB Dequeue\n");
+	dwc2_dump_urb_info(hcd, urb, "urb_dequeue");
+
+	spin_lock_irqsave(&hsotg->lock, flags);
+
+	if (!urb->hcpriv) {
+		dev_dbg(hsotg->dev, "## urb->hcpriv is NULL ##\n");
+		goto out;
+	}
+
+	rc = dwc2_hcd_urb_dequeue(hsotg, urb->hcpriv);
+
+	kfree(urb->hcpriv);
+	urb->hcpriv = NULL;
+
+	/* Higher layer software sets URB status */
+	spin_unlock(&hsotg->lock);
+	usb_hcd_giveback_urb(hcd, urb, status);
+	spin_lock(&hsotg->lock);
+
+	dev_dbg(hsotg->dev, "Called usb_hcd_giveback_urb()\n");
+	dev_dbg(hsotg->dev, "  urb->status = %d\n", urb->status);
+out:
+	spin_unlock_irqrestore(&hsotg->lock, flags);
+
+	return rc;
+}
+
+/*
+ * Frees resources in the DWC_otg controller related to a given endpoint. Also
+ * clears state in the HCD related to the endpoint. Any URBs for the endpoint
+ * must already be dequeued.
+ */
+static void _dwc2_hcd_endpoint_disable(struct usb_hcd *hcd,
+				       struct usb_host_endpoint *ep)
+{
+	struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd);
+
+	dev_dbg(hsotg->dev,
+		"DWC OTG HCD EP DISABLE: bEndpointAddress=0x%02x, ep->hcpriv=%p\n",
+		ep->desc.bEndpointAddress, ep->hcpriv);
+	dwc2_hcd_endpoint_disable(hsotg, ep, 250);
+}
+
+/*
+ * Resets endpoint specific parameter values, in current version used to reset
+ * the data toggle (as a WA). This function can be called from usb_clear_halt
+ * routine.
+ */
+static void _dwc2_hcd_endpoint_reset(struct usb_hcd *hcd,
+				     struct usb_host_endpoint *ep)
+{
+	struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd);
+	int is_control = usb_endpoint_xfer_control(&ep->desc);
+	int is_out = usb_endpoint_dir_out(&ep->desc);
+	int epnum = usb_endpoint_num(&ep->desc);
+	struct usb_device *udev;
+	unsigned long flags;
+
+	dev_dbg(hsotg->dev,
+		"DWC OTG HCD EP RESET: bEndpointAddress=0x%02x\n",
+		ep->desc.bEndpointAddress);
+
+	udev = to_usb_device(hsotg->dev);
+
+	spin_lock_irqsave(&hsotg->lock, flags);
+
+	usb_settoggle(udev, epnum, is_out, 0);
+	if (is_control)
+		usb_settoggle(udev, epnum, !is_out, 0);
+	dwc2_hcd_endpoint_reset(hsotg, ep);
+
+	spin_unlock_irqrestore(&hsotg->lock, flags);
+}
+
+/*
+ * Handles host mode interrupts for the DWC_otg controller. Returns IRQ_NONE if
+ * there was no interrupt to handle. Returns IRQ_HANDLED if there was a valid
+ * interrupt.
+ *
+ * This function is called by the USB core when an interrupt occurs
+ */
+static irqreturn_t _dwc2_hcd_irq(struct usb_hcd *hcd)
+{
+	struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd);
+	int retval = dwc2_hcd_intr(hsotg);
+
+	return IRQ_RETVAL(retval);
+}
+
+/*
+ * Creates Status Change bitmap for the root hub and root port. The bitmap is
+ * returned in buf. Bit 0 is the status change indicator for the root hub. Bit 1
+ * is the status change indicator for the single root port. Returns 1 if either
+ * change indicator is 1, otherwise returns 0.
+ */
+static int _dwc2_hcd_hub_status_data(struct usb_hcd *hcd, char *buf)
+{
+	struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd);
+
+	buf[0] = dwc2_hcd_is_status_changed(hsotg, 1) << 1;
+	return buf[0] != 0;
+}
+
+/* Handles hub class-specific requests */
+static int _dwc2_hcd_hub_control(struct usb_hcd *hcd, u16 typereq, u16 wvalue,
+				 u16 windex, char *buf, u16 wlength)
+{
+	int retval = dwc2_hcd_hub_control(dwc2_hcd_to_hsotg(hcd), typereq,
+					  wvalue, windex, buf, wlength);
+	return retval;
+}
+
+/* Handles hub TT buffer clear completions */
+static void _dwc2_hcd_clear_tt_buffer_complete(struct usb_hcd *hcd,
+					       struct usb_host_endpoint *ep)
+{
+	struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd);
+	struct dwc2_qh *qh;
+	unsigned long flags;
+
+	qh = ep->hcpriv;
+	if (!qh)
+		return;
+
+	spin_lock_irqsave(&hsotg->lock, flags);
+	qh->tt_buffer_dirty = 0;
+
+	if (hsotg->flags.b.port_connect_status)
+		dwc2_hcd_queue_transactions(hsotg, DWC2_TRANSACTION_ALL);
+
+	spin_unlock_irqrestore(&hsotg->lock, flags);
+}
+
+static struct hc_driver dwc2_hc_driver = {
+	.description = "dwc2_hsotg",
+	.product_desc = "DWC OTG Controller",
+	.hcd_priv_size = sizeof(struct wrapper_priv_data),
+
+	.irq = _dwc2_hcd_irq,
+	.flags = HCD_MEMORY | HCD_USB2,
+
+	.start = _dwc2_hcd_start,
+	.stop = _dwc2_hcd_stop,
+	.urb_enqueue = _dwc2_hcd_urb_enqueue,
+	.urb_dequeue = _dwc2_hcd_urb_dequeue,
+	.endpoint_disable = _dwc2_hcd_endpoint_disable,
+	.endpoint_reset = _dwc2_hcd_endpoint_reset,
+	.get_frame_number = _dwc2_hcd_get_frame_number,
+
+	.hub_status_data = _dwc2_hcd_hub_status_data,
+	.hub_control = _dwc2_hcd_hub_control,
+	.clear_tt_buffer_complete = _dwc2_hcd_clear_tt_buffer_complete,
+};
+
+/*
+ * Frees secondary storage associated with the dwc2_hsotg structure contained
+ * in the struct usb_hcd field
+ */
+static void dwc2_hcd_free(struct dwc2_hsotg *hsotg)
+{
+	u32 ahbcfg;
+	u32 dctl;
+	int i;
+
+	dev_dbg(hsotg->dev, "DWC OTG HCD FREE\n");
+
+	/* Free memory for QH/QTD lists */
+	dwc2_qh_list_free(hsotg, &hsotg->non_periodic_sched_inactive);
+	dwc2_qh_list_free(hsotg, &hsotg->non_periodic_sched_active);
+	dwc2_qh_list_free(hsotg, &hsotg->periodic_sched_inactive);
+	dwc2_qh_list_free(hsotg, &hsotg->periodic_sched_ready);
+	dwc2_qh_list_free(hsotg, &hsotg->periodic_sched_assigned);
+	dwc2_qh_list_free(hsotg, &hsotg->periodic_sched_queued);
+
+	/* Free memory for the host channels */
+	for (i = 0; i < MAX_EPS_CHANNELS; i++) {
+		struct dwc2_host_chan *chan = hsotg->hc_ptr_array[i];
+
+		if (chan != NULL) {
+			dev_dbg(hsotg->dev, "HCD Free channel #%i, chan=%p\n",
+				i, chan);
+			hsotg->hc_ptr_array[i] = NULL;
+			kfree(chan);
+		}
+	}
+
+	if (hsotg->core_params->dma_enable > 0) {
+		if (hsotg->status_buf) {
+			dma_free_coherent(hsotg->dev, DWC2_HCD_STATUS_BUF_SIZE,
+					  hsotg->status_buf,
+					  hsotg->status_buf_dma);
+			hsotg->status_buf = NULL;
+		}
+	} else {
+		kfree(hsotg->status_buf);
+		hsotg->status_buf = NULL;
+	}
+
+	ahbcfg = readl(hsotg->regs + GAHBCFG);
+
+	/* Disable all interrupts */
+	ahbcfg &= ~GAHBCFG_GLBL_INTR_EN;
+	writel(ahbcfg, hsotg->regs + GAHBCFG);
+	writel(0, hsotg->regs + GINTMSK);
+
+	if (hsotg->snpsid >= DWC2_CORE_REV_3_00a) {
+		dctl = readl(hsotg->regs + DCTL);
+		dctl |= DCTL_SFTDISCON;
+		writel(dctl, hsotg->regs + DCTL);
+	}
+
+	if (hsotg->wq_otg) {
+		if (!cancel_work_sync(&hsotg->wf_otg))
+			flush_workqueue(hsotg->wq_otg);
+		destroy_workqueue(hsotg->wq_otg);
+	}
+
+	kfree(hsotg->core_params);
+	hsotg->core_params = NULL;
+	del_timer(&hsotg->wkp_timer);
+}
+
+static void dwc2_hcd_release(struct dwc2_hsotg *hsotg)
+{
+	/* Turn off all host-specific interrupts */
+	dwc2_disable_host_interrupts(hsotg);
+
+	dwc2_hcd_free(hsotg);
+}
+
+static void dwc2_set_uninitialized(int *p, int size)
+{
+	int i;
+
+	for (i = 0; i < size; i++)
+		p[i] = -1;
+}
+
+/*
+ * Initializes the HCD. This function allocates memory for and initializes the
+ * static parts of the usb_hcd and dwc2_hsotg structures. It also registers the
+ * USB bus with the core and calls the hc_driver->start() function. It returns
+ * a negative error on failure.
+ */
+int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq,
+		  struct dwc2_core_params *params)
+{
+	struct usb_hcd *hcd;
+	struct dwc2_host_chan *channel;
+	u32 snpsid, gusbcfg, hcfg;
+	int i, num_channels;
+	int retval = -ENOMEM;
+
+	dev_dbg(hsotg->dev, "DWC OTG HCD INIT\n");
+
+	/*
+	 * Attempt to ensure this device is really a DWC_otg Controller.
+	 * Read and verify the GSNPSID register contents. The value should be
+	 * 0x45f42xxx or 0x45f43xxx, which corresponds to either "OT2" or "OT3",
+	 * as in "OTG version 2.xx" or "OTG version 3.xx".
+	 */
+	snpsid = readl(hsotg->regs + GSNPSID);
+	if ((snpsid & 0xfffff000) != 0x4f542000 &&
+	    (snpsid & 0xfffff000) != 0x4f543000) {
+		dev_err(hsotg->dev, "Bad value for GSNPSID: 0x%08x\n", snpsid);
+		retval = -ENODEV;
+		goto error1;
+	}
+
+	/*
+	 * Store the contents of the hardware configuration registers here for
+	 * easy access later
+	 */
+	hsotg->hwcfg1 = readl(hsotg->regs + GHWCFG1);
+	hsotg->hwcfg2 = readl(hsotg->regs + GHWCFG2);
+	hsotg->hwcfg3 = readl(hsotg->regs + GHWCFG3);
+	hsotg->hwcfg4 = readl(hsotg->regs + GHWCFG4);
+
+	dev_dbg(hsotg->dev, "hwcfg1=%08x\n", hsotg->hwcfg1);
+	dev_dbg(hsotg->dev, "hwcfg2=%08x\n", hsotg->hwcfg2);
+	dev_dbg(hsotg->dev, "hwcfg3=%08x\n", hsotg->hwcfg3);
+	dev_dbg(hsotg->dev, "hwcfg4=%08x\n", hsotg->hwcfg4);
+
+	/* Force host mode to get HPTXFSIZ exact power on value */
+	gusbcfg = readl(hsotg->regs + GUSBCFG);
+	gusbcfg |= GUSBCFG_FORCEHOSTMODE;
+	writel(gusbcfg, hsotg->regs + GUSBCFG);
+	usleep_range(100000, 150000);
+
+	hsotg->hptxfsiz = readl(hsotg->regs + HPTXFSIZ);
+	dev_dbg(hsotg->dev, "hptxfsiz=%08x\n", hsotg->hptxfsiz);
+	gusbcfg = readl(hsotg->regs + GUSBCFG);
+	gusbcfg &= ~GUSBCFG_FORCEHOSTMODE;
+	writel(gusbcfg, hsotg->regs + GUSBCFG);
+	usleep_range(100000, 150000);
+
+	hcfg = readl(hsotg->regs + HCFG);
+	dev_dbg(hsotg->dev, "hcfg=%08x\n", hcfg);
+	dev_dbg(hsotg->dev, "op_mode=%0x\n",
+		hsotg->hwcfg2 >> GHWCFG2_OP_MODE_SHIFT &
+		GHWCFG2_OP_MODE_MASK >> GHWCFG2_OP_MODE_SHIFT);
+	dev_dbg(hsotg->dev, "arch=%0x\n",
+		hsotg->hwcfg2 >> GHWCFG2_ARCHITECTURE_SHIFT &
+		GHWCFG2_ARCHITECTURE_MASK >> GHWCFG2_ARCHITECTURE_SHIFT);
+	dev_dbg(hsotg->dev, "num_dev_ep=%d\n",
+		hsotg->hwcfg2 >> GHWCFG2_NUM_DEV_EP_SHIFT &
+		GHWCFG2_NUM_DEV_EP_MASK >> GHWCFG2_NUM_DEV_EP_SHIFT);
+	dev_dbg(hsotg->dev, "max_host_chan=%d\n",
+		hsotg->hwcfg2 >> GHWCFG2_NUM_HOST_CHAN_SHIFT &
+		GHWCFG2_NUM_HOST_CHAN_MASK >> GHWCFG2_NUM_HOST_CHAN_SHIFT);
+	dev_dbg(hsotg->dev, "nonperio_tx_q_depth=0x%0x\n",
+		hsotg->hwcfg2 >> GHWCFG2_NONPERIO_TX_Q_DEPTH_SHIFT &
+		GHWCFG2_NONPERIO_TX_Q_DEPTH_MASK >>
+				GHWCFG2_NONPERIO_TX_Q_DEPTH_SHIFT);
+	dev_dbg(hsotg->dev, "host_perio_tx_q_depth=0x%0x\n",
+		hsotg->hwcfg2 >> GHWCFG2_HOST_PERIO_TX_Q_DEPTH_SHIFT &
+		GHWCFG2_HOST_PERIO_TX_Q_DEPTH_MASK >>
+				GHWCFG2_HOST_PERIO_TX_Q_DEPTH_SHIFT);
+	dev_dbg(hsotg->dev, "dev_token_q_depth=0x%0x\n",
+		hsotg->hwcfg2 >> GHWCFG2_DEV_TOKEN_Q_DEPTH_SHIFT &
+		GHWCFG3_XFER_SIZE_CNTR_WIDTH_MASK >>
+				GHWCFG3_XFER_SIZE_CNTR_WIDTH_SHIFT);
+
+#ifdef CONFIG_USB_DWC2_TRACK_MISSED_SOFS
+	hsotg->frame_num_array = kzalloc(sizeof(*hsotg->frame_num_array) *
+					 FRAME_NUM_ARRAY_SIZE, GFP_KERNEL);
+	if (!hsotg->frame_num_array)
+		goto error1;
+	hsotg->last_frame_num_array = kzalloc(
+			sizeof(*hsotg->last_frame_num_array) *
+			FRAME_NUM_ARRAY_SIZE, GFP_KERNEL);
+	if (!hsotg->last_frame_num_array)
+		goto error1;
+	hsotg->last_frame_num = HFNUM_MAX_FRNUM;
+#endif
+
+	hsotg->core_params = kzalloc(sizeof(*hsotg->core_params), GFP_KERNEL);
+	if (!hsotg->core_params)
+		goto error1;
+
+	dwc2_set_uninitialized((int *)hsotg->core_params,
+			       sizeof(*hsotg->core_params) / sizeof(int));
+
+	/* Validate parameter values */
+	dwc2_set_parameters(hsotg, params);
+
+	/* Set device flags indicating whether the HCD supports DMA */
+	if (hsotg->core_params->dma_enable > 0) {
+		if (dma_set_mask(hsotg->dev, DMA_BIT_MASK(31)) < 0)
+			dev_warn(hsotg->dev,
+				 "can't enable workaround for >2GB RAM\n");
+		if (dma_set_coherent_mask(hsotg->dev, DMA_BIT_MASK(31)) < 0)
+			dev_warn(hsotg->dev,
+				 "can't enable workaround for >2GB RAM\n");
+	} else {
+		dma_set_mask(hsotg->dev, 0);
+		dma_set_coherent_mask(hsotg->dev, 0);
+	}
+
+	hcd = usb_create_hcd(&dwc2_hc_driver, hsotg->dev, dev_name(hsotg->dev));
+	if (!hcd)
+		goto error1;
+
+	hcd->has_tt = 1;
+
+	spin_lock_init(&hsotg->lock);
+	((struct wrapper_priv_data *) &hcd->hcd_priv)->hsotg = hsotg;
+	hsotg->priv = hcd;
+
+	/* Initialize the DWC_otg core, and select the Phy type */
+	retval = dwc2_core_init(hsotg, true);
+	if (retval)
+		goto error2;
+
+	/*
+	 * Disable the global interrupt until all the interrupt handlers are
+	 * installed
+	 */
+	dwc2_disable_global_interrupts(hsotg);
+
+	/* Create new workqueue and init work */
+	hsotg->wq_otg = create_singlethread_workqueue("dwc_otg");
+	if (!hsotg->wq_otg) {
+		dev_err(hsotg->dev, "Failed to create workqueue\n");
+		goto error2;
+	}
+	INIT_WORK(&hsotg->wf_otg, dwc2_conn_id_status_change);
+
+	hsotg->snpsid = readl(hsotg->regs + GSNPSID);
+	dev_dbg(hsotg->dev, "Core Release: %1x.%1x%1x%1x\n",
+		hsotg->snpsid >> 12 & 0xf, hsotg->snpsid >> 8 & 0xf,
+		hsotg->snpsid >> 4 & 0xf, hsotg->snpsid & 0xf);
+
+	setup_timer(&hsotg->wkp_timer, dwc2_wakeup_detected,
+		    (unsigned long)hsotg);
+
+	/* Initialize the non-periodic schedule */
+	INIT_LIST_HEAD(&hsotg->non_periodic_sched_inactive);
+	INIT_LIST_HEAD(&hsotg->non_periodic_sched_active);
+
+	/* Initialize the periodic schedule */
+	INIT_LIST_HEAD(&hsotg->periodic_sched_inactive);
+	INIT_LIST_HEAD(&hsotg->periodic_sched_ready);
+	INIT_LIST_HEAD(&hsotg->periodic_sched_assigned);
+	INIT_LIST_HEAD(&hsotg->periodic_sched_queued);
+
+	/*
+	 * Create a host channel descriptor for each host channel implemented
+	 * in the controller. Initialize the channel descriptor array.
+	 */
+	INIT_LIST_HEAD(&hsotg->free_hc_list);
+	num_channels = hsotg->core_params->host_channels;
+	memset(&hsotg->hc_ptr_array[0], 0, sizeof(hsotg->hc_ptr_array));
+
+	for (i = 0; i < num_channels; i++) {
+		channel = kzalloc(sizeof(*channel), GFP_KERNEL);
+		if (channel == NULL)
+			goto error3;
+		channel->hc_num = i;
+		hsotg->hc_ptr_array[i] = channel;
+	}
+
+	/* Initialize hsotg start work */
+	INIT_DELAYED_WORK(&hsotg->start_work, dwc2_hcd_start_func);
+
+	/* Initialize port reset work */
+	INIT_DELAYED_WORK(&hsotg->reset_work, dwc2_hcd_reset_func);
+
+	/*
+	 * Allocate space for storing data on status transactions. Normally no
+	 * data is sent, but this space acts as a bit bucket. This must be
+	 * done after usb_add_hcd since that function allocates the DMA buffer
+	 * pool.
+	 */
+	if (hsotg->core_params->dma_enable > 0)
+		hsotg->status_buf = dma_alloc_coherent(hsotg->dev,
+					DWC2_HCD_STATUS_BUF_SIZE,
+					&hsotg->status_buf_dma, GFP_KERNEL);
+	else
+		hsotg->status_buf = kzalloc(DWC2_HCD_STATUS_BUF_SIZE,
+					  GFP_KERNEL);
+
+	if (!hsotg->status_buf)
+		goto error3;
+
+	hsotg->otg_port = 1;
+	hsotg->frame_list = NULL;
+	hsotg->frame_list_dma = 0;
+	hsotg->periodic_qh_count = 0;
+
+	/* Initiate lx_state to L3 disconnected state */
+	hsotg->lx_state = DWC2_L3;
+
+	hcd->self.otg_port = hsotg->otg_port;
+
+	/* Don't support SG list at this point */
+	hcd->self.sg_tablesize = 0;
+
+	/*
+	 * Finish generic HCD initialization and start the HCD. This function
+	 * allocates the DMA buffer pool, registers the USB bus, requests the
+	 * IRQ line, and calls hcd_start method.
+	 */
+	retval = usb_add_hcd(hcd, irq, IRQF_SHARED | IRQF_DISABLED);
+	if (retval < 0)
+		goto error3;
+
+	dwc2_dump_global_registers(hsotg);
+	dwc2_dump_host_registers(hsotg);
+	dwc2_hcd_dump_state(hsotg);
+
+	dwc2_enable_global_interrupts(hsotg);
+
+	return 0;
+
+error3:
+	dwc2_hcd_release(hsotg);
+error2:
+	usb_put_hcd(hcd);
+error1:
+	kfree(hsotg->core_params);
+
+#ifdef CONFIG_USB_DWC2_TRACK_MISSED_SOFS
+	kfree(hsotg->last_frame_num_array);
+	kfree(hsotg->frame_num_array);
+#endif
+
+	dev_err(hsotg->dev, "%s() FAILED, returning %d\n", __func__, retval);
+	return retval;
+}
+EXPORT_SYMBOL_GPL(dwc2_hcd_init);
+
+/*
+ * Removes the HCD.
+ * Frees memory and resources associated with the HCD and deregisters the bus.
+ */
+void dwc2_hcd_remove(struct dwc2_hsotg *hsotg)
+{
+	struct usb_hcd *hcd;
+
+	dev_dbg(hsotg->dev, "DWC OTG HCD REMOVE\n");
+
+	hcd = dwc2_hsotg_to_hcd(hsotg);
+	dev_dbg(hsotg->dev, "hsotg->hcd = %p\n", hcd);
+
+	if (!hcd) {
+		dev_dbg(hsotg->dev, "%s: dwc2_hsotg_to_hcd(hsotg) NULL!\n",
+			__func__);
+		return;
+	}
+
+	usb_remove_hcd(hcd);
+	hsotg->priv = NULL;
+	dwc2_hcd_release(hsotg);
+	usb_put_hcd(hcd);
+
+#ifdef CONFIG_USB_DWC2_TRACK_MISSED_SOFS
+	kfree(hsotg->last_frame_num_array);
+	kfree(hsotg->frame_num_array);
+#endif
+}
+EXPORT_SYMBOL_GPL(dwc2_hcd_remove);
diff --git a/drivers/staging/dwc2/hcd.h b/drivers/staging/dwc2/hcd.h
new file mode 100644
index 0000000..8a60dcf
--- /dev/null
+++ b/drivers/staging/dwc2/hcd.h
@@ -0,0 +1,737 @@
+/*
+ * hcd.h - DesignWare HS OTG Controller host-mode declarations
+ *
+ * Copyright (C) 2004-2013 Synopsys, Inc.
+ *
+ * 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, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 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 names of the above-listed copyright holders may not 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 the License, or (at your option) any
+ * later version.
+ *
+ * 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 __DWC2_HCD_H__
+#define __DWC2_HCD_H__
+
+/*
+ * This file contains the structures, constants, and interfaces for the
+ * Host Contoller Driver (HCD)
+ *
+ * The Host Controller Driver (HCD) is responsible for translating requests
+ * from the USB Driver into the appropriate actions on the DWC_otg controller.
+ * It isolates the USBD from the specifics of the controller by providing an
+ * API to the USBD.
+ */
+
+struct dwc2_qh;
+
+/**
+ * struct dwc2_host_chan - Software host channel descriptor
+ *
+ * @hc_num:             Host channel number, used for register address lookup
+ * @dev_addr:           Address of the device
+ * @ep_num:             Endpoint of the device
+ * @ep_is_in:           Endpoint direction
+ * @speed:              Device speed. One of the following values:
+ *                       - USB_SPEED_LOW
+ *                       - USB_SPEED_FULL
+ *                       - USB_SPEED_HIGH
+ * @ep_type:            Endpoint type. One of the following values:
+ *                       - USB_ENDPOINT_XFER_CONTROL: 0
+ *                       - USB_ENDPOINT_XFER_ISOC:    1
+ *                       - USB_ENDPOINT_XFER_BULK:    2
+ *                       - USB_ENDPOINT_XFER_INTR:    3
+ * @max_packet:         Max packet size in bytes
+ * @data_pid_start:     PID for initial transaction.
+ *                       0: DATA0
+ *                       1: DATA2
+ *                       2: DATA1
+ *                       3: MDATA (non-Control EP),
+ *                          SETUP (Control EP)
+ * @multi_count:        Number of additional periodic transactions per
+ *                      (micro)frame
+ * @xfer_buf:           Pointer to current transfer buffer position
+ * @xfer_dma:           DMA address of xfer_buf
+ * @align_buf:          In Buffer DMA mode this will be used if xfer_buf is not
+ *                      DWORD aligned
+ * @xfer_len:           Total number of bytes to transfer
+ * @xfer_count:         Number of bytes transferred so far
+ * @start_pkt_count:    Packet count at start of transfer
+ * @xfer_started:       True if the transfer has been started
+ * @ping:               True if a PING request should be issued on this channel
+ * @error_state:        True if the error count for this transaction is non-zero
+ * @halt_on_queue:      True if this channel should be halted the next time a
+ *                      request is queued for the channel. This is necessary in
+ *                      slave mode if no request queue space is available when
+ *                      an attempt is made to halt the channel.
+ * @halt_pending:       True if the host channel has been halted, but the core
+ *                      is not finished flushing queued requests
+ * @do_split:           Enable split for the channel
+ * @complete_split:     Enable complete split
+ * @hub_addr:           Address of high speed hub for the split
+ * @hub_port:           Port of the low/full speed device for the split
+ * @xact_pos:           Split transaction position. One of the following values:
+ *                       - DWC2_HCSPLT_XACTPOS_MID
+ *                       - DWC2_HCSPLT_XACTPOS_BEGIN
+ *                       - DWC2_HCSPLT_XACTPOS_END
+ *                       - DWC2_HCSPLT_XACTPOS_ALL
+ * @requests:           Number of requests issued for this channel since it was
+ *                      assigned to the current transfer (not counting PINGs)
+ * @schinfo:            Scheduling micro-frame bitmap
+ * @ntd:                Number of transfer descriptors for the transfer
+ * @halt_status:        Reason for halting the host channel
+ * @hcint               Contents of the HCINT register when the interrupt came
+ * @qh:                 QH for the transfer being processed by this channel
+ * @hc_list_entry:      For linking to list of host channels
+ * @desc_list_addr:     Current QH's descriptor list DMA address
+ *
+ * This structure represents the state of a single host channel when acting in
+ * host mode. It contains the data items needed to transfer packets to an
+ * endpoint via a host channel.
+ */
+struct dwc2_host_chan {
+	u8 hc_num;
+
+	unsigned dev_addr:7;
+	unsigned ep_num:4;
+	unsigned ep_is_in:1;
+	unsigned speed:4;
+	unsigned ep_type:2;
+	unsigned max_packet:11;
+	unsigned data_pid_start:2;
+#define DWC2_HC_PID_DATA0	(TSIZ_SC_MC_PID_DATA0 >> TSIZ_SC_MC_PID_SHIFT)
+#define DWC2_HC_PID_DATA2	(TSIZ_SC_MC_PID_DATA2 >> TSIZ_SC_MC_PID_SHIFT)
+#define DWC2_HC_PID_DATA1	(TSIZ_SC_MC_PID_DATA1 >> TSIZ_SC_MC_PID_SHIFT)
+#define DWC2_HC_PID_MDATA	(TSIZ_SC_MC_PID_MDATA >> TSIZ_SC_MC_PID_SHIFT)
+#define DWC2_HC_PID_SETUP	(TSIZ_SC_MC_PID_SETUP >> TSIZ_SC_MC_PID_SHIFT)
+
+	unsigned multi_count:2;
+
+	u8 *xfer_buf;
+	dma_addr_t xfer_dma;
+	dma_addr_t align_buf;
+	u32 xfer_len;
+	u32 xfer_count;
+	u16 start_pkt_count;
+	u8 xfer_started;
+	u8 do_ping;
+	u8 error_state;
+	u8 halt_on_queue;
+	u8 halt_pending;
+	u8 do_split;
+	u8 complete_split;
+	u8 hub_addr;
+	u8 hub_port;
+	u8 xact_pos;
+#define DWC2_HCSPLT_XACTPOS_MID	(HCSPLT_XACTPOS_MID >> HCSPLT_XACTPOS_SHIFT)
+#define DWC2_HCSPLT_XACTPOS_END	(HCSPLT_XACTPOS_END >> HCSPLT_XACTPOS_SHIFT)
+#define DWC2_HCSPLT_XACTPOS_BEGIN (HCSPLT_XACTPOS_BEGIN >> HCSPLT_XACTPOS_SHIFT)
+#define DWC2_HCSPLT_XACTPOS_ALL	(HCSPLT_XACTPOS_ALL >> HCSPLT_XACTPOS_SHIFT)
+
+	u8 requests;
+	u8 schinfo;
+	u16 ntd;
+	enum dwc2_halt_status halt_status;
+	u32 hcint;
+	struct dwc2_qh *qh;
+	struct list_head hc_list_entry;
+	dma_addr_t desc_list_addr;
+};
+
+struct dwc2_hcd_pipe_info {
+	u8 dev_addr;
+	u8 ep_num;
+	u8 pipe_type;
+	u8 pipe_dir;
+	u16 mps;
+};
+
+struct dwc2_hcd_iso_packet_desc {
+	u32 offset;
+	u32 length;
+	u32 actual_length;
+	u32 status;
+};
+
+struct dwc2_qtd;
+
+struct dwc2_hcd_urb {
+	void *priv;
+	struct dwc2_qtd *qtd;
+	void *buf;
+	dma_addr_t dma;
+	void *setup_packet;
+	dma_addr_t setup_dma;
+	u32 length;
+	u32 actual_length;
+	u32 status;
+	u32 error_count;
+	u32 packet_count;
+	u32 flags;
+	u16 interval;
+	struct dwc2_hcd_pipe_info pipe_info;
+	struct dwc2_hcd_iso_packet_desc iso_descs[0];
+};
+
+/* Phases for control transfers */
+enum dwc2_control_phase {
+	DWC2_CONTROL_SETUP,
+	DWC2_CONTROL_DATA,
+	DWC2_CONTROL_STATUS,
+};
+
+/* Transaction types */
+enum dwc2_transaction_type {
+	DWC2_TRANSACTION_NONE,
+	DWC2_TRANSACTION_PERIODIC,
+	DWC2_TRANSACTION_NON_PERIODIC,
+	DWC2_TRANSACTION_ALL,
+};
+
+/**
+ * struct dwc2_qh - Software queue head structure
+ *
+ * @ep_type:            Endpoint type. One of the following values:
+ *                       - USB_ENDPOINT_XFER_CONTROL
+ *                       - USB_ENDPOINT_XFER_BULK
+ *                       - USB_ENDPOINT_XFER_INT
+ *                       - USB_ENDPOINT_XFER_ISOC
+ * @ep_is_in:           Endpoint direction
+ * @maxp:               Value from wMaxPacketSize field of Endpoint Descriptor
+ * @dev_speed:          Device speed. One of the following values:
+ *                       - USB_SPEED_LOW
+ *                       - USB_SPEED_FULL
+ *                       - USB_SPEED_HIGH
+ * @data_toggle:        Determines the PID of the next data packet for
+ *                      non-controltransfers. Ignored for control transfers.
+ *                      One of the following values:
+ *                       - DWC2_HC_PID_DATA0
+ *                       - DWC2_HC_PID_DATA1
+ * @ping_state:         Ping state
+ * @do_split:           Full/low speed endpoint on high-speed hub requires split
+ * @qtd_list:           List of QTDs for this QH
+ * @channel:            Host channel currently processing transfers for this QH
+ * @usecs:              Bandwidth in microseconds per (micro)frame
+ * @interval:           Interval between transfers in (micro)frames
+ * @sched_frame:        (micro)frame to initialize a periodic transfer.
+ *                      The transfer executes in the following (micro)frame.
+ * @start_split_frame:  (Micro)frame at which last start split was initialized
+ * @dw_align_buf:       Used instead of original buffer if its physical address
+ *                      is not dword-aligned
+ * @dw_align_buf_dma:   DMA address for align_buf
+ * @qh_list_entry:      Entry for QH in either the periodic or non-periodic
+ *                      schedule
+ * @desc_list:          List of transfer descriptors
+ * @desc_list_dma:      Physical address of desc_list
+ * @n_bytes:            Xfer Bytes array. Each element corresponds to a transfer
+ *                      descriptor and indicates original XferSize value for the
+ *                      descriptor
+ * @ntd:                Actual number of transfer descriptors in a list
+ * @td_first:           Index of first activated isochronous transfer descriptor
+ * @td_last:            Index of last activated isochronous transfer descriptor
+ * @tt_buffer_dirty     True if clear_tt_buffer_complete is pending
+ *
+ * A Queue Head (QH) holds the static characteristics of an endpoint and
+ * maintains a list of transfers (QTDs) for that endpoint. A QH structure may
+ * be entered in either the non-periodic or periodic schedule.
+ */
+struct dwc2_qh {
+	u8 ep_type;
+	u8 ep_is_in;
+	u16 maxp;
+	u8 dev_speed;
+	u8 data_toggle;
+	u8 ping_state;
+	u8 do_split;
+	struct list_head qtd_list;
+	struct dwc2_host_chan *channel;
+	u16 usecs;
+	u16 interval;
+	u16 sched_frame;
+	u16 start_split_frame;
+	u8 *dw_align_buf;
+	dma_addr_t dw_align_buf_dma;
+	struct list_head qh_list_entry;
+	struct dwc2_hcd_dma_desc *desc_list;
+	dma_addr_t desc_list_dma;
+	u32 *n_bytes;
+	u16 ntd;
+	u8 td_first;
+	u8 td_last;
+	unsigned tt_buffer_dirty:1;
+};
+
+/**
+ * struct dwc2_qtd - Software queue transfer descriptor (QTD)
+ *
+ * @control_phase:      Current phase for control transfers (Setup, Data, or
+ *                      Status)
+ * @in_process:         Indicates if this QTD is currently processed by HW
+ * @data_toggle:        Determines the PID of the next data packet for the
+ *                      data phase of control transfers. Ignored for other
+ *                      transfer types. One of the following values:
+ *                       - DWC2_HC_PID_DATA0
+ *                       - DWC2_HC_PID_DATA1
+ * @complete_split:     Keeps track of the current split type for FS/LS
+ *                      endpoints on a HS Hub
+ * @isoc_split_pos:     Position of the ISOC split in full/low speed
+ * @isoc_frame_index:   Index of the next frame descriptor for an isochronous
+ *                      transfer. A frame descriptor describes the buffer
+ *                      position and length of the data to be transferred in the
+ *                      next scheduled (micro)frame of an isochronous transfer.
+ *                      It also holds status for that transaction. The frame
+ *                      index starts at 0.
+ * @isoc_split_offset:  Position of the ISOC split in the buffer for the
+ *                      current frame
+ * @ssplit_out_xfer_count: How many bytes transferred during SSPLIT OUT
+ * @error_count:        Holds the number of bus errors that have occurred for
+ *                      a transaction within this transfer
+ * @n_desc:             Number of DMA descriptors for this QTD
+ * @isoc_frame_index_last: Last activated frame (packet) index, used in
+ *                      descriptor DMA mode only
+ * @urb:                URB for this transfer
+ * @qh:                 Queue head for this QTD
+ * @qtd_list_entry:     For linking to the QH's list of QTDs
+ *
+ * A Queue Transfer Descriptor (QTD) holds the state of a bulk, control,
+ * interrupt, or isochronous transfer. A single QTD is created for each URB
+ * (of one of these types) submitted to the HCD. The transfer associated with
+ * a QTD may require one or multiple transactions.
+ *
+ * A QTD is linked to a Queue Head, which is entered in either the
+ * non-periodic or periodic schedule for execution. When a QTD is chosen for
+ * execution, some or all of its transactions may be executed. After
+ * execution, the state of the QTD is updated. The QTD may be retired if all
+ * its transactions are complete or if an error occurred. Otherwise, it
+ * remains in the schedule so more transactions can be executed later.
+ */
+struct dwc2_qtd {
+	enum dwc2_control_phase control_phase;
+	u8 in_process;
+	u8 data_toggle;
+	u8 complete_split;
+	u8 isoc_split_pos;
+	u16 isoc_frame_index;
+	u16 isoc_split_offset;
+	u32 ssplit_out_xfer_count;
+	u8 error_count;
+	u8 n_desc;
+	u16 isoc_frame_index_last;
+	struct dwc2_hcd_urb *urb;
+	struct dwc2_qh *qh;
+	struct list_head qtd_list_entry;
+};
+
+#ifdef DEBUG
+struct hc_xfer_info {
+	struct dwc2_hsotg *hsotg;
+	struct dwc2_host_chan *chan;
+};
+#endif
+
+/* Gets the struct usb_hcd that contains a struct dwc2_hsotg */
+static inline struct usb_hcd *dwc2_hsotg_to_hcd(struct dwc2_hsotg *hsotg)
+{
+	return (struct usb_hcd *)hsotg->priv;
+}
+
+/*
+ * Inline used to disable one channel interrupt. Channel interrupts are
+ * disabled when the channel is halted or released by the interrupt handler.
+ * There is no need to handle further interrupts of that type until the
+ * channel is re-assigned. In fact, subsequent handling may cause crashes
+ * because the channel structures are cleaned up when the channel is released.
+ */
+static inline void disable_hc_int(struct dwc2_hsotg *hsotg, int chnum, u32 intr)
+{
+	u32 mask = readl(hsotg->regs + HCINTMSK(chnum));
+
+	mask &= ~intr;
+	writel(mask, hsotg->regs + HCINTMSK(chnum));
+}
+
+/*
+ * Returns the mode of operation, host or device
+ */
+static inline int dwc2_is_host_mode(struct dwc2_hsotg *hsotg)
+{
+	return (readl(hsotg->regs + GINTSTS) & GINTSTS_CURMODE_HOST) != 0;
+}
+static inline int dwc2_is_device_mode(struct dwc2_hsotg *hsotg)
+{
+	return (readl(hsotg->regs + GINTSTS) & GINTSTS_CURMODE_HOST) == 0;
+}
+
+/*
+ * Reads HPRT0 in preparation to modify. It keeps the WC bits 0 so that if they
+ * are read as 1, they won't clear when written back.
+ */
+static inline u32 dwc2_read_hprt0(struct dwc2_hsotg *hsotg)
+{
+	u32 hprt0 = readl(hsotg->regs + HPRT0);
+
+	hprt0 &= ~(HPRT0_ENA | HPRT0_CONNDET | HPRT0_ENACHG | HPRT0_OVRCURRCHG);
+	return hprt0;
+}
+
+static inline u8 dwc2_hcd_get_ep_num(struct dwc2_hcd_pipe_info *pipe)
+{
+	return pipe->ep_num;
+}
+
+static inline u8 dwc2_hcd_get_pipe_type(struct dwc2_hcd_pipe_info *pipe)
+{
+	return pipe->pipe_type;
+}
+
+static inline u16 dwc2_hcd_get_mps(struct dwc2_hcd_pipe_info *pipe)
+{
+	return pipe->mps;
+}
+
+static inline u8 dwc2_hcd_get_dev_addr(struct dwc2_hcd_pipe_info *pipe)
+{
+	return pipe->dev_addr;
+}
+
+static inline u8 dwc2_hcd_is_pipe_isoc(struct dwc2_hcd_pipe_info *pipe)
+{
+	return pipe->pipe_type == USB_ENDPOINT_XFER_ISOC;
+}
+
+static inline u8 dwc2_hcd_is_pipe_int(struct dwc2_hcd_pipe_info *pipe)
+{
+	return pipe->pipe_type == USB_ENDPOINT_XFER_INT;
+}
+
+static inline u8 dwc2_hcd_is_pipe_bulk(struct dwc2_hcd_pipe_info *pipe)
+{
+	return pipe->pipe_type == USB_ENDPOINT_XFER_BULK;
+}
+
+static inline u8 dwc2_hcd_is_pipe_control(struct dwc2_hcd_pipe_info *pipe)
+{
+	return pipe->pipe_type == USB_ENDPOINT_XFER_CONTROL;
+}
+
+static inline u8 dwc2_hcd_is_pipe_in(struct dwc2_hcd_pipe_info *pipe)
+{
+	return pipe->pipe_dir == USB_DIR_IN;
+}
+
+static inline u8 dwc2_hcd_is_pipe_out(struct dwc2_hcd_pipe_info *pipe)
+{
+	return !dwc2_hcd_is_pipe_in(pipe);
+}
+
+extern int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq,
+			 struct dwc2_core_params *params);
+extern void dwc2_hcd_remove(struct dwc2_hsotg *hsotg);
+extern int dwc2_set_parameters(struct dwc2_hsotg *hsotg,
+			       struct dwc2_core_params *params);
+
+/* Transaction Execution Functions */
+extern enum dwc2_transaction_type dwc2_hcd_select_transactions(
+						struct dwc2_hsotg *hsotg);
+extern void dwc2_hcd_queue_transactions(struct dwc2_hsotg *hsotg,
+					enum dwc2_transaction_type tr_type);
+
+/* Schedule Queue Functions */
+/* Implemented in hcd_queue.c */
+extern void dwc2_hcd_qh_free(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh);
+extern int dwc2_hcd_qh_add(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh);
+extern void dwc2_hcd_qh_unlink(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh);
+extern void dwc2_hcd_qh_deactivate(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh,
+				   int sched_csplit);
+
+extern void dwc2_hcd_qtd_init(struct dwc2_qtd *qtd, struct dwc2_hcd_urb *urb);
+extern int dwc2_hcd_qtd_add(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd,
+			    struct dwc2_qh **qh, gfp_t mem_flags);
+
+/* Unlinks and frees a QTD */
+static inline void dwc2_hcd_qtd_unlink_and_free(struct dwc2_hsotg *hsotg,
+						struct dwc2_qtd *qtd,
+						struct dwc2_qh *qh)
+{
+	list_del(&qtd->qtd_list_entry);
+	kfree(qtd);
+}
+
+/* Descriptor DMA support functions */
+extern void dwc2_hcd_start_xfer_ddma(struct dwc2_hsotg *hsotg,
+				     struct dwc2_qh *qh);
+extern void dwc2_hcd_complete_xfer_ddma(struct dwc2_hsotg *hsotg,
+					struct dwc2_host_chan *chan, int chnum,
+					enum dwc2_halt_status halt_status);
+
+extern int dwc2_hcd_qh_init_ddma(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh,
+				 gfp_t mem_flags);
+extern void dwc2_hcd_qh_free_ddma(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh);
+
+/* Check if QH is non-periodic */
+#define dwc2_qh_is_non_per(_qh_ptr_) \
+	((_qh_ptr_)->ep_type == USB_ENDPOINT_XFER_BULK || \
+	 (_qh_ptr_)->ep_type == USB_ENDPOINT_XFER_CONTROL)
+
+/* High bandwidth multiplier as encoded in highspeed endpoint descriptors */
+#define dwc2_hb_mult(wmaxpacketsize) (1 + (((wmaxpacketsize) >> 11) & 0x03))
+
+/* Packet size for any kind of endpoint descriptor */
+#define dwc2_max_packet(wmaxpacketsize) ((wmaxpacketsize) & 0x07ff)
+
+/*
+ * Returns true if frame1 is less than or equal to frame2. The comparison is
+ * done modulo HFNUM_MAX_FRNUM. This accounts for the rollover of the
+ * frame number when the max frame number is reached.
+ */
+static inline int dwc2_frame_num_le(u16 frame1, u16 frame2)
+{
+	return ((frame2 - frame1) & HFNUM_MAX_FRNUM) <= (HFNUM_MAX_FRNUM >> 1);
+}
+
+/*
+ * Returns true if frame1 is greater than frame2. The comparison is done
+ * modulo HFNUM_MAX_FRNUM. This accounts for the rollover of the frame
+ * number when the max frame number is reached.
+ */
+static inline int dwc2_frame_num_gt(u16 frame1, u16 frame2)
+{
+	return (frame1 != frame2) &&
+	       ((frame1 - frame2) & HFNUM_MAX_FRNUM) < (HFNUM_MAX_FRNUM >> 1);
+}
+
+/*
+ * Increments frame by the amount specified by inc. The addition is done
+ * modulo HFNUM_MAX_FRNUM. Returns the incremented value.
+ */
+static inline u16 dwc2_frame_num_inc(u16 frame, u16 inc)
+{
+	return (frame + inc) & HFNUM_MAX_FRNUM;
+}
+
+static inline u16 dwc2_full_frame_num(u16 frame)
+{
+	return (frame & HFNUM_MAX_FRNUM) >> 3;
+}
+
+static inline u16 dwc2_micro_frame_num(u16 frame)
+{
+	return frame & 0x7;
+}
+
+/*
+ * Returns the Core Interrupt Status register contents, ANDed with the Core
+ * Interrupt Mask register contents
+ */
+static inline u32 dwc2_read_core_intr(struct dwc2_hsotg *hsotg)
+{
+	return readl(hsotg->regs + GINTSTS) & readl(hsotg->regs + GINTMSK);
+}
+
+static inline u32 dwc2_hcd_urb_get_status(struct dwc2_hcd_urb *dwc2_urb)
+{
+	return dwc2_urb->status;
+}
+
+static inline u32 dwc2_hcd_urb_get_actual_length(
+		struct dwc2_hcd_urb *dwc2_urb)
+{
+	return dwc2_urb->actual_length;
+}
+
+static inline u32 dwc2_hcd_urb_get_error_count(struct dwc2_hcd_urb *dwc2_urb)
+{
+	return dwc2_urb->error_count;
+}
+
+static inline void dwc2_hcd_urb_set_iso_desc_params(
+		struct dwc2_hcd_urb *dwc2_urb, int desc_num, u32 offset,
+		u32 length)
+{
+	dwc2_urb->iso_descs[desc_num].offset = offset;
+	dwc2_urb->iso_descs[desc_num].length = length;
+}
+
+static inline u32 dwc2_hcd_urb_get_iso_desc_status(
+		struct dwc2_hcd_urb *dwc2_urb, int desc_num)
+{
+	return dwc2_urb->iso_descs[desc_num].status;
+}
+
+static inline u32 dwc2_hcd_urb_get_iso_desc_actual_length(
+		struct dwc2_hcd_urb *dwc2_urb, int desc_num)
+{
+	return dwc2_urb->iso_descs[desc_num].actual_length;
+}
+
+static inline int dwc2_hcd_is_bandwidth_allocated(struct dwc2_hsotg *hsotg,
+						  struct usb_host_endpoint *ep)
+{
+	struct dwc2_qh *qh = ep->hcpriv;
+
+	if (qh && !list_empty(&qh->qh_list_entry))
+		return 1;
+
+	return 0;
+}
+
+static inline u16 dwc2_hcd_get_ep_bandwidth(struct dwc2_hsotg *hsotg,
+					    struct usb_host_endpoint *ep)
+{
+	struct dwc2_qh *qh = ep->hcpriv;
+
+	if (!qh) {
+		WARN_ON(1);
+		return 0;
+	}
+
+	return qh->usecs;
+}
+
+extern void dwc2_hcd_save_data_toggle(struct dwc2_hsotg *hsotg,
+				      struct dwc2_host_chan *chan, int chnum,
+				      struct dwc2_qtd *qtd);
+
+/* HCD Core API */
+
+/**
+ * dwc2_hcd_intr() - Called on every hardware interrupt
+ *
+ * @hsotg: The DWC2 HCD
+ *
+ * Returns non zero if interrupt is handled
+ * Return 0 if interrupt is not handled
+ */
+extern int dwc2_hcd_intr(struct dwc2_hsotg *hsotg);
+
+/**
+ * dwc2_hcd_stop() - Halts the DWC_otg host mode operation
+ *
+ * @hsotg: The DWC2 HCD
+ */
+extern void dwc2_hcd_stop(struct dwc2_hsotg *hsotg);
+
+extern void dwc2_hcd_start(struct dwc2_hsotg *hsotg);
+extern void dwc2_hcd_disconnect(struct dwc2_hsotg *hsotg);
+
+/**
+ * dwc2_hcd_is_b_host() - Returns 1 if core currently is acting as B host,
+ * and 0 otherwise
+ *
+ * @hsotg: The DWC2 HCD
+ */
+extern int dwc2_hcd_is_b_host(struct dwc2_hsotg *hsotg);
+
+/**
+ * dwc2_hcd_get_frame_number() - Returns current frame number
+ *
+ * @hsotg: The DWC2 HCD
+ */
+extern int dwc2_hcd_get_frame_number(struct dwc2_hsotg *hsotg);
+
+/**
+ * dwc2_hcd_dump_state() - Dumps hsotg state
+ *
+ * @hsotg: The DWC2 HCD
+ *
+ * NOTE: This function will be removed once the peripheral controller code
+ * is integrated and the driver is stable
+ */
+extern void dwc2_hcd_dump_state(struct dwc2_hsotg *hsotg);
+
+/**
+ * dwc2_hcd_dump_frrem() - Dumps the average frame remaining at SOF
+ *
+ * @hsotg: The DWC2 HCD
+ *
+ * This can be used to determine average interrupt latency. Frame remaining is
+ * also shown for start transfer and two additional sample points.
+ *
+ * NOTE: This function will be removed once the peripheral controller code
+ * is integrated and the driver is stable
+ */
+extern void dwc2_hcd_dump_frrem(struct dwc2_hsotg *hsotg);
+
+/* URB interface */
+
+/* Transfer flags */
+#define URB_GIVEBACK_ASAP	0x1
+#define URB_SEND_ZERO_PACKET	0x2
+
+/* Host driver callbacks */
+
+extern void dwc2_host_start(struct dwc2_hsotg *hsotg);
+extern void dwc2_host_disconnect(struct dwc2_hsotg *hsotg);
+extern void dwc2_host_hub_info(struct dwc2_hsotg *hsotg, void *context,
+			       int *hub_addr, int *hub_port);
+extern int dwc2_host_get_speed(struct dwc2_hsotg *hsotg, void *context);
+extern void dwc2_host_complete(struct dwc2_hsotg *hsotg, void *context,
+			       struct dwc2_hcd_urb *dwc2_urb, int status);
+
+#ifdef DEBUG
+/*
+ * Macro to sample the remaining PHY clocks left in the current frame. This
+ * may be used during debugging to determine the average time it takes to
+ * execute sections of code. There are two possible sample points, "a" and
+ * "b", so the _letter_ argument must be one of these values.
+ *
+ * To dump the average sample times, read the "hcd_frrem" sysfs attribute. For
+ * example, "cat /sys/devices/lm0/hcd_frrem".
+ */
+#define dwc2_sample_frrem(_hcd_, _qh_, _letter_)			\
+do {									\
+	struct hfnum_data _hfnum_;					\
+	struct dwc2_qtd *_qtd_;						\
+									\
+	_qtd_ = list_entry((_qh_)->qtd_list.next, struct dwc2_qtd,	\
+			   qtd_list_entry);				\
+	if (usb_pipeint(_qtd_->urb->pipe) &&				\
+	    (_qh_)->start_split_frame != 0 && !_qtd_->complete_split) {	\
+		_hfnum_.d32 = readl((_hcd_)->regs + HFNUM);		\
+		switch (_hfnum_.b.frnum & 0x7) {			\
+		case 7:							\
+			(_hcd_)->hfnum_7_samples_##_letter_++;		\
+			(_hcd_)->hfnum_7_frrem_accum_##_letter_ +=	\
+				_hfnum_.b.frrem;			\
+			break;						\
+		case 0:							\
+			(_hcd_)->hfnum_0_samples_##_letter_++;		\
+			(_hcd_)->hfnum_0_frrem_accum_##_letter_ +=	\
+				_hfnum_.b.frrem;			\
+			break;						\
+		default:						\
+			(_hcd_)->hfnum_other_samples_##_letter_++;	\
+			(_hcd_)->hfnum_other_frrem_accum_##_letter_ +=	\
+				_hfnum_.b.frrem;			\
+			break;						\
+		}							\
+	}								\
+} while (0)
+#else
+#define dwc2_sample_frrem(_hcd_, _qh_, _letter_)	do {} while (0)
+#endif
+
+#endif /* __DWC2_HCD_H__ */
diff --git a/drivers/staging/dwc2/hcd_ddma.c b/drivers/staging/dwc2/hcd_ddma.c
new file mode 100644
index 0000000..ab88f50
--- /dev/null
+++ b/drivers/staging/dwc2/hcd_ddma.c
@@ -0,0 +1,1196 @@
+/*
+ * hcd_ddma.c - DesignWare HS OTG Controller descriptor DMA routines
+ *
+ * Copyright (C) 2004-2013 Synopsys, Inc.
+ *
+ * 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, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 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 names of the above-listed copyright holders may not 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 the License, or (at your option) any
+ * later version.
+ *
+ * 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.
+ */
+
+/*
+ * This file contains the Descriptor DMA implementation for Host mode
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+
+#include <linux/usb/hcd.h>
+#include <linux/usb/ch11.h>
+
+#include "core.h"
+#include "hcd.h"
+
+static u16 dwc2_frame_list_idx(u16 frame)
+{
+	return frame & (FRLISTEN_64_SIZE - 1);
+}
+
+static u16 dwc2_desclist_idx_inc(u16 idx, u16 inc, u8 speed)
+{
+	return (idx + inc) &
+		((speed == USB_SPEED_HIGH ? MAX_DMA_DESC_NUM_HS_ISOC :
+		  MAX_DMA_DESC_NUM_GENERIC) - 1);
+}
+
+static u16 dwc2_desclist_idx_dec(u16 idx, u16 inc, u8 speed)
+{
+	return (idx - inc) &
+		((speed == USB_SPEED_HIGH ? MAX_DMA_DESC_NUM_HS_ISOC :
+		  MAX_DMA_DESC_NUM_GENERIC) - 1);
+}
+
+static u16 dwc2_max_desc_num(struct dwc2_qh *qh)
+{
+	return (qh->ep_type == USB_ENDPOINT_XFER_ISOC &&
+		qh->dev_speed == USB_SPEED_HIGH) ?
+		MAX_DMA_DESC_NUM_HS_ISOC : MAX_DMA_DESC_NUM_GENERIC;
+}
+
+static u16 dwc2_frame_incr_val(struct dwc2_qh *qh)
+{
+	return qh->dev_speed == USB_SPEED_HIGH ?
+	       (qh->interval + 8 - 1) / 8 : qh->interval;
+}
+
+static int dwc2_desc_list_alloc(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh,
+				gfp_t flags)
+{
+	qh->desc_list = dma_alloc_coherent(hsotg->dev,
+				sizeof(struct dwc2_hcd_dma_desc) *
+				dwc2_max_desc_num(qh), &qh->desc_list_dma,
+				flags);
+
+	if (!qh->desc_list)
+		return -ENOMEM;
+
+	memset(qh->desc_list, 0,
+	       sizeof(struct dwc2_hcd_dma_desc) * dwc2_max_desc_num(qh));
+
+	qh->n_bytes = kzalloc(sizeof(u32) * dwc2_max_desc_num(qh), flags);
+	if (!qh->n_bytes) {
+		dma_free_coherent(hsotg->dev, sizeof(struct dwc2_hcd_dma_desc)
+				  * dwc2_max_desc_num(qh), qh->desc_list,
+				  qh->desc_list_dma);
+		qh->desc_list = NULL;
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static void dwc2_desc_list_free(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
+{
+	if (qh->desc_list) {
+		dma_free_coherent(hsotg->dev, sizeof(struct dwc2_hcd_dma_desc)
+				  * dwc2_max_desc_num(qh), qh->desc_list,
+				  qh->desc_list_dma);
+		qh->desc_list = NULL;
+	}
+
+	kfree(qh->n_bytes);
+	qh->n_bytes = NULL;
+}
+
+static int dwc2_frame_list_alloc(struct dwc2_hsotg *hsotg, gfp_t mem_flags)
+{
+	if (hsotg->frame_list)
+		return 0;
+
+	hsotg->frame_list = dma_alloc_coherent(hsotg->dev,
+					       4 * FRLISTEN_64_SIZE,
+					       &hsotg->frame_list_dma,
+					       mem_flags);
+	if (!hsotg->frame_list)
+		return -ENOMEM;
+
+	memset(hsotg->frame_list, 0, 4 * FRLISTEN_64_SIZE);
+	return 0;
+}
+
+static void dwc2_frame_list_free(struct dwc2_hsotg *hsotg)
+{
+	u32 *frame_list;
+	dma_addr_t frame_list_dma;
+	unsigned long flags;
+
+	spin_lock_irqsave(&hsotg->lock, flags);
+
+	if (!hsotg->frame_list) {
+		spin_unlock_irqrestore(&hsotg->lock, flags);
+		return;
+	}
+
+	frame_list = hsotg->frame_list;
+	frame_list_dma = hsotg->frame_list_dma;
+	hsotg->frame_list = NULL;
+
+	spin_unlock_irqrestore(&hsotg->lock, flags);
+
+	dma_free_coherent(hsotg->dev, 4 * FRLISTEN_64_SIZE, frame_list,
+			  frame_list_dma);
+}
+
+static void dwc2_per_sched_enable(struct dwc2_hsotg *hsotg, u32 fr_list_en)
+{
+	u32 hcfg;
+	unsigned long flags;
+
+	spin_lock_irqsave(&hsotg->lock, flags);
+
+	hcfg = readl(hsotg->regs + HCFG);
+	if (hcfg & HCFG_PERSCHEDENA) {
+		/* already enabled */
+		spin_unlock_irqrestore(&hsotg->lock, flags);
+		return;
+	}
+
+	writel(hsotg->frame_list_dma, hsotg->regs + HFLBADDR);
+
+	hcfg &= ~HCFG_FRLISTEN_MASK;
+	hcfg |= fr_list_en | HCFG_PERSCHEDENA;
+	dev_vdbg(hsotg->dev, "Enabling Periodic schedule\n");
+	writel(hcfg, hsotg->regs + HCFG);
+
+	spin_unlock_irqrestore(&hsotg->lock, flags);
+}
+
+static void dwc2_per_sched_disable(struct dwc2_hsotg *hsotg)
+{
+	u32 hcfg;
+	unsigned long flags;
+
+	spin_lock_irqsave(&hsotg->lock, flags);
+
+	hcfg = readl(hsotg->regs + HCFG);
+	if (!(hcfg & HCFG_PERSCHEDENA)) {
+		/* already disabled */
+		spin_unlock_irqrestore(&hsotg->lock, flags);
+		return;
+	}
+
+	hcfg &= ~HCFG_PERSCHEDENA;
+	dev_vdbg(hsotg->dev, "Disabling Periodic schedule\n");
+	writel(hcfg, hsotg->regs + HCFG);
+
+	spin_unlock_irqrestore(&hsotg->lock, flags);
+}
+
+/*
+ * Activates/Deactivates FrameList entries for the channel based on endpoint
+ * servicing period
+ */
+static void dwc2_update_frame_list(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh,
+				   int enable)
+{
+	struct dwc2_host_chan *chan;
+	u16 i, j, inc;
+
+	if (!qh->channel) {
+		dev_err(hsotg->dev, "qh->channel = %p", qh->channel);
+		return;
+	}
+
+	if (!hsotg) {
+		dev_err(hsotg->dev, "------hsotg = %p", hsotg);
+		return;
+	}
+
+	if (!hsotg->frame_list) {
+		dev_err(hsotg->dev, "-------hsotg->frame_list = %p",
+			hsotg->frame_list);
+		return;
+	}
+
+	chan = qh->channel;
+	inc = dwc2_frame_incr_val(qh);
+	if (qh->ep_type == USB_ENDPOINT_XFER_ISOC)
+		i = dwc2_frame_list_idx(qh->sched_frame);
+	else
+		i = 0;
+
+	j = i;
+	do {
+		if (enable)
+			hsotg->frame_list[j] |= 1 << chan->hc_num;
+		else
+			hsotg->frame_list[j] &= ~(1 << chan->hc_num);
+		j = (j + inc) & (FRLISTEN_64_SIZE - 1);
+	} while (j != i);
+
+	if (!enable)
+		return;
+
+	chan->schinfo = 0;
+	if (chan->speed == USB_SPEED_HIGH && qh->interval) {
+		j = 1;
+		/* TODO - check this */
+		inc = (8 + qh->interval - 1) / qh->interval;
+		for (i = 0; i < inc; i++) {
+			chan->schinfo |= j;
+			j = j << qh->interval;
+		}
+	} else {
+		chan->schinfo = 0xff;
+	}
+}
+
+static void dwc2_release_channel_ddma(struct dwc2_hsotg *hsotg,
+				      struct dwc2_qh *qh)
+{
+	struct dwc2_host_chan *chan = qh->channel;
+
+	if (dwc2_qh_is_non_per(qh))
+		hsotg->non_periodic_channels--;
+	else
+		dwc2_update_frame_list(hsotg, qh, 0);
+
+	/*
+	 * The condition is added to prevent double cleanup try in case of
+	 * device disconnect. See channel cleanup in dwc2_hcd_disconnect().
+	 */
+	if (chan->qh) {
+		if (!list_empty(&chan->hc_list_entry))
+			list_del(&chan->hc_list_entry);
+		dwc2_hc_cleanup(hsotg, chan);
+		list_add_tail(&chan->hc_list_entry, &hsotg->free_hc_list);
+		chan->qh = NULL;
+	}
+
+	qh->channel = NULL;
+	qh->ntd = 0;
+
+	if (qh->desc_list)
+		memset(qh->desc_list, 0, sizeof(struct dwc2_hcd_dma_desc) *
+		       dwc2_max_desc_num(qh));
+}
+
+/**
+ * dwc2_hcd_qh_init_ddma() - Initializes a QH structure's Descriptor DMA
+ * related members
+ *
+ * @hsotg: The HCD state structure for the DWC OTG controller
+ * @qh:    The QH to init
+ *
+ * Return: 0 if successful, negative error code otherwise
+ *
+ * Allocates memory for the descriptor list. For the first periodic QH,
+ * allocates memory for the FrameList and enables periodic scheduling.
+ */
+int dwc2_hcd_qh_init_ddma(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh,
+			  gfp_t mem_flags)
+{
+	int retval;
+
+	if (qh->do_split) {
+		dev_err(hsotg->dev,
+			"SPLIT Transfers are not supported in Descriptor DMA mode.\n");
+		retval = -EINVAL;
+		goto err0;
+	}
+
+	retval = dwc2_desc_list_alloc(hsotg, qh, mem_flags);
+	if (retval)
+		goto err0;
+
+	if (qh->ep_type == USB_ENDPOINT_XFER_ISOC ||
+	    qh->ep_type == USB_ENDPOINT_XFER_INT) {
+		if (!hsotg->frame_list) {
+			retval = dwc2_frame_list_alloc(hsotg, mem_flags);
+			if (retval)
+				goto err1;
+			/* Enable periodic schedule on first periodic QH */
+			dwc2_per_sched_enable(hsotg, HCFG_FRLISTEN_64);
+		}
+	}
+
+	qh->ntd = 0;
+	return 0;
+
+err1:
+	dwc2_desc_list_free(hsotg, qh);
+err0:
+	return retval;
+}
+
+/**
+ * dwc2_hcd_qh_free_ddma() - Frees a QH structure's Descriptor DMA related
+ * members
+ *
+ * @hsotg: The HCD state structure for the DWC OTG controller
+ * @qh:    The QH to free
+ *
+ * Frees descriptor list memory associated with the QH. If QH is periodic and
+ * the last, frees FrameList memory and disables periodic scheduling.
+ */
+void dwc2_hcd_qh_free_ddma(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
+{
+	dwc2_desc_list_free(hsotg, qh);
+
+	/*
+	 * Channel still assigned due to some reasons.
+	 * Seen on Isoc URB dequeue. Channel halted but no subsequent
+	 * ChHalted interrupt to release the channel. Afterwards
+	 * when it comes here from endpoint disable routine
+	 * channel remains assigned.
+	 */
+	if (qh->channel)
+		dwc2_release_channel_ddma(hsotg, qh);
+
+	if ((qh->ep_type == USB_ENDPOINT_XFER_ISOC ||
+	     qh->ep_type == USB_ENDPOINT_XFER_INT) &&
+	    !hsotg->periodic_channels && hsotg->frame_list) {
+		dwc2_per_sched_disable(hsotg);
+		dwc2_frame_list_free(hsotg);
+	}
+}
+
+static u8 dwc2_frame_to_desc_idx(struct dwc2_qh *qh, u16 frame_idx)
+{
+	if (qh->dev_speed == USB_SPEED_HIGH)
+		/* Descriptor set (8 descriptors) index which is 8-aligned */
+		return (frame_idx & ((MAX_DMA_DESC_NUM_HS_ISOC / 8) - 1)) * 8;
+	else
+		return frame_idx & (MAX_DMA_DESC_NUM_GENERIC - 1);
+}
+
+/*
+ * Determine starting frame for Isochronous transfer.
+ * Few frames skipped to prevent race condition with HC.
+ */
+static u16 dwc2_calc_starting_frame(struct dwc2_hsotg *hsotg,
+				    struct dwc2_qh *qh, u16 *skip_frames)
+{
+	u16 frame;
+
+	hsotg->frame_number = dwc2_hcd_get_frame_number(hsotg);
+
+	/* sched_frame is always frame number (not uFrame) both in FS and HS! */
+
+	/*
+	 * skip_frames is used to limit activated descriptors number
+	 * to avoid the situation when HC services the last activated
+	 * descriptor firstly.
+	 * Example for FS:
+	 * Current frame is 1, scheduled frame is 3. Since HC always fetches
+	 * the descriptor corresponding to curr_frame+1, the descriptor
+	 * corresponding to frame 2 will be fetched. If the number of
+	 * descriptors is max=64 (or greather) the list will be fully programmed
+	 * with Active descriptors and it is possible case (rare) that the
+	 * latest descriptor(considering rollback) corresponding to frame 2 will
+	 * be serviced first. HS case is more probable because, in fact, up to
+	 * 11 uframes (16 in the code) may be skipped.
+	 */
+	if (qh->dev_speed == USB_SPEED_HIGH) {
+		/*
+		 * Consider uframe counter also, to start xfer asap. If half of
+		 * the frame elapsed skip 2 frames otherwise just 1 frame.
+		 * Starting descriptor index must be 8-aligned, so if the
+		 * current frame is near to complete the next one is skipped as
+		 * well.
+		 */
+		if (dwc2_micro_frame_num(hsotg->frame_number) >= 5) {
+			*skip_frames = 2 * 8;
+			frame = dwc2_frame_num_inc(hsotg->frame_number,
+						   *skip_frames);
+		} else {
+			*skip_frames = 1 * 8;
+			frame = dwc2_frame_num_inc(hsotg->frame_number,
+						   *skip_frames);
+		}
+
+		frame = dwc2_full_frame_num(frame);
+	} else {
+		/*
+		 * Two frames are skipped for FS - the current and the next.
+		 * But for descriptor programming, 1 frame (descriptor) is
+		 * enough, see example above.
+		 */
+		*skip_frames = 1;
+		frame = dwc2_frame_num_inc(hsotg->frame_number, 2);
+	}
+
+	return frame;
+}
+
+/*
+ * Calculate initial descriptor index for isochronous transfer based on
+ * scheduled frame
+ */
+static u16 dwc2_recalc_initial_desc_idx(struct dwc2_hsotg *hsotg,
+					struct dwc2_qh *qh)
+{
+	u16 frame, fr_idx, fr_idx_tmp, skip_frames;
+
+	/*
+	 * With current ISOC processing algorithm the channel is being released
+	 * when no more QTDs in the list (qh->ntd == 0). Thus this function is
+	 * called only when qh->ntd == 0 and qh->channel == 0.
+	 *
+	 * So qh->channel != NULL branch is not used and just not removed from
+	 * the source file. It is required for another possible approach which
+	 * is, do not disable and release the channel when ISOC session
+	 * completed, just move QH to inactive schedule until new QTD arrives.
+	 * On new QTD, the QH moved back to 'ready' schedule, starting frame and
+	 * therefore starting desc_index are recalculated. In this case channel
+	 * is released only on ep_disable.
+	 */
+
+	/*
+	 * Calculate starting descriptor index. For INTERRUPT endpoint it is
+	 * always 0.
+	 */
+	if (qh->channel) {
+		frame = dwc2_calc_starting_frame(hsotg, qh, &skip_frames);
+		/*
+		 * Calculate initial descriptor index based on FrameList current
+		 * bitmap and servicing period
+		 */
+		fr_idx_tmp = dwc2_frame_list_idx(frame);
+		fr_idx = (FRLISTEN_64_SIZE +
+			  dwc2_frame_list_idx(qh->sched_frame) - fr_idx_tmp)
+			 % dwc2_frame_incr_val(qh);
+		fr_idx = (fr_idx + fr_idx_tmp) % FRLISTEN_64_SIZE;
+	} else {
+		qh->sched_frame = dwc2_calc_starting_frame(hsotg, qh,
+							   &skip_frames);
+		fr_idx = dwc2_frame_list_idx(qh->sched_frame);
+	}
+
+	qh->td_first = qh->td_last = dwc2_frame_to_desc_idx(qh, fr_idx);
+
+	return skip_frames;
+}
+
+#define ISOC_URB_GIVEBACK_ASAP
+
+#define MAX_ISOC_XFER_SIZE_FS	1023
+#define MAX_ISOC_XFER_SIZE_HS	3072
+#define DESCNUM_THRESHOLD	4
+
+static void dwc2_fill_host_isoc_dma_desc(struct dwc2_hsotg *hsotg,
+					 struct dwc2_qtd *qtd,
+					 struct dwc2_qh *qh, u32 max_xfer_size,
+					 u16 idx)
+{
+	struct dwc2_hcd_dma_desc *dma_desc = &qh->desc_list[idx];
+	struct dwc2_hcd_iso_packet_desc *frame_desc;
+
+	memset(dma_desc, 0, sizeof(*dma_desc));
+	frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index_last];
+
+	if (frame_desc->length > max_xfer_size)
+		qh->n_bytes[idx] = max_xfer_size;
+	else
+		qh->n_bytes[idx] = frame_desc->length;
+
+	dma_desc->buf = (u32)(qtd->urb->dma + frame_desc->offset);
+	dma_desc->status = qh->n_bytes[idx] << HOST_DMA_ISOC_NBYTES_SHIFT &
+			   HOST_DMA_ISOC_NBYTES_MASK;
+
+#ifdef ISOC_URB_GIVEBACK_ASAP
+	/* Set IOC for each descriptor corresponding to last frame of URB */
+	if (qtd->isoc_frame_index_last == qtd->urb->packet_count)
+		dma_desc->status |= HOST_DMA_IOC;
+#endif
+
+	qh->ntd++;
+	qtd->isoc_frame_index_last++;
+}
+
+static void dwc2_init_isoc_dma_desc(struct dwc2_hsotg *hsotg,
+				    struct dwc2_qh *qh, u16 skip_frames)
+{
+	struct dwc2_qtd *qtd;
+	u32 max_xfer_size;
+	u16 idx, inc, n_desc, ntd_max = 0;
+
+	idx = qh->td_last;
+	inc = qh->interval;
+	n_desc = 0;
+
+	if (qh->interval) {
+		ntd_max = (dwc2_max_desc_num(qh) + qh->interval - 1) /
+				qh->interval;
+		if (skip_frames && !qh->channel)
+			ntd_max -= skip_frames / qh->interval;
+	}
+
+	max_xfer_size = qh->dev_speed == USB_SPEED_HIGH ?
+			MAX_ISOC_XFER_SIZE_HS : MAX_ISOC_XFER_SIZE_FS;
+
+	list_for_each_entry(qtd, &qh->qtd_list, qtd_list_entry) {
+		while (qh->ntd < ntd_max && qtd->isoc_frame_index_last <
+						qtd->urb->packet_count) {
+			if (n_desc > 1)
+				qh->desc_list[n_desc - 1].status |= HOST_DMA_A;
+			dwc2_fill_host_isoc_dma_desc(hsotg, qtd, qh,
+						     max_xfer_size, idx);
+			idx = dwc2_desclist_idx_inc(idx, inc, qh->dev_speed);
+			n_desc++;
+		}
+		qtd->in_process = 1;
+	}
+
+	qh->td_last = idx;
+
+#ifdef ISOC_URB_GIVEBACK_ASAP
+	/* Set IOC for last descriptor if descriptor list is full */
+	if (qh->ntd == ntd_max) {
+		idx = dwc2_desclist_idx_dec(qh->td_last, inc, qh->dev_speed);
+		qh->desc_list[idx].status |= HOST_DMA_IOC;
+	}
+#else
+	/*
+	 * Set IOC bit only for one descriptor. Always try to be ahead of HW
+	 * processing, i.e. on IOC generation driver activates next descriptor
+	 * but core continues to process descriptors following the one with IOC
+	 * set.
+	 */
+
+	if (n_desc > DESCNUM_THRESHOLD)
+		/*
+		 * Move IOC "up". Required even if there is only one QTD
+		 * in the list, because QTDs might continue to be queued,
+		 * but during the activation it was only one queued.
+		 * Actually more than one QTD might be in the list if this
+		 * function called from XferCompletion - QTDs was queued during
+		 * HW processing of the previous descriptor chunk.
+		 */
+		idx = dwc2_desclist_idx_dec(idx, inc * ((qh->ntd + 1) / 2),
+					    qh->dev_speed);
+	else
+		/*
+		 * Set the IOC for the latest descriptor if either number of
+		 * descriptors is not greater than threshold or no more new
+		 * descriptors activated
+		 */
+		idx = dwc2_desclist_idx_dec(qh->td_last, inc, qh->dev_speed);
+
+	qh->desc_list[idx].status |= HOST_DMA_IOC;
+#endif
+
+	if (n_desc) {
+		qh->desc_list[n_desc - 1].status |= HOST_DMA_A;
+		if (n_desc > 1)
+			qh->desc_list[0].status |= HOST_DMA_A;
+	}
+}
+
+static void dwc2_fill_host_dma_desc(struct dwc2_hsotg *hsotg,
+				    struct dwc2_host_chan *chan,
+				    struct dwc2_qtd *qtd, struct dwc2_qh *qh,
+				    int n_desc)
+{
+	struct dwc2_hcd_dma_desc *dma_desc = &qh->desc_list[n_desc];
+	int len = chan->xfer_len;
+
+	if (len > MAX_DMA_DESC_SIZE)
+		len = MAX_DMA_DESC_SIZE - chan->max_packet + 1;
+
+	if (chan->ep_is_in) {
+		int num_packets;
+
+		if (len > 0 && chan->max_packet)
+			num_packets = (len + chan->max_packet - 1)
+					/ chan->max_packet;
+		else
+			/* Need 1 packet for transfer length of 0 */
+			num_packets = 1;
+
+		/* Always program an integral # of packets for IN transfers */
+		len = num_packets * chan->max_packet;
+	}
+
+	dma_desc->status = len << HOST_DMA_NBYTES_SHIFT & HOST_DMA_NBYTES_MASK;
+	qh->n_bytes[n_desc] = len;
+
+	if (qh->ep_type == USB_ENDPOINT_XFER_CONTROL &&
+	    qtd->control_phase == DWC2_CONTROL_SETUP)
+		dma_desc->status |= HOST_DMA_SUP;
+
+	dma_desc->buf = (u32)chan->xfer_dma;
+
+	/*
+	 * Last (or only) descriptor of IN transfer with actual size less
+	 * than MaxPacket
+	 */
+	if (len > chan->xfer_len) {
+		chan->xfer_len = 0;
+	} else {
+		chan->xfer_dma += len;
+		chan->xfer_len -= len;
+	}
+}
+
+static void dwc2_init_non_isoc_dma_desc(struct dwc2_hsotg *hsotg,
+					struct dwc2_qh *qh)
+{
+	struct dwc2_qtd *qtd;
+	struct dwc2_host_chan *chan = qh->channel;
+	int n_desc = 0;
+
+	dev_vdbg(hsotg->dev, "%s(): qh=%p dma=%08lx len=%d\n", __func__, qh,
+		 (unsigned long)chan->xfer_dma, chan->xfer_len);
+
+	/*
+	 * Start with chan->xfer_dma initialized in assign_and_init_hc(), then
+	 * if SG transfer consists of multiple URBs, this pointer is re-assigned
+	 * to the buffer of the currently processed QTD. For non-SG request
+	 * there is always one QTD active.
+	 */
+
+	list_for_each_entry(qtd, &qh->qtd_list, qtd_list_entry) {
+		dev_vdbg(hsotg->dev, "qtd=%p\n", qtd);
+
+		if (n_desc) {
+			/* SG request - more than 1 QTD */
+			chan->xfer_dma = qtd->urb->dma +
+					qtd->urb->actual_length;
+			chan->xfer_len = qtd->urb->length -
+					qtd->urb->actual_length;
+			dev_vdbg(hsotg->dev, "buf=%08lx len=%d\n",
+				 (unsigned long)chan->xfer_dma, chan->xfer_len);
+		}
+
+		qtd->n_desc = 0;
+		do {
+			if (n_desc > 1) {
+				qh->desc_list[n_desc - 1].status |= HOST_DMA_A;
+				dev_vdbg(hsotg->dev,
+					 "set A bit in desc %d (%p)\n",
+					 n_desc - 1,
+					 &qh->desc_list[n_desc - 1]);
+			}
+			dwc2_fill_host_dma_desc(hsotg, chan, qtd, qh, n_desc);
+			dev_vdbg(hsotg->dev,
+				 "desc %d (%p) buf=%08x status=%08x\n",
+				 n_desc, &qh->desc_list[n_desc],
+				 qh->desc_list[n_desc].buf,
+				 qh->desc_list[n_desc].status);
+			qtd->n_desc++;
+			n_desc++;
+		} while (chan->xfer_len > 0 &&
+			 n_desc != MAX_DMA_DESC_NUM_GENERIC);
+
+		dev_vdbg(hsotg->dev, "n_desc=%d\n", n_desc);
+		qtd->in_process = 1;
+		if (qh->ep_type == USB_ENDPOINT_XFER_CONTROL)
+			break;
+		if (n_desc == MAX_DMA_DESC_NUM_GENERIC)
+			break;
+	}
+
+	if (n_desc) {
+		qh->desc_list[n_desc - 1].status |=
+				HOST_DMA_IOC | HOST_DMA_EOL | HOST_DMA_A;
+		dev_vdbg(hsotg->dev, "set IOC/EOL/A bits in desc %d (%p)\n",
+			 n_desc - 1, &qh->desc_list[n_desc - 1]);
+		if (n_desc > 1) {
+			qh->desc_list[0].status |= HOST_DMA_A;
+			dev_vdbg(hsotg->dev, "set A bit in desc 0 (%p)\n",
+				 &qh->desc_list[0]);
+		}
+		chan->ntd = n_desc;
+	}
+}
+
+/**
+ * dwc2_hcd_start_xfer_ddma() - Starts a transfer in Descriptor DMA mode
+ *
+ * @hsotg: The HCD state structure for the DWC OTG controller
+ * @qh:    The QH to init
+ *
+ * Return: 0 if successful, negative error code otherwise
+ *
+ * For Control and Bulk endpoints, initializes descriptor list and starts the
+ * transfer. For Interrupt and Isochronous endpoints, initializes descriptor
+ * list then updates FrameList, marking appropriate entries as active.
+ *
+ * For Isochronous endpoints the starting descriptor index is calculated based
+ * on the scheduled frame, but only on the first transfer descriptor within a
+ * session. Then the transfer is started via enabling the channel.
+ *
+ * For Isochronous endpoints the channel is not halted on XferComplete
+ * interrupt so remains assigned to the endpoint(QH) until session is done.
+ */
+void dwc2_hcd_start_xfer_ddma(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
+{
+	/* Channel is already assigned */
+	struct dwc2_host_chan *chan = qh->channel;
+	u16 skip_frames = 0;
+
+	switch (chan->ep_type) {
+	case USB_ENDPOINT_XFER_CONTROL:
+	case USB_ENDPOINT_XFER_BULK:
+		dwc2_init_non_isoc_dma_desc(hsotg, qh);
+		dwc2_hc_start_transfer_ddma(hsotg, chan);
+		break;
+	case USB_ENDPOINT_XFER_INT:
+		dwc2_init_non_isoc_dma_desc(hsotg, qh);
+		dwc2_update_frame_list(hsotg, qh, 1);
+		dwc2_hc_start_transfer_ddma(hsotg, chan);
+		break;
+	case USB_ENDPOINT_XFER_ISOC:
+		if (!qh->ntd)
+			skip_frames = dwc2_recalc_initial_desc_idx(hsotg, qh);
+		dwc2_init_isoc_dma_desc(hsotg, qh, skip_frames);
+
+		if (!chan->xfer_started) {
+			dwc2_update_frame_list(hsotg, qh, 1);
+
+			/*
+			 * Always set to max, instead of actual size. Otherwise
+			 * ntd will be changed with channel being enabled. Not
+			 * recommended.
+			 */
+			chan->ntd = dwc2_max_desc_num(qh);
+
+			/* Enable channel only once for ISOC */
+			dwc2_hc_start_transfer_ddma(hsotg, chan);
+		}
+
+		break;
+	default:
+		break;
+	}
+}
+
+#define DWC2_CMPL_DONE		1
+#define DWC2_CMPL_STOP		2
+
+static int dwc2_cmpl_host_isoc_dma_desc(struct dwc2_hsotg *hsotg,
+					struct dwc2_host_chan *chan,
+					struct dwc2_qtd *qtd,
+					struct dwc2_qh *qh, u16 idx)
+{
+	struct dwc2_hcd_dma_desc *dma_desc = &qh->desc_list[idx];
+	struct dwc2_hcd_iso_packet_desc *frame_desc;
+	u16 remain = 0;
+	int rc = 0;
+
+	frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index_last];
+	dma_desc->buf = (u32)(qtd->urb->dma + frame_desc->offset);
+	if (chan->ep_is_in)
+		remain = dma_desc->status >> HOST_DMA_ISOC_NBYTES_SHIFT &
+			HOST_DMA_ISOC_NBYTES_MASK >> HOST_DMA_ISOC_NBYTES_SHIFT;
+
+	if ((dma_desc->status & HOST_DMA_STS_MASK) == HOST_DMA_STS_PKTERR) {
+		/*
+		 * XactError, or unable to complete all the transactions
+		 * in the scheduled micro-frame/frame, both indicated by
+		 * HOST_DMA_STS_PKTERR
+		 */
+		qtd->urb->error_count++;
+		frame_desc->actual_length = qh->n_bytes[idx] - remain;
+		frame_desc->status = -EPROTO;
+	} else {
+		/* Success */
+		frame_desc->actual_length = qh->n_bytes[idx] - remain;
+		frame_desc->status = 0;
+	}
+
+	if (++qtd->isoc_frame_index == qtd->urb->packet_count) {
+		/*
+		 * urb->status is not used for isoc transfers here. The
+		 * individual frame_desc status are used instead.
+		 */
+		dwc2_host_complete(hsotg, qtd->urb->priv, qtd->urb, 0);
+		dwc2_hcd_qtd_unlink_and_free(hsotg, qtd, qh);
+
+		/*
+		 * This check is necessary because urb_dequeue can be called
+		 * from urb complete callback (sound driver for example). All
+		 * pending URBs are dequeued there, so no need for further
+		 * processing.
+		 */
+		if (chan->halt_status == DWC2_HC_XFER_URB_DEQUEUE)
+			return -1;
+		rc = DWC2_CMPL_DONE;
+	}
+
+	qh->ntd--;
+
+	/* Stop if IOC requested descriptor reached */
+	if (dma_desc->status & HOST_DMA_IOC)
+		rc = DWC2_CMPL_STOP;
+
+	return rc;
+}
+
+static void dwc2_complete_isoc_xfer_ddma(struct dwc2_hsotg *hsotg,
+					 struct dwc2_host_chan *chan,
+					 enum dwc2_halt_status halt_status)
+{
+	struct dwc2_hcd_iso_packet_desc *frame_desc;
+	struct dwc2_qtd *qtd, *qtd_tmp;
+	struct dwc2_qh *qh;
+	u16 idx;
+	int rc;
+
+	qh = chan->qh;
+	idx = qh->td_first;
+
+	if (chan->halt_status == DWC2_HC_XFER_URB_DEQUEUE) {
+		list_for_each_entry(qtd, &qh->qtd_list, qtd_list_entry)
+			qtd->in_process = 0;
+		return;
+	}
+
+	if (halt_status == DWC2_HC_XFER_AHB_ERR ||
+	    halt_status == DWC2_HC_XFER_BABBLE_ERR) {
+		/*
+		 * Channel is halted in these error cases, considered as serious
+		 * issues.
+		 * Complete all URBs marking all frames as failed, irrespective
+		 * whether some of the descriptors (frames) succeeded or not.
+		 * Pass error code to completion routine as well, to update
+		 * urb->status, some of class drivers might use it to stop
+		 * queing transfer requests.
+		 */
+		int err = halt_status == DWC2_HC_XFER_AHB_ERR ?
+			  -EIO : -EOVERFLOW;
+
+		list_for_each_entry_safe(qtd, qtd_tmp, &qh->qtd_list,
+					 qtd_list_entry) {
+			for (idx = 0; idx < qtd->urb->packet_count; idx++) {
+				frame_desc = &qtd->urb->iso_descs[idx];
+				frame_desc->status = err;
+			}
+
+			dwc2_host_complete(hsotg, qtd->urb->priv, qtd->urb,
+					   err);
+			dwc2_hcd_qtd_unlink_and_free(hsotg, qtd, qh);
+		}
+
+		return;
+	}
+
+	list_for_each_entry_safe(qtd, qtd_tmp, &qh->qtd_list, qtd_list_entry) {
+		if (!qtd->in_process)
+			break;
+		do {
+			rc = dwc2_cmpl_host_isoc_dma_desc(hsotg, chan, qtd, qh,
+							  idx);
+			if (rc < 0)
+				return;
+			idx = dwc2_desclist_idx_inc(idx, qh->interval,
+						    chan->speed);
+			if (rc == DWC2_CMPL_STOP)
+				goto stop_scan;
+			if (rc == DWC2_CMPL_DONE)
+				break;
+		} while (idx != qh->td_first);
+	}
+
+stop_scan:
+	qh->td_first = idx;
+}
+
+static int dwc2_update_non_isoc_urb_state_ddma(struct dwc2_hsotg *hsotg,
+					struct dwc2_host_chan *chan,
+					struct dwc2_qtd *qtd,
+					struct dwc2_hcd_dma_desc *dma_desc,
+					enum dwc2_halt_status halt_status,
+					u32 n_bytes, int *xfer_done)
+{
+	struct dwc2_hcd_urb *urb = qtd->urb;
+	u16 remain = 0;
+
+	if (chan->ep_is_in)
+		remain = dma_desc->status >> HOST_DMA_NBYTES_SHIFT &
+			 HOST_DMA_NBYTES_MASK >> HOST_DMA_NBYTES_SHIFT;
+
+	dev_vdbg(hsotg->dev, "remain=%d dwc2_urb=%p\n", remain, urb);
+
+	if (halt_status == DWC2_HC_XFER_AHB_ERR) {
+		dev_err(hsotg->dev, "EIO\n");
+		urb->status = -EIO;
+		return 1;
+	}
+
+	if ((dma_desc->status & HOST_DMA_STS_MASK) == HOST_DMA_STS_PKTERR) {
+		switch (halt_status) {
+		case DWC2_HC_XFER_STALL:
+			dev_vdbg(hsotg->dev, "Stall\n");
+			urb->status = -EPIPE;
+			break;
+		case DWC2_HC_XFER_BABBLE_ERR:
+			dev_err(hsotg->dev, "Babble\n");
+			urb->status = -EOVERFLOW;
+			break;
+		case DWC2_HC_XFER_XACT_ERR:
+			dev_err(hsotg->dev, "XactErr\n");
+			urb->status = -EPROTO;
+			break;
+		default:
+			dev_err(hsotg->dev,
+				"%s: Unhandled descriptor error status (%d)\n",
+				__func__, halt_status);
+			break;
+		}
+		return 1;
+	}
+
+	if (dma_desc->status & HOST_DMA_A) {
+		dev_vdbg(hsotg->dev,
+			 "Active descriptor encountered on channel %d\n",
+			 chan->hc_num);
+		return 0;
+	}
+
+	if (chan->ep_type == USB_ENDPOINT_XFER_CONTROL) {
+		if (qtd->control_phase == DWC2_CONTROL_DATA) {
+			urb->actual_length += n_bytes - remain;
+			if (remain || urb->actual_length >= urb->length) {
+				/*
+				 * For Control Data stage do not set urb->status
+				 * to 0, to prevent URB callback. Set it when
+				 * Status phase is done. See below.
+				 */
+				*xfer_done = 1;
+			}
+		} else if (qtd->control_phase == DWC2_CONTROL_STATUS) {
+			urb->status = 0;
+			*xfer_done = 1;
+		}
+		/* No handling for SETUP stage */
+	} else {
+		/* BULK and INTR */
+		urb->actual_length += n_bytes - remain;
+		dev_vdbg(hsotg->dev, "length=%d actual=%d\n", urb->length,
+			 urb->actual_length);
+		if (remain || urb->actual_length >= urb->length) {
+			urb->status = 0;
+			*xfer_done = 1;
+		}
+	}
+
+	return 0;
+}
+
+static int dwc2_process_non_isoc_desc(struct dwc2_hsotg *hsotg,
+				      struct dwc2_host_chan *chan,
+				      int chnum, struct dwc2_qtd *qtd,
+				      int desc_num,
+				      enum dwc2_halt_status halt_status,
+				      int *xfer_done)
+{
+	struct dwc2_qh *qh = chan->qh;
+	struct dwc2_hcd_urb *urb = qtd->urb;
+	struct dwc2_hcd_dma_desc *dma_desc;
+	u32 n_bytes;
+	int failed;
+
+	dev_vdbg(hsotg->dev, "%s()\n", __func__);
+
+	dma_desc = &qh->desc_list[desc_num];
+	n_bytes = qh->n_bytes[desc_num];
+	dev_vdbg(hsotg->dev,
+		 "qtd=%p dwc2_urb=%p desc_num=%d desc=%p n_bytes=%d\n",
+		 qtd, urb, desc_num, dma_desc, n_bytes);
+	failed = dwc2_update_non_isoc_urb_state_ddma(hsotg, chan, qtd, dma_desc,
+						     halt_status, n_bytes,
+						     xfer_done);
+	if (failed || (*xfer_done && urb->status != -EINPROGRESS)) {
+		dwc2_host_complete(hsotg, urb->priv, urb, urb->status);
+		dwc2_hcd_qtd_unlink_and_free(hsotg, qtd, qh);
+		dev_vdbg(hsotg->dev, "failed=%1x xfer_done=%1x status=%08x\n",
+			 failed, *xfer_done, urb->status);
+		return failed;
+	}
+
+	if (qh->ep_type == USB_ENDPOINT_XFER_CONTROL) {
+		switch (qtd->control_phase) {
+		case DWC2_CONTROL_SETUP:
+			if (urb->length > 0)
+				qtd->control_phase = DWC2_CONTROL_DATA;
+			else
+				qtd->control_phase = DWC2_CONTROL_STATUS;
+			dev_vdbg(hsotg->dev,
+				 "  Control setup transaction done\n");
+			break;
+		case DWC2_CONTROL_DATA:
+			if (*xfer_done) {
+				qtd->control_phase = DWC2_CONTROL_STATUS;
+				dev_vdbg(hsotg->dev,
+					 "  Control data transfer done\n");
+			} else if (desc_num + 1 == qtd->n_desc) {
+				/*
+				 * Last descriptor for Control data stage which
+				 * is not completed yet
+				 */
+				dwc2_hcd_save_data_toggle(hsotg, chan, chnum,
+							  qtd);
+			}
+			break;
+		default:
+			break;
+		}
+	}
+
+	return 0;
+}
+
+static void dwc2_complete_non_isoc_xfer_ddma(struct dwc2_hsotg *hsotg,
+					     struct dwc2_host_chan *chan,
+					     int chnum,
+					     enum dwc2_halt_status halt_status)
+{
+	struct list_head *qtd_item, *qtd_tmp;
+	struct dwc2_qh *qh = chan->qh;
+	struct dwc2_qtd *qtd = NULL;
+	int xfer_done;
+	int desc_num = 0;
+
+	if (chan->halt_status == DWC2_HC_XFER_URB_DEQUEUE) {
+		list_for_each_entry(qtd, &qh->qtd_list, qtd_list_entry)
+			qtd->in_process = 0;
+		return;
+	}
+
+	list_for_each_safe(qtd_item, qtd_tmp, &qh->qtd_list) {
+		int i;
+
+		qtd = list_entry(qtd_item, struct dwc2_qtd, qtd_list_entry);
+		xfer_done = 0;
+
+		for (i = 0; i < qtd->n_desc; i++) {
+			if (dwc2_process_non_isoc_desc(hsotg, chan, chnum, qtd,
+						       desc_num, halt_status,
+						       &xfer_done))
+				break;
+			desc_num++;
+		}
+	}
+
+	if (qh->ep_type != USB_ENDPOINT_XFER_CONTROL) {
+		/*
+		 * Resetting the data toggle for bulk and interrupt endpoints
+		 * in case of stall. See handle_hc_stall_intr().
+		 */
+		if (halt_status == DWC2_HC_XFER_STALL)
+			qh->data_toggle = DWC2_HC_PID_DATA0;
+		else if (qtd)
+			dwc2_hcd_save_data_toggle(hsotg, chan, chnum, qtd);
+	}
+
+	if (halt_status == DWC2_HC_XFER_COMPLETE) {
+		if (chan->hcint & HCINTMSK_NYET) {
+			/*
+			 * Got a NYET on the last transaction of the transfer.
+			 * It means that the endpoint should be in the PING
+			 * state at the beginning of the next transfer.
+			 */
+			qh->ping_state = 1;
+		}
+	}
+}
+
+/**
+ * dwc2_hcd_complete_xfer_ddma() - Scans the descriptor list, updates URB's
+ * status and calls completion routine for the URB if it's done. Called from
+ * interrupt handlers.
+ *
+ * @hsotg:       The HCD state structure for the DWC OTG controller
+ * @chan:        Host channel the transfer is completed on
+ * @chnum:       Index of Host channel registers
+ * @halt_status: Reason the channel is being halted or just XferComplete
+ *               for isochronous transfers
+ *
+ * Releases the channel to be used by other transfers.
+ * In case of Isochronous endpoint the channel is not halted until the end of
+ * the session, i.e. QTD list is empty.
+ * If periodic channel released the FrameList is updated accordingly.
+ * Calls transaction selection routines to activate pending transfers.
+ */
+void dwc2_hcd_complete_xfer_ddma(struct dwc2_hsotg *hsotg,
+				 struct dwc2_host_chan *chan, int chnum,
+				 enum dwc2_halt_status halt_status)
+{
+	struct dwc2_qh *qh = chan->qh;
+	int continue_isoc_xfer = 0;
+	enum dwc2_transaction_type tr_type;
+
+	if (chan->ep_type == USB_ENDPOINT_XFER_ISOC) {
+		dwc2_complete_isoc_xfer_ddma(hsotg, chan, halt_status);
+
+		/* Release the channel if halted or session completed */
+		if (halt_status != DWC2_HC_XFER_COMPLETE ||
+		    list_empty(&qh->qtd_list)) {
+			/* Halt the channel if session completed */
+			if (halt_status == DWC2_HC_XFER_COMPLETE)
+				dwc2_hc_halt(hsotg, chan, halt_status);
+			dwc2_release_channel_ddma(hsotg, qh);
+			dwc2_hcd_qh_unlink(hsotg, qh);
+		} else {
+			/* Keep in assigned schedule to continue transfer */
+			list_move(&qh->qh_list_entry,
+				  &hsotg->periodic_sched_assigned);
+			continue_isoc_xfer = 1;
+		}
+		/*
+		 * Todo: Consider the case when period exceeds FrameList size.
+		 * Frame Rollover interrupt should be used.
+		 */
+	} else {
+		/*
+		 * Scan descriptor list to complete the URB(s), then release
+		 * the channel
+		 */
+		dwc2_complete_non_isoc_xfer_ddma(hsotg, chan, chnum,
+						 halt_status);
+		dwc2_release_channel_ddma(hsotg, qh);
+		dwc2_hcd_qh_unlink(hsotg, qh);
+
+		if (!list_empty(&qh->qtd_list)) {
+			/*
+			 * Add back to inactive non-periodic schedule on normal
+			 * completion
+			 */
+			dwc2_hcd_qh_add(hsotg, qh);
+		}
+	}
+
+	tr_type = dwc2_hcd_select_transactions(hsotg);
+	if (tr_type != DWC2_TRANSACTION_NONE || continue_isoc_xfer) {
+		if (continue_isoc_xfer) {
+			if (tr_type == DWC2_TRANSACTION_NONE)
+				tr_type = DWC2_TRANSACTION_PERIODIC;
+			else if (tr_type == DWC2_TRANSACTION_NON_PERIODIC)
+				tr_type = DWC2_TRANSACTION_ALL;
+		}
+		dwc2_hcd_queue_transactions(hsotg, tr_type);
+	}
+}
diff --git a/drivers/staging/dwc2/hcd_intr.c b/drivers/staging/dwc2/hcd_intr.c
new file mode 100644
index 0000000..8b68df8
--- /dev/null
+++ b/drivers/staging/dwc2/hcd_intr.c
@@ -0,0 +1,2104 @@
+/*
+ * hcd_intr.c - DesignWare HS OTG Controller host-mode interrupt handling
+ *
+ * Copyright (C) 2004-2013 Synopsys, Inc.
+ *
+ * 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, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 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 names of the above-listed copyright holders may not 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 the License, or (at your option) any
+ * later version.
+ *
+ * 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.
+ */
+
+/*
+ * This file contains the interrupt handlers for Host mode
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+
+#include <linux/usb/hcd.h>
+#include <linux/usb/ch11.h>
+
+#include "core.h"
+#include "hcd.h"
+
+/* This function is for debug only */
+static void dwc2_track_missed_sofs(struct dwc2_hsotg *hsotg)
+{
+#ifdef CONFIG_USB_DWC2_TRACK_MISSED_SOFS
+#warning Compiling code to track missed SOFs
+
+	u16 curr_frame_number = hsotg->frame_number;
+
+	if (hsotg->frame_num_idx < FRAME_NUM_ARRAY_SIZE) {
+		if (((hsotg->last_frame_num + 1) & HFNUM_MAX_FRNUM) !=
+		    curr_frame_number) {
+			hsotg->frame_num_array[hsotg->frame_num_idx] =
+					curr_frame_number;
+			hsotg->last_frame_num_array[hsotg->frame_num_idx] =
+					hsotg->last_frame_num;
+			hsotg->frame_num_idx++;
+		}
+	} else if (!hsotg->dumped_frame_num_array) {
+		int i;
+
+		dev_info(hsotg->dev, "Frame     Last Frame\n");
+		dev_info(hsotg->dev, "-----     ----------\n");
+		for (i = 0; i < FRAME_NUM_ARRAY_SIZE; i++) {
+			dev_info(hsotg->dev, "0x%04x    0x%04x\n",
+				 hsotg->frame_num_array[i],
+				 hsotg->last_frame_num_array[i]);
+		}
+		hsotg->dumped_frame_num_array = 1;
+	}
+	hsotg->last_frame_num = curr_frame_number;
+#endif
+}
+
+static void dwc2_hc_handle_tt_clear(struct dwc2_hsotg *hsotg,
+				    struct dwc2_host_chan *chan,
+				    struct dwc2_qtd *qtd)
+{
+	struct urb *usb_urb;
+
+	if (!chan->qh || !qtd->urb)
+		return;
+
+	usb_urb = qtd->urb->priv;
+	if (!usb_urb || !usb_urb->dev)
+		return;
+
+	if (chan->qh->dev_speed != USB_SPEED_HIGH &&
+	    qtd->urb->status != -EPIPE && qtd->urb->status != -EREMOTEIO) {
+		chan->qh->tt_buffer_dirty = 1;
+		if (usb_hub_clear_tt_buffer(usb_urb))
+			/* Clear failed; let's hope things work anyway */
+			chan->qh->tt_buffer_dirty = 0;
+	}
+}
+
+/*
+ * Handles the start-of-frame interrupt in host mode. Non-periodic
+ * transactions may be queued to the DWC_otg controller for the current
+ * (micro)frame. Periodic transactions may be queued to the controller
+ * for the next (micro)frame.
+ */
+static void dwc2_sof_intr(struct dwc2_hsotg *hsotg)
+{
+	struct list_head *qh_entry;
+	struct dwc2_qh *qh;
+	u32 hfnum;
+	enum dwc2_transaction_type tr_type;
+
+#ifdef DEBUG_SOF
+	dev_vdbg(hsotg->dev, "--Start of Frame Interrupt--\n");
+#endif
+
+	hfnum = readl(hsotg->regs + HFNUM);
+	hsotg->frame_number = hfnum >> HFNUM_FRNUM_SHIFT &
+			    HFNUM_FRNUM_MASK >> HFNUM_FRNUM_SHIFT;
+
+	dwc2_track_missed_sofs(hsotg);
+
+	/* Determine whether any periodic QHs should be executed */
+	qh_entry = hsotg->periodic_sched_inactive.next;
+	while (qh_entry != &hsotg->periodic_sched_inactive) {
+		qh = list_entry(qh_entry, struct dwc2_qh, qh_list_entry);
+		qh_entry = qh_entry->next;
+		if (dwc2_frame_num_le(qh->sched_frame, hsotg->frame_number))
+			/*
+			 * Move QH to the ready list to be executed next
+			 * (micro)frame
+			 */
+			list_move(&qh->qh_list_entry,
+				  &hsotg->periodic_sched_ready);
+	}
+	tr_type = dwc2_hcd_select_transactions(hsotg);
+	if (tr_type != DWC2_TRANSACTION_NONE)
+		dwc2_hcd_queue_transactions(hsotg, tr_type);
+
+	/* Clear interrupt */
+	writel(GINTSTS_SOF, hsotg->regs + GINTSTS);
+}
+
+/*
+ * Handles the Rx FIFO Level Interrupt, which indicates that there is
+ * at least one packet in the Rx FIFO. The packets are moved from the FIFO to
+ * memory if the DWC_otg controller is operating in Slave mode.
+ */
+static void dwc2_rx_fifo_level_intr(struct dwc2_hsotg *hsotg)
+{
+	u32 grxsts, chnum, bcnt, dpid, pktsts;
+	struct dwc2_host_chan *chan;
+
+	dev_vdbg(hsotg->dev, "--RxFIFO Level Interrupt--\n");
+
+	grxsts = readl(hsotg->regs + GRXSTSP);
+	chnum = grxsts >> GRXSTS_HCHNUM_SHIFT &
+		GRXSTS_HCHNUM_MASK >> GRXSTS_HCHNUM_SHIFT;
+	chan = hsotg->hc_ptr_array[chnum];
+	if (!chan) {
+		dev_err(hsotg->dev, "Unable to get corresponding channel\n");
+		return;
+	}
+
+	bcnt = grxsts >> GRXSTS_BYTECNT_SHIFT &
+	       GRXSTS_BYTECNT_MASK >> GRXSTS_BYTECNT_SHIFT;
+	dpid = grxsts >> GRXSTS_DPID_SHIFT &
+	       GRXSTS_DPID_MASK >> GRXSTS_DPID_SHIFT;
+	pktsts = grxsts & GRXSTS_PKTSTS_MASK;
+
+	/* Packet Status */
+	dev_vdbg(hsotg->dev, "    Ch num = %d\n", chnum);
+	dev_vdbg(hsotg->dev, "    Count = %d\n", bcnt);
+	dev_vdbg(hsotg->dev, "    DPID = %d, chan.dpid = %d\n", dpid,
+		 chan->data_pid_start);
+	dev_vdbg(hsotg->dev, "    PStatus = %d\n",
+		 pktsts >> GRXSTS_PKTSTS_SHIFT &
+		 GRXSTS_PKTSTS_MASK >> GRXSTS_PKTSTS_SHIFT);
+
+	switch (pktsts) {
+	case GRXSTS_PKTSTS_HCHIN:
+		/* Read the data into the host buffer */
+		if (bcnt > 0) {
+			dwc2_read_packet(hsotg, chan->xfer_buf, bcnt);
+
+			/* Update the HC fields for the next packet received */
+			chan->xfer_count += bcnt;
+			chan->xfer_buf += bcnt;
+		}
+		break;
+	case GRXSTS_PKTSTS_HCHIN_XFER_COMP:
+	case GRXSTS_PKTSTS_DATATOGGLEERR:
+	case GRXSTS_PKTSTS_HCHHALTED:
+		/* Handled in interrupt, just ignore data */
+		break;
+	default:
+		dev_err(hsotg->dev,
+			"RxFIFO Level Interrupt: Unknown status %d\n", pktsts);
+		break;
+	}
+}
+
+/*
+ * This interrupt occurs when the non-periodic Tx FIFO is half-empty. More
+ * data packets may be written to the FIFO for OUT transfers. More requests
+ * may be written to the non-periodic request queue for IN transfers. This
+ * interrupt is enabled only in Slave mode.
+ */
+static void dwc2_np_tx_fifo_empty_intr(struct dwc2_hsotg *hsotg)
+{
+	dev_vdbg(hsotg->dev, "--Non-Periodic TxFIFO Empty Interrupt--\n");
+	dwc2_hcd_queue_transactions(hsotg, DWC2_TRANSACTION_NON_PERIODIC);
+}
+
+/*
+ * This interrupt occurs when the periodic Tx FIFO is half-empty. More data
+ * packets may be written to the FIFO for OUT transfers. More requests may be
+ * written to the periodic request queue for IN transfers. This interrupt is
+ * enabled only in Slave mode.
+ */
+static void dwc2_perio_tx_fifo_empty_intr(struct dwc2_hsotg *hsotg)
+{
+	dev_vdbg(hsotg->dev, "--Periodic TxFIFO Empty Interrupt--\n");
+	dwc2_hcd_queue_transactions(hsotg, DWC2_TRANSACTION_PERIODIC);
+}
+
+static void dwc2_hprt0_enable(struct dwc2_hsotg *hsotg, u32 hprt0,
+			      u32 *hprt0_modify)
+{
+	struct dwc2_core_params *params = hsotg->core_params;
+	int do_reset = 0;
+	u32 usbcfg;
+	u32 prtspd;
+	u32 hcfg;
+	u32 hfir;
+
+	dev_vdbg(hsotg->dev, "%s(%p)\n", __func__, hsotg);
+
+	/* Every time when port enables calculate HFIR.FrInterval */
+	hfir = readl(hsotg->regs + HFIR);
+	hfir &= ~HFIR_FRINT_MASK;
+	hfir |= dwc2_calc_frame_interval(hsotg) << HFIR_FRINT_SHIFT &
+		HFIR_FRINT_MASK;
+	writel(hfir, hsotg->regs + HFIR);
+
+	/* Check if we need to adjust the PHY clock speed for low power */
+	if (!params->host_support_fs_ls_low_power) {
+		/* Port has been enabled, set the reset change flag */
+		hsotg->flags.b.port_reset_change = 1;
+		return;
+	}
+
+	usbcfg = readl(hsotg->regs + GUSBCFG);
+	prtspd = hprt0 & HPRT0_SPD_MASK;
+
+	if (prtspd == HPRT0_SPD_LOW_SPEED || prtspd == HPRT0_SPD_FULL_SPEED) {
+		/* Low power */
+		if (!(usbcfg & GUSBCFG_PHY_LP_CLK_SEL)) {
+			/* Set PHY low power clock select for FS/LS devices */
+			usbcfg |= GUSBCFG_PHY_LP_CLK_SEL;
+			writel(usbcfg, hsotg->regs + GUSBCFG);
+			do_reset = 1;
+		}
+
+		hcfg = readl(hsotg->regs + HCFG);
+
+		if (prtspd == HPRT0_SPD_LOW_SPEED &&
+		    params->host_ls_low_power_phy_clk ==
+		    DWC2_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ) {
+			/* 6 MHZ */
+			dev_vdbg(hsotg->dev,
+				 "FS_PHY programming HCFG to 6 MHz\n");
+			if ((hcfg & HCFG_FSLSPCLKSEL_MASK) !=
+			    HCFG_FSLSPCLKSEL_6_MHZ) {
+				hcfg &= ~HCFG_FSLSPCLKSEL_MASK;
+				hcfg |= HCFG_FSLSPCLKSEL_6_MHZ;
+				writel(hcfg, hsotg->regs + HCFG);
+				do_reset = 1;
+			}
+		} else {
+			/* 48 MHZ */
+			dev_vdbg(hsotg->dev,
+				 "FS_PHY programming HCFG to 48 MHz\n");
+			if ((hcfg & HCFG_FSLSPCLKSEL_MASK) !=
+			    HCFG_FSLSPCLKSEL_48_MHZ) {
+				hcfg &= ~HCFG_FSLSPCLKSEL_MASK;
+				hcfg |= HCFG_FSLSPCLKSEL_48_MHZ;
+				writel(hcfg, hsotg->regs + HCFG);
+				do_reset = 1;
+			}
+		}
+	} else {
+		/* Not low power */
+		if (usbcfg & GUSBCFG_PHY_LP_CLK_SEL) {
+			usbcfg &= ~GUSBCFG_PHY_LP_CLK_SEL;
+			writel(usbcfg, hsotg->regs + GUSBCFG);
+			do_reset = 1;
+		}
+	}
+
+	if (do_reset) {
+		*hprt0_modify |= HPRT0_RST;
+		queue_delayed_work(hsotg->wq_otg, &hsotg->reset_work,
+				   msecs_to_jiffies(60));
+	} else {
+		/* Port has been enabled, set the reset change flag */
+		hsotg->flags.b.port_reset_change = 1;
+	}
+}
+
+/*
+ * There are multiple conditions that can cause a port interrupt. This function
+ * determines which interrupt conditions have occurred and handles them
+ * appropriately.
+ */
+static void dwc2_port_intr(struct dwc2_hsotg *hsotg)
+{
+	u32 hprt0;
+	u32 hprt0_modify;
+
+	dev_vdbg(hsotg->dev, "--Port Interrupt--\n");
+
+	hprt0 = readl(hsotg->regs + HPRT0);
+	hprt0_modify = hprt0;
+
+	/*
+	 * Clear appropriate bits in HPRT0 to clear the interrupt bit in
+	 * GINTSTS
+	 */
+	hprt0_modify &= ~(HPRT0_ENA | HPRT0_CONNDET | HPRT0_ENACHG |
+			  HPRT0_OVRCURRCHG);
+
+	/*
+	 * Port Connect Detected
+	 * Set flag and clear if detected
+	 */
+	if (hprt0 & HPRT0_CONNDET) {
+		dev_vdbg(hsotg->dev,
+			 "--Port Interrupt HPRT0=0x%08x Port Connect Detected--\n",
+			 hprt0);
+		hsotg->flags.b.port_connect_status_change = 1;
+		hsotg->flags.b.port_connect_status = 1;
+		hprt0_modify |= HPRT0_CONNDET;
+
+		/*
+		 * The Hub driver asserts a reset when it sees port connect
+		 * status change flag
+		 */
+	}
+
+	/*
+	 * Port Enable Changed
+	 * Clear if detected - Set internal flag if disabled
+	 */
+	if (hprt0 & HPRT0_ENACHG) {
+		dev_vdbg(hsotg->dev,
+			 "  --Port Interrupt HPRT0=0x%08x Port Enable Changed (now %d)--\n",
+			 hprt0, !!(hprt0 & HPRT0_ENA));
+		hprt0_modify |= HPRT0_ENACHG;
+		if (hprt0 & HPRT0_ENA)
+			dwc2_hprt0_enable(hsotg, hprt0, &hprt0_modify);
+		else
+			hsotg->flags.b.port_enable_change = 1;
+	}
+
+	/* Overcurrent Change Interrupt */
+	if (hprt0 & HPRT0_OVRCURRCHG) {
+		dev_vdbg(hsotg->dev,
+			 "  --Port Interrupt HPRT0=0x%08x Port Overcurrent Changed--\n",
+			 hprt0);
+		hsotg->flags.b.port_over_current_change = 1;
+		hprt0_modify |= HPRT0_OVRCURRCHG;
+	}
+
+	/* Clear Port Interrupts */
+	writel(hprt0_modify, hsotg->regs + HPRT0);
+}
+
+/*
+ * Gets the actual length of a transfer after the transfer halts. halt_status
+ * holds the reason for the halt.
+ *
+ * For IN transfers where halt_status is DWC2_HC_XFER_COMPLETE, *short_read
+ * is set to 1 upon return if less than the requested number of bytes were
+ * transferred. short_read may also be NULL on entry, in which case it remains
+ * unchanged.
+ */
+static u32 dwc2_get_actual_xfer_length(struct dwc2_hsotg *hsotg,
+				       struct dwc2_host_chan *chan, int chnum,
+				       struct dwc2_qtd *qtd,
+				       enum dwc2_halt_status halt_status,
+				       int *short_read)
+{
+	u32 hctsiz, count, length;
+
+	hctsiz = readl(hsotg->regs + HCTSIZ(chnum));
+
+	if (halt_status == DWC2_HC_XFER_COMPLETE) {
+		if (chan->ep_is_in) {
+			count = hctsiz >> TSIZ_XFERSIZE_SHIFT &
+				TSIZ_XFERSIZE_MASK >> TSIZ_XFERSIZE_SHIFT;
+			length = chan->xfer_len - count;
+			if (short_read != NULL)
+				*short_read = (count != 0);
+		} else if (chan->qh->do_split) {
+			length = qtd->ssplit_out_xfer_count;
+		} else {
+			length = chan->xfer_len;
+		}
+	} else {
+		/*
+		 * Must use the hctsiz.pktcnt field to determine how much data
+		 * has been transferred. This field reflects the number of
+		 * packets that have been transferred via the USB. This is
+		 * always an integral number of packets if the transfer was
+		 * halted before its normal completion. (Can't use the
+		 * hctsiz.xfersize field because that reflects the number of
+		 * bytes transferred via the AHB, not the USB).
+		 */
+		count = hctsiz >> TSIZ_PKTCNT_SHIFT &
+			TSIZ_PKTCNT_MASK >> TSIZ_PKTCNT_SHIFT;
+		length = (chan->start_pkt_count - count) * chan->max_packet;
+	}
+
+	return length;
+}
+
+/**
+ * dwc2_update_urb_state() - Updates the state of the URB after a Transfer
+ * Complete interrupt on the host channel. Updates the actual_length field
+ * of the URB based on the number of bytes transferred via the host channel.
+ * Sets the URB status if the data transfer is finished.
+ *
+ * Return: 1 if the data transfer specified by the URB is completely finished,
+ * 0 otherwise
+ */
+static int dwc2_update_urb_state(struct dwc2_hsotg *hsotg,
+				 struct dwc2_host_chan *chan, int chnum,
+				 struct dwc2_hcd_urb *urb,
+				 struct dwc2_qtd *qtd)
+{
+	u32 hctsiz;
+	int xfer_done = 0;
+	int short_read = 0;
+	int xfer_length = dwc2_get_actual_xfer_length(hsotg, chan, chnum, qtd,
+						      DWC2_HC_XFER_COMPLETE,
+						      &short_read);
+
+	if (urb->actual_length + xfer_length > urb->length) {
+		dev_warn(hsotg->dev, "%s(): trimming xfer length\n", __func__);
+		xfer_length = urb->length - urb->actual_length;
+	}
+
+	/* Non DWORD-aligned buffer case handling */
+	if (chan->align_buf && xfer_length && chan->ep_is_in) {
+		dev_dbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__);
+		dma_sync_single_for_cpu(hsotg->dev, urb->dma, urb->length,
+					DMA_FROM_DEVICE);
+		memcpy(urb->buf + urb->actual_length, chan->qh->dw_align_buf,
+		       xfer_length);
+		dma_sync_single_for_device(hsotg->dev, urb->dma, urb->length,
+					   DMA_FROM_DEVICE);
+	}
+
+	dev_vdbg(hsotg->dev, "urb->actual_length=%d xfer_length=%d\n",
+		 urb->actual_length, xfer_length);
+	urb->actual_length += xfer_length;
+
+	if (xfer_length && chan->ep_type == USB_ENDPOINT_XFER_BULK &&
+	    (urb->flags & URB_SEND_ZERO_PACKET) &&
+	    urb->actual_length >= urb->length &&
+	    !(urb->length % chan->max_packet)) {
+		xfer_done = 0;
+	} else if (short_read || urb->actual_length >= urb->length) {
+		xfer_done = 1;
+		urb->status = 0;
+	}
+
+	hctsiz = readl(hsotg->regs + HCTSIZ(chnum));
+	dev_vdbg(hsotg->dev, "DWC_otg: %s: %s, channel %d\n",
+		 __func__, (chan->ep_is_in ? "IN" : "OUT"), chnum);
+	dev_vdbg(hsotg->dev, "  chan->xfer_len %d\n", chan->xfer_len);
+	dev_vdbg(hsotg->dev, "  hctsiz.xfersize %d\n",
+		 hctsiz >> TSIZ_XFERSIZE_SHIFT &
+		 TSIZ_XFERSIZE_MASK >> TSIZ_XFERSIZE_SHIFT);
+	dev_vdbg(hsotg->dev, "  urb->transfer_buffer_length %d\n", urb->length);
+	dev_vdbg(hsotg->dev, "  urb->actual_length %d\n", urb->actual_length);
+	dev_vdbg(hsotg->dev, "  short_read %d, xfer_done %d\n", short_read,
+		 xfer_done);
+
+	return xfer_done;
+}
+
+/*
+ * Save the starting data toggle for the next transfer. The data toggle is
+ * saved in the QH for non-control transfers and it's saved in the QTD for
+ * control transfers.
+ */
+void dwc2_hcd_save_data_toggle(struct dwc2_hsotg *hsotg,
+			       struct dwc2_host_chan *chan, int chnum,
+			       struct dwc2_qtd *qtd)
+{
+	u32 hctsiz = readl(hsotg->regs + HCTSIZ(chnum));
+	u32 pid = hctsiz & TSIZ_SC_MC_PID_MASK;
+
+	if (chan->ep_type != USB_ENDPOINT_XFER_CONTROL) {
+		if (pid == TSIZ_SC_MC_PID_DATA0)
+			chan->qh->data_toggle = DWC2_HC_PID_DATA0;
+		else
+			chan->qh->data_toggle = DWC2_HC_PID_DATA1;
+	} else {
+		if (pid == TSIZ_SC_MC_PID_DATA0)
+			qtd->data_toggle = DWC2_HC_PID_DATA0;
+		else
+			qtd->data_toggle = DWC2_HC_PID_DATA1;
+	}
+}
+
+/**
+ * dwc2_update_isoc_urb_state() - Updates the state of an Isochronous URB when
+ * the transfer is stopped for any reason. The fields of the current entry in
+ * the frame descriptor array are set based on the transfer state and the input
+ * halt_status. Completes the Isochronous URB if all the URB frames have been
+ * completed.
+ *
+ * Return: DWC2_HC_XFER_COMPLETE if there are more frames remaining to be
+ * transferred in the URB. Otherwise return DWC2_HC_XFER_URB_COMPLETE.
+ */
+static enum dwc2_halt_status dwc2_update_isoc_urb_state(
+		struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan,
+		int chnum, struct dwc2_qtd *qtd,
+		enum dwc2_halt_status halt_status)
+{
+	struct dwc2_hcd_iso_packet_desc *frame_desc;
+	struct dwc2_hcd_urb *urb = qtd->urb;
+
+	if (!urb)
+		return DWC2_HC_XFER_NO_HALT_STATUS;
+
+	frame_desc = &urb->iso_descs[qtd->isoc_frame_index];
+
+	switch (halt_status) {
+	case DWC2_HC_XFER_COMPLETE:
+		frame_desc->status = 0;
+		frame_desc->actual_length = dwc2_get_actual_xfer_length(hsotg,
+					chan, chnum, qtd, halt_status, NULL);
+
+		/* Non DWORD-aligned buffer case handling */
+		if (chan->align_buf && frame_desc->actual_length &&
+		    chan->ep_is_in) {
+			dev_dbg(hsotg->dev, "%s(): non-aligned buffer\n",
+				__func__);
+			dma_sync_single_for_cpu(hsotg->dev, urb->dma,
+						urb->length, DMA_FROM_DEVICE);
+			memcpy(urb->buf + frame_desc->offset +
+			       qtd->isoc_split_offset, chan->qh->dw_align_buf,
+			       frame_desc->actual_length);
+			dma_sync_single_for_device(hsotg->dev, urb->dma,
+						   urb->length,
+						   DMA_FROM_DEVICE);
+		}
+		break;
+	case DWC2_HC_XFER_FRAME_OVERRUN:
+		urb->error_count++;
+		if (chan->ep_is_in)
+			frame_desc->status = -ENOSR;
+		else
+			frame_desc->status = -ECOMM;
+		frame_desc->actual_length = 0;
+		break;
+	case DWC2_HC_XFER_BABBLE_ERR:
+		urb->error_count++;
+		frame_desc->status = -EOVERFLOW;
+		/* Don't need to update actual_length in this case */
+		break;
+	case DWC2_HC_XFER_XACT_ERR:
+		urb->error_count++;
+		frame_desc->status = -EPROTO;
+		frame_desc->actual_length = dwc2_get_actual_xfer_length(hsotg,
+					chan, chnum, qtd, halt_status, NULL);
+
+		/* Non DWORD-aligned buffer case handling */
+		if (chan->align_buf && frame_desc->actual_length &&
+		    chan->ep_is_in) {
+			dev_dbg(hsotg->dev, "%s(): non-aligned buffer\n",
+				__func__);
+			dma_sync_single_for_cpu(hsotg->dev, urb->dma,
+						urb->length, DMA_FROM_DEVICE);
+			memcpy(urb->buf + frame_desc->offset +
+			       qtd->isoc_split_offset, chan->qh->dw_align_buf,
+			       frame_desc->actual_length);
+			dma_sync_single_for_device(hsotg->dev, urb->dma,
+						   urb->length,
+						   DMA_FROM_DEVICE);
+		}
+
+		/* Skip whole frame */
+		if (chan->qh->do_split &&
+		    chan->ep_type == USB_ENDPOINT_XFER_ISOC && chan->ep_is_in &&
+		    hsotg->core_params->dma_enable > 0) {
+			qtd->complete_split = 0;
+			qtd->isoc_split_offset = 0;
+		}
+
+		break;
+	default:
+		dev_err(hsotg->dev, "Unhandled halt_status (%d)\n",
+			halt_status);
+		break;
+	}
+
+	if (++qtd->isoc_frame_index == urb->packet_count) {
+		/*
+		 * urb->status is not used for isoc transfers. The individual
+		 * frame_desc statuses are used instead.
+		 */
+		dwc2_host_complete(hsotg, urb->priv, urb, 0);
+		halt_status = DWC2_HC_XFER_URB_COMPLETE;
+	} else {
+		halt_status = DWC2_HC_XFER_COMPLETE;
+	}
+
+	return halt_status;
+}
+
+/*
+ * Frees the first QTD in the QH's list if free_qtd is 1. For non-periodic
+ * QHs, removes the QH from the active non-periodic schedule. If any QTDs are
+ * still linked to the QH, the QH is added to the end of the inactive
+ * non-periodic schedule. For periodic QHs, removes the QH from the periodic
+ * schedule if no more QTDs are linked to the QH.
+ */
+static void dwc2_deactivate_qh(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh,
+			       int free_qtd)
+{
+	int continue_split = 0;
+	struct dwc2_qtd *qtd;
+
+	dev_vdbg(hsotg->dev, "  %s(%p,%p,%d)\n", __func__, hsotg, qh, free_qtd);
+
+	if (list_empty(&qh->qtd_list)) {
+		dev_dbg(hsotg->dev, "## QTD list empty ##\n");
+		goto no_qtd;
+	}
+
+	qtd = list_first_entry(&qh->qtd_list, struct dwc2_qtd, qtd_list_entry);
+
+	if (qtd->complete_split)
+		continue_split = 1;
+	else if (qtd->isoc_split_pos == DWC2_HCSPLT_XACTPOS_MID ||
+		 qtd->isoc_split_pos == DWC2_HCSPLT_XACTPOS_END)
+		continue_split = 1;
+
+	if (free_qtd) {
+		dwc2_hcd_qtd_unlink_and_free(hsotg, qtd, qh);
+		continue_split = 0;
+	}
+
+no_qtd:
+	if (qh->channel)
+		qh->channel->align_buf = 0;
+	qh->channel = NULL;
+	dwc2_hcd_qh_deactivate(hsotg, qh, continue_split);
+}
+
+/**
+ * dwc2_release_channel() - Releases a host channel for use by other transfers
+ *
+ * @hsotg:       The HCD state structure
+ * @chan:        The host channel to release
+ * @qtd:         The QTD associated with the host channel. This QTD may be
+ *               freed if the transfer is complete or an error has occurred.
+ * @halt_status: Reason the channel is being released. This status
+ *               determines the actions taken by this function.
+ *
+ * Also attempts to select and queue more transactions since at least one host
+ * channel is available.
+ */
+static void dwc2_release_channel(struct dwc2_hsotg *hsotg,
+				 struct dwc2_host_chan *chan,
+				 struct dwc2_qtd *qtd,
+				 enum dwc2_halt_status halt_status)
+{
+	enum dwc2_transaction_type tr_type;
+	u32 haintmsk;
+	int free_qtd = 0;
+
+	dev_vdbg(hsotg->dev, "  %s: channel %d, halt_status %d\n",
+		 __func__, chan->hc_num, halt_status);
+
+	switch (halt_status) {
+	case DWC2_HC_XFER_URB_COMPLETE:
+		free_qtd = 1;
+		break;
+	case DWC2_HC_XFER_AHB_ERR:
+	case DWC2_HC_XFER_STALL:
+	case DWC2_HC_XFER_BABBLE_ERR:
+		free_qtd = 1;
+		break;
+	case DWC2_HC_XFER_XACT_ERR:
+		if (qtd && qtd->error_count >= 3) {
+			dev_vdbg(hsotg->dev,
+				 "  Complete URB with transaction error\n");
+			free_qtd = 1;
+			if (qtd->urb) {
+				qtd->urb->status = -EPROTO;
+				dwc2_host_complete(hsotg, qtd->urb->priv,
+						   qtd->urb, -EPROTO);
+			}
+		}
+		break;
+	case DWC2_HC_XFER_URB_DEQUEUE:
+		/*
+		 * The QTD has already been removed and the QH has been
+		 * deactivated. Don't want to do anything except release the
+		 * host channel and try to queue more transfers.
+		 */
+		goto cleanup;
+	case DWC2_HC_XFER_PERIODIC_INCOMPLETE:
+		dev_vdbg(hsotg->dev, "  Complete URB with I/O error\n");
+		free_qtd = 1;
+		if (qtd && qtd->urb) {
+			qtd->urb->status = -EIO;
+			dwc2_host_complete(hsotg, qtd->urb->priv, qtd->urb,
+					   -EIO);
+		}
+		break;
+	case DWC2_HC_XFER_NO_HALT_STATUS:
+	default:
+		break;
+	}
+
+	dwc2_deactivate_qh(hsotg, chan->qh, free_qtd);
+
+cleanup:
+	/*
+	 * Release the host channel for use by other transfers. The cleanup
+	 * function clears the channel interrupt enables and conditions, so
+	 * there's no need to clear the Channel Halted interrupt separately.
+	 */
+	if (!list_empty(&chan->hc_list_entry))
+		list_del(&chan->hc_list_entry);
+	dwc2_hc_cleanup(hsotg, chan);
+	list_add_tail(&chan->hc_list_entry, &hsotg->free_hc_list);
+
+	switch (chan->ep_type) {
+	case USB_ENDPOINT_XFER_CONTROL:
+	case USB_ENDPOINT_XFER_BULK:
+		hsotg->non_periodic_channels--;
+		break;
+	default:
+		/*
+		 * Don't release reservations for periodic channels here.
+		 * That's done when a periodic transfer is descheduled (i.e.
+		 * when the QH is removed from the periodic schedule).
+		 */
+		break;
+	}
+
+	haintmsk = readl(hsotg->regs + HAINTMSK);
+	haintmsk &= ~(1 << chan->hc_num);
+	writel(haintmsk, hsotg->regs + HAINTMSK);
+
+	/* Try to queue more transfers now that there's a free channel */
+	tr_type = dwc2_hcd_select_transactions(hsotg);
+	if (tr_type != DWC2_TRANSACTION_NONE)
+		dwc2_hcd_queue_transactions(hsotg, tr_type);
+}
+
+/*
+ * Halts a host channel. If the channel cannot be halted immediately because
+ * the request queue is full, this function ensures that the FIFO empty
+ * interrupt for the appropriate queue is enabled so that the halt request can
+ * be queued when there is space in the request queue.
+ *
+ * This function may also be called in DMA mode. In that case, the channel is
+ * simply released since the core always halts the channel automatically in
+ * DMA mode.
+ */
+static void dwc2_halt_channel(struct dwc2_hsotg *hsotg,
+			      struct dwc2_host_chan *chan, struct dwc2_qtd *qtd,
+			      enum dwc2_halt_status halt_status)
+{
+	dev_vdbg(hsotg->dev, "%s()\n", __func__);
+
+	if (hsotg->core_params->dma_enable > 0) {
+		dev_vdbg(hsotg->dev, "DMA enabled\n");
+		dwc2_release_channel(hsotg, chan, qtd, halt_status);
+		return;
+	}
+
+	/* Slave mode processing */
+	dwc2_hc_halt(hsotg, chan, halt_status);
+
+	if (chan->halt_on_queue) {
+		u32 gintmsk;
+
+		dev_vdbg(hsotg->dev, "Halt on queue\n");
+		if (chan->ep_type == USB_ENDPOINT_XFER_CONTROL ||
+		    chan->ep_type == USB_ENDPOINT_XFER_BULK) {
+			dev_vdbg(hsotg->dev, "control/bulk\n");
+			/*
+			 * Make sure the Non-periodic Tx FIFO empty interrupt
+			 * is enabled so that the non-periodic schedule will
+			 * be processed
+			 */
+			gintmsk = readl(hsotg->regs + GINTMSK);
+			gintmsk |= GINTSTS_NPTXFEMP;
+			writel(gintmsk, hsotg->regs + GINTMSK);
+		} else {
+			dev_vdbg(hsotg->dev, "isoc/intr\n");
+			/*
+			 * Move the QH from the periodic queued schedule to
+			 * the periodic assigned schedule. This allows the
+			 * halt to be queued when the periodic schedule is
+			 * processed.
+			 */
+			list_move(&chan->qh->qh_list_entry,
+				  &hsotg->periodic_sched_assigned);
+
+			/*
+			 * Make sure the Periodic Tx FIFO Empty interrupt is
+			 * enabled so that the periodic schedule will be
+			 * processed
+			 */
+			gintmsk = readl(hsotg->regs + GINTMSK);
+			gintmsk |= GINTSTS_PTXFEMP;
+			writel(gintmsk, hsotg->regs + GINTMSK);
+		}
+	}
+}
+
+/*
+ * Performs common cleanup for non-periodic transfers after a Transfer
+ * Complete interrupt. This function should be called after any endpoint type
+ * specific handling is finished to release the host channel.
+ */
+static void dwc2_complete_non_periodic_xfer(struct dwc2_hsotg *hsotg,
+					    struct dwc2_host_chan *chan,
+					    int chnum, struct dwc2_qtd *qtd,
+					    enum dwc2_halt_status halt_status)
+{
+	dev_vdbg(hsotg->dev, "%s()\n", __func__);
+
+	qtd->error_count = 0;
+
+	if (chan->hcint & HCINTMSK_NYET) {
+		/*
+		 * Got a NYET on the last transaction of the transfer. This
+		 * means that the endpoint should be in the PING state at the
+		 * beginning of the next transfer.
+		 */
+		dev_vdbg(hsotg->dev, "got NYET\n");
+		chan->qh->ping_state = 1;
+	}
+
+	/*
+	 * Always halt and release the host channel to make it available for
+	 * more transfers. There may still be more phases for a control
+	 * transfer or more data packets for a bulk transfer at this point,
+	 * but the host channel is still halted. A channel will be reassigned
+	 * to the transfer when the non-periodic schedule is processed after
+	 * the channel is released. This allows transactions to be queued
+	 * properly via dwc2_hcd_queue_transactions, which also enables the
+	 * Tx FIFO Empty interrupt if necessary.
+	 */
+	if (chan->ep_is_in) {
+		/*
+		 * IN transfers in Slave mode require an explicit disable to
+		 * halt the channel. (In DMA mode, this call simply releases
+		 * the channel.)
+		 */
+		dwc2_halt_channel(hsotg, chan, qtd, halt_status);
+	} else {
+		/*
+		 * The channel is automatically disabled by the core for OUT
+		 * transfers in Slave mode
+		 */
+		dwc2_release_channel(hsotg, chan, qtd, halt_status);
+	}
+}
+
+/*
+ * Performs common cleanup for periodic transfers after a Transfer Complete
+ * interrupt. This function should be called after any endpoint type specific
+ * handling is finished to release the host channel.
+ */
+static void dwc2_complete_periodic_xfer(struct dwc2_hsotg *hsotg,
+					struct dwc2_host_chan *chan, int chnum,
+					struct dwc2_qtd *qtd,
+					enum dwc2_halt_status halt_status)
+{
+	u32 hctsiz = readl(hsotg->regs + HCTSIZ(chnum));
+
+	qtd->error_count = 0;
+
+	if (!chan->ep_is_in || (hctsiz & TSIZ_PKTCNT_MASK) == 0)
+		/* Core halts channel in these cases */
+		dwc2_release_channel(hsotg, chan, qtd, halt_status);
+	else
+		/* Flush any outstanding requests from the Tx queue */
+		dwc2_halt_channel(hsotg, chan, qtd, halt_status);
+}
+
+static int dwc2_xfercomp_isoc_split_in(struct dwc2_hsotg *hsotg,
+				       struct dwc2_host_chan *chan, int chnum,
+				       struct dwc2_qtd *qtd)
+{
+	struct dwc2_hcd_iso_packet_desc *frame_desc;
+	u32 len;
+
+	if (!qtd->urb)
+		return 0;
+
+	frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index];
+	len = dwc2_get_actual_xfer_length(hsotg, chan, chnum, qtd,
+					  DWC2_HC_XFER_COMPLETE, NULL);
+	if (!len) {
+		qtd->complete_split = 0;
+		qtd->isoc_split_offset = 0;
+		return 0;
+	}
+
+	frame_desc->actual_length += len;
+
+	if (chan->align_buf && len) {
+		dev_dbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__);
+		dma_sync_single_for_cpu(hsotg->dev, qtd->urb->dma,
+					qtd->urb->length, DMA_FROM_DEVICE);
+		memcpy(qtd->urb->buf + frame_desc->offset +
+		       qtd->isoc_split_offset, chan->qh->dw_align_buf, len);
+		dma_sync_single_for_device(hsotg->dev, qtd->urb->dma,
+					   qtd->urb->length, DMA_FROM_DEVICE);
+	}
+
+	qtd->isoc_split_offset += len;
+
+	if (frame_desc->actual_length >= frame_desc->length) {
+		frame_desc->status = 0;
+		qtd->isoc_frame_index++;
+		qtd->complete_split = 0;
+		qtd->isoc_split_offset = 0;
+	}
+
+	if (qtd->isoc_frame_index == qtd->urb->packet_count) {
+		dwc2_host_complete(hsotg, qtd->urb->priv, qtd->urb, 0);
+		dwc2_release_channel(hsotg, chan, qtd,
+				     DWC2_HC_XFER_URB_COMPLETE);
+	} else {
+		dwc2_release_channel(hsotg, chan, qtd,
+				     DWC2_HC_XFER_NO_HALT_STATUS);
+	}
+
+	return 1;	/* Indicates that channel released */
+}
+
+/*
+ * Handles a host channel Transfer Complete interrupt. This handler may be
+ * called in either DMA mode or Slave mode.
+ */
+static void dwc2_hc_xfercomp_intr(struct dwc2_hsotg *hsotg,
+				  struct dwc2_host_chan *chan, int chnum,
+				  struct dwc2_qtd *qtd)
+{
+	struct dwc2_hcd_urb *urb = qtd->urb;
+	int pipe_type = dwc2_hcd_get_pipe_type(&urb->pipe_info);
+	enum dwc2_halt_status halt_status = DWC2_HC_XFER_COMPLETE;
+	int urb_xfer_done;
+
+	dev_vdbg(hsotg->dev,
+		 "--Host Channel %d Interrupt: Transfer Complete--\n", chnum);
+
+	if (hsotg->core_params->dma_desc_enable > 0) {
+		dwc2_hcd_complete_xfer_ddma(hsotg, chan, chnum, halt_status);
+		if (pipe_type == USB_ENDPOINT_XFER_ISOC)
+			/* Do not disable the interrupt, just clear it */
+			return;
+		goto handle_xfercomp_done;
+	}
+
+	/* Handle xfer complete on CSPLIT */
+	if (chan->qh->do_split) {
+		if (chan->ep_type == USB_ENDPOINT_XFER_ISOC && chan->ep_is_in &&
+		    hsotg->core_params->dma_enable > 0) {
+			if (qtd->complete_split &&
+			    dwc2_xfercomp_isoc_split_in(hsotg, chan, chnum,
+							qtd))
+				goto handle_xfercomp_done;
+		} else {
+			qtd->complete_split = 0;
+		}
+	}
+
+	if (!urb)
+		goto handle_xfercomp_done;
+
+	/* Update the QTD and URB states */
+	switch (pipe_type) {
+	case USB_ENDPOINT_XFER_CONTROL:
+		switch (qtd->control_phase) {
+		case DWC2_CONTROL_SETUP:
+			if (urb->length > 0)
+				qtd->control_phase = DWC2_CONTROL_DATA;
+			else
+				qtd->control_phase = DWC2_CONTROL_STATUS;
+			dev_vdbg(hsotg->dev,
+				 "  Control setup transaction done\n");
+			halt_status = DWC2_HC_XFER_COMPLETE;
+			break;
+		case DWC2_CONTROL_DATA:
+			urb_xfer_done = dwc2_update_urb_state(hsotg, chan,
+							      chnum, urb, qtd);
+			if (urb_xfer_done) {
+				qtd->control_phase = DWC2_CONTROL_STATUS;
+				dev_vdbg(hsotg->dev,
+					 "  Control data transfer done\n");
+			} else {
+				dwc2_hcd_save_data_toggle(hsotg, chan, chnum,
+							  qtd);
+			}
+			halt_status = DWC2_HC_XFER_COMPLETE;
+			break;
+		case DWC2_CONTROL_STATUS:
+			dev_vdbg(hsotg->dev, "  Control transfer complete\n");
+			if (urb->status == -EINPROGRESS)
+				urb->status = 0;
+			dwc2_host_complete(hsotg, urb->priv, urb, urb->status);
+			halt_status = DWC2_HC_XFER_URB_COMPLETE;
+			break;
+		}
+
+		dwc2_complete_non_periodic_xfer(hsotg, chan, chnum, qtd,
+						halt_status);
+		break;
+	case USB_ENDPOINT_XFER_BULK:
+		dev_vdbg(hsotg->dev, "  Bulk transfer complete\n");
+		urb_xfer_done = dwc2_update_urb_state(hsotg, chan, chnum, urb,
+						      qtd);
+		if (urb_xfer_done) {
+			dwc2_host_complete(hsotg, urb->priv, urb, urb->status);
+			halt_status = DWC2_HC_XFER_URB_COMPLETE;
+		} else {
+			halt_status = DWC2_HC_XFER_COMPLETE;
+		}
+
+		dwc2_hcd_save_data_toggle(hsotg, chan, chnum, qtd);
+		dwc2_complete_non_periodic_xfer(hsotg, chan, chnum, qtd,
+						halt_status);
+		break;
+	case USB_ENDPOINT_XFER_INT:
+		dev_vdbg(hsotg->dev, "  Interrupt transfer complete\n");
+		urb_xfer_done = dwc2_update_urb_state(hsotg, chan, chnum, urb,
+						      qtd);
+
+		/*
+		 * Interrupt URB is done on the first transfer complete
+		 * interrupt
+		 */
+		if (urb_xfer_done) {
+				dwc2_host_complete(hsotg, urb->priv, urb,
+						   urb->status);
+				halt_status = DWC2_HC_XFER_URB_COMPLETE;
+		} else {
+				halt_status = DWC2_HC_XFER_COMPLETE;
+		}
+
+		dwc2_hcd_save_data_toggle(hsotg, chan, chnum, qtd);
+		dwc2_complete_periodic_xfer(hsotg, chan, chnum, qtd,
+					    halt_status);
+		break;
+	case USB_ENDPOINT_XFER_ISOC:
+		dev_vdbg(hsotg->dev, "  Isochronous transfer complete\n");
+		if (qtd->isoc_split_pos == DWC2_HCSPLT_XACTPOS_ALL)
+			halt_status = dwc2_update_isoc_urb_state(hsotg, chan,
+					chnum, qtd, DWC2_HC_XFER_COMPLETE);
+		dwc2_complete_periodic_xfer(hsotg, chan, chnum, qtd,
+					    halt_status);
+		break;
+	}
+
+handle_xfercomp_done:
+	disable_hc_int(hsotg, chnum, HCINTMSK_XFERCOMPL);
+}
+
+/*
+ * Handles a host channel STALL interrupt. This handler may be called in
+ * either DMA mode or Slave mode.
+ */
+static void dwc2_hc_stall_intr(struct dwc2_hsotg *hsotg,
+			       struct dwc2_host_chan *chan, int chnum,
+			       struct dwc2_qtd *qtd)
+{
+	struct dwc2_hcd_urb *urb = qtd->urb;
+	int pipe_type = dwc2_hcd_get_pipe_type(&urb->pipe_info);
+
+	dev_dbg(hsotg->dev, "--Host Channel %d Interrupt: STALL Received--\n",
+		chnum);
+
+	if (hsotg->core_params->dma_desc_enable > 0) {
+		dwc2_hcd_complete_xfer_ddma(hsotg, chan, chnum,
+					    DWC2_HC_XFER_STALL);
+		goto handle_stall_done;
+	}
+
+	if (!urb)
+		goto handle_stall_halt;
+
+	if (pipe_type == USB_ENDPOINT_XFER_CONTROL)
+		dwc2_host_complete(hsotg, urb->priv, urb, -EPIPE);
+
+	if (pipe_type == USB_ENDPOINT_XFER_BULK ||
+	    pipe_type == USB_ENDPOINT_XFER_INT) {
+		dwc2_host_complete(hsotg, urb->priv, urb, -EPIPE);
+		/*
+		 * USB protocol requires resetting the data toggle for bulk
+		 * and interrupt endpoints when a CLEAR_FEATURE(ENDPOINT_HALT)
+		 * setup command is issued to the endpoint. Anticipate the
+		 * CLEAR_FEATURE command since a STALL has occurred and reset
+		 * the data toggle now.
+		 */
+		chan->qh->data_toggle = 0;
+	}
+
+handle_stall_halt:
+	dwc2_halt_channel(hsotg, chan, qtd, DWC2_HC_XFER_STALL);
+
+handle_stall_done:
+	disable_hc_int(hsotg, chnum, HCINTMSK_STALL);
+}
+
+/*
+ * Updates the state of the URB when a transfer has been stopped due to an
+ * abnormal condition before the transfer completes. Modifies the
+ * actual_length field of the URB to reflect the number of bytes that have
+ * actually been transferred via the host channel.
+ */
+static void dwc2_update_urb_state_abn(struct dwc2_hsotg *hsotg,
+				      struct dwc2_host_chan *chan, int chnum,
+				      struct dwc2_hcd_urb *urb,
+				      struct dwc2_qtd *qtd,
+				      enum dwc2_halt_status halt_status)
+{
+	u32 xfer_length = dwc2_get_actual_xfer_length(hsotg, chan, chnum,
+						      qtd, halt_status, NULL);
+	u32 hctsiz;
+
+	if (urb->actual_length + xfer_length > urb->length) {
+		dev_warn(hsotg->dev, "%s(): trimming xfer length\n", __func__);
+		xfer_length = urb->length - urb->actual_length;
+	}
+
+	/* Non DWORD-aligned buffer case handling */
+	if (chan->align_buf && xfer_length && chan->ep_is_in) {
+		dev_dbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__);
+		dma_sync_single_for_cpu(hsotg->dev, urb->dma, urb->length,
+					DMA_FROM_DEVICE);
+		memcpy(urb->buf + urb->actual_length, chan->qh->dw_align_buf,
+		       xfer_length);
+		dma_sync_single_for_device(hsotg->dev, urb->dma, urb->length,
+					   DMA_FROM_DEVICE);
+	}
+
+	urb->actual_length += xfer_length;
+
+	hctsiz = readl(hsotg->regs + HCTSIZ(chnum));
+	dev_vdbg(hsotg->dev, "DWC_otg: %s: %s, channel %d\n",
+		 __func__, (chan->ep_is_in ? "IN" : "OUT"), chnum);
+	dev_vdbg(hsotg->dev, "  chan->start_pkt_count %d\n",
+		 chan->start_pkt_count);
+	dev_vdbg(hsotg->dev, "  hctsiz.pktcnt %d\n",
+		 hctsiz >> TSIZ_PKTCNT_SHIFT &
+		 TSIZ_PKTCNT_MASK >> TSIZ_PKTCNT_SHIFT);
+	dev_vdbg(hsotg->dev, "  chan->max_packet %d\n", chan->max_packet);
+	dev_vdbg(hsotg->dev, "  bytes_transferred %d\n",
+		 xfer_length);
+	dev_vdbg(hsotg->dev, "  urb->actual_length %d\n",
+		 urb->actual_length);
+	dev_vdbg(hsotg->dev, "  urb->transfer_buffer_length %d\n",
+		 urb->length);
+}
+
+/*
+ * Handles a host channel NAK interrupt. This handler may be called in either
+ * DMA mode or Slave mode.
+ */
+static void dwc2_hc_nak_intr(struct dwc2_hsotg *hsotg,
+			     struct dwc2_host_chan *chan, int chnum,
+			     struct dwc2_qtd *qtd)
+{
+	dev_vdbg(hsotg->dev, "--Host Channel %d Interrupt: NAK Received--\n",
+		 chnum);
+
+	/*
+	 * Handle NAK for IN/OUT SSPLIT/CSPLIT transfers, bulk, control, and
+	 * interrupt. Re-start the SSPLIT transfer.
+	 */
+	if (chan->do_split) {
+		if (chan->complete_split)
+			qtd->error_count = 0;
+		qtd->complete_split = 0;
+		dwc2_halt_channel(hsotg, chan, qtd, DWC2_HC_XFER_NAK);
+		goto handle_nak_done;
+	}
+
+	switch (dwc2_hcd_get_pipe_type(&qtd->urb->pipe_info)) {
+	case USB_ENDPOINT_XFER_CONTROL:
+	case USB_ENDPOINT_XFER_BULK:
+		if (hsotg->core_params->dma_enable > 0 && chan->ep_is_in) {
+			/*
+			 * NAK interrupts are enabled on bulk/control IN
+			 * transfers in DMA mode for the sole purpose of
+			 * resetting the error count after a transaction error
+			 * occurs. The core will continue transferring data.
+			 */
+			qtd->error_count = 0;
+			break;
+		}
+
+		/*
+		 * NAK interrupts normally occur during OUT transfers in DMA
+		 * or Slave mode. For IN transfers, more requests will be
+		 * queued as request queue space is available.
+		 */
+		qtd->error_count = 0;
+
+		if (!chan->qh->ping_state) {
+			dwc2_update_urb_state_abn(hsotg, chan, chnum, qtd->urb,
+						  qtd, DWC2_HC_XFER_NAK);
+			dwc2_hcd_save_data_toggle(hsotg, chan, chnum, qtd);
+
+			if (chan->speed == USB_SPEED_HIGH)
+				chan->qh->ping_state = 1;
+		}
+
+		/*
+		 * Halt the channel so the transfer can be re-started from
+		 * the appropriate point or the PING protocol will
+		 * start/continue
+		 */
+		dwc2_halt_channel(hsotg, chan, qtd, DWC2_HC_XFER_NAK);
+		break;
+	case USB_ENDPOINT_XFER_INT:
+		qtd->error_count = 0;
+		dwc2_halt_channel(hsotg, chan, qtd, DWC2_HC_XFER_NAK);
+		break;
+	case USB_ENDPOINT_XFER_ISOC:
+		/* Should never get called for isochronous transfers */
+		dev_err(hsotg->dev, "NACK interrupt for ISOC transfer\n");
+		break;
+	}
+
+handle_nak_done:
+	disable_hc_int(hsotg, chnum, HCINTMSK_NAK);
+}
+
+/*
+ * Handles a host channel ACK interrupt. This interrupt is enabled when
+ * performing the PING protocol in Slave mode, when errors occur during
+ * either Slave mode or DMA mode, and during Start Split transactions.
+ */
+static void dwc2_hc_ack_intr(struct dwc2_hsotg *hsotg,
+			     struct dwc2_host_chan *chan, int chnum,
+			     struct dwc2_qtd *qtd)
+{
+	struct dwc2_hcd_iso_packet_desc *frame_desc;
+
+	dev_vdbg(hsotg->dev, "--Host Channel %d Interrupt: ACK Received--\n",
+		 chnum);
+
+	if (chan->do_split) {
+		/* Handle ACK on SSPLIT. ACK should not occur in CSPLIT. */
+		if (!chan->ep_is_in &&
+		    chan->data_pid_start != DWC2_HC_PID_SETUP)
+			qtd->ssplit_out_xfer_count = chan->xfer_len;
+
+		if (chan->ep_type != USB_ENDPOINT_XFER_ISOC || chan->ep_is_in) {
+			qtd->complete_split = 1;
+			dwc2_halt_channel(hsotg, chan, qtd, DWC2_HC_XFER_ACK);
+		} else {
+			/* ISOC OUT */
+			switch (chan->xact_pos) {
+			case DWC2_HCSPLT_XACTPOS_ALL:
+				break;
+			case DWC2_HCSPLT_XACTPOS_END:
+				qtd->isoc_split_pos = DWC2_HCSPLT_XACTPOS_ALL;
+				qtd->isoc_split_offset = 0;
+				break;
+			case DWC2_HCSPLT_XACTPOS_BEGIN:
+			case DWC2_HCSPLT_XACTPOS_MID:
+				/*
+				 * For BEGIN or MID, calculate the length for
+				 * the next microframe to determine the correct
+				 * SSPLIT token, either MID or END
+				 */
+				frame_desc = &qtd->urb->iso_descs[
+						qtd->isoc_frame_index];
+				qtd->isoc_split_offset += 188;
+
+				if (frame_desc->length - qtd->isoc_split_offset
+							<= 188)
+					qtd->isoc_split_pos =
+							DWC2_HCSPLT_XACTPOS_END;
+				else
+					qtd->isoc_split_pos =
+							DWC2_HCSPLT_XACTPOS_MID;
+				break;
+			}
+		}
+	} else {
+		qtd->error_count = 0;
+
+		if (chan->qh->ping_state) {
+			chan->qh->ping_state = 0;
+			/*
+			 * Halt the channel so the transfer can be re-started
+			 * from the appropriate point. This only happens in
+			 * Slave mode. In DMA mode, the ping_state is cleared
+			 * when the transfer is started because the core
+			 * automatically executes the PING, then the transfer.
+			 */
+			dwc2_halt_channel(hsotg, chan, qtd, DWC2_HC_XFER_ACK);
+		}
+	}
+
+	/*
+	 * If the ACK occurred when _not_ in the PING state, let the channel
+	 * continue transferring data after clearing the error count
+	 */
+	disable_hc_int(hsotg, chnum, HCINTMSK_ACK);
+}
+
+/*
+ * Handles a host channel NYET interrupt. This interrupt should only occur on
+ * Bulk and Control OUT endpoints and for complete split transactions. If a
+ * NYET occurs at the same time as a Transfer Complete interrupt, it is
+ * handled in the xfercomp interrupt handler, not here. This handler may be
+ * called in either DMA mode or Slave mode.
+ */
+static void dwc2_hc_nyet_intr(struct dwc2_hsotg *hsotg,
+			      struct dwc2_host_chan *chan, int chnum,
+			      struct dwc2_qtd *qtd)
+{
+	dev_vdbg(hsotg->dev, "--Host Channel %d Interrupt: NYET Received--\n",
+		 chnum);
+
+	/*
+	 * NYET on CSPLIT
+	 * re-do the CSPLIT immediately on non-periodic
+	 */
+	if (chan->do_split && chan->complete_split) {
+		if (chan->ep_is_in && chan->ep_type == USB_ENDPOINT_XFER_ISOC &&
+		    hsotg->core_params->dma_enable > 0) {
+			qtd->complete_split = 0;
+			qtd->isoc_split_offset = 0;
+			if (++qtd->isoc_frame_index == qtd->urb->packet_count) {
+				if (qtd->urb)
+					dwc2_host_complete(hsotg,
+							   qtd->urb->priv,
+							   qtd->urb, 0);
+				dwc2_release_channel(hsotg, chan, qtd,
+						DWC2_HC_XFER_URB_COMPLETE);
+			} else {
+				dwc2_release_channel(hsotg, chan, qtd,
+						DWC2_HC_XFER_NO_HALT_STATUS);
+			}
+			goto handle_nyet_done;
+		}
+
+		if (chan->ep_type == USB_ENDPOINT_XFER_INT ||
+		    chan->ep_type == USB_ENDPOINT_XFER_ISOC) {
+			int frnum = dwc2_hcd_get_frame_number(hsotg);
+
+			if (dwc2_full_frame_num(frnum) !=
+			    dwc2_full_frame_num(chan->qh->sched_frame)) {
+				/*
+				 * No longer in the same full speed frame.
+				 * Treat this as a transaction error.
+				 */
+#if 0
+				/*
+				 * Todo: Fix system performance so this can
+				 * be treated as an error. Right now complete
+				 * splits cannot be scheduled precisely enough
+				 * due to other system activity, so this error
+				 * occurs regularly in Slave mode.
+				 */
+				qtd->error_count++;
+#endif
+				qtd->complete_split = 0;
+				dwc2_halt_channel(hsotg, chan, qtd,
+						  DWC2_HC_XFER_XACT_ERR);
+				/* Todo: add support for isoc release */
+				goto handle_nyet_done;
+			}
+		}
+
+		dwc2_halt_channel(hsotg, chan, qtd, DWC2_HC_XFER_NYET);
+		goto handle_nyet_done;
+	}
+
+	chan->qh->ping_state = 1;
+	qtd->error_count = 0;
+
+	dwc2_update_urb_state_abn(hsotg, chan, chnum, qtd->urb, qtd,
+				  DWC2_HC_XFER_NYET);
+	dwc2_hcd_save_data_toggle(hsotg, chan, chnum, qtd);
+
+	/*
+	 * Halt the channel and re-start the transfer so the PING protocol
+	 * will start
+	 */
+	dwc2_halt_channel(hsotg, chan, qtd, DWC2_HC_XFER_NYET);
+
+handle_nyet_done:
+	disable_hc_int(hsotg, chnum, HCINTMSK_NYET);
+}
+
+/*
+ * Handles a host channel babble interrupt. This handler may be called in
+ * either DMA mode or Slave mode.
+ */
+static void dwc2_hc_babble_intr(struct dwc2_hsotg *hsotg,
+				struct dwc2_host_chan *chan, int chnum,
+				struct dwc2_qtd *qtd)
+{
+	dev_dbg(hsotg->dev, "--Host Channel %d Interrupt: Babble Error--\n",
+		chnum);
+
+	if (hsotg->core_params->dma_desc_enable > 0) {
+		dwc2_hcd_complete_xfer_ddma(hsotg, chan, chnum,
+					    DWC2_HC_XFER_BABBLE_ERR);
+		goto handle_babble_done;
+	}
+
+	if (chan->ep_type != USB_ENDPOINT_XFER_ISOC) {
+		if (qtd->urb)
+			dwc2_host_complete(hsotg, qtd->urb->priv, qtd->urb,
+					   -EOVERFLOW);
+		dwc2_halt_channel(hsotg, chan, qtd, DWC2_HC_XFER_BABBLE_ERR);
+	} else {
+		enum dwc2_halt_status halt_status;
+
+		halt_status = dwc2_update_isoc_urb_state(hsotg, chan, chnum,
+						qtd, DWC2_HC_XFER_BABBLE_ERR);
+		dwc2_halt_channel(hsotg, chan, qtd, halt_status);
+	}
+
+handle_babble_done:
+	dwc2_hc_handle_tt_clear(hsotg, chan, qtd);
+	disable_hc_int(hsotg, chnum, HCINTMSK_BBLERR);
+}
+
+/*
+ * Handles a host channel AHB error interrupt. This handler is only called in
+ * DMA mode.
+ */
+static void dwc2_hc_ahberr_intr(struct dwc2_hsotg *hsotg,
+				struct dwc2_host_chan *chan, int chnum,
+				struct dwc2_qtd *qtd)
+{
+	struct dwc2_hcd_urb *urb = qtd->urb;
+	char *pipetype, *speed;
+	u32 hcchar;
+	u32 hcsplt;
+	u32 hctsiz;
+	u32 hc_dma;
+
+	dev_dbg(hsotg->dev, "--Host Channel %d Interrupt: AHB Error--\n",
+		chnum);
+
+	if (!urb)
+		goto handle_ahberr_halt;
+
+	hcchar = readl(hsotg->regs + HCCHAR(chnum));
+	hcsplt = readl(hsotg->regs + HCSPLT(chnum));
+	hctsiz = readl(hsotg->regs + HCTSIZ(chnum));
+	hc_dma = readl(hsotg->regs + HCDMA(chnum));
+
+	dev_err(hsotg->dev, "AHB ERROR, Channel %d\n", chnum);
+	dev_err(hsotg->dev, "  hcchar 0x%08x, hcsplt 0x%08x\n", hcchar, hcsplt);
+	dev_err(hsotg->dev, "  hctsiz 0x%08x, hc_dma 0x%08x\n", hctsiz, hc_dma);
+	dev_err(hsotg->dev, "  Device address: %d\n",
+		dwc2_hcd_get_dev_addr(&urb->pipe_info));
+	dev_err(hsotg->dev, "  Endpoint: %d, %s\n",
+		dwc2_hcd_get_ep_num(&urb->pipe_info),
+		dwc2_hcd_is_pipe_in(&urb->pipe_info) ? "IN" : "OUT");
+
+	switch (dwc2_hcd_get_pipe_type(&urb->pipe_info)) {
+	case USB_ENDPOINT_XFER_CONTROL:
+		pipetype = "CONTROL";
+		break;
+	case USB_ENDPOINT_XFER_BULK:
+		pipetype = "BULK";
+		break;
+	case USB_ENDPOINT_XFER_INT:
+		pipetype = "INTERRUPT";
+		break;
+	case USB_ENDPOINT_XFER_ISOC:
+		pipetype = "ISOCHRONOUS";
+		break;
+	default:
+		pipetype = "UNKNOWN";
+		break;
+	}
+
+	dev_err(hsotg->dev, "  Endpoint type: %s\n", pipetype);
+
+	switch (chan->speed) {
+	case USB_SPEED_HIGH:
+		speed = "HIGH";
+		break;
+	case USB_SPEED_FULL:
+		speed = "FULL";
+		break;
+	case USB_SPEED_LOW:
+		speed = "LOW";
+		break;
+	default:
+		speed = "UNKNOWN";
+		break;
+	}
+
+	dev_err(hsotg->dev, "  Speed: %s\n", speed);
+
+	dev_err(hsotg->dev, "  Max packet size: %d\n",
+		dwc2_hcd_get_mps(&urb->pipe_info));
+	dev_err(hsotg->dev, "  Data buffer length: %d\n", urb->length);
+	dev_err(hsotg->dev, "  Transfer buffer: %p, Transfer DMA: %08lx\n",
+		urb->buf, (unsigned long)urb->dma);
+	dev_err(hsotg->dev, "  Setup buffer: %p, Setup DMA: %08lx\n",
+		urb->setup_packet, (unsigned long)urb->setup_dma);
+	dev_err(hsotg->dev, "  Interval: %d\n", urb->interval);
+
+	/* Core halts the channel for Descriptor DMA mode */
+	if (hsotg->core_params->dma_desc_enable > 0) {
+		dwc2_hcd_complete_xfer_ddma(hsotg, chan, chnum,
+					    DWC2_HC_XFER_AHB_ERR);
+		goto handle_ahberr_done;
+	}
+
+	dwc2_host_complete(hsotg, urb->priv, urb, -EIO);
+
+handle_ahberr_halt:
+	/*
+	 * Force a channel halt. Don't call dwc2_halt_channel because that won't
+	 * write to the HCCHARn register in DMA mode to force the halt.
+	 */
+	dwc2_hc_halt(hsotg, chan, DWC2_HC_XFER_AHB_ERR);
+
+handle_ahberr_done:
+	dwc2_hc_handle_tt_clear(hsotg, chan, qtd);
+	disable_hc_int(hsotg, chnum, HCINTMSK_AHBERR);
+}
+
+/*
+ * Handles a host channel transaction error interrupt. This handler may be
+ * called in either DMA mode or Slave mode.
+ */
+static void dwc2_hc_xacterr_intr(struct dwc2_hsotg *hsotg,
+				 struct dwc2_host_chan *chan, int chnum,
+				 struct dwc2_qtd *qtd)
+{
+	dev_dbg(hsotg->dev,
+		"--Host Channel %d Interrupt: Transaction Error--\n", chnum);
+
+	if (hsotg->core_params->dma_desc_enable > 0) {
+		dwc2_hcd_complete_xfer_ddma(hsotg, chan, chnum,
+					    DWC2_HC_XFER_XACT_ERR);
+		goto handle_xacterr_done;
+	}
+
+	switch (dwc2_hcd_get_pipe_type(&qtd->urb->pipe_info)) {
+	case USB_ENDPOINT_XFER_CONTROL:
+	case USB_ENDPOINT_XFER_BULK:
+		qtd->error_count++;
+		if (!chan->qh->ping_state) {
+
+			dwc2_update_urb_state_abn(hsotg, chan, chnum, qtd->urb,
+						  qtd, DWC2_HC_XFER_XACT_ERR);
+			dwc2_hcd_save_data_toggle(hsotg, chan, chnum, qtd);
+			if (!chan->ep_is_in && chan->speed == USB_SPEED_HIGH)
+				chan->qh->ping_state = 1;
+		}
+
+		/*
+		 * Halt the channel so the transfer can be re-started from
+		 * the appropriate point or the PING protocol will start
+		 */
+		dwc2_halt_channel(hsotg, chan, qtd, DWC2_HC_XFER_XACT_ERR);
+		break;
+	case USB_ENDPOINT_XFER_INT:
+		qtd->error_count++;
+		if (chan->do_split && chan->complete_split)
+			qtd->complete_split = 0;
+		dwc2_halt_channel(hsotg, chan, qtd, DWC2_HC_XFER_XACT_ERR);
+		break;
+	case USB_ENDPOINT_XFER_ISOC:
+		{
+			enum dwc2_halt_status halt_status;
+
+			halt_status = dwc2_update_isoc_urb_state(hsotg, chan,
+					chnum, qtd, DWC2_HC_XFER_XACT_ERR);
+			dwc2_halt_channel(hsotg, chan, qtd, halt_status);
+		}
+		break;
+	}
+
+handle_xacterr_done:
+	dwc2_hc_handle_tt_clear(hsotg, chan, qtd);
+	disable_hc_int(hsotg, chnum, HCINTMSK_XACTERR);
+}
+
+/*
+ * Handles a host channel frame overrun interrupt. This handler may be called
+ * in either DMA mode or Slave mode.
+ */
+static void dwc2_hc_frmovrun_intr(struct dwc2_hsotg *hsotg,
+				  struct dwc2_host_chan *chan, int chnum,
+				  struct dwc2_qtd *qtd)
+{
+	enum dwc2_halt_status halt_status;
+
+	dev_dbg(hsotg->dev, "--Host Channel %d Interrupt: Frame Overrun--\n",
+		chnum);
+
+	switch (dwc2_hcd_get_pipe_type(&qtd->urb->pipe_info)) {
+	case USB_ENDPOINT_XFER_CONTROL:
+	case USB_ENDPOINT_XFER_BULK:
+		break;
+	case USB_ENDPOINT_XFER_INT:
+		dwc2_halt_channel(hsotg, chan, qtd, DWC2_HC_XFER_FRAME_OVERRUN);
+		break;
+	case USB_ENDPOINT_XFER_ISOC:
+		halt_status = dwc2_update_isoc_urb_state(hsotg, chan, chnum,
+					qtd, DWC2_HC_XFER_FRAME_OVERRUN);
+		dwc2_halt_channel(hsotg, chan, qtd, halt_status);
+		break;
+	}
+
+	dwc2_hc_handle_tt_clear(hsotg, chan, qtd);
+	disable_hc_int(hsotg, chnum, HCINTMSK_FRMOVRUN);
+}
+
+/*
+ * Handles a host channel data toggle error interrupt. This handler may be
+ * called in either DMA mode or Slave mode.
+ */
+static void dwc2_hc_datatglerr_intr(struct dwc2_hsotg *hsotg,
+				    struct dwc2_host_chan *chan, int chnum,
+				    struct dwc2_qtd *qtd)
+{
+	dev_dbg(hsotg->dev,
+		"--Host Channel %d Interrupt: Data Toggle Error--\n", chnum);
+
+	if (chan->ep_is_in)
+		qtd->error_count = 0;
+	else
+		dev_err(hsotg->dev,
+			"Data Toggle Error on OUT transfer, channel %d\n",
+			chnum);
+
+	dwc2_hc_handle_tt_clear(hsotg, chan, qtd);
+	disable_hc_int(hsotg, chnum, HCINTMSK_DATATGLERR);
+}
+
+/*
+ * For debug only. It checks that a valid halt status is set and that
+ * HCCHARn.chdis is clear. If there's a problem, corrective action is
+ * taken and a warning is issued.
+ *
+ * Return: true if halt status is ok, false otherwise
+ */
+static bool dwc2_halt_status_ok(struct dwc2_hsotg *hsotg,
+				struct dwc2_host_chan *chan, int chnum,
+				struct dwc2_qtd *qtd)
+{
+#ifdef DEBUG
+	u32 hcchar;
+	u32 hctsiz;
+	u32 hcintmsk;
+	u32 hcsplt;
+
+	if (chan->halt_status == DWC2_HC_XFER_NO_HALT_STATUS) {
+		/*
+		 * This code is here only as a check. This condition should
+		 * never happen. Ignore the halt if it does occur.
+		 */
+		hcchar = readl(hsotg->regs + HCCHAR(chnum));
+		hctsiz = readl(hsotg->regs + HCTSIZ(chnum));
+		hcintmsk = readl(hsotg->regs + HCINTMSK(chnum));
+		hcsplt = readl(hsotg->regs + HCSPLT(chnum));
+		dev_dbg(hsotg->dev,
+			"%s: chan->halt_status DWC2_HC_XFER_NO_HALT_STATUS,\n",
+			 __func__);
+		dev_dbg(hsotg->dev,
+			"channel %d, hcchar 0x%08x, hctsiz 0x%08x,\n",
+			chnum, hcchar, hctsiz);
+		dev_dbg(hsotg->dev,
+			"hcint 0x%08x, hcintmsk 0x%08x, hcsplt 0x%08x,\n",
+			chan->hcint, hcintmsk, hcsplt);
+		if (qtd)
+			dev_dbg(hsotg->dev, "qtd->complete_split %d\n",
+				qtd->complete_split);
+		dev_warn(hsotg->dev,
+			 "%s: no halt status, channel %d, ignoring interrupt\n",
+			 __func__, chnum);
+		return false;
+	}
+
+	/*
+	 * This code is here only as a check. hcchar.chdis should never be set
+	 * when the halt interrupt occurs. Halt the channel again if it does
+	 * occur.
+	 */
+	hcchar = readl(hsotg->regs + HCCHAR(chnum));
+	if (hcchar & HCCHAR_CHDIS) {
+		dev_warn(hsotg->dev,
+			 "%s: hcchar.chdis set unexpectedly, hcchar 0x%08x, trying to halt again\n",
+			 __func__, hcchar);
+		chan->halt_pending = 0;
+		dwc2_halt_channel(hsotg, chan, qtd, chan->halt_status);
+		return false;
+	}
+#endif
+
+	return true;
+}
+
+/*
+ * Handles a host Channel Halted interrupt in DMA mode. This handler
+ * determines the reason the channel halted and proceeds accordingly.
+ */
+static void dwc2_hc_chhltd_intr_dma(struct dwc2_hsotg *hsotg,
+				    struct dwc2_host_chan *chan, int chnum,
+				    struct dwc2_qtd *qtd)
+{
+	u32 hcintmsk;
+	int out_nak_enh = 0;
+
+	dev_vdbg(hsotg->dev,
+		 "--Host Channel %d Interrupt: DMA Channel Halted--\n", chnum);
+
+	/*
+	 * For core with OUT NAK enhancement, the flow for high-speed
+	 * CONTROL/BULK OUT is handled a little differently
+	 */
+	if (hsotg->snpsid >= DWC2_CORE_REV_2_71a) {
+		if (chan->speed == USB_SPEED_HIGH && !chan->ep_is_in &&
+		    (chan->ep_type == USB_ENDPOINT_XFER_CONTROL ||
+		     chan->ep_type == USB_ENDPOINT_XFER_BULK)) {
+			out_nak_enh = 1;
+		}
+	}
+
+	if (chan->halt_status == DWC2_HC_XFER_URB_DEQUEUE ||
+	    (chan->halt_status == DWC2_HC_XFER_AHB_ERR &&
+	     hsotg->core_params->dma_desc_enable <= 0)) {
+		if (hsotg->core_params->dma_desc_enable > 0)
+			dwc2_hcd_complete_xfer_ddma(hsotg, chan, chnum,
+						    chan->halt_status);
+		else
+			/*
+			 * Just release the channel. A dequeue can happen on a
+			 * transfer timeout. In the case of an AHB Error, the
+			 * channel was forced to halt because there's no way to
+			 * gracefully recover.
+			 */
+			dwc2_release_channel(hsotg, chan, qtd,
+					     chan->halt_status);
+		return;
+	}
+
+	hcintmsk = readl(hsotg->regs + HCINTMSK(chnum));
+
+	if (chan->hcint & HCINTMSK_XFERCOMPL) {
+		/*
+		 * Todo: This is here because of a possible hardware bug. Spec
+		 * says that on SPLIT-ISOC OUT transfers in DMA mode that a HALT
+		 * interrupt w/ACK bit set should occur, but I only see the
+		 * XFERCOMP bit, even with it masked out. This is a workaround
+		 * for that behavior. Should fix this when hardware is fixed.
+		 */
+		if (chan->ep_type == USB_ENDPOINT_XFER_ISOC && !chan->ep_is_in)
+			dwc2_hc_ack_intr(hsotg, chan, chnum, qtd);
+		dwc2_hc_xfercomp_intr(hsotg, chan, chnum, qtd);
+	} else if (chan->hcint & HCINTMSK_STALL) {
+		dwc2_hc_stall_intr(hsotg, chan, chnum, qtd);
+	} else if ((chan->hcint & HCINTMSK_XACTERR) &&
+		   hsotg->core_params->dma_desc_enable <= 0) {
+		if (out_nak_enh) {
+			if (chan->hcint &
+			    (HCINTMSK_NYET | HCINTMSK_NAK | HCINTMSK_ACK)) {
+				dev_vdbg(hsotg->dev,
+					 "XactErr with NYET/NAK/ACK\n");
+				qtd->error_count = 0;
+			} else {
+				dev_vdbg(hsotg->dev,
+					 "XactErr without NYET/NAK/ACK\n");
+			}
+		}
+
+		/*
+		 * Must handle xacterr before nak or ack. Could get a xacterr
+		 * at the same time as either of these on a BULK/CONTROL OUT
+		 * that started with a PING. The xacterr takes precedence.
+		 */
+		dwc2_hc_xacterr_intr(hsotg, chan, chnum, qtd);
+	} else if ((chan->hcint & HCINTMSK_XCS_XACT) &&
+		   hsotg->core_params->dma_desc_enable > 0) {
+		dwc2_hc_xacterr_intr(hsotg, chan, chnum, qtd);
+	} else if ((chan->hcint & HCINTMSK_AHBERR) &&
+		   hsotg->core_params->dma_desc_enable > 0) {
+		dwc2_hc_ahberr_intr(hsotg, chan, chnum, qtd);
+	} else if (chan->hcint & HCINTMSK_BBLERR) {
+		dwc2_hc_babble_intr(hsotg, chan, chnum, qtd);
+	} else if (chan->hcint & HCINTMSK_FRMOVRUN) {
+		dwc2_hc_frmovrun_intr(hsotg, chan, chnum, qtd);
+	} else if (!out_nak_enh) {
+		if (chan->hcint & HCINTMSK_NYET) {
+			/*
+			 * Must handle nyet before nak or ack. Could get a nyet
+			 * at the same time as either of those on a BULK/CONTROL
+			 * OUT that started with a PING. The nyet takes
+			 * precedence.
+			 */
+			dwc2_hc_nyet_intr(hsotg, chan, chnum, qtd);
+		} else if ((chan->hcint & HCINTMSK_NAK) &&
+			   !(hcintmsk & HCINTMSK_NAK)) {
+			/*
+			 * If nak is not masked, it's because a non-split IN
+			 * transfer is in an error state. In that case, the nak
+			 * is handled by the nak interrupt handler, not here.
+			 * Handle nak here for BULK/CONTROL OUT transfers, which
+			 * halt on a NAK to allow rewinding the buffer pointer.
+			 */
+			dwc2_hc_nak_intr(hsotg, chan, chnum, qtd);
+		} else if ((chan->hcint & HCINTMSK_ACK) &&
+			   !(hcintmsk & HCINTMSK_ACK)) {
+			/*
+			 * If ack is not masked, it's because a non-split IN
+			 * transfer is in an error state. In that case, the ack
+			 * is handled by the ack interrupt handler, not here.
+			 * Handle ack here for split transfers. Start splits
+			 * halt on ACK.
+			 */
+			dwc2_hc_ack_intr(hsotg, chan, chnum, qtd);
+		} else {
+			if (chan->ep_type == USB_ENDPOINT_XFER_INT ||
+			    chan->ep_type == USB_ENDPOINT_XFER_ISOC) {
+				/*
+				 * A periodic transfer halted with no other
+				 * channel interrupts set. Assume it was halted
+				 * by the core because it could not be completed
+				 * in its scheduled (micro)frame.
+				 */
+				dev_dbg(hsotg->dev,
+					"%s: Halt channel %d (assume incomplete periodic transfer)\n",
+					__func__, chnum);
+				dwc2_halt_channel(hsotg, chan, qtd,
+					DWC2_HC_XFER_PERIODIC_INCOMPLETE);
+			} else {
+				dev_err(hsotg->dev,
+					"%s: Channel %d - ChHltd set, but reason is unknown\n",
+					__func__, chnum);
+				dev_err(hsotg->dev,
+					"hcint 0x%08x, intsts 0x%08x\n",
+					chan->hcint,
+					readl(hsotg->regs + GINTSTS));
+			}
+		}
+	} else {
+		dev_info(hsotg->dev,
+			 "NYET/NAK/ACK/other in non-error case, 0x%08x\n",
+			 chan->hcint);
+	}
+}
+
+/*
+ * Handles a host channel Channel Halted interrupt
+ *
+ * In slave mode, this handler is called only when the driver specifically
+ * requests a halt. This occurs during handling other host channel interrupts
+ * (e.g. nak, xacterr, stall, nyet, etc.).
+ *
+ * In DMA mode, this is the interrupt that occurs when the core has finished
+ * processing a transfer on a channel. Other host channel interrupts (except
+ * ahberr) are disabled in DMA mode.
+ */
+static void dwc2_hc_chhltd_intr(struct dwc2_hsotg *hsotg,
+				struct dwc2_host_chan *chan, int chnum,
+				struct dwc2_qtd *qtd)
+{
+	dev_vdbg(hsotg->dev, "--Host Channel %d Interrupt: Channel Halted--\n",
+		 chnum);
+
+	if (hsotg->core_params->dma_enable > 0) {
+		dwc2_hc_chhltd_intr_dma(hsotg, chan, chnum, qtd);
+	} else {
+		if (!dwc2_halt_status_ok(hsotg, chan, chnum, qtd))
+			return;
+		dwc2_release_channel(hsotg, chan, qtd, chan->halt_status);
+	}
+}
+
+/* Handles interrupt for a specific Host Channel */
+static void dwc2_hc_n_intr(struct dwc2_hsotg *hsotg, int chnum)
+{
+	struct dwc2_qtd *qtd;
+	struct dwc2_host_chan *chan;
+	u32 hcint, hcintmsk;
+
+	dev_vdbg(hsotg->dev, "--Host Channel Interrupt--, Channel %d\n", chnum);
+
+	hcint = readl(hsotg->regs + HCINT(chnum));
+	hcintmsk = readl(hsotg->regs + HCINTMSK(chnum));
+	dev_vdbg(hsotg->dev,
+		 "  hcint 0x%08x, hcintmsk 0x%08x, hcint&hcintmsk 0x%08x\n",
+		 hcint, hcintmsk, hcint & hcintmsk);
+
+	chan = hsotg->hc_ptr_array[chnum];
+	if (!chan) {
+		dev_err(hsotg->dev, "## hc_ptr_array for channel is NULL ##\n");
+		writel(hcint, hsotg->regs + HCINT(chnum));
+		return;
+	}
+
+	writel(hcint, hsotg->regs + HCINT(chnum));
+	chan->hcint = hcint;
+	hcint &= hcintmsk;
+
+	/*
+	 * If the channel was halted due to a dequeue, the qtd list might
+	 * be empty or at least the first entry will not be the active qtd.
+	 * In this case, take a shortcut and just release the channel.
+	 */
+	if (chan->halt_status == DWC2_HC_XFER_URB_DEQUEUE) {
+		/*
+		 * If the channel was halted, this should be the only
+		 * interrupt unmasked
+		 */
+		WARN_ON(hcint != HCINTMSK_CHHLTD);
+		if (hsotg->core_params->dma_desc_enable > 0)
+			dwc2_hcd_complete_xfer_ddma(hsotg, chan, chnum,
+						    chan->halt_status);
+		else
+			dwc2_release_channel(hsotg, chan, NULL,
+					     chan->halt_status);
+		return;
+	}
+
+	if (list_empty(&chan->qh->qtd_list)) {
+		/*
+		 * TODO: Will this ever happen with the
+		 * DWC2_HC_XFER_URB_DEQUEUE handling above?
+		 */
+		dev_dbg(hsotg->dev, "## no QTD queued for channel %d ##\n",
+			chnum);
+		dev_dbg(hsotg->dev,
+			"  hcint 0x%08x, hcintmsk 0x%08x, hcint&hcintmsk 0x%08x\n",
+			chan->hcint, hcintmsk, hcint);
+		chan->halt_status = DWC2_HC_XFER_NO_HALT_STATUS;
+		disable_hc_int(hsotg, chnum, HCINTMSK_CHHLTD);
+		chan->hcint = 0;
+		return;
+	}
+
+	qtd = list_first_entry(&chan->qh->qtd_list, struct dwc2_qtd,
+			       qtd_list_entry);
+
+	if (hsotg->core_params->dma_enable <= 0) {
+		if ((hcint & HCINTMSK_CHHLTD) && hcint != HCINTMSK_CHHLTD)
+			hcint &= ~HCINTMSK_CHHLTD;
+	}
+
+	if (hcint & HCINTMSK_XFERCOMPL) {
+		dwc2_hc_xfercomp_intr(hsotg, chan, chnum, qtd);
+		/*
+		 * If NYET occurred at same time as Xfer Complete, the NYET is
+		 * handled by the Xfer Complete interrupt handler. Don't want
+		 * to call the NYET interrupt handler in this case.
+		 */
+		hcint &= ~HCINTMSK_NYET;
+	}
+	if (hcint & HCINTMSK_CHHLTD)
+		dwc2_hc_chhltd_intr(hsotg, chan, chnum, qtd);
+	if (hcint & HCINTMSK_AHBERR)
+		dwc2_hc_ahberr_intr(hsotg, chan, chnum, qtd);
+	if (hcint & HCINTMSK_STALL)
+		dwc2_hc_stall_intr(hsotg, chan, chnum, qtd);
+	if (hcint & HCINTMSK_NAK)
+		dwc2_hc_nak_intr(hsotg, chan, chnum, qtd);
+	if (hcint & HCINTMSK_ACK)
+		dwc2_hc_ack_intr(hsotg, chan, chnum, qtd);
+	if (hcint & HCINTMSK_NYET)
+		dwc2_hc_nyet_intr(hsotg, chan, chnum, qtd);
+	if (hcint & HCINTMSK_XACTERR)
+		dwc2_hc_xacterr_intr(hsotg, chan, chnum, qtd);
+	if (hcint & HCINTMSK_BBLERR)
+		dwc2_hc_babble_intr(hsotg, chan, chnum, qtd);
+	if (hcint & HCINTMSK_FRMOVRUN)
+		dwc2_hc_frmovrun_intr(hsotg, chan, chnum, qtd);
+	if (hcint & HCINTMSK_DATATGLERR)
+		dwc2_hc_datatglerr_intr(hsotg, chan, chnum, qtd);
+
+	chan->hcint = 0;
+}
+
+/*
+ * This interrupt indicates that one or more host channels has a pending
+ * interrupt. There are multiple conditions that can cause each host channel
+ * interrupt. This function determines which conditions have occurred for each
+ * host channel interrupt and handles them appropriately.
+ */
+static void dwc2_hc_intr(struct dwc2_hsotg *hsotg)
+{
+	u32 haint;
+	int i;
+
+	dev_vdbg(hsotg->dev, "%s()\n", __func__);
+
+	haint = readl(hsotg->regs + HAINT);
+	dev_vdbg(hsotg->dev, "HAINT=%08x\n", haint);
+
+	for (i = 0; i < hsotg->core_params->host_channels; i++) {
+		if (haint & (1 << i))
+			dwc2_hc_n_intr(hsotg, i);
+	}
+}
+
+/* This function handles interrupts for the HCD */
+int dwc2_hcd_intr(struct dwc2_hsotg *hsotg)
+{
+	u32 gintsts;
+	int retval = 0;
+
+	if (dwc2_check_core_status(hsotg) < 0) {
+		dev_warn(hsotg->dev, "Controller is disconnected");
+		return 0;
+	}
+
+	spin_lock(&hsotg->lock);
+
+	/* Check if HOST Mode */
+	if (dwc2_is_host_mode(hsotg)) {
+		gintsts = dwc2_read_core_intr(hsotg);
+		if (!gintsts) {
+			spin_unlock(&hsotg->lock);
+			return 0;
+		}
+
+		retval = 1;
+
+#ifndef DEBUG_SOF
+		/* Don't print debug message in the interrupt handler on SOF */
+		if (gintsts != GINTSTS_SOF)
+#endif
+			dev_vdbg(hsotg->dev,
+				 "DWC OTG HCD Interrupt Detected gintsts&gintmsk=0x%08x\n",
+				 gintsts);
+
+		if (gintsts & GINTSTS_SOF)
+			dwc2_sof_intr(hsotg);
+		if (gintsts & GINTSTS_RXFLVL)
+			dwc2_rx_fifo_level_intr(hsotg);
+		if (gintsts & GINTSTS_NPTXFEMP)
+			dwc2_np_tx_fifo_empty_intr(hsotg);
+		if (gintsts & GINTSTS_I2CINT)
+			/* Todo: Implement i2cintr handler */
+			writel(GINTSTS_I2CINT, hsotg->regs + GINTSTS);
+		if (gintsts & GINTSTS_PRTINT)
+			dwc2_port_intr(hsotg);
+		if (gintsts & GINTSTS_HCHINT)
+			dwc2_hc_intr(hsotg);
+		if (gintsts & GINTSTS_PTXFEMP)
+			dwc2_perio_tx_fifo_empty_intr(hsotg);
+
+#ifndef DEBUG_SOF
+		if (gintsts != GINTSTS_SOF) {
+#endif
+			dev_vdbg(hsotg->dev,
+				 "DWC OTG HCD Finished Servicing Interrupts\n");
+			dev_vdbg(hsotg->dev,
+				 "DWC OTG HCD gintsts=0x%08x gintmsk=0x%08x\n",
+				 readl(hsotg->regs + GINTSTS),
+				 readl(hsotg->regs + GINTMSK));
+#ifndef DEBUG_SOF
+		}
+#endif
+	}
+
+	spin_unlock(&hsotg->lock);
+
+	return retval;
+}
diff --git a/drivers/staging/dwc2/hcd_queue.c b/drivers/staging/dwc2/hcd_queue.c
new file mode 100644
index 0000000..74b7b9b
--- /dev/null
+++ b/drivers/staging/dwc2/hcd_queue.c
@@ -0,0 +1,675 @@
+/*
+ * hcd_queue.c - DesignWare HS OTG Controller host queuing routines
+ *
+ * Copyright (C) 2004-2013 Synopsys, Inc.
+ *
+ * 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, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 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 names of the above-listed copyright holders may not 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 the License, or (at your option) any
+ * later version.
+ *
+ * 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.
+ */
+
+/*
+ * This file contains the functions to manage Queue Heads and Queue
+ * Transfer Descriptors for Host mode
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+
+#include <linux/usb/hcd.h>
+#include <linux/usb/ch11.h>
+
+#include "core.h"
+#include "hcd.h"
+
+/**
+ * dwc2_qh_init() - Initializes a QH structure
+ *
+ * @hsotg: The HCD state structure for the DWC OTG controller
+ * @qh:    The QH to init
+ * @urb:   Holds the information about the device/endpoint needed to initialize
+ *         the QH
+ */
+#define SCHEDULE_SLOP 10
+static void dwc2_qh_init(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh,
+			 struct dwc2_hcd_urb *urb)
+{
+	int dev_speed, hub_addr, hub_port;
+	char *speed, *type;
+
+	dev_vdbg(hsotg->dev, "%s()\n", __func__);
+
+	/* Initialize QH */
+	qh->ep_type = dwc2_hcd_get_pipe_type(&urb->pipe_info);
+	qh->ep_is_in = dwc2_hcd_is_pipe_in(&urb->pipe_info) ? 1 : 0;
+
+	qh->data_toggle = DWC2_HC_PID_DATA0;
+	qh->maxp = dwc2_hcd_get_mps(&urb->pipe_info);
+	INIT_LIST_HEAD(&qh->qtd_list);
+	INIT_LIST_HEAD(&qh->qh_list_entry);
+
+	/* FS/LS Endpoint on HS Hub, NOT virtual root hub */
+	dev_speed = dwc2_host_get_speed(hsotg, urb->priv);
+
+	dwc2_host_hub_info(hsotg, urb->priv, &hub_addr, &hub_port);
+
+	if ((dev_speed == USB_SPEED_LOW || dev_speed == USB_SPEED_FULL) &&
+	    hub_addr != 0 && hub_addr != 1) {
+		dev_vdbg(hsotg->dev,
+			 "QH init: EP %d: TT found at hub addr %d, for port %d\n",
+			 dwc2_hcd_get_ep_num(&urb->pipe_info), hub_addr,
+			 hub_port);
+		qh->do_split = 1;
+	}
+
+	if (qh->ep_type == USB_ENDPOINT_XFER_INT ||
+	    qh->ep_type == USB_ENDPOINT_XFER_ISOC) {
+		/* Compute scheduling parameters once and save them */
+		u32 hprt, prtspd;
+
+		/* Todo: Account for split transfers in the bus time */
+		int bytecount =
+			dwc2_hb_mult(qh->maxp) * dwc2_max_packet(qh->maxp);
+
+		qh->usecs = NS_TO_US(usb_calc_bus_time(qh->do_split ?
+				USB_SPEED_HIGH : dev_speed, qh->ep_is_in,
+				qh->ep_type == USB_ENDPOINT_XFER_ISOC,
+				bytecount));
+		/* Start in a slightly future (micro)frame */
+		qh->sched_frame = dwc2_frame_num_inc(hsotg->frame_number,
+						     SCHEDULE_SLOP);
+		qh->interval = urb->interval;
+#if 0
+		/* Increase interrupt polling rate for debugging */
+		if (qh->ep_type == USB_ENDPOINT_XFER_INT)
+			qh->interval = 8;
+#endif
+		hprt = readl(hsotg->regs + HPRT0);
+		prtspd = hprt & HPRT0_SPD_MASK;
+		if (prtspd == HPRT0_SPD_HIGH_SPEED &&
+		    (dev_speed == USB_SPEED_LOW ||
+		     dev_speed == USB_SPEED_FULL)) {
+			qh->interval *= 8;
+			qh->sched_frame |= 0x7;
+			qh->start_split_frame = qh->sched_frame;
+		}
+		dev_dbg(hsotg->dev, "interval=%d\n", qh->interval);
+	}
+
+	dev_vdbg(hsotg->dev, "DWC OTG HCD QH Initialized\n");
+	dev_vdbg(hsotg->dev, "DWC OTG HCD QH - qh = %p\n", qh);
+	dev_vdbg(hsotg->dev, "DWC OTG HCD QH - Device Address = %d\n",
+		 dwc2_hcd_get_dev_addr(&urb->pipe_info));
+	dev_vdbg(hsotg->dev, "DWC OTG HCD QH - Endpoint %d, %s\n",
+		 dwc2_hcd_get_ep_num(&urb->pipe_info),
+		 dwc2_hcd_is_pipe_in(&urb->pipe_info) ? "IN" : "OUT");
+
+	qh->dev_speed = dev_speed;
+
+	switch (dev_speed) {
+	case USB_SPEED_LOW:
+		speed = "low";
+		break;
+	case USB_SPEED_FULL:
+		speed = "full";
+		break;
+	case USB_SPEED_HIGH:
+		speed = "high";
+		break;
+	default:
+		speed = "?";
+		break;
+	}
+	dev_vdbg(hsotg->dev, "DWC OTG HCD QH - Speed = %s\n", speed);
+
+	switch (qh->ep_type) {
+	case USB_ENDPOINT_XFER_ISOC:
+		type = "isochronous";
+		break;
+	case USB_ENDPOINT_XFER_INT:
+		type = "interrupt";
+		break;
+	case USB_ENDPOINT_XFER_CONTROL:
+		type = "control";
+		break;
+	case USB_ENDPOINT_XFER_BULK:
+		type = "bulk";
+		break;
+	default:
+		type = "?";
+		break;
+	}
+
+	dev_vdbg(hsotg->dev, "DWC OTG HCD QH - Type = %s\n", type);
+
+	if (qh->ep_type == USB_ENDPOINT_XFER_INT) {
+		dev_vdbg(hsotg->dev, "DWC OTG HCD QH - usecs = %d\n",
+			 qh->usecs);
+		dev_vdbg(hsotg->dev, "DWC OTG HCD QH - interval = %d\n",
+			 qh->interval);
+	}
+}
+
+/**
+ * dwc2_hcd_qh_create() - Allocates and initializes a QH
+ *
+ * @hsotg:        The HCD state structure for the DWC OTG controller
+ * @urb:          Holds the information about the device/endpoint needed
+ *                to initialize the QH
+ * @atomic_alloc: Flag to do atomic allocation if needed
+ *
+ * Return: Pointer to the newly allocated QH, or NULL on error
+ */
+static struct dwc2_qh *dwc2_hcd_qh_create(struct dwc2_hsotg *hsotg,
+					  struct dwc2_hcd_urb *urb,
+					  gfp_t mem_flags)
+{
+	struct dwc2_qh *qh;
+
+	/* Allocate memory */
+	qh = kzalloc(sizeof(*qh), mem_flags);
+	if (!qh)
+		return NULL;
+
+	dwc2_qh_init(hsotg, qh, urb);
+
+	if (hsotg->core_params->dma_desc_enable > 0 &&
+	    dwc2_hcd_qh_init_ddma(hsotg, qh, mem_flags) < 0) {
+		dwc2_hcd_qh_free(hsotg, qh);
+		return NULL;
+	}
+
+	return qh;
+}
+
+/**
+ * dwc2_hcd_qh_free() - Frees the QH
+ *
+ * @hsotg: HCD instance
+ * @qh:    The QH to free
+ *
+ * QH should already be removed from the list. QTD list should already be empty
+ * if called from URB Dequeue.
+ *
+ * Must NOT be called with interrupt disabled or spinlock held
+ */
+void dwc2_hcd_qh_free(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
+{
+	u32 buf_size;
+
+	if (hsotg->core_params->dma_desc_enable > 0) {
+		dwc2_hcd_qh_free_ddma(hsotg, qh);
+	} else if (qh->dw_align_buf) {
+		if (qh->ep_type == USB_ENDPOINT_XFER_ISOC)
+			buf_size = 4096;
+		else
+			buf_size = hsotg->core_params->max_transfer_size;
+		dma_free_coherent(hsotg->dev, buf_size, qh->dw_align_buf,
+				  qh->dw_align_buf_dma);
+	}
+
+	kfree(qh);
+}
+
+/**
+ * dwc2_periodic_channel_available() - Checks that a channel is available for a
+ * periodic transfer
+ *
+ * @hsotg: The HCD state structure for the DWC OTG controller
+ *
+ * Return: 0 if successful, negative error code otherise
+ */
+static int dwc2_periodic_channel_available(struct dwc2_hsotg *hsotg)
+{
+	/*
+	 * Currently assuming that there is a dedicated host channnel for
+	 * each periodic transaction plus at least one host channel for
+	 * non-periodic transactions
+	 */
+	int status;
+	int num_channels;
+
+	num_channels = hsotg->core_params->host_channels;
+	if (hsotg->periodic_channels + hsotg->non_periodic_channels <
+								num_channels
+	    && hsotg->periodic_channels < num_channels - 1) {
+		status = 0;
+	} else {
+		dev_dbg(hsotg->dev,
+			"%s: Total channels: %d, Periodic: %d, "
+			"Non-periodic: %d\n", __func__, num_channels,
+			hsotg->periodic_channels, hsotg->non_periodic_channels);
+		status = -ENOSPC;
+	}
+
+	return status;
+}
+
+/**
+ * dwc2_check_periodic_bandwidth() - Checks that there is sufficient bandwidth
+ * for the specified QH in the periodic schedule
+ *
+ * @hsotg: The HCD state structure for the DWC OTG controller
+ * @qh:    QH containing periodic bandwidth required
+ *
+ * Return: 0 if successful, negative error code otherwise
+ *
+ * For simplicity, this calculation assumes that all the transfers in the
+ * periodic schedule may occur in the same (micro)frame
+ */
+static int dwc2_check_periodic_bandwidth(struct dwc2_hsotg *hsotg,
+					 struct dwc2_qh *qh)
+{
+	int status;
+	s16 max_claimed_usecs;
+
+	status = 0;
+
+	if (qh->dev_speed == USB_SPEED_HIGH || qh->do_split) {
+		/*
+		 * High speed mode
+		 * Max periodic usecs is 80% x 125 usec = 100 usec
+		 */
+		max_claimed_usecs = 100 - qh->usecs;
+	} else {
+		/*
+		 * Full speed mode
+		 * Max periodic usecs is 90% x 1000 usec = 900 usec
+		 */
+		max_claimed_usecs = 900 - qh->usecs;
+	}
+
+	if (hsotg->periodic_usecs > max_claimed_usecs) {
+		dev_err(hsotg->dev,
+			"%s: already claimed usecs %d, required usecs %d\n",
+			__func__, hsotg->periodic_usecs, qh->usecs);
+		status = -ENOSPC;
+	}
+
+	return status;
+}
+
+/**
+ * dwc2_check_max_xfer_size() - Checks that the max transfer size allowed in a
+ * host channel is large enough to handle the maximum data transfer in a single
+ * (micro)frame for a periodic transfer
+ *
+ * @hsotg: The HCD state structure for the DWC OTG controller
+ * @qh:    QH for a periodic endpoint
+ *
+ * Return: 0 if successful, negative error code otherwise
+ */
+static int dwc2_check_max_xfer_size(struct dwc2_hsotg *hsotg,
+				    struct dwc2_qh *qh)
+{
+	u32 max_xfer_size;
+	u32 max_channel_xfer_size;
+	int status = 0;
+
+	max_xfer_size = dwc2_max_packet(qh->maxp) * dwc2_hb_mult(qh->maxp);
+	max_channel_xfer_size = hsotg->core_params->max_transfer_size;
+
+	if (max_xfer_size > max_channel_xfer_size) {
+		dev_err(hsotg->dev,
+			"%s: Periodic xfer length %d > max xfer length for channel %d\n",
+			__func__, max_xfer_size, max_channel_xfer_size);
+		status = -ENOSPC;
+	}
+
+	return status;
+}
+
+/**
+ * dwc2_schedule_periodic() - Schedules an interrupt or isochronous transfer in
+ * the periodic schedule
+ *
+ * @hsotg: The HCD state structure for the DWC OTG controller
+ * @qh:    QH for the periodic transfer. The QH should already contain the
+ *         scheduling information.
+ *
+ * Return: 0 if successful, negative error code otherwise
+ */
+static int dwc2_schedule_periodic(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
+{
+	int status;
+
+	status = dwc2_periodic_channel_available(hsotg);
+	if (status) {
+		dev_dbg(hsotg->dev,
+			"%s: No host channel available for periodic transfer\n",
+			__func__);
+		return status;
+	}
+
+	status = dwc2_check_periodic_bandwidth(hsotg, qh);
+	if (status) {
+		dev_dbg(hsotg->dev,
+			"%s: Insufficient periodic bandwidth for periodic transfer\n",
+			__func__);
+		return status;
+	}
+
+	status = dwc2_check_max_xfer_size(hsotg, qh);
+	if (status) {
+		dev_dbg(hsotg->dev,
+			"%s: Channel max transfer size too small for periodic transfer\n",
+			__func__);
+		return status;
+	}
+
+	if (hsotg->core_params->dma_desc_enable > 0)
+		/* Don't rely on SOF and start in ready schedule */
+		list_add_tail(&qh->qh_list_entry, &hsotg->periodic_sched_ready);
+	else
+		/* Always start in inactive schedule */
+		list_add_tail(&qh->qh_list_entry,
+			      &hsotg->periodic_sched_inactive);
+
+	/* Reserve periodic channel */
+	hsotg->periodic_channels++;
+
+	/* Update claimed usecs per (micro)frame */
+	hsotg->periodic_usecs += qh->usecs;
+
+	return status;
+}
+
+/**
+ * dwc2_deschedule_periodic() - Removes an interrupt or isochronous transfer
+ * from the periodic schedule
+ *
+ * @hsotg: The HCD state structure for the DWC OTG controller
+ * @qh:	   QH for the periodic transfer
+ */
+static void dwc2_deschedule_periodic(struct dwc2_hsotg *hsotg,
+				     struct dwc2_qh *qh)
+{
+	list_del_init(&qh->qh_list_entry);
+
+	/* Release periodic channel reservation */
+	hsotg->periodic_channels--;
+
+	/* Update claimed usecs per (micro)frame */
+	hsotg->periodic_usecs -= qh->usecs;
+}
+
+/**
+ * dwc2_hcd_qh_add() - Adds a QH to either the non periodic or periodic
+ * schedule if it is not already in the schedule. If the QH is already in
+ * the schedule, no action is taken.
+ *
+ * @hsotg: The HCD state structure for the DWC OTG controller
+ * @qh:    The QH to add
+ *
+ * Return: 0 if successful, negative error code otherwise
+ */
+int dwc2_hcd_qh_add(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
+{
+	int status = 0;
+	u32 intr_mask;
+
+	dev_vdbg(hsotg->dev, "%s()\n", __func__);
+
+	if (!list_empty(&qh->qh_list_entry))
+		/* QH already in a schedule */
+		return status;
+
+	/* Add the new QH to the appropriate schedule */
+	if (dwc2_qh_is_non_per(qh)) {
+		/* Always start in inactive schedule */
+		list_add_tail(&qh->qh_list_entry,
+			      &hsotg->non_periodic_sched_inactive);
+	} else {
+		status = dwc2_schedule_periodic(hsotg, qh);
+		if (status == 0) {
+			if (!hsotg->periodic_qh_count) {
+				intr_mask = readl(hsotg->regs + GINTMSK);
+				intr_mask |= GINTSTS_SOF;
+				writel(intr_mask, hsotg->regs + GINTMSK);
+			}
+			hsotg->periodic_qh_count++;
+		}
+	}
+
+	return status;
+}
+
+/**
+ * dwc2_hcd_qh_unlink() - Removes a QH from either the non-periodic or periodic
+ * schedule. Memory is not freed.
+ *
+ * @hsotg: The HCD state structure
+ * @qh:    QH to remove from schedule
+ */
+void dwc2_hcd_qh_unlink(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
+{
+	u32 intr_mask;
+
+	dev_vdbg(hsotg->dev, "%s()\n", __func__);
+
+	if (list_empty(&qh->qh_list_entry))
+		/* QH is not in a schedule */
+		return;
+
+	if (dwc2_qh_is_non_per(qh)) {
+		if (hsotg->non_periodic_qh_ptr == &qh->qh_list_entry)
+			hsotg->non_periodic_qh_ptr =
+					hsotg->non_periodic_qh_ptr->next;
+		list_del_init(&qh->qh_list_entry);
+	} else {
+		dwc2_deschedule_periodic(hsotg, qh);
+		hsotg->periodic_qh_count--;
+		if (!hsotg->periodic_qh_count) {
+			intr_mask = readl(hsotg->regs + GINTMSK);
+			intr_mask &= ~GINTSTS_SOF;
+			writel(intr_mask, hsotg->regs + GINTMSK);
+		}
+	}
+}
+
+/*
+ * Schedule the next continuing periodic split transfer
+ */
+static void dwc2_sched_periodic_split(struct dwc2_hsotg *hsotg,
+				      struct dwc2_qh *qh, u16 frame_number,
+				      int sched_next_periodic_split)
+{
+	u16 incr;
+
+	if (sched_next_periodic_split) {
+		qh->sched_frame = frame_number;
+		incr = dwc2_frame_num_inc(qh->start_split_frame, 1);
+		if (dwc2_frame_num_le(frame_number, incr)) {
+			/*
+			 * Allow one frame to elapse after start split
+			 * microframe before scheduling complete split, but
+			 * DON'T if we are doing the next start split in the
+			 * same frame for an ISOC out
+			 */
+			if (qh->ep_type != USB_ENDPOINT_XFER_ISOC ||
+			    qh->ep_is_in != 0) {
+				qh->sched_frame =
+					dwc2_frame_num_inc(qh->sched_frame, 1);
+			}
+		}
+	} else {
+		qh->sched_frame = dwc2_frame_num_inc(qh->start_split_frame,
+						     qh->interval);
+		if (dwc2_frame_num_le(qh->sched_frame, frame_number))
+			qh->sched_frame = frame_number;
+		qh->sched_frame |= 0x7;
+		qh->start_split_frame = qh->sched_frame;
+	}
+}
+
+/*
+ * Deactivates a QH. For non-periodic QHs, removes the QH from the active
+ * non-periodic schedule. The QH is added to the inactive non-periodic
+ * schedule if any QTDs are still attached to the QH.
+ *
+ * For periodic QHs, the QH is removed from the periodic queued schedule. If
+ * there are any QTDs still attached to the QH, the QH is added to either the
+ * periodic inactive schedule or the periodic ready schedule and its next
+ * scheduled frame is calculated. The QH is placed in the ready schedule if
+ * the scheduled frame has been reached already. Otherwise it's placed in the
+ * inactive schedule. If there are no QTDs attached to the QH, the QH is
+ * completely removed from the periodic schedule.
+ */
+void dwc2_hcd_qh_deactivate(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh,
+			    int sched_next_periodic_split)
+{
+	dev_vdbg(hsotg->dev, "%s()\n", __func__);
+
+	if (dwc2_qh_is_non_per(qh)) {
+		dwc2_hcd_qh_unlink(hsotg, qh);
+		if (!list_empty(&qh->qtd_list))
+			/* Add back to inactive non-periodic schedule */
+			dwc2_hcd_qh_add(hsotg, qh);
+	} else {
+		u16 frame_number = dwc2_hcd_get_frame_number(hsotg);
+
+		if (qh->do_split) {
+			dwc2_sched_periodic_split(hsotg, qh, frame_number,
+						  sched_next_periodic_split);
+		} else {
+			qh->sched_frame = dwc2_frame_num_inc(qh->sched_frame,
+							     qh->interval);
+			if (dwc2_frame_num_le(qh->sched_frame, frame_number))
+				qh->sched_frame = frame_number;
+		}
+
+		if (list_empty(&qh->qtd_list)) {
+			dwc2_hcd_qh_unlink(hsotg, qh);
+		} else {
+			/*
+			 * Remove from periodic_sched_queued and move to
+			 * appropriate queue
+			 */
+			if (qh->sched_frame == frame_number)
+				list_move(&qh->qh_list_entry,
+					  &hsotg->periodic_sched_ready);
+			else
+				list_move(&qh->qh_list_entry,
+					  &hsotg->periodic_sched_inactive);
+		}
+	}
+}
+
+/**
+ * dwc2_hcd_qtd_init() - Initializes a QTD structure
+ *
+ * @qtd: The QTD to initialize
+ * @urb: The associated URB
+ */
+void dwc2_hcd_qtd_init(struct dwc2_qtd *qtd, struct dwc2_hcd_urb *urb)
+{
+	qtd->urb = urb;
+	if (dwc2_hcd_get_pipe_type(&urb->pipe_info) ==
+			USB_ENDPOINT_XFER_CONTROL) {
+		/*
+		 * The only time the QTD data toggle is used is on the data
+		 * phase of control transfers. This phase always starts with
+		 * DATA1.
+		 */
+		qtd->data_toggle = DWC2_HC_PID_DATA1;
+		qtd->control_phase = DWC2_CONTROL_SETUP;
+	}
+
+	/* Start split */
+	qtd->complete_split = 0;
+	qtd->isoc_split_pos = DWC2_HCSPLT_XACTPOS_ALL;
+	qtd->isoc_split_offset = 0;
+	qtd->in_process = 0;
+
+	/* Store the qtd ptr in the urb to reference the QTD */
+	urb->qtd = qtd;
+}
+
+/**
+ * dwc2_hcd_qtd_add() - Adds a QTD to the QTD-list of a QH
+ *
+ * @hsotg:        The DWC HCD structure
+ * @qtd:          The QTD to add
+ * @qh:           Out parameter to return queue head
+ * @atomic_alloc: Flag to do atomic alloc if needed
+ *
+ * Return: 0 if successful, negative error code otherwise
+ *
+ * Finds the correct QH to place the QTD into. If it does not find a QH, it
+ * will create a new QH. If the QH to which the QTD is added is not currently
+ * scheduled, it is placed into the proper schedule based on its EP type.
+ */
+int dwc2_hcd_qtd_add(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd,
+		     struct dwc2_qh **qh, gfp_t mem_flags)
+{
+	struct dwc2_hcd_urb *urb = qtd->urb;
+	unsigned long flags;
+	int allocated = 0;
+	int retval = 0;
+
+	/*
+	 * Get the QH which holds the QTD-list to insert to. Create QH if it
+	 * doesn't exist.
+	 */
+	if (*qh == NULL) {
+		*qh = dwc2_hcd_qh_create(hsotg, urb, mem_flags);
+		if (*qh == NULL)
+			return -ENOMEM;
+		allocated = 1;
+	}
+
+	spin_lock_irqsave(&hsotg->lock, flags);
+	retval = dwc2_hcd_qh_add(hsotg, *qh);
+	if (retval && allocated) {
+		struct dwc2_qtd *qtd2, *qtd2_tmp;
+		struct dwc2_qh *qh_tmp = *qh;
+
+		*qh = NULL;
+		dwc2_hcd_qh_unlink(hsotg, qh_tmp);
+
+		/* Free each QTD in the QH's QTD list */
+		list_for_each_entry_safe(qtd2, qtd2_tmp, &qh_tmp->qtd_list,
+					 qtd_list_entry)
+			dwc2_hcd_qtd_unlink_and_free(hsotg, qtd2, qh_tmp);
+
+		spin_unlock_irqrestore(&hsotg->lock, flags);
+		dwc2_hcd_qh_free(hsotg, qh_tmp);
+	} else {
+		qtd->qh = *qh;
+		list_add_tail(&qtd->qtd_list_entry, &(*qh)->qtd_list);
+		spin_unlock_irqrestore(&hsotg->lock, flags);
+	}
+
+	return retval;
+}
diff --git a/drivers/staging/dwc2/hw.h b/drivers/staging/dwc2/hw.h
new file mode 100644
index 0000000..382a1d7
--- /dev/null
+++ b/drivers/staging/dwc2/hw.h
@@ -0,0 +1,811 @@
+/*
+ * hw.h - DesignWare HS OTG Controller hardware definitions
+ *
+ * Copyright 2004-2013 Synopsys, Inc.
+ *
+ * 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, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 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 names of the above-listed copyright holders may not 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 the License, or (at your option) any
+ * later version.
+ *
+ * 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 __DWC2_HW_H__
+#define __DWC2_HW_H__
+
+#define HSOTG_REG(x)	(x)
+
+#define GOTGCTL				HSOTG_REG(0x000)
+#define GOTGCTL_CHIRPEN			(1 << 27)
+#define GOTGCTL_MULT_VALID_BC_MASK	(0x1f << 22)
+#define GOTGCTL_MULT_VALID_BC_SHIFT	22
+#define GOTGCTL_OTGVER			(1 << 20)
+#define GOTGCTL_BSESVLD			(1 << 19)
+#define GOTGCTL_ASESVLD			(1 << 18)
+#define GOTGCTL_DBNC_SHORT		(1 << 17)
+#define GOTGCTL_CONID_B			(1 << 16)
+#define GOTGCTL_DEVHNPEN		(1 << 11)
+#define GOTGCTL_HSTSETHNPEN		(1 << 10)
+#define GOTGCTL_HNPREQ			(1 << 9)
+#define GOTGCTL_HSTNEGSCS		(1 << 8)
+#define GOTGCTL_SESREQ			(1 << 1)
+#define GOTGCTL_SESREQSCS		(1 << 0)
+
+#define GOTGINT				HSOTG_REG(0x004)
+#define GOTGINT_DBNCE_DONE		(1 << 19)
+#define GOTGINT_A_DEV_TOUT_CHG		(1 << 18)
+#define GOTGINT_HST_NEG_DET		(1 << 17)
+#define GOTGINT_HST_NEG_SUC_STS_CHNG	(1 << 9)
+#define GOTGINT_SES_REQ_SUC_STS_CHNG	(1 << 8)
+#define GOTGINT_SES_END_DET		(1 << 2)
+
+#define GAHBCFG				HSOTG_REG(0x008)
+#define GAHBCFG_AHB_SINGLE		(1 << 23)
+#define GAHBCFG_NOTI_ALL_DMA_WRIT	(1 << 22)
+#define GAHBCFG_REM_MEM_SUPP		(1 << 21)
+#define GAHBCFG_P_TXF_EMP_LVL		(1 << 8)
+#define GAHBCFG_NP_TXF_EMP_LVL		(1 << 7)
+#define GAHBCFG_DMA_EN			(1 << 5)
+#define GAHBCFG_HBSTLEN_MASK		(0xf << 1)
+#define GAHBCFG_HBSTLEN_SHIFT		1
+#define GAHBCFG_HBSTLEN_SINGLE			(0 << 1)
+#define GAHBCFG_HBSTLEN_INCR			(1 << 1)
+#define GAHBCFG_HBSTLEN_INCR4			(3 << 1)
+#define GAHBCFG_HBSTLEN_INCR8			(5 << 1)
+#define GAHBCFG_HBSTLEN_INCR16			(7 << 1)
+#define GAHBCFG_GLBL_INTR_EN		(1 << 0)
+
+#define GUSBCFG				HSOTG_REG(0x00C)
+#define GUSBCFG_FORCEDEVMODE		(1 << 30)
+#define GUSBCFG_FORCEHOSTMODE		(1 << 29)
+#define GUSBCFG_TXENDDELAY		(1 << 28)
+#define GUSBCFG_ICTRAFFICPULLREMOVE	(1 << 27)
+#define GUSBCFG_ICUSBCAP		(1 << 26)
+#define GUSBCFG_ULPI_INT_PROT_DIS	(1 << 25)
+#define GUSBCFG_INDICATORPASSTHROUGH	(1 << 24)
+#define GUSBCFG_INDICATORCOMPLEMENT	(1 << 23)
+#define GUSBCFG_TERMSELDLPULSE		(1 << 22)
+#define GUSBCFG_ULPI_INT_VBUS_IND	(1 << 21)
+#define GUSBCFG_ULPI_EXT_VBUS_DRV	(1 << 20)
+#define GUSBCFG_ULPI_CLK_SUSP_M		(1 << 19)
+#define GUSBCFG_ULPI_AUTO_RES		(1 << 18)
+#define GUSBCFG_ULPI_FS_LS		(1 << 17)
+#define GUSBCFG_OTG_UTMI_FS_SEL		(1 << 16)
+#define GUSBCFG_PHY_LP_CLK_SEL		(1 << 15)
+#define GUSBCFG_USBTRDTIM_MASK		(0xf << 10)
+#define GUSBCFG_USBTRDTIM_SHIFT		10
+#define GUSBCFG_HNPCAP			(1 << 9)
+#define GUSBCFG_SRPCAP			(1 << 8)
+#define GUSBCFG_DDRSEL			(1 << 7)
+#define GUSBCFG_PHYSEL			(1 << 6)
+#define GUSBCFG_FSINTF			(1 << 5)
+#define GUSBCFG_ULPI_UTMI_SEL		(1 << 4)
+#define GUSBCFG_PHYIF16			(1 << 3)
+#define GUSBCFG_TOUTCAL_MASK		(0x7 << 0)
+#define GUSBCFG_TOUTCAL_SHIFT		0
+#define GUSBCFG_TOUTCAL_LIMIT		0x7
+#define GUSBCFG_TOUTCAL(_x)		((_x) << 0)
+
+#define GRSTCTL				HSOTG_REG(0x010)
+#define GRSTCTL_AHBIDLE			(1 << 31)
+#define GRSTCTL_DMAREQ			(1 << 30)
+#define GRSTCTL_TXFNUM_MASK		(0x1f << 6)
+#define GRSTCTL_TXFNUM_SHIFT		6
+#define GRSTCTL_TXFNUM_LIMIT		0x1f
+#define GRSTCTL_TXFNUM(_x)		((_x) << 6)
+#define GRSTCTL_TXFFLSH			(1 << 5)
+#define GRSTCTL_RXFFLSH			(1 << 4)
+#define GRSTCTL_IN_TKNQ_FLSH		(1 << 3)
+#define GRSTCTL_FRMCNTRRST		(1 << 2)
+#define GRSTCTL_HSFTRST			(1 << 1)
+#define GRSTCTL_CSFTRST			(1 << 0)
+
+#define GINTSTS				HSOTG_REG(0x014)
+#define GINTMSK				HSOTG_REG(0x018)
+#define GINTSTS_WKUPINT			(1 << 31)
+#define GINTSTS_SESSREQINT		(1 << 30)
+#define GINTSTS_DISCONNINT		(1 << 29)
+#define GINTSTS_CONIDSTSCHNG		(1 << 28)
+#define GINTSTS_LPMTRANRCVD		(1 << 27)
+#define GINTSTS_PTXFEMP			(1 << 26)
+#define GINTSTS_HCHINT			(1 << 25)
+#define GINTSTS_PRTINT			(1 << 24)
+#define GINTSTS_RESETDET		(1 << 23)
+#define GINTSTS_FET_SUSP		(1 << 22)
+#define GINTSTS_INCOMPL_IP		(1 << 21)
+#define GINTSTS_INCOMPL_SOIN		(1 << 20)
+#define GINTSTS_OEPINT			(1 << 19)
+#define GINTSTS_IEPINT			(1 << 18)
+#define GINTSTS_EPMIS			(1 << 17)
+#define GINTSTS_RESTOREDONE		(1 << 16)
+#define GINTSTS_EOPF			(1 << 15)
+#define GINTSTS_ISOUTDROP		(1 << 14)
+#define GINTSTS_ENUMDONE		(1 << 13)
+#define GINTSTS_USBRST			(1 << 12)
+#define GINTSTS_USBSUSP			(1 << 11)
+#define GINTSTS_ERLYSUSP		(1 << 10)
+#define GINTSTS_I2CINT			(1 << 9)
+#define GINTSTS_ULPI_CK_INT		(1 << 8)
+#define GINTSTS_GOUTNAKEFF		(1 << 7)
+#define GINTSTS_GINNAKEFF		(1 << 6)
+#define GINTSTS_NPTXFEMP		(1 << 5)
+#define GINTSTS_RXFLVL			(1 << 4)
+#define GINTSTS_SOF			(1 << 3)
+#define GINTSTS_OTGINT			(1 << 2)
+#define GINTSTS_MODEMIS			(1 << 1)
+#define GINTSTS_CURMODE_HOST		(1 << 0)
+
+#define GRXSTSR				HSOTG_REG(0x01C)
+#define GRXSTSP				HSOTG_REG(0x020)
+#define GRXSTS_FN_MASK			(0x7f << 25)
+#define GRXSTS_FN_SHIFT			25
+#define GRXSTS_PKTSTS_MASK		(0xf << 17)
+#define GRXSTS_PKTSTS_SHIFT		17
+#define GRXSTS_PKTSTS_GLOBALOUTNAK		(1 << 17)
+#define GRXSTS_PKTSTS_OUTRX			(2 << 17)
+#define GRXSTS_PKTSTS_HCHIN			(2 << 17)
+#define GRXSTS_PKTSTS_OUTDONE			(3 << 17)
+#define GRXSTS_PKTSTS_HCHIN_XFER_COMP		(3 << 17)
+#define GRXSTS_PKTSTS_SETUPDONE			(4 << 17)
+#define GRXSTS_PKTSTS_DATATOGGLEERR		(5 << 17)
+#define GRXSTS_PKTSTS_SETUPRX			(6 << 17)
+#define GRXSTS_PKTSTS_HCHHALTED			(7 << 17)
+#define GRXSTS_HCHNUM_MASK		(0xf << 0)
+#define GRXSTS_HCHNUM_SHIFT		0
+#define GRXSTS_DPID_MASK		(0x3 << 15)
+#define GRXSTS_DPID_SHIFT		15
+#define GRXSTS_BYTECNT_MASK		(0x7ff << 4)
+#define GRXSTS_BYTECNT_SHIFT		4
+#define GRXSTS_EPNUM_MASK		(0xf << 0)
+#define GRXSTS_EPNUM_SHIFT		0
+
+#define GRXFSIZ				HSOTG_REG(0x024)
+
+#define GNPTXFSIZ			HSOTG_REG(0x028)
+#define GNPTXFSIZ_NP_TXF_DEP_MASK	(0xffff << 16)
+#define GNPTXFSIZ_NP_TXF_DEP_SHIFT	16
+#define GNPTXFSIZ_NP_TXF_DEP_LIMIT	0xffff
+#define GNPTXFSIZ_NP_TXF_DEP(_x)	((_x) << 16)
+#define GNPTXFSIZ_NP_TXF_ST_ADDR_MASK	(0xffff << 0)
+#define GNPTXFSIZ_NP_TXF_ST_ADDR_SHIFT	0
+#define GNPTXFSIZ_NP_TXF_ST_ADDR_LIMIT	0xffff
+#define GNPTXFSIZ_NP_TXF_ST_ADDR(_x)	((_x) << 0)
+
+#define GNPTXSTS			HSOTG_REG(0x02C)
+#define GNPTXSTS_NP_TXQ_TOP_MASK		(0x7f << 24)
+#define GNPTXSTS_NP_TXQ_TOP_SHIFT		24
+#define GNPTXSTS_NP_TXQ_SPC_AVAIL_MASK		(0xff << 16)
+#define GNPTXSTS_NP_TXQ_SPC_AVAIL_SHIFT		16
+#define GNPTXSTS_NP_TXQ_SPC_AVAIL_GET(_v)	(((_v) >> 16) & 0xff)
+#define GNPTXSTS_NP_TXF_SPC_AVAIL_MASK		(0xffff << 0)
+#define GNPTXSTS_NP_TXF_SPC_AVAIL_SHIFT		0
+#define GNPTXSTS_NP_TXF_SPC_AVAIL_GET(_v)	(((_v) >> 0) & 0xffff)
+
+#define GI2CCTL				HSOTG_REG(0x0030)
+#define GI2CCTL_BSYDNE			(1 << 31)
+#define GI2CCTL_RW			(1 << 30)
+#define GI2CCTL_I2CDATSE0		(1 << 28)
+#define GI2CCTL_I2CDEVADDR_MASK		(0x3 << 26)
+#define GI2CCTL_I2CDEVADDR_SHIFT	26
+#define GI2CCTL_I2CSUSPCTL		(1 << 25)
+#define GI2CCTL_ACK			(1 << 24)
+#define GI2CCTL_I2CEN			(1 << 23)
+#define GI2CCTL_ADDR_MASK		(0x7f << 16)
+#define GI2CCTL_ADDR_SHIFT		16
+#define GI2CCTL_REGADDR_MASK		(0xff << 8)
+#define GI2CCTL_REGADDR_SHIFT		8
+#define GI2CCTL_RWDATA_MASK		(0xff << 0)
+#define GI2CCTL_RWDATA_SHIFT		0
+
+#define GPVNDCTL			HSOTG_REG(0x0034)
+#define GGPIO				HSOTG_REG(0x0038)
+#define GUID				HSOTG_REG(0x003c)
+#define GSNPSID				HSOTG_REG(0x0040)
+#define GHWCFG1				HSOTG_REG(0x0044)
+
+#define GHWCFG2				HSOTG_REG(0x0048)
+#define GHWCFG2_OTG_ENABLE_IC_USB		(1 << 31)
+#define GHWCFG2_DEV_TOKEN_Q_DEPTH_MASK		(0x1f << 26)
+#define GHWCFG2_DEV_TOKEN_Q_DEPTH_SHIFT		26
+#define GHWCFG2_HOST_PERIO_TX_Q_DEPTH_MASK	(0x3 << 24)
+#define GHWCFG2_HOST_PERIO_TX_Q_DEPTH_SHIFT	24
+#define GHWCFG2_NONPERIO_TX_Q_DEPTH_MASK	(0x3 << 22)
+#define GHWCFG2_NONPERIO_TX_Q_DEPTH_SHIFT	22
+#define GHWCFG2_MULTI_PROC_INT			(1 << 20)
+#define GHWCFG2_DYNAMIC_FIFO			(1 << 19)
+#define GHWCFG2_PERIO_EP_SUPPORTED		(1 << 18)
+#define GHWCFG2_NUM_HOST_CHAN_MASK		(0xf << 14)
+#define GHWCFG2_NUM_HOST_CHAN_SHIFT		14
+#define GHWCFG2_NUM_DEV_EP_MASK			(0xf << 10)
+#define GHWCFG2_NUM_DEV_EP_SHIFT		10
+#define GHWCFG2_FS_PHY_TYPE_MASK		(0x3 << 8)
+#define GHWCFG2_FS_PHY_TYPE_SHIFT		8
+#define GHWCFG2_FS_PHY_TYPE_NOT_SUPPORTED		(0 << 8)
+#define GHWCFG2_FS_PHY_TYPE_DEDICATED			(1 << 8)
+#define GHWCFG2_FS_PHY_TYPE_SHARED_UTMI			(2 << 8)
+#define GHWCFG2_FS_PHY_TYPE_SHARED_ULPI			(3 << 8)
+#define GHWCFG2_HS_PHY_TYPE_MASK		(0x3 << 6)
+#define GHWCFG2_HS_PHY_TYPE_SHIFT		6
+#define GHWCFG2_HS_PHY_TYPE_NOT_SUPPORTED		(0 << 6)
+#define GHWCFG2_HS_PHY_TYPE_UTMI			(1 << 6)
+#define GHWCFG2_HS_PHY_TYPE_ULPI			(2 << 6)
+#define GHWCFG2_HS_PHY_TYPE_UTMI_ULPI			(3 << 6)
+#define GHWCFG2_POINT2POINT			(1 << 5)
+#define GHWCFG2_ARCHITECTURE_MASK		(0x3 << 3)
+#define GHWCFG2_ARCHITECTURE_SHIFT		3
+#define GHWCFG2_SLAVE_ONLY_ARCH				(0 << 3)
+#define GHWCFG2_EXT_DMA_ARCH				(1 << 3)
+#define GHWCFG2_INT_DMA_ARCH				(2 << 3)
+#define GHWCFG2_OP_MODE_MASK			(0x7 << 0)
+#define GHWCFG2_OP_MODE_SHIFT			0
+#define GHWCFG2_OP_MODE_HNP_SRP_CAPABLE			(0 << 0)
+#define GHWCFG2_OP_MODE_SRP_ONLY_CAPABLE		(1 << 0)
+#define GHWCFG2_OP_MODE_NO_HNP_SRP_CAPABLE		(2 << 0)
+#define GHWCFG2_OP_MODE_SRP_CAPABLE_DEVICE		(3 << 0)
+#define GHWCFG2_OP_MODE_NO_SRP_CAPABLE_DEVICE		(4 << 0)
+#define GHWCFG2_OP_MODE_SRP_CAPABLE_HOST		(5 << 0)
+#define GHWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST		(6 << 0)
+#define GHWCFG2_OP_MODE_UNDEFINED			(7 << 0)
+
+#define GHWCFG3				HSOTG_REG(0x004c)
+#define GHWCFG3_DFIFO_DEPTH_MASK		(0xffff << 16)
+#define GHWCFG3_DFIFO_DEPTH_SHIFT		16
+#define GHWCFG3_OTG_LPM_EN			(1 << 15)
+#define GHWCFG3_BC_SUPPORT			(1 << 14)
+#define GHWCFG3_OTG_ENABLE_HSIC			(1 << 13)
+#define GHWCFG3_ADP_SUPP			(1 << 12)
+#define GHWCFG3_SYNCH_RESET_TYPE		(1 << 11)
+#define GHWCFG3_OPTIONAL_FEATURES		(1 << 10)
+#define GHWCFG3_VENDOR_CTRL_IF			(1 << 9)
+#define GHWCFG3_I2C				(1 << 8)
+#define GHWCFG3_OTG_FUNC			(1 << 7)
+#define GHWCFG3_PACKET_SIZE_CNTR_WIDTH_MASK	(0x7 << 4)
+#define GHWCFG3_PACKET_SIZE_CNTR_WIDTH_SHIFT	4
+#define GHWCFG3_XFER_SIZE_CNTR_WIDTH_MASK	(0xf << 0)
+#define GHWCFG3_XFER_SIZE_CNTR_WIDTH_SHIFT	0
+
+#define GHWCFG4				HSOTG_REG(0x0050)
+#define GHWCFG4_DESC_DMA_DYN			(1 << 31)
+#define GHWCFG4_DESC_DMA			(1 << 30)
+#define GHWCFG4_NUM_IN_EPS_MASK			(0xf << 26)
+#define GHWCFG4_NUM_IN_EPS_SHIFT		26
+#define GHWCFG4_DED_FIFO_EN			(1 << 25)
+#define GHWCFG4_SESSION_END_FILT_EN		(1 << 24)
+#define GHWCFG4_B_VALID_FILT_EN			(1 << 23)
+#define GHWCFG4_A_VALID_FILT_EN			(1 << 22)
+#define GHWCFG4_VBUS_VALID_FILT_EN		(1 << 21)
+#define GHWCFG4_IDDIG_FILT_EN			(1 << 20)
+#define GHWCFG4_NUM_DEV_MODE_CTRL_EP_MASK	(0xf << 16)
+#define GHWCFG4_NUM_DEV_MODE_CTRL_EP_SHIFT	16
+#define GHWCFG4_UTMI_PHY_DATA_WIDTH_MASK	(0x3 << 14)
+#define GHWCFG4_UTMI_PHY_DATA_WIDTH_SHIFT	14
+#define GHWCFG4_XHIBER				(1 << 7)
+#define GHWCFG4_HIBER				(1 << 6)
+#define GHWCFG4_MIN_AHB_FREQ			(1 << 5)
+#define GHWCFG4_POWER_OPTIMIZ			(1 << 4)
+#define GHWCFG4_NUM_DEV_PERIO_IN_EP_MASK	(0xf << 0)
+#define GHWCFG4_NUM_DEV_PERIO_IN_EP_SHIFT	0
+
+#define GLPMCFG				HSOTG_REG(0x0054)
+#define GLPMCFG_INV_SEL_HSIC		(1 << 31)
+#define GLPMCFG_HSIC_CONNECT		(1 << 30)
+#define GLPMCFG_RETRY_COUNT_STS_MASK	(0x7 << 25)
+#define GLPMCFG_RETRY_COUNT_STS_SHIFT	25
+#define GLPMCFG_SEND_LPM		(1 << 24)
+#define GLPMCFG_RETRY_COUNT_MASK	(0x7 << 21)
+#define GLPMCFG_RETRY_COUNT_SHIFT	21
+#define GLPMCFG_LPM_CHAN_INDEX_MASK	(0xf << 17)
+#define GLPMCFG_LPM_CHAN_INDEX_SHIFT	17
+#define GLPMCFG_SLEEP_STATE_RESUMEOK	(1 << 16)
+#define GLPMCFG_PRT_SLEEP_STS		(1 << 15)
+#define GLPMCFG_LPM_RESP_MASK		(0x3 << 13)
+#define GLPMCFG_LPM_RESP_SHIFT		13
+#define GLPMCFG_HIRD_THRES_MASK		(0x1f << 8)
+#define GLPMCFG_HIRD_THRES_SHIFT	8
+#define GLPMCFG_HIRD_THRES_EN			(0x10 << 8)
+#define GLPMCFG_EN_UTMI_SLEEP		(1 << 7)
+#define GLPMCFG_REM_WKUP_EN		(1 << 6)
+#define GLPMCFG_HIRD_MASK		(0xf << 2)
+#define GLPMCFG_HIRD_SHIFT		2
+#define GLPMCFG_APPL_RESP		(1 << 1)
+#define GLPMCFG_LPM_CAP_EN		(1 << 0)
+
+#define GPWRDN				HSOTG_REG(0x0058)
+#define GPWRDN_MULT_VAL_ID_BC_MASK	(0x1f << 24)
+#define GPWRDN_MULT_VAL_ID_BC_SHIFT	24
+#define GPWRDN_ADP_INT			(1 << 23)
+#define GPWRDN_BSESSVLD			(1 << 22)
+#define GPWRDN_IDSTS			(1 << 21)
+#define GPWRDN_LINESTATE_MASK		(0x3 << 19)
+#define GPWRDN_LINESTATE_SHIFT		19
+#define GPWRDN_STS_CHGINT_MSK		(1 << 18)
+#define GPWRDN_STS_CHGINT		(1 << 17)
+#define GPWRDN_SRP_DET_MSK		(1 << 16)
+#define GPWRDN_SRP_DET			(1 << 15)
+#define GPWRDN_CONNECT_DET_MSK		(1 << 14)
+#define GPWRDN_CONNECT_DET		(1 << 13)
+#define GPWRDN_DISCONN_DET_MSK		(1 << 12)
+#define GPWRDN_DISCONN_DET		(1 << 11)
+#define GPWRDN_RST_DET_MSK		(1 << 10)
+#define GPWRDN_RST_DET			(1 << 9)
+#define GPWRDN_LNSTSCHG_MSK		(1 << 8)
+#define GPWRDN_LNSTSCHG			(1 << 7)
+#define GPWRDN_DIS_VBUS			(1 << 6)
+#define GPWRDN_PWRDNSWTCH		(1 << 5)
+#define GPWRDN_PWRDNRSTN		(1 << 4)
+#define GPWRDN_PWRDNCLMP		(1 << 3)
+#define GPWRDN_RESTORE			(1 << 2)
+#define GPWRDN_PMUACTV			(1 << 1)
+#define GPWRDN_PMUINTSEL		(1 << 0)
+
+#define GDFIFOCFG			HSOTG_REG(0x005c)
+#define GDFIFOCFG_EPINFOBASE_MASK	(0xffff << 16)
+#define GDFIFOCFG_EPINFOBASE_SHIFT	16
+#define GDFIFOCFG_GDFIFOCFG_MASK	(0xffff << 0)
+#define GDFIFOCFG_GDFIFOCFG_SHIFT	0
+
+#define ADPCTL				HSOTG_REG(0x0060)
+#define ADPCTL_AR_MASK			(0x3 << 27)
+#define ADPCTL_AR_SHIFT			27
+#define ADPCTL_ADP_TMOUT_INT_MSK	(1 << 26)
+#define ADPCTL_ADP_SNS_INT_MSK		(1 << 25)
+#define ADPCTL_ADP_PRB_INT_MSK		(1 << 24)
+#define ADPCTL_ADP_TMOUT_INT		(1 << 23)
+#define ADPCTL_ADP_SNS_INT		(1 << 22)
+#define ADPCTL_ADP_PRB_INT		(1 << 21)
+#define ADPCTL_ADPENA			(1 << 20)
+#define ADPCTL_ADPRES			(1 << 19)
+#define ADPCTL_ENASNS			(1 << 18)
+#define ADPCTL_ENAPRB			(1 << 17)
+#define ADPCTL_RTIM_MASK		(0x7ff << 6)
+#define ADPCTL_RTIM_SHIFT		6
+#define ADPCTL_PRB_PER_MASK		(0x3 << 4)
+#define ADPCTL_PRB_PER_SHIFT		4
+#define ADPCTL_PRB_DELTA_MASK		(0x3 << 2)
+#define ADPCTL_PRB_DELTA_SHIFT		2
+#define ADPCTL_PRB_DSCHRG_MASK		(0x3 << 0)
+#define ADPCTL_PRB_DSCHRG_SHIFT		0
+
+#define HPTXFSIZ			HSOTG_REG(0x100)
+
+#define DPTXFSIZN(_a)			HSOTG_REG(0x104 + (((_a) - 1) * 4))
+#define DPTXFSIZN_DP_TXF_SIZE_MASK	(0xffff << 16)
+#define DPTXFSIZN_DP_TXF_SIZE_SHIFT	16
+#define DPTXFSIZN_DP_TXF_SIZE_GET(_v)	(((_v) >> 16) & 0xffff)
+#define DPTXFSIZN_DP_TXF_SIZE_LIMIT	0xffff
+#define DPTXFSIZN_DP_TXF_SIZE(_x)	((_x) << 16)
+#define DPTXFSIZN_DP_TXF_ST_ADDR_MASK	(0xffff << 0)
+#define DPTXFSIZN_DP_TXF_ST_ADDR_SHIFT	0
+
+#define FIFOSIZE_DEPTH_MASK		(0xffff << 16)
+#define FIFOSIZE_DEPTH_SHIFT		16
+#define FIFOSIZE_STARTADDR_MASK		(0xffff << 0)
+#define FIFOSIZE_STARTADDR_SHIFT	0
+
+/* Device mode registers */
+
+#define DCFG				HSOTG_REG(0x800)
+#define DCFG_EPMISCNT_MASK		(0x1f << 18)
+#define DCFG_EPMISCNT_SHIFT		18
+#define DCFG_EPMISCNT_LIMIT		0x1f
+#define DCFG_EPMISCNT(_x)		((_x) << 18)
+#define DCFG_PERFRINT_MASK		(0x3 << 11)
+#define DCFG_PERFRINT_SHIFT		11
+#define DCFG_PERFRINT_LIMIT		0x3
+#define DCFG_PERFRINT(_x)		((_x) << 11)
+#define DCFG_DEVADDR_MASK		(0x7f << 4)
+#define DCFG_DEVADDR_SHIFT		4
+#define DCFG_DEVADDR_LIMIT		0x7f
+#define DCFG_DEVADDR(_x)		((_x) << 4)
+#define DCFG_NZ_STS_OUT_HSHK		(1 << 2)
+#define DCFG_DEVSPD_MASK		(0x3 << 0)
+#define DCFG_DEVSPD_SHIFT		0
+#define DCFG_DEVSPD_HS				(0 << 0)
+#define DCFG_DEVSPD_FS				(1 << 0)
+#define DCFG_DEVSPD_LS				(2 << 0)
+#define DCFG_DEVSPD_FS48			(3 << 0)
+
+#define DCTL				HSOTG_REG(0x804)
+#define DCTL_PWRONPRGDONE		(1 << 11)
+#define DCTL_CGOUTNAK			(1 << 10)
+#define DCTL_SGOUTNAK			(1 << 9)
+#define DCTL_CGNPINNAK			(1 << 8)
+#define DCTL_SGNPINNAK			(1 << 7)
+#define DCTL_TSTCTL_MASK		(0x7 << 4)
+#define DCTL_TSTCTL_SHIFT		4
+#define DCTL_GOUTNAKSTS			(1 << 3)
+#define DCTL_GNPINNAKSTS		(1 << 2)
+#define DCTL_SFTDISCON			(1 << 1)
+#define DCTL_RMTWKUPSIG			(1 << 0)
+
+#define DSTS				HSOTG_REG(0x808)
+#define DSTS_SOFFN_MASK			(0x3fff << 8)
+#define DSTS_SOFFN_SHIFT		8
+#define DSTS_SOFFN_LIMIT		0x3fff
+#define DSTS_SOFFN(_x)			((_x) << 8)
+#define DSTS_ERRATICERR			(1 << 3)
+#define DSTS_ENUMSPD_MASK		(0x3 << 1)
+#define DSTS_ENUMSPD_SHIFT		1
+#define DSTS_ENUMSPD_HS				(0 << 1)
+#define DSTS_ENUMSPD_FS				(1 << 1)
+#define DSTS_ENUMSPD_LS				(2 << 1)
+#define DSTS_ENUMSPD_FS48			(3 << 1)
+#define DSTS_SUSPSTS			(1 << 0)
+
+#define DIEPMSK				HSOTG_REG(0x810)
+#define DIEPMSK_TXFIFOEMPTY		(1 << 7)
+#define DIEPMSK_INEPNAKEFFMSK		(1 << 6)
+#define DIEPMSK_INTKNEPMISMSK		(1 << 5)
+#define DIEPMSK_INTKNTXFEMPMSK		(1 << 4)
+#define DIEPMSK_TIMEOUTMSK		(1 << 3)
+#define DIEPMSK_AHBERRMSK		(1 << 2)
+#define DIEPMSK_EPDISBLDMSK		(1 << 1)
+#define DIEPMSK_XFERCOMPLMSK		(1 << 0)
+
+#define DOEPMSK				HSOTG_REG(0x814)
+#define DOEPMSK_BACK2BACKSETUP		(1 << 6)
+#define DOEPMSK_OUTTKNEPDISMSK		(1 << 4)
+#define DOEPMSK_SETUPMSK		(1 << 3)
+#define DOEPMSK_AHBERRMSK		(1 << 2)
+#define DOEPMSK_EPDISBLDMSK		(1 << 1)
+#define DOEPMSK_XFERCOMPLMSK		(1 << 0)
+
+#define DAINT				HSOTG_REG(0x818)
+#define DAINTMSK			HSOTG_REG(0x81C)
+#define DAINT_OUTEP_SHIFT		16
+#define DAINT_OUTEP(_x)			(1 << ((_x) + 16))
+#define DAINT_INEP(_x)			(1 << (_x))
+
+#define DTKNQR1				HSOTG_REG(0x820)
+#define DTKNQR2				HSOTG_REG(0x824)
+#define DTKNQR3				HSOTG_REG(0x830)
+#define DTKNQR4				HSOTG_REG(0x834)
+
+#define DVBUSDIS			HSOTG_REG(0x828)
+#define DVBUSPULSE			HSOTG_REG(0x82C)
+
+#define DIEPCTL0			HSOTG_REG(0x900)
+#define DIEPCTL(_a)			HSOTG_REG(0x900 + ((_a) * 0x20))
+
+#define DOEPCTL0			HSOTG_REG(0xB00)
+#define DOEPCTL(_a)			HSOTG_REG(0xB00 + ((_a) * 0x20))
+
+/* EP0 specialness:
+ * bits[29..28] - reserved (no SetD0PID, SetD1PID)
+ * bits[25..22] - should always be zero, this isn't a periodic endpoint
+ * bits[10..0]  - MPS setting different for EP0
+ */
+#define D0EPCTL_MPS_MASK		(0x3 << 0)
+#define D0EPCTL_MPS_SHIFT		0
+#define D0EPCTL_MPS_64				(0 << 0)
+#define D0EPCTL_MPS_32				(1 << 0)
+#define D0EPCTL_MPS_16				(2 << 0)
+#define D0EPCTL_MPS_8				(3 << 0)
+
+#define DXEPCTL_EPENA			(1 << 31)
+#define DXEPCTL_EPDIS			(1 << 30)
+#define DXEPCTL_SETD1PID		(1 << 29)
+#define DXEPCTL_SETODDFR		(1 << 29)
+#define DXEPCTL_SETD0PID		(1 << 28)
+#define DXEPCTL_SETEVENFR		(1 << 28)
+#define DXEPCTL_SNAK			(1 << 27)
+#define DXEPCTL_CNAK			(1 << 26)
+#define DXEPCTL_TXFNUM_MASK		(0xf << 22)
+#define DXEPCTL_TXFNUM_SHIFT		22
+#define DXEPCTL_TXFNUM_LIMIT		0xf
+#define DXEPCTL_TXFNUM(_x)		((_x) << 22)
+#define DXEPCTL_STALL			(1 << 21)
+#define DXEPCTL_SNP			(1 << 20)
+#define DXEPCTL_EPTYPE_MASK		(0x3 << 18)
+#define DXEPCTL_EPTYPE_SHIFT		18
+#define DXEPCTL_EPTYPE_CONTROL			(0 << 18)
+#define DXEPCTL_EPTYPE_ISO			(1 << 18)
+#define DXEPCTL_EPTYPE_BULK			(2 << 18)
+#define DXEPCTL_EPTYPE_INTTERUPT		(3 << 18)
+#define DXEPCTL_NAKSTS			(1 << 17)
+#define DXEPCTL_DPID			(1 << 16)
+#define DXEPCTL_EOFRNUM			(1 << 16)
+#define DXEPCTL_USBACTEP		(1 << 15)
+#define DXEPCTL_NEXTEP_MASK		(0xf << 11)
+#define DXEPCTL_NEXTEP_SHIFT		11
+#define DXEPCTL_NEXTEP_LIMIT		0xf
+#define DXEPCTL_NEXTEP(_x)		((_x) << 11)
+#define DXEPCTL_MPS_MASK		(0x7ff << 0)
+#define DXEPCTL_MPS_SHIFT		0
+#define DXEPCTL_MPS_LIMIT		0x7ff
+#define DXEPCTL_MPS(_x)			((_x) << 0)
+
+#define DIEPINT(_a)			HSOTG_REG(0x908 + ((_a) * 0x20))
+#define DOEPINT(_a)			HSOTG_REG(0xB08 + ((_a) * 0x20))
+#define DXEPINT_INEPNAKEFF		(1 << 6)
+#define DXEPINT_BACK2BACKSETUP		(1 << 6)
+#define DXEPINT_INTKNEPMIS		(1 << 5)
+#define DXEPINT_INTKNTXFEMP		(1 << 4)
+#define DXEPINT_OUTTKNEPDIS		(1 << 4)
+#define DXEPINT_TIMEOUT			(1 << 3)
+#define DXEPINT_SETUP			(1 << 3)
+#define DXEPINT_AHBERR			(1 << 2)
+#define DXEPINT_EPDISBLD		(1 << 1)
+#define DXEPINT_XFERCOMPL		(1 << 0)
+
+#define DIEPTSIZ0			HSOTG_REG(0x910)
+#define DIEPTSIZ0_PKTCNT_MASK		(0x3 << 19)
+#define DIEPTSIZ0_PKTCNT_SHIFT		19
+#define DIEPTSIZ0_PKTCNT_LIMIT		0x3
+#define DIEPTSIZ0_PKTCNT(_x)		((_x) << 19)
+#define DIEPTSIZ0_XFERSIZE_MASK		(0x7f << 0)
+#define DIEPTSIZ0_XFERSIZE_SHIFT	0
+#define DIEPTSIZ0_XFERSIZE_LIMIT	0x7f
+#define DIEPTSIZ0_XFERSIZE(_x)		((_x) << 0)
+
+#define DOEPTSIZ0			HSOTG_REG(0xB10)
+#define DOEPTSIZ0_SUPCNT_MASK		(0x3 << 29)
+#define DOEPTSIZ0_SUPCNT_SHIFT		29
+#define DOEPTSIZ0_SUPCNT_LIMIT		0x3
+#define DOEPTSIZ0_SUPCNT(_x)		((_x) << 29)
+#define DOEPTSIZ0_PKTCNT		(1 << 19)
+#define DOEPTSIZ0_XFERSIZE_MASK		(0x7f << 0)
+#define DOEPTSIZ0_XFERSIZE_SHIFT	0
+
+#define DIEPTSIZ(_a)			HSOTG_REG(0x910 + ((_a) * 0x20))
+#define DOEPTSIZ(_a)			HSOTG_REG(0xB10 + ((_a) * 0x20))
+#define DXEPTSIZ_MC_MASK		(0x3 << 29)
+#define DXEPTSIZ_MC_SHIFT		29
+#define DXEPTSIZ_MC_LIMIT		0x3
+#define DXEPTSIZ_MC(_x)			((_x) << 29)
+#define DXEPTSIZ_PKTCNT_MASK		(0x3ff << 19)
+#define DXEPTSIZ_PKTCNT_SHIFT		19
+#define DXEPTSIZ_PKTCNT_LIMIT		0x3ff
+#define DXEPTSIZ_PKTCNT_GET(_v)		(((_v) >> 19) & 0x3ff)
+#define DXEPTSIZ_PKTCNT(_x)		((_x) << 19)
+#define DXEPTSIZ_XFERSIZE_MASK		(0x7ffff << 0)
+#define DXEPTSIZ_XFERSIZE_SHIFT		0
+#define DXEPTSIZ_XFERSIZE_LIMIT		0x7ffff
+#define DXEPTSIZ_XFERSIZE_GET(_v)	(((_v) >> 0) & 0x7ffff)
+#define DXEPTSIZ_XFERSIZE(_x)		((_x) << 0)
+
+#define DIEPDMA(_a)			HSOTG_REG(0x914 + ((_a) * 0x20))
+#define DOEPDMA(_a)			HSOTG_REG(0xB14 + ((_a) * 0x20))
+
+#define DTXFSTS(_a)			HSOTG_REG(0x918 + ((_a) * 0x20))
+
+#define PCGCTL				HSOTG_REG(0x0e00)
+#define PCGCTL_IF_DEV_MODE		(1 << 31)
+#define PCGCTL_P2HD_PRT_SPD_MASK	(0x3 << 29)
+#define PCGCTL_P2HD_PRT_SPD_SHIFT	29
+#define PCGCTL_P2HD_DEV_ENUM_SPD_MASK	(0x3 << 27)
+#define PCGCTL_P2HD_DEV_ENUM_SPD_SHIFT	27
+#define PCGCTL_MAC_DEV_ADDR_MASK	(0x7f << 20)
+#define PCGCTL_MAC_DEV_ADDR_SHIFT	20
+#define PCGCTL_MAX_TERMSEL		(1 << 19)
+#define PCGCTL_MAX_XCVRSELECT_MASK	(0x3 << 17)
+#define PCGCTL_MAX_XCVRSELECT_SHIFT	17
+#define PCGCTL_PORT_POWER		(1 << 16)
+#define PCGCTL_PRT_CLK_SEL_MASK		(0x3 << 14)
+#define PCGCTL_PRT_CLK_SEL_SHIFT	14
+#define PCGCTL_ESS_REG_RESTORED		(1 << 13)
+#define PCGCTL_EXTND_HIBER_SWITCH	(1 << 12)
+#define PCGCTL_EXTND_HIBER_PWRCLMP	(1 << 11)
+#define PCGCTL_ENBL_EXTND_HIBER		(1 << 10)
+#define PCGCTL_RESTOREMODE		(1 << 9)
+#define PCGCTL_RESETAFTSUSP		(1 << 8)
+#define PCGCTL_DEEP_SLEEP		(1 << 7)
+#define PCGCTL_PHY_IN_SLEEP		(1 << 6)
+#define PCGCTL_ENBL_SLEEP_GATING	(1 << 5)
+#define PCGCTL_RSTPDWNMODULE		(1 << 3)
+#define PCGCTL_PWRCLMP			(1 << 2)
+#define PCGCTL_GATEHCLK			(1 << 1)
+#define PCGCTL_STOPPCLK			(1 << 0)
+
+#define EPFIFO(_a)			HSOTG_REG(0x1000 + ((_a) * 0x1000))
+
+/* Host Mode Registers */
+
+#define HCFG				HSOTG_REG(0x0400)
+#define HCFG_MODECHTIMEN		(1 << 31)
+#define HCFG_PERSCHEDENA		(1 << 26)
+#define HCFG_FRLISTEN_MASK		(0x3 << 24)
+#define HCFG_FRLISTEN_SHIFT		24
+#define HCFG_FRLISTEN_8				(0 << 24)
+#define FRLISTEN_8_SIZE				8
+#define HCFG_FRLISTEN_16			(1 << 24)
+#define FRLISTEN_16_SIZE			16
+#define HCFG_FRLISTEN_32			(2 << 24)
+#define FRLISTEN_32_SIZE			32
+#define HCFG_FRLISTEN_64			(3 << 24)
+#define FRLISTEN_64_SIZE			64
+#define HCFG_DESCDMA			(1 << 23)
+#define HCFG_RESVALID_MASK		(0xff << 8)
+#define HCFG_RESVALID_SHIFT		8
+#define HCFG_ENA32KHZ			(1 << 7)
+#define HCFG_FSLSSUPP			(1 << 2)
+#define HCFG_FSLSPCLKSEL_MASK		(0x3 << 0)
+#define HCFG_FSLSPCLKSEL_SHIFT		0
+#define HCFG_FSLSPCLKSEL_30_60_MHZ		(0 << 0)
+#define HCFG_FSLSPCLKSEL_48_MHZ			(1 << 0)
+#define HCFG_FSLSPCLKSEL_6_MHZ			(2 << 0)
+
+#define HFIR				HSOTG_REG(0x0404)
+#define HFIR_FRINT_MASK			(0xffff << 0)
+#define HFIR_FRINT_SHIFT		0
+#define HFIR_RLDCTRL			(1 << 16)
+
+#define HFNUM				HSOTG_REG(0x0408)
+#define HFNUM_FRREM_MASK		(0xffff << 16)
+#define HFNUM_FRREM_SHIFT		16
+#define HFNUM_FRNUM_MASK		(0xffff << 0)
+#define HFNUM_FRNUM_SHIFT		0
+#define HFNUM_MAX_FRNUM			0x3fff
+
+#define HPTXSTS				HSOTG_REG(0x0410)
+#define TXSTS_QTOP_ODD			(1 << 31)
+#define TXSTS_QTOP_CHNEP_MASK		(0xf << 27)
+#define TXSTS_QTOP_CHNEP_SHIFT		27
+#define TXSTS_QTOP_TOKEN_MASK		(0x3 << 25)
+#define TXSTS_QTOP_TOKEN_SHIFT		25
+#define TXSTS_QTOP_TERMINATE		(1 << 24)
+#define TXSTS_QSPCAVAIL_MASK		(0xff << 16)
+#define TXSTS_QSPCAVAIL_SHIFT		16
+#define TXSTS_FSPCAVAIL_MASK		(0xffff << 0)
+#define TXSTS_FSPCAVAIL_SHIFT		0
+
+#define HAINT				HSOTG_REG(0x0414)
+#define HAINTMSK			HSOTG_REG(0x0418)
+#define HFLBADDR			HSOTG_REG(0x041c)
+
+#define HPRT0				HSOTG_REG(0x0440)
+#define HPRT0_SPD_MASK			(0x3 << 17)
+#define HPRT0_SPD_SHIFT			17
+#define HPRT0_SPD_HIGH_SPEED		(0 << 17)
+#define HPRT0_SPD_FULL_SPEED		(1 << 17)
+#define HPRT0_SPD_LOW_SPEED		(2 << 17)
+#define HPRT0_TSTCTL_MASK		(0xf << 13)
+#define HPRT0_TSTCTL_SHIFT		13
+#define HPRT0_PWR			(1 << 12)
+#define HPRT0_LNSTS_MASK		(0x3 << 10)
+#define HPRT0_LNSTS_SHIFT		10
+#define HPRT0_RST			(1 << 8)
+#define HPRT0_SUSP			(1 << 7)
+#define HPRT0_RES			(1 << 6)
+#define HPRT0_OVRCURRCHG		(1 << 5)
+#define HPRT0_OVRCURRACT		(1 << 4)
+#define HPRT0_ENACHG			(1 << 3)
+#define HPRT0_ENA			(1 << 2)
+#define HPRT0_CONNDET			(1 << 1)
+#define HPRT0_CONNSTS			(1 << 0)
+
+#define HCCHAR(_ch)			HSOTG_REG(0x0500 + 0x20 * (_ch))
+#define HCCHAR_CHENA			(1 << 31)
+#define HCCHAR_CHDIS			(1 << 30)
+#define HCCHAR_ODDFRM			(1 << 29)
+#define HCCHAR_DEVADDR_MASK		(0x7f << 22)
+#define HCCHAR_DEVADDR_SHIFT		22
+#define HCCHAR_MULTICNT_MASK		(0x3 << 20)
+#define HCCHAR_MULTICNT_SHIFT		20
+#define HCCHAR_EPTYPE_MASK		(0x3 << 18)
+#define HCCHAR_EPTYPE_SHIFT		18
+#define HCCHAR_LSPDDEV			(1 << 17)
+#define HCCHAR_EPDIR			(1 << 15)
+#define HCCHAR_EPNUM_MASK		(0xf << 11)
+#define HCCHAR_EPNUM_SHIFT		11
+#define HCCHAR_MPS_MASK			(0x7ff << 0)
+#define HCCHAR_MPS_SHIFT		0
+
+#define HCSPLT(_ch)			HSOTG_REG(0x0504 + 0x20 * (_ch))
+#define HCSPLT_SPLTENA			(1 << 31)
+#define HCSPLT_COMPSPLT			(1 << 16)
+#define HCSPLT_XACTPOS_MASK		(0x3 << 14)
+#define HCSPLT_XACTPOS_SHIFT		14
+#define HCSPLT_XACTPOS_MID		(0 << 14)
+#define HCSPLT_XACTPOS_END		(1 << 14)
+#define HCSPLT_XACTPOS_BEGIN		(2 << 14)
+#define HCSPLT_XACTPOS_ALL		(3 << 14)
+#define HCSPLT_HUBADDR_MASK		(0x7f << 7)
+#define HCSPLT_HUBADDR_SHIFT		7
+#define HCSPLT_PRTADDR_MASK		(0x7f << 0)
+#define HCSPLT_PRTADDR_SHIFT		0
+
+#define HCINT(_ch)			HSOTG_REG(0x0508 + 0x20 * (_ch))
+#define HCINTMSK(_ch)			HSOTG_REG(0x050c + 0x20 * (_ch))
+#define HCINTMSK_RESERVED14_31		(0x3ffff << 14)
+#define HCINTMSK_FRM_LIST_ROLL		(1 << 13)
+#define HCINTMSK_XCS_XACT		(1 << 12)
+#define HCINTMSK_BNA			(1 << 11)
+#define HCINTMSK_DATATGLERR		(1 << 10)
+#define HCINTMSK_FRMOVRUN		(1 << 9)
+#define HCINTMSK_BBLERR			(1 << 8)
+#define HCINTMSK_XACTERR		(1 << 7)
+#define HCINTMSK_NYET			(1 << 6)
+#define HCINTMSK_ACK			(1 << 5)
+#define HCINTMSK_NAK			(1 << 4)
+#define HCINTMSK_STALL			(1 << 3)
+#define HCINTMSK_AHBERR			(1 << 2)
+#define HCINTMSK_CHHLTD			(1 << 1)
+#define HCINTMSK_XFERCOMPL		(1 << 0)
+
+#define HCTSIZ(_ch)			HSOTG_REG(0x0510 + 0x20 * (_ch))
+#define TSIZ_DOPNG			(1 << 31)
+#define TSIZ_SC_MC_PID_MASK		(0x3 << 29)
+#define TSIZ_SC_MC_PID_SHIFT		29
+#define TSIZ_SC_MC_PID_DATA0		(0 << 29)
+#define TSIZ_SC_MC_PID_DATA2		(1 << 29)
+#define TSIZ_SC_MC_PID_DATA1		(2 << 29)
+#define TSIZ_SC_MC_PID_MDATA		(3 << 29)
+#define TSIZ_SC_MC_PID_SETUP		(3 << 29)
+#define TSIZ_PKTCNT_MASK		(0x3ff << 19)
+#define TSIZ_PKTCNT_SHIFT		19
+#define TSIZ_NTD_MASK			(0xff << 8)
+#define TSIZ_NTD_SHIFT			8
+#define TSIZ_SCHINFO_MASK		(0xff << 0)
+#define TSIZ_SCHINFO_SHIFT		0
+#define TSIZ_XFERSIZE_MASK		(0x7ffff << 0)
+#define TSIZ_XFERSIZE_SHIFT		0
+
+#define HCDMA(_ch)			HSOTG_REG(0x0514 + 0x20 * (_ch))
+#define HCDMA_DMA_ADDR_MASK		(0x1fffff << 11)
+#define HCDMA_DMA_ADDR_SHIFT		11
+#define HCDMA_CTD_MASK			(0xff << 3)
+#define HCDMA_CTD_SHIFT			3
+
+#define HCDMAB(_ch)			HSOTG_REG(0x051c + 0x20 * (_ch))
+
+#define HCFIFO(_ch)			HSOTG_REG(0x1000 + 0x1000 * (_ch))
+
+/**
+ * struct dwc2_hcd_dma_desc - Host-mode DMA descriptor structure
+ *
+ * @status: DMA descriptor status quadlet
+ * @buf:    DMA descriptor data buffer pointer
+ *
+ * DMA Descriptor structure contains two quadlets:
+ * Status quadlet and Data buffer pointer.
+ */
+struct dwc2_hcd_dma_desc {
+	u32 status;
+	u32 buf;
+};
+
+#define HOST_DMA_A			(1 << 31)
+#define HOST_DMA_STS_MASK		(0x3 << 28)
+#define HOST_DMA_STS_SHIFT		28
+#define HOST_DMA_STS_PKTERR		(1 << 28)
+#define HOST_DMA_EOL			(1 << 26)
+#define HOST_DMA_IOC			(1 << 25)
+#define HOST_DMA_SUP			(1 << 24)
+#define HOST_DMA_ALT_QTD		(1 << 23)
+#define HOST_DMA_QTD_OFFSET_MASK	(0x3f << 17)
+#define HOST_DMA_QTD_OFFSET_SHIFT	17
+#define HOST_DMA_ISOC_NBYTES_MASK	(0xfff << 0)
+#define HOST_DMA_ISOC_NBYTES_SHIFT	0
+#define HOST_DMA_NBYTES_MASK		(0x1ffff << 0)
+#define HOST_DMA_NBYTES_SHIFT		0
+
+#define MAX_DMA_DESC_SIZE		131071
+#define MAX_DMA_DESC_NUM_GENERIC	64
+#define MAX_DMA_DESC_NUM_HS_ISOC	256
+
+#endif /* __DWC2_HW_H__ */
diff --git a/drivers/staging/dwc2/pci.c b/drivers/staging/dwc2/pci.c
new file mode 100644
index 0000000..0825eef
--- /dev/null
+++ b/drivers/staging/dwc2/pci.c
@@ -0,0 +1,187 @@
+/*
+ * pci.c - DesignWare HS OTG Controller PCI driver
+ *
+ * Copyright (C) 2004-2013 Synopsys, Inc.
+ *
+ * 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, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 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 names of the above-listed copyright holders may not 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 the License, or (at your option) any
+ * later version.
+ *
+ * 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.
+ */
+
+/*
+ * Provides the initialization and cleanup entry points for the DWC_otg PCI
+ * driver
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/usb.h>
+
+#include <linux/usb/hcd.h>
+#include <linux/usb/ch11.h>
+
+#include "core.h"
+#include "hcd.h"
+
+#define PCI_VENDOR_ID_SYNOPSYS		0x16c3
+#define PCI_PRODUCT_ID_HAPS_HSOTG	0xabc0
+
+static const char dwc2_driver_name[] = "dwc_otg";
+
+static struct dwc2_core_params dwc2_module_params = {
+	.otg_cap			= -1,
+	.otg_ver			= -1,
+	.dma_enable			= -1,
+	.dma_desc_enable		= 0,
+	.speed				= -1,
+	.enable_dynamic_fifo		= -1,
+	.en_multiple_tx_fifo		= -1,
+	.host_rx_fifo_size		= 1024,
+	.host_nperio_tx_fifo_size	= 256,
+	.host_perio_tx_fifo_size	= 1024,
+	.max_transfer_size		= 65535,
+	.max_packet_count		= 511,
+	.host_channels			= -1,
+	.phy_type			= -1,
+	.phy_utmi_width			= 16,	/* 16 bits - NOT DETECTABLE */
+	.phy_ulpi_ddr			= -1,
+	.phy_ulpi_ext_vbus		= -1,
+	.i2c_enable			= -1,
+	.ulpi_fs_ls			= -1,
+	.host_support_fs_ls_low_power	= -1,
+	.host_ls_low_power_phy_clk	= -1,
+	.ts_dline			= -1,
+	.reload_ctl			= -1,
+	.ahb_single			= -1,
+};
+
+/**
+ * dwc2_driver_remove() - Called when the DWC_otg core is unregistered with the
+ * DWC_otg driver
+ *
+ * @dev: Bus device
+ *
+ * This routine is called, for example, when the rmmod command is executed. The
+ * device may or may not be electrically present. If it is present, the driver
+ * stops device processing. Any resources used on behalf of this device are
+ * freed.
+ */
+static void dwc2_driver_remove(struct pci_dev *dev)
+{
+	struct dwc2_hsotg *hsotg = pci_get_drvdata(dev);
+
+	dev_dbg(&dev->dev, "%s(%p)\n", __func__, dev);
+
+	dwc2_hcd_remove(hsotg);
+	pci_disable_device(dev);
+}
+
+/**
+ * dwc2_driver_probe() - Called when the DWC_otg core is bound to the DWC_otg
+ * driver
+ *
+ * @dev: Bus device
+ *
+ * This routine creates the driver components required to control the device
+ * (core, HCD, and PCD) and initializes the device. The driver components are
+ * stored in a dwc2_hsotg structure. A reference to the dwc2_hsotg is saved
+ * in the device private data. This allows the driver to access the dwc2_hsotg
+ * structure on subsequent calls to driver methods for this device.
+ */
+static int dwc2_driver_probe(struct pci_dev *dev,
+			     const struct pci_device_id *id)
+{
+	struct dwc2_hsotg *hsotg;
+	int retval;
+
+	dev_dbg(&dev->dev, "%s(%p)\n", __func__, dev);
+
+	hsotg = devm_kzalloc(&dev->dev, sizeof(*hsotg), GFP_KERNEL);
+	if (!hsotg)
+		return -ENOMEM;
+
+	pci_set_power_state(dev, PCI_D0);
+
+	hsotg->dev = &dev->dev;
+	hsotg->regs = devm_request_and_ioremap(&dev->dev, &dev->resource[0]);
+	if (!hsotg->regs)
+		return -ENOMEM;
+
+	dev_dbg(&dev->dev, "mapped PA %08lx to VA %p\n",
+		(unsigned long)pci_resource_start(dev, 0), hsotg->regs);
+
+	if (pci_enable_device(dev) < 0)
+		return -ENODEV;
+
+	pci_set_master(dev);
+
+	retval = dwc2_hcd_init(hsotg, dev->irq, &dwc2_module_params);
+	if (retval) {
+		pci_disable_device(dev);
+		return retval;
+	}
+
+	pci_set_drvdata(dev, hsotg);
+	dev_dbg(&dev->dev, "hsotg=%p\n", hsotg);
+
+	dev_dbg(&dev->dev, "registering common handler for irq%d\n", dev->irq);
+	retval = devm_request_irq(&dev->dev, dev->irq, dwc2_handle_common_intr,
+				  IRQF_SHARED | IRQ_LEVEL, dev_name(&dev->dev),
+				  hsotg);
+	if (retval)
+		dwc2_hcd_remove(hsotg);
+
+	return retval;
+}
+
+static DEFINE_PCI_DEVICE_TABLE(dwc2_pci_ids) = {
+	{
+		PCI_DEVICE(PCI_VENDOR_ID_SYNOPSYS, PCI_PRODUCT_ID_HAPS_HSOTG),
+	},
+	{ /* end: all zeroes */ }
+};
+MODULE_DEVICE_TABLE(pci, dwc2_pci_ids);
+
+static struct pci_driver dwc2_pci_driver = {
+	.name = dwc2_driver_name,
+	.id_table = dwc2_pci_ids,
+	.probe = dwc2_driver_probe,
+	.remove = dwc2_driver_remove,
+};
+
+module_pci_driver(dwc2_pci_driver);
+
+MODULE_DESCRIPTION("DESIGNWARE HS OTG PCI Bus Glue");
+MODULE_AUTHOR("Synopsys, Inc.");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/staging/et131x/et131x.c b/drivers/staging/et131x/et131x.c
index 42ae5e8..c7e9e1d 100644
--- a/drivers/staging/et131x/et131x.c
+++ b/drivers/staging/et131x/et131x.c
@@ -595,7 +595,7 @@ static int eeprom_write(struct et131x_adapter *adapter, u32 addr, u8 data)
 	 */
 
 	err = eeprom_wait_ready(pdev, NULL);
-	if (err)
+	if (err < 0)
 		return err;
 
 	 /* 2. Write to the LBCIF Control Register:  bit 7=1, bit 6=1, bit 3=0,
@@ -709,7 +709,7 @@ static int eeprom_read(struct et131x_adapter *adapter, u32 addr, u8 *pdata)
 	 */
 
 	err = eeprom_wait_ready(pdev, NULL);
-	if (err)
+	if (err < 0)
 		return err;
 	/* Write to the LBCIF Control Register:  bit 7=1, bit 6=0, bit 3=0,
 	 * and bits 1:0 both =0.  Bit 5 should be set according to the type
diff --git a/drivers/staging/fwserial/fwserial.c b/drivers/staging/fwserial/fwserial.c
index 5a6fb44..5c64e3a 100644
--- a/drivers/staging/fwserial/fwserial.c
+++ b/drivers/staging/fwserial/fwserial.c
@@ -744,7 +744,6 @@ static void fwtty_tx_complete(struct fw_card *card, int rcode,
 			      struct fwtty_transaction *txn)
 {
 	struct fwtty_port *port = txn->port;
-	struct tty_struct *tty;
 	int len;
 
 	fwtty_dbg(port, "rcode: %d", rcode);
@@ -769,13 +768,8 @@ static void fwtty_tx_complete(struct fw_card *card, int rcode,
 		port->stats.dropped += txn->dma_pended.len;
 	}
 
-	if (len < WAKEUP_CHARS) {
-		tty = tty_port_tty_get(&port->port);
-		if (tty) {
-			tty_wakeup(tty);
-			tty_kref_put(tty);
-		}
-	}
+	if (len < WAKEUP_CHARS)
+		tty_port_tty_wakeup(&port->port);
 }
 
 static int fwtty_tx(struct fwtty_port *port, bool drain)
diff --git a/drivers/staging/gdm72xx/gdm_qos.c b/drivers/staging/gdm72xx/gdm_qos.c
index 1e63031..b795353 100644
--- a/drivers/staging/gdm72xx/gdm_qos.c
+++ b/drivers/staging/gdm72xx/gdm_qos.c
@@ -337,7 +337,6 @@ void gdm_recv_qos_hci_packet(void *nic_ptr, u8 *buf, int size)
 	struct nic *nic = nic_ptr;
 	u32 i, SFID, index, pos;
 	u8 subCmdEvt;
-	u8 len;
 	struct qos_cb_s *qcb = &nic->qos;
 	struct qos_entry_s *entry, *n;
 	struct list_head send_list;
@@ -347,8 +346,6 @@ void gdm_recv_qos_hci_packet(void *nic_ptr, u8 *buf, int size)
 	subCmdEvt = (u8)buf[4];
 
 	if (subCmdEvt == QOS_REPORT) {
-		len = (u8)buf[5];
-
 		spin_lock_irqsave(&qcb->qos_lock, flags);
 		for (i = 0; i < qcb->qos_list_cnt; i++) {
 			SFID = ((buf[(i*5)+6]<<24)&0xff000000);
@@ -368,21 +365,24 @@ void gdm_recv_qos_hci_packet(void *nic_ptr, u8 *buf, int size)
 		spin_unlock_irqrestore(&qcb->qos_lock, flags);
 		send_qos_list(nic, &send_list);
 		return;
-	} else if (subCmdEvt == QOS_ADD) {
-		pos = 5;
-		len = (u8)buf[pos++];
-
-		SFID = ((buf[pos++]<<24)&0xff000000);
-		SFID += ((buf[pos++]<<16)&0xff0000);
-		SFID += ((buf[pos++]<<8)&0xff00);
-		SFID += (buf[pos++]);
-
-		index = get_csr(qcb, SFID, 1);
-		if (index == -1) {
-			netdev_err(nic->netdev, "QoS ERROR: csr Update Error\n");
-			return;
-		}
+	}
+
+	/* subCmdEvt == QOS_ADD || subCmdEvt == QOS_CHANG_DEL */
+	pos = 6;
+	SFID = ((buf[pos++]<<24)&0xff000000);
+	SFID += ((buf[pos++]<<16)&0xff0000);
+	SFID += ((buf[pos++]<<8)&0xff00);
+	SFID += (buf[pos++]);
+
+	index = get_csr(qcb, SFID, 1);
+	if (index == -1) {
+		netdev_err(nic->netdev,
+			   "QoS ERROR: csr Update Error / Wrong index (%d) \n",
+			   index);
+		return;
+	}
 
+	if (subCmdEvt == QOS_ADD) {
 		netdev_dbg(nic->netdev, "QOS_ADD SFID = 0x%x, index=%d\n",
 			   SFID, index);
 
@@ -424,19 +424,6 @@ void gdm_recv_qos_hci_packet(void *nic_ptr, u8 *buf, int size)
 		qcb->qos_limit_size = 254/qcb->qos_list_cnt;
 		spin_unlock_irqrestore(&qcb->qos_lock, flags);
 	} else if (subCmdEvt == QOS_CHANGE_DEL) {
-		pos = 5;
-		len = (u8)buf[pos++];
-		SFID = ((buf[pos++]<<24)&0xff000000);
-		SFID += ((buf[pos++]<<16)&0xff0000);
-		SFID += ((buf[pos++]<<8)&0xff00);
-		SFID += (buf[pos++]);
-		index = get_csr(qcb, SFID, 1);
-		if (index == -1) {
-			netdev_err(nic->netdev, "QoS ERROR: Wrong index(%d)\n",
-				   index);
-			return;
-		}
-
 		netdev_dbg(nic->netdev, "QOS_CHANGE_DEL SFID = 0x%x, index=%d\n",
 			   SFID, index);
 
diff --git a/drivers/staging/gdm72xx/netlink_k.c b/drivers/staging/gdm72xx/netlink_k.c
index 52c25ba..af7f1c1 100644
--- a/drivers/staging/gdm72xx/netlink_k.c
+++ b/drivers/staging/gdm72xx/netlink_k.c
@@ -15,9 +15,10 @@
 
 #include <linux/module.h>
 #include <linux/etherdevice.h>
-#include <linux/netlink.h>
+#include <net/netlink.h>
 #include <asm/byteorder.h>
 #include <net/sock.h>
+#include "netlink_k.h"
 
 #if !defined(NLMSG_HDRLEN)
 #define NLMSG_HDRLEN	 ((int) NLMSG_ALIGN(sizeof(struct nlmsghdr)))
@@ -25,12 +26,12 @@
 
 #define ND_MAX_GROUP			30
 #define ND_IFINDEX_LEN			sizeof(int)
-#define ND_NLMSG_SPACE(len)		(NLMSG_SPACE(len) + ND_IFINDEX_LEN)
+#define ND_NLMSG_SPACE(len)		(nlmsg_total_size(len) + ND_IFINDEX_LEN)
 #define ND_NLMSG_DATA(nlh) \
-	((void *)((char *)NLMSG_DATA(nlh) + ND_IFINDEX_LEN))
+	((void *)((char *)nlmsg_data(nlh) + ND_IFINDEX_LEN))
 #define ND_NLMSG_S_LEN(len)		(len+ND_IFINDEX_LEN)
 #define ND_NLMSG_R_LEN(nlh)		(nlh->nlmsg_len-ND_IFINDEX_LEN)
-#define ND_NLMSG_IFIDX(nlh)		NLMSG_DATA(nlh)
+#define ND_NLMSG_IFIDX(nlh)		nlmsg_data(nlh)
 #define ND_MAX_MSG_LEN			8096
 
 #if defined(DEFINE_MUTEX)
@@ -51,7 +52,7 @@ static void netlink_rcv_cb(struct sk_buff *skb)
 	void *msg;
 	int ifindex;
 
-	if (skb->len >= NLMSG_SPACE(0)) {
+	if (skb->len >= NLMSG_HDRLEN) {
 		nlh = (struct nlmsghdr *)skb->data;
 
 		if (skb->len < nlh->nlmsg_len ||
@@ -124,7 +125,7 @@ int netlink_send(struct sock *sock, int group, u16 type, void *msg, int len)
 		return -EINVAL;
 	}
 
-	skb = alloc_skb(NLMSG_SPACE(len), GFP_ATOMIC);
+	skb = nlmsg_new(len, GFP_ATOMIC);
 	if (!skb) {
 		pr_err("netlink_broadcast ret=%d\n", ret);
 		return -ENOMEM;
diff --git a/drivers/staging/gdm72xx/sdio_boot.c b/drivers/staging/gdm72xx/sdio_boot.c
index 93046dd..4302fcb 100644
--- a/drivers/staging/gdm72xx/sdio_boot.c
+++ b/drivers/staging/gdm72xx/sdio_boot.c
@@ -27,6 +27,7 @@
 #include <linux/firmware.h>
 
 #include "gdm_sdio.h"
+#include "sdio_boot.h"
 
 #define TYPE_A_HEADER_SIZE	4
 #define TYPE_A_LOOKAHEAD_SIZE   16
diff --git a/drivers/staging/iio/Documentation/trigger.txt b/drivers/staging/iio/Documentation/trigger.txt
index 75cc37f..64e2e08 100644
--- a/drivers/staging/iio/Documentation/trigger.txt
+++ b/drivers/staging/iio/Documentation/trigger.txt
@@ -10,9 +10,6 @@ struct iio_trig *trig = iio_trigger_alloc("<trigger format string>", ...);
 allocates a trigger structure.  The key elements to then fill in within
 a driver are:
 
-trig->private_data
-	Device specific private data.
-
 trig->owner
 	Typically set to THIS_MODULE. Used to ensure correct
 	ownership of core allocated resources.
diff --git a/drivers/staging/iio/Kconfig b/drivers/staging/iio/Kconfig
index dc26717..db4d6dc 100644
--- a/drivers/staging/iio/Kconfig
+++ b/drivers/staging/iio/Kconfig
@@ -4,14 +4,6 @@
 menu "IIO staging drivers"
 	depends on IIO
 
-config IIO_ST_HWMON
-	tristate "Hwmon driver that uses channels specified via iio maps"
-	depends on HWMON
-	help
-	  This is a platform driver that in combination with a suitable
-	  map allows IIO devices to provide  basic hwmon functionality
-	  for those channels specified in the map.
-
 source "drivers/staging/iio/accel/Kconfig"
 source "drivers/staging/iio/adc/Kconfig"
 source "drivers/staging/iio/addac/Kconfig"
diff --git a/drivers/staging/iio/Makefile b/drivers/staging/iio/Makefile
index 158e0a0..d871061 100644
--- a/drivers/staging/iio/Makefile
+++ b/drivers/staging/iio/Makefile
@@ -9,8 +9,6 @@ iio_dummy-$(CONFIG_IIO_SIMPLE_DUMMY_BUFFER) += iio_simple_dummy_buffer.o
 
 obj-$(CONFIG_IIO_DUMMY_EVGEN) += iio_dummy_evgen.o
 
-obj-$(CONFIG_IIO_ST_HWMON) += iio_hwmon.o
-
 obj-y += accel/
 obj-y += adc/
 obj-y += addac/
diff --git a/drivers/staging/iio/accel/adis16201_core.c b/drivers/staging/iio/accel/adis16201_core.c
index 9e5791f..ab8ec7a 100644
--- a/drivers/staging/iio/accel/adis16201_core.c
+++ b/drivers/staging/iio/accel/adis16201_core.c
@@ -134,14 +134,14 @@ static const struct iio_chan_spec adis16201_channels[] = {
 	ADIS_SUPPLY_CHAN(ADIS16201_SUPPLY_OUT, ADIS16201_SCAN_SUPPLY, 12),
 	ADIS_TEMP_CHAN(ADIS16201_TEMP_OUT, ADIS16201_SCAN_TEMP, 12),
 	ADIS_ACCEL_CHAN(X, ADIS16201_XACCL_OUT, ADIS16201_SCAN_ACC_X,
-		IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, 14),
+		BIT(IIO_CHAN_INFO_CALIBBIAS), 14),
 	ADIS_ACCEL_CHAN(Y, ADIS16201_YACCL_OUT, ADIS16201_SCAN_ACC_Y,
-		IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, 14),
+		BIT(IIO_CHAN_INFO_CALIBBIAS), 14),
 	ADIS_AUX_ADC_CHAN(ADIS16201_AUX_ADC, ADIS16201_SCAN_AUX_ADC, 12),
 	ADIS_INCLI_CHAN(X, ADIS16201_XINCL_OUT, ADIS16201_SCAN_INCLI_X,
-		IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, 14),
+		BIT(IIO_CHAN_INFO_CALIBBIAS), 14),
 	ADIS_INCLI_CHAN(X, ADIS16201_YINCL_OUT, ADIS16201_SCAN_INCLI_Y,
-		IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, 14),
+		BIT(IIO_CHAN_INFO_CALIBBIAS), 14),
 	IIO_CHAN_SOFT_TIMESTAMP(7)
 };
 
diff --git a/drivers/staging/iio/accel/adis16203_core.c b/drivers/staging/iio/accel/adis16203_core.c
index 8c23527..b08ac8f 100644
--- a/drivers/staging/iio/accel/adis16203_core.c
+++ b/drivers/staging/iio/accel/adis16203_core.c
@@ -102,7 +102,7 @@ static const struct iio_chan_spec adis16203_channels[] = {
 	ADIS_SUPPLY_CHAN(ADIS16203_SUPPLY_OUT, ADIS16203_SCAN_SUPPLY, 12),
 	ADIS_AUX_ADC_CHAN(ADIS16203_AUX_ADC, ADIS16203_SCAN_AUX_ADC, 12),
 	ADIS_INCLI_CHAN(X, ADIS16203_XINCL_OUT, ADIS16203_SCAN_INCLI_X,
-		IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, 14),
+		BIT(IIO_CHAN_INFO_CALIBBIAS), 14),
 	/* Fixme: Not what it appears to be - see data sheet */
 	ADIS_INCLI_CHAN(Y, ADIS16203_YINCL_OUT, ADIS16203_SCAN_INCLI_Y, 0, 14),
 	ADIS_TEMP_CHAN(ADIS16203_TEMP_OUT, ADIS16203_SCAN_TEMP, 12),
diff --git a/drivers/staging/iio/accel/adis16204_core.c b/drivers/staging/iio/accel/adis16204_core.c
index f359266..792ec25 100644
--- a/drivers/staging/iio/accel/adis16204_core.c
+++ b/drivers/staging/iio/accel/adis16204_core.c
@@ -140,13 +140,11 @@ static const struct iio_chan_spec adis16204_channels[] = {
 	ADIS_AUX_ADC_CHAN(ADIS16204_AUX_ADC, ADIS16204_SCAN_AUX_ADC, 12),
 	ADIS_TEMP_CHAN(ADIS16204_TEMP_OUT, ADIS16204_SCAN_TEMP, 12),
 	ADIS_ACCEL_CHAN(X, ADIS16204_XACCL_OUT, ADIS16204_SCAN_ACC_X,
-		IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
-		IIO_CHAN_INFO_PEAK_SEPARATE_BIT, 14),
+		BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 14),
 	ADIS_ACCEL_CHAN(Y, ADIS16204_YACCL_OUT, ADIS16204_SCAN_ACC_Y,
-		IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
-		IIO_CHAN_INFO_PEAK_SEPARATE_BIT, 14),
+		BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 14),
 	ADIS_ACCEL_CHAN(ROOT_SUM_SQUARED_X_Y, ADIS16204_XY_RSS_OUT,
-		ADIS16204_SCAN_ACC_XY, IIO_CHAN_INFO_PEAK_SEPARATE_BIT, 14),
+		ADIS16204_SCAN_ACC_XY, BIT(IIO_CHAN_INFO_PEAK), 14),
 	IIO_CHAN_SOFT_TIMESTAMP(5),
 };
 
diff --git a/drivers/staging/iio/accel/adis16209_core.c b/drivers/staging/iio/accel/adis16209_core.c
index 69c50ee..323c169 100644
--- a/drivers/staging/iio/accel/adis16209_core.c
+++ b/drivers/staging/iio/accel/adis16209_core.c
@@ -133,9 +133,9 @@ static const struct iio_chan_spec adis16209_channels[] = {
 	ADIS_SUPPLY_CHAN(ADIS16209_SUPPLY_OUT, ADIS16209_SCAN_SUPPLY, 14),
 	ADIS_TEMP_CHAN(ADIS16209_TEMP_OUT, ADIS16209_SCAN_TEMP, 12),
 	ADIS_ACCEL_CHAN(X, ADIS16209_XACCL_OUT, ADIS16209_SCAN_ACC_X,
-		IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, 14),
+		BIT(IIO_CHAN_INFO_CALIBBIAS), 14),
 	ADIS_ACCEL_CHAN(Y, ADIS16209_YACCL_OUT, ADIS16209_SCAN_ACC_Y,
-		IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, 14),
+		BIT(IIO_CHAN_INFO_CALIBBIAS), 14),
 	ADIS_AUX_ADC_CHAN(ADIS16209_AUX_ADC, ADIS16209_SCAN_AUX_ADC, 12),
 	ADIS_INCLI_CHAN(X, ADIS16209_XINCL_OUT, ADIS16209_SCAN_INCLI_X, 0, 14),
 	ADIS_INCLI_CHAN(Y, ADIS16209_YINCL_OUT, ADIS16209_SCAN_INCLI_Y, 0, 14),
diff --git a/drivers/staging/iio/accel/adis16220_core.c b/drivers/staging/iio/accel/adis16220_core.c
index 370b01a..0e72f79 100644
--- a/drivers/staging/iio/accel/adis16220_core.c
+++ b/drivers/staging/iio/accel/adis16220_core.c
@@ -344,37 +344,37 @@ static const struct iio_chan_spec adis16220_channels[] = {
 		.indexed = 1,
 		.channel = 0,
 		.extend_name = "supply",
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-			     IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+			BIT(IIO_CHAN_INFO_SCALE),
 		.address = in_supply,
 	}, {
 		.type = IIO_ACCEL,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-			     IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |
-			     IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
-			     IIO_CHAN_INFO_PEAK_SEPARATE_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+			BIT(IIO_CHAN_INFO_OFFSET) |
+			BIT(IIO_CHAN_INFO_SCALE) |
+			BIT(IIO_CHAN_INFO_PEAK),
 		.address = accel,
 	}, {
 		.type = IIO_TEMP,
 		.indexed = 1,
 		.channel = 0,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-			     IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |
-			     IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+			BIT(IIO_CHAN_INFO_OFFSET) |
+			BIT(IIO_CHAN_INFO_SCALE),
 		.address = temp,
 	}, {
 		.type = IIO_VOLTAGE,
 		.indexed = 1,
 		.channel = 1,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-			     IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |
-			     IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+			BIT(IIO_CHAN_INFO_OFFSET) |
+			BIT(IIO_CHAN_INFO_SCALE),
 		.address = in_1,
 	}, {
 		.type = IIO_VOLTAGE,
 		.indexed = 1,
 		.channel = 2,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
 		.address = in_2,
 	}
 };
diff --git a/drivers/staging/iio/accel/adis16240_core.c b/drivers/staging/iio/accel/adis16240_core.c
index e97fa0b..fd1f0fd 100644
--- a/drivers/staging/iio/accel/adis16240_core.c
+++ b/drivers/staging/iio/accel/adis16240_core.c
@@ -176,14 +176,11 @@ static const struct iio_chan_spec adis16240_channels[] = {
 	ADIS_SUPPLY_CHAN(ADIS16240_SUPPLY_OUT, ADIS16240_SCAN_SUPPLY, 10),
 	ADIS_AUX_ADC_CHAN(ADIS16240_AUX_ADC, ADIS16240_SCAN_AUX_ADC, 10),
 	ADIS_ACCEL_CHAN(X, ADIS16240_XACCL_OUT, ADIS16240_SCAN_ACC_X,
-		IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
-		IIO_CHAN_INFO_PEAK_SEPARATE_BIT, 10),
+		BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 10),
 	ADIS_ACCEL_CHAN(Y, ADIS16240_YACCL_OUT, ADIS16240_SCAN_ACC_Y,
-		IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
-		IIO_CHAN_INFO_PEAK_SEPARATE_BIT, 10),
+		BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 10),
 	ADIS_ACCEL_CHAN(Z, ADIS16240_ZACCL_OUT, ADIS16240_SCAN_ACC_Z,
-		IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
-		IIO_CHAN_INFO_PEAK_SEPARATE_BIT, 10),
+		BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 10),
 	ADIS_TEMP_CHAN(ADIS16240_TEMP_OUT, ADIS16240_SCAN_TEMP, 10),
 	IIO_CHAN_SOFT_TIMESTAMP(6)
 };
diff --git a/drivers/staging/iio/accel/lis3l02dq_core.c b/drivers/staging/iio/accel/lis3l02dq_core.c
index 0e01930..1bfe5d8 100644
--- a/drivers/staging/iio/accel/lis3l02dq_core.c
+++ b/drivers/staging/iio/accel/lis3l02dq_core.c
@@ -501,12 +501,6 @@ static irqreturn_t lis3l02dq_event_handler(int irq, void *private)
 	return IRQ_HANDLED;
 }
 
-#define LIS3L02DQ_INFO_MASK				\
-	(IIO_CHAN_INFO_RAW_SEPARATE_BIT |		\
-	 IIO_CHAN_INFO_SCALE_SHARED_BIT |		\
-	 IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT |	\
-	 IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT)
-
 #define LIS3L02DQ_EVENT_MASK					\
 	(IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING) |	\
 	 IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING))
@@ -516,7 +510,10 @@ static irqreturn_t lis3l02dq_event_handler(int irq, void *private)
 		.type = IIO_ACCEL,				\
 		.modified = 1,					\
 		.channel2 = mod,				\
-		.info_mask =  LIS3L02DQ_INFO_MASK,		\
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |	\
+			BIT(IIO_CHAN_INFO_CALIBSCALE) |		\
+			BIT(IIO_CHAN_INFO_CALIBBIAS),		\
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
 		.address = index,				\
 		.scan_index = index,				\
 		.scan_type = {					\
diff --git a/drivers/staging/iio/accel/lis3l02dq_ring.c b/drivers/staging/iio/accel/lis3l02dq_ring.c
index e676403..5b8f0f6 100644
--- a/drivers/staging/iio/accel/lis3l02dq_ring.c
+++ b/drivers/staging/iio/accel/lis3l02dq_ring.c
@@ -228,7 +228,7 @@ error_ret:
 static int lis3l02dq_data_rdy_trigger_set_state(struct iio_trigger *trig,
 						bool state)
 {
-	struct iio_dev *indio_dev = trig->private_data;
+	struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
 	int ret = 0;
 	u8 t;
 
@@ -252,7 +252,7 @@ static int lis3l02dq_data_rdy_trigger_set_state(struct iio_trigger *trig,
  */
 static int lis3l02dq_trig_try_reen(struct iio_trigger *trig)
 {
-	struct iio_dev *indio_dev = trig->private_data;
+	struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
 	struct lis3l02dq_state *st = iio_priv(indio_dev);
 	int i;
 
@@ -290,7 +290,7 @@ int lis3l02dq_probe_trigger(struct iio_dev *indio_dev)
 
 	st->trig->dev.parent = &st->us->dev;
 	st->trig->ops = &lis3l02dq_trigger_ops;
-	st->trig->private_data = indio_dev;
+	iio_trigger_set_drvdata(st->trig, indio_dev);
 	ret = iio_trigger_register(st->trig);
 	if (ret)
 		goto error_free_trig;
diff --git a/drivers/staging/iio/accel/sca3000_core.c b/drivers/staging/iio/accel/sca3000_core.c
index 14683f5..32950ad 100644
--- a/drivers/staging/iio/accel/sca3000_core.c
+++ b/drivers/staging/iio/accel/sca3000_core.c
@@ -419,8 +419,6 @@ static IIO_DEVICE_ATTR(measurement_mode, S_IRUGO | S_IWUSR,
 
 static IIO_DEVICE_ATTR(revision, S_IRUGO, sca3000_show_rev, NULL, 0);
 
-#define SCA3000_INFO_MASK			\
-	IIO_CHAN_INFO_RAW_SEPARATE_BIT | IIO_CHAN_INFO_SCALE_SHARED_BIT
 #define SCA3000_EVENT_MASK					\
 	(IIO_EV_BIT(IIO_EV_TYPE_MAG, IIO_EV_DIR_RISING))
 
@@ -429,7 +427,8 @@ static IIO_DEVICE_ATTR(revision, S_IRUGO, sca3000_show_rev, NULL, 0);
 		.type = IIO_ACCEL,				\
 		.modified = 1,					\
 		.channel2 = mod,				\
-		.info_mask = SCA3000_INFO_MASK,			\
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),	\
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),\
 		.address = index,				\
 		.scan_index = index,				\
 		.scan_type = {					\
diff --git a/drivers/staging/iio/adc/Kconfig b/drivers/staging/iio/adc/Kconfig
index 7b2a01d..d990829 100644
--- a/drivers/staging/iio/adc/Kconfig
+++ b/drivers/staging/iio/adc/Kconfig
@@ -90,13 +90,6 @@ config AD7192
 	  To compile this driver as a module, choose M here: the
 	  module will be called ad7192.
 
-config ADT7410
-	tristate "Analog Devices ADT7310/ADT7410 temperature sensor driver"
-	depends on I2C || SPI_MASTER
-	help
-	  Say yes here to build support for Analog Devices ADT7310/ADT7410
-	  temperature sensors.
-
 config AD7280
 	tristate "Analog Devices AD7280A Lithium Ion Battery Monitoring System"
 	depends on SPI
diff --git a/drivers/staging/iio/adc/Makefile b/drivers/staging/iio/adc/Makefile
index d285596..3e9fb14 100644
--- a/drivers/staging/iio/adc/Makefile
+++ b/drivers/staging/iio/adc/Makefile
@@ -16,7 +16,6 @@ obj-$(CONFIG_AD7291) += ad7291.o
 obj-$(CONFIG_AD7780) += ad7780.o
 obj-$(CONFIG_AD7816) += ad7816.o
 obj-$(CONFIG_AD7192) += ad7192.o
-obj-$(CONFIG_ADT7410) += adt7410.o
 obj-$(CONFIG_AD7280) += ad7280a.o
 obj-$(CONFIG_LPC32XX_ADC) += lpc32xx_adc.o
 obj-$(CONFIG_MXS_LRADC) += mxs-lradc.o
diff --git a/drivers/staging/iio/adc/ad7280a.c b/drivers/staging/iio/adc/ad7280a.c
index 1f190c1..2fd6ee3 100644
--- a/drivers/staging/iio/adc/ad7280a.c
+++ b/drivers/staging/iio/adc/ad7280a.c
@@ -503,9 +503,10 @@ static int ad7280_channel_init(struct ad7280_state *st)
 				st->channels[cnt].channel = (dev * 6) + ch - 6;
 			}
 			st->channels[cnt].indexed = 1;
-			st->channels[cnt].info_mask =
-				IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-				IIO_CHAN_INFO_SCALE_SHARED_BIT;
+			st->channels[cnt].info_mask_separate =
+				BIT(IIO_CHAN_INFO_RAW);
+			st->channels[cnt].info_mask_shared_by_type =
+				BIT(IIO_CHAN_INFO_SCALE);
 			st->channels[cnt].address =
 				AD7280A_DEVADDR(dev) << 8 | ch;
 			st->channels[cnt].scan_index = cnt;
@@ -521,9 +522,8 @@ static int ad7280_channel_init(struct ad7280_state *st)
 	st->channels[cnt].channel2 = dev * 6;
 	st->channels[cnt].address = AD7280A_ALL_CELLS;
 	st->channels[cnt].indexed = 1;
-	st->channels[cnt].info_mask =
-		IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-		IIO_CHAN_INFO_SCALE_SHARED_BIT;
+	st->channels[cnt].info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
+	st->channels[cnt].info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE);
 	st->channels[cnt].scan_index = cnt;
 	st->channels[cnt].scan_type.sign = 'u';
 	st->channels[cnt].scan_type.realbits = 32;
diff --git a/drivers/staging/iio/adc/ad7291.c b/drivers/staging/iio/adc/ad7291.c
index 6e58e36..d088c66 100644
--- a/drivers/staging/iio/adc/ad7291.c
+++ b/drivers/staging/iio/adc/ad7291.c
@@ -536,8 +536,8 @@ static int ad7291_read_raw(struct iio_dev *indio_dev,
 #define AD7291_VOLTAGE_CHAN(_chan)					\
 {									\
 	.type = IIO_VOLTAGE,						\
-	.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |			\
-	IIO_CHAN_INFO_SCALE_SHARED_BIT,					\
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),			\
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),		\
 	.indexed = 1,							\
 	.channel = _chan,						\
 	.event_mask = IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING)|\
@@ -555,9 +555,9 @@ static const struct iio_chan_spec ad7291_channels[] = {
 	AD7291_VOLTAGE_CHAN(7),
 	{
 		.type = IIO_TEMP,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-				IIO_CHAN_INFO_AVERAGE_RAW_SEPARATE_BIT |
-				IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+				BIT(IIO_CHAN_INFO_AVERAGE_RAW) |
+				BIT(IIO_CHAN_INFO_SCALE),
 		.indexed = 1,
 		.channel = 0,
 		.event_mask =
diff --git a/drivers/staging/iio/adc/ad7606_core.c b/drivers/staging/iio/adc/ad7606_core.c
index bae61cb..d104b43 100644
--- a/drivers/staging/iio/adc/ad7606_core.c
+++ b/drivers/staging/iio/adc/ad7606_core.c
@@ -235,8 +235,8 @@ static const struct attribute_group ad7606_attribute_group_range = {
 		.indexed = 1,					\
 		.channel = num,					\
 		.address = num,					\
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |	\
-				IIO_CHAN_INFO_SCALE_SHARED_BIT, \
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),	\
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),\
 		.scan_index = num,				\
 		.scan_type = IIO_ST('s', 16, 16, 0),		\
 	}
diff --git a/drivers/staging/iio/adc/ad799x.h b/drivers/staging/iio/adc/ad799x.h
index 3e363c4..b51680c 100644
--- a/drivers/staging/iio/adc/ad799x.h
+++ b/drivers/staging/iio/adc/ad799x.h
@@ -87,7 +87,6 @@ struct ad799x_state;
  * struct ad799x_chip_info - chip specifc information
  * @channel:		channel specification
  * @num_channels:	number of channels
- * @int_vref_mv:	the internal reference voltage
  * @monitor_mode:	whether the chip supports monitor interrupts
  * @default_config:	device default configuration
  * @event_attrs:	pointer to the monitor event attribute group
@@ -96,7 +95,6 @@ struct ad799x_state;
 struct ad799x_chip_info {
 	struct iio_chan_spec		channel[9];
 	int				num_channels;
-	u16				int_vref_mv;
 	u16				default_config;
 	const struct iio_info		*info;
 };
@@ -104,12 +102,13 @@ struct ad799x_chip_info {
 struct ad799x_state {
 	struct i2c_client		*client;
 	const struct ad799x_chip_info	*chip_info;
-	struct iio_trigger		*trig;
 	struct regulator		*reg;
 	u16				int_vref_mv;
 	unsigned			id;
-	char				*name;
 	u16				config;
+
+	u8				*rx_buf;
+	unsigned int			transfer_size;
 };
 
 /*
diff --git a/drivers/staging/iio/adc/ad799x_core.c b/drivers/staging/iio/adc/ad799x_core.c
index 077eedb..8dc97b3 100644
--- a/drivers/staging/iio/adc/ad799x_core.c
+++ b/drivers/staging/iio/adc/ad799x_core.c
@@ -48,13 +48,13 @@ static int ad799x_i2c_read16(struct ad799x_state *st, u8 reg, u16 *data)
 	struct i2c_client *client = st->client;
 	int ret = 0;
 
-	ret = i2c_smbus_read_word_data(client, reg);
+	ret = i2c_smbus_read_word_swapped(client, reg);
 	if (ret < 0) {
 		dev_err(&client->dev, "I2C read error\n");
 		return ret;
 	}
 
-	*data = swab16((u16)ret);
+	*data = (u16)ret;
 
 	return 0;
 }
@@ -80,7 +80,7 @@ static int ad799x_i2c_write16(struct ad799x_state *st, u8 reg, u16 data)
 	struct i2c_client *client = st->client;
 	int ret = 0;
 
-	ret = i2c_smbus_write_word_data(client, reg, swab16(data));
+	ret = i2c_smbus_write_word_swapped(client, reg, data);
 	if (ret < 0)
 		dev_err(&client->dev, "I2C write error\n");
 
@@ -104,6 +104,13 @@ static int ad7997_8_update_scan_mode(struct iio_dev *indio_dev,
 {
 	struct ad799x_state *st = iio_priv(indio_dev);
 
+	kfree(st->rx_buf);
+	st->rx_buf = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
+	if (!st->rx_buf)
+		return -ENOMEM;
+
+	st->transfer_size = bitmap_weight(scan_mask, indio_dev->masklength) * 2;
+
 	switch (st->id) {
 	case ad7997:
 	case ad7998:
@@ -460,395 +467,114 @@ static const struct iio_info ad7993_4_7_8_info = {
 #define AD799X_EV_MASK (IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING) | \
 			IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING))
 
+#define AD799X_CHANNEL(_index, _realbits, _evmask) { \
+	.type = IIO_VOLTAGE, \
+	.indexed = 1, \
+	.channel = (_index), \
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
+	.scan_index = (_index), \
+	.scan_type = IIO_ST('u', _realbits, 16, 12 - (_realbits)), \
+	.event_mask = (_evmask), \
+}
+
 static const struct ad799x_chip_info ad799x_chip_info_tbl[] = {
 	[ad7991] = {
 		.channel = {
-			[0] = {
-				.type = IIO_VOLTAGE,
-				.indexed = 1,
-				.channel = 0,
-				.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
-				.scan_index = 0,
-				.scan_type = IIO_ST('u', 12, 16, 0),
-			},
-			[1] = {
-				.type = IIO_VOLTAGE,
-				.indexed = 1,
-				.channel = 1,
-				.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
-				.scan_index = 1,
-				.scan_type = IIO_ST('u', 12, 16, 0),
-			},
-			[2] = {
-				.type = IIO_VOLTAGE,
-				.indexed = 1,
-				.channel = 2,
-				.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
-				.scan_index = 2,
-				.scan_type = IIO_ST('u', 12, 16, 0),
-			},
-			[3] = {
-				.type = IIO_VOLTAGE,
-				.indexed = 1,
-				.channel = 3,
-				.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
-				.scan_index = 3,
-				.scan_type = IIO_ST('u', 12, 16, 0),
-			},
-			[4] = IIO_CHAN_SOFT_TIMESTAMP(4),
+			AD799X_CHANNEL(0, 12, 0),
+			AD799X_CHANNEL(1, 12, 0),
+			AD799X_CHANNEL(2, 12, 0),
+			AD799X_CHANNEL(3, 12, 0),
+			IIO_CHAN_SOFT_TIMESTAMP(4),
 		},
 		.num_channels = 5,
-		.int_vref_mv = 4096,
 		.info = &ad7991_info,
 	},
 	[ad7995] = {
 		.channel = {
-			[0] = {
-				.type = IIO_VOLTAGE,
-				.indexed = 1,
-				.channel = 0,
-				.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
-				.scan_index = 0,
-				.scan_type = IIO_ST('u', 10, 16, 2),
-			},
-			[1] = {
-				.type = IIO_VOLTAGE,
-				.indexed = 1,
-				.channel = 1,
-				.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
-				.scan_index = 1,
-				.scan_type = IIO_ST('u', 10, 16, 2),
-			},
-			[2] = {
-				.type = IIO_VOLTAGE,
-				.indexed = 1,
-				.channel = 2,
-				.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
-				.scan_index = 2,
-				.scan_type = IIO_ST('u', 10, 16, 2),
-			},
-			[3] = {
-				.type = IIO_VOLTAGE,
-				.indexed = 1,
-				.channel = 3,
-				.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
-				.scan_index = 3,
-				.scan_type = IIO_ST('u', 10, 16, 2),
-			},
-			[4] = IIO_CHAN_SOFT_TIMESTAMP(4),
+			AD799X_CHANNEL(0, 10, 0),
+			AD799X_CHANNEL(1, 10, 0),
+			AD799X_CHANNEL(2, 10, 0),
+			AD799X_CHANNEL(3, 10, 0),
+			IIO_CHAN_SOFT_TIMESTAMP(4),
 		},
 		.num_channels = 5,
-		.int_vref_mv = 1024,
 		.info = &ad7991_info,
 	},
 	[ad7999] = {
 		.channel = {
-			[0] = {
-				.type = IIO_VOLTAGE,
-				.indexed = 1,
-				.channel = 0,
-				.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
-				.scan_index = 0,
-				.scan_type = IIO_ST('u', 8, 16, 4),
-			},
-			[1] = {
-				.type = IIO_VOLTAGE,
-				.indexed = 1,
-				.channel = 1,
-				.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
-				.scan_index = 1,
-				.scan_type = IIO_ST('u', 8, 16, 4),
-			},
-			[2] = {
-				.type = IIO_VOLTAGE,
-				.indexed = 1,
-				.channel = 2,
-				.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
-				.scan_index = 2,
-				.scan_type = IIO_ST('u', 8, 16, 4),
-			},
-			[3] = {
-				.type = IIO_VOLTAGE,
-				.indexed = 1,
-				.channel = 3,
-				.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
-				.scan_index = 3,
-				.scan_type = IIO_ST('u', 8, 16, 4),
-			},
-			[4] = IIO_CHAN_SOFT_TIMESTAMP(4),
+			AD799X_CHANNEL(0, 8, 0),
+			AD799X_CHANNEL(1, 8, 0),
+			AD799X_CHANNEL(2, 8, 0),
+			AD799X_CHANNEL(3, 8, 0),
+			IIO_CHAN_SOFT_TIMESTAMP(4),
 		},
 		.num_channels = 5,
-		.int_vref_mv = 1024,
 		.info = &ad7991_info,
 	},
 	[ad7992] = {
 		.channel = {
-			[0] = {
-				.type = IIO_VOLTAGE,
-				.indexed = 1,
-				.channel = 0,
-				.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
-				.scan_index = 0,
-				.scan_type = IIO_ST('u', 12, 16, 0),
-				.event_mask = AD799X_EV_MASK,
-			},
-			[1] = {
-				.type = IIO_VOLTAGE,
-				.indexed = 1,
-				.channel = 1,
-				.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
-				.scan_index = 1,
-				.scan_type = IIO_ST('u', 12, 16, 0),
-				.event_mask = AD799X_EV_MASK,
-			},
-			[2] = IIO_CHAN_SOFT_TIMESTAMP(2),
+			AD799X_CHANNEL(0, 12, AD799X_EV_MASK),
+			AD799X_CHANNEL(1, 12, AD799X_EV_MASK),
+			IIO_CHAN_SOFT_TIMESTAMP(3),
 		},
 		.num_channels = 3,
-		.int_vref_mv = 4096,
 		.default_config = AD7998_ALERT_EN,
 		.info = &ad7992_info,
 	},
 	[ad7993] = {
 		.channel = {
-			[0] = {
-				.type = IIO_VOLTAGE,
-				.indexed = 1,
-				.channel = 0,
-				.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
-				.scan_index = 0,
-				.scan_type = IIO_ST('u', 10, 16, 2),
-				.event_mask = AD799X_EV_MASK,
-			},
-			[1] = {
-				.type = IIO_VOLTAGE,
-				.indexed = 1,
-				.channel = 1,
-				.scan_index = 1,
-				.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
-				.scan_type = IIO_ST('u', 10, 16, 2),
-				.event_mask = AD799X_EV_MASK,
-			},
-			[2] = {
-				.type = IIO_VOLTAGE,
-				.indexed = 1,
-				.channel = 2,
-				.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
-				.scan_index = 2,
-				.scan_type = IIO_ST('u', 10, 16, 2),
-				.event_mask = AD799X_EV_MASK,
-			},
-			[3] = {
-				.type = IIO_VOLTAGE,
-				.indexed = 1,
-				.channel = 3,
-				.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
-				.scan_index = 3,
-				.scan_type = IIO_ST('u', 10, 16, 2),
-				.event_mask = AD799X_EV_MASK,
-			},
-			[4] = IIO_CHAN_SOFT_TIMESTAMP(4),
+			AD799X_CHANNEL(0, 10, AD799X_EV_MASK),
+			AD799X_CHANNEL(1, 10, AD799X_EV_MASK),
+			AD799X_CHANNEL(2, 10, AD799X_EV_MASK),
+			AD799X_CHANNEL(3, 10, AD799X_EV_MASK),
+			IIO_CHAN_SOFT_TIMESTAMP(4),
 		},
 		.num_channels = 5,
-		.int_vref_mv = 1024,
 		.default_config = AD7998_ALERT_EN,
 		.info = &ad7993_4_7_8_info,
 	},
 	[ad7994] = {
 		.channel = {
-			[0] = {
-				.type = IIO_VOLTAGE,
-				.indexed = 1,
-				.channel = 0,
-				.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
-				.scan_index = 0,
-				.scan_type = IIO_ST('u', 12, 16, 0),
-				.event_mask = AD799X_EV_MASK,
-			},
-			[1] = {
-				.type = IIO_VOLTAGE,
-				.indexed = 1,
-				.channel = 1,
-				.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
-				.scan_index = 1,
-				.scan_type = IIO_ST('u', 12, 16, 0),
-				.event_mask = AD799X_EV_MASK,
-			},
-			[2] = {
-				.type = IIO_VOLTAGE,
-				.indexed = 1,
-				.channel = 2,
-				.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
-				.scan_index = 2,
-				.scan_type = IIO_ST('u', 12, 16, 0),
-				.event_mask = AD799X_EV_MASK,
-			},
-			[3] = {
-				.type = IIO_VOLTAGE,
-				.indexed = 1,
-				.channel = 3,
-				.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
-				.scan_index = 3,
-				.scan_type = IIO_ST('u', 12, 16, 0),
-				.event_mask = AD799X_EV_MASK,
-			},
-			[4] = IIO_CHAN_SOFT_TIMESTAMP(4),
+			AD799X_CHANNEL(0, 12, AD799X_EV_MASK),
+			AD799X_CHANNEL(1, 12, AD799X_EV_MASK),
+			AD799X_CHANNEL(2, 12, AD799X_EV_MASK),
+			AD799X_CHANNEL(3, 12, AD799X_EV_MASK),
+			IIO_CHAN_SOFT_TIMESTAMP(4),
 		},
 		.num_channels = 5,
-		.int_vref_mv = 4096,
 		.default_config = AD7998_ALERT_EN,
 		.info = &ad7993_4_7_8_info,
 	},
 	[ad7997] = {
 		.channel = {
-			[0] = {
-				.type = IIO_VOLTAGE,
-				.indexed = 1,
-				.channel = 0,
-				.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
-				.scan_index = 0,
-				.scan_type = IIO_ST('u', 10, 16, 2),
-				.event_mask = AD799X_EV_MASK,
-			},
-			[1] = {
-				.type = IIO_VOLTAGE,
-				.indexed = 1,
-				.channel = 1,
-				.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
-				.scan_index = 1,
-				.scan_type = IIO_ST('u', 10, 16, 2),
-				.event_mask = AD799X_EV_MASK,
-			},
-			[2] = {
-				.type = IIO_VOLTAGE,
-				.indexed = 1,
-				.channel = 2,
-				.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
-				.scan_index = 2,
-				.scan_type = IIO_ST('u', 10, 16, 2),
-				.event_mask = AD799X_EV_MASK,
-			},
-			[3] = {
-				.type = IIO_VOLTAGE,
-				.indexed = 1,
-				.channel = 3,
-				.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
-				.scan_index = 3,
-				.scan_type = IIO_ST('u', 10, 16, 2),
-				.event_mask = AD799X_EV_MASK,
-			},
-			[4] = {
-				.type = IIO_VOLTAGE,
-				.indexed = 1,
-				.channel = 4,
-				.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
-				.scan_index = 4,
-				.scan_type = IIO_ST('u', 10, 16, 2),
-			},
-			[5] = {
-				.type = IIO_VOLTAGE,
-				.indexed = 1,
-				.channel = 5,
-				.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
-				.scan_index = 5,
-				.scan_type = IIO_ST('u', 10, 16, 2),
-			},
-			[6] = {
-				.type = IIO_VOLTAGE,
-				.indexed = 1,
-				.channel = 6,
-				.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
-				.scan_index = 6,
-				.scan_type = IIO_ST('u', 10, 16, 2),
-			},
-			[7] = {
-				.type = IIO_VOLTAGE,
-				.indexed = 1,
-				.channel = 7,
-				.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
-				.scan_index = 7,
-				.scan_type = IIO_ST('u', 10, 16, 2),
-			},
-			[8] = IIO_CHAN_SOFT_TIMESTAMP(8),
+			AD799X_CHANNEL(0, 10, AD799X_EV_MASK),
+			AD799X_CHANNEL(1, 10, AD799X_EV_MASK),
+			AD799X_CHANNEL(2, 10, AD799X_EV_MASK),
+			AD799X_CHANNEL(3, 10, AD799X_EV_MASK),
+			AD799X_CHANNEL(4, 10, 0),
+			AD799X_CHANNEL(5, 10, 0),
+			AD799X_CHANNEL(6, 10, 0),
+			AD799X_CHANNEL(7, 10, 0),
+			IIO_CHAN_SOFT_TIMESTAMP(8),
 		},
 		.num_channels = 9,
-		.int_vref_mv = 1024,
 		.default_config = AD7998_ALERT_EN,
 		.info = &ad7993_4_7_8_info,
 	},
 	[ad7998] = {
 		.channel = {
-			[0] = {
-				.type = IIO_VOLTAGE,
-				.indexed = 1,
-				.channel = 0,
-				.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
-				.scan_index = 0,
-				.scan_type = IIO_ST('u', 12, 16, 0),
-				.event_mask = AD799X_EV_MASK,
-			},
-			[1] = {
-				.type = IIO_VOLTAGE,
-				.indexed = 1,
-				.channel = 1,
-				.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
-				.scan_index = 1,
-				.scan_type = IIO_ST('u', 12, 16, 0),
-				.event_mask = AD799X_EV_MASK,
-			},
-			[2] = {
-				.type = IIO_VOLTAGE,
-				.indexed = 1,
-				.channel = 2,
-				.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
-				.scan_index = 2,
-				.scan_type = IIO_ST('u', 12, 16, 0),
-				.event_mask = AD799X_EV_MASK,
-			},
-			[3] = {
-				.type = IIO_VOLTAGE,
-				.indexed = 1,
-				.channel = 3,
-				.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
-				.scan_index = 3,
-				.scan_type = IIO_ST('u', 12, 16, 0),
-				.event_mask = AD799X_EV_MASK,
-			},
-			[4] = {
-				.type = IIO_VOLTAGE,
-				.indexed = 1,
-				.channel = 4,
-				.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
-				.scan_index = 4,
-				.scan_type = IIO_ST('u', 12, 16, 0),
-			},
-			[5] = {
-				.type = IIO_VOLTAGE,
-				.indexed = 1,
-				.channel = 5,
-				.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
-				.scan_index = 5,
-				.scan_type = IIO_ST('u', 12, 16, 0),
-			},
-			[6] = {
-				.type = IIO_VOLTAGE,
-				.indexed = 1,
-				.channel = 6,
-				.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
-				.scan_index = 6,
-				.scan_type = IIO_ST('u', 12, 16, 0),
-			},
-			[7] = {
-				.type = IIO_VOLTAGE,
-				.indexed = 1,
-				.channel = 7,
-				.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
-				.scan_index = 7,
-				.scan_type = IIO_ST('u', 12, 16, 0),
-			},
-			[8] = IIO_CHAN_SOFT_TIMESTAMP(8),
+			AD799X_CHANNEL(0, 12, AD799X_EV_MASK),
+			AD799X_CHANNEL(1, 12, AD799X_EV_MASK),
+			AD799X_CHANNEL(2, 12, AD799X_EV_MASK),
+			AD799X_CHANNEL(3, 12, AD799X_EV_MASK),
+			AD799X_CHANNEL(4, 12, 0),
+			AD799X_CHANNEL(5, 12, 0),
+			AD799X_CHANNEL(6, 12, 0),
+			AD799X_CHANNEL(7, 12, 0),
+			IIO_CHAN_SOFT_TIMESTAMP(8),
 		},
 		.num_channels = 9,
-		.int_vref_mv = 4096,
 		.default_config = AD7998_ALERT_EN,
 		.info = &ad7993_4_7_8_info,
 	},
@@ -875,10 +601,10 @@ static int ad799x_probe(struct i2c_client *client,
 
 	/* TODO: Add pdata options for filtering and bit delay */
 
-	if (pdata)
-		st->int_vref_mv = pdata->vref_mv;
-	else
-		st->int_vref_mv = st->chip_info->int_vref_mv;
+	if (!pdata)
+		return -EINVAL;
+
+	st->int_vref_mv = pdata->vref_mv;
 
 	st->reg = regulator_get(&client->dev, "vcc");
 	if (!IS_ERR(st->reg)) {
@@ -946,6 +672,7 @@ static int ad799x_remove(struct i2c_client *client)
 		regulator_disable(st->reg);
 		regulator_put(st->reg);
 	}
+	kfree(st->rx_buf);
 	iio_device_free(indio_dev);
 
 	return 0;
diff --git a/drivers/staging/iio/adc/ad799x_ring.c b/drivers/staging/iio/adc/ad799x_ring.c
index 2c5f384..c2ebae1 100644
--- a/drivers/staging/iio/adc/ad799x_ring.c
+++ b/drivers/staging/iio/adc/ad799x_ring.c
@@ -36,14 +36,9 @@ static irqreturn_t ad799x_trigger_handler(int irq, void *p)
 	struct iio_dev *indio_dev = pf->indio_dev;
 	struct ad799x_state *st = iio_priv(indio_dev);
 	s64 time_ns;
-	__u8 *rxbuf;
 	int b_sent;
 	u8 cmd;
 
-	rxbuf = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
-	if (rxbuf == NULL)
-		goto out;
-
 	switch (st->id) {
 	case ad7991:
 	case ad7995:
@@ -66,20 +61,17 @@ static irqreturn_t ad799x_trigger_handler(int irq, void *p)
 	}
 
 	b_sent = i2c_smbus_read_i2c_block_data(st->client,
-			cmd, bitmap_weight(indio_dev->active_scan_mask,
-					   indio_dev->masklength) * 2, rxbuf);
+			cmd, st->transfer_size, st->rx_buf);
 	if (b_sent < 0)
-		goto done;
+		goto out;
 
 	time_ns = iio_get_time_ns();
 
 	if (indio_dev->scan_timestamp)
-		memcpy(rxbuf + indio_dev->scan_bytes - sizeof(s64),
+		memcpy(st->rx_buf + indio_dev->scan_bytes - sizeof(s64),
 			&time_ns, sizeof(time_ns));
 
-	iio_push_to_buffers(indio_dev, rxbuf);
-done:
-	kfree(rxbuf);
+	iio_push_to_buffers(indio_dev, st->rx_buf);
 out:
 	iio_trigger_notify_done(indio_dev->trig);
 
diff --git a/drivers/staging/iio/adc/adt7410.c b/drivers/staging/iio/adc/adt7410.c
deleted file mode 100644
index 35455e1..0000000
--- a/drivers/staging/iio/adc/adt7410.c
+++ /dev/null
@@ -1,1102 +0,0 @@
-/*
- * ADT7410 digital temperature sensor driver supporting ADT7310/ADT7410
- *
- * Copyright 2010 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
-
-#include <linux/interrupt.h>
-#include <linux/device.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/sysfs.h>
-#include <linux/list.h>
-#include <linux/i2c.h>
-#include <linux/spi/spi.h>
-#include <linux/module.h>
-
-#include <linux/iio/iio.h>
-#include <linux/iio/sysfs.h>
-#include <linux/iio/events.h>
-
-/*
- * ADT7410 registers definition
- */
-
-#define ADT7410_TEMPERATURE		0
-#define ADT7410_STATUS			2
-#define ADT7410_CONFIG			3
-#define ADT7410_T_ALARM_HIGH		4
-#define ADT7410_T_ALARM_LOW		6
-#define ADT7410_T_CRIT			8
-#define ADT7410_T_HYST			0xA
-#define ADT7410_ID			0xB
-#define ADT7410_RESET			0x2F
-
-/*
- * ADT7310 registers definition
- */
-
-#define ADT7310_STATUS			0
-#define ADT7310_CONFIG			1
-#define ADT7310_TEMPERATURE		2
-#define ADT7310_ID			3
-#define ADT7310_T_CRIT			4
-#define ADT7310_T_HYST			5
-#define ADT7310_T_ALARM_HIGH		6
-#define ADT7310_T_ALARM_LOW		7
-
-/*
- * ADT7410 status
- */
-#define ADT7410_STAT_T_LOW		0x10
-#define ADT7410_STAT_T_HIGH		0x20
-#define ADT7410_STAT_T_CRIT		0x40
-#define ADT7410_STAT_NOT_RDY		0x80
-
-/*
- * ADT7410 config
- */
-#define ADT7410_FAULT_QUEUE_MASK	0x3
-#define ADT7410_CT_POLARITY		0x4
-#define ADT7410_INT_POLARITY		0x8
-#define ADT7410_EVENT_MODE		0x10
-#define ADT7410_MODE_MASK		0x60
-#define ADT7410_ONESHOT			0x20
-#define ADT7410_SPS			0x40
-#define ADT7410_PD			0x60
-#define ADT7410_RESOLUTION		0x80
-
-/*
- * ADT7410 masks
- */
-#define ADT7410_T16_VALUE_SIGN			0x8000
-#define ADT7410_T16_VALUE_FLOAT_OFFSET		7
-#define ADT7410_T16_VALUE_FLOAT_MASK		0x7F
-#define ADT7410_T13_VALUE_SIGN			0x1000
-#define ADT7410_T13_VALUE_OFFSET		3
-#define ADT7410_T13_VALUE_FLOAT_OFFSET		4
-#define ADT7410_T13_VALUE_FLOAT_MASK		0xF
-#define ADT7410_T_HYST_MASK			0xF
-#define ADT7410_DEVICE_ID_MASK			0xF
-#define ADT7410_MANUFACTORY_ID_MASK		0xF0
-#define ADT7410_MANUFACTORY_ID_OFFSET		4
-
-
-#define ADT7310_CMD_REG_MASK			0x28
-#define ADT7310_CMD_REG_OFFSET			3
-#define ADT7310_CMD_READ			0x40
-#define ADT7310_CMD_CON_READ			0x4
-
-#define ADT7410_IRQS				2
-
-/*
- * struct adt7410_chip_info - chip specifc information
- */
-
-struct adt7410_chip_info;
-
-struct adt7410_ops {
-	int (*read_word)(struct adt7410_chip_info *, u8 reg, u16 *data);
-	int (*write_word)(struct adt7410_chip_info *, u8 reg, u16 data);
-	int (*read_byte)(struct adt7410_chip_info *, u8 reg, u8 *data);
-	int (*write_byte)(struct adt7410_chip_info *, u8 reg, u8 data);
-};
-
-struct adt7410_chip_info {
-	struct device *dev;
-	u8  config;
-
-	const struct adt7410_ops *ops;
-};
-
-static int adt7410_read_word(struct adt7410_chip_info *chip, u8 reg, u16 *data)
-{
-	return chip->ops->read_word(chip, reg, data);
-}
-
-static int adt7410_write_word(struct adt7410_chip_info *chip, u8 reg, u16 data)
-{
-	return chip->ops->write_word(chip, reg, data);
-}
-
-static int adt7410_read_byte(struct adt7410_chip_info *chip, u8 reg, u8 *data)
-{
-	return chip->ops->read_byte(chip, reg, data);
-}
-
-static int adt7410_write_byte(struct adt7410_chip_info *chip, u8 reg, u8 data)
-{
-	return chip->ops->write_byte(chip, reg, data);
-}
-
-static ssize_t adt7410_show_mode(struct device *dev,
-		struct device_attribute *attr,
-		char *buf)
-{
-	struct iio_dev *dev_info = dev_to_iio_dev(dev);
-	struct adt7410_chip_info *chip = iio_priv(dev_info);
-	u8 config;
-
-	config = chip->config & ADT7410_MODE_MASK;
-
-	switch (config) {
-	case ADT7410_PD:
-		return sprintf(buf, "power-down\n");
-	case ADT7410_ONESHOT:
-		return sprintf(buf, "one-shot\n");
-	case ADT7410_SPS:
-		return sprintf(buf, "sps\n");
-	default:
-		return sprintf(buf, "full\n");
-	}
-}
-
-static ssize_t adt7410_store_mode(struct device *dev,
-		struct device_attribute *attr,
-		const char *buf,
-		size_t len)
-{
-	struct iio_dev *dev_info = dev_to_iio_dev(dev);
-	struct adt7410_chip_info *chip = iio_priv(dev_info);
-	u16 config;
-	int ret;
-
-	ret = adt7410_read_byte(chip, ADT7410_CONFIG, &chip->config);
-	if (ret)
-		return -EIO;
-
-	config = chip->config & (~ADT7410_MODE_MASK);
-	if (strcmp(buf, "power-down"))
-		config |= ADT7410_PD;
-	else if (strcmp(buf, "one-shot"))
-		config |= ADT7410_ONESHOT;
-	else if (strcmp(buf, "sps"))
-		config |= ADT7410_SPS;
-
-	ret = adt7410_write_byte(chip, ADT7410_CONFIG, config);
-	if (ret)
-		return -EIO;
-
-	chip->config = config;
-
-	return len;
-}
-
-static IIO_DEVICE_ATTR(mode, S_IRUGO | S_IWUSR,
-		adt7410_show_mode,
-		adt7410_store_mode,
-		0);
-
-static ssize_t adt7410_show_available_modes(struct device *dev,
-		struct device_attribute *attr,
-		char *buf)
-{
-	return sprintf(buf, "full\none-shot\nsps\npower-down\n");
-}
-
-static IIO_DEVICE_ATTR(available_modes, S_IRUGO, adt7410_show_available_modes, NULL, 0);
-
-static ssize_t adt7410_show_resolution(struct device *dev,
-		struct device_attribute *attr,
-		char *buf)
-{
-	struct iio_dev *dev_info = dev_to_iio_dev(dev);
-	struct adt7410_chip_info *chip = iio_priv(dev_info);
-	int ret;
-	int bits;
-
-	ret = adt7410_read_byte(chip, ADT7410_CONFIG, &chip->config);
-	if (ret)
-		return -EIO;
-
-	if (chip->config & ADT7410_RESOLUTION)
-		bits = 16;
-	else
-		bits = 13;
-
-	return sprintf(buf, "%d bits\n", bits);
-}
-
-static ssize_t adt7410_store_resolution(struct device *dev,
-		struct device_attribute *attr,
-		const char *buf,
-		size_t len)
-{
-	struct iio_dev *dev_info = dev_to_iio_dev(dev);
-	struct adt7410_chip_info *chip = iio_priv(dev_info);
-	unsigned long data;
-	u16 config;
-	int ret;
-
-	ret = strict_strtoul(buf, 10, &data);
-	if (ret)
-		return -EINVAL;
-
-	ret = adt7410_read_byte(chip, ADT7410_CONFIG, &chip->config);
-	if (ret)
-		return -EIO;
-
-	config = chip->config & (~ADT7410_RESOLUTION);
-	if (data)
-		config |= ADT7410_RESOLUTION;
-
-	ret = adt7410_write_byte(chip, ADT7410_CONFIG, config);
-	if (ret)
-		return -EIO;
-
-	chip->config = config;
-
-	return len;
-}
-
-static IIO_DEVICE_ATTR(resolution, S_IRUGO | S_IWUSR,
-		adt7410_show_resolution,
-		adt7410_store_resolution,
-		0);
-
-static ssize_t adt7410_show_id(struct device *dev,
-		struct device_attribute *attr,
-		char *buf)
-{
-	struct iio_dev *dev_info = dev_to_iio_dev(dev);
-	struct adt7410_chip_info *chip = iio_priv(dev_info);
-	u8 id;
-	int ret;
-
-	ret = adt7410_read_byte(chip, ADT7410_ID, &id);
-	if (ret)
-		return -EIO;
-
-	return sprintf(buf, "device id: 0x%x\nmanufactory id: 0x%x\n",
-			id & ADT7410_DEVICE_ID_MASK,
-			(id & ADT7410_MANUFACTORY_ID_MASK) >> ADT7410_MANUFACTORY_ID_OFFSET);
-}
-
-static IIO_DEVICE_ATTR(id, S_IRUGO | S_IWUSR,
-		adt7410_show_id,
-		NULL,
-		0);
-
-static ssize_t adt7410_convert_temperature(struct adt7410_chip_info *chip,
-		u16 data, char *buf)
-{
-	char sign = ' ';
-
-	if (!(chip->config & ADT7410_RESOLUTION))
-		data &= ~0x7;
-
-	if (data & ADT7410_T16_VALUE_SIGN) {
-		/* convert supplement to positive value */
-		data = (u16)((ADT7410_T16_VALUE_SIGN << 1) - (u32)data);
-		sign = '-';
-	}
-	return sprintf(buf, "%c%d.%.7d\n", sign,
-			(data >> ADT7410_T16_VALUE_FLOAT_OFFSET),
-			(data & ADT7410_T16_VALUE_FLOAT_MASK) * 78125);
-}
-
-static ssize_t adt7410_show_value(struct device *dev,
-		struct device_attribute *attr,
-		char *buf)
-{
-	struct iio_dev *dev_info = dev_to_iio_dev(dev);
-	struct adt7410_chip_info *chip = iio_priv(dev_info);
-	u8 status;
-	u16 data;
-	int ret, i = 0;
-
-	do {
-		ret = adt7410_read_byte(chip, ADT7410_STATUS, &status);
-		if (ret)
-			return -EIO;
-		i++;
-		if (i == 10000)
-			return -EIO;
-	} while (status & ADT7410_STAT_NOT_RDY);
-
-	ret = adt7410_read_word(chip, ADT7410_TEMPERATURE, &data);
-	if (ret)
-		return -EIO;
-
-	return adt7410_convert_temperature(chip, data, buf);
-}
-
-static IIO_DEVICE_ATTR(value, S_IRUGO, adt7410_show_value, NULL, 0);
-
-static struct attribute *adt7410_attributes[] = {
-	&iio_dev_attr_available_modes.dev_attr.attr,
-	&iio_dev_attr_mode.dev_attr.attr,
-	&iio_dev_attr_resolution.dev_attr.attr,
-	&iio_dev_attr_id.dev_attr.attr,
-	&iio_dev_attr_value.dev_attr.attr,
-	NULL,
-};
-
-static const struct attribute_group adt7410_attribute_group = {
-	.attrs = adt7410_attributes,
-};
-
-static irqreturn_t adt7410_event_handler(int irq, void *private)
-{
-	struct iio_dev *indio_dev = private;
-	struct adt7410_chip_info *chip = iio_priv(indio_dev);
-	s64 timestamp = iio_get_time_ns();
-	u8 status;
-
-	if (adt7410_read_byte(chip, ADT7410_STATUS, &status))
-		return IRQ_HANDLED;
-
-	if (status & ADT7410_STAT_T_HIGH)
-		iio_push_event(indio_dev,
-			       IIO_UNMOD_EVENT_CODE(IIO_TEMP, 0,
-						    IIO_EV_TYPE_THRESH,
-						    IIO_EV_DIR_RISING),
-			       timestamp);
-	if (status & ADT7410_STAT_T_LOW)
-		iio_push_event(indio_dev,
-			       IIO_UNMOD_EVENT_CODE(IIO_TEMP, 0,
-						    IIO_EV_TYPE_THRESH,
-						    IIO_EV_DIR_FALLING),
-			       timestamp);
-	if (status & ADT7410_STAT_T_CRIT)
-		iio_push_event(indio_dev,
-			       IIO_UNMOD_EVENT_CODE(IIO_TEMP, 0,
-						    IIO_EV_TYPE_THRESH,
-						    IIO_EV_DIR_RISING),
-			       timestamp);
-
-	return IRQ_HANDLED;
-}
-
-static ssize_t adt7410_show_event_mode(struct device *dev,
-		struct device_attribute *attr,
-		char *buf)
-{
-	struct iio_dev *dev_info = dev_to_iio_dev(dev);
-	struct adt7410_chip_info *chip = iio_priv(dev_info);
-	int ret;
-
-	ret = adt7410_read_byte(chip, ADT7410_CONFIG, &chip->config);
-	if (ret)
-		return -EIO;
-
-	if (chip->config & ADT7410_EVENT_MODE)
-		return sprintf(buf, "interrupt\n");
-	else
-		return sprintf(buf, "comparator\n");
-}
-
-static ssize_t adt7410_set_event_mode(struct device *dev,
-		struct device_attribute *attr,
-		const char *buf,
-		size_t len)
-{
-	struct iio_dev *dev_info = dev_to_iio_dev(dev);
-	struct adt7410_chip_info *chip = iio_priv(dev_info);
-	u16 config;
-	int ret;
-
-	ret = adt7410_read_byte(chip, ADT7410_CONFIG, &chip->config);
-	if (ret)
-		return -EIO;
-
-	config = chip->config &= ~ADT7410_EVENT_MODE;
-	if (strcmp(buf, "comparator") != 0)
-		config |= ADT7410_EVENT_MODE;
-
-	ret = adt7410_write_byte(chip, ADT7410_CONFIG, config);
-	if (ret)
-		return -EIO;
-
-	chip->config = config;
-
-	return ret;
-}
-
-static ssize_t adt7410_show_available_event_modes(struct device *dev,
-		struct device_attribute *attr,
-		char *buf)
-{
-	return sprintf(buf, "comparator\ninterrupt\n");
-}
-
-static ssize_t adt7410_show_fault_queue(struct device *dev,
-		struct device_attribute *attr,
-		char *buf)
-{
-	struct iio_dev *dev_info = dev_to_iio_dev(dev);
-	struct adt7410_chip_info *chip = iio_priv(dev_info);
-	int ret;
-
-	ret = adt7410_read_byte(chip, ADT7410_CONFIG, &chip->config);
-	if (ret)
-		return -EIO;
-
-	return sprintf(buf, "%d\n", chip->config & ADT7410_FAULT_QUEUE_MASK);
-}
-
-static ssize_t adt7410_set_fault_queue(struct device *dev,
-		struct device_attribute *attr,
-		const char *buf,
-		size_t len)
-{
-	struct iio_dev *dev_info = dev_to_iio_dev(dev);
-	struct adt7410_chip_info *chip = iio_priv(dev_info);
-	unsigned long data;
-	int ret;
-	u8 config;
-
-	ret = strict_strtoul(buf, 10, &data);
-	if (ret || data > 3)
-		return -EINVAL;
-
-	ret = adt7410_read_byte(chip, ADT7410_CONFIG, &chip->config);
-	if (ret)
-		return -EIO;
-
-	config = chip->config & ~ADT7410_FAULT_QUEUE_MASK;
-	config |= data;
-	ret = adt7410_write_byte(chip, ADT7410_CONFIG, config);
-	if (ret)
-		return -EIO;
-
-	chip->config = config;
-
-	return ret;
-}
-
-static inline ssize_t adt7410_show_t_bound(struct device *dev,
-		struct device_attribute *attr,
-		u8 bound_reg,
-		char *buf)
-{
-	struct iio_dev *dev_info = dev_to_iio_dev(dev);
-	struct adt7410_chip_info *chip = iio_priv(dev_info);
-	u16 data;
-	int ret;
-
-	ret = adt7410_read_word(chip, bound_reg, &data);
-	if (ret)
-		return -EIO;
-
-	return adt7410_convert_temperature(chip, data, buf);
-}
-
-static inline ssize_t adt7410_set_t_bound(struct device *dev,
-		struct device_attribute *attr,
-		u8 bound_reg,
-		const char *buf,
-		size_t len)
-{
-	struct iio_dev *dev_info = dev_to_iio_dev(dev);
-	struct adt7410_chip_info *chip = iio_priv(dev_info);
-	long tmp1, tmp2;
-	u16 data;
-	char *pos;
-	int ret;
-
-	pos = strchr(buf, '.');
-
-	ret = strict_strtol(buf, 10, &tmp1);
-
-	if (ret || tmp1 > 127 || tmp1 < -128)
-		return -EINVAL;
-
-	if (pos) {
-		len = strlen(pos);
-
-		if (chip->config & ADT7410_RESOLUTION) {
-			if (len > ADT7410_T16_VALUE_FLOAT_OFFSET)
-				len = ADT7410_T16_VALUE_FLOAT_OFFSET;
-			pos[len] = 0;
-			ret = strict_strtol(pos, 10, &tmp2);
-
-			if (!ret)
-				tmp2 = (tmp2 / 78125) * 78125;
-		} else {
-			if (len > ADT7410_T13_VALUE_FLOAT_OFFSET)
-				len = ADT7410_T13_VALUE_FLOAT_OFFSET;
-			pos[len] = 0;
-			ret = strict_strtol(pos, 10, &tmp2);
-
-			if (!ret)
-				tmp2 = (tmp2 / 625) * 625;
-		}
-	}
-
-	if (tmp1 < 0)
-		data = (u16)(-tmp1);
-	else
-		data = (u16)tmp1;
-
-	if (chip->config & ADT7410_RESOLUTION) {
-		data = (data << ADT7410_T16_VALUE_FLOAT_OFFSET) |
-			(tmp2 & ADT7410_T16_VALUE_FLOAT_MASK);
-
-		if (tmp1 < 0)
-			/* convert positive value to supplyment */
-			data = (u16)((ADT7410_T16_VALUE_SIGN << 1) - (u32)data);
-	} else {
-		data = (data << ADT7410_T13_VALUE_FLOAT_OFFSET) |
-			(tmp2 & ADT7410_T13_VALUE_FLOAT_MASK);
-
-		if (tmp1 < 0)
-			/* convert positive value to supplyment */
-			data = (ADT7410_T13_VALUE_SIGN << 1) - data;
-		data <<= ADT7410_T13_VALUE_OFFSET;
-	}
-
-	ret = adt7410_write_word(chip, bound_reg, data);
-	if (ret)
-		return -EIO;
-
-	return ret;
-}
-
-static ssize_t adt7410_show_t_alarm_high(struct device *dev,
-		struct device_attribute *attr,
-		char *buf)
-{
-	return adt7410_show_t_bound(dev, attr,
-			ADT7410_T_ALARM_HIGH, buf);
-}
-
-static inline ssize_t adt7410_set_t_alarm_high(struct device *dev,
-		struct device_attribute *attr,
-		const char *buf,
-		size_t len)
-{
-	return adt7410_set_t_bound(dev, attr,
-			ADT7410_T_ALARM_HIGH, buf, len);
-}
-
-static ssize_t adt7410_show_t_alarm_low(struct device *dev,
-		struct device_attribute *attr,
-		char *buf)
-{
-	return adt7410_show_t_bound(dev, attr,
-			ADT7410_T_ALARM_LOW, buf);
-}
-
-static inline ssize_t adt7410_set_t_alarm_low(struct device *dev,
-		struct device_attribute *attr,
-		const char *buf,
-		size_t len)
-{
-	return adt7410_set_t_bound(dev, attr,
-			ADT7410_T_ALARM_LOW, buf, len);
-}
-
-static ssize_t adt7410_show_t_crit(struct device *dev,
-		struct device_attribute *attr,
-		char *buf)
-{
-	return adt7410_show_t_bound(dev, attr,
-			ADT7410_T_CRIT, buf);
-}
-
-static inline ssize_t adt7410_set_t_crit(struct device *dev,
-		struct device_attribute *attr,
-		const char *buf,
-		size_t len)
-{
-	return adt7410_set_t_bound(dev, attr,
-			ADT7410_T_CRIT, buf, len);
-}
-
-static ssize_t adt7410_show_t_hyst(struct device *dev,
-		struct device_attribute *attr,
-		char *buf)
-{
-	struct iio_dev *dev_info = dev_to_iio_dev(dev);
-	struct adt7410_chip_info *chip = iio_priv(dev_info);
-	int ret;
-	u8 t_hyst;
-
-	ret = adt7410_read_byte(chip, ADT7410_T_HYST, &t_hyst);
-	if (ret)
-		return -EIO;
-
-	return sprintf(buf, "%d\n", t_hyst & ADT7410_T_HYST_MASK);
-}
-
-static inline ssize_t adt7410_set_t_hyst(struct device *dev,
-		struct device_attribute *attr,
-		const char *buf,
-		size_t len)
-{
-	struct iio_dev *dev_info = dev_to_iio_dev(dev);
-	struct adt7410_chip_info *chip = iio_priv(dev_info);
-	int ret;
-	unsigned long data;
-	u8 t_hyst;
-
-	ret = strict_strtol(buf, 10, &data);
-
-	if (ret || data > ADT7410_T_HYST_MASK)
-		return -EINVAL;
-
-	t_hyst = (u8)data;
-
-	ret = adt7410_write_byte(chip, ADT7410_T_HYST, t_hyst);
-	if (ret)
-		return -EIO;
-
-	return ret;
-}
-
-static IIO_DEVICE_ATTR(event_mode,
-		       S_IRUGO | S_IWUSR,
-		       adt7410_show_event_mode, adt7410_set_event_mode, 0);
-static IIO_DEVICE_ATTR(available_event_modes,
-		       S_IRUGO,
-		       adt7410_show_available_event_modes, NULL, 0);
-static IIO_DEVICE_ATTR(fault_queue,
-		       S_IRUGO | S_IWUSR,
-		       adt7410_show_fault_queue, adt7410_set_fault_queue, 0);
-static IIO_DEVICE_ATTR(t_alarm_high,
-		       S_IRUGO | S_IWUSR,
-		       adt7410_show_t_alarm_high, adt7410_set_t_alarm_high, 0);
-static IIO_DEVICE_ATTR(t_alarm_low,
-		       S_IRUGO | S_IWUSR,
-		       adt7410_show_t_alarm_low, adt7410_set_t_alarm_low, 0);
-static IIO_DEVICE_ATTR(t_crit,
-		       S_IRUGO | S_IWUSR,
-		       adt7410_show_t_crit, adt7410_set_t_crit, 0);
-static IIO_DEVICE_ATTR(t_hyst,
-		       S_IRUGO | S_IWUSR,
-		       adt7410_show_t_hyst, adt7410_set_t_hyst, 0);
-
-static struct attribute *adt7410_event_int_attributes[] = {
-	&iio_dev_attr_event_mode.dev_attr.attr,
-	&iio_dev_attr_available_event_modes.dev_attr.attr,
-	&iio_dev_attr_fault_queue.dev_attr.attr,
-	&iio_dev_attr_t_alarm_high.dev_attr.attr,
-	&iio_dev_attr_t_alarm_low.dev_attr.attr,
-	&iio_dev_attr_t_crit.dev_attr.attr,
-	&iio_dev_attr_t_hyst.dev_attr.attr,
-	NULL,
-};
-
-static struct attribute_group adt7410_event_attribute_group = {
-	.attrs = adt7410_event_int_attributes,
-	.name = "events",
-};
-
-static const struct iio_info adt7410_info = {
-	.attrs = &adt7410_attribute_group,
-	.event_attrs = &adt7410_event_attribute_group,
-	.driver_module = THIS_MODULE,
-};
-
-/*
- * device probe and remove
- */
-
-static int adt7410_probe(struct device *dev, int irq,
-	const char *name, const struct adt7410_ops *ops)
-{
-	unsigned long *adt7410_platform_data = dev->platform_data;
-	unsigned long local_pdata[] = {0, 0};
-	struct adt7410_chip_info *chip;
-	struct iio_dev *indio_dev;
-	int ret = 0;
-
-	indio_dev = iio_device_alloc(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, indio_dev);
-
-	chip->dev = dev;
-	chip->ops = ops;
-
-	indio_dev->name = name;
-	indio_dev->dev.parent = dev;
-	indio_dev->info = &adt7410_info;
-	indio_dev->modes = INDIO_DIRECT_MODE;
-
-	if (!adt7410_platform_data)
-		adt7410_platform_data = local_pdata;
-
-	/* CT critcal temperature event. line 0 */
-	if (irq) {
-		ret = request_threaded_irq(irq,
-					   NULL,
-					   &adt7410_event_handler,
-					   IRQF_TRIGGER_LOW | IRQF_ONESHOT,
-					   name,
-					   indio_dev);
-		if (ret)
-			goto error_free_dev;
-	}
-
-	/* INT bound temperature alarm event. line 1 */
-	if (adt7410_platform_data[0]) {
-		ret = request_threaded_irq(adt7410_platform_data[0],
-					   NULL,
-					   &adt7410_event_handler,
-					   adt7410_platform_data[1] |
-					   IRQF_ONESHOT,
-					   name,
-					   indio_dev);
-		if (ret)
-			goto error_unreg_ct_irq;
-	}
-
-	ret = adt7410_read_byte(chip, ADT7410_CONFIG, &chip->config);
-	if (ret) {
-		ret = -EIO;
-		goto error_unreg_int_irq;
-	}
-
-	chip->config |= ADT7410_RESOLUTION;
-
-	if (irq && adt7410_platform_data[0]) {
-
-		/* set irq polarity low level */
-		chip->config &= ~ADT7410_CT_POLARITY;
-
-		if (adt7410_platform_data[1] & IRQF_TRIGGER_HIGH)
-			chip->config |= ADT7410_INT_POLARITY;
-		else
-			chip->config &= ~ADT7410_INT_POLARITY;
-	}
-
-	ret = adt7410_write_byte(chip, ADT7410_CONFIG, chip->config);
-	if (ret) {
-		ret = -EIO;
-		goto error_unreg_int_irq;
-	}
-	ret = iio_device_register(indio_dev);
-	if (ret)
-		goto error_unreg_int_irq;
-
-	dev_info(dev, "%s temperature sensor registered.\n",
-			 name);
-
-	return 0;
-
-error_unreg_int_irq:
-	free_irq(adt7410_platform_data[0], indio_dev);
-error_unreg_ct_irq:
-	free_irq(irq, indio_dev);
-error_free_dev:
-	iio_device_free(indio_dev);
-error_ret:
-	return ret;
-}
-
-static int adt7410_remove(struct device *dev, int irq)
-{
-	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	unsigned long *adt7410_platform_data = dev->platform_data;
-
-	iio_device_unregister(indio_dev);
-	if (adt7410_platform_data[0])
-		free_irq(adt7410_platform_data[0], indio_dev);
-	if (irq)
-		free_irq(irq, indio_dev);
-	iio_device_free(indio_dev);
-
-	return 0;
-}
-
-#if IS_ENABLED(CONFIG_I2C)
-
-static int adt7410_i2c_read_word(struct adt7410_chip_info *chip, u8 reg,
-	u16 *data)
-{
-	struct i2c_client *client = to_i2c_client(chip->dev);
-	int ret = 0;
-
-	ret = i2c_smbus_read_word_data(client, reg);
-	if (ret < 0) {
-		dev_err(&client->dev, "I2C read error\n");
-		return ret;
-	}
-
-	*data = swab16((u16)ret);
-
-	return 0;
-}
-
-static int adt7410_i2c_write_word(struct adt7410_chip_info *chip, u8 reg,
-	u16 data)
-{
-	struct i2c_client *client = to_i2c_client(chip->dev);
-	int ret = 0;
-
-	ret = i2c_smbus_write_word_data(client, reg, swab16(data));
-	if (ret < 0)
-		dev_err(&client->dev, "I2C write error\n");
-
-	return ret;
-}
-
-static int adt7410_i2c_read_byte(struct adt7410_chip_info *chip, u8 reg,
-	u8 *data)
-{
-	struct i2c_client *client = to_i2c_client(chip->dev);
-	int ret = 0;
-
-	ret = i2c_smbus_read_byte_data(client, reg);
-	if (ret < 0) {
-		dev_err(&client->dev, "I2C read error\n");
-		return ret;
-	}
-
-	*data = (u8)ret;
-
-	return 0;
-}
-
-static int adt7410_i2c_write_byte(struct adt7410_chip_info *chip, u8 reg,
-	u8 data)
-{
-	struct i2c_client *client = to_i2c_client(chip->dev);
-	int ret = 0;
-
-	ret = i2c_smbus_write_byte_data(client, reg, data);
-	if (ret < 0)
-		dev_err(&client->dev, "I2C write error\n");
-
-	return ret;
-}
-
-static const struct adt7410_ops adt7410_i2c_ops = {
-	.read_word = adt7410_i2c_read_word,
-	.write_word = adt7410_i2c_write_word,
-	.read_byte = adt7410_i2c_read_byte,
-	.write_byte = adt7410_i2c_write_byte,
-};
-
-static int adt7410_i2c_probe(struct i2c_client *client,
-	const struct i2c_device_id *id)
-{
-	return adt7410_probe(&client->dev, client->irq, id->name,
-		&adt7410_i2c_ops);
-}
-
-static int adt7410_i2c_remove(struct i2c_client *client)
-{
-	return adt7410_remove(&client->dev, client->irq);
-}
-
-static const struct i2c_device_id adt7410_id[] = {
-	{ "adt7410", 0 },
-	{}
-};
-
-MODULE_DEVICE_TABLE(i2c, adt7410_id);
-
-static struct i2c_driver adt7410_driver = {
-	.driver = {
-		.name = "adt7410",
-	},
-	.probe = adt7410_i2c_probe,
-	.remove = adt7410_i2c_remove,
-	.id_table = adt7410_id,
-};
-
-static int __init adt7410_i2c_init(void)
-{
-	return i2c_add_driver(&adt7410_driver);
-}
-
-static void __exit adt7410_i2c_exit(void)
-{
-	i2c_del_driver(&adt7410_driver);
-}
-
-#else
-
-static int  __init adt7410_i2c_init(void) { return 0; };
-static void __exit adt7410_i2c_exit(void) {};
-
-#endif
-
-#if IS_ENABLED(CONFIG_SPI_MASTER)
-
-static const u8 adt7371_reg_table[] = {
-	[ADT7410_TEMPERATURE]   = ADT7310_TEMPERATURE,
-	[ADT7410_STATUS]	= ADT7310_STATUS,
-	[ADT7410_CONFIG]	= ADT7310_CONFIG,
-	[ADT7410_T_ALARM_HIGH]	= ADT7310_T_ALARM_HIGH,
-	[ADT7410_T_ALARM_LOW]	= ADT7310_T_ALARM_LOW,
-	[ADT7410_T_CRIT]	= ADT7310_T_CRIT,
-	[ADT7410_T_HYST]	= ADT7310_T_HYST,
-	[ADT7410_ID]		= ADT7310_ID,
-};
-
-#define AD7310_COMMAND(reg) (adt7371_reg_table[(reg)] << ADT7310_CMD_REG_OFFSET)
-
-static int adt7310_spi_read_word(struct adt7410_chip_info *chip,
-	u8 reg, u16 *data)
-{
-	struct spi_device *spi = to_spi_device(chip->dev);
-	u8 command = AD7310_COMMAND(reg);
-	int ret = 0;
-
-	command |= ADT7310_CMD_READ;
-	ret = spi_write(spi, &command, sizeof(command));
-	if (ret < 0) {
-		dev_err(&spi->dev, "SPI write command error\n");
-		return ret;
-	}
-
-	ret = spi_read(spi, (u8 *)data, sizeof(*data));
-	if (ret < 0) {
-		dev_err(&spi->dev, "SPI read word error\n");
-		return ret;
-	}
-
-	*data = be16_to_cpu(*data);
-
-	return 0;
-}
-
-static int adt7310_spi_write_word(struct adt7410_chip_info *chip, u8 reg,
-	u16 data)
-{
-	struct spi_device *spi = to_spi_device(chip->dev);
-	u8 buf[3];
-	int ret = 0;
-
-	buf[0] = AD7310_COMMAND(reg);
-	buf[1] = (u8)(data >> 8);
-	buf[2] = (u8)(data & 0xFF);
-
-	ret = spi_write(spi, buf, 3);
-	if (ret < 0) {
-		dev_err(&spi->dev, "SPI write word error\n");
-		return ret;
-	}
-
-	return ret;
-}
-
-static int adt7310_spi_read_byte(struct adt7410_chip_info *chip, u8 reg,
-	u8 *data)
-{
-	struct spi_device *spi = to_spi_device(chip->dev);
-	u8 command = AD7310_COMMAND(reg);
-	int ret = 0;
-
-	command |= ADT7310_CMD_READ;
-	ret = spi_write(spi, &command, sizeof(command));
-	if (ret < 0) {
-		dev_err(&spi->dev, "SPI write command error\n");
-		return ret;
-	}
-
-	ret = spi_read(spi, data, sizeof(*data));
-	if (ret < 0) {
-		dev_err(&spi->dev, "SPI read byte error\n");
-		return ret;
-	}
-
-	return 0;
-}
-
-static int adt7310_spi_write_byte(struct adt7410_chip_info *chip, u8 reg,
-	u8 data)
-{
-	struct spi_device *spi = to_spi_device(chip->dev);
-	u8 buf[2];
-	int ret = 0;
-
-	buf[0] = AD7310_COMMAND(reg);
-	buf[1] = data;
-
-	ret = spi_write(spi, buf, 2);
-	if (ret < 0) {
-		dev_err(&spi->dev, "SPI write byte error\n");
-		return ret;
-	}
-
-	return ret;
-}
-
-static const struct adt7410_ops adt7310_spi_ops = {
-	.read_word = adt7310_spi_read_word,
-	.write_word = adt7310_spi_write_word,
-	.read_byte = adt7310_spi_read_byte,
-	.write_byte = adt7310_spi_write_byte,
-};
-
-static int adt7310_spi_probe(struct spi_device *spi)
-{
-	return adt7410_probe(&spi->dev, spi->irq,
-		spi_get_device_id(spi)->name, &adt7310_spi_ops);
-}
-
-static int adt7310_spi_remove(struct spi_device *spi)
-{
-	return adt7410_remove(&spi->dev, spi->irq);
-}
-
-static const struct spi_device_id adt7310_id[] = {
-	{ "adt7310", 0 },
-	{}
-};
-MODULE_DEVICE_TABLE(spi, adt7310_id);
-
-static struct spi_driver adt7310_driver = {
-	.driver = {
-		.name = "adt7310",
-		.owner = THIS_MODULE,
-	},
-	.probe = adt7310_spi_probe,
-	.remove = adt7310_spi_remove,
-	.id_table = adt7310_id,
-};
-
-static int __init adt7310_spi_init(void)
-{
-	return spi_register_driver(&adt7310_driver);
-}
-
-static void adt7310_spi_exit(void)
-{
-	spi_unregister_driver(&adt7310_driver);
-}
-
-#else
-
-static int __init adt7310_spi_init(void) { return 0; };
-static void adt7310_spi_exit(void) {};
-
-#endif
-
-static int __init adt7410_init(void)
-{
-	int ret;
-
-	ret = adt7310_spi_init();
-	if (ret)
-		return ret;
-
-	ret = adt7410_i2c_init();
-	if (ret)
-		adt7310_spi_exit();
-
-	return ret;
-}
-module_init(adt7410_init);
-
-static void __exit adt7410_exit(void)
-{
-	adt7410_i2c_exit();
-	adt7310_spi_exit();
-}
-module_exit(adt7410_exit);
-
-MODULE_AUTHOR("Sonic Zhang <sonic.zhang@analog.com>");
-MODULE_DESCRIPTION("Analog Devices ADT7310/ADT7410 digital temperature sensor driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/iio/adc/lpc32xx_adc.c b/drivers/staging/iio/adc/lpc32xx_adc.c
index 0bf2a6c..2f2f7fd 100644
--- a/drivers/staging/iio/adc/lpc32xx_adc.c
+++ b/drivers/staging/iio/adc/lpc32xx_adc.c
@@ -103,7 +103,7 @@ static const struct iio_info lpc32xx_adc_iio_info = {
 	.type = IIO_VOLTAGE,				\
 	.indexed = 1,					\
 	.channel = _index,				\
-	.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,	\
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),	\
 	.address = AD_IN * _index,			\
 	.scan_index = _index,				\
 }
diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c
index 55a459b..2856b8f 100644
--- a/drivers/staging/iio/adc/mxs-lradc.c
+++ b/drivers/staging/iio/adc/mxs-lradc.c
@@ -36,9 +36,6 @@
 #include <linux/delay.h>
 #include <linux/input.h>
 
-#include <mach/mxs.h>
-#include <mach/common.h>
-
 #include <linux/iio/iio.h>
 #include <linux/iio/buffer.h>
 #include <linux/iio/trigger.h>
@@ -646,7 +643,7 @@ static irqreturn_t mxs_lradc_trigger_handler(int irq, void *p)
 
 static int mxs_lradc_configure_trigger(struct iio_trigger *trig, bool state)
 {
-	struct iio_dev *iio = trig->private_data;
+	struct iio_dev *iio = iio_trigger_get_drvdata(trig);
 	struct mxs_lradc *lradc = iio_priv(iio);
 	const uint32_t st = state ? STMP_OFFSET_REG_SET : STMP_OFFSET_REG_CLR;
 
@@ -670,7 +667,7 @@ static int mxs_lradc_trigger_init(struct iio_dev *iio)
 		return -ENOMEM;
 
 	trig->dev.parent = iio->dev.parent;
-	trig->private_data = iio;
+	iio_trigger_set_drvdata(trig, iio);
 	trig->ops = &mxs_lradc_trigger_ops;
 
 	ret = iio_trigger_register(trig);
@@ -822,7 +819,7 @@ static const struct iio_buffer_setup_ops mxs_lradc_buffer_ops = {
 	.type = (chan_type),					\
 	.indexed = 1,						\
 	.scan_index = (idx),					\
-	.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,		\
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\
 	.channel = (idx),					\
 	.scan_type = {						\
 		.sign = 'u',					\
@@ -983,6 +980,9 @@ static int mxs_lradc_probe(struct platform_device *pdev)
 	if (ret)
 		goto err_trig;
 
+	/* Configure the hardware. */
+	mxs_lradc_hw_init(lradc);
+
 	/* Register the touchscreen input device. */
 	ret = mxs_lradc_ts_register(lradc);
 	if (ret)
@@ -995,9 +995,6 @@ static int mxs_lradc_probe(struct platform_device *pdev)
 		goto err_ts;
 	}
 
-	/* Configure the hardware. */
-	mxs_lradc_hw_init(lradc);
-
 	return 0;
 
 err_ts:
diff --git a/drivers/staging/iio/adc/spear_adc.c b/drivers/staging/iio/adc/spear_adc.c
index 13052ce..f45da42 100644
--- a/drivers/staging/iio/adc/spear_adc.c
+++ b/drivers/staging/iio/adc/spear_adc.c
@@ -180,8 +180,8 @@ static int spear_read_raw(struct iio_dev *indio_dev,
 #define SPEAR_ADC_CHAN(idx) {				\
 	.type = IIO_VOLTAGE,				\
 	.indexed = 1,					\
-	.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |	\
-	IIO_CHAN_INFO_SCALE_SHARED_BIT,			\
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),	\
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),	\
 	.channel = idx,					\
 	.scan_type = {					\
 		.sign = 'u',				\
diff --git a/drivers/staging/iio/cdc/ad7150.c b/drivers/staging/iio/cdc/ad7150.c
index 3c608c1..687dd2c 100644
--- a/drivers/staging/iio/cdc/ad7150.c
+++ b/drivers/staging/iio/cdc/ad7150.c
@@ -429,8 +429,8 @@ static const struct iio_chan_spec ad7150_channels[] = {
 		.type = IIO_CAPACITANCE,
 		.indexed = 1,
 		.channel = 0,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-		IIO_CHAN_INFO_AVERAGE_RAW_SEPARATE_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+		BIT(IIO_CHAN_INFO_AVERAGE_RAW),
 		.event_mask =
 		IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING) |
 		IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING) |
@@ -442,8 +442,8 @@ static const struct iio_chan_spec ad7150_channels[] = {
 		.type = IIO_CAPACITANCE,
 		.indexed = 1,
 		.channel = 1,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-		IIO_CHAN_INFO_AVERAGE_RAW_SEPARATE_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+		BIT(IIO_CHAN_INFO_AVERAGE_RAW),
 		.event_mask =
 		IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING) |
 		IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING) |
diff --git a/drivers/staging/iio/cdc/ad7152.c b/drivers/staging/iio/cdc/ad7152.c
index 3c92ba3..1d7c528 100644
--- a/drivers/staging/iio/cdc/ad7152.c
+++ b/drivers/staging/iio/cdc/ad7152.c
@@ -436,38 +436,38 @@ static const struct iio_chan_spec ad7152_channels[] = {
 		.type = IIO_CAPACITANCE,
 		.indexed = 1,
 		.channel = 0,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-		IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT |
-		IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
-		IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+		BIT(IIO_CHAN_INFO_CALIBSCALE) |
+		BIT(IIO_CHAN_INFO_CALIBBIAS) |
+		BIT(IIO_CHAN_INFO_SCALE),
 	}, {
 		.type = IIO_CAPACITANCE,
 		.differential = 1,
 		.indexed = 1,
 		.channel = 0,
 		.channel2 = 2,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-		IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT |
-		IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
-		IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+		BIT(IIO_CHAN_INFO_CALIBSCALE) |
+		BIT(IIO_CHAN_INFO_CALIBBIAS) |
+		BIT(IIO_CHAN_INFO_SCALE),
 	}, {
 		.type = IIO_CAPACITANCE,
 		.indexed = 1,
 		.channel = 1,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-		IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT |
-		IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
-		IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+		BIT(IIO_CHAN_INFO_CALIBSCALE) |
+		BIT(IIO_CHAN_INFO_CALIBBIAS) |
+		BIT(IIO_CHAN_INFO_SCALE),
 	}, {
 		.type = IIO_CAPACITANCE,
 		.differential = 1,
 		.indexed = 1,
 		.channel = 1,
 		.channel2 = 3,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-		IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT |
-		IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
-		IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+		BIT(IIO_CHAN_INFO_CALIBSCALE) |
+		BIT(IIO_CHAN_INFO_CALIBBIAS) |
+		BIT(IIO_CHAN_INFO_SCALE),
 	}
 };
 /*
diff --git a/drivers/staging/iio/cdc/ad7746.c b/drivers/staging/iio/cdc/ad7746.c
index 466b82e..94f9ca7 100644
--- a/drivers/staging/iio/cdc/ad7746.c
+++ b/drivers/staging/iio/cdc/ad7746.c
@@ -123,8 +123,8 @@ static const struct iio_chan_spec ad7746_channels[] = {
 		.type = IIO_VOLTAGE,
 		.indexed = 1,
 		.channel = 0,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-		IIO_CHAN_INFO_SCALE_SHARED_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
 		.address = AD7746_REG_VT_DATA_HIGH << 8 |
 			AD7746_VTSETUP_VTMD_EXT_VIN,
 	},
@@ -133,8 +133,8 @@ static const struct iio_chan_spec ad7746_channels[] = {
 		.indexed = 1,
 		.channel = 1,
 		.extend_name = "supply",
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-		IIO_CHAN_INFO_SCALE_SHARED_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
 		.address = AD7746_REG_VT_DATA_HIGH << 8 |
 			AD7746_VTSETUP_VTMD_VDD_MON,
 	},
@@ -142,7 +142,7 @@ static const struct iio_chan_spec ad7746_channels[] = {
 		.type = IIO_TEMP,
 		.indexed = 1,
 		.channel = 0,
-		.info_mask = IIO_CHAN_INFO_PROCESSED_SEPARATE_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
 		.address = AD7746_REG_VT_DATA_HIGH << 8 |
 			AD7746_VTSETUP_VTMD_INT_TEMP,
 	},
@@ -150,7 +150,7 @@ static const struct iio_chan_spec ad7746_channels[] = {
 		.type = IIO_TEMP,
 		.indexed = 1,
 		.channel = 1,
-		.info_mask = IIO_CHAN_INFO_PROCESSED_SEPARATE_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
 		.address = AD7746_REG_VT_DATA_HIGH << 8 |
 			AD7746_VTSETUP_VTMD_EXT_TEMP,
 	},
@@ -158,11 +158,10 @@ static const struct iio_chan_spec ad7746_channels[] = {
 		.type = IIO_CAPACITANCE,
 		.indexed = 1,
 		.channel = 0,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-		IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT |
-		IIO_CHAN_INFO_CALIBBIAS_SHARED_BIT |
-		IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |
-		IIO_CHAN_INFO_SCALE_SHARED_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+		BIT(IIO_CHAN_INFO_CALIBSCALE) | BIT(IIO_CHAN_INFO_OFFSET),
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_CALIBBIAS) |
+		BIT(IIO_CHAN_INFO_SCALE),
 		.address = AD7746_REG_CAP_DATA_HIGH << 8,
 	},
 	[CIN1_DIFF] = {
@@ -171,11 +170,10 @@ static const struct iio_chan_spec ad7746_channels[] = {
 		.indexed = 1,
 		.channel = 0,
 		.channel2 = 2,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-		IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT |
-		IIO_CHAN_INFO_CALIBBIAS_SHARED_BIT |
-		IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |
-		IIO_CHAN_INFO_SCALE_SHARED_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+		BIT(IIO_CHAN_INFO_CALIBSCALE) | BIT(IIO_CHAN_INFO_OFFSET),
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_CALIBBIAS) |
+		BIT(IIO_CHAN_INFO_SCALE),
 		.address = AD7746_REG_CAP_DATA_HIGH << 8 |
 			AD7746_CAPSETUP_CAPDIFF
 	},
@@ -183,11 +181,10 @@ static const struct iio_chan_spec ad7746_channels[] = {
 		.type = IIO_CAPACITANCE,
 		.indexed = 1,
 		.channel = 1,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-		IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT |
-		IIO_CHAN_INFO_CALIBBIAS_SHARED_BIT |
-		IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |
-		IIO_CHAN_INFO_SCALE_SHARED_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+		BIT(IIO_CHAN_INFO_CALIBSCALE) | BIT(IIO_CHAN_INFO_OFFSET),
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_CALIBBIAS) |
+		BIT(IIO_CHAN_INFO_SCALE),
 		.address = AD7746_REG_CAP_DATA_HIGH << 8 |
 			AD7746_CAPSETUP_CIN2,
 	},
@@ -197,11 +194,10 @@ static const struct iio_chan_spec ad7746_channels[] = {
 		.indexed = 1,
 		.channel = 1,
 		.channel2 = 3,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-		IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT |
-		IIO_CHAN_INFO_CALIBBIAS_SHARED_BIT |
-		IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |
-		IIO_CHAN_INFO_SCALE_SHARED_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+		BIT(IIO_CHAN_INFO_CALIBSCALE) | BIT(IIO_CHAN_INFO_OFFSET),
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_CALIBBIAS) |
+		BIT(IIO_CHAN_INFO_SCALE),
 		.address = AD7746_REG_CAP_DATA_HIGH << 8 |
 			AD7746_CAPSETUP_CAPDIFF | AD7746_CAPSETUP_CIN2,
 	}
diff --git a/drivers/staging/iio/gyro/adis16060_core.c b/drivers/staging/iio/gyro/adis16060_core.c
index 687c151..c67d3a8 100644
--- a/drivers/staging/iio/gyro/adis16060_core.c
+++ b/drivers/staging/iio/gyro/adis16060_core.c
@@ -120,27 +120,26 @@ static const struct iio_chan_spec adis16060_channels[] = {
 		.type = IIO_ANGL_VEL,
 		.modified = 1,
 		.channel2 = IIO_MOD_Z,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
 		.address = ADIS16060_GYRO,
 	}, {
 		.type = IIO_VOLTAGE,
 		.indexed = 1,
 		.channel = 0,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
 		.address = ADIS16060_AIN1,
 	}, {
 		.type = IIO_VOLTAGE,
 		.indexed = 1,
 		.channel = 1,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
 		.address = ADIS16060_AIN2,
 	}, {
 		.type = IIO_TEMP,
 		.indexed = 1,
 		.channel = 0,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-		IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |
-		IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+		BIT(IIO_CHAN_INFO_OFFSET) | BIT(IIO_CHAN_INFO_SCALE),
 		.address = ADIS16060_TEMP_OUT,
 	}
 };
diff --git a/drivers/staging/iio/gyro/adis16130_core.c b/drivers/staging/iio/gyro/adis16130_core.c
index 835801e..531b803 100644
--- a/drivers/staging/iio/gyro/adis16130_core.c
+++ b/drivers/staging/iio/gyro/adis16130_core.c
@@ -100,13 +100,13 @@ static const struct iio_chan_spec adis16130_channels[] = {
 		.type = IIO_ANGL_VEL,
 		.modified = 1,
 		.channel2 = IIO_MOD_Z,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
 		.address = ADIS16130_RATEDATA,
 	}, {
 		.type = IIO_TEMP,
 		.indexed = 1,
 		.channel = 0,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
 		.address = ADIS16130_TEMPDATA,
 	}
 };
diff --git a/drivers/staging/iio/gyro/adis16260_core.c b/drivers/staging/iio/gyro/adis16260_core.c
index 6e80b8c..620d63f 100644
--- a/drivers/staging/iio/gyro/adis16260_core.c
+++ b/drivers/staging/iio/gyro/adis16260_core.c
@@ -124,8 +124,8 @@ static IIO_DEVICE_ATTR(sampling_frequency_available,
 #define ADIS16260_GYRO_CHANNEL_SET(axis, mod)				\
 struct iio_chan_spec adis16260_channels_##axis[] = {		\
 	ADIS_GYRO_CHAN(mod, ADIS16260_GYRO_OUT, ADIS16260_SCAN_GYRO, \
-		IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | \
-		IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT, 14), \
+		BIT(IIO_CHAN_INFO_CALIBBIAS) | \
+		BIT(IIO_CHAN_INFO_CALIBSCALE), 14), \
 	ADIS_INCLI_CHAN(mod, ADIS16260_ANGL_OUT, ADIS16260_SCAN_ANGL, 0, 14), \
 	ADIS_TEMP_CHAN(ADIS16260_TEMP_OUT, ADIS16260_SCAN_TEMP, 12), \
 	ADIS_SUPPLY_CHAN(ADIS16260_SUPPLY_OUT, ADIS16260_SCAN_SUPPLY, 12), \
diff --git a/drivers/staging/iio/iio_hwmon.c b/drivers/staging/iio/iio_hwmon.c
deleted file mode 100644
index 93af756..0000000
--- a/drivers/staging/iio/iio_hwmon.c
+++ /dev/null
@@ -1,190 +0,0 @@
-/* Hwmon client for industrial I/O devices
- *
- * Copyright (c) 2011 Jonathan Cameron
- *
- * This program is free software; you can 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/slab.h>
-#include <linux/module.h>
-#include <linux/err.h>
-#include <linux/platform_device.h>
-#include <linux/hwmon.h>
-#include <linux/hwmon-sysfs.h>
-#include <linux/iio/consumer.h>
-#include <linux/iio/types.h>
-
-/**
- * struct iio_hwmon_state - device instance state
- * @channels:		filled with array of channels from iio
- * @num_channels:	number of channels in channels (saves counting twice)
- * @hwmon_dev:		associated hwmon device
- * @attr_group:	the group of attributes
- * @attrs:		null terminated array of attribute pointers.
- */
-struct iio_hwmon_state {
-	struct iio_channel *channels;
-	int num_channels;
-	struct device *hwmon_dev;
-	struct attribute_group attr_group;
-	struct attribute **attrs;
-};
-
-/*
- * Assumes that IIO and hwmon operate in the same base units.
- * This is supposed to be true, but needs verification for
- * new channel types.
- */
-static ssize_t iio_hwmon_read_val(struct device *dev,
-				  struct device_attribute *attr,
-				  char *buf)
-{
-	int result;
-	int ret;
-	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
-	struct iio_hwmon_state *state = dev_get_drvdata(dev);
-
-	ret = iio_read_channel_processed(&state->channels[sattr->index],
-					&result);
-	if (ret < 0)
-		return ret;
-
-	return sprintf(buf, "%d\n", result);
-}
-
-static ssize_t show_name(struct device *dev, struct device_attribute *attr,
-			 char *buf)
-{
-	return sprintf(buf, "iio_hwmon\n");
-}
-
-static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
-
-static int iio_hwmon_probe(struct platform_device *pdev)
-{
-	struct device *dev = &pdev->dev;
-	struct iio_hwmon_state *st;
-	struct sensor_device_attribute *a;
-	int ret, i;
-	int in_i = 1, temp_i = 1, curr_i = 1;
-	enum iio_chan_type type;
-	struct iio_channel *channels;
-
-	channels = iio_channel_get_all(dev);
-	if (IS_ERR(channels))
-		return PTR_ERR(channels);
-
-	st = devm_kzalloc(dev, sizeof(*st), GFP_KERNEL);
-	if (st == NULL)
-		return -ENOMEM;
-
-	st->channels = channels;
-
-	/* count how many attributes we have */
-	while (st->channels[st->num_channels].indio_dev)
-		st->num_channels++;
-
-	st->attrs = devm_kzalloc(dev,
-				 sizeof(*st->attrs) * (st->num_channels + 2),
-				 GFP_KERNEL);
-	if (st->attrs == NULL) {
-		ret = -ENOMEM;
-		goto error_release_channels;
-	}
-
-	for (i = 0; i < st->num_channels; i++) {
-		a = devm_kzalloc(dev, sizeof(*a), GFP_KERNEL);
-		if (a == NULL) {
-			ret = -ENOMEM;
-			goto error_release_channels;
-		}
-
-		sysfs_attr_init(&a->dev_attr.attr);
-		ret = iio_get_channel_type(&st->channels[i], &type);
-		if (ret < 0)
-			goto error_release_channels;
-
-		switch (type) {
-		case IIO_VOLTAGE:
-			a->dev_attr.attr.name = kasprintf(GFP_KERNEL,
-							  "in%d_input",
-							  in_i++);
-			break;
-		case IIO_TEMP:
-			a->dev_attr.attr.name = kasprintf(GFP_KERNEL,
-							  "temp%d_input",
-							  temp_i++);
-			break;
-		case IIO_CURRENT:
-			a->dev_attr.attr.name = kasprintf(GFP_KERNEL,
-							  "curr%d_input",
-							  curr_i++);
-			break;
-		default:
-			ret = -EINVAL;
-			goto error_release_channels;
-		}
-		if (a->dev_attr.attr.name == NULL) {
-			ret = -ENOMEM;
-			goto error_release_channels;
-		}
-		a->dev_attr.show = iio_hwmon_read_val;
-		a->dev_attr.attr.mode = S_IRUGO;
-		a->index = i;
-		st->attrs[i] = &a->dev_attr.attr;
-	}
-	st->attrs[st->num_channels] = &dev_attr_name.attr;
-	st->attr_group.attrs = st->attrs;
-	platform_set_drvdata(pdev, st);
-	ret = sysfs_create_group(&dev->kobj, &st->attr_group);
-	if (ret < 0)
-		goto error_release_channels;
-
-	st->hwmon_dev = hwmon_device_register(dev);
-	if (IS_ERR(st->hwmon_dev)) {
-		ret = PTR_ERR(st->hwmon_dev);
-		goto error_remove_group;
-	}
-	return 0;
-
-error_remove_group:
-	sysfs_remove_group(&dev->kobj, &st->attr_group);
-error_release_channels:
-	iio_channel_release_all(st->channels);
-	return ret;
-}
-
-static int iio_hwmon_remove(struct platform_device *pdev)
-{
-	struct iio_hwmon_state *st = platform_get_drvdata(pdev);
-
-	hwmon_device_unregister(st->hwmon_dev);
-	sysfs_remove_group(&pdev->dev.kobj, &st->attr_group);
-	iio_channel_release_all(st->channels);
-
-	return 0;
-}
-
-static struct of_device_id iio_hwmon_of_match[] = {
-	{ .compatible = "iio-hwmon", },
-	{ }
-};
-
-static struct platform_driver __refdata iio_hwmon_driver = {
-	.driver = {
-		.name = "iio_hwmon",
-		.owner = THIS_MODULE,
-		.of_match_table = iio_hwmon_of_match,
-	},
-	.probe = iio_hwmon_probe,
-	.remove = iio_hwmon_remove,
-};
-
-module_platform_driver(iio_hwmon_driver);
-
-MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>");
-MODULE_DESCRIPTION("IIO to hwmon driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/iio/iio_simple_dummy.c b/drivers/staging/iio/iio_simple_dummy.c
index aee76c7..0193e17 100644
--- a/drivers/staging/iio/iio_simple_dummy.c
+++ b/drivers/staging/iio/iio_simple_dummy.c
@@ -71,25 +71,25 @@ static const struct iio_chan_spec iio_dummy_channels[] = {
 		.indexed = 1,
 		.channel = 0,
 		/* What other information is available? */
-		.info_mask =
+		.info_mask_separate =
 		/*
 		 * in_voltage0_raw
 		 * Raw (unscaled no bias removal etc) measurement
 		 * from the device.
 		 */
-		IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+		BIT(IIO_CHAN_INFO_RAW) |
 		/*
 		 * in_voltage0_offset
 		 * Offset for userspace to apply prior to scale
 		 * when converting to standard units (microvolts)
 		 */
-		IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |
+		BIT(IIO_CHAN_INFO_OFFSET) |
 		/*
 		 * in_voltage0_scale
 		 * Multipler for userspace to apply post offset
 		 * when converting to standard units (microvolts)
 		 */
-		IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+		BIT(IIO_CHAN_INFO_SCALE),
 		/* The ordering of elements in the buffer via an enum */
 		.scan_index = voltage0,
 		.scan_type = { /* Description of storage in buffer */
@@ -118,19 +118,18 @@ static const struct iio_chan_spec iio_dummy_channels[] = {
 		.indexed = 1,
 		.channel = 1,
 		.channel2 = 2,
-		.info_mask =
 		/*
 		 * in_voltage1-voltage2_raw
 		 * Raw (unscaled no bias removal etc) measurement
 		 * from the device.
 		 */
-		IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
 		/*
 		 * in_voltage-voltage_scale
 		 * Shared version of scale - shared by differential
 		 * input channels of type IIO_VOLTAGE.
 		 */
-		IIO_CHAN_INFO_SCALE_SHARED_BIT,
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
 		.scan_index = diffvoltage1m2,
 		.scan_type = { /* Description of storage in buffer */
 			.sign = 's', /* signed */
@@ -146,9 +145,8 @@ static const struct iio_chan_spec iio_dummy_channels[] = {
 		.indexed = 1,
 		.channel = 3,
 		.channel2 = 4,
-		.info_mask =
-		IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-		IIO_CHAN_INFO_SCALE_SHARED_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
 		.scan_index = diffvoltage3m4,
 		.scan_type = {
 			.sign = 's',
@@ -166,15 +164,14 @@ static const struct iio_chan_spec iio_dummy_channels[] = {
 		.modified = 1,
 		/* Channel 2 is use for modifiers */
 		.channel2 = IIO_MOD_X,
-		.info_mask =
-		IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
 		/*
 		 * Internal bias correction value. Applied
 		 * by the hardware or driver prior to userspace
 		 * seeing the readings. Typically part of hardware
 		 * calibration.
 		 */
-		IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT,
+		BIT(IIO_CHAN_INFO_CALIBBIAS),
 		.scan_index = accelx,
 		.scan_type = { /* Description of storage in buffer */
 			.sign = 's', /* signed */
@@ -191,7 +188,7 @@ static const struct iio_chan_spec iio_dummy_channels[] = {
 	/* DAC channel out_voltage0_raw */
 	{
 		.type = IIO_VOLTAGE,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
 		.output = 1,
 		.indexed = 1,
 		.channel = 0,
@@ -204,8 +201,8 @@ static const struct iio_chan_spec iio_dummy_channels[] = {
  * @chan:	the channel whose data is to be read
  * @val:	first element of returned value (typically INT)
  * @val2:	second element of returned value (typically MICRO)
- * @mask:	what we actually want to read. 0 is the channel, everything else
- *		is as per the info_mask in iio_chan_spec.
+ * @mask:	what we actually want to read as per the info_mask_*
+ *		in iio_chan_spec.
  */
 static int iio_dummy_read_raw(struct iio_dev *indio_dev,
 			      struct iio_chan_spec const *chan,
@@ -287,8 +284,8 @@ static int iio_dummy_read_raw(struct iio_dev *indio_dev,
  * @chan:	the channel whose data is to be written
  * @val:	first element of value to set (typically INT)
  * @val2:	second element of value to set (typically MICRO)
- * @mask:	what we actually want to write. 0 is the channel, everything else
- *		is as per the info_mask in iio_chan_spec.
+ * @mask:	what we actually want to write as per the info_mask_*
+ *		in iio_chan_spec.
  *
  * Note that all raw writes are assumed IIO_VAL_INT and info mask elements
  * are assumed to be IIO_INT_PLUS_MICRO unless the callback write_raw_get_fmt
diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c
index 440e226..6330af6 100644
--- a/drivers/staging/iio/impedance-analyzer/ad5933.c
+++ b/drivers/staging/iio/impedance-analyzer/ad5933.c
@@ -113,7 +113,7 @@ static const struct iio_chan_spec ad5933_channels[] = {
 		.type = IIO_TEMP,
 		.indexed = 1,
 		.channel = 0,
-		.info_mask = IIO_CHAN_INFO_PROCESSED_SEPARATE_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
 		.address = AD5933_REG_TEMP_DATA,
 		.scan_type = {
 			.sign = 's',
@@ -125,8 +125,8 @@ static const struct iio_chan_spec ad5933_channels[] = {
 		.indexed = 1,
 		.channel = 0,
 		.extend_name = "real_raw",
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-		IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+		BIT(IIO_CHAN_INFO_SCALE),
 		.address = AD5933_REG_REAL_DATA,
 		.scan_index = 0,
 		.scan_type = {
@@ -139,8 +139,8 @@ static const struct iio_chan_spec ad5933_channels[] = {
 		.indexed = 1,
 		.channel = 0,
 		.extend_name = "imag_raw",
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-		IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+		BIT(IIO_CHAN_INFO_SCALE),
 		.address = AD5933_REG_IMAG_DATA,
 		.scan_index = 1,
 		.scan_type = {
diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c
index b0adac0..82478a5 100644
--- a/drivers/staging/iio/light/isl29018.c
+++ b/drivers/staging/iio/light/isl29018.c
@@ -412,17 +412,17 @@ static const struct iio_chan_spec isl29018_channels[] = {
 		.type = IIO_LIGHT,
 		.indexed = 1,
 		.channel = 0,
-		.info_mask = IIO_CHAN_INFO_PROCESSED_SEPARATE_BIT |
-		IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
+		BIT(IIO_CHAN_INFO_CALIBSCALE),
 	}, {
 		.type = IIO_INTENSITY,
 		.modified = 1,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
 		.channel2 = IIO_MOD_LIGHT_IR,
 	}, {
 		/* Unindexed in current ABI.  But perhaps it should be. */
 		.type = IIO_PROXIMITY,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
 	}
 };
 
diff --git a/drivers/staging/iio/light/isl29028.c b/drivers/staging/iio/light/isl29028.c
index e52af77..8bb0d03 100644
--- a/drivers/staging/iio/light/isl29028.c
+++ b/drivers/staging/iio/light/isl29028.c
@@ -391,15 +391,15 @@ static const struct attribute_group isl29108_group = {
 static const struct iio_chan_spec isl29028_channels[] = {
 	{
 		.type = IIO_LIGHT,
-		.info_mask = IIO_CHAN_INFO_PROCESSED_SEPARATE_BIT |
-		IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
+		BIT(IIO_CHAN_INFO_SCALE),
 	}, {
 		.type = IIO_INTENSITY,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
 	}, {
 		.type = IIO_PROXIMITY,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-		IIO_CHAN_INFO_SAMP_FREQ_SEPARATE_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+		BIT(IIO_CHAN_INFO_SAMP_FREQ),
 	}
 };
 
diff --git a/drivers/staging/iio/light/tsl2x7x_core.c b/drivers/staging/iio/light/tsl2x7x_core.c
index a58731e..d060f25 100644
--- a/drivers/staging/iio/light/tsl2x7x_core.c
+++ b/drivers/staging/iio/light/tsl2x7x_core.c
@@ -1733,14 +1733,14 @@ static const struct tsl2x7x_chip_info tsl2x7x_chip_info_tbl[] = {
 			.type = IIO_LIGHT,
 			.indexed = 1,
 			.channel = 0,
-			.info_mask = IIO_CHAN_INFO_PROCESSED_SEPARATE_BIT,
+			.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
 			}, {
 			.type = IIO_INTENSITY,
 			.indexed = 1,
 			.channel = 0,
-			.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-				IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT |
-				IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT,
+			.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+				BIT(IIO_CHAN_INFO_CALIBSCALE) |
+				BIT(IIO_CHAN_INFO_CALIBBIAS),
 			.event_mask = TSL2X7X_EVENT_MASK
 			}, {
 			.type = IIO_INTENSITY,
@@ -1757,7 +1757,7 @@ static const struct tsl2x7x_chip_info tsl2x7x_chip_info_tbl[] = {
 			.type = IIO_PROXIMITY,
 			.indexed = 1,
 			.channel = 0,
-			.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
+			.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
 			.event_mask = TSL2X7X_EVENT_MASK
 			},
 		},
@@ -1770,25 +1770,25 @@ static const struct tsl2x7x_chip_info tsl2x7x_chip_info_tbl[] = {
 			.type = IIO_LIGHT,
 			.indexed = 1,
 			.channel = 0,
-			.info_mask = IIO_CHAN_INFO_PROCESSED_SEPARATE_BIT
+			.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED)
 			}, {
 			.type = IIO_INTENSITY,
 			.indexed = 1,
 			.channel = 0,
-			.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-				IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT |
-				IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT,
+			.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+				BIT(IIO_CHAN_INFO_CALIBSCALE) |
+				BIT(IIO_CHAN_INFO_CALIBBIAS),
 			.event_mask = TSL2X7X_EVENT_MASK
 			}, {
 			.type = IIO_INTENSITY,
 			.indexed = 1,
 			.channel = 1,
-			.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
+			.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
 			}, {
 			.type = IIO_PROXIMITY,
 			.indexed = 1,
 			.channel = 0,
-			.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
+			.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
 			.event_mask = TSL2X7X_EVENT_MASK
 			},
 		},
@@ -1801,8 +1801,8 @@ static const struct tsl2x7x_chip_info tsl2x7x_chip_info_tbl[] = {
 			.type = IIO_PROXIMITY,
 			.indexed = 1,
 			.channel = 0,
-			.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-				IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT,
+			.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+				BIT(IIO_CHAN_INFO_CALIBSCALE),
 			.event_mask = TSL2X7X_EVENT_MASK
 			},
 		},
@@ -1815,26 +1815,26 @@ static const struct tsl2x7x_chip_info tsl2x7x_chip_info_tbl[] = {
 			.type = IIO_LIGHT,
 			.indexed = 1,
 			.channel = 0,
-			.info_mask = IIO_CHAN_INFO_PROCESSED_SEPARATE_BIT,
+			.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
 			}, {
 			.type = IIO_INTENSITY,
 			.indexed = 1,
 			.channel = 0,
-			.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-				IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT |
-				IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT,
+			.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+				BIT(IIO_CHAN_INFO_CALIBSCALE) |
+				BIT(IIO_CHAN_INFO_CALIBBIAS),
 			.event_mask = TSL2X7X_EVENT_MASK
 			}, {
 			.type = IIO_INTENSITY,
 			.indexed = 1,
 			.channel = 1,
-			.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
+			.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
 			}, {
 			.type = IIO_PROXIMITY,
 			.indexed = 1,
 			.channel = 0,
-			.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-				IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT,
+			.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+				BIT(IIO_CHAN_INFO_CALIBSCALE),
 			.event_mask = TSL2X7X_EVENT_MASK
 			},
 		},
diff --git a/drivers/staging/iio/magnetometer/Kconfig b/drivers/staging/iio/magnetometer/Kconfig
index df5e0d4..a3ea69e 100644
--- a/drivers/staging/iio/magnetometer/Kconfig
+++ b/drivers/staging/iio/magnetometer/Kconfig
@@ -3,17 +3,6 @@
 #
 menu "Magnetometer sensors"
 
-config SENSORS_AK8975
-	tristate "Asahi Kasei AK8975 3-Axis Magnetometer"
-	depends on I2C
-	depends on GPIOLIB
-	help
-	  Say yes here to build support for Asahi Kasei AK8975 3-Axis
-	  Magnetometer.
-
-	  To compile this driver as a module, choose M here: the module
-	  will be called ak8975.
-
 config SENSORS_HMC5843
 	tristate "Honeywell HMC5843/5883/5883L 3-Axis Magnetometer"
 	depends on I2C
diff --git a/drivers/staging/iio/magnetometer/Makefile b/drivers/staging/iio/magnetometer/Makefile
index f2a753f..f9bfb2e 100644
--- a/drivers/staging/iio/magnetometer/Makefile
+++ b/drivers/staging/iio/magnetometer/Makefile
@@ -2,5 +2,4 @@
 # Makefile for industrial I/O Magnetometer sensors
 #
 
-obj-$(CONFIG_SENSORS_AK8975)	+= ak8975.o
 obj-$(CONFIG_SENSORS_HMC5843)	+= hmc5843.o
diff --git a/drivers/staging/iio/magnetometer/ak8975.c b/drivers/staging/iio/magnetometer/ak8975.c
deleted file mode 100644
index 28f080e..0000000
--- a/drivers/staging/iio/magnetometer/ak8975.c
+++ /dev/null
@@ -1,520 +0,0 @@
-/*
- * A sensor driver for the magnetometer AK8975.
- *
- * Magnetic compass sensor driver for monitoring magnetic flux information.
- *
- * Copyright (c) 2010, NVIDIA Corporation.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA	02110-1301, USA.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/i2c.h>
-#include <linux/err.h>
-#include <linux/mutex.h>
-#include <linux/delay.h>
-
-#include <linux/gpio.h>
-
-#include <linux/iio/iio.h>
-#include <linux/iio/sysfs.h>
-/*
- * Register definitions, as well as various shifts and masks to get at the
- * individual fields of the registers.
- */
-#define AK8975_REG_WIA			0x00
-#define AK8975_DEVICE_ID		0x48
-
-#define AK8975_REG_INFO			0x01
-
-#define AK8975_REG_ST1			0x02
-#define AK8975_REG_ST1_DRDY_SHIFT	0
-#define AK8975_REG_ST1_DRDY_MASK	(1 << AK8975_REG_ST1_DRDY_SHIFT)
-
-#define AK8975_REG_HXL			0x03
-#define AK8975_REG_HXH			0x04
-#define AK8975_REG_HYL			0x05
-#define AK8975_REG_HYH			0x06
-#define AK8975_REG_HZL			0x07
-#define AK8975_REG_HZH			0x08
-#define AK8975_REG_ST2			0x09
-#define AK8975_REG_ST2_DERR_SHIFT	2
-#define AK8975_REG_ST2_DERR_MASK	(1 << AK8975_REG_ST2_DERR_SHIFT)
-
-#define AK8975_REG_ST2_HOFL_SHIFT	3
-#define AK8975_REG_ST2_HOFL_MASK	(1 << AK8975_REG_ST2_HOFL_SHIFT)
-
-#define AK8975_REG_CNTL			0x0A
-#define AK8975_REG_CNTL_MODE_SHIFT	0
-#define AK8975_REG_CNTL_MODE_MASK	(0xF << AK8975_REG_CNTL_MODE_SHIFT)
-#define AK8975_REG_CNTL_MODE_POWER_DOWN	0
-#define AK8975_REG_CNTL_MODE_ONCE	1
-#define AK8975_REG_CNTL_MODE_SELF_TEST	8
-#define AK8975_REG_CNTL_MODE_FUSE_ROM	0xF
-
-#define AK8975_REG_RSVC			0x0B
-#define AK8975_REG_ASTC			0x0C
-#define AK8975_REG_TS1			0x0D
-#define AK8975_REG_TS2			0x0E
-#define AK8975_REG_I2CDIS		0x0F
-#define AK8975_REG_ASAX			0x10
-#define AK8975_REG_ASAY			0x11
-#define AK8975_REG_ASAZ			0x12
-
-#define AK8975_MAX_REGS			AK8975_REG_ASAZ
-
-/*
- * Miscellaneous values.
- */
-#define AK8975_MAX_CONVERSION_TIMEOUT	500
-#define AK8975_CONVERSION_DONE_POLL_TIME 10
-
-/*
- * Per-instance context data for the device.
- */
-struct ak8975_data {
-	struct i2c_client	*client;
-	struct attribute_group	attrs;
-	struct mutex		lock;
-	u8			asa[3];
-	long			raw_to_gauss[3];
-	u8			reg_cache[AK8975_MAX_REGS];
-	int			eoc_gpio;
-	int			eoc_irq;
-};
-
-static const int ak8975_index_to_reg[] = {
-	AK8975_REG_HXL, AK8975_REG_HYL, AK8975_REG_HZL,
-};
-
-/*
- * Helper function to write to the I2C device's registers.
- */
-static int ak8975_write_data(struct i2c_client *client,
-			     u8 reg, u8 val, u8 mask, u8 shift)
-{
-	struct iio_dev *indio_dev = i2c_get_clientdata(client);
-	struct ak8975_data *data = iio_priv(indio_dev);
-	u8 regval;
-	int ret;
-
-	regval = (data->reg_cache[reg] & ~mask) | (val << shift);
-	ret = i2c_smbus_write_byte_data(client, reg, regval);
-	if (ret < 0) {
-		dev_err(&client->dev, "Write to device fails status %x\n", ret);
-		return ret;
-	}
-	data->reg_cache[reg] = regval;
-
-	return 0;
-}
-
-/*
- * Helper function to read a contiguous set of the I2C device's registers.
- */
-static int ak8975_read_data(struct i2c_client *client,
-			    u8 reg, u8 length, u8 *buffer)
-{
-	int ret;
-	struct i2c_msg msg[2] = {
-		{
-			.addr = client->addr,
-			.flags = I2C_M_NOSTART,
-			.len = 1,
-			.buf = &reg,
-		}, {
-			.addr = client->addr,
-			.flags = I2C_M_RD,
-			.len = length,
-			.buf = buffer,
-		}
-	};
-
-	ret = i2c_transfer(client->adapter, msg, 2);
-	if (ret < 0) {
-		dev_err(&client->dev, "Read from device fails\n");
-		return ret;
-	}
-
-	return 0;
-}
-
-/*
- * Perform some start-of-day setup, including reading the asa calibration
- * values and caching them.
- */
-static int ak8975_setup(struct i2c_client *client)
-{
-	struct iio_dev *indio_dev = i2c_get_clientdata(client);
-	struct ak8975_data *data = iio_priv(indio_dev);
-	u8 device_id;
-	int ret;
-
-	/* Confirm that the device we're talking to is really an AK8975. */
-	ret = ak8975_read_data(client, AK8975_REG_WIA, 1, &device_id);
-	if (ret < 0) {
-		dev_err(&client->dev, "Error reading WIA\n");
-		return ret;
-	}
-	if (device_id != AK8975_DEVICE_ID) {
-		dev_err(&client->dev, "Device ak8975 not found\n");
-		return -ENODEV;
-	}
-
-	/* Write the fused rom access mode. */
-	ret = ak8975_write_data(client,
-				AK8975_REG_CNTL,
-				AK8975_REG_CNTL_MODE_FUSE_ROM,
-				AK8975_REG_CNTL_MODE_MASK,
-				AK8975_REG_CNTL_MODE_SHIFT);
-	if (ret < 0) {
-		dev_err(&client->dev, "Error in setting fuse access mode\n");
-		return ret;
-	}
-
-	/* Get asa data and store in the device data. */
-	ret = ak8975_read_data(client, AK8975_REG_ASAX, 3, data->asa);
-	if (ret < 0) {
-		dev_err(&client->dev, "Not able to read asa data\n");
-		return ret;
-	}
-
-	/* After reading fuse ROM data set power-down mode */
-	ret = ak8975_write_data(client,
-				AK8975_REG_CNTL,
-				AK8975_REG_CNTL_MODE_POWER_DOWN,
-				AK8975_REG_CNTL_MODE_MASK,
-				AK8975_REG_CNTL_MODE_SHIFT);
-	if (ret < 0) {
-		dev_err(&client->dev, "Error in setting power-down mode\n");
-		return ret;
-	}
-
-/*
- * Precalculate scale factor (in Gauss units) for each axis and
- * store in the device data.
- *
- * This scale factor is axis-dependent, and is derived from 3 calibration
- * factors ASA(x), ASA(y), and ASA(z).
- *
- * These ASA values are read from the sensor device at start of day, and
- * cached in the device context struct.
- *
- * Adjusting the flux value with the sensitivity adjustment value should be
- * done via the following formula:
- *
- * Hadj = H * ( ( ( (ASA-128)*0.5 ) / 128 ) + 1 )
- *
- * where H is the raw value, ASA is the sensitivity adjustment, and Hadj
- * is the resultant adjusted value.
- *
- * We reduce the formula to:
- *
- * Hadj = H * (ASA + 128) / 256
- *
- * H is in the range of -4096 to 4095.  The magnetometer has a range of
- * +-1229uT.  To go from the raw value to uT is:
- *
- * HuT = H * 1229/4096, or roughly, 3/10.
- *
- * Since 1uT = 100 gauss, our final scale factor becomes:
- *
- * Hadj = H * ((ASA + 128) / 256) * 3/10 * 100
- * Hadj = H * ((ASA + 128) * 30 / 256
- *
- * Since ASA doesn't change, we cache the resultant scale factor into the
- * device context in ak8975_setup().
- */
-	data->raw_to_gauss[0] = ((data->asa[0] + 128) * 30) >> 8;
-	data->raw_to_gauss[1] = ((data->asa[1] + 128) * 30) >> 8;
-	data->raw_to_gauss[2] = ((data->asa[2] + 128) * 30) >> 8;
-
-	return 0;
-}
-
-static int wait_conversion_complete_gpio(struct ak8975_data *data)
-{
-	struct i2c_client *client = data->client;
-	u8 read_status;
-	u32 timeout_ms = AK8975_MAX_CONVERSION_TIMEOUT;
-	int ret;
-
-	/* Wait for the conversion to complete. */
-	while (timeout_ms) {
-		msleep(AK8975_CONVERSION_DONE_POLL_TIME);
-		if (gpio_get_value(data->eoc_gpio))
-			break;
-		timeout_ms -= AK8975_CONVERSION_DONE_POLL_TIME;
-	}
-	if (!timeout_ms) {
-		dev_err(&client->dev, "Conversion timeout happened\n");
-		return -EINVAL;
-	}
-
-	ret = ak8975_read_data(client, AK8975_REG_ST1, 1, &read_status);
-	if (ret < 0) {
-		dev_err(&client->dev, "Error in reading ST1\n");
-		return ret;
-	}
-	return read_status;
-}
-
-static int wait_conversion_complete_polled(struct ak8975_data *data)
-{
-	struct i2c_client *client = data->client;
-	u8 read_status;
-	u32 timeout_ms = AK8975_MAX_CONVERSION_TIMEOUT;
-	int ret;
-
-	/* Wait for the conversion to complete. */
-	while (timeout_ms) {
-		msleep(AK8975_CONVERSION_DONE_POLL_TIME);
-		ret = ak8975_read_data(client, AK8975_REG_ST1, 1, &read_status);
-		if (ret < 0) {
-			dev_err(&client->dev, "Error in reading ST1\n");
-			return ret;
-		}
-		if (read_status)
-			break;
-		timeout_ms -= AK8975_CONVERSION_DONE_POLL_TIME;
-	}
-	if (!timeout_ms) {
-		dev_err(&client->dev, "Conversion timeout happened\n");
-		return -EINVAL;
-	}
-	return read_status;
-}
-
-/*
- * Emits the raw flux value for the x, y, or z axis.
- */
-static int ak8975_read_axis(struct iio_dev *indio_dev, int index, int *val)
-{
-	struct ak8975_data *data = iio_priv(indio_dev);
-	struct i2c_client *client = data->client;
-	u16 meas_reg;
-	s16 raw;
-	u8 read_status;
-	int ret;
-
-	mutex_lock(&data->lock);
-
-	/* Set up the device for taking a sample. */
-	ret = ak8975_write_data(client,
-				AK8975_REG_CNTL,
-				AK8975_REG_CNTL_MODE_ONCE,
-				AK8975_REG_CNTL_MODE_MASK,
-				AK8975_REG_CNTL_MODE_SHIFT);
-	if (ret < 0) {
-		dev_err(&client->dev, "Error in setting operating mode\n");
-		goto exit;
-	}
-
-	/* Wait for the conversion to complete. */
-	if (gpio_is_valid(data->eoc_gpio))
-		ret = wait_conversion_complete_gpio(data);
-	else
-		ret = wait_conversion_complete_polled(data);
-	if (ret < 0)
-		goto exit;
-
-	read_status = ret;
-
-	if (read_status & AK8975_REG_ST1_DRDY_MASK) {
-		ret = ak8975_read_data(client, AK8975_REG_ST2, 1, &read_status);
-		if (ret < 0) {
-			dev_err(&client->dev, "Error in reading ST2\n");
-			goto exit;
-		}
-		if (read_status & (AK8975_REG_ST2_DERR_MASK |
-				   AK8975_REG_ST2_HOFL_MASK)) {
-			dev_err(&client->dev, "ST2 status error 0x%x\n",
-				read_status);
-			ret = -EINVAL;
-			goto exit;
-		}
-	}
-
-	/* Read the flux value from the appropriate register
-	   (the register is specified in the iio device attributes). */
-	ret = ak8975_read_data(client, ak8975_index_to_reg[index],
-			       2, (u8 *)&meas_reg);
-	if (ret < 0) {
-		dev_err(&client->dev, "Read axis data fails\n");
-		goto exit;
-	}
-
-	mutex_unlock(&data->lock);
-
-	/* Endian conversion of the measured values. */
-	raw = (s16) (le16_to_cpu(meas_reg));
-
-	/* Clamp to valid range. */
-	raw = clamp_t(s16, raw, -4096, 4095);
-	*val = raw;
-	return IIO_VAL_INT;
-
-exit:
-	mutex_unlock(&data->lock);
-	return ret;
-}
-
-static int ak8975_read_raw(struct iio_dev *indio_dev,
-			   struct iio_chan_spec const *chan,
-			   int *val, int *val2,
-			   long mask)
-{
-	struct ak8975_data *data = iio_priv(indio_dev);
-
-	switch (mask) {
-	case IIO_CHAN_INFO_RAW:
-		return ak8975_read_axis(indio_dev, chan->address, val);
-	case IIO_CHAN_INFO_SCALE:
-		*val = data->raw_to_gauss[chan->address];
-		return IIO_VAL_INT;
-	}
-	return -EINVAL;
-}
-
-#define AK8975_CHANNEL(axis, index)					\
-	{								\
-		.type = IIO_MAGN,					\
-		.modified = 1,						\
-		.channel2 = IIO_MOD_##axis,				\
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |		\
-			     IIO_CHAN_INFO_SCALE_SEPARATE_BIT,		\
-		.address = index,					\
-	}
-
-static const struct iio_chan_spec ak8975_channels[] = {
-	AK8975_CHANNEL(X, 0), AK8975_CHANNEL(Y, 1), AK8975_CHANNEL(Z, 2),
-};
-
-static const struct iio_info ak8975_info = {
-	.read_raw = &ak8975_read_raw,
-	.driver_module = THIS_MODULE,
-};
-
-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;
-
-	/* Grab and set up the supplied GPIO. */
-	if (client->dev.platform_data == NULL)
-		eoc_gpio = -1;
-	else
-		eoc_gpio = *(int *)(client->dev.platform_data);
-
-	/* We may not have a GPIO based IRQ to scan, that is fine, we will
-	   poll if so */
-	if (gpio_is_valid(eoc_gpio)) {
-		err = gpio_request_one(eoc_gpio, GPIOF_IN, "ak_8975");
-		if (err < 0) {
-			dev_err(&client->dev,
-				"failed to request GPIO %d, error %d\n",
-							eoc_gpio, err);
-			goto exit;
-		}
-	}
-
-	/* Register with IIO */
-	indio_dev = iio_device_alloc(sizeof(*data));
-	if (indio_dev == NULL) {
-		err = -ENOMEM;
-		goto exit_gpio;
-	}
-	data = iio_priv(indio_dev);
-	i2c_set_clientdata(client, indio_dev);
-	/* Perform some basic start-of-day setup of the device. */
-	err = ak8975_setup(client);
-	if (err < 0) {
-		dev_err(&client->dev, "AK8975 initialization fails\n");
-		goto exit_free_iio;
-	}
-
-	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->channels = ak8975_channels;
-	indio_dev->num_channels = ARRAY_SIZE(ak8975_channels);
-	indio_dev->info = &ak8975_info;
-	indio_dev->modes = INDIO_DIRECT_MODE;
-
-	err = iio_device_register(indio_dev);
-	if (err < 0)
-		goto exit_free_iio;
-
-	return 0;
-
-exit_free_iio:
-	iio_device_free(indio_dev);
-exit_gpio:
-	if (gpio_is_valid(eoc_gpio))
-		gpio_free(eoc_gpio);
-exit:
-	return err;
-}
-
-static int ak8975_remove(struct i2c_client *client)
-{
-	struct iio_dev *indio_dev = i2c_get_clientdata(client);
-	struct ak8975_data *data = iio_priv(indio_dev);
-
-	iio_device_unregister(indio_dev);
-
-	if (gpio_is_valid(data->eoc_gpio))
-		gpio_free(data->eoc_gpio);
-
-	iio_device_free(indio_dev);
-
-	return 0;
-}
-
-static const struct i2c_device_id ak8975_id[] = {
-	{"ak8975", 0},
-	{}
-};
-
-MODULE_DEVICE_TABLE(i2c, ak8975_id);
-
-static const struct of_device_id ak8975_of_match[] = {
-	{ .compatible = "asahi-kasei,ak8975", },
-	{ .compatible = "ak8975", },
-	{ }
-};
-MODULE_DEVICE_TABLE(of, ak8975_of_match);
-
-static struct i2c_driver ak8975_driver = {
-	.driver = {
-		.name	= "ak8975",
-		.of_match_table = ak8975_of_match,
-	},
-	.probe		= ak8975_probe,
-	.remove		= ak8975_remove,
-	.id_table	= ak8975_id,
-};
-module_i2c_driver(ak8975_driver);
-
-MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
-MODULE_DESCRIPTION("AK8975 magnetometer driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/iio/magnetometer/hmc5843.c b/drivers/staging/iio/magnetometer/hmc5843.c
index 1a520ec..86c6bf9 100644
--- a/drivers/staging/iio/magnetometer/hmc5843.c
+++ b/drivers/staging/iio/magnetometer/hmc5843.c
@@ -564,8 +564,8 @@ static int hmc5843_read_raw(struct iio_dev *indio_dev,
 		.type = IIO_MAGN,					\
 		.modified = 1,						\
 		.channel2 = IIO_MOD_##axis,				\
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |		\
-			     IIO_CHAN_INFO_SCALE_SHARED_BIT,		\
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),	\
 		.address = add						\
 	}
 
diff --git a/drivers/staging/iio/meter/ade7758_core.c b/drivers/staging/iio/meter/ade7758_core.c
index 53c68dc..8f5bcfa 100644
--- a/drivers/staging/iio/meter/ade7758_core.c
+++ b/drivers/staging/iio/meter/ade7758_core.c
@@ -649,8 +649,8 @@ static const struct iio_chan_spec ade7758_channels[] = {
 		.indexed = 1,
 		.channel = 0,
 		.extend_name = "raw",
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-			     IIO_CHAN_INFO_SCALE_SHARED_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
 		.address = AD7758_WT(AD7758_PHASE_A, AD7758_VOLTAGE),
 		.scan_index = 0,
 		.scan_type = {
@@ -663,8 +663,8 @@ static const struct iio_chan_spec ade7758_channels[] = {
 		.indexed = 1,
 		.channel = 0,
 		.extend_name = "raw",
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-			     IIO_CHAN_INFO_SCALE_SHARED_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
 		.address = AD7758_WT(AD7758_PHASE_A, AD7758_CURRENT),
 		.scan_index = 1,
 		.scan_type = {
@@ -677,8 +677,8 @@ static const struct iio_chan_spec ade7758_channels[] = {
 		.indexed = 1,
 		.channel = 0,
 		.extend_name = "apparent_raw",
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-			     IIO_CHAN_INFO_SCALE_SHARED_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
 		.address = AD7758_WT(AD7758_PHASE_A, AD7758_APP_PWR),
 		.scan_index = 2,
 		.scan_type = {
@@ -691,8 +691,8 @@ static const struct iio_chan_spec ade7758_channels[] = {
 		.indexed = 1,
 		.channel = 0,
 		.extend_name = "active_raw",
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-			     IIO_CHAN_INFO_SCALE_SHARED_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
 		.address = AD7758_WT(AD7758_PHASE_A, AD7758_ACT_PWR),
 		.scan_index = 3,
 		.scan_type = {
@@ -705,8 +705,8 @@ static const struct iio_chan_spec ade7758_channels[] = {
 		.indexed = 1,
 		.channel = 0,
 		.extend_name = "reactive_raw",
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-			     IIO_CHAN_INFO_SCALE_SHARED_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
 		.address = AD7758_WT(AD7758_PHASE_A, AD7758_REACT_PWR),
 		.scan_index = 4,
 		.scan_type = {
@@ -719,8 +719,8 @@ static const struct iio_chan_spec ade7758_channels[] = {
 		.indexed = 1,
 		.channel = 1,
 		.extend_name = "raw",
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-			     IIO_CHAN_INFO_SCALE_SHARED_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
 		.address = AD7758_WT(AD7758_PHASE_B, AD7758_VOLTAGE),
 		.scan_index = 5,
 		.scan_type = {
@@ -733,8 +733,8 @@ static const struct iio_chan_spec ade7758_channels[] = {
 		.indexed = 1,
 		.channel = 1,
 		.extend_name = "raw",
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-			     IIO_CHAN_INFO_SCALE_SHARED_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
 		.address = AD7758_WT(AD7758_PHASE_B, AD7758_CURRENT),
 		.scan_index = 6,
 		.scan_type = {
@@ -747,8 +747,8 @@ static const struct iio_chan_spec ade7758_channels[] = {
 		.indexed = 1,
 		.channel = 1,
 		.extend_name = "apparent_raw",
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-			     IIO_CHAN_INFO_SCALE_SHARED_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
 		.address = AD7758_WT(AD7758_PHASE_B, AD7758_APP_PWR),
 		.scan_index = 7,
 		.scan_type = {
@@ -761,8 +761,8 @@ static const struct iio_chan_spec ade7758_channels[] = {
 		.indexed = 1,
 		.channel = 1,
 		.extend_name = "active_raw",
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-			     IIO_CHAN_INFO_SCALE_SHARED_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
 		.address = AD7758_WT(AD7758_PHASE_B, AD7758_ACT_PWR),
 		.scan_index = 8,
 		.scan_type = {
@@ -775,8 +775,8 @@ static const struct iio_chan_spec ade7758_channels[] = {
 		.indexed = 1,
 		.channel = 1,
 		.extend_name = "reactive_raw",
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-			     IIO_CHAN_INFO_SCALE_SHARED_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
 		.address = AD7758_WT(AD7758_PHASE_B, AD7758_REACT_PWR),
 		.scan_index = 9,
 		.scan_type = {
@@ -789,8 +789,8 @@ static const struct iio_chan_spec ade7758_channels[] = {
 		.indexed = 1,
 		.channel = 2,
 		.extend_name = "raw",
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-			     IIO_CHAN_INFO_SCALE_SHARED_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
 		.address = AD7758_WT(AD7758_PHASE_C, AD7758_VOLTAGE),
 		.scan_index = 10,
 		.scan_type = {
@@ -803,8 +803,8 @@ static const struct iio_chan_spec ade7758_channels[] = {
 		.indexed = 1,
 		.channel = 2,
 		.extend_name = "raw",
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-			     IIO_CHAN_INFO_SCALE_SHARED_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
 		.address = AD7758_WT(AD7758_PHASE_C, AD7758_CURRENT),
 		.scan_index = 11,
 		.scan_type = {
@@ -817,8 +817,8 @@ static const struct iio_chan_spec ade7758_channels[] = {
 		.indexed = 1,
 		.channel = 2,
 		.extend_name = "apparent_raw",
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-			     IIO_CHAN_INFO_SCALE_SHARED_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
 		.address = AD7758_WT(AD7758_PHASE_C, AD7758_APP_PWR),
 		.scan_index = 12,
 		.scan_type = {
@@ -831,8 +831,8 @@ static const struct iio_chan_spec ade7758_channels[] = {
 		.indexed = 1,
 		.channel = 2,
 		.extend_name = "active_raw",
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-			     IIO_CHAN_INFO_SCALE_SHARED_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
 		.address = AD7758_WT(AD7758_PHASE_C, AD7758_ACT_PWR),
 		.scan_index = 13,
 		.scan_type = {
@@ -845,8 +845,8 @@ static const struct iio_chan_spec ade7758_channels[] = {
 		.indexed = 1,
 		.channel = 2,
 		.extend_name = "reactive_raw",
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-			     IIO_CHAN_INFO_SCALE_SHARED_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
 		.address = AD7758_WT(AD7758_PHASE_C, AD7758_REACT_PWR),
 		.scan_index = 14,
 		.scan_type = {
diff --git a/drivers/staging/iio/meter/ade7758_trigger.c b/drivers/staging/iio/meter/ade7758_trigger.c
index f9c6a34..7a94ddd 100644
--- a/drivers/staging/iio/meter/ade7758_trigger.c
+++ b/drivers/staging/iio/meter/ade7758_trigger.c
@@ -32,7 +32,7 @@ static irqreturn_t ade7758_data_rdy_trig_poll(int irq, void *private)
 static int ade7758_data_rdy_trigger_set_state(struct iio_trigger *trig,
 						bool state)
 {
-	struct iio_dev *indio_dev = trig->private_data;
+	struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
 
 	dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state);
 	return ade7758_set_irq(&indio_dev->dev, state);
@@ -44,7 +44,7 @@ static int ade7758_data_rdy_trigger_set_state(struct iio_trigger *trig,
  **/
 static int ade7758_trig_try_reen(struct iio_trigger *trig)
 {
-	struct iio_dev *indio_dev = trig->private_data;
+	struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
 	struct ade7758_state *st = iio_priv(indio_dev);
 
 	enable_irq(st->us->irq);
@@ -81,7 +81,7 @@ int ade7758_probe_trigger(struct iio_dev *indio_dev)
 
 	st->trig->dev.parent = &st->us->dev;
 	st->trig->ops = &ade7758_trigger_ops;
-	st->trig->private_data = indio_dev;
+	iio_trigger_set_drvdata(st->trig, indio_dev);
 	ret = iio_trigger_register(st->trig);
 
 	/* select default trigger */
diff --git a/drivers/staging/iio/resolver/ad2s1200.c b/drivers/staging/iio/resolver/ad2s1200.c
index 4fe3499..7122116 100644
--- a/drivers/staging/iio/resolver/ad2s1200.c
+++ b/drivers/staging/iio/resolver/ad2s1200.c
@@ -85,12 +85,12 @@ static const struct iio_chan_spec ad2s1200_channels[] = {
 		.type = IIO_ANGL,
 		.indexed = 1,
 		.channel = 0,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
 	}, {
 		.type = IIO_ANGL_VEL,
 		.indexed = 1,
 		.channel = 0,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
 	}
 };
 
diff --git a/drivers/staging/iio/resolver/ad2s1210.c b/drivers/staging/iio/resolver/ad2s1210.c
index 53110b6..0d3356d 100644
--- a/drivers/staging/iio/resolver/ad2s1210.c
+++ b/drivers/staging/iio/resolver/ad2s1210.c
@@ -577,12 +577,12 @@ static const struct iio_chan_spec ad2s1210_channels[] = {
 		.type = IIO_ANGL,
 		.indexed = 1,
 		.channel = 0,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
 	}, {
 		.type = IIO_ANGL_VEL,
 		.indexed = 1,
 		.channel = 0,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
 	}
 };
 
diff --git a/drivers/staging/iio/resolver/ad2s90.c b/drivers/staging/iio/resolver/ad2s90.c
index 0aecfbc..40b8252 100644
--- a/drivers/staging/iio/resolver/ad2s90.c
+++ b/drivers/staging/iio/resolver/ad2s90.c
@@ -55,7 +55,7 @@ static const struct iio_chan_spec ad2s90_chan = {
 	.type = IIO_ANGL,
 	.indexed = 1,
 	.channel = 0,
-	.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
 };
 
 static int ad2s90_probe(struct spi_device *spi)
diff --git a/drivers/staging/iio/trigger/iio-trig-bfin-timer.c b/drivers/staging/iio/trigger/iio-trig-bfin-timer.c
index 42798da..38a158b 100644
--- a/drivers/staging/iio/trigger/iio-trig-bfin-timer.c
+++ b/drivers/staging/iio/trigger/iio-trig-bfin-timer.c
@@ -65,7 +65,7 @@ struct bfin_tmr_state {
 
 static int iio_bfin_tmr_set_state(struct iio_trigger *trig, bool state)
 {
-	struct bfin_tmr_state *st = trig->private_data;
+	struct bfin_tmr_state *st = iio_trigger_get_drvdata(trig);
 
 	if (get_gptimer_period(st->t->id) == 0)
 		return -EINVAL;
@@ -82,7 +82,7 @@ static ssize_t iio_bfin_tmr_frequency_store(struct device *dev,
 		struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct iio_trigger *trig = to_iio_trigger(dev);
-	struct bfin_tmr_state *st = trig->private_data;
+	struct bfin_tmr_state *st = iio_trigger_get_drvdata(trig);
 	unsigned long val;
 	bool enabled;
 	int ret;
@@ -125,7 +125,7 @@ static ssize_t iio_bfin_tmr_frequency_show(struct device *dev,
 				 char *buf)
 {
 	struct iio_trigger *trig = to_iio_trigger(dev);
-	struct bfin_tmr_state *st = trig->private_data;
+	struct bfin_tmr_state *st = iio_trigger_get_drvdata(trig);
 	unsigned int period = get_gptimer_period(st->t->id);
 	unsigned long val;
 
@@ -213,9 +213,9 @@ static int iio_bfin_tmr_trigger_probe(struct platform_device *pdev)
 		goto out1;
 	}
 
-	st->trig->private_data = st;
 	st->trig->ops = &iio_bfin_tmr_trigger_ops;
 	st->trig->dev.groups = iio_bfin_tmr_trigger_attr_groups;
+	iio_trigger_set_drvdata(st->trig, st);
 	ret = iio_trigger_register(st->trig);
 	if (ret)
 		goto out2;
diff --git a/drivers/staging/iio/trigger/iio-trig-gpio.c b/drivers/staging/iio/trigger/iio-trig-gpio.c
index fcc4cb0..7c593d1 100644
--- a/drivers/staging/iio/trigger/iio-trig-gpio.c
+++ b/drivers/staging/iio/trigger/iio-trig-gpio.c
@@ -83,7 +83,7 @@ static int iio_gpio_trigger_probe(struct platform_device *pdev)
 				ret = -ENOMEM;
 				goto error_put_trigger;
 			}
-			trig->private_data = trig_info;
+			iio_trigger_set_drvdata(trig, trig_info);
 			trig_info->irq = irq;
 			trig->ops = &iio_gpio_trigger_ops;
 			ret = request_irq(irq, iio_gpio_trigger_poll,
@@ -121,7 +121,7 @@ error_free_completed_registrations:
 				 trig2,
 				 &iio_gpio_trigger_list,
 				 alloc_list) {
-		trig_info = trig->private_data;
+		trig_info = iio_trigger_get_drvdata(trig);
 		free_irq(gpio_to_irq(trig_info->irq), trig);
 		kfree(trig_info);
 		iio_trigger_unregister(trig);
@@ -140,7 +140,7 @@ static int iio_gpio_trigger_remove(struct platform_device *pdev)
 				 trig2,
 				 &iio_gpio_trigger_list,
 				 alloc_list) {
-		trig_info = trig->private_data;
+		trig_info = iio_trigger_get_drvdata(trig);
 		iio_trigger_unregister(trig);
 		free_irq(trig_info->irq, trig);
 		kfree(trig_info);
diff --git a/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c b/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c
index 9102b1b..7969597 100644
--- a/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c
+++ b/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c
@@ -30,7 +30,7 @@ struct iio_prtc_trigger_info {
 
 static int iio_trig_periodic_rtc_set_state(struct iio_trigger *trig, bool state)
 {
-	struct iio_prtc_trigger_info *trig_info = trig->private_data;
+	struct iio_prtc_trigger_info *trig_info = iio_trigger_get_drvdata(trig);
 	if (trig_info->frequency == 0)
 		return -EINVAL;
 	printk(KERN_INFO "trigger frequency is %d\n", trig_info->frequency);
@@ -42,7 +42,7 @@ static ssize_t iio_trig_periodic_read_freq(struct device *dev,
 					   char *buf)
 {
 	struct iio_trigger *trig = to_iio_trigger(dev);
-	struct iio_prtc_trigger_info *trig_info = trig->private_data;
+	struct iio_prtc_trigger_info *trig_info = iio_trigger_get_drvdata(trig);
 	return sprintf(buf, "%u\n", trig_info->frequency);
 }
 
@@ -52,7 +52,7 @@ static ssize_t iio_trig_periodic_write_freq(struct device *dev,
 					    size_t len)
 {
 	struct iio_trigger *trig = to_iio_trigger(dev);
-	struct iio_prtc_trigger_info *trig_info = trig->private_data;
+	struct iio_prtc_trigger_info *trig_info = iio_trigger_get_drvdata(trig);
 	unsigned long val;
 	int ret;
 
@@ -124,7 +124,7 @@ static int iio_trig_periodic_rtc_probe(struct platform_device *dev)
 			ret = -ENOMEM;
 			goto error_put_trigger_and_remove_from_list;
 		}
-		trig->private_data = trig_info;
+		iio_trigger_set_drvdata(trig, trig_info);
 		trig->ops = &iio_prtc_trigger_ops;
 		/* RTC access */
 		trig_info->rtc
@@ -158,7 +158,7 @@ error_free_completed_registrations:
 				 trig2,
 				 &iio_prtc_trigger_list,
 				 alloc_list) {
-		trig_info = trig->private_data;
+		trig_info = iio_trigger_get_drvdata(trig);
 		rtc_irq_unregister(trig_info->rtc, &trig_info->task);
 		rtc_class_close(trig_info->rtc);
 		kfree(trig_info);
@@ -176,7 +176,7 @@ static int iio_trig_periodic_rtc_remove(struct platform_device *dev)
 				 trig2,
 				 &iio_prtc_trigger_list,
 				 alloc_list) {
-		trig_info = trig->private_data;
+		trig_info = iio_trigger_get_drvdata(trig);
 		rtc_irq_unregister(trig_info->rtc, &trig_info->task);
 		rtc_class_close(trig_info->rtc);
 		kfree(trig_info);
diff --git a/drivers/staging/iio/trigger/iio-trig-sysfs.c b/drivers/staging/iio/trigger/iio-trig-sysfs.c
index 3bac972..b727bde 100644
--- a/drivers/staging/iio/trigger/iio-trig-sysfs.c
+++ b/drivers/staging/iio/trigger/iio-trig-sysfs.c
@@ -103,7 +103,7 @@ static ssize_t iio_sysfs_trigger_poll(struct device *dev,
 		struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct iio_trigger *trig = to_iio_trigger(dev);
-	struct iio_sysfs_trig *sysfs_trig = trig->private_data;
+	struct iio_sysfs_trig *sysfs_trig = iio_trigger_get_drvdata(trig);
 
 	irq_work_queue(&sysfs_trig->work);
 
@@ -160,7 +160,7 @@ static int iio_sysfs_trigger_probe(int id)
 	t->trig->dev.groups = iio_sysfs_trigger_attr_groups;
 	t->trig->ops = &iio_sysfs_trigger_ops;
 	t->trig->dev.parent = &iio_sysfs_trig_dev;
-	t->trig->private_data = t;
+	iio_trigger_set_drvdata(t->trig, t);
 
 	init_irq_work(&t->work, iio_sysfs_trigger_work);
 
diff --git a/drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h b/drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h
index 99d1cce..66572d5 100644
--- a/drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h
+++ b/drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h
@@ -292,7 +292,8 @@ static inline void ipu_cpmem_interlaced_scan(struct ipu_ch_param *p,
 
 void ipu_cpmem_set_yuv_planar(struct ipu_ch_param __iomem *p, u32 pixel_format,
 			int stride, int height);
-void ipu_cpmem_set_yuv_interleaved(struct ipu_ch_param *p, u32 pixel_format);
+void ipu_cpmem_set_yuv_interleaved(struct ipu_ch_param __iomem *p,
+				   u32 pixel_format);
 void ipu_cpmem_set_yuv_planar_full(struct ipu_ch_param __iomem *p,
 		u32 pixel_format, int stride, int u_offset, int v_offset);
 int ipu_cpmem_set_fmt(struct ipu_ch_param __iomem *cpmem, u32 pixelformat);
diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-common.c b/drivers/staging/imx-drm/ipu-v3/ipu-common.c
index 366f259..0127601 100644
--- a/drivers/staging/imx-drm/ipu-v3/ipu-common.c
+++ b/drivers/staging/imx-drm/ipu-v3/ipu-common.c
@@ -16,6 +16,7 @@
 #include <linux/export.h>
 #include <linux/types.h>
 #include <linux/init.h>
+#include <linux/reset.h>
 #include <linux/platform_device.h>
 #include <linux/err.h>
 #include <linux/spinlock.h>
@@ -25,8 +26,8 @@
 #include <linux/clk.h>
 #include <linux/list.h>
 #include <linux/irq.h>
+#include <linux/irqchip/chained_irq.h>
 #include <linux/of_device.h>
-#include <asm/mach/irq.h>
 
 #include "imx-ipu-v3.h"
 #include "ipu-prv.h"
@@ -225,7 +226,8 @@ int ipu_cpmem_set_format_passthrough(struct ipu_ch_param __iomem *p,
 }
 EXPORT_SYMBOL_GPL(ipu_cpmem_set_format_passthrough);
 
-void ipu_cpmem_set_yuv_interleaved(struct ipu_ch_param *p, u32 pixel_format)
+void ipu_cpmem_set_yuv_interleaved(struct ipu_ch_param __iomem *p,
+				   u32 pixel_format)
 {
 	switch (pixel_format) {
 	case V4L2_PIX_FMT_UYVY:
@@ -660,7 +662,7 @@ int ipu_idmac_disable_channel(struct ipuv3_channel *channel)
 }
 EXPORT_SYMBOL_GPL(ipu_idmac_disable_channel);
 
-static int ipu_reset(struct ipu_soc *ipu)
+static int ipu_memory_reset(struct ipu_soc *ipu)
 {
 	unsigned long timeout;
 
@@ -1104,7 +1106,12 @@ static int ipu_probe(struct platform_device *pdev)
 	if (ret)
 		goto out_failed_irq;
 
-	ret = ipu_reset(ipu);
+	ret = device_reset(&pdev->dev);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to reset: %d\n", ret);
+		goto out_failed_reset;
+	}
+	ret = ipu_memory_reset(ipu);
 	if (ret)
 		goto out_failed_reset;
 
@@ -1130,8 +1137,8 @@ static int ipu_probe(struct platform_device *pdev)
 failed_add_clients:
 	ipu_submodules_exit(ipu);
 failed_submodules_init:
-	ipu_irq_exit(ipu);
 out_failed_reset:
+	ipu_irq_exit(ipu);
 out_failed_irq:
 	clk_disable_unprepare(ipu->clk);
 failed_clk_get:
diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-dp.c b/drivers/staging/imx-drm/ipu-v3/ipu-dp.c
index 26aecaf..113b046 100644
--- a/drivers/staging/imx-drm/ipu-v3/ipu-dp.c
+++ b/drivers/staging/imx-drm/ipu-v3/ipu-dp.c
@@ -316,7 +316,6 @@ int ipu_dp_init(struct ipu_soc *ipu, struct device *dev, unsigned long base)
 
 	priv->base = devm_ioremap(dev, base, PAGE_SIZE);
 	if (!priv->base) {
-		kfree(priv);
 		return -ENOMEM;
 	}
 
diff --git a/drivers/staging/imx-drm/parallel-display.c b/drivers/staging/imx-drm/parallel-display.c
index a8064fc..2a25202 100644
--- a/drivers/staging/imx-drm/parallel-display.c
+++ b/drivers/staging/imx-drm/parallel-display.c
@@ -57,6 +57,7 @@ static void imx_pd_connector_destroy(struct drm_connector *connector)
 static int imx_pd_connector_get_modes(struct drm_connector *connector)
 {
 	struct imx_parallel_display *imxpd = con_to_imxpd(connector);
+	struct device_node *np = imxpd->dev->of_node;
 	int num_modes = 0;
 
 	if (imxpd->edid) {
@@ -72,6 +73,15 @@ static int imx_pd_connector_get_modes(struct drm_connector *connector)
 		num_modes++;
 	}
 
+	if (np) {
+		struct drm_display_mode *mode = drm_mode_create(connector->dev);
+		of_get_drm_display_mode(np, &imxpd->mode, 0);
+		drm_mode_copy(mode, &imxpd->mode);
+		mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
+		drm_mode_probed_add(connector, mode);
+		num_modes++;
+	}
+
 	return num_modes;
 }
 
diff --git a/drivers/staging/keucr/scsiglue.c b/drivers/staging/keucr/scsiglue.c
index 083b20e..48e1005 100644
--- a/drivers/staging/keucr/scsiglue.c
+++ b/drivers/staging/keucr/scsiglue.c
@@ -229,26 +229,18 @@ void usb_stor_report_bus_reset(struct us_data *us)
 
 /* we use this macro to help us write into the buffer */
 #undef SPRINTF
-#define SPRINTF(args...) \
-	do { \
-		if (pos < buffer+length) \
-			pos += sprintf(pos, ## args); \
-	} while (0)
+#define SPRINTF(args...) seq_printf(m, ##args)
 
-/*
- * proc_info()
- */
-static int proc_info(struct Scsi_Host *host, char *buffer, char **start,
-					off_t offset, int length, int inout)
+static int write_info(struct Scsi_Host *host, char *buffer, int length)
+{
+	return length;
+}
+
+static int show_info(struct seq_file *m, struct Scsi_Host *host)
 {
 	struct us_data *us = host_to_us(host);
-	char *pos = buffer;
 	const char *string;
 
-	/* pr_info("scsiglue --- proc_info\n"); */
-	if (inout)
-		return length;
-
 	/* print the controller name */
 	SPRINTF("   Host scsi%d: usb-storage\n", host->host_no);
 
@@ -278,29 +270,17 @@ static int proc_info(struct Scsi_Host *host, char *buffer, char **start,
 	SPRINTF("    Transport: %s\n", us->transport_name);
 
 	/* show the device flags */
-	if (pos < buffer + length) {
-		pos += sprintf(pos, "       Quirks:");
+	SPRINTF("       Quirks:");
 
 #define US_FLAG(name, value) \
 	do { \
 		if (us->fflags & value) \
-			pos += sprintf(pos, " " #name); \
+			SPRINTF(" " #name); \
 	} while (0);
 US_DO_ALL_FLAGS
 #undef US_FLAG
-
-		*(pos++) = '\n';
-	}
-
-	/* Calculate start of next buffer, and return value. */
-	*start = buffer + offset;
-
-	if ((pos - buffer) < offset)
-		return 0;
-	else if ((pos - buffer - offset) < length)
-		return pos - buffer - offset;
-	else
-		return length;
+	seq_putc(m, '\n');
+	return 0;
 }
 
 /***********************************************************************
@@ -351,7 +331,8 @@ struct scsi_host_template usb_stor_host_template = {
 	/* basic userland interface stuff */
 	.name =				"eucr-storage",
 	.proc_name =			"eucr-storage",
-	.proc_info =			proc_info,
+	.write_info =			write_info,
+	.show_info =			show_info,
 	.info =				host_info,
 
 	/* command interface -- queued only */
diff --git a/drivers/staging/line6/pod.c b/drivers/staging/line6/pod.c
index 74898c3..699b217 100644
--- a/drivers/staging/line6/pod.c
+++ b/drivers/staging/line6/pod.c
@@ -148,9 +148,8 @@ void line6_pod_process_message(struct usb_line6_pod *pod)
 	    buf[0] != (LINE6_SYSEX_BEGIN | LINE6_CHANNEL_UNKNOWN)) {
 		return;
 	}
-	if (memcmp(buf + 1, line6_midi_id, sizeof(line6_midi_id)) != 0) {
+	if (memcmp(buf + 1, line6_midi_id, sizeof(line6_midi_id)) != 0)
 		return;
-	}
 
 	if (buf[5] == POD_SYSEX_SYSTEM && buf[6] == POD_MONITOR_LEVEL) {
 		short value = ((int)buf[7] << 12) | ((int)buf[8] << 8) |
diff --git a/drivers/staging/media/as102/Makefile b/drivers/staging/media/as102/Makefile
index d8dfb75..8916d8a 100644
--- a/drivers/staging/media/as102/Makefile
+++ b/drivers/staging/media/as102/Makefile
@@ -3,4 +3,4 @@ dvb-as102-objs := as102_drv.o as102_fw.o as10x_cmd.o as10x_cmd_stream.o \
 
 obj-$(CONFIG_DVB_AS102) += dvb-as102.o
 
-EXTRA_CFLAGS += -Idrivers/media/dvb-core
+ccflags-y += -Idrivers/media/dvb-core
diff --git a/drivers/staging/media/davinci_vpfe/davinci-vpfe-mc.txt b/drivers/staging/media/davinci_vpfe/davinci-vpfe-mc.txt
index 1dbd564..a1e9177 100644
--- a/drivers/staging/media/davinci_vpfe/davinci-vpfe-mc.txt
+++ b/drivers/staging/media/davinci_vpfe/davinci-vpfe-mc.txt
@@ -38,7 +38,7 @@ interface to userspace.
 	DAVINCI RESIZER A
 	DAVINCI RESIZER B
 
-Each possible link in the VPFE is modeled by a link in the Media controller
+Each possible link in the VPFE is modelled by a link in the Media controller
 interface. For an example program see [1].
 
 
diff --git a/drivers/staging/media/davinci_vpfe/dm365_ipipe.c b/drivers/staging/media/davinci_vpfe/dm365_ipipe.c
index 9285353..05673ed 100644
--- a/drivers/staging/media/davinci_vpfe/dm365_ipipe.c
+++ b/drivers/staging/media/davinci_vpfe/dm365_ipipe.c
@@ -1859,5 +1859,5 @@ void vpfe_ipipe_cleanup(struct vpfe_ipipe_device *ipipe,
 	iounmap(ipipe->isp5_base_addr);
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 4);
 	if (res)
-		release_mem_region(res->start, res->end - res->start + 1);
+		release_mem_region(res->start, resource_size(res));
 }
diff --git a/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c b/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c
index c8cae51..b2f4ef8 100644
--- a/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c
+++ b/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c
@@ -1065,7 +1065,6 @@ vpfe_ipipeif_cleanup(struct vpfe_ipipeif_device *ipipeif,
 	iounmap(ipipeif->ipipeif_base_addr);
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 3);
 	if (res)
-		release_mem_region(res->start,
-					res->end - res->start + 1);
+		release_mem_region(res->start, resource_size(res));
 
 }
diff --git a/drivers/staging/media/davinci_vpfe/dm365_isif.c b/drivers/staging/media/davinci_vpfe/dm365_isif.c
index ebeea72..5829360 100644
--- a/drivers/staging/media/davinci_vpfe/dm365_isif.c
+++ b/drivers/staging/media/davinci_vpfe/dm365_isif.c
@@ -685,7 +685,7 @@ static void isif_config_bclamp(struct vpfe_isif_device *isif,
 	val = (bc->bc_mode_color & ISIF_BC_MODE_COLOR_MASK) <<
 		ISIF_BC_MODE_COLOR_SHIFT;
 
-	/* Enable BC and horizontal clamp caculation paramaters */
+	/* Enable BC and horizontal clamp calculation paramaters */
 	val = val | 1 | ((bc->horz.mode & ISIF_HORZ_BC_MODE_MASK) <<
 	      ISIF_HORZ_BC_MODE_SHIFT);
 
@@ -722,7 +722,7 @@ static void isif_config_bclamp(struct vpfe_isif_device *isif,
 		isif_write(isif->isif_cfg.base_addr, val, CLHWIN2);
 	}
 
-	/* vertical clamp caculation paramaters */
+	/* vertical clamp calculation paramaters */
 	/* OB H Valid */
 	val = bc->vert.ob_h_sz_calc & ISIF_VERT_BC_OB_H_SZ_MASK;
 
@@ -1569,7 +1569,7 @@ isif_pad_set_crop(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
 		crop->rect.width = format->width;
 		crop->rect.height = format->height;
 	}
-	/* adjust the width to 16 pixel boundry */
+	/* adjust the width to 16 pixel boundary */
 	crop->rect.width = ((crop->rect.width + 15) & ~0xf);
 	vpfe_isif->crop = crop->rect;
 	if (crop->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
@@ -1953,7 +1953,7 @@ static void isif_remove(struct vpfe_isif_device *isif,
 		res = platform_get_resource(pdev, IORESOURCE_MEM, i);
 		if (res)
 			release_mem_region(res->start,
-					   res->end - res->start + 1);
+					   resource_size(res));
 		i++;
 	}
 }
@@ -2003,7 +2003,7 @@ int vpfe_isif_init(struct vpfe_isif_device *isif, struct platform_device *pdev)
 			status = -ENOENT;
 			goto fail_nobase_res;
 		}
-		res_len = res->end - res->start + 1;
+		res_len = resource_size(res);
 		res = request_mem_region(res->start, res_len, res->name);
 		if (!res) {
 			status = -EBUSY;
diff --git a/drivers/staging/media/davinci_vpfe/dm365_resizer.c b/drivers/staging/media/davinci_vpfe/dm365_resizer.c
index 9cb0262..126f84c 100644
--- a/drivers/staging/media/davinci_vpfe/dm365_resizer.c
+++ b/drivers/staging/media/davinci_vpfe/dm365_resizer.c
@@ -1995,5 +1995,5 @@ vpfe_resizer_cleanup(struct vpfe_resizer_device *vpfe_rsz,
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 5);
 	if (res)
 		release_mem_region(res->start,
-					res->end - res->start + 1);
+					resource_size(res));
 }
diff --git a/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c b/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c
index 7b35171..b88e1dd 100644
--- a/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c
+++ b/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c
@@ -243,7 +243,7 @@ static int vpfe_enable_clock(struct vpfe_device *vpfe_dev)
 
 		vpfe_dev->clks[i] =
 				clk_get(vpfe_dev->pdev, vpfe_cfg->clocks[i]);
-		if (vpfe_dev->clks[i] == NULL) {
+		if (IS_ERR(vpfe_dev->clks[i])) {
 			v4l2_err(vpfe_dev->pdev->driver,
 				"Failed to get clock %s\n",
 				vpfe_cfg->clocks[i]);
@@ -264,7 +264,7 @@ static int vpfe_enable_clock(struct vpfe_device *vpfe_dev)
 	return 0;
 out:
 	for (i = 0; i < vpfe_cfg->num_clocks; i++)
-		if (vpfe_dev->clks[i]) {
+		if (!IS_ERR(vpfe_dev->clks[i])) {
 			clk_disable_unprepare(vpfe_dev->clks[i]);
 			clk_put(vpfe_dev->clks[i]);
 		}
@@ -719,22 +719,4 @@ static struct platform_driver vpfe_driver = {
 	.remove = vpfe_remove,
 };
 
-/**
- * vpfe_init : This function registers device driver
- */
-static __init int vpfe_init(void)
-{
-	/* Register driver to the kernel */
-	return platform_driver_register(&vpfe_driver);
-}
-
-/**
- * vpfe_cleanup : This function un-registers device driver
- */
-static void vpfe_cleanup(void)
-{
-	platform_driver_unregister(&vpfe_driver);
-}
-
-module_init(vpfe_init);
-module_exit(vpfe_cleanup);
+module_platform_driver(vpfe_driver);
diff --git a/drivers/staging/media/davinci_vpfe/vpfe_video.c b/drivers/staging/media/davinci_vpfe/vpfe_video.c
index 99ccbeb..ba913f1 100644
--- a/drivers/staging/media/davinci_vpfe/vpfe_video.c
+++ b/drivers/staging/media/davinci_vpfe/vpfe_video.c
@@ -357,7 +357,7 @@ static int vpfe_pipeline_disable(struct vpfe_pipeline *pipe)
  *
  * Set the pipeline to the given stream state.
  *
- * Return 0 if successfull, or the return value of the failed video::s_stream
+ * Return 0 if successful, or the return value of the failed video::s_stream
  * operation otherwise.
  */
 static int vpfe_pipeline_set_stream(struct vpfe_pipeline *pipe,
@@ -644,7 +644,7 @@ static int vpfe_g_fmt(struct file *file, void *priv,
  * fills v4l2_fmtdesc structure with output format set on adjacent subdev,
  * only one format is enumearted as subdevs are already configured
  *
- * Return 0 if successfull, error code otherwise
+ * Return 0 if successful, error code otherwise
  */
 static int vpfe_enum_fmt(struct file *file, void  *priv,
 				   struct v4l2_fmtdesc *fmt)
@@ -769,7 +769,7 @@ static int vpfe_try_fmt(struct file *file, void *priv,
  * fills v4l2_input structure with input available on media chain,
  * only one input is enumearted as media chain is setup by this time
  *
- * Return 0 if successfull, -EINVAL is media chain is invalid
+ * Return 0 if successful, -EINVAL is media chain is invalid
  */
 static int vpfe_enum_input(struct file *file, void *priv,
 				 struct v4l2_input *inp)
@@ -779,7 +779,7 @@ static int vpfe_enum_input(struct file *file, void *priv,
 	struct vpfe_device *vpfe_dev = video->vpfe_dev;
 
 	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_enum_input\n");
-	/* enumerate from the subdev user has choosen through mc */
+	/* enumerate from the subdev user has chosen through mc */
 	if (inp->index < sdinfo->num_inputs) {
 		memcpy(inp, &sdinfo->inputs[inp->index],
 		       sizeof(struct v4l2_input));
@@ -924,7 +924,7 @@ static int vpfe_querystd(struct file *file, void *priv, v4l2_std_id *std_id)
  *
  * Return 0 on success, error code otherwise
  */
-static int vpfe_s_std(struct file *file, void *priv, v4l2_std_id *std_id)
+static int vpfe_s_std(struct file *file, void *priv, v4l2_std_id std_id)
 {
 	struct vpfe_video_device *video = video_drvdata(file);
 	struct vpfe_device *vpfe_dev = video->vpfe_dev;
@@ -945,13 +945,13 @@ static int vpfe_s_std(struct file *file, void *priv, v4l2_std_id *std_id)
 		goto unlock_out;
 	}
 	ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id,
-					 core, s_std, *std_id);
+					 core, s_std, std_id);
 	if (ret < 0) {
 		v4l2_err(&vpfe_dev->v4l2_dev, "Failed to set standard\n");
 		video->stdid = V4L2_STD_UNKNOWN;
 		goto unlock_out;
 	}
-	video->stdid = *std_id;
+	video->stdid = std_id;
 unlock_out:
 	mutex_unlock(&video->lock);
 	return ret;
@@ -1016,12 +1016,12 @@ vpfe_query_dv_timings(struct file *file, void *fh,
 }
 
 /*
- * vpfe_s_dv_timings() - set dv_preset on external subdev
+ * vpfe_s_dv_timings() - set dv_timings on external subdev
  * @file: file pointer
  * @priv: void pointer
  * @timings: pointer to v4l2_dv_timings structure
  *
- * set dv_timings pointed by preset on external subdev through
+ * set dv_timings pointed by timings on external subdev through
  * v4l2_device_call_until_err, this configures amplifier also
  *
  * Return 0 on success, error code otherwise
@@ -1042,12 +1042,12 @@ vpfe_s_dv_timings(struct file *file, void *fh,
 }
 
 /*
- * vpfe_g_dv_timings() - get dv_preset which is set on external subdev
+ * vpfe_g_dv_timings() - get dv_timings which is set on external subdev
  * @file: file pointer
  * @priv: void pointer
  * @timings: pointer to v4l2_dv_timings structure
  *
- * get dv_preset which is set on external subdev through
+ * get dv_timings which is set on external subdev through
  * v4l2_subdev_call
  *
  * Return 0 on success, error code otherwise
@@ -1423,7 +1423,7 @@ static int vpfe_dqbuf(struct file *file, void *priv,
 }
 
 /*
- * vpfe_streamon() - get dv_preset which is set on external subdev
+ * vpfe_streamon() - start streaming
  * @file: file pointer
  * @priv: void pointer
  * @buf_type: enum v4l2_buf_type
@@ -1472,7 +1472,7 @@ static int vpfe_streamon(struct file *file, void *priv,
 }
 
 /*
- * vpfe_streamoff() - get dv_preset which is set on external subdev
+ * vpfe_streamoff() - stop streaming
  * @file: file pointer
  * @priv: void pointer
  * @buf_type: enum v4l2_buf_type
diff --git a/drivers/staging/media/davinci_vpfe/vpfe_video.h b/drivers/staging/media/davinci_vpfe/vpfe_video.h
index bf8af01..df0aeec 100644
--- a/drivers/staging/media/davinci_vpfe/vpfe_video.h
+++ b/drivers/staging/media/davinci_vpfe/vpfe_video.h
@@ -138,7 +138,7 @@ struct vpfe_video_device {
 	v4l2_std_id				stdid;
 	/*
 	 * offset where second field starts from the starting of the
-	 * buffer for field seperated YCbCr formats
+	 * buffer for field separated YCbCr formats
 	 */
 	u32					field_off;
 };
diff --git a/drivers/staging/media/dt3155v4l/dt3155v4l.c b/drivers/staging/media/dt3155v4l/dt3155v4l.c
index e33b7f5..073b3b3 100644
--- a/drivers/staging/media/dt3155v4l/dt3155v4l.c
+++ b/drivers/staging/media/dt3155v4l/dt3155v4l.c
@@ -612,9 +612,9 @@ dt3155_ioc_g_std(struct file *filp, void *p, v4l2_std_id *norm)
 }
 
 static int
-dt3155_ioc_s_std(struct file *filp, void *p, v4l2_std_id *norm)
+dt3155_ioc_s_std(struct file *filp, void *p, v4l2_std_id norm)
 {
-	if (*norm & DT3155_CURRENT_NORM)
+	if (norm & DT3155_CURRENT_NORM)
 		return 0;
 	return -EINVAL;
 }
diff --git a/drivers/staging/media/go7007/Kconfig b/drivers/staging/media/go7007/Kconfig
index 7dfb281..b10f996 100644
--- a/drivers/staging/media/go7007/Kconfig
+++ b/drivers/staging/media/go7007/Kconfig
@@ -1,20 +1,24 @@
 config VIDEO_GO7007
 	tristate "WIS GO7007 MPEG encoder support"
-	depends on VIDEO_DEV && PCI && I2C
+	depends on VIDEO_DEV && I2C
 	depends on SND
-	select VIDEOBUF_DMA_SG
-	depends on RC_CORE
+	select VIDEOBUF2_VMALLOC
 	select VIDEO_TUNER
-	select VIDEO_TVEEPROM
 	select SND_PCM
-	select CRC32
+	select VIDEO_SONY_BTF_MPX if MEDIA_SUBDRV_AUTOSELECT
+	select VIDEO_SAA711X if MEDIA_SUBDRV_AUTOSELECT
+	select VIDEO_TW2804 if MEDIA_SUBDRV_AUTOSELECT
+	select VIDEO_TW9903 if MEDIA_SUBDRV_AUTOSELECT
+	select VIDEO_TW9906 if MEDIA_SUBDRV_AUTOSELECT
+	select VIDEO_OV7640 if MEDIA_SUBDRV_AUTOSELECT
+	select VIDEO_UDA1342 if MEDIA_SUBDRV_AUTOSELECT
 	default N
 	---help---
 	  This is a video4linux driver for the WIS GO7007 MPEG
 	  encoder chip.
 
 	  To compile this driver as a module, choose M here: the
-	  module will be called go7007
+	  module will be called go7007.
 
 config VIDEO_GO7007_USB
 	tristate "WIS GO7007 USB support"
@@ -25,85 +29,25 @@ config VIDEO_GO7007_USB
 	  encoder chip over USB.
 
 	  To compile this driver as a module, choose M here: the
-	  module will be called go7007-usb
+	  module will be called go7007-usb.
 
-config VIDEO_GO7007_USB_S2250_BOARD
-	tristate "Sensoray 2250/2251 support"
-	depends on VIDEO_GO7007_USB && DVB_USB
-	default N
-	---help---
-	  This is a video4linux driver for the Sensoray 2250/2251 device.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called s2250
-
-config VIDEO_GO7007_OV7640
-	tristate "OV7640 subdev support"
-	depends on VIDEO_GO7007
-	default N
-	---help---
-	  This is a video4linux driver for the OV7640 sub-device.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called wis-ov7640
-
-config VIDEO_GO7007_SAA7113
-	tristate "SAA7113 subdev support"
-	depends on VIDEO_GO7007
-	default N
-	---help---
-	  This is a video4linux driver for the SAA7113 sub-device.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called wis-saa7113
-
-config VIDEO_GO7007_SAA7115
-	tristate "SAA7115 subdev support"
-	depends on VIDEO_GO7007
-	default N
+config VIDEO_GO7007_LOADER
+	tristate "WIS GO7007 Loader support"
+	depends on VIDEO_GO7007 && DVB_USB
+	default y
 	---help---
-	  This is a video4linux driver for the SAA7115 sub-device.
+	  This is a go7007 firmware loader driver for the WIS GO7007
+	  MPEG encoder chip over USB.
 
 	  To compile this driver as a module, choose M here: the
-	  module will be called wis-saa7115
+	  module will be called go7007-loader.
 
-config VIDEO_GO7007_TW9903
-	tristate "TW9903 subdev support"
-	depends on VIDEO_GO7007
-	default N
-	---help---
-	  This is a video4linux driver for the TW9903 sub-device.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called wis-tw9903
-
-config VIDEO_GO7007_UDA1342
-	tristate "UDA1342 subdev support"
-	depends on VIDEO_GO7007
-	default N
-	---help---
-	  This is a video4linux driver for the UDA1342 sub-device.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called wis-uda1342
-
-config VIDEO_GO7007_SONY_TUNER
-	tristate "Sony tuner subdev support"
-	depends on VIDEO_GO7007
-	default N
-	---help---
-	  This is a video4linux driver for the Sony Tuner sub-device.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called wis-sony-tuner
-
-config VIDEO_GO7007_TW2804
-	tristate "TW2804 subdev support"
-	depends on VIDEO_GO7007
+config VIDEO_GO7007_USB_S2250_BOARD
+	tristate "Sensoray 2250/2251 support"
+	depends on VIDEO_GO7007_USB && USB
 	default N
 	---help---
-	  This is a video4linux driver for the TW2804 sub-device.
+	  This is a video4linux driver for the Sensoray 2250/2251 device.
 
 	  To compile this driver as a module, choose M here: the
-	  module will be called wis-tw2804
-
+	  module will be called s2250.
diff --git a/drivers/staging/media/go7007/Makefile b/drivers/staging/media/go7007/Makefile
index 3fdbef5..bbc8a320 100644
--- a/drivers/staging/media/go7007/Makefile
+++ b/drivers/staging/media/go7007/Makefile
@@ -1,18 +1,7 @@
-#obj-m += go7007.o go7007-usb.o snd-go7007.o wis-saa7115.o wis-tw9903.o \
-		wis-uda1342.o wis-sony-tuner.o wis-saa7113.o wis-ov7640.o \
-		wis-tw2804.o
-
-
 obj-$(CONFIG_VIDEO_GO7007) += go7007.o
 obj-$(CONFIG_VIDEO_GO7007_USB) += go7007-usb.o
-obj-$(CONFIG_VIDEO_GO7007_USB_S2250_BOARD) += s2250.o s2250-loader.o
-obj-$(CONFIG_VIDEO_GO7007_SAA7113) += wis-saa7113.o
-obj-$(CONFIG_VIDEO_GO7007_OV7640) += wis-ov7640.o
-obj-$(CONFIG_VIDEO_GO7007_SAA7115) += wis-saa7115.o
-obj-$(CONFIG_VIDEO_GO7007_TW9903) += wis-tw9903.o
-obj-$(CONFIG_VIDEO_GO7007_UDA1342) += wis-uda1342.o
-obj-$(CONFIG_VIDEO_GO7007_SONY_TUNER) += wis-sony-tuner.o
-obj-$(CONFIG_VIDEO_GO7007_TW2804) += wis-tw2804.o
+obj-$(CONFIG_VIDEO_GO7007_LOADER) += go7007-loader.o
+obj-$(CONFIG_VIDEO_GO7007_USB_S2250_BOARD) += s2250.o
 
 go7007-y := go7007-v4l2.o go7007-driver.o go7007-i2c.o go7007-fw.o \
 		snd-go7007.o
@@ -21,10 +10,10 @@ s2250-y := s2250-board.o
 
 # Uncomment when the saa7134 patches get into upstream
 #obj-$(CONFIG_VIDEO_SAA7134) += saa7134-go7007.o
-#ccflags-$(CONFIG_VIDEO_SAA7134:m=y) += -Idrivers/media/video/saa7134 -DSAA7134_MPEG_GO7007=3
+#ccflags-$(CONFIG_VIDEO_SAA7134:m=y) += -Idrivers/media/pci/saa7134
 
-# S2250 needs cypress ezusb loader from dvb-usb
-ccflags-$(CONFIG_VIDEO_GO7007_USB_S2250_BOARD:m=y) += -Idrivers/media/usb/dvb-usb
+# go7007-loader needs cypress ezusb loader from dvb-usb-v2
+ccflags-$(CONFIG_VIDEO_GO7007_LOADER:m=y) += -Idrivers/media/usb/dvb-usb-v2
 
 ccflags-y += -Idrivers/media/dvb-frontends
 ccflags-y += -Idrivers/media/dvb-core
diff --git a/drivers/staging/media/go7007/README b/drivers/staging/media/go7007/README
index aeba132..3af0d90 100644
--- a/drivers/staging/media/go7007/README
+++ b/drivers/staging/media/go7007/README
@@ -1,11 +1,137 @@
 Todo:
-	- checkpatch.pl cleanups
-	- sparse cleanups
-	- lots of little modules, should be merged together
-	  and added to the build.
-	- testing?
-	- handle churn in v4l layer.
+	- create an API for motion detection
+	- let s2250-board use i2c subdevs as well instead of hardcoding
+	  support for the i2c devices.
+	- when the driver is moved out of staging, support for saa7134-go7007
+	  should be added to the saa7134 driver. The patch for that is
+	  included below.
 
-Please send patches to Greg Kroah-Hartman <greg@linuxfoundation.org> and Cc: Ross
-Cohen <rcohen@snurgle.org> as well.
+Patch for saa7134:
 
+diff --git a/drivers/media/pci/saa7134/saa7134-cards.c b/drivers/media/pci/saa7134/saa7134-cards.c
+index dc68cf1..9a53794 100644
+--- a/drivers/media/pci/saa7134/saa7134-cards.c
++++ b/drivers/media/pci/saa7134/saa7134-cards.c
+@@ -5790,6 +5790,29 @@ struct saa7134_board saa7134_boards[] = {
+ 			.gpio = 0x6010000,
+ 		} },
+ 	},
++	[SAA7134_BOARD_WIS_VOYAGER] = {
++		.name           = "WIS Voyager or compatible",
++		.audio_clock    = 0x00200000,
++		.tuner_type	= TUNER_PHILIPS_TDA8290,
++		.radio_type     = UNSET,
++		.tuner_addr     = ADDR_UNSET,
++		.radio_addr     = ADDR_UNSET,
++		.mpeg		= SAA7134_MPEG_GO7007,
++		.inputs		= { {
++			.name = name_comp1,
++			.vmux = 0,
++			.amux = LINE2,
++		}, {
++			.name = name_tv,
++			.vmux = 3,
++			.amux = TV,
++			.tv   = 1,
++		}, {
++			.name = name_svideo,
++			.vmux = 6,
++		.amux = LINE1,
++		} },
++	},
+ 
+ };
+ 
+@@ -7037,6 +7060,12 @@ struct pci_device_id saa7134_pci_tbl[] = {
+ 		.subdevice    = 0x0911,
+ 		.driver_data  = SAA7134_BOARD_SENSORAY811_911,
+ 	}, {
++		.vendor       = PCI_VENDOR_ID_PHILIPS,
++		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
++		.subvendor    = 0x1905, /* WIS */
++		.subdevice    = 0x7007,
++		.driver_data  = SAA7134_BOARD_WIS_VOYAGER,
++	}, {
+ 		/* --- boards without eeprom + subsystem ID --- */
+ 		.vendor       = PCI_VENDOR_ID_PHILIPS,
+ 		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+diff --git a/drivers/media/pci/saa7134/saa7134-core.c b/drivers/media/pci/saa7134/saa7134-core.c
+index 8fd24e7..0a849ea 100644
+--- a/drivers/media/pci/saa7134/saa7134-core.c
++++ b/drivers/media/pci/saa7134/saa7134-core.c
+@@ -156,6 +156,8 @@ static void request_module_async(struct work_struct *work){
+ 		request_module("saa7134-empress");
+ 	if (card_is_dvb(dev))
+ 		request_module("saa7134-dvb");
++	if (card_is_go7007(dev))
++		request_module("saa7134-go7007");
+ 	if (alsa) {
+ 		if (dev->pci->device != PCI_DEVICE_ID_PHILIPS_SAA7130)
+ 			request_module("saa7134-alsa");
+@@ -557,8 +559,12 @@ static irqreturn_t saa7134_irq(int irq, void *dev_id)
+ 			saa7134_irq_vbi_done(dev,status);
+ 
+ 		if ((report & SAA7134_IRQ_REPORT_DONE_RA2) &&
+-		    card_has_mpeg(dev))
+-			saa7134_irq_ts_done(dev,status);
++		    card_has_mpeg(dev)) {
++			if (dev->mops->irq_ts_done != NULL)
++				dev->mops->irq_ts_done(dev, status);
++			else
++				saa7134_irq_ts_done(dev, status);
++		}
+ 
+ 		if (report & SAA7134_IRQ_REPORT_GPIO16) {
+ 			switch (dev->has_remote) {
+diff --git a/drivers/media/pci/saa7134/saa7134.h b/drivers/media/pci/saa7134/saa7134.h
+index 62169dd..5fad39a 100644
+--- a/drivers/media/pci/saa7134/saa7134.h
++++ b/drivers/media/pci/saa7134/saa7134.h
+@@ -334,6 +334,7 @@ struct saa7134_card_ir {
+ #define SAA7134_BOARD_KWORLD_PC150U         189
+ #define SAA7134_BOARD_ASUSTeK_PS3_100      190
+ #define SAA7134_BOARD_HAWELL_HW_9004V1      191
++#define SAA7134_BOARD_WIS_VOYAGER           192
+ 
+ #define SAA7134_MAXBOARDS 32
+ #define SAA7134_INPUT_MAX 8
+@@ -364,6 +365,7 @@ enum saa7134_mpeg_type {
+ 	SAA7134_MPEG_UNUSED,
+ 	SAA7134_MPEG_EMPRESS,
+ 	SAA7134_MPEG_DVB,
++	SAA7134_MPEG_GO7007,
+ };
+ 
+ enum saa7134_mpeg_ts_type {
+@@ -403,6 +405,7 @@ struct saa7134_board {
+ #define card_has_radio(dev)   (NULL != saa7134_boards[dev->board].radio.name)
+ #define card_is_empress(dev)  (SAA7134_MPEG_EMPRESS == saa7134_boards[dev->board].mpeg)
+ #define card_is_dvb(dev)      (SAA7134_MPEG_DVB     == saa7134_boards[dev->board].mpeg)
++#define card_is_go7007(dev)   (SAA7134_MPEG_GO7007  == saa7134_boards[dev->board].mpeg)
+ #define card_has_mpeg(dev)    (SAA7134_MPEG_UNUSED  != saa7134_boards[dev->board].mpeg)
+ #define card(dev)             (saa7134_boards[dev->board])
+ #define card_in(dev,n)        (saa7134_boards[dev->board].inputs[n])
+@@ -535,6 +538,8 @@ struct saa7134_mpeg_ops {
+ 	int                        (*init)(struct saa7134_dev *dev);
+ 	int                        (*fini)(struct saa7134_dev *dev);
+ 	void                       (*signal_change)(struct saa7134_dev *dev);
++	void                       (*irq_ts_done)(struct saa7134_dev *dev,
++						  unsigned long status);
+ };
+ 
+ /* global device status */
+diff --git a/drivers/staging/media/go7007/Makefile b/drivers/staging/media/go7007/Makefile
+index 9c6ad4a..1b23689 100644
+--- a/drivers/staging/media/go7007/Makefile
++++ b/drivers/staging/media/go7007/Makefile
+@@ -8,8 +8,7 @@ go7007-y := go7007-v4l2.o go7007-driver.o go7007-i2c.o go7007-fw.o \
+ 
+ s2250-y := s2250-board.o
+ 
+-# Uncomment when the saa7134 patches get into upstream
+-#obj-$(CONFIG_VIDEO_SAA7134) += saa7134-go7007.o
+-#ccflags-$(CONFIG_VIDEO_SAA7134:m=y) += -Idrivers/media/pci/saa7134
++obj-$(CONFIG_VIDEO_SAA7134) += saa7134-go7007.o
++ccflags-$(CONFIG_VIDEO_SAA7134:m=y) += -Idrivers/media/pci/saa7134
+ 
+ ccflags-$(CONFIG_VIDEO_GO7007_LOADER:m=y) += -Idrivers/media/common
diff --git a/drivers/staging/media/go7007/go7007-driver.c b/drivers/staging/media/go7007/go7007-driver.c
index 6695091..3640df0 100644
--- a/drivers/staging/media/go7007/go7007-driver.c
+++ b/drivers/staging/media/go7007/go7007-driver.c
@@ -35,7 +35,6 @@
 #include <media/v4l2-common.h>
 
 #include "go7007-priv.h"
-#include "wis-i2c.h"
 
 /*
  * Wait for an interrupt to be delivered from the GO7007SB and return
@@ -91,43 +90,43 @@ EXPORT_SYMBOL(go7007_read_addr);
 static int go7007_load_encoder(struct go7007 *go)
 {
 	const struct firmware *fw_entry;
-	char fw_name[] = "go7007fw.bin";
+	char fw_name[] = "go7007/go7007fw.bin";
 	void *bounce;
 	int fw_len, rv = 0;
 	u16 intr_val, intr_data;
 
-	if (request_firmware(&fw_entry, fw_name, go->dev)) {
-		v4l2_err(go, "unable to load firmware from file "
-			"\"%s\"\n", fw_name);
-		return -1;
-	}
-	if (fw_entry->size < 16 || memcmp(fw_entry->data, "WISGO7007FW", 11)) {
-		v4l2_err(go, "file \"%s\" does not appear to be "
-				"go7007 firmware\n", fw_name);
-		release_firmware(fw_entry);
-		return -1;
-	}
-	fw_len = fw_entry->size - 16;
-	bounce = kmemdup(fw_entry->data + 16, fw_len, GFP_KERNEL);
-	if (bounce == NULL) {
-		v4l2_err(go, "unable to allocate %d bytes for "
-				"firmware transfer\n", fw_len);
+	if (go->boot_fw == NULL) {
+		if (request_firmware(&fw_entry, fw_name, go->dev)) {
+			v4l2_err(go, "unable to load firmware from file \"%s\"\n", fw_name);
+			return -1;
+		}
+		if (fw_entry->size < 16 || memcmp(fw_entry->data, "WISGO7007FW", 11)) {
+			v4l2_err(go, "file \"%s\" does not appear to be go7007 firmware\n", fw_name);
+			release_firmware(fw_entry);
+			return -1;
+		}
+		fw_len = fw_entry->size - 16;
+		bounce = kmemdup(fw_entry->data + 16, fw_len, GFP_KERNEL);
+		if (bounce == NULL) {
+			v4l2_err(go, "unable to allocate %d bytes for firmware transfer\n", fw_len);
+			release_firmware(fw_entry);
+			return -1;
+		}
 		release_firmware(fw_entry);
-		return -1;
+		go->boot_fw_len = fw_len;
+		go->boot_fw = bounce;
 	}
-	release_firmware(fw_entry);
 	if (go7007_interface_reset(go) < 0 ||
-			go7007_send_firmware(go, bounce, fw_len) < 0 ||
-			go7007_read_interrupt(go, &intr_val, &intr_data) < 0 ||
+	    go7007_send_firmware(go, go->boot_fw, go->boot_fw_len) < 0 ||
+	    go7007_read_interrupt(go, &intr_val, &intr_data) < 0 ||
 			(intr_val & ~0x1) != 0x5a5a) {
 		v4l2_err(go, "error transferring firmware\n");
 		rv = -1;
 	}
-	kfree(bounce);
 	return rv;
 }
 
-MODULE_FIRMWARE("go7007fw.bin");
+MODULE_FIRMWARE("go7007/go7007fw.bin");
 
 /*
  * Boot the encoder and register the I2C adapter if requested.  Do the
@@ -167,15 +166,24 @@ static int go7007_init_encoder(struct go7007 *go)
 		go7007_write_addr(go, 0x1000, 0x0811);
 		go7007_write_addr(go, 0x1000, 0x0c11);
 	}
-	if (go->board_id == GO7007_BOARDID_MATRIX_REV) {
+	switch (go->board_id) {
+	case GO7007_BOARDID_MATRIX_REV:
 		/* Set GPIO pin 0 to be an output (audio clock control) */
 		go7007_write_addr(go, 0x3c82, 0x0001);
 		go7007_write_addr(go, 0x3c80, 0x00fe);
-	}
-	if (go->board_id == GO7007_BOARDID_ADLINK_MPG24) {
+		break;
+	case GO7007_BOARDID_ADLINK_MPG24:
 		/* set GPIO5 to be an output, currently low */
 		go7007_write_addr(go, 0x3c82, 0x0000);
 		go7007_write_addr(go, 0x3c80, 0x00df);
+		break;
+	case GO7007_BOARDID_ADS_USBAV_709:
+		/* GPIO pin 0: audio clock control */
+		/*      pin 2: TW9906 reset */
+		/*      pin 3: capture LED */
+		go7007_write_addr(go, 0x3c82, 0x000d);
+		go7007_write_addr(go, 0x3c80, 0x00f2);
+		break;
 	}
 	return 0;
 }
@@ -196,18 +204,51 @@ int go7007_reset_encoder(struct go7007 *go)
 /*
  * Attempt to instantiate an I2C client by ID, probably loading a module.
  */
-static int init_i2c_module(struct i2c_adapter *adapter, const char *type,
-			   int addr)
+static int init_i2c_module(struct i2c_adapter *adapter, const struct go_i2c *const i2c)
 {
 	struct go7007 *go = i2c_get_adapdata(adapter);
 	struct v4l2_device *v4l2_dev = &go->v4l2_dev;
-
-	if (v4l2_i2c_new_subdev(v4l2_dev, adapter, type, addr, NULL))
+	struct v4l2_subdev *sd;
+	struct i2c_board_info info;
+
+	memset(&info, 0, sizeof(info));
+	strlcpy(info.type, i2c->type, sizeof(info.type));
+	info.addr = i2c->addr;
+	info.flags = i2c->flags;
+
+	sd = v4l2_i2c_new_subdev_board(v4l2_dev, adapter, &info, NULL);
+	if (sd) {
+		if (i2c->is_video)
+			go->sd_video = sd;
+		if (i2c->is_audio)
+			go->sd_audio = sd;
 		return 0;
+	}
 
-	dev_info(&adapter->dev,
-		 "go7007: probing for module i2c:%s failed\n", type);
-	return -1;
+	printk(KERN_INFO "go7007: probing for module i2c:%s failed\n", i2c->type);
+	return -EINVAL;
+}
+
+/*
+ * Detach and unregister the encoder.  The go7007 struct won't be freed
+ * until v4l2 finishes releasing its resources and all associated fds are
+ * closed by applications.
+ */
+static void go7007_remove(struct v4l2_device *v4l2_dev)
+{
+	struct go7007 *go = container_of(v4l2_dev, struct go7007, v4l2_dev);
+
+	v4l2_device_unregister(v4l2_dev);
+	if (go->hpi_ops->release)
+		go->hpi_ops->release(go);
+	if (go->i2c_adapter_online) {
+		i2c_del_adapter(&go->i2c_adapter);
+		go->i2c_adapter_online = 0;
+	}
+
+	kfree(go->boot_fw);
+	go7007_v4l2_remove(go);
+	kfree(go);
 }
 
 /*
@@ -218,38 +259,63 @@ static int init_i2c_module(struct i2c_adapter *adapter, const char *type,
  *
  * Must NOT be called with the hw_lock held.
  */
-int go7007_register_encoder(struct go7007 *go)
+int go7007_register_encoder(struct go7007 *go, unsigned num_i2c_devs)
 {
 	int i, ret;
 
 	dev_info(go->dev, "go7007: registering new %s\n", go->name);
 
+	go->v4l2_dev.release = go7007_remove;
+	ret = v4l2_device_register(go->dev, &go->v4l2_dev);
+	if (ret < 0)
+		return ret;
+
 	mutex_lock(&go->hw_lock);
 	ret = go7007_init_encoder(go);
 	mutex_unlock(&go->hw_lock);
 	if (ret < 0)
-		return -1;
+		return ret;
 
-	/* v4l2 init must happen before i2c subdevs */
-	ret = go7007_v4l2_init(go);
+	ret = go7007_v4l2_ctrl_init(go);
 	if (ret < 0)
 		return ret;
 
 	if (!go->i2c_adapter_online &&
 			go->board_info->flags & GO7007_BOARD_USE_ONBOARD_I2C) {
-		if (go7007_i2c_init(go) < 0)
-			return -1;
+		ret = go7007_i2c_init(go);
+		if (ret < 0)
+			return ret;
 		go->i2c_adapter_online = 1;
 	}
 	if (go->i2c_adapter_online) {
-		for (i = 0; i < go->board_info->num_i2c_devs; ++i)
-			init_i2c_module(&go->i2c_adapter,
-					go->board_info->i2c_devs[i].type,
-					go->board_info->i2c_devs[i].addr);
+		if (go->board_id == GO7007_BOARDID_ADS_USBAV_709) {
+			/* Reset the TW9906 */
+			go7007_write_addr(go, 0x3c82, 0x0009);
+			msleep(50);
+			go7007_write_addr(go, 0x3c82, 0x000d);
+		}
+		for (i = 0; i < num_i2c_devs; ++i)
+			init_i2c_module(&go->i2c_adapter, &go->board_info->i2c_devs[i]);
+
+		if (go->tuner_type >= 0) {
+			struct tuner_setup setup = {
+				.addr = ADDR_UNSET,
+				.type = go->tuner_type,
+				.mode_mask = T_ANALOG_TV,
+			};
+
+			v4l2_device_call_all(&go->v4l2_dev, 0, tuner,
+				s_type_addr, &setup);
+		}
 		if (go->board_id == GO7007_BOARDID_ADLINK_MPG24)
-			i2c_clients_command(&go->i2c_adapter,
-				DECODER_SET_CHANNEL, &go->channel_number);
+			v4l2_subdev_call(go->sd_video, video, s_routing,
+					0, 0, go->channel_number + 1);
 	}
+
+	ret = go7007_v4l2_init(go);
+	if (ret < 0)
+		return ret;
+
 	if (go->board_info->flags & GO7007_BOARD_HAS_AUDIO) {
 		go->audio_enabled = 1;
 		go7007_snd_init(go);
@@ -309,48 +375,54 @@ start_error:
 /*
  * Store a byte in the current video buffer, if there is one.
  */
-static inline void store_byte(struct go7007_buffer *gobuf, u8 byte)
+static inline void store_byte(struct go7007_buffer *vb, u8 byte)
 {
-	if (gobuf != NULL && gobuf->bytesused < GO7007_BUF_SIZE) {
-		unsigned int pgidx = gobuf->offset >> PAGE_SHIFT;
-		unsigned int pgoff = gobuf->offset & ~PAGE_MASK;
+	if (vb && vb->vb.v4l2_planes[0].bytesused < GO7007_BUF_SIZE) {
+		u8 *ptr = vb2_plane_vaddr(&vb->vb, 0);
 
-		*((u8 *)page_address(gobuf->pages[pgidx]) + pgoff) = byte;
-		++gobuf->offset;
-		++gobuf->bytesused;
+		ptr[vb->vb.v4l2_planes[0].bytesused++] = byte;
 	}
 }
 
 /*
  * Deliver the last video buffer and get a new one to start writing to.
  */
-static void frame_boundary(struct go7007 *go)
+static struct go7007_buffer *frame_boundary(struct go7007 *go, struct go7007_buffer *vb)
 {
-	struct go7007_buffer *gobuf;
+	struct go7007_buffer *vb_tmp = NULL;
+	u32 *bytesused = &vb->vb.v4l2_planes[0].bytesused;
 	int i;
 
-	if (go->active_buf) {
-		if (go->active_buf->modet_active) {
-			if (go->active_buf->bytesused + 216 < GO7007_BUF_SIZE) {
+	if (vb) {
+		if (vb->modet_active) {
+			if (*bytesused + 216 < GO7007_BUF_SIZE) {
 				for (i = 0; i < 216; ++i)
-					store_byte(go->active_buf,
-							go->active_map[i]);
-				go->active_buf->bytesused -= 216;
+					store_byte(vb, go->active_map[i]);
+				*bytesused -= 216;
 			} else
-				go->active_buf->modet_active = 0;
+				vb->modet_active = 0;
 		}
-		go->active_buf->state = BUF_STATE_DONE;
-		wake_up_interruptible(&go->frame_waitq);
-		go->active_buf = NULL;
+		vb->vb.v4l2_buf.sequence = go->next_seq++;
+		v4l2_get_timestamp(&vb->vb.v4l2_buf.timestamp);
+		vb_tmp = vb;
+		spin_lock(&go->spinlock);
+		list_del(&vb->list);
+		if (list_empty(&go->vidq_active))
+			vb = NULL;
+		else
+			vb = list_first_entry(&go->vidq_active, struct go7007_buffer, list);
+		go->active_buf = vb;
+		spin_unlock(&go->spinlock);
+		vb2_buffer_done(&vb_tmp->vb, VB2_BUF_STATE_DONE);
+		return vb;
 	}
-	list_for_each_entry(gobuf, &go->stream, stream)
-		if (gobuf->state == BUF_STATE_QUEUED) {
-			gobuf->seq = go->next_seq;
-			do_gettimeofday(&gobuf->timestamp);
-			go->active_buf = gobuf;
-			break;
-		}
-	++go->next_seq;
+	spin_lock(&go->spinlock);
+	if (!list_empty(&go->vidq_active))
+		vb = go->active_buf =
+			list_first_entry(&go->vidq_active, struct go7007_buffer, list);
+	spin_unlock(&go->spinlock);
+	go->next_seq++;
+	return vb;
 }
 
 static void write_bitmap_word(struct go7007 *go)
@@ -374,30 +446,30 @@ static void write_bitmap_word(struct go7007 *go)
  */
 void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length)
 {
-	int i, seq_start_code = -1, frame_start_code = -1;
-
-	spin_lock(&go->spinlock);
+	struct go7007_buffer *vb = go->active_buf;
+	int i, seq_start_code = -1, gop_start_code = -1, frame_start_code = -1;
 
 	switch (go->format) {
-	case GO7007_FORMAT_MPEG4:
+	case V4L2_PIX_FMT_MPEG4:
 		seq_start_code = 0xB0;
+		gop_start_code = 0xB3;
 		frame_start_code = 0xB6;
 		break;
-	case GO7007_FORMAT_MPEG1:
-	case GO7007_FORMAT_MPEG2:
+	case V4L2_PIX_FMT_MPEG1:
+	case V4L2_PIX_FMT_MPEG2:
 		seq_start_code = 0xB3;
+		gop_start_code = 0xB8;
 		frame_start_code = 0x00;
 		break;
 	}
 
 	for (i = 0; i < length; ++i) {
-		if (go->active_buf != NULL &&
-			    go->active_buf->bytesused >= GO7007_BUF_SIZE - 3) {
+		if (vb && vb->vb.v4l2_planes[0].bytesused >= GO7007_BUF_SIZE - 3) {
 			v4l2_info(&go->v4l2_dev, "dropping oversized frame\n");
-			go->active_buf->offset -= go->active_buf->bytesused;
-			go->active_buf->bytesused = 0;
-			go->active_buf->modet_active = 0;
-			go->active_buf = NULL;
+			vb->vb.v4l2_planes[0].bytesused = 0;
+			vb->frame_offset = 0;
+			vb->modet_active = 0;
+			vb = go->active_buf = NULL;
 		}
 
 		switch (go->state) {
@@ -410,7 +482,7 @@ void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length)
 				go->state = STATE_FF;
 				break;
 			default:
-				store_byte(go->active_buf, buf[i]);
+				store_byte(vb, buf[i]);
 				break;
 			}
 			break;
@@ -420,12 +492,12 @@ void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length)
 				go->state = STATE_00_00;
 				break;
 			case 0xFF:
-				store_byte(go->active_buf, 0x00);
+				store_byte(vb, 0x00);
 				go->state = STATE_FF;
 				break;
 			default:
-				store_byte(go->active_buf, 0x00);
-				store_byte(go->active_buf, buf[i]);
+				store_byte(vb, 0x00);
+				store_byte(vb, buf[i]);
 				go->state = STATE_DATA;
 				break;
 			}
@@ -433,21 +505,21 @@ void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length)
 		case STATE_00_00:
 			switch (buf[i]) {
 			case 0x00:
-				store_byte(go->active_buf, 0x00);
+				store_byte(vb, 0x00);
 				/* go->state remains STATE_00_00 */
 				break;
 			case 0x01:
 				go->state = STATE_00_00_01;
 				break;
 			case 0xFF:
-				store_byte(go->active_buf, 0x00);
-				store_byte(go->active_buf, 0x00);
+				store_byte(vb, 0x00);
+				store_byte(vb, 0x00);
 				go->state = STATE_FF;
 				break;
 			default:
-				store_byte(go->active_buf, 0x00);
-				store_byte(go->active_buf, 0x00);
-				store_byte(go->active_buf, buf[i]);
+				store_byte(vb, 0x00);
+				store_byte(vb, 0x00);
+				store_byte(vb, buf[i]);
 				go->state = STATE_DATA;
 				break;
 			}
@@ -455,31 +527,26 @@ void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length)
 		case STATE_00_00_01:
 			if (buf[i] == 0xF8 && go->modet_enable == 0) {
 				/* MODET start code, but MODET not enabled */
-				store_byte(go->active_buf, 0x00);
-				store_byte(go->active_buf, 0x00);
-				store_byte(go->active_buf, 0x01);
-				store_byte(go->active_buf, 0xF8);
+				store_byte(vb, 0x00);
+				store_byte(vb, 0x00);
+				store_byte(vb, 0x01);
+				store_byte(vb, 0xF8);
 				go->state = STATE_DATA;
 				break;
 			}
 			/* If this is the start of a new MPEG frame,
 			 * get a new buffer */
-			if ((go->format == GO7007_FORMAT_MPEG1 ||
-					go->format == GO7007_FORMAT_MPEG2 ||
-					go->format == GO7007_FORMAT_MPEG4) &&
-					(buf[i] == seq_start_code ||
-						buf[i] == 0xB8 || /* GOP code */
-						buf[i] == frame_start_code)) {
-				if (go->active_buf == NULL || go->seen_frame)
-					frame_boundary(go);
-				if (buf[i] == frame_start_code) {
-					if (go->active_buf != NULL)
-						go->active_buf->frame_offset =
-							go->active_buf->offset;
-					go->seen_frame = 1;
-				} else {
-					go->seen_frame = 0;
-				}
+			if ((go->format == V4L2_PIX_FMT_MPEG1 ||
+			     go->format == V4L2_PIX_FMT_MPEG2 ||
+			     go->format == V4L2_PIX_FMT_MPEG4) &&
+			    (buf[i] == seq_start_code ||
+			     buf[i] == gop_start_code ||
+			     buf[i] == frame_start_code)) {
+				if (vb == NULL || go->seen_frame)
+					vb = frame_boundary(go, vb);
+				go->seen_frame = buf[i] == frame_start_code;
+				if (vb && go->seen_frame)
+					vb->frame_offset = vb->vb.v4l2_planes[0].bytesused;
 			}
 			/* Handle any special chunk types, or just write the
 			 * start code to the (potentially new) buffer */
@@ -498,16 +565,16 @@ void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length)
 				go->state = STATE_MODET_MAP;
 				break;
 			case 0xFF: /* Potential JPEG start code */
-				store_byte(go->active_buf, 0x00);
-				store_byte(go->active_buf, 0x00);
-				store_byte(go->active_buf, 0x01);
+				store_byte(vb, 0x00);
+				store_byte(vb, 0x00);
+				store_byte(vb, 0x01);
 				go->state = STATE_FF;
 				break;
 			default:
-				store_byte(go->active_buf, 0x00);
-				store_byte(go->active_buf, 0x00);
-				store_byte(go->active_buf, 0x01);
-				store_byte(go->active_buf, buf[i]);
+				store_byte(vb, 0x00);
+				store_byte(vb, 0x00);
+				store_byte(vb, 0x01);
+				store_byte(vb, buf[i]);
 				go->state = STATE_DATA;
 				break;
 			}
@@ -515,20 +582,20 @@ void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length)
 		case STATE_FF:
 			switch (buf[i]) {
 			case 0x00:
-				store_byte(go->active_buf, 0xFF);
+				store_byte(vb, 0xFF);
 				go->state = STATE_00;
 				break;
 			case 0xFF:
-				store_byte(go->active_buf, 0xFF);
+				store_byte(vb, 0xFF);
 				/* go->state remains STATE_FF */
 				break;
 			case 0xD8:
-				if (go->format == GO7007_FORMAT_MJPEG)
-					frame_boundary(go);
+				if (go->format == V4L2_PIX_FMT_MJPEG)
+					vb = frame_boundary(go, vb);
 				/* fall through */
 			default:
-				store_byte(go->active_buf, 0xFF);
-				store_byte(go->active_buf, buf[i]);
+				store_byte(vb, 0xFF);
+				store_byte(vb, buf[i]);
 				go->state = STATE_DATA;
 				break;
 			}
@@ -551,8 +618,8 @@ void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length)
 					write_bitmap_word(go);
 				} else
 					go->modet_word = buf[i] << 8;
-			} else if (go->parse_length == 207 && go->active_buf) {
-				go->active_buf->modet_active = buf[i];
+			} else if (go->parse_length == 207 && vb) {
+				vb->modet_active = buf[i];
 			}
 			if (++go->parse_length == 208)
 				go->state = STATE_DATA;
@@ -563,15 +630,14 @@ void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length)
 			break;
 		}
 	}
-
-	spin_unlock(&go->spinlock);
 }
 EXPORT_SYMBOL(go7007_parse_video_stream);
 
 /*
  * Allocate a new go7007 struct.  Used by the hardware-specific probe.
  */
-struct go7007 *go7007_alloc(struct go7007_board_info *board, struct device *dev)
+struct go7007 *go7007_alloc(const struct go7007_board_info *board,
+						struct device *dev)
 {
 	struct go7007 *go;
 	int i;
@@ -588,33 +654,17 @@ struct go7007 *go7007_alloc(struct go7007_board_info *board, struct device *dev)
 	mutex_init(&go->hw_lock);
 	init_waitqueue_head(&go->frame_waitq);
 	spin_lock_init(&go->spinlock);
-	go->video_dev = NULL;
-	go->ref_count = 0;
 	go->status = STATUS_INIT;
 	memset(&go->i2c_adapter, 0, sizeof(go->i2c_adapter));
 	go->i2c_adapter_online = 0;
 	go->interrupt_available = 0;
 	init_waitqueue_head(&go->interrupt_waitq);
-	go->in_use = 0;
 	go->input = 0;
-	if (board->sensor_flags & GO7007_SENSOR_TV) {
-		go->standard = GO7007_STD_NTSC;
-		go->width = 720;
-		go->height = 480;
-		go->sensor_framerate = 30000;
-	} else {
-		go->standard = GO7007_STD_OTHER;
-		go->width = board->sensor_width;
-		go->height = board->sensor_height;
-		go->sensor_framerate = board->sensor_framerate;
-	}
-	go->encoder_v_offset = board->sensor_v_offset;
-	go->encoder_h_offset = board->sensor_h_offset;
+	go7007_update_board(go);
 	go->encoder_h_halve = 0;
 	go->encoder_v_halve = 0;
 	go->encoder_subsample = 0;
-	go->streaming = 0;
-	go->format = GO7007_FORMAT_MJPEG;
+	go->format = V4L2_PIX_FMT_MJPEG;
 	go->bitrate = 1500000;
 	go->fps_scale = 1;
 	go->pali = 0;
@@ -633,31 +683,30 @@ struct go7007 *go7007_alloc(struct go7007_board_info *board, struct device *dev)
 		go->modet_map[i] = 0;
 	go->audio_deliver = NULL;
 	go->audio_enabled = 0;
-	INIT_LIST_HEAD(&go->stream);
 
 	return go;
 }
 EXPORT_SYMBOL(go7007_alloc);
 
-/*
- * Detach and unregister the encoder.  The go7007 struct won't be freed
- * until v4l2 finishes releasing its resources and all associated fds are
- * closed by applications.
- */
-void go7007_remove(struct go7007 *go)
+void go7007_update_board(struct go7007 *go)
 {
-	if (go->i2c_adapter_online) {
-		if (i2c_del_adapter(&go->i2c_adapter) == 0)
-			go->i2c_adapter_online = 0;
-		else
-			v4l2_err(&go->v4l2_dev,
-				"error removing I2C adapter!\n");
-	}
+	const struct go7007_board_info *board = go->board_info;
 
-	if (go->audio_enabled)
-		go7007_snd_remove(go);
-	go7007_v4l2_remove(go);
+	if (board->sensor_flags & GO7007_SENSOR_TV) {
+		go->standard = GO7007_STD_NTSC;
+		go->std = V4L2_STD_NTSC_M;
+		go->width = 720;
+		go->height = 480;
+		go->sensor_framerate = 30000;
+	} else {
+		go->standard = GO7007_STD_OTHER;
+		go->width = board->sensor_width;
+		go->height = board->sensor_height;
+		go->sensor_framerate = board->sensor_framerate;
+	}
+	go->encoder_v_offset = board->sensor_v_offset;
+	go->encoder_h_offset = board->sensor_h_offset;
 }
-EXPORT_SYMBOL(go7007_remove);
+EXPORT_SYMBOL(go7007_update_board);
 
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/media/go7007/go7007-fw.c b/drivers/staging/media/go7007/go7007-fw.c
index a5ede1c..c2d0e58af 100644
--- a/drivers/staging/media/go7007/go7007-fw.c
+++ b/drivers/staging/media/go7007/go7007-fw.c
@@ -36,6 +36,8 @@
 
 #include "go7007-priv.h"
 
+#define GO7007_FW_NAME "go7007/go7007tv.bin"
+
 /* Constants used in the source firmware image to describe code segments */
 
 #define	FLAG_MODE_MJPEG		(1)
@@ -455,9 +457,9 @@ static int mpeg1_frame_header(struct go7007 *go, unsigned char *buf,
 
 	CODE_ADD(c, frame == PFRAME ? 0x2 : 0x3, 13);
 	CODE_ADD(c, 0xffff, 16);
-	CODE_ADD(c, go->format == GO7007_FORMAT_MPEG2 ? 0x7 : 0x4, 4);
+	CODE_ADD(c, go->format == V4L2_PIX_FMT_MPEG2 ? 0x7 : 0x4, 4);
 	if (frame != PFRAME)
-		CODE_ADD(c, go->format == GO7007_FORMAT_MPEG2 ? 0x7 : 0x4, 4);
+		CODE_ADD(c, go->format == V4L2_PIX_FMT_MPEG2 ? 0x7 : 0x4, 4);
 	else
 		CODE_ADD(c, 0, 4); /* Is this supposed to be here?? */
 	CODE_ADD(c, 0, 3); /* What is this?? */
@@ -466,7 +468,7 @@ static int mpeg1_frame_header(struct go7007 *go, unsigned char *buf,
 	if (j != 8)
 		CODE_ADD(c, 0, j);
 
-	if (go->format == GO7007_FORMAT_MPEG2) {
+	if (go->format == V4L2_PIX_FMT_MPEG2) {
 		CODE_ADD(c, 0x1, 24);
 		CODE_ADD(c, 0xb5, 8);
 		CODE_ADD(c, 0x844, 12);
@@ -537,7 +539,7 @@ static int mpeg1_sequence_header(struct go7007 *go, unsigned char *buf, int ext)
 	int i, aspect_ratio, picture_rate;
 	CODE_GEN(c, buf + 6);
 
-	if (go->format == GO7007_FORMAT_MPEG1) {
+	if (go->format == V4L2_PIX_FMT_MPEG1) {
 		switch (go->aspect_ratio) {
 		case GO7007_RATIO_4_3:
 			aspect_ratio = go->standard == GO7007_STD_NTSC ? 3 : 2;
@@ -587,9 +589,9 @@ static int mpeg1_sequence_header(struct go7007 *go, unsigned char *buf, int ext)
 	CODE_ADD(c, go->height, 12);
 	CODE_ADD(c, aspect_ratio, 4);
 	CODE_ADD(c, picture_rate, 4);
-	CODE_ADD(c, go->format == GO7007_FORMAT_MPEG2 ? 20000 : 0x3ffff, 18);
+	CODE_ADD(c, go->format == V4L2_PIX_FMT_MPEG2 ? 20000 : 0x3ffff, 18);
 	CODE_ADD(c, 1, 1);
-	CODE_ADD(c, go->format == GO7007_FORMAT_MPEG2 ? 112 : 20, 10);
+	CODE_ADD(c, go->format == V4L2_PIX_FMT_MPEG2 ? 112 : 20, 10);
 	CODE_ADD(c, 0, 3);
 
 	/* Byte-align with zeros */
@@ -597,7 +599,7 @@ static int mpeg1_sequence_header(struct go7007 *go, unsigned char *buf, int ext)
 	if (i != 8)
 		CODE_ADD(c, 0, i);
 
-	if (go->format == GO7007_FORMAT_MPEG2) {
+	if (go->format == V4L2_PIX_FMT_MPEG2) {
 		CODE_ADD(c, 0x1, 24);
 		CODE_ADD(c, 0xb5, 8);
 		CODE_ADD(c, 0x148, 12);
@@ -930,10 +932,10 @@ static int brctrl_to_package(struct go7007 *go,
 					__le16 *code, int space, int *framelen)
 {
 	int converge_speed = 0;
-	int lambda = (go->format == GO7007_FORMAT_MJPEG || go->dvd_mode) ?
+	int lambda = (go->format == V4L2_PIX_FMT_MJPEG || go->dvd_mode) ?
 				100 : 0;
 	int peak_rate = 6 * go->bitrate / 5;
-	int vbv_buffer = go->format == GO7007_FORMAT_MJPEG ?
+	int vbv_buffer = go->format == V4L2_PIX_FMT_MJPEG ?
 				go->bitrate :
 				(go->dvd_mode ? 900000 : peak_rate);
 	int fps = go->sensor_framerate / go->fps_scale;
@@ -1096,10 +1098,10 @@ static int config_package(struct go7007 *go, __le16 *code, int space)
 		0xc003,		0x28b4,
 		0xc004,		0x3c5a,
 		0xdc05,		0x2a77,
-		0xc6c3,		go->format == GO7007_FORMAT_MPEG4 ? 0 :
-				(go->format == GO7007_FORMAT_H263 ? 0 : 1),
-		0xc680,		go->format == GO7007_FORMAT_MPEG4 ? 0xf1 :
-				(go->format == GO7007_FORMAT_H263 ? 0x61 :
+		0xc6c3,		go->format == V4L2_PIX_FMT_MPEG4 ? 0 :
+				(go->format == V4L2_PIX_FMT_H263 ? 0 : 1),
+		0xc680,		go->format == V4L2_PIX_FMT_MPEG4 ? 0xf1 :
+				(go->format == V4L2_PIX_FMT_H263 ? 0x61 :
 									0xd3),
 		0xc780,		0x0140,
 		0xe009,		0x0001,
@@ -1123,15 +1125,15 @@ static int config_package(struct go7007 *go, __le16 *code, int space)
 						(!go->interlace_coding) ?
 					0x0008 : 0x0009,
 		0xc404,		go->interlace_coding ? 0x44 :
-				(go->format == GO7007_FORMAT_MPEG4 ? 0x11 :
-				(go->format == GO7007_FORMAT_MPEG1 ? 0x02 :
-				(go->format == GO7007_FORMAT_MPEG2 ? 0x04 :
-				(go->format == GO7007_FORMAT_H263  ? 0x08 :
+				(go->format == V4L2_PIX_FMT_MPEG4 ? 0x11 :
+				(go->format == V4L2_PIX_FMT_MPEG1 ? 0x02 :
+				(go->format == V4L2_PIX_FMT_MPEG2 ? 0x04 :
+				(go->format == V4L2_PIX_FMT_H263  ? 0x08 :
 								     0x20)))),
-		0xbf0a,		(go->format == GO7007_FORMAT_MPEG4 ? 8 :
-				(go->format == GO7007_FORMAT_MPEG1 ? 1 :
-				(go->format == GO7007_FORMAT_MPEG2 ? 2 :
-				(go->format == GO7007_FORMAT_H263 ? 4 : 16)))) |
+		0xbf0a,		(go->format == V4L2_PIX_FMT_MPEG4 ? 8 :
+				(go->format == V4L2_PIX_FMT_MPEG1 ? 1 :
+				(go->format == V4L2_PIX_FMT_MPEG2 ? 2 :
+				(go->format == V4L2_PIX_FMT_H263 ? 4 : 16)))) |
 				((go->repeat_seqhead ? 1 : 0) << 6) |
 				((go->dvd_mode ? 1 : 0) << 9) |
 				((go->gop_header_enable ? 1 : 0) << 10),
@@ -1348,19 +1350,19 @@ static int final_package(struct go7007 *go, __le16 *code, int space)
 			0x41,
 		go->ipb ? 0xd4c : 0x36b,
 		(rows << 8) | (go->width >> 4),
-		go->format == GO7007_FORMAT_MPEG4 ? 0x0404 : 0,
+		go->format == V4L2_PIX_FMT_MPEG4 ? 0x0404 : 0,
 		(1 << 15) | ((go->interlace_coding ? 1 : 0) << 13) |
 			((go->closed_gop ? 1 : 0) << 12) |
-			((go->format == GO7007_FORMAT_MPEG4 ? 1 : 0) << 11) |
+			((go->format == V4L2_PIX_FMT_MPEG4 ? 1 : 0) << 11) |
 		/*	(1 << 9) |   */
 			((go->ipb ? 3 : 0) << 7) |
 			((go->modet_enable ? 1 : 0) << 2) |
 			((go->dvd_mode ? 1 : 0) << 1) | 1,
-		(go->format == GO7007_FORMAT_MPEG1 ? 0x89a0 :
-			(go->format == GO7007_FORMAT_MPEG2 ? 0x89a0 :
-			(go->format == GO7007_FORMAT_MJPEG ? 0x89a0 :
-			(go->format == GO7007_FORMAT_MPEG4 ? 0x8920 :
-			(go->format == GO7007_FORMAT_H263 ? 0x8920 : 0))))),
+		(go->format == V4L2_PIX_FMT_MPEG1 ? 0x89a0 :
+			(go->format == V4L2_PIX_FMT_MPEG2 ? 0x89a0 :
+			(go->format == V4L2_PIX_FMT_MJPEG ? 0x89a0 :
+			(go->format == V4L2_PIX_FMT_MPEG4 ? 0x8920 :
+			(go->format == V4L2_PIX_FMT_H263 ? 0x8920 : 0))))),
 		go->ipb ? 0x1f15 : 0x1f0b,
 		go->ipb ? 0x0015 : 0x000b,
 		go->ipb ? 0xa800 : 0x5800,
@@ -1503,13 +1505,13 @@ static int do_special(struct go7007 *go, u16 type, __le16 *code, int space,
 	switch (type) {
 	case SPECIAL_FRM_HEAD:
 		switch (go->format) {
-		case GO7007_FORMAT_MJPEG:
+		case V4L2_PIX_FMT_MJPEG:
 			return gen_mjpeghdr_to_package(go, code, space);
-		case GO7007_FORMAT_MPEG1:
-		case GO7007_FORMAT_MPEG2:
+		case V4L2_PIX_FMT_MPEG1:
+		case V4L2_PIX_FMT_MPEG2:
 			return gen_mpeg1hdr_to_package(go, code, space,
 								framelen);
-		case GO7007_FORMAT_MPEG4:
+		case V4L2_PIX_FMT_MPEG4:
 			return gen_mpeg4hdr_to_package(go, code, space,
 								framelen);
 		}
@@ -1519,11 +1521,11 @@ static int do_special(struct go7007 *go, u16 type, __le16 *code, int space,
 		return config_package(go, code, space);
 	case SPECIAL_SEQHEAD:
 		switch (go->format) {
-		case GO7007_FORMAT_MPEG1:
-		case GO7007_FORMAT_MPEG2:
+		case V4L2_PIX_FMT_MPEG1:
+		case V4L2_PIX_FMT_MPEG2:
 			return seqhead_to_package(go, code, space,
 					mpeg1_sequence_header);
-		case GO7007_FORMAT_MPEG4:
+		case V4L2_PIX_FMT_MPEG4:
 			return seqhead_to_package(go, code, space,
 					mpeg4_sequence_header);
 		default:
@@ -1553,25 +1555,25 @@ int go7007_construct_fw_image(struct go7007 *go, u8 **fw, int *fwlen)
 	int ret;
 
 	switch (go->format) {
-	case GO7007_FORMAT_MJPEG:
+	case V4L2_PIX_FMT_MJPEG:
 		mode_flag = FLAG_MODE_MJPEG;
 		break;
-	case GO7007_FORMAT_MPEG1:
+	case V4L2_PIX_FMT_MPEG1:
 		mode_flag = FLAG_MODE_MPEG1;
 		break;
-	case GO7007_FORMAT_MPEG2:
+	case V4L2_PIX_FMT_MPEG2:
 		mode_flag = FLAG_MODE_MPEG2;
 		break;
-	case GO7007_FORMAT_MPEG4:
+	case V4L2_PIX_FMT_MPEG4:
 		mode_flag = FLAG_MODE_MPEG4;
 		break;
 	default:
 		return -1;
 	}
-	if (request_firmware(&fw_entry, go->board_info->firmware, go->dev)) {
+	if (request_firmware(&fw_entry, GO7007_FW_NAME, go->dev)) {
 		dev_err(go->dev,
 			"unable to load firmware from file \"%s\"\n",
-			go->board_info->firmware);
+			GO7007_FW_NAME);
 		return -1;
 	}
 	code = kzalloc(codespace * 2, GFP_KERNEL);
@@ -1586,7 +1588,7 @@ int go7007_construct_fw_image(struct go7007 *go, u8 **fw, int *fwlen)
 		if (chunk_len + 2 > srclen) {
 			dev_err(go->dev,
 				"firmware file \"%s\" appears to be corrupted\n",
-				go->board_info->firmware);
+				GO7007_FW_NAME);
 			goto fw_failed;
 		}
 		if (chunk_flags & mode_flag) {
@@ -1622,3 +1624,5 @@ fw_failed:
 	release_firmware(fw_entry);
 	return -1;
 }
+
+MODULE_FIRMWARE(GO7007_FW_NAME);
diff --git a/drivers/staging/media/go7007/go7007-i2c.c b/drivers/staging/media/go7007/go7007-i2c.c
index 39456a3..74f25e0 100644
--- a/drivers/staging/media/go7007/go7007-i2c.c
+++ b/drivers/staging/media/go7007/go7007-i2c.c
@@ -28,7 +28,6 @@
 #include <linux/uaccess.h>
 
 #include "go7007-priv.h"
-#include "wis-i2c.h"
 
 /********************* Driver for on-board I2C adapter *********************/
 
@@ -52,11 +51,11 @@ static DEFINE_MUTEX(adlink_mpg24_i2c_lock);
 static int go7007_i2c_xfer(struct go7007 *go, u16 addr, int read,
 		u16 command, int flags, u8 *data)
 {
-	int i, ret = -1;
+	int i, ret = -EIO;
 	u16 val;
 
 	if (go->status == STATUS_SHUTDOWN)
-		return -1;
+		return -ENODEV;
 
 #ifdef GO7007_I2C_DEBUG
 	if (read)
@@ -146,7 +145,7 @@ static int go7007_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
 	struct go7007 *go = i2c_get_adapdata(adapter);
 
 	if (size != I2C_SMBUS_BYTE_DATA)
-		return -1;
+		return -EIO;
 	return go7007_i2c_xfer(go, addr, read_write == I2C_SMBUS_READ, command,
 			flags & I2C_CLIENT_SCCB ? 0x10 : 0x00, &data->byte);
 }
@@ -170,26 +169,26 @@ static int go7007_i2c_master_xfer(struct i2c_adapter *adapter,
 					(msgs[i].flags & I2C_M_RD) ||
 					!(msgs[i + 1].flags & I2C_M_RD) ||
 					msgs[i + 1].len != 1)
-				return -1;
+				return -EIO;
 			if (go7007_i2c_xfer(go, msgs[i].addr, 1,
 					(msgs[i].buf[0] << 8) | msgs[i].buf[1],
 					0x01, &msgs[i + 1].buf[0]) < 0)
-				return -1;
+				return -EIO;
 			++i;
 		} else if (msgs[i].len == 3) {
 			if (msgs[i].flags & I2C_M_RD)
-				return -1;
+				return -EIO;
 			if (msgs[i].len != 3)
-				return -1;
+				return -EIO;
 			if (go7007_i2c_xfer(go, msgs[i].addr, 0,
 					(msgs[i].buf[0] << 8) | msgs[i].buf[1],
 					0x01, &msgs[i].buf[2]) < 0)
-				return -1;
+				return -EIO;
 		} else
-			return -1;
+			return -EIO;
 	}
 
-	return 0;
+	return num;
 }
 
 static u32 go7007_functionality(struct i2c_adapter *adapter)
diff --git a/drivers/staging/media/go7007/go7007-loader.c b/drivers/staging/media/go7007/go7007-loader.c
new file mode 100644
index 0000000..4ce53d6
--- /dev/null
+++ b/drivers/staging/media/go7007/go7007-loader.c
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2008 Sensoray Company 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., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+#include <linux/firmware.h>
+#include <cypress_firmware.h>
+
+struct fw_config {
+	u16 vendor;
+	u16 product;
+	const char * const fw_name1;
+	const char * const fw_name2;
+};
+
+struct fw_config fw_configs[] = {
+	{ 0x1943, 0xa250, "go7007/s2250-1.fw", "go7007/s2250-2.fw" },
+	{ 0x093b, 0xa002, "go7007/px-m402u.fw", NULL },
+	{ 0x093b, 0xa004, "go7007/px-tv402u.fw", NULL },
+	{ 0x0eb1, 0x6666, "go7007/lr192.fw", NULL },
+	{ 0x0eb1, 0x6668, "go7007/wis-startrek.fw", NULL },
+	{ 0, 0, NULL, NULL }
+};
+MODULE_FIRMWARE("go7007/s2250-1.fw");
+MODULE_FIRMWARE("go7007/s2250-2.fw");
+MODULE_FIRMWARE("go7007/px-m402u.fw");
+MODULE_FIRMWARE("go7007/px-tv402u.fw");
+MODULE_FIRMWARE("go7007/lr192.fw");
+MODULE_FIRMWARE("go7007/wis-startrek.fw");
+
+static int go7007_loader_probe(struct usb_interface *interface,
+				const struct usb_device_id *id)
+{
+	struct usb_device *usbdev;
+	const struct firmware *fw;
+	u16 vendor, product;
+	const char *fw1, *fw2;
+	int ret;
+	int i;
+
+	usbdev = usb_get_dev(interface_to_usbdev(interface));
+	if (!usbdev)
+		goto failed2;
+
+	if (usbdev->descriptor.bNumConfigurations != 1) {
+		dev_err(&interface->dev, "can't handle multiple config\n");
+		return -ENODEV;
+	}
+
+	vendor = le16_to_cpu(usbdev->descriptor.idVendor);
+	product = le16_to_cpu(usbdev->descriptor.idProduct);
+
+	for (i = 0; fw_configs[i].fw_name1; i++)
+		if (fw_configs[i].vendor == vendor &&
+		    fw_configs[i].product == product)
+			break;
+
+	/* Should never happen */
+	if (fw_configs[i].fw_name1 == NULL)
+		goto failed2;
+
+	fw1 = fw_configs[i].fw_name1;
+	fw2 = fw_configs[i].fw_name2;
+
+	dev_info(&interface->dev, "loading firmware %s\n", fw1);
+
+	if (request_firmware(&fw, fw1, &usbdev->dev)) {
+		dev_err(&interface->dev,
+			"unable to load firmware from file \"%s\"\n", fw1);
+		goto failed2;
+	}
+	ret = usbv2_cypress_load_firmware(usbdev, fw, CYPRESS_FX2);
+	release_firmware(fw);
+	if (0 != ret) {
+		dev_err(&interface->dev, "loader download failed\n");
+		goto failed2;
+	}
+
+	if (fw2 == NULL)
+		return 0;
+
+	if (request_firmware(&fw, fw2, &usbdev->dev)) {
+		dev_err(&interface->dev,
+			"unable to load firmware from file \"%s\"\n", fw2);
+		goto failed2;
+	}
+	ret = usbv2_cypress_load_firmware(usbdev, fw, CYPRESS_FX2);
+	release_firmware(fw);
+	if (0 != ret) {
+		dev_err(&interface->dev, "firmware download failed\n");
+		goto failed2;
+	}
+	return 0;
+
+failed2:
+	dev_err(&interface->dev, "probe failed\n");
+	return -ENODEV;
+}
+
+static void go7007_loader_disconnect(struct usb_interface *interface)
+{
+	dev_info(&interface->dev, "disconnect\n");
+	usb_set_intfdata(interface, NULL);
+}
+
+static const struct usb_device_id go7007_loader_ids[] = {
+	{ USB_DEVICE(0x1943, 0xa250) },
+	{ USB_DEVICE(0x093b, 0xa002) },
+	{ USB_DEVICE(0x093b, 0xa004) },
+	{ USB_DEVICE(0x0eb1, 0x6666) },
+	{ USB_DEVICE(0x0eb1, 0x6668) },
+	{}                          /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, go7007_loader_ids);
+
+static struct usb_driver go7007_loader_driver = {
+	.name		= "go7007-loader",
+	.probe		= go7007_loader_probe,
+	.disconnect	= go7007_loader_disconnect,
+	.id_table	= go7007_loader_ids,
+};
+
+module_usb_driver(go7007_loader_driver);
+
+MODULE_AUTHOR("");
+MODULE_DESCRIPTION("firmware loader for go7007-usb");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/media/go7007/go7007-priv.h b/drivers/staging/media/go7007/go7007-priv.h
index b58c394..8bde187 100644
--- a/drivers/staging/media/go7007/go7007-priv.h
+++ b/drivers/staging/media/go7007/go7007-priv.h
@@ -22,6 +22,9 @@
  */
 
 #include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-fh.h>
+#include <media/videobuf2-core.h>
 
 struct go7007;
 
@@ -34,15 +37,13 @@ struct go7007;
 #define GO7007_BOARDID_XMEN_II		5
 #define GO7007_BOARDID_XMEN_III		6
 #define GO7007_BOARDID_MATRIX_REV	7
-#define GO7007_BOARDID_PX_M402U		16
-#define GO7007_BOARDID_PX_TV402U_ANY	17 /* need to check tuner model */
-#define GO7007_BOARDID_PX_TV402U_NA	18 /* detected NTSC tuner */
-#define GO7007_BOARDID_PX_TV402U_EU	19 /* detected PAL tuner */
-#define GO7007_BOARDID_PX_TV402U_JP	20 /* detected NTSC-J tuner */
-#define GO7007_BOARDID_LIFEVIEW_LR192	21 /* TV Walker Ultra */
-#define GO7007_BOARDID_ENDURA		22
-#define GO7007_BOARDID_ADLINK_MPG24	23
-#define GO7007_BOARDID_SENSORAY_2250	24 /* Sensoray 2250/2251 */
+#define GO7007_BOARDID_PX_M402U		8
+#define GO7007_BOARDID_PX_TV402U	9
+#define GO7007_BOARDID_LIFEVIEW_LR192	10 /* TV Walker Ultra */
+#define GO7007_BOARDID_ENDURA		11
+#define GO7007_BOARDID_ADLINK_MPG24	12
+#define GO7007_BOARDID_SENSORAY_2250	13 /* Sensoray 2250/2251 */
+#define GO7007_BOARDID_ADS_USBAV_709    14
 
 /* Various characteristics of each board */
 #define GO7007_BOARD_HAS_AUDIO		(1<<0)
@@ -61,6 +62,7 @@ struct go7007;
 #define GO7007_SENSOR_TV		(1<<7)
 #define GO7007_SENSOR_VBI		(1<<8)
 #define GO7007_SENSOR_SCALING		(1<<9)
+#define GO7007_SENSOR_SAA7115		(1<<10)
 
 /* Characteristics of audio sensor devices */
 #define GO7007_AUDIO_I2S_MODE_1		(1)
@@ -74,7 +76,6 @@ struct go7007;
 #define GO7007_AUDIO_OKI_MODE		(1<<17)
 
 struct go7007_board_info {
-	char *firmware;
 	unsigned int flags;
 	int hpi_buffer_cap;
 	unsigned int sensor_flags;
@@ -88,17 +89,25 @@ struct go7007_board_info {
 	int audio_bclk_div;
 	int audio_main_div;
 	int num_i2c_devs;
-	struct {
+	struct go_i2c {
 		const char *type;
-		int id;
+		int is_video:1;
+		int is_audio:1;
 		int addr;
-	} i2c_devs[4];
+		u32 flags;
+	} i2c_devs[5];
 	int num_inputs;
 	struct {
 		int video_input;
-		int audio_input;
+		int audio_index;
 		char *name;
 	} inputs[4];
+	int video_config;
+	int num_aud_inputs;
+	struct {
+		int audio_input;
+		char *name;
+	} aud_inputs[3];
 };
 
 struct go7007_hpi_ops {
@@ -109,6 +118,7 @@ struct go7007_hpi_ops {
 	int (*stream_stop)(struct go7007 *go);
 	int (*send_firmware)(struct go7007 *go, u8 *data, int len);
 	int (*send_command)(struct go7007 *go, unsigned int cmd, void *arg);
+	void (*release)(struct go7007 *go);
 };
 
 /* The video buffer size must be a multiple of PAGE_SIZE */
@@ -116,35 +126,12 @@ struct go7007_hpi_ops {
 #define	GO7007_BUF_SIZE		(GO7007_BUF_PAGES << PAGE_SHIFT)
 
 struct go7007_buffer {
-	struct go7007 *go; /* Reverse reference for VMA ops */
-	int index; /* Reverse reference for DQBUF */
-	enum { BUF_STATE_IDLE, BUF_STATE_QUEUED, BUF_STATE_DONE } state;
-	u32 seq;
-	struct timeval timestamp;
-	struct list_head stream;
-	struct page *pages[GO7007_BUF_PAGES + 1]; /* extra for straddling */
-	unsigned long user_addr;
-	unsigned int page_count;
-	unsigned int offset;
-	unsigned int bytesused;
+	struct vb2_buffer vb;
+	struct list_head list;
 	unsigned int frame_offset;
 	u32 modet_active;
-	int mapped;
 };
 
-struct go7007_file {
-	struct go7007 *go;
-	struct mutex lock;
-	int buf_count;
-	struct go7007_buffer *bufs;
-};
-
-#define	GO7007_FORMAT_MJPEG	0
-#define GO7007_FORMAT_MPEG4	1
-#define GO7007_FORMAT_MPEG1	2
-#define GO7007_FORMAT_MPEG2	3
-#define GO7007_FORMAT_H263	4
-
 #define GO7007_RATIO_1_1	0
 #define GO7007_RATIO_4_3	1
 #define GO7007_RATIO_16_9	2
@@ -163,24 +150,38 @@ enum go7007_parser_state {
 
 struct go7007 {
 	struct device *dev;
-	struct go7007_board_info *board_info;
+	u8 bus_info[32];
+	const struct go7007_board_info *board_info;
 	unsigned int board_id;
 	int tuner_type;
 	int channel_number; /* for multi-channel boards like Adlink PCI-MPG24 */
 	char name[64];
-	struct video_device *video_dev;
+	struct video_device vdev;
+	void *boot_fw;
+	unsigned boot_fw_len;
 	struct v4l2_device v4l2_dev;
-	int ref_count;
+	struct v4l2_ctrl_handler hdl;
+	struct v4l2_ctrl *mpeg_video_encoding;
+	struct v4l2_ctrl *mpeg_video_gop_size;
+	struct v4l2_ctrl *mpeg_video_gop_closure;
+	struct v4l2_ctrl *mpeg_video_bitrate;
+	struct v4l2_ctrl *mpeg_video_aspect_ratio;
+	struct v4l2_ctrl *mpeg_video_b_frames;
+	struct v4l2_ctrl *mpeg_video_rep_seqheader;
 	enum { STATUS_INIT, STATUS_ONLINE, STATUS_SHUTDOWN } status;
 	spinlock_t spinlock;
 	struct mutex hw_lock;
-	int streaming;
-	int in_use;
+	struct mutex serialize_lock;
 	int audio_enabled;
+	struct v4l2_subdev *sd_video;
+	struct v4l2_subdev *sd_audio;
+	u8 usb_buf[16];
 
 	/* Video input */
 	int input;
+	int aud_input;
 	enum { GO7007_STD_NTSC, GO7007_STD_PAL, GO7007_STD_OTHER } standard;
+	v4l2_std_id std;
 	int sensor_framerate;
 	int width;
 	int height;
@@ -191,7 +192,7 @@ struct go7007 {
 	unsigned int encoder_subsample:1;
 
 	/* Encoder config */
-	int format;
+	u32 format;
 	int bitrate;
 	int fps_scale;
 	int pali;
@@ -217,14 +218,16 @@ struct go7007 {
 	unsigned char active_map[216];
 
 	/* Video streaming */
-	struct go7007_buffer *active_buf;
+	struct mutex queue_lock;
+	struct vb2_queue vidq;
 	enum go7007_parser_state state;
 	int parse_length;
 	u16 modet_word;
 	int seen_frame;
 	u32 next_seq;
-	struct list_head stream;
+	struct list_head vidq_active;
 	wait_queue_head_t frame_waitq;
+	struct go7007_buffer *active_buf;
 
 	/* Audio streaming */
 	void (*audio_deliver)(struct go7007 *go, u8 *buf, int length);
@@ -267,12 +270,12 @@ int go7007_read_addr(struct go7007 *go, u16 addr, u16 *data);
 int go7007_read_interrupt(struct go7007 *go, u16 *value, u16 *data);
 int go7007_boot_encoder(struct go7007 *go, int init_i2c);
 int go7007_reset_encoder(struct go7007 *go);
-int go7007_register_encoder(struct go7007 *go);
+int go7007_register_encoder(struct go7007 *go, unsigned num_i2c_devs);
 int go7007_start_encoder(struct go7007 *go);
 void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length);
-struct go7007 *go7007_alloc(struct go7007_board_info *board,
+struct go7007 *go7007_alloc(const struct go7007_board_info *board,
 					struct device *dev);
-void go7007_remove(struct go7007 *go);
+void go7007_update_board(struct go7007 *go);
 
 /* go7007-fw.c */
 int go7007_construct_fw_image(struct go7007 *go, u8 **fw, int *fwlen);
@@ -283,6 +286,7 @@ int go7007_i2c_remove(struct go7007 *go);
 
 /* go7007-v4l2.c */
 int go7007_v4l2_init(struct go7007 *go);
+int go7007_v4l2_ctrl_init(struct go7007 *go);
 void go7007_v4l2_remove(struct go7007 *go);
 
 /* snd-go7007.c */
diff --git a/drivers/staging/media/go7007/go7007-usb.c b/drivers/staging/media/go7007/go7007-usb.c
index 9dbf5ec..50066e0 100644
--- a/drivers/staging/media/go7007/go7007-usb.c
+++ b/drivers/staging/media/go7007/go7007-usb.c
@@ -26,10 +26,11 @@
 #include <linux/usb.h>
 #include <linux/i2c.h>
 #include <asm/byteorder.h>
-#include <media/tvaudio.h>
+#include <media/saa7115.h>
+#include <media/tuner.h>
+#include <media/uda1342.h>
 
 #include "go7007-priv.h"
-#include "wis-i2c.h"
 
 static unsigned int assume_endura;
 module_param(assume_endura, int, 0644);
@@ -62,7 +63,7 @@ struct go7007_usb_board {
 };
 
 struct go7007_usb {
-	struct go7007_usb_board *board;
+	const struct go7007_usb_board *board;
 	struct mutex i2c_lock;
 	struct usb_device *usbdev;
 	struct urb *video_urbs[8];
@@ -72,10 +73,9 @@ struct go7007_usb {
 
 /*********************** Product specification data ***********************/
 
-static struct go7007_usb_board board_matrix_ii = {
+static const struct go7007_usb_board board_matrix_ii = {
 	.flags		= GO7007_USB_EZUSB,
 	.main_info	= {
-		.firmware	 = "go7007tv.bin",
 		.flags		 = GO7007_BOARD_HAS_AUDIO |
 					GO7007_BOARD_USE_ONBOARD_I2C,
 		.audio_flags	 = GO7007_AUDIO_I2S_MODE_1 |
@@ -87,14 +87,15 @@ static struct go7007_usb_board board_matrix_ii = {
 		.sensor_flags	 = GO7007_SENSOR_656 |
 					GO7007_SENSOR_VALID_ENABLE |
 					GO7007_SENSOR_TV |
+					GO7007_SENSOR_SAA7115 |
 					GO7007_SENSOR_VBI |
 					GO7007_SENSOR_SCALING,
 		.num_i2c_devs	 = 1,
 		.i2c_devs	 = {
 			{
-				.type	= "wis_saa7115",
-				.id	= I2C_DRIVERID_WIS_SAA7115,
+				.type	= "saa7115",
 				.addr	= 0x20,
+				.is_video = 1,
 			},
 		},
 		.num_inputs	 = 2,
@@ -108,13 +109,13 @@ static struct go7007_usb_board board_matrix_ii = {
 				.name		= "S-Video",
 			},
 		},
+		.video_config	= SAA7115_IDQ_IS_DEFAULT,
 	},
 };
 
-static struct go7007_usb_board board_matrix_reload = {
+static const struct go7007_usb_board board_matrix_reload = {
 	.flags		= GO7007_USB_EZUSB,
 	.main_info	= {
-		.firmware	 = "go7007tv.bin",
 		.flags		 = GO7007_BOARD_HAS_AUDIO |
 					GO7007_BOARD_USE_ONBOARD_I2C,
 		.audio_flags	 = GO7007_AUDIO_I2S_MODE_1 |
@@ -129,9 +130,9 @@ static struct go7007_usb_board board_matrix_reload = {
 		.num_i2c_devs	 = 1,
 		.i2c_devs	 = {
 			{
-				.type	= "wis_saa7113",
-				.id	= I2C_DRIVERID_WIS_SAA7113,
+				.type	= "saa7113",
 				.addr	= 0x25,
+				.is_video = 1,
 			},
 		},
 		.num_inputs	 = 2,
@@ -145,18 +146,19 @@ static struct go7007_usb_board board_matrix_reload = {
 				.name		= "S-Video",
 			},
 		},
+		.video_config	= SAA7115_IDQ_IS_DEFAULT,
 	},
 };
 
-static struct go7007_usb_board board_star_trek = {
+static const struct go7007_usb_board board_star_trek = {
 	.flags		= GO7007_USB_EZUSB | GO7007_USB_EZUSB_I2C,
 	.main_info	= {
-		.firmware	 = "go7007tv.bin",
 		.flags		 = GO7007_BOARD_HAS_AUDIO, /* |
 					GO7007_BOARD_HAS_TUNER, */
 		.sensor_flags	 = GO7007_SENSOR_656 |
 					GO7007_SENSOR_VALID_ENABLE |
 					GO7007_SENSOR_TV |
+					GO7007_SENSOR_SAA7115 |
 					GO7007_SENSOR_VBI |
 					GO7007_SENSOR_SCALING,
 		.audio_flags	 = GO7007_AUDIO_I2S_MODE_1 |
@@ -167,42 +169,43 @@ static struct go7007_usb_board board_star_trek = {
 		.num_i2c_devs	 = 1,
 		.i2c_devs	 = {
 			{
-				.type	= "wis_saa7115",
-				.id	= I2C_DRIVERID_WIS_SAA7115,
+				.type	= "saa7115",
 				.addr	= 0x20,
+				.is_video = 1,
 			},
 		},
 		.num_inputs	 = 2,
 		.inputs		 = {
+		/*	{
+		 *		.video_input	= 3,
+		 *		.audio_index	= AUDIO_TUNER,
+		 *		.name		= "Tuner",
+		 *	},
+		 */
 			{
 				.video_input	= 1,
-			/*	.audio_input	= AUDIO_EXTERN, */
+			/*	.audio_index	= AUDIO_EXTERN, */
 				.name		= "Composite",
 			},
 			{
 				.video_input	= 8,
-			/*	.audio_input	= AUDIO_EXTERN, */
+			/*	.audio_index	= AUDIO_EXTERN, */
 				.name		= "S-Video",
 			},
-		/*	{
-		 *		.video_input	= 3,
-		 *		.audio_input	= AUDIO_TUNER,
-		 *		.name		= "Tuner",
-		 *	},
-		 */
 		},
+		.video_config	= SAA7115_IDQ_IS_DEFAULT,
 	},
 };
 
-static struct go7007_usb_board board_px_tv402u = {
+static const struct go7007_usb_board board_px_tv402u = {
 	.flags		= GO7007_USB_EZUSB | GO7007_USB_EZUSB_I2C,
 	.main_info	= {
-		.firmware	 = "go7007tv.bin",
 		.flags		 = GO7007_BOARD_HAS_AUDIO |
 					GO7007_BOARD_HAS_TUNER,
 		.sensor_flags	 = GO7007_SENSOR_656 |
 					GO7007_SENSOR_VALID_ENABLE |
 					GO7007_SENSOR_TV |
+					GO7007_SENSOR_SAA7115 |
 					GO7007_SENSOR_VBI |
 					GO7007_SENSOR_SCALING,
 		.audio_flags	 = GO7007_AUDIO_I2S_MODE_1 |
@@ -210,49 +213,67 @@ static struct go7007_usb_board board_px_tv402u = {
 		.audio_bclk_div	 = 8,
 		.audio_main_div	 = 2,
 		.hpi_buffer_cap  = 7,
-		.num_i2c_devs	 = 3,
+		.num_i2c_devs	 = 5,
 		.i2c_devs	 = {
 			{
-				.type	= "wis_saa7115",
-				.id	= I2C_DRIVERID_WIS_SAA7115,
+				.type	= "saa7115",
 				.addr	= 0x20,
+				.is_video = 1,
 			},
 			{
-				.type	= "wis_uda1342",
-				.id	= I2C_DRIVERID_WIS_UDA1342,
+				.type	= "uda1342",
 				.addr	= 0x1a,
+				.is_audio = 1,
 			},
 			{
-				.type	= "wis_sony_tuner",
-				.id	= I2C_DRIVERID_WIS_SONY_TUNER,
+				.type	= "tuner",
 				.addr	= 0x60,
 			},
+			{
+				.type	= "tuner",
+				.addr	= 0x43,
+			},
+			{
+				.type	= "sony-btf-mpx",
+				.addr	= 0x44,
+			},
 		},
 		.num_inputs	 = 3,
 		.inputs		 = {
 			{
+				.video_input	= 3,
+				.audio_index	= 0,
+				.name		= "Tuner",
+			},
+			{
 				.video_input	= 1,
-				.audio_input	= TVAUDIO_INPUT_EXTERN,
+				.audio_index	= 1,
 				.name		= "Composite",
 			},
 			{
 				.video_input	= 8,
-				.audio_input	= TVAUDIO_INPUT_EXTERN,
+				.audio_index	= 1,
 				.name		= "S-Video",
 			},
+		},
+		.video_config	= SAA7115_IDQ_IS_DEFAULT,
+		.num_aud_inputs	 = 2,
+		.aud_inputs	 = {
 			{
-				.video_input	= 3,
-				.audio_input	= TVAUDIO_INPUT_TUNER,
+				.audio_input	= UDA1342_IN2,
 				.name		= "Tuner",
 			},
+			{
+				.audio_input	= UDA1342_IN1,
+				.name		= "Line In",
+			},
 		},
 	},
 };
 
-static struct go7007_usb_board board_xmen = {
+static const struct go7007_usb_board board_xmen = {
 	.flags		= 0,
 	.main_info	= {
-		.firmware	  = "go7007tv.bin",
 		.flags		  = GO7007_BOARD_USE_ONBOARD_I2C,
 		.hpi_buffer_cap   = 0,
 		.sensor_flags	  = GO7007_SENSOR_VREF_POLAR,
@@ -271,8 +292,7 @@ static struct go7007_usb_board board_xmen = {
 		.num_i2c_devs	  = 1,
 		.i2c_devs	  = {
 			{
-				.type	= "wis_ov7640",
-				.id	= I2C_DRIVERID_WIS_OV7640,
+				.type	= "ov7640",
 				.addr	= 0x21,
 			},
 		},
@@ -285,10 +305,9 @@ static struct go7007_usb_board board_xmen = {
 	},
 };
 
-static struct go7007_usb_board board_matrix_revolution = {
+static const struct go7007_usb_board board_matrix_revolution = {
 	.flags		= GO7007_USB_EZUSB,
 	.main_info	= {
-		.firmware	 = "go7007tv.bin",
 		.flags		 = GO7007_BOARD_HAS_AUDIO |
 					GO7007_BOARD_USE_ONBOARD_I2C,
 		.audio_flags	 = GO7007_AUDIO_I2S_MODE_1 |
@@ -304,8 +323,8 @@ static struct go7007_usb_board board_matrix_revolution = {
 		.num_i2c_devs	 = 1,
 		.i2c_devs	 = {
 			{
-				.type	= "wis_tw9903",
-				.id	= I2C_DRIVERID_WIS_TW9903,
+				.type	= "tw9903",
+				.is_video = 1,
 				.addr	= 0x44,
 			},
 		},
@@ -323,10 +342,9 @@ static struct go7007_usb_board board_matrix_revolution = {
 	},
 };
 
-static struct go7007_usb_board board_lifeview_lr192 = {
+static const struct go7007_usb_board board_lifeview_lr192 = {
 	.flags		= GO7007_USB_EZUSB,
 	.main_info	= {
-		.firmware	 = "go7007tv.bin",
 		.flags		 = GO7007_BOARD_HAS_AUDIO |
 					GO7007_BOARD_USE_ONBOARD_I2C,
 		.audio_flags	 = GO7007_AUDIO_I2S_MODE_1 |
@@ -351,10 +369,9 @@ static struct go7007_usb_board board_lifeview_lr192 = {
 	},
 };
 
-static struct go7007_usb_board board_endura = {
+static const struct go7007_usb_board board_endura = {
 	.flags		= 0,
 	.main_info	= {
-		.firmware	 = "go7007tv.bin",
 		.flags		 = 0,
 		.audio_flags	 = GO7007_AUDIO_I2S_MODE_1 |
 					GO7007_AUDIO_I2S_MASTER |
@@ -376,10 +393,9 @@ static struct go7007_usb_board board_endura = {
 	},
 };
 
-static struct go7007_usb_board board_adlink_mpg24 = {
+static const struct go7007_usb_board board_adlink_mpg24 = {
 	.flags		= 0,
 	.main_info	= {
-		.firmware	 = "go7007tv.bin",
 		.flags		 = GO7007_BOARD_USE_ONBOARD_I2C,
 		.audio_flags	 = GO7007_AUDIO_I2S_MODE_1 |
 					GO7007_AUDIO_I2S_MASTER |
@@ -394,9 +410,10 @@ static struct go7007_usb_board board_adlink_mpg24 = {
 		.num_i2c_devs	 = 1,
 		.i2c_devs	 = {
 			{
-				.type	= "wis_tw2804",
-				.id	= I2C_DRIVERID_WIS_TW2804,
+				.type	= "tw2804",
 				.addr	= 0x00, /* yes, really */
+				.flags  = I2C_CLIENT_TEN,
+				.is_video = 1,
 			},
 		},
 		.num_inputs	 = 1,
@@ -408,10 +425,9 @@ static struct go7007_usb_board board_adlink_mpg24 = {
 	},
 };
 
-static struct go7007_usb_board board_sensoray_2250 = {
+static const struct go7007_usb_board board_sensoray_2250 = {
 	.flags		= GO7007_USB_EZUSB | GO7007_USB_EZUSB_I2C,
 	.main_info	= {
-		.firmware	 = "go7007tv.bin",
 		.audio_flags	 = GO7007_AUDIO_I2S_MODE_1 |
 					GO7007_AUDIO_I2S_MASTER |
 					GO7007_AUDIO_WORD_16,
@@ -426,8 +442,9 @@ static struct go7007_usb_board board_sensoray_2250 = {
 		.i2c_devs	 = {
 			{
 				.type	= "s2250",
-				.id	= I2C_DRIVERID_S2250,
 				.addr	= 0x43,
+				.is_video = 1,
+				.is_audio = 1,
 			},
 		},
 		.num_inputs	 = 2,
@@ -441,10 +458,60 @@ static struct go7007_usb_board board_sensoray_2250 = {
 				.name		= "S-Video",
 			},
 		},
+		.num_aud_inputs	 = 3,
+		.aud_inputs	 = {
+			{
+				.audio_input	= 0,
+				.name		= "Line In",
+			},
+			{
+				.audio_input	= 1,
+				.name		= "Mic",
+			},
+			{
+				.audio_input	= 2,
+				.name		= "Mic Boost",
+			},
+		},
 	},
 };
 
-MODULE_FIRMWARE("go7007tv.bin");
+static const struct go7007_usb_board board_ads_usbav_709 = {
+	.flags		= GO7007_USB_EZUSB,
+	.main_info	= {
+		.flags		 = GO7007_BOARD_HAS_AUDIO |
+					GO7007_BOARD_USE_ONBOARD_I2C,
+		.audio_flags	 = GO7007_AUDIO_I2S_MODE_1 |
+					GO7007_AUDIO_I2S_MASTER |
+					GO7007_AUDIO_WORD_16,
+		.audio_rate	 = 48000,
+		.audio_bclk_div	 = 8,
+		.audio_main_div	 = 2,
+		.hpi_buffer_cap  = 7,
+		.sensor_flags	 = GO7007_SENSOR_656 |
+					GO7007_SENSOR_TV |
+					GO7007_SENSOR_VBI,
+		.num_i2c_devs	 = 1,
+		.i2c_devs	 = {
+			{
+				.type	= "tw9906",
+				.is_video = 1,
+				.addr	= 0x44,
+			},
+		},
+		.num_inputs	 = 2,
+		.inputs		 = {
+			{
+				.video_input	= 0,
+				.name		= "Composite",
+			},
+			{
+				.video_input	= 10,
+				.name		= "S-Video",
+			},
+		},
+	},
+};
 
 static const struct usb_device_id go7007_usb_id_table[] = {
 	{
@@ -529,7 +596,7 @@ static const struct usb_device_id go7007_usb_id_table[] = {
 		.idProduct	= 0xa104,  /* Product ID of TV402U */
 		.bcdDevice_lo	= 0x1,
 		.bcdDevice_hi	= 0x1,
-		.driver_info	= (kernel_ulong_t)GO7007_BOARDID_PX_TV402U_ANY,
+		.driver_info	= (kernel_ulong_t)GO7007_BOARDID_PX_TV402U,
 	},
 	{
 		.match_flags	= USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION,
@@ -547,6 +614,14 @@ static const struct usb_device_id go7007_usb_id_table[] = {
 		.bcdDevice_hi	= 0x1,
 		.driver_info	= (kernel_ulong_t)GO7007_BOARDID_SENSORAY_2250,
 	},
+	{
+		.match_flags	= USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION,
+		.idVendor	= 0x06e1,  /* Vendor ID of ADS Technologies */
+		.idProduct	= 0x0709,  /* Product ID of DVD Xpress DX2 */
+		.bcdDevice_lo	= 0x204,
+		.bcdDevice_hi	= 0x204,
+		.driver_info	= (kernel_ulong_t)GO7007_BOARDID_ADS_USBAV_709,
+	},
 	{ }					/* Terminating entry */
 };
 
@@ -578,6 +653,8 @@ static int go7007_usb_interface_reset(struct go7007 *go)
 	struct go7007_usb *usb = go->hpi_context;
 	u16 intr_val, intr_data;
 
+	if (go->status == STATUS_SHUTDOWN)
+		return -1;
 	/* Reset encoder */
 	if (go7007_write_interrupt(go, 0x0001, 0x0001) < 0)
 		return -1;
@@ -613,7 +690,7 @@ static int go7007_usb_ezusb_write_interrupt(struct go7007 *go,
 {
 	struct go7007_usb *usb = go->hpi_context;
 	int i, r;
-	u16 status_reg;
+	u16 status_reg = 0;
 	int timeout = 500;
 
 #ifdef GO7007_USB_DEBUG
@@ -625,15 +702,17 @@ static int go7007_usb_ezusb_write_interrupt(struct go7007 *go,
 		r = usb_control_msg(usb->usbdev,
 				usb_rcvctrlpipe(usb->usbdev, 0), 0x14,
 				USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
-				0, HPI_STATUS_ADDR, &status_reg,
+				0, HPI_STATUS_ADDR, go->usb_buf,
 				sizeof(status_reg), timeout);
 		if (r < 0)
-			goto write_int_error;
-		__le16_to_cpus(&status_reg);
+			break;
+		status_reg = le16_to_cpu(*((u16 *)go->usb_buf));
 		if (!(status_reg & 0x0010))
 			break;
 		msleep(10);
 	}
+	if (r < 0)
+		goto write_int_error;
 	if (i == 100) {
 		printk(KERN_ERR
 			"go7007-usb: device is hung, status reg = 0x%04x\n",
@@ -661,7 +740,6 @@ static int go7007_usb_onboard_write_interrupt(struct go7007 *go,
 						int addr, int data)
 {
 	struct go7007_usb *usb = go->hpi_context;
-	u8 *tbuf;
 	int r;
 	int timeout = 500;
 
@@ -670,17 +748,14 @@ static int go7007_usb_onboard_write_interrupt(struct go7007 *go,
 		"go7007-usb: WriteInterrupt: %04x %04x\n", addr, data);
 #endif
 
-	tbuf = kzalloc(8, GFP_KERNEL);
-	if (tbuf == NULL)
-		return -ENOMEM;
-	tbuf[0] = data & 0xff;
-	tbuf[1] = data >> 8;
-	tbuf[2] = addr & 0xff;
-	tbuf[3] = addr >> 8;
+	go->usb_buf[0] = data & 0xff;
+	go->usb_buf[1] = data >> 8;
+	go->usb_buf[2] = addr & 0xff;
+	go->usb_buf[3] = addr >> 8;
+	go->usb_buf[4] = go->usb_buf[5] = go->usb_buf[6] = go->usb_buf[7] = 0;
 	r = usb_control_msg(usb->usbdev, usb_sndctrlpipe(usb->usbdev, 2), 0x00,
 			USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, 0x55aa,
-			0xf0f0, tbuf, 8, timeout);
-	kfree(tbuf);
+			0xf0f0, go->usb_buf, 8, timeout);
 	if (r < 0) {
 		printk(KERN_ERR "go7007-usb: error in WriteInterrupt: %d\n", r);
 		return r;
@@ -738,7 +813,7 @@ static void go7007_usb_read_video_pipe_complete(struct urb *urb)
 	struct go7007 *go = (struct go7007 *)urb->context;
 	int r, status = urb->status;
 
-	if (!go->streaming) {
+	if (!vb2_is_streaming(&go->vidq)) {
 		wake_up_interruptible(&go->frame_waitq);
 		return;
 	}
@@ -762,7 +837,7 @@ static void go7007_usb_read_audio_pipe_complete(struct urb *urb)
 	struct go7007 *go = (struct go7007 *)urb->context;
 	int r, status = urb->status;
 
-	if (!go->streaming)
+	if (!vb2_is_streaming(&go->vidq))
 		return;
 	if (status) {
 		printk(KERN_ERR "go7007-usb: error in audio pipe: %d\n",
@@ -849,6 +924,37 @@ static int go7007_usb_send_firmware(struct go7007 *go, u8 *data, int len)
 					&transferred, timeout);
 }
 
+static void go7007_usb_release(struct go7007 *go)
+{
+	struct go7007_usb *usb = go->hpi_context;
+	struct urb *vurb, *aurb;
+	int i;
+
+	if (usb->intr_urb) {
+		usb_kill_urb(usb->intr_urb);
+		kfree(usb->intr_urb->transfer_buffer);
+		usb_free_urb(usb->intr_urb);
+	}
+
+	/* Free USB-related structs */
+	for (i = 0; i < 8; ++i) {
+		vurb = usb->video_urbs[i];
+		if (vurb) {
+			usb_kill_urb(vurb);
+			kfree(vurb->transfer_buffer);
+			usb_free_urb(vurb);
+		}
+		aurb = usb->audio_urbs[i];
+		if (aurb) {
+			usb_kill_urb(aurb);
+			kfree(aurb->transfer_buffer);
+			usb_free_urb(aurb);
+		}
+	}
+
+	kfree(go->hpi_context);
+}
+
 static struct go7007_hpi_ops go7007_usb_ezusb_hpi_ops = {
 	.interface_reset	= go7007_usb_interface_reset,
 	.write_interrupt	= go7007_usb_ezusb_write_interrupt,
@@ -856,6 +962,7 @@ static struct go7007_hpi_ops go7007_usb_ezusb_hpi_ops = {
 	.stream_start		= go7007_usb_stream_start,
 	.stream_stop		= go7007_usb_stream_stop,
 	.send_firmware		= go7007_usb_send_firmware,
+	.release		= go7007_usb_release,
 };
 
 static struct go7007_hpi_ops go7007_usb_onboard_hpi_ops = {
@@ -865,6 +972,7 @@ static struct go7007_hpi_ops go7007_usb_onboard_hpi_ops = {
 	.stream_start		= go7007_usb_stream_start,
 	.stream_stop		= go7007_usb_stream_stop,
 	.send_firmware		= go7007_usb_send_firmware,
+	.release		= go7007_usb_release,
 };
 
 /********************* Driver for EZ-USB I2C adapter *********************/
@@ -874,12 +982,12 @@ static int go7007_usb_i2c_master_xfer(struct i2c_adapter *adapter,
 {
 	struct go7007 *go = i2c_get_adapdata(adapter);
 	struct go7007_usb *usb = go->hpi_context;
-	u8 buf[16];
+	u8 *buf = go->usb_buf;
 	int buf_len, i;
-	int ret = -1;
+	int ret = -EIO;
 
 	if (go->status == STATUS_SHUTDOWN)
-		return -1;
+		return -ENODEV;
 
 	mutex_lock(&usb->i2c_lock);
 
@@ -929,14 +1037,14 @@ static int go7007_usb_i2c_master_xfer(struct i2c_adapter *adapter,
 						buf, buf_len, 0) < 0)
 			goto i2c_done;
 		if (msgs[i].flags & I2C_M_RD) {
-			memset(buf, 0, sizeof(buf));
+			memset(buf, 0, msgs[i].len + 1);
 			if (go7007_usb_vendor_request(go, 0x25, 0, 0, buf,
 						msgs[i].len + 1, 1) < 0)
 				goto i2c_done;
 			memcpy(msgs[i].buf, buf + 1, msgs[i].len);
 		}
 	}
-	ret = 0;
+	ret = num;
 
 i2c_done:
 	mutex_unlock(&usb->i2c_lock);
@@ -968,8 +1076,9 @@ static int go7007_usb_probe(struct usb_interface *intf,
 {
 	struct go7007 *go;
 	struct go7007_usb *usb;
-	struct go7007_usb_board *board;
+	const struct go7007_usb_board *board;
 	struct usb_device *usbdev = interface_to_usbdev(intf);
+	unsigned num_i2c_devs;
 	char *name;
 	int video_pipe, i, v_urb_len;
 
@@ -1008,7 +1117,7 @@ static int go7007_usb_probe(struct usb_interface *intf,
 		name = "Plextor PX-M402U";
 		board = &board_matrix_ii;
 		break;
-	case GO7007_BOARDID_PX_TV402U_ANY:
+	case GO7007_BOARDID_PX_TV402U:
 		name = "Plextor PX-TV402U (unknown tuner)";
 		board = &board_px_tv402u;
 		break;
@@ -1024,29 +1133,29 @@ static int go7007_usb_probe(struct usb_interface *intf,
 		name = "Sensoray 2250/2251";
 		board = &board_sensoray_2250;
 		break;
+	case GO7007_BOARDID_ADS_USBAV_709:
+		name = "ADS Tech DVD Xpress DX2";
+		board = &board_ads_usbav_709;
+		break;
 	default:
 		printk(KERN_ERR "go7007-usb: unknown board ID %d!\n",
 				(unsigned int)id->driver_info);
 		return 0;
 	}
 
-	usb = kzalloc(sizeof(struct go7007_usb), GFP_KERNEL);
-	if (usb == NULL)
+	go = go7007_alloc(&board->main_info, &intf->dev);
+	if (go == NULL)
 		return -ENOMEM;
 
-	/* Allocate the URB and buffer for receiving incoming interrupts */
-	usb->intr_urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (usb->intr_urb == NULL)
-		goto allocfail;
-	usb->intr_urb->transfer_buffer = kmalloc(2*sizeof(u16), GFP_KERNEL);
-	if (usb->intr_urb->transfer_buffer == NULL)
-		goto allocfail;
+	usb = kzalloc(sizeof(struct go7007_usb), GFP_KERNEL);
+	if (usb == NULL) {
+		kfree(go);
+		return -ENOMEM;
+	}
 
-	go = go7007_alloc(&board->main_info, &intf->dev);
-	if (go == NULL)
-		goto allocfail;
 	usb->board = board;
 	usb->usbdev = usbdev;
+	usb_make_path(usbdev, go->bus_info, sizeof(go->bus_info));
 	go->board_id = id->driver_info;
 	strncpy(go->name, name, sizeof(go->name));
 	if (board->flags & GO7007_USB_EZUSB)
@@ -1054,6 +1163,15 @@ static int go7007_usb_probe(struct usb_interface *intf,
 	else
 		go->hpi_ops = &go7007_usb_onboard_hpi_ops;
 	go->hpi_context = usb;
+
+	/* Allocate the URB and buffer for receiving incoming interrupts */
+	usb->intr_urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (usb->intr_urb == NULL)
+		goto allocfail;
+	usb->intr_urb->transfer_buffer = kmalloc(2*sizeof(u16), GFP_KERNEL);
+	if (usb->intr_urb->transfer_buffer == NULL)
+		goto allocfail;
+
 	if (go->board_id == GO7007_BOARDID_SENSORAY_2250)
 		usb_fill_bulk_urb(usb->intr_urb, usb->usbdev,
 			usb_rcvbulkpipe(usb->usbdev, 4),
@@ -1069,7 +1187,7 @@ static int go7007_usb_probe(struct usb_interface *intf,
 	/* Boot the GO7007 */
 	if (go7007_boot_encoder(go, go->board_info->flags &
 					GO7007_BOARD_USE_ONBOARD_I2C) < 0)
-		goto initfail;
+		goto allocfail;
 
 	/* Register the EZ-USB I2C adapter, if we're using it */
 	if (board->flags & GO7007_USB_EZUSB_I2C) {
@@ -1081,7 +1199,7 @@ static int go7007_usb_probe(struct usb_interface *intf,
 		if (i2c_add_adapter(&go->i2c_adapter) < 0) {
 			printk(KERN_ERR
 				"go7007-usb: error: i2c_add_adapter failed\n");
-			goto initfail;
+			goto allocfail;
 		}
 		go->i2c_adapter_online = 1;
 	}
@@ -1121,34 +1239,36 @@ static int go7007_usb_probe(struct usb_interface *intf,
 					"Adlink PCI-MPG24, channel #%d",
 					channel);
 			}
+			go7007_update_board(go);
 		}
 	}
 
-	/* Probe the tuner model on the TV402U */
-	if (go->board_id == GO7007_BOARDID_PX_TV402U_ANY) {
-		u8 data[3];
+	num_i2c_devs = go->board_info->num_i2c_devs;
 
+	/* Probe the tuner model on the TV402U */
+	if (go->board_id == GO7007_BOARDID_PX_TV402U) {
 		/* Board strapping indicates tuner model */
-		if (go7007_usb_vendor_request(go, 0x41, 0, 0, data, 3, 1) < 0) {
+		if (go7007_usb_vendor_request(go, 0x41, 0, 0, go->usb_buf, 3, 1) < 0) {
 			printk(KERN_ERR "go7007-usb: GPIO read failed!\n");
-			goto initfail;
+			goto allocfail;
 		}
-		switch (data[0] >> 6) {
+		switch (go->usb_buf[0] >> 6) {
 		case 1:
-			go->board_id = GO7007_BOARDID_PX_TV402U_EU;
 			go->tuner_type = TUNER_SONY_BTF_PG472Z;
+			go->std = V4L2_STD_PAL;
 			strncpy(go->name, "Plextor PX-TV402U-EU",
 					sizeof(go->name));
 			break;
 		case 2:
-			go->board_id = GO7007_BOARDID_PX_TV402U_JP;
 			go->tuner_type = TUNER_SONY_BTF_PK467Z;
+			go->std = V4L2_STD_NTSC_M_JP;
+			num_i2c_devs -= 2;
 			strncpy(go->name, "Plextor PX-TV402U-JP",
 					sizeof(go->name));
 			break;
 		case 3:
-			go->board_id = GO7007_BOARDID_PX_TV402U_NA;
 			go->tuner_type = TUNER_SONY_BTF_PB463Z;
+			num_i2c_devs -= 2;
 			strncpy(go->name, "Plextor PX-TV402U-NA",
 					sizeof(go->name));
 			break;
@@ -1162,7 +1282,7 @@ static int go7007_usb_probe(struct usb_interface *intf,
 		if (go7007_usb_vendor_request(go, 0x40, 0x7f02, 0,
 					NULL, 0, 0) < 0) {
 			printk(KERN_ERR "go7007-usb: GPIO write failed!\n");
-			goto initfail;
+			goto allocfail;
 		}
 	}
 
@@ -1176,11 +1296,6 @@ static int go7007_usb_probe(struct usb_interface *intf,
 				"port will result in stream corruption, even "
 				"at low bitrates!\n");
 
-	/* Do any final GO7007 initialization, then register the
-	 * V4L2 and ALSA interfaces */
-	if (go7007_register_encoder(go) < 0)
-		goto initfail;
-
 	/* Allocate the URBs and buffers for receiving the video stream */
 	if (board->flags & GO7007_USB_EZUSB) {
 		v_urb_len = 1024;
@@ -1192,80 +1307,65 @@ static int go7007_usb_probe(struct usb_interface *intf,
 	for (i = 0; i < 8; ++i) {
 		usb->video_urbs[i] = usb_alloc_urb(0, GFP_KERNEL);
 		if (usb->video_urbs[i] == NULL)
-			goto initfail;
+			goto allocfail;
 		usb->video_urbs[i]->transfer_buffer =
 						kmalloc(v_urb_len, GFP_KERNEL);
 		if (usb->video_urbs[i]->transfer_buffer == NULL)
-			goto initfail;
+			goto allocfail;
 		usb_fill_bulk_urb(usb->video_urbs[i], usb->usbdev, video_pipe,
 				usb->video_urbs[i]->transfer_buffer, v_urb_len,
 				go7007_usb_read_video_pipe_complete, go);
 	}
 
 	/* Allocate the URBs and buffers for receiving the audio stream */
-	if ((board->flags & GO7007_USB_EZUSB) && go->audio_enabled)
+	if ((board->flags & GO7007_USB_EZUSB) &&
+	    (board->flags & GO7007_BOARD_HAS_AUDIO)) {
 		for (i = 0; i < 8; ++i) {
 			usb->audio_urbs[i] = usb_alloc_urb(0, GFP_KERNEL);
 			if (usb->audio_urbs[i] == NULL)
-				goto initfail;
+				goto allocfail;
 			usb->audio_urbs[i]->transfer_buffer = kmalloc(4096,
 								GFP_KERNEL);
 			if (usb->audio_urbs[i]->transfer_buffer == NULL)
-				goto initfail;
+				goto allocfail;
 			usb_fill_bulk_urb(usb->audio_urbs[i], usb->usbdev,
 				usb_rcvbulkpipe(usb->usbdev, 8),
 				usb->audio_urbs[i]->transfer_buffer, 4096,
 				go7007_usb_read_audio_pipe_complete, go);
 		}
+	}
 
+	/* Do any final GO7007 initialization, then register the
+	 * V4L2 and ALSA interfaces */
+	if (go7007_register_encoder(go, num_i2c_devs) < 0)
+		goto allocfail;
 
 	go->status = STATUS_ONLINE;
 	return 0;
 
-initfail:
-	go->status = STATUS_SHUTDOWN;
-	return 0;
-
 allocfail:
-	if (usb->intr_urb) {
-		kfree(usb->intr_urb->transfer_buffer);
-		usb_free_urb(usb->intr_urb);
-	}
-	kfree(usb);
+	go7007_usb_release(go);
+	kfree(go);
 	return -ENOMEM;
 }
 
 static void go7007_usb_disconnect(struct usb_interface *intf)
 {
 	struct go7007 *go = to_go7007(usb_get_intfdata(intf));
-	struct go7007_usb *usb = go->hpi_context;
-	struct urb *vurb, *aurb;
-	int i;
 
-	usb_kill_urb(usb->intr_urb);
+	mutex_lock(&go->queue_lock);
+	mutex_lock(&go->serialize_lock);
 
-	/* Free USB-related structs */
-	for (i = 0; i < 8; ++i) {
-		vurb = usb->video_urbs[i];
-		if (vurb) {
-			usb_kill_urb(vurb);
-			kfree(vurb->transfer_buffer);
-			usb_free_urb(vurb);
-		}
-		aurb = usb->audio_urbs[i];
-		if (aurb) {
-			usb_kill_urb(aurb);
-			kfree(aurb->transfer_buffer);
-			usb_free_urb(aurb);
-		}
-	}
-	kfree(usb->intr_urb->transfer_buffer);
-	usb_free_urb(usb->intr_urb);
-
-	kfree(go->hpi_context);
+	if (go->audio_enabled)
+		go7007_snd_remove(go);
 
-	go7007_remove(go);
 	go->status = STATUS_SHUTDOWN;
+	v4l2_device_disconnect(&go->v4l2_dev);
+	video_unregister_device(&go->vdev);
+	mutex_unlock(&go->serialize_lock);
+	mutex_unlock(&go->queue_lock);
+
+	v4l2_device_put(&go->v4l2_dev);
 }
 
 static struct usb_driver go7007_usb_driver = {
diff --git a/drivers/staging/media/go7007/go7007-v4l2.c b/drivers/staging/media/go7007/go7007-v4l2.c
index cb9fe33..50eb69a 100644
--- a/drivers/staging/media/go7007/go7007-v4l2.c
+++ b/drivers/staging/media/go7007/go7007-v4l2.c
@@ -17,7 +17,6 @@
 
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/version.h>
 #include <linux/delay.h>
 #include <linux/sched.h>
 #include <linux/spinlock.h>
@@ -27,115 +26,45 @@
 #include <linux/time.h>
 #include <linux/vmalloc.h>
 #include <linux/pagemap.h>
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+#include <linux/uaccess.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-subdev.h>
-#include <linux/i2c.h>
-#include <linux/mutex.h>
-#include <linux/uaccess.h>
+#include <media/v4l2-event.h>
+#include <media/videobuf2-vmalloc.h>
+#include <media/saa7115.h>
 
 #include "go7007.h"
 #include "go7007-priv.h"
-#include "wis-i2c.h"
-
-/* Temporary defines until accepted in v4l-dvb */
-#ifndef V4L2_MPEG_STREAM_TYPE_MPEG_ELEM
-#define	V4L2_MPEG_STREAM_TYPE_MPEG_ELEM   6 /* MPEG elementary stream */
-#endif
-#ifndef V4L2_MPEG_VIDEO_ENCODING_MPEG_4
-#define	V4L2_MPEG_VIDEO_ENCODING_MPEG_4   3
-#endif
 
 #define call_all(dev, o, f, args...) \
 	v4l2_device_call_until_err(dev, 0, o, f, ##args)
 
-static void deactivate_buffer(struct go7007_buffer *gobuf)
-{
-	int i;
-
-	if (gobuf->state != BUF_STATE_IDLE) {
-		list_del(&gobuf->stream);
-		gobuf->state = BUF_STATE_IDLE;
-	}
-	if (gobuf->page_count > 0) {
-		for (i = 0; i < gobuf->page_count; ++i)
-			page_cache_release(gobuf->pages[i]);
-		gobuf->page_count = 0;
-	}
-}
-
-static void abort_queued(struct go7007 *go)
-{
-	struct go7007_buffer *gobuf, *next;
-
-	list_for_each_entry_safe(gobuf, next, &go->stream, stream) {
-		deactivate_buffer(gobuf);
-	}
-}
-
-static int go7007_streamoff(struct go7007 *go)
-{
-	unsigned long flags;
-
-	mutex_lock(&go->hw_lock);
-	if (go->streaming) {
-		go->streaming = 0;
-		go7007_stream_stop(go);
-		spin_lock_irqsave(&go->spinlock, flags);
-		abort_queued(go);
-		spin_unlock_irqrestore(&go->spinlock, flags);
-		go7007_reset_encoder(go);
-	}
-	mutex_unlock(&go->hw_lock);
-	return 0;
-}
-
-static int go7007_open(struct file *file)
-{
-	struct go7007 *go = video_get_drvdata(video_devdata(file));
-	struct go7007_file *gofh;
-
-	if (go->status != STATUS_ONLINE)
-		return -EBUSY;
-	gofh = kzalloc(sizeof(struct go7007_file), GFP_KERNEL);
-	if (gofh == NULL)
-		return -ENOMEM;
-	++go->ref_count;
-	gofh->go = go;
-	mutex_init(&gofh->lock);
-	gofh->buf_count = 0;
-	file->private_data = gofh;
-	return 0;
-}
-
-static int go7007_release(struct file *file)
+static bool valid_pixelformat(u32 pixelformat)
 {
-	struct go7007_file *gofh = file->private_data;
-	struct go7007 *go = gofh->go;
-
-	if (gofh->buf_count > 0) {
-		go7007_streamoff(go);
-		go->in_use = 0;
-		kfree(gofh->bufs);
-		gofh->buf_count = 0;
+	switch (pixelformat) {
+	case V4L2_PIX_FMT_MJPEG:
+	case V4L2_PIX_FMT_MPEG1:
+	case V4L2_PIX_FMT_MPEG2:
+	case V4L2_PIX_FMT_MPEG4:
+		return true;
+	default:
+		return false;
 	}
-	kfree(gofh);
-	if (--go->ref_count == 0)
-		kfree(go);
-	file->private_data = NULL;
-	return 0;
 }
 
-static u32 get_frame_type_flag(struct go7007_buffer *gobuf, int format)
+static u32 get_frame_type_flag(struct go7007_buffer *vb, int format)
 {
-	u8 *f = page_address(gobuf->pages[0]);
+	u8 *ptr = vb2_plane_vaddr(&vb->vb, 0);
 
 	switch (format) {
-	case GO7007_FORMAT_MJPEG:
+	case V4L2_PIX_FMT_MJPEG:
 		return V4L2_BUF_FLAG_KEYFRAME;
-	case GO7007_FORMAT_MPEG4:
-		switch ((f[gobuf->frame_offset + 4] >> 6) & 0x3) {
+	case V4L2_PIX_FMT_MPEG4:
+		switch ((ptr[vb->frame_offset + 4] >> 6) & 0x3) {
 		case 0:
 			return V4L2_BUF_FLAG_KEYFRAME;
 		case 1:
@@ -145,9 +74,9 @@ static u32 get_frame_type_flag(struct go7007_buffer *gobuf, int format)
 		default:
 			return 0;
 		}
-	case GO7007_FORMAT_MPEG1:
-	case GO7007_FORMAT_MPEG2:
-		switch ((f[gobuf->frame_offset + 5] >> 3) & 0x7) {
+	case V4L2_PIX_FMT_MPEG1:
+	case V4L2_PIX_FMT_MPEG2:
+		switch ((ptr[vb->frame_offset + 5] >> 3) & 0x7) {
 		case 1:
 			return V4L2_BUF_FLAG_KEYFRAME;
 		case 2:
@@ -162,30 +91,111 @@ static u32 get_frame_type_flag(struct go7007_buffer *gobuf, int format)
 	return 0;
 }
 
-static int set_capture_size(struct go7007 *go, struct v4l2_format *fmt, int try)
+static void get_resolution(struct go7007 *go, int *width, int *height)
 {
-	int sensor_height = 0, sensor_width = 0;
-	int width, height, i;
-
-	if (fmt != NULL && fmt->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG &&
-			fmt->fmt.pix.pixelformat != V4L2_PIX_FMT_MPEG &&
-			fmt->fmt.pix.pixelformat != V4L2_PIX_FMT_MPEG4)
-		return -EINVAL;
-
 	switch (go->standard) {
 	case GO7007_STD_NTSC:
-		sensor_width = 720;
-		sensor_height = 480;
+		*width = 720;
+		*height = 480;
 		break;
 	case GO7007_STD_PAL:
-		sensor_width = 720;
-		sensor_height = 576;
+		*width = 720;
+		*height = 576;
 		break;
 	case GO7007_STD_OTHER:
-		sensor_width = go->board_info->sensor_width;
-		sensor_height = go->board_info->sensor_height;
+	default:
+		*width = go->board_info->sensor_width;
+		*height = go->board_info->sensor_height;
+		break;
+	}
+}
+
+static void set_formatting(struct go7007 *go)
+{
+	if (go->format == V4L2_PIX_FMT_MJPEG) {
+		go->pali = 0;
+		go->aspect_ratio = GO7007_RATIO_1_1;
+		go->gop_size = 0;
+		go->ipb = 0;
+		go->closed_gop = 0;
+		go->repeat_seqhead = 0;
+		go->seq_header_enable = 0;
+		go->gop_header_enable = 0;
+		go->dvd_mode = 0;
+		return;
+	}
+
+	switch (go->format) {
+	case V4L2_PIX_FMT_MPEG1:
+		go->pali = 0;
+		break;
+	default:
+	case V4L2_PIX_FMT_MPEG2:
+		go->pali = 0x48;
+		break;
+	case V4L2_PIX_FMT_MPEG4:
+		/* For future reference: this is the list of MPEG4
+		 * profiles that are available, although they are
+		 * untested:
+		 *
+		 * Profile		pali
+		 * --------------	----
+		 * PROFILE_S_L0		0x08
+		 * PROFILE_S_L1		0x01
+		 * PROFILE_S_L2		0x02
+		 * PROFILE_S_L3		0x03
+		 * PROFILE_ARTS_L1	0x91
+		 * PROFILE_ARTS_L2	0x92
+		 * PROFILE_ARTS_L3	0x93
+		 * PROFILE_ARTS_L4	0x94
+		 * PROFILE_AS_L0	0xf0
+		 * PROFILE_AS_L1	0xf1
+		 * PROFILE_AS_L2	0xf2
+		 * PROFILE_AS_L3	0xf3
+		 * PROFILE_AS_L4	0xf4
+		 * PROFILE_AS_L5	0xf5
+		 */
+		go->pali = 0xf5;
+		break;
+	}
+	go->gop_size = v4l2_ctrl_g_ctrl(go->mpeg_video_gop_size);
+	go->closed_gop = v4l2_ctrl_g_ctrl(go->mpeg_video_gop_closure);
+	go->ipb = v4l2_ctrl_g_ctrl(go->mpeg_video_b_frames) != 0;
+	go->bitrate = v4l2_ctrl_g_ctrl(go->mpeg_video_bitrate);
+	go->repeat_seqhead = v4l2_ctrl_g_ctrl(go->mpeg_video_rep_seqheader);
+	go->gop_header_enable = 1;
+	go->dvd_mode = 0;
+	if (go->format == V4L2_PIX_FMT_MPEG2)
+		go->dvd_mode =
+			go->bitrate == 9800000 &&
+			go->gop_size == 15 &&
+			go->ipb == 0 &&
+			go->repeat_seqhead == 1 &&
+			go->closed_gop;
+
+	switch (v4l2_ctrl_g_ctrl(go->mpeg_video_aspect_ratio)) {
+	default:
+	case V4L2_MPEG_VIDEO_ASPECT_1x1:
+		go->aspect_ratio = GO7007_RATIO_1_1;
+		break;
+	case V4L2_MPEG_VIDEO_ASPECT_4x3:
+		go->aspect_ratio = GO7007_RATIO_4_3;
+		break;
+	case V4L2_MPEG_VIDEO_ASPECT_16x9:
+		go->aspect_ratio = GO7007_RATIO_16_9;
 		break;
 	}
+}
+
+static int set_capture_size(struct go7007 *go, struct v4l2_format *fmt, int try)
+{
+	int sensor_height = 0, sensor_width = 0;
+	int width, height, i;
+
+	if (fmt != NULL && !valid_pixelformat(fmt->fmt.pix.pixelformat))
+		return -EINVAL;
+
+	get_resolution(go, &sensor_width, &sensor_height);
 
 	if (fmt == NULL) {
 		width = sensor_width;
@@ -205,13 +215,12 @@ static int set_capture_size(struct go7007 *go, struct v4l2_format *fmt, int try)
 		else
 			height = fmt->fmt.pix.height & ~0x0f;
 	} else {
-		int requested_size = fmt->fmt.pix.width * fmt->fmt.pix.height;
-		int sensor_size = sensor_width * sensor_height;
+		width = fmt->fmt.pix.width;
 
-		if (64 * requested_size < 9 * sensor_size) {
+		if (width <= sensor_width / 4) {
 			width = sensor_width / 4;
 			height = sensor_height / 4;
-		} else if (64 * requested_size < 36 * sensor_size) {
+		} else if (width <= sensor_width / 2) {
 			width = sensor_width / 2;
 			height = sensor_height / 2;
 		} else {
@@ -233,12 +242,14 @@ static int set_capture_size(struct go7007 *go, struct v4l2_format *fmt, int try)
 		fmt->fmt.pix.field = V4L2_FIELD_NONE;
 		fmt->fmt.pix.bytesperline = 0;
 		fmt->fmt.pix.sizeimage = GO7007_BUF_SIZE;
-		fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; /* ?? */
+		fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
 	}
 
 	if (try)
 		return 0;
 
+	if (fmt)
+		go->format = fmt->fmt.pix.pixelformat;
 	go->width = width;
 	go->height = height;
 	go->encoder_h_offset = go->board_info->sensor_h_offset;
@@ -252,18 +263,11 @@ static int set_capture_size(struct go7007 *go, struct v4l2_format *fmt, int try)
 		struct v4l2_mbus_framefmt mbus_fmt;
 
 		mbus_fmt.code = V4L2_MBUS_FMT_FIXED;
-		if (fmt != NULL)
-			mbus_fmt.width = fmt->fmt.pix.width;
-		else
-			mbus_fmt.width = width;
-
-		if (height > sensor_height / 2) {
-			mbus_fmt.height = height / 2;
-			go->encoder_v_halve = 0;
-		} else {
-			mbus_fmt.height = height;
-			go->encoder_v_halve = 1;
-		}
+		mbus_fmt.width = fmt ? fmt->fmt.pix.width : width;
+		mbus_fmt.height = height;
+		go->encoder_h_halve = 0;
+		go->encoder_v_halve = 0;
+		go->encoder_subsample = 0;
 		call_all(&go->v4l2_dev, video, s_mbus_fmt, &mbus_fmt);
 	} else {
 		if (width <= sensor_width / 4) {
@@ -280,55 +284,6 @@ static int set_capture_size(struct go7007 *go, struct v4l2_format *fmt, int try)
 			go->encoder_subsample = 0;
 		}
 	}
-
-	if (fmt == NULL)
-		return 0;
-
-	switch (fmt->fmt.pix.pixelformat) {
-	case V4L2_PIX_FMT_MPEG:
-		if (go->format == GO7007_FORMAT_MPEG1 ||
-				go->format == GO7007_FORMAT_MPEG2 ||
-				go->format == GO7007_FORMAT_MPEG4)
-			break;
-		go->format = GO7007_FORMAT_MPEG1;
-		go->pali = 0;
-		go->aspect_ratio = GO7007_RATIO_1_1;
-		go->gop_size = go->sensor_framerate / 1000;
-		go->ipb = 0;
-		go->closed_gop = 1;
-		go->repeat_seqhead = 1;
-		go->seq_header_enable = 1;
-		go->gop_header_enable = 1;
-		go->dvd_mode = 0;
-		break;
-	/* Backwards compatibility only! */
-	case V4L2_PIX_FMT_MPEG4:
-		if (go->format == GO7007_FORMAT_MPEG4)
-			break;
-		go->format = GO7007_FORMAT_MPEG4;
-		go->pali = 0xf5;
-		go->aspect_ratio = GO7007_RATIO_1_1;
-		go->gop_size = go->sensor_framerate / 1000;
-		go->ipb = 0;
-		go->closed_gop = 1;
-		go->repeat_seqhead = 1;
-		go->seq_header_enable = 1;
-		go->gop_header_enable = 1;
-		go->dvd_mode = 0;
-		break;
-	case V4L2_PIX_FMT_MJPEG:
-		go->format = GO7007_FORMAT_MJPEG;
-		go->pali = 0;
-		go->aspect_ratio = GO7007_RATIO_1_1;
-		go->gop_size = 0;
-		go->ipb = 0;
-		go->closed_gop = 0;
-		go->repeat_seqhead = 0;
-		go->seq_header_enable = 0;
-		go->gop_header_enable = 0;
-		go->dvd_mode = 0;
-		break;
-	}
 	return 0;
 }
 
@@ -390,230 +345,23 @@ static int clip_to_modet_map(struct go7007 *go, int region,
 }
 #endif
 
-static int mpeg_query_ctrl(struct v4l2_queryctrl *ctrl)
-{
-	static const u32 mpeg_ctrls[] = {
-		V4L2_CID_MPEG_CLASS,
-		V4L2_CID_MPEG_STREAM_TYPE,
-		V4L2_CID_MPEG_VIDEO_ENCODING,
-		V4L2_CID_MPEG_VIDEO_ASPECT,
-		V4L2_CID_MPEG_VIDEO_GOP_SIZE,
-		V4L2_CID_MPEG_VIDEO_GOP_CLOSURE,
-		V4L2_CID_MPEG_VIDEO_BITRATE,
-		0
-	};
-	static const u32 *ctrl_classes[] = {
-		mpeg_ctrls,
-		NULL
-	};
-
-	ctrl->id = v4l2_ctrl_next(ctrl_classes, ctrl->id);
-
-	switch (ctrl->id) {
-	case V4L2_CID_MPEG_CLASS:
-		return v4l2_ctrl_query_fill(ctrl, 0, 0, 0, 0);
-	case V4L2_CID_MPEG_STREAM_TYPE:
-		return v4l2_ctrl_query_fill(ctrl,
-				V4L2_MPEG_STREAM_TYPE_MPEG2_DVD,
-				V4L2_MPEG_STREAM_TYPE_MPEG_ELEM, 1,
-				V4L2_MPEG_STREAM_TYPE_MPEG_ELEM);
-	case V4L2_CID_MPEG_VIDEO_ENCODING:
-		return v4l2_ctrl_query_fill(ctrl,
-				V4L2_MPEG_VIDEO_ENCODING_MPEG_1,
-				V4L2_MPEG_VIDEO_ENCODING_MPEG_4, 1,
-				V4L2_MPEG_VIDEO_ENCODING_MPEG_2);
-	case V4L2_CID_MPEG_VIDEO_ASPECT:
-		return v4l2_ctrl_query_fill(ctrl,
-				V4L2_MPEG_VIDEO_ASPECT_1x1,
-				V4L2_MPEG_VIDEO_ASPECT_16x9, 1,
-				V4L2_MPEG_VIDEO_ASPECT_1x1);
-	case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
-		return v4l2_ctrl_query_fill(ctrl, 0, 34, 1, 15);
-	case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
-		return v4l2_ctrl_query_fill(ctrl, 0, 1, 1, 0);
-	case V4L2_CID_MPEG_VIDEO_BITRATE:
-		return v4l2_ctrl_query_fill(ctrl,
-				64000,
-				10000000, 1,
-				1500000);
-	default:
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static int mpeg_s_ctrl(struct v4l2_control *ctrl, struct go7007 *go)
-{
-	/* pretty sure we can't change any of these while streaming */
-	if (go->streaming)
-		return -EBUSY;
-
-	switch (ctrl->id) {
-	case V4L2_CID_MPEG_STREAM_TYPE:
-		switch (ctrl->value) {
-		case V4L2_MPEG_STREAM_TYPE_MPEG2_DVD:
-			go->format = GO7007_FORMAT_MPEG2;
-			go->bitrate = 9800000;
-			go->gop_size = 15;
-			go->pali = 0x48;
-			go->closed_gop = 1;
-			go->repeat_seqhead = 0;
-			go->seq_header_enable = 1;
-			go->gop_header_enable = 1;
-			go->dvd_mode = 1;
-			break;
-		case V4L2_MPEG_STREAM_TYPE_MPEG_ELEM:
-			/* todo: */
-			break;
-		default:
-			return -EINVAL;
-		}
-		break;
-	case V4L2_CID_MPEG_VIDEO_ENCODING:
-		switch (ctrl->value) {
-		case V4L2_MPEG_VIDEO_ENCODING_MPEG_1:
-			go->format = GO7007_FORMAT_MPEG1;
-			go->pali = 0;
-			break;
-		case V4L2_MPEG_VIDEO_ENCODING_MPEG_2:
-			go->format = GO7007_FORMAT_MPEG2;
-			/*if (mpeg->pali >> 24 == 2)
-				go->pali = mpeg->pali & 0xff;
-			else*/
-				go->pali = 0x48;
-			break;
-		case V4L2_MPEG_VIDEO_ENCODING_MPEG_4:
-			go->format = GO7007_FORMAT_MPEG4;
-			/*if (mpeg->pali >> 24 == 4)
-				go->pali = mpeg->pali & 0xff;
-			else*/
-				go->pali = 0xf5;
-			break;
-		default:
-			return -EINVAL;
-		}
-		go->gop_header_enable =
-			/*mpeg->flags & GO7007_MPEG_OMIT_GOP_HEADER
-			? 0 :*/ 1;
-		/*if (mpeg->flags & GO7007_MPEG_REPEAT_SEQHEADER)
-			go->repeat_seqhead = 1;
-		else*/
-			go->repeat_seqhead = 0;
-		go->dvd_mode = 0;
-		break;
-	case V4L2_CID_MPEG_VIDEO_ASPECT:
-		if (go->format == GO7007_FORMAT_MJPEG)
-			return -EINVAL;
-		switch (ctrl->value) {
-		case V4L2_MPEG_VIDEO_ASPECT_1x1:
-			go->aspect_ratio = GO7007_RATIO_1_1;
-			break;
-		case V4L2_MPEG_VIDEO_ASPECT_4x3:
-			go->aspect_ratio = GO7007_RATIO_4_3;
-			break;
-		case V4L2_MPEG_VIDEO_ASPECT_16x9:
-			go->aspect_ratio = GO7007_RATIO_16_9;
-			break;
-		case V4L2_MPEG_VIDEO_ASPECT_221x100:
-		default:
-			return -EINVAL;
-		}
-		break;
-	case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
-		if (ctrl->value < 0 || ctrl->value > 34)
-			return -EINVAL;
-		go->gop_size = ctrl->value;
-		break;
-	case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
-		if (ctrl->value != 0 && ctrl->value != 1)
-			return -EINVAL;
-		go->closed_gop = ctrl->value;
-		break;
-	case V4L2_CID_MPEG_VIDEO_BITRATE:
-		/* Upper bound is kind of arbitrary here */
-		if (ctrl->value < 64000 || ctrl->value > 10000000)
-			return -EINVAL;
-		go->bitrate = ctrl->value;
-		break;
-	default:
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static int mpeg_g_ctrl(struct v4l2_control *ctrl, struct go7007 *go)
-{
-	switch (ctrl->id) {
-	case V4L2_CID_MPEG_STREAM_TYPE:
-		if (go->dvd_mode)
-			ctrl->value = V4L2_MPEG_STREAM_TYPE_MPEG2_DVD;
-		else
-			ctrl->value = V4L2_MPEG_STREAM_TYPE_MPEG_ELEM;
-		break;
-	case V4L2_CID_MPEG_VIDEO_ENCODING:
-		switch (go->format) {
-		case GO7007_FORMAT_MPEG1:
-			ctrl->value = V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
-			break;
-		case GO7007_FORMAT_MPEG2:
-			ctrl->value = V4L2_MPEG_VIDEO_ENCODING_MPEG_2;
-			break;
-		case GO7007_FORMAT_MPEG4:
-			ctrl->value = V4L2_MPEG_VIDEO_ENCODING_MPEG_4;
-			break;
-		default:
-			return -EINVAL;
-		}
-		break;
-	case V4L2_CID_MPEG_VIDEO_ASPECT:
-		switch (go->aspect_ratio) {
-		case GO7007_RATIO_1_1:
-			ctrl->value = V4L2_MPEG_VIDEO_ASPECT_1x1;
-			break;
-		case GO7007_RATIO_4_3:
-			ctrl->value = V4L2_MPEG_VIDEO_ASPECT_4x3;
-			break;
-		case GO7007_RATIO_16_9:
-			ctrl->value = V4L2_MPEG_VIDEO_ASPECT_16x9;
-			break;
-		default:
-			return -EINVAL;
-		}
-		break;
-	case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
-		ctrl->value = go->gop_size;
-		break;
-	case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
-		ctrl->value = go->closed_gop;
-		break;
-	case V4L2_CID_MPEG_VIDEO_BITRATE:
-		ctrl->value = go->bitrate;
-		break;
-	default:
-		return -EINVAL;
-	}
-	return 0;
-}
-
 static int vidioc_querycap(struct file *file, void  *priv,
 					struct v4l2_capability *cap)
 {
-	struct go7007 *go = ((struct go7007_file *) priv)->go;
+	struct go7007 *go = video_drvdata(file);
 
 	strlcpy(cap->driver, "go7007", sizeof(cap->driver));
 	strlcpy(cap->card, go->name, sizeof(cap->card));
-#if 0
-	strlcpy(cap->bus_info, dev_name(&dev->udev->dev), sizeof(cap->bus_info));
-#endif
-
-	cap->version = KERNEL_VERSION(0, 9, 8);
+	strlcpy(cap->bus_info, go->bus_info, sizeof(cap->bus_info));
 
-	cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
-			    V4L2_CAP_STREAMING; /* | V4L2_CAP_AUDIO; */
+	cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
+				V4L2_CAP_STREAMING;
 
+	if (go->board_info->num_aud_inputs)
+		cap->device_caps |= V4L2_CAP_AUDIO;
 	if (go->board_info->flags & GO7007_BOARD_HAS_TUNER)
-		cap->capabilities |= V4L2_CAP_TUNER;
-
+		cap->device_caps |= V4L2_CAP_TUNER;
+	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
 	return 0;
 }
 
@@ -625,11 +373,19 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void  *priv,
 	switch (fmt->index) {
 	case 0:
 		fmt->pixelformat = V4L2_PIX_FMT_MJPEG;
-		desc = "Motion-JPEG";
+		desc = "Motion JPEG";
 		break;
 	case 1:
-		fmt->pixelformat = V4L2_PIX_FMT_MPEG;
-		desc = "MPEG1/MPEG2/MPEG4";
+		fmt->pixelformat = V4L2_PIX_FMT_MPEG1;
+		desc = "MPEG-1 ES";
+		break;
+	case 2:
+		fmt->pixelformat = V4L2_PIX_FMT_MPEG2;
+		desc = "MPEG-2 ES";
+		break;
+	case 3:
+		fmt->pixelformat = V4L2_PIX_FMT_MPEG4;
+		desc = "MPEG-4 ES";
 		break;
 	default:
 		return -EINVAL;
@@ -645,13 +401,12 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void  *priv,
 static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
 					struct v4l2_format *fmt)
 {
-	struct go7007 *go = ((struct go7007_file *) priv)->go;
+	struct go7007 *go = video_drvdata(file);
 
 	fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 	fmt->fmt.pix.width = go->width;
 	fmt->fmt.pix.height = go->height;
-	fmt->fmt.pix.pixelformat = (go->format == GO7007_FORMAT_MJPEG) ?
-				   V4L2_PIX_FMT_MJPEG : V4L2_PIX_FMT_MPEG;
+	fmt->fmt.pix.pixelformat = go->format;
 	fmt->fmt.pix.field = V4L2_FIELD_NONE;
 	fmt->fmt.pix.bytesperline = 0;
 	fmt->fmt.pix.sizeimage = GO7007_BUF_SIZE;
@@ -663,7 +418,7 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
 static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
 			struct v4l2_format *fmt)
 {
-	struct go7007 *go = ((struct go7007_file *) priv)->go;
+	struct go7007 *go = video_drvdata(file);
 
 	return set_capture_size(go, fmt, 1);
 }
@@ -671,348 +426,137 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
 static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
 			struct v4l2_format *fmt)
 {
-	struct go7007 *go = ((struct go7007_file *) priv)->go;
+	struct go7007 *go = video_drvdata(file);
 
-	if (go->streaming)
+	if (vb2_is_busy(&go->vidq))
 		return -EBUSY;
 
 	return set_capture_size(go, fmt, 0);
 }
 
-static int vidioc_reqbufs(struct file *file, void *priv,
-			  struct v4l2_requestbuffers *req)
+static int go7007_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+		unsigned int *num_buffers, unsigned int *num_planes,
+		unsigned int sizes[], void *alloc_ctxs[])
 {
-	struct go7007_file *gofh = priv;
-	struct go7007 *go = gofh->go;
-	int retval = -EBUSY;
-	unsigned int count, i;
-
-	if (go->streaming)
-		return retval;
-
-	if (req->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
-			req->memory != V4L2_MEMORY_MMAP)
-		return -EINVAL;
-
-	mutex_lock(&gofh->lock);
-	for (i = 0; i < gofh->buf_count; ++i)
-		if (gofh->bufs[i].mapped > 0)
-			goto unlock_and_return;
-
-	mutex_lock(&go->hw_lock);
-	if (go->in_use > 0 && gofh->buf_count == 0) {
-		mutex_unlock(&go->hw_lock);
-		goto unlock_and_return;
-	}
+	sizes[0] = GO7007_BUF_SIZE;
+	*num_planes = 1;
 
-	if (gofh->buf_count > 0)
-		kfree(gofh->bufs);
-
-	retval = -ENOMEM;
-	count = req->count;
-	if (count > 0) {
-		if (count < 2)
-			count = 2;
-		if (count > 32)
-			count = 32;
-
-		gofh->bufs = kcalloc(count, sizeof(struct go7007_buffer),
-				     GFP_KERNEL);
-
-		if (!gofh->bufs) {
-			mutex_unlock(&go->hw_lock);
-			goto unlock_and_return;
-		}
-
-		for (i = 0; i < count; ++i) {
-			gofh->bufs[i].go = go;
-			gofh->bufs[i].index = i;
-			gofh->bufs[i].state = BUF_STATE_IDLE;
-			gofh->bufs[i].mapped = 0;
-		}
-
-		go->in_use = 1;
-	} else {
-		go->in_use = 0;
-	}
-
-	gofh->buf_count = count;
-	mutex_unlock(&go->hw_lock);
-	mutex_unlock(&gofh->lock);
-
-	memset(req, 0, sizeof(*req));
-
-	req->count = count;
-	req->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	req->memory = V4L2_MEMORY_MMAP;
-
-	return 0;
-
-unlock_and_return:
-	mutex_unlock(&gofh->lock);
-	return retval;
-}
-
-static int vidioc_querybuf(struct file *file, void *priv,
-			   struct v4l2_buffer *buf)
-{
-	struct go7007_file *gofh = priv;
-	int retval = -EINVAL;
-	unsigned int index;
-
-	if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		return retval;
-
-	index = buf->index;
-
-	mutex_lock(&gofh->lock);
-	if (index >= gofh->buf_count)
-		goto unlock_and_return;
-
-	memset(buf, 0, sizeof(*buf));
-	buf->index = index;
-	buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
-	switch (gofh->bufs[index].state) {
-	case BUF_STATE_QUEUED:
-		buf->flags = V4L2_BUF_FLAG_QUEUED;
-		break;
-	case BUF_STATE_DONE:
-		buf->flags = V4L2_BUF_FLAG_DONE;
-		break;
-	default:
-		buf->flags = 0;
-	}
-
-	if (gofh->bufs[index].mapped)
-		buf->flags |= V4L2_BUF_FLAG_MAPPED;
-	buf->memory = V4L2_MEMORY_MMAP;
-	buf->m.offset = index * GO7007_BUF_SIZE;
-	buf->length = GO7007_BUF_SIZE;
-	mutex_unlock(&gofh->lock);
+	if (*num_buffers < 2)
+		*num_buffers = 2;
 
 	return 0;
-
-unlock_and_return:
-	mutex_unlock(&gofh->lock);
-	return retval;
 }
 
-static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
+static void go7007_buf_queue(struct vb2_buffer *vb)
 {
-	struct go7007_file *gofh = priv;
-	struct go7007 *go = gofh->go;
-	struct go7007_buffer *gobuf;
+	struct vb2_queue *vq = vb->vb2_queue;
+	struct go7007 *go = vb2_get_drv_priv(vq);
+	struct go7007_buffer *go7007_vb =
+		container_of(vb, struct go7007_buffer, vb);
 	unsigned long flags;
-	int retval = -EINVAL;
-	int ret;
 
-	if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
-			buf->memory != V4L2_MEMORY_MMAP)
-		return retval;
-
-	mutex_lock(&gofh->lock);
-	if (buf->index >= gofh->buf_count)
-		goto unlock_and_return;
-
-	gobuf = &gofh->bufs[buf->index];
-	if (!gobuf->mapped)
-		goto unlock_and_return;
-
-	retval = -EBUSY;
-	if (gobuf->state != BUF_STATE_IDLE)
-		goto unlock_and_return;
-
-	/* offset will be 0 until we really support USERPTR streaming */
-	gobuf->offset = gobuf->user_addr & ~PAGE_MASK;
-	gobuf->bytesused = 0;
-	gobuf->frame_offset = 0;
-	gobuf->modet_active = 0;
-	if (gobuf->offset > 0)
-		gobuf->page_count = GO7007_BUF_PAGES + 1;
-	else
-		gobuf->page_count = GO7007_BUF_PAGES;
-
-	retval = -ENOMEM;
-	down_read(&current->mm->mmap_sem);
-	ret = get_user_pages(current, current->mm,
-			gobuf->user_addr & PAGE_MASK, gobuf->page_count,
-			1, 1, gobuf->pages, NULL);
-	up_read(&current->mm->mmap_sem);
-
-	if (ret != gobuf->page_count) {
-		int i;
-		for (i = 0; i < ret; ++i)
-			page_cache_release(gobuf->pages[i]);
-		gobuf->page_count = 0;
-		goto unlock_and_return;
-	}
-
-	gobuf->state = BUF_STATE_QUEUED;
 	spin_lock_irqsave(&go->spinlock, flags);
-	list_add_tail(&gobuf->stream, &go->stream);
+	list_add_tail(&go7007_vb->list, &go->vidq_active);
 	spin_unlock_irqrestore(&go->spinlock, flags);
-	mutex_unlock(&gofh->lock);
+}
 
-	return 0;
+static int go7007_buf_prepare(struct vb2_buffer *vb)
+{
+	struct go7007_buffer *go7007_vb =
+		container_of(vb, struct go7007_buffer, vb);
 
-unlock_and_return:
-	mutex_unlock(&gofh->lock);
-	return retval;
+	go7007_vb->modet_active = 0;
+	go7007_vb->frame_offset = 0;
+	vb->v4l2_planes[0].bytesused = 0;
+	return 0;
 }
 
-
-static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
+static int go7007_buf_finish(struct vb2_buffer *vb)
 {
-	struct go7007_file *gofh = priv;
-	struct go7007 *go = gofh->go;
-	struct go7007_buffer *gobuf;
-	int retval = -EINVAL;
-	unsigned long flags;
-	u32 frame_type_flag;
-	DEFINE_WAIT(wait);
-
-	if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		return retval;
-	if (buf->memory != V4L2_MEMORY_MMAP)
-		return retval;
-
-	mutex_lock(&gofh->lock);
-	if (list_empty(&go->stream))
-		goto unlock_and_return;
-	gobuf = list_entry(go->stream.next,
-			struct go7007_buffer, stream);
-
-	retval = -EAGAIN;
-	if (gobuf->state != BUF_STATE_DONE &&
-			!(file->f_flags & O_NONBLOCK)) {
-		for (;;) {
-			prepare_to_wait(&go->frame_waitq, &wait,
-					TASK_INTERRUPTIBLE);
-			if (gobuf->state == BUF_STATE_DONE)
-				break;
-			if (signal_pending(current)) {
-				retval = -ERESTARTSYS;
-				break;
-			}
-			schedule();
-		}
-		finish_wait(&go->frame_waitq, &wait);
-	}
-	if (gobuf->state != BUF_STATE_DONE)
-		goto unlock_and_return;
-
-	spin_lock_irqsave(&go->spinlock, flags);
-	deactivate_buffer(gobuf);
-	spin_unlock_irqrestore(&go->spinlock, flags);
-	frame_type_flag = get_frame_type_flag(gobuf, go->format);
-	gobuf->state = BUF_STATE_IDLE;
-
-	memset(buf, 0, sizeof(*buf));
-	buf->index = gobuf->index;
-	buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	buf->bytesused = gobuf->bytesused;
-	buf->flags = V4L2_BUF_FLAG_MAPPED | frame_type_flag;
+	struct vb2_queue *vq = vb->vb2_queue;
+	struct go7007 *go = vb2_get_drv_priv(vq);
+	struct go7007_buffer *go7007_vb =
+		container_of(vb, struct go7007_buffer, vb);
+	u32 frame_type_flag = get_frame_type_flag(go7007_vb, go->format);
+	struct v4l2_buffer *buf = &vb->v4l2_buf;
+
+	buf->flags &= ~(V4L2_BUF_FLAG_KEYFRAME | V4L2_BUF_FLAG_BFRAME |
+			V4L2_BUF_FLAG_PFRAME);
+	buf->flags |= frame_type_flag;
 	buf->field = V4L2_FIELD_NONE;
-	buf->timestamp = gobuf->timestamp;
-	buf->sequence = gobuf->seq;
-	buf->memory = V4L2_MEMORY_MMAP;
-	buf->m.offset = gobuf->index * GO7007_BUF_SIZE;
-	buf->length = GO7007_BUF_SIZE;
-	buf->reserved = gobuf->modet_active;
-
-	mutex_unlock(&gofh->lock);
 	return 0;
-
-unlock_and_return:
-	mutex_unlock(&gofh->lock);
-	return retval;
 }
 
-static int vidioc_streamon(struct file *file, void *priv,
-					enum v4l2_buf_type type)
+static int go7007_start_streaming(struct vb2_queue *q, unsigned int count)
 {
-	struct go7007_file *gofh = priv;
-	struct go7007 *go = gofh->go;
-	int retval = 0;
-
-	if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		return -EINVAL;
+	struct go7007 *go = vb2_get_drv_priv(q);
+	int ret;
 
-	mutex_lock(&gofh->lock);
+	set_formatting(go);
 	mutex_lock(&go->hw_lock);
-
-	if (!go->streaming) {
-		go->streaming = 1;
-		go->next_seq = 0;
-		go->active_buf = NULL;
-		if (go7007_start_encoder(go) < 0)
-			retval = -EIO;
-		else
-			retval = 0;
-	}
+	go->next_seq = 0;
+	go->active_buf = NULL;
+	q->streaming = 1;
+	if (go7007_start_encoder(go) < 0)
+		ret = -EIO;
+	else
+		ret = 0;
 	mutex_unlock(&go->hw_lock);
-	mutex_unlock(&gofh->lock);
+	if (ret) {
+		q->streaming = 0;
+		return ret;
+	}
 	call_all(&go->v4l2_dev, video, s_stream, 1);
-
-	return retval;
+	v4l2_ctrl_grab(go->mpeg_video_gop_size, true);
+	v4l2_ctrl_grab(go->mpeg_video_gop_closure, true);
+	v4l2_ctrl_grab(go->mpeg_video_bitrate, true);
+	v4l2_ctrl_grab(go->mpeg_video_aspect_ratio, true);
+	/* Turn on Capture LED */
+	if (go->board_id == GO7007_BOARDID_ADS_USBAV_709)
+		go7007_write_addr(go, 0x3c82, 0x0005);
+	return ret;
 }
 
-static int vidioc_streamoff(struct file *file, void *priv,
-					enum v4l2_buf_type type)
+static int go7007_stop_streaming(struct vb2_queue *q)
 {
-	struct go7007_file *gofh = priv;
-	struct go7007 *go = gofh->go;
+	struct go7007 *go = vb2_get_drv_priv(q);
+	unsigned long flags;
 
-	if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		return -EINVAL;
-	mutex_lock(&gofh->lock);
-	go7007_streamoff(go);
-	mutex_unlock(&gofh->lock);
+	q->streaming = 0;
+	go7007_stream_stop(go);
+	mutex_lock(&go->hw_lock);
+	go7007_reset_encoder(go);
+	mutex_unlock(&go->hw_lock);
 	call_all(&go->v4l2_dev, video, s_stream, 0);
 
+	spin_lock_irqsave(&go->spinlock, flags);
+	INIT_LIST_HEAD(&go->vidq_active);
+	spin_unlock_irqrestore(&go->spinlock, flags);
+	v4l2_ctrl_grab(go->mpeg_video_gop_size, false);
+	v4l2_ctrl_grab(go->mpeg_video_gop_closure, false);
+	v4l2_ctrl_grab(go->mpeg_video_bitrate, false);
+	v4l2_ctrl_grab(go->mpeg_video_aspect_ratio, false);
+	/* Turn on Capture LED */
+	if (go->board_id == GO7007_BOARDID_ADS_USBAV_709)
+		go7007_write_addr(go, 0x3c82, 0x000d);
 	return 0;
 }
 
-static int vidioc_queryctrl(struct file *file, void *priv,
-			   struct v4l2_queryctrl *query)
-{
-	struct go7007 *go = ((struct go7007_file *) priv)->go;
-	int id = query->id;
-
-	if (0 == call_all(&go->v4l2_dev, core, queryctrl, query))
-		return 0;
-
-	query->id = id;
-	return mpeg_query_ctrl(query);
-}
-
-static int vidioc_g_ctrl(struct file *file, void *priv,
-				struct v4l2_control *ctrl)
-{
-	struct go7007 *go = ((struct go7007_file *) priv)->go;
-
-	if (0 == call_all(&go->v4l2_dev, core, g_ctrl, ctrl))
-		return 0;
-
-	return mpeg_g_ctrl(ctrl, go);
-}
-
-static int vidioc_s_ctrl(struct file *file, void *priv,
-				struct v4l2_control *ctrl)
-{
-	struct go7007 *go = ((struct go7007_file *) priv)->go;
-
-	if (0 == call_all(&go->v4l2_dev, core, s_ctrl, ctrl))
-		return 0;
-
-	return mpeg_s_ctrl(ctrl, go);
-}
+static struct vb2_ops go7007_video_qops = {
+	.queue_setup    = go7007_queue_setup,
+	.buf_queue      = go7007_buf_queue,
+	.buf_prepare    = go7007_buf_prepare,
+	.buf_finish     = go7007_buf_finish,
+	.start_streaming = go7007_start_streaming,
+	.stop_streaming = go7007_stop_streaming,
+	.wait_prepare   = vb2_ops_wait_prepare,
+	.wait_finish    = vb2_ops_wait_finish,
+};
 
 static int vidioc_g_parm(struct file *filp, void *priv,
 		struct v4l2_streamparm *parm)
 {
-	struct go7007 *go = ((struct go7007_file *) priv)->go;
+	struct go7007 *go = video_drvdata(filp);
 	struct v4l2_fract timeperframe = {
 		.numerator = 1001 *  go->fps_scale,
 		.denominator = go->sensor_framerate,
@@ -1021,7 +565,8 @@ static int vidioc_g_parm(struct file *filp, void *priv,
 	if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
 		return -EINVAL;
 
-	parm->parm.capture.capability |= V4L2_CAP_TIMEPERFRAME;
+	parm->parm.capture.readbuffers = 2;
+	parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
 	parm->parm.capture.timeperframe = timeperframe;
 
 	return 0;
@@ -1030,13 +575,11 @@ static int vidioc_g_parm(struct file *filp, void *priv,
 static int vidioc_s_parm(struct file *filp, void *priv,
 		struct v4l2_streamparm *parm)
 {
-	struct go7007 *go = ((struct go7007_file *) priv)->go;
+	struct go7007 *go = video_drvdata(filp);
 	unsigned int n, d;
 
 	if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
 		return -EINVAL;
-	if (parm->parm.capture.capturemode != 0)
-		return -EINVAL;
 
 	n = go->sensor_framerate *
 		parm->parm.capture.timeperframe.numerator;
@@ -1046,7 +589,7 @@ static int vidioc_s_parm(struct file *filp, void *priv,
 	else
 		go->fps_scale = 1;
 
-	return 0;
+	return vidioc_g_parm(filp, priv, parm);
 }
 
 /* VIDIOC_ENUMSTD on go7007 were used for enumerating the supported fps and
@@ -1062,121 +605,96 @@ static int vidioc_s_parm(struct file *filp, void *priv,
 static int vidioc_enum_framesizes(struct file *filp, void *priv,
 				  struct v4l2_frmsizeenum *fsize)
 {
-	struct go7007 *go = ((struct go7007_file *) priv)->go;
+	struct go7007 *go = video_drvdata(filp);
+	int width, height;
 
-	/* Return -EINVAL, if it is a TV board */
-	if ((go->board_info->flags & GO7007_BOARD_HAS_TUNER) ||
-	    (go->board_info->sensor_flags & GO7007_SENSOR_TV))
+	if (fsize->index > 2)
 		return -EINVAL;
 
-	if (fsize->index > 0)
+	if (!valid_pixelformat(fsize->pixel_format))
 		return -EINVAL;
 
+	get_resolution(go, &width, &height);
 	fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
-	fsize->discrete.width = go->board_info->sensor_width;
-	fsize->discrete.height = go->board_info->sensor_height;
-
+	fsize->discrete.width = (width >> fsize->index) & ~0xf;
+	fsize->discrete.height = (height >> fsize->index) & ~0xf;
 	return 0;
 }
 
 static int vidioc_enum_frameintervals(struct file *filp, void *priv,
 				      struct v4l2_frmivalenum *fival)
 {
-	struct go7007 *go = ((struct go7007_file *) priv)->go;
+	struct go7007 *go = video_drvdata(filp);
+	int width, height;
+	int i;
 
-	/* Return -EINVAL, if it is a TV board */
-	if ((go->board_info->flags & GO7007_BOARD_HAS_TUNER) ||
-	    (go->board_info->sensor_flags & GO7007_SENSOR_TV))
+	if (fival->index > 4)
 		return -EINVAL;
 
-	if (fival->index > 0)
+	if (!valid_pixelformat(fival->pixel_format))
 		return -EINVAL;
 
+	if (!(go->board_info->sensor_flags & GO7007_SENSOR_SCALING)) {
+		get_resolution(go, &width, &height);
+		for (i = 0; i <= 2; i++)
+			if (fival->width == ((width >> i) & ~0xf) &&
+			    fival->height == ((height >> i) & ~0xf))
+				break;
+		if (i > 2)
+			return -EINVAL;
+	}
 	fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
-	fival->discrete.numerator = 1001;
-	fival->discrete.denominator = go->board_info->sensor_framerate;
-
+	fival->discrete.numerator = 1001 * (fival->index + 1);
+	fival->discrete.denominator = go->sensor_framerate;
 	return 0;
 }
 
 static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *std)
 {
-	struct go7007 *go = ((struct go7007_file *) priv)->go;
+	struct go7007 *go = video_drvdata(file);
 
-	switch (go->standard) {
-	case GO7007_STD_NTSC:
-		*std = V4L2_STD_NTSC;
-		break;
-	case GO7007_STD_PAL:
-		*std = V4L2_STD_PAL;
-		break;
-	default:
-		return -EINVAL;
+	*std = go->std;
+	return 0;
+}
+
+static int go7007_s_std(struct go7007 *go)
+{
+	if (go->std & V4L2_STD_625_50) {
+		go->standard = GO7007_STD_PAL;
+		go->sensor_framerate = 25025;
+	} else {
+		go->standard = GO7007_STD_NTSC;
+		go->sensor_framerate = 30000;
 	}
 
+	call_all(&go->v4l2_dev, core, s_std, go->std);
+	set_capture_size(go, NULL, 0);
 	return 0;
 }
 
-static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *std)
+static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id std)
 {
-	struct go7007 *go = ((struct go7007_file *) priv)->go;
+	struct go7007 *go = video_drvdata(file);
 
-	if (go->streaming)
+	if (vb2_is_busy(&go->vidq))
 		return -EBUSY;
 
-	if (!(go->board_info->sensor_flags & GO7007_SENSOR_TV) && *std != 0)
-		return -EINVAL;
-
-	if (*std == 0)
-		return -EINVAL;
-
-	if ((go->board_info->flags & GO7007_BOARD_HAS_TUNER) &&
-			go->input == go->board_info->num_inputs - 1) {
-		if (!go->i2c_adapter_online)
-			return -EIO;
-		if (call_all(&go->v4l2_dev, core, s_std, *std) < 0)
-			return -EINVAL;
-	}
-
-	if (*std & V4L2_STD_NTSC) {
-		go->standard = GO7007_STD_NTSC;
-		go->sensor_framerate = 30000;
-	} else if (*std & V4L2_STD_PAL) {
-		go->standard = GO7007_STD_PAL;
-		go->sensor_framerate = 25025;
-	} else if (*std & V4L2_STD_SECAM) {
-		go->standard = GO7007_STD_PAL;
-		go->sensor_framerate = 25025;
-	} else
-		return -EINVAL;
-
-	call_all(&go->v4l2_dev, core, s_std, *std);
-	set_capture_size(go, NULL, 0);
+	go->std = std;
 
-	return 0;
+	return go7007_s_std(go);
 }
 
 static int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *std)
 {
-	struct go7007 *go = ((struct go7007_file *) priv)->go;
-
-	if ((go->board_info->flags & GO7007_BOARD_HAS_TUNER) &&
-			go->input == go->board_info->num_inputs - 1) {
-		if (!go->i2c_adapter_online)
-			return -EIO;
-		return call_all(&go->v4l2_dev, video, querystd, std);
-	} else if (go->board_info->sensor_flags & GO7007_SENSOR_TV)
-		*std = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM;
-	else
-		*std = 0;
+	struct go7007 *go = video_drvdata(file);
 
-	return 0;
+	return call_all(&go->v4l2_dev, video, querystd, std);
 }
 
 static int vidioc_enum_input(struct file *file, void *priv,
 				struct v4l2_input *inp)
 {
-	struct go7007 *go = ((struct go7007_file *) priv)->go;
+	struct go7007 *go = video_drvdata(file);
 
 	if (inp->index >= go->board_info->num_inputs)
 		return -EINVAL;
@@ -1184,18 +702,20 @@ static int vidioc_enum_input(struct file *file, void *priv,
 	strncpy(inp->name, go->board_info->inputs[inp->index].name,
 			sizeof(inp->name));
 
-	/* If this board has a tuner, it will be the last input */
+	/* If this board has a tuner, it will be the first input */
 	if ((go->board_info->flags & GO7007_BOARD_HAS_TUNER) &&
-			inp->index == go->board_info->num_inputs - 1)
+			inp->index == 0)
 		inp->type = V4L2_INPUT_TYPE_TUNER;
 	else
 		inp->type = V4L2_INPUT_TYPE_CAMERA;
 
-	inp->audioset = 0;
+	if (go->board_info->num_aud_inputs)
+		inp->audioset = (1 << go->board_info->num_aud_inputs) - 1;
+	else
+		inp->audioset = 0;
 	inp->tuner = 0;
 	if (go->board_info->sensor_flags & GO7007_SENSOR_TV)
-		inp->std = V4L2_STD_NTSC | V4L2_STD_PAL |
-						V4L2_STD_SECAM;
+		inp->std = video_devdata(file)->tvnorms;
 	else
 		inp->std = 0;
 
@@ -1205,203 +725,128 @@ static int vidioc_enum_input(struct file *file, void *priv,
 
 static int vidioc_g_input(struct file *file, void *priv, unsigned int *input)
 {
-	struct go7007 *go = ((struct go7007_file *) priv)->go;
+	struct go7007 *go = video_drvdata(file);
 
 	*input = go->input;
 
 	return 0;
 }
 
-static int vidioc_s_input(struct file *file, void *priv, unsigned int input)
+static int vidioc_enumaudio(struct file *file, void *fh, struct v4l2_audio *a)
 {
-	struct go7007 *go = ((struct go7007_file *) priv)->go;
+	struct go7007 *go = video_drvdata(file);
 
-	if (input >= go->board_info->num_inputs)
+	if (a->index >= go->board_info->num_aud_inputs)
 		return -EINVAL;
-	if (go->streaming)
-		return -EBUSY;
+	strlcpy(a->name, go->board_info->aud_inputs[a->index].name, sizeof(a->name));
+	a->capability = V4L2_AUDCAP_STEREO;
+	return 0;
+}
 
-	go->input = input;
+static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a)
+{
+	struct go7007 *go = video_drvdata(file);
 
-	return call_all(&go->v4l2_dev, video, s_routing, input, 0, 0);
+	a->index = go->aud_input;
+	strlcpy(a->name, go->board_info->aud_inputs[go->aud_input].name, sizeof(a->name));
+	a->capability = V4L2_AUDCAP_STEREO;
+	return 0;
 }
 
-static int vidioc_g_tuner(struct file *file, void *priv,
-				struct v4l2_tuner *t)
+static int vidioc_s_audio(struct file *file, void *fh, const struct v4l2_audio *a)
 {
-	struct go7007 *go = ((struct go7007_file *) priv)->go;
+	struct go7007 *go = video_drvdata(file);
 
-	if (!(go->board_info->flags & GO7007_BOARD_HAS_TUNER))
-		return -EINVAL;
-	if (t->index != 0)
+	if (a->index >= go->board_info->num_aud_inputs)
 		return -EINVAL;
-	if (!go->i2c_adapter_online)
-		return -EIO;
-
-	return call_all(&go->v4l2_dev, tuner, g_tuner, t);
+	go->aud_input = a->index;
+	v4l2_subdev_call(go->sd_audio, audio, s_routing,
+			go->board_info->aud_inputs[go->aud_input].audio_input, 0, 0);
+	return 0;
 }
 
-static int vidioc_s_tuner(struct file *file, void *priv,
-				struct v4l2_tuner *t)
+static void go7007_s_input(struct go7007 *go)
 {
-	struct go7007 *go = ((struct go7007_file *) priv)->go;
+	unsigned int input = go->input;
 
-	if (!(go->board_info->flags & GO7007_BOARD_HAS_TUNER))
-		return -EINVAL;
-	if (t->index != 0)
-		return -EINVAL;
-	if (!go->i2c_adapter_online)
-		return -EIO;
-
-	switch (go->board_id) {
-	case GO7007_BOARDID_PX_TV402U_NA:
-	case GO7007_BOARDID_PX_TV402U_JP:
-		/* No selectable options currently */
-		if (t->audmode != V4L2_TUNER_MODE_STEREO)
-			return -EINVAL;
-		break;
-	}
+	v4l2_subdev_call(go->sd_video, video, s_routing,
+			go->board_info->inputs[input].video_input, 0,
+			go->board_info->video_config);
+	if (go->board_info->num_aud_inputs) {
+		int aud_input = go->board_info->inputs[input].audio_index;
 
-	return call_all(&go->v4l2_dev, tuner, s_tuner, t);
+		v4l2_subdev_call(go->sd_audio, audio, s_routing,
+			go->board_info->aud_inputs[aud_input].audio_input, 0, 0);
+		go->aud_input = aud_input;
+	}
 }
 
-static int vidioc_g_frequency(struct file *file, void *priv,
-				struct v4l2_frequency *f)
+static int vidioc_s_input(struct file *file, void *priv, unsigned int input)
 {
-	struct go7007 *go = ((struct go7007_file *) priv)->go;
+	struct go7007 *go = video_drvdata(file);
 
-	if (!(go->board_info->flags & GO7007_BOARD_HAS_TUNER))
+	if (input >= go->board_info->num_inputs)
 		return -EINVAL;
-	if (!go->i2c_adapter_online)
-		return -EIO;
+	if (vb2_is_busy(&go->vidq))
+		return -EBUSY;
 
-	f->type = V4L2_TUNER_ANALOG_TV;
+	go->input = input;
+	go7007_s_input(go);
 
-	return call_all(&go->v4l2_dev, tuner, g_frequency, f);
+	return 0;
 }
 
-static int vidioc_s_frequency(struct file *file, void *priv,
-				struct v4l2_frequency *f)
+static int vidioc_g_tuner(struct file *file, void *priv,
+				struct v4l2_tuner *t)
 {
-	struct go7007 *go = ((struct go7007_file *) priv)->go;
+	struct go7007 *go = video_drvdata(file);
 
-	if (!(go->board_info->flags & GO7007_BOARD_HAS_TUNER))
+	if (t->index != 0)
 		return -EINVAL;
-	if (!go->i2c_adapter_online)
-		return -EIO;
 
-	return call_all(&go->v4l2_dev, tuner, s_frequency, f);
+	strlcpy(t->name, "Tuner", sizeof(t->name));
+	return call_all(&go->v4l2_dev, tuner, g_tuner, t);
 }
 
-static int vidioc_cropcap(struct file *file, void *priv,
-					struct v4l2_cropcap *cropcap)
+static int vidioc_s_tuner(struct file *file, void *priv,
+				const struct v4l2_tuner *t)
 {
-	struct go7007 *go = ((struct go7007_file *) priv)->go;
+	struct go7007 *go = video_drvdata(file);
 
-	if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+	if (t->index != 0)
 		return -EINVAL;
 
-	/* These specify the raw input of the sensor */
-	switch (go->standard) {
-	case GO7007_STD_NTSC:
-		cropcap->bounds.top = 0;
-		cropcap->bounds.left = 0;
-		cropcap->bounds.width = 720;
-		cropcap->bounds.height = 480;
-		cropcap->defrect.top = 0;
-		cropcap->defrect.left = 0;
-		cropcap->defrect.width = 720;
-		cropcap->defrect.height = 480;
-		break;
-	case GO7007_STD_PAL:
-		cropcap->bounds.top = 0;
-		cropcap->bounds.left = 0;
-		cropcap->bounds.width = 720;
-		cropcap->bounds.height = 576;
-		cropcap->defrect.top = 0;
-		cropcap->defrect.left = 0;
-		cropcap->defrect.width = 720;
-		cropcap->defrect.height = 576;
-		break;
-	case GO7007_STD_OTHER:
-		cropcap->bounds.top = 0;
-		cropcap->bounds.left = 0;
-		cropcap->bounds.width = go->board_info->sensor_width;
-		cropcap->bounds.height = go->board_info->sensor_height;
-		cropcap->defrect.top = 0;
-		cropcap->defrect.left = 0;
-		cropcap->defrect.width = go->board_info->sensor_width;
-		cropcap->defrect.height = go->board_info->sensor_height;
-		break;
-	}
-
-	return 0;
+	return call_all(&go->v4l2_dev, tuner, s_tuner, t);
 }
 
-static int vidioc_g_crop(struct file *file, void *priv, struct v4l2_crop *crop)
+static int vidioc_g_frequency(struct file *file, void *priv,
+				struct v4l2_frequency *f)
 {
-	struct go7007 *go = ((struct go7007_file *) priv)->go;
+	struct go7007 *go = video_drvdata(file);
 
-	if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+	if (f->tuner)
 		return -EINVAL;
 
-	crop->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
-	/* These specify the raw input of the sensor */
-	switch (go->standard) {
-	case GO7007_STD_NTSC:
-		crop->c.top = 0;
-		crop->c.left = 0;
-		crop->c.width = 720;
-		crop->c.height = 480;
-		break;
-	case GO7007_STD_PAL:
-		crop->c.top = 0;
-		crop->c.left = 0;
-		crop->c.width = 720;
-		crop->c.height = 576;
-		break;
-	case GO7007_STD_OTHER:
-		crop->c.top = 0;
-		crop->c.left = 0;
-		crop->c.width = go->board_info->sensor_width;
-		crop->c.height = go->board_info->sensor_height;
-		break;
-	}
-
-	return 0;
+	return call_all(&go->v4l2_dev, tuner, g_frequency, f);
 }
 
-/* FIXME: vidioc_s_crop is not really implemented!!!
- */
-static int vidioc_s_crop(struct file *file, void *priv, const struct v4l2_crop *crop)
+static int vidioc_s_frequency(struct file *file, void *priv,
+				const struct v4l2_frequency *f)
 {
-	if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		return -EINVAL;
-
-	return 0;
-}
+	struct go7007 *go = video_drvdata(file);
 
-static int vidioc_g_jpegcomp(struct file *file, void *priv,
-			 struct v4l2_jpegcompression *params)
-{
-	memset(params, 0, sizeof(*params));
-	params->quality = 50; /* ?? */
-	params->jpeg_markers = V4L2_JPEG_MARKER_DHT |
-				V4L2_JPEG_MARKER_DQT;
+	if (f->tuner)
+		return -EINVAL;
 
-	return 0;
+	return call_all(&go->v4l2_dev, tuner, s_frequency, f);
 }
 
-static int vidioc_s_jpegcomp(struct file *file, void *priv,
-			 const struct v4l2_jpegcompression *params)
+static int vidioc_log_status(struct file *file, void *priv)
 {
-	if (params->quality != 50 ||
-			params->jpeg_markers != (V4L2_JPEG_MARKER_DHT |
-						V4L2_JPEG_MARKER_DQT))
-		return -EINVAL;
+	struct go7007 *go = video_drvdata(file);
 
-	return 0;
+	v4l2_ctrl_log_status(file, priv);
+	return call_all(&go->v4l2_dev, core, log_status);
 }
 
 /* FIXME:
@@ -1412,180 +857,6 @@ static int vidioc_s_jpegcomp(struct file *file, void *priv,
  */
 
 #if 0
-	/* Temporary ioctls for controlling compression characteristics */
-	case GO7007IOC_S_BITRATE:
-	{
-		int *bitrate = arg;
-
-		if (go->streaming)
-			return -EINVAL;
-		/* Upper bound is kind of arbitrary here */
-		if (*bitrate < 64000 || *bitrate > 10000000)
-			return -EINVAL;
-		go->bitrate = *bitrate;
-		return 0;
-	}
-	case GO7007IOC_G_BITRATE:
-	{
-		int *bitrate = arg;
-
-		*bitrate = go->bitrate;
-		return 0;
-	}
-	case GO7007IOC_S_COMP_PARAMS:
-	{
-		struct go7007_comp_params *comp = arg;
-
-		if (go->format == GO7007_FORMAT_MJPEG)
-			return -EINVAL;
-		if (comp->gop_size > 0)
-			go->gop_size = comp->gop_size;
-		else
-			go->gop_size = go->sensor_framerate / 1000;
-		if (go->gop_size != 15)
-			go->dvd_mode = 0;
-		/*go->ipb = comp->max_b_frames > 0;*/ /* completely untested */
-		if (go->board_info->sensor_flags & GO7007_SENSOR_TV) {
-			switch (comp->aspect_ratio) {
-			case GO7007_ASPECT_RATIO_4_3_NTSC:
-			case GO7007_ASPECT_RATIO_4_3_PAL:
-				go->aspect_ratio = GO7007_RATIO_4_3;
-				break;
-			case GO7007_ASPECT_RATIO_16_9_NTSC:
-			case GO7007_ASPECT_RATIO_16_9_PAL:
-				go->aspect_ratio = GO7007_RATIO_16_9;
-				break;
-			default:
-				go->aspect_ratio = GO7007_RATIO_1_1;
-				break;
-			}
-		}
-		if (comp->flags & GO7007_COMP_OMIT_SEQ_HEADER) {
-			go->dvd_mode = 0;
-			go->seq_header_enable = 0;
-		} else {
-			go->seq_header_enable = 1;
-		}
-		/* fall-through */
-	}
-	case GO7007IOC_G_COMP_PARAMS:
-	{
-		struct go7007_comp_params *comp = arg;
-
-		if (go->format == GO7007_FORMAT_MJPEG)
-			return -EINVAL;
-		memset(comp, 0, sizeof(*comp));
-		comp->gop_size = go->gop_size;
-		comp->max_b_frames = go->ipb ? 2 : 0;
-		switch (go->aspect_ratio) {
-		case GO7007_RATIO_4_3:
-			if (go->standard == GO7007_STD_NTSC)
-				comp->aspect_ratio =
-					GO7007_ASPECT_RATIO_4_3_NTSC;
-			else
-				comp->aspect_ratio =
-					GO7007_ASPECT_RATIO_4_3_PAL;
-			break;
-		case GO7007_RATIO_16_9:
-			if (go->standard == GO7007_STD_NTSC)
-				comp->aspect_ratio =
-					GO7007_ASPECT_RATIO_16_9_NTSC;
-			else
-				comp->aspect_ratio =
-					GO7007_ASPECT_RATIO_16_9_PAL;
-			break;
-		default:
-			comp->aspect_ratio = GO7007_ASPECT_RATIO_1_1;
-			break;
-		}
-		if (go->closed_gop)
-			comp->flags |= GO7007_COMP_CLOSED_GOP;
-		if (!go->seq_header_enable)
-			comp->flags |= GO7007_COMP_OMIT_SEQ_HEADER;
-		return 0;
-	}
-	case GO7007IOC_S_MPEG_PARAMS:
-	{
-		struct go7007_mpeg_params *mpeg = arg;
-
-		if (go->format != GO7007_FORMAT_MPEG1 &&
-				go->format != GO7007_FORMAT_MPEG2 &&
-				go->format != GO7007_FORMAT_MPEG4)
-			return -EINVAL;
-
-		if (mpeg->flags & GO7007_MPEG_FORCE_DVD_MODE) {
-			go->format = GO7007_FORMAT_MPEG2;
-			go->bitrate = 9800000;
-			go->gop_size = 15;
-			go->pali = 0x48;
-			go->closed_gop = 1;
-			go->repeat_seqhead = 0;
-			go->seq_header_enable = 1;
-			go->gop_header_enable = 1;
-			go->dvd_mode = 1;
-		} else {
-			switch (mpeg->mpeg_video_standard) {
-			case GO7007_MPEG_VIDEO_MPEG1:
-				go->format = GO7007_FORMAT_MPEG1;
-				go->pali = 0;
-				break;
-			case GO7007_MPEG_VIDEO_MPEG2:
-				go->format = GO7007_FORMAT_MPEG2;
-				if (mpeg->pali >> 24 == 2)
-					go->pali = mpeg->pali & 0xff;
-				else
-					go->pali = 0x48;
-				break;
-			case GO7007_MPEG_VIDEO_MPEG4:
-				go->format = GO7007_FORMAT_MPEG4;
-				if (mpeg->pali >> 24 == 4)
-					go->pali = mpeg->pali & 0xff;
-				else
-					go->pali = 0xf5;
-				break;
-			default:
-				return -EINVAL;
-			}
-			go->gop_header_enable =
-				mpeg->flags & GO7007_MPEG_OMIT_GOP_HEADER
-				? 0 : 1;
-			if (mpeg->flags & GO7007_MPEG_REPEAT_SEQHEADER)
-				go->repeat_seqhead = 1;
-			else
-				go->repeat_seqhead = 0;
-			go->dvd_mode = 0;
-		}
-		/* fall-through */
-	}
-	case GO7007IOC_G_MPEG_PARAMS:
-	{
-		struct go7007_mpeg_params *mpeg = arg;
-
-		memset(mpeg, 0, sizeof(*mpeg));
-		switch (go->format) {
-		case GO7007_FORMAT_MPEG1:
-			mpeg->mpeg_video_standard = GO7007_MPEG_VIDEO_MPEG1;
-			mpeg->pali = 0;
-			break;
-		case GO7007_FORMAT_MPEG2:
-			mpeg->mpeg_video_standard = GO7007_MPEG_VIDEO_MPEG2;
-			mpeg->pali = GO7007_MPEG_PROFILE(2, go->pali);
-			break;
-		case GO7007_FORMAT_MPEG4:
-			mpeg->mpeg_video_standard = GO7007_MPEG_VIDEO_MPEG4;
-			mpeg->pali = GO7007_MPEG_PROFILE(4, go->pali);
-			break;
-		default:
-			return -EINVAL;
-		}
-		if (!go->gop_header_enable)
-			mpeg->flags |= GO7007_MPEG_OMIT_GOP_HEADER;
-		if (go->repeat_seqhead)
-			mpeg->flags |= GO7007_MPEG_REPEAT_SEQHEADER;
-		if (go->dvd_mode)
-			mpeg->flags |= GO7007_MPEG_FORCE_DVD_MODE;
-		return 0;
-	}
 	case GO7007IOC_S_MD_PARAMS:
 	{
 		struct go7007_md_params *mdp = arg;
@@ -1604,25 +875,6 @@ static int vidioc_s_jpegcomp(struct file *file, void *priv,
 			go->modet[mdp->region].enable = 0;
 		/* fall-through */
 	}
-	case GO7007IOC_G_MD_PARAMS:
-	{
-		struct go7007_md_params *mdp = arg;
-		int region = mdp->region;
-
-		if (mdp->region > 3)
-			return -EINVAL;
-		memset(mdp, 0, sizeof(struct go7007_md_params));
-		mdp->region = region;
-		if (!go->modet[region].enable)
-			return 0;
-		mdp->pixel_threshold =
-			(go->modet[region].pixel_threshold << 1) + 1;
-		mdp->motion_threshold =
-			(go->modet[region].motion_threshold << 1) + 1;
-		mdp->trigger =
-			(go->modet[region].mb_threshold << 1) + 1;
-		return 0;
-	}
 	case GO7007IOC_S_MD_REGION:
 	{
 		struct go7007_md_region *region = arg;
@@ -1633,116 +885,14 @@ static int vidioc_s_jpegcomp(struct file *file, void *priv,
 	}
 #endif
 
-static ssize_t go7007_read(struct file *file, char __user *data,
-		size_t count, loff_t *ppos)
-{
-	return -EINVAL;
-}
-
-static void go7007_vm_open(struct vm_area_struct *vma)
-{
-	struct go7007_buffer *gobuf = vma->vm_private_data;
-
-	++gobuf->mapped;
-}
-
-static void go7007_vm_close(struct vm_area_struct *vma)
-{
-	struct go7007_buffer *gobuf = vma->vm_private_data;
-	unsigned long flags;
-
-	if (--gobuf->mapped == 0) {
-		spin_lock_irqsave(&gobuf->go->spinlock, flags);
-		deactivate_buffer(gobuf);
-		spin_unlock_irqrestore(&gobuf->go->spinlock, flags);
-	}
-}
-
-/* Copied from videobuf-dma-sg.c */
-static int go7007_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
-{
-	struct page *page;
-
-	page = alloc_page(GFP_USER | __GFP_DMA32);
-	if (!page)
-		return VM_FAULT_OOM;
-	clear_user_highpage(page, (unsigned long)vmf->virtual_address);
-	vmf->page = page;
-	return 0;
-}
-
-static struct vm_operations_struct go7007_vm_ops = {
-	.open	= go7007_vm_open,
-	.close	= go7007_vm_close,
-	.fault	= go7007_vm_fault,
-};
-
-static int go7007_mmap(struct file *file, struct vm_area_struct *vma)
-{
-	struct go7007_file *gofh = file->private_data;
-	unsigned int index;
-
-	if (gofh->go->status != STATUS_ONLINE)
-		return -EIO;
-	if (!(vma->vm_flags & VM_SHARED))
-		return -EINVAL; /* only support VM_SHARED mapping */
-	if (vma->vm_end - vma->vm_start != GO7007_BUF_SIZE)
-		return -EINVAL; /* must map exactly one full buffer */
-	mutex_lock(&gofh->lock);
-	index = vma->vm_pgoff / GO7007_BUF_PAGES;
-	if (index >= gofh->buf_count) {
-		mutex_unlock(&gofh->lock);
-		return -EINVAL; /* trying to map beyond requested buffers */
-	}
-	if (index * GO7007_BUF_PAGES != vma->vm_pgoff) {
-		mutex_unlock(&gofh->lock);
-		return -EINVAL; /* offset is not aligned on buffer boundary */
-	}
-	if (gofh->bufs[index].mapped > 0) {
-		mutex_unlock(&gofh->lock);
-		return -EBUSY;
-	}
-	gofh->bufs[index].mapped = 1;
-	gofh->bufs[index].user_addr = vma->vm_start;
-	vma->vm_ops = &go7007_vm_ops;
-	vma->vm_flags |= VM_DONTEXPAND;
-	vma->vm_flags &= ~VM_IO;
-	vma->vm_private_data = &gofh->bufs[index];
-	mutex_unlock(&gofh->lock);
-	return 0;
-}
-
-static unsigned int go7007_poll(struct file *file, poll_table *wait)
-{
-	struct go7007_file *gofh = file->private_data;
-	struct go7007_buffer *gobuf;
-
-	if (list_empty(&gofh->go->stream))
-		return POLLERR;
-	gobuf = list_entry(gofh->go->stream.next, struct go7007_buffer, stream);
-	poll_wait(file, &gofh->go->frame_waitq, wait);
-	if (gobuf->state == BUF_STATE_DONE)
-		return POLLIN | POLLRDNORM;
-	return 0;
-}
-
-static void go7007_vfl_release(struct video_device *vfd)
-{
-	struct go7007 *go = video_get_drvdata(vfd);
-
-	video_device_release(vfd);
-	if (--go->ref_count == 0)
-		kfree(go);
-}
-
 static struct v4l2_file_operations go7007_fops = {
 	.owner		= THIS_MODULE,
-	.open		= go7007_open,
-	.release	= go7007_release,
-	.ioctl		= video_ioctl2,
-	.read		= go7007_read,
-	.mmap		= go7007_mmap,
-	.poll		= go7007_poll,
+	.open		= v4l2_fh_open,
+	.release	= vb2_fop_release,
+	.unlocked_ioctl	= video_ioctl2,
+	.read		= vb2_fop_read,
+	.mmap		= vb2_fop_mmap,
+	.poll		= vb2_fop_poll,
 };
 
 static const struct v4l2_ioctl_ops video_ioctl_ops = {
@@ -1751,21 +901,21 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = {
 	.vidioc_g_fmt_vid_cap     = vidioc_g_fmt_vid_cap,
 	.vidioc_try_fmt_vid_cap   = vidioc_try_fmt_vid_cap,
 	.vidioc_s_fmt_vid_cap     = vidioc_s_fmt_vid_cap,
-	.vidioc_reqbufs           = vidioc_reqbufs,
-	.vidioc_querybuf          = vidioc_querybuf,
-	.vidioc_qbuf              = vidioc_qbuf,
-	.vidioc_dqbuf             = vidioc_dqbuf,
+	.vidioc_reqbufs           = vb2_ioctl_reqbufs,
+	.vidioc_querybuf          = vb2_ioctl_querybuf,
+	.vidioc_qbuf              = vb2_ioctl_qbuf,
+	.vidioc_dqbuf             = vb2_ioctl_dqbuf,
 	.vidioc_g_std             = vidioc_g_std,
 	.vidioc_s_std             = vidioc_s_std,
 	.vidioc_querystd          = vidioc_querystd,
 	.vidioc_enum_input        = vidioc_enum_input,
 	.vidioc_g_input           = vidioc_g_input,
 	.vidioc_s_input           = vidioc_s_input,
-	.vidioc_queryctrl         = vidioc_queryctrl,
-	.vidioc_g_ctrl            = vidioc_g_ctrl,
-	.vidioc_s_ctrl            = vidioc_s_ctrl,
-	.vidioc_streamon          = vidioc_streamon,
-	.vidioc_streamoff         = vidioc_streamoff,
+	.vidioc_enumaudio         = vidioc_enumaudio,
+	.vidioc_g_audio           = vidioc_g_audio,
+	.vidioc_s_audio           = vidioc_s_audio,
+	.vidioc_streamon          = vb2_ioctl_streamon,
+	.vidioc_streamoff         = vb2_ioctl_streamoff,
 	.vidioc_g_tuner           = vidioc_g_tuner,
 	.vidioc_s_tuner           = vidioc_s_tuner,
 	.vidioc_g_frequency       = vidioc_g_frequency,
@@ -1774,66 +924,129 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = {
 	.vidioc_s_parm            = vidioc_s_parm,
 	.vidioc_enum_framesizes   = vidioc_enum_framesizes,
 	.vidioc_enum_frameintervals = vidioc_enum_frameintervals,
-	.vidioc_cropcap           = vidioc_cropcap,
-	.vidioc_g_crop            = vidioc_g_crop,
-	.vidioc_s_crop            = vidioc_s_crop,
-	.vidioc_g_jpegcomp        = vidioc_g_jpegcomp,
-	.vidioc_s_jpegcomp        = vidioc_s_jpegcomp,
+	.vidioc_log_status        = vidioc_log_status,
+	.vidioc_subscribe_event   = v4l2_ctrl_subscribe_event,
+	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
 };
 
 static struct video_device go7007_template = {
 	.name		= "go7007",
 	.fops		= &go7007_fops,
-	.release	= go7007_vfl_release,
+	.release	= video_device_release_empty,
 	.ioctl_ops	= &video_ioctl_ops,
 	.tvnorms	= V4L2_STD_ALL,
-	.current_norm	= V4L2_STD_NTSC,
 };
 
+int go7007_v4l2_ctrl_init(struct go7007 *go)
+{
+	struct v4l2_ctrl_handler *hdl = &go->hdl;
+	struct v4l2_ctrl *ctrl;
+
+	v4l2_ctrl_handler_init(hdl, 13);
+	go->mpeg_video_gop_size = v4l2_ctrl_new_std(hdl, NULL,
+			V4L2_CID_MPEG_VIDEO_GOP_SIZE, 0, 34, 1, 15);
+	go->mpeg_video_gop_closure = v4l2_ctrl_new_std(hdl, NULL,
+			V4L2_CID_MPEG_VIDEO_GOP_CLOSURE, 0, 1, 1, 1);
+	go->mpeg_video_bitrate = v4l2_ctrl_new_std(hdl, NULL,
+			V4L2_CID_MPEG_VIDEO_BITRATE,
+			64000, 10000000, 1, 9800000);
+	go->mpeg_video_b_frames = v4l2_ctrl_new_std(hdl, NULL,
+			V4L2_CID_MPEG_VIDEO_B_FRAMES, 0, 2, 2, 0);
+	go->mpeg_video_rep_seqheader = v4l2_ctrl_new_std(hdl, NULL,
+			V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER, 0, 1, 1, 1);
+
+	go->mpeg_video_aspect_ratio = v4l2_ctrl_new_std_menu(hdl, NULL,
+			V4L2_CID_MPEG_VIDEO_ASPECT,
+			V4L2_MPEG_VIDEO_ASPECT_16x9, 0,
+			V4L2_MPEG_VIDEO_ASPECT_1x1);
+	ctrl = v4l2_ctrl_new_std(hdl, NULL,
+			V4L2_CID_JPEG_ACTIVE_MARKER, 0,
+			V4L2_JPEG_ACTIVE_MARKER_DQT | V4L2_JPEG_ACTIVE_MARKER_DHT, 0,
+			V4L2_JPEG_ACTIVE_MARKER_DQT | V4L2_JPEG_ACTIVE_MARKER_DHT);
+	if (ctrl)
+		ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+	if (hdl->error) {
+		int rv = hdl->error;
+
+		v4l2_err(&go->v4l2_dev, "Could not register controls\n");
+		return rv;
+	}
+	go->v4l2_dev.ctrl_handler = hdl;
+	return 0;
+}
+
 int go7007_v4l2_init(struct go7007 *go)
 {
+	struct video_device *vdev = &go->vdev;
 	int rv;
 
-	go->video_dev = video_device_alloc();
-	if (go->video_dev == NULL)
-		return -ENOMEM;
-	*go->video_dev = go7007_template;
-	go->video_dev->parent = go->dev;
-	rv = video_register_device(go->video_dev, VFL_TYPE_GRABBER, -1);
-	if (rv < 0) {
-		video_device_release(go->video_dev);
-		go->video_dev = NULL;
+	mutex_init(&go->serialize_lock);
+	mutex_init(&go->queue_lock);
+
+	INIT_LIST_HEAD(&go->vidq_active);
+	go->vidq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	go->vidq.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
+	go->vidq.ops = &go7007_video_qops;
+	go->vidq.mem_ops = &vb2_vmalloc_memops;
+	go->vidq.drv_priv = go;
+	go->vidq.buf_struct_size = sizeof(struct go7007_buffer);
+	go->vidq.timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+	go->vidq.lock = &go->queue_lock;
+	rv = vb2_queue_init(&go->vidq);
+	if (rv)
 		return rv;
+	*vdev = go7007_template;
+	vdev->lock = &go->serialize_lock;
+	vdev->queue = &go->vidq;
+	set_bit(V4L2_FL_USE_FH_PRIO, &vdev->flags);
+	video_set_drvdata(vdev, go);
+	vdev->v4l2_dev = &go->v4l2_dev;
+	if (!v4l2_device_has_op(&go->v4l2_dev, video, querystd))
+		v4l2_disable_ioctl(vdev, VIDIOC_QUERYSTD);
+	if (!(go->board_info->flags & GO7007_BOARD_HAS_TUNER)) {
+		v4l2_disable_ioctl(vdev, VIDIOC_S_FREQUENCY);
+		v4l2_disable_ioctl(vdev, VIDIOC_G_FREQUENCY);
+		v4l2_disable_ioctl(vdev, VIDIOC_S_TUNER);
+		v4l2_disable_ioctl(vdev, VIDIOC_G_TUNER);
+	} else {
+		struct v4l2_frequency f = {
+			.type = V4L2_TUNER_ANALOG_TV,
+			.frequency = 980,
+		};
+
+		call_all(&go->v4l2_dev, tuner, s_frequency, &f);
 	}
-	rv = v4l2_device_register(go->dev, &go->v4l2_dev);
-	if (rv < 0) {
-		video_device_release(go->video_dev);
-		go->video_dev = NULL;
-		return rv;
+	if (!(go->board_info->sensor_flags & GO7007_SENSOR_TV)) {
+		v4l2_disable_ioctl(vdev, VIDIOC_G_STD);
+		v4l2_disable_ioctl(vdev, VIDIOC_S_STD);
+		vdev->tvnorms = 0;
+	}
+	if (go->board_info->sensor_flags & GO7007_SENSOR_SCALING)
+		v4l2_disable_ioctl(vdev, VIDIOC_ENUM_FRAMESIZES);
+	if (go->board_info->num_aud_inputs == 0) {
+		v4l2_disable_ioctl(vdev, VIDIOC_G_AUDIO);
+		v4l2_disable_ioctl(vdev, VIDIOC_S_AUDIO);
+		v4l2_disable_ioctl(vdev, VIDIOC_ENUMAUDIO);
 	}
-	video_set_drvdata(go->video_dev, go);
-	++go->ref_count;
+	/* Setup correct crystal frequency on this board */
+	if (go->board_info->sensor_flags & GO7007_SENSOR_SAA7115)
+		v4l2_subdev_call(go->sd_video, video, s_crystal_freq,
+				SAA7115_FREQ_24_576_MHZ,
+				SAA7115_FREQ_FL_APLL | SAA7115_FREQ_FL_UCGC |
+				SAA7115_FREQ_FL_DOUBLE_ASCLK);
+	go7007_s_input(go);
+	if (go->board_info->sensor_flags & GO7007_SENSOR_TV)
+		go7007_s_std(go);
+	rv = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
+	if (rv < 0)
+		return rv;
 	dev_info(go->dev, "registered device %s [v4l2]\n",
-		 video_device_node_name(go->video_dev));
+		 video_device_node_name(vdev));
 
 	return 0;
 }
 
 void go7007_v4l2_remove(struct go7007 *go)
 {
-	unsigned long flags;
-
-	mutex_lock(&go->hw_lock);
-	if (go->streaming) {
-		go->streaming = 0;
-		go7007_stream_stop(go);
-		spin_lock_irqsave(&go->spinlock, flags);
-		abort_queued(go);
-		spin_unlock_irqrestore(&go->spinlock, flags);
-	}
-	mutex_unlock(&go->hw_lock);
-	if (go->video_dev)
-		video_unregister_device(go->video_dev);
-	if (go->status != STATUS_SHUTDOWN)
-		v4l2_device_unregister(&go->v4l2_dev);
+	v4l2_ctrl_handler_free(&go->hdl);
 }
diff --git a/drivers/staging/media/go7007/go7007.h b/drivers/staging/media/go7007/go7007.h
index 7399c91..54b9897 100644
--- a/drivers/staging/media/go7007/go7007.h
+++ b/drivers/staging/media/go7007/go7007.h
@@ -17,72 +17,6 @@
  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 
-/* DEPRECATED -- use V4L2_PIX_FMT_MPEG and then call GO7007IOC_S_MPEG_PARAMS
- * to select between MPEG1, MPEG2, and MPEG4 */
-#define V4L2_PIX_FMT_MPEG4     v4l2_fourcc('M', 'P', 'G', '4') /* MPEG4 */
-
-/* These will be replaced with a better interface
- * soon, so don't get too attached to them */
-#define	GO7007IOC_S_BITRATE	_IOW('V', BASE_VIDIOC_PRIVATE + 0, int)
-#define	GO7007IOC_G_BITRATE	_IOR('V', BASE_VIDIOC_PRIVATE + 1, int)
-
-enum go7007_aspect_ratio {
-	GO7007_ASPECT_RATIO_1_1 = 0,
-	GO7007_ASPECT_RATIO_4_3_NTSC = 1,
-	GO7007_ASPECT_RATIO_4_3_PAL = 2,
-	GO7007_ASPECT_RATIO_16_9_NTSC = 3,
-	GO7007_ASPECT_RATIO_16_9_PAL = 4,
-};
-
-/* Used to set generic compression parameters */
-struct go7007_comp_params {
-	__u32 gop_size;
-	__u32 max_b_frames;
-	enum go7007_aspect_ratio aspect_ratio;
-	__u32 flags;
-	__u32 reserved[8];
-};
-
-#define GO7007_COMP_CLOSED_GOP		0x00000001
-#define GO7007_COMP_OMIT_SEQ_HEADER	0x00000002
-
-enum go7007_mpeg_video_standard {
-	GO7007_MPEG_VIDEO_MPEG1 = 0,
-	GO7007_MPEG_VIDEO_MPEG2 = 1,
-	GO7007_MPEG_VIDEO_MPEG4 = 2,
-};
-
-/* Used to set parameters for V4L2_PIX_FMT_MPEG format */
-struct go7007_mpeg_params {
-	enum go7007_mpeg_video_standard mpeg_video_standard;
-	__u32 flags;
-	__u32 pali;
-	__u32 reserved[8];
-};
-
-#define GO7007_MPEG_FORCE_DVD_MODE	0x00000001
-#define GO7007_MPEG_OMIT_GOP_HEADER	0x00000002
-#define GO7007_MPEG_REPEAT_SEQHEADER	0x00000004
-
-#define GO7007_MPEG_PROFILE(format, pali)	(((format)<<24)|(pali))
-
-#define GO7007_MPEG2_PROFILE_MAIN_MAIN		GO7007_MPEG_PROFILE(2, 0x48)
-
-#define GO7007_MPEG4_PROFILE_S_L0		GO7007_MPEG_PROFILE(4, 0x08)
-#define GO7007_MPEG4_PROFILE_S_L1		GO7007_MPEG_PROFILE(4, 0x01)
-#define GO7007_MPEG4_PROFILE_S_L2		GO7007_MPEG_PROFILE(4, 0x02)
-#define GO7007_MPEG4_PROFILE_S_L3		GO7007_MPEG_PROFILE(4, 0x03)
-#define GO7007_MPEG4_PROFILE_ARTS_L1		GO7007_MPEG_PROFILE(4, 0x91)
-#define GO7007_MPEG4_PROFILE_ARTS_L2		GO7007_MPEG_PROFILE(4, 0x92)
-#define GO7007_MPEG4_PROFILE_ARTS_L3		GO7007_MPEG_PROFILE(4, 0x93)
-#define GO7007_MPEG4_PROFILE_ARTS_L4		GO7007_MPEG_PROFILE(4, 0x94)
-#define GO7007_MPEG4_PROFILE_AS_L0		GO7007_MPEG_PROFILE(4, 0xf0)
-#define GO7007_MPEG4_PROFILE_AS_L1		GO7007_MPEG_PROFILE(4, 0xf1)
-#define GO7007_MPEG4_PROFILE_AS_L2		GO7007_MPEG_PROFILE(4, 0xf2)
-#define GO7007_MPEG4_PROFILE_AS_L3		GO7007_MPEG_PROFILE(4, 0xf3)
-#define GO7007_MPEG4_PROFILE_AS_L4		GO7007_MPEG_PROFILE(4, 0xf4)
-#define GO7007_MPEG4_PROFILE_AS_L5		GO7007_MPEG_PROFILE(4, 0xf5)
-
 struct go7007_md_params {
 	__u16 region;
 	__u16 trigger;
@@ -98,14 +32,6 @@ struct go7007_md_region {
 	__u32 reserved[8];
 };
 
-#define	GO7007IOC_S_MPEG_PARAMS	_IOWR('V', BASE_VIDIOC_PRIVATE + 2, \
-					struct go7007_mpeg_params)
-#define	GO7007IOC_G_MPEG_PARAMS	_IOR('V', BASE_VIDIOC_PRIVATE + 3, \
-					struct go7007_mpeg_params)
-#define	GO7007IOC_S_COMP_PARAMS	_IOWR('V', BASE_VIDIOC_PRIVATE + 4, \
-					struct go7007_comp_params)
-#define	GO7007IOC_G_COMP_PARAMS	_IOR('V', BASE_VIDIOC_PRIVATE + 5, \
-					struct go7007_comp_params)
 #define	GO7007IOC_S_MD_PARAMS	_IOWR('V', BASE_VIDIOC_PRIVATE + 6, \
 					struct go7007_md_params)
 #define	GO7007IOC_G_MD_PARAMS	_IOR('V', BASE_VIDIOC_PRIVATE + 7, \
diff --git a/drivers/staging/media/go7007/s2250-board.c b/drivers/staging/media/go7007/s2250-board.c
index 37400bf..beaa98b 100644
--- a/drivers/staging/media/go7007/s2250-board.c
+++ b/drivers/staging/media/go7007/s2250-board.c
@@ -29,6 +29,13 @@
 MODULE_DESCRIPTION("Sensoray 2250/2251 i2c v4l2 subdev driver");
 MODULE_LICENSE("GPL v2");
 
+/*
+ * Note: this board has two i2c devices: a vpx3226f and a tlv320aic23b.
+ * Due to the unusual way these are accessed on this device we do not
+ * reuse the i2c drivers, but instead they are implemented in this
+ * driver. It would be nice to improve on this, though.
+ */
+
 #define TLV320_ADDRESS      0x34
 #define VPX322_ADDR_ANALOGCONTROL1	0x02
 #define VPX322_ADDR_BRIGHTNESS0		0x0127
@@ -116,6 +123,7 @@ static u16 vid_regs_fp_pal[] = {
 
 struct s2250 {
 	struct v4l2_subdev sd;
+	struct v4l2_ctrl_handler hdl;
 	v4l2_std_id std;
 	int input;
 	int brightness;
@@ -353,127 +361,48 @@ static int s2250_s_std(struct v4l2_subdev *sd, v4l2_std_id norm)
 	u16 vidsource;
 
 	vidsource = (state->input == 1) ? 0x040 : 0x020;
-	switch (norm) {
-	case V4L2_STD_NTSC:
-		write_regs_fp(client, vid_regs_fp);
-		write_reg_fp(client, 0x20, vidsource | 1);
-		break;
-	case V4L2_STD_PAL:
+	if (norm & V4L2_STD_625_50) {
 		write_regs_fp(client, vid_regs_fp);
 		write_regs_fp(client, vid_regs_fp_pal);
 		write_reg_fp(client, 0x20, vidsource);
-		break;
-	default:
-		return -EINVAL;
+	} else {
+		write_regs_fp(client, vid_regs_fp);
+		write_reg_fp(client, 0x20, vidsource | 1);
 	}
 	state->std = norm;
 	return 0;
 }
 
-static int s2250_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *query)
+static int s2250_s_ctrl(struct v4l2_ctrl *ctrl)
 {
-	switch (query->id) {
-	case V4L2_CID_BRIGHTNESS:
-		return v4l2_ctrl_query_fill(query, 0, 100, 1, 50);
-	case V4L2_CID_CONTRAST:
-		return v4l2_ctrl_query_fill(query, 0, 100, 1, 50);
-	case V4L2_CID_SATURATION:
-		return v4l2_ctrl_query_fill(query, 0, 100, 1, 50);
-	case V4L2_CID_HUE:
-		return v4l2_ctrl_query_fill(query, -50, 50, 1, 0);
-	default:
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static int s2250_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
-{
-	struct s2250 *state = to_state(sd);
-	struct i2c_client *client = v4l2_get_subdevdata(sd);
-	int value1;
+	struct s2250 *state = container_of(ctrl->handler, struct s2250, hdl);
+	struct i2c_client *client = v4l2_get_subdevdata(&state->sd);
 	u16 oldvalue;
 
 	switch (ctrl->id) {
 	case V4L2_CID_BRIGHTNESS:
-		if (ctrl->value > 100)
-			state->brightness = 100;
-		else if (ctrl->value < 0)
-			state->brightness = 0;
-		else
-			state->brightness = ctrl->value;
-		value1 = (state->brightness - 50) * 255 / 100;
 		read_reg_fp(client, VPX322_ADDR_BRIGHTNESS0, &oldvalue);
 		write_reg_fp(client, VPX322_ADDR_BRIGHTNESS0,
-			     value1 | (oldvalue & ~0xff));
+			     ctrl->val | (oldvalue & ~0xff));
 		read_reg_fp(client, VPX322_ADDR_BRIGHTNESS1, &oldvalue);
 		write_reg_fp(client, VPX322_ADDR_BRIGHTNESS1,
-			     value1 | (oldvalue & ~0xff));
+			     ctrl->val | (oldvalue & ~0xff));
 		write_reg_fp(client, 0x140, 0x60);
 		break;
 	case V4L2_CID_CONTRAST:
-		if (ctrl->value > 100)
-			state->contrast = 100;
-		else if (ctrl->value < 0)
-			state->contrast = 0;
-		else
-			state->contrast = ctrl->value;
-		value1 = state->contrast * 0x40 / 100;
-		if (value1 > 0x3f)
-			value1 = 0x3f; /* max */
 		read_reg_fp(client, VPX322_ADDR_CONTRAST0, &oldvalue);
 		write_reg_fp(client, VPX322_ADDR_CONTRAST0,
-			     value1 | (oldvalue & ~0x3f));
+			     ctrl->val | (oldvalue & ~0x3f));
 		read_reg_fp(client, VPX322_ADDR_CONTRAST1, &oldvalue);
 		write_reg_fp(client, VPX322_ADDR_CONTRAST1,
-			     value1 | (oldvalue & ~0x3f));
+			     ctrl->val | (oldvalue & ~0x3f));
 		write_reg_fp(client, 0x140, 0x60);
 		break;
 	case V4L2_CID_SATURATION:
-		if (ctrl->value > 100)
-			state->saturation = 100;
-		else if (ctrl->value < 0)
-			state->saturation = 0;
-		else
-			state->saturation = ctrl->value;
-		value1 = state->saturation * 4140 / 100;
-		if (value1 > 4094)
-			value1 = 4094;
-		write_reg_fp(client, VPX322_ADDR_SAT, value1);
-		break;
-	case V4L2_CID_HUE:
-		if (ctrl->value > 50)
-			state->hue = 50;
-		else if (ctrl->value < -50)
-			state->hue = -50;
-		else
-			state->hue = ctrl->value;
-		/* clamp the hue range */
-		value1 = state->hue * 280 / 50;
-		write_reg_fp(client, VPX322_ADDR_HUE, value1);
-		break;
-	default:
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static int s2250_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
-{
-	struct s2250 *state = to_state(sd);
-
-	switch (ctrl->id) {
-	case V4L2_CID_BRIGHTNESS:
-		ctrl->value = state->brightness;
-		break;
-	case V4L2_CID_CONTRAST:
-		ctrl->value = state->contrast;
-		break;
-	case V4L2_CID_SATURATION:
-		ctrl->value = state->saturation;
+		write_reg_fp(client, VPX322_ADDR_SAT, ctrl->val);
 		break;
 	case V4L2_CID_HUE:
-		ctrl->value = state->hue;
+		write_reg_fp(client, VPX322_ADDR_HUE, ctrl->val);
 		break;
 	default:
 		return -EINVAL;
@@ -531,24 +460,21 @@ static int s2250_log_status(struct v4l2_subdev *sd)
 	v4l2_info(sd, "Input: %s\n", state->input == 0 ? "Composite" :
 					state->input == 1 ? "S-video" :
 					"error");
-	v4l2_info(sd, "Brightness: %d\n", state->brightness);
-	v4l2_info(sd, "Contrast: %d\n", state->contrast);
-	v4l2_info(sd, "Saturation: %d\n", state->saturation);
-	v4l2_info(sd, "Hue: %d\n", state->hue);
 	v4l2_info(sd, "Audio input: %s\n", state->audio_input == 0 ? "Line In" :
 					state->audio_input == 1 ? "Mic" :
 					state->audio_input == 2 ? "Mic Boost" :
 					"error");
-	return 0;
+	return v4l2_ctrl_subdev_log_status(sd);
 }
 
 /* --------------------------------------------------------------------------*/
 
+static const struct v4l2_ctrl_ops s2250_ctrl_ops = {
+	.s_ctrl = s2250_s_ctrl,
+};
+
 static const struct v4l2_subdev_core_ops s2250_core_ops = {
 	.log_status = s2250_log_status,
-	.g_ctrl = s2250_g_ctrl,
-	.s_ctrl = s2250_s_ctrl,
-	.queryctrl = s2250_queryctrl,
 	.s_std = s2250_s_std,
 };
 
@@ -584,7 +510,7 @@ static int s2250_probe(struct i2c_client *client,
 	if (audio == NULL)
 		return -ENOMEM;
 
-	state = kmalloc(sizeof(struct s2250), GFP_KERNEL);
+	state = kzalloc(sizeof(struct s2250), GFP_KERNEL);
 	if (state == NULL) {
 		i2c_unregister_device(audio);
 		return -ENOMEM;
@@ -596,6 +522,24 @@ static int s2250_probe(struct i2c_client *client,
 	v4l2_info(sd, "initializing %s at address 0x%x on %s\n",
 	       "Sensoray 2250/2251", client->addr, client->adapter->name);
 
+	v4l2_ctrl_handler_init(&state->hdl, 4);
+	v4l2_ctrl_new_std(&state->hdl, &s2250_ctrl_ops,
+		V4L2_CID_BRIGHTNESS, -128, 127, 1, 0);
+	v4l2_ctrl_new_std(&state->hdl, &s2250_ctrl_ops,
+		V4L2_CID_CONTRAST, 0, 0x3f, 1, 0x32);
+	v4l2_ctrl_new_std(&state->hdl, &s2250_ctrl_ops,
+		V4L2_CID_SATURATION, 0, 4094, 1, 2070);
+	v4l2_ctrl_new_std(&state->hdl, &s2250_ctrl_ops,
+		V4L2_CID_HUE, -512, 511, 1, 0);
+	sd->ctrl_handler = &state->hdl;
+	if (state->hdl.error) {
+		int err = state->hdl.error;
+
+		v4l2_ctrl_handler_free(&state->hdl);
+		kfree(state);
+		return err;
+	}
+
 	state->std = V4L2_STD_NTSC;
 	state->brightness = 50;
 	state->contrast = 50;
@@ -606,22 +550,16 @@ static int s2250_probe(struct i2c_client *client,
 	/* initialize the audio */
 	if (write_regs(audio, aud_regs) < 0) {
 		dev_err(&client->dev, "error initializing audio\n");
-		i2c_unregister_device(audio);
-		kfree(state);
-		return 0;
+		goto fail;
 	}
 
 	if (write_regs(client, vid_regs) < 0) {
 		dev_err(&client->dev, "error initializing decoder\n");
-		i2c_unregister_device(audio);
-		kfree(state);
-		return 0;
+		goto fail;
 	}
 	if (write_regs_fp(client, vid_regs_fp) < 0) {
 		dev_err(&client->dev, "error initializing decoder\n");
-		i2c_unregister_device(audio);
-		kfree(state);
-		return 0;
+		goto fail;
 	}
 	/* set default channel */
 	/* composite */
@@ -657,14 +595,21 @@ static int s2250_probe(struct i2c_client *client,
 
 	v4l2_info(sd, "initialized successfully\n");
 	return 0;
+
+fail:
+	i2c_unregister_device(audio);
+	v4l2_ctrl_handler_free(&state->hdl);
+	kfree(state);
+	return -EIO;
 }
 
 static int s2250_remove(struct i2c_client *client)
 {
-	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct s2250 *state = to_state(i2c_get_clientdata(client));
 
-	v4l2_device_unregister_subdev(sd);
-	kfree(to_state(sd));
+	v4l2_device_unregister_subdev(&state->sd);
+	v4l2_ctrl_handler_free(&state->hdl);
+	kfree(state);
 	return 0;
 }
 
diff --git a/drivers/staging/media/go7007/s2250-loader.c b/drivers/staging/media/go7007/s2250-loader.c
deleted file mode 100644
index 72e5175..0000000
--- a/drivers/staging/media/go7007/s2250-loader.c
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Copyright (C) 2008 Sensoray Company 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., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/usb.h>
-#include <dvb-usb.h>
-
-#define S2250_LOADER_FIRMWARE	"s2250_loader.fw"
-#define S2250_FIRMWARE		"s2250.fw"
-
-typedef struct device_extension_s {
-    struct kref     kref;
-    int minor;
-    struct usb_device *usbdev;
-} device_extension_t, *pdevice_extension_t;
-
-#define USB_s2250loader_MAJOR 240
-#define USB_s2250loader_MINOR_BASE 0
-#define MAX_DEVICES 256
-
-static pdevice_extension_t s2250_dev_table[MAX_DEVICES];
-static DEFINE_MUTEX(s2250_dev_table_mutex);
-
-#define to_s2250loader_dev_common(d) container_of(d, device_extension_t, kref)
-static void s2250loader_delete(struct kref *kref)
-{
-	pdevice_extension_t s = to_s2250loader_dev_common(kref);
-	s2250_dev_table[s->minor] = NULL;
-	kfree(s);
-}
-
-static int s2250loader_probe(struct usb_interface *interface,
-				const struct usb_device_id *id)
-{
-	struct usb_device *usbdev;
-	int minor, ret;
-	pdevice_extension_t s = NULL;
-	const struct firmware *fw;
-
-	usbdev = usb_get_dev(interface_to_usbdev(interface));
-	if (!usbdev) {
-		dev_err(&interface->dev, "Enter s2250loader_probe failed\n");
-		return -1;
-	}
-	dev_info(&interface->dev, "Enter s2250loader_probe 2.6 kernel\n");
-	dev_info(&interface->dev, "vendor id 0x%x, device id 0x%x devnum:%d\n",
-		 usbdev->descriptor.idVendor, usbdev->descriptor.idProduct,
-		 usbdev->devnum);
-
-	if (usbdev->descriptor.bNumConfigurations != 1) {
-		dev_err(&interface->dev, "can't handle multiple config\n");
-		return -1;
-	}
-	mutex_lock(&s2250_dev_table_mutex);
-
-	for (minor = 0; minor < MAX_DEVICES; minor++) {
-		if (s2250_dev_table[minor] == NULL)
-			break;
-	}
-
-	if (minor < 0 || minor >= MAX_DEVICES) {
-		dev_err(&interface->dev, "Invalid minor: %d\n", minor);
-		goto failed;
-	}
-
-	/* Allocate dev data structure */
-	s = kmalloc(sizeof(device_extension_t), GFP_KERNEL);
-	if (s == NULL)
-		goto failed;
-
-	s2250_dev_table[minor] = s;
-
-	dev_info(&interface->dev,
-		 "s2250loader_probe: Device %d on Bus %d Minor %d\n",
-		 usbdev->devnum, usbdev->bus->busnum, minor);
-
-	memset(s, 0, sizeof(device_extension_t));
-	s->usbdev = usbdev;
-	dev_info(&interface->dev, "loading 2250 loader\n");
-
-	kref_init(&(s->kref));
-
-	mutex_unlock(&s2250_dev_table_mutex);
-
-	if (request_firmware(&fw, S2250_LOADER_FIRMWARE, &usbdev->dev)) {
-		dev_err(&interface->dev,
-			"s2250: unable to load firmware from file \"%s\"\n",
-			S2250_LOADER_FIRMWARE);
-		goto failed2;
-	}
-	ret = usb_cypress_load_firmware(usbdev, fw, CYPRESS_FX2);
-	release_firmware(fw);
-	if (0 != ret) {
-		dev_err(&interface->dev, "loader download failed\n");
-		goto failed2;
-	}
-
-	if (request_firmware(&fw, S2250_FIRMWARE, &usbdev->dev)) {
-		dev_err(&interface->dev,
-			"s2250: unable to load firmware from file \"%s\"\n",
-			S2250_FIRMWARE);
-		goto failed2;
-	}
-	ret = usb_cypress_load_firmware(usbdev, fw, CYPRESS_FX2);
-	release_firmware(fw);
-	if (0 != ret) {
-		dev_err(&interface->dev, "firmware_s2250 download failed\n");
-		goto failed2;
-	}
-
-	usb_set_intfdata(interface, s);
-	return 0;
-
-failed:
-	mutex_unlock(&s2250_dev_table_mutex);
-failed2:
-	if (s)
-		kref_put(&(s->kref), s2250loader_delete);
-
-	dev_err(&interface->dev, "probe failed\n");
-	return -1;
-}
-
-static void s2250loader_disconnect(struct usb_interface *interface)
-{
-	pdevice_extension_t s;
-	dev_info(&interface->dev, "s2250: disconnect\n");
-	s = usb_get_intfdata(interface);
-	usb_set_intfdata(interface, NULL);
-	kref_put(&(s->kref), s2250loader_delete);
-}
-
-static const struct usb_device_id s2250loader_ids[] = {
-	{USB_DEVICE(0x1943, 0xa250)},
-	{}                          /* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE(usb, s2250loader_ids);
-
-static struct usb_driver s2250loader_driver = {
-	.name		= "s2250-loader",
-	.probe		= s2250loader_probe,
-	.disconnect	= s2250loader_disconnect,
-	.id_table	= s2250loader_ids,
-};
-
-module_usb_driver(s2250loader_driver);
-
-MODULE_AUTHOR("");
-MODULE_DESCRIPTION("firmware loader for Sensoray 2250/2251");
-MODULE_LICENSE("GPL v2");
-MODULE_FIRMWARE(S2250_LOADER_FIRMWARE);
-MODULE_FIRMWARE(S2250_FIRMWARE);
diff --git a/drivers/staging/media/go7007/s2250-loader.h b/drivers/staging/media/go7007/s2250-loader.h
deleted file mode 100644
index b7c301a..0000000
--- a/drivers/staging/media/go7007/s2250-loader.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (C) 2005-2006 Micronas USA 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., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- */
-
-#ifndef _S2250_LOADER_H_
-#define _S2250_LOADER_H_
-
-extern int s2250loader_init(void);
-extern void s2250loader_cleanup(void);
-
-#endif
diff --git a/drivers/staging/media/go7007/saa7134-go7007.c b/drivers/staging/media/go7007/saa7134-go7007.c
index cf7c34a..d80b235 100644
--- a/drivers/staging/media/go7007/saa7134-go7007.c
+++ b/drivers/staging/media/go7007/saa7134-go7007.c
@@ -28,12 +28,15 @@
 #include <linux/i2c.h>
 #include <asm/byteorder.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
 
-#include "saa7134-reg.h"
 #include "saa7134.h"
+#include "saa7134-reg.h"
+#include "go7007.h"
 #include "go7007-priv.h"
 
-#define GO7007_HPI_DEBUG
+/*#define GO7007_HPI_DEBUG*/
 
 enum hpi_address {
 	HPI_ADDR_VIDEO_BUFFER = 0xe4,
@@ -57,6 +60,7 @@ enum gpio_command {
 };
 
 struct saa7134_go7007 {
+	struct v4l2_subdev sd;
 	struct saa7134_dev *dev;
 	u8 *top;
 	u8 *bottom;
@@ -64,8 +68,12 @@ struct saa7134_go7007 {
 	dma_addr_t bottom_dma;
 };
 
-static struct go7007_board_info board_voyager = {
-	.firmware	 = "go7007tv.bin",
+static inline struct saa7134_go7007 *to_state(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct saa7134_go7007, sd);
+}
+
+static const struct go7007_board_info board_voyager = {
 	.flags		 = 0,
 	.sensor_flags	 = GO7007_SENSOR_656 |
 				GO7007_SENSOR_VALID_ENABLE |
@@ -84,7 +92,6 @@ static struct go7007_board_info board_voyager = {
 		},
 	},
 };
-MODULE_FIRMWARE("go7007tv.bin");
 
 /********************* Driver for GPIO HPI interface *********************/
 
@@ -236,7 +243,7 @@ static void saa7134_go7007_irq_ts_done(struct saa7134_dev *dev,
 	struct go7007 *go = video_get_drvdata(dev->empress_dev);
 	struct saa7134_go7007 *saa = go->hpi_context;
 
-	if (!go->streaming)
+	if (!vb2_is_streaming(&go->vidq))
 		return;
 	if (0 != (status & 0x000f0000))
 		printk(KERN_DEBUG "saa7134-go7007: irq: lost %ld\n",
@@ -261,12 +268,12 @@ static int saa7134_go7007_stream_start(struct go7007 *go)
 
 	saa->top_dma = dma_map_page(&dev->pci->dev, virt_to_page(saa->top),
 			0, PAGE_SIZE, DMA_FROM_DEVICE);
-	if (!saa->top_dma)
+	if (dma_mapping_error(&dev->pci->dev, saa->top_dma))
 		return -ENOMEM;
 	saa->bottom_dma = dma_map_page(&dev->pci->dev,
 			virt_to_page(saa->bottom),
 			0, PAGE_SIZE, DMA_FROM_DEVICE);
-	if (!saa->bottom_dma) {
+	if (dma_mapping_error(&dev->pci->dev, saa->bottom_dma)) {
 		dma_unmap_page(&dev->pci->dev, saa->top_dma, PAGE_SIZE,
 				DMA_FROM_DEVICE);
 		return -ENOMEM;
@@ -380,47 +387,6 @@ static int saa7134_go7007_send_firmware(struct go7007 *go, u8 *data, int len)
 	return 0;
 }
 
-static int saa7134_go7007_send_command(struct go7007 *go, unsigned int cmd,
-					void *arg)
-{
-	struct saa7134_go7007 *saa = go->hpi_context;
-	struct saa7134_dev *dev = saa->dev;
-
-	switch (cmd) {
-	case VIDIOC_S_STD:
-	{
-		v4l2_std_id *std = arg;
-		return saa7134_s_std_internal(dev, NULL, std);
-	}
-	case VIDIOC_G_STD:
-	{
-		v4l2_std_id *std = arg;
-		*std = dev->tvnorm->id;
-		return 0;
-	}
-	case VIDIOC_QUERYCTRL:
-	{
-		struct v4l2_queryctrl *ctrl = arg;
-		if (V4L2_CTRL_ID2CLASS(ctrl->id) == V4L2_CTRL_CLASS_USER)
-			return saa7134_queryctrl(NULL, NULL, ctrl);
-	}
-	case VIDIOC_G_CTRL:
-	{
-		struct v4l2_control *ctrl = arg;
-		if (V4L2_CTRL_ID2CLASS(ctrl->id) == V4L2_CTRL_CLASS_USER)
-			return saa7134_g_ctrl_internal(dev, NULL, ctrl);
-	}
-	case VIDIOC_S_CTRL:
-	{
-		struct v4l2_control *ctrl = arg;
-		if (V4L2_CTRL_ID2CLASS(ctrl->id) == V4L2_CTRL_CLASS_USER)
-			return saa7134_s_ctrl_internal(dev, NULL, ctrl);
-	}
-	}
-	return -EINVAL;
-
-}
-
 static struct go7007_hpi_ops saa7134_go7007_hpi_ops = {
 	.interface_reset	= saa7134_go7007_interface_reset,
 	.write_interrupt	= saa7134_go7007_write_interrupt,
@@ -428,21 +394,88 @@ static struct go7007_hpi_ops saa7134_go7007_hpi_ops = {
 	.stream_start		= saa7134_go7007_stream_start,
 	.stream_stop		= saa7134_go7007_stream_stop,
 	.send_firmware		= saa7134_go7007_send_firmware,
-	.send_command		= saa7134_go7007_send_command,
+};
+MODULE_FIRMWARE("go7007/go7007tv.bin");
+
+/* --------------------------------------------------------------------------*/
+
+static int saa7134_go7007_s_std(struct v4l2_subdev *sd, v4l2_std_id norm)
+{
+	struct saa7134_go7007 *saa = to_state(sd);
+	struct saa7134_dev *dev = saa->dev;
+
+	return saa7134_s_std_internal(dev, NULL, norm);
+}
+
+static int saa7134_go7007_queryctrl(struct v4l2_subdev *sd,
+				    struct v4l2_queryctrl *query)
+{
+	return saa7134_queryctrl(NULL, NULL, query);
+}
+static int saa7134_go7007_s_ctrl(struct v4l2_subdev *sd,
+				 struct v4l2_control *ctrl)
+{
+	struct saa7134_go7007 *saa = to_state(sd);
+	struct saa7134_dev *dev = saa->dev;
+	return saa7134_s_ctrl_internal(dev, NULL, ctrl);
+}
+
+static int saa7134_go7007_g_ctrl(struct v4l2_subdev *sd,
+				 struct v4l2_control *ctrl)
+{
+	struct saa7134_go7007 *saa = to_state(sd);
+	struct saa7134_dev *dev = saa->dev;
+	return saa7134_g_ctrl_internal(dev, NULL, ctrl);
+}
+
+/* --------------------------------------------------------------------------*/
+
+static const struct v4l2_subdev_core_ops saa7134_go7007_core_ops = {
+	.g_ctrl = saa7134_go7007_g_ctrl,
+	.s_ctrl = saa7134_go7007_s_ctrl,
+	.queryctrl = saa7134_go7007_queryctrl,
+	.s_std = saa7134_go7007_s_std,
+};
+
+static const struct v4l2_subdev_ops saa7134_go7007_sd_ops = {
+	.core = &saa7134_go7007_core_ops,
 };
 
+/* --------------------------------------------------------------------------*/
+
+
 /********************* Add/remove functions *********************/
 
 static int saa7134_go7007_init(struct saa7134_dev *dev)
 {
 	struct go7007 *go;
 	struct saa7134_go7007 *saa;
+	struct v4l2_subdev *sd;
 
 	printk(KERN_DEBUG "saa7134-go7007: probing new SAA713X board\n");
 
+	go = go7007_alloc(&board_voyager, &dev->pci->dev);
+	if (go == NULL)
+		return -ENOMEM;
+
 	saa = kzalloc(sizeof(struct saa7134_go7007), GFP_KERNEL);
-	if (saa == NULL)
+	if (saa == NULL) {
+		kfree(go);
 		return -ENOMEM;
+	}
+
+	go->board_id = GO7007_BOARDID_PCI_VOYAGER;
+	snprintf(go->bus_info, sizeof(go->bus_info), "PCI:%s", pci_name(dev->pci));
+	strlcpy(go->name, saa7134_boards[dev->board].name, sizeof(go->name));
+	go->hpi_ops = &saa7134_go7007_hpi_ops;
+	go->hpi_context = saa;
+	saa->dev = dev;
+
+	/* Init the subdevice interface */
+	sd = &saa->sd;
+	v4l2_subdev_init(sd, &saa7134_go7007_sd_ops);
+	v4l2_set_subdevdata(sd, saa);
+	strncpy(sd->name, "saa7134-go7007", sizeof(sd->name));
 
 	/* Allocate a couple pages for receiving the compressed stream */
 	saa->top = (u8 *)get_zeroed_page(GFP_KERNEL);
@@ -452,32 +485,23 @@ static int saa7134_go7007_init(struct saa7134_dev *dev)
 	if (!saa->bottom)
 		goto allocfail;
 
-	go = go7007_alloc(&board_voyager, &dev->pci->dev);
-	if (go == NULL)
-		goto allocfail;
-	go->board_id = GO7007_BOARDID_PCI_VOYAGER;
-	strncpy(go->name, saa7134_boards[dev->board].name, sizeof(go->name));
-	go->hpi_ops = &saa7134_go7007_hpi_ops;
-	go->hpi_context = saa;
-	saa->dev = dev;
-
 	/* Boot the GO7007 */
 	if (go7007_boot_encoder(go, go->board_info->flags &
 					GO7007_BOARD_USE_ONBOARD_I2C) < 0)
-		goto initfail;
+		goto allocfail;
 
 	/* Do any final GO7007 initialization, then register the
 	 * V4L2 and ALSA interfaces */
-	if (go7007_register_encoder(go) < 0)
-		goto initfail;
-	dev->empress_dev = go->video_dev;
-	video_set_drvdata(dev->empress_dev, go);
+	if (go7007_register_encoder(go, go->board_info->num_i2c_devs) < 0)
+		goto allocfail;
 
-	go->status = STATUS_ONLINE;
-	return 0;
+	/* Register the subdevice interface with the go7007 device */
+	if (v4l2_device_register_subdev(&go->v4l2_dev, sd) < 0)
+		printk(KERN_INFO "saa7134-go7007: register subdev failed\n");
 
-initfail:
-	go->status = STATUS_SHUTDOWN;
+	dev->empress_dev = &go->vdev;
+
+	go->status = STATUS_ONLINE;
 	return 0;
 
 allocfail:
@@ -486,6 +510,7 @@ allocfail:
 	if (saa->bottom)
 		free_page((unsigned long)saa->bottom);
 	kfree(saa);
+	kfree(go);
 	return -ENOMEM;
 }
 
@@ -498,12 +523,18 @@ static int saa7134_go7007_fini(struct saa7134_dev *dev)
 		return 0;
 
 	go = video_get_drvdata(dev->empress_dev);
+	if (go->audio_enabled)
+		go7007_snd_remove(go);
+
 	saa = go->hpi_context;
 	go->status = STATUS_SHUTDOWN;
 	free_page((unsigned long)saa->top);
 	free_page((unsigned long)saa->bottom);
+	v4l2_device_unregister_subdev(&saa->sd);
 	kfree(saa);
-	go7007_remove(go);
+	video_unregister_device(&go->vdev);
+
+	v4l2_device_put(&go->v4l2_dev);
 	dev->empress_dev = NULL;
 
 	return 0;
diff --git a/drivers/staging/media/go7007/snd-go7007.c b/drivers/staging/media/go7007/snd-go7007.c
index 5af29ff..4be0fa4 100644
--- a/drivers/staging/media/go7007/snd-go7007.c
+++ b/drivers/staging/media/go7007/snd-go7007.c
@@ -221,8 +221,6 @@ static int go7007_snd_free(struct snd_device *device)
 
 	kfree(go->snd_context);
 	go->snd_context = NULL;
-	if (--go->ref_count == 0)
-		kfree(go);
 	return 0;
 }
 
@@ -267,9 +265,9 @@ int go7007_snd_init(struct go7007 *go)
 		kfree(gosnd);
 		return ret;
 	}
-	strncpy(gosnd->card->driver, "go7007", sizeof(gosnd->card->driver));
-	strncpy(gosnd->card->shortname, go->name, sizeof(gosnd->card->driver));
-	strncpy(gosnd->card->longname, gosnd->card->shortname,
+	strlcpy(gosnd->card->driver, "go7007", sizeof(gosnd->card->driver));
+	strlcpy(gosnd->card->shortname, go->name, sizeof(gosnd->card->driver));
+	strlcpy(gosnd->card->longname, gosnd->card->shortname,
 			sizeof(gosnd->card->longname));
 
 	gosnd->pcm->private_data = go;
@@ -285,8 +283,8 @@ int go7007_snd_init(struct go7007 *go)
 
 	gosnd->substream = NULL;
 	go->snd_context = gosnd;
+	v4l2_device_get(&go->v4l2_dev);
 	++dev;
-	++go->ref_count;
 
 	return 0;
 }
@@ -298,6 +296,7 @@ int go7007_snd_remove(struct go7007 *go)
 
 	snd_card_disconnect(gosnd->card);
 	snd_card_free_when_closed(gosnd->card);
+	v4l2_device_put(&go->v4l2_dev);
 	return 0;
 }
 EXPORT_SYMBOL(go7007_snd_remove);
diff --git a/drivers/staging/media/go7007/wis-i2c.h b/drivers/staging/media/go7007/wis-i2c.h
deleted file mode 100644
index 6d09c06..0000000
--- a/drivers/staging/media/go7007/wis-i2c.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2005-2006 Micronas USA 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., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- */
-
-/* Temporary I2C IDs -- these need to be replaced with real registered IDs */
-#define	I2C_DRIVERID_WIS_SAA7115	0xf0f0
-#define	I2C_DRIVERID_WIS_UDA1342	0xf0f1
-#define	I2C_DRIVERID_WIS_SONY_TUNER	0xf0f2
-#define	I2C_DRIVERID_WIS_TW9903		0xf0f3
-#define	I2C_DRIVERID_WIS_SAA7113	0xf0f4
-#define	I2C_DRIVERID_WIS_OV7640		0xf0f5
-#define	I2C_DRIVERID_WIS_TW2804		0xf0f6
-#define	I2C_DRIVERID_S2250		0xf0f7
-
-/* Definitions for new video decoder commands */
-
-struct video_decoder_resolution {
-	unsigned int width;
-	unsigned int height;
-};
-
-#define	DECODER_SET_RESOLUTION	_IOW('d', 200, struct video_decoder_resolution)
-#define	DECODER_SET_CHANNEL	_IOW('d', 201, int)
-
-/* Sony tuner types */
-
-#define TUNER_SONY_BTF_PG472Z		200
-#define TUNER_SONY_BTF_PK467Z		201
-#define TUNER_SONY_BTF_PB463Z		202
diff --git a/drivers/staging/media/go7007/wis-ov7640.c b/drivers/staging/media/go7007/wis-ov7640.c
deleted file mode 100644
index 9f01657..0000000
--- a/drivers/staging/media/go7007/wis-ov7640.c
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2005-2006 Micronas USA 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., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/i2c.h>
-#include <linux/videodev2.h>
-
-#include "wis-i2c.h"
-
-struct wis_ov7640 {
-	int brightness;
-	int contrast;
-	int saturation;
-	int hue;
-};
-
-static u8 initial_registers[] = {
-	0x12, 0x80,
-	0x12, 0x54,
-	0x14, 0x24,
-	0x15, 0x01,
-	0x28, 0x20,
-	0x75, 0x82,
-	0xFF, 0xFF, /* Terminator (reg 0xFF is unused) */
-};
-
-static int write_regs(struct i2c_client *client, u8 *regs)
-{
-	int i;
-
-	for (i = 0; regs[i] != 0xFF; i += 2)
-		if (i2c_smbus_write_byte_data(client, regs[i], regs[i + 1]) < 0)
-			return -1;
-	return 0;
-}
-
-static int wis_ov7640_probe(struct i2c_client *client,
-			    const struct i2c_device_id *id)
-{
-	struct i2c_adapter *adapter = client->adapter;
-
-	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
-		return -ENODEV;
-
-	client->flags = I2C_CLIENT_SCCB;
-
-	dev_dbg(&client->dev,
-		"wis-ov7640: initializing OV7640 at address %d on %s\n",
-		client->addr, adapter->name);
-
-	if (write_regs(client, initial_registers) < 0) {
-		dev_err(&client->dev, "wis-ov7640: error initializing OV7640\n");
-		return -ENODEV;
-	}
-
-	return 0;
-}
-
-static int wis_ov7640_remove(struct i2c_client *client)
-{
-	return 0;
-}
-
-static const struct i2c_device_id wis_ov7640_id[] = {
-	{ "wis_ov7640", 0 },
-	{ }
-};
-MODULE_DEVICE_TABLE(i2c, wis_ov7640_id);
-
-static struct i2c_driver wis_ov7640_driver = {
-	.driver = {
-		.name	= "WIS OV7640 I2C driver",
-	},
-	.probe		= wis_ov7640_probe,
-	.remove		= wis_ov7640_remove,
-	.id_table	= wis_ov7640_id,
-};
-
-module_i2c_driver(wis_ov7640_driver);
-
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/media/go7007/wis-saa7113.c b/drivers/staging/media/go7007/wis-saa7113.c
deleted file mode 100644
index 891cde7..0000000
--- a/drivers/staging/media/go7007/wis-saa7113.c
+++ /dev/null
@@ -1,324 +0,0 @@
-/*
- * Copyright (C) 2005-2006 Micronas USA 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., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/i2c.h>
-#include <linux/videodev2.h>
-#include <linux/ioctl.h>
-#include <linux/slab.h>
-
-#include "wis-i2c.h"
-
-struct wis_saa7113 {
-	int norm;
-	int brightness;
-	int contrast;
-	int saturation;
-	int hue;
-};
-
-static u8 initial_registers[] = {
-	0x01, 0x08,
-	0x02, 0xc0,
-	0x03, 0x33,
-	0x04, 0x00,
-	0x05, 0x00,
-	0x06, 0xe9,
-	0x07, 0x0d,
-	0x08, 0xd8,
-	0x09, 0x40,
-	0x0a, 0x80,
-	0x0b, 0x47,
-	0x0c, 0x40,
-	0x0d, 0x00,
-	0x0e, 0x01,
-	0x0f, 0x2a,
-	0x10, 0x40,
-	0x11, 0x0c,
-	0x12, 0xfe,
-	0x13, 0x00,
-	0x14, 0x00,
-	0x15, 0x04,
-	0x16, 0x00,
-	0x17, 0x00,
-	0x18, 0x00,
-	0x19, 0x00,
-	0x1a, 0x00,
-	0x1b, 0x00,
-	0x1c, 0x00,
-	0x1d, 0x00,
-	0x1e, 0x00,
-	0x1f, 0xc8,
-	0x40, 0x00,
-	0x41, 0xff,
-	0x42, 0xff,
-	0x43, 0xff,
-	0x44, 0xff,
-	0x45, 0xff,
-	0x46, 0xff,
-	0x47, 0xff,
-	0x48, 0xff,
-	0x49, 0xff,
-	0x4a, 0xff,
-	0x4b, 0xff,
-	0x4c, 0xff,
-	0x4d, 0xff,
-	0x4e, 0xff,
-	0x4f, 0xff,
-	0x50, 0xff,
-	0x51, 0xff,
-	0x52, 0xff,
-	0x53, 0xff,
-	0x54, 0xff,
-	0x55, 0xff,
-	0x56, 0xff,
-	0x57, 0xff,
-	0x58, 0x00,
-	0x59, 0x54,
-	0x5a, 0x07,
-	0x5b, 0x83,
-	0x5c, 0x00,
-	0x5d, 0x00,
-	0x5e, 0x00,
-	0x5f, 0x00,
-	0x60, 0x00,
-	0x61, 0x00,
-	0x00, 0x00, /* Terminator (reg 0x00 is read-only) */
-};
-
-static int write_reg(struct i2c_client *client, u8 reg, u8 value)
-{
-	return i2c_smbus_write_byte_data(client, reg, value);
-}
-
-static int write_regs(struct i2c_client *client, u8 *regs)
-{
-	int i;
-
-	for (i = 0; regs[i] != 0x00; i += 2)
-		if (i2c_smbus_write_byte_data(client, regs[i], regs[i + 1]) < 0)
-			return -1;
-	return 0;
-}
-
-static int wis_saa7113_command(struct i2c_client *client,
-				unsigned int cmd, void *arg)
-{
-	struct wis_saa7113 *dec = i2c_get_clientdata(client);
-
-	switch (cmd) {
-	case VIDIOC_S_INPUT:
-	{
-		int *input = arg;
-
-		i2c_smbus_write_byte_data(client, 0x02, 0xC0 | *input);
-		i2c_smbus_write_byte_data(client, 0x09,
-				*input < 6 ? 0x40 : 0x80);
-		break;
-	}
-	case VIDIOC_S_STD:
-	{
-		v4l2_std_id *input = arg;
-		dec->norm = *input;
-		if (dec->norm & V4L2_STD_NTSC) {
-			write_reg(client, 0x0e, 0x01);
-			write_reg(client, 0x10, 0x40);
-		} else if (dec->norm & V4L2_STD_PAL) {
-			write_reg(client, 0x0e, 0x01);
-			write_reg(client, 0x10, 0x48);
-		} else if (dec->norm & V4L2_STD_SECAM) {
-			write_reg(client, 0x0e, 0x50);
-			write_reg(client, 0x10, 0x48);
-		}
-		break;
-	}
-	case VIDIOC_QUERYCTRL:
-	{
-		struct v4l2_queryctrl *ctrl = arg;
-
-		switch (ctrl->id) {
-		case V4L2_CID_BRIGHTNESS:
-			ctrl->type = V4L2_CTRL_TYPE_INTEGER;
-			strncpy(ctrl->name, "Brightness", sizeof(ctrl->name));
-			ctrl->minimum = 0;
-			ctrl->maximum = 255;
-			ctrl->step = 1;
-			ctrl->default_value = 128;
-			ctrl->flags = 0;
-			break;
-		case V4L2_CID_CONTRAST:
-			ctrl->type = V4L2_CTRL_TYPE_INTEGER;
-			strncpy(ctrl->name, "Contrast", sizeof(ctrl->name));
-			ctrl->minimum = 0;
-			ctrl->maximum = 127;
-			ctrl->step = 1;
-			ctrl->default_value = 71;
-			ctrl->flags = 0;
-			break;
-		case V4L2_CID_SATURATION:
-			ctrl->type = V4L2_CTRL_TYPE_INTEGER;
-			strncpy(ctrl->name, "Saturation", sizeof(ctrl->name));
-			ctrl->minimum = 0;
-			ctrl->maximum = 127;
-			ctrl->step = 1;
-			ctrl->default_value = 64;
-			ctrl->flags = 0;
-			break;
-		case V4L2_CID_HUE:
-			ctrl->type = V4L2_CTRL_TYPE_INTEGER;
-			strncpy(ctrl->name, "Hue", sizeof(ctrl->name));
-			ctrl->minimum = -128;
-			ctrl->maximum = 127;
-			ctrl->step = 1;
-			ctrl->default_value = 0;
-			ctrl->flags = 0;
-			break;
-		}
-		break;
-	}
-	case VIDIOC_S_CTRL:
-	{
-		struct v4l2_control *ctrl = arg;
-
-		switch (ctrl->id) {
-		case V4L2_CID_BRIGHTNESS:
-			if (ctrl->value > 255)
-				dec->brightness = 255;
-			else if (ctrl->value < 0)
-				dec->brightness = 0;
-			else
-				dec->brightness = ctrl->value;
-			write_reg(client, 0x0a, dec->brightness);
-			break;
-		case V4L2_CID_CONTRAST:
-			if (ctrl->value > 127)
-				dec->contrast = 127;
-			else if (ctrl->value < 0)
-				dec->contrast = 0;
-			else
-				dec->contrast = ctrl->value;
-			write_reg(client, 0x0b, dec->contrast);
-			break;
-		case V4L2_CID_SATURATION:
-			if (ctrl->value > 127)
-				dec->saturation = 127;
-			else if (ctrl->value < 0)
-				dec->saturation = 0;
-			else
-				dec->saturation = ctrl->value;
-			write_reg(client, 0x0c, dec->saturation);
-			break;
-		case V4L2_CID_HUE:
-			if (ctrl->value > 127)
-				dec->hue = 127;
-			else if (ctrl->value < -128)
-				dec->hue = -128;
-			else
-				dec->hue = ctrl->value;
-			write_reg(client, 0x0d, dec->hue);
-			break;
-		}
-		break;
-	}
-	case VIDIOC_G_CTRL:
-	{
-		struct v4l2_control *ctrl = arg;
-
-		switch (ctrl->id) {
-		case V4L2_CID_BRIGHTNESS:
-			ctrl->value = dec->brightness;
-			break;
-		case V4L2_CID_CONTRAST:
-			ctrl->value = dec->contrast;
-			break;
-		case V4L2_CID_SATURATION:
-			ctrl->value = dec->saturation;
-			break;
-		case V4L2_CID_HUE:
-			ctrl->value = dec->hue;
-			break;
-		}
-		break;
-	}
-	default:
-		break;
-	}
-	return 0;
-}
-
-static int wis_saa7113_probe(struct i2c_client *client,
-			     const struct i2c_device_id *id)
-{
-	struct i2c_adapter *adapter = client->adapter;
-	struct wis_saa7113 *dec;
-
-	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
-		return -ENODEV;
-
-	dec = kmalloc(sizeof(struct wis_saa7113), GFP_KERNEL);
-	if (dec == NULL)
-		return -ENOMEM;
-
-	dec->norm = V4L2_STD_NTSC;
-	dec->brightness = 128;
-	dec->contrast = 71;
-	dec->saturation = 64;
-	dec->hue = 0;
-	i2c_set_clientdata(client, dec);
-
-	dev_dbg(&client->dev,
-		"wis-saa7113: initializing SAA7113 at address %d on %s\n",
-		client->addr, adapter->name);
-
-	if (write_regs(client, initial_registers) < 0) {
-		dev_err(&client->dev,
-			"wis-saa7113: error initializing SAA7113\n");
-		kfree(dec);
-		return -ENODEV;
-	}
-
-	return 0;
-}
-
-static int wis_saa7113_remove(struct i2c_client *client)
-{
-	struct wis_saa7113 *dec = i2c_get_clientdata(client);
-
-	kfree(dec);
-	return 0;
-}
-
-static const struct i2c_device_id wis_saa7113_id[] = {
-	{ "wis_saa7113", 0 },
-	{ }
-};
-MODULE_DEVICE_TABLE(i2c, wis_saa7113_id);
-
-static struct i2c_driver wis_saa7113_driver = {
-	.driver = {
-		.name	= "WIS SAA7113 I2C driver",
-	},
-	.probe		= wis_saa7113_probe,
-	.remove		= wis_saa7113_remove,
-	.command	= wis_saa7113_command,
-	.id_table	= wis_saa7113_id,
-};
-
-module_i2c_driver(wis_saa7113_driver);
-
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/media/go7007/wis-saa7115.c b/drivers/staging/media/go7007/wis-saa7115.c
deleted file mode 100644
index fa86acd..0000000
--- a/drivers/staging/media/go7007/wis-saa7115.c
+++ /dev/null
@@ -1,457 +0,0 @@
-/*
- * Copyright (C) 2005-2006 Micronas USA 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., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/i2c.h>
-#include <linux/videodev2.h>
-#include <linux/ioctl.h>
-#include <linux/slab.h>
-
-#include "wis-i2c.h"
-
-struct wis_saa7115 {
-	int norm;
-	int brightness;
-	int contrast;
-	int saturation;
-	int hue;
-};
-
-static u8 initial_registers[] = {
-	0x01, 0x08,
-	0x02, 0xc0,
-	0x03, 0x20,
-	0x04, 0x80,
-	0x05, 0x80,
-	0x06, 0xeb,
-	0x07, 0xe0,
-	0x08, 0xf0,	/* always toggle FID */
-	0x09, 0x40,
-	0x0a, 0x80,
-	0x0b, 0x40,
-	0x0c, 0x40,
-	0x0d, 0x00,
-	0x0e, 0x03,
-	0x0f, 0x2a,
-	0x10, 0x0e,
-	0x11, 0x00,
-	0x12, 0x8d,
-	0x13, 0x00,
-	0x14, 0x00,
-	0x15, 0x11,
-	0x16, 0x01,
-	0x17, 0xda,
-	0x18, 0x40,
-	0x19, 0x80,
-	0x1a, 0x00,
-	0x1b, 0x42,
-	0x1c, 0xa9,
-	0x30, 0x66,
-	0x31, 0x90,
-	0x32, 0x01,
-	0x34, 0x00,
-	0x35, 0x00,
-	0x36, 0x20,
-	0x38, 0x03,
-	0x39, 0x20,
-	0x3a, 0x88,
-	0x40, 0x00,
-	0x41, 0xff,
-	0x42, 0xff,
-	0x43, 0xff,
-	0x44, 0xff,
-	0x45, 0xff,
-	0x46, 0xff,
-	0x47, 0xff,
-	0x48, 0xff,
-	0x49, 0xff,
-	0x4a, 0xff,
-	0x4b, 0xff,
-	0x4c, 0xff,
-	0x4d, 0xff,
-	0x4e, 0xff,
-	0x4f, 0xff,
-	0x50, 0xff,
-	0x51, 0xff,
-	0x52, 0xff,
-	0x53, 0xff,
-	0x54, 0xf4 /*0xff*/,
-	0x55, 0xff,
-	0x56, 0xff,
-	0x57, 0xff,
-	0x58, 0x40,
-	0x59, 0x47,
-	0x5a, 0x06 /*0x03*/,
-	0x5b, 0x83,
-	0x5d, 0x06,
-	0x5e, 0x00,
-	0x80, 0x30, /* window defined scaler operation, task A and B enabled */
-	0x81, 0x03, /* use scaler datapath generated V */
-	0x83, 0x00,
-	0x84, 0x00,
-	0x85, 0x00,
-	0x86, 0x45,
-	0x87, 0x31,
-	0x88, 0xc0,
-	0x90, 0x02, /* task A process top field */
-	0x91, 0x08,
-	0x92, 0x09,
-	0x93, 0x80,
-	0x94, 0x06,
-	0x95, 0x00,
-	0x96, 0xc0,
-	0x97, 0x02,
-	0x98, 0x12,
-	0x99, 0x00,
-	0x9a, 0xf2,
-	0x9b, 0x00,
-	0x9c, 0xd0,
-	0x9d, 0x02,
-	0x9e, 0xf2,
-	0x9f, 0x00,
-	0xa0, 0x01,
-	0xa1, 0x01,
-	0xa2, 0x01,
-	0xa4, 0x80,
-	0xa5, 0x40,
-	0xa6, 0x40,
-	0xa8, 0x00,
-	0xa9, 0x04,
-	0xaa, 0x00,
-	0xac, 0x00,
-	0xad, 0x02,
-	0xae, 0x00,
-	0xb0, 0x00,
-	0xb1, 0x04,
-	0xb2, 0x00,
-	0xb3, 0x04,
-	0xb4, 0x00,
-	0xb8, 0x00,
-	0xbc, 0x00,
-	0xc0, 0x03,	/* task B process bottom field */
-	0xc1, 0x08,
-	0xc2, 0x09,
-	0xc3, 0x80,
-	0xc4, 0x06,
-	0xc5, 0x00,
-	0xc6, 0xc0,
-	0xc7, 0x02,
-	0xc8, 0x12,
-	0xc9, 0x00,
-	0xca, 0xf2,
-	0xcb, 0x00,
-	0xcc, 0xd0,
-	0xcd, 0x02,
-	0xce, 0xf2,
-	0xcf, 0x00,
-	0xd0, 0x01,
-	0xd1, 0x01,
-	0xd2, 0x01,
-	0xd4, 0x80,
-	0xd5, 0x40,
-	0xd6, 0x40,
-	0xd8, 0x00,
-	0xd9, 0x04,
-	0xda, 0x00,
-	0xdc, 0x00,
-	0xdd, 0x02,
-	0xde, 0x00,
-	0xe0, 0x00,
-	0xe1, 0x04,
-	0xe2, 0x00,
-	0xe3, 0x04,
-	0xe4, 0x00,
-	0xe8, 0x00,
-	0x88, 0xf0, /* End of original static list */
-	0x00, 0x00, /* Terminator (reg 0x00 is read-only) */
-};
-
-static int write_reg(struct i2c_client *client, u8 reg, u8 value)
-{
-	return i2c_smbus_write_byte_data(client, reg, value);
-}
-
-static int write_regs(struct i2c_client *client, u8 *regs)
-{
-	int i;
-
-	for (i = 0; regs[i] != 0x00; i += 2)
-		if (i2c_smbus_write_byte_data(client, regs[i], regs[i + 1]) < 0)
-			return -1;
-	return 0;
-}
-
-static int wis_saa7115_command(struct i2c_client *client,
-				unsigned int cmd, void *arg)
-{
-	struct wis_saa7115 *dec = i2c_get_clientdata(client);
-
-	switch (cmd) {
-	case VIDIOC_S_INPUT:
-	{
-		int *input = arg;
-
-		i2c_smbus_write_byte_data(client, 0x02, 0xC0 | *input);
-		i2c_smbus_write_byte_data(client, 0x09,
-				*input < 6 ? 0x40 : 0xC0);
-		break;
-	}
-	case DECODER_SET_RESOLUTION:
-	{
-		struct video_decoder_resolution *res = arg;
-		/* Course-grained scaler */
-		int h_integer_scaler = res->width < 704 ? 704 / res->width : 1;
-		/* Fine-grained scaler to take care of remainder */
-		int h_scaling_increment = (704 / h_integer_scaler) *
-					1024 / res->width;
-		/* Fine-grained scaler only */
-		int v_scaling_increment = (dec->norm & V4L2_STD_NTSC ?
-				240 : 288) * 1024 / res->height;
-		u8 regs[] = {
-			0x88,	0xc0,
-			0x9c,	res->width & 0xff,
-			0x9d,	res->width >> 8,
-			0x9e,	res->height & 0xff,
-			0x9f,	res->height >> 8,
-			0xa0,	h_integer_scaler,
-			0xa1,	1,
-			0xa2,	1,
-			0xa8,	h_scaling_increment & 0xff,
-			0xa9,	h_scaling_increment >> 8,
-			0xac,	(h_scaling_increment / 2) & 0xff,
-			0xad,	(h_scaling_increment / 2) >> 8,
-			0xb0,	v_scaling_increment & 0xff,
-			0xb1,	v_scaling_increment >> 8,
-			0xb2,	v_scaling_increment & 0xff,
-			0xb3,	v_scaling_increment >> 8,
-			0xcc,	res->width & 0xff,
-			0xcd,	res->width >> 8,
-			0xce,	res->height & 0xff,
-			0xcf,	res->height >> 8,
-			0xd0,	h_integer_scaler,
-			0xd1,	1,
-			0xd2,	1,
-			0xd8,	h_scaling_increment & 0xff,
-			0xd9,	h_scaling_increment >> 8,
-			0xdc,	(h_scaling_increment / 2) & 0xff,
-			0xdd,	(h_scaling_increment / 2) >> 8,
-			0xe0,	v_scaling_increment & 0xff,
-			0xe1,	v_scaling_increment >> 8,
-			0xe2,	v_scaling_increment & 0xff,
-			0xe3,	v_scaling_increment >> 8,
-			0x88,	0xf0,
-			0,	0,
-		};
-		write_regs(client, regs);
-		break;
-	}
-	case VIDIOC_S_STD:
-	{
-		v4l2_std_id *input = arg;
-		u8 regs[] = {
-			0x88,	0xc0,
-			0x98,	*input & V4L2_STD_NTSC ? 0x12 : 0x16,
-			0x9a,	*input & V4L2_STD_NTSC ? 0xf2 : 0x20,
-			0x9b,	*input & V4L2_STD_NTSC ? 0x00 : 0x01,
-			0xc8,	*input & V4L2_STD_NTSC ? 0x12 : 0x16,
-			0xca,	*input & V4L2_STD_NTSC ? 0xf2 : 0x20,
-			0xcb,	*input & V4L2_STD_NTSC ? 0x00 : 0x01,
-			0x88,	0xf0,
-			0x30,	*input & V4L2_STD_NTSC ? 0x66 : 0x00,
-			0x31,	*input & V4L2_STD_NTSC ? 0x90 : 0xe0,
-			0,	0,
-		};
-		write_regs(client, regs);
-		dec->norm = *input;
-		break;
-	}
-	case VIDIOC_QUERYCTRL:
-	{
-		struct v4l2_queryctrl *ctrl = arg;
-
-		switch (ctrl->id) {
-		case V4L2_CID_BRIGHTNESS:
-			ctrl->type = V4L2_CTRL_TYPE_INTEGER;
-			strncpy(ctrl->name, "Brightness", sizeof(ctrl->name));
-			ctrl->minimum = 0;
-			ctrl->maximum = 255;
-			ctrl->step = 1;
-			ctrl->default_value = 128;
-			ctrl->flags = 0;
-			break;
-		case V4L2_CID_CONTRAST:
-			ctrl->type = V4L2_CTRL_TYPE_INTEGER;
-			strncpy(ctrl->name, "Contrast", sizeof(ctrl->name));
-			ctrl->minimum = 0;
-			ctrl->maximum = 127;
-			ctrl->step = 1;
-			ctrl->default_value = 64;
-			ctrl->flags = 0;
-			break;
-		case V4L2_CID_SATURATION:
-			ctrl->type = V4L2_CTRL_TYPE_INTEGER;
-			strncpy(ctrl->name, "Saturation", sizeof(ctrl->name));
-			ctrl->minimum = 0;
-			ctrl->maximum = 127;
-			ctrl->step = 1;
-			ctrl->default_value = 64;
-			ctrl->flags = 0;
-			break;
-		case V4L2_CID_HUE:
-			ctrl->type = V4L2_CTRL_TYPE_INTEGER;
-			strncpy(ctrl->name, "Hue", sizeof(ctrl->name));
-			ctrl->minimum = -128;
-			ctrl->maximum = 127;
-			ctrl->step = 1;
-			ctrl->default_value = 0;
-			ctrl->flags = 0;
-			break;
-		}
-		break;
-	}
-	case VIDIOC_S_CTRL:
-	{
-		struct v4l2_control *ctrl = arg;
-
-		switch (ctrl->id) {
-		case V4L2_CID_BRIGHTNESS:
-			if (ctrl->value > 255)
-				dec->brightness = 255;
-			else if (ctrl->value < 0)
-				dec->brightness = 0;
-			else
-				dec->brightness = ctrl->value;
-			write_reg(client, 0x0a, dec->brightness);
-			break;
-		case V4L2_CID_CONTRAST:
-			if (ctrl->value > 127)
-				dec->contrast = 127;
-			else if (ctrl->value < 0)
-				dec->contrast = 0;
-			else
-				dec->contrast = ctrl->value;
-			write_reg(client, 0x0b, dec->contrast);
-			break;
-		case V4L2_CID_SATURATION:
-			if (ctrl->value > 127)
-				dec->saturation = 127;
-			else if (ctrl->value < 0)
-				dec->saturation = 0;
-			else
-				dec->saturation = ctrl->value;
-			write_reg(client, 0x0c, dec->saturation);
-			break;
-		case V4L2_CID_HUE:
-			if (ctrl->value > 127)
-				dec->hue = 127;
-			else if (ctrl->value < -128)
-				dec->hue = -128;
-			else
-				dec->hue = ctrl->value;
-			write_reg(client, 0x0d, dec->hue);
-			break;
-		}
-		break;
-	}
-	case VIDIOC_G_CTRL:
-	{
-		struct v4l2_control *ctrl = arg;
-
-		switch (ctrl->id) {
-		case V4L2_CID_BRIGHTNESS:
-			ctrl->value = dec->brightness;
-			break;
-		case V4L2_CID_CONTRAST:
-			ctrl->value = dec->contrast;
-			break;
-		case V4L2_CID_SATURATION:
-			ctrl->value = dec->saturation;
-			break;
-		case V4L2_CID_HUE:
-			ctrl->value = dec->hue;
-			break;
-		}
-		break;
-	}
-	default:
-		break;
-	}
-	return 0;
-}
-
-static int wis_saa7115_probe(struct i2c_client *client,
-			     const struct i2c_device_id *id)
-{
-	struct i2c_adapter *adapter = client->adapter;
-	struct wis_saa7115 *dec;
-
-	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
-		return -ENODEV;
-
-	dec = kmalloc(sizeof(struct wis_saa7115), GFP_KERNEL);
-	if (dec == NULL)
-		return -ENOMEM;
-
-	dec->norm = V4L2_STD_NTSC;
-	dec->brightness = 128;
-	dec->contrast = 64;
-	dec->saturation = 64;
-	dec->hue = 0;
-	i2c_set_clientdata(client, dec);
-
-	dev_dbg(&client->dev,
-		"wis-saa7115: initializing SAA7115 at address %d on %s\n",
-		client->addr, adapter->name);
-
-	if (write_regs(client, initial_registers) < 0) {
-		dev_err(&client->dev,
-			"wis-saa7115: error initializing SAA7115\n");
-		kfree(dec);
-		return -ENODEV;
-	}
-
-	return 0;
-}
-
-static int wis_saa7115_remove(struct i2c_client *client)
-{
-	struct wis_saa7115 *dec = i2c_get_clientdata(client);
-
-	kfree(dec);
-	return 0;
-}
-
-static const struct i2c_device_id wis_saa7115_id[] = {
-	{ "wis_saa7115", 0 },
-	{ }
-};
-MODULE_DEVICE_TABLE(i2c, wis_saa7115_id);
-
-static struct i2c_driver wis_saa7115_driver = {
-	.driver = {
-		.name	= "WIS SAA7115 I2C driver",
-	},
-	.probe		= wis_saa7115_probe,
-	.remove		= wis_saa7115_remove,
-	.command	= wis_saa7115_command,
-	.id_table	= wis_saa7115_id,
-};
-
-module_i2c_driver(wis_saa7115_driver);
-
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/media/go7007/wis-sony-tuner.c b/drivers/staging/media/go7007/wis-sony-tuner.c
deleted file mode 100644
index 5d7ff8c..0000000
--- a/drivers/staging/media/go7007/wis-sony-tuner.c
+++ /dev/null
@@ -1,707 +0,0 @@
-/*
- * Copyright (C) 2005-2006 Micronas USA 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., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/i2c.h>
-#include <linux/videodev2.h>
-#include <linux/slab.h>
-#include <media/tuner.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
-
-#include "wis-i2c.h"
-
-/* #define MPX_DEBUG */
-
-/* AS(IF/MPX) pin:      LOW      HIGH/OPEN
- * IF/MPX address:   0x42/0x40   0x43/0x44
- */
-#define IF_I2C_ADDR	0x43
-#define MPX_I2C_ADDR	0x44
-
-static v4l2_std_id force_band;
-static char force_band_str[] = "-";
-module_param_string(force_band, force_band_str, sizeof(force_band_str), 0644);
-static int force_mpx_mode = -1;
-module_param(force_mpx_mode, int, 0644);
-
-/* Store tuner info in the same format as tuner.c, so maybe we can put the
- * Sony tuner support in there. */
-struct sony_tunertype {
-	char *name;
-	unsigned char Vendor; /* unused here */
-	unsigned char Type; /* unused here */
-
-	unsigned short thresh1; /*  band switch VHF_LO <=> VHF_HI */
-	unsigned short thresh2; /*  band switch VHF_HI <=> UHF */
-	unsigned char VHF_L;
-	unsigned char VHF_H;
-	unsigned char UHF;
-	unsigned char config;
-	unsigned short IFPCoff;
-};
-
-/* This array is indexed by (tuner_type - 200) */
-static struct sony_tunertype sony_tuners[] = {
-	{ "Sony PAL+SECAM (BTF-PG472Z)", 0, 0,
-	  16*144.25, 16*427.25, 0x01, 0x02, 0x04, 0xc6, 623},
-	{ "Sony NTSC_JP (BTF-PK467Z)", 0, 0,
-	  16*220.25, 16*467.25, 0x01, 0x02, 0x04, 0xc6, 940},
-	{ "Sony NTSC (BTF-PB463Z)", 0, 0,
-	  16*130.25, 16*364.25, 0x01, 0x02, 0x04, 0xc6, 732},
-};
-
-struct wis_sony_tuner {
-	int type;
-	v4l2_std_id std;
-	unsigned int freq;
-	int mpxmode;
-	u32 audmode;
-};
-
-/* Basically the same as default_set_tv_freq() in tuner.c */
-static int set_freq(struct i2c_client *client, int freq)
-{
-	struct wis_sony_tuner *t = i2c_get_clientdata(client);
-	char *band_name;
-	int n;
-	int band_select;
-	struct sony_tunertype *tun;
-	u8 buffer[4];
-
-	tun = &sony_tuners[t->type - 200];
-	if (freq < tun->thresh1) {
-		band_name = "VHF_L";
-		band_select = tun->VHF_L;
-	} else if (freq < tun->thresh2) {
-		band_name = "VHF_H";
-		band_select = tun->VHF_H;
-	} else {
-		band_name = "UHF";
-		band_select = tun->UHF;
-	}
-	dev_dbg(&client->dev, "tuning to frequency %d.%04d (%s)\n",
-		freq / 16, (freq % 16) * 625, band_name);
-	n = freq + tun->IFPCoff;
-
-	buffer[0] = n >> 8;
-	buffer[1] = n & 0xff;
-	buffer[2] = tun->config;
-	buffer[3] = band_select;
-	i2c_master_send(client, buffer, 4);
-
-	return 0;
-}
-
-static int mpx_write(struct i2c_client *client, int dev, int addr, int val)
-{
-	u8 buffer[5];
-	struct i2c_msg msg;
-
-	buffer[0] = dev;
-	buffer[1] = addr >> 8;
-	buffer[2] = addr & 0xff;
-	buffer[3] = val >> 8;
-	buffer[4] = val & 0xff;
-	msg.addr = MPX_I2C_ADDR;
-	msg.flags = 0;
-	msg.len = 5;
-	msg.buf = buffer;
-	i2c_transfer(client->adapter, &msg, 1);
-	return 0;
-}
-
-/*
- * MPX register values for the BTF-PG472Z:
- *
- *                                 FM_     NICAM_  SCART_
- *          MODUS  SOURCE    ACB   PRESCAL PRESCAL PRESCAL SYSTEM  VOLUME
- *         10/0030 12/0008 12/0013 12/000E 12/0010 12/0000 10/0020 12/0000
- *         ---------------------------------------------------------------
- * Auto     1003    0020    0100    2603    5000    XXXX    0001    7500
- *
- * B/G
- *  Mono    1003    0020    0100    2603    5000    XXXX    0003    7500
- *  A2      1003    0020    0100    2601    5000    XXXX    0003    7500
- *  NICAM   1003    0120    0100    2603    5000    XXXX    0008    7500
- *
- * I
- *  Mono    1003    0020    0100    2603    7900    XXXX    000A    7500
- *  NICAM   1003    0120    0100    2603    7900    XXXX    000A    7500
- *
- * D/K
- *  Mono    1003    0020    0100    2603    5000    XXXX    0004    7500
- *  A2-1    1003    0020    0100    2601    5000    XXXX    0004    7500
- *  A2-2    1003    0020    0100    2601    5000    XXXX    0005    7500
- *  A2-3    1003    0020    0100    2601    5000    XXXX    0007    7500
- *  NICAM   1003    0120    0100    2603    5000    XXXX    000B    7500
- *
- * L/L'
- *  Mono    0003    0200    0100    7C03    5000    2200    0009    7500
- *  NICAM   0003    0120    0100    7C03    5000    XXXX    0009    7500
- *
- * M
- *  Mono    1003    0200    0100    2B03    5000    2B00    0002    7500
- *
- * For Asia, replace the 0x26XX in FM_PRESCALE with 0x14XX.
- *
- * Bilingual selection in A2/NICAM:
- *
- *         High byte of SOURCE     Left chan   Right chan
- *                 0x01              MAIN         SUB
- *                 0x03              MAIN         MAIN
- *                 0x04              SUB          SUB
- *
- * Force mono in NICAM by setting the high byte of SOURCE to 0x02 (L/L') or
- * 0x00 (all other bands).  Force mono in A2 with FMONO_A2:
- *
- *                      FMONO_A2
- *                      10/0022
- *                      --------
- *     Forced mono ON     07F0
- *     Forced mono OFF    0190
- */
-
-static struct {
-	enum { AUD_MONO, AUD_A2, AUD_NICAM, AUD_NICAM_L } audio_mode;
-	u16 modus;
-	u16 source;
-	u16 acb;
-	u16 fm_prescale;
-	u16 nicam_prescale;
-	u16 scart_prescale;
-	u16 system;
-	u16 volume;
-} mpx_audio_modes[] = {
-	/* Auto */	{ AUD_MONO,	0x1003, 0x0020, 0x0100, 0x2603,
-					0x5000, 0x0000, 0x0001, 0x7500 },
-	/* B/G Mono */	{ AUD_MONO,	0x1003, 0x0020, 0x0100, 0x2603,
-					0x5000, 0x0000, 0x0003, 0x7500 },
-	/* B/G A2 */	{ AUD_A2,	0x1003, 0x0020, 0x0100, 0x2601,
-					0x5000, 0x0000, 0x0003, 0x7500 },
-	/* B/G NICAM */ { AUD_NICAM,	0x1003, 0x0120, 0x0100, 0x2603,
-					0x5000, 0x0000, 0x0008, 0x7500 },
-	/* I Mono */	{ AUD_MONO,	0x1003, 0x0020, 0x0100, 0x2603,
-					0x7900, 0x0000, 0x000A, 0x7500 },
-	/* I NICAM */	{ AUD_NICAM,	0x1003, 0x0120, 0x0100, 0x2603,
-					0x7900, 0x0000, 0x000A, 0x7500 },
-	/* D/K Mono */	{ AUD_MONO,	0x1003, 0x0020, 0x0100, 0x2603,
-					0x5000, 0x0000, 0x0004, 0x7500 },
-	/* D/K A2-1 */	{ AUD_A2,	0x1003, 0x0020, 0x0100, 0x2601,
-					0x5000, 0x0000, 0x0004, 0x7500 },
-	/* D/K A2-2 */	{ AUD_A2,	0x1003, 0x0020, 0x0100, 0x2601,
-					0x5000, 0x0000, 0x0005, 0x7500 },
-	/* D/K A2-3 */	{ AUD_A2,	0x1003, 0x0020, 0x0100, 0x2601,
-					0x5000, 0x0000, 0x0007, 0x7500 },
-	/* D/K NICAM */	{ AUD_NICAM,	0x1003, 0x0120, 0x0100, 0x2603,
-					0x5000, 0x0000, 0x000B, 0x7500 },
-	/* L/L' Mono */	{ AUD_MONO,	0x0003, 0x0200, 0x0100, 0x7C03,
-					0x5000, 0x2200, 0x0009, 0x7500 },
-	/* L/L' NICAM */{ AUD_NICAM_L,	0x0003, 0x0120, 0x0100, 0x7C03,
-					0x5000, 0x0000, 0x0009, 0x7500 },
-};
-
-#define MPX_NUM_MODES	ARRAY_SIZE(mpx_audio_modes)
-
-static int mpx_setup(struct i2c_client *client)
-{
-	struct wis_sony_tuner *t = i2c_get_clientdata(client);
-	u16 source = 0;
-	u8 buffer[3];
-	struct i2c_msg msg;
-
-	/* reset MPX */
-	buffer[0] = 0x00;
-	buffer[1] = 0x80;
-	buffer[2] = 0x00;
-	msg.addr = MPX_I2C_ADDR;
-	msg.flags = 0;
-	msg.len = 3;
-	msg.buf = buffer;
-	i2c_transfer(client->adapter, &msg, 1);
-	buffer[1] = 0x00;
-	i2c_transfer(client->adapter, &msg, 1);
-
-	if (mpx_audio_modes[t->mpxmode].audio_mode != AUD_MONO) {
-		switch (t->audmode) {
-		case V4L2_TUNER_MODE_MONO:
-			switch (mpx_audio_modes[t->mpxmode].audio_mode) {
-			case AUD_A2:
-				source = mpx_audio_modes[t->mpxmode].source;
-				break;
-			case AUD_NICAM:
-				source = 0x0000;
-				break;
-			case AUD_NICAM_L:
-				source = 0x0200;
-				break;
-			default:
-				break;
-			}
-			break;
-		case V4L2_TUNER_MODE_STEREO:
-			source = mpx_audio_modes[t->mpxmode].source;
-			break;
-		case V4L2_TUNER_MODE_LANG1:
-			source = 0x0300;
-			break;
-		case V4L2_TUNER_MODE_LANG2:
-			source = 0x0400;
-			break;
-		}
-		source |= mpx_audio_modes[t->mpxmode].source & 0x00ff;
-	} else
-		source = mpx_audio_modes[t->mpxmode].source;
-
-	mpx_write(client, 0x10, 0x0030, mpx_audio_modes[t->mpxmode].modus);
-	mpx_write(client, 0x12, 0x0008, source);
-	mpx_write(client, 0x12, 0x0013, mpx_audio_modes[t->mpxmode].acb);
-	mpx_write(client, 0x12, 0x000e,
-			mpx_audio_modes[t->mpxmode].fm_prescale);
-	mpx_write(client, 0x12, 0x0010,
-			mpx_audio_modes[t->mpxmode].nicam_prescale);
-	mpx_write(client, 0x12, 0x000d,
-			mpx_audio_modes[t->mpxmode].scart_prescale);
-	mpx_write(client, 0x10, 0x0020, mpx_audio_modes[t->mpxmode].system);
-	mpx_write(client, 0x12, 0x0000, mpx_audio_modes[t->mpxmode].volume);
-	if (mpx_audio_modes[t->mpxmode].audio_mode == AUD_A2)
-		mpx_write(client, 0x10, 0x0022,
-			t->audmode == V4L2_TUNER_MODE_MONO ?  0x07f0 : 0x0190);
-
-#ifdef MPX_DEBUG
-	{
-		u8 buf1[3], buf2[2];
-		struct i2c_msg msgs[2];
-
-		dev_dbg(&client->dev,
-			"MPX registers: %04x %04x %04x %04x %04x %04x %04x %04x\n",
-			mpx_audio_modes[t->mpxmode].modus,
-			source,
-			mpx_audio_modes[t->mpxmode].acb,
-			mpx_audio_modes[t->mpxmode].fm_prescale,
-			mpx_audio_modes[t->mpxmode].nicam_prescale,
-			mpx_audio_modes[t->mpxmode].scart_prescale,
-			mpx_audio_modes[t->mpxmode].system,
-			mpx_audio_modes[t->mpxmode].volume);
-		buf1[0] = 0x11;
-		buf1[1] = 0x00;
-		buf1[2] = 0x7e;
-		msgs[0].addr = MPX_I2C_ADDR;
-		msgs[0].flags = 0;
-		msgs[0].len = 3;
-		msgs[0].buf = buf1;
-		msgs[1].addr = MPX_I2C_ADDR;
-		msgs[1].flags = I2C_M_RD;
-		msgs[1].len = 2;
-		msgs[1].buf = buf2;
-		i2c_transfer(client->adapter, msgs, 2);
-		dev_dbg(&client->dev, "MPX system: %02x%02x\n",
-			buf2[0], buf2[1]);
-		buf1[0] = 0x11;
-		buf1[1] = 0x02;
-		buf1[2] = 0x00;
-		i2c_transfer(client->adapter, msgs, 2);
-		dev_dbg(&client->dev, "MPX status: %02x%02x\n",
-			buf2[0], buf2[1]);
-	}
-#endif
-	return 0;
-}
-
-/*
- * IF configuration values for the BTF-PG472Z:
- *
- *	B/G: 0x94 0x70 0x49
- *	I:   0x14 0x70 0x4a
- *	D/K: 0x14 0x70 0x4b
- *	L:   0x04 0x70 0x4b
- *	L':  0x44 0x70 0x53
- *	M:   0x50 0x30 0x4c
- */
-
-static int set_if(struct i2c_client *client)
-{
-	struct wis_sony_tuner *t = i2c_get_clientdata(client);
-	u8 buffer[4];
-	struct i2c_msg msg;
-	int default_mpx_mode = 0;
-
-	/* configure IF */
-	buffer[0] = 0;
-	if (t->std & V4L2_STD_PAL_BG) {
-		buffer[1] = 0x94;
-		buffer[2] = 0x70;
-		buffer[3] = 0x49;
-		default_mpx_mode = 1;
-	} else if (t->std & V4L2_STD_PAL_I) {
-		buffer[1] = 0x14;
-		buffer[2] = 0x70;
-		buffer[3] = 0x4a;
-		default_mpx_mode = 4;
-	} else if (t->std & V4L2_STD_PAL_DK) {
-		buffer[1] = 0x14;
-		buffer[2] = 0x70;
-		buffer[3] = 0x4b;
-		default_mpx_mode = 6;
-	} else if (t->std & V4L2_STD_SECAM_L) {
-		buffer[1] = 0x04;
-		buffer[2] = 0x70;
-		buffer[3] = 0x4b;
-		default_mpx_mode = 11;
-	}
-	msg.addr = IF_I2C_ADDR;
-	msg.flags = 0;
-	msg.len = 4;
-	msg.buf = buffer;
-	i2c_transfer(client->adapter, &msg, 1);
-
-	/* Select MPX mode if not forced by the user */
-	if (force_mpx_mode >= 0 && force_mpx_mode < MPX_NUM_MODES)
-		t->mpxmode = force_mpx_mode;
-	else
-		t->mpxmode = default_mpx_mode;
-	dev_dbg(&client->dev, "setting MPX to mode %d\n", t->mpxmode);
-	mpx_setup(client);
-
-	return 0;
-}
-
-static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
-{
-	struct wis_sony_tuner *t = i2c_get_clientdata(client);
-
-	switch (cmd) {
-#if 0
-#ifdef TUNER_SET_TYPE_ADDR
-	case TUNER_SET_TYPE_ADDR:
-	{
-		struct tuner_setup *tun_setup = arg;
-		int *type = &tun_setup->type;
-#else
-	case TUNER_SET_TYPE:
-	{
-		int *type = arg;
-#endif
-
-		if (t->type >= 0) {
-			if (t->type != *type)
-				dev_err(&client->dev,
-					"type already set to %d, ignoring request for %d\n",
-					t->type, *type);
-			break;
-		}
-		t->type = *type;
-		switch (t->type) {
-		case TUNER_SONY_BTF_PG472Z:
-			switch (force_band_str[0]) {
-			case 'b':
-			case 'B':
-			case 'g':
-			case 'G':
-				dev_info(&client->dev,
-					 "forcing tuner to PAL-B/G bands\n");
-				force_band = V4L2_STD_PAL_BG;
-				break;
-			case 'i':
-			case 'I':
-				dev_info(&client->dev,
-					 "forcing tuner to PAL-I band\n");
-				force_band = V4L2_STD_PAL_I;
-				break;
-			case 'd':
-			case 'D':
-			case 'k':
-			case 'K':
-				dev_info(&client->dev,
-					 "forcing tuner to PAL-D/K bands\n");
-				force_band = V4L2_STD_PAL_I;
-				break;
-			case 'l':
-			case 'L':
-				dev_info(&client->dev,
-					 "forcing tuner to SECAM-L band\n");
-				force_band = V4L2_STD_SECAM_L;
-				break;
-			default:
-				force_band = 0;
-				break;
-			}
-			if (force_band)
-				t->std = force_band;
-			else
-				t->std = V4L2_STD_PAL_BG;
-			set_if(client);
-			break;
-		case TUNER_SONY_BTF_PK467Z:
-			t->std = V4L2_STD_NTSC_M_JP;
-			break;
-		case TUNER_SONY_BTF_PB463Z:
-			t->std = V4L2_STD_NTSC_M;
-			break;
-		default:
-			dev_err(&client->dev,
-				"tuner type %d is not supported by this module\n",
-				*type);
-			break;
-		}
-		if (type >= 0)
-			dev_info(&clinet->dev,
-				 "type set to %d (%s)\n",
-				 t->type, sony_tuners[t->type - 200].name);
-		break;
-	}
-#endif
-	case VIDIOC_G_FREQUENCY:
-	{
-		struct v4l2_frequency *f = arg;
-
-		f->frequency = t->freq;
-		break;
-	}
-	case VIDIOC_S_FREQUENCY:
-	{
-		struct v4l2_frequency *f = arg;
-
-		t->freq = f->frequency;
-		set_freq(client, t->freq);
-		break;
-	}
-	case VIDIOC_ENUMSTD:
-	{
-		struct v4l2_standard *std = arg;
-
-		switch (t->type) {
-		case TUNER_SONY_BTF_PG472Z:
-			switch (std->index) {
-			case 0:
-				v4l2_video_std_construct(std,
-						V4L2_STD_PAL_BG, "PAL-B/G");
-				break;
-			case 1:
-				v4l2_video_std_construct(std,
-						V4L2_STD_PAL_I, "PAL-I");
-				break;
-			case 2:
-				v4l2_video_std_construct(std,
-						V4L2_STD_PAL_DK, "PAL-D/K");
-				break;
-			case 3:
-				v4l2_video_std_construct(std,
-						V4L2_STD_SECAM_L, "SECAM-L");
-				break;
-			default:
-				std->id = 0; /* hack to indicate EINVAL */
-				break;
-			}
-			break;
-		case TUNER_SONY_BTF_PK467Z:
-			if (std->index != 0) {
-				std->id = 0; /* hack to indicate EINVAL */
-				break;
-			}
-			v4l2_video_std_construct(std,
-					V4L2_STD_NTSC_M_JP, "NTSC-J");
-			break;
-		case TUNER_SONY_BTF_PB463Z:
-			if (std->index != 0) {
-				std->id = 0; /* hack to indicate EINVAL */
-				break;
-			}
-			v4l2_video_std_construct(std, V4L2_STD_NTSC_M, "NTSC");
-			break;
-		}
-		break;
-	}
-	case VIDIOC_G_STD:
-	{
-		v4l2_std_id *std = arg;
-
-		*std = t->std;
-		break;
-	}
-	case VIDIOC_S_STD:
-	{
-		v4l2_std_id *std = arg;
-		v4l2_std_id old = t->std;
-
-		switch (t->type) {
-		case TUNER_SONY_BTF_PG472Z:
-			if (force_band && (*std & force_band) != *std &&
-					*std != V4L2_STD_PAL &&
-					*std != V4L2_STD_SECAM) {
-				dev_dbg(&client->dev,
-					"ignoring requested TV standard in favor of force_band value\n");
-				t->std = force_band;
-			} else if (*std & V4L2_STD_PAL_BG) { /* default */
-				t->std = V4L2_STD_PAL_BG;
-			} else if (*std & V4L2_STD_PAL_I) {
-				t->std = V4L2_STD_PAL_I;
-			} else if (*std & V4L2_STD_PAL_DK) {
-				t->std = V4L2_STD_PAL_DK;
-			} else if (*std & V4L2_STD_SECAM_L) {
-				t->std = V4L2_STD_SECAM_L;
-			} else {
-				dev_err(&client->dev,
-					"TV standard not supported\n");
-				*std = 0; /* hack to indicate EINVAL */
-				break;
-			}
-			if (old != t->std)
-				set_if(client);
-			break;
-		case TUNER_SONY_BTF_PK467Z:
-			if (!(*std & V4L2_STD_NTSC_M_JP)) {
-				dev_err(&client->dev,
-					"TV standard not supported\n");
-				*std = 0; /* hack to indicate EINVAL */
-			}
-			break;
-		case TUNER_SONY_BTF_PB463Z:
-			if (!(*std & V4L2_STD_NTSC_M)) {
-				dev_err(&client->dev,
-					"TV standard not supported\n");
-				*std = 0; /* hack to indicate EINVAL */
-			}
-			break;
-		}
-		break;
-	}
-	case VIDIOC_QUERYSTD:
-	{
-		v4l2_std_id *std = arg;
-
-		switch (t->type) {
-		case TUNER_SONY_BTF_PG472Z:
-			if (force_band)
-				*std = force_band;
-			else
-				*std = V4L2_STD_PAL_BG | V4L2_STD_PAL_I |
-					V4L2_STD_PAL_DK | V4L2_STD_SECAM_L;
-			break;
-		case TUNER_SONY_BTF_PK467Z:
-			*std = V4L2_STD_NTSC_M_JP;
-			break;
-		case TUNER_SONY_BTF_PB463Z:
-			*std = V4L2_STD_NTSC_M;
-			break;
-		}
-		break;
-	}
-	case VIDIOC_G_TUNER:
-	{
-		struct v4l2_tuner *tun = arg;
-
-		memset(tun, 0, sizeof(*tun));
-		strcpy(tun->name, "Television");
-		tun->type = V4L2_TUNER_ANALOG_TV;
-		tun->rangelow = 0UL; /* does anything use these? */
-		tun->rangehigh = 0xffffffffUL;
-		switch (t->type) {
-		case TUNER_SONY_BTF_PG472Z:
-			tun->capability = V4L2_TUNER_CAP_NORM |
-				V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 |
-				V4L2_TUNER_CAP_LANG2;
-			tun->rxsubchans = V4L2_TUNER_SUB_MONO |
-				V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_LANG1 |
-				V4L2_TUNER_SUB_LANG2;
-			break;
-		case TUNER_SONY_BTF_PK467Z:
-		case TUNER_SONY_BTF_PB463Z:
-			tun->capability = V4L2_TUNER_CAP_STEREO;
-			tun->rxsubchans = V4L2_TUNER_SUB_MONO |
-						V4L2_TUNER_SUB_STEREO;
-			break;
-		}
-		tun->audmode = t->audmode;
-		return 0;
-	}
-	case VIDIOC_S_TUNER:
-	{
-		struct v4l2_tuner *tun = arg;
-
-		switch (t->type) {
-		case TUNER_SONY_BTF_PG472Z:
-			if (tun->audmode != t->audmode) {
-				t->audmode = tun->audmode;
-				mpx_setup(client);
-			}
-			break;
-		case TUNER_SONY_BTF_PK467Z:
-		case TUNER_SONY_BTF_PB463Z:
-			break;
-		}
-		return 0;
-	}
-	default:
-		break;
-	}
-	return 0;
-}
-
-static int wis_sony_tuner_probe(struct i2c_client *client,
-				const struct i2c_device_id *id)
-{
-	struct i2c_adapter *adapter = client->adapter;
-	struct wis_sony_tuner *t;
-
-	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_I2C_BLOCK))
-		return -ENODEV;
-
-	t = kmalloc(sizeof(struct wis_sony_tuner), GFP_KERNEL);
-	if (t == NULL)
-		return -ENOMEM;
-
-	t->type = -1;
-	t->freq = 0;
-	t->mpxmode = 0;
-	t->audmode = V4L2_TUNER_MODE_STEREO;
-	i2c_set_clientdata(client, t);
-
-	dev_dbg(&client->dev, "initializing tuner at address %d on %s\n",
-		client->addr, adapter->name);
-
-	return 0;
-}
-
-static int wis_sony_tuner_remove(struct i2c_client *client)
-{
-	struct wis_sony_tuner *t = i2c_get_clientdata(client);
-
-	kfree(t);
-	return 0;
-}
-
-static const struct i2c_device_id wis_sony_tuner_id[] = {
-	{ "wis_sony_tuner", 0 },
-	{ }
-};
-MODULE_DEVICE_TABLE(i2c, wis_sony_tuner_id);
-
-static struct i2c_driver wis_sony_tuner_driver = {
-	.driver = {
-		.name	= "WIS Sony TV Tuner I2C driver",
-	},
-	.probe		= wis_sony_tuner_probe,
-	.remove		= wis_sony_tuner_remove,
-	.command	= tuner_command,
-	.id_table	= wis_sony_tuner_id,
-};
-
-module_i2c_driver(wis_sony_tuner_driver);
-
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/media/go7007/wis-tw2804.c b/drivers/staging/media/go7007/wis-tw2804.c
deleted file mode 100644
index 290fd8c..0000000
--- a/drivers/staging/media/go7007/wis-tw2804.c
+++ /dev/null
@@ -1,348 +0,0 @@
-/*
- * Copyright (C) 2005-2006 Micronas USA 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., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/i2c.h>
-#include <linux/videodev2.h>
-#include <linux/ioctl.h>
-#include <linux/slab.h>
-
-#include "wis-i2c.h"
-
-struct wis_tw2804 {
-	int channel;
-	int norm;
-	int brightness;
-	int contrast;
-	int saturation;
-	int hue;
-};
-
-static u8 global_registers[] = {
-	0x39, 0x00,
-	0x3a, 0xff,
-	0x3b, 0x84,
-	0x3c, 0x80,
-	0x3d, 0x80,
-	0x3e, 0x82,
-	0x3f, 0x82,
-	0xff, 0xff, /* Terminator (reg 0xff does not exist) */
-};
-
-static u8 channel_registers[] = {
-	0x01, 0xc4,
-	0x02, 0xa5,
-	0x03, 0x20,
-	0x04, 0xd0,
-	0x05, 0x20,
-	0x06, 0xd0,
-	0x07, 0x88,
-	0x08, 0x20,
-	0x09, 0x07,
-	0x0a, 0xf0,
-	0x0b, 0x07,
-	0x0c, 0xf0,
-	0x0d, 0x40,
-	0x0e, 0xd2,
-	0x0f, 0x80,
-	0x10, 0x80,
-	0x11, 0x80,
-	0x12, 0x80,
-	0x13, 0x1f,
-	0x14, 0x00,
-	0x15, 0x00,
-	0x16, 0x00,
-	0x17, 0x00,
-	0x18, 0xff,
-	0x19, 0xff,
-	0x1a, 0xff,
-	0x1b, 0xff,
-	0x1c, 0xff,
-	0x1d, 0xff,
-	0x1e, 0xff,
-	0x1f, 0xff,
-	0x20, 0x07,
-	0x21, 0x07,
-	0x22, 0x00,
-	0x23, 0x91,
-	0x24, 0x51,
-	0x25, 0x03,
-	0x26, 0x00,
-	0x27, 0x00,
-	0x28, 0x00,
-	0x29, 0x00,
-	0x2a, 0x00,
-	0x2b, 0x00,
-	0x2c, 0x00,
-	0x2d, 0x00,
-	0x2e, 0x00,
-	0x2f, 0x00,
-	0x30, 0x00,
-	0x31, 0x00,
-	0x32, 0x00,
-	0x33, 0x00,
-	0x34, 0x00,
-	0x35, 0x00,
-	0x36, 0x00,
-	0x37, 0x00,
-	0xff, 0xff, /* Terminator (reg 0xff does not exist) */
-};
-
-static int write_reg(struct i2c_client *client, u8 reg, u8 value, int channel)
-{
-	return i2c_smbus_write_byte_data(client, reg | (channel << 6), value);
-}
-
-static int write_regs(struct i2c_client *client, u8 *regs, int channel)
-{
-	int i;
-
-	for (i = 0; regs[i] != 0xff; i += 2)
-		if (i2c_smbus_write_byte_data(client,
-				regs[i] | (channel << 6), regs[i + 1]) < 0)
-			return -1;
-	return 0;
-}
-
-static int wis_tw2804_command(struct i2c_client *client,
-				unsigned int cmd, void *arg)
-{
-	struct wis_tw2804 *dec = i2c_get_clientdata(client);
-
-	if (cmd == DECODER_SET_CHANNEL) {
-		int *input = arg;
-
-		if (*input < 0 || *input > 3) {
-			dev_err(&client->dev,
-				"channel %d is not between 0 and 3!\n", *input);
-			return 0;
-		}
-		dec->channel = *input;
-		dev_dbg(&client->dev, "initializing TW2804 channel %d\n",
-			dec->channel);
-		if (dec->channel == 0 &&
-				write_regs(client, global_registers, 0) < 0) {
-			dev_err(&client->dev,
-				"error initializing TW2804 global registers\n");
-			return 0;
-		}
-		if (write_regs(client, channel_registers, dec->channel) < 0) {
-			dev_err(&client->dev,
-				"error initializing TW2804 channel %d\n",
-				dec->channel);
-			return 0;
-		}
-		return 0;
-	}
-
-	if (dec->channel < 0) {
-		dev_dbg(&client->dev,
-			"ignoring command %08x until channel number is set\n",
-			cmd);
-		return 0;
-	}
-
-	switch (cmd) {
-	case VIDIOC_S_STD:
-	{
-		v4l2_std_id *input = arg;
-		u8 regs[] = {
-			0x01, *input & V4L2_STD_NTSC ? 0xc4 : 0x84,
-			0x09, *input & V4L2_STD_NTSC ? 0x07 : 0x04,
-			0x0a, *input & V4L2_STD_NTSC ? 0xf0 : 0x20,
-			0x0b, *input & V4L2_STD_NTSC ? 0x07 : 0x04,
-			0x0c, *input & V4L2_STD_NTSC ? 0xf0 : 0x20,
-			0x0d, *input & V4L2_STD_NTSC ? 0x40 : 0x4a,
-			0x16, *input & V4L2_STD_NTSC ? 0x00 : 0x40,
-			0x17, *input & V4L2_STD_NTSC ? 0x00 : 0x40,
-			0x20, *input & V4L2_STD_NTSC ? 0x07 : 0x0f,
-			0x21, *input & V4L2_STD_NTSC ? 0x07 : 0x0f,
-			0xff,	0xff,
-		};
-		write_regs(client, regs, dec->channel);
-		dec->norm = *input;
-		break;
-	}
-	case VIDIOC_QUERYCTRL:
-	{
-		struct v4l2_queryctrl *ctrl = arg;
-
-		switch (ctrl->id) {
-		case V4L2_CID_BRIGHTNESS:
-			ctrl->type = V4L2_CTRL_TYPE_INTEGER;
-			strncpy(ctrl->name, "Brightness", sizeof(ctrl->name));
-			ctrl->minimum = 0;
-			ctrl->maximum = 255;
-			ctrl->step = 1;
-			ctrl->default_value = 128;
-			ctrl->flags = 0;
-			break;
-		case V4L2_CID_CONTRAST:
-			ctrl->type = V4L2_CTRL_TYPE_INTEGER;
-			strncpy(ctrl->name, "Contrast", sizeof(ctrl->name));
-			ctrl->minimum = 0;
-			ctrl->maximum = 255;
-			ctrl->step = 1;
-			ctrl->default_value = 128;
-			ctrl->flags = 0;
-			break;
-		case V4L2_CID_SATURATION:
-			ctrl->type = V4L2_CTRL_TYPE_INTEGER;
-			strncpy(ctrl->name, "Saturation", sizeof(ctrl->name));
-			ctrl->minimum = 0;
-			ctrl->maximum = 255;
-			ctrl->step = 1;
-			ctrl->default_value = 128;
-			ctrl->flags = 0;
-			break;
-		case V4L2_CID_HUE:
-			ctrl->type = V4L2_CTRL_TYPE_INTEGER;
-			strncpy(ctrl->name, "Hue", sizeof(ctrl->name));
-			ctrl->minimum = 0;
-			ctrl->maximum = 255;
-			ctrl->step = 1;
-			ctrl->default_value = 128;
-			ctrl->flags = 0;
-			break;
-		}
-		break;
-	}
-	case VIDIOC_S_CTRL:
-	{
-		struct v4l2_control *ctrl = arg;
-
-		switch (ctrl->id) {
-		case V4L2_CID_BRIGHTNESS:
-			if (ctrl->value > 255)
-				dec->brightness = 255;
-			else if (ctrl->value < 0)
-				dec->brightness = 0;
-			else
-				dec->brightness = ctrl->value;
-			write_reg(client, 0x12, dec->brightness, dec->channel);
-			break;
-		case V4L2_CID_CONTRAST:
-			if (ctrl->value > 255)
-				dec->contrast = 255;
-			else if (ctrl->value < 0)
-				dec->contrast = 0;
-			else
-				dec->contrast = ctrl->value;
-			write_reg(client, 0x11, dec->contrast, dec->channel);
-			break;
-		case V4L2_CID_SATURATION:
-			if (ctrl->value > 255)
-				dec->saturation = 255;
-			else if (ctrl->value < 0)
-				dec->saturation = 0;
-			else
-				dec->saturation = ctrl->value;
-			write_reg(client, 0x10, dec->saturation, dec->channel);
-			break;
-		case V4L2_CID_HUE:
-			if (ctrl->value > 255)
-				dec->hue = 255;
-			else if (ctrl->value < 0)
-				dec->hue = 0;
-			else
-				dec->hue = ctrl->value;
-			write_reg(client, 0x0f, dec->hue, dec->channel);
-			break;
-		}
-		break;
-	}
-	case VIDIOC_G_CTRL:
-	{
-		struct v4l2_control *ctrl = arg;
-
-		switch (ctrl->id) {
-		case V4L2_CID_BRIGHTNESS:
-			ctrl->value = dec->brightness;
-			break;
-		case V4L2_CID_CONTRAST:
-			ctrl->value = dec->contrast;
-			break;
-		case V4L2_CID_SATURATION:
-			ctrl->value = dec->saturation;
-			break;
-		case V4L2_CID_HUE:
-			ctrl->value = dec->hue;
-			break;
-		}
-		break;
-	}
-	default:
-		break;
-	}
-	return 0;
-}
-
-static int wis_tw2804_probe(struct i2c_client *client,
-			    const struct i2c_device_id *id)
-{
-	struct i2c_adapter *adapter = client->adapter;
-	struct wis_tw2804 *dec;
-
-	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
-		return -ENODEV;
-
-	dec = kmalloc(sizeof(struct wis_tw2804), GFP_KERNEL);
-	if (dec == NULL)
-		return -ENOMEM;
-
-	dec->channel = -1;
-	dec->norm = V4L2_STD_NTSC;
-	dec->brightness = 128;
-	dec->contrast = 128;
-	dec->saturation = 128;
-	dec->hue = 128;
-	i2c_set_clientdata(client, dec);
-
-	dev_dbg(&client->dev, "creating TW2804 at address %d on %s\n",
-		client->addr, adapter->name);
-
-	return 0;
-}
-
-static int wis_tw2804_remove(struct i2c_client *client)
-{
-	struct wis_tw2804 *dec = i2c_get_clientdata(client);
-
-	kfree(dec);
-	return 0;
-}
-
-static const struct i2c_device_id wis_tw2804_id[] = {
-	{ "wis_tw2804", 0 },
-	{ }
-};
-MODULE_DEVICE_TABLE(i2c, wis_tw2804_id);
-
-static struct i2c_driver wis_tw2804_driver = {
-	.driver = {
-		.name	= "WIS TW2804 I2C driver",
-	},
-	.probe		= wis_tw2804_probe,
-	.remove		= wis_tw2804_remove,
-	.command	= wis_tw2804_command,
-	.id_table	= wis_tw2804_id,
-};
-
-module_i2c_driver(wis_tw2804_driver);
-
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/media/go7007/wis-tw9903.c b/drivers/staging/media/go7007/wis-tw9903.c
deleted file mode 100644
index 684ca37..0000000
--- a/drivers/staging/media/go7007/wis-tw9903.c
+++ /dev/null
@@ -1,328 +0,0 @@
-/*
- * Copyright (C) 2005-2006 Micronas USA 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., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/i2c.h>
-#include <linux/videodev2.h>
-#include <linux/ioctl.h>
-#include <linux/slab.h>
-
-#include "wis-i2c.h"
-
-struct wis_tw9903 {
-	int norm;
-	int brightness;
-	int contrast;
-	int hue;
-};
-
-static u8 initial_registers[] = {
-	0x02, 0x44, /* input 1, composite */
-	0x03, 0x92, /* correct digital format */
-	0x04, 0x00,
-	0x05, 0x80, /* or 0x00 for PAL */
-	0x06, 0x40, /* second internal current reference */
-	0x07, 0x02, /* window */
-	0x08, 0x14, /* window */
-	0x09, 0xf0, /* window */
-	0x0a, 0x81, /* window */
-	0x0b, 0xd0, /* window */
-	0x0c, 0x8c,
-	0x0d, 0x00, /* scaling */
-	0x0e, 0x11, /* scaling */
-	0x0f, 0x00, /* scaling */
-	0x10, 0x00, /* brightness */
-	0x11, 0x60, /* contrast */
-	0x12, 0x01, /* sharpness */
-	0x13, 0x7f, /* U gain */
-	0x14, 0x5a, /* V gain */
-	0x15, 0x00, /* hue */
-	0x16, 0xc3, /* sharpness */
-	0x18, 0x00,
-	0x19, 0x58, /* vbi */
-	0x1a, 0x80,
-	0x1c, 0x0f, /* video norm */
-	0x1d, 0x7f, /* video norm */
-	0x20, 0xa0, /* clamping gain (working 0x50) */
-	0x21, 0x22,
-	0x22, 0xf0,
-	0x23, 0xfe,
-	0x24, 0x3c,
-	0x25, 0x38,
-	0x26, 0x44,
-	0x27, 0x20,
-	0x28, 0x00,
-	0x29, 0x15,
-	0x2a, 0xa0,
-	0x2b, 0x44,
-	0x2c, 0x37,
-	0x2d, 0x00,
-	0x2e, 0xa5, /* burst PLL control (working: a9) */
-	0x2f, 0xe0, /* 0xea is blue test frame -- 0xe0 for normal */
-	0x31, 0x00,
-	0x33, 0x22,
-	0x34, 0x11,
-	0x35, 0x35,
-	0x3b, 0x05,
-	0x06, 0xc0, /* reset device */
-	0x00, 0x00, /* Terminator (reg 0x00 is read-only) */
-};
-
-static int write_reg(struct i2c_client *client, u8 reg, u8 value)
-{
-	return i2c_smbus_write_byte_data(client, reg, value);
-}
-
-static int write_regs(struct i2c_client *client, u8 *regs)
-{
-	int i;
-
-	for (i = 0; regs[i] != 0x00; i += 2)
-		if (i2c_smbus_write_byte_data(client, regs[i], regs[i + 1]) < 0)
-			return -1;
-	return 0;
-}
-
-static int wis_tw9903_command(struct i2c_client *client,
-				unsigned int cmd, void *arg)
-{
-	struct wis_tw9903 *dec = i2c_get_clientdata(client);
-
-	switch (cmd) {
-	case VIDIOC_S_INPUT:
-	{
-		int *input = arg;
-
-		i2c_smbus_write_byte_data(client, 0x02, 0x40 | (*input << 1));
-		break;
-	}
-#if 0
-	/* The scaler on this thing seems to be horribly broken */
-	case DECODER_SET_RESOLUTION:
-	{
-		struct video_decoder_resolution *res = arg;
-		/*int hscale = 256 * 720 / res->width;*/
-		int hscale = 256 * 720 / (res->width - (res->width > 704 ? 0 : 8));
-		int vscale = 256 * (dec->norm & V4L2_STD_NTSC ?  240 : 288)
-				/ res->height;
-		u8 regs[] = {
-			0x0d, vscale & 0xff,
-			0x0f, hscale & 0xff,
-			0x0e, ((vscale & 0xf00) >> 4) | ((hscale & 0xf00) >> 8),
-			0x06, 0xc0, /* reset device */
-			0,	0,
-		};
-		dev_dbg(&client->dev, "vscale is %04x, hscale is %04x\n",
-			vscale, hscale);
-		/*write_regs(client, regs);*/
-		break;
-	}
-#endif
-	case VIDIOC_S_STD:
-	{
-		v4l2_std_id *input = arg;
-		u8 regs[] = {
-			0x05, *input & V4L2_STD_NTSC ? 0x80 : 0x00,
-			0x07, *input & V4L2_STD_NTSC ? 0x02 : 0x12,
-			0x08, *input & V4L2_STD_NTSC ? 0x14 : 0x18,
-			0x09, *input & V4L2_STD_NTSC ? 0xf0 : 0x20,
-			0,	0,
-		};
-		write_regs(client, regs);
-		dec->norm = *input;
-		break;
-	}
-	case VIDIOC_QUERYCTRL:
-	{
-		struct v4l2_queryctrl *ctrl = arg;
-
-		switch (ctrl->id) {
-		case V4L2_CID_BRIGHTNESS:
-			ctrl->type = V4L2_CTRL_TYPE_INTEGER;
-			strncpy(ctrl->name, "Brightness", sizeof(ctrl->name));
-			ctrl->minimum = -128;
-			ctrl->maximum = 127;
-			ctrl->step = 1;
-			ctrl->default_value = 0x00;
-			ctrl->flags = 0;
-			break;
-		case V4L2_CID_CONTRAST:
-			ctrl->type = V4L2_CTRL_TYPE_INTEGER;
-			strncpy(ctrl->name, "Contrast", sizeof(ctrl->name));
-			ctrl->minimum = 0;
-			ctrl->maximum = 255;
-			ctrl->step = 1;
-			ctrl->default_value = 0x60;
-			ctrl->flags = 0;
-			break;
-#if 0
-		/* I don't understand how the Chroma Gain registers work... */
-		case V4L2_CID_SATURATION:
-			ctrl->type = V4L2_CTRL_TYPE_INTEGER;
-			strncpy(ctrl->name, "Saturation", sizeof(ctrl->name));
-			ctrl->minimum = 0;
-			ctrl->maximum = 127;
-			ctrl->step = 1;
-			ctrl->default_value = 64;
-			ctrl->flags = 0;
-			break;
-#endif
-		case V4L2_CID_HUE:
-			ctrl->type = V4L2_CTRL_TYPE_INTEGER;
-			strncpy(ctrl->name, "Hue", sizeof(ctrl->name));
-			ctrl->minimum = -128;
-			ctrl->maximum = 127;
-			ctrl->step = 1;
-			ctrl->default_value = 0;
-			ctrl->flags = 0;
-			break;
-		}
-		break;
-	}
-	case VIDIOC_S_CTRL:
-	{
-		struct v4l2_control *ctrl = arg;
-
-		switch (ctrl->id) {
-		case V4L2_CID_BRIGHTNESS:
-			if (ctrl->value > 127)
-				dec->brightness = 127;
-			else if (ctrl->value < -128)
-				dec->brightness = -128;
-			else
-				dec->brightness = ctrl->value;
-			write_reg(client, 0x10, dec->brightness);
-			break;
-		case V4L2_CID_CONTRAST:
-			if (ctrl->value > 255)
-				dec->contrast = 255;
-			else if (ctrl->value < 0)
-				dec->contrast = 0;
-			else
-				dec->contrast = ctrl->value;
-			write_reg(client, 0x11, dec->contrast);
-			break;
-#if 0
-		case V4L2_CID_SATURATION:
-			if (ctrl->value > 127)
-				dec->saturation = 127;
-			else if (ctrl->value < 0)
-				dec->saturation = 0;
-			else
-				dec->saturation = ctrl->value;
-			/*write_reg(client, 0x0c, dec->saturation);*/
-			break;
-#endif
-		case V4L2_CID_HUE:
-			if (ctrl->value > 127)
-				dec->hue = 127;
-			else if (ctrl->value < -128)
-				dec->hue = -128;
-			else
-				dec->hue = ctrl->value;
-			write_reg(client, 0x15, dec->hue);
-			break;
-		}
-		break;
-	}
-	case VIDIOC_G_CTRL:
-	{
-		struct v4l2_control *ctrl = arg;
-
-		switch (ctrl->id) {
-		case V4L2_CID_BRIGHTNESS:
-			ctrl->value = dec->brightness;
-			break;
-		case V4L2_CID_CONTRAST:
-			ctrl->value = dec->contrast;
-			break;
-#if 0
-		case V4L2_CID_SATURATION:
-			ctrl->value = dec->saturation;
-			break;
-#endif
-		case V4L2_CID_HUE:
-			ctrl->value = dec->hue;
-			break;
-		}
-		break;
-	}
-	default:
-		break;
-	}
-	return 0;
-}
-
-static int wis_tw9903_probe(struct i2c_client *client,
-			    const struct i2c_device_id *id)
-{
-	struct i2c_adapter *adapter = client->adapter;
-	struct wis_tw9903 *dec;
-
-	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
-		return -ENODEV;
-
-	dec = kmalloc(sizeof(struct wis_tw9903), GFP_KERNEL);
-	if (dec == NULL)
-		return -ENOMEM;
-
-	dec->norm = V4L2_STD_NTSC;
-	dec->brightness = 0;
-	dec->contrast = 0x60;
-	dec->hue = 0;
-	i2c_set_clientdata(client, dec);
-
-	dev_dbg(&client->dev, "initializing TW9903 at address %d on %s\n",
-		client->addr, adapter->name);
-
-	if (write_regs(client, initial_registers) < 0) {
-		dev_err(&client->dev, "error initializing TW9903\n");
-		kfree(dec);
-		return -ENODEV;
-	}
-
-	return 0;
-}
-
-static int wis_tw9903_remove(struct i2c_client *client)
-{
-	struct wis_tw9903 *dec = i2c_get_clientdata(client);
-
-	kfree(dec);
-	return 0;
-}
-
-static const struct i2c_device_id wis_tw9903_id[] = {
-	{ "wis_tw9903", 0 },
-	{ }
-};
-MODULE_DEVICE_TABLE(i2c, wis_tw9903_id);
-
-static struct i2c_driver wis_tw9903_driver = {
-	.driver = {
-		.name	= "WIS TW9903 I2C driver",
-	},
-	.probe		= wis_tw9903_probe,
-	.remove		= wis_tw9903_remove,
-	.command	= wis_tw9903_command,
-	.id_table	= wis_tw9903_id,
-};
-
-module_i2c_driver(wis_tw9903_driver);
-
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/media/go7007/wis-uda1342.c b/drivers/staging/media/go7007/wis-uda1342.c
deleted file mode 100644
index 582ea12..0000000
--- a/drivers/staging/media/go7007/wis-uda1342.c
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2005-2006 Micronas USA 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., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/i2c.h>
-#include <linux/videodev2.h>
-#include <media/tvaudio.h>
-#include <media/v4l2-common.h>
-
-#include "wis-i2c.h"
-
-static int write_reg(struct i2c_client *client, int reg, int value)
-{
-	/* UDA1342 wants MSB first, but SMBus sends LSB first */
-	i2c_smbus_write_word_data(client, reg, swab16(value));
-	return 0;
-}
-
-static int wis_uda1342_command(struct i2c_client *client,
-				unsigned int cmd, void *arg)
-{
-	switch (cmd) {
-	case VIDIOC_S_AUDIO:
-	{
-		int *inp = arg;
-
-		switch (*inp) {
-		case TVAUDIO_INPUT_TUNER:
-			write_reg(client, 0x00, 0x1441); /* select input 2 */
-			break;
-		case TVAUDIO_INPUT_EXTERN:
-			write_reg(client, 0x00, 0x1241); /* select input 1 */
-			break;
-		default:
-			dev_err(&client->dev, "input %d not supported\n",
-				*inp);
-			break;
-		}
-		break;
-	}
-	default:
-		break;
-	}
-	return 0;
-}
-
-static int wis_uda1342_probe(struct i2c_client *client,
-			     const struct i2c_device_id *id)
-{
-	struct i2c_adapter *adapter = client->adapter;
-
-	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA))
-		return -ENODEV;
-
-	dev_dbg(&client->dev, "initializing UDA1342 at address %d on %s\n",
-		client->addr, adapter->name);
-
-	write_reg(client, 0x00, 0x8000); /* reset registers */
-	write_reg(client, 0x00, 0x1241); /* select input 1 */
-
-	return 0;
-}
-
-static int wis_uda1342_remove(struct i2c_client *client)
-{
-	return 0;
-}
-
-static const struct i2c_device_id wis_uda1342_id[] = {
-	{ "wis_uda1342", 0 },
-	{ }
-};
-MODULE_DEVICE_TABLE(i2c, wis_uda1342_id);
-
-static struct i2c_driver wis_uda1342_driver = {
-	.driver = {
-		.name	= "WIS UDA1342 I2C driver",
-	},
-	.probe		= wis_uda1342_probe,
-	.remove		= wis_uda1342_remove,
-	.command	= wis_uda1342_command,
-	.id_table	= wis_uda1342_id,
-};
-
-module_i2c_driver(wis_uda1342_driver);
-
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/media/lirc/lirc_sir.c b/drivers/staging/media/lirc/lirc_sir.c
index 63a554c..f781c53 100644
--- a/drivers/staging/media/lirc/lirc_sir.c
+++ b/drivers/staging/media/lirc/lirc_sir.c
@@ -787,12 +787,6 @@ static int init_hardware(void)
 	spin_lock_irqsave(&hardware_lock, flags);
 	/* reset UART */
 #ifdef LIRC_ON_SA1100
-#ifdef CONFIG_SA1100_BITSY
-	if (machine_is_bitsy()) {
-		pr_info("Power on IR module\n");
-		set_bitsy_egpio(EGPIO_BITSY_IR_ON);
-	}
-#endif
 #ifdef CONFIG_SA1100_COLLIE
 	sa1100_irda_set_power_collie(3);	/* power on */
 #endif
@@ -942,10 +936,6 @@ static void drop_hardware(void)
 	Ser2UTCR3 = sr.utcr3;
 
 	Ser2HSCR0 = sr.hscr0;
-#ifdef CONFIG_SA1100_BITSY
-	if (machine_is_bitsy())
-		clr_bitsy_egpio(EGPIO_BITSY_IR_ON);
-#endif
 #ifdef CONFIG_SA1100_COLLIE
 	sa1100_irda_set_power_collie(0);	/* power off */
 #endif
diff --git a/drivers/staging/media/solo6x10/Kconfig b/drivers/staging/media/solo6x10/Kconfig
index 63352de..ec32776 100644
--- a/drivers/staging/media/solo6x10/Kconfig
+++ b/drivers/staging/media/solo6x10/Kconfig
@@ -1,7 +1,8 @@
 config SOLO6X10
 	tristate "Softlogic 6x10 MPEG codec cards"
 	depends on PCI && VIDEO_DEV && SND && I2C
-	select VIDEOBUF_DMA_SG
+	select VIDEOBUF2_DMA_SG
+	select VIDEOBUF2_DMA_CONTIG
 	select SND_PCM
 	---help---
 	  This driver supports the Softlogic based MPEG-4 and h.264 codec
diff --git a/drivers/staging/media/solo6x10/Makefile b/drivers/staging/media/solo6x10/Makefile
index 337e38c..7aae118 100644
--- a/drivers/staging/media/solo6x10/Makefile
+++ b/drivers/staging/media/solo6x10/Makefile
@@ -1,3 +1,5 @@
-solo6x10-y := core.o i2c.o p2m.o v4l2.o tw28.o gpio.o disp.o enc.o v4l2-enc.o g723.o
+solo6x10-y := solo6x10-core.o solo6x10-i2c.o solo6x10-p2m.o solo6x10-v4l2.o \
+		solo6x10-tw28.o solo6x10-gpio.o solo6x10-disp.o solo6x10-enc.o \
+		solo6x10-v4l2-enc.o solo6x10-g723.o solo6x10-eeprom.o
 
 obj-$(CONFIG_SOLO6X10) += solo6x10.o
diff --git a/drivers/staging/media/solo6x10/TODO b/drivers/staging/media/solo6x10/TODO
index 539f739..7b8db75 100644
--- a/drivers/staging/media/solo6x10/TODO
+++ b/drivers/staging/media/solo6x10/TODO
@@ -1,24 +1,15 @@
-TODO (staging => main):
-
-	* Motion detection flags need to be moved to v4l2
-	* Some private CIDs need to be moved to v4l2
-
-TODO (general):
-
-	* encoder on/off controls
-	* mpeg cid bitrate mode (vbr/cbr)
-	* mpeg cid bitrate/bitrate-peak
-	* mpeg encode of user data
-	* mpeg decode of user data
-	* switch between 4 frames/irq to 1 when using mjpeg (and then back
-	  when not)
-	* implement a CID control for motion areas/thresholds
-	* implement CID controls for mozaic areas
-	* allow for higher level of interval (for < 1 fps)
-	* sound:
-	  - implement playback via external sound jack
-	  - implement loopback of external sound jack with incoming audio?
-	  - implement pause/resume
-
-Plase send patches to Mauro Carvalho Chehab <mchehab@redhat.com> and Cc Ben Collins
-<bcollins@bluecherry.net>
+- batch up desc requests for more efficient use of p2m?
+- encoder on/off controls
+- mpeg cid bitrate mode (vbr/cbr)
+- mpeg cid bitrate/bitrate-peak
+- mpeg encode of user data
+- mpeg decode of user data
+- implement CID controls for mozaic areas
+
+- sound
+ - implement playback via external sound jack
+ - implement loopback of external sound jack with incoming audio?
+ - implement pause/resume (make use of in bc-server)
+
+Please send patches to the linux media list <linux-media@vger.kernel.org> and
+Cc Ismael Luceno <ismael.luceno@corp.bluecherry.net>.
diff --git a/drivers/staging/media/solo6x10/core.c b/drivers/staging/media/solo6x10/core.c
deleted file mode 100644
index fd83d6d..0000000
--- a/drivers/staging/media/solo6x10/core.c
+++ /dev/null
@@ -1,321 +0,0 @@
-/*
- * Copyright (C) 2010 Bluecherry, LLC www.bluecherrydvr.com
- * Copyright (C) 2010 Ben Collins <bcollins@bluecherry.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You 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/pci.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-#include <linux/videodev2.h>
-#include "solo6x10.h"
-#include "tw28.h"
-
-MODULE_DESCRIPTION("Softlogic 6x10 MP4/H.264 Encoder/Decoder V4L2/ALSA Driver");
-MODULE_AUTHOR("Ben Collins <bcollins@bluecherry.net>");
-MODULE_VERSION(SOLO6X10_VERSION);
-MODULE_LICENSE("GPL");
-
-void solo_irq_on(struct solo_dev *solo_dev, u32 mask)
-{
-	solo_dev->irq_mask |= mask;
-	solo_reg_write(solo_dev, SOLO_IRQ_ENABLE, solo_dev->irq_mask);
-}
-
-void solo_irq_off(struct solo_dev *solo_dev, u32 mask)
-{
-	solo_dev->irq_mask &= ~mask;
-	solo_reg_write(solo_dev, SOLO_IRQ_ENABLE, solo_dev->irq_mask);
-}
-
-/* XXX We should check the return value of the sub-device ISR's */
-static irqreturn_t solo_isr(int irq, void *data)
-{
-	struct solo_dev *solo_dev = data;
-	u32 status;
-	int i;
-
-	status = solo_reg_read(solo_dev, SOLO_IRQ_STAT);
-	if (!status)
-		return IRQ_NONE;
-
-	if (status & ~solo_dev->irq_mask) {
-		solo_reg_write(solo_dev, SOLO_IRQ_STAT,
-			       status & ~solo_dev->irq_mask);
-		status &= solo_dev->irq_mask;
-	}
-
-	if (status & SOLO_IRQ_PCI_ERR) {
-		u32 err = solo_reg_read(solo_dev, SOLO_PCI_ERR);
-		solo_p2m_error_isr(solo_dev, err);
-		solo_reg_write(solo_dev, SOLO_IRQ_STAT, SOLO_IRQ_PCI_ERR);
-	}
-
-	for (i = 0; i < SOLO_NR_P2M; i++)
-		if (status & SOLO_IRQ_P2M(i))
-			solo_p2m_isr(solo_dev, i);
-
-	if (status & SOLO_IRQ_IIC)
-		solo_i2c_isr(solo_dev);
-
-	if (status & SOLO_IRQ_VIDEO_IN)
-		solo_video_in_isr(solo_dev);
-
-	/* Call this first so enc gets detected flag set */
-	if (status & SOLO_IRQ_MOTION)
-		solo_motion_isr(solo_dev);
-
-	if (status & SOLO_IRQ_ENCODER)
-		solo_enc_v4l2_isr(solo_dev);
-
-	if (status & SOLO_IRQ_G723)
-		solo_g723_isr(solo_dev);
-
-	return IRQ_HANDLED;
-}
-
-static void free_solo_dev(struct solo_dev *solo_dev)
-{
-	struct pci_dev *pdev;
-
-	if (!solo_dev)
-		return;
-
-	pdev = solo_dev->pdev;
-
-	/* If we never initialized the PCI device, then nothing else
-	 * below here needs cleanup */
-	if (!pdev) {
-		kfree(solo_dev);
-		return;
-	}
-
-	/* Bring down the sub-devices first */
-	solo_g723_exit(solo_dev);
-	solo_enc_v4l2_exit(solo_dev);
-	solo_enc_exit(solo_dev);
-	solo_v4l2_exit(solo_dev);
-	solo_disp_exit(solo_dev);
-	solo_gpio_exit(solo_dev);
-	solo_p2m_exit(solo_dev);
-	solo_i2c_exit(solo_dev);
-
-	/* Now cleanup the PCI device */
-	if (solo_dev->reg_base) {
-		solo_irq_off(solo_dev, ~0);
-		pci_iounmap(pdev, solo_dev->reg_base);
-		free_irq(pdev->irq, solo_dev);
-	}
-
-	pci_release_regions(pdev);
-	pci_disable_device(pdev);
-	pci_set_drvdata(pdev, NULL);
-
-	kfree(solo_dev);
-}
-
-static int solo_pci_probe(struct pci_dev *pdev,
-				    const struct pci_device_id *id)
-{
-	struct solo_dev *solo_dev;
-	int ret;
-	int sdram;
-	u8 chip_id;
-	u32 reg;
-
-	solo_dev = kzalloc(sizeof(*solo_dev), GFP_KERNEL);
-	if (solo_dev == NULL)
-		return -ENOMEM;
-
-	solo_dev->pdev = pdev;
-	spin_lock_init(&solo_dev->reg_io_lock);
-	pci_set_drvdata(pdev, solo_dev);
-
-	ret = pci_enable_device(pdev);
-	if (ret)
-		goto fail_probe;
-
-	pci_set_master(pdev);
-
-	ret = pci_request_regions(pdev, SOLO6X10_NAME);
-	if (ret)
-		goto fail_probe;
-
-	solo_dev->reg_base = pci_ioremap_bar(pdev, 0);
-	if (solo_dev->reg_base == NULL) {
-		ret = -ENOMEM;
-		goto fail_probe;
-	}
-
-	chip_id = solo_reg_read(solo_dev, SOLO_CHIP_OPTION) &
-					SOLO_CHIP_ID_MASK;
-	switch (chip_id) {
-	case 7:
-		solo_dev->nr_chans = 16;
-		solo_dev->nr_ext = 5;
-		break;
-	case 6:
-		solo_dev->nr_chans = 8;
-		solo_dev->nr_ext = 2;
-		break;
-	default:
-		dev_warn(&pdev->dev, "Invalid chip_id 0x%02x, "
-			 "defaulting to 4 channels\n",
-			 chip_id);
-	case 5:
-		solo_dev->nr_chans = 4;
-		solo_dev->nr_ext = 1;
-	}
-
-	solo_dev->flags = id->driver_data;
-
-	/* Disable all interrupts to start */
-	solo_irq_off(solo_dev, ~0);
-
-	reg = SOLO_SYS_CFG_SDRAM64BIT;
-	/* Initial global settings */
-	if (!(solo_dev->flags & FLAGS_6110))
-		reg |= SOLO6010_SYS_CFG_INPUTDIV(25) |
-			SOLO6010_SYS_CFG_FEEDBACKDIV((SOLO_CLOCK_MHZ * 2) - 2) |
-			SOLO6010_SYS_CFG_OUTDIV(3);
-	solo_reg_write(solo_dev, SOLO_SYS_CFG, reg);
-
-	if (solo_dev->flags & FLAGS_6110) {
-		u32 sys_clock_MHz = SOLO_CLOCK_MHZ;
-		u32 pll_DIVQ;
-		u32 pll_DIVF;
-
-		if (sys_clock_MHz < 125) {
-			pll_DIVQ = 3;
-			pll_DIVF = (sys_clock_MHz * 4) / 3;
-		} else {
-			pll_DIVQ = 2;
-			pll_DIVF = (sys_clock_MHz * 2) / 3;
-		}
-
-		solo_reg_write(solo_dev, SOLO6110_PLL_CONFIG,
-			       SOLO6110_PLL_RANGE_5_10MHZ |
-			       SOLO6110_PLL_DIVR(9) |
-			       SOLO6110_PLL_DIVQ_EXP(pll_DIVQ) |
-			       SOLO6110_PLL_DIVF(pll_DIVF) | SOLO6110_PLL_FSEN);
-		mdelay(1);      /* PLL Locking time (1ms) */
-
-		solo_reg_write(solo_dev, SOLO_DMA_CTRL1, 3 << 8); /* ? */
-	} else
-		solo_reg_write(solo_dev, SOLO_DMA_CTRL1, 1 << 8); /* ? */
-
-	solo_reg_write(solo_dev, SOLO_TIMER_CLOCK_NUM, SOLO_CLOCK_MHZ - 1);
-
-	/* PLL locking time of 1ms */
-	mdelay(1);
-
-	ret = request_irq(pdev->irq, solo_isr, IRQF_SHARED, SOLO6X10_NAME,
-			  solo_dev);
-	if (ret)
-		goto fail_probe;
-
-	/* Handle this from the start */
-	solo_irq_on(solo_dev, SOLO_IRQ_PCI_ERR);
-
-	ret = solo_i2c_init(solo_dev);
-	if (ret)
-		goto fail_probe;
-
-	/* Setup the DMA engine */
-	sdram = (solo_dev->nr_chans >= 8) ? 2 : 1;
-	solo_reg_write(solo_dev, SOLO_DMA_CTRL,
-		       SOLO_DMA_CTRL_REFRESH_CYCLE(1) |
-		       SOLO_DMA_CTRL_SDRAM_SIZE(sdram) |
-		       SOLO_DMA_CTRL_SDRAM_CLK_INVERT |
-		       SOLO_DMA_CTRL_READ_CLK_SELECT |
-		       SOLO_DMA_CTRL_LATENCY(1));
-
-	ret = solo_p2m_init(solo_dev);
-	if (ret)
-		goto fail_probe;
-
-	ret = solo_disp_init(solo_dev);
-	if (ret)
-		goto fail_probe;
-
-	ret = solo_gpio_init(solo_dev);
-	if (ret)
-		goto fail_probe;
-
-	ret = solo_tw28_init(solo_dev);
-	if (ret)
-		goto fail_probe;
-
-	ret = solo_v4l2_init(solo_dev);
-	if (ret)
-		goto fail_probe;
-
-	ret = solo_enc_init(solo_dev);
-	if (ret)
-		goto fail_probe;
-
-	ret = solo_enc_v4l2_init(solo_dev);
-	if (ret)
-		goto fail_probe;
-
-	ret = solo_g723_init(solo_dev);
-	if (ret)
-		goto fail_probe;
-
-	return 0;
-
-fail_probe:
-	free_solo_dev(solo_dev);
-	return ret;
-}
-
-static void solo_pci_remove(struct pci_dev *pdev)
-{
-	struct solo_dev *solo_dev = pci_get_drvdata(pdev);
-
-	free_solo_dev(solo_dev);
-}
-
-static struct pci_device_id solo_id_table[] = {
-	/* 6010 based cards */
-	{PCI_DEVICE(PCI_VENDOR_ID_SOFTLOGIC, PCI_DEVICE_ID_SOLO6010)},
-	{PCI_DEVICE(PCI_VENDOR_ID_SOFTLOGIC, PCI_DEVICE_ID_SOLO6110),
-	 .driver_data = FLAGS_6110},
-	{PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_NEUSOLO_4)},
-	{PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_NEUSOLO_9)},
-	{PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_NEUSOLO_16)},
-	{PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_SOLO_4)},
-	{PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_SOLO_9)},
-	{PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_SOLO_16)},
-	/* 6110 based cards */
-	{PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_6110_4)},
-	{PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_6110_8)},
-	{PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_6110_16)},
-	{0,}
-};
-
-MODULE_DEVICE_TABLE(pci, solo_id_table);
-
-static struct pci_driver solo_pci_driver = {
-	.name = SOLO6X10_NAME,
-	.id_table = solo_id_table,
-	.probe = solo_pci_probe,
-	.remove = solo_pci_remove,
-};
-
-module_pci_driver(solo_pci_driver);
diff --git a/drivers/staging/media/solo6x10/disp.c b/drivers/staging/media/solo6x10/disp.c
deleted file mode 100644
index 884c0eb..0000000
--- a/drivers/staging/media/solo6x10/disp.c
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * Copyright (C) 2010 Bluecherry, LLC www.bluecherrydvr.com
- * Copyright (C) 2010 Ben Collins <bcollins@bluecherry.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You 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/videodev2.h>
-#include <media/v4l2-ioctl.h>
-#include "solo6x10.h"
-
-#define SOLO_VCLK_DELAY			3
-#define SOLO_PROGRESSIVE_VSIZE		1024
-
-#define SOLO_MOT_THRESH_W		64
-#define SOLO_MOT_THRESH_H		64
-#define SOLO_MOT_THRESH_SIZE		8192
-#define SOLO_MOT_THRESH_REAL		(SOLO_MOT_THRESH_W * SOLO_MOT_THRESH_H)
-#define SOLO_MOT_FLAG_SIZE		512
-#define SOLO_MOT_FLAG_AREA		(SOLO_MOT_FLAG_SIZE * 32)
-
-static unsigned video_type;
-module_param(video_type, uint, 0644);
-MODULE_PARM_DESC(video_type, "video_type (0 = NTSC/Default, 1 = PAL)");
-
-static void solo_vin_config(struct solo_dev *solo_dev)
-{
-	solo_dev->vin_hstart = 8;
-	solo_dev->vin_vstart = 2;
-
-	solo_reg_write(solo_dev, SOLO_SYS_VCLK,
-		       SOLO_VCLK_SELECT(2) |
-		       SOLO_VCLK_VIN1415_DELAY(SOLO_VCLK_DELAY) |
-		       SOLO_VCLK_VIN1213_DELAY(SOLO_VCLK_DELAY) |
-		       SOLO_VCLK_VIN1011_DELAY(SOLO_VCLK_DELAY) |
-		       SOLO_VCLK_VIN0809_DELAY(SOLO_VCLK_DELAY) |
-		       SOLO_VCLK_VIN0607_DELAY(SOLO_VCLK_DELAY) |
-		       SOLO_VCLK_VIN0405_DELAY(SOLO_VCLK_DELAY) |
-		       SOLO_VCLK_VIN0203_DELAY(SOLO_VCLK_DELAY) |
-		       SOLO_VCLK_VIN0001_DELAY(SOLO_VCLK_DELAY));
-
-	solo_reg_write(solo_dev, SOLO_VI_ACT_I_P,
-		       SOLO_VI_H_START(solo_dev->vin_hstart) |
-		       SOLO_VI_V_START(solo_dev->vin_vstart) |
-		       SOLO_VI_V_STOP(solo_dev->vin_vstart +
-				      solo_dev->video_vsize));
-
-	solo_reg_write(solo_dev, SOLO_VI_ACT_I_S,
-		       SOLO_VI_H_START(solo_dev->vout_hstart) |
-		       SOLO_VI_V_START(solo_dev->vout_vstart) |
-		       SOLO_VI_V_STOP(solo_dev->vout_vstart +
-				      solo_dev->video_vsize));
-
-	solo_reg_write(solo_dev, SOLO_VI_ACT_P,
-		       SOLO_VI_H_START(0) |
-		       SOLO_VI_V_START(1) |
-		       SOLO_VI_V_STOP(SOLO_PROGRESSIVE_VSIZE));
-
-	solo_reg_write(solo_dev, SOLO_VI_CH_FORMAT,
-		       SOLO_VI_FD_SEL_MASK(0) | SOLO_VI_PROG_MASK(0));
-
-	solo_reg_write(solo_dev, SOLO_VI_FMT_CFG, 0);
-	solo_reg_write(solo_dev, SOLO_VI_PAGE_SW, 2);
-
-	if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) {
-		solo_reg_write(solo_dev, SOLO_VI_PB_CONFIG,
-			       SOLO_VI_PB_USER_MODE);
-		solo_reg_write(solo_dev, SOLO_VI_PB_RANGE_HV,
-			       SOLO_VI_PB_HSIZE(858) | SOLO_VI_PB_VSIZE(246));
-		solo_reg_write(solo_dev, SOLO_VI_PB_ACT_V,
-			       SOLO_VI_PB_VSTART(4) |
-			       SOLO_VI_PB_VSTOP(4 + 240));
-	} else {
-		solo_reg_write(solo_dev, SOLO_VI_PB_CONFIG,
-			       SOLO_VI_PB_USER_MODE | SOLO_VI_PB_PAL);
-		solo_reg_write(solo_dev, SOLO_VI_PB_RANGE_HV,
-			       SOLO_VI_PB_HSIZE(864) | SOLO_VI_PB_VSIZE(294));
-		solo_reg_write(solo_dev, SOLO_VI_PB_ACT_V,
-			       SOLO_VI_PB_VSTART(4) |
-			       SOLO_VI_PB_VSTOP(4 + 288));
-	}
-	solo_reg_write(solo_dev, SOLO_VI_PB_ACT_H, SOLO_VI_PB_HSTART(16) |
-		       SOLO_VI_PB_HSTOP(16 + 720));
-}
-
-static void solo_disp_config(struct solo_dev *solo_dev)
-{
-	solo_dev->vout_hstart = 6;
-	solo_dev->vout_vstart = 8;
-
-	solo_reg_write(solo_dev, SOLO_VO_BORDER_LINE_COLOR,
-		       (0xa0 << 24) | (0x88 << 16) | (0xa0 << 8) | 0x88);
-	solo_reg_write(solo_dev, SOLO_VO_BORDER_FILL_COLOR,
-		       (0x10 << 24) | (0x8f << 16) | (0x10 << 8) | 0x8f);
-	solo_reg_write(solo_dev, SOLO_VO_BKG_COLOR,
-		       (16 << 24) | (128 << 16) | (16 << 8) | 128);
-
-	solo_reg_write(solo_dev, SOLO_VO_FMT_ENC,
-		       solo_dev->video_type |
-		       SOLO_VO_USER_COLOR_SET_NAV |
-		       SOLO_VO_NA_COLOR_Y(0) |
-		       SOLO_VO_NA_COLOR_CB(0) |
-		       SOLO_VO_NA_COLOR_CR(0));
-
-	solo_reg_write(solo_dev, SOLO_VO_ACT_H,
-		       SOLO_VO_H_START(solo_dev->vout_hstart) |
-		       SOLO_VO_H_STOP(solo_dev->vout_hstart +
-				      solo_dev->video_hsize));
-
-	solo_reg_write(solo_dev, SOLO_VO_ACT_V,
-		       SOLO_VO_V_START(solo_dev->vout_vstart) |
-		       SOLO_VO_V_STOP(solo_dev->vout_vstart +
-				      solo_dev->video_vsize));
-
-	solo_reg_write(solo_dev, SOLO_VO_RANGE_HV,
-		       SOLO_VO_H_LEN(solo_dev->video_hsize) |
-		       SOLO_VO_V_LEN(solo_dev->video_vsize));
-
-	solo_reg_write(solo_dev, SOLO_VI_WIN_SW, 5);
-
-	solo_reg_write(solo_dev, SOLO_VO_DISP_CTRL, SOLO_VO_DISP_ON |
-		       SOLO_VO_DISP_ERASE_COUNT(8) |
-		       SOLO_VO_DISP_BASE(SOLO_DISP_EXT_ADDR));
-
-	solo_reg_write(solo_dev, SOLO_VO_DISP_ERASE, SOLO_VO_DISP_ERASE_ON);
-
-	/* Enable channels we support */
-	solo_reg_write(solo_dev, SOLO_VI_CH_ENA, (1 << solo_dev->nr_chans) - 1);
-
-	/* Disable the watchdog */
-	solo_reg_write(solo_dev, SOLO_WATCHDOG, 0);
-}
-
-static int solo_dma_vin_region(struct solo_dev *solo_dev, u32 off,
-			       u16 val, int reg_size)
-{
-	u16 buf[64];
-	int i;
-	int ret = 0;
-
-	for (i = 0; i < sizeof(buf) >> 1; i++)
-		buf[i] = val;
-
-	for (i = 0; i < reg_size; i += sizeof(buf))
-		ret |= solo_p2m_dma(solo_dev, SOLO_P2M_DMA_ID_VIN, 1, buf,
-				    SOLO_MOTION_EXT_ADDR(solo_dev) + off + i,
-				    sizeof(buf));
-
-	return ret;
-}
-
-void solo_set_motion_threshold(struct solo_dev *solo_dev, u8 ch, u16 val)
-{
-	if (ch > solo_dev->nr_chans)
-		return;
-
-	solo_dma_vin_region(solo_dev, SOLO_MOT_FLAG_AREA +
-			    (ch * SOLO_MOT_THRESH_SIZE * 2),
-			    val, SOLO_MOT_THRESH_REAL);
-}
-
-/* First 8k is motion flag (512 bytes * 16). Following that is an 8k+8k
- * threshold and working table for each channel. Atleast that's what the
- * spec says. However, this code (take from rdk) has some mystery 8k
- * block right after the flag area, before the first thresh table. */
-static void solo_motion_config(struct solo_dev *solo_dev)
-{
-	int i;
-
-	for (i = 0; i < solo_dev->nr_chans; i++) {
-		/* Clear motion flag area */
-		solo_dma_vin_region(solo_dev, i * SOLO_MOT_FLAG_SIZE, 0x0000,
-				    SOLO_MOT_FLAG_SIZE);
-
-		/* Clear working cache table */
-		solo_dma_vin_region(solo_dev, SOLO_MOT_FLAG_AREA +
-				    SOLO_MOT_THRESH_SIZE +
-				    (i * SOLO_MOT_THRESH_SIZE * 2),
-				    0x0000, SOLO_MOT_THRESH_REAL);
-
-		/* Set default threshold table */
-		solo_set_motion_threshold(solo_dev, i, SOLO_DEF_MOT_THRESH);
-	}
-
-	/* Default motion settings */
-	solo_reg_write(solo_dev, SOLO_VI_MOT_ADR, SOLO_VI_MOTION_EN(0) |
-		       (SOLO_MOTION_EXT_ADDR(solo_dev) >> 16));
-	solo_reg_write(solo_dev, SOLO_VI_MOT_CTRL,
-		       SOLO_VI_MOTION_FRAME_COUNT(3) |
-		       SOLO_VI_MOTION_SAMPLE_LENGTH(solo_dev->video_hsize / 16)
-		       | /* SOLO_VI_MOTION_INTR_START_STOP | */
-		       SOLO_VI_MOTION_SAMPLE_COUNT(10));
-
-	solo_reg_write(solo_dev, SOLO_VI_MOTION_BORDER, 0);
-	solo_reg_write(solo_dev, SOLO_VI_MOTION_BAR, 0);
-}
-
-int solo_disp_init(struct solo_dev *solo_dev)
-{
-	int i;
-
-	solo_dev->video_hsize = 704;
-	if (video_type == 0) {
-		solo_dev->video_type = SOLO_VO_FMT_TYPE_NTSC;
-		solo_dev->video_vsize = 240;
-		solo_dev->fps = 30;
-	} else {
-		solo_dev->video_type = SOLO_VO_FMT_TYPE_PAL;
-		solo_dev->video_vsize = 288;
-		solo_dev->fps = 25;
-	}
-
-	solo_vin_config(solo_dev);
-	solo_motion_config(solo_dev);
-	solo_disp_config(solo_dev);
-
-	for (i = 0; i < solo_dev->nr_chans; i++)
-		solo_reg_write(solo_dev, SOLO_VI_WIN_ON(i), 1);
-
-	return 0;
-}
-
-void solo_disp_exit(struct solo_dev *solo_dev)
-{
-	int i;
-
-	solo_irq_off(solo_dev, SOLO_IRQ_MOTION);
-
-	solo_reg_write(solo_dev, SOLO_VO_DISP_CTRL, 0);
-	solo_reg_write(solo_dev, SOLO_VO_ZOOM_CTRL, 0);
-	solo_reg_write(solo_dev, SOLO_VO_FREEZE_CTRL, 0);
-
-	for (i = 0; i < solo_dev->nr_chans; i++) {
-		solo_reg_write(solo_dev, SOLO_VI_WIN_CTRL0(i), 0);
-		solo_reg_write(solo_dev, SOLO_VI_WIN_CTRL1(i), 0);
-		solo_reg_write(solo_dev, SOLO_VI_WIN_ON(i), 0);
-	}
-
-	/* Set default border */
-	for (i = 0; i < 5; i++)
-		solo_reg_write(solo_dev, SOLO_VO_BORDER_X(i), 0);
-
-	for (i = 0; i < 5; i++)
-		solo_reg_write(solo_dev, SOLO_VO_BORDER_Y(i), 0);
-
-	solo_reg_write(solo_dev, SOLO_VO_BORDER_LINE_MASK, 0);
-	solo_reg_write(solo_dev, SOLO_VO_BORDER_FILL_MASK, 0);
-
-	solo_reg_write(solo_dev, SOLO_VO_RECTANGLE_CTRL(0), 0);
-	solo_reg_write(solo_dev, SOLO_VO_RECTANGLE_START(0), 0);
-	solo_reg_write(solo_dev, SOLO_VO_RECTANGLE_STOP(0), 0);
-
-	solo_reg_write(solo_dev, SOLO_VO_RECTANGLE_CTRL(1), 0);
-	solo_reg_write(solo_dev, SOLO_VO_RECTANGLE_START(1), 0);
-	solo_reg_write(solo_dev, SOLO_VO_RECTANGLE_STOP(1), 0);
-}
diff --git a/drivers/staging/media/solo6x10/enc.c b/drivers/staging/media/solo6x10/enc.c
deleted file mode 100644
index de50259..0000000
--- a/drivers/staging/media/solo6x10/enc.c
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- * Copyright (C) 2010 Bluecherry, LLC www.bluecherrydvr.com
- * Copyright (C) 2010 Ben Collins <bcollins@bluecherry.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You 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 "solo6x10.h"
-#include "osd-font.h"
-
-#define CAPTURE_MAX_BANDWIDTH		32	/* D1 4channel (D1 == 4) */
-#define OSG_BUFFER_SIZE			1024
-
-#define VI_PROG_HSIZE			(1280 - 16)
-#define VI_PROG_VSIZE			(1024 - 16)
-
-static void solo_capture_config(struct solo_dev *solo_dev)
-{
-	int i, j;
-	unsigned long height;
-	unsigned long width;
-	unsigned char *buf;
-
-	solo_reg_write(solo_dev, SOLO_CAP_BASE,
-		       SOLO_CAP_MAX_PAGE(SOLO_CAP_EXT_MAX_PAGE *
-					 solo_dev->nr_chans) |
-		       SOLO_CAP_BASE_ADDR(SOLO_CAP_EXT_ADDR(solo_dev) >> 16));
-	solo_reg_write(solo_dev, SOLO_CAP_BTW,
-		       (1 << 17) | SOLO_CAP_PROG_BANDWIDTH(2) |
-		       SOLO_CAP_MAX_BANDWIDTH(CAPTURE_MAX_BANDWIDTH));
-
-	/* Set scale 1, 9 dimension */
-	width = solo_dev->video_hsize;
-	height = solo_dev->video_vsize;
-	solo_reg_write(solo_dev, SOLO_DIM_SCALE1,
-		       SOLO_DIM_H_MB_NUM(width / 16) |
-		       SOLO_DIM_V_MB_NUM_FRAME(height / 8) |
-		       SOLO_DIM_V_MB_NUM_FIELD(height / 16));
-
-	/* Set scale 2, 10 dimension */
-	width = solo_dev->video_hsize / 2;
-	height = solo_dev->video_vsize;
-	solo_reg_write(solo_dev, SOLO_DIM_SCALE2,
-		       SOLO_DIM_H_MB_NUM(width / 16) |
-		       SOLO_DIM_V_MB_NUM_FRAME(height / 8) |
-		       SOLO_DIM_V_MB_NUM_FIELD(height / 16));
-
-	/* Set scale 3, 11 dimension */
-	width = solo_dev->video_hsize / 2;
-	height = solo_dev->video_vsize / 2;
-	solo_reg_write(solo_dev, SOLO_DIM_SCALE3,
-		       SOLO_DIM_H_MB_NUM(width / 16) |
-		       SOLO_DIM_V_MB_NUM_FRAME(height / 8) |
-		       SOLO_DIM_V_MB_NUM_FIELD(height / 16));
-
-	/* Set scale 4, 12 dimension */
-	width = solo_dev->video_hsize / 3;
-	height = solo_dev->video_vsize / 3;
-	solo_reg_write(solo_dev, SOLO_DIM_SCALE4,
-		       SOLO_DIM_H_MB_NUM(width / 16) |
-		       SOLO_DIM_V_MB_NUM_FRAME(height / 8) |
-		       SOLO_DIM_V_MB_NUM_FIELD(height / 16));
-
-	/* Set scale 5, 13 dimension */
-	width = solo_dev->video_hsize / 4;
-	height = solo_dev->video_vsize / 2;
-	solo_reg_write(solo_dev, SOLO_DIM_SCALE5,
-		       SOLO_DIM_H_MB_NUM(width / 16) |
-		       SOLO_DIM_V_MB_NUM_FRAME(height / 8) |
-		       SOLO_DIM_V_MB_NUM_FIELD(height / 16));
-
-	/* Progressive */
-	width = VI_PROG_HSIZE;
-	height = VI_PROG_VSIZE;
-	solo_reg_write(solo_dev, SOLO_DIM_PROG,
-		       SOLO_DIM_H_MB_NUM(width / 16) |
-		       SOLO_DIM_V_MB_NUM_FRAME(height / 16) |
-		       SOLO_DIM_V_MB_NUM_FIELD(height / 16));
-
-	/* Clear OSD */
-	solo_reg_write(solo_dev, SOLO_VE_OSD_CH, 0);
-	solo_reg_write(solo_dev, SOLO_VE_OSD_BASE, SOLO_EOSD_EXT_ADDR >> 16);
-	solo_reg_write(solo_dev, SOLO_VE_OSD_CLR,
-		       0xF0 << 16 | 0x80 << 8 | 0x80);
-	solo_reg_write(solo_dev, SOLO_VE_OSD_OPT, 0);
-
-	/* Clear OSG buffer */
-	buf = kzalloc(OSG_BUFFER_SIZE, GFP_KERNEL);
-	if (!buf)
-		return;
-
-	for (i = 0; i < solo_dev->nr_chans; i++) {
-		for (j = 0; j < SOLO_EOSD_EXT_SIZE; j += OSG_BUFFER_SIZE) {
-			solo_p2m_dma(solo_dev, SOLO_P2M_DMA_ID_MP4E, 1, buf,
-				     SOLO_EOSD_EXT_ADDR +
-				     (i * SOLO_EOSD_EXT_SIZE) + j,
-				     OSG_BUFFER_SIZE);
-		}
-	}
-	kfree(buf);
-}
-
-int solo_osd_print(struct solo_enc_dev *solo_enc)
-{
-	struct solo_dev *solo_dev = solo_enc->solo_dev;
-	char *str = solo_enc->osd_text;
-	u8 *buf;
-	u32 reg = solo_reg_read(solo_dev, SOLO_VE_OSD_CH);
-	int len = strlen(str);
-	int i, j;
-	int x = 1, y = 1;
-
-	if (len == 0) {
-		reg &= ~(1 << solo_enc->ch);
-		solo_reg_write(solo_dev, SOLO_VE_OSD_CH, reg);
-		return 0;
-	}
-
-	buf = kzalloc(SOLO_EOSD_EXT_SIZE, GFP_KERNEL);
-	if (!buf)
-		return -ENOMEM;
-
-	for (i = 0; i < len; i++) {
-		for (j = 0; j < 16; j++) {
-			buf[(j*2) + (i%2) + ((x + (i/2)) * 32) + (y * 2048)] =
-				(solo_osd_font[(str[i] * 4) + (j / 4)]
-					>> ((3 - (j % 4)) * 8)) & 0xff;
-		}
-	}
-
-	solo_p2m_dma(solo_dev, 0, 1, buf, SOLO_EOSD_EXT_ADDR +
-		     (solo_enc->ch * SOLO_EOSD_EXT_SIZE), SOLO_EOSD_EXT_SIZE);
-	reg |= (1 << solo_enc->ch);
-	solo_reg_write(solo_dev, SOLO_VE_OSD_CH, reg);
-
-	kfree(buf);
-
-	return 0;
-}
-
-static void solo_jpeg_config(struct solo_dev *solo_dev)
-{
-	u32 reg;
-	if (solo_dev->flags & FLAGS_6110)
-		reg = (4 << 24) | (3 << 16) | (2 << 8) | (1 << 0);
-	else
-		reg = (2 << 24) | (2 << 16) | (2 << 8) | (2 << 0);
-	solo_reg_write(solo_dev, SOLO_VE_JPEG_QP_TBL, reg);
-	solo_reg_write(solo_dev, SOLO_VE_JPEG_QP_CH_L, 0);
-	solo_reg_write(solo_dev, SOLO_VE_JPEG_QP_CH_H, 0);
-	solo_reg_write(solo_dev, SOLO_VE_JPEG_CFG,
-		(SOLO_JPEG_EXT_SIZE(solo_dev) & 0xffff0000) |
-		((SOLO_JPEG_EXT_ADDR(solo_dev) >> 16) & 0x0000ffff));
-	solo_reg_write(solo_dev, SOLO_VE_JPEG_CTRL, 0xffffffff);
-	/* que limit, samp limit, pos limit */
-	solo_reg_write(solo_dev, 0x0688, (0 << 16) | (30 << 8) | 60);
-}
-
-static void solo_mp4e_config(struct solo_dev *solo_dev)
-{
-	int i;
-	u32 reg;
-
-	/* We can only use VE_INTR_CTRL(0) if we want to support mjpeg */
-	solo_reg_write(solo_dev, SOLO_VE_CFG0,
-		       SOLO_VE_INTR_CTRL(0) |
-		       SOLO_VE_BLOCK_SIZE(SOLO_MP4E_EXT_SIZE(solo_dev) >> 16) |
-		       SOLO_VE_BLOCK_BASE(SOLO_MP4E_EXT_ADDR(solo_dev) >> 16));
-
-	solo_reg_write(solo_dev, SOLO_VE_CFG1,
-		       SOLO_VE_INSERT_INDEX | SOLO_VE_MOTION_MODE(0));
-
-	solo_reg_write(solo_dev, SOLO_VE_WMRK_POLY, 0);
-	solo_reg_write(solo_dev, SOLO_VE_VMRK_INIT_KEY, 0);
-	solo_reg_write(solo_dev, SOLO_VE_WMRK_STRL, 0);
-	solo_reg_write(solo_dev, SOLO_VE_ENCRYP_POLY, 0);
-	solo_reg_write(solo_dev, SOLO_VE_ENCRYP_INIT, 0);
-
-	reg = SOLO_VE_LITTLE_ENDIAN | SOLO_COMP_ATTR_FCODE(1) |
-		SOLO_COMP_TIME_INC(0) | SOLO_COMP_TIME_WIDTH(15);
-	if (solo_dev->flags & FLAGS_6110)
-		reg |= SOLO_DCT_INTERVAL(10);
-	else
-		reg |= SOLO_DCT_INTERVAL(36 / 4);
-	solo_reg_write(solo_dev, SOLO_VE_ATTR, reg);
-
-	for (i = 0; i < solo_dev->nr_chans; i++)
-		solo_reg_write(solo_dev, SOLO_VE_CH_REF_BASE(i),
-			       (SOLO_EREF_EXT_ADDR(solo_dev) +
-			       (i * SOLO_EREF_EXT_SIZE)) >> 16);
-
-	if (solo_dev->flags & FLAGS_6110)
-		solo_reg_write(solo_dev, 0x0634, 0x00040008); /* ? */
-}
-
-int solo_enc_init(struct solo_dev *solo_dev)
-{
-	int i;
-
-	solo_capture_config(solo_dev);
-	solo_mp4e_config(solo_dev);
-	solo_jpeg_config(solo_dev);
-
-	for (i = 0; i < solo_dev->nr_chans; i++) {
-		solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(i), 0);
-		solo_reg_write(solo_dev, SOLO_CAP_CH_COMP_ENA_E(i), 0);
-	}
-
-	solo_irq_on(solo_dev, SOLO_IRQ_ENCODER);
-
-	return 0;
-}
-
-void solo_enc_exit(struct solo_dev *solo_dev)
-{
-	int i;
-
-	solo_irq_off(solo_dev, SOLO_IRQ_ENCODER);
-
-	for (i = 0; i < solo_dev->nr_chans; i++) {
-		solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(i), 0);
-		solo_reg_write(solo_dev, SOLO_CAP_CH_COMP_ENA_E(i), 0);
-	}
-}
diff --git a/drivers/staging/media/solo6x10/g723.c b/drivers/staging/media/solo6x10/g723.c
deleted file mode 100644
index 2cd0de2..0000000
--- a/drivers/staging/media/solo6x10/g723.c
+++ /dev/null
@@ -1,400 +0,0 @@
-/*
- * Copyright (C) 2010 Bluecherry, LLC www.bluecherrydvr.com
- * Copyright (C) 2010 Ben Collins <bcollins@bluecherry.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You 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/mempool.h>
-#include <linux/poll.h>
-#include <linux/kthread.h>
-#include <linux/slab.h>
-#include <linux/freezer.h>
-#include <linux/export.h>
-#include <sound/core.h>
-#include <sound/initval.h>
-#include <sound/pcm.h>
-#include <sound/control.h>
-#include "solo6x10.h"
-#include "tw28.h"
-
-#define G723_INTR_ORDER		0
-#define G723_FDMA_PAGES		32
-#define G723_PERIOD_BYTES	48
-#define G723_PERIOD_BLOCK	1024
-#define G723_FRAMES_PER_PAGE	48
-
-/* Sets up channels 16-19 for decoding and 0-15 for encoding */
-#define OUTMODE_MASK		0x300
-
-#define SAMPLERATE		8000
-#define BITRATE			25
-
-/* The solo writes to 1k byte pages, 32 pages, in the dma. Each 1k page
- * is broken down to 20 * 48 byte regions (one for each channel possible)
- * with the rest of the page being dummy data. */
-#define MAX_BUFFER		(G723_PERIOD_BYTES * PERIODS_MAX)
-#define IRQ_PAGES		4 /* 0 - 4 */
-#define PERIODS_MIN		(1 << IRQ_PAGES)
-#define PERIODS_MAX		G723_FDMA_PAGES
-
-struct solo_snd_pcm {
-	int		on;
-	spinlock_t	lock;
-	struct solo_dev	*solo_dev;
-	unsigned char	g723_buf[G723_PERIOD_BYTES];
-};
-
-static void solo_g723_config(struct solo_dev *solo_dev)
-{
-	int clk_div;
-
-	clk_div = SOLO_CLOCK_MHZ / (SAMPLERATE * (BITRATE * 2) * 2);
-
-	solo_reg_write(solo_dev, SOLO_AUDIO_SAMPLE,
-		       SOLO_AUDIO_BITRATE(BITRATE) |
-		       SOLO_AUDIO_CLK_DIV(clk_div));
-
-	solo_reg_write(solo_dev, SOLO_AUDIO_FDMA_INTR,
-		      SOLO_AUDIO_FDMA_INTERVAL(IRQ_PAGES) |
-		      SOLO_AUDIO_INTR_ORDER(G723_INTR_ORDER) |
-		      SOLO_AUDIO_FDMA_BASE(SOLO_G723_EXT_ADDR(solo_dev) >> 16));
-
-	solo_reg_write(solo_dev, SOLO_AUDIO_CONTROL,
-		       SOLO_AUDIO_ENABLE | SOLO_AUDIO_I2S_MODE |
-		       SOLO_AUDIO_I2S_MULTI(3) | SOLO_AUDIO_MODE(OUTMODE_MASK));
-}
-
-void solo_g723_isr(struct solo_dev *solo_dev)
-{
-	struct snd_pcm_str *pstr =
-		&solo_dev->snd_pcm->streams[SNDRV_PCM_STREAM_CAPTURE];
-	struct snd_pcm_substream *ss;
-	struct solo_snd_pcm *solo_pcm;
-
-	solo_reg_write(solo_dev, SOLO_IRQ_STAT, SOLO_IRQ_G723);
-
-	for (ss = pstr->substream; ss != NULL; ss = ss->next) {
-		if (snd_pcm_substream_chip(ss) == NULL)
-			continue;
-
-		/* This means open() hasn't been called on this one */
-		if (snd_pcm_substream_chip(ss) == solo_dev)
-			continue;
-
-		/* Haven't triggered a start yet */
-		solo_pcm = snd_pcm_substream_chip(ss);
-		if (!solo_pcm->on)
-			continue;
-
-		snd_pcm_period_elapsed(ss);
-	}
-}
-
-static int snd_solo_hw_params(struct snd_pcm_substream *ss,
-			      struct snd_pcm_hw_params *hw_params)
-{
-	return snd_pcm_lib_malloc_pages(ss, params_buffer_bytes(hw_params));
-}
-
-static int snd_solo_hw_free(struct snd_pcm_substream *ss)
-{
-	return snd_pcm_lib_free_pages(ss);
-}
-
-static struct snd_pcm_hardware snd_solo_pcm_hw = {
-	.info			= (SNDRV_PCM_INFO_MMAP |
-				   SNDRV_PCM_INFO_INTERLEAVED |
-				   SNDRV_PCM_INFO_BLOCK_TRANSFER |
-				   SNDRV_PCM_INFO_MMAP_VALID),
-	.formats		= SNDRV_PCM_FMTBIT_U8,
-	.rates			= SNDRV_PCM_RATE_8000,
-	.rate_min		= 8000,
-	.rate_max		= 8000,
-	.channels_min		= 1,
-	.channels_max		= 1,
-	.buffer_bytes_max	= MAX_BUFFER,
-	.period_bytes_min	= G723_PERIOD_BYTES,
-	.period_bytes_max	= G723_PERIOD_BYTES,
-	.periods_min		= PERIODS_MIN,
-	.periods_max		= PERIODS_MAX,
-};
-
-static int snd_solo_pcm_open(struct snd_pcm_substream *ss)
-{
-	struct solo_dev *solo_dev = snd_pcm_substream_chip(ss);
-	struct solo_snd_pcm *solo_pcm;
-
-	solo_pcm = kzalloc(sizeof(*solo_pcm), GFP_KERNEL);
-	if (solo_pcm == NULL)
-		return -ENOMEM;
-
-	spin_lock_init(&solo_pcm->lock);
-	solo_pcm->solo_dev = solo_dev;
-	ss->runtime->hw = snd_solo_pcm_hw;
-
-	snd_pcm_substream_chip(ss) = solo_pcm;
-
-	return 0;
-}
-
-static int snd_solo_pcm_close(struct snd_pcm_substream *ss)
-{
-	struct solo_snd_pcm *solo_pcm = snd_pcm_substream_chip(ss);
-
-	snd_pcm_substream_chip(ss) = solo_pcm->solo_dev;
-	kfree(solo_pcm);
-
-	return 0;
-}
-
-static int snd_solo_pcm_trigger(struct snd_pcm_substream *ss, int cmd)
-{
-	struct solo_snd_pcm *solo_pcm = snd_pcm_substream_chip(ss);
-	struct solo_dev *solo_dev = solo_pcm->solo_dev;
-	int ret = 0;
-
-	spin_lock(&solo_pcm->lock);
-
-	switch (cmd) {
-	case SNDRV_PCM_TRIGGER_START:
-		if (solo_pcm->on == 0) {
-			/* If this is the first user, switch on interrupts */
-			if (atomic_inc_return(&solo_dev->snd_users) == 1)
-				solo_irq_on(solo_dev, SOLO_IRQ_G723);
-			solo_pcm->on = 1;
-		}
-		break;
-	case SNDRV_PCM_TRIGGER_STOP:
-		if (solo_pcm->on) {
-			/* If this was our last user, switch them off */
-			if (atomic_dec_return(&solo_dev->snd_users) == 0)
-				solo_irq_off(solo_dev, SOLO_IRQ_G723);
-			solo_pcm->on = 0;
-		}
-		break;
-	default:
-		ret = -EINVAL;
-	}
-
-	spin_unlock(&solo_pcm->lock);
-
-	return ret;
-}
-
-static int snd_solo_pcm_prepare(struct snd_pcm_substream *ss)
-{
-	return 0;
-}
-
-static snd_pcm_uframes_t snd_solo_pcm_pointer(struct snd_pcm_substream *ss)
-{
-	struct solo_snd_pcm *solo_pcm = snd_pcm_substream_chip(ss);
-	struct solo_dev *solo_dev = solo_pcm->solo_dev;
-	snd_pcm_uframes_t idx = solo_reg_read(solo_dev, SOLO_AUDIO_STA) & 0x1f;
-
-	return idx * G723_FRAMES_PER_PAGE;
-}
-
-static int snd_solo_pcm_copy(struct snd_pcm_substream *ss, int channel,
-			     snd_pcm_uframes_t pos, void __user *dst,
-			     snd_pcm_uframes_t count)
-{
-	struct solo_snd_pcm *solo_pcm = snd_pcm_substream_chip(ss);
-	struct solo_dev *solo_dev = solo_pcm->solo_dev;
-	int err, i;
-
-	for (i = 0; i < (count / G723_FRAMES_PER_PAGE); i++) {
-		int page = (pos / G723_FRAMES_PER_PAGE) + i;
-
-		err = solo_p2m_dma(solo_dev, SOLO_P2M_DMA_ID_G723E, 0,
-				   solo_pcm->g723_buf,
-				   SOLO_G723_EXT_ADDR(solo_dev) +
-				   (page * G723_PERIOD_BLOCK) +
-				   (ss->number * G723_PERIOD_BYTES),
-				   G723_PERIOD_BYTES);
-		if (err)
-			return err;
-
-		err = copy_to_user(dst + (i * G723_PERIOD_BYTES),
-				   solo_pcm->g723_buf, G723_PERIOD_BYTES);
-
-		if (err)
-			return -EFAULT;
-	}
-
-	return 0;
-}
-
-static struct snd_pcm_ops snd_solo_pcm_ops = {
-	.open = snd_solo_pcm_open,
-	.close = snd_solo_pcm_close,
-	.ioctl = snd_pcm_lib_ioctl,
-	.hw_params = snd_solo_hw_params,
-	.hw_free = snd_solo_hw_free,
-	.prepare = snd_solo_pcm_prepare,
-	.trigger = snd_solo_pcm_trigger,
-	.pointer = snd_solo_pcm_pointer,
-	.copy = snd_solo_pcm_copy,
-};
-
-static int snd_solo_capture_volume_info(struct snd_kcontrol *kcontrol,
-					struct snd_ctl_elem_info *info)
-{
-	info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
-	info->count = 1;
-	info->value.integer.min = 0;
-	info->value.integer.max = 15;
-	info->value.integer.step = 1;
-
-	return 0;
-}
-
-static int snd_solo_capture_volume_get(struct snd_kcontrol *kcontrol,
-				       struct snd_ctl_elem_value *value)
-{
-	struct solo_dev *solo_dev = snd_kcontrol_chip(kcontrol);
-	u8 ch = value->id.numid - 1;
-
-	value->value.integer.value[0] = tw28_get_audio_gain(solo_dev, ch);
-
-	return 0;
-}
-
-static int snd_solo_capture_volume_put(struct snd_kcontrol *kcontrol,
-				       struct snd_ctl_elem_value *value)
-{
-	struct solo_dev *solo_dev = snd_kcontrol_chip(kcontrol);
-	u8 ch = value->id.numid - 1;
-	u8 old_val;
-
-	old_val = tw28_get_audio_gain(solo_dev, ch);
-	if (old_val == value->value.integer.value[0])
-		return 0;
-
-	tw28_set_audio_gain(solo_dev, ch, value->value.integer.value[0]);
-
-	return 1;
-}
-
-static struct snd_kcontrol_new snd_solo_capture_volume = {
-	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-	.name = "Capture Volume",
-	.info = snd_solo_capture_volume_info,
-	.get = snd_solo_capture_volume_get,
-	.put = snd_solo_capture_volume_put,
-};
-
-static int solo_snd_pcm_init(struct solo_dev *solo_dev)
-{
-	struct snd_card *card = solo_dev->snd_card;
-	struct snd_pcm *pcm;
-	struct snd_pcm_substream *ss;
-	int ret;
-	int i;
-
-	ret = snd_pcm_new(card, card->driver, 0, 0, solo_dev->nr_chans,
-			  &pcm);
-	if (ret < 0)
-		return ret;
-
-	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
-			&snd_solo_pcm_ops);
-
-	snd_pcm_chip(pcm) = solo_dev;
-	pcm->info_flags = 0;
-	strcpy(pcm->name, card->shortname);
-
-	for (i = 0, ss = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
-	     ss; ss = ss->next, i++)
-		sprintf(ss->name, "Camera #%d Audio", i);
-
-	ret = snd_pcm_lib_preallocate_pages_for_all(pcm,
-					SNDRV_DMA_TYPE_CONTINUOUS,
-					snd_dma_continuous_data(GFP_KERNEL),
-					MAX_BUFFER, MAX_BUFFER);
-	if (ret < 0)
-		return ret;
-
-	solo_dev->snd_pcm = pcm;
-
-	return 0;
-}
-
-int solo_g723_init(struct solo_dev *solo_dev)
-{
-	static struct snd_device_ops ops = { NULL };
-	struct snd_card *card;
-	struct snd_kcontrol_new kctl;
-	char name[32];
-	int ret;
-
-	atomic_set(&solo_dev->snd_users, 0);
-
-	/* Allows for easier mapping between video and audio */
-	sprintf(name, "Softlogic%d", solo_dev->vfd->num);
-
-	ret = snd_card_create(SNDRV_DEFAULT_IDX1, name, THIS_MODULE, 0,
-			      &solo_dev->snd_card);
-	if (ret < 0)
-		return ret;
-
-	card = solo_dev->snd_card;
-
-	strcpy(card->driver, SOLO6X10_NAME);
-	strcpy(card->shortname, "SOLO-6x10 Audio");
-	sprintf(card->longname, "%s on %s IRQ %d", card->shortname,
-		pci_name(solo_dev->pdev), solo_dev->pdev->irq);
-	snd_card_set_dev(card, &solo_dev->pdev->dev);
-
-	ret = snd_device_new(card, SNDRV_DEV_LOWLEVEL, solo_dev, &ops);
-	if (ret < 0)
-		goto snd_error;
-
-	/* Mixer controls */
-	strcpy(card->mixername, "SOLO-6x10");
-	kctl = snd_solo_capture_volume;
-	kctl.count = solo_dev->nr_chans;
-	ret = snd_ctl_add(card, snd_ctl_new1(&kctl, solo_dev));
-	if (ret < 0)
-		return ret;
-
-	ret = solo_snd_pcm_init(solo_dev);
-	if (ret < 0)
-		goto snd_error;
-
-	ret = snd_card_register(card);
-	if (ret < 0)
-		goto snd_error;
-
-	solo_g723_config(solo_dev);
-
-	dev_info(&solo_dev->pdev->dev, "Alsa sound card as %s\n", name);
-
-	return 0;
-
-snd_error:
-	snd_card_free(card);
-	return ret;
-}
-
-void solo_g723_exit(struct solo_dev *solo_dev)
-{
-	solo_reg_write(solo_dev, SOLO_AUDIO_CONTROL, 0);
-	solo_irq_off(solo_dev, SOLO_IRQ_G723);
-
-	snd_card_free(solo_dev->snd_card);
-}
diff --git a/drivers/staging/media/solo6x10/gpio.c b/drivers/staging/media/solo6x10/gpio.c
deleted file mode 100644
index 0925e6f..0000000
--- a/drivers/staging/media/solo6x10/gpio.c
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2010 Bluecherry, LLC www.bluecherrydvr.com
- * Copyright (C) 2010 Ben Collins <bcollins@bluecherry.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You 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/fs.h>
-#include <asm/uaccess.h>
-#include "solo6x10.h"
-
-static void solo_gpio_mode(struct solo_dev *solo_dev,
-			   unsigned int port_mask, unsigned int mode)
-{
-	int port;
-	unsigned int ret;
-
-	ret = solo_reg_read(solo_dev, SOLO_GPIO_CONFIG_0);
-
-	/* To set gpio */
-	for (port = 0; port < 16; port++) {
-		if (!((1 << port) & port_mask))
-			continue;
-
-		ret &= (~(3 << (port << 1)));
-		ret |= ((mode & 3) << (port << 1));
-	}
-
-	solo_reg_write(solo_dev, SOLO_GPIO_CONFIG_0, ret);
-
-	/* To set extended gpio - sensor */
-	ret = solo_reg_read(solo_dev, SOLO_GPIO_CONFIG_1);
-
-	for (port = 0; port < 16; port++) {
-		if (!((1 << (port + 16)) & port_mask))
-			continue;
-
-		if (!mode)
-			ret &= ~(1 << port);
-		else
-			ret |= 1 << port;
-	}
-
-	solo_reg_write(solo_dev, SOLO_GPIO_CONFIG_1, ret);
-}
-
-static void solo_gpio_set(struct solo_dev *solo_dev, unsigned int value)
-{
-	solo_reg_write(solo_dev, SOLO_GPIO_DATA_OUT,
-		       solo_reg_read(solo_dev, SOLO_GPIO_DATA_OUT) | value);
-}
-
-static void solo_gpio_clear(struct solo_dev *solo_dev, unsigned int value)
-{
-	solo_reg_write(solo_dev, SOLO_GPIO_DATA_OUT,
-		       solo_reg_read(solo_dev, SOLO_GPIO_DATA_OUT) & ~value);
-}
-
-static void solo_gpio_config(struct solo_dev *solo_dev)
-{
-	/* Video reset */
-	solo_gpio_mode(solo_dev, 0x30, 1);
-	solo_gpio_clear(solo_dev, 0x30);
-	udelay(100);
-	solo_gpio_set(solo_dev, 0x30);
-	udelay(100);
-
-	/* Warning: Don't touch the next line unless you're sure of what
-	 * you're doing: first four gpio [0-3] are used for video. */
-	solo_gpio_mode(solo_dev, 0x0f, 2);
-
-	/* We use bit 8-15 of SOLO_GPIO_CONFIG_0 for relay purposes */
-	solo_gpio_mode(solo_dev, 0xff00, 1);
-
-	/* Initially set relay status to 0 */
-	solo_gpio_clear(solo_dev, 0xff00);
-}
-
-int solo_gpio_init(struct solo_dev *solo_dev)
-{
-	solo_gpio_config(solo_dev);
-	return 0;
-}
-
-void solo_gpio_exit(struct solo_dev *solo_dev)
-{
-	solo_gpio_clear(solo_dev, 0x30);
-	solo_gpio_config(solo_dev);
-}
diff --git a/drivers/staging/media/solo6x10/i2c.c b/drivers/staging/media/solo6x10/i2c.c
deleted file mode 100644
index 398070a..0000000
--- a/drivers/staging/media/solo6x10/i2c.c
+++ /dev/null
@@ -1,330 +0,0 @@
-/*
- * Copyright (C) 2010 Bluecherry, LLC www.bluecherrydvr.com
- * Copyright (C) 2010 Ben Collins <bcollins@bluecherry.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You 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.
- */
-
-/* XXX: The SOLO6x10 i2c does not have separate interrupts for each i2c
- * channel. The bus can only handle one i2c event at a time. The below handles
- * this all wrong. We should be using the status registers to see if the bus
- * is in use, and have a global lock to check the status register. Also,
- * the bulk of the work should be handled out-of-interrupt. The ugly loops
- * that occur during interrupt scare me. The ISR should merely signal
- * thread context, ACK the interrupt, and move on. -- BenC */
-
-#include <linux/kernel.h>
-#include "solo6x10.h"
-
-u8 solo_i2c_readbyte(struct solo_dev *solo_dev, int id, u8 addr, u8 off)
-{
-	struct i2c_msg msgs[2];
-	u8 data;
-
-	msgs[0].flags = 0;
-	msgs[0].addr = addr;
-	msgs[0].len = 1;
-	msgs[0].buf = &off;
-
-	msgs[1].flags = I2C_M_RD;
-	msgs[1].addr = addr;
-	msgs[1].len = 1;
-	msgs[1].buf = &data;
-
-	i2c_transfer(&solo_dev->i2c_adap[id], msgs, 2);
-
-	return data;
-}
-
-void solo_i2c_writebyte(struct solo_dev *solo_dev, int id, u8 addr,
-			u8 off, u8 data)
-{
-	struct i2c_msg msgs;
-	u8 buf[2];
-
-	buf[0] = off;
-	buf[1] = data;
-	msgs.flags = 0;
-	msgs.addr = addr;
-	msgs.len = 2;
-	msgs.buf = buf;
-
-	i2c_transfer(&solo_dev->i2c_adap[id], &msgs, 1);
-}
-
-static void solo_i2c_flush(struct solo_dev *solo_dev, int wr)
-{
-	u32 ctrl;
-
-	ctrl = SOLO_IIC_CH_SET(solo_dev->i2c_id);
-
-	if (solo_dev->i2c_state == IIC_STATE_START)
-		ctrl |= SOLO_IIC_START;
-
-	if (wr) {
-		ctrl |= SOLO_IIC_WRITE;
-	} else {
-		ctrl |= SOLO_IIC_READ;
-		if (!(solo_dev->i2c_msg->flags & I2C_M_NO_RD_ACK))
-			ctrl |= SOLO_IIC_ACK_EN;
-	}
-
-	if (solo_dev->i2c_msg_ptr == solo_dev->i2c_msg->len)
-		ctrl |= SOLO_IIC_STOP;
-
-	solo_reg_write(solo_dev, SOLO_IIC_CTRL, ctrl);
-}
-
-static void solo_i2c_start(struct solo_dev *solo_dev)
-{
-	u32 addr = solo_dev->i2c_msg->addr << 1;
-
-	if (solo_dev->i2c_msg->flags & I2C_M_RD)
-		addr |= 1;
-
-	solo_dev->i2c_state = IIC_STATE_START;
-	solo_reg_write(solo_dev, SOLO_IIC_TXD, addr);
-	solo_i2c_flush(solo_dev, 1);
-}
-
-static void solo_i2c_stop(struct solo_dev *solo_dev)
-{
-	solo_irq_off(solo_dev, SOLO_IRQ_IIC);
-	solo_reg_write(solo_dev, SOLO_IIC_CTRL, 0);
-	solo_dev->i2c_state = IIC_STATE_STOP;
-	wake_up(&solo_dev->i2c_wait);
-}
-
-static int solo_i2c_handle_read(struct solo_dev *solo_dev)
-{
-prepare_read:
-	if (solo_dev->i2c_msg_ptr != solo_dev->i2c_msg->len) {
-		solo_i2c_flush(solo_dev, 0);
-		return 0;
-	}
-
-	solo_dev->i2c_msg_ptr = 0;
-	solo_dev->i2c_msg++;
-	solo_dev->i2c_msg_num--;
-
-	if (solo_dev->i2c_msg_num == 0) {
-		solo_i2c_stop(solo_dev);
-		return 0;
-	}
-
-	if (!(solo_dev->i2c_msg->flags & I2C_M_NOSTART)) {
-		solo_i2c_start(solo_dev);
-	} else {
-		if (solo_dev->i2c_msg->flags & I2C_M_RD)
-			goto prepare_read;
-		else
-			solo_i2c_stop(solo_dev);
-	}
-
-	return 0;
-}
-
-static int solo_i2c_handle_write(struct solo_dev *solo_dev)
-{
-retry_write:
-	if (solo_dev->i2c_msg_ptr != solo_dev->i2c_msg->len) {
-		solo_reg_write(solo_dev, SOLO_IIC_TXD,
-			       solo_dev->i2c_msg->buf[solo_dev->i2c_msg_ptr]);
-		solo_dev->i2c_msg_ptr++;
-		solo_i2c_flush(solo_dev, 1);
-		return 0;
-	}
-
-	solo_dev->i2c_msg_ptr = 0;
-	solo_dev->i2c_msg++;
-	solo_dev->i2c_msg_num--;
-
-	if (solo_dev->i2c_msg_num == 0) {
-		solo_i2c_stop(solo_dev);
-		return 0;
-	}
-
-	if (!(solo_dev->i2c_msg->flags & I2C_M_NOSTART)) {
-		solo_i2c_start(solo_dev);
-	} else {
-		if (solo_dev->i2c_msg->flags & I2C_M_RD)
-			solo_i2c_stop(solo_dev);
-		else
-			goto retry_write;
-	}
-
-	return 0;
-}
-
-int solo_i2c_isr(struct solo_dev *solo_dev)
-{
-	u32 status = solo_reg_read(solo_dev, SOLO_IIC_CTRL);
-	int ret = -EINVAL;
-
-	solo_reg_write(solo_dev, SOLO_IRQ_STAT, SOLO_IRQ_IIC);
-
-	if (status & (SOLO_IIC_STATE_TRNS | SOLO_IIC_STATE_SIG_ERR) ||
-	    solo_dev->i2c_id < 0) {
-		solo_i2c_stop(solo_dev);
-		return -ENXIO;
-	}
-
-	switch (solo_dev->i2c_state) {
-	case IIC_STATE_START:
-		if (solo_dev->i2c_msg->flags & I2C_M_RD) {
-			solo_dev->i2c_state = IIC_STATE_READ;
-			ret = solo_i2c_handle_read(solo_dev);
-			break;
-		}
-
-		solo_dev->i2c_state = IIC_STATE_WRITE;
-	case IIC_STATE_WRITE:
-		ret = solo_i2c_handle_write(solo_dev);
-		break;
-
-	case IIC_STATE_READ:
-		solo_dev->i2c_msg->buf[solo_dev->i2c_msg_ptr] =
-			solo_reg_read(solo_dev, SOLO_IIC_RXD);
-		solo_dev->i2c_msg_ptr++;
-
-		ret = solo_i2c_handle_read(solo_dev);
-		break;
-
-	default:
-		solo_i2c_stop(solo_dev);
-	}
-
-	return ret;
-}
-
-static int solo_i2c_master_xfer(struct i2c_adapter *adap,
-				struct i2c_msg msgs[], int num)
-{
-	struct solo_dev *solo_dev = adap->algo_data;
-	unsigned long timeout;
-	int ret;
-	int i;
-	DEFINE_WAIT(wait);
-
-	for (i = 0; i < SOLO_I2C_ADAPTERS; i++) {
-		if (&solo_dev->i2c_adap[i] == adap)
-			break;
-	}
-
-	if (i == SOLO_I2C_ADAPTERS)
-		return num; /* XXX Right return value for failure? */
-
-	mutex_lock(&solo_dev->i2c_mutex);
-	solo_dev->i2c_id = i;
-	solo_dev->i2c_msg = msgs;
-	solo_dev->i2c_msg_num = num;
-	solo_dev->i2c_msg_ptr = 0;
-
-	solo_reg_write(solo_dev, SOLO_IIC_CTRL, 0);
-	solo_irq_on(solo_dev, SOLO_IRQ_IIC);
-	solo_i2c_start(solo_dev);
-
-	timeout = HZ / 2;
-
-	for (;;) {
-		prepare_to_wait(&solo_dev->i2c_wait, &wait, TASK_INTERRUPTIBLE);
-
-		if (solo_dev->i2c_state == IIC_STATE_STOP)
-			break;
-
-		timeout = schedule_timeout(timeout);
-		if (!timeout)
-			break;
-
-		if (signal_pending(current))
-			break;
-	}
-
-	finish_wait(&solo_dev->i2c_wait, &wait);
-	ret = num - solo_dev->i2c_msg_num;
-	solo_dev->i2c_state = IIC_STATE_IDLE;
-	solo_dev->i2c_id = -1;
-
-	mutex_unlock(&solo_dev->i2c_mutex);
-
-	return ret;
-}
-
-static u32 solo_i2c_functionality(struct i2c_adapter *adap)
-{
-	return I2C_FUNC_I2C;
-}
-
-static struct i2c_algorithm solo_i2c_algo = {
-	.master_xfer	= solo_i2c_master_xfer,
-	.functionality	= solo_i2c_functionality,
-};
-
-int solo_i2c_init(struct solo_dev *solo_dev)
-{
-	int i;
-	int ret;
-
-	solo_reg_write(solo_dev, SOLO_IIC_CFG,
-		       SOLO_IIC_PRESCALE(8) | SOLO_IIC_ENABLE);
-
-	solo_dev->i2c_id = -1;
-	solo_dev->i2c_state = IIC_STATE_IDLE;
-	init_waitqueue_head(&solo_dev->i2c_wait);
-	mutex_init(&solo_dev->i2c_mutex);
-
-	for (i = 0; i < SOLO_I2C_ADAPTERS; i++) {
-		struct i2c_adapter *adap = &solo_dev->i2c_adap[i];
-
-		snprintf(adap->name, I2C_NAME_SIZE, "%s I2C %d", SOLO6X10_NAME, i);
-		adap->algo = &solo_i2c_algo;
-		adap->algo_data = solo_dev;
-		adap->retries = 1;
-		adap->dev.parent = &solo_dev->pdev->dev;
-
-		ret = i2c_add_adapter(adap);
-		if (ret) {
-			adap->algo_data = NULL;
-			break;
-		}
-	}
-
-	if (ret) {
-		for (i = 0; i < SOLO_I2C_ADAPTERS; i++) {
-			if (!solo_dev->i2c_adap[i].algo_data)
-				break;
-			i2c_del_adapter(&solo_dev->i2c_adap[i]);
-			solo_dev->i2c_adap[i].algo_data = NULL;
-		}
-		return ret;
-	}
-
-	dev_info(&solo_dev->pdev->dev, "Enabled %d i2c adapters\n",
-		 SOLO_I2C_ADAPTERS);
-
-	return 0;
-}
-
-void solo_i2c_exit(struct solo_dev *solo_dev)
-{
-	int i;
-
-	for (i = 0; i < SOLO_I2C_ADAPTERS; i++) {
-		if (!solo_dev->i2c_adap[i].algo_data)
-			continue;
-		i2c_del_adapter(&solo_dev->i2c_adap[i]);
-		solo_dev->i2c_adap[i].algo_data = NULL;
-	}
-}
diff --git a/drivers/staging/media/solo6x10/offsets.h b/drivers/staging/media/solo6x10/offsets.h
deleted file mode 100644
index 3d7e569..0000000
--- a/drivers/staging/media/solo6x10/offsets.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2010 Bluecherry, LLC www.bluecherrydvr.com
- * Copyright (C) 2010 Ben Collins <bcollins@bluecherry.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You 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 __SOLO6X10_OFFSETS_H
-#define __SOLO6X10_OFFSETS_H
-
-/* Offsets and sizes of the external address */
-#define SOLO_DISP_EXT_ADDR			0x00000000
-#define SOLO_DISP_EXT_SIZE			0x00480000
-
-#define SOLO_DEC2LIVE_EXT_ADDR (SOLO_DISP_EXT_ADDR + SOLO_DISP_EXT_SIZE)
-#define SOLO_DEC2LIVE_EXT_SIZE			0x00240000
-
-#define SOLO_OSG_EXT_ADDR (SOLO_DEC2LIVE_EXT_ADDR + SOLO_DEC2LIVE_EXT_SIZE)
-#define SOLO_OSG_EXT_SIZE			0x00120000
-
-#define SOLO_EOSD_EXT_ADDR (SOLO_OSG_EXT_ADDR + SOLO_OSG_EXT_SIZE)
-#define SOLO_EOSD_EXT_SIZE			0x00010000
-
-#define SOLO_MOTION_EXT_ADDR(__solo) (SOLO_EOSD_EXT_ADDR +	\
-				      (SOLO_EOSD_EXT_SIZE * __solo->nr_chans))
-#define SOLO_MOTION_EXT_SIZE			0x00080000
-
-#define SOLO_G723_EXT_ADDR(__solo) \
-		(SOLO_MOTION_EXT_ADDR(__solo) + SOLO_MOTION_EXT_SIZE)
-#define SOLO_G723_EXT_SIZE			0x00010000
-
-#define SOLO_CAP_EXT_ADDR(__solo) \
-		(SOLO_G723_EXT_ADDR(__solo) + SOLO_G723_EXT_SIZE)
-#define SOLO_CAP_EXT_MAX_PAGE			(18 + 15)
-#define SOLO_CAP_EXT_SIZE			(SOLO_CAP_EXT_MAX_PAGE * 65536)
-
-/* This +1 is very important -- Why?! -- BenC */
-#define SOLO_EREF_EXT_ADDR(__solo) \
-		(SOLO_CAP_EXT_ADDR(__solo) + \
-		 (SOLO_CAP_EXT_SIZE * (__solo->nr_chans + 1)))
-#define SOLO_EREF_EXT_SIZE			0x00140000
-
-#define SOLO_MP4E_EXT_ADDR(__solo) \
-		(SOLO_EREF_EXT_ADDR(__solo) + \
-		 (SOLO_EREF_EXT_SIZE * __solo->nr_chans))
-#define SOLO_MP4E_EXT_SIZE(__solo)		(0x00080000 * __solo->nr_chans)
-
-#define SOLO_DREF_EXT_ADDR(__solo) \
-		(SOLO_MP4E_EXT_ADDR(__solo) + SOLO_MP4E_EXT_SIZE(__solo))
-#define SOLO_DREF_EXT_SIZE			0x00140000
-
-#define SOLO_MP4D_EXT_ADDR(__solo) \
-		(SOLO_DREF_EXT_ADDR(__solo) + \
-		 (SOLO_DREF_EXT_SIZE * __solo->nr_chans))
-#define SOLO_MP4D_EXT_SIZE			0x00080000
-
-#define SOLO_JPEG_EXT_ADDR(__solo) \
-		(SOLO_MP4D_EXT_ADDR(__solo) + \
-		 (SOLO_MP4D_EXT_SIZE * __solo->nr_chans))
-#define SOLO_JPEG_EXT_SIZE(__solo)		(0x00080000 * __solo->nr_chans)
-
-#endif /* __SOLO6X10_OFFSETS_H */
diff --git a/drivers/staging/media/solo6x10/osd-font.h b/drivers/staging/media/solo6x10/osd-font.h
deleted file mode 100644
index 591e0e8..0000000
--- a/drivers/staging/media/solo6x10/osd-font.h
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Copyright (C) 2010 Bluecherry, LLC www.bluecherrydvr.com
- * Copyright (C) 2010 Ben Collins <bcollins@bluecherry.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You 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 __SOLO6X10_OSD_FONT_H
-#define __SOLO6X10_OSD_FONT_H
-
-static const unsigned int solo_osd_font[] = {
-	0x00000000, 0x0000c0c8, 0xccfefe0c, 0x08000000,
-	0x00000000, 0x10103838, 0x7c7cfefe, 0x00000000,	/* 0 */
-	0x00000000, 0xfefe7c7c, 0x38381010, 0x10000000,
-	0x00000000, 0x7c82fefe, 0xfefefe7c, 0x00000000,
-	0x00000000, 0x00001038, 0x10000000, 0x00000000,
-	0x00000000, 0x0010387c, 0xfe7c3810, 0x00000000,
-	0x00000000, 0x00384444, 0x44380000, 0x00000000,
-	0x00000000, 0x38448282, 0x82443800, 0x00000000,
-	0x00000000, 0x007c7c7c, 0x7c7c0000, 0x00000000,
-	0x00000000, 0x6c6c6c6c, 0x6c6c6c6c, 0x00000000,
-	0x00000000, 0x061e7efe, 0xfe7e1e06, 0x00000000,
-	0x00000000, 0xc0f0fcfe, 0xfefcf0c0, 0x00000000,
-	0x00000000, 0xc6cedefe, 0xfedecec6, 0x00000000,
-	0x00000000, 0xc6e6f6fe, 0xfef6e6c6, 0x00000000,
-	0x00000000, 0x12367efe, 0xfe7e3612, 0x00000000,
-	0x00000000, 0x90d8fcfe, 0xfefcd890, 0x00000000,
-	0x00000038, 0x7cc692ba, 0x92c67c38, 0x00000000,
-	0x00000038, 0x7cc6aa92, 0xaac67c38, 0x00000000,
-	0x00000038, 0x7830107c, 0xbaa8680c, 0x00000000,
-	0x00000038, 0x3c18127c, 0xb8382c60, 0x00000000,
-	0x00000044, 0xaa6c8254, 0x38eec67c, 0x00000000,
-	0x00000082, 0x44288244, 0x38c6827c, 0x00000000,
-	0x00000038, 0x444444fe, 0xfeeec6fe, 0x00000000,
-	0x00000018, 0x78187818, 0x3c7e7e3c, 0x00000000,
-	0x00000000, 0x3854929a, 0x82443800, 0x00000000,
-	0x00000000, 0x00c0c8cc, 0xfefe0c08, 0x00000000,
-	0x0000e0a0, 0xe040e00e, 0x8a0ea40e, 0x00000000,
-	0x0000e0a0, 0xe040e00e, 0x0a8e440e, 0x00000000,
-	0x0000007c, 0x82829292, 0x929282fe, 0x00000000,
-	0x000000f8, 0xfc046494, 0x946404fc, 0x00000000,
-	0x0000003f, 0x7f404c52, 0x524c407f, 0x00000000,
-	0x0000007c, 0x82ba82ba, 0x82ba82fe, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x183c3c3c, 0x18180018, 0x18000000,	/* 32   ! */
-	0x00000066, 0x66240000, 0x00000000, 0x00000000,
-	0x00000000, 0x6c6cfe6c, 0x6c6cfe6c, 0x6c000000,	/* 34 " # */
-	0x00001010, 0x7cd6d616, 0x7cd0d6d6, 0x7c101000,
-	0x00000000, 0x0086c660, 0x30180cc6, 0xc2000000,	/* 36 $ % */
-	0x00000000, 0x386c6c38, 0xdc766666, 0xdc000000,
-	0x0000000c, 0x0c0c0600, 0x00000000, 0x00000000,	/* 38 & ' */
-	0x00000000, 0x30180c0c, 0x0c0c0c18, 0x30000000,
-	0x00000000, 0x0c183030, 0x30303018, 0x0c000000,	/* 40 ( ) */
-	0x00000000, 0x0000663c, 0xff3c6600, 0x00000000,
-	0x00000000, 0x00001818, 0x7e181800, 0x00000000,	/* 42 * + */
-	0x00000000, 0x00000000, 0x00000e0e, 0x0c060000,
-	0x00000000, 0x00000000, 0x7e000000, 0x00000000,	/* 44 , - */
-	0x00000000, 0x00000000, 0x00000006, 0x06000000,
-	0x00000000, 0x80c06030, 0x180c0602, 0x00000000,	/* 46 . / */
-	0x0000007c, 0xc6e6f6de, 0xcec6c67c, 0x00000000,
-	0x00000030, 0x383c3030, 0x303030fc, 0x00000000,	/* 48 0 1 */
-	0x0000007c, 0xc6c06030, 0x180cc6fe, 0x00000000,
-	0x0000007c, 0xc6c0c07c, 0xc0c0c67c, 0x00000000,	/* 50 2 3 */
-	0x00000060, 0x70786c66, 0xfe6060f0, 0x00000000,
-	0x000000fe, 0x0606067e, 0xc0c0c67c, 0x00000000,	/* 52 4 5 */
-	0x00000038, 0x0c06067e, 0xc6c6c67c, 0x00000000,
-	0x000000fe, 0xc6c06030, 0x18181818, 0x00000000,	/* 54 6 7 */
-	0x0000007c, 0xc6c6c67c, 0xc6c6c67c, 0x00000000,
-	0x0000007c, 0xc6c6c6fc, 0xc0c06038, 0x00000000,	/* 56 8 9 */
-	0x00000000, 0x18180000, 0x00181800, 0x00000000,
-	0x00000000, 0x18180000, 0x0018180c, 0x00000000,	/* 58 : ; */
-	0x00000060, 0x30180c06, 0x0c183060, 0x00000000,
-	0x00000000, 0x007e0000, 0x007e0000, 0x00000000,
-	0x00000006, 0x0c183060, 0x30180c06, 0x00000000,
-	0x0000007c, 0xc6c66030, 0x30003030, 0x00000000,
-	0x0000007c, 0xc6f6d6d6, 0x7606067c, 0x00000000,
-	0x00000010, 0x386cc6c6, 0xfec6c6c6, 0x00000000,	/* 64 @ A */
-	0x0000007e, 0xc6c6c67e, 0xc6c6c67e, 0x00000000,
-	0x00000078, 0xcc060606, 0x0606cc78, 0x00000000,	/* 66 */
-	0x0000003e, 0x66c6c6c6, 0xc6c6663e, 0x00000000,
-	0x000000fe, 0x0606063e, 0x060606fe, 0x00000000,	/* 68 */
-	0x000000fe, 0x0606063e, 0x06060606, 0x00000000,
-	0x00000078, 0xcc060606, 0xf6c6ccb8, 0x00000000,	/* 70 */
-	0x000000c6, 0xc6c6c6fe, 0xc6c6c6c6, 0x00000000,
-	0x0000003c, 0x18181818, 0x1818183c, 0x00000000,	/* 72 */
-	0x00000060, 0x60606060, 0x6066663c, 0x00000000,
-	0x000000c6, 0xc666361e, 0x3666c6c6, 0x00000000,	/* 74 */
-	0x00000006, 0x06060606, 0x060606fe, 0x00000000,
-	0x000000c6, 0xeefed6c6, 0xc6c6c6c6, 0x00000000,	/* 76 */
-	0x000000c6, 0xcedefef6, 0xe6c6c6c6, 0x00000000,
-	0x00000038, 0x6cc6c6c6, 0xc6c66c38, 0x00000000,	/* 78 */
-	0x0000007e, 0xc6c6c67e, 0x06060606, 0x00000000,
-	0x00000038, 0x6cc6c6c6, 0xc6d67c38, 0x60000000,	/* 80 */
-	0x0000007e, 0xc6c6c67e, 0x66c6c6c6, 0x00000000,
-	0x0000007c, 0xc6c60c38, 0x60c6c67c, 0x00000000,	/* 82 */
-	0x0000007e, 0x18181818, 0x18181818, 0x00000000,
-	0x000000c6, 0xc6c6c6c6, 0xc6c6c67c, 0x00000000,	/* 84 */
-	0x000000c6, 0xc6c6c6c6, 0xc66c3810, 0x00000000,
-	0x000000c6, 0xc6c6c6c6, 0xd6d6fe6c, 0x00000000,	/* 86 */
-	0x000000c6, 0xc6c66c38, 0x6cc6c6c6, 0x00000000,
-	0x00000066, 0x66666666, 0x3c181818, 0x00000000,	/* 88 */
-	0x000000fe, 0xc0603018, 0x0c0606fe, 0x00000000,
-	0x0000003c, 0x0c0c0c0c, 0x0c0c0c3c, 0x00000000,	/* 90 */
-	0x00000002, 0x060c1830, 0x60c08000, 0x00000000,
-	0x0000003c, 0x30303030, 0x3030303c, 0x00000000,	/* 92 */
-	0x00001038, 0x6cc60000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00fe0000,
-	0x00001818, 0x30000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00003c60, 0x7c66667c, 0x00000000,
-	0x0000000c, 0x0c0c7ccc, 0xcccccc7c, 0x00000000,
-	0x00000000, 0x00007cc6, 0x0606c67c, 0x00000000,
-	0x00000060, 0x60607c66, 0x6666667c, 0x00000000,
-	0x00000000, 0x00007cc6, 0xfe06c67c, 0x00000000,
-	0x00000078, 0x0c0c0c3e, 0x0c0c0c0c, 0x00000000,
-	0x00000000, 0x00007c66, 0x6666667c, 0x60603e00,
-	0x0000000c, 0x0c0c7ccc, 0xcccccccc, 0x00000000,
-	0x00000030, 0x30003830, 0x30303078, 0x00000000,
-	0x00000030, 0x30003c30, 0x30303030, 0x30301f00,
-	0x0000000c, 0x0c0ccc6c, 0x3c6ccccc, 0x00000000,
-	0x00000030, 0x30303030, 0x30303030, 0x00000000,
-	0x00000000, 0x000066fe, 0xd6d6d6d6, 0x00000000,
-	0x00000000, 0x000078cc, 0xcccccccc, 0x00000000,
-	0x00000000, 0x00007cc6, 0xc6c6c67c, 0x00000000,
-	0x00000000, 0x00007ccc, 0xcccccc7c, 0x0c0c0c00,
-	0x00000000, 0x00007c66, 0x6666667c, 0x60606000,
-	0x00000000, 0x000076dc, 0x0c0c0c0c, 0x00000000,
-	0x00000000, 0x00007cc6, 0x1c70c67c, 0x00000000,
-	0x00000000, 0x1818fe18, 0x18181870, 0x00000000,
-	0x00000000, 0x00006666, 0x6666663c, 0x00000000,
-	0x00000000, 0x0000c6c6, 0xc66c3810, 0x00000000,
-	0x00000000, 0x0000c6d6, 0xd6d6fe6c, 0x00000000,
-	0x00000000, 0x0000c66c, 0x38386cc6, 0x00000000,
-	0x00000000, 0x00006666, 0x6666667c, 0x60603e00,
-	0x00000000, 0x0000fe60, 0x30180cfe, 0x00000000,
-	0x00000070, 0x1818180e, 0x18181870, 0x00000000,
-	0x00000018, 0x18181800, 0x18181818, 0x00000000,
-	0x0000000e, 0x18181870, 0x1818180e, 0x00000000,
-	0x000000dc, 0x76000000, 0x00000000, 0x00000000,
-	0x00000000, 0x0010386c, 0xc6c6fe00, 0x00000000
-};
-
-#endif /* __SOLO6X10_OSD_FONT_H */
diff --git a/drivers/staging/media/solo6x10/p2m.c b/drivers/staging/media/solo6x10/p2m.c
deleted file mode 100644
index 58ab61b..0000000
--- a/drivers/staging/media/solo6x10/p2m.c
+++ /dev/null
@@ -1,306 +0,0 @@
-/*
- * Copyright (C) 2010 Bluecherry, LLC www.bluecherrydvr.com
- * Copyright (C) 2010 Ben Collins <bcollins@bluecherry.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You 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/scatterlist.h>
-#include "solo6x10.h"
-
-/* #define SOLO_TEST_P2M */
-
-int solo_p2m_dma(struct solo_dev *solo_dev, u8 id, int wr,
-		 void *sys_addr, u32 ext_addr, u32 size)
-{
-	dma_addr_t dma_addr;
-	int ret;
-
-	WARN_ON(!size);
-	BUG_ON(id >= SOLO_NR_P2M);
-
-	if (!size)
-		return -EINVAL;
-
-	dma_addr = pci_map_single(solo_dev->pdev, sys_addr, size,
-				  wr ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
-
-	ret = solo_p2m_dma_t(solo_dev, id, wr, dma_addr, ext_addr, size);
-
-	pci_unmap_single(solo_dev->pdev, dma_addr, size,
-			 wr ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
-
-	return ret;
-}
-
-int solo_p2m_dma_t(struct solo_dev *solo_dev, u8 id, int wr,
-		   dma_addr_t dma_addr, u32 ext_addr, u32 size)
-{
-	struct p2m_desc *desc = kzalloc(sizeof(*desc) * 2, GFP_DMA);
-	int ret;
-
-	if (desc == NULL)
-		return -ENOMEM;
-
-	solo_p2m_push_desc(&desc[1], wr, dma_addr, ext_addr, size, 0, 0);
-	ret = solo_p2m_dma_desc(solo_dev, id, desc, 2);
-	kfree(desc);
-
-	return ret;
-}
-
-void solo_p2m_push_desc(struct p2m_desc *desc, int wr, dma_addr_t dma_addr,
-			u32 ext_addr, u32 size, int repeat, u32 ext_size)
-{
-	desc->ta = cpu_to_le32(dma_addr);
-	desc->fa = cpu_to_le32(ext_addr);
-
-	desc->ext = cpu_to_le32(SOLO_P2M_COPY_SIZE(size >> 2));
-	desc->ctrl = cpu_to_le32(SOLO_P2M_BURST_SIZE(SOLO_P2M_BURST_256) |
-				 (wr ? SOLO_P2M_WRITE : 0) | SOLO_P2M_TRANS_ON);
-
-	/* Ext size only matters when we're repeating */
-	if (repeat) {
-		desc->ext |= cpu_to_le32(SOLO_P2M_EXT_INC(ext_size >> 2));
-		desc->ctrl |=  cpu_to_le32(SOLO_P2M_PCI_INC(size >> 2) |
-					   SOLO_P2M_REPEAT(repeat));
-	}
-}
-
-int solo_p2m_dma_desc(struct solo_dev *solo_dev, u8 id,
-		      struct p2m_desc *desc, int desc_count)
-{
-	struct solo_p2m_dev *p2m_dev;
-	unsigned int timeout;
-	int ret = 0;
-	u32 config = 0;
-	dma_addr_t desc_dma = 0;
-
-	BUG_ON(id >= SOLO_NR_P2M);
-	BUG_ON(!desc_count || desc_count > SOLO_NR_P2M_DESC);
-
-	p2m_dev = &solo_dev->p2m_dev[id];
-
-	mutex_lock(&p2m_dev->mutex);
-
-	solo_reg_write(solo_dev, SOLO_P2M_CONTROL(id), 0);
-
-	INIT_COMPLETION(p2m_dev->completion);
-	p2m_dev->error = 0;
-
-	/* Enable the descriptors */
-	config = solo_reg_read(solo_dev, SOLO_P2M_CONFIG(id));
-	desc_dma = pci_map_single(solo_dev->pdev, desc,
-				  desc_count * sizeof(*desc),
-				  PCI_DMA_TODEVICE);
-	solo_reg_write(solo_dev, SOLO_P2M_DES_ADR(id), desc_dma);
-	solo_reg_write(solo_dev, SOLO_P2M_DESC_ID(id), desc_count - 1);
-	solo_reg_write(solo_dev, SOLO_P2M_CONFIG(id), config |
-		       SOLO_P2M_DESC_MODE);
-
-	/* Should have all descriptors completed from one interrupt */
-	timeout = wait_for_completion_timeout(&p2m_dev->completion, HZ);
-
-	solo_reg_write(solo_dev, SOLO_P2M_CONTROL(id), 0);
-
-	/* Reset back to non-descriptor mode */
-	solo_reg_write(solo_dev, SOLO_P2M_CONFIG(id), config);
-	solo_reg_write(solo_dev, SOLO_P2M_DESC_ID(id), 0);
-	solo_reg_write(solo_dev, SOLO_P2M_DES_ADR(id), 0);
-	pci_unmap_single(solo_dev->pdev, desc_dma,
-			 desc_count * sizeof(*desc),
-			 PCI_DMA_TODEVICE);
-
-	if (p2m_dev->error)
-		ret = -EIO;
-	else if (timeout == 0)
-		ret = -EAGAIN;
-
-	mutex_unlock(&p2m_dev->mutex);
-
-	WARN_ON_ONCE(ret);
-
-	return ret;
-}
-
-int solo_p2m_dma_sg(struct solo_dev *solo_dev, u8 id,
-		    struct p2m_desc *pdesc, int wr,
-		    struct scatterlist *sg, u32 sg_off,
-		    u32 ext_addr, u32 size)
-{
-	int i;
-	int idx;
-
-	BUG_ON(id >= SOLO_NR_P2M);
-
-	if (WARN_ON_ONCE(!size))
-		return -EINVAL;
-
-	memset(pdesc, 0, sizeof(*pdesc));
-
-	/* Should rewrite this to handle > SOLO_NR_P2M_DESC transactions */
-	for (i = 0, idx = 1; idx < SOLO_NR_P2M_DESC && sg && size > 0;
-	     i++, sg = sg_next(sg)) {
-		struct p2m_desc *desc = &pdesc[idx];
-		u32 sg_len = sg_dma_len(sg);
-		u32 len;
-
-		if (sg_off >= sg_len) {
-			sg_off -= sg_len;
-			continue;
-		}
-
-		sg_len -= sg_off;
-		len = min(sg_len, size);
-
-		solo_p2m_push_desc(desc, wr, sg_dma_address(sg) + sg_off,
-				   ext_addr, len, 0, 0);
-
-		size -= len;
-		ext_addr += len;
-		idx++;
-
-		sg_off = 0;
-	}
-
-	WARN_ON_ONCE(size || i >= SOLO_NR_P2M_DESC);
-
-	return solo_p2m_dma_desc(solo_dev, id, pdesc, idx);
-}
-
-#ifdef SOLO_TEST_P2M
-
-#define P2M_TEST_CHAR		0xbe
-
-static unsigned long long p2m_test(struct solo_dev *solo_dev, u8 id,
-				   u32 base, int size)
-{
-	u8 *wr_buf;
-	u8 *rd_buf;
-	int i;
-	unsigned long long err_cnt = 0;
-
-	wr_buf = kmalloc(size, GFP_KERNEL);
-	if (!wr_buf) {
-		printk(SOLO6X10_NAME ": Failed to malloc for p2m_test\n");
-		return size;
-	}
-
-	rd_buf = kmalloc(size, GFP_KERNEL);
-	if (!rd_buf) {
-		printk(SOLO6X10_NAME ": Failed to malloc for p2m_test\n");
-		kfree(wr_buf);
-		return size;
-	}
-
-	memset(wr_buf, P2M_TEST_CHAR, size);
-	memset(rd_buf, P2M_TEST_CHAR + 1, size);
-
-	solo_p2m_dma(solo_dev, id, 1, wr_buf, base, size);
-	solo_p2m_dma(solo_dev, id, 0, rd_buf, base, size);
-
-	for (i = 0; i < size; i++)
-		if (wr_buf[i] != rd_buf[i])
-			err_cnt++;
-
-	kfree(wr_buf);
-	kfree(rd_buf);
-
-	return err_cnt;
-}
-
-#define TEST_CHUNK_SIZE		(8 * 1024)
-
-static void run_p2m_test(struct solo_dev *solo_dev)
-{
-	unsigned long long errs = 0;
-	u32 size = SOLO_JPEG_EXT_ADDR(solo_dev) + SOLO_JPEG_EXT_SIZE(solo_dev);
-	int i, d;
-
-	dev_warn(&solo_dev->pdev->dev, "Testing %u bytes of external ram\n",
-		 size);
-
-	for (i = 0; i < size; i += TEST_CHUNK_SIZE)
-		for (d = 0; d < 4; d++)
-			errs += p2m_test(solo_dev, d, i, TEST_CHUNK_SIZE);
-
-	dev_warn(&solo_dev->pdev->dev, "Found %llu errors during p2m test\n",
-		 errs);
-
-	return;
-}
-#else
-#define run_p2m_test(__solo)	do {} while (0)
-#endif
-
-void solo_p2m_isr(struct solo_dev *solo_dev, int id)
-{
-	struct solo_p2m_dev *p2m_dev = &solo_dev->p2m_dev[id];
-
-	solo_reg_write(solo_dev, SOLO_IRQ_STAT, SOLO_IRQ_P2M(id));
-
-	complete(&p2m_dev->completion);
-}
-
-void solo_p2m_error_isr(struct solo_dev *solo_dev, u32 status)
-{
-	struct solo_p2m_dev *p2m_dev;
-	int i;
-
-	if (!(status & SOLO_PCI_ERR_P2M))
-		return;
-
-	for (i = 0; i < SOLO_NR_P2M; i++) {
-		p2m_dev = &solo_dev->p2m_dev[i];
-		p2m_dev->error = 1;
-		solo_reg_write(solo_dev, SOLO_P2M_CONTROL(i), 0);
-		complete(&p2m_dev->completion);
-	}
-}
-
-void solo_p2m_exit(struct solo_dev *solo_dev)
-{
-	int i;
-
-	for (i = 0; i < SOLO_NR_P2M; i++)
-		solo_irq_off(solo_dev, SOLO_IRQ_P2M(i));
-}
-
-int solo_p2m_init(struct solo_dev *solo_dev)
-{
-	struct solo_p2m_dev *p2m_dev;
-	int i;
-
-	for (i = 0; i < SOLO_NR_P2M; i++) {
-		p2m_dev = &solo_dev->p2m_dev[i];
-
-		mutex_init(&p2m_dev->mutex);
-		init_completion(&p2m_dev->completion);
-
-		solo_reg_write(solo_dev, SOLO_P2M_CONTROL(i), 0);
-		solo_reg_write(solo_dev, SOLO_P2M_CONFIG(i),
-			       SOLO_P2M_CSC_16BIT_565 |
-			       SOLO_P2M_DMA_INTERVAL(3) |
-			       SOLO_P2M_DESC_INTR_OPT |
-			       SOLO_P2M_PCI_MASTER_MODE);
-		solo_irq_on(solo_dev, SOLO_IRQ_P2M(i));
-	}
-
-	run_p2m_test(solo_dev);
-
-	return 0;
-}
diff --git a/drivers/staging/media/solo6x10/registers.h b/drivers/staging/media/solo6x10/registers.h
deleted file mode 100644
index aca5444..0000000
--- a/drivers/staging/media/solo6x10/registers.h
+++ /dev/null
@@ -1,637 +0,0 @@
-/*
- * Copyright (C) 2010 Bluecherry, LLC www.bluecherrydvr.com
- * Copyright (C) 2010 Ben Collins <bcollins@bluecherry.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You 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 __SOLO6X10_REGISTERS_H
-#define __SOLO6X10_REGISTERS_H
-
-#include "offsets.h"
-
-/* Global 6X10 system configuration */
-#define SOLO_SYS_CFG				0x0000
-#define   SOLO6010_SYS_CFG_FOUT_EN		0x00000001 /* 6010 only */
-#define   SOLO6010_SYS_CFG_PLL_BYPASS		0x00000002 /* 6010 only */
-#define   SOLO6010_SYS_CFG_PLL_PWDN		0x00000004 /* 6010 only */
-#define   SOLO6010_SYS_CFG_OUTDIV(__n)		(((__n) & 0x003) << 3) /* 6010 only */
-#define   SOLO6010_SYS_CFG_FEEDBACKDIV(__n)	(((__n) & 0x1ff) << 5) /* 6010 only */
-#define   SOLO6010_SYS_CFG_INPUTDIV(__n)	(((__n) & 0x01f) << 14) /* 6010 only */
-#define   SOLO_SYS_CFG_CLOCK_DIV		0x00080000
-#define   SOLO_SYS_CFG_NCLK_DELAY(__n)		(((__n) & 0x003) << 24)
-#define   SOLO_SYS_CFG_PCLK_DELAY(__n)		(((__n) & 0x00f) << 26)
-#define   SOLO_SYS_CFG_SDRAM64BIT		0x40000000 /* 6110: must be set */
-#define   SOLO_SYS_CFG_RESET			0x80000000
-
-#define	SOLO_DMA_CTRL				0x0004
-#define	  SOLO_DMA_CTRL_REFRESH_CYCLE(n)	((n)<<8)
-/* 0=16/32MB, 1=32/64MB, 2=64/128MB, 3=128/256MB */
-#define	  SOLO_DMA_CTRL_SDRAM_SIZE(n)		((n)<<6)
-#define	  SOLO_DMA_CTRL_SDRAM_CLK_INVERT	(1<<5)
-#define	  SOLO_DMA_CTRL_STROBE_SELECT		(1<<4)
-#define	  SOLO_DMA_CTRL_READ_DATA_SELECT	(1<<3)
-#define	  SOLO_DMA_CTRL_READ_CLK_SELECT		(1<<2)
-#define	  SOLO_DMA_CTRL_LATENCY(n)		((n)<<0)
-#define	SOLO_DMA_CTRL1				0x0008
-
-#define SOLO_SYS_VCLK				0x000C
-#define	  SOLO_VCLK_INVERT			(1<<22)
-/* 0=sys_clk/4, 1=sys_clk/2, 2=clk_in/2 of system input */
-#define	  SOLO_VCLK_SELECT(n)			((n)<<20)
-#define	  SOLO_VCLK_VIN1415_DELAY(n)		((n)<<14)
-#define	  SOLO_VCLK_VIN1213_DELAY(n)		((n)<<12)
-#define	  SOLO_VCLK_VIN1011_DELAY(n)		((n)<<10)
-#define	  SOLO_VCLK_VIN0809_DELAY(n)		((n)<<8)
-#define	  SOLO_VCLK_VIN0607_DELAY(n)		((n)<<6)
-#define	  SOLO_VCLK_VIN0405_DELAY(n)		((n)<<4)
-#define	  SOLO_VCLK_VIN0203_DELAY(n)		((n)<<2)
-#define	  SOLO_VCLK_VIN0001_DELAY(n)		((n)<<0)
-
-#define SOLO_IRQ_STAT				0x0010
-#define SOLO_IRQ_ENABLE				0x0014
-#define	  SOLO_IRQ_P2M(n)			(1<<((n)+17))
-#define	  SOLO_IRQ_GPIO				(1<<16)
-#define	  SOLO_IRQ_VIDEO_LOSS			(1<<15)
-#define	  SOLO_IRQ_VIDEO_IN			(1<<14)
-#define	  SOLO_IRQ_MOTION			(1<<13)
-#define	  SOLO_IRQ_ATA_CMD			(1<<12)
-#define	  SOLO_IRQ_ATA_DIR			(1<<11)
-#define	  SOLO_IRQ_PCI_ERR			(1<<10)
-#define	  SOLO_IRQ_PS2_1			(1<<9)
-#define	  SOLO_IRQ_PS2_0			(1<<8)
-#define	  SOLO_IRQ_SPI				(1<<7)
-#define	  SOLO_IRQ_IIC				(1<<6)
-#define	  SOLO_IRQ_UART(n)			(1<<((n) + 4))
-#define	  SOLO_IRQ_G723				(1<<3)
-#define	  SOLO_IRQ_DECODER			(1<<1)
-#define	  SOLO_IRQ_ENCODER			(1<<0)
-
-#define SOLO_CHIP_OPTION			0x001C
-#define   SOLO_CHIP_ID_MASK			0x00000007
-
-#define SOLO6110_PLL_CONFIG			0x0020
-#define   SOLO6110_PLL_RANGE_BYPASS		(0 << 20)
-#define   SOLO6110_PLL_RANGE_5_10MHZ		(1 << 20)
-#define   SOLO6110_PLL_RANGE_8_16MHZ		(2 << 20)
-#define   SOLO6110_PLL_RANGE_13_26MHZ		(3 << 20)
-#define   SOLO6110_PLL_RANGE_21_42MHZ		(4 << 20)
-#define   SOLO6110_PLL_RANGE_34_68MHZ		(5 << 20)
-#define   SOLO6110_PLL_RANGE_54_108MHZ		(6 << 20)
-#define   SOLO6110_PLL_RANGE_88_200MHZ		(7 << 20)
-#define   SOLO6110_PLL_DIVR(x)			(((x) - 1) << 15)
-#define   SOLO6110_PLL_DIVQ_EXP(x)		((x) << 12)
-#define   SOLO6110_PLL_DIVF(x)			(((x) - 1) << 4)
-#define   SOLO6110_PLL_RESET			(1 << 3)
-#define   SOLO6110_PLL_BYPASS			(1 << 2)
-#define   SOLO6110_PLL_FSEN			(1 << 1)
-#define   SOLO6110_PLL_FB			(1 << 0)
-
-#define SOLO_EEPROM_CTRL			0x0060
-#define	  SOLO_EEPROM_ACCESS_EN			(1<<7)
-#define	  SOLO_EEPROM_CS			(1<<3)
-#define	  SOLO_EEPROM_CLK			(1<<2)
-#define	  SOLO_EEPROM_DO			(1<<1)
-#define	  SOLO_EEPROM_DI			(1<<0)
-#define	  SOLO_EEPROM_ENABLE			(EEPROM_ACCESS_EN | EEPROM_CS)
-
-#define SOLO_PCI_ERR				0x0070
-#define   SOLO_PCI_ERR_FATAL			0x00000001
-#define   SOLO_PCI_ERR_PARITY			0x00000002
-#define   SOLO_PCI_ERR_TARGET			0x00000004
-#define   SOLO_PCI_ERR_TIMEOUT			0x00000008
-#define   SOLO_PCI_ERR_P2M			0x00000010
-#define   SOLO_PCI_ERR_ATA			0x00000020
-#define   SOLO_PCI_ERR_P2M_DESC			0x00000040
-#define   SOLO_PCI_ERR_FSM0(__s)		(((__s) >> 16) & 0x0f)
-#define   SOLO_PCI_ERR_FSM1(__s)		(((__s) >> 20) & 0x0f)
-#define   SOLO_PCI_ERR_FSM2(__s)		(((__s) >> 24) & 0x1f)
-
-#define SOLO_P2M_BASE				0x0080
-
-#define SOLO_P2M_CONFIG(n)			(0x0080 + ((n)*0x20))
-#define	  SOLO_P2M_DMA_INTERVAL(n)		((n)<<6)/* N*32 clocks */
-#define	  SOLO_P2M_CSC_BYTE_REORDER		(1<<5)	/* BGR -> RGB */
-/* 0:r=[14:10] g=[9:5] b=[4:0], 1:r=[15:11] g=[10:5] b=[4:0] */
-#define	  SOLO_P2M_CSC_16BIT_565		(1<<4)
-#define	  SOLO_P2M_UV_SWAP			(1<<3)
-#define	  SOLO_P2M_PCI_MASTER_MODE		(1<<2)
-#define	  SOLO_P2M_DESC_INTR_OPT		(1<<1)	/* 1:Empty, 0:Each */
-#define	  SOLO_P2M_DESC_MODE			(1<<0)
-
-#define SOLO_P2M_DES_ADR(n)			(0x0084 + ((n)*0x20))
-
-#define SOLO_P2M_DESC_ID(n)			(0x0088 + ((n)*0x20))
-#define	  SOLO_P2M_UPDATE_ID(n)			((n)<<0)
-
-#define SOLO_P2M_STATUS(n)			(0x008C + ((n)*0x20))
-#define	  SOLO_P2M_COMMAND_DONE			(1<<8)
-#define	  SOLO_P2M_CURRENT_ID(stat)		(0xff & (stat))
-
-#define SOLO_P2M_CONTROL(n)			(0x0090 + ((n)*0x20))
-#define	  SOLO_P2M_PCI_INC(n)			((n)<<20)
-#define	  SOLO_P2M_REPEAT(n)			((n)<<10)
-/* 0:512, 1:256, 2:128, 3:64, 4:32, 5:128(2page) */
-#define	  SOLO_P2M_BURST_SIZE(n)		((n)<<7)
-#define	    SOLO_P2M_BURST_512			0
-#define	    SOLO_P2M_BURST_256			1
-#define	    SOLO_P2M_BURST_128			2
-#define	    SOLO_P2M_BURST_64			3
-#define	    SOLO_P2M_BURST_32			4
-#define	  SOLO_P2M_CSC_16BIT			(1<<6)	/* 0:24bit, 1:16bit */
-/* 0:Y[0]<-0(OFF), 1:Y[0]<-1(ON), 2:Y[0]<-G[0], 3:Y[0]<-Bit[15] */
-#define	  SOLO_P2M_ALPHA_MODE(n)		((n)<<4)
-#define	  SOLO_P2M_CSC_ON			(1<<3)
-#define	  SOLO_P2M_INTERRUPT_REQ		(1<<2)
-#define	  SOLO_P2M_WRITE			(1<<1)
-#define	  SOLO_P2M_TRANS_ON			(1<<0)
-
-#define SOLO_P2M_EXT_CFG(n)			(0x0094 + ((n)*0x20))
-#define	  SOLO_P2M_EXT_INC(n)			((n)<<20)
-#define	  SOLO_P2M_COPY_SIZE(n)			((n)<<0)
-
-#define SOLO_P2M_TAR_ADR(n)			(0x0098 + ((n)*0x20))
-
-#define SOLO_P2M_EXT_ADR(n)			(0x009C + ((n)*0x20))
-
-#define SOLO_P2M_BUFFER(i)			(0x2000 + ((i)*4))
-
-#define SOLO_VI_CH_SWITCH_0			0x0100
-#define SOLO_VI_CH_SWITCH_1			0x0104
-#define SOLO_VI_CH_SWITCH_2			0x0108
-
-#define	SOLO_VI_CH_ENA				0x010C
-#define	SOLO_VI_CH_FORMAT			0x0110
-#define	  SOLO_VI_FD_SEL_MASK(n)		((n)<<16)
-#define	  SOLO_VI_PROG_MASK(n)			((n)<<0)
-
-#define SOLO_VI_FMT_CFG				0x0114
-#define	  SOLO_VI_FMT_CHECK_VCOUNT		(1<<31)
-#define	  SOLO_VI_FMT_CHECK_HCOUNT		(1<<30)
-#define   SOLO_VI_FMT_TEST_SIGNAL		(1<<28)
-
-#define	SOLO_VI_PAGE_SW				0x0118
-#define	  SOLO_FI_INV_DISP_LIVE(n)		((n)<<8)
-#define	  SOLO_FI_INV_DISP_OUT(n)		((n)<<7)
-#define	  SOLO_DISP_SYNC_FI(n)			((n)<<6)
-#define	  SOLO_PIP_PAGE_ADD(n)			((n)<<3)
-#define	  SOLO_NORMAL_PAGE_ADD(n)		((n)<<0)
-
-#define	SOLO_VI_ACT_I_P				0x011C
-#define	SOLO_VI_ACT_I_S				0x0120
-#define	SOLO_VI_ACT_P				0x0124
-#define	  SOLO_VI_FI_INVERT			(1<<31)
-#define	  SOLO_VI_H_START(n)			((n)<<21)
-#define	  SOLO_VI_V_START(n)			((n)<<11)
-#define	  SOLO_VI_V_STOP(n)			((n)<<0)
-
-#define SOLO_VI_STATUS0				0x0128
-#define   SOLO_VI_STATUS0_PAGE(__n)		((__n) & 0x07)
-#define SOLO_VI_STATUS1				0x012C
-
-/* XXX: Might be better off in kernel level disp.h */
-#define DISP_PAGE(stat)				((stat) & 0x07)
-
-#define SOLO_VI_PB_CONFIG			0x0130
-#define	  SOLO_VI_PB_USER_MODE			(1<<1)
-#define	  SOLO_VI_PB_PAL			(1<<0)
-#define SOLO_VI_PB_RANGE_HV			0x0134
-#define	  SOLO_VI_PB_HSIZE(h)			((h)<<12)
-#define	  SOLO_VI_PB_VSIZE(v)			((v)<<0)
-#define SOLO_VI_PB_ACT_H			0x0138
-#define	  SOLO_VI_PB_HSTART(n)			((n)<<12)
-#define	  SOLO_VI_PB_HSTOP(n)			((n)<<0)
-#define SOLO_VI_PB_ACT_V			0x013C
-#define	  SOLO_VI_PB_VSTART(n)			((n)<<12)
-#define	  SOLO_VI_PB_VSTOP(n)			((n)<<0)
-
-#define	SOLO_VI_MOSAIC(ch)			(0x0140 + ((ch)*4))
-#define	  SOLO_VI_MOSAIC_SX(x)			((x)<<24)
-#define	  SOLO_VI_MOSAIC_EX(x)			((x)<<16)
-#define	  SOLO_VI_MOSAIC_SY(x)			((x)<<8)
-#define	  SOLO_VI_MOSAIC_EY(x)			((x)<<0)
-
-#define	SOLO_VI_WIN_CTRL0(ch)			(0x0180 + ((ch)*4))
-#define	SOLO_VI_WIN_CTRL1(ch)			(0x01C0 + ((ch)*4))
-
-#define	  SOLO_VI_WIN_CHANNEL(n)		((n)<<28)
-
-#define	  SOLO_VI_WIN_PIP(n)			((n)<<27)
-#define	  SOLO_VI_WIN_SCALE(n)			((n)<<24)
-
-#define	  SOLO_VI_WIN_SX(x)			((x)<<12)
-#define	  SOLO_VI_WIN_EX(x)			((x)<<0)
-
-#define	  SOLO_VI_WIN_SY(x)			((x)<<12)
-#define	  SOLO_VI_WIN_EY(x)			((x)<<0)
-
-#define	SOLO_VI_WIN_ON(ch)			(0x0200 + ((ch)*4))
-
-#define SOLO_VI_WIN_SW				0x0240
-#define SOLO_VI_WIN_LIVE_AUTO_MUTE		0x0244
-
-#define	SOLO_VI_MOT_ADR				0x0260
-#define	  SOLO_VI_MOTION_EN(mask)		((mask)<<16)
-#define	SOLO_VI_MOT_CTRL			0x0264
-#define	  SOLO_VI_MOTION_FRAME_COUNT(n)		((n)<<24)
-#define	  SOLO_VI_MOTION_SAMPLE_LENGTH(n)	((n)<<16)
-#define	  SOLO_VI_MOTION_INTR_START_STOP	(1<<15)
-#define	  SOLO_VI_MOTION_FREEZE_DATA		(1<<14)
-#define	  SOLO_VI_MOTION_SAMPLE_COUNT(n)	((n)<<0)
-#define SOLO_VI_MOT_CLEAR			0x0268
-#define SOLO_VI_MOT_STATUS			0x026C
-#define	  SOLO_VI_MOTION_CNT(n)			((n)<<0)
-#define SOLO_VI_MOTION_BORDER			0x0270
-#define SOLO_VI_MOTION_BAR			0x0274
-#define	  SOLO_VI_MOTION_Y_SET			(1<<29)
-#define	  SOLO_VI_MOTION_Y_ADD			(1<<28)
-#define	  SOLO_VI_MOTION_CB_SET			(1<<27)
-#define	  SOLO_VI_MOTION_CB_ADD			(1<<26)
-#define	  SOLO_VI_MOTION_CR_SET			(1<<25)
-#define	  SOLO_VI_MOTION_CR_ADD			(1<<24)
-#define	  SOLO_VI_MOTION_Y_VALUE(v)		((v)<<16)
-#define	  SOLO_VI_MOTION_CB_VALUE(v)		((v)<<8)
-#define	  SOLO_VI_MOTION_CR_VALUE(v)		((v)<<0)
-
-#define	SOLO_VO_FMT_ENC				0x0300
-#define	  SOLO_VO_SCAN_MODE_PROGRESSIVE		(1<<31)
-#define	  SOLO_VO_FMT_TYPE_PAL			(1<<30)
-#define   SOLO_VO_FMT_TYPE_NTSC			0
-#define	  SOLO_VO_USER_SET			(1<<29)
-
-#define	  SOLO_VO_FI_CHANGE			(1<<20)
-#define	  SOLO_VO_USER_COLOR_SET_VSYNC		(1<<19)
-#define	  SOLO_VO_USER_COLOR_SET_HSYNC		(1<<18)
-#define	  SOLO_VO_USER_COLOR_SET_NAV		(1<<17)
-#define	  SOLO_VO_USER_COLOR_SET_NAH		(1<<16)
-#define	  SOLO_VO_NA_COLOR_Y(Y)			((Y)<<8)
-#define	  SOLO_VO_NA_COLOR_CB(CB)		(((CB)/16)<<4)
-#define	  SOLO_VO_NA_COLOR_CR(CR)		(((CR)/16)<<0)
-
-#define	SOLO_VO_ACT_H				0x0304
-#define	  SOLO_VO_H_BLANK(n)			((n)<<22)
-#define	  SOLO_VO_H_START(n)			((n)<<11)
-#define	  SOLO_VO_H_STOP(n)			((n)<<0)
-
-#define	SOLO_VO_ACT_V				0x0308
-#define	  SOLO_VO_V_BLANK(n)			((n)<<22)
-#define	  SOLO_VO_V_START(n)			((n)<<11)
-#define	  SOLO_VO_V_STOP(n)			((n)<<0)
-
-#define	SOLO_VO_RANGE_HV			0x030C
-#define	  SOLO_VO_SYNC_INVERT			(1<<24)
-#define	  SOLO_VO_HSYNC_INVERT			(1<<23)
-#define	  SOLO_VO_VSYNC_INVERT			(1<<22)
-#define	  SOLO_VO_H_LEN(n)			((n)<<11)
-#define	  SOLO_VO_V_LEN(n)			((n)<<0)
-
-#define	SOLO_VO_DISP_CTRL			0x0310
-#define	  SOLO_VO_DISP_ON			(1<<31)
-#define	  SOLO_VO_DISP_ERASE_COUNT(n)		((n&0xf)<<24)
-#define	  SOLO_VO_DISP_DOUBLE_SCAN		(1<<22)
-#define	  SOLO_VO_DISP_SINGLE_PAGE		(1<<21)
-#define	  SOLO_VO_DISP_BASE(n)			(((n)>>16) & 0xffff)
-
-#define SOLO_VO_DISP_ERASE			0x0314
-#define	  SOLO_VO_DISP_ERASE_ON			(1<<0)
-
-#define	SOLO_VO_ZOOM_CTRL			0x0318
-#define	  SOLO_VO_ZOOM_VER_ON			(1<<24)
-#define	  SOLO_VO_ZOOM_HOR_ON			(1<<23)
-#define	  SOLO_VO_ZOOM_V_COMP			(1<<22)
-#define	  SOLO_VO_ZOOM_SX(h)			(((h)/2)<<11)
-#define	  SOLO_VO_ZOOM_SY(v)			(((v)/2)<<0)
-
-#define SOLO_VO_FREEZE_CTRL			0x031C
-#define	  SOLO_VO_FREEZE_ON			(1<<1)
-#define	  SOLO_VO_FREEZE_INTERPOLATION		(1<<0)
-
-#define	SOLO_VO_BKG_COLOR			0x0320
-#define	  SOLO_BG_Y(y)				((y)<<16)
-#define	  SOLO_BG_U(u)				((u)<<8)
-#define	  SOLO_BG_V(v)				((v)<<0)
-
-#define	SOLO_VO_DEINTERLACE			0x0324
-#define	  SOLO_VO_DEINTERLACE_THRESHOLD(n)	((n)<<8)
-#define	  SOLO_VO_DEINTERLACE_EDGE_VALUE(n)	((n)<<0)
-
-#define SOLO_VO_BORDER_LINE_COLOR		0x0330
-#define SOLO_VO_BORDER_FILL_COLOR		0x0334
-#define SOLO_VO_BORDER_LINE_MASK		0x0338
-#define SOLO_VO_BORDER_FILL_MASK		0x033c
-
-#define SOLO_VO_BORDER_X(n)			(0x0340+((n)*4))
-#define SOLO_VO_BORDER_Y(n)			(0x0354+((n)*4))
-
-#define SOLO_VO_CELL_EXT_SET			0x0368
-#define SOLO_VO_CELL_EXT_START			0x036c
-#define SOLO_VO_CELL_EXT_STOP			0x0370
-
-#define SOLO_VO_CELL_EXT_SET2			0x0374
-#define SOLO_VO_CELL_EXT_START2			0x0378
-#define SOLO_VO_CELL_EXT_STOP2			0x037c
-
-#define SOLO_VO_RECTANGLE_CTRL(n)		(0x0368+((n)*12))
-#define SOLO_VO_RECTANGLE_START(n)		(0x036c+((n)*12))
-#define SOLO_VO_RECTANGLE_STOP(n)		(0x0370+((n)*12))
-
-#define SOLO_VO_CURSOR_POS			(0x0380)
-#define SOLO_VO_CURSOR_CLR			(0x0384)
-#define SOLO_VO_CURSOR_CLR2			(0x0388)
-#define SOLO_VO_CURSOR_MASK(id)			(0x0390+((id)*4))
-
-#define SOLO_VO_EXPANSION(id)			(0x0250+((id)*4))
-
-#define	SOLO_OSG_CONFIG				0x03E0
-#define	  SOLO_VO_OSG_ON			(1<<31)
-#define	  SOLO_VO_OSG_COLOR_MUTE		(1<<28)
-#define	  SOLO_VO_OSG_ALPHA_RATE(n)		((n)<<22)
-#define	  SOLO_VO_OSG_ALPHA_BG_RATE(n)		((n)<<16)
-#define	  SOLO_VO_OSG_BASE(offset)		(((offset)>>16)&0xffff)
-
-#define SOLO_OSG_ERASE				0x03E4
-#define	  SOLO_OSG_ERASE_ON			(0x80)
-#define	  SOLO_OSG_ERASE_OFF			(0x00)
-
-#define SOLO_VO_OSG_BLINK			0x03E8
-#define	  SOLO_VO_OSG_BLINK_ON			(1<<1)
-#define	  SOLO_VO_OSG_BLINK_INTREVAL18		(1<<0)
-
-#define SOLO_CAP_BASE				0x0400
-#define	  SOLO_CAP_MAX_PAGE(n)			((n)<<16)
-#define	  SOLO_CAP_BASE_ADDR(n)			((n)<<0)
-#define SOLO_CAP_BTW				0x0404
-#define	  SOLO_CAP_PROG_BANDWIDTH(n)		((n)<<8)
-#define	  SOLO_CAP_MAX_BANDWIDTH(n)		((n)<<0)
-
-#define SOLO_DIM_SCALE1				0x0408
-#define SOLO_DIM_SCALE2				0x040C
-#define SOLO_DIM_SCALE3				0x0410
-#define SOLO_DIM_SCALE4				0x0414
-#define SOLO_DIM_SCALE5				0x0418
-#define	  SOLO_DIM_V_MB_NUM_FRAME(n)		((n)<<16)
-#define	  SOLO_DIM_V_MB_NUM_FIELD(n)		((n)<<8)
-#define	  SOLO_DIM_H_MB_NUM(n)			((n)<<0)
-
-#define SOLO_DIM_PROG				0x041C
-#define SOLO_CAP_STATUS				0x0420
-
-#define SOLO_CAP_CH_SCALE(ch)			(0x0440+((ch)*4))
-#define SOLO_CAP_CH_COMP_ENA_E(ch)		(0x0480+((ch)*4))
-#define SOLO_CAP_CH_INTV(ch)			(0x04C0+((ch)*4))
-#define SOLO_CAP_CH_INTV_E(ch)			(0x0500+((ch)*4))
-
-
-#define SOLO_VE_CFG0				0x0610
-#define	  SOLO_VE_TWO_PAGE_MODE			(1<<31)
-#define	  SOLO_VE_INTR_CTRL(n)			((n)<<24)
-#define	  SOLO_VE_BLOCK_SIZE(n)			((n)<<16)
-#define	  SOLO_VE_BLOCK_BASE(n)			((n)<<0)
-
-#define SOLO_VE_CFG1				0x0614
-#define   SOLO6110_VE_MPEG_SIZE_H(n)		((n)<<28) /* 6110 only */
-#define	  SOLO6010_VE_BYTE_ALIGN(n)		((n)<<24) /* 6010 only */
-#define   SOLO6110_VE_JPEG_SIZE_H(n)		((n)<<20) /* 6110 only */
-#define	  SOLO_VE_INSERT_INDEX			(1<<18)
-#define	  SOLO_VE_MOTION_MODE(n)		((n)<<16)
-#define	  SOLO_VE_MOTION_BASE(n)		((n)<<0)
-
-#define SOLO_VE_WMRK_POLY			0x061C
-#define SOLO_VE_VMRK_INIT_KEY			0x0620
-#define SOLO_VE_WMRK_STRL			0x0624
-#define SOLO_VE_ENCRYP_POLY			0x0628
-#define SOLO_VE_ENCRYP_INIT			0x062C
-#define SOLO_VE_ATTR				0x0630
-#define	  SOLO_VE_LITTLE_ENDIAN			(1<<31)
-#define	  SOLO_COMP_ATTR_RN			(1<<30)
-#define	  SOLO_COMP_ATTR_FCODE(n)		((n)<<27)
-#define	  SOLO_COMP_TIME_INC(n)			((n)<<25)
-#define	  SOLO_COMP_TIME_WIDTH(n)		((n)<<21)
-#define	  SOLO_DCT_INTERVAL(n)			((n)<<16)
-
-#define SOLO_VE_STATE(n)			(0x0640+((n)*4))
-
-#define SOLO_VE_JPEG_QP_TBL			0x0670
-#define SOLO_VE_JPEG_QP_CH_L			0x0674
-#define SOLO_VE_JPEG_QP_CH_H			0x0678
-#define SOLO_VE_JPEG_CFG			0x067C
-#define SOLO_VE_JPEG_CTRL			0x0680
-
-#define SOLO_VE_OSD_CH				0x0690
-#define SOLO_VE_OSD_BASE			0x0694
-#define SOLO_VE_OSD_CLR				0x0698
-#define SOLO_VE_OSD_OPT				0x069C
-
-#define SOLO_VE_CH_INTL(ch)			(0x0700+((ch)*4))
-#define SOLO6010_VE_CH_MOT(ch)			(0x0740+((ch)*4)) /* 6010 only */
-#define SOLO_VE_CH_QP(ch)			(0x0780+((ch)*4))
-#define SOLO_VE_CH_QP_E(ch)			(0x07C0+((ch)*4))
-#define SOLO_VE_CH_GOP(ch)			(0x0800+((ch)*4))
-#define SOLO_VE_CH_GOP_E(ch)			(0x0840+((ch)*4))
-#define SOLO_VE_CH_REF_BASE(ch)			(0x0880+((ch)*4))
-#define SOLO_VE_CH_REF_BASE_E(ch)		(0x08C0+((ch)*4))
-
-#define SOLO_VE_MPEG4_QUE(n)			(0x0A00+((n)*8))
-#define SOLO_VE_JPEG_QUE(n)			(0x0A04+((n)*8))
-
-#define SOLO_VD_CFG0				0x0900
-#define	  SOLO6010_VD_CFG_NO_WRITE_NO_WINDOW	(1<<24) /* 6010 only */
-#define	  SOLO_VD_CFG_BUSY_WIAT_CODE		(1<<23)
-#define	  SOLO_VD_CFG_BUSY_WIAT_REF		(1<<22)
-#define	  SOLO_VD_CFG_BUSY_WIAT_RES		(1<<21)
-#define	  SOLO_VD_CFG_BUSY_WIAT_MS		(1<<20)
-#define	  SOLO_VD_CFG_SINGLE_MODE		(1<<18)
-#define	  SOLO_VD_CFG_SCAL_MANUAL		(1<<17)
-#define	  SOLO_VD_CFG_USER_PAGE_CTRL		(1<<16)
-#define	  SOLO_VD_CFG_LITTLE_ENDIAN		(1<<15)
-#define	  SOLO_VD_CFG_START_FI			(1<<14)
-#define	  SOLO_VD_CFG_ERR_LOCK			(1<<13)
-#define	  SOLO_VD_CFG_ERR_INT_ENA		(1<<12)
-#define	  SOLO_VD_CFG_TIME_WIDTH(n)		((n)<<8)
-#define	  SOLO_VD_CFG_DCT_INTERVAL(n)		((n)<<0)
-
-#define SOLO_VD_CFG1				0x0904
-
-#define	SOLO_VD_DEINTERLACE			0x0908
-#define	  SOLO_VD_DEINTERLACE_THRESHOLD(n)	((n)<<8)
-#define	  SOLO_VD_DEINTERLACE_EDGE_VALUE(n)	((n)<<0)
-
-#define SOLO_VD_CODE_ADR			0x090C
-
-#define SOLO_VD_CTRL				0x0910
-#define	  SOLO_VD_OPER_ON			(1<<31)
-#define	  SOLO_VD_MAX_ITEM(n)			((n)<<0)
-
-#define SOLO_VD_STATUS0				0x0920
-#define	  SOLO_VD_STATUS0_INTR_ACK		(1<<22)
-#define	  SOLO_VD_STATUS0_INTR_EMPTY		(1<<21)
-#define	  SOLO_VD_STATUS0_INTR_ERR		(1<<20)
-
-#define SOLO_VD_STATUS1				0x0924
-
-#define SOLO_VD_IDX0				0x0930
-#define	  SOLO_VD_IDX_INTERLACE			(1<<30)
-#define	  SOLO_VD_IDX_CHANNEL(n)		((n)<<24)
-#define	  SOLO_VD_IDX_SIZE(n)			((n)<<0)
-
-#define SOLO_VD_IDX1				0x0934
-#define	  SOLO_VD_IDX_SRC_SCALE(n)		((n)<<28)
-#define	  SOLO_VD_IDX_WINDOW(n)			((n)<<24)
-#define	  SOLO_VD_IDX_DEINTERLACE		(1<<16)
-#define	  SOLO_VD_IDX_H_BLOCK(n)		((n)<<8)
-#define	  SOLO_VD_IDX_V_BLOCK(n)		((n)<<0)
-
-#define SOLO_VD_IDX2				0x0938
-#define	  SOLO_VD_IDX_REF_BASE_SIDE		(1<<31)
-#define	  SOLO_VD_IDX_REF_BASE(n)		(((n)>>16)&0xffff)
-
-#define SOLO_VD_IDX3				0x093C
-#define	  SOLO_VD_IDX_DISP_SCALE(n)		((n)<<28)
-#define	  SOLO_VD_IDX_INTERLACE_WR		(1<<27)
-#define	  SOLO_VD_IDX_INTERPOL			(1<<26)
-#define	  SOLO_VD_IDX_HOR2X			(1<<25)
-#define	  SOLO_VD_IDX_OFFSET_X(n)		((n)<<12)
-#define	  SOLO_VD_IDX_OFFSET_Y(n)		((n)<<0)
-
-#define SOLO_VD_IDX4				0x0940
-#define	  SOLO_VD_IDX_DEC_WR_PAGE(n)		((n)<<8)
-#define	  SOLO_VD_IDX_DISP_RD_PAGE(n)		((n)<<0)
-
-#define SOLO_VD_WR_PAGE(n)			(0x03F0 + ((n) * 4))
-
-
-#define SOLO_GPIO_CONFIG_0			0x0B00
-#define SOLO_GPIO_CONFIG_1			0x0B04
-#define SOLO_GPIO_DATA_OUT			0x0B08
-#define SOLO_GPIO_DATA_IN			0x0B0C
-#define SOLO_GPIO_INT_ACK_STA			0x0B10
-#define SOLO_GPIO_INT_ENA			0x0B14
-#define SOLO_GPIO_INT_CFG_0			0x0B18
-#define SOLO_GPIO_INT_CFG_1			0x0B1C
-
-
-#define SOLO_IIC_CFG				0x0B20
-#define	  SOLO_IIC_ENABLE			(1<<8)
-#define	  SOLO_IIC_PRESCALE(n)			((n)<<0)
-
-#define SOLO_IIC_CTRL				0x0B24
-#define	  SOLO_IIC_AUTO_CLEAR			(1<<20)
-#define	  SOLO_IIC_STATE_RX_ACK			(1<<19)
-#define	  SOLO_IIC_STATE_BUSY			(1<<18)
-#define	  SOLO_IIC_STATE_SIG_ERR		(1<<17)
-#define	  SOLO_IIC_STATE_TRNS			(1<<16)
-#define	  SOLO_IIC_CH_SET(n)			((n)<<5)
-#define	  SOLO_IIC_ACK_EN			(1<<4)
-#define	  SOLO_IIC_START			(1<<3)
-#define	  SOLO_IIC_STOP				(1<<2)
-#define	  SOLO_IIC_READ				(1<<1)
-#define	  SOLO_IIC_WRITE			(1<<0)
-
-#define SOLO_IIC_TXD				0x0B28
-#define SOLO_IIC_RXD				0x0B2C
-
-/*
- *	UART REGISTER
- */
-#define SOLO_UART_CONTROL(n)			(0x0BA0 + ((n)*0x20))
-#define	  SOLO_UART_CLK_DIV(n)			((n)<<24)
-#define	  SOLO_MODEM_CTRL_EN			(1<<20)
-#define	  SOLO_PARITY_ERROR_DROP		(1<<18)
-#define	  SOLO_IRQ_ERR_EN			(1<<17)
-#define	  SOLO_IRQ_RX_EN			(1<<16)
-#define	  SOLO_IRQ_TX_EN			(1<<15)
-#define	  SOLO_RX_EN				(1<<14)
-#define	  SOLO_TX_EN				(1<<13)
-#define	  SOLO_UART_HALF_DUPLEX			(1<<12)
-#define	  SOLO_UART_LOOPBACK			(1<<11)
-
-#define	  SOLO_BAUDRATE_230400			((0<<9)|(0<<6))
-#define	  SOLO_BAUDRATE_115200			((0<<9)|(1<<6))
-#define	  SOLO_BAUDRATE_57600			((0<<9)|(2<<6))
-#define	  SOLO_BAUDRATE_38400			((0<<9)|(3<<6))
-#define	  SOLO_BAUDRATE_19200			((0<<9)|(4<<6))
-#define	  SOLO_BAUDRATE_9600			((0<<9)|(5<<6))
-#define	  SOLO_BAUDRATE_4800			((0<<9)|(6<<6))
-#define	  SOLO_BAUDRATE_2400			((1<<9)|(6<<6))
-#define	  SOLO_BAUDRATE_1200			((2<<9)|(6<<6))
-#define	  SOLO_BAUDRATE_300			((3<<9)|(6<<6))
-
-#define	  SOLO_UART_DATA_BIT_8			(3<<4)
-#define	  SOLO_UART_DATA_BIT_7			(2<<4)
-#define	  SOLO_UART_DATA_BIT_6			(1<<4)
-#define	  SOLO_UART_DATA_BIT_5			(0<<4)
-
-#define	  SOLO_UART_STOP_BIT_1			(0<<2)
-#define	  SOLO_UART_STOP_BIT_2			(1<<2)
-
-#define	  SOLO_UART_PARITY_NONE			(0<<0)
-#define	  SOLO_UART_PARITY_EVEN			(2<<0)
-#define	  SOLO_UART_PARITY_ODD			(3<<0)
-
-#define SOLO_UART_STATUS(n)			(0x0BA4 + ((n)*0x20))
-#define	  SOLO_UART_CTS				(1<<15)
-#define	  SOLO_UART_RX_BUSY			(1<<14)
-#define	  SOLO_UART_OVERRUN			(1<<13)
-#define	  SOLO_UART_FRAME_ERR			(1<<12)
-#define	  SOLO_UART_PARITY_ERR			(1<<11)
-#define	  SOLO_UART_TX_BUSY			(1<<5)
-
-#define	  SOLO_UART_RX_BUFF_CNT(stat)		(((stat)>>6) & 0x1f)
-#define	  SOLO_UART_RX_BUFF_SIZE		8
-#define	  SOLO_UART_TX_BUFF_CNT(stat)		(((stat)>>0) & 0x1f)
-#define	  SOLO_UART_TX_BUFF_SIZE		8
-
-#define SOLO_UART_TX_DATA(n)			(0x0BA8 + ((n)*0x20))
-#define	  SOLO_UART_TX_DATA_PUSH		(1<<8)
-#define SOLO_UART_RX_DATA(n)			(0x0BAC + ((n)*0x20))
-#define	  SOLO_UART_RX_DATA_POP			(1<<8)
-
-#define SOLO_TIMER_CLOCK_NUM			0x0be0
-#define SOLO_TIMER_WATCHDOG			0x0be4
-#define SOLO_TIMER_USEC				0x0be8
-#define SOLO_TIMER_SEC				0x0bec
-
-#define SOLO_AUDIO_CONTROL			0x0D00
-#define	  SOLO_AUDIO_ENABLE			(1<<31)
-#define	  SOLO_AUDIO_MASTER_MODE		(1<<30)
-#define	  SOLO_AUDIO_I2S_MODE			(1<<29)
-#define	  SOLO_AUDIO_I2S_LR_SWAP		(1<<27)
-#define	  SOLO_AUDIO_I2S_8BIT			(1<<26)
-#define	  SOLO_AUDIO_I2S_MULTI(n)		((n)<<24)
-#define	  SOLO_AUDIO_MIX_9TO0			(1<<23)
-#define	  SOLO_AUDIO_DEC_9TO0_VOL(n)		((n)<<20)
-#define	  SOLO_AUDIO_MIX_19TO10			(1<<19)
-#define	  SOLO_AUDIO_DEC_19TO10_VOL(n)		((n)<<16)
-#define	  SOLO_AUDIO_MODE(n)			((n)<<0)
-#define SOLO_AUDIO_SAMPLE			0x0D04
-#define	  SOLO_AUDIO_EE_MODE_ON			(1<<30)
-#define	  SOLO_AUDIO_EE_ENC_CH(ch)		((ch)<<25)
-#define	  SOLO_AUDIO_BITRATE(n)			((n)<<16)
-#define	  SOLO_AUDIO_CLK_DIV(n)			((n)<<0)
-#define SOLO_AUDIO_FDMA_INTR			0x0D08
-#define	  SOLO_AUDIO_FDMA_INTERVAL(n)		((n)<<19)
-#define	  SOLO_AUDIO_INTR_ORDER(n)		((n)<<16)
-#define	  SOLO_AUDIO_FDMA_BASE(n)		((n)<<0)
-#define SOLO_AUDIO_EVOL_0			0x0D0C
-#define SOLO_AUDIO_EVOL_1			0x0D10
-#define	  SOLO_AUDIO_EVOL(ch, value)		((value)<<((ch)%10))
-#define SOLO_AUDIO_STA				0x0D14
-
-
-#define SOLO_WATCHDOG				0x0BE4
-#define WATCHDOG_STAT(status)			(status<<8)
-#define WATCHDOG_TIME(sec)			(sec&0xff)
-
-#endif /* __SOLO6X10_REGISTERS_H */
diff --git a/drivers/staging/media/solo6x10/solo6x10-core.c b/drivers/staging/media/solo6x10/solo6x10-core.c
new file mode 100644
index 0000000..3675020
--- /dev/null
+++ b/drivers/staging/media/solo6x10/solo6x10-core.c
@@ -0,0 +1,709 @@
+/*
+ * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
+ *
+ * Original author:
+ * Ben Collins <bcollins@ubuntu.com>
+ *
+ * Additional work by:
+ * John Brooks <john.brooks@bluecherry.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You 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/pci.h>
+#include <linux/interrupt.h>
+#include <linux/videodev2.h>
+#include <linux/delay.h>
+#include <linux/sysfs.h>
+#include <linux/ktime.h>
+#include <linux/slab.h>
+
+#include "solo6x10.h"
+#include "solo6x10-tw28.h"
+
+MODULE_DESCRIPTION("Softlogic 6x10 MPEG4/H.264/G.723 CODEC V4L2/ALSA Driver");
+MODULE_AUTHOR("Bluecherry <maintainers@bluecherrydvr.com>");
+MODULE_VERSION(SOLO6X10_VERSION);
+MODULE_LICENSE("GPL");
+
+unsigned video_nr = -1;
+module_param(video_nr, uint, 0644);
+MODULE_PARM_DESC(video_nr, "videoX start number, -1 is autodetect (default)");
+
+static int full_eeprom; /* default is only top 64B */
+module_param(full_eeprom, uint, 0644);
+MODULE_PARM_DESC(full_eeprom, "Allow access to full 128B EEPROM (dangerous)");
+
+
+static void solo_set_time(struct solo_dev *solo_dev)
+{
+	struct timespec ts;
+
+	ktime_get_ts(&ts);
+
+	solo_reg_write(solo_dev, SOLO_TIMER_SEC, ts.tv_sec);
+	solo_reg_write(solo_dev, SOLO_TIMER_USEC, ts.tv_nsec / NSEC_PER_USEC);
+}
+
+static void solo_timer_sync(struct solo_dev *solo_dev)
+{
+	u32 sec, usec;
+	struct timespec ts;
+	long diff;
+
+	if (solo_dev->type != SOLO_DEV_6110)
+		return;
+
+	if (++solo_dev->time_sync < 60)
+		return;
+
+	solo_dev->time_sync = 0;
+
+	sec = solo_reg_read(solo_dev, SOLO_TIMER_SEC);
+	usec = solo_reg_read(solo_dev, SOLO_TIMER_USEC);
+
+	ktime_get_ts(&ts);
+
+	diff = (long)ts.tv_sec - (long)sec;
+	diff = (diff * 1000000)
+		+ ((long)(ts.tv_nsec / NSEC_PER_USEC) - (long)usec);
+
+	if (diff > 1000 || diff < -1000) {
+		solo_set_time(solo_dev);
+	} else if (diff) {
+		long usec_lsb = solo_dev->usec_lsb;
+
+		usec_lsb -= diff / 4;
+		if (usec_lsb < 0)
+			usec_lsb = 0;
+		else if (usec_lsb > 255)
+			usec_lsb = 255;
+
+		solo_dev->usec_lsb = usec_lsb;
+		solo_reg_write(solo_dev, SOLO_TIMER_USEC_LSB,
+			       solo_dev->usec_lsb);
+	}
+}
+
+static irqreturn_t solo_isr(int irq, void *data)
+{
+	struct solo_dev *solo_dev = data;
+	u32 status;
+	int i;
+
+	status = solo_reg_read(solo_dev, SOLO_IRQ_STAT);
+	if (!status)
+		return IRQ_NONE;
+
+	if (status & ~solo_dev->irq_mask) {
+		solo_reg_write(solo_dev, SOLO_IRQ_STAT,
+			       status & ~solo_dev->irq_mask);
+		status &= solo_dev->irq_mask;
+	}
+
+	if (status & SOLO_IRQ_PCI_ERR)
+		solo_p2m_error_isr(solo_dev);
+
+	for (i = 0; i < SOLO_NR_P2M; i++)
+		if (status & SOLO_IRQ_P2M(i))
+			solo_p2m_isr(solo_dev, i);
+
+	if (status & SOLO_IRQ_IIC)
+		solo_i2c_isr(solo_dev);
+
+	if (status & SOLO_IRQ_VIDEO_IN) {
+		solo_video_in_isr(solo_dev);
+		solo_timer_sync(solo_dev);
+	}
+
+	if (status & SOLO_IRQ_ENCODER)
+		solo_enc_v4l2_isr(solo_dev);
+
+	if (status & SOLO_IRQ_G723)
+		solo_g723_isr(solo_dev);
+
+	/* Clear all interrupts handled */
+	solo_reg_write(solo_dev, SOLO_IRQ_STAT, status);
+
+	return IRQ_HANDLED;
+}
+
+static void free_solo_dev(struct solo_dev *solo_dev)
+{
+	struct pci_dev *pdev;
+
+	if (!solo_dev)
+		return;
+
+	if (solo_dev->dev.parent)
+		device_unregister(&solo_dev->dev);
+
+	pdev = solo_dev->pdev;
+
+	/* If we never initialized the PCI device, then nothing else
+	 * below here needs cleanup */
+	if (!pdev) {
+		kfree(solo_dev);
+		return;
+	}
+
+	if (solo_dev->reg_base) {
+		/* Bring down the sub-devices first */
+		solo_g723_exit(solo_dev);
+		solo_enc_v4l2_exit(solo_dev);
+		solo_enc_exit(solo_dev);
+		solo_v4l2_exit(solo_dev);
+		solo_disp_exit(solo_dev);
+		solo_gpio_exit(solo_dev);
+		solo_p2m_exit(solo_dev);
+		solo_i2c_exit(solo_dev);
+
+		/* Now cleanup the PCI device */
+		solo_irq_off(solo_dev, ~0);
+		pci_iounmap(pdev, solo_dev->reg_base);
+		if (pdev->irq)
+			free_irq(pdev->irq, solo_dev);
+	}
+
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+	v4l2_device_unregister(&solo_dev->v4l2_dev);
+	pci_set_drvdata(pdev, NULL);
+
+	kfree(solo_dev);
+}
+
+static ssize_t eeprom_store(struct device *dev, struct device_attribute *attr,
+			    const char *buf, size_t count)
+{
+	struct solo_dev *solo_dev =
+		container_of(dev, struct solo_dev, dev);
+	unsigned short *p = (unsigned short *)buf;
+	int i;
+
+	if (count & 0x1)
+		dev_warn(dev, "EEPROM Write not aligned (truncating)\n");
+
+	if (!full_eeprom && count > 64) {
+		dev_warn(dev, "EEPROM Write truncated to 64 bytes\n");
+		count = 64;
+	} else if (full_eeprom && count > 128) {
+		dev_warn(dev, "EEPROM Write truncated to 128 bytes\n");
+		count = 128;
+	}
+
+	solo_eeprom_ewen(solo_dev, 1);
+
+	for (i = full_eeprom ? 0 : 32; i < min((int)(full_eeprom ? 64 : 32),
+					       (int)(count / 2)); i++)
+		solo_eeprom_write(solo_dev, i, cpu_to_be16(p[i]));
+
+	solo_eeprom_ewen(solo_dev, 0);
+
+	return count;
+}
+
+static ssize_t eeprom_show(struct device *dev, struct device_attribute *attr,
+			   char *buf)
+{
+	struct solo_dev *solo_dev =
+		container_of(dev, struct solo_dev, dev);
+	unsigned short *p = (unsigned short *)buf;
+	int count = (full_eeprom ? 128 : 64);
+	int i;
+
+	for (i = (full_eeprom ? 0 : 32); i < (count / 2); i++)
+		p[i] = be16_to_cpu(solo_eeprom_read(solo_dev, i));
+
+	return count;
+}
+
+static ssize_t p2m_timeouts_show(struct device *dev,
+				 struct device_attribute *attr,
+				 char *buf)
+{
+	struct solo_dev *solo_dev =
+		container_of(dev, struct solo_dev, dev);
+
+	return sprintf(buf, "%d\n", solo_dev->p2m_timeouts);
+}
+
+static ssize_t sdram_size_show(struct device *dev,
+			       struct device_attribute *attr,
+			       char *buf)
+{
+	struct solo_dev *solo_dev =
+		container_of(dev, struct solo_dev, dev);
+
+	return sprintf(buf, "%dMegs\n", solo_dev->sdram_size >> 20);
+}
+
+static ssize_t tw28xx_show(struct device *dev,
+			   struct device_attribute *attr,
+			   char *buf)
+{
+	struct solo_dev *solo_dev =
+		container_of(dev, struct solo_dev, dev);
+
+	return sprintf(buf, "tw2815[%d] tw2864[%d] tw2865[%d]\n",
+		       hweight32(solo_dev->tw2815),
+		       hweight32(solo_dev->tw2864),
+		       hweight32(solo_dev->tw2865));
+}
+
+static ssize_t input_map_show(struct device *dev,
+			      struct device_attribute *attr,
+			      char *buf)
+{
+	struct solo_dev *solo_dev =
+		container_of(dev, struct solo_dev, dev);
+	unsigned int val;
+	char *out = buf;
+
+	val = solo_reg_read(solo_dev, SOLO_VI_CH_SWITCH_0);
+	out += sprintf(out, "Channel 0   => Input %d\n", val & 0x1f);
+	out += sprintf(out, "Channel 1   => Input %d\n", (val >> 5) & 0x1f);
+	out += sprintf(out, "Channel 2   => Input %d\n", (val >> 10) & 0x1f);
+	out += sprintf(out, "Channel 3   => Input %d\n", (val >> 15) & 0x1f);
+	out += sprintf(out, "Channel 4   => Input %d\n", (val >> 20) & 0x1f);
+	out += sprintf(out, "Channel 5   => Input %d\n", (val >> 25) & 0x1f);
+
+	val = solo_reg_read(solo_dev, SOLO_VI_CH_SWITCH_1);
+	out += sprintf(out, "Channel 6   => Input %d\n", val & 0x1f);
+	out += sprintf(out, "Channel 7   => Input %d\n", (val >> 5) & 0x1f);
+	out += sprintf(out, "Channel 8   => Input %d\n", (val >> 10) & 0x1f);
+	out += sprintf(out, "Channel 9   => Input %d\n", (val >> 15) & 0x1f);
+	out += sprintf(out, "Channel 10  => Input %d\n", (val >> 20) & 0x1f);
+	out += sprintf(out, "Channel 11  => Input %d\n", (val >> 25) & 0x1f);
+
+	val = solo_reg_read(solo_dev, SOLO_VI_CH_SWITCH_2);
+	out += sprintf(out, "Channel 12  => Input %d\n", val & 0x1f);
+	out += sprintf(out, "Channel 13  => Input %d\n", (val >> 5) & 0x1f);
+	out += sprintf(out, "Channel 14  => Input %d\n", (val >> 10) & 0x1f);
+	out += sprintf(out, "Channel 15  => Input %d\n", (val >> 15) & 0x1f);
+	out += sprintf(out, "Spot Output => Input %d\n", (val >> 20) & 0x1f);
+
+	return out - buf;
+}
+
+static ssize_t p2m_timeout_store(struct device *dev,
+				 struct device_attribute *attr,
+				 const char *buf, size_t count)
+{
+	struct solo_dev *solo_dev =
+		container_of(dev, struct solo_dev, dev);
+	unsigned long ms;
+
+	int ret = kstrtoul(buf, 10, &ms);
+	if (ret < 0 || ms > 200)
+		return -EINVAL;
+	solo_dev->p2m_jiffies = msecs_to_jiffies(ms);
+
+	return count;
+}
+
+static ssize_t p2m_timeout_show(struct device *dev,
+				struct device_attribute *attr,
+				char *buf)
+{
+	struct solo_dev *solo_dev =
+		container_of(dev, struct solo_dev, dev);
+
+	return sprintf(buf, "%ums\n", jiffies_to_msecs(solo_dev->p2m_jiffies));
+}
+
+static ssize_t intervals_show(struct device *dev,
+			      struct device_attribute *attr,
+			      char *buf)
+{
+	struct solo_dev *solo_dev =
+		container_of(dev, struct solo_dev, dev);
+	char *out = buf;
+	int fps = solo_dev->fps;
+	int i;
+
+	for (i = 0; i < solo_dev->nr_chans; i++) {
+		out += sprintf(out, "Channel %d: %d/%d (0x%08x)\n",
+			       i, solo_dev->v4l2_enc[i]->interval, fps,
+			       solo_reg_read(solo_dev, SOLO_CAP_CH_INTV(i)));
+	}
+
+	return out - buf;
+}
+
+static ssize_t sdram_offsets_show(struct device *dev,
+				  struct device_attribute *attr,
+				  char *buf)
+{
+	struct solo_dev *solo_dev =
+		container_of(dev, struct solo_dev, dev);
+	char *out = buf;
+
+	out += sprintf(out, "DISP: 0x%08x @ 0x%08x\n",
+		       SOLO_DISP_EXT_ADDR,
+		       SOLO_DISP_EXT_SIZE);
+
+	out += sprintf(out, "EOSD: 0x%08x @ 0x%08x (0x%08x * %d)\n",
+		       SOLO_EOSD_EXT_ADDR,
+		       SOLO_EOSD_EXT_AREA(solo_dev),
+		       SOLO_EOSD_EXT_SIZE(solo_dev),
+		       SOLO_EOSD_EXT_AREA(solo_dev) /
+		       SOLO_EOSD_EXT_SIZE(solo_dev));
+
+	out += sprintf(out, "MOTI: 0x%08x @ 0x%08x\n",
+		       SOLO_MOTION_EXT_ADDR(solo_dev),
+		       SOLO_MOTION_EXT_SIZE);
+
+	out += sprintf(out, "G723: 0x%08x @ 0x%08x\n",
+		       SOLO_G723_EXT_ADDR(solo_dev),
+		       SOLO_G723_EXT_SIZE);
+
+	out += sprintf(out, "CAPT: 0x%08x @ 0x%08x (0x%08x * %d)\n",
+		       SOLO_CAP_EXT_ADDR(solo_dev),
+		       SOLO_CAP_EXT_SIZE(solo_dev),
+		       SOLO_CAP_PAGE_SIZE,
+		       SOLO_CAP_EXT_SIZE(solo_dev) / SOLO_CAP_PAGE_SIZE);
+
+	out += sprintf(out, "EREF: 0x%08x @ 0x%08x (0x%08x * %d)\n",
+		       SOLO_EREF_EXT_ADDR(solo_dev),
+		       SOLO_EREF_EXT_AREA(solo_dev),
+		       SOLO_EREF_EXT_SIZE,
+		       SOLO_EREF_EXT_AREA(solo_dev) / SOLO_EREF_EXT_SIZE);
+
+	out += sprintf(out, "MPEG: 0x%08x @ 0x%08x\n",
+		       SOLO_MP4E_EXT_ADDR(solo_dev),
+		       SOLO_MP4E_EXT_SIZE(solo_dev));
+
+	out += sprintf(out, "JPEG: 0x%08x @ 0x%08x\n",
+		       SOLO_JPEG_EXT_ADDR(solo_dev),
+		       SOLO_JPEG_EXT_SIZE(solo_dev));
+
+	return out - buf;
+}
+
+static ssize_t sdram_show(struct file *file, struct kobject *kobj,
+			  struct bin_attribute *a, char *buf,
+			  loff_t off, size_t count)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct solo_dev *solo_dev =
+		container_of(dev, struct solo_dev, dev);
+	const int size = solo_dev->sdram_size;
+
+	if (off >= size)
+		return 0;
+
+	if (off + count > size)
+		count = size - off;
+
+	if (solo_p2m_dma(solo_dev, 0, buf, off, count, 0, 0))
+		return -EIO;
+
+	return count;
+}
+
+static const struct device_attribute solo_dev_attrs[] = {
+	__ATTR(eeprom, 0640, eeprom_show, eeprom_store),
+	__ATTR(p2m_timeout, 0644, p2m_timeout_show, p2m_timeout_store),
+	__ATTR_RO(p2m_timeouts),
+	__ATTR_RO(sdram_size),
+	__ATTR_RO(tw28xx),
+	__ATTR_RO(input_map),
+	__ATTR_RO(intervals),
+	__ATTR_RO(sdram_offsets),
+};
+
+static void solo_device_release(struct device *dev)
+{
+	/* Do nothing */
+}
+
+static int solo_sysfs_init(struct solo_dev *solo_dev)
+{
+	struct bin_attribute *sdram_attr = &solo_dev->sdram_attr;
+	struct device *dev = &solo_dev->dev;
+	const char *driver;
+	int i;
+
+	if (solo_dev->type == SOLO_DEV_6110)
+		driver = "solo6110";
+	else
+		driver = "solo6010";
+
+	dev->release = solo_device_release;
+	dev->parent = &solo_dev->pdev->dev;
+	set_dev_node(dev, dev_to_node(&solo_dev->pdev->dev));
+	dev_set_name(dev, "%s-%d-%d", driver, solo_dev->vfd->num,
+		     solo_dev->nr_chans);
+
+	if (device_register(dev)) {
+		dev->parent = NULL;
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(solo_dev_attrs); i++) {
+		if (device_create_file(dev, &solo_dev_attrs[i])) {
+			device_unregister(dev);
+			return -ENOMEM;
+		}
+	}
+
+	sysfs_attr_init(&sdram_attr->attr);
+	sdram_attr->attr.name = "sdram";
+	sdram_attr->attr.mode = 0440;
+	sdram_attr->read = sdram_show;
+	sdram_attr->size = solo_dev->sdram_size;
+
+	if (device_create_bin_file(dev, sdram_attr)) {
+		device_unregister(dev);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static int solo_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+	struct solo_dev *solo_dev;
+	int ret;
+	u8 chip_id;
+
+	solo_dev = kzalloc(sizeof(*solo_dev), GFP_KERNEL);
+	if (solo_dev == NULL)
+		return -ENOMEM;
+
+	if (id->driver_data == SOLO_DEV_6010)
+		dev_info(&pdev->dev, "Probing Softlogic 6010\n");
+	else
+		dev_info(&pdev->dev, "Probing Softlogic 6110\n");
+
+	solo_dev->type = id->driver_data;
+	solo_dev->pdev = pdev;
+	spin_lock_init(&solo_dev->reg_io_lock);
+	ret = v4l2_device_register(&pdev->dev, &solo_dev->v4l2_dev);
+	if (ret)
+		goto fail_probe;
+
+	/* Only for during init */
+	solo_dev->p2m_jiffies = msecs_to_jiffies(100);
+
+	ret = pci_enable_device(pdev);
+	if (ret)
+		goto fail_probe;
+
+	pci_set_master(pdev);
+
+	/* RETRY/TRDY Timeout disabled */
+	pci_write_config_byte(pdev, 0x40, 0x00);
+	pci_write_config_byte(pdev, 0x41, 0x00);
+
+	ret = pci_request_regions(pdev, SOLO6X10_NAME);
+	if (ret)
+		goto fail_probe;
+
+	solo_dev->reg_base = pci_ioremap_bar(pdev, 0);
+	if (solo_dev->reg_base == NULL) {
+		ret = -ENOMEM;
+		goto fail_probe;
+	}
+
+	chip_id = solo_reg_read(solo_dev, SOLO_CHIP_OPTION) &
+				SOLO_CHIP_ID_MASK;
+	switch (chip_id) {
+	case 7:
+		solo_dev->nr_chans = 16;
+		solo_dev->nr_ext = 5;
+		break;
+	case 6:
+		solo_dev->nr_chans = 8;
+		solo_dev->nr_ext = 2;
+		break;
+	default:
+		dev_warn(&pdev->dev, "Invalid chip_id 0x%02x, assuming 4 ch\n",
+			 chip_id);
+	case 5:
+		solo_dev->nr_chans = 4;
+		solo_dev->nr_ext = 1;
+	}
+
+	/* Disable all interrupts to start */
+	solo_irq_off(solo_dev, ~0);
+
+	/* Initial global settings */
+	if (solo_dev->type == SOLO_DEV_6010) {
+		solo_dev->clock_mhz = 108;
+		solo_dev->sys_config = SOLO_SYS_CFG_SDRAM64BIT
+			| SOLO_SYS_CFG_INPUTDIV(25)
+			| SOLO_SYS_CFG_FEEDBACKDIV(solo_dev->clock_mhz * 2 - 2)
+			| SOLO_SYS_CFG_OUTDIV(3);
+		solo_reg_write(solo_dev, SOLO_SYS_CFG, solo_dev->sys_config);
+	} else {
+		u32 divq, divf;
+
+		solo_dev->clock_mhz = 135;
+
+		if (solo_dev->clock_mhz < 125) {
+			divq = 3;
+			divf = (solo_dev->clock_mhz * 4) / 3 - 1;
+		} else {
+			divq = 2;
+			divf = (solo_dev->clock_mhz * 2) / 3 - 1;
+		}
+
+		solo_reg_write(solo_dev, SOLO_PLL_CONFIG,
+			       (1 << 20) | /* PLL_RANGE */
+			       (8 << 15) | /* PLL_DIVR  */
+			       (divq << 12) |
+			       (divf <<  4) |
+			       (1 <<  1)   /* PLL_FSEN */);
+
+		solo_dev->sys_config = SOLO_SYS_CFG_SDRAM64BIT;
+	}
+
+	solo_reg_write(solo_dev, SOLO_SYS_CFG, solo_dev->sys_config);
+	solo_reg_write(solo_dev, SOLO_TIMER_CLOCK_NUM,
+		       solo_dev->clock_mhz - 1);
+
+	/* PLL locking time of 1ms */
+	mdelay(1);
+
+	ret = request_irq(pdev->irq, solo_isr, IRQF_SHARED, SOLO6X10_NAME,
+			  solo_dev);
+	if (ret)
+		goto fail_probe;
+
+	/* Handle this from the start */
+	solo_irq_on(solo_dev, SOLO_IRQ_PCI_ERR);
+
+	ret = solo_i2c_init(solo_dev);
+	if (ret)
+		goto fail_probe;
+
+	/* Setup the DMA engine */
+	solo_reg_write(solo_dev, SOLO_DMA_CTRL,
+		       SOLO_DMA_CTRL_REFRESH_CYCLE(1) |
+		       SOLO_DMA_CTRL_SDRAM_SIZE(2) |
+		       SOLO_DMA_CTRL_SDRAM_CLK_INVERT |
+		       SOLO_DMA_CTRL_READ_CLK_SELECT |
+		       SOLO_DMA_CTRL_LATENCY(1));
+
+	/* Undocumented crap */
+	solo_reg_write(solo_dev, SOLO_DMA_CTRL1,
+		       solo_dev->type == SOLO_DEV_6010 ? 0x100 : 0x300);
+
+	if (solo_dev->type != SOLO_DEV_6010) {
+		solo_dev->usec_lsb = 0x3f;
+		solo_set_time(solo_dev);
+	}
+
+	/* Disable watchdog */
+	solo_reg_write(solo_dev, SOLO_WATCHDOG, 0);
+
+	/* Initialize sub components */
+
+	ret = solo_p2m_init(solo_dev);
+	if (ret)
+		goto fail_probe;
+
+	ret = solo_disp_init(solo_dev);
+	if (ret)
+		goto fail_probe;
+
+	ret = solo_gpio_init(solo_dev);
+	if (ret)
+		goto fail_probe;
+
+	ret = solo_tw28_init(solo_dev);
+	if (ret)
+		goto fail_probe;
+
+	ret = solo_v4l2_init(solo_dev, video_nr);
+	if (ret)
+		goto fail_probe;
+
+	ret = solo_enc_init(solo_dev);
+	if (ret)
+		goto fail_probe;
+
+	ret = solo_enc_v4l2_init(solo_dev, video_nr);
+	if (ret)
+		goto fail_probe;
+
+	ret = solo_g723_init(solo_dev);
+	if (ret)
+		goto fail_probe;
+
+	ret = solo_sysfs_init(solo_dev);
+	if (ret)
+		goto fail_probe;
+
+	/* Now that init is over, set this lower */
+	solo_dev->p2m_jiffies = msecs_to_jiffies(20);
+
+	return 0;
+
+fail_probe:
+	free_solo_dev(solo_dev);
+	return ret;
+}
+
+static void solo_pci_remove(struct pci_dev *pdev)
+{
+	struct v4l2_device *v4l2_dev = pci_get_drvdata(pdev);
+	struct solo_dev *solo_dev = container_of(v4l2_dev, struct solo_dev, v4l2_dev);
+
+	free_solo_dev(solo_dev);
+}
+
+static DEFINE_PCI_DEVICE_TABLE(solo_id_table) = {
+	/* 6010 based cards */
+	{ PCI_DEVICE(PCI_VENDOR_ID_SOFTLOGIC, PCI_DEVICE_ID_SOLO6010),
+	  .driver_data = SOLO_DEV_6010 },
+	{ PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_NEUSOLO_4),
+	  .driver_data = SOLO_DEV_6010 },
+	{ PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_NEUSOLO_9),
+	  .driver_data = SOLO_DEV_6010 },
+	{ PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_NEUSOLO_16),
+	  .driver_data = SOLO_DEV_6010 },
+	{ PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_SOLO_4),
+	  .driver_data = SOLO_DEV_6010 },
+	{ PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_SOLO_9),
+	  .driver_data = SOLO_DEV_6010 },
+	{ PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_SOLO_16),
+	  .driver_data = SOLO_DEV_6010 },
+	/* 6110 based cards */
+	{ PCI_DEVICE(PCI_VENDOR_ID_SOFTLOGIC, PCI_DEVICE_ID_SOLO6110),
+	  .driver_data = SOLO_DEV_6110 },
+	{ PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_6110_4),
+	  .driver_data = SOLO_DEV_6110 },
+	{ PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_6110_8),
+	  .driver_data = SOLO_DEV_6110 },
+	{ PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_6110_16),
+	  .driver_data = SOLO_DEV_6110 },
+	{0,}
+};
+
+MODULE_DEVICE_TABLE(pci, solo_id_table);
+
+static struct pci_driver solo_pci_driver = {
+	.name = SOLO6X10_NAME,
+	.id_table = solo_id_table,
+	.probe = solo_pci_probe,
+	.remove = solo_pci_remove,
+};
+
+module_pci_driver(solo_pci_driver);
diff --git a/drivers/staging/media/solo6x10/solo6x10-disp.c b/drivers/staging/media/solo6x10/solo6x10-disp.c
new file mode 100644
index 0000000..32d9953
--- /dev/null
+++ b/drivers/staging/media/solo6x10/solo6x10-disp.c
@@ -0,0 +1,313 @@
+/*
+ * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
+ *
+ * Original author:
+ * Ben Collins <bcollins@ubuntu.com>
+ *
+ * Additional work by:
+ * John Brooks <john.brooks@bluecherry.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You 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/videodev2.h>
+#include <media/v4l2-ioctl.h>
+
+#include "solo6x10.h"
+
+#define SOLO_VCLK_DELAY			3
+#define SOLO_PROGRESSIVE_VSIZE		1024
+
+#define SOLO_MOT_THRESH_W		64
+#define SOLO_MOT_THRESH_H		64
+#define SOLO_MOT_THRESH_SIZE		8192
+#define SOLO_MOT_THRESH_REAL		(SOLO_MOT_THRESH_W * SOLO_MOT_THRESH_H)
+#define SOLO_MOT_FLAG_SIZE		1024
+#define SOLO_MOT_FLAG_AREA		(SOLO_MOT_FLAG_SIZE * 16)
+
+static void solo_vin_config(struct solo_dev *solo_dev)
+{
+	solo_dev->vin_hstart = 8;
+	solo_dev->vin_vstart = 2;
+
+	solo_reg_write(solo_dev, SOLO_SYS_VCLK,
+		       SOLO_VCLK_SELECT(2) |
+		       SOLO_VCLK_VIN1415_DELAY(SOLO_VCLK_DELAY) |
+		       SOLO_VCLK_VIN1213_DELAY(SOLO_VCLK_DELAY) |
+		       SOLO_VCLK_VIN1011_DELAY(SOLO_VCLK_DELAY) |
+		       SOLO_VCLK_VIN0809_DELAY(SOLO_VCLK_DELAY) |
+		       SOLO_VCLK_VIN0607_DELAY(SOLO_VCLK_DELAY) |
+		       SOLO_VCLK_VIN0405_DELAY(SOLO_VCLK_DELAY) |
+		       SOLO_VCLK_VIN0203_DELAY(SOLO_VCLK_DELAY) |
+		       SOLO_VCLK_VIN0001_DELAY(SOLO_VCLK_DELAY));
+
+	solo_reg_write(solo_dev, SOLO_VI_ACT_I_P,
+		       SOLO_VI_H_START(solo_dev->vin_hstart) |
+		       SOLO_VI_V_START(solo_dev->vin_vstart) |
+		       SOLO_VI_V_STOP(solo_dev->vin_vstart +
+				      solo_dev->video_vsize));
+
+	solo_reg_write(solo_dev, SOLO_VI_ACT_I_S,
+		       SOLO_VI_H_START(solo_dev->vout_hstart) |
+		       SOLO_VI_V_START(solo_dev->vout_vstart) |
+		       SOLO_VI_V_STOP(solo_dev->vout_vstart +
+				      solo_dev->video_vsize));
+
+	solo_reg_write(solo_dev, SOLO_VI_ACT_P,
+		       SOLO_VI_H_START(0) |
+		       SOLO_VI_V_START(1) |
+		       SOLO_VI_V_STOP(SOLO_PROGRESSIVE_VSIZE));
+
+	solo_reg_write(solo_dev, SOLO_VI_CH_FORMAT,
+		       SOLO_VI_FD_SEL_MASK(0) | SOLO_VI_PROG_MASK(0));
+
+	/* On 6110, initialize mozaic darkness stength */
+	if (solo_dev->type == SOLO_DEV_6010)
+		solo_reg_write(solo_dev, SOLO_VI_FMT_CFG, 0);
+	else
+		solo_reg_write(solo_dev, SOLO_VI_FMT_CFG, 16 << 22);
+
+	solo_reg_write(solo_dev, SOLO_VI_PAGE_SW, 2);
+
+	if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) {
+		solo_reg_write(solo_dev, SOLO_VI_PB_CONFIG,
+			       SOLO_VI_PB_USER_MODE);
+		solo_reg_write(solo_dev, SOLO_VI_PB_RANGE_HV,
+			       SOLO_VI_PB_HSIZE(858) | SOLO_VI_PB_VSIZE(246));
+		solo_reg_write(solo_dev, SOLO_VI_PB_ACT_V,
+			       SOLO_VI_PB_VSTART(4) |
+			       SOLO_VI_PB_VSTOP(4 + 240));
+	} else {
+		solo_reg_write(solo_dev, SOLO_VI_PB_CONFIG,
+			       SOLO_VI_PB_USER_MODE | SOLO_VI_PB_PAL);
+		solo_reg_write(solo_dev, SOLO_VI_PB_RANGE_HV,
+			       SOLO_VI_PB_HSIZE(864) | SOLO_VI_PB_VSIZE(294));
+		solo_reg_write(solo_dev, SOLO_VI_PB_ACT_V,
+			       SOLO_VI_PB_VSTART(4) |
+			       SOLO_VI_PB_VSTOP(4 + 288));
+	}
+	solo_reg_write(solo_dev, SOLO_VI_PB_ACT_H, SOLO_VI_PB_HSTART(16) |
+		       SOLO_VI_PB_HSTOP(16 + 720));
+}
+
+static void solo_vout_config_cursor(struct solo_dev *dev)
+{
+	int i;
+
+	/* Load (blank) cursor bitmap mask (2bpp) */
+	for (i = 0; i < 20; i++)
+		solo_reg_write(dev, SOLO_VO_CURSOR_MASK(i), 0);
+
+	solo_reg_write(dev, SOLO_VO_CURSOR_POS, 0);
+
+	solo_reg_write(dev, SOLO_VO_CURSOR_CLR,
+		       (0x80 << 24) | (0x80 << 16) | (0x10 << 8) | 0x80);
+	solo_reg_write(dev, SOLO_VO_CURSOR_CLR2, (0xe0 << 8) | 0x80);
+}
+
+static void solo_vout_config(struct solo_dev *solo_dev)
+{
+	solo_dev->vout_hstart = 6;
+	solo_dev->vout_vstart = 8;
+
+	solo_reg_write(solo_dev, SOLO_VO_FMT_ENC,
+		       solo_dev->video_type |
+		       SOLO_VO_USER_COLOR_SET_NAV |
+		       SOLO_VO_USER_COLOR_SET_NAH |
+		       SOLO_VO_NA_COLOR_Y(0) |
+		       SOLO_VO_NA_COLOR_CB(0) |
+		       SOLO_VO_NA_COLOR_CR(0));
+
+	solo_reg_write(solo_dev, SOLO_VO_ACT_H,
+		       SOLO_VO_H_START(solo_dev->vout_hstart) |
+		       SOLO_VO_H_STOP(solo_dev->vout_hstart +
+				      solo_dev->video_hsize));
+
+	solo_reg_write(solo_dev, SOLO_VO_ACT_V,
+		       SOLO_VO_V_START(solo_dev->vout_vstart) |
+		       SOLO_VO_V_STOP(solo_dev->vout_vstart +
+				      solo_dev->video_vsize));
+
+	solo_reg_write(solo_dev, SOLO_VO_RANGE_HV,
+		       SOLO_VO_H_LEN(solo_dev->video_hsize) |
+		       SOLO_VO_V_LEN(solo_dev->video_vsize));
+
+	/* Border & background colors */
+	solo_reg_write(solo_dev, SOLO_VO_BORDER_LINE_COLOR,
+		       (0xa0 << 24) | (0x88 << 16) | (0xa0 << 8) | 0x88);
+	solo_reg_write(solo_dev, SOLO_VO_BORDER_FILL_COLOR,
+		       (0x10 << 24) | (0x8f << 16) | (0x10 << 8) | 0x8f);
+	solo_reg_write(solo_dev, SOLO_VO_BKG_COLOR,
+		       (16 << 24) | (128 << 16) | (16 << 8) | 128);
+
+	solo_reg_write(solo_dev, SOLO_VO_DISP_ERASE, SOLO_VO_DISP_ERASE_ON);
+
+	solo_reg_write(solo_dev, SOLO_VI_WIN_SW, 0);
+
+	solo_reg_write(solo_dev, SOLO_VO_ZOOM_CTRL, 0);
+	solo_reg_write(solo_dev, SOLO_VO_FREEZE_CTRL, 0);
+
+	solo_reg_write(solo_dev, SOLO_VO_DISP_CTRL, SOLO_VO_DISP_ON |
+		       SOLO_VO_DISP_ERASE_COUNT(8) |
+		       SOLO_VO_DISP_BASE(SOLO_DISP_EXT_ADDR));
+
+
+	solo_vout_config_cursor(solo_dev);
+
+	/* Enable channels we support */
+	solo_reg_write(solo_dev, SOLO_VI_CH_ENA,
+		       (1 << solo_dev->nr_chans) - 1);
+}
+
+static int solo_dma_vin_region(struct solo_dev *solo_dev, u32 off,
+			       u16 val, int reg_size)
+{
+	u16 buf[64];
+	int i;
+	int ret = 0;
+
+	for (i = 0; i < sizeof(buf) >> 1; i++)
+		buf[i] = cpu_to_le16(val);
+
+	for (i = 0; i < reg_size; i += sizeof(buf))
+		ret |= solo_p2m_dma(solo_dev, 1, buf,
+				    SOLO_MOTION_EXT_ADDR(solo_dev) + off + i,
+				    sizeof(buf), 0, 0);
+
+	return ret;
+}
+
+int solo_set_motion_threshold(struct solo_dev *solo_dev, u8 ch, u16 val)
+{
+	if (ch > solo_dev->nr_chans)
+		return -EINVAL;
+
+	return solo_dma_vin_region(solo_dev, SOLO_MOT_FLAG_AREA +
+				   (ch * SOLO_MOT_THRESH_SIZE * 2),
+				   val, SOLO_MOT_THRESH_SIZE);
+}
+
+int solo_set_motion_block(struct solo_dev *solo_dev, u8 ch,
+		const struct solo_motion_thresholds *thresholds)
+{
+	u32 off = SOLO_MOT_FLAG_AREA + ch * SOLO_MOT_THRESH_SIZE * 2;
+	u16 buf[64];
+	int x, y;
+	int ret = 0;
+
+	memset(buf, 0, sizeof(buf));
+	for (y = 0; y < SOLO_MOTION_SZ; y++) {
+		for (x = 0; x < SOLO_MOTION_SZ; x++)
+			buf[x] = cpu_to_le16(thresholds->thresholds[y][x]);
+		ret |= solo_p2m_dma(solo_dev, 1, buf,
+			SOLO_MOTION_EXT_ADDR(solo_dev) + off + y * sizeof(buf),
+			sizeof(buf), 0, 0);
+	}
+	return ret;
+}
+
+/* First 8k is motion flag (512 bytes * 16). Following that is an 8k+8k
+ * threshold and working table for each channel. Atleast that's what the
+ * spec says. However, this code (taken from rdk) has some mystery 8k
+ * block right after the flag area, before the first thresh table. */
+static void solo_motion_config(struct solo_dev *solo_dev)
+{
+	int i;
+
+	for (i = 0; i < solo_dev->nr_chans; i++) {
+		/* Clear motion flag area */
+		solo_dma_vin_region(solo_dev, i * SOLO_MOT_FLAG_SIZE, 0x0000,
+				    SOLO_MOT_FLAG_SIZE);
+
+		/* Clear working cache table */
+		solo_dma_vin_region(solo_dev, SOLO_MOT_FLAG_AREA +
+				    (i * SOLO_MOT_THRESH_SIZE * 2) +
+				    SOLO_MOT_THRESH_SIZE, 0x0000,
+				    SOLO_MOT_THRESH_SIZE);
+
+		/* Set default threshold table */
+		solo_set_motion_threshold(solo_dev, i, SOLO_DEF_MOT_THRESH);
+	}
+
+	/* Default motion settings */
+	solo_reg_write(solo_dev, SOLO_VI_MOT_ADR, SOLO_VI_MOTION_EN(0) |
+		       (SOLO_MOTION_EXT_ADDR(solo_dev) >> 16));
+	solo_reg_write(solo_dev, SOLO_VI_MOT_CTRL,
+		       SOLO_VI_MOTION_FRAME_COUNT(3) |
+		       SOLO_VI_MOTION_SAMPLE_LENGTH(solo_dev->video_hsize / 16)
+		       /* | SOLO_VI_MOTION_INTR_START_STOP */
+		       | SOLO_VI_MOTION_SAMPLE_COUNT(10));
+
+	solo_reg_write(solo_dev, SOLO_VI_MOTION_BORDER, 0);
+	solo_reg_write(solo_dev, SOLO_VI_MOTION_BAR, 0);
+}
+
+int solo_disp_init(struct solo_dev *solo_dev)
+{
+	int i;
+
+	solo_dev->video_hsize = 704;
+	if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) {
+		solo_dev->video_vsize = 240;
+		solo_dev->fps = 30;
+	} else {
+		solo_dev->video_vsize = 288;
+		solo_dev->fps = 25;
+	}
+
+	solo_vin_config(solo_dev);
+	solo_motion_config(solo_dev);
+	solo_vout_config(solo_dev);
+
+	for (i = 0; i < solo_dev->nr_chans; i++)
+		solo_reg_write(solo_dev, SOLO_VI_WIN_ON(i), 1);
+
+	return 0;
+}
+
+void solo_disp_exit(struct solo_dev *solo_dev)
+{
+	int i;
+
+	solo_reg_write(solo_dev, SOLO_VO_DISP_CTRL, 0);
+	solo_reg_write(solo_dev, SOLO_VO_ZOOM_CTRL, 0);
+	solo_reg_write(solo_dev, SOLO_VO_FREEZE_CTRL, 0);
+
+	for (i = 0; i < solo_dev->nr_chans; i++) {
+		solo_reg_write(solo_dev, SOLO_VI_WIN_CTRL0(i), 0);
+		solo_reg_write(solo_dev, SOLO_VI_WIN_CTRL1(i), 0);
+		solo_reg_write(solo_dev, SOLO_VI_WIN_ON(i), 0);
+	}
+
+	/* Set default border */
+	for (i = 0; i < 5; i++)
+		solo_reg_write(solo_dev, SOLO_VO_BORDER_X(i), 0);
+
+	for (i = 0; i < 5; i++)
+		solo_reg_write(solo_dev, SOLO_VO_BORDER_Y(i), 0);
+
+	solo_reg_write(solo_dev, SOLO_VO_BORDER_LINE_MASK, 0);
+	solo_reg_write(solo_dev, SOLO_VO_BORDER_FILL_MASK, 0);
+
+	solo_reg_write(solo_dev, SOLO_VO_RECTANGLE_CTRL(0), 0);
+	solo_reg_write(solo_dev, SOLO_VO_RECTANGLE_START(0), 0);
+	solo_reg_write(solo_dev, SOLO_VO_RECTANGLE_STOP(0), 0);
+
+	solo_reg_write(solo_dev, SOLO_VO_RECTANGLE_CTRL(1), 0);
+	solo_reg_write(solo_dev, SOLO_VO_RECTANGLE_START(1), 0);
+	solo_reg_write(solo_dev, SOLO_VO_RECTANGLE_STOP(1), 0);
+}
diff --git a/drivers/staging/media/solo6x10/solo6x10-eeprom.c b/drivers/staging/media/solo6x10/solo6x10-eeprom.c
new file mode 100644
index 0000000..9d1c9bb
--- /dev/null
+++ b/drivers/staging/media/solo6x10/solo6x10-eeprom.c
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
+ *
+ * Original author:
+ * Ben Collins <bcollins@ubuntu.com>
+ *
+ * Additional work by:
+ * John Brooks <john.brooks@bluecherry.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You 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/delay.h>
+
+#include "solo6x10.h"
+
+/* Control */
+#define EE_SHIFT_CLK	0x04
+#define EE_CS		0x08
+#define EE_DATA_WRITE	0x02
+#define EE_DATA_READ	0x01
+#define EE_ENB		(0x80 | EE_CS)
+
+#define eeprom_delay()	udelay(100)
+#if 0
+#define eeprom_delay()	solo_reg_read(solo_dev, SOLO_EEPROM_CTRL)
+#define eeprom_delay()	({				\
+	int i, ret;					\
+	udelay(100);					\
+	for (i = ret = 0; i < 1000 && !ret; i++)	\
+		ret = solo_eeprom_reg_read(solo_dev);	\
+})
+#endif
+#define ADDR_LEN	6
+
+/* Commands */
+#define EE_EWEN_CMD	4
+#define EE_EWDS_CMD	4
+#define EE_WRITE_CMD	5
+#define EE_READ_CMD	6
+#define EE_ERASE_CMD	7
+
+static unsigned int solo_eeprom_reg_read(struct solo_dev *solo_dev)
+{
+	return solo_reg_read(solo_dev, SOLO_EEPROM_CTRL) & EE_DATA_READ;
+}
+
+static void solo_eeprom_reg_write(struct solo_dev *solo_dev, u32 data)
+{
+	solo_reg_write(solo_dev, SOLO_EEPROM_CTRL, data);
+	eeprom_delay();
+}
+
+static void solo_eeprom_cmd(struct solo_dev *solo_dev, int cmd)
+{
+	int i;
+
+	solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ACCESS_EN);
+	solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE);
+
+	for (i = 4 + ADDR_LEN; i >= 0; i--) {
+		int dataval = (cmd & (1 << i)) ? EE_DATA_WRITE : 0;
+
+		solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE | dataval);
+		solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE |
+				      EE_SHIFT_CLK | dataval);
+	}
+
+	solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE);
+}
+
+unsigned int solo_eeprom_ewen(struct solo_dev *solo_dev, int w_en)
+{
+	int ewen_cmd = (w_en ? 0x3f : 0) | (EE_EWEN_CMD << ADDR_LEN);
+	unsigned int retval = 0;
+	int i;
+
+	solo_eeprom_cmd(solo_dev, ewen_cmd);
+
+	for (i = 0; i < 16; i++) {
+		solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE |
+				      EE_SHIFT_CLK);
+		retval = (retval << 1) | solo_eeprom_reg_read(solo_dev);
+		solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE);
+		retval = (retval << 1) | solo_eeprom_reg_read(solo_dev);
+	}
+
+	solo_eeprom_reg_write(solo_dev, ~EE_CS);
+	retval = (retval << 1) | solo_eeprom_reg_read(solo_dev);
+
+	return retval;
+}
+
+unsigned short solo_eeprom_read(struct solo_dev *solo_dev, int loc)
+{
+	int read_cmd = loc | (EE_READ_CMD << ADDR_LEN);
+	unsigned short retval = 0;
+	int i;
+
+	solo_eeprom_cmd(solo_dev, read_cmd);
+
+	for (i = 0; i < 16; i++) {
+		solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE |
+				      EE_SHIFT_CLK);
+		retval = (retval << 1) | solo_eeprom_reg_read(solo_dev);
+		solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE);
+	}
+
+	solo_eeprom_reg_write(solo_dev, ~EE_CS);
+
+	return retval;
+}
+
+int solo_eeprom_write(struct solo_dev *solo_dev, int loc,
+		      unsigned short data)
+{
+	int write_cmd = loc | (EE_WRITE_CMD << ADDR_LEN);
+	unsigned int retval;
+	int i;
+
+	solo_eeprom_cmd(solo_dev, write_cmd);
+
+	for (i = 15; i >= 0; i--) {
+		unsigned int dataval = (data >> i) & 1;
+
+		solo_eeprom_reg_write(solo_dev, EE_ENB);
+		solo_eeprom_reg_write(solo_dev,
+				      EE_ENB | (dataval << 1) | EE_SHIFT_CLK);
+	}
+
+	solo_eeprom_reg_write(solo_dev, EE_ENB);
+	solo_eeprom_reg_write(solo_dev, ~EE_CS);
+	solo_eeprom_reg_write(solo_dev, EE_ENB);
+
+	for (i = retval = 0; i < 10000 && !retval; i++)
+		retval = solo_eeprom_reg_read(solo_dev);
+
+	solo_eeprom_reg_write(solo_dev, ~EE_CS);
+
+	return !retval;
+}
diff --git a/drivers/staging/media/solo6x10/solo6x10-enc.c b/drivers/staging/media/solo6x10/solo6x10-enc.c
new file mode 100644
index 0000000..94d5735
--- /dev/null
+++ b/drivers/staging/media/solo6x10/solo6x10-enc.c
@@ -0,0 +1,347 @@
+/*
+ * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
+ *
+ * Original author:
+ * Ben Collins <bcollins@ubuntu.com>
+ *
+ * Additional work by:
+ * John Brooks <john.brooks@bluecherry.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You 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/font.h>
+#include <linux/bitrev.h>
+#include <linux/slab.h>
+
+#include "solo6x10.h"
+
+#define VI_PROG_HSIZE			(1280 - 16)
+#define VI_PROG_VSIZE			(1024 - 16)
+
+#define IRQ_LEVEL			2
+
+static void solo_capture_config(struct solo_dev *solo_dev)
+{
+	unsigned long height;
+	unsigned long width;
+	void *buf;
+	int i;
+
+	solo_reg_write(solo_dev, SOLO_CAP_BASE,
+		       SOLO_CAP_MAX_PAGE((SOLO_CAP_EXT_SIZE(solo_dev)
+					  - SOLO_CAP_PAGE_SIZE) >> 16)
+		       | SOLO_CAP_BASE_ADDR(SOLO_CAP_EXT_ADDR(solo_dev) >> 16));
+
+	/* XXX: Undocumented bits at b17 and b24 */
+	if (solo_dev->type == SOLO_DEV_6110) {
+		/* NOTE: Ref driver has (62 << 24) here as well, but it causes
+		 * wacked out frame timing on 4-port 6110. */
+		solo_reg_write(solo_dev, SOLO_CAP_BTW,
+			       (1 << 17) | SOLO_CAP_PROG_BANDWIDTH(2) |
+			       SOLO_CAP_MAX_BANDWIDTH(36));
+	} else {
+		solo_reg_write(solo_dev, SOLO_CAP_BTW,
+			       (1 << 17) | SOLO_CAP_PROG_BANDWIDTH(2) |
+			       SOLO_CAP_MAX_BANDWIDTH(32));
+	}
+
+	/* Set scale 1, 9 dimension */
+	width = solo_dev->video_hsize;
+	height = solo_dev->video_vsize;
+	solo_reg_write(solo_dev, SOLO_DIM_SCALE1,
+		       SOLO_DIM_H_MB_NUM(width / 16) |
+		       SOLO_DIM_V_MB_NUM_FRAME(height / 8) |
+		       SOLO_DIM_V_MB_NUM_FIELD(height / 16));
+
+	/* Set scale 2, 10 dimension */
+	width = solo_dev->video_hsize / 2;
+	height = solo_dev->video_vsize;
+	solo_reg_write(solo_dev, SOLO_DIM_SCALE2,
+		       SOLO_DIM_H_MB_NUM(width / 16) |
+		       SOLO_DIM_V_MB_NUM_FRAME(height / 8) |
+		       SOLO_DIM_V_MB_NUM_FIELD(height / 16));
+
+	/* Set scale 3, 11 dimension */
+	width = solo_dev->video_hsize / 2;
+	height = solo_dev->video_vsize / 2;
+	solo_reg_write(solo_dev, SOLO_DIM_SCALE3,
+		       SOLO_DIM_H_MB_NUM(width / 16) |
+		       SOLO_DIM_V_MB_NUM_FRAME(height / 8) |
+		       SOLO_DIM_V_MB_NUM_FIELD(height / 16));
+
+	/* Set scale 4, 12 dimension */
+	width = solo_dev->video_hsize / 3;
+	height = solo_dev->video_vsize / 3;
+	solo_reg_write(solo_dev, SOLO_DIM_SCALE4,
+		       SOLO_DIM_H_MB_NUM(width / 16) |
+		       SOLO_DIM_V_MB_NUM_FRAME(height / 8) |
+		       SOLO_DIM_V_MB_NUM_FIELD(height / 16));
+
+	/* Set scale 5, 13 dimension */
+	width = solo_dev->video_hsize / 4;
+	height = solo_dev->video_vsize / 2;
+	solo_reg_write(solo_dev, SOLO_DIM_SCALE5,
+		       SOLO_DIM_H_MB_NUM(width / 16) |
+		       SOLO_DIM_V_MB_NUM_FRAME(height / 8) |
+		       SOLO_DIM_V_MB_NUM_FIELD(height / 16));
+
+	/* Progressive */
+	width = VI_PROG_HSIZE;
+	height = VI_PROG_VSIZE;
+	solo_reg_write(solo_dev, SOLO_DIM_PROG,
+		       SOLO_DIM_H_MB_NUM(width / 16) |
+		       SOLO_DIM_V_MB_NUM_FRAME(height / 16) |
+		       SOLO_DIM_V_MB_NUM_FIELD(height / 16));
+
+	/* Clear OSD */
+	solo_reg_write(solo_dev, SOLO_VE_OSD_CH, 0);
+	solo_reg_write(solo_dev, SOLO_VE_OSD_BASE, SOLO_EOSD_EXT_ADDR >> 16);
+	solo_reg_write(solo_dev, SOLO_VE_OSD_CLR,
+		       0xF0 << 16 | 0x80 << 8 | 0x80);
+
+	if (solo_dev->type == SOLO_DEV_6010)
+		solo_reg_write(solo_dev, SOLO_VE_OSD_OPT,
+			       SOLO_VE_OSD_H_SHADOW | SOLO_VE_OSD_V_SHADOW);
+	else
+		solo_reg_write(solo_dev, SOLO_VE_OSD_OPT, SOLO_VE_OSD_V_DOUBLE
+			       | SOLO_VE_OSD_H_SHADOW | SOLO_VE_OSD_V_SHADOW);
+
+	/* Clear OSG buffer */
+	buf = kzalloc(SOLO_EOSD_EXT_SIZE(solo_dev), GFP_KERNEL);
+	if (!buf)
+		return;
+
+	for (i = 0; i < solo_dev->nr_chans; i++) {
+		solo_p2m_dma(solo_dev, 1, buf,
+			     SOLO_EOSD_EXT_ADDR +
+			     (SOLO_EOSD_EXT_SIZE(solo_dev) * i),
+			     SOLO_EOSD_EXT_SIZE(solo_dev), 0, 0);
+	}
+	kfree(buf);
+}
+
+/* Should be called with enable_lock held */
+int solo_osd_print(struct solo_enc_dev *solo_enc)
+{
+	struct solo_dev *solo_dev = solo_enc->solo_dev;
+	unsigned char *str = solo_enc->osd_text;
+	u8 *buf = solo_enc->osd_buf;
+	u32 reg = solo_reg_read(solo_dev, SOLO_VE_OSD_CH);
+	const struct font_desc *vga = find_font("VGA8x16");
+	const unsigned char *vga_data;
+	int len;
+	int i, j;
+
+	if (WARN_ON_ONCE(!vga))
+		return -ENODEV;
+
+	len = strlen(str);
+
+	if (len == 0) {
+		/* Disable OSD on this channel */
+		reg &= ~(1 << solo_enc->ch);
+		solo_reg_write(solo_dev, SOLO_VE_OSD_CH, reg);
+		return 0;
+	}
+
+	memset(buf, 0, SOLO_EOSD_EXT_SIZE_MAX);
+	vga_data = (const unsigned char *)vga->data;
+
+	for (i = 0; i < len; i++) {
+		unsigned char c = str[i];
+
+		for (j = 0; j < 16; j++) {
+			buf[(j * 2) + (i % 2) + (i / 2 * 32)] =
+				bitrev8(vga_data[(c * 16) + j]);
+		}
+	}
+
+	solo_p2m_dma(solo_dev, 1, buf,
+		     SOLO_EOSD_EXT_ADDR +
+		     (solo_enc->ch * SOLO_EOSD_EXT_SIZE(solo_dev)),
+		     SOLO_EOSD_EXT_SIZE(solo_dev), 0, 0);
+
+	/* Enable OSD on this channel */
+	reg |= (1 << solo_enc->ch);
+	solo_reg_write(solo_dev, SOLO_VE_OSD_CH, reg);
+
+	return 0;
+}
+
+/**
+ * Set channel Quality Profile (0-3).
+ */
+void solo_s_jpeg_qp(struct solo_dev *solo_dev, unsigned int ch,
+		    unsigned int qp)
+{
+	unsigned long flags;
+	unsigned int idx, reg;
+
+	if ((ch > 31) || (qp > 3))
+		return;
+
+	if (solo_dev->type == SOLO_DEV_6010)
+		return;
+
+	if (ch < 16) {
+		idx = 0;
+		reg = SOLO_VE_JPEG_QP_CH_L;
+	} else {
+		ch -= 16;
+		idx = 1;
+		reg = SOLO_VE_JPEG_QP_CH_H;
+	}
+	ch *= 2;
+
+	spin_lock_irqsave(&solo_dev->jpeg_qp_lock, flags);
+
+	solo_dev->jpeg_qp[idx] &= ~(3 << ch);
+	solo_dev->jpeg_qp[idx] |= (qp & 3) << ch;
+
+	solo_reg_write(solo_dev, reg, solo_dev->jpeg_qp[idx]);
+
+	spin_unlock_irqrestore(&solo_dev->jpeg_qp_lock, flags);
+}
+
+int solo_g_jpeg_qp(struct solo_dev *solo_dev, unsigned int ch)
+{
+	int idx;
+
+	if (solo_dev->type == SOLO_DEV_6010)
+		return 2;
+
+	if (WARN_ON_ONCE(ch > 31))
+		return 2;
+
+	if (ch < 16) {
+		idx = 0;
+	} else {
+		ch -= 16;
+		idx = 1;
+	}
+	ch *= 2;
+
+	return (solo_dev->jpeg_qp[idx] >> ch) & 3;
+}
+
+#define SOLO_QP_INIT 0xaaaaaaaa
+
+static void solo_jpeg_config(struct solo_dev *solo_dev)
+{
+	if (solo_dev->type == SOLO_DEV_6010) {
+		solo_reg_write(solo_dev, SOLO_VE_JPEG_QP_TBL,
+			       (2 << 24) | (2 << 16) | (2 << 8) | 2);
+	} else {
+		solo_reg_write(solo_dev, SOLO_VE_JPEG_QP_TBL,
+			       (4 << 24) | (3 << 16) | (2 << 8) | 1);
+	}
+
+	spin_lock_init(&solo_dev->jpeg_qp_lock);
+
+	/* Initialize Quality Profile for all channels */
+	solo_dev->jpeg_qp[0] = solo_dev->jpeg_qp[1] = SOLO_QP_INIT;
+	solo_reg_write(solo_dev, SOLO_VE_JPEG_QP_CH_L, SOLO_QP_INIT);
+	solo_reg_write(solo_dev, SOLO_VE_JPEG_QP_CH_H, SOLO_QP_INIT);
+
+	solo_reg_write(solo_dev, SOLO_VE_JPEG_CFG,
+		(SOLO_JPEG_EXT_SIZE(solo_dev) & 0xffff0000) |
+		((SOLO_JPEG_EXT_ADDR(solo_dev) >> 16) & 0x0000ffff));
+	solo_reg_write(solo_dev, SOLO_VE_JPEG_CTRL, 0xffffffff);
+	if (solo_dev->type == SOLO_DEV_6110) {
+		solo_reg_write(solo_dev, SOLO_VE_JPEG_CFG1,
+			       (0 << 16) | (30 << 8) | 60);
+	}
+}
+
+static void solo_mp4e_config(struct solo_dev *solo_dev)
+{
+	int i;
+	u32 cfg;
+
+	solo_reg_write(solo_dev, SOLO_VE_CFG0,
+		       SOLO_VE_INTR_CTRL(IRQ_LEVEL) |
+		       SOLO_VE_BLOCK_SIZE(SOLO_MP4E_EXT_SIZE(solo_dev) >> 16) |
+		       SOLO_VE_BLOCK_BASE(SOLO_MP4E_EXT_ADDR(solo_dev) >> 16));
+
+
+	cfg = SOLO_VE_BYTE_ALIGN(2) | SOLO_VE_INSERT_INDEX
+		| SOLO_VE_MOTION_MODE(0);
+	if (solo_dev->type != SOLO_DEV_6010) {
+		cfg |= SOLO_VE_MPEG_SIZE_H(
+			(SOLO_MP4E_EXT_SIZE(solo_dev) >> 24) & 0x0f);
+		cfg |= SOLO_VE_JPEG_SIZE_H(
+			(SOLO_JPEG_EXT_SIZE(solo_dev) >> 24) & 0x0f);
+	}
+	solo_reg_write(solo_dev, SOLO_VE_CFG1, cfg);
+
+	solo_reg_write(solo_dev, SOLO_VE_WMRK_POLY, 0);
+	solo_reg_write(solo_dev, SOLO_VE_VMRK_INIT_KEY, 0);
+	solo_reg_write(solo_dev, SOLO_VE_WMRK_STRL, 0);
+	if (solo_dev->type == SOLO_DEV_6110)
+		solo_reg_write(solo_dev, SOLO_VE_WMRK_ENABLE, 0);
+	solo_reg_write(solo_dev, SOLO_VE_ENCRYP_POLY, 0);
+	solo_reg_write(solo_dev, SOLO_VE_ENCRYP_INIT, 0);
+
+	solo_reg_write(solo_dev, SOLO_VE_ATTR,
+		       SOLO_VE_LITTLE_ENDIAN |
+		       SOLO_COMP_ATTR_FCODE(1) |
+		       SOLO_COMP_TIME_INC(0) |
+		       SOLO_COMP_TIME_WIDTH(15) |
+		       SOLO_DCT_INTERVAL(solo_dev->type == SOLO_DEV_6010 ? 9 : 10));
+
+	for (i = 0; i < solo_dev->nr_chans; i++) {
+		solo_reg_write(solo_dev, SOLO_VE_CH_REF_BASE(i),
+			       (SOLO_EREF_EXT_ADDR(solo_dev) +
+			       (i * SOLO_EREF_EXT_SIZE)) >> 16);
+		solo_reg_write(solo_dev, SOLO_VE_CH_REF_BASE_E(i),
+			       (SOLO_EREF_EXT_ADDR(solo_dev) +
+			       ((i + 16) * SOLO_EREF_EXT_SIZE)) >> 16);
+	}
+
+	if (solo_dev->type == SOLO_DEV_6110) {
+		solo_reg_write(solo_dev, SOLO_VE_COMPT_MOT, 0x00040008);
+	} else {
+		for (i = 0; i < solo_dev->nr_chans; i++)
+			solo_reg_write(solo_dev, SOLO_VE_CH_MOT(i), 0x100);
+	}
+}
+
+int solo_enc_init(struct solo_dev *solo_dev)
+{
+	int i;
+
+	solo_capture_config(solo_dev);
+	solo_mp4e_config(solo_dev);
+	solo_jpeg_config(solo_dev);
+
+	for (i = 0; i < solo_dev->nr_chans; i++) {
+		solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(i), 0);
+		solo_reg_write(solo_dev, SOLO_CAP_CH_COMP_ENA_E(i), 0);
+	}
+
+	return 0;
+}
+
+void solo_enc_exit(struct solo_dev *solo_dev)
+{
+	int i;
+
+	for (i = 0; i < solo_dev->nr_chans; i++) {
+		solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(i), 0);
+		solo_reg_write(solo_dev, SOLO_CAP_CH_COMP_ENA_E(i), 0);
+	}
+}
diff --git a/drivers/staging/media/solo6x10/solo6x10-g723.c b/drivers/staging/media/solo6x10/solo6x10-g723.c
new file mode 100644
index 0000000..1db18c7
--- /dev/null
+++ b/drivers/staging/media/solo6x10/solo6x10-g723.c
@@ -0,0 +1,424 @@
+/*
+ * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
+ *
+ * Original author:
+ * Ben Collins <bcollins@ubuntu.com>
+ *
+ * Additional work by:
+ * John Brooks <john.brooks@bluecherry.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You 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/mempool.h>
+#include <linux/poll.h>
+#include <linux/kthread.h>
+#include <linux/freezer.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/pcm.h>
+#include <sound/control.h>
+
+#include "solo6x10.h"
+#include "solo6x10-tw28.h"
+
+#define G723_FDMA_PAGES		32
+#define G723_PERIOD_BYTES	48
+#define G723_PERIOD_BLOCK	1024
+#define G723_FRAMES_PER_PAGE	48
+
+/* Sets up channels 16-19 for decoding and 0-15 for encoding */
+#define OUTMODE_MASK		0x300
+
+#define SAMPLERATE		8000
+#define BITRATE			25
+
+/* The solo writes to 1k byte pages, 32 pages, in the dma. Each 1k page
+ * is broken down to 20 * 48 byte regions (one for each channel possible)
+ * with the rest of the page being dummy data. */
+#define G723_MAX_BUFFER		(G723_PERIOD_BYTES * PERIODS_MAX)
+#define G723_INTR_ORDER		4 /* 0 - 4 */
+#define PERIODS_MIN		(1 << G723_INTR_ORDER)
+#define PERIODS_MAX		G723_FDMA_PAGES
+
+struct solo_snd_pcm {
+	int				on;
+	spinlock_t			lock;
+	struct solo_dev		*solo_dev;
+	unsigned char			*g723_buf;
+	dma_addr_t			g723_dma;
+};
+
+static void solo_g723_config(struct solo_dev *solo_dev)
+{
+	int clk_div;
+
+	clk_div = (solo_dev->clock_mhz * 1000000)
+		/ (SAMPLERATE * (BITRATE * 2) * 2);
+
+	solo_reg_write(solo_dev, SOLO_AUDIO_SAMPLE,
+		       SOLO_AUDIO_BITRATE(BITRATE)
+		       | SOLO_AUDIO_CLK_DIV(clk_div));
+
+	solo_reg_write(solo_dev, SOLO_AUDIO_FDMA_INTR,
+		       SOLO_AUDIO_FDMA_INTERVAL(1)
+		       | SOLO_AUDIO_INTR_ORDER(G723_INTR_ORDER)
+		       | SOLO_AUDIO_FDMA_BASE(SOLO_G723_EXT_ADDR(solo_dev) >> 16));
+
+	solo_reg_write(solo_dev, SOLO_AUDIO_CONTROL,
+		       SOLO_AUDIO_ENABLE
+		       | SOLO_AUDIO_I2S_MODE
+		       | SOLO_AUDIO_I2S_MULTI(3)
+		       | SOLO_AUDIO_MODE(OUTMODE_MASK));
+}
+
+void solo_g723_isr(struct solo_dev *solo_dev)
+{
+	struct snd_pcm_str *pstr =
+		&solo_dev->snd_pcm->streams[SNDRV_PCM_STREAM_CAPTURE];
+	struct snd_pcm_substream *ss;
+	struct solo_snd_pcm *solo_pcm;
+
+	for (ss = pstr->substream; ss != NULL; ss = ss->next) {
+		if (snd_pcm_substream_chip(ss) == NULL)
+			continue;
+
+		/* This means open() hasn't been called on this one */
+		if (snd_pcm_substream_chip(ss) == solo_dev)
+			continue;
+
+		/* Haven't triggered a start yet */
+		solo_pcm = snd_pcm_substream_chip(ss);
+		if (!solo_pcm->on)
+			continue;
+
+		snd_pcm_period_elapsed(ss);
+	}
+}
+
+static int snd_solo_hw_params(struct snd_pcm_substream *ss,
+			      struct snd_pcm_hw_params *hw_params)
+{
+	return snd_pcm_lib_malloc_pages(ss, params_buffer_bytes(hw_params));
+}
+
+static int snd_solo_hw_free(struct snd_pcm_substream *ss)
+{
+	return snd_pcm_lib_free_pages(ss);
+}
+
+static const struct snd_pcm_hardware snd_solo_pcm_hw = {
+	.info			= (SNDRV_PCM_INFO_MMAP |
+				   SNDRV_PCM_INFO_INTERLEAVED |
+				   SNDRV_PCM_INFO_BLOCK_TRANSFER |
+				   SNDRV_PCM_INFO_MMAP_VALID),
+	.formats		= SNDRV_PCM_FMTBIT_U8,
+	.rates			= SNDRV_PCM_RATE_8000,
+	.rate_min		= SAMPLERATE,
+	.rate_max		= SAMPLERATE,
+	.channels_min		= 1,
+	.channels_max		= 1,
+	.buffer_bytes_max	= G723_MAX_BUFFER,
+	.period_bytes_min	= G723_PERIOD_BYTES,
+	.period_bytes_max	= G723_PERIOD_BYTES,
+	.periods_min		= PERIODS_MIN,
+	.periods_max		= PERIODS_MAX,
+};
+
+static int snd_solo_pcm_open(struct snd_pcm_substream *ss)
+{
+	struct solo_dev *solo_dev = snd_pcm_substream_chip(ss);
+	struct solo_snd_pcm *solo_pcm;
+
+	solo_pcm = kzalloc(sizeof(*solo_pcm), GFP_KERNEL);
+	if (solo_pcm == NULL)
+		goto oom;
+
+	solo_pcm->g723_buf = pci_alloc_consistent(solo_dev->pdev,
+						  G723_PERIOD_BYTES,
+						  &solo_pcm->g723_dma);
+	if (solo_pcm->g723_buf == NULL)
+		goto oom;
+
+	spin_lock_init(&solo_pcm->lock);
+	solo_pcm->solo_dev = solo_dev;
+	ss->runtime->hw = snd_solo_pcm_hw;
+
+	snd_pcm_substream_chip(ss) = solo_pcm;
+
+	return 0;
+
+oom:
+	kfree(solo_pcm);
+	return -ENOMEM;
+}
+
+static int snd_solo_pcm_close(struct snd_pcm_substream *ss)
+{
+	struct solo_snd_pcm *solo_pcm = snd_pcm_substream_chip(ss);
+
+	snd_pcm_substream_chip(ss) = solo_pcm->solo_dev;
+	pci_free_consistent(solo_pcm->solo_dev->pdev, G723_PERIOD_BYTES,
+			    solo_pcm->g723_buf, solo_pcm->g723_dma);
+	kfree(solo_pcm);
+
+	return 0;
+}
+
+static int snd_solo_pcm_trigger(struct snd_pcm_substream *ss, int cmd)
+{
+	struct solo_snd_pcm *solo_pcm = snd_pcm_substream_chip(ss);
+	struct solo_dev *solo_dev = solo_pcm->solo_dev;
+	int ret = 0;
+
+	spin_lock(&solo_pcm->lock);
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+		if (solo_pcm->on == 0) {
+			/* If this is the first user, switch on interrupts */
+			if (atomic_inc_return(&solo_dev->snd_users) == 1)
+				solo_irq_on(solo_dev, SOLO_IRQ_G723);
+			solo_pcm->on = 1;
+		}
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+		if (solo_pcm->on) {
+			/* If this was our last user, switch them off */
+			if (atomic_dec_return(&solo_dev->snd_users) == 0)
+				solo_irq_off(solo_dev, SOLO_IRQ_G723);
+			solo_pcm->on = 0;
+		}
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	spin_unlock(&solo_pcm->lock);
+
+	return ret;
+}
+
+static int snd_solo_pcm_prepare(struct snd_pcm_substream *ss)
+{
+	return 0;
+}
+
+static snd_pcm_uframes_t snd_solo_pcm_pointer(struct snd_pcm_substream *ss)
+{
+	struct solo_snd_pcm *solo_pcm = snd_pcm_substream_chip(ss);
+	struct solo_dev *solo_dev = solo_pcm->solo_dev;
+	snd_pcm_uframes_t idx = solo_reg_read(solo_dev, SOLO_AUDIO_STA) & 0x1f;
+
+	return idx * G723_FRAMES_PER_PAGE;
+}
+
+static int snd_solo_pcm_copy(struct snd_pcm_substream *ss, int channel,
+			     snd_pcm_uframes_t pos, void __user *dst,
+			     snd_pcm_uframes_t count)
+{
+	struct solo_snd_pcm *solo_pcm = snd_pcm_substream_chip(ss);
+	struct solo_dev *solo_dev = solo_pcm->solo_dev;
+	int err, i;
+
+	for (i = 0; i < (count / G723_FRAMES_PER_PAGE); i++) {
+		int page = (pos / G723_FRAMES_PER_PAGE) + i;
+
+		err = solo_p2m_dma_t(solo_dev, 0, solo_pcm->g723_dma,
+				     SOLO_G723_EXT_ADDR(solo_dev) +
+				     (page * G723_PERIOD_BLOCK) +
+				     (ss->number * G723_PERIOD_BYTES),
+				     G723_PERIOD_BYTES, 0, 0);
+		if (err)
+			return err;
+
+		err = copy_to_user(dst + (i * G723_PERIOD_BYTES),
+				   solo_pcm->g723_buf, G723_PERIOD_BYTES);
+
+		if (err)
+			return -EFAULT;
+	}
+
+	return 0;
+}
+
+static struct snd_pcm_ops snd_solo_pcm_ops = {
+	.open = snd_solo_pcm_open,
+	.close = snd_solo_pcm_close,
+	.ioctl = snd_pcm_lib_ioctl,
+	.hw_params = snd_solo_hw_params,
+	.hw_free = snd_solo_hw_free,
+	.prepare = snd_solo_pcm_prepare,
+	.trigger = snd_solo_pcm_trigger,
+	.pointer = snd_solo_pcm_pointer,
+	.copy = snd_solo_pcm_copy,
+};
+
+static int snd_solo_capture_volume_info(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_info *info)
+{
+	info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	info->count = 1;
+	info->value.integer.min = 0;
+	info->value.integer.max = 15;
+	info->value.integer.step = 1;
+
+	return 0;
+}
+
+static int snd_solo_capture_volume_get(struct snd_kcontrol *kcontrol,
+				       struct snd_ctl_elem_value *value)
+{
+	struct solo_dev *solo_dev = snd_kcontrol_chip(kcontrol);
+	u8 ch = value->id.numid - 1;
+
+	value->value.integer.value[0] = tw28_get_audio_gain(solo_dev, ch);
+
+	return 0;
+}
+
+static int snd_solo_capture_volume_put(struct snd_kcontrol *kcontrol,
+				       struct snd_ctl_elem_value *value)
+{
+	struct solo_dev *solo_dev = snd_kcontrol_chip(kcontrol);
+	u8 ch = value->id.numid - 1;
+	u8 old_val;
+
+	old_val = tw28_get_audio_gain(solo_dev, ch);
+	if (old_val == value->value.integer.value[0])
+		return 0;
+
+	tw28_set_audio_gain(solo_dev, ch, value->value.integer.value[0]);
+
+	return 1;
+}
+
+static struct snd_kcontrol_new snd_solo_capture_volume = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "Capture Volume",
+	.info = snd_solo_capture_volume_info,
+	.get = snd_solo_capture_volume_get,
+	.put = snd_solo_capture_volume_put,
+};
+
+static int solo_snd_pcm_init(struct solo_dev *solo_dev)
+{
+	struct snd_card *card = solo_dev->snd_card;
+	struct snd_pcm *pcm;
+	struct snd_pcm_substream *ss;
+	int ret;
+	int i;
+
+	ret = snd_pcm_new(card, card->driver, 0, 0, solo_dev->nr_chans,
+			  &pcm);
+	if (ret < 0)
+		return ret;
+
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
+			&snd_solo_pcm_ops);
+
+	snd_pcm_chip(pcm) = solo_dev;
+	pcm->info_flags = 0;
+	strcpy(pcm->name, card->shortname);
+
+	for (i = 0, ss = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
+	     ss; ss = ss->next, i++)
+		sprintf(ss->name, "Camera #%d Audio", i);
+
+	ret = snd_pcm_lib_preallocate_pages_for_all(pcm,
+					SNDRV_DMA_TYPE_CONTINUOUS,
+					snd_dma_continuous_data(GFP_KERNEL),
+					G723_MAX_BUFFER, G723_MAX_BUFFER);
+	if (ret < 0)
+		return ret;
+
+	solo_dev->snd_pcm = pcm;
+
+	return 0;
+}
+
+int solo_g723_init(struct solo_dev *solo_dev)
+{
+	static struct snd_device_ops ops = { NULL };
+	struct snd_card *card;
+	struct snd_kcontrol_new kctl;
+	char name[32];
+	int ret;
+
+	atomic_set(&solo_dev->snd_users, 0);
+
+	/* Allows for easier mapping between video and audio */
+	sprintf(name, "Softlogic%d", solo_dev->vfd->num);
+
+	ret = snd_card_create(SNDRV_DEFAULT_IDX1, name, THIS_MODULE, 0,
+			      &solo_dev->snd_card);
+	if (ret < 0)
+		return ret;
+
+	card = solo_dev->snd_card;
+
+	strcpy(card->driver, SOLO6X10_NAME);
+	strcpy(card->shortname, "SOLO-6x10 Audio");
+	sprintf(card->longname, "%s on %s IRQ %d", card->shortname,
+		pci_name(solo_dev->pdev), solo_dev->pdev->irq);
+	snd_card_set_dev(card, &solo_dev->pdev->dev);
+
+	ret = snd_device_new(card, SNDRV_DEV_LOWLEVEL, solo_dev, &ops);
+	if (ret < 0)
+		goto snd_error;
+
+	/* Mixer controls */
+	strcpy(card->mixername, "SOLO-6x10");
+	kctl = snd_solo_capture_volume;
+	kctl.count = solo_dev->nr_chans;
+
+	ret = snd_ctl_add(card, snd_ctl_new1(&kctl, solo_dev));
+	if (ret < 0)
+		return ret;
+
+	ret = solo_snd_pcm_init(solo_dev);
+	if (ret < 0)
+		goto snd_error;
+
+	ret = snd_card_register(card);
+	if (ret < 0)
+		goto snd_error;
+
+	solo_g723_config(solo_dev);
+
+	dev_info(&solo_dev->pdev->dev, "Alsa sound card as %s\n", name);
+
+	return 0;
+
+snd_error:
+	snd_card_free(card);
+	return ret;
+}
+
+void solo_g723_exit(struct solo_dev *solo_dev)
+{
+	if (!solo_dev->snd_card)
+		return;
+
+	solo_reg_write(solo_dev, SOLO_AUDIO_CONTROL, 0);
+	solo_irq_off(solo_dev, SOLO_IRQ_G723);
+
+	snd_card_free(solo_dev->snd_card);
+	solo_dev->snd_card = NULL;
+}
diff --git a/drivers/staging/media/solo6x10/solo6x10-gpio.c b/drivers/staging/media/solo6x10/solo6x10-gpio.c
new file mode 100644
index 0000000..73276dc
--- /dev/null
+++ b/drivers/staging/media/solo6x10/solo6x10-gpio.c
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
+ *
+ * Original author:
+ * Ben Collins <bcollins@ubuntu.com>
+ *
+ * Additional work by:
+ * John Brooks <john.brooks@bluecherry.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You 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/fs.h>
+#include <linux/delay.h>
+#include <linux/uaccess.h>
+
+#include "solo6x10.h"
+
+static void solo_gpio_mode(struct solo_dev *solo_dev,
+			   unsigned int port_mask, unsigned int mode)
+{
+	int port;
+	unsigned int ret;
+
+	ret = solo_reg_read(solo_dev, SOLO_GPIO_CONFIG_0);
+
+	/* To set gpio */
+	for (port = 0; port < 16; port++) {
+		if (!((1 << port) & port_mask))
+			continue;
+
+		ret &= (~(3 << (port << 1)));
+		ret |= ((mode & 3) << (port << 1));
+	}
+
+	solo_reg_write(solo_dev, SOLO_GPIO_CONFIG_0, ret);
+
+	/* To set extended gpio - sensor */
+	ret = solo_reg_read(solo_dev, SOLO_GPIO_CONFIG_1);
+
+	for (port = 0; port < 16; port++) {
+		if (!((1 << (port + 16)) & port_mask))
+			continue;
+
+		if (!mode)
+			ret &= ~(1 << port);
+		else
+			ret |= 1 << port;
+	}
+
+	solo_reg_write(solo_dev, SOLO_GPIO_CONFIG_1, ret);
+}
+
+static void solo_gpio_set(struct solo_dev *solo_dev, unsigned int value)
+{
+	solo_reg_write(solo_dev, SOLO_GPIO_DATA_OUT,
+		       solo_reg_read(solo_dev, SOLO_GPIO_DATA_OUT) | value);
+}
+
+static void solo_gpio_clear(struct solo_dev *solo_dev, unsigned int value)
+{
+	solo_reg_write(solo_dev, SOLO_GPIO_DATA_OUT,
+		       solo_reg_read(solo_dev, SOLO_GPIO_DATA_OUT) & ~value);
+}
+
+static void solo_gpio_config(struct solo_dev *solo_dev)
+{
+	/* Video reset */
+	solo_gpio_mode(solo_dev, 0x30, 1);
+	solo_gpio_clear(solo_dev, 0x30);
+	udelay(100);
+	solo_gpio_set(solo_dev, 0x30);
+	udelay(100);
+
+	/* Warning: Don't touch the next line unless you're sure of what
+	 * you're doing: first four gpio [0-3] are used for video. */
+	solo_gpio_mode(solo_dev, 0x0f, 2);
+
+	/* We use bit 8-15 of SOLO_GPIO_CONFIG_0 for relay purposes */
+	solo_gpio_mode(solo_dev, 0xff00, 1);
+
+	/* Initially set relay status to 0 */
+	solo_gpio_clear(solo_dev, 0xff00);
+}
+
+int solo_gpio_init(struct solo_dev *solo_dev)
+{
+	solo_gpio_config(solo_dev);
+	return 0;
+}
+
+void solo_gpio_exit(struct solo_dev *solo_dev)
+{
+	solo_gpio_clear(solo_dev, 0x30);
+	solo_gpio_config(solo_dev);
+}
diff --git a/drivers/staging/media/solo6x10/solo6x10-i2c.c b/drivers/staging/media/solo6x10/solo6x10-i2c.c
new file mode 100644
index 0000000..01aa417
--- /dev/null
+++ b/drivers/staging/media/solo6x10/solo6x10-i2c.c
@@ -0,0 +1,334 @@
+/*
+ * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
+ *
+ * Original author:
+ * Ben Collins <bcollins@ubuntu.com>
+ *
+ * Additional work by:
+ * John Brooks <john.brooks@bluecherry.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You 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.
+ */
+
+/* XXX: The SOLO6x10 i2c does not have separate interrupts for each i2c
+ * channel. The bus can only handle one i2c event at a time. The below handles
+ * this all wrong. We should be using the status registers to see if the bus
+ * is in use, and have a global lock to check the status register. Also,
+ * the bulk of the work should be handled out-of-interrupt. The ugly loops
+ * that occur during interrupt scare me. The ISR should merely signal
+ * thread context, ACK the interrupt, and move on. -- BenC */
+
+#include <linux/kernel.h>
+
+#include "solo6x10.h"
+
+u8 solo_i2c_readbyte(struct solo_dev *solo_dev, int id, u8 addr, u8 off)
+{
+	struct i2c_msg msgs[2];
+	u8 data;
+
+	msgs[0].flags = 0;
+	msgs[0].addr = addr;
+	msgs[0].len = 1;
+	msgs[0].buf = &off;
+
+	msgs[1].flags = I2C_M_RD;
+	msgs[1].addr = addr;
+	msgs[1].len = 1;
+	msgs[1].buf = &data;
+
+	i2c_transfer(&solo_dev->i2c_adap[id], msgs, 2);
+
+	return data;
+}
+
+void solo_i2c_writebyte(struct solo_dev *solo_dev, int id, u8 addr,
+			u8 off, u8 data)
+{
+	struct i2c_msg msgs;
+	u8 buf[2];
+
+	buf[0] = off;
+	buf[1] = data;
+	msgs.flags = 0;
+	msgs.addr = addr;
+	msgs.len = 2;
+	msgs.buf = buf;
+
+	i2c_transfer(&solo_dev->i2c_adap[id], &msgs, 1);
+}
+
+static void solo_i2c_flush(struct solo_dev *solo_dev, int wr)
+{
+	u32 ctrl;
+
+	ctrl = SOLO_IIC_CH_SET(solo_dev->i2c_id);
+
+	if (solo_dev->i2c_state == IIC_STATE_START)
+		ctrl |= SOLO_IIC_START;
+
+	if (wr) {
+		ctrl |= SOLO_IIC_WRITE;
+	} else {
+		ctrl |= SOLO_IIC_READ;
+		if (!(solo_dev->i2c_msg->flags & I2C_M_NO_RD_ACK))
+			ctrl |= SOLO_IIC_ACK_EN;
+	}
+
+	if (solo_dev->i2c_msg_ptr == solo_dev->i2c_msg->len)
+		ctrl |= SOLO_IIC_STOP;
+
+	solo_reg_write(solo_dev, SOLO_IIC_CTRL, ctrl);
+}
+
+static void solo_i2c_start(struct solo_dev *solo_dev)
+{
+	u32 addr = solo_dev->i2c_msg->addr << 1;
+
+	if (solo_dev->i2c_msg->flags & I2C_M_RD)
+		addr |= 1;
+
+	solo_dev->i2c_state = IIC_STATE_START;
+	solo_reg_write(solo_dev, SOLO_IIC_TXD, addr);
+	solo_i2c_flush(solo_dev, 1);
+}
+
+static void solo_i2c_stop(struct solo_dev *solo_dev)
+{
+	solo_irq_off(solo_dev, SOLO_IRQ_IIC);
+	solo_reg_write(solo_dev, SOLO_IIC_CTRL, 0);
+	solo_dev->i2c_state = IIC_STATE_STOP;
+	wake_up(&solo_dev->i2c_wait);
+}
+
+static int solo_i2c_handle_read(struct solo_dev *solo_dev)
+{
+prepare_read:
+	if (solo_dev->i2c_msg_ptr != solo_dev->i2c_msg->len) {
+		solo_i2c_flush(solo_dev, 0);
+		return 0;
+	}
+
+	solo_dev->i2c_msg_ptr = 0;
+	solo_dev->i2c_msg++;
+	solo_dev->i2c_msg_num--;
+
+	if (solo_dev->i2c_msg_num == 0) {
+		solo_i2c_stop(solo_dev);
+		return 0;
+	}
+
+	if (!(solo_dev->i2c_msg->flags & I2C_M_NOSTART)) {
+		solo_i2c_start(solo_dev);
+	} else {
+		if (solo_dev->i2c_msg->flags & I2C_M_RD)
+			goto prepare_read;
+		else
+			solo_i2c_stop(solo_dev);
+	}
+
+	return 0;
+}
+
+static int solo_i2c_handle_write(struct solo_dev *solo_dev)
+{
+retry_write:
+	if (solo_dev->i2c_msg_ptr != solo_dev->i2c_msg->len) {
+		solo_reg_write(solo_dev, SOLO_IIC_TXD,
+			       solo_dev->i2c_msg->buf[solo_dev->i2c_msg_ptr]);
+		solo_dev->i2c_msg_ptr++;
+		solo_i2c_flush(solo_dev, 1);
+		return 0;
+	}
+
+	solo_dev->i2c_msg_ptr = 0;
+	solo_dev->i2c_msg++;
+	solo_dev->i2c_msg_num--;
+
+	if (solo_dev->i2c_msg_num == 0) {
+		solo_i2c_stop(solo_dev);
+		return 0;
+	}
+
+	if (!(solo_dev->i2c_msg->flags & I2C_M_NOSTART)) {
+		solo_i2c_start(solo_dev);
+	} else {
+		if (solo_dev->i2c_msg->flags & I2C_M_RD)
+			solo_i2c_stop(solo_dev);
+		else
+			goto retry_write;
+	}
+
+	return 0;
+}
+
+int solo_i2c_isr(struct solo_dev *solo_dev)
+{
+	u32 status = solo_reg_read(solo_dev, SOLO_IIC_CTRL);
+	int ret = -EINVAL;
+
+
+	if (CHK_FLAGS(status, SOLO_IIC_STATE_TRNS | SOLO_IIC_STATE_SIG_ERR)
+	    || solo_dev->i2c_id < 0) {
+		solo_i2c_stop(solo_dev);
+		return -ENXIO;
+	}
+
+	switch (solo_dev->i2c_state) {
+	case IIC_STATE_START:
+		if (solo_dev->i2c_msg->flags & I2C_M_RD) {
+			solo_dev->i2c_state = IIC_STATE_READ;
+			ret = solo_i2c_handle_read(solo_dev);
+			break;
+		}
+
+		solo_dev->i2c_state = IIC_STATE_WRITE;
+	case IIC_STATE_WRITE:
+		ret = solo_i2c_handle_write(solo_dev);
+		break;
+
+	case IIC_STATE_READ:
+		solo_dev->i2c_msg->buf[solo_dev->i2c_msg_ptr] =
+			solo_reg_read(solo_dev, SOLO_IIC_RXD);
+		solo_dev->i2c_msg_ptr++;
+
+		ret = solo_i2c_handle_read(solo_dev);
+		break;
+
+	default:
+		solo_i2c_stop(solo_dev);
+	}
+
+	return ret;
+}
+
+static int solo_i2c_master_xfer(struct i2c_adapter *adap,
+				struct i2c_msg msgs[], int num)
+{
+	struct solo_dev *solo_dev = adap->algo_data;
+	unsigned long timeout;
+	int ret;
+	int i;
+	DEFINE_WAIT(wait);
+
+	for (i = 0; i < SOLO_I2C_ADAPTERS; i++) {
+		if (&solo_dev->i2c_adap[i] == adap)
+			break;
+	}
+
+	if (i == SOLO_I2C_ADAPTERS)
+		return num; /* XXX Right return value for failure? */
+
+	mutex_lock(&solo_dev->i2c_mutex);
+	solo_dev->i2c_id = i;
+	solo_dev->i2c_msg = msgs;
+	solo_dev->i2c_msg_num = num;
+	solo_dev->i2c_msg_ptr = 0;
+
+	solo_reg_write(solo_dev, SOLO_IIC_CTRL, 0);
+	solo_irq_on(solo_dev, SOLO_IRQ_IIC);
+	solo_i2c_start(solo_dev);
+
+	timeout = HZ / 2;
+
+	for (;;) {
+		prepare_to_wait(&solo_dev->i2c_wait, &wait,
+				TASK_INTERRUPTIBLE);
+
+		if (solo_dev->i2c_state == IIC_STATE_STOP)
+			break;
+
+		timeout = schedule_timeout(timeout);
+		if (!timeout)
+			break;
+
+		if (signal_pending(current))
+			break;
+	}
+
+	finish_wait(&solo_dev->i2c_wait, &wait);
+	ret = num - solo_dev->i2c_msg_num;
+	solo_dev->i2c_state = IIC_STATE_IDLE;
+	solo_dev->i2c_id = -1;
+
+	mutex_unlock(&solo_dev->i2c_mutex);
+
+	return ret;
+}
+
+static u32 solo_i2c_functionality(struct i2c_adapter *adap)
+{
+	return I2C_FUNC_I2C;
+}
+
+static const struct i2c_algorithm solo_i2c_algo = {
+	.master_xfer	= solo_i2c_master_xfer,
+	.functionality	= solo_i2c_functionality,
+};
+
+int solo_i2c_init(struct solo_dev *solo_dev)
+{
+	int i;
+	int ret;
+
+	solo_reg_write(solo_dev, SOLO_IIC_CFG,
+		       SOLO_IIC_PRESCALE(8) | SOLO_IIC_ENABLE);
+
+	solo_dev->i2c_id = -1;
+	solo_dev->i2c_state = IIC_STATE_IDLE;
+	init_waitqueue_head(&solo_dev->i2c_wait);
+	mutex_init(&solo_dev->i2c_mutex);
+
+	for (i = 0; i < SOLO_I2C_ADAPTERS; i++) {
+		struct i2c_adapter *adap = &solo_dev->i2c_adap[i];
+
+		snprintf(adap->name, I2C_NAME_SIZE, "%s I2C %d",
+			 SOLO6X10_NAME, i);
+		adap->algo = &solo_i2c_algo;
+		adap->algo_data = solo_dev;
+		adap->retries = 1;
+		adap->dev.parent = &solo_dev->pdev->dev;
+
+		ret = i2c_add_adapter(adap);
+		if (ret) {
+			adap->algo_data = NULL;
+			break;
+		}
+	}
+
+	if (ret) {
+		for (i = 0; i < SOLO_I2C_ADAPTERS; i++) {
+			if (!solo_dev->i2c_adap[i].algo_data)
+				break;
+			i2c_del_adapter(&solo_dev->i2c_adap[i]);
+			solo_dev->i2c_adap[i].algo_data = NULL;
+		}
+		return ret;
+	}
+
+	return 0;
+}
+
+void solo_i2c_exit(struct solo_dev *solo_dev)
+{
+	int i;
+
+	for (i = 0; i < SOLO_I2C_ADAPTERS; i++) {
+		if (!solo_dev->i2c_adap[i].algo_data)
+			continue;
+		i2c_del_adapter(&solo_dev->i2c_adap[i]);
+		solo_dev->i2c_adap[i].algo_data = NULL;
+	}
+}
diff --git a/drivers/staging/media/solo6x10/solo6x10-jpeg.h b/drivers/staging/media/solo6x10/solo6x10-jpeg.h
index 50defec..c5218ce 100644
--- a/drivers/staging/media/solo6x10/solo6x10-jpeg.h
+++ b/drivers/staging/media/solo6x10/solo6x10-jpeg.h
@@ -1,6 +1,11 @@
 /*
- * Copyright (C) 2010 Bluecherry, LLC www.bluecherrydvr.com
- * Copyright (C) 2010 Ben Collins <bcollins@bluecherry.net>
+ * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
+ *
+ * Original author:
+ * Ben Collins <bcollins@ubuntu.com>
+ *
+ * Additional work by:
+ * John Brooks <john.brooks@bluecherry.net>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -20,7 +25,7 @@
 #ifndef __SOLO6X10_JPEG_H
 #define __SOLO6X10_JPEG_H
 
-static unsigned char jpeg_header[] = {
+static const unsigned char jpeg_header[] = {
 	0xff, 0xd8, 0xff, 0xfe, 0x00, 0x0d, 0x42, 0x6c,
 	0x75, 0x65, 0x63, 0x68, 0x65, 0x72, 0x72, 0x79,
 	0x20, 0xff, 0xdb, 0x00, 0x43, 0x00, 0x20, 0x16,
@@ -102,4 +107,87 @@ static unsigned char jpeg_header[] = {
 /* This is the byte marker for the start of SOF0: 0xffc0 marker */
 #define SOF0_START	575
 
+/* This is the byte marker for the start of the DQT */
+#define DQT_START	17
+#define DQT_LEN		138
+const unsigned char jpeg_dqt[4][DQT_LEN] = {
+	{
+		0xff, 0xdb, 0x00, 0x43, 0x00,
+		0x08, 0x06, 0x06, 0x07, 0x06, 0x05, 0x08, 0x07,
+		0x07, 0x07, 0x09, 0x09, 0x08, 0x0a, 0x0c, 0x14,
+		0x0d, 0x0c, 0x0b, 0x0b, 0x0c, 0x19, 0x12, 0x13,
+		0x0f, 0x14, 0x1d, 0x1a, 0x1f, 0x1e, 0x1d, 0x1a,
+		0x1c, 0x1c, 0x20, 0x24, 0x2e, 0x27, 0x20, 0x22,
+		0x2c, 0x23, 0x1c, 0x1c, 0x28, 0x37, 0x29, 0x2c,
+		0x30, 0x31, 0x34, 0x34, 0x34, 0x1f, 0x27, 0x39,
+		0x3d, 0x38, 0x32, 0x3c, 0x2e, 0x33, 0x34, 0x32,
+		0xff, 0xdb, 0x00, 0x43, 0x01,
+		0x09, 0x09, 0x09, 0x0c, 0x0b, 0x0c, 0x18, 0x0d,
+		0x0d, 0x18, 0x32, 0x21, 0x1c, 0x21, 0x32, 0x32,
+		0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32,
+		0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32,
+		0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32,
+		0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32,
+		0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32,
+		0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32
+	}, {
+		0xff, 0xdb, 0x00, 0x43, 0x00,
+		0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e,
+		0x0d, 0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28,
+		0x1a, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25,
+		0x1d, 0x28, 0x3a, 0x33, 0x3d, 0x3c, 0x39, 0x33,
+		0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40, 0x44,
+		0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51, 0x57,
+		0x5f, 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71,
+		0x79, 0x70, 0x64, 0x78, 0x5c, 0x65, 0x67, 0x63,
+		0xff, 0xdb, 0x00, 0x43, 0x01,
+		0x11, 0x12, 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a,
+		0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63,
+		0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+		0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+		0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+		0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+		0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+		0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63
+	}, {
+		0xff, 0xdb, 0x00, 0x43, 0x00,
+		0x20, 0x16, 0x18, 0x1c, 0x18, 0x14, 0x20, 0x1c,
+		0x1a, 0x1c, 0x24, 0x22, 0x20, 0x26, 0x30, 0x50,
+		0x34, 0x30, 0x2c, 0x2c, 0x30, 0x62, 0x46, 0x4a,
+		0x3a, 0x50, 0x74, 0x66, 0x7a, 0x78, 0x72, 0x66,
+		0x70, 0x6e, 0x80, 0x90, 0xb8, 0x9c, 0x80, 0x88,
+		0xae, 0x8a, 0x6e, 0x70, 0xa0, 0xda, 0xa2, 0xae,
+		0xbe, 0xc4, 0xce, 0xd0, 0xce, 0x7c, 0x9a, 0xe2,
+		0xf2, 0xe0, 0xc8, 0xf0, 0xb8, 0xca, 0xce, 0xc6,
+		0xff, 0xdb, 0x00, 0x43, 0x01,
+		0x22, 0x24, 0x24, 0x30, 0x2a, 0x30, 0x5e, 0x34,
+		0x34, 0x5e, 0xc6, 0x84, 0x70, 0x84, 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,
+		0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+		0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+		0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6
+	}, {
+		0xff, 0xdb, 0x00, 0x43, 0x00,
+		0x30, 0x21, 0x24, 0x2a, 0x24, 0x1e, 0x30, 0x2a,
+		0x27, 0x2a, 0x36, 0x33, 0x30, 0x39, 0x48, 0x78,
+		0x4e, 0x48, 0x42, 0x42, 0x48, 0x93, 0x69, 0x6f,
+		0x57, 0x78, 0xae, 0x99, 0xb7, 0xb4, 0xab, 0x99,
+		0xa8, 0xa5, 0xc0, 0xd8, 0xff, 0xea, 0xc0, 0xcc,
+		0xff, 0xcf, 0xa5, 0xa8, 0xf0, 0xff, 0xf3, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xba, 0xe7, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xdb, 0x00, 0x43, 0x01,
+		0x33, 0x36, 0x36, 0x48, 0x3f, 0x48, 0x8d, 0x4e,
+		0x4e, 0x8d, 0xff, 0xc6, 0xa8, 0xc6, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+	}
+};
+
 #endif /* __SOLO6X10_JPEG_H */
diff --git a/drivers/staging/media/solo6x10/solo6x10-offsets.h b/drivers/staging/media/solo6x10/solo6x10-offsets.h
new file mode 100644
index 0000000..f005dca
--- /dev/null
+++ b/drivers/staging/media/solo6x10/solo6x10-offsets.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
+ *
+ * Original author:
+ * Ben Collins <bcollins@ubuntu.com>
+ *
+ * Additional work by:
+ * John Brooks <john.brooks@bluecherry.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You 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 __SOLO6X10_OFFSETS_H
+#define __SOLO6X10_OFFSETS_H
+
+#define SOLO_DISP_EXT_ADDR			0x00000000
+#define SOLO_DISP_EXT_SIZE			0x00480000
+
+#define SOLO_EOSD_EXT_ADDR \
+	(SOLO_DISP_EXT_ADDR + SOLO_DISP_EXT_SIZE)
+#define SOLO_EOSD_EXT_SIZE(__solo) \
+	(__solo->type == SOLO_DEV_6010 ? 0x10000 : 0x20000)
+#define SOLO_EOSD_EXT_SIZE_MAX			0x20000
+#define SOLO_EOSD_EXT_AREA(__solo) \
+	(SOLO_EOSD_EXT_SIZE(__solo) * 32)
+
+#define SOLO_MOTION_EXT_ADDR(__solo) \
+	(SOLO_EOSD_EXT_ADDR + SOLO_EOSD_EXT_AREA(__solo))
+#define SOLO_MOTION_EXT_SIZE			0x00080000
+
+#define SOLO_G723_EXT_ADDR(__solo) \
+	(SOLO_MOTION_EXT_ADDR(__solo) + SOLO_MOTION_EXT_SIZE)
+#define SOLO_G723_EXT_SIZE			0x00010000
+
+#define SOLO_CAP_EXT_ADDR(__solo) \
+	(SOLO_G723_EXT_ADDR(__solo) + SOLO_G723_EXT_SIZE)
+
+/* 18 is the maximum number of pages required for PAL@D1, the largest frame
+ * possible */
+#define SOLO_CAP_PAGE_SIZE			(18 << 16)
+
+/* Always allow the encoder enough for 16 channels, even if we have less. The
+ * exception is if we have card with only 32Megs of memory. */
+#define SOLO_CAP_EXT_SIZE(__solo) \
+	((((__solo->sdram_size <= (32 << 20)) ? 4 : 16) + 1)	\
+	 * SOLO_CAP_PAGE_SIZE)
+
+#define SOLO_EREF_EXT_ADDR(__solo) \
+	(SOLO_CAP_EXT_ADDR(__solo) + SOLO_CAP_EXT_SIZE(__solo))
+#define SOLO_EREF_EXT_SIZE			0x00140000
+#define SOLO_EREF_EXT_AREA(__solo) \
+	(SOLO_EREF_EXT_SIZE * __solo->nr_chans * 2)
+
+#define __SOLO_JPEG_MIN_SIZE(__solo)		(__solo->nr_chans * 0x00080000)
+
+#define SOLO_MP4E_EXT_ADDR(__solo) \
+	(SOLO_EREF_EXT_ADDR(__solo) + SOLO_EREF_EXT_AREA(__solo))
+#define SOLO_MP4E_EXT_SIZE(__solo) \
+	max((__solo->nr_chans * 0x00080000),				\
+	    min(((__solo->sdram_size - SOLO_MP4E_EXT_ADDR(__solo)) -	\
+		 __SOLO_JPEG_MIN_SIZE(__solo)), 0x00ff0000))
+
+#define __SOLO_JPEG_MIN_SIZE(__solo)		(__solo->nr_chans * 0x00080000)
+#define SOLO_JPEG_EXT_ADDR(__solo) \
+		(SOLO_MP4E_EXT_ADDR(__solo) + SOLO_MP4E_EXT_SIZE(__solo))
+#define SOLO_JPEG_EXT_SIZE(__solo) \
+	max(__SOLO_JPEG_MIN_SIZE(__solo),				\
+	    min((__solo->sdram_size - SOLO_JPEG_EXT_ADDR(__solo)), 0x00ff0000))
+
+#define SOLO_SDRAM_END(__solo) \
+	(SOLO_JPEG_EXT_ADDR(__solo) + SOLO_JPEG_EXT_SIZE(__solo))
+
+#endif /* __SOLO6X10_OFFSETS_H */
diff --git a/drivers/staging/media/solo6x10/solo6x10-p2m.c b/drivers/staging/media/solo6x10/solo6x10-p2m.c
new file mode 100644
index 0000000..3335941
--- /dev/null
+++ b/drivers/staging/media/solo6x10/solo6x10-p2m.c
@@ -0,0 +1,333 @@
+/*
+ * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
+ *
+ * Original author:
+ * Ben Collins <bcollins@ubuntu.com>
+ *
+ * Additional work by:
+ * John Brooks <john.brooks@bluecherry.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You 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/slab.h>
+
+#include "solo6x10.h"
+
+static int multi_p2m;
+module_param(multi_p2m, uint, 0644);
+MODULE_PARM_DESC(multi_p2m,
+		 "Use multiple P2M DMA channels (default: no, 6010-only)");
+
+static int desc_mode;
+module_param(desc_mode, uint, 0644);
+MODULE_PARM_DESC(desc_mode,
+		 "Allow use of descriptor mode DMA (default: no, 6010-only)");
+
+int solo_p2m_dma(struct solo_dev *solo_dev, int wr,
+		 void *sys_addr, u32 ext_addr, u32 size,
+		 int repeat, u32 ext_size)
+{
+	dma_addr_t dma_addr;
+	int ret;
+
+	if (WARN_ON_ONCE((unsigned long)sys_addr & 0x03))
+		return -EINVAL;
+	if (WARN_ON_ONCE(!size))
+		return -EINVAL;
+
+	dma_addr = pci_map_single(solo_dev->pdev, sys_addr, size,
+				  wr ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
+	if (pci_dma_mapping_error(solo_dev->pdev, dma_addr))
+		return -ENOMEM;
+
+	ret = solo_p2m_dma_t(solo_dev, wr, dma_addr, ext_addr, size,
+			     repeat, ext_size);
+
+	pci_unmap_single(solo_dev->pdev, dma_addr, size,
+			 wr ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
+
+	return ret;
+}
+
+/* Mutex must be held for p2m_id before calling this!! */
+int solo_p2m_dma_desc(struct solo_dev *solo_dev,
+		      struct solo_p2m_desc *desc, dma_addr_t desc_dma,
+		      int desc_cnt)
+{
+	struct solo_p2m_dev *p2m_dev;
+	unsigned int timeout;
+	unsigned int config = 0;
+	int ret = 0;
+	int p2m_id = 0;
+
+	/* Get next ID. According to Softlogic, 6110 has problems on !=0 P2M */
+	if (solo_dev->type != SOLO_DEV_6110 && multi_p2m) {
+		p2m_id = atomic_inc_return(&solo_dev->p2m_count) % SOLO_NR_P2M;
+		if (p2m_id < 0)
+			p2m_id = -p2m_id;
+	}
+
+	p2m_dev = &solo_dev->p2m_dev[p2m_id];
+
+	if (mutex_lock_interruptible(&p2m_dev->mutex))
+		return -EINTR;
+
+	INIT_COMPLETION(p2m_dev->completion);
+	p2m_dev->error = 0;
+
+	if (desc_cnt > 1 && solo_dev->type != SOLO_DEV_6110 && desc_mode) {
+		/* For 6010 with more than one desc, we can do a one-shot */
+		p2m_dev->desc_count = p2m_dev->desc_idx = 0;
+		config = solo_reg_read(solo_dev, SOLO_P2M_CONFIG(p2m_id));
+
+		solo_reg_write(solo_dev, SOLO_P2M_DES_ADR(p2m_id), desc_dma);
+		solo_reg_write(solo_dev, SOLO_P2M_DESC_ID(p2m_id), desc_cnt);
+		solo_reg_write(solo_dev, SOLO_P2M_CONFIG(p2m_id), config |
+			       SOLO_P2M_DESC_MODE);
+	} else {
+		/* For single descriptors and 6110, we need to run each desc */
+		p2m_dev->desc_count = desc_cnt;
+		p2m_dev->desc_idx = 1;
+		p2m_dev->descs = desc;
+
+		solo_reg_write(solo_dev, SOLO_P2M_TAR_ADR(p2m_id),
+			       desc[1].dma_addr);
+		solo_reg_write(solo_dev, SOLO_P2M_EXT_ADR(p2m_id),
+			       desc[1].ext_addr);
+		solo_reg_write(solo_dev, SOLO_P2M_EXT_CFG(p2m_id),
+			       desc[1].cfg);
+		solo_reg_write(solo_dev, SOLO_P2M_CONTROL(p2m_id),
+			       desc[1].ctrl);
+	}
+
+	timeout = wait_for_completion_timeout(&p2m_dev->completion,
+					      solo_dev->p2m_jiffies);
+
+	if (WARN_ON_ONCE(p2m_dev->error))
+		ret = -EIO;
+	else if (timeout == 0) {
+		solo_dev->p2m_timeouts++;
+		ret = -EAGAIN;
+	}
+
+	solo_reg_write(solo_dev, SOLO_P2M_CONTROL(p2m_id), 0);
+
+	/* Don't write here for the no_desc_mode case, because config is 0.
+	 * We can't test no_desc_mode again, it might race. */
+	if (desc_cnt > 1 && solo_dev->type != SOLO_DEV_6110 && config)
+		solo_reg_write(solo_dev, SOLO_P2M_CONFIG(p2m_id), config);
+
+	mutex_unlock(&p2m_dev->mutex);
+
+	return ret;
+}
+
+void solo_p2m_fill_desc(struct solo_p2m_desc *desc, int wr,
+			dma_addr_t dma_addr, u32 ext_addr, u32 size,
+			int repeat, u32 ext_size)
+{
+	WARN_ON_ONCE(dma_addr & 0x03);
+	WARN_ON_ONCE(!size);
+
+	desc->cfg = SOLO_P2M_COPY_SIZE(size >> 2);
+	desc->ctrl = SOLO_P2M_BURST_SIZE(SOLO_P2M_BURST_256) |
+		(wr ? SOLO_P2M_WRITE : 0) | SOLO_P2M_TRANS_ON;
+
+	if (repeat) {
+		desc->cfg |= SOLO_P2M_EXT_INC(ext_size >> 2);
+		desc->ctrl |=  SOLO_P2M_PCI_INC(size >> 2) |
+			 SOLO_P2M_REPEAT(repeat);
+	}
+
+	desc->dma_addr = dma_addr;
+	desc->ext_addr = ext_addr;
+}
+
+int solo_p2m_dma_t(struct solo_dev *solo_dev, int wr,
+		   dma_addr_t dma_addr, u32 ext_addr, u32 size,
+		   int repeat, u32 ext_size)
+{
+	struct solo_p2m_desc desc[2];
+
+	solo_p2m_fill_desc(&desc[1], wr, dma_addr, ext_addr, size, repeat,
+			   ext_size);
+
+	/* No need for desc_dma since we know it is a single-shot */
+	return solo_p2m_dma_desc(solo_dev, desc, 0, 1);
+}
+
+void solo_p2m_isr(struct solo_dev *solo_dev, int id)
+{
+	struct solo_p2m_dev *p2m_dev = &solo_dev->p2m_dev[id];
+	struct solo_p2m_desc *desc;
+
+	if (p2m_dev->desc_count <= p2m_dev->desc_idx) {
+		complete(&p2m_dev->completion);
+		return;
+	}
+
+	/* Setup next descriptor */
+	p2m_dev->desc_idx++;
+	desc = &p2m_dev->descs[p2m_dev->desc_idx];
+
+	solo_reg_write(solo_dev, SOLO_P2M_CONTROL(id), 0);
+	solo_reg_write(solo_dev, SOLO_P2M_TAR_ADR(id), desc->dma_addr);
+	solo_reg_write(solo_dev, SOLO_P2M_EXT_ADR(id), desc->ext_addr);
+	solo_reg_write(solo_dev, SOLO_P2M_EXT_CFG(id), desc->cfg);
+	solo_reg_write(solo_dev, SOLO_P2M_CONTROL(id), desc->ctrl);
+}
+
+void solo_p2m_error_isr(struct solo_dev *solo_dev)
+{
+	unsigned int err = solo_reg_read(solo_dev, SOLO_PCI_ERR);
+	struct solo_p2m_dev *p2m_dev;
+	int i;
+
+	if (!(err & (SOLO_PCI_ERR_P2M | SOLO_PCI_ERR_P2M_DESC)))
+		return;
+
+	for (i = 0; i < SOLO_NR_P2M; i++) {
+		p2m_dev = &solo_dev->p2m_dev[i];
+		p2m_dev->error = 1;
+		solo_reg_write(solo_dev, SOLO_P2M_CONTROL(i), 0);
+		complete(&p2m_dev->completion);
+	}
+}
+
+void solo_p2m_exit(struct solo_dev *solo_dev)
+{
+	int i;
+
+	for (i = 0; i < SOLO_NR_P2M; i++)
+		solo_irq_off(solo_dev, SOLO_IRQ_P2M(i));
+}
+
+static int solo_p2m_test(struct solo_dev *solo_dev, int base, int size)
+{
+	u32 *wr_buf;
+	u32 *rd_buf;
+	int i;
+	int ret = -EIO;
+	int order = get_order(size);
+
+	wr_buf = (u32 *)__get_free_pages(GFP_KERNEL, order);
+	if (wr_buf == NULL)
+		return -1;
+
+	rd_buf = (u32 *)__get_free_pages(GFP_KERNEL, order);
+	if (rd_buf == NULL) {
+		free_pages((unsigned long)wr_buf, order);
+		return -1;
+	}
+
+	for (i = 0; i < (size >> 3); i++)
+		*(wr_buf + i) = (i << 16) | (i + 1);
+
+	for (i = (size >> 3); i < (size >> 2); i++)
+		*(wr_buf + i) = ~((i << 16) | (i + 1));
+
+	memset(rd_buf, 0x55, size);
+
+	if (solo_p2m_dma(solo_dev, 1, wr_buf, base, size, 0, 0))
+		goto test_fail;
+
+	if (solo_p2m_dma(solo_dev, 0, rd_buf, base, size, 0, 0))
+		goto test_fail;
+
+	for (i = 0; i < (size >> 2); i++) {
+		if (*(wr_buf + i) != *(rd_buf + i))
+			goto test_fail;
+	}
+
+	ret = 0;
+
+test_fail:
+	free_pages((unsigned long)wr_buf, order);
+	free_pages((unsigned long)rd_buf, order);
+
+	return ret;
+}
+
+int solo_p2m_init(struct solo_dev *solo_dev)
+{
+	struct solo_p2m_dev *p2m_dev;
+	int i;
+
+	for (i = 0; i < SOLO_NR_P2M; i++) {
+		p2m_dev = &solo_dev->p2m_dev[i];
+
+		mutex_init(&p2m_dev->mutex);
+		init_completion(&p2m_dev->completion);
+
+		solo_reg_write(solo_dev, SOLO_P2M_CONTROL(i), 0);
+		solo_reg_write(solo_dev, SOLO_P2M_CONFIG(i),
+			       SOLO_P2M_CSC_16BIT_565 |
+			       SOLO_P2M_DESC_INTR_OPT |
+			       SOLO_P2M_DMA_INTERVAL(0) |
+			       SOLO_P2M_PCI_MASTER_MODE);
+		solo_irq_on(solo_dev, SOLO_IRQ_P2M(i));
+	}
+
+	/* Find correct SDRAM size */
+	for (solo_dev->sdram_size = 0, i = 2; i >= 0; i--) {
+		solo_reg_write(solo_dev, SOLO_DMA_CTRL,
+			       SOLO_DMA_CTRL_REFRESH_CYCLE(1) |
+			       SOLO_DMA_CTRL_SDRAM_SIZE(i) |
+			       SOLO_DMA_CTRL_SDRAM_CLK_INVERT |
+			       SOLO_DMA_CTRL_READ_CLK_SELECT |
+			       SOLO_DMA_CTRL_LATENCY(1));
+
+		solo_reg_write(solo_dev, SOLO_SYS_CFG, solo_dev->sys_config |
+			       SOLO_SYS_CFG_RESET);
+		solo_reg_write(solo_dev, SOLO_SYS_CFG, solo_dev->sys_config);
+
+		switch (i) {
+		case 2:
+			if (solo_p2m_test(solo_dev, 0x07ff0000, 0x00010000) ||
+			    solo_p2m_test(solo_dev, 0x05ff0000, 0x00010000))
+				continue;
+			break;
+
+		case 1:
+			if (solo_p2m_test(solo_dev, 0x03ff0000, 0x00010000))
+				continue;
+			break;
+
+		default:
+			if (solo_p2m_test(solo_dev, 0x01ff0000, 0x00010000))
+				continue;
+		}
+
+		solo_dev->sdram_size = (32 << 20) << i;
+		break;
+	}
+
+	if (!solo_dev->sdram_size) {
+		dev_err(&solo_dev->pdev->dev, "Error detecting SDRAM size\n");
+		return -EIO;
+	}
+
+	if (SOLO_SDRAM_END(solo_dev) > solo_dev->sdram_size) {
+		dev_err(&solo_dev->pdev->dev,
+			"SDRAM is not large enough (%u < %u)\n",
+			solo_dev->sdram_size, SOLO_SDRAM_END(solo_dev));
+		return -EIO;
+	}
+
+	return 0;
+}
diff --git a/drivers/staging/media/solo6x10/solo6x10-regs.h b/drivers/staging/media/solo6x10/solo6x10-regs.h
new file mode 100644
index 0000000..428f6c9
--- /dev/null
+++ b/drivers/staging/media/solo6x10/solo6x10-regs.h
@@ -0,0 +1,639 @@
+/*
+ * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
+ *
+ * Original author:
+ * Ben Collins <bcollins@ubuntu.com>
+ *
+ * Additional work by:
+ * John Brooks <john.brooks@bluecherry.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You 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 __SOLO6X10_REGISTERS_H
+#define __SOLO6X10_REGISTERS_H
+
+#include "solo6x10-offsets.h"
+
+/* Global 6010 system configuration */
+#define SOLO_SYS_CFG				0x0000
+#define   SOLO_SYS_CFG_FOUT_EN			0x00000001
+#define   SOLO_SYS_CFG_PLL_BYPASS		0x00000002
+#define   SOLO_SYS_CFG_PLL_PWDN			0x00000004
+#define   SOLO_SYS_CFG_OUTDIV(__n)		(((__n) & 0x003) << 3)
+#define   SOLO_SYS_CFG_FEEDBACKDIV(__n)		(((__n) & 0x1ff) << 5)
+#define   SOLO_SYS_CFG_INPUTDIV(__n)		(((__n) & 0x01f) << 14)
+#define   SOLO_SYS_CFG_CLOCK_DIV		0x00080000
+#define   SOLO_SYS_CFG_NCLK_DELAY(__n)		(((__n) & 0x003) << 24)
+#define   SOLO_SYS_CFG_PCLK_DELAY(__n)		(((__n) & 0x00f) << 26)
+#define   SOLO_SYS_CFG_SDRAM64BIT		0x40000000
+#define   SOLO_SYS_CFG_RESET			0x80000000
+
+#define	SOLO_DMA_CTRL				0x0004
+#define	  SOLO_DMA_CTRL_REFRESH_CYCLE(n)	((n)<<8)
+/* 0=16/32MB, 1=32/64MB, 2=64/128MB, 3=128/256MB */
+#define	  SOLO_DMA_CTRL_SDRAM_SIZE(n)		((n)<<6)
+#define	  SOLO_DMA_CTRL_SDRAM_CLK_INVERT	(1<<5)
+#define	  SOLO_DMA_CTRL_STROBE_SELECT		(1<<4)
+#define	  SOLO_DMA_CTRL_READ_DATA_SELECT	(1<<3)
+#define	  SOLO_DMA_CTRL_READ_CLK_SELECT		(1<<2)
+#define	  SOLO_DMA_CTRL_LATENCY(n)		((n)<<0)
+
+/* Some things we set in this are undocumented. Why Softlogic?!?! */
+#define SOLO_DMA_CTRL1				0x0008
+
+#define SOLO_SYS_VCLK				0x000C
+#define	  SOLO_VCLK_INVERT			(1<<22)
+/* 0=sys_clk/4, 1=sys_clk/2, 2=clk_in/2 of system input */
+#define	  SOLO_VCLK_SELECT(n)			((n)<<20)
+#define	  SOLO_VCLK_VIN1415_DELAY(n)		((n)<<14)
+#define	  SOLO_VCLK_VIN1213_DELAY(n)		((n)<<12)
+#define	  SOLO_VCLK_VIN1011_DELAY(n)		((n)<<10)
+#define	  SOLO_VCLK_VIN0809_DELAY(n)		((n)<<8)
+#define	  SOLO_VCLK_VIN0607_DELAY(n)		((n)<<6)
+#define	  SOLO_VCLK_VIN0405_DELAY(n)		((n)<<4)
+#define	  SOLO_VCLK_VIN0203_DELAY(n)		((n)<<2)
+#define	  SOLO_VCLK_VIN0001_DELAY(n)		((n)<<0)
+
+#define SOLO_IRQ_STAT				0x0010
+#define SOLO_IRQ_MASK				0x0014
+#define	  SOLO_IRQ_P2M(n)			(1<<((n)+17))
+#define	  SOLO_IRQ_GPIO				(1<<16)
+#define	  SOLO_IRQ_VIDEO_LOSS			(1<<15)
+#define	  SOLO_IRQ_VIDEO_IN			(1<<14)
+#define	  SOLO_IRQ_MOTION			(1<<13)
+#define	  SOLO_IRQ_ATA_CMD			(1<<12)
+#define	  SOLO_IRQ_ATA_DIR			(1<<11)
+#define	  SOLO_IRQ_PCI_ERR			(1<<10)
+#define	  SOLO_IRQ_PS2_1			(1<<9)
+#define	  SOLO_IRQ_PS2_0			(1<<8)
+#define	  SOLO_IRQ_SPI				(1<<7)
+#define	  SOLO_IRQ_IIC				(1<<6)
+#define	  SOLO_IRQ_UART(n)			(1<<((n) + 4))
+#define	  SOLO_IRQ_G723				(1<<3)
+#define	  SOLO_IRQ_DECODER			(1<<1)
+#define	  SOLO_IRQ_ENCODER			(1<<0)
+
+#define SOLO_CHIP_OPTION			0x001C
+#define   SOLO_CHIP_ID_MASK			0x00000007
+
+#define SOLO_PLL_CONFIG				0x0020 /* 6110 Only */
+
+#define SOLO_EEPROM_CTRL			0x0060
+#define	  SOLO_EEPROM_ACCESS_EN			(1<<7)
+#define	  SOLO_EEPROM_CS			(1<<3)
+#define	  SOLO_EEPROM_CLK			(1<<2)
+#define	  SOLO_EEPROM_DO			(1<<1)
+#define	  SOLO_EEPROM_DI			(1<<0)
+#define	  SOLO_EEPROM_ENABLE (SOLO_EEPROM_ACCESS_EN | SOLO_EEPROM_CS)
+
+#define SOLO_PCI_ERR				0x0070
+#define   SOLO_PCI_ERR_FATAL			0x00000001
+#define   SOLO_PCI_ERR_PARITY			0x00000002
+#define   SOLO_PCI_ERR_TARGET			0x00000004
+#define   SOLO_PCI_ERR_TIMEOUT			0x00000008
+#define   SOLO_PCI_ERR_P2M			0x00000010
+#define   SOLO_PCI_ERR_ATA			0x00000020
+#define   SOLO_PCI_ERR_P2M_DESC			0x00000040
+#define   SOLO_PCI_ERR_FSM0(__s)		(((__s) >> 16) & 0x0f)
+#define   SOLO_PCI_ERR_FSM1(__s)		(((__s) >> 20) & 0x0f)
+#define   SOLO_PCI_ERR_FSM2(__s)		(((__s) >> 24) & 0x1f)
+
+#define SOLO_P2M_BASE				0x0080
+
+#define SOLO_P2M_CONFIG(n)			(0x0080 + ((n)*0x20))
+#define	  SOLO_P2M_DMA_INTERVAL(n)		((n)<<6)/* N*32 clocks */
+#define	  SOLO_P2M_CSC_BYTE_REORDER		(1<<5)	/* BGR -> RGB */
+/* 0:r=[14:10] g=[9:5] b=[4:0], 1:r=[15:11] g=[10:5] b=[4:0] */
+#define	  SOLO_P2M_CSC_16BIT_565		(1<<4)
+#define	  SOLO_P2M_UV_SWAP			(1<<3)
+#define	  SOLO_P2M_PCI_MASTER_MODE		(1<<2)
+#define	  SOLO_P2M_DESC_INTR_OPT		(1<<1)	/* 1:Empty, 0:Each */
+#define	  SOLO_P2M_DESC_MODE			(1<<0)
+
+#define SOLO_P2M_DES_ADR(n)			(0x0084 + ((n)*0x20))
+
+#define SOLO_P2M_DESC_ID(n)			(0x0088 + ((n)*0x20))
+#define	  SOLO_P2M_UPDATE_ID(n)			((n)<<0)
+
+#define SOLO_P2M_STATUS(n)			(0x008C + ((n)*0x20))
+#define	  SOLO_P2M_COMMAND_DONE			(1<<8)
+#define	  SOLO_P2M_CURRENT_ID(stat)		(0xff & (stat))
+
+#define SOLO_P2M_CONTROL(n)			(0x0090 + ((n)*0x20))
+#define	  SOLO_P2M_PCI_INC(n)			((n)<<20)
+#define	  SOLO_P2M_REPEAT(n)			((n)<<10)
+/* 0:512, 1:256, 2:128, 3:64, 4:32, 5:128(2page) */
+#define	  SOLO_P2M_BURST_SIZE(n)		((n)<<7)
+#define	    SOLO_P2M_BURST_512			0
+#define	    SOLO_P2M_BURST_256			1
+#define	    SOLO_P2M_BURST_128			2
+#define	    SOLO_P2M_BURST_64			3
+#define	    SOLO_P2M_BURST_32			4
+#define	  SOLO_P2M_CSC_16BIT			(1<<6)	/* 0:24bit, 1:16bit */
+/* 0:Y[0]<-0(OFF), 1:Y[0]<-1(ON), 2:Y[0]<-G[0], 3:Y[0]<-Bit[15] */
+#define	  SOLO_P2M_ALPHA_MODE(n)		((n)<<4)
+#define	  SOLO_P2M_CSC_ON			(1<<3)
+#define	  SOLO_P2M_INTERRUPT_REQ		(1<<2)
+#define	  SOLO_P2M_WRITE			(1<<1)
+#define	  SOLO_P2M_TRANS_ON			(1<<0)
+
+#define SOLO_P2M_EXT_CFG(n)			(0x0094 + ((n)*0x20))
+#define	  SOLO_P2M_EXT_INC(n)			((n)<<20)
+#define	  SOLO_P2M_COPY_SIZE(n)			((n)<<0)
+
+#define SOLO_P2M_TAR_ADR(n)			(0x0098 + ((n)*0x20))
+
+#define SOLO_P2M_EXT_ADR(n)			(0x009C + ((n)*0x20))
+
+#define SOLO_P2M_BUFFER(i)			(0x2000 + ((i)*4))
+
+#define SOLO_VI_CH_SWITCH_0			0x0100
+#define SOLO_VI_CH_SWITCH_1			0x0104
+#define SOLO_VI_CH_SWITCH_2			0x0108
+
+#define	SOLO_VI_CH_ENA				0x010C
+#define	SOLO_VI_CH_FORMAT			0x0110
+#define	  SOLO_VI_FD_SEL_MASK(n)		((n)<<16)
+#define	  SOLO_VI_PROG_MASK(n)			((n)<<0)
+
+#define SOLO_VI_FMT_CFG				0x0114
+#define	  SOLO_VI_FMT_CHECK_VCOUNT		(1<<31)
+#define	  SOLO_VI_FMT_CHECK_HCOUNT		(1<<30)
+#define   SOLO_VI_FMT_TEST_SIGNAL		(1<<28)
+
+#define	SOLO_VI_PAGE_SW				0x0118
+#define	  SOLO_FI_INV_DISP_LIVE(n)		((n)<<8)
+#define	  SOLO_FI_INV_DISP_OUT(n)		((n)<<7)
+#define	  SOLO_DISP_SYNC_FI(n)			((n)<<6)
+#define	  SOLO_PIP_PAGE_ADD(n)			((n)<<3)
+#define	  SOLO_NORMAL_PAGE_ADD(n)		((n)<<0)
+
+#define	SOLO_VI_ACT_I_P				0x011C
+#define	SOLO_VI_ACT_I_S				0x0120
+#define	SOLO_VI_ACT_P				0x0124
+#define	  SOLO_VI_FI_INVERT			(1<<31)
+#define	  SOLO_VI_H_START(n)			((n)<<21)
+#define	  SOLO_VI_V_START(n)			((n)<<11)
+#define	  SOLO_VI_V_STOP(n)			((n)<<0)
+
+#define SOLO_VI_STATUS0				0x0128
+#define   SOLO_VI_STATUS0_PAGE(__n)		((__n) & 0x07)
+#define SOLO_VI_STATUS1				0x012C
+
+/* XXX: Might be better off in kernel level disp.h */
+#define DISP_PAGE(stat)				((stat) & 0x07)
+
+#define SOLO_VI_PB_CONFIG			0x0130
+#define	  SOLO_VI_PB_USER_MODE			(1<<1)
+#define	  SOLO_VI_PB_PAL			(1<<0)
+#define SOLO_VI_PB_RANGE_HV			0x0134
+#define	  SOLO_VI_PB_HSIZE(h)			((h)<<12)
+#define	  SOLO_VI_PB_VSIZE(v)			((v)<<0)
+#define SOLO_VI_PB_ACT_H			0x0138
+#define	  SOLO_VI_PB_HSTART(n)			((n)<<12)
+#define	  SOLO_VI_PB_HSTOP(n)			((n)<<0)
+#define SOLO_VI_PB_ACT_V			0x013C
+#define	  SOLO_VI_PB_VSTART(n)			((n)<<12)
+#define	  SOLO_VI_PB_VSTOP(n)			((n)<<0)
+
+#define	SOLO_VI_MOSAIC(ch)			(0x0140 + ((ch)*4))
+#define	  SOLO_VI_MOSAIC_SX(x)			((x)<<24)
+#define	  SOLO_VI_MOSAIC_EX(x)			((x)<<16)
+#define	  SOLO_VI_MOSAIC_SY(x)			((x)<<8)
+#define	  SOLO_VI_MOSAIC_EY(x)			((x)<<0)
+
+#define	SOLO_VI_WIN_CTRL0(ch)			(0x0180 + ((ch)*4))
+#define	SOLO_VI_WIN_CTRL1(ch)			(0x01C0 + ((ch)*4))
+
+#define	  SOLO_VI_WIN_CHANNEL(n)		((n)<<28)
+
+#define	  SOLO_VI_WIN_PIP(n)			((n)<<27)
+#define	  SOLO_VI_WIN_SCALE(n)			((n)<<24)
+
+#define	  SOLO_VI_WIN_SX(x)			((x)<<12)
+#define	  SOLO_VI_WIN_EX(x)			((x)<<0)
+
+#define	  SOLO_VI_WIN_SY(x)			((x)<<12)
+#define	  SOLO_VI_WIN_EY(x)			((x)<<0)
+
+#define	SOLO_VI_WIN_ON(ch)			(0x0200 + ((ch)*4))
+
+#define SOLO_VI_WIN_SW				0x0240
+#define SOLO_VI_WIN_LIVE_AUTO_MUTE		0x0244
+
+#define	SOLO_VI_MOT_ADR				0x0260
+#define	  SOLO_VI_MOTION_EN(mask)		((mask)<<16)
+#define	SOLO_VI_MOT_CTRL			0x0264
+#define	  SOLO_VI_MOTION_FRAME_COUNT(n)		((n)<<24)
+#define	  SOLO_VI_MOTION_SAMPLE_LENGTH(n)	((n)<<16)
+#define	  SOLO_VI_MOTION_INTR_START_STOP	(1<<15)
+#define	  SOLO_VI_MOTION_FREEZE_DATA		(1<<14)
+#define	  SOLO_VI_MOTION_SAMPLE_COUNT(n)	((n)<<0)
+#define SOLO_VI_MOT_CLEAR			0x0268
+#define SOLO_VI_MOT_STATUS			0x026C
+#define	  SOLO_VI_MOTION_CNT(n)			((n)<<0)
+#define SOLO_VI_MOTION_BORDER			0x0270
+#define SOLO_VI_MOTION_BAR			0x0274
+#define	  SOLO_VI_MOTION_Y_SET			(1<<29)
+#define	  SOLO_VI_MOTION_Y_ADD			(1<<28)
+#define	  SOLO_VI_MOTION_CB_SET			(1<<27)
+#define	  SOLO_VI_MOTION_CB_ADD			(1<<26)
+#define	  SOLO_VI_MOTION_CR_SET			(1<<25)
+#define	  SOLO_VI_MOTION_CR_ADD			(1<<24)
+#define	  SOLO_VI_MOTION_Y_VALUE(v)		((v)<<16)
+#define	  SOLO_VI_MOTION_CB_VALUE(v)		((v)<<8)
+#define	  SOLO_VI_MOTION_CR_VALUE(v)		((v)<<0)
+
+#define	SOLO_VO_FMT_ENC				0x0300
+#define	  SOLO_VO_SCAN_MODE_PROGRESSIVE		(1<<31)
+#define	  SOLO_VO_FMT_TYPE_PAL			(1<<30)
+#define   SOLO_VO_FMT_TYPE_NTSC			0
+#define	  SOLO_VO_USER_SET			(1<<29)
+
+#define	  SOLO_VO_FI_CHANGE			(1<<20)
+#define	  SOLO_VO_USER_COLOR_SET_VSYNC		(1<<19)
+#define	  SOLO_VO_USER_COLOR_SET_HSYNC		(1<<18)
+#define	  SOLO_VO_USER_COLOR_SET_NAH		(1<<17)
+#define	  SOLO_VO_USER_COLOR_SET_NAV		(1<<16)
+#define	  SOLO_VO_NA_COLOR_Y(Y)			((Y)<<8)
+#define	  SOLO_VO_NA_COLOR_CB(CB)		(((CB)/16)<<4)
+#define	  SOLO_VO_NA_COLOR_CR(CR)		(((CR)/16)<<0)
+
+#define	SOLO_VO_ACT_H				0x0304
+#define	  SOLO_VO_H_BLANK(n)			((n)<<22)
+#define	  SOLO_VO_H_START(n)			((n)<<11)
+#define	  SOLO_VO_H_STOP(n)			((n)<<0)
+
+#define	SOLO_VO_ACT_V				0x0308
+#define	  SOLO_VO_V_BLANK(n)			((n)<<22)
+#define	  SOLO_VO_V_START(n)			((n)<<11)
+#define	  SOLO_VO_V_STOP(n)			((n)<<0)
+
+#define	SOLO_VO_RANGE_HV			0x030C
+#define	  SOLO_VO_SYNC_INVERT			(1<<24)
+#define	  SOLO_VO_HSYNC_INVERT			(1<<23)
+#define	  SOLO_VO_VSYNC_INVERT			(1<<22)
+#define	  SOLO_VO_H_LEN(n)			((n)<<11)
+#define	  SOLO_VO_V_LEN(n)			((n)<<0)
+
+#define	SOLO_VO_DISP_CTRL			0x0310
+#define	  SOLO_VO_DISP_ON			(1<<31)
+#define	  SOLO_VO_DISP_ERASE_COUNT(n)		((n&0xf)<<24)
+#define	  SOLO_VO_DISP_DOUBLE_SCAN		(1<<22)
+#define	  SOLO_VO_DISP_SINGLE_PAGE		(1<<21)
+#define	  SOLO_VO_DISP_BASE(n)			(((n)>>16) & 0xffff)
+
+#define SOLO_VO_DISP_ERASE			0x0314
+#define	  SOLO_VO_DISP_ERASE_ON			(1<<0)
+
+#define	SOLO_VO_ZOOM_CTRL			0x0318
+#define	  SOLO_VO_ZOOM_VER_ON			(1<<24)
+#define	  SOLO_VO_ZOOM_HOR_ON			(1<<23)
+#define	  SOLO_VO_ZOOM_V_COMP			(1<<22)
+#define	  SOLO_VO_ZOOM_SX(h)			(((h)/2)<<11)
+#define	  SOLO_VO_ZOOM_SY(v)			(((v)/2)<<0)
+
+#define SOLO_VO_FREEZE_CTRL			0x031C
+#define	  SOLO_VO_FREEZE_ON			(1<<1)
+#define	  SOLO_VO_FREEZE_INTERPOLATION		(1<<0)
+
+#define	SOLO_VO_BKG_COLOR			0x0320
+#define	  SOLO_BG_Y(y)				((y)<<16)
+#define	  SOLO_BG_U(u)				((u)<<8)
+#define	  SOLO_BG_V(v)				((v)<<0)
+
+#define	SOLO_VO_DEINTERLACE			0x0324
+#define	  SOLO_VO_DEINTERLACE_THRESHOLD(n)	((n)<<8)
+#define	  SOLO_VO_DEINTERLACE_EDGE_VALUE(n)	((n)<<0)
+
+#define SOLO_VO_BORDER_LINE_COLOR		0x0330
+#define SOLO_VO_BORDER_FILL_COLOR		0x0334
+#define SOLO_VO_BORDER_LINE_MASK		0x0338
+#define SOLO_VO_BORDER_FILL_MASK		0x033c
+
+#define SOLO_VO_BORDER_X(n)			(0x0340+((n)*4))
+#define SOLO_VO_BORDER_Y(n)			(0x0354+((n)*4))
+
+#define SOLO_VO_CELL_EXT_SET			0x0368
+#define SOLO_VO_CELL_EXT_START			0x036c
+#define SOLO_VO_CELL_EXT_STOP			0x0370
+
+#define SOLO_VO_CELL_EXT_SET2			0x0374
+#define SOLO_VO_CELL_EXT_START2			0x0378
+#define SOLO_VO_CELL_EXT_STOP2			0x037c
+
+#define SOLO_VO_RECTANGLE_CTRL(n)		(0x0368+((n)*12))
+#define SOLO_VO_RECTANGLE_START(n)		(0x036c+((n)*12))
+#define SOLO_VO_RECTANGLE_STOP(n)		(0x0370+((n)*12))
+
+#define SOLO_VO_CURSOR_POS			(0x0380)
+#define SOLO_VO_CURSOR_CLR			(0x0384)
+#define SOLO_VO_CURSOR_CLR2			(0x0388)
+#define SOLO_VO_CURSOR_MASK(id)			(0x0390+((id)*4))
+
+#define SOLO_VO_EXPANSION(id)			(0x0250+((id)*4))
+
+#define	SOLO_OSG_CONFIG				0x03E0
+#define	  SOLO_VO_OSG_ON			(1<<31)
+#define	  SOLO_VO_OSG_COLOR_MUTE		(1<<28)
+#define	  SOLO_VO_OSG_ALPHA_RATE(n)		((n)<<22)
+#define	  SOLO_VO_OSG_ALPHA_BG_RATE(n)		((n)<<16)
+#define	  SOLO_VO_OSG_BASE(offset)		(((offset)>>16)&0xffff)
+
+#define SOLO_OSG_ERASE				0x03E4
+#define	  SOLO_OSG_ERASE_ON			(0x80)
+#define	  SOLO_OSG_ERASE_OFF			(0x00)
+
+#define SOLO_VO_OSG_BLINK			0x03E8
+#define	  SOLO_VO_OSG_BLINK_ON			(1<<1)
+#define	  SOLO_VO_OSG_BLINK_INTREVAL18		(1<<0)
+
+#define SOLO_CAP_BASE				0x0400
+#define	  SOLO_CAP_MAX_PAGE(n)			((n)<<16)
+#define	  SOLO_CAP_BASE_ADDR(n)			((n)<<0)
+#define SOLO_CAP_BTW				0x0404
+#define	  SOLO_CAP_PROG_BANDWIDTH(n)		((n)<<8)
+#define	  SOLO_CAP_MAX_BANDWIDTH(n)		((n)<<0)
+
+#define SOLO_DIM_SCALE1				0x0408
+#define SOLO_DIM_SCALE2				0x040C
+#define SOLO_DIM_SCALE3				0x0410
+#define SOLO_DIM_SCALE4				0x0414
+#define SOLO_DIM_SCALE5				0x0418
+#define	  SOLO_DIM_V_MB_NUM_FRAME(n)		((n)<<16)
+#define	  SOLO_DIM_V_MB_NUM_FIELD(n)		((n)<<8)
+#define	  SOLO_DIM_H_MB_NUM(n)			((n)<<0)
+
+#define SOLO_DIM_PROG				0x041C
+#define SOLO_CAP_STATUS				0x0420
+
+#define SOLO_CAP_CH_SCALE(ch)			(0x0440+((ch)*4))
+#define SOLO_CAP_CH_COMP_ENA_E(ch)		(0x0480+((ch)*4))
+#define SOLO_CAP_CH_INTV(ch)			(0x04C0+((ch)*4))
+#define SOLO_CAP_CH_INTV_E(ch)			(0x0500+((ch)*4))
+
+
+#define SOLO_VE_CFG0				0x0610
+#define	  SOLO_VE_TWO_PAGE_MODE			(1<<31)
+#define	  SOLO_VE_INTR_CTRL(n)			((n)<<24)
+#define	  SOLO_VE_BLOCK_SIZE(n)			((n)<<16)
+#define	  SOLO_VE_BLOCK_BASE(n)			((n)<<0)
+
+#define SOLO_VE_CFG1				0x0614
+#define	  SOLO_VE_BYTE_ALIGN(n)			((n)<<24)
+#define	  SOLO_VE_INSERT_INDEX			(1<<18)
+#define	  SOLO_VE_MOTION_MODE(n)		((n)<<16)
+#define	  SOLO_VE_MOTION_BASE(n)		((n)<<0)
+#define   SOLO_VE_MPEG_SIZE_H(n)		((n)<<28) /* 6110 Only */
+#define   SOLO_VE_JPEG_SIZE_H(n)		((n)<<20) /* 6110 Only */
+#define   SOLO_VE_INSERT_INDEX_JPEG		(1<<19)   /* 6110 Only */
+
+#define SOLO_VE_WMRK_POLY			0x061C
+#define SOLO_VE_VMRK_INIT_KEY			0x0620
+#define SOLO_VE_WMRK_STRL			0x0624
+#define SOLO_VE_ENCRYP_POLY			0x0628
+#define SOLO_VE_ENCRYP_INIT			0x062C
+#define SOLO_VE_ATTR				0x0630
+#define	  SOLO_VE_LITTLE_ENDIAN			(1<<31)
+#define	  SOLO_COMP_ATTR_RN			(1<<30)
+#define	  SOLO_COMP_ATTR_FCODE(n)		((n)<<27)
+#define	  SOLO_COMP_TIME_INC(n)			((n)<<25)
+#define	  SOLO_COMP_TIME_WIDTH(n)		((n)<<21)
+#define	  SOLO_DCT_INTERVAL(n)			((n)<<16)
+#define SOLO_VE_COMPT_MOT			0x0634 /* 6110 Only */
+
+#define SOLO_VE_STATE(n)			(0x0640+((n)*4))
+
+#define SOLO_VE_JPEG_QP_TBL			0x0670
+#define SOLO_VE_JPEG_QP_CH_L			0x0674
+#define SOLO_VE_JPEG_QP_CH_H			0x0678
+#define SOLO_VE_JPEG_CFG			0x067C
+#define SOLO_VE_JPEG_CTRL			0x0680
+#define SOLO_VE_CODE_ENCRYPT			0x0684 /* 6110 Only */
+#define SOLO_VE_JPEG_CFG1			0x0688 /* 6110 Only */
+#define SOLO_VE_WMRK_ENABLE			0x068C /* 6110 Only */
+#define SOLO_VE_OSD_CH				0x0690
+#define SOLO_VE_OSD_BASE			0x0694
+#define SOLO_VE_OSD_CLR				0x0698
+#define SOLO_VE_OSD_OPT				0x069C
+#define   SOLO_VE_OSD_V_DOUBLE			(1<<16) /* 6110 Only */
+#define   SOLO_VE_OSD_H_SHADOW			(1<<15)
+#define   SOLO_VE_OSD_V_SHADOW			(1<<14)
+#define   SOLO_VE_OSD_H_OFFSET(n)		((n & 0x7f)<<7)
+#define   SOLO_VE_OSD_V_OFFSET(n)		(n & 0x7f)
+
+#define SOLO_VE_CH_INTL(ch)			(0x0700+((ch)*4))
+#define SOLO_VE_CH_MOT(ch)			(0x0740+((ch)*4))
+#define SOLO_VE_CH_QP(ch)			(0x0780+((ch)*4))
+#define SOLO_VE_CH_QP_E(ch)			(0x07C0+((ch)*4))
+#define SOLO_VE_CH_GOP(ch)			(0x0800+((ch)*4))
+#define SOLO_VE_CH_GOP_E(ch)			(0x0840+((ch)*4))
+#define SOLO_VE_CH_REF_BASE(ch)			(0x0880+((ch)*4))
+#define SOLO_VE_CH_REF_BASE_E(ch)		(0x08C0+((ch)*4))
+
+#define SOLO_VE_MPEG4_QUE(n)			(0x0A00+((n)*8))
+#define SOLO_VE_JPEG_QUE(n)			(0x0A04+((n)*8))
+
+#define SOLO_VD_CFG0				0x0900
+#define	  SOLO_VD_CFG_NO_WRITE_NO_WINDOW	(1<<24)
+#define	  SOLO_VD_CFG_BUSY_WIAT_CODE		(1<<23)
+#define	  SOLO_VD_CFG_BUSY_WIAT_REF		(1<<22)
+#define	  SOLO_VD_CFG_BUSY_WIAT_RES		(1<<21)
+#define	  SOLO_VD_CFG_BUSY_WIAT_MS		(1<<20)
+#define	  SOLO_VD_CFG_SINGLE_MODE		(1<<18)
+#define	  SOLO_VD_CFG_SCAL_MANUAL		(1<<17)
+#define	  SOLO_VD_CFG_USER_PAGE_CTRL		(1<<16)
+#define	  SOLO_VD_CFG_LITTLE_ENDIAN		(1<<15)
+#define	  SOLO_VD_CFG_START_FI			(1<<14)
+#define	  SOLO_VD_CFG_ERR_LOCK			(1<<13)
+#define	  SOLO_VD_CFG_ERR_INT_ENA		(1<<12)
+#define	  SOLO_VD_CFG_TIME_WIDTH(n)		((n)<<8)
+#define	  SOLO_VD_CFG_DCT_INTERVAL(n)		((n)<<0)
+
+#define SOLO_VD_CFG1				0x0904
+
+#define	SOLO_VD_DEINTERLACE			0x0908
+#define	  SOLO_VD_DEINTERLACE_THRESHOLD(n)	((n)<<8)
+#define	  SOLO_VD_DEINTERLACE_EDGE_VALUE(n)	((n)<<0)
+
+#define SOLO_VD_CODE_ADR			0x090C
+
+#define SOLO_VD_CTRL				0x0910
+#define	  SOLO_VD_OPER_ON			(1<<31)
+#define	  SOLO_VD_MAX_ITEM(n)			((n)<<0)
+
+#define SOLO_VD_STATUS0				0x0920
+#define	  SOLO_VD_STATUS0_INTR_ACK		(1<<22)
+#define	  SOLO_VD_STATUS0_INTR_EMPTY		(1<<21)
+#define	  SOLO_VD_STATUS0_INTR_ERR		(1<<20)
+
+#define SOLO_VD_STATUS1				0x0924
+
+#define SOLO_VD_IDX0				0x0930
+#define	  SOLO_VD_IDX_INTERLACE			(1<<30)
+#define	  SOLO_VD_IDX_CHANNEL(n)		((n)<<24)
+#define	  SOLO_VD_IDX_SIZE(n)			((n)<<0)
+
+#define SOLO_VD_IDX1				0x0934
+#define	  SOLO_VD_IDX_SRC_SCALE(n)		((n)<<28)
+#define	  SOLO_VD_IDX_WINDOW(n)			((n)<<24)
+#define	  SOLO_VD_IDX_DEINTERLACE		(1<<16)
+#define	  SOLO_VD_IDX_H_BLOCK(n)		((n)<<8)
+#define	  SOLO_VD_IDX_V_BLOCK(n)		((n)<<0)
+
+#define SOLO_VD_IDX2				0x0938
+#define	  SOLO_VD_IDX_REF_BASE_SIDE		(1<<31)
+#define	  SOLO_VD_IDX_REF_BASE(n)		(((n)>>16)&0xffff)
+
+#define SOLO_VD_IDX3				0x093C
+#define	  SOLO_VD_IDX_DISP_SCALE(n)		((n)<<28)
+#define	  SOLO_VD_IDX_INTERLACE_WR		(1<<27)
+#define	  SOLO_VD_IDX_INTERPOL			(1<<26)
+#define	  SOLO_VD_IDX_HOR2X			(1<<25)
+#define	  SOLO_VD_IDX_OFFSET_X(n)		((n)<<12)
+#define	  SOLO_VD_IDX_OFFSET_Y(n)		((n)<<0)
+
+#define SOLO_VD_IDX4				0x0940
+#define	  SOLO_VD_IDX_DEC_WR_PAGE(n)		((n)<<8)
+#define	  SOLO_VD_IDX_DISP_RD_PAGE(n)		((n)<<0)
+
+#define SOLO_VD_WR_PAGE(n)			(0x03F0 + ((n) * 4))
+
+
+#define SOLO_GPIO_CONFIG_0			0x0B00
+#define SOLO_GPIO_CONFIG_1			0x0B04
+#define SOLO_GPIO_DATA_OUT			0x0B08
+#define SOLO_GPIO_DATA_IN			0x0B0C
+#define SOLO_GPIO_INT_ACK_STA			0x0B10
+#define SOLO_GPIO_INT_ENA			0x0B14
+#define SOLO_GPIO_INT_CFG_0			0x0B18
+#define SOLO_GPIO_INT_CFG_1			0x0B1C
+
+
+#define SOLO_IIC_CFG				0x0B20
+#define	  SOLO_IIC_ENABLE			(1<<8)
+#define	  SOLO_IIC_PRESCALE(n)			((n)<<0)
+
+#define SOLO_IIC_CTRL				0x0B24
+#define	  SOLO_IIC_AUTO_CLEAR			(1<<20)
+#define	  SOLO_IIC_STATE_RX_ACK			(1<<19)
+#define	  SOLO_IIC_STATE_BUSY			(1<<18)
+#define	  SOLO_IIC_STATE_SIG_ERR		(1<<17)
+#define	  SOLO_IIC_STATE_TRNS			(1<<16)
+#define	  SOLO_IIC_CH_SET(n)			((n)<<5)
+#define	  SOLO_IIC_ACK_EN			(1<<4)
+#define	  SOLO_IIC_START			(1<<3)
+#define	  SOLO_IIC_STOP				(1<<2)
+#define	  SOLO_IIC_READ				(1<<1)
+#define	  SOLO_IIC_WRITE			(1<<0)
+
+#define SOLO_IIC_TXD				0x0B28
+#define SOLO_IIC_RXD				0x0B2C
+
+/*
+ *	UART REGISTER
+ */
+#define SOLO_UART_CONTROL(n)			(0x0BA0 + ((n)*0x20))
+#define	  SOLO_UART_CLK_DIV(n)			((n)<<24)
+#define	  SOLO_MODEM_CTRL_EN			(1<<20)
+#define	  SOLO_PARITY_ERROR_DROP		(1<<18)
+#define	  SOLO_IRQ_ERR_EN			(1<<17)
+#define	  SOLO_IRQ_RX_EN			(1<<16)
+#define	  SOLO_IRQ_TX_EN			(1<<15)
+#define	  SOLO_RX_EN				(1<<14)
+#define	  SOLO_TX_EN				(1<<13)
+#define	  SOLO_UART_HALF_DUPLEX			(1<<12)
+#define	  SOLO_UART_LOOPBACK			(1<<11)
+
+#define	  SOLO_BAUDRATE_230400			((0<<9)|(0<<6))
+#define	  SOLO_BAUDRATE_115200			((0<<9)|(1<<6))
+#define	  SOLO_BAUDRATE_57600			((0<<9)|(2<<6))
+#define	  SOLO_BAUDRATE_38400			((0<<9)|(3<<6))
+#define	  SOLO_BAUDRATE_19200			((0<<9)|(4<<6))
+#define	  SOLO_BAUDRATE_9600			((0<<9)|(5<<6))
+#define	  SOLO_BAUDRATE_4800			((0<<9)|(6<<6))
+#define	  SOLO_BAUDRATE_2400			((1<<9)|(6<<6))
+#define	  SOLO_BAUDRATE_1200			((2<<9)|(6<<6))
+#define	  SOLO_BAUDRATE_300			((3<<9)|(6<<6))
+
+#define	  SOLO_UART_DATA_BIT_8			(3<<4)
+#define	  SOLO_UART_DATA_BIT_7			(2<<4)
+#define	  SOLO_UART_DATA_BIT_6			(1<<4)
+#define	  SOLO_UART_DATA_BIT_5			(0<<4)
+
+#define	  SOLO_UART_STOP_BIT_1			(0<<2)
+#define	  SOLO_UART_STOP_BIT_2			(1<<2)
+
+#define	  SOLO_UART_PARITY_NONE			(0<<0)
+#define	  SOLO_UART_PARITY_EVEN			(2<<0)
+#define	  SOLO_UART_PARITY_ODD			(3<<0)
+
+#define SOLO_UART_STATUS(n)			(0x0BA4 + ((n)*0x20))
+#define	  SOLO_UART_CTS				(1<<15)
+#define	  SOLO_UART_RX_BUSY			(1<<14)
+#define	  SOLO_UART_OVERRUN			(1<<13)
+#define	  SOLO_UART_FRAME_ERR			(1<<12)
+#define	  SOLO_UART_PARITY_ERR			(1<<11)
+#define	  SOLO_UART_TX_BUSY			(1<<5)
+
+#define	  SOLO_UART_RX_BUFF_CNT(stat)		(((stat)>>6) & 0x1f)
+#define	  SOLO_UART_RX_BUFF_SIZE		8
+#define	  SOLO_UART_TX_BUFF_CNT(stat)		(((stat)>>0) & 0x1f)
+#define	  SOLO_UART_TX_BUFF_SIZE		8
+
+#define SOLO_UART_TX_DATA(n)			(0x0BA8 + ((n)*0x20))
+#define	  SOLO_UART_TX_DATA_PUSH		(1<<8)
+#define SOLO_UART_RX_DATA(n)			(0x0BAC + ((n)*0x20))
+#define	  SOLO_UART_RX_DATA_POP			(1<<8)
+
+#define SOLO_TIMER_CLOCK_NUM			0x0be0
+#define SOLO_TIMER_USEC				0x0be8
+#define SOLO_TIMER_SEC				0x0bec
+#define SOLO_TIMER_USEC_LSB			0x0d20 /* 6110 Only */
+
+#define SOLO_AUDIO_CONTROL			0x0D00
+#define	  SOLO_AUDIO_ENABLE			(1<<31)
+#define	  SOLO_AUDIO_MASTER_MODE		(1<<30)
+#define	  SOLO_AUDIO_I2S_MODE			(1<<29)
+#define	  SOLO_AUDIO_I2S_LR_SWAP		(1<<27)
+#define	  SOLO_AUDIO_I2S_8BIT			(1<<26)
+#define	  SOLO_AUDIO_I2S_MULTI(n)		((n)<<24)
+#define	  SOLO_AUDIO_MIX_9TO0			(1<<23)
+#define	  SOLO_AUDIO_DEC_9TO0_VOL(n)		((n)<<20)
+#define	  SOLO_AUDIO_MIX_19TO10			(1<<19)
+#define	  SOLO_AUDIO_DEC_19TO10_VOL(n)		((n)<<16)
+#define	  SOLO_AUDIO_MODE(n)			((n)<<0)
+#define SOLO_AUDIO_SAMPLE			0x0D04
+#define	  SOLO_AUDIO_EE_MODE_ON			(1<<30)
+#define	  SOLO_AUDIO_EE_ENC_CH(ch)		((ch)<<25)
+#define	  SOLO_AUDIO_BITRATE(n)			((n)<<16)
+#define	  SOLO_AUDIO_CLK_DIV(n)			((n)<<0)
+#define SOLO_AUDIO_FDMA_INTR			0x0D08
+#define	  SOLO_AUDIO_FDMA_INTERVAL(n)		((n)<<19)
+#define	  SOLO_AUDIO_INTR_ORDER(n)		((n)<<16)
+#define	  SOLO_AUDIO_FDMA_BASE(n)		((n)<<0)
+#define SOLO_AUDIO_EVOL_0			0x0D0C
+#define SOLO_AUDIO_EVOL_1			0x0D10
+#define	  SOLO_AUDIO_EVOL(ch, value)		((value)<<((ch)%10))
+#define SOLO_AUDIO_STA				0x0D14
+
+/*
+ * Watchdog configuration
+ */
+#define SOLO_WATCHDOG				0x0be4
+#define SOLO_WATCHDOG_SET(status, sec)		(status << 8 | (sec & 0xff))
+
+#endif /* __SOLO6X10_REGISTERS_H */
diff --git a/drivers/staging/media/solo6x10/solo6x10-tw28.c b/drivers/staging/media/solo6x10/solo6x10-tw28.c
new file mode 100644
index 0000000..ad00e2b
--- /dev/null
+++ b/drivers/staging/media/solo6x10/solo6x10-tw28.c
@@ -0,0 +1,854 @@
+/*
+ * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
+ *
+ * Original author:
+ * Ben Collins <bcollins@ubuntu.com>
+ *
+ * Additional work by:
+ * John Brooks <john.brooks@bluecherry.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You 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/delay.h>
+
+#include "solo6x10.h"
+#include "solo6x10-tw28.h"
+
+#define DEFAULT_HDELAY_NTSC		(32 - 8)
+#define DEFAULT_HACTIVE_NTSC		(720 + 16)
+#define DEFAULT_VDELAY_NTSC		(7 - 2)
+#define DEFAULT_VACTIVE_NTSC		(240 + 4)
+
+#define DEFAULT_HDELAY_PAL		(32 + 4)
+#define DEFAULT_HACTIVE_PAL		(864-DEFAULT_HDELAY_PAL)
+#define DEFAULT_VDELAY_PAL		(6)
+#define DEFAULT_VACTIVE_PAL		(312-DEFAULT_VDELAY_PAL)
+
+
+static const u8 tbl_tw2864_ntsc_template[] = {
+	0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x02, /* 0x00 */
+	0x12, 0xf5, 0x0c, 0xd0, 0x00, 0x00, 0x00, 0x7f,
+	0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x02, /* 0x10 */
+	0x12, 0xf5, 0x0c, 0xd0, 0x00, 0x00, 0x00, 0x7f,
+	0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x02, /* 0x20 */
+	0x12, 0xf5, 0x0c, 0xd0, 0x00, 0x00, 0x00, 0x7f,
+	0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x02, /* 0x30 */
+	0x12, 0xf5, 0x0c, 0xd0, 0x00, 0x00, 0x00, 0x7f,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA3, 0x00,
+	0x00, 0x02, 0x00, 0xcc, 0x00, 0x80, 0x44, 0x50, /* 0x80 */
+	0x22, 0x01, 0xd8, 0xbc, 0xb8, 0x44, 0x38, 0x00,
+	0x00, 0x78, 0x72, 0x3e, 0x14, 0xa5, 0xe4, 0x05, /* 0x90 */
+	0x00, 0x28, 0x44, 0x44, 0xa0, 0x88, 0x5a, 0x01,
+	0x08, 0x08, 0x08, 0x08, 0x1a, 0x1a, 0x1a, 0x1a, /* 0xa0 */
+	0x00, 0x00, 0x00, 0xf0, 0xf0, 0xf0, 0xf0, 0x44,
+	0x44, 0x0a, 0x00, 0xff, 0xef, 0xef, 0xef, 0xef, /* 0xb0 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0 */
+	0x00, 0x00, 0x55, 0x00, 0xb1, 0xe4, 0x40, 0x00,
+	0x77, 0x77, 0x01, 0x13, 0x57, 0x9b, 0xdf, 0x20, /* 0xd0 */
+	0x64, 0xa8, 0xec, 0xc1, 0x0f, 0x11, 0x11, 0x81,
+	0x00, 0xe0, 0xbb, 0xbb, 0x00, 0x11, 0x00, 0x00, /* 0xe0 */
+	0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0x11, 0x00,
+	0x83, 0xb5, 0x09, 0x78, 0x85, 0x00, 0x01, 0x20, /* 0xf0 */
+	0x64, 0x11, 0x40, 0xaf, 0xff, 0x00, 0x00, 0x00,
+};
+
+static const u8 tbl_tw2864_pal_template[] = {
+	0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12, /* 0x00 */
+	0x18, 0xf5, 0x0c, 0xd0, 0x00, 0x00, 0x01, 0x7f,
+	0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12, /* 0x10 */
+	0x18, 0xf5, 0x0c, 0xd0, 0x00, 0x00, 0x01, 0x7f,
+	0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12, /* 0x20 */
+	0x18, 0xf5, 0x0c, 0xd0, 0x00, 0x00, 0x01, 0x7f,
+	0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12, /* 0x30 */
+	0x18, 0xf5, 0x0c, 0xd0, 0x00, 0x00, 0x01, 0x7f,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA3, 0x00,
+	0x00, 0x02, 0x00, 0xcc, 0x00, 0x80, 0x44, 0x50, /* 0x80 */
+	0x22, 0x01, 0xd8, 0xbc, 0xb8, 0x44, 0x38, 0x00,
+	0x00, 0x78, 0x72, 0x3e, 0x14, 0xa5, 0xe4, 0x05, /* 0x90 */
+	0x00, 0x28, 0x44, 0x44, 0xa0, 0x90, 0x5a, 0x01,
+	0x0a, 0x0a, 0x0a, 0x0a, 0x1a, 0x1a, 0x1a, 0x1a, /* 0xa0 */
+	0x00, 0x00, 0x00, 0xf0, 0xf0, 0xf0, 0xf0, 0x44,
+	0x44, 0x0a, 0x00, 0xff, 0xef, 0xef, 0xef, 0xef, /* 0xb0 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0 */
+	0x00, 0x00, 0x55, 0x00, 0xb1, 0xe4, 0x40, 0x00,
+	0x77, 0x77, 0x01, 0x13, 0x57, 0x9b, 0xdf, 0x20, /* 0xd0 */
+	0x64, 0xa8, 0xec, 0xc1, 0x0f, 0x11, 0x11, 0x81,
+	0x00, 0xe0, 0xbb, 0xbb, 0x00, 0x11, 0x00, 0x00, /* 0xe0 */
+	0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0x11, 0x00,
+	0x83, 0xb5, 0x09, 0x00, 0xa0, 0x00, 0x01, 0x20, /* 0xf0 */
+	0x64, 0x11, 0x40, 0xaf, 0xff, 0x00, 0x00, 0x00,
+};
+
+static const u8 tbl_tw2865_ntsc_template[] = {
+	0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x02, /* 0x00 */
+	0x12, 0xff, 0x09, 0xd0, 0x00, 0x00, 0x00, 0x7f,
+	0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x02, /* 0x10 */
+	0x12, 0xff, 0x09, 0xd0, 0x00, 0x00, 0x00, 0x7f,
+	0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x02, /* 0x20 */
+	0x12, 0xff, 0x09, 0xd0, 0x00, 0x00, 0x00, 0x7f,
+	0x00, 0xf0, 0x70, 0x48, 0x80, 0x80, 0x00, 0x02, /* 0x30 */
+	0x12, 0xff, 0x09, 0xd0, 0x00, 0x00, 0x00, 0x7f,
+	0x00, 0x00, 0x90, 0x68, 0x00, 0x38, 0x80, 0x80, /* 0x40 */
+	0x80, 0x80, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x45, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x43,
+	0x08, 0x00, 0x00, 0x01, 0xf1, 0x03, 0xEF, 0x03, /* 0x70 */
+	0xE9, 0x03, 0xD9, 0x15, 0x15, 0xE4, 0xA3, 0x80,
+	0x00, 0x02, 0x00, 0xCC, 0x00, 0x80, 0x44, 0x50, /* 0x80 */
+	0x22, 0x01, 0xD8, 0xBC, 0xB8, 0x44, 0x38, 0x00,
+	0x00, 0x78, 0x44, 0x3D, 0x14, 0xA5, 0xE0, 0x05, /* 0x90 */
+	0x00, 0x28, 0x44, 0x44, 0xA0, 0x90, 0x52, 0x13,
+	0x08, 0x08, 0x08, 0x08, 0x1A, 0x1A, 0x1B, 0x1A, /* 0xa0 */
+	0x00, 0x00, 0x00, 0xF0, 0xF0, 0xF0, 0xF0, 0x44,
+	0x44, 0x4A, 0x00, 0xFF, 0xEF, 0xEF, 0xEF, 0xEF, /* 0xb0 */
+	0xFF, 0xE7, 0xE9, 0xE9, 0xEB, 0xFF, 0xD6, 0xD8,
+	0xD8, 0xD7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0 */
+	0x00, 0x00, 0x55, 0x00, 0xE4, 0x39, 0x00, 0x80,
+	0x77, 0x77, 0x03, 0x20, 0x57, 0x9b, 0xdf, 0x31, /* 0xd0 */
+	0x64, 0xa8, 0xec, 0xd1, 0x0f, 0x11, 0x11, 0x81,
+	0x10, 0xC0, 0xAA, 0xAA, 0x00, 0x11, 0x00, 0x00, /* 0xe0 */
+	0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0x11, 0x00,
+	0x83, 0xB5, 0x09, 0x78, 0x85, 0x00, 0x01, 0x20, /* 0xf0 */
+	0x64, 0x51, 0x40, 0xaf, 0xFF, 0xF0, 0x00, 0xC0,
+};
+
+static const u8 tbl_tw2865_pal_template[] = {
+	0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12, /* 0x00 */
+	0x11, 0xff, 0x01, 0xc3, 0x00, 0x00, 0x01, 0x7f,
+	0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12, /* 0x10 */
+	0x11, 0xff, 0x01, 0xc3, 0x00, 0x00, 0x01, 0x7f,
+	0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12, /* 0x20 */
+	0x11, 0xff, 0x01, 0xc3, 0x00, 0x00, 0x01, 0x7f,
+	0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12, /* 0x30 */
+	0x11, 0xff, 0x01, 0xc3, 0x00, 0x00, 0x01, 0x7f,
+	0x00, 0x94, 0x90, 0x48, 0x00, 0x38, 0x7F, 0x80, /* 0x40 */
+	0x80, 0x80, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x45, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x43,
+	0x08, 0x00, 0x00, 0x01, 0xf1, 0x03, 0xEF, 0x03, /* 0x70 */
+	0xEA, 0x03, 0xD9, 0x15, 0x15, 0xE4, 0xA3, 0x80,
+	0x00, 0x02, 0x00, 0xCC, 0x00, 0x80, 0x44, 0x50, /* 0x80 */
+	0x22, 0x01, 0xD8, 0xBC, 0xB8, 0x44, 0x38, 0x00,
+	0x00, 0x78, 0x44, 0x3D, 0x14, 0xA5, 0xE0, 0x05, /* 0x90 */
+	0x00, 0x28, 0x44, 0x44, 0xA0, 0x90, 0x52, 0x13,
+	0x08, 0x08, 0x08, 0x08, 0x1A, 0x1A, 0x1A, 0x1A, /* 0xa0 */
+	0x00, 0x00, 0x00, 0xF0, 0xF0, 0xF0, 0xF0, 0x44,
+	0x44, 0x4A, 0x00, 0xFF, 0xEF, 0xEF, 0xEF, 0xEF, /* 0xb0 */
+	0xFF, 0xE7, 0xE9, 0xE9, 0xE9, 0xFF, 0xD7, 0xD8,
+	0xD9, 0xD8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0 */
+	0x00, 0x00, 0x55, 0x00, 0xE4, 0x39, 0x00, 0x80,
+	0x77, 0x77, 0x03, 0x20, 0x57, 0x9b, 0xdf, 0x31, /* 0xd0 */
+	0x64, 0xa8, 0xec, 0xd1, 0x0f, 0x11, 0x11, 0x81,
+	0x10, 0xC0, 0xAA, 0xAA, 0x00, 0x11, 0x00, 0x00, /* 0xe0 */
+	0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0x11, 0x00,
+	0x83, 0xB5, 0x09, 0x00, 0xA0, 0x00, 0x01, 0x20, /* 0xf0 */
+	0x64, 0x51, 0x40, 0xaf, 0xFF, 0xF0, 0x00, 0xC0,
+};
+
+#define is_tw286x(__solo, __id) (!(__solo->tw2815 & (1 << __id)))
+
+static u8 tw_readbyte(struct solo_dev *solo_dev, int chip_id, u8 tw6x_off,
+		      u8 tw_off)
+{
+	if (is_tw286x(solo_dev, chip_id))
+		return solo_i2c_readbyte(solo_dev, SOLO_I2C_TW,
+					 TW_CHIP_OFFSET_ADDR(chip_id),
+					 tw6x_off);
+	else
+		return solo_i2c_readbyte(solo_dev, SOLO_I2C_TW,
+					 TW_CHIP_OFFSET_ADDR(chip_id),
+					 tw_off);
+}
+
+static void tw_writebyte(struct solo_dev *solo_dev, int chip_id,
+			 u8 tw6x_off, u8 tw_off, u8 val)
+{
+	if (is_tw286x(solo_dev, chip_id))
+		solo_i2c_writebyte(solo_dev, SOLO_I2C_TW,
+				   TW_CHIP_OFFSET_ADDR(chip_id),
+				   tw6x_off, val);
+	else
+		solo_i2c_writebyte(solo_dev, SOLO_I2C_TW,
+				   TW_CHIP_OFFSET_ADDR(chip_id),
+				   tw_off, val);
+}
+
+static void tw_write_and_verify(struct solo_dev *solo_dev, u8 addr, u8 off,
+				u8 val)
+{
+	int i;
+
+	for (i = 0; i < 5; i++) {
+		u8 rval = solo_i2c_readbyte(solo_dev, SOLO_I2C_TW, addr, off);
+		if (rval == val)
+			return;
+
+		solo_i2c_writebyte(solo_dev, SOLO_I2C_TW, addr, off, val);
+		msleep_interruptible(1);
+	}
+
+/*	printk("solo6x10/tw28: Error writing register: %02x->%02x [%02x]\n", */
+/*		addr, off, val); */
+}
+
+static int tw2865_setup(struct solo_dev *solo_dev, u8 dev_addr)
+{
+	u8 tbl_tw2865_common[256];
+	int i;
+
+	if (solo_dev->video_type == SOLO_VO_FMT_TYPE_PAL)
+		memcpy(tbl_tw2865_common, tbl_tw2865_pal_template,
+		       sizeof(tbl_tw2865_common));
+	else
+		memcpy(tbl_tw2865_common, tbl_tw2865_ntsc_template,
+		       sizeof(tbl_tw2865_common));
+
+	/* ALINK Mode */
+	if (solo_dev->nr_chans == 4) {
+		tbl_tw2865_common[0xd2] = 0x01;
+		tbl_tw2865_common[0xcf] = 0x00;
+	} else if (solo_dev->nr_chans == 8) {
+		tbl_tw2865_common[0xd2] = 0x02;
+		if (dev_addr == TW_CHIP_OFFSET_ADDR(1))
+			tbl_tw2865_common[0xcf] = 0x80;
+	} else if (solo_dev->nr_chans == 16) {
+		tbl_tw2865_common[0xd2] = 0x03;
+		if (dev_addr == TW_CHIP_OFFSET_ADDR(1))
+			tbl_tw2865_common[0xcf] = 0x83;
+		else if (dev_addr == TW_CHIP_OFFSET_ADDR(2))
+			tbl_tw2865_common[0xcf] = 0x83;
+		else if (dev_addr == TW_CHIP_OFFSET_ADDR(3))
+			tbl_tw2865_common[0xcf] = 0x80;
+	}
+
+	for (i = 0; i < 0xff; i++) {
+		/* Skip read only registers */
+		switch (i) {
+		case 0xb8 ... 0xc1:
+		case 0xc4 ... 0xc7:
+		case 0xfd:
+			continue;
+		}
+		switch (i & ~0x30) {
+		case 0x00:
+		case 0x0c ... 0x0d:
+			continue;
+		}
+
+		tw_write_and_verify(solo_dev, dev_addr, i,
+				    tbl_tw2865_common[i]);
+	}
+
+	return 0;
+}
+
+static int tw2864_setup(struct solo_dev *solo_dev, u8 dev_addr)
+{
+	u8 tbl_tw2864_common[256];
+	int i;
+
+	if (solo_dev->video_type == SOLO_VO_FMT_TYPE_PAL)
+		memcpy(tbl_tw2864_common, tbl_tw2864_pal_template,
+		       sizeof(tbl_tw2864_common));
+	else
+		memcpy(tbl_tw2864_common, tbl_tw2864_ntsc_template,
+		       sizeof(tbl_tw2864_common));
+
+	if (solo_dev->tw2865 == 0) {
+		/* IRQ Mode */
+		if (solo_dev->nr_chans == 4) {
+			tbl_tw2864_common[0xd2] = 0x01;
+			tbl_tw2864_common[0xcf] = 0x00;
+		} else if (solo_dev->nr_chans == 8) {
+			tbl_tw2864_common[0xd2] = 0x02;
+			if (dev_addr == TW_CHIP_OFFSET_ADDR(0))
+				tbl_tw2864_common[0xcf] = 0x43;
+			else if (dev_addr == TW_CHIP_OFFSET_ADDR(1))
+				tbl_tw2864_common[0xcf] = 0x40;
+		} else if (solo_dev->nr_chans == 16) {
+			tbl_tw2864_common[0xd2] = 0x03;
+			if (dev_addr == TW_CHIP_OFFSET_ADDR(0))
+				tbl_tw2864_common[0xcf] = 0x43;
+			else if (dev_addr == TW_CHIP_OFFSET_ADDR(1))
+				tbl_tw2864_common[0xcf] = 0x43;
+			else if (dev_addr == TW_CHIP_OFFSET_ADDR(2))
+				tbl_tw2864_common[0xcf] = 0x43;
+			else if (dev_addr == TW_CHIP_OFFSET_ADDR(3))
+				tbl_tw2864_common[0xcf] = 0x40;
+		}
+	} else {
+		/* ALINK Mode. Assumes that the first tw28xx is a
+		 * 2865 and these are in cascade. */
+		for (i = 0; i <= 4; i++)
+			tbl_tw2864_common[0x08 | i << 4] = 0x12;
+
+		if (solo_dev->nr_chans == 8) {
+			tbl_tw2864_common[0xd2] = 0x02;
+			if (dev_addr == TW_CHIP_OFFSET_ADDR(1))
+				tbl_tw2864_common[0xcf] = 0x80;
+		} else if (solo_dev->nr_chans == 16) {
+			tbl_tw2864_common[0xd2] = 0x03;
+			if (dev_addr == TW_CHIP_OFFSET_ADDR(1))
+				tbl_tw2864_common[0xcf] = 0x83;
+			else if (dev_addr == TW_CHIP_OFFSET_ADDR(2))
+				tbl_tw2864_common[0xcf] = 0x83;
+			else if (dev_addr == TW_CHIP_OFFSET_ADDR(3))
+				tbl_tw2864_common[0xcf] = 0x80;
+		}
+	}
+
+	for (i = 0; i < 0xff; i++) {
+		/* Skip read only registers */
+		switch (i) {
+		case 0xb8 ... 0xc1:
+		case 0xfd:
+			continue;
+		}
+		switch (i & ~0x30) {
+		case 0x00:
+		case 0x0c:
+		case 0x0d:
+			continue;
+		}
+
+		tw_write_and_verify(solo_dev, dev_addr, i,
+				    tbl_tw2864_common[i]);
+	}
+
+	return 0;
+}
+
+static int tw2815_setup(struct solo_dev *solo_dev, u8 dev_addr)
+{
+	u8 tbl_ntsc_tw2815_common[] = {
+		0x00, 0xc8, 0x20, 0xd0, 0x06, 0xf0, 0x08, 0x80,
+		0x80, 0x80, 0x80, 0x02, 0x06, 0x00, 0x11,
+	};
+
+	u8 tbl_pal_tw2815_common[] = {
+		0x00, 0x88, 0x20, 0xd0, 0x05, 0x20, 0x28, 0x80,
+		0x80, 0x80, 0x80, 0x82, 0x06, 0x00, 0x11,
+	};
+
+	u8 tbl_tw2815_sfr[] = {
+		0x00, 0x00, 0x00, 0xc0, 0x45, 0xa0, 0xd0, 0x2f, /* 0x00 */
+		0x64, 0x80, 0x80, 0x82, 0x82, 0x00, 0x00, 0x00,
+		0x00, 0x0f, 0x05, 0x00, 0x00, 0x80, 0x06, 0x00, /* 0x10 */
+		0x00, 0x00, 0x00, 0xff, 0x8f, 0x00, 0x00, 0x00,
+		0x88, 0x88, 0xc0, 0x00, 0x20, 0x64, 0xa8, 0xec, /* 0x20 */
+		0x31, 0x75, 0xb9, 0xfd, 0x00, 0x00, 0x88, 0x88,
+		0x88, 0x11, 0x00, 0x88, 0x88, 0x00,		/* 0x30 */
+	};
+	u8 *tbl_tw2815_common;
+	int i;
+	int ch;
+
+	tbl_ntsc_tw2815_common[0x06] = 0;
+
+	/* Horizontal Delay Control */
+	tbl_ntsc_tw2815_common[0x02] = DEFAULT_HDELAY_NTSC & 0xff;
+	tbl_ntsc_tw2815_common[0x06] |= 0x03 & (DEFAULT_HDELAY_NTSC >> 8);
+
+	/* Horizontal Active Control */
+	tbl_ntsc_tw2815_common[0x03] = DEFAULT_HACTIVE_NTSC & 0xff;
+	tbl_ntsc_tw2815_common[0x06] |=
+		((0x03 & (DEFAULT_HACTIVE_NTSC >> 8)) << 2);
+
+	/* Vertical Delay Control */
+	tbl_ntsc_tw2815_common[0x04] = DEFAULT_VDELAY_NTSC & 0xff;
+	tbl_ntsc_tw2815_common[0x06] |=
+		((0x01 & (DEFAULT_VDELAY_NTSC >> 8)) << 4);
+
+	/* Vertical Active Control */
+	tbl_ntsc_tw2815_common[0x05] = DEFAULT_VACTIVE_NTSC & 0xff;
+	tbl_ntsc_tw2815_common[0x06] |=
+		((0x01 & (DEFAULT_VACTIVE_NTSC >> 8)) << 5);
+
+	tbl_pal_tw2815_common[0x06] = 0;
+
+	/* Horizontal Delay Control */
+	tbl_pal_tw2815_common[0x02] = DEFAULT_HDELAY_PAL & 0xff;
+	tbl_pal_tw2815_common[0x06] |= 0x03 & (DEFAULT_HDELAY_PAL >> 8);
+
+	/* Horizontal Active Control */
+	tbl_pal_tw2815_common[0x03] = DEFAULT_HACTIVE_PAL & 0xff;
+	tbl_pal_tw2815_common[0x06] |=
+		((0x03 & (DEFAULT_HACTIVE_PAL >> 8)) << 2);
+
+	/* Vertical Delay Control */
+	tbl_pal_tw2815_common[0x04] = DEFAULT_VDELAY_PAL & 0xff;
+	tbl_pal_tw2815_common[0x06] |=
+		((0x01 & (DEFAULT_VDELAY_PAL >> 8)) << 4);
+
+	/* Vertical Active Control */
+	tbl_pal_tw2815_common[0x05] = DEFAULT_VACTIVE_PAL & 0xff;
+	tbl_pal_tw2815_common[0x06] |=
+		((0x01 & (DEFAULT_VACTIVE_PAL >> 8)) << 5);
+
+	tbl_tw2815_common =
+	    (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) ?
+	     tbl_ntsc_tw2815_common : tbl_pal_tw2815_common;
+
+	/* Dual ITU-R BT.656 format */
+	tbl_tw2815_common[0x0d] |= 0x04;
+
+	/* Audio configuration */
+	tbl_tw2815_sfr[0x62 - 0x40] &= ~(3 << 6);
+
+	if (solo_dev->nr_chans == 4) {
+		tbl_tw2815_sfr[0x63 - 0x40] |= 1;
+		tbl_tw2815_sfr[0x62 - 0x40] |= 3 << 6;
+	} else if (solo_dev->nr_chans == 8) {
+		tbl_tw2815_sfr[0x63 - 0x40] |= 2;
+		if (dev_addr == TW_CHIP_OFFSET_ADDR(0))
+			tbl_tw2815_sfr[0x62 - 0x40] |= 1 << 6;
+		else if (dev_addr == TW_CHIP_OFFSET_ADDR(1))
+			tbl_tw2815_sfr[0x62 - 0x40] |= 2 << 6;
+	} else if (solo_dev->nr_chans == 16) {
+		tbl_tw2815_sfr[0x63 - 0x40] |= 3;
+		if (dev_addr == TW_CHIP_OFFSET_ADDR(0))
+			tbl_tw2815_sfr[0x62 - 0x40] |= 1 << 6;
+		else if (dev_addr == TW_CHIP_OFFSET_ADDR(1))
+			tbl_tw2815_sfr[0x62 - 0x40] |= 0 << 6;
+		else if (dev_addr == TW_CHIP_OFFSET_ADDR(2))
+			tbl_tw2815_sfr[0x62 - 0x40] |= 0 << 6;
+		else if (dev_addr == TW_CHIP_OFFSET_ADDR(3))
+			tbl_tw2815_sfr[0x62 - 0x40] |= 2 << 6;
+	}
+
+	/* Output mode of R_ADATM pin (0 mixing, 1 record) */
+	/* tbl_tw2815_sfr[0x63 - 0x40] |= 0 << 2; */
+
+	/* 8KHz, used to be 16KHz, but changed for remote client compat */
+	tbl_tw2815_sfr[0x62 - 0x40] |= 0 << 2;
+	tbl_tw2815_sfr[0x6c - 0x40] |= 0 << 2;
+
+	/* Playback of right channel */
+	tbl_tw2815_sfr[0x6c - 0x40] |= 1 << 5;
+
+	/* Reserved value (XXX ??) */
+	tbl_tw2815_sfr[0x5c - 0x40] |= 1 << 5;
+
+	/* Analog output gain and mix ratio playback on full */
+	tbl_tw2815_sfr[0x70 - 0x40] |= 0xff;
+	/* Select playback audio and mute all except */
+	tbl_tw2815_sfr[0x71 - 0x40] |= 0x10;
+	tbl_tw2815_sfr[0x6d - 0x40] |= 0x0f;
+
+	/* End of audio configuration */
+
+	for (ch = 0; ch < 4; ch++) {
+		tbl_tw2815_common[0x0d] &= ~3;
+		switch (ch) {
+		case 0:
+			tbl_tw2815_common[0x0d] |= 0x21;
+			break;
+		case 1:
+			tbl_tw2815_common[0x0d] |= 0x20;
+			break;
+		case 2:
+			tbl_tw2815_common[0x0d] |= 0x23;
+			break;
+		case 3:
+			tbl_tw2815_common[0x0d] |= 0x22;
+			break;
+		}
+
+		for (i = 0; i < 0x0f; i++) {
+			if (i == 0x00)
+				continue;	/* read-only */
+			solo_i2c_writebyte(solo_dev, SOLO_I2C_TW,
+					   dev_addr, (ch * 0x10) + i,
+					   tbl_tw2815_common[i]);
+		}
+	}
+
+	for (i = 0x40; i < 0x76; i++) {
+		/* Skip read-only and nop registers */
+		if (i == 0x40 || i == 0x59 || i == 0x5a ||
+		    i == 0x5d || i == 0x5e || i == 0x5f)
+			continue;
+
+		solo_i2c_writebyte(solo_dev, SOLO_I2C_TW, dev_addr, i,
+				       tbl_tw2815_sfr[i - 0x40]);
+	}
+
+	return 0;
+}
+
+#define FIRST_ACTIVE_LINE	0x0008
+#define LAST_ACTIVE_LINE	0x0102
+
+static void saa7128_setup(struct solo_dev *solo_dev)
+{
+	int i;
+	unsigned char regs[128] = {
+		0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x1C, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00,
+		0x59, 0x1d, 0x75, 0x3f, 0x06, 0x3f, 0x00, 0x00,
+		0x1c, 0x33, 0x00, 0x3f, 0x00, 0x00, 0x3f, 0x00,
+		0x1a, 0x1a, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x68, 0x10, 0x97, 0x4c, 0x18,
+		0x9b, 0x93, 0x9f, 0xff, 0x7c, 0x34, 0x3f, 0x3f,
+		0x3f, 0x83, 0x83, 0x80, 0x0d, 0x0f, 0xc3, 0x06,
+		0x02, 0x80, 0x71, 0x77, 0xa7, 0x67, 0x66, 0x2e,
+		0x7b, 0x11, 0x4f, 0x1f, 0x7c, 0xf0, 0x21, 0x77,
+		0x41, 0x88, 0x41, 0x12, 0xed, 0x10, 0x10, 0x00,
+		0x41, 0xc3, 0x00, 0x3e, 0xb8, 0x02, 0x00, 0x00,
+		0x00, 0x00, 0x08, 0xff, 0x80, 0x00, 0xff, 0xff,
+	};
+
+	regs[0x7A] = FIRST_ACTIVE_LINE & 0xff;
+	regs[0x7B] = LAST_ACTIVE_LINE & 0xff;
+	regs[0x7C] = ((1 << 7) |
+			(((LAST_ACTIVE_LINE >> 8) & 1) << 6) |
+			(((FIRST_ACTIVE_LINE >> 8) & 1) << 4));
+
+	/* PAL: XXX: We could do a second set of regs to avoid this */
+	if (solo_dev->video_type != SOLO_VO_FMT_TYPE_NTSC) {
+		regs[0x28] = 0xE1;
+
+		regs[0x5A] = 0x0F;
+		regs[0x61] = 0x02;
+		regs[0x62] = 0x35;
+		regs[0x63] = 0xCB;
+		regs[0x64] = 0x8A;
+		regs[0x65] = 0x09;
+		regs[0x66] = 0x2A;
+
+		regs[0x6C] = 0xf1;
+		regs[0x6E] = 0x20;
+
+		regs[0x7A] = 0x06 + 12;
+		regs[0x7b] = 0x24 + 12;
+		regs[0x7c] |= 1 << 6;
+	}
+
+	/* First 0x25 bytes are read-only? */
+	for (i = 0x26; i < 128; i++) {
+		if (i == 0x60 || i == 0x7D)
+			continue;
+		solo_i2c_writebyte(solo_dev, SOLO_I2C_SAA, 0x46, i, regs[i]);
+	}
+
+	return;
+}
+
+int solo_tw28_init(struct solo_dev *solo_dev)
+{
+	int i;
+	u8 value;
+
+	solo_dev->tw28_cnt = 0;
+
+	/* Detect techwell chip type(s) */
+	for (i = 0; i < solo_dev->nr_chans / 4; i++) {
+		value = solo_i2c_readbyte(solo_dev, SOLO_I2C_TW,
+					  TW_CHIP_OFFSET_ADDR(i), 0xFF);
+
+		switch (value >> 3) {
+		case 0x18:
+			solo_dev->tw2865 |= 1 << i;
+			solo_dev->tw28_cnt++;
+			break;
+		case 0x0c:
+			solo_dev->tw2864 |= 1 << i;
+			solo_dev->tw28_cnt++;
+			break;
+		default:
+			value = solo_i2c_readbyte(solo_dev, SOLO_I2C_TW,
+						  TW_CHIP_OFFSET_ADDR(i),
+						  0x59);
+			if ((value >> 3) == 0x04) {
+				solo_dev->tw2815 |= 1 << i;
+				solo_dev->tw28_cnt++;
+			}
+		}
+	}
+
+	if (solo_dev->tw28_cnt != (solo_dev->nr_chans >> 2)) {
+		dev_err(&solo_dev->pdev->dev,
+			"Could not initialize any techwell chips\n");
+		return -EINVAL;
+	}
+
+	saa7128_setup(solo_dev);
+
+	for (i = 0; i < solo_dev->tw28_cnt; i++) {
+		if ((solo_dev->tw2865 & (1 << i)))
+			tw2865_setup(solo_dev, TW_CHIP_OFFSET_ADDR(i));
+		else if ((solo_dev->tw2864 & (1 << i)))
+			tw2864_setup(solo_dev, TW_CHIP_OFFSET_ADDR(i));
+		else
+			tw2815_setup(solo_dev, TW_CHIP_OFFSET_ADDR(i));
+	}
+
+	return 0;
+}
+
+/*
+ * We accessed the video status signal in the Techwell chip through
+ * iic/i2c because the video status reported by register REG_VI_STATUS1
+ * (address 0x012C) of the SOLO6010 chip doesn't give the correct video
+ * status signal values.
+ */
+int tw28_get_video_status(struct solo_dev *solo_dev, u8 ch)
+{
+	u8 val, chip_num;
+
+	/* Get the right chip and on-chip channel */
+	chip_num = ch / 4;
+	ch %= 4;
+
+	val = tw_readbyte(solo_dev, chip_num, TW286x_AV_STAT_ADDR,
+			  TW_AV_STAT_ADDR) & 0x0f;
+
+	return val & (1 << ch) ? 1 : 0;
+}
+
+#if 0
+/* Status of audio from up to 4 techwell chips are combined into 1 variable.
+ * See techwell datasheet for details. */
+u16 tw28_get_audio_status(struct solo_dev *solo_dev)
+{
+	u8 val;
+	u16 status = 0;
+	int i;
+
+	for (i = 0; i < solo_dev->tw28_cnt; i++) {
+		val = (tw_readbyte(solo_dev, i, TW286x_AV_STAT_ADDR,
+				   TW_AV_STAT_ADDR) & 0xf0) >> 4;
+		status |= val << (i * 4);
+	}
+
+	return status;
+}
+#endif
+
+bool tw28_has_sharpness(struct solo_dev *solo_dev, u8 ch)
+{
+	return is_tw286x(solo_dev, ch / 4);
+}
+
+int tw28_set_ctrl_val(struct solo_dev *solo_dev, u32 ctrl, u8 ch,
+		      s32 val)
+{
+	char sval;
+	u8 chip_num;
+
+	/* Get the right chip and on-chip channel */
+	chip_num = ch / 4;
+	ch %= 4;
+
+	if (val > 255 || val < 0)
+		return -ERANGE;
+
+	switch (ctrl) {
+	case V4L2_CID_SHARPNESS:
+		/* Only 286x has sharpness */
+		if (is_tw286x(solo_dev, chip_num)) {
+			u8 v = solo_i2c_readbyte(solo_dev, SOLO_I2C_TW,
+						 TW_CHIP_OFFSET_ADDR(chip_num),
+						 TW286x_SHARPNESS(chip_num));
+			v &= 0xf0;
+			v |= val;
+			solo_i2c_writebyte(solo_dev, SOLO_I2C_TW,
+					   TW_CHIP_OFFSET_ADDR(chip_num),
+					   TW286x_SHARPNESS(chip_num), v);
+		} else {
+			return -EINVAL;
+		}
+		break;
+
+	case V4L2_CID_HUE:
+		if (is_tw286x(solo_dev, chip_num))
+			sval = val - 128;
+		else
+			sval = (char)val;
+		tw_writebyte(solo_dev, chip_num, TW286x_HUE_ADDR(ch),
+			     TW_HUE_ADDR(ch), sval);
+
+		break;
+
+	case V4L2_CID_SATURATION:
+		/* 286x chips have a U and V component for saturation */
+		if (is_tw286x(solo_dev, chip_num)) {
+			solo_i2c_writebyte(solo_dev, SOLO_I2C_TW,
+					   TW_CHIP_OFFSET_ADDR(chip_num),
+					   TW286x_SATURATIONU_ADDR(ch), val);
+		}
+		tw_writebyte(solo_dev, chip_num, TW286x_SATURATIONV_ADDR(ch),
+			     TW_SATURATION_ADDR(ch), val);
+
+		break;
+
+	case V4L2_CID_CONTRAST:
+		tw_writebyte(solo_dev, chip_num, TW286x_CONTRAST_ADDR(ch),
+			     TW_CONTRAST_ADDR(ch), val);
+		break;
+
+	case V4L2_CID_BRIGHTNESS:
+		if (is_tw286x(solo_dev, chip_num))
+			sval = val - 128;
+		else
+			sval = (char)val;
+		tw_writebyte(solo_dev, chip_num, TW286x_BRIGHTNESS_ADDR(ch),
+			     TW_BRIGHTNESS_ADDR(ch), sval);
+
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+int tw28_get_ctrl_val(struct solo_dev *solo_dev, u32 ctrl, u8 ch,
+		      s32 *val)
+{
+	u8 rval, chip_num;
+
+	/* Get the right chip and on-chip channel */
+	chip_num = ch / 4;
+	ch %= 4;
+
+	switch (ctrl) {
+	case V4L2_CID_SHARPNESS:
+		/* Only 286x has sharpness */
+		if (is_tw286x(solo_dev, chip_num)) {
+			rval = solo_i2c_readbyte(solo_dev, SOLO_I2C_TW,
+						 TW_CHIP_OFFSET_ADDR(chip_num),
+						 TW286x_SHARPNESS(chip_num));
+			*val = rval & 0x0f;
+		} else
+			*val = 0;
+		break;
+	case V4L2_CID_HUE:
+		rval = tw_readbyte(solo_dev, chip_num, TW286x_HUE_ADDR(ch),
+				   TW_HUE_ADDR(ch));
+		if (is_tw286x(solo_dev, chip_num))
+			*val = (s32)((char)rval) + 128;
+		else
+			*val = rval;
+		break;
+	case V4L2_CID_SATURATION:
+		*val = tw_readbyte(solo_dev, chip_num,
+				   TW286x_SATURATIONU_ADDR(ch),
+				   TW_SATURATION_ADDR(ch));
+		break;
+	case V4L2_CID_CONTRAST:
+		*val = tw_readbyte(solo_dev, chip_num,
+				   TW286x_CONTRAST_ADDR(ch),
+				   TW_CONTRAST_ADDR(ch));
+		break;
+	case V4L2_CID_BRIGHTNESS:
+		rval = tw_readbyte(solo_dev, chip_num,
+				   TW286x_BRIGHTNESS_ADDR(ch),
+				   TW_BRIGHTNESS_ADDR(ch));
+		if (is_tw286x(solo_dev, chip_num))
+			*val = (s32)((char)rval) + 128;
+		else
+			*val = rval;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+#if 0
+/*
+ * For audio output volume, the output channel is only 1. In this case we
+ * don't need to offset TW_CHIP_OFFSET_ADDR. The TW_CHIP_OFFSET_ADDR used
+ * is the base address of the techwell chip.
+ */
+void tw2815_Set_AudioOutVol(struct solo_dev *solo_dev, unsigned int u_val)
+{
+	unsigned int val;
+	unsigned int chip_num;
+
+	chip_num = (solo_dev->nr_chans - 1) / 4;
+
+	val = tw_readbyte(solo_dev, chip_num, TW286x_AUDIO_OUTPUT_VOL_ADDR,
+			  TW_AUDIO_OUTPUT_VOL_ADDR);
+
+	u_val = (val & 0x0f) | (u_val << 4);
+
+	tw_writebyte(solo_dev, chip_num, TW286x_AUDIO_OUTPUT_VOL_ADDR,
+		     TW_AUDIO_OUTPUT_VOL_ADDR, u_val);
+}
+#endif
+
+u8 tw28_get_audio_gain(struct solo_dev *solo_dev, u8 ch)
+{
+	u8 val;
+	u8 chip_num;
+
+	/* Get the right chip and on-chip channel */
+	chip_num = ch / 4;
+	ch %= 4;
+
+	val = tw_readbyte(solo_dev, chip_num,
+			  TW286x_AUDIO_INPUT_GAIN_ADDR(ch),
+			  TW_AUDIO_INPUT_GAIN_ADDR(ch));
+
+	return (ch % 2) ? (val >> 4) : (val & 0x0f);
+}
+
+void tw28_set_audio_gain(struct solo_dev *solo_dev, u8 ch, u8 val)
+{
+	u8 old_val;
+	u8 chip_num;
+
+	/* Get the right chip and on-chip channel */
+	chip_num = ch / 4;
+	ch %= 4;
+
+	old_val = tw_readbyte(solo_dev, chip_num,
+			      TW286x_AUDIO_INPUT_GAIN_ADDR(ch),
+			      TW_AUDIO_INPUT_GAIN_ADDR(ch));
+
+	val = (old_val & ((ch % 2) ? 0x0f : 0xf0)) |
+		((ch % 2) ? (val << 4) : val);
+
+	tw_writebyte(solo_dev, chip_num, TW286x_AUDIO_INPUT_GAIN_ADDR(ch),
+		     TW_AUDIO_INPUT_GAIN_ADDR(ch), val);
+}
diff --git a/drivers/staging/media/solo6x10/solo6x10-tw28.h b/drivers/staging/media/solo6x10/solo6x10-tw28.h
new file mode 100644
index 0000000..1a02c87
--- /dev/null
+++ b/drivers/staging/media/solo6x10/solo6x10-tw28.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
+ *
+ * Original author:
+ * Ben Collins <bcollins@ubuntu.com>
+ *
+ * Additional work by:
+ * John Brooks <john.brooks@bluecherry.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You 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 __SOLO6X10_TW28_H
+#define __SOLO6X10_TW28_H
+
+#include "solo6x10.h"
+
+#define TW_NUM_CHIP				4
+#define TW_BASE_ADDR				0x28
+#define TW_CHIP_OFFSET_ADDR(n)			(TW_BASE_ADDR + (n))
+
+/* tw2815 */
+#define TW_AV_STAT_ADDR				0x5a
+#define TW_HUE_ADDR(n)				(0x07 | ((n) << 4))
+#define TW_SATURATION_ADDR(n)			(0x08 | ((n) << 4))
+#define TW_CONTRAST_ADDR(n)			(0x09 | ((n) << 4))
+#define TW_BRIGHTNESS_ADDR(n)			(0x0a | ((n) << 4))
+#define TW_AUDIO_OUTPUT_VOL_ADDR		0x70
+#define TW_AUDIO_INPUT_GAIN_ADDR(n)		(0x60 + ((n > 1) ? 1 : 0))
+
+/* tw286x */
+#define TW286x_AV_STAT_ADDR			0xfd
+#define TW286x_HUE_ADDR(n)			(0x06 | ((n) << 4))
+#define TW286x_SATURATIONU_ADDR(n)		(0x04 | ((n) << 4))
+#define TW286x_SATURATIONV_ADDR(n)		(0x05 | ((n) << 4))
+#define TW286x_CONTRAST_ADDR(n)			(0x02 | ((n) << 4))
+#define TW286x_BRIGHTNESS_ADDR(n)		(0x01 | ((n) << 4))
+#define TW286x_SHARPNESS(n)			(0x03 | ((n) << 4))
+#define TW286x_AUDIO_OUTPUT_VOL_ADDR		0xdf
+#define TW286x_AUDIO_INPUT_GAIN_ADDR(n)		(0xD0 + ((n > 1) ? 1 : 0))
+
+int solo_tw28_init(struct solo_dev *solo_dev);
+
+int tw28_set_ctrl_val(struct solo_dev *solo_dev, u32 ctrl, u8 ch, s32 val);
+int tw28_get_ctrl_val(struct solo_dev *solo_dev, u32 ctrl, u8 ch, s32 *val);
+bool tw28_has_sharpness(struct solo_dev *solo_dev, u8 ch);
+
+u8 tw28_get_audio_gain(struct solo_dev *solo_dev, u8 ch);
+void tw28_set_audio_gain(struct solo_dev *solo_dev, u8 ch, u8 val);
+int tw28_get_video_status(struct solo_dev *solo_dev, u8 ch);
+
+#if 0
+unsigned int tw2815_get_audio_status(struct SOLO *solo);
+void tw2815_Set_AudioOutVol(struct SOLO *solo, unsigned int u_val);
+#endif
+
+#endif /* __SOLO6X10_TW28_H */
diff --git a/drivers/staging/media/solo6x10/solo6x10-v4l2-enc.c b/drivers/staging/media/solo6x10/solo6x10-v4l2-enc.c
new file mode 100644
index 0000000..6c7d20f
--- /dev/null
+++ b/drivers/staging/media/solo6x10/solo6x10-v4l2-enc.c
@@ -0,0 +1,1363 @@
+/*
+ * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
+ *
+ * Original author:
+ * Ben Collins <bcollins@ubuntu.com>
+ *
+ * Additional work by:
+ * John Brooks <john.brooks@bluecherry.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You 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/kthread.h>
+#include <linux/freezer.h>
+
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-event.h>
+#include <media/videobuf2-dma-sg.h>
+
+#include "solo6x10.h"
+#include "solo6x10-tw28.h"
+#include "solo6x10-jpeg.h"
+
+#define MIN_VID_BUFFERS		2
+#define FRAME_BUF_SIZE		(196 * 1024)
+#define MP4_QS			16
+#define DMA_ALIGN		4096
+
+/* 6010 M4V */
+static unsigned char vop_6010_ntsc_d1[] = {
+	0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x20,
+	0x02, 0x48, 0x1d, 0xc0, 0x00, 0x40, 0x00, 0x40,
+	0x00, 0x40, 0x00, 0x80, 0x00, 0x97, 0x53, 0x04,
+	0x1f, 0x4c, 0x58, 0x10, 0xf0, 0x71, 0x18, 0x3f,
+};
+
+static unsigned char vop_6010_ntsc_cif[] = {
+	0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x20,
+	0x02, 0x48, 0x1d, 0xc0, 0x00, 0x40, 0x00, 0x40,
+	0x00, 0x40, 0x00, 0x80, 0x00, 0x97, 0x53, 0x04,
+	0x1f, 0x4c, 0x2c, 0x10, 0x78, 0x51, 0x18, 0x3f,
+};
+
+static unsigned char vop_6010_pal_d1[] = {
+	0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x20,
+	0x02, 0x48, 0x15, 0xc0, 0x00, 0x40, 0x00, 0x40,
+	0x00, 0x40, 0x00, 0x80, 0x00, 0x97, 0x53, 0x04,
+	0x1f, 0x4c, 0x58, 0x11, 0x20, 0x71, 0x18, 0x3f,
+};
+
+static unsigned char vop_6010_pal_cif[] = {
+	0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x20,
+	0x02, 0x48, 0x15, 0xc0, 0x00, 0x40, 0x00, 0x40,
+	0x00, 0x40, 0x00, 0x80, 0x00, 0x97, 0x53, 0x04,
+	0x1f, 0x4c, 0x2c, 0x10, 0x90, 0x51, 0x18, 0x3f,
+};
+
+/* 6110 h.264 */
+static unsigned char vop_6110_ntsc_d1[] = {
+	0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1e,
+	0x9a, 0x74, 0x05, 0x81, 0xec, 0x80, 0x00, 0x00,
+	0x00, 0x01, 0x68, 0xce, 0x32, 0x28, 0x00, 0x00,
+};
+
+static unsigned char vop_6110_ntsc_cif[] = {
+	0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1e,
+	0x9a, 0x74, 0x0b, 0x0f, 0xc8, 0x00, 0x00, 0x00,
+	0x01, 0x68, 0xce, 0x32, 0x28, 0x00, 0x00, 0x00,
+};
+
+static unsigned char vop_6110_pal_d1[] = {
+	0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1e,
+	0x9a, 0x74, 0x05, 0x80, 0x93, 0x20, 0x00, 0x00,
+	0x00, 0x01, 0x68, 0xce, 0x32, 0x28, 0x00, 0x00,
+};
+
+static unsigned char vop_6110_pal_cif[] = {
+	0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1e,
+	0x9a, 0x74, 0x0b, 0x04, 0xb2, 0x00, 0x00, 0x00,
+	0x01, 0x68, 0xce, 0x32, 0x28, 0x00, 0x00, 0x00,
+};
+
+struct vop_header {
+	/* VE_STATUS0 */
+	u32 mpeg_size:20, sad_motion_flag:1, video_motion_flag:1, vop_type:2,
+		channel:5, source_fl:1, interlace:1, progressive:1;
+
+	/* VE_STATUS1 */
+	u32 vsize:8, hsize:8, last_queue:4, nop0:8, scale:4;
+
+	/* VE_STATUS2 */
+	u32 mpeg_off;
+
+	/* VE_STATUS3 */
+	u32 jpeg_off;
+
+	/* VE_STATUS4 */
+	u32 jpeg_size:20, interval:10, nop1:2;
+
+	/* VE_STATUS5/6 */
+	u32 sec, usec;
+
+	/* VE_STATUS7/8/9 */
+	u32 nop2[3];
+
+	/* VE_STATUS10 */
+	u32 mpeg_size_alt:20, nop3:12;
+
+	u32 end_nops[5];
+} __packed;
+
+struct solo_enc_buf {
+	enum solo_enc_types	type;
+	struct vop_header	*vh;
+	int			motion;
+};
+
+static int solo_is_motion_on(struct solo_enc_dev *solo_enc)
+{
+	struct solo_dev *solo_dev = solo_enc->solo_dev;
+
+	return (solo_dev->motion_mask >> solo_enc->ch) & 1;
+}
+
+static int solo_motion_detected(struct solo_enc_dev *solo_enc)
+{
+	struct solo_dev *solo_dev = solo_enc->solo_dev;
+	unsigned long flags;
+	u32 ch_mask = 1 << solo_enc->ch;
+	int ret = 0;
+
+	spin_lock_irqsave(&solo_enc->motion_lock, flags);
+	if (solo_reg_read(solo_dev, SOLO_VI_MOT_STATUS) & ch_mask) {
+		solo_reg_write(solo_dev, SOLO_VI_MOT_CLEAR, ch_mask);
+		ret = 1;
+	}
+	spin_unlock_irqrestore(&solo_enc->motion_lock, flags);
+
+	return ret;
+}
+
+static void solo_motion_toggle(struct solo_enc_dev *solo_enc, int on)
+{
+	struct solo_dev *solo_dev = solo_enc->solo_dev;
+	u32 mask = 1 << solo_enc->ch;
+	unsigned long flags;
+
+	spin_lock_irqsave(&solo_enc->motion_lock, flags);
+
+	if (on)
+		solo_dev->motion_mask |= mask;
+	else
+		solo_dev->motion_mask &= ~mask;
+
+	solo_reg_write(solo_dev, SOLO_VI_MOT_CLEAR, mask);
+
+	solo_reg_write(solo_dev, SOLO_VI_MOT_ADR,
+		       SOLO_VI_MOTION_EN(solo_dev->motion_mask) |
+		       (SOLO_MOTION_EXT_ADDR(solo_dev) >> 16));
+
+	spin_unlock_irqrestore(&solo_enc->motion_lock, flags);
+}
+
+void solo_update_mode(struct solo_enc_dev *solo_enc)
+{
+	struct solo_dev *solo_dev = solo_enc->solo_dev;
+	int vop_len;
+	unsigned char *vop;
+
+	solo_enc->interlaced = (solo_enc->mode & 0x08) ? 1 : 0;
+	solo_enc->bw_weight = max(solo_dev->fps / solo_enc->interval, 1);
+
+	if (solo_enc->mode == SOLO_ENC_MODE_CIF) {
+		solo_enc->width = solo_dev->video_hsize >> 1;
+		solo_enc->height = solo_dev->video_vsize;
+		if (solo_dev->type == SOLO_DEV_6110) {
+			if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) {
+				vop = vop_6110_ntsc_cif;
+				vop_len = sizeof(vop_6110_ntsc_cif);
+			} else {
+				vop = vop_6110_pal_cif;
+				vop_len = sizeof(vop_6110_pal_cif);
+			}
+		} else {
+			if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) {
+				vop = vop_6010_ntsc_cif;
+				vop_len = sizeof(vop_6010_ntsc_cif);
+			} else {
+				vop = vop_6010_pal_cif;
+				vop_len = sizeof(vop_6010_pal_cif);
+			}
+		}
+	} else {
+		solo_enc->width = solo_dev->video_hsize;
+		solo_enc->height = solo_dev->video_vsize << 1;
+		solo_enc->bw_weight <<= 2;
+		if (solo_dev->type == SOLO_DEV_6110) {
+			if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) {
+				vop = vop_6110_ntsc_d1;
+				vop_len = sizeof(vop_6110_ntsc_d1);
+			} else {
+				vop = vop_6110_pal_d1;
+				vop_len = sizeof(vop_6110_pal_d1);
+			}
+		} else {
+			if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) {
+				vop = vop_6010_ntsc_d1;
+				vop_len = sizeof(vop_6010_ntsc_d1);
+			} else {
+				vop = vop_6010_pal_d1;
+				vop_len = sizeof(vop_6010_pal_d1);
+			}
+		}
+	}
+
+	memcpy(solo_enc->vop, vop, vop_len);
+
+	/* Some fixups for 6010/M4V */
+	if (solo_dev->type == SOLO_DEV_6010) {
+		u16 fps = solo_dev->fps * 1000;
+		u16 interval = solo_enc->interval * 1000;
+
+		vop = solo_enc->vop;
+
+		/* Frame rate and interval */
+		vop[22] = fps >> 4;
+		vop[23] = ((fps << 4) & 0xf0) | 0x0c
+			| ((interval >> 13) & 0x3);
+		vop[24] = (interval >> 5) & 0xff;
+		vop[25] = ((interval << 3) & 0xf8) | 0x04;
+	}
+
+	solo_enc->vop_len = vop_len;
+
+	/* Now handle the jpeg header */
+	vop = solo_enc->jpeg_header;
+	vop[SOF0_START + 5] = 0xff & (solo_enc->height >> 8);
+	vop[SOF0_START + 6] = 0xff & solo_enc->height;
+	vop[SOF0_START + 7] = 0xff & (solo_enc->width >> 8);
+	vop[SOF0_START + 8] = 0xff & solo_enc->width;
+
+	memcpy(vop + DQT_START,
+	       jpeg_dqt[solo_g_jpeg_qp(solo_dev, solo_enc->ch)], DQT_LEN);
+}
+
+static int solo_enc_on(struct solo_enc_dev *solo_enc)
+{
+	u8 ch = solo_enc->ch;
+	struct solo_dev *solo_dev = solo_enc->solo_dev;
+	u8 interval;
+
+	solo_update_mode(solo_enc);
+
+	/* Make sure to do a bandwidth check */
+	if (solo_enc->bw_weight > solo_dev->enc_bw_remain)
+		return -EBUSY;
+	solo_enc->sequence = 0;
+	solo_dev->enc_bw_remain -= solo_enc->bw_weight;
+
+	if (solo_enc->type == SOLO_ENC_TYPE_EXT)
+		solo_reg_write(solo_dev, SOLO_CAP_CH_COMP_ENA_E(ch), 1);
+
+	/* Disable all encoding for this channel */
+	solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(ch), 0);
+
+	/* Common for both std and ext encoding */
+	solo_reg_write(solo_dev, SOLO_VE_CH_INTL(ch),
+		       solo_enc->interlaced ? 1 : 0);
+
+	if (solo_enc->interlaced)
+		interval = solo_enc->interval - 1;
+	else
+		interval = solo_enc->interval;
+
+	/* Standard encoding only */
+	solo_reg_write(solo_dev, SOLO_VE_CH_GOP(ch), solo_enc->gop);
+	solo_reg_write(solo_dev, SOLO_VE_CH_QP(ch), solo_enc->qp);
+	solo_reg_write(solo_dev, SOLO_CAP_CH_INTV(ch), interval);
+
+	/* Extended encoding only */
+	solo_reg_write(solo_dev, SOLO_VE_CH_GOP_E(ch), solo_enc->gop);
+	solo_reg_write(solo_dev, SOLO_VE_CH_QP_E(ch), solo_enc->qp);
+	solo_reg_write(solo_dev, SOLO_CAP_CH_INTV_E(ch), interval);
+
+	/* Enables the standard encoder */
+	solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(ch), solo_enc->mode);
+
+	return 0;
+}
+
+static void solo_enc_off(struct solo_enc_dev *solo_enc)
+{
+	struct solo_dev *solo_dev = solo_enc->solo_dev;
+
+	solo_dev->enc_bw_remain += solo_enc->bw_weight;
+
+	solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(solo_enc->ch), 0);
+	solo_reg_write(solo_dev, SOLO_CAP_CH_COMP_ENA_E(solo_enc->ch), 0);
+}
+
+static int enc_get_mpeg_dma(struct solo_dev *solo_dev, dma_addr_t dma,
+			      unsigned int off, unsigned int size)
+{
+	int ret;
+
+	if (off > SOLO_MP4E_EXT_SIZE(solo_dev))
+		return -EINVAL;
+
+	/* Single shot */
+	if (off + size <= SOLO_MP4E_EXT_SIZE(solo_dev)) {
+		return solo_p2m_dma_t(solo_dev, 0, dma,
+				      SOLO_MP4E_EXT_ADDR(solo_dev) + off, size,
+				      0, 0);
+	}
+
+	/* Buffer wrap */
+	ret = solo_p2m_dma_t(solo_dev, 0, dma,
+			     SOLO_MP4E_EXT_ADDR(solo_dev) + off,
+			     SOLO_MP4E_EXT_SIZE(solo_dev) - off, 0, 0);
+
+	if (!ret) {
+		ret = solo_p2m_dma_t(solo_dev, 0,
+			     dma + SOLO_MP4E_EXT_SIZE(solo_dev) - off,
+			     SOLO_MP4E_EXT_ADDR(solo_dev),
+			     size + off - SOLO_MP4E_EXT_SIZE(solo_dev), 0, 0);
+	}
+
+	return ret;
+}
+
+/* Build a descriptor queue out of an SG list and send it to the P2M for
+ * processing. */
+static int solo_send_desc(struct solo_enc_dev *solo_enc, int skip,
+			  struct vb2_dma_sg_desc *vbuf, int off, int size,
+			  unsigned int base, unsigned int base_size)
+{
+	struct solo_dev *solo_dev = solo_enc->solo_dev;
+	struct scatterlist *sg;
+	int i;
+	int ret;
+
+	if (WARN_ON_ONCE(size > FRAME_BUF_SIZE))
+		return -EINVAL;
+
+	solo_enc->desc_count = 1;
+
+	for_each_sg(vbuf->sglist, sg, vbuf->num_pages, i) {
+		struct solo_p2m_desc *desc;
+		dma_addr_t dma;
+		int len;
+		int left = base_size - off;
+
+		desc = &solo_enc->desc_items[solo_enc->desc_count++];
+		dma = sg_dma_address(sg);
+		len = sg_dma_len(sg);
+
+		/* We assume this is smaller than the scatter size */
+		BUG_ON(skip >= len);
+		if (skip) {
+			len -= skip;
+			dma += skip;
+			size -= skip;
+			skip = 0;
+		}
+
+		len = min(len, size);
+
+		if (len <= left) {
+			/* Single descriptor */
+			solo_p2m_fill_desc(desc, 0, dma, base + off,
+					   len, 0, 0);
+		} else {
+			/* Buffer wrap */
+			/* XXX: Do these as separate DMA requests, to avoid
+			   timeout errors triggered by awkwardly sized
+			   descriptors. See
+			   <https://github.com/bluecherrydvr/solo6x10/issues/8>
+			 */
+			ret = solo_p2m_dma_t(solo_dev, 0, dma, base + off,
+					     left, 0, 0);
+			if (ret)
+				return ret;
+
+			ret = solo_p2m_dma_t(solo_dev, 0, dma + left, base,
+					     len - left, 0, 0);
+			if (ret)
+				return ret;
+
+			solo_enc->desc_count--;
+		}
+
+		size -= len;
+		if (size <= 0)
+			break;
+
+		off += len;
+		if (off >= base_size)
+			off -= base_size;
+
+		/* Because we may use two descriptors per loop */
+		if (solo_enc->desc_count >= (solo_enc->desc_nelts - 1)) {
+			ret = solo_p2m_dma_desc(solo_dev, solo_enc->desc_items,
+						solo_enc->desc_dma,
+						solo_enc->desc_count - 1);
+			if (ret)
+				return ret;
+			solo_enc->desc_count = 1;
+		}
+	}
+
+	if (solo_enc->desc_count <= 1)
+		return 0;
+
+	return solo_p2m_dma_desc(solo_dev, solo_enc->desc_items, solo_enc->desc_dma,
+				 solo_enc->desc_count - 1);
+}
+
+static int solo_fill_jpeg(struct solo_enc_dev *solo_enc,
+		struct vb2_buffer *vb, struct vop_header *vh)
+{
+	struct solo_dev *solo_dev = solo_enc->solo_dev;
+	struct vb2_dma_sg_desc *vbuf = vb2_dma_sg_plane_desc(vb, 0);
+	int frame_size;
+	int ret;
+
+	vb->v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME;
+
+	if (vb2_plane_size(vb, 0) < vh->jpeg_size + solo_enc->jpeg_len)
+		return -EIO;
+
+	sg_copy_from_buffer(vbuf->sglist, vbuf->num_pages,
+			solo_enc->jpeg_header,
+			solo_enc->jpeg_len);
+
+	frame_size = (vh->jpeg_size + solo_enc->jpeg_len + (DMA_ALIGN - 1))
+		& ~(DMA_ALIGN - 1);
+	vb2_set_plane_payload(vb, 0, vh->jpeg_size + solo_enc->jpeg_len);
+
+	dma_map_sg(&solo_dev->pdev->dev, vbuf->sglist, vbuf->num_pages,
+			DMA_FROM_DEVICE);
+	ret = solo_send_desc(solo_enc, solo_enc->jpeg_len, vbuf, vh->jpeg_off,
+			frame_size, SOLO_JPEG_EXT_ADDR(solo_dev),
+			SOLO_JPEG_EXT_SIZE(solo_dev));
+	dma_unmap_sg(&solo_dev->pdev->dev, vbuf->sglist, vbuf->num_pages,
+			DMA_FROM_DEVICE);
+	return ret;
+}
+
+static int solo_fill_mpeg(struct solo_enc_dev *solo_enc,
+		struct vb2_buffer *vb, struct vop_header *vh)
+{
+	struct solo_dev *solo_dev = solo_enc->solo_dev;
+	struct vb2_dma_sg_desc *vbuf = vb2_dma_sg_plane_desc(vb, 0);
+	int frame_off, frame_size;
+	int skip = 0;
+	int ret;
+
+	if (vb2_plane_size(vb, 0) < vh->mpeg_size)
+		return -EIO;
+
+	/* If this is a key frame, add extra header */
+	if (!vh->vop_type) {
+		sg_copy_from_buffer(vbuf->sglist, vbuf->num_pages,
+				solo_enc->vop,
+				solo_enc->vop_len);
+
+		skip = solo_enc->vop_len;
+
+		vb->v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME;
+		vb2_set_plane_payload(vb, 0, vh->mpeg_size + solo_enc->vop_len);
+	} else {
+		vb->v4l2_buf.flags |= V4L2_BUF_FLAG_PFRAME;
+		vb2_set_plane_payload(vb, 0, vh->mpeg_size);
+	}
+
+	/* Now get the actual mpeg payload */
+	frame_off = (vh->mpeg_off + sizeof(*vh))
+		% SOLO_MP4E_EXT_SIZE(solo_dev);
+	frame_size = (vh->mpeg_size + skip + (DMA_ALIGN - 1))
+		& ~(DMA_ALIGN - 1);
+
+	dma_map_sg(&solo_dev->pdev->dev, vbuf->sglist, vbuf->num_pages,
+			DMA_FROM_DEVICE);
+	ret = solo_send_desc(solo_enc, skip, vbuf, frame_off, frame_size,
+			SOLO_MP4E_EXT_ADDR(solo_dev),
+			SOLO_MP4E_EXT_SIZE(solo_dev));
+	dma_unmap_sg(&solo_dev->pdev->dev, vbuf->sglist, vbuf->num_pages,
+			DMA_FROM_DEVICE);
+	return ret;
+}
+
+static int solo_enc_fillbuf(struct solo_enc_dev *solo_enc,
+			    struct vb2_buffer *vb, struct solo_enc_buf *enc_buf)
+{
+	struct vop_header *vh = enc_buf->vh;
+	int ret;
+
+	/* Check for motion flags */
+	vb->v4l2_buf.flags &= ~(V4L2_BUF_FLAG_MOTION_ON |
+				V4L2_BUF_FLAG_MOTION_DETECTED);
+	if (solo_is_motion_on(solo_enc)) {
+		vb->v4l2_buf.flags |= V4L2_BUF_FLAG_MOTION_ON;
+		if (enc_buf->motion)
+			vb->v4l2_buf.flags |= V4L2_BUF_FLAG_MOTION_DETECTED;
+	}
+
+	if (solo_enc->fmt == V4L2_PIX_FMT_MPEG4)
+		ret = solo_fill_mpeg(solo_enc, vb, vh);
+	else
+		ret = solo_fill_jpeg(solo_enc, vb, vh);
+
+	if (!ret) {
+		vb->v4l2_buf.sequence = solo_enc->sequence++;
+		vb->v4l2_buf.timestamp.tv_sec = vh->sec;
+		vb->v4l2_buf.timestamp.tv_usec = vh->usec;
+	}
+
+	vb2_buffer_done(vb, ret ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
+
+	return ret;
+}
+
+static void solo_enc_handle_one(struct solo_enc_dev *solo_enc,
+				struct solo_enc_buf *enc_buf)
+{
+	struct solo_vb2_buf *vb;
+	unsigned long flags;
+
+	mutex_lock(&solo_enc->lock);
+	if (solo_enc->type != enc_buf->type)
+		goto unlock;
+
+	spin_lock_irqsave(&solo_enc->av_lock, flags);
+	if (list_empty(&solo_enc->vidq_active)) {
+		spin_unlock_irqrestore(&solo_enc->av_lock, flags);
+		goto unlock;
+	}
+	vb = list_first_entry(&solo_enc->vidq_active, struct solo_vb2_buf, list);
+	list_del(&vb->list);
+	spin_unlock_irqrestore(&solo_enc->av_lock, flags);
+
+	solo_enc_fillbuf(solo_enc, &vb->vb, enc_buf);
+unlock:
+	mutex_unlock(&solo_enc->lock);
+}
+
+void solo_enc_v4l2_isr(struct solo_dev *solo_dev)
+{
+	wake_up_interruptible_all(&solo_dev->ring_thread_wait);
+}
+
+static void solo_handle_ring(struct solo_dev *solo_dev)
+{
+	for (;;) {
+		struct solo_enc_dev *solo_enc;
+		struct solo_enc_buf enc_buf;
+		u32 mpeg_current, off;
+		u8 ch;
+		u8 cur_q;
+
+		/* Check if the hardware has any new ones in the queue */
+		cur_q = solo_reg_read(solo_dev, SOLO_VE_STATE(11)) & 0xff;
+		if (cur_q == solo_dev->enc_idx)
+			break;
+
+		mpeg_current = solo_reg_read(solo_dev,
+					SOLO_VE_MPEG4_QUE(solo_dev->enc_idx));
+		solo_dev->enc_idx = (solo_dev->enc_idx + 1) % MP4_QS;
+
+		ch = (mpeg_current >> 24) & 0x1f;
+		off = mpeg_current & 0x00ffffff;
+
+		if (ch >= SOLO_MAX_CHANNELS) {
+			ch -= SOLO_MAX_CHANNELS;
+			enc_buf.type = SOLO_ENC_TYPE_EXT;
+		} else
+			enc_buf.type = SOLO_ENC_TYPE_STD;
+
+		solo_enc = solo_dev->v4l2_enc[ch];
+		if (solo_enc == NULL) {
+			dev_err(&solo_dev->pdev->dev,
+				"Got spurious packet for channel %d\n", ch);
+			continue;
+		}
+
+		/* FAIL... */
+		if (enc_get_mpeg_dma(solo_dev, solo_dev->vh_dma, off,
+				     sizeof(struct vop_header)))
+			continue;
+
+		enc_buf.vh = (struct vop_header *)solo_dev->vh_buf;
+		enc_buf.vh->mpeg_off -= SOLO_MP4E_EXT_ADDR(solo_dev);
+		enc_buf.vh->jpeg_off -= SOLO_JPEG_EXT_ADDR(solo_dev);
+
+		/* Sanity check */
+		if (enc_buf.vh->mpeg_off != off)
+			continue;
+
+		if (solo_motion_detected(solo_enc))
+			enc_buf.motion = 1;
+		else
+			enc_buf.motion = 0;
+
+		solo_enc_handle_one(solo_enc, &enc_buf);
+	}
+}
+
+static int solo_ring_thread(void *data)
+{
+	struct solo_dev *solo_dev = data;
+	DECLARE_WAITQUEUE(wait, current);
+
+	set_freezable();
+	add_wait_queue(&solo_dev->ring_thread_wait, &wait);
+
+	for (;;) {
+		long timeout = schedule_timeout_interruptible(HZ);
+		if (timeout == -ERESTARTSYS || kthread_should_stop())
+			break;
+		solo_irq_off(solo_dev, SOLO_IRQ_ENCODER);
+		solo_handle_ring(solo_dev);
+		solo_irq_on(solo_dev, SOLO_IRQ_ENCODER);
+		try_to_freeze();
+	}
+
+	remove_wait_queue(&solo_dev->ring_thread_wait, &wait);
+
+	return 0;
+}
+
+static int solo_enc_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+			   unsigned int *num_buffers, unsigned int *num_planes,
+			   unsigned int sizes[], void *alloc_ctxs[])
+{
+	sizes[0] = FRAME_BUF_SIZE;
+	*num_planes = 1;
+
+	if (*num_buffers < MIN_VID_BUFFERS)
+		*num_buffers = MIN_VID_BUFFERS;
+
+	return 0;
+}
+
+static void solo_enc_buf_queue(struct vb2_buffer *vb)
+{
+	struct vb2_queue *vq = vb->vb2_queue;
+	struct solo_enc_dev *solo_enc = vb2_get_drv_priv(vq);
+	struct solo_vb2_buf *solo_vb =
+		container_of(vb, struct solo_vb2_buf, vb);
+
+	spin_lock(&solo_enc->av_lock);
+	list_add_tail(&solo_vb->list, &solo_enc->vidq_active);
+	spin_unlock(&solo_enc->av_lock);
+}
+
+static int solo_ring_start(struct solo_dev *solo_dev)
+{
+	solo_dev->ring_thread = kthread_run(solo_ring_thread, solo_dev,
+					    SOLO6X10_NAME "_ring");
+	if (IS_ERR(solo_dev->ring_thread)) {
+		int err = PTR_ERR(solo_dev->ring_thread);
+		solo_dev->ring_thread = NULL;
+		return err;
+	}
+
+	solo_irq_on(solo_dev, SOLO_IRQ_ENCODER);
+
+	return 0;
+}
+
+static void solo_ring_stop(struct solo_dev *solo_dev)
+{
+	if (solo_dev->ring_thread) {
+		kthread_stop(solo_dev->ring_thread);
+		solo_dev->ring_thread = NULL;
+	}
+
+	solo_irq_off(solo_dev, SOLO_IRQ_ENCODER);
+}
+
+static int solo_enc_start_streaming(struct vb2_queue *q, unsigned int count)
+{
+	struct solo_enc_dev *solo_enc = vb2_get_drv_priv(q);
+	int ret;
+
+	ret = solo_enc_on(solo_enc);
+	if (ret)
+		return ret;
+	return solo_ring_start(solo_enc->solo_dev);
+}
+
+static int solo_enc_stop_streaming(struct vb2_queue *q)
+{
+	struct solo_enc_dev *solo_enc = vb2_get_drv_priv(q);
+
+	solo_enc_off(solo_enc);
+	INIT_LIST_HEAD(&solo_enc->vidq_active);
+	solo_ring_stop(solo_enc->solo_dev);
+	return 0;
+}
+
+static struct vb2_ops solo_enc_video_qops = {
+	.queue_setup	= solo_enc_queue_setup,
+	.buf_queue	= solo_enc_buf_queue,
+	.start_streaming = solo_enc_start_streaming,
+	.stop_streaming = solo_enc_stop_streaming,
+	.wait_prepare	= vb2_ops_wait_prepare,
+	.wait_finish	= vb2_ops_wait_finish,
+};
+
+static int solo_enc_querycap(struct file *file, void  *priv,
+			     struct v4l2_capability *cap)
+{
+	struct solo_enc_dev *solo_enc = video_drvdata(file);
+	struct solo_dev *solo_dev = solo_enc->solo_dev;
+
+	strcpy(cap->driver, SOLO6X10_NAME);
+	snprintf(cap->card, sizeof(cap->card), "Softlogic 6x10 Enc %d",
+		 solo_enc->ch);
+	snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s",
+		 pci_name(solo_dev->pdev));
+	cap->device_caps = V4L2_CAP_VIDEO_CAPTURE |
+			V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
+	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+	return 0;
+}
+
+static int solo_enc_enum_input(struct file *file, void *priv,
+			       struct v4l2_input *input)
+{
+	struct solo_enc_dev *solo_enc = video_drvdata(file);
+	struct solo_dev *solo_dev = solo_enc->solo_dev;
+
+	if (input->index)
+		return -EINVAL;
+
+	snprintf(input->name, sizeof(input->name), "Encoder %d",
+		 solo_enc->ch + 1);
+	input->type = V4L2_INPUT_TYPE_CAMERA;
+	input->std = solo_enc->vfd->tvnorms;
+
+	if (!tw28_get_video_status(solo_dev, solo_enc->ch))
+		input->status = V4L2_IN_ST_NO_SIGNAL;
+
+	return 0;
+}
+
+static int solo_enc_set_input(struct file *file, void *priv,
+			      unsigned int index)
+{
+	if (index)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int solo_enc_get_input(struct file *file, void *priv,
+			      unsigned int *index)
+{
+	*index = 0;
+
+	return 0;
+}
+
+static int solo_enc_enum_fmt_cap(struct file *file, void *priv,
+				 struct v4l2_fmtdesc *f)
+{
+	switch (f->index) {
+	case 0:
+		f->pixelformat = V4L2_PIX_FMT_MPEG4;
+		strcpy(f->description, "MPEG-4 AVC");
+		break;
+	case 1:
+		f->pixelformat = V4L2_PIX_FMT_MJPEG;
+		strcpy(f->description, "MJPEG");
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	f->flags = V4L2_FMT_FLAG_COMPRESSED;
+
+	return 0;
+}
+
+static int solo_enc_try_fmt_cap(struct file *file, void *priv,
+			    struct v4l2_format *f)
+{
+	struct solo_enc_dev *solo_enc = video_drvdata(file);
+	struct solo_dev *solo_dev = solo_enc->solo_dev;
+	struct v4l2_pix_format *pix = &f->fmt.pix;
+
+	if (pix->pixelformat != V4L2_PIX_FMT_MPEG4 &&
+	    pix->pixelformat != V4L2_PIX_FMT_MJPEG)
+		return -EINVAL;
+
+	if (pix->width < solo_dev->video_hsize ||
+	    pix->height < solo_dev->video_vsize << 1) {
+		/* Default to CIF 1/2 size */
+		pix->width = solo_dev->video_hsize >> 1;
+		pix->height = solo_dev->video_vsize;
+	} else {
+		/* Full frame */
+		pix->width = solo_dev->video_hsize;
+		pix->height = solo_dev->video_vsize << 1;
+	}
+
+	switch (pix->field) {
+	case V4L2_FIELD_NONE:
+	case V4L2_FIELD_INTERLACED:
+		break;
+	case V4L2_FIELD_ANY:
+	default:
+		pix->field = V4L2_FIELD_INTERLACED;
+		break;
+	}
+
+	/* Just set these */
+	pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
+	pix->sizeimage = FRAME_BUF_SIZE;
+	pix->bytesperline = 0;
+	pix->priv = 0;
+
+	return 0;
+}
+
+static int solo_enc_set_fmt_cap(struct file *file, void *priv,
+				struct v4l2_format *f)
+{
+	struct solo_enc_dev *solo_enc = video_drvdata(file);
+	struct solo_dev *solo_dev = solo_enc->solo_dev;
+	struct v4l2_pix_format *pix = &f->fmt.pix;
+	int ret;
+
+	if (vb2_is_busy(&solo_enc->vidq))
+		return -EBUSY;
+
+	ret = solo_enc_try_fmt_cap(file, priv, f);
+	if (ret)
+		return ret;
+
+	if (pix->width == solo_dev->video_hsize)
+		solo_enc->mode = SOLO_ENC_MODE_D1;
+	else
+		solo_enc->mode = SOLO_ENC_MODE_CIF;
+
+	/* This does not change the encoder at all */
+	solo_enc->fmt = pix->pixelformat;
+
+	/*
+	 * More information is needed about these 'extended' types. As far
+	 * as I can tell these are basically additional video streams with
+	 * different MPEG encoding attributes that can run in parallel with
+	 * the main stream. If so, then this should be implemented as a
+	 * second video node. Abusing priv like this is certainly not the
+	 * right approach.
+	if (pix->priv)
+		solo_enc->type = SOLO_ENC_TYPE_EXT;
+	 */
+	return 0;
+}
+
+static int solo_enc_get_fmt_cap(struct file *file, void *priv,
+				struct v4l2_format *f)
+{
+	struct solo_enc_dev *solo_enc = video_drvdata(file);
+	struct v4l2_pix_format *pix = &f->fmt.pix;
+
+	pix->width = solo_enc->width;
+	pix->height = solo_enc->height;
+	pix->pixelformat = solo_enc->fmt;
+	pix->field = solo_enc->interlaced ? V4L2_FIELD_INTERLACED :
+		     V4L2_FIELD_NONE;
+	pix->sizeimage = FRAME_BUF_SIZE;
+	pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
+	pix->priv = 0;
+
+	return 0;
+}
+
+static int solo_enc_g_std(struct file *file, void *priv, v4l2_std_id *i)
+{
+	struct solo_enc_dev *solo_enc = video_drvdata(file);
+	struct solo_dev *solo_dev = solo_enc->solo_dev;
+
+	if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC)
+		*i = V4L2_STD_NTSC_M;
+	else
+		*i = V4L2_STD_PAL;
+	return 0;
+}
+
+static int solo_enc_s_std(struct file *file, void *priv, v4l2_std_id std)
+{
+	struct solo_enc_dev *solo_enc = video_drvdata(file);
+
+	return solo_set_video_type(solo_enc->solo_dev, std & V4L2_STD_PAL);
+}
+
+static int solo_enum_framesizes(struct file *file, void *priv,
+				struct v4l2_frmsizeenum *fsize)
+{
+	struct solo_enc_dev *solo_enc = video_drvdata(file);
+	struct solo_dev *solo_dev = solo_enc->solo_dev;
+
+	if (fsize->pixel_format != V4L2_PIX_FMT_MPEG4 &&
+	    fsize->pixel_format != V4L2_PIX_FMT_MJPEG)
+		return -EINVAL;
+
+	switch (fsize->index) {
+	case 0:
+		fsize->discrete.width = solo_dev->video_hsize >> 1;
+		fsize->discrete.height = solo_dev->video_vsize;
+		break;
+	case 1:
+		fsize->discrete.width = solo_dev->video_hsize;
+		fsize->discrete.height = solo_dev->video_vsize << 1;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+
+	return 0;
+}
+
+static int solo_enum_frameintervals(struct file *file, void *priv,
+				    struct v4l2_frmivalenum *fintv)
+{
+	struct solo_enc_dev *solo_enc = video_drvdata(file);
+	struct solo_dev *solo_dev = solo_enc->solo_dev;
+
+	if (fintv->pixel_format != V4L2_PIX_FMT_MPEG4 &&
+	    fintv->pixel_format != V4L2_PIX_FMT_MJPEG)
+		return -EINVAL;
+	if (fintv->index)
+		return -EINVAL;
+	if ((fintv->width != solo_dev->video_hsize >> 1 ||
+	     fintv->height != solo_dev->video_vsize) &&
+	    (fintv->width != solo_dev->video_hsize ||
+	     fintv->height != solo_dev->video_vsize << 1))
+		return -EINVAL;
+
+	fintv->type = V4L2_FRMIVAL_TYPE_STEPWISE;
+
+	fintv->stepwise.min.numerator = 1;
+	fintv->stepwise.min.denominator = solo_dev->fps;
+
+	fintv->stepwise.max.numerator = 15;
+	fintv->stepwise.max.denominator = solo_dev->fps;
+
+	fintv->stepwise.step.numerator = 1;
+	fintv->stepwise.step.denominator = solo_dev->fps;
+
+	return 0;
+}
+
+static int solo_g_parm(struct file *file, void *priv,
+		       struct v4l2_streamparm *sp)
+{
+	struct solo_enc_dev *solo_enc = video_drvdata(file);
+	struct solo_dev *solo_dev = solo_enc->solo_dev;
+	struct v4l2_captureparm *cp = &sp->parm.capture;
+
+	cp->capability = V4L2_CAP_TIMEPERFRAME;
+	cp->timeperframe.numerator = solo_enc->interval;
+	cp->timeperframe.denominator = solo_dev->fps;
+	cp->capturemode = 0;
+	/* XXX: Shouldn't we be able to get/set this from videobuf? */
+	cp->readbuffers = 2;
+
+	return 0;
+}
+
+static int solo_s_parm(struct file *file, void *priv,
+		       struct v4l2_streamparm *sp)
+{
+	struct solo_enc_dev *solo_enc = video_drvdata(file);
+	struct solo_dev *solo_dev = solo_enc->solo_dev;
+	struct v4l2_captureparm *cp = &sp->parm.capture;
+
+	if (vb2_is_streaming(&solo_enc->vidq))
+		return -EBUSY;
+
+	if ((cp->timeperframe.numerator == 0) ||
+	    (cp->timeperframe.denominator == 0)) {
+		/* reset framerate */
+		cp->timeperframe.numerator = 1;
+		cp->timeperframe.denominator = solo_dev->fps;
+	}
+
+	if (cp->timeperframe.denominator != solo_dev->fps)
+		cp->timeperframe.denominator = solo_dev->fps;
+
+	if (cp->timeperframe.numerator > 15)
+		cp->timeperframe.numerator = 15;
+
+	solo_enc->interval = cp->timeperframe.numerator;
+
+	cp->capability = V4L2_CAP_TIMEPERFRAME;
+	cp->readbuffers = 2;
+
+	solo_update_mode(solo_enc);
+	return 0;
+}
+
+static long solo_enc_default(struct file *file, void *fh,
+			bool valid_prio, unsigned int cmd, void *arg)
+{
+	struct solo_enc_dev *solo_enc = video_drvdata(file);
+	struct solo_dev *solo_dev = solo_enc->solo_dev;
+	struct solo_motion_thresholds *thresholds = arg;
+
+	switch (cmd) {
+	case SOLO_IOC_G_MOTION_THRESHOLDS:
+		*thresholds = solo_enc->motion_thresholds;
+		return 0;
+
+	case SOLO_IOC_S_MOTION_THRESHOLDS:
+		if (!valid_prio)
+			return -EBUSY;
+		solo_enc->motion_thresholds = *thresholds;
+		if (solo_enc->motion_enabled && !solo_enc->motion_global)
+			return solo_set_motion_block(solo_dev, solo_enc->ch,
+						&solo_enc->motion_thresholds);
+		return 0;
+	default:
+		return -ENOTTY;
+	}
+}
+
+static int solo_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct solo_enc_dev *solo_enc =
+		container_of(ctrl->handler, struct solo_enc_dev, hdl);
+	struct solo_dev *solo_dev = solo_enc->solo_dev;
+	int err;
+
+	switch (ctrl->id) {
+	case V4L2_CID_BRIGHTNESS:
+	case V4L2_CID_CONTRAST:
+	case V4L2_CID_SATURATION:
+	case V4L2_CID_HUE:
+	case V4L2_CID_SHARPNESS:
+		return tw28_set_ctrl_val(solo_dev, ctrl->id, solo_enc->ch,
+					 ctrl->val);
+	case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
+		solo_enc->gop = ctrl->val;
+		return 0;
+	case V4L2_CID_MOTION_THRESHOLD:
+		solo_enc->motion_thresh = ctrl->val;
+		if (!solo_enc->motion_global || !solo_enc->motion_enabled)
+			return 0;
+		return solo_set_motion_threshold(solo_dev, solo_enc->ch, ctrl->val);
+	case V4L2_CID_MOTION_MODE:
+		solo_enc->motion_global = ctrl->val == 1;
+		solo_enc->motion_enabled = ctrl->val > 0;
+		if (ctrl->val) {
+			if (solo_enc->motion_global)
+				solo_set_motion_threshold(solo_dev, solo_enc->ch,
+						solo_enc->motion_thresh);
+			else
+				solo_set_motion_block(solo_dev, solo_enc->ch,
+						&solo_enc->motion_thresholds);
+		}
+		solo_motion_toggle(solo_enc, ctrl->val);
+		return 0;
+	case V4L2_CID_OSD_TEXT:
+		strcpy(solo_enc->osd_text, ctrl->string);
+		err = solo_osd_print(solo_enc);
+		return err;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static const struct v4l2_file_operations solo_enc_fops = {
+	.owner			= THIS_MODULE,
+	.open			= v4l2_fh_open,
+	.release		= vb2_fop_release,
+	.read			= vb2_fop_read,
+	.poll			= vb2_fop_poll,
+	.mmap			= vb2_fop_mmap,
+	.unlocked_ioctl		= video_ioctl2,
+};
+
+static const struct v4l2_ioctl_ops solo_enc_ioctl_ops = {
+	.vidioc_querycap		= solo_enc_querycap,
+	.vidioc_s_std			= solo_enc_s_std,
+	.vidioc_g_std			= solo_enc_g_std,
+	/* Input callbacks */
+	.vidioc_enum_input		= solo_enc_enum_input,
+	.vidioc_s_input			= solo_enc_set_input,
+	.vidioc_g_input			= solo_enc_get_input,
+	/* Video capture format callbacks */
+	.vidioc_enum_fmt_vid_cap	= solo_enc_enum_fmt_cap,
+	.vidioc_try_fmt_vid_cap		= solo_enc_try_fmt_cap,
+	.vidioc_s_fmt_vid_cap		= solo_enc_set_fmt_cap,
+	.vidioc_g_fmt_vid_cap		= solo_enc_get_fmt_cap,
+	/* Streaming I/O */
+	.vidioc_reqbufs			= vb2_ioctl_reqbufs,
+	.vidioc_querybuf		= vb2_ioctl_querybuf,
+	.vidioc_qbuf			= vb2_ioctl_qbuf,
+	.vidioc_dqbuf			= vb2_ioctl_dqbuf,
+	.vidioc_streamon		= vb2_ioctl_streamon,
+	.vidioc_streamoff		= vb2_ioctl_streamoff,
+	/* Frame size and interval */
+	.vidioc_enum_framesizes		= solo_enum_framesizes,
+	.vidioc_enum_frameintervals	= solo_enum_frameintervals,
+	/* Video capture parameters */
+	.vidioc_s_parm			= solo_s_parm,
+	.vidioc_g_parm			= solo_g_parm,
+	/* Logging and events */
+	.vidioc_log_status		= v4l2_ctrl_log_status,
+	.vidioc_subscribe_event		= v4l2_ctrl_subscribe_event,
+	.vidioc_unsubscribe_event	= v4l2_event_unsubscribe,
+	.vidioc_default			= solo_enc_default,
+};
+
+static const struct video_device solo_enc_template = {
+	.name			= SOLO6X10_NAME,
+	.fops			= &solo_enc_fops,
+	.ioctl_ops		= &solo_enc_ioctl_ops,
+	.minor			= -1,
+	.release		= video_device_release,
+	.tvnorms		= V4L2_STD_NTSC_M | V4L2_STD_PAL,
+};
+
+static const struct v4l2_ctrl_ops solo_ctrl_ops = {
+	.s_ctrl = solo_s_ctrl,
+};
+
+static const struct v4l2_ctrl_config solo_motion_threshold_ctrl = {
+	.ops = &solo_ctrl_ops,
+	.id = V4L2_CID_MOTION_THRESHOLD,
+	.name = "Motion Detection Threshold",
+	.type = V4L2_CTRL_TYPE_INTEGER,
+	.max = 0xffff,
+	.def = SOLO_DEF_MOT_THRESH,
+	.step = 1,
+	.flags = V4L2_CTRL_FLAG_SLIDER,
+};
+
+static const char * const solo_motion_mode_menu[] = {
+	"Disabled",
+	"Global Threshold",
+	"Regional Threshold",
+	NULL
+};
+
+static const struct v4l2_ctrl_config solo_motion_enable_ctrl = {
+	.ops = &solo_ctrl_ops,
+	.id = V4L2_CID_MOTION_MODE,
+	.name = "Motion Detection Mode",
+	.type = V4L2_CTRL_TYPE_MENU,
+	.qmenu = solo_motion_mode_menu,
+	.max = 2,
+};
+
+static const struct v4l2_ctrl_config solo_osd_text_ctrl = {
+	.ops = &solo_ctrl_ops,
+	.id = V4L2_CID_OSD_TEXT,
+	.name = "OSD Text",
+	.type = V4L2_CTRL_TYPE_STRING,
+	.max = OSD_TEXT_MAX,
+	.step = 1,
+};
+
+static struct solo_enc_dev *solo_enc_alloc(struct solo_dev *solo_dev,
+					   u8 ch, unsigned nr)
+{
+	struct solo_enc_dev *solo_enc;
+	struct v4l2_ctrl_handler *hdl;
+	int ret;
+	int x, y;
+
+	solo_enc = kzalloc(sizeof(*solo_enc), GFP_KERNEL);
+	if (!solo_enc)
+		return ERR_PTR(-ENOMEM);
+
+	hdl = &solo_enc->hdl;
+	v4l2_ctrl_handler_init(hdl, 10);
+	v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
+			V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
+	v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
+			V4L2_CID_CONTRAST, 0, 255, 1, 128);
+	v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
+			V4L2_CID_SATURATION, 0, 255, 1, 128);
+	v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
+			V4L2_CID_HUE, 0, 255, 1, 128);
+	if (tw28_has_sharpness(solo_dev, ch))
+		v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
+			V4L2_CID_SHARPNESS, 0, 15, 1, 0);
+	v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
+			V4L2_CID_MPEG_VIDEO_GOP_SIZE, 1, 255, 1, solo_dev->fps);
+	v4l2_ctrl_new_custom(hdl, &solo_motion_threshold_ctrl, NULL);
+	v4l2_ctrl_new_custom(hdl, &solo_motion_enable_ctrl, NULL);
+	v4l2_ctrl_new_custom(hdl, &solo_osd_text_ctrl, NULL);
+	if (hdl->error) {
+		ret = hdl->error;
+		goto hdl_free;
+	}
+
+	solo_enc->solo_dev = solo_dev;
+	solo_enc->ch = ch;
+	mutex_init(&solo_enc->lock);
+	spin_lock_init(&solo_enc->av_lock);
+	INIT_LIST_HEAD(&solo_enc->vidq_active);
+	solo_enc->fmt = V4L2_PIX_FMT_MPEG4;
+	solo_enc->type = SOLO_ENC_TYPE_STD;
+
+	solo_enc->qp = SOLO_DEFAULT_QP;
+	solo_enc->gop = solo_dev->fps;
+	solo_enc->interval = 1;
+	solo_enc->mode = SOLO_ENC_MODE_CIF;
+	solo_enc->motion_global = true;
+	solo_enc->motion_thresh = SOLO_DEF_MOT_THRESH;
+	for (y = 0; y < SOLO_MOTION_SZ; y++)
+		for (x = 0; x < SOLO_MOTION_SZ; x++)
+			solo_enc->motion_thresholds.thresholds[y][x] =
+							SOLO_DEF_MOT_THRESH;
+
+	solo_enc->vidq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	solo_enc->vidq.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
+	solo_enc->vidq.ops = &solo_enc_video_qops;
+	solo_enc->vidq.mem_ops = &vb2_dma_sg_memops;
+	solo_enc->vidq.drv_priv = solo_enc;
+	solo_enc->vidq.gfp_flags = __GFP_DMA32;
+	solo_enc->vidq.timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+	solo_enc->vidq.buf_struct_size = sizeof(struct solo_vb2_buf);
+	solo_enc->vidq.lock = &solo_enc->lock;
+	ret = vb2_queue_init(&solo_enc->vidq);
+	if (ret)
+		goto hdl_free;
+	solo_update_mode(solo_enc);
+
+	spin_lock_init(&solo_enc->motion_lock);
+
+	/* Initialize this per encoder */
+	solo_enc->jpeg_len = sizeof(jpeg_header);
+	memcpy(solo_enc->jpeg_header, jpeg_header, solo_enc->jpeg_len);
+
+	solo_enc->desc_nelts = 32;
+	solo_enc->desc_items = pci_alloc_consistent(solo_dev->pdev,
+				      sizeof(struct solo_p2m_desc) *
+				      solo_enc->desc_nelts, &solo_enc->desc_dma);
+	ret = -ENOMEM;
+	if (solo_enc->desc_items == NULL)
+		goto hdl_free;
+
+	solo_enc->vfd = video_device_alloc();
+	if (!solo_enc->vfd)
+		goto pci_free;
+
+	*solo_enc->vfd = solo_enc_template;
+	solo_enc->vfd->v4l2_dev = &solo_dev->v4l2_dev;
+	solo_enc->vfd->ctrl_handler = hdl;
+	solo_enc->vfd->queue = &solo_enc->vidq;
+	solo_enc->vfd->lock = &solo_enc->lock;
+	set_bit(V4L2_FL_USE_FH_PRIO, &solo_enc->vfd->flags);
+	video_set_drvdata(solo_enc->vfd, solo_enc);
+	ret = video_register_device(solo_enc->vfd, VFL_TYPE_GRABBER, nr);
+	if (ret < 0)
+		goto vdev_release;
+
+	snprintf(solo_enc->vfd->name, sizeof(solo_enc->vfd->name),
+		 "%s-enc (%i/%i)", SOLO6X10_NAME, solo_dev->vfd->num,
+		 solo_enc->vfd->num);
+
+	return solo_enc;
+
+vdev_release:
+	video_device_release(solo_enc->vfd);
+pci_free:
+	pci_free_consistent(solo_enc->solo_dev->pdev,
+			sizeof(struct solo_p2m_desc) * solo_enc->desc_nelts,
+			solo_enc->desc_items, solo_enc->desc_dma);
+hdl_free:
+	v4l2_ctrl_handler_free(hdl);
+	kfree(solo_enc);
+	return ERR_PTR(ret);
+}
+
+static void solo_enc_free(struct solo_enc_dev *solo_enc)
+{
+	if (solo_enc == NULL)
+		return;
+
+	video_unregister_device(solo_enc->vfd);
+	v4l2_ctrl_handler_free(&solo_enc->hdl);
+	kfree(solo_enc);
+}
+
+int solo_enc_v4l2_init(struct solo_dev *solo_dev, unsigned nr)
+{
+	int i;
+
+	init_waitqueue_head(&solo_dev->ring_thread_wait);
+
+	solo_dev->vh_size = sizeof(struct vop_header);
+	solo_dev->vh_buf = pci_alloc_consistent(solo_dev->pdev,
+						solo_dev->vh_size,
+						&solo_dev->vh_dma);
+	if (solo_dev->vh_buf == NULL)
+		return -ENOMEM;
+
+	for (i = 0; i < solo_dev->nr_chans; i++) {
+		solo_dev->v4l2_enc[i] = solo_enc_alloc(solo_dev, i, nr);
+		if (IS_ERR(solo_dev->v4l2_enc[i]))
+			break;
+	}
+
+	if (i != solo_dev->nr_chans) {
+		int ret = PTR_ERR(solo_dev->v4l2_enc[i]);
+		while (i--)
+			solo_enc_free(solo_dev->v4l2_enc[i]);
+		pci_free_consistent(solo_dev->pdev, solo_dev->vh_size,
+				    solo_dev->vh_buf, solo_dev->vh_dma);
+		solo_dev->vh_buf = NULL;
+		return ret;
+	}
+
+	if (solo_dev->type == SOLO_DEV_6010)
+		solo_dev->enc_bw_remain = solo_dev->fps * 4 * 4;
+	else
+		solo_dev->enc_bw_remain = solo_dev->fps * 4 * 5;
+
+	dev_info(&solo_dev->pdev->dev, "Encoders as /dev/video%d-%d\n",
+		 solo_dev->v4l2_enc[0]->vfd->num,
+		 solo_dev->v4l2_enc[solo_dev->nr_chans - 1]->vfd->num);
+
+	return 0;
+}
+
+void solo_enc_v4l2_exit(struct solo_dev *solo_dev)
+{
+	int i;
+
+	for (i = 0; i < solo_dev->nr_chans; i++)
+		solo_enc_free(solo_dev->v4l2_enc[i]);
+
+	if (solo_dev->vh_buf)
+		pci_free_consistent(solo_dev->pdev, solo_dev->vh_size,
+			    solo_dev->vh_buf, solo_dev->vh_dma);
+}
diff --git a/drivers/staging/media/solo6x10/solo6x10-v4l2.c b/drivers/staging/media/solo6x10/solo6x10-v4l2.c
new file mode 100644
index 0000000..7b26de3
--- /dev/null
+++ b/drivers/staging/media/solo6x10/solo6x10-v4l2.c
@@ -0,0 +1,734 @@
+/*
+ * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
+ *
+ * Original author:
+ * Ben Collins <bcollins@ubuntu.com>
+ *
+ * Additional work by:
+ * John Brooks <john.brooks@bluecherry.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You 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/kthread.h>
+#include <linux/freezer.h>
+
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-event.h>
+#include <media/videobuf2-dma-contig.h>
+
+#include "solo6x10.h"
+#include "solo6x10-tw28.h"
+
+/* Image size is two fields, SOLO_HW_BPL is one horizontal line in hardware */
+#define SOLO_HW_BPL		2048
+#define solo_vlines(__solo)	(__solo->video_vsize * 2)
+#define solo_image_size(__solo) (solo_bytesperline(__solo) * \
+				 solo_vlines(__solo))
+#define solo_bytesperline(__solo) (__solo->video_hsize * 2)
+
+#define MIN_VID_BUFFERS		2
+
+static inline void erase_on(struct solo_dev *solo_dev)
+{
+	solo_reg_write(solo_dev, SOLO_VO_DISP_ERASE, SOLO_VO_DISP_ERASE_ON);
+	solo_dev->erasing = 1;
+	solo_dev->frame_blank = 0;
+}
+
+static inline int erase_off(struct solo_dev *solo_dev)
+{
+	if (!solo_dev->erasing)
+		return 0;
+
+	/* First time around, assert erase off */
+	if (!solo_dev->frame_blank)
+		solo_reg_write(solo_dev, SOLO_VO_DISP_ERASE, 0);
+	/* Keep the erasing flag on for 8 frames minimum */
+	if (solo_dev->frame_blank++ >= 8)
+		solo_dev->erasing = 0;
+
+	return 1;
+}
+
+void solo_video_in_isr(struct solo_dev *solo_dev)
+{
+	wake_up_interruptible_all(&solo_dev->disp_thread_wait);
+}
+
+static void solo_win_setup(struct solo_dev *solo_dev, u8 ch,
+			   int sx, int sy, int ex, int ey, int scale)
+{
+	if (ch >= solo_dev->nr_chans)
+		return;
+
+	/* Here, we just keep window/channel the same */
+	solo_reg_write(solo_dev, SOLO_VI_WIN_CTRL0(ch),
+		       SOLO_VI_WIN_CHANNEL(ch) |
+		       SOLO_VI_WIN_SX(sx) |
+		       SOLO_VI_WIN_EX(ex) |
+		       SOLO_VI_WIN_SCALE(scale));
+
+	solo_reg_write(solo_dev, SOLO_VI_WIN_CTRL1(ch),
+		       SOLO_VI_WIN_SY(sy) |
+		       SOLO_VI_WIN_EY(ey));
+}
+
+static int solo_v4l2_ch_ext_4up(struct solo_dev *solo_dev, u8 idx, int on)
+{
+	u8 ch = idx * 4;
+
+	if (ch >= solo_dev->nr_chans)
+		return -EINVAL;
+
+	if (!on) {
+		u8 i;
+		for (i = ch; i < ch + 4; i++)
+			solo_win_setup(solo_dev, i, solo_dev->video_hsize,
+				       solo_vlines(solo_dev),
+				       solo_dev->video_hsize,
+				       solo_vlines(solo_dev), 0);
+		return 0;
+	}
+
+	/* Row 1 */
+	solo_win_setup(solo_dev, ch, 0, 0, solo_dev->video_hsize / 2,
+		       solo_vlines(solo_dev) / 2, 3);
+	solo_win_setup(solo_dev, ch + 1, solo_dev->video_hsize / 2, 0,
+		       solo_dev->video_hsize, solo_vlines(solo_dev) / 2, 3);
+	/* Row 2 */
+	solo_win_setup(solo_dev, ch + 2, 0, solo_vlines(solo_dev) / 2,
+		       solo_dev->video_hsize / 2, solo_vlines(solo_dev), 3);
+	solo_win_setup(solo_dev, ch + 3, solo_dev->video_hsize / 2,
+		       solo_vlines(solo_dev) / 2, solo_dev->video_hsize,
+		       solo_vlines(solo_dev), 3);
+
+	return 0;
+}
+
+static int solo_v4l2_ch_ext_16up(struct solo_dev *solo_dev, int on)
+{
+	int sy, ysize, hsize, i;
+
+	if (!on) {
+		for (i = 0; i < 16; i++)
+			solo_win_setup(solo_dev, i, solo_dev->video_hsize,
+				       solo_vlines(solo_dev),
+				       solo_dev->video_hsize,
+				       solo_vlines(solo_dev), 0);
+		return 0;
+	}
+
+	ysize = solo_vlines(solo_dev) / 4;
+	hsize = solo_dev->video_hsize / 4;
+
+	for (sy = 0, i = 0; i < 4; i++, sy += ysize) {
+		solo_win_setup(solo_dev, i * 4, 0, sy, hsize,
+			       sy + ysize, 5);
+		solo_win_setup(solo_dev, (i * 4) + 1, hsize, sy,
+			       hsize * 2, sy + ysize, 5);
+		solo_win_setup(solo_dev, (i * 4) + 2, hsize * 2, sy,
+			       hsize * 3, sy + ysize, 5);
+		solo_win_setup(solo_dev, (i * 4) + 3, hsize * 3, sy,
+			       solo_dev->video_hsize, sy + ysize, 5);
+	}
+
+	return 0;
+}
+
+static int solo_v4l2_ch(struct solo_dev *solo_dev, u8 ch, int on)
+{
+	u8 ext_ch;
+
+	if (ch < solo_dev->nr_chans) {
+		solo_win_setup(solo_dev, ch, on ? 0 : solo_dev->video_hsize,
+			       on ? 0 : solo_vlines(solo_dev),
+			       solo_dev->video_hsize, solo_vlines(solo_dev),
+			       on ? 1 : 0);
+		return 0;
+	}
+
+	if (ch >= solo_dev->nr_chans + solo_dev->nr_ext)
+		return -EINVAL;
+
+	ext_ch = ch - solo_dev->nr_chans;
+
+	/* 4up's first */
+	if (ext_ch < 4)
+		return solo_v4l2_ch_ext_4up(solo_dev, ext_ch, on);
+
+	/* Remaining case is 16up for 16-port */
+	return solo_v4l2_ch_ext_16up(solo_dev, on);
+}
+
+static int solo_v4l2_set_ch(struct solo_dev *solo_dev, u8 ch)
+{
+	if (ch >= solo_dev->nr_chans + solo_dev->nr_ext)
+		return -EINVAL;
+
+	erase_on(solo_dev);
+
+	solo_v4l2_ch(solo_dev, solo_dev->cur_disp_ch, 0);
+	solo_v4l2_ch(solo_dev, ch, 1);
+
+	solo_dev->cur_disp_ch = ch;
+
+	return 0;
+}
+
+static void solo_fillbuf(struct solo_dev *solo_dev,
+			 struct vb2_buffer *vb)
+{
+	dma_addr_t vbuf;
+	unsigned int fdma_addr;
+	int error = -1;
+	int i;
+
+	vbuf = vb2_dma_contig_plane_dma_addr(vb, 0);
+	if (!vbuf)
+		goto finish_buf;
+
+	if (erase_off(solo_dev)) {
+		void *p = vb2_plane_vaddr(vb, 0);
+		int image_size = solo_image_size(solo_dev);
+		for (i = 0; i < image_size; i += 2) {
+			((u8 *)p)[i] = 0x80;
+			((u8 *)p)[i + 1] = 0x00;
+		}
+		error = 0;
+	} else {
+		fdma_addr = SOLO_DISP_EXT_ADDR + (solo_dev->old_write *
+				(SOLO_HW_BPL * solo_vlines(solo_dev)));
+
+		error = solo_p2m_dma_t(solo_dev, 0, vbuf, fdma_addr,
+				       solo_bytesperline(solo_dev),
+				       solo_vlines(solo_dev), SOLO_HW_BPL);
+	}
+
+finish_buf:
+	if (!error) {
+		vb2_set_plane_payload(vb, 0,
+			solo_vlines(solo_dev) * solo_bytesperline(solo_dev));
+		vb->v4l2_buf.sequence = solo_dev->sequence++;
+		v4l2_get_timestamp(&vb->v4l2_buf.timestamp);
+	}
+
+	vb2_buffer_done(vb, error ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
+}
+
+static void solo_thread_try(struct solo_dev *solo_dev)
+{
+	struct solo_vb2_buf *vb;
+
+	/* Only "break" from this loop if slock is held, otherwise
+	 * just return. */
+	for (;;) {
+		unsigned int cur_write;
+
+		cur_write = SOLO_VI_STATUS0_PAGE(
+			solo_reg_read(solo_dev, SOLO_VI_STATUS0));
+		if (cur_write == solo_dev->old_write)
+			return;
+
+		spin_lock(&solo_dev->slock);
+
+		if (list_empty(&solo_dev->vidq_active))
+			break;
+
+		vb = list_first_entry(&solo_dev->vidq_active, struct solo_vb2_buf,
+				      list);
+
+		solo_dev->old_write = cur_write;
+		list_del(&vb->list);
+
+		spin_unlock(&solo_dev->slock);
+
+		solo_fillbuf(solo_dev, &vb->vb);
+	}
+
+	assert_spin_locked(&solo_dev->slock);
+	spin_unlock(&solo_dev->slock);
+}
+
+static int solo_thread(void *data)
+{
+	struct solo_dev *solo_dev = data;
+	DECLARE_WAITQUEUE(wait, current);
+
+	set_freezable();
+	add_wait_queue(&solo_dev->disp_thread_wait, &wait);
+
+	for (;;) {
+		long timeout = schedule_timeout_interruptible(HZ);
+		if (timeout == -ERESTARTSYS || kthread_should_stop())
+			break;
+		solo_thread_try(solo_dev);
+		try_to_freeze();
+	}
+
+	remove_wait_queue(&solo_dev->disp_thread_wait, &wait);
+
+	return 0;
+}
+
+static int solo_start_thread(struct solo_dev *solo_dev)
+{
+	int ret = 0;
+
+	solo_dev->kthread = kthread_run(solo_thread, solo_dev, SOLO6X10_NAME "_disp");
+
+	if (IS_ERR(solo_dev->kthread)) {
+		ret = PTR_ERR(solo_dev->kthread);
+		solo_dev->kthread = NULL;
+		return ret;
+	}
+	solo_irq_on(solo_dev, SOLO_IRQ_VIDEO_IN);
+
+	return ret;
+}
+
+static void solo_stop_thread(struct solo_dev *solo_dev)
+{
+	if (!solo_dev->kthread)
+		return;
+
+	solo_irq_off(solo_dev, SOLO_IRQ_VIDEO_IN);
+	kthread_stop(solo_dev->kthread);
+	solo_dev->kthread = NULL;
+}
+
+static int solo_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+			   unsigned int *num_buffers, unsigned int *num_planes,
+			   unsigned int sizes[], void *alloc_ctxs[])
+{
+	struct solo_dev *solo_dev = vb2_get_drv_priv(q);
+
+	sizes[0] = solo_image_size(solo_dev);
+	alloc_ctxs[0] = solo_dev->alloc_ctx;
+	*num_planes = 1;
+
+	if (*num_buffers < MIN_VID_BUFFERS)
+		*num_buffers = MIN_VID_BUFFERS;
+
+	return 0;
+}
+
+static int solo_start_streaming(struct vb2_queue *q, unsigned int count)
+{
+	struct solo_dev *solo_dev = vb2_get_drv_priv(q);
+
+	solo_dev->sequence = 0;
+	return solo_start_thread(solo_dev);
+}
+
+static int solo_stop_streaming(struct vb2_queue *q)
+{
+	struct solo_dev *solo_dev = vb2_get_drv_priv(q);
+
+	solo_stop_thread(solo_dev);
+	INIT_LIST_HEAD(&solo_dev->vidq_active);
+	return 0;
+}
+
+static void solo_buf_queue(struct vb2_buffer *vb)
+{
+	struct vb2_queue *vq = vb->vb2_queue;
+	struct solo_dev *solo_dev = vb2_get_drv_priv(vq);
+	struct solo_vb2_buf *solo_vb =
+		container_of(vb, struct solo_vb2_buf, vb);
+
+	spin_lock(&solo_dev->slock);
+	list_add_tail(&solo_vb->list, &solo_dev->vidq_active);
+	spin_unlock(&solo_dev->slock);
+	wake_up_interruptible(&solo_dev->disp_thread_wait);
+}
+
+static const struct vb2_ops solo_video_qops = {
+	.queue_setup	= solo_queue_setup,
+	.buf_queue	= solo_buf_queue,
+	.start_streaming = solo_start_streaming,
+	.stop_streaming = solo_stop_streaming,
+	.wait_prepare	= vb2_ops_wait_prepare,
+	.wait_finish	= vb2_ops_wait_finish,
+};
+
+static int solo_querycap(struct file *file, void  *priv,
+			 struct v4l2_capability *cap)
+{
+	struct solo_dev *solo_dev = video_drvdata(file);
+
+	strcpy(cap->driver, SOLO6X10_NAME);
+	strcpy(cap->card, "Softlogic 6x10");
+	snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s",
+		 pci_name(solo_dev->pdev));
+	cap->device_caps = V4L2_CAP_VIDEO_CAPTURE |
+			V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
+	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+	return 0;
+}
+
+static int solo_enum_ext_input(struct solo_dev *solo_dev,
+			       struct v4l2_input *input)
+{
+	static const char * const dispnames_1[] = { "4UP" };
+	static const char * const dispnames_2[] = { "4UP-1", "4UP-2" };
+	static const char * const dispnames_5[] = {
+		"4UP-1", "4UP-2", "4UP-3", "4UP-4", "16UP"
+	};
+	const char * const *dispnames;
+
+	if (input->index >= (solo_dev->nr_chans + solo_dev->nr_ext))
+		return -EINVAL;
+
+	if (solo_dev->nr_ext == 5)
+		dispnames = dispnames_5;
+	else if (solo_dev->nr_ext == 2)
+		dispnames = dispnames_2;
+	else
+		dispnames = dispnames_1;
+
+	snprintf(input->name, sizeof(input->name), "Multi %s",
+		 dispnames[input->index - solo_dev->nr_chans]);
+
+	return 0;
+}
+
+static int solo_enum_input(struct file *file, void *priv,
+			   struct v4l2_input *input)
+{
+	struct solo_dev *solo_dev = video_drvdata(file);
+
+	if (input->index >= solo_dev->nr_chans) {
+		int ret = solo_enum_ext_input(solo_dev, input);
+		if (ret < 0)
+			return ret;
+	} else {
+		snprintf(input->name, sizeof(input->name), "Camera %d",
+			 input->index + 1);
+
+		/* We can only check this for normal inputs */
+		if (!tw28_get_video_status(solo_dev, input->index))
+			input->status = V4L2_IN_ST_NO_SIGNAL;
+	}
+
+	input->type = V4L2_INPUT_TYPE_CAMERA;
+	input->std = solo_dev->vfd->tvnorms;
+	return 0;
+}
+
+static int solo_set_input(struct file *file, void *priv, unsigned int index)
+{
+	struct solo_dev *solo_dev = video_drvdata(file);
+	int ret = solo_v4l2_set_ch(solo_dev, index);
+
+	if (!ret) {
+		while (erase_off(solo_dev))
+			/* Do nothing */;
+	}
+
+	return ret;
+}
+
+static int solo_get_input(struct file *file, void *priv, unsigned int *index)
+{
+	struct solo_dev *solo_dev = video_drvdata(file);
+
+	*index = solo_dev->cur_disp_ch;
+
+	return 0;
+}
+
+static int solo_enum_fmt_cap(struct file *file, void *priv,
+			     struct v4l2_fmtdesc *f)
+{
+	if (f->index)
+		return -EINVAL;
+
+	f->pixelformat = V4L2_PIX_FMT_UYVY;
+	strlcpy(f->description, "UYUV 4:2:2 Packed", sizeof(f->description));
+
+	return 0;
+}
+
+static int solo_try_fmt_cap(struct file *file, void *priv,
+			    struct v4l2_format *f)
+{
+	struct solo_dev *solo_dev = video_drvdata(file);
+	struct v4l2_pix_format *pix = &f->fmt.pix;
+	int image_size = solo_image_size(solo_dev);
+
+	if (pix->pixelformat != V4L2_PIX_FMT_UYVY)
+		return -EINVAL;
+
+	pix->width = solo_dev->video_hsize;
+	pix->height = solo_vlines(solo_dev);
+	pix->sizeimage = image_size;
+	pix->field = V4L2_FIELD_INTERLACED;
+	pix->pixelformat = V4L2_PIX_FMT_UYVY;
+	pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
+	pix->priv = 0;
+	return 0;
+}
+
+static int solo_set_fmt_cap(struct file *file, void *priv,
+			    struct v4l2_format *f)
+{
+	struct solo_dev *solo_dev = video_drvdata(file);
+
+	if (vb2_is_busy(&solo_dev->vidq))
+		return -EBUSY;
+
+	/* For right now, if it doesn't match our running config,
+	 * then fail */
+	return solo_try_fmt_cap(file, priv, f);
+}
+
+static int solo_get_fmt_cap(struct file *file, void *priv,
+			    struct v4l2_format *f)
+{
+	struct solo_dev *solo_dev = video_drvdata(file);
+	struct v4l2_pix_format *pix = &f->fmt.pix;
+
+	pix->width = solo_dev->video_hsize;
+	pix->height = solo_vlines(solo_dev);
+	pix->pixelformat = V4L2_PIX_FMT_UYVY;
+	pix->field = V4L2_FIELD_INTERLACED;
+	pix->sizeimage = solo_image_size(solo_dev);
+	pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
+	pix->bytesperline = solo_bytesperline(solo_dev);
+	pix->priv = 0;
+
+	return 0;
+}
+
+static int solo_g_std(struct file *file, void *priv, v4l2_std_id *i)
+{
+	struct solo_dev *solo_dev = video_drvdata(file);
+
+	if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC)
+		*i = V4L2_STD_NTSC_M;
+	else
+		*i = V4L2_STD_PAL;
+	return 0;
+}
+
+int solo_set_video_type(struct solo_dev *solo_dev, bool type)
+{
+	int i;
+
+	/* Make sure all video nodes are idle */
+	if (vb2_is_busy(&solo_dev->vidq))
+		return -EBUSY;
+	for (i = 0; i < solo_dev->nr_chans; i++)
+		if (vb2_is_busy(&solo_dev->v4l2_enc[i]->vidq))
+			return -EBUSY;
+	solo_dev->video_type = type;
+	/* Reconfigure for the new standard */
+	solo_disp_init(solo_dev);
+	solo_enc_init(solo_dev);
+	solo_tw28_init(solo_dev);
+	for (i = 0; i < solo_dev->nr_chans; i++)
+		solo_update_mode(solo_dev->v4l2_enc[i]);
+	return solo_v4l2_set_ch(solo_dev, solo_dev->cur_disp_ch);
+}
+
+static int solo_s_std(struct file *file, void *priv, v4l2_std_id std)
+{
+	struct solo_dev *solo_dev = video_drvdata(file);
+
+	return solo_set_video_type(solo_dev, std & V4L2_STD_PAL);
+}
+
+static int solo_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct solo_dev *solo_dev =
+		container_of(ctrl->handler, struct solo_dev, disp_hdl);
+
+	switch (ctrl->id) {
+	case V4L2_CID_MOTION_TRACE:
+		if (ctrl->val) {
+			solo_reg_write(solo_dev, SOLO_VI_MOTION_BORDER,
+					SOLO_VI_MOTION_Y_ADD |
+					SOLO_VI_MOTION_Y_VALUE(0x20) |
+					SOLO_VI_MOTION_CB_VALUE(0x10) |
+					SOLO_VI_MOTION_CR_VALUE(0x10));
+			solo_reg_write(solo_dev, SOLO_VI_MOTION_BAR,
+					SOLO_VI_MOTION_CR_ADD |
+					SOLO_VI_MOTION_Y_VALUE(0x10) |
+					SOLO_VI_MOTION_CB_VALUE(0x80) |
+					SOLO_VI_MOTION_CR_VALUE(0x10));
+		} else {
+			solo_reg_write(solo_dev, SOLO_VI_MOTION_BORDER, 0);
+			solo_reg_write(solo_dev, SOLO_VI_MOTION_BAR, 0);
+		}
+		return 0;
+	default:
+		break;
+	}
+	return -EINVAL;
+}
+
+static const struct v4l2_file_operations solo_v4l2_fops = {
+	.owner			= THIS_MODULE,
+	.open			= v4l2_fh_open,
+	.release		= vb2_fop_release,
+	.read			= vb2_fop_read,
+	.poll			= vb2_fop_poll,
+	.mmap			= vb2_fop_mmap,
+	.unlocked_ioctl		= video_ioctl2,
+};
+
+static const struct v4l2_ioctl_ops solo_v4l2_ioctl_ops = {
+	.vidioc_querycap		= solo_querycap,
+	.vidioc_s_std			= solo_s_std,
+	.vidioc_g_std			= solo_g_std,
+	/* Input callbacks */
+	.vidioc_enum_input		= solo_enum_input,
+	.vidioc_s_input			= solo_set_input,
+	.vidioc_g_input			= solo_get_input,
+	/* Video capture format callbacks */
+	.vidioc_enum_fmt_vid_cap	= solo_enum_fmt_cap,
+	.vidioc_try_fmt_vid_cap		= solo_try_fmt_cap,
+	.vidioc_s_fmt_vid_cap		= solo_set_fmt_cap,
+	.vidioc_g_fmt_vid_cap		= solo_get_fmt_cap,
+	/* Streaming I/O */
+	.vidioc_reqbufs			= vb2_ioctl_reqbufs,
+	.vidioc_querybuf		= vb2_ioctl_querybuf,
+	.vidioc_qbuf			= vb2_ioctl_qbuf,
+	.vidioc_dqbuf			= vb2_ioctl_dqbuf,
+	.vidioc_streamon		= vb2_ioctl_streamon,
+	.vidioc_streamoff		= vb2_ioctl_streamoff,
+	/* Logging and events */
+	.vidioc_log_status		= v4l2_ctrl_log_status,
+	.vidioc_subscribe_event		= v4l2_ctrl_subscribe_event,
+	.vidioc_unsubscribe_event	= v4l2_event_unsubscribe,
+};
+
+static struct video_device solo_v4l2_template = {
+	.name			= SOLO6X10_NAME,
+	.fops			= &solo_v4l2_fops,
+	.ioctl_ops		= &solo_v4l2_ioctl_ops,
+	.minor			= -1,
+	.release		= video_device_release,
+	.tvnorms		= V4L2_STD_NTSC_M | V4L2_STD_PAL,
+};
+
+static const struct v4l2_ctrl_ops solo_ctrl_ops = {
+	.s_ctrl = solo_s_ctrl,
+};
+
+static const struct v4l2_ctrl_config solo_motion_trace_ctrl = {
+	.ops = &solo_ctrl_ops,
+	.id = V4L2_CID_MOTION_TRACE,
+	.name = "Motion Detection Trace",
+	.type = V4L2_CTRL_TYPE_BOOLEAN,
+	.max = 1,
+	.step = 1,
+};
+
+int solo_v4l2_init(struct solo_dev *solo_dev, unsigned nr)
+{
+	int ret;
+	int i;
+
+	init_waitqueue_head(&solo_dev->disp_thread_wait);
+	spin_lock_init(&solo_dev->slock);
+	mutex_init(&solo_dev->lock);
+	INIT_LIST_HEAD(&solo_dev->vidq_active);
+
+	solo_dev->vfd = video_device_alloc();
+	if (!solo_dev->vfd)
+		return -ENOMEM;
+
+	*solo_dev->vfd = solo_v4l2_template;
+	solo_dev->vfd->v4l2_dev = &solo_dev->v4l2_dev;
+	solo_dev->vfd->queue = &solo_dev->vidq;
+	solo_dev->vfd->lock = &solo_dev->lock;
+	v4l2_ctrl_handler_init(&solo_dev->disp_hdl, 1);
+	v4l2_ctrl_new_custom(&solo_dev->disp_hdl, &solo_motion_trace_ctrl, NULL);
+	if (solo_dev->disp_hdl.error) {
+		ret = solo_dev->disp_hdl.error;
+		goto fail;
+	}
+	solo_dev->vfd->ctrl_handler = &solo_dev->disp_hdl;
+	set_bit(V4L2_FL_USE_FH_PRIO, &solo_dev->vfd->flags);
+
+	video_set_drvdata(solo_dev->vfd, solo_dev);
+
+	solo_dev->vidq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	solo_dev->vidq.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
+	solo_dev->vidq.ops = &solo_video_qops;
+	solo_dev->vidq.mem_ops = &vb2_dma_contig_memops;
+	solo_dev->vidq.drv_priv = solo_dev;
+	solo_dev->vidq.timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+	solo_dev->vidq.gfp_flags = __GFP_DMA32;
+	solo_dev->vidq.buf_struct_size = sizeof(struct solo_vb2_buf);
+	solo_dev->vidq.lock = &solo_dev->lock;
+	ret = vb2_queue_init(&solo_dev->vidq);
+	if (ret < 0)
+		goto fail;
+
+	solo_dev->alloc_ctx = vb2_dma_contig_init_ctx(&solo_dev->pdev->dev);
+	if (IS_ERR(solo_dev->alloc_ctx)) {
+		dev_err(&solo_dev->pdev->dev, "Can't allocate buffer context");
+		return PTR_ERR(solo_dev->alloc_ctx);
+	}
+
+	/* Cycle all the channels and clear */
+	for (i = 0; i < solo_dev->nr_chans; i++) {
+		solo_v4l2_set_ch(solo_dev, i);
+		while (erase_off(solo_dev))
+			/* Do nothing */;
+	}
+
+	/* Set the default display channel */
+	solo_v4l2_set_ch(solo_dev, 0);
+	while (erase_off(solo_dev))
+		/* Do nothing */;
+
+	ret = video_register_device(solo_dev->vfd, VFL_TYPE_GRABBER, nr);
+	if (ret < 0)
+		goto fail;
+
+	snprintf(solo_dev->vfd->name, sizeof(solo_dev->vfd->name), "%s (%i)",
+		 SOLO6X10_NAME, solo_dev->vfd->num);
+
+	dev_info(&solo_dev->pdev->dev, "Display as /dev/video%d with "
+		 "%d inputs (%d extended)\n", solo_dev->vfd->num,
+		 solo_dev->nr_chans, solo_dev->nr_ext);
+
+	return 0;
+
+fail:
+	video_device_release(solo_dev->vfd);
+	vb2_dma_contig_cleanup_ctx(solo_dev->alloc_ctx);
+	v4l2_ctrl_handler_free(&solo_dev->disp_hdl);
+	solo_dev->vfd = NULL;
+	return ret;
+}
+
+void solo_v4l2_exit(struct solo_dev *solo_dev)
+{
+	if (solo_dev->vfd == NULL)
+		return;
+
+	video_unregister_device(solo_dev->vfd);
+	vb2_dma_contig_cleanup_ctx(solo_dev->alloc_ctx);
+	v4l2_ctrl_handler_free(&solo_dev->disp_hdl);
+	solo_dev->vfd = NULL;
+}
diff --git a/drivers/staging/media/solo6x10/solo6x10.h b/drivers/staging/media/solo6x10/solo6x10.h
index abee721..6f91d2e 100644
--- a/drivers/staging/media/solo6x10/solo6x10.h
+++ b/drivers/staging/media/solo6x10/solo6x10.h
@@ -1,6 +1,11 @@
 /*
- * Copyright (C) 2010 Bluecherry, LLC www.bluecherrydvr.com
- * Copyright (C) 2010 Ben Collins <bcollins@bluecherry.net>
+ * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
+ *
+ * Original author:
+ * Ben Collins <bcollins@ubuntu.com>
+ *
+ * Additional work by:
+ * John Brooks <john.brooks@bluecherry.net>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -20,21 +25,23 @@
 #ifndef __SOLO6X10_H
 #define __SOLO6X10_H
 
-#include <linux/version.h>
 #include <linux/pci.h>
 #include <linux/i2c.h>
-#include <linux/semaphore.h>
 #include <linux/mutex.h>
 #include <linux/list.h>
 #include <linux/wait.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <asm/io.h>
+#include <linux/stringify.h>
+#include <linux/io.h>
 #include <linux/atomic.h>
+#include <linux/slab.h>
 #include <linux/videodev2.h>
+
 #include <media/v4l2-dev.h>
-#include <media/videobuf-core.h>
-#include "registers.h"
+#include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
+#include <media/videobuf2-core.h>
+
+#include "solo6x10-regs.h"
 
 #ifndef PCI_VENDOR_ID_SOFTLOGIC
 #define PCI_VENDOR_ID_SOFTLOGIC		0x9413
@@ -58,19 +65,15 @@
 #define PCI_DEVICE_ID_BC_6110_16	0x5310
 #endif /* Bluecherry */
 
+/* Used in pci_device_id, and solo_dev->type */
+#define SOLO_DEV_6010			0
+#define SOLO_DEV_6110			1
+
 #define SOLO6X10_NAME			"solo6x10"
 
 #define SOLO_MAX_CHANNELS		16
 
-/* Make sure these two match */
-#define SOLO6X10_VERSION		"2.1.0"
-#define SOLO6X10_VER_MAJOR		2
-#define SOLO6X10_VER_MINOR		0
-#define SOLO6X10_VER_SUB		0
-#define SOLO6X10_VER_NUM \
-	KERNEL_VERSION(SOLO6X10_VER_MAJOR, SOLO6X10_VER_MINOR, SOLO6X10_VER_SUB)
-
-#define FLAGS_6110			1
+#define SOLO6X10_VERSION		"3.0.0"
 
 /*
  * The SOLO6x10 actually has 8 i2c channels, but we only use 2.
@@ -84,16 +87,7 @@
 /* DMA Engine setup */
 #define SOLO_NR_P2M			4
 #define SOLO_NR_P2M_DESC		256
-/* MPEG and JPEG share the same interrupt and locks so they must be together
- * in the same dma channel. */
-#define SOLO_P2M_DMA_ID_MP4E		0
-#define SOLO_P2M_DMA_ID_JPEG		0
-#define SOLO_P2M_DMA_ID_MP4D		1
-#define SOLO_P2M_DMA_ID_G723D		1
-#define SOLO_P2M_DMA_ID_DISP		2
-#define SOLO_P2M_DMA_ID_OSG		2
-#define SOLO_P2M_DMA_ID_G723E		3
-#define SOLO_P2M_DMA_ID_VIN		3
+#define SOLO_P2M_DESC_SIZE		(SOLO_NR_P2M_DESC * 16)
 
 /* Encoder standard modes */
 #define SOLO_ENC_MODE_CIF		2
@@ -103,23 +97,37 @@
 #define SOLO_DEFAULT_GOP		30
 #define SOLO_DEFAULT_QP			3
 
-/* There is 8MB memory available for solo to buffer MPEG4 frames.
- * This gives us 512 * 16kbyte queues. */
-#define SOLO_NR_RING_BUFS		512
-
-#define SOLO_CLOCK_MHZ			108
-
 #ifndef V4L2_BUF_FLAG_MOTION_ON
-#define V4L2_BUF_FLAG_MOTION_ON		0x0400
-#define V4L2_BUF_FLAG_MOTION_DETECTED	0x0800
-#endif
-#ifndef V4L2_CID_MOTION_ENABLE
-#define PRIVATE_CIDS
-#define V4L2_CID_MOTION_ENABLE		(V4L2_CID_PRIVATE_BASE+0)
-#define V4L2_CID_MOTION_THRESHOLD	(V4L2_CID_PRIVATE_BASE+1)
-#define V4L2_CID_MOTION_TRACE		(V4L2_CID_PRIVATE_BASE+2)
+#define V4L2_BUF_FLAG_MOTION_ON		0x10000
+#define V4L2_BUF_FLAG_MOTION_DETECTED	0x20000
 #endif
 
+#define SOLO_CID_CUSTOM_BASE		(V4L2_CID_USER_BASE | 0xf000)
+#define V4L2_CID_MOTION_MODE		(SOLO_CID_CUSTOM_BASE+0)
+#define V4L2_CID_MOTION_THRESHOLD	(SOLO_CID_CUSTOM_BASE+1)
+#define V4L2_CID_MOTION_TRACE		(SOLO_CID_CUSTOM_BASE+2)
+#define V4L2_CID_OSD_TEXT		(SOLO_CID_CUSTOM_BASE+3)
+
+/*
+ * Motion thresholds are in a table of 64x64 samples, with
+ * each sample representing 16x16 pixels of the source. In
+ * effect, 44x30 samples are used for NTSC, and 44x36 for PAL.
+ * The 5th sample on the 10th row is (10*64)+5 = 645.
+ *
+ * Using a 64x64 array will result in a problem on some architectures like
+ * the powerpc where the size of the argument is limited to 13 bits.
+ * Since both PAL and NTSC do not use the full table anyway I've chosen
+ * to limit the array to 45x45 (45*16 = 720, which is the maximum PAL/NTSC
+ * width).
+ */
+#define SOLO_MOTION_SZ (45)
+struct solo_motion_thresholds {
+	__u16	thresholds[SOLO_MOTION_SZ][SOLO_MOTION_SZ];
+};
+
+#define SOLO_IOC_G_MOTION_THRESHOLDS	_IOR('V', BASE_VIDIOC_PRIVATE+0, struct solo_motion_thresholds)
+#define SOLO_IOC_S_MOTION_THRESHOLDS	_IOW('V', BASE_VIDIOC_PRIVATE+1, struct solo_motion_thresholds)
+
 enum SOLO_I2C_STATE {
 	IIC_STATE_IDLE,
 	IIC_STATE_START,
@@ -128,20 +136,29 @@ enum SOLO_I2C_STATE {
 	IIC_STATE_STOP
 };
 
-struct p2m_desc {
-	u32 ctrl;
-	u32 ext;
-	u32 ta;
-	u32 fa;
+/* Defined in Table 4-16, Page 68-69 of the 6010 Datasheet */
+struct solo_p2m_desc {
+	u32	ctrl;
+	u32	cfg;
+	u32	dma_addr;
+	u32	ext_addr;
 };
 
 struct solo_p2m_dev {
 	struct mutex		mutex;
 	struct completion	completion;
+	int			desc_count;
+	int			desc_idx;
+	struct solo_p2m_desc	*descs;
 	int			error;
 };
 
-#define OSD_TEXT_MAX		30
+#define OSD_TEXT_MAX		44
+
+struct solo_vb2_buf {
+	struct vb2_buffer vb;
+	struct list_head list;
+};
 
 enum solo_enc_types {
 	SOLO_ENC_TYPE_STD,
@@ -149,46 +166,61 @@ enum solo_enc_types {
 };
 
 struct solo_enc_dev {
-	struct solo_dev		*solo_dev;
+	struct solo_dev	*solo_dev;
 	/* V4L2 Items */
+	struct v4l2_ctrl_handler hdl;
 	struct video_device	*vfd;
 	/* General accounting */
-	wait_queue_head_t	thread_wait;
-	spinlock_t		lock;
-	atomic_t		readers;
+	struct mutex		lock;
+	spinlock_t		motion_lock;
 	u8			ch;
 	u8			mode, gop, qp, interlaced, interval;
-	u8			reset_gop;
 	u8			bw_weight;
-	u8			motion_detected;
 	u16			motion_thresh;
+	struct solo_motion_thresholds motion_thresholds;
+	bool			motion_global;
+	bool			motion_enabled;
 	u16			width;
 	u16			height;
+
+	/* OSD buffers */
 	char			osd_text[OSD_TEXT_MAX + 1];
-};
+	u8			osd_buf[SOLO_EOSD_EXT_SIZE_MAX]
+					__aligned(4);
 
-struct solo_enc_buf {
-	u8			vop;
-	u8			ch;
+	/* VOP stuff */
+	unsigned char		vop[64];
+	int			vop_len;
+	unsigned char		jpeg_header[1024];
+	int			jpeg_len;
+
+	u32			fmt;
 	enum solo_enc_types	type;
-	u32			off;
-	u32			size;
-	u32			jpeg_off;
-	u32			jpeg_size;
-	struct timeval		ts;
+	u32			sequence;
+	struct vb2_queue	vidq;
+	struct list_head	vidq_active;
+	int			desc_count;
+	int			desc_nelts;
+	struct solo_p2m_desc	*desc_items;
+	dma_addr_t		desc_dma;
+	spinlock_t		av_lock;
 };
 
 /* The SOLO6x10 PCI Device */
 struct solo_dev {
 	/* General stuff */
 	struct pci_dev		*pdev;
+	int			type;
+	unsigned int		time_sync;
+	unsigned int		usec_lsb;
+	unsigned int		clock_mhz;
 	u8 __iomem		*reg_base;
 	int			nr_chans;
 	int			nr_ext;
-	u32			flags;
 	u32			irq_mask;
 	u32			motion_mask;
 	spinlock_t		reg_io_lock;
+	struct v4l2_device	v4l2_dev;
 
 	/* tw28xx accounting */
 	u8			tw2865, tw2864, tw2815;
@@ -206,6 +238,9 @@ struct solo_dev {
 
 	/* P2M DMA Engine */
 	struct solo_p2m_dev	p2m_dev[SOLO_NR_P2M];
+	atomic_t		p2m_count;
+	int			p2m_jiffies;
+	unsigned int		p2m_timeouts;
 
 	/* V4L2 Display items */
 	struct video_device	*vfd;
@@ -213,15 +248,13 @@ struct solo_dev {
 	unsigned int		frame_blank;
 	u8			cur_disp_ch;
 	wait_queue_head_t	disp_thread_wait;
+	struct v4l2_ctrl_handler disp_hdl;
 
 	/* V4L2 Encoder items */
 	struct solo_enc_dev	*v4l2_enc[SOLO_MAX_CHANNELS];
 	u16			enc_bw_remain;
 	/* IDX into hw mp4 encoder */
 	u8			enc_idx;
-	/* Our software ring of enc buf references */
-	u16			enc_wr_idx;
-	struct solo_enc_buf	enc_buf[SOLO_NR_RING_BUFS];
 
 	/* Current video settings */
 	u32			video_type;
@@ -230,11 +263,40 @@ struct solo_dev {
 	u16			vin_hstart, vin_vstart;
 	u8			fps;
 
+	/* JPEG Qp setting */
+	spinlock_t      jpeg_qp_lock;
+	u32		jpeg_qp[2];
+
 	/* Audio components */
 	struct snd_card		*snd_card;
 	struct snd_pcm		*snd_pcm;
 	atomic_t		snd_users;
 	int			g723_hw_idx;
+
+	/* sysfs stuffs */
+	struct device		dev;
+	int			sdram_size;
+	struct bin_attribute	sdram_attr;
+	unsigned int		sys_config;
+
+	/* Ring thread */
+	struct task_struct	*ring_thread;
+	wait_queue_head_t	ring_thread_wait;
+
+	/* VOP_HEADER handling */
+	void                    *vh_buf;
+	dma_addr_t		vh_dma;
+	int			vh_size;
+
+	/* Buffer handling */
+	struct vb2_queue	vidq;
+	struct vb2_alloc_ctx	*alloc_ctx;
+	u32			sequence;
+	struct task_struct      *kthread;
+	struct mutex		lock;
+	spinlock_t		slock;
+	int			old_write;
+	struct list_head	vidq_active;
 };
 
 static inline u32 solo_reg_read(struct solo_dev *solo_dev, int reg)
@@ -255,7 +317,8 @@ static inline u32 solo_reg_read(struct solo_dev *solo_dev, int reg)
 	return ret;
 }
 
-static inline void solo_reg_write(struct solo_dev *solo_dev, int reg, u32 data)
+static inline void solo_reg_write(struct solo_dev *solo_dev, int reg,
+				  u32 data)
 {
 	unsigned long flags;
 	u16 val;
@@ -270,10 +333,19 @@ static inline void solo_reg_write(struct solo_dev *solo_dev, int reg, u32 data)
 	spin_unlock_irqrestore(&solo_dev->reg_io_lock, flags);
 }
 
-void solo_irq_on(struct solo_dev *solo_dev, u32 mask);
-void solo_irq_off(struct solo_dev *solo_dev, u32 mask);
+static inline void solo_irq_on(struct solo_dev *dev, u32 mask)
+{
+	dev->irq_mask |= mask;
+	solo_reg_write(dev, SOLO_IRQ_MASK, dev->irq_mask);
+}
+
+static inline void solo_irq_off(struct solo_dev *dev, u32 mask)
+{
+	dev->irq_mask &= ~mask;
+	solo_reg_write(dev, SOLO_IRQ_MASK, dev->irq_mask);
+}
 
-/* Init/exit routeines for subsystems */
+/* Init/exit routines for subsystems */
 int solo_disp_init(struct solo_dev *solo_dev);
 void solo_disp_exit(struct solo_dev *solo_dev);
 
@@ -286,13 +358,13 @@ void solo_i2c_exit(struct solo_dev *solo_dev);
 int solo_p2m_init(struct solo_dev *solo_dev);
 void solo_p2m_exit(struct solo_dev *solo_dev);
 
-int solo_v4l2_init(struct solo_dev *solo_dev);
+int solo_v4l2_init(struct solo_dev *solo_dev, unsigned nr);
 void solo_v4l2_exit(struct solo_dev *solo_dev);
 
 int solo_enc_init(struct solo_dev *solo_dev);
 void solo_enc_exit(struct solo_dev *solo_dev);
 
-int solo_enc_v4l2_init(struct solo_dev *solo_dev);
+int solo_enc_v4l2_init(struct solo_dev *solo_dev, unsigned nr);
 void solo_enc_v4l2_exit(struct solo_dev *solo_dev);
 
 int solo_g723_init(struct solo_dev *solo_dev);
@@ -301,7 +373,7 @@ void solo_g723_exit(struct solo_dev *solo_dev);
 /* ISR's */
 int solo_i2c_isr(struct solo_dev *solo_dev);
 void solo_p2m_isr(struct solo_dev *solo_dev, int id);
-void solo_p2m_error_isr(struct solo_dev *solo_dev, u32 status);
+void solo_p2m_error_isr(struct solo_dev *solo_dev);
 void solo_enc_v4l2_isr(struct solo_dev *solo_dev);
 void solo_g723_isr(struct solo_dev *solo_dev);
 void solo_motion_isr(struct solo_dev *solo_dev);
@@ -313,24 +385,43 @@ void solo_i2c_writebyte(struct solo_dev *solo_dev, int id, u8 addr, u8 off,
 			u8 data);
 
 /* P2M DMA */
-int solo_p2m_dma_t(struct solo_dev *solo_dev, u8 id, int wr,
-		   dma_addr_t dma_addr, u32 ext_addr, u32 size);
-int solo_p2m_dma(struct solo_dev *solo_dev, u8 id, int wr,
-		 void *sys_addr, u32 ext_addr, u32 size);
-int solo_p2m_dma_sg(struct solo_dev *solo_dev, u8 id,
-		    struct p2m_desc *pdesc, int wr,
-		    struct scatterlist *sglist, u32 sg_off,
-		    u32 ext_addr, u32 size);
-void solo_p2m_push_desc(struct p2m_desc *desc, int wr, dma_addr_t dma_addr,
-			u32 ext_addr, u32 size, int repeat, u32 ext_size);
-int solo_p2m_dma_desc(struct solo_dev *solo_dev, u8 id,
-		      struct p2m_desc *desc, int desc_count);
+int solo_p2m_dma_t(struct solo_dev *solo_dev, int wr,
+		   dma_addr_t dma_addr, u32 ext_addr, u32 size,
+		   int repeat, u32 ext_size);
+int solo_p2m_dma(struct solo_dev *solo_dev, int wr,
+		 void *sys_addr, u32 ext_addr, u32 size,
+		 int repeat, u32 ext_size);
+void solo_p2m_fill_desc(struct solo_p2m_desc *desc, int wr,
+			dma_addr_t dma_addr, u32 ext_addr, u32 size,
+			int repeat, u32 ext_size);
+int solo_p2m_dma_desc(struct solo_dev *solo_dev,
+		      struct solo_p2m_desc *desc, dma_addr_t desc_dma,
+		      int desc_cnt);
+
+/* Global s_std ioctl */
+int solo_set_video_type(struct solo_dev *solo_dev, bool type);
+void solo_update_mode(struct solo_enc_dev *solo_enc);
 
 /* Set the threshold for motion detection */
-void solo_set_motion_threshold(struct solo_dev *solo_dev, u8 ch, u16 val);
+int solo_set_motion_threshold(struct solo_dev *solo_dev, u8 ch, u16 val);
+int solo_set_motion_block(struct solo_dev *solo_dev, u8 ch,
+		const struct solo_motion_thresholds *thresholds);
 #define SOLO_DEF_MOT_THRESH		0x0300
 
 /* Write text on OSD */
 int solo_osd_print(struct solo_enc_dev *solo_enc);
 
+/* EEPROM commands */
+unsigned int solo_eeprom_ewen(struct solo_dev *solo_dev, int w_en);
+unsigned short solo_eeprom_read(struct solo_dev *solo_dev, int loc);
+int solo_eeprom_write(struct solo_dev *solo_dev, int loc,
+		      unsigned short data);
+
+/* JPEG Qp functions */
+void solo_s_jpeg_qp(struct solo_dev *solo_dev, unsigned int ch,
+		    unsigned int qp);
+int solo_g_jpeg_qp(struct solo_dev *solo_dev, unsigned int ch);
+
+#define CHK_FLAGS(v, flags) (((v) & (flags)) == (flags))
+
 #endif /* __SOLO6X10_H */
diff --git a/drivers/staging/media/solo6x10/tw28.c b/drivers/staging/media/solo6x10/tw28.c
deleted file mode 100644
index db56b42..0000000
--- a/drivers/staging/media/solo6x10/tw28.c
+++ /dev/null
@@ -1,821 +0,0 @@
-/*
- * Copyright (C) 2010 Bluecherry, LLC www.bluecherrydvr.com
- * Copyright (C) 2010 Ben Collins <bcollins@bluecherry.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You 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 "solo6x10.h"
-#include "tw28.h"
-
-/* XXX: Some of these values are masked into an 8-bit regs, and shifted
- * around for other 8-bit regs. What are the magic bits in these values? */
-#define DEFAULT_HDELAY_NTSC		(32 - 4)
-#define DEFAULT_HACTIVE_NTSC		(720 + 16)
-#define DEFAULT_VDELAY_NTSC		(7 - 2)
-#define DEFAULT_VACTIVE_NTSC		(240 + 4)
-
-#define DEFAULT_HDELAY_PAL		(32 + 4)
-#define DEFAULT_HACTIVE_PAL		(864-DEFAULT_HDELAY_PAL)
-#define DEFAULT_VDELAY_PAL		(6)
-#define DEFAULT_VACTIVE_PAL		(312-DEFAULT_VDELAY_PAL)
-
-static u8 tbl_tw2864_template[] = {
-	0x00, 0x00, 0x80, 0x10, 0x80, 0x80, 0x00, 0x02, /* 0x00 */
-	0x12, 0xf5, 0x09, 0xd0, 0x00, 0x00, 0x00, 0x7f,
-	0x00, 0x00, 0x80, 0x10, 0x80, 0x80, 0x00, 0x02, /* 0x10 */
-	0x12, 0xf5, 0x09, 0xd0, 0x00, 0x00, 0x00, 0x7f,
-	0x00, 0x00, 0x80, 0x10, 0x80, 0x80, 0x00, 0x02, /* 0x20 */
-	0x12, 0xf5, 0x09, 0xd0, 0x00, 0x00, 0x00, 0x7f,
-	0x00, 0x00, 0x80, 0x10, 0x80, 0x80, 0x00, 0x02, /* 0x30 */
-	0x12, 0xf5, 0x09, 0xd0, 0x00, 0x00, 0x00, 0x7f,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40 */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50 */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60 */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70 */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA3, 0x00,
-	0x00, 0x02, 0x00, 0xcc, 0x00, 0x80, 0x44, 0x50, /* 0x80 */
-	0x22, 0x01, 0xd8, 0xbc, 0xb8, 0x44, 0x38, 0x00,
-	0x00, 0x78, 0x72, 0x3e, 0x14, 0xa5, 0xe4, 0x05, /* 0x90 */
-	0x00, 0x28, 0x44, 0x44, 0xa0, 0x88, 0x5a, 0x01,
-	0x08, 0x08, 0x08, 0x08, 0x1a, 0x1a, 0x1a, 0x1a, /* 0xa0 */
-	0x00, 0x00, 0x00, 0xf0, 0xf0, 0xf0, 0xf0, 0x44,
-	0x44, 0x0a, 0x00, 0xff, 0xef, 0xef, 0xef, 0xef, /* 0xb0 */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0 */
-	0x00, 0x00, 0x55, 0x00, 0xb1, 0xe4, 0x40, 0x00,
-	0x77, 0x77, 0x01, 0x13, 0x57, 0x9b, 0xdf, 0x20, /* 0xd0 */
-	0x64, 0xa8, 0xec, 0xd1, 0x0f, 0x11, 0x11, 0x81,
-	0x10, 0xe0, 0xbb, 0xbb, 0x00, 0x11, 0x00, 0x00, /* 0xe0 */
-	0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0x11, 0x00,
-	0x83, 0xb5, 0x09, 0x78, 0x85, 0x00, 0x01, 0x20, /* 0xf0 */
-	0x64, 0x11, 0x40, 0xaf, 0xff, 0x00, 0x00, 0x00,
-};
-
-static u8 tbl_tw2865_ntsc_template[] = {
-	0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x02, /* 0x00 */
-	0x12, 0xff, 0x09, 0xd0, 0x00, 0x00, 0x00, 0x7f,
-	0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x02, /* 0x10 */
-	0x12, 0xff, 0x09, 0xd0, 0x00, 0x00, 0x00, 0x7f,
-	0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x02, /* 0x20 */
-	0x12, 0xff, 0x09, 0xd0, 0x00, 0x00, 0x00, 0x7f,
-	0x00, 0xf0, 0x70, 0x48, 0x80, 0x80, 0x00, 0x02, /* 0x30 */
-	0x12, 0xff, 0x09, 0xd0, 0x00, 0x00, 0x00, 0x7f,
-	0x00, 0x00, 0x90, 0x68, 0x00, 0x38, 0x80, 0x80, /* 0x40 */
-	0x80, 0x80, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50 */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x45, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60 */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x43,
-	0x08, 0x00, 0x00, 0x01, 0xf1, 0x03, 0xEF, 0x03, /* 0x70 */
-	0xE9, 0x03, 0xD9, 0x15, 0x15, 0xE4, 0xA3, 0x80,
-	0x00, 0x02, 0x00, 0xCC, 0x00, 0x80, 0x44, 0x50, /* 0x80 */
-	0x22, 0x01, 0xD8, 0xBC, 0xB8, 0x44, 0x38, 0x00,
-	0x00, 0x78, 0x44, 0x3D, 0x14, 0xA5, 0xE0, 0x05, /* 0x90 */
-	0x00, 0x28, 0x44, 0x44, 0xA0, 0x90, 0x52, 0x13,
-	0x08, 0x08, 0x08, 0x08, 0x1A, 0x1A, 0x1B, 0x1A, /* 0xa0 */
-	0x00, 0x00, 0x00, 0xF0, 0xF0, 0xF0, 0xF0, 0x44,
-	0x44, 0x4A, 0x00, 0xFF, 0xEF, 0xEF, 0xEF, 0xEF, /* 0xb0 */
-	0xFF, 0xE7, 0xE9, 0xE9, 0xEB, 0xFF, 0xD6, 0xD8,
-	0xD8, 0xD7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0 */
-	0x00, 0x00, 0x55, 0x00, 0xE4, 0x39, 0x00, 0x80,
-	0x77, 0x77, 0x03, 0x20, 0x57, 0x9b, 0xdf, 0x31, /* 0xd0 */
-	0x64, 0xa8, 0xec, 0xd1, 0x0f, 0x11, 0x11, 0x81,
-	0x10, 0xC0, 0xAA, 0xAA, 0x00, 0x11, 0x00, 0x00, /* 0xe0 */
-	0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0x11, 0x00,
-	0x83, 0xB5, 0x09, 0x78, 0x85, 0x00, 0x01, 0x20, /* 0xf0 */
-	0x64, 0x51, 0x40, 0xaf, 0xFF, 0xF0, 0x00, 0xC0,
-};
-
-static u8 tbl_tw2865_pal_template[] = {
-	0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12, /* 0x00 */
-	0x11, 0xff, 0x01, 0xc3, 0x00, 0x00, 0x01, 0x7f,
-	0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12, /* 0x10 */
-	0x11, 0xff, 0x01, 0xc3, 0x00, 0x00, 0x01, 0x7f,
-	0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12, /* 0x20 */
-	0x11, 0xff, 0x01, 0xc3, 0x00, 0x00, 0x01, 0x7f,
-	0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12, /* 0x30 */
-	0x11, 0xff, 0x01, 0xc3, 0x00, 0x00, 0x01, 0x7f,
-	0x00, 0x94, 0x90, 0x48, 0x00, 0x38, 0x7F, 0x80, /* 0x40 */
-	0x80, 0x80, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50 */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x45, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60 */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x43,
-	0x08, 0x00, 0x00, 0x01, 0xf1, 0x03, 0xEF, 0x03, /* 0x70 */
-	0xEA, 0x03, 0xD9, 0x15, 0x15, 0xE4, 0xA3, 0x80,
-	0x00, 0x02, 0x00, 0xCC, 0x00, 0x80, 0x44, 0x50, /* 0x80 */
-	0x22, 0x01, 0xD8, 0xBC, 0xB8, 0x44, 0x38, 0x00,
-	0x00, 0x78, 0x44, 0x3D, 0x14, 0xA5, 0xE0, 0x05, /* 0x90 */
-	0x00, 0x28, 0x44, 0x44, 0xA0, 0x90, 0x52, 0x13,
-	0x08, 0x08, 0x08, 0x08, 0x1A, 0x1A, 0x1A, 0x1A, /* 0xa0 */
-	0x00, 0x00, 0x00, 0xF0, 0xF0, 0xF0, 0xF0, 0x44,
-	0x44, 0x4A, 0x00, 0xFF, 0xEF, 0xEF, 0xEF, 0xEF, /* 0xb0 */
-	0xFF, 0xE7, 0xE9, 0xE9, 0xE9, 0xFF, 0xD7, 0xD8,
-	0xD9, 0xD8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0 */
-	0x00, 0x00, 0x55, 0x00, 0xE4, 0x39, 0x00, 0x80,
-	0x77, 0x77, 0x03, 0x20, 0x57, 0x9b, 0xdf, 0x31, /* 0xd0 */
-	0x64, 0xa8, 0xec, 0xd1, 0x0f, 0x11, 0x11, 0x81,
-	0x10, 0xC0, 0xAA, 0xAA, 0x00, 0x11, 0x00, 0x00, /* 0xe0 */
-	0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0x11, 0x00,
-	0x83, 0xB5, 0x09, 0x00, 0xA0, 0x00, 0x01, 0x20, /* 0xf0 */
-	0x64, 0x51, 0x40, 0xaf, 0xFF, 0xF0, 0x00, 0xC0,
-};
-
-#define is_tw286x(__solo, __id) (!(__solo->tw2815 & (1 << __id)))
-
-static u8 tw_readbyte(struct solo_dev *solo_dev, int chip_id, u8 tw6x_off,
-		      u8 tw_off)
-{
-	if (is_tw286x(solo_dev, chip_id))
-		return solo_i2c_readbyte(solo_dev, SOLO_I2C_TW,
-					 TW_CHIP_OFFSET_ADDR(chip_id),
-					 tw6x_off);
-	else
-		return solo_i2c_readbyte(solo_dev, SOLO_I2C_TW,
-					 TW_CHIP_OFFSET_ADDR(chip_id),
-					 tw_off);
-}
-
-static void tw_writebyte(struct solo_dev *solo_dev, int chip_id,
-			 u8 tw6x_off, u8 tw_off, u8 val)
-{
-	if (is_tw286x(solo_dev, chip_id))
-		solo_i2c_writebyte(solo_dev, SOLO_I2C_TW,
-				   TW_CHIP_OFFSET_ADDR(chip_id),
-				   tw6x_off, val);
-	else
-		solo_i2c_writebyte(solo_dev, SOLO_I2C_TW,
-				   TW_CHIP_OFFSET_ADDR(chip_id),
-				   tw_off, val);
-}
-
-static void tw_write_and_verify(struct solo_dev *solo_dev, u8 addr, u8 off,
-				u8 val)
-{
-	int i;
-
-	for (i = 0; i < 5; i++) {
-		u8 rval = solo_i2c_readbyte(solo_dev, SOLO_I2C_TW, addr, off);
-		if (rval == val)
-			return;
-
-		solo_i2c_writebyte(solo_dev, SOLO_I2C_TW, addr, off, val);
-		msleep_interruptible(1);
-	}
-
-/*	printk("solo6x10/tw28: Error writing register: %02x->%02x [%02x]\n",
-		addr, off, val); */
-}
-
-static int tw2865_setup(struct solo_dev *solo_dev, u8 dev_addr)
-{
-	u8 tbl_tw2865_common[256];
-	int i;
-
-	if (solo_dev->video_type == SOLO_VO_FMT_TYPE_PAL)
-		memcpy(tbl_tw2865_common, tbl_tw2865_pal_template,
-		       sizeof(tbl_tw2865_common));
-	else
-		memcpy(tbl_tw2865_common, tbl_tw2865_ntsc_template,
-		       sizeof(tbl_tw2865_common));
-
-	/* ALINK Mode */
-	if (solo_dev->nr_chans == 4) {
-		tbl_tw2865_common[0xd2] = 0x01;
-		tbl_tw2865_common[0xcf] = 0x00;
-	} else if (solo_dev->nr_chans == 8) {
-		tbl_tw2865_common[0xd2] = 0x02;
-		if (dev_addr == TW_CHIP_OFFSET_ADDR(1))
-			tbl_tw2865_common[0xcf] = 0x80;
-	} else if (solo_dev->nr_chans == 16) {
-		tbl_tw2865_common[0xd2] = 0x03;
-		if (dev_addr == TW_CHIP_OFFSET_ADDR(1))
-			tbl_tw2865_common[0xcf] = 0x83;
-		else if (dev_addr == TW_CHIP_OFFSET_ADDR(2))
-			tbl_tw2865_common[0xcf] = 0x83;
-		else if (dev_addr == TW_CHIP_OFFSET_ADDR(3))
-			tbl_tw2865_common[0xcf] = 0x80;
-	}
-
-	for (i = 0; i < 0xff; i++) {
-		/* Skip read only registers */
-		if (i >= 0xb8 && i <= 0xc1)
-			continue;
-		if ((i & ~0x30) == 0x00 ||
-		    (i & ~0x30) == 0x0c ||
-		    (i & ~0x30) == 0x0d)
-			continue;
-		if (i >= 0xc4 && i <= 0xc7)
-			continue;
-		if (i == 0xfd)
-			continue;
-
-		tw_write_and_verify(solo_dev, dev_addr, i,
-				    tbl_tw2865_common[i]);
-	}
-
-	return 0;
-}
-
-static int tw2864_setup(struct solo_dev *solo_dev, u8 dev_addr)
-{
-	u8 tbl_tw2864_common[sizeof(tbl_tw2864_template)];
-	int i;
-
-	memcpy(tbl_tw2864_common, tbl_tw2864_template,
-	       sizeof(tbl_tw2864_common));
-
-	if (solo_dev->tw2865 == 0) {
-		/* IRQ Mode */
-		if (solo_dev->nr_chans == 4) {
-			tbl_tw2864_common[0xd2] = 0x01;
-			tbl_tw2864_common[0xcf] = 0x00;
-		} else if (solo_dev->nr_chans == 8) {
-			tbl_tw2864_common[0xd2] = 0x02;
-			if (dev_addr == TW_CHIP_OFFSET_ADDR(0))
-				tbl_tw2864_common[0xcf] = 0x43;
-			else if (dev_addr == TW_CHIP_OFFSET_ADDR(1))
-				tbl_tw2864_common[0xcf] = 0x40;
-		} else if (solo_dev->nr_chans == 16) {
-			tbl_tw2864_common[0xd2] = 0x03;
-			if (dev_addr == TW_CHIP_OFFSET_ADDR(0))
-				tbl_tw2864_common[0xcf] = 0x43;
-			else if (dev_addr == TW_CHIP_OFFSET_ADDR(1))
-				tbl_tw2864_common[0xcf] = 0x43;
-			else if (dev_addr == TW_CHIP_OFFSET_ADDR(2))
-				tbl_tw2864_common[0xcf] = 0x43;
-			else if (dev_addr == TW_CHIP_OFFSET_ADDR(3))
-				tbl_tw2864_common[0xcf] = 0x40;
-		}
-	} else {
-		/* ALINK Mode. Assumes that the first tw28xx is a
-		 * 2865 and these are in cascade. */
-		for (i = 0; i <= 4; i++)
-			tbl_tw2864_common[0x08 | i << 4] = 0x12;
-
-		if (solo_dev->nr_chans == 8) {
-			tbl_tw2864_common[0xd2] = 0x02;
-			if (dev_addr == TW_CHIP_OFFSET_ADDR(1))
-				tbl_tw2864_common[0xcf] = 0x80;
-		} else if (solo_dev->nr_chans == 16) {
-			tbl_tw2864_common[0xd2] = 0x03;
-			if (dev_addr == TW_CHIP_OFFSET_ADDR(1))
-				tbl_tw2864_common[0xcf] = 0x83;
-			else if (dev_addr == TW_CHIP_OFFSET_ADDR(2))
-				tbl_tw2864_common[0xcf] = 0x83;
-			else if (dev_addr == TW_CHIP_OFFSET_ADDR(3))
-				tbl_tw2864_common[0xcf] = 0x80;
-		}
-	}
-
-	/* NTSC or PAL */
-	if (solo_dev->video_type == SOLO_VO_FMT_TYPE_PAL) {
-		for (i = 0; i < 4; i++) {
-			tbl_tw2864_common[0x07 | (i << 4)] |= 0x10;
-			tbl_tw2864_common[0x08 | (i << 4)] |= 0x06;
-			tbl_tw2864_common[0x0a | (i << 4)] |= 0x08;
-			tbl_tw2864_common[0x0b | (i << 4)] |= 0x13;
-			tbl_tw2864_common[0x0e | (i << 4)] |= 0x01;
-		}
-		tbl_tw2864_common[0x9d] = 0x90;
-		tbl_tw2864_common[0xf3] = 0x00;
-		tbl_tw2864_common[0xf4] = 0xa0;
-	}
-
-	for (i = 0; i < 0xff; i++) {
-		/* Skip read only registers */
-		if (i >= 0xb8 && i <= 0xc1)
-			continue;
-		if ((i & ~0x30) == 0x00 ||
-		    (i & ~0x30) == 0x0c ||
-		    (i & ~0x30) == 0x0d)
-			continue;
-		if (i == 0x74 || i == 0x77 || i == 0x78 ||
-		    i == 0x79 || i == 0x7a)
-			continue;
-		if (i == 0xfd)
-			continue;
-
-		tw_write_and_verify(solo_dev, dev_addr, i,
-				    tbl_tw2864_common[i]);
-	}
-
-	return 0;
-}
-
-static int tw2815_setup(struct solo_dev *solo_dev, u8 dev_addr)
-{
-	u8 tbl_ntsc_tw2815_common[] = {
-		0x00, 0xc8, 0x20, 0xd0, 0x06, 0xf0, 0x08, 0x80,
-		0x80, 0x80, 0x80, 0x02, 0x06, 0x00, 0x11,
-	};
-
-	u8 tbl_pal_tw2815_common[] = {
-		0x00, 0x88, 0x20, 0xd0, 0x05, 0x20, 0x28, 0x80,
-		0x80, 0x80, 0x80, 0x82, 0x06, 0x00, 0x11,
-	};
-
-	u8 tbl_tw2815_sfr[] = {
-		0x00, 0x00, 0x00, 0xc0, 0x45, 0xa0, 0xd0, 0x2f, /* 0x00 */
-		0x64, 0x80, 0x80, 0x82, 0x82, 0x00, 0x00, 0x00,
-		0x00, 0x0f, 0x05, 0x00, 0x00, 0x80, 0x06, 0x00, /* 0x10 */
-		0x00, 0x00, 0x00, 0xff, 0x8f, 0x00, 0x00, 0x00,
-		0x88, 0x88, 0xc0, 0x00, 0x20, 0x64, 0xa8, 0xec, /* 0x20 */
-		0x31, 0x75, 0xb9, 0xfd, 0x00, 0x00, 0x88, 0x88,
-		0x88, 0x11, 0x00, 0x88, 0x88, 0x00,		/* 0x30 */
-	};
-	u8 *tbl_tw2815_common;
-	int i;
-	int ch;
-
-	tbl_ntsc_tw2815_common[0x06] = 0;
-
-	/* Horizontal Delay Control */
-	tbl_ntsc_tw2815_common[0x02] = DEFAULT_HDELAY_NTSC & 0xff;
-	tbl_ntsc_tw2815_common[0x06] |= 0x03 & (DEFAULT_HDELAY_NTSC >> 8);
-
-	/* Horizontal Active Control */
-	tbl_ntsc_tw2815_common[0x03] = DEFAULT_HACTIVE_NTSC & 0xff;
-	tbl_ntsc_tw2815_common[0x06] |=
-		((0x03 & (DEFAULT_HACTIVE_NTSC >> 8)) << 2);
-
-	/* Vertical Delay Control */
-	tbl_ntsc_tw2815_common[0x04] = DEFAULT_VDELAY_NTSC & 0xff;
-	tbl_ntsc_tw2815_common[0x06] |=
-		((0x01 & (DEFAULT_VDELAY_NTSC >> 8)) << 4);
-
-	/* Vertical Active Control */
-	tbl_ntsc_tw2815_common[0x05] = DEFAULT_VACTIVE_NTSC & 0xff;
-	tbl_ntsc_tw2815_common[0x06] |=
-		((0x01 & (DEFAULT_VACTIVE_NTSC >> 8)) << 5);
-
-	tbl_pal_tw2815_common[0x06] = 0;
-
-	/* Horizontal Delay Control */
-	tbl_pal_tw2815_common[0x02] = DEFAULT_HDELAY_PAL & 0xff;
-	tbl_pal_tw2815_common[0x06] |= 0x03 & (DEFAULT_HDELAY_PAL >> 8);
-
-	/* Horizontal Active Control */
-	tbl_pal_tw2815_common[0x03] = DEFAULT_HACTIVE_PAL & 0xff;
-	tbl_pal_tw2815_common[0x06] |=
-		((0x03 & (DEFAULT_HACTIVE_PAL >> 8)) << 2);
-
-	/* Vertical Delay Control */
-	tbl_pal_tw2815_common[0x04] = DEFAULT_VDELAY_PAL & 0xff;
-	tbl_pal_tw2815_common[0x06] |=
-		((0x01 & (DEFAULT_VDELAY_PAL >> 8)) << 4);
-
-	/* Vertical Active Control */
-	tbl_pal_tw2815_common[0x05] = DEFAULT_VACTIVE_PAL & 0xff;
-	tbl_pal_tw2815_common[0x06] |=
-		((0x01 & (DEFAULT_VACTIVE_PAL >> 8)) << 5);
-
-	tbl_tw2815_common =
-	    (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) ?
-	     tbl_ntsc_tw2815_common : tbl_pal_tw2815_common;
-
-	/* Dual ITU-R BT.656 format */
-	tbl_tw2815_common[0x0d] |= 0x04;
-
-	/* Audio configuration */
-	tbl_tw2815_sfr[0x62 - 0x40] &= ~(3 << 6);
-
-	if (solo_dev->nr_chans == 4) {
-		tbl_tw2815_sfr[0x63 - 0x40] |= 1;
-		tbl_tw2815_sfr[0x62 - 0x40] |= 3 << 6;
-	} else if (solo_dev->nr_chans == 8) {
-		tbl_tw2815_sfr[0x63 - 0x40] |= 2;
-		if (dev_addr == TW_CHIP_OFFSET_ADDR(0))
-			tbl_tw2815_sfr[0x62 - 0x40] |= 1 << 6;
-		else if (dev_addr == TW_CHIP_OFFSET_ADDR(1))
-			tbl_tw2815_sfr[0x62 - 0x40] |= 2 << 6;
-	} else if (solo_dev->nr_chans == 16) {
-		tbl_tw2815_sfr[0x63 - 0x40] |= 3;
-		if (dev_addr == TW_CHIP_OFFSET_ADDR(0))
-			tbl_tw2815_sfr[0x62 - 0x40] |= 1 << 6;
-		else if (dev_addr == TW_CHIP_OFFSET_ADDR(1))
-			tbl_tw2815_sfr[0x62 - 0x40] |= 0 << 6;
-		else if (dev_addr == TW_CHIP_OFFSET_ADDR(2))
-			tbl_tw2815_sfr[0x62 - 0x40] |= 0 << 6;
-		else if (dev_addr == TW_CHIP_OFFSET_ADDR(3))
-			tbl_tw2815_sfr[0x62 - 0x40] |= 2 << 6;
-	}
-
-	/* Output mode of R_ADATM pin (0 mixing, 1 record) */
-	/* tbl_tw2815_sfr[0x63 - 0x40] |= 0 << 2; */
-
-	/* 8KHz, used to be 16KHz, but changed for remote client compat */
-	tbl_tw2815_sfr[0x62 - 0x40] |= 0 << 2;
-	tbl_tw2815_sfr[0x6c - 0x40] |= 0 << 2;
-
-	/* Playback of right channel */
-	tbl_tw2815_sfr[0x6c - 0x40] |= 1 << 5;
-
-	/* Reserved value (XXX ??) */
-	tbl_tw2815_sfr[0x5c - 0x40] |= 1 << 5;
-
-	/* Analog output gain and mix ratio playback on full */
-	tbl_tw2815_sfr[0x70 - 0x40] |= 0xff;
-	/* Select playback audio and mute all except */
-	tbl_tw2815_sfr[0x71 - 0x40] |= 0x10;
-	tbl_tw2815_sfr[0x6d - 0x40] |= 0x0f;
-
-	/* End of audio configuration */
-
-	for (ch = 0; ch < 4; ch++) {
-		tbl_tw2815_common[0x0d] &= ~3;
-		switch (ch) {
-		case 0:
-			tbl_tw2815_common[0x0d] |= 0x21;
-			break;
-		case 1:
-			tbl_tw2815_common[0x0d] |= 0x20;
-			break;
-		case 2:
-			tbl_tw2815_common[0x0d] |= 0x23;
-			break;
-		case 3:
-			tbl_tw2815_common[0x0d] |= 0x22;
-			break;
-		}
-
-		for (i = 0; i < 0x0f; i++) {
-			if (i == 0x00)
-				continue;	/* read-only */
-			solo_i2c_writebyte(solo_dev, SOLO_I2C_TW,
-					   dev_addr, (ch * 0x10) + i,
-					   tbl_tw2815_common[i]);
-		}
-	}
-
-	for (i = 0x40; i < 0x76; i++) {
-		/* Skip read-only and nop registers */
-		if (i == 0x40 || i == 0x59 || i == 0x5a ||
-		    i == 0x5d || i == 0x5e || i == 0x5f)
-			continue;
-
-		solo_i2c_writebyte(solo_dev, SOLO_I2C_TW, dev_addr, i,
-				       tbl_tw2815_sfr[i - 0x40]);
-	}
-
-	return 0;
-}
-
-#define FIRST_ACTIVE_LINE	0x0008
-#define LAST_ACTIVE_LINE	0x0102
-
-static void saa7128_setup(struct solo_dev *solo_dev)
-{
-	int i;
-	unsigned char regs[128] = {
-		0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x1C, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00,
-		0x59, 0x1d, 0x75, 0x3f, 0x06, 0x3f, 0x00, 0x00,
-		0x1c, 0x33, 0x00, 0x3f, 0x00, 0x00, 0x3f, 0x00,
-		0x1a, 0x1a, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x68, 0x10, 0x97, 0x4c, 0x18,
-		0x9b, 0x93, 0x9f, 0xff, 0x7c, 0x34, 0x3f, 0x3f,
-		0x3f, 0x83, 0x83, 0x80, 0x0d, 0x0f, 0xc3, 0x06,
-		0x02, 0x80, 0x71, 0x77, 0xa7, 0x67, 0x66, 0x2e,
-		0x7b, 0x11, 0x4f, 0x1f, 0x7c, 0xf0, 0x21, 0x77,
-		0x41, 0x88, 0x41, 0x12, 0xed, 0x10, 0x10, 0x00,
-		0x41, 0xc3, 0x00, 0x3e, 0xb8, 0x02, 0x00, 0x00,
-		0x00, 0x00, 0x08, 0xff, 0x80, 0x00, 0xff, 0xff,
-	};
-
-	regs[0x7A] = FIRST_ACTIVE_LINE & 0xff;
-	regs[0x7B] = LAST_ACTIVE_LINE & 0xff;
-	regs[0x7C] = ((1 << 7) |
-			(((LAST_ACTIVE_LINE >> 8) & 1) << 6) |
-			(((FIRST_ACTIVE_LINE >> 8) & 1) << 4));
-
-	/* PAL: XXX: We could do a second set of regs to avoid this */
-	if (solo_dev->video_type != SOLO_VO_FMT_TYPE_NTSC) {
-		regs[0x28] = 0xE1;
-
-		regs[0x5A] = 0x0F;
-		regs[0x61] = 0x02;
-		regs[0x62] = 0x35;
-		regs[0x63] = 0xCB;
-		regs[0x64] = 0x8A;
-		regs[0x65] = 0x09;
-		regs[0x66] = 0x2A;
-
-		regs[0x6C] = 0xf1;
-		regs[0x6E] = 0x20;
-
-		regs[0x7A] = 0x06 + 12;
-		regs[0x7b] = 0x24 + 12;
-		regs[0x7c] |= 1 << 6;
-	}
-
-	/* First 0x25 bytes are read-only? */
-	for (i = 0x26; i < 128; i++) {
-		if (i == 0x60 || i == 0x7D)
-			continue;
-		solo_i2c_writebyte(solo_dev, SOLO_I2C_SAA, 0x46, i, regs[i]);
-	}
-
-	return;
-}
-
-int solo_tw28_init(struct solo_dev *solo_dev)
-{
-	int i;
-	u8 value;
-
-	/* Detect techwell chip type */
-	for (i = 0; i < TW_NUM_CHIP; i++) {
-		value = solo_i2c_readbyte(solo_dev, SOLO_I2C_TW,
-					  TW_CHIP_OFFSET_ADDR(i), 0xFF);
-
-		switch (value >> 3) {
-		case 0x18:
-			solo_dev->tw2865 |= 1 << i;
-			solo_dev->tw28_cnt++;
-			break;
-		case 0x0c:
-			solo_dev->tw2864 |= 1 << i;
-			solo_dev->tw28_cnt++;
-			break;
-		default:
-			value = solo_i2c_readbyte(solo_dev, SOLO_I2C_TW,
-						  TW_CHIP_OFFSET_ADDR(i), 0x59);
-			if ((value >> 3) == 0x04) {
-				solo_dev->tw2815 |= 1 << i;
-				solo_dev->tw28_cnt++;
-			}
-		}
-	}
-
-	if (!solo_dev->tw28_cnt)
-		return -EINVAL;
-
-	saa7128_setup(solo_dev);
-
-	for (i = 0; i < solo_dev->tw28_cnt; i++) {
-		if ((solo_dev->tw2865 & (1 << i)))
-			tw2865_setup(solo_dev, TW_CHIP_OFFSET_ADDR(i));
-		else if ((solo_dev->tw2864 & (1 << i)))
-			tw2864_setup(solo_dev, TW_CHIP_OFFSET_ADDR(i));
-		else
-			tw2815_setup(solo_dev, TW_CHIP_OFFSET_ADDR(i));
-	}
-
-	dev_info(&solo_dev->pdev->dev, "Initialized %d tw28xx chip%s:",
-		 solo_dev->tw28_cnt, solo_dev->tw28_cnt == 1 ? "" : "s");
-
-	if (solo_dev->tw2865)
-		printk(" tw2865[%d]", hweight32(solo_dev->tw2865));
-	if (solo_dev->tw2864)
-		printk(" tw2864[%d]", hweight32(solo_dev->tw2864));
-	if (solo_dev->tw2815)
-		printk(" tw2815[%d]", hweight32(solo_dev->tw2815));
-	printk("\n");
-
-	return 0;
-}
-
-/*
- * We accessed the video status signal in the Techwell chip through
- * iic/i2c because the video status reported by register REG_VI_STATUS1
- * (address 0x012C) of the SOLO6010 chip doesn't give the correct video
- * status signal values.
- */
-int tw28_get_video_status(struct solo_dev *solo_dev, u8 ch)
-{
-	u8 val, chip_num;
-
-	/* Get the right chip and on-chip channel */
-	chip_num = ch / 4;
-	ch %= 4;
-
-	val = tw_readbyte(solo_dev, chip_num, TW286X_AV_STAT_ADDR,
-			  TW_AV_STAT_ADDR) & 0x0f;
-
-	return val & (1 << ch) ? 1 : 0;
-}
-
-#if 0
-/* Status of audio from up to 4 techwell chips are combined into 1 variable.
- * See techwell datasheet for details. */
-u16 tw28_get_audio_status(struct solo_dev *solo_dev)
-{
-	u8 val;
-	u16 status = 0;
-	int i;
-
-	for (i = 0; i < solo_dev->tw28_cnt; i++) {
-		val = (tw_readbyte(solo_dev, i, TW286X_AV_STAT_ADDR,
-				   TW_AV_STAT_ADDR) & 0xf0) >> 4;
-		status |= val << (i * 4);
-	}
-
-	return status;
-}
-#endif
-
-int tw28_set_ctrl_val(struct solo_dev *solo_dev, u32 ctrl, u8 ch, s32 val)
-{
-	char sval;
-	u8 chip_num;
-
-	/* Get the right chip and on-chip channel */
-	chip_num = ch / 4;
-	ch %= 4;
-
-	if (val > 255 || val < 0)
-		return -ERANGE;
-
-	switch (ctrl) {
-	case V4L2_CID_SHARPNESS:
-		/* Only 286x has sharpness */
-		if (val > 0x0f || val < 0)
-			return -ERANGE;
-		if (is_tw286x(solo_dev, chip_num)) {
-			u8 v = solo_i2c_readbyte(solo_dev, SOLO_I2C_TW,
-						 TW_CHIP_OFFSET_ADDR(chip_num),
-						 TW286x_SHARPNESS(chip_num));
-			v &= 0xf0;
-			v |= val;
-			solo_i2c_writebyte(solo_dev, SOLO_I2C_TW,
-					   TW_CHIP_OFFSET_ADDR(chip_num),
-					   TW286x_SHARPNESS(chip_num), v);
-		} else if (val != 0)
-			return -ERANGE;
-		break;
-
-	case V4L2_CID_HUE:
-		if (is_tw286x(solo_dev, chip_num))
-			sval = val - 128;
-		else
-			sval = (char)val;
-		tw_writebyte(solo_dev, chip_num, TW286x_HUE_ADDR(ch),
-			     TW_HUE_ADDR(ch), sval);
-
-		break;
-
-	case V4L2_CID_SATURATION:
-		if (is_tw286x(solo_dev, chip_num)) {
-			solo_i2c_writebyte(solo_dev, SOLO_I2C_TW,
-					   TW_CHIP_OFFSET_ADDR(chip_num),
-					   TW286x_SATURATIONU_ADDR(ch), val);
-		}
-		tw_writebyte(solo_dev, chip_num, TW286x_SATURATIONV_ADDR(ch),
-			     TW_SATURATION_ADDR(ch), val);
-
-		break;
-
-	case V4L2_CID_CONTRAST:
-		tw_writebyte(solo_dev, chip_num, TW286x_CONTRAST_ADDR(ch),
-			     TW_CONTRAST_ADDR(ch), val);
-		break;
-
-	case V4L2_CID_BRIGHTNESS:
-		if (is_tw286x(solo_dev, chip_num))
-			sval = val - 128;
-		else
-			sval = (char)val;
-		tw_writebyte(solo_dev, chip_num, TW286x_BRIGHTNESS_ADDR(ch),
-			     TW_BRIGHTNESS_ADDR(ch), sval);
-
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-int tw28_get_ctrl_val(struct solo_dev *solo_dev, u32 ctrl, u8 ch,
-		      s32 *val)
-{
-	u8 rval, chip_num;
-
-	/* Get the right chip and on-chip channel */
-	chip_num = ch / 4;
-	ch %= 4;
-
-	switch (ctrl) {
-	case V4L2_CID_SHARPNESS:
-		/* Only 286x has sharpness */
-		if (is_tw286x(solo_dev, chip_num)) {
-			rval = solo_i2c_readbyte(solo_dev, SOLO_I2C_TW,
-						 TW_CHIP_OFFSET_ADDR(chip_num),
-						 TW286x_SHARPNESS(chip_num));
-			*val = rval & 0x0f;
-		} else
-			*val = 0;
-		break;
-	case V4L2_CID_HUE:
-		rval = tw_readbyte(solo_dev, chip_num, TW286x_HUE_ADDR(ch),
-				   TW_HUE_ADDR(ch));
-		if (is_tw286x(solo_dev, chip_num))
-			*val = (s32)((char)rval) + 128;
-		else
-			*val = rval;
-		break;
-	case V4L2_CID_SATURATION:
-		*val = tw_readbyte(solo_dev, chip_num,
-				   TW286x_SATURATIONU_ADDR(ch),
-				   TW_SATURATION_ADDR(ch));
-		break;
-	case V4L2_CID_CONTRAST:
-		*val = tw_readbyte(solo_dev, chip_num,
-				   TW286x_CONTRAST_ADDR(ch),
-				   TW_CONTRAST_ADDR(ch));
-		break;
-	case V4L2_CID_BRIGHTNESS:
-		rval = tw_readbyte(solo_dev, chip_num,
-				   TW286x_BRIGHTNESS_ADDR(ch),
-				   TW_BRIGHTNESS_ADDR(ch));
-		if (is_tw286x(solo_dev, chip_num))
-			*val = (s32)((char)rval) + 128;
-		else
-			*val = rval;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-#if 0
-/*
- * For audio output volume, the output channel is only 1. In this case we
- * don't need to offset TW_CHIP_OFFSET_ADDR. The TW_CHIP_OFFSET_ADDR used
- * is the base address of the techwell chip.
- */
-void tw2815_Set_AudioOutVol(struct solo_dev *solo_dev, unsigned int u_val)
-{
-	unsigned int val;
-	unsigned int chip_num;
-
-	chip_num = (solo_dev->nr_chans - 1) / 4;
-
-	val = tw_readbyte(solo_dev, chip_num, TW286x_AUDIO_OUTPUT_VOL_ADDR,
-			  TW_AUDIO_OUTPUT_VOL_ADDR);
-
-	u_val = (val & 0x0f) | (u_val << 4);
-
-	tw_writebyte(solo_dev, chip_num, TW286x_AUDIO_OUTPUT_VOL_ADDR,
-		     TW_AUDIO_OUTPUT_VOL_ADDR, u_val);
-}
-#endif
-
-u8 tw28_get_audio_gain(struct solo_dev *solo_dev, u8 ch)
-{
-	u8 val;
-	u8 chip_num;
-
-	/* Get the right chip and on-chip channel */
-	chip_num = ch / 4;
-	ch %= 4;
-
-	val = tw_readbyte(solo_dev, chip_num,
-			  TW286x_AUDIO_INPUT_GAIN_ADDR(ch),
-			  TW_AUDIO_INPUT_GAIN_ADDR(ch));
-
-	return (ch % 2) ? (val >> 4) : (val & 0x0f);
-}
-
-void tw28_set_audio_gain(struct solo_dev *solo_dev, u8 ch, u8 val)
-{
-	u8 old_val;
-	u8 chip_num;
-
-	/* Get the right chip and on-chip channel */
-	chip_num = ch / 4;
-	ch %= 4;
-
-	old_val = tw_readbyte(solo_dev, chip_num,
-			      TW286x_AUDIO_INPUT_GAIN_ADDR(ch),
-			      TW_AUDIO_INPUT_GAIN_ADDR(ch));
-
-	val = (old_val & ((ch % 2) ? 0x0f : 0xf0)) |
-		((ch % 2) ? (val << 4) : val);
-
-	tw_writebyte(solo_dev, chip_num, TW286x_AUDIO_INPUT_GAIN_ADDR(ch),
-		     TW_AUDIO_INPUT_GAIN_ADDR(ch), val);
-}
diff --git a/drivers/staging/media/solo6x10/tw28.h b/drivers/staging/media/solo6x10/tw28.h
deleted file mode 100644
index a44a03a..0000000
--- a/drivers/staging/media/solo6x10/tw28.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2010 Bluecherry, LLC www.bluecherrydvr.com
- * Copyright (C) 2010 Ben Collins <bcollins@bluecherry.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You 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 __SOLO6X10_TW28_H
-#define __SOLO6X10_TW28_H
-
-#include "solo6x10.h"
-
-#define TW_NUM_CHIP				4
-#define TW_BASE_ADDR				0x28
-#define TW_CHIP_OFFSET_ADDR(n)			(TW_BASE_ADDR + (n))
-
-/* tw2815 */
-#define TW_AV_STAT_ADDR				0x5a
-#define TW_HUE_ADDR(n)				(0x07 | ((n) << 4))
-#define TW_SATURATION_ADDR(n)			(0x08 | ((n) << 4))
-#define TW_CONTRAST_ADDR(n)			(0x09 | ((n) << 4))
-#define TW_BRIGHTNESS_ADDR(n)			(0x0a | ((n) << 4))
-#define TW_AUDIO_OUTPUT_VOL_ADDR		0x70
-#define TW_AUDIO_INPUT_GAIN_ADDR(n)		(0x60 + ((n > 1) ? 1 : 0))
-
-/* tw286x */
-#define TW286X_AV_STAT_ADDR			0xfd
-#define TW286x_HUE_ADDR(n)			(0x06 | ((n) << 4))
-#define TW286x_SATURATIONU_ADDR(n)		(0x04 | ((n) << 4))
-#define TW286x_SATURATIONV_ADDR(n)		(0x05 | ((n) << 4))
-#define TW286x_CONTRAST_ADDR(n)			(0x02 | ((n) << 4))
-#define TW286x_BRIGHTNESS_ADDR(n)		(0x01 | ((n) << 4))
-#define TW286x_SHARPNESS(n)			(0x03 | ((n) << 4))
-#define TW286x_AUDIO_OUTPUT_VOL_ADDR		0xdf
-#define TW286x_AUDIO_INPUT_GAIN_ADDR(n)		(0xD0 + ((n > 1) ? 1 : 0))
-
-int solo_tw28_init(struct solo_dev *solo_dev);
-
-int tw28_set_ctrl_val(struct solo_dev *solo_dev, u32 ctrl, u8 ch, s32 val);
-int tw28_get_ctrl_val(struct solo_dev *solo_dev, u32 ctrl, u8 ch, s32 *val);
-
-u8 tw28_get_audio_gain(struct solo_dev *solo_dev, u8 ch);
-void tw28_set_audio_gain(struct solo_dev *solo_dev, u8 ch, u8 val);
-int tw28_get_video_status(struct solo_dev *solo_dev, u8 ch);
-
-#if 0
-unsigned int tw2815_get_audio_status(struct SOLO *solo);
-void tw2815_Set_AudioOutVol(struct SOLO *solo, unsigned int u_val);
-#endif
-
-#endif /* __SOLO6X10_TW28_H */
diff --git a/drivers/staging/media/solo6x10/v4l2-enc.c b/drivers/staging/media/solo6x10/v4l2-enc.c
deleted file mode 100644
index 4977e86..0000000
--- a/drivers/staging/media/solo6x10/v4l2-enc.c
+++ /dev/null
@@ -1,1829 +0,0 @@
-/*
- * Copyright (C) 2010 Bluecherry, LLC www.bluecherrydvr.com
- * Copyright (C) 2010 Ben Collins <bcollins@bluecherry.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You 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/kthread.h>
-#include <linux/freezer.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-common.h>
-#include <media/videobuf-dma-sg.h>
-#include "solo6x10.h"
-#include "tw28.h"
-#include "solo6x10-jpeg.h"
-
-#define MIN_VID_BUFFERS		4
-#define FRAME_BUF_SIZE		(128 * 1024)
-#define MP4_QS			16
-
-static int solo_enc_thread(void *data);
-
-extern unsigned video_nr;
-
-struct solo_enc_fh {
-	struct			solo_enc_dev *enc;
-	u32			fmt;
-	u16			rd_idx;
-	u8			enc_on;
-	enum solo_enc_types	type;
-	struct videobuf_queue	vidq;
-	struct list_head	vidq_active;
-	struct task_struct	*kthread;
-	struct p2m_desc		desc[SOLO_NR_P2M_DESC];
-};
-
-static const u32 solo_user_ctrls[] = {
-	V4L2_CID_BRIGHTNESS,
-	V4L2_CID_CONTRAST,
-	V4L2_CID_SATURATION,
-	V4L2_CID_HUE,
-	V4L2_CID_SHARPNESS,
-	0
-};
-
-static const u32 solo_mpeg_ctrls[] = {
-	V4L2_CID_MPEG_VIDEO_ENCODING,
-	V4L2_CID_MPEG_VIDEO_GOP_SIZE,
-	0
-};
-
-static const u32 solo_private_ctrls[] = {
-	V4L2_CID_MOTION_ENABLE,
-	V4L2_CID_MOTION_THRESHOLD,
-	0
-};
-
-static const u32 solo_fmtx_ctrls[] = {
-	V4L2_CID_RDS_TX_RADIO_TEXT,
-	0
-};
-
-static const u32 *solo_ctrl_classes[] = {
-	solo_user_ctrls,
-	solo_mpeg_ctrls,
-	solo_fmtx_ctrls,
-	solo_private_ctrls,
-	NULL
-};
-
-static int solo_is_motion_on(struct solo_enc_dev *solo_enc)
-{
-	struct solo_dev *solo_dev = solo_enc->solo_dev;
-	u8 ch = solo_enc->ch;
-
-	if (solo_dev->motion_mask & (1 << ch))
-		return 1;
-	return 0;
-}
-
-static void solo_motion_toggle(struct solo_enc_dev *solo_enc, int on)
-{
-	struct solo_dev *solo_dev = solo_enc->solo_dev;
-	u8 ch = solo_enc->ch;
-
-	spin_lock(&solo_enc->lock);
-
-	if (on)
-		solo_dev->motion_mask |= (1 << ch);
-	else
-		solo_dev->motion_mask &= ~(1 << ch);
-
-	/* Do this regardless of if we are turning on or off */
-	solo_reg_write(solo_enc->solo_dev, SOLO_VI_MOT_CLEAR,
-		       1 << solo_enc->ch);
-	solo_enc->motion_detected = 0;
-
-	solo_reg_write(solo_dev, SOLO_VI_MOT_ADR,
-		       SOLO_VI_MOTION_EN(solo_dev->motion_mask) |
-		       (SOLO_MOTION_EXT_ADDR(solo_dev) >> 16));
-
-	if (solo_dev->motion_mask)
-		solo_irq_on(solo_dev, SOLO_IRQ_MOTION);
-	else
-		solo_irq_off(solo_dev, SOLO_IRQ_MOTION);
-
-	spin_unlock(&solo_enc->lock);
-}
-
-/* Should be called with solo_enc->lock held */
-static void solo_update_mode(struct solo_enc_dev *solo_enc)
-{
-	struct solo_dev *solo_dev = solo_enc->solo_dev;
-
-	assert_spin_locked(&solo_enc->lock);
-
-	solo_enc->interlaced = (solo_enc->mode & 0x08) ? 1 : 0;
-	solo_enc->bw_weight = max(solo_dev->fps / solo_enc->interval, 1);
-
-	switch (solo_enc->mode) {
-	case SOLO_ENC_MODE_CIF:
-		solo_enc->width = solo_dev->video_hsize >> 1;
-		solo_enc->height = solo_dev->video_vsize;
-		break;
-	case SOLO_ENC_MODE_D1:
-		solo_enc->width = solo_dev->video_hsize;
-		solo_enc->height = solo_dev->video_vsize << 1;
-		solo_enc->bw_weight <<= 2;
-		break;
-	default:
-		WARN(1, "mode is unknown\n");
-	}
-}
-
-/* Should be called with solo_enc->lock held */
-static int solo_enc_on(struct solo_enc_fh *fh)
-{
-	struct solo_enc_dev *solo_enc = fh->enc;
-	u8 ch = solo_enc->ch;
-	struct solo_dev *solo_dev = solo_enc->solo_dev;
-	u8 interval;
-
-	assert_spin_locked(&solo_enc->lock);
-
-	if (fh->enc_on)
-		return 0;
-
-	solo_update_mode(solo_enc);
-
-	/* Make sure to bw check on first reader */
-	if (!atomic_read(&solo_enc->readers)) {
-		if (solo_enc->bw_weight > solo_dev->enc_bw_remain)
-			return -EBUSY;
-		else
-			solo_dev->enc_bw_remain -= solo_enc->bw_weight;
-	}
-
-	fh->enc_on = 1;
-	fh->rd_idx = solo_enc->solo_dev->enc_wr_idx;
-
-	if (fh->type == SOLO_ENC_TYPE_EXT)
-		solo_reg_write(solo_dev, SOLO_CAP_CH_COMP_ENA_E(ch), 1);
-
-	if (atomic_inc_return(&solo_enc->readers) > 1)
-		return 0;
-
-	/* Disable all encoding for this channel */
-	solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(ch), 0);
-
-	/* Common for both std and ext encoding */
-	solo_reg_write(solo_dev, SOLO_VE_CH_INTL(ch),
-		       solo_enc->interlaced ? 1 : 0);
-
-	if (solo_enc->interlaced)
-		interval = solo_enc->interval - 1;
-	else
-		interval = solo_enc->interval;
-
-	/* Standard encoding only */
-	solo_reg_write(solo_dev, SOLO_VE_CH_GOP(ch), solo_enc->gop);
-	solo_reg_write(solo_dev, SOLO_VE_CH_QP(ch), solo_enc->qp);
-	solo_reg_write(solo_dev, SOLO_CAP_CH_INTV(ch), interval);
-
-	/* Extended encoding only */
-	solo_reg_write(solo_dev, SOLO_VE_CH_GOP_E(ch), solo_enc->gop);
-	solo_reg_write(solo_dev, SOLO_VE_CH_QP_E(ch), solo_enc->qp);
-	solo_reg_write(solo_dev, SOLO_CAP_CH_INTV_E(ch), interval);
-
-	/* Enables the standard encoder */
-	solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(ch), solo_enc->mode);
-
-	/* Settle down Beavis... */
-	mdelay(10);
-
-	return 0;
-}
-
-static void solo_enc_off(struct solo_enc_fh *fh)
-{
-	struct solo_enc_dev *solo_enc = fh->enc;
-	struct solo_dev *solo_dev = solo_enc->solo_dev;
-
-	if (!fh->enc_on)
-		return;
-
-	if (fh->kthread) {
-		kthread_stop(fh->kthread);
-		fh->kthread = NULL;
-	}
-
-	solo_dev->enc_bw_remain += solo_enc->bw_weight;
-	fh->enc_on = 0;
-
-	if (atomic_dec_return(&solo_enc->readers) > 0)
-		return;
-
-	solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(solo_enc->ch), 0);
-	solo_reg_write(solo_dev, SOLO_CAP_CH_COMP_ENA_E(solo_enc->ch), 0);
-}
-
-static int solo_start_fh_thread(struct solo_enc_fh *fh)
-{
-	struct solo_enc_dev *solo_enc = fh->enc;
-
-	fh->kthread = kthread_run(solo_enc_thread, fh, SOLO6X10_NAME "_enc");
-
-	/* Oops, we had a problem */
-	if (IS_ERR(fh->kthread)) {
-		spin_lock(&solo_enc->lock);
-		solo_enc_off(fh);
-		spin_unlock(&solo_enc->lock);
-
-		return PTR_ERR(fh->kthread);
-	}
-
-	return 0;
-}
-
-static void enc_reset_gop(struct solo_dev *solo_dev, u8 ch)
-{
-	BUG_ON(ch >= solo_dev->nr_chans);
-	solo_reg_write(solo_dev, SOLO_VE_CH_GOP(ch), 1);
-	solo_dev->v4l2_enc[ch]->reset_gop = 1;
-}
-
-static int enc_gop_reset(struct solo_dev *solo_dev, u8 ch, u8 vop)
-{
-	BUG_ON(ch >= solo_dev->nr_chans);
-	if (!solo_dev->v4l2_enc[ch]->reset_gop)
-		return 0;
-	if (vop)
-		return 1;
-	solo_dev->v4l2_enc[ch]->reset_gop = 0;
-	solo_reg_write(solo_dev, SOLO_VE_CH_GOP(ch),
-		       solo_dev->v4l2_enc[ch]->gop);
-	return 0;
-}
-
-static void enc_write_sg(struct scatterlist *sglist, void *buf, int size)
-{
-	struct scatterlist *sg;
-	u8 *src = buf;
-
-	for (sg = sglist; sg && size > 0; sg = sg_next(sg)) {
-		u8 *p = sg_virt(sg);
-		size_t len = sg_dma_len(sg);
-		int i;
-
-		for (i = 0; i < len && size; i++)
-			p[i] = *(src++);
-	}
-}
-
-static int enc_get_mpeg_dma_sg(struct solo_dev *solo_dev,
-			       struct p2m_desc *desc,
-			       struct scatterlist *sglist, int skip,
-			       unsigned int off, unsigned int size)
-{
-	int ret;
-
-	if (off > SOLO_MP4E_EXT_SIZE(solo_dev))
-		return -EINVAL;
-
-	if (off + size <= SOLO_MP4E_EXT_SIZE(solo_dev)) {
-		return solo_p2m_dma_sg(solo_dev, SOLO_P2M_DMA_ID_MP4E,
-				       desc, 0, sglist, skip,
-				       SOLO_MP4E_EXT_ADDR(solo_dev) + off, size);
-	}
-
-	/* Buffer wrap */
-	ret = solo_p2m_dma_sg(solo_dev, SOLO_P2M_DMA_ID_MP4E, desc, 0,
-			      sglist, skip, SOLO_MP4E_EXT_ADDR(solo_dev) + off,
-			      SOLO_MP4E_EXT_SIZE(solo_dev) - off);
-
-	ret |= solo_p2m_dma_sg(solo_dev, SOLO_P2M_DMA_ID_MP4E, desc, 0,
-			       sglist, skip + SOLO_MP4E_EXT_SIZE(solo_dev) - off,
-			       SOLO_MP4E_EXT_ADDR(solo_dev),
-			       size + off - SOLO_MP4E_EXT_SIZE(solo_dev));
-
-	return ret;
-}
-
-static int enc_get_mpeg_dma_t(struct solo_dev *solo_dev,
-			      dma_addr_t buf, unsigned int off,
-			      unsigned int size)
-{
-	int ret;
-
-	if (off > SOLO_MP4E_EXT_SIZE(solo_dev))
-		return -EINVAL;
-
-	if (off + size <= SOLO_MP4E_EXT_SIZE(solo_dev)) {
-		return solo_p2m_dma_t(solo_dev, SOLO_P2M_DMA_ID_MP4E, 0, buf,
-				      SOLO_MP4E_EXT_ADDR(solo_dev) + off, size);
-	}
-
-	/* Buffer wrap */
-	ret = solo_p2m_dma_t(solo_dev, SOLO_P2M_DMA_ID_MP4E, 0, buf,
-			     SOLO_MP4E_EXT_ADDR(solo_dev) + off,
-			     SOLO_MP4E_EXT_SIZE(solo_dev) - off);
-
-	ret |= solo_p2m_dma_t(solo_dev, SOLO_P2M_DMA_ID_MP4E, 0,
-			      buf + SOLO_MP4E_EXT_SIZE(solo_dev) - off,
-			      SOLO_MP4E_EXT_ADDR(solo_dev),
-			      size + off - SOLO_MP4E_EXT_SIZE(solo_dev));
-
-	return ret;
-}
-
-static int enc_get_mpeg_dma(struct solo_dev *solo_dev, void *buf,
-			    unsigned int off, unsigned int size)
-{
-	int ret;
-
-	dma_addr_t dma_addr = pci_map_single(solo_dev->pdev, buf, size,
-					     PCI_DMA_FROMDEVICE);
-	ret = enc_get_mpeg_dma_t(solo_dev, dma_addr, off, size);
-	pci_unmap_single(solo_dev->pdev, dma_addr, size, PCI_DMA_FROMDEVICE);
-
-	return ret;
-}
-
-static int enc_get_jpeg_dma_sg(struct solo_dev *solo_dev,
-			       struct p2m_desc *desc,
-			       struct scatterlist *sglist, int skip,
-			       unsigned int off, unsigned int size)
-{
-	int ret;
-
-	if (off > SOLO_JPEG_EXT_SIZE(solo_dev))
-		return -EINVAL;
-
-	if (off + size <= SOLO_JPEG_EXT_SIZE(solo_dev)) {
-		return solo_p2m_dma_sg(solo_dev, SOLO_P2M_DMA_ID_JPEG,
-				       desc, 0, sglist, skip,
-				       SOLO_JPEG_EXT_ADDR(solo_dev) + off, size);
-	}
-
-	/* Buffer wrap */
-	ret = solo_p2m_dma_sg(solo_dev, SOLO_P2M_DMA_ID_JPEG, desc, 0,
-			      sglist, skip, SOLO_JPEG_EXT_ADDR(solo_dev) + off,
-			      SOLO_JPEG_EXT_SIZE(solo_dev) - off);
-
-	ret |= solo_p2m_dma_sg(solo_dev, SOLO_P2M_DMA_ID_JPEG, desc, 0,
-			       sglist, skip + SOLO_JPEG_EXT_SIZE(solo_dev) - off,
-			       SOLO_JPEG_EXT_ADDR(solo_dev),
-			       size + off - SOLO_JPEG_EXT_SIZE(solo_dev));
-
-	return ret;
-}
-
-/* Returns true of __chk is within the first __range bytes of __off */
-#define OFF_IN_RANGE(__off, __range, __chk) \
-	((__off <= __chk) && ((__off + __range) >= __chk))
-
-static void solo_jpeg_header(struct solo_enc_dev *solo_enc,
-			     struct videobuf_dmabuf *vbuf)
-{
-	struct scatterlist *sg;
-	void *src = jpeg_header;
-	size_t copied = 0;
-	size_t to_copy = sizeof(jpeg_header);
-
-	for (sg = vbuf->sglist; sg && copied < to_copy; sg = sg_next(sg)) {
-		size_t this_copy = min(sg_dma_len(sg),
-				       (unsigned int)(to_copy - copied));
-		u8 *p = sg_virt(sg);
-
-		memcpy(p, src + copied, this_copy);
-
-		if (OFF_IN_RANGE(copied, this_copy, SOF0_START + 5))
-			p[(SOF0_START + 5) - copied] =
-				0xff & (solo_enc->height >> 8);
-		if (OFF_IN_RANGE(copied, this_copy, SOF0_START + 6))
-			p[(SOF0_START + 6) - copied] = 0xff & solo_enc->height;
-		if (OFF_IN_RANGE(copied, this_copy, SOF0_START + 7))
-			p[(SOF0_START + 7) - copied] =
-				0xff & (solo_enc->width >> 8);
-		if (OFF_IN_RANGE(copied, this_copy, SOF0_START + 8))
-			p[(SOF0_START + 8) - copied] = 0xff & solo_enc->width;
-
-		copied += this_copy;
-	}
-}
-
-static int solo_fill_jpeg(struct solo_enc_fh *fh, struct solo_enc_buf *enc_buf,
-			  struct videobuf_buffer *vb,
-			  struct videobuf_dmabuf *vbuf)
-{
-	struct solo_dev *solo_dev = fh->enc->solo_dev;
-	int size = enc_buf->jpeg_size;
-
-	/* Copy the header first (direct write) */
-	solo_jpeg_header(fh->enc, vbuf);
-
-	vb->size = size + sizeof(jpeg_header);
-
-	/* Grab the jpeg frame */
-	return enc_get_jpeg_dma_sg(solo_dev, fh->desc, vbuf->sglist,
-				   sizeof(jpeg_header),
-				   enc_buf->jpeg_off, size);
-}
-
-static inline int vop_interlaced(__le32 *vh)
-{
-	return (__le32_to_cpu(vh[0]) >> 30) & 1;
-}
-
-static inline u32 vop_size(__le32 *vh)
-{
-	return __le32_to_cpu(vh[0]) & 0xFFFFF;
-}
-
-static inline u8 vop_hsize(__le32 *vh)
-{
-	return (__le32_to_cpu(vh[1]) >> 8) & 0xFF;
-}
-
-static inline u8 vop_vsize(__le32 *vh)
-{
-	return __le32_to_cpu(vh[1]) & 0xFF;
-}
-
-/* must be called with *bits % 8 = 0 */
-static void write_bytes(u8 **out, unsigned *bits, const u8 *src, unsigned count)
-{
-	memcpy(*out, src, count);
-	*out += count;
-	*bits += count * 8;
-}
-
-static void write_bits(u8 **out, unsigned *bits, u32 value, unsigned count)
-{
-
-	value <<= 32 - count; // shift to the right
-
-	while (count--) {
-		**out <<= 1;
-		**out |= !!(value & (1 << 31)); /* MSB */
-		value <<= 1;
-		if (++(*bits) % 8 == 0)
-			(*out)++;
-	}
-}
-
-static void write_ue(u8 **out, unsigned *bits, unsigned value) /* H.264 only */
-{
-	uint32_t max = 0, cnt = 0;
-
-	while (value > max) {
-		max = (max + 2) * 2 - 2;
-		cnt++;
-	}
-	write_bits(out, bits, 1, cnt + 1);
-	write_bits(out, bits, ~(max - value), cnt);
-}
-
-static void write_se(u8 **out, unsigned *bits, int value) /* H.264 only */
-{
-	if (value <= 0)
-		write_ue(out, bits, -value * 2);
-	else
-		write_ue(out, bits, value * 2 - 1);
-}
-
-static void write_mpeg4_end(u8 **out, unsigned *bits)
-{
-	write_bits(out, bits, 0, 1);
-	/* align on 32-bit boundary */
-	if (*bits % 32)
-		write_bits(out, bits, 0xFFFFFFFF, 32 - *bits % 32);
-}
-
-static void write_h264_end(u8 **out, unsigned *bits, int align)
-{
-	write_bits(out, bits, 1, 1);
-	while ((*bits) % 8)
-		write_bits(out, bits, 0, 1);
-	if (align)
-		while ((*bits) % 32)
-			write_bits(out, bits, 0, 1);
-}
-
-static void mpeg4_write_vol(u8 **out, struct solo_dev *solo_dev,
-			    __le32 *vh, unsigned fps, unsigned interval)
-{
-	static const u8 hdr[] = {
-		0, 0, 1, 0x00 /* video_object_start_code */,
-		0, 0, 1, 0x20 /* video_object_layer_start_code */
-	};
-	unsigned bits = 0;
-	unsigned width = vop_hsize(vh) << 4;
-	unsigned height = vop_vsize(vh) << 4;
-	unsigned interlaced = vop_interlaced(vh);
-
-	write_bytes(out, &bits, hdr, sizeof(hdr));
-	write_bits(out, &bits,    0,  1); /* random_accessible_vol */
-	write_bits(out, &bits, 0x04,  8); /* video_object_type_indication: main */
-	write_bits(out, &bits,    1,  1); /* is_object_layer_identifier */
-	write_bits(out, &bits,    2,  4); /* video_object_layer_verid: table V2-39 */
-	write_bits(out, &bits,    0,  3); /* video_object_layer_priority */
-	if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC)
-		write_bits(out, &bits,  3,  4); /* aspect_ratio_info, assuming 4:3 */
-	else
-		write_bits(out, &bits,  2,  4);
-	write_bits(out, &bits,    1,  1); /* vol_control_parameters */
-	write_bits(out, &bits,    1,  2); /* chroma_format: 4:2:0 */
-	write_bits(out, &bits,    1,  1); /* low_delay */
-	write_bits(out, &bits,    0,  1); /* vbv_parameters */
-	write_bits(out, &bits,    0,  2); /* video_object_layer_shape: rectangular */
-	write_bits(out, &bits,    1,  1); /* marker_bit */
-	write_bits(out, &bits,  fps, 16); /* vop_time_increment_resolution */
-	write_bits(out, &bits,    1,  1); /* marker_bit */
-	write_bits(out, &bits,    1,  1); /* fixed_vop_rate */
-	write_bits(out, &bits, interval, 15); /* fixed_vop_time_increment */
-	write_bits(out, &bits,    1,  1); /* marker_bit */
-	write_bits(out, &bits, width, 13); /* video_object_layer_width */
-	write_bits(out, &bits,    1,  1); /* marker_bit */
-	write_bits(out, &bits, height, 13); /* video_object_layer_height */
-	write_bits(out, &bits,    1,  1); /* marker_bit */
-	write_bits(out, &bits, interlaced, 1); /* interlaced */
-	write_bits(out, &bits,    1,  1); /* obmc_disable */
-	write_bits(out, &bits,    0,  2); /* sprite_enable */
-	write_bits(out, &bits,    0,  1); /* not_8_bit */
-	write_bits(out, &bits,    1,  0); /* quant_type */
-	write_bits(out, &bits,    0,  1); /* load_intra_quant_mat */
-	write_bits(out, &bits,    0,  1); /* load_nonintra_quant_mat */
-	write_bits(out, &bits,    0,  1); /* quarter_sample */
-	write_bits(out, &bits,    1,  1); /* complexity_estimation_disable */
-	write_bits(out, &bits,    1,  1); /* resync_marker_disable */
-	write_bits(out, &bits,    0,  1); /* data_partitioned */
-	write_bits(out, &bits,    0,  1); /* newpred_enable */
-	write_bits(out, &bits,    0,  1); /* reduced_resolution_vop_enable */
-	write_bits(out, &bits,    0,  1); /* scalability */
-	write_mpeg4_end(out, &bits);
-}
-
-static void h264_write_vol(u8 **out, struct solo_dev *solo_dev, __le32 *vh)
-{
-	static const u8 sps[] = {
-		0, 0, 0, 1 /* start code */, 0x67, 66 /* profile_idc */,
-		0 /* constraints */, 30 /* level_idc */
-	};
-	static const u8 pps[] = {
-		0, 0, 0, 1 /* start code */, 0x68
-	};
-
-	unsigned bits = 0;
-	unsigned mbs_w = vop_hsize(vh);
-	unsigned mbs_h = vop_vsize(vh);
-
-	write_bytes(out, &bits, sps, sizeof(sps));
-	write_ue(out, &bits,   0);	/* seq_parameter_set_id */
-	write_ue(out, &bits,   5);	/* log2_max_frame_num_minus4 */
-	write_ue(out, &bits,   0);	/* pic_order_cnt_type */
-	write_ue(out, &bits,   6);	/* log2_max_pic_order_cnt_lsb_minus4 */
-	write_ue(out, &bits,   1);	/* max_num_ref_frames */
-	write_bits(out, &bits, 0, 1);	/* gaps_in_frame_num_value_allowed_flag */
-	write_ue(out, &bits, mbs_w - 1);	/* pic_width_in_mbs_minus1 */
-	write_ue(out, &bits, mbs_h - 1);	/* pic_height_in_map_units_minus1 */
-	write_bits(out, &bits, 1, 1);	/* frame_mbs_only_flag */
-	write_bits(out, &bits, 1, 1);	/* direct_8x8_frame_field_flag */
-	write_bits(out, &bits, 0, 1);	/* frame_cropping_flag */
-	write_bits(out, &bits, 0, 1);	/* vui_parameters_present_flag */
-	write_h264_end(out, &bits, 0);
-
-	write_bytes(out, &bits, pps, sizeof(pps));
-	write_ue(out, &bits,   0);	/* pic_parameter_set_id */
-	write_ue(out, &bits,   0);	/* seq_parameter_set_id */
-	write_bits(out, &bits, 0, 1);	/* entropy_coding_mode_flag */
-	write_bits(out, &bits, 0, 1);	/* bottom_field_pic_order_in_frame_present_flag */
-	write_ue(out, &bits,   0);	/* num_slice_groups_minus1 */
-	write_ue(out, &bits,   0);	/* num_ref_idx_l0_default_active_minus1 */
-	write_ue(out, &bits,   0);	/* num_ref_idx_l1_default_active_minus1 */
-	write_bits(out, &bits, 0, 1);	/* weighted_pred_flag */
-	write_bits(out, &bits, 0, 2);	/* weighted_bipred_idc */
-	write_se(out, &bits,   0);	/* pic_init_qp_minus26 */
-	write_se(out, &bits,   0);	/* pic_init_qs_minus26 */
-	write_se(out, &bits,   2);	/* chroma_qp_index_offset */
-	write_bits(out, &bits, 0, 1);	/* deblocking_filter_control_present_flag */
-	write_bits(out, &bits, 1, 1);	/* constrained_intra_pred_flag */
-	write_bits(out, &bits, 0, 1);	/* redundant_pic_cnt_present_flag */
-	write_h264_end(out, &bits, 1);
-}
-
-static int solo_fill_mpeg(struct solo_enc_fh *fh, struct solo_enc_buf *enc_buf,
-			  struct videobuf_buffer *vb,
-			  struct videobuf_dmabuf *vbuf)
-{
-	struct solo_enc_dev *solo_enc = fh->enc;
-	struct solo_dev *solo_dev = solo_enc->solo_dev;
-
-#define VH_WORDS 16
-#define MAX_VOL_HEADER_LENGTH 64
-
-	__le32 vh[VH_WORDS];
-	int ret;
-	int frame_size, frame_off;
-	int skip = 0;
-
-	if (WARN_ON_ONCE(enc_buf->size <= sizeof(vh)))
-		return -EINVAL;
-
-	/* First get the hardware vop header (not real mpeg) */
-	ret = enc_get_mpeg_dma(solo_dev, vh, enc_buf->off, sizeof(vh));
-	if (WARN_ON_ONCE(ret))
-		return ret;
-
-	if (WARN_ON_ONCE(vop_size(vh) > enc_buf->size))
-		return -EINVAL;
-
-	vb->width = vop_hsize(vh) << 4;
-	vb->height = vop_vsize(vh) << 4;
-	vb->size = vop_size(vh);
-
-	/* If this is a key frame, add extra m4v header */
-	if (!enc_buf->vop) {
-		u8 header[MAX_VOL_HEADER_LENGTH], *out = header;
-
-		if (solo_dev->flags & FLAGS_6110)
-			h264_write_vol(&out, solo_dev, vh);
-		else
-			mpeg4_write_vol(&out, solo_dev, vh,
-					solo_dev->fps * 1000,
-					solo_enc->interval * 1000);
-		skip = out - header;
-		enc_write_sg(vbuf->sglist, header, skip);
-		/* Adjust the dma buffer past this header */
-		vb->size += skip;
-	}
-
-	/* Now get the actual mpeg payload */
-	frame_off = (enc_buf->off + sizeof(vh)) % SOLO_MP4E_EXT_SIZE(solo_dev);
-	frame_size = enc_buf->size - sizeof(vh);
-
-	ret = enc_get_mpeg_dma_sg(solo_dev, fh->desc, vbuf->sglist,
-				  skip, frame_off, frame_size);
-	WARN_ON_ONCE(ret);
-
-	return ret;
-}
-
-static void solo_enc_fillbuf(struct solo_enc_fh *fh,
-			    struct videobuf_buffer *vb)
-{
-	struct solo_enc_dev *solo_enc = fh->enc;
-	struct solo_dev *solo_dev = solo_enc->solo_dev;
-	struct solo_enc_buf *enc_buf = NULL;
-	struct videobuf_dmabuf *vbuf;
-	int ret;
-	int error = 1;
-	u16 idx = fh->rd_idx;
-
-	while (idx != solo_dev->enc_wr_idx) {
-		struct solo_enc_buf *ebuf = &solo_dev->enc_buf[idx];
-
-		idx = (idx + 1) % SOLO_NR_RING_BUFS;
-
-		if (ebuf->ch != solo_enc->ch)
-			continue;
-
-		if (fh->fmt == V4L2_PIX_FMT_MPEG) {
-			if (fh->type == ebuf->type) {
-				enc_buf = ebuf;
-				break;
-			}
-		} else {
-			/* For mjpeg, keep reading to the newest frame */
-			enc_buf = ebuf;
-		}
-	}
-
-	fh->rd_idx = idx;
-
-	if (WARN_ON_ONCE(!enc_buf))
-		goto buf_err;
-
-	if ((fh->fmt == V4L2_PIX_FMT_MPEG &&
-	     vb->bsize < enc_buf->size) ||
-	    (fh->fmt == V4L2_PIX_FMT_MJPEG &&
-	     vb->bsize < (enc_buf->jpeg_size + sizeof(jpeg_header)))) {
-		WARN_ON_ONCE(1);
-		goto buf_err;
-	}
-
-	vbuf = videobuf_to_dma(vb);
-	if (WARN_ON_ONCE(!vbuf))
-		goto buf_err;
-
-	if (fh->fmt == V4L2_PIX_FMT_MPEG)
-		ret = solo_fill_mpeg(fh, enc_buf, vb, vbuf);
-	else
-		ret = solo_fill_jpeg(fh, enc_buf, vb, vbuf);
-
-	if (!ret)
-		error = 0;
-
-buf_err:
-	if (error) {
-		vb->state = VIDEOBUF_ERROR;
-	} else {
-		vb->field_count++;
-		vb->ts = enc_buf->ts;
-		vb->state = VIDEOBUF_DONE;
-	}
-
-	wake_up(&vb->done);
-
-	return;
-}
-
-static void solo_enc_thread_try(struct solo_enc_fh *fh)
-{
-	struct solo_enc_dev *solo_enc = fh->enc;
-	struct solo_dev *solo_dev = solo_enc->solo_dev;
-	struct videobuf_buffer *vb;
-
-	for (;;) {
-		spin_lock(&solo_enc->lock);
-
-		if (fh->rd_idx == solo_dev->enc_wr_idx)
-			break;
-
-		if (list_empty(&fh->vidq_active))
-			break;
-
-		vb = list_first_entry(&fh->vidq_active,
-				      struct videobuf_buffer, queue);
-
-		if (!waitqueue_active(&vb->done))
-			break;
-
-		list_del(&vb->queue);
-
-		spin_unlock(&solo_enc->lock);
-
-		solo_enc_fillbuf(fh, vb);
-	}
-
-	assert_spin_locked(&solo_enc->lock);
-	spin_unlock(&solo_enc->lock);
-}
-
-static int solo_enc_thread(void *data)
-{
-	struct solo_enc_fh *fh = data;
-	struct solo_enc_dev *solo_enc = fh->enc;
-	DECLARE_WAITQUEUE(wait, current);
-
-	set_freezable();
-	add_wait_queue(&solo_enc->thread_wait, &wait);
-
-	for (;;) {
-		long timeout = schedule_timeout_interruptible(HZ);
-		if (timeout == -ERESTARTSYS || kthread_should_stop())
-			break;
-		solo_enc_thread_try(fh);
-		try_to_freeze();
-	}
-
-	remove_wait_queue(&solo_enc->thread_wait, &wait);
-
-	return 0;
-}
-
-void solo_motion_isr(struct solo_dev *solo_dev)
-{
-	u32 status;
-	int i;
-
-	solo_reg_write(solo_dev, SOLO_IRQ_STAT, SOLO_IRQ_MOTION);
-
-	status = solo_reg_read(solo_dev, SOLO_VI_MOT_STATUS);
-
-	for (i = 0; i < solo_dev->nr_chans; i++) {
-		struct solo_enc_dev *solo_enc = solo_dev->v4l2_enc[i];
-
-		BUG_ON(solo_enc == NULL);
-
-		if (solo_enc->motion_detected)
-			continue;
-		if (!(status & (1 << i)))
-			continue;
-
-		solo_enc->motion_detected = 1;
-	}
-}
-
-void solo_enc_v4l2_isr(struct solo_dev *solo_dev)
-{
-	struct solo_enc_buf *enc_buf;
-	u32 mpeg_current, mpeg_next, mpeg_size;
-	u32 jpeg_current, jpeg_next, jpeg_size;
-	u32 reg_mpeg_size;
-	u8 cur_q, vop_type;
-	u8 ch;
-	enum solo_enc_types enc_type;
-
-	solo_reg_write(solo_dev, SOLO_IRQ_STAT, SOLO_IRQ_ENCODER);
-
-	cur_q = ((solo_reg_read(solo_dev, SOLO_VE_STATE(11)) & 0xF) + 1) % MP4_QS;
-
-	reg_mpeg_size = ((solo_reg_read(solo_dev, SOLO_VE_STATE(0)) & 0xFFFFF) + 64 + 8) & ~7;
-
-	while (solo_dev->enc_idx != cur_q) {
-		mpeg_current = solo_reg_read(solo_dev,
-					SOLO_VE_MPEG4_QUE(solo_dev->enc_idx));
-		jpeg_current = solo_reg_read(solo_dev,
-					SOLO_VE_JPEG_QUE(solo_dev->enc_idx));
-		solo_dev->enc_idx = (solo_dev->enc_idx + 1) % MP4_QS;
-		mpeg_next = solo_reg_read(solo_dev,
-					SOLO_VE_MPEG4_QUE(solo_dev->enc_idx));
-		jpeg_next = solo_reg_read(solo_dev,
-					SOLO_VE_JPEG_QUE(solo_dev->enc_idx));
-
-		ch = (mpeg_current >> 24) & 0x1f;
-		if (ch >= SOLO_MAX_CHANNELS) {
-			ch -= SOLO_MAX_CHANNELS;
-			enc_type = SOLO_ENC_TYPE_EXT;
-		} else
-			enc_type = SOLO_ENC_TYPE_STD;
-
-		vop_type = (mpeg_current >> 29) & 3;
-
-		mpeg_current &= 0x00ffffff;
-		mpeg_next    &= 0x00ffffff;
-		jpeg_current &= 0x00ffffff;
-		jpeg_next    &= 0x00ffffff;
-
-		mpeg_size = (SOLO_MP4E_EXT_SIZE(solo_dev) +
-			     mpeg_next - mpeg_current) %
-			    SOLO_MP4E_EXT_SIZE(solo_dev);
-
-		jpeg_size = (SOLO_JPEG_EXT_SIZE(solo_dev) +
-			     jpeg_next - jpeg_current) %
-			    SOLO_JPEG_EXT_SIZE(solo_dev);
-
-		/* XXX I think this means we had a ring overflow? */
-		if (mpeg_current > mpeg_next && mpeg_size != reg_mpeg_size) {
-			enc_reset_gop(solo_dev, ch);
-			continue;
-		}
-
-		/* When resetting the GOP, skip frames until I-frame */
-		if (enc_gop_reset(solo_dev, ch, vop_type))
-			continue;
-
-		enc_buf = &solo_dev->enc_buf[solo_dev->enc_wr_idx];
-
-		enc_buf->vop = vop_type;
-		enc_buf->ch = ch;
-		enc_buf->off = mpeg_current;
-		enc_buf->size = mpeg_size;
-		enc_buf->jpeg_off = jpeg_current;
-		enc_buf->jpeg_size = jpeg_size;
-		enc_buf->type = enc_type;
-
-		do_gettimeofday(&enc_buf->ts);
-
-		solo_dev->enc_wr_idx = (solo_dev->enc_wr_idx + 1) %
-					SOLO_NR_RING_BUFS;
-
-		wake_up_interruptible(&solo_dev->v4l2_enc[ch]->thread_wait);
-	}
-
-	return;
-}
-
-static int solo_enc_buf_setup(struct videobuf_queue *vq, unsigned int *count,
-			      unsigned int *size)
-{
-	*size = FRAME_BUF_SIZE;
-
-	if (*count < MIN_VID_BUFFERS)
-		*count = MIN_VID_BUFFERS;
-
-	return 0;
-}
-
-static int solo_enc_buf_prepare(struct videobuf_queue *vq,
-				struct videobuf_buffer *vb,
-				enum v4l2_field field)
-{
-	struct solo_enc_fh *fh = vq->priv_data;
-	struct solo_enc_dev *solo_enc = fh->enc;
-
-	vb->size = FRAME_BUF_SIZE;
-	if (vb->baddr != 0 && vb->bsize < vb->size)
-		return -EINVAL;
-
-	/* These properties only change when queue is idle */
-	vb->width = solo_enc->width;
-	vb->height = solo_enc->height;
-	vb->field  = field;
-
-	if (vb->state == VIDEOBUF_NEEDS_INIT) {
-		int rc = videobuf_iolock(vq, vb, NULL);
-		if (rc < 0) {
-			struct videobuf_dmabuf *dma = videobuf_to_dma(vb);
-			videobuf_dma_unmap(vq->dev, dma);
-			videobuf_dma_free(dma);
-			vb->state = VIDEOBUF_NEEDS_INIT;
-			return rc;
-		}
-	}
-	vb->state = VIDEOBUF_PREPARED;
-
-	return 0;
-}
-
-static void solo_enc_buf_queue(struct videobuf_queue *vq,
-			       struct videobuf_buffer *vb)
-{
-	struct solo_enc_fh *fh = vq->priv_data;
-
-	vb->state = VIDEOBUF_QUEUED;
-	list_add_tail(&vb->queue, &fh->vidq_active);
-	wake_up_interruptible(&fh->enc->thread_wait);
-}
-
-static void solo_enc_buf_release(struct videobuf_queue *vq,
-				 struct videobuf_buffer *vb)
-{
-	struct videobuf_dmabuf *dma = videobuf_to_dma(vb);
-
-	videobuf_dma_unmap(vq->dev, dma);
-	videobuf_dma_free(dma);
-	vb->state = VIDEOBUF_NEEDS_INIT;
-}
-
-static struct videobuf_queue_ops solo_enc_video_qops = {
-	.buf_setup	= solo_enc_buf_setup,
-	.buf_prepare	= solo_enc_buf_prepare,
-	.buf_queue	= solo_enc_buf_queue,
-	.buf_release	= solo_enc_buf_release,
-};
-
-static unsigned int solo_enc_poll(struct file *file,
-				  struct poll_table_struct *wait)
-{
-	struct solo_enc_fh *fh = file->private_data;
-
-	return videobuf_poll_stream(file, &fh->vidq, wait);
-}
-
-static int solo_enc_mmap(struct file *file, struct vm_area_struct *vma)
-{
-	struct solo_enc_fh *fh = file->private_data;
-
-	return videobuf_mmap_mapper(&fh->vidq, vma);
-}
-
-static int solo_enc_open(struct file *file)
-{
-	struct solo_enc_dev *solo_enc = video_drvdata(file);
-	struct solo_enc_fh *fh;
-
-	fh = kzalloc(sizeof(*fh), GFP_KERNEL);
-	if (fh == NULL)
-		return -ENOMEM;
-
-	fh->enc = solo_enc;
-	file->private_data = fh;
-	INIT_LIST_HEAD(&fh->vidq_active);
-	fh->fmt = V4L2_PIX_FMT_MPEG;
-	fh->type = SOLO_ENC_TYPE_STD;
-
-	videobuf_queue_sg_init(&fh->vidq, &solo_enc_video_qops,
-			       &solo_enc->solo_dev->pdev->dev,
-			       &solo_enc->lock,
-			       V4L2_BUF_TYPE_VIDEO_CAPTURE,
-			       V4L2_FIELD_INTERLACED,
-			       sizeof(struct videobuf_buffer), fh, NULL);
-
-	return 0;
-}
-
-static ssize_t solo_enc_read(struct file *file, char __user *data,
-			     size_t count, loff_t *ppos)
-{
-	struct solo_enc_fh *fh = file->private_data;
-	struct solo_enc_dev *solo_enc = fh->enc;
-
-	/* Make sure the encoder is on */
-	if (!fh->enc_on) {
-		int ret;
-
-		spin_lock(&solo_enc->lock);
-		ret = solo_enc_on(fh);
-		spin_unlock(&solo_enc->lock);
-		if (ret)
-			return ret;
-
-		ret = solo_start_fh_thread(fh);
-		if (ret)
-			return ret;
-	}
-
-	return videobuf_read_stream(&fh->vidq, data, count, ppos, 0,
-				    file->f_flags & O_NONBLOCK);
-}
-
-static int solo_enc_release(struct file *file)
-{
-	struct solo_enc_fh *fh = file->private_data;
-	struct solo_enc_dev *solo_enc = fh->enc;
-
-	videobuf_stop(&fh->vidq);
-	videobuf_mmap_free(&fh->vidq);
-
-	spin_lock(&solo_enc->lock);
-	solo_enc_off(fh);
-	spin_unlock(&solo_enc->lock);
-
-	kfree(fh);
-
-	return 0;
-}
-
-static int solo_enc_querycap(struct file *file, void  *priv,
-			     struct v4l2_capability *cap)
-{
-	struct solo_enc_fh *fh = priv;
-	struct solo_enc_dev *solo_enc = fh->enc;
-	struct solo_dev *solo_dev = solo_enc->solo_dev;
-
-	strcpy(cap->driver, SOLO6X10_NAME);
-	snprintf(cap->card, sizeof(cap->card), "Softlogic 6x10 Enc %d",
-		 solo_enc->ch);
-	snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI %s",
-		 pci_name(solo_dev->pdev));
-	cap->version = SOLO6X10_VER_NUM;
-	cap->capabilities =     V4L2_CAP_VIDEO_CAPTURE |
-				V4L2_CAP_READWRITE |
-				V4L2_CAP_STREAMING;
-	return 0;
-}
-
-static int solo_enc_enum_input(struct file *file, void *priv,
-			       struct v4l2_input *input)
-{
-	struct solo_enc_fh *fh = priv;
-	struct solo_enc_dev *solo_enc = fh->enc;
-	struct solo_dev *solo_dev = solo_enc->solo_dev;
-
-	if (input->index)
-		return -EINVAL;
-
-	snprintf(input->name, sizeof(input->name), "Encoder %d",
-		 solo_enc->ch + 1);
-	input->type = V4L2_INPUT_TYPE_CAMERA;
-
-	if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC)
-		input->std = V4L2_STD_NTSC_M;
-	else
-		input->std = V4L2_STD_PAL_B;
-
-	if (!tw28_get_video_status(solo_dev, solo_enc->ch))
-		input->status = V4L2_IN_ST_NO_SIGNAL;
-
-	return 0;
-}
-
-static int solo_enc_set_input(struct file *file, void *priv, unsigned int index)
-{
-	if (index)
-		return -EINVAL;
-
-	return 0;
-}
-
-static int solo_enc_get_input(struct file *file, void *priv,
-			      unsigned int *index)
-{
-	*index = 0;
-
-	return 0;
-}
-
-static int solo_enc_enum_fmt_cap(struct file *file, void *priv,
-				 struct v4l2_fmtdesc *f)
-{
-	switch (f->index) {
-	case 0:
-		f->pixelformat = V4L2_PIX_FMT_MPEG;
-		strcpy(f->description, "MPEG-4 AVC");
-		break;
-	case 1:
-		f->pixelformat = V4L2_PIX_FMT_MJPEG;
-		strcpy(f->description, "MJPEG");
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	f->flags = V4L2_FMT_FLAG_COMPRESSED;
-
-	return 0;
-}
-
-static int solo_enc_try_fmt_cap(struct file *file, void *priv,
-			    struct v4l2_format *f)
-{
-	struct solo_enc_fh *fh = priv;
-	struct solo_enc_dev *solo_enc = fh->enc;
-	struct solo_dev *solo_dev = solo_enc->solo_dev;
-	struct v4l2_pix_format *pix = &f->fmt.pix;
-
-	if (pix->pixelformat != V4L2_PIX_FMT_MPEG &&
-	    pix->pixelformat != V4L2_PIX_FMT_MJPEG)
-		return -EINVAL;
-
-	/* We cannot change width/height in mid read */
-	if (atomic_read(&solo_enc->readers) > 0) {
-		if (pix->width != solo_enc->width ||
-		    pix->height != solo_enc->height)
-			return -EBUSY;
-	}
-
-	if (pix->width < solo_dev->video_hsize ||
-	    pix->height < solo_dev->video_vsize << 1) {
-		/* Default to CIF 1/2 size */
-		pix->width = solo_dev->video_hsize >> 1;
-		pix->height = solo_dev->video_vsize;
-	} else {
-		/* Full frame */
-		pix->width = solo_dev->video_hsize;
-		pix->height = solo_dev->video_vsize << 1;
-	}
-
-	if (pix->field == V4L2_FIELD_ANY)
-		pix->field = V4L2_FIELD_INTERLACED;
-	else if (pix->field != V4L2_FIELD_INTERLACED)
-		pix->field = V4L2_FIELD_INTERLACED;
-
-	/* Just set these */
-	pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
-	pix->sizeimage = FRAME_BUF_SIZE;
-
-	return 0;
-}
-
-static int solo_enc_set_fmt_cap(struct file *file, void *priv,
-				struct v4l2_format *f)
-{
-	struct solo_enc_fh *fh = priv;
-	struct solo_enc_dev *solo_enc = fh->enc;
-	struct solo_dev *solo_dev = solo_enc->solo_dev;
-	struct v4l2_pix_format *pix = &f->fmt.pix;
-	int ret;
-
-	spin_lock(&solo_enc->lock);
-
-	ret = solo_enc_try_fmt_cap(file, priv, f);
-	if (ret) {
-		spin_unlock(&solo_enc->lock);
-		return ret;
-	}
-
-	if (pix->width == solo_dev->video_hsize)
-		solo_enc->mode = SOLO_ENC_MODE_D1;
-	else
-		solo_enc->mode = SOLO_ENC_MODE_CIF;
-
-	/* This does not change the encoder at all */
-	fh->fmt = pix->pixelformat;
-
-	if (pix->priv)
-		fh->type = SOLO_ENC_TYPE_EXT;
-	ret = solo_enc_on(fh);
-
-	spin_unlock(&solo_enc->lock);
-
-	if (ret)
-		return ret;
-
-	return solo_start_fh_thread(fh);
-}
-
-static int solo_enc_get_fmt_cap(struct file *file, void *priv,
-				struct v4l2_format *f)
-{
-	struct solo_enc_fh *fh = priv;
-	struct solo_enc_dev *solo_enc = fh->enc;
-	struct v4l2_pix_format *pix = &f->fmt.pix;
-
-	pix->width = solo_enc->width;
-	pix->height = solo_enc->height;
-	pix->pixelformat = fh->fmt;
-	pix->field = solo_enc->interlaced ? V4L2_FIELD_INTERLACED :
-		     V4L2_FIELD_NONE;
-	pix->sizeimage = FRAME_BUF_SIZE;
-	pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
-
-	return 0;
-}
-
-static int solo_enc_reqbufs(struct file *file, void *priv,
-			    struct v4l2_requestbuffers *req)
-{
-	struct solo_enc_fh *fh = priv;
-
-	return videobuf_reqbufs(&fh->vidq, req);
-}
-
-static int solo_enc_querybuf(struct file *file, void *priv,
-			     struct v4l2_buffer *buf)
-{
-	struct solo_enc_fh *fh = priv;
-
-	return videobuf_querybuf(&fh->vidq, buf);
-}
-
-static int solo_enc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
-{
-	struct solo_enc_fh *fh = priv;
-
-	return videobuf_qbuf(&fh->vidq, buf);
-}
-
-static int solo_enc_dqbuf(struct file *file, void *priv,
-			  struct v4l2_buffer *buf)
-{
-	struct solo_enc_fh *fh = priv;
-	struct solo_enc_dev *solo_enc = fh->enc;
-	int ret;
-
-	/* Make sure the encoder is on */
-	if (!fh->enc_on) {
-		spin_lock(&solo_enc->lock);
-		ret = solo_enc_on(fh);
-		spin_unlock(&solo_enc->lock);
-		if (ret)
-			return ret;
-
-		ret = solo_start_fh_thread(fh);
-		if (ret)
-			return ret;
-	}
-
-	ret = videobuf_dqbuf(&fh->vidq, buf, file->f_flags & O_NONBLOCK);
-	if (ret)
-		return ret;
-
-	/* Signal motion detection */
-	if (solo_is_motion_on(solo_enc)) {
-		buf->flags |= V4L2_BUF_FLAG_MOTION_ON;
-		if (solo_enc->motion_detected) {
-			buf->flags |= V4L2_BUF_FLAG_MOTION_DETECTED;
-			solo_reg_write(solo_enc->solo_dev, SOLO_VI_MOT_CLEAR,
-				       1 << solo_enc->ch);
-			solo_enc->motion_detected = 0;
-		}
-	}
-
-	/* Check for key frame on mpeg data */
-	if (fh->fmt == V4L2_PIX_FMT_MPEG) {
-		struct videobuf_dmabuf *vbuf =
-				videobuf_to_dma(fh->vidq.bufs[buf->index]);
-
-		if (vbuf) {
-			u8 *p = sg_virt(vbuf->sglist);
-			if (p[3] == 0x00)
-				buf->flags |= V4L2_BUF_FLAG_KEYFRAME;
-			else
-				buf->flags |= V4L2_BUF_FLAG_PFRAME;
-		}
-	}
-
-	return 0;
-}
-
-static int solo_enc_streamon(struct file *file, void *priv,
-			     enum v4l2_buf_type i)
-{
-	struct solo_enc_fh *fh = priv;
-
-	if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		return -EINVAL;
-
-	return videobuf_streamon(&fh->vidq);
-}
-
-static int solo_enc_streamoff(struct file *file, void *priv,
-			      enum v4l2_buf_type i)
-{
-	struct solo_enc_fh *fh = priv;
-
-	if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		return -EINVAL;
-
-	return videobuf_streamoff(&fh->vidq);
-}
-
-static int solo_enc_s_std(struct file *file, void *priv, v4l2_std_id *i)
-{
-	return 0;
-}
-
-static int solo_enum_framesizes(struct file *file, void *priv,
-				struct v4l2_frmsizeenum *fsize)
-{
-	struct solo_enc_fh *fh = priv;
-	struct solo_dev *solo_dev = fh->enc->solo_dev;
-
-	if (fsize->pixel_format != V4L2_PIX_FMT_MPEG)
-		return -EINVAL;
-
-	switch (fsize->index) {
-	case 0:
-		fsize->discrete.width = solo_dev->video_hsize >> 1;
-		fsize->discrete.height = solo_dev->video_vsize;
-		break;
-	case 1:
-		fsize->discrete.width = solo_dev->video_hsize;
-		fsize->discrete.height = solo_dev->video_vsize << 1;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
-
-	return 0;
-}
-
-static int solo_enum_frameintervals(struct file *file, void *priv,
-				    struct v4l2_frmivalenum *fintv)
-{
-	struct solo_enc_fh *fh = priv;
-	struct solo_dev *solo_dev = fh->enc->solo_dev;
-
-	if (fintv->pixel_format != V4L2_PIX_FMT_MPEG || fintv->index)
-		return -EINVAL;
-
-	fintv->type = V4L2_FRMIVAL_TYPE_STEPWISE;
-
-	fintv->stepwise.min.numerator = solo_dev->fps;
-	fintv->stepwise.min.denominator = 1;
-
-	fintv->stepwise.max.numerator = solo_dev->fps;
-	fintv->stepwise.max.denominator = 15;
-
-	fintv->stepwise.step.numerator = 1;
-	fintv->stepwise.step.denominator = 1;
-
-	return 0;
-}
-
-static int solo_g_parm(struct file *file, void *priv,
-		       struct v4l2_streamparm *sp)
-{
-	struct solo_enc_fh *fh = priv;
-	struct solo_enc_dev *solo_enc = fh->enc;
-	struct solo_dev *solo_dev = solo_enc->solo_dev;
-	struct v4l2_captureparm *cp = &sp->parm.capture;
-
-	cp->capability = V4L2_CAP_TIMEPERFRAME;
-	cp->timeperframe.numerator = solo_enc->interval;
-	cp->timeperframe.denominator = solo_dev->fps;
-	cp->capturemode = 0;
-	/* XXX: Shouldn't we be able to get/set this from videobuf? */
-	cp->readbuffers = 2;
-
-	return 0;
-}
-
-static int solo_s_parm(struct file *file, void *priv,
-		       struct v4l2_streamparm *sp)
-{
-	struct solo_enc_fh *fh = priv;
-	struct solo_enc_dev *solo_enc = fh->enc;
-	struct solo_dev *solo_dev = solo_enc->solo_dev;
-	struct v4l2_captureparm *cp = &sp->parm.capture;
-
-	spin_lock(&solo_enc->lock);
-
-	if (atomic_read(&solo_enc->readers) > 0) {
-		spin_unlock(&solo_enc->lock);
-		return -EBUSY;
-	}
-
-	if ((cp->timeperframe.numerator == 0) ||
-	    (cp->timeperframe.denominator == 0)) {
-		/* reset framerate */
-		cp->timeperframe.numerator = 1;
-		cp->timeperframe.denominator = solo_dev->fps;
-	}
-
-	if (cp->timeperframe.denominator != solo_dev->fps)
-		cp->timeperframe.denominator = solo_dev->fps;
-
-	if (cp->timeperframe.numerator > 15)
-		cp->timeperframe.numerator = 15;
-
-	solo_enc->interval = cp->timeperframe.numerator;
-
-	cp->capability = V4L2_CAP_TIMEPERFRAME;
-
-	solo_enc->gop = max(solo_dev->fps / solo_enc->interval, 1);
-	solo_update_mode(solo_enc);
-
-	spin_unlock(&solo_enc->lock);
-
-	return 0;
-}
-
-static int solo_queryctrl(struct file *file, void *priv,
-			  struct v4l2_queryctrl *qc)
-{
-	struct solo_enc_fh *fh = priv;
-	struct solo_enc_dev *solo_enc = fh->enc;
-	struct solo_dev *solo_dev = solo_enc->solo_dev;
-
-	qc->id = v4l2_ctrl_next(solo_ctrl_classes, qc->id);
-	if (!qc->id)
-		return -EINVAL;
-
-	switch (qc->id) {
-	case V4L2_CID_BRIGHTNESS:
-	case V4L2_CID_CONTRAST:
-	case V4L2_CID_SATURATION:
-	case V4L2_CID_HUE:
-		return v4l2_ctrl_query_fill(qc, 0x00, 0xff, 1, 0x80);
-	case V4L2_CID_SHARPNESS:
-		return v4l2_ctrl_query_fill(qc, 0x00, 0x0f, 1, 0x00);
-	case V4L2_CID_MPEG_VIDEO_ENCODING:
-		return v4l2_ctrl_query_fill(
-			qc, V4L2_MPEG_VIDEO_ENCODING_MPEG_1,
-			V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC, 1,
-			V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC);
-	case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
-		return v4l2_ctrl_query_fill(qc, 1, 255, 1, solo_dev->fps);
-#ifdef PRIVATE_CIDS
-	case V4L2_CID_MOTION_THRESHOLD:
-		qc->flags |= V4L2_CTRL_FLAG_SLIDER;
-		qc->type = V4L2_CTRL_TYPE_INTEGER;
-		qc->minimum = 0;
-		qc->maximum = 0xffff;
-		qc->step = 1;
-		qc->default_value = SOLO_DEF_MOT_THRESH;
-		strlcpy(qc->name, "Motion Detection Threshold",
-			sizeof(qc->name));
-		return 0;
-	case V4L2_CID_MOTION_ENABLE:
-		qc->type = V4L2_CTRL_TYPE_BOOLEAN;
-		qc->minimum = 0;
-		qc->maximum = qc->step = 1;
-		qc->default_value = 0;
-		strlcpy(qc->name, "Motion Detection Enable", sizeof(qc->name));
-		return 0;
-#else
-	case V4L2_CID_MOTION_THRESHOLD:
-		return v4l2_ctrl_query_fill(qc, 0, 0xffff, 1,
-					    SOLO_DEF_MOT_THRESH);
-	case V4L2_CID_MOTION_ENABLE:
-		return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0);
-#endif
-	case V4L2_CID_RDS_TX_RADIO_TEXT:
-		qc->type = V4L2_CTRL_TYPE_STRING;
-		qc->minimum = 0;
-		qc->maximum = OSD_TEXT_MAX;
-		qc->step = 1;
-		qc->default_value = 0;
-		strlcpy(qc->name, "OSD Text", sizeof(qc->name));
-		return 0;
-	}
-
-	return -EINVAL;
-}
-
-static int solo_querymenu(struct file *file, void *priv,
-			  struct v4l2_querymenu *qmenu)
-{
-	struct v4l2_queryctrl qctrl;
-	int err;
-
-	qctrl.id = qmenu->id;
-	err = solo_queryctrl(file, priv, &qctrl);
-	if (err)
-		return err;
-
-	return v4l2_ctrl_query_menu(qmenu, &qctrl, NULL);
-}
-
-static int solo_g_ctrl(struct file *file, void *priv,
-		       struct v4l2_control *ctrl)
-{
-	struct solo_enc_fh *fh = priv;
-	struct solo_enc_dev *solo_enc = fh->enc;
-	struct solo_dev *solo_dev = solo_enc->solo_dev;
-
-	switch (ctrl->id) {
-	case V4L2_CID_BRIGHTNESS:
-	case V4L2_CID_CONTRAST:
-	case V4L2_CID_SATURATION:
-	case V4L2_CID_HUE:
-	case V4L2_CID_SHARPNESS:
-		return tw28_get_ctrl_val(solo_dev, ctrl->id, solo_enc->ch,
-					 &ctrl->value);
-	case V4L2_CID_MPEG_VIDEO_ENCODING:
-		ctrl->value = V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC;
-		break;
-	case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
-		ctrl->value = solo_enc->gop;
-		break;
-	case V4L2_CID_MOTION_THRESHOLD:
-		ctrl->value = solo_enc->motion_thresh;
-		break;
-	case V4L2_CID_MOTION_ENABLE:
-		ctrl->value = solo_is_motion_on(solo_enc);
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int solo_s_ctrl(struct file *file, void *priv,
-		       struct v4l2_control *ctrl)
-{
-	struct solo_enc_fh *fh = priv;
-	struct solo_enc_dev *solo_enc = fh->enc;
-	struct solo_dev *solo_dev = solo_enc->solo_dev;
-
-	switch (ctrl->id) {
-	case V4L2_CID_BRIGHTNESS:
-	case V4L2_CID_CONTRAST:
-	case V4L2_CID_SATURATION:
-	case V4L2_CID_HUE:
-	case V4L2_CID_SHARPNESS:
-		return tw28_set_ctrl_val(solo_dev, ctrl->id, solo_enc->ch,
-					 ctrl->value);
-	case V4L2_CID_MPEG_VIDEO_ENCODING:
-		if (ctrl->value != V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC)
-			return -ERANGE;
-		break;
-	case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
-		if (ctrl->value < 1 || ctrl->value > 255)
-			return -ERANGE;
-		solo_enc->gop = ctrl->value;
-		solo_reg_write(solo_dev, SOLO_VE_CH_GOP(solo_enc->ch),
-			       solo_enc->gop);
-		solo_reg_write(solo_dev, SOLO_VE_CH_GOP_E(solo_enc->ch),
-			       solo_enc->gop);
-		break;
-	case V4L2_CID_MOTION_THRESHOLD:
-		/* TODO accept value on lower 16-bits and use high
-		 * 16-bits to assign the value to a specific block */
-		if (ctrl->value < 0 || ctrl->value > 0xffff)
-			return -ERANGE;
-		solo_enc->motion_thresh = ctrl->value;
-		solo_set_motion_threshold(solo_dev, solo_enc->ch, ctrl->value);
-		break;
-	case V4L2_CID_MOTION_ENABLE:
-		solo_motion_toggle(solo_enc, ctrl->value);
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int solo_s_ext_ctrls(struct file *file, void *priv,
-			    struct v4l2_ext_controls *ctrls)
-{
-	struct solo_enc_fh *fh = priv;
-	struct solo_enc_dev *solo_enc = fh->enc;
-	int i;
-
-	for (i = 0; i < ctrls->count; i++) {
-		struct v4l2_ext_control *ctrl = (ctrls->controls + i);
-		int err;
-
-		switch (ctrl->id) {
-		case V4L2_CID_RDS_TX_RADIO_TEXT:
-			if (ctrl->size - 1 > OSD_TEXT_MAX)
-				err = -ERANGE;
-			else {
-				err = copy_from_user(solo_enc->osd_text,
-						     ctrl->string,
-						     OSD_TEXT_MAX);
-				solo_enc->osd_text[OSD_TEXT_MAX] = '\0';
-				if (!err)
-					err = solo_osd_print(solo_enc);
-				else
-					err = -EFAULT;
-			}
-			break;
-		default:
-			err = -EINVAL;
-		}
-
-		if (err < 0) {
-			ctrls->error_idx = i;
-			return err;
-		}
-	}
-
-	return 0;
-}
-
-static int solo_g_ext_ctrls(struct file *file, void *priv,
-			    struct v4l2_ext_controls *ctrls)
-{
-	struct solo_enc_fh *fh = priv;
-	struct solo_enc_dev *solo_enc = fh->enc;
-	int i;
-
-	for (i = 0; i < ctrls->count; i++) {
-		struct v4l2_ext_control *ctrl = (ctrls->controls + i);
-		int err;
-
-		switch (ctrl->id) {
-		case V4L2_CID_RDS_TX_RADIO_TEXT:
-			if (ctrl->size < OSD_TEXT_MAX) {
-				ctrl->size = OSD_TEXT_MAX;
-				err = -ENOSPC;
-			} else {
-				err = copy_to_user(ctrl->string,
-						   solo_enc->osd_text,
-						   OSD_TEXT_MAX);
-				if (err)
-					err = -EFAULT;
-			}
-			break;
-		default:
-			err = -EINVAL;
-		}
-
-		if (err < 0) {
-			ctrls->error_idx = i;
-			return err;
-		}
-	}
-
-	return 0;
-}
-
-static const struct v4l2_file_operations solo_enc_fops = {
-	.owner			= THIS_MODULE,
-	.open			= solo_enc_open,
-	.release		= solo_enc_release,
-	.read			= solo_enc_read,
-	.poll			= solo_enc_poll,
-	.mmap			= solo_enc_mmap,
-	.ioctl			= video_ioctl2,
-};
-
-static const struct v4l2_ioctl_ops solo_enc_ioctl_ops = {
-	.vidioc_querycap		= solo_enc_querycap,
-	.vidioc_s_std			= solo_enc_s_std,
-	/* Input callbacks */
-	.vidioc_enum_input		= solo_enc_enum_input,
-	.vidioc_s_input			= solo_enc_set_input,
-	.vidioc_g_input			= solo_enc_get_input,
-	/* Video capture format callbacks */
-	.vidioc_enum_fmt_vid_cap	= solo_enc_enum_fmt_cap,
-	.vidioc_try_fmt_vid_cap		= solo_enc_try_fmt_cap,
-	.vidioc_s_fmt_vid_cap		= solo_enc_set_fmt_cap,
-	.vidioc_g_fmt_vid_cap		= solo_enc_get_fmt_cap,
-	/* Streaming I/O */
-	.vidioc_reqbufs			= solo_enc_reqbufs,
-	.vidioc_querybuf		= solo_enc_querybuf,
-	.vidioc_qbuf			= solo_enc_qbuf,
-	.vidioc_dqbuf			= solo_enc_dqbuf,
-	.vidioc_streamon		= solo_enc_streamon,
-	.vidioc_streamoff		= solo_enc_streamoff,
-	/* Frame size and interval */
-	.vidioc_enum_framesizes		= solo_enum_framesizes,
-	.vidioc_enum_frameintervals	= solo_enum_frameintervals,
-	/* Video capture parameters */
-	.vidioc_s_parm			= solo_s_parm,
-	.vidioc_g_parm			= solo_g_parm,
-	/* Controls */
-	.vidioc_queryctrl		= solo_queryctrl,
-	.vidioc_querymenu		= solo_querymenu,
-	.vidioc_g_ctrl			= solo_g_ctrl,
-	.vidioc_s_ctrl			= solo_s_ctrl,
-	.vidioc_g_ext_ctrls		= solo_g_ext_ctrls,
-	.vidioc_s_ext_ctrls		= solo_s_ext_ctrls,
-};
-
-static struct video_device solo_enc_template = {
-	.name			= SOLO6X10_NAME,
-	.fops			= &solo_enc_fops,
-	.ioctl_ops		= &solo_enc_ioctl_ops,
-	.minor			= -1,
-	.release		= video_device_release,
-
-	.tvnorms		= V4L2_STD_NTSC_M | V4L2_STD_PAL_B,
-	.current_norm		= V4L2_STD_NTSC_M,
-};
-
-static struct solo_enc_dev *solo_enc_alloc(struct solo_dev *solo_dev, u8 ch)
-{
-	struct solo_enc_dev *solo_enc;
-	int ret;
-
-	solo_enc = kzalloc(sizeof(*solo_enc), GFP_KERNEL);
-	if (!solo_enc)
-		return ERR_PTR(-ENOMEM);
-
-	solo_enc->vfd = video_device_alloc();
-	if (!solo_enc->vfd) {
-		kfree(solo_enc);
-		return ERR_PTR(-ENOMEM);
-	}
-
-	solo_enc->solo_dev = solo_dev;
-	solo_enc->ch = ch;
-
-	*solo_enc->vfd = solo_enc_template;
-	solo_enc->vfd->parent = &solo_dev->pdev->dev;
-	ret = video_register_device(solo_enc->vfd, VFL_TYPE_GRABBER,
-				    video_nr);
-	if (ret < 0) {
-		video_device_release(solo_enc->vfd);
-		kfree(solo_enc);
-		return ERR_PTR(ret);
-	}
-
-	video_set_drvdata(solo_enc->vfd, solo_enc);
-
-	snprintf(solo_enc->vfd->name, sizeof(solo_enc->vfd->name),
-		 "%s-enc (%i/%i)", SOLO6X10_NAME, solo_dev->vfd->num,
-		 solo_enc->vfd->num);
-
-	if (video_nr != -1)
-		video_nr++;
-
-	spin_lock_init(&solo_enc->lock);
-	init_waitqueue_head(&solo_enc->thread_wait);
-	atomic_set(&solo_enc->readers, 0);
-
-	solo_enc->qp = SOLO_DEFAULT_QP;
-	solo_enc->gop = solo_dev->fps;
-	solo_enc->interval = 1;
-	solo_enc->mode = SOLO_ENC_MODE_CIF;
-	solo_enc->motion_thresh = SOLO_DEF_MOT_THRESH;
-
-	spin_lock(&solo_enc->lock);
-	solo_update_mode(solo_enc);
-	spin_unlock(&solo_enc->lock);
-
-	return solo_enc;
-}
-
-static void solo_enc_free(struct solo_enc_dev *solo_enc)
-{
-	if (solo_enc == NULL)
-		return;
-
-	video_unregister_device(solo_enc->vfd);
-	kfree(solo_enc);
-}
-
-int solo_enc_v4l2_init(struct solo_dev *solo_dev)
-{
-	int i;
-
-	for (i = 0; i < solo_dev->nr_chans; i++) {
-		solo_dev->v4l2_enc[i] = solo_enc_alloc(solo_dev, i);
-		if (IS_ERR(solo_dev->v4l2_enc[i]))
-			break;
-	}
-
-	if (i != solo_dev->nr_chans) {
-		int ret = PTR_ERR(solo_dev->v4l2_enc[i]);
-		while (i--)
-			solo_enc_free(solo_dev->v4l2_enc[i]);
-		return ret;
-	}
-
-	/* D1@MAX-FPS * 4 */
-	solo_dev->enc_bw_remain = solo_dev->fps * 4 * 4;
-
-	dev_info(&solo_dev->pdev->dev, "Encoders as /dev/video%d-%d\n",
-		 solo_dev->v4l2_enc[0]->vfd->num,
-		 solo_dev->v4l2_enc[solo_dev->nr_chans - 1]->vfd->num);
-
-	return 0;
-}
-
-void solo_enc_v4l2_exit(struct solo_dev *solo_dev)
-{
-	int i;
-
-	solo_irq_off(solo_dev, SOLO_IRQ_MOTION);
-
-	for (i = 0; i < solo_dev->nr_chans; i++)
-		solo_enc_free(solo_dev->v4l2_enc[i]);
-}
diff --git a/drivers/staging/media/solo6x10/v4l2.c b/drivers/staging/media/solo6x10/v4l2.c
deleted file mode 100644
index ca774cc..0000000
--- a/drivers/staging/media/solo6x10/v4l2.c
+++ /dev/null
@@ -1,961 +0,0 @@
-/*
- * Copyright (C) 2010 Bluecherry, LLC www.bluecherrydvr.com
- * Copyright (C) 2010 Ben Collins <bcollins@bluecherry.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You 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/kthread.h>
-#include <linux/freezer.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-common.h>
-#include <media/videobuf-dma-sg.h>
-#include "solo6x10.h"
-#include "tw28.h"
-
-#define SOLO_HW_BPL		2048
-#define SOLO_DISP_PIX_FIELD	V4L2_FIELD_INTERLACED
-
-/* Image size is two fields, SOLO_HW_BPL is one horizontal line */
-#define solo_vlines(__solo)	(__solo->video_vsize * 2)
-#define solo_image_size(__solo) (solo_bytesperline(__solo) * \
-				 solo_vlines(__solo))
-#define solo_bytesperline(__solo) (__solo->video_hsize * 2)
-
-#define MIN_VID_BUFFERS		4
-
-/* Simple file handle */
-struct solo_filehandle {
-	struct solo_dev		*solo_dev;
-	struct videobuf_queue	vidq;
-	struct task_struct      *kthread;
-	spinlock_t		slock;
-	int			old_write;
-	struct list_head	vidq_active;
-	struct p2m_desc		desc[SOLO_NR_P2M_DESC];
-	int			desc_idx;
-};
-
-unsigned video_nr = -1;
-module_param(video_nr, uint, 0644);
-MODULE_PARM_DESC(video_nr, "videoX start number, -1 is autodetect (default)");
-
-static void erase_on(struct solo_dev *solo_dev)
-{
-	solo_reg_write(solo_dev, SOLO_VO_DISP_ERASE, SOLO_VO_DISP_ERASE_ON);
-	solo_dev->erasing = 1;
-	solo_dev->frame_blank = 0;
-}
-
-static int erase_off(struct solo_dev *solo_dev)
-{
-	if (!solo_dev->erasing)
-		return 0;
-
-	/* First time around, assert erase off */
-	if (!solo_dev->frame_blank)
-		solo_reg_write(solo_dev, SOLO_VO_DISP_ERASE, 0);
-	/* Keep the erasing flag on for 8 frames minimum */
-	if (solo_dev->frame_blank++ >= 8)
-		solo_dev->erasing = 0;
-
-	return 1;
-}
-
-void solo_video_in_isr(struct solo_dev *solo_dev)
-{
-	solo_reg_write(solo_dev, SOLO_IRQ_STAT, SOLO_IRQ_VIDEO_IN);
-	wake_up_interruptible(&solo_dev->disp_thread_wait);
-}
-
-static void solo_win_setup(struct solo_dev *solo_dev, u8 ch,
-			   int sx, int sy, int ex, int ey, int scale)
-{
-	if (ch >= solo_dev->nr_chans)
-		return;
-
-	/* Here, we just keep window/channel the same */
-	solo_reg_write(solo_dev, SOLO_VI_WIN_CTRL0(ch),
-		       SOLO_VI_WIN_CHANNEL(ch) |
-		       SOLO_VI_WIN_SX(sx) |
-		       SOLO_VI_WIN_EX(ex) |
-		       SOLO_VI_WIN_SCALE(scale));
-
-	solo_reg_write(solo_dev, SOLO_VI_WIN_CTRL1(ch),
-		       SOLO_VI_WIN_SY(sy) |
-		       SOLO_VI_WIN_EY(ey));
-}
-
-static int solo_v4l2_ch_ext_4up(struct solo_dev *solo_dev, u8 idx, int on)
-{
-	u8 ch = idx * 4;
-
-	if (ch >= solo_dev->nr_chans)
-		return -EINVAL;
-
-	if (!on) {
-		u8 i;
-		for (i = ch; i < ch + 4; i++)
-			solo_win_setup(solo_dev, i, solo_dev->video_hsize,
-				       solo_vlines(solo_dev),
-				       solo_dev->video_hsize,
-				       solo_vlines(solo_dev), 0);
-		return 0;
-	}
-
-	/* Row 1 */
-	solo_win_setup(solo_dev, ch, 0, 0, solo_dev->video_hsize / 2,
-		       solo_vlines(solo_dev) / 2, 3);
-	solo_win_setup(solo_dev, ch + 1, solo_dev->video_hsize / 2, 0,
-		       solo_dev->video_hsize, solo_vlines(solo_dev) / 2, 3);
-	/* Row 2 */
-	solo_win_setup(solo_dev, ch + 2, 0, solo_vlines(solo_dev) / 2,
-		       solo_dev->video_hsize / 2, solo_vlines(solo_dev), 3);
-	solo_win_setup(solo_dev, ch + 3, solo_dev->video_hsize / 2,
-		       solo_vlines(solo_dev) / 2, solo_dev->video_hsize,
-		       solo_vlines(solo_dev), 3);
-
-	return 0;
-}
-
-static int solo_v4l2_ch_ext_16up(struct solo_dev *solo_dev, int on)
-{
-	int sy, ysize, hsize, i;
-
-	if (!on) {
-		for (i = 0; i < 16; i++)
-			solo_win_setup(solo_dev, i, solo_dev->video_hsize,
-				       solo_vlines(solo_dev),
-				       solo_dev->video_hsize,
-				       solo_vlines(solo_dev), 0);
-		return 0;
-	}
-
-	ysize = solo_vlines(solo_dev) / 4;
-	hsize = solo_dev->video_hsize / 4;
-
-	for (sy = 0, i = 0; i < 4; i++, sy += ysize) {
-		solo_win_setup(solo_dev, i * 4, 0, sy, hsize,
-			       sy + ysize, 5);
-		solo_win_setup(solo_dev, (i * 4) + 1, hsize, sy,
-			       hsize * 2, sy + ysize, 5);
-		solo_win_setup(solo_dev, (i * 4) + 2, hsize * 2, sy,
-			       hsize * 3, sy + ysize, 5);
-		solo_win_setup(solo_dev, (i * 4) + 3, hsize * 3, sy,
-			       solo_dev->video_hsize, sy + ysize, 5);
-	}
-
-	return 0;
-}
-
-static int solo_v4l2_ch(struct solo_dev *solo_dev, u8 ch, int on)
-{
-	u8 ext_ch;
-
-	if (ch < solo_dev->nr_chans) {
-		solo_win_setup(solo_dev, ch, on ? 0 : solo_dev->video_hsize,
-			       on ? 0 : solo_vlines(solo_dev),
-			       solo_dev->video_hsize, solo_vlines(solo_dev),
-			       on ? 1 : 0);
-		return 0;
-	}
-
-	if (ch >= solo_dev->nr_chans + solo_dev->nr_ext)
-		return -EINVAL;
-
-	ext_ch = ch - solo_dev->nr_chans;
-
-	/* 4up's first */
-	if (ext_ch < 4)
-		return solo_v4l2_ch_ext_4up(solo_dev, ext_ch, on);
-
-	/* Remaining case is 16up for 16-port */
-	return solo_v4l2_ch_ext_16up(solo_dev, on);
-}
-
-static int solo_v4l2_set_ch(struct solo_dev *solo_dev, u8 ch)
-{
-	if (ch >= solo_dev->nr_chans + solo_dev->nr_ext)
-		return -EINVAL;
-
-	erase_on(solo_dev);
-
-	solo_v4l2_ch(solo_dev, solo_dev->cur_disp_ch, 0);
-	solo_v4l2_ch(solo_dev, ch, 1);
-
-	solo_dev->cur_disp_ch = ch;
-
-	return 0;
-}
-
-static void disp_reset_desc(struct solo_filehandle *fh)
-{
-	/* We use desc mode, which ignores desc 0 */
-	memset(fh->desc, 0, sizeof(*fh->desc));
-	fh->desc_idx = 1;
-}
-
-static int disp_flush_descs(struct solo_filehandle *fh)
-{
-	int ret;
-
-	if (!fh->desc_idx)
-		return 0;
-
-	ret = solo_p2m_dma_desc(fh->solo_dev, SOLO_P2M_DMA_ID_DISP,
-				fh->desc, fh->desc_idx);
-	disp_reset_desc(fh);
-
-	return ret;
-}
-
-static int disp_push_desc(struct solo_filehandle *fh, dma_addr_t dma_addr,
-		      u32 ext_addr, int size, int repeat, int ext_size)
-{
-	if (fh->desc_idx >= SOLO_NR_P2M_DESC) {
-		int ret = disp_flush_descs(fh);
-		if (ret)
-			return ret;
-	}
-
-	solo_p2m_push_desc(&fh->desc[fh->desc_idx], 0, dma_addr, ext_addr,
-			   size, repeat, ext_size);
-	fh->desc_idx++;
-
-	return 0;
-}
-
-static void solo_fillbuf(struct solo_filehandle *fh,
-			 struct videobuf_buffer *vb)
-{
-	struct solo_dev *solo_dev = fh->solo_dev;
-	struct videobuf_dmabuf *vbuf;
-	unsigned int fdma_addr;
-	int error = 1;
-	int i;
-	struct scatterlist *sg;
-	dma_addr_t sg_dma;
-	int sg_size_left;
-
-	vbuf = videobuf_to_dma(vb);
-	if (!vbuf)
-		goto finish_buf;
-
-	if (erase_off(solo_dev)) {
-		int i;
-
-		/* Just blit to the entire sg list, ignoring size */
-		for_each_sg(vbuf->sglist, sg, vbuf->sglen, i) {
-			void *p = sg_virt(sg);
-			size_t len = sg_dma_len(sg);
-
-			for (i = 0; i < len; i += 2) {
-				((u8 *)p)[i] = 0x80;
-				((u8 *)p)[i + 1] = 0x00;
-			}
-		}
-
-		error = 0;
-		goto finish_buf;
-	}
-
-	disp_reset_desc(fh);
-	sg = vbuf->sglist;
-	sg_dma = sg_dma_address(sg);
-	sg_size_left = sg_dma_len(sg);
-
-	fdma_addr = SOLO_DISP_EXT_ADDR + (fh->old_write *
-			(SOLO_HW_BPL * solo_vlines(solo_dev)));
-
-	for (i = 0; i < solo_vlines(solo_dev); i++) {
-		int line_len = solo_bytesperline(solo_dev);
-		int lines;
-
-		if (!sg_size_left) {
-			sg = sg_next(sg);
-			if (sg == NULL)
-				goto finish_buf;
-			sg_dma = sg_dma_address(sg);
-			sg_size_left = sg_dma_len(sg);
-		}
-
-		/* No room for an entire line, so chunk it up */
-		if (sg_size_left < line_len) {
-			int this_addr = fdma_addr;
-
-			while (line_len > 0) {
-				int this_write;
-
-				if (!sg_size_left) {
-					sg = sg_next(sg);
-					if (sg == NULL)
-						goto finish_buf;
-					sg_dma = sg_dma_address(sg);
-					sg_size_left = sg_dma_len(sg);
-				}
-
-				this_write = min(sg_size_left, line_len);
-
-				if (disp_push_desc(fh, sg_dma, this_addr,
-						   this_write, 0, 0))
-					goto finish_buf;
-
-				line_len -= this_write;
-				sg_size_left -= this_write;
-				sg_dma += this_write;
-				this_addr += this_write;
-			}
-
-			fdma_addr += SOLO_HW_BPL;
-			continue;
-		}
-
-		/* Shove as many lines into a repeating descriptor as possible */
-		lines = min(sg_size_left / line_len,
-			    solo_vlines(solo_dev) - i);
-
-		if (disp_push_desc(fh, sg_dma, fdma_addr, line_len,
-				   lines - 1, SOLO_HW_BPL))
-			goto finish_buf;
-
-		i += lines - 1;
-		fdma_addr += SOLO_HW_BPL * lines;
-		sg_dma += lines * line_len;
-		sg_size_left -= lines * line_len;
-	}
-
-	error = disp_flush_descs(fh);
-
-finish_buf:
-	if (error) {
-		vb->state = VIDEOBUF_ERROR;
-	} else {
-		vb->size = solo_vlines(solo_dev) * solo_bytesperline(solo_dev);
-		vb->state = VIDEOBUF_DONE;
-		vb->field_count++;
-		do_gettimeofday(&vb->ts);
-	}
-
-	wake_up(&vb->done);
-
-	return;
-}
-
-static void solo_thread_try(struct solo_filehandle *fh)
-{
-	struct videobuf_buffer *vb;
-	unsigned int cur_write;
-
-	for (;;) {
-		spin_lock(&fh->slock);
-
-		if (list_empty(&fh->vidq_active))
-			break;
-
-		vb = list_first_entry(&fh->vidq_active, struct videobuf_buffer,
-				      queue);
-
-		if (!waitqueue_active(&vb->done))
-			break;
-
-		cur_write = SOLO_VI_STATUS0_PAGE(solo_reg_read(fh->solo_dev,
-						 SOLO_VI_STATUS0));
-		if (cur_write == fh->old_write)
-			break;
-
-		fh->old_write = cur_write;
-		list_del(&vb->queue);
-
-		spin_unlock(&fh->slock);
-
-		solo_fillbuf(fh, vb);
-	}
-
-	assert_spin_locked(&fh->slock);
-	spin_unlock(&fh->slock);
-}
-
-static int solo_thread(void *data)
-{
-	struct solo_filehandle *fh = data;
-	struct solo_dev *solo_dev = fh->solo_dev;
-	DECLARE_WAITQUEUE(wait, current);
-
-	set_freezable();
-	add_wait_queue(&solo_dev->disp_thread_wait, &wait);
-
-	for (;;) {
-		long timeout = schedule_timeout_interruptible(HZ);
-		if (timeout == -ERESTARTSYS || kthread_should_stop())
-			break;
-		solo_thread_try(fh);
-		try_to_freeze();
-	}
-
-	remove_wait_queue(&solo_dev->disp_thread_wait, &wait);
-
-	return 0;
-}
-
-static int solo_start_thread(struct solo_filehandle *fh)
-{
-	fh->kthread = kthread_run(solo_thread, fh, SOLO6X10_NAME "_disp");
-
-	return PTR_RET(fh->kthread);
-}
-
-static void solo_stop_thread(struct solo_filehandle *fh)
-{
-	if (fh->kthread) {
-		kthread_stop(fh->kthread);
-		fh->kthread = NULL;
-	}
-}
-
-static int solo_buf_setup(struct videobuf_queue *vq, unsigned int *count,
-			  unsigned int *size)
-{
-	struct solo_filehandle *fh = vq->priv_data;
-	struct solo_dev *solo_dev  = fh->solo_dev;
-
-	*size = solo_image_size(solo_dev);
-
-	if (*count < MIN_VID_BUFFERS)
-		*count = MIN_VID_BUFFERS;
-
-	return 0;
-}
-
-static int solo_buf_prepare(struct videobuf_queue *vq,
-			    struct videobuf_buffer *vb, enum v4l2_field field)
-{
-	struct solo_filehandle *fh  = vq->priv_data;
-	struct solo_dev *solo_dev = fh->solo_dev;
-
-	vb->size = solo_image_size(solo_dev);
-	if (vb->baddr != 0 && vb->bsize < vb->size)
-		return -EINVAL;
-
-	/* XXX: These properties only change when queue is idle */
-	vb->width  = solo_dev->video_hsize;
-	vb->height = solo_vlines(solo_dev);
-	vb->bytesperline = solo_bytesperline(solo_dev);
-	vb->field  = field;
-
-	if (vb->state == VIDEOBUF_NEEDS_INIT) {
-		int rc = videobuf_iolock(vq, vb, NULL);
-		if (rc < 0) {
-			struct videobuf_dmabuf *dma = videobuf_to_dma(vb);
-			videobuf_dma_unmap(vq->dev, dma);
-			videobuf_dma_free(dma);
-			vb->state = VIDEOBUF_NEEDS_INIT;
-			return rc;
-		}
-	}
-	vb->state = VIDEOBUF_PREPARED;
-
-	return 0;
-}
-
-static void solo_buf_queue(struct videobuf_queue *vq,
-			   struct videobuf_buffer *vb)
-{
-	struct solo_filehandle *fh = vq->priv_data;
-	struct solo_dev *solo_dev = fh->solo_dev;
-
-	vb->state = VIDEOBUF_QUEUED;
-	list_add_tail(&vb->queue, &fh->vidq_active);
-	wake_up_interruptible(&solo_dev->disp_thread_wait);
-}
-
-static void solo_buf_release(struct videobuf_queue *vq,
-			     struct videobuf_buffer *vb)
-{
-	struct videobuf_dmabuf *dma = videobuf_to_dma(vb);
-
-	videobuf_dma_unmap(vq->dev, dma);
-	videobuf_dma_free(dma);
-	vb->state = VIDEOBUF_NEEDS_INIT;
-}
-
-static struct videobuf_queue_ops solo_video_qops = {
-	.buf_setup	= solo_buf_setup,
-	.buf_prepare	= solo_buf_prepare,
-	.buf_queue	= solo_buf_queue,
-	.buf_release	= solo_buf_release,
-};
-
-static unsigned int solo_v4l2_poll(struct file *file,
-				   struct poll_table_struct *wait)
-{
-	struct solo_filehandle *fh = file->private_data;
-
-	return videobuf_poll_stream(file, &fh->vidq, wait);
-}
-
-static int solo_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
-{
-	struct solo_filehandle *fh = file->private_data;
-
-	return videobuf_mmap_mapper(&fh->vidq, vma);
-}
-
-static int solo_v4l2_open(struct file *file)
-{
-	struct solo_dev *solo_dev = video_drvdata(file);
-	struct solo_filehandle *fh;
-	int ret;
-
-	fh = kzalloc(sizeof(*fh), GFP_KERNEL);
-	if (fh == NULL)
-		return -ENOMEM;
-
-	spin_lock_init(&fh->slock);
-	INIT_LIST_HEAD(&fh->vidq_active);
-	fh->solo_dev = solo_dev;
-	file->private_data = fh;
-
-	ret = solo_start_thread(fh);
-	if (ret) {
-		kfree(fh);
-		return ret;
-	}
-
-	videobuf_queue_sg_init(&fh->vidq, &solo_video_qops,
-			       &solo_dev->pdev->dev, &fh->slock,
-			       V4L2_BUF_TYPE_VIDEO_CAPTURE,
-			       SOLO_DISP_PIX_FIELD,
-			       sizeof(struct videobuf_buffer), fh, NULL);
-
-	return 0;
-}
-
-static ssize_t solo_v4l2_read(struct file *file, char __user *data,
-			      size_t count, loff_t *ppos)
-{
-	struct solo_filehandle *fh = file->private_data;
-
-	return videobuf_read_stream(&fh->vidq, data, count, ppos, 0,
-				    file->f_flags & O_NONBLOCK);
-}
-
-static int solo_v4l2_release(struct file *file)
-{
-	struct solo_filehandle *fh = file->private_data;
-
-	videobuf_stop(&fh->vidq);
-	videobuf_mmap_free(&fh->vidq);
-	solo_stop_thread(fh);
-	kfree(fh);
-
-	return 0;
-}
-
-static int solo_querycap(struct file *file, void  *priv,
-			 struct v4l2_capability *cap)
-{
-	struct solo_filehandle  *fh  = priv;
-	struct solo_dev *solo_dev = fh->solo_dev;
-
-	strcpy(cap->driver, SOLO6X10_NAME);
-	strcpy(cap->card, "Softlogic 6x10");
-	snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI %s",
-		 pci_name(solo_dev->pdev));
-	cap->version = SOLO6X10_VER_NUM;
-	cap->capabilities =     V4L2_CAP_VIDEO_CAPTURE |
-				V4L2_CAP_READWRITE |
-				V4L2_CAP_STREAMING;
-	return 0;
-}
-
-static int solo_enum_ext_input(struct solo_dev *solo_dev,
-			       struct v4l2_input *input)
-{
-	static const char *dispnames_1[] = { "4UP" };
-	static const char *dispnames_2[] = { "4UP-1", "4UP-2" };
-	static const char *dispnames_5[] = {
-		"4UP-1", "4UP-2", "4UP-3", "4UP-4", "16UP"
-	};
-	const char **dispnames;
-
-	if (input->index >= (solo_dev->nr_chans + solo_dev->nr_ext))
-		return -EINVAL;
-
-	if (solo_dev->nr_ext == 5)
-		dispnames = dispnames_5;
-	else if (solo_dev->nr_ext == 2)
-		dispnames = dispnames_2;
-	else
-		dispnames = dispnames_1;
-
-	snprintf(input->name, sizeof(input->name), "Multi %s",
-		 dispnames[input->index - solo_dev->nr_chans]);
-
-	return 0;
-}
-
-static int solo_enum_input(struct file *file, void *priv,
-			   struct v4l2_input *input)
-{
-	struct solo_filehandle *fh  = priv;
-	struct solo_dev *solo_dev = fh->solo_dev;
-
-	if (input->index >= solo_dev->nr_chans) {
-		int ret = solo_enum_ext_input(solo_dev, input);
-		if (ret < 0)
-			return ret;
-	} else {
-		snprintf(input->name, sizeof(input->name), "Camera %d",
-			 input->index + 1);
-
-		/* We can only check this for normal inputs */
-		if (!tw28_get_video_status(solo_dev, input->index))
-			input->status = V4L2_IN_ST_NO_SIGNAL;
-	}
-
-	input->type = V4L2_INPUT_TYPE_CAMERA;
-
-	if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC)
-		input->std = V4L2_STD_NTSC_M;
-	else
-		input->std = V4L2_STD_PAL_B;
-
-	return 0;
-}
-
-static int solo_set_input(struct file *file, void *priv, unsigned int index)
-{
-	struct solo_filehandle *fh = priv;
-
-	return solo_v4l2_set_ch(fh->solo_dev, index);
-}
-
-static int solo_get_input(struct file *file, void *priv, unsigned int *index)
-{
-	struct solo_filehandle *fh = priv;
-
-	*index = fh->solo_dev->cur_disp_ch;
-
-	return 0;
-}
-
-static int solo_enum_fmt_cap(struct file *file, void *priv,
-			     struct v4l2_fmtdesc *f)
-{
-	if (f->index)
-		return -EINVAL;
-
-	f->pixelformat = V4L2_PIX_FMT_UYVY;
-	strlcpy(f->description, "UYUV 4:2:2 Packed", sizeof(f->description));
-
-	return 0;
-}
-
-static int solo_try_fmt_cap(struct file *file, void *priv,
-			    struct v4l2_format *f)
-{
-	struct solo_filehandle *fh = priv;
-	struct solo_dev *solo_dev = fh->solo_dev;
-	struct v4l2_pix_format *pix = &f->fmt.pix;
-	int image_size = solo_image_size(solo_dev);
-
-	/* Check supported sizes */
-	if (pix->width != solo_dev->video_hsize)
-		pix->width = solo_dev->video_hsize;
-	if (pix->height != solo_vlines(solo_dev))
-		pix->height = solo_vlines(solo_dev);
-	if (pix->sizeimage != image_size)
-		pix->sizeimage = image_size;
-
-	/* Check formats */
-	if (pix->field == V4L2_FIELD_ANY)
-		pix->field = SOLO_DISP_PIX_FIELD;
-
-	if (pix->pixelformat != V4L2_PIX_FMT_UYVY ||
-	    pix->field       != SOLO_DISP_PIX_FIELD ||
-	    pix->colorspace  != V4L2_COLORSPACE_SMPTE170M)
-		return -EINVAL;
-
-	return 0;
-}
-
-static int solo_set_fmt_cap(struct file *file, void *priv,
-			    struct v4l2_format *f)
-{
-	struct solo_filehandle *fh = priv;
-
-	if (videobuf_queue_is_busy(&fh->vidq))
-		return -EBUSY;
-
-	/* For right now, if it doesn't match our running config,
-	 * then fail */
-	return solo_try_fmt_cap(file, priv, f);
-}
-
-static int solo_get_fmt_cap(struct file *file, void *priv,
-			    struct v4l2_format *f)
-{
-	struct solo_filehandle *fh = priv;
-	struct solo_dev *solo_dev = fh->solo_dev;
-	struct v4l2_pix_format *pix = &f->fmt.pix;
-
-	pix->width = solo_dev->video_hsize;
-	pix->height = solo_vlines(solo_dev);
-	pix->pixelformat = V4L2_PIX_FMT_UYVY;
-	pix->field = SOLO_DISP_PIX_FIELD;
-	pix->sizeimage = solo_image_size(solo_dev);
-	pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
-	pix->bytesperline = solo_bytesperline(solo_dev);
-
-	return 0;
-}
-
-static int solo_reqbufs(struct file *file, void *priv,
-			struct v4l2_requestbuffers *req)
-{
-	struct solo_filehandle *fh = priv;
-
-	return videobuf_reqbufs(&fh->vidq, req);
-}
-
-static int solo_querybuf(struct file *file, void *priv, struct v4l2_buffer *buf)
-{
-	struct solo_filehandle *fh = priv;
-
-	return videobuf_querybuf(&fh->vidq, buf);
-}
-
-static int solo_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
-{
-	struct solo_filehandle *fh = priv;
-
-	return videobuf_qbuf(&fh->vidq, buf);
-}
-
-static int solo_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
-{
-	struct solo_filehandle *fh = priv;
-
-	return videobuf_dqbuf(&fh->vidq, buf, file->f_flags & O_NONBLOCK);
-}
-
-static int solo_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
-{
-	struct solo_filehandle *fh = priv;
-
-	if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		return -EINVAL;
-
-	return videobuf_streamon(&fh->vidq);
-}
-
-static int solo_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
-{
-	struct solo_filehandle *fh = priv;
-
-	if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		return -EINVAL;
-
-	return videobuf_streamoff(&fh->vidq);
-}
-
-static int solo_s_std(struct file *file, void *priv, v4l2_std_id *i)
-{
-	return 0;
-}
-
-static const u32 solo_motion_ctrls[] = {
-	V4L2_CID_MOTION_TRACE,
-	0
-};
-
-static const u32 *solo_ctrl_classes[] = {
-	solo_motion_ctrls,
-	NULL
-};
-
-static int solo_disp_queryctrl(struct file *file, void *priv,
-			       struct v4l2_queryctrl *qc)
-{
-	qc->id = v4l2_ctrl_next(solo_ctrl_classes, qc->id);
-	if (!qc->id)
-		return -EINVAL;
-
-	switch (qc->id) {
-#ifdef PRIVATE_CIDS
-	case V4L2_CID_MOTION_TRACE:
-		qc->type = V4L2_CTRL_TYPE_BOOLEAN;
-		qc->minimum = 0;
-		qc->maximum = qc->step = 1;
-		qc->default_value = 0;
-		strlcpy(qc->name, "Motion Detection Trace", sizeof(qc->name));
-		return 0;
-#else
-	case V4L2_CID_MOTION_TRACE:
-		return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0);
-#endif
-	}
-	return -EINVAL;
-}
-
-static int solo_disp_g_ctrl(struct file *file, void *priv,
-			    struct v4l2_control *ctrl)
-{
-	struct solo_filehandle *fh = priv;
-	struct solo_dev *solo_dev = fh->solo_dev;
-
-	switch (ctrl->id) {
-	case V4L2_CID_MOTION_TRACE:
-		ctrl->value = solo_reg_read(solo_dev, SOLO_VI_MOTION_BAR)
-			? 1 : 0;
-		return 0;
-	}
-	return -EINVAL;
-}
-
-static int solo_disp_s_ctrl(struct file *file, void *priv,
-			    struct v4l2_control *ctrl)
-{
-	struct solo_filehandle *fh = priv;
-	struct solo_dev *solo_dev = fh->solo_dev;
-
-	switch (ctrl->id) {
-	case V4L2_CID_MOTION_TRACE:
-		if (ctrl->value) {
-			solo_reg_write(solo_dev, SOLO_VI_MOTION_BORDER,
-					SOLO_VI_MOTION_Y_ADD |
-					SOLO_VI_MOTION_Y_VALUE(0x20) |
-					SOLO_VI_MOTION_CB_VALUE(0x10) |
-					SOLO_VI_MOTION_CR_VALUE(0x10));
-			solo_reg_write(solo_dev, SOLO_VI_MOTION_BAR,
-					SOLO_VI_MOTION_CR_ADD |
-					SOLO_VI_MOTION_Y_VALUE(0x10) |
-					SOLO_VI_MOTION_CB_VALUE(0x80) |
-					SOLO_VI_MOTION_CR_VALUE(0x10));
-		} else {
-			solo_reg_write(solo_dev, SOLO_VI_MOTION_BORDER, 0);
-			solo_reg_write(solo_dev, SOLO_VI_MOTION_BAR, 0);
-		}
-		return 0;
-	}
-	return -EINVAL;
-}
-
-static const struct v4l2_file_operations solo_v4l2_fops = {
-	.owner			= THIS_MODULE,
-	.open			= solo_v4l2_open,
-	.release		= solo_v4l2_release,
-	.read			= solo_v4l2_read,
-	.poll			= solo_v4l2_poll,
-	.mmap			= solo_v4l2_mmap,
-	.ioctl			= video_ioctl2,
-};
-
-static const struct v4l2_ioctl_ops solo_v4l2_ioctl_ops = {
-	.vidioc_querycap		= solo_querycap,
-	.vidioc_s_std			= solo_s_std,
-	/* Input callbacks */
-	.vidioc_enum_input		= solo_enum_input,
-	.vidioc_s_input			= solo_set_input,
-	.vidioc_g_input			= solo_get_input,
-	/* Video capture format callbacks */
-	.vidioc_enum_fmt_vid_cap	= solo_enum_fmt_cap,
-	.vidioc_try_fmt_vid_cap		= solo_try_fmt_cap,
-	.vidioc_s_fmt_vid_cap		= solo_set_fmt_cap,
-	.vidioc_g_fmt_vid_cap		= solo_get_fmt_cap,
-	/* Streaming I/O */
-	.vidioc_reqbufs			= solo_reqbufs,
-	.vidioc_querybuf		= solo_querybuf,
-	.vidioc_qbuf			= solo_qbuf,
-	.vidioc_dqbuf			= solo_dqbuf,
-	.vidioc_streamon		= solo_streamon,
-	.vidioc_streamoff		= solo_streamoff,
-	/* Controls */
-	.vidioc_queryctrl		= solo_disp_queryctrl,
-	.vidioc_g_ctrl			= solo_disp_g_ctrl,
-	.vidioc_s_ctrl			= solo_disp_s_ctrl,
-};
-
-static struct video_device solo_v4l2_template = {
-	.name			= SOLO6X10_NAME,
-	.fops			= &solo_v4l2_fops,
-	.ioctl_ops		= &solo_v4l2_ioctl_ops,
-	.minor			= -1,
-	.release		= video_device_release,
-
-	.tvnorms		= V4L2_STD_NTSC_M | V4L2_STD_PAL_B,
-	.current_norm		= V4L2_STD_NTSC_M,
-};
-
-int solo_v4l2_init(struct solo_dev *solo_dev)
-{
-	int ret;
-	int i;
-
-	init_waitqueue_head(&solo_dev->disp_thread_wait);
-
-	solo_dev->vfd = video_device_alloc();
-	if (!solo_dev->vfd)
-		return -ENOMEM;
-
-	*solo_dev->vfd = solo_v4l2_template;
-	solo_dev->vfd->parent = &solo_dev->pdev->dev;
-
-	ret = video_register_device(solo_dev->vfd, VFL_TYPE_GRABBER, video_nr);
-	if (ret < 0) {
-		video_device_release(solo_dev->vfd);
-		solo_dev->vfd = NULL;
-		return ret;
-	}
-
-	video_set_drvdata(solo_dev->vfd, solo_dev);
-
-	snprintf(solo_dev->vfd->name, sizeof(solo_dev->vfd->name), "%s (%i)",
-		 SOLO6X10_NAME, solo_dev->vfd->num);
-
-	if (video_nr != -1)
-		video_nr++;
-
-	dev_info(&solo_dev->pdev->dev, "Display as /dev/video%d with "
-		 "%d inputs (%d extended)\n", solo_dev->vfd->num,
-		 solo_dev->nr_chans, solo_dev->nr_ext);
-
-	/* Cycle all the channels and clear */
-	for (i = 0; i < solo_dev->nr_chans; i++) {
-		solo_v4l2_set_ch(solo_dev, i);
-		while (erase_off(solo_dev))
-			;/* Do nothing */
-	}
-
-	/* Set the default display channel */
-	solo_v4l2_set_ch(solo_dev, 0);
-	while (erase_off(solo_dev))
-		;/* Do nothing */
-
-	solo_irq_on(solo_dev, SOLO_IRQ_VIDEO_IN);
-
-	return 0;
-}
-
-void solo_v4l2_exit(struct solo_dev *solo_dev)
-{
-	solo_irq_off(solo_dev, SOLO_IRQ_VIDEO_IN);
-	if (solo_dev->vfd) {
-		video_unregister_device(solo_dev->vfd);
-		solo_dev->vfd = NULL;
-	}
-}
diff --git a/drivers/staging/netlogic/Kconfig b/drivers/staging/netlogic/Kconfig
new file mode 100644
index 0000000..d660de5
--- /dev/null
+++ b/drivers/staging/netlogic/Kconfig
@@ -0,0 +1,7 @@
+config NETLOGIC_XLR_NET
+	tristate "Netlogic XLR/XLS network device"
+	depends on CPU_XLR
+	select PHYLIB
+	---help---
+	This driver support Netlogic XLR/XLS on chip gigabit
+	Ethernet.
diff --git a/drivers/staging/netlogic/Makefile b/drivers/staging/netlogic/Makefile
new file mode 100644
index 0000000..f7355e3
--- /dev/null
+++ b/drivers/staging/netlogic/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_NETLOGIC_XLR_NET) += xlr_net.o platform_net.o
diff --git a/drivers/staging/netlogic/TODO b/drivers/staging/netlogic/TODO
new file mode 100644
index 0000000..08e6d52
--- /dev/null
+++ b/drivers/staging/netlogic/TODO
@@ -0,0 +1,12 @@
+* Implementing 64bit stat counter in software
+* All memory allocation should be changed to DMA allocations
+* All the netdev should be linked to single pdev as parent
+* Changing comments in to linux standred format
+
+Please send patches
+To:
+Ganesan Ramalingam <ganesanr@broadcom.com>
+Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc:
+Jayachandran Chandrashekaran Nair <jchandra@broadcom.com>
+
diff --git a/drivers/staging/netlogic/platform_net.c b/drivers/staging/netlogic/platform_net.c
new file mode 100644
index 0000000..61f20e1
--- /dev/null
+++ b/drivers/staging/netlogic/platform_net.c
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 2003-2012 Broadcom Corporation
+ * 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
+ * 1. Redistributions of source code must retain the above copyright
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the Broadcom
+ * license below:
+ *
+ * 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, this list of conditions and the following disclaimer.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BROADCOM ``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 BROADCOM 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/device.h>
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/resource.h>
+#include <linux/phy.h>
+
+#include <asm/netlogic/haldefs.h>
+#include <asm/netlogic/common.h>
+#include <asm/netlogic/xlr/fmn.h>
+#include <asm/netlogic/xlr/xlr.h>
+#include <asm/netlogic/psb-bootinfo.h>
+#include <asm/netlogic/xlr/pic.h>
+#include <asm/netlogic/xlr/iomap.h>
+
+#include "platform_net.h"
+
+/* Linux Net */
+#define MAX_NUM_GMAC		8
+#define MAX_NUM_XLS_GMAC	8
+#define MAX_NUM_XLR_GMAC	4
+
+
+static u32 xlr_gmac_offsets[] = {
+	NETLOGIC_IO_GMAC_0_OFFSET, NETLOGIC_IO_GMAC_1_OFFSET,
+	NETLOGIC_IO_GMAC_2_OFFSET, NETLOGIC_IO_GMAC_3_OFFSET,
+	NETLOGIC_IO_GMAC_4_OFFSET, NETLOGIC_IO_GMAC_5_OFFSET,
+	NETLOGIC_IO_GMAC_6_OFFSET, NETLOGIC_IO_GMAC_7_OFFSET
+};
+
+static u32 xlr_gmac_irqs[] = { PIC_GMAC_0_IRQ, PIC_GMAC_1_IRQ,
+	PIC_GMAC_2_IRQ, PIC_GMAC_3_IRQ,
+	PIC_GMAC_4_IRQ, PIC_GMAC_5_IRQ,
+	PIC_GMAC_6_IRQ, PIC_GMAC_7_IRQ
+};
+
+static struct xlr_net_data ndata[MAX_NUM_GMAC];
+static struct resource xlr_net_res[8][2];
+static struct platform_device xlr_net_dev[8];
+static u32 __iomem *gmac0_addr;
+static u32 __iomem *gmac4_addr;
+static u32 __iomem *gpio_addr;
+
+static void config_mac(struct xlr_net_data *nd, int phy, u32 __iomem *serdes,
+		u32 __iomem *pcs, int rfr, int tx, int *bkt_size,
+		struct xlr_fmn_info *gmac_fmn_info, int phy_addr)
+{
+	nd->cpu_mask = nlm_current_node()->coremask;
+	nd->phy_interface = phy;
+	nd->rfr_station = rfr;
+	nd->tx_stnid = tx;
+	nd->mii_addr = gmac0_addr;
+	nd->serdes_addr = serdes;
+	nd->pcs_addr = pcs;
+	nd->gpio_addr = gpio_addr;
+
+	nd->bucket_size = bkt_size;
+	nd->gmac_fmn_info = gmac_fmn_info;
+	nd->phy_addr = phy_addr;
+}
+
+static void net_device_init(int id, struct resource *res, int offset, int irq)
+{
+	res[0].name = "gmac";
+	res[0].start = CPHYSADDR(nlm_mmio_base(offset));
+	res[0].end = res[0].start + 0xfff;
+	res[0].flags = IORESOURCE_MEM;
+
+	res[1].name = "gmac";
+	res[1].start = irq;
+	res[1].end = irq;
+	res[1].flags = IORESOURCE_IRQ;
+
+	xlr_net_dev[id].name = "xlr-net";
+	xlr_net_dev[id].id = id;
+	xlr_net_dev[id].num_resources = 2;
+	xlr_net_dev[id].resource = res;
+	xlr_net_dev[id].dev.platform_data = &ndata[id];
+}
+
+static void xls_gmac_init(void)
+{
+	int mac;
+
+	gmac4_addr = ioremap(CPHYSADDR(
+		nlm_mmio_base(NETLOGIC_IO_GMAC_4_OFFSET)), 0xfff);
+	/* Passing GPIO base for serdes init. Only needed on sgmii ports*/
+	gpio_addr = ioremap(CPHYSADDR(
+		nlm_mmio_base(NETLOGIC_IO_GPIO_OFFSET)), 0xfff);
+
+	switch (nlm_prom_info.board_major_version) {
+	case 12:
+		/* first block RGMII or XAUI, use RGMII */
+		config_mac(&ndata[0],
+			PHY_INTERFACE_MODE_RGMII,
+			gmac0_addr,	/* serdes */
+			gmac0_addr,	/* pcs */
+			FMN_STNID_GMACRFR_0,
+			FMN_STNID_GMAC0_TX0,
+			xlr_board_fmn_config.bucket_size,
+			&xlr_board_fmn_config.gmac[0],
+			0);
+
+		net_device_init(0, xlr_net_res[0], xlr_gmac_offsets[0],
+				xlr_gmac_irqs[0]);
+		platform_device_register(&xlr_net_dev[0]);
+
+		/* second block is XAUI, not supported yet */
+		break;
+	default:
+		/* default XLS config, all ports SGMII */
+		for (mac = 0; mac < 4; mac++) {
+			config_mac(&ndata[mac],
+				PHY_INTERFACE_MODE_SGMII,
+				gmac0_addr,	/* serdes */
+				gmac0_addr,	/* pcs */
+				FMN_STNID_GMACRFR_0,
+				FMN_STNID_GMAC0_TX0 + mac,
+				xlr_board_fmn_config.bucket_size,
+				&xlr_board_fmn_config.gmac[0],
+				/* PHY address according to chip/board */
+				mac + 0x10);
+
+			net_device_init(mac, xlr_net_res[mac],
+					xlr_gmac_offsets[mac],
+					xlr_gmac_irqs[mac]);
+			platform_device_register(&xlr_net_dev[mac]);
+		}
+
+		for (mac = 4; mac < MAX_NUM_XLS_GMAC; mac++) {
+			config_mac(&ndata[mac],
+				PHY_INTERFACE_MODE_SGMII,
+				gmac4_addr,	/* serdes */
+				gmac4_addr,	/* pcs */
+				FMN_STNID_GMAC1_FR_0,
+				FMN_STNID_GMAC1_TX0 + mac - 4,
+				xlr_board_fmn_config.bucket_size,
+				&xlr_board_fmn_config.gmac[1],
+				/* PHY address according to chip/board */
+				mac + 0x10);
+
+			net_device_init(mac, xlr_net_res[mac],
+					xlr_gmac_offsets[mac],
+					xlr_gmac_irqs[mac]);
+			platform_device_register(&xlr_net_dev[mac]);
+		}
+	}
+}
+
+static void xlr_gmac_init(void)
+{
+	int mac;
+
+	/* assume all GMACs for now */
+	for (mac = 0; mac < MAX_NUM_XLR_GMAC; mac++) {
+		config_mac(&ndata[mac],
+			PHY_INTERFACE_MODE_RGMII,
+			0,
+			0,
+			FMN_STNID_GMACRFR_0,
+			FMN_STNID_GMAC0_TX0,
+			xlr_board_fmn_config.bucket_size,
+			&xlr_board_fmn_config.gmac[0],
+			mac);
+
+		net_device_init(mac, xlr_net_res[mac], xlr_gmac_offsets[mac],
+				xlr_gmac_irqs[mac]);
+		platform_device_register(&xlr_net_dev[mac]);
+	}
+}
+
+static int __init xlr_net_init(void)
+{
+	gmac0_addr = ioremap(CPHYSADDR(
+		nlm_mmio_base(NETLOGIC_IO_GMAC_0_OFFSET)), 0xfff);
+
+	if (nlm_chip_is_xls())
+		xls_gmac_init();
+	else
+		xlr_gmac_init();
+
+	return 0;
+}
+
+arch_initcall(xlr_net_init);
diff --git a/drivers/staging/netlogic/platform_net.h b/drivers/staging/netlogic/platform_net.h
new file mode 100644
index 0000000..29deeea
--- /dev/null
+++ b/drivers/staging/netlogic/platform_net.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2003-2012 Broadcom Corporation
+ * 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 Broadcom
+ * license below:
+ *
+ * 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, this list of conditions and the following disclaimer.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BROADCOM ``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 BROADCOM 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.
+ */
+struct xlr_net_data {
+	int cpu_mask;
+	u32 __iomem *mii_addr;
+	u32 __iomem *serdes_addr;
+	u32 __iomem *pcs_addr;
+	u32 __iomem *gpio_addr;
+	int phy_interface;
+	int rfr_station;
+	int tx_stnid;
+	int *bucket_size;
+	int phy_addr;
+	struct xlr_fmn_info *gmac_fmn_info;
+};
diff --git a/drivers/staging/netlogic/xlr_net.c b/drivers/staging/netlogic/xlr_net.c
new file mode 100644
index 0000000..dd98cb1
--- /dev/null
+++ b/drivers/staging/netlogic/xlr_net.c
@@ -0,0 +1,1114 @@
+/*
+ * Copyright (c) 2003-2012 Broadcom Corporation
+ * 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 Broadcom
+ * license below:
+ *
+ * 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, this list of conditions and the following disclaimer.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BROADCOM ``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 BROADCOM 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/phy.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/smp.h>
+#include <linux/ethtool.h>
+#include <linux/module.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/jiffies.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+
+#include <asm/mipsregs.h>
+
+/* fmn.h - For FMN credit configuration and registering fmn_handler.
+ * FMN is communication mechanism that allows processing agents within
+ * XLR/XLS to communicate each other.
+ */
+#include <asm/netlogic/xlr/fmn.h>
+
+#include "platform_net.h"
+#include "xlr_net.h"
+
+/*
+ * The readl/writel implementation byteswaps on XLR/XLS, so
+ * we need to use __raw_ IO to read the NAE registers
+ * because they are in the big-endian MMIO area on the SoC.
+ */
+static inline void xlr_nae_wreg(u32 __iomem *base, unsigned int reg, u32 val)
+{
+	__raw_writel(val, base + reg);
+}
+
+static inline u32 xlr_nae_rdreg(u32 __iomem *base, unsigned int reg)
+{
+	return __raw_readl(base + reg);
+}
+
+static inline void xlr_reg_update(u32 *base_addr,
+		u32 off, u32 val, u32 mask)
+{
+	u32 tmp;
+
+	tmp = xlr_nae_rdreg(base_addr, off);
+	xlr_nae_wreg(base_addr, off, (tmp & ~mask) | (val & mask));
+}
+
+/*
+ * Table of net_device pointers indexed by port, this will be used to
+ * lookup the net_device corresponding to a port by the message ring handler.
+ *
+ * Maximum ports in XLR/XLS is 8(8 GMAC on XLS, 4 GMAC + 2 XGMAC on XLR)
+ */
+static struct net_device *mac_to_ndev[8];
+
+static inline struct sk_buff *mac_get_skb_back_ptr(void *addr)
+{
+	struct sk_buff **back_ptr;
+
+	/* this function should be used only for newly allocated packets.
+	 * It assumes the first cacheline is for the back pointer related
+	 * book keeping info.
+	 */
+	back_ptr = (struct sk_buff **)(addr - MAC_SKB_BACK_PTR_SIZE);
+	return *back_ptr;
+}
+
+static inline void mac_put_skb_back_ptr(struct sk_buff *skb)
+{
+	struct sk_buff **back_ptr = (struct sk_buff **)skb->data;
+
+	/* this function should be used only for newly allocated packets.
+	 * It assumes the first cacheline is for the back pointer related
+	 * book keeping info.
+	 */
+	skb_reserve(skb, MAC_SKB_BACK_PTR_SIZE);
+	*back_ptr = skb;
+}
+
+static int send_to_rfr_fifo(struct xlr_net_priv *priv, void *addr)
+{
+	struct nlm_fmn_msg msg;
+	int ret = 0, num_try = 0, stnid;
+	unsigned long paddr, mflags;
+
+	paddr = virt_to_bus(addr);
+	msg.msg0 = (u64)paddr & 0xffffffffe0ULL;
+	msg.msg1 = 0;
+	msg.msg2 = 0;
+	msg.msg3 = 0;
+	stnid = priv->nd->rfr_station;
+	do {
+		mflags = nlm_cop2_enable();
+		ret = nlm_fmn_send(1, 0, stnid, &msg);
+		nlm_cop2_restore(mflags);
+		if (ret == 0)
+			return 0;
+	} while (++num_try < 10000);
+
+	pr_err("Send to RFR failed in RX path\n");
+	return ret;
+}
+
+static inline struct sk_buff *xlr_alloc_skb(void)
+{
+	struct sk_buff *skb;
+
+	/* skb->data is cache aligned */
+	skb = alloc_skb(XLR_RX_BUF_SIZE, GFP_ATOMIC);
+	if (!skb) {
+		pr_err("SKB allocation failed\n");
+		return NULL;
+	}
+	mac_put_skb_back_ptr(skb);
+	return skb;
+}
+
+static void xlr_net_fmn_handler(int bkt, int src_stnid, int size,
+		int code, struct nlm_fmn_msg *msg, void *arg)
+{
+	struct sk_buff *skb, *skb_new = NULL;
+	struct net_device *ndev;
+	struct xlr_net_priv *priv;
+	u64 length, port;
+	void *addr;
+
+	length = (msg->msg0 >> 40) & 0x3fff;
+	if (length == 0) {
+		addr = bus_to_virt(msg->msg0 & 0xffffffffffULL);
+		dev_kfree_skb_any(addr);
+	} else if (length) {
+		addr = bus_to_virt(msg->msg0 & 0xffffffffe0ULL);
+		length = length - BYTE_OFFSET - MAC_CRC_LEN;
+		port = msg->msg0 & 0x0f;
+		if (src_stnid == FMN_STNID_GMAC1)
+			port = port + 4;
+		skb = mac_get_skb_back_ptr(addr);
+		skb->dev = mac_to_ndev[port];
+		ndev = skb->dev;
+		priv = netdev_priv(ndev);
+
+		/* 16 byte IP header align */
+		skb_reserve(skb, BYTE_OFFSET);
+		skb_put(skb, length);
+		skb->protocol = eth_type_trans(skb, skb->dev);
+		skb->dev->last_rx = jiffies;
+		netif_rx(skb);
+		/* Fill rx ring */
+		skb_new = xlr_alloc_skb();
+		if (skb_new)
+			send_to_rfr_fifo(priv, skb_new->data);
+	}
+	return;
+}
+
+/* Ethtool operation */
+static int xlr_get_settings(struct net_device *ndev, struct ethtool_cmd *ecmd)
+{
+	struct xlr_net_priv *priv = netdev_priv(ndev);
+	struct phy_device *phydev = priv->mii_bus->phy_map[priv->phy_addr];
+
+	if (!phydev)
+		return -ENODEV;
+	return phy_ethtool_gset(phydev, ecmd);
+}
+
+static int xlr_set_settings(struct net_device *ndev, struct ethtool_cmd *ecmd)
+{
+	struct xlr_net_priv *priv = netdev_priv(ndev);
+	struct phy_device *phydev = priv->mii_bus->phy_map[priv->phy_addr];
+
+	if (!phydev)
+		return -ENODEV;
+	return phy_ethtool_sset(phydev, ecmd);
+}
+
+static struct ethtool_ops xlr_ethtool_ops = {
+	.get_settings = xlr_get_settings,
+	.set_settings = xlr_set_settings,
+};
+
+/* Net operations */
+static int xlr_net_fill_rx_ring(struct net_device *ndev)
+{
+	struct sk_buff *skb;
+	struct xlr_net_priv *priv = netdev_priv(ndev);
+	int i;
+
+	for (i = 0; i < MAX_FRIN_SPILL/2; i++) {
+		skb = xlr_alloc_skb();
+		if (!skb)
+			return -ENOMEM;
+		send_to_rfr_fifo(priv, skb->data);
+	}
+	pr_info("Rx ring setup done\n");
+	return 0;
+}
+
+static int xlr_net_open(struct net_device *ndev)
+{
+	u32 err;
+	struct xlr_net_priv *priv = netdev_priv(ndev);
+	struct phy_device *phydev = priv->mii_bus->phy_map[priv->phy_addr];
+
+	/* schedule a link state check */
+	phy_start(phydev);
+
+	err = phy_start_aneg(phydev);
+	if (err) {
+		pr_err("Autoneg failed\n");
+		return err;
+	}
+
+	/* Setup the speed from PHY to internal reg*/
+	xlr_set_gmac_speed(priv);
+	netif_tx_start_all_queues(ndev);
+	return 0;
+}
+
+static int xlr_net_stop(struct net_device *ndev)
+{
+	struct xlr_net_priv *priv = netdev_priv(ndev);
+	struct phy_device *phydev = priv->mii_bus->phy_map[priv->phy_addr];
+
+	phy_stop(phydev);
+	netif_tx_stop_all_queues(ndev);
+	return 0;
+}
+
+static void xlr_make_tx_desc(struct nlm_fmn_msg *msg, unsigned long addr,
+		struct sk_buff *skb)
+{
+	unsigned long physkb = virt_to_phys(skb);
+	int cpu_core = nlm_core_id();
+	int fr_stn_id = cpu_core * 8 + XLR_FB_STN;	/* FB to 6th bucket */
+	msg->msg0 = (((u64)1 << 63)	|	/* End of packet descriptor */
+		((u64)127 << 54)	|	/* No Free back */
+		(u64)skb->len << 40	|	/* Length of data */
+		((u64)addr));
+	msg->msg1 = (((u64)1 << 63)	|
+		((u64)fr_stn_id << 54)	|	/* Free back id */
+		(u64)0 << 40		|	/* Set len to 0 */
+		((u64)physkb  & 0xffffffff));	/* 32bit address */
+	msg->msg2 = msg->msg3 = 0;
+}
+
+static void __maybe_unused xlr_wakeup_queue(unsigned long dev)
+{
+	struct net_device *ndev = (struct net_device *) dev;
+	struct xlr_net_priv *priv = netdev_priv(ndev);
+	struct phy_device *phydev = priv->mii_bus->phy_map[priv->phy_addr];
+
+	if (phydev->link)
+		netif_tx_wake_queue(netdev_get_tx_queue(ndev, priv->wakeup_q));
+}
+
+static netdev_tx_t xlr_net_start_xmit(struct sk_buff *skb,
+		struct net_device *ndev)
+{
+	struct nlm_fmn_msg msg;
+	struct xlr_net_priv *priv = netdev_priv(ndev);
+	int ret;
+	u32 flags;
+
+	xlr_make_tx_desc(&msg, virt_to_phys(skb->data), skb);
+	flags = nlm_cop2_enable();
+	ret = nlm_fmn_send(2, 0, priv->nd->tx_stnid, &msg);
+	nlm_cop2_restore(flags);
+	if (ret)
+		dev_kfree_skb_any(skb);
+	return NETDEV_TX_OK;
+}
+
+static u16 xlr_net_select_queue(struct net_device *ndev, struct sk_buff *skb)
+{
+	return (u16)smp_processor_id();
+}
+
+static void xlr_hw_set_mac_addr(struct net_device *ndev)
+{
+	struct xlr_net_priv *priv = netdev_priv(ndev);
+
+	/* set mac station address */
+	xlr_nae_wreg(priv->base_addr, R_MAC_ADDR0,
+		((ndev->dev_addr[5] << 24) | (ndev->dev_addr[4] << 16) |
+		(ndev->dev_addr[3] << 8) | (ndev->dev_addr[2])));
+	xlr_nae_wreg(priv->base_addr, R_MAC_ADDR0 + 1,
+		((ndev->dev_addr[1] << 24) | (ndev->dev_addr[0] << 16)));
+
+	xlr_nae_wreg(priv->base_addr, R_MAC_ADDR_MASK2, 0xffffffff);
+	xlr_nae_wreg(priv->base_addr, R_MAC_ADDR_MASK2 + 1, 0xffffffff);
+	xlr_nae_wreg(priv->base_addr, R_MAC_ADDR_MASK3, 0xffffffff);
+	xlr_nae_wreg(priv->base_addr, R_MAC_ADDR_MASK3 + 1, 0xffffffff);
+
+	xlr_nae_wreg(priv->base_addr, R_MAC_FILTER_CONFIG,
+		(1 << O_MAC_FILTER_CONFIG__BROADCAST_EN) |
+		(1 << O_MAC_FILTER_CONFIG__ALL_MCAST_EN) |
+		(1 << O_MAC_FILTER_CONFIG__MAC_ADDR0_VALID));
+
+	if (priv->nd->phy_interface == PHY_INTERFACE_MODE_RGMII ||
+			priv->nd->phy_interface == PHY_INTERFACE_MODE_SGMII)
+		xlr_reg_update(priv->base_addr, R_IPG_IFG, MAC_B2B_IPG, 0x7f);
+}
+
+static int xlr_net_set_mac_addr(struct net_device *ndev, void *data)
+{
+	int err;
+
+	err = eth_mac_addr(ndev, data);
+	if (err)
+		return err;
+	xlr_hw_set_mac_addr(ndev);
+	return 0;
+}
+
+static void xlr_set_rx_mode(struct net_device *ndev)
+{
+	struct xlr_net_priv *priv = netdev_priv(ndev);
+	u32 regval;
+
+	regval = xlr_nae_rdreg(priv->base_addr, R_MAC_FILTER_CONFIG);
+
+	if (ndev->flags & IFF_PROMISC) {
+		regval |= (1 << O_MAC_FILTER_CONFIG__BROADCAST_EN) |
+		(1 << O_MAC_FILTER_CONFIG__PAUSE_FRAME_EN) |
+		(1 << O_MAC_FILTER_CONFIG__ALL_MCAST_EN) |
+		(1 << O_MAC_FILTER_CONFIG__ALL_UCAST_EN);
+	} else {
+		regval &= ~((1 << O_MAC_FILTER_CONFIG__PAUSE_FRAME_EN) |
+		(1 << O_MAC_FILTER_CONFIG__ALL_UCAST_EN));
+	}
+
+	xlr_nae_wreg(priv->base_addr, R_MAC_FILTER_CONFIG, regval);
+}
+
+static void xlr_stats(struct net_device *ndev, struct rtnl_link_stats64 *stats)
+{
+	struct xlr_net_priv *priv = netdev_priv(ndev);
+
+	stats->rx_packets = xlr_nae_rdreg(priv->base_addr, RX_PACKET_COUNTER);
+	stats->tx_packets = xlr_nae_rdreg(priv->base_addr, TX_PACKET_COUNTER);
+	stats->rx_bytes = xlr_nae_rdreg(priv->base_addr, RX_BYTE_COUNTER);
+	stats->tx_bytes = xlr_nae_rdreg(priv->base_addr, TX_BYTE_COUNTER);
+	stats->tx_errors = xlr_nae_rdreg(priv->base_addr, TX_FCS_ERROR_COUNTER);
+	stats->rx_dropped = xlr_nae_rdreg(priv->base_addr,
+			RX_DROP_PACKET_COUNTER);
+	stats->tx_dropped = xlr_nae_rdreg(priv->base_addr,
+			TX_DROP_FRAME_COUNTER);
+
+	stats->multicast = xlr_nae_rdreg(priv->base_addr,
+			RX_MULTICAST_PACKET_COUNTER);
+	stats->collisions = xlr_nae_rdreg(priv->base_addr,
+			TX_TOTAL_COLLISION_COUNTER);
+
+	stats->rx_length_errors = xlr_nae_rdreg(priv->base_addr,
+			RX_FRAME_LENGTH_ERROR_COUNTER);
+	stats->rx_over_errors = xlr_nae_rdreg(priv->base_addr,
+			RX_DROP_PACKET_COUNTER);
+	stats->rx_crc_errors = xlr_nae_rdreg(priv->base_addr,
+			RX_FCS_ERROR_COUNTER);
+	stats->rx_frame_errors = xlr_nae_rdreg(priv->base_addr,
+			RX_ALIGNMENT_ERROR_COUNTER);
+
+	stats->rx_fifo_errors = xlr_nae_rdreg(priv->base_addr,
+			RX_DROP_PACKET_COUNTER);
+	stats->rx_missed_errors = xlr_nae_rdreg(priv->base_addr,
+			RX_CARRIER_SENSE_ERROR_COUNTER);
+
+	stats->rx_errors = (stats->rx_over_errors + stats->rx_crc_errors +
+			stats->rx_frame_errors + stats->rx_fifo_errors +
+			stats->rx_missed_errors);
+
+	stats->tx_aborted_errors = xlr_nae_rdreg(priv->base_addr,
+			TX_EXCESSIVE_COLLISION_PACKET_COUNTER);
+	stats->tx_carrier_errors = xlr_nae_rdreg(priv->base_addr,
+			TX_DROP_FRAME_COUNTER);
+	stats->tx_fifo_errors = xlr_nae_rdreg(priv->base_addr,
+			TX_DROP_FRAME_COUNTER);
+}
+
+static struct rtnl_link_stats64 *xlr_get_stats64(struct net_device *ndev,
+		struct rtnl_link_stats64 *stats)
+{
+	xlr_stats(ndev, stats);
+	return stats;
+}
+
+static struct net_device_ops xlr_netdev_ops = {
+	.ndo_open = xlr_net_open,
+	.ndo_stop = xlr_net_stop,
+	.ndo_start_xmit = xlr_net_start_xmit,
+	.ndo_select_queue = xlr_net_select_queue,
+	.ndo_set_mac_address = xlr_net_set_mac_addr,
+	.ndo_set_rx_mode = xlr_set_rx_mode,
+	.ndo_get_stats64 = xlr_get_stats64,
+};
+
+/* Gmac init */
+static void *xlr_config_spill(struct xlr_net_priv *priv, int reg_start_0,
+		int reg_start_1, int reg_size, int size)
+{
+	void *spill;
+	u32 *base;
+	unsigned long phys_addr;
+	u32 spill_size;
+
+	base = priv->base_addr;
+	spill_size = size;
+	spill = kmalloc(spill_size + SMP_CACHE_BYTES, GFP_ATOMIC);
+	if (!spill)
+		pr_err("Unable to allocate memory for spill area!\n");
+
+	spill = PTR_ALIGN(spill, SMP_CACHE_BYTES);
+	phys_addr = virt_to_phys(spill);
+	dev_dbg(&priv->ndev->dev, "Allocated spill %d bytes at %lx\n",
+			size, phys_addr);
+	xlr_nae_wreg(base, reg_start_0, (phys_addr >> 5) & 0xffffffff);
+	xlr_nae_wreg(base, reg_start_1, ((u64)phys_addr >> 37) & 0x07);
+	xlr_nae_wreg(base, reg_size, spill_size);
+
+	return spill;
+}
+
+/*
+ * Configure the 6 FIFO's that are used by the network accelarator to
+ * communicate with the rest of the XLx device. 4 of the FIFO's are for
+ * packets from NA --> cpu (called Class FIFO's) and 2 are for feeding
+ * the NA with free descriptors.
+ */
+static void xlr_config_fifo_spill_area(struct xlr_net_priv *priv)
+{
+	priv->frin_spill = xlr_config_spill(priv,
+			R_REG_FRIN_SPILL_MEM_START_0,
+			R_REG_FRIN_SPILL_MEM_START_1,
+			R_REG_FRIN_SPILL_MEM_SIZE,
+			MAX_FRIN_SPILL *
+			sizeof(u64));
+	priv->frout_spill = xlr_config_spill(priv,
+			R_FROUT_SPILL_MEM_START_0,
+			R_FROUT_SPILL_MEM_START_1,
+			R_FROUT_SPILL_MEM_SIZE,
+			MAX_FROUT_SPILL *
+			sizeof(u64));
+	priv->class_0_spill = xlr_config_spill(priv,
+			R_CLASS0_SPILL_MEM_START_0,
+			R_CLASS0_SPILL_MEM_START_1,
+			R_CLASS0_SPILL_MEM_SIZE,
+			MAX_CLASS_0_SPILL *
+			sizeof(u64));
+	priv->class_1_spill = xlr_config_spill(priv,
+			R_CLASS1_SPILL_MEM_START_0,
+			R_CLASS1_SPILL_MEM_START_1,
+			R_CLASS1_SPILL_MEM_SIZE,
+			MAX_CLASS_1_SPILL *
+			sizeof(u64));
+	priv->class_2_spill = xlr_config_spill(priv,
+			R_CLASS2_SPILL_MEM_START_0,
+			R_CLASS2_SPILL_MEM_START_1,
+			R_CLASS2_SPILL_MEM_SIZE,
+			MAX_CLASS_2_SPILL *
+			sizeof(u64));
+	priv->class_3_spill = xlr_config_spill(priv,
+			R_CLASS3_SPILL_MEM_START_0,
+			R_CLASS3_SPILL_MEM_START_1,
+			R_CLASS3_SPILL_MEM_SIZE,
+			MAX_CLASS_3_SPILL *
+			sizeof(u64));
+}
+
+/* Configure PDE to Round-Robin distribution of packets to the
+ * available cpu */
+static void xlr_config_pde(struct xlr_net_priv *priv)
+{
+	int i = 0;
+	u64 bkt_map = 0;
+
+	/* Each core has 8 buckets(station) */
+	for (i = 0; i < hweight32(priv->nd->cpu_mask); i++)
+		bkt_map |= (0xff << (i * 8));
+
+	xlr_nae_wreg(priv->base_addr, R_PDE_CLASS_0, (bkt_map & 0xffffffff));
+	xlr_nae_wreg(priv->base_addr, R_PDE_CLASS_0 + 1,
+			((bkt_map >> 32) & 0xffffffff));
+
+	xlr_nae_wreg(priv->base_addr, R_PDE_CLASS_1, (bkt_map & 0xffffffff));
+	xlr_nae_wreg(priv->base_addr, R_PDE_CLASS_1 + 1,
+			((bkt_map >> 32) & 0xffffffff));
+
+	xlr_nae_wreg(priv->base_addr, R_PDE_CLASS_2, (bkt_map & 0xffffffff));
+	xlr_nae_wreg(priv->base_addr, R_PDE_CLASS_2 + 1,
+			((bkt_map >> 32) & 0xffffffff));
+
+	xlr_nae_wreg(priv->base_addr, R_PDE_CLASS_3, (bkt_map & 0xffffffff));
+	xlr_nae_wreg(priv->base_addr, R_PDE_CLASS_3 + 1,
+			((bkt_map >> 32) & 0xffffffff));
+}
+
+/* Setup the Message ring credits, bucket size and other
+ * common configuration */
+static void xlr_config_common(struct xlr_net_priv *priv)
+{
+	struct xlr_fmn_info *gmac = priv->nd->gmac_fmn_info;
+	int start_stn_id = gmac->start_stn_id;
+	int end_stn_id = gmac->end_stn_id;
+	int *bucket_size = priv->nd->bucket_size;
+	int i, j;
+
+	/* Setting non-core MsgBktSize(0x321 - 0x325) */
+	for (i = start_stn_id; i <= end_stn_id; i++) {
+		xlr_nae_wreg(priv->base_addr,
+				R_GMAC_RFR0_BUCKET_SIZE + i - start_stn_id,
+				bucket_size[i]);
+	}
+
+	/* Setting non-core Credit counter register
+	 * Distributing Gmac's credit to CPU's*/
+	for (i = 0; i < 8; i++) {
+		for (j = 0; j < 8; j++)
+			xlr_nae_wreg(priv->base_addr,
+					(R_CC_CPU0_0 + (i * 8)) + j,
+					gmac->credit_config[(i * 8) + j]);
+	}
+
+	xlr_nae_wreg(priv->base_addr, R_MSG_TX_THRESHOLD, 3);
+	xlr_nae_wreg(priv->base_addr, R_DMACR0, 0xffffffff);
+	xlr_nae_wreg(priv->base_addr, R_DMACR1, 0xffffffff);
+	xlr_nae_wreg(priv->base_addr, R_DMACR2, 0xffffffff);
+	xlr_nae_wreg(priv->base_addr, R_DMACR3, 0xffffffff);
+	xlr_nae_wreg(priv->base_addr, R_FREEQCARVE, 0);
+
+	xlr_net_fill_rx_ring(priv->ndev);
+	nlm_register_fmn_handler(start_stn_id, end_stn_id, xlr_net_fmn_handler,
+					NULL);
+}
+
+static void xlr_config_translate_table(struct xlr_net_priv *priv)
+{
+	u32 cpu_mask;
+	u32 val;
+	int bkts[32]; /* one bucket is assumed for each cpu */
+	int b1, b2, c1, c2, i, j, k;
+	int use_bkt;
+
+	use_bkt = 0;
+	cpu_mask = priv->nd->cpu_mask;
+
+	pr_info("Using %s-based distribution\n",
+			(use_bkt) ? "bucket" : "class");
+	j = 0;
+	for (i = 0; i < 32; i++) {
+		if ((1 << i) & cpu_mask) {
+			/* for each cpu, mark the 4+threadid bucket */
+			bkts[j] = ((i / 4) * 8) + (i % 4);
+			j++;
+		}
+	}
+
+	/*configure the 128 * 9 Translation table to send to available buckets*/
+	k = 0;
+	c1 = 3;
+	c2 = 0;
+	for (i = 0; i < 64; i++) {
+		/* On use_bkt set the b0, b1 are used, else
+		 * the 4 classes are used, here implemented
+		 * a logic to distribute the packets to the
+		 * buckets equally or based on the class
+		 */
+		c1 = (c1 + 1) & 3;
+		c2 = (c1 + 1) & 3;
+		b1 = bkts[k];
+		k = (k + 1) % j;
+		b2 = bkts[k];
+		k = (k + 1) % j;
+		val = ((c1 << 23) | (b1 << 17) | (use_bkt << 16) |
+				(c2 << 7) | (b2 << 1) | (use_bkt << 0));
+
+		val = ((c1 << 23) | (b1 << 17) | (use_bkt << 16) |
+				(c2 << 7) | (b2 << 1) | (use_bkt << 0));
+		dev_dbg(&priv->ndev->dev, "Table[%d] b1=%d b2=%d c1=%d c2=%d\n",
+				i, b1, b2, c1, c2);
+		xlr_nae_wreg(priv->base_addr, R_TRANSLATETABLE + i, val);
+		c1 = c2;
+	}
+}
+
+static void xlr_config_parser(struct xlr_net_priv *priv)
+{
+	u32 val;
+
+	/* Mark it as ETHERNET type */
+	xlr_nae_wreg(priv->base_addr, R_L2TYPE_0, 0x01);
+
+	/* Use 7bit CRChash for flow classification with 127 as CRC polynomial*/
+	xlr_nae_wreg(priv->base_addr, R_PARSERCONFIGREG,
+			((0x7f << 8) | (1 << 1)));
+
+	/* configure the parser : L2 Type is configured in the bootloader */
+	/* extract IP: src, dest protocol */
+	xlr_nae_wreg(priv->base_addr, R_L3CTABLE,
+			(9 << 20) | (1 << 19) | (1 << 18) | (0x01 << 16) |
+			(0x0800 << 0));
+	xlr_nae_wreg(priv->base_addr, R_L3CTABLE + 1,
+			(9 << 25) | (1 << 21) | (12 << 14) | (4 << 10) |
+			(16 << 4) | 4);
+
+	/* Configure to extract SRC port and Dest port for TCP and UDP pkts */
+	xlr_nae_wreg(priv->base_addr, R_L4CTABLE, 6);
+	xlr_nae_wreg(priv->base_addr, R_L4CTABLE + 2, 17);
+	val = ((0 << 21) | (2 << 17) | (2 << 11) | (2 << 7));
+	xlr_nae_wreg(priv->base_addr, R_L4CTABLE + 1, val);
+	xlr_nae_wreg(priv->base_addr, R_L4CTABLE + 3, val);
+
+	xlr_config_translate_table(priv);
+}
+
+static int xlr_phy_write(u32 *base_addr, int phy_addr, int regnum, u16 val)
+{
+	unsigned long timeout, stoptime, checktime;
+	int timedout;
+
+	/* 100ms timeout*/
+	timeout = msecs_to_jiffies(100);
+	stoptime = jiffies + timeout;
+	timedout = 0;
+
+	xlr_nae_wreg(base_addr, R_MII_MGMT_ADDRESS, (phy_addr << 8) | regnum);
+
+	/* Write the data which starts the write cycle */
+	xlr_nae_wreg(base_addr, R_MII_MGMT_WRITE_DATA, (u32) val);
+
+	/* poll for the read cycle to complete */
+	while (!timedout) {
+		checktime = jiffies;
+		if (xlr_nae_rdreg(base_addr, R_MII_MGMT_INDICATORS) == 0)
+			break;
+		timedout = time_after(checktime, stoptime);
+	}
+	if (timedout) {
+		pr_info("Phy device write err: device busy");
+		return -EBUSY;
+	}
+
+	return 0;
+}
+
+static int xlr_phy_read(u32 *base_addr, int phy_addr, int regnum)
+{
+	unsigned long timeout, stoptime, checktime;
+	int timedout;
+
+	/* 100ms timeout*/
+	timeout = msecs_to_jiffies(100);
+	stoptime = jiffies + timeout;
+	timedout = 0;
+
+	/* setup the phy reg to be used */
+	xlr_nae_wreg(base_addr, R_MII_MGMT_ADDRESS,
+			(phy_addr << 8) | (regnum << 0));
+
+	/* Issue the read command */
+	xlr_nae_wreg(base_addr, R_MII_MGMT_COMMAND,
+			(1 << O_MII_MGMT_COMMAND__rstat));
+
+
+	/* poll for the read cycle to complete */
+	while (!timedout) {
+		checktime = jiffies;
+		if (xlr_nae_rdreg(base_addr, R_MII_MGMT_INDICATORS) == 0)
+			break;
+		timedout = time_after(checktime, stoptime);
+	}
+	if (timedout) {
+		pr_info("Phy device read err: device busy");
+		return -EBUSY;
+	}
+
+	/* clear the read cycle */
+	xlr_nae_wreg(base_addr, R_MII_MGMT_COMMAND, 0);
+
+	/* Read the data */
+	return xlr_nae_rdreg(base_addr, R_MII_MGMT_STATUS);
+}
+
+static int xlr_mii_write(struct mii_bus *bus, int phy_addr, int regnum, u16 val)
+{
+	struct xlr_net_priv *priv = bus->priv;
+	int ret;
+
+	ret = xlr_phy_write(priv->mii_addr, phy_addr, regnum, val);
+	dev_dbg(&priv->ndev->dev, "mii_write phy %d : %d <- %x [%x]\n",
+			phy_addr, regnum, val, ret);
+	return ret;
+}
+
+static int xlr_mii_read(struct mii_bus *bus, int phy_addr, int regnum)
+{
+	struct xlr_net_priv *priv = bus->priv;
+	int ret;
+
+	ret =  xlr_phy_read(priv->mii_addr, phy_addr, regnum);
+	dev_dbg(&priv->ndev->dev, "mii_read phy %d : %d [%x]\n",
+			phy_addr, regnum, ret);
+	return ret;
+}
+
+/* XLR ports are RGMII. XLS ports are SGMII mostly except the port0,
+ * which can be configured either SGMII or RGMII, considered SGMII
+ * by default, if board setup to RGMII the port_type need to set
+ * accordingly.Serdes and PCS layer need to configured for SGMII
+ */
+static void xlr_sgmii_init(struct xlr_net_priv *priv)
+{
+	int phy;
+
+	xlr_phy_write(priv->serdes_addr, 26, 0, 0x6DB0);
+	xlr_phy_write(priv->serdes_addr, 26, 1, 0xFFFF);
+	xlr_phy_write(priv->serdes_addr, 26, 2, 0xB6D0);
+	xlr_phy_write(priv->serdes_addr, 26, 3, 0x00FF);
+	xlr_phy_write(priv->serdes_addr, 26, 4, 0x0000);
+	xlr_phy_write(priv->serdes_addr, 26, 5, 0x0000);
+	xlr_phy_write(priv->serdes_addr, 26, 6, 0x0005);
+	xlr_phy_write(priv->serdes_addr, 26, 7, 0x0001);
+	xlr_phy_write(priv->serdes_addr, 26, 8, 0x0000);
+	xlr_phy_write(priv->serdes_addr, 26, 9, 0x0000);
+	xlr_phy_write(priv->serdes_addr, 26, 10, 0x0000);
+
+	/* program  GPIO values for serdes init parameters */
+	xlr_nae_wreg(priv->gpio_addr, 0x20, 0x7e6802);
+	xlr_nae_wreg(priv->gpio_addr, 0x10, 0x7104);
+
+	xlr_nae_wreg(priv->gpio_addr, 0x22, 0x7e6802);
+	xlr_nae_wreg(priv->gpio_addr, 0x21, 0x7104);
+
+	/* enable autoneg - more magic */
+	phy = priv->port_id % 4 + 27;
+	xlr_phy_write(priv->pcs_addr, phy, 0, 0x1000);
+	xlr_phy_write(priv->pcs_addr, phy, 0, 0x0200);
+}
+
+void xlr_set_gmac_speed(struct xlr_net_priv *priv)
+{
+	struct phy_device *phydev = priv->mii_bus->phy_map[priv->phy_addr];
+	int speed;
+
+	if (phydev->interface == PHY_INTERFACE_MODE_SGMII)
+		xlr_sgmii_init(priv);
+
+	if (phydev->speed != priv->phy_speed) {
+		pr_info("change %d to %d\n", priv->phy_speed, phydev->speed);
+		speed = phydev->speed;
+		if (speed == SPEED_1000) {
+			/* Set interface to Byte mode */
+			xlr_nae_wreg(priv->base_addr, R_MAC_CONFIG_2, 0x7217);
+			priv->phy_speed = speed;
+		} else if (speed == SPEED_100 || speed == SPEED_10) {
+			/* Set interface to Nibble mode */
+			xlr_nae_wreg(priv->base_addr, R_MAC_CONFIG_2, 0x7117);
+			priv->phy_speed = speed;
+		}
+		/* Set SGMII speed in Interface controll reg */
+		if (phydev->interface == PHY_INTERFACE_MODE_SGMII) {
+			if (speed == SPEED_10)
+				xlr_nae_wreg(priv->base_addr,
+					R_INTERFACE_CONTROL, SGMII_SPEED_10);
+			if (speed == SPEED_100)
+				xlr_nae_wreg(priv->base_addr,
+					R_INTERFACE_CONTROL, SGMII_SPEED_100);
+			if (speed == SPEED_1000)
+				xlr_nae_wreg(priv->base_addr,
+					R_INTERFACE_CONTROL, SGMII_SPEED_1000);
+		}
+		if (speed == SPEED_10)
+			xlr_nae_wreg(priv->base_addr, R_CORECONTROL, 0x2);
+		if (speed == SPEED_100)
+			xlr_nae_wreg(priv->base_addr, R_CORECONTROL, 0x1);
+		if (speed == SPEED_1000)
+			xlr_nae_wreg(priv->base_addr, R_CORECONTROL, 0x0);
+	}
+	pr_info("gmac%d : %dMbps\n", priv->port_id, priv->phy_speed);
+}
+
+static void xlr_gmac_link_adjust(struct net_device *ndev)
+{
+	struct xlr_net_priv *priv = netdev_priv(ndev);
+	struct phy_device *phydev = priv->mii_bus->phy_map[priv->phy_addr];
+	u32 intreg;
+
+	intreg = xlr_nae_rdreg(priv->base_addr, R_INTREG);
+	if (phydev->link) {
+		if (phydev->speed != priv->phy_speed) {
+			pr_info("gmac%d : Link up\n", priv->port_id);
+			xlr_set_gmac_speed(priv);
+		}
+	} else {
+		pr_info("gmac%d : Link down\n", priv->port_id);
+		xlr_set_gmac_speed(priv);
+	}
+}
+
+static int xlr_mii_probe(struct xlr_net_priv *priv)
+{
+	struct phy_device *phydev = priv->mii_bus->phy_map[priv->phy_addr];
+
+	if (!phydev) {
+		pr_err("no PHY found on phy_addr %d\n", priv->phy_addr);
+		return -ENODEV;
+	}
+
+	/* Attach MAC to PHY */
+	phydev = phy_connect(priv->ndev, dev_name(&phydev->dev),
+			&xlr_gmac_link_adjust, priv->nd->phy_interface);
+
+	if (IS_ERR(phydev)) {
+		pr_err("could not attach PHY\n");
+		return PTR_ERR(phydev);
+	}
+	phydev->supported &= (ADVERTISED_10baseT_Full
+				| ADVERTISED_10baseT_Half
+				| ADVERTISED_100baseT_Full
+				| ADVERTISED_100baseT_Half
+				| ADVERTISED_1000baseT_Full
+				| ADVERTISED_Autoneg
+				| ADVERTISED_MII);
+
+	phydev->advertising = phydev->supported;
+	pr_info("attached PHY driver [%s] (mii_bus:phy_addr=%s\n",
+		phydev->drv->name, dev_name(&phydev->dev));
+	return 0;
+}
+
+static int xlr_setup_mdio(struct xlr_net_priv *priv,
+		struct platform_device *pdev)
+{
+	int err;
+
+	priv->phy_addr = priv->nd->phy_addr;
+	priv->mii_bus = mdiobus_alloc();
+	if (!priv->mii_bus) {
+		pr_err("mdiobus alloc failed\n");
+		return -ENOMEM;
+	}
+
+	priv->mii_bus->priv = priv;
+	priv->mii_bus->name = "xlr-mdio";
+	snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "%s-%d",
+			priv->mii_bus->name, priv->port_id);
+	priv->mii_bus->read = xlr_mii_read;
+	priv->mii_bus->write = xlr_mii_write;
+	priv->mii_bus->parent = &pdev->dev;
+	priv->mii_bus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
+	priv->mii_bus->irq[priv->phy_addr] = priv->ndev->irq;
+
+	/* Scan only the enabled address */
+	priv->mii_bus->phy_mask = ~(1 << priv->phy_addr);
+
+	/* setting clock divisor to 54 */
+	xlr_nae_wreg(priv->base_addr, R_MII_MGMT_CONFIG, 0x7);
+
+	err = mdiobus_register(priv->mii_bus);
+	if (err) {
+		mdiobus_free(priv->mii_bus);
+		pr_err("mdio bus registration failed\n");
+		return err;
+	}
+
+	pr_info("Registerd mdio bus id : %s\n", priv->mii_bus->id);
+	err = xlr_mii_probe(priv);
+	if (err) {
+		mdiobus_free(priv->mii_bus);
+		return err;
+	}
+	return 0;
+}
+
+static void xlr_port_enable(struct xlr_net_priv *priv)
+{
+	u32 prid = (read_c0_prid() & 0xf000);
+
+	/* Setup MAC_CONFIG reg if (xls & rgmii) */
+	if ((prid == 0x8000 || prid == 0x4000 || prid == 0xc000) &&
+			priv->nd->phy_interface == PHY_INTERFACE_MODE_RGMII)
+		xlr_reg_update(priv->base_addr, R_RX_CONTROL,
+			(1 << O_RX_CONTROL__RGMII), (1 << O_RX_CONTROL__RGMII));
+
+	/* Rx Tx enable */
+	xlr_reg_update(priv->base_addr, R_MAC_CONFIG_1,
+		((1 << O_MAC_CONFIG_1__rxen) | (1 << O_MAC_CONFIG_1__txen) |
+		(1 << O_MAC_CONFIG_1__rxfc) | (1 << O_MAC_CONFIG_1__txfc)),
+		((1 << O_MAC_CONFIG_1__rxen) | (1 << O_MAC_CONFIG_1__txen) |
+		(1 << O_MAC_CONFIG_1__rxfc) | (1 << O_MAC_CONFIG_1__txfc)));
+
+	/* Setup tx control reg */
+	xlr_reg_update(priv->base_addr, R_TX_CONTROL,
+		((1 << O_TX_CONTROL__TxEnable) |
+		(512 << O_TX_CONTROL__TxThreshold)), 0x3fff);
+
+	/* Setup rx control reg */
+	xlr_reg_update(priv->base_addr, R_RX_CONTROL,
+		1 << O_RX_CONTROL__RxEnable, 1 << O_RX_CONTROL__RxEnable);
+}
+
+static void xlr_port_disable(struct xlr_net_priv *priv)
+{
+	/* Setup MAC_CONFIG reg */
+	/* Rx Tx disable*/
+	xlr_reg_update(priv->base_addr, R_MAC_CONFIG_1,
+		((1 << O_MAC_CONFIG_1__rxen) | (1 << O_MAC_CONFIG_1__txen) |
+		(1 << O_MAC_CONFIG_1__rxfc) | (1 << O_MAC_CONFIG_1__txfc)),
+		0x0);
+
+	/* Setup tx control reg */
+	xlr_reg_update(priv->base_addr, R_TX_CONTROL,
+		((1 << O_TX_CONTROL__TxEnable) |
+		(512 << O_TX_CONTROL__TxThreshold)), 0);
+
+	/* Setup rx control reg */
+	xlr_reg_update(priv->base_addr, R_RX_CONTROL,
+		1 << O_RX_CONTROL__RxEnable, 0);
+}
+
+/* Initialization of gmac */
+static int xlr_gmac_init(struct xlr_net_priv *priv,
+		struct platform_device *pdev)
+{
+	int ret;
+
+	pr_info("Initializing the gmac%d\n", priv->port_id);
+
+	xlr_port_disable(priv);
+	xlr_nae_wreg(priv->base_addr, R_DESC_PACK_CTRL,
+			(1 << O_DESC_PACK_CTRL__MaxEntry)
+			| (BYTE_OFFSET << O_DESC_PACK_CTRL__ByteOffset)
+			| (1600 << O_DESC_PACK_CTRL__RegularSize));
+
+	ret = xlr_setup_mdio(priv, pdev);
+	if (ret)
+		return ret;
+	xlr_port_enable(priv);
+
+	/* Enable Full-duplex/1000Mbps/CRC */
+	xlr_nae_wreg(priv->base_addr, R_MAC_CONFIG_2, 0x7217);
+	/* speed 2.5Mhz */
+	xlr_nae_wreg(priv->base_addr, R_CORECONTROL, 0x02);
+	/* Setup Interrupt mask reg */
+	xlr_nae_wreg(priv->base_addr, R_INTMASK,
+		(1 << O_INTMASK__TxIllegal)	|
+		(1 << O_INTMASK__MDInt)		|
+		(1 << O_INTMASK__TxFetchError)	|
+		(1 << O_INTMASK__P2PSpillEcc)	|
+		(1 << O_INTMASK__TagFull)	|
+		(1 << O_INTMASK__Underrun)	|
+		(1 << O_INTMASK__Abort)
+		);
+
+	/* Clear all stats */
+	xlr_reg_update(priv->base_addr, R_STATCTRL,
+		0, 1 << O_STATCTRL__ClrCnt);
+	xlr_reg_update(priv->base_addr, R_STATCTRL,
+		1 << O_STATCTRL__ClrCnt, 1 << O_STATCTRL__ClrCnt);
+	return 0;
+}
+
+static int xlr_net_probe(struct platform_device *pdev)
+{
+	struct xlr_net_priv *priv = NULL;
+	struct net_device *ndev;
+	struct resource *res;
+	int mac, err;
+
+	mac = pdev->id;
+	ndev = alloc_etherdev_mq(sizeof(struct xlr_net_priv), 32);
+	if (!ndev) {
+		pr_err("Allocation of Ethernet device failed\n");
+		return -ENOMEM;
+	}
+
+	priv = netdev_priv(ndev);
+	priv->pdev = pdev;
+	priv->ndev = ndev;
+	priv->port_id = mac;
+	priv->nd = (struct xlr_net_data *)pdev->dev.platform_data;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res == NULL) {
+		pr_err("No memory resource for MAC %d\n", mac);
+		err = -ENODEV;
+		goto err_gmac;
+	}
+
+	ndev->base_addr = (unsigned long) devm_request_and_ioremap
+		(&pdev->dev, res);
+	if (!ndev->base_addr) {
+		dev_err(&pdev->dev,
+				"devm_request_and_ioremap failed\n");
+		return -EBUSY;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (res == NULL) {
+		pr_err("No irq resource for MAC %d\n", mac);
+		err = -ENODEV;
+		goto err_gmac;
+	}
+	ndev->irq = res->start;
+
+	priv->mii_addr = priv->nd->mii_addr;
+	priv->serdes_addr = priv->nd->serdes_addr;
+	priv->pcs_addr = priv->nd->pcs_addr;
+	priv->gpio_addr = priv->nd->gpio_addr;
+	priv->base_addr = (u32 *) ndev->base_addr;
+
+	mac_to_ndev[mac] = ndev;
+	ndev->netdev_ops = &xlr_netdev_ops;
+	ndev->watchdog_timeo = HZ;
+
+	/* Setup Mac address and Rx mode */
+	eth_hw_addr_random(ndev);
+	xlr_hw_set_mac_addr(ndev);
+	xlr_set_rx_mode(ndev);
+
+	priv->num_rx_desc += MAX_NUM_DESC_SPILL;
+	SET_ETHTOOL_OPS(ndev, &xlr_ethtool_ops);
+	SET_NETDEV_DEV(ndev, &pdev->dev);
+
+	/* Common registers, do one time initialization */
+	if (mac == 0 || mac == 4) {
+		xlr_config_fifo_spill_area(priv);
+		/* Configure PDE to Round-Robin pkt distribution */
+		xlr_config_pde(priv);
+		xlr_config_parser(priv);
+	}
+	/* Call init with respect to port */
+	if (strcmp(res->name, "gmac") == 0) {
+		err = xlr_gmac_init(priv, pdev);
+		if (err) {
+			pr_err("gmac%d init failed\n", mac);
+			goto err_gmac;
+		}
+	}
+
+	if (mac == 0 || mac == 4)
+		xlr_config_common(priv);
+
+	err = register_netdev(ndev);
+	if (err)
+		goto err_netdev;
+	platform_set_drvdata(pdev, priv);
+	return 0;
+
+err_netdev:
+	mdiobus_free(priv->mii_bus);
+err_gmac:
+	free_netdev(ndev);
+	return err;
+}
+
+static int xlr_net_remove(struct platform_device *pdev)
+{
+	struct xlr_net_priv *priv = platform_get_drvdata(pdev);
+	unregister_netdev(priv->ndev);
+	mdiobus_unregister(priv->mii_bus);
+	mdiobus_free(priv->mii_bus);
+	free_netdev(priv->ndev);
+	return 0;
+}
+
+static struct platform_driver xlr_net_driver = {
+	.probe		= xlr_net_probe,
+	.remove		= xlr_net_remove,
+	.driver		= {
+		.name	= "xlr-net",
+		.owner	= THIS_MODULE,
+	},
+};
+
+module_platform_driver(xlr_net_driver);
+
+MODULE_AUTHOR("Ganesan Ramalingam <ganesanr@broadcom.com>");
+MODULE_DESCRIPTION("Ethernet driver for Netlogic XLR/XLS");
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_ALIAS("platform:xlr-net");
diff --git a/drivers/staging/netlogic/xlr_net.h b/drivers/staging/netlogic/xlr_net.h
new file mode 100644
index 0000000..f91d27e
--- /dev/null
+++ b/drivers/staging/netlogic/xlr_net.h
@@ -0,0 +1,1099 @@
+/*
+ * Copyright (c) 2003-2012 Broadcom Corporation
+ * 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 Broadcom
+ * license below:
+ *
+ * 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, this list of conditions and the following disclaimer.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BROADCOM ``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 BROADCOM 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.
+ */
+/* #define MAC_SPLIT_MODE */
+
+#define MAC_SPACING                 0x400
+#define XGMAC_SPACING               0x400
+
+/* PE-MCXMAC register and bit field definitions */
+#define R_MAC_CONFIG_1                                              0x00
+#define   O_MAC_CONFIG_1__srst                                      31
+#define   O_MAC_CONFIG_1__simr                                      30
+#define   O_MAC_CONFIG_1__hrrmc                                     18
+#define   W_MAC_CONFIG_1__hrtmc                                      2
+#define   O_MAC_CONFIG_1__hrrfn                                     16
+#define   W_MAC_CONFIG_1__hrtfn                                      2
+#define   O_MAC_CONFIG_1__intlb                                      8
+#define   O_MAC_CONFIG_1__rxfc                                       5
+#define   O_MAC_CONFIG_1__txfc                                       4
+#define   O_MAC_CONFIG_1__srxen                                      3
+#define   O_MAC_CONFIG_1__rxen                                       2
+#define   O_MAC_CONFIG_1__stxen                                      1
+#define   O_MAC_CONFIG_1__txen                                       0
+#define R_MAC_CONFIG_2                                              0x01
+#define   O_MAC_CONFIG_2__prlen                                     12
+#define   W_MAC_CONFIG_2__prlen                                      4
+#define   O_MAC_CONFIG_2__speed                                      8
+#define   W_MAC_CONFIG_2__speed                                      2
+#define   O_MAC_CONFIG_2__hugen                                      5
+#define   O_MAC_CONFIG_2__flchk                                      4
+#define   O_MAC_CONFIG_2__crce                                       1
+#define   O_MAC_CONFIG_2__fulld                                      0
+#define R_IPG_IFG                                                   0x02
+#define   O_IPG_IFG__ipgr1                                          24
+#define   W_IPG_IFG__ipgr1                                           7
+#define   O_IPG_IFG__ipgr2                                          16
+#define   W_IPG_IFG__ipgr2                                           7
+#define   O_IPG_IFG__mifg                                            8
+#define   W_IPG_IFG__mifg                                            8
+#define   O_IPG_IFG__ipgt                                            0
+#define   W_IPG_IFG__ipgt                                            7
+#define R_HALF_DUPLEX                                               0x03
+#define   O_HALF_DUPLEX__abebt                                      24
+#define   W_HALF_DUPLEX__abebt                                       4
+#define   O_HALF_DUPLEX__abebe                                      19
+#define   O_HALF_DUPLEX__bpnb                                       18
+#define   O_HALF_DUPLEX__nobo                                       17
+#define   O_HALF_DUPLEX__edxsdfr                                    16
+#define   O_HALF_DUPLEX__retry                                      12
+#define   W_HALF_DUPLEX__retry                                       4
+#define   O_HALF_DUPLEX__lcol                                        0
+#define   W_HALF_DUPLEX__lcol                                       10
+#define R_MAXIMUM_FRAME_LENGTH                                      0x04
+#define   O_MAXIMUM_FRAME_LENGTH__maxf                               0
+#define   W_MAXIMUM_FRAME_LENGTH__maxf                              16
+#define R_TEST                                                      0x07
+#define   O_TEST__mbof                                               3
+#define   O_TEST__rthdf                                              2
+#define   O_TEST__tpause                                             1
+#define   O_TEST__sstct                                              0
+#define R_MII_MGMT_CONFIG                                           0x08
+#define   O_MII_MGMT_CONFIG__scinc                                   5
+#define   O_MII_MGMT_CONFIG__spre                                    4
+#define   O_MII_MGMT_CONFIG__clks                                    3
+#define   W_MII_MGMT_CONFIG__clks                                    3
+#define R_MII_MGMT_COMMAND                                          0x09
+#define   O_MII_MGMT_COMMAND__scan                                   1
+#define   O_MII_MGMT_COMMAND__rstat                                  0
+#define R_MII_MGMT_ADDRESS                                          0x0A
+#define   O_MII_MGMT_ADDRESS__fiad                                   8
+#define   W_MII_MGMT_ADDRESS__fiad                                   5
+#define   O_MII_MGMT_ADDRESS__fgad                                   5
+#define   W_MII_MGMT_ADDRESS__fgad                                   0
+#define R_MII_MGMT_WRITE_DATA                                       0x0B
+#define   O_MII_MGMT_WRITE_DATA__ctld                                0
+#define   W_MII_MGMT_WRITE_DATA__ctld                               16
+#define R_MII_MGMT_STATUS                                           0x0C
+#define R_MII_MGMT_INDICATORS                                       0x0D
+#define   O_MII_MGMT_INDICATORS__nvalid                              2
+#define   O_MII_MGMT_INDICATORS__scan                                1
+#define   O_MII_MGMT_INDICATORS__busy                                0
+#define R_INTERFACE_CONTROL                                         0x0E
+#define   O_INTERFACE_CONTROL__hrstint                              31
+#define   O_INTERFACE_CONTROL__tbimode                              27
+#define   O_INTERFACE_CONTROL__ghdmode                              26
+#define   O_INTERFACE_CONTROL__lhdmode                              25
+#define   O_INTERFACE_CONTROL__phymod                               24
+#define   O_INTERFACE_CONTROL__hrrmi                                23
+#define   O_INTERFACE_CONTROL__rspd                                 16
+#define   O_INTERFACE_CONTROL__hr100                                15
+#define   O_INTERFACE_CONTROL__frcq                                 10
+#define   O_INTERFACE_CONTROL__nocfr                                 9
+#define   O_INTERFACE_CONTROL__dlfct                                 8
+#define   O_INTERFACE_CONTROL__enjab                                 0
+#define R_INTERFACE_STATUS                                         0x0F
+#define   O_INTERFACE_STATUS__xsdfr                                  9
+#define   O_INTERFACE_STATUS__ssrr                                   8
+#define   W_INTERFACE_STATUS__ssrr                                   5
+#define   O_INTERFACE_STATUS__miilf                                  3
+#define   O_INTERFACE_STATUS__locar                                  2
+#define   O_INTERFACE_STATUS__sqerr                                  1
+#define   O_INTERFACE_STATUS__jabber                                 0
+#define R_STATION_ADDRESS_LS                                       0x10
+#define R_STATION_ADDRESS_MS                                       0x11
+
+/* A-XGMAC register and bit field definitions */
+#define R_XGMAC_CONFIG_0    0x00
+#define   O_XGMAC_CONFIG_0__hstmacrst               31
+#define   O_XGMAC_CONFIG_0__hstrstrctl              23
+#define   O_XGMAC_CONFIG_0__hstrstrfn               22
+#define   O_XGMAC_CONFIG_0__hstrsttctl              18
+#define   O_XGMAC_CONFIG_0__hstrsttfn               17
+#define   O_XGMAC_CONFIG_0__hstrstmiim              16
+#define   O_XGMAC_CONFIG_0__hstloopback             8
+#define R_XGMAC_CONFIG_1    0x01
+#define   O_XGMAC_CONFIG_1__hsttctlen               31
+#define   O_XGMAC_CONFIG_1__hsttfen                 30
+#define   O_XGMAC_CONFIG_1__hstrctlen               29
+#define   O_XGMAC_CONFIG_1__hstrfen                 28
+#define   O_XGMAC_CONFIG_1__tfen                    26
+#define   O_XGMAC_CONFIG_1__rfen                    24
+#define   O_XGMAC_CONFIG_1__hstrctlshrtp            12
+#define   O_XGMAC_CONFIG_1__hstdlyfcstx             10
+#define   W_XGMAC_CONFIG_1__hstdlyfcstx              2
+#define   O_XGMAC_CONFIG_1__hstdlyfcsrx              8
+#define   W_XGMAC_CONFIG_1__hstdlyfcsrx              2
+#define   O_XGMAC_CONFIG_1__hstppen                  7
+#define   O_XGMAC_CONFIG_1__hstbytswp                6
+#define   O_XGMAC_CONFIG_1__hstdrplt64               5
+#define   O_XGMAC_CONFIG_1__hstprmscrx               4
+#define   O_XGMAC_CONFIG_1__hstlenchk                3
+#define   O_XGMAC_CONFIG_1__hstgenfcs                2
+#define   O_XGMAC_CONFIG_1__hstpadmode               0
+#define   W_XGMAC_CONFIG_1__hstpadmode               2
+#define R_XGMAC_CONFIG_2    0x02
+#define   O_XGMAC_CONFIG_2__hsttctlfrcp             31
+#define   O_XGMAC_CONFIG_2__hstmlnkflth             27
+#define   O_XGMAC_CONFIG_2__hstalnkflth             26
+#define   O_XGMAC_CONFIG_2__rflnkflt                24
+#define   W_XGMAC_CONFIG_2__rflnkflt                 2
+#define   O_XGMAC_CONFIG_2__hstipgextmod            16
+#define   W_XGMAC_CONFIG_2__hstipgextmod             5
+#define   O_XGMAC_CONFIG_2__hstrctlfrcp             15
+#define   O_XGMAC_CONFIG_2__hstipgexten              5
+#define   O_XGMAC_CONFIG_2__hstmipgext               0
+#define   W_XGMAC_CONFIG_2__hstmipgext               5
+#define R_XGMAC_CONFIG_3    0x03
+#define   O_XGMAC_CONFIG_3__hstfltrfrm              31
+#define   W_XGMAC_CONFIG_3__hstfltrfrm              16
+#define   O_XGMAC_CONFIG_3__hstfltrfrmdc            15
+#define   W_XGMAC_CONFIG_3__hstfltrfrmdc            16
+#define R_XGMAC_STATION_ADDRESS_LS      0x04
+#define   O_XGMAC_STATION_ADDRESS_LS__hstmacadr0    0
+#define   W_XGMAC_STATION_ADDRESS_LS__hstmacadr0    32
+#define R_XGMAC_STATION_ADDRESS_MS      0x05
+#define R_XGMAC_MAX_FRAME_LEN           0x08
+#define   O_XGMAC_MAX_FRAME_LEN__hstmxfrmwctx       16
+#define   W_XGMAC_MAX_FRAME_LEN__hstmxfrmwctx       14
+#define   O_XGMAC_MAX_FRAME_LEN__hstmxfrmbcrx        0
+#define   W_XGMAC_MAX_FRAME_LEN__hstmxfrmbcrx       16
+#define R_XGMAC_REV_LEVEL               0x0B
+#define   O_XGMAC_REV_LEVEL__revlvl                  0
+#define   W_XGMAC_REV_LEVEL__revlvl                 15
+#define R_XGMAC_MIIM_COMMAND            0x10
+#define   O_XGMAC_MIIM_COMMAND__hstldcmd             3
+#define   O_XGMAC_MIIM_COMMAND__hstmiimcmd           0
+#define   W_XGMAC_MIIM_COMMAND__hstmiimcmd           3
+#define R_XGMAC_MIIM_FILED              0x11
+#define   O_XGMAC_MIIM_FILED__hststfield            30
+#define   W_XGMAC_MIIM_FILED__hststfield             2
+#define   O_XGMAC_MIIM_FILED__hstopfield            28
+#define   W_XGMAC_MIIM_FILED__hstopfield             2
+#define   O_XGMAC_MIIM_FILED__hstphyadx             23
+#define   W_XGMAC_MIIM_FILED__hstphyadx              5
+#define   O_XGMAC_MIIM_FILED__hstregadx             18
+#define   W_XGMAC_MIIM_FILED__hstregadx              5
+#define   O_XGMAC_MIIM_FILED__hsttafield            16
+#define   W_XGMAC_MIIM_FILED__hsttafield             2
+#define   O_XGMAC_MIIM_FILED__miimrddat              0
+#define   W_XGMAC_MIIM_FILED__miimrddat             16
+#define R_XGMAC_MIIM_CONFIG             0x12
+#define   O_XGMAC_MIIM_CONFIG__hstnopram             7
+#define   O_XGMAC_MIIM_CONFIG__hstclkdiv             0
+#define   W_XGMAC_MIIM_CONFIG__hstclkdiv             7
+#define R_XGMAC_MIIM_LINK_FAIL_VECTOR   0x13
+#define   O_XGMAC_MIIM_LINK_FAIL_VECTOR__miimlfvec   0
+#define   W_XGMAC_MIIM_LINK_FAIL_VECTOR__miimlfvec  32
+#define R_XGMAC_MIIM_INDICATOR          0x14
+#define   O_XGMAC_MIIM_INDICATOR__miimphylf          4
+#define   O_XGMAC_MIIM_INDICATOR__miimmoncplt        3
+#define   O_XGMAC_MIIM_INDICATOR__miimmonvld         2
+#define   O_XGMAC_MIIM_INDICATOR__miimmon            1
+#define   O_XGMAC_MIIM_INDICATOR__miimbusy           0
+
+/* GMAC stats registers */
+#define R_RBYT							    0x27
+#define R_RPKT							    0x28
+#define R_RFCS							    0x29
+#define R_RMCA							    0x2A
+#define R_RBCA							    0x2B
+#define R_RXCF							    0x2C
+#define R_RXPF							    0x2D
+#define R_RXUO							    0x2E
+#define R_RALN							    0x2F
+#define R_RFLR							    0x30
+#define R_RCDE							    0x31
+#define R_RCSE							    0x32
+#define R_RUND							    0x33
+#define R_ROVR							    0x34
+#define R_TBYT							    0x38
+#define R_TPKT							    0x39
+#define R_TMCA							    0x3A
+#define R_TBCA							    0x3B
+#define R_TXPF							    0x3C
+#define R_TDFR							    0x3D
+#define R_TEDF							    0x3E
+#define R_TSCL							    0x3F
+#define R_TMCL							    0x40
+#define R_TLCL							    0x41
+#define R_TXCL							    0x42
+#define R_TNCL							    0x43
+#define R_TJBR							    0x46
+#define R_TFCS							    0x47
+#define R_TXCF							    0x48
+#define R_TOVR							    0x49
+#define R_TUND							    0x4A
+#define R_TFRG							    0x4B
+
+/* Glue logic register and bit field definitions */
+#define R_MAC_ADDR0                                                 0x50
+#define R_MAC_ADDR1                                                 0x52
+#define R_MAC_ADDR2                                                 0x54
+#define R_MAC_ADDR3                                                 0x56
+#define R_MAC_ADDR_MASK2                                            0x58
+#define R_MAC_ADDR_MASK3                                            0x5A
+#define R_MAC_FILTER_CONFIG                                         0x5C
+#define   O_MAC_FILTER_CONFIG__BROADCAST_EN                         10
+#define   O_MAC_FILTER_CONFIG__PAUSE_FRAME_EN                       9
+#define   O_MAC_FILTER_CONFIG__ALL_MCAST_EN                         8
+#define   O_MAC_FILTER_CONFIG__ALL_UCAST_EN                         7
+#define   O_MAC_FILTER_CONFIG__HASH_MCAST_EN                        6
+#define   O_MAC_FILTER_CONFIG__HASH_UCAST_EN                        5
+#define   O_MAC_FILTER_CONFIG__ADDR_MATCH_DISC                      4
+#define   O_MAC_FILTER_CONFIG__MAC_ADDR3_VALID                      3
+#define   O_MAC_FILTER_CONFIG__MAC_ADDR2_VALID                      2
+#define   O_MAC_FILTER_CONFIG__MAC_ADDR1_VALID                      1
+#define   O_MAC_FILTER_CONFIG__MAC_ADDR0_VALID                      0
+#define R_HASH_TABLE_VECTOR                                         0x30
+#define R_TX_CONTROL                                                 0x0A0
+#define   O_TX_CONTROL__Tx15Halt                                     31
+#define   O_TX_CONTROL__Tx14Halt                                     30
+#define   O_TX_CONTROL__Tx13Halt                                     29
+#define   O_TX_CONTROL__Tx12Halt                                     28
+#define   O_TX_CONTROL__Tx11Halt                                     27
+#define   O_TX_CONTROL__Tx10Halt                                     26
+#define   O_TX_CONTROL__Tx9Halt                                      25
+#define   O_TX_CONTROL__Tx8Halt                                      24
+#define   O_TX_CONTROL__Tx7Halt                                      23
+#define   O_TX_CONTROL__Tx6Halt                                      22
+#define   O_TX_CONTROL__Tx5Halt                                      21
+#define   O_TX_CONTROL__Tx4Halt                                      20
+#define   O_TX_CONTROL__Tx3Halt                                      19
+#define   O_TX_CONTROL__Tx2Halt                                      18
+#define   O_TX_CONTROL__Tx1Halt                                      17
+#define   O_TX_CONTROL__Tx0Halt                                      16
+#define   O_TX_CONTROL__TxIdle                                       15
+#define   O_TX_CONTROL__TxEnable                                     14
+#define   O_TX_CONTROL__TxThreshold                                  0
+#define   W_TX_CONTROL__TxThreshold                                  14
+#define R_RX_CONTROL                                                 0x0A1
+#define   O_RX_CONTROL__RGMII                                        10
+#define   O_RX_CONTROL__SoftReset			             2
+#define   O_RX_CONTROL__RxHalt                                       1
+#define   O_RX_CONTROL__RxEnable                                     0
+#define R_DESC_PACK_CTRL                                            0x0A2
+#define   O_DESC_PACK_CTRL__ByteOffset                              17
+#define   W_DESC_PACK_CTRL__ByteOffset                              3
+#define   O_DESC_PACK_CTRL__PrePadEnable                            16
+#define   O_DESC_PACK_CTRL__MaxEntry                                14
+#define   W_DESC_PACK_CTRL__MaxEntry                                2
+#define   O_DESC_PACK_CTRL__RegularSize                             0
+#define   W_DESC_PACK_CTRL__RegularSize                             14
+#define R_STATCTRL                                                  0x0A3
+#define   O_STATCTRL__OverFlowEn                                    4
+#define   O_STATCTRL__GIG                                           3
+#define   O_STATCTRL__Sten                                          2
+#define   O_STATCTRL__ClrCnt                                        1
+#define   O_STATCTRL__AutoZ                                         0
+#define R_L2ALLOCCTRL                                               0x0A4
+#define   O_L2ALLOCCTRL__TxL2Allocate                               9
+#define   W_L2ALLOCCTRL__TxL2Allocate                               9
+#define   O_L2ALLOCCTRL__RxL2Allocate                               0
+#define   W_L2ALLOCCTRL__RxL2Allocate                               9
+#define R_INTMASK                                                   0x0A5
+#define   O_INTMASK__Spi4TxError                                     28
+#define   O_INTMASK__Spi4RxError                                     27
+#define   O_INTMASK__RGMIIHalfDupCollision                           27
+#define   O_INTMASK__Abort                                           26
+#define   O_INTMASK__Underrun                                        25
+#define   O_INTMASK__DiscardPacket                                   24
+#define   O_INTMASK__AsyncFifoFull                                   23
+#define   O_INTMASK__TagFull                                         22
+#define   O_INTMASK__Class3Full                                      21
+#define   O_INTMASK__C3EarlyFull                                     20
+#define   O_INTMASK__Class2Full                                      19
+#define   O_INTMASK__C2EarlyFull                                     18
+#define   O_INTMASK__Class1Full                                      17
+#define   O_INTMASK__C1EarlyFull                                     16
+#define   O_INTMASK__Class0Full                                      15
+#define   O_INTMASK__C0EarlyFull                                     14
+#define   O_INTMASK__RxDataFull                                      13
+#define   O_INTMASK__RxEarlyFull                                     12
+#define   O_INTMASK__RFreeEmpty                                      9
+#define   O_INTMASK__RFEarlyEmpty                                    8
+#define   O_INTMASK__P2PSpillEcc                                     7
+#define   O_INTMASK__FreeDescFull                                    5
+#define   O_INTMASK__FreeEarlyFull                                   4
+#define   O_INTMASK__TxFetchError                                    3
+#define   O_INTMASK__StatCarry                                       2
+#define   O_INTMASK__MDInt                                           1
+#define   O_INTMASK__TxIllegal                                       0
+#define R_INTREG                                                    0x0A6
+#define   O_INTREG__Spi4TxError                                     28
+#define   O_INTREG__Spi4RxError                                     27
+#define   O_INTREG__RGMIIHalfDupCollision                           27
+#define   O_INTREG__Abort                                           26
+#define   O_INTREG__Underrun                                        25
+#define   O_INTREG__DiscardPacket                                   24
+#define   O_INTREG__AsyncFifoFull                                   23
+#define   O_INTREG__TagFull                                         22
+#define   O_INTREG__Class3Full                                      21
+#define   O_INTREG__C3EarlyFull                                     20
+#define   O_INTREG__Class2Full                                      19
+#define   O_INTREG__C2EarlyFull                                     18
+#define   O_INTREG__Class1Full                                      17
+#define   O_INTREG__C1EarlyFull                                     16
+#define   O_INTREG__Class0Full                                      15
+#define   O_INTREG__C0EarlyFull                                     14
+#define   O_INTREG__RxDataFull                                      13
+#define   O_INTREG__RxEarlyFull                                     12
+#define   O_INTREG__RFreeEmpty                                      9
+#define   O_INTREG__RFEarlyEmpty                                    8
+#define   O_INTREG__P2PSpillEcc                                     7
+#define   O_INTREG__FreeDescFull                                    5
+#define   O_INTREG__FreeEarlyFull                                   4
+#define   O_INTREG__TxFetchError                                    3
+#define   O_INTREG__StatCarry                                       2
+#define   O_INTREG__MDInt                                           1
+#define   O_INTREG__TxIllegal                                       0
+#define R_TXRETRY                                                   0x0A7
+#define   O_TXRETRY__CollisionRetry                                 6
+#define   O_TXRETRY__BusErrorRetry                                  5
+#define   O_TXRETRY__UnderRunRetry                                  4
+#define   O_TXRETRY__Retries                                        0
+#define   W_TXRETRY__Retries                                        4
+#define R_CORECONTROL                                               0x0A8
+#define   O_CORECONTROL__ErrorThread                                4
+#define   W_CORECONTROL__ErrorThread                                7
+#define   O_CORECONTROL__Shutdown                                   2
+#define   O_CORECONTROL__Speed                                      0
+#define   W_CORECONTROL__Speed                                      2
+#define R_BYTEOFFSET0                                               0x0A9
+#define R_BYTEOFFSET1                                               0x0AA
+#define R_L2TYPE_0                                                  0x0F0
+#define   O_L2TYPE__ExtraHdrProtoSize                               26
+#define   W_L2TYPE__ExtraHdrProtoSize                               5
+#define   O_L2TYPE__ExtraHdrProtoOffset                             20
+#define   W_L2TYPE__ExtraHdrProtoOffset                             6
+#define   O_L2TYPE__ExtraHeaderSize                                 14
+#define   W_L2TYPE__ExtraHeaderSize                                 6
+#define   O_L2TYPE__ProtoOffset                                     8
+#define   W_L2TYPE__ProtoOffset                                     6
+#define   O_L2TYPE__L2HdrOffset                                     2
+#define   W_L2TYPE__L2HdrOffset                                     6
+#define   O_L2TYPE__L2Proto                                         0
+#define   W_L2TYPE__L2Proto                                         2
+#define R_L2TYPE_1                                                  0xF0
+#define R_L2TYPE_2                                                  0xF0
+#define R_L2TYPE_3                                                  0xF0
+#define R_PARSERCONFIGREG                                           0x100
+#define   O_PARSERCONFIGREG__CRCHashPoly                            8
+#define   W_PARSERCONFIGREG__CRCHashPoly                            7
+#define   O_PARSERCONFIGREG__PrePadOffset                           4
+#define   W_PARSERCONFIGREG__PrePadOffset                           4
+#define   O_PARSERCONFIGREG__UseCAM                                 2
+#define   O_PARSERCONFIGREG__UseHASH                                1
+#define   O_PARSERCONFIGREG__UseProto                               0
+#define R_L3CTABLE                                                  0x140
+#define   O_L3CTABLE__Offset0                                       25
+#define   W_L3CTABLE__Offset0                                       7
+#define   O_L3CTABLE__Len0                                          21
+#define   W_L3CTABLE__Len0                                          4
+#define   O_L3CTABLE__Offset1                                       14
+#define   W_L3CTABLE__Offset1                                       7
+#define   O_L3CTABLE__Len1                                          10
+#define   W_L3CTABLE__Len1                                          4
+#define   O_L3CTABLE__Offset2                                       4
+#define   W_L3CTABLE__Offset2                                       6
+#define   O_L3CTABLE__Len2                                          0
+#define   W_L3CTABLE__Len2                                          4
+#define   O_L3CTABLE__L3HdrOffset                                   26
+#define   W_L3CTABLE__L3HdrOffset                                   6
+#define   O_L3CTABLE__L4ProtoOffset                                 20
+#define   W_L3CTABLE__L4ProtoOffset                                 6
+#define   O_L3CTABLE__IPChksumCompute                               19
+#define   O_L3CTABLE__L4Classify                                    18
+#define   O_L3CTABLE__L2Proto                                       16
+#define   W_L3CTABLE__L2Proto                                       2
+#define   O_L3CTABLE__L3ProtoKey                                    0
+#define   W_L3CTABLE__L3ProtoKey                                    16
+#define R_L4CTABLE                                                  0x160
+#define   O_L4CTABLE__Offset0                                       21
+#define   W_L4CTABLE__Offset0                                       6
+#define   O_L4CTABLE__Len0                                          17
+#define   W_L4CTABLE__Len0                                          4
+#define   O_L4CTABLE__Offset1                                       11
+#define   W_L4CTABLE__Offset1                                       6
+#define   O_L4CTABLE__Len1                                          7
+#define   W_L4CTABLE__Len1                                          4
+#define   O_L4CTABLE__TCPChksumEnable                               0
+#define R_CAM4X128TABLE                                             0x172
+#define   O_CAM4X128TABLE__ClassId                                  7
+#define   W_CAM4X128TABLE__ClassId                                  2
+#define   O_CAM4X128TABLE__BucketId                                 1
+#define   W_CAM4X128TABLE__BucketId                                 6
+#define   O_CAM4X128TABLE__UseBucket                                0
+#define R_CAM4X128KEY                                               0x180
+#define R_TRANSLATETABLE                                            0x1A0
+#define R_DMACR0                                                    0x200
+#define   O_DMACR0__Data0WrMaxCr                                    27
+#define   W_DMACR0__Data0WrMaxCr                                    3
+#define   O_DMACR0__Data0RdMaxCr                                    24
+#define   W_DMACR0__Data0RdMaxCr                                    3
+#define   O_DMACR0__Data1WrMaxCr                                    21
+#define   W_DMACR0__Data1WrMaxCr                                    3
+#define   O_DMACR0__Data1RdMaxCr                                    18
+#define   W_DMACR0__Data1RdMaxCr                                    3
+#define   O_DMACR0__Data2WrMaxCr                                    15
+#define   W_DMACR0__Data2WrMaxCr                                    3
+#define   O_DMACR0__Data2RdMaxCr                                    12
+#define   W_DMACR0__Data2RdMaxCr                                    3
+#define   O_DMACR0__Data3WrMaxCr                                    9
+#define   W_DMACR0__Data3WrMaxCr                                    3
+#define   O_DMACR0__Data3RdMaxCr                                    6
+#define   W_DMACR0__Data3RdMaxCr                                    3
+#define   O_DMACR0__Data4WrMaxCr                                    3
+#define   W_DMACR0__Data4WrMaxCr                                    3
+#define   O_DMACR0__Data4RdMaxCr                                    0
+#define   W_DMACR0__Data4RdMaxCr                                    3
+#define R_DMACR1                                                    0x201
+#define   O_DMACR1__Data5WrMaxCr                                    27
+#define   W_DMACR1__Data5WrMaxCr                                    3
+#define   O_DMACR1__Data5RdMaxCr                                    24
+#define   W_DMACR1__Data5RdMaxCr                                    3
+#define   O_DMACR1__Data6WrMaxCr                                    21
+#define   W_DMACR1__Data6WrMaxCr                                    3
+#define   O_DMACR1__Data6RdMaxCr                                    18
+#define   W_DMACR1__Data6RdMaxCr                                    3
+#define   O_DMACR1__Data7WrMaxCr                                    15
+#define   W_DMACR1__Data7WrMaxCr                                    3
+#define   O_DMACR1__Data7RdMaxCr                                    12
+#define   W_DMACR1__Data7RdMaxCr                                    3
+#define   O_DMACR1__Data8WrMaxCr                                    9
+#define   W_DMACR1__Data8WrMaxCr                                    3
+#define   O_DMACR1__Data8RdMaxCr                                    6
+#define   W_DMACR1__Data8RdMaxCr                                    3
+#define   O_DMACR1__Data9WrMaxCr                                    3
+#define   W_DMACR1__Data9WrMaxCr                                    3
+#define   O_DMACR1__Data9RdMaxCr                                    0
+#define   W_DMACR1__Data9RdMaxCr                                    3
+#define R_DMACR2                                                    0x202
+#define   O_DMACR2__Data10WrMaxCr                                   27
+#define   W_DMACR2__Data10WrMaxCr                                   3
+#define   O_DMACR2__Data10RdMaxCr                                   24
+#define   W_DMACR2__Data10RdMaxCr                                   3
+#define   O_DMACR2__Data11WrMaxCr                                   21
+#define   W_DMACR2__Data11WrMaxCr                                   3
+#define   O_DMACR2__Data11RdMaxCr                                   18
+#define   W_DMACR2__Data11RdMaxCr                                   3
+#define   O_DMACR2__Data12WrMaxCr                                   15
+#define   W_DMACR2__Data12WrMaxCr                                   3
+#define   O_DMACR2__Data12RdMaxCr                                   12
+#define   W_DMACR2__Data12RdMaxCr                                   3
+#define   O_DMACR2__Data13WrMaxCr                                   9
+#define   W_DMACR2__Data13WrMaxCr                                   3
+#define   O_DMACR2__Data13RdMaxCr                                   6
+#define   W_DMACR2__Data13RdMaxCr                                   3
+#define   O_DMACR2__Data14WrMaxCr                                   3
+#define   W_DMACR2__Data14WrMaxCr                                   3
+#define   O_DMACR2__Data14RdMaxCr                                   0
+#define   W_DMACR2__Data14RdMaxCr                                   3
+#define R_DMACR3                                                    0x203
+#define   O_DMACR3__Data15WrMaxCr                                   27
+#define   W_DMACR3__Data15WrMaxCr                                   3
+#define   O_DMACR3__Data15RdMaxCr                                   24
+#define   W_DMACR3__Data15RdMaxCr                                   3
+#define   O_DMACR3__SpClassWrMaxCr                                  21
+#define   W_DMACR3__SpClassWrMaxCr                                  3
+#define   O_DMACR3__SpClassRdMaxCr                                  18
+#define   W_DMACR3__SpClassRdMaxCr                                  3
+#define   O_DMACR3__JumFrInWrMaxCr                                  15
+#define   W_DMACR3__JumFrInWrMaxCr                                  3
+#define   O_DMACR3__JumFrInRdMaxCr                                  12
+#define   W_DMACR3__JumFrInRdMaxCr                                  3
+#define   O_DMACR3__RegFrInWrMaxCr                                  9
+#define   W_DMACR3__RegFrInWrMaxCr                                  3
+#define   O_DMACR3__RegFrInRdMaxCr                                  6
+#define   W_DMACR3__RegFrInRdMaxCr                                  3
+#define   O_DMACR3__FrOutWrMaxCr                                    3
+#define   W_DMACR3__FrOutWrMaxCr                                    3
+#define   O_DMACR3__FrOutRdMaxCr                                    0
+#define   W_DMACR3__FrOutRdMaxCr                                    3
+#define R_REG_FRIN_SPILL_MEM_START_0                                0x204
+#define   O_REG_FRIN_SPILL_MEM_START_0__RegFrInSpillMemStart0        0
+#define   W_REG_FRIN_SPILL_MEM_START_0__RegFrInSpillMemStart0       32
+#define R_REG_FRIN_SPILL_MEM_START_1                                0x205
+#define   O_REG_FRIN_SPILL_MEM_START_1__RegFrInSpillMemStart1        0
+#define   W_REG_FRIN_SPILL_MEM_START_1__RegFrInSpillMemStart1        3
+#define R_REG_FRIN_SPILL_MEM_SIZE                                   0x206
+#define   O_REG_FRIN_SPILL_MEM_SIZE__RegFrInSpillMemSize             0
+#define   W_REG_FRIN_SPILL_MEM_SIZE__RegFrInSpillMemSize            32
+#define R_FROUT_SPILL_MEM_START_0                                   0x207
+#define   O_FROUT_SPILL_MEM_START_0__FrOutSpillMemStart0             0
+#define   W_FROUT_SPILL_MEM_START_0__FrOutSpillMemStart0            32
+#define R_FROUT_SPILL_MEM_START_1                                   0x208
+#define   O_FROUT_SPILL_MEM_START_1__FrOutSpillMemStart1             0
+#define   W_FROUT_SPILL_MEM_START_1__FrOutSpillMemStart1             3
+#define R_FROUT_SPILL_MEM_SIZE                                      0x209
+#define   O_FROUT_SPILL_MEM_SIZE__FrOutSpillMemSize                  0
+#define   W_FROUT_SPILL_MEM_SIZE__FrOutSpillMemSize                 32
+#define R_CLASS0_SPILL_MEM_START_0                                  0x20A
+#define   O_CLASS0_SPILL_MEM_START_0__Class0SpillMemStart0           0
+#define   W_CLASS0_SPILL_MEM_START_0__Class0SpillMemStart0          32
+#define R_CLASS0_SPILL_MEM_START_1                                  0x20B
+#define   O_CLASS0_SPILL_MEM_START_1__Class0SpillMemStart1           0
+#define   W_CLASS0_SPILL_MEM_START_1__Class0SpillMemStart1           3
+#define R_CLASS0_SPILL_MEM_SIZE                                     0x20C
+#define   O_CLASS0_SPILL_MEM_SIZE__Class0SpillMemSize                0
+#define   W_CLASS0_SPILL_MEM_SIZE__Class0SpillMemSize               32
+#define R_JUMFRIN_SPILL_MEM_START_0                                 0x20D
+#define   O_JUMFRIN_SPILL_MEM_START_0__JumFrInSpillMemStar0          0
+#define   W_JUMFRIN_SPILL_MEM_START_0__JumFrInSpillMemStar0         32
+#define R_JUMFRIN_SPILL_MEM_START_1                                 0x20E
+#define   O_JUMFRIN_SPILL_MEM_START_1__JumFrInSpillMemStart1         0
+#define   W_JUMFRIN_SPILL_MEM_START_1__JumFrInSpillMemStart1         3
+#define R_JUMFRIN_SPILL_MEM_SIZE                                    0x20F
+#define   O_JUMFRIN_SPILL_MEM_SIZE__JumFrInSpillMemSize              0
+#define   W_JUMFRIN_SPILL_MEM_SIZE__JumFrInSpillMemSize             32
+#define R_CLASS1_SPILL_MEM_START_0                                  0x210
+#define   O_CLASS1_SPILL_MEM_START_0__Class1SpillMemStart0           0
+#define   W_CLASS1_SPILL_MEM_START_0__Class1SpillMemStart0          32
+#define R_CLASS1_SPILL_MEM_START_1                                  0x211
+#define   O_CLASS1_SPILL_MEM_START_1__Class1SpillMemStart1           0
+#define   W_CLASS1_SPILL_MEM_START_1__Class1SpillMemStart1           3
+#define R_CLASS1_SPILL_MEM_SIZE                                     0x212
+#define   O_CLASS1_SPILL_MEM_SIZE__Class1SpillMemSize                0
+#define   W_CLASS1_SPILL_MEM_SIZE__Class1SpillMemSize               32
+#define R_CLASS2_SPILL_MEM_START_0                                  0x213
+#define   O_CLASS2_SPILL_MEM_START_0__Class2SpillMemStart0           0
+#define   W_CLASS2_SPILL_MEM_START_0__Class2SpillMemStart0          32
+#define R_CLASS2_SPILL_MEM_START_1                                  0x214
+#define   O_CLASS2_SPILL_MEM_START_1__Class2SpillMemStart1           0
+#define   W_CLASS2_SPILL_MEM_START_1__Class2SpillMemStart1           3
+#define R_CLASS2_SPILL_MEM_SIZE                                     0x215
+#define   O_CLASS2_SPILL_MEM_SIZE__Class2SpillMemSize                0
+#define   W_CLASS2_SPILL_MEM_SIZE__Class2SpillMemSize               32
+#define R_CLASS3_SPILL_MEM_START_0                                  0x216
+#define   O_CLASS3_SPILL_MEM_START_0__Class3SpillMemStart0           0
+#define   W_CLASS3_SPILL_MEM_START_0__Class3SpillMemStart0          32
+#define R_CLASS3_SPILL_MEM_START_1                                  0x217
+#define   O_CLASS3_SPILL_MEM_START_1__Class3SpillMemStart1           0
+#define   W_CLASS3_SPILL_MEM_START_1__Class3SpillMemStart1           3
+#define R_CLASS3_SPILL_MEM_SIZE                                     0x218
+#define   O_CLASS3_SPILL_MEM_SIZE__Class3SpillMemSize                0
+#define   W_CLASS3_SPILL_MEM_SIZE__Class3SpillMemSize               32
+#define R_REG_FRIN1_SPILL_MEM_START_0                               0x219
+#define R_REG_FRIN1_SPILL_MEM_START_1                               0x21a
+#define R_REG_FRIN1_SPILL_MEM_SIZE                                  0x21b
+#define R_SPIHNGY0                                                  0x219
+#define   O_SPIHNGY0__EG_HNGY_THRESH_0                              24
+#define   W_SPIHNGY0__EG_HNGY_THRESH_0                              7
+#define   O_SPIHNGY0__EG_HNGY_THRESH_1                              16
+#define   W_SPIHNGY0__EG_HNGY_THRESH_1                              7
+#define   O_SPIHNGY0__EG_HNGY_THRESH_2                              8
+#define   W_SPIHNGY0__EG_HNGY_THRESH_2                              7
+#define   O_SPIHNGY0__EG_HNGY_THRESH_3                              0
+#define   W_SPIHNGY0__EG_HNGY_THRESH_3                              7
+#define R_SPIHNGY1                                                  0x21A
+#define   O_SPIHNGY1__EG_HNGY_THRESH_4                              24
+#define   W_SPIHNGY1__EG_HNGY_THRESH_4                              7
+#define   O_SPIHNGY1__EG_HNGY_THRESH_5                              16
+#define   W_SPIHNGY1__EG_HNGY_THRESH_5                              7
+#define   O_SPIHNGY1__EG_HNGY_THRESH_6                              8
+#define   W_SPIHNGY1__EG_HNGY_THRESH_6                              7
+#define   O_SPIHNGY1__EG_HNGY_THRESH_7                              0
+#define   W_SPIHNGY1__EG_HNGY_THRESH_7                              7
+#define R_SPIHNGY2                                                  0x21B
+#define   O_SPIHNGY2__EG_HNGY_THRESH_8                              24
+#define   W_SPIHNGY2__EG_HNGY_THRESH_8                              7
+#define   O_SPIHNGY2__EG_HNGY_THRESH_9                              16
+#define   W_SPIHNGY2__EG_HNGY_THRESH_9                              7
+#define   O_SPIHNGY2__EG_HNGY_THRESH_10                             8
+#define   W_SPIHNGY2__EG_HNGY_THRESH_10                             7
+#define   O_SPIHNGY2__EG_HNGY_THRESH_11                             0
+#define   W_SPIHNGY2__EG_HNGY_THRESH_11                             7
+#define R_SPIHNGY3                                                  0x21C
+#define   O_SPIHNGY3__EG_HNGY_THRESH_12                             24
+#define   W_SPIHNGY3__EG_HNGY_THRESH_12                             7
+#define   O_SPIHNGY3__EG_HNGY_THRESH_13                             16
+#define   W_SPIHNGY3__EG_HNGY_THRESH_13                             7
+#define   O_SPIHNGY3__EG_HNGY_THRESH_14                             8
+#define   W_SPIHNGY3__EG_HNGY_THRESH_14                             7
+#define   O_SPIHNGY3__EG_HNGY_THRESH_15                             0
+#define   W_SPIHNGY3__EG_HNGY_THRESH_15                             7
+#define R_SPISTRV0                                                  0x21D
+#define   O_SPISTRV0__EG_STRV_THRESH_0                              24
+#define   W_SPISTRV0__EG_STRV_THRESH_0                              7
+#define   O_SPISTRV0__EG_STRV_THRESH_1                              16
+#define   W_SPISTRV0__EG_STRV_THRESH_1                              7
+#define   O_SPISTRV0__EG_STRV_THRESH_2                              8
+#define   W_SPISTRV0__EG_STRV_THRESH_2                              7
+#define   O_SPISTRV0__EG_STRV_THRESH_3                              0
+#define   W_SPISTRV0__EG_STRV_THRESH_3                              7
+#define R_SPISTRV1                                                  0x21E
+#define   O_SPISTRV1__EG_STRV_THRESH_4                              24
+#define   W_SPISTRV1__EG_STRV_THRESH_4                              7
+#define   O_SPISTRV1__EG_STRV_THRESH_5                              16
+#define   W_SPISTRV1__EG_STRV_THRESH_5                              7
+#define   O_SPISTRV1__EG_STRV_THRESH_6                              8
+#define   W_SPISTRV1__EG_STRV_THRESH_6                              7
+#define   O_SPISTRV1__EG_STRV_THRESH_7                              0
+#define   W_SPISTRV1__EG_STRV_THRESH_7                              7
+#define R_SPISTRV2                                                  0x21F
+#define   O_SPISTRV2__EG_STRV_THRESH_8                              24
+#define   W_SPISTRV2__EG_STRV_THRESH_8                              7
+#define   O_SPISTRV2__EG_STRV_THRESH_9                              16
+#define   W_SPISTRV2__EG_STRV_THRESH_9                              7
+#define   O_SPISTRV2__EG_STRV_THRESH_10                             8
+#define   W_SPISTRV2__EG_STRV_THRESH_10                             7
+#define   O_SPISTRV2__EG_STRV_THRESH_11                             0
+#define   W_SPISTRV2__EG_STRV_THRESH_11                             7
+#define R_SPISTRV3                                                  0x220
+#define   O_SPISTRV3__EG_STRV_THRESH_12                             24
+#define   W_SPISTRV3__EG_STRV_THRESH_12                             7
+#define   O_SPISTRV3__EG_STRV_THRESH_13                             16
+#define   W_SPISTRV3__EG_STRV_THRESH_13                             7
+#define   O_SPISTRV3__EG_STRV_THRESH_14                             8
+#define   W_SPISTRV3__EG_STRV_THRESH_14                             7
+#define   O_SPISTRV3__EG_STRV_THRESH_15                             0
+#define   W_SPISTRV3__EG_STRV_THRESH_15                             7
+#define R_TXDATAFIFO0                                               0x221
+#define   O_TXDATAFIFO0__Tx0DataFifoStart                           24
+#define   W_TXDATAFIFO0__Tx0DataFifoStart                           7
+#define   O_TXDATAFIFO0__Tx0DataFifoSize                            16
+#define   W_TXDATAFIFO0__Tx0DataFifoSize                            7
+#define   O_TXDATAFIFO0__Tx1DataFifoStart                           8
+#define   W_TXDATAFIFO0__Tx1DataFifoStart                           7
+#define   O_TXDATAFIFO0__Tx1DataFifoSize                            0
+#define   W_TXDATAFIFO0__Tx1DataFifoSize                            7
+#define R_TXDATAFIFO1                                               0x222
+#define   O_TXDATAFIFO1__Tx2DataFifoStart                           24
+#define   W_TXDATAFIFO1__Tx2DataFifoStart                           7
+#define   O_TXDATAFIFO1__Tx2DataFifoSize                            16
+#define   W_TXDATAFIFO1__Tx2DataFifoSize                            7
+#define   O_TXDATAFIFO1__Tx3DataFifoStart                           8
+#define   W_TXDATAFIFO1__Tx3DataFifoStart                           7
+#define   O_TXDATAFIFO1__Tx3DataFifoSize                            0
+#define   W_TXDATAFIFO1__Tx3DataFifoSize                            7
+#define R_TXDATAFIFO2                                               0x223
+#define   O_TXDATAFIFO2__Tx4DataFifoStart                           24
+#define   W_TXDATAFIFO2__Tx4DataFifoStart                           7
+#define   O_TXDATAFIFO2__Tx4DataFifoSize                            16
+#define   W_TXDATAFIFO2__Tx4DataFifoSize                            7
+#define   O_TXDATAFIFO2__Tx5DataFifoStart                           8
+#define   W_TXDATAFIFO2__Tx5DataFifoStart                           7
+#define   O_TXDATAFIFO2__Tx5DataFifoSize                            0
+#define   W_TXDATAFIFO2__Tx5DataFifoSize                            7
+#define R_TXDATAFIFO3                                               0x224
+#define   O_TXDATAFIFO3__Tx6DataFifoStart                           24
+#define   W_TXDATAFIFO3__Tx6DataFifoStart                           7
+#define   O_TXDATAFIFO3__Tx6DataFifoSize                            16
+#define   W_TXDATAFIFO3__Tx6DataFifoSize                            7
+#define   O_TXDATAFIFO3__Tx7DataFifoStart                           8
+#define   W_TXDATAFIFO3__Tx7DataFifoStart                           7
+#define   O_TXDATAFIFO3__Tx7DataFifoSize                            0
+#define   W_TXDATAFIFO3__Tx7DataFifoSize                            7
+#define R_TXDATAFIFO4                                               0x225
+#define   O_TXDATAFIFO4__Tx8DataFifoStart                           24
+#define   W_TXDATAFIFO4__Tx8DataFifoStart                           7
+#define   O_TXDATAFIFO4__Tx8DataFifoSize                            16
+#define   W_TXDATAFIFO4__Tx8DataFifoSize                            7
+#define   O_TXDATAFIFO4__Tx9DataFifoStart                           8
+#define   W_TXDATAFIFO4__Tx9DataFifoStart                           7
+#define   O_TXDATAFIFO4__Tx9DataFifoSize                            0
+#define   W_TXDATAFIFO4__Tx9DataFifoSize                            7
+#define R_TXDATAFIFO5                                               0x226
+#define   O_TXDATAFIFO5__Tx10DataFifoStart                          24
+#define   W_TXDATAFIFO5__Tx10DataFifoStart                          7
+#define   O_TXDATAFIFO5__Tx10DataFifoSize                           16
+#define   W_TXDATAFIFO5__Tx10DataFifoSize                           7
+#define   O_TXDATAFIFO5__Tx11DataFifoStart                          8
+#define   W_TXDATAFIFO5__Tx11DataFifoStart                          7
+#define   O_TXDATAFIFO5__Tx11DataFifoSize                           0
+#define   W_TXDATAFIFO5__Tx11DataFifoSize                           7
+#define R_TXDATAFIFO6                                               0x227
+#define   O_TXDATAFIFO6__Tx12DataFifoStart                          24
+#define   W_TXDATAFIFO6__Tx12DataFifoStart                          7
+#define   O_TXDATAFIFO6__Tx12DataFifoSize                           16
+#define   W_TXDATAFIFO6__Tx12DataFifoSize                           7
+#define   O_TXDATAFIFO6__Tx13DataFifoStart                          8
+#define   W_TXDATAFIFO6__Tx13DataFifoStart                          7
+#define   O_TXDATAFIFO6__Tx13DataFifoSize                           0
+#define   W_TXDATAFIFO6__Tx13DataFifoSize                           7
+#define R_TXDATAFIFO7                                               0x228
+#define   O_TXDATAFIFO7__Tx14DataFifoStart                          24
+#define   W_TXDATAFIFO7__Tx14DataFifoStart                          7
+#define   O_TXDATAFIFO7__Tx14DataFifoSize                           16
+#define   W_TXDATAFIFO7__Tx14DataFifoSize                           7
+#define   O_TXDATAFIFO7__Tx15DataFifoStart                          8
+#define   W_TXDATAFIFO7__Tx15DataFifoStart                          7
+#define   O_TXDATAFIFO7__Tx15DataFifoSize                           0
+#define   W_TXDATAFIFO7__Tx15DataFifoSize                           7
+#define R_RXDATAFIFO0                                               0x229
+#define   O_RXDATAFIFO0__Rx0DataFifoStart                           24
+#define   W_RXDATAFIFO0__Rx0DataFifoStart                           7
+#define   O_RXDATAFIFO0__Rx0DataFifoSize                            16
+#define   W_RXDATAFIFO0__Rx0DataFifoSize                            7
+#define   O_RXDATAFIFO0__Rx1DataFifoStart                           8
+#define   W_RXDATAFIFO0__Rx1DataFifoStart                           7
+#define   O_RXDATAFIFO0__Rx1DataFifoSize                            0
+#define   W_RXDATAFIFO0__Rx1DataFifoSize                            7
+#define R_RXDATAFIFO1                                               0x22A
+#define   O_RXDATAFIFO1__Rx2DataFifoStart                           24
+#define   W_RXDATAFIFO1__Rx2DataFifoStart                           7
+#define   O_RXDATAFIFO1__Rx2DataFifoSize                            16
+#define   W_RXDATAFIFO1__Rx2DataFifoSize                            7
+#define   O_RXDATAFIFO1__Rx3DataFifoStart                           8
+#define   W_RXDATAFIFO1__Rx3DataFifoStart                           7
+#define   O_RXDATAFIFO1__Rx3DataFifoSize                            0
+#define   W_RXDATAFIFO1__Rx3DataFifoSize                            7
+#define R_RXDATAFIFO2                                               0x22B
+#define   O_RXDATAFIFO2__Rx4DataFifoStart                           24
+#define   W_RXDATAFIFO2__Rx4DataFifoStart                           7
+#define   O_RXDATAFIFO2__Rx4DataFifoSize                            16
+#define   W_RXDATAFIFO2__Rx4DataFifoSize                            7
+#define   O_RXDATAFIFO2__Rx5DataFifoStart                           8
+#define   W_RXDATAFIFO2__Rx5DataFifoStart                           7
+#define   O_RXDATAFIFO2__Rx5DataFifoSize                            0
+#define   W_RXDATAFIFO2__Rx5DataFifoSize                            7
+#define R_RXDATAFIFO3                                               0x22C
+#define   O_RXDATAFIFO3__Rx6DataFifoStart                           24
+#define   W_RXDATAFIFO3__Rx6DataFifoStart                           7
+#define   O_RXDATAFIFO3__Rx6DataFifoSize                            16
+#define   W_RXDATAFIFO3__Rx6DataFifoSize                            7
+#define   O_RXDATAFIFO3__Rx7DataFifoStart                           8
+#define   W_RXDATAFIFO3__Rx7DataFifoStart                           7
+#define   O_RXDATAFIFO3__Rx7DataFifoSize                            0
+#define   W_RXDATAFIFO3__Rx7DataFifoSize                            7
+#define R_RXDATAFIFO4                                               0x22D
+#define   O_RXDATAFIFO4__Rx8DataFifoStart                           24
+#define   W_RXDATAFIFO4__Rx8DataFifoStart                           7
+#define   O_RXDATAFIFO4__Rx8DataFifoSize                            16
+#define   W_RXDATAFIFO4__Rx8DataFifoSize                            7
+#define   O_RXDATAFIFO4__Rx9DataFifoStart                           8
+#define   W_RXDATAFIFO4__Rx9DataFifoStart                           7
+#define   O_RXDATAFIFO4__Rx9DataFifoSize                            0
+#define   W_RXDATAFIFO4__Rx9DataFifoSize                            7
+#define R_RXDATAFIFO5                                               0x22E
+#define   O_RXDATAFIFO5__Rx10DataFifoStart                          24
+#define   W_RXDATAFIFO5__Rx10DataFifoStart                          7
+#define   O_RXDATAFIFO5__Rx10DataFifoSize                           16
+#define   W_RXDATAFIFO5__Rx10DataFifoSize                           7
+#define   O_RXDATAFIFO5__Rx11DataFifoStart                          8
+#define   W_RXDATAFIFO5__Rx11DataFifoStart                          7
+#define   O_RXDATAFIFO5__Rx11DataFifoSize                           0
+#define   W_RXDATAFIFO5__Rx11DataFifoSize                           7
+#define R_RXDATAFIFO6                                               0x22F
+#define   O_RXDATAFIFO6__Rx12DataFifoStart                          24
+#define   W_RXDATAFIFO6__Rx12DataFifoStart                          7
+#define   O_RXDATAFIFO6__Rx12DataFifoSize                           16
+#define   W_RXDATAFIFO6__Rx12DataFifoSize                           7
+#define   O_RXDATAFIFO6__Rx13DataFifoStart                          8
+#define   W_RXDATAFIFO6__Rx13DataFifoStart                          7
+#define   O_RXDATAFIFO6__Rx13DataFifoSize                           0
+#define   W_RXDATAFIFO6__Rx13DataFifoSize                           7
+#define R_RXDATAFIFO7                                               0x230
+#define   O_RXDATAFIFO7__Rx14DataFifoStart                          24
+#define   W_RXDATAFIFO7__Rx14DataFifoStart                          7
+#define   O_RXDATAFIFO7__Rx14DataFifoSize                           16
+#define   W_RXDATAFIFO7__Rx14DataFifoSize                           7
+#define   O_RXDATAFIFO7__Rx15DataFifoStart                          8
+#define   W_RXDATAFIFO7__Rx15DataFifoStart                          7
+#define   O_RXDATAFIFO7__Rx15DataFifoSize                           0
+#define   W_RXDATAFIFO7__Rx15DataFifoSize                           7
+#define R_XGMACPADCALIBRATION                                       0x231
+#define R_FREEQCARVE                                                0x233
+#define R_SPI4STATICDELAY0                                          0x240
+#define   O_SPI4STATICDELAY0__DataLine7                             28
+#define   W_SPI4STATICDELAY0__DataLine7                             4
+#define   O_SPI4STATICDELAY0__DataLine6                             24
+#define   W_SPI4STATICDELAY0__DataLine6                             4
+#define   O_SPI4STATICDELAY0__DataLine5                             20
+#define   W_SPI4STATICDELAY0__DataLine5                             4
+#define   O_SPI4STATICDELAY0__DataLine4                             16
+#define   W_SPI4STATICDELAY0__DataLine4                             4
+#define   O_SPI4STATICDELAY0__DataLine3                             12
+#define   W_SPI4STATICDELAY0__DataLine3                             4
+#define   O_SPI4STATICDELAY0__DataLine2                             8
+#define   W_SPI4STATICDELAY0__DataLine2                             4
+#define   O_SPI4STATICDELAY0__DataLine1                             4
+#define   W_SPI4STATICDELAY0__DataLine1                             4
+#define   O_SPI4STATICDELAY0__DataLine0                             0
+#define   W_SPI4STATICDELAY0__DataLine0                             4
+#define R_SPI4STATICDELAY1                                          0x241
+#define   O_SPI4STATICDELAY1__DataLine15                            28
+#define   W_SPI4STATICDELAY1__DataLine15                            4
+#define   O_SPI4STATICDELAY1__DataLine14                            24
+#define   W_SPI4STATICDELAY1__DataLine14                            4
+#define   O_SPI4STATICDELAY1__DataLine13                            20
+#define   W_SPI4STATICDELAY1__DataLine13                            4
+#define   O_SPI4STATICDELAY1__DataLine12                            16
+#define   W_SPI4STATICDELAY1__DataLine12                            4
+#define   O_SPI4STATICDELAY1__DataLine11                            12
+#define   W_SPI4STATICDELAY1__DataLine11                            4
+#define   O_SPI4STATICDELAY1__DataLine10                            8
+#define   W_SPI4STATICDELAY1__DataLine10                            4
+#define   O_SPI4STATICDELAY1__DataLine9                             4
+#define   W_SPI4STATICDELAY1__DataLine9                             4
+#define   O_SPI4STATICDELAY1__DataLine8                             0
+#define   W_SPI4STATICDELAY1__DataLine8                             4
+#define R_SPI4STATICDELAY2                                          0x242
+#define   O_SPI4STATICDELAY0__TxStat1                               8
+#define   W_SPI4STATICDELAY0__TxStat1                               4
+#define   O_SPI4STATICDELAY0__TxStat0                               4
+#define   W_SPI4STATICDELAY0__TxStat0                               4
+#define   O_SPI4STATICDELAY0__RxControl                             0
+#define   W_SPI4STATICDELAY0__RxControl                             4
+#define R_SPI4CONTROL                                               0x243
+#define   O_SPI4CONTROL__StaticDelay                                2
+#define   O_SPI4CONTROL__LVDS_LVTTL                                 1
+#define   O_SPI4CONTROL__SPI4Enable                                 0
+#define R_CLASSWATERMARKS                                           0x244
+#define   O_CLASSWATERMARKS__Class0Watermark                        24
+#define   W_CLASSWATERMARKS__Class0Watermark                        5
+#define   O_CLASSWATERMARKS__Class1Watermark                        16
+#define   W_CLASSWATERMARKS__Class1Watermark                        5
+#define   O_CLASSWATERMARKS__Class3Watermark                        0
+#define   W_CLASSWATERMARKS__Class3Watermark                        5
+#define R_RXWATERMARKS1                                              0x245
+#define   O_RXWATERMARKS__Rx0DataWatermark                          24
+#define   W_RXWATERMARKS__Rx0DataWatermark                          7
+#define   O_RXWATERMARKS__Rx1DataWatermark                          16
+#define   W_RXWATERMARKS__Rx1DataWatermark                          7
+#define   O_RXWATERMARKS__Rx3DataWatermark                          0
+#define   W_RXWATERMARKS__Rx3DataWatermark                          7
+#define R_RXWATERMARKS2                                              0x246
+#define   O_RXWATERMARKS__Rx4DataWatermark                          24
+#define   W_RXWATERMARKS__Rx4DataWatermark                          7
+#define   O_RXWATERMARKS__Rx5DataWatermark                          16
+#define   W_RXWATERMARKS__Rx5DataWatermark                          7
+#define   O_RXWATERMARKS__Rx6DataWatermark                          8
+#define   W_RXWATERMARKS__Rx6DataWatermark                          7
+#define   O_RXWATERMARKS__Rx7DataWatermark                          0
+#define   W_RXWATERMARKS__Rx7DataWatermark                          7
+#define R_RXWATERMARKS3                                              0x247
+#define   O_RXWATERMARKS__Rx8DataWatermark                          24
+#define   W_RXWATERMARKS__Rx8DataWatermark                          7
+#define   O_RXWATERMARKS__Rx9DataWatermark                          16
+#define   W_RXWATERMARKS__Rx9DataWatermark                          7
+#define   O_RXWATERMARKS__Rx10DataWatermark                         8
+#define   W_RXWATERMARKS__Rx10DataWatermark                         7
+#define   O_RXWATERMARKS__Rx11DataWatermark                         0
+#define   W_RXWATERMARKS__Rx11DataWatermark                         7
+#define R_RXWATERMARKS4                                              0x248
+#define   O_RXWATERMARKS__Rx12DataWatermark                         24
+#define   W_RXWATERMARKS__Rx12DataWatermark                         7
+#define   O_RXWATERMARKS__Rx13DataWatermark                         16
+#define   W_RXWATERMARKS__Rx13DataWatermark                         7
+#define   O_RXWATERMARKS__Rx14DataWatermark                         8
+#define   W_RXWATERMARKS__Rx14DataWatermark                         7
+#define   O_RXWATERMARKS__Rx15DataWatermark                         0
+#define   W_RXWATERMARKS__Rx15DataWatermark                         7
+#define R_FREEWATERMARKS                                            0x249
+#define   O_FREEWATERMARKS__FreeOutWatermark                        16
+#define   W_FREEWATERMARKS__FreeOutWatermark                        16
+#define   O_FREEWATERMARKS__JumFrWatermark                          8
+#define   W_FREEWATERMARKS__JumFrWatermark                          7
+#define   O_FREEWATERMARKS__RegFrWatermark                          0
+#define   W_FREEWATERMARKS__RegFrWatermark                          7
+#define R_EGRESSFIFOCARVINGSLOTS                                    0x24a
+
+#define CTRL_RES0           0
+#define CTRL_RES1           1
+#define CTRL_REG_FREE       2
+#define CTRL_JUMBO_FREE     3
+#define CTRL_CONT           4
+#define CTRL_EOP            5
+#define CTRL_START          6
+#define CTRL_SNGL           7
+
+#define CTRL_B0_NOT_EOP     0
+#define CTRL_B0_EOP         1
+
+#define R_ROUND_ROBIN_TABLE                 0
+#define R_PDE_CLASS_0                       0x300
+#define R_PDE_CLASS_1                       0x302
+#define R_PDE_CLASS_2                       0x304
+#define R_PDE_CLASS_3                       0x306
+
+#define R_MSG_TX_THRESHOLD                  0x308
+
+#define R_GMAC_JFR0_BUCKET_SIZE              0x320
+#define R_GMAC_RFR0_BUCKET_SIZE              0x321
+#define R_GMAC_TX0_BUCKET_SIZE              0x322
+#define R_GMAC_TX1_BUCKET_SIZE              0x323
+#define R_GMAC_TX2_BUCKET_SIZE              0x324
+#define R_GMAC_TX3_BUCKET_SIZE              0x325
+#define R_GMAC_JFR1_BUCKET_SIZE              0x326
+#define R_GMAC_RFR1_BUCKET_SIZE              0x327
+
+#define R_XGS_TX0_BUCKET_SIZE               0x320
+#define R_XGS_TX1_BUCKET_SIZE               0x321
+#define R_XGS_TX2_BUCKET_SIZE               0x322
+#define R_XGS_TX3_BUCKET_SIZE               0x323
+#define R_XGS_TX4_BUCKET_SIZE               0x324
+#define R_XGS_TX5_BUCKET_SIZE               0x325
+#define R_XGS_TX6_BUCKET_SIZE               0x326
+#define R_XGS_TX7_BUCKET_SIZE               0x327
+#define R_XGS_TX8_BUCKET_SIZE               0x328
+#define R_XGS_TX9_BUCKET_SIZE               0x329
+#define R_XGS_TX10_BUCKET_SIZE              0x32A
+#define R_XGS_TX11_BUCKET_SIZE              0x32B
+#define R_XGS_TX12_BUCKET_SIZE              0x32C
+#define R_XGS_TX13_BUCKET_SIZE              0x32D
+#define R_XGS_TX14_BUCKET_SIZE              0x32E
+#define R_XGS_TX15_BUCKET_SIZE              0x32F
+#define R_XGS_JFR_BUCKET_SIZE               0x330
+#define R_XGS_RFR_BUCKET_SIZE               0x331
+
+#define R_CC_CPU0_0                         0x380
+#define R_CC_CPU1_0                         0x388
+#define R_CC_CPU2_0                         0x390
+#define R_CC_CPU3_0                         0x398
+#define R_CC_CPU4_0                         0x3a0
+#define R_CC_CPU5_0                         0x3a8
+#define R_CC_CPU6_0                         0x3b0
+#define R_CC_CPU7_0                         0x3b8
+
+#define XLR_GMAC_BLK_SZ		            (XLR_IO_GMAC_1_OFFSET - \
+		XLR_IO_GMAC_0_OFFSET)
+
+/* Constants used for configuring the devices */
+
+#define XLR_FB_STN			6 /* Bucket used for Tx freeback */
+
+#define MAC_B2B_IPG                     88
+
+#define	XLR_NET_PREPAD_LEN		32
+
+/* frame sizes need to be cacheline aligned */
+#define MAX_FRAME_SIZE                  (1536 + XLR_NET_PREPAD_LEN)
+#define MAX_FRAME_SIZE_JUMBO            9216
+
+#define MAC_SKB_BACK_PTR_SIZE           SMP_CACHE_BYTES
+#define MAC_PREPAD                      0
+#define BYTE_OFFSET                     2
+#define XLR_RX_BUF_SIZE                 (MAX_FRAME_SIZE + BYTE_OFFSET + \
+		MAC_PREPAD + MAC_SKB_BACK_PTR_SIZE + SMP_CACHE_BYTES)
+#define MAC_CRC_LEN                     4
+#define MAX_NUM_MSGRNG_STN_CC           128
+#define MAX_MSG_SND_ATTEMPTS		100	/* 13 stns x 4 entry msg/stn +
+						   headroom */
+
+#define MAC_FRIN_TO_BE_SENT_THRESHOLD   16
+
+#define MAX_NUM_DESC_SPILL		1024
+#define MAX_FRIN_SPILL                  (MAX_NUM_DESC_SPILL << 2)
+#define MAX_FROUT_SPILL                 (MAX_NUM_DESC_SPILL << 2)
+#define MAX_CLASS_0_SPILL               (MAX_NUM_DESC_SPILL << 2)
+#define MAX_CLASS_1_SPILL               (MAX_NUM_DESC_SPILL << 2)
+#define MAX_CLASS_2_SPILL               (MAX_NUM_DESC_SPILL << 2)
+#define MAX_CLASS_3_SPILL               (MAX_NUM_DESC_SPILL << 2)
+
+enum {
+	SGMII_SPEED_10 = 0x00000000,
+	SGMII_SPEED_100 = 0x02000000,
+	SGMII_SPEED_1000 = 0x04000000,
+};
+
+enum tsv_rsv_reg {
+	TX_RX_64_BYTE_FRAME = 0x20,
+	TX_RX_64_127_BYTE_FRAME,
+	TX_RX_128_255_BYTE_FRAME,
+	TX_RX_256_511_BYTE_FRAME,
+	TX_RX_512_1023_BYTE_FRAME,
+	TX_RX_1024_1518_BYTE_FRAME,
+	TX_RX_1519_1522_VLAN_BYTE_FRAME,
+
+	RX_BYTE_COUNTER = 0x27,
+	RX_PACKET_COUNTER,
+	RX_FCS_ERROR_COUNTER,
+	RX_MULTICAST_PACKET_COUNTER,
+	RX_BROADCAST_PACKET_COUNTER,
+	RX_CONTROL_FRAME_PACKET_COUNTER,
+	RX_PAUSE_FRAME_PACKET_COUNTER,
+	RX_UNKNOWN_OP_CODE_COUNTER,
+	RX_ALIGNMENT_ERROR_COUNTER,
+	RX_FRAME_LENGTH_ERROR_COUNTER,
+	RX_CODE_ERROR_COUNTER,
+	RX_CARRIER_SENSE_ERROR_COUNTER,
+	RX_UNDERSIZE_PACKET_COUNTER,
+	RX_OVERSIZE_PACKET_COUNTER,
+	RX_FRAGMENTS_COUNTER,
+	RX_JABBER_COUNTER,
+	RX_DROP_PACKET_COUNTER,
+
+	TX_BYTE_COUNTER   = 0x38,
+	TX_PACKET_COUNTER,
+	TX_MULTICAST_PACKET_COUNTER,
+	TX_BROADCAST_PACKET_COUNTER,
+	TX_PAUSE_CONTROL_FRAME_COUNTER,
+	TX_DEFERRAL_PACKET_COUNTER,
+	TX_EXCESSIVE_DEFERRAL_PACKET_COUNTER,
+	TX_SINGLE_COLLISION_PACKET_COUNTER,
+	TX_MULTI_COLLISION_PACKET_COUNTER,
+	TX_LATE_COLLISION_PACKET_COUNTER,
+	TX_EXCESSIVE_COLLISION_PACKET_COUNTER,
+	TX_TOTAL_COLLISION_COUNTER,
+	TX_PAUSE_FRAME_HONERED_COUNTER,
+	TX_DROP_FRAME_COUNTER,
+	TX_JABBER_FRAME_COUNTER,
+	TX_FCS_ERROR_COUNTER,
+	TX_CONTROL_FRAME_COUNTER,
+	TX_OVERSIZE_FRAME_COUNTER,
+	TX_UNDERSIZE_FRAME_COUNTER,
+	TX_FRAGMENT_FRAME_COUNTER,
+
+	CARRY_REG_1 = 0x4c,
+	CARRY_REG_2 = 0x4d,
+};
+
+struct xlr_net_priv {
+	u32 __iomem *base_addr;
+	struct net_device *ndev;
+	struct mii_bus *mii_bus;
+	int num_rx_desc;
+	int phy_addr;	/* PHY addr on MDIO bus */
+	int pcs_id;	/* PCS id on MDIO bus */
+	int port_id;	/* Port(gmac/xgmac) number, i.e 0-7 */
+	u32 __iomem *mii_addr;
+	u32 __iomem *serdes_addr;
+	u32 __iomem *pcs_addr;
+	u32 __iomem *gpio_addr;
+	int phy_speed;
+	int port_type;
+	struct timer_list queue_timer;
+	int wakeup_q;
+	struct platform_device *pdev;
+	struct xlr_net_data *nd;
+
+	u64 *frin_spill;
+	u64 *frout_spill;
+	u64 *class_0_spill;
+	u64 *class_1_spill;
+	u64 *class_2_spill;
+	u64 *class_3_spill;
+};
+
+extern void xlr_set_gmac_speed(struct xlr_net_priv *priv);
diff --git a/drivers/staging/nvec/nvec.c b/drivers/staging/nvec/nvec.c
index cf15936..a88959f 100644
--- a/drivers/staging/nvec/nvec.c
+++ b/drivers/staging/nvec/nvec.c
@@ -352,10 +352,10 @@ static void nvec_toggle_global_events(struct nvec_chip *nvec, bool state)
  */
 static void nvec_event_mask(char *ev, u32 mask)
 {
-	ev[3] = mask >> 16 && 0xff;
-	ev[4] = mask >> 24 && 0xff;
-	ev[5] = mask >> 0  && 0xff;
-	ev[6] = mask >> 8  && 0xff;
+	ev[3] = mask >> 16 & 0xff;
+	ev[4] = mask >> 24 & 0xff;
+	ev[5] = mask >> 0  & 0xff;
+	ev[6] = mask >> 8  & 0xff;
 }
 
 /**
diff --git a/drivers/staging/olpc_dcon/olpc_dcon.c b/drivers/staging/olpc_dcon/olpc_dcon.c
index 54ed6f6..193e1c6 100644
--- a/drivers/staging/olpc_dcon/olpc_dcon.c
+++ b/drivers/staging/olpc_dcon/olpc_dcon.c
@@ -550,12 +550,12 @@ static int dcon_reboot_notify(struct notifier_block *nb,
 	struct dcon_priv *dcon = container_of(nb, struct dcon_priv, reboot_nb);
 
 	if (!dcon || !dcon->client)
-		return 0;
+		return NOTIFY_DONE;
 
 	/* Turn off the DCON. Entirely. */
 	dcon_write(dcon, DCON_REG_MODE, 0x39);
 	dcon_write(dcon, DCON_REG_MODE, 0x32);
-	return 0;
+	return NOTIFY_DONE;
 }
 
 static int unfreeze_on_panic(struct notifier_block *nb,
diff --git a/drivers/staging/omap-thermal/Kconfig b/drivers/staging/omap-thermal/Kconfig
deleted file mode 100644
index 30cbc3b..0000000
--- a/drivers/staging/omap-thermal/Kconfig
+++ /dev/null
@@ -1,46 +0,0 @@
-config OMAP_BANDGAP
-	tristate "Texas Instruments OMAP4+ temperature sensor driver"
-	depends on THERMAL
-	depends on ARCH_OMAP4 || SOC_OMAP5
-	help
-	  If you say yes here you get support for the Texas Instruments
-	  OMAP4460+ on die bandgap temperature sensor support. The register
-	  set is part of system control module.
-
-	  This includes alert interrupts generation and also the TSHUT
-	  support.
-
-config OMAP_THERMAL
-	bool "Texas Instruments OMAP4+ thermal framework support"
-	depends on OMAP_BANDGAP
-	depends on CPU_THERMAL
-	help
-	  If you say yes here you want to get support for generic thermal
-	  framework for the Texas Instruments OMAP4460+ on die bandgap
-	  temperature sensor.
-
-config OMAP4_THERMAL
-	bool "Texas Instruments OMAP4 thermal support"
-	depends on OMAP_BANDGAP
-	depends on ARCH_OMAP4
-	help
-	  If you say yes here you get thermal support for the Texas Instruments
-	  OMAP4 SoC family. The current chip supported are:
-	   - OMAP4430
-	   - OMAP4460
-	   - OMAP4470
-
-	  This includes alert interrupts generation and also the TSHUT
-	  support.
-
-config OMAP5_THERMAL
-	bool "Texas Instruments OMAP5 thermal support"
-	depends on OMAP_BANDGAP
-	depends on SOC_OMAP5
-	help
-	  If you say yes here you get thermal support for the Texas Instruments
-	  OMAP5 SoC family. The current chip supported are:
-	   - OMAP5430
-
-	  This includes alert interrupts generation and also the TSHUT
-	  support.
diff --git a/drivers/staging/omap-thermal/Makefile b/drivers/staging/omap-thermal/Makefile
deleted file mode 100644
index 091c4d2..0000000
--- a/drivers/staging/omap-thermal/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-obj-$(CONFIG_OMAP_BANDGAP)	+= omap-thermal.o
-omap-thermal-y			:= omap-bandgap.o
-omap-thermal-$(CONFIG_OMAP_THERMAL)	+= omap-thermal-common.o
-omap-thermal-$(CONFIG_OMAP4_THERMAL)	+= omap4-thermal.o
-omap-thermal-$(CONFIG_OMAP5_THERMAL)	+= omap5-thermal.o
diff --git a/drivers/staging/omap-thermal/TODO b/drivers/staging/omap-thermal/TODO
deleted file mode 100644
index 9e23cc4..0000000
--- a/drivers/staging/omap-thermal/TODO
+++ /dev/null
@@ -1,28 +0,0 @@
-List of TODOs (by Eduardo Valentin)
-
-on omap-bandgap.c:
-- Rework locking
-- Improve driver code by adding usage of regmap-mmio
-- Test every exposed API to userland
-- Add support to hwmon
-- Review and revisit all API exposed
-- Revisit PM support
-- Revisit data structures and simplify them
-- Once SCM-core api settles, update this driver accordingly
-
-on omap-thermal-common.c/omap-thermal.h:
-- Revisit extrapolation constants for O4/O5
-- Revisit need for locking
-- Revisit trips and its definitions
-- Revisit trending
-
-on omap5-thermal.c
-- Add support for GPU cooling
-
-generally:
-- write Kconfig dependencies so that omap variants are covered
-- make checkpatch.pl and sparse happy
-- make sure this code works on OMAP4430, OMAP4460 and OMAP5430
-- update documentation
-
-Copy patches to Eduardo Valentin <eduardo.valentin@ti.com>
diff --git a/drivers/staging/omap-thermal/omap-bandgap.c b/drivers/staging/omap-thermal/omap-bandgap.c
deleted file mode 100644
index dcc1448..0000000
--- a/drivers/staging/omap-thermal/omap-bandgap.c
+++ /dev/null
@@ -1,1174 +0,0 @@
-/*
- * OMAP4 Bandgap temperature sensor driver
- *
- * Copyright (C) 2011-2012 Texas Instruments Incorporated - http://www.ti.com/
- * Author: J Keerthy <j-keerthy@ti.com>
- * Author: Moiz Sonasath <m-sonasath@ti.com>
- * Couple of fixes, DT and MFD adaptation:
- *   Eduardo Valentin <eduardo.valentin@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/module.h>
-#include <linux/export.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/clk.h>
-#include <linux/gpio.h>
-#include <linux/platform_device.h>
-#include <linux/err.h>
-#include <linux/types.h>
-#include <linux/mutex.h>
-#include <linux/reboot.h>
-#include <linux/of_device.h>
-#include <linux/of_platform.h>
-#include <linux/of_irq.h>
-#include <linux/io.h>
-
-#include "omap-bandgap.h"
-
-static u32 omap_bandgap_readl(struct omap_bandgap *bg_ptr, u32 reg)
-{
-	return readl(bg_ptr->base + reg);
-}
-
-static void omap_bandgap_writel(struct omap_bandgap *bg_ptr, u32 val, u32 reg)
-{
-	writel(val, bg_ptr->base + reg);
-}
-
-static int omap_bandgap_power(struct omap_bandgap *bg_ptr, bool on)
-{
-	struct temp_sensor_registers *tsr;
-	int i;
-	u32 ctrl;
-
-	if (!OMAP_BANDGAP_HAS(bg_ptr, POWER_SWITCH))
-		return 0;
-
-	for (i = 0; i < bg_ptr->conf->sensor_count; i++) {
-		tsr = bg_ptr->conf->sensors[i].registers;
-		ctrl = omap_bandgap_readl(bg_ptr, tsr->temp_sensor_ctrl);
-		ctrl &= ~tsr->bgap_tempsoff_mask;
-		/* active on 0 */
-		ctrl |= !on << __ffs(tsr->bgap_tempsoff_mask);
-
-		/* write BGAP_TEMPSOFF should be reset to 0 */
-		omap_bandgap_writel(bg_ptr, ctrl, tsr->temp_sensor_ctrl);
-	}
-
-	return 0;
-}
-
-/* This is the Talert handler. Call it only if HAS(TALERT) is set */
-static irqreturn_t talert_irq_handler(int irq, void *data)
-{
-	struct omap_bandgap *bg_ptr = data;
-	struct temp_sensor_registers *tsr;
-	u32 t_hot = 0, t_cold = 0, temp, ctrl;
-	int i;
-
-	bg_ptr = data;
-	/* Read the status of t_hot */
-	for (i = 0; i < bg_ptr->conf->sensor_count; i++) {
-		tsr = bg_ptr->conf->sensors[i].registers;
-		t_hot = omap_bandgap_readl(bg_ptr, tsr->bgap_status);
-		t_hot &= tsr->status_hot_mask;
-
-		/* Read the status of t_cold */
-		t_cold = omap_bandgap_readl(bg_ptr, tsr->bgap_status);
-		t_cold &= tsr->status_cold_mask;
-
-		if (!t_cold && !t_hot)
-			continue;
-
-		ctrl = omap_bandgap_readl(bg_ptr, tsr->bgap_mask_ctrl);
-		/*
-		 * One TALERT interrupt: Two sources
-		 * If the interrupt is due to t_hot then mask t_hot and
-		 * and unmask t_cold else mask t_cold and unmask t_hot
-		 */
-		if (t_hot) {
-			ctrl &= ~tsr->mask_hot_mask;
-			ctrl |= tsr->mask_cold_mask;
-		} else if (t_cold) {
-			ctrl &= ~tsr->mask_cold_mask;
-			ctrl |= tsr->mask_hot_mask;
-		}
-
-		omap_bandgap_writel(bg_ptr, ctrl, tsr->bgap_mask_ctrl);
-
-		dev_dbg(bg_ptr->dev,
-			"%s: IRQ from %s sensor: hotevent %d coldevent %d\n",
-			__func__, bg_ptr->conf->sensors[i].domain,
-			t_hot, t_cold);
-
-		/* read temperature */
-		temp = omap_bandgap_readl(bg_ptr, tsr->temp_sensor_ctrl);
-		temp &= tsr->bgap_dtemp_mask;
-
-		/* report temperature to whom may concern */
-		if (bg_ptr->conf->report_temperature)
-			bg_ptr->conf->report_temperature(bg_ptr, i);
-	}
-
-	return IRQ_HANDLED;
-}
-
-/* This is the Tshut handler. Call it only if HAS(TSHUT) is set */
-static irqreturn_t omap_bandgap_tshut_irq_handler(int irq, void *data)
-{
-	orderly_poweroff(true);
-
-	return IRQ_HANDLED;
-}
-
-static
-int adc_to_temp_conversion(struct omap_bandgap *bg_ptr, int id, int adc_val,
-			   int *t)
-{
-	struct temp_sensor_data *ts_data = bg_ptr->conf->sensors[id].ts_data;
-
-	/* look up for temperature in the table and return the temperature */
-	if (adc_val < ts_data->adc_start_val || adc_val > ts_data->adc_end_val)
-		return -ERANGE;
-
-	*t = bg_ptr->conv_table[adc_val - ts_data->adc_start_val];
-
-	return 0;
-}
-
-static int temp_to_adc_conversion(long temp, struct omap_bandgap *bg_ptr, int i,
-				  int *adc)
-{
-	struct temp_sensor_data *ts_data = bg_ptr->conf->sensors[i].ts_data;
-	int high, low, mid;
-
-	low = 0;
-	high = ts_data->adc_end_val - ts_data->adc_start_val;
-	mid = (high + low) / 2;
-
-	if (temp < bg_ptr->conv_table[low] || temp > bg_ptr->conv_table[high])
-		return -EINVAL;
-
-	while (low < high) {
-		if (temp < bg_ptr->conv_table[mid])
-			high = mid - 1;
-		else
-			low = mid + 1;
-		mid = (low + high) / 2;
-	}
-
-	*adc = ts_data->adc_start_val + low;
-
-	return 0;
-}
-
-/* Talert masks. Call it only if HAS(TALERT) is set */
-static int temp_sensor_unmask_interrupts(struct omap_bandgap *bg_ptr, int id,
-					 u32 t_hot, u32 t_cold)
-{
-	struct temp_sensor_registers *tsr;
-	u32 temp, reg_val;
-
-	/* Read the current on die temperature */
-	tsr = bg_ptr->conf->sensors[id].registers;
-	temp = omap_bandgap_readl(bg_ptr, tsr->temp_sensor_ctrl);
-	temp &= tsr->bgap_dtemp_mask;
-
-	reg_val = omap_bandgap_readl(bg_ptr, tsr->bgap_mask_ctrl);
-	if (temp < t_hot)
-		reg_val |= tsr->mask_hot_mask;
-	else
-		reg_val &= ~tsr->mask_hot_mask;
-
-	if (t_cold < temp)
-		reg_val |= tsr->mask_cold_mask;
-	else
-		reg_val &= ~tsr->mask_cold_mask;
-	omap_bandgap_writel(bg_ptr, reg_val, tsr->bgap_mask_ctrl);
-
-	return 0;
-}
-
-static
-int add_hyst(int adc_val, int hyst_val, struct omap_bandgap *bg_ptr, int i,
-	     u32 *sum)
-{
-	int temp, ret;
-
-	ret = adc_to_temp_conversion(bg_ptr, i, adc_val, &temp);
-	if (ret < 0)
-		return ret;
-
-	temp += hyst_val;
-
-	return temp_to_adc_conversion(temp, bg_ptr, i, sum);
-}
-
-/* Talert Thot threshold. Call it only if HAS(TALERT) is set */
-static
-int temp_sensor_configure_thot(struct omap_bandgap *bg_ptr, int id, int t_hot)
-{
-	struct temp_sensor_data *ts_data = bg_ptr->conf->sensors[id].ts_data;
-	struct temp_sensor_registers *tsr;
-	u32 thresh_val, reg_val;
-	int cold, err = 0;
-
-	tsr = bg_ptr->conf->sensors[id].registers;
-
-	/* obtain the T cold value */
-	thresh_val = omap_bandgap_readl(bg_ptr, tsr->bgap_threshold);
-	cold = (thresh_val & tsr->threshold_tcold_mask) >>
-	    __ffs(tsr->threshold_tcold_mask);
-	if (t_hot <= cold) {
-		/* change the t_cold to t_hot - 5000 millidegrees */
-		err |= add_hyst(t_hot, -ts_data->hyst_val, bg_ptr, id, &cold);
-		/* write the new t_cold value */
-		reg_val = thresh_val & (~tsr->threshold_tcold_mask);
-		reg_val |= cold << __ffs(tsr->threshold_tcold_mask);
-		omap_bandgap_writel(bg_ptr, reg_val, tsr->bgap_threshold);
-		thresh_val = reg_val;
-	}
-
-	/* write the new t_hot value */
-	reg_val = thresh_val & ~tsr->threshold_thot_mask;
-	reg_val |= (t_hot << __ffs(tsr->threshold_thot_mask));
-	omap_bandgap_writel(bg_ptr, reg_val, tsr->bgap_threshold);
-	if (err) {
-		dev_err(bg_ptr->dev, "failed to reprogram thot threshold\n");
-		return -EIO;
-	}
-
-	return temp_sensor_unmask_interrupts(bg_ptr, id, t_hot, cold);
-}
-
-/* Talert Thot and Tcold thresholds. Call it only if HAS(TALERT) is set */
-static
-int temp_sensor_init_talert_thresholds(struct omap_bandgap *bg_ptr, int id,
-				       int t_hot, int t_cold)
-{
-	struct temp_sensor_registers *tsr;
-	u32 reg_val, thresh_val;
-
-	tsr = bg_ptr->conf->sensors[id].registers;
-	thresh_val = omap_bandgap_readl(bg_ptr, tsr->bgap_threshold);
-
-	/* write the new t_cold value */
-	reg_val = thresh_val & ~tsr->threshold_tcold_mask;
-	reg_val |= (t_cold << __ffs(tsr->threshold_tcold_mask));
-	omap_bandgap_writel(bg_ptr, reg_val, tsr->bgap_threshold);
-
-	thresh_val = omap_bandgap_readl(bg_ptr, tsr->bgap_threshold);
-
-	/* write the new t_hot value */
-	reg_val = thresh_val & ~tsr->threshold_thot_mask;
-	reg_val |= (t_hot << __ffs(tsr->threshold_thot_mask));
-	omap_bandgap_writel(bg_ptr, reg_val, tsr->bgap_threshold);
-
-	reg_val = omap_bandgap_readl(bg_ptr, tsr->bgap_mask_ctrl);
-	reg_val |= tsr->mask_hot_mask;
-	reg_val |= tsr->mask_cold_mask;
-	omap_bandgap_writel(bg_ptr, reg_val, tsr->bgap_mask_ctrl);
-
-	return 0;
-}
-
-/* Talert Tcold threshold. Call it only if HAS(TALERT) is set */
-static
-int temp_sensor_configure_tcold(struct omap_bandgap *bg_ptr, int id,
-				int t_cold)
-{
-	struct temp_sensor_data *ts_data = bg_ptr->conf->sensors[id].ts_data;
-	struct temp_sensor_registers *tsr;
-	u32 thresh_val, reg_val;
-	int hot, err = 0;
-
-	tsr = bg_ptr->conf->sensors[id].registers;
-	/* obtain the T cold value */
-	thresh_val = omap_bandgap_readl(bg_ptr, tsr->bgap_threshold);
-	hot = (thresh_val & tsr->threshold_thot_mask) >>
-	    __ffs(tsr->threshold_thot_mask);
-
-	if (t_cold >= hot) {
-		/* change the t_hot to t_cold + 5000 millidegrees */
-		err |= add_hyst(t_cold, ts_data->hyst_val, bg_ptr, id, &hot);
-		/* write the new t_hot value */
-		reg_val = thresh_val & (~tsr->threshold_thot_mask);
-		reg_val |= hot << __ffs(tsr->threshold_thot_mask);
-		omap_bandgap_writel(bg_ptr, reg_val, tsr->bgap_threshold);
-		thresh_val = reg_val;
-	}
-
-	/* write the new t_cold value */
-	reg_val = thresh_val & ~tsr->threshold_tcold_mask;
-	reg_val |= (t_cold << __ffs(tsr->threshold_tcold_mask));
-	omap_bandgap_writel(bg_ptr, reg_val, tsr->bgap_threshold);
-	if (err) {
-		dev_err(bg_ptr->dev, "failed to reprogram tcold threshold\n");
-		return -EIO;
-	}
-
-	return temp_sensor_unmask_interrupts(bg_ptr, id, hot, t_cold);
-}
-
-/* This is Tshut Thot config. Call it only if HAS(TSHUT_CONFIG) is set */
-static int temp_sensor_configure_tshut_hot(struct omap_bandgap *bg_ptr,
-					   int id, int tshut_hot)
-{
-	struct temp_sensor_registers *tsr;
-	u32 reg_val;
-
-	tsr = bg_ptr->conf->sensors[id].registers;
-	reg_val = omap_bandgap_readl(bg_ptr, tsr->tshut_threshold);
-	reg_val &= ~tsr->tshut_hot_mask;
-	reg_val |= tshut_hot << __ffs(tsr->tshut_hot_mask);
-	omap_bandgap_writel(bg_ptr, reg_val, tsr->tshut_threshold);
-
-	return 0;
-}
-
-/* This is Tshut Tcold config. Call it only if HAS(TSHUT_CONFIG) is set */
-static int temp_sensor_configure_tshut_cold(struct omap_bandgap *bg_ptr,
-					    int id, int tshut_cold)
-{
-	struct temp_sensor_registers *tsr;
-	u32 reg_val;
-
-	tsr = bg_ptr->conf->sensors[id].registers;
-	reg_val = omap_bandgap_readl(bg_ptr, tsr->tshut_threshold);
-	reg_val &= ~tsr->tshut_cold_mask;
-	reg_val |= tshut_cold << __ffs(tsr->tshut_cold_mask);
-	omap_bandgap_writel(bg_ptr, reg_val, tsr->tshut_threshold);
-
-	return 0;
-}
-
-/* This is counter config. Call it only if HAS(COUNTER) is set */
-static int configure_temp_sensor_counter(struct omap_bandgap *bg_ptr, int id,
-					 u32 counter)
-{
-	struct temp_sensor_registers *tsr;
-	u32 val;
-
-	tsr = bg_ptr->conf->sensors[id].registers;
-	val = omap_bandgap_readl(bg_ptr, tsr->bgap_counter);
-	val &= ~tsr->counter_mask;
-	val |= counter << __ffs(tsr->counter_mask);
-	omap_bandgap_writel(bg_ptr, val, tsr->bgap_counter);
-
-	return 0;
-}
-
-#define bandgap_is_valid(b)						\
-			(!IS_ERR_OR_NULL(b))
-#define bandgap_is_valid_sensor_id(b, i)				\
-			((i) >= 0 && (i) < (b)->conf->sensor_count)
-static inline int omap_bandgap_validate(struct omap_bandgap *bg_ptr, int id)
-{
-	if (!bandgap_is_valid(bg_ptr)) {
-		pr_err("%s: invalid bandgap pointer\n", __func__);
-		return -EINVAL;
-	}
-
-	if (!bandgap_is_valid_sensor_id(bg_ptr, id)) {
-		dev_err(bg_ptr->dev, "%s: sensor id out of range (%d)\n",
-			__func__, id);
-		return -ERANGE;
-	}
-
-	return 0;
-}
-
-/* Exposed APIs */
-/**
- * omap_bandgap_read_thot() - reads sensor current thot
- * @bg_ptr - pointer to bandgap instance
- * @id - sensor id
- * @thot - resulting current thot value
- *
- * returns 0 on success or the proper error code
- */
-int omap_bandgap_read_thot(struct omap_bandgap *bg_ptr, int id,
-			      int *thot)
-{
-	struct temp_sensor_registers *tsr;
-	u32 temp;
-	int ret;
-
-	ret = omap_bandgap_validate(bg_ptr, id);
-	if (ret)
-		return ret;
-
-	if (!OMAP_BANDGAP_HAS(bg_ptr, TALERT))
-		return -ENOTSUPP;
-
-	tsr = bg_ptr->conf->sensors[id].registers;
-	temp = omap_bandgap_readl(bg_ptr, tsr->bgap_threshold);
-	temp = (temp & tsr->threshold_thot_mask) >>
-		__ffs(tsr->threshold_thot_mask);
-	ret |= adc_to_temp_conversion(bg_ptr, id, temp, &temp);
-	if (ret) {
-		dev_err(bg_ptr->dev, "failed to read thot\n");
-		return -EIO;
-	}
-
-	*thot = temp;
-
-	return 0;
-}
-
-/**
- * omap_bandgap_write_thot() - sets sensor current thot
- * @bg_ptr - pointer to bandgap instance
- * @id - sensor id
- * @val - desired thot value
- *
- * returns 0 on success or the proper error code
- */
-int omap_bandgap_write_thot(struct omap_bandgap *bg_ptr, int id, int val)
-{
-	struct temp_sensor_data *ts_data;
-	struct temp_sensor_registers *tsr;
-	u32 t_hot;
-	int ret;
-
-	ret = omap_bandgap_validate(bg_ptr, id);
-	if (ret)
-		return ret;
-
-	if (!OMAP_BANDGAP_HAS(bg_ptr, TALERT))
-		return -ENOTSUPP;
-
-	ts_data = bg_ptr->conf->sensors[id].ts_data;
-	tsr = bg_ptr->conf->sensors[id].registers;
-
-	if (val < ts_data->min_temp + ts_data->hyst_val)
-		return -EINVAL;
-	ret = temp_to_adc_conversion(val, bg_ptr, id, &t_hot);
-	if (ret < 0)
-		return ret;
-
-	mutex_lock(&bg_ptr->bg_mutex);
-	temp_sensor_configure_thot(bg_ptr, id, t_hot);
-	mutex_unlock(&bg_ptr->bg_mutex);
-
-	return 0;
-}
-
-/**
- * omap_bandgap_read_tcold() - reads sensor current tcold
- * @bg_ptr - pointer to bandgap instance
- * @id - sensor id
- * @tcold - resulting current tcold value
- *
- * returns 0 on success or the proper error code
- */
-int omap_bandgap_read_tcold(struct omap_bandgap *bg_ptr, int id,
-			       int *tcold)
-{
-	struct temp_sensor_registers *tsr;
-	u32 temp;
-	int ret;
-
-	ret = omap_bandgap_validate(bg_ptr, id);
-	if (ret)
-		return ret;
-
-	if (!OMAP_BANDGAP_HAS(bg_ptr, TALERT))
-		return -ENOTSUPP;
-
-	tsr = bg_ptr->conf->sensors[id].registers;
-	temp = omap_bandgap_readl(bg_ptr, tsr->bgap_threshold);
-	temp = (temp & tsr->threshold_tcold_mask)
-	    >> __ffs(tsr->threshold_tcold_mask);
-	ret |= adc_to_temp_conversion(bg_ptr, id, temp, &temp);
-	if (ret)
-		return -EIO;
-
-	*tcold = temp;
-
-	return 0;
-}
-
-/**
- * omap_bandgap_write_tcold() - sets the sensor tcold
- * @bg_ptr - pointer to bandgap instance
- * @id - sensor id
- * @val - desired tcold value
- *
- * returns 0 on success or the proper error code
- */
-int omap_bandgap_write_tcold(struct omap_bandgap *bg_ptr, int id, int val)
-{
-	struct temp_sensor_data *ts_data;
-	struct temp_sensor_registers *tsr;
-	u32 t_cold;
-	int ret;
-
-	ret = omap_bandgap_validate(bg_ptr, id);
-	if (ret)
-		return ret;
-
-	if (!OMAP_BANDGAP_HAS(bg_ptr, TALERT))
-		return -ENOTSUPP;
-
-	ts_data = bg_ptr->conf->sensors[id].ts_data;
-	tsr = bg_ptr->conf->sensors[id].registers;
-	if (val > ts_data->max_temp + ts_data->hyst_val)
-		return -EINVAL;
-
-	ret = temp_to_adc_conversion(val, bg_ptr, id, &t_cold);
-	if (ret < 0)
-		return ret;
-
-	mutex_lock(&bg_ptr->bg_mutex);
-	temp_sensor_configure_tcold(bg_ptr, id, t_cold);
-	mutex_unlock(&bg_ptr->bg_mutex);
-
-	return 0;
-}
-
-/**
- * omap_bandgap_read_update_interval() - read the sensor update interval
- * @bg_ptr - pointer to bandgap instance
- * @id - sensor id
- * @interval - resulting update interval in miliseconds
- *
- * returns 0 on success or the proper error code
- */
-int omap_bandgap_read_update_interval(struct omap_bandgap *bg_ptr, int id,
-					 int *interval)
-{
-	struct temp_sensor_registers *tsr;
-	u32 time;
-	int ret;
-
-	ret = omap_bandgap_validate(bg_ptr, id);
-	if (ret)
-		return ret;
-
-	if (!OMAP_BANDGAP_HAS(bg_ptr, COUNTER))
-		return -ENOTSUPP;
-
-	tsr = bg_ptr->conf->sensors[id].registers;
-	time = omap_bandgap_readl(bg_ptr, tsr->bgap_counter);
-	time = (time & tsr->counter_mask) >> __ffs(tsr->counter_mask);
-	time = time * 1000 / bg_ptr->clk_rate;
-
-	*interval = time;
-
-	return 0;
-}
-
-/**
- * omap_bandgap_write_update_interval() - set the update interval
- * @bg_ptr - pointer to bandgap instance
- * @id - sensor id
- * @interval - desired update interval in miliseconds
- *
- * returns 0 on success or the proper error code
- */
-int omap_bandgap_write_update_interval(struct omap_bandgap *bg_ptr,
-					  int id, u32 interval)
-{
-	int ret = omap_bandgap_validate(bg_ptr, id);
-	if (ret)
-		return ret;
-
-	if (!OMAP_BANDGAP_HAS(bg_ptr, COUNTER))
-		return -ENOTSUPP;
-
-	interval = interval * bg_ptr->clk_rate / 1000;
-	mutex_lock(&bg_ptr->bg_mutex);
-	configure_temp_sensor_counter(bg_ptr, id, interval);
-	mutex_unlock(&bg_ptr->bg_mutex);
-
-	return 0;
-}
-
-/**
- * omap_bandgap_read_temperature() - report current temperature
- * @bg_ptr - pointer to bandgap instance
- * @id - sensor id
- * @temperature - resulting temperature
- *
- * returns 0 on success or the proper error code
- */
-int omap_bandgap_read_temperature(struct omap_bandgap *bg_ptr, int id,
-				     int *temperature)
-{
-	struct temp_sensor_registers *tsr;
-	u32 temp;
-	int ret;
-
-	ret = omap_bandgap_validate(bg_ptr, id);
-	if (ret)
-		return ret;
-
-	tsr = bg_ptr->conf->sensors[id].registers;
-	temp = omap_bandgap_readl(bg_ptr, tsr->temp_sensor_ctrl);
-	temp &= tsr->bgap_dtemp_mask;
-
-	ret |= adc_to_temp_conversion(bg_ptr, id, temp, &temp);
-	if (ret)
-		return -EIO;
-
-	*temperature = temp;
-
-	return 0;
-}
-
-/**
- * omap_bandgap_set_sensor_data() - helper function to store thermal
- * framework related data.
- * @bg_ptr - pointer to bandgap instance
- * @id - sensor id
- * @data - thermal framework related data to be stored
- *
- * returns 0 on success or the proper error code
- */
-int omap_bandgap_set_sensor_data(struct omap_bandgap *bg_ptr, int id,
-				void *data)
-{
-	int ret = omap_bandgap_validate(bg_ptr, id);
-	if (ret)
-		return ret;
-
-	bg_ptr->conf->sensors[id].data = data;
-
-	return 0;
-}
-
-/**
- * omap_bandgap_get_sensor_data() - helper function to get thermal
- * framework related data.
- * @bg_ptr - pointer to bandgap instance
- * @id - sensor id
- *
- * returns data stored by set function with sensor id on success or NULL
- */
-void *omap_bandgap_get_sensor_data(struct omap_bandgap *bg_ptr, int id)
-{
-	int ret = omap_bandgap_validate(bg_ptr, id);
-	if (ret)
-		return ERR_PTR(ret);
-
-	return bg_ptr->conf->sensors[id].data;
-}
-
-static int
-omap_bandgap_force_single_read(struct omap_bandgap *bg_ptr, int id)
-{
-	struct temp_sensor_registers *tsr;
-	u32 temp = 0, counter = 1000;
-
-	tsr = bg_ptr->conf->sensors[id].registers;
-	/* Select single conversion mode */
-	if (OMAP_BANDGAP_HAS(bg_ptr, MODE_CONFIG)) {
-		temp = omap_bandgap_readl(bg_ptr, tsr->bgap_mode_ctrl);
-		temp &= ~(1 << __ffs(tsr->mode_ctrl_mask));
-		omap_bandgap_writel(bg_ptr, temp, tsr->bgap_mode_ctrl);
-	}
-
-	/* Start of Conversion = 1 */
-	temp = omap_bandgap_readl(bg_ptr, tsr->temp_sensor_ctrl);
-	temp |= 1 << __ffs(tsr->bgap_soc_mask);
-	omap_bandgap_writel(bg_ptr, temp, tsr->temp_sensor_ctrl);
-	/* Wait until DTEMP is updated */
-	temp = omap_bandgap_readl(bg_ptr, tsr->temp_sensor_ctrl);
-	temp &= (tsr->bgap_dtemp_mask);
-	while ((temp == 0) && --counter) {
-		temp = omap_bandgap_readl(bg_ptr, tsr->temp_sensor_ctrl);
-		temp &= (tsr->bgap_dtemp_mask);
-	}
-	/* Start of Conversion = 0 */
-	temp = omap_bandgap_readl(bg_ptr, tsr->temp_sensor_ctrl);
-	temp &= ~(1 << __ffs(tsr->bgap_soc_mask));
-	omap_bandgap_writel(bg_ptr, temp, tsr->temp_sensor_ctrl);
-
-	return 0;
-}
-
-/**
- * enable_continuous_mode() - One time enabling of continuous conversion mode
- * @bg_ptr - pointer to scm instance
- *
- * Call this function only if HAS(MODE_CONFIG) is set
- */
-static int enable_continuous_mode(struct omap_bandgap *bg_ptr)
-{
-	struct temp_sensor_registers *tsr;
-	int i;
-	u32 val;
-
-	for (i = 0; i < bg_ptr->conf->sensor_count; i++) {
-		/* Perform a single read just before enabling continuous */
-		omap_bandgap_force_single_read(bg_ptr, i);
-		tsr = bg_ptr->conf->sensors[i].registers;
-		val = omap_bandgap_readl(bg_ptr, tsr->bgap_mode_ctrl);
-		val |= 1 << __ffs(tsr->mode_ctrl_mask);
-		omap_bandgap_writel(bg_ptr, val, tsr->bgap_mode_ctrl);
-	}
-
-	return 0;
-}
-
-static int omap_bandgap_tshut_init(struct omap_bandgap *bg_ptr,
-				      struct platform_device *pdev)
-{
-	int gpio_nr = bg_ptr->tshut_gpio;
-	int status;
-
-	/* Request for gpio_86 line */
-	status = gpio_request(gpio_nr, "tshut");
-	if (status < 0) {
-		dev_err(bg_ptr->dev,
-			"Could not request for TSHUT GPIO:%i\n", 86);
-		return status;
-	}
-	status = gpio_direction_input(gpio_nr);
-	if (status) {
-		dev_err(bg_ptr->dev,
-			"Cannot set input TSHUT GPIO %d\n", gpio_nr);
-		return status;
-	}
-
-	status = request_irq(gpio_to_irq(gpio_nr),
-			     omap_bandgap_tshut_irq_handler,
-			     IRQF_TRIGGER_RISING, "tshut",
-			     NULL);
-	if (status) {
-		gpio_free(gpio_nr);
-		dev_err(bg_ptr->dev, "request irq failed for TSHUT");
-	}
-
-	return 0;
-}
-
-/* Initialization of Talert. Call it only if HAS(TALERT) is set */
-static int omap_bandgap_talert_init(struct omap_bandgap *bg_ptr,
-				       struct platform_device *pdev)
-{
-	int ret;
-
-	bg_ptr->irq = platform_get_irq(pdev, 0);
-	if (bg_ptr->irq < 0) {
-		dev_err(&pdev->dev, "get_irq failed\n");
-		return bg_ptr->irq;
-	}
-	ret = request_threaded_irq(bg_ptr->irq, NULL,
-				   talert_irq_handler,
-				   IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
-				   "talert", bg_ptr);
-	if (ret) {
-		dev_err(&pdev->dev, "Request threaded irq failed.\n");
-		return ret;
-	}
-
-	return 0;
-}
-
-static const struct of_device_id of_omap_bandgap_match[];
-static struct omap_bandgap *omap_bandgap_build(struct platform_device *pdev)
-{
-	struct device_node *node = pdev->dev.of_node;
-	const struct of_device_id *of_id;
-	struct omap_bandgap *bg_ptr;
-	struct resource *res;
-	u32 prop;
-	int i;
-
-	/* just for the sake */
-	if (!node) {
-		dev_err(&pdev->dev, "no platform information available\n");
-		return ERR_PTR(-EINVAL);
-	}
-
-	bg_ptr = devm_kzalloc(&pdev->dev, sizeof(struct omap_bandgap),
-				    GFP_KERNEL);
-	if (!bg_ptr) {
-		dev_err(&pdev->dev, "Unable to allocate mem for driver ref\n");
-		return ERR_PTR(-ENOMEM);
-	}
-
-	of_id = of_match_device(of_omap_bandgap_match, &pdev->dev);
-	if (of_id)
-		bg_ptr->conf = of_id->data;
-
-	i = 0;
-	do {
-		void __iomem *chunk;
-
-		res = platform_get_resource(pdev, IORESOURCE_MEM, i);
-		if (!res)
-			break;
-		chunk = devm_ioremap_resource(&pdev->dev, res);
-		if (i == 0)
-			bg_ptr->base = chunk;
-		if (IS_ERR(chunk))
-			return ERR_CAST(chunk);
-		
-		i++;
-	} while (res);
-
-	if (OMAP_BANDGAP_HAS(bg_ptr, TSHUT)) {
-		if (of_property_read_u32(node, "ti,tshut-gpio", &prop) < 0) {
-			dev_err(&pdev->dev, "missing tshut gpio in device tree\n");
-			return ERR_PTR(-EINVAL);
-		}
-		bg_ptr->tshut_gpio = prop;
-		if (!gpio_is_valid(bg_ptr->tshut_gpio)) {
-			dev_err(&pdev->dev, "invalid gpio for tshut (%d)\n",
-				bg_ptr->tshut_gpio);
-			return ERR_PTR(-EINVAL);
-		}
-	}
-
-	return bg_ptr;
-}
-
-static
-int omap_bandgap_probe(struct platform_device *pdev)
-{
-	struct omap_bandgap *bg_ptr;
-	int clk_rate, ret = 0, i;
-
-	bg_ptr = omap_bandgap_build(pdev);
-	if (IS_ERR_OR_NULL(bg_ptr)) {
-		dev_err(&pdev->dev, "failed to fetch platform data\n");
-		return PTR_ERR(bg_ptr);
-	}
-	bg_ptr->dev = &pdev->dev;
-
-	if (OMAP_BANDGAP_HAS(bg_ptr, TSHUT)) {
-		ret = omap_bandgap_tshut_init(bg_ptr, pdev);
-		if (ret) {
-			dev_err(&pdev->dev,
-				"failed to initialize system tshut IRQ\n");
-			return ret;
-		}
-	}
-
-	bg_ptr->fclock = clk_get(NULL, bg_ptr->conf->fclock_name);
-	ret = IS_ERR_OR_NULL(bg_ptr->fclock);
-	if (ret) {
-		dev_err(&pdev->dev, "failed to request fclock reference\n");
-		goto free_irqs;
-	}
-
-	bg_ptr->div_clk = clk_get(NULL,  bg_ptr->conf->div_ck_name);
-	ret = IS_ERR_OR_NULL(bg_ptr->div_clk);
-	if (ret) {
-		dev_err(&pdev->dev,
-			"failed to request div_ts_ck clock ref\n");
-		goto free_irqs;
-	}
-
-	bg_ptr->conv_table = bg_ptr->conf->conv_table;
-	for (i = 0; i < bg_ptr->conf->sensor_count; i++) {
-		struct temp_sensor_registers *tsr;
-		u32 val;
-
-		tsr = bg_ptr->conf->sensors[i].registers;
-		/*
-		 * check if the efuse has a non-zero value if not
-		 * it is an untrimmed sample and the temperatures
-		 * may not be accurate
-		 */
-		val = omap_bandgap_readl(bg_ptr, tsr->bgap_efuse);
-		if (ret || !val)
-			dev_info(&pdev->dev,
-				 "Non-trimmed BGAP, Temp not accurate\n");
-	}
-
-	clk_rate = clk_round_rate(bg_ptr->div_clk,
-				  bg_ptr->conf->sensors[0].ts_data->max_freq);
-	if (clk_rate < bg_ptr->conf->sensors[0].ts_data->min_freq ||
-	    clk_rate == 0xffffffff) {
-		ret = -ENODEV;
-		dev_err(&pdev->dev, "wrong clock rate (%d)\n", clk_rate);
-		goto put_clks;
-	}
-
-	ret = clk_set_rate(bg_ptr->div_clk, clk_rate);
-	if (ret)
-		dev_err(&pdev->dev, "Cannot re-set clock rate. Continuing\n");
-
-	bg_ptr->clk_rate = clk_rate;
-	clk_enable(bg_ptr->fclock);
-
-	mutex_init(&bg_ptr->bg_mutex);
-	bg_ptr->dev = &pdev->dev;
-	platform_set_drvdata(pdev, bg_ptr);
-
-	omap_bandgap_power(bg_ptr, true);
-
-	/* Set default counter to 1 for now */
-	if (OMAP_BANDGAP_HAS(bg_ptr, COUNTER))
-		for (i = 0; i < bg_ptr->conf->sensor_count; i++)
-			configure_temp_sensor_counter(bg_ptr, i, 1);
-
-	for (i = 0; i < bg_ptr->conf->sensor_count; i++) {
-		struct temp_sensor_data *ts_data;
-
-		ts_data = bg_ptr->conf->sensors[i].ts_data;
-
-		if (OMAP_BANDGAP_HAS(bg_ptr, TALERT))
-			temp_sensor_init_talert_thresholds(bg_ptr, i,
-							   ts_data->t_hot,
-							   ts_data->t_cold);
-		if (OMAP_BANDGAP_HAS(bg_ptr, TSHUT_CONFIG)) {
-			temp_sensor_configure_tshut_hot(bg_ptr, i,
-							ts_data->tshut_hot);
-			temp_sensor_configure_tshut_cold(bg_ptr, i,
-							 ts_data->tshut_cold);
-		}
-	}
-
-	if (OMAP_BANDGAP_HAS(bg_ptr, MODE_CONFIG))
-		enable_continuous_mode(bg_ptr);
-
-	/* Set .250 seconds time as default counter */
-	if (OMAP_BANDGAP_HAS(bg_ptr, COUNTER))
-		for (i = 0; i < bg_ptr->conf->sensor_count; i++)
-			configure_temp_sensor_counter(bg_ptr, i,
-						      bg_ptr->clk_rate / 4);
-
-	/* Every thing is good? Then expose the sensors */
-	for (i = 0; i < bg_ptr->conf->sensor_count; i++) {
-		char *domain;
-
-		if (bg_ptr->conf->sensors[i].register_cooling)
-			bg_ptr->conf->sensors[i].register_cooling(bg_ptr, i);
-
-		domain = bg_ptr->conf->sensors[i].domain;
-		if (bg_ptr->conf->expose_sensor)
-			bg_ptr->conf->expose_sensor(bg_ptr, i, domain);
-	}
-
-	/*
-	 * Enable the Interrupts once everything is set. Otherwise irq handler
-	 * might be called as soon as it is enabled where as rest of framework
-	 * is still getting initialised.
-	 */
-	if (OMAP_BANDGAP_HAS(bg_ptr, TALERT)) {
-		ret = omap_bandgap_talert_init(bg_ptr, pdev);
-		if (ret) {
-			dev_err(&pdev->dev, "failed to initialize Talert IRQ\n");
-			i = bg_ptr->conf->sensor_count;
-			goto disable_clk;
-		}
-	}
-
-	return 0;
-
-disable_clk:
-	clk_disable(bg_ptr->fclock);
-put_clks:
-	clk_put(bg_ptr->fclock);
-	clk_put(bg_ptr->div_clk);
-free_irqs:
-	if (OMAP_BANDGAP_HAS(bg_ptr, TSHUT)) {
-		free_irq(gpio_to_irq(bg_ptr->tshut_gpio), NULL);
-		gpio_free(bg_ptr->tshut_gpio);
-	}
-
-	return ret;
-}
-
-static
-int omap_bandgap_remove(struct platform_device *pdev)
-{
-	struct omap_bandgap *bg_ptr = platform_get_drvdata(pdev);
-	int i;
-
-	/* First thing is to remove sensor interfaces */
-	for (i = 0; i < bg_ptr->conf->sensor_count; i++) {
-		if (bg_ptr->conf->sensors[i].register_cooling)
-			bg_ptr->conf->sensors[i].unregister_cooling(bg_ptr, i);
-
-		if (bg_ptr->conf->remove_sensor)
-			bg_ptr->conf->remove_sensor(bg_ptr, i);
-	}
-
-	omap_bandgap_power(bg_ptr, false);
-
-	clk_disable(bg_ptr->fclock);
-	clk_put(bg_ptr->fclock);
-	clk_put(bg_ptr->div_clk);
-
-	if (OMAP_BANDGAP_HAS(bg_ptr, TALERT))
-		free_irq(bg_ptr->irq, bg_ptr);
-
-	if (OMAP_BANDGAP_HAS(bg_ptr, TSHUT)) {
-		free_irq(gpio_to_irq(bg_ptr->tshut_gpio), NULL);
-		gpio_free(bg_ptr->tshut_gpio);
-	}
-
-	return 0;
-}
-
-#ifdef CONFIG_PM
-static int omap_bandgap_save_ctxt(struct omap_bandgap *bg_ptr)
-{
-	int i;
-
-	for (i = 0; i < bg_ptr->conf->sensor_count; i++) {
-		struct temp_sensor_registers *tsr;
-		struct temp_sensor_regval *rval;
-
-		rval = &bg_ptr->conf->sensors[i].regval;
-		tsr = bg_ptr->conf->sensors[i].registers;
-
-		if (OMAP_BANDGAP_HAS(bg_ptr, MODE_CONFIG))
-			rval->bg_mode_ctrl = omap_bandgap_readl(bg_ptr,
-							tsr->bgap_mode_ctrl);
-		if (OMAP_BANDGAP_HAS(bg_ptr, COUNTER))
-			rval->bg_counter = omap_bandgap_readl(bg_ptr,
-							tsr->bgap_counter);
-		if (OMAP_BANDGAP_HAS(bg_ptr, TALERT)) {
-			rval->bg_threshold = omap_bandgap_readl(bg_ptr,
-							tsr->bgap_threshold);
-			rval->bg_ctrl = omap_bandgap_readl(bg_ptr,
-						   tsr->bgap_mask_ctrl);
-		}
-
-		if (OMAP_BANDGAP_HAS(bg_ptr, TSHUT_CONFIG))
-			rval->tshut_threshold = omap_bandgap_readl(bg_ptr,
-						   tsr->tshut_threshold);
-	}
-
-	return 0;
-}
-
-static int omap_bandgap_restore_ctxt(struct omap_bandgap *bg_ptr)
-{
-	int i;
-
-	for (i = 0; i < bg_ptr->conf->sensor_count; i++) {
-		struct temp_sensor_registers *tsr;
-		struct temp_sensor_regval *rval;
-		u32 val = 0;
-
-		rval = &bg_ptr->conf->sensors[i].regval;
-		tsr = bg_ptr->conf->sensors[i].registers;
-
-		if (OMAP_BANDGAP_HAS(bg_ptr, COUNTER))
-			val = omap_bandgap_readl(bg_ptr, tsr->bgap_counter);
-
-		if (OMAP_BANDGAP_HAS(bg_ptr, TSHUT_CONFIG))
-			omap_bandgap_writel(bg_ptr,
-				rval->tshut_threshold,
-					   tsr->tshut_threshold);
-		/* Force immediate temperature measurement and update
-		 * of the DTEMP field
-		 */
-		omap_bandgap_force_single_read(bg_ptr, i);
-
-		if (OMAP_BANDGAP_HAS(bg_ptr, COUNTER))
-			omap_bandgap_writel(bg_ptr, rval->bg_counter,
-						   tsr->bgap_counter);
-		if (OMAP_BANDGAP_HAS(bg_ptr, MODE_CONFIG))
-			omap_bandgap_writel(bg_ptr, rval->bg_mode_ctrl,
-						   tsr->bgap_mode_ctrl);
-		if (OMAP_BANDGAP_HAS(bg_ptr, TALERT)) {
-			omap_bandgap_writel(bg_ptr,
-						   rval->bg_threshold,
-						   tsr->bgap_threshold);
-			omap_bandgap_writel(bg_ptr, rval->bg_ctrl,
-						   tsr->bgap_mask_ctrl);
-		}
-	}
-
-	return 0;
-}
-
-static int omap_bandgap_suspend(struct device *dev)
-{
-	struct omap_bandgap *bg_ptr = dev_get_drvdata(dev);
-	int err;
-
-	err = omap_bandgap_save_ctxt(bg_ptr);
-	omap_bandgap_power(bg_ptr, false);
-	clk_disable(bg_ptr->fclock);
-
-	return err;
-}
-
-static int omap_bandgap_resume(struct device *dev)
-{
-	struct omap_bandgap *bg_ptr = dev_get_drvdata(dev);
-
-	clk_enable(bg_ptr->fclock);
-	omap_bandgap_power(bg_ptr, true);
-
-	return omap_bandgap_restore_ctxt(bg_ptr);
-}
-static const struct dev_pm_ops omap_bandgap_dev_pm_ops = {
-	SET_SYSTEM_SLEEP_PM_OPS(omap_bandgap_suspend,
-				omap_bandgap_resume)
-};
-
-#define DEV_PM_OPS	(&omap_bandgap_dev_pm_ops)
-#else
-#define DEV_PM_OPS	NULL
-#endif
-
-static const struct of_device_id of_omap_bandgap_match[] = {
-#ifdef CONFIG_OMAP4_THERMAL
-	{
-		.compatible = "ti,omap4430-bandgap",
-		.data = (void *)&omap4430_data,
-	},
-	{
-		.compatible = "ti,omap4460-bandgap",
-		.data = (void *)&omap4460_data,
-	},
-	{
-		.compatible = "ti,omap4470-bandgap",
-		.data = (void *)&omap4470_data,
-	},
-#endif
-#ifdef CONFIG_OMAP5_THERMAL
-	{
-		.compatible = "ti,omap5430-bandgap",
-		.data = (void *)&omap5430_data,
-	},
-#endif
-	/* Sentinel */
-	{ },
-};
-MODULE_DEVICE_TABLE(of, of_omap_bandgap_match);
-
-static struct platform_driver omap_bandgap_sensor_driver = {
-	.probe = omap_bandgap_probe,
-	.remove = omap_bandgap_remove,
-	.driver = {
-			.name = "omap-bandgap",
-			.pm = DEV_PM_OPS,
-			.of_match_table	= of_omap_bandgap_match,
-	},
-};
-
-module_platform_driver(omap_bandgap_sensor_driver);
-
-MODULE_DESCRIPTION("OMAP4+ bandgap temperature sensor driver");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:omap-bandgap");
-MODULE_AUTHOR("Texas Instrument Inc.");
diff --git a/drivers/staging/omap-thermal/omap-bandgap.h b/drivers/staging/omap-thermal/omap-bandgap.h
deleted file mode 100644
index 2bb14bd..0000000
--- a/drivers/staging/omap-thermal/omap-bandgap.h
+++ /dev/null
@@ -1,432 +0,0 @@
-/*
- * OMAP4 Bandgap temperature sensor driver
- *
- * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
- * Contact:
- *   Eduardo Valentin <eduardo.valentin@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_BANDGAP_H
-#define __OMAP_BANDGAP_H
-
-#include <linux/mutex.h>
-#include <linux/types.h>
-#include <linux/err.h>
-
-/* TEMP_SENSOR OMAP4430 */
-#define OMAP4430_BGAP_TSHUT_SHIFT			11
-#define OMAP4430_BGAP_TSHUT_MASK			(1 << 11)
-
-/* TEMP_SENSOR OMAP4430 */
-#define OMAP4430_BGAP_TEMPSOFF_SHIFT			12
-#define OMAP4430_BGAP_TEMPSOFF_MASK			(1 << 12)
-#define OMAP4430_SINGLE_MODE_SHIFT			10
-#define OMAP4430_SINGLE_MODE_MASK			(1 << 10)
-#define OMAP4430_BGAP_TEMP_SENSOR_SOC_SHIFT		9
-#define OMAP4430_BGAP_TEMP_SENSOR_SOC_MASK		(1 << 9)
-#define OMAP4430_BGAP_TEMP_SENSOR_EOCZ_SHIFT		8
-#define OMAP4430_BGAP_TEMP_SENSOR_EOCZ_MASK		(1 << 8)
-#define OMAP4430_BGAP_TEMP_SENSOR_DTEMP_SHIFT		0
-#define OMAP4430_BGAP_TEMP_SENSOR_DTEMP_MASK		(0xff << 0)
-
-#define OMAP4430_ADC_START_VALUE			0
-#define OMAP4430_ADC_END_VALUE				127
-#define OMAP4430_MAX_FREQ				32768
-#define OMAP4430_MIN_FREQ				32768
-#define OMAP4430_MIN_TEMP				-40000
-#define OMAP4430_MAX_TEMP				125000
-#define OMAP4430_HYST_VAL				5000
-
-/* TEMP_SENSOR OMAP4460 */
-#define OMAP4460_BGAP_TEMPSOFF_SHIFT			13
-#define OMAP4460_BGAP_TEMPSOFF_MASK			(1 << 13)
-#define OMAP4460_BGAP_TEMP_SENSOR_SOC_SHIFT		11
-#define OMAP4460_BGAP_TEMP_SENSOR_SOC_MASK		(1 << 11)
-#define OMAP4460_BGAP_TEMP_SENSOR_EOCZ_SHIFT		10
-#define OMAP4460_BGAP_TEMP_SENSOR_EOCZ_MASK		(1 << 10)
-#define OMAP4460_BGAP_TEMP_SENSOR_DTEMP_SHIFT		0
-#define OMAP4460_BGAP_TEMP_SENSOR_DTEMP_MASK		(0x3ff << 0)
-
-/* BANDGAP_CTRL */
-#define OMAP4460_SINGLE_MODE_SHIFT			31
-#define OMAP4460_SINGLE_MODE_MASK			(1 << 31)
-#define OMAP4460_MASK_HOT_SHIFT				1
-#define OMAP4460_MASK_HOT_MASK				(1 << 1)
-#define OMAP4460_MASK_COLD_SHIFT			0
-#define OMAP4460_MASK_COLD_MASK				(1 << 0)
-
-/* BANDGAP_COUNTER */
-#define OMAP4460_COUNTER_SHIFT				0
-#define OMAP4460_COUNTER_MASK				(0xffffff << 0)
-
-/* BANDGAP_THRESHOLD */
-#define OMAP4460_T_HOT_SHIFT				16
-#define OMAP4460_T_HOT_MASK				(0x3ff << 16)
-#define OMAP4460_T_COLD_SHIFT				0
-#define OMAP4460_T_COLD_MASK				(0x3ff << 0)
-
-/* TSHUT_THRESHOLD */
-#define OMAP4460_TSHUT_HOT_SHIFT			16
-#define OMAP4460_TSHUT_HOT_MASK				(0x3ff << 16)
-#define OMAP4460_TSHUT_COLD_SHIFT			0
-#define OMAP4460_TSHUT_COLD_MASK			(0x3ff << 0)
-
-/* BANDGAP_STATUS */
-#define OMAP4460_CLEAN_STOP_SHIFT			3
-#define OMAP4460_CLEAN_STOP_MASK			(1 << 3)
-#define OMAP4460_BGAP_ALERT_SHIFT			2
-#define OMAP4460_BGAP_ALERT_MASK			(1 << 2)
-#define OMAP4460_HOT_FLAG_SHIFT				1
-#define OMAP4460_HOT_FLAG_MASK				(1 << 1)
-#define OMAP4460_COLD_FLAG_SHIFT			0
-#define OMAP4460_COLD_FLAG_MASK				(1 << 0)
-
-/* TEMP_SENSOR OMAP5430 */
-#define OMAP5430_BGAP_TEMP_SENSOR_SOC_SHIFT		12
-#define OMAP5430_BGAP_TEMP_SENSOR_SOC_MASK		(1 << 12)
-#define OMAP5430_BGAP_TEMPSOFF_SHIFT			11
-#define OMAP5430_BGAP_TEMPSOFF_MASK			(1 << 11)
-#define OMAP5430_BGAP_TEMP_SENSOR_EOCZ_SHIFT		10
-#define OMAP5430_BGAP_TEMP_SENSOR_EOCZ_MASK		(1 << 10)
-#define OMAP5430_BGAP_TEMP_SENSOR_DTEMP_SHIFT		0
-#define OMAP5430_BGAP_TEMP_SENSOR_DTEMP_MASK		(0x3ff << 0)
-
-/* BANDGAP_CTRL */
-#define OMAP5430_MASK_HOT_CORE_SHIFT			5
-#define OMAP5430_MASK_HOT_CORE_MASK			(1 << 5)
-#define OMAP5430_MASK_COLD_CORE_SHIFT			4
-#define OMAP5430_MASK_COLD_CORE_MASK			(1 << 4)
-#define OMAP5430_MASK_HOT_MM_SHIFT			3
-#define OMAP5430_MASK_HOT_MM_MASK			(1 << 3)
-#define OMAP5430_MASK_COLD_MM_SHIFT			2
-#define OMAP5430_MASK_COLD_MM_MASK			(1 << 2)
-#define OMAP5430_MASK_HOT_MPU_SHIFT			1
-#define OMAP5430_MASK_HOT_MPU_MASK			(1 << 1)
-#define OMAP5430_MASK_COLD_MPU_SHIFT			0
-#define OMAP5430_MASK_COLD_MPU_MASK			(1 << 0)
-
-/* BANDGAP_COUNTER */
-#define OMAP5430_REPEAT_MODE_SHIFT			31
-#define OMAP5430_REPEAT_MODE_MASK			(1 << 31)
-#define OMAP5430_COUNTER_SHIFT				0
-#define OMAP5430_COUNTER_MASK				(0xffffff << 0)
-
-/* BANDGAP_THRESHOLD */
-#define OMAP5430_T_HOT_SHIFT				16
-#define OMAP5430_T_HOT_MASK				(0x3ff << 16)
-#define OMAP5430_T_COLD_SHIFT				0
-#define OMAP5430_T_COLD_MASK				(0x3ff << 0)
-
-/* TSHUT_THRESHOLD */
-#define OMAP5430_TSHUT_HOT_SHIFT			16
-#define OMAP5430_TSHUT_HOT_MASK				(0x3ff << 16)
-#define OMAP5430_TSHUT_COLD_SHIFT			0
-#define OMAP5430_TSHUT_COLD_MASK			(0x3ff << 0)
-
-/* BANDGAP_STATUS */
-#define OMAP5430_BGAP_ALERT_SHIFT			31
-#define OMAP5430_BGAP_ALERT_MASK			(1 << 31)
-#define OMAP5430_HOT_CORE_FLAG_SHIFT			5
-#define OMAP5430_HOT_CORE_FLAG_MASK			(1 << 5)
-#define OMAP5430_COLD_CORE_FLAG_SHIFT			4
-#define OMAP5430_COLD_CORE_FLAG_MASK			(1 << 4)
-#define OMAP5430_HOT_MM_FLAG_SHIFT			3
-#define OMAP5430_HOT_MM_FLAG_MASK			(1 << 3)
-#define OMAP5430_COLD_MM_FLAG_SHIFT			2
-#define OMAP5430_COLD_MM_FLAG_MASK			(1 << 2)
-#define OMAP5430_HOT_MPU_FLAG_SHIFT			1
-#define OMAP5430_HOT_MPU_FLAG_MASK			(1 << 1)
-#define OMAP5430_COLD_MPU_FLAG_SHIFT			0
-#define OMAP5430_COLD_MPU_FLAG_MASK			(1 << 0)
-
-/* Offsets from the base of temperature sensor registers */
-
-/* 4430 - All goes relative to OPP_BGAP */
-#define OMAP4430_FUSE_OPP_BGAP				0x0
-#define OMAP4430_TEMP_SENSOR_CTRL_OFFSET		0xCC
-
-/* 4460 - All goes relative to OPP_BGAP */
-#define OMAP4460_FUSE_OPP_BGAP				0x0
-#define OMAP4460_TEMP_SENSOR_CTRL_OFFSET		0xCC
-#define OMAP4460_BGAP_CTRL_OFFSET			0x118
-#define OMAP4460_BGAP_COUNTER_OFFSET			0x11C
-#define OMAP4460_BGAP_THRESHOLD_OFFSET			0x120
-#define OMAP4460_BGAP_TSHUT_OFFSET			0x124
-#define OMAP4460_BGAP_STATUS_OFFSET			0x128
-
-/* 5430 - All goes relative to OPP_BGAP_GPU */
-#define OMAP5430_FUSE_OPP_BGAP_GPU			0x0
-#define OMAP5430_TEMP_SENSOR_GPU_OFFSET			0x150
-#define OMAP5430_BGAP_COUNTER_GPU_OFFSET		0x1C0
-#define OMAP5430_BGAP_THRESHOLD_GPU_OFFSET		0x1A8
-#define OMAP5430_BGAP_TSHUT_GPU_OFFSET			0x1B4
-
-#define OMAP5430_FUSE_OPP_BGAP_MPU			0x4
-#define OMAP5430_TEMP_SENSOR_MPU_OFFSET			0x14C
-#define OMAP5430_BGAP_CTRL_OFFSET			0x1A0
-#define OMAP5430_BGAP_COUNTER_MPU_OFFSET		0x1BC
-#define OMAP5430_BGAP_THRESHOLD_MPU_OFFSET		0x1A4
-#define OMAP5430_BGAP_TSHUT_MPU_OFFSET			0x1B0
-#define OMAP5430_BGAP_STATUS_OFFSET			0x1C8
-
-#define OMAP5430_FUSE_OPP_BGAP_CORE			0x8
-#define OMAP5430_TEMP_SENSOR_CORE_OFFSET		0x154
-#define OMAP5430_BGAP_COUNTER_CORE_OFFSET		0x1C4
-#define OMAP5430_BGAP_THRESHOLD_CORE_OFFSET		0x1AC
-#define OMAP5430_BGAP_TSHUT_CORE_OFFSET			0x1B8
-
-#define OMAP4460_TSHUT_HOT				900	/* 122 deg C */
-#define OMAP4460_TSHUT_COLD				895	/* 100 deg C */
-#define OMAP4460_T_HOT					800	/* 73 deg C */
-#define OMAP4460_T_COLD					795	/* 71 deg C */
-#define OMAP4460_MAX_FREQ				1500000
-#define OMAP4460_MIN_FREQ				1000000
-#define OMAP4460_MIN_TEMP				-40000
-#define OMAP4460_MAX_TEMP				123000
-#define OMAP4460_HYST_VAL				5000
-#define OMAP4460_ADC_START_VALUE			530
-#define OMAP4460_ADC_END_VALUE				932
-
-#define OMAP5430_MPU_TSHUT_HOT				915
-#define OMAP5430_MPU_TSHUT_COLD				900
-#define OMAP5430_MPU_T_HOT				800
-#define OMAP5430_MPU_T_COLD				795
-#define OMAP5430_MPU_MAX_FREQ				1500000
-#define OMAP5430_MPU_MIN_FREQ				1000000
-#define OMAP5430_MPU_MIN_TEMP				-40000
-#define OMAP5430_MPU_MAX_TEMP				125000
-#define OMAP5430_MPU_HYST_VAL				5000
-#define OMAP5430_ADC_START_VALUE			532
-#define OMAP5430_ADC_END_VALUE				934
-
-
-#define OMAP5430_GPU_TSHUT_HOT				915
-#define OMAP5430_GPU_TSHUT_COLD				900
-#define OMAP5430_GPU_T_HOT				800
-#define OMAP5430_GPU_T_COLD				795
-#define OMAP5430_GPU_MAX_FREQ				1500000
-#define OMAP5430_GPU_MIN_FREQ				1000000
-#define OMAP5430_GPU_MIN_TEMP				-40000
-#define OMAP5430_GPU_MAX_TEMP				125000
-#define OMAP5430_GPU_HYST_VAL				5000
-
-#define OMAP5430_CORE_TSHUT_HOT				915
-#define OMAP5430_CORE_TSHUT_COLD			900
-#define OMAP5430_CORE_T_HOT				800
-#define OMAP5430_CORE_T_COLD				795
-#define OMAP5430_CORE_MAX_FREQ				1500000
-#define OMAP5430_CORE_MIN_FREQ				1000000
-#define OMAP5430_CORE_MIN_TEMP				-40000
-#define OMAP5430_CORE_MAX_TEMP				125000
-#define OMAP5430_CORE_HYST_VAL				5000
-
-/**
- * The register offsets and bit fields might change across
- * OMAP versions hence populating them in this structure.
- */
-
-struct temp_sensor_registers {
-	u32	temp_sensor_ctrl;
-	u32	bgap_tempsoff_mask;
-	u32	bgap_soc_mask;
-	u32	bgap_eocz_mask;
-	u32	bgap_dtemp_mask;
-
-	u32	bgap_mask_ctrl;
-	u32	mask_hot_mask;
-	u32	mask_cold_mask;
-
-	u32	bgap_mode_ctrl;
-	u32	mode_ctrl_mask;
-
-	u32	bgap_counter;
-	u32	counter_mask;
-
-	u32	bgap_threshold;
-	u32	threshold_thot_mask;
-	u32	threshold_tcold_mask;
-
-	u32	tshut_threshold;
-	u32	tshut_hot_mask;
-	u32	tshut_cold_mask;
-
-	u32	bgap_status;
-	u32	status_clean_stop_mask;
-	u32	status_bgap_alert_mask;
-	u32	status_hot_mask;
-	u32	status_cold_mask;
-
-	u32	bgap_efuse;
-};
-
-/**
- * The thresholds and limits for temperature sensors.
- */
-struct temp_sensor_data {
-	u32	tshut_hot;
-	u32	tshut_cold;
-	u32	t_hot;
-	u32	t_cold;
-	u32	min_freq;
-	u32	max_freq;
-	int     max_temp;
-	int     min_temp;
-	int     hyst_val;
-	u32     adc_start_val;
-	u32     adc_end_val;
-	u32     update_int1;
-	u32     update_int2;
-};
-
-struct omap_bandgap_data;
-
-/**
- * struct omap_bandgap - bandgap device structure
- * @dev: device pointer
- * @conf: platform data with sensor data
- * @fclock: pointer to functional clock of temperature sensor
- * @div_clk: pointer to parent clock of temperature sensor fclk
- * @conv_table: Pointer to adc to temperature conversion table
- * @bg_mutex: Mutex for sysfs, irq and PM
- * @irq: MPU Irq number for thermal alert
- * @tshut_gpio: GPIO where Tshut signal is routed
- * @clk_rate: Holds current clock rate
- */
-struct omap_bandgap {
-	struct device			*dev;
-	void __iomem			*base;
-	struct omap_bandgap_data	*conf;
-	struct clk			*fclock;
-	struct clk			*div_clk;
-	const int			*conv_table;
-	struct mutex			bg_mutex; /* Mutex for irq and PM */
-	int				irq;
-	int				tshut_gpio;
-	u32				clk_rate;
-};
-
-/**
- * struct temp_sensor_regval - temperature sensor register values
- * @bg_mode_ctrl: temp sensor control register value
- * @bg_ctrl: bandgap ctrl register value
- * @bg_counter: bandgap counter value
- * @bg_threshold: bandgap threshold register value
- * @tshut_threshold: bandgap tshut register value
- */
-struct temp_sensor_regval {
-	u32			bg_mode_ctrl;
-	u32			bg_ctrl;
-	u32			bg_counter;
-	u32			bg_threshold;
-	u32			tshut_threshold;
-};
-
-/**
- * struct omap_temp_sensor - bandgap temperature sensor platform data
- * @ts_data: pointer to struct with thresholds, limits of temperature sensor
- * @registers: pointer to the list of register offsets and bitfields
- * @regval: temperature sensor register values
- * @domain: the name of the domain where the sensor is located
- * @cooling_data: description on how the zone should be cooled off.
- * @slope: sensor gradient slope info for hotspot extrapolation
- * @const: sensor gradient const info for hotspot extrapolation
- * @slope_pcb: sensor gradient slope info for hotspot extrapolation
- *             with no external influence
- * @const_pcb: sensor gradient const info for hotspot extrapolation
- *             with no external influence
- * @data: private data
- * @register_cooling: function to describe how this sensor is going to be cooled
- * @unregister_cooling: function to release cooling data
- */
-struct omap_temp_sensor {
-	struct temp_sensor_data		*ts_data;
-	struct temp_sensor_registers	*registers;
-	struct temp_sensor_regval	regval;
-	char				*domain;
-	/* for hotspot extrapolation */
-	const int			slope;
-	const int			constant;
-	const int			slope_pcb;
-	const int			constant_pcb;
-	void				*data;
-	int (*register_cooling)(struct omap_bandgap *bg_ptr, int id);
-	int (*unregister_cooling)(struct omap_bandgap *bg_ptr, int id);
-};
-
-/**
- * struct omap_bandgap_data - bandgap platform data structure
- * @features: a bitwise flag set to describe the device features
- * @conv_table: Pointer to adc to temperature conversion table
- * @fclock_name: clock name of the functional clock
- * @div_ck_nme: clock name of the clock divisor
- * @sensor_count: count of temperature sensor device in scm
- * @sensors: array of sensors present in this bandgap instance
- * @expose_sensor: callback to export sensor to thermal API
- */
-struct omap_bandgap_data {
-#define OMAP_BANDGAP_FEATURE_TSHUT		(1 << 0)
-#define OMAP_BANDGAP_FEATURE_TSHUT_CONFIG	(1 << 1)
-#define OMAP_BANDGAP_FEATURE_TALERT		(1 << 2)
-#define OMAP_BANDGAP_FEATURE_MODE_CONFIG	(1 << 3)
-#define OMAP_BANDGAP_FEATURE_COUNTER		(1 << 4)
-#define OMAP_BANDGAP_FEATURE_POWER_SWITCH	(1 << 5)
-#define OMAP_BANDGAP_HAS(b, f)			\
-			((b)->conf->features & OMAP_BANDGAP_FEATURE_ ## f)
-	unsigned int			features;
-	const int			*conv_table;
-	char				*fclock_name;
-	char				*div_ck_name;
-	int				sensor_count;
-	int (*report_temperature)(struct omap_bandgap *bg_ptr, int id);
-	int (*expose_sensor)(struct omap_bandgap *bg_ptr, int id, char *domain);
-	int (*remove_sensor)(struct omap_bandgap *bg_ptr, int id);
-
-	/* this needs to be at the end */
-	struct omap_temp_sensor		sensors[];
-};
-
-int omap_bandgap_read_thot(struct omap_bandgap *bg_ptr, int id, int *thot);
-int omap_bandgap_write_thot(struct omap_bandgap *bg_ptr, int id, int val);
-int omap_bandgap_read_tcold(struct omap_bandgap *bg_ptr, int id, int *tcold);
-int omap_bandgap_write_tcold(struct omap_bandgap *bg_ptr, int id, int val);
-int omap_bandgap_read_update_interval(struct omap_bandgap *bg_ptr, int id,
-				      int *interval);
-int omap_bandgap_write_update_interval(struct omap_bandgap *bg_ptr, int id,
-				       u32 interval);
-int omap_bandgap_read_temperature(struct omap_bandgap *bg_ptr, int id,
-				  int *temperature);
-int omap_bandgap_set_sensor_data(struct omap_bandgap *bg_ptr, int id,
-				 void *data);
-void *omap_bandgap_get_sensor_data(struct omap_bandgap *bg_ptr, int id);
-
-#ifdef CONFIG_OMAP4_THERMAL
-extern const struct omap_bandgap_data omap4430_data;
-extern const struct omap_bandgap_data omap4460_data;
-extern const struct omap_bandgap_data omap4470_data;
-#else
-#define omap4430_data					NULL
-#define omap4460_data					NULL
-#define omap4470_data					NULL
-#endif
-
-#ifdef CONFIG_OMAP5_THERMAL
-extern const struct omap_bandgap_data omap5430_data;
-#else
-#define omap5430_data					NULL
-#endif
-
-#endif
diff --git a/drivers/staging/omap-thermal/omap-thermal-common.c b/drivers/staging/omap-thermal/omap-thermal-common.c
deleted file mode 100644
index 79a55aa..0000000
--- a/drivers/staging/omap-thermal/omap-thermal-common.c
+++ /dev/null
@@ -1,338 +0,0 @@
-/*
- * OMAP thermal driver interface
- *
- * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
- * Contact:
- *   Eduardo Valentin <eduardo.valentin@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/device.h>
-#include <linux/err.h>
-#include <linux/mutex.h>
-#include <linux/gfp.h>
-#include <linux/kernel.h>
-#include <linux/workqueue.h>
-#include <linux/thermal.h>
-#include <linux/cpufreq.h>
-#include <linux/cpumask.h>
-#include <linux/cpu_cooling.h>
-
-#include "omap-thermal.h"
-#include "omap-bandgap.h"
-
-/* common data structures */
-struct omap_thermal_data {
-	struct thermal_zone_device *omap_thermal;
-	struct thermal_cooling_device *cool_dev;
-	struct omap_bandgap *bg_ptr;
-	enum thermal_device_mode mode;
-	struct work_struct thermal_wq;
-	int sensor_id;
-};
-
-static void omap_thermal_work(struct work_struct *work)
-{
-	struct omap_thermal_data *data = container_of(work,
-					struct omap_thermal_data, thermal_wq);
-
-	thermal_zone_device_update(data->omap_thermal);
-
-	dev_dbg(&data->omap_thermal->device, "updated thermal zone %s\n",
-		data->omap_thermal->type);
-}
-
-/**
- * omap_thermal_hotspot_temperature - returns sensor extrapolated temperature
- * @t:	omap sensor temperature
- * @s:	omap sensor slope value
- * @c:	omap sensor const value
- */
-static inline int omap_thermal_hotspot_temperature(int t, int s, int c)
-{
-	int delta = t * s / 1000 + c;
-
-	if (delta < 0)
-		delta = 0;
-
-	return t + delta;
-}
-
-/* thermal zone ops */
-/* Get temperature callback function for thermal zone*/
-static inline int omap_thermal_get_temp(struct thermal_zone_device *thermal,
-					 unsigned long *temp)
-{
-	struct omap_thermal_data *data = thermal->devdata;
-	struct omap_bandgap *bg_ptr;
-	struct omap_temp_sensor *s;
-	int ret, tmp, pcb_temp, slope, constant;
-
-	if (!data)
-		return 0;
-
-	bg_ptr = data->bg_ptr;
-	s = &bg_ptr->conf->sensors[data->sensor_id];
-
-	ret = omap_bandgap_read_temperature(bg_ptr, data->sensor_id, &tmp);
-	if (ret)
-		return ret;
-
-	pcb_temp = 0;
-	/* TODO: Introduce pcb temperature lookup */
-	/* In case pcb zone is available, use the extrapolation rule with it */
-	if (pcb_temp) {
-		tmp -= pcb_temp;
-		slope = s->slope_pcb;
-		constant = s->constant_pcb;
-	} else {
-		slope = s->slope;
-		constant = s->constant;
-	}
-	*temp = omap_thermal_hotspot_temperature(tmp, slope, constant);
-
-	return ret;
-}
-
-/* Bind callback functions for thermal zone */
-static int omap_thermal_bind(struct thermal_zone_device *thermal,
-			      struct thermal_cooling_device *cdev)
-{
-	struct omap_thermal_data *data = thermal->devdata;
-	int id;
-
-	if (IS_ERR_OR_NULL(data))
-		return -ENODEV;
-
-	/* check if this is the cooling device we registered */
-	if (data->cool_dev != cdev)
-		return 0;
-
-	id = data->sensor_id;
-
-	/* TODO: bind with min and max states */
-	/* Simple thing, two trips, one passive another critical */
-	return thermal_zone_bind_cooling_device(thermal, 0, cdev,
-						THERMAL_NO_LIMIT,
-						THERMAL_NO_LIMIT);
-}
-
-/* Unbind callback functions for thermal zone */
-static int omap_thermal_unbind(struct thermal_zone_device *thermal,
-				struct thermal_cooling_device *cdev)
-{
-	struct omap_thermal_data *data = thermal->devdata;
-
-	if (IS_ERR_OR_NULL(data))
-		return -ENODEV;
-
-	/* check if this is the cooling device we registered */
-	if (data->cool_dev != cdev)
-		return 0;
-
-	/* Simple thing, two trips, one passive another critical */
-	return thermal_zone_unbind_cooling_device(thermal, 0, cdev);
-}
-
-/* Get mode callback functions for thermal zone */
-static int omap_thermal_get_mode(struct thermal_zone_device *thermal,
-				  enum thermal_device_mode *mode)
-{
-	struct omap_thermal_data *data = thermal->devdata;
-
-	if (data)
-		*mode = data->mode;
-
-	return 0;
-}
-
-/* Set mode callback functions for thermal zone */
-static int omap_thermal_set_mode(struct thermal_zone_device *thermal,
-				  enum thermal_device_mode mode)
-{
-	struct omap_thermal_data *data = thermal->devdata;
-
-	if (!data->omap_thermal) {
-		dev_notice(&thermal->device, "thermal zone not registered\n");
-		return 0;
-	}
-
-	mutex_lock(&data->omap_thermal->lock);
-
-	if (mode == THERMAL_DEVICE_ENABLED)
-		data->omap_thermal->polling_delay = FAST_TEMP_MONITORING_RATE;
-	else
-		data->omap_thermal->polling_delay = 0;
-
-	mutex_unlock(&data->omap_thermal->lock);
-
-	data->mode = mode;
-	thermal_zone_device_update(data->omap_thermal);
-	dev_dbg(&thermal->device, "thermal polling set for duration=%d msec\n",
-		data->omap_thermal->polling_delay);
-
-	return 0;
-}
-
-/* Get trip type callback functions for thermal zone */
-static int omap_thermal_get_trip_type(struct thermal_zone_device *thermal,
-				       int trip, enum thermal_trip_type *type)
-{
-	if (!omap_thermal_is_valid_trip(trip))
-		return -EINVAL;
-
-	if (trip + 1 == OMAP_TRIP_NUMBER)
-		*type = THERMAL_TRIP_CRITICAL;
-	else
-		*type = THERMAL_TRIP_PASSIVE;
-
-	return 0;
-}
-
-/* Get trip temperature callback functions for thermal zone */
-static int omap_thermal_get_trip_temp(struct thermal_zone_device *thermal,
-				       int trip, unsigned long *temp)
-{
-	if (!omap_thermal_is_valid_trip(trip))
-		return -EINVAL;
-
-	*temp = omap_thermal_get_trip_value(trip);
-
-	return 0;
-}
-
-/* Get critical temperature callback functions for thermal zone */
-static int omap_thermal_get_crit_temp(struct thermal_zone_device *thermal,
-				       unsigned long *temp)
-{
-	/* shutdown zone */
-	return omap_thermal_get_trip_temp(thermal, OMAP_TRIP_NUMBER - 1, temp);
-}
-
-static struct thermal_zone_device_ops omap_thermal_ops = {
-	.get_temp = omap_thermal_get_temp,
-	/* TODO: add .get_trend */
-	.bind = omap_thermal_bind,
-	.unbind = omap_thermal_unbind,
-	.get_mode = omap_thermal_get_mode,
-	.set_mode = omap_thermal_set_mode,
-	.get_trip_type = omap_thermal_get_trip_type,
-	.get_trip_temp = omap_thermal_get_trip_temp,
-	.get_crit_temp = omap_thermal_get_crit_temp,
-};
-
-static struct omap_thermal_data
-*omap_thermal_build_data(struct omap_bandgap *bg_ptr, int id)
-{
-	struct omap_thermal_data *data;
-
-	data = devm_kzalloc(bg_ptr->dev, sizeof(*data), GFP_KERNEL);
-	if (!data) {
-		dev_err(bg_ptr->dev, "kzalloc fail\n");
-		return NULL;
-	}
-	data->sensor_id = id;
-	data->bg_ptr = bg_ptr;
-	data->mode = THERMAL_DEVICE_ENABLED;
-	INIT_WORK(&data->thermal_wq, omap_thermal_work);
-
-	return data;
-}
-
-int omap_thermal_expose_sensor(struct omap_bandgap *bg_ptr, int id,
-			       char *domain)
-{
-	struct omap_thermal_data *data;
-
-	data = omap_bandgap_get_sensor_data(bg_ptr, id);
-
-	if (IS_ERR(data))
-		data = omap_thermal_build_data(bg_ptr, id);
-
-	if (!data)
-		return -EINVAL;
-
-	/* TODO: remove TC1 TC2 */
-	/* Create thermal zone */
-	data->omap_thermal = thermal_zone_device_register(domain,
-				OMAP_TRIP_NUMBER, 0, data, &omap_thermal_ops,
-				NULL, FAST_TEMP_MONITORING_RATE,
-				FAST_TEMP_MONITORING_RATE);
-	if (IS_ERR_OR_NULL(data->omap_thermal)) {
-		dev_err(bg_ptr->dev, "thermal zone device is NULL\n");
-		return PTR_ERR(data->omap_thermal);
-	}
-	data->omap_thermal->polling_delay = FAST_TEMP_MONITORING_RATE;
-	omap_bandgap_set_sensor_data(bg_ptr, id, data);
-
-	return 0;
-}
-
-int omap_thermal_remove_sensor(struct omap_bandgap *bg_ptr, int id)
-{
-	struct omap_thermal_data *data;
-
-	data = omap_bandgap_get_sensor_data(bg_ptr, id);
-
-	thermal_zone_device_unregister(data->omap_thermal);
-
-	return 0;
-}
-
-int omap_thermal_report_sensor_temperature(struct omap_bandgap *bg_ptr, int id)
-{
-	struct omap_thermal_data *data;
-
-	data = omap_bandgap_get_sensor_data(bg_ptr, id);
-
-	schedule_work(&data->thermal_wq);
-
-	return 0;
-}
-
-int omap_thermal_register_cpu_cooling(struct omap_bandgap *bg_ptr, int id)
-{
-	struct omap_thermal_data *data;
-
-	data = omap_bandgap_get_sensor_data(bg_ptr, id);
-	if (IS_ERR(data))
-		data = omap_thermal_build_data(bg_ptr, id);
-
-	if (!data)
-		return -EINVAL;
-
-	/* Register cooling device */
-	data->cool_dev = cpufreq_cooling_register(cpu_present_mask);
-	if (IS_ERR_OR_NULL(data->cool_dev)) {
-		dev_err(bg_ptr->dev,
-			"Failed to register cpufreq cooling device\n");
-		return PTR_ERR(data->cool_dev);
-	}
-	omap_bandgap_set_sensor_data(bg_ptr, id, data);
-
-	return 0;
-}
-
-int omap_thermal_unregister_cpu_cooling(struct omap_bandgap *bg_ptr, int id)
-{
-	struct omap_thermal_data *data;
-
-	data = omap_bandgap_get_sensor_data(bg_ptr, id);
-	cpufreq_cooling_unregister(data->cool_dev);
-
-	return 0;
-}
diff --git a/drivers/staging/omap-thermal/omap-thermal.h b/drivers/staging/omap-thermal/omap-thermal.h
deleted file mode 100644
index 0dd2184..0000000
--- a/drivers/staging/omap-thermal/omap-thermal.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * OMAP thermal definitions
- *
- * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
- * Contact:
- *   Eduardo Valentin <eduardo.valentin@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_THERMAL_H
-#define __OMAP_THERMAL_H
-
-#include "omap-bandgap.h"
-
-/* sensors gradient and offsets */
-#define OMAP_GRADIENT_SLOPE_4460				348
-#define OMAP_GRADIENT_CONST_4460				-9301
-#define OMAP_GRADIENT_SLOPE_4470				308
-#define OMAP_GRADIENT_CONST_4470				-7896
-
-#define OMAP_GRADIENT_SLOPE_5430_CPU				196
-#define OMAP_GRADIENT_CONST_5430_CPU				-6822
-#define OMAP_GRADIENT_SLOPE_5430_GPU				64
-#define OMAP_GRADIENT_CONST_5430_GPU				978
-
-/* PCB sensor calculation constants */
-#define OMAP_GRADIENT_SLOPE_W_PCB_4460				1142
-#define OMAP_GRADIENT_CONST_W_PCB_4460				-393
-#define OMAP_GRADIENT_SLOPE_W_PCB_4470				1063
-#define OMAP_GRADIENT_CONST_W_PCB_4470				-477
-
-#define OMAP_GRADIENT_SLOPE_W_PCB_5430_CPU			469
-#define OMAP_GRADIENT_CONST_W_PCB_5430_CPU			-1272
-#define OMAP_GRADIENT_SLOPE_W_PCB_5430_GPU			378
-#define OMAP_GRADIENT_CONST_W_PCB_5430_GPU			154
-
-/* trip points of interest in milicelsius (at hotspot level) */
-#define OMAP_TRIP_COLD						100000
-#define OMAP_TRIP_HOT						110000
-#define OMAP_TRIP_SHUTDOWN					125000
-#define OMAP_TRIP_NUMBER					2
-#define OMAP_TRIP_STEP							\
-	((OMAP_TRIP_SHUTDOWN - OMAP_TRIP_HOT) / (OMAP_TRIP_NUMBER - 1))
-
-/* Update rates */
-#define FAST_TEMP_MONITORING_RATE				250
-
-/* helper macros */
-/**
- * omap_thermal_get_trip_value - returns trip temperature based on index
- * @i:	trip index
- */
-#define omap_thermal_get_trip_value(i)					\
-	(OMAP_TRIP_HOT + ((i) * OMAP_TRIP_STEP))
-
-/**
- * omap_thermal_is_valid_trip - check for trip index
- * @i:	trip index
- */
-#define omap_thermal_is_valid_trip(trip)				\
-	((trip) >= 0 && (trip) < OMAP_TRIP_NUMBER)
-
-#ifdef CONFIG_OMAP_THERMAL
-int omap_thermal_expose_sensor(struct omap_bandgap *bg_ptr, int id,
-			       char *domain);
-int omap_thermal_remove_sensor(struct omap_bandgap *bg_ptr, int id);
-int omap_thermal_register_cpu_cooling(struct omap_bandgap *bg_ptr, int id);
-int omap_thermal_unregister_cpu_cooling(struct omap_bandgap *bg_ptr, int id);
-#else
-static inline
-int omap_thermal_expose_sensor(struct omap_bandgap *bg_ptr, int id,
-			       char *domain)
-{
-	return 0;
-}
-
-static inline
-int omap_thermal_remove_sensor(struct omap_bandgap *bg_ptr, int id)
-{
-	return 0;
-}
-
-static inline
-int omap_thermal_register_cpu_cooling(struct omap_bandgap *bg_ptr, int id)
-{
-	return 0;
-}
-
-static inline
-int omap_thermal_unregister_cpu_cooling(struct omap_bandgap *bg_ptr, int id)
-{
-	return 0;
-}
-#endif
-#endif
diff --git a/drivers/staging/omap-thermal/omap4-thermal.c b/drivers/staging/omap-thermal/omap4-thermal.c
deleted file mode 100644
index 04c02b6..0000000
--- a/drivers/staging/omap-thermal/omap4-thermal.c
+++ /dev/null
@@ -1,259 +0,0 @@
-/*
- * OMAP4 thermal driver.
- *
- * Copyright (C) 2011-2012 Texas Instruments Inc.
- * Contact:
- *	Eduardo Valentin <eduardo.valentin@ti.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 "omap-thermal.h"
-#include "omap-bandgap.h"
-
-/*
- * OMAP4430 has one instance of thermal sensor for MPU
- * need to describe the individual bit fields
- */
-static struct temp_sensor_registers
-omap4430_mpu_temp_sensor_registers = {
-	.temp_sensor_ctrl = OMAP4430_TEMP_SENSOR_CTRL_OFFSET,
-	.bgap_tempsoff_mask = OMAP4430_BGAP_TEMPSOFF_MASK,
-	.bgap_soc_mask = OMAP4430_BGAP_TEMP_SENSOR_SOC_MASK,
-	.bgap_eocz_mask = OMAP4430_BGAP_TEMP_SENSOR_EOCZ_MASK,
-	.bgap_dtemp_mask = OMAP4430_BGAP_TEMP_SENSOR_DTEMP_MASK,
-
-	.bgap_mode_ctrl = OMAP4430_TEMP_SENSOR_CTRL_OFFSET,
-	.mode_ctrl_mask = OMAP4430_SINGLE_MODE_MASK,
-
-	.bgap_efuse = OMAP4430_FUSE_OPP_BGAP,
-};
-
-/* Thresholds and limits for OMAP4430 MPU temperature sensor */
-static struct temp_sensor_data omap4430_mpu_temp_sensor_data = {
-	.min_freq = OMAP4430_MIN_FREQ,
-	.max_freq = OMAP4430_MAX_FREQ,
-	.max_temp = OMAP4430_MAX_TEMP,
-	.min_temp = OMAP4430_MIN_TEMP,
-	.hyst_val = OMAP4430_HYST_VAL,
-	.adc_start_val = OMAP4430_ADC_START_VALUE,
-	.adc_end_val = OMAP4430_ADC_END_VALUE,
-};
-
-/*
- * Temperature values in milli degree celsius
- * ADC code values from 530 to 923
- */
-static const int
-omap4430_adc_to_temp[OMAP4430_ADC_END_VALUE - OMAP4430_ADC_START_VALUE + 1] = {
-	-38000, -35000, -34000, -32000, -30000, -28000, -26000, -24000, -22000,
-	-20000, -18000, -17000, -15000, -13000, -12000, -10000, -8000, -6000,
-	-5000, -3000, -1000, 0, 2000, 3000, 5000, 6000, 8000, 10000, 12000,
-	13000, 15000, 17000, 19000, 21000, 23000, 25000, 27000, 28000, 30000,
-	32000, 33000, 35000, 37000, 38000, 40000, 42000, 43000, 45000, 47000,
-	48000, 50000, 52000, 53000, 55000, 57000, 58000, 60000, 62000, 64000,
-	66000, 68000, 70000, 71000, 73000, 75000, 77000, 78000, 80000, 82000,
-	83000, 85000, 87000, 88000, 90000, 92000, 93000, 95000, 97000, 98000,
-	100000, 102000, 103000, 105000, 107000, 109000, 111000, 113000, 115000,
-	117000, 118000, 120000, 122000, 123000,
-};
-
-/* OMAP4430 data */
-const struct omap_bandgap_data omap4430_data = {
-	.features = OMAP_BANDGAP_FEATURE_MODE_CONFIG |
-			OMAP_BANDGAP_FEATURE_POWER_SWITCH,
-	.fclock_name = "bandgap_fclk",
-	.div_ck_name = "bandgap_fclk",
-	.conv_table = omap4430_adc_to_temp,
-	.expose_sensor = omap_thermal_expose_sensor,
-	.remove_sensor = omap_thermal_remove_sensor,
-	.sensors = {
-		{
-		.registers = &omap4430_mpu_temp_sensor_registers,
-		.ts_data = &omap4430_mpu_temp_sensor_data,
-		.domain = "cpu",
-		.slope = 0,
-		.constant = 20000,
-		.slope_pcb = 0,
-		.constant_pcb = 20000,
-		.register_cooling = omap_thermal_register_cpu_cooling,
-		.unregister_cooling = omap_thermal_unregister_cpu_cooling,
-		},
-	},
-	.sensor_count = 1,
-};
-/*
- * OMAP4460 has one instance of thermal sensor for MPU
- * need to describe the individual bit fields
- */
-static struct temp_sensor_registers
-omap4460_mpu_temp_sensor_registers = {
-	.temp_sensor_ctrl = OMAP4460_TEMP_SENSOR_CTRL_OFFSET,
-	.bgap_tempsoff_mask = OMAP4460_BGAP_TEMPSOFF_MASK,
-	.bgap_soc_mask = OMAP4460_BGAP_TEMP_SENSOR_SOC_MASK,
-	.bgap_eocz_mask = OMAP4460_BGAP_TEMP_SENSOR_EOCZ_MASK,
-	.bgap_dtemp_mask = OMAP4460_BGAP_TEMP_SENSOR_DTEMP_MASK,
-
-	.bgap_mask_ctrl = OMAP4460_BGAP_CTRL_OFFSET,
-	.mask_hot_mask = OMAP4460_MASK_HOT_MASK,
-	.mask_cold_mask = OMAP4460_MASK_COLD_MASK,
-
-	.bgap_mode_ctrl = OMAP4460_BGAP_CTRL_OFFSET,
-	.mode_ctrl_mask = OMAP4460_SINGLE_MODE_MASK,
-
-	.bgap_counter = OMAP4460_BGAP_COUNTER_OFFSET,
-	.counter_mask = OMAP4460_COUNTER_MASK,
-
-	.bgap_threshold = OMAP4460_BGAP_THRESHOLD_OFFSET,
-	.threshold_thot_mask = OMAP4460_T_HOT_MASK,
-	.threshold_tcold_mask = OMAP4460_T_COLD_MASK,
-
-	.tshut_threshold = OMAP4460_BGAP_TSHUT_OFFSET,
-	.tshut_hot_mask = OMAP4460_TSHUT_HOT_MASK,
-	.tshut_cold_mask = OMAP4460_TSHUT_COLD_MASK,
-
-	.bgap_status = OMAP4460_BGAP_STATUS_OFFSET,
-	.status_clean_stop_mask = OMAP4460_CLEAN_STOP_MASK,
-	.status_bgap_alert_mask = OMAP4460_BGAP_ALERT_MASK,
-	.status_hot_mask = OMAP4460_HOT_FLAG_MASK,
-	.status_cold_mask = OMAP4460_COLD_FLAG_MASK,
-
-	.bgap_efuse = OMAP4460_FUSE_OPP_BGAP,
-};
-
-/* Thresholds and limits for OMAP4460 MPU temperature sensor */
-static struct temp_sensor_data omap4460_mpu_temp_sensor_data = {
-	.tshut_hot = OMAP4460_TSHUT_HOT,
-	.tshut_cold = OMAP4460_TSHUT_COLD,
-	.t_hot = OMAP4460_T_HOT,
-	.t_cold = OMAP4460_T_COLD,
-	.min_freq = OMAP4460_MIN_FREQ,
-	.max_freq = OMAP4460_MAX_FREQ,
-	.max_temp = OMAP4460_MAX_TEMP,
-	.min_temp = OMAP4460_MIN_TEMP,
-	.hyst_val = OMAP4460_HYST_VAL,
-	.adc_start_val = OMAP4460_ADC_START_VALUE,
-	.adc_end_val = OMAP4460_ADC_END_VALUE,
-	.update_int1 = 1000,
-	.update_int2 = 2000,
-};
-
-/*
- * Temperature values in milli degree celsius
- * ADC code values from 530 to 923
- */
-static const int
-omap4460_adc_to_temp[OMAP4460_ADC_END_VALUE - OMAP4460_ADC_START_VALUE + 1] = {
-	-40000, -40000, -40000, -40000, -39800, -39400, -39000, -38600, -38200,
-	-37800, -37300, -36800, -36400, -36000, -35600, -35200, -34800,
-	-34300, -33800, -33400, -33000, -32600, -32200, -31800, -31300,
-	-30800, -30400, -30000, -29600, -29200, -28700, -28200, -27800,
-	-27400, -27000, -26600, -26200, -25700, -25200, -24800, -24400,
-	-24000, -23600, -23200, -22700, -22200, -21800, -21400, -21000,
-	-20600, -20200, -19700, -19200, -18800, -18400, -18000, -17600,
-	-17200, -16700, -16200, -15800, -15400, -15000, -14600, -14200,
-	-13700, -13200, -12800, -12400, -12000, -11600, -11200, -10700,
-	-10200, -9800, -9400, -9000, -8600, -8200, -7700, -7200, -6800,
-	-6400, -6000, -5600, -5200, -4800, -4300, -3800, -3400, -3000,
-	-2600, -2200, -1800, -1300, -800, -400, 0, 400, 800, 1200, 1600,
-	2100, 2600, 3000, 3400, 3800, 4200, 4600, 5100, 5600, 6000, 6400,
-	6800, 7200, 7600, 8000, 8500, 9000, 9400, 9800, 10200, 10600, 11000,
-	11400, 11900, 12400, 12800, 13200, 13600, 14000, 14400, 14800,
-	15300, 15800, 16200, 16600, 17000, 17400, 17800, 18200, 18700,
-	19200, 19600, 20000, 20400, 20800, 21200, 21600, 22100, 22600,
-	23000, 23400, 23800, 24200, 24600, 25000, 25400, 25900, 26400,
-	26800, 27200, 27600, 28000, 28400, 28800, 29300, 29800, 30200,
-	30600, 31000, 31400, 31800, 32200, 32600, 33100, 33600, 34000,
-	34400, 34800, 35200, 35600, 36000, 36400, 36800, 37300, 37800,
-	38200, 38600, 39000, 39400, 39800, 40200, 40600, 41100, 41600,
-	42000, 42400, 42800, 43200, 43600, 44000, 44400, 44800, 45300,
-	45800, 46200, 46600, 47000, 47400, 47800, 48200, 48600, 49000,
-	49500, 50000, 50400, 50800, 51200, 51600, 52000, 52400, 52800,
-	53200, 53700, 54200, 54600, 55000, 55400, 55800, 56200, 56600,
-	57000, 57400, 57800, 58200, 58700, 59200, 59600, 60000, 60400,
-	60800, 61200, 61600, 62000, 62400, 62800, 63300, 63800, 64200,
-	64600, 65000, 65400, 65800, 66200, 66600, 67000, 67400, 67800,
-	68200, 68700, 69200, 69600, 70000, 70400, 70800, 71200, 71600,
-	72000, 72400, 72800, 73200, 73600, 74100, 74600, 75000, 75400,
-	75800, 76200, 76600, 77000, 77400, 77800, 78200, 78600, 79000,
-	79400, 79800, 80300, 80800, 81200, 81600, 82000, 82400, 82800,
-	83200, 83600, 84000, 84400, 84800, 85200, 85600, 86000, 86400,
-	86800, 87300, 87800, 88200, 88600, 89000, 89400, 89800, 90200,
-	90600, 91000, 91400, 91800, 92200, 92600, 93000, 93400, 93800,
-	94200, 94600, 95000, 95500, 96000, 96400, 96800, 97200, 97600,
-	98000, 98400, 98800, 99200, 99600, 100000, 100400, 100800, 101200,
-	101600, 102000, 102400, 102800, 103200, 103600, 104000, 104400,
-	104800, 105200, 105600, 106100, 106600, 107000, 107400, 107800,
-	108200, 108600, 109000, 109400, 109800, 110200, 110600, 111000,
-	111400, 111800, 112200, 112600, 113000, 113400, 113800, 114200,
-	114600, 115000, 115400, 115800, 116200, 116600, 117000, 117400,
-	117800, 118200, 118600, 119000, 119400, 119800, 120200, 120600,
-	121000, 121400, 121800, 122200, 122600, 123000, 123400, 123800, 124200,
-	124600, 124900, 125000, 125000, 125000, 125000
-};
-
-/* OMAP4460 data */
-const struct omap_bandgap_data omap4460_data = {
-	.features = OMAP_BANDGAP_FEATURE_TSHUT |
-			OMAP_BANDGAP_FEATURE_TSHUT_CONFIG |
-			OMAP_BANDGAP_FEATURE_TALERT |
-			OMAP_BANDGAP_FEATURE_MODE_CONFIG |
-			OMAP_BANDGAP_FEATURE_POWER_SWITCH |
-			OMAP_BANDGAP_FEATURE_COUNTER,
-	.fclock_name = "bandgap_ts_fclk",
-	.div_ck_name = "div_ts_ck",
-	.conv_table = omap4460_adc_to_temp,
-	.expose_sensor = omap_thermal_expose_sensor,
-	.remove_sensor = omap_thermal_remove_sensor,
-	.sensors = {
-		{
-		.registers = &omap4460_mpu_temp_sensor_registers,
-		.ts_data = &omap4460_mpu_temp_sensor_data,
-		.domain = "cpu",
-		.slope = OMAP_GRADIENT_SLOPE_4460,
-		.constant = OMAP_GRADIENT_CONST_4460,
-		.slope_pcb = OMAP_GRADIENT_SLOPE_W_PCB_4460,
-		.constant_pcb = OMAP_GRADIENT_CONST_W_PCB_4460,
-		.register_cooling = omap_thermal_register_cpu_cooling,
-		.unregister_cooling = omap_thermal_unregister_cpu_cooling,
-		},
-	},
-	.sensor_count = 1,
-};
-
-/* OMAP4470 data */
-const struct omap_bandgap_data omap4470_data = {
-	.features = OMAP_BANDGAP_FEATURE_TSHUT |
-			OMAP_BANDGAP_FEATURE_TSHUT_CONFIG |
-			OMAP_BANDGAP_FEATURE_TALERT |
-			OMAP_BANDGAP_FEATURE_MODE_CONFIG |
-			OMAP_BANDGAP_FEATURE_POWER_SWITCH |
-			OMAP_BANDGAP_FEATURE_COUNTER,
-	.fclock_name = "bandgap_ts_fclk",
-	.div_ck_name = "div_ts_ck",
-	.conv_table = omap4460_adc_to_temp,
-	.expose_sensor = omap_thermal_expose_sensor,
-	.remove_sensor = omap_thermal_remove_sensor,
-	.sensors = {
-		{
-		.registers = &omap4460_mpu_temp_sensor_registers,
-		.ts_data = &omap4460_mpu_temp_sensor_data,
-		.domain = "cpu",
-		.slope = OMAP_GRADIENT_SLOPE_4470,
-		.constant = OMAP_GRADIENT_CONST_4470,
-		.slope_pcb = OMAP_GRADIENT_SLOPE_W_PCB_4470,
-		.constant_pcb = OMAP_GRADIENT_CONST_W_PCB_4470,
-		.register_cooling = omap_thermal_register_cpu_cooling,
-		.unregister_cooling = omap_thermal_unregister_cpu_cooling,
-		},
-	},
-	.sensor_count = 1,
-};
diff --git a/drivers/staging/omap-thermal/omap5-thermal.c b/drivers/staging/omap-thermal/omap5-thermal.c
deleted file mode 100644
index 2f3a498..0000000
--- a/drivers/staging/omap-thermal/omap5-thermal.c
+++ /dev/null
@@ -1,297 +0,0 @@
-/*
- * OMAP5 thermal driver.
- *
- * Copyright (C) 2011-2012 Texas Instruments Inc.
- * Contact:
- *	Eduardo Valentin <eduardo.valentin@ti.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 "omap-bandgap.h"
-#include "omap-thermal.h"
-
-/*
- * omap5430 has one instance of thermal sensor for MPU
- * need to describe the individual bit fields
- */
-static struct temp_sensor_registers
-omap5430_mpu_temp_sensor_registers = {
-	.temp_sensor_ctrl = OMAP5430_TEMP_SENSOR_MPU_OFFSET,
-	.bgap_tempsoff_mask = OMAP5430_BGAP_TEMPSOFF_MASK,
-	.bgap_soc_mask = OMAP5430_BGAP_TEMP_SENSOR_SOC_MASK,
-	.bgap_eocz_mask = OMAP5430_BGAP_TEMP_SENSOR_EOCZ_MASK,
-	.bgap_dtemp_mask = OMAP5430_BGAP_TEMP_SENSOR_DTEMP_MASK,
-
-	.bgap_mask_ctrl = OMAP5430_BGAP_CTRL_OFFSET,
-	.mask_hot_mask = OMAP5430_MASK_HOT_MPU_MASK,
-	.mask_cold_mask = OMAP5430_MASK_COLD_MPU_MASK,
-
-	.bgap_mode_ctrl = OMAP5430_BGAP_COUNTER_MPU_OFFSET,
-	.mode_ctrl_mask = OMAP5430_REPEAT_MODE_MASK,
-
-	.bgap_counter = OMAP5430_BGAP_COUNTER_MPU_OFFSET,
-	.counter_mask = OMAP5430_COUNTER_MASK,
-
-	.bgap_threshold = OMAP5430_BGAP_THRESHOLD_MPU_OFFSET,
-	.threshold_thot_mask = OMAP5430_T_HOT_MASK,
-	.threshold_tcold_mask = OMAP5430_T_COLD_MASK,
-
-	.tshut_threshold = OMAP5430_BGAP_TSHUT_MPU_OFFSET,
-	.tshut_hot_mask = OMAP5430_TSHUT_HOT_MASK,
-	.tshut_cold_mask = OMAP5430_TSHUT_COLD_MASK,
-
-	.bgap_status = OMAP5430_BGAP_STATUS_OFFSET,
-	.status_clean_stop_mask = 0x0,
-	.status_bgap_alert_mask = OMAP5430_BGAP_ALERT_MASK,
-	.status_hot_mask = OMAP5430_HOT_MPU_FLAG_MASK,
-	.status_cold_mask = OMAP5430_COLD_MPU_FLAG_MASK,
-
-	.bgap_efuse = OMAP5430_FUSE_OPP_BGAP_MPU,
-};
-
-/*
- * omap5430 has one instance of thermal sensor for GPU
- * need to describe the individual bit fields
- */
-static struct temp_sensor_registers
-omap5430_gpu_temp_sensor_registers = {
-	.temp_sensor_ctrl = OMAP5430_TEMP_SENSOR_GPU_OFFSET,
-	.bgap_tempsoff_mask = OMAP5430_BGAP_TEMPSOFF_MASK,
-	.bgap_soc_mask = OMAP5430_BGAP_TEMP_SENSOR_SOC_MASK,
-	.bgap_eocz_mask = OMAP5430_BGAP_TEMP_SENSOR_EOCZ_MASK,
-	.bgap_dtemp_mask = OMAP5430_BGAP_TEMP_SENSOR_DTEMP_MASK,
-
-	.bgap_mask_ctrl = OMAP5430_BGAP_CTRL_OFFSET,
-	.mask_hot_mask = OMAP5430_MASK_HOT_MM_MASK,
-	.mask_cold_mask = OMAP5430_MASK_COLD_MM_MASK,
-
-	.bgap_mode_ctrl = OMAP5430_BGAP_COUNTER_GPU_OFFSET,
-	.mode_ctrl_mask = OMAP5430_REPEAT_MODE_MASK,
-
-	.bgap_counter = OMAP5430_BGAP_COUNTER_GPU_OFFSET,
-	.counter_mask = OMAP5430_COUNTER_MASK,
-
-	.bgap_threshold = OMAP5430_BGAP_THRESHOLD_GPU_OFFSET,
-	.threshold_thot_mask = OMAP5430_T_HOT_MASK,
-	.threshold_tcold_mask = OMAP5430_T_COLD_MASK,
-
-	.tshut_threshold = OMAP5430_BGAP_TSHUT_GPU_OFFSET,
-	.tshut_hot_mask = OMAP5430_TSHUT_HOT_MASK,
-	.tshut_cold_mask = OMAP5430_TSHUT_COLD_MASK,
-
-	.bgap_status = OMAP5430_BGAP_STATUS_OFFSET,
-	.status_clean_stop_mask = 0x0,
-	.status_bgap_alert_mask = OMAP5430_BGAP_ALERT_MASK,
-	.status_hot_mask = OMAP5430_HOT_MM_FLAG_MASK,
-	.status_cold_mask = OMAP5430_COLD_MM_FLAG_MASK,
-
-	.bgap_efuse = OMAP5430_FUSE_OPP_BGAP_GPU,
-};
-
-/*
- * omap5430 has one instance of thermal sensor for CORE
- * need to describe the individual bit fields
- */
-static struct temp_sensor_registers
-omap5430_core_temp_sensor_registers = {
-	.temp_sensor_ctrl = OMAP5430_TEMP_SENSOR_CORE_OFFSET,
-	.bgap_tempsoff_mask = OMAP5430_BGAP_TEMPSOFF_MASK,
-	.bgap_soc_mask = OMAP5430_BGAP_TEMP_SENSOR_SOC_MASK,
-	.bgap_eocz_mask = OMAP5430_BGAP_TEMP_SENSOR_EOCZ_MASK,
-	.bgap_dtemp_mask = OMAP5430_BGAP_TEMP_SENSOR_DTEMP_MASK,
-
-	.bgap_mask_ctrl = OMAP5430_BGAP_CTRL_OFFSET,
-	.mask_hot_mask = OMAP5430_MASK_HOT_CORE_MASK,
-	.mask_cold_mask = OMAP5430_MASK_COLD_CORE_MASK,
-
-	.bgap_mode_ctrl = OMAP5430_BGAP_COUNTER_CORE_OFFSET,
-	.mode_ctrl_mask = OMAP5430_REPEAT_MODE_MASK,
-
-	.bgap_counter = OMAP5430_BGAP_COUNTER_CORE_OFFSET,
-	.counter_mask = OMAP5430_COUNTER_MASK,
-
-	.bgap_threshold = OMAP5430_BGAP_THRESHOLD_CORE_OFFSET,
-	.threshold_thot_mask = OMAP5430_T_HOT_MASK,
-	.threshold_tcold_mask = OMAP5430_T_COLD_MASK,
-
-	.tshut_threshold = OMAP5430_BGAP_TSHUT_CORE_OFFSET,
-	.tshut_hot_mask = OMAP5430_TSHUT_HOT_MASK,
-	.tshut_cold_mask = OMAP5430_TSHUT_COLD_MASK,
-
-	.bgap_status = OMAP5430_BGAP_STATUS_OFFSET,
-	.status_clean_stop_mask = 0x0,
-	.status_bgap_alert_mask = OMAP5430_BGAP_ALERT_MASK,
-	.status_hot_mask = OMAP5430_HOT_CORE_FLAG_MASK,
-	.status_cold_mask = OMAP5430_COLD_CORE_FLAG_MASK,
-
-	.bgap_efuse = OMAP5430_FUSE_OPP_BGAP_CORE,
-};
-
-/* Thresholds and limits for OMAP5430 MPU temperature sensor */
-static struct temp_sensor_data omap5430_mpu_temp_sensor_data = {
-	.tshut_hot = OMAP5430_MPU_TSHUT_HOT,
-	.tshut_cold = OMAP5430_MPU_TSHUT_COLD,
-	.t_hot = OMAP5430_MPU_T_HOT,
-	.t_cold = OMAP5430_MPU_T_COLD,
-	.min_freq = OMAP5430_MPU_MIN_FREQ,
-	.max_freq = OMAP5430_MPU_MAX_FREQ,
-	.max_temp = OMAP5430_MPU_MAX_TEMP,
-	.min_temp = OMAP5430_MPU_MIN_TEMP,
-	.hyst_val = OMAP5430_MPU_HYST_VAL,
-	.adc_start_val = OMAP5430_ADC_START_VALUE,
-	.adc_end_val = OMAP5430_ADC_END_VALUE,
-	.update_int1 = 1000,
-	.update_int2 = 2000,
-};
-
-/* Thresholds and limits for OMAP5430 GPU temperature sensor */
-static struct temp_sensor_data omap5430_gpu_temp_sensor_data = {
-	.tshut_hot = OMAP5430_GPU_TSHUT_HOT,
-	.tshut_cold = OMAP5430_GPU_TSHUT_COLD,
-	.t_hot = OMAP5430_GPU_T_HOT,
-	.t_cold = OMAP5430_GPU_T_COLD,
-	.min_freq = OMAP5430_GPU_MIN_FREQ,
-	.max_freq = OMAP5430_GPU_MAX_FREQ,
-	.max_temp = OMAP5430_GPU_MAX_TEMP,
-	.min_temp = OMAP5430_GPU_MIN_TEMP,
-	.hyst_val = OMAP5430_GPU_HYST_VAL,
-	.adc_start_val = OMAP5430_ADC_START_VALUE,
-	.adc_end_val = OMAP5430_ADC_END_VALUE,
-	.update_int1 = 1000,
-	.update_int2 = 2000,
-};
-
-/* Thresholds and limits for OMAP5430 CORE temperature sensor */
-static struct temp_sensor_data omap5430_core_temp_sensor_data = {
-	.tshut_hot = OMAP5430_CORE_TSHUT_HOT,
-	.tshut_cold = OMAP5430_CORE_TSHUT_COLD,
-	.t_hot = OMAP5430_CORE_T_HOT,
-	.t_cold = OMAP5430_CORE_T_COLD,
-	.min_freq = OMAP5430_CORE_MIN_FREQ,
-	.max_freq = OMAP5430_CORE_MAX_FREQ,
-	.max_temp = OMAP5430_CORE_MAX_TEMP,
-	.min_temp = OMAP5430_CORE_MIN_TEMP,
-	.hyst_val = OMAP5430_CORE_HYST_VAL,
-	.adc_start_val = OMAP5430_ADC_START_VALUE,
-	.adc_end_val = OMAP5430_ADC_END_VALUE,
-	.update_int1 = 1000,
-	.update_int2 = 2000,
-};
-
-static const int
-omap5430_adc_to_temp[OMAP5430_ADC_END_VALUE - OMAP5430_ADC_START_VALUE + 1] = {
-	-40000, -40000, -40000, -40000, -39800, -39400, -39000, -38600,
-	-38200, -37800, -37300, -36800,
-	-36400, -36000, -35600, -35200, -34800, -34300, -33800, -33400, -33000,
-	-32600,
-	-32200, -31800, -31300, -30800, -30400, -30000, -29600, -29200, -28700,
-	-28200, -27800, -27400, -27000, -26600, -26200, -25700, -25200, -24800,
-	-24400, -24000, -23600, -23200, -22700, -22200, -21800, -21400, -21000,
-	-20600, -20200, -19700, -19200, -9300, -18400, -18000, -17600, -17200,
-	-16700, -16200, -15800, -15400, -15000, -14600, -14200, -13700, -13200,
-	-12800, -12400, -12000, -11600, -11200, -10700, -10200, -9800, -9400,
-	-9000,
-	-8600, -8200, -7700, -7200, -6800, -6400, -6000, -5600, -5200, -4800,
-	-4300,
-	-3800, -3400, -3000, -2600, -2200, -1800, -1300, -800, -400, 0, 400,
-	800,
-	1200, 1600, 2100, 2600, 3000, 3400, 3800, 4200, 4600, 5100, 5600, 6000,
-	6400, 6800, 7200, 7600, 8000, 8500, 9000, 9400, 9800, 10200, 10800,
-	11100,
-	11400, 11900, 12400, 12800, 13200, 13600, 14000, 14400, 14800, 15300,
-	15800,
-	16200, 16600, 17000, 17400, 17800, 18200, 18700, 19200, 19600, 20000,
-	20400,
-	20800, 21200, 21600, 22100, 22600, 23000, 23400, 23800, 24200, 24600,
-	25000,
-	25400, 25900, 26400, 26800, 27200, 27600, 28000, 28400, 28800, 29300,
-	29800,
-	30200, 30600, 31000, 31400, 31800, 32200, 32600, 33100, 33600, 34000,
-	34400,
-	34800, 35200, 35600, 36000, 36400, 36800, 37300, 37800, 38200, 38600,
-	39000,
-	39400, 39800, 40200, 40600, 41100, 41600, 42000, 42400, 42800, 43200,
-	43600,
-	44000, 44400, 44800, 45300, 45800, 46200, 46600, 47000, 47400, 47800,
-	48200,
-	48600, 49000, 49500, 50000, 50400, 50800, 51200, 51600, 52000, 52400,
-	52800,
-	53200, 53700, 54200, 54600, 55000, 55400, 55800, 56200, 56600, 57000,
-	57400,
-	57800, 58200, 58700, 59200, 59600, 60000, 60400, 60800, 61200, 61600,
-	62000,
-	62400, 62800, 63300, 63800, 64200, 64600, 65000, 65400, 65800, 66200,
-	66600,
-	67000, 67400, 67800, 68200, 68700, 69200, 69600, 70000, 70400, 70800,
-	71200,
-	71600, 72000, 72400, 72800, 73200, 73600, 74100, 74600, 75000, 75400,
-	75800,
-	76200, 76600, 77000, 77400, 77800, 78200, 78600, 79000, 79400, 79800,
-	80300,
-	80800, 81200, 81600, 82000, 82400, 82800, 83200, 83600, 84000, 84400,
-	84800,
-	85200, 85600, 86000, 86400, 86800, 87300, 87800, 88200, 88600, 89000,
-	89400,
-	89800, 90200, 90600, 91000, 91400, 91800, 92200, 92600, 93000, 93400,
-	93800,
-	94200, 94600, 95000, 95500, 96000, 96400, 96800, 97200, 97600, 98000,
-	98400,
-	98800, 99200, 99600, 100000, 100400, 100800, 101200, 101600, 102000,
-	102400,
-	102800, 103200, 103600, 104000, 104400, 104800, 105200, 105600, 106100,
-	106600, 107000, 107400, 107800, 108200, 108600, 109000, 109400, 109800,
-	110200, 110600, 111000, 111400, 111800, 112200, 112600, 113000, 113400,
-	113800, 114200, 114600, 115000, 115400, 115800, 116200, 116600, 117000,
-	117400, 117800, 118200, 118600, 119000, 119400, 119800, 120200, 120600,
-	121000, 121400, 121800, 122200, 122600, 123000, 123400, 123800, 124200,
-	124600, 124900, 125000, 125000, 125000, 125000,
-};
-
-const struct omap_bandgap_data omap5430_data = {
-	.features = OMAP_BANDGAP_FEATURE_TSHUT_CONFIG |
-			OMAP_BANDGAP_FEATURE_TALERT |
-			OMAP_BANDGAP_FEATURE_MODE_CONFIG |
-			OMAP_BANDGAP_FEATURE_COUNTER,
-	.fclock_name = "ts_clk_div_ck",
-	.div_ck_name = "ts_clk_div_ck",
-	.conv_table = omap5430_adc_to_temp,
-	.expose_sensor = omap_thermal_expose_sensor,
-	.remove_sensor = omap_thermal_remove_sensor,
-	.sensors = {
-		{
-		.registers = &omap5430_mpu_temp_sensor_registers,
-		.ts_data = &omap5430_mpu_temp_sensor_data,
-		.domain = "cpu",
-		.register_cooling = omap_thermal_register_cpu_cooling,
-		.unregister_cooling = omap_thermal_unregister_cpu_cooling,
-		.slope = OMAP_GRADIENT_SLOPE_5430_CPU,
-		.constant = OMAP_GRADIENT_CONST_5430_CPU,
-		.slope_pcb = OMAP_GRADIENT_SLOPE_W_PCB_5430_CPU,
-		.constant_pcb = OMAP_GRADIENT_CONST_W_PCB_5430_CPU,
-		},
-		{
-		.registers = &omap5430_gpu_temp_sensor_registers,
-		.ts_data = &omap5430_gpu_temp_sensor_data,
-		.domain = "gpu",
-		.slope = OMAP_GRADIENT_SLOPE_5430_GPU,
-		.constant = OMAP_GRADIENT_CONST_5430_GPU,
-		.slope_pcb = OMAP_GRADIENT_SLOPE_W_PCB_5430_GPU,
-		.constant_pcb = OMAP_GRADIENT_CONST_W_PCB_5430_GPU,
-		},
-		{
-		.registers = &omap5430_core_temp_sensor_registers,
-		.ts_data = &omap5430_core_temp_sensor_data,
-		.domain = "core",
-		},
-	},
-	.sensor_count = 3,
-};
diff --git a/drivers/staging/omap-thermal/omap_bandgap.txt b/drivers/staging/omap-thermal/omap_bandgap.txt
deleted file mode 100644
index 6008a14..0000000
--- a/drivers/staging/omap-thermal/omap_bandgap.txt
+++ /dev/null
@@ -1,30 +0,0 @@
-* Texas Instrument OMAP SCM bandgap bindings
-
-In the System Control Module, OMAP supplies a voltage reference
-and a temperature sensor feature that are gathered in the band
-gap voltage and temperature sensor (VBGAPTS) module. The band
-gap provides current and voltage reference for its internal
-circuits and other analog IP blocks. The analog-to-digital
-converter (ADC) produces an output value that is proportional
-to the silicon temperature.
-
-Required properties:
-- compatible : Should be:
-  - "ti,omap4460-control-bandgap" : for OMAP4460 bandgap
-  - "ti,omap5430-control-bandgap" : for OMAP5430 bandgap
-- interrupts : this entry should indicate which interrupt line
-the talert signal is routed to;
-Specific:
-- ti,tshut-gpio : this entry should be used to inform which GPIO
-line the tshut signal is routed to;
-
-Example:
-
-bandgap {
-	reg = <0x4a002260 0x4
-		0x4a00232C 0x4
-		0x4a002378 0x18>;
-	compatible = "ti,omap4460-control-bandgap";
-	interrupts = <0 126 4>; /* talert */
-	ti,tshut-gpio = <86>;
-};
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_debug.c b/drivers/staging/rtl8192e/rtl8192e/rtl_debug.c
index c19b14c..a35af16 100644
--- a/drivers/staging/rtl8192e/rtl8192e/rtl_debug.c
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_debug.c
@@ -809,7 +809,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(DRV_NAME, S_IFDIR, init_net.proc_net);
+	rtl8192_proc = proc_mkdir(DRV_NAME, init_net.proc_net);
 }
 
 
@@ -862,9 +862,7 @@ void rtl8192_proc_init_one(struct net_device *dev)
 	struct proc_dir_entry *e;
 	struct r8192_priv *priv = (struct r8192_priv *)rtllib_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);
diff --git a/drivers/staging/rtl8192e/rtllib_module.c b/drivers/staging/rtl8192e/rtllib_module.c
index f9dae95..84ea721 100644
--- a/drivers/staging/rtl8192e/rtllib_module.c
+++ b/drivers/staging/rtl8192e/rtllib_module.c
@@ -208,61 +208,51 @@ static int debug = \
 			    ;
 static struct proc_dir_entry *rtllib_proc;
 
-static int show_debug_level(char *page, char **start, off_t offset,
-			    int count, int *eof, void *data)
+static int show_debug_level(struct seq_file *m, void *v)
 {
-	return snprintf(page, count, "0x%08X\n", rtllib_debug_level);
+	return seq_printf(m, "0x%08X\n", rtllib_debug_level);
 }
 
-static int store_debug_level(struct file *file, const char __user *buffer,
-			     unsigned long count, void *data)
+static ssize_t write_debug_level(struct file *file, const char __user *buffer,
+			     size_t count, loff_t *ppos)
 {
-	char buf[] = "0x00000000";
-	unsigned long len = min((unsigned long)sizeof(buf) - 1, count);
-	char *p = (char *)buf;
 	unsigned long val;
+	int err = kstrtoul_from_user(buffer, count, 0, &val);
+	if (err)
+		return err;
+	rtllib_debug_level = val;
+	return count;
+}
 
-	if (copy_from_user(buf, buffer, len))
-		return count;
-	buf[len] = 0;
-	if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') {
-		p++;
-		if (p[0] == 'x' || p[0] == 'X')
-			p++;
-		val = simple_strtoul(p, &p, 16);
-	} else
-		val = simple_strtoul(p, &p, 10);
-	if (p == buf)
-		printk(KERN_INFO DRV_NAME
-		       ": %s is not in hex or decimal form.\n", buf);
-	else
-		rtllib_debug_level = val;
-
-	return strnlen(buf, count);
+static int open_debug_level(struct inode *inode, struct file *file)
+{
+	return single_open(file, show_debug_level, NULL);
 }
 
+static const struct file_operations fops = {
+	.open = open_debug_level,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.write = write_debug_level
+};
+
 int __init rtllib_init(void)
 {
 	struct proc_dir_entry *e;
 
 	rtllib_debug_level = debug;
-	rtllib_proc = create_proc_entry(DRV_NAME, S_IFDIR, init_net.proc_net);
+	rtllib_proc = proc_mkdir(DRV_NAME, init_net.proc_net);
 	if (rtllib_proc == NULL) {
 		RTLLIB_ERROR("Unable to create " DRV_NAME
 				" proc directory\n");
 		return -EIO;
 	}
-	e = create_proc_entry("debug_level", S_IFREG | S_IRUGO | S_IWUSR,
-			      rtllib_proc);
+	e = proc_create("debug_level", S_IRUGO | S_IWUSR, rtllib_proc, &fops);
 	if (!e) {
 		remove_proc_entry(DRV_NAME, init_net.proc_net);
 		rtllib_proc = NULL;
 		return -EIO;
 	}
-	e->read_proc = show_debug_level;
-	e->write_proc = store_debug_level;
-	e->data = NULL;
-
 	return 0;
 }
 
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c
index 76c56e5..e0870c0 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c
@@ -243,39 +243,34 @@ static int debug = \
 			    ;
 struct proc_dir_entry *ieee80211_proc;
 
-static int show_debug_level(char *page, char **start, off_t offset,
-			    int count, int *eof, void *data)
+static int show_debug_level(struct seq_file *m, void *v)
 {
-	return snprintf(page, count, "0x%08X\n", ieee80211_debug_level);
+	return seq_printf(m, "0x%08X\n", ieee80211_debug_level);
 }
 
-static int store_debug_level(struct file *file, const char *buffer,
-			     unsigned long count, void *data)
+static ssize_t write_debug_level(struct file *file, const char __user *buffer,
+			     size_t count, loff_t *ppos)
 {
-	char buf[] = "0x00000000";
-	unsigned long len = min_t(unsigned long, sizeof(buf) - 1, count);
-	char *p = (char *)buf;
 	unsigned long val;
+	int err = kstrtoul_from_user(buffer, count, 0, &val);
+	if (err)
+		return err;
+	ieee80211_debug_level = val;
+	return count;
+}
 
-	if (copy_from_user(buf, buffer, len))
-		return count;
-	buf[len] = 0;
-	if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') {
-		p++;
-		if (p[0] == 'x' || p[0] == 'X')
-			p++;
-		val = simple_strtoul(p, &p, 16);
-	} else
-		val = simple_strtoul(p, &p, 10);
-	if (p == buf)
-		printk(KERN_INFO DRV_NAME
-		       ": %s is not in hex or decimal form.\n", buf);
-	else
-		ieee80211_debug_level = val;
-
-	return strnlen(buf, count);
+static int open_debug_level(struct inode *inode, struct file *file)
+{
+	return single_open(file, show_debug_level, NULL);
 }
 
+static const struct file_operations fops = {
+	.open = open_debug_level,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.write = write_debug_level
+};
+
 int __init ieee80211_debug_init(void)
 {
 	struct proc_dir_entry *e;
@@ -288,17 +283,13 @@ int __init ieee80211_debug_init(void)
 				" proc directory\n");
 		return -EIO;
 	}
-	e = create_proc_entry("debug_level", S_IFREG | S_IRUGO | S_IWUSR,
-			      ieee80211_proc);
+	e = proc_create("debug_level", S_IRUGO | S_IWUSR, 
+			      ieee80211_proc, &fops);
 	if (!e) {
 		remove_proc_entry(DRV_NAME, init_net.proc_net);
 		ieee80211_proc = NULL;
 		return -EIO;
 	}
-	e->read_proc = show_debug_level;
-	e->write_proc = store_debug_level;
-	e->data = NULL;
-
 	return 0;
 }
 
diff --git a/drivers/staging/rtl8192u/ieee80211/proc.c b/drivers/staging/rtl8192u/ieee80211/proc.c
index 6eda928..54026a4 100644
--- a/drivers/staging/rtl8192u/ieee80211/proc.c
+++ b/drivers/staging/rtl8192u/ieee80211/proc.c
@@ -108,9 +108,5 @@ static struct file_operations proc_crypto_ops = {
 
 void __init crypto_init_proc(void)
 {
-	struct proc_dir_entry *proc;
-
-	proc = create_proc_entry("crypto", 0, NULL);
-	if (proc)
-		proc->proc_fops = &proc_crypto_ops;
+	proc_create("crypto", 0, NULL, &proc_crypto_ops);
 }
diff --git a/drivers/staging/rtl8192u/r8192U_dm.h b/drivers/staging/rtl8192u/r8192U_dm.h
index ffb083c..ae55052 100644
--- a/drivers/staging/rtl8192u/r8192U_dm.h
+++ b/drivers/staging/rtl8192u/r8192U_dm.h
@@ -48,16 +48,16 @@
 #define		VeryLowRSSI					15
 #define		CTSToSelfTHVal					30
 
-//defined by vivi, for tx power track
+/* defined by vivi, for tx power track */
 #define		E_FOR_TX_POWER_TRACK               300
-//Dynamic Tx Power Control Threshold
+/* Dynamic Tx Power Control Threshold */
 #define		TX_POWER_NEAR_FIELD_THRESH_HIGH		68
 #define		TX_POWER_NEAR_FIELD_THRESH_LOW		62
-//added by amy for atheros AP
+/* added by amy for atheros AP */
 #define         TX_POWER_ATHEROAP_THRESH_HIGH           78
 #define		TX_POWER_ATHEROAP_THRESH_LOW		72
 
-//defined by vivi, for showing on UI
+/* defined by vivi, for showing on UI */
 #define			Current_Tx_Rate_Reg         0x1b8
 #define			Initial_Tx_Rate_Reg		  0x1b9
 #define			Tx_Retry_Count_Reg         0x1ac
@@ -98,28 +98,25 @@ typedef struct _dynamic_initial_gain_threshold_ {
 	bool		initialgain_lowerbound_state;
 
 	long		rssi_val;
-}dig_t;
+} dig_t;
 
-typedef enum tag_dynamic_init_gain_state_definition
-{
+typedef enum tag_dynamic_init_gain_state_definition {
 	DM_STA_DIG_OFF = 0,
 	DM_STA_DIG_ON,
 	DM_STA_DIG_MAX
-}dm_dig_sta_e;
+} dm_dig_sta_e;
 
 
 /* 2007/10/08 MH Define RATR state. */
-typedef enum tag_dynamic_ratr_state_definition
-{
+typedef enum tag_dynamic_ratr_state_definition {
 	DM_RATR_STA_HIGH = 0,
 	DM_RATR_STA_MIDDLE = 1,
 	DM_RATR_STA_LOW = 2,
 	DM_RATR_STA_MAX
-}dm_ratr_sta_e;
+} dm_ratr_sta_e;
 
 /* 2007/10/11 MH Define DIG operation type. */
-typedef enum tag_dynamic_init_gain_operation_type_definition
-{
+typedef enum tag_dynamic_init_gain_operation_type_definition {
 	DIG_TYPE_THRESH_HIGH	= 0,
 	DIG_TYPE_THRESH_LOW	= 1,
 	DIG_TYPE_THRESH_HIGHPWR_HIGH	= 2,
@@ -134,43 +131,38 @@ typedef enum tag_dynamic_init_gain_operation_type_definition
 	DIG_TYPE_ENABLE			= 20,
 	DIG_TYPE_DISABLE		= 30,
 	DIG_OP_TYPE_MAX
-}dm_dig_op_e;
+} dm_dig_op_e;
 
-typedef enum tag_dig_algorithm_definition
-{
+typedef enum tag_dig_algorithm_definition {
 	DIG_ALGO_BY_FALSE_ALARM = 0,
 	DIG_ALGO_BY_RSSI	= 1,
 	DIG_ALGO_MAX
-}dm_dig_alg_e;
+} dm_dig_alg_e;
 
-typedef enum tag_dig_dbgmode_definition
-{
+typedef enum tag_dig_dbgmode_definition {
 	DIG_DBG_OFF = 0,
 	DIG_DBG_ON = 1,
 	DIG_DBG_MAX
-}dm_dig_dbg_e;
+} dm_dig_dbg_e;
 
-typedef enum tag_dig_connect_definition
-{
+typedef enum tag_dig_connect_definition {
 	DIG_DISCONNECT = 0,
 	DIG_CONNECT = 1,
 	DIG_CONNECT_MAX
-}dm_dig_connect_e;
+} dm_dig_connect_e;
 
-typedef enum tag_dig_packetdetection_threshold_definition
-{
+typedef enum tag_dig_packetdetection_threshold_definition {
 	DIG_PD_AT_LOW_POWER = 0,
 	DIG_PD_AT_NORMAL_POWER = 1,
 	DIG_PD_AT_HIGH_POWER = 2,
 	DIG_PD_MAX
-}dm_dig_pd_th_e;
+} dm_dig_pd_th_e;
 
-typedef enum tag_dig_cck_cs_ratio_state_definition
-{
+typedef enum tag_dig_cck_cs_ratio_state_definition {
 	DIG_CS_RATIO_LOWER = 0,
 	DIG_CS_RATIO_HIGHER = 1,
 	DIG_CS_MAX
-}dm_dig_cs_ratio_e;
+} dm_dig_cs_ratio_e;
 typedef struct _Dynamic_Rx_Path_Selection_ {
 	u8		Enable;
 	u8		DbgMode;
@@ -185,27 +177,25 @@ typedef struct _Dynamic_Rx_Path_Selection_ {
 	u8		rf_rssi[4];
 	u8		rf_enable_rssi_th[4];
 	long		cck_pwdb_sta[4];
-}DRxPathSel;
+} DRxPathSel;
 
-typedef enum tag_CCK_Rx_Path_Method_Definition
-{
+typedef enum tag_CCK_Rx_Path_Method_Definition {
 	CCK_Rx_Version_1 = 0,
-	CCK_Rx_Version_2= 1,
+	CCK_Rx_Version_2 = 1,
 	CCK_Rx_Version_MAX
-}DM_CCK_Rx_Path_Method;
+} DM_CCK_Rx_Path_Method;
 
-typedef enum tag_DM_DbgMode_Definition
-{
+typedef enum tag_DM_DbgMode_Definition {
 	DM_DBG_OFF = 0,
 	DM_DBG_ON = 1,
 	DM_DBG_MAX
-}DM_DBG_E;
+} DM_DBG_E;
 
 typedef struct tag_Tx_Config_Cmd_Format {
-	u32	Op;										/* Command packet type. */
-	u32	Length;									/* Command packet length. */
+	u32	Op;			/* Command packet type. */
+	u32	Length;			/* Command packet length. */
 	u32	Value;
-}DCMD_TXCMD_T, *PDCMD_TXCMD_T;
+} DCMD_TXCMD_T, *PDCMD_TXCMD_T;
 /*------------------------------Define structure----------------------------*/
 
 
@@ -232,13 +222,14 @@ extern  void    dm_txpower_trackingcallback(struct work_struct *work);
 extern  void    dm_restore_dynamic_mechanism_state(struct net_device *dev);
 extern  void    dm_backup_dynamic_mechanism_state(struct net_device *dev);
 extern  void    dm_change_dynamic_initgain_thresh(struct net_device *dev,
-								u32 dm_type, u32 dm_value);
-extern  void    dm_force_tx_fw_info(struct net_device *dev,u32 force_type, u32 force_value);
+						u32 dm_type, u32 dm_value);
+extern  void    dm_force_tx_fw_info(struct net_device *dev,
+					u32 force_type, u32 force_value);
 extern  void    dm_init_edca_turbo(struct net_device *dev);
 extern  void    dm_rf_operation_test_callback(unsigned long data);
 extern  void    dm_rf_pathcheck_workitemcallback(struct work_struct *work);
 extern  void dm_fsync_timer_callback(unsigned long data);
-extern	void	dm_cck_txpower_adjust(struct net_device *dev,bool  binch14);
+extern	void	dm_cck_txpower_adjust(struct net_device *dev, bool  binch14);
 extern  void    dm_shadow_init(struct net_device *dev);
 extern void dm_initialize_txpower_tracking(struct net_device *dev);
 /*--------------------------Exported Function prototype---------------------*/
diff --git a/drivers/staging/rtl8712/rtl8712_led.c b/drivers/staging/rtl8712/rtl8712_led.c
index c9eb4b7..6cb1a0a 100644
--- a/drivers/staging/rtl8712/rtl8712_led.c
+++ b/drivers/staging/rtl8712/rtl8712_led.c
@@ -267,12 +267,8 @@ static void SwLedBlink(struct LED_871x *pLed)
 				   LED_BLINK_SLOWLY_INTERVAL);
 			break;
 		case LED_BLINK_WPS:
-			if (pLed->BlinkingLedState == LED_ON)
-				_set_timer(&(pLed->BlinkTimer),
-					   LED_BLINK_LONG_INTERVAL);
-			else
-				_set_timer(&(pLed->BlinkTimer),
-					   LED_BLINK_LONG_INTERVAL);
+			_set_timer(&(pLed->BlinkTimer),
+					LED_BLINK_LONG_INTERVAL);
 			break;
 		default:
 			_set_timer(&(pLed->BlinkTimer),
diff --git a/drivers/staging/rtl8712/rtl871x_recv.h b/drivers/staging/rtl8712/rtl871x_recv.h
index e42e6f0..92ca899 100644
--- a/drivers/staging/rtl8712/rtl871x_recv.h
+++ b/drivers/staging/rtl8712/rtl871x_recv.h
@@ -9,9 +9,6 @@
 #define RXFRAME_ALIGN	8
 #define RXFRAME_ALIGN_SZ	(1 << RXFRAME_ALIGN)
 
-#define MAX_RXFRAME_CNT	512
-#define MAX_RX_NUMBLKS		(32)
-#define RECVFRAME_HDR_ALIGN 128
 #define MAX_SUBFRAME_COUNT	64
 
 #define SNAP_SIZE sizeof(struct ieee80211_snap_hdr)
@@ -130,15 +127,10 @@ struct sta_recv_priv {
 
 /* get a free recv_frame from pfree_recv_queue */
 union recv_frame *r8712_alloc_recvframe(struct  __queue *pfree_recv_queue);
-union recv_frame *r8712_dequeue_recvframe(struct  __queue *queue);
-int r8712_enqueue_recvframe(union recv_frame *precvframe,
-			     struct  __queue *queue);
 int r8712_free_recvframe(union recv_frame *precvframe,
 			  struct  __queue *pfree_recv_queue);
 void r8712_free_recvframe_queue(struct  __queue *pframequeue,
 				 struct  __queue *pfree_recv_queue);
-void r8712_init_recvframe(union recv_frame *precvframe,
-			   struct recv_priv *precvpriv);
 int r8712_wlanhdr_to_ethhdr(union recv_frame *precvframe);
 int recv_func(struct _adapter *padapter, void *pcontext);
 
@@ -150,11 +142,6 @@ static inline u8 *get_rxmem(union recv_frame *precvframe)
 	return precvframe->u.hdr.rx_head;
 }
 
-static inline u8 *get_rx_status(union recv_frame *precvframe)
-{
-	return get_rxmem(precvframe);
-}
-
 static inline u8 *get_recvframe_data(union recv_frame *precvframe)
 {
 	/* always return rx_data */
@@ -163,28 +150,6 @@ static inline u8 *get_recvframe_data(union recv_frame *precvframe)
 	return precvframe->u.hdr.rx_data;
 }
 
-static inline u8 *recvframe_push(union recv_frame *precvframe, sint sz)
-{
-	/* append data before rx_data */
-
-	/* add data to the start of recv_frame
-	 *
-	 * This function extends the used data area of the recv_frame at the
-	 * buffer start. rx_data must be still larger than rx_head, after
-	 * pushing.
-	 */
-
-	if (precvframe == NULL)
-		return NULL;
-	precvframe->u.hdr.rx_data -= sz ;
-	if (precvframe->u.hdr.rx_data < precvframe->u.hdr.rx_head) {
-		precvframe->u.hdr.rx_data += sz ;
-		return NULL;
-	}
-	precvframe->u.hdr.len += sz;
-	return precvframe->u.hdr.rx_data;
-}
-
 static inline u8 *recvframe_pull(union recv_frame *precvframe, sint sz)
 {
 	/* used for extract sz bytes from rx_data, update rx_data and return
@@ -236,53 +201,6 @@ static inline u8 *recvframe_pull_tail(union recv_frame *precvframe, sint sz)
 	return precvframe->u.hdr.rx_tail;
 }
 
-static inline _buffer *get_rxbuf_desc(union recv_frame *precvframe)
-{
-	_buffer *buf_desc;
-	if (precvframe == NULL)
-		return NULL;
-	return buf_desc;
-}
-
-static inline union recv_frame *rxmem_to_recvframe(u8 *rxmem)
-{
-	/* due to the design of 2048 bytes alignment of recv_frame, we can
-	 * reference the union recv_frame from any given member of recv_frame.
-	 * rxmem indicates the any member/address in recv_frame */
-	return (union recv_frame *)(((addr_t)rxmem >> RXFRAME_ALIGN) <<
-				  RXFRAME_ALIGN);
-}
-
-static inline union recv_frame *pkt_to_recvframe(_pkt *pkt)
-{
-	u8 *buf_star;
-	union recv_frame *precv_frame;
-
-	precv_frame = rxmem_to_recvframe((unsigned char *)buf_star);
-	return precv_frame;
-}
-
-static inline u8 *pkt_to_recvmem(_pkt *pkt)
-{
-	/* return the rx_head */
-	union recv_frame *precv_frame = pkt_to_recvframe(pkt);
-
-	return	precv_frame->u.hdr.rx_head;
-}
-
-static inline u8 *pkt_to_recvdata(_pkt *pkt)
-{
-	/* return the rx_data */
-	union recv_frame *precv_frame = pkt_to_recvframe(pkt);
-
-	return	precv_frame->u.hdr.rx_data;
-}
-
-static inline sint get_recvframe_len(union recv_frame *precvframe)
-{
-	return precvframe->u.hdr.len;
-}
-
 struct sta_info;
 
 void	_r8712_init_sta_recv_priv(struct sta_recv_priv *psta_recvpriv);
@@ -292,36 +210,10 @@ union recv_frame *r8712_decryptor(struct _adapter *adapter,
 				  union recv_frame *precv_frame);
 union recv_frame *r8712_recvframe_chk_defrag(struct _adapter *adapter,
 					     union recv_frame *precv_frame);
-union recv_frame *r8712_recvframe_defrag(struct _adapter *adapter,
-					 struct  __queue *defrag_q);
-union recv_frame *r8712_recvframe_chk_defrag_new(struct _adapter *adapter,
-					union recv_frame *precv_frame);
-union recv_frame *r8712_recvframe_defrag_new(struct _adapter *adapter,
-					struct  __queue *defrag_q,
-					union recv_frame *precv_frame);
-int r8712_recv_decache(union recv_frame *precv_frame, u8 bretry,
-		       struct stainfo_rxcache *prxcache);
-int r8712_sta2sta_data_frame(struct _adapter *adapter,
-			     union recv_frame *precv_frame,
-			     struct sta_info **psta);
-int r8712_ap2sta_data_frame(struct _adapter *adapter,
-			    union recv_frame *precv_frame,
-			    struct sta_info **psta);
-int r8712_sta2ap_data_frame(struct _adapter *adapter,
-			    union recv_frame *precv_frame,
-			    struct sta_info **psta);
-int r8712_validate_recv_ctrl_frame(struct _adapter *adapter,
-				   union recv_frame *precv_frame);
-int r8712_validate_recv_mgnt_frame(struct _adapter *adapter,
-				   union recv_frame *precv_frame);
-int r8712_validate_recv_data_frame(struct _adapter *adapter,
-				   union recv_frame *precv_frame);
 int r8712_validate_recv_frame(struct _adapter *adapter,
 			      union recv_frame *precv_frame);
 union recv_frame *r8712_portctrl(struct _adapter *adapter,
 				 union recv_frame *precv_frame);
-void  r8712_mgt_dispatcher(struct _adapter *padapter, u8 *pframe, uint len);
-int r8712_amsdu_to_msdu(struct _adapter *padapter, union recv_frame *prframe);
 
 #endif
 
diff --git a/drivers/staging/rts5139/rts51x_scsi.c b/drivers/staging/rts5139/rts51x_scsi.c
index 052911c..6108705 100644
--- a/drivers/staging/rts5139/rts51x_scsi.c
+++ b/drivers/staging/rts5139/rts51x_scsi.c
@@ -1968,18 +1968,16 @@ int slave_configure(struct scsi_device *sdev)
 
 /* we use this macro to help us write into the buffer */
 #undef SPRINTF
-#define SPRINTF(args...) \
-	do { if (pos < buffer+length) pos += sprintf(pos, ## args); } while (0)
+#define SPRINTF(args...) seq_printf(m, ##args)
 
-int proc_info(struct Scsi_Host *host, char *buffer,
-	      char **start, off_t offset, int length, int inout)
+static int write_info(struct Scsi_Host *host, char *buffer, int length)
 {
-	char *pos = buffer;
-
 	/* if someone is sending us data, just throw it away */
-	if (inout)
-		return length;
+	return length;
+}
 
+static int show_info(struct seq_file *m, struct Scsi_Host *host)
+{
 	/* print the controller name */
 	SPRINTF("   Host scsi%d: %s\n", host->host_no, RTS51X_NAME);
 
@@ -1988,18 +1986,7 @@ int proc_info(struct Scsi_Host *host, char *buffer,
 	SPRINTF("      Product: RTS51xx USB Card Reader\n");
 	SPRINTF("      Version: %s\n", DRIVER_VERSION);
 	SPRINTF("        Build: %s\n", __TIME__);
-
-	/*
-	 * Calculate start of next buffer, and return value.
-	 */
-	*start = buffer + offset;
-
-	if ((pos - buffer) < offset)
-		return 0;
-	else if ((pos - buffer - offset) < length)
-		return pos - buffer - offset;
-	else
-		return length;
+	return 0;
 }
 
 /* queue a command */
@@ -2072,7 +2059,7 @@ int command_abort(struct scsi_cmnd *srb)
 
 /* This invokes the transport reset mechanism to reset the state of the
  * device */
-int device_reset(struct scsi_cmnd *srb)
+static int device_reset(struct scsi_cmnd *srb)
 {
 	int result = 0;
 
@@ -2100,7 +2087,8 @@ struct scsi_host_template rts51x_host_template = {
 	/* basic userland interface stuff */
 	.name = RTS51X_NAME,
 	.proc_name = RTS51X_NAME,
-	.proc_info = proc_info,
+	.show_info = show_info,
+	.write_info = write_info,
 	.info = rts5139_info,
 
 	/* command interface -- queued only */
diff --git a/drivers/staging/rts5139/rts51x_scsi.h b/drivers/staging/rts5139/rts51x_scsi.h
index cdfe550..1a0d705 100644
--- a/drivers/staging/rts5139/rts51x_scsi.h
+++ b/drivers/staging/rts5139/rts51x_scsi.h
@@ -147,11 +147,8 @@ struct scsi_cmnd;
 
 int slave_alloc(struct scsi_device *sdev);
 int slave_configure(struct scsi_device *sdev);
-int proc_info(struct Scsi_Host *host, char *buffer,
-	      char **start, off_t offset, int length, int inout);
 int queuecommand(struct Scsi_Host *, struct scsi_cmnd *);
 int command_abort(struct scsi_cmnd *srb);
-int device_reset(struct scsi_cmnd *srb);
 int bus_reset(struct scsi_cmnd *srb);
 
 #endif /* __RTS51X_SCSI_H */
diff --git a/drivers/staging/sb105x/sb_mp_register.h b/drivers/staging/sb105x/sb_mp_register.h
index a2087f5..304e1bc 100644
--- a/drivers/staging/sb105x/sb_mp_register.h
+++ b/drivers/staging/sb105x/sb_mp_register.h
@@ -19,7 +19,7 @@
  * option register 
  */
 
-/* Device Infomation Register */
+/* Device Information Register */
 #define MP_OPTR_DIR0		0x04 	/* port0 ~ port8 */
 #define MP_OPTR_DIR1		0x05 	/* port8 ~ port15 */
 #define MP_OPTR_DIR2		0x06 	/* port16 ~ port23 */
@@ -47,7 +47,7 @@
 #define IIR_RS485		0x20		/* RS485 type */
 #define IIR_TYPE_MASK		0x30
 
-/* Interrrupt Mask Register */
+/* Interrupt Mask Register */
 #define MP_OPTR_IMR0		0x0C 	/* port0 ~ port8 */
 #define MP_OPTR_IMR1		0x0D 	/* port8 ~ port15 */
 #define MP_OPTR_IMR2		0x0E 	/* port16 ~ port23 */
diff --git a/drivers/staging/sb105x/sb_pci_mp.c b/drivers/staging/sb105x/sb_pci_mp.c
index f75ee1d..cd94f6c 100644
--- a/drivers/staging/sb105x/sb_pci_mp.c
+++ b/drivers/staging/sb105x/sb_pci_mp.c
@@ -2248,7 +2248,7 @@ static irqreturn_t multi_interrupt(int irq, void *dev_id)
 		mtpt = list_entry(lhead, struct mp_port, list);
 		
 		iir = serial_in(mtpt, UART_IIR);
-		printk("intrrupt! port %d, iir 0x%x\n", mtpt->port.line, iir); //wlee
+		printk("interrupt! port %d, iir 0x%x\n", mtpt->port.line, iir); //wlee
 		if (!(iir & UART_IIR_NO_INT)) 
 		{
 			printk("interrupt handle\n");
@@ -2830,7 +2830,7 @@ static void __init multi_init_ports(void)
 
 			mtpt->port.uartclk  = BASE_BAUD * 16;
 
-			/* get input clock infomation */
+			/* get input clock information */
 			osc = inb(sbdev->option_reg_addr + MP_OPTR_DIR0 + i/8) & 0x0F;
 			if (osc==0x0f)
 				osc = 0;
diff --git a/drivers/staging/sb105x/sb_pci_mp.h b/drivers/staging/sb105x/sb_pci_mp.h
index f33efde..a15f470 100644
--- a/drivers/staging/sb105x/sb_pci_mp.h
+++ b/drivers/staging/sb105x/sb_pci_mp.h
@@ -174,7 +174,7 @@ static DEFINE_MUTEX(mp_mutex);
 #define DEBUG_INTR(fmt...)  do { } while (0)
 #endif
 
-#if defined(__i386__) && (defined(CONFIG_M386) || defined(CONFIG_M486))
+#if defined(__i386__) && defined(CONFIG_M486)
 #define SERIAL_INLINE
 #endif
 #ifdef SERIAL_INLINE
diff --git a/drivers/staging/sep/sep_crypto.c b/drivers/staging/sep/sep_crypto.c
index cd3bb39..490a31e 100644
--- a/drivers/staging/sep/sep_crypto.c
+++ b/drivers/staging/sep/sep_crypto.c
@@ -1206,7 +1206,7 @@ static int sep_crypto_block_data(struct ablkcipher_request *req)
 
 		if (copy_result != crypto_ablkcipher_blocksize(tfm)) {
 			dev_warn(&ta_ctx->sep_used->pdev->dev,
-				"des block copy faild\n");
+				"des block copy failed\n");
 			return -ENOMEM;
 		}
 
@@ -1637,7 +1637,7 @@ static u32 crypto_post_op(struct sep_device *sep)
 					crypto_ablkcipher_blocksize(tfm)) {
 
 					dev_warn(&ta_ctx->sep_used->pdev->dev,
-						"des block copy faild\n");
+						"des block copy failed\n");
 					sep_crypto_release(sctx, ta_ctx,
 						-ENOMEM);
 					return -ENOMEM;
diff --git a/drivers/staging/sep/sep_driver_config.h b/drivers/staging/sep/sep_driver_config.h
index 7d7c7ab..4b6e307 100644
--- a/drivers/staging/sep/sep_driver_config.h
+++ b/drivers/staging/sep/sep_driver_config.h
@@ -219,7 +219,7 @@ held by the process (struct file) */
 /* maximum number of entries in the caller id table */
 #define SEP_CALLER_ID_TABLE_NUM_ENTRIES                       20
 
-/* maximum number of symetric operation (that require DMA resource)
+/* maximum number of symmetric operation (that require DMA resource)
 	per one message */
 #define SEP_MAX_NUM_SYNC_DMA_OPS			16
 
diff --git a/drivers/staging/sep/sep_main.c b/drivers/staging/sep/sep_main.c
index 30e8d25..6a98a20 100644
--- a/drivers/staging/sep/sep_main.c
+++ b/drivers/staging/sep/sep_main.c
@@ -1986,7 +1986,7 @@ static int sep_prepare_input_dma_table(struct sep_device *sep,
 					dma_ctx,
 					sep_lli_entries);
 		if (error)
-			return error;
+			goto end_function_error;
 		lli_table_alloc_addr = *dmatables_region;
 	}
 
@@ -2276,7 +2276,7 @@ static int sep_construct_dma_tables_from_lli(
 			table_data_size);
 
 		/* If info entry is null - this is the first table built */
-		if (info_in_entry_ptr == NULL) {
+		if (info_in_entry_ptr == NULL || info_out_entry_ptr == NULL) {
 			/* Set the output parameters to physical addresses */
 			*lli_table_in_ptr =
 			sep_shared_area_virt_to_bus(sep, dma_in_lli_table_ptr);
@@ -2880,6 +2880,8 @@ static int sep_free_dma_tables_and_dcb(struct sep_device *sep, bool isapplet,
 
 	dev_dbg(&sep->pdev->dev, "[PID%d] sep_free_dma_tables_and_dcb\n",
 					current->pid);
+	if (!dma_ctx || !*dma_ctx) /* nothing to be done here*/
+		return 0;
 
 	if (((*dma_ctx)->secure_dma == false) && (isapplet == true)) {
 		dev_dbg(&sep->pdev->dev, "[PID%d] handling applet\n",
@@ -2895,8 +2897,7 @@ static int sep_free_dma_tables_and_dcb(struct sep_device *sep, bool isapplet,
 		 * Go over each DCB and see if
 		 * tail pointer must be updated
 		 */
-		for (i = 0; dma_ctx && *dma_ctx &&
-			i < (*dma_ctx)->nr_dcb_creat; i++, dcb_table_ptr++) {
+		for (i = 0; i < (*dma_ctx)->nr_dcb_creat; i++, dcb_table_ptr++) {
 			if (dcb_table_ptr->out_vr_tail_pt) {
 				pt_hold = (unsigned long)dcb_table_ptr->
 					out_vr_tail_pt;
diff --git a/drivers/staging/sep/sep_trace_events.h b/drivers/staging/sep/sep_trace_events.h
index 2b053a9..74f4c9a 100644
--- a/drivers/staging/sep/sep_trace_events.h
+++ b/drivers/staging/sep/sep_trace_events.h
@@ -53,6 +53,11 @@
 #include <linux/tracepoint.h>
 
 /*
+ * Since use str*cpy in header file, better to include string.h, directly.
+ */
+#include <linux/string.h>
+
+/*
  * The TRACE_EVENT macro is broken up into 5 parts.
  *
  * name: name of the trace point. This is also how to enable the tracepoint.
@@ -97,7 +102,7 @@ TRACE_EVENT(sep_func_start,
 	),
 
 	TP_fast_assign(
-		strncpy(__entry->name, name, 20);
+		strlcpy(__entry->name, name, 20);
 		__entry->branch	= branch;
 	),
 
@@ -116,7 +121,7 @@ TRACE_EVENT(sep_func_end,
 	),
 
 	TP_fast_assign(
-		strncpy(__entry->name, name, 20);
+		strlcpy(__entry->name, name, 20);
 		__entry->branch	= branch;
 	),
 
@@ -135,7 +140,7 @@ TRACE_EVENT(sep_misc_event,
 	),
 
 	TP_fast_assign(
-		strncpy(__entry->name, name, 20);
+		strlcpy(__entry->name, name, 20);
 		__entry->branch	= branch;
 	),
 
diff --git a/drivers/staging/serqt_usb2/serqt_usb2.c b/drivers/staging/serqt_usb2/serqt_usb2.c
index b1bb1a6..8a6e5ea 100644
--- a/drivers/staging/serqt_usb2/serqt_usb2.c
+++ b/drivers/staging/serqt_usb2/serqt_usb2.c
@@ -264,7 +264,6 @@ static void ProcessRxChar(struct usb_serial_port *port, unsigned char data)
 
 static void qt_write_bulk_callback(struct urb *urb)
 {
-	struct tty_struct *tty;
 	int status;
 	struct quatech_port *quatech_port;
 
@@ -278,11 +277,7 @@ static void qt_write_bulk_callback(struct urb *urb)
 
 	quatech_port = urb->context;
 
-	tty = tty_port_tty_get(&quatech_port->port->port);
-
-	if (tty)
-		tty_wakeup(tty);
-	tty_kref_put(tty);
+	tty_port_tty_wakeup(&quatech_port->port->port);
 }
 
 static void qt_interrupt_callback(struct urb *urb)
diff --git a/drivers/staging/silicom/bp_mod.c b/drivers/staging/silicom/bp_mod.c
index 58c5f5c..5cb2f7d 100644
--- a/drivers/staging/silicom/bp_mod.c
+++ b/drivers/staging/silicom/bp_mod.c
@@ -60,35 +60,9 @@ typedef enum {
 	bp_none,
 } bp_media_type;
 
-struct pfs_unit_sd {
-	struct proc_dir_entry *proc_entry;
-	char proc_name[32];
-};
-
 struct bypass_pfs_sd {
 	char dir_name[32];
 	struct proc_dir_entry *bypass_entry;
-	struct pfs_unit_sd bypass_info;
-	struct pfs_unit_sd bypass_slave;
-	struct pfs_unit_sd bypass_caps;
-	struct pfs_unit_sd wd_set_caps;
-	struct pfs_unit_sd bypass;
-	struct pfs_unit_sd bypass_change;
-	struct pfs_unit_sd bypass_wd;
-	struct pfs_unit_sd wd_expire_time;
-	struct pfs_unit_sd reset_bypass_wd;
-	struct pfs_unit_sd dis_bypass;
-	struct pfs_unit_sd bypass_pwup;
-	struct pfs_unit_sd bypass_pwoff;
-	struct pfs_unit_sd std_nic;
-	struct pfs_unit_sd tap;
-	struct pfs_unit_sd dis_tap;
-	struct pfs_unit_sd tap_pwup;
-	struct pfs_unit_sd tap_change;
-	struct pfs_unit_sd wd_exp_mode;
-	struct pfs_unit_sd wd_autoreset;
-	struct pfs_unit_sd tpl;
-
 };
 
 typedef struct _bpctl_dev {
@@ -1728,62 +1702,33 @@ int gpio6_clear_fn(bpctl_dev_t *pbpctl_dev)
 }
 #endif				/*BYPASS_DEBUG */
 
-static bpctl_dev_t *get_status_port_fn(bpctl_dev_t *pbpctl_dev)
+static bpctl_dev_t *lookup_port(bpctl_dev_t *dev)
 {
-	int idx_dev = 0;
-
-	if (pbpctl_dev == NULL)
-		return NULL;
-
-	if ((pbpctl_dev->func == 0) || (pbpctl_dev->func == 2)) {
-		for (idx_dev = 0;
-		     ((bpctl_dev_arr[idx_dev].pdev != NULL)
-		      && (idx_dev < device_num)); idx_dev++) {
-			if ((bpctl_dev_arr[idx_dev].bus == pbpctl_dev->bus)
-			    && (bpctl_dev_arr[idx_dev].slot == pbpctl_dev->slot)
-			    && ((bpctl_dev_arr[idx_dev].func == 1)
-				&& (pbpctl_dev->func == 0))) {
-
-				return &(bpctl_dev_arr[idx_dev]);
-			}
-			if ((bpctl_dev_arr[idx_dev].bus == pbpctl_dev->bus) &&
-			    (bpctl_dev_arr[idx_dev].slot == pbpctl_dev->slot) &&
-			    ((bpctl_dev_arr[idx_dev].func == 3)
-			     && (pbpctl_dev->func == 2))) {
+	bpctl_dev_t *p;
+	int n;
+	for (n = 0, p = bpctl_dev_arr; n < device_num && p->pdev; n++) {
+		if (p->bus == dev->bus
+		    && p->slot == dev->slot
+		    && p->func == (dev->func ^ 1))
+			return p;
+	}
+	return NULL;
+}
 
-				return &(bpctl_dev_arr[idx_dev]);
-			}
-		}
+static bpctl_dev_t *get_status_port_fn(bpctl_dev_t *pbpctl_dev)
+{
+	if (pbpctl_dev) {
+		if (pbpctl_dev->func == 0 || pbpctl_dev->func == 2)
+			return lookup_port(pbpctl_dev);
 	}
 	return NULL;
 }
 
 static bpctl_dev_t *get_master_port_fn(bpctl_dev_t *pbpctl_dev)
 {
-	int idx_dev = 0;
-
-	if (pbpctl_dev == NULL)
-		return NULL;
-
-	if ((pbpctl_dev->func == 1) || (pbpctl_dev->func == 3)) {
-		for (idx_dev = 0;
-		     ((bpctl_dev_arr[idx_dev].pdev != NULL)
-		      && (idx_dev < device_num)); idx_dev++) {
-			if ((bpctl_dev_arr[idx_dev].bus == pbpctl_dev->bus)
-			    && (bpctl_dev_arr[idx_dev].slot == pbpctl_dev->slot)
-			    && ((bpctl_dev_arr[idx_dev].func == 0)
-				&& (pbpctl_dev->func == 1))) {
-
-				return &(bpctl_dev_arr[idx_dev]);
-			}
-			if ((bpctl_dev_arr[idx_dev].bus == pbpctl_dev->bus) &&
-			    (bpctl_dev_arr[idx_dev].slot == pbpctl_dev->slot) &&
-			    ((bpctl_dev_arr[idx_dev].func == 2)
-			     && (pbpctl_dev->func == 3))) {
-
-				return &(bpctl_dev_arr[idx_dev]);
-			}
-		}
+	if (pbpctl_dev) {
+		if (pbpctl_dev->func == 1 || pbpctl_dev->func == 3)
+			return lookup_port(pbpctl_dev);
 	}
 	return NULL;
 }
@@ -6686,6 +6631,118 @@ static bpmod_info_t tx_ctl_pci_tbl[] = {
 	{0,}
 };
 
+static void find_fw(bpctl_dev_t *dev)
+{
+	unsigned long mmio_start, mmio_len;
+	struct pci_dev *pdev1 = dev->pdev;
+
+	if ((OLD_IF_SERIES(dev->subdevice)) ||
+	    (INTEL_IF_SERIES(dev->subdevice)))
+		dev->bp_fw_ver = 0xff;
+	else
+		dev->bp_fw_ver = bypass_fw_ver(dev);
+
+	if (dev->bp_10gb == 1 && dev->bp_fw_ver == 0xff) {
+		int cnt = 100;
+		while (cnt--) {
+			iounmap((void *)dev->mem_map);
+			mmio_start = pci_resource_start(pdev1, 0);
+			mmio_len = pci_resource_len(pdev1, 0);
+
+			dev->mem_map = (unsigned long)
+			    ioremap(mmio_start, mmio_len);
+
+			dev->bp_fw_ver = bypass_fw_ver(dev);
+			if (dev-> bp_fw_ver == 0xa8)
+				break;
+		}
+	}
+	/* dev->bp_fw_ver=0xa8; */
+	printk("firmware version: 0x%x\n", dev->bp_fw_ver);
+}
+
+static int init_one(bpctl_dev_t *dev, bpmod_info_t *info, struct pci_dev *pdev1)
+{
+	unsigned long mmio_start, mmio_len;
+
+	dev->pdev = pdev1;
+	mmio_start = pci_resource_start(pdev1, 0);
+	mmio_len = pci_resource_len(pdev1, 0);
+
+	dev->desc = dev_desc[info->index].name;
+	dev->name = info->bp_name;
+	dev->device = info->device;
+	dev->vendor = info->vendor;
+	dev->subdevice = info->subdevice;
+	dev->subvendor = info->subvendor;
+	dev->func = PCI_FUNC(pdev1->devfn);
+	dev->slot = PCI_SLOT(pdev1->devfn);
+	dev->bus = pdev1->bus->number;
+	dev->mem_map = (unsigned long)ioremap(mmio_start, mmio_len);
+#ifdef BP_SYNC_FLAG
+	spin_lock_init(&dev->bypass_wr_lock);
+#endif
+	if (BP10G9_IF_SERIES(dev->subdevice))
+		dev->bp_10g9 = 1;
+	if (BP10G_IF_SERIES(dev->subdevice))
+		dev->bp_10g = 1;
+	if (PEG540_IF_SERIES(dev->subdevice))
+		dev->bp_540 = 1;
+	if (PEGF5_IF_SERIES(dev->subdevice))
+		dev->bp_fiber5 = 1;
+	if (PEG80_IF_SERIES(dev->subdevice))
+		dev->bp_i80 = 1;
+	if (PEGF80_IF_SERIES(dev->subdevice))
+		dev->bp_i80 = 1;
+	if ((dev->subdevice & 0xa00) == 0xa00)
+		dev->bp_i80 = 1;
+	if (BP10GB_IF_SERIES(dev->subdevice)) {
+		if (dev->ifindex == 0) {
+			unregister_chrdev(major_num, DEVICE_NAME);
+			printk("Please load network driver for %s adapter!\n",
+			     dev->name);
+			return -1;
+		}
+
+		if (dev->ndev && !(dev->ndev->flags & IFF_UP)) {
+			unregister_chrdev(major_num, DEVICE_NAME);
+			printk("Please bring up network interfaces for %s adapter!\n",
+			     dev->name);
+			return -1;
+		}
+		dev->bp_10gb = 1;
+	}
+
+	if (!dev->bp_10g9) {
+		if (is_bypass_fn(dev)) {
+			printk(KERN_INFO "%s found, ",
+			       dev->name);
+			find_fw(dev);
+		}
+		dev->wdt_status = WDT_STATUS_UNKNOWN;
+		dev->reset_time = 0;
+		atomic_set(&dev->wdt_busy, 0);
+		dev->bp_status_un = 1;
+
+		bypass_caps_init(dev);
+
+		init_bypass_wd_auto(dev);
+		init_bypass_tpl_auto(dev);
+		if (NOKIA_SERIES(dev->subdevice))
+			reset_cont(dev);
+	}
+#ifdef BP_SELF_TEST
+	if ((dev->bp_tx_data = kzalloc(BPTEST_DATA_LEN, GFP_KERNEL))) {
+		memset(dev->bp_tx_data, 0xff, 6);
+		memset(dev->bp_tx_data + 6, 0x0, 1);
+		memset(dev->bp_tx_data + 7, 0xaa, 5);
+		*(__be16 *)(dev->bp_tx_data + 12) = htons(ETH_P_BPTEST);
+	} else
+		printk("bp_ctl: Memory allocation error!\n");
+#endif
+	return 0;
+}
+
 /*
 * Initialize the module - Register the character device
 */
@@ -6694,7 +6751,7 @@ static int __init bypass_init_module(void)
 {
 	int ret_val, idx, idx_dev = 0;
 	struct pci_dev *pdev1 = NULL;
-	unsigned long mmio_start, mmio_len;
+	bpctl_dev_t *dev;
 
 	printk(BP_MOD_DESCR " v" BP_MOD_VER "\n");
 	ret_val = register_chrdev(major_num, DEVICE_NAME, &Fops);
@@ -6729,181 +6786,16 @@ static int __init bypass_init_module(void)
 	memset(bpctl_dev_arr, 0, ((device_num) * sizeof(bpctl_dev_t)));
 
 	pdev1 = NULL;
+	dev = bpctl_dev_arr;
 	for (idx = 0; tx_ctl_pci_tbl[idx].vendor; idx++) {
 		while ((pdev1 = pci_get_subsys(tx_ctl_pci_tbl[idx].vendor,
 					       tx_ctl_pci_tbl[idx].device,
 					       tx_ctl_pci_tbl[idx].subvendor,
 					       tx_ctl_pci_tbl[idx].subdevice,
 					       pdev1))) {
-			bpctl_dev_arr[idx_dev].pdev = pdev1;
-
-			mmio_start = pci_resource_start(pdev1, 0);
-			mmio_len = pci_resource_len(pdev1, 0);
-
-			bpctl_dev_arr[idx_dev].desc =
-			    dev_desc[tx_ctl_pci_tbl[idx].index].name;
-			bpctl_dev_arr[idx_dev].name =
-			    tx_ctl_pci_tbl[idx].bp_name;
-			bpctl_dev_arr[idx_dev].device =
-			    tx_ctl_pci_tbl[idx].device;
-			bpctl_dev_arr[idx_dev].vendor =
-			    tx_ctl_pci_tbl[idx].vendor;
-			bpctl_dev_arr[idx_dev].subdevice =
-			    tx_ctl_pci_tbl[idx].subdevice;
-			bpctl_dev_arr[idx_dev].subvendor =
-			    tx_ctl_pci_tbl[idx].subvendor;
-			/* bpctl_dev_arr[idx_dev].pdev=pdev1; */
-			bpctl_dev_arr[idx_dev].func = PCI_FUNC(pdev1->devfn);
-			bpctl_dev_arr[idx_dev].slot = PCI_SLOT(pdev1->devfn);
-			bpctl_dev_arr[idx_dev].bus = pdev1->bus->number;
-			bpctl_dev_arr[idx_dev].mem_map =
-			    (unsigned long)ioremap(mmio_start, mmio_len);
-#ifdef BP_SYNC_FLAG
-			spin_lock_init(&bpctl_dev_arr[idx_dev].bypass_wr_lock);
-#endif
-			if (BP10G9_IF_SERIES(bpctl_dev_arr[idx_dev].subdevice))
-				bpctl_dev_arr[idx_dev].bp_10g9 = 1;
-			if (BP10G_IF_SERIES(bpctl_dev_arr[idx_dev].subdevice))
-				bpctl_dev_arr[idx_dev].bp_10g = 1;
-			if (PEG540_IF_SERIES(bpctl_dev_arr[idx_dev].subdevice)) {
-
-				bpctl_dev_arr[idx_dev].bp_540 = 1;
-			}
-			if (PEGF5_IF_SERIES(bpctl_dev_arr[idx_dev].subdevice))
-				bpctl_dev_arr[idx_dev].bp_fiber5 = 1;
-			if (PEG80_IF_SERIES(bpctl_dev_arr[idx_dev].subdevice))
-				bpctl_dev_arr[idx_dev].bp_i80 = 1;
-			if (PEGF80_IF_SERIES(bpctl_dev_arr[idx_dev].subdevice))
-				bpctl_dev_arr[idx_dev].bp_i80 = 1;
-			if ((bpctl_dev_arr[idx_dev].subdevice & 0xa00) == 0xa00)
-				bpctl_dev_arr[idx_dev].bp_i80 = 1;
-			if (BP10GB_IF_SERIES(bpctl_dev_arr[idx_dev].subdevice)) {
-				if (bpctl_dev_arr[idx_dev].ifindex == 0) {
-					unregister_chrdev(major_num,
-							  DEVICE_NAME);
-					printk
-					    ("Please load network driver for %s adapter!\n",
-					     bpctl_dev_arr[idx_dev].name);
-					return -1;
-				}
-
-				if (bpctl_dev_arr[idx_dev].ndev) {
-					if (!
-					    (bpctl_dev_arr[idx_dev].ndev->
-					     flags & IFF_UP)) {
-						if (!
-						    (bpctl_dev_arr[idx_dev].
-						     ndev->flags & IFF_UP)) {
-							unregister_chrdev
-							    (major_num,
-							     DEVICE_NAME);
-							printk
-							    ("Please bring up network interfaces for %s adapter!\n",
-							     bpctl_dev_arr
-							     [idx_dev].name);
-							return -1;
-						}
-
-					}
-				}
-				bpctl_dev_arr[idx_dev].bp_10gb = 1;
-			}
-
-			if (!bpctl_dev_arr[idx_dev].bp_10g9) {
-
-				if (is_bypass_fn(&bpctl_dev_arr[idx_dev])) {
-					printk(KERN_INFO "%s found, ",
-					       bpctl_dev_arr[idx_dev].name);
-					if ((OLD_IF_SERIES
-					     (bpctl_dev_arr[idx_dev].subdevice))
-					    ||
-					    (INTEL_IF_SERIES
-					     (bpctl_dev_arr[idx_dev].
-					      subdevice)))
-						bpctl_dev_arr[idx_dev].
-						    bp_fw_ver = 0xff;
-					else
-						bpctl_dev_arr[idx_dev].
-						    bp_fw_ver =
-						    bypass_fw_ver(&bpctl_dev_arr
-								  [idx_dev]);
-					if ((bpctl_dev_arr[idx_dev].bp_10gb ==
-					     1)
-					    && (bpctl_dev_arr[idx_dev].
-						bp_fw_ver == 0xff)) {
-						int cnt = 100;
-						while (cnt--) {
-							iounmap((void
-								 *)
-								(bpctl_dev_arr
-								 [idx_dev].
-								 mem_map));
-							mmio_start =
-							    pci_resource_start
-							    (pdev1, 0);
-							mmio_len =
-							    pci_resource_len
-							    (pdev1, 0);
-
-							bpctl_dev_arr[idx_dev].
-							    mem_map =
-							    (unsigned long)
-							    ioremap(mmio_start,
-								    mmio_len);
-
-							bpctl_dev_arr[idx_dev].
-							    bp_fw_ver =
-							    bypass_fw_ver
-							    (&bpctl_dev_arr
-							     [idx_dev]);
-							if (bpctl_dev_arr
-							    [idx_dev].
-							    bp_fw_ver == 0xa8)
-								break;
-
-						}
-					}
-					/* bpctl_dev_arr[idx_dev].bp_fw_ver=0xa8; */
-					printk("firmware version: 0x%x\n",
-					       bpctl_dev_arr[idx_dev].
-					       bp_fw_ver);
-				}
-				bpctl_dev_arr[idx_dev].wdt_status =
-				    WDT_STATUS_UNKNOWN;
-				bpctl_dev_arr[idx_dev].reset_time = 0;
-				atomic_set(&bpctl_dev_arr[idx_dev].wdt_busy, 0);
-				bpctl_dev_arr[idx_dev].bp_status_un = 1;
-
-				bypass_caps_init(&bpctl_dev_arr[idx_dev]);
-
-				init_bypass_wd_auto(&bpctl_dev_arr[idx_dev]);
-				init_bypass_tpl_auto(&bpctl_dev_arr[idx_dev]);
-				if (NOKIA_SERIES
-				    (bpctl_dev_arr[idx_dev].subdevice))
-					reset_cont(&bpctl_dev_arr[idx_dev]);
-			}
-#ifdef BP_SELF_TEST
-			if ((bpctl_dev_arr[idx_dev].bp_tx_data =
-			     kmalloc(BPTEST_DATA_LEN, GFP_KERNEL))) {
-
-				memset(bpctl_dev_arr[idx_dev].bp_tx_data, 0x0,
-				       BPTEST_DATA_LEN);
-
-				memset(bpctl_dev_arr[idx_dev].bp_tx_data, 0xff,
-				       6);
-				memset(bpctl_dev_arr[idx_dev].bp_tx_data + 6,
-				       0x0, 1);
-				memset(bpctl_dev_arr[idx_dev].bp_tx_data + 7,
-				       0xaa, 5);
-
-				*(__be16 *) (bpctl_dev_arr[idx_dev].bp_tx_data +
-					     12) = htons(ETH_P_BPTEST);
-
-			} else
-				printk("bp_ctl: Memory allocation error!\n");
-#endif
-			idx_dev++;
-
+			if (init_one(dev, &tx_ctl_pci_tbl[idx], pdev1) < 0)
+				return -1;
+			dev++;
 		}
 	}
 	if_scan_init();
@@ -6913,33 +6805,27 @@ static int __init bypass_init_module(void)
 	{
 
 		bpctl_dev_t *pbpctl_dev_c = NULL;
-		for (idx_dev = 0;
-		     ((bpctl_dev_arr[idx_dev].pdev != NULL)
-		      && (idx_dev < device_num)); idx_dev++) {
-			if (bpctl_dev_arr[idx_dev].bp_10g9) {
-				pbpctl_dev_c =
-				    get_status_port_fn(&bpctl_dev_arr[idx_dev]);
-				if (is_bypass_fn(&bpctl_dev_arr[idx_dev])) {
+		for (idx_dev = 0, dev = bpctl_dev_arr;
+		     idx_dev < device_num && dev->pdev;
+		     idx_dev++, dev++) {
+			if (dev->bp_10g9) {
+				pbpctl_dev_c = get_status_port_fn(dev);
+				if (is_bypass_fn(dev)) {
 					printk(KERN_INFO "%s found, ",
-					       bpctl_dev_arr[idx_dev].name);
-					bpctl_dev_arr[idx_dev].bp_fw_ver =
-					    bypass_fw_ver(&bpctl_dev_arr
-							  [idx_dev]);
+					       dev->name);
+					dev->bp_fw_ver = bypass_fw_ver(dev);
 					printk("firmware version: 0x%x\n",
-					       bpctl_dev_arr[idx_dev].
-					       bp_fw_ver);
-
+					       dev->bp_fw_ver);
 				}
-				bpctl_dev_arr[idx_dev].wdt_status =
-				    WDT_STATUS_UNKNOWN;
-				bpctl_dev_arr[idx_dev].reset_time = 0;
-				atomic_set(&bpctl_dev_arr[idx_dev].wdt_busy, 0);
-				bpctl_dev_arr[idx_dev].bp_status_un = 1;
+				dev->wdt_status = WDT_STATUS_UNKNOWN;
+				dev->reset_time = 0;
+				atomic_set(&dev->wdt_busy, 0);
+				dev->bp_status_un = 1;
 
-				bypass_caps_init(&bpctl_dev_arr[idx_dev]);
+				bypass_caps_init(dev);
 
-				init_bypass_wd_auto(&bpctl_dev_arr[idx_dev]);
-				init_bypass_tpl_auto(&bpctl_dev_arr[idx_dev]);
+				init_bypass_wd_auto(dev);
+				init_bypass_tpl_auto(dev);
 
 			}
 
@@ -6983,7 +6869,7 @@ static void __exit bypass_cleanup_module(void)
 /*	spin_lock_irqsave(&bpvm_lock, flags);
 	rcu_read_lock(); */
 		bypass_proc_remove_dev_sd(&bpctl_dev_arr[i]);
-/*	spin_unlock_irqrestore(&bpvm_lock, flags);        
+/*	spin_unlock_irqrestore(&bpvm_lock, flags);
 	rcu_read_unlock(); */
 #endif
 		remove_bypass_wd_auto(&bpctl_dev_arr[i]);
@@ -6995,18 +6881,16 @@ static void __exit bypass_cleanup_module(void)
 	/* unmap all devices */
 	for (i = 0; i < device_num; i++) {
 #ifdef BP_SELF_TEST
-		if (bpctl_dev_arr[i].bp_tx_data)
-			kfree(bpctl_dev_arr[i].bp_tx_data);
+		kfree(bpctl_dev_arr[i].bp_tx_data);
 #endif
 		iounmap((void *)(bpctl_dev_arr[i].mem_map));
 	}
 
 	/* free all devices space */
-	if (bpctl_dev_arr)
-		kfree(bpctl_dev_arr);
+	kfree(bpctl_dev_arr);
 
 /*
-* Unregister the device                             
+* Unregister the device
 */
 	unregister_chrdev(major_num, DEVICE_NAME);
 }
@@ -7338,78 +7222,11 @@ EXPORT_SYMBOL_NOVERS(bp_if_scan_sd);
 
 #define BP_PROC_DIR "bypass"
 
-#define GPIO6_SET_ENTRY_SD           "gpio6_set"
-#define GPIO6_CLEAR_ENTRY_SD         "gpio6_clear"
-
-#define GPIO7_SET_ENTRY_SD           "gpio7_set"
-#define GPIO7_CLEAR_ENTRY_SD         "gpio7_clear"
-
-#define PULSE_SET_ENTRY_SD            "pulse_set"
-#define ZERO_SET_ENTRY_SD            "zero_set"
-#define PULSE_GET1_ENTRY_SD            "pulse_get1"
-#define PULSE_GET2_ENTRY_SD            "pulse_get2"
-
-#define CMND_ON_ENTRY_SD              "cmnd_on"
-#define CMND_OFF_ENTRY_SD             "cmnd_off"
-#define RESET_CONT_ENTRY_SD           "reset_cont"
-
- /*COMMANDS*/
-#define BYPASS_INFO_ENTRY_SD     "bypass_info"
-#define BYPASS_SLAVE_ENTRY_SD    "bypass_slave"
-#define BYPASS_CAPS_ENTRY_SD     "bypass_caps"
-#define WD_SET_CAPS_ENTRY_SD     "wd_set_caps"
-#define BYPASS_ENTRY_SD          "bypass"
-#define BYPASS_CHANGE_ENTRY_SD   "bypass_change"
-#define BYPASS_WD_ENTRY_SD       "bypass_wd"
-#define WD_EXPIRE_TIME_ENTRY_SD  "wd_expire_time"
-#define RESET_BYPASS_WD_ENTRY_SD "reset_bypass_wd"
-#define DIS_BYPASS_ENTRY_SD      "dis_bypass"
-#define BYPASS_PWUP_ENTRY_SD     "bypass_pwup"
-#define BYPASS_PWOFF_ENTRY_SD     "bypass_pwoff"
-#define STD_NIC_ENTRY_SD         "std_nic"
-#define STD_NIC_ENTRY_SD         "std_nic"
-#define TAP_ENTRY_SD             "tap"
-#define TAP_CHANGE_ENTRY_SD      "tap_change"
-#define DIS_TAP_ENTRY_SD         "dis_tap"
-#define TAP_PWUP_ENTRY_SD        "tap_pwup"
-#define TWO_PORT_LINK_ENTRY_SD   "two_port_link"
-#define WD_EXP_MODE_ENTRY_SD     "wd_exp_mode"
-#define WD_AUTORESET_ENTRY_SD    "wd_autoreset"
-#define TPL_ENTRY_SD             "tpl"
-#define WAIT_AT_PWUP_ENTRY_SD    "wait_at_pwup"
-#define HW_RESET_ENTRY_SD        "hw_reset"
-#define DISC_ENTRY_SD             "disc"
-#define DISC_CHANGE_ENTRY_SD      "disc_change"
-#define DIS_DISC_ENTRY_SD         "dis_disc"
-#define DISC_PWUP_ENTRY_SD        "disc_pwup"
 static struct proc_dir_entry *bp_procfs_dir;
 
-static struct proc_dir_entry *proc_getdir(char *name,
-					  struct proc_dir_entry *proc_dir)
-{
-	struct proc_dir_entry *pde = proc_dir;
-
-	for (pde = pde->subdir; pde; pde = pde->next) {
-		if (pde->namelen && (strcmp(name, pde->name) == 0)) {
-			/* directory exists */
-			break;
-		}
-	}
-	if (pde == (struct proc_dir_entry *)0) {
-		/* create the directory */
-		pde = proc_mkdir(name, proc_dir);
-		if (pde == (struct proc_dir_entry *)0) {
-
-			return pde;
-		}
-	}
-
-	return pde;
-}
-
 int bp_proc_create(void)
 {
-	bp_procfs_dir = proc_getdir(BP_PROC_DIR, init_net.proc_net);
+	bp_procfs_dir = proc_mkdir(BP_PROC_DIR, init_net.proc_net);
 	if (bp_procfs_dir == (struct proc_dir_entry *)0) {
 		printk(KERN_DEBUG
 		       "Could not create procfs nicinfo directory %s\n",
@@ -7419,144 +7236,99 @@ int bp_proc_create(void)
 	return 0;
 }
 
-int
-bypass_proc_create_entry_sd(struct pfs_unit_sd *pfs_unit_curr,
-			    char *proc_name,
-			    write_proc_t *write_proc,
-			    read_proc_t *read_proc,
-			    struct proc_dir_entry *parent_pfs, void *data)
+static int procfs_add(char *proc_name, const struct file_operations *fops,
+		      bpctl_dev_t *dev)
 {
-	strcpy(pfs_unit_curr->proc_name, proc_name);
-	pfs_unit_curr->proc_entry = create_proc_entry(pfs_unit_curr->proc_name,
-						      S_IFREG | S_IRUSR |
-						      S_IWUSR | S_IRGRP |
-						      S_IROTH, parent_pfs);
-	if (pfs_unit_curr->proc_entry == NULL)
+	struct bypass_pfs_sd *pfs = &dev->bypass_pfs_set;
+	if (!proc_create_data(proc_name, 0644, pfs->bypass_entry, fops, dev))
 		return -1;
-
-	pfs_unit_curr->proc_entry->read_proc = read_proc;
-	pfs_unit_curr->proc_entry->write_proc = write_proc;
-	pfs_unit_curr->proc_entry->data = data;
-
 	return 0;
-
 }
 
-int
-get_bypass_info_pfs(char *page, char **start, off_t off, int count,
-		    int *eof, void *data)
-{
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-	int len = 0;
-
-	len += sprintf(page, "Name\t\t\t%s\n", pbp_device_block->name);
-	len +=
-	    sprintf(page + len, "Firmware version\t0x%x\n",
-		    pbp_device_block->bp_fw_ver);
+#define RO_FOPS(name)	\
+static int name##_open(struct inode *inode, struct file *file)	\
+{								\
+	return single_open(file, show_##name, PDE_DATA(inode));\
+}								\
+static const struct file_operations name##_ops = {		\
+	.open = name##_open,					\
+	.read = seq_read,					\
+	.llseek = seq_lseek,					\
+	.release = single_release,				\
+};
 
-	*eof = 1;
-	return len;
-}
+#define RW_FOPS(name)	\
+static int name##_open(struct inode *inode, struct file *file)	\
+{								\
+	return single_open(file, show_##name, PDE_DATA(inode));\
+}								\
+static const struct file_operations name##_ops = {		\
+	.open = name##_open,					\
+	.read = seq_read,					\
+	.write = name##_write,					\
+	.llseek = seq_lseek,					\
+	.release = single_release,				\
+};
 
-int
-get_bypass_slave_pfs(char *page, char **start, off_t off, int count,
-		     int *eof, void *data)
+static int show_bypass_info(struct seq_file *m, void *v)
 {
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0;
-	bpctl_dev_t *pbp_device_block_slave = NULL;
-	int idx_dev = 0;
-	struct net_device *net_slave_dev = NULL;
-
-	if ((pbp_device_block->func == 0) || (pbp_device_block->func == 2)) {
-		for (idx_dev = 0;
-		     ((bpctl_dev_arr[idx_dev].pdev != NULL)
-		      && (idx_dev < device_num)); idx_dev++) {
-			if ((bpctl_dev_arr[idx_dev].bus ==
-			     pbp_device_block->bus)
-			    && (bpctl_dev_arr[idx_dev].slot ==
-				pbp_device_block->slot)) {
-				if ((pbp_device_block->func == 0)
-				    && (bpctl_dev_arr[idx_dev].func == 1)) {
-					pbp_device_block_slave =
-					    &bpctl_dev_arr[idx_dev];
-					break;
-				}
-				if ((pbp_device_block->func == 2) &&
-				    (bpctl_dev_arr[idx_dev].func == 3)) {
-					pbp_device_block_slave =
-					    &bpctl_dev_arr[idx_dev];
-					break;
-				}
-			}
-		}
-	} else
-		pbp_device_block_slave = pbp_device_block;
-	if (!pbp_device_block_slave) {
-		len = sprintf(page, "fail\n");
-		*eof = 1;
-		return len;
-	}
-	net_slave_dev = pbp_device_block_slave->ndev;
-	if (net_slave_dev)
-		len = sprintf(page, "%s\n", net_slave_dev->name);
+	bpctl_dev_t *dev = m->private;
 
-	*eof = 1;
-	return len;
+	seq_printf(m, "Name\t\t\t%s\n", dev->name);
+	seq_printf(m, "Firmware version\t0x%x\n", dev->bp_fw_ver);
+	return 0;
 }
+RO_FOPS(bypass_info)
 
-int
-get_bypass_caps_pfs(char *page, char **start, off_t off, int count,
-		    int *eof, void *data)
+static int show_bypass_slave(struct seq_file *m, void *v)
 {
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
+	bpctl_dev_t *dev = m->private;
+	bpctl_dev_t *slave = get_status_port_fn(dev);
+	if (!slave)
+		slave = dev;
+	if (!slave)
+		seq_printf(m, "fail\n");
+	else if (slave->ndev)
+		seq_printf(m, "%s\n", slave->ndev->name);
+	return 0;
+}
+RO_FOPS(bypass_slave)
 
-	ret = get_bypass_caps_fn(pbp_device_block);
+static int show_bypass_caps(struct seq_file *m, void *v)
+{
+	bpctl_dev_t *dev = m->private;
+	int ret = get_bypass_caps_fn(dev);
 	if (ret == BP_NOT_CAP)
-		len = sprintf(page, "-1\n");
+		seq_printf(m, "-1\n");
 	else
-		len = sprintf(page, "0x%x\n", ret);
-	*eof = 1;
-	return len;
-
+		seq_printf(m, "0x%x\n", ret);
+	return 0;
 }
+RO_FOPS(bypass_caps)
 
-int
-get_wd_set_caps_pfs(char *page, char **start, off_t off, int count,
-		    int *eof, void *data)
+static int show_wd_set_caps(struct seq_file *m, void *v)
 {
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
-
-	ret = get_wd_set_caps_fn(pbp_device_block);
+	bpctl_dev_t *dev = m->private;
+	int ret = get_wd_set_caps_fn(dev);
 	if (ret == BP_NOT_CAP)
-		len = sprintf(page, "-1\n");
+		seq_printf(m, "-1\n");
 	else
-		len = sprintf(page, "0x%x\n", ret);
-	*eof = 1;
-	return len;
+		seq_printf(m, "0x%x\n", ret);
+	return 0;
 }
+RO_FOPS(wd_set_caps)
 
-int
-set_bypass_pfs(struct file *file, const char *buffer,
-	       unsigned long count, void *data)
+static int user_on_off(const void __user *buffer, size_t count)
 {
 
 	char kbuf[256];
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int bypass_param = 0, length = 0;
+	int length = 0;
 
 	if (count > (sizeof(kbuf) - 1))
 		return -1;
 
-	if (copy_from_user(&kbuf, buffer, count)) {
+	if (copy_from_user(&kbuf, buffer, count))
 		return -1;
-	}
 
 	kbuf[count] = '\0';
 	length = strlen(kbuf);
@@ -7564,806 +7336,467 @@ set_bypass_pfs(struct file *file, const char *buffer,
 		kbuf[--length] = '\0';
 
 	if (strcmp(kbuf, "on") == 0)
-		bypass_param = 1;
-	else if (strcmp(kbuf, "off") == 0)
-		bypass_param = 0;
-
-	set_bypass_fn(pbp_device_block, bypass_param);
-
-	return count;
+		return 1;
+	if (strcmp(kbuf, "off") == 0)
+		return 0;
+	return 0;
 }
 
-int
-set_tap_pfs(struct file *file, const char *buffer,
-	    unsigned long count, void *data)
+static ssize_t bypass_write(struct file *file, const char __user *buffer,
+				  size_t count, loff_t *pos)
 {
-
-	char kbuf[256];
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int tap_param = 0, length = 0;
-
-	if (count > (sizeof(kbuf) - 1))
+	int bypass_param = user_on_off(buffer, count);
+	if (bypass_param < 0)
 		return -1;
 
-	if (copy_from_user(&kbuf, buffer, count)) {
-		return -1;
-	}
-
-	kbuf[count] = '\0';
-	length = strlen(kbuf);
-	if (kbuf[length - 1] == '\n')
-		kbuf[--length] = '\0';
-
-	if (strcmp(kbuf, "on") == 0)
-		tap_param = 1;
-	else if (strcmp(kbuf, "off") == 0)
-		tap_param = 0;
-
-	set_tap_fn(pbp_device_block, tap_param);
-
+	set_bypass_fn(PDE_DATA(file_inode(file)), bypass_param);
 	return count;
 }
-
-int
-set_disc_pfs(struct file *file, const char *buffer,
-	     unsigned long count, void *data)
+static int show_bypass(struct seq_file *m, void *v)
 {
+	bpctl_dev_t *dev = m->private;
+	int ret = get_bypass_fn(dev);
+	if (ret == BP_NOT_CAP)
+		seq_printf(m, "fail\n");
+	else if (ret == 1)
+		seq_printf(m, "on\n");
+	else if (ret == 0)
+		seq_printf(m, "off\n");
+	return 0;
+}
+RW_FOPS(bypass)
 
-	char kbuf[256];
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int tap_param = 0, length = 0;
-
-	if (count > (sizeof(kbuf) - 1))
-		return -1;
-
-	if (copy_from_user(&kbuf, buffer, count)) {
+static ssize_t tap_write(struct file *file, const char __user *buffer,
+				  size_t count, loff_t *pos)
+{
+	int tap_param = user_on_off(buffer, count);
+	if (tap_param < 0)
 		return -1;
-	}
-
-	kbuf[count] = '\0';
-	length = strlen(kbuf);
-	if (kbuf[length - 1] == '\n')
-		kbuf[--length] = '\0';
-
-	if (strcmp(kbuf, "on") == 0)
-		tap_param = 1;
-	else if (strcmp(kbuf, "off") == 0)
-		tap_param = 0;
-
-	set_disc_fn(pbp_device_block, tap_param);
 
+	set_tap_fn(PDE_DATA(file_inode(file)), tap_param);
 	return count;
 }
-
-int
-get_bypass_pfs(char *page, char **start, off_t off, int count,
-	       int *eof, void *data)
+static int show_tap(struct seq_file *m, void *v)
 {
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
-
-	ret = get_bypass_fn(pbp_device_block);
+	bpctl_dev_t *dev = m->private;
+	int ret = get_tap_fn(dev);
 	if (ret == BP_NOT_CAP)
-		len = sprintf(page, "fail\n");
+		seq_printf(m, "fail\n");
 	else if (ret == 1)
-		len = sprintf(page, "on\n");
+		seq_printf(m, "on\n");
 	else if (ret == 0)
-		len = sprintf(page, "off\n");
-
-	*eof = 1;
-	return len;
+		seq_printf(m, "off\n");
+	return 0;
 }
+RW_FOPS(tap)
 
-int
-get_tap_pfs(char *page, char **start, off_t off, int count,
-	    int *eof, void *data)
+static ssize_t disc_write(struct file *file, const char __user *buffer,
+				  size_t count, loff_t *pos)
 {
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
-
-	ret = get_tap_fn(pbp_device_block);
-	if (ret == BP_NOT_CAP)
-		len = sprintf(page, "fail\n");
-	else if (ret == 1)
-		len = sprintf(page, "on\n");
-	else if (ret == 0)
-		len = sprintf(page, "off\n");
+	int tap_param = user_on_off(buffer, count);
+	if (tap_param < 0)
+		return -1;
 
-	*eof = 1;
-	return len;
+	set_disc_fn(PDE_DATA(file_inode(file)), tap_param);
+	return count;
 }
-
-int
-get_disc_pfs(char *page, char **start, off_t off, int count,
-	     int *eof, void *data)
+static int show_disc(struct seq_file *m, void *v)
 {
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
-
-	ret = get_disc_fn(pbp_device_block);
+	bpctl_dev_t *dev = m->private;
+	int ret = get_disc_fn(dev);
 	if (ret == BP_NOT_CAP)
-		len = sprintf(page, "fail\n");
+		seq_printf(m, "fail\n");
 	else if (ret == 1)
-		len = sprintf(page, "on\n");
+		seq_printf(m, "on\n");
 	else if (ret == 0)
-		len = sprintf(page, "off\n");
-
-	*eof = 1;
-	return len;
+		seq_printf(m, "off\n");
+	return 0;
 }
+RW_FOPS(disc)
 
-int
-get_bypass_change_pfs(char *page, char **start, off_t off, int count,
-		      int *eof, void *data)
+static int show_bypass_change(struct seq_file *m, void *v)
 {
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
-
-	ret = get_bypass_change_fn(pbp_device_block);
+	bpctl_dev_t *dev = m->private;
+	int ret = get_bypass_change_fn(dev);
 	if (ret == 1)
-		len = sprintf(page, "on\n");
+		seq_printf(m, "on\n");
 	else if (ret == 0)
-		len = sprintf(page, "off\n");
+		seq_printf(m, "off\n");
 	else
-		len = sprintf(page, "fail\n");
-
-	*eof = 1;
-	return len;
+		seq_printf(m, "fail\n");
+	return 0;
 }
+RO_FOPS(bypass_change)
 
-int
-get_tap_change_pfs(char *page, char **start, off_t off, int count,
-		   int *eof, void *data)
+static int show_tap_change(struct seq_file *m, void *v)
 {
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
-
-	ret = get_tap_change_fn(pbp_device_block);
+	bpctl_dev_t *dev = m->private;
+	int ret = get_tap_change_fn(dev);
 	if (ret == 1)
-		len = sprintf(page, "on\n");
+		seq_printf(m, "on\n");
 	else if (ret == 0)
-		len = sprintf(page, "off\n");
+		seq_printf(m, "off\n");
 	else
-		len = sprintf(page, "fail\n");
-
-	*eof = 1;
-	return len;
+		seq_printf(m, "fail\n");
+	return 0;
 }
+RO_FOPS(tap_change)
 
-int
-get_disc_change_pfs(char *page, char **start, off_t off, int count,
-		    int *eof, void *data)
+static int show_disc_change(struct seq_file *m, void *v)
 {
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
-
-	ret = get_disc_change_fn(pbp_device_block);
+	bpctl_dev_t *dev = m->private;
+	int ret = get_disc_change_fn(dev);
 	if (ret == 1)
-		len = sprintf(page, "on\n");
+		seq_printf(m, "on\n");
 	else if (ret == 0)
-		len = sprintf(page, "off\n");
+		seq_printf(m, "off\n");
 	else
-		len = sprintf(page, "fail\n");
-
-	*eof = 1;
-	return len;
-}
-
-#define isdigit(c) (c >= '0' && c <= '9')
-__inline static int atoi(char **s)
-{
-	int i = 0;
-	while (isdigit(**s))
-		i = i * 10 + *((*s)++) - '0';
-	return i;
+		seq_printf(m, "fail\n");
+	return 0;
 }
+RO_FOPS(disc_change)
 
-int
-set_bypass_wd_pfs(struct file *file, const char *buffer,
-		  unsigned long count, void *data)
+static ssize_t bypass_wd_write(struct file *file, const char __user *buffer,
+				  size_t count, loff_t *pos)
 {
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
+	bpctl_dev_t *dev = PDE_DATA(file_inode(file));
 	int timeout;
-	int ret;
-
-	ret = kstrtoint_from_user(buffer, count, 10, &timeout);
+	int ret = kstrtoint_from_user(buffer, count, 10, &timeout);
 	if (ret)
 		return ret;
-	set_bypass_wd_fn(pbp_device_block, timeout);
-
+	set_bypass_wd_fn(dev, timeout);
 	return count;
 }
-
-int
-get_bypass_wd_pfs(char *page, char **start, off_t off, int count,
-		  int *eof, void *data)
+static int show_bypass_wd(struct seq_file *m, void *v)
 {
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
+	bpctl_dev_t *dev = m->private;
+	int ret = 0, timeout = 0;
 
-	int len = 0, ret = 0, timeout = 0;
-
-	ret = get_bypass_wd_fn(pbp_device_block, &timeout);
+	ret = get_bypass_wd_fn(dev, &timeout);
 	if (ret == BP_NOT_CAP)
-		len = sprintf(page, "fail\n");
+		seq_printf(m,  "fail\n");
 	else if (timeout == -1)
-		len = sprintf(page, "unknown\n");
+		seq_printf(m,  "unknown\n");
 	else if (timeout == 0)
-		len = sprintf(page, "disable\n");
+		seq_printf(m,  "disable\n");
 	else
-		len = sprintf(page, "%d\n", timeout);
-
-	*eof = 1;
-	return len;
+		seq_printf(m, "%d\n", timeout);
+	return 0;
 }
+RW_FOPS(bypass_wd)
 
-int
-get_wd_expire_time_pfs(char *page, char **start, off_t off, int count,
-		       int *eof, void *data)
+static int show_wd_expire_time(struct seq_file *m, void *v)
 {
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0, timeout = 0;
-
-	ret = get_wd_expire_time_fn(pbp_device_block, &timeout);
+	bpctl_dev_t *dev = m->private;
+	int ret = 0, timeout = 0;
+	ret = get_wd_expire_time_fn(dev, &timeout);
 	if (ret == BP_NOT_CAP)
-		len = sprintf(page, "fail\n");
+		seq_printf(m, "fail\n");
 	else if (timeout == -1)
-		len = sprintf(page, "expire\n");
+		seq_printf(m, "expire\n");
 	else if (timeout == 0)
-		len = sprintf(page, "disable\n");
-
+		seq_printf(m, "disable\n");
 	else
-		len = sprintf(page, "%d\n", timeout);
-	*eof = 1;
-	return len;
+		seq_printf(m, "%d\n", timeout);
+	return 0;
 }
+RO_FOPS(wd_expire_time)
 
-int
-get_tpl_pfs(char *page, char **start, off_t off, int count,
-	    int *eof, void *data)
+static ssize_t tpl_write(struct file *file, const char __user *buffer,
+				  size_t count, loff_t *pos)
 {
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
+	bpctl_dev_t *dev = PDE_DATA(file_inode(file));
+	int tpl_param = user_on_off(buffer, count);
+	if (tpl_param < 0)
+		return -1;
 
-	ret = get_tpl_fn(pbp_device_block);
+	set_tpl_fn(dev, tpl_param);
+	return count;
+}
+static int show_tpl(struct seq_file *m, void *v)
+{
+	bpctl_dev_t *dev = m->private;
+	int ret = get_tpl_fn(dev);
 	if (ret == BP_NOT_CAP)
-		len = sprintf(page, "fail\n");
+		seq_printf(m, "fail\n");
 	else if (ret == 1)
-		len = sprintf(page, "on\n");
+		seq_printf(m, "on\n");
 	else if (ret == 0)
-		len = sprintf(page, "off\n");
-
-	*eof = 1;
-	return len;
+		seq_printf(m, "off\n");
+	return 0;
 }
+RW_FOPS(tpl)
 
 #ifdef PMC_FIX_FLAG
-int
-get_wait_at_pwup_pfs(char *page, char **start, off_t off, int count,
-		     int *eof, void *data)
+static ssize_t wait_at_pwup_write(struct file *file, const char __user *buffer,
+				  size_t count, loff_t *pos)
 {
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
+	bpctl_dev_t *dev = PDE_DATA(file_inode(file));
+	int tpl_param = user_on_off(buffer, count);
+	if (tpl_param < 0)
+		return -1;
 
-	ret = get_bp_wait_at_pwup_fn(pbp_device_block);
+	set_bp_wait_at_pwup_fn(dev, tpl_param);
+	return count;
+}
+static int show_wait_at_pwup(struct seq_file *m, void *v)
+{
+	bpctl_dev_t *dev = m->private;
+	int ret = get_bp_wait_at_pwup_fn(dev);
 	if (ret == BP_NOT_CAP)
-		len = sprintf(page, "fail\n");
+		seq_printf(m, "fail\n");
 	else if (ret == 1)
-		len = sprintf(page, "on\n");
+		seq_printf(m, "on\n");
 	else if (ret == 0)
-		len = sprintf(page, "off\n");
-
-	*eof = 1;
-	return len;
+		seq_printf(m, "off\n");
+	return 0;
 }
+RW_FOPS(wait_at_pwup)
 
-int
-get_hw_reset_pfs(char *page, char **start, off_t off, int count,
-		 int *eof, void *data)
+static ssize_t hw_reset_write(struct file *file, const char __user *buffer,
+				  size_t count, loff_t *pos)
 {
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
+	bpctl_dev_t *dev = PDE_DATA(file_inode(file));
+	int tpl_param = user_on_off(buffer, count);
+	if (tpl_param < 0)
+		return -1;
 
-	ret = get_bp_hw_reset_fn(pbp_device_block);
+	set_bp_hw_reset_fn(dev, tpl_param);
+	return count;
+}
+static int show_hw_reset(struct seq_file *m, void *v)
+{
+	bpctl_dev_t *dev = m->private;
+	int ret = get_bp_hw_reset_fn(dev);
 	if (ret == BP_NOT_CAP)
-		len = sprintf(page, "fail\n");
+		seq_printf(m, "fail\n");
 	else if (ret == 1)
-		len = sprintf(page, "on\n");
+		seq_printf(m, "on\n");
 	else if (ret == 0)
-		len = sprintf(page, "off\n");
-
-	*eof = 1;
-	return len;
+		seq_printf(m, "off\n");
+	return 0;
 }
+RW_FOPS(hw_reset)
 
 #endif				/*PMC_WAIT_FLAG */
 
-int
-reset_bypass_wd_pfs(char *page, char **start, off_t off, int count,
-		    int *eof, void *data)
+static int show_reset_bypass_wd(struct seq_file *m, void *v)
 {
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
-
-	ret = reset_bypass_wd_timer_fn(pbp_device_block);
+	bpctl_dev_t *dev = m->private;
+	int ret = reset_bypass_wd_timer_fn(dev);
 	if (ret == BP_NOT_CAP)
-		len = sprintf(page, "fail\n");
+		seq_printf(m, "fail\n");
 	else if (ret == 0)
-		len = sprintf(page, "disable\n");
+		seq_printf(m, "disable\n");
 	else if (ret == 1)
-		len = sprintf(page, "success\n");
-
-	*eof = 1;
-	return len;
+		seq_printf(m, "success\n");
+	return 0;
 }
+RO_FOPS(reset_bypass_wd)
 
-int
-set_dis_bypass_pfs(struct file *file, const char *buffer,
-		   unsigned long count, void *data)
+static ssize_t dis_bypass_write(struct file *file, const char __user *buffer,
+				  size_t count, loff_t *pos)
 {
-
-	char kbuf[256];
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int bypass_param = 0, length = 0;
-
-	if (count >= sizeof(kbuf))
+	int bypass_param = user_on_off(buffer, count);
+	if (bypass_param < 0)
 		return -EINVAL;
 
-	if (copy_from_user(&kbuf, buffer, count)) {
-		return -1;
-	}
-
-	kbuf[count] = '\0';
-	length = strlen(kbuf);
-	if (kbuf[length - 1] == '\n')
-		kbuf[--length] = '\0';
-
-	if (strcmp(kbuf, "on") == 0)
-		bypass_param = 1;
-	else if (strcmp(kbuf, "off") == 0)
-		bypass_param = 0;
-
-	set_dis_bypass_fn(pbp_device_block, bypass_param);
-
+	set_dis_bypass_fn(PDE_DATA(file_inode(file)), bypass_param);
 	return count;
 }
-
-int
-set_dis_tap_pfs(struct file *file, const char *buffer,
-		unsigned long count, void *data)
+static int show_dis_bypass(struct seq_file *m, void *v)
 {
-
-	char kbuf[256];
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int tap_param = 0, length = 0;
-
-	if (count >= sizeof(kbuf))
-		return -EINVAL;
-
-	if (copy_from_user(&kbuf, buffer, count)) {
-		return -1;
-	}
-
-	kbuf[count] = '\0';
-	length = strlen(kbuf);
-	if (kbuf[length - 1] == '\n')
-		kbuf[--length] = '\0';
-
-	if (strcmp(kbuf, "on") == 0)
-		tap_param = 1;
-	else if (strcmp(kbuf, "off") == 0)
-		tap_param = 0;
-
-	set_dis_tap_fn(pbp_device_block, tap_param);
-
-	return count;
+	bpctl_dev_t *dev = m->private;
+	int ret = get_dis_bypass_fn(dev);
+	if (ret == BP_NOT_CAP)
+		seq_printf(m, "fail\n");
+	else if (ret == 0)
+		seq_printf(m, "off\n");
+	else
+		seq_printf(m, "on\n");
+	return 0;
 }
+RW_FOPS(dis_bypass)
 
-int
-set_dis_disc_pfs(struct file *file, const char *buffer,
-		 unsigned long count, void *data)
+static ssize_t dis_tap_write(struct file *file, const char __user *buffer,
+				  size_t count, loff_t *pos)
 {
-
-	char kbuf[256];
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int tap_param = 0, length = 0;
-
-	if (count >= sizeof(kbuf))
+	int tap_param = user_on_off(buffer, count);
+	if (tap_param < 0)
 		return -EINVAL;
 
-	if (copy_from_user(&kbuf, buffer, count)) {
-		return -1;
-	}
-
-	kbuf[count] = '\0';
-	length = strlen(kbuf);
-	if (kbuf[length - 1] == '\n')
-		kbuf[--length] = '\0';
-
-	if (strcmp(kbuf, "on") == 0)
-		tap_param = 1;
-	else if (strcmp(kbuf, "off") == 0)
-		tap_param = 0;
-
-	set_dis_disc_fn(pbp_device_block, tap_param);
-
+	set_dis_tap_fn(PDE_DATA(file_inode(file)), tap_param);
 	return count;
 }
-
-int
-get_dis_bypass_pfs(char *page, char **start, off_t off, int count,
-		   int *eof, void *data)
+static int show_dis_tap(struct seq_file *m, void *v)
 {
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
-
-	ret = get_dis_bypass_fn(pbp_device_block);
+	bpctl_dev_t *dev = m->private;
+	int ret = get_dis_tap_fn(dev);
 	if (ret == BP_NOT_CAP)
-		len = sprintf(page, "fail\n");
+		seq_printf(m, "fail\n");
 	else if (ret == 0)
-		len = sprintf(page, "off\n");
+		seq_printf(m, "off\n");
 	else
-		len = sprintf(page, "on\n");
-
-	*eof = 1;
-	return len;
+		seq_printf(m, "on\n");
+	return 0;
 }
+RW_FOPS(dis_tap)
 
-int
-get_dis_tap_pfs(char *page, char **start, off_t off, int count,
-		int *eof, void *data)
+static ssize_t dis_disc_write(struct file *file, const char __user *buffer,
+				  size_t count, loff_t *pos)
 {
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
-
-	ret = get_dis_tap_fn(pbp_device_block);
-	if (ret == BP_NOT_CAP)
-		len = sprintf(page, "fail\n");
-	else if (ret == 0)
-		len = sprintf(page, "off\n");
-	else
-		len = sprintf(page, "on\n");
+	int tap_param = user_on_off(buffer, count);
+	if (tap_param < 0)
+		return -EINVAL;
 
-	*eof = 1;
-	return len;
+	set_dis_disc_fn(PDE_DATA(file_inode(file)), tap_param);
+	return count;
 }
-
-int
-get_dis_disc_pfs(char *page, char **start, off_t off, int count,
-		 int *eof, void *data)
+static int show_dis_disc(struct seq_file *m, void *v)
 {
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
-
-	ret = get_dis_disc_fn(pbp_device_block);
+	bpctl_dev_t *dev = m->private;
+	int ret = get_dis_disc_fn(dev);
 	if (ret == BP_NOT_CAP)
-		len = sprintf(page, "fail\n");
+		seq_printf(m, "fail\n");
 	else if (ret == 0)
-		len = sprintf(page, "off\n");
+		seq_printf(m, "off\n");
 	else
-		len = sprintf(page, "on\n");
-
-	*eof = 1;
-	return len;
+		seq_printf(m, "on\n");
+	return 0;
 }
+RW_FOPS(dis_disc)
 
-int
-set_bypass_pwup_pfs(struct file *file, const char *buffer,
-		    unsigned long count, void *data)
+static ssize_t bypass_pwup_write(struct file *file, const char __user *buffer,
+				  size_t count, loff_t *pos)
 {
-
-	char kbuf[256];
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int bypass_param = 0, length = 0;
-
-	if (count >= sizeof(kbuf))
+	int bypass_param = user_on_off(buffer, count);
+	if (bypass_param < 0)
 		return -EINVAL;
 
-	if (copy_from_user(&kbuf, buffer, count)) {
-		return -1;
-	}
-
-	kbuf[count] = '\0';
-	length = strlen(kbuf);
-	if (kbuf[length - 1] == '\n')
-		kbuf[--length] = '\0';
-
-	if (strcmp(kbuf, "on") == 0)
-		bypass_param = 1;
-	else if (strcmp(kbuf, "off") == 0)
-		bypass_param = 0;
-
-	set_bypass_pwup_fn(pbp_device_block, bypass_param);
-
+	set_bypass_pwup_fn(PDE_DATA(file_inode(file)), bypass_param);
 	return count;
 }
-
-int
-set_bypass_pwoff_pfs(struct file *file, const char *buffer,
-		     unsigned long count, void *data)
+static int show_bypass_pwup(struct seq_file *m, void *v)
 {
-
-	char kbuf[256];
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int bypass_param = 0, length = 0;
-
-	if (count >= sizeof(kbuf))
-		return -EINVAL;
-
-	if (copy_from_user(&kbuf, buffer, count)) {
-		return -1;
-	}
-
-	kbuf[count] = '\0';
-	length = strlen(kbuf);
-	if (kbuf[length - 1] == '\n')
-		kbuf[--length] = '\0';
-
-	if (strcmp(kbuf, "on") == 0)
-		bypass_param = 1;
-	else if (strcmp(kbuf, "off") == 0)
-		bypass_param = 0;
-
-	set_bypass_pwoff_fn(pbp_device_block, bypass_param);
-
-	return count;
+	bpctl_dev_t *dev = m->private;
+	int ret = get_bypass_pwup_fn(dev);
+	if (ret == BP_NOT_CAP)
+		seq_printf(m, "fail\n");
+	else if (ret == 0)
+		seq_printf(m, "off\n");
+	else
+		seq_printf(m, "on\n");
+	return 0;
 }
+RW_FOPS(bypass_pwup)
 
-int
-set_tap_pwup_pfs(struct file *file, const char *buffer,
-		 unsigned long count, void *data)
+static ssize_t bypass_pwoff_write(struct file *file, const char __user *buffer,
+				  size_t count, loff_t *pos)
 {
-
-	char kbuf[256];
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int tap_param = 0, length = 0;
-
-	if (count >= sizeof(kbuf))
+	int bypass_param = user_on_off(buffer, count);
+	if (bypass_param < 0)
 		return -EINVAL;
 
-	if (copy_from_user(&kbuf, buffer, count)) {
-		return -1;
-	}
-
-	kbuf[count] = '\0';
-	length = strlen(kbuf);
-	if (kbuf[length - 1] == '\n')
-		kbuf[--length] = '\0';
-
-	if (strcmp(kbuf, "on") == 0)
-		tap_param = 1;
-	else if (strcmp(kbuf, "off") == 0)
-		tap_param = 0;
-
-	set_tap_pwup_fn(pbp_device_block, tap_param);
-
+	set_bypass_pwoff_fn(PDE_DATA(file_inode(file)), bypass_param);
 	return count;
 }
-
-int
-set_disc_pwup_pfs(struct file *file, const char *buffer,
-		  unsigned long count, void *data)
+static int show_bypass_pwoff(struct seq_file *m, void *v)
 {
-
-	char kbuf[256];
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int tap_param = 0, length = 0;
-
-	if (count >= sizeof(kbuf))
-		return -EINVAL;
-
-	if (copy_from_user(&kbuf, buffer, count)) {
-		return -1;
-	}
-
-	kbuf[count] = '\0';
-	length = strlen(kbuf);
-	if (kbuf[length - 1] == '\n')
-		kbuf[--length] = '\0';
-
-	if (strcmp(kbuf, "on") == 0)
-		tap_param = 1;
-	else if (strcmp(kbuf, "off") == 0)
-		tap_param = 0;
-
-	set_disc_pwup_fn(pbp_device_block, tap_param);
-
-	return count;
-}
-
-int
-get_bypass_pwup_pfs(char *page, char **start, off_t off, int count,
-		    int *eof, void *data)
-{
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
-
-	ret = get_bypass_pwup_fn(pbp_device_block);
+	bpctl_dev_t *dev = m->private;
+	int ret = get_bypass_pwoff_fn(dev);
 	if (ret == BP_NOT_CAP)
-		len = sprintf(page, "fail\n");
+		seq_printf(m, "fail\n");
 	else if (ret == 0)
-		len = sprintf(page, "off\n");
+		seq_printf(m, "off\n");
 	else
-		len = sprintf(page, "on\n");
-
-	*eof = 1;
-	return len;
+		seq_printf(m, "on\n");
+	return 0;
 }
+RW_FOPS(bypass_pwoff)
 
-int
-get_bypass_pwoff_pfs(char *page, char **start, off_t off, int count,
-		     int *eof, void *data)
+static ssize_t tap_pwup_write(struct file *file, const char __user *buffer,
+				  size_t count, loff_t *pos)
 {
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
-
-	ret = get_bypass_pwoff_fn(pbp_device_block);
-	if (ret == BP_NOT_CAP)
-		len = sprintf(page, "fail\n");
-	else if (ret == 0)
-		len = sprintf(page, "off\n");
-	else
-		len = sprintf(page, "on\n");
+	int tap_param = user_on_off(buffer, count);
+	if (tap_param < 0)
+		return -EINVAL;
 
-	*eof = 1;
-	return len;
+	set_tap_pwup_fn(PDE_DATA(file_inode(file)), tap_param);
+	return count;
 }
-
-int
-get_tap_pwup_pfs(char *page, char **start, off_t off, int count,
-		 int *eof, void *data)
+static int show_tap_pwup(struct seq_file *m, void *v)
 {
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
-
-	ret = get_tap_pwup_fn(pbp_device_block);
+	bpctl_dev_t *dev = m->private;
+	int ret = get_tap_pwup_fn(dev);
 	if (ret == BP_NOT_CAP)
-		len = sprintf(page, "fail\n");
+		seq_printf(m, "fail\n");
 	else if (ret == 0)
-		len = sprintf(page, "off\n");
+		seq_printf(m, "off\n");
 	else
-		len = sprintf(page, "on\n");
-
-	*eof = 1;
-	return len;
+		seq_printf(m, "on\n");
+	return 0;
 }
+RW_FOPS(tap_pwup)
 
-int
-get_disc_pwup_pfs(char *page, char **start, off_t off, int count,
-		  int *eof, void *data)
+static ssize_t disc_pwup_write(struct file *file, const char __user *buffer,
+				  size_t count, loff_t *pos)
 {
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
+	int tap_param = user_on_off(buffer, count);
+	if (tap_param < 0)
+		return -EINVAL;
 
-	ret = get_disc_pwup_fn(pbp_device_block);
+	set_disc_pwup_fn(PDE_DATA(file_inode(file)), tap_param);
+	return count;
+}
+static int show_disc_pwup(struct seq_file *m, void *v)
+{
+	bpctl_dev_t *dev = m->private;
+	int ret = get_disc_pwup_fn(dev);
 	if (ret == BP_NOT_CAP)
-		len = sprintf(page, "fail\n");
+		seq_printf(m, "fail\n");
 	else if (ret == 0)
-		len = sprintf(page, "off\n");
+		seq_printf(m, "off\n");
 	else
-		len = sprintf(page, "on\n");
-
-	*eof = 1;
-	return len;
+		seq_printf(m, "on\n");
+	return 0;
 }
+RW_FOPS(disc_pwup)
 
-int
-set_std_nic_pfs(struct file *file, const char *buffer,
-		unsigned long count, void *data)
+static ssize_t std_nic_write(struct file *file, const char __user *buffer,
+				  size_t count, loff_t *pos)
 {
-
-	char kbuf[256];
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int bypass_param = 0, length = 0;
-
-	if (count >= sizeof(kbuf))
+	int bypass_param = user_on_off(buffer, count);
+	if (bypass_param < 0)
 		return -EINVAL;
 
-	if (copy_from_user(&kbuf, buffer, count)) {
-		return -1;
-	}
-
-	kbuf[count] = '\0';
-	length = strlen(kbuf);
-	if (kbuf[length - 1] == '\n')
-		kbuf[--length] = '\0';
-
-	if (strcmp(kbuf, "on") == 0)
-		bypass_param = 1;
-	else if (strcmp(kbuf, "off") == 0)
-		bypass_param = 0;
-
-	set_std_nic_fn(pbp_device_block, bypass_param);
-
+	set_std_nic_fn(PDE_DATA(file_inode(file)), bypass_param);
 	return count;
 }
-
-int
-get_std_nic_pfs(char *page, char **start, off_t off, int count,
-		int *eof, void *data)
+static int show_std_nic(struct seq_file *m, void *v)
 {
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
-
-	ret = get_std_nic_fn(pbp_device_block);
+	bpctl_dev_t *dev = m->private;
+	int ret = get_std_nic_fn(dev);
 	if (ret == BP_NOT_CAP)
-		len = sprintf(page, "fail\n");
+		seq_printf(m, "fail\n");
 	else if (ret == 0)
-		len = sprintf(page, "off\n");
-	else
-		len = sprintf(page, "on\n");
-
-	*eof = 1;
-	return len;
-}
-
-int
-get_wd_exp_mode_pfs(char *page, char **start, off_t off, int count,
-		    int *eof, void *data)
-{
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
-
-	ret = get_wd_exp_mode_fn(pbp_device_block);
-	if (ret == 1)
-		len = sprintf(page, "tap\n");
-	else if (ret == 0)
-		len = sprintf(page, "bypass\n");
-	else if (ret == 2)
-		len = sprintf(page, "disc\n");
-
+		seq_printf(m, "off\n");
 	else
-		len = sprintf(page, "fail\n");
-
-	*eof = 1;
-	return len;
+		seq_printf(m, "on\n");
+	return 0;
 }
+RW_FOPS(std_nic)
 
-int
-set_wd_exp_mode_pfs(struct file *file, const char *buffer,
-		    unsigned long count, void *data)
+static ssize_t wd_exp_mode_write(struct file *file, const char __user *buffer,
+				  size_t count, loff_t *pos)
 {
-
 	char kbuf[256];
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
 	int bypass_param = 0, length = 0;
 
 	if (count > (sizeof(kbuf) - 1))
 		return -1;
 
-	if (copy_from_user(&kbuf, buffer, count)) {
+	if (copy_from_user(&kbuf, buffer, count))
 		return -1;
-	}
 
 	kbuf[count] = '\0';
 	length = strlen(kbuf);
@@ -8377,143 +7810,47 @@ set_wd_exp_mode_pfs(struct file *file, const char *buffer,
 	else if (strcmp(kbuf, "disc") == 0)
 		bypass_param = 2;
 
-	set_wd_exp_mode_fn(pbp_device_block, bypass_param);
+	set_wd_exp_mode_fn(PDE_DATA(file_inode(file)), bypass_param);
 
 	return count;
 }
-
-int
-get_wd_autoreset_pfs(char *page, char **start, off_t off, int count,
-		     int *eof, void *data)
+static int show_wd_exp_mode(struct seq_file *m, void *v)
 {
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int len = 0, ret = 0;
-
-	ret = get_wd_autoreset_fn(pbp_device_block);
-	if (ret >= 0)
-		len = sprintf(page, "%d\n", ret);
+	bpctl_dev_t *dev = m->private;
+	int ret = get_wd_exp_mode_fn(dev);
+	if (ret == 1)
+		seq_printf(m, "tap\n");
+	else if (ret == 0)
+		seq_printf(m, "bypass\n");
+	else if (ret == 2)
+		seq_printf(m, "disc\n");
 	else
-		len = sprintf(page, "fail\n");
-
-	*eof = 1;
-	return len;
+		seq_printf(m, "fail\n");
+	return 0;
 }
+RW_FOPS(wd_exp_mode)
 
-int
-set_wd_autoreset_pfs(struct file *file, const char *buffer,
-		     unsigned long count, void *data)
+static ssize_t wd_autoreset_write(struct file *file, const char __user *buffer,
+				  size_t count, loff_t *pos)
 {
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
 	int timeout;
-	int ret;
-
-	ret = kstrtoint_from_user(buffer, count, 10, &timeout);
+	int ret = kstrtoint_from_user(buffer, count, 10, &timeout);
 	if (ret)
 		return ret;
-	set_wd_autoreset_fn(pbp_device_block, timeout);
-
+	set_wd_autoreset_fn(PDE_DATA(file_inode(file)), timeout);
 	return count;
 }
-
-int
-set_tpl_pfs(struct file *file, const char *buffer,
-	    unsigned long count, void *data)
+static int show_wd_autoreset(struct seq_file *m, void *v)
 {
-
-	char kbuf[256];
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int tpl_param = 0, length = 0;
-
-	if (count > (sizeof(kbuf) - 1))
-		return -1;
-
-	if (copy_from_user(&kbuf, buffer, count)) {
-		return -1;
-	}
-
-	kbuf[count] = '\0';
-	length = strlen(kbuf);
-	if (kbuf[length - 1] == '\n')
-		kbuf[--length] = '\0';
-
-	if (strcmp(kbuf, "on") == 0)
-		tpl_param = 1;
-	else if (strcmp(kbuf, "off") == 0)
-		tpl_param = 0;
-
-	set_tpl_fn(pbp_device_block, tpl_param);
-
-	return count;
-}
-
-#ifdef PMC_FIX_FLAG
-int
-set_wait_at_pwup_pfs(struct file *file, const char *buffer,
-		     unsigned long count, void *data)
-{
-
-	char kbuf[256];
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int tpl_param = 0, length = 0;
-
-	if (count > (sizeof(kbuf) - 1))
-		return -1;
-
-	if (copy_from_user(&kbuf, buffer, count)) {
-		return -1;
-	}
-
-	kbuf[count] = '\0';
-	length = strlen(kbuf);
-	if (kbuf[length - 1] == '\n')
-		kbuf[--length] = '\0';
-
-	if (strcmp(kbuf, "on") == 0)
-		tpl_param = 1;
-	else if (strcmp(kbuf, "off") == 0)
-		tpl_param = 0;
-
-	set_bp_wait_at_pwup_fn(pbp_device_block, tpl_param);
-
-	return count;
-}
-
-int
-set_hw_reset_pfs(struct file *file, const char *buffer,
-		 unsigned long count, void *data)
-{
-
-	char kbuf[256];
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int tpl_param = 0, length = 0;
-
-	if (count > (sizeof(kbuf) - 1))
-		return -1;
-
-	if (copy_from_user(&kbuf, buffer, count)) {
-		return -1;
-	}
-
-	kbuf[count] = '\0';
-	length = strlen(kbuf);
-	if (kbuf[length - 1] == '\n')
-		kbuf[--length] = '\0';
-
-	if (strcmp(kbuf, "on") == 0)
-		tpl_param = 1;
-	else if (strcmp(kbuf, "off") == 0)
-		tpl_param = 0;
-
-	set_bp_hw_reset_fn(pbp_device_block, tpl_param);
-
-	return count;
+	bpctl_dev_t *dev = m->private;
+	int ret = get_wd_autoreset_fn(dev);
+	if (ret >= 0)
+		seq_printf(m, "%d\n", ret);
+	else
+		seq_printf(m, "fail\n");
+	return 0;
 }
-
-#endif				/*PMC_FIX_FLAG */
+RW_FOPS(wd_autoreset)
 
 int bypass_proc_create_dev_sd(bpctl_dev_t *pbp_device_block)
 {
@@ -8530,168 +7867,54 @@ int bypass_proc_create_dev_sd(bpctl_dev_t *pbp_device_block)
 		return -1;
 
 	/* create device proc dir */
-	procfs_dir = proc_getdir(current_pfs->dir_name, bp_procfs_dir);
-	if (procfs_dir == 0) {
+	procfs_dir = proc_mkdir(current_pfs->dir_name, bp_procfs_dir);
+	if (!procfs_dir) {
 		printk(KERN_DEBUG "Could not create procfs directory %s\n",
 		       current_pfs->dir_name);
 		return -1;
 	}
 	current_pfs->bypass_entry = procfs_dir;
 
-	if (bypass_proc_create_entry_sd(&(current_pfs->bypass_info), BYPASS_INFO_ENTRY_SD, NULL,	/* write */
-					get_bypass_info_pfs,	/* read  */
-					procfs_dir, pbp_device_block))
-		ret = -1;
-
+#define ENTRY(x) ret |= procfs_add(#x, &x##_ops, pbp_device_block)
+	ENTRY(bypass_info);
 	if (pbp_device_block->bp_caps & SW_CTL_CAP) {
-
 		/* Create set param proc's */
-		if (bypass_proc_create_entry_sd(&(current_pfs->bypass_slave), BYPASS_SLAVE_ENTRY_SD, NULL,	/* write */
-						get_bypass_slave_pfs,	/* read  */
-						procfs_dir, pbp_device_block))
-			ret = -1;
-
-		if (bypass_proc_create_entry_sd(&(current_pfs->bypass_caps), BYPASS_CAPS_ENTRY_SD, NULL,	/* write */
-						get_bypass_caps_pfs,	/* read  */
-						procfs_dir, pbp_device_block))
-			ret = -1;
-
-		if (bypass_proc_create_entry_sd(&(current_pfs->wd_set_caps), WD_SET_CAPS_ENTRY_SD, NULL,	/* write */
-						get_wd_set_caps_pfs,	/* read  */
-						procfs_dir, pbp_device_block))
-			ret = -1;
-		if (bypass_proc_create_entry_sd(&(current_pfs->bypass_wd), BYPASS_WD_ENTRY_SD, set_bypass_wd_pfs,	/* write */
-						get_bypass_wd_pfs,	/* read  */
-						procfs_dir, pbp_device_block))
-			ret = -1;
-
-		if (bypass_proc_create_entry_sd(&(current_pfs->wd_expire_time), WD_EXPIRE_TIME_ENTRY_SD, NULL,	/* write */
-						get_wd_expire_time_pfs,	/* read  */
-						procfs_dir, pbp_device_block))
-			ret = -1;
-
-		if (bypass_proc_create_entry_sd(&(current_pfs->reset_bypass_wd), RESET_BYPASS_WD_ENTRY_SD, NULL,	/* write */
-						reset_bypass_wd_pfs,	/* read  */
-						procfs_dir, pbp_device_block))
-			ret = -1;
-
-		if (bypass_proc_create_entry_sd(&(current_pfs->std_nic), STD_NIC_ENTRY_SD, set_std_nic_pfs,	/* write */
-						get_std_nic_pfs,	/* read  */
-						procfs_dir, pbp_device_block))
-			ret = -1;
-
+		ENTRY(bypass_slave);
+		ENTRY(bypass_caps);
+		ENTRY(wd_set_caps);
+		ENTRY(bypass_wd);
+		ENTRY(wd_expire_time);
+		ENTRY(reset_bypass_wd);
+		ENTRY(std_nic);
 		if (pbp_device_block->bp_caps & BP_CAP) {
-			if (bypass_proc_create_entry_sd(&(current_pfs->bypass), BYPASS_ENTRY_SD, set_bypass_pfs,	/* write */
-							get_bypass_pfs,	/* read  */
-							procfs_dir,
-							pbp_device_block))
-				ret = -1;
-
-			if (bypass_proc_create_entry_sd(&(current_pfs->dis_bypass), DIS_BYPASS_ENTRY_SD, set_dis_bypass_pfs,	/* write */
-							get_dis_bypass_pfs,	/* read  */
-							procfs_dir,
-							pbp_device_block))
-				ret = -1;
-
-			if (bypass_proc_create_entry_sd(&(current_pfs->bypass_pwup), BYPASS_PWUP_ENTRY_SD, set_bypass_pwup_pfs,	/* write */
-							get_bypass_pwup_pfs,	/* read  */
-							procfs_dir,
-							pbp_device_block))
-				ret = -1;
-			if (bypass_proc_create_entry_sd(&(current_pfs->bypass_pwoff), BYPASS_PWOFF_ENTRY_SD, set_bypass_pwoff_pfs,	/* write */
-							get_bypass_pwoff_pfs,	/* read  */
-							procfs_dir,
-							pbp_device_block))
-				ret = -1;
-
-			if (bypass_proc_create_entry_sd(&(current_pfs->bypass_change), BYPASS_CHANGE_ENTRY_SD, NULL,	/* write */
-							get_bypass_change_pfs,	/* read  */
-							procfs_dir,
-							pbp_device_block))
-				ret = -1;
+			ENTRY(bypass);
+			ENTRY(dis_bypass);
+			ENTRY(bypass_pwup);
+			ENTRY(bypass_pwoff);
+			ENTRY(bypass_change);
 		}
-
 		if (pbp_device_block->bp_caps & TAP_CAP) {
-
-			if (bypass_proc_create_entry_sd(&(current_pfs->tap), TAP_ENTRY_SD, set_tap_pfs,	/* write */
-							get_tap_pfs,	/* read  */
-							procfs_dir,
-							pbp_device_block))
-				ret = -1;
-
-			if (bypass_proc_create_entry_sd(&(current_pfs->dis_tap), DIS_TAP_ENTRY_SD, set_dis_tap_pfs,	/* write */
-							get_dis_tap_pfs,	/* read  */
-							procfs_dir,
-							pbp_device_block))
-				ret = -1;
-
-			if (bypass_proc_create_entry_sd(&(current_pfs->tap_pwup), TAP_PWUP_ENTRY_SD, set_tap_pwup_pfs,	/* write */
-							get_tap_pwup_pfs,	/* read  */
-							procfs_dir,
-							pbp_device_block))
-				ret = -1;
-
-			if (bypass_proc_create_entry_sd(&(current_pfs->tap_change), TAP_CHANGE_ENTRY_SD, NULL,	/* write */
-							get_tap_change_pfs,	/* read  */
-							procfs_dir,
-							pbp_device_block))
-				ret = -1;
+			ENTRY(tap);
+			ENTRY(dis_tap);
+			ENTRY(tap_pwup);
+			ENTRY(tap_change);
 		}
 		if (pbp_device_block->bp_caps & DISC_CAP) {
-
-			if (bypass_proc_create_entry_sd(&(current_pfs->tap), DISC_ENTRY_SD, set_disc_pfs,	/* write */
-							get_disc_pfs,	/* read  */
-							procfs_dir,
-							pbp_device_block))
-				ret = -1;
-#if 1
-
-			if (bypass_proc_create_entry_sd(&(current_pfs->dis_tap), DIS_DISC_ENTRY_SD, set_dis_disc_pfs,	/* write */
-							get_dis_disc_pfs,	/* read  */
-							procfs_dir,
-							pbp_device_block))
-				ret = -1;
-#endif
-
-			if (bypass_proc_create_entry_sd(&(current_pfs->tap_pwup), DISC_PWUP_ENTRY_SD, set_disc_pwup_pfs,	/* write */
-							get_disc_pwup_pfs,	/* read  */
-							procfs_dir,
-							pbp_device_block))
-				ret = -1;
-
-			if (bypass_proc_create_entry_sd(&(current_pfs->tap_change), DISC_CHANGE_ENTRY_SD, NULL,	/* write */
-							get_disc_change_pfs,	/* read  */
-							procfs_dir,
-							pbp_device_block))
-				ret = -1;
+			ENTRY(disc);
+			ENTRY(dis_disc);
+			ENTRY(disc_pwup);
+			ENTRY(disc_change);
 		}
 
-		if (bypass_proc_create_entry_sd(&(current_pfs->wd_exp_mode), WD_EXP_MODE_ENTRY_SD, set_wd_exp_mode_pfs,	/* write */
-						get_wd_exp_mode_pfs,	/* read  */
-						procfs_dir, pbp_device_block))
-			ret = -1;
-
-		if (bypass_proc_create_entry_sd(&(current_pfs->wd_autoreset), WD_AUTORESET_ENTRY_SD, set_wd_autoreset_pfs,	/* write */
-						get_wd_autoreset_pfs,	/* read  */
-						procfs_dir, pbp_device_block))
-			ret = -1;
-		if (bypass_proc_create_entry_sd(&(current_pfs->tpl), TPL_ENTRY_SD, set_tpl_pfs,	/* write */
-						get_tpl_pfs,	/* read  */
-						procfs_dir, pbp_device_block))
-			ret = -1;
+		ENTRY(wd_exp_mode);
+		ENTRY(wd_autoreset);
+		ENTRY(tpl);
 #ifdef PMC_FIX_FLAG
-		if (bypass_proc_create_entry_sd(&(current_pfs->tpl), WAIT_AT_PWUP_ENTRY_SD, set_wait_at_pwup_pfs,	/* write */
-						get_wait_at_pwup_pfs,	/* read  */
-						procfs_dir, pbp_device_block))
-			ret = -1;
-		if (bypass_proc_create_entry_sd(&(current_pfs->tpl), HW_RESET_ENTRY_SD, set_hw_reset_pfs,	/* write */
-						get_hw_reset_pfs,	/* read  */
-						procfs_dir, pbp_device_block))
-			ret = -1;
-
+		ENTRY(wait_at_pwup);
+		ENTRY(hw_reset);
 #endif
-
 	}
+#undef ENTRY
 	if (ret < 0)
 		printk(KERN_DEBUG "Create proc entry failed\n");
 
@@ -8702,21 +7925,7 @@ int bypass_proc_remove_dev_sd(bpctl_dev_t *pbp_device_block)
 {
 
 	struct bypass_pfs_sd *current_pfs = &pbp_device_block->bypass_pfs_set;
-	struct proc_dir_entry *pde = current_pfs->bypass_entry, *pde_curr =
-	    NULL;
-	char name[256];
-
-	if (!pde)
-		return 0;
-	for (pde = pde->subdir; pde;) {
-		strcpy(name, pde->name);
-		pde_curr = pde;
-		pde = pde->next;
-		remove_proc_entry(name, current_pfs->bypass_entry);
-	}
-	if (!pde)
-		remove_proc_entry(current_pfs->dir_name, bp_procfs_dir);
+	remove_proc_subtree(current_pfs->dir_name, bp_procfs_dir);
 	current_pfs->bypass_entry = NULL;
-
 	return 0;
 }
diff --git a/drivers/staging/silicom/bp_proc.c b/drivers/staging/silicom/bp_proc.c
index a01ca97..71cb892 100644
--- a/drivers/staging/silicom/bp_proc.c
+++ b/drivers/staging/silicom/bp_proc.c
@@ -84,7 +84,7 @@ static struct proc_dir_entry *proc_getdir(char *name,
 	}
 	if (pde == (struct proc_dir_entry *)0) {
 		/* create the directory */
-		pde = create_proc_entry(name, S_IFDIR, proc_dir);
+		pde = proc_mkdir(name, proc_dir);
 		if (pde == (struct proc_dir_entry *)0)
 			return pde;
 	}
@@ -188,15 +188,11 @@ get_wd_set_caps_pfs(char *page, char **start, off_t off, int count,
 	return len;
 }
 
-int
-set_bypass_pfs(struct file *file, const char *buffer,
-	       unsigned long count, void *data)
+static int user_on_off(const void __user *buffer, size_t count)
 {
 
 	char kbuf[256];
-	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
-
-	int bypass_param = 0, length = 0;
+	int length = 0;
 
 	if (count > (sizeof(kbuf) - 1))
 		return -1;
@@ -210,12 +206,24 @@ set_bypass_pfs(struct file *file, const char *buffer,
 		kbuf[--length] = '\0';
 
 	if (strcmp(kbuf, "on") == 0)
-		bypass_param = 1;
-	else if (strcmp(kbuf, "off") == 0)
-		bypass_param = 0;
+		return 1;
+	if (strcmp(kbuf, "off") == 0)
+		return 0;
+	return 0;
+}
 
-	set_bypass_fn(pbp_device_block, bypass_param);
+int
+set_bypass_pfs(struct file *file, const char *buffer,
+	       unsigned long count, void *data)
+{
+
+	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
+	int bypass_param = user_on_off(buffer, count);
+
+	if (bypass_param < 0)
+		return -1;
 
+	set_bypass_fn(pbp_device_block, bypass_param);
 	return count;
 }
 
@@ -224,29 +232,13 @@ set_tap_pfs(struct file *file, const char *buffer,
 	    unsigned long count, void *data)
 {
 
-	char kbuf[256];
 	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
+	int tap_param = user_on_off(buffer, count);
 
-	int tap_param = 0, length = 0;
-
-	if (count > (sizeof(kbuf) - 1))
-		return -1;
-
-	if (copy_from_user(&kbuf, buffer, count))
+	if (tap_param < 0)
 		return -1;
 
-	kbuf[count] = '\0';
-	length = strlen(kbuf);
-	if (kbuf[length - 1] == '\n')
-		kbuf[--length] = '\0';
-
-	if (strcmp(kbuf, "on") == 0)
-		tap_param = 1;
-	else if (strcmp(kbuf, "off") == 0)
-		tap_param = 0;
-
 	set_tap_fn(pbp_device_block, tap_param);
-
 	return count;
 }
 
@@ -255,29 +247,13 @@ set_disc_pfs(struct file *file, const char *buffer,
 	     unsigned long count, void *data)
 {
 
-	char kbuf[256];
 	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
+	int tap_param = user_on_off(buffer, count);
 
-	int tap_param = 0, length = 0;
-
-	if (count > (sizeof(kbuf) - 1))
-		return -1;
-
-	if (copy_from_user(&kbuf, buffer, count))
+	if (tap_param < 0)
 		return -1;
 
-	kbuf[count] = '\0';
-	length = strlen(kbuf);
-	if (kbuf[length - 1] == '\n')
-		kbuf[--length] = '\0';
-
-	if (strcmp(kbuf, "on") == 0)
-		tap_param = 1;
-	else if (strcmp(kbuf, "off") == 0)
-		tap_param = 0;
-
 	set_disc_fn(pbp_device_block, tap_param);
-
 	return count;
 }
 
@@ -555,26 +531,13 @@ set_dis_bypass_pfs(struct file *file, const char *buffer,
 		   unsigned long count, void *data)
 {
 
-	char kbuf[256];
 	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
+	int bypass_param = user_on_off(buffer, count);
 
-	int bypass_param = 0, length = 0;
-
-	if (copy_from_user(&kbuf, buffer, count))
+	if (bypass_param < 0)
 		return -1;
 
-	kbuf[count] = '\0';
-	length = strlen(kbuf);
-	if (kbuf[length - 1] == '\n')
-		kbuf[--length] = '\0';
-
-	if (strcmp(kbuf, "on") == 0)
-		bypass_param = 1;
-	else if (strcmp(kbuf, "off") == 0)
-		bypass_param = 0;
-
 	set_dis_bypass_fn(pbp_device_block, bypass_param);
-
 	return count;
 }
 
@@ -583,26 +546,13 @@ set_dis_tap_pfs(struct file *file, const char *buffer,
 		unsigned long count, void *data)
 {
 
-	char kbuf[256];
 	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
+	int tap_param = user_on_off(buffer, count);
 
-	int tap_param = 0, length = 0;
-
-	if (copy_from_user(&kbuf, buffer, count))
+	if (tap_param < 0)
 		return -1;
 
-	kbuf[count] = '\0';
-	length = strlen(kbuf);
-	if (kbuf[length - 1] == '\n')
-		kbuf[--length] = '\0';
-
-	if (strcmp(kbuf, "on") == 0)
-		tap_param = 1;
-	else if (strcmp(kbuf, "off") == 0)
-		tap_param = 0;
-
 	set_dis_tap_fn(pbp_device_block, tap_param);
-
 	return count;
 }
 
@@ -611,26 +561,13 @@ set_dis_disc_pfs(struct file *file, const char *buffer,
 		 unsigned long count, void *data)
 {
 
-	char kbuf[256];
 	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
+	int tap_param = user_on_off(buffer, count);
 
-	int tap_param = 0, length = 0;
-
-	if (copy_from_user(&kbuf, buffer, count))
+	if (tap_param < 0)
 		return -1;
 
-	kbuf[count] = '\0';
-	length = strlen(kbuf);
-	if (kbuf[length - 1] == '\n')
-		kbuf[--length] = '\0';
-
-	if (strcmp(kbuf, "on") == 0)
-		tap_param = 1;
-	else if (strcmp(kbuf, "off") == 0)
-		tap_param = 0;
-
 	set_dis_disc_fn(pbp_device_block, tap_param);
-
 	return count;
 }
 
@@ -699,26 +636,13 @@ set_bypass_pwup_pfs(struct file *file, const char *buffer,
 		    unsigned long count, void *data)
 {
 
-	char kbuf[256];
 	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
+	int bypass_param = user_on_off(buffer, count);
 
-	int bypass_param = 0, length = 0;
-
-	if (copy_from_user(&kbuf, buffer, count))
+	if (bypass_param < 0)
 		return -1;
 
-	kbuf[count] = '\0';
-	length = strlen(kbuf);
-	if (kbuf[length - 1] == '\n')
-		kbuf[--length] = '\0';
-
-	if (strcmp(kbuf, "on") == 0)
-		bypass_param = 1;
-	else if (strcmp(kbuf, "off") == 0)
-		bypass_param = 0;
-
 	set_bypass_pwup_fn(pbp_device_block, bypass_param);
-
 	return count;
 }
 
@@ -727,26 +651,13 @@ set_bypass_pwoff_pfs(struct file *file, const char *buffer,
 		     unsigned long count, void *data)
 {
 
-	char kbuf[256];
 	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
+	int bypass_param = user_on_off(buffer, count);
 
-	int bypass_param = 0, length = 0;
-
-	if (copy_from_user(&kbuf, buffer, count))
+	if (bypass_param < 0)
 		return -1;
 
-	kbuf[count] = '\0';
-	length = strlen(kbuf);
-	if (kbuf[length - 1] == '\n')
-		kbuf[--length] = '\0';
-
-	if (strcmp(kbuf, "on") == 0)
-		bypass_param = 1;
-	else if (strcmp(kbuf, "off") == 0)
-		bypass_param = 0;
-
 	set_bypass_pwoff_fn(pbp_device_block, bypass_param);
-
 	return count;
 }
 
@@ -755,26 +666,13 @@ set_tap_pwup_pfs(struct file *file, const char *buffer,
 		 unsigned long count, void *data)
 {
 
-	char kbuf[256];
 	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
+	int tap_param = user_on_off(buffer, count);
 
-	int tap_param = 0, length = 0;
-
-	if (copy_from_user(&kbuf, buffer, count))
+	if (tap_param < 0)
 		return -1;
 
-	kbuf[count] = '\0';
-	length = strlen(kbuf);
-	if (kbuf[length - 1] == '\n')
-		kbuf[--length] = '\0';
-
-	if (strcmp(kbuf, "on") == 0)
-		tap_param = 1;
-	else if (strcmp(kbuf, "off") == 0)
-		tap_param = 0;
-
 	set_tap_pwup_fn(pbp_device_block, tap_param);
-
 	return count;
 }
 
@@ -783,26 +681,13 @@ set_disc_pwup_pfs(struct file *file, const char *buffer,
 		  unsigned long count, void *data)
 {
 
-	char kbuf[256];
 	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
+	int tap_param = user_on_off(buffer, count);
 
-	int tap_param = 0, length = 0;
-
-	if (copy_from_user(&kbuf, buffer, count))
+	if (tap_param < 0)
 		return -1;
 
-	kbuf[count] = '\0';
-	length = strlen(kbuf);
-	if (kbuf[length - 1] == '\n')
-		kbuf[--length] = '\0';
-
-	if (strcmp(kbuf, "on") == 0)
-		tap_param = 1;
-	else if (strcmp(kbuf, "off") == 0)
-		tap_param = 0;
-
 	set_disc_pwup_fn(pbp_device_block, tap_param);
-
 	return count;
 }
 
@@ -891,26 +776,13 @@ set_std_nic_pfs(struct file *file, const char *buffer,
 		unsigned long count, void *data)
 {
 
-	char kbuf[256];
 	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
+	int bypass_param = user_on_off(buffer, count);
 
-	int bypass_param = 0, length = 0;
-
-	if (copy_from_user(&kbuf, buffer, count))
+	if (bypass_param < 0)
 		return -1;
 
-	kbuf[count] = '\0';
-	length = strlen(kbuf);
-	if (kbuf[length - 1] == '\n')
-		kbuf[--length] = '\0';
-
-	if (strcmp(kbuf, "on") == 0)
-		bypass_param = 1;
-	else if (strcmp(kbuf, "off") == 0)
-		bypass_param = 0;
-
 	set_std_nic_fn(pbp_device_block, bypass_param);
-
 	return count;
 }
 
@@ -1033,29 +905,13 @@ set_tpl_pfs(struct file *file, const char *buffer,
 	    unsigned long count, void *data)
 {
 
-	char kbuf[256];
 	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
+	int tpl_param = user_on_off(buffer, count);
 
-	int tpl_param = 0, length = 0;
-
-	if (count > (sizeof(kbuf) - 1))
-		return -1;
-
-	if (copy_from_user(&kbuf, buffer, count))
+	if (tpl_param < 0)
 		return -1;
 
-	kbuf[count] = '\0';
-	length = strlen(kbuf);
-	if (kbuf[length - 1] == '\n')
-		kbuf[--length] = '\0';
-
-	if (strcmp(kbuf, "on") == 0)
-		tpl_param = 1;
-	else if (strcmp(kbuf, "off") == 0)
-		tpl_param = 0;
-
 	set_tpl_fn(pbp_device_block, tpl_param);
-
 	return count;
 }
 
@@ -1065,29 +921,13 @@ set_wait_at_pwup_pfs(struct file *file, const char *buffer,
 		     unsigned long count, void *data)
 {
 
-	char kbuf[256];
 	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
+	int tpl_param = user_on_off(buffer, count);
 
-	int tpl_param = 0, length = 0;
-
-	if (count > (sizeof(kbuf) - 1))
+	if (tpl_param < 0)
 		return -1;
 
-	if (copy_from_user(&kbuf, buffer, count))
-		return -1;
-
-	kbuf[count] = '\0';
-	length = strlen(kbuf);
-	if (kbuf[length - 1] == '\n')
-		kbuf[--length] = '\0';
-
-	if (strcmp(kbuf, "on") == 0)
-		tpl_param = 1;
-	else if (strcmp(kbuf, "off") == 0)
-		tpl_param = 0;
-
 	set_bp_wait_at_pwup_fn(pbp_device_block, tpl_param);
-
 	return count;
 }
 
@@ -1096,29 +936,13 @@ set_hw_reset_pfs(struct file *file, const char *buffer,
 		 unsigned long count, void *data)
 {
 
-	char kbuf[256];
 	bpctl_dev_t *pbp_device_block = (bpctl_dev_t *) data;
+	int tpl_param = user_on_off(buffer, count);
 
-	int tpl_param = 0, length = 0;
-
-	if (count > (sizeof(kbuf) - 1))
+	if (tpl_param < 0)
 		return -1;
 
-	if (copy_from_user(&kbuf, buffer, count))
-		return -1;
-
-	kbuf[count] = '\0';
-	length = strlen(kbuf);
-	if (kbuf[length - 1] == '\n')
-		kbuf[--length] = '\0';
-
-	if (strcmp(kbuf, "on") == 0)
-		tpl_param = 1;
-	else if (strcmp(kbuf, "off") == 0)
-		tpl_param = 0;
-
 	set_bp_hw_reset_fn(pbp_device_block, tpl_param);
-
 	return count;
 }
 
diff --git a/drivers/staging/silicom/bypasslib/bypass.c b/drivers/staging/silicom/bypasslib/bypass.c
index 95a1f18..9ed2508 100644
--- a/drivers/staging/silicom/bypasslib/bypass.c
+++ b/drivers/staging/silicom/bypasslib/bypass.c
@@ -134,7 +134,7 @@ static int is_dev_sd(int if_index)
 	return (ret >= 0 ? 1 : 0);
 }
 
-int is_bypass_dev(int if_index)
+static int is_bypass_dev(int if_index)
 {
 	struct pci_dev *pdev = NULL;
 	struct net_device *dev = NULL;
@@ -179,7 +179,7 @@ int is_bypass_dev(int if_index)
 	return (ret < 0 ? -1 : ret);
 }
 
-int is_bypass(int if_index)
+static int is_bypass(int if_index)
 {
 	int ret = 0;
 	SET_BPLIB_INT_FN(is_bypass, int, if_index, ret);
@@ -189,70 +189,70 @@ int is_bypass(int if_index)
 	return ret;
 }
 
-int get_bypass_slave(int if_index)
+static int get_bypass_slave(int if_index)
 {
 	DO_BPLIB_GET_ARG_FN(get_bypass_slave, GET_BYPASS_SLAVE, if_index);
 }
 
-int get_bypass_caps(int if_index)
+static int get_bypass_caps(int if_index)
 {
 	DO_BPLIB_GET_ARG_FN(get_bypass_caps, GET_BYPASS_CAPS, if_index);
 }
 
-int get_wd_set_caps(int if_index)
+static int get_wd_set_caps(int if_index)
 {
 	DO_BPLIB_GET_ARG_FN(get_wd_set_caps, GET_WD_SET_CAPS, if_index);
 }
 
-int set_bypass(int if_index, int bypass_mode)
+static int set_bypass(int if_index, int bypass_mode)
 {
 	DO_BPLIB_SET_ARG_FN(set_bypass, SET_BYPASS, if_index, bypass_mode);
 }
 
-int get_bypass(int if_index)
+static int get_bypass(int if_index)
 {
 	DO_BPLIB_GET_ARG_FN(get_bypass, GET_BYPASS, if_index);
 }
 
-int get_bypass_change(int if_index)
+static int get_bypass_change(int if_index)
 {
 	DO_BPLIB_GET_ARG_FN(get_bypass_change, GET_BYPASS_CHANGE, if_index);
 }
 
-int set_dis_bypass(int if_index, int dis_bypass)
+static int set_dis_bypass(int if_index, int dis_bypass)
 {
 	DO_BPLIB_SET_ARG_FN(set_dis_bypass, SET_DIS_BYPASS, if_index,
 			    dis_bypass);
 }
 
-int get_dis_bypass(int if_index)
+static int get_dis_bypass(int if_index)
 {
 	DO_BPLIB_GET_ARG_FN(get_dis_bypass, GET_DIS_BYPASS, if_index);
 }
 
-int set_bypass_pwoff(int if_index, int bypass_mode)
+static int set_bypass_pwoff(int if_index, int bypass_mode)
 {
 	DO_BPLIB_SET_ARG_FN(set_bypass_pwoff, SET_BYPASS_PWOFF, if_index,
 			    bypass_mode);
 }
 
-int get_bypass_pwoff(int if_index)
+static int get_bypass_pwoff(int if_index)
 {
 	DO_BPLIB_GET_ARG_FN(get_bypass_pwoff, GET_BYPASS_PWOFF, if_index);
 }
 
-int set_bypass_pwup(int if_index, int bypass_mode)
+static int set_bypass_pwup(int if_index, int bypass_mode)
 {
 	DO_BPLIB_SET_ARG_FN(set_bypass_pwup, SET_BYPASS_PWUP, if_index,
 			    bypass_mode);
 }
 
-int get_bypass_pwup(int if_index)
+static int get_bypass_pwup(int if_index)
 {
 	DO_BPLIB_GET_ARG_FN(get_bypass_pwup, GET_BYPASS_PWUP, if_index);
 }
 
-int set_bypass_wd(int if_index, int ms_timeout, int *ms_timeout_set)
+static int set_bypass_wd(int if_index, int ms_timeout, int *ms_timeout_set)
 {
 	int data = ms_timeout, ret = 0;
 	if (is_dev_sd(if_index))
@@ -268,7 +268,7 @@ int set_bypass_wd(int if_index, int ms_timeout, int *ms_timeout_set)
 	return ret;
 }
 
-int get_bypass_wd(int if_index, int *ms_timeout_set)
+static int get_bypass_wd(int if_index, int *ms_timeout_set)
 {
 	int *data = ms_timeout_set, ret = 0;
 	if (is_dev_sd(if_index))
@@ -279,7 +279,7 @@ int get_bypass_wd(int if_index, int *ms_timeout_set)
 	return ret;
 }
 
-int get_wd_expire_time(int if_index, int *ms_time_left)
+static int get_wd_expire_time(int if_index, int *ms_time_left)
 {
 	int *data = ms_time_left, ret = 0;
 	if (is_dev_sd(if_index))
@@ -293,144 +293,144 @@ int get_wd_expire_time(int if_index, int *ms_time_left)
 	return ret;
 }
 
-int reset_bypass_wd_timer(int if_index)
+static int reset_bypass_wd_timer(int if_index)
 {
 	DO_BPLIB_GET_ARG_FN(reset_bypass_wd_timer, RESET_BYPASS_WD_TIMER,
 			    if_index);
 }
 
-int set_std_nic(int if_index, int bypass_mode)
+static int set_std_nic(int if_index, int bypass_mode)
 {
 	DO_BPLIB_SET_ARG_FN(set_std_nic, SET_STD_NIC, if_index, bypass_mode);
 }
 
-int get_std_nic(int if_index)
+static int get_std_nic(int if_index)
 {
 	DO_BPLIB_GET_ARG_FN(get_std_nic, GET_STD_NIC, if_index);
 }
 
-int set_tx(int if_index, int tx_state)
+static int set_tx(int if_index, int tx_state)
 {
 	DO_BPLIB_SET_ARG_FN(set_tx, SET_TX, if_index, tx_state);
 }
 
-int get_tx(int if_index)
+static int get_tx(int if_index)
 {
 	DO_BPLIB_GET_ARG_FN(get_tx, GET_TX, if_index);
 }
 
-int set_tap(int if_index, int tap_mode)
+static int set_tap(int if_index, int tap_mode)
 {
 	DO_BPLIB_SET_ARG_FN(set_tap, SET_TAP, if_index, tap_mode);
 }
 
-int get_tap(int if_index)
+static int get_tap(int if_index)
 {
 	DO_BPLIB_GET_ARG_FN(get_tap, GET_TAP, if_index);
 }
 
-int get_tap_change(int if_index)
+static int get_tap_change(int if_index)
 {
 	DO_BPLIB_GET_ARG_FN(get_tap_change, GET_TAP_CHANGE, if_index);
 }
 
-int set_dis_tap(int if_index, int dis_tap)
+static int set_dis_tap(int if_index, int dis_tap)
 {
 	DO_BPLIB_SET_ARG_FN(set_dis_tap, SET_DIS_TAP, if_index, dis_tap);
 }
 
-int get_dis_tap(int if_index)
+static int get_dis_tap(int if_index)
 {
 	DO_BPLIB_GET_ARG_FN(get_dis_tap, GET_DIS_TAP, if_index);
 }
 
-int set_tap_pwup(int if_index, int tap_mode)
+static int set_tap_pwup(int if_index, int tap_mode)
 {
 	DO_BPLIB_SET_ARG_FN(set_tap_pwup, SET_TAP_PWUP, if_index, tap_mode);
 }
 
-int get_tap_pwup(int if_index)
+static int get_tap_pwup(int if_index)
 {
 	DO_BPLIB_GET_ARG_FN(get_tap_pwup, GET_TAP_PWUP, if_index);
 }
 
-int set_bp_disc(int if_index, int disc_mode)
+static int set_bp_disc(int if_index, int disc_mode)
 {
 	DO_BPLIB_SET_ARG_FN(set_bp_disc, SET_DISC, if_index, disc_mode);
 }
 
-int get_bp_disc(int if_index)
+static int get_bp_disc(int if_index)
 {
 	DO_BPLIB_GET_ARG_FN(get_bp_disc, GET_DISC, if_index);
 }
 
-int get_bp_disc_change(int if_index)
+static int get_bp_disc_change(int if_index)
 {
 	DO_BPLIB_GET_ARG_FN(get_bp_disc_change, GET_DISC_CHANGE, if_index);
 }
 
-int set_bp_dis_disc(int if_index, int dis_disc)
+static int set_bp_dis_disc(int if_index, int dis_disc)
 {
 	DO_BPLIB_SET_ARG_FN(set_bp_dis_disc, SET_DIS_DISC, if_index, dis_disc);
 }
 
-int get_bp_dis_disc(int if_index)
+static int get_bp_dis_disc(int if_index)
 {
 	DO_BPLIB_GET_ARG_FN(get_bp_dis_disc, GET_DIS_DISC, if_index);
 }
 
-int set_bp_disc_pwup(int if_index, int disc_mode)
+static int set_bp_disc_pwup(int if_index, int disc_mode)
 {
 	DO_BPLIB_SET_ARG_FN(set_bp_disc_pwup, SET_DISC_PWUP, if_index,
 			    disc_mode);
 }
 
-int get_bp_disc_pwup(int if_index)
+static int get_bp_disc_pwup(int if_index)
 {
 	DO_BPLIB_GET_ARG_FN(get_bp_disc_pwup, GET_DISC_PWUP, if_index);
 }
 
-int set_wd_exp_mode(int if_index, int mode)
+static int set_wd_exp_mode(int if_index, int mode)
 {
 	DO_BPLIB_SET_ARG_FN(set_wd_exp_mode, SET_WD_EXP_MODE, if_index, mode);
 }
 
-int get_wd_exp_mode(int if_index)
+static int get_wd_exp_mode(int if_index)
 {
 	DO_BPLIB_GET_ARG_FN(get_wd_exp_mode, GET_WD_EXP_MODE, if_index);
 }
 
-int set_wd_autoreset(int if_index, int time)
+static int set_wd_autoreset(int if_index, int time)
 {
 	DO_BPLIB_SET_ARG_FN(set_wd_autoreset, SET_WD_AUTORESET, if_index, time);
 }
 
-int get_wd_autoreset(int if_index)
+static int get_wd_autoreset(int if_index)
 {
 	DO_BPLIB_GET_ARG_FN(get_wd_autoreset, GET_WD_AUTORESET, if_index);
 }
 
-int set_tpl(int if_index, int tpl_mode)
+static int set_tpl(int if_index, int tpl_mode)
 {
 	DO_BPLIB_SET_ARG_FN(set_tpl, SET_TPL, if_index, tpl_mode);
 }
 
-int get_tpl(int if_index)
+static int get_tpl(int if_index)
 {
 	DO_BPLIB_GET_ARG_FN(get_tpl, GET_TPL, if_index);
 }
 
-int set_bp_hw_reset(int if_index, int mode)
+static int set_bp_hw_reset(int if_index, int mode)
 {
 	DO_BPLIB_SET_ARG_FN(set_tpl, SET_BP_HW_RESET, if_index, mode);
 }
 
-int get_bp_hw_reset(int if_index)
+static int get_bp_hw_reset(int if_index)
 {
 	DO_BPLIB_GET_ARG_FN(get_tpl, GET_BP_HW_RESET, if_index);
 }
 
-int get_bypass_info(int if_index, struct bp_info *bp_info)
+static int get_bypass_info(int if_index, struct bp_info *bp_info)
 {
 	int ret = 0;
 	if (is_dev_sd(if_index)) {
@@ -468,14 +468,14 @@ int get_bypass_info(int if_index, struct bp_info *bp_info)
 	return ret;
 }
 
-int init_lib_module()
+int init_lib_module(void)
 {
 
 	printk(VERSION);
 	return 0;
 }
 
-void cleanup_lib_module()
+void cleanup_lib_module(void)
 {
 }
 
diff --git a/drivers/staging/slicoss/slicoss.c b/drivers/staging/slicoss/slicoss.c
index 76fc2e5..c8375a2 100644
--- a/drivers/staging/slicoss/slicoss.c
+++ b/drivers/staging/slicoss/slicoss.c
@@ -76,6 +76,7 @@
 #include <linux/bitops.h>
 #include <linux/io.h>
 #include <linux/netdevice.h>
+#include <linux/crc32.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/delay.h>
@@ -189,76 +190,14 @@ static inline void slic_reg64_write(struct adapter *adapter, void __iomem *reg,
 				adapter->bit64reglock.flags);
 }
 
-/*
- * Functions to obtain the CRC corresponding to the destination mac address.
- * This is a standard ethernet CRC in that it is a 32-bit, reflected CRC using
- * the polynomial:
- *   x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 +
- *   x^4 + x^2 + x^1.
- *
- * After the CRC for the 6 bytes is generated (but before the value is
- * complemented),
- * we must then transpose the value and return bits 30-23.
- *
- */
-static u32 slic_crc_table[256];	/* Table of CRCs for all possible byte values */
-static u32 slic_crc_init;	/* Is table initialized */
-
-/*
- *  Contruct the CRC32 table
- */
-static void slic_mcast_init_crc32(void)
-{
-	u32 c;			/*  CRC reg                      */
-	u32 e = 0;		/*  Poly X-or pattern            */
-	int i;			/*  counter                      */
-	int k;			/*  byte being shifted into crc  */
-
-	static int p[] = { 0, 1, 2, 4, 5, 7, 8, 10, 11, 12, 16, 22, 23, 26 };
-
-	for (i = 0; i < ARRAY_SIZE(p); i++)
-		e |= 1L << (31 - p[i]);
-
-	for (i = 1; i < 256; i++) {
-		c = i;
-		for (k = 8; k; k--)
-			c = c & 1 ? (c >> 1) ^ e : c >> 1;
-		slic_crc_table[i] = c;
-	}
-}
-
-/*
- *  Return the MAC hast as described above.
- */
-static unsigned char slic_mcast_get_mac_hash(char *macaddr)
-{
-	u32 crc;
-	char *p;
-	int i;
-	unsigned char machash = 0;
-
-	if (!slic_crc_init) {
-		slic_mcast_init_crc32();
-		slic_crc_init = 1;
-	}
-
-	crc = 0xFFFFFFFF;	/* Preload shift register, per crc-32 spec */
-	for (i = 0, p = macaddr; i < 6; ++p, ++i)
-		crc = (crc >> 8) ^ slic_crc_table[(crc ^ *p) & 0xFF];
-
-	/* Return bits 1-8, transposed */
-	for (i = 1; i < 9; i++)
-		machash |= (((crc >> i) & 1) << (8 - i));
-
-	return machash;
-}
-
 static void slic_mcast_set_bit(struct adapter *adapter, char *address)
 {
 	unsigned char crcpoly;
 
 	/* Get the CRC polynomial for the mac address */
-	crcpoly = slic_mcast_get_mac_hash(address);
+	/* we use bits 1-8 (lsb), bitwise reversed,
+	 * msb (= lsb bit 0 before bitrev) is automatically discarded */
+	crcpoly = (ether_crc(ETH_ALEN, address)>>23);
 
 	/* We only have space on the SLIC for 64 entries.  Lop
 	 * off the top two bits. (2^6 = 64)
@@ -901,10 +840,9 @@ static void slic_timer_load_check(ulong cardaddr)
 	u32 load = card->events;
 	u32 level = 0;
 
-	intagg = &adapter->slic_regs->slic_intagg;
-
 	if ((adapter) && (adapter->state == ADAPT_UP) &&
 	    (card->state == CARD_UP) && (slic_global.dynamic_intagg)) {
+		intagg = &adapter->slic_regs->slic_intagg;
 		if (adapter->devid == SLIC_1GB_DEVICE_ID) {
 			if (adapter->linkspeed == LINK_1000MB)
 				level = 100;
@@ -1061,7 +999,8 @@ static void slic_link_upr_complete(struct adapter *adapter, u32 isr)
 	if ((isr & ISR_UPCERR) || (isr & ISR_UPCBSY)) {
 		struct slic_shmem *pshmem;
 
-		pshmem = (struct slic_shmem *)adapter->phys_shmem;
+		pshmem = (struct slic_shmem *)(unsigned long)
+			 adapter->phys_shmem;
 #if BITS_PER_LONG == 64
 		slic_upr_queue_request(adapter,
 				       SLIC_UPR_RLSR,
@@ -1415,7 +1354,7 @@ static struct slic_rspbuf *slic_rspqueue_getnext(struct adapter *adapter)
 		slic_reg64_write(adapter, &adapter->slic_regs->slic_rbar64,
 			(rspq->paddr[rspq->pageindex] | SLIC_RSPQ_BUFSINPAGE),
 			&adapter->slic_regs->slic_addr_upper, 0, DONT_FLUSH);
-		rspq->pageindex = (++rspq->pageindex) % rspq->num_pages;
+		rspq->pageindex = (rspq->pageindex + 1) % rspq->num_pages;
 		rspq->offset = 0;
 		rspq->rspbuf = (struct slic_rspbuf *)
 						rspq->vaddr[rspq->pageindex];
@@ -1693,10 +1632,11 @@ retry_rcvqfill:
 #endif
 		skb = alloc_skb(SLIC_RCVQ_RCVBUFSIZE, GFP_ATOMIC);
 		if (skb) {
-			paddr = (void *)pci_map_single(adapter->pcidev,
-							  skb->data,
-							  SLIC_RCVQ_RCVBUFSIZE,
-							  PCI_DMA_FROMDEVICE);
+			paddr = (void *)(unsigned long)
+				pci_map_single(adapter->pcidev,
+					       skb->data,
+					       SLIC_RCVQ_RCVBUFSIZE,
+					       PCI_DMA_FROMDEVICE);
 			paddrl = SLIC_GET_ADDR_LOW(paddr);
 			paddrh = SLIC_GET_ADDR_HIGH(paddr);
 
@@ -1843,8 +1783,9 @@ static u32 slic_rcvqueue_reinsert(struct adapter *adapter, struct sk_buff *skb)
 	struct slic_rcvbuf *rcvbuf = (struct slic_rcvbuf *)skb->head;
 	struct device *dev;
 
-	paddr = (void *)pci_map_single(adapter->pcidev, skb->head,
-				  SLIC_RCVQ_RCVBUFSIZE, PCI_DMA_FROMDEVICE);
+	paddr = (void *)(unsigned long)
+		pci_map_single(adapter->pcidev, skb->head,
+			       SLIC_RCVQ_RCVBUFSIZE, PCI_DMA_FROMDEVICE);
 	rcvbuf->status = 0;
 	skb->next = NULL;
 
@@ -2341,7 +2282,7 @@ static void slic_link_event_handler(struct adapter *adapter)
 		return;
 	}
 
-	pshmem = (struct slic_shmem *)adapter->phys_shmem;
+	pshmem = (struct slic_shmem *)(unsigned long)adapter->phys_shmem;
 
 #if BITS_PER_LONG == 64
 	status = slic_upr_request(adapter,
@@ -2368,7 +2309,7 @@ static void slic_init_cleanup(struct adapter *adapter)
 				    sizeof(struct slic_shmem),
 				    adapter->pshmem, adapter->phys_shmem);
 		adapter->pshmem = NULL;
-		adapter->phys_shmem = (dma_addr_t) NULL;
+		adapter->phys_shmem = (dma_addr_t)(unsigned long)NULL;
 	}
 
 	if (adapter->pingtimerset) {
@@ -2787,7 +2728,6 @@ static netdev_tx_t slic_xmit_start(struct sk_buff *skb, struct net_device *dev)
 	struct adapter *adapter = netdev_priv(dev);
 	struct slic_hostcmd *hcmd = NULL;
 	u32 status = 0;
-	u32 skbtype = NORMAL_ETHFRAME;
 	void *offloadcmd = NULL;
 
 	card = adapter->card;
@@ -2801,19 +2741,16 @@ static netdev_tx_t slic_xmit_start(struct sk_buff *skb, struct net_device *dev)
 		goto xmit_fail;
 	}
 
-	if (skbtype == NORMAL_ETHFRAME) {
-		hcmd = slic_cmdq_getfree(adapter);
-		if (!hcmd) {
-			adapter->xmitq_full = 1;
-			status = XMIT_FAIL_HOSTCMD_FAIL;
-			goto xmit_fail;
-		}
-		hcmd->skb = skb;
-		hcmd->busy = 1;
-		hcmd->type = SLIC_CMD_DUMB;
-		if (skbtype == NORMAL_ETHFRAME)
-			slic_xmit_build_request(adapter, hcmd, skb);
+	hcmd = slic_cmdq_getfree(adapter);
+	if (!hcmd) {
+		adapter->xmitq_full = 1;
+		status = XMIT_FAIL_HOSTCMD_FAIL;
+		goto xmit_fail;
 	}
+	hcmd->skb = skb;
+	hcmd->busy = 1;
+	hcmd->type = SLIC_CMD_DUMB;
+	slic_xmit_build_request(adapter, hcmd, skb);
 	dev->stats.tx_packets++;
 	dev->stats.tx_bytes += skb->len;
 
@@ -2839,7 +2776,7 @@ static netdev_tx_t slic_xmit_start(struct sk_buff *skb, struct net_device *dev)
 xmit_done:
 	return NETDEV_TX_OK;
 xmit_fail:
-	slic_xmit_fail(adapter, skb, offloadcmd, skbtype, status);
+	slic_xmit_fail(adapter, skb, offloadcmd, NORMAL_ETHFRAME, status);
 	goto xmit_done;
 }
 
@@ -2946,7 +2883,8 @@ static int slic_if_init(struct adapter *adapter)
 	mdelay(1);
 
 	if (!adapter->isp_initialized) {
-		pshmem = (struct slic_shmem *)adapter->phys_shmem;
+		pshmem = (struct slic_shmem *)(unsigned long)
+			 adapter->phys_shmem;
 
 		spin_lock_irqsave(&adapter->bit64reglock.lock,
 					adapter->bit64reglock.flags);
@@ -3348,7 +3286,8 @@ static int slic_card_init(struct sliccard *card, struct adapter *adapter)
 		}
 		slic_reg32_write(&slic_regs->slic_icr, ICR_INT_OFF, FLUSH);
 		mdelay(1);
-		pshmem = (struct slic_shmem *)adapter->phys_shmem;
+		pshmem = (struct slic_shmem *)(unsigned long)
+			 adapter->phys_shmem;
 
 		spin_lock_irqsave(&adapter->bit64reglock.lock,
 					adapter->bit64reglock.flags);
@@ -3648,11 +3587,12 @@ static u32 slic_card_locate(struct adapter *adapter)
 
 	while (physcard) {
 		for (i = 0; i < SLIC_MAX_PORTS; i++) {
-			if (!physcard->adapter[i])
-				continue;
-			else
+			if (physcard->adapter[i])
 				break;
 		}
+		if (i == SLIC_MAX_PORTS)
+			break;
+
 		if (physcard->adapter[i]->slotnumber == adapter->slotnumber)
 			break;
 		physcard = physcard->next;
diff --git a/drivers/staging/sm7xxfb/sm7xxfb.c b/drivers/staging/sm7xxfb/sm7xxfb.c
index 0764bbb..8add64b 100644
--- a/drivers/staging/sm7xxfb/sm7xxfb.c
+++ b/drivers/staging/sm7xxfb/sm7xxfb.c
@@ -1006,15 +1006,7 @@ static int smtcfb_pci_resume(struct device *device)
 	return 0;
 }
 
-static const struct dev_pm_ops sm7xx_pm_ops = {
-	.suspend = smtcfb_pci_suspend,
-	.resume = smtcfb_pci_resume,
-	.freeze = smtcfb_pci_suspend,
-	.thaw = smtcfb_pci_resume,
-	.poweroff = smtcfb_pci_suspend,
-	.restore = smtcfb_pci_resume,
-};
-
+static SIMPLE_DEV_PM_OPS(sm7xx_pm_ops, smtcfb_pci_suspend, smtcfb_pci_resume);
 #define SM7XX_PM_OPS (&sm7xx_pm_ops)
 
 #else  /* !CONFIG_PM */
diff --git a/drivers/staging/speakup/kobjects.c b/drivers/staging/speakup/kobjects.c
index 35f647c..d6d9264 100644
--- a/drivers/staging/speakup/kobjects.c
+++ b/drivers/staging/speakup/kobjects.c
@@ -617,9 +617,9 @@ ssize_t spk_var_store(struct kobject *kobj, struct kobj_attribute *attr,
 			len = E_INC;
 		else
 			len = E_SET;
-		speakup_s2i(cp, &value);
+		value = simple_strtol(cp, NULL, 10);
 		ret = spk_set_num_var(value, param, len);
-		if (ret == E_RANGE) {
+		if (ret == -ERANGE) {
 			var_data = param->data;
 			pr_warn("value for %s out of range, expect %d to %d\n",
 				attr->attr.name,
@@ -637,7 +637,7 @@ ssize_t spk_var_store(struct kobject *kobj, struct kobj_attribute *attr,
 		cp = (char *) buf;
 		cp[len] = '\0';
 		ret = spk_set_string_var(buf, param, len);
-		if (ret == E_TOOLONG)
+		if (ret == -E2BIG)
 			pr_warn("value too long for %s\n",
 					attr->attr.name);
 		break;
@@ -670,7 +670,7 @@ ssize_t spk_var_store(struct kobject *kobj, struct kobj_attribute *attr,
 	}
 	spk_unlock(flags);
 
-	if (ret == SET_DEFAULT)
+	if (ret == -ERESTART)
 		pr_info("%s reset to default value\n", attr->attr.name);
 	return count;
 }
diff --git a/drivers/staging/speakup/main.c b/drivers/staging/speakup/main.c
index 9916e94..6c7b55c 100644
--- a/drivers/staging/speakup/main.c
+++ b/drivers/staging/speakup/main.c
@@ -1892,7 +1892,7 @@ oops:
 		spk_special_handler = NULL;
 		return 1;
 	}
-	cp = speakup_s2i(goto_buf, &go_pos);
+	go_pos = simple_strtol(goto_buf, &cp, 10);
 	goto_pos = (u_long) go_pos;
 	if (*cp == 'x') {
 		if (*goto_buf < '0')
diff --git a/drivers/staging/speakup/speakup.h b/drivers/staging/speakup/speakup.h
index 22f0fbb..c387a02 100644
--- a/drivers/staging/speakup/speakup.h
+++ b/drivers/staging/speakup/speakup.h
@@ -44,11 +44,6 @@
 #define IS_CHAR(x, type) (spk_chartab[((u_char)x)]&type)
 #define IS_TYPE(x, type) ((spk_chartab[((u_char)x)]&type) == type)
 
-#define SET_DEFAULT -4
-#define E_RANGE -3
-#define E_TOOLONG -2
-#define E_UNDEF -1
-
 extern int speakup_thread(void *data);
 extern void spk_reset_default_chars(void);
 extern void spk_reset_default_chartab(void);
@@ -58,7 +53,6 @@ void spk_reset_index_count(int sc);
 void spk_get_index_count(int *linecount, int *sentcount);
 extern int spk_set_key_info(const u_char *key_info, u_char *k_buffer);
 extern char *spk_strlwr(char *s);
-extern char *speakup_s2i(char *start, int *dest);
 extern char *spk_s2uchar(char *start, char *dest);
 extern char *spk_xlate(char *s);
 extern int speakup_kobj_init(void);
diff --git a/drivers/staging/speakup/varhandlers.c b/drivers/staging/speakup/varhandlers.c
index f8c1e45..be61a4e 100644
--- a/drivers/staging/speakup/varhandlers.c
+++ b/drivers/staging/speakup/varhandlers.c
@@ -184,19 +184,19 @@ int spk_set_num_var(int input, struct st_var_header *var, int how)
 	char buf[32];
 	char *cp;
 	struct var_t *var_data = var->data;
+
 	if (var_data == NULL)
-		return E_UNDEF;
+		return -ENODATA;
 
 	if (how == E_NEW_DEFAULT) {
 		if (input < var_data->u.n.low || input > var_data->u.n.high)
-			ret = E_RANGE;
-		else
-			var_data->u.n.default_val = input;
-		return ret;
+			return -ERANGE;
+		var_data->u.n.default_val = input;
+		return 0;
 	}
 	if (how == E_DEFAULT) {
 		val = var_data->u.n.default_val;
-		ret = SET_DEFAULT;
+		ret = -ERESTART;
 	} else {
 		if (how == E_SET)
 			val = input;
@@ -207,7 +207,7 @@ int spk_set_num_var(int input, struct st_var_header *var, int how)
 		else if (how == E_DEC)
 			val -= input;
 		if (val < var_data->u.n.low || val > var_data->u.n.high)
-			return E_RANGE;
+			return -ERANGE;
 	}
 	var_data->u.n.value = val;
 	if (var->var_type == VAR_TIME && p_val != NULL) {
@@ -246,25 +246,25 @@ int spk_set_num_var(int input, struct st_var_header *var, int how)
 
 int spk_set_string_var(const char *page, struct st_var_header *var, int len)
 {
-	int ret = 0;
 	struct var_t *var_data = var->data;
+
 	if (var_data == NULL)
-		return E_UNDEF;
+		return -ENODATA;
 	if (len > MAXVARLEN)
-		return -E_TOOLONG;
+		return -E2BIG;
 	if (!len) {
 		if (!var_data->u.s.default_val)
 			return 0;
-		ret = SET_DEFAULT;
 		if (!var->p_val)
 			var->p_val = var_data->u.s.default_val;
 		if (var->p_val != var_data->u.s.default_val)
 			strcpy((char *)var->p_val, var_data->u.s.default_val);
+		return -ERESTART;
 	} else if (var->p_val)
 		strcpy((char *)var->p_val, page);
 	else
-		return -E_TOOLONG;
-	return ret;
+		return -E2BIG;
+	return 0;
 }
 
 /* spk_set_mask_bits sets or clears the punc/delim/repeat bits,
@@ -319,38 +319,10 @@ char *spk_strlwr(char *s)
 	return s;
 }
 
-char *speakup_s2i(char *start, int *dest)
-{
-	int val;
-	char ch = *start;
-	if (ch == '-' || ch == '+')
-		start++;
-	if (*start < '0' || *start > '9')
-		return start;
-	val = (*start) - '0';
-	start++;
-	while (*start >= '0' && *start <= '9') {
-		val *= 10;
-		val += (*start) - '0';
-		start++;
-	}
-	if (ch == '-')
-		*dest = -val;
-	else
-		*dest = val;
-	return start;
-}
-
 char *spk_s2uchar(char *start, char *dest)
 {
 	int val = 0;
-	while (*start && *start <= SPACE)
-		start++;
-	while (*start >= '0' && *start <= '9') {
-		val *= 10;
-		val += (*start) - '0';
-		start++;
-	}
+	val = simple_strtoul(skip_spaces(start), &start, 10);
 	if (*start == ',')
 		start++;
 	*dest = (u_char)val;
diff --git a/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c b/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c
index 6a21f67..a126b25 100644
--- a/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c
+++ b/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c
@@ -649,7 +649,7 @@ static int synpatics_rmi4_touchpad_detect(struct synaptics_rmi4_data *pdata,
  *
  * This function calls to configures the rmi4 touchpad device
  */
-int synaptics_rmi4_touchpad_config(struct synaptics_rmi4_data *pdata,
+static int synaptics_rmi4_touchpad_config(struct synaptics_rmi4_data *pdata,
 						struct synaptics_rmi4_fn *rfi)
 {
 	/*
diff --git a/drivers/staging/ti-soc-thermal/Kconfig b/drivers/staging/ti-soc-thermal/Kconfig
new file mode 100644
index 0000000..e81375f
--- /dev/null
+++ b/drivers/staging/ti-soc-thermal/Kconfig
@@ -0,0 +1,48 @@
+config TI_SOC_THERMAL
+	tristate "Texas Instruments SoCs temperature sensor driver"
+	depends on THERMAL
+	depends on ARCH_HAS_BANDGAP
+	help
+	  If you say yes here you get support for the Texas Instruments
+	  OMAP4460+ on die bandgap temperature sensor support. The register
+	  set is part of system control module.
+
+	  This includes alert interrupts generation and also the TSHUT
+	  support.
+
+config TI_THERMAL
+	bool "Texas Instruments SoCs thermal framework support"
+	depends on TI_SOC_THERMAL
+	depends on CPU_THERMAL
+	help
+	  If you say yes here you want to get support for generic thermal
+	  framework for the Texas Instruments on die bandgap temperature sensor.
+
+	  This includes trip points definitions, extrapolation rules and
+	  CPU cooling device bindings.
+
+config OMAP4_THERMAL
+	bool "Texas Instruments OMAP4 thermal support"
+	depends on TI_SOC_THERMAL
+	depends on ARCH_OMAP4
+	help
+	  If you say yes here you get thermal support for the Texas Instruments
+	  OMAP4 SoC family. The current chip supported are:
+	   - OMAP4430
+	   - OMAP4460
+	   - OMAP4470
+
+	  This includes alert interrupts generation and also the TSHUT
+	  support.
+
+config OMAP5_THERMAL
+	bool "Texas Instruments OMAP5 thermal support"
+	depends on TI_SOC_THERMAL
+	depends on SOC_OMAP5
+	help
+	  If you say yes here you get thermal support for the Texas Instruments
+	  OMAP5 SoC family. The current chip supported are:
+	   - OMAP5430
+
+	  This includes alert interrupts generation and also the TSHUT
+	  support.
diff --git a/drivers/staging/ti-soc-thermal/Makefile b/drivers/staging/ti-soc-thermal/Makefile
new file mode 100644
index 0000000..0ca034f
--- /dev/null
+++ b/drivers/staging/ti-soc-thermal/Makefile
@@ -0,0 +1,5 @@
+obj-$(CONFIG_TI_SOC_THERMAL)		+= ti-soc-thermal.o
+ti-soc-thermal-y			:= ti-bandgap.o
+ti-soc-thermal-$(CONFIG_TI_THERMAL)	+= ti-thermal-common.o
+ti-soc-thermal-$(CONFIG_OMAP4_THERMAL)	+= omap4-thermal-data.o
+ti-soc-thermal-$(CONFIG_OMAP5_THERMAL)	+= omap5-thermal-data.o
diff --git a/drivers/staging/ti-soc-thermal/TODO b/drivers/staging/ti-soc-thermal/TODO
new file mode 100644
index 0000000..9b4c841
--- /dev/null
+++ b/drivers/staging/ti-soc-thermal/TODO
@@ -0,0 +1,24 @@
+List of TODOs (by Eduardo Valentin)
+
+on ti-bandgap.c:
+- Test every exposed API to userland
+- Add support to hwmon
+- Revisit PM support
+- Revisit data structures and simplify them
+- Once SCM-core api settles, update this driver accordingly
+
+on ti-thermal-common.c/ti-thermal.h:
+- Revisit extrapolation constants for O4/O5
+- Revisit need for locking
+- Revisit trips and its definitions
+- Revisit trending
+
+on omap5-thermal.c
+- Add support for GPU cooling
+
+generally:
+- make checkpatch.pl and sparse happy
+- make sure this code works on OMAP4430, OMAP4460 and OMAP5430
+- update documentation
+
+Copy patches to Eduardo Valentin <eduardo.valentin@ti.com>
diff --git a/drivers/staging/ti-soc-thermal/omap4-thermal-data.c b/drivers/staging/ti-soc-thermal/omap4-thermal-data.c
new file mode 100644
index 0000000..ee9c902
--- /dev/null
+++ b/drivers/staging/ti-soc-thermal/omap4-thermal-data.c
@@ -0,0 +1,267 @@
+/*
+ * OMAP4 thermal driver.
+ *
+ * Copyright (C) 2011-2012 Texas Instruments Inc.
+ * Contact:
+ *	Eduardo Valentin <eduardo.valentin@ti.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 "ti-thermal.h"
+#include "ti-bandgap.h"
+#include "omap4xxx-bandgap.h"
+
+/*
+ * OMAP4430 has one instance of thermal sensor for MPU
+ * need to describe the individual bit fields
+ */
+static struct temp_sensor_registers
+omap4430_mpu_temp_sensor_registers = {
+	.temp_sensor_ctrl = OMAP4430_TEMP_SENSOR_CTRL_OFFSET,
+	.bgap_tempsoff_mask = OMAP4430_BGAP_TEMPSOFF_MASK,
+	.bgap_soc_mask = OMAP4430_BGAP_TEMP_SENSOR_SOC_MASK,
+	.bgap_eocz_mask = OMAP4430_BGAP_TEMP_SENSOR_EOCZ_MASK,
+	.bgap_dtemp_mask = OMAP4430_BGAP_TEMP_SENSOR_DTEMP_MASK,
+
+	.bgap_mode_ctrl = OMAP4430_TEMP_SENSOR_CTRL_OFFSET,
+	.mode_ctrl_mask = OMAP4430_SINGLE_MODE_MASK,
+
+	.bgap_efuse = OMAP4430_FUSE_OPP_BGAP,
+};
+
+/* Thresholds and limits for OMAP4430 MPU temperature sensor */
+static struct temp_sensor_data omap4430_mpu_temp_sensor_data = {
+	.min_freq = OMAP4430_MIN_FREQ,
+	.max_freq = OMAP4430_MAX_FREQ,
+	.max_temp = OMAP4430_MAX_TEMP,
+	.min_temp = OMAP4430_MIN_TEMP,
+	.hyst_val = OMAP4430_HYST_VAL,
+};
+
+/*
+ * Temperature values in milli degree celsius
+ * ADC code values from 530 to 923
+ */
+static const int
+omap4430_adc_to_temp[OMAP4430_ADC_END_VALUE - OMAP4430_ADC_START_VALUE + 1] = {
+	-38000, -35000, -34000, -32000, -30000, -28000, -26000, -24000, -22000,
+	-20000, -18000, -17000, -15000, -13000, -12000, -10000, -8000, -6000,
+	-5000, -3000, -1000, 0, 2000, 3000, 5000, 6000, 8000, 10000, 12000,
+	13000, 15000, 17000, 19000, 21000, 23000, 25000, 27000, 28000, 30000,
+	32000, 33000, 35000, 37000, 38000, 40000, 42000, 43000, 45000, 47000,
+	48000, 50000, 52000, 53000, 55000, 57000, 58000, 60000, 62000, 64000,
+	66000, 68000, 70000, 71000, 73000, 75000, 77000, 78000, 80000, 82000,
+	83000, 85000, 87000, 88000, 90000, 92000, 93000, 95000, 97000, 98000,
+	100000, 102000, 103000, 105000, 107000, 109000, 111000, 113000, 115000,
+	117000, 118000, 120000, 122000, 123000,
+};
+
+/* OMAP4430 data */
+const struct ti_bandgap_data omap4430_data = {
+	.features = TI_BANDGAP_FEATURE_MODE_CONFIG |
+			TI_BANDGAP_FEATURE_CLK_CTRL |
+			TI_BANDGAP_FEATURE_POWER_SWITCH,
+	.fclock_name = "bandgap_fclk",
+	.div_ck_name = "bandgap_fclk",
+	.conv_table = omap4430_adc_to_temp,
+	.adc_start_val = OMAP4430_ADC_START_VALUE,
+	.adc_end_val = OMAP4430_ADC_END_VALUE,
+	.expose_sensor = ti_thermal_expose_sensor,
+	.remove_sensor = ti_thermal_remove_sensor,
+	.sensors = {
+		{
+		.registers = &omap4430_mpu_temp_sensor_registers,
+		.ts_data = &omap4430_mpu_temp_sensor_data,
+		.domain = "cpu",
+		.slope = 0,
+		.constant = 20000,
+		.slope_pcb = 0,
+		.constant_pcb = 20000,
+		.register_cooling = ti_thermal_register_cpu_cooling,
+		.unregister_cooling = ti_thermal_unregister_cpu_cooling,
+		},
+	},
+	.sensor_count = 1,
+};
+/*
+ * OMAP4460 has one instance of thermal sensor for MPU
+ * need to describe the individual bit fields
+ */
+static struct temp_sensor_registers
+omap4460_mpu_temp_sensor_registers = {
+	.temp_sensor_ctrl = OMAP4460_TEMP_SENSOR_CTRL_OFFSET,
+	.bgap_tempsoff_mask = OMAP4460_BGAP_TEMPSOFF_MASK,
+	.bgap_soc_mask = OMAP4460_BGAP_TEMP_SENSOR_SOC_MASK,
+	.bgap_eocz_mask = OMAP4460_BGAP_TEMP_SENSOR_EOCZ_MASK,
+	.bgap_dtemp_mask = OMAP4460_BGAP_TEMP_SENSOR_DTEMP_MASK,
+
+	.bgap_mask_ctrl = OMAP4460_BGAP_CTRL_OFFSET,
+	.mask_hot_mask = OMAP4460_MASK_HOT_MASK,
+	.mask_cold_mask = OMAP4460_MASK_COLD_MASK,
+
+	.bgap_mode_ctrl = OMAP4460_BGAP_CTRL_OFFSET,
+	.mode_ctrl_mask = OMAP4460_SINGLE_MODE_MASK,
+
+	.bgap_counter = OMAP4460_BGAP_COUNTER_OFFSET,
+	.counter_mask = OMAP4460_COUNTER_MASK,
+
+	.bgap_threshold = OMAP4460_BGAP_THRESHOLD_OFFSET,
+	.threshold_thot_mask = OMAP4460_T_HOT_MASK,
+	.threshold_tcold_mask = OMAP4460_T_COLD_MASK,
+
+	.tshut_threshold = OMAP4460_BGAP_TSHUT_OFFSET,
+	.tshut_hot_mask = OMAP4460_TSHUT_HOT_MASK,
+	.tshut_cold_mask = OMAP4460_TSHUT_COLD_MASK,
+
+	.bgap_status = OMAP4460_BGAP_STATUS_OFFSET,
+	.status_clean_stop_mask = OMAP4460_CLEAN_STOP_MASK,
+	.status_bgap_alert_mask = OMAP4460_BGAP_ALERT_MASK,
+	.status_hot_mask = OMAP4460_HOT_FLAG_MASK,
+	.status_cold_mask = OMAP4460_COLD_FLAG_MASK,
+
+	.bgap_efuse = OMAP4460_FUSE_OPP_BGAP,
+};
+
+/* Thresholds and limits for OMAP4460 MPU temperature sensor */
+static struct temp_sensor_data omap4460_mpu_temp_sensor_data = {
+	.tshut_hot = OMAP4460_TSHUT_HOT,
+	.tshut_cold = OMAP4460_TSHUT_COLD,
+	.t_hot = OMAP4460_T_HOT,
+	.t_cold = OMAP4460_T_COLD,
+	.min_freq = OMAP4460_MIN_FREQ,
+	.max_freq = OMAP4460_MAX_FREQ,
+	.max_temp = OMAP4460_MAX_TEMP,
+	.min_temp = OMAP4460_MIN_TEMP,
+	.hyst_val = OMAP4460_HYST_VAL,
+	.update_int1 = 1000,
+	.update_int2 = 2000,
+};
+
+/*
+ * Temperature values in milli degree celsius
+ * ADC code values from 530 to 923
+ */
+static const int
+omap4460_adc_to_temp[OMAP4460_ADC_END_VALUE - OMAP4460_ADC_START_VALUE + 1] = {
+	-40000, -40000, -40000, -40000, -39800, -39400, -39000, -38600, -38200,
+	-37800, -37300, -36800, -36400, -36000, -35600, -35200, -34800,
+	-34300, -33800, -33400, -33000, -32600, -32200, -31800, -31300,
+	-30800, -30400, -30000, -29600, -29200, -28700, -28200, -27800,
+	-27400, -27000, -26600, -26200, -25700, -25200, -24800, -24400,
+	-24000, -23600, -23200, -22700, -22200, -21800, -21400, -21000,
+	-20600, -20200, -19700, -19200, -18800, -18400, -18000, -17600,
+	-17200, -16700, -16200, -15800, -15400, -15000, -14600, -14200,
+	-13700, -13200, -12800, -12400, -12000, -11600, -11200, -10700,
+	-10200, -9800, -9400, -9000, -8600, -8200, -7700, -7200, -6800,
+	-6400, -6000, -5600, -5200, -4800, -4300, -3800, -3400, -3000,
+	-2600, -2200, -1800, -1300, -800, -400, 0, 400, 800, 1200, 1600,
+	2100, 2600, 3000, 3400, 3800, 4200, 4600, 5100, 5600, 6000, 6400,
+	6800, 7200, 7600, 8000, 8500, 9000, 9400, 9800, 10200, 10600, 11000,
+	11400, 11900, 12400, 12800, 13200, 13600, 14000, 14400, 14800,
+	15300, 15800, 16200, 16600, 17000, 17400, 17800, 18200, 18700,
+	19200, 19600, 20000, 20400, 20800, 21200, 21600, 22100, 22600,
+	23000, 23400, 23800, 24200, 24600, 25000, 25400, 25900, 26400,
+	26800, 27200, 27600, 28000, 28400, 28800, 29300, 29800, 30200,
+	30600, 31000, 31400, 31800, 32200, 32600, 33100, 33600, 34000,
+	34400, 34800, 35200, 35600, 36000, 36400, 36800, 37300, 37800,
+	38200, 38600, 39000, 39400, 39800, 40200, 40600, 41100, 41600,
+	42000, 42400, 42800, 43200, 43600, 44000, 44400, 44800, 45300,
+	45800, 46200, 46600, 47000, 47400, 47800, 48200, 48600, 49000,
+	49500, 50000, 50400, 50800, 51200, 51600, 52000, 52400, 52800,
+	53200, 53700, 54200, 54600, 55000, 55400, 55800, 56200, 56600,
+	57000, 57400, 57800, 58200, 58700, 59200, 59600, 60000, 60400,
+	60800, 61200, 61600, 62000, 62400, 62800, 63300, 63800, 64200,
+	64600, 65000, 65400, 65800, 66200, 66600, 67000, 67400, 67800,
+	68200, 68700, 69200, 69600, 70000, 70400, 70800, 71200, 71600,
+	72000, 72400, 72800, 73200, 73600, 74100, 74600, 75000, 75400,
+	75800, 76200, 76600, 77000, 77400, 77800, 78200, 78600, 79000,
+	79400, 79800, 80300, 80800, 81200, 81600, 82000, 82400, 82800,
+	83200, 83600, 84000, 84400, 84800, 85200, 85600, 86000, 86400,
+	86800, 87300, 87800, 88200, 88600, 89000, 89400, 89800, 90200,
+	90600, 91000, 91400, 91800, 92200, 92600, 93000, 93400, 93800,
+	94200, 94600, 95000, 95500, 96000, 96400, 96800, 97200, 97600,
+	98000, 98400, 98800, 99200, 99600, 100000, 100400, 100800, 101200,
+	101600, 102000, 102400, 102800, 103200, 103600, 104000, 104400,
+	104800, 105200, 105600, 106100, 106600, 107000, 107400, 107800,
+	108200, 108600, 109000, 109400, 109800, 110200, 110600, 111000,
+	111400, 111800, 112200, 112600, 113000, 113400, 113800, 114200,
+	114600, 115000, 115400, 115800, 116200, 116600, 117000, 117400,
+	117800, 118200, 118600, 119000, 119400, 119800, 120200, 120600,
+	121000, 121400, 121800, 122200, 122600, 123000, 123400, 123800, 124200,
+	124600, 124900, 125000, 125000, 125000, 125000
+};
+
+/* OMAP4460 data */
+const struct ti_bandgap_data omap4460_data = {
+	.features = TI_BANDGAP_FEATURE_TSHUT |
+			TI_BANDGAP_FEATURE_TSHUT_CONFIG |
+			TI_BANDGAP_FEATURE_TALERT |
+			TI_BANDGAP_FEATURE_MODE_CONFIG |
+			TI_BANDGAP_FEATURE_POWER_SWITCH |
+			TI_BANDGAP_FEATURE_CLK_CTRL |
+			TI_BANDGAP_FEATURE_COUNTER,
+	.fclock_name = "bandgap_ts_fclk",
+	.div_ck_name = "div_ts_ck",
+	.conv_table = omap4460_adc_to_temp,
+	.adc_start_val = OMAP4460_ADC_START_VALUE,
+	.adc_end_val = OMAP4460_ADC_END_VALUE,
+	.expose_sensor = ti_thermal_expose_sensor,
+	.remove_sensor = ti_thermal_remove_sensor,
+	.report_temperature = ti_thermal_report_sensor_temperature,
+	.sensors = {
+		{
+		.registers = &omap4460_mpu_temp_sensor_registers,
+		.ts_data = &omap4460_mpu_temp_sensor_data,
+		.domain = "cpu",
+		.slope = OMAP_GRADIENT_SLOPE_4460,
+		.constant = OMAP_GRADIENT_CONST_4460,
+		.slope_pcb = OMAP_GRADIENT_SLOPE_W_PCB_4460,
+		.constant_pcb = OMAP_GRADIENT_CONST_W_PCB_4460,
+		.register_cooling = ti_thermal_register_cpu_cooling,
+		.unregister_cooling = ti_thermal_unregister_cpu_cooling,
+		},
+	},
+	.sensor_count = 1,
+};
+
+/* OMAP4470 data */
+const struct ti_bandgap_data omap4470_data = {
+	.features = TI_BANDGAP_FEATURE_TSHUT |
+			TI_BANDGAP_FEATURE_TSHUT_CONFIG |
+			TI_BANDGAP_FEATURE_TALERT |
+			TI_BANDGAP_FEATURE_MODE_CONFIG |
+			TI_BANDGAP_FEATURE_POWER_SWITCH |
+			TI_BANDGAP_FEATURE_CLK_CTRL |
+			TI_BANDGAP_FEATURE_COUNTER,
+	.fclock_name = "bandgap_ts_fclk",
+	.div_ck_name = "div_ts_ck",
+	.conv_table = omap4460_adc_to_temp,
+	.adc_start_val = OMAP4460_ADC_START_VALUE,
+	.adc_end_val = OMAP4460_ADC_END_VALUE,
+	.expose_sensor = ti_thermal_expose_sensor,
+	.remove_sensor = ti_thermal_remove_sensor,
+	.report_temperature = ti_thermal_report_sensor_temperature,
+	.sensors = {
+		{
+		.registers = &omap4460_mpu_temp_sensor_registers,
+		.ts_data = &omap4460_mpu_temp_sensor_data,
+		.domain = "cpu",
+		.slope = OMAP_GRADIENT_SLOPE_4470,
+		.constant = OMAP_GRADIENT_CONST_4470,
+		.slope_pcb = OMAP_GRADIENT_SLOPE_W_PCB_4470,
+		.constant_pcb = OMAP_GRADIENT_CONST_W_PCB_4470,
+		.register_cooling = ti_thermal_register_cpu_cooling,
+		.unregister_cooling = ti_thermal_unregister_cpu_cooling,
+		},
+	},
+	.sensor_count = 1,
+};
diff --git a/drivers/staging/ti-soc-thermal/omap4xxx-bandgap.h b/drivers/staging/ti-soc-thermal/omap4xxx-bandgap.h
new file mode 100644
index 0000000..6f2de3a
--- /dev/null
+++ b/drivers/staging/ti-soc-thermal/omap4xxx-bandgap.h
@@ -0,0 +1,175 @@
+/*
+ * OMAP4xxx bandgap registers, bitfields and temperature definitions
+ *
+ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
+ * Contact:
+ *   Eduardo Valentin <eduardo.valentin@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 __OMAP4XXX_BANDGAP_H
+#define __OMAP4XXX_BANDGAP_H
+
+/**
+ * *** OMAP4430 ***
+ *
+ * Below, in sequence, are the Register definitions,
+ * the bitfields and the temperature definitions for OMAP4430.
+ */
+
+/**
+ * OMAP4430 register definitions
+ *
+ * Registers are defined as offsets. The offsets are
+ * relative to FUSE_OPP_BGAP on 4430.
+ */
+
+/* OMAP4430.FUSE_OPP_BGAP */
+#define OMAP4430_FUSE_OPP_BGAP				0x0
+
+/* OMAP4430.TEMP_SENSOR  */
+#define OMAP4430_TEMP_SENSOR_CTRL_OFFSET		0xCC
+
+/**
+ * Register and bit definitions for OMAP4430
+ *
+ * All the macros bellow define the required bits for
+ * controlling temperature on OMAP4430. Bit defines are
+ * grouped by register.
+ */
+
+/* OMAP4430.TEMP_SENSOR bits */
+#define OMAP4430_BGAP_TEMPSOFF_MASK			BIT(12)
+#define OMAP4430_BGAP_TSHUT_MASK			BIT(11)
+#define OMAP4430_SINGLE_MODE_MASK			BIT(10)
+#define OMAP4430_BGAP_TEMP_SENSOR_SOC_MASK		BIT(9)
+#define OMAP4430_BGAP_TEMP_SENSOR_EOCZ_MASK		BIT(8)
+#define OMAP4430_BGAP_TEMP_SENSOR_DTEMP_MASK		(0xff << 0)
+
+/**
+ * Temperature limits and thresholds for OMAP4430
+ *
+ * All the macros bellow are definitions for handling the
+ * ADC conversions and representation of temperature limits
+ * and thresholds for OMAP4430.
+ */
+
+/* ADC conversion table limits */
+#define OMAP4430_ADC_START_VALUE			0
+#define OMAP4430_ADC_END_VALUE				127
+/* bandgap clock limits (no control on 4430) */
+#define OMAP4430_MAX_FREQ				32768
+#define OMAP4430_MIN_FREQ				32768
+/* sensor limits */
+#define OMAP4430_MIN_TEMP				-40000
+#define OMAP4430_MAX_TEMP				125000
+#define OMAP4430_HYST_VAL				5000
+
+/**
+ * *** OMAP4460 *** Applicable for OMAP4470
+ *
+ * Below, in sequence, are the Register definitions,
+ * the bitfields and the temperature definitions for OMAP4460.
+ */
+
+/**
+ * OMAP4460 register definitions
+ *
+ * Registers are defined as offsets. The offsets are
+ * relative to FUSE_OPP_BGAP on 4460.
+ */
+
+/* OMAP4460.FUSE_OPP_BGAP */
+#define OMAP4460_FUSE_OPP_BGAP				0x0
+
+/* OMAP4460.TEMP_SENSOR */
+#define OMAP4460_TEMP_SENSOR_CTRL_OFFSET		0xCC
+
+/* OMAP4460.BANDGAP_CTRL */
+#define OMAP4460_BGAP_CTRL_OFFSET			0x118
+
+/* OMAP4460.BANDGAP_COUNTER */
+#define OMAP4460_BGAP_COUNTER_OFFSET			0x11C
+
+/* OMAP4460.BANDGAP_THRESHOLD */
+#define OMAP4460_BGAP_THRESHOLD_OFFSET			0x120
+
+/* OMAP4460.TSHUT_THRESHOLD */
+#define OMAP4460_BGAP_TSHUT_OFFSET			0x124
+
+/* OMAP4460.BANDGAP_STATUS */
+#define OMAP4460_BGAP_STATUS_OFFSET			0x128
+
+/**
+ * Register bitfields for OMAP4460
+ *
+ * All the macros bellow define the required bits for
+ * controlling temperature on OMAP4460. Bit defines are
+ * grouped by register.
+ */
+/* OMAP4460.TEMP_SENSOR bits */
+#define OMAP4460_BGAP_TEMPSOFF_MASK			BIT(13)
+#define OMAP4460_BGAP_TEMP_SENSOR_SOC_MASK		BIT(11)
+#define OMAP4460_BGAP_TEMP_SENSOR_EOCZ_MASK		BIT(10)
+#define OMAP4460_BGAP_TEMP_SENSOR_DTEMP_MASK		(0x3ff << 0)
+
+/* OMAP4460.BANDGAP_CTRL bits */
+#define OMAP4460_SINGLE_MODE_MASK			BIT(31)
+#define OMAP4460_MASK_HOT_MASK				BIT(1)
+#define OMAP4460_MASK_COLD_MASK				BIT(0)
+
+/* OMAP4460.BANDGAP_COUNTER bits */
+#define OMAP4460_COUNTER_MASK				(0xffffff << 0)
+
+/* OMAP4460.BANDGAP_THRESHOLD bits */
+#define OMAP4460_T_HOT_MASK				(0x3ff << 16)
+#define OMAP4460_T_COLD_MASK				(0x3ff << 0)
+
+/* OMAP4460.TSHUT_THRESHOLD bits */
+#define OMAP4460_TSHUT_HOT_MASK				(0x3ff << 16)
+#define OMAP4460_TSHUT_COLD_MASK			(0x3ff << 0)
+
+/* OMAP4460.BANDGAP_STATUS bits */
+#define OMAP4460_CLEAN_STOP_MASK			BIT(3)
+#define OMAP4460_BGAP_ALERT_MASK			BIT(2)
+#define OMAP4460_HOT_FLAG_MASK				BIT(1)
+#define OMAP4460_COLD_FLAG_MASK				BIT(0)
+
+/**
+ * Temperature limits and thresholds for OMAP4460
+ *
+ * All the macros bellow are definitions for handling the
+ * ADC conversions and representation of temperature limits
+ * and thresholds for OMAP4460.
+ */
+
+/* ADC conversion table limits */
+#define OMAP4460_ADC_START_VALUE			530
+#define OMAP4460_ADC_END_VALUE				932
+/* bandgap clock limits */
+#define OMAP4460_MAX_FREQ				1500000
+#define OMAP4460_MIN_FREQ				1000000
+/* sensor limits */
+#define OMAP4460_MIN_TEMP				-40000
+#define OMAP4460_MAX_TEMP				123000
+#define OMAP4460_HYST_VAL				5000
+/* interrupts thresholds */
+#define OMAP4460_TSHUT_HOT				900	/* 122 deg C */
+#define OMAP4460_TSHUT_COLD				895	/* 100 deg C */
+#define OMAP4460_T_HOT					800	/* 73 deg C */
+#define OMAP4460_T_COLD					795	/* 71 deg C */
+
+#endif /* __OMAP4XXX_BANDGAP_H */
diff --git a/drivers/staging/ti-soc-thermal/omap5-thermal-data.c b/drivers/staging/ti-soc-thermal/omap5-thermal-data.c
new file mode 100644
index 0000000..f170211
--- /dev/null
+++ b/drivers/staging/ti-soc-thermal/omap5-thermal-data.c
@@ -0,0 +1,360 @@
+/*
+ * OMAP5 thermal driver.
+ *
+ * Copyright (C) 2011-2012 Texas Instruments Inc.
+ * Contact:
+ *	Eduardo Valentin <eduardo.valentin@ti.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 "ti-thermal.h"
+#include "ti-bandgap.h"
+#include "omap5xxx-bandgap.h"
+
+/*
+ * OMAP5430 has three instances of thermal sensor for MPU, GPU & CORE,
+ * need to describe the individual registers and bit fields.
+ */
+
+/*
+ * OMAP5430 MPU thermal sensor register offset and bit-fields
+ */
+static struct temp_sensor_registers
+omap5430_mpu_temp_sensor_registers = {
+	.temp_sensor_ctrl = OMAP5430_TEMP_SENSOR_MPU_OFFSET,
+	.bgap_tempsoff_mask = OMAP5430_BGAP_TEMPSOFF_MASK,
+	.bgap_eocz_mask = OMAP5430_BGAP_TEMP_SENSOR_EOCZ_MASK,
+	.bgap_dtemp_mask = OMAP5430_BGAP_TEMP_SENSOR_DTEMP_MASK,
+
+	.bgap_mask_ctrl = OMAP5430_BGAP_CTRL_OFFSET,
+	.mask_hot_mask = OMAP5430_MASK_HOT_MPU_MASK,
+	.mask_cold_mask = OMAP5430_MASK_COLD_MPU_MASK,
+	.mask_sidlemode_mask = OMAP5430_MASK_SIDLEMODE_MASK,
+	.mask_counter_delay_mask = OMAP5430_MASK_COUNTER_DELAY_MASK,
+	.mask_freeze_mask = OMAP5430_MASK_FREEZE_MPU_MASK,
+	.mask_clear_mask = OMAP5430_MASK_CLEAR_MPU_MASK,
+	.mask_clear_accum_mask = OMAP5430_MASK_CLEAR_ACCUM_MPU_MASK,
+
+
+	.bgap_counter = OMAP5430_BGAP_CTRL_OFFSET,
+	.counter_mask = OMAP5430_COUNTER_MASK,
+
+	.bgap_threshold = OMAP5430_BGAP_THRESHOLD_MPU_OFFSET,
+	.threshold_thot_mask = OMAP5430_T_HOT_MASK,
+	.threshold_tcold_mask = OMAP5430_T_COLD_MASK,
+
+	.tshut_threshold = OMAP5430_BGAP_TSHUT_MPU_OFFSET,
+	.tshut_hot_mask = OMAP5430_TSHUT_HOT_MASK,
+	.tshut_cold_mask = OMAP5430_TSHUT_COLD_MASK,
+
+	.bgap_status = OMAP5430_BGAP_STATUS_OFFSET,
+	.status_clean_stop_mask = 0x0,
+	.status_bgap_alert_mask = OMAP5430_BGAP_ALERT_MASK,
+	.status_hot_mask = OMAP5430_HOT_MPU_FLAG_MASK,
+	.status_cold_mask = OMAP5430_COLD_MPU_FLAG_MASK,
+
+	.bgap_cumul_dtemp = OMAP5430_BGAP_CUMUL_DTEMP_MPU_OFFSET,
+	.ctrl_dtemp_0 = OMAP5430_BGAP_DTEMP_MPU_0_OFFSET,
+	.ctrl_dtemp_1 = OMAP5430_BGAP_DTEMP_MPU_1_OFFSET,
+	.ctrl_dtemp_2 = OMAP5430_BGAP_DTEMP_MPU_2_OFFSET,
+	.ctrl_dtemp_3 = OMAP5430_BGAP_DTEMP_MPU_3_OFFSET,
+	.ctrl_dtemp_4 = OMAP5430_BGAP_DTEMP_MPU_4_OFFSET,
+	.bgap_efuse = OMAP5430_FUSE_OPP_BGAP_MPU,
+};
+
+/*
+ * OMAP5430 GPU thermal sensor register offset and bit-fields
+ */
+static struct temp_sensor_registers
+omap5430_gpu_temp_sensor_registers = {
+	.temp_sensor_ctrl = OMAP5430_TEMP_SENSOR_GPU_OFFSET,
+	.bgap_tempsoff_mask = OMAP5430_BGAP_TEMPSOFF_MASK,
+	.bgap_eocz_mask = OMAP5430_BGAP_TEMP_SENSOR_EOCZ_MASK,
+	.bgap_dtemp_mask = OMAP5430_BGAP_TEMP_SENSOR_DTEMP_MASK,
+
+	.bgap_mask_ctrl = OMAP5430_BGAP_CTRL_OFFSET,
+	.mask_hot_mask = OMAP5430_MASK_HOT_GPU_MASK,
+	.mask_cold_mask = OMAP5430_MASK_COLD_GPU_MASK,
+	.mask_sidlemode_mask = OMAP5430_MASK_SIDLEMODE_MASK,
+	.mask_counter_delay_mask = OMAP5430_MASK_COUNTER_DELAY_MASK,
+	.mask_freeze_mask = OMAP5430_MASK_FREEZE_GPU_MASK,
+	.mask_clear_mask = OMAP5430_MASK_CLEAR_GPU_MASK,
+	.mask_clear_accum_mask = OMAP5430_MASK_CLEAR_ACCUM_GPU_MASK,
+
+	.bgap_counter = OMAP5430_BGAP_CTRL_OFFSET,
+	.counter_mask = OMAP5430_COUNTER_MASK,
+
+	.bgap_threshold = OMAP5430_BGAP_THRESHOLD_GPU_OFFSET,
+	.threshold_thot_mask = OMAP5430_T_HOT_MASK,
+	.threshold_tcold_mask = OMAP5430_T_COLD_MASK,
+
+	.tshut_threshold = OMAP5430_BGAP_TSHUT_GPU_OFFSET,
+	.tshut_hot_mask = OMAP5430_TSHUT_HOT_MASK,
+	.tshut_cold_mask = OMAP5430_TSHUT_COLD_MASK,
+
+	.bgap_status = OMAP5430_BGAP_STATUS_OFFSET,
+	.status_clean_stop_mask = 0x0,
+	.status_bgap_alert_mask = OMAP5430_BGAP_ALERT_MASK,
+	.status_hot_mask = OMAP5430_HOT_GPU_FLAG_MASK,
+	.status_cold_mask = OMAP5430_COLD_GPU_FLAG_MASK,
+
+	.bgap_cumul_dtemp = OMAP5430_BGAP_CUMUL_DTEMP_GPU_OFFSET,
+	.ctrl_dtemp_0 = OMAP5430_BGAP_DTEMP_GPU_0_OFFSET,
+	.ctrl_dtemp_1 = OMAP5430_BGAP_DTEMP_GPU_1_OFFSET,
+	.ctrl_dtemp_2 = OMAP5430_BGAP_DTEMP_GPU_2_OFFSET,
+	.ctrl_dtemp_3 = OMAP5430_BGAP_DTEMP_GPU_3_OFFSET,
+	.ctrl_dtemp_4 = OMAP5430_BGAP_DTEMP_GPU_4_OFFSET,
+
+	.bgap_efuse = OMAP5430_FUSE_OPP_BGAP_GPU,
+};
+
+/*
+ * OMAP5430 CORE thermal sensor register offset and bit-fields
+ */
+static struct temp_sensor_registers
+omap5430_core_temp_sensor_registers = {
+	.temp_sensor_ctrl = OMAP5430_TEMP_SENSOR_CORE_OFFSET,
+	.bgap_tempsoff_mask = OMAP5430_BGAP_TEMPSOFF_MASK,
+	.bgap_eocz_mask = OMAP5430_BGAP_TEMP_SENSOR_EOCZ_MASK,
+	.bgap_dtemp_mask = OMAP5430_BGAP_TEMP_SENSOR_DTEMP_MASK,
+
+	.bgap_mask_ctrl = OMAP5430_BGAP_CTRL_OFFSET,
+	.mask_hot_mask = OMAP5430_MASK_HOT_CORE_MASK,
+	.mask_cold_mask = OMAP5430_MASK_COLD_CORE_MASK,
+	.mask_sidlemode_mask = OMAP5430_MASK_SIDLEMODE_MASK,
+	.mask_counter_delay_mask = OMAP5430_MASK_COUNTER_DELAY_MASK,
+	.mask_freeze_mask = OMAP5430_MASK_FREEZE_CORE_MASK,
+	.mask_clear_mask = OMAP5430_MASK_CLEAR_CORE_MASK,
+	.mask_clear_accum_mask = OMAP5430_MASK_CLEAR_ACCUM_CORE_MASK,
+
+	.bgap_counter = OMAP5430_BGAP_CTRL_OFFSET,
+	.counter_mask = OMAP5430_COUNTER_MASK,
+
+	.bgap_threshold = OMAP5430_BGAP_THRESHOLD_CORE_OFFSET,
+	.threshold_thot_mask = OMAP5430_T_HOT_MASK,
+	.threshold_tcold_mask = OMAP5430_T_COLD_MASK,
+
+	.tshut_threshold = OMAP5430_BGAP_TSHUT_CORE_OFFSET,
+	.tshut_hot_mask = OMAP5430_TSHUT_HOT_MASK,
+	.tshut_cold_mask = OMAP5430_TSHUT_COLD_MASK,
+
+	.bgap_status = OMAP5430_BGAP_STATUS_OFFSET,
+	.status_clean_stop_mask = 0x0,
+	.status_bgap_alert_mask = OMAP5430_BGAP_ALERT_MASK,
+	.status_hot_mask = OMAP5430_HOT_CORE_FLAG_MASK,
+	.status_cold_mask = OMAP5430_COLD_CORE_FLAG_MASK,
+
+	.bgap_cumul_dtemp = OMAP5430_BGAP_CUMUL_DTEMP_CORE_OFFSET,
+	.ctrl_dtemp_0 = OMAP5430_BGAP_DTEMP_CORE_0_OFFSET,
+	.ctrl_dtemp_1 = OMAP5430_BGAP_DTEMP_CORE_1_OFFSET,
+	.ctrl_dtemp_2 = OMAP5430_BGAP_DTEMP_CORE_2_OFFSET,
+	.ctrl_dtemp_3 = OMAP5430_BGAP_DTEMP_CORE_3_OFFSET,
+	.ctrl_dtemp_4 = OMAP5430_BGAP_DTEMP_CORE_4_OFFSET,
+
+	.bgap_efuse = OMAP5430_FUSE_OPP_BGAP_CORE,
+};
+
+/* Thresholds and limits for OMAP5430 MPU temperature sensor */
+static struct temp_sensor_data omap5430_mpu_temp_sensor_data = {
+	.tshut_hot = OMAP5430_MPU_TSHUT_HOT,
+	.tshut_cold = OMAP5430_MPU_TSHUT_COLD,
+	.t_hot = OMAP5430_MPU_T_HOT,
+	.t_cold = OMAP5430_MPU_T_COLD,
+	.min_freq = OMAP5430_MPU_MIN_FREQ,
+	.max_freq = OMAP5430_MPU_MAX_FREQ,
+	.max_temp = OMAP5430_MPU_MAX_TEMP,
+	.min_temp = OMAP5430_MPU_MIN_TEMP,
+	.hyst_val = OMAP5430_MPU_HYST_VAL,
+	.update_int1 = 1000,
+	.update_int2 = 2000,
+};
+
+/* Thresholds and limits for OMAP5430 GPU temperature sensor */
+static struct temp_sensor_data omap5430_gpu_temp_sensor_data = {
+	.tshut_hot = OMAP5430_GPU_TSHUT_HOT,
+	.tshut_cold = OMAP5430_GPU_TSHUT_COLD,
+	.t_hot = OMAP5430_GPU_T_HOT,
+	.t_cold = OMAP5430_GPU_T_COLD,
+	.min_freq = OMAP5430_GPU_MIN_FREQ,
+	.max_freq = OMAP5430_GPU_MAX_FREQ,
+	.max_temp = OMAP5430_GPU_MAX_TEMP,
+	.min_temp = OMAP5430_GPU_MIN_TEMP,
+	.hyst_val = OMAP5430_GPU_HYST_VAL,
+	.update_int1 = 1000,
+	.update_int2 = 2000,
+};
+
+/* Thresholds and limits for OMAP5430 CORE temperature sensor */
+static struct temp_sensor_data omap5430_core_temp_sensor_data = {
+	.tshut_hot = OMAP5430_CORE_TSHUT_HOT,
+	.tshut_cold = OMAP5430_CORE_TSHUT_COLD,
+	.t_hot = OMAP5430_CORE_T_HOT,
+	.t_cold = OMAP5430_CORE_T_COLD,
+	.min_freq = OMAP5430_CORE_MIN_FREQ,
+	.max_freq = OMAP5430_CORE_MAX_FREQ,
+	.max_temp = OMAP5430_CORE_MAX_TEMP,
+	.min_temp = OMAP5430_CORE_MIN_TEMP,
+	.hyst_val = OMAP5430_CORE_HYST_VAL,
+	.update_int1 = 1000,
+	.update_int2 = 2000,
+};
+
+/*
+ * OMAP54xx ES2.0 : Temperature values in milli degree celsius
+ * ADC code values from 540 to 945
+ */
+static int
+omap5430_adc_to_temp[
+	OMAP5430_ADC_END_VALUE - OMAP5430_ADC_START_VALUE + 1] = {
+	/* Index 540 - 549 */
+	-40000, -40000, -40000, -40000, -39800, -39400, -39000, -38600, -38200,
+	-37800,
+	/* Index 550 - 559 */
+	-37400, -37000, -36600, -36200, -35800, -35300, -34700, -34200, -33800,
+	-33400,
+	/* Index 560 - 569 */
+	-33000, -32600, -32200, -31800, -31400, -31000, -30600, -30200, -29800,
+	-29400,
+	/* Index 570 - 579 */
+	-29000, -28600, -28200, -27700, -27100, -26600, -26200, -25800, -25400,
+	-25000,
+	/* Index 580 - 589 */
+	-24600, -24200, -23800, -23400, -23000, -22600, -22200, -21600, -21400,
+	-21000,
+	/* Index 590 - 599 */
+	-20500, -19900, -19400, -19000, -18600, -18200, -17800, -17400, -17000,
+	-16600,
+	/* Index 600 - 609 */
+	-16200, -15800, -15400, -15000, -14600, -14200, -13800,	-13400, -13000,
+	-12500,
+	/* Index 610 - 619 */
+	-11900, -11400, -11000, -10600, -10200, -9800, -9400, -9000, -8600,
+	-8200,
+	/* Index 620 - 629 */
+	-7800, -7400, -7000, -6600, -6200, -5800, -5400, -5000, -4500, -3900,
+	/* Index 630 - 639 */
+	-3400, -3000, -2600, -2200, -1800, -1400, -1000, -600, -200, 200,
+	/* Index 640 - 649 */
+	600, 1000, 1400, 1800, 2200, 2600, 3000, 3400, 3900, 4500,
+	/* Index 650 - 659 */
+	5000, 5400, 5800, 6200, 6600, 7000, 7400, 7800, 8200, 8600,
+	/* Index 660 - 669 */
+	9000, 9400, 9800, 10200, 10600, 11000, 11400, 11800, 12200, 12700,
+	/* Index 670 - 679 */
+	13300, 13800, 14200, 14600, 15000, 15400, 15800, 16200, 16600, 17000,
+	/* Index 680 - 689 */
+	17400, 17800, 18200, 18600, 19000, 19400, 19800, 20200, 20600, 21100,
+	/* Index 690 - 699 */
+	21400, 21900, 22500, 23000, 23400, 23800, 24200, 24600, 25000, 25400,
+	/* Index 700 - 709 */
+	25800, 26200, 26600, 27000, 27400, 27800, 28200, 28600, 29000, 29400,
+	/* Index 710 - 719 */
+	29800, 30200, 30600, 31000, 31400, 31900, 32500, 33000, 33400, 33800,
+	/* Index 720 - 729 */
+	34200, 34600, 35000, 35400, 35800, 36200, 36600, 37000, 37400, 37800,
+	/* Index 730 - 739 */
+	38200, 38600, 39000, 39400, 39800, 40200, 40600, 41000, 41400, 41800,
+	/* Index 740 - 749 */
+	42200, 42600, 43100, 43700, 44200, 44600, 45000, 45400, 45800, 46200,
+	/* Index 750 - 759 */
+	46600, 47000, 47400, 47800, 48200, 48600, 49000, 49400, 49800, 50200,
+	/* Index 760 - 769 */
+	50600, 51000, 51400, 51800, 52200, 52600, 53000, 53400, 53800, 54200,
+	/* Index 770 - 779 */
+	54600, 55000, 55400, 55900, 56500, 57000, 57400, 57800, 58200, 58600,
+	/* Index 780 - 789 */
+	59000, 59400, 59800, 60200, 60600, 61000, 61400, 61800, 62200, 62600,
+	/* Index 790 - 799 */
+	63000, 63400, 63800, 64200, 64600, 65000, 65400, 65800, 66200, 66600,
+	/* Index 800 - 809 */
+	67000, 67400, 67800, 68200, 68600, 69000, 69400, 69800, 70200, 70600,
+	/* Index 810 - 819 */
+	71000, 71500, 72100, 72600, 73000, 73400, 73800, 74200, 74600, 75000,
+	/* Index 820 - 829 */
+	75400, 75800, 76200, 76600, 77000, 77400, 77800, 78200, 78600, 79000,
+	/* Index 830 - 839 */
+	79400, 79800, 80200, 80600, 81000, 81400, 81800, 82200, 82600, 83000,
+	/* Index 840 - 849 */
+	83400, 83800, 84200, 84600, 85000, 85400, 85800, 86200, 86600, 87000,
+	/* Index 850 - 859 */
+	87400, 87800, 88200, 88600, 89000, 89400, 89800, 90200, 90600, 91000,
+	/* Index 860 - 869 */
+	91400, 91800, 92200, 92600, 93000, 93400, 93800, 94200, 94600, 95000,
+	/* Index 870 - 879 */
+	95400, 95800, 96200, 96600, 97000, 97500, 98100, 98600, 99000, 99400,
+	/* Index 880 - 889 */
+	99800, 100200, 100600, 101000, 101400, 101800, 102200, 102600, 103000,
+	103400,
+	/* Index 890 - 899 */
+	103800, 104200, 104600, 105000, 105400, 105800, 106200, 106600, 107000,
+	107400,
+	/* Index 900 - 909 */
+	107800, 108200, 108600, 109000, 109400, 109800, 110200, 110600, 111000,
+	111400,
+	/* Index 910 - 919 */
+	111800, 112200, 112600, 113000, 113400, 113800, 114200, 114600, 115000,
+	115400,
+	/* Index 920 - 929 */
+	115800, 116200, 116600, 117000, 117400, 117800, 118200, 118600, 119000,
+	119400,
+	/* Index 930 - 939 */
+	119800, 120200, 120600, 121000, 121400, 121800, 122400, 122600, 123000,
+	123400,
+	/* Index 940 - 945 */
+	123800, 1242000, 124600, 124900, 125000, 125000,
+};
+
+/* OMAP54xx ES2.0 data */
+/* TODO : Need to update the slope/constant for ES2.0 silicon */
+const struct ti_bandgap_data omap5430_data = {
+	.features = TI_BANDGAP_FEATURE_TSHUT_CONFIG |
+			TI_BANDGAP_FEATURE_FREEZE_BIT |
+			TI_BANDGAP_FEATURE_TALERT |
+			TI_BANDGAP_FEATURE_COUNTER_DELAY |
+			TI_BANDGAP_FEATURE_HISTORY_BUFFER,
+	.fclock_name = "l3instr_ts_gclk_div",
+	.div_ck_name = "l3instr_ts_gclk_div",
+	.conv_table = omap5430_adc_to_temp,
+	.adc_start_val = OMAP5430_ADC_START_VALUE,
+	.adc_end_val = OMAP5430_ADC_END_VALUE,
+	.expose_sensor = ti_thermal_expose_sensor,
+	.remove_sensor = ti_thermal_remove_sensor,
+	.report_temperature = ti_thermal_report_sensor_temperature,
+	.sensors = {
+		{
+		.registers = &omap5430_mpu_temp_sensor_registers,
+		.ts_data = &omap5430_mpu_temp_sensor_data,
+		.domain = "cpu",
+		.register_cooling = ti_thermal_register_cpu_cooling,
+		.unregister_cooling = ti_thermal_unregister_cpu_cooling,
+		.slope = OMAP_GRADIENT_SLOPE_5430_CPU,
+		.constant = OMAP_GRADIENT_CONST_5430_CPU,
+		.slope_pcb = OMAP_GRADIENT_SLOPE_W_PCB_5430_CPU,
+		.constant_pcb = OMAP_GRADIENT_CONST_W_PCB_5430_CPU,
+		},
+		{
+		.registers = &omap5430_gpu_temp_sensor_registers,
+		.ts_data = &omap5430_gpu_temp_sensor_data,
+		.domain = "gpu",
+		.slope = OMAP_GRADIENT_SLOPE_5430_GPU,
+		.constant = OMAP_GRADIENT_CONST_5430_GPU,
+		.slope_pcb = OMAP_GRADIENT_SLOPE_W_PCB_5430_GPU,
+		.constant_pcb = OMAP_GRADIENT_CONST_W_PCB_5430_GPU,
+		},
+		{
+		.registers = &omap5430_core_temp_sensor_registers,
+		.ts_data = &omap5430_core_temp_sensor_data,
+		.domain = "core",
+		},
+	},
+	.sensor_count = 3,
+};
diff --git a/drivers/staging/ti-soc-thermal/omap5xxx-bandgap.h b/drivers/staging/ti-soc-thermal/omap5xxx-bandgap.h
new file mode 100644
index 0000000..400b55d
--- /dev/null
+++ b/drivers/staging/ti-soc-thermal/omap5xxx-bandgap.h
@@ -0,0 +1,200 @@
+/*
+ * OMAP5xxx bandgap registers, bitfields and temperature definitions
+ *
+ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
+ * Contact:
+ *   Eduardo Valentin <eduardo.valentin@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 __OMAP5XXX_BANDGAP_H
+#define __OMAP5XXX_BANDGAP_H
+
+/**
+ * *** OMAP5430 ***
+ *
+ * Below, in sequence, are the Register definitions,
+ * the bitfields and the temperature definitions for OMAP5430.
+ */
+
+/**
+ * OMAP5430 register definitions
+ *
+ * Registers are defined as offsets. The offsets are
+ * relative to FUSE_OPP_BGAP_GPU on 5430.
+ *
+ * Register below are grouped by domain (not necessarily in offset order)
+ */
+
+/* OMAP5430.GPU register offsets */
+#define OMAP5430_FUSE_OPP_BGAP_GPU			0x0
+#define OMAP5430_TEMP_SENSOR_GPU_OFFSET			0x150
+#define OMAP5430_BGAP_THRESHOLD_GPU_OFFSET		0x1A8
+#define OMAP5430_BGAP_TSHUT_GPU_OFFSET			0x1B4
+#define OMAP5430_BGAP_CUMUL_DTEMP_GPU_OFFSET		0x1C0
+#define OMAP5430_BGAP_DTEMP_GPU_0_OFFSET		0x1F4
+#define OMAP5430_BGAP_DTEMP_GPU_1_OFFSET		0x1F8
+#define OMAP5430_BGAP_DTEMP_GPU_2_OFFSET		0x1FC
+#define OMAP5430_BGAP_DTEMP_GPU_3_OFFSET		0x200
+#define OMAP5430_BGAP_DTEMP_GPU_4_OFFSET		0x204
+
+/* OMAP5430.MPU register offsets */
+#define OMAP5430_FUSE_OPP_BGAP_MPU			0x4
+#define OMAP5430_TEMP_SENSOR_MPU_OFFSET			0x14C
+#define OMAP5430_BGAP_THRESHOLD_MPU_OFFSET		0x1A4
+#define OMAP5430_BGAP_TSHUT_MPU_OFFSET			0x1B0
+#define OMAP5430_BGAP_CUMUL_DTEMP_MPU_OFFSET		0x1BC
+#define OMAP5430_BGAP_DTEMP_MPU_0_OFFSET		0x1E0
+#define OMAP5430_BGAP_DTEMP_MPU_1_OFFSET		0x1E4
+#define OMAP5430_BGAP_DTEMP_MPU_2_OFFSET		0x1E8
+#define OMAP5430_BGAP_DTEMP_MPU_3_OFFSET		0x1EC
+#define OMAP5430_BGAP_DTEMP_MPU_4_OFFSET		0x1F0
+
+/* OMAP5430.MPU register offsets */
+#define OMAP5430_FUSE_OPP_BGAP_CORE			0x8
+#define OMAP5430_TEMP_SENSOR_CORE_OFFSET		0x154
+#define OMAP5430_BGAP_THRESHOLD_CORE_OFFSET		0x1AC
+#define OMAP5430_BGAP_TSHUT_CORE_OFFSET			0x1B8
+#define OMAP5430_BGAP_CUMUL_DTEMP_CORE_OFFSET		0x1C4
+#define OMAP5430_BGAP_DTEMP_CORE_0_OFFSET		0x208
+#define OMAP5430_BGAP_DTEMP_CORE_1_OFFSET		0x20C
+#define OMAP5430_BGAP_DTEMP_CORE_2_OFFSET		0x210
+#define OMAP5430_BGAP_DTEMP_CORE_3_OFFSET		0x214
+#define OMAP5430_BGAP_DTEMP_CORE_4_OFFSET		0x218
+
+/* OMAP5430.common register offsets */
+#define OMAP5430_BGAP_CTRL_OFFSET			0x1A0
+#define OMAP5430_BGAP_STATUS_OFFSET			0x1C8
+
+/**
+ * Register bitfields for OMAP5430
+ *
+ * All the macros bellow define the required bits for
+ * controlling temperature on OMAP5430. Bit defines are
+ * grouped by register.
+ */
+
+/* OMAP5430.TEMP_SENSOR */
+#define OMAP5430_BGAP_TEMP_SENSOR_SOC_MASK		BIT(12)
+#define OMAP5430_BGAP_TEMPSOFF_MASK			BIT(11)
+#define OMAP5430_BGAP_TEMP_SENSOR_EOCZ_MASK		BIT(10)
+#define OMAP5430_BGAP_TEMP_SENSOR_DTEMP_MASK		(0x3ff << 0)
+
+/* OMAP5430.BANDGAP_CTRL */
+#define OMAP5430_MASK_SIDLEMODE_MASK			(0x3 << 30)
+#define OMAP5430_MASK_COUNTER_DELAY_MASK		(0x7 << 27)
+#define OMAP5430_MASK_FREEZE_CORE_MASK			BIT(23)
+#define OMAP5430_MASK_FREEZE_GPU_MASK			BIT(22)
+#define OMAP5430_MASK_FREEZE_MPU_MASK			BIT(21)
+#define OMAP5430_MASK_CLEAR_CORE_MASK			BIT(20)
+#define OMAP5430_MASK_CLEAR_GPU_MASK			BIT(19)
+#define OMAP5430_MASK_CLEAR_MPU_MASK			BIT(18)
+#define OMAP5430_MASK_CLEAR_ACCUM_CORE_MASK		BIT(17)
+#define OMAP5430_MASK_CLEAR_ACCUM_GPU_MASK		BIT(16)
+#define OMAP5430_MASK_CLEAR_ACCUM_MPU_MASK		BIT(15)
+#define OMAP5430_MASK_HOT_CORE_MASK			BIT(5)
+#define OMAP5430_MASK_COLD_CORE_MASK			BIT(4)
+#define OMAP5430_MASK_HOT_GPU_MASK			BIT(3)
+#define OMAP5430_MASK_COLD_GPU_MASK			BIT(2)
+#define OMAP5430_MASK_HOT_MPU_MASK			BIT(1)
+#define OMAP5430_MASK_COLD_MPU_MASK			BIT(0)
+
+/* OMAP5430.BANDGAP_COUNTER */
+#define OMAP5430_COUNTER_MASK				(0xffffff << 0)
+
+/* OMAP5430.BANDGAP_THRESHOLD */
+#define OMAP5430_T_HOT_MASK				(0x3ff << 16)
+#define OMAP5430_T_COLD_MASK				(0x3ff << 0)
+
+/* OMAP5430.TSHUT_THRESHOLD */
+#define OMAP5430_TSHUT_HOT_MASK				(0x3ff << 16)
+#define OMAP5430_TSHUT_COLD_MASK			(0x3ff << 0)
+
+/* OMAP5430.BANDGAP_CUMUL_DTEMP_MPU */
+#define OMAP5430_CUMUL_DTEMP_MPU_MASK			(0xffffffff << 0)
+
+/* OMAP5430.BANDGAP_CUMUL_DTEMP_GPU */
+#define OMAP5430_CUMUL_DTEMP_GPU_MASK			(0xffffffff << 0)
+
+/* OMAP5430.BANDGAP_CUMUL_DTEMP_CORE */
+#define OMAP5430_CUMUL_DTEMP_CORE_MASK			(0xffffffff << 0)
+
+/* OMAP5430.BANDGAP_STATUS */
+#define OMAP5430_BGAP_ALERT_MASK			BIT(31)
+#define OMAP5430_HOT_CORE_FLAG_MASK			BIT(5)
+#define OMAP5430_COLD_CORE_FLAG_MASK			BIT(4)
+#define OMAP5430_HOT_GPU_FLAG_MASK			BIT(3)
+#define OMAP5430_COLD_GPU_FLAG_MASK			BIT(2)
+#define OMAP5430_HOT_MPU_FLAG_MASK			BIT(1)
+#define OMAP5430_COLD_MPU_FLAG_MASK			BIT(0)
+
+/**
+ * Temperature limits and thresholds for OMAP5430
+ *
+ * All the macros bellow are definitions for handling the
+ * ADC conversions and representation of temperature limits
+ * and thresholds for OMAP5430. Definitions are grouped
+ * by temperature domain.
+ */
+
+/* OMAP5430.common temperature definitions */
+/* ADC conversion table limits */
+#define OMAP5430_ADC_START_VALUE			540
+#define OMAP5430_ADC_END_VALUE				945
+
+/* OMAP5430.GPU temperature definitions */
+/* bandgap clock limits */
+#define OMAP5430_GPU_MAX_FREQ				1500000
+#define OMAP5430_GPU_MIN_FREQ				1000000
+/* sensor limits */
+#define OMAP5430_GPU_MIN_TEMP				-40000
+#define OMAP5430_GPU_MAX_TEMP				125000
+#define OMAP5430_GPU_HYST_VAL				5000
+/* interrupts thresholds */
+#define OMAP5430_GPU_TSHUT_HOT				915
+#define OMAP5430_GPU_TSHUT_COLD				900
+#define OMAP5430_GPU_T_HOT				800
+#define OMAP5430_GPU_T_COLD				795
+
+/* OMAP5430.MPU temperature definitions */
+/* bandgap clock limits */
+#define OMAP5430_MPU_MAX_FREQ				1500000
+#define OMAP5430_MPU_MIN_FREQ				1000000
+/* sensor limits */
+#define OMAP5430_MPU_MIN_TEMP				-40000
+#define OMAP5430_MPU_MAX_TEMP				125000
+#define OMAP5430_MPU_HYST_VAL				5000
+/* interrupts thresholds */
+#define OMAP5430_MPU_TSHUT_HOT				915
+#define OMAP5430_MPU_TSHUT_COLD				900
+#define OMAP5430_MPU_T_HOT				800
+#define OMAP5430_MPU_T_COLD				795
+
+/* OMAP5430.CORE temperature definitions */
+/* bandgap clock limits */
+#define OMAP5430_CORE_MAX_FREQ				1500000
+#define OMAP5430_CORE_MIN_FREQ				1000000
+/* sensor limits */
+#define OMAP5430_CORE_MIN_TEMP				-40000
+#define OMAP5430_CORE_MAX_TEMP				125000
+#define OMAP5430_CORE_HYST_VAL				5000
+/* interrupts thresholds */
+#define OMAP5430_CORE_TSHUT_HOT				915
+#define OMAP5430_CORE_TSHUT_COLD			900
+#define OMAP5430_CORE_T_HOT				800
+#define OMAP5430_CORE_T_COLD				795
+
+#endif /* __OMAP5XXX_BANDGAP_H */
diff --git a/drivers/staging/ti-soc-thermal/ti-bandgap.c b/drivers/staging/ti-soc-thermal/ti-bandgap.c
new file mode 100644
index 0000000..5b06b12
--- /dev/null
+++ b/drivers/staging/ti-soc-thermal/ti-bandgap.c
@@ -0,0 +1,1529 @@
+/*
+ * TI Bandgap temperature sensor driver
+ *
+ * Copyright (C) 2011-2012 Texas Instruments Incorporated - http://www.ti.com/
+ * Author: J Keerthy <j-keerthy@ti.com>
+ * Author: Moiz Sonasath <m-sonasath@ti.com>
+ * Couple of fixes, DT and MFD adaptation:
+ *   Eduardo Valentin <eduardo.valentin@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/module.h>
+#include <linux/export.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/clk.h>
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/types.h>
+#include <linux/spinlock.h>
+#include <linux/reboot.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+#include <linux/of_irq.h>
+#include <linux/io.h>
+
+#include "ti-bandgap.h"
+
+/***   Helper functions to access registers and their bitfields   ***/
+
+/**
+ * ti_bandgap_readl() - simple read helper function
+ * @bgp: pointer to ti_bandgap structure
+ * @reg: desired register (offset) to be read
+ *
+ * Helper function to read bandgap registers. It uses the io remapped area.
+ * Return: the register value.
+ */
+static u32 ti_bandgap_readl(struct ti_bandgap *bgp, u32 reg)
+{
+	return readl(bgp->base + reg);
+}
+
+/**
+ * ti_bandgap_writel() - simple write helper function
+ * @bgp: pointer to ti_bandgap structure
+ * @val: desired register value to be written
+ * @reg: desired register (offset) to be written
+ *
+ * Helper function to write bandgap registers. It uses the io remapped area.
+ */
+static void ti_bandgap_writel(struct ti_bandgap *bgp, u32 val, u32 reg)
+{
+	writel(val, bgp->base + reg);
+}
+
+/**
+ * DOC: macro to update bits.
+ *
+ * RMW_BITS() - used to read, modify and update bandgap bitfields.
+ *            The value passed will be shifted.
+ */
+#define RMW_BITS(bgp, id, reg, mask, val)			\
+do {								\
+	struct temp_sensor_registers *t;			\
+	u32 r;							\
+								\
+	t = bgp->conf->sensors[(id)].registers;		\
+	r = ti_bandgap_readl(bgp, t->reg);			\
+	r &= ~t->mask;						\
+	r |= (val) << __ffs(t->mask);				\
+	ti_bandgap_writel(bgp, r, t->reg);			\
+} while (0)
+
+/***   Basic helper functions   ***/
+
+/**
+ * ti_bandgap_power() - controls the power state of a bandgap device
+ * @bgp: pointer to ti_bandgap structure
+ * @on: desired power state (1 - on, 0 - off)
+ *
+ * Used to power on/off a bandgap device instance. Only used on those
+ * that features tempsoff bit.
+ *
+ * Return: 0 on success, -ENOTSUPP if tempsoff is not supported.
+ */
+static int ti_bandgap_power(struct ti_bandgap *bgp, bool on)
+{
+	int i, ret = 0;
+
+	if (!TI_BANDGAP_HAS(bgp, POWER_SWITCH)) {
+		ret = -ENOTSUPP;
+		goto exit;
+	}
+
+	for (i = 0; i < bgp->conf->sensor_count; i++)
+		/* active on 0 */
+		RMW_BITS(bgp, i, temp_sensor_ctrl, bgap_tempsoff_mask, !on);
+
+exit:
+	return ret;
+}
+
+/**
+ * ti_bandgap_read_temp() - helper function to read sensor temperature
+ * @bgp: pointer to ti_bandgap structure
+ * @id: bandgap sensor id
+ *
+ * Function to concentrate the steps to read sensor temperature register.
+ * This function is desired because, depending on bandgap device version,
+ * it might be needed to freeze the bandgap state machine, before fetching
+ * the register value.
+ *
+ * Return: temperature in ADC values.
+ */
+static u32 ti_bandgap_read_temp(struct ti_bandgap *bgp, int id)
+{
+	struct temp_sensor_registers *tsr;
+	u32 temp, reg;
+
+	tsr = bgp->conf->sensors[id].registers;
+	reg = tsr->temp_sensor_ctrl;
+
+	if (TI_BANDGAP_HAS(bgp, FREEZE_BIT)) {
+		RMW_BITS(bgp, id, bgap_mask_ctrl, mask_freeze_mask, 1);
+		/*
+		 * In case we cannot read from cur_dtemp / dtemp_0,
+		 * then we read from the last valid temp read
+		 */
+		reg = tsr->ctrl_dtemp_1;
+	}
+
+	/* read temperature */
+	temp = ti_bandgap_readl(bgp, reg);
+	temp &= tsr->bgap_dtemp_mask;
+
+	if (TI_BANDGAP_HAS(bgp, FREEZE_BIT))
+		RMW_BITS(bgp, id, bgap_mask_ctrl, mask_freeze_mask, 0);
+
+	return temp;
+}
+
+/***   IRQ handlers   ***/
+
+/**
+ * ti_bandgap_talert_irq_handler() - handles Temperature alert IRQs
+ * @irq: IRQ number
+ * @data: private data (struct ti_bandgap *)
+ *
+ * This is the Talert handler. Use it only if bandgap device features
+ * HAS(TALERT). This handler goes over all sensors and checks their
+ * conditions and acts accordingly. In case there are events pending,
+ * it will reset the event mask to wait for the opposite event (next event).
+ * Every time there is a new event, it will be reported to thermal layer.
+ *
+ * Return: IRQ_HANDLED
+ */
+static irqreturn_t ti_bandgap_talert_irq_handler(int irq, void *data)
+{
+	struct ti_bandgap *bgp = data;
+	struct temp_sensor_registers *tsr;
+	u32 t_hot = 0, t_cold = 0, ctrl;
+	int i;
+
+	spin_lock(&bgp->lock);
+	for (i = 0; i < bgp->conf->sensor_count; i++) {
+		tsr = bgp->conf->sensors[i].registers;
+		ctrl = ti_bandgap_readl(bgp, tsr->bgap_status);
+
+		/* Read the status of t_hot */
+		t_hot = ctrl & tsr->status_hot_mask;
+
+		/* Read the status of t_cold */
+		t_cold = ctrl & tsr->status_cold_mask;
+
+		if (!t_cold && !t_hot)
+			continue;
+
+		ctrl = ti_bandgap_readl(bgp, tsr->bgap_mask_ctrl);
+		/*
+		 * One TALERT interrupt: Two sources
+		 * If the interrupt is due to t_hot then mask t_hot and
+		 * and unmask t_cold else mask t_cold and unmask t_hot
+		 */
+		if (t_hot) {
+			ctrl &= ~tsr->mask_hot_mask;
+			ctrl |= tsr->mask_cold_mask;
+		} else if (t_cold) {
+			ctrl &= ~tsr->mask_cold_mask;
+			ctrl |= tsr->mask_hot_mask;
+		}
+
+		ti_bandgap_writel(bgp, ctrl, tsr->bgap_mask_ctrl);
+
+		dev_dbg(bgp->dev,
+			"%s: IRQ from %s sensor: hotevent %d coldevent %d\n",
+			__func__, bgp->conf->sensors[i].domain,
+			t_hot, t_cold);
+
+		/* report temperature to whom may concern */
+		if (bgp->conf->report_temperature)
+			bgp->conf->report_temperature(bgp, i);
+	}
+	spin_unlock(&bgp->lock);
+
+	return IRQ_HANDLED;
+}
+
+/**
+ * ti_bandgap_tshut_irq_handler() - handles Temperature shutdown signal
+ * @irq: IRQ number
+ * @data: private data (unused)
+ *
+ * This is the Tshut handler. Use it only if bandgap device features
+ * HAS(TSHUT). If any sensor fires the Tshut signal, we simply shutdown
+ * the system.
+ *
+ * Return: IRQ_HANDLED
+ */
+static irqreturn_t ti_bandgap_tshut_irq_handler(int irq, void *data)
+{
+	pr_emerg("%s: TSHUT temperature reached. Needs shut down...\n",
+		 __func__);
+
+	orderly_poweroff(true);
+
+	return IRQ_HANDLED;
+}
+
+/***   Helper functions which manipulate conversion ADC <-> mi Celsius   ***/
+
+/**
+ * ti_bandgap_adc_to_mcelsius() - converts an ADC value to mCelsius scale
+ * @bgp: struct ti_bandgap pointer
+ * @adc_val: value in ADC representation
+ * @t: address where to write the resulting temperature in mCelsius
+ *
+ * Simple conversion from ADC representation to mCelsius. In case the ADC value
+ * is out of the ADC conv table range, it returns -ERANGE, 0 on success.
+ * The conversion table is indexed by the ADC values.
+ *
+ * Return: 0 if conversion was successful, else -ERANGE in case the @adc_val
+ * argument is out of the ADC conv table range.
+ */
+static
+int ti_bandgap_adc_to_mcelsius(struct ti_bandgap *bgp, int adc_val, int *t)
+{
+	const struct ti_bandgap_data *conf = bgp->conf;
+	int ret = 0;
+
+	/* look up for temperature in the table and return the temperature */
+	if (adc_val < conf->adc_start_val || adc_val > conf->adc_end_val) {
+		ret = -ERANGE;
+		goto exit;
+	}
+
+	*t = bgp->conf->conv_table[adc_val - conf->adc_start_val];
+
+exit:
+	return ret;
+}
+
+/**
+ * ti_bandgap_mcelsius_to_adc() - converts a mCelsius value to ADC scale
+ * @bgp: struct ti_bandgap pointer
+ * @temp: value in mCelsius
+ * @adc: address where to write the resulting temperature in ADC representation
+ *
+ * Simple conversion from mCelsius to ADC values. In case the temp value
+ * is out of the ADC conv table range, it returns -ERANGE, 0 on success.
+ * The conversion table is indexed by the ADC values.
+ *
+ * Return: 0 if conversion was successful, else -ERANGE in case the @temp
+ * argument is out of the ADC conv table range.
+ */
+static
+int ti_bandgap_mcelsius_to_adc(struct ti_bandgap *bgp, long temp, int *adc)
+{
+	const struct ti_bandgap_data *conf = bgp->conf;
+	const int *conv_table = bgp->conf->conv_table;
+	int high, low, mid, ret = 0;
+
+	low = 0;
+	high = conf->adc_end_val - conf->adc_start_val;
+	mid = (high + low) / 2;
+
+	if (temp < conv_table[low] || temp > conv_table[high]) {
+		ret = -ERANGE;
+		goto exit;
+	}
+
+	while (low < high) {
+		if (temp < conv_table[mid])
+			high = mid - 1;
+		else
+			low = mid + 1;
+		mid = (low + high) / 2;
+	}
+
+	*adc = conf->adc_start_val + low;
+
+exit:
+	return ret;
+}
+
+/**
+ * ti_bandgap_add_hyst() - add hysteresis (in mCelsius) to an ADC value
+ * @bgp: struct ti_bandgap pointer
+ * @adc_val: temperature value in ADC representation
+ * @hyst_val: hysteresis value in mCelsius
+ * @sum: address where to write the resulting temperature (in ADC scale)
+ *
+ * Adds an hysteresis value (in mCelsius) to a ADC temperature value.
+ *
+ * Return: 0 on success, -ERANGE otherwise.
+ */
+static
+int ti_bandgap_add_hyst(struct ti_bandgap *bgp, int adc_val, int hyst_val,
+			u32 *sum)
+{
+	int temp, ret;
+
+	/*
+	 * Need to add in the mcelsius domain, so we have a temperature
+	 * the conv_table range
+	 */
+	ret = ti_bandgap_adc_to_mcelsius(bgp, adc_val, &temp);
+	if (ret < 0)
+		goto exit;
+
+	temp += hyst_val;
+
+	ret = ti_bandgap_mcelsius_to_adc(bgp, temp, sum);
+
+exit:
+	return ret;
+}
+
+/***   Helper functions handling device Alert/Shutdown signals   ***/
+
+/**
+ * ti_bandgap_unmask_interrupts() - unmasks the events of thot & tcold
+ * @bgp: struct ti_bandgap pointer
+ * @id: bandgap sensor id
+ * @t_hot: hot temperature value to trigger alert signal
+ * @t_cold: cold temperature value to trigger alert signal
+ *
+ * Checks the requested t_hot and t_cold values and configures the IRQ event
+ * masks accordingly. Call this function only if bandgap features HAS(TALERT).
+ */
+static void ti_bandgap_unmask_interrupts(struct ti_bandgap *bgp, int id,
+					 u32 t_hot, u32 t_cold)
+{
+	struct temp_sensor_registers *tsr;
+	u32 temp, reg_val;
+
+	/* Read the current on die temperature */
+	temp = ti_bandgap_read_temp(bgp, id);
+
+	tsr = bgp->conf->sensors[id].registers;
+	reg_val = ti_bandgap_readl(bgp, tsr->bgap_mask_ctrl);
+
+	if (temp < t_hot)
+		reg_val |= tsr->mask_hot_mask;
+	else
+		reg_val &= ~tsr->mask_hot_mask;
+
+	if (t_cold < temp)
+		reg_val |= tsr->mask_cold_mask;
+	else
+		reg_val &= ~tsr->mask_cold_mask;
+	ti_bandgap_writel(bgp, reg_val, tsr->bgap_mask_ctrl);
+}
+
+/**
+ * ti_bandgap_update_alert_threshold() - sequence to update thresholds
+ * @bgp: struct ti_bandgap pointer
+ * @id: bandgap sensor id
+ * @val: value (ADC) of a new threshold
+ * @hot: desired threshold to be updated. true if threshold hot, false if
+ *       threshold cold
+ *
+ * It will program the required thresholds (hot and cold) for TALERT signal.
+ * This function can be used to update t_hot or t_cold, depending on @hot value.
+ * It checks the resulting t_hot and t_cold values, based on the new passed @val
+ * and configures the thresholds so that t_hot is always greater than t_cold.
+ * Call this function only if bandgap features HAS(TALERT).
+ *
+ * Return: 0 if no error, else corresponding error
+ */
+static int ti_bandgap_update_alert_threshold(struct ti_bandgap *bgp, int id,
+					     int val, bool hot)
+{
+	struct temp_sensor_data *ts_data = bgp->conf->sensors[id].ts_data;
+	struct temp_sensor_registers *tsr;
+	u32 thresh_val, reg_val, t_hot, t_cold;
+	int err = 0;
+
+	tsr = bgp->conf->sensors[id].registers;
+
+	/* obtain the current value */
+	thresh_val = ti_bandgap_readl(bgp, tsr->bgap_threshold);
+	t_cold = (thresh_val & tsr->threshold_tcold_mask) >>
+		__ffs(tsr->threshold_tcold_mask);
+	t_hot = (thresh_val & tsr->threshold_thot_mask) >>
+		__ffs(tsr->threshold_thot_mask);
+	if (hot)
+		t_hot = val;
+	else
+		t_cold = val;
+
+	if (t_cold > t_hot) {
+		if (hot)
+			err = ti_bandgap_add_hyst(bgp, t_hot,
+						  -ts_data->hyst_val,
+						  &t_cold);
+		else
+			err = ti_bandgap_add_hyst(bgp, t_cold,
+						  ts_data->hyst_val,
+						  &t_hot);
+	}
+
+	/* write the new threshold values */
+	reg_val = thresh_val &
+		  ~(tsr->threshold_thot_mask | tsr->threshold_tcold_mask);
+	reg_val |= (t_hot << __ffs(tsr->threshold_thot_mask)) |
+		   (t_cold << __ffs(tsr->threshold_tcold_mask));
+	ti_bandgap_writel(bgp, reg_val, tsr->bgap_threshold);
+
+	if (err) {
+		dev_err(bgp->dev, "failed to reprogram thot threshold\n");
+		err = -EIO;
+		goto exit;
+	}
+
+	ti_bandgap_unmask_interrupts(bgp, id, t_hot, t_cold);
+exit:
+	return err;
+}
+
+/**
+ * ti_bandgap_validate() - helper to check the sanity of a struct ti_bandgap
+ * @bgp: struct ti_bandgap pointer
+ * @id: bandgap sensor id
+ *
+ * Checks if the bandgap pointer is valid and if the sensor id is also
+ * applicable.
+ *
+ * Return: 0 if no errors, -EINVAL for invalid @bgp pointer or -ERANGE if
+ * @id cannot index @bgp sensors.
+ */
+static inline int ti_bandgap_validate(struct ti_bandgap *bgp, int id)
+{
+	int ret = 0;
+
+	if (IS_ERR_OR_NULL(bgp)) {
+		pr_err("%s: invalid bandgap pointer\n", __func__);
+		ret = -EINVAL;
+		goto exit;
+	}
+
+	if ((id < 0) || (id >= bgp->conf->sensor_count)) {
+		dev_err(bgp->dev, "%s: sensor id out of range (%d)\n",
+			__func__, id);
+		ret = -ERANGE;
+	}
+
+exit:
+	return ret;
+}
+
+/**
+ * _ti_bandgap_write_threshold() - helper to update TALERT t_cold or t_hot
+ * @bgp: struct ti_bandgap pointer
+ * @id: bandgap sensor id
+ * @val: value (mCelsius) of a new threshold
+ * @hot: desired threshold to be updated. true if threshold hot, false if
+ *       threshold cold
+ *
+ * It will update the required thresholds (hot and cold) for TALERT signal.
+ * This function can be used to update t_hot or t_cold, depending on @hot value.
+ * Validates the mCelsius range and update the requested threshold.
+ * Call this function only if bandgap features HAS(TALERT).
+ *
+ * Return: 0 if no error, else corresponding error value.
+ */
+static int _ti_bandgap_write_threshold(struct ti_bandgap *bgp, int id, int val,
+				       bool hot)
+{
+	struct temp_sensor_data *ts_data;
+	struct temp_sensor_registers *tsr;
+	u32 adc_val;
+	int ret;
+
+	ret = ti_bandgap_validate(bgp, id);
+	if (ret)
+		goto exit;
+
+	if (!TI_BANDGAP_HAS(bgp, TALERT)) {
+		ret = -ENOTSUPP;
+		goto exit;
+	}
+
+	ts_data = bgp->conf->sensors[id].ts_data;
+	tsr = bgp->conf->sensors[id].registers;
+	if (hot) {
+		if (val < ts_data->min_temp + ts_data->hyst_val)
+			ret = -EINVAL;
+	} else {
+		if (val > ts_data->max_temp + ts_data->hyst_val)
+			ret = -EINVAL;
+	}
+
+	if (ret)
+		goto exit;
+
+	ret = ti_bandgap_mcelsius_to_adc(bgp, val, &adc_val);
+	if (ret < 0)
+		goto exit;
+
+	spin_lock(&bgp->lock);
+	ret = ti_bandgap_update_alert_threshold(bgp, id, adc_val, hot);
+	spin_unlock(&bgp->lock);
+
+exit:
+	return ret;
+}
+
+/**
+ * _ti_bandgap_read_threshold() - helper to read TALERT t_cold or t_hot
+ * @bgp: struct ti_bandgap pointer
+ * @id: bandgap sensor id
+ * @val: value (mCelsius) of a threshold
+ * @hot: desired threshold to be read. true if threshold hot, false if
+ *       threshold cold
+ *
+ * It will fetch the required thresholds (hot and cold) for TALERT signal.
+ * This function can be used to read t_hot or t_cold, depending on @hot value.
+ * Call this function only if bandgap features HAS(TALERT).
+ *
+ * Return: 0 if no error, -ENOTSUPP if it has no TALERT support, or the
+ * corresponding error value if some operation fails.
+ */
+static int _ti_bandgap_read_threshold(struct ti_bandgap *bgp, int id,
+				      int *val, bool hot)
+{
+	struct temp_sensor_registers *tsr;
+	u32 temp, mask;
+	int ret = 0;
+
+	ret = ti_bandgap_validate(bgp, id);
+	if (ret)
+		goto exit;
+
+	if (!TI_BANDGAP_HAS(bgp, TALERT)) {
+		ret = -ENOTSUPP;
+		goto exit;
+	}
+
+	tsr = bgp->conf->sensors[id].registers;
+	if (hot)
+		mask = tsr->threshold_thot_mask;
+	else
+		mask = tsr->threshold_tcold_mask;
+
+	temp = ti_bandgap_readl(bgp, tsr->bgap_threshold);
+	temp = (temp & mask) >> __ffs(mask);
+	ret |= ti_bandgap_adc_to_mcelsius(bgp, temp, &temp);
+	if (ret) {
+		dev_err(bgp->dev, "failed to read thot\n");
+		ret = -EIO;
+		goto exit;
+	}
+
+	*val = temp;
+
+exit:
+	return ret;
+}
+
+/***   Exposed APIs   ***/
+
+/**
+ * ti_bandgap_read_thot() - reads sensor current thot
+ * @bgp: pointer to bandgap instance
+ * @id: sensor id
+ * @thot: resulting current thot value
+ *
+ * Return: 0 on success or the proper error code
+ */
+int ti_bandgap_read_thot(struct ti_bandgap *bgp, int id, int *thot)
+{
+	return _ti_bandgap_read_threshold(bgp, id, thot, true);
+}
+
+/**
+ * ti_bandgap_write_thot() - sets sensor current thot
+ * @bgp: pointer to bandgap instance
+ * @id: sensor id
+ * @val: desired thot value
+ *
+ * Return: 0 on success or the proper error code
+ */
+int ti_bandgap_write_thot(struct ti_bandgap *bgp, int id, int val)
+{
+	return _ti_bandgap_write_threshold(bgp, id, val, true);
+}
+
+/**
+ * ti_bandgap_read_tcold() - reads sensor current tcold
+ * @bgp: pointer to bandgap instance
+ * @id: sensor id
+ * @tcold: resulting current tcold value
+ *
+ * Return: 0 on success or the proper error code
+ */
+int ti_bandgap_read_tcold(struct ti_bandgap *bgp, int id, int *tcold)
+{
+	return _ti_bandgap_read_threshold(bgp, id, tcold, false);
+}
+
+/**
+ * ti_bandgap_write_tcold() - sets the sensor tcold
+ * @bgp: pointer to bandgap instance
+ * @id: sensor id
+ * @val: desired tcold value
+ *
+ * Return: 0 on success or the proper error code
+ */
+int ti_bandgap_write_tcold(struct ti_bandgap *bgp, int id, int val)
+{
+	return _ti_bandgap_write_threshold(bgp, id, val, false);
+}
+
+/**
+ * ti_bandgap_read_counter() - read the sensor counter
+ * @bgp: pointer to bandgap instance
+ * @id: sensor id
+ * @interval: resulting update interval in miliseconds
+ */
+static void ti_bandgap_read_counter(struct ti_bandgap *bgp, int id,
+				    int *interval)
+{
+	struct temp_sensor_registers *tsr;
+	int time;
+
+	tsr = bgp->conf->sensors[id].registers;
+	time = ti_bandgap_readl(bgp, tsr->bgap_counter);
+	time = (time & tsr->counter_mask) >>
+					__ffs(tsr->counter_mask);
+	time = time * 1000 / bgp->clk_rate;
+	*interval = time;
+}
+
+/**
+ * ti_bandgap_read_counter_delay() - read the sensor counter delay
+ * @bgp: pointer to bandgap instance
+ * @id: sensor id
+ * @interval: resulting update interval in miliseconds
+ */
+static void ti_bandgap_read_counter_delay(struct ti_bandgap *bgp, int id,
+					  int *interval)
+{
+	struct temp_sensor_registers *tsr;
+	int reg_val;
+
+	tsr = bgp->conf->sensors[id].registers;
+
+	reg_val = ti_bandgap_readl(bgp, tsr->bgap_mask_ctrl);
+	reg_val = (reg_val & tsr->mask_counter_delay_mask) >>
+				__ffs(tsr->mask_counter_delay_mask);
+	switch (reg_val) {
+	case 0:
+		*interval = 0;
+		break;
+	case 1:
+		*interval = 1;
+		break;
+	case 2:
+		*interval = 10;
+		break;
+	case 3:
+		*interval = 100;
+		break;
+	case 4:
+		*interval = 250;
+		break;
+	case 5:
+		*interval = 500;
+		break;
+	default:
+		dev_warn(bgp->dev, "Wrong counter delay value read from register %X",
+			 reg_val);
+	}
+}
+
+/**
+ * ti_bandgap_read_update_interval() - read the sensor update interval
+ * @bgp: pointer to bandgap instance
+ * @id: sensor id
+ * @interval: resulting update interval in miliseconds
+ *
+ * Return: 0 on success or the proper error code
+ */
+int ti_bandgap_read_update_interval(struct ti_bandgap *bgp, int id,
+				    int *interval)
+{
+	int ret = 0;
+
+	ret = ti_bandgap_validate(bgp, id);
+	if (ret)
+		goto exit;
+
+	if (!TI_BANDGAP_HAS(bgp, COUNTER) &&
+	    !TI_BANDGAP_HAS(bgp, COUNTER_DELAY)) {
+		ret = -ENOTSUPP;
+		goto exit;
+	}
+
+	if (TI_BANDGAP_HAS(bgp, COUNTER)) {
+		ti_bandgap_read_counter(bgp, id, interval);
+		goto exit;
+	}
+
+	ti_bandgap_read_counter_delay(bgp, id, interval);
+exit:
+	return ret;
+}
+
+/**
+ * ti_bandgap_write_counter_delay() - set the counter_delay
+ * @bgp: pointer to bandgap instance
+ * @id: sensor id
+ * @interval: desired update interval in miliseconds
+ *
+ * Return: 0 on success or the proper error code
+ */
+static int ti_bandgap_write_counter_delay(struct ti_bandgap *bgp, int id,
+					  u32 interval)
+{
+	int rval;
+
+	switch (interval) {
+	case 0: /* Immediate conversion */
+		rval = 0x0;
+		break;
+	case 1: /* Conversion after ever 1ms */
+		rval = 0x1;
+		break;
+	case 10: /* Conversion after ever 10ms */
+		rval = 0x2;
+		break;
+	case 100: /* Conversion after ever 100ms */
+		rval = 0x3;
+		break;
+	case 250: /* Conversion after ever 250ms */
+		rval = 0x4;
+		break;
+	case 500: /* Conversion after ever 500ms */
+		rval = 0x5;
+		break;
+	default:
+		dev_warn(bgp->dev, "Delay %d ms is not supported\n", interval);
+		return -EINVAL;
+	}
+
+	spin_lock(&bgp->lock);
+	RMW_BITS(bgp, id, bgap_mask_ctrl, mask_counter_delay_mask, rval);
+	spin_unlock(&bgp->lock);
+
+	return 0;
+}
+
+/**
+ * ti_bandgap_write_counter() - set the bandgap sensor counter
+ * @bgp: pointer to bandgap instance
+ * @id: sensor id
+ * @interval: desired update interval in miliseconds
+ */
+static void ti_bandgap_write_counter(struct ti_bandgap *bgp, int id,
+				     u32 interval)
+{
+	interval = interval * bgp->clk_rate / 1000;
+	spin_lock(&bgp->lock);
+	RMW_BITS(bgp, id, bgap_counter, counter_mask, interval);
+	spin_unlock(&bgp->lock);
+}
+
+/**
+ * ti_bandgap_write_update_interval() - set the update interval
+ * @bgp: pointer to bandgap instance
+ * @id: sensor id
+ * @interval: desired update interval in miliseconds
+ *
+ * Return: 0 on success or the proper error code
+ */
+int ti_bandgap_write_update_interval(struct ti_bandgap *bgp,
+				     int id, u32 interval)
+{
+	int ret = ti_bandgap_validate(bgp, id);
+	if (ret)
+		goto exit;
+
+	if (!TI_BANDGAP_HAS(bgp, COUNTER) &&
+	    !TI_BANDGAP_HAS(bgp, COUNTER_DELAY)) {
+		ret = -ENOTSUPP;
+		goto exit;
+	}
+
+	if (TI_BANDGAP_HAS(bgp, COUNTER)) {
+		ti_bandgap_write_counter(bgp, id, interval);
+		goto exit;
+	}
+
+	ret = ti_bandgap_write_counter_delay(bgp, id, interval);
+exit:
+	return ret;
+}
+
+/**
+ * ti_bandgap_read_temperature() - report current temperature
+ * @bgp: pointer to bandgap instance
+ * @id: sensor id
+ * @temperature: resulting temperature
+ *
+ * Return: 0 on success or the proper error code
+ */
+int ti_bandgap_read_temperature(struct ti_bandgap *bgp, int id,
+				int *temperature)
+{
+	u32 temp;
+	int ret;
+
+	ret = ti_bandgap_validate(bgp, id);
+	if (ret)
+		return ret;
+
+	spin_lock(&bgp->lock);
+	temp = ti_bandgap_read_temp(bgp, id);
+	spin_unlock(&bgp->lock);
+
+	ret |= ti_bandgap_adc_to_mcelsius(bgp, temp, &temp);
+	if (ret)
+		return -EIO;
+
+	*temperature = temp;
+
+	return 0;
+}
+
+/**
+ * ti_bandgap_set_sensor_data() - helper function to store thermal
+ * framework related data.
+ * @bgp: pointer to bandgap instance
+ * @id: sensor id
+ * @data: thermal framework related data to be stored
+ *
+ * Return: 0 on success or the proper error code
+ */
+int ti_bandgap_set_sensor_data(struct ti_bandgap *bgp, int id, void *data)
+{
+	int ret = ti_bandgap_validate(bgp, id);
+	if (ret)
+		return ret;
+
+	bgp->regval[id].data = data;
+
+	return 0;
+}
+
+/**
+ * ti_bandgap_get_sensor_data() - helper function to get thermal
+ * framework related data.
+ * @bgp: pointer to bandgap instance
+ * @id: sensor id
+ *
+ * Return: data stored by set function with sensor id on success or NULL
+ */
+void *ti_bandgap_get_sensor_data(struct ti_bandgap *bgp, int id)
+{
+	int ret = ti_bandgap_validate(bgp, id);
+	if (ret)
+		return ERR_PTR(ret);
+
+	return bgp->regval[id].data;
+}
+
+/***   Helper functions used during device initialization   ***/
+
+/**
+ * ti_bandgap_force_single_read() - executes 1 single ADC conversion
+ * @bgp: pointer to struct ti_bandgap
+ * @id: sensor id which it is desired to read 1 temperature
+ *
+ * Used to initialize the conversion state machine and set it to a valid
+ * state. Called during device initialization and context restore events.
+ *
+ * Return: 0
+ */
+static int
+ti_bandgap_force_single_read(struct ti_bandgap *bgp, int id)
+{
+	u32 temp = 0, counter = 1000;
+
+	/* Select single conversion mode */
+	if (TI_BANDGAP_HAS(bgp, MODE_CONFIG))
+		RMW_BITS(bgp, id, bgap_mode_ctrl, mode_ctrl_mask, 0);
+
+	/* Start of Conversion = 1 */
+	RMW_BITS(bgp, id, temp_sensor_ctrl, bgap_soc_mask, 1);
+	/* Wait until DTEMP is updated */
+	temp = ti_bandgap_read_temp(bgp, id);
+
+	while ((temp == 0) && --counter)
+		temp = ti_bandgap_read_temp(bgp, id);
+	/* REVISIT: Check correct condition for end of conversion */
+
+	/* Start of Conversion = 0 */
+	RMW_BITS(bgp, id, temp_sensor_ctrl, bgap_soc_mask, 0);
+
+	return 0;
+}
+
+/**
+ * ti_bandgap_set_continous_mode() - One time enabling of continuous mode
+ * @bgp: pointer to struct ti_bandgap
+ *
+ * Call this function only if HAS(MODE_CONFIG) is set. As this driver may
+ * be used for junction temperature monitoring, it is desirable that the
+ * sensors are operational all the time, so that alerts are generated
+ * properly.
+ *
+ * Return: 0
+ */
+static int ti_bandgap_set_continuous_mode(struct ti_bandgap *bgp)
+{
+	int i;
+
+	for (i = 0; i < bgp->conf->sensor_count; i++) {
+		/* Perform a single read just before enabling continuous */
+		ti_bandgap_force_single_read(bgp, i);
+		RMW_BITS(bgp, i, bgap_mode_ctrl, mode_ctrl_mask, 1);
+	}
+
+	return 0;
+}
+
+/**
+ * ti_bandgap_get_trend() - To fetch the temperature trend of a sensor
+ * @bgp: pointer to struct ti_bandgap
+ * @id: id of the individual sensor
+ * @trend: Pointer to trend.
+ *
+ * This function needs to be called to fetch the temperature trend of a
+ * Particular sensor. The function computes the difference in temperature
+ * w.r.t time. For the bandgaps with built in history buffer the temperatures
+ * are read from the buffer and for those without the Buffer -ENOTSUPP is
+ * returned.
+ *
+ * Return: 0 if no error, else return corresponding error. If no
+ *		error then the trend value is passed on to trend parameter
+ */
+int ti_bandgap_get_trend(struct ti_bandgap *bgp, int id, int *trend)
+{
+	struct temp_sensor_registers *tsr;
+	u32 temp1, temp2, reg1, reg2;
+	int t1, t2, interval, ret = 0;
+
+	ret = ti_bandgap_validate(bgp, id);
+	if (ret)
+		goto exit;
+
+	if (!TI_BANDGAP_HAS(bgp, HISTORY_BUFFER) ||
+	    !TI_BANDGAP_HAS(bgp, FREEZE_BIT)) {
+		ret = -ENOTSUPP;
+		goto exit;
+	}
+
+	tsr = bgp->conf->sensors[id].registers;
+
+	/* Freeze and read the last 2 valid readings */
+	reg1 = tsr->ctrl_dtemp_1;
+	reg2 = tsr->ctrl_dtemp_2;
+
+	/* read temperature from history buffer */
+	temp1 = ti_bandgap_readl(bgp, reg1);
+	temp1 &= tsr->bgap_dtemp_mask;
+
+	temp2 = ti_bandgap_readl(bgp, reg2);
+	temp2 &= tsr->bgap_dtemp_mask;
+
+	/* Convert from adc values to mCelsius temperature */
+	ret = ti_bandgap_adc_to_mcelsius(bgp, temp1, &t1);
+	if (ret)
+		goto exit;
+
+	ret = ti_bandgap_adc_to_mcelsius(bgp, temp2, &t2);
+	if (ret)
+		goto exit;
+
+	/* Fetch the update interval */
+	ret = ti_bandgap_read_update_interval(bgp, id, &interval);
+	if (ret || !interval)
+		goto exit;
+
+	*trend = (t1 - t2) / interval;
+
+	dev_dbg(bgp->dev, "The temperatures are t1 = %d and t2 = %d and trend =%d\n",
+		t1, t2, *trend);
+
+exit:
+	return ret;
+}
+
+/**
+ * ti_bandgap_tshut_init() - setup and initialize tshut handling
+ * @bgp: pointer to struct ti_bandgap
+ * @pdev: pointer to device struct platform_device
+ *
+ * Call this function only in case the bandgap features HAS(TSHUT).
+ * In this case, the driver needs to handle the TSHUT signal as an IRQ.
+ * The IRQ is wired as a GPIO, and for this purpose, it is required
+ * to specify which GPIO line is used. TSHUT IRQ is fired anytime
+ * one of the bandgap sensors violates the TSHUT high/hot threshold.
+ * And in that case, the system must go off.
+ *
+ * Return: 0 if no error, else error status
+ */
+static int ti_bandgap_tshut_init(struct ti_bandgap *bgp,
+				 struct platform_device *pdev)
+{
+	int gpio_nr = bgp->tshut_gpio;
+	int status;
+
+	/* Request for gpio_86 line */
+	status = gpio_request(gpio_nr, "tshut");
+	if (status < 0) {
+		dev_err(bgp->dev, "Could not request for TSHUT GPIO:%i\n", 86);
+		return status;
+	}
+	status = gpio_direction_input(gpio_nr);
+	if (status) {
+		dev_err(bgp->dev, "Cannot set input TSHUT GPIO %d\n", gpio_nr);
+		return status;
+	}
+
+	status = request_irq(gpio_to_irq(gpio_nr), ti_bandgap_tshut_irq_handler,
+			     IRQF_TRIGGER_RISING, "tshut", NULL);
+	if (status) {
+		gpio_free(gpio_nr);
+		dev_err(bgp->dev, "request irq failed for TSHUT");
+	}
+
+	return 0;
+}
+
+/**
+ * ti_bandgap_alert_init() - setup and initialize talert handling
+ * @bgp: pointer to struct ti_bandgap
+ * @pdev: pointer to device struct platform_device
+ *
+ * Call this function only in case the bandgap features HAS(TALERT).
+ * In this case, the driver needs to handle the TALERT signals as an IRQs.
+ * TALERT is a normal IRQ and it is fired any time thresholds (hot or cold)
+ * are violated. In these situation, the driver must reprogram the thresholds,
+ * accordingly to specified policy.
+ *
+ * Return: 0 if no error, else return corresponding error.
+ */
+static int ti_bandgap_talert_init(struct ti_bandgap *bgp,
+				  struct platform_device *pdev)
+{
+	int ret;
+
+	bgp->irq = platform_get_irq(pdev, 0);
+	if (bgp->irq < 0) {
+		dev_err(&pdev->dev, "get_irq failed\n");
+		return bgp->irq;
+	}
+	ret = request_threaded_irq(bgp->irq, NULL,
+				   ti_bandgap_talert_irq_handler,
+				   IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+				   "talert", bgp);
+	if (ret) {
+		dev_err(&pdev->dev, "Request threaded irq failed.\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static const struct of_device_id of_ti_bandgap_match[];
+/**
+ * ti_bandgap_build() - parse DT and setup a struct ti_bandgap
+ * @pdev: pointer to device struct platform_device
+ *
+ * Used to read the device tree properties accordingly to the bandgap
+ * matching version. Based on bandgap version and its capabilities it
+ * will build a struct ti_bandgap out of the required DT entries.
+ *
+ * Return: valid bandgap structure if successful, else returns ERR_PTR
+ * return value must be verified with IS_ERR.
+ */
+static struct ti_bandgap *ti_bandgap_build(struct platform_device *pdev)
+{
+	struct device_node *node = pdev->dev.of_node;
+	const struct of_device_id *of_id;
+	struct ti_bandgap *bgp;
+	struct resource *res;
+	u32 prop;
+	int i;
+
+	/* just for the sake */
+	if (!node) {
+		dev_err(&pdev->dev, "no platform information available\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	bgp = devm_kzalloc(&pdev->dev, sizeof(*bgp), GFP_KERNEL);
+	if (!bgp) {
+		dev_err(&pdev->dev, "Unable to allocate mem for driver ref\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	of_id = of_match_device(of_ti_bandgap_match, &pdev->dev);
+	if (of_id)
+		bgp->conf = of_id->data;
+
+	/* register shadow for context save and restore */
+	bgp->regval = devm_kzalloc(&pdev->dev, sizeof(*bgp->regval) *
+				   bgp->conf->sensor_count, GFP_KERNEL);
+	if (!bgp) {
+		dev_err(&pdev->dev, "Unable to allocate mem for driver ref\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	i = 0;
+	do {
+		void __iomem *chunk;
+
+		res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+		if (!res)
+			break;
+		chunk = devm_ioremap_resource(&pdev->dev, res);
+		if (i == 0)
+			bgp->base = chunk;
+		if (IS_ERR(chunk))
+			return ERR_CAST(chunk);
+
+		i++;
+	} while (res);
+
+	if (TI_BANDGAP_HAS(bgp, TSHUT)) {
+		if (of_property_read_u32(node, "ti,tshut-gpio", &prop) < 0) {
+			dev_err(&pdev->dev, "missing tshut gpio in device tree\n");
+			return ERR_PTR(-EINVAL);
+		}
+		bgp->tshut_gpio = prop;
+		if (!gpio_is_valid(bgp->tshut_gpio)) {
+			dev_err(&pdev->dev, "invalid gpio for tshut (%d)\n",
+				bgp->tshut_gpio);
+			return ERR_PTR(-EINVAL);
+		}
+	}
+
+	return bgp;
+}
+
+/***   Device driver call backs   ***/
+
+static
+int ti_bandgap_probe(struct platform_device *pdev)
+{
+	struct ti_bandgap *bgp;
+	int clk_rate, ret = 0, i;
+
+	bgp = ti_bandgap_build(pdev);
+	if (IS_ERR_OR_NULL(bgp)) {
+		dev_err(&pdev->dev, "failed to fetch platform data\n");
+		return PTR_ERR(bgp);
+	}
+	bgp->dev = &pdev->dev;
+
+	if (TI_BANDGAP_HAS(bgp, TSHUT)) {
+		ret = ti_bandgap_tshut_init(bgp, pdev);
+		if (ret) {
+			dev_err(&pdev->dev,
+				"failed to initialize system tshut IRQ\n");
+			return ret;
+		}
+	}
+
+	bgp->fclock = clk_get(NULL, bgp->conf->fclock_name);
+	ret = IS_ERR_OR_NULL(bgp->fclock);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to request fclock reference\n");
+		goto free_irqs;
+	}
+
+	bgp->div_clk = clk_get(NULL,  bgp->conf->div_ck_name);
+	ret = IS_ERR_OR_NULL(bgp->div_clk);
+	if (ret) {
+		dev_err(&pdev->dev,
+			"failed to request div_ts_ck clock ref\n");
+		goto free_irqs;
+	}
+
+	for (i = 0; i < bgp->conf->sensor_count; i++) {
+		struct temp_sensor_registers *tsr;
+		u32 val;
+
+		tsr = bgp->conf->sensors[i].registers;
+		/*
+		 * check if the efuse has a non-zero value if not
+		 * it is an untrimmed sample and the temperatures
+		 * may not be accurate
+		 */
+		val = ti_bandgap_readl(bgp, tsr->bgap_efuse);
+		if (ret || !val)
+			dev_info(&pdev->dev,
+				 "Non-trimmed BGAP, Temp not accurate\n");
+	}
+
+	clk_rate = clk_round_rate(bgp->div_clk,
+				  bgp->conf->sensors[0].ts_data->max_freq);
+	if (clk_rate < bgp->conf->sensors[0].ts_data->min_freq ||
+	    clk_rate == 0xffffffff) {
+		ret = -ENODEV;
+		dev_err(&pdev->dev, "wrong clock rate (%d)\n", clk_rate);
+		goto put_clks;
+	}
+
+	ret = clk_set_rate(bgp->div_clk, clk_rate);
+	if (ret)
+		dev_err(&pdev->dev, "Cannot re-set clock rate. Continuing\n");
+
+	bgp->clk_rate = clk_rate;
+	if (TI_BANDGAP_HAS(bgp, CLK_CTRL))
+		clk_prepare_enable(bgp->fclock);
+
+
+	spin_lock_init(&bgp->lock);
+	bgp->dev = &pdev->dev;
+	platform_set_drvdata(pdev, bgp);
+
+	ti_bandgap_power(bgp, true);
+
+	/* Set default counter to 1 for now */
+	if (TI_BANDGAP_HAS(bgp, COUNTER))
+		for (i = 0; i < bgp->conf->sensor_count; i++)
+			RMW_BITS(bgp, i, bgap_counter, counter_mask, 1);
+
+	/* Set default thresholds for alert and shutdown */
+	for (i = 0; i < bgp->conf->sensor_count; i++) {
+		struct temp_sensor_data *ts_data;
+
+		ts_data = bgp->conf->sensors[i].ts_data;
+
+		if (TI_BANDGAP_HAS(bgp, TALERT)) {
+			/* Set initial Talert thresholds */
+			RMW_BITS(bgp, i, bgap_threshold,
+				 threshold_tcold_mask, ts_data->t_cold);
+			RMW_BITS(bgp, i, bgap_threshold,
+				 threshold_thot_mask, ts_data->t_hot);
+			/* Enable the alert events */
+			RMW_BITS(bgp, i, bgap_mask_ctrl, mask_hot_mask, 1);
+			RMW_BITS(bgp, i, bgap_mask_ctrl, mask_cold_mask, 1);
+		}
+
+		if (TI_BANDGAP_HAS(bgp, TSHUT_CONFIG)) {
+			/* Set initial Tshut thresholds */
+			RMW_BITS(bgp, i, tshut_threshold,
+				 tshut_hot_mask, ts_data->tshut_hot);
+			RMW_BITS(bgp, i, tshut_threshold,
+				 tshut_cold_mask, ts_data->tshut_cold);
+		}
+	}
+
+	if (TI_BANDGAP_HAS(bgp, MODE_CONFIG))
+		ti_bandgap_set_continuous_mode(bgp);
+
+	/* Set .250 seconds time as default counter */
+	if (TI_BANDGAP_HAS(bgp, COUNTER))
+		for (i = 0; i < bgp->conf->sensor_count; i++)
+			RMW_BITS(bgp, i, bgap_counter, counter_mask,
+				 bgp->clk_rate / 4);
+
+	/* Every thing is good? Then expose the sensors */
+	for (i = 0; i < bgp->conf->sensor_count; i++) {
+		char *domain;
+
+		if (bgp->conf->sensors[i].register_cooling)
+			bgp->conf->sensors[i].register_cooling(bgp, i);
+
+		domain = bgp->conf->sensors[i].domain;
+		if (bgp->conf->expose_sensor)
+			bgp->conf->expose_sensor(bgp, i, domain);
+	}
+
+	/*
+	 * Enable the Interrupts once everything is set. Otherwise irq handler
+	 * might be called as soon as it is enabled where as rest of framework
+	 * is still getting initialised.
+	 */
+	if (TI_BANDGAP_HAS(bgp, TALERT)) {
+		ret = ti_bandgap_talert_init(bgp, pdev);
+		if (ret) {
+			dev_err(&pdev->dev, "failed to initialize Talert IRQ\n");
+			i = bgp->conf->sensor_count;
+			goto disable_clk;
+		}
+	}
+
+	return 0;
+
+disable_clk:
+	if (TI_BANDGAP_HAS(bgp, CLK_CTRL))
+		clk_disable_unprepare(bgp->fclock);
+put_clks:
+	clk_put(bgp->fclock);
+	clk_put(bgp->div_clk);
+free_irqs:
+	if (TI_BANDGAP_HAS(bgp, TSHUT)) {
+		free_irq(gpio_to_irq(bgp->tshut_gpio), NULL);
+		gpio_free(bgp->tshut_gpio);
+	}
+
+	return ret;
+}
+
+static
+int ti_bandgap_remove(struct platform_device *pdev)
+{
+	struct ti_bandgap *bgp = platform_get_drvdata(pdev);
+	int i;
+
+	/* First thing is to remove sensor interfaces */
+	for (i = 0; i < bgp->conf->sensor_count; i++) {
+		if (bgp->conf->sensors[i].register_cooling)
+			bgp->conf->sensors[i].unregister_cooling(bgp, i);
+
+		if (bgp->conf->remove_sensor)
+			bgp->conf->remove_sensor(bgp, i);
+	}
+
+	ti_bandgap_power(bgp, false);
+
+	if (TI_BANDGAP_HAS(bgp, CLK_CTRL))
+		clk_disable_unprepare(bgp->fclock);
+	clk_put(bgp->fclock);
+	clk_put(bgp->div_clk);
+
+	if (TI_BANDGAP_HAS(bgp, TALERT))
+		free_irq(bgp->irq, bgp);
+
+	if (TI_BANDGAP_HAS(bgp, TSHUT)) {
+		free_irq(gpio_to_irq(bgp->tshut_gpio), NULL);
+		gpio_free(bgp->tshut_gpio);
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int ti_bandgap_save_ctxt(struct ti_bandgap *bgp)
+{
+	int i;
+
+	for (i = 0; i < bgp->conf->sensor_count; i++) {
+		struct temp_sensor_registers *tsr;
+		struct temp_sensor_regval *rval;
+
+		rval = &bgp->regval[i];
+		tsr = bgp->conf->sensors[i].registers;
+
+		if (TI_BANDGAP_HAS(bgp, MODE_CONFIG))
+			rval->bg_mode_ctrl = ti_bandgap_readl(bgp,
+							tsr->bgap_mode_ctrl);
+		if (TI_BANDGAP_HAS(bgp, COUNTER))
+			rval->bg_counter = ti_bandgap_readl(bgp,
+							tsr->bgap_counter);
+		if (TI_BANDGAP_HAS(bgp, TALERT)) {
+			rval->bg_threshold = ti_bandgap_readl(bgp,
+							tsr->bgap_threshold);
+			rval->bg_ctrl = ti_bandgap_readl(bgp,
+						   tsr->bgap_mask_ctrl);
+		}
+
+		if (TI_BANDGAP_HAS(bgp, TSHUT_CONFIG))
+			rval->tshut_threshold = ti_bandgap_readl(bgp,
+						   tsr->tshut_threshold);
+	}
+
+	return 0;
+}
+
+static int ti_bandgap_restore_ctxt(struct ti_bandgap *bgp)
+{
+	int i;
+
+	for (i = 0; i < bgp->conf->sensor_count; i++) {
+		struct temp_sensor_registers *tsr;
+		struct temp_sensor_regval *rval;
+		u32 val = 0;
+
+		rval = &bgp->regval[i];
+		tsr = bgp->conf->sensors[i].registers;
+
+		if (TI_BANDGAP_HAS(bgp, COUNTER))
+			val = ti_bandgap_readl(bgp, tsr->bgap_counter);
+
+		if (TI_BANDGAP_HAS(bgp, TSHUT_CONFIG))
+			ti_bandgap_writel(bgp, rval->tshut_threshold,
+					  tsr->tshut_threshold);
+		/* Force immediate temperature measurement and update
+		 * of the DTEMP field
+		 */
+		ti_bandgap_force_single_read(bgp, i);
+
+		if (TI_BANDGAP_HAS(bgp, COUNTER))
+			ti_bandgap_writel(bgp, rval->bg_counter,
+					  tsr->bgap_counter);
+		if (TI_BANDGAP_HAS(bgp, MODE_CONFIG))
+			ti_bandgap_writel(bgp, rval->bg_mode_ctrl,
+					  tsr->bgap_mode_ctrl);
+		if (TI_BANDGAP_HAS(bgp, TALERT)) {
+			ti_bandgap_writel(bgp, rval->bg_threshold,
+					  tsr->bgap_threshold);
+			ti_bandgap_writel(bgp, rval->bg_ctrl,
+					  tsr->bgap_mask_ctrl);
+		}
+	}
+
+	return 0;
+}
+
+static int ti_bandgap_suspend(struct device *dev)
+{
+	struct ti_bandgap *bgp = dev_get_drvdata(dev);
+	int err;
+
+	err = ti_bandgap_save_ctxt(bgp);
+	ti_bandgap_power(bgp, false);
+
+	if (TI_BANDGAP_HAS(bgp, CLK_CTRL))
+		clk_disable_unprepare(bgp->fclock);
+
+	return err;
+}
+
+static int ti_bandgap_resume(struct device *dev)
+{
+	struct ti_bandgap *bgp = dev_get_drvdata(dev);
+
+	if (TI_BANDGAP_HAS(bgp, CLK_CTRL))
+		clk_prepare_enable(bgp->fclock);
+
+	ti_bandgap_power(bgp, true);
+
+	return ti_bandgap_restore_ctxt(bgp);
+}
+static const struct dev_pm_ops ti_bandgap_dev_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(ti_bandgap_suspend,
+				ti_bandgap_resume)
+};
+
+#define DEV_PM_OPS	(&ti_bandgap_dev_pm_ops)
+#else
+#define DEV_PM_OPS	NULL
+#endif
+
+static const struct of_device_id of_ti_bandgap_match[] = {
+#ifdef CONFIG_OMAP4_THERMAL
+	{
+		.compatible = "ti,omap4430-bandgap",
+		.data = (void *)&omap4430_data,
+	},
+	{
+		.compatible = "ti,omap4460-bandgap",
+		.data = (void *)&omap4460_data,
+	},
+	{
+		.compatible = "ti,omap4470-bandgap",
+		.data = (void *)&omap4470_data,
+	},
+#endif
+#ifdef CONFIG_OMAP5_THERMAL
+	{
+		.compatible = "ti,omap5430-bandgap",
+		.data = (void *)&omap5430_data,
+	},
+#endif
+	/* Sentinel */
+	{ },
+};
+MODULE_DEVICE_TABLE(of, of_ti_bandgap_match);
+
+static struct platform_driver ti_bandgap_sensor_driver = {
+	.probe = ti_bandgap_probe,
+	.remove = ti_bandgap_remove,
+	.driver = {
+			.name = "ti-soc-thermal",
+			.pm = DEV_PM_OPS,
+			.of_match_table	= of_ti_bandgap_match,
+	},
+};
+
+module_platform_driver(ti_bandgap_sensor_driver);
+
+MODULE_DESCRIPTION("OMAP4+ bandgap temperature sensor driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:ti-soc-thermal");
+MODULE_AUTHOR("Texas Instrument Inc.");
diff --git a/drivers/staging/ti-soc-thermal/ti-bandgap.h b/drivers/staging/ti-soc-thermal/ti-bandgap.h
new file mode 100644
index 0000000..5f4794a
--- /dev/null
+++ b/drivers/staging/ti-soc-thermal/ti-bandgap.h
@@ -0,0 +1,403 @@
+/*
+ * OMAP4 Bandgap temperature sensor driver
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ * Contact:
+ *   Eduardo Valentin <eduardo.valentin@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 __TI_BANDGAP_H
+#define __TI_BANDGAP_H
+
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <linux/err.h>
+
+/**
+ * DOC: bandgap driver data structure
+ * ==================================
+ *
+ *   +----------+----------------+
+ *   | struct temp_sensor_regval |
+ *   +---------------------------+
+ *              * (Array of)
+ *              |
+ *              |
+ *   +-------------------+   +-----------------+
+ *   | struct ti_bandgap |-->| struct device * |
+ *   +----------+--------+   +-----------------+
+ *              |
+ *              |
+ *              V
+ *   +------------------------+
+ *   | struct ti_bandgap_data |
+ *   +------------------------+
+ *              |
+ *              |
+ *              * (Array of)
+ * +------------+------------------------------------------------------+
+ * | +----------+------------+   +-------------------------+           |
+ * | | struct ti_temp_sensor |-->| struct temp_sensor_data |           |
+ * | +-----------------------+   +------------+------------+           |
+ * |            |                                                      |
+ * |            +                                                      |
+ * |            V                                                      |
+ * | +----------+-------------------+                                  |
+ * | | struct temp_sensor_registers |                                  |
+ * | +------------------------------+                                  |
+ * |                                                                   |
+ * +-------------------------------------------------------------------+
+ *
+ * Above is a simple diagram describing how the data structure below
+ * are organized. For each bandgap device there should be a ti_bandgap_data
+ * containing the device instance configuration, as well as, an array of
+ * sensors, representing every sensor instance present in this bandgap.
+ */
+
+/**
+ * struct temp_sensor_registers - descriptor to access registers and bitfields
+ * @temp_sensor_ctrl: TEMP_SENSOR_CTRL register offset
+ * @bgap_tempsoff_mask: mask to temp_sensor_ctrl.tempsoff
+ * @bgap_soc_mask: mask to temp_sensor_ctrl.soc
+ * @bgap_eocz_mask: mask to temp_sensor_ctrl.eocz
+ * @bgap_dtemp_mask: mask to temp_sensor_ctrl.dtemp
+ * @bgap_mask_ctrl: BANDGAP_MASK_CTRL register offset
+ * @mask_hot_mask: mask to bandgap_mask_ctrl.mask_hot
+ * @mask_cold_mask: mask to bandgap_mask_ctrl.mask_cold
+ * @mask_sidlemode_mask: mask to bandgap_mask_ctrl.mask_sidlemode
+ * @mask_counter_delay_mask: mask to bandgap_mask_ctrl.mask_counter_delay
+ * @mask_freeze_mask: mask to bandgap_mask_ctrl.mask_free
+ * @mask_clear_mask: mask to bandgap_mask_ctrl.mask_clear
+ * @mask_clear_accum_mask: mask to bandgap_mask_ctrl.mask_clear_accum
+ * @bgap_mode_ctrl: BANDGAP_MODE_CTRL register offset
+ * @mode_ctrl_mask: mask to bandgap_mode_ctrl.mode_ctrl
+ * @bgap_counter: BANDGAP_COUNTER register offset
+ * @counter_mask: mask to bandgap_counter.counter
+ * @bgap_threshold: BANDGAP_THRESHOLD register offset (TALERT thresholds)
+ * @threshold_thot_mask: mask to bandgap_threhold.thot
+ * @threshold_tcold_mask: mask to bandgap_threhold.tcold
+ * @tshut_threshold: TSHUT_THRESHOLD register offset (TSHUT thresholds)
+ * @tshut_efuse_mask: mask to tshut_threshold.tshut_efuse
+ * @tshut_efuse_shift: shift to tshut_threshold.tshut_efuse
+ * @tshut_hot_mask: mask to tshut_threhold.thot
+ * @tshut_cold_mask: mask to tshut_threhold.thot
+ * @bgap_status: BANDGAP_STATUS register offset
+ * @status_clean_stop_mask: mask to bandgap_status.clean_stop
+ * @status_bgap_alert_mask: mask to bandgap_status.bandgap_alert
+ * @status_hot_mask: mask to bandgap_status.hot
+ * @status_cold_mask: mask to bandgap_status.cold
+ * @bgap_cumul_dtemp: BANDGAP_CUMUL_DTEMP register offset
+ * @ctrl_dtemp_0: CTRL_DTEMP0 register offset
+ * @ctrl_dtemp_1: CTRL_DTEMP1 register offset
+ * @ctrl_dtemp_2: CTRL_DTEMP2 register offset
+ * @ctrl_dtemp_3: CTRL_DTEMP3 register offset
+ * @ctrl_dtemp_4: CTRL_DTEMP4 register offset
+ * @bgap_efuse: BANDGAP_EFUSE register offset
+ *
+ * The register offsets and bitfields might change across
+ * OMAP and variants versions. Hence this struct serves as a
+ * descriptor map on how to access the registers and the bitfields.
+ *
+ * This descriptor contains registers of all versions of bandgap chips.
+ * Not all versions will use all registers, depending on the available
+ * features. Please read TRMs for descriptive explanation on each bitfield.
+ */
+
+struct temp_sensor_registers {
+	u32	temp_sensor_ctrl;
+	u32	bgap_tempsoff_mask;
+	u32	bgap_soc_mask;
+	u32	bgap_eocz_mask; /* not used: but needs revisit */
+	u32	bgap_dtemp_mask;
+
+	u32	bgap_mask_ctrl;
+	u32	mask_hot_mask;
+	u32	mask_cold_mask;
+	u32	mask_sidlemode_mask; /* not used: but may be needed for pm */
+	u32	mask_counter_delay_mask;
+	u32	mask_freeze_mask;
+	u32	mask_clear_mask; /* not used: but needed for trending */
+	u32	mask_clear_accum_mask; /* not used: but needed for trending */
+
+	u32	bgap_mode_ctrl;
+	u32	mode_ctrl_mask;
+
+	u32	bgap_counter;
+	u32	counter_mask;
+
+	u32	bgap_threshold;
+	u32	threshold_thot_mask;
+	u32	threshold_tcold_mask;
+
+	u32	tshut_threshold;
+	u32	tshut_efuse_mask; /* not used */
+	u32	tshut_efuse_shift; /* not used */
+	u32	tshut_hot_mask;
+	u32	tshut_cold_mask;
+
+	u32	bgap_status;
+	u32	status_clean_stop_mask; /* not used: but needed for trending */
+	u32	status_bgap_alert_mask; /* not used */
+	u32	status_hot_mask;
+	u32	status_cold_mask;
+
+	u32	bgap_cumul_dtemp; /* not used: but needed for trending */
+	u32	ctrl_dtemp_0; /* not used: but needed for trending */
+	u32	ctrl_dtemp_1; /* not used: but needed for trending */
+	u32	ctrl_dtemp_2; /* not used: but needed for trending */
+	u32	ctrl_dtemp_3; /* not used: but needed for trending */
+	u32	ctrl_dtemp_4; /* not used: but needed for trending */
+	u32	bgap_efuse;
+};
+
+/**
+ * struct temp_sensor_data - The thresholds and limits for temperature sensors.
+ * @tshut_hot: temperature to trigger a thermal reset (initial value)
+ * @tshut_cold: temp to get the plat out of reset due to thermal (init val)
+ * @t_hot: temperature to trigger a thermal alert (high initial value)
+ * @t_cold: temperature to trigger a thermal alert (low initial value)
+ * @min_freq: sensor minimum clock rate
+ * @max_freq: sensor maximum clock rate
+ * @max_temp: sensor maximum temperature
+ * @min_temp: sensor minimum temperature
+ * @hyst_val: temperature hysteresis considered while converting ADC values
+ * @update_int1: update interval
+ * @update_int2: update interval
+ *
+ * This data structure will hold the required thresholds and temperature limits
+ * for a specific temperature sensor, like shutdown temperature, alert
+ * temperature, clock / rate used, ADC conversion limits and update intervals
+ */
+struct temp_sensor_data {
+	u32	tshut_hot;
+	u32	tshut_cold;
+	u32	t_hot;
+	u32	t_cold;
+	u32	min_freq;
+	u32	max_freq;
+	int     max_temp;
+	int     min_temp;
+	int     hyst_val;
+	u32     update_int1; /* not used */
+	u32     update_int2; /* not used */
+};
+
+struct ti_bandgap_data;
+
+/**
+ * struct temp_sensor_regval - temperature sensor register values and priv data
+ * @bg_mode_ctrl: temp sensor control register value
+ * @bg_ctrl: bandgap ctrl register value
+ * @bg_counter: bandgap counter value
+ * @bg_threshold: bandgap threshold register value
+ * @tshut_threshold: bandgap tshut register value
+ * @data: private data
+ *
+ * Data structure to save and restore bandgap register set context. Only
+ * required registers are shadowed, when needed.
+ */
+struct temp_sensor_regval {
+	u32			bg_mode_ctrl;
+	u32			bg_ctrl;
+	u32			bg_counter;
+	u32			bg_threshold;
+	u32			tshut_threshold;
+	void			*data;
+};
+
+/**
+ * struct ti_bandgap - bandgap device structure
+ * @dev: struct device pointer
+ * @base: io memory base address
+ * @conf: struct with bandgap configuration set (# sensors, conv_table, etc)
+ * @regval: temperature sensor register values
+ * @fclock: pointer to functional clock of temperature sensor
+ * @div_clk: pointer to divider clock of temperature sensor fclk
+ * @lock: spinlock for ti_bandgap structure
+ * @irq: MPU IRQ number for thermal alert
+ * @tshut_gpio: GPIO where Tshut signal is routed
+ * @clk_rate: Holds current clock rate
+ *
+ * The bandgap device structure representing the bandgap device instance.
+ * It holds most of the dynamic stuff. Configurations and sensor specific
+ * entries are inside the @conf structure.
+ */
+struct ti_bandgap {
+	struct device			*dev;
+	void __iomem			*base;
+	const struct ti_bandgap_data	*conf;
+	struct temp_sensor_regval	*regval;
+	struct clk			*fclock;
+	struct clk			*div_clk;
+	spinlock_t			lock; /* shields this struct */
+	int				irq;
+	int				tshut_gpio;
+	u32				clk_rate;
+};
+
+/**
+ * struct ti_temp_sensor - bandgap temperature sensor configuration data
+ * @ts_data: pointer to struct with thresholds, limits of temperature sensor
+ * @registers: pointer to the list of register offsets and bitfields
+ * @domain: the name of the domain where the sensor is located
+ * @slope: sensor gradient slope info for hotspot extrapolation equation
+ * @constant: sensor gradient const info for hotspot extrapolation equation
+ * @slope_pcb: sensor gradient slope info for hotspot extrapolation equation
+ *             with no external influence
+ * @constant_pcb: sensor gradient const info for hotspot extrapolation equation
+ *             with no external influence
+ * @register_cooling: function to describe how this sensor is going to be cooled
+ * @unregister_cooling: function to release cooling data
+ *
+ * Data structure to describe a temperature sensor handled by a bandgap device.
+ * It should provide configuration details on this sensor, such as how to
+ * access the registers affecting this sensor, shadow register buffer, how to
+ * assess the gradient from hotspot, how to cooldown the domain when sensor
+ * reports too hot temperature.
+ */
+struct ti_temp_sensor {
+	struct temp_sensor_data		*ts_data;
+	struct temp_sensor_registers	*registers;
+	char				*domain;
+	/* for hotspot extrapolation */
+	const int			slope;
+	const int			constant;
+	const int			slope_pcb;
+	const int			constant_pcb;
+	int (*register_cooling)(struct ti_bandgap *bgp, int id);
+	int (*unregister_cooling)(struct ti_bandgap *bgp, int id);
+};
+
+/**
+ * DOC: ti bandgap feature types
+ *
+ * TI_BANDGAP_FEATURE_TSHUT - used when the thermal shutdown signal output
+ *      of a bandgap device instance is routed to the processor. This means
+ *      the system must react and perform the shutdown by itself (handle an
+ *      IRQ, for instance).
+ *
+ * TI_BANDGAP_FEATURE_TSHUT_CONFIG - used when the bandgap device has control
+ *      over the thermal shutdown configuration. This means that the thermal
+ *      shutdown thresholds are programmable, for instance.
+ *
+ * TI_BANDGAP_FEATURE_TALERT - used when the bandgap device instance outputs
+ *      a signal representing violation of programmable alert thresholds.
+ *
+ * TI_BANDGAP_FEATURE_MODE_CONFIG - used when it is possible to choose which
+ *      mode, continuous or one shot, the bandgap device instance will operate.
+ *
+ * TI_BANDGAP_FEATURE_COUNTER - used when the bandgap device instance allows
+ *      programming the update interval of its internal state machine.
+ *
+ * TI_BANDGAP_FEATURE_POWER_SWITCH - used when the bandgap device allows
+ *      itself to be switched on/off.
+ *
+ * TI_BANDGAP_FEATURE_CLK_CTRL - used when the clocks feeding the bandgap
+ *      device are gateable or not.
+ *
+ * TI_BANDGAP_FEATURE_FREEZE_BIT - used when the bandgap device features
+ *      a history buffer that its update can be freezed/unfreezed.
+ *
+ * TI_BANDGAP_FEATURE_COUNTER_DELAY - used when the bandgap device features
+ *	a delay programming based on distinct values.
+ *
+ * TI_BANDGAP_FEATURE_HISTORY_BUFFER - used when the bandgap device features
+ *	a history buffer of temperatures.
+ *
+ * TI_BANDGAP_HAS(b, f) - macro to check if a bandgap device is capable of a
+ *      specific feature (above) or not. Return non-zero, if yes.
+ */
+#define TI_BANDGAP_FEATURE_TSHUT		BIT(0)
+#define TI_BANDGAP_FEATURE_TSHUT_CONFIG		BIT(1)
+#define TI_BANDGAP_FEATURE_TALERT		BIT(2)
+#define TI_BANDGAP_FEATURE_MODE_CONFIG		BIT(3)
+#define TI_BANDGAP_FEATURE_COUNTER		BIT(4)
+#define TI_BANDGAP_FEATURE_POWER_SWITCH		BIT(5)
+#define TI_BANDGAP_FEATURE_CLK_CTRL		BIT(6)
+#define TI_BANDGAP_FEATURE_FREEZE_BIT		BIT(7)
+#define TI_BANDGAP_FEATURE_COUNTER_DELAY	BIT(8)
+#define TI_BANDGAP_FEATURE_HISTORY_BUFFER	BIT(9)
+#define TI_BANDGAP_HAS(b, f)			\
+			((b)->conf->features & TI_BANDGAP_FEATURE_ ## f)
+
+/**
+ * struct ti_bandgap_data - ti bandgap data configuration structure
+ * @features: a bitwise flag set to describe the device features
+ * @conv_table: Pointer to ADC to temperature conversion table
+ * @adc_start_val: ADC conversion table starting value
+ * @adc_end_val: ADC conversion table ending value
+ * @fclock_name: clock name of the functional clock
+ * @div_ck_name: clock name of the clock divisor
+ * @sensor_count: count of temperature sensor within this bandgap device
+ * @report_temperature: callback to report thermal alert to thermal API
+ * @expose_sensor: callback to export sensor to thermal API
+ * @remove_sensor: callback to destroy sensor from thermal API
+ * @sensors: array of sensors present in this bandgap instance
+ *
+ * This is a data structure which should hold most of the static configuration
+ * of a bandgap device instance. It should describe which features this instance
+ * is capable of, the clock names to feed this device, the amount of sensors and
+ * their configuration representation, and how to export and unexport them to
+ * a thermal API.
+ */
+struct ti_bandgap_data {
+	unsigned int			features;
+	const int			*conv_table;
+	u32				adc_start_val;
+	u32				adc_end_val;
+	char				*fclock_name;
+	char				*div_ck_name;
+	int				sensor_count;
+	int (*report_temperature)(struct ti_bandgap *bgp, int id);
+	int (*expose_sensor)(struct ti_bandgap *bgp, int id, char *domain);
+	int (*remove_sensor)(struct ti_bandgap *bgp, int id);
+
+	/* this needs to be at the end */
+	struct ti_temp_sensor		sensors[];
+};
+
+int ti_bandgap_read_thot(struct ti_bandgap *bgp, int id, int *thot);
+int ti_bandgap_write_thot(struct ti_bandgap *bgp, int id, int val);
+int ti_bandgap_read_tcold(struct ti_bandgap *bgp, int id, int *tcold);
+int ti_bandgap_write_tcold(struct ti_bandgap *bgp, int id, int val);
+int ti_bandgap_read_update_interval(struct ti_bandgap *bgp, int id,
+				    int *interval);
+int ti_bandgap_write_update_interval(struct ti_bandgap *bgp, int id,
+				     u32 interval);
+int ti_bandgap_read_temperature(struct ti_bandgap *bgp, int id,
+				  int *temperature);
+int ti_bandgap_set_sensor_data(struct ti_bandgap *bgp, int id, void *data);
+void *ti_bandgap_get_sensor_data(struct ti_bandgap *bgp, int id);
+int ti_bandgap_get_trend(struct ti_bandgap *bgp, int id, int *trend);
+
+#ifdef CONFIG_OMAP4_THERMAL
+extern const struct ti_bandgap_data omap4430_data;
+extern const struct ti_bandgap_data omap4460_data;
+extern const struct ti_bandgap_data omap4470_data;
+#else
+#define omap4430_data					NULL
+#define omap4460_data					NULL
+#define omap4470_data					NULL
+#endif
+
+#ifdef CONFIG_OMAP5_THERMAL
+extern const struct ti_bandgap_data omap5430_data;
+#else
+#define omap5430_data					NULL
+#endif
+
+#endif
diff --git a/drivers/staging/ti-soc-thermal/ti-thermal-common.c b/drivers/staging/ti-soc-thermal/ti-thermal-common.c
new file mode 100644
index 0000000..092b39d
--- /dev/null
+++ b/drivers/staging/ti-soc-thermal/ti-thermal-common.c
@@ -0,0 +1,363 @@
+/*
+ * OMAP thermal driver interface
+ *
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ * Contact:
+ *   Eduardo Valentin <eduardo.valentin@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/device.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/gfp.h>
+#include <linux/kernel.h>
+#include <linux/workqueue.h>
+#include <linux/thermal.h>
+#include <linux/cpufreq.h>
+#include <linux/cpumask.h>
+#include <linux/cpu_cooling.h>
+
+#include "ti-thermal.h"
+#include "ti-bandgap.h"
+
+/* common data structures */
+struct ti_thermal_data {
+	struct thermal_zone_device *ti_thermal;
+	struct thermal_cooling_device *cool_dev;
+	struct ti_bandgap *bgp;
+	enum thermal_device_mode mode;
+	struct work_struct thermal_wq;
+	int sensor_id;
+};
+
+static void ti_thermal_work(struct work_struct *work)
+{
+	struct ti_thermal_data *data = container_of(work,
+					struct ti_thermal_data, thermal_wq);
+
+	thermal_zone_device_update(data->ti_thermal);
+
+	dev_dbg(&data->ti_thermal->device, "updated thermal zone %s\n",
+		data->ti_thermal->type);
+}
+
+/**
+ * ti_thermal_hotspot_temperature - returns sensor extrapolated temperature
+ * @t:	omap sensor temperature
+ * @s:	omap sensor slope value
+ * @c:	omap sensor const value
+ */
+static inline int ti_thermal_hotspot_temperature(int t, int s, int c)
+{
+	int delta = t * s / 1000 + c;
+
+	if (delta < 0)
+		delta = 0;
+
+	return t + delta;
+}
+
+/* thermal zone ops */
+/* Get temperature callback function for thermal zone*/
+static inline int ti_thermal_get_temp(struct thermal_zone_device *thermal,
+				      unsigned long *temp)
+{
+	struct ti_thermal_data *data = thermal->devdata;
+	struct ti_bandgap *bgp;
+	const struct ti_temp_sensor *s;
+	int ret, tmp, pcb_temp, slope, constant;
+
+	if (!data)
+		return 0;
+
+	bgp = data->bgp;
+	s = &bgp->conf->sensors[data->sensor_id];
+
+	ret = ti_bandgap_read_temperature(bgp, data->sensor_id, &tmp);
+	if (ret)
+		return ret;
+
+	pcb_temp = 0;
+	/* TODO: Introduce pcb temperature lookup */
+	/* In case pcb zone is available, use the extrapolation rule with it */
+	if (pcb_temp) {
+		tmp -= pcb_temp;
+		slope = s->slope_pcb;
+		constant = s->constant_pcb;
+	} else {
+		slope = s->slope;
+		constant = s->constant;
+	}
+	*temp = ti_thermal_hotspot_temperature(tmp, slope, constant);
+
+	return ret;
+}
+
+/* Bind callback functions for thermal zone */
+static int ti_thermal_bind(struct thermal_zone_device *thermal,
+			   struct thermal_cooling_device *cdev)
+{
+	struct ti_thermal_data *data = thermal->devdata;
+	int id;
+
+	if (IS_ERR_OR_NULL(data))
+		return -ENODEV;
+
+	/* check if this is the cooling device we registered */
+	if (data->cool_dev != cdev)
+		return 0;
+
+	id = data->sensor_id;
+
+	/* TODO: bind with min and max states */
+	/* Simple thing, two trips, one passive another critical */
+	return thermal_zone_bind_cooling_device(thermal, 0, cdev,
+						THERMAL_NO_LIMIT,
+						THERMAL_NO_LIMIT);
+}
+
+/* Unbind callback functions for thermal zone */
+static int ti_thermal_unbind(struct thermal_zone_device *thermal,
+			     struct thermal_cooling_device *cdev)
+{
+	struct ti_thermal_data *data = thermal->devdata;
+
+	if (IS_ERR_OR_NULL(data))
+		return -ENODEV;
+
+	/* check if this is the cooling device we registered */
+	if (data->cool_dev != cdev)
+		return 0;
+
+	/* Simple thing, two trips, one passive another critical */
+	return thermal_zone_unbind_cooling_device(thermal, 0, cdev);
+}
+
+/* Get mode callback functions for thermal zone */
+static int ti_thermal_get_mode(struct thermal_zone_device *thermal,
+			       enum thermal_device_mode *mode)
+{
+	struct ti_thermal_data *data = thermal->devdata;
+
+	if (data)
+		*mode = data->mode;
+
+	return 0;
+}
+
+/* Set mode callback functions for thermal zone */
+static int ti_thermal_set_mode(struct thermal_zone_device *thermal,
+			       enum thermal_device_mode mode)
+{
+	struct ti_thermal_data *data = thermal->devdata;
+
+	if (!data->ti_thermal) {
+		dev_notice(&thermal->device, "thermal zone not registered\n");
+		return 0;
+	}
+
+	mutex_lock(&data->ti_thermal->lock);
+
+	if (mode == THERMAL_DEVICE_ENABLED)
+		data->ti_thermal->polling_delay = FAST_TEMP_MONITORING_RATE;
+	else
+		data->ti_thermal->polling_delay = 0;
+
+	mutex_unlock(&data->ti_thermal->lock);
+
+	data->mode = mode;
+	thermal_zone_device_update(data->ti_thermal);
+	dev_dbg(&thermal->device, "thermal polling set for duration=%d msec\n",
+		data->ti_thermal->polling_delay);
+
+	return 0;
+}
+
+/* Get trip type callback functions for thermal zone */
+static int ti_thermal_get_trip_type(struct thermal_zone_device *thermal,
+				    int trip, enum thermal_trip_type *type)
+{
+	if (!ti_thermal_is_valid_trip(trip))
+		return -EINVAL;
+
+	if (trip + 1 == OMAP_TRIP_NUMBER)
+		*type = THERMAL_TRIP_CRITICAL;
+	else
+		*type = THERMAL_TRIP_PASSIVE;
+
+	return 0;
+}
+
+/* Get trip temperature callback functions for thermal zone */
+static int ti_thermal_get_trip_temp(struct thermal_zone_device *thermal,
+				    int trip, unsigned long *temp)
+{
+	if (!ti_thermal_is_valid_trip(trip))
+		return -EINVAL;
+
+	*temp = ti_thermal_get_trip_value(trip);
+
+	return 0;
+}
+
+/* Get the temperature trend callback functions for thermal zone */
+static int ti_thermal_get_trend(struct thermal_zone_device *thermal,
+				int trip, enum thermal_trend *trend)
+{
+	struct ti_thermal_data *data = thermal->devdata;
+	struct ti_bandgap *bgp;
+	int id, tr, ret = 0;
+
+	bgp = data->bgp;
+	id = data->sensor_id;
+
+	ret = ti_bandgap_get_trend(bgp, id, &tr);
+	if (ret)
+		return ret;
+
+	if (tr > 0)
+		*trend = THERMAL_TREND_RAISING;
+	else if (tr < 0)
+		*trend = THERMAL_TREND_DROPPING;
+	else
+		*trend = THERMAL_TREND_STABLE;
+
+	return 0;
+}
+
+/* Get critical temperature callback functions for thermal zone */
+static int ti_thermal_get_crit_temp(struct thermal_zone_device *thermal,
+				    unsigned long *temp)
+{
+	/* shutdown zone */
+	return ti_thermal_get_trip_temp(thermal, OMAP_TRIP_NUMBER - 1, temp);
+}
+
+static struct thermal_zone_device_ops ti_thermal_ops = {
+	.get_temp = ti_thermal_get_temp,
+	.get_trend = ti_thermal_get_trend,
+	.bind = ti_thermal_bind,
+	.unbind = ti_thermal_unbind,
+	.get_mode = ti_thermal_get_mode,
+	.set_mode = ti_thermal_set_mode,
+	.get_trip_type = ti_thermal_get_trip_type,
+	.get_trip_temp = ti_thermal_get_trip_temp,
+	.get_crit_temp = ti_thermal_get_crit_temp,
+};
+
+static struct ti_thermal_data
+*ti_thermal_build_data(struct ti_bandgap *bgp, int id)
+{
+	struct ti_thermal_data *data;
+
+	data = devm_kzalloc(bgp->dev, sizeof(*data), GFP_KERNEL);
+	if (!data) {
+		dev_err(bgp->dev, "kzalloc fail\n");
+		return NULL;
+	}
+	data->sensor_id = id;
+	data->bgp = bgp;
+	data->mode = THERMAL_DEVICE_ENABLED;
+	INIT_WORK(&data->thermal_wq, ti_thermal_work);
+
+	return data;
+}
+
+int ti_thermal_expose_sensor(struct ti_bandgap *bgp, int id,
+			     char *domain)
+{
+	struct ti_thermal_data *data;
+
+	data = ti_bandgap_get_sensor_data(bgp, id);
+
+	if (IS_ERR_OR_NULL(data))
+		data = ti_thermal_build_data(bgp, id);
+
+	if (!data)
+		return -EINVAL;
+
+	/* TODO: remove TC1 TC2 */
+	/* Create thermal zone */
+	data->ti_thermal = thermal_zone_device_register(domain,
+				OMAP_TRIP_NUMBER, 0, data, &ti_thermal_ops,
+				NULL, FAST_TEMP_MONITORING_RATE,
+				FAST_TEMP_MONITORING_RATE);
+	if (IS_ERR_OR_NULL(data->ti_thermal)) {
+		dev_err(bgp->dev, "thermal zone device is NULL\n");
+		return PTR_ERR(data->ti_thermal);
+	}
+	data->ti_thermal->polling_delay = FAST_TEMP_MONITORING_RATE;
+	ti_bandgap_set_sensor_data(bgp, id, data);
+
+	return 0;
+}
+
+int ti_thermal_remove_sensor(struct ti_bandgap *bgp, int id)
+{
+	struct ti_thermal_data *data;
+
+	data = ti_bandgap_get_sensor_data(bgp, id);
+
+	thermal_zone_device_unregister(data->ti_thermal);
+
+	return 0;
+}
+
+int ti_thermal_report_sensor_temperature(struct ti_bandgap *bgp, int id)
+{
+	struct ti_thermal_data *data;
+
+	data = ti_bandgap_get_sensor_data(bgp, id);
+
+	schedule_work(&data->thermal_wq);
+
+	return 0;
+}
+
+int ti_thermal_register_cpu_cooling(struct ti_bandgap *bgp, int id)
+{
+	struct ti_thermal_data *data;
+
+	data = ti_bandgap_get_sensor_data(bgp, id);
+	if (IS_ERR_OR_NULL(data))
+		data = ti_thermal_build_data(bgp, id);
+
+	if (!data)
+		return -EINVAL;
+
+	/* Register cooling device */
+	data->cool_dev = cpufreq_cooling_register(cpu_present_mask);
+	if (IS_ERR_OR_NULL(data->cool_dev)) {
+		dev_err(bgp->dev,
+			"Failed to register cpufreq cooling device\n");
+		return PTR_ERR(data->cool_dev);
+	}
+	ti_bandgap_set_sensor_data(bgp, id, data);
+
+	return 0;
+}
+
+int ti_thermal_unregister_cpu_cooling(struct ti_bandgap *bgp, int id)
+{
+	struct ti_thermal_data *data;
+
+	data = ti_bandgap_get_sensor_data(bgp, id);
+	cpufreq_cooling_unregister(data->cool_dev);
+
+	return 0;
+}
diff --git a/drivers/staging/ti-soc-thermal/ti-thermal.h b/drivers/staging/ti-soc-thermal/ti-thermal.h
new file mode 100644
index 0000000..7b2d600
--- /dev/null
+++ b/drivers/staging/ti-soc-thermal/ti-thermal.h
@@ -0,0 +1,113 @@
+/*
+ * OMAP thermal definitions
+ *
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ * Contact:
+ *   Eduardo Valentin <eduardo.valentin@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 __TI_THERMAL_H
+#define __TI_THERMAL_H
+
+#include "ti-bandgap.h"
+
+/* sensors gradient and offsets */
+#define OMAP_GRADIENT_SLOPE_4460				348
+#define OMAP_GRADIENT_CONST_4460				-9301
+#define OMAP_GRADIENT_SLOPE_4470				308
+#define OMAP_GRADIENT_CONST_4470				-7896
+
+#define OMAP_GRADIENT_SLOPE_5430_CPU				196
+#define OMAP_GRADIENT_CONST_5430_CPU				-6822
+#define OMAP_GRADIENT_SLOPE_5430_GPU				64
+#define OMAP_GRADIENT_CONST_5430_GPU				978
+
+/* PCB sensor calculation constants */
+#define OMAP_GRADIENT_SLOPE_W_PCB_4460				1142
+#define OMAP_GRADIENT_CONST_W_PCB_4460				-393
+#define OMAP_GRADIENT_SLOPE_W_PCB_4470				1063
+#define OMAP_GRADIENT_CONST_W_PCB_4470				-477
+
+#define OMAP_GRADIENT_SLOPE_W_PCB_5430_CPU			469
+#define OMAP_GRADIENT_CONST_W_PCB_5430_CPU			-1272
+#define OMAP_GRADIENT_SLOPE_W_PCB_5430_GPU			378
+#define OMAP_GRADIENT_CONST_W_PCB_5430_GPU			154
+
+/* trip points of interest in milicelsius (at hotspot level) */
+#define OMAP_TRIP_COLD						100000
+#define OMAP_TRIP_HOT						110000
+#define OMAP_TRIP_SHUTDOWN					125000
+#define OMAP_TRIP_NUMBER					2
+#define OMAP_TRIP_STEP							\
+	((OMAP_TRIP_SHUTDOWN - OMAP_TRIP_HOT) / (OMAP_TRIP_NUMBER - 1))
+
+/* Update rates */
+#define FAST_TEMP_MONITORING_RATE				250
+
+/* helper macros */
+/**
+ * ti_thermal_get_trip_value - returns trip temperature based on index
+ * @i:	trip index
+ */
+#define ti_thermal_get_trip_value(i)					\
+	(OMAP_TRIP_HOT + ((i) * OMAP_TRIP_STEP))
+
+/**
+ * ti_thermal_is_valid_trip - check for trip index
+ * @i:	trip index
+ */
+#define ti_thermal_is_valid_trip(trip)				\
+	((trip) >= 0 && (trip) < OMAP_TRIP_NUMBER)
+
+#ifdef CONFIG_TI_THERMAL
+int ti_thermal_expose_sensor(struct ti_bandgap *bgp, int id, char *domain);
+int ti_thermal_remove_sensor(struct ti_bandgap *bgp, int id);
+int ti_thermal_report_sensor_temperature(struct ti_bandgap *bgp, int id);
+int ti_thermal_register_cpu_cooling(struct ti_bandgap *bgp, int id);
+int ti_thermal_unregister_cpu_cooling(struct ti_bandgap *bgp, int id);
+#else
+static inline
+int ti_thermal_expose_sensor(struct ti_bandgap *bgp, int id, char *domain)
+{
+	return 0;
+}
+
+static inline
+int ti_thermal_remove_sensor(struct ti_bandgap *bgp, int id)
+{
+	return 0;
+}
+
+static inline
+int ti_thermal_report_sensor_temperature(struct ti_bandgap *bgp, int id)
+{
+	return 0;
+}
+
+static inline
+int ti_thermal_register_cpu_cooling(struct ti_bandgap *bgp, int id)
+{
+	return 0;
+}
+
+static inline
+int ti_thermal_unregister_cpu_cooling(struct ti_bandgap *bgp, int id)
+{
+	return 0;
+}
+#endif
+#endif
diff --git a/drivers/staging/ti-soc-thermal/ti_soc_thermal.txt b/drivers/staging/ti-soc-thermal/ti_soc_thermal.txt
new file mode 100644
index 0000000..a4a33d1
--- /dev/null
+++ b/drivers/staging/ti-soc-thermal/ti_soc_thermal.txt
@@ -0,0 +1,60 @@
+* Texas Instrument OMAP SCM bandgap bindings
+
+In the System Control Module, OMAP supplies a voltage reference
+and a temperature sensor feature that are gathered in the band
+gap voltage and temperature sensor (VBGAPTS) module. The band
+gap provides current and voltage reference for its internal
+circuits and other analog IP blocks. The analog-to-digital
+converter (ADC) produces an output value that is proportional
+to the silicon temperature.
+
+Required properties:
+- compatible : Should be:
+  - "ti,omap4430-bandgap" : for OMAP4430 bandgap
+  - "ti,omap4460-bandgap" : for OMAP4460 bandgap
+  - "ti,omap4470-bandgap" : for OMAP4470 bandgap
+  - "ti,omap5430-bandgap" : for OMAP5430 bandgap
+- interrupts : this entry should indicate which interrupt line
+the talert signal is routed to;
+Specific:
+- ti,tshut-gpio : this entry should be used to inform which GPIO
+line the tshut signal is routed to;
+- regs : this entry must also be specified and it is specific
+to each bandgap version, because the mapping may change from
+soc to soc, apart of depending on available features.
+
+Example:
+OMAP4430:
+bandgap {
+	reg = <0x4a002260 0x4 0x4a00232C 0x4>;
+	compatible = "ti,omap4430-bandgap";
+};
+
+OMAP4460:
+bandgap {
+	reg = <0x4a002260 0x4
+		0x4a00232C 0x4
+		0x4a002378 0x18>;
+	compatible = "ti,omap4460-bandgap";
+	interrupts = <0 126 4>; /* talert */
+	ti,tshut-gpio = <86>;
+};
+
+OMAP4470:
+bandgap {
+	reg = <0x4a002260 0x4
+		0x4a00232C 0x4
+		0x4a002378 0x18>;
+	compatible = "ti,omap4470-bandgap";
+	interrupts = <0 126 4>; /* talert */
+	ti,tshut-gpio = <86>;
+};
+
+OMAP5430:
+bandgap {
+	reg = <0x4a0021e0 0xc
+		0x4a00232c 0xc
+		0x4a002380 0x2c
+		0x4a0023C0 0x3c>;
+	compatible = "ti,omap5430-bandgap";
+};
diff --git a/drivers/staging/tidspbridge/Kconfig b/drivers/staging/tidspbridge/Kconfig
index 60848f1..165b918 100644
--- a/drivers/staging/tidspbridge/Kconfig
+++ b/drivers/staging/tidspbridge/Kconfig
@@ -5,7 +5,8 @@
 menuconfig TIDSPBRIDGE
 	tristate "DSP Bridge driver"
 	depends on ARCH_OMAP3 && !ARCH_MULTIPLATFORM
-	select OMAP_MBOX_FWK
+	select MAILBOX
+	select OMAP2PLUS_MBOX
 	help
 	  DSP/BIOS Bridge is designed for platforms that contain a GPP and
 	  one or more attached DSPs.  The GPP is considered the master or
diff --git a/drivers/staging/tidspbridge/core/_tiomap.h b/drivers/staging/tidspbridge/core/_tiomap.h
index b783bfa..f71a89d 100644
--- a/drivers/staging/tidspbridge/core/_tiomap.h
+++ b/drivers/staging/tidspbridge/core/_tiomap.h
@@ -338,7 +338,7 @@ struct bridge_dev_context {
 	u32 dsp_start_add;	/* API Boot vector */
 	u32 internal_size;	/* Internal memory size */
 
-	struct omap_mbox *mbox;		/* Mail box handle */
+	struct mailbox *mbox;		/* Mail box handle */
 
 	struct cfg_hostres *resources;	/* Host Resources */
 
diff --git a/drivers/staging/tidspbridge/core/chnl_sm.c b/drivers/staging/tidspbridge/core/chnl_sm.c
index 16fa346..1cae172 100644
--- a/drivers/staging/tidspbridge/core/chnl_sm.c
+++ b/drivers/staging/tidspbridge/core/chnl_sm.c
@@ -155,7 +155,7 @@ func_cont:
 	 * we disable ALL DPCs. We will try to disable ONLY IO DPC later. */
 	chnl_mgr_obj = pchnl->chnl_mgr_obj;
 	spin_lock_bh(&chnl_mgr_obj->chnl_mgr_lock);
-	omap_mbox_disable_irq(dev_ctxt->mbox, IRQ_RX);
+	mailbox_disable_irq(dev_ctxt->mbox, IRQ_RX);
 	if (pchnl->chnl_type == CHNL_PCPY) {
 		/* This is a processor-copy channel. */
 		if (CHNL_IS_OUTPUT(pchnl->chnl_mode)) {
@@ -210,7 +210,7 @@ func_cont:
 			 IO_OUTPUT), &mb_val);
 	sched_dpc = true;
 out:
-	omap_mbox_enable_irq(dev_ctxt->mbox, IRQ_RX);
+	mailbox_enable_irq(dev_ctxt->mbox, IRQ_RX);
 	spin_unlock_bh(&chnl_mgr_obj->chnl_mgr_lock);
 	if (mb_val != 0)
 		sm_interrupt_dsp(dev_ctxt, mb_val);
@@ -570,7 +570,7 @@ int bridge_chnl_get_ioc(struct chnl_object *chnl_obj, u32 timeout,
 	}
 	/* See comment in AddIOReq */
 	spin_lock_bh(&pchnl->chnl_mgr_obj->chnl_mgr_lock);
-	omap_mbox_disable_irq(dev_ctxt->mbox, IRQ_RX);
+	mailbox_disable_irq(dev_ctxt->mbox, IRQ_RX);
 	if (dequeue_ioc) {
 		/* Dequeue IOC and set chan_ioc; */
 		chnl_packet_obj = list_first_entry(&pchnl->io_completions,
@@ -616,7 +616,7 @@ int bridge_chnl_get_ioc(struct chnl_object *chnl_obj, u32 timeout,
 		/* else, if list is empty, ensure event is reset. */
 		sync_reset_event(pchnl->sync_event);
 	}
-	omap_mbox_enable_irq(dev_ctxt->mbox, IRQ_RX);
+	mailbox_enable_irq(dev_ctxt->mbox, IRQ_RX);
 	spin_unlock_bh(&pchnl->chnl_mgr_obj->chnl_mgr_lock);
 	if (dequeue_ioc
 	    && (pchnl->chnl_type == CHNL_PCPY && pchnl->chnl_id > 1)) {
diff --git a/drivers/staging/tidspbridge/core/io_sm.c b/drivers/staging/tidspbridge/core/io_sm.c
index e322fb7..495ef98 100644
--- a/drivers/staging/tidspbridge/core/io_sm.c
+++ b/drivers/staging/tidspbridge/core/io_sm.c
@@ -908,10 +908,11 @@ func_end:
  *      Calls the Bridge's CHNL_ISR to determine if this interrupt is ours, then
  *      schedules a DPC to dispatch I/O.
  */
-int io_mbox_msg(struct notifier_block *self, unsigned long len, void *msg)
+int io_mbox_msg(struct notifier_block *self, unsigned long len, void *data)
 {
 	struct io_mgr *pio_mgr;
 	struct dev_object *dev_obj;
+	u32 msg = (u32)((struct mailbox_msg *)data)->pdata;
 	unsigned long flags;
 
 	dev_obj = dev_get_first();
@@ -920,7 +921,7 @@ int io_mbox_msg(struct notifier_block *self, unsigned long len, void *msg)
 	if (!pio_mgr)
 		return NOTIFY_BAD;
 
-	pio_mgr->intr_val = (u16)((u32)msg);
+	pio_mgr->intr_val = (u16)(msg);
 	if (pio_mgr->intr_val & MBX_PM_CLASS)
 		io_dispatch_pm(pio_mgr);
 
diff --git a/drivers/staging/tidspbridge/core/tiomap3430.c b/drivers/staging/tidspbridge/core/tiomap3430.c
index b770b22..c637299 100644
--- a/drivers/staging/tidspbridge/core/tiomap3430.c
+++ b/drivers/staging/tidspbridge/core/tiomap3430.c
@@ -542,7 +542,7 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt,
 		 * Enable Mailbox events and also drain any pending
 		 * stale messages.
 		 */
-		dev_context->mbox = omap_mbox_get("dsp", &dsp_mbox_notifier);
+		dev_context->mbox = mailbox_get("dsp", &dsp_mbox_notifier);
 		if (IS_ERR(dev_context->mbox)) {
 			dev_context->mbox = NULL;
 			pr_err("%s: Failed to get dsp mailbox handle\n",
@@ -677,8 +677,8 @@ static int bridge_brd_stop(struct bridge_dev_context *dev_ctxt)
 	}
 	/* Disable the mailbox interrupts */
 	if (dev_context->mbox) {
-		omap_mbox_disable_irq(dev_context->mbox, IRQ_RX);
-		omap_mbox_put(dev_context->mbox, &dsp_mbox_notifier);
+		mailbox_disable_irq(dev_context->mbox, IRQ_RX);
+		mailbox_put(dev_context->mbox, &dsp_mbox_notifier);
 		dev_context->mbox = NULL;
 	}
 	/* Reset IVA2 clocks*/
diff --git a/drivers/staging/tidspbridge/core/tiomap3430_pwr.c b/drivers/staging/tidspbridge/core/tiomap3430_pwr.c
index dafa6d9..e50f404 100644
--- a/drivers/staging/tidspbridge/core/tiomap3430_pwr.c
+++ b/drivers/staging/tidspbridge/core/tiomap3430_pwr.c
@@ -108,7 +108,7 @@ int handle_hibernation_from_dsp(struct bridge_dev_context *dev_context)
 	} else {
 
 		/* Save mailbox settings */
-		omap_mbox_save_ctx(dev_context->mbox);
+		mailbox_save_ctx(dev_context->mbox);
 
 		/* Turn off DSP Peripheral clocks and DSP Load monitor timer */
 		status = dsp_clock_disable_all(dev_context->dsp_per_clks);
@@ -165,7 +165,7 @@ int sleep_dsp(struct bridge_dev_context *dev_context, u32 dw_cmd,
 
 	switch (dev_context->brd_state) {
 	case BRD_RUNNING:
-		omap_mbox_save_ctx(dev_context->mbox);
+		mailbox_save_ctx(dev_context->mbox);
 		if (dsp_test_sleepstate == PWRDM_POWER_OFF) {
 			sm_interrupt_dsp(dev_context, MBX_PM_DSPHIBERNATE);
 			dev_dbg(bridge, "PM: %s - sent hibernate cmd to DSP\n",
@@ -177,7 +177,7 @@ int sleep_dsp(struct bridge_dev_context *dev_context, u32 dw_cmd,
 		}
 		break;
 	case BRD_RETENTION:
-		omap_mbox_save_ctx(dev_context->mbox);
+		mailbox_save_ctx(dev_context->mbox);
 		if (dsp_test_sleepstate == PWRDM_POWER_OFF) {
 			sm_interrupt_dsp(dev_context, MBX_PM_DSPHIBERNATE);
 			target_pwr_state = PWRDM_POWER_OFF;
diff --git a/drivers/staging/tidspbridge/core/tiomap_io.c b/drivers/staging/tidspbridge/core/tiomap_io.c
index f53ed98..5bd57dd 100644
--- a/drivers/staging/tidspbridge/core/tiomap_io.c
+++ b/drivers/staging/tidspbridge/core/tiomap_io.c
@@ -374,6 +374,7 @@ int sm_interrupt_dsp(struct bridge_dev_context *dev_context, u16 mb_val)
 	struct omap_dsp_platform_data *pdata =
 		omap_dspbridge_dev->dev.platform_data;
 	struct cfg_hostres *resources = dev_context->resources;
+	struct mailbox_msg msg;
 	int status = 0;
 	u32 temp;
 
@@ -416,7 +417,7 @@ int sm_interrupt_dsp(struct bridge_dev_context *dev_context, u16 mb_val)
 				OMAP3430_IVA2_MOD, OMAP3430_CM_CLKEN_PLL);
 
 		/* Restore mailbox settings */
-		omap_mbox_restore_ctx(dev_context->mbox);
+		mailbox_restore_ctx(dev_context->mbox);
 
 		/* Access MMU SYS CONFIG register to generate a short wakeup */
 		temp = readl(resources->dmmu_base + 0x10);
@@ -427,10 +428,12 @@ int sm_interrupt_dsp(struct bridge_dev_context *dev_context, u16 mb_val)
 		dsp_clock_enable_all(dev_context->dsp_per_clks);
 	}
 
-	status = omap_mbox_msg_send(dev_context->mbox, mb_val);
+	temp = mb_val;
+	MAILBOX_FILL_MSG(msg, 0, temp, 0);
+	status = mailbox_msg_send(dev_context->mbox, &msg);
 
 	if (status) {
-		pr_err("omap_mbox_msg_send Fail and status = %d\n", status);
+		pr_err("mailbox_msg_send Fail and status = %d\n", status);
 		status = -EPERM;
 	}
 
diff --git a/drivers/staging/tidspbridge/include/dspbridge/host_os.h b/drivers/staging/tidspbridge/include/dspbridge/host_os.h
index 7f3a1db..27f6bd6 100644
--- a/drivers/staging/tidspbridge/include/dspbridge/host_os.h
+++ b/drivers/staging/tidspbridge/include/dspbridge/host_os.h
@@ -41,7 +41,7 @@
 #include <linux/ioport.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
-#include <plat/mailbox.h>
+#include <linux/mailbox.h>
 #include <linux/pagemap.h>
 #include <asm/cacheflush.h>
 #include <linux/dma-mapping.h>
diff --git a/drivers/staging/tidspbridge/rmgr/proc.c b/drivers/staging/tidspbridge/rmgr/proc.c
index 0df55bd..cd5235a 100644
--- a/drivers/staging/tidspbridge/rmgr/proc.c
+++ b/drivers/staging/tidspbridge/rmgr/proc.c
@@ -488,7 +488,7 @@ func_end:
  *      Call the bridge_dev_ctrl fxn with the Argument. This is a Synchronous
  *      Operation. arg can be null.
  */
-int proc_ctrl(void *hprocessor, u32 dw_cmd, struct dsp_cbdata * arg)
+int proc_ctrl(void *hprocessor, u32 dw_cmd, struct dsp_cbdata *arg)
 {
 	int status = 0;
 	struct proc_object *p_proc_object = hprocessor;
@@ -982,7 +982,7 @@ int proc_get_state(void *hprocessor,
  *      This call is destructive, meaning the processor is placed in the monitor
  *      state as a result of this function.
  */
-int proc_get_trace(void *hprocessor, u8 * pbuf, u32 max_size)
+int proc_get_trace(void *hprocessor, u8 *pbuf, u32 max_size)
 {
 	int status;
 	status = -ENOSYS;
@@ -1338,7 +1338,7 @@ func_end:
  */
 int proc_register_notify(void *hprocessor, u32 event_mask,
 				u32 notify_type, struct dsp_notification
-				* hnotification)
+				*hnotification)
 {
 	int status = 0;
 	struct proc_object *p_proc_object = (struct proc_object *)hprocessor;
@@ -1549,8 +1549,8 @@ int proc_stop(void *hprocessor)
 		status = node_enum_nodes(hnode_mgr, &hnode, node_tab_size,
 					 &num_nodes, &nodes_allocated);
 		if ((status == -EINVAL) || (nodes_allocated > 0)) {
-			pr_err("%s: Can't stop device, active nodes = %d \n",
-			       __func__, nodes_allocated);
+			pr_err("%s: Can't stop device, active nodes = %d\n",
+				__func__, nodes_allocated);
 			return -EBADR;
 		}
 	}
@@ -1819,7 +1819,7 @@ func_end:
  *  Purpose:
  *      Retrieves the processor ID.
  */
-int proc_get_processor_id(void *proc, u32 * proc_id)
+int proc_get_processor_id(void *proc, u32 *proc_id)
 {
 	int status = 0;
 	struct proc_object *p_proc_object = (struct proc_object *)proc;
diff --git a/drivers/staging/tidspbridge/rmgr/strm.c b/drivers/staging/tidspbridge/rmgr/strm.c
index 34cc934..b88b27b 100644
--- a/drivers/staging/tidspbridge/rmgr/strm.c
+++ b/drivers/staging/tidspbridge/rmgr/strm.c
@@ -223,7 +223,7 @@ void strm_delete(struct strm_mgr *strm_mgr_obj)
  *  Purpose:
  *      Frees the buffers allocated for a stream.
  */
-int strm_free_buffer(struct strm_res_object *strmres, u8 ** ap_buffer,
+int strm_free_buffer(struct strm_res_object *strmres, u8 **ap_buffer,
 			    u32 num_bufs, struct process_context *pr_ctxt)
 {
 	int status = 0;
@@ -523,7 +523,7 @@ func_cont:
  *  Purpose:
  *      Relcaims a buffer from a stream.
  */
-int strm_reclaim(struct strm_object *stream_obj, u8 ** buf_ptr,
+int strm_reclaim(struct strm_object *stream_obj, u8 **buf_ptr,
 			u32 *nbytes, u32 *buff_size, u32 *pdw_arg)
 {
 	struct bridge_drv_interface *intf_fxns;
@@ -599,7 +599,7 @@ func_end:
  */
 int strm_register_notify(struct strm_object *stream_obj, u32 event_mask,
 				u32 notify_type, struct dsp_notification
-				* hnotification)
+				*hnotification)
 {
 	struct bridge_drv_interface *intf_fxns;
 	int status = 0;
diff --git a/drivers/staging/usbip/stub_dev.c b/drivers/staging/usbip/stub_dev.c
index 67556ac..0a70b8e 100644
--- a/drivers/staging/usbip/stub_dev.c
+++ b/drivers/staging/usbip/stub_dev.c
@@ -114,8 +114,10 @@ static ssize_t store_sockfd(struct device *dev, struct device_attribute *attr,
 
 		spin_unlock_irq(&sdev->ud.lock);
 
-		sdev->ud.tcp_rx = kthread_get_run(stub_rx_loop, &sdev->ud, "stub_rx");
-		sdev->ud.tcp_tx = kthread_get_run(stub_tx_loop, &sdev->ud, "stub_tx");
+		sdev->ud.tcp_rx = kthread_get_run(stub_rx_loop, &sdev->ud,
+						  "stub_rx");
+		sdev->ud.tcp_tx = kthread_get_run(stub_tx_loop, &sdev->ud,
+						  "stub_tx");
 
 		spin_lock_irq(&sdev->ud.lock);
 		sdev->ud.status = SDEV_ST_USED;
diff --git a/drivers/staging/usbip/userspace/libsrc/names.c b/drivers/staging/usbip/userspace/libsrc/names.c
index b4de18b..3b151df 100644
--- a/drivers/staging/usbip/userspace/libsrc/names.c
+++ b/drivers/staging/usbip/userspace/libsrc/names.c
@@ -22,8 +22,8 @@
  */
 
 /*
- * 	Copyright (C) 2005 Takahiro Hirofuchi
- * 		- names_deinit() is added.
+ *	Copyright (C) 2005 Takahiro Hirofuchi
+ *		- names_deinit() is added.
  */
 
 /*****************************************************************************/
@@ -82,9 +82,9 @@ struct audioterminal {
 };
 
 struct genericstrtable {
-        struct genericstrtable *next;
-        unsigned int num;
-        char name[1];
+	struct genericstrtable *next;
+	unsigned int num;
+	char name[1];
 };
 
 /* ---------------------------------------------------------------------- */
@@ -122,14 +122,15 @@ static struct genericstrtable *countrycodes[HASHSZ] = { NULL, };
 
 /* ---------------------------------------------------------------------- */
 
-static const char *names_genericstrtable(struct genericstrtable *t[HASHSZ], unsigned int index)
+static const char *names_genericstrtable(struct genericstrtable *t[HASHSZ],
+					 unsigned int index)
 {
-        struct genericstrtable *h;
+	struct genericstrtable *h;
 
-        for (h = t[hashnum(index)]; h; h = h->next)
-                if (h->num == index)
-                        return h->name;
-        return NULL;
+	for (h = t[hashnum(index)]; h; h = h->next)
+		if (h->num == index)
+			return h->name;
+	return NULL;
 }
 
 const char *names_hid(u_int8_t hidd)
@@ -216,13 +217,16 @@ const char *names_subclass(u_int8_t classid, u_int8_t subclassid)
 	return NULL;
 }
 
-const char *names_protocol(u_int8_t classid, u_int8_t subclassid, u_int8_t protocolid)
+const char *names_protocol(u_int8_t classid, u_int8_t subclassid,
+			   u_int8_t protocolid)
 {
 	struct protocol *p;
 
-	p = protocols[hashnum((classid << 16) | (subclassid << 8) | protocolid)];
+	p = protocols[hashnum((classid << 16) | (subclassid << 8)
+			      | protocolid)];
 	for (; p; p = p->next)
-		if (p->classid == classid && p->subclassid == subclassid && p->protocolid == protocolid)
+		if (p->classid == classid && p->subclassid == subclassid &&
+		    p->protocolid == protocolid)
 			return p->name;
 	return NULL;
 }
@@ -246,7 +250,7 @@ struct pool {
 	void *mem;
 };
 
-static struct pool *pool_head = NULL;
+static struct pool *pool_head;
 
 static void *my_malloc(size_t size)
 {
@@ -308,7 +312,8 @@ static int new_vendor(const char *name, u_int16_t vendorid)
 	return 0;
 }
 
-static int new_product(const char *name, u_int16_t vendorid, u_int16_t productid)
+static int new_product(const char *name, u_int16_t vendorid,
+		       u_int16_t productid)
 {
 	struct product *p;
 	unsigned int h = hashnum((vendorid << 16) | productid);
@@ -367,14 +372,17 @@ static int new_subclass(const char *name, u_int8_t classid, u_int8_t subclassid)
 	return 0;
 }
 
-static int new_protocol(const char *name, u_int8_t classid, u_int8_t subclassid, u_int8_t protocolid)
+static int new_protocol(const char *name, u_int8_t classid, u_int8_t subclassid,
+			u_int8_t protocolid)
 {
 	struct protocol *p;
-	unsigned int h = hashnum((classid << 16) | (subclassid << 8) | protocolid);
+	unsigned int h = hashnum((classid << 16) | (subclassid << 8)
+				 | protocolid);
 
 	p = protocols[h];
 	for (; p; p = p->next)
-		if (p->classid == classid && p->subclassid == subclassid && p->protocolid == protocolid)
+		if (p->classid == classid && p->subclassid == subclassid
+		    && p->protocolid == protocolid)
 			return -1;
 	p = my_malloc(sizeof(struct protocol) + strlen(name));
 	if (!p)
@@ -407,22 +415,23 @@ static int new_audioterminal(const char *name, u_int16_t termt)
 	return 0;
 }
 
-static int new_genericstrtable(struct genericstrtable *t[HASHSZ], const char *name, unsigned int index)
+static int new_genericstrtable(struct genericstrtable *t[HASHSZ],
+			       const char *name, unsigned int index)
 {
-        struct genericstrtable *g;
+	struct genericstrtable *g;
 	unsigned int h = hashnum(index);
 
-        for (g = t[h]; g; g = g->next)
-                if (g->num == index)
-                        return -1;
-        g = my_malloc(sizeof(struct genericstrtable) + strlen(name));
-        if (!g)
-                return -1;
-        strcpy(g->name, name);
-        g->num = index;
-        g->next = t[h];
-        t[h] = g;
-        return 0;
+	for (g = t[h]; g; g = g->next)
+		if (g->num == index)
+			return -1;
+	g = my_malloc(sizeof(struct genericstrtable) + strlen(name));
+	if (!g)
+		return -1;
+	strcpy(g->name, name);
+	g->num = index;
+	g->next = t[h];
+	t[h] = g;
+	return 0;
 }
 
 static int new_hid(const char *name, u_int8_t hidd)
@@ -472,123 +481,151 @@ static void parse(FILE *f)
 {
 	char buf[512], *cp;
 	unsigned int linectr = 0;
-	int lastvendor = -1, lastclass = -1, lastsubclass = -1, lasthut=-1, lastlang=-1;
+	int lastvendor = -1;
+	int lastclass = -1;
+	int lastsubclass = -1;
+	int lasthut = -1;
+	int lastlang = -1;
 	unsigned int u;
 
 	while (fgets(buf, sizeof(buf), f)) {
 		linectr++;
 		/* remove line ends */
-		if ((cp = strchr(buf, 13)))
+		cp = strchr(buf, 13);
+		if (cp)
 			*cp = 0;
-		if ((cp = strchr(buf, 10)))
+		cp = strchr(buf, 10);
+		if (cp)
 			*cp = 0;
 		if (buf[0] == '#' || !buf[0])
 			continue;
 		cp = buf;
-                if (buf[0] == 'P' && buf[1] == 'H' && buf[2] == 'Y' && buf[3] == 'S' && buf[4] == 'D' &&
-                    buf[5] == 'E' && buf[6] == 'S' && /*isspace(buf[7])*/ buf[7] == ' ') {
-                        cp = buf + 8;
-                        while (isspace(*cp))
-                                cp++;
-                        if (!isxdigit(*cp)) {
-                                fprintf(stderr, "Invalid Physdes type at line %u\n", linectr);
-                                continue;
-                        }
-                        u = strtoul(cp, &cp, 16);
-                        while (isspace(*cp))
-                                cp++;
-                        if (!*cp) {
-                                fprintf(stderr, "Invalid Physdes type at line %u\n", linectr);
-                                continue;
-                        }
-                        if (new_physdes(cp, u))
-                                fprintf(stderr, "Duplicate Physdes  type spec at line %u terminal type %04x %s\n", linectr, u, cp);
-                        DBG(printf("line %5u physdes type %02x %s\n", linectr, u, cp));
-                        continue;
-
-                }
-                if (buf[0] == 'P' && buf[1] == 'H' && buf[2] == 'Y' && /*isspace(buf[3])*/ buf[3] == ' ') {
-                        cp = buf + 4;
-                        while (isspace(*cp))
-                                cp++;
-                        if (!isxdigit(*cp)) {
-                                fprintf(stderr, "Invalid PHY type at line %u\n", linectr);
-                                continue;
-                        }
-                        u = strtoul(cp, &cp, 16);
-                        while (isspace(*cp))
-                                cp++;
-                        if (!*cp) {
-                                fprintf(stderr, "Invalid PHY type at line %u\n", linectr);
-                                continue;
-                        }
-                        if (new_physdes(cp, u))
-                                fprintf(stderr, "Duplicate PHY type spec at line %u terminal type %04x %s\n", linectr, u, cp);
-                        DBG(printf("line %5u PHY type %02x %s\n", linectr, u, cp));
-                        continue;
-
-                }
-                if (buf[0] == 'B' && buf[1] == 'I' && buf[2] == 'A' && buf[3] == 'S' && /*isspace(buf[4])*/ buf[4] == ' ') {
-                        cp = buf + 5;
-                        while (isspace(*cp))
-                                cp++;
-                        if (!isxdigit(*cp)) {
-                                fprintf(stderr, "Invalid BIAS type at line %u\n", linectr);
-                                continue;
-                        }
-                        u = strtoul(cp, &cp, 16);
-                        while (isspace(*cp))
-                                cp++;
-                        if (!*cp) {
-                                fprintf(stderr, "Invalid BIAS type at line %u\n", linectr);
-                                continue;
-                        }
-                        if (new_bias(cp, u))
-                                fprintf(stderr, "Duplicate BIAS  type spec at line %u terminal type %04x %s\n", linectr, u, cp);
-                        DBG(printf("line %5u BIAS type %02x %s\n", linectr, u, cp));
-                        continue;
-
-                }
-                if (buf[0] == 'L' && /*isspace(buf[1])*/ buf[1] == ' ') {
-                        cp =  buf+2;
-                        while (isspace(*cp))
-                                cp++;
-                        if (!isxdigit(*cp)) {
-                                fprintf(stderr, "Invalid LANGID spec at line %u\n", linectr);
-                                continue;
-                        }
-                        u = strtoul(cp, &cp, 16);
-                        while (isspace(*cp))
-                                cp++;
-                        if (!*cp) {
-                                fprintf(stderr, "Invalid LANGID spec at line %u\n", linectr);
-                                continue;
-                        }
-                        if (new_langid(cp, u))
-                                fprintf(stderr, "Duplicate LANGID spec at line %u language-id %04x %s\n", linectr, u, cp);
-                        DBG(printf("line %5u LANGID %02x %s\n", linectr, u, cp));
-                        lasthut = lastclass = lastvendor = lastsubclass = -1;
-                        lastlang = u;
-                        continue;
-                }
+		if (buf[0] == 'P' && buf[1] == 'H' && buf[2] == 'Y'
+		    && buf[3] == 'S' && buf[4] == 'D' && buf[5] == 'E'
+		    && buf[6] == 'S' && /*isspace(buf[7])*/ buf[7] == ' ') {
+			cp = buf + 8;
+			while (isspace(*cp))
+				cp++;
+			if (!isxdigit(*cp)) {
+				fprintf(stderr, "Invalid Physdes type at line %u\n",
+					linectr);
+				continue;
+			}
+			u = strtoul(cp, &cp, 16);
+			while (isspace(*cp))
+				cp++;
+			if (!*cp) {
+				fprintf(stderr, "Invalid Physdes type at line %u\n",
+					linectr);
+				continue;
+			}
+			if (new_physdes(cp, u))
+				fprintf(stderr, "Duplicate Physdes  type spec at line %u terminal type %04x %s\n",
+					linectr, u, cp);
+			DBG(printf("line %5u physdes type %02x %s\n", linectr,
+				   u, cp));
+			continue;
+
+		}
+		if (buf[0] == 'P' && buf[1] == 'H' && buf[2] == 'Y'
+		    && /*isspace(buf[3])*/ buf[3] == ' ') {
+			cp = buf + 4;
+			while (isspace(*cp))
+				cp++;
+			if (!isxdigit(*cp)) {
+				fprintf(stderr, "Invalid PHY type at line %u\n",
+					linectr);
+				continue;
+			}
+			u = strtoul(cp, &cp, 16);
+			while (isspace(*cp))
+				cp++;
+			if (!*cp) {
+				fprintf(stderr, "Invalid PHY type at line %u\n",
+					linectr);
+				continue;
+			}
+			if (new_physdes(cp, u))
+				fprintf(stderr, "Duplicate PHY type spec at line %u terminal type %04x %s\n",
+					linectr, u, cp);
+			DBG(printf("line %5u PHY type %02x %s\n", linectr, u,
+				   cp));
+			continue;
+
+		}
+		if (buf[0] == 'B' && buf[1] == 'I' && buf[2] == 'A'
+		    && buf[3] == 'S' && /*isspace(buf[4])*/ buf[4] == ' ') {
+			cp = buf + 5;
+			while (isspace(*cp))
+				cp++;
+			if (!isxdigit(*cp)) {
+				fprintf(stderr, "Invalid BIAS type at line %u\n",
+					linectr);
+				continue;
+			}
+			u = strtoul(cp, &cp, 16);
+			while (isspace(*cp))
+				cp++;
+			if (!*cp) {
+				fprintf(stderr, "Invalid BIAS type at line %u\n",
+					linectr);
+				continue;
+			}
+			if (new_bias(cp, u))
+				fprintf(stderr, "Duplicate BIAS  type spec at line %u terminal type %04x %s\n",
+					linectr, u, cp);
+			DBG(printf("line %5u BIAS type %02x %s\n", linectr, u,
+				   cp));
+			continue;
+
+		}
+		if (buf[0] == 'L' && /*isspace(buf[1])*/ buf[1] == ' ') {
+			cp =  buf+2;
+			while (isspace(*cp))
+				cp++;
+			if (!isxdigit(*cp)) {
+				fprintf(stderr, "Invalid LANGID spec at line %u\n",
+					linectr);
+				continue;
+			}
+			u = strtoul(cp, &cp, 16);
+			while (isspace(*cp))
+				cp++;
+			if (!*cp) {
+				fprintf(stderr, "Invalid LANGID spec at line %u\n",
+					linectr);
+				continue;
+			}
+			if (new_langid(cp, u))
+				fprintf(stderr, "Duplicate LANGID spec at line %u language-id %04x %s\n",
+					linectr, u, cp);
+			DBG(printf("line %5u LANGID %02x %s\n", linectr, u,
+				   cp));
+			lasthut = lastclass = lastvendor = lastsubclass = -1;
+			lastlang = u;
+			continue;
+		}
 		if (buf[0] == 'C' && /*isspace(buf[1])*/ buf[1] == ' ') {
 			/* class spec */
 			cp = buf+2;
 			while (isspace(*cp))
 				cp++;
 			if (!isxdigit(*cp)) {
-				fprintf(stderr, "Invalid class spec at line %u\n", linectr);
+				fprintf(stderr, "Invalid class spec at line %u\n",
+					linectr);
 				continue;
 			}
 			u = strtoul(cp, &cp, 16);
 			while (isspace(*cp))
 				cp++;
 			if (!*cp) {
-				fprintf(stderr, "Invalid class spec at line %u\n", linectr);
+				fprintf(stderr, "Invalid class spec at line %u\n",
+					linectr);
 				continue;
 			}
 			if (new_class(cp, u))
-				fprintf(stderr, "Duplicate class spec at line %u class %04x %s\n", linectr, u, cp);
+				fprintf(stderr, "Duplicate class spec at line %u class %04x %s\n",
+					linectr, u, cp);
 			DBG(printf("line %5u class %02x %s\n", linectr, u, cp));
 			lasthut = lastlang = lastvendor = lastsubclass = -1;
 			lastclass = u;
@@ -600,41 +637,50 @@ static void parse(FILE *f)
 			while (isspace(*cp))
 				cp++;
 			if (!isxdigit(*cp)) {
-				fprintf(stderr, "Invalid audio terminal type at line %u\n", linectr);
+				fprintf(stderr, "Invalid audio terminal type at line %u\n",
+					linectr);
 				continue;
 			}
 			u = strtoul(cp, &cp, 16);
 			while (isspace(*cp))
 				cp++;
 			if (!*cp) {
-				fprintf(stderr, "Invalid audio terminal type at line %u\n", linectr);
+				fprintf(stderr, "Invalid audio terminal type at line %u\n",
+					linectr);
 				continue;
 			}
 			if (new_audioterminal(cp, u))
-				fprintf(stderr, "Duplicate audio terminal type spec at line %u terminal type %04x %s\n", linectr, u, cp);
-			DBG(printf("line %5u audio terminal type %02x %s\n", linectr, u, cp));
+				fprintf(stderr, "Duplicate audio terminal type spec at line %u terminal type %04x %s\n",
+					linectr, u, cp);
+			DBG(printf("line %5u audio terminal type %02x %s\n",
+				   linectr, u, cp));
 			continue;
 		}
-		if (buf[0] == 'H' && buf[1] == 'C' && buf[2] == 'C' && isspace(buf[3])) {
+		if (buf[0] == 'H' && buf[1] == 'C' && buf[2] == 'C'
+		    && isspace(buf[3])) {
 			/* HID Descriptor bCountryCode */
-                        cp =  buf+3;
-                        while (isspace(*cp))
-                                cp++;
-                        if (!isxdigit(*cp)) {
-                                fprintf(stderr, "Invalid HID country code at line %u\n", linectr);
-                                continue;
-                        }
-                        u = strtoul(cp, &cp, 10);
-                        while (isspace(*cp))
-                                cp++;
-                        if (!*cp) {
-                                fprintf(stderr, "Invalid HID country code at line %u\n", linectr);
-                                continue;
-                        }
-                        if (new_countrycode(cp, u))
-                                fprintf(stderr, "Duplicate HID country code at line %u country %02u %s\n", linectr, u, cp);
-                        DBG(printf("line %5u keyboard country code %02u %s\n", linectr, u, cp));
-                        continue;
+			cp =  buf+3;
+			while (isspace(*cp))
+				cp++;
+			if (!isxdigit(*cp)) {
+				fprintf(stderr, "Invalid HID country code at line %u\n",
+					linectr);
+				continue;
+			}
+			u = strtoul(cp, &cp, 10);
+			while (isspace(*cp))
+				cp++;
+			if (!*cp) {
+				fprintf(stderr, "Invalid HID country code at line %u\n",
+					linectr);
+				continue;
+			}
+			if (new_countrycode(cp, u))
+				fprintf(stderr, "Duplicate HID country code at line %u country %02u %s\n",
+					linectr, u, cp);
+			DBG(printf("line %5u keyboard country code %02u %s\n",
+				   linectr, u, cp));
+			continue;
 		}
 		if (isxdigit(*cp)) {
 			/* vendor */
@@ -642,12 +688,15 @@ static void parse(FILE *f)
 			while (isspace(*cp))
 				cp++;
 			if (!*cp) {
-				fprintf(stderr, "Invalid vendor spec at line %u\n", linectr);
+				fprintf(stderr, "Invalid vendor spec at line %u\n",
+					linectr);
 				continue;
 			}
 			if (new_vendor(cp, u))
-				fprintf(stderr, "Duplicate vendor spec at line %u vendor %04x %s\n", linectr, u, cp);
-			DBG(printf("line %5u vendor %04x %s\n", linectr, u, cp));
+				fprintf(stderr, "Duplicate vendor spec at line %u vendor %04x %s\n",
+					linectr, u, cp);
+			DBG(printf("line %5u vendor %04x %s\n", linectr, u,
+				   cp));
 			lastvendor = u;
 			lasthut = lastlang = lastclass = lastsubclass = -1;
 			continue;
@@ -658,33 +707,41 @@ static void parse(FILE *f)
 			while (isspace(*cp))
 				cp++;
 			if (!*cp) {
-				fprintf(stderr, "Invalid product/subclass spec at line %u\n", linectr);
+				fprintf(stderr, "Invalid product/subclass spec at line %u\n",
+					linectr);
 				continue;
 			}
 			if (lastvendor != -1) {
 				if (new_product(cp, lastvendor, u))
-					fprintf(stderr, "Duplicate product spec at line %u product %04x:%04x %s\n", linectr, lastvendor, u, cp);
-				DBG(printf("line %5u product %04x:%04x %s\n", linectr, lastvendor, u, cp));
+					fprintf(stderr, "Duplicate product spec at line %u product %04x:%04x %s\n",
+						linectr, lastvendor, u, cp);
+				DBG(printf("line %5u product %04x:%04x %s\n",
+					   linectr, lastvendor, u, cp));
 				continue;
 			}
 			if (lastclass != -1) {
 				if (new_subclass(cp, lastclass, u))
-					fprintf(stderr, "Duplicate subclass spec at line %u class %02x:%02x %s\n", linectr, lastclass, u, cp);
-				DBG(printf("line %5u subclass %02x:%02x %s\n", linectr, lastclass, u, cp));
+					fprintf(stderr, "Duplicate subclass spec at line %u class %02x:%02x %s\n",
+						linectr, lastclass, u, cp);
+				DBG(printf("line %5u subclass %02x:%02x %s\n",
+					   linectr, lastclass, u, cp));
 				lastsubclass = u;
 				continue;
 			}
 			if (lasthut != -1) {
 				if (new_hutus(cp, (lasthut << 16)+u))
-					fprintf(stderr, "Duplicate HUT Usage Spec at line %u\n", linectr);
+					fprintf(stderr, "Duplicate HUT Usage Spec at line %u\n",
+						linectr);
 				continue;
 			}
 			if (lastlang != -1) {
-                                if (new_langid(cp, lastlang+(u<<10)))
-                                        fprintf(stderr, "Duplicate LANGID Usage Spec at line %u\n", linectr);
-                                continue;
-                        }
-			fprintf(stderr, "Product/Subclass spec without prior Vendor/Class spec at line %u\n", linectr);
+				if (new_langid(cp, lastlang+(u<<10)))
+					fprintf(stderr, "Duplicate LANGID Usage Spec at line %u\n",
+						linectr);
+				continue;
+			}
+			fprintf(stderr, "Product/Subclass spec without prior Vendor/Class spec at line %u\n",
+				linectr);
 			continue;
 		}
 		if (buf[0] == '\t' && buf[1] == '\t' && isxdigit(buf[2])) {
@@ -693,84 +750,102 @@ static void parse(FILE *f)
 			while (isspace(*cp))
 				cp++;
 			if (!*cp) {
-				fprintf(stderr, "Invalid protocol spec at line %u\n", linectr);
+				fprintf(stderr, "Invalid protocol spec at line %u\n",
+					linectr);
 				continue;
 			}
 			if (lastclass != -1 && lastsubclass != -1) {
 				if (new_protocol(cp, lastclass, lastsubclass, u))
-					fprintf(stderr, "Duplicate protocol spec at line %u class %02x:%02x:%02x %s\n", linectr, lastclass, lastsubclass, u, cp);
-				DBG(printf("line %5u protocol %02x:%02x:%02x %s\n", linectr, lastclass, lastsubclass, u, cp));
+					fprintf(stderr, "Duplicate protocol spec at line %u class %02x:%02x:%02x %s\n",
+						linectr, lastclass, lastsubclass, u, cp);
+				DBG(printf("line %5u protocol %02x:%02x:%02x %s\n",
+					   linectr, lastclass, lastsubclass, u, cp));
 				continue;
 			}
-			fprintf(stderr, "Protocol spec without prior Class and Subclass spec at line %u\n", linectr);
+			fprintf(stderr, "Protocol spec without prior Class and Subclass spec at line %u\n",
+				linectr);
 			continue;
 		}
-		if (buf[0] == 'H' && buf[1] == 'I' && buf[2] == 'D' && /*isspace(buf[3])*/ buf[3] == ' ') {
+		if (buf[0] == 'H' && buf[1] == 'I' && buf[2] == 'D'
+		    && /*isspace(buf[3])*/ buf[3] == ' ') {
 			cp = buf + 4;
-                        while (isspace(*cp))
-                                cp++;
-                        if (!isxdigit(*cp)) {
-                                fprintf(stderr, "Invalid HID type at line %u\n", linectr);
-                                continue;
-                        }
-                        u = strtoul(cp, &cp, 16);
-                        while (isspace(*cp))
-                                cp++;
-                        if (!*cp) {
-                                fprintf(stderr, "Invalid HID type at line %u\n", linectr);
-                                continue;
-                        }
-                        if (new_hid(cp, u))
-                                fprintf(stderr, "Duplicate HID type spec at line %u terminal type %04x %s\n", linectr, u, cp);
-                        DBG(printf("line %5u HID type %02x %s\n", linectr, u, cp));
-                        continue;
+			while (isspace(*cp))
+				cp++;
+			if (!isxdigit(*cp)) {
+				fprintf(stderr, "Invalid HID type at line %u\n",
+					linectr);
+				continue;
+			}
+			u = strtoul(cp, &cp, 16);
+			while (isspace(*cp))
+				cp++;
+			if (!*cp) {
+				fprintf(stderr, "Invalid HID type at line %u\n",
+					linectr);
+				continue;
+			}
+			if (new_hid(cp, u))
+				fprintf(stderr, "Duplicate HID type spec at line %u terminal type %04x %s\n",
+					linectr, u, cp);
+			DBG(printf("line %5u HID type %02x %s\n", linectr, u,
+				   cp));
+			continue;
 
 		}
-                if (buf[0] == 'H' && buf[1] == 'U' && buf[2] == 'T' && /*isspace(buf[3])*/ buf[3] == ' ') {
-                        cp = buf + 4;
-                        while (isspace(*cp))
-                                cp++;
-                        if (!isxdigit(*cp)) {
-                                fprintf(stderr, "Invalid HUT type at line %u\n", linectr);
-                                continue;
-                        }
-                        u = strtoul(cp, &cp, 16);
-                        while (isspace(*cp))
-                                cp++;
-                        if (!*cp) {
-                                fprintf(stderr, "Invalid HUT type at line %u\n", linectr);
-                                continue;
-                        }
-                        if (new_huts(cp, u))
-                                fprintf(stderr, "Duplicate HUT type spec at line %u terminal type %04x %s\n", linectr, u, cp);
+		if (buf[0] == 'H' && buf[1] == 'U' && buf[2] == 'T'
+		    && /*isspace(buf[3])*/ buf[3] == ' ') {
+			cp = buf + 4;
+			while (isspace(*cp))
+				cp++;
+			if (!isxdigit(*cp)) {
+				fprintf(stderr, "Invalid HUT type at line %u\n",
+					linectr);
+				continue;
+			}
+			u = strtoul(cp, &cp, 16);
+			while (isspace(*cp))
+				cp++;
+			if (!*cp) {
+				fprintf(stderr, "Invalid HUT type at line %u\n",
+					linectr);
+				continue;
+			}
+			if (new_huts(cp, u))
+				fprintf(stderr, "Duplicate HUT type spec at line %u terminal type %04x %s\n",
+					linectr, u, cp);
 			lastlang = lastclass = lastvendor = lastsubclass = -1;
 			lasthut = u;
-                        DBG(printf("line %5u HUT type %02x %s\n", linectr, u, cp));
-                        continue;
-
-                }
-                if (buf[0] == 'R' && buf[1] == ' ') {
-                        cp = buf + 2;
-                        while (isspace(*cp))
-                                cp++;
-                        if (!isxdigit(*cp)) {
-                                fprintf(stderr, "Invalid Report type at line %u\n", linectr);
-                                continue;
-                        }
-                        u = strtoul(cp, &cp, 16);
-                        while (isspace(*cp))
-                                cp++;
-                        if (!*cp) {
-                                fprintf(stderr, "Invalid Report type at line %u\n", linectr);
-                                continue;
-                        }
-                        if (new_reporttag(cp, u))
-                                fprintf(stderr, "Duplicate Report type spec at line %u terminal type %04x %s\n", linectr, u, cp);
-                        DBG(printf("line %5u Report type %02x %s\n", linectr, u, cp));
-                        continue;
-
-                }
-                if (buf[0] == 'V' && buf[1] == 'T') {
+			DBG(printf("line %5u HUT type %02x %s\n", linectr, u,
+				   cp));
+			continue;
+
+		}
+		if (buf[0] == 'R' && buf[1] == ' ') {
+			cp = buf + 2;
+			while (isspace(*cp))
+				cp++;
+			if (!isxdigit(*cp)) {
+				fprintf(stderr, "Invalid Report type at line %u\n",
+					linectr);
+				continue;
+			}
+			u = strtoul(cp, &cp, 16);
+			while (isspace(*cp))
+				cp++;
+			if (!*cp) {
+				fprintf(stderr, "Invalid Report type at line %u\n",
+					linectr);
+				continue;
+			}
+			if (new_reporttag(cp, u))
+				fprintf(stderr, "Duplicate Report type spec at line %u terminal type %04x %s\n",
+					linectr, u, cp);
+			DBG(printf("line %5u Report type %02x %s\n", linectr,
+				   u, cp));
+			continue;
+
+		}
+		if (buf[0] == 'V' && buf[1] == 'T') {
 			/* add here */
 			continue;
 		}
@@ -784,9 +859,10 @@ int names_init(char *n)
 {
 	FILE *f;
 
-	if (!(f = fopen(n, "r"))) {
+	f = fopen(n, "r");
+	if (!f)
 		return errno;
-	}
+
 	parse(f);
 	fclose(f);
 	return 0;
diff --git a/drivers/staging/usbip/userspace/libsrc/names.h b/drivers/staging/usbip/userspace/libsrc/names.h
index 3a269fe..28dafc5 100644
--- a/drivers/staging/usbip/userspace/libsrc/names.h
+++ b/drivers/staging/usbip/userspace/libsrc/names.h
@@ -40,7 +40,8 @@ extern const char *names_vendor(u_int16_t vendorid);
 extern const char *names_product(u_int16_t vendorid, u_int16_t productid);
 extern const char *names_class(u_int8_t classid);
 extern const char *names_subclass(u_int8_t classid, u_int8_t subclassid);
-extern const char *names_protocol(u_int8_t classid, u_int8_t subclassid, u_int8_t protocolid);
+extern const char *names_protocol(u_int8_t classid, u_int8_t subclassid,
+				  u_int8_t protocolid);
 extern const char *names_audioterminal(u_int16_t termt);
 extern const char *names_hid(u_int8_t hidd);
 extern const char *names_reporttag(u_int8_t rt);
diff --git a/drivers/staging/usbip/userspace/libsrc/usbip_common.c b/drivers/staging/usbip/userspace/libsrc/usbip_common.c
index 154b4b1..17e08e0 100644
--- a/drivers/staging/usbip/userspace/libsrc/usbip_common.c
+++ b/drivers/staging/usbip/userspace/libsrc/usbip_common.c
@@ -8,9 +8,9 @@
 #undef  PROGNAME
 #define PROGNAME "libusbip"
 
-int usbip_use_syslog = 0;
-int usbip_use_stderr = 0;
-int usbip_use_debug  = 0;
+int usbip_use_syslog;
+int usbip_use_stderr;
+int usbip_use_debug;
 
 struct speed_string {
 	int num;
@@ -44,7 +44,7 @@ static struct portst_string portst_strings[] = {
 
 const char *usbip_status_string(int32_t status)
 {
-	for (int i=0; portst_strings[i].desc != NULL; i++)
+	for (int i = 0; portst_strings[i].desc != NULL; i++)
 		if (portst_strings[i].num == status)
 			return portst_strings[i].desc;
 
@@ -53,7 +53,7 @@ const char *usbip_status_string(int32_t status)
 
 const char *usbip_speed_string(int num)
 {
-	for (int i=0; speed_strings[i].speed != NULL; i++)
+	for (int i = 0; speed_strings[i].speed != NULL; i++)
 		if (speed_strings[i].num == num)
 			return speed_strings[i].desc;
 
@@ -109,7 +109,8 @@ void dump_usb_device(struct usbip_usb_device *udev)
 }
 
 
-int read_attr_value(struct sysfs_device *dev, const char *name, const char *format)
+int read_attr_value(struct sysfs_device *dev, const char *name,
+		    const char *format)
 {
 	char attrpath[SYSFS_PATH_MAX];
 	struct sysfs_attribute *attr;
@@ -172,7 +173,7 @@ int read_attr_speed(struct sysfs_device *dev)
 err:
 	sysfs_close_attribute(attr);
 
-	for (int i=0; speed_strings[i].speed != NULL; i++) {
+	for (int i = 0; speed_strings[i].speed != NULL; i++) {
 		if (!strcmp(speed, speed_strings[i].speed))
 			return speed_strings[i].num;
 	}
@@ -180,8 +181,11 @@ err:
 	return USB_SPEED_UNKNOWN;
 }
 
-#define READ_ATTR(object, type, dev, name, format)\
-	do { (object)->name = (type) read_attr_value(dev, to_string(name), format); } while (0)
+#define READ_ATTR(object, type, dev, name, format)			      \
+	do {								      \
+		(object)->name = (type) read_attr_value(dev, to_string(name), \
+							format);	      \
+	} while (0)
 
 
 int read_usb_device(struct sysfs_device *sdev, struct usbip_usb_device *udev)
@@ -245,7 +249,8 @@ void usbip_names_free()
 	names_free();
 }
 
-void usbip_names_get_product(char *buff, size_t size, uint16_t vendor, uint16_t product)
+void usbip_names_get_product(char *buff, size_t size, uint16_t vendor,
+			     uint16_t product)
 {
 	const char *prod, *vend;
 
@@ -261,7 +266,8 @@ void usbip_names_get_product(char *buff, size_t size, uint16_t vendor, uint16_t
 	snprintf(buff, size, "%s : %s (%04x:%04x)", vend, prod, vendor, product);
 }
 
-void usbip_names_get_class(char *buff, size_t size, uint8_t class, uint8_t subclass, uint8_t protocol)
+void usbip_names_get_class(char *buff, size_t size, uint8_t class,
+			   uint8_t subclass, uint8_t protocol)
 {
 	const char *c, *s, *p;
 
diff --git a/drivers/staging/usbip/userspace/libsrc/usbip_common.h b/drivers/staging/usbip/userspace/libsrc/usbip_common.h
index eedefbd..938ad1c 100644
--- a/drivers/staging/usbip/userspace/libsrc/usbip_common.h
+++ b/drivers/staging/usbip/userspace/libsrc/usbip_common.h
@@ -84,7 +84,7 @@ enum usb_device_speed {
 };
 
 /* FIXME: how to sync with drivers/usbip_common.h ? */
-enum usbip_device_status{
+enum usbip_device_status {
 	/* sdev is available. */
 	SDEV_ST_AVAILABLE = 0x01,
 	/* sdev is now used. */
@@ -132,7 +132,8 @@ struct usbip_usb_device {
 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_attr_value(struct sysfs_device *dev, const char *name,
+		    const char *format);
 int read_usb_interface(struct usbip_usb_device *udev, int i,
 		       struct usbip_usb_interface *uinf);
 
@@ -141,7 +142,9 @@ const char *usbip_status_string(int32_t status);
 
 int usbip_names_init(char *);
 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);
+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 /* __USBIP_COMMON_H */
diff --git a/drivers/staging/usbip/userspace/libsrc/vhci_driver.c b/drivers/staging/usbip/userspace/libsrc/vhci_driver.c
index 0958ba5..25e62e9 100644
--- a/drivers/staging/usbip/userspace/libsrc/vhci_driver.c
+++ b/drivers/staging/usbip/userspace/libsrc/vhci_driver.c
@@ -10,7 +10,8 @@
 
 struct usbip_vhci_driver *vhci_driver;
 
-static struct usbip_imported_device *imported_device_init(struct usbip_imported_device *idev, char *busid)
+static struct usbip_imported_device *
+imported_device_init(struct usbip_imported_device *idev, char *busid)
 {
 	struct sysfs_device *sudev;
 
@@ -29,14 +30,16 @@ static struct usbip_imported_device *imported_device_init(struct usbip_imported_
 		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 */
+			/*
+			 * alloc and copy because dlist is linked
+			 * from only one list
+			 */
 			new_cdev = calloc(1, sizeof(*new_cdev));
 			if (!new_cdev)
 				goto err;
 
 			memcpy(new_cdev, cdev, sizeof(*new_cdev));
-			dlist_unshift(idev->cdev_list, (void*) new_cdev);
+			dlist_unshift(idev->cdev_list, (void *) new_cdev);
 		}
 	}
 
@@ -101,7 +104,8 @@ static int parse_status(char *value)
 				return -1;
 			}
 
-			if (idev->status != VDEV_ST_NULL && idev->status != VDEV_ST_NOTASSIGNED) {
+			if (idev->status != VDEV_ST_NULL
+			    && idev->status != VDEV_ST_NOTASSIGNED) {
 				idev = imported_device_init(idev, lbusid);
 				if (!idev) {
 					dbg("imported_device_init failed");
@@ -126,8 +130,10 @@ static int parse_status(char *value)
 
 static int check_usbip_device(struct sysfs_class_device *cdev)
 {
-	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 */
+	/* /sys/class/video4linux/video0/device */
+	char class_path[SYSFS_PATH_MAX];
+	/* /sys/devices/platform/vhci_hcd/usb6/6-1:1.1 */
+	char dev_path[SYSFS_PATH_MAX];
 	int ret;
 	struct usbip_class_device *usbip_cdev;
 
@@ -289,25 +295,25 @@ static int get_nports(void)
 
 static int get_hc_busid(char *sysfs_mntpath, char *hc_busid)
 {
-        struct sysfs_driver *sdriver;
-        char sdriver_path[SYSFS_PATH_MAX];
+	struct sysfs_driver *sdriver;
+	char sdriver_path[SYSFS_PATH_MAX];
 
 	struct sysfs_device *hc_dev;
 	struct dlist *hc_devs;
 
 	int found = 0;
 
-        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);
+	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) {
+	sdriver = sysfs_open_driver_path(sdriver_path);
+	if (!sdriver) {
 		dbg("sysfs_open_driver_path failed: %s", sdriver_path);
-                dbg("make sure " USBIP_CORE_MOD_NAME ".ko and "
+		dbg("make sure " USBIP_CORE_MOD_NAME ".ko and "
 		    USBIP_VHCI_DRV_NAME ".ko are loaded!");
-                return -1;
-        }
+		return -1;
+	}
 
 	hc_devs = sysfs_get_driver_devices(sdriver);
 	if (!hc_devs) {
diff --git a/drivers/staging/usbip/userspace/src/usbip_detach.c b/drivers/staging/usbip/userspace/src/usbip_detach.c
index dac5f06..13308df 100644
--- a/drivers/staging/usbip/userspace/src/usbip_detach.c
+++ b/drivers/staging/usbip/userspace/src/usbip_detach.c
@@ -49,7 +49,7 @@ static int detach_port(char *port)
 	uint8_t portnum;
 	char path[PATH_MAX+1];
 
-	for (unsigned int i=0; i < strlen(port); i++)
+	for (unsigned int i = 0; i < strlen(port); i++)
 		if (!isdigit(port[i])) {
 			err("invalid port %s", port);
 			return -1;
diff --git a/drivers/staging/usbip/userspace/src/usbip_network.c b/drivers/staging/usbip/userspace/src/usbip_network.c
index 1a84dd3..4cb76e5 100644
--- a/drivers/staging/usbip/userspace/src/usbip_network.c
+++ b/drivers/staging/usbip/userspace/src/usbip_network.c
@@ -56,7 +56,7 @@ void usbip_net_pack_usb_device(int pack, struct usbip_usb_device *udev)
 {
 	usbip_net_pack_uint32_t(pack, &udev->busnum);
 	usbip_net_pack_uint32_t(pack, &udev->devnum);
-	usbip_net_pack_uint32_t(pack, &udev->speed );
+	usbip_net_pack_uint32_t(pack, &udev->speed);
 
 	usbip_net_pack_uint16_t(pack, &udev->idVendor);
 	usbip_net_pack_uint16_t(pack, &udev->idProduct);
diff --git a/drivers/staging/usbip/userspace/src/usbip_network.h b/drivers/staging/usbip/userspace/src/usbip_network.h
index 2d1e070..1bbefc9 100644
--- a/drivers/staging/usbip/userspace/src/usbip_network.h
+++ b/drivers/staging/usbip/userspace/src/usbip_network.h
@@ -35,8 +35,8 @@ struct op_common {
 
 #define PACK_OP_COMMON(pack, op_common)  do {\
 	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 );\
+	usbip_net_pack_uint16_t(pack, &(op_common)->code);\
+	usbip_net_pack_uint32_t(pack, &(op_common)->status);\
 } while (0)
 
 /* ---------------------------------------------------------------------- */
diff --git a/drivers/staging/usbip/userspace/src/usbipd.c b/drivers/staging/usbip/userspace/src/usbipd.c
index 34760cc..cc3be17 100644
--- a/drivers/staging/usbip/userspace/src/usbipd.c
+++ b/drivers/staging/usbip/userspace/src/usbipd.c
@@ -60,7 +60,7 @@ static const char usbipd_help_string[] =
 	"	-d, --debug				\n"
 	"		Print debugging information.	\n"
 	"						\n"
-	"	-h, --help 				\n"
+	"	-h, --help				\n"
 	"		Print this help.		\n"
 	"						\n"
 	"	-v, --version				\n"
@@ -446,7 +446,7 @@ static int do_standalone_mode(int daemonize)
 	}
 
 	if (daemonize) {
-		if (daemon(0,0) < 0) {
+		if (daemon(0, 0) < 0) {
 			err("daemonizing failed: %s", strerror(errno));
 			return -1;
 		}
diff --git a/drivers/staging/usbip/vhci_hcd.c b/drivers/staging/usbip/vhci_hcd.c
index f1ca084..d7974cb 100644
--- a/drivers/staging/usbip/vhci_hcd.c
+++ b/drivers/staging/usbip/vhci_hcd.c
@@ -956,11 +956,10 @@ static int vhci_bus_resume(struct usb_hcd *hcd)
 	dev_dbg(&hcd->self.root_hub->dev, "%s\n", __func__);
 
 	spin_lock(&vhci->lock);
-	if (!HCD_HW_ACCESSIBLE(hcd)) {
+	if (!HCD_HW_ACCESSIBLE(hcd))
 		rc = -ESHUTDOWN;
-	} else {
+	else
 		hcd->state = HC_STATE_RUNNING;
-	}
 	spin_unlock(&vhci->lock);
 
 	return rc;
diff --git a/drivers/staging/vme/devices/vme_user.c b/drivers/staging/vme/devices/vme_user.c
index d074b1e..da7f759 100644
--- a/drivers/staging/vme/devices/vme_user.c
+++ b/drivers/staging/vme/devices/vme_user.c
@@ -710,6 +710,10 @@ static int vme_user_probe(struct vme_dev *vdev)
 
 	/* Register the driver as a char device */
 	vme_user_cdev = cdev_alloc();
+	if (!vme_user_cdev) {
+		err = -ENOMEM;
+		goto err_char;
+	}
 	vme_user_cdev->ops = &vme_user_fops;
 	vme_user_cdev->owner = THIS_MODULE;
 	err = cdev_add(vme_user_cdev, MKDEV(VME_MAJOR, 0), VME_DEVS);
diff --git a/drivers/staging/vt6655/80211hdr.h b/drivers/staging/vt6655/80211hdr.h
index c4d2349..28078a1 100644
--- a/drivers/staging/vt6655/80211hdr.h
+++ b/drivers/staging/vt6655/80211hdr.h
@@ -86,7 +86,6 @@
 #define WLAN_DATA_MAXLEN            2312
 #define WLAN_A3FR_MAXLEN            (WLAN_HDR_ADDR3_LEN + WLAN_DATA_MAXLEN + WLAN_CRC_LEN)
 
-
 #define WLAN_BEACON_FR_MAXLEN       WLAN_A3FR_MAXLEN
 #define WLAN_ATIM_FR_MAXLEN         (WLAN_HDR_ADDR3_LEN + 0)
 #define WLAN_NULLDATA_FR_MAXLEN     (WLAN_HDR_ADDR3_LEN + 0)
@@ -100,7 +99,6 @@
 #define WLAN_AUTHEN_FR_MAXLEN       WLAN_A3FR_MAXLEN
 #define WLAN_DEAUTHEN_FR_MAXLEN     (WLAN_HDR_ADDR3_LEN + 2)
 
-
 #define WLAN_WEP_NKEYS              4
 #define WLAN_WEP40_KEYLEN           5
 #define WLAN_WEP104_KEYLEN          13
@@ -122,7 +120,6 @@
 #define WLAN_FTYPE_CTL  0x01
 #define WLAN_FTYPE_DATA 0x02
 
-
 /* Frame Subtypes */
 #define WLAN_FSTYPE_ASSOCREQ        0x00
 #define WLAN_FSTYPE_ASSOCRESP       0x01
@@ -155,7 +152,6 @@
 #define WLAN_FSTYPE_CFPOLL          0x06
 #define WLAN_FSTYPE_CFACK_CFPOLL    0x07
 
-
 #ifdef __BIG_ENDIAN
 
 /* GET & SET Frame Control bit */
@@ -175,7 +171,6 @@
 #define WLAN_GET_SEQ_FRGNUM(n) (((unsigned short)(n) >> 8) & (BIT0|BIT1|BIT2|BIT3))
 #define WLAN_GET_SEQ_SEQNUM(n) ((((unsigned short)(n) >> 8) & (~(BIT0|BIT1|BIT2|BIT3))) >> 4)
 
-
 /* Capability Field bit */
 #define WLAN_GET_CAP_INFO_ESS(n)           (((n) >> 8) & BIT0)
 #define WLAN_GET_CAP_INFO_IBSS(n)          ((((n) >> 8) & BIT1) >> 1)
@@ -190,7 +185,6 @@
 #define WLAN_GET_CAP_INFO_DSSSOFDM(n)      ((((n))      & BIT13) >> 13)
 #define WLAN_GET_CAP_INFO_GRPACK(n)        ((((n))      & BIT14) >> 14)
 
-
 #else
 
 /* GET & SET Frame Control bit */
@@ -206,12 +200,10 @@
 #define WLAN_GET_FC_ISWEP(n)    ((((unsigned short)(n)) & (BIT14)) >> 14)
 #define WLAN_GET_FC_ORDER(n)    ((((unsigned short)(n)) & (BIT15)) >> 15)
 
-
 /* Sequence Field bit */
 #define WLAN_GET_SEQ_FRGNUM(n) (((unsigned short)(n)) & (BIT0|BIT1|BIT2|BIT3))
 #define WLAN_GET_SEQ_SEQNUM(n) ((((unsigned short)(n)) & (~(BIT0|BIT1|BIT2|BIT3))) >> 4)
 
-
 /* Capability Field bit */
 #define WLAN_GET_CAP_INFO_ESS(n)           ((n) & BIT0)
 #define WLAN_GET_CAP_INFO_IBSS(n)          (((n) & BIT1) >> 1)
@@ -226,10 +218,8 @@
 #define WLAN_GET_CAP_INFO_DSSSOFDM(n)      (((n) & BIT13) >> 13)
 #define WLAN_GET_CAP_INFO_GRPACK(n)        (((n) & BIT14) >> 14)
 
-
 #endif /*#ifdef __BIG_ENDIAN */
 
-
 #define WLAN_SET_CAP_INFO_ESS(n)           (n)
 #define WLAN_SET_CAP_INFO_IBSS(n)          ((n) << 1)
 #define WLAN_SET_CAP_INFO_CFPOLLABLE(n)    ((n) << 2)
@@ -243,7 +233,6 @@
 #define WLAN_SET_CAP_INFO_DSSSOFDM(n)      ((n) << 13)
 #define WLAN_SET_CAP_INFO_GRPACK(n)        ((n) << 14)
 
-
 #define WLAN_SET_FC_PRVER(n)    ((unsigned short)(n))
 #define WLAN_SET_FC_FTYPE(n)    (((unsigned short)(n)) << 2)
 #define WLAN_SET_FC_FSTYPE(n)   (((unsigned short)(n)) << 4)
@@ -269,8 +258,6 @@
 #define WLAN_SET_ERP_USE_PROTECTION(n)     ((n) << 1)
 #define WLAN_SET_ERP_BARKER_MODE(n)        ((n) << 2)
 
-
-
 /* Support & Basic Rates field */
 #define WLAN_MGMT_IS_BASICRATE(b)    ((b) & BIT7)
 #define WLAN_MGMT_GET_RATE(b)        ((b) & ~BIT7)
@@ -288,64 +275,50 @@
 #define IEEE_ADDR_GROUP             0x01
 
 typedef struct {
-    unsigned char abyAddr[6];
+	unsigned char abyAddr[6];
 } IEEE_ADDR, *PIEEE_ADDR;
 
 /* 802.11 Header Format */
 
 typedef struct tagWLAN_80211HDR_A2 {
-
-    unsigned short wFrameCtl;
-    unsigned short wDurationID;
-    unsigned char abyAddr1[WLAN_ADDR_LEN];
-    unsigned char abyAddr2[WLAN_ADDR_LEN];
-
+	unsigned short wFrameCtl;
+	unsigned short wDurationID;
+	unsigned char abyAddr1[WLAN_ADDR_LEN];
+	unsigned char abyAddr2[WLAN_ADDR_LEN];
 } __attribute__ ((__packed__))
 WLAN_80211HDR_A2, *PWLAN_80211HDR_A2;
 
 typedef struct tagWLAN_80211HDR_A3 {
-
-    unsigned short wFrameCtl;
-    unsigned short wDurationID;
-    unsigned char abyAddr1[WLAN_ADDR_LEN];
-    unsigned char abyAddr2[WLAN_ADDR_LEN];
-    unsigned char abyAddr3[WLAN_ADDR_LEN];
-    unsigned short wSeqCtl;
-
-}__attribute__ ((__packed__))
+	unsigned short wFrameCtl;
+	unsigned short wDurationID;
+	unsigned char abyAddr1[WLAN_ADDR_LEN];
+	unsigned char abyAddr2[WLAN_ADDR_LEN];
+	unsigned char abyAddr3[WLAN_ADDR_LEN];
+	unsigned short wSeqCtl;
+} __attribute__ ((__packed__))
 WLAN_80211HDR_A3, *PWLAN_80211HDR_A3;
 
 typedef struct tagWLAN_80211HDR_A4 {
-
-    unsigned short wFrameCtl;
-    unsigned short wDurationID;
-    unsigned char abyAddr1[WLAN_ADDR_LEN];
-    unsigned char abyAddr2[WLAN_ADDR_LEN];
-    unsigned char abyAddr3[WLAN_ADDR_LEN];
-    unsigned short wSeqCtl;
-    unsigned char abyAddr4[WLAN_ADDR_LEN];
-
+	unsigned short wFrameCtl;
+	unsigned short wDurationID;
+	unsigned char abyAddr1[WLAN_ADDR_LEN];
+	unsigned char abyAddr2[WLAN_ADDR_LEN];
+	unsigned char abyAddr3[WLAN_ADDR_LEN];
+	unsigned short wSeqCtl;
+	unsigned char abyAddr4[WLAN_ADDR_LEN];
 } __attribute__ ((__packed__))
 WLAN_80211HDR_A4, *PWLAN_80211HDR_A4;
 
-
 typedef union tagUWLAN_80211HDR {
-
-    WLAN_80211HDR_A2        sA2;
-    WLAN_80211HDR_A3        sA3;
-    WLAN_80211HDR_A4        sA4;
-
+	WLAN_80211HDR_A2        sA2;
+	WLAN_80211HDR_A3        sA3;
+	WLAN_80211HDR_A4        sA4;
 } UWLAN_80211HDR, *PUWLAN_80211HDR;
 
-
 /*---------------------  Export Classes  ----------------------------*/
 
 /*---------------------  Export Variables  --------------------------*/
 
 /*---------------------  Export Functions  --------------------------*/
 
-
-
 #endif /* __80211HDR_H__ */
-
-
diff --git a/drivers/staging/vt6655/80211mgr.c b/drivers/staging/vt6655/80211mgr.c
index 1ed0f26..4cb26f3 100644
--- a/drivers/staging/vt6655/80211mgr.c
+++ b/drivers/staging/vt6655/80211mgr.c
@@ -61,24 +61,18 @@
 
 /*---------------------  Static Definitions -------------------------*/
 
-
-
 /*---------------------  Static Classes  ----------------------------*/
 
 /*---------------------  Static Variables  --------------------------*/
 
-static int          msglevel                =MSG_LEVEL_INFO;
+static int msglevel = MSG_LEVEL_INFO;
 //static int          msglevel                =MSG_LEVEL_DEBUG;
 /*---------------------  Static Functions  --------------------------*/
 
-
-
 /*---------------------  Export Variables  --------------------------*/
 
-
 /*---------------------  Export Functions  --------------------------*/
 
-
 /*+
  *
  * Routine Description:
@@ -87,26 +81,26 @@ static int          msglevel                =MSG_LEVEL_INFO;
  * Return Value:
  *    None.
  *
--*/
+ -*/
 
 void
 vMgrEncodeBeacon(
-    PWLAN_FR_BEACON  pFrame
-     )
+	PWLAN_FR_BEACON  pFrame
+)
 {
-    pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
+	pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
 
-    // Fixed Fields
-    pFrame->pqwTimestamp = (PQWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
-                                    + WLAN_BEACON_OFF_TS);
-    pFrame->pwBeaconInterval = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
-                                       + WLAN_BEACON_OFF_BCN_INT);
-    pFrame->pwCapInfo = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
-                                + WLAN_BEACON_OFF_CAPINFO);
+	// Fixed Fields
+	pFrame->pqwTimestamp = (PQWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+					+ WLAN_BEACON_OFF_TS);
+	pFrame->pwBeaconInterval = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+						      + WLAN_BEACON_OFF_BCN_INT);
+	pFrame->pwCapInfo = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+					       + WLAN_BEACON_OFF_CAPINFO);
 
-    pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_BEACON_OFF_SSID;
+	pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_BEACON_OFF_SSID;
 
-    return;
+	return;
 }
 
 /*+
@@ -118,118 +112,115 @@ vMgrEncodeBeacon(
  * Return Value:
  *    None.
  *
--*/
-
+ -*/
 
 void
 vMgrDecodeBeacon(
-    PWLAN_FR_BEACON  pFrame
-    )
+	PWLAN_FR_BEACON  pFrame
+)
 {
-    PWLAN_IE        pItem;
-
-    pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
-
-    // Fixed Fields
-    pFrame->pqwTimestamp = (PQWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
-                                    + WLAN_BEACON_OFF_TS);
-    pFrame->pwBeaconInterval = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
-                                       + WLAN_BEACON_OFF_BCN_INT);
-    pFrame->pwCapInfo = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
-                                + WLAN_BEACON_OFF_CAPINFO);
-
-    // Information elements
-    pItem = (PWLAN_IE)((unsigned char *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)))
-                       + WLAN_BEACON_OFF_SSID);
-    while( ((unsigned char *)pItem) < (pFrame->pBuf + pFrame->len) ){
-
-        switch (pItem->byElementID) {
-            case WLAN_EID_SSID:
-                if (pFrame->pSSID == NULL)
-                    pFrame->pSSID = (PWLAN_IE_SSID)pItem;
-                break;
-            case WLAN_EID_SUPP_RATES:
-                if (pFrame->pSuppRates == NULL)
-                    pFrame->pSuppRates = (PWLAN_IE_SUPP_RATES)pItem;
-                break;
-            case WLAN_EID_FH_PARMS:
-                //pFrame->pFHParms = (PWLAN_IE_FH_PARMS)pItem;
-                break;
-            case WLAN_EID_DS_PARMS:
-                if (pFrame->pDSParms == NULL)
-                    pFrame->pDSParms = (PWLAN_IE_DS_PARMS)pItem;
-                break;
-            case WLAN_EID_CF_PARMS:
-                if (pFrame->pCFParms == NULL)
-                    pFrame->pCFParms = (PWLAN_IE_CF_PARMS)pItem;
-                break;
-            case WLAN_EID_IBSS_PARMS:
-                if (pFrame->pIBSSParms == NULL)
-                    pFrame->pIBSSParms = (PWLAN_IE_IBSS_PARMS)pItem;
-                break;
-            case WLAN_EID_TIM:
-                if (pFrame->pTIM == NULL)
-                    pFrame->pTIM = (PWLAN_IE_TIM)pItem;
-                break;
-
-            case WLAN_EID_RSN:
-                if (pFrame->pRSN == NULL) {
-                    pFrame->pRSN = (PWLAN_IE_RSN)pItem;
-                }
-                break;
-            case WLAN_EID_RSN_WPA:
-                if (pFrame->pRSNWPA == NULL) {
-                    if (WPAb_Is_RSN((PWLAN_IE_RSN_EXT)pItem) == true)
-                        pFrame->pRSNWPA = (PWLAN_IE_RSN_EXT)pItem;
-                }
-                break;
-
-            case WLAN_EID_ERP:
-                if (pFrame->pERP == NULL)
-                    pFrame->pERP = (PWLAN_IE_ERP)pItem;
-                break;
-            case WLAN_EID_EXTSUPP_RATES:
-                if (pFrame->pExtSuppRates == NULL)
-                    pFrame->pExtSuppRates = (PWLAN_IE_SUPP_RATES)pItem;
-                break;
-
-            case WLAN_EID_COUNTRY:      //7
-                if (pFrame->pIE_Country == NULL)
-                    pFrame->pIE_Country = (PWLAN_IE_COUNTRY)pItem;
-                break;
-
-            case WLAN_EID_PWR_CONSTRAINT:   //32
-                if (pFrame->pIE_PowerConstraint == NULL)
-                    pFrame->pIE_PowerConstraint = (PWLAN_IE_PW_CONST)pItem;
-                break;
-
-            case WLAN_EID_CH_SWITCH:    //37
-                if (pFrame->pIE_CHSW == NULL)
-                    pFrame->pIE_CHSW = (PWLAN_IE_CH_SW)pItem;
-                break;
-
-            case WLAN_EID_QUIET:        //40
-                if (pFrame->pIE_Quiet == NULL)
-                    pFrame->pIE_Quiet = (PWLAN_IE_QUIET)pItem;
-                break;
-
-            case WLAN_EID_IBSS_DFS:
-                if (pFrame->pIE_IBSSDFS == NULL)
-                    pFrame->pIE_IBSSDFS = (PWLAN_IE_IBSS_DFS)pItem;
-                break;
-
-            default:
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Unrecognized EID=%dd in beacon decode.\n", pItem->byElementID);
-                break;
-
-        }
-        pItem = (PWLAN_IE)(((unsigned char *)pItem) + 2 + pItem->len);
-    }
-
-    return;
+	PWLAN_IE        pItem;
+
+	pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
+
+	// Fixed Fields
+	pFrame->pqwTimestamp = (PQWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+					+ WLAN_BEACON_OFF_TS);
+	pFrame->pwBeaconInterval = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+						      + WLAN_BEACON_OFF_BCN_INT);
+	pFrame->pwCapInfo = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+					       + WLAN_BEACON_OFF_CAPINFO);
+
+	// Information elements
+	pItem = (PWLAN_IE)((unsigned char *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)))
+			   + WLAN_BEACON_OFF_SSID);
+	while (((unsigned char *)pItem) < (pFrame->pBuf + pFrame->len)) {
+		switch (pItem->byElementID) {
+		case WLAN_EID_SSID:
+			if (pFrame->pSSID == NULL)
+				pFrame->pSSID = (PWLAN_IE_SSID)pItem;
+			break;
+		case WLAN_EID_SUPP_RATES:
+			if (pFrame->pSuppRates == NULL)
+				pFrame->pSuppRates = (PWLAN_IE_SUPP_RATES)pItem;
+			break;
+		case WLAN_EID_FH_PARMS:
+			//pFrame->pFHParms = (PWLAN_IE_FH_PARMS)pItem;
+			break;
+		case WLAN_EID_DS_PARMS:
+			if (pFrame->pDSParms == NULL)
+				pFrame->pDSParms = (PWLAN_IE_DS_PARMS)pItem;
+			break;
+		case WLAN_EID_CF_PARMS:
+			if (pFrame->pCFParms == NULL)
+				pFrame->pCFParms = (PWLAN_IE_CF_PARMS)pItem;
+			break;
+		case WLAN_EID_IBSS_PARMS:
+			if (pFrame->pIBSSParms == NULL)
+				pFrame->pIBSSParms = (PWLAN_IE_IBSS_PARMS)pItem;
+			break;
+		case WLAN_EID_TIM:
+			if (pFrame->pTIM == NULL)
+				pFrame->pTIM = (PWLAN_IE_TIM)pItem;
+			break;
+
+		case WLAN_EID_RSN:
+			if (pFrame->pRSN == NULL) {
+				pFrame->pRSN = (PWLAN_IE_RSN)pItem;
+			}
+			break;
+		case WLAN_EID_RSN_WPA:
+			if (pFrame->pRSNWPA == NULL) {
+				if (WPAb_Is_RSN((PWLAN_IE_RSN_EXT)pItem) == true)
+					pFrame->pRSNWPA = (PWLAN_IE_RSN_EXT)pItem;
+			}
+			break;
+
+		case WLAN_EID_ERP:
+			if (pFrame->pERP == NULL)
+				pFrame->pERP = (PWLAN_IE_ERP)pItem;
+			break;
+		case WLAN_EID_EXTSUPP_RATES:
+			if (pFrame->pExtSuppRates == NULL)
+				pFrame->pExtSuppRates = (PWLAN_IE_SUPP_RATES)pItem;
+			break;
+
+		case WLAN_EID_COUNTRY:      //7
+			if (pFrame->pIE_Country == NULL)
+				pFrame->pIE_Country = (PWLAN_IE_COUNTRY)pItem;
+			break;
+
+		case WLAN_EID_PWR_CONSTRAINT:   //32
+			if (pFrame->pIE_PowerConstraint == NULL)
+				pFrame->pIE_PowerConstraint = (PWLAN_IE_PW_CONST)pItem;
+			break;
+
+		case WLAN_EID_CH_SWITCH:    //37
+			if (pFrame->pIE_CHSW == NULL)
+				pFrame->pIE_CHSW = (PWLAN_IE_CH_SW)pItem;
+			break;
+
+		case WLAN_EID_QUIET:        //40
+			if (pFrame->pIE_Quiet == NULL)
+				pFrame->pIE_Quiet = (PWLAN_IE_QUIET)pItem;
+			break;
+
+		case WLAN_EID_IBSS_DFS:
+			if (pFrame->pIE_IBSSDFS == NULL)
+				pFrame->pIE_IBSSDFS = (PWLAN_IE_IBSS_DFS)pItem;
+			break;
+
+		default:
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Unrecognized EID=%dd in beacon decode.\n", pItem->byElementID);
+			break;
+
+		}
+		pItem = (PWLAN_IE)(((unsigned char *)pItem) + 2 + pItem->len);
+	}
+
+	return;
 }
 
-
 /*+
  *
  * Routine Description:
@@ -239,21 +230,19 @@ vMgrDecodeBeacon(
  * Return Value:
  *    None.
  *
--*/
-
+ -*/
 
 void
 vMgrEncodeIBSSATIM(
-    PWLAN_FR_IBSSATIM   pFrame
-    )
+	PWLAN_FR_IBSSATIM   pFrame
+)
 {
-    pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
-    pFrame->len = WLAN_HDR_ADDR3_LEN;
+	pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
+	pFrame->len = WLAN_HDR_ADDR3_LEN;
 
-    return;
+	return;
 }
 
-
 /*+
  *
  * Routine Description:
@@ -263,19 +252,18 @@ vMgrEncodeIBSSATIM(
  * Return Value:
  *    None.
  *
--*/
+ -*/
 
 void
 vMgrDecodeIBSSATIM(
-    PWLAN_FR_IBSSATIM   pFrame
-    )
+	PWLAN_FR_IBSSATIM   pFrame
+)
 {
-    pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
+	pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
 
-    return;
+	return;
 }
 
-
 /*+
  *
  * Routine Description:
@@ -285,25 +273,23 @@ vMgrDecodeIBSSATIM(
  * Return Value:
  *    None.
  *
--*/
+ -*/
 
 void
 vMgrEncodeDisassociation(
-    PWLAN_FR_DISASSOC  pFrame
-    )
+	PWLAN_FR_DISASSOC  pFrame
+)
 {
-    pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
+	pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
 
+	// Fixed Fields
+	pFrame->pwReason = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+					      + WLAN_DISASSOC_OFF_REASON);
+	pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_DISASSOC_OFF_REASON + sizeof(*(pFrame->pwReason));
 
-    // Fixed Fields
-    pFrame->pwReason = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
-                               + WLAN_DISASSOC_OFF_REASON);
-    pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_DISASSOC_OFF_REASON + sizeof(*(pFrame->pwReason));
-
-    return;
+	return;
 }
 
-
 /*+
  *
  * Routine Description:
@@ -313,20 +299,20 @@ vMgrEncodeDisassociation(
  * Return Value:
  *    None.
  *
--*/
+ -*/
 
 void
 vMgrDecodeDisassociation(
-    PWLAN_FR_DISASSOC  pFrame
-    )
+	PWLAN_FR_DISASSOC  pFrame
+)
 {
-    pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
+	pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
 
-    // Fixed Fields
-    pFrame->pwReason = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
-                               + WLAN_DISASSOC_OFF_REASON);
+	// Fixed Fields
+	pFrame->pwReason = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+					      + WLAN_DISASSOC_OFF_REASON);
 
-    return;
+	return;
 }
 
 /*+
@@ -338,25 +324,23 @@ vMgrDecodeDisassociation(
  * Return Value:
  *    None.
  *
--*/
-
+ -*/
 
 void
 vMgrEncodeAssocRequest(
-    PWLAN_FR_ASSOCREQ  pFrame
-    )
+	PWLAN_FR_ASSOCREQ  pFrame
+)
 {
-    pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
-    // Fixed Fields
-    pFrame->pwCapInfo = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
-                                + WLAN_ASSOCREQ_OFF_CAP_INFO);
-    pFrame->pwListenInterval = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
-                                       + WLAN_ASSOCREQ_OFF_LISTEN_INT);
-    pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_ASSOCREQ_OFF_LISTEN_INT + sizeof(*(pFrame->pwListenInterval));
-    return;
+	pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
+	// Fixed Fields
+	pFrame->pwCapInfo = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+					       + WLAN_ASSOCREQ_OFF_CAP_INFO);
+	pFrame->pwListenInterval = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+						      + WLAN_ASSOCREQ_OFF_LISTEN_INT);
+	pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_ASSOCREQ_OFF_LISTEN_INT + sizeof(*(pFrame->pwListenInterval));
+	return;
 }
 
-
 /*+
  *
  * Routine Description: (AP)
@@ -366,61 +350,61 @@ vMgrEncodeAssocRequest(
  * Return Value:
  *    None.
  *
--*/
+ -*/
 
 void
 vMgrDecodeAssocRequest(
-    PWLAN_FR_ASSOCREQ  pFrame
-    )
+	PWLAN_FR_ASSOCREQ  pFrame
+)
 {
-    PWLAN_IE   pItem;
-
-    pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
-    // Fixed Fields
-    pFrame->pwCapInfo = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
-                                + WLAN_ASSOCREQ_OFF_CAP_INFO);
-    pFrame->pwListenInterval = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
-                                + WLAN_ASSOCREQ_OFF_LISTEN_INT);
-
-    // Information elements
-    pItem = (PWLAN_IE)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
-                            + WLAN_ASSOCREQ_OFF_SSID);
-
-    while (((unsigned char *)pItem) < (pFrame->pBuf + pFrame->len)) {
-        switch (pItem->byElementID){
-            case WLAN_EID_SSID:
-                if (pFrame->pSSID == NULL)
-                    pFrame->pSSID = (PWLAN_IE_SSID)pItem;
-                break;
-            case WLAN_EID_SUPP_RATES:
-                if (pFrame->pSuppRates == NULL)
-                    pFrame->pSuppRates = (PWLAN_IE_SUPP_RATES)pItem;
-                break;
-
-            case WLAN_EID_RSN:
-                if (pFrame->pRSN == NULL) {
-                    pFrame->pRSN = (PWLAN_IE_RSN)pItem;
-                }
-                break;
-            case WLAN_EID_RSN_WPA:
-                if (pFrame->pRSNWPA == NULL) {
-                    if (WPAb_Is_RSN((PWLAN_IE_RSN_EXT)pItem) == true)
-                        pFrame->pRSNWPA = (PWLAN_IE_RSN_EXT)pItem;
-                }
-                break;
-            case WLAN_EID_EXTSUPP_RATES:
-                if (pFrame->pExtSuppRates == NULL)
-                    pFrame->pExtSuppRates = (PWLAN_IE_SUPP_RATES)pItem;
-                break;
-
-            default:
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Unrecognized EID=%dd in assocreq decode.\n",
-                        pItem->byElementID);
-                break;
-        }
-        pItem = (PWLAN_IE)(((unsigned char *)pItem) + 2 + pItem->len);
-    }
-    return;
+	PWLAN_IE   pItem;
+
+	pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
+	// Fixed Fields
+	pFrame->pwCapInfo = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+					       + WLAN_ASSOCREQ_OFF_CAP_INFO);
+	pFrame->pwListenInterval = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+						      + WLAN_ASSOCREQ_OFF_LISTEN_INT);
+
+	// Information elements
+	pItem = (PWLAN_IE)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+			   + WLAN_ASSOCREQ_OFF_SSID);
+
+	while (((unsigned char *)pItem) < (pFrame->pBuf + pFrame->len)) {
+		switch (pItem->byElementID) {
+		case WLAN_EID_SSID:
+			if (pFrame->pSSID == NULL)
+				pFrame->pSSID = (PWLAN_IE_SSID)pItem;
+			break;
+		case WLAN_EID_SUPP_RATES:
+			if (pFrame->pSuppRates == NULL)
+				pFrame->pSuppRates = (PWLAN_IE_SUPP_RATES)pItem;
+			break;
+
+		case WLAN_EID_RSN:
+			if (pFrame->pRSN == NULL) {
+				pFrame->pRSN = (PWLAN_IE_RSN)pItem;
+			}
+			break;
+		case WLAN_EID_RSN_WPA:
+			if (pFrame->pRSNWPA == NULL) {
+				if (WPAb_Is_RSN((PWLAN_IE_RSN_EXT)pItem) == true)
+					pFrame->pRSNWPA = (PWLAN_IE_RSN_EXT)pItem;
+			}
+			break;
+		case WLAN_EID_EXTSUPP_RATES:
+			if (pFrame->pExtSuppRates == NULL)
+				pFrame->pExtSuppRates = (PWLAN_IE_SUPP_RATES)pItem;
+			break;
+
+		default:
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Unrecognized EID=%dd in assocreq decode.\n",
+				pItem->byElementID);
+			break;
+		}
+		pItem = (PWLAN_IE)(((unsigned char *)pItem) + 2 + pItem->len);
+	}
+	return;
 }
 
 /*+
@@ -432,29 +416,28 @@ vMgrDecodeAssocRequest(
  * Return Value:
  *    None.
  *
--*/
+ -*/
 
 void
 vMgrEncodeAssocResponse(
-    PWLAN_FR_ASSOCRESP  pFrame
-     )
+	PWLAN_FR_ASSOCRESP  pFrame
+)
 {
-    pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
-
-    // Fixed Fields
-    pFrame->pwCapInfo = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
-                                + WLAN_ASSOCRESP_OFF_CAP_INFO);
-    pFrame->pwStatus = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
-                               + WLAN_ASSOCRESP_OFF_STATUS);
-    pFrame->pwAid = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
-                            + WLAN_ASSOCRESP_OFF_AID);
-    pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_ASSOCRESP_OFF_AID
-                  + sizeof(*(pFrame->pwAid));
-
-    return;
+	pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
+
+	// Fixed Fields
+	pFrame->pwCapInfo = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+					       + WLAN_ASSOCRESP_OFF_CAP_INFO);
+	pFrame->pwStatus = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+					      + WLAN_ASSOCRESP_OFF_STATUS);
+	pFrame->pwAid = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+					   + WLAN_ASSOCRESP_OFF_AID);
+	pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_ASSOCRESP_OFF_AID
+		+ sizeof(*(pFrame->pwAid));
+
+	return;
 }
 
-
 /*+
  *
  * Routine Description:
@@ -464,44 +447,42 @@ vMgrEncodeAssocResponse(
  * Return Value:
  *    None.
  *
--*/
+ -*/
 
 void
 vMgrDecodeAssocResponse(
-    PWLAN_FR_ASSOCRESP  pFrame
-     )
+	PWLAN_FR_ASSOCRESP  pFrame
+)
 {
-    PWLAN_IE   pItem;
-
-    pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
-
-    // Fixed Fields
-    pFrame->pwCapInfo = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
-                                + WLAN_ASSOCRESP_OFF_CAP_INFO);
-    pFrame->pwStatus = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
-                               + WLAN_ASSOCRESP_OFF_STATUS);
-    pFrame->pwAid = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
-                            + WLAN_ASSOCRESP_OFF_AID);
-
-    // Information elements
-    pFrame->pSuppRates  = (PWLAN_IE_SUPP_RATES)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
-                           + WLAN_ASSOCRESP_OFF_SUPP_RATES);
-
-    pItem = (PWLAN_IE)(pFrame->pSuppRates);
-    pItem = (PWLAN_IE)(((unsigned char *)pItem) + 2 + pItem->len);
-
-    if ((((unsigned char *)pItem) < (pFrame->pBuf + pFrame->len)) &&
-		    (pItem->byElementID == WLAN_EID_EXTSUPP_RATES)) {
-        pFrame->pExtSuppRates = (PWLAN_IE_SUPP_RATES)pItem;
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pFrame->pExtSuppRates=[%p].\n", pItem);
-    }
-    else {
-        pFrame->pExtSuppRates = NULL;
-    }
-    return;
+	PWLAN_IE   pItem;
+
+	pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
+
+	// Fixed Fields
+	pFrame->pwCapInfo = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+					       + WLAN_ASSOCRESP_OFF_CAP_INFO);
+	pFrame->pwStatus = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+					      + WLAN_ASSOCRESP_OFF_STATUS);
+	pFrame->pwAid = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+					   + WLAN_ASSOCRESP_OFF_AID);
+
+	// Information elements
+	pFrame->pSuppRates  = (PWLAN_IE_SUPP_RATES)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+						    + WLAN_ASSOCRESP_OFF_SUPP_RATES);
+
+	pItem = (PWLAN_IE)(pFrame->pSuppRates);
+	pItem = (PWLAN_IE)(((unsigned char *)pItem) + 2 + pItem->len);
+
+	if ((((unsigned char *)pItem) < (pFrame->pBuf + pFrame->len)) &&
+	    (pItem->byElementID == WLAN_EID_EXTSUPP_RATES)) {
+		pFrame->pExtSuppRates = (PWLAN_IE_SUPP_RATES)pItem;
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pFrame->pExtSuppRates=[%p].\n", pItem);
+	} else {
+		pFrame->pExtSuppRates = NULL;
+	}
+	return;
 }
 
-
 /*+
  *
  * Routine Description:
@@ -511,28 +492,27 @@ vMgrDecodeAssocResponse(
  * Return Value:
  *    None.
  *
--*/
+ -*/
 
 void
 vMgrEncodeReassocRequest(
-    PWLAN_FR_REASSOCREQ  pFrame
-     )
+	PWLAN_FR_REASSOCREQ  pFrame
+)
 {
-    pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
-
-    // Fixed Fields
-    pFrame->pwCapInfo = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
-                                + WLAN_REASSOCREQ_OFF_CAP_INFO);
-    pFrame->pwListenInterval = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
-                                      + WLAN_REASSOCREQ_OFF_LISTEN_INT);
-    pFrame->pAddrCurrAP = (PIEEE_ADDR)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
-                                       + WLAN_REASSOCREQ_OFF_CURR_AP);
-    pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_REASSOCREQ_OFF_CURR_AP + sizeof(*(pFrame->pAddrCurrAP));
-
-    return;
+	pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
+
+	// Fixed Fields
+	pFrame->pwCapInfo = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+					       + WLAN_REASSOCREQ_OFF_CAP_INFO);
+	pFrame->pwListenInterval = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+						      + WLAN_REASSOCREQ_OFF_LISTEN_INT);
+	pFrame->pAddrCurrAP = (PIEEE_ADDR)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+					   + WLAN_REASSOCREQ_OFF_CURR_AP);
+	pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_REASSOCREQ_OFF_CURR_AP + sizeof(*(pFrame->pAddrCurrAP));
+
+	return;
 }
 
-
 /*+
  *
  * Routine Description: (AP)
@@ -542,69 +522,65 @@ vMgrEncodeReassocRequest(
  * Return Value:
  *    None.
  *
--*/
-
+ -*/
 
 void
 vMgrDecodeReassocRequest(
-    PWLAN_FR_REASSOCREQ  pFrame
-     )
+	PWLAN_FR_REASSOCREQ  pFrame
+)
 {
-    PWLAN_IE   pItem;
-    pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
-
-    // Fixed Fields
-    pFrame->pwCapInfo = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
-                                + WLAN_REASSOCREQ_OFF_CAP_INFO);
-    pFrame->pwListenInterval = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
-                                      + WLAN_REASSOCREQ_OFF_LISTEN_INT);
-    pFrame->pAddrCurrAP = (PIEEE_ADDR)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
-                                       + WLAN_REASSOCREQ_OFF_CURR_AP);
-
-    // Information elements
-    pItem = (PWLAN_IE)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
-                       + WLAN_REASSOCREQ_OFF_SSID);
-
-    while(((unsigned char *)pItem) < (pFrame->pBuf + pFrame->len)) {
-
-        switch (pItem->byElementID){
-            case WLAN_EID_SSID:
-                if (pFrame->pSSID == NULL)
-                    pFrame->pSSID = (PWLAN_IE_SSID)pItem;
-                break;
-            case WLAN_EID_SUPP_RATES:
-                if (pFrame->pSuppRates == NULL)
-                    pFrame->pSuppRates = (PWLAN_IE_SUPP_RATES)pItem;
-                break;
-
-            case WLAN_EID_RSN:
-                if (pFrame->pRSN == NULL) {
-                    pFrame->pRSN = (PWLAN_IE_RSN)pItem;
-                }
-                break;
-            case WLAN_EID_RSN_WPA:
-                if (pFrame->pRSNWPA == NULL) {
-                    if (WPAb_Is_RSN((PWLAN_IE_RSN_EXT)pItem) == true)
-                        pFrame->pRSNWPA = (PWLAN_IE_RSN_EXT)pItem;
-                }
-                break;
-
-            case WLAN_EID_EXTSUPP_RATES:
-                if (pFrame->pExtSuppRates == NULL)
-                    pFrame->pExtSuppRates = (PWLAN_IE_SUPP_RATES)pItem;
-                break;
-            default:
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Unrecognized EID=%dd in reassocreq decode.\n",
-                            pItem->byElementID);
-                break;
-        }
-        pItem = (PWLAN_IE)(((unsigned char *)pItem) + 2 + pItem->len);
-    }
-    return;
+	PWLAN_IE   pItem;
+	pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
+
+	// Fixed Fields
+	pFrame->pwCapInfo = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+					       + WLAN_REASSOCREQ_OFF_CAP_INFO);
+	pFrame->pwListenInterval = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+						      + WLAN_REASSOCREQ_OFF_LISTEN_INT);
+	pFrame->pAddrCurrAP = (PIEEE_ADDR)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+					   + WLAN_REASSOCREQ_OFF_CURR_AP);
+
+	// Information elements
+	pItem = (PWLAN_IE)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+			   + WLAN_REASSOCREQ_OFF_SSID);
+
+	while (((unsigned char *)pItem) < (pFrame->pBuf + pFrame->len)) {
+		switch (pItem->byElementID) {
+		case WLAN_EID_SSID:
+			if (pFrame->pSSID == NULL)
+				pFrame->pSSID = (PWLAN_IE_SSID)pItem;
+			break;
+		case WLAN_EID_SUPP_RATES:
+			if (pFrame->pSuppRates == NULL)
+				pFrame->pSuppRates = (PWLAN_IE_SUPP_RATES)pItem;
+			break;
+
+		case WLAN_EID_RSN:
+			if (pFrame->pRSN == NULL) {
+				pFrame->pRSN = (PWLAN_IE_RSN)pItem;
+			}
+			break;
+		case WLAN_EID_RSN_WPA:
+			if (pFrame->pRSNWPA == NULL) {
+				if (WPAb_Is_RSN((PWLAN_IE_RSN_EXT)pItem) == true)
+					pFrame->pRSNWPA = (PWLAN_IE_RSN_EXT)pItem;
+			}
+			break;
+
+		case WLAN_EID_EXTSUPP_RATES:
+			if (pFrame->pExtSuppRates == NULL)
+				pFrame->pExtSuppRates = (PWLAN_IE_SUPP_RATES)pItem;
+			break;
+		default:
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Unrecognized EID=%dd in reassocreq decode.\n",
+				pItem->byElementID);
+			break;
+		}
+		pItem = (PWLAN_IE)(((unsigned char *)pItem) + 2 + pItem->len);
+	}
+	return;
 }
 
-
-
 /*+
  *
  * Routine Description:
@@ -614,17 +590,16 @@ vMgrDecodeReassocRequest(
  * Return Value:
  *    None.
  *
--*/
-
+ -*/
 
 void
 vMgrEncodeProbeRequest(
-    PWLAN_FR_PROBEREQ  pFrame
-     )
+	PWLAN_FR_PROBEREQ  pFrame
+)
 {
-    pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
-    pFrame->len = WLAN_HDR_ADDR3_LEN;
-    return;
+	pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
+	pFrame->len = WLAN_HDR_ADDR3_LEN;
+	return;
 }
 
 /*+
@@ -636,49 +611,47 @@ vMgrEncodeProbeRequest(
  * Return Value:
  *    None.
  *
--*/
+ -*/
 
 void
 vMgrDecodeProbeRequest(
-    PWLAN_FR_PROBEREQ  pFrame
-     )
+	PWLAN_FR_PROBEREQ  pFrame
+)
 {
-    PWLAN_IE   pItem;
-
-    pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
-
-    // Information elements
-    pItem = (PWLAN_IE)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)));
-
-    while( ((unsigned char *)pItem) < (pFrame->pBuf + pFrame->len) ) {
-
-        switch (pItem->byElementID) {
-            case WLAN_EID_SSID:
-                if (pFrame->pSSID == NULL)
-                    pFrame->pSSID = (PWLAN_IE_SSID)pItem;
-                break;
-
-            case WLAN_EID_SUPP_RATES:
-                if (pFrame->pSuppRates == NULL)
-                    pFrame->pSuppRates = (PWLAN_IE_SUPP_RATES)pItem;
-                break;
-
-            case WLAN_EID_EXTSUPP_RATES:
-                if (pFrame->pExtSuppRates == NULL)
-                    pFrame->pExtSuppRates = (PWLAN_IE_SUPP_RATES)pItem;
-                break;
-
-            default:
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Bad EID=%dd in probereq\n", pItem->byElementID);
-                break;
-        }
-
-        pItem = (PWLAN_IE)(((unsigned char *)pItem) + 2 +  pItem->len);
-    }
-    return;
+	PWLAN_IE   pItem;
+
+	pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
+
+	// Information elements
+	pItem = (PWLAN_IE)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)));
+
+	while (((unsigned char *)pItem) < (pFrame->pBuf + pFrame->len)) {
+		switch (pItem->byElementID) {
+		case WLAN_EID_SSID:
+			if (pFrame->pSSID == NULL)
+				pFrame->pSSID = (PWLAN_IE_SSID)pItem;
+			break;
+
+		case WLAN_EID_SUPP_RATES:
+			if (pFrame->pSuppRates == NULL)
+				pFrame->pSuppRates = (PWLAN_IE_SUPP_RATES)pItem;
+			break;
+
+		case WLAN_EID_EXTSUPP_RATES:
+			if (pFrame->pExtSuppRates == NULL)
+				pFrame->pExtSuppRates = (PWLAN_IE_SUPP_RATES)pItem;
+			break;
+
+		default:
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Bad EID=%dd in probereq\n", pItem->byElementID);
+			break;
+		}
+
+		pItem = (PWLAN_IE)(((unsigned char *)pItem) + 2 +  pItem->len);
+	}
+	return;
 }
 
-
 /*+
  *
  * Routine Description:
@@ -688,32 +661,29 @@ vMgrDecodeProbeRequest(
  * Return Value:
  *    None.
  *
--*/
-
+ -*/
 
 void
 vMgrEncodeProbeResponse(
-    PWLAN_FR_PROBERESP  pFrame
-    )
+	PWLAN_FR_PROBERESP  pFrame
+)
 {
-    pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
+	pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
 
-    // Fixed Fields
-    pFrame->pqwTimestamp = (PQWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
-                                    + WLAN_PROBERESP_OFF_TS);
-    pFrame->pwBeaconInterval = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
-                                       + WLAN_PROBERESP_OFF_BCN_INT);
-    pFrame->pwCapInfo = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
-                                + WLAN_PROBERESP_OFF_CAP_INFO);
+	// Fixed Fields
+	pFrame->pqwTimestamp = (PQWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+					+ WLAN_PROBERESP_OFF_TS);
+	pFrame->pwBeaconInterval = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+						      + WLAN_PROBERESP_OFF_BCN_INT);
+	pFrame->pwCapInfo = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+					       + WLAN_PROBERESP_OFF_CAP_INFO);
 
-    pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_PROBERESP_OFF_CAP_INFO +
-                  sizeof(*(pFrame->pwCapInfo));
+	pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_PROBERESP_OFF_CAP_INFO +
+		sizeof(*(pFrame->pwCapInfo));
 
-    return;
+	return;
 }
 
-
-
 /*+
  *
  * Routine Description:
@@ -723,111 +693,109 @@ vMgrEncodeProbeResponse(
  * Return Value:
  *    None.
  *
--*/
+ -*/
 
 void
 vMgrDecodeProbeResponse(
-    PWLAN_FR_PROBERESP  pFrame
-    )
+	PWLAN_FR_PROBERESP  pFrame
+)
 {
-    PWLAN_IE    pItem;
-
-
-    pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
-
-    // Fixed Fields
-    pFrame->pqwTimestamp = (PQWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
-                                    + WLAN_PROBERESP_OFF_TS);
-    pFrame->pwBeaconInterval = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
-                                       + WLAN_PROBERESP_OFF_BCN_INT);
-    pFrame->pwCapInfo = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
-                                + WLAN_PROBERESP_OFF_CAP_INFO);
-
-    // Information elements
-    pItem = (PWLAN_IE)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
-                       + WLAN_PROBERESP_OFF_SSID);
-
-    while( ((unsigned char *)pItem) < (pFrame->pBuf + pFrame->len) ) {
-        switch (pItem->byElementID) {
-            case WLAN_EID_SSID:
-                if (pFrame->pSSID == NULL)
-                pFrame->pSSID = (PWLAN_IE_SSID)pItem;
-                break;
-            case WLAN_EID_SUPP_RATES:
-                if (pFrame->pSuppRates == NULL)
-                pFrame->pSuppRates = (PWLAN_IE_SUPP_RATES)pItem;
-                break;
-            case WLAN_EID_FH_PARMS:
-                break;
-            case WLAN_EID_DS_PARMS:
-                if (pFrame->pDSParms == NULL)
-                    pFrame->pDSParms = (PWLAN_IE_DS_PARMS)pItem;
-                break;
-            case WLAN_EID_CF_PARMS:
-                if (pFrame->pCFParms == NULL)
-                    pFrame->pCFParms = (PWLAN_IE_CF_PARMS)pItem;
-                break;
-            case WLAN_EID_IBSS_PARMS:
-                if (pFrame->pIBSSParms == NULL)
-                    pFrame->pIBSSParms = (PWLAN_IE_IBSS_PARMS)pItem;
-                break;
-
-            case WLAN_EID_RSN:
-                if (pFrame->pRSN == NULL) {
-                    pFrame->pRSN = (PWLAN_IE_RSN)pItem;
-                }
-                break;
-            case WLAN_EID_RSN_WPA:
-                if (pFrame->pRSNWPA == NULL) {
-                    if (WPAb_Is_RSN((PWLAN_IE_RSN_EXT)pItem) == true)
-                        pFrame->pRSNWPA = (PWLAN_IE_RSN_EXT)pItem;
-                }
-                break;
-            case WLAN_EID_ERP:
-                if (pFrame->pERP == NULL)
-                    pFrame->pERP = (PWLAN_IE_ERP)pItem;
-                break;
-            case WLAN_EID_EXTSUPP_RATES:
-                if (pFrame->pExtSuppRates == NULL)
-                    pFrame->pExtSuppRates = (PWLAN_IE_SUPP_RATES)pItem;
-                break;
-
-            case WLAN_EID_COUNTRY:      //7
-                if (pFrame->pIE_Country == NULL)
-                    pFrame->pIE_Country = (PWLAN_IE_COUNTRY)pItem;
-                break;
-
-            case WLAN_EID_PWR_CONSTRAINT:   //32
-                if (pFrame->pIE_PowerConstraint == NULL)
-                    pFrame->pIE_PowerConstraint = (PWLAN_IE_PW_CONST)pItem;
-                break;
-
-            case WLAN_EID_CH_SWITCH:    //37
-                if (pFrame->pIE_CHSW == NULL)
-                    pFrame->pIE_CHSW = (PWLAN_IE_CH_SW)pItem;
-                break;
-
-            case WLAN_EID_QUIET:        //40
-                if (pFrame->pIE_Quiet == NULL)
-                    pFrame->pIE_Quiet = (PWLAN_IE_QUIET)pItem;
-                break;
-
-            case WLAN_EID_IBSS_DFS:
-                if (pFrame->pIE_IBSSDFS == NULL)
-                    pFrame->pIE_IBSSDFS = (PWLAN_IE_IBSS_DFS)pItem;
-                break;
-
-            default:
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Bad EID=%dd in proberesp\n", pItem->byElementID);
-                break;
-        }
-
-        pItem = (PWLAN_IE)(((unsigned char *)pItem) + 2 +  pItem->len);
-    }
-    return;
+	PWLAN_IE    pItem;
+
+	pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
+
+	// Fixed Fields
+	pFrame->pqwTimestamp = (PQWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+					+ WLAN_PROBERESP_OFF_TS);
+	pFrame->pwBeaconInterval = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+						      + WLAN_PROBERESP_OFF_BCN_INT);
+	pFrame->pwCapInfo = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+					       + WLAN_PROBERESP_OFF_CAP_INFO);
+
+	// Information elements
+	pItem = (PWLAN_IE)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+			   + WLAN_PROBERESP_OFF_SSID);
+
+	while (((unsigned char *)pItem) < (pFrame->pBuf + pFrame->len)) {
+		switch (pItem->byElementID) {
+		case WLAN_EID_SSID:
+			if (pFrame->pSSID == NULL)
+				pFrame->pSSID = (PWLAN_IE_SSID)pItem;
+			break;
+		case WLAN_EID_SUPP_RATES:
+			if (pFrame->pSuppRates == NULL)
+				pFrame->pSuppRates = (PWLAN_IE_SUPP_RATES)pItem;
+			break;
+		case WLAN_EID_FH_PARMS:
+			break;
+		case WLAN_EID_DS_PARMS:
+			if (pFrame->pDSParms == NULL)
+				pFrame->pDSParms = (PWLAN_IE_DS_PARMS)pItem;
+			break;
+		case WLAN_EID_CF_PARMS:
+			if (pFrame->pCFParms == NULL)
+				pFrame->pCFParms = (PWLAN_IE_CF_PARMS)pItem;
+			break;
+		case WLAN_EID_IBSS_PARMS:
+			if (pFrame->pIBSSParms == NULL)
+				pFrame->pIBSSParms = (PWLAN_IE_IBSS_PARMS)pItem;
+			break;
+
+		case WLAN_EID_RSN:
+			if (pFrame->pRSN == NULL) {
+				pFrame->pRSN = (PWLAN_IE_RSN)pItem;
+			}
+			break;
+		case WLAN_EID_RSN_WPA:
+			if (pFrame->pRSNWPA == NULL) {
+				if (WPAb_Is_RSN((PWLAN_IE_RSN_EXT)pItem) == true)
+					pFrame->pRSNWPA = (PWLAN_IE_RSN_EXT)pItem;
+			}
+			break;
+		case WLAN_EID_ERP:
+			if (pFrame->pERP == NULL)
+				pFrame->pERP = (PWLAN_IE_ERP)pItem;
+			break;
+		case WLAN_EID_EXTSUPP_RATES:
+			if (pFrame->pExtSuppRates == NULL)
+				pFrame->pExtSuppRates = (PWLAN_IE_SUPP_RATES)pItem;
+			break;
+
+		case WLAN_EID_COUNTRY:      //7
+			if (pFrame->pIE_Country == NULL)
+				pFrame->pIE_Country = (PWLAN_IE_COUNTRY)pItem;
+			break;
+
+		case WLAN_EID_PWR_CONSTRAINT:   //32
+			if (pFrame->pIE_PowerConstraint == NULL)
+				pFrame->pIE_PowerConstraint = (PWLAN_IE_PW_CONST)pItem;
+			break;
+
+		case WLAN_EID_CH_SWITCH:    //37
+			if (pFrame->pIE_CHSW == NULL)
+				pFrame->pIE_CHSW = (PWLAN_IE_CH_SW)pItem;
+			break;
+
+		case WLAN_EID_QUIET:        //40
+			if (pFrame->pIE_Quiet == NULL)
+				pFrame->pIE_Quiet = (PWLAN_IE_QUIET)pItem;
+			break;
+
+		case WLAN_EID_IBSS_DFS:
+			if (pFrame->pIE_IBSSDFS == NULL)
+				pFrame->pIE_IBSSDFS = (PWLAN_IE_IBSS_DFS)pItem;
+			break;
+
+		default:
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Bad EID=%dd in proberesp\n", pItem->byElementID);
+			break;
+		}
+
+		pItem = (PWLAN_IE)(((unsigned char *)pItem) + 2 +  pItem->len);
+	}
+	return;
 }
 
-
 /*+
  *
  * Routine Description:
@@ -837,28 +805,27 @@ vMgrDecodeProbeResponse(
  * Return Value:
  *    None.
  *
--*/
+ -*/
 
 void
 vMgrEncodeAuthen(
-    PWLAN_FR_AUTHEN  pFrame
-    )
+	PWLAN_FR_AUTHEN  pFrame
+)
 {
-    pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
-
-    // Fixed Fields
-    pFrame->pwAuthAlgorithm = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
-                                      + WLAN_AUTHEN_OFF_AUTH_ALG);
-    pFrame->pwAuthSequence = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
-                                     + WLAN_AUTHEN_OFF_AUTH_SEQ);
-    pFrame->pwStatus = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
-                               + WLAN_AUTHEN_OFF_STATUS);
-    pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_AUTHEN_OFF_STATUS + sizeof(*(pFrame->pwStatus));
-
-    return;
+	pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
+
+	// Fixed Fields
+	pFrame->pwAuthAlgorithm = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+						     + WLAN_AUTHEN_OFF_AUTH_ALG);
+	pFrame->pwAuthSequence = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+						    + WLAN_AUTHEN_OFF_AUTH_SEQ);
+	pFrame->pwStatus = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+					      + WLAN_AUTHEN_OFF_STATUS);
+	pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_AUTHEN_OFF_STATUS + sizeof(*(pFrame->pwStatus));
+
+	return;
 }
 
-
 /*+
  *
  * Routine Description:
@@ -868,37 +835,36 @@ vMgrEncodeAuthen(
  * Return Value:
  *    None.
  *
--*/
+ -*/
 
 void
 vMgrDecodeAuthen(
-    PWLAN_FR_AUTHEN  pFrame
-    )
+	PWLAN_FR_AUTHEN  pFrame
+)
 {
-    PWLAN_IE    pItem;
+	PWLAN_IE    pItem;
 
-    pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
+	pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
 
-    // Fixed Fields
-    pFrame->pwAuthAlgorithm = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
-                                      + WLAN_AUTHEN_OFF_AUTH_ALG);
-    pFrame->pwAuthSequence = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
-                                     + WLAN_AUTHEN_OFF_AUTH_SEQ);
-    pFrame->pwStatus = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
-                               + WLAN_AUTHEN_OFF_STATUS);
+	// Fixed Fields
+	pFrame->pwAuthAlgorithm = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+						     + WLAN_AUTHEN_OFF_AUTH_ALG);
+	pFrame->pwAuthSequence = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+						    + WLAN_AUTHEN_OFF_AUTH_SEQ);
+	pFrame->pwStatus = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+					      + WLAN_AUTHEN_OFF_STATUS);
 
-    // Information elements
-    pItem = (PWLAN_IE)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
-                       + WLAN_AUTHEN_OFF_CHALLENGE);
+	// Information elements
+	pItem = (PWLAN_IE)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+			   + WLAN_AUTHEN_OFF_CHALLENGE);
 
-    if ((((unsigned char *)pItem) < (pFrame->pBuf + pFrame->len)) && (pItem->byElementID == WLAN_EID_CHALLENGE)) {
-        pFrame->pChallenge = (PWLAN_IE_CHALLENGE)pItem;
-    }
+	if ((((unsigned char *)pItem) < (pFrame->pBuf + pFrame->len)) && (pItem->byElementID == WLAN_EID_CHALLENGE)) {
+		pFrame->pChallenge = (PWLAN_IE_CHALLENGE)pItem;
+	}
 
-    return;
+	return;
 }
 
-
 /*+
  *
  * Routine Description:
@@ -908,24 +874,23 @@ vMgrDecodeAuthen(
  * Return Value:
  *    None.
  *
--*/
+ -*/
 
 void
 vMgrEncodeDeauthen(
-    PWLAN_FR_DEAUTHEN  pFrame
-    )
+	PWLAN_FR_DEAUTHEN  pFrame
+)
 {
-    pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
+	pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
 
-    // Fixed Fields
-    pFrame->pwReason = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
-                               + WLAN_DEAUTHEN_OFF_REASON);
-    pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_DEAUTHEN_OFF_REASON + sizeof(*(pFrame->pwReason));
+	// Fixed Fields
+	pFrame->pwReason = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+					      + WLAN_DEAUTHEN_OFF_REASON);
+	pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_DEAUTHEN_OFF_REASON + sizeof(*(pFrame->pwReason));
 
-    return;
+	return;
 }
 
-
 /*+
  *
  * Routine Description:
@@ -935,23 +900,22 @@ vMgrEncodeDeauthen(
  * Return Value:
  *    None.
  *
--*/
+ -*/
 
 void
 vMgrDecodeDeauthen(
-    PWLAN_FR_DEAUTHEN  pFrame
-    )
+	PWLAN_FR_DEAUTHEN  pFrame
+)
 {
-    pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
+	pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
 
-    // Fixed Fields
-    pFrame->pwReason = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
-                               + WLAN_DEAUTHEN_OFF_REASON);
+	// Fixed Fields
+	pFrame->pwReason = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+					      + WLAN_DEAUTHEN_OFF_REASON);
 
-    return;
+	return;
 }
 
-
 /*+
  *
  * Routine Description: (AP)
@@ -961,29 +925,28 @@ vMgrDecodeDeauthen(
  * Return Value:
  *    None.
  *
--*/
+ -*/
 
 void
 vMgrEncodeReassocResponse(
-    PWLAN_FR_REASSOCRESP  pFrame
-     )
+	PWLAN_FR_REASSOCRESP  pFrame
+)
 {
-    pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
+	pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
 
-    // Fixed Fields
-    pFrame->pwCapInfo = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
-                                + WLAN_REASSOCRESP_OFF_CAP_INFO);
-    pFrame->pwStatus = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
-                               + WLAN_REASSOCRESP_OFF_STATUS);
-    pFrame->pwAid = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
-                            + WLAN_REASSOCRESP_OFF_AID);
+	// Fixed Fields
+	pFrame->pwCapInfo = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+					       + WLAN_REASSOCRESP_OFF_CAP_INFO);
+	pFrame->pwStatus = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+					      + WLAN_REASSOCRESP_OFF_STATUS);
+	pFrame->pwAid = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+					   + WLAN_REASSOCRESP_OFF_AID);
 
-    pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_REASSOCRESP_OFF_AID + sizeof(*(pFrame->pwAid));
+	pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_REASSOCRESP_OFF_AID + sizeof(*(pFrame->pwAid));
 
-    return;
+	return;
 }
 
-
 /*+
  *
  * Routine Description:
@@ -993,36 +956,35 @@ vMgrEncodeReassocResponse(
  * Return Value:
  *    None.
  *
--*/
-
+ -*/
 
 void
 vMgrDecodeReassocResponse(
-    PWLAN_FR_REASSOCRESP  pFrame
-     )
+	PWLAN_FR_REASSOCRESP  pFrame
+)
 {
-    PWLAN_IE   pItem;
-
-    pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
-
-    // Fixed Fields
-    pFrame->pwCapInfo = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
-                                + WLAN_REASSOCRESP_OFF_CAP_INFO);
-    pFrame->pwStatus = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
-                               + WLAN_REASSOCRESP_OFF_STATUS);
-    pFrame->pwAid = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
-                            + WLAN_REASSOCRESP_OFF_AID);
-
-    //Information elements
-    pFrame->pSuppRates = (PWLAN_IE_SUPP_RATES)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
-                                               + WLAN_REASSOCRESP_OFF_SUPP_RATES);
-
-    pItem = (PWLAN_IE)(pFrame->pSuppRates);
-    pItem = (PWLAN_IE)(((unsigned char *)pItem) + 2 + pItem->len);
-
-    if ((((unsigned char *)pItem) < (pFrame->pBuf + pFrame->len)) &&
-		    (pItem->byElementID == WLAN_EID_EXTSUPP_RATES)) {
-        pFrame->pExtSuppRates = (PWLAN_IE_SUPP_RATES)pItem;
-    }
-    return;
+	PWLAN_IE   pItem;
+
+	pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
+
+	// Fixed Fields
+	pFrame->pwCapInfo = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+					       + WLAN_REASSOCRESP_OFF_CAP_INFO);
+	pFrame->pwStatus = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+					      + WLAN_REASSOCRESP_OFF_STATUS);
+	pFrame->pwAid = (unsigned short *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+					   + WLAN_REASSOCRESP_OFF_AID);
+
+	//Information elements
+	pFrame->pSuppRates = (PWLAN_IE_SUPP_RATES)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+						   + WLAN_REASSOCRESP_OFF_SUPP_RATES);
+
+	pItem = (PWLAN_IE)(pFrame->pSuppRates);
+	pItem = (PWLAN_IE)(((unsigned char *)pItem) + 2 + pItem->len);
+
+	if ((((unsigned char *)pItem) < (pFrame->pBuf + pFrame->len)) &&
+	    (pItem->byElementID == WLAN_EID_EXTSUPP_RATES)) {
+		pFrame->pExtSuppRates = (PWLAN_IE_SUPP_RATES)pItem;
+	}
+	return;
 }
diff --git a/drivers/staging/vt6655/80211mgr.h b/drivers/staging/vt6655/80211mgr.h
index 65780f2..16402cf 100644
--- a/drivers/staging/vt6655/80211mgr.h
+++ b/drivers/staging/vt6655/80211mgr.h
@@ -65,7 +65,6 @@
 // reference WiFi WPA spec.
 #define WLAN_EID_RSN_WPA        221
 
-
 #define WLAN_EID_ERP_NONERP_PRESENT             0x01
 #define WLAN_EID_ERP_USE_PROTECTION             0x02
 #define WLAN_EID_ERP_BARKER_MODE                0x04
@@ -132,14 +131,10 @@
 #define WLAN_MGMT_STATUS_INVALID_RSN_IE_CAP             45
 #define WLAN_MGMT_STATUS_CIPHER_REJECT                  46
 
-
-
 // Auth Algorithm
 #define WLAN_AUTH_ALG_OPENSYSTEM                0
 #define WLAN_AUTH_ALG_SHAREDKEY                 1
 
-
-
 // Management Frame Field Offsets
 // Note: Not all fields are listed because of variable lengths.
 // Note: These offsets are from the start of the frame data
@@ -184,7 +179,6 @@
 
 #define WLAN_DEAUTHEN_OFF_REASON            0
 
-
 //
 // Cipher Suite Selectors defined in 802.11i
 //
@@ -217,611 +211,567 @@
 #define MEASURE_MODE_INCAPABLE  0x02
 #define MEASURE_MODE_REFUSED    0x04
 
-
-
 /*---------------------  Export Classes  ----------------------------*/
 
 /*---------------------  Export Variables  --------------------------*/
 
 /*---------------------  Export Types  ------------------------------*/
 
-
 // Information Element Types
 
 #pragma pack(1)
 typedef struct tagWLAN_IE {
-    unsigned char byElementID;
-    unsigned char len;
-}__attribute__ ((__packed__))
+	unsigned char byElementID;
+	unsigned char len;
+} __attribute__ ((__packed__))
 WLAN_IE, *PWLAN_IE;
 
-
 // Service Set Identity (SSID)
 #pragma pack(1)
 typedef struct tagWLAN_IE_SSID {
-    unsigned char byElementID;
-    unsigned char len;
-    unsigned char abySSID[1];
-}__attribute__ ((__packed__))
+	unsigned char byElementID;
+	unsigned char len;
+	unsigned char abySSID[1];
+} __attribute__ ((__packed__))
 WLAN_IE_SSID, *PWLAN_IE_SSID;
 
-
 // Supported Rates
 #pragma pack(1)
 typedef struct tagWLAN_IE_SUPP_RATES {
-    unsigned char byElementID;
-    unsigned char len;
-    unsigned char abyRates[1];
-}__attribute__ ((__packed__))
+	unsigned char byElementID;
+	unsigned char len;
+	unsigned char abyRates[1];
+} __attribute__ ((__packed__))
 WLAN_IE_SUPP_RATES,  *PWLAN_IE_SUPP_RATES;
 
-
-
 // FH Parameter Set
 #pragma pack(1)
 typedef struct _WLAN_IE_FH_PARMS {
-    unsigned char byElementID;
-    unsigned char len;
-    unsigned short wDwellTime;
-    unsigned char byHopSet;
-    unsigned char byHopPattern;
-    unsigned char byHopIndex;
+	unsigned char byElementID;
+	unsigned char len;
+	unsigned short wDwellTime;
+	unsigned char byHopSet;
+	unsigned char byHopPattern;
+	unsigned char byHopIndex;
 } WLAN_IE_FH_PARMS,  *PWLAN_IE_FH_PARMS;
 
 // DS Parameter Set
 #pragma pack(1)
 typedef struct tagWLAN_IE_DS_PARMS {
-    unsigned char byElementID;
-    unsigned char len;
-    unsigned char byCurrChannel;
-}__attribute__ ((__packed__))
+	unsigned char byElementID;
+	unsigned char len;
+	unsigned char byCurrChannel;
+} __attribute__ ((__packed__))
 WLAN_IE_DS_PARMS,  *PWLAN_IE_DS_PARMS;
 
-
 // CF Parameter Set
 #pragma pack(1)
 typedef struct tagWLAN_IE_CF_PARMS {
-    unsigned char byElementID;
-    unsigned char len;
-    unsigned char byCFPCount;
-    unsigned char byCFPPeriod;
-    unsigned short wCFPMaxDuration;
-    unsigned short wCFPDurRemaining;
-}__attribute__ ((__packed__))
+	unsigned char byElementID;
+	unsigned char len;
+	unsigned char byCFPCount;
+	unsigned char byCFPPeriod;
+	unsigned short wCFPMaxDuration;
+	unsigned short wCFPDurRemaining;
+} __attribute__ ((__packed__))
 WLAN_IE_CF_PARMS,  *PWLAN_IE_CF_PARMS;
 
-
 // TIM
 #pragma pack(1)
 typedef struct tagWLAN_IE_TIM {
-    unsigned char byElementID;
-    unsigned char len;
-    unsigned char byDTIMCount;
-    unsigned char byDTIMPeriod;
-    unsigned char byBitMapCtl;
-    unsigned char byVirtBitMap[1];
-}__attribute__ ((__packed__))
+	unsigned char byElementID;
+	unsigned char len;
+	unsigned char byDTIMCount;
+	unsigned char byDTIMPeriod;
+	unsigned char byBitMapCtl;
+	unsigned char byVirtBitMap[1];
+} __attribute__ ((__packed__))
 WLAN_IE_TIM,  *PWLAN_IE_TIM;
 
-
 // IBSS Parameter Set
 #pragma pack(1)
 typedef struct tagWLAN_IE_IBSS_PARMS {
-    unsigned char byElementID;
-    unsigned char len;
-    unsigned short wATIMWindow;
-}__attribute__ ((__packed__))
+	unsigned char byElementID;
+	unsigned char len;
+	unsigned short wATIMWindow;
+} __attribute__ ((__packed__))
 WLAN_IE_IBSS_PARMS, *PWLAN_IE_IBSS_PARMS;
 
-
 // Challenge Text
 #pragma pack(1)
 typedef struct tagWLAN_IE_CHALLENGE {
-    unsigned char byElementID;
-    unsigned char len;
-    unsigned char abyChallenge[1];
-}__attribute__ ((__packed__))
+	unsigned char byElementID;
+	unsigned char len;
+	unsigned char abyChallenge[1];
+} __attribute__ ((__packed__))
 WLAN_IE_CHALLENGE,  *PWLAN_IE_CHALLENGE;
 
-
 #pragma pack(1)
 typedef struct tagWLAN_IE_RSN_EXT {
-    unsigned char byElementID;
-    unsigned char len;
-    unsigned char abyOUI[4];
-    unsigned short wVersion;
-    unsigned char abyMulticast[4];
-    unsigned short wPKCount;
-    struct {
-        unsigned char abyOUI[4];
-    } PKSList[1]; // the rest is variable so need to
-    // overlay ieauth structure
+	unsigned char byElementID;
+	unsigned char len;
+	unsigned char abyOUI[4];
+	unsigned short wVersion;
+	unsigned char abyMulticast[4];
+	unsigned short wPKCount;
+	struct {
+		unsigned char abyOUI[4];
+	} PKSList[1]; // the rest is variable so need to
+	// overlay ieauth structure
 } WLAN_IE_RSN_EXT, *PWLAN_IE_RSN_EXT;
 
 #pragma pack(1)
 typedef struct tagWLAN_IE_RSN_AUTH {
-    unsigned short wAuthCount;
-    struct {
-        unsigned char abyOUI[4];
-    } AuthKSList[1];
+	unsigned short wAuthCount;
+	struct {
+		unsigned char abyOUI[4];
+	} AuthKSList[1];
 } WLAN_IE_RSN_AUTH, *PWLAN_IE_RSN_AUTH;
 
 // RSN Identity
 #pragma pack(1)
 typedef struct tagWLAN_IE_RSN {
-    unsigned char byElementID;
-    unsigned char len;
-    unsigned short wVersion;
-    unsigned char abyRSN[WLAN_MIN_ARRAY];
+	unsigned char byElementID;
+	unsigned char len;
+	unsigned short wVersion;
+	unsigned char abyRSN[WLAN_MIN_ARRAY];
 } WLAN_IE_RSN, *PWLAN_IE_RSN;
 
-
 // ERP
 #pragma pack(1)
 typedef struct tagWLAN_IE_ERP {
-    unsigned char byElementID;
-    unsigned char len;
-    unsigned char byContext;
-}__attribute__ ((__packed__))
+	unsigned char byElementID;
+	unsigned char len;
+	unsigned char byContext;
+} __attribute__ ((__packed__))
 WLAN_IE_ERP,  *PWLAN_IE_ERP;
 
-
 #pragma pack(1)
 typedef struct _MEASEURE_REQ {
-    unsigned char byChannel;
-    unsigned char abyStartTime[8];
-    unsigned char abyDuration[2];
+	unsigned char byChannel;
+	unsigned char abyStartTime[8];
+	unsigned char abyDuration[2];
 } MEASEURE_REQ, *PMEASEURE_REQ,
-  MEASEURE_REQ_BASIC, *PMEASEURE_REQ_BASIC,
-  MEASEURE_REQ_CCA, *PMEASEURE_REQ_CCA,
-  MEASEURE_REQ_RPI, *PMEASEURE_REQ_RPI;
+	MEASEURE_REQ_BASIC, *PMEASEURE_REQ_BASIC,
+	MEASEURE_REQ_CCA, *PMEASEURE_REQ_CCA,
+	MEASEURE_REQ_RPI, *PMEASEURE_REQ_RPI;
 
 typedef struct _MEASEURE_REP_BASIC {
-    unsigned char byChannel;
-    unsigned char abyStartTime[8];
-    unsigned char abyDuration[2];
-    unsigned char byMap;
+	unsigned char byChannel;
+	unsigned char abyStartTime[8];
+	unsigned char abyDuration[2];
+	unsigned char byMap;
 } MEASEURE_REP_BASIC, *PMEASEURE_REP_BASIC;
 
 typedef struct _MEASEURE_REP_CCA {
-    unsigned char byChannel;
-    unsigned char abyStartTime[8];
-    unsigned char abyDuration[2];
-    unsigned char byCCABusyFraction;
+	unsigned char byChannel;
+	unsigned char abyStartTime[8];
+	unsigned char abyDuration[2];
+	unsigned char byCCABusyFraction;
 } MEASEURE_REP_CCA, *PMEASEURE_REP_CCA;
 
 typedef struct _MEASEURE_REP_RPI {
-    unsigned char byChannel;
-    unsigned char abyStartTime[8];
-    unsigned char abyDuration[2];
-    unsigned char abyRPIdensity[8];
+	unsigned char byChannel;
+	unsigned char abyStartTime[8];
+	unsigned char abyDuration[2];
+	unsigned char abyRPIdensity[8];
 } MEASEURE_REP_RPI, *PMEASEURE_REP_RPI;
 
 typedef union _MEASEURE_REP {
-
-    MEASEURE_REP_BASIC  sBasic;
-    MEASEURE_REP_CCA    sCCA;
-    MEASEURE_REP_RPI    sRPI;
-
+	MEASEURE_REP_BASIC  sBasic;
+	MEASEURE_REP_CCA    sCCA;
+	MEASEURE_REP_RPI    sRPI;
 } MEASEURE_REP, *PMEASEURE_REP;
 
 typedef struct _WLAN_IE_MEASURE_REQ {
-    unsigned char byElementID;
-    unsigned char len;
-    unsigned char byToken;
-    unsigned char byMode;
-    unsigned char byType;
-    MEASEURE_REQ        sReq;
+	unsigned char byElementID;
+	unsigned char len;
+	unsigned char byToken;
+	unsigned char byMode;
+	unsigned char byType;
+	MEASEURE_REQ        sReq;
 } WLAN_IE_MEASURE_REQ, *PWLAN_IE_MEASURE_REQ;
 
 typedef struct _WLAN_IE_MEASURE_REP {
-    unsigned char byElementID;
-    unsigned char len;
-    unsigned char byToken;
-    unsigned char byMode;
-    unsigned char byType;
-    MEASEURE_REP        sRep;
+	unsigned char byElementID;
+	unsigned char len;
+	unsigned char byToken;
+	unsigned char byMode;
+	unsigned char byType;
+	MEASEURE_REP        sRep;
 } WLAN_IE_MEASURE_REP, *PWLAN_IE_MEASURE_REP;
 
 typedef struct _WLAN_IE_CH_SW {
-    unsigned char byElementID;
-    unsigned char len;
-    unsigned char byMode;
-    unsigned char byChannel;
-    unsigned char byCount;
+	unsigned char byElementID;
+	unsigned char len;
+	unsigned char byMode;
+	unsigned char byChannel;
+	unsigned char byCount;
 } WLAN_IE_CH_SW, *PWLAN_IE_CH_SW;
 
 typedef struct _WLAN_IE_QUIET {
-    unsigned char byElementID;
-    unsigned char len;
-    unsigned char byQuietCount;
-    unsigned char byQuietPeriod;
-    unsigned char abyQuietDuration[2];
-    unsigned char abyQuietOffset[2];
+	unsigned char byElementID;
+	unsigned char len;
+	unsigned char byQuietCount;
+	unsigned char byQuietPeriod;
+	unsigned char abyQuietDuration[2];
+	unsigned char abyQuietOffset[2];
 } WLAN_IE_QUIET, *PWLAN_IE_QUIET;
 
 typedef struct _WLAN_IE_COUNTRY {
-    unsigned char byElementID;
-    unsigned char len;
-    unsigned char abyCountryString[3];
-    unsigned char abyCountryInfo[3];
+	unsigned char byElementID;
+	unsigned char len;
+	unsigned char abyCountryString[3];
+	unsigned char abyCountryInfo[3];
 } WLAN_IE_COUNTRY, *PWLAN_IE_COUNTRY;
 
 typedef struct _WLAN_IE_PW_CONST {
-    unsigned char byElementID;
-    unsigned char len;
-    unsigned char byPower;
+	unsigned char byElementID;
+	unsigned char len;
+	unsigned char byPower;
 } WLAN_IE_PW_CONST, *PWLAN_IE_PW_CONST;
 
 typedef struct _WLAN_IE_PW_CAP {
-    unsigned char byElementID;
-    unsigned char len;
-    unsigned char byMinPower;
-    unsigned char byMaxPower;
+	unsigned char byElementID;
+	unsigned char len;
+	unsigned char byMinPower;
+	unsigned char byMaxPower;
 } WLAN_IE_PW_CAP, *PWLAN_IE_PW_CAP;
 
 typedef struct _WLAN_IE_SUPP_CH {
-    unsigned char byElementID;
-    unsigned char len;
-    unsigned char abyChannelTuple[2];
+	unsigned char byElementID;
+	unsigned char len;
+	unsigned char abyChannelTuple[2];
 } WLAN_IE_SUPP_CH, *PWLAN_IE_SUPP_CH;
 
 typedef struct _WLAN_IE_TPC_REQ {
-    unsigned char byElementID;
-    unsigned char len;
+	unsigned char byElementID;
+	unsigned char len;
 } WLAN_IE_TPC_REQ, *PWLAN_IE_TPC_REQ;
 
 typedef struct _WLAN_IE_TPC_REP {
-    unsigned char byElementID;
-    unsigned char len;
-    unsigned char byTxPower;
-    unsigned char byLinkMargin;
+	unsigned char byElementID;
+	unsigned char len;
+	unsigned char byTxPower;
+	unsigned char byLinkMargin;
 } WLAN_IE_TPC_REP, *PWLAN_IE_TPC_REP;
 
-
 typedef struct _WLAN_IE_IBSS_DFS {
-    unsigned char byElementID;
-    unsigned char len;
-    unsigned char abyDFSOwner[6];
-    unsigned char byDFSRecovery;
-    unsigned char abyChannelMap[2];
+	unsigned char byElementID;
+	unsigned char len;
+	unsigned char abyDFSOwner[6];
+	unsigned char byDFSRecovery;
+	unsigned char abyChannelMap[2];
 } WLAN_IE_IBSS_DFS, *PWLAN_IE_IBSS_DFS;
 
 #pragma pack()
 
-
-
 // Frame Types
 // prototype structure, all mgmt frame types will start with these members
 typedef struct tagWLAN_FR_MGMT {
-
-    unsigned int	uType;
-    unsigned int	len;
-    unsigned char *pBuf;
-    PUWLAN_80211HDR       pHdr;
-
+	unsigned int	uType;
+	unsigned int	len;
+	unsigned char *pBuf;
+	PUWLAN_80211HDR       pHdr;
 } WLAN_FR_MGMT,  *PWLAN_FR_MGMT;
 
 // Beacon frame
 typedef struct tagWLAN_FR_BEACON {
-
-    unsigned int	uType;
-    unsigned int	len;
-    unsigned char *pBuf;
-    PUWLAN_80211HDR         pHdr;
-    // fixed fields
-    PQWORD                  pqwTimestamp;
-    unsigned short *pwBeaconInterval;
-    unsigned short *pwCapInfo;
-    /*-- info elements ----------*/
-    PWLAN_IE_SSID           pSSID;
-    PWLAN_IE_SUPP_RATES     pSuppRates;
+	unsigned int	uType;
+	unsigned int	len;
+	unsigned char *pBuf;
+	PUWLAN_80211HDR         pHdr;
+	// fixed fields
+	PQWORD                  pqwTimestamp;
+	unsigned short *pwBeaconInterval;
+	unsigned short *pwCapInfo;
+	/*-- info elements ----------*/
+	PWLAN_IE_SSID           pSSID;
+	PWLAN_IE_SUPP_RATES     pSuppRates;
 //  PWLAN_IE_FH_PARMS       pFHParms;
-    PWLAN_IE_DS_PARMS       pDSParms;
-    PWLAN_IE_CF_PARMS       pCFParms;
-    PWLAN_IE_TIM            pTIM;
-    PWLAN_IE_IBSS_PARMS     pIBSSParms;
-    PWLAN_IE_RSN            pRSN;
-    PWLAN_IE_RSN_EXT        pRSNWPA;
-    PWLAN_IE_ERP            pERP;
-    PWLAN_IE_SUPP_RATES     pExtSuppRates;
-    PWLAN_IE_COUNTRY        pIE_Country;
-    PWLAN_IE_PW_CONST       pIE_PowerConstraint;
-    PWLAN_IE_CH_SW          pIE_CHSW;
-    PWLAN_IE_IBSS_DFS       pIE_IBSSDFS;
-    PWLAN_IE_QUIET          pIE_Quiet;
-
+	PWLAN_IE_DS_PARMS       pDSParms;
+	PWLAN_IE_CF_PARMS       pCFParms;
+	PWLAN_IE_TIM            pTIM;
+	PWLAN_IE_IBSS_PARMS     pIBSSParms;
+	PWLAN_IE_RSN            pRSN;
+	PWLAN_IE_RSN_EXT        pRSNWPA;
+	PWLAN_IE_ERP            pERP;
+	PWLAN_IE_SUPP_RATES     pExtSuppRates;
+	PWLAN_IE_COUNTRY        pIE_Country;
+	PWLAN_IE_PW_CONST       pIE_PowerConstraint;
+	PWLAN_IE_CH_SW          pIE_CHSW;
+	PWLAN_IE_IBSS_DFS       pIE_IBSSDFS;
+	PWLAN_IE_QUIET          pIE_Quiet;
 } WLAN_FR_BEACON, *PWLAN_FR_BEACON;
 
-
 // IBSS ATIM frame
 typedef struct tagWLAN_FR_IBSSATIM {
-
-    unsigned int	uType;
-    unsigned int	len;
-    unsigned char *pBuf;
-    PUWLAN_80211HDR         pHdr;
-
-    // fixed fields
-    // info elements
-    // this frame type has a null body
-
+	unsigned int	uType;
+	unsigned int	len;
+	unsigned char *pBuf;
+	PUWLAN_80211HDR         pHdr;
+
+	// fixed fields
+	// info elements
+	// this frame type has a null body
 } WLAN_FR_IBSSATIM, *PWLAN_FR_IBSSATIM;
 
 // Disassociation
 typedef struct tagWLAN_FR_DISASSOC {
-
-    unsigned int	uType;
-    unsigned int	len;
-    unsigned char *pBuf;
-    PUWLAN_80211HDR         pHdr;
-    /*-- fixed fields -----------*/
-    unsigned short *pwReason;
-    /*-- info elements ----------*/
-
+	unsigned int	uType;
+	unsigned int	len;
+	unsigned char *pBuf;
+	PUWLAN_80211HDR         pHdr;
+	/*-- fixed fields -----------*/
+	unsigned short *pwReason;
+	/*-- info elements ----------*/
 } WLAN_FR_DISASSOC, *PWLAN_FR_DISASSOC;
 
 // Association Request
 typedef struct tagWLAN_FR_ASSOCREQ {
-
-    unsigned int	uType;
-    unsigned int	len;
-    unsigned char *pBuf;
-    PUWLAN_80211HDR         pHdr;
-    /*-- fixed fields -----------*/
-    unsigned short *pwCapInfo;
-    unsigned short *pwListenInterval;
-    /*-- info elements ----------*/
-    PWLAN_IE_SSID           pSSID;
-    PWLAN_IE_SUPP_RATES     pSuppRates;
-    PWLAN_IE_RSN            pRSN;
-    PWLAN_IE_RSN_EXT        pRSNWPA;
-    PWLAN_IE_SUPP_RATES     pExtSuppRates;
-    PWLAN_IE_PW_CAP         pCurrPowerCap;
-    PWLAN_IE_SUPP_CH        pCurrSuppCh;
-
+	unsigned int	uType;
+	unsigned int	len;
+	unsigned char *pBuf;
+	PUWLAN_80211HDR         pHdr;
+	/*-- fixed fields -----------*/
+	unsigned short *pwCapInfo;
+	unsigned short *pwListenInterval;
+	/*-- info elements ----------*/
+	PWLAN_IE_SSID           pSSID;
+	PWLAN_IE_SUPP_RATES     pSuppRates;
+	PWLAN_IE_RSN            pRSN;
+	PWLAN_IE_RSN_EXT        pRSNWPA;
+	PWLAN_IE_SUPP_RATES     pExtSuppRates;
+	PWLAN_IE_PW_CAP         pCurrPowerCap;
+	PWLAN_IE_SUPP_CH        pCurrSuppCh;
 } WLAN_FR_ASSOCREQ, *PWLAN_FR_ASSOCREQ;
 
 // Association Response
 typedef struct tagWLAN_FR_ASSOCRESP {
-
-    unsigned int	uType;
-    unsigned int	len;
-    unsigned char *pBuf;
-    PUWLAN_80211HDR         pHdr;
-    /*-- fixed fields -----------*/
-    unsigned short *pwCapInfo;
-    unsigned short *pwStatus;
-    unsigned short *pwAid;
-    /*-- info elements ----------*/
-    PWLAN_IE_SUPP_RATES     pSuppRates;
-    PWLAN_IE_SUPP_RATES     pExtSuppRates;
-
+	unsigned int	uType;
+	unsigned int	len;
+	unsigned char *pBuf;
+	PUWLAN_80211HDR         pHdr;
+	/*-- fixed fields -----------*/
+	unsigned short *pwCapInfo;
+	unsigned short *pwStatus;
+	unsigned short *pwAid;
+	/*-- info elements ----------*/
+	PWLAN_IE_SUPP_RATES     pSuppRates;
+	PWLAN_IE_SUPP_RATES     pExtSuppRates;
 } WLAN_FR_ASSOCRESP, *PWLAN_FR_ASSOCRESP;
 
 // Reassociation Request
 typedef struct tagWLAN_FR_REASSOCREQ {
-
-    unsigned int	uType;
-    unsigned int	len;
-    unsigned char *pBuf;
-    PUWLAN_80211HDR         pHdr;
-
-    /*-- fixed fields -----------*/
-    unsigned short *pwCapInfo;
-    unsigned short *pwListenInterval;
-    PIEEE_ADDR              pAddrCurrAP;
-
-    /*-- info elements ----------*/
-    PWLAN_IE_SSID           pSSID;
-    PWLAN_IE_SUPP_RATES     pSuppRates;
-    PWLAN_IE_RSN            pRSN;
-    PWLAN_IE_RSN_EXT        pRSNWPA;
-    PWLAN_IE_SUPP_RATES     pExtSuppRates;
-
+	unsigned int	uType;
+	unsigned int	len;
+	unsigned char *pBuf;
+	PUWLAN_80211HDR         pHdr;
+
+	/*-- fixed fields -----------*/
+	unsigned short *pwCapInfo;
+	unsigned short *pwListenInterval;
+	PIEEE_ADDR              pAddrCurrAP;
+
+	/*-- info elements ----------*/
+	PWLAN_IE_SSID           pSSID;
+	PWLAN_IE_SUPP_RATES     pSuppRates;
+	PWLAN_IE_RSN            pRSN;
+	PWLAN_IE_RSN_EXT        pRSNWPA;
+	PWLAN_IE_SUPP_RATES     pExtSuppRates;
 } WLAN_FR_REASSOCREQ, *PWLAN_FR_REASSOCREQ;
 
 // Reassociation Response
 typedef struct tagWLAN_FR_REASSOCRESP {
-
-    unsigned int	uType;
-    unsigned int	len;
-    unsigned char *pBuf;
-    PUWLAN_80211HDR         pHdr;
-    /*-- fixed fields -----------*/
-    unsigned short *pwCapInfo;
-    unsigned short *pwStatus;
-    unsigned short *pwAid;
-    /*-- info elements ----------*/
-    PWLAN_IE_SUPP_RATES     pSuppRates;
-    PWLAN_IE_SUPP_RATES     pExtSuppRates;
-
+	unsigned int	uType;
+	unsigned int	len;
+	unsigned char *pBuf;
+	PUWLAN_80211HDR         pHdr;
+	/*-- fixed fields -----------*/
+	unsigned short *pwCapInfo;
+	unsigned short *pwStatus;
+	unsigned short *pwAid;
+	/*-- info elements ----------*/
+	PWLAN_IE_SUPP_RATES     pSuppRates;
+	PWLAN_IE_SUPP_RATES     pExtSuppRates;
 } WLAN_FR_REASSOCRESP, *PWLAN_FR_REASSOCRESP;
 
 // Probe Request
 typedef struct tagWLAN_FR_PROBEREQ {
-
-    unsigned int	uType;
-    unsigned int	len;
-    unsigned char *pBuf;
-    PUWLAN_80211HDR         pHdr;
-    /*-- fixed fields -----------*/
-    /*-- info elements ----------*/
-    PWLAN_IE_SSID           pSSID;
-    PWLAN_IE_SUPP_RATES     pSuppRates;
-    PWLAN_IE_SUPP_RATES     pExtSuppRates;
-
+	unsigned int	uType;
+	unsigned int	len;
+	unsigned char *pBuf;
+	PUWLAN_80211HDR         pHdr;
+	/*-- fixed fields -----------*/
+	/*-- info elements ----------*/
+	PWLAN_IE_SSID           pSSID;
+	PWLAN_IE_SUPP_RATES     pSuppRates;
+	PWLAN_IE_SUPP_RATES     pExtSuppRates;
 } WLAN_FR_PROBEREQ, *PWLAN_FR_PROBEREQ;
 
 // Probe Response
 typedef struct tagWLAN_FR_PROBERESP {
-
-    unsigned int	uType;
-    unsigned int	len;
-    unsigned char *pBuf;
-    PUWLAN_80211HDR         pHdr;
-    /*-- fixed fields -----------*/
-    PQWORD                  pqwTimestamp;
-    unsigned short *pwBeaconInterval;
-    unsigned short *pwCapInfo;
-    /*-- info elements ----------*/
-    PWLAN_IE_SSID           pSSID;
-    PWLAN_IE_SUPP_RATES     pSuppRates;
-    PWLAN_IE_DS_PARMS       pDSParms;
-    PWLAN_IE_CF_PARMS       pCFParms;
-    PWLAN_IE_IBSS_PARMS     pIBSSParms;
-    PWLAN_IE_RSN            pRSN;
-    PWLAN_IE_RSN_EXT        pRSNWPA;
-    PWLAN_IE_ERP            pERP;
-    PWLAN_IE_SUPP_RATES     pExtSuppRates;
-    PWLAN_IE_COUNTRY        pIE_Country;
-    PWLAN_IE_PW_CONST       pIE_PowerConstraint;
-    PWLAN_IE_CH_SW          pIE_CHSW;
-    PWLAN_IE_IBSS_DFS       pIE_IBSSDFS;
-    PWLAN_IE_QUIET          pIE_Quiet;
-
+	unsigned int	uType;
+	unsigned int	len;
+	unsigned char *pBuf;
+	PUWLAN_80211HDR         pHdr;
+	/*-- fixed fields -----------*/
+	PQWORD                  pqwTimestamp;
+	unsigned short *pwBeaconInterval;
+	unsigned short *pwCapInfo;
+	/*-- info elements ----------*/
+	PWLAN_IE_SSID           pSSID;
+	PWLAN_IE_SUPP_RATES     pSuppRates;
+	PWLAN_IE_DS_PARMS       pDSParms;
+	PWLAN_IE_CF_PARMS       pCFParms;
+	PWLAN_IE_IBSS_PARMS     pIBSSParms;
+	PWLAN_IE_RSN            pRSN;
+	PWLAN_IE_RSN_EXT        pRSNWPA;
+	PWLAN_IE_ERP            pERP;
+	PWLAN_IE_SUPP_RATES     pExtSuppRates;
+	PWLAN_IE_COUNTRY        pIE_Country;
+	PWLAN_IE_PW_CONST       pIE_PowerConstraint;
+	PWLAN_IE_CH_SW          pIE_CHSW;
+	PWLAN_IE_IBSS_DFS       pIE_IBSSDFS;
+	PWLAN_IE_QUIET          pIE_Quiet;
 } WLAN_FR_PROBERESP, *PWLAN_FR_PROBERESP;
 
 // Authentication
 typedef struct tagWLAN_FR_AUTHEN {
-
-    unsigned int	uType;
-    unsigned int	len;
-    unsigned char *pBuf;
-    PUWLAN_80211HDR         pHdr;
-    /*-- fixed fields -----------*/
-    unsigned short *pwAuthAlgorithm;
-    unsigned short *pwAuthSequence;
-    unsigned short *pwStatus;
-    /*-- info elements ----------*/
-    PWLAN_IE_CHALLENGE      pChallenge;
-
+	unsigned int	uType;
+	unsigned int	len;
+	unsigned char *pBuf;
+	PUWLAN_80211HDR         pHdr;
+	/*-- fixed fields -----------*/
+	unsigned short *pwAuthAlgorithm;
+	unsigned short *pwAuthSequence;
+	unsigned short *pwStatus;
+	/*-- info elements ----------*/
+	PWLAN_IE_CHALLENGE      pChallenge;
 } WLAN_FR_AUTHEN, *PWLAN_FR_AUTHEN;
 
 // Deauthenication
 typedef struct tagWLAN_FR_DEAUTHEN {
-
-    unsigned int	uType;
-    unsigned int	len;
-    unsigned char *pBuf;
-    PUWLAN_80211HDR         pHdr;
-    /*-- fixed fields -----------*/
-    unsigned short *pwReason;
-
-    /*-- info elements ----------*/
-
+	unsigned int	uType;
+	unsigned int	len;
+	unsigned char *pBuf;
+	PUWLAN_80211HDR         pHdr;
+	/*-- fixed fields -----------*/
+	unsigned short *pwReason;
+
+	/*-- info elements ----------*/
 } WLAN_FR_DEAUTHEN, *PWLAN_FR_DEAUTHEN;
 
 /*---------------------  Export Functions  --------------------------*/
 
 void
 vMgrEncodeBeacon(
-    PWLAN_FR_BEACON  pFrame
-     );
+	PWLAN_FR_BEACON  pFrame
+);
 
 void
 vMgrDecodeBeacon(
-    PWLAN_FR_BEACON  pFrame
-    );
+	PWLAN_FR_BEACON  pFrame
+);
 
 void
 vMgrEncodeIBSSATIM(
-    PWLAN_FR_IBSSATIM   pFrame
-    );
+	PWLAN_FR_IBSSATIM   pFrame
+);
 
 void
 vMgrDecodeIBSSATIM(
-    PWLAN_FR_IBSSATIM   pFrame
-    );
+	PWLAN_FR_IBSSATIM   pFrame
+);
 
 void
 vMgrEncodeDisassociation(
-    PWLAN_FR_DISASSOC  pFrame
-    );
+	PWLAN_FR_DISASSOC  pFrame
+);
 
 void
 vMgrDecodeDisassociation(
-    PWLAN_FR_DISASSOC  pFrame
-    );
+	PWLAN_FR_DISASSOC  pFrame
+);
 
 void
 vMgrEncodeAssocRequest(
-    PWLAN_FR_ASSOCREQ  pFrame
-    );
+	PWLAN_FR_ASSOCREQ  pFrame
+);
 
 void
 vMgrDecodeAssocRequest(
-    PWLAN_FR_ASSOCREQ  pFrame
-    );
+	PWLAN_FR_ASSOCREQ  pFrame
+);
 
 void
 vMgrEncodeAssocResponse(
-    PWLAN_FR_ASSOCRESP  pFrame
-    );
+	PWLAN_FR_ASSOCRESP  pFrame
+);
 
 void
 vMgrDecodeAssocResponse(
-    PWLAN_FR_ASSOCRESP  pFrame
-    );
+	PWLAN_FR_ASSOCRESP  pFrame
+);
 
 void
 vMgrEncodeReassocRequest(
-    PWLAN_FR_REASSOCREQ  pFrame
-    );
+	PWLAN_FR_REASSOCREQ  pFrame
+);
 
 void
 vMgrDecodeReassocRequest(
-    PWLAN_FR_REASSOCREQ  pFrame
-    );
+	PWLAN_FR_REASSOCREQ  pFrame
+);
 
 void
 vMgrEncodeProbeRequest(
-    PWLAN_FR_PROBEREQ  pFrame
-    );
+	PWLAN_FR_PROBEREQ  pFrame
+);
 
 void
 vMgrDecodeProbeRequest(
-    PWLAN_FR_PROBEREQ  pFrame
-    );
+	PWLAN_FR_PROBEREQ  pFrame
+);
 
 void
 vMgrEncodeProbeResponse(
-    PWLAN_FR_PROBERESP  pFrame
-    );
+	PWLAN_FR_PROBERESP  pFrame
+);
 
 void
 vMgrDecodeProbeResponse(
-    PWLAN_FR_PROBERESP  pFrame
-    );
+	PWLAN_FR_PROBERESP  pFrame
+);
 
 void
 vMgrEncodeAuthen(
-    PWLAN_FR_AUTHEN  pFrame
-    );
+	PWLAN_FR_AUTHEN  pFrame
+);
 
 void
 vMgrDecodeAuthen(
-    PWLAN_FR_AUTHEN  pFrame
-    );
+	PWLAN_FR_AUTHEN  pFrame
+);
 
 void
 vMgrEncodeDeauthen(
-    PWLAN_FR_DEAUTHEN  pFrame
-    );
+	PWLAN_FR_DEAUTHEN  pFrame
+);
 
 void
 vMgrDecodeDeauthen(
-    PWLAN_FR_DEAUTHEN  pFrame
-    );
+	PWLAN_FR_DEAUTHEN  pFrame
+);
 
 void
 vMgrEncodeReassocResponse(
-    PWLAN_FR_REASSOCRESP  pFrame
-    );
+	PWLAN_FR_REASSOCRESP  pFrame
+);
 
 void
 vMgrDecodeReassocResponse(
-    PWLAN_FR_REASSOCRESP  pFrame
-    );
+	PWLAN_FR_REASSOCRESP  pFrame
+);
 
 #endif// __80211MGR_H__
diff --git a/drivers/staging/vt6655/IEEE11h.c b/drivers/staging/vt6655/IEEE11h.c
index cf7364d..dfda3c8 100644
--- a/drivers/staging/vt6655/IEEE11h.c
+++ b/drivers/staging/vt6655/IEEE11h.c
@@ -99,7 +99,7 @@ typedef struct _WLAN_FRAME_TPCREP {
 
 /*---------------------  Static Functions  --------------------------*/
 static bool s_bRxMSRReq(PSMgmtObject pMgmt, PWLAN_FRAME_MSRREQ pMSRReq,
-		unsigned int uLength)
+			unsigned int uLength)
 {
 	size_t    uNumOfEIDs = 0;
 	bool bResult = true;
@@ -107,20 +107,19 @@ static bool s_bRxMSRReq(PSMgmtObject pMgmt, PWLAN_FRAME_MSRREQ pMSRReq,
 	if (uLength <= WLAN_A3FR_MAXLEN)
 		memcpy(pMgmt->abyCurrentMSRReq, pMSRReq, uLength);
 	uNumOfEIDs = ((uLength - offsetof(WLAN_FRAME_MSRREQ,
-			sMSRReqEIDs))/
-			(sizeof(WLAN_IE_MEASURE_REQ)));
+					  sMSRReqEIDs))/
+		      (sizeof(WLAN_IE_MEASURE_REQ)));
 	pMgmt->pCurrMeasureEIDRep = &(((PWLAN_FRAME_MSRREP)
-			(pMgmt->abyCurrentMSRRep))->sMSRRepEIDs[0]);
+				       (pMgmt->abyCurrentMSRRep))->sMSRRepEIDs[0]);
 	pMgmt->uLengthOfRepEIDs = 0;
 	bResult = CARDbStartMeasure(pMgmt->pAdapter,
-				((PWLAN_FRAME_MSRREQ)
-				(pMgmt->abyCurrentMSRReq))->sMSRReqEIDs,
-				uNumOfEIDs
-				);
+				    ((PWLAN_FRAME_MSRREQ)
+				     (pMgmt->abyCurrentMSRReq))->sMSRReqEIDs,
+				    uNumOfEIDs
+);
 	return bResult;
 }
 
-
 static bool s_bRxTPCReq(PSMgmtObject pMgmt,
 			PWLAN_FRAME_TPCREQ pTPCReq,
 			unsigned char byRate,
@@ -132,29 +131,29 @@ static bool s_bRxTPCReq(PSMgmtObject pMgmt,
 	pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool;
 	memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_A3FR_MAXLEN);
 	pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket +
-sizeof(STxMgmtPacket));
+						    sizeof(STxMgmtPacket));
 
 	pFrame = (PWLAN_FRAME_TPCREP)((unsigned char *)pTxPacket +
-sizeof(STxMgmtPacket));
+				      sizeof(STxMgmtPacket));
 
 	pFrame->Header.wFrameCtl = (WLAN_SET_FC_FTYPE(WLAN_FTYPE_MGMT) |
-				WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_ACTION)
-				);
+				    WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_ACTION)
+);
 
 	memcpy(pFrame->Header.abyAddr1,
-		pTPCReq->Header.abyAddr2,
-		WLAN_ADDR_LEN);
+	       pTPCReq->Header.abyAddr2,
+	       WLAN_ADDR_LEN);
 	memcpy(pFrame->Header.abyAddr2,
-		CARDpGetCurrentAddress(pMgmt->pAdapter),
-		WLAN_ADDR_LEN);
+	       CARDpGetCurrentAddress(pMgmt->pAdapter),
+	       WLAN_ADDR_LEN);
 	memcpy(pFrame->Header.abyAddr3,
-		pMgmt->abyCurrBSSID,
-		WLAN_BSSID_LEN);
+	       pMgmt->abyCurrBSSID,
+	       WLAN_BSSID_LEN);
 
 	pFrame->byCategory = 0;
 	pFrame->byAction = 3;
 	pFrame->byDialogToken = ((PWLAN_FRAME_MSRREQ)
-(pMgmt->abyCurrentMSRReq))->byDialogToken;
+				 (pMgmt->abyCurrentMSRReq))->byDialogToken;
 
 	pFrame->sTPCRepEIDs.byElementID = WLAN_EID_TPC_REP;
 	pFrame->sTPCRepEIDs.len = 2;
@@ -185,25 +184,22 @@ sizeof(STxMgmtPacket));
 	default:
 		pFrame->sTPCRepEIDs.byLinkMargin = 82 - byRSSI;
 		break;
-}
+	}
 
 	pTxPacket->cbMPDULen = sizeof(WLAN_FRAME_TPCREP);
 	pTxPacket->cbPayloadLen = sizeof(WLAN_FRAME_TPCREP) -
-WLAN_HDR_ADDR3_LEN;
+		WLAN_HDR_ADDR3_LEN;
 	if (csMgmt_xmit(pMgmt->pAdapter, pTxPacket) != CMD_STATUS_PENDING)
 		return false;
 	return true;
-/*    return (CARDbSendPacket(pMgmt->pAdapter, pFrame, PKT_TYPE_802_11_MNG,
-sizeof(WLAN_FRAME_TPCREP))); */
-
+/*    return CARDbSendPacket(pMgmt->pAdapter, pFrame, PKT_TYPE_802_11_MNG,
+      sizeof(WLAN_FRAME_TPCREP)); */
 }
 
-
 /*---------------------  Export Variables  --------------------------*/
 
 /*---------------------  Export Functions  --------------------------*/
 
-
 /*+
  *
  * Description:
@@ -218,7 +214,7 @@ sizeof(WLAN_FRAME_TPCREP))); */
  *
  * Return Value: None.
  *
--*/
+ -*/
 bool
 IEEE11hbMgrRxAction(void *pMgmtHandle, void *pRxPacket)
 {
@@ -233,86 +229,85 @@ IEEE11hbMgrRxAction(void *pMgmtHandle, void *pRxPacket)
 		return false;
 
 	pAction = (PWLAN_FRAME_ACTION)
-(((PSRxMgmtPacket)pRxPacket)->p80211Header);
+		(((PSRxMgmtPacket)pRxPacket)->p80211Header);
 
 	if (pAction->byCategory == 0) {
 		switch (pAction->byAction) {
 		case ACTION_MSRREQ:
 			return s_bRxMSRReq(pMgmt,
-					(PWLAN_FRAME_MSRREQ)
-					pAction,
-					uLength);
+					   (PWLAN_FRAME_MSRREQ)
+					   pAction,
+					   uLength);
 			break;
 		case ACTION_MSRREP:
 			break;
 		case ACTION_TPCREQ:
 			return s_bRxTPCReq(pMgmt,
-				(PWLAN_FRAME_TPCREQ) pAction,
-				((PSRxMgmtPacket)pRxPacket)->byRxRate,
-				(unsigned char)
-				((PSRxMgmtPacket)pRxPacket)->uRSSI);
+					   (PWLAN_FRAME_TPCREQ) pAction,
+					   ((PSRxMgmtPacket)pRxPacket)->byRxRate,
+					   (unsigned char)
+					   ((PSRxMgmtPacket)pRxPacket)->uRSSI);
 			break;
 		case ACTION_TPCREP:
 			break;
 		case ACTION_CHSW:
 			pChannelSwitch = (PWLAN_IE_CH_SW) (pAction->abyVars);
 			if ((pChannelSwitch->byElementID == WLAN_EID_CH_SWITCH)
-			&& (pChannelSwitch->len == 3)) {
+			    && (pChannelSwitch->len == 3)) {
 				/* valid element id */
 				CARDbChannelSwitch(pMgmt->pAdapter,
-				pChannelSwitch->byMode,
-				get_channel_mapping(pMgmt->pAdapter,
-				pChannelSwitch->byChannel,
-				pMgmt->eCurrentPHYMode),
-				pChannelSwitch->byCount);
+						   pChannelSwitch->byMode,
+						   get_channel_mapping(pMgmt->pAdapter,
+								       pChannelSwitch->byChannel,
+								       pMgmt->eCurrentPHYMode),
+						   pChannelSwitch->byCount);
 			}
 			break;
 		default:
 			DBG_PRT(MSG_LEVEL_DEBUG,
-				KERN_INFO"Unknown Action = %d\n",
+				KERN_INFO "Unknown Action = %d\n",
 				pAction->byAction);
 			break;
 		}
 	} else {
-	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Unknown Category = %d\n",
-pAction->byCategory);
-	pAction->byCategory |= 0x80;
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Unknown Category = %d\n",
+			pAction->byCategory);
+		pAction->byCategory |= 0x80;
 
-	/*return (CARDbSendPacket(pMgmt->pAdapter, pAction, PKT_TYPE_802_11_MNG,
-uLength));*/
-	return true;
+		/*return CARDbSendPacket(pMgmt->pAdapter, pAction, PKT_TYPE_802_11_MNG,
+		  uLength);*/
+		return true;
 	}
 	return true;
 }
 
-
 bool IEEE11hbMSRRepTx(void *pMgmtHandle)
 {
 	PSMgmtObject            pMgmt = (PSMgmtObject) pMgmtHandle;
 	PWLAN_FRAME_MSRREP      pMSRRep = (PWLAN_FRAME_MSRREP)
-(pMgmt->abyCurrentMSRRep + sizeof(STxMgmtPacket));
+		(pMgmt->abyCurrentMSRRep + sizeof(STxMgmtPacket));
 	size_t                    uLength = 0;
 	PSTxMgmtPacket          pTxPacket = NULL;
 
 	pTxPacket = (PSTxMgmtPacket)pMgmt->abyCurrentMSRRep;
 	memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_A3FR_MAXLEN);
 	pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket +
-sizeof(STxMgmtPacket));
+						    sizeof(STxMgmtPacket));
 
 	pMSRRep->Header.wFrameCtl = (WLAN_SET_FC_FTYPE(WLAN_FTYPE_MGMT) |
-				WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_ACTION)
-				);
+				     WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_ACTION)
+);
 
 	memcpy(pMSRRep->Header.abyAddr1, ((PWLAN_FRAME_MSRREQ)
-		(pMgmt->abyCurrentMSRReq))->Header.abyAddr2, WLAN_ADDR_LEN);
+					  (pMgmt->abyCurrentMSRReq))->Header.abyAddr2, WLAN_ADDR_LEN);
 	memcpy(pMSRRep->Header.abyAddr2,
-		CARDpGetCurrentAddress(pMgmt->pAdapter), WLAN_ADDR_LEN);
+	       CARDpGetCurrentAddress(pMgmt->pAdapter), WLAN_ADDR_LEN);
 	memcpy(pMSRRep->Header.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN);
 
 	pMSRRep->byCategory = 0;
 	pMSRRep->byAction = 1;
 	pMSRRep->byDialogToken = ((PWLAN_FRAME_MSRREQ)
-		(pMgmt->abyCurrentMSRReq))->byDialogToken;
+				  (pMgmt->abyCurrentMSRReq))->byDialogToken;
 
 	uLength = pMgmt->uLengthOfRepEIDs + offsetof(WLAN_FRAME_MSRREP,
 						     sMSRRepEIDs);
@@ -322,8 +317,6 @@ sizeof(STxMgmtPacket));
 	if (csMgmt_xmit(pMgmt->pAdapter, pTxPacket) != CMD_STATUS_PENDING)
 		return false;
 	return true;
-/*    return (CARDbSendPacket(pMgmt->pAdapter, pMSRRep, PKT_TYPE_802_11_MNG,
-uLength)); */
-
+/*    return CARDbSendPacket(pMgmt->pAdapter, pMSRRep, PKT_TYPE_802_11_MNG,
+      uLength); */
 }
-
diff --git a/drivers/staging/vt6655/IEEE11h.h b/drivers/staging/vt6655/IEEE11h.h
index 542340b..8819fa1 100644
--- a/drivers/staging/vt6655/IEEE11h.h
+++ b/drivers/staging/vt6655/IEEE11h.h
@@ -45,8 +45,8 @@
 
 /*---------------------  Export Functions  --------------------------*/
 
-bool IEEE11hbMSRRepTx (
-    void *pMgmtHandle
-    );
+bool IEEE11hbMSRRepTx(
+	void *pMgmtHandle
+);
 
 #endif // __IEEE11h_H__
diff --git a/drivers/staging/vt6655/aes_ccmp.c b/drivers/staging/vt6655/aes_ccmp.c
index e30168f..3608148 100644
--- a/drivers/staging/vt6655/aes_ccmp.c
+++ b/drivers/staging/vt6655/aes_ccmp.c
@@ -48,60 +48,60 @@
 
 unsigned char sbox_table[256] =
 {
-0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
-0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
-0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
-0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
-0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
-0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
-0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
-0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
-0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
-0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
-0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
-0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
-0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
-0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
-0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
-0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
+	0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
+	0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
+	0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
+	0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
+	0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
+	0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
+	0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
+	0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
+	0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
+	0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
+	0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
+	0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
+	0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
+	0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
+	0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
+	0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
 };
 
 unsigned char dot2_table[256] = {
-0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
-0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e,
-0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e,
-0x60, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x6c, 0x6e, 0x70, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7e,
-0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9c, 0x9e,
-0xa0, 0xa2, 0xa4, 0xa6, 0xa8, 0xaa, 0xac, 0xae, 0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe,
-0xc0, 0xc2, 0xc4, 0xc6, 0xc8, 0xca, 0xcc, 0xce, 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
-0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, 0xec, 0xee, 0xf0, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfc, 0xfe,
-0x1b, 0x19, 0x1f, 0x1d, 0x13, 0x11, 0x17, 0x15, 0x0b, 0x09, 0x0f, 0x0d, 0x03, 0x01, 0x07, 0x05,
-0x3b, 0x39, 0x3f, 0x3d, 0x33, 0x31, 0x37, 0x35, 0x2b, 0x29, 0x2f, 0x2d, 0x23, 0x21, 0x27, 0x25,
-0x5b, 0x59, 0x5f, 0x5d, 0x53, 0x51, 0x57, 0x55, 0x4b, 0x49, 0x4f, 0x4d, 0x43, 0x41, 0x47, 0x45,
-0x7b, 0x79, 0x7f, 0x7d, 0x73, 0x71, 0x77, 0x75, 0x6b, 0x69, 0x6f, 0x6d, 0x63, 0x61, 0x67, 0x65,
-0x9b, 0x99, 0x9f, 0x9d, 0x93, 0x91, 0x97, 0x95, 0x8b, 0x89, 0x8f, 0x8d, 0x83, 0x81, 0x87, 0x85,
-0xbb, 0xb9, 0xbf, 0xbd, 0xb3, 0xb1, 0xb7, 0xb5, 0xab, 0xa9, 0xaf, 0xad, 0xa3, 0xa1, 0xa7, 0xa5,
-0xdb, 0xd9, 0xdf, 0xdd, 0xd3, 0xd1, 0xd7, 0xd5, 0xcb, 0xc9, 0xcf, 0xcd, 0xc3, 0xc1, 0xc7, 0xc5,
-0xfb, 0xf9, 0xff, 0xfd, 0xf3, 0xf1, 0xf7, 0xf5, 0xeb, 0xe9, 0xef, 0xed, 0xe3, 0xe1, 0xe7, 0xe5
+	0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
+	0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e,
+	0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e,
+	0x60, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x6c, 0x6e, 0x70, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7e,
+	0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9c, 0x9e,
+	0xa0, 0xa2, 0xa4, 0xa6, 0xa8, 0xaa, 0xac, 0xae, 0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe,
+	0xc0, 0xc2, 0xc4, 0xc6, 0xc8, 0xca, 0xcc, 0xce, 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
+	0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, 0xec, 0xee, 0xf0, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfc, 0xfe,
+	0x1b, 0x19, 0x1f, 0x1d, 0x13, 0x11, 0x17, 0x15, 0x0b, 0x09, 0x0f, 0x0d, 0x03, 0x01, 0x07, 0x05,
+	0x3b, 0x39, 0x3f, 0x3d, 0x33, 0x31, 0x37, 0x35, 0x2b, 0x29, 0x2f, 0x2d, 0x23, 0x21, 0x27, 0x25,
+	0x5b, 0x59, 0x5f, 0x5d, 0x53, 0x51, 0x57, 0x55, 0x4b, 0x49, 0x4f, 0x4d, 0x43, 0x41, 0x47, 0x45,
+	0x7b, 0x79, 0x7f, 0x7d, 0x73, 0x71, 0x77, 0x75, 0x6b, 0x69, 0x6f, 0x6d, 0x63, 0x61, 0x67, 0x65,
+	0x9b, 0x99, 0x9f, 0x9d, 0x93, 0x91, 0x97, 0x95, 0x8b, 0x89, 0x8f, 0x8d, 0x83, 0x81, 0x87, 0x85,
+	0xbb, 0xb9, 0xbf, 0xbd, 0xb3, 0xb1, 0xb7, 0xb5, 0xab, 0xa9, 0xaf, 0xad, 0xa3, 0xa1, 0xa7, 0xa5,
+	0xdb, 0xd9, 0xdf, 0xdd, 0xd3, 0xd1, 0xd7, 0xd5, 0xcb, 0xc9, 0xcf, 0xcd, 0xc3, 0xc1, 0xc7, 0xc5,
+	0xfb, 0xf9, 0xff, 0xfd, 0xf3, 0xf1, 0xf7, 0xf5, 0xeb, 0xe9, 0xef, 0xed, 0xe3, 0xe1, 0xe7, 0xe5
 };
 
 unsigned char dot3_table[256] = {
-0x00, 0x03, 0x06, 0x05, 0x0c, 0x0f, 0x0a, 0x09, 0x18, 0x1b, 0x1e, 0x1d, 0x14, 0x17, 0x12, 0x11,
-0x30, 0x33, 0x36, 0x35, 0x3c, 0x3f, 0x3a, 0x39, 0x28, 0x2b, 0x2e, 0x2d, 0x24, 0x27, 0x22, 0x21,
-0x60, 0x63, 0x66, 0x65, 0x6c, 0x6f, 0x6a, 0x69, 0x78, 0x7b, 0x7e, 0x7d, 0x74, 0x77, 0x72, 0x71,
-0x50, 0x53, 0x56, 0x55, 0x5c, 0x5f, 0x5a, 0x59, 0x48, 0x4b, 0x4e, 0x4d, 0x44, 0x47, 0x42, 0x41,
-0xc0, 0xc3, 0xc6, 0xc5, 0xcc, 0xcf, 0xca, 0xc9, 0xd8, 0xdb, 0xde, 0xdd, 0xd4, 0xd7, 0xd2, 0xd1,
-0xf0, 0xf3, 0xf6, 0xf5, 0xfc, 0xff, 0xfa, 0xf9, 0xe8, 0xeb, 0xee, 0xed, 0xe4, 0xe7, 0xe2, 0xe1,
-0xa0, 0xa3, 0xa6, 0xa5, 0xac, 0xaf, 0xaa, 0xa9, 0xb8, 0xbb, 0xbe, 0xbd, 0xb4, 0xb7, 0xb2, 0xb1,
-0x90, 0x93, 0x96, 0x95, 0x9c, 0x9f, 0x9a, 0x99, 0x88, 0x8b, 0x8e, 0x8d, 0x84, 0x87, 0x82, 0x81,
-0x9b, 0x98, 0x9d, 0x9e, 0x97, 0x94, 0x91, 0x92, 0x83, 0x80, 0x85, 0x86, 0x8f, 0x8c, 0x89, 0x8a,
-0xab, 0xa8, 0xad, 0xae, 0xa7, 0xa4, 0xa1, 0xa2, 0xb3, 0xb0, 0xb5, 0xb6, 0xbf, 0xbc, 0xb9, 0xba,
-0xfb, 0xf8, 0xfd, 0xfe, 0xf7, 0xf4, 0xf1, 0xf2, 0xe3, 0xe0, 0xe5, 0xe6, 0xef, 0xec, 0xe9, 0xea,
-0xcb, 0xc8, 0xcd, 0xce, 0xc7, 0xc4, 0xc1, 0xc2, 0xd3, 0xd0, 0xd5, 0xd6, 0xdf, 0xdc, 0xd9, 0xda,
-0x5b, 0x58, 0x5d, 0x5e, 0x57, 0x54, 0x51, 0x52, 0x43, 0x40, 0x45, 0x46, 0x4f, 0x4c, 0x49, 0x4a,
-0x6b, 0x68, 0x6d, 0x6e, 0x67, 0x64, 0x61, 0x62, 0x73, 0x70, 0x75, 0x76, 0x7f, 0x7c, 0x79, 0x7a,
-0x3b, 0x38, 0x3d, 0x3e, 0x37, 0x34, 0x31, 0x32, 0x23, 0x20, 0x25, 0x26, 0x2f, 0x2c, 0x29, 0x2a,
-0x0b, 0x08, 0x0d, 0x0e, 0x07, 0x04, 0x01, 0x02, 0x13, 0x10, 0x15, 0x16, 0x1f, 0x1c, 0x19, 0x1a
+	0x00, 0x03, 0x06, 0x05, 0x0c, 0x0f, 0x0a, 0x09, 0x18, 0x1b, 0x1e, 0x1d, 0x14, 0x17, 0x12, 0x11,
+	0x30, 0x33, 0x36, 0x35, 0x3c, 0x3f, 0x3a, 0x39, 0x28, 0x2b, 0x2e, 0x2d, 0x24, 0x27, 0x22, 0x21,
+	0x60, 0x63, 0x66, 0x65, 0x6c, 0x6f, 0x6a, 0x69, 0x78, 0x7b, 0x7e, 0x7d, 0x74, 0x77, 0x72, 0x71,
+	0x50, 0x53, 0x56, 0x55, 0x5c, 0x5f, 0x5a, 0x59, 0x48, 0x4b, 0x4e, 0x4d, 0x44, 0x47, 0x42, 0x41,
+	0xc0, 0xc3, 0xc6, 0xc5, 0xcc, 0xcf, 0xca, 0xc9, 0xd8, 0xdb, 0xde, 0xdd, 0xd4, 0xd7, 0xd2, 0xd1,
+	0xf0, 0xf3, 0xf6, 0xf5, 0xfc, 0xff, 0xfa, 0xf9, 0xe8, 0xeb, 0xee, 0xed, 0xe4, 0xe7, 0xe2, 0xe1,
+	0xa0, 0xa3, 0xa6, 0xa5, 0xac, 0xaf, 0xaa, 0xa9, 0xb8, 0xbb, 0xbe, 0xbd, 0xb4, 0xb7, 0xb2, 0xb1,
+	0x90, 0x93, 0x96, 0x95, 0x9c, 0x9f, 0x9a, 0x99, 0x88, 0x8b, 0x8e, 0x8d, 0x84, 0x87, 0x82, 0x81,
+	0x9b, 0x98, 0x9d, 0x9e, 0x97, 0x94, 0x91, 0x92, 0x83, 0x80, 0x85, 0x86, 0x8f, 0x8c, 0x89, 0x8a,
+	0xab, 0xa8, 0xad, 0xae, 0xa7, 0xa4, 0xa1, 0xa2, 0xb3, 0xb0, 0xb5, 0xb6, 0xbf, 0xbc, 0xb9, 0xba,
+	0xfb, 0xf8, 0xfd, 0xfe, 0xf7, 0xf4, 0xf1, 0xf2, 0xe3, 0xe0, 0xe5, 0xe6, 0xef, 0xec, 0xe9, 0xea,
+	0xcb, 0xc8, 0xcd, 0xce, 0xc7, 0xc4, 0xc1, 0xc2, 0xd3, 0xd0, 0xd5, 0xd6, 0xdf, 0xdc, 0xd9, 0xda,
+	0x5b, 0x58, 0x5d, 0x5e, 0x57, 0x54, 0x51, 0x52, 0x43, 0x40, 0x45, 0x46, 0x4f, 0x4c, 0x49, 0x4a,
+	0x6b, 0x68, 0x6d, 0x6e, 0x67, 0x64, 0x61, 0x62, 0x73, 0x70, 0x75, 0x76, 0x7f, 0x7c, 0x79, 0x7a,
+	0x3b, 0x38, 0x3d, 0x3e, 0x37, 0x34, 0x31, 0x32, 0x23, 0x20, 0x25, 0x26, 0x2f, 0x2c, 0x29, 0x2a,
+	0x0b, 0x08, 0x0d, 0x0e, 0x07, 0x04, 0x01, 0x02, 0x13, 0x10, 0x15, 0x16, 0x1f, 0x1c, 0x19, 0x1a
 };
 
 /*---------------------  Static Functions  --------------------------*/
@@ -112,121 +112,111 @@ unsigned char dot3_table[256] = {
 
 void xor_128(unsigned char *a, unsigned char *b, unsigned char *out)
 {
-unsigned long *dwPtrA = (unsigned long *) a;
-unsigned long *dwPtrB = (unsigned long *) b;
-unsigned long *dwPtrOut =(unsigned long *) out;
-
-    (*dwPtrOut++) = (*dwPtrA++) ^ (*dwPtrB++);
-    (*dwPtrOut++) = (*dwPtrA++) ^ (*dwPtrB++);
-    (*dwPtrOut++) = (*dwPtrA++) ^ (*dwPtrB++);
-    (*dwPtrOut++) = (*dwPtrA++) ^ (*dwPtrB++);
+	unsigned long *dwPtrA = (unsigned long *)a;
+	unsigned long *dwPtrB = (unsigned long *)b;
+	unsigned long *dwPtrOut = (unsigned long *)out;
+
+	(*dwPtrOut++) = (*dwPtrA++) ^ (*dwPtrB++);
+	(*dwPtrOut++) = (*dwPtrA++) ^ (*dwPtrB++);
+	(*dwPtrOut++) = (*dwPtrA++) ^ (*dwPtrB++);
+	(*dwPtrOut++) = (*dwPtrA++) ^ (*dwPtrB++);
 }
 
-
 void xor_32(unsigned char *a, unsigned char *b, unsigned char *out)
 {
-unsigned long *dwPtrA = (unsigned long *) a;
-unsigned long *dwPtrB = (unsigned long *) b;
-unsigned long *dwPtrOut =(unsigned long *) out;
+	unsigned long *dwPtrA = (unsigned long *)a;
+	unsigned long *dwPtrB = (unsigned long *)b;
+	unsigned long *dwPtrOut = (unsigned long *)out;
 
-    (*dwPtrOut++) = (*dwPtrA++) ^ (*dwPtrB++);
+	(*dwPtrOut++) = (*dwPtrA++) ^ (*dwPtrB++);
 }
 
 void AddRoundKey(unsigned char *key, int round)
 {
-unsigned char sbox_key[4];
-unsigned char rcon_table[10] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36};
+	unsigned char sbox_key[4];
+	unsigned char rcon_table[10] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36};
 
-    sbox_key[0] = sbox_table[key[13]];
-    sbox_key[1] = sbox_table[key[14]];
-    sbox_key[2] = sbox_table[key[15]];
-    sbox_key[3] = sbox_table[key[12]];
+	sbox_key[0] = sbox_table[key[13]];
+	sbox_key[1] = sbox_table[key[14]];
+	sbox_key[2] = sbox_table[key[15]];
+	sbox_key[3] = sbox_table[key[12]];
 
-    key[0] = key[0] ^ rcon_table[round];
-    xor_32(&key[0], sbox_key, &key[0]);
+	key[0] = key[0] ^ rcon_table[round];
+	xor_32(&key[0], sbox_key, &key[0]);
 
-    xor_32(&key[4], &key[0], &key[4]);
-    xor_32(&key[8], &key[4], &key[8]);
-    xor_32(&key[12], &key[8], &key[12]);
+	xor_32(&key[4], &key[0], &key[4]);
+	xor_32(&key[8], &key[4], &key[8]);
+	xor_32(&key[12], &key[8], &key[12]);
 }
 
 void SubBytes(unsigned char *in, unsigned char *out)
 {
-int i;
+	int i;
 
-    for (i=0; i< 16; i++)
-    {
-        out[i] = sbox_table[in[i]];
-    }
+	for (i = 0; i < 16; i++) {
+		out[i] = sbox_table[in[i]];
+	}
 }
 
 void ShiftRows(unsigned char *in, unsigned char *out)
 {
-    out[0]  = in[0];
-    out[1]  = in[5];
-    out[2]  = in[10];
-    out[3]  = in[15];
-    out[4]  = in[4];
-    out[5]  = in[9];
-    out[6]  = in[14];
-    out[7]  = in[3];
-    out[8]  = in[8];
-    out[9]  = in[13];
-    out[10] = in[2];
-    out[11] = in[7];
-    out[12] = in[12];
-    out[13] = in[1];
-    out[14] = in[6];
-    out[15] = in[11];
+	out[0]  = in[0];
+	out[1]  = in[5];
+	out[2]  = in[10];
+	out[3]  = in[15];
+	out[4]  = in[4];
+	out[5]  = in[9];
+	out[6]  = in[14];
+	out[7]  = in[3];
+	out[8]  = in[8];
+	out[9]  = in[13];
+	out[10] = in[2];
+	out[11] = in[7];
+	out[12] = in[12];
+	out[13] = in[1];
+	out[14] = in[6];
+	out[15] = in[11];
 }
 
 void MixColumns(unsigned char *in, unsigned char *out)
 {
-
-    out[0] = dot2_table[in[0]] ^ dot3_table[in[1]] ^ in[2] ^ in[3];
-    out[1] = in[0] ^ dot2_table[in[1]] ^ dot3_table[in[2]] ^ in[3];
-    out[2] = in[0] ^ in[1] ^ dot2_table[in[2]] ^ dot3_table[in[3]];
-    out[3] = dot3_table[in[0]] ^ in[1] ^ in[2] ^ dot2_table[in[3]];
+	out[0] = dot2_table[in[0]] ^ dot3_table[in[1]] ^ in[2] ^ in[3];
+	out[1] = in[0] ^ dot2_table[in[1]] ^ dot3_table[in[2]] ^ in[3];
+	out[2] = in[0] ^ in[1] ^ dot2_table[in[2]] ^ dot3_table[in[3]];
+	out[3] = dot3_table[in[0]] ^ in[1] ^ in[2] ^ dot2_table[in[3]];
 }
 
-
 void AESv128(unsigned char *key, unsigned char *data, unsigned char *ciphertext)
 {
-int  i;
-int  round;
-unsigned char TmpdataA[16];
-unsigned char TmpdataB[16];
-unsigned char abyRoundKey[16];
-
-    for(i=0; i<16; i++)
-        abyRoundKey[i] = key[i];
-
-    for (round = 0; round < 11; round++)
-    {
-        if (round == 0)
-        {
-            xor_128(abyRoundKey, data, ciphertext);
-            AddRoundKey(abyRoundKey, round);
-        }
-        else if (round == 10)
-        {
-            SubBytes(ciphertext, TmpdataA);
-            ShiftRows(TmpdataA, TmpdataB);
-            xor_128(TmpdataB, abyRoundKey, ciphertext);
-        }
-        else // round 1 ~ 9
-        {
-            SubBytes(ciphertext, TmpdataA);
-            ShiftRows(TmpdataA, TmpdataB);
-            MixColumns(&TmpdataB[0], &TmpdataA[0]);
-            MixColumns(&TmpdataB[4], &TmpdataA[4]);
-            MixColumns(&TmpdataB[8], &TmpdataA[8]);
-            MixColumns(&TmpdataB[12], &TmpdataA[12]);
-            xor_128(TmpdataA, abyRoundKey, ciphertext);
-            AddRoundKey(abyRoundKey, round);
-        }
-    }
-
+	int  i;
+	int  round;
+	unsigned char TmpdataA[16];
+	unsigned char TmpdataB[16];
+	unsigned char abyRoundKey[16];
+
+	for (i = 0; i < 16; i++)
+		abyRoundKey[i] = key[i];
+
+	for (round = 0; round < 11; round++) {
+		if (round == 0) {
+			xor_128(abyRoundKey, data, ciphertext);
+			AddRoundKey(abyRoundKey, round);
+		} else if (round == 10) {
+			SubBytes(ciphertext, TmpdataA);
+			ShiftRows(TmpdataA, TmpdataB);
+			xor_128(TmpdataB, abyRoundKey, ciphertext);
+		} else // round 1 ~ 9
+		{
+			SubBytes(ciphertext, TmpdataA);
+			ShiftRows(TmpdataA, TmpdataB);
+			MixColumns(&TmpdataB[0], &TmpdataA[0]);
+			MixColumns(&TmpdataB[4], &TmpdataA[4]);
+			MixColumns(&TmpdataB[8], &TmpdataA[8]);
+			MixColumns(&TmpdataB[12], &TmpdataA[12]);
+			xor_128(TmpdataA, abyRoundKey, ciphertext);
+			AddRoundKey(abyRoundKey, round);
+		}
+	}
 }
 
 /*
@@ -245,158 +235,155 @@ unsigned char abyRoundKey[16];
  */
 bool AESbGenCCMP(unsigned char *pbyRxKey, unsigned char *pbyFrame, unsigned short wFrameSize)
 {
-unsigned char abyNonce[13];
-unsigned char MIC_IV[16];
-unsigned char MIC_HDR1[16];
-unsigned char MIC_HDR2[16];
-unsigned char abyMIC[16];
-unsigned char abyCTRPLD[16];
-unsigned char abyTmp[16];
-unsigned char abyPlainText[16];
-unsigned char abyLastCipher[16];
-
-PS802_11Header  pMACHeader = (PS802_11Header) pbyFrame;
-unsigned char *pbyIV;
-unsigned char *pbyPayload;
-unsigned short wHLen = 22;
-unsigned short wPayloadSize = wFrameSize - 8 - 8 - 4 - WLAN_HDR_ADDR3_LEN;//8 is IV, 8 is MIC, 4 is CRC
-bool bA4 = false;
-unsigned char byTmp;
-unsigned short wCnt;
-int             ii,jj,kk;
-
-
-    pbyIV = pbyFrame + WLAN_HDR_ADDR3_LEN;
-    if ( WLAN_GET_FC_TODS(*(unsigned short *)pbyFrame) &&
-         WLAN_GET_FC_FROMDS(*(unsigned short *)pbyFrame) ) {
-         bA4 = true;
-         pbyIV += 6;             // 6 is 802.11 address4
-         wHLen += 6;
-         wPayloadSize -= 6;
-    }
-    pbyPayload = pbyIV + 8; //IV-length
-
-    abyNonce[0]  = 0x00; //now is 0, if Qos here will be priority
-    memcpy(&(abyNonce[1]), pMACHeader->abyAddr2, ETH_ALEN);
-    abyNonce[7]  = pbyIV[7];
-    abyNonce[8]  = pbyIV[6];
-    abyNonce[9]  = pbyIV[5];
-    abyNonce[10] = pbyIV[4];
-    abyNonce[11] = pbyIV[1];
-    abyNonce[12] = pbyIV[0];
-
-    //MIC_IV
-    MIC_IV[0] = 0x59;
-    memcpy(&(MIC_IV[1]), &(abyNonce[0]), 13);
-    MIC_IV[14] = (unsigned char)(wPayloadSize >> 8);
-    MIC_IV[15] = (unsigned char)(wPayloadSize & 0xff);
-
-    //MIC_HDR1
-    MIC_HDR1[0] = (unsigned char)(wHLen >> 8);
-    MIC_HDR1[1] = (unsigned char)(wHLen & 0xff);
-    byTmp = (unsigned char)(pMACHeader->wFrameCtl & 0xff);
-    MIC_HDR1[2] = byTmp & 0x8f;
-    byTmp = (unsigned char)(pMACHeader->wFrameCtl >> 8);
-    byTmp &= 0x87;
-    MIC_HDR1[3] = byTmp | 0x40;
-    memcpy(&(MIC_HDR1[4]), pMACHeader->abyAddr1, ETH_ALEN);
-    memcpy(&(MIC_HDR1[10]), pMACHeader->abyAddr2, ETH_ALEN);
-
-    //MIC_HDR2
-    memcpy(&(MIC_HDR2[0]), pMACHeader->abyAddr3, ETH_ALEN);
-    byTmp = (unsigned char)(pMACHeader->wSeqCtl & 0xff);
-    MIC_HDR2[6] = byTmp & 0x0f;
-    MIC_HDR2[7] = 0;
-    if ( bA4 ) {
-        memcpy(&(MIC_HDR2[8]), pMACHeader->abyAddr4, ETH_ALEN);
-    } else {
-        MIC_HDR2[8]  = 0x00;
-        MIC_HDR2[9]  = 0x00;
-        MIC_HDR2[10] = 0x00;
-        MIC_HDR2[11] = 0x00;
-        MIC_HDR2[12] = 0x00;
-        MIC_HDR2[13] = 0x00;
-    }
-    MIC_HDR2[14] = 0x00;
-    MIC_HDR2[15] = 0x00;
-
-    //CCMP
-    AESv128(pbyRxKey,MIC_IV,abyMIC);
-    for ( kk=0; kk<16; kk++ ) {
-        abyTmp[kk] = MIC_HDR1[kk] ^ abyMIC[kk];
-    }
-    AESv128(pbyRxKey,abyTmp,abyMIC);
-    for ( kk=0; kk<16; kk++ ) {
-        abyTmp[kk] = MIC_HDR2[kk] ^ abyMIC[kk];
-    }
-    AESv128(pbyRxKey,abyTmp,abyMIC);
-
-    wCnt = 1;
-    abyCTRPLD[0] = 0x01;
-    memcpy(&(abyCTRPLD[1]), &(abyNonce[0]), 13);
-
-    for(jj=wPayloadSize; jj>16; jj=jj-16) {
-
-        abyCTRPLD[14] = (unsigned char) (wCnt >> 8);
-        abyCTRPLD[15] = (unsigned char) (wCnt & 0xff);
-
-        AESv128(pbyRxKey,abyCTRPLD,abyTmp);
-
-        for ( kk=0; kk<16; kk++ ) {
-            abyPlainText[kk] = abyTmp[kk] ^ pbyPayload[kk];
-        }
-        for ( kk=0; kk<16; kk++ ) {
-            abyTmp[kk] = abyMIC[kk] ^ abyPlainText[kk];
-        }
-        AESv128(pbyRxKey,abyTmp,abyMIC);
-
-        memcpy(pbyPayload, abyPlainText, 16);
-        wCnt++;
-        pbyPayload += 16;
-    } //for wPayloadSize
-
-    //last payload
-    memcpy(&(abyLastCipher[0]), pbyPayload, jj);
-    for ( ii=jj; ii<16; ii++ ) {
-        abyLastCipher[ii] = 0x00;
-    }
-
-    abyCTRPLD[14] = (unsigned char) (wCnt >> 8);
-    abyCTRPLD[15] = (unsigned char) (wCnt & 0xff);
-
-    AESv128(pbyRxKey,abyCTRPLD,abyTmp);
-    for ( kk=0; kk<16; kk++ ) {
-        abyPlainText[kk] = abyTmp[kk] ^ abyLastCipher[kk];
-    }
-    memcpy(pbyPayload, abyPlainText, jj);
-    pbyPayload += jj;
-
-    //for MIC calculation
-    for ( ii=jj; ii<16; ii++ ) {
-        abyPlainText[ii] = 0x00;
-    }
-    for ( kk=0; kk<16; kk++ ) {
-        abyTmp[kk] = abyMIC[kk] ^ abyPlainText[kk];
-    }
-    AESv128(pbyRxKey,abyTmp,abyMIC);
-
-    //=>above is the calculate MIC
-    //--------------------------------------------
-
-    wCnt = 0;
-    abyCTRPLD[14] = (unsigned char) (wCnt >> 8);
-    abyCTRPLD[15] = (unsigned char) (wCnt & 0xff);
-    AESv128(pbyRxKey,abyCTRPLD,abyTmp);
-    for ( kk=0; kk<8; kk++ ) {
-        abyTmp[kk] = abyTmp[kk] ^ pbyPayload[kk];
-    }
-    //=>above is the dec-MIC from packet
-    //--------------------------------------------
-
-    if ( !memcmp(abyMIC,abyTmp,8) ) {
-        return true;
-    } else {
-        return false;
-    }
-
+	unsigned char abyNonce[13];
+	unsigned char MIC_IV[16];
+	unsigned char MIC_HDR1[16];
+	unsigned char MIC_HDR2[16];
+	unsigned char abyMIC[16];
+	unsigned char abyCTRPLD[16];
+	unsigned char abyTmp[16];
+	unsigned char abyPlainText[16];
+	unsigned char abyLastCipher[16];
+
+	PS802_11Header  pMACHeader = (PS802_11Header) pbyFrame;
+	unsigned char *pbyIV;
+	unsigned char *pbyPayload;
+	unsigned short wHLen = 22;
+	unsigned short wPayloadSize = wFrameSize - 8 - 8 - 4 - WLAN_HDR_ADDR3_LEN;//8 is IV, 8 is MIC, 4 is CRC
+	bool bA4 = false;
+	unsigned char byTmp;
+	unsigned short wCnt;
+	int ii, jj, kk;
+
+	pbyIV = pbyFrame + WLAN_HDR_ADDR3_LEN;
+	if (WLAN_GET_FC_TODS(*(unsigned short *)pbyFrame) &&
+	    WLAN_GET_FC_FROMDS(*(unsigned short *)pbyFrame)) {
+		bA4 = true;
+		pbyIV += 6;             // 6 is 802.11 address4
+		wHLen += 6;
+		wPayloadSize -= 6;
+	}
+	pbyPayload = pbyIV + 8; //IV-length
+
+	abyNonce[0]  = 0x00; //now is 0, if Qos here will be priority
+	memcpy(&(abyNonce[1]), pMACHeader->abyAddr2, ETH_ALEN);
+	abyNonce[7]  = pbyIV[7];
+	abyNonce[8]  = pbyIV[6];
+	abyNonce[9]  = pbyIV[5];
+	abyNonce[10] = pbyIV[4];
+	abyNonce[11] = pbyIV[1];
+	abyNonce[12] = pbyIV[0];
+
+	//MIC_IV
+	MIC_IV[0] = 0x59;
+	memcpy(&(MIC_IV[1]), &(abyNonce[0]), 13);
+	MIC_IV[14] = (unsigned char)(wPayloadSize >> 8);
+	MIC_IV[15] = (unsigned char)(wPayloadSize & 0xff);
+
+	//MIC_HDR1
+	MIC_HDR1[0] = (unsigned char)(wHLen >> 8);
+	MIC_HDR1[1] = (unsigned char)(wHLen & 0xff);
+	byTmp = (unsigned char)(pMACHeader->wFrameCtl & 0xff);
+	MIC_HDR1[2] = byTmp & 0x8f;
+	byTmp = (unsigned char)(pMACHeader->wFrameCtl >> 8);
+	byTmp &= 0x87;
+	MIC_HDR1[3] = byTmp | 0x40;
+	memcpy(&(MIC_HDR1[4]), pMACHeader->abyAddr1, ETH_ALEN);
+	memcpy(&(MIC_HDR1[10]), pMACHeader->abyAddr2, ETH_ALEN);
+
+	//MIC_HDR2
+	memcpy(&(MIC_HDR2[0]), pMACHeader->abyAddr3, ETH_ALEN);
+	byTmp = (unsigned char)(pMACHeader->wSeqCtl & 0xff);
+	MIC_HDR2[6] = byTmp & 0x0f;
+	MIC_HDR2[7] = 0;
+	if (bA4) {
+		memcpy(&(MIC_HDR2[8]), pMACHeader->abyAddr4, ETH_ALEN);
+	} else {
+		MIC_HDR2[8]  = 0x00;
+		MIC_HDR2[9]  = 0x00;
+		MIC_HDR2[10] = 0x00;
+		MIC_HDR2[11] = 0x00;
+		MIC_HDR2[12] = 0x00;
+		MIC_HDR2[13] = 0x00;
+	}
+	MIC_HDR2[14] = 0x00;
+	MIC_HDR2[15] = 0x00;
+
+	//CCMP
+	AESv128(pbyRxKey, MIC_IV, abyMIC);
+	for (kk = 0; kk < 16; kk++) {
+		abyTmp[kk] = MIC_HDR1[kk] ^ abyMIC[kk];
+	}
+	AESv128(pbyRxKey, abyTmp, abyMIC);
+	for (kk = 0; kk < 16; kk++) {
+		abyTmp[kk] = MIC_HDR2[kk] ^ abyMIC[kk];
+	}
+	AESv128(pbyRxKey, abyTmp, abyMIC);
+
+	wCnt = 1;
+	abyCTRPLD[0] = 0x01;
+	memcpy(&(abyCTRPLD[1]), &(abyNonce[0]), 13);
+
+	for (jj = wPayloadSize; jj > 16; jj = jj - 16) {
+		abyCTRPLD[14] = (unsigned char)(wCnt >> 8);
+		abyCTRPLD[15] = (unsigned char)(wCnt & 0xff);
+
+		AESv128(pbyRxKey, abyCTRPLD, abyTmp);
+
+		for (kk = 0; kk < 16; kk++) {
+			abyPlainText[kk] = abyTmp[kk] ^ pbyPayload[kk];
+		}
+		for (kk = 0; kk < 16; kk++) {
+			abyTmp[kk] = abyMIC[kk] ^ abyPlainText[kk];
+		}
+		AESv128(pbyRxKey, abyTmp, abyMIC);
+
+		memcpy(pbyPayload, abyPlainText, 16);
+		wCnt++;
+		pbyPayload += 16;
+	} //for wPayloadSize
+
+	//last payload
+	memcpy(&(abyLastCipher[0]), pbyPayload, jj);
+	for (ii = jj; ii < 16; ii++) {
+		abyLastCipher[ii] = 0x00;
+	}
+
+	abyCTRPLD[14] = (unsigned char)(wCnt >> 8);
+	abyCTRPLD[15] = (unsigned char)(wCnt & 0xff);
+
+	AESv128(pbyRxKey, abyCTRPLD, abyTmp);
+	for (kk = 0; kk < 16; kk++) {
+		abyPlainText[kk] = abyTmp[kk] ^ abyLastCipher[kk];
+	}
+	memcpy(pbyPayload, abyPlainText, jj);
+	pbyPayload += jj;
+
+	//for MIC calculation
+	for (ii = jj; ii < 16; ii++) {
+		abyPlainText[ii] = 0x00;
+	}
+	for (kk = 0; kk < 16; kk++) {
+		abyTmp[kk] = abyMIC[kk] ^ abyPlainText[kk];
+	}
+	AESv128(pbyRxKey, abyTmp, abyMIC);
+
+	//=>above is the calculate MIC
+	//--------------------------------------------
+
+	wCnt = 0;
+	abyCTRPLD[14] = (unsigned char)(wCnt >> 8);
+	abyCTRPLD[15] = (unsigned char)(wCnt & 0xff);
+	AESv128(pbyRxKey, abyCTRPLD, abyTmp);
+	for (kk = 0; kk < 8; kk++) {
+		abyTmp[kk] = abyTmp[kk] ^ pbyPayload[kk];
+	}
+	//=>above is the dec-MIC from packet
+	//--------------------------------------------
+
+	if (!memcmp(abyMIC, abyTmp, 8)) {
+		return true;
+	} else {
+		return false;
+	}
 }
diff --git a/drivers/staging/vt6655/baseband.c b/drivers/staging/vt6655/baseband.c
index 8d2c6a7..c26418d 100644
--- a/drivers/staging/vt6655/baseband.c
+++ b/drivers/staging/vt6655/baseband.c
@@ -58,7 +58,7 @@
 
 /*---------------------  Static Definitions -------------------------*/
 //static int          msglevel                =MSG_LEVEL_DEBUG;
-static int          msglevel                =MSG_LEVEL_INFO;
+static int msglevel = MSG_LEVEL_INFO;
 
 /*---------------------  Static Classes  ----------------------------*/
 
@@ -74,1646 +74,1641 @@ static int          msglevel                =MSG_LEVEL_INFO;
 
 /*---------------------  Static Variables  --------------------------*/
 
-
-
 #define CB_VT3253_INIT_FOR_RFMD 446
 unsigned char byVT3253InitTab_RFMD[CB_VT3253_INIT_FOR_RFMD][2] = {
-    {0x00, 0x30},
-    {0x01, 0x00},
-    {0x02, 0x00},
-    {0x03, 0x00},
-    {0x04, 0x00},
-    {0x05, 0x00},
-    {0x06, 0x00},
-    {0x07, 0x00},
-    {0x08, 0x70},
-    {0x09, 0x45},
-    {0x0a, 0x2a},
-    {0x0b, 0x76},
-    {0x0c, 0x00},
-    {0x0d, 0x01},
-    {0x0e, 0x80},
-    {0x0f, 0x00},
-    {0x10, 0x00},
-    {0x11, 0x00},
-    {0x12, 0x00},
-    {0x13, 0x00},
-    {0x14, 0x00},
-    {0x15, 0x00},
-    {0x16, 0x00},
-    {0x17, 0x00},
-    {0x18, 0x00},
-    {0x19, 0x00},
-    {0x1a, 0x00},
-    {0x1b, 0x9d},
-    {0x1c, 0x05},
-    {0x1d, 0x00},
-    {0x1e, 0x00},
-    {0x1f, 0x00},
-    {0x20, 0x00},
-    {0x21, 0x00},
-    {0x22, 0x00},
-    {0x23, 0x00},
-    {0x24, 0x00},
-    {0x25, 0x4a},
-    {0x26, 0x00},
-    {0x27, 0x00},
-    {0x28, 0x00},
-    {0x29, 0x00},
-    {0x2a, 0x00},
-    {0x2b, 0x00},
-    {0x2c, 0x00},
-    {0x2d, 0xa8},
-    {0x2e, 0x1a},
-    {0x2f, 0x0c},
-    {0x30, 0x26},
-    {0x31, 0x5b},
-    {0x32, 0x00},
-    {0x33, 0x00},
-    {0x34, 0x00},
-    {0x35, 0x00},
-    {0x36, 0xaa},
-    {0x37, 0xaa},
-    {0x38, 0xff},
-    {0x39, 0xff},
-    {0x3a, 0x00},
-    {0x3b, 0x00},
-    {0x3c, 0x00},
-    {0x3d, 0x0d},
-    {0x3e, 0x51},
-    {0x3f, 0x04},
-    {0x40, 0x00},
-    {0x41, 0x08},
-    {0x42, 0x00},
-    {0x43, 0x08},
-    {0x44, 0x06},
-    {0x45, 0x14},
-    {0x46, 0x05},
-    {0x47, 0x08},
-    {0x48, 0x00},
-    {0x49, 0x00},
-    {0x4a, 0x00},
-    {0x4b, 0x00},
-    {0x4c, 0x09},
-    {0x4d, 0x80},
-    {0x4e, 0x00},
-    {0x4f, 0xc5},
-    {0x50, 0x14},
-    {0x51, 0x19},
-    {0x52, 0x00},
-    {0x53, 0x00},
-    {0x54, 0x00},
-    {0x55, 0x00},
-    {0x56, 0x00},
-    {0x57, 0x00},
-    {0x58, 0x00},
-    {0x59, 0xb0},
-    {0x5a, 0x00},
-    {0x5b, 0x00},
-    {0x5c, 0x00},
-    {0x5d, 0x00},
-    {0x5e, 0x00},
-    {0x5f, 0x00},
-    {0x60, 0x44},
-    {0x61, 0x04},
-    {0x62, 0x00},
-    {0x63, 0x00},
-    {0x64, 0x00},
-    {0x65, 0x00},
-    {0x66, 0x04},
-    {0x67, 0xb7},
-    {0x68, 0x00},
-    {0x69, 0x00},
-    {0x6a, 0x00},
-    {0x6b, 0x00},
-    {0x6c, 0x00},
-    {0x6d, 0x03},
-    {0x6e, 0x01},
-    {0x6f, 0x00},
-    {0x70, 0x00},
-    {0x71, 0x00},
-    {0x72, 0x00},
-    {0x73, 0x00},
-    {0x74, 0x00},
-    {0x75, 0x00},
-    {0x76, 0x00},
-    {0x77, 0x00},
-    {0x78, 0x00},
-    {0x79, 0x00},
-    {0x7a, 0x00},
-    {0x7b, 0x00},
-    {0x7c, 0x00},
-    {0x7d, 0x00},
-    {0x7e, 0x00},
-    {0x7f, 0x00},
-    {0x80, 0x0b},
-    {0x81, 0x00},
-    {0x82, 0x3c},
-    {0x83, 0x00},
-    {0x84, 0x00},
-    {0x85, 0x00},
-    {0x86, 0x00},
-    {0x87, 0x00},
-    {0x88, 0x08},
-    {0x89, 0x00},
-    {0x8a, 0x08},
-    {0x8b, 0xa6},
-    {0x8c, 0x84},
-    {0x8d, 0x47},
-    {0x8e, 0xbb},
-    {0x8f, 0x02},
-    {0x90, 0x21},
-    {0x91, 0x0c},
-    {0x92, 0x04},
-    {0x93, 0x22},
-    {0x94, 0x00},
-    {0x95, 0x00},
-    {0x96, 0x00},
-    {0x97, 0xeb},
-    {0x98, 0x00},
-    {0x99, 0x00},
-    {0x9a, 0x00},
-    {0x9b, 0x00},
-    {0x9c, 0x00},
-    {0x9d, 0x00},
-    {0x9e, 0x00},
-    {0x9f, 0x00},
-    {0xa0, 0x00},
-    {0xa1, 0x00},
-    {0xa2, 0x00},
-    {0xa3, 0x00},
-    {0xa4, 0x00},
-    {0xa5, 0x00},
-    {0xa6, 0x10},
-    {0xa7, 0x04},
-    {0xa8, 0x10},
-    {0xa9, 0x00},
-    {0xaa, 0x8f},
-    {0xab, 0x00},
-    {0xac, 0x00},
-    {0xad, 0x00},
-    {0xae, 0x00},
-    {0xaf, 0x80},
-    {0xb0, 0x38},
-    {0xb1, 0x00},
-    {0xb2, 0x00},
-    {0xb3, 0x00},
-    {0xb4, 0xee},
-    {0xb5, 0xff},
-    {0xb6, 0x10},
-    {0xb7, 0x00},
-    {0xb8, 0x00},
-    {0xb9, 0x00},
-    {0xba, 0x00},
-    {0xbb, 0x03},
-    {0xbc, 0x00},
-    {0xbd, 0x00},
-    {0xbe, 0x00},
-    {0xbf, 0x00},
-    {0xc0, 0x10},
-    {0xc1, 0x10},
-    {0xc2, 0x18},
-    {0xc3, 0x20},
-    {0xc4, 0x10},
-    {0xc5, 0x00},
-    {0xc6, 0x22},
-    {0xc7, 0x14},
-    {0xc8, 0x0f},
-    {0xc9, 0x08},
-    {0xca, 0xa4},
-    {0xcb, 0xa7},
-    {0xcc, 0x3c},
-    {0xcd, 0x10},
-    {0xce, 0x20},
-    {0xcf, 0x00},
-    {0xd0, 0x00},
-    {0xd1, 0x10},
-    {0xd2, 0x00},
-    {0xd3, 0x00},
-    {0xd4, 0x10},
-    {0xd5, 0x33},
-    {0xd6, 0x70},
-    {0xd7, 0x01},
-    {0xd8, 0x00},
-    {0xd9, 0x00},
-    {0xda, 0x00},
-    {0xdb, 0x00},
-    {0xdc, 0x00},
-    {0xdd, 0x00},
-    {0xde, 0x00},
-    {0xdf, 0x00},
-    {0xe0, 0x00},
-    {0xe1, 0x00},
-    {0xe2, 0xcc},
-    {0xe3, 0x04},
-    {0xe4, 0x08},
-    {0xe5, 0x10},
-    {0xe6, 0x00},
-    {0xe7, 0x0e},
-    {0xe8, 0x88},
-    {0xe9, 0xd4},
-    {0xea, 0x05},
-    {0xeb, 0xf0},
-    {0xec, 0x79},
-    {0xed, 0x0f},
-    {0xee, 0x04},
-    {0xef, 0x04},
-    {0xf0, 0x00},
-    {0xf1, 0x00},
-    {0xf2, 0x00},
-    {0xf3, 0x00},
-    {0xf4, 0x00},
-    {0xf5, 0x00},
-    {0xf6, 0x00},
-    {0xf7, 0x00},
-    {0xf8, 0x00},
-    {0xf9, 0x00},
-    {0xF0, 0x00},
-    {0xF1, 0xF8},
-    {0xF0, 0x80},
-    {0xF0, 0x00},
-    {0xF1, 0xF4},
-    {0xF0, 0x81},
-    {0xF0, 0x01},
-    {0xF1, 0xF0},
-    {0xF0, 0x82},
-    {0xF0, 0x02},
-    {0xF1, 0xEC},
-    {0xF0, 0x83},
-    {0xF0, 0x03},
-    {0xF1, 0xE8},
-    {0xF0, 0x84},
-    {0xF0, 0x04},
-    {0xF1, 0xE4},
-    {0xF0, 0x85},
-    {0xF0, 0x05},
-    {0xF1, 0xE0},
-    {0xF0, 0x86},
-    {0xF0, 0x06},
-    {0xF1, 0xDC},
-    {0xF0, 0x87},
-    {0xF0, 0x07},
-    {0xF1, 0xD8},
-    {0xF0, 0x88},
-    {0xF0, 0x08},
-    {0xF1, 0xD4},
-    {0xF0, 0x89},
-    {0xF0, 0x09},
-    {0xF1, 0xD0},
-    {0xF0, 0x8A},
-    {0xF0, 0x0A},
-    {0xF1, 0xCC},
-    {0xF0, 0x8B},
-    {0xF0, 0x0B},
-    {0xF1, 0xC8},
-    {0xF0, 0x8C},
-    {0xF0, 0x0C},
-    {0xF1, 0xC4},
-    {0xF0, 0x8D},
-    {0xF0, 0x0D},
-    {0xF1, 0xC0},
-    {0xF0, 0x8E},
-    {0xF0, 0x0E},
-    {0xF1, 0xBC},
-    {0xF0, 0x8F},
-    {0xF0, 0x0F},
-    {0xF1, 0xB8},
-    {0xF0, 0x90},
-    {0xF0, 0x10},
-    {0xF1, 0xB4},
-    {0xF0, 0x91},
-    {0xF0, 0x11},
-    {0xF1, 0xB0},
-    {0xF0, 0x92},
-    {0xF0, 0x12},
-    {0xF1, 0xAC},
-    {0xF0, 0x93},
-    {0xF0, 0x13},
-    {0xF1, 0xA8},
-    {0xF0, 0x94},
-    {0xF0, 0x14},
-    {0xF1, 0xA4},
-    {0xF0, 0x95},
-    {0xF0, 0x15},
-    {0xF1, 0xA0},
-    {0xF0, 0x96},
-    {0xF0, 0x16},
-    {0xF1, 0x9C},
-    {0xF0, 0x97},
-    {0xF0, 0x17},
-    {0xF1, 0x98},
-    {0xF0, 0x98},
-    {0xF0, 0x18},
-    {0xF1, 0x94},
-    {0xF0, 0x99},
-    {0xF0, 0x19},
-    {0xF1, 0x90},
-    {0xF0, 0x9A},
-    {0xF0, 0x1A},
-    {0xF1, 0x8C},
-    {0xF0, 0x9B},
-    {0xF0, 0x1B},
-    {0xF1, 0x88},
-    {0xF0, 0x9C},
-    {0xF0, 0x1C},
-    {0xF1, 0x84},
-    {0xF0, 0x9D},
-    {0xF0, 0x1D},
-    {0xF1, 0x80},
-    {0xF0, 0x9E},
-    {0xF0, 0x1E},
-    {0xF1, 0x7C},
-    {0xF0, 0x9F},
-    {0xF0, 0x1F},
-    {0xF1, 0x78},
-    {0xF0, 0xA0},
-    {0xF0, 0x20},
-    {0xF1, 0x74},
-    {0xF0, 0xA1},
-    {0xF0, 0x21},
-    {0xF1, 0x70},
-    {0xF0, 0xA2},
-    {0xF0, 0x22},
-    {0xF1, 0x6C},
-    {0xF0, 0xA3},
-    {0xF0, 0x23},
-    {0xF1, 0x68},
-    {0xF0, 0xA4},
-    {0xF0, 0x24},
-    {0xF1, 0x64},
-    {0xF0, 0xA5},
-    {0xF0, 0x25},
-    {0xF1, 0x60},
-    {0xF0, 0xA6},
-    {0xF0, 0x26},
-    {0xF1, 0x5C},
-    {0xF0, 0xA7},
-    {0xF0, 0x27},
-    {0xF1, 0x58},
-    {0xF0, 0xA8},
-    {0xF0, 0x28},
-    {0xF1, 0x54},
-    {0xF0, 0xA9},
-    {0xF0, 0x29},
-    {0xF1, 0x50},
-    {0xF0, 0xAA},
-    {0xF0, 0x2A},
-    {0xF1, 0x4C},
-    {0xF0, 0xAB},
-    {0xF0, 0x2B},
-    {0xF1, 0x48},
-    {0xF0, 0xAC},
-    {0xF0, 0x2C},
-    {0xF1, 0x44},
-    {0xF0, 0xAD},
-    {0xF0, 0x2D},
-    {0xF1, 0x40},
-    {0xF0, 0xAE},
-    {0xF0, 0x2E},
-    {0xF1, 0x3C},
-    {0xF0, 0xAF},
-    {0xF0, 0x2F},
-    {0xF1, 0x38},
-    {0xF0, 0xB0},
-    {0xF0, 0x30},
-    {0xF1, 0x34},
-    {0xF0, 0xB1},
-    {0xF0, 0x31},
-    {0xF1, 0x30},
-    {0xF0, 0xB2},
-    {0xF0, 0x32},
-    {0xF1, 0x2C},
-    {0xF0, 0xB3},
-    {0xF0, 0x33},
-    {0xF1, 0x28},
-    {0xF0, 0xB4},
-    {0xF0, 0x34},
-    {0xF1, 0x24},
-    {0xF0, 0xB5},
-    {0xF0, 0x35},
-    {0xF1, 0x20},
-    {0xF0, 0xB6},
-    {0xF0, 0x36},
-    {0xF1, 0x1C},
-    {0xF0, 0xB7},
-    {0xF0, 0x37},
-    {0xF1, 0x18},
-    {0xF0, 0xB8},
-    {0xF0, 0x38},
-    {0xF1, 0x14},
-    {0xF0, 0xB9},
-    {0xF0, 0x39},
-    {0xF1, 0x10},
-    {0xF0, 0xBA},
-    {0xF0, 0x3A},
-    {0xF1, 0x0C},
-    {0xF0, 0xBB},
-    {0xF0, 0x3B},
-    {0xF1, 0x08},
-    {0xF0, 0x00},
-    {0xF0, 0x3C},
-    {0xF1, 0x04},
-    {0xF0, 0xBD},
-    {0xF0, 0x3D},
-    {0xF1, 0x00},
-    {0xF0, 0xBE},
-    {0xF0, 0x3E},
-    {0xF1, 0x00},
-    {0xF0, 0xBF},
-    {0xF0, 0x3F},
-    {0xF1, 0x00},
-    {0xF0, 0xC0},
-    {0xF0, 0x00},
+	{0x00, 0x30},
+	{0x01, 0x00},
+	{0x02, 0x00},
+	{0x03, 0x00},
+	{0x04, 0x00},
+	{0x05, 0x00},
+	{0x06, 0x00},
+	{0x07, 0x00},
+	{0x08, 0x70},
+	{0x09, 0x45},
+	{0x0a, 0x2a},
+	{0x0b, 0x76},
+	{0x0c, 0x00},
+	{0x0d, 0x01},
+	{0x0e, 0x80},
+	{0x0f, 0x00},
+	{0x10, 0x00},
+	{0x11, 0x00},
+	{0x12, 0x00},
+	{0x13, 0x00},
+	{0x14, 0x00},
+	{0x15, 0x00},
+	{0x16, 0x00},
+	{0x17, 0x00},
+	{0x18, 0x00},
+	{0x19, 0x00},
+	{0x1a, 0x00},
+	{0x1b, 0x9d},
+	{0x1c, 0x05},
+	{0x1d, 0x00},
+	{0x1e, 0x00},
+	{0x1f, 0x00},
+	{0x20, 0x00},
+	{0x21, 0x00},
+	{0x22, 0x00},
+	{0x23, 0x00},
+	{0x24, 0x00},
+	{0x25, 0x4a},
+	{0x26, 0x00},
+	{0x27, 0x00},
+	{0x28, 0x00},
+	{0x29, 0x00},
+	{0x2a, 0x00},
+	{0x2b, 0x00},
+	{0x2c, 0x00},
+	{0x2d, 0xa8},
+	{0x2e, 0x1a},
+	{0x2f, 0x0c},
+	{0x30, 0x26},
+	{0x31, 0x5b},
+	{0x32, 0x00},
+	{0x33, 0x00},
+	{0x34, 0x00},
+	{0x35, 0x00},
+	{0x36, 0xaa},
+	{0x37, 0xaa},
+	{0x38, 0xff},
+	{0x39, 0xff},
+	{0x3a, 0x00},
+	{0x3b, 0x00},
+	{0x3c, 0x00},
+	{0x3d, 0x0d},
+	{0x3e, 0x51},
+	{0x3f, 0x04},
+	{0x40, 0x00},
+	{0x41, 0x08},
+	{0x42, 0x00},
+	{0x43, 0x08},
+	{0x44, 0x06},
+	{0x45, 0x14},
+	{0x46, 0x05},
+	{0x47, 0x08},
+	{0x48, 0x00},
+	{0x49, 0x00},
+	{0x4a, 0x00},
+	{0x4b, 0x00},
+	{0x4c, 0x09},
+	{0x4d, 0x80},
+	{0x4e, 0x00},
+	{0x4f, 0xc5},
+	{0x50, 0x14},
+	{0x51, 0x19},
+	{0x52, 0x00},
+	{0x53, 0x00},
+	{0x54, 0x00},
+	{0x55, 0x00},
+	{0x56, 0x00},
+	{0x57, 0x00},
+	{0x58, 0x00},
+	{0x59, 0xb0},
+	{0x5a, 0x00},
+	{0x5b, 0x00},
+	{0x5c, 0x00},
+	{0x5d, 0x00},
+	{0x5e, 0x00},
+	{0x5f, 0x00},
+	{0x60, 0x44},
+	{0x61, 0x04},
+	{0x62, 0x00},
+	{0x63, 0x00},
+	{0x64, 0x00},
+	{0x65, 0x00},
+	{0x66, 0x04},
+	{0x67, 0xb7},
+	{0x68, 0x00},
+	{0x69, 0x00},
+	{0x6a, 0x00},
+	{0x6b, 0x00},
+	{0x6c, 0x00},
+	{0x6d, 0x03},
+	{0x6e, 0x01},
+	{0x6f, 0x00},
+	{0x70, 0x00},
+	{0x71, 0x00},
+	{0x72, 0x00},
+	{0x73, 0x00},
+	{0x74, 0x00},
+	{0x75, 0x00},
+	{0x76, 0x00},
+	{0x77, 0x00},
+	{0x78, 0x00},
+	{0x79, 0x00},
+	{0x7a, 0x00},
+	{0x7b, 0x00},
+	{0x7c, 0x00},
+	{0x7d, 0x00},
+	{0x7e, 0x00},
+	{0x7f, 0x00},
+	{0x80, 0x0b},
+	{0x81, 0x00},
+	{0x82, 0x3c},
+	{0x83, 0x00},
+	{0x84, 0x00},
+	{0x85, 0x00},
+	{0x86, 0x00},
+	{0x87, 0x00},
+	{0x88, 0x08},
+	{0x89, 0x00},
+	{0x8a, 0x08},
+	{0x8b, 0xa6},
+	{0x8c, 0x84},
+	{0x8d, 0x47},
+	{0x8e, 0xbb},
+	{0x8f, 0x02},
+	{0x90, 0x21},
+	{0x91, 0x0c},
+	{0x92, 0x04},
+	{0x93, 0x22},
+	{0x94, 0x00},
+	{0x95, 0x00},
+	{0x96, 0x00},
+	{0x97, 0xeb},
+	{0x98, 0x00},
+	{0x99, 0x00},
+	{0x9a, 0x00},
+	{0x9b, 0x00},
+	{0x9c, 0x00},
+	{0x9d, 0x00},
+	{0x9e, 0x00},
+	{0x9f, 0x00},
+	{0xa0, 0x00},
+	{0xa1, 0x00},
+	{0xa2, 0x00},
+	{0xa3, 0x00},
+	{0xa4, 0x00},
+	{0xa5, 0x00},
+	{0xa6, 0x10},
+	{0xa7, 0x04},
+	{0xa8, 0x10},
+	{0xa9, 0x00},
+	{0xaa, 0x8f},
+	{0xab, 0x00},
+	{0xac, 0x00},
+	{0xad, 0x00},
+	{0xae, 0x00},
+	{0xaf, 0x80},
+	{0xb0, 0x38},
+	{0xb1, 0x00},
+	{0xb2, 0x00},
+	{0xb3, 0x00},
+	{0xb4, 0xee},
+	{0xb5, 0xff},
+	{0xb6, 0x10},
+	{0xb7, 0x00},
+	{0xb8, 0x00},
+	{0xb9, 0x00},
+	{0xba, 0x00},
+	{0xbb, 0x03},
+	{0xbc, 0x00},
+	{0xbd, 0x00},
+	{0xbe, 0x00},
+	{0xbf, 0x00},
+	{0xc0, 0x10},
+	{0xc1, 0x10},
+	{0xc2, 0x18},
+	{0xc3, 0x20},
+	{0xc4, 0x10},
+	{0xc5, 0x00},
+	{0xc6, 0x22},
+	{0xc7, 0x14},
+	{0xc8, 0x0f},
+	{0xc9, 0x08},
+	{0xca, 0xa4},
+	{0xcb, 0xa7},
+	{0xcc, 0x3c},
+	{0xcd, 0x10},
+	{0xce, 0x20},
+	{0xcf, 0x00},
+	{0xd0, 0x00},
+	{0xd1, 0x10},
+	{0xd2, 0x00},
+	{0xd3, 0x00},
+	{0xd4, 0x10},
+	{0xd5, 0x33},
+	{0xd6, 0x70},
+	{0xd7, 0x01},
+	{0xd8, 0x00},
+	{0xd9, 0x00},
+	{0xda, 0x00},
+	{0xdb, 0x00},
+	{0xdc, 0x00},
+	{0xdd, 0x00},
+	{0xde, 0x00},
+	{0xdf, 0x00},
+	{0xe0, 0x00},
+	{0xe1, 0x00},
+	{0xe2, 0xcc},
+	{0xe3, 0x04},
+	{0xe4, 0x08},
+	{0xe5, 0x10},
+	{0xe6, 0x00},
+	{0xe7, 0x0e},
+	{0xe8, 0x88},
+	{0xe9, 0xd4},
+	{0xea, 0x05},
+	{0xeb, 0xf0},
+	{0xec, 0x79},
+	{0xed, 0x0f},
+	{0xee, 0x04},
+	{0xef, 0x04},
+	{0xf0, 0x00},
+	{0xf1, 0x00},
+	{0xf2, 0x00},
+	{0xf3, 0x00},
+	{0xf4, 0x00},
+	{0xf5, 0x00},
+	{0xf6, 0x00},
+	{0xf7, 0x00},
+	{0xf8, 0x00},
+	{0xf9, 0x00},
+	{0xF0, 0x00},
+	{0xF1, 0xF8},
+	{0xF0, 0x80},
+	{0xF0, 0x00},
+	{0xF1, 0xF4},
+	{0xF0, 0x81},
+	{0xF0, 0x01},
+	{0xF1, 0xF0},
+	{0xF0, 0x82},
+	{0xF0, 0x02},
+	{0xF1, 0xEC},
+	{0xF0, 0x83},
+	{0xF0, 0x03},
+	{0xF1, 0xE8},
+	{0xF0, 0x84},
+	{0xF0, 0x04},
+	{0xF1, 0xE4},
+	{0xF0, 0x85},
+	{0xF0, 0x05},
+	{0xF1, 0xE0},
+	{0xF0, 0x86},
+	{0xF0, 0x06},
+	{0xF1, 0xDC},
+	{0xF0, 0x87},
+	{0xF0, 0x07},
+	{0xF1, 0xD8},
+	{0xF0, 0x88},
+	{0xF0, 0x08},
+	{0xF1, 0xD4},
+	{0xF0, 0x89},
+	{0xF0, 0x09},
+	{0xF1, 0xD0},
+	{0xF0, 0x8A},
+	{0xF0, 0x0A},
+	{0xF1, 0xCC},
+	{0xF0, 0x8B},
+	{0xF0, 0x0B},
+	{0xF1, 0xC8},
+	{0xF0, 0x8C},
+	{0xF0, 0x0C},
+	{0xF1, 0xC4},
+	{0xF0, 0x8D},
+	{0xF0, 0x0D},
+	{0xF1, 0xC0},
+	{0xF0, 0x8E},
+	{0xF0, 0x0E},
+	{0xF1, 0xBC},
+	{0xF0, 0x8F},
+	{0xF0, 0x0F},
+	{0xF1, 0xB8},
+	{0xF0, 0x90},
+	{0xF0, 0x10},
+	{0xF1, 0xB4},
+	{0xF0, 0x91},
+	{0xF0, 0x11},
+	{0xF1, 0xB0},
+	{0xF0, 0x92},
+	{0xF0, 0x12},
+	{0xF1, 0xAC},
+	{0xF0, 0x93},
+	{0xF0, 0x13},
+	{0xF1, 0xA8},
+	{0xF0, 0x94},
+	{0xF0, 0x14},
+	{0xF1, 0xA4},
+	{0xF0, 0x95},
+	{0xF0, 0x15},
+	{0xF1, 0xA0},
+	{0xF0, 0x96},
+	{0xF0, 0x16},
+	{0xF1, 0x9C},
+	{0xF0, 0x97},
+	{0xF0, 0x17},
+	{0xF1, 0x98},
+	{0xF0, 0x98},
+	{0xF0, 0x18},
+	{0xF1, 0x94},
+	{0xF0, 0x99},
+	{0xF0, 0x19},
+	{0xF1, 0x90},
+	{0xF0, 0x9A},
+	{0xF0, 0x1A},
+	{0xF1, 0x8C},
+	{0xF0, 0x9B},
+	{0xF0, 0x1B},
+	{0xF1, 0x88},
+	{0xF0, 0x9C},
+	{0xF0, 0x1C},
+	{0xF1, 0x84},
+	{0xF0, 0x9D},
+	{0xF0, 0x1D},
+	{0xF1, 0x80},
+	{0xF0, 0x9E},
+	{0xF0, 0x1E},
+	{0xF1, 0x7C},
+	{0xF0, 0x9F},
+	{0xF0, 0x1F},
+	{0xF1, 0x78},
+	{0xF0, 0xA0},
+	{0xF0, 0x20},
+	{0xF1, 0x74},
+	{0xF0, 0xA1},
+	{0xF0, 0x21},
+	{0xF1, 0x70},
+	{0xF0, 0xA2},
+	{0xF0, 0x22},
+	{0xF1, 0x6C},
+	{0xF0, 0xA3},
+	{0xF0, 0x23},
+	{0xF1, 0x68},
+	{0xF0, 0xA4},
+	{0xF0, 0x24},
+	{0xF1, 0x64},
+	{0xF0, 0xA5},
+	{0xF0, 0x25},
+	{0xF1, 0x60},
+	{0xF0, 0xA6},
+	{0xF0, 0x26},
+	{0xF1, 0x5C},
+	{0xF0, 0xA7},
+	{0xF0, 0x27},
+	{0xF1, 0x58},
+	{0xF0, 0xA8},
+	{0xF0, 0x28},
+	{0xF1, 0x54},
+	{0xF0, 0xA9},
+	{0xF0, 0x29},
+	{0xF1, 0x50},
+	{0xF0, 0xAA},
+	{0xF0, 0x2A},
+	{0xF1, 0x4C},
+	{0xF0, 0xAB},
+	{0xF0, 0x2B},
+	{0xF1, 0x48},
+	{0xF0, 0xAC},
+	{0xF0, 0x2C},
+	{0xF1, 0x44},
+	{0xF0, 0xAD},
+	{0xF0, 0x2D},
+	{0xF1, 0x40},
+	{0xF0, 0xAE},
+	{0xF0, 0x2E},
+	{0xF1, 0x3C},
+	{0xF0, 0xAF},
+	{0xF0, 0x2F},
+	{0xF1, 0x38},
+	{0xF0, 0xB0},
+	{0xF0, 0x30},
+	{0xF1, 0x34},
+	{0xF0, 0xB1},
+	{0xF0, 0x31},
+	{0xF1, 0x30},
+	{0xF0, 0xB2},
+	{0xF0, 0x32},
+	{0xF1, 0x2C},
+	{0xF0, 0xB3},
+	{0xF0, 0x33},
+	{0xF1, 0x28},
+	{0xF0, 0xB4},
+	{0xF0, 0x34},
+	{0xF1, 0x24},
+	{0xF0, 0xB5},
+	{0xF0, 0x35},
+	{0xF1, 0x20},
+	{0xF0, 0xB6},
+	{0xF0, 0x36},
+	{0xF1, 0x1C},
+	{0xF0, 0xB7},
+	{0xF0, 0x37},
+	{0xF1, 0x18},
+	{0xF0, 0xB8},
+	{0xF0, 0x38},
+	{0xF1, 0x14},
+	{0xF0, 0xB9},
+	{0xF0, 0x39},
+	{0xF1, 0x10},
+	{0xF0, 0xBA},
+	{0xF0, 0x3A},
+	{0xF1, 0x0C},
+	{0xF0, 0xBB},
+	{0xF0, 0x3B},
+	{0xF1, 0x08},
+	{0xF0, 0x00},
+	{0xF0, 0x3C},
+	{0xF1, 0x04},
+	{0xF0, 0xBD},
+	{0xF0, 0x3D},
+	{0xF1, 0x00},
+	{0xF0, 0xBE},
+	{0xF0, 0x3E},
+	{0xF1, 0x00},
+	{0xF0, 0xBF},
+	{0xF0, 0x3F},
+	{0xF1, 0x00},
+	{0xF0, 0xC0},
+	{0xF0, 0x00},
 };
 
 #define CB_VT3253B0_INIT_FOR_RFMD 256
 unsigned char byVT3253B0_RFMD[CB_VT3253B0_INIT_FOR_RFMD][2] = {
-    {0x00, 0x31},
-    {0x01, 0x00},
-    {0x02, 0x00},
-    {0x03, 0x00},
-    {0x04, 0x00},
-    {0x05, 0x81},
-    {0x06, 0x00},
-    {0x07, 0x00},
-    {0x08, 0x38},
-    {0x09, 0x45},
-    {0x0a, 0x2a},
-    {0x0b, 0x76},
-    {0x0c, 0x00},
-    {0x0d, 0x00},
-    {0x0e, 0x80},
-    {0x0f, 0x00},
-    {0x10, 0x00},
-    {0x11, 0x00},
-    {0x12, 0x00},
-    {0x13, 0x00},
-    {0x14, 0x00},
-    {0x15, 0x00},
-    {0x16, 0x00},
-    {0x17, 0x00},
-    {0x18, 0x00},
-    {0x19, 0x00},
-    {0x1a, 0x00},
-    {0x1b, 0x8e},
-    {0x1c, 0x06},
-    {0x1d, 0x00},
-    {0x1e, 0x00},
-    {0x1f, 0x00},
-    {0x20, 0x00},
-    {0x21, 0x00},
-    {0x22, 0x00},
-    {0x23, 0x00},
-    {0x24, 0x00},
-    {0x25, 0x4a},
-    {0x26, 0x00},
-    {0x27, 0x00},
-    {0x28, 0x00},
-    {0x29, 0x00},
-    {0x2a, 0x00},
-    {0x2b, 0x00},
-    {0x2c, 0x00},
-    {0x2d, 0x34},
-    {0x2e, 0x18},
-    {0x2f, 0x0c},
-    {0x30, 0x26},
-    {0x31, 0x5b},
-    {0x32, 0x00},
-    {0x33, 0x00},
-    {0x34, 0x00},
-    {0x35, 0x00},
-    {0x36, 0xaa},
-    {0x37, 0xaa},
-    {0x38, 0xff},
-    {0x39, 0xff},
-    {0x3a, 0xf8},
-    {0x3b, 0x00},
-    {0x3c, 0x00},
-    {0x3d, 0x09},
-    {0x3e, 0x0d},
-    {0x3f, 0x04},
-    {0x40, 0x00},
-    {0x41, 0x08},
-    {0x42, 0x00},
-    {0x43, 0x08},
-    {0x44, 0x08},
-    {0x45, 0x14},
-    {0x46, 0x05},
-    {0x47, 0x08},
-    {0x48, 0x00},
-    {0x49, 0x00},
-    {0x4a, 0x00},
-    {0x4b, 0x00},
-    {0x4c, 0x09},
-    {0x4d, 0x80},
-    {0x4e, 0x00},
-    {0x4f, 0xc5},
-    {0x50, 0x14},
-    {0x51, 0x19},
-    {0x52, 0x00},
-    {0x53, 0x00},
-    {0x54, 0x00},
-    {0x55, 0x00},
-    {0x56, 0x00},
-    {0x57, 0x00},
-    {0x58, 0x00},
-    {0x59, 0xb0},
-    {0x5a, 0x00},
-    {0x5b, 0x00},
-    {0x5c, 0x00},
-    {0x5d, 0x00},
-    {0x5e, 0x00},
-    {0x5f, 0x00},
-    {0x60, 0x39},
-    {0x61, 0x83},
-    {0x62, 0x00},
-    {0x63, 0x00},
-    {0x64, 0x00},
-    {0x65, 0x00},
-    {0x66, 0xc0},
-    {0x67, 0x49},
-    {0x68, 0x00},
-    {0x69, 0x00},
-    {0x6a, 0x00},
-    {0x6b, 0x00},
-    {0x6c, 0x00},
-    {0x6d, 0x03},
-    {0x6e, 0x01},
-    {0x6f, 0x00},
-    {0x70, 0x00},
-    {0x71, 0x00},
-    {0x72, 0x00},
-    {0x73, 0x00},
-    {0x74, 0x00},
-    {0x75, 0x00},
-    {0x76, 0x00},
-    {0x77, 0x00},
-    {0x78, 0x00},
-    {0x79, 0x00},
-    {0x7a, 0x00},
-    {0x7b, 0x00},
-    {0x7c, 0x00},
-    {0x7d, 0x00},
-    {0x7e, 0x00},
-    {0x7f, 0x00},
-    {0x80, 0x89},
-    {0x81, 0x00},
-    {0x82, 0x0e},
-    {0x83, 0x00},
-    {0x84, 0x00},
-    {0x85, 0x00},
-    {0x86, 0x00},
-    {0x87, 0x00},
-    {0x88, 0x08},
-    {0x89, 0x00},
-    {0x8a, 0x0e},
-    {0x8b, 0xa7},
-    {0x8c, 0x88},
-    {0x8d, 0x47},
-    {0x8e, 0xaa},
-    {0x8f, 0x02},
-    {0x90, 0x23},
-    {0x91, 0x0c},
-    {0x92, 0x06},
-    {0x93, 0x08},
-    {0x94, 0x00},
-    {0x95, 0x00},
-    {0x96, 0x00},
-    {0x97, 0xeb},
-    {0x98, 0x00},
-    {0x99, 0x00},
-    {0x9a, 0x00},
-    {0x9b, 0x00},
-    {0x9c, 0x00},
-    {0x9d, 0x00},
-    {0x9e, 0x00},
-    {0x9f, 0x00},
-    {0xa0, 0x00},
-    {0xa1, 0x00},
-    {0xa2, 0x00},
-    {0xa3, 0xcd},
-    {0xa4, 0x07},
-    {0xa5, 0x33},
-    {0xa6, 0x18},
-    {0xa7, 0x00},
-    {0xa8, 0x18},
-    {0xa9, 0x00},
-    {0xaa, 0x28},
-    {0xab, 0x00},
-    {0xac, 0x00},
-    {0xad, 0x00},
-    {0xae, 0x00},
-    {0xaf, 0x18},
-    {0xb0, 0x38},
-    {0xb1, 0x30},
-    {0xb2, 0x00},
-    {0xb3, 0x00},
-    {0xb4, 0x00},
-    {0xb5, 0x00},
-    {0xb6, 0x84},
-    {0xb7, 0xfd},
-    {0xb8, 0x00},
-    {0xb9, 0x00},
-    {0xba, 0x00},
-    {0xbb, 0x03},
-    {0xbc, 0x00},
-    {0xbd, 0x00},
-    {0xbe, 0x00},
-    {0xbf, 0x00},
-    {0xc0, 0x10},
-    {0xc1, 0x20},
-    {0xc2, 0x18},
-    {0xc3, 0x20},
-    {0xc4, 0x10},
-    {0xc5, 0x2c},
-    {0xc6, 0x1e},
-    {0xc7, 0x10},
-    {0xc8, 0x12},
-    {0xc9, 0x01},
-    {0xca, 0x6f},
-    {0xcb, 0xa7},
-    {0xcc, 0x3c},
-    {0xcd, 0x10},
-    {0xce, 0x00},
-    {0xcf, 0x22},
-    {0xd0, 0x00},
-    {0xd1, 0x10},
-    {0xd2, 0x00},
-    {0xd3, 0x00},
-    {0xd4, 0x10},
-    {0xd5, 0x33},
-    {0xd6, 0x80},
-    {0xd7, 0x21},
-    {0xd8, 0x00},
-    {0xd9, 0x00},
-    {0xda, 0x00},
-    {0xdb, 0x00},
-    {0xdc, 0x00},
-    {0xdd, 0x00},
-    {0xde, 0x00},
-    {0xdf, 0x00},
-    {0xe0, 0x00},
-    {0xe1, 0xB3},
-    {0xe2, 0x00},
-    {0xe3, 0x00},
-    {0xe4, 0x00},
-    {0xe5, 0x10},
-    {0xe6, 0x00},
-    {0xe7, 0x18},
-    {0xe8, 0x08},
-    {0xe9, 0xd4},
-    {0xea, 0x00},
-    {0xeb, 0xff},
-    {0xec, 0x79},
-    {0xed, 0x10},
-    {0xee, 0x30},
-    {0xef, 0x02},
-    {0xf0, 0x00},
-    {0xf1, 0x09},
-    {0xf2, 0x00},
-    {0xf3, 0x00},
-    {0xf4, 0x00},
-    {0xf5, 0x00},
-    {0xf6, 0x00},
-    {0xf7, 0x00},
-    {0xf8, 0x00},
-    {0xf9, 0x00},
-    {0xfa, 0x00},
-    {0xfb, 0x00},
-    {0xfc, 0x00},
-    {0xfd, 0x00},
-    {0xfe, 0x00},
-    {0xff, 0x00},
+	{0x00, 0x31},
+	{0x01, 0x00},
+	{0x02, 0x00},
+	{0x03, 0x00},
+	{0x04, 0x00},
+	{0x05, 0x81},
+	{0x06, 0x00},
+	{0x07, 0x00},
+	{0x08, 0x38},
+	{0x09, 0x45},
+	{0x0a, 0x2a},
+	{0x0b, 0x76},
+	{0x0c, 0x00},
+	{0x0d, 0x00},
+	{0x0e, 0x80},
+	{0x0f, 0x00},
+	{0x10, 0x00},
+	{0x11, 0x00},
+	{0x12, 0x00},
+	{0x13, 0x00},
+	{0x14, 0x00},
+	{0x15, 0x00},
+	{0x16, 0x00},
+	{0x17, 0x00},
+	{0x18, 0x00},
+	{0x19, 0x00},
+	{0x1a, 0x00},
+	{0x1b, 0x8e},
+	{0x1c, 0x06},
+	{0x1d, 0x00},
+	{0x1e, 0x00},
+	{0x1f, 0x00},
+	{0x20, 0x00},
+	{0x21, 0x00},
+	{0x22, 0x00},
+	{0x23, 0x00},
+	{0x24, 0x00},
+	{0x25, 0x4a},
+	{0x26, 0x00},
+	{0x27, 0x00},
+	{0x28, 0x00},
+	{0x29, 0x00},
+	{0x2a, 0x00},
+	{0x2b, 0x00},
+	{0x2c, 0x00},
+	{0x2d, 0x34},
+	{0x2e, 0x18},
+	{0x2f, 0x0c},
+	{0x30, 0x26},
+	{0x31, 0x5b},
+	{0x32, 0x00},
+	{0x33, 0x00},
+	{0x34, 0x00},
+	{0x35, 0x00},
+	{0x36, 0xaa},
+	{0x37, 0xaa},
+	{0x38, 0xff},
+	{0x39, 0xff},
+	{0x3a, 0xf8},
+	{0x3b, 0x00},
+	{0x3c, 0x00},
+	{0x3d, 0x09},
+	{0x3e, 0x0d},
+	{0x3f, 0x04},
+	{0x40, 0x00},
+	{0x41, 0x08},
+	{0x42, 0x00},
+	{0x43, 0x08},
+	{0x44, 0x08},
+	{0x45, 0x14},
+	{0x46, 0x05},
+	{0x47, 0x08},
+	{0x48, 0x00},
+	{0x49, 0x00},
+	{0x4a, 0x00},
+	{0x4b, 0x00},
+	{0x4c, 0x09},
+	{0x4d, 0x80},
+	{0x4e, 0x00},
+	{0x4f, 0xc5},
+	{0x50, 0x14},
+	{0x51, 0x19},
+	{0x52, 0x00},
+	{0x53, 0x00},
+	{0x54, 0x00},
+	{0x55, 0x00},
+	{0x56, 0x00},
+	{0x57, 0x00},
+	{0x58, 0x00},
+	{0x59, 0xb0},
+	{0x5a, 0x00},
+	{0x5b, 0x00},
+	{0x5c, 0x00},
+	{0x5d, 0x00},
+	{0x5e, 0x00},
+	{0x5f, 0x00},
+	{0x60, 0x39},
+	{0x61, 0x83},
+	{0x62, 0x00},
+	{0x63, 0x00},
+	{0x64, 0x00},
+	{0x65, 0x00},
+	{0x66, 0xc0},
+	{0x67, 0x49},
+	{0x68, 0x00},
+	{0x69, 0x00},
+	{0x6a, 0x00},
+	{0x6b, 0x00},
+	{0x6c, 0x00},
+	{0x6d, 0x03},
+	{0x6e, 0x01},
+	{0x6f, 0x00},
+	{0x70, 0x00},
+	{0x71, 0x00},
+	{0x72, 0x00},
+	{0x73, 0x00},
+	{0x74, 0x00},
+	{0x75, 0x00},
+	{0x76, 0x00},
+	{0x77, 0x00},
+	{0x78, 0x00},
+	{0x79, 0x00},
+	{0x7a, 0x00},
+	{0x7b, 0x00},
+	{0x7c, 0x00},
+	{0x7d, 0x00},
+	{0x7e, 0x00},
+	{0x7f, 0x00},
+	{0x80, 0x89},
+	{0x81, 0x00},
+	{0x82, 0x0e},
+	{0x83, 0x00},
+	{0x84, 0x00},
+	{0x85, 0x00},
+	{0x86, 0x00},
+	{0x87, 0x00},
+	{0x88, 0x08},
+	{0x89, 0x00},
+	{0x8a, 0x0e},
+	{0x8b, 0xa7},
+	{0x8c, 0x88},
+	{0x8d, 0x47},
+	{0x8e, 0xaa},
+	{0x8f, 0x02},
+	{0x90, 0x23},
+	{0x91, 0x0c},
+	{0x92, 0x06},
+	{0x93, 0x08},
+	{0x94, 0x00},
+	{0x95, 0x00},
+	{0x96, 0x00},
+	{0x97, 0xeb},
+	{0x98, 0x00},
+	{0x99, 0x00},
+	{0x9a, 0x00},
+	{0x9b, 0x00},
+	{0x9c, 0x00},
+	{0x9d, 0x00},
+	{0x9e, 0x00},
+	{0x9f, 0x00},
+	{0xa0, 0x00},
+	{0xa1, 0x00},
+	{0xa2, 0x00},
+	{0xa3, 0xcd},
+	{0xa4, 0x07},
+	{0xa5, 0x33},
+	{0xa6, 0x18},
+	{0xa7, 0x00},
+	{0xa8, 0x18},
+	{0xa9, 0x00},
+	{0xaa, 0x28},
+	{0xab, 0x00},
+	{0xac, 0x00},
+	{0xad, 0x00},
+	{0xae, 0x00},
+	{0xaf, 0x18},
+	{0xb0, 0x38},
+	{0xb1, 0x30},
+	{0xb2, 0x00},
+	{0xb3, 0x00},
+	{0xb4, 0x00},
+	{0xb5, 0x00},
+	{0xb6, 0x84},
+	{0xb7, 0xfd},
+	{0xb8, 0x00},
+	{0xb9, 0x00},
+	{0xba, 0x00},
+	{0xbb, 0x03},
+	{0xbc, 0x00},
+	{0xbd, 0x00},
+	{0xbe, 0x00},
+	{0xbf, 0x00},
+	{0xc0, 0x10},
+	{0xc1, 0x20},
+	{0xc2, 0x18},
+	{0xc3, 0x20},
+	{0xc4, 0x10},
+	{0xc5, 0x2c},
+	{0xc6, 0x1e},
+	{0xc7, 0x10},
+	{0xc8, 0x12},
+	{0xc9, 0x01},
+	{0xca, 0x6f},
+	{0xcb, 0xa7},
+	{0xcc, 0x3c},
+	{0xcd, 0x10},
+	{0xce, 0x00},
+	{0xcf, 0x22},
+	{0xd0, 0x00},
+	{0xd1, 0x10},
+	{0xd2, 0x00},
+	{0xd3, 0x00},
+	{0xd4, 0x10},
+	{0xd5, 0x33},
+	{0xd6, 0x80},
+	{0xd7, 0x21},
+	{0xd8, 0x00},
+	{0xd9, 0x00},
+	{0xda, 0x00},
+	{0xdb, 0x00},
+	{0xdc, 0x00},
+	{0xdd, 0x00},
+	{0xde, 0x00},
+	{0xdf, 0x00},
+	{0xe0, 0x00},
+	{0xe1, 0xB3},
+	{0xe2, 0x00},
+	{0xe3, 0x00},
+	{0xe4, 0x00},
+	{0xe5, 0x10},
+	{0xe6, 0x00},
+	{0xe7, 0x18},
+	{0xe8, 0x08},
+	{0xe9, 0xd4},
+	{0xea, 0x00},
+	{0xeb, 0xff},
+	{0xec, 0x79},
+	{0xed, 0x10},
+	{0xee, 0x30},
+	{0xef, 0x02},
+	{0xf0, 0x00},
+	{0xf1, 0x09},
+	{0xf2, 0x00},
+	{0xf3, 0x00},
+	{0xf4, 0x00},
+	{0xf5, 0x00},
+	{0xf6, 0x00},
+	{0xf7, 0x00},
+	{0xf8, 0x00},
+	{0xf9, 0x00},
+	{0xfa, 0x00},
+	{0xfb, 0x00},
+	{0xfc, 0x00},
+	{0xfd, 0x00},
+	{0xfe, 0x00},
+	{0xff, 0x00},
 };
 
 #define CB_VT3253B0_AGC_FOR_RFMD2959 195
 // For RFMD2959
 unsigned char byVT3253B0_AGC4_RFMD2959[CB_VT3253B0_AGC_FOR_RFMD2959][2] = {
-    {0xF0, 0x00},
-    {0xF1, 0x3E},
-    {0xF0, 0x80},
-    {0xF0, 0x00},
-    {0xF1, 0x3E},
-    {0xF0, 0x81},
-    {0xF0, 0x01},
-    {0xF1, 0x3E},
-    {0xF0, 0x82},
-    {0xF0, 0x02},
-    {0xF1, 0x3E},
-    {0xF0, 0x83},
-    {0xF0, 0x03},
-    {0xF1, 0x3B},
-    {0xF0, 0x84},
-    {0xF0, 0x04},
-    {0xF1, 0x39},
-    {0xF0, 0x85},
-    {0xF0, 0x05},
-    {0xF1, 0x38},
-    {0xF0, 0x86},
-    {0xF0, 0x06},
-    {0xF1, 0x37},
-    {0xF0, 0x87},
-    {0xF0, 0x07},
-    {0xF1, 0x36},
-    {0xF0, 0x88},
-    {0xF0, 0x08},
-    {0xF1, 0x35},
-    {0xF0, 0x89},
-    {0xF0, 0x09},
-    {0xF1, 0x35},
-    {0xF0, 0x8A},
-    {0xF0, 0x0A},
-    {0xF1, 0x34},
-    {0xF0, 0x8B},
-    {0xF0, 0x0B},
-    {0xF1, 0x34},
-    {0xF0, 0x8C},
-    {0xF0, 0x0C},
-    {0xF1, 0x33},
-    {0xF0, 0x8D},
-    {0xF0, 0x0D},
-    {0xF1, 0x32},
-    {0xF0, 0x8E},
-    {0xF0, 0x0E},
-    {0xF1, 0x31},
-    {0xF0, 0x8F},
-    {0xF0, 0x0F},
-    {0xF1, 0x30},
-    {0xF0, 0x90},
-    {0xF0, 0x10},
-    {0xF1, 0x2F},
-    {0xF0, 0x91},
-    {0xF0, 0x11},
-    {0xF1, 0x2F},
-    {0xF0, 0x92},
-    {0xF0, 0x12},
-    {0xF1, 0x2E},
-    {0xF0, 0x93},
-    {0xF0, 0x13},
-    {0xF1, 0x2D},
-    {0xF0, 0x94},
-    {0xF0, 0x14},
-    {0xF1, 0x2C},
-    {0xF0, 0x95},
-    {0xF0, 0x15},
-    {0xF1, 0x2B},
-    {0xF0, 0x96},
-    {0xF0, 0x16},
-    {0xF1, 0x2B},
-    {0xF0, 0x97},
-    {0xF0, 0x17},
-    {0xF1, 0x2A},
-    {0xF0, 0x98},
-    {0xF0, 0x18},
-    {0xF1, 0x29},
-    {0xF0, 0x99},
-    {0xF0, 0x19},
-    {0xF1, 0x28},
-    {0xF0, 0x9A},
-    {0xF0, 0x1A},
-    {0xF1, 0x27},
-    {0xF0, 0x9B},
-    {0xF0, 0x1B},
-    {0xF1, 0x26},
-    {0xF0, 0x9C},
-    {0xF0, 0x1C},
-    {0xF1, 0x25},
-    {0xF0, 0x9D},
-    {0xF0, 0x1D},
-    {0xF1, 0x24},
-    {0xF0, 0x9E},
-    {0xF0, 0x1E},
-    {0xF1, 0x24},
-    {0xF0, 0x9F},
-    {0xF0, 0x1F},
-    {0xF1, 0x23},
-    {0xF0, 0xA0},
-    {0xF0, 0x20},
-    {0xF1, 0x22},
-    {0xF0, 0xA1},
-    {0xF0, 0x21},
-    {0xF1, 0x21},
-    {0xF0, 0xA2},
-    {0xF0, 0x22},
-    {0xF1, 0x20},
-    {0xF0, 0xA3},
-    {0xF0, 0x23},
-    {0xF1, 0x20},
-    {0xF0, 0xA4},
-    {0xF0, 0x24},
-    {0xF1, 0x1F},
-    {0xF0, 0xA5},
-    {0xF0, 0x25},
-    {0xF1, 0x1E},
-    {0xF0, 0xA6},
-    {0xF0, 0x26},
-    {0xF1, 0x1D},
-    {0xF0, 0xA7},
-    {0xF0, 0x27},
-    {0xF1, 0x1C},
-    {0xF0, 0xA8},
-    {0xF0, 0x28},
-    {0xF1, 0x1B},
-    {0xF0, 0xA9},
-    {0xF0, 0x29},
-    {0xF1, 0x1B},
-    {0xF0, 0xAA},
-    {0xF0, 0x2A},
-    {0xF1, 0x1A},
-    {0xF0, 0xAB},
-    {0xF0, 0x2B},
-    {0xF1, 0x1A},
-    {0xF0, 0xAC},
-    {0xF0, 0x2C},
-    {0xF1, 0x19},
-    {0xF0, 0xAD},
-    {0xF0, 0x2D},
-    {0xF1, 0x18},
-    {0xF0, 0xAE},
-    {0xF0, 0x2E},
-    {0xF1, 0x17},
-    {0xF0, 0xAF},
-    {0xF0, 0x2F},
-    {0xF1, 0x16},
-    {0xF0, 0xB0},
-    {0xF0, 0x30},
-    {0xF1, 0x15},
-    {0xF0, 0xB1},
-    {0xF0, 0x31},
-    {0xF1, 0x15},
-    {0xF0, 0xB2},
-    {0xF0, 0x32},
-    {0xF1, 0x15},
-    {0xF0, 0xB3},
-    {0xF0, 0x33},
-    {0xF1, 0x14},
-    {0xF0, 0xB4},
-    {0xF0, 0x34},
-    {0xF1, 0x13},
-    {0xF0, 0xB5},
-    {0xF0, 0x35},
-    {0xF1, 0x12},
-    {0xF0, 0xB6},
-    {0xF0, 0x36},
-    {0xF1, 0x11},
-    {0xF0, 0xB7},
-    {0xF0, 0x37},
-    {0xF1, 0x10},
-    {0xF0, 0xB8},
-    {0xF0, 0x38},
-    {0xF1, 0x0F},
-    {0xF0, 0xB9},
-    {0xF0, 0x39},
-    {0xF1, 0x0E},
-    {0xF0, 0xBA},
-    {0xF0, 0x3A},
-    {0xF1, 0x0D},
-    {0xF0, 0xBB},
-    {0xF0, 0x3B},
-    {0xF1, 0x0C},
-    {0xF0, 0xBC},
-    {0xF0, 0x3C},
-    {0xF1, 0x0B},
-    {0xF0, 0xBD},
-    {0xF0, 0x3D},
-    {0xF1, 0x0B},
-    {0xF0, 0xBE},
-    {0xF0, 0x3E},
-    {0xF1, 0x0A},
-    {0xF0, 0xBF},
-    {0xF0, 0x3F},
-    {0xF1, 0x09},
-    {0xF0, 0x00},
+	{0xF0, 0x00},
+	{0xF1, 0x3E},
+	{0xF0, 0x80},
+	{0xF0, 0x00},
+	{0xF1, 0x3E},
+	{0xF0, 0x81},
+	{0xF0, 0x01},
+	{0xF1, 0x3E},
+	{0xF0, 0x82},
+	{0xF0, 0x02},
+	{0xF1, 0x3E},
+	{0xF0, 0x83},
+	{0xF0, 0x03},
+	{0xF1, 0x3B},
+	{0xF0, 0x84},
+	{0xF0, 0x04},
+	{0xF1, 0x39},
+	{0xF0, 0x85},
+	{0xF0, 0x05},
+	{0xF1, 0x38},
+	{0xF0, 0x86},
+	{0xF0, 0x06},
+	{0xF1, 0x37},
+	{0xF0, 0x87},
+	{0xF0, 0x07},
+	{0xF1, 0x36},
+	{0xF0, 0x88},
+	{0xF0, 0x08},
+	{0xF1, 0x35},
+	{0xF0, 0x89},
+	{0xF0, 0x09},
+	{0xF1, 0x35},
+	{0xF0, 0x8A},
+	{0xF0, 0x0A},
+	{0xF1, 0x34},
+	{0xF0, 0x8B},
+	{0xF0, 0x0B},
+	{0xF1, 0x34},
+	{0xF0, 0x8C},
+	{0xF0, 0x0C},
+	{0xF1, 0x33},
+	{0xF0, 0x8D},
+	{0xF0, 0x0D},
+	{0xF1, 0x32},
+	{0xF0, 0x8E},
+	{0xF0, 0x0E},
+	{0xF1, 0x31},
+	{0xF0, 0x8F},
+	{0xF0, 0x0F},
+	{0xF1, 0x30},
+	{0xF0, 0x90},
+	{0xF0, 0x10},
+	{0xF1, 0x2F},
+	{0xF0, 0x91},
+	{0xF0, 0x11},
+	{0xF1, 0x2F},
+	{0xF0, 0x92},
+	{0xF0, 0x12},
+	{0xF1, 0x2E},
+	{0xF0, 0x93},
+	{0xF0, 0x13},
+	{0xF1, 0x2D},
+	{0xF0, 0x94},
+	{0xF0, 0x14},
+	{0xF1, 0x2C},
+	{0xF0, 0x95},
+	{0xF0, 0x15},
+	{0xF1, 0x2B},
+	{0xF0, 0x96},
+	{0xF0, 0x16},
+	{0xF1, 0x2B},
+	{0xF0, 0x97},
+	{0xF0, 0x17},
+	{0xF1, 0x2A},
+	{0xF0, 0x98},
+	{0xF0, 0x18},
+	{0xF1, 0x29},
+	{0xF0, 0x99},
+	{0xF0, 0x19},
+	{0xF1, 0x28},
+	{0xF0, 0x9A},
+	{0xF0, 0x1A},
+	{0xF1, 0x27},
+	{0xF0, 0x9B},
+	{0xF0, 0x1B},
+	{0xF1, 0x26},
+	{0xF0, 0x9C},
+	{0xF0, 0x1C},
+	{0xF1, 0x25},
+	{0xF0, 0x9D},
+	{0xF0, 0x1D},
+	{0xF1, 0x24},
+	{0xF0, 0x9E},
+	{0xF0, 0x1E},
+	{0xF1, 0x24},
+	{0xF0, 0x9F},
+	{0xF0, 0x1F},
+	{0xF1, 0x23},
+	{0xF0, 0xA0},
+	{0xF0, 0x20},
+	{0xF1, 0x22},
+	{0xF0, 0xA1},
+	{0xF0, 0x21},
+	{0xF1, 0x21},
+	{0xF0, 0xA2},
+	{0xF0, 0x22},
+	{0xF1, 0x20},
+	{0xF0, 0xA3},
+	{0xF0, 0x23},
+	{0xF1, 0x20},
+	{0xF0, 0xA4},
+	{0xF0, 0x24},
+	{0xF1, 0x1F},
+	{0xF0, 0xA5},
+	{0xF0, 0x25},
+	{0xF1, 0x1E},
+	{0xF0, 0xA6},
+	{0xF0, 0x26},
+	{0xF1, 0x1D},
+	{0xF0, 0xA7},
+	{0xF0, 0x27},
+	{0xF1, 0x1C},
+	{0xF0, 0xA8},
+	{0xF0, 0x28},
+	{0xF1, 0x1B},
+	{0xF0, 0xA9},
+	{0xF0, 0x29},
+	{0xF1, 0x1B},
+	{0xF0, 0xAA},
+	{0xF0, 0x2A},
+	{0xF1, 0x1A},
+	{0xF0, 0xAB},
+	{0xF0, 0x2B},
+	{0xF1, 0x1A},
+	{0xF0, 0xAC},
+	{0xF0, 0x2C},
+	{0xF1, 0x19},
+	{0xF0, 0xAD},
+	{0xF0, 0x2D},
+	{0xF1, 0x18},
+	{0xF0, 0xAE},
+	{0xF0, 0x2E},
+	{0xF1, 0x17},
+	{0xF0, 0xAF},
+	{0xF0, 0x2F},
+	{0xF1, 0x16},
+	{0xF0, 0xB0},
+	{0xF0, 0x30},
+	{0xF1, 0x15},
+	{0xF0, 0xB1},
+	{0xF0, 0x31},
+	{0xF1, 0x15},
+	{0xF0, 0xB2},
+	{0xF0, 0x32},
+	{0xF1, 0x15},
+	{0xF0, 0xB3},
+	{0xF0, 0x33},
+	{0xF1, 0x14},
+	{0xF0, 0xB4},
+	{0xF0, 0x34},
+	{0xF1, 0x13},
+	{0xF0, 0xB5},
+	{0xF0, 0x35},
+	{0xF1, 0x12},
+	{0xF0, 0xB6},
+	{0xF0, 0x36},
+	{0xF1, 0x11},
+	{0xF0, 0xB7},
+	{0xF0, 0x37},
+	{0xF1, 0x10},
+	{0xF0, 0xB8},
+	{0xF0, 0x38},
+	{0xF1, 0x0F},
+	{0xF0, 0xB9},
+	{0xF0, 0x39},
+	{0xF1, 0x0E},
+	{0xF0, 0xBA},
+	{0xF0, 0x3A},
+	{0xF1, 0x0D},
+	{0xF0, 0xBB},
+	{0xF0, 0x3B},
+	{0xF1, 0x0C},
+	{0xF0, 0xBC},
+	{0xF0, 0x3C},
+	{0xF1, 0x0B},
+	{0xF0, 0xBD},
+	{0xF0, 0x3D},
+	{0xF1, 0x0B},
+	{0xF0, 0xBE},
+	{0xF0, 0x3E},
+	{0xF1, 0x0A},
+	{0xF0, 0xBF},
+	{0xF0, 0x3F},
+	{0xF1, 0x09},
+	{0xF0, 0x00},
 };
 
 #define CB_VT3253B0_INIT_FOR_AIROHA2230 256
 // For AIROHA
 unsigned char byVT3253B0_AIROHA2230[CB_VT3253B0_INIT_FOR_AIROHA2230][2] = {
-    {0x00, 0x31},
-    {0x01, 0x00},
-    {0x02, 0x00},
-    {0x03, 0x00},
-    {0x04, 0x00},
-    {0x05, 0x80},
-    {0x06, 0x00},
-    {0x07, 0x00},
-    {0x08, 0x70},
-    {0x09, 0x41},
-    {0x0a, 0x2A},
-    {0x0b, 0x76},
-    {0x0c, 0x00},
-    {0x0d, 0x00},
-    {0x0e, 0x80},
-    {0x0f, 0x00},
-    {0x10, 0x00},
-    {0x11, 0x00},
-    {0x12, 0x00},
-    {0x13, 0x00},
-    {0x14, 0x00},
-    {0x15, 0x00},
-    {0x16, 0x00},
-    {0x17, 0x00},
-    {0x18, 0x00},
-    {0x19, 0x00},
-    {0x1a, 0x00},
-    {0x1b, 0x8f},
-    {0x1c, 0x09},
-    {0x1d, 0x00},
-    {0x1e, 0x00},
-    {0x1f, 0x00},
-    {0x20, 0x00},
-    {0x21, 0x00},
-    {0x22, 0x00},
-    {0x23, 0x00},
-    {0x24, 0x00},
-    {0x25, 0x4a},
-    {0x26, 0x00},
-    {0x27, 0x00},
-    {0x28, 0x00},
-    {0x29, 0x00},
-    {0x2a, 0x00},
-    {0x2b, 0x00},
-    {0x2c, 0x00},
-    {0x2d, 0x4a},
-    {0x2e, 0x00},
-    {0x2f, 0x0a},
-    {0x30, 0x26},
-    {0x31, 0x5b},
-    {0x32, 0x00},
-    {0x33, 0x00},
-    {0x34, 0x00},
-    {0x35, 0x00},
-    {0x36, 0xaa},
-    {0x37, 0xaa},
-    {0x38, 0xff},
-    {0x39, 0xff},
-    {0x3a, 0x79},
-    {0x3b, 0x00},
-    {0x3c, 0x00},
-    {0x3d, 0x0b},
-    {0x3e, 0x48},
-    {0x3f, 0x04},
-    {0x40, 0x00},
-    {0x41, 0x08},
-    {0x42, 0x00},
-    {0x43, 0x08},
-    {0x44, 0x08},
-    {0x45, 0x14},
-    {0x46, 0x05},
-    {0x47, 0x09},
-    {0x48, 0x00},
-    {0x49, 0x00},
-    {0x4a, 0x00},
-    {0x4b, 0x00},
-    {0x4c, 0x09},
-    {0x4d, 0x73},
-    {0x4e, 0x00},
-    {0x4f, 0xc5},
-    {0x50, 0x15},
-    {0x51, 0x19},
-    {0x52, 0x00},
-    {0x53, 0x00},
-    {0x54, 0x00},
-    {0x55, 0x00},
-    {0x56, 0x00},
-    {0x57, 0x00},
-    {0x58, 0x00},
-    {0x59, 0xb0},
-    {0x5a, 0x00},
-    {0x5b, 0x00},
-    {0x5c, 0x00},
-    {0x5d, 0x00},
-    {0x5e, 0x00},
-    {0x5f, 0x00},
-    {0x60, 0xe4},
-    {0x61, 0x80},
-    {0x62, 0x00},
-    {0x63, 0x00},
-    {0x64, 0x00},
-    {0x65, 0x00},
-    {0x66, 0x98},
-    {0x67, 0x0a},
-    {0x68, 0x00},
-    {0x69, 0x00},
-    {0x6a, 0x00},
-    {0x6b, 0x00},
-    //{0x6c, 0x80},
-    {0x6c, 0x00}, //RobertYu:20050125, request by JJSue
-    {0x6d, 0x03},
-    {0x6e, 0x01},
-    {0x6f, 0x00},
-    {0x70, 0x00},
-    {0x71, 0x00},
-    {0x72, 0x00},
-    {0x73, 0x00},
-    {0x74, 0x00},
-    {0x75, 0x00},
-    {0x76, 0x00},
-    {0x77, 0x00},
-    {0x78, 0x00},
-    {0x79, 0x00},
-    {0x7a, 0x00},
-    {0x7b, 0x00},
-    {0x7c, 0x00},
-    {0x7d, 0x00},
-    {0x7e, 0x00},
-    {0x7f, 0x00},
-    {0x80, 0x8c},
-    {0x81, 0x01},
-    {0x82, 0x09},
-    {0x83, 0x00},
-    {0x84, 0x00},
-    {0x85, 0x00},
-    {0x86, 0x00},
-    {0x87, 0x00},
-    {0x88, 0x08},
-    {0x89, 0x00},
-    {0x8a, 0x0f},
-    {0x8b, 0xb7},
-    {0x8c, 0x88},
-    {0x8d, 0x47},
-    {0x8e, 0xaa},
-    {0x8f, 0x02},
-    {0x90, 0x22},
-    {0x91, 0x00},
-    {0x92, 0x00},
-    {0x93, 0x00},
-    {0x94, 0x00},
-    {0x95, 0x00},
-    {0x96, 0x00},
-    {0x97, 0xeb},
-    {0x98, 0x00},
-    {0x99, 0x00},
-    {0x9a, 0x00},
-    {0x9b, 0x00},
-    {0x9c, 0x00},
-    {0x9d, 0x00},
-    {0x9e, 0x00},
-    {0x9f, 0x01},
-    {0xa0, 0x00},
-    {0xa1, 0x00},
-    {0xa2, 0x00},
-    {0xa3, 0x00},
-    {0xa4, 0x00},
-    {0xa5, 0x00},
-    {0xa6, 0x10},
-    {0xa7, 0x00},
-    {0xa8, 0x18},
-    {0xa9, 0x00},
-    {0xaa, 0x00},
-    {0xab, 0x00},
-    {0xac, 0x00},
-    {0xad, 0x00},
-    {0xae, 0x00},
-    {0xaf, 0x18},
-    {0xb0, 0x38},
-    {0xb1, 0x30},
-    {0xb2, 0x00},
-    {0xb3, 0x00},
-    {0xb4, 0xff},
-    {0xb5, 0x0f},
-    {0xb6, 0xe4},
-    {0xb7, 0xe2},
-    {0xb8, 0x00},
-    {0xb9, 0x00},
-    {0xba, 0x00},
-    {0xbb, 0x03},
-    {0xbc, 0x01},
-    {0xbd, 0x00},
-    {0xbe, 0x00},
-    {0xbf, 0x00},
-    {0xc0, 0x18},
-    {0xc1, 0x20},
-    {0xc2, 0x07},
-    {0xc3, 0x18},
-    {0xc4, 0xff},
-    {0xc5, 0x2c},
-    {0xc6, 0x0c},
-    {0xc7, 0x0a},
-    {0xc8, 0x0e},
-    {0xc9, 0x01},
-    {0xca, 0x68},
-    {0xcb, 0xa7},
-    {0xcc, 0x3c},
-    {0xcd, 0x10},
-    {0xce, 0x00},
-    {0xcf, 0x25},
-    {0xd0, 0x40},
-    {0xd1, 0x12},
-    {0xd2, 0x00},
-    {0xd3, 0x00},
-    {0xd4, 0x10},
-    {0xd5, 0x28},
-    {0xd6, 0x80},
-    {0xd7, 0x2A},
-    {0xd8, 0x00},
-    {0xd9, 0x00},
-    {0xda, 0x00},
-    {0xdb, 0x00},
-    {0xdc, 0x00},
-    {0xdd, 0x00},
-    {0xde, 0x00},
-    {0xdf, 0x00},
-    {0xe0, 0x00},
-    {0xe1, 0xB3},
-    {0xe2, 0x00},
-    {0xe3, 0x00},
-    {0xe4, 0x00},
-    {0xe5, 0x10},
-    {0xe6, 0x00},
-    {0xe7, 0x1C},
-    {0xe8, 0x00},
-    {0xe9, 0xf4},
-    {0xea, 0x00},
-    {0xeb, 0xff},
-    {0xec, 0x79},
-    {0xed, 0x20},
-    {0xee, 0x30},
-    {0xef, 0x01},
-    {0xf0, 0x00},
-    {0xf1, 0x3e},
-    {0xf2, 0x00},
-    {0xf3, 0x00},
-    {0xf4, 0x00},
-    {0xf5, 0x00},
-    {0xf6, 0x00},
-    {0xf7, 0x00},
-    {0xf8, 0x00},
-    {0xf9, 0x00},
-    {0xfa, 0x00},
-    {0xfb, 0x00},
-    {0xfc, 0x00},
-    {0xfd, 0x00},
-    {0xfe, 0x00},
-    {0xff, 0x00},
+	{0x00, 0x31},
+	{0x01, 0x00},
+	{0x02, 0x00},
+	{0x03, 0x00},
+	{0x04, 0x00},
+	{0x05, 0x80},
+	{0x06, 0x00},
+	{0x07, 0x00},
+	{0x08, 0x70},
+	{0x09, 0x41},
+	{0x0a, 0x2A},
+	{0x0b, 0x76},
+	{0x0c, 0x00},
+	{0x0d, 0x00},
+	{0x0e, 0x80},
+	{0x0f, 0x00},
+	{0x10, 0x00},
+	{0x11, 0x00},
+	{0x12, 0x00},
+	{0x13, 0x00},
+	{0x14, 0x00},
+	{0x15, 0x00},
+	{0x16, 0x00},
+	{0x17, 0x00},
+	{0x18, 0x00},
+	{0x19, 0x00},
+	{0x1a, 0x00},
+	{0x1b, 0x8f},
+	{0x1c, 0x09},
+	{0x1d, 0x00},
+	{0x1e, 0x00},
+	{0x1f, 0x00},
+	{0x20, 0x00},
+	{0x21, 0x00},
+	{0x22, 0x00},
+	{0x23, 0x00},
+	{0x24, 0x00},
+	{0x25, 0x4a},
+	{0x26, 0x00},
+	{0x27, 0x00},
+	{0x28, 0x00},
+	{0x29, 0x00},
+	{0x2a, 0x00},
+	{0x2b, 0x00},
+	{0x2c, 0x00},
+	{0x2d, 0x4a},
+	{0x2e, 0x00},
+	{0x2f, 0x0a},
+	{0x30, 0x26},
+	{0x31, 0x5b},
+	{0x32, 0x00},
+	{0x33, 0x00},
+	{0x34, 0x00},
+	{0x35, 0x00},
+	{0x36, 0xaa},
+	{0x37, 0xaa},
+	{0x38, 0xff},
+	{0x39, 0xff},
+	{0x3a, 0x79},
+	{0x3b, 0x00},
+	{0x3c, 0x00},
+	{0x3d, 0x0b},
+	{0x3e, 0x48},
+	{0x3f, 0x04},
+	{0x40, 0x00},
+	{0x41, 0x08},
+	{0x42, 0x00},
+	{0x43, 0x08},
+	{0x44, 0x08},
+	{0x45, 0x14},
+	{0x46, 0x05},
+	{0x47, 0x09},
+	{0x48, 0x00},
+	{0x49, 0x00},
+	{0x4a, 0x00},
+	{0x4b, 0x00},
+	{0x4c, 0x09},
+	{0x4d, 0x73},
+	{0x4e, 0x00},
+	{0x4f, 0xc5},
+	{0x50, 0x15},
+	{0x51, 0x19},
+	{0x52, 0x00},
+	{0x53, 0x00},
+	{0x54, 0x00},
+	{0x55, 0x00},
+	{0x56, 0x00},
+	{0x57, 0x00},
+	{0x58, 0x00},
+	{0x59, 0xb0},
+	{0x5a, 0x00},
+	{0x5b, 0x00},
+	{0x5c, 0x00},
+	{0x5d, 0x00},
+	{0x5e, 0x00},
+	{0x5f, 0x00},
+	{0x60, 0xe4},
+	{0x61, 0x80},
+	{0x62, 0x00},
+	{0x63, 0x00},
+	{0x64, 0x00},
+	{0x65, 0x00},
+	{0x66, 0x98},
+	{0x67, 0x0a},
+	{0x68, 0x00},
+	{0x69, 0x00},
+	{0x6a, 0x00},
+	{0x6b, 0x00},
+	//{0x6c, 0x80},
+	{0x6c, 0x00}, //RobertYu:20050125, request by JJSue
+	{0x6d, 0x03},
+	{0x6e, 0x01},
+	{0x6f, 0x00},
+	{0x70, 0x00},
+	{0x71, 0x00},
+	{0x72, 0x00},
+	{0x73, 0x00},
+	{0x74, 0x00},
+	{0x75, 0x00},
+	{0x76, 0x00},
+	{0x77, 0x00},
+	{0x78, 0x00},
+	{0x79, 0x00},
+	{0x7a, 0x00},
+	{0x7b, 0x00},
+	{0x7c, 0x00},
+	{0x7d, 0x00},
+	{0x7e, 0x00},
+	{0x7f, 0x00},
+	{0x80, 0x8c},
+	{0x81, 0x01},
+	{0x82, 0x09},
+	{0x83, 0x00},
+	{0x84, 0x00},
+	{0x85, 0x00},
+	{0x86, 0x00},
+	{0x87, 0x00},
+	{0x88, 0x08},
+	{0x89, 0x00},
+	{0x8a, 0x0f},
+	{0x8b, 0xb7},
+	{0x8c, 0x88},
+	{0x8d, 0x47},
+	{0x8e, 0xaa},
+	{0x8f, 0x02},
+	{0x90, 0x22},
+	{0x91, 0x00},
+	{0x92, 0x00},
+	{0x93, 0x00},
+	{0x94, 0x00},
+	{0x95, 0x00},
+	{0x96, 0x00},
+	{0x97, 0xeb},
+	{0x98, 0x00},
+	{0x99, 0x00},
+	{0x9a, 0x00},
+	{0x9b, 0x00},
+	{0x9c, 0x00},
+	{0x9d, 0x00},
+	{0x9e, 0x00},
+	{0x9f, 0x01},
+	{0xa0, 0x00},
+	{0xa1, 0x00},
+	{0xa2, 0x00},
+	{0xa3, 0x00},
+	{0xa4, 0x00},
+	{0xa5, 0x00},
+	{0xa6, 0x10},
+	{0xa7, 0x00},
+	{0xa8, 0x18},
+	{0xa9, 0x00},
+	{0xaa, 0x00},
+	{0xab, 0x00},
+	{0xac, 0x00},
+	{0xad, 0x00},
+	{0xae, 0x00},
+	{0xaf, 0x18},
+	{0xb0, 0x38},
+	{0xb1, 0x30},
+	{0xb2, 0x00},
+	{0xb3, 0x00},
+	{0xb4, 0xff},
+	{0xb5, 0x0f},
+	{0xb6, 0xe4},
+	{0xb7, 0xe2},
+	{0xb8, 0x00},
+	{0xb9, 0x00},
+	{0xba, 0x00},
+	{0xbb, 0x03},
+	{0xbc, 0x01},
+	{0xbd, 0x00},
+	{0xbe, 0x00},
+	{0xbf, 0x00},
+	{0xc0, 0x18},
+	{0xc1, 0x20},
+	{0xc2, 0x07},
+	{0xc3, 0x18},
+	{0xc4, 0xff},
+	{0xc5, 0x2c},
+	{0xc6, 0x0c},
+	{0xc7, 0x0a},
+	{0xc8, 0x0e},
+	{0xc9, 0x01},
+	{0xca, 0x68},
+	{0xcb, 0xa7},
+	{0xcc, 0x3c},
+	{0xcd, 0x10},
+	{0xce, 0x00},
+	{0xcf, 0x25},
+	{0xd0, 0x40},
+	{0xd1, 0x12},
+	{0xd2, 0x00},
+	{0xd3, 0x00},
+	{0xd4, 0x10},
+	{0xd5, 0x28},
+	{0xd6, 0x80},
+	{0xd7, 0x2A},
+	{0xd8, 0x00},
+	{0xd9, 0x00},
+	{0xda, 0x00},
+	{0xdb, 0x00},
+	{0xdc, 0x00},
+	{0xdd, 0x00},
+	{0xde, 0x00},
+	{0xdf, 0x00},
+	{0xe0, 0x00},
+	{0xe1, 0xB3},
+	{0xe2, 0x00},
+	{0xe3, 0x00},
+	{0xe4, 0x00},
+	{0xe5, 0x10},
+	{0xe6, 0x00},
+	{0xe7, 0x1C},
+	{0xe8, 0x00},
+	{0xe9, 0xf4},
+	{0xea, 0x00},
+	{0xeb, 0xff},
+	{0xec, 0x79},
+	{0xed, 0x20},
+	{0xee, 0x30},
+	{0xef, 0x01},
+	{0xf0, 0x00},
+	{0xf1, 0x3e},
+	{0xf2, 0x00},
+	{0xf3, 0x00},
+	{0xf4, 0x00},
+	{0xf5, 0x00},
+	{0xf6, 0x00},
+	{0xf7, 0x00},
+	{0xf8, 0x00},
+	{0xf9, 0x00},
+	{0xfa, 0x00},
+	{0xfb, 0x00},
+	{0xfc, 0x00},
+	{0xfd, 0x00},
+	{0xfe, 0x00},
+	{0xff, 0x00},
 };
 
-
-
 #define CB_VT3253B0_INIT_FOR_UW2451 256
 //For UW2451
 unsigned char byVT3253B0_UW2451[CB_VT3253B0_INIT_FOR_UW2451][2] = {
-    {0x00, 0x31},
-    {0x01, 0x00},
-    {0x02, 0x00},
-    {0x03, 0x00},
-    {0x04, 0x00},
-    {0x05, 0x81},
-    {0x06, 0x00},
-    {0x07, 0x00},
-    {0x08, 0x38},
-    {0x09, 0x45},
-    {0x0a, 0x28},
-    {0x0b, 0x76},
-    {0x0c, 0x00},
-    {0x0d, 0x00},
-    {0x0e, 0x80},
-    {0x0f, 0x00},
-    {0x10, 0x00},
-    {0x11, 0x00},
-    {0x12, 0x00},
-    {0x13, 0x00},
-    {0x14, 0x00},
-    {0x15, 0x00},
-    {0x16, 0x00},
-    {0x17, 0x00},
-    {0x18, 0x00},
-    {0x19, 0x00},
-    {0x1a, 0x00},
-    {0x1b, 0x8f},
-    {0x1c, 0x0f},
-    {0x1d, 0x00},
-    {0x1e, 0x00},
-    {0x1f, 0x00},
-    {0x20, 0x00},
-    {0x21, 0x00},
-    {0x22, 0x00},
-    {0x23, 0x00},
-    {0x24, 0x00},
-    {0x25, 0x4a},
-    {0x26, 0x00},
-    {0x27, 0x00},
-    {0x28, 0x00},
-    {0x29, 0x00},
-    {0x2a, 0x00},
-    {0x2b, 0x00},
-    {0x2c, 0x00},
-    {0x2d, 0x18},
-    {0x2e, 0x00},
-    {0x2f, 0x0a},
-    {0x30, 0x26},
-    {0x31, 0x5b},
-    {0x32, 0x00},
-    {0x33, 0x00},
-    {0x34, 0x00},
-    {0x35, 0x00},
-    {0x36, 0xaa},
-    {0x37, 0xaa},
-    {0x38, 0xff},
-    {0x39, 0xff},
-    {0x3a, 0x00},
-    {0x3b, 0x00},
-    {0x3c, 0x00},
-    {0x3d, 0x03},
-    {0x3e, 0x1d},
-    {0x3f, 0x04},
-    {0x40, 0x00},
-    {0x41, 0x08},
-    {0x42, 0x00},
-    {0x43, 0x08},
-    {0x44, 0x08},
-    {0x45, 0x14},
-    {0x46, 0x05},
-    {0x47, 0x09},
-    {0x48, 0x00},
-    {0x49, 0x00},
-    {0x4a, 0x00},
-    {0x4b, 0x00},
-    {0x4c, 0x09},
-    {0x4d, 0x90},
-    {0x4e, 0x00},
-    {0x4f, 0xc5},
-    {0x50, 0x15},
-    {0x51, 0x19},
-    {0x52, 0x00},
-    {0x53, 0x00},
-    {0x54, 0x00},
-    {0x55, 0x00},
-    {0x56, 0x00},
-    {0x57, 0x00},
-    {0x58, 0x00},
-    {0x59, 0xb0},
-    {0x5a, 0x00},
-    {0x5b, 0x00},
-    {0x5c, 0x00},
-    {0x5d, 0x00},
-    {0x5e, 0x00},
-    {0x5f, 0x00},
-    {0x60, 0xb3},
-    {0x61, 0x81},
-    {0x62, 0x00},
-    {0x63, 0x00},
-    {0x64, 0x00},
-    {0x65, 0x00},
-    {0x66, 0x57},
-    {0x67, 0x6c},
-    {0x68, 0x00},
-    {0x69, 0x00},
-    {0x6a, 0x00},
-    {0x6b, 0x00},
-    //{0x6c, 0x80},
-    {0x6c, 0x00}, //RobertYu:20050125, request by JJSue
-    {0x6d, 0x03},
-    {0x6e, 0x01},
-    {0x6f, 0x00},
-    {0x70, 0x00},
-    {0x71, 0x00},
-    {0x72, 0x00},
-    {0x73, 0x00},
-    {0x74, 0x00},
-    {0x75, 0x00},
-    {0x76, 0x00},
-    {0x77, 0x00},
-    {0x78, 0x00},
-    {0x79, 0x00},
-    {0x7a, 0x00},
-    {0x7b, 0x00},
-    {0x7c, 0x00},
-    {0x7d, 0x00},
-    {0x7e, 0x00},
-    {0x7f, 0x00},
-    {0x80, 0x8c},
-    {0x81, 0x00},
-    {0x82, 0x0e},
-    {0x83, 0x00},
-    {0x84, 0x00},
-    {0x85, 0x00},
-    {0x86, 0x00},
-    {0x87, 0x00},
-    {0x88, 0x08},
-    {0x89, 0x00},
-    {0x8a, 0x0e},
-    {0x8b, 0xa7},
-    {0x8c, 0x88},
-    {0x8d, 0x47},
-    {0x8e, 0xaa},
-    {0x8f, 0x02},
-    {0x90, 0x00},
-    {0x91, 0x00},
-    {0x92, 0x00},
-    {0x93, 0x00},
-    {0x94, 0x00},
-    {0x95, 0x00},
-    {0x96, 0x00},
-    {0x97, 0xe3},
-    {0x98, 0x00},
-    {0x99, 0x00},
-    {0x9a, 0x00},
-    {0x9b, 0x00},
-    {0x9c, 0x00},
-    {0x9d, 0x00},
-    {0x9e, 0x00},
-    {0x9f, 0x00},
-    {0xa0, 0x00},
-    {0xa1, 0x00},
-    {0xa2, 0x00},
-    {0xa3, 0x00},
-    {0xa4, 0x00},
-    {0xa5, 0x00},
-    {0xa6, 0x10},
-    {0xa7, 0x00},
-    {0xa8, 0x18},
-    {0xa9, 0x00},
-    {0xaa, 0x00},
-    {0xab, 0x00},
-    {0xac, 0x00},
-    {0xad, 0x00},
-    {0xae, 0x00},
-    {0xaf, 0x18},
-    {0xb0, 0x18},
-    {0xb1, 0x30},
-    {0xb2, 0x00},
-    {0xb3, 0x00},
-    {0xb4, 0x00},
-    {0xb5, 0x00},
-    {0xb6, 0x00},
-    {0xb7, 0x00},
-    {0xb8, 0x00},
-    {0xb9, 0x00},
-    {0xba, 0x00},
-    {0xbb, 0x03},
-    {0xbc, 0x01},
-    {0xbd, 0x00},
-    {0xbe, 0x00},
-    {0xbf, 0x00},
-    {0xc0, 0x10},
-    {0xc1, 0x20},
-    {0xc2, 0x00},
-    {0xc3, 0x20},
-    {0xc4, 0x00},
-    {0xc5, 0x2c},
-    {0xc6, 0x1c},
-    {0xc7, 0x10},
-    {0xc8, 0x10},
-    {0xc9, 0x01},
-    {0xca, 0x68},
-    {0xcb, 0xa7},
-    {0xcc, 0x3c},
-    {0xcd, 0x09},
-    {0xce, 0x00},
-    {0xcf, 0x20},
-    {0xd0, 0x40},
-    {0xd1, 0x10},
-    {0xd2, 0x00},
-    {0xd3, 0x00},
-    {0xd4, 0x20},
-    {0xd5, 0x28},
-    {0xd6, 0xa0},
-    {0xd7, 0x2a},
-    {0xd8, 0x00},
-    {0xd9, 0x00},
-    {0xda, 0x00},
-    {0xdb, 0x00},
-    {0xdc, 0x00},
-    {0xdd, 0x00},
-    {0xde, 0x00},
-    {0xdf, 0x00},
-    {0xe0, 0x00},
-    {0xe1, 0xd3},
-    {0xe2, 0xc0},
-    {0xe3, 0x00},
-    {0xe4, 0x00},
-    {0xe5, 0x10},
-    {0xe6, 0x00},
-    {0xe7, 0x12},
-    {0xe8, 0x12},
-    {0xe9, 0x34},
-    {0xea, 0x00},
-    {0xeb, 0xff},
-    {0xec, 0x79},
-    {0xed, 0x20},
-    {0xee, 0x30},
-    {0xef, 0x01},
-    {0xf0, 0x00},
-    {0xf1, 0x3e},
-    {0xf2, 0x00},
-    {0xf3, 0x00},
-    {0xf4, 0x00},
-    {0xf5, 0x00},
-    {0xf6, 0x00},
-    {0xf7, 0x00},
-    {0xf8, 0x00},
-    {0xf9, 0x00},
-    {0xfa, 0x00},
-    {0xfb, 0x00},
-    {0xfc, 0x00},
-    {0xfd, 0x00},
-    {0xfe, 0x00},
-    {0xff, 0x00},
+	{0x00, 0x31},
+	{0x01, 0x00},
+	{0x02, 0x00},
+	{0x03, 0x00},
+	{0x04, 0x00},
+	{0x05, 0x81},
+	{0x06, 0x00},
+	{0x07, 0x00},
+	{0x08, 0x38},
+	{0x09, 0x45},
+	{0x0a, 0x28},
+	{0x0b, 0x76},
+	{0x0c, 0x00},
+	{0x0d, 0x00},
+	{0x0e, 0x80},
+	{0x0f, 0x00},
+	{0x10, 0x00},
+	{0x11, 0x00},
+	{0x12, 0x00},
+	{0x13, 0x00},
+	{0x14, 0x00},
+	{0x15, 0x00},
+	{0x16, 0x00},
+	{0x17, 0x00},
+	{0x18, 0x00},
+	{0x19, 0x00},
+	{0x1a, 0x00},
+	{0x1b, 0x8f},
+	{0x1c, 0x0f},
+	{0x1d, 0x00},
+	{0x1e, 0x00},
+	{0x1f, 0x00},
+	{0x20, 0x00},
+	{0x21, 0x00},
+	{0x22, 0x00},
+	{0x23, 0x00},
+	{0x24, 0x00},
+	{0x25, 0x4a},
+	{0x26, 0x00},
+	{0x27, 0x00},
+	{0x28, 0x00},
+	{0x29, 0x00},
+	{0x2a, 0x00},
+	{0x2b, 0x00},
+	{0x2c, 0x00},
+	{0x2d, 0x18},
+	{0x2e, 0x00},
+	{0x2f, 0x0a},
+	{0x30, 0x26},
+	{0x31, 0x5b},
+	{0x32, 0x00},
+	{0x33, 0x00},
+	{0x34, 0x00},
+	{0x35, 0x00},
+	{0x36, 0xaa},
+	{0x37, 0xaa},
+	{0x38, 0xff},
+	{0x39, 0xff},
+	{0x3a, 0x00},
+	{0x3b, 0x00},
+	{0x3c, 0x00},
+	{0x3d, 0x03},
+	{0x3e, 0x1d},
+	{0x3f, 0x04},
+	{0x40, 0x00},
+	{0x41, 0x08},
+	{0x42, 0x00},
+	{0x43, 0x08},
+	{0x44, 0x08},
+	{0x45, 0x14},
+	{0x46, 0x05},
+	{0x47, 0x09},
+	{0x48, 0x00},
+	{0x49, 0x00},
+	{0x4a, 0x00},
+	{0x4b, 0x00},
+	{0x4c, 0x09},
+	{0x4d, 0x90},
+	{0x4e, 0x00},
+	{0x4f, 0xc5},
+	{0x50, 0x15},
+	{0x51, 0x19},
+	{0x52, 0x00},
+	{0x53, 0x00},
+	{0x54, 0x00},
+	{0x55, 0x00},
+	{0x56, 0x00},
+	{0x57, 0x00},
+	{0x58, 0x00},
+	{0x59, 0xb0},
+	{0x5a, 0x00},
+	{0x5b, 0x00},
+	{0x5c, 0x00},
+	{0x5d, 0x00},
+	{0x5e, 0x00},
+	{0x5f, 0x00},
+	{0x60, 0xb3},
+	{0x61, 0x81},
+	{0x62, 0x00},
+	{0x63, 0x00},
+	{0x64, 0x00},
+	{0x65, 0x00},
+	{0x66, 0x57},
+	{0x67, 0x6c},
+	{0x68, 0x00},
+	{0x69, 0x00},
+	{0x6a, 0x00},
+	{0x6b, 0x00},
+	//{0x6c, 0x80},
+	{0x6c, 0x00}, //RobertYu:20050125, request by JJSue
+	{0x6d, 0x03},
+	{0x6e, 0x01},
+	{0x6f, 0x00},
+	{0x70, 0x00},
+	{0x71, 0x00},
+	{0x72, 0x00},
+	{0x73, 0x00},
+	{0x74, 0x00},
+	{0x75, 0x00},
+	{0x76, 0x00},
+	{0x77, 0x00},
+	{0x78, 0x00},
+	{0x79, 0x00},
+	{0x7a, 0x00},
+	{0x7b, 0x00},
+	{0x7c, 0x00},
+	{0x7d, 0x00},
+	{0x7e, 0x00},
+	{0x7f, 0x00},
+	{0x80, 0x8c},
+	{0x81, 0x00},
+	{0x82, 0x0e},
+	{0x83, 0x00},
+	{0x84, 0x00},
+	{0x85, 0x00},
+	{0x86, 0x00},
+	{0x87, 0x00},
+	{0x88, 0x08},
+	{0x89, 0x00},
+	{0x8a, 0x0e},
+	{0x8b, 0xa7},
+	{0x8c, 0x88},
+	{0x8d, 0x47},
+	{0x8e, 0xaa},
+	{0x8f, 0x02},
+	{0x90, 0x00},
+	{0x91, 0x00},
+	{0x92, 0x00},
+	{0x93, 0x00},
+	{0x94, 0x00},
+	{0x95, 0x00},
+	{0x96, 0x00},
+	{0x97, 0xe3},
+	{0x98, 0x00},
+	{0x99, 0x00},
+	{0x9a, 0x00},
+	{0x9b, 0x00},
+	{0x9c, 0x00},
+	{0x9d, 0x00},
+	{0x9e, 0x00},
+	{0x9f, 0x00},
+	{0xa0, 0x00},
+	{0xa1, 0x00},
+	{0xa2, 0x00},
+	{0xa3, 0x00},
+	{0xa4, 0x00},
+	{0xa5, 0x00},
+	{0xa6, 0x10},
+	{0xa7, 0x00},
+	{0xa8, 0x18},
+	{0xa9, 0x00},
+	{0xaa, 0x00},
+	{0xab, 0x00},
+	{0xac, 0x00},
+	{0xad, 0x00},
+	{0xae, 0x00},
+	{0xaf, 0x18},
+	{0xb0, 0x18},
+	{0xb1, 0x30},
+	{0xb2, 0x00},
+	{0xb3, 0x00},
+	{0xb4, 0x00},
+	{0xb5, 0x00},
+	{0xb6, 0x00},
+	{0xb7, 0x00},
+	{0xb8, 0x00},
+	{0xb9, 0x00},
+	{0xba, 0x00},
+	{0xbb, 0x03},
+	{0xbc, 0x01},
+	{0xbd, 0x00},
+	{0xbe, 0x00},
+	{0xbf, 0x00},
+	{0xc0, 0x10},
+	{0xc1, 0x20},
+	{0xc2, 0x00},
+	{0xc3, 0x20},
+	{0xc4, 0x00},
+	{0xc5, 0x2c},
+	{0xc6, 0x1c},
+	{0xc7, 0x10},
+	{0xc8, 0x10},
+	{0xc9, 0x01},
+	{0xca, 0x68},
+	{0xcb, 0xa7},
+	{0xcc, 0x3c},
+	{0xcd, 0x09},
+	{0xce, 0x00},
+	{0xcf, 0x20},
+	{0xd0, 0x40},
+	{0xd1, 0x10},
+	{0xd2, 0x00},
+	{0xd3, 0x00},
+	{0xd4, 0x20},
+	{0xd5, 0x28},
+	{0xd6, 0xa0},
+	{0xd7, 0x2a},
+	{0xd8, 0x00},
+	{0xd9, 0x00},
+	{0xda, 0x00},
+	{0xdb, 0x00},
+	{0xdc, 0x00},
+	{0xdd, 0x00},
+	{0xde, 0x00},
+	{0xdf, 0x00},
+	{0xe0, 0x00},
+	{0xe1, 0xd3},
+	{0xe2, 0xc0},
+	{0xe3, 0x00},
+	{0xe4, 0x00},
+	{0xe5, 0x10},
+	{0xe6, 0x00},
+	{0xe7, 0x12},
+	{0xe8, 0x12},
+	{0xe9, 0x34},
+	{0xea, 0x00},
+	{0xeb, 0xff},
+	{0xec, 0x79},
+	{0xed, 0x20},
+	{0xee, 0x30},
+	{0xef, 0x01},
+	{0xf0, 0x00},
+	{0xf1, 0x3e},
+	{0xf2, 0x00},
+	{0xf3, 0x00},
+	{0xf4, 0x00},
+	{0xf5, 0x00},
+	{0xf6, 0x00},
+	{0xf7, 0x00},
+	{0xf8, 0x00},
+	{0xf9, 0x00},
+	{0xfa, 0x00},
+	{0xfb, 0x00},
+	{0xfc, 0x00},
+	{0xfd, 0x00},
+	{0xfe, 0x00},
+	{0xff, 0x00},
 };
 
 #define CB_VT3253B0_AGC 193
 // For AIROHA
 unsigned char byVT3253B0_AGC[CB_VT3253B0_AGC][2] = {
-    {0xF0, 0x00},
-    {0xF1, 0x00},
-    {0xF0, 0x80},
-    {0xF0, 0x01},
-    {0xF1, 0x00},
-    {0xF0, 0x81},
-    {0xF0, 0x02},
-    {0xF1, 0x02},
-    {0xF0, 0x82},
-    {0xF0, 0x03},
-    {0xF1, 0x04},
-    {0xF0, 0x83},
-    {0xF0, 0x03},
-    {0xF1, 0x04},
-    {0xF0, 0x84},
-    {0xF0, 0x04},
-    {0xF1, 0x06},
-    {0xF0, 0x85},
-    {0xF0, 0x05},
-    {0xF1, 0x06},
-    {0xF0, 0x86},
-    {0xF0, 0x06},
-    {0xF1, 0x06},
-    {0xF0, 0x87},
-    {0xF0, 0x07},
-    {0xF1, 0x08},
-    {0xF0, 0x88},
-    {0xF0, 0x08},
-    {0xF1, 0x08},
-    {0xF0, 0x89},
-    {0xF0, 0x09},
-    {0xF1, 0x0A},
-    {0xF0, 0x8A},
-    {0xF0, 0x0A},
-    {0xF1, 0x0A},
-    {0xF0, 0x8B},
-    {0xF0, 0x0B},
-    {0xF1, 0x0C},
-    {0xF0, 0x8C},
-    {0xF0, 0x0C},
-    {0xF1, 0x0C},
-    {0xF0, 0x8D},
-    {0xF0, 0x0D},
-    {0xF1, 0x0E},
-    {0xF0, 0x8E},
-    {0xF0, 0x0E},
-    {0xF1, 0x0E},
-    {0xF0, 0x8F},
-    {0xF0, 0x0F},
-    {0xF1, 0x10},
-    {0xF0, 0x90},
-    {0xF0, 0x10},
-    {0xF1, 0x10},
-    {0xF0, 0x91},
-    {0xF0, 0x11},
-    {0xF1, 0x12},
-    {0xF0, 0x92},
-    {0xF0, 0x12},
-    {0xF1, 0x12},
-    {0xF0, 0x93},
-    {0xF0, 0x13},
-    {0xF1, 0x14},
-    {0xF0, 0x94},
-    {0xF0, 0x14},
-    {0xF1, 0x14},
-    {0xF0, 0x95},
-    {0xF0, 0x15},
-    {0xF1, 0x16},
-    {0xF0, 0x96},
-    {0xF0, 0x16},
-    {0xF1, 0x16},
-    {0xF0, 0x97},
-    {0xF0, 0x17},
-    {0xF1, 0x18},
-    {0xF0, 0x98},
-    {0xF0, 0x18},
-    {0xF1, 0x18},
-    {0xF0, 0x99},
-    {0xF0, 0x19},
-    {0xF1, 0x1A},
-    {0xF0, 0x9A},
-    {0xF0, 0x1A},
-    {0xF1, 0x1A},
-    {0xF0, 0x9B},
-    {0xF0, 0x1B},
-    {0xF1, 0x1C},
-    {0xF0, 0x9C},
-    {0xF0, 0x1C},
-    {0xF1, 0x1C},
-    {0xF0, 0x9D},
-    {0xF0, 0x1D},
-    {0xF1, 0x1E},
-    {0xF0, 0x9E},
-    {0xF0, 0x1E},
-    {0xF1, 0x1E},
-    {0xF0, 0x9F},
-    {0xF0, 0x1F},
-    {0xF1, 0x20},
-    {0xF0, 0xA0},
-    {0xF0, 0x20},
-    {0xF1, 0x20},
-    {0xF0, 0xA1},
-    {0xF0, 0x21},
-    {0xF1, 0x22},
-    {0xF0, 0xA2},
-    {0xF0, 0x22},
-    {0xF1, 0x22},
-    {0xF0, 0xA3},
-    {0xF0, 0x23},
-    {0xF1, 0x24},
-    {0xF0, 0xA4},
-    {0xF0, 0x24},
-    {0xF1, 0x24},
-    {0xF0, 0xA5},
-    {0xF0, 0x25},
-    {0xF1, 0x26},
-    {0xF0, 0xA6},
-    {0xF0, 0x26},
-    {0xF1, 0x26},
-    {0xF0, 0xA7},
-    {0xF0, 0x27},
-    {0xF1, 0x28},
-    {0xF0, 0xA8},
-    {0xF0, 0x28},
-    {0xF1, 0x28},
-    {0xF0, 0xA9},
-    {0xF0, 0x29},
-    {0xF1, 0x2A},
-    {0xF0, 0xAA},
-    {0xF0, 0x2A},
-    {0xF1, 0x2A},
-    {0xF0, 0xAB},
-    {0xF0, 0x2B},
-    {0xF1, 0x2C},
-    {0xF0, 0xAC},
-    {0xF0, 0x2C},
-    {0xF1, 0x2C},
-    {0xF0, 0xAD},
-    {0xF0, 0x2D},
-    {0xF1, 0x2E},
-    {0xF0, 0xAE},
-    {0xF0, 0x2E},
-    {0xF1, 0x2E},
-    {0xF0, 0xAF},
-    {0xF0, 0x2F},
-    {0xF1, 0x30},
-    {0xF0, 0xB0},
-    {0xF0, 0x30},
-    {0xF1, 0x30},
-    {0xF0, 0xB1},
-    {0xF0, 0x31},
-    {0xF1, 0x32},
-    {0xF0, 0xB2},
-    {0xF0, 0x32},
-    {0xF1, 0x32},
-    {0xF0, 0xB3},
-    {0xF0, 0x33},
-    {0xF1, 0x34},
-    {0xF0, 0xB4},
-    {0xF0, 0x34},
-    {0xF1, 0x34},
-    {0xF0, 0xB5},
-    {0xF0, 0x35},
-    {0xF1, 0x36},
-    {0xF0, 0xB6},
-    {0xF0, 0x36},
-    {0xF1, 0x36},
-    {0xF0, 0xB7},
-    {0xF0, 0x37},
-    {0xF1, 0x38},
-    {0xF0, 0xB8},
-    {0xF0, 0x38},
-    {0xF1, 0x38},
-    {0xF0, 0xB9},
-    {0xF0, 0x39},
-    {0xF1, 0x3A},
-    {0xF0, 0xBA},
-    {0xF0, 0x3A},
-    {0xF1, 0x3A},
-    {0xF0, 0xBB},
-    {0xF0, 0x3B},
-    {0xF1, 0x3C},
-    {0xF0, 0xBC},
-    {0xF0, 0x3C},
-    {0xF1, 0x3C},
-    {0xF0, 0xBD},
-    {0xF0, 0x3D},
-    {0xF1, 0x3E},
-    {0xF0, 0xBE},
-    {0xF0, 0x3E},
-    {0xF1, 0x3E},
-    {0xF0, 0xBF},
-    {0xF0, 0x00},
+	{0xF0, 0x00},
+	{0xF1, 0x00},
+	{0xF0, 0x80},
+	{0xF0, 0x01},
+	{0xF1, 0x00},
+	{0xF0, 0x81},
+	{0xF0, 0x02},
+	{0xF1, 0x02},
+	{0xF0, 0x82},
+	{0xF0, 0x03},
+	{0xF1, 0x04},
+	{0xF0, 0x83},
+	{0xF0, 0x03},
+	{0xF1, 0x04},
+	{0xF0, 0x84},
+	{0xF0, 0x04},
+	{0xF1, 0x06},
+	{0xF0, 0x85},
+	{0xF0, 0x05},
+	{0xF1, 0x06},
+	{0xF0, 0x86},
+	{0xF0, 0x06},
+	{0xF1, 0x06},
+	{0xF0, 0x87},
+	{0xF0, 0x07},
+	{0xF1, 0x08},
+	{0xF0, 0x88},
+	{0xF0, 0x08},
+	{0xF1, 0x08},
+	{0xF0, 0x89},
+	{0xF0, 0x09},
+	{0xF1, 0x0A},
+	{0xF0, 0x8A},
+	{0xF0, 0x0A},
+	{0xF1, 0x0A},
+	{0xF0, 0x8B},
+	{0xF0, 0x0B},
+	{0xF1, 0x0C},
+	{0xF0, 0x8C},
+	{0xF0, 0x0C},
+	{0xF1, 0x0C},
+	{0xF0, 0x8D},
+	{0xF0, 0x0D},
+	{0xF1, 0x0E},
+	{0xF0, 0x8E},
+	{0xF0, 0x0E},
+	{0xF1, 0x0E},
+	{0xF0, 0x8F},
+	{0xF0, 0x0F},
+	{0xF1, 0x10},
+	{0xF0, 0x90},
+	{0xF0, 0x10},
+	{0xF1, 0x10},
+	{0xF0, 0x91},
+	{0xF0, 0x11},
+	{0xF1, 0x12},
+	{0xF0, 0x92},
+	{0xF0, 0x12},
+	{0xF1, 0x12},
+	{0xF0, 0x93},
+	{0xF0, 0x13},
+	{0xF1, 0x14},
+	{0xF0, 0x94},
+	{0xF0, 0x14},
+	{0xF1, 0x14},
+	{0xF0, 0x95},
+	{0xF0, 0x15},
+	{0xF1, 0x16},
+	{0xF0, 0x96},
+	{0xF0, 0x16},
+	{0xF1, 0x16},
+	{0xF0, 0x97},
+	{0xF0, 0x17},
+	{0xF1, 0x18},
+	{0xF0, 0x98},
+	{0xF0, 0x18},
+	{0xF1, 0x18},
+	{0xF0, 0x99},
+	{0xF0, 0x19},
+	{0xF1, 0x1A},
+	{0xF0, 0x9A},
+	{0xF0, 0x1A},
+	{0xF1, 0x1A},
+	{0xF0, 0x9B},
+	{0xF0, 0x1B},
+	{0xF1, 0x1C},
+	{0xF0, 0x9C},
+	{0xF0, 0x1C},
+	{0xF1, 0x1C},
+	{0xF0, 0x9D},
+	{0xF0, 0x1D},
+	{0xF1, 0x1E},
+	{0xF0, 0x9E},
+	{0xF0, 0x1E},
+	{0xF1, 0x1E},
+	{0xF0, 0x9F},
+	{0xF0, 0x1F},
+	{0xF1, 0x20},
+	{0xF0, 0xA0},
+	{0xF0, 0x20},
+	{0xF1, 0x20},
+	{0xF0, 0xA1},
+	{0xF0, 0x21},
+	{0xF1, 0x22},
+	{0xF0, 0xA2},
+	{0xF0, 0x22},
+	{0xF1, 0x22},
+	{0xF0, 0xA3},
+	{0xF0, 0x23},
+	{0xF1, 0x24},
+	{0xF0, 0xA4},
+	{0xF0, 0x24},
+	{0xF1, 0x24},
+	{0xF0, 0xA5},
+	{0xF0, 0x25},
+	{0xF1, 0x26},
+	{0xF0, 0xA6},
+	{0xF0, 0x26},
+	{0xF1, 0x26},
+	{0xF0, 0xA7},
+	{0xF0, 0x27},
+	{0xF1, 0x28},
+	{0xF0, 0xA8},
+	{0xF0, 0x28},
+	{0xF1, 0x28},
+	{0xF0, 0xA9},
+	{0xF0, 0x29},
+	{0xF1, 0x2A},
+	{0xF0, 0xAA},
+	{0xF0, 0x2A},
+	{0xF1, 0x2A},
+	{0xF0, 0xAB},
+	{0xF0, 0x2B},
+	{0xF1, 0x2C},
+	{0xF0, 0xAC},
+	{0xF0, 0x2C},
+	{0xF1, 0x2C},
+	{0xF0, 0xAD},
+	{0xF0, 0x2D},
+	{0xF1, 0x2E},
+	{0xF0, 0xAE},
+	{0xF0, 0x2E},
+	{0xF1, 0x2E},
+	{0xF0, 0xAF},
+	{0xF0, 0x2F},
+	{0xF1, 0x30},
+	{0xF0, 0xB0},
+	{0xF0, 0x30},
+	{0xF1, 0x30},
+	{0xF0, 0xB1},
+	{0xF0, 0x31},
+	{0xF1, 0x32},
+	{0xF0, 0xB2},
+	{0xF0, 0x32},
+	{0xF1, 0x32},
+	{0xF0, 0xB3},
+	{0xF0, 0x33},
+	{0xF1, 0x34},
+	{0xF0, 0xB4},
+	{0xF0, 0x34},
+	{0xF1, 0x34},
+	{0xF0, 0xB5},
+	{0xF0, 0x35},
+	{0xF1, 0x36},
+	{0xF0, 0xB6},
+	{0xF0, 0x36},
+	{0xF1, 0x36},
+	{0xF0, 0xB7},
+	{0xF0, 0x37},
+	{0xF1, 0x38},
+	{0xF0, 0xB8},
+	{0xF0, 0x38},
+	{0xF1, 0x38},
+	{0xF0, 0xB9},
+	{0xF0, 0x39},
+	{0xF1, 0x3A},
+	{0xF0, 0xBA},
+	{0xF0, 0x3A},
+	{0xF1, 0x3A},
+	{0xF0, 0xBB},
+	{0xF0, 0x3B},
+	{0xF1, 0x3C},
+	{0xF0, 0xBC},
+	{0xF0, 0x3C},
+	{0xF1, 0x3C},
+	{0xF0, 0xBD},
+	{0xF0, 0x3D},
+	{0xF1, 0x3E},
+	{0xF0, 0xBE},
+	{0xF0, 0x3E},
+	{0xF1, 0x3E},
+	{0xF0, 0xBF},
+	{0xF0, 0x00},
 };
 
 const unsigned short awcFrameTime[MAX_RATE] =
 {10, 20, 55, 110, 24, 36, 48, 72, 96, 144, 192, 216};
 
-
 /*---------------------  Static Functions  --------------------------*/
 
 static
@@ -1723,42 +1718,37 @@ s_ulGetRatio(PSDevice pDevice);
 static
 void
 s_vChangeAntenna(
-    PSDevice pDevice
-    );
+	PSDevice pDevice
+);
 
 static
 void
-s_vChangeAntenna (
-    PSDevice pDevice
-    )
+s_vChangeAntenna(
+	PSDevice pDevice
+)
 {
-
-#ifdef	PLICE_DEBUG
-	//printk("Enter s_vChangeAntenna:original RxMode is %d,TxMode is %d\n",pDevice->byRxAntennaMode,pDevice->byTxAntennaMode);
-#endif
-    if ( pDevice->dwRxAntennaSel == 0) {
-        pDevice->dwRxAntennaSel=1;
-        if (pDevice->bTxRxAntInv == true)
-            BBvSetRxAntennaMode(pDevice->PortOffset, ANT_A);
-        else
-            BBvSetRxAntennaMode(pDevice->PortOffset, ANT_B);
-    } else {
-        pDevice->dwRxAntennaSel=0;
-        if (pDevice->bTxRxAntInv == true)
-            BBvSetRxAntennaMode(pDevice->PortOffset, ANT_B);
-        else
-            BBvSetRxAntennaMode(pDevice->PortOffset, ANT_A);
-    }
-    if ( pDevice->dwTxAntennaSel == 0) {
-        pDevice->dwTxAntennaSel=1;
-        BBvSetTxAntennaMode(pDevice->PortOffset, ANT_B);
-    } else {
-        pDevice->dwTxAntennaSel=0;
-        BBvSetTxAntennaMode(pDevice->PortOffset, ANT_A);
-    }
+	if (pDevice->dwRxAntennaSel == 0) {
+		pDevice->dwRxAntennaSel = 1;
+		if (pDevice->bTxRxAntInv == true)
+			BBvSetRxAntennaMode(pDevice->PortOffset, ANT_A);
+		else
+			BBvSetRxAntennaMode(pDevice->PortOffset, ANT_B);
+	} else {
+		pDevice->dwRxAntennaSel = 0;
+		if (pDevice->bTxRxAntInv == true)
+			BBvSetRxAntennaMode(pDevice->PortOffset, ANT_B);
+		else
+			BBvSetRxAntennaMode(pDevice->PortOffset, ANT_A);
+	}
+	if (pDevice->dwTxAntennaSel == 0) {
+		pDevice->dwTxAntennaSel = 1;
+		BBvSetTxAntennaMode(pDevice->PortOffset, ANT_B);
+	} else {
+		pDevice->dwTxAntennaSel = 0;
+		BBvSetTxAntennaMode(pDevice->PortOffset, ANT_A);
+	}
 }
 
-
 /*---------------------  Export Variables  --------------------------*/
 /*
  * Description: Calculate data frame transmitting time
@@ -1775,54 +1765,52 @@ s_vChangeAntenna (
  *
  */
 unsigned int
-BBuGetFrameTime (
-    unsigned char byPreambleType,
-    unsigned char byPktType,
-    unsigned int cbFrameLength,
-    unsigned short wRate
-    )
+BBuGetFrameTime(
+	unsigned char byPreambleType,
+	unsigned char byPktType,
+	unsigned int cbFrameLength,
+	unsigned short wRate
+)
 {
-    unsigned int uFrameTime;
-    unsigned int uPreamble;
-    unsigned int uTmp;
-    unsigned int uRateIdx = (unsigned int) wRate;
-    unsigned int uRate = 0;
-
-
-    if (uRateIdx > RATE_54M) {
-	    ASSERT(0);
-        return 0;
-    }
-
-    uRate = (unsigned int) awcFrameTime[uRateIdx];
-
-    if (uRateIdx <= 3) {          //CCK mode
-
-        if (byPreambleType == 1) {//Short
-            uPreamble = 96;
-        } else {
-            uPreamble = 192;
-        }
-        uFrameTime = (cbFrameLength * 80) / uRate;  //?????
-        uTmp = (uFrameTime * uRate) / 80;
-        if (cbFrameLength != uTmp) {
-            uFrameTime ++;
-        }
-
-        return (uPreamble + uFrameTime);
-    }
-    else {
-        uFrameTime = (cbFrameLength * 8 + 22) / uRate;   //????????
-        uTmp = ((uFrameTime * uRate) - 22) / 8;
-        if(cbFrameLength != uTmp) {
-            uFrameTime ++;
-        }
-        uFrameTime = uFrameTime * 4;    //???????
-        if(byPktType != PK_TYPE_11A) {
-            uFrameTime += 6;     //??????
-        }
-        return (20 + uFrameTime); //??????
-    }
+	unsigned int uFrameTime;
+	unsigned int uPreamble;
+	unsigned int uTmp;
+	unsigned int uRateIdx = (unsigned int) wRate;
+	unsigned int uRate = 0;
+
+	if (uRateIdx > RATE_54M) {
+		ASSERT(0);
+		return 0;
+	}
+
+	uRate = (unsigned int)awcFrameTime[uRateIdx];
+
+	if (uRateIdx <= 3) {          //CCK mode
+
+		if (byPreambleType == 1) {//Short
+			uPreamble = 96;
+		} else {
+			uPreamble = 192;
+		}
+		uFrameTime = (cbFrameLength * 80) / uRate;  //?????
+		uTmp = (uFrameTime * uRate) / 80;
+		if (cbFrameLength != uTmp) {
+			uFrameTime++;
+		}
+
+		return uPreamble + uFrameTime;
+	} else {
+		uFrameTime = (cbFrameLength * 8 + 22) / uRate;   //????????
+		uTmp = ((uFrameTime * uRate) - 22) / 8;
+		if (cbFrameLength != uTmp) {
+			uFrameTime++;
+		}
+		uFrameTime = uFrameTime * 4;    //???????
+		if (byPktType != PK_TYPE_11A) {
+			uFrameTime += 6;     //??????
+		}
+		return 20 + uFrameTime; //??????
+	}
 }
 
 /*
@@ -1842,162 +1830,152 @@ BBuGetFrameTime (
  *
  */
 void
-BBvCalculateParameter (
-    PSDevice pDevice,
-    unsigned int cbFrameLength,
-    unsigned short wRate,
-    unsigned char byPacketType,
-    unsigned short *pwPhyLen,
-    unsigned char *pbyPhySrv,
-    unsigned char *pbyPhySgn
-    )
+BBvCalculateParameter(
+	PSDevice pDevice,
+	unsigned int cbFrameLength,
+	unsigned short wRate,
+	unsigned char byPacketType,
+	unsigned short *pwPhyLen,
+	unsigned char *pbyPhySrv,
+	unsigned char *pbyPhySgn
+)
 {
-    unsigned int cbBitCount;
-    unsigned int cbUsCount = 0;
-    unsigned int cbTmp;
-    bool bExtBit;
-    unsigned char byPreambleType = pDevice->byPreambleType;
-    bool bCCK = pDevice->bCCK;
-
-    cbBitCount = cbFrameLength * 8;
-    bExtBit = false;
-
-    switch (wRate) {
-    case RATE_1M :
-        cbUsCount = cbBitCount;
-        *pbyPhySgn = 0x00;
-        break;
-
-    case RATE_2M :
-        cbUsCount = cbBitCount / 2;
-        if (byPreambleType == 1)
-            *pbyPhySgn = 0x09;
-        else // long preamble
-            *pbyPhySgn = 0x01;
-        break;
-
-    case RATE_5M :
-        if (bCCK == false)
-            cbBitCount ++;
-        cbUsCount = (cbBitCount * 10) / 55;
-        cbTmp = (cbUsCount * 55) / 10;
-        if (cbTmp != cbBitCount)
-            cbUsCount ++;
-        if (byPreambleType == 1)
-            *pbyPhySgn = 0x0a;
-        else // long preamble
-            *pbyPhySgn = 0x02;
-        break;
-
-    case RATE_11M :
-
-        if (bCCK == false)
-            cbBitCount ++;
-        cbUsCount = cbBitCount / 11;
-        cbTmp = cbUsCount * 11;
-        if (cbTmp != cbBitCount) {
-            cbUsCount ++;
-            if ((cbBitCount - cbTmp) <= 3)
-                bExtBit = true;
-        }
-        if (byPreambleType == 1)
-            *pbyPhySgn = 0x0b;
-        else // long preamble
-            *pbyPhySgn = 0x03;
-        break;
-
-    case RATE_6M :
-        if(byPacketType == PK_TYPE_11A) {//11a, 5GHZ
-            *pbyPhySgn = 0x9B; //1001 1011
-        }
-        else {//11g, 2.4GHZ
-            *pbyPhySgn = 0x8B; //1000 1011
-        }
-        break;
-
-    case RATE_9M :
-        if(byPacketType == PK_TYPE_11A) {//11a, 5GHZ
-            *pbyPhySgn = 0x9F; //1001 1111
-        }
-        else {//11g, 2.4GHZ
-            *pbyPhySgn = 0x8F; //1000 1111
-        }
-        break;
-
-    case RATE_12M :
-        if(byPacketType == PK_TYPE_11A) {//11a, 5GHZ
-            *pbyPhySgn = 0x9A; //1001 1010
-        }
-        else {//11g, 2.4GHZ
-            *pbyPhySgn = 0x8A; //1000 1010
-        }
-        break;
-
-    case RATE_18M :
-        if(byPacketType == PK_TYPE_11A) {//11a, 5GHZ
-            *pbyPhySgn = 0x9E; //1001 1110
-        }
-        else {//11g, 2.4GHZ
-            *pbyPhySgn = 0x8E; //1000 1110
-        }
-        break;
-
-    case RATE_24M :
-        if(byPacketType == PK_TYPE_11A) {//11a, 5GHZ
-            *pbyPhySgn = 0x99; //1001 1001
-        }
-        else {//11g, 2.4GHZ
-            *pbyPhySgn = 0x89; //1000 1001
-        }
-        break;
-
-    case RATE_36M :
-        if(byPacketType == PK_TYPE_11A) {//11a, 5GHZ
-            *pbyPhySgn = 0x9D; //1001 1101
-        }
-        else {//11g, 2.4GHZ
-            *pbyPhySgn = 0x8D; //1000 1101
-        }
-        break;
-
-    case RATE_48M :
-        if(byPacketType == PK_TYPE_11A) {//11a, 5GHZ
-            *pbyPhySgn = 0x98; //1001 1000
-        }
-        else {//11g, 2.4GHZ
-            *pbyPhySgn = 0x88; //1000 1000
-        }
-        break;
-
-    case RATE_54M :
-        if (byPacketType == PK_TYPE_11A) {//11a, 5GHZ
-            *pbyPhySgn = 0x9C; //1001 1100
-        }
-        else {//11g, 2.4GHZ
-            *pbyPhySgn = 0x8C; //1000 1100
-        }
-        break;
-
-    default :
-        if (byPacketType == PK_TYPE_11A) {//11a, 5GHZ
-            *pbyPhySgn = 0x9C; //1001 1100
-        }
-        else {//11g, 2.4GHZ
-            *pbyPhySgn = 0x8C; //1000 1100
-        }
-        break;
-    }
-
-    if (byPacketType == PK_TYPE_11B) {
-        *pbyPhySrv = 0x00;
-        if (bExtBit)
-            *pbyPhySrv = *pbyPhySrv | 0x80;
-        *pwPhyLen = (unsigned short)cbUsCount;
-    }
-    else {
-        *pbyPhySrv = 0x00;
-        *pwPhyLen = (unsigned short)cbFrameLength;
-    }
+	unsigned int cbBitCount;
+	unsigned int cbUsCount = 0;
+	unsigned int cbTmp;
+	bool bExtBit;
+	unsigned char byPreambleType = pDevice->byPreambleType;
+	bool bCCK = pDevice->bCCK;
+
+	cbBitCount = cbFrameLength * 8;
+	bExtBit = false;
+
+	switch (wRate) {
+	case RATE_1M:
+		cbUsCount = cbBitCount;
+		*pbyPhySgn = 0x00;
+		break;
+
+	case RATE_2M:
+		cbUsCount = cbBitCount / 2;
+		if (byPreambleType == 1)
+			*pbyPhySgn = 0x09;
+		else // long preamble
+			*pbyPhySgn = 0x01;
+		break;
+
+	case RATE_5M:
+		if (bCCK == false)
+			cbBitCount++;
+		cbUsCount = (cbBitCount * 10) / 55;
+		cbTmp = (cbUsCount * 55) / 10;
+		if (cbTmp != cbBitCount)
+			cbUsCount++;
+		if (byPreambleType == 1)
+			*pbyPhySgn = 0x0a;
+		else // long preamble
+			*pbyPhySgn = 0x02;
+		break;
+
+	case RATE_11M:
+
+		if (bCCK == false)
+			cbBitCount++;
+		cbUsCount = cbBitCount / 11;
+		cbTmp = cbUsCount * 11;
+		if (cbTmp != cbBitCount) {
+			cbUsCount++;
+			if ((cbBitCount - cbTmp) <= 3)
+				bExtBit = true;
+		}
+		if (byPreambleType == 1)
+			*pbyPhySgn = 0x0b;
+		else // long preamble
+			*pbyPhySgn = 0x03;
+		break;
+
+	case RATE_6M:
+		if (byPacketType == PK_TYPE_11A) {//11a, 5GHZ
+			*pbyPhySgn = 0x9B; //1001 1011
+		} else {//11g, 2.4GHZ
+			*pbyPhySgn = 0x8B; //1000 1011
+		}
+		break;
+
+	case RATE_9M:
+		if (byPacketType == PK_TYPE_11A) {//11a, 5GHZ
+			*pbyPhySgn = 0x9F; //1001 1111
+		} else {//11g, 2.4GHZ
+			*pbyPhySgn = 0x8F; //1000 1111
+		}
+		break;
+
+	case RATE_12M:
+		if (byPacketType == PK_TYPE_11A) {//11a, 5GHZ
+			*pbyPhySgn = 0x9A; //1001 1010
+		} else {//11g, 2.4GHZ
+			*pbyPhySgn = 0x8A; //1000 1010
+		}
+		break;
+
+	case RATE_18M:
+		if (byPacketType == PK_TYPE_11A) {//11a, 5GHZ
+			*pbyPhySgn = 0x9E; //1001 1110
+		} else {//11g, 2.4GHZ
+			*pbyPhySgn = 0x8E; //1000 1110
+		}
+		break;
+
+	case RATE_24M:
+		if (byPacketType == PK_TYPE_11A) {//11a, 5GHZ
+			*pbyPhySgn = 0x99; //1001 1001
+		} else {//11g, 2.4GHZ
+			*pbyPhySgn = 0x89; //1000 1001
+		}
+		break;
+
+	case RATE_36M:
+		if (byPacketType == PK_TYPE_11A) {//11a, 5GHZ
+			*pbyPhySgn = 0x9D; //1001 1101
+		} else {//11g, 2.4GHZ
+			*pbyPhySgn = 0x8D; //1000 1101
+		}
+		break;
+
+	case RATE_48M:
+		if (byPacketType == PK_TYPE_11A) {//11a, 5GHZ
+			*pbyPhySgn = 0x98; //1001 1000
+		} else {//11g, 2.4GHZ
+			*pbyPhySgn = 0x88; //1000 1000
+		}
+		break;
+
+	case RATE_54M:
+		if (byPacketType == PK_TYPE_11A) {//11a, 5GHZ
+			*pbyPhySgn = 0x9C; //1001 1100
+		} else {//11g, 2.4GHZ
+			*pbyPhySgn = 0x8C; //1000 1100
+		}
+		break;
+
+	default:
+		if (byPacketType == PK_TYPE_11A) {//11a, 5GHZ
+			*pbyPhySgn = 0x9C; //1001 1100
+		} else {//11g, 2.4GHZ
+			*pbyPhySgn = 0x8C; //1000 1100
+		}
+		break;
+	}
+
+	if (byPacketType == PK_TYPE_11B) {
+		*pbyPhySrv = 0x00;
+		if (bExtBit)
+			*pbyPhySrv = *pbyPhySrv | 0x80;
+		*pwPhyLen = (unsigned short)cbUsCount;
+	} else {
+		*pbyPhySrv = 0x00;
+		*pwPhyLen = (unsigned short)cbFrameLength;
+	}
 }
 
 /*
@@ -2013,35 +1991,34 @@ BBvCalculateParameter (
  * Return Value: true if succeeded; false if failed.
  *
  */
-bool BBbReadEmbedded (unsigned long dwIoBase, unsigned char byBBAddr, unsigned char *pbyData)
+bool BBbReadEmbedded(unsigned long dwIoBase, unsigned char byBBAddr, unsigned char *pbyData)
 {
-    unsigned short ww;
-    unsigned char byValue;
-
-    // BB reg offset
-    VNSvOutPortB(dwIoBase + MAC_REG_BBREGADR, byBBAddr);
-
-    // turn on REGR
-    MACvRegBitsOn(dwIoBase, MAC_REG_BBREGCTL, BBREGCTL_REGR);
-    // W_MAX_TIMEOUT is the timeout period
-    for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
-        VNSvInPortB(dwIoBase + MAC_REG_BBREGCTL, &byValue);
-        if (byValue & BBREGCTL_DONE)
-            break;
-    }
-
-    // get BB data
-    VNSvInPortB(dwIoBase + MAC_REG_BBREGDATA, pbyData);
-
-    if (ww == W_MAX_TIMEOUT) {
-        DBG_PORT80(0x30);
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" DBG_PORT80(0x30)\n");
-        return false;
-    }
-    return true;
+	unsigned short ww;
+	unsigned char byValue;
+
+	// BB reg offset
+	VNSvOutPortB(dwIoBase + MAC_REG_BBREGADR, byBBAddr);
+
+	// turn on REGR
+	MACvRegBitsOn(dwIoBase, MAC_REG_BBREGCTL, BBREGCTL_REGR);
+	// W_MAX_TIMEOUT is the timeout period
+	for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
+		VNSvInPortB(dwIoBase + MAC_REG_BBREGCTL, &byValue);
+		if (byValue & BBREGCTL_DONE)
+			break;
+	}
+
+	// get BB data
+	VNSvInPortB(dwIoBase + MAC_REG_BBREGDATA, pbyData);
+
+	if (ww == W_MAX_TIMEOUT) {
+		DBG_PORT80(0x30);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " DBG_PORT80(0x30)\n");
+		return false;
+	}
+	return true;
 }
 
-
 /*
  * Description: Write a Byte to BASEBAND, by embedded programming
  *
@@ -2056,34 +2033,33 @@ bool BBbReadEmbedded (unsigned long dwIoBase, unsigned char byBBAddr, unsigned c
  * Return Value: true if succeeded; false if failed.
  *
  */
-bool BBbWriteEmbedded (unsigned long dwIoBase, unsigned char byBBAddr, unsigned char byData)
+bool BBbWriteEmbedded(unsigned long dwIoBase, unsigned char byBBAddr, unsigned char byData)
 {
-    unsigned short ww;
-    unsigned char byValue;
-
-    // BB reg offset
-    VNSvOutPortB(dwIoBase + MAC_REG_BBREGADR, byBBAddr);
-    // set BB data
-    VNSvOutPortB(dwIoBase + MAC_REG_BBREGDATA, byData);
-
-    // turn on BBREGCTL_REGW
-    MACvRegBitsOn(dwIoBase, MAC_REG_BBREGCTL, BBREGCTL_REGW);
-    // W_MAX_TIMEOUT is the timeout period
-    for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
-        VNSvInPortB(dwIoBase + MAC_REG_BBREGCTL, &byValue);
-        if (byValue & BBREGCTL_DONE)
-            break;
-    }
-
-    if (ww == W_MAX_TIMEOUT) {
-        DBG_PORT80(0x31);
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" DBG_PORT80(0x31)\n");
-        return false;
-    }
-    return true;
+	unsigned short ww;
+	unsigned char byValue;
+
+	// BB reg offset
+	VNSvOutPortB(dwIoBase + MAC_REG_BBREGADR, byBBAddr);
+	// set BB data
+	VNSvOutPortB(dwIoBase + MAC_REG_BBREGDATA, byData);
+
+	// turn on BBREGCTL_REGW
+	MACvRegBitsOn(dwIoBase, MAC_REG_BBREGCTL, BBREGCTL_REGW);
+	// W_MAX_TIMEOUT is the timeout period
+	for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
+		VNSvInPortB(dwIoBase + MAC_REG_BBREGCTL, &byValue);
+		if (byValue & BBREGCTL_DONE)
+			break;
+	}
+
+	if (ww == W_MAX_TIMEOUT) {
+		DBG_PORT80(0x31);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " DBG_PORT80(0x31)\n");
+		return false;
+	}
+	return true;
 }
 
-
 /*
  * Description: Test if all bits are set for the Baseband register
  *
@@ -2098,15 +2074,14 @@ bool BBbWriteEmbedded (unsigned long dwIoBase, unsigned char byBBAddr, unsigned
  * Return Value: true if all TestBits are set; false otherwise.
  *
  */
-bool BBbIsRegBitsOn (unsigned long dwIoBase, unsigned char byBBAddr, unsigned char byTestBits)
+bool BBbIsRegBitsOn(unsigned long dwIoBase, unsigned char byBBAddr, unsigned char byTestBits)
 {
-    unsigned char byOrgData;
+	unsigned char byOrgData;
 
-    BBbReadEmbedded(dwIoBase, byBBAddr, &byOrgData);
-    return (byOrgData & byTestBits) == byTestBits;
+	BBbReadEmbedded(dwIoBase, byBBAddr, &byOrgData);
+	return (byOrgData & byTestBits) == byTestBits;
 }
 
-
 /*
  * Description: Test if all bits are clear for the Baseband register
  *
@@ -2121,12 +2096,12 @@ bool BBbIsRegBitsOn (unsigned long dwIoBase, unsigned char byBBAddr, unsigned ch
  * Return Value: true if all TestBits are clear; false otherwise.
  *
  */
-bool BBbIsRegBitsOff (unsigned long dwIoBase, unsigned char byBBAddr, unsigned char byTestBits)
+bool BBbIsRegBitsOff(unsigned long dwIoBase, unsigned char byBBAddr, unsigned char byTestBits)
 {
-    unsigned char byOrgData;
+	unsigned char byOrgData;
 
-    BBbReadEmbedded(dwIoBase, byBBAddr, &byOrgData);
-    return (byOrgData & byTestBits) == 0;
+	BBbReadEmbedded(dwIoBase, byBBAddr, &byOrgData);
+	return (byOrgData & byTestBits) == 0;
 }
 
 /*
@@ -2144,168 +2119,166 @@ bool BBbIsRegBitsOff (unsigned long dwIoBase, unsigned char byBBAddr, unsigned c
  *
  */
 
-bool BBbVT3253Init (PSDevice pDevice)
+bool BBbVT3253Init(PSDevice pDevice)
 {
-    bool bResult = true;
-    int        ii;
-    unsigned long dwIoBase = pDevice->PortOffset;
-    unsigned char byRFType = pDevice->byRFType;
-    unsigned char byLocalID = pDevice->byLocalID;
-
-    if (byRFType == RF_RFMD2959) {
-        if (byLocalID <= REV_ID_VT3253_A1) {
-            for (ii = 0; ii < CB_VT3253_INIT_FOR_RFMD; ii++) {
-                bResult &= BBbWriteEmbedded(dwIoBase,byVT3253InitTab_RFMD[ii][0],byVT3253InitTab_RFMD[ii][1]);
-            }
-        } else {
-            for (ii = 0; ii < CB_VT3253B0_INIT_FOR_RFMD; ii++) {
-                bResult &= BBbWriteEmbedded(dwIoBase,byVT3253B0_RFMD[ii][0],byVT3253B0_RFMD[ii][1]);
-            }
-            for (ii = 0; ii < CB_VT3253B0_AGC_FOR_RFMD2959; ii++) {
-        	    bResult &= BBbWriteEmbedded(dwIoBase,byVT3253B0_AGC4_RFMD2959[ii][0],byVT3253B0_AGC4_RFMD2959[ii][1]);
-            }
-            VNSvOutPortD(dwIoBase + MAC_REG_ITRTMSET, 0x23);
-            MACvRegBitsOn(dwIoBase, MAC_REG_PAPEDELAY, BIT0);
-        }
-        pDevice->abyBBVGA[0] = 0x18;
-        pDevice->abyBBVGA[1] = 0x0A;
-        pDevice->abyBBVGA[2] = 0x0;
-        pDevice->abyBBVGA[3] = 0x0;
-        pDevice->ldBmThreshold[0] = -70;
-        pDevice->ldBmThreshold[1] = -50;
-        pDevice->ldBmThreshold[2] = 0;
-        pDevice->ldBmThreshold[3] = 0;
-    } else if ((byRFType == RF_AIROHA) || (byRFType == RF_AL2230S) ) {
-        for (ii = 0; ii < CB_VT3253B0_INIT_FOR_AIROHA2230; ii++) {
-    	    bResult &= BBbWriteEmbedded(dwIoBase,byVT3253B0_AIROHA2230[ii][0],byVT3253B0_AIROHA2230[ii][1]);
-    	}
-        for (ii = 0; ii < CB_VT3253B0_AGC; ii++) {
-    	    bResult &= BBbWriteEmbedded(dwIoBase,byVT3253B0_AGC[ii][0],byVT3253B0_AGC[ii][1]);
-    	}
-        pDevice->abyBBVGA[0] = 0x1C;
-        pDevice->abyBBVGA[1] = 0x10;
-        pDevice->abyBBVGA[2] = 0x0;
-        pDevice->abyBBVGA[3] = 0x0;
-        pDevice->ldBmThreshold[0] = -70;
-        pDevice->ldBmThreshold[1] = -48;
-        pDevice->ldBmThreshold[2] = 0;
-        pDevice->ldBmThreshold[3] = 0;
-    } else if (byRFType == RF_UW2451) {
-        for (ii = 0; ii < CB_VT3253B0_INIT_FOR_UW2451; ii++) {
-    	        bResult &= BBbWriteEmbedded(dwIoBase,byVT3253B0_UW2451[ii][0],byVT3253B0_UW2451[ii][1]);
-    	}
-        for (ii = 0; ii < CB_VT3253B0_AGC; ii++) {
-    	    bResult &= BBbWriteEmbedded(dwIoBase,byVT3253B0_AGC[ii][0],byVT3253B0_AGC[ii][1]);
-    	}
-        VNSvOutPortB(dwIoBase + MAC_REG_ITRTMSET, 0x23);
-        MACvRegBitsOn(dwIoBase, MAC_REG_PAPEDELAY, BIT0);
-
-        pDevice->abyBBVGA[0] = 0x14;
-        pDevice->abyBBVGA[1] = 0x0A;
-        pDevice->abyBBVGA[2] = 0x0;
-        pDevice->abyBBVGA[3] = 0x0;
-        pDevice->ldBmThreshold[0] = -60;
-        pDevice->ldBmThreshold[1] = -50;
-        pDevice->ldBmThreshold[2] = 0;
-        pDevice->ldBmThreshold[3] = 0;
-    } else if (byRFType == RF_UW2452) {
-        for (ii = 0; ii < CB_VT3253B0_INIT_FOR_UW2451; ii++) {
-            bResult &= BBbWriteEmbedded(dwIoBase,byVT3253B0_UW2451[ii][0],byVT3253B0_UW2451[ii][1]);
-    	}
-        // Init ANT B select,TX Config CR09 = 0x61->0x45, 0x45->0x41(VC1/VC2 define, make the ANT_A, ANT_B inverted)
-        //bResult &= BBbWriteEmbedded(dwIoBase,0x09,0x41);
-        // Init ANT B select,RX Config CR10 = 0x28->0x2A, 0x2A->0x28(VC1/VC2 define, make the ANT_A, ANT_B inverted)
-        //bResult &= BBbWriteEmbedded(dwIoBase,0x0a,0x28);
-        // Select VC1/VC2, CR215 = 0x02->0x06
-        bResult &= BBbWriteEmbedded(dwIoBase,0xd7,0x06);
-
-        //{{RobertYu:20050125, request by Jack
-        bResult &= BBbWriteEmbedded(dwIoBase,0x90,0x20);
-        bResult &= BBbWriteEmbedded(dwIoBase,0x97,0xeb);
-        //}}
-
-        //{{RobertYu:20050221, request by Jack
-        bResult &= BBbWriteEmbedded(dwIoBase,0xa6,0x00);
-        bResult &= BBbWriteEmbedded(dwIoBase,0xa8,0x30);
-        //}}
-        bResult &= BBbWriteEmbedded(dwIoBase,0xb0,0x58);
-
-        for (ii = 0; ii < CB_VT3253B0_AGC; ii++) {
-    	    bResult &= BBbWriteEmbedded(dwIoBase,byVT3253B0_AGC[ii][0],byVT3253B0_AGC[ii][1]);
-    	}
-        //VNSvOutPortB(dwIoBase + MAC_REG_ITRTMSET, 0x23); // RobertYu: 20050104, 20050131 disable PA_Delay
-        //MACvRegBitsOn(dwIoBase, MAC_REG_PAPEDELAY, BIT0); // RobertYu: 20050104, 20050131 disable PA_Delay
-
-        pDevice->abyBBVGA[0] = 0x14;
-        pDevice->abyBBVGA[1] = 0x0A;
-        pDevice->abyBBVGA[2] = 0x0;
-        pDevice->abyBBVGA[3] = 0x0;
-        pDevice->ldBmThreshold[0] = -60;
-        pDevice->ldBmThreshold[1] = -50;
-        pDevice->ldBmThreshold[2] = 0;
-        pDevice->ldBmThreshold[3] = 0;
-    //}} RobertYu
-
-    } else if (byRFType == RF_VT3226) {
-        for (ii = 0; ii < CB_VT3253B0_INIT_FOR_AIROHA2230; ii++) {
-    	    bResult &= BBbWriteEmbedded(dwIoBase,byVT3253B0_AIROHA2230[ii][0],byVT3253B0_AIROHA2230[ii][1]);
-    	}
-        for (ii = 0; ii < CB_VT3253B0_AGC; ii++) {
-    	    bResult &= BBbWriteEmbedded(dwIoBase,byVT3253B0_AGC[ii][0],byVT3253B0_AGC[ii][1]);
-    	}
-        pDevice->abyBBVGA[0] = 0x1C;
-        pDevice->abyBBVGA[1] = 0x10;
-        pDevice->abyBBVGA[2] = 0x0;
-        pDevice->abyBBVGA[3] = 0x0;
-        pDevice->ldBmThreshold[0] = -70;
-        pDevice->ldBmThreshold[1] = -48;
-        pDevice->ldBmThreshold[2] = 0;
-        pDevice->ldBmThreshold[3] = 0;
-        // Fix VT3226 DFC system timing issue
-        MACvSetRFLE_LatchBase(dwIoBase);
-         //{{ RobertYu: 20050104
-    } else if (byRFType == RF_AIROHA7230) {
-        for (ii = 0; ii < CB_VT3253B0_INIT_FOR_AIROHA2230; ii++) {
-    	    bResult &= BBbWriteEmbedded(dwIoBase,byVT3253B0_AIROHA2230[ii][0],byVT3253B0_AIROHA2230[ii][1]);
-    	}
-
-        //{{ RobertYu:20050223, request by JerryChung
-        // Init ANT B select,TX Config CR09 = 0x61->0x45, 0x45->0x41(VC1/VC2 define, make the ANT_A, ANT_B inverted)
-        //bResult &= BBbWriteEmbedded(dwIoBase,0x09,0x41);
-        // Init ANT B select,RX Config CR10 = 0x28->0x2A, 0x2A->0x28(VC1/VC2 define, make the ANT_A, ANT_B inverted)
-        //bResult &= BBbWriteEmbedded(dwIoBase,0x0a,0x28);
-        // Select VC1/VC2, CR215 = 0x02->0x06
-        bResult &= BBbWriteEmbedded(dwIoBase,0xd7,0x06);
-        //}}
-
-        for (ii = 0; ii < CB_VT3253B0_AGC; ii++) {
-    	    bResult &= BBbWriteEmbedded(dwIoBase,byVT3253B0_AGC[ii][0],byVT3253B0_AGC[ii][1]);
-    	}
-        pDevice->abyBBVGA[0] = 0x1C;
-        pDevice->abyBBVGA[1] = 0x10;
-        pDevice->abyBBVGA[2] = 0x0;
-        pDevice->abyBBVGA[3] = 0x0;
-        pDevice->ldBmThreshold[0] = -70;
-        pDevice->ldBmThreshold[1] = -48;
-        pDevice->ldBmThreshold[2] = 0;
-        pDevice->ldBmThreshold[3] = 0;
-    //}} RobertYu
-    } else {
-    	// No VGA Table now
-    	pDevice->bUpdateBBVGA = false;
-        pDevice->abyBBVGA[0] = 0x1C;
-    }
-
-    if (byLocalID > REV_ID_VT3253_A1) {
-        BBbWriteEmbedded(dwIoBase, 0x04, 0x7F);
-        BBbWriteEmbedded(dwIoBase, 0x0D, 0x01);
-    }
-
-    return bResult;
+	bool bResult = true;
+	int        ii;
+	unsigned long dwIoBase = pDevice->PortOffset;
+	unsigned char byRFType = pDevice->byRFType;
+	unsigned char byLocalID = pDevice->byLocalID;
+
+	if (byRFType == RF_RFMD2959) {
+		if (byLocalID <= REV_ID_VT3253_A1) {
+			for (ii = 0; ii < CB_VT3253_INIT_FOR_RFMD; ii++) {
+				bResult &= BBbWriteEmbedded(dwIoBase, byVT3253InitTab_RFMD[ii][0], byVT3253InitTab_RFMD[ii][1]);
+			}
+		} else {
+			for (ii = 0; ii < CB_VT3253B0_INIT_FOR_RFMD; ii++) {
+				bResult &= BBbWriteEmbedded(dwIoBase, byVT3253B0_RFMD[ii][0], byVT3253B0_RFMD[ii][1]);
+			}
+			for (ii = 0; ii < CB_VT3253B0_AGC_FOR_RFMD2959; ii++) {
+				bResult &= BBbWriteEmbedded(dwIoBase, byVT3253B0_AGC4_RFMD2959[ii][0], byVT3253B0_AGC4_RFMD2959[ii][1]);
+			}
+			VNSvOutPortD(dwIoBase + MAC_REG_ITRTMSET, 0x23);
+			MACvRegBitsOn(dwIoBase, MAC_REG_PAPEDELAY, BIT0);
+		}
+		pDevice->abyBBVGA[0] = 0x18;
+		pDevice->abyBBVGA[1] = 0x0A;
+		pDevice->abyBBVGA[2] = 0x0;
+		pDevice->abyBBVGA[3] = 0x0;
+		pDevice->ldBmThreshold[0] = -70;
+		pDevice->ldBmThreshold[1] = -50;
+		pDevice->ldBmThreshold[2] = 0;
+		pDevice->ldBmThreshold[3] = 0;
+	} else if ((byRFType == RF_AIROHA) || (byRFType == RF_AL2230S)) {
+		for (ii = 0; ii < CB_VT3253B0_INIT_FOR_AIROHA2230; ii++) {
+			bResult &= BBbWriteEmbedded(dwIoBase, byVT3253B0_AIROHA2230[ii][0], byVT3253B0_AIROHA2230[ii][1]);
+		}
+		for (ii = 0; ii < CB_VT3253B0_AGC; ii++) {
+			bResult &= BBbWriteEmbedded(dwIoBase, byVT3253B0_AGC[ii][0], byVT3253B0_AGC[ii][1]);
+		}
+		pDevice->abyBBVGA[0] = 0x1C;
+		pDevice->abyBBVGA[1] = 0x10;
+		pDevice->abyBBVGA[2] = 0x0;
+		pDevice->abyBBVGA[3] = 0x0;
+		pDevice->ldBmThreshold[0] = -70;
+		pDevice->ldBmThreshold[1] = -48;
+		pDevice->ldBmThreshold[2] = 0;
+		pDevice->ldBmThreshold[3] = 0;
+	} else if (byRFType == RF_UW2451) {
+		for (ii = 0; ii < CB_VT3253B0_INIT_FOR_UW2451; ii++) {
+			bResult &= BBbWriteEmbedded(dwIoBase, byVT3253B0_UW2451[ii][0], byVT3253B0_UW2451[ii][1]);
+		}
+		for (ii = 0; ii < CB_VT3253B0_AGC; ii++) {
+			bResult &= BBbWriteEmbedded(dwIoBase, byVT3253B0_AGC[ii][0], byVT3253B0_AGC[ii][1]);
+		}
+		VNSvOutPortB(dwIoBase + MAC_REG_ITRTMSET, 0x23);
+		MACvRegBitsOn(dwIoBase, MAC_REG_PAPEDELAY, BIT0);
+
+		pDevice->abyBBVGA[0] = 0x14;
+		pDevice->abyBBVGA[1] = 0x0A;
+		pDevice->abyBBVGA[2] = 0x0;
+		pDevice->abyBBVGA[3] = 0x0;
+		pDevice->ldBmThreshold[0] = -60;
+		pDevice->ldBmThreshold[1] = -50;
+		pDevice->ldBmThreshold[2] = 0;
+		pDevice->ldBmThreshold[3] = 0;
+	} else if (byRFType == RF_UW2452) {
+		for (ii = 0; ii < CB_VT3253B0_INIT_FOR_UW2451; ii++) {
+			bResult &= BBbWriteEmbedded(dwIoBase, byVT3253B0_UW2451[ii][0], byVT3253B0_UW2451[ii][1]);
+		}
+		// Init ANT B select,TX Config CR09 = 0x61->0x45, 0x45->0x41(VC1/VC2 define, make the ANT_A, ANT_B inverted)
+		//bResult &= BBbWriteEmbedded(dwIoBase,0x09,0x41);
+		// Init ANT B select,RX Config CR10 = 0x28->0x2A, 0x2A->0x28(VC1/VC2 define, make the ANT_A, ANT_B inverted)
+		//bResult &= BBbWriteEmbedded(dwIoBase,0x0a,0x28);
+		// Select VC1/VC2, CR215 = 0x02->0x06
+		bResult &= BBbWriteEmbedded(dwIoBase, 0xd7, 0x06);
+
+		//{{RobertYu:20050125, request by Jack
+		bResult &= BBbWriteEmbedded(dwIoBase, 0x90, 0x20);
+		bResult &= BBbWriteEmbedded(dwIoBase, 0x97, 0xeb);
+		//}}
+
+		//{{RobertYu:20050221, request by Jack
+		bResult &= BBbWriteEmbedded(dwIoBase, 0xa6, 0x00);
+		bResult &= BBbWriteEmbedded(dwIoBase, 0xa8, 0x30);
+		//}}
+		bResult &= BBbWriteEmbedded(dwIoBase, 0xb0, 0x58);
+
+		for (ii = 0; ii < CB_VT3253B0_AGC; ii++) {
+			bResult &= BBbWriteEmbedded(dwIoBase, byVT3253B0_AGC[ii][0], byVT3253B0_AGC[ii][1]);
+		}
+		//VNSvOutPortB(dwIoBase + MAC_REG_ITRTMSET, 0x23); // RobertYu: 20050104, 20050131 disable PA_Delay
+		//MACvRegBitsOn(dwIoBase, MAC_REG_PAPEDELAY, BIT0); // RobertYu: 20050104, 20050131 disable PA_Delay
+
+		pDevice->abyBBVGA[0] = 0x14;
+		pDevice->abyBBVGA[1] = 0x0A;
+		pDevice->abyBBVGA[2] = 0x0;
+		pDevice->abyBBVGA[3] = 0x0;
+		pDevice->ldBmThreshold[0] = -60;
+		pDevice->ldBmThreshold[1] = -50;
+		pDevice->ldBmThreshold[2] = 0;
+		pDevice->ldBmThreshold[3] = 0;
+		//}} RobertYu
+
+	} else if (byRFType == RF_VT3226) {
+		for (ii = 0; ii < CB_VT3253B0_INIT_FOR_AIROHA2230; ii++) {
+			bResult &= BBbWriteEmbedded(dwIoBase, byVT3253B0_AIROHA2230[ii][0], byVT3253B0_AIROHA2230[ii][1]);
+		}
+		for (ii = 0; ii < CB_VT3253B0_AGC; ii++) {
+			bResult &= BBbWriteEmbedded(dwIoBase, byVT3253B0_AGC[ii][0], byVT3253B0_AGC[ii][1]);
+		}
+		pDevice->abyBBVGA[0] = 0x1C;
+		pDevice->abyBBVGA[1] = 0x10;
+		pDevice->abyBBVGA[2] = 0x0;
+		pDevice->abyBBVGA[3] = 0x0;
+		pDevice->ldBmThreshold[0] = -70;
+		pDevice->ldBmThreshold[1] = -48;
+		pDevice->ldBmThreshold[2] = 0;
+		pDevice->ldBmThreshold[3] = 0;
+		// Fix VT3226 DFC system timing issue
+		MACvSetRFLE_LatchBase(dwIoBase);
+		//{{ RobertYu: 20050104
+	} else if (byRFType == RF_AIROHA7230) {
+		for (ii = 0; ii < CB_VT3253B0_INIT_FOR_AIROHA2230; ii++) {
+			bResult &= BBbWriteEmbedded(dwIoBase, byVT3253B0_AIROHA2230[ii][0], byVT3253B0_AIROHA2230[ii][1]);
+		}
+
+		//{{ RobertYu:20050223, request by JerryChung
+		// Init ANT B select,TX Config CR09 = 0x61->0x45, 0x45->0x41(VC1/VC2 define, make the ANT_A, ANT_B inverted)
+		//bResult &= BBbWriteEmbedded(dwIoBase,0x09,0x41);
+		// Init ANT B select,RX Config CR10 = 0x28->0x2A, 0x2A->0x28(VC1/VC2 define, make the ANT_A, ANT_B inverted)
+		//bResult &= BBbWriteEmbedded(dwIoBase,0x0a,0x28);
+		// Select VC1/VC2, CR215 = 0x02->0x06
+		bResult &= BBbWriteEmbedded(dwIoBase, 0xd7, 0x06);
+		//}}
+
+		for (ii = 0; ii < CB_VT3253B0_AGC; ii++) {
+			bResult &= BBbWriteEmbedded(dwIoBase, byVT3253B0_AGC[ii][0], byVT3253B0_AGC[ii][1]);
+		}
+		pDevice->abyBBVGA[0] = 0x1C;
+		pDevice->abyBBVGA[1] = 0x10;
+		pDevice->abyBBVGA[2] = 0x0;
+		pDevice->abyBBVGA[3] = 0x0;
+		pDevice->ldBmThreshold[0] = -70;
+		pDevice->ldBmThreshold[1] = -48;
+		pDevice->ldBmThreshold[2] = 0;
+		pDevice->ldBmThreshold[3] = 0;
+		//}} RobertYu
+	} else {
+		// No VGA Table now
+		pDevice->bUpdateBBVGA = false;
+		pDevice->abyBBVGA[0] = 0x1C;
+	}
+
+	if (byLocalID > REV_ID_VT3253_A1) {
+		BBbWriteEmbedded(dwIoBase, 0x04, 0x7F);
+		BBbWriteEmbedded(dwIoBase, 0x0D, 0x01);
+	}
+
+	return bResult;
 }
 
-
-
 /*
  * Description: Read All Baseband Registers
  *
@@ -2319,14 +2292,14 @@ bool BBbVT3253Init (PSDevice pDevice)
  * Return Value: none
  *
  */
-void BBvReadAllRegs (unsigned long dwIoBase, unsigned char *pbyBBRegs)
+void BBvReadAllRegs(unsigned long dwIoBase, unsigned char *pbyBBRegs)
 {
-    int  ii;
-    unsigned char byBase = 1;
-    for (ii = 0; ii < BB_MAX_CONTEXT_SIZE; ii++) {
-        BBbReadEmbedded(dwIoBase, (unsigned char)(ii*byBase), pbyBBRegs);
-        pbyBBRegs += byBase;
-    }
+	int  ii;
+	unsigned char byBase = 1;
+	for (ii = 0; ii < BB_MAX_CONTEXT_SIZE; ii++) {
+		BBbReadEmbedded(dwIoBase, (unsigned char)(ii*byBase), pbyBBRegs);
+		pbyBBRegs += byBase;
+	}
 }
 
 /*
@@ -2343,46 +2316,44 @@ void BBvReadAllRegs (unsigned long dwIoBase, unsigned char *pbyBBRegs)
  *
  */
 
-
-void BBvLoopbackOn (PSDevice pDevice)
+void BBvLoopbackOn(PSDevice pDevice)
 {
-    unsigned char byData;
-    unsigned long dwIoBase = pDevice->PortOffset;
-
-    //CR C9 = 0x00
-    BBbReadEmbedded(dwIoBase, 0xC9, &pDevice->byBBCRc9);//CR201
-    BBbWriteEmbedded(dwIoBase, 0xC9, 0);
-    BBbReadEmbedded(dwIoBase, 0x4D, &pDevice->byBBCR4d);//CR77
-    BBbWriteEmbedded(dwIoBase, 0x4D, 0x90);
-
-    //CR 88 = 0x02(CCK), 0x03(OFDM)
-    BBbReadEmbedded(dwIoBase, 0x88, &pDevice->byBBCR88);//CR136
-
-    if (pDevice->uConnectionRate <= RATE_11M) { //CCK
-        // Enable internal digital loopback: CR33 |= 0000 0001
-        BBbReadEmbedded(dwIoBase, 0x21, &byData);//CR33
-        BBbWriteEmbedded(dwIoBase, 0x21, (unsigned char)(byData | 0x01));//CR33
-        // CR154 = 0x00
-        BBbWriteEmbedded(dwIoBase, 0x9A, 0);   //CR154
-
-        BBbWriteEmbedded(dwIoBase, 0x88, 0x02);//CR239
-    }
-    else { //OFDM
-        // Enable internal digital loopback:CR154 |= 0000 0001
-        BBbReadEmbedded(dwIoBase, 0x9A, &byData);//CR154
-        BBbWriteEmbedded(dwIoBase, 0x9A, (unsigned char)(byData | 0x01));//CR154
-        // CR33 = 0x00
-        BBbWriteEmbedded(dwIoBase, 0x21, 0);   //CR33
-
-        BBbWriteEmbedded(dwIoBase, 0x88, 0x03);//CR239
-    }
-
-    //CR14 = 0x00
-    BBbWriteEmbedded(dwIoBase, 0x0E, 0);//CR14
-
-    // Disable TX_IQUN
-    BBbReadEmbedded(pDevice->PortOffset, 0x09, &pDevice->byBBCR09);
-    BBbWriteEmbedded(pDevice->PortOffset, 0x09, (unsigned char)(pDevice->byBBCR09 & 0xDE));
+	unsigned char byData;
+	unsigned long dwIoBase = pDevice->PortOffset;
+
+	//CR C9 = 0x00
+	BBbReadEmbedded(dwIoBase, 0xC9, &pDevice->byBBCRc9);//CR201
+	BBbWriteEmbedded(dwIoBase, 0xC9, 0);
+	BBbReadEmbedded(dwIoBase, 0x4D, &pDevice->byBBCR4d);//CR77
+	BBbWriteEmbedded(dwIoBase, 0x4D, 0x90);
+
+	//CR 88 = 0x02(CCK), 0x03(OFDM)
+	BBbReadEmbedded(dwIoBase, 0x88, &pDevice->byBBCR88);//CR136
+
+	if (pDevice->uConnectionRate <= RATE_11M) { //CCK
+		// Enable internal digital loopback: CR33 |= 0000 0001
+		BBbReadEmbedded(dwIoBase, 0x21, &byData);//CR33
+		BBbWriteEmbedded(dwIoBase, 0x21, (unsigned char)(byData | 0x01));//CR33
+		// CR154 = 0x00
+		BBbWriteEmbedded(dwIoBase, 0x9A, 0);   //CR154
+
+		BBbWriteEmbedded(dwIoBase, 0x88, 0x02);//CR239
+	} else { //OFDM
+		// Enable internal digital loopback:CR154 |= 0000 0001
+		BBbReadEmbedded(dwIoBase, 0x9A, &byData);//CR154
+		BBbWriteEmbedded(dwIoBase, 0x9A, (unsigned char)(byData | 0x01));//CR154
+		// CR33 = 0x00
+		BBbWriteEmbedded(dwIoBase, 0x21, 0);   //CR33
+
+		BBbWriteEmbedded(dwIoBase, 0x88, 0x03);//CR239
+	}
+
+	//CR14 = 0x00
+	BBbWriteEmbedded(dwIoBase, 0x0E, 0);//CR14
+
+	// Disable TX_IQUN
+	BBbReadEmbedded(pDevice->PortOffset, 0x09, &pDevice->byBBCR09);
+	BBbWriteEmbedded(pDevice->PortOffset, 0x09, (unsigned char)(pDevice->byBBCR09 & 0xDE));
 }
 
 /*
@@ -2398,32 +2369,28 @@ void BBvLoopbackOn (PSDevice pDevice)
  * Return Value: none
  *
  */
-void BBvLoopbackOff (PSDevice pDevice)
+void BBvLoopbackOff(PSDevice pDevice)
 {
-    unsigned char byData;
-    unsigned long dwIoBase = pDevice->PortOffset;
-
-    BBbWriteEmbedded(dwIoBase, 0xC9, pDevice->byBBCRc9);//CR201
-    BBbWriteEmbedded(dwIoBase, 0x88, pDevice->byBBCR88);//CR136
-    BBbWriteEmbedded(dwIoBase, 0x09, pDevice->byBBCR09);//CR136
-    BBbWriteEmbedded(dwIoBase, 0x4D, pDevice->byBBCR4d);//CR77
-
-    if (pDevice->uConnectionRate <= RATE_11M) { // CCK
-        // Set the CR33 Bit2 to disable internal Loopback.
-        BBbReadEmbedded(dwIoBase, 0x21, &byData);//CR33
-        BBbWriteEmbedded(dwIoBase, 0x21, (unsigned char)(byData & 0xFE));//CR33
-    }
-    else { // OFDM
-        BBbReadEmbedded(dwIoBase, 0x9A, &byData);//CR154
-        BBbWriteEmbedded(dwIoBase, 0x9A, (unsigned char)(byData & 0xFE));//CR154
-    }
-    BBbReadEmbedded(dwIoBase, 0x0E, &byData);//CR14
-    BBbWriteEmbedded(dwIoBase, 0x0E, (unsigned char)(byData | 0x80));//CR14
-
+	unsigned char byData;
+	unsigned long dwIoBase = pDevice->PortOffset;
+
+	BBbWriteEmbedded(dwIoBase, 0xC9, pDevice->byBBCRc9);//CR201
+	BBbWriteEmbedded(dwIoBase, 0x88, pDevice->byBBCR88);//CR136
+	BBbWriteEmbedded(dwIoBase, 0x09, pDevice->byBBCR09);//CR136
+	BBbWriteEmbedded(dwIoBase, 0x4D, pDevice->byBBCR4d);//CR77
+
+	if (pDevice->uConnectionRate <= RATE_11M) { // CCK
+		// Set the CR33 Bit2 to disable internal Loopback.
+		BBbReadEmbedded(dwIoBase, 0x21, &byData);//CR33
+		BBbWriteEmbedded(dwIoBase, 0x21, (unsigned char)(byData & 0xFE));//CR33
+	} else { // OFDM
+		BBbReadEmbedded(dwIoBase, 0x9A, &byData);//CR154
+		BBbWriteEmbedded(dwIoBase, 0x9A, (unsigned char)(byData & 0xFE));//CR154
+	}
+	BBbReadEmbedded(dwIoBase, 0x0E, &byData);//CR14
+	BBbWriteEmbedded(dwIoBase, 0x0E, (unsigned char)(byData | 0x80));//CR14
 }
 
-
-
 /*
  * Description: Set ShortSlotTime mode
  *
@@ -2437,49 +2404,47 @@ void BBvLoopbackOff (PSDevice pDevice)
  *
  */
 void
-BBvSetShortSlotTime (PSDevice pDevice)
+BBvSetShortSlotTime(PSDevice pDevice)
 {
-    unsigned char byBBRxConf=0;
-    unsigned char byBBVGA=0;
+	unsigned char byBBRxConf = 0;
+	unsigned char byBBVGA = 0;
 
-    BBbReadEmbedded(pDevice->PortOffset, 0x0A, &byBBRxConf);//CR10
+	BBbReadEmbedded(pDevice->PortOffset, 0x0A, &byBBRxConf);//CR10
 
-    if (pDevice->bShortSlotTime) {
-        byBBRxConf &= 0xDF;//1101 1111
-    } else {
-        byBBRxConf |= 0x20;//0010 0000
-    }
+	if (pDevice->bShortSlotTime) {
+		byBBRxConf &= 0xDF;//1101 1111
+	} else {
+		byBBRxConf |= 0x20;//0010 0000
+	}
 
-    // patch for 3253B0 Baseband with Cardbus module
-    BBbReadEmbedded(pDevice->PortOffset, 0xE7, &byBBVGA);
-    if (byBBVGA == pDevice->abyBBVGA[0]) {
-        byBBRxConf |= 0x20;//0010 0000
-    }
-
-    BBbWriteEmbedded(pDevice->PortOffset, 0x0A, byBBRxConf);//CR10
+	// patch for 3253B0 Baseband with Cardbus module
+	BBbReadEmbedded(pDevice->PortOffset, 0xE7, &byBBVGA);
+	if (byBBVGA == pDevice->abyBBVGA[0]) {
+		byBBRxConf |= 0x20;//0010 0000
+	}
 
+	BBbWriteEmbedded(pDevice->PortOffset, 0x0A, byBBRxConf);//CR10
 }
 
 void BBvSetVGAGainOffset(PSDevice pDevice, unsigned char byData)
 {
-    unsigned char byBBRxConf=0;
-
-    BBbWriteEmbedded(pDevice->PortOffset, 0xE7, byData);
-
-    BBbReadEmbedded(pDevice->PortOffset, 0x0A, &byBBRxConf);//CR10
-    // patch for 3253B0 Baseband with Cardbus module
-    if (byData == pDevice->abyBBVGA[0]) {
-        byBBRxConf |= 0x20;//0010 0000
-    } else if (pDevice->bShortSlotTime) {
-        byBBRxConf &= 0xDF;//1101 1111
-    } else {
-        byBBRxConf |= 0x20;//0010 0000
-    }
-    pDevice->byBBVGACurrent = byData;
-    BBbWriteEmbedded(pDevice->PortOffset, 0x0A, byBBRxConf);//CR10
+	unsigned char byBBRxConf = 0;
+
+	BBbWriteEmbedded(pDevice->PortOffset, 0xE7, byData);
+
+	BBbReadEmbedded(pDevice->PortOffset, 0x0A, &byBBRxConf);//CR10
+	// patch for 3253B0 Baseband with Cardbus module
+	if (byData == pDevice->abyBBVGA[0]) {
+		byBBRxConf |= 0x20;//0010 0000
+	} else if (pDevice->bShortSlotTime) {
+		byBBRxConf &= 0xDF;//1101 1111
+	} else {
+		byBBRxConf |= 0x20;//0010 0000
+	}
+	pDevice->byBBVGACurrent = byData;
+	BBbWriteEmbedded(pDevice->PortOffset, 0x0A, byBBRxConf);//CR10
 }
 
-
 /*
  * Description: Baseband SoftwareReset
  *
@@ -2493,12 +2458,12 @@ void BBvSetVGAGainOffset(PSDevice pDevice, unsigned char byData)
  *
  */
 void
-BBvSoftwareReset (unsigned long dwIoBase)
+BBvSoftwareReset(unsigned long dwIoBase)
 {
-    BBbWriteEmbedded(dwIoBase, 0x50, 0x40);
-    BBbWriteEmbedded(dwIoBase, 0x50, 0);
-    BBbWriteEmbedded(dwIoBase, 0x9C, 0x01);
-    BBbWriteEmbedded(dwIoBase, 0x9C, 0);
+	BBbWriteEmbedded(dwIoBase, 0x50, 0x40);
+	BBbWriteEmbedded(dwIoBase, 0x50, 0);
+	BBbWriteEmbedded(dwIoBase, 0x9C, 0x01);
+	BBbWriteEmbedded(dwIoBase, 0x9C, 0);
 }
 
 /*
@@ -2514,13 +2479,13 @@ BBvSoftwareReset (unsigned long dwIoBase)
  *
  */
 void
-BBvPowerSaveModeON (unsigned long dwIoBase)
+BBvPowerSaveModeON(unsigned long dwIoBase)
 {
-    unsigned char byOrgData;
+	unsigned char byOrgData;
 
-    BBbReadEmbedded(dwIoBase, 0x0D, &byOrgData);
-    byOrgData |= BIT0;
-    BBbWriteEmbedded(dwIoBase, 0x0D, byOrgData);
+	BBbReadEmbedded(dwIoBase, 0x0D, &byOrgData);
+	byOrgData |= BIT0;
+	BBbWriteEmbedded(dwIoBase, 0x0D, byOrgData);
 }
 
 /*
@@ -2536,13 +2501,13 @@ BBvPowerSaveModeON (unsigned long dwIoBase)
  *
  */
 void
-BBvPowerSaveModeOFF (unsigned long dwIoBase)
+BBvPowerSaveModeOFF(unsigned long dwIoBase)
 {
-    unsigned char byOrgData;
+	unsigned char byOrgData;
 
-    BBbReadEmbedded(dwIoBase, 0x0D, &byOrgData);
-    byOrgData &= ~(BIT0);
-    BBbWriteEmbedded(dwIoBase, 0x0D, byOrgData);
+	BBbReadEmbedded(dwIoBase, 0x0D, &byOrgData);
+	byOrgData &= ~(BIT0);
+	BBbWriteEmbedded(dwIoBase, 0x0D, byOrgData);
 }
 
 /*
@@ -2560,33 +2525,24 @@ BBvPowerSaveModeOFF (unsigned long dwIoBase)
  */
 
 void
-BBvSetTxAntennaMode (unsigned long dwIoBase, unsigned char byAntennaMode)
+BBvSetTxAntennaMode(unsigned long dwIoBase, unsigned char byAntennaMode)
 {
-    unsigned char byBBTxConf;
-
-#ifdef	PLICE_DEBUG
-	//printk("Enter BBvSetTxAntennaMode\n");
-#endif
-    BBbReadEmbedded(dwIoBase, 0x09, &byBBTxConf);//CR09
-    if (byAntennaMode == ANT_DIVERSITY) {
-        // bit 1 is diversity
-        byBBTxConf |= 0x02;
-    } else if (byAntennaMode == ANT_A) {
-        // bit 2 is ANTSEL
-        byBBTxConf &= 0xF9; // 1111 1001
-    } else if (byAntennaMode == ANT_B) {
-#ifdef	PLICE_DEBUG
-	//printk("BBvSetTxAntennaMode:ANT_B\n");
-#endif
-        byBBTxConf &= 0xFD; // 1111 1101
-        byBBTxConf |= 0x04;
-    }
-    BBbWriteEmbedded(dwIoBase, 0x09, byBBTxConf);//CR09
+	unsigned char byBBTxConf;
+
+	BBbReadEmbedded(dwIoBase, 0x09, &byBBTxConf);//CR09
+	if (byAntennaMode == ANT_DIVERSITY) {
+		// bit 1 is diversity
+		byBBTxConf |= 0x02;
+	} else if (byAntennaMode == ANT_A) {
+		// bit 2 is ANTSEL
+		byBBTxConf &= 0xF9; // 1111 1001
+	} else if (byAntennaMode == ANT_B) {
+		byBBTxConf &= 0xFD; // 1111 1101
+		byBBTxConf |= 0x04;
+	}
+	BBbWriteEmbedded(dwIoBase, 0x09, byBBTxConf);//CR09
 }
 
-
-
-
 /*
  * Description: Set Rx Antenna mode
  *
@@ -2602,24 +2558,23 @@ BBvSetTxAntennaMode (unsigned long dwIoBase, unsigned char byAntennaMode)
  */
 
 void
-BBvSetRxAntennaMode (unsigned long dwIoBase, unsigned char byAntennaMode)
+BBvSetRxAntennaMode(unsigned long dwIoBase, unsigned char byAntennaMode)
 {
-    unsigned char byBBRxConf;
-
-    BBbReadEmbedded(dwIoBase, 0x0A, &byBBRxConf);//CR10
-    if (byAntennaMode == ANT_DIVERSITY) {
-        byBBRxConf |= 0x01;
-
-    } else if (byAntennaMode == ANT_A) {
-        byBBRxConf &= 0xFC; // 1111 1100
-    } else if (byAntennaMode == ANT_B) {
-        byBBRxConf &= 0xFE; // 1111 1110
-        byBBRxConf |= 0x02;
-    }
-    BBbWriteEmbedded(dwIoBase, 0x0A, byBBRxConf);//CR10
+	unsigned char byBBRxConf;
+
+	BBbReadEmbedded(dwIoBase, 0x0A, &byBBRxConf);//CR10
+	if (byAntennaMode == ANT_DIVERSITY) {
+		byBBRxConf |= 0x01;
+
+	} else if (byAntennaMode == ANT_A) {
+		byBBRxConf &= 0xFC; // 1111 1100
+	} else if (byAntennaMode == ANT_B) {
+		byBBRxConf &= 0xFE; // 1111 1110
+		byBBRxConf |= 0x02;
+	}
+	BBbWriteEmbedded(dwIoBase, 0x0A, byBBRxConf);//CR10
 }
 
-
 /*
  * Description: BBvSetDeepSleep
  *
@@ -2633,142 +2588,138 @@ BBvSetRxAntennaMode (unsigned long dwIoBase, unsigned char byAntennaMode)
  *
  */
 void
-BBvSetDeepSleep (unsigned long dwIoBase, unsigned char byLocalID)
+BBvSetDeepSleep(unsigned long dwIoBase, unsigned char byLocalID)
 {
-    BBbWriteEmbedded(dwIoBase, 0x0C, 0x17);//CR12
-    BBbWriteEmbedded(dwIoBase, 0x0D, 0xB9);//CR13
+	BBbWriteEmbedded(dwIoBase, 0x0C, 0x17);//CR12
+	BBbWriteEmbedded(dwIoBase, 0x0D, 0xB9);//CR13
 }
 
 void
-BBvExitDeepSleep (unsigned long dwIoBase, unsigned char byLocalID)
+BBvExitDeepSleep(unsigned long dwIoBase, unsigned char byLocalID)
 {
-    BBbWriteEmbedded(dwIoBase, 0x0C, 0x00);//CR12
-    BBbWriteEmbedded(dwIoBase, 0x0D, 0x01);//CR13
+	BBbWriteEmbedded(dwIoBase, 0x0C, 0x00);//CR12
+	BBbWriteEmbedded(dwIoBase, 0x0D, 0x01);//CR13
 }
 
-
-
 static
 unsigned long
-s_ulGetRatio (PSDevice pDevice)
+s_ulGetRatio(PSDevice pDevice)
 {
-unsigned long ulRatio = 0;
-unsigned long ulMaxPacket;
-unsigned long ulPacketNum;
-
-    //This is a thousand-ratio
-    ulMaxPacket = pDevice->uNumSQ3[RATE_54M];
-    if ( pDevice->uNumSQ3[RATE_54M] != 0 ) {
-        ulPacketNum = pDevice->uNumSQ3[RATE_54M];
-        ulRatio = (ulPacketNum * 1000 / pDevice->uDiversityCnt);
-        //ulRatio = (pDevice->uNumSQ3[RATE_54M] * 1000 / pDevice->uDiversityCnt);
-        ulRatio += TOP_RATE_54M;
-    }
-    if ( pDevice->uNumSQ3[RATE_48M] > ulMaxPacket ) {
-        ulPacketNum = pDevice->uNumSQ3[RATE_54M] + pDevice->uNumSQ3[RATE_48M];
-        ulRatio = (ulPacketNum * 1000 / pDevice->uDiversityCnt);
-        //ulRatio = (pDevice->uNumSQ3[RATE_48M] * 1000 / pDevice->uDiversityCnt);
-        ulRatio += TOP_RATE_48M;
-        ulMaxPacket = pDevice->uNumSQ3[RATE_48M];
-    }
-    if ( pDevice->uNumSQ3[RATE_36M] > ulMaxPacket ) {
-        ulPacketNum = pDevice->uNumSQ3[RATE_54M] + pDevice->uNumSQ3[RATE_48M] +
-                      pDevice->uNumSQ3[RATE_36M];
-        ulRatio = (ulPacketNum * 1000 / pDevice->uDiversityCnt);
-        //ulRatio = (pDevice->uNumSQ3[RATE_36M] * 1000 / pDevice->uDiversityCnt);
-        ulRatio += TOP_RATE_36M;
-        ulMaxPacket = pDevice->uNumSQ3[RATE_36M];
-    }
-    if ( pDevice->uNumSQ3[RATE_24M] > ulMaxPacket ) {
-        ulPacketNum = pDevice->uNumSQ3[RATE_54M] + pDevice->uNumSQ3[RATE_48M] +
-                      pDevice->uNumSQ3[RATE_36M] + pDevice->uNumSQ3[RATE_24M];
-        ulRatio = (ulPacketNum * 1000 / pDevice->uDiversityCnt);
-        //ulRatio = (pDevice->uNumSQ3[RATE_24M] * 1000 / pDevice->uDiversityCnt);
-        ulRatio += TOP_RATE_24M;
-        ulMaxPacket = pDevice->uNumSQ3[RATE_24M];
-    }
-    if ( pDevice->uNumSQ3[RATE_18M] > ulMaxPacket ) {
-        ulPacketNum = pDevice->uNumSQ3[RATE_54M] + pDevice->uNumSQ3[RATE_48M] +
-                      pDevice->uNumSQ3[RATE_36M] + pDevice->uNumSQ3[RATE_24M] +
-                      pDevice->uNumSQ3[RATE_18M];
-        ulRatio = (ulPacketNum * 1000 / pDevice->uDiversityCnt);
-        //ulRatio = (pDevice->uNumSQ3[RATE_18M] * 1000 / pDevice->uDiversityCnt);
-        ulRatio += TOP_RATE_18M;
-        ulMaxPacket = pDevice->uNumSQ3[RATE_18M];
-    }
-    if ( pDevice->uNumSQ3[RATE_12M] > ulMaxPacket ) {
-        ulPacketNum = pDevice->uNumSQ3[RATE_54M] + pDevice->uNumSQ3[RATE_48M] +
-                      pDevice->uNumSQ3[RATE_36M] + pDevice->uNumSQ3[RATE_24M] +
-                      pDevice->uNumSQ3[RATE_18M] + pDevice->uNumSQ3[RATE_12M];
-        ulRatio = (ulPacketNum * 1000 / pDevice->uDiversityCnt);
-        //ulRatio = (pDevice->uNumSQ3[RATE_12M] * 1000 / pDevice->uDiversityCnt);
-        ulRatio += TOP_RATE_12M;
-        ulMaxPacket = pDevice->uNumSQ3[RATE_12M];
-    }
-    if ( pDevice->uNumSQ3[RATE_11M] > ulMaxPacket ) {
-        ulPacketNum = pDevice->uDiversityCnt - pDevice->uNumSQ3[RATE_1M] -
-                      pDevice->uNumSQ3[RATE_2M] - pDevice->uNumSQ3[RATE_5M] -
-                      pDevice->uNumSQ3[RATE_6M] - pDevice->uNumSQ3[RATE_9M];
-        ulRatio = (ulPacketNum * 1000 / pDevice->uDiversityCnt);
-        //ulRatio = (pDevice->uNumSQ3[RATE_11M] * 1000 / pDevice->uDiversityCnt);
-        ulRatio += TOP_RATE_11M;
-        ulMaxPacket = pDevice->uNumSQ3[RATE_11M];
-    }
-    if ( pDevice->uNumSQ3[RATE_9M] > ulMaxPacket ) {
-        ulPacketNum = pDevice->uDiversityCnt - pDevice->uNumSQ3[RATE_1M] -
-                      pDevice->uNumSQ3[RATE_2M] - pDevice->uNumSQ3[RATE_5M] -
-                      pDevice->uNumSQ3[RATE_6M];
-        ulRatio = (ulPacketNum * 1000 / pDevice->uDiversityCnt);
-        //ulRatio = (pDevice->uNumSQ3[RATE_9M] * 1000 / pDevice->uDiversityCnt);
-        ulRatio += TOP_RATE_9M;
-        ulMaxPacket = pDevice->uNumSQ3[RATE_9M];
-    }
-    if ( pDevice->uNumSQ3[RATE_6M] > ulMaxPacket ) {
-        ulPacketNum = pDevice->uDiversityCnt - pDevice->uNumSQ3[RATE_1M] -
-                      pDevice->uNumSQ3[RATE_2M] - pDevice->uNumSQ3[RATE_5M];
-        ulRatio = (ulPacketNum * 1000 / pDevice->uDiversityCnt);
-        //ulRatio = (pDevice->uNumSQ3[RATE_6M] * 1000 / pDevice->uDiversityCnt);
-        ulRatio += TOP_RATE_6M;
-        ulMaxPacket = pDevice->uNumSQ3[RATE_6M];
-    }
-    if ( pDevice->uNumSQ3[RATE_5M] > ulMaxPacket ) {
-        ulPacketNum = pDevice->uDiversityCnt - pDevice->uNumSQ3[RATE_1M] -
-                      pDevice->uNumSQ3[RATE_2M];
-        ulRatio = (ulPacketNum * 1000 / pDevice->uDiversityCnt);
-        //ulRatio = (pDevice->uNumSQ3[RATE_5M] * 1000 / pDevice->uDiversityCnt);
-        ulRatio += TOP_RATE_55M;
-        ulMaxPacket = pDevice->uNumSQ3[RATE_5M];
-    }
-    if ( pDevice->uNumSQ3[RATE_2M] > ulMaxPacket ) {
-        ulPacketNum = pDevice->uDiversityCnt - pDevice->uNumSQ3[RATE_1M];
-        ulRatio = (ulPacketNum * 1000 / pDevice->uDiversityCnt);
-        //ulRatio = (pDevice->uNumSQ3[RATE_2M]  * 1000 / pDevice->uDiversityCnt);
-        ulRatio += TOP_RATE_2M;
-        ulMaxPacket = pDevice->uNumSQ3[RATE_2M];
-    }
-    if ( pDevice->uNumSQ3[RATE_1M] > ulMaxPacket ) {
-        ulPacketNum = pDevice->uDiversityCnt;
-        ulRatio = (ulPacketNum * 1000 / pDevice->uDiversityCnt);
-        //ulRatio = (pDevice->uNumSQ3[RATE_1M]  * 1000 / pDevice->uDiversityCnt);
-        ulRatio += TOP_RATE_1M;
-    }
-
-    return ulRatio;
+	unsigned long ulRatio = 0;
+	unsigned long ulMaxPacket;
+	unsigned long ulPacketNum;
+
+	//This is a thousand-ratio
+	ulMaxPacket = pDevice->uNumSQ3[RATE_54M];
+	if (pDevice->uNumSQ3[RATE_54M] != 0) {
+		ulPacketNum = pDevice->uNumSQ3[RATE_54M];
+		ulRatio = (ulPacketNum * 1000 / pDevice->uDiversityCnt);
+		//ulRatio = (pDevice->uNumSQ3[RATE_54M] * 1000 / pDevice->uDiversityCnt);
+		ulRatio += TOP_RATE_54M;
+	}
+	if (pDevice->uNumSQ3[RATE_48M] > ulMaxPacket) {
+		ulPacketNum = pDevice->uNumSQ3[RATE_54M] + pDevice->uNumSQ3[RATE_48M];
+		ulRatio = (ulPacketNum * 1000 / pDevice->uDiversityCnt);
+		//ulRatio = (pDevice->uNumSQ3[RATE_48M] * 1000 / pDevice->uDiversityCnt);
+		ulRatio += TOP_RATE_48M;
+		ulMaxPacket = pDevice->uNumSQ3[RATE_48M];
+	}
+	if (pDevice->uNumSQ3[RATE_36M] > ulMaxPacket) {
+		ulPacketNum = pDevice->uNumSQ3[RATE_54M] + pDevice->uNumSQ3[RATE_48M] +
+			pDevice->uNumSQ3[RATE_36M];
+		ulRatio = (ulPacketNum * 1000 / pDevice->uDiversityCnt);
+		//ulRatio = (pDevice->uNumSQ3[RATE_36M] * 1000 / pDevice->uDiversityCnt);
+		ulRatio += TOP_RATE_36M;
+		ulMaxPacket = pDevice->uNumSQ3[RATE_36M];
+	}
+	if (pDevice->uNumSQ3[RATE_24M] > ulMaxPacket) {
+		ulPacketNum = pDevice->uNumSQ3[RATE_54M] + pDevice->uNumSQ3[RATE_48M] +
+			pDevice->uNumSQ3[RATE_36M] + pDevice->uNumSQ3[RATE_24M];
+		ulRatio = (ulPacketNum * 1000 / pDevice->uDiversityCnt);
+		//ulRatio = (pDevice->uNumSQ3[RATE_24M] * 1000 / pDevice->uDiversityCnt);
+		ulRatio += TOP_RATE_24M;
+		ulMaxPacket = pDevice->uNumSQ3[RATE_24M];
+	}
+	if (pDevice->uNumSQ3[RATE_18M] > ulMaxPacket) {
+		ulPacketNum = pDevice->uNumSQ3[RATE_54M] + pDevice->uNumSQ3[RATE_48M] +
+			pDevice->uNumSQ3[RATE_36M] + pDevice->uNumSQ3[RATE_24M] +
+			pDevice->uNumSQ3[RATE_18M];
+		ulRatio = (ulPacketNum * 1000 / pDevice->uDiversityCnt);
+		//ulRatio = (pDevice->uNumSQ3[RATE_18M] * 1000 / pDevice->uDiversityCnt);
+		ulRatio += TOP_RATE_18M;
+		ulMaxPacket = pDevice->uNumSQ3[RATE_18M];
+	}
+	if (pDevice->uNumSQ3[RATE_12M] > ulMaxPacket) {
+		ulPacketNum = pDevice->uNumSQ3[RATE_54M] + pDevice->uNumSQ3[RATE_48M] +
+			pDevice->uNumSQ3[RATE_36M] + pDevice->uNumSQ3[RATE_24M] +
+			pDevice->uNumSQ3[RATE_18M] + pDevice->uNumSQ3[RATE_12M];
+		ulRatio = (ulPacketNum * 1000 / pDevice->uDiversityCnt);
+		//ulRatio = (pDevice->uNumSQ3[RATE_12M] * 1000 / pDevice->uDiversityCnt);
+		ulRatio += TOP_RATE_12M;
+		ulMaxPacket = pDevice->uNumSQ3[RATE_12M];
+	}
+	if (pDevice->uNumSQ3[RATE_11M] > ulMaxPacket) {
+		ulPacketNum = pDevice->uDiversityCnt - pDevice->uNumSQ3[RATE_1M] -
+			pDevice->uNumSQ3[RATE_2M] - pDevice->uNumSQ3[RATE_5M] -
+			pDevice->uNumSQ3[RATE_6M] - pDevice->uNumSQ3[RATE_9M];
+		ulRatio = (ulPacketNum * 1000 / pDevice->uDiversityCnt);
+		//ulRatio = (pDevice->uNumSQ3[RATE_11M] * 1000 / pDevice->uDiversityCnt);
+		ulRatio += TOP_RATE_11M;
+		ulMaxPacket = pDevice->uNumSQ3[RATE_11M];
+	}
+	if (pDevice->uNumSQ3[RATE_9M] > ulMaxPacket) {
+		ulPacketNum = pDevice->uDiversityCnt - pDevice->uNumSQ3[RATE_1M] -
+			pDevice->uNumSQ3[RATE_2M] - pDevice->uNumSQ3[RATE_5M] -
+			pDevice->uNumSQ3[RATE_6M];
+		ulRatio = (ulPacketNum * 1000 / pDevice->uDiversityCnt);
+		//ulRatio = (pDevice->uNumSQ3[RATE_9M] * 1000 / pDevice->uDiversityCnt);
+		ulRatio += TOP_RATE_9M;
+		ulMaxPacket = pDevice->uNumSQ3[RATE_9M];
+	}
+	if (pDevice->uNumSQ3[RATE_6M] > ulMaxPacket) {
+		ulPacketNum = pDevice->uDiversityCnt - pDevice->uNumSQ3[RATE_1M] -
+			pDevice->uNumSQ3[RATE_2M] - pDevice->uNumSQ3[RATE_5M];
+		ulRatio = (ulPacketNum * 1000 / pDevice->uDiversityCnt);
+		//ulRatio = (pDevice->uNumSQ3[RATE_6M] * 1000 / pDevice->uDiversityCnt);
+		ulRatio += TOP_RATE_6M;
+		ulMaxPacket = pDevice->uNumSQ3[RATE_6M];
+	}
+	if (pDevice->uNumSQ3[RATE_5M] > ulMaxPacket) {
+		ulPacketNum = pDevice->uDiversityCnt - pDevice->uNumSQ3[RATE_1M] -
+			pDevice->uNumSQ3[RATE_2M];
+		ulRatio = (ulPacketNum * 1000 / pDevice->uDiversityCnt);
+		//ulRatio = (pDevice->uNumSQ3[RATE_5M] * 1000 / pDevice->uDiversityCnt);
+		ulRatio += TOP_RATE_55M;
+		ulMaxPacket = pDevice->uNumSQ3[RATE_5M];
+	}
+	if (pDevice->uNumSQ3[RATE_2M] > ulMaxPacket) {
+		ulPacketNum = pDevice->uDiversityCnt - pDevice->uNumSQ3[RATE_1M];
+		ulRatio = (ulPacketNum * 1000 / pDevice->uDiversityCnt);
+		//ulRatio = (pDevice->uNumSQ3[RATE_2M]  * 1000 / pDevice->uDiversityCnt);
+		ulRatio += TOP_RATE_2M;
+		ulMaxPacket = pDevice->uNumSQ3[RATE_2M];
+	}
+	if (pDevice->uNumSQ3[RATE_1M] > ulMaxPacket) {
+		ulPacketNum = pDevice->uDiversityCnt;
+		ulRatio = (ulPacketNum * 1000 / pDevice->uDiversityCnt);
+		//ulRatio = (pDevice->uNumSQ3[RATE_1M]  * 1000 / pDevice->uDiversityCnt);
+		ulRatio += TOP_RATE_1M;
+	}
+
+	return ulRatio;
 }
 
-
 void
-BBvClearAntDivSQ3Value (PSDevice pDevice)
+BBvClearAntDivSQ3Value(PSDevice pDevice)
 {
-    unsigned int ii;
+	unsigned int ii;
 
-    pDevice->uDiversityCnt = 0;
-    for (ii = 0; ii < MAX_RATE; ii++) {
-        pDevice->uNumSQ3[ii] = 0;
-    }
+	pDevice->uDiversityCnt = 0;
+	for (ii = 0; ii < MAX_RATE; ii++) {
+		pDevice->uNumSQ3[ii] = 0;
+	}
 }
 
-
 /*
  * Description: Antenna Diversity
  *
@@ -2785,79 +2736,70 @@ BBvClearAntDivSQ3Value (PSDevice pDevice)
  */
 
 void
-BBvAntennaDiversity (PSDevice pDevice, unsigned char byRxRate, unsigned char bySQ3)
+BBvAntennaDiversity(PSDevice pDevice, unsigned char byRxRate, unsigned char bySQ3)
 {
+	if ((byRxRate >= MAX_RATE) || (pDevice->wAntDiversityMaxRate >= MAX_RATE)) {
+		return;
+	}
+	pDevice->uDiversityCnt++;
+	// DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pDevice->uDiversityCnt = %d\n", (int)pDevice->uDiversityCnt);
 
-    if ((byRxRate >= MAX_RATE) || (pDevice->wAntDiversityMaxRate >= MAX_RATE)) {
-        return;
-    }
-    pDevice->uDiversityCnt++;
-   // DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pDevice->uDiversityCnt = %d\n", (int)pDevice->uDiversityCnt);
-
-    pDevice->uNumSQ3[byRxRate]++;
+	pDevice->uNumSQ3[byRxRate]++;
 
-    if (pDevice->byAntennaState == 0) {
+	if (pDevice->byAntennaState == 0) {
+		if (pDevice->uDiversityCnt > pDevice->ulDiversityNValue) {
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ulDiversityNValue=[%d],54M-[%d]\n",
+				(int)pDevice->ulDiversityNValue, (int)pDevice->uNumSQ3[(int)pDevice->wAntDiversityMaxRate]);
 
-        if (pDevice->uDiversityCnt > pDevice->ulDiversityNValue) {
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ulDiversityNValue=[%d],54M-[%d]\n",
-                          (int)pDevice->ulDiversityNValue, (int)pDevice->uNumSQ3[(int)pDevice->wAntDiversityMaxRate]);
+			if (pDevice->uNumSQ3[pDevice->wAntDiversityMaxRate] < pDevice->uDiversityCnt/2) {
+				pDevice->ulRatio_State0 = s_ulGetRatio(pDevice);
+				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "SQ3_State0, rate = [%08x]\n", (int)pDevice->ulRatio_State0);
 
-            if (pDevice->uNumSQ3[pDevice->wAntDiversityMaxRate] < pDevice->uDiversityCnt/2) {
+				if (pDevice->byTMax == 0)
+					return;
+				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "1.[%08x], uNumSQ3[%d]=%d, %d\n",
+					(int)pDevice->ulRatio_State0, (int)pDevice->wAntDiversityMaxRate,
+					(int)pDevice->uNumSQ3[(int)pDevice->wAntDiversityMaxRate], (int)pDevice->uDiversityCnt);
 
-                pDevice->ulRatio_State0 = s_ulGetRatio(pDevice);
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"SQ3_State0, rate = [%08x]\n", (int)pDevice->ulRatio_State0);
+				s_vChangeAntenna(pDevice);
+				pDevice->byAntennaState = 1;
+				del_timer(&pDevice->TimerSQ3Tmax3);
+				del_timer(&pDevice->TimerSQ3Tmax2);
+				pDevice->TimerSQ3Tmax1.expires =  RUN_AT(pDevice->byTMax * HZ);
+				add_timer(&pDevice->TimerSQ3Tmax1);
+
+			} else {
+				pDevice->TimerSQ3Tmax3.expires =  RUN_AT(pDevice->byTMax3 * HZ);
+				add_timer(&pDevice->TimerSQ3Tmax3);
+			}
+			BBvClearAntDivSQ3Value(pDevice);
+
+		}
+	} else { //byAntennaState == 1
+
+		if (pDevice->uDiversityCnt > pDevice->ulDiversityMValue) {
+			del_timer(&pDevice->TimerSQ3Tmax1);
+
+			pDevice->ulRatio_State1 = s_ulGetRatio(pDevice);
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "RX:SQ3_State1, rate0 = %08x,rate1 = %08x\n",
+				(int)pDevice->ulRatio_State0, (int)pDevice->ulRatio_State1);
+
+			if (pDevice->ulRatio_State1 < pDevice->ulRatio_State0) {
+				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "2.[%08x][%08x], uNumSQ3[%d]=%d, %d\n",
+					(int)pDevice->ulRatio_State0, (int)pDevice->ulRatio_State1,
+					(int)pDevice->wAntDiversityMaxRate,
+					(int)pDevice->uNumSQ3[(int)pDevice->wAntDiversityMaxRate], (int)pDevice->uDiversityCnt);
 
-                if ( pDevice->byTMax == 0 )
-                    return;
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"1.[%08x], uNumSQ3[%d]=%d, %d\n",
-                              (int)pDevice->ulRatio_State0, (int)pDevice->wAntDiversityMaxRate,
-                              (int)pDevice->uNumSQ3[(int)pDevice->wAntDiversityMaxRate], (int)pDevice->uDiversityCnt);
-#ifdef	PLICE_DEBUG
-		//printk("BBvAntennaDiversity1:call s_vChangeAntenna\n");
-#endif
-		s_vChangeAntenna(pDevice);
-                pDevice->byAntennaState = 1;
-                del_timer(&pDevice->TimerSQ3Tmax3);
-                del_timer(&pDevice->TimerSQ3Tmax2);
-                pDevice->TimerSQ3Tmax1.expires =  RUN_AT(pDevice->byTMax * HZ);
-                add_timer(&pDevice->TimerSQ3Tmax1);
-
-            } else {
-
-                pDevice->TimerSQ3Tmax3.expires =  RUN_AT(pDevice->byTMax3 * HZ);
-                add_timer(&pDevice->TimerSQ3Tmax3);
-            }
-            BBvClearAntDivSQ3Value(pDevice);
-
-        }
-    } else { //byAntennaState == 1
-
-        if (pDevice->uDiversityCnt > pDevice->ulDiversityMValue) {
-
-            del_timer(&pDevice->TimerSQ3Tmax1);
-
-            pDevice->ulRatio_State1 = s_ulGetRatio(pDevice);
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"RX:SQ3_State1, rate0 = %08x,rate1 = %08x\n",
-                          (int)pDevice->ulRatio_State0,(int)pDevice->ulRatio_State1);
-
-            if (pDevice->ulRatio_State1 < pDevice->ulRatio_State0) {
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"2.[%08x][%08x], uNumSQ3[%d]=%d, %d\n",
-                              (int)pDevice->ulRatio_State0, (int)pDevice->ulRatio_State1,
-                              (int)pDevice->wAntDiversityMaxRate,
-                              (int)pDevice->uNumSQ3[(int)pDevice->wAntDiversityMaxRate], (int)pDevice->uDiversityCnt);
-#ifdef	PLICE_DEBUG
-		//printk("BBvAntennaDiversity2:call s_vChangeAntenna\n");
-#endif
 				s_vChangeAntenna(pDevice);
-                pDevice->TimerSQ3Tmax3.expires =  RUN_AT(pDevice->byTMax3 * HZ);
-                pDevice->TimerSQ3Tmax2.expires =  RUN_AT(pDevice->byTMax2 * HZ);
-                add_timer(&pDevice->TimerSQ3Tmax3);
-                add_timer(&pDevice->TimerSQ3Tmax2);
-            }
-            pDevice->byAntennaState = 0;
-            BBvClearAntDivSQ3Value(pDevice);
-        }
-    } //byAntennaState
+				pDevice->TimerSQ3Tmax3.expires =  RUN_AT(pDevice->byTMax3 * HZ);
+				pDevice->TimerSQ3Tmax2.expires =  RUN_AT(pDevice->byTMax2 * HZ);
+				add_timer(&pDevice->TimerSQ3Tmax3);
+				add_timer(&pDevice->TimerSQ3Tmax2);
+			}
+			pDevice->byAntennaState = 0;
+			BBvClearAntDivSQ3Value(pDevice);
+		}
+	} //byAntennaState
 }
 
 /*+
@@ -2872,38 +2814,33 @@ BBvAntennaDiversity (PSDevice pDevice, unsigned char byRxRate, unsigned char byS
  *
  * Return Value: none
  *
--*/
+ -*/
 
 void
-TimerSQ3CallBack (
-    void *hDeviceContext
-    )
+TimerSQ3CallBack(
+	void *hDeviceContext
+)
 {
-    PSDevice        pDevice = (PSDevice)hDeviceContext;
+	PSDevice        pDevice = (PSDevice)hDeviceContext;
 
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"TimerSQ3CallBack...");
-    spin_lock_irq(&pDevice->lock);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "TimerSQ3CallBack...");
+	spin_lock_irq(&pDevice->lock);
 
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"3.[%08x][%08x], %d\n",(int)pDevice->ulRatio_State0, (int)pDevice->ulRatio_State1, (int)pDevice->uDiversityCnt);
-#ifdef	PLICE_DEBUG
-		//printk("TimerSQ3CallBack1:call s_vChangeAntenna\n");
-#endif
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "3.[%08x][%08x], %d\n", (int)pDevice->ulRatio_State0, (int)pDevice->ulRatio_State1, (int)pDevice->uDiversityCnt);
 
-    s_vChangeAntenna(pDevice);
-    pDevice->byAntennaState = 0;
-    BBvClearAntDivSQ3Value(pDevice);
+	s_vChangeAntenna(pDevice);
+	pDevice->byAntennaState = 0;
+	BBvClearAntDivSQ3Value(pDevice);
 
-    pDevice->TimerSQ3Tmax3.expires =  RUN_AT(pDevice->byTMax3 * HZ);
-    pDevice->TimerSQ3Tmax2.expires =  RUN_AT(pDevice->byTMax2 * HZ);
-    add_timer(&pDevice->TimerSQ3Tmax3);
-    add_timer(&pDevice->TimerSQ3Tmax2);
+	pDevice->TimerSQ3Tmax3.expires =  RUN_AT(pDevice->byTMax3 * HZ);
+	pDevice->TimerSQ3Tmax2.expires =  RUN_AT(pDevice->byTMax2 * HZ);
+	add_timer(&pDevice->TimerSQ3Tmax3);
+	add_timer(&pDevice->TimerSQ3Tmax2);
 
-
-    spin_unlock_irq(&pDevice->lock);
-    return;
+	spin_unlock_irq(&pDevice->lock);
+	return;
 }
 
-
 /*+
  *
  * Description:
@@ -2920,54 +2857,46 @@ TimerSQ3CallBack (
  *
  * Return Value: none
  *
--*/
+ -*/
 
 void
-TimerState1CallBack (
-    void *hDeviceContext
-    )
+TimerState1CallBack(
+	void *hDeviceContext
+)
 {
-    PSDevice        pDevice = (PSDevice)hDeviceContext;
+	PSDevice        pDevice = (PSDevice)hDeviceContext;
 
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"TimerState1CallBack...");
-
-    spin_lock_irq(&pDevice->lock);
-    if (pDevice->uDiversityCnt < pDevice->ulDiversityMValue/100) {
-#ifdef	PLICE_DEBUG
-		//printk("TimerSQ3CallBack2:call s_vChangeAntenna\n");
-#endif
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "TimerState1CallBack...");
 
+	spin_lock_irq(&pDevice->lock);
+	if (pDevice->uDiversityCnt < pDevice->ulDiversityMValue/100) {
 		s_vChangeAntenna(pDevice);
-        pDevice->TimerSQ3Tmax3.expires =  RUN_AT(pDevice->byTMax3 * HZ);
-        pDevice->TimerSQ3Tmax2.expires =  RUN_AT(pDevice->byTMax2 * HZ);
-        add_timer(&pDevice->TimerSQ3Tmax3);
-        add_timer(&pDevice->TimerSQ3Tmax2);
-    } else {
-        pDevice->ulRatio_State1 = s_ulGetRatio(pDevice);
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"SQ3_State1, rate0 = %08x,rate1 = %08x\n",
-                      (int)pDevice->ulRatio_State0,(int)pDevice->ulRatio_State1);
-
-        if ( pDevice->ulRatio_State1 < pDevice->ulRatio_State0 ) {
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"2.[%08x][%08x], uNumSQ3[%d]=%d, %d\n",
-                          (int)pDevice->ulRatio_State0, (int)pDevice->ulRatio_State1,
-                          (int)pDevice->wAntDiversityMaxRate,
-                          (int)pDevice->uNumSQ3[(int)pDevice->wAntDiversityMaxRate], (int)pDevice->uDiversityCnt);
-#ifdef	PLICE_DEBUG
-		//printk("TimerSQ3CallBack3:call s_vChangeAntenna\n");
-#endif
+		pDevice->TimerSQ3Tmax3.expires =  RUN_AT(pDevice->byTMax3 * HZ);
+		pDevice->TimerSQ3Tmax2.expires =  RUN_AT(pDevice->byTMax2 * HZ);
+		add_timer(&pDevice->TimerSQ3Tmax3);
+		add_timer(&pDevice->TimerSQ3Tmax2);
+	} else {
+		pDevice->ulRatio_State1 = s_ulGetRatio(pDevice);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "SQ3_State1, rate0 = %08x,rate1 = %08x\n",
+			(int)pDevice->ulRatio_State0, (int)pDevice->ulRatio_State1);
+
+		if (pDevice->ulRatio_State1 < pDevice->ulRatio_State0) {
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "2.[%08x][%08x], uNumSQ3[%d]=%d, %d\n",
+				(int)pDevice->ulRatio_State0, (int)pDevice->ulRatio_State1,
+				(int)pDevice->wAntDiversityMaxRate,
+				(int)pDevice->uNumSQ3[(int)pDevice->wAntDiversityMaxRate], (int)pDevice->uDiversityCnt);
 
 			s_vChangeAntenna(pDevice);
 
-            pDevice->TimerSQ3Tmax3.expires =  RUN_AT(pDevice->byTMax3 * HZ);
-            pDevice->TimerSQ3Tmax2.expires =  RUN_AT(pDevice->byTMax2 * HZ);
-            add_timer(&pDevice->TimerSQ3Tmax3);
-            add_timer(&pDevice->TimerSQ3Tmax2);
-        }
-    }
-    pDevice->byAntennaState = 0;
-    BBvClearAntDivSQ3Value(pDevice);
-    spin_unlock_irq(&pDevice->lock);
-
-    return;
+			pDevice->TimerSQ3Tmax3.expires =  RUN_AT(pDevice->byTMax3 * HZ);
+			pDevice->TimerSQ3Tmax2.expires =  RUN_AT(pDevice->byTMax2 * HZ);
+			add_timer(&pDevice->TimerSQ3Tmax3);
+			add_timer(&pDevice->TimerSQ3Tmax2);
+		}
+	}
+	pDevice->byAntennaState = 0;
+	BBvClearAntDivSQ3Value(pDevice);
+	spin_unlock_irq(&pDevice->lock);
+
+	return;
 }
-
diff --git a/drivers/staging/vt6655/baseband.h b/drivers/staging/vt6655/baseband.h
index 9b5bc9c..e31bb76 100644
--- a/drivers/staging/vt6655/baseband.h
+++ b/drivers/staging/vt6655/baseband.h
@@ -41,7 +41,6 @@
 //
 #define BB_MAX_CONTEXT_SIZE 256
 
-
 //
 // Baseband RF pair definition in eeprom (Bits 6..0)
 //
@@ -49,7 +48,6 @@
 #define PREAMBLE_LONG   0
 #define PREAMBLE_SHORT  1
 
-
 #define F5G             0
 #define F2_4G           1
 
@@ -66,21 +64,15 @@
 #define TOP_RATE_2M         0x00200000
 #define TOP_RATE_1M         0x00100000
 
-
 /*---------------------  Export Types  ------------------------------*/
 
 /*---------------------  Export Macros ------------------------------*/
 
-#define BBvClearFOE(dwIoBase)                               \
-{                                                           \
-    BBbWriteEmbedded(dwIoBase, 0xB1, 0);                     \
-}
-
-#define BBvSetFOE(dwIoBase)                                 \
-{                                                           \
-    BBbWriteEmbedded(dwIoBase, 0xB1, 0x0C);                  \
-}
+#define BBvClearFOE(dwIoBase)				\
+	BBbWriteEmbedded(dwIoBase, 0xB1, 0)
 
+#define BBvSetFOE(dwIoBase)				\
+	BBbWriteEmbedded(dwIoBase, 0xB1, 0x0C)
 
 /*---------------------  Export Classes  ----------------------------*/
 
@@ -90,22 +82,22 @@
 
 unsigned int
 BBuGetFrameTime(
-    unsigned char byPreambleType,
-    unsigned char byPktType,
-    unsigned int cbFrameLength,
-    unsigned short wRate
-    );
+	unsigned char byPreambleType,
+	unsigned char byPktType,
+	unsigned int cbFrameLength,
+	unsigned short wRate
+);
 
 void
-BBvCalculateParameter (
-    PSDevice pDevice,
-    unsigned int cbFrameLength,
-    unsigned short wRate,
-    unsigned char byPacketType,
-    unsigned short *pwPhyLen,
-    unsigned char *pbyPhySrv,
-    unsigned char *pbyPhySgn
-    );
+BBvCalculateParameter(
+	PSDevice pDevice,
+	unsigned int cbFrameLength,
+	unsigned short wRate,
+	unsigned char byPacketType,
+	unsigned short *pwPhyLen,
+	unsigned char *pbyPhySrv,
+	unsigned char *pbyPhySgn
+);
 
 bool BBbReadEmbedded(unsigned long dwIoBase, unsigned char byBBAddr, unsigned char *pbyData);
 bool BBbWriteEmbedded(unsigned long dwIoBase, unsigned char byBBAddr, unsigned char byData);
@@ -131,17 +123,17 @@ void BBvExitDeepSleep(unsigned long dwIoBase, unsigned char byLocalID);
 // timer for antenna diversity
 
 void
-TimerSQ3CallBack (
-    void *hDeviceContext
-    );
+TimerSQ3CallBack(
+	void *hDeviceContext
+);
 
 void
 TimerState1CallBack(
-    void *hDeviceContext
-    );
+	void *hDeviceContext
+);
 
 void BBvAntennaDiversity(PSDevice pDevice, unsigned char byRxRate, unsigned char bySQ3);
 void
-BBvClearAntDivSQ3Value (PSDevice pDevice);
+BBvClearAntDivSQ3Value(PSDevice pDevice);
 
 #endif // __BASEBAND_H__
diff --git a/drivers/staging/vt6655/bssdb.c b/drivers/staging/vt6655/bssdb.c
index fe57fb8..f983915 100644
--- a/drivers/staging/vt6655/bssdb.c
+++ b/drivers/staging/vt6655/bssdb.c
@@ -60,59 +60,46 @@
 
 /*---------------------  Static Definitions -------------------------*/
 
-
-
-
 /*---------------------  Static Classes  ----------------------------*/
 
 /*---------------------  Static Variables  --------------------------*/
-static int          msglevel                =MSG_LEVEL_INFO;
+static int msglevel = MSG_LEVEL_INFO;
 //static int          msglevel                =MSG_LEVEL_DEBUG;
 
-
-
 const unsigned short awHWRetry0[5][5] = {
-                                            {RATE_18M, RATE_18M, RATE_12M, RATE_12M, RATE_12M},
-                                            {RATE_24M, RATE_24M, RATE_18M, RATE_12M, RATE_12M},
-                                            {RATE_36M, RATE_36M, RATE_24M, RATE_18M, RATE_18M},
-                                            {RATE_48M, RATE_48M, RATE_36M, RATE_24M, RATE_24M},
-                                            {RATE_54M, RATE_54M, RATE_48M, RATE_36M, RATE_36M}
-                                           };
+	{RATE_18M, RATE_18M, RATE_12M, RATE_12M, RATE_12M},
+	{RATE_24M, RATE_24M, RATE_18M, RATE_12M, RATE_12M},
+	{RATE_36M, RATE_36M, RATE_24M, RATE_18M, RATE_18M},
+	{RATE_48M, RATE_48M, RATE_36M, RATE_24M, RATE_24M},
+	{RATE_54M, RATE_54M, RATE_48M, RATE_36M, RATE_36M}
+};
 const unsigned short awHWRetry1[5][5] = {
-                                            {RATE_18M, RATE_18M, RATE_12M, RATE_6M, RATE_6M},
-                                            {RATE_24M, RATE_24M, RATE_18M, RATE_6M, RATE_6M},
-                                            {RATE_36M, RATE_36M, RATE_24M, RATE_12M, RATE_12M},
-                                            {RATE_48M, RATE_48M, RATE_24M, RATE_12M, RATE_12M},
-                                            {RATE_54M, RATE_54M, RATE_36M, RATE_18M, RATE_18M}
-                                           };
-
-
+	{RATE_18M, RATE_18M, RATE_12M, RATE_6M, RATE_6M},
+	{RATE_24M, RATE_24M, RATE_18M, RATE_6M, RATE_6M},
+	{RATE_36M, RATE_36M, RATE_24M, RATE_12M, RATE_12M},
+	{RATE_48M, RATE_48M, RATE_24M, RATE_12M, RATE_12M},
+	{RATE_54M, RATE_54M, RATE_36M, RATE_18M, RATE_18M}
+};
 
 /*---------------------  Static Functions  --------------------------*/
 
 void s_vCheckSensitivity(
-    void *hDeviceContext
-    );
+	void *hDeviceContext
+);
 
 #ifdef Calcu_LinkQual
 void s_uCalculateLinkQual(
-    void *hDeviceContext
-    );
+	void *hDeviceContext
+);
 #endif
 
-
 void s_vCheckPreEDThreshold(
-    void *hDeviceContext
-    );
+	void *hDeviceContext
+);
 /*---------------------  Export Variables  --------------------------*/
 
-
 /*---------------------  Export Functions  --------------------------*/
 
-
-
-
-
 /*+
  *
  * Routine Description:
@@ -121,153 +108,150 @@ void s_vCheckPreEDThreshold(
  * Return Value:
  *    PTR to KnownBSS or NULL
  *
--*/
+ -*/
 
 PKnownBSS
 BSSpSearchBSSList(
-    void *hDeviceContext,
-    unsigned char *pbyDesireBSSID,
-    unsigned char *pbyDesireSSID,
-    CARD_PHY_TYPE  ePhyType
-    )
+	void *hDeviceContext,
+	unsigned char *pbyDesireBSSID,
+	unsigned char *pbyDesireSSID,
+	CARD_PHY_TYPE  ePhyType
+)
 {
-    PSDevice        pDevice = (PSDevice)hDeviceContext;
-    PSMgmtObject    pMgmt = pDevice->pMgmt;
-    unsigned char *pbyBSSID = NULL;
-    PWLAN_IE_SSID   pSSID = NULL;
-    PKnownBSS       pCurrBSS = NULL;
-    PKnownBSS       pSelect = NULL;
-    unsigned char ZeroBSSID[WLAN_BSSID_LEN]={0x00,0x00,0x00,0x00,0x00,0x00};
-    unsigned int ii = 0;
-
-    if (pbyDesireBSSID != NULL) {
+	PSDevice        pDevice = (PSDevice)hDeviceContext;
+	PSMgmtObject    pMgmt = pDevice->pMgmt;
+	unsigned char *pbyBSSID = NULL;
+	PWLAN_IE_SSID   pSSID = NULL;
+	PKnownBSS       pCurrBSS = NULL;
+	PKnownBSS       pSelect = NULL;
+	unsigned char ZeroBSSID[WLAN_BSSID_LEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+	unsigned int ii = 0;
+
+	if (pbyDesireBSSID != NULL) {
 		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
 			"BSSpSearchBSSList BSSID[%pM]\n", pbyDesireBSSID);
-        if ((!is_broadcast_ether_addr(pbyDesireBSSID)) &&
-	     (memcmp(pbyDesireBSSID, ZeroBSSID, 6)!= 0)){
-            pbyBSSID = pbyDesireBSSID;
-        }
-    }
-    if (pbyDesireSSID != NULL) {
-        if (((PWLAN_IE_SSID)pbyDesireSSID)->len != 0) {
-            pSSID = (PWLAN_IE_SSID) pbyDesireSSID;
-        }
-    }
-
-    if (pbyBSSID != NULL) {
-        // match BSSID first
-        for (ii = 0; ii <MAX_BSS_NUM; ii++) {
-            pCurrBSS = &(pMgmt->sBSSList[ii]);
-if(pDevice->bLinkPass==false) pCurrBSS->bSelected = false;
-            if ((pCurrBSS->bActive) &&
-                (pCurrBSS->bSelected == false)) {
-                if (!compare_ether_addr(pCurrBSS->abyBSSID, pbyBSSID)) {
-                    if (pSSID != NULL) {
-                        // compare ssid
-                        if ( !memcmp(pSSID->abySSID,
-                            ((PWLAN_IE_SSID)pCurrBSS->abySSID)->abySSID,
-                            pSSID->len)) {
-                            if ((pMgmt->eConfigMode == WMAC_CONFIG_AUTO) ||
-                                ((pMgmt->eConfigMode == WMAC_CONFIG_IBSS_STA) && WLAN_GET_CAP_INFO_IBSS(pCurrBSS->wCapInfo)) ||
-                                ((pMgmt->eConfigMode == WMAC_CONFIG_ESS_STA) && WLAN_GET_CAP_INFO_ESS(pCurrBSS->wCapInfo))
-                                ) {
-                                pCurrBSS->bSelected = true;
-                                return(pCurrBSS);
-                            }
-                        }
-                    } else {
-                        if ((pMgmt->eConfigMode == WMAC_CONFIG_AUTO) ||
-                            ((pMgmt->eConfigMode == WMAC_CONFIG_IBSS_STA) && WLAN_GET_CAP_INFO_IBSS(pCurrBSS->wCapInfo)) ||
-                            ((pMgmt->eConfigMode == WMAC_CONFIG_ESS_STA) && WLAN_GET_CAP_INFO_ESS(pCurrBSS->wCapInfo))
-                            ) {
-                            pCurrBSS->bSelected = true;
-                            return(pCurrBSS);
-                        }
-                    }
-                }
-            }
-        }
-    } else {
-        // ignore BSSID
-        for (ii = 0; ii <MAX_BSS_NUM; ii++) {
-            pCurrBSS = &(pMgmt->sBSSList[ii]);
-	//2007-0721-01<Add>by MikeLiu
-	  pCurrBSS->bSelected = false;
-          if (pCurrBSS->bActive) {
-
-                if (pSSID != NULL) {
-                    // matched SSID
-                    if (! !memcmp(pSSID->abySSID,
-                        ((PWLAN_IE_SSID)pCurrBSS->abySSID)->abySSID,
-                        pSSID->len) ||
-                        (pSSID->len != ((PWLAN_IE_SSID)pCurrBSS->abySSID)->len)) {
-                        // SSID not match skip this BSS
-                        continue;
-                      }
-                }
-                if (((pMgmt->eConfigMode == WMAC_CONFIG_IBSS_STA) && WLAN_GET_CAP_INFO_ESS(pCurrBSS->wCapInfo)) ||
-                    ((pMgmt->eConfigMode == WMAC_CONFIG_ESS_STA) && WLAN_GET_CAP_INFO_IBSS(pCurrBSS->wCapInfo))
-                    ){
-                    // Type not match skip this BSS
-                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"BSS type mismatch.... Config[%d] BSS[0x%04x]\n", pMgmt->eConfigMode, pCurrBSS->wCapInfo);
-                    continue;
-                }
-
-                if (ePhyType != PHY_TYPE_AUTO) {
-                    if (((ePhyType == PHY_TYPE_11A) && (PHY_TYPE_11A != pCurrBSS->eNetworkTypeInUse)) ||
-                        ((ePhyType != PHY_TYPE_11A) && (PHY_TYPE_11A == pCurrBSS->eNetworkTypeInUse))) {
-                        // PhyType not match skip this BSS
-                        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Physical type mismatch.... ePhyType[%d] BSS[%d]\n", ePhyType, pCurrBSS->eNetworkTypeInUse);
-                        continue;
-                    }
-                }
+		if ((!is_broadcast_ether_addr(pbyDesireBSSID)) &&
+		    (memcmp(pbyDesireBSSID, ZeroBSSID, 6) != 0)) {
+			pbyBSSID = pbyDesireBSSID;
+		}
+	}
+	if (pbyDesireSSID != NULL) {
+		if (((PWLAN_IE_SSID)pbyDesireSSID)->len != 0) {
+			pSSID = (PWLAN_IE_SSID) pbyDesireSSID;
+		}
+	}
+
+	if (pbyBSSID != NULL) {
+		// match BSSID first
+		for (ii = 0; ii < MAX_BSS_NUM; ii++) {
+			pCurrBSS = &(pMgmt->sBSSList[ii]);
+			if (pDevice->bLinkPass == false) pCurrBSS->bSelected = false;
+			if ((pCurrBSS->bActive) &&
+			    (pCurrBSS->bSelected == false)) {
+				if (!compare_ether_addr(pCurrBSS->abyBSSID, pbyBSSID)) {
+					if (pSSID != NULL) {
+						// compare ssid
+						if (!memcmp(pSSID->abySSID,
+							    ((PWLAN_IE_SSID)pCurrBSS->abySSID)->abySSID,
+							    pSSID->len)) {
+							if ((pMgmt->eConfigMode == WMAC_CONFIG_AUTO) ||
+							    ((pMgmt->eConfigMode == WMAC_CONFIG_IBSS_STA) && WLAN_GET_CAP_INFO_IBSS(pCurrBSS->wCapInfo)) ||
+							    ((pMgmt->eConfigMode == WMAC_CONFIG_ESS_STA) && WLAN_GET_CAP_INFO_ESS(pCurrBSS->wCapInfo))
+) {
+								pCurrBSS->bSelected = true;
+								return pCurrBSS;
+							}
+						}
+					} else {
+						if ((pMgmt->eConfigMode == WMAC_CONFIG_AUTO) ||
+						    ((pMgmt->eConfigMode == WMAC_CONFIG_IBSS_STA) && WLAN_GET_CAP_INFO_IBSS(pCurrBSS->wCapInfo)) ||
+						    ((pMgmt->eConfigMode == WMAC_CONFIG_ESS_STA) && WLAN_GET_CAP_INFO_ESS(pCurrBSS->wCapInfo))
+) {
+							pCurrBSS->bSelected = true;
+							return pCurrBSS;
+						}
+					}
+				}
+			}
+		}
+	} else {
+		// ignore BSSID
+		for (ii = 0; ii < MAX_BSS_NUM; ii++) {
+			pCurrBSS = &(pMgmt->sBSSList[ii]);
+			//2007-0721-01<Add>by MikeLiu
+			pCurrBSS->bSelected = false;
+			if (pCurrBSS->bActive) {
+				if (pSSID != NULL) {
+					// matched SSID
+					if (!!memcmp(pSSID->abySSID,
+						     ((PWLAN_IE_SSID)pCurrBSS->abySSID)->abySSID,
+						     pSSID->len) ||
+					    (pSSID->len != ((PWLAN_IE_SSID)pCurrBSS->abySSID)->len)) {
+						// SSID not match skip this BSS
+						continue;
+					}
+				}
+				if (((pMgmt->eConfigMode == WMAC_CONFIG_IBSS_STA) && WLAN_GET_CAP_INFO_ESS(pCurrBSS->wCapInfo)) ||
+				    ((pMgmt->eConfigMode == WMAC_CONFIG_ESS_STA) && WLAN_GET_CAP_INFO_IBSS(pCurrBSS->wCapInfo))
+) {
+					// Type not match skip this BSS
+					DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "BSS type mismatch.... Config[%d] BSS[0x%04x]\n", pMgmt->eConfigMode, pCurrBSS->wCapInfo);
+					continue;
+				}
+
+				if (ePhyType != PHY_TYPE_AUTO) {
+					if (((ePhyType == PHY_TYPE_11A) && (PHY_TYPE_11A != pCurrBSS->eNetworkTypeInUse)) ||
+					    ((ePhyType != PHY_TYPE_11A) && (PHY_TYPE_11A == pCurrBSS->eNetworkTypeInUse))) {
+						// PhyType not match skip this BSS
+						DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Physical type mismatch.... ePhyType[%d] BSS[%d]\n", ePhyType, pCurrBSS->eNetworkTypeInUse);
+						continue;
+					}
+				}
 /*
-                if (pMgmt->eAuthenMode < WMAC_AUTH_WPA) {
-                    if (pCurrBSS->bWPAValid == true) {
-                        // WPA AP will reject connection of station without WPA enable.
-                        continue;
-                    }
-                } else if ((pMgmt->eAuthenMode == WMAC_AUTH_WPA) ||
-                           (pMgmt->eAuthenMode == WMAC_AUTH_WPAPSK)) {
-                    if (pCurrBSS->bWPAValid == false) {
-                        // station with WPA enable can't join NonWPA AP.
-                        continue;
-                    }
-                } else if ((pMgmt->eAuthenMode == WMAC_AUTH_WPA2) ||
-                           (pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK)) {
-                    if (pCurrBSS->bWPA2Valid == false) {
-                        // station with WPA2 enable can't join NonWPA2 AP.
-                        continue;
-                    }
-                }
+  if (pMgmt->eAuthenMode < WMAC_AUTH_WPA) {
+  if (pCurrBSS->bWPAValid == true) {
+  // WPA AP will reject connection of station without WPA enable.
+  continue;
+  }
+  } else if ((pMgmt->eAuthenMode == WMAC_AUTH_WPA) ||
+  (pMgmt->eAuthenMode == WMAC_AUTH_WPAPSK)) {
+  if (pCurrBSS->bWPAValid == false) {
+  // station with WPA enable can't join NonWPA AP.
+  continue;
+  }
+  } else if ((pMgmt->eAuthenMode == WMAC_AUTH_WPA2) ||
+  (pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK)) {
+  if (pCurrBSS->bWPA2Valid == false) {
+  // station with WPA2 enable can't join NonWPA2 AP.
+  continue;
+  }
+  }
 */
-                if (pSelect == NULL) {
-                    pSelect = pCurrBSS;
-                } else {
-                    // compare RSSI, select signal strong one
-                    if (pCurrBSS->uRSSI < pSelect->uRSSI) {
-                        pSelect = pCurrBSS;
-                    }
-                }
-            }
-        }
-        if (pSelect != NULL) {
-            pSelect->bSelected = true;
+				if (pSelect == NULL) {
+					pSelect = pCurrBSS;
+				} else {
+					// compare RSSI, select signal strong one
+					if (pCurrBSS->uRSSI < pSelect->uRSSI) {
+						pSelect = pCurrBSS;
+					}
+				}
+			}
+		}
+		if (pSelect != NULL) {
+			pSelect->bSelected = true;
 /*
-                        if (pDevice->bRoaming == false)  {
-	//       Einsn Add @20070907
-			memset(pbyDesireSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
-			memcpy(pbyDesireSSID,pCurrBSS->abySSID,WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1) ;
-                                                }*/
-
-            return(pSelect);
-        }
-    }
-    return(NULL);
+  if (pDevice->bRoaming == false)  {
+  //       Einsn Add @20070907
+  memset(pbyDesireSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
+  memcpy(pbyDesireSSID,pCurrBSS->abySSID,WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
+  }*/
 
+			return pSelect;
+		}
+	}
+	return NULL;
 }
 
-
 /*+
  *
  * Routine Description:
@@ -276,42 +260,39 @@ if(pDevice->bLinkPass==false) pCurrBSS->bSelected = false;
  * Return Value:
  *    None.
  *
--*/
-
+ -*/
 
 void
 BSSvClearBSSList(
-    void *hDeviceContext,
-    bool bKeepCurrBSSID
-    )
+	void *hDeviceContext,
+	bool bKeepCurrBSSID
+)
 {
-    PSDevice     pDevice = (PSDevice)hDeviceContext;
-    PSMgmtObject    pMgmt = pDevice->pMgmt;
-    unsigned int ii;
-
-    for (ii = 0; ii < MAX_BSS_NUM; ii++) {
-        if (bKeepCurrBSSID) {
-            if (pMgmt->sBSSList[ii].bActive &&
-                !compare_ether_addr(pMgmt->sBSSList[ii].abyBSSID, pMgmt->abyCurrBSSID)) {
-               // bKeepCurrBSSID = false;
-                continue;
-            }
-        }
-
-        if ((pMgmt->sBSSList[ii].bActive) && (pMgmt->sBSSList[ii].uClearCount < BSS_CLEAR_COUNT)) {
-             pMgmt->sBSSList[ii].uClearCount ++;
-             continue;
-        }
-
-        pMgmt->sBSSList[ii].bActive = false;
-        memset(&pMgmt->sBSSList[ii], 0, sizeof(KnownBSS));
-    }
-    BSSvClearAnyBSSJoinRecord(pDevice);
-
-    return;
-}
+	PSDevice     pDevice = (PSDevice)hDeviceContext;
+	PSMgmtObject    pMgmt = pDevice->pMgmt;
+	unsigned int ii;
+
+	for (ii = 0; ii < MAX_BSS_NUM; ii++) {
+		if (bKeepCurrBSSID) {
+			if (pMgmt->sBSSList[ii].bActive &&
+			    !compare_ether_addr(pMgmt->sBSSList[ii].abyBSSID, pMgmt->abyCurrBSSID)) {
+				// bKeepCurrBSSID = false;
+				continue;
+			}
+		}
 
+		if ((pMgmt->sBSSList[ii].bActive) && (pMgmt->sBSSList[ii].uClearCount < BSS_CLEAR_COUNT)) {
+			pMgmt->sBSSList[ii].uClearCount++;
+			continue;
+		}
 
+		pMgmt->sBSSList[ii].bActive = false;
+		memset(&pMgmt->sBSSList[ii], 0, sizeof(KnownBSS));
+	}
+	BSSvClearAnyBSSJoinRecord(pDevice);
+
+	return;
+}
 
 /*+
  *
@@ -321,39 +302,35 @@ BSSvClearBSSList(
  * Return Value:
  *    true if found.
  *
--*/
+ -*/
 PKnownBSS
 BSSpAddrIsInBSSList(
-    void *hDeviceContext,
-    unsigned char *abyBSSID,
-    PWLAN_IE_SSID pSSID
-    )
+	void *hDeviceContext,
+	unsigned char *abyBSSID,
+	PWLAN_IE_SSID pSSID
+)
 {
-    PSDevice     pDevice = (PSDevice)hDeviceContext;
-    PSMgmtObject    pMgmt = pDevice->pMgmt;
-    PKnownBSS       pBSSList = NULL;
-    unsigned int ii;
-
-    for (ii = 0; ii < MAX_BSS_NUM; ii++) {
-        pBSSList = &(pMgmt->sBSSList[ii]);
-        if (pBSSList->bActive) {
-            if (!compare_ether_addr(pBSSList->abyBSSID, abyBSSID)) {
-//                if (pSSID == NULL)
-//                    return pBSSList;
-                if (pSSID->len == ((PWLAN_IE_SSID)pBSSList->abySSID)->len){
-                    if (memcmp(pSSID->abySSID,
-                            ((PWLAN_IE_SSID)pBSSList->abySSID)->abySSID,
-                            pSSID->len) == 0)
-                        return pBSSList;
-                }
-            }
-        }
-    }
-
-    return NULL;
-};
-
+	PSDevice     pDevice = (PSDevice)hDeviceContext;
+	PSMgmtObject    pMgmt = pDevice->pMgmt;
+	PKnownBSS       pBSSList = NULL;
+	unsigned int ii;
+
+	for (ii = 0; ii < MAX_BSS_NUM; ii++) {
+		pBSSList = &(pMgmt->sBSSList[ii]);
+		if (pBSSList->bActive) {
+			if (!compare_ether_addr(pBSSList->abyBSSID, abyBSSID)) {
+				if (pSSID->len == ((PWLAN_IE_SSID)pBSSList->abySSID)->len) {
+					if (memcmp(pSSID->abySSID,
+						   ((PWLAN_IE_SSID)pBSSList->abySSID)->abySSID,
+						   pSSID->len) == 0)
+						return pBSSList;
+				}
+			}
+		}
+	}
 
+	return NULL;
+};
 
 /*+
  *
@@ -363,212 +340,206 @@ BSSpAddrIsInBSSList(
  * Return Value:
  *    true if success.
  *
--*/
+ -*/
 
 bool
-BSSbInsertToBSSList (
-    void *hDeviceContext,
-    unsigned char *abyBSSIDAddr,
-    QWORD qwTimestamp,
-    unsigned short wBeaconInterval,
-    unsigned short wCapInfo,
-    unsigned char byCurrChannel,
-    PWLAN_IE_SSID pSSID,
-    PWLAN_IE_SUPP_RATES pSuppRates,
-    PWLAN_IE_SUPP_RATES pExtSuppRates,
-    PERPObject psERP,
-    PWLAN_IE_RSN pRSN,
-    PWLAN_IE_RSN_EXT pRSNWPA,
-    PWLAN_IE_COUNTRY pIE_Country,
-    PWLAN_IE_QUIET pIE_Quiet,
-    unsigned int uIELength,
-    unsigned char *pbyIEs,
-    void *pRxPacketContext
-    )
+BSSbInsertToBSSList(
+	void *hDeviceContext,
+	unsigned char *abyBSSIDAddr,
+	QWORD qwTimestamp,
+	unsigned short wBeaconInterval,
+	unsigned short wCapInfo,
+	unsigned char byCurrChannel,
+	PWLAN_IE_SSID pSSID,
+	PWLAN_IE_SUPP_RATES pSuppRates,
+	PWLAN_IE_SUPP_RATES pExtSuppRates,
+	PERPObject psERP,
+	PWLAN_IE_RSN pRSN,
+	PWLAN_IE_RSN_EXT pRSNWPA,
+	PWLAN_IE_COUNTRY pIE_Country,
+	PWLAN_IE_QUIET pIE_Quiet,
+	unsigned int uIELength,
+	unsigned char *pbyIEs,
+	void *pRxPacketContext
+)
 {
+	PSDevice     pDevice = (PSDevice)hDeviceContext;
+	PSMgmtObject    pMgmt = pDevice->pMgmt;
+	PSRxMgmtPacket  pRxPacket = (PSRxMgmtPacket)pRxPacketContext;
+	PKnownBSS       pBSSList = NULL;
+	unsigned int ii;
+	bool bParsingQuiet = false;
+	PWLAN_IE_QUIET  pQuiet = NULL;
+
+	pBSSList = (PKnownBSS)&(pMgmt->sBSSList[0]);
+
+	for (ii = 0; ii < MAX_BSS_NUM; ii++) {
+		pBSSList = (PKnownBSS)&(pMgmt->sBSSList[ii]);
+		if (!pBSSList->bActive)
+			break;
+	}
+
+	if (ii == MAX_BSS_NUM) {
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Get free KnowBSS node failed.\n");
+		return false;
+	}
+	// save the BSS info
+	pBSSList->bActive = true;
+	memcpy(pBSSList->abyBSSID, abyBSSIDAddr, WLAN_BSSID_LEN);
+	HIDWORD(pBSSList->qwBSSTimestamp) = cpu_to_le32(HIDWORD(qwTimestamp));
+	LODWORD(pBSSList->qwBSSTimestamp) = cpu_to_le32(LODWORD(qwTimestamp));
+	pBSSList->wBeaconInterval = cpu_to_le16(wBeaconInterval);
+	pBSSList->wCapInfo = cpu_to_le16(wCapInfo);
+	pBSSList->uClearCount = 0;
+
+	if (pSSID->len > WLAN_SSID_MAXLEN)
+		pSSID->len = WLAN_SSID_MAXLEN;
+	memcpy(pBSSList->abySSID, pSSID, pSSID->len + WLAN_IEHDR_LEN);
+
+	pBSSList->uChannel = byCurrChannel;
+
+	if (pSuppRates->len > WLAN_RATES_MAXLEN)
+		pSuppRates->len = WLAN_RATES_MAXLEN;
+	memcpy(pBSSList->abySuppRates, pSuppRates, pSuppRates->len + WLAN_IEHDR_LEN);
+
+	if (pExtSuppRates != NULL) {
+		if (pExtSuppRates->len > WLAN_RATES_MAXLEN)
+			pExtSuppRates->len = WLAN_RATES_MAXLEN;
+		memcpy(pBSSList->abyExtSuppRates, pExtSuppRates, pExtSuppRates->len + WLAN_IEHDR_LEN);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "BSSbInsertToBSSList: pExtSuppRates->len = %d\n", pExtSuppRates->len);
+
+	} else {
+		memset(pBSSList->abyExtSuppRates, 0, WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1);
+	}
+	pBSSList->sERP.byERP = psERP->byERP;
+	pBSSList->sERP.bERPExist = psERP->bERPExist;
+
+	// Check if BSS is 802.11a/b/g
+	if (pBSSList->uChannel > CB_MAX_CHANNEL_24G) {
+		pBSSList->eNetworkTypeInUse = PHY_TYPE_11A;
+	} else {
+		if (pBSSList->sERP.bERPExist == true) {
+			pBSSList->eNetworkTypeInUse = PHY_TYPE_11G;
+		} else {
+			pBSSList->eNetworkTypeInUse = PHY_TYPE_11B;
+		}
+	}
+
+	pBSSList->byRxRate = pRxPacket->byRxRate;
+	pBSSList->qwLocalTSF = pRxPacket->qwLocalTSF;
+	pBSSList->uRSSI = pRxPacket->uRSSI;
+	pBSSList->bySQ = pRxPacket->bySQ;
+
+	if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) &&
+	    (pMgmt->eCurrState == WMAC_STATE_ASSOC)) {
+		// assoc with BSS
+		if (pBSSList == pMgmt->pCurrBSS) {
+			bParsingQuiet = true;
+		}
+	}
 
-    PSDevice     pDevice = (PSDevice)hDeviceContext;
-    PSMgmtObject    pMgmt = pDevice->pMgmt;
-    PSRxMgmtPacket  pRxPacket = (PSRxMgmtPacket)pRxPacketContext;
-    PKnownBSS       pBSSList = NULL;
-    unsigned int ii;
-    bool bParsingQuiet = false;
-    PWLAN_IE_QUIET  pQuiet = NULL;
-
-
-
-    pBSSList = (PKnownBSS)&(pMgmt->sBSSList[0]);
-
-    for (ii = 0; ii < MAX_BSS_NUM; ii++) {
-        pBSSList = (PKnownBSS)&(pMgmt->sBSSList[ii]);
-        if (!pBSSList->bActive)
-                break;
-    }
-
-    if (ii == MAX_BSS_NUM){
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Get free KnowBSS node failed.\n");
-        return false;
-    }
-    // save the BSS info
-    pBSSList->bActive = true;
-    memcpy( pBSSList->abyBSSID, abyBSSIDAddr, WLAN_BSSID_LEN);
-    HIDWORD(pBSSList->qwBSSTimestamp) = cpu_to_le32(HIDWORD(qwTimestamp));
-    LODWORD(pBSSList->qwBSSTimestamp) = cpu_to_le32(LODWORD(qwTimestamp));
-    pBSSList->wBeaconInterval = cpu_to_le16(wBeaconInterval);
-    pBSSList->wCapInfo = cpu_to_le16(wCapInfo);
-    pBSSList->uClearCount = 0;
-
-    if (pSSID->len > WLAN_SSID_MAXLEN)
-        pSSID->len = WLAN_SSID_MAXLEN;
-    memcpy( pBSSList->abySSID, pSSID, pSSID->len + WLAN_IEHDR_LEN);
-
-    pBSSList->uChannel = byCurrChannel;
-
-    if (pSuppRates->len > WLAN_RATES_MAXLEN)
-        pSuppRates->len = WLAN_RATES_MAXLEN;
-    memcpy( pBSSList->abySuppRates, pSuppRates, pSuppRates->len + WLAN_IEHDR_LEN);
-
-    if (pExtSuppRates != NULL) {
-        if (pExtSuppRates->len > WLAN_RATES_MAXLEN)
-            pExtSuppRates->len = WLAN_RATES_MAXLEN;
-        memcpy(pBSSList->abyExtSuppRates, pExtSuppRates, pExtSuppRates->len + WLAN_IEHDR_LEN);
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"BSSbInsertToBSSList: pExtSuppRates->len = %d\n", pExtSuppRates->len);
-
-    } else {
-        memset(pBSSList->abyExtSuppRates, 0, WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1);
-    }
-    pBSSList->sERP.byERP = psERP->byERP;
-    pBSSList->sERP.bERPExist = psERP->bERPExist;
-
-    // Check if BSS is 802.11a/b/g
-    if (pBSSList->uChannel > CB_MAX_CHANNEL_24G) {
-        pBSSList->eNetworkTypeInUse = PHY_TYPE_11A;
-    } else {
-        if (pBSSList->sERP.bERPExist == true) {
-            pBSSList->eNetworkTypeInUse = PHY_TYPE_11G;
-        } else {
-            pBSSList->eNetworkTypeInUse = PHY_TYPE_11B;
-        }
-    }
-
-    pBSSList->byRxRate = pRxPacket->byRxRate;
-    pBSSList->qwLocalTSF = pRxPacket->qwLocalTSF;
-    pBSSList->uRSSI = pRxPacket->uRSSI;
-    pBSSList->bySQ = pRxPacket->bySQ;
-
-   if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) &&
-        (pMgmt->eCurrState == WMAC_STATE_ASSOC)) {
-        // assoc with BSS
-        if (pBSSList == pMgmt->pCurrBSS) {
-            bParsingQuiet = true;
-        }
-    }
-
-    WPA_ClearRSN(pBSSList);
-
-    if (pRSNWPA != NULL) {
-        unsigned int uLen = pRSNWPA->len + 2;
-
-        if (uLen <= (uIELength - (unsigned int)((unsigned char *)pRSNWPA - pbyIEs))) {
-            pBSSList->wWPALen = uLen;
-            memcpy(pBSSList->byWPAIE, pRSNWPA, uLen);
-            WPA_ParseRSN(pBSSList, pRSNWPA);
-        }
-    }
-
-    WPA2_ClearRSN(pBSSList);
-
-    if (pRSN != NULL) {
-        unsigned int uLen = pRSN->len + 2;
-        if (uLen <= (uIELength - (unsigned int)((unsigned char *)pRSN - pbyIEs))) {
-            pBSSList->wRSNLen = uLen;
-            memcpy(pBSSList->byRSNIE, pRSN, uLen);
-            WPA2vParseRSN(pBSSList, pRSN);
-        }
-    }
-
-    if ((pMgmt->eAuthenMode == WMAC_AUTH_WPA2) || (pBSSList->bWPA2Valid == true)) {
-
-        PSKeyItem  pTransmitKey = NULL;
-        bool bIs802_1x = false;
-
-        for (ii = 0; ii < pBSSList->wAKMSSAuthCount; ii ++) {
-            if (pBSSList->abyAKMSSAuthType[ii] == WLAN_11i_AKMSS_802_1X) {
-                bIs802_1x = true;
-                break;
-            }
-        }
-        if ((bIs802_1x == true) && (pSSID->len == ((PWLAN_IE_SSID)pMgmt->abyDesireSSID)->len) &&
-            ( !memcmp(pSSID->abySSID, ((PWLAN_IE_SSID)pMgmt->abyDesireSSID)->abySSID, pSSID->len))) {
-
-            bAdd_PMKID_Candidate((void *)pDevice, pBSSList->abyBSSID, &pBSSList->sRSNCapObj);
-
-            if ((pDevice->bLinkPass == true) && (pMgmt->eCurrState == WMAC_STATE_ASSOC)) {
-                if ((KeybGetTransmitKey(&(pDevice->sKey), pDevice->abyBSSID, PAIRWISE_KEY, &pTransmitKey) == true) ||
-                    (KeybGetTransmitKey(&(pDevice->sKey), pDevice->abyBSSID, GROUP_KEY, &pTransmitKey) == true)) {
-                    pDevice->gsPMKIDCandidate.StatusType = Ndis802_11StatusType_PMKID_CandidateList;
-                    pDevice->gsPMKIDCandidate.Version = 1;
-
-                }
-
-            }
-        }
-    }
-
-    if (pDevice->bUpdateBBVGA) {
-        // Moniter if RSSI is too strong.
-        pBSSList->byRSSIStatCnt = 0;
-        RFvRSSITodBm(pDevice, (unsigned char)(pRxPacket->uRSSI), &pBSSList->ldBmMAX);
-        pBSSList->ldBmAverage[0] = pBSSList->ldBmMAX;
-        for (ii = 1; ii < RSSI_STAT_COUNT; ii++)
-            pBSSList->ldBmAverage[ii] = 0;
-    }
-
-    if ((pIE_Country != NULL) &&
-        (pMgmt->b11hEnable == true)) {
-        set_country_info(pMgmt->pAdapter, pBSSList->eNetworkTypeInUse,
-                            pIE_Country);
-    }
-
-    if ((bParsingQuiet == true) && (pIE_Quiet != NULL)) {
-        if ((((PWLAN_IE_QUIET)pIE_Quiet)->len == 8) &&
-            (((PWLAN_IE_QUIET)pIE_Quiet)->byQuietCount != 0)) {
-            // valid EID
-            if (pQuiet == NULL) {
-                pQuiet = (PWLAN_IE_QUIET)pIE_Quiet;
-                CARDbSetQuiet(  pMgmt->pAdapter,
-                                true,
-                                pQuiet->byQuietCount,
-                                pQuiet->byQuietPeriod,
-                                *((unsigned short *)pQuiet->abyQuietDuration),
-                                *((unsigned short *)pQuiet->abyQuietOffset)
-                                );
-            } else {
-                pQuiet = (PWLAN_IE_QUIET)pIE_Quiet;
-                CARDbSetQuiet(  pMgmt->pAdapter,
-                                false,
-                                pQuiet->byQuietCount,
-                                pQuiet->byQuietPeriod,
-                                *((unsigned short *)pQuiet->abyQuietDuration),
-                                *((unsigned short *)pQuiet->abyQuietOffset)
-                                );
-            }
-        }
-    }
-
-    if ((bParsingQuiet == true) &&
-        (pQuiet != NULL)) {
-        CARDbStartQuiet(pMgmt->pAdapter);
-    }
-
-    pBSSList->uIELength = uIELength;
-    if (pBSSList->uIELength > WLAN_BEACON_FR_MAXLEN)
-        pBSSList->uIELength = WLAN_BEACON_FR_MAXLEN;
-    memcpy(pBSSList->abyIEs, pbyIEs, pBSSList->uIELength);
-
-    return true;
-}
+	WPA_ClearRSN(pBSSList);
 
+	if (pRSNWPA != NULL) {
+		unsigned int uLen = pRSNWPA->len + 2;
+
+		if (uLen <= (uIELength - (unsigned int)((unsigned char *)pRSNWPA - pbyIEs))) {
+			pBSSList->wWPALen = uLen;
+			memcpy(pBSSList->byWPAIE, pRSNWPA, uLen);
+			WPA_ParseRSN(pBSSList, pRSNWPA);
+		}
+	}
+
+	WPA2_ClearRSN(pBSSList);
+
+	if (pRSN != NULL) {
+		unsigned int uLen = pRSN->len + 2;
+		if (uLen <= (uIELength - (unsigned int)((unsigned char *)pRSN - pbyIEs))) {
+			pBSSList->wRSNLen = uLen;
+			memcpy(pBSSList->byRSNIE, pRSN, uLen);
+			WPA2vParseRSN(pBSSList, pRSN);
+		}
+	}
+
+	if ((pMgmt->eAuthenMode == WMAC_AUTH_WPA2) || (pBSSList->bWPA2Valid == true)) {
+		PSKeyItem  pTransmitKey = NULL;
+		bool bIs802_1x = false;
+
+		for (ii = 0; ii < pBSSList->wAKMSSAuthCount; ii++) {
+			if (pBSSList->abyAKMSSAuthType[ii] == WLAN_11i_AKMSS_802_1X) {
+				bIs802_1x = true;
+				break;
+			}
+		}
+		if ((bIs802_1x == true) && (pSSID->len == ((PWLAN_IE_SSID)pMgmt->abyDesireSSID)->len) &&
+		    (!memcmp(pSSID->abySSID, ((PWLAN_IE_SSID)pMgmt->abyDesireSSID)->abySSID, pSSID->len))) {
+			bAdd_PMKID_Candidate((void *)pDevice, pBSSList->abyBSSID, &pBSSList->sRSNCapObj);
+
+			if ((pDevice->bLinkPass == true) && (pMgmt->eCurrState == WMAC_STATE_ASSOC)) {
+				if ((KeybGetTransmitKey(&(pDevice->sKey), pDevice->abyBSSID, PAIRWISE_KEY, &pTransmitKey) == true) ||
+				    (KeybGetTransmitKey(&(pDevice->sKey), pDevice->abyBSSID, GROUP_KEY, &pTransmitKey) == true)) {
+					pDevice->gsPMKIDCandidate.StatusType = Ndis802_11StatusType_PMKID_CandidateList;
+					pDevice->gsPMKIDCandidate.Version = 1;
+
+				}
+
+			}
+		}
+	}
+
+	if (pDevice->bUpdateBBVGA) {
+		// Moniter if RSSI is too strong.
+		pBSSList->byRSSIStatCnt = 0;
+		RFvRSSITodBm(pDevice, (unsigned char)(pRxPacket->uRSSI), &pBSSList->ldBmMAX);
+		pBSSList->ldBmAverage[0] = pBSSList->ldBmMAX;
+		for (ii = 1; ii < RSSI_STAT_COUNT; ii++)
+			pBSSList->ldBmAverage[ii] = 0;
+	}
+
+	if ((pIE_Country != NULL) &&
+	    (pMgmt->b11hEnable == true)) {
+		set_country_info(pMgmt->pAdapter, pBSSList->eNetworkTypeInUse,
+				 pIE_Country);
+	}
+
+	if ((bParsingQuiet == true) && (pIE_Quiet != NULL)) {
+		if ((((PWLAN_IE_QUIET)pIE_Quiet)->len == 8) &&
+		    (((PWLAN_IE_QUIET)pIE_Quiet)->byQuietCount != 0)) {
+			// valid EID
+			if (pQuiet == NULL) {
+				pQuiet = (PWLAN_IE_QUIET)pIE_Quiet;
+				CARDbSetQuiet(pMgmt->pAdapter,
+					      true,
+					      pQuiet->byQuietCount,
+					      pQuiet->byQuietPeriod,
+					      *((unsigned short *)pQuiet->abyQuietDuration),
+					      *((unsigned short *)pQuiet->abyQuietOffset)
+);
+			} else {
+				pQuiet = (PWLAN_IE_QUIET)pIE_Quiet;
+				CARDbSetQuiet(pMgmt->pAdapter,
+					      false,
+					      pQuiet->byQuietCount,
+					      pQuiet->byQuietPeriod,
+					      *((unsigned short *)pQuiet->abyQuietDuration),
+					      *((unsigned short *)pQuiet->abyQuietOffset)
+					);
+			}
+		}
+	}
+
+	if ((bParsingQuiet == true) &&
+	    (pQuiet != NULL)) {
+		CARDbStartQuiet(pMgmt->pAdapter);
+	}
+
+	pBSSList->uIELength = uIELength;
+	if (pBSSList->uIELength > WLAN_BEACON_FR_MAXLEN)
+		pBSSList->uIELength = WLAN_BEACON_FR_MAXLEN;
+	memcpy(pBSSList->abyIEs, pbyIEs, pBSSList->uIELength);
+
+	return true;
+}
 
 /*+
  *
@@ -578,176 +549,169 @@ BSSbInsertToBSSList (
  * Return Value:
  *    true if success.
  *
--*/
+ -*/
 // TODO: input structure modify
 
 bool
-BSSbUpdateToBSSList (
-    void *hDeviceContext,
-    QWORD qwTimestamp,
-    unsigned short wBeaconInterval,
-    unsigned short wCapInfo,
-    unsigned char byCurrChannel,
-    bool bChannelHit,
-    PWLAN_IE_SSID pSSID,
-    PWLAN_IE_SUPP_RATES pSuppRates,
-    PWLAN_IE_SUPP_RATES pExtSuppRates,
-    PERPObject psERP,
-    PWLAN_IE_RSN pRSN,
-    PWLAN_IE_RSN_EXT pRSNWPA,
-    PWLAN_IE_COUNTRY pIE_Country,
-    PWLAN_IE_QUIET pIE_Quiet,
-    PKnownBSS pBSSList,
-    unsigned int uIELength,
-    unsigned char *pbyIEs,
-    void *pRxPacketContext
-    )
+BSSbUpdateToBSSList(
+	void *hDeviceContext,
+	QWORD qwTimestamp,
+	unsigned short wBeaconInterval,
+	unsigned short wCapInfo,
+	unsigned char byCurrChannel,
+	bool bChannelHit,
+	PWLAN_IE_SSID pSSID,
+	PWLAN_IE_SUPP_RATES pSuppRates,
+	PWLAN_IE_SUPP_RATES pExtSuppRates,
+	PERPObject psERP,
+	PWLAN_IE_RSN pRSN,
+	PWLAN_IE_RSN_EXT pRSNWPA,
+	PWLAN_IE_COUNTRY pIE_Country,
+	PWLAN_IE_QUIET pIE_Quiet,
+	PKnownBSS pBSSList,
+	unsigned int uIELength,
+	unsigned char *pbyIEs,
+	void *pRxPacketContext
+)
 {
-    int             ii;
-    PSDevice        pDevice = (PSDevice)hDeviceContext;
-    PSMgmtObject    pMgmt = pDevice->pMgmt;
-    PSRxMgmtPacket  pRxPacket = (PSRxMgmtPacket)pRxPacketContext;
-    long            ldBm;
-    bool bParsingQuiet = false;
-    PWLAN_IE_QUIET  pQuiet = NULL;
-
-
-
-    if (pBSSList == NULL)
-        return false;
-
-
-    HIDWORD(pBSSList->qwBSSTimestamp) = cpu_to_le32(HIDWORD(qwTimestamp));
-    LODWORD(pBSSList->qwBSSTimestamp) = cpu_to_le32(LODWORD(qwTimestamp));
-    pBSSList->wBeaconInterval = cpu_to_le16(wBeaconInterval);
-    pBSSList->wCapInfo = cpu_to_le16(wCapInfo);
-    pBSSList->uClearCount = 0;
-    pBSSList->uChannel = byCurrChannel;
-//    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"BSSbUpdateToBSSList: pBSSList->uChannel: %d\n", pBSSList->uChannel);
-
-    if (pSSID->len > WLAN_SSID_MAXLEN)
-        pSSID->len = WLAN_SSID_MAXLEN;
-
-    if ((pSSID->len != 0) && (pSSID->abySSID[0] != 0))
-        memcpy(pBSSList->abySSID, pSSID, pSSID->len + WLAN_IEHDR_LEN);
-    memcpy(pBSSList->abySuppRates, pSuppRates,pSuppRates->len + WLAN_IEHDR_LEN);
-
-    if (pExtSuppRates != NULL) {
-        memcpy(pBSSList->abyExtSuppRates, pExtSuppRates,pExtSuppRates->len + WLAN_IEHDR_LEN);
-    } else {
-        memset(pBSSList->abyExtSuppRates, 0, WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1);
-    }
-    pBSSList->sERP.byERP = psERP->byERP;
-    pBSSList->sERP.bERPExist = psERP->bERPExist;
-
-    // Check if BSS is 802.11a/b/g
-    if (pBSSList->uChannel > CB_MAX_CHANNEL_24G) {
-        pBSSList->eNetworkTypeInUse = PHY_TYPE_11A;
-    } else {
-        if (pBSSList->sERP.bERPExist == true) {
-            pBSSList->eNetworkTypeInUse = PHY_TYPE_11G;
-        } else {
-            pBSSList->eNetworkTypeInUse = PHY_TYPE_11B;
-        }
-    }
-
-    pBSSList->byRxRate = pRxPacket->byRxRate;
-    pBSSList->qwLocalTSF = pRxPacket->qwLocalTSF;
-    if(bChannelHit)
-        pBSSList->uRSSI = pRxPacket->uRSSI;
-    pBSSList->bySQ = pRxPacket->bySQ;
-
-   if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) &&
-        (pMgmt->eCurrState == WMAC_STATE_ASSOC)) {
-        // assoc with BSS
-        if (pBSSList == pMgmt->pCurrBSS) {
-            bParsingQuiet = true;
-        }
-    }
-
-   WPA_ClearRSN(pBSSList);         //mike update
-
-    if (pRSNWPA != NULL) {
-        unsigned int uLen = pRSNWPA->len + 2;
-        if (uLen <= (uIELength - (unsigned int)((unsigned char *)pRSNWPA - pbyIEs))) {
-            pBSSList->wWPALen = uLen;
-            memcpy(pBSSList->byWPAIE, pRSNWPA, uLen);
-            WPA_ParseRSN(pBSSList, pRSNWPA);
-        }
-    }
-
-   WPA2_ClearRSN(pBSSList);  //mike update
-
-    if (pRSN != NULL) {
-        unsigned int uLen = pRSN->len + 2;
-        if (uLen <= (uIELength - (unsigned int)((unsigned char *)pRSN - pbyIEs))) {
-            pBSSList->wRSNLen = uLen;
-            memcpy(pBSSList->byRSNIE, pRSN, uLen);
-            WPA2vParseRSN(pBSSList, pRSN);
-        }
-    }
-
-    if (pRxPacket->uRSSI != 0) {
-        RFvRSSITodBm(pDevice, (unsigned char)(pRxPacket->uRSSI), &ldBm);
-        // Moniter if RSSI is too strong.
-        pBSSList->byRSSIStatCnt++;
-        pBSSList->byRSSIStatCnt %= RSSI_STAT_COUNT;
-        pBSSList->ldBmAverage[pBSSList->byRSSIStatCnt] = ldBm;
-        for(ii=0;ii<RSSI_STAT_COUNT;ii++) {
-            if (pBSSList->ldBmAverage[ii] != 0) {
-                pBSSList->ldBmMAX = max(pBSSList->ldBmAverage[ii], ldBm);
-            }
-        }
-    }
-
-    if ((pIE_Country != NULL) &&
-        (pMgmt->b11hEnable == true)) {
-        set_country_info(pMgmt->pAdapter, pBSSList->eNetworkTypeInUse,
-                            pIE_Country);
-    }
-
-    if ((bParsingQuiet == true) && (pIE_Quiet != NULL)) {
-        if ((((PWLAN_IE_QUIET)pIE_Quiet)->len == 8) &&
-            (((PWLAN_IE_QUIET)pIE_Quiet)->byQuietCount != 0)) {
-            // valid EID
-            if (pQuiet == NULL) {
-                pQuiet = (PWLAN_IE_QUIET)pIE_Quiet;
-                CARDbSetQuiet(  pMgmt->pAdapter,
-                                true,
-                                pQuiet->byQuietCount,
-                                pQuiet->byQuietPeriod,
-                                *((unsigned short *)pQuiet->abyQuietDuration),
-                                *((unsigned short *)pQuiet->abyQuietOffset)
-                                );
-            } else {
-                pQuiet = (PWLAN_IE_QUIET)pIE_Quiet;
-                CARDbSetQuiet(  pMgmt->pAdapter,
-                                false,
-                                pQuiet->byQuietCount,
-                                pQuiet->byQuietPeriod,
-                                *((unsigned short *)pQuiet->abyQuietDuration),
-                                *((unsigned short *)pQuiet->abyQuietOffset)
-                                );
-            }
-        }
-    }
-
-    if ((bParsingQuiet == true) &&
-        (pQuiet != NULL)) {
-        CARDbStartQuiet(pMgmt->pAdapter);
-    }
-
-    pBSSList->uIELength = uIELength;
-    if (pBSSList->uIELength > WLAN_BEACON_FR_MAXLEN)
-        pBSSList->uIELength = WLAN_BEACON_FR_MAXLEN;
-    memcpy(pBSSList->abyIEs, pbyIEs, pBSSList->uIELength);
-
-    return true;
-}
+	int             ii;
+	PSDevice        pDevice = (PSDevice)hDeviceContext;
+	PSMgmtObject    pMgmt = pDevice->pMgmt;
+	PSRxMgmtPacket  pRxPacket = (PSRxMgmtPacket)pRxPacketContext;
+	long            ldBm;
+	bool bParsingQuiet = false;
+	PWLAN_IE_QUIET  pQuiet = NULL;
+
+	if (pBSSList == NULL)
+		return false;
+
+	HIDWORD(pBSSList->qwBSSTimestamp) = cpu_to_le32(HIDWORD(qwTimestamp));
+	LODWORD(pBSSList->qwBSSTimestamp) = cpu_to_le32(LODWORD(qwTimestamp));
+	pBSSList->wBeaconInterval = cpu_to_le16(wBeaconInterval);
+	pBSSList->wCapInfo = cpu_to_le16(wCapInfo);
+	pBSSList->uClearCount = 0;
+	pBSSList->uChannel = byCurrChannel;
+//    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "BSSbUpdateToBSSList: pBSSList->uChannel: %d\n", pBSSList->uChannel);
+
+	if (pSSID->len > WLAN_SSID_MAXLEN)
+		pSSID->len = WLAN_SSID_MAXLEN;
+
+	if ((pSSID->len != 0) && (pSSID->abySSID[0] != 0))
+		memcpy(pBSSList->abySSID, pSSID, pSSID->len + WLAN_IEHDR_LEN);
+	memcpy(pBSSList->abySuppRates, pSuppRates, pSuppRates->len + WLAN_IEHDR_LEN);
+
+	if (pExtSuppRates != NULL) {
+		memcpy(pBSSList->abyExtSuppRates, pExtSuppRates, pExtSuppRates->len + WLAN_IEHDR_LEN);
+	} else {
+		memset(pBSSList->abyExtSuppRates, 0, WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1);
+	}
+	pBSSList->sERP.byERP = psERP->byERP;
+	pBSSList->sERP.bERPExist = psERP->bERPExist;
+
+	// Check if BSS is 802.11a/b/g
+	if (pBSSList->uChannel > CB_MAX_CHANNEL_24G) {
+		pBSSList->eNetworkTypeInUse = PHY_TYPE_11A;
+	} else {
+		if (pBSSList->sERP.bERPExist == true) {
+			pBSSList->eNetworkTypeInUse = PHY_TYPE_11G;
+		} else {
+			pBSSList->eNetworkTypeInUse = PHY_TYPE_11B;
+		}
+	}
+
+	pBSSList->byRxRate = pRxPacket->byRxRate;
+	pBSSList->qwLocalTSF = pRxPacket->qwLocalTSF;
+	if (bChannelHit)
+		pBSSList->uRSSI = pRxPacket->uRSSI;
+	pBSSList->bySQ = pRxPacket->bySQ;
+
+	if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) &&
+	    (pMgmt->eCurrState == WMAC_STATE_ASSOC)) {
+		// assoc with BSS
+		if (pBSSList == pMgmt->pCurrBSS) {
+			bParsingQuiet = true;
+		}
+	}
 
+	WPA_ClearRSN(pBSSList);         //mike update
 
+	if (pRSNWPA != NULL) {
+		unsigned int uLen = pRSNWPA->len + 2;
+		if (uLen <= (uIELength - (unsigned int)((unsigned char *)pRSNWPA - pbyIEs))) {
+			pBSSList->wWPALen = uLen;
+			memcpy(pBSSList->byWPAIE, pRSNWPA, uLen);
+			WPA_ParseRSN(pBSSList, pRSNWPA);
+		}
+	}
+
+	WPA2_ClearRSN(pBSSList);  //mike update
+
+	if (pRSN != NULL) {
+		unsigned int uLen = pRSN->len + 2;
+		if (uLen <= (uIELength - (unsigned int)((unsigned char *)pRSN - pbyIEs))) {
+			pBSSList->wRSNLen = uLen;
+			memcpy(pBSSList->byRSNIE, pRSN, uLen);
+			WPA2vParseRSN(pBSSList, pRSN);
+		}
+	}
+
+	if (pRxPacket->uRSSI != 0) {
+		RFvRSSITodBm(pDevice, (unsigned char)(pRxPacket->uRSSI), &ldBm);
+		// Moniter if RSSI is too strong.
+		pBSSList->byRSSIStatCnt++;
+		pBSSList->byRSSIStatCnt %= RSSI_STAT_COUNT;
+		pBSSList->ldBmAverage[pBSSList->byRSSIStatCnt] = ldBm;
+		for (ii = 0; ii < RSSI_STAT_COUNT; ii++) {
+			if (pBSSList->ldBmAverage[ii] != 0) {
+				pBSSList->ldBmMAX = max(pBSSList->ldBmAverage[ii], ldBm);
+			}
+		}
+	}
+
+	if ((pIE_Country != NULL) &&
+	    (pMgmt->b11hEnable == true)) {
+		set_country_info(pMgmt->pAdapter, pBSSList->eNetworkTypeInUse,
+				 pIE_Country);
+	}
+
+	if ((bParsingQuiet == true) && (pIE_Quiet != NULL)) {
+		if ((((PWLAN_IE_QUIET)pIE_Quiet)->len == 8) &&
+		    (((PWLAN_IE_QUIET)pIE_Quiet)->byQuietCount != 0)) {
+			// valid EID
+			if (pQuiet == NULL) {
+				pQuiet = (PWLAN_IE_QUIET)pIE_Quiet;
+				CARDbSetQuiet(pMgmt->pAdapter,
+					      true,
+					      pQuiet->byQuietCount,
+					      pQuiet->byQuietPeriod,
+					      *((unsigned short *)pQuiet->abyQuietDuration),
+					      *((unsigned short *)pQuiet->abyQuietOffset)
+);
+			} else {
+				pQuiet = (PWLAN_IE_QUIET)pIE_Quiet;
+				CARDbSetQuiet(pMgmt->pAdapter,
+					      false,
+					      pQuiet->byQuietCount,
+					      pQuiet->byQuietPeriod,
+					      *((unsigned short *)pQuiet->abyQuietDuration),
+					      *((unsigned short *)pQuiet->abyQuietOffset)
+					);
+			}
+		}
+	}
 
+	if ((bParsingQuiet == true) &&
+	    (pQuiet != NULL)) {
+		CARDbStartQuiet(pMgmt->pAdapter);
+	}
 
+	pBSSList->uIELength = uIELength;
+	if (pBSSList->uIELength > WLAN_BEACON_FR_MAXLEN)
+		pBSSList->uIELength = WLAN_BEACON_FR_MAXLEN;
+	memcpy(pBSSList->abyIEs, pbyIEs, pBSSList->uIELength);
+
+	return true;
+}
 
 /*+
  *
@@ -757,29 +721,27 @@ BSSbUpdateToBSSList (
  * Return Value:
  *    None
  *
--*/
+ -*/
 
 bool
 BSSDBbIsSTAInNodeDB(void *pMgmtObject, unsigned char *abyDstAddr,
-		unsigned int *puNodeIndex)
+		    unsigned int *puNodeIndex)
 {
-    PSMgmtObject    pMgmt = (PSMgmtObject) pMgmtObject;
-    unsigned int ii;
-
-    // Index = 0 reserved for AP Node
-    for (ii = 1; ii < (MAX_NODE_NUM + 1); ii++) {
-        if (pMgmt->sNodeDBTable[ii].bActive) {
-            if (!compare_ether_addr(abyDstAddr, pMgmt->sNodeDBTable[ii].abyMACAddr)) {
-                *puNodeIndex = ii;
-                return true;
-            }
-        }
-    }
-
-   return false;
-};
-
+	PSMgmtObject    pMgmt = (PSMgmtObject) pMgmtObject;
+	unsigned int ii;
+
+	// Index = 0 reserved for AP Node
+	for (ii = 1; ii < (MAX_NODE_NUM + 1); ii++) {
+		if (pMgmt->sNodeDBTable[ii].bActive) {
+			if (!compare_ether_addr(abyDstAddr, pMgmt->sNodeDBTable[ii].abyMACAddr)) {
+				*puNodeIndex = ii;
+				return true;
+			}
+		}
+	}
 
+	return false;
+};
 
 /*+
  *
@@ -790,59 +752,54 @@ BSSDBbIsSTAInNodeDB(void *pMgmtObject, unsigned char *abyDstAddr,
  * Return Value:
  *    None
  *
--*/
+ -*/
 void
 BSSvCreateOneNode(void *hDeviceContext, unsigned int *puNodeIndex)
 {
-
-    PSDevice     pDevice = (PSDevice)hDeviceContext;
-    PSMgmtObject    pMgmt = pDevice->pMgmt;
-    unsigned int ii;
-    unsigned int BigestCount = 0;
-    unsigned int SelectIndex;
-    struct sk_buff  *skb;
-    // Index = 0 reserved for AP Node (In STA mode)
-    // Index = 0 reserved for Broadcast/MultiCast (In AP mode)
-    SelectIndex = 1;
-    for (ii = 1; ii < (MAX_NODE_NUM + 1); ii++) {
-        if (pMgmt->sNodeDBTable[ii].bActive) {
-            if (pMgmt->sNodeDBTable[ii].uInActiveCount > BigestCount) {
-                BigestCount = pMgmt->sNodeDBTable[ii].uInActiveCount;
-                SelectIndex = ii;
-            }
-        }
-        else {
-            break;
-        }
-    }
-
-    // if not found replace uInActiveCount is largest one.
-    if ( ii == (MAX_NODE_NUM + 1)) {
-        *puNodeIndex = SelectIndex;
-        DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Replace inactive node = %d\n", SelectIndex);
-        // clear ps buffer
-        if (pMgmt->sNodeDBTable[*puNodeIndex].sTxPSQueue.next != NULL) {
-      	    while ((skb = skb_dequeue(&pMgmt->sNodeDBTable[*puNodeIndex].sTxPSQueue)) != NULL)
-            dev_kfree_skb(skb);
-        }
-    }
-    else {
-        *puNodeIndex = ii;
-    }
-
-    memset(&pMgmt->sNodeDBTable[*puNodeIndex], 0, sizeof(KnownNodeDB));
-    pMgmt->sNodeDBTable[*puNodeIndex].bActive = true;
-    pMgmt->sNodeDBTable[*puNodeIndex].uRatePollTimeout = FALLBACK_POLL_SECOND;
-    // for AP mode PS queue
-    skb_queue_head_init(&pMgmt->sNodeDBTable[*puNodeIndex].sTxPSQueue);
-    pMgmt->sNodeDBTable[*puNodeIndex].byAuthSequence = 0;
-    pMgmt->sNodeDBTable[*puNodeIndex].wEnQueueCnt = 0;
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Create node index = %d\n", ii);
-    return;
+	PSDevice     pDevice = (PSDevice)hDeviceContext;
+	PSMgmtObject    pMgmt = pDevice->pMgmt;
+	unsigned int ii;
+	unsigned int BigestCount = 0;
+	unsigned int SelectIndex;
+	struct sk_buff  *skb;
+	// Index = 0 reserved for AP Node (In STA mode)
+	// Index = 0 reserved for Broadcast/MultiCast (In AP mode)
+	SelectIndex = 1;
+	for (ii = 1; ii < (MAX_NODE_NUM + 1); ii++) {
+		if (pMgmt->sNodeDBTable[ii].bActive) {
+			if (pMgmt->sNodeDBTable[ii].uInActiveCount > BigestCount) {
+				BigestCount = pMgmt->sNodeDBTable[ii].uInActiveCount;
+				SelectIndex = ii;
+			}
+		} else {
+			break;
+		}
+	}
+
+	// if not found replace uInActiveCount is largest one.
+	if (ii == (MAX_NODE_NUM + 1)) {
+		*puNodeIndex = SelectIndex;
+		DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Replace inactive node = %d\n", SelectIndex);
+		// clear ps buffer
+		if (pMgmt->sNodeDBTable[*puNodeIndex].sTxPSQueue.next != NULL) {
+			while ((skb = skb_dequeue(&pMgmt->sNodeDBTable[*puNodeIndex].sTxPSQueue)) != NULL)
+				dev_kfree_skb(skb);
+		}
+	} else {
+		*puNodeIndex = ii;
+	}
+
+	memset(&pMgmt->sNodeDBTable[*puNodeIndex], 0, sizeof(KnownNodeDB));
+	pMgmt->sNodeDBTable[*puNodeIndex].bActive = true;
+	pMgmt->sNodeDBTable[*puNodeIndex].uRatePollTimeout = FALLBACK_POLL_SECOND;
+	// for AP mode PS queue
+	skb_queue_head_init(&pMgmt->sNodeDBTable[*puNodeIndex].sTxPSQueue);
+	pMgmt->sNodeDBTable[*puNodeIndex].byAuthSequence = 0;
+	pMgmt->sNodeDBTable[*puNodeIndex].wEnQueueCnt = 0;
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Create node index = %d\n", ii);
+	return;
 };
 
-
-
 /*+
  *
  * Routine Description:
@@ -852,28 +809,26 @@ BSSvCreateOneNode(void *hDeviceContext, unsigned int *puNodeIndex)
  * Return Value:
  *    None
  *
--*/
+ -*/
 void
 BSSvRemoveOneNode(
-    void *hDeviceContext,
-    unsigned int uNodeIndex
-    )
+	void *hDeviceContext,
+	unsigned int uNodeIndex
+)
 {
-
-    PSDevice        pDevice = (PSDevice)hDeviceContext;
-    PSMgmtObject    pMgmt = pDevice->pMgmt;
-    unsigned char byMask[8] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80};
-    struct sk_buff  *skb;
-
-
-    while ((skb = skb_dequeue(&pMgmt->sNodeDBTable[uNodeIndex].sTxPSQueue)) != NULL)
-            dev_kfree_skb(skb);
-    // clear context
-    memset(&pMgmt->sNodeDBTable[uNodeIndex], 0, sizeof(KnownNodeDB));
-    // clear tx bit map
-    pMgmt->abyPSTxMap[pMgmt->sNodeDBTable[uNodeIndex].wAID >> 3] &=  ~byMask[pMgmt->sNodeDBTable[uNodeIndex].wAID & 7];
-
-    return;
+	PSDevice        pDevice = (PSDevice)hDeviceContext;
+	PSMgmtObject    pMgmt = pDevice->pMgmt;
+	unsigned char byMask[8] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80};
+	struct sk_buff  *skb;
+
+	while ((skb = skb_dequeue(&pMgmt->sNodeDBTable[uNodeIndex].sTxPSQueue)) != NULL)
+		dev_kfree_skb(skb);
+	// clear context
+	memset(&pMgmt->sNodeDBTable[uNodeIndex], 0, sizeof(KnownNodeDB));
+	// clear tx bit map
+	pMgmt->abyPSTxMap[pMgmt->sNodeDBTable[uNodeIndex].wAID >> 3] &=  ~byMask[pMgmt->sNodeDBTable[uNodeIndex].wAID & 7];
+
+	return;
 };
 /*+
  *
@@ -884,59 +839,54 @@ BSSvRemoveOneNode(
  * Return Value:
  *    None
  *
--*/
+ -*/
 
 void
 BSSvUpdateAPNode(
-    void *hDeviceContext,
-    unsigned short *pwCapInfo,
-    PWLAN_IE_SUPP_RATES pSuppRates,
-    PWLAN_IE_SUPP_RATES pExtSuppRates
-    )
+	void *hDeviceContext,
+	unsigned short *pwCapInfo,
+	PWLAN_IE_SUPP_RATES pSuppRates,
+	PWLAN_IE_SUPP_RATES pExtSuppRates
+)
 {
-    PSDevice     pDevice = (PSDevice)hDeviceContext;
-    PSMgmtObject    pMgmt = pDevice->pMgmt;
-    unsigned int uRateLen = WLAN_RATES_MAXLEN;
-
-    memset(&pMgmt->sNodeDBTable[0], 0, sizeof(KnownNodeDB));
-
-    pMgmt->sNodeDBTable[0].bActive = true;
-    if (pDevice->eCurrentPHYType == PHY_TYPE_11B) {
-        uRateLen = WLAN_RATES_MAXLEN_11B;
-    }
-    pMgmt->abyCurrSuppRates[1] = RATEuSetIE((PWLAN_IE_SUPP_RATES)pSuppRates,
-                                            (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates,
-                                            uRateLen);
-    pMgmt->abyCurrExtSuppRates[1] = RATEuSetIE((PWLAN_IE_SUPP_RATES)pExtSuppRates,
-                                            (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates,
-                                            uRateLen);
-    RATEvParseMaxRate((void *)pDevice,
-                       (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates,
-                       (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates,
-                       true,
-                       &(pMgmt->sNodeDBTable[0].wMaxBasicRate),
-                       &(pMgmt->sNodeDBTable[0].wMaxSuppRate),
-                       &(pMgmt->sNodeDBTable[0].wSuppRate),
-                       &(pMgmt->sNodeDBTable[0].byTopCCKBasicRate),
-                       &(pMgmt->sNodeDBTable[0].byTopOFDMBasicRate)
-                      );
-    memcpy(pMgmt->sNodeDBTable[0].abyMACAddr, pMgmt->abyCurrBSSID, WLAN_ADDR_LEN);
-    pMgmt->sNodeDBTable[0].wTxDataRate = pMgmt->sNodeDBTable[0].wMaxSuppRate;
-    pMgmt->sNodeDBTable[0].bShortPreamble = WLAN_GET_CAP_INFO_SHORTPREAMBLE(*pwCapInfo);
-    pMgmt->sNodeDBTable[0].uRatePollTimeout = FALLBACK_POLL_SECOND;
+	PSDevice     pDevice = (PSDevice)hDeviceContext;
+	PSMgmtObject    pMgmt = pDevice->pMgmt;
+	unsigned int uRateLen = WLAN_RATES_MAXLEN;
+
+	memset(&pMgmt->sNodeDBTable[0], 0, sizeof(KnownNodeDB));
+
+	pMgmt->sNodeDBTable[0].bActive = true;
+	if (pDevice->eCurrentPHYType == PHY_TYPE_11B) {
+		uRateLen = WLAN_RATES_MAXLEN_11B;
+	}
+	pMgmt->abyCurrSuppRates[1] = RATEuSetIE((PWLAN_IE_SUPP_RATES)pSuppRates,
+						(PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates,
+						uRateLen);
+	pMgmt->abyCurrExtSuppRates[1] = RATEuSetIE((PWLAN_IE_SUPP_RATES)pExtSuppRates,
+						   (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates,
+						   uRateLen);
+	RATEvParseMaxRate((void *)pDevice,
+			  (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates,
+			  (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates,
+			  true,
+			  &(pMgmt->sNodeDBTable[0].wMaxBasicRate),
+			  &(pMgmt->sNodeDBTable[0].wMaxSuppRate),
+			  &(pMgmt->sNodeDBTable[0].wSuppRate),
+			  &(pMgmt->sNodeDBTable[0].byTopCCKBasicRate),
+			  &(pMgmt->sNodeDBTable[0].byTopOFDMBasicRate)
+);
+	memcpy(pMgmt->sNodeDBTable[0].abyMACAddr, pMgmt->abyCurrBSSID, WLAN_ADDR_LEN);
+	pMgmt->sNodeDBTable[0].wTxDataRate = pMgmt->sNodeDBTable[0].wMaxSuppRate;
+	pMgmt->sNodeDBTable[0].bShortPreamble = WLAN_GET_CAP_INFO_SHORTPREAMBLE(*pwCapInfo);
+	pMgmt->sNodeDBTable[0].uRatePollTimeout = FALLBACK_POLL_SECOND;
 #ifdef	PLICE_DEBUG
-	printk("BSSvUpdateAPNode:MaxSuppRate is %d\n",pMgmt->sNodeDBTable[0].wMaxSuppRate);
+	printk("BSSvUpdateAPNode:MaxSuppRate is %d\n", pMgmt->sNodeDBTable[0].wMaxSuppRate);
 #endif
-    // Auto rate fallback function initiation.
-    // RATEbInit(pDevice);
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pMgmt->sNodeDBTable[0].wTxDataRate = %d \n", pMgmt->sNodeDBTable[0].wTxDataRate);
-
+	// Auto rate fallback function initiation.
+	// RATEbInit(pDevice);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pMgmt->sNodeDBTable[0].wTxDataRate = %d \n", pMgmt->sNodeDBTable[0].wTxDataRate);
 };
 
-
-
-
-
 /*+
  *
  * Routine Description:
@@ -946,45 +896,39 @@ BSSvUpdateAPNode(
  * Return Value:
  *    None
  *
--*/
-
+ -*/
 
 void
 BSSvAddMulticastNode(
-    void *hDeviceContext
-    )
+	void *hDeviceContext
+)
 {
-    PSDevice     pDevice = (PSDevice)hDeviceContext;
-    PSMgmtObject    pMgmt = pDevice->pMgmt;
-
-    if (!pDevice->bEnableHostWEP)
-        memset(&pMgmt->sNodeDBTable[0], 0, sizeof(KnownNodeDB));
-    memset(pMgmt->sNodeDBTable[0].abyMACAddr, 0xff, WLAN_ADDR_LEN);
-    pMgmt->sNodeDBTable[0].bActive = true;
-    pMgmt->sNodeDBTable[0].bPSEnable = false;
-    skb_queue_head_init(&pMgmt->sNodeDBTable[0].sTxPSQueue);
-    RATEvParseMaxRate((void *)pDevice,
-                      (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates,
-                      (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates,
-                      true,
-                      &(pMgmt->sNodeDBTable[0].wMaxBasicRate),
-                      &(pMgmt->sNodeDBTable[0].wMaxSuppRate),
-                       &(pMgmt->sNodeDBTable[0].wSuppRate),
-                      &(pMgmt->sNodeDBTable[0].byTopCCKBasicRate),
-                      &(pMgmt->sNodeDBTable[0].byTopOFDMBasicRate)
-                     );
-    pMgmt->sNodeDBTable[0].wTxDataRate = pMgmt->sNodeDBTable[0].wMaxBasicRate;
+	PSDevice     pDevice = (PSDevice)hDeviceContext;
+	PSMgmtObject    pMgmt = pDevice->pMgmt;
+
+	if (!pDevice->bEnableHostWEP)
+		memset(&pMgmt->sNodeDBTable[0], 0, sizeof(KnownNodeDB));
+	memset(pMgmt->sNodeDBTable[0].abyMACAddr, 0xff, WLAN_ADDR_LEN);
+	pMgmt->sNodeDBTable[0].bActive = true;
+	pMgmt->sNodeDBTable[0].bPSEnable = false;
+	skb_queue_head_init(&pMgmt->sNodeDBTable[0].sTxPSQueue);
+	RATEvParseMaxRate((void *)pDevice,
+			  (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates,
+			  (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates,
+			  true,
+			  &(pMgmt->sNodeDBTable[0].wMaxBasicRate),
+			  &(pMgmt->sNodeDBTable[0].wMaxSuppRate),
+			  &(pMgmt->sNodeDBTable[0].wSuppRate),
+			  &(pMgmt->sNodeDBTable[0].byTopCCKBasicRate),
+			  &(pMgmt->sNodeDBTable[0].byTopOFDMBasicRate)
+);
+	pMgmt->sNodeDBTable[0].wTxDataRate = pMgmt->sNodeDBTable[0].wMaxBasicRate;
 #ifdef	PLICE_DEBUG
-	printk("BSSvAddMultiCastNode:pMgmt->sNodeDBTable[0].wTxDataRate is %d\n",pMgmt->sNodeDBTable[0].wTxDataRate);
+	printk("BSSvAddMultiCastNode:pMgmt->sNodeDBTable[0].wTxDataRate is %d\n", pMgmt->sNodeDBTable[0].wTxDataRate);
 #endif
-    pMgmt->sNodeDBTable[0].uRatePollTimeout = FALLBACK_POLL_SECOND;
-
+	pMgmt->sNodeDBTable[0].uRatePollTimeout = FALLBACK_POLL_SECOND;
 };
 
-
-
-
-
 /*+
  *
  * Routine Description:
@@ -996,373 +940,348 @@ BSSvAddMulticastNode(
  * Return Value:
  *    none.
  *
--*/
- //2008-4-14 <add> by chester for led issue
- #ifdef FOR_LED_ON_NOTEBOOK
-bool cc=false;
+ -*/
+//2008-4-14 <add> by chester for led issue
+#ifdef FOR_LED_ON_NOTEBOOK
+bool cc = false;
 unsigned int status;
 #endif
 void
 BSSvSecondCallBack(
-    void *hDeviceContext
-    )
+	void *hDeviceContext
+)
 {
-    PSDevice        pDevice = (PSDevice)hDeviceContext;
-    PSMgmtObject    pMgmt = pDevice->pMgmt;
-    unsigned int ii;
-    PWLAN_IE_SSID   pItemSSID, pCurrSSID;
-    unsigned int uSleepySTACnt = 0;
-    unsigned int uNonShortSlotSTACnt = 0;
-    unsigned int uLongPreambleSTACnt = 0;
-    viawget_wpa_header* wpahdr;  //DavidWang
-
-    spin_lock_irq(&pDevice->lock);
-
-    pDevice->uAssocCount = 0;
-
-    pDevice->byERPFlag &=
-        ~(WLAN_SET_ERP_BARKER_MODE(1) | WLAN_SET_ERP_NONERP_PRESENT(1));
- //2008-4-14 <add> by chester for led issue
+	PSDevice        pDevice = (PSDevice)hDeviceContext;
+	PSMgmtObject    pMgmt = pDevice->pMgmt;
+	unsigned int ii;
+	PWLAN_IE_SSID   pItemSSID, pCurrSSID;
+	unsigned int uSleepySTACnt = 0;
+	unsigned int uNonShortSlotSTACnt = 0;
+	unsigned int uLongPreambleSTACnt = 0;
+	viawget_wpa_header *wpahdr;  //DavidWang
+
+	spin_lock_irq(&pDevice->lock);
+
+	pDevice->uAssocCount = 0;
+
+	pDevice->byERPFlag &=
+		~(WLAN_SET_ERP_BARKER_MODE(1) | WLAN_SET_ERP_NONERP_PRESENT(1));
+	//2008-4-14 <add> by chester for led issue
 #ifdef FOR_LED_ON_NOTEBOOK
-MACvGPIOIn(pDevice->PortOffset, &pDevice->byGPIO);
-if ((( !(pDevice->byGPIO & GPIO0_DATA)&&(pDevice->bHWRadioOff == false))||((pDevice->byGPIO & GPIO0_DATA)&&(pDevice->bHWRadioOff == true)))&&(cc==false)){
-cc=true;
-}
-else if(cc==true){
-
-if(pDevice->bHWRadioOff == true){
-            if ( !(pDevice->byGPIO & GPIO0_DATA))
-//||( !(pDevice->byGPIO & GPIO0_DATA) && (pDevice->byRadioCtl & EEP_RADIOCTL_INV)))
-{if(status==1) goto start;
-status=1;
-CARDbRadioPowerOff(pDevice);
-                pMgmt->sNodeDBTable[0].bActive = false;
-                pMgmt->eCurrMode = WMAC_MODE_STANDBY;
-                pMgmt->eCurrState = WMAC_STATE_IDLE;
-                //netif_stop_queue(pDevice->dev);
-                pDevice->bLinkPass = false;
-
-}
-  if (pDevice->byGPIO &GPIO0_DATA)
-//||( !(pDevice->byGPIO & GPIO0_DATA) && (pDevice->byRadioCtl & EEP_RADIOCTL_INV)))
-{if(status==2) goto start;
-status=2;
-CARDbRadioPowerOn(pDevice);
-} }
-else{
-            if (pDevice->byGPIO & GPIO0_DATA)
-//||( !(pDevice->byGPIO & GPIO0_DATA) && (pDevice->byRadioCtl & EEP_RADIOCTL_INV)))
-{if(status==3) goto start;
-status=3;
-CARDbRadioPowerOff(pDevice);
-                pMgmt->sNodeDBTable[0].bActive = false;
-                pMgmt->eCurrMode = WMAC_MODE_STANDBY;
-                pMgmt->eCurrState = WMAC_STATE_IDLE;
-                //netif_stop_queue(pDevice->dev);
-                pDevice->bLinkPass = false;
-
-}
-  if ( !(pDevice->byGPIO & GPIO0_DATA))
-//||( !(pDevice->byGPIO & GPIO0_DATA) && (pDevice->byRadioCtl & EEP_RADIOCTL_INV)))
-{if(status==4) goto start;
-status=4;
-CARDbRadioPowerOn(pDevice);
-} }
-}
+	MACvGPIOIn(pDevice->PortOffset, &pDevice->byGPIO);
+	if (((!(pDevice->byGPIO & GPIO0_DATA) && (pDevice->bHWRadioOff == false)) || ((pDevice->byGPIO & GPIO0_DATA) && (pDevice->bHWRadioOff == true))) && (cc == false)) {
+		cc = true;
+	} else if (cc == true) {
+		if (pDevice->bHWRadioOff == true) {
+			if (!(pDevice->byGPIO & GPIO0_DATA))
+//||(!(pDevice->byGPIO & GPIO0_DATA) && (pDevice->byRadioCtl & EEP_RADIOCTL_INV)))
+			{
+				if (status == 1) goto start;
+				status = 1;
+				CARDbRadioPowerOff(pDevice);
+				pMgmt->sNodeDBTable[0].bActive = false;
+				pMgmt->eCurrMode = WMAC_MODE_STANDBY;
+				pMgmt->eCurrState = WMAC_STATE_IDLE;
+				//netif_stop_queue(pDevice->dev);
+				pDevice->bLinkPass = false;
+
+			}
+			if (pDevice->byGPIO & GPIO0_DATA)
+//||(!(pDevice->byGPIO & GPIO0_DATA) && (pDevice->byRadioCtl & EEP_RADIOCTL_INV)))
+			{
+				if (status == 2) goto start;
+				status = 2;
+				CARDbRadioPowerOn(pDevice);
+			}
+		} else {
+			if (pDevice->byGPIO & GPIO0_DATA)
+//||(!(pDevice->byGPIO & GPIO0_DATA) && (pDevice->byRadioCtl & EEP_RADIOCTL_INV)))
+			{
+				if (status == 3) goto start;
+				status = 3;
+				CARDbRadioPowerOff(pDevice);
+				pMgmt->sNodeDBTable[0].bActive = false;
+				pMgmt->eCurrMode = WMAC_MODE_STANDBY;
+				pMgmt->eCurrState = WMAC_STATE_IDLE;
+				//netif_stop_queue(pDevice->dev);
+				pDevice->bLinkPass = false;
+
+			}
+			if (!(pDevice->byGPIO & GPIO0_DATA))
+//||(!(pDevice->byGPIO & GPIO0_DATA) && (pDevice->byRadioCtl & EEP_RADIOCTL_INV)))
+			{
+				if (status == 4) goto start;
+				status = 4;
+				CARDbRadioPowerOn(pDevice);
+			}
+		}
+	}
 start:
 #endif
 
-
-    if (pDevice->wUseProtectCntDown > 0) {
-        pDevice->wUseProtectCntDown --;
-    }
-    else {
-        // disable protect mode
-        pDevice->byERPFlag &= ~(WLAN_SET_ERP_USE_PROTECTION(1));
-    }
-
-{
-       pDevice->byReAssocCount++;
-   if((pDevice->byReAssocCount > 10) && (pDevice->bLinkPass != true)) {  //10 sec timeout
-                     printk("Re-association timeout!!!\n");
-		   pDevice->byReAssocCount = 0;
-                     #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
-                    // if(pDevice->bWPASuppWextEnabled == true)
-                        {
-                  	union iwreq_data  wrqu;
-                  	memset(&wrqu, 0, sizeof (wrqu));
-                          wrqu.ap_addr.sa_family = ARPHRD_ETHER;
-                  	PRINT_K("wireless_send_event--->SIOCGIWAP(disassociated)\n");
-                  	wireless_send_event(pDevice->dev, SIOCGIWAP, &wrqu, NULL);
-                       }
-                    #endif
-     }
-   else if(pDevice->bLinkPass == true)
-   	pDevice->byReAssocCount = 0;
-}
+	if (pDevice->wUseProtectCntDown > 0) {
+		pDevice->wUseProtectCntDown--;
+	} else {
+		// disable protect mode
+		pDevice->byERPFlag &= ~(WLAN_SET_ERP_USE_PROTECTION(1));
+	}
+
+	{
+		pDevice->byReAssocCount++;
+		if ((pDevice->byReAssocCount > 10) && (pDevice->bLinkPass != true)) {  //10 sec timeout
+			printk("Re-association timeout!!!\n");
+			pDevice->byReAssocCount = 0;
+#ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
+			{
+				union iwreq_data  wrqu;
+				memset(&wrqu, 0, sizeof(wrqu));
+				wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+				PRINT_K("wireless_send_event--->SIOCGIWAP(disassociated)\n");
+				wireless_send_event(pDevice->dev, SIOCGIWAP, &wrqu, NULL);
+			}
+#endif
+		} else if (pDevice->bLinkPass == true)
+			pDevice->byReAssocCount = 0;
+	}
 
 #ifdef Calcu_LinkQual
-   s_uCalculateLinkQual((void *)pDevice);
+	s_uCalculateLinkQual((void *)pDevice);
 #endif
 
-    for (ii = 0; ii < (MAX_NODE_NUM + 1); ii++) {
-
-        if (pMgmt->sNodeDBTable[ii].bActive) {
-            // Increase in-activity counter
-            pMgmt->sNodeDBTable[ii].uInActiveCount++;
-
-            if (ii > 0) {
-                if (pMgmt->sNodeDBTable[ii].uInActiveCount > MAX_INACTIVE_COUNT) {
-                    BSSvRemoveOneNode(pDevice, ii);
-                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
-                        "Inactive timeout [%d] sec, STA index = [%d] remove\n", MAX_INACTIVE_COUNT, ii);
-                    continue;
-                }
-
-                if (pMgmt->sNodeDBTable[ii].eNodeState >= NODE_ASSOC) {
-
-                    pDevice->uAssocCount++;
-
-                    // check if Non ERP exist
-                    if (pMgmt->sNodeDBTable[ii].uInActiveCount < ERP_RECOVER_COUNT) {
-                        if (!pMgmt->sNodeDBTable[ii].bShortPreamble) {
-                            pDevice->byERPFlag |= WLAN_SET_ERP_BARKER_MODE(1);
-                            uLongPreambleSTACnt ++;
-                        }
-                        if (!pMgmt->sNodeDBTable[ii].bERPExist) {
-                            pDevice->byERPFlag |= WLAN_SET_ERP_NONERP_PRESENT(1);
-                            pDevice->byERPFlag |= WLAN_SET_ERP_USE_PROTECTION(1);
-                        }
-                        if (!pMgmt->sNodeDBTable[ii].bShortSlotTime)
-                            uNonShortSlotSTACnt++;
-                    }
-                }
+	for (ii = 0; ii < (MAX_NODE_NUM + 1); ii++) {
+		if (pMgmt->sNodeDBTable[ii].bActive) {
+			// Increase in-activity counter
+			pMgmt->sNodeDBTable[ii].uInActiveCount++;
+
+			if (ii > 0) {
+				if (pMgmt->sNodeDBTable[ii].uInActiveCount > MAX_INACTIVE_COUNT) {
+					BSSvRemoveOneNode(pDevice, ii);
+					DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
+						"Inactive timeout [%d] sec, STA index = [%d] remove\n", MAX_INACTIVE_COUNT, ii);
+					continue;
+				}
 
-                // check if any STA in PS mode
-                if (pMgmt->sNodeDBTable[ii].bPSEnable)
-                    uSleepySTACnt++;
+				if (pMgmt->sNodeDBTable[ii].eNodeState >= NODE_ASSOC) {
+					pDevice->uAssocCount++;
+
+					// check if Non ERP exist
+					if (pMgmt->sNodeDBTable[ii].uInActiveCount < ERP_RECOVER_COUNT) {
+						if (!pMgmt->sNodeDBTable[ii].bShortPreamble) {
+							pDevice->byERPFlag |= WLAN_SET_ERP_BARKER_MODE(1);
+							uLongPreambleSTACnt++;
+						}
+						if (!pMgmt->sNodeDBTable[ii].bERPExist) {
+							pDevice->byERPFlag |= WLAN_SET_ERP_NONERP_PRESENT(1);
+							pDevice->byERPFlag |= WLAN_SET_ERP_USE_PROTECTION(1);
+						}
+						if (!pMgmt->sNodeDBTable[ii].bShortSlotTime)
+							uNonShortSlotSTACnt++;
+					}
+				}
 
+				// check if any STA in PS mode
+				if (pMgmt->sNodeDBTable[ii].bPSEnable)
+					uSleepySTACnt++;
 
-            }
+			}
 
-            // Rate fallback check
-            if (!pDevice->bFixRate) {
+			// Rate fallback check
+			if (!pDevice->bFixRate) {
 /*
-                if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && (ii == 0))
-                    RATEvTxRateFallBack(pDevice, &(pMgmt->sNodeDBTable[ii]));
+  if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && (ii == 0))
+  RATEvTxRateFallBack(pDevice, &(pMgmt->sNodeDBTable[ii]));
 */
-                if (ii > 0) {
-                    // ii = 0 for multicast node (AP & Adhoc)
-                    RATEvTxRateFallBack((void *)pDevice, &(pMgmt->sNodeDBTable[ii]));
-                }
-                else {
-                    // ii = 0 reserved for unicast AP node (Infra STA)
-                    if (pMgmt->eCurrMode == WMAC_MODE_ESS_STA)
+				if (ii > 0) {
+					// ii = 0 for multicast node (AP & Adhoc)
+					RATEvTxRateFallBack((void *)pDevice, &(pMgmt->sNodeDBTable[ii]));
+				} else {
+					// ii = 0 reserved for unicast AP node (Infra STA)
+					if (pMgmt->eCurrMode == WMAC_MODE_ESS_STA)
 #ifdef	PLICE_DEBUG
-		printk("SecondCallback:Before:TxDataRate is %d\n",pMgmt->sNodeDBTable[0].wTxDataRate);
+						printk("SecondCallback:Before:TxDataRate is %d\n", pMgmt->sNodeDBTable[0].wTxDataRate);
 #endif
-                        RATEvTxRateFallBack((void *)pDevice, &(pMgmt->sNodeDBTable[ii]));
+					RATEvTxRateFallBack((void *)pDevice, &(pMgmt->sNodeDBTable[ii]));
 #ifdef	PLICE_DEBUG
-		printk("SecondCallback:After:TxDataRate is %d\n",pMgmt->sNodeDBTable[0].wTxDataRate);
+					printk("SecondCallback:After:TxDataRate is %d\n", pMgmt->sNodeDBTable[0].wTxDataRate);
 #endif
 
+				}
+
+			}
+
+			// check if pending PS queue
+			if (pMgmt->sNodeDBTable[ii].wEnQueueCnt != 0) {
+				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Index= %d, Queue = %d pending \n",
+					ii, pMgmt->sNodeDBTable[ii].wEnQueueCnt);
+				if ((ii > 0) && (pMgmt->sNodeDBTable[ii].wEnQueueCnt > 15)) {
+					BSSvRemoveOneNode(pDevice, ii);
+					DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Pending many queues PS STA Index = %d remove \n", ii);
+					continue;
+				}
+			}
 		}
 
-            }
-
-            // check if pending PS queue
-            if (pMgmt->sNodeDBTable[ii].wEnQueueCnt != 0) {
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Index= %d, Queue = %d pending \n",
-                           ii, pMgmt->sNodeDBTable[ii].wEnQueueCnt);
-                if ((ii >0) && (pMgmt->sNodeDBTable[ii].wEnQueueCnt > 15)) {
-                    BSSvRemoveOneNode(pDevice, ii);
-                    DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Pending many queues PS STA Index = %d remove \n", ii);
-                    continue;
-                }
-            }
-        }
-
-    }
-
-
-    if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) && (pDevice->eCurrentPHYType == PHY_TYPE_11G)) {
-
-        // on/off protect mode
-        if (WLAN_GET_ERP_USE_PROTECTION(pDevice->byERPFlag)) {
-            if (!pDevice->bProtectMode) {
-                MACvEnableProtectMD(pDevice->PortOffset);
-                pDevice->bProtectMode = true;
-            }
-        }
-        else {
-            if (pDevice->bProtectMode) {
-                MACvDisableProtectMD(pDevice->PortOffset);
-                pDevice->bProtectMode = false;
-            }
-        }
-        // on/off short slot time
-
-        if (uNonShortSlotSTACnt > 0) {
-            if (pDevice->bShortSlotTime) {
-                pDevice->bShortSlotTime = false;
-                BBvSetShortSlotTime(pDevice);
-                vUpdateIFS((void *)pDevice);
-            }
-        }
-        else {
-            if (!pDevice->bShortSlotTime) {
-                pDevice->bShortSlotTime = true;
-                BBvSetShortSlotTime(pDevice);
-                vUpdateIFS((void *)pDevice);
-            }
-        }
-
-        // on/off barker long preamble mode
-
-        if (uLongPreambleSTACnt > 0) {
-            if (!pDevice->bBarkerPreambleMd) {
-                MACvEnableBarkerPreambleMd(pDevice->PortOffset);
-                pDevice->bBarkerPreambleMd = true;
-            }
-        }
-        else {
-            if (pDevice->bBarkerPreambleMd) {
-                MACvDisableBarkerPreambleMd(pDevice->PortOffset);
-                pDevice->bBarkerPreambleMd = false;
-            }
-        }
-
-    }
-
-
-    // Check if any STA in PS mode, enable DTIM multicast deliver
-    if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) {
-        if (uSleepySTACnt > 0)
-            pMgmt->sNodeDBTable[0].bPSEnable = true;
-        else
-            pMgmt->sNodeDBTable[0].bPSEnable = false;
-    }
-
-    pItemSSID = (PWLAN_IE_SSID)pMgmt->abyDesireSSID;
-    pCurrSSID = (PWLAN_IE_SSID)pMgmt->abyCurrSSID;
-
-    if ((pMgmt->eCurrMode == WMAC_MODE_STANDBY) ||
-        (pMgmt->eCurrMode == WMAC_MODE_ESS_STA)) {
-
-        if (pMgmt->sNodeDBTable[0].bActive) { // Assoc with BSS
-           // DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "Callback inactive Count = [%d]\n", pMgmt->sNodeDBTable[0].uInActiveCount);
-            //if (pDevice->bUpdateBBVGA) {
-            //  s_vCheckSensitivity((void *) pDevice);
-            //}
-
-            if (pDevice->bUpdateBBVGA) {
-               // s_vCheckSensitivity((void *) pDevice);
-               s_vCheckPreEDThreshold((void *)pDevice);
-            }
-
-    	    if ((pMgmt->sNodeDBTable[0].uInActiveCount >= (LOST_BEACON_COUNT/2)) &&
-    	        (pDevice->byBBVGACurrent != pDevice->abyBBVGA[0]) ) {
-    	        pDevice->byBBVGANew = pDevice->abyBBVGA[0];
-                bScheduleCommand((void *) pDevice, WLAN_CMD_CHANGE_BBSENSITIVITY, NULL);
-    	    }
-
-        	if (pMgmt->sNodeDBTable[0].uInActiveCount >= LOST_BEACON_COUNT) {
-                pMgmt->sNodeDBTable[0].bActive = false;
-                pMgmt->eCurrMode = WMAC_MODE_STANDBY;
-                pMgmt->eCurrState = WMAC_STATE_IDLE;
-                netif_stop_queue(pDevice->dev);
-                pDevice->bLinkPass = false;
-                pDevice->bRoaming = true;
-                DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Lost AP beacon [%d] sec, disconnected !\n", pMgmt->sNodeDBTable[0].uInActiveCount);
-        if ((pDevice->bWPADEVUp) && (pDevice->skb != NULL)) {
-             wpahdr = (viawget_wpa_header *)pDevice->skb->data;
-             wpahdr->type = VIAWGET_DISASSOC_MSG;
-             wpahdr->resp_ie_len = 0;
-             wpahdr->req_ie_len = 0;
-             skb_put(pDevice->skb, sizeof(viawget_wpa_header));
-             pDevice->skb->dev = pDevice->wpadev;
-	     skb_reset_mac_header(pDevice->skb);
-             pDevice->skb->pkt_type = PACKET_HOST;
-             pDevice->skb->protocol = htons(ETH_P_802_2);
-             memset(pDevice->skb->cb, 0, sizeof(pDevice->skb->cb));
-             netif_rx(pDevice->skb);
-             pDevice->skb = dev_alloc_skb((int)pDevice->rx_buf_sz);
-         }
-   #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
-  // if(pDevice->bWPASuppWextEnabled == true)
-      {
-	union iwreq_data  wrqu;
-	memset(&wrqu, 0, sizeof (wrqu));
-        wrqu.ap_addr.sa_family = ARPHRD_ETHER;
-	PRINT_K("wireless_send_event--->SIOCGIWAP(disassociated)\n");
-	wireless_send_event(pDevice->dev, SIOCGIWAP, &wrqu, NULL);
-     }
-  #endif
-	    }
-        }
-        else if (pItemSSID->len != 0) {
-            if (pDevice->uAutoReConnectTime < 10) {
-                pDevice->uAutoReConnectTime++;
-	       #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
-                //network manager support need not do Roaming scan???
-                if(pDevice->bWPASuppWextEnabled ==true)
-		 pDevice->uAutoReConnectTime = 0;
-	     #endif
-            }
-            else {
-	   //mike use old encryption status for wpa reauthen
-	      if(pDevice->bWPADEVUp)
-	          pDevice->eEncryptionStatus = pDevice->eOldEncryptionStatus;
-
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Roaming ...\n");
-                BSSvClearBSSList((void *)pDevice, pDevice->bLinkPass);
- 	      pMgmt->eScanType = WMAC_SCAN_ACTIVE;
-                bScheduleCommand((void *) pDevice, WLAN_CMD_BSSID_SCAN, pMgmt->abyDesireSSID);
-                bScheduleCommand((void *) pDevice, WLAN_CMD_SSID, pMgmt->abyDesireSSID);
-                pDevice->uAutoReConnectTime = 0;
-            }
-        }
-    }
-
-    if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) {
-        // if adhoc started which essid is NULL string, rescanning.
-        if ((pMgmt->eCurrState == WMAC_STATE_STARTED) && (pCurrSSID->len == 0)) {
-            if (pDevice->uAutoReConnectTime < 10) {
-                pDevice->uAutoReConnectTime++;
-            }
-            else {
-                DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Adhoc re-scanning ...\n");
-	      pMgmt->eScanType = WMAC_SCAN_ACTIVE;
-                bScheduleCommand((void *) pDevice, WLAN_CMD_BSSID_SCAN, NULL);
-                bScheduleCommand((void *) pDevice, WLAN_CMD_SSID, NULL);
-                pDevice->uAutoReConnectTime = 0;
-            };
-        }
-        if (pMgmt->eCurrState == WMAC_STATE_JOINTED) {
-
-            if (pDevice->bUpdateBBVGA) {
-               //s_vCheckSensitivity((void *) pDevice);
-               s_vCheckPreEDThreshold((void *)pDevice);
-            }
-        	if (pMgmt->sNodeDBTable[0].uInActiveCount >=ADHOC_LOST_BEACON_COUNT) {
-        	    DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Lost other STA beacon [%d] sec, started !\n", pMgmt->sNodeDBTable[0].uInActiveCount);
-                pMgmt->sNodeDBTable[0].uInActiveCount = 0;
-                pMgmt->eCurrState = WMAC_STATE_STARTED;
-                netif_stop_queue(pDevice->dev);
-                pDevice->bLinkPass = false;
-            }
-        }
-    }
-
-    spin_unlock_irq(&pDevice->lock);
-
-    pMgmt->sTimerSecondCallback.expires = RUN_AT(HZ);
-    add_timer(&pMgmt->sTimerSecondCallback);
-    return;
-}
+	}
+
+	if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) && (pDevice->eCurrentPHYType == PHY_TYPE_11G)) {
+		// on/off protect mode
+		if (WLAN_GET_ERP_USE_PROTECTION(pDevice->byERPFlag)) {
+			if (!pDevice->bProtectMode) {
+				MACvEnableProtectMD(pDevice->PortOffset);
+				pDevice->bProtectMode = true;
+			}
+		} else {
+			if (pDevice->bProtectMode) {
+				MACvDisableProtectMD(pDevice->PortOffset);
+				pDevice->bProtectMode = false;
+			}
+		}
+		// on/off short slot time
+
+		if (uNonShortSlotSTACnt > 0) {
+			if (pDevice->bShortSlotTime) {
+				pDevice->bShortSlotTime = false;
+				BBvSetShortSlotTime(pDevice);
+				vUpdateIFS((void *)pDevice);
+			}
+		} else {
+			if (!pDevice->bShortSlotTime) {
+				pDevice->bShortSlotTime = true;
+				BBvSetShortSlotTime(pDevice);
+				vUpdateIFS((void *)pDevice);
+			}
+		}
+
+		// on/off barker long preamble mode
+
+		if (uLongPreambleSTACnt > 0) {
+			if (!pDevice->bBarkerPreambleMd) {
+				MACvEnableBarkerPreambleMd(pDevice->PortOffset);
+				pDevice->bBarkerPreambleMd = true;
+			}
+		} else {
+			if (pDevice->bBarkerPreambleMd) {
+				MACvDisableBarkerPreambleMd(pDevice->PortOffset);
+				pDevice->bBarkerPreambleMd = false;
+			}
+		}
 
+	}
+
+	// Check if any STA in PS mode, enable DTIM multicast deliver
+	if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) {
+		if (uSleepySTACnt > 0)
+			pMgmt->sNodeDBTable[0].bPSEnable = true;
+		else
+			pMgmt->sNodeDBTable[0].bPSEnable = false;
+	}
+
+	pItemSSID = (PWLAN_IE_SSID)pMgmt->abyDesireSSID;
+	pCurrSSID = (PWLAN_IE_SSID)pMgmt->abyCurrSSID;
+
+	if ((pMgmt->eCurrMode == WMAC_MODE_STANDBY) ||
+	    (pMgmt->eCurrMode == WMAC_MODE_ESS_STA)) {
+		if (pMgmt->sNodeDBTable[0].bActive) { // Assoc with BSS
+			if (pDevice->bUpdateBBVGA) {
+				// s_vCheckSensitivity((void *) pDevice);
+				s_vCheckPreEDThreshold((void *)pDevice);
+			}
+
+			if ((pMgmt->sNodeDBTable[0].uInActiveCount >= (LOST_BEACON_COUNT/2)) &&
+			    (pDevice->byBBVGACurrent != pDevice->abyBBVGA[0])) {
+				pDevice->byBBVGANew = pDevice->abyBBVGA[0];
+				bScheduleCommand((void *)pDevice, WLAN_CMD_CHANGE_BBSENSITIVITY, NULL);
+			}
+
+			if (pMgmt->sNodeDBTable[0].uInActiveCount >= LOST_BEACON_COUNT) {
+				pMgmt->sNodeDBTable[0].bActive = false;
+				pMgmt->eCurrMode = WMAC_MODE_STANDBY;
+				pMgmt->eCurrState = WMAC_STATE_IDLE;
+				netif_stop_queue(pDevice->dev);
+				pDevice->bLinkPass = false;
+				pDevice->bRoaming = true;
+				DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Lost AP beacon [%d] sec, disconnected !\n", pMgmt->sNodeDBTable[0].uInActiveCount);
+				if ((pDevice->bWPADEVUp) && (pDevice->skb != NULL)) {
+					wpahdr = (viawget_wpa_header *)pDevice->skb->data;
+					wpahdr->type = VIAWGET_DISASSOC_MSG;
+					wpahdr->resp_ie_len = 0;
+					wpahdr->req_ie_len = 0;
+					skb_put(pDevice->skb, sizeof(viawget_wpa_header));
+					pDevice->skb->dev = pDevice->wpadev;
+					skb_reset_mac_header(pDevice->skb);
+					pDevice->skb->pkt_type = PACKET_HOST;
+					pDevice->skb->protocol = htons(ETH_P_802_2);
+					memset(pDevice->skb->cb, 0, sizeof(pDevice->skb->cb));
+					netif_rx(pDevice->skb);
+					pDevice->skb = dev_alloc_skb((int)pDevice->rx_buf_sz);
+				}
+#ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
+				{
+					union iwreq_data  wrqu;
+					memset(&wrqu, 0, sizeof(wrqu));
+					wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+					PRINT_K("wireless_send_event--->SIOCGIWAP(disassociated)\n");
+					wireless_send_event(pDevice->dev, SIOCGIWAP, &wrqu, NULL);
+				}
+#endif
+			}
+		} else if (pItemSSID->len != 0) {
+			if (pDevice->uAutoReConnectTime < 10) {
+				pDevice->uAutoReConnectTime++;
+#ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
+				//network manager support need not do Roaming scan???
+				if (pDevice->bWPASuppWextEnabled == true)
+					pDevice->uAutoReConnectTime = 0;
+#endif
+			} else {
+				//mike use old encryption status for wpa reauthen
+				if (pDevice->bWPADEVUp)
+					pDevice->eEncryptionStatus = pDevice->eOldEncryptionStatus;
+
+				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Roaming ...\n");
+				BSSvClearBSSList((void *)pDevice, pDevice->bLinkPass);
+				pMgmt->eScanType = WMAC_SCAN_ACTIVE;
+				bScheduleCommand((void *)pDevice, WLAN_CMD_BSSID_SCAN, pMgmt->abyDesireSSID);
+				bScheduleCommand((void *)pDevice, WLAN_CMD_SSID, pMgmt->abyDesireSSID);
+				pDevice->uAutoReConnectTime = 0;
+			}
+		}
+	}
+
+	if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) {
+		// if adhoc started which essid is NULL string, rescanning.
+		if ((pMgmt->eCurrState == WMAC_STATE_STARTED) && (pCurrSSID->len == 0)) {
+			if (pDevice->uAutoReConnectTime < 10) {
+				pDevice->uAutoReConnectTime++;
+			} else {
+				DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Adhoc re-scanning ...\n");
+				pMgmt->eScanType = WMAC_SCAN_ACTIVE;
+				bScheduleCommand((void *)pDevice, WLAN_CMD_BSSID_SCAN, NULL);
+				bScheduleCommand((void *)pDevice, WLAN_CMD_SSID, NULL);
+				pDevice->uAutoReConnectTime = 0;
+			};
+		}
+		if (pMgmt->eCurrState == WMAC_STATE_JOINTED) {
+			if (pDevice->bUpdateBBVGA) {
+				//s_vCheckSensitivity((void *) pDevice);
+				s_vCheckPreEDThreshold((void *)pDevice);
+			}
+			if (pMgmt->sNodeDBTable[0].uInActiveCount >= ADHOC_LOST_BEACON_COUNT) {
+				DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Lost other STA beacon [%d] sec, started !\n", pMgmt->sNodeDBTable[0].uInActiveCount);
+				pMgmt->sNodeDBTable[0].uInActiveCount = 0;
+				pMgmt->eCurrState = WMAC_STATE_STARTED;
+				netif_stop_queue(pDevice->dev);
+				pDevice->bLinkPass = false;
+			}
+		}
+	}
 
+	spin_unlock_irq(&pDevice->lock);
 
+	pMgmt->sTimerSecondCallback.expires = RUN_AT(HZ);
+	add_timer(&pMgmt->sTimerSecondCallback);
+	return;
+}
 
 /*+
  *
@@ -1375,184 +1294,162 @@ start:
  * Return Value:
  *    none.
  *
--*/
-
-
+ -*/
 
 void
 BSSvUpdateNodeTxCounter(
-    void *hDeviceContext,
-    unsigned char byTsr0,
-    unsigned char byTsr1,
-    unsigned char *pbyBuffer,
-    unsigned int uFIFOHeaderSize
-    )
+	void *hDeviceContext,
+	unsigned char byTsr0,
+	unsigned char byTsr1,
+	unsigned char *pbyBuffer,
+	unsigned int uFIFOHeaderSize
+)
 {
-    PSDevice        pDevice = (PSDevice)hDeviceContext;
-    PSMgmtObject    pMgmt = pDevice->pMgmt;
-    unsigned int uNodeIndex = 0;
-    unsigned char byTxRetry = (byTsr0 & TSR0_NCR);
-    PSTxBufHead     pTxBufHead;
-    PS802_11Header  pMACHeader;
-    unsigned short wRate;
-    unsigned short wFallBackRate = RATE_1M;
-    unsigned char byFallBack;
-    unsigned int ii;
+	PSDevice        pDevice = (PSDevice)hDeviceContext;
+	PSMgmtObject    pMgmt = pDevice->pMgmt;
+	unsigned int uNodeIndex = 0;
+	unsigned char byTxRetry = (byTsr0 & TSR0_NCR);
+	PSTxBufHead     pTxBufHead;
+	PS802_11Header  pMACHeader;
+	unsigned short wRate;
+	unsigned short wFallBackRate = RATE_1M;
+	unsigned char byFallBack;
+	unsigned int ii;
 //	unsigned int txRetryTemp;
 //PLICE_DEBUG->
 	//txRetryTemp = byTxRetry;
-	//if (txRetryTemp== 8)
-	//txRetryTemp -=3;
 //PLICE_DEBUG <-
-    pTxBufHead = (PSTxBufHead) pbyBuffer;
-    if (pTxBufHead->wFIFOCtl & FIFOCTL_AUTO_FB_0) {
-        byFallBack = AUTO_FB_0;
-    } else if (pTxBufHead->wFIFOCtl & FIFOCTL_AUTO_FB_1) {
-        byFallBack = AUTO_FB_1;
-    } else {
-        byFallBack = AUTO_FB_NONE;
-    }
-    wRate = pTxBufHead->wReserved; //?wRate
-    //printk("BSSvUpdateNodeTxCounter:byTxRetry is %d\n",byTxRetry);
-
-//printk("BSSvUpdateNodeTx:wRate is %d,byFallback is %d\n",wRate,byFallBack);
-//#ifdef	PLICE_DEBUG
-	//printk("BSSvUpdateNodeTx: wRate is %d\n",wRate);
-////#endif
-    // Only Unicast using support rates
-    if (pTxBufHead->wFIFOCtl & FIFOCTL_NEEDACK) {
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"wRate %04X, byTsr0 %02X, byTsr1 %02X\n", wRate, byTsr0, byTsr1);
-        if (pMgmt->eCurrMode == WMAC_MODE_ESS_STA) {
-            pMgmt->sNodeDBTable[0].uTxAttempts += 1;
-            if ((byTsr1 & TSR1_TERR) == 0) {
-                // transmit success, TxAttempts at least plus one
-                pMgmt->sNodeDBTable[0].uTxOk[MAX_RATE]++;
-                if ( (byFallBack == AUTO_FB_NONE) ||
-                     (wRate < RATE_18M) ) {
-                    wFallBackRate = wRate;
-                } else if (byFallBack == AUTO_FB_0) {
+	pTxBufHead = (PSTxBufHead) pbyBuffer;
+	if (pTxBufHead->wFIFOCtl & FIFOCTL_AUTO_FB_0) {
+		byFallBack = AUTO_FB_0;
+	} else if (pTxBufHead->wFIFOCtl & FIFOCTL_AUTO_FB_1) {
+		byFallBack = AUTO_FB_1;
+	} else {
+		byFallBack = AUTO_FB_NONE;
+	}
+	wRate = pTxBufHead->wReserved; //?wRate
+
+	// Only Unicast using support rates
+	if (pTxBufHead->wFIFOCtl & FIFOCTL_NEEDACK) {
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wRate %04X, byTsr0 %02X, byTsr1 %02X\n", wRate, byTsr0, byTsr1);
+		if (pMgmt->eCurrMode == WMAC_MODE_ESS_STA) {
+			pMgmt->sNodeDBTable[0].uTxAttempts += 1;
+			if ((byTsr1 & TSR1_TERR) == 0) {
+				// transmit success, TxAttempts at least plus one
+				pMgmt->sNodeDBTable[0].uTxOk[MAX_RATE]++;
+				if ((byFallBack == AUTO_FB_NONE) ||
+				    (wRate < RATE_18M)) {
+					wFallBackRate = wRate;
+				} else if (byFallBack == AUTO_FB_0) {
 //PLICE_DEBUG
-				  if (byTxRetry < 5)
-				//if (txRetryTemp < 5)
-					wFallBackRate = awHWRetry0[wRate-RATE_18M][byTxRetry];
-			//wFallBackRate = awHWRetry0[wRate-RATE_12M][byTxRetry];
-			//wFallBackRate = awHWRetry0[wRate-RATE_18M][txRetryTemp] +1;
-		else
-                        wFallBackRate = awHWRetry0[wRate-RATE_18M][4];
-			//wFallBackRate = awHWRetry0[wRate-RATE_12M][4];
-		} else if (byFallBack == AUTO_FB_1) {
-                    if (byTxRetry < 5)
-                        wFallBackRate = awHWRetry1[wRate-RATE_18M][byTxRetry];
-                    else
-                        wFallBackRate = awHWRetry1[wRate-RATE_18M][4];
-                }
-                pMgmt->sNodeDBTable[0].uTxOk[wFallBackRate]++;
-            } else {
-                pMgmt->sNodeDBTable[0].uTxFailures ++;
-            }
-            pMgmt->sNodeDBTable[0].uTxRetry += byTxRetry;
-            if (byTxRetry != 0) {
-                pMgmt->sNodeDBTable[0].uTxFail[MAX_RATE]+=byTxRetry;
-                if ( (byFallBack == AUTO_FB_NONE) ||
-                     (wRate < RATE_18M) ) {
-                    pMgmt->sNodeDBTable[0].uTxFail[wRate]+=byTxRetry;
-                } else if (byFallBack == AUTO_FB_0) {
+					if (byTxRetry < 5)
+						wFallBackRate = awHWRetry0[wRate-RATE_18M][byTxRetry];
+					//wFallBackRate = awHWRetry0[wRate-RATE_12M][byTxRetry];
+					//wFallBackRate = awHWRetry0[wRate-RATE_18M][txRetryTemp] +1;
+					else
+						wFallBackRate = awHWRetry0[wRate-RATE_18M][4];
+					//wFallBackRate = awHWRetry0[wRate-RATE_12M][4];
+				} else if (byFallBack == AUTO_FB_1) {
+					if (byTxRetry < 5)
+						wFallBackRate = awHWRetry1[wRate-RATE_18M][byTxRetry];
+					else
+						wFallBackRate = awHWRetry1[wRate-RATE_18M][4];
+				}
+				pMgmt->sNodeDBTable[0].uTxOk[wFallBackRate]++;
+			} else {
+				pMgmt->sNodeDBTable[0].uTxFailures++;
+			}
+			pMgmt->sNodeDBTable[0].uTxRetry += byTxRetry;
+			if (byTxRetry != 0) {
+				pMgmt->sNodeDBTable[0].uTxFail[MAX_RATE] += byTxRetry;
+				if ((byFallBack == AUTO_FB_NONE) ||
+				    (wRate < RATE_18M)) {
+					pMgmt->sNodeDBTable[0].uTxFail[wRate] += byTxRetry;
+				} else if (byFallBack == AUTO_FB_0) {
 //PLICE_DEBUG
-				   for(ii=0;ii<byTxRetry;ii++)
-		//for (ii=0;ii<txRetryTemp;ii++)
-		{
-                        if (ii < 5)
-                        	{
-
+					for (ii = 0; ii < byTxRetry; ii++)
+						//for (ii=0;ii<txRetryTemp;ii++)
+					{
+						if (ii < 5) {
 //PLICE_DEBUG
-						wFallBackRate = awHWRetry0[wRate-RATE_18M][ii];
-					//printk(" II is %d:BSSvUpdateNodeTx:wFallBackRate is %d\n",ii,wFallBackRate);
-				//wFallBackRate = awHWRetry0[wRate-RATE_12M][ii];
-                        	}
-			else
-				{
-			wFallBackRate = awHWRetry0[wRate-RATE_18M][4];
-			//printk("ii is %d BSSvUpdateNodeTx:wFallBackRate is %d\n",ii,wFallBackRate);
-				//wFallBackRate = awHWRetry0[wRate-RATE_12M][4];
-				}
+							wFallBackRate = awHWRetry0[wRate-RATE_18M][ii];
+							//wFallBackRate = awHWRetry0[wRate-RATE_12M][ii];
+						} else {
+							wFallBackRate = awHWRetry0[wRate-RATE_18M][4];
+							//wFallBackRate = awHWRetry0[wRate-RATE_12M][4];
+						}
 						pMgmt->sNodeDBTable[0].uTxFail[wFallBackRate]++;
-                    }
-                } else if (byFallBack == AUTO_FB_1) {
-                    for(ii=0;ii<byTxRetry;ii++) {
-                        if (ii < 5)
-                            wFallBackRate = awHWRetry1[wRate-RATE_18M][ii];
-                        else
-                            wFallBackRate = awHWRetry1[wRate-RATE_18M][4];
-                        pMgmt->sNodeDBTable[0].uTxFail[wFallBackRate]++;
-                    }
-                }
-            }
-        }
-
-        if ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) ||
-            (pMgmt->eCurrMode == WMAC_MODE_ESS_AP)) {
-
-            pMACHeader = (PS802_11Header)(pbyBuffer + uFIFOHeaderSize);
-
-            if (BSSDBbIsSTAInNodeDB((void *)pMgmt, &(pMACHeader->abyAddr1[0]), &uNodeIndex)){
-                pMgmt->sNodeDBTable[uNodeIndex].uTxAttempts += 1;
-                if ((byTsr1 & TSR1_TERR) == 0) {
-                    // transmit success, TxAttempts at least plus one
-                    pMgmt->sNodeDBTable[uNodeIndex].uTxOk[MAX_RATE]++;
-                    if ( (byFallBack == AUTO_FB_NONE) ||
-                         (wRate < RATE_18M) ) {
-                        wFallBackRate = wRate;
-                    } else if (byFallBack == AUTO_FB_0) {
-                        if (byTxRetry < 5)
-                            wFallBackRate = awHWRetry0[wRate-RATE_18M][byTxRetry];
-                        else
-                            wFallBackRate = awHWRetry0[wRate-RATE_18M][4];
-                    } else if (byFallBack == AUTO_FB_1) {
-                        if (byTxRetry < 5)
-                            wFallBackRate = awHWRetry1[wRate-RATE_18M][byTxRetry];
-                        else
-                            wFallBackRate = awHWRetry1[wRate-RATE_18M][4];
-                    }
-                    pMgmt->sNodeDBTable[uNodeIndex].uTxOk[wFallBackRate]++;
-                } else {
-                    pMgmt->sNodeDBTable[uNodeIndex].uTxFailures ++;
-                }
-                pMgmt->sNodeDBTable[uNodeIndex].uTxRetry += byTxRetry;
-                if (byTxRetry != 0) {
-                    pMgmt->sNodeDBTable[uNodeIndex].uTxFail[MAX_RATE]+=byTxRetry;
-                    if ( (byFallBack == AUTO_FB_NONE) ||
-                         (wRate < RATE_18M) ) {
-                        pMgmt->sNodeDBTable[uNodeIndex].uTxFail[wRate]+=byTxRetry;
-                    } else if (byFallBack == AUTO_FB_0) {
-                        for(ii=0;ii<byTxRetry;ii++) {
-                            if (ii < 5)
-                                wFallBackRate = awHWRetry0[wRate-RATE_18M][ii];
-                            else
-                                wFallBackRate = awHWRetry0[wRate-RATE_18M][4];
-                            pMgmt->sNodeDBTable[uNodeIndex].uTxFail[wFallBackRate]++;
-                        }
-                    } else if (byFallBack == AUTO_FB_1) {
-                        for(ii=0;ii<byTxRetry;ii++) {
-                            if (ii < 5)
-                                wFallBackRate = awHWRetry1[wRate-RATE_18M][ii];
-                            else
-                                wFallBackRate = awHWRetry1[wRate-RATE_18M][4];
-                            pMgmt->sNodeDBTable[uNodeIndex].uTxFail[wFallBackRate]++;
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    return;
+					}
+				} else if (byFallBack == AUTO_FB_1) {
+					for (ii = 0; ii < byTxRetry; ii++) {
+						if (ii < 5)
+							wFallBackRate = awHWRetry1[wRate-RATE_18M][ii];
+						else
+							wFallBackRate = awHWRetry1[wRate-RATE_18M][4];
+						pMgmt->sNodeDBTable[0].uTxFail[wFallBackRate]++;
+					}
+				}
+			}
+		}
 
+		if ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) ||
+		    (pMgmt->eCurrMode == WMAC_MODE_ESS_AP)) {
+			pMACHeader = (PS802_11Header)(pbyBuffer + uFIFOHeaderSize);
+
+			if (BSSDBbIsSTAInNodeDB((void *)pMgmt,  &(pMACHeader->abyAddr1[0]), &uNodeIndex)) {
+				pMgmt->sNodeDBTable[uNodeIndex].uTxAttempts += 1;
+				if ((byTsr1 & TSR1_TERR) == 0) {
+					// transmit success, TxAttempts at least plus one
+					pMgmt->sNodeDBTable[uNodeIndex].uTxOk[MAX_RATE]++;
+					if ((byFallBack == AUTO_FB_NONE) ||
+					    (wRate < RATE_18M)) {
+						wFallBackRate = wRate;
+					} else if (byFallBack == AUTO_FB_0) {
+						if (byTxRetry < 5)
+							wFallBackRate = awHWRetry0[wRate-RATE_18M][byTxRetry];
+						else
+							wFallBackRate = awHWRetry0[wRate-RATE_18M][4];
+					} else if (byFallBack == AUTO_FB_1) {
+						if (byTxRetry < 5)
+							wFallBackRate = awHWRetry1[wRate-RATE_18M][byTxRetry];
+						else
+							wFallBackRate = awHWRetry1[wRate-RATE_18M][4];
+					}
+					pMgmt->sNodeDBTable[uNodeIndex].uTxOk[wFallBackRate]++;
+				} else {
+					pMgmt->sNodeDBTable[uNodeIndex].uTxFailures++;
+				}
+				pMgmt->sNodeDBTable[uNodeIndex].uTxRetry += byTxRetry;
+				if (byTxRetry != 0) {
+					pMgmt->sNodeDBTable[uNodeIndex].uTxFail[MAX_RATE] += byTxRetry;
+					if ((byFallBack == AUTO_FB_NONE) ||
+					    (wRate < RATE_18M)) {
+						pMgmt->sNodeDBTable[uNodeIndex].uTxFail[wRate] += byTxRetry;
+					} else if (byFallBack == AUTO_FB_0) {
+						for (ii = 0; ii < byTxRetry; ii++) {
+							if (ii < 5)
+								wFallBackRate = awHWRetry0[wRate - RATE_18M][ii];
+							else
+								wFallBackRate = awHWRetry0[wRate - RATE_18M][4];
+							pMgmt->sNodeDBTable[uNodeIndex].uTxFail[wFallBackRate]++;
+						}
+					} else if (byFallBack == AUTO_FB_1) {
+						for (ii = 0; ii < byTxRetry; ii++) {
+							if (ii < 5)
+								wFallBackRate = awHWRetry1[wRate-RATE_18M][ii];
+							else
+								wFallBackRate = awHWRetry1[wRate-RATE_18M][4];
+							pMgmt->sNodeDBTable[uNodeIndex].uTxFail[wFallBackRate]++;
+						}
+					}
+				}
+			}
+		}
+	}
 
+	return;
 }
 
-
-
-
 /*+
  *
  * Routine Description:
@@ -1569,167 +1466,157 @@ BSSvUpdateNodeTxCounter(
  * Return Value:
  *    None.
  *
--*/
-
+ -*/
 
 void
 BSSvClearNodeDBTable(
-    void *hDeviceContext,
-    unsigned int uStartIndex
-    )
+	void *hDeviceContext,
+	unsigned int uStartIndex
+)
 
 {
-    PSDevice     pDevice = (PSDevice)hDeviceContext;
-    PSMgmtObject    pMgmt = pDevice->pMgmt;
-    struct sk_buff  *skb;
-    unsigned int ii;
-
-    for (ii = uStartIndex; ii < (MAX_NODE_NUM + 1); ii++) {
-        if (pMgmt->sNodeDBTable[ii].bActive) {
-            // check if sTxPSQueue has been initial
-            if (pMgmt->sNodeDBTable[ii].sTxPSQueue.next != NULL) {
-                while ((skb = skb_dequeue(&pMgmt->sNodeDBTable[ii].sTxPSQueue)) != NULL){
-                        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "PS skb != NULL %d\n", ii);
-                        dev_kfree_skb(skb);
-                }
-            }
-            memset(&pMgmt->sNodeDBTable[ii], 0, sizeof(KnownNodeDB));
-        }
-    }
-
-    return;
-};
+	PSDevice     pDevice = (PSDevice)hDeviceContext;
+	PSMgmtObject    pMgmt = pDevice->pMgmt;
+	struct sk_buff  *skb;
+	unsigned int ii;
+
+	for (ii = uStartIndex; ii < (MAX_NODE_NUM + 1); ii++) {
+		if (pMgmt->sNodeDBTable[ii].bActive) {
+			// check if sTxPSQueue has been initial
+			if (pMgmt->sNodeDBTable[ii].sTxPSQueue.next != NULL) {
+				while ((skb = skb_dequeue(&pMgmt->sNodeDBTable[ii].sTxPSQueue)) != NULL) {
+					DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "PS skb != NULL %d\n", ii);
+					dev_kfree_skb(skb);
+				}
+			}
+			memset(&pMgmt->sNodeDBTable[ii], 0, sizeof(KnownNodeDB));
+		}
+	}
 
+	return;
+};
 
 void s_vCheckSensitivity(
-    void *hDeviceContext
-    )
+	void *hDeviceContext
+)
 {
-    PSDevice        pDevice = (PSDevice)hDeviceContext;
-    PKnownBSS       pBSSList = NULL;
-    PSMgmtObject    pMgmt = pDevice->pMgmt;
-    int             ii;
-
-    if ((pDevice->byLocalID <= REV_ID_VT3253_A1) && (pDevice->byRFType == RF_RFMD2959) &&
-        (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA)) {
-        return;
-    }
-
-    if ((pMgmt->eCurrState == WMAC_STATE_ASSOC) ||
-        ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) && (pMgmt->eCurrState == WMAC_STATE_JOINTED))) {
-        pBSSList = BSSpAddrIsInBSSList(pDevice, pMgmt->abyCurrBSSID, (PWLAN_IE_SSID)pMgmt->abyCurrSSID);
-        if (pBSSList != NULL) {
-            // Updata BB Reg if RSSI is too strong.
-            long    LocalldBmAverage = 0;
-            long    uNumofdBm = 0;
-            for (ii = 0; ii < RSSI_STAT_COUNT; ii++) {
-                if (pBSSList->ldBmAverage[ii] != 0) {
-                    uNumofdBm ++;
-                    LocalldBmAverage += pBSSList->ldBmAverage[ii];
-                }
-            }
-            if (uNumofdBm > 0) {
-                LocalldBmAverage = LocalldBmAverage/uNumofdBm;
-                for (ii=0;ii<BB_VGA_LEVEL;ii++) {
-                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"LocalldBmAverage:%ld, %ld %02x\n", LocalldBmAverage, pDevice->ldBmThreshold[ii], pDevice->abyBBVGA[ii]);
-                    if (LocalldBmAverage < pDevice->ldBmThreshold[ii]) {
-                	    pDevice->byBBVGANew = pDevice->abyBBVGA[ii];
-                        break;
-                    }
-                }
-                if (pDevice->byBBVGANew != pDevice->byBBVGACurrent) {
-                    pDevice->uBBVGADiffCount++;
-                    if (pDevice->uBBVGADiffCount >= BB_VGA_CHANGE_THRESHOLD)
-                        bScheduleCommand((void *) pDevice, WLAN_CMD_CHANGE_BBSENSITIVITY, NULL);
-                } else {
-                    pDevice->uBBVGADiffCount = 0;
-                }
-            }
-        }
-    }
+	PSDevice        pDevice = (PSDevice)hDeviceContext;
+	PKnownBSS       pBSSList = NULL;
+	PSMgmtObject    pMgmt = pDevice->pMgmt;
+	int             ii;
+
+	if ((pDevice->byLocalID <= REV_ID_VT3253_A1) && (pDevice->byRFType == RF_RFMD2959) &&
+	    (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA)) {
+		return;
+	}
+
+	if ((pMgmt->eCurrState == WMAC_STATE_ASSOC) ||
+	    ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) && (pMgmt->eCurrState == WMAC_STATE_JOINTED))) {
+		pBSSList = BSSpAddrIsInBSSList(pDevice, pMgmt->abyCurrBSSID, (PWLAN_IE_SSID)pMgmt->abyCurrSSID);
+		if (pBSSList != NULL) {
+			// Updata BB Reg if RSSI is too strong.
+			long    LocalldBmAverage = 0;
+			long    uNumofdBm = 0;
+			for (ii = 0; ii < RSSI_STAT_COUNT; ii++) {
+				if (pBSSList->ldBmAverage[ii] != 0) {
+					uNumofdBm++;
+					LocalldBmAverage += pBSSList->ldBmAverage[ii];
+				}
+			}
+			if (uNumofdBm > 0) {
+				LocalldBmAverage = LocalldBmAverage/uNumofdBm;
+				for (ii = 0; ii < BB_VGA_LEVEL; ii++) {
+					DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "LocalldBmAverage:%ld, %ld %02x\n", LocalldBmAverage, pDevice->ldBmThreshold[ii], pDevice->abyBBVGA[ii]);
+					if (LocalldBmAverage < pDevice->ldBmThreshold[ii]) {
+						pDevice->byBBVGANew = pDevice->abyBBVGA[ii];
+						break;
+					}
+				}
+				if (pDevice->byBBVGANew != pDevice->byBBVGACurrent) {
+					pDevice->uBBVGADiffCount++;
+					if (pDevice->uBBVGADiffCount >= BB_VGA_CHANGE_THRESHOLD)
+						bScheduleCommand((void *)pDevice, WLAN_CMD_CHANGE_BBSENSITIVITY, NULL);
+				} else {
+					pDevice->uBBVGADiffCount = 0;
+				}
+			}
+		}
+	}
 }
 
-
 void
-BSSvClearAnyBSSJoinRecord (
-    void *hDeviceContext
-    )
+BSSvClearAnyBSSJoinRecord(
+	void *hDeviceContext
+)
 {
-    PSDevice        pDevice = (PSDevice)hDeviceContext;
-    PSMgmtObject    pMgmt = pDevice->pMgmt;
-    unsigned int ii;
-
-    for (ii = 0; ii < MAX_BSS_NUM; ii++) {
-        pMgmt->sBSSList[ii].bSelected = false;
-    }
-    return;
+	PSDevice        pDevice = (PSDevice)hDeviceContext;
+	PSMgmtObject    pMgmt = pDevice->pMgmt;
+	unsigned int ii;
+
+	for (ii = 0; ii < MAX_BSS_NUM; ii++) {
+		pMgmt->sBSSList[ii].bSelected = false;
+	}
+	return;
 }
 
 #ifdef Calcu_LinkQual
 void s_uCalculateLinkQual(
-    void *hDeviceContext
-    )
+	void *hDeviceContext
+)
 {
-   PSDevice        pDevice = (PSDevice)hDeviceContext;
-   unsigned long TxOkRatio, TxCnt;
-   unsigned long RxOkRatio,RxCnt;
-   unsigned long RssiRatio;
-   long ldBm;
-
-TxCnt = pDevice->scStatistic.TxNoRetryOkCount +
-	      pDevice->scStatistic.TxRetryOkCount +
-	      pDevice->scStatistic.TxFailCount;
-RxCnt = pDevice->scStatistic.RxFcsErrCnt +
-	      pDevice->scStatistic.RxOkCnt;
-TxOkRatio = (TxCnt < 6) ? 4000:((pDevice->scStatistic.TxNoRetryOkCount * 4000) / TxCnt);
-RxOkRatio = (RxCnt < 6) ? 2000:((pDevice->scStatistic.RxOkCnt * 2000) / RxCnt);
+	PSDevice        pDevice = (PSDevice)hDeviceContext;
+	unsigned long TxOkRatio, TxCnt;
+	unsigned long RxOkRatio, RxCnt;
+	unsigned long RssiRatio;
+	long ldBm;
+
+	TxCnt = pDevice->scStatistic.TxNoRetryOkCount +
+		pDevice->scStatistic.TxRetryOkCount +
+		pDevice->scStatistic.TxFailCount;
+	RxCnt = pDevice->scStatistic.RxFcsErrCnt +
+		pDevice->scStatistic.RxOkCnt;
+	TxOkRatio = (TxCnt < 6) ? 4000 : ((pDevice->scStatistic.TxNoRetryOkCount * 4000) / TxCnt);
+	RxOkRatio = (RxCnt < 6) ? 2000 : ((pDevice->scStatistic.RxOkCnt * 2000) / RxCnt);
 //decide link quality
-if(pDevice->bLinkPass !=true)
-{
- //  printk("s_uCalculateLinkQual-->Link disconnect and Poor quality**\n");
-   pDevice->scStatistic.LinkQuality = 0;
-   pDevice->scStatistic.SignalStren = 0;
-}
-else
-{
-   RFvRSSITodBm(pDevice, (unsigned char)(pDevice->uCurrRSSI), &ldBm);
-   if(-ldBm < 50)  {
-   	RssiRatio = 4000;
-     }
-   else if(-ldBm > 90) {
-   	RssiRatio = 0;
-     }
-   else {
-   	RssiRatio = (40-(-ldBm-50))*4000/40;
-     }
-   pDevice->scStatistic.SignalStren = RssiRatio/40;
-   pDevice->scStatistic.LinkQuality = (RssiRatio+TxOkRatio+RxOkRatio)/100;
-}
-   pDevice->scStatistic.RxFcsErrCnt = 0;
-   pDevice->scStatistic.RxOkCnt = 0;
-   pDevice->scStatistic.TxFailCount = 0;
-   pDevice->scStatistic.TxNoRetryOkCount = 0;
-   pDevice->scStatistic.TxRetryOkCount = 0;
-   return;
+	if (pDevice->bLinkPass != true) {
+		pDevice->scStatistic.LinkQuality = 0;
+		pDevice->scStatistic.SignalStren = 0;
+	} else {
+		RFvRSSITodBm(pDevice, (unsigned char)(pDevice->uCurrRSSI), &ldBm);
+		if (-ldBm < 50)  {
+			RssiRatio = 4000;
+		} else if (-ldBm > 90) {
+			RssiRatio = 0;
+		} else {
+			RssiRatio = (40-(-ldBm-50))*4000/40;
+		}
+		pDevice->scStatistic.SignalStren = RssiRatio/40;
+		pDevice->scStatistic.LinkQuality = (RssiRatio+TxOkRatio+RxOkRatio)/100;
+	}
+	pDevice->scStatistic.RxFcsErrCnt = 0;
+	pDevice->scStatistic.RxOkCnt = 0;
+	pDevice->scStatistic.TxFailCount = 0;
+	pDevice->scStatistic.TxNoRetryOkCount = 0;
+	pDevice->scStatistic.TxRetryOkCount = 0;
+	return;
 }
 #endif
 
 void s_vCheckPreEDThreshold(
-    void *hDeviceContext
-    )
+	void *hDeviceContext
+)
 {
-    PSDevice        pDevice = (PSDevice)hDeviceContext;
-    PKnownBSS       pBSSList = NULL;
-    PSMgmtObject    pMgmt = &(pDevice->sMgmtObj);
-
-    if ((pMgmt->eCurrState == WMAC_STATE_ASSOC) ||
-        ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) && (pMgmt->eCurrState == WMAC_STATE_JOINTED))) {
-        pBSSList = BSSpAddrIsInBSSList(pDevice, pMgmt->abyCurrBSSID, (PWLAN_IE_SSID)pMgmt->abyCurrSSID);
-        if (pBSSList != NULL) {
-            pDevice->byBBPreEDRSSI = (unsigned char) (~(pBSSList->ldBmAverRange) + 1);
-            //BBvUpdatePreEDThreshold(pDevice, false);
-        }
-    }
-    return;
+	PSDevice        pDevice = (PSDevice)hDeviceContext;
+	PKnownBSS       pBSSList = NULL;
+	PSMgmtObject    pMgmt = &(pDevice->sMgmtObj);
+
+	if ((pMgmt->eCurrState == WMAC_STATE_ASSOC) ||
+	    ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) && (pMgmt->eCurrState == WMAC_STATE_JOINTED))) {
+		pBSSList = BSSpAddrIsInBSSList(pDevice, pMgmt->abyCurrBSSID, (PWLAN_IE_SSID)pMgmt->abyCurrSSID);
+		if (pBSSList != NULL) {
+			pDevice->byBBPreEDRSSI = (unsigned char) (~(pBSSList->ldBmAverRange) + 1);
+			//BBvUpdatePreEDThreshold(pDevice, false);
+		}
+	}
+	return;
 }
-
diff --git a/drivers/staging/vt6655/bssdb.h b/drivers/staging/vt6655/bssdb.h
index 0af4211..5c77677 100644
--- a/drivers/staging/vt6655/bssdb.h
+++ b/drivers/staging/vt6655/bssdb.h
@@ -39,7 +39,7 @@
 
 #define MAX_NODE_NUM             64
 #define MAX_BSS_NUM              42
-#define LOST_BEACON_COUNT      	 10   // 10 sec, XP defined
+#define LOST_BEACON_COUNT        10   // 10 sec, XP defined
 #define MAX_PS_TX_BUF            32   // sta max power saving tx buf
 #define ADHOC_LOST_BEACON_COUNT  30   // 30 sec, beacon lost for adhoc only
 #define MAX_INACTIVE_COUNT       300  // 300 sec, inactive STA node refresh
@@ -67,12 +67,10 @@
 
 #define MAX_WPA_IE_LEN      64
 
-
 /*---------------------  Export Classes  ----------------------------*/
 
 /*---------------------  Export Variables  --------------------------*/
 
-
 /*---------------------  Export Types  ------------------------------*/
 
 //
@@ -81,285 +79,272 @@
 
 typedef enum _NDIS_802_11_NETWORK_TYPE
 {
-    Ndis802_11FH,
-    Ndis802_11DS,
-    Ndis802_11OFDM5,
-    Ndis802_11OFDM24,
-    Ndis802_11NetworkTypeMax    // not a real type, defined as an upper bound
+	Ndis802_11FH,
+	Ndis802_11DS,
+	Ndis802_11OFDM5,
+	Ndis802_11OFDM24,
+	Ndis802_11NetworkTypeMax    // not a real type, defined as an upper bound
 } NDIS_802_11_NETWORK_TYPE, *PNDIS_802_11_NETWORK_TYPE;
 
-
 typedef struct tagSERPObject {
-    bool bERPExist;
-    unsigned char byERP;
-}ERPObject, *PERPObject;
-
+	bool bERPExist;
+	unsigned char byERP;
+} ERPObject, *PERPObject;
 
 typedef struct tagSRSNCapObject {
-    bool bRSNCapExist;
-    unsigned short wRSNCap;
-}SRSNCapObject, *PSRSNCapObject;
+	bool bRSNCapExist;
+	unsigned short wRSNCap;
+} SRSNCapObject, *PSRSNCapObject;
 
 // BSS info(AP)
 #pragma pack(1)
 typedef struct tagKnownBSS {
-    // BSS info
-    bool bActive;
-    unsigned char abyBSSID[WLAN_BSSID_LEN];
-    unsigned int	uChannel;
-    unsigned char abySuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1];
-    unsigned char abyExtSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1];
-    unsigned int	uRSSI;
-    unsigned char bySQ;
-    unsigned short wBeaconInterval;
-    unsigned short wCapInfo;
-    unsigned char abySSID[WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1];
-    unsigned char byRxRate;
+	// BSS info
+	bool bActive;
+	unsigned char abyBSSID[WLAN_BSSID_LEN];
+	unsigned int	uChannel;
+	unsigned char abySuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1];
+	unsigned char abyExtSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1];
+	unsigned int	uRSSI;
+	unsigned char bySQ;
+	unsigned short wBeaconInterval;
+	unsigned short wCapInfo;
+	unsigned char abySSID[WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1];
+	unsigned char byRxRate;
 
 //    unsigned short wATIMWindow;
-    unsigned char byRSSIStatCnt;
-    long            ldBmMAX;
-    long            ldBmAverage[RSSI_STAT_COUNT];
-    long            ldBmAverRange;
-    //For any BSSID selection improvment
-    bool bSelected;
-
-    //++ WPA informations
-    bool bWPAValid;
-    unsigned char byGKType;
-    unsigned char abyPKType[4];
-    unsigned short wPKCount;
-    unsigned char abyAuthType[4];
-    unsigned short wAuthCount;
-    unsigned char byDefaultK_as_PK;
-    unsigned char byReplayIdx;
-    //--
-
-    //++ WPA2 informations
-    bool bWPA2Valid;
-    unsigned char byCSSGK;
-    unsigned short wCSSPKCount;
-    unsigned char abyCSSPK[4];
-    unsigned short wAKMSSAuthCount;
-    unsigned char abyAKMSSAuthType[4];
-
-    //++  wpactl
-    unsigned char byWPAIE[MAX_WPA_IE_LEN];
-    unsigned char byRSNIE[MAX_WPA_IE_LEN];
-    unsigned short wWPALen;
-    unsigned short wRSNLen;
-
-    // Clear count
-    unsigned int	uClearCount;
+	unsigned char byRSSIStatCnt;
+	long            ldBmMAX;
+	long            ldBmAverage[RSSI_STAT_COUNT];
+	long            ldBmAverRange;
+	//For any BSSID selection improvment
+	bool bSelected;
+
+	//++ WPA informations
+	bool bWPAValid;
+	unsigned char byGKType;
+	unsigned char abyPKType[4];
+	unsigned short wPKCount;
+	unsigned char abyAuthType[4];
+	unsigned short wAuthCount;
+	unsigned char byDefaultK_as_PK;
+	unsigned char byReplayIdx;
+	//--
+
+	//++ WPA2 informations
+	bool bWPA2Valid;
+	unsigned char byCSSGK;
+	unsigned short wCSSPKCount;
+	unsigned char abyCSSPK[4];
+	unsigned short wAKMSSAuthCount;
+	unsigned char abyAKMSSAuthType[4];
+
+	//++  wpactl
+	unsigned char byWPAIE[MAX_WPA_IE_LEN];
+	unsigned char byRSNIE[MAX_WPA_IE_LEN];
+	unsigned short wWPALen;
+	unsigned short wRSNLen;
+
+	// Clear count
+	unsigned int	uClearCount;
 //    unsigned char abyIEs[WLAN_BEACON_FR_MAXLEN];
-    unsigned int	uIELength;
-    QWORD           qwBSSTimestamp;
-    QWORD           qwLocalTSF;     // local TSF timer
+	unsigned int	uIELength;
+	QWORD           qwBSSTimestamp;
+	QWORD           qwLocalTSF;     // local TSF timer
 
 //    NDIS_802_11_NETWORK_TYPE    NetworkTypeInUse;
-    CARD_PHY_TYPE   eNetworkTypeInUse;
+	CARD_PHY_TYPE   eNetworkTypeInUse;
 
-    ERPObject       sERP;
-    SRSNCapObject   sRSNCapObj;
-    unsigned char abyIEs[1024];   // don't move this field !!
-
-}__attribute__ ((__packed__))
+	ERPObject       sERP;
+	SRSNCapObject   sRSNCapObj;
+	unsigned char abyIEs[1024];   // don't move this field !!
+} __attribute__ ((__packed__))
 KnownBSS , *PKnownBSS;
 
 //2006-1116-01,<Add> by NomadZhao
 #pragma pack()
 
 typedef enum tagNODE_STATE {
-    NODE_FREE,
-    NODE_AGED,
-    NODE_KNOWN,
-    NODE_AUTH,
-    NODE_ASSOC
+	NODE_FREE,
+	NODE_AGED,
+	NODE_KNOWN,
+	NODE_AUTH,
+	NODE_ASSOC
 } NODE_STATE, *PNODE_STATE;
 
-
 // STA node info
 typedef struct tagKnownNodeDB {
-    // STA info
-    bool bActive;
-    unsigned char abyMACAddr[WLAN_ADDR_LEN];
-    unsigned char abyCurrSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN];
-    unsigned char abyCurrExtSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN];
-    unsigned short wTxDataRate;
-    bool bShortPreamble;
-    bool bERPExist;
-    bool bShortSlotTime;
-    unsigned int	uInActiveCount;
-    unsigned short wMaxBasicRate;     //Get from byTopOFDMBasicRate or byTopCCKBasicRate which depends on packetTyp.
-    unsigned short wMaxSuppRate;      //Records the highest supported rate getting from SuppRates IE and ExtSuppRates IE in Beacon.
-    unsigned short wSuppRate;
-    unsigned char byTopOFDMBasicRate;//Records the highest basic rate in OFDM mode
-    unsigned char byTopCCKBasicRate; //Records the highest basic rate in CCK mode
-
-    // For AP mode
-    struct sk_buff_head sTxPSQueue;
-    unsigned short wCapInfo;
-    unsigned short wListenInterval;
-    unsigned short wAID;
-    NODE_STATE      eNodeState;
-    bool bPSEnable;
-    bool bRxPSPoll;
-    unsigned char byAuthSequence;
-    unsigned long ulLastRxJiffer;
-    unsigned char bySuppRate;
-    unsigned long dwFlags;
-    unsigned short wEnQueueCnt;
-
-    bool bOnFly;
-    unsigned long long       KeyRSC;
-    unsigned char byKeyIndex;
-    unsigned long dwKeyIndex;
-    unsigned char byCipherSuite;
-    unsigned long dwTSC47_16;
-    unsigned short wTSC15_0;
-    unsigned int	uWepKeyLength;
-    unsigned char abyWepKey[WLAN_WEPMAX_KEYLEN];
-    //
-    // Auto rate fallback vars
-    bool bIsInFallback;
-    unsigned int	uAverageRSSI;
-    unsigned int	uRateRecoveryTimeout;
-    unsigned int	uRatePollTimeout;
-    unsigned int	uTxFailures;
-    unsigned int	uTxAttempts;
-
-    unsigned int	uTxRetry;
-    unsigned int	uFailureRatio;
-    unsigned int	uRetryRatio;
-    unsigned int	uTxOk[MAX_RATE+1];
-    unsigned int	uTxFail[MAX_RATE+1];
-    unsigned int	uTimeCount;
-
+	// STA info
+	bool bActive;
+	unsigned char abyMACAddr[WLAN_ADDR_LEN];
+	unsigned char abyCurrSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN];
+	unsigned char abyCurrExtSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN];
+	unsigned short wTxDataRate;
+	bool bShortPreamble;
+	bool bERPExist;
+	bool bShortSlotTime;
+	unsigned int	uInActiveCount;
+	unsigned short wMaxBasicRate;     //Get from byTopOFDMBasicRate or byTopCCKBasicRate which depends on packetTyp.
+	unsigned short wMaxSuppRate;      //Records the highest supported rate getting from SuppRates IE and ExtSuppRates IE in Beacon.
+	unsigned short wSuppRate;
+	unsigned char byTopOFDMBasicRate;//Records the highest basic rate in OFDM mode
+	unsigned char byTopCCKBasicRate; //Records the highest basic rate in CCK mode
+
+	// For AP mode
+	struct sk_buff_head sTxPSQueue;
+	unsigned short wCapInfo;
+	unsigned short wListenInterval;
+	unsigned short wAID;
+	NODE_STATE      eNodeState;
+	bool bPSEnable;
+	bool bRxPSPoll;
+	unsigned char byAuthSequence;
+	unsigned long ulLastRxJiffer;
+	unsigned char bySuppRate;
+	unsigned long dwFlags;
+	unsigned short wEnQueueCnt;
+
+	bool bOnFly;
+	unsigned long long       KeyRSC;
+	unsigned char byKeyIndex;
+	unsigned long dwKeyIndex;
+	unsigned char byCipherSuite;
+	unsigned long dwTSC47_16;
+	unsigned short wTSC15_0;
+	unsigned int	uWepKeyLength;
+	unsigned char abyWepKey[WLAN_WEPMAX_KEYLEN];
+	//
+	// Auto rate fallback vars
+	bool bIsInFallback;
+	unsigned int	uAverageRSSI;
+	unsigned int	uRateRecoveryTimeout;
+	unsigned int	uRatePollTimeout;
+	unsigned int	uTxFailures;
+	unsigned int	uTxAttempts;
+
+	unsigned int	uTxRetry;
+	unsigned int	uFailureRatio;
+	unsigned int	uRetryRatio;
+	unsigned int	uTxOk[MAX_RATE+1];
+	unsigned int	uTxFail[MAX_RATE+1];
+	unsigned int	uTimeCount;
 } KnownNodeDB, *PKnownNodeDB;
 
-
 /*---------------------  Export Functions  --------------------------*/
 
-
-
 PKnownBSS
 BSSpSearchBSSList(
-    void *hDeviceContext,
-    unsigned char *pbyDesireBSSID,
-    unsigned char *pbyDesireSSID,
-    CARD_PHY_TYPE ePhyType
-    );
+	void *hDeviceContext,
+	unsigned char *pbyDesireBSSID,
+	unsigned char *pbyDesireSSID,
+	CARD_PHY_TYPE ePhyType
+);
 
 PKnownBSS
 BSSpAddrIsInBSSList(
-    void *hDeviceContext,
-    unsigned char *abyBSSID,
-    PWLAN_IE_SSID pSSID
-    );
+	void *hDeviceContext,
+	unsigned char *abyBSSID,
+	PWLAN_IE_SSID pSSID
+);
 
 void
 BSSvClearBSSList(
-    void *hDeviceContext,
-    bool bKeepCurrBSSID
-    );
+	void *hDeviceContext,
+	bool bKeepCurrBSSID
+);
 
 bool
 BSSbInsertToBSSList(
-    void *hDeviceContext,
-    unsigned char *abyBSSIDAddr,
-    QWORD qwTimestamp,
-    unsigned short wBeaconInterval,
-    unsigned short wCapInfo,
-    unsigned char byCurrChannel,
-    PWLAN_IE_SSID pSSID,
-    PWLAN_IE_SUPP_RATES pSuppRates,
-    PWLAN_IE_SUPP_RATES pExtSuppRates,
-    PERPObject psERP,
-    PWLAN_IE_RSN pRSN,
-    PWLAN_IE_RSN_EXT pRSNWPA,
-    PWLAN_IE_COUNTRY pIE_Country,
-    PWLAN_IE_QUIET pIE_Quiet,
-    unsigned int uIELength,
-    unsigned char *pbyIEs,
-    void *pRxPacketContext
-    );
-
+	void *hDeviceContext,
+	unsigned char *abyBSSIDAddr,
+	QWORD qwTimestamp,
+	unsigned short wBeaconInterval,
+	unsigned short wCapInfo,
+	unsigned char byCurrChannel,
+	PWLAN_IE_SSID pSSID,
+	PWLAN_IE_SUPP_RATES pSuppRates,
+	PWLAN_IE_SUPP_RATES pExtSuppRates,
+	PERPObject psERP,
+	PWLAN_IE_RSN pRSN,
+	PWLAN_IE_RSN_EXT pRSNWPA,
+	PWLAN_IE_COUNTRY pIE_Country,
+	PWLAN_IE_QUIET pIE_Quiet,
+	unsigned int uIELength,
+	unsigned char *pbyIEs,
+	void *pRxPacketContext
+);
 
 bool
 BSSbUpdateToBSSList(
-    void *hDeviceContext,
-    QWORD qwTimestamp,
-    unsigned short wBeaconInterval,
-    unsigned short wCapInfo,
-    unsigned char byCurrChannel,
-    bool bChannelHit,
-    PWLAN_IE_SSID pSSID,
-    PWLAN_IE_SUPP_RATES pSuppRates,
-    PWLAN_IE_SUPP_RATES pExtSuppRates,
-    PERPObject psERP,
-    PWLAN_IE_RSN pRSN,
-    PWLAN_IE_RSN_EXT pRSNWPA,
-    PWLAN_IE_COUNTRY pIE_Country,
-    PWLAN_IE_QUIET pIE_Quiet,
-    PKnownBSS pBSSList,
-    unsigned int uIELength,
-    unsigned char *pbyIEs,
-    void *pRxPacketContext
-    );
-
+	void *hDeviceContext,
+	QWORD qwTimestamp,
+	unsigned short wBeaconInterval,
+	unsigned short wCapInfo,
+	unsigned char byCurrChannel,
+	bool bChannelHit,
+	PWLAN_IE_SSID pSSID,
+	PWLAN_IE_SUPP_RATES pSuppRates,
+	PWLAN_IE_SUPP_RATES pExtSuppRates,
+	PERPObject psERP,
+	PWLAN_IE_RSN pRSN,
+	PWLAN_IE_RSN_EXT pRSNWPA,
+	PWLAN_IE_COUNTRY pIE_Country,
+	PWLAN_IE_QUIET pIE_Quiet,
+	PKnownBSS pBSSList,
+	unsigned int uIELength,
+	unsigned char *pbyIEs,
+	void *pRxPacketContext
+);
 
 bool
 BSSDBbIsSTAInNodeDB(void *hDeviceContext, unsigned char *abyDstAddr,
-		unsigned int *puNodeIndex);
+		    unsigned int *puNodeIndex);
 
 void
 BSSvCreateOneNode(void *hDeviceContext, unsigned int *puNodeIndex);
 
 void
 BSSvUpdateAPNode(
-    void *hDeviceContext,
-    unsigned short *pwCapInfo,
-    PWLAN_IE_SUPP_RATES pItemRates,
-    PWLAN_IE_SUPP_RATES pExtSuppRates
-    );
-
+	void *hDeviceContext,
+	unsigned short *pwCapInfo,
+	PWLAN_IE_SUPP_RATES pItemRates,
+	PWLAN_IE_SUPP_RATES pExtSuppRates
+);
 
 void
 BSSvSecondCallBack(
-    void *hDeviceContext
-    );
-
+	void *hDeviceContext
+);
 
 void
 BSSvUpdateNodeTxCounter(
-    void *hDeviceContext,
-    unsigned char byTsr0,
-    unsigned char byTsr1,
-    unsigned char *pbyBuffer,
-    unsigned int uFIFOHeaderSize
-    );
+	void *hDeviceContext,
+	unsigned char byTsr0,
+	unsigned char byTsr1,
+	unsigned char *pbyBuffer,
+	unsigned int uFIFOHeaderSize
+);
 
 void
 BSSvRemoveOneNode(
-    void *hDeviceContext,
-    unsigned int uNodeIndex
-    );
+	void *hDeviceContext,
+	unsigned int uNodeIndex
+);
 
 void
 BSSvAddMulticastNode(
-    void *hDeviceContext
-    );
-
+	void *hDeviceContext
+);
 
 void
 BSSvClearNodeDBTable(
-    void *hDeviceContext,
-    unsigned int uStartIndex
-    );
+	void *hDeviceContext,
+	unsigned int uStartIndex
+);
 
 void
 BSSvClearAnyBSSJoinRecord(
-    void *hDeviceContext
-    );
+	void *hDeviceContext
+);
 
 #endif //__BSSDB_H__
diff --git a/drivers/staging/vt6655/card.c b/drivers/staging/vt6655/card.c
index 319ca48..fbf18e2 100644
--- a/drivers/staging/vt6655/card.c
+++ b/drivers/staging/vt6655/card.c
@@ -61,14 +61,13 @@
 /*---------------------  Static Definitions -------------------------*/
 
 //static int          msglevel                =MSG_LEVEL_DEBUG;
-static int          msglevel                =MSG_LEVEL_INFO;
+static int msglevel = MSG_LEVEL_INFO;
 
 #define C_SIFS_A        16      // micro sec.
 #define C_SIFS_BG       10
 
 #define C_EIFS          80      // micro sec.
 
-
 #define C_SLOT_SHORT    9       // micro sec.
 #define C_SLOT_LONG     20
 
@@ -79,34 +78,30 @@ static int          msglevel                =MSG_LEVEL_INFO;
 
 #define WAIT_BEACON_TX_DOWN_TMO         3    // Times
 
-                                                              //1M,   2M,   5M,  11M,  18M,  24M,  36M,  54M
+//1M,   2M,   5M,  11M,  18M,  24M,  36M,  54M
 static unsigned char abyDefaultSuppRatesG[] = {WLAN_EID_SUPP_RATES, 8, 0x02, 0x04, 0x0B, 0x16, 0x24, 0x30, 0x48, 0x6C};
-                                                                    //6M,   9M,  12M,  48M
+//6M,   9M,  12M,  48M
 static unsigned char abyDefaultExtSuppRatesG[] = {WLAN_EID_EXTSUPP_RATES, 4, 0x0C, 0x12, 0x18, 0x60};
-                                                              //6M,   9M,  12M,  18M,  24M,  36M,  48M,  54M
+//6M,   9M,  12M,  18M,  24M,  36M,  48M,  54M
 static unsigned char abyDefaultSuppRatesA[] = {WLAN_EID_SUPP_RATES, 8, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6C};
-                                                              //1M,   2M,   5M,  11M,
+//1M,   2M,   5M,  11M,
 static unsigned char abyDefaultSuppRatesB[] = {WLAN_EID_SUPP_RATES, 4, 0x02, 0x04, 0x0B, 0x16};
 
-
 /*---------------------  Static Variables  --------------------------*/
 
-
 const unsigned short cwRXBCNTSFOff[MAX_RATE] =
 {17, 17, 17, 17, 34, 23, 17, 11, 8, 5, 4, 3};
 
-
 /*---------------------  Static Functions  --------------------------*/
 
 static
 void
 s_vCalculateOFDMRParameter(
-    unsigned char byRate,
-    CARD_PHY_TYPE ePHYType,
-    unsigned char *pbyTxRate,
-    unsigned char *pbyRsvTime
-    );
-
+	unsigned char byRate,
+	CARD_PHY_TYPE ePHYType,
+	unsigned char *pbyTxRate,
+	unsigned char *pbyRsvTime
+);
 
 /*---------------------  Export Functions  --------------------------*/
 
@@ -126,107 +121,97 @@ s_vCalculateOFDMRParameter(
  */
 static
 void
-s_vCalculateOFDMRParameter (
-    unsigned char byRate,
-    CARD_PHY_TYPE ePHYType,
-    unsigned char *pbyTxRate,
-    unsigned char *pbyRsvTime
-    )
+s_vCalculateOFDMRParameter(
+	unsigned char byRate,
+	CARD_PHY_TYPE ePHYType,
+	unsigned char *pbyTxRate,
+	unsigned char *pbyRsvTime
+)
 {
-    switch (byRate) {
-    case RATE_6M :
-        if (ePHYType == PHY_TYPE_11A) {//5GHZ
-            *pbyTxRate = 0x9B;
-            *pbyRsvTime = 44;
-        }
-        else {
-            *pbyTxRate = 0x8B;
-            *pbyRsvTime = 50;
-        }
-        break;
-
-    case RATE_9M :
-        if (ePHYType == PHY_TYPE_11A) {//5GHZ
-            *pbyTxRate = 0x9F;
-            *pbyRsvTime = 36;
-        }
-        else {
-            *pbyTxRate = 0x8F;
-            *pbyRsvTime = 42;
-        }
-        break;
-
-   case RATE_12M :
-        if (ePHYType == PHY_TYPE_11A) {//5GHZ
-            *pbyTxRate = 0x9A;
-            *pbyRsvTime = 32;
-        }
-        else {
-            *pbyTxRate = 0x8A;
-            *pbyRsvTime = 38;
-        }
-        break;
-
-   case RATE_18M :
-        if (ePHYType == PHY_TYPE_11A) {//5GHZ
-            *pbyTxRate = 0x9E;
-            *pbyRsvTime = 28;
-        }
-        else {
-            *pbyTxRate = 0x8E;
-            *pbyRsvTime = 34;
-        }
-        break;
-
-    case RATE_36M :
-        if (ePHYType == PHY_TYPE_11A) {//5GHZ
-            *pbyTxRate = 0x9D;
-            *pbyRsvTime = 24;
-        }
-        else {
-            *pbyTxRate = 0x8D;
-            *pbyRsvTime = 30;
-        }
-        break;
-
-    case RATE_48M :
-        if (ePHYType == PHY_TYPE_11A) {//5GHZ
-            *pbyTxRate = 0x98;
-            *pbyRsvTime = 24;
-        }
-        else {
-            *pbyTxRate = 0x88;
-            *pbyRsvTime = 30;
-        }
-        break;
-
-    case RATE_54M :
-        if (ePHYType == PHY_TYPE_11A) {//5GHZ
-            *pbyTxRate = 0x9C;
-            *pbyRsvTime = 24;
-        }
-        else {
-            *pbyTxRate = 0x8C;
-            *pbyRsvTime = 30;
-        }
-        break;
-
-    case RATE_24M :
-    default :
-        if (ePHYType == PHY_TYPE_11A) {//5GHZ
-            *pbyTxRate = 0x99;
-            *pbyRsvTime = 28;
-        }
-        else {
-            *pbyTxRate = 0x89;
-            *pbyRsvTime = 34;
-        }
-        break;
-    }
+	switch (byRate) {
+	case RATE_6M:
+		if (ePHYType == PHY_TYPE_11A) {//5GHZ
+			*pbyTxRate = 0x9B;
+			*pbyRsvTime = 44;
+		} else {
+			*pbyTxRate = 0x8B;
+			*pbyRsvTime = 50;
+		}
+		break;
+
+	case RATE_9M:
+		if (ePHYType == PHY_TYPE_11A) {//5GHZ
+			*pbyTxRate = 0x9F;
+			*pbyRsvTime = 36;
+		} else {
+			*pbyTxRate = 0x8F;
+			*pbyRsvTime = 42;
+		}
+		break;
+
+	case RATE_12M:
+		if (ePHYType == PHY_TYPE_11A) {//5GHZ
+			*pbyTxRate = 0x9A;
+			*pbyRsvTime = 32;
+		} else {
+			*pbyTxRate = 0x8A;
+			*pbyRsvTime = 38;
+		}
+		break;
+
+	case RATE_18M:
+		if (ePHYType == PHY_TYPE_11A) {//5GHZ
+			*pbyTxRate = 0x9E;
+			*pbyRsvTime = 28;
+		} else {
+			*pbyTxRate = 0x8E;
+			*pbyRsvTime = 34;
+		}
+		break;
+
+	case RATE_36M:
+		if (ePHYType == PHY_TYPE_11A) {//5GHZ
+			*pbyTxRate = 0x9D;
+			*pbyRsvTime = 24;
+		} else {
+			*pbyTxRate = 0x8D;
+			*pbyRsvTime = 30;
+		}
+		break;
+
+	case RATE_48M:
+		if (ePHYType == PHY_TYPE_11A) {//5GHZ
+			*pbyTxRate = 0x98;
+			*pbyRsvTime = 24;
+		} else {
+			*pbyTxRate = 0x88;
+			*pbyRsvTime = 30;
+		}
+		break;
+
+	case RATE_54M:
+		if (ePHYType == PHY_TYPE_11A) {//5GHZ
+			*pbyTxRate = 0x9C;
+			*pbyRsvTime = 24;
+		} else {
+			*pbyTxRate = 0x8C;
+			*pbyRsvTime = 30;
+		}
+		break;
+
+	case RATE_24M:
+	default:
+		if (ePHYType == PHY_TYPE_11A) {//5GHZ
+			*pbyTxRate = 0x99;
+			*pbyRsvTime = 28;
+		} else {
+			*pbyTxRate = 0x89;
+			*pbyRsvTime = 34;
+		}
+		break;
+	}
 }
 
-
-
 /*
  * Description: Set RSPINF
  *
@@ -241,114 +226,114 @@ s_vCalculateOFDMRParameter (
  */
 static
 void
-s_vSetRSPINF (PSDevice pDevice, CARD_PHY_TYPE ePHYType, void *pvSupportRateIEs, void *pvExtSupportRateIEs)
+s_vSetRSPINF(PSDevice pDevice, CARD_PHY_TYPE ePHYType, void *pvSupportRateIEs, void *pvExtSupportRateIEs)
 {
-    unsigned char byServ = 0, bySignal = 0; // For CCK
-    unsigned short wLen = 0;
-    unsigned char byTxRate = 0, byRsvTime = 0;    // For OFDM
-
-    //Set to Page1
-    MACvSelectPage1(pDevice->PortOffset);
-
-    //RSPINF_b_1
-    BBvCalculateParameter(pDevice,
-                         14,
-                         VNTWIFIbyGetACKTxRate(RATE_1M, pvSupportRateIEs, pvExtSupportRateIEs),
-                         PK_TYPE_11B,
-                         &wLen,
-                         &byServ,
-                         &bySignal
-    );
-
-    VNSvOutPortD(pDevice->PortOffset + MAC_REG_RSPINF_B_1, MAKEDWORD(wLen,MAKEWORD(bySignal,byServ)));
-    ///RSPINF_b_2
-    BBvCalculateParameter(pDevice,
-                         14,
-                         VNTWIFIbyGetACKTxRate(RATE_2M, pvSupportRateIEs, pvExtSupportRateIEs),
-                         PK_TYPE_11B,
-                         &wLen,
-                         &byServ,
-                         &bySignal
-    );
-
-    VNSvOutPortD(pDevice->PortOffset + MAC_REG_RSPINF_B_2, MAKEDWORD(wLen,MAKEWORD(bySignal,byServ)));
-    //RSPINF_b_5
-    BBvCalculateParameter(pDevice,
-                         14,
-                         VNTWIFIbyGetACKTxRate(RATE_5M, pvSupportRateIEs, pvExtSupportRateIEs),
-                         PK_TYPE_11B,
-                         &wLen,
-                         &byServ,
-                         &bySignal
-    );
-
-    VNSvOutPortD(pDevice->PortOffset + MAC_REG_RSPINF_B_5, MAKEDWORD(wLen,MAKEWORD(bySignal,byServ)));
-    //RSPINF_b_11
-    BBvCalculateParameter(pDevice,
-                         14,
-                         VNTWIFIbyGetACKTxRate(RATE_11M, pvSupportRateIEs, pvExtSupportRateIEs),
-                         PK_TYPE_11B,
-                         &wLen,
-                         &byServ,
-                         &bySignal
-    );
-
-    VNSvOutPortD(pDevice->PortOffset + MAC_REG_RSPINF_B_11, MAKEDWORD(wLen,MAKEWORD(bySignal,byServ)));
-    //RSPINF_a_6
-    s_vCalculateOFDMRParameter(RATE_6M,
-                              ePHYType,
-                              &byTxRate,
-                              &byRsvTime);
-    VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_6, MAKEWORD(byTxRate,byRsvTime));
-    //RSPINF_a_9
-    s_vCalculateOFDMRParameter(RATE_9M,
-                              ePHYType,
-                              &byTxRate,
-                              &byRsvTime);
-    VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_9, MAKEWORD(byTxRate,byRsvTime));
-    //RSPINF_a_12
-    s_vCalculateOFDMRParameter(RATE_12M,
-                              ePHYType,
-                              &byTxRate,
-                              &byRsvTime);
-    VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_12, MAKEWORD(byTxRate,byRsvTime));
-    //RSPINF_a_18
-    s_vCalculateOFDMRParameter(RATE_18M,
-                              ePHYType,
-                              &byTxRate,
-                              &byRsvTime);
-    VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_18, MAKEWORD(byTxRate,byRsvTime));
-    //RSPINF_a_24
-    s_vCalculateOFDMRParameter(RATE_24M,
-                              ePHYType,
-                              &byTxRate,
-                              &byRsvTime);
-    VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_24, MAKEWORD(byTxRate,byRsvTime));
-    //RSPINF_a_36
-    s_vCalculateOFDMRParameter(
-                              VNTWIFIbyGetACKTxRate(RATE_36M, pvSupportRateIEs, pvExtSupportRateIEs),
-                              ePHYType,
-                              &byTxRate,
-                              &byRsvTime);
-    VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_36, MAKEWORD(byTxRate,byRsvTime));
-    //RSPINF_a_48
-    s_vCalculateOFDMRParameter(
-                              VNTWIFIbyGetACKTxRate(RATE_48M, pvSupportRateIEs, pvExtSupportRateIEs),
-                              ePHYType,
-                              &byTxRate,
-                              &byRsvTime);
-    VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_48, MAKEWORD(byTxRate,byRsvTime));
-    //RSPINF_a_54
-    s_vCalculateOFDMRParameter(
-                              VNTWIFIbyGetACKTxRate(RATE_54M, pvSupportRateIEs, pvExtSupportRateIEs),
-                              ePHYType,
-                              &byTxRate,
-                              &byRsvTime);
-    VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_54, MAKEWORD(byTxRate,byRsvTime));
-    //RSPINF_a_72
-    VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_72, MAKEWORD(byTxRate,byRsvTime));
-    //Set to Page0
-    MACvSelectPage0(pDevice->PortOffset);
+	unsigned char byServ = 0, bySignal = 0; // For CCK
+	unsigned short wLen = 0;
+	unsigned char byTxRate = 0, byRsvTime = 0;    // For OFDM
+
+	//Set to Page1
+	MACvSelectPage1(pDevice->PortOffset);
+
+	//RSPINF_b_1
+	BBvCalculateParameter(pDevice,
+			      14,
+			      VNTWIFIbyGetACKTxRate(RATE_1M, pvSupportRateIEs, pvExtSupportRateIEs),
+			      PK_TYPE_11B,
+			      &wLen,
+			      &byServ,
+			      &bySignal
+);
+
+	VNSvOutPortD(pDevice->PortOffset + MAC_REG_RSPINF_B_1, MAKEDWORD(wLen, MAKEWORD(bySignal, byServ)));
+	///RSPINF_b_2
+	BBvCalculateParameter(pDevice,
+			      14,
+			      VNTWIFIbyGetACKTxRate(RATE_2M, pvSupportRateIEs, pvExtSupportRateIEs),
+			      PK_TYPE_11B,
+			      &wLen,
+			      &byServ,
+			      &bySignal
+);
+
+	VNSvOutPortD(pDevice->PortOffset + MAC_REG_RSPINF_B_2, MAKEDWORD(wLen, MAKEWORD(bySignal, byServ)));
+	//RSPINF_b_5
+	BBvCalculateParameter(pDevice,
+			      14,
+			      VNTWIFIbyGetACKTxRate(RATE_5M, pvSupportRateIEs, pvExtSupportRateIEs),
+			      PK_TYPE_11B,
+			      &wLen,
+			      &byServ,
+			      &bySignal
+);
+
+	VNSvOutPortD(pDevice->PortOffset + MAC_REG_RSPINF_B_5, MAKEDWORD(wLen, MAKEWORD(bySignal, byServ)));
+	//RSPINF_b_11
+	BBvCalculateParameter(pDevice,
+			      14,
+			      VNTWIFIbyGetACKTxRate(RATE_11M, pvSupportRateIEs, pvExtSupportRateIEs),
+			      PK_TYPE_11B,
+			      &wLen,
+			      &byServ,
+			      &bySignal
+);
+
+	VNSvOutPortD(pDevice->PortOffset + MAC_REG_RSPINF_B_11, MAKEDWORD(wLen, MAKEWORD(bySignal, byServ)));
+	//RSPINF_a_6
+	s_vCalculateOFDMRParameter(RATE_6M,
+				   ePHYType,
+				   &byTxRate,
+				   &byRsvTime);
+	VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_6, MAKEWORD(byTxRate, byRsvTime));
+	//RSPINF_a_9
+	s_vCalculateOFDMRParameter(RATE_9M,
+				   ePHYType,
+				   &byTxRate,
+				   &byRsvTime);
+	VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_9, MAKEWORD(byTxRate, byRsvTime));
+	//RSPINF_a_12
+	s_vCalculateOFDMRParameter(RATE_12M,
+				   ePHYType,
+				   &byTxRate,
+				   &byRsvTime);
+	VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_12, MAKEWORD(byTxRate, byRsvTime));
+	//RSPINF_a_18
+	s_vCalculateOFDMRParameter(RATE_18M,
+				   ePHYType,
+				   &byTxRate,
+				   &byRsvTime);
+	VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_18, MAKEWORD(byTxRate, byRsvTime));
+	//RSPINF_a_24
+	s_vCalculateOFDMRParameter(RATE_24M,
+				   ePHYType,
+				   &byTxRate,
+				   &byRsvTime);
+	VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_24, MAKEWORD(byTxRate, byRsvTime));
+	//RSPINF_a_36
+	s_vCalculateOFDMRParameter(
+		VNTWIFIbyGetACKTxRate(RATE_36M, pvSupportRateIEs, pvExtSupportRateIEs),
+		ePHYType,
+		&byTxRate,
+		&byRsvTime);
+	VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_36, MAKEWORD(byTxRate, byRsvTime));
+	//RSPINF_a_48
+	s_vCalculateOFDMRParameter(
+		VNTWIFIbyGetACKTxRate(RATE_48M, pvSupportRateIEs, pvExtSupportRateIEs),
+		ePHYType,
+		&byTxRate,
+		&byRsvTime);
+	VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_48, MAKEWORD(byTxRate, byRsvTime));
+	//RSPINF_a_54
+	s_vCalculateOFDMRParameter(
+		VNTWIFIbyGetACKTxRate(RATE_54M, pvSupportRateIEs, pvExtSupportRateIEs),
+		ePHYType,
+		&byTxRate,
+		&byRsvTime);
+	VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_54, MAKEWORD(byTxRate, byRsvTime));
+	//RSPINF_a_72
+	VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_72, MAKEWORD(byTxRate, byRsvTime));
+	//Set to Page0
+	MACvSelectPage0(pDevice->PortOffset);
 }
 
 /*---------------------  Export Functions  --------------------------*/
@@ -369,22 +354,20 @@ s_vSetRSPINF (PSDevice pDevice, CARD_PHY_TYPE ePHYType, void *pvSupportRateIEs,
  *
  */
 /*
-bool CARDbSendPacket (void *pDeviceHandler, void *pPacket, CARD_PKT_TYPE ePktType, unsigned int uLength)
-{
-    PSDevice    pDevice = (PSDevice) pDeviceHandler;
-    if (ePktType == PKT_TYPE_802_11_MNG) {
-        return TXbTD0Send(pDevice, pPacket, uLength);
-    } else if (ePktType == PKT_TYPE_802_11_BCN) {
-        return TXbBeaconSend(pDevice, pPacket, uLength);
-    } if (ePktType == PKT_TYPE_802_11_DATA) {
-        return TXbTD1Send(pDevice, pPacket, uLength);
-    }
-
-    return (true);
-}
+  bool CARDbSendPacket (void *pDeviceHandler, void *pPacket, CARD_PKT_TYPE ePktType, unsigned int uLength) {
+  PSDevice    pDevice = (PSDevice) pDeviceHandler;
+  if (ePktType == PKT_TYPE_802_11_MNG) {
+  return TXbTD0Send(pDevice, pPacket, uLength);
+  } else if (ePktType == PKT_TYPE_802_11_BCN) {
+  return TXbBeaconSend(pDevice, pPacket, uLength);
+  } if (ePktType == PKT_TYPE_802_11_DATA) {
+  return TXbTD1Send(pDevice, pPacket, uLength);
+  }
+
+  return true;
+  }
 */
 
-
 /*
  * Description: Get Card short preamble option value
  *
@@ -397,13 +380,13 @@ bool CARDbSendPacket (void *pDeviceHandler, void *pPacket, CARD_PKT_TYPE ePktTyp
  * Return Value: true if short preamble; otherwise false
  *
  */
-bool CARDbIsShortPreamble (void *pDeviceHandler)
+bool CARDbIsShortPreamble(void *pDeviceHandler)
 {
-    PSDevice    pDevice = (PSDevice) pDeviceHandler;
-    if (pDevice->byPreambleType == 0) {
-        return(false);
-    }
-    return(true);
+	PSDevice    pDevice = (PSDevice) pDeviceHandler;
+	if (pDevice->byPreambleType == 0) {
+		return false;
+	}
+	return true;
 }
 
 /*
@@ -418,13 +401,12 @@ bool CARDbIsShortPreamble (void *pDeviceHandler)
  * Return Value: true if short slot time; otherwise false
  *
  */
-bool CARDbIsShorSlotTime (void *pDeviceHandler)
+bool CARDbIsShorSlotTime(void *pDeviceHandler)
 {
-    PSDevice    pDevice = (PSDevice) pDeviceHandler;
-    return(pDevice->bShortSlotTime);
+	PSDevice    pDevice = (PSDevice) pDeviceHandler;
+	return pDevice->bShortSlotTime;
 }
 
-
 /*
  * Description: Update IFS
  *
@@ -437,175 +419,174 @@ bool CARDbIsShorSlotTime (void *pDeviceHandler)
  * Return Value: None.
  *
  */
-bool CARDbSetPhyParameter (void *pDeviceHandler, CARD_PHY_TYPE ePHYType, unsigned short wCapInfo, unsigned char byERPField, void *pvSupportRateIEs, void *pvExtSupportRateIEs)
+bool CARDbSetPhyParameter(void *pDeviceHandler, CARD_PHY_TYPE ePHYType, unsigned short wCapInfo, unsigned char byERPField, void *pvSupportRateIEs, void *pvExtSupportRateIEs)
 {
-    PSDevice    pDevice = (PSDevice) pDeviceHandler;
-    unsigned char byCWMaxMin = 0;
-    unsigned char bySlot = 0;
-    unsigned char bySIFS = 0;
-    unsigned char byDIFS = 0;
-    unsigned char byData;
+	PSDevice    pDevice = (PSDevice) pDeviceHandler;
+	unsigned char byCWMaxMin = 0;
+	unsigned char bySlot = 0;
+	unsigned char bySIFS = 0;
+	unsigned char byDIFS = 0;
+	unsigned char byData;
 //    PWLAN_IE_SUPP_RATES pRates = NULL;
-    PWLAN_IE_SUPP_RATES pSupportRates = (PWLAN_IE_SUPP_RATES) pvSupportRateIEs;
-    PWLAN_IE_SUPP_RATES pExtSupportRates = (PWLAN_IE_SUPP_RATES) pvExtSupportRateIEs;
-
-
-    //Set SIFS, DIFS, EIFS, SlotTime, CwMin
-    if (ePHYType == PHY_TYPE_11A) {
-        if (pSupportRates == NULL) {
-            pSupportRates = (PWLAN_IE_SUPP_RATES) abyDefaultSuppRatesA;
-        }
-        if (pDevice->byRFType == RF_AIROHA7230) {
-            // AL7230 use single PAPE and connect to PAPE_2.4G
-            MACvSetBBType(pDevice->PortOffset, BB_TYPE_11G);
-            pDevice->abyBBVGA[0] = 0x20;
-            pDevice->abyBBVGA[2] = 0x10;
-            pDevice->abyBBVGA[3] = 0x10;
-            BBbReadEmbedded(pDevice->PortOffset, 0xE7, &byData);
-            if (byData == 0x1C) {
-                BBbWriteEmbedded(pDevice->PortOffset, 0xE7, pDevice->abyBBVGA[0]);
-            }
-        } else if (pDevice->byRFType == RF_UW2452) {
-            MACvSetBBType(pDevice->PortOffset, BB_TYPE_11A);
-            pDevice->abyBBVGA[0] = 0x18;
-            BBbReadEmbedded(pDevice->PortOffset, 0xE7, &byData);
-            if (byData == 0x14) {
-                BBbWriteEmbedded(pDevice->PortOffset, 0xE7, pDevice->abyBBVGA[0]);
-                BBbWriteEmbedded(pDevice->PortOffset, 0xE1, 0x57);
-            }
-        } else {
-            MACvSetBBType(pDevice->PortOffset, BB_TYPE_11A);
-        }
-        BBbWriteEmbedded(pDevice->PortOffset, 0x88, 0x03);
-        bySlot = C_SLOT_SHORT;
-        bySIFS = C_SIFS_A;
-        byDIFS = C_SIFS_A + 2*C_SLOT_SHORT;
-        byCWMaxMin = 0xA4;
-    } else if (ePHYType == PHY_TYPE_11B) {
-        if (pSupportRates == NULL) {
-            pSupportRates = (PWLAN_IE_SUPP_RATES) abyDefaultSuppRatesB;
-        }
-        MACvSetBBType(pDevice->PortOffset, BB_TYPE_11B);
-        if (pDevice->byRFType == RF_AIROHA7230) {
-            pDevice->abyBBVGA[0] = 0x1C;
-            pDevice->abyBBVGA[2] = 0x00;
-            pDevice->abyBBVGA[3] = 0x00;
-            BBbReadEmbedded(pDevice->PortOffset, 0xE7, &byData);
-            if (byData == 0x20) {
-                BBbWriteEmbedded(pDevice->PortOffset, 0xE7, pDevice->abyBBVGA[0]);
-            }
-        } else if (pDevice->byRFType == RF_UW2452) {
-            pDevice->abyBBVGA[0] = 0x14;
-            BBbReadEmbedded(pDevice->PortOffset, 0xE7, &byData);
-            if (byData == 0x18) {
-                BBbWriteEmbedded(pDevice->PortOffset, 0xE7, pDevice->abyBBVGA[0]);
-                BBbWriteEmbedded(pDevice->PortOffset, 0xE1, 0xD3);
-            }
-        }
-        BBbWriteEmbedded(pDevice->PortOffset, 0x88, 0x02);
-        bySlot = C_SLOT_LONG;
-        bySIFS = C_SIFS_BG;
-        byDIFS = C_SIFS_BG + 2*C_SLOT_LONG;
-        byCWMaxMin = 0xA5;
-    } else {// PK_TYPE_11GA & PK_TYPE_11GB
-        if (pSupportRates == NULL) {
-            pSupportRates = (PWLAN_IE_SUPP_RATES) abyDefaultSuppRatesG;
-            pExtSupportRates = (PWLAN_IE_SUPP_RATES) abyDefaultExtSuppRatesG;
-        }
-        MACvSetBBType(pDevice->PortOffset, BB_TYPE_11G);
-        if (pDevice->byRFType == RF_AIROHA7230) {
-            pDevice->abyBBVGA[0] = 0x1C;
-            pDevice->abyBBVGA[2] = 0x00;
-            pDevice->abyBBVGA[3] = 0x00;
-            BBbReadEmbedded(pDevice->PortOffset, 0xE7, &byData);
-            if (byData == 0x20) {
-                BBbWriteEmbedded(pDevice->PortOffset, 0xE7, pDevice->abyBBVGA[0]);
-            }
-        } else if (pDevice->byRFType == RF_UW2452) {
-            pDevice->abyBBVGA[0] = 0x14;
-            BBbReadEmbedded(pDevice->PortOffset, 0xE7, &byData);
-            if (byData == 0x18) {
-                BBbWriteEmbedded(pDevice->PortOffset, 0xE7, pDevice->abyBBVGA[0]);
-                BBbWriteEmbedded(pDevice->PortOffset, 0xE1, 0xD3);
-            }
-        }
-        BBbWriteEmbedded(pDevice->PortOffset, 0x88, 0x08);
-        bySIFS = C_SIFS_BG;
-        if(VNTWIFIbIsShortSlotTime(wCapInfo)) {
-            bySlot = C_SLOT_SHORT;
-            byDIFS = C_SIFS_BG + 2*C_SLOT_SHORT;
-        } else {
-            bySlot = C_SLOT_LONG;
-            byDIFS = C_SIFS_BG + 2*C_SLOT_LONG;
-	    }
-        if (VNTWIFIbyGetMaxSupportRate(pSupportRates, pExtSupportRates) > RATE_11M) {
-            byCWMaxMin = 0xA4;
-        } else {
-            byCWMaxMin = 0xA5;
-        }
-        if (pDevice->bProtectMode != VNTWIFIbIsProtectMode(byERPField)) {
-            pDevice->bProtectMode = VNTWIFIbIsProtectMode(byERPField);
-            if (pDevice->bProtectMode) {
-                MACvEnableProtectMD(pDevice->PortOffset);
-            } else {
-                MACvDisableProtectMD(pDevice->PortOffset);
-            }
-        }
-        if (pDevice->bBarkerPreambleMd != VNTWIFIbIsBarkerMode(byERPField)) {
-            pDevice->bBarkerPreambleMd = VNTWIFIbIsBarkerMode(byERPField);
-            if (pDevice->bBarkerPreambleMd) {
-                MACvEnableBarkerPreambleMd(pDevice->PortOffset);
-            } else {
-                MACvDisableBarkerPreambleMd(pDevice->PortOffset);
-            }
-        }
-    }
-
-    if (pDevice->byRFType == RF_RFMD2959) {
-        // bcs TX_PE will reserve 3 us
-        // hardware's processing time here is 2 us.
-        bySIFS -= 3;
-        byDIFS -= 3;
-    //{{ RobertYu: 20041202
-    //// TX_PE will reserve 3 us for MAX2829 A mode only, it is for better TX throughput
-    //// MAC will need 2 us to process, so the SIFS, DIFS can be shorter by 2 us.
-    }
-
-    if (pDevice->bySIFS != bySIFS) {
-        pDevice->bySIFS = bySIFS;
-        VNSvOutPortB(pDevice->PortOffset + MAC_REG_SIFS, pDevice->bySIFS);
-    }
-    if (pDevice->byDIFS != byDIFS) {
-        pDevice->byDIFS = byDIFS;
-        VNSvOutPortB(pDevice->PortOffset + MAC_REG_DIFS, pDevice->byDIFS);
-    }
-    if (pDevice->byEIFS != C_EIFS) {
-        pDevice->byEIFS = C_EIFS;
-        VNSvOutPortB(pDevice->PortOffset + MAC_REG_EIFS, pDevice->byEIFS);
-    }
-    if (pDevice->bySlot != bySlot) {
-        pDevice->bySlot = bySlot;
-        VNSvOutPortB(pDevice->PortOffset + MAC_REG_SLOT, pDevice->bySlot);
-        if (pDevice->bySlot == C_SLOT_SHORT) {
-            pDevice->bShortSlotTime = true;
-        } else {
-            pDevice->bShortSlotTime = false;
-        }
-        BBvSetShortSlotTime(pDevice);
-    }
-    if (pDevice->byCWMaxMin != byCWMaxMin) {
-        pDevice->byCWMaxMin = byCWMaxMin;
-        VNSvOutPortB(pDevice->PortOffset + MAC_REG_CWMAXMIN0, pDevice->byCWMaxMin);
-    }
-    if (VNTWIFIbIsShortPreamble(wCapInfo)) {
-        pDevice->byPreambleType = pDevice->byShortPreamble;
-    } else {
-        pDevice->byPreambleType = 0;
-    }
-    s_vSetRSPINF(pDevice, ePHYType, pSupportRates, pExtSupportRates);
-    pDevice->eCurrentPHYType = ePHYType;
-    // set for NDIS OID_802_11SUPPORTED_RATES
-    return (true);
+	PWLAN_IE_SUPP_RATES pSupportRates = (PWLAN_IE_SUPP_RATES) pvSupportRateIEs;
+	PWLAN_IE_SUPP_RATES pExtSupportRates = (PWLAN_IE_SUPP_RATES) pvExtSupportRateIEs;
+
+	//Set SIFS, DIFS, EIFS, SlotTime, CwMin
+	if (ePHYType == PHY_TYPE_11A) {
+		if (pSupportRates == NULL) {
+			pSupportRates = (PWLAN_IE_SUPP_RATES) abyDefaultSuppRatesA;
+		}
+		if (pDevice->byRFType == RF_AIROHA7230) {
+			// AL7230 use single PAPE and connect to PAPE_2.4G
+			MACvSetBBType(pDevice->PortOffset, BB_TYPE_11G);
+			pDevice->abyBBVGA[0] = 0x20;
+			pDevice->abyBBVGA[2] = 0x10;
+			pDevice->abyBBVGA[3] = 0x10;
+			BBbReadEmbedded(pDevice->PortOffset, 0xE7, &byData);
+			if (byData == 0x1C) {
+				BBbWriteEmbedded(pDevice->PortOffset, 0xE7, pDevice->abyBBVGA[0]);
+			}
+		} else if (pDevice->byRFType == RF_UW2452) {
+			MACvSetBBType(pDevice->PortOffset, BB_TYPE_11A);
+			pDevice->abyBBVGA[0] = 0x18;
+			BBbReadEmbedded(pDevice->PortOffset, 0xE7, &byData);
+			if (byData == 0x14) {
+				BBbWriteEmbedded(pDevice->PortOffset, 0xE7, pDevice->abyBBVGA[0]);
+				BBbWriteEmbedded(pDevice->PortOffset, 0xE1, 0x57);
+			}
+		} else {
+			MACvSetBBType(pDevice->PortOffset, BB_TYPE_11A);
+		}
+		BBbWriteEmbedded(pDevice->PortOffset, 0x88, 0x03);
+		bySlot = C_SLOT_SHORT;
+		bySIFS = C_SIFS_A;
+		byDIFS = C_SIFS_A + 2*C_SLOT_SHORT;
+		byCWMaxMin = 0xA4;
+	} else if (ePHYType == PHY_TYPE_11B) {
+		if (pSupportRates == NULL) {
+			pSupportRates = (PWLAN_IE_SUPP_RATES) abyDefaultSuppRatesB;
+		}
+		MACvSetBBType(pDevice->PortOffset, BB_TYPE_11B);
+		if (pDevice->byRFType == RF_AIROHA7230) {
+			pDevice->abyBBVGA[0] = 0x1C;
+			pDevice->abyBBVGA[2] = 0x00;
+			pDevice->abyBBVGA[3] = 0x00;
+			BBbReadEmbedded(pDevice->PortOffset, 0xE7, &byData);
+			if (byData == 0x20) {
+				BBbWriteEmbedded(pDevice->PortOffset, 0xE7, pDevice->abyBBVGA[0]);
+			}
+		} else if (pDevice->byRFType == RF_UW2452) {
+			pDevice->abyBBVGA[0] = 0x14;
+			BBbReadEmbedded(pDevice->PortOffset, 0xE7, &byData);
+			if (byData == 0x18) {
+				BBbWriteEmbedded(pDevice->PortOffset, 0xE7, pDevice->abyBBVGA[0]);
+				BBbWriteEmbedded(pDevice->PortOffset, 0xE1, 0xD3);
+			}
+		}
+		BBbWriteEmbedded(pDevice->PortOffset, 0x88, 0x02);
+		bySlot = C_SLOT_LONG;
+		bySIFS = C_SIFS_BG;
+		byDIFS = C_SIFS_BG + 2*C_SLOT_LONG;
+		byCWMaxMin = 0xA5;
+	} else {// PK_TYPE_11GA & PK_TYPE_11GB
+		if (pSupportRates == NULL) {
+			pSupportRates = (PWLAN_IE_SUPP_RATES) abyDefaultSuppRatesG;
+			pExtSupportRates = (PWLAN_IE_SUPP_RATES) abyDefaultExtSuppRatesG;
+		}
+		MACvSetBBType(pDevice->PortOffset, BB_TYPE_11G);
+		if (pDevice->byRFType == RF_AIROHA7230) {
+			pDevice->abyBBVGA[0] = 0x1C;
+			pDevice->abyBBVGA[2] = 0x00;
+			pDevice->abyBBVGA[3] = 0x00;
+			BBbReadEmbedded(pDevice->PortOffset, 0xE7, &byData);
+			if (byData == 0x20) {
+				BBbWriteEmbedded(pDevice->PortOffset, 0xE7, pDevice->abyBBVGA[0]);
+			}
+		} else if (pDevice->byRFType == RF_UW2452) {
+			pDevice->abyBBVGA[0] = 0x14;
+			BBbReadEmbedded(pDevice->PortOffset, 0xE7, &byData);
+			if (byData == 0x18) {
+				BBbWriteEmbedded(pDevice->PortOffset, 0xE7, pDevice->abyBBVGA[0]);
+				BBbWriteEmbedded(pDevice->PortOffset, 0xE1, 0xD3);
+			}
+		}
+		BBbWriteEmbedded(pDevice->PortOffset, 0x88, 0x08);
+		bySIFS = C_SIFS_BG;
+		if (VNTWIFIbIsShortSlotTime(wCapInfo)) {
+			bySlot = C_SLOT_SHORT;
+			byDIFS = C_SIFS_BG + 2*C_SLOT_SHORT;
+		} else {
+			bySlot = C_SLOT_LONG;
+			byDIFS = C_SIFS_BG + 2*C_SLOT_LONG;
+		}
+		if (VNTWIFIbyGetMaxSupportRate(pSupportRates, pExtSupportRates) > RATE_11M) {
+			byCWMaxMin = 0xA4;
+		} else {
+			byCWMaxMin = 0xA5;
+		}
+		if (pDevice->bProtectMode != VNTWIFIbIsProtectMode(byERPField)) {
+			pDevice->bProtectMode = VNTWIFIbIsProtectMode(byERPField);
+			if (pDevice->bProtectMode) {
+				MACvEnableProtectMD(pDevice->PortOffset);
+			} else {
+				MACvDisableProtectMD(pDevice->PortOffset);
+			}
+		}
+		if (pDevice->bBarkerPreambleMd != VNTWIFIbIsBarkerMode(byERPField)) {
+			pDevice->bBarkerPreambleMd = VNTWIFIbIsBarkerMode(byERPField);
+			if (pDevice->bBarkerPreambleMd) {
+				MACvEnableBarkerPreambleMd(pDevice->PortOffset);
+			} else {
+				MACvDisableBarkerPreambleMd(pDevice->PortOffset);
+			}
+		}
+	}
+
+	if (pDevice->byRFType == RF_RFMD2959) {
+		// bcs TX_PE will reserve 3 us
+		// hardware's processing time here is 2 us.
+		bySIFS -= 3;
+		byDIFS -= 3;
+		//{{ RobertYu: 20041202
+		//// TX_PE will reserve 3 us for MAX2829 A mode only, it is for better TX throughput
+		//// MAC will need 2 us to process, so the SIFS, DIFS can be shorter by 2 us.
+	}
+
+	if (pDevice->bySIFS != bySIFS) {
+		pDevice->bySIFS = bySIFS;
+		VNSvOutPortB(pDevice->PortOffset + MAC_REG_SIFS, pDevice->bySIFS);
+	}
+	if (pDevice->byDIFS != byDIFS) {
+		pDevice->byDIFS = byDIFS;
+		VNSvOutPortB(pDevice->PortOffset + MAC_REG_DIFS, pDevice->byDIFS);
+	}
+	if (pDevice->byEIFS != C_EIFS) {
+		pDevice->byEIFS = C_EIFS;
+		VNSvOutPortB(pDevice->PortOffset + MAC_REG_EIFS, pDevice->byEIFS);
+	}
+	if (pDevice->bySlot != bySlot) {
+		pDevice->bySlot = bySlot;
+		VNSvOutPortB(pDevice->PortOffset + MAC_REG_SLOT, pDevice->bySlot);
+		if (pDevice->bySlot == C_SLOT_SHORT) {
+			pDevice->bShortSlotTime = true;
+		} else {
+			pDevice->bShortSlotTime = false;
+		}
+		BBvSetShortSlotTime(pDevice);
+	}
+	if (pDevice->byCWMaxMin != byCWMaxMin) {
+		pDevice->byCWMaxMin = byCWMaxMin;
+		VNSvOutPortB(pDevice->PortOffset + MAC_REG_CWMAXMIN0, pDevice->byCWMaxMin);
+	}
+	if (VNTWIFIbIsShortPreamble(wCapInfo)) {
+		pDevice->byPreambleType = pDevice->byShortPreamble;
+	} else {
+		pDevice->byPreambleType = 0;
+	}
+	s_vSetRSPINF(pDevice, ePHYType, pSupportRates, pExtSupportRates);
+	pDevice->eCurrentPHYType = ePHYType;
+	// set for NDIS OID_802_11SUPPORTED_RATES
+	return true;
 }
 
 /*
@@ -624,27 +605,26 @@ bool CARDbSetPhyParameter (void *pDeviceHandler, CARD_PHY_TYPE ePHYType, unsigne
  * Return Value: none
  *
  */
-bool CARDbUpdateTSF (void *pDeviceHandler, unsigned char byRxRate, QWORD qwBSSTimestamp, QWORD qwLocalTSF)
+bool CARDbUpdateTSF(void *pDeviceHandler, unsigned char byRxRate, QWORD qwBSSTimestamp, QWORD qwLocalTSF)
 {
-    PSDevice    pDevice = (PSDevice) pDeviceHandler;
-    QWORD       qwTSFOffset;
-
-    HIDWORD(qwTSFOffset) = 0;
-    LODWORD(qwTSFOffset) = 0;
-
-    if ((HIDWORD(qwBSSTimestamp) != HIDWORD(qwLocalTSF)) ||
-        (LODWORD(qwBSSTimestamp) != LODWORD(qwLocalTSF))) {
-        qwTSFOffset = CARDqGetTSFOffset(byRxRate, qwBSSTimestamp, qwLocalTSF);
-        // adjust TSF
-        // HW's TSF add TSF Offset reg
-        VNSvOutPortD(pDevice->PortOffset + MAC_REG_TSFOFST, LODWORD(qwTSFOffset));
-        VNSvOutPortD(pDevice->PortOffset + MAC_REG_TSFOFST + 4, HIDWORD(qwTSFOffset));
-        MACvRegBitsOn(pDevice->PortOffset, MAC_REG_TFTCTL, TFTCTL_TSFSYNCEN);
-    }
-    return(true);
+	PSDevice    pDevice = (PSDevice) pDeviceHandler;
+	QWORD       qwTSFOffset;
+
+	HIDWORD(qwTSFOffset) = 0;
+	LODWORD(qwTSFOffset) = 0;
+
+	if ((HIDWORD(qwBSSTimestamp) != HIDWORD(qwLocalTSF)) ||
+	    (LODWORD(qwBSSTimestamp) != LODWORD(qwLocalTSF))) {
+		qwTSFOffset = CARDqGetTSFOffset(byRxRate, qwBSSTimestamp, qwLocalTSF);
+		// adjust TSF
+		// HW's TSF add TSF Offset reg
+		VNSvOutPortD(pDevice->PortOffset + MAC_REG_TSFOFST, LODWORD(qwTSFOffset));
+		VNSvOutPortD(pDevice->PortOffset + MAC_REG_TSFOFST + 4, HIDWORD(qwTSFOffset));
+		MACvRegBitsOn(pDevice->PortOffset, MAC_REG_TFTCTL, TFTCTL_TSFSYNCEN);
+	}
+	return true;
 }
 
-
 /*
  * Description: Set NIC TSF counter for first Beacon time
  *              Get NEXTTBTT from adjusted TSF and Beacon Interval
@@ -659,47 +639,45 @@ bool CARDbUpdateTSF (void *pDeviceHandler, unsigned char byRxRate, QWORD qwBSSTi
  * Return Value: true if succeed; otherwise false
  *
  */
-bool CARDbSetBeaconPeriod (void *pDeviceHandler, unsigned short wBeaconInterval)
+bool CARDbSetBeaconPeriod(void *pDeviceHandler, unsigned short wBeaconInterval)
 {
-    PSDevice    pDevice = (PSDevice) pDeviceHandler;
-    unsigned int uBeaconInterval = 0;
-    unsigned int uLowNextTBTT = 0;
-    unsigned int uHighRemain = 0;
-    unsigned int uLowRemain = 0;
-    QWORD       qwNextTBTT;
-
-    HIDWORD(qwNextTBTT) = 0;
-    LODWORD(qwNextTBTT) = 0;
-    CARDbGetCurrentTSF(pDevice->PortOffset, &qwNextTBTT); //Get Local TSF counter
-    uBeaconInterval = wBeaconInterval * 1024;
-    // Next TBTT = ((local_current_TSF / beacon_interval) + 1 ) * beacon_interval
-    uLowNextTBTT = (LODWORD(qwNextTBTT) >> 10) << 10;
-    uLowRemain = (uLowNextTBTT) % uBeaconInterval;
-    // high dword (mod) bcn
-    uHighRemain = (((0xffffffff % uBeaconInterval) + 1) * HIDWORD(qwNextTBTT))
-                  % uBeaconInterval;
-    uLowRemain = (uHighRemain + uLowRemain) % uBeaconInterval;
-    uLowRemain = uBeaconInterval - uLowRemain;
-
-    // check if carry when add one beacon interval
-    if ((~uLowNextTBTT) < uLowRemain) {
-        HIDWORD(qwNextTBTT) ++ ;
-    }
-    LODWORD(qwNextTBTT) = uLowNextTBTT + uLowRemain;
-
-    // set HW beacon interval
-    VNSvOutPortW(pDevice->PortOffset + MAC_REG_BI, wBeaconInterval);
-    pDevice->wBeaconInterval = wBeaconInterval;
-    // Set NextTBTT
-    VNSvOutPortD(pDevice->PortOffset + MAC_REG_NEXTTBTT, LODWORD(qwNextTBTT));
-    VNSvOutPortD(pDevice->PortOffset + MAC_REG_NEXTTBTT + 4, HIDWORD(qwNextTBTT));
-    MACvRegBitsOn(pDevice->PortOffset, MAC_REG_TFTCTL, TFTCTL_TBTTSYNCEN);
-
-    return(true);
+	PSDevice    pDevice = (PSDevice) pDeviceHandler;
+	unsigned int uBeaconInterval = 0;
+	unsigned int uLowNextTBTT = 0;
+	unsigned int uHighRemain = 0;
+	unsigned int uLowRemain = 0;
+	QWORD       qwNextTBTT;
+
+	HIDWORD(qwNextTBTT) = 0;
+	LODWORD(qwNextTBTT) = 0;
+	CARDbGetCurrentTSF(pDevice->PortOffset, &qwNextTBTT); //Get Local TSF counter
+	uBeaconInterval = wBeaconInterval * 1024;
+	// Next TBTT = ((local_current_TSF / beacon_interval) + 1) * beacon_interval
+	uLowNextTBTT = (LODWORD(qwNextTBTT) >> 10) << 10;
+	uLowRemain = (uLowNextTBTT) % uBeaconInterval;
+	// high dword (mod) bcn
+	uHighRemain = (((0xffffffff % uBeaconInterval) + 1) * HIDWORD(qwNextTBTT))
+		% uBeaconInterval;
+	uLowRemain = (uHighRemain + uLowRemain) % uBeaconInterval;
+	uLowRemain = uBeaconInterval - uLowRemain;
+
+	// check if carry when add one beacon interval
+	if ((~uLowNextTBTT) < uLowRemain) {
+		HIDWORD(qwNextTBTT)++;
+	}
+	LODWORD(qwNextTBTT) = uLowNextTBTT + uLowRemain;
+
+	// set HW beacon interval
+	VNSvOutPortW(pDevice->PortOffset + MAC_REG_BI, wBeaconInterval);
+	pDevice->wBeaconInterval = wBeaconInterval;
+	// Set NextTBTT
+	VNSvOutPortD(pDevice->PortOffset + MAC_REG_NEXTTBTT, LODWORD(qwNextTBTT));
+	VNSvOutPortD(pDevice->PortOffset + MAC_REG_NEXTTBTT + 4, HIDWORD(qwNextTBTT));
+	MACvRegBitsOn(pDevice->PortOffset, MAC_REG_TFTCTL, TFTCTL_TBTTSYNCEN);
+
+	return true;
 }
 
-
-
 /*
  * Description: Card Stop Hardware Tx
  *
@@ -713,51 +691,49 @@ bool CARDbSetBeaconPeriod (void *pDeviceHandler, unsigned short wBeaconInterval)
  * Return Value: true if all data packet complete; otherwise false.
  *
  */
-bool CARDbStopTxPacket (void *pDeviceHandler, CARD_PKT_TYPE ePktType)
+bool CARDbStopTxPacket(void *pDeviceHandler, CARD_PKT_TYPE ePktType)
 {
-    PSDevice    pDevice = (PSDevice) pDeviceHandler;
-
-
-    if (ePktType == PKT_TYPE_802_11_ALL) {
-        pDevice->bStopBeacon = true;
-        pDevice->bStopTx0Pkt = true;
-        pDevice->bStopDataPkt = true;
-    } else if (ePktType == PKT_TYPE_802_11_BCN) {
-        pDevice->bStopBeacon = true;
-    } else if (ePktType == PKT_TYPE_802_11_MNG) {
-        pDevice->bStopTx0Pkt = true;
-    } else if (ePktType == PKT_TYPE_802_11_DATA) {
-        pDevice->bStopDataPkt = true;
-    }
-
-    if (pDevice->bStopBeacon == true) {
-        if (pDevice->bIsBeaconBufReadySet == true) {
-            if (pDevice->cbBeaconBufReadySetCnt < WAIT_BEACON_TX_DOWN_TMO) {
-                pDevice->cbBeaconBufReadySetCnt ++;
-                return(false);
-            }
-        }
-        pDevice->bIsBeaconBufReadySet = false;
-        pDevice->cbBeaconBufReadySetCnt = 0;
-        MACvRegBitsOff(pDevice->PortOffset, MAC_REG_TCR, TCR_AUTOBCNTX);
-    }
-    // wait all TD0 complete
-    if (pDevice->bStopTx0Pkt == true) {
-         if (pDevice->iTDUsed[TYPE_TXDMA0] != 0){
-            return(false);
-        }
-    }
-    // wait all Data TD complete
-    if (pDevice->bStopDataPkt == true) {
-        if (pDevice->iTDUsed[TYPE_AC0DMA] != 0){
-            return(false);
-        }
-    }
-
-    return(true);
+	PSDevice    pDevice = (PSDevice) pDeviceHandler;
+
+	if (ePktType == PKT_TYPE_802_11_ALL) {
+		pDevice->bStopBeacon = true;
+		pDevice->bStopTx0Pkt = true;
+		pDevice->bStopDataPkt = true;
+	} else if (ePktType == PKT_TYPE_802_11_BCN) {
+		pDevice->bStopBeacon = true;
+	} else if (ePktType == PKT_TYPE_802_11_MNG) {
+		pDevice->bStopTx0Pkt = true;
+	} else if (ePktType == PKT_TYPE_802_11_DATA) {
+		pDevice->bStopDataPkt = true;
+	}
+
+	if (pDevice->bStopBeacon == true) {
+		if (pDevice->bIsBeaconBufReadySet == true) {
+			if (pDevice->cbBeaconBufReadySetCnt < WAIT_BEACON_TX_DOWN_TMO) {
+				pDevice->cbBeaconBufReadySetCnt++;
+				return false;
+			}
+		}
+		pDevice->bIsBeaconBufReadySet = false;
+		pDevice->cbBeaconBufReadySetCnt = 0;
+		MACvRegBitsOff(pDevice->PortOffset, MAC_REG_TCR, TCR_AUTOBCNTX);
+	}
+	// wait all TD0 complete
+	if (pDevice->bStopTx0Pkt == true) {
+		if (pDevice->iTDUsed[TYPE_TXDMA0] != 0) {
+			return false;
+		}
+	}
+	// wait all Data TD complete
+	if (pDevice->bStopDataPkt == true) {
+		if (pDevice->iTDUsed[TYPE_AC0DMA] != 0) {
+			return false;
+		}
+	}
+
+	return true;
 }
 
-
 /*
  * Description: Card Start Hardware Tx
  *
@@ -771,34 +747,31 @@ bool CARDbStopTxPacket (void *pDeviceHandler, CARD_PKT_TYPE ePktType)
  * Return Value: true if success; false if failed.
  *
  */
-bool CARDbStartTxPacket (void *pDeviceHandler, CARD_PKT_TYPE ePktType)
+bool CARDbStartTxPacket(void *pDeviceHandler, CARD_PKT_TYPE ePktType)
 {
-    PSDevice    pDevice = (PSDevice) pDeviceHandler;
-
-
-    if (ePktType == PKT_TYPE_802_11_ALL) {
-        pDevice->bStopBeacon = false;
-        pDevice->bStopTx0Pkt = false;
-        pDevice->bStopDataPkt = false;
-    } else if (ePktType == PKT_TYPE_802_11_BCN) {
-        pDevice->bStopBeacon = false;
-    } else if (ePktType == PKT_TYPE_802_11_MNG) {
-        pDevice->bStopTx0Pkt = false;
-    } else if (ePktType == PKT_TYPE_802_11_DATA) {
-        pDevice->bStopDataPkt = false;
-    }
-
-    if ((pDevice->bStopBeacon == false) &&
-        (pDevice->bBeaconBufReady == true) &&
-        (pDevice->eOPMode == OP_MODE_ADHOC)) {
-        MACvRegBitsOn(pDevice->PortOffset, MAC_REG_TCR, TCR_AUTOBCNTX);
-    }
-
-    return(true);
+	PSDevice    pDevice = (PSDevice) pDeviceHandler;
+
+	if (ePktType == PKT_TYPE_802_11_ALL) {
+		pDevice->bStopBeacon = false;
+		pDevice->bStopTx0Pkt = false;
+		pDevice->bStopDataPkt = false;
+	} else if (ePktType == PKT_TYPE_802_11_BCN) {
+		pDevice->bStopBeacon = false;
+	} else if (ePktType == PKT_TYPE_802_11_MNG) {
+		pDevice->bStopTx0Pkt = false;
+	} else if (ePktType == PKT_TYPE_802_11_DATA) {
+		pDevice->bStopDataPkt = false;
+	}
+
+	if ((pDevice->bStopBeacon == false) &&
+	    (pDevice->bBeaconBufReady == true) &&
+	    (pDevice->eOPMode == OP_MODE_ADHOC)) {
+		MACvRegBitsOn(pDevice->PortOffset, MAC_REG_TCR, TCR_AUTOBCNTX);
+	}
+
+	return true;
 }
 
-
-
 /*
  * Description: Card Set BSSID value
  *
@@ -815,39 +788,38 @@ bool CARDbStartTxPacket (void *pDeviceHandler, CARD_PKT_TYPE ePktType)
  */
 bool CARDbSetBSSID(void *pDeviceHandler, unsigned char *pbyBSSID, CARD_OP_MODE eOPMode)
 {
-    PSDevice    pDevice = (PSDevice) pDeviceHandler;
-
-    MACvWriteBSSIDAddress(pDevice->PortOffset, pbyBSSID);
-    memcpy(pDevice->abyBSSID, pbyBSSID, WLAN_BSSID_LEN);
-    if (eOPMode == OP_MODE_ADHOC) {
-        MACvRegBitsOn(pDevice->PortOffset, MAC_REG_HOSTCR, HOSTCR_ADHOC);
-    } else {
-        MACvRegBitsOff(pDevice->PortOffset, MAC_REG_HOSTCR, HOSTCR_ADHOC);
-    }
-    if (eOPMode == OP_MODE_AP) {
-        MACvRegBitsOn(pDevice->PortOffset, MAC_REG_HOSTCR, HOSTCR_AP);
-    } else {
-        MACvRegBitsOff(pDevice->PortOffset, MAC_REG_HOSTCR, HOSTCR_AP);
-    }
-    if (eOPMode == OP_MODE_UNKNOWN) {
-        MACvRegBitsOff(pDevice->PortOffset, MAC_REG_RCR, RCR_BSSID);
-        pDevice->bBSSIDFilter = false;
-        pDevice->byRxMode &= ~RCR_BSSID;
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wcmd: rx_mode = %x\n", pDevice->byRxMode );
-    } else {
-        if (is_zero_ether_addr(pDevice->abyBSSID) == false) {
-            MACvRegBitsOn(pDevice->PortOffset, MAC_REG_RCR, RCR_BSSID);
-            pDevice->bBSSIDFilter = true;
-            pDevice->byRxMode |= RCR_BSSID;
-	    }
-	    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wmgr: rx_mode = %x\n", pDevice->byRxMode );
-    }
-    // Adopt BSS state in Adapter Device Object
-    pDevice->eOPMode = eOPMode;
-    return(true);
+	PSDevice    pDevice = (PSDevice) pDeviceHandler;
+
+	MACvWriteBSSIDAddress(pDevice->PortOffset, pbyBSSID);
+	memcpy(pDevice->abyBSSID, pbyBSSID, WLAN_BSSID_LEN);
+	if (eOPMode == OP_MODE_ADHOC) {
+		MACvRegBitsOn(pDevice->PortOffset, MAC_REG_HOSTCR, HOSTCR_ADHOC);
+	} else {
+		MACvRegBitsOff(pDevice->PortOffset, MAC_REG_HOSTCR, HOSTCR_ADHOC);
+	}
+	if (eOPMode == OP_MODE_AP) {
+		MACvRegBitsOn(pDevice->PortOffset, MAC_REG_HOSTCR, HOSTCR_AP);
+	} else {
+		MACvRegBitsOff(pDevice->PortOffset, MAC_REG_HOSTCR, HOSTCR_AP);
+	}
+	if (eOPMode == OP_MODE_UNKNOWN) {
+		MACvRegBitsOff(pDevice->PortOffset, MAC_REG_RCR, RCR_BSSID);
+		pDevice->bBSSIDFilter = false;
+		pDevice->byRxMode &= ~RCR_BSSID;
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wcmd: rx_mode = %x\n", pDevice->byRxMode);
+	} else {
+		if (is_zero_ether_addr(pDevice->abyBSSID) == false) {
+			MACvRegBitsOn(pDevice->PortOffset, MAC_REG_RCR, RCR_BSSID);
+			pDevice->bBSSIDFilter = true;
+			pDevice->byRxMode |= RCR_BSSID;
+		}
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wmgr: rx_mode = %x\n", pDevice->byRxMode);
+	}
+	// Adopt BSS state in Adapter Device Object
+	pDevice->eOPMode = eOPMode;
+	return true;
 }
 
-
 /*
  * Description: Card indicate status
  *
@@ -862,9 +834,6 @@ bool CARDbSetBSSID(void *pDeviceHandler, unsigned char *pbyBSSID, CARD_OP_MODE e
  *
  */
 
-
-
-
 /*
  * Description: Save Assoc info. contain in assoc. response frame
  *
@@ -883,14 +852,14 @@ bool CARDbSetBSSID(void *pDeviceHandler, unsigned char *pbyBSSID, CARD_OP_MODE e
  *
  */
 bool CARDbSetTxDataRate(
-    void *pDeviceHandler,
-    unsigned short wDataRate
-    )
+	void *pDeviceHandler,
+	unsigned short wDataRate
+)
 {
-    PSDevice    pDevice = (PSDevice) pDeviceHandler;
+	PSDevice    pDevice = (PSDevice) pDeviceHandler;
 
-    pDevice->wCurrentRate = wDataRate;
-    return(true);
+	pDevice->wCurrentRate = wDataRate;
+	return true;
 }
 
 /*+
@@ -906,32 +875,32 @@ bool CARDbSetTxDataRate(
  *
  * Return Value: true if power down success; otherwise false
  *
--*/
+ -*/
 bool
 CARDbPowerDown(
-    void *pDeviceHandler
-    )
+	void *pDeviceHandler
+)
 {
-    PSDevice        pDevice = (PSDevice)pDeviceHandler;
-    unsigned int uIdx;
+	PSDevice        pDevice = (PSDevice)pDeviceHandler;
+	unsigned int uIdx;
 
-    // check if already in Doze mode
-    if (MACbIsRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_PS))
-        return true;
+	// check if already in Doze mode
+	if (MACbIsRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_PS))
+		return true;
 
-    // Froce PSEN on
-    MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_PSEN);
+	// Froce PSEN on
+	MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_PSEN);
 
-    // check if all TD are empty,
+	// check if all TD are empty,
 
-    for (uIdx = 0; uIdx < TYPE_MAXTD; uIdx ++) {
-        if (pDevice->iTDUsed[uIdx] != 0)
-            return false;
-    }
+	for (uIdx = 0; uIdx < TYPE_MAXTD; uIdx++) {
+		if (pDevice->iTDUsed[uIdx] != 0)
+			return false;
+	}
 
-    MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_GO2DOZE);
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Go to Doze ZZZZZZZZZZZZZZZ\n");
-    return true;
+	MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_GO2DOZE);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Go to Doze ZZZZZZZZZZZZZZZ\n");
+	return true;
 }
 
 /*
@@ -946,43 +915,40 @@ CARDbPowerDown(
  * Return Value: true if success; otherwise false
  *
  */
-bool CARDbRadioPowerOff (void *pDeviceHandler)
+bool CARDbRadioPowerOff(void *pDeviceHandler)
 {
-    PSDevice    pDevice = (PSDevice) pDeviceHandler;
-    bool bResult = true;
-
-    if (pDevice->bRadioOff == true)
-        return true;
+	PSDevice    pDevice = (PSDevice)pDeviceHandler;
+	bool bResult = true;
 
+	if (pDevice->bRadioOff == true)
+		return true;
 
-    switch (pDevice->byRFType) {
+	switch (pDevice->byRFType) {
+	case RF_RFMD2959:
+		MACvWordRegBitsOff(pDevice->PortOffset, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_TXPEINV);
+		MACvWordRegBitsOn(pDevice->PortOffset, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE1);
+		break;
 
-        case RF_RFMD2959:
-            MACvWordRegBitsOff(pDevice->PortOffset, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_TXPEINV);
-            MACvWordRegBitsOn(pDevice->PortOffset, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE1);
-            break;
+	case RF_AIROHA:
+	case RF_AL2230S:
+	case RF_AIROHA7230: //RobertYu:20050104
+		MACvWordRegBitsOff(pDevice->PortOffset, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE2);
+		MACvWordRegBitsOff(pDevice->PortOffset, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3);
+		break;
 
-        case RF_AIROHA:
-        case RF_AL2230S:
-        case RF_AIROHA7230: //RobertYu:20050104
-            MACvWordRegBitsOff(pDevice->PortOffset, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE2);
-            MACvWordRegBitsOff(pDevice->PortOffset, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3);
-            break;
+	}
 
-    }
+	MACvRegBitsOff(pDevice->PortOffset, MAC_REG_HOSTCR, HOSTCR_RXON);
 
-    MACvRegBitsOff(pDevice->PortOffset, MAC_REG_HOSTCR, HOSTCR_RXON);
+	BBvSetDeepSleep(pDevice->PortOffset, pDevice->byLocalID);
 
-    BBvSetDeepSleep(pDevice->PortOffset, pDevice->byLocalID);
-
-    pDevice->bRadioOff = true;
-     //2007-0409-03,<Add> by chester
-printk("chester power off\n");
-MACvRegBitsOn(pDevice->PortOffset, MAC_REG_GPIOCTL0, LED_ACTSET);  //LED issue
-    return bResult;
+	pDevice->bRadioOff = true;
+	//2007-0409-03,<Add> by chester
+	printk("chester power off\n");
+	MACvRegBitsOn(pDevice->PortOffset, MAC_REG_GPIOCTL0, LED_ACTSET);  //LED issue
+	return bResult;
 }
 
-
 /*
  * Description: Turn on Radio power
  *
@@ -995,59 +961,54 @@ MACvRegBitsOn(pDevice->PortOffset, MAC_REG_GPIOCTL0, LED_ACTSET);  //LED issue
  * Return Value: true if success; otherwise false
  *
  */
-bool CARDbRadioPowerOn (void *pDeviceHandler)
+bool CARDbRadioPowerOn(void *pDeviceHandler)
 {
-    PSDevice    pDevice = (PSDevice) pDeviceHandler;
-    bool bResult = true;
-printk("chester power on\n");
-    if (pDevice->bRadioControlOff == true){
-if (pDevice->bHWRadioOff == true) printk("chester bHWRadioOff\n");
-if (pDevice->bRadioControlOff == true) printk("chester bRadioControlOff\n");
-        return false;}
-
-    if (pDevice->bRadioOff == false)
-       {
-printk("chester pbRadioOff\n");
-return true;}
-
-    BBvExitDeepSleep(pDevice->PortOffset, pDevice->byLocalID);
-
-    MACvRegBitsOn(pDevice->PortOffset, MAC_REG_HOSTCR, HOSTCR_RXON);
-
-    switch (pDevice->byRFType) {
-
-        case RF_RFMD2959:
-            MACvWordRegBitsOn(pDevice->PortOffset, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_TXPEINV);
-            MACvWordRegBitsOff(pDevice->PortOffset, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE1);
-            break;
-
-        case RF_AIROHA:
-        case RF_AL2230S:
-        case RF_AIROHA7230: //RobertYu:20050104
-            MACvWordRegBitsOn(pDevice->PortOffset, MAC_REG_SOFTPWRCTL, (SOFTPWRCTL_SWPE2 |
-                                                                        SOFTPWRCTL_SWPE3));
-            break;
-
-    }
-
-    pDevice->bRadioOff = false;
+	PSDevice    pDevice = (PSDevice) pDeviceHandler;
+	bool bResult = true;
+	printk("chester power on\n");
+	if (pDevice->bRadioControlOff == true) {
+		if (pDevice->bHWRadioOff == true) printk("chester bHWRadioOff\n");
+		if (pDevice->bRadioControlOff == true) printk("chester bRadioControlOff\n");
+		return false; }
+
+	if (pDevice->bRadioOff == false) {
+		printk("chester pbRadioOff\n");
+		return true; }
+
+	BBvExitDeepSleep(pDevice->PortOffset, pDevice->byLocalID);
+
+	MACvRegBitsOn(pDevice->PortOffset, MAC_REG_HOSTCR, HOSTCR_RXON);
+
+	switch (pDevice->byRFType) {
+	case RF_RFMD2959:
+		MACvWordRegBitsOn(pDevice->PortOffset, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_TXPEINV);
+		MACvWordRegBitsOff(pDevice->PortOffset, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE1);
+		break;
+
+	case RF_AIROHA:
+	case RF_AL2230S:
+	case RF_AIROHA7230: //RobertYu:20050104
+		MACvWordRegBitsOn(pDevice->PortOffset, MAC_REG_SOFTPWRCTL, (SOFTPWRCTL_SWPE2 |
+									    SOFTPWRCTL_SWPE3));
+		break;
+
+	}
+
+	pDevice->bRadioOff = false;
 //  2007-0409-03,<Add> by chester
-printk("chester power on\n");
-MACvRegBitsOff(pDevice->PortOffset, MAC_REG_GPIOCTL0, LED_ACTSET); //LED issue
-    return bResult;
+	printk("chester power on\n");
+	MACvRegBitsOff(pDevice->PortOffset, MAC_REG_GPIOCTL0, LED_ACTSET); //LED issue
+	return bResult;
 }
 
-
-
-bool CARDbRemoveKey (void *pDeviceHandler, unsigned char *pbyBSSID)
+bool CARDbRemoveKey(void *pDeviceHandler, unsigned char *pbyBSSID)
 {
-    PSDevice    pDevice = (PSDevice) pDeviceHandler;
+	PSDevice    pDevice = (PSDevice) pDeviceHandler;
 
-    KeybRemoveAllKey(&(pDevice->sKey), pbyBSSID, pDevice->PortOffset);
-    return (true);
+	KeybRemoveAllKey(&(pDevice->sKey), pbyBSSID, pDevice->PortOffset);
+	return true;
 }
 
-
 /*
  *
  * Description:
@@ -1063,66 +1024,65 @@ bool CARDbRemoveKey (void *pDeviceHandler, unsigned char *pbyBSSID)
  *
  * Return Value: none.
  *
--*/
+ -*/
 bool
-CARDbAdd_PMKID_Candidate (
-    void *pDeviceHandler,
-    unsigned char *pbyBSSID,
-    bool bRSNCapExist,
-    unsigned short wRSNCap
-    )
+CARDbAdd_PMKID_Candidate(
+	void *pDeviceHandler,
+	unsigned char *pbyBSSID,
+	bool bRSNCapExist,
+	unsigned short wRSNCap
+)
 {
-    PSDevice            pDevice = (PSDevice) pDeviceHandler;
-    PPMKID_CANDIDATE    pCandidateList;
-    unsigned int ii = 0;
-
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"bAdd_PMKID_Candidate START: (%d)\n", (int)pDevice->gsPMKIDCandidate.NumCandidates);
-
-    if (pDevice->gsPMKIDCandidate.NumCandidates >= MAX_PMKIDLIST) {
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"vFlush_PMKID_Candidate: 3\n");
-        memset(&pDevice->gsPMKIDCandidate, 0, sizeof(SPMKIDCandidateEvent));
-    }
-
-    for (ii = 0; ii < 6; ii++) {
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"%02X ", *(pbyBSSID + ii));
-    }
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n");
-
-
-    // Update Old Candidate
-    for (ii = 0; ii < pDevice->gsPMKIDCandidate.NumCandidates; ii++) {
-        pCandidateList = &pDevice->gsPMKIDCandidate.CandidateList[ii];
-        if ( !memcmp(pCandidateList->BSSID, pbyBSSID, ETH_ALEN)) {
-            if ((bRSNCapExist == true) && (wRSNCap & BIT0)) {
-                pCandidateList->Flags |= NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED;
-            } else {
-                pCandidateList->Flags &= ~(NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED);
-            }
-            return true;
-        }
-    }
-
-    // New Candidate
-    pCandidateList = &pDevice->gsPMKIDCandidate.CandidateList[pDevice->gsPMKIDCandidate.NumCandidates];
-    if ((bRSNCapExist == true) && (wRSNCap & BIT0)) {
-        pCandidateList->Flags |= NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED;
-    } else {
-        pCandidateList->Flags &= ~(NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED);
-    }
-    memcpy(pCandidateList->BSSID, pbyBSSID, ETH_ALEN);
-    pDevice->gsPMKIDCandidate.NumCandidates++;
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"NumCandidates:%d\n", (int)pDevice->gsPMKIDCandidate.NumCandidates);
-    return true;
+	PSDevice            pDevice = (PSDevice) pDeviceHandler;
+	PPMKID_CANDIDATE    pCandidateList;
+	unsigned int ii = 0;
+
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "bAdd_PMKID_Candidate START: (%d)\n", (int)pDevice->gsPMKIDCandidate.NumCandidates);
+
+	if (pDevice->gsPMKIDCandidate.NumCandidates >= MAX_PMKIDLIST) {
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "vFlush_PMKID_Candidate: 3\n");
+		memset(&pDevice->gsPMKIDCandidate, 0, sizeof(SPMKIDCandidateEvent));
+	}
+
+	for (ii = 0; ii < 6; ii++) {
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%02X ", *(pbyBSSID + ii));
+	}
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "\n");
+
+	// Update Old Candidate
+	for (ii = 0; ii < pDevice->gsPMKIDCandidate.NumCandidates; ii++) {
+		pCandidateList = &pDevice->gsPMKIDCandidate.CandidateList[ii];
+		if (!memcmp(pCandidateList->BSSID, pbyBSSID, ETH_ALEN)) {
+			if ((bRSNCapExist == true) && (wRSNCap & BIT0)) {
+				pCandidateList->Flags |= NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED;
+			} else {
+				pCandidateList->Flags &= ~(NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED);
+			}
+			return true;
+		}
+	}
+
+	// New Candidate
+	pCandidateList = &pDevice->gsPMKIDCandidate.CandidateList[pDevice->gsPMKIDCandidate.NumCandidates];
+	if ((bRSNCapExist == true) && (wRSNCap & BIT0)) {
+		pCandidateList->Flags |= NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED;
+	} else {
+		pCandidateList->Flags &= ~(NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED);
+	}
+	memcpy(pCandidateList->BSSID, pbyBSSID, ETH_ALEN);
+	pDevice->gsPMKIDCandidate.NumCandidates++;
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "NumCandidates:%d\n", (int)pDevice->gsPMKIDCandidate.NumCandidates);
+	return true;
 }
 
 void *
-CARDpGetCurrentAddress (
-    void *pDeviceHandler
-    )
+CARDpGetCurrentAddress(
+	void *pDeviceHandler
+)
 {
-    PSDevice            pDevice = (PSDevice) pDeviceHandler;
+	PSDevice            pDevice = (PSDevice) pDeviceHandler;
 
-    return (pDevice->abyCurrentNetAddr);
+	return pDevice->abyCurrentNetAddr;
 }
 
 /*
@@ -1138,120 +1098,119 @@ CARDpGetCurrentAddress (
  *
  * Return Value: none.
  *
--*/
+ -*/
 bool
-CARDbStartMeasure (
-    void *pDeviceHandler,
-    void *pvMeasureEIDs,
-    unsigned int uNumOfMeasureEIDs
-    )
+CARDbStartMeasure(
+	void *pDeviceHandler,
+	void *pvMeasureEIDs,
+	unsigned int uNumOfMeasureEIDs
+)
 {
-    PSDevice                pDevice = (PSDevice) pDeviceHandler;
-    PWLAN_IE_MEASURE_REQ    pEID = (PWLAN_IE_MEASURE_REQ) pvMeasureEIDs;
-    QWORD                   qwCurrTSF;
-    QWORD                   qwStartTSF;
-    bool bExpired = true;
-    unsigned short wDuration = 0;
-
-    if ((pEID == NULL) ||
-        (uNumOfMeasureEIDs == 0)) {
-        return (true);
-    }
-    CARDbGetCurrentTSF(pDevice->PortOffset, &qwCurrTSF);
-    if (pDevice->bMeasureInProgress == true) {
-        pDevice->bMeasureInProgress = false;
-        VNSvOutPortB(pDevice->PortOffset + MAC_REG_RCR, pDevice->byOrgRCR);
-        MACvSelectPage1(pDevice->PortOffset);
-        VNSvOutPortD(pDevice->PortOffset + MAC_REG_MAR0, pDevice->dwOrgMAR0);
-        VNSvOutPortD(pDevice->PortOffset + MAC_REG_MAR4, pDevice->dwOrgMAR4);
-        // clear measure control
-        MACvRegBitsOff(pDevice->PortOffset, MAC_REG_MSRCTL, MSRCTL_EN);
-        MACvSelectPage0(pDevice->PortOffset);
-        set_channel(pDevice, pDevice->byOrgChannel);
-        MACvSelectPage1(pDevice->PortOffset);
-        MACvRegBitsOn(pDevice->PortOffset, MAC_REG_MSRCTL+1, MSRCTL1_TXPAUSE);
-        MACvSelectPage0(pDevice->PortOffset);
-    }
-    pDevice->uNumOfMeasureEIDs = uNumOfMeasureEIDs;
-
-    do {
-        pDevice->pCurrMeasureEID = pEID;
-        pEID++;
-        pDevice->uNumOfMeasureEIDs--;
-
-        if (pDevice->byLocalID > REV_ID_VT3253_B1) {
-            HIDWORD(qwStartTSF) = HIDWORD(*((PQWORD) (pDevice->pCurrMeasureEID->sReq.abyStartTime)));
-            LODWORD(qwStartTSF) = LODWORD(*((PQWORD) (pDevice->pCurrMeasureEID->sReq.abyStartTime)));
-            wDuration = *((unsigned short *) (pDevice->pCurrMeasureEID->sReq.abyDuration));
-            wDuration += 1; // 1 TU for channel switching
-
-            if ((LODWORD(qwStartTSF) == 0) && (HIDWORD(qwStartTSF) == 0)) {
-                // start immediately by setting start TSF == current TSF + 2 TU
-                LODWORD(qwStartTSF) = LODWORD(qwCurrTSF) + 2048;
-                HIDWORD(qwStartTSF) = HIDWORD(qwCurrTSF);
-                if (LODWORD(qwCurrTSF) > LODWORD(qwStartTSF)) {
-                    HIDWORD(qwStartTSF)++;
-                }
-                bExpired = false;
-                break;
-            } else {
-                // start at setting start TSF - 1TU(for channel switching)
-                if (LODWORD(qwStartTSF) < 1024) {
-                    HIDWORD(qwStartTSF)--;
-                }
-                LODWORD(qwStartTSF) -= 1024;
-            }
-
-            if ((HIDWORD(qwCurrTSF) < HIDWORD(qwStartTSF)) ||
-                ((HIDWORD(qwCurrTSF) == HIDWORD(qwStartTSF)) &&
-                (LODWORD(qwCurrTSF) < LODWORD(qwStartTSF)))
-                ) {
-                bExpired = false;
-                break;
-            }
-            VNTWIFIbMeasureReport(  pDevice->pMgmt,
-                                    false,
-                                    pDevice->pCurrMeasureEID,
-                                    MEASURE_MODE_LATE,
-                                    pDevice->byBasicMap,
-                                    pDevice->byCCAFraction,
-                                    pDevice->abyRPIs
-                                    );
-        } else {
-            // hardware do not support measure
-            VNTWIFIbMeasureReport(  pDevice->pMgmt,
-                                    false,
-                                    pDevice->pCurrMeasureEID,
-                                    MEASURE_MODE_INCAPABLE,
-                                    pDevice->byBasicMap,
-                                    pDevice->byCCAFraction,
-                                    pDevice->abyRPIs
-                                    );
-        }
-    } while (pDevice->uNumOfMeasureEIDs != 0);
-
-    if (bExpired == false) {
-        MACvSelectPage1(pDevice->PortOffset);
-        VNSvOutPortD(pDevice->PortOffset + MAC_REG_MSRSTART, LODWORD(qwStartTSF));
-        VNSvOutPortD(pDevice->PortOffset + MAC_REG_MSRSTART + 4, HIDWORD(qwStartTSF));
-        VNSvOutPortW(pDevice->PortOffset + MAC_REG_MSRDURATION, wDuration);
-        MACvRegBitsOn(pDevice->PortOffset, MAC_REG_MSRCTL, MSRCTL_EN);
-        MACvSelectPage0(pDevice->PortOffset);
-    } else {
-        // all measure start time expired we should complete action
-        VNTWIFIbMeasureReport(  pDevice->pMgmt,
-                                true,
-                                NULL,
-                                0,
-                                pDevice->byBasicMap,
-                                pDevice->byCCAFraction,
-                                pDevice->abyRPIs
-                                );
-    }
-    return (true);
+	PSDevice                pDevice = (PSDevice) pDeviceHandler;
+	PWLAN_IE_MEASURE_REQ    pEID = (PWLAN_IE_MEASURE_REQ) pvMeasureEIDs;
+	QWORD                   qwCurrTSF;
+	QWORD                   qwStartTSF;
+	bool bExpired = true;
+	unsigned short wDuration = 0;
+
+	if ((pEID == NULL) ||
+	    (uNumOfMeasureEIDs == 0)) {
+		return true;
+	}
+	CARDbGetCurrentTSF(pDevice->PortOffset, &qwCurrTSF);
+	if (pDevice->bMeasureInProgress == true) {
+		pDevice->bMeasureInProgress = false;
+		VNSvOutPortB(pDevice->PortOffset + MAC_REG_RCR, pDevice->byOrgRCR);
+		MACvSelectPage1(pDevice->PortOffset);
+		VNSvOutPortD(pDevice->PortOffset + MAC_REG_MAR0, pDevice->dwOrgMAR0);
+		VNSvOutPortD(pDevice->PortOffset + MAC_REG_MAR4, pDevice->dwOrgMAR4);
+		// clear measure control
+		MACvRegBitsOff(pDevice->PortOffset, MAC_REG_MSRCTL, MSRCTL_EN);
+		MACvSelectPage0(pDevice->PortOffset);
+		set_channel(pDevice, pDevice->byOrgChannel);
+		MACvSelectPage1(pDevice->PortOffset);
+		MACvRegBitsOn(pDevice->PortOffset, MAC_REG_MSRCTL+1, MSRCTL1_TXPAUSE);
+		MACvSelectPage0(pDevice->PortOffset);
+	}
+	pDevice->uNumOfMeasureEIDs = uNumOfMeasureEIDs;
+
+	do {
+		pDevice->pCurrMeasureEID = pEID;
+		pEID++;
+		pDevice->uNumOfMeasureEIDs--;
+
+		if (pDevice->byLocalID > REV_ID_VT3253_B1) {
+			HIDWORD(qwStartTSF) = HIDWORD(*((PQWORD)(pDevice->pCurrMeasureEID->sReq.abyStartTime)));
+			LODWORD(qwStartTSF) = LODWORD(*((PQWORD)(pDevice->pCurrMeasureEID->sReq.abyStartTime)));
+			wDuration = *((unsigned short *)(pDevice->pCurrMeasureEID->sReq.abyDuration));
+			wDuration += 1; // 1 TU for channel switching
+
+			if ((LODWORD(qwStartTSF) == 0) && (HIDWORD(qwStartTSF) == 0)) {
+				// start immediately by setting start TSF == current TSF + 2 TU
+				LODWORD(qwStartTSF) = LODWORD(qwCurrTSF) + 2048;
+				HIDWORD(qwStartTSF) = HIDWORD(qwCurrTSF);
+				if (LODWORD(qwCurrTSF) > LODWORD(qwStartTSF)) {
+					HIDWORD(qwStartTSF)++;
+				}
+				bExpired = false;
+				break;
+			} else {
+				// start at setting start TSF - 1TU(for channel switching)
+				if (LODWORD(qwStartTSF) < 1024) {
+					HIDWORD(qwStartTSF)--;
+				}
+				LODWORD(qwStartTSF) -= 1024;
+			}
+
+			if ((HIDWORD(qwCurrTSF) < HIDWORD(qwStartTSF)) ||
+			    ((HIDWORD(qwCurrTSF) == HIDWORD(qwStartTSF)) &&
+			     (LODWORD(qwCurrTSF) < LODWORD(qwStartTSF)))
+) {
+				bExpired = false;
+				break;
+			}
+			VNTWIFIbMeasureReport(pDevice->pMgmt,
+					      false,
+					      pDevice->pCurrMeasureEID,
+					      MEASURE_MODE_LATE,
+					      pDevice->byBasicMap,
+					      pDevice->byCCAFraction,
+					      pDevice->abyRPIs
+				);
+		} else {
+			// hardware do not support measure
+			VNTWIFIbMeasureReport(pDevice->pMgmt,
+					      false,
+					      pDevice->pCurrMeasureEID,
+					      MEASURE_MODE_INCAPABLE,
+					      pDevice->byBasicMap,
+					      pDevice->byCCAFraction,
+					      pDevice->abyRPIs
+				);
+		}
+	} while (pDevice->uNumOfMeasureEIDs != 0);
+
+	if (bExpired == false) {
+		MACvSelectPage1(pDevice->PortOffset);
+		VNSvOutPortD(pDevice->PortOffset + MAC_REG_MSRSTART, LODWORD(qwStartTSF));
+		VNSvOutPortD(pDevice->PortOffset + MAC_REG_MSRSTART + 4, HIDWORD(qwStartTSF));
+		VNSvOutPortW(pDevice->PortOffset + MAC_REG_MSRDURATION, wDuration);
+		MACvRegBitsOn(pDevice->PortOffset, MAC_REG_MSRCTL, MSRCTL_EN);
+		MACvSelectPage0(pDevice->PortOffset);
+	} else {
+		// all measure start time expired we should complete action
+		VNTWIFIbMeasureReport(pDevice->pMgmt,
+				      true,
+				      NULL,
+				      0,
+				      pDevice->byBasicMap,
+				      pDevice->byCCAFraction,
+				      pDevice->abyRPIs
+			);
+	}
+	return true;
 }
 
-
 /*
  *
  * Description:
@@ -1265,36 +1224,35 @@ CARDbStartMeasure (
  *
  * Return Value: none.
  *
--*/
+ -*/
 bool
-CARDbChannelSwitch (
-    void *pDeviceHandler,
-    unsigned char byMode,
-    unsigned char byNewChannel,
-    unsigned char byCount
-    )
+CARDbChannelSwitch(
+	void *pDeviceHandler,
+	unsigned char byMode,
+	unsigned char byNewChannel,
+	unsigned char byCount
+)
 {
-    PSDevice    pDevice = (PSDevice) pDeviceHandler;
-    bool bResult = true;
-
-    if (byCount == 0) {
-        bResult = set_channel(pDevice, byNewChannel);
-        VNTWIFIbChannelSwitch(pDevice->pMgmt, byNewChannel);
-        MACvSelectPage1(pDevice->PortOffset);
-        MACvRegBitsOn(pDevice->PortOffset, MAC_REG_MSRCTL+1, MSRCTL1_TXPAUSE);
-        MACvSelectPage0(pDevice->PortOffset);
-        return(bResult);
-    }
-    pDevice->byChannelSwitchCount = byCount;
-    pDevice->byNewChannel = byNewChannel;
-    pDevice->bChannelSwitch = true;
-    if (byMode == 1) {
-        bResult=CARDbStopTxPacket(pDevice, PKT_TYPE_802_11_ALL);
-    }
-    return (bResult);
+	PSDevice    pDevice = (PSDevice) pDeviceHandler;
+	bool bResult = true;
+
+	if (byCount == 0) {
+		bResult = set_channel(pDevice, byNewChannel);
+		VNTWIFIbChannelSwitch(pDevice->pMgmt, byNewChannel);
+		MACvSelectPage1(pDevice->PortOffset);
+		MACvRegBitsOn(pDevice->PortOffset, MAC_REG_MSRCTL+1, MSRCTL1_TXPAUSE);
+		MACvSelectPage0(pDevice->PortOffset);
+		return bResult;
+	}
+	pDevice->byChannelSwitchCount = byCount;
+	pDevice->byNewChannel = byNewChannel;
+	pDevice->bChannelSwitch = true;
+	if (byMode == 1) {
+		bResult = CARDbStopTxPacket(pDevice, PKT_TYPE_802_11_ALL);
+	}
+	return bResult;
 }
 
-
 /*
  *
  * Description:
@@ -1308,53 +1266,52 @@ CARDbChannelSwitch (
  *
  * Return Value: none.
  *
--*/
+ -*/
 bool
-CARDbSetQuiet (
-    void *pDeviceHandler,
-    bool bResetQuiet,
-    unsigned char byQuietCount,
-    unsigned char byQuietPeriod,
-    unsigned short wQuietDuration,
-    unsigned short wQuietOffset
-    )
+CARDbSetQuiet(
+	void *pDeviceHandler,
+	bool bResetQuiet,
+	unsigned char byQuietCount,
+	unsigned char byQuietPeriod,
+	unsigned short wQuietDuration,
+	unsigned short wQuietOffset
+)
 {
-    PSDevice    pDevice = (PSDevice) pDeviceHandler;
-    unsigned int ii = 0;
-
-    if (bResetQuiet == true) {
-        MACvRegBitsOff(pDevice->PortOffset, MAC_REG_MSRCTL, (MSRCTL_QUIETTXCHK | MSRCTL_QUIETEN));
-        for(ii=0;ii<MAX_QUIET_COUNT;ii++) {
-            pDevice->sQuiet[ii].bEnable = false;
-        }
-        pDevice->uQuietEnqueue = 0;
-        pDevice->bEnableFirstQuiet = false;
-        pDevice->bQuietEnable = false;
-        pDevice->byQuietStartCount = byQuietCount;
-    }
-    if (pDevice->sQuiet[pDevice->uQuietEnqueue].bEnable == false) {
-        pDevice->sQuiet[pDevice->uQuietEnqueue].bEnable = true;
-        pDevice->sQuiet[pDevice->uQuietEnqueue].byPeriod = byQuietPeriod;
-        pDevice->sQuiet[pDevice->uQuietEnqueue].wDuration = wQuietDuration;
-        pDevice->sQuiet[pDevice->uQuietEnqueue].dwStartTime = (unsigned long) byQuietCount;
-        pDevice->sQuiet[pDevice->uQuietEnqueue].dwStartTime *= pDevice->wBeaconInterval;
-        pDevice->sQuiet[pDevice->uQuietEnqueue].dwStartTime += wQuietOffset;
-        pDevice->uQuietEnqueue++;
-        pDevice->uQuietEnqueue %= MAX_QUIET_COUNT;
-        if (pDevice->byQuietStartCount < byQuietCount) {
-            pDevice->byQuietStartCount = byQuietCount;
-        }
-    } else {
-        // we can not handle Quiet EID more
-    }
-    return (true);
+	PSDevice    pDevice = (PSDevice) pDeviceHandler;
+	unsigned int ii = 0;
+
+	if (bResetQuiet == true) {
+		MACvRegBitsOff(pDevice->PortOffset, MAC_REG_MSRCTL, (MSRCTL_QUIETTXCHK | MSRCTL_QUIETEN));
+		for (ii = 0; ii < MAX_QUIET_COUNT; ii++) {
+			pDevice->sQuiet[ii].bEnable = false;
+		}
+		pDevice->uQuietEnqueue = 0;
+		pDevice->bEnableFirstQuiet = false;
+		pDevice->bQuietEnable = false;
+		pDevice->byQuietStartCount = byQuietCount;
+	}
+	if (pDevice->sQuiet[pDevice->uQuietEnqueue].bEnable == false) {
+		pDevice->sQuiet[pDevice->uQuietEnqueue].bEnable = true;
+		pDevice->sQuiet[pDevice->uQuietEnqueue].byPeriod = byQuietPeriod;
+		pDevice->sQuiet[pDevice->uQuietEnqueue].wDuration = wQuietDuration;
+		pDevice->sQuiet[pDevice->uQuietEnqueue].dwStartTime = (unsigned long) byQuietCount;
+		pDevice->sQuiet[pDevice->uQuietEnqueue].dwStartTime *= pDevice->wBeaconInterval;
+		pDevice->sQuiet[pDevice->uQuietEnqueue].dwStartTime += wQuietOffset;
+		pDevice->uQuietEnqueue++;
+		pDevice->uQuietEnqueue %= MAX_QUIET_COUNT;
+		if (pDevice->byQuietStartCount < byQuietCount) {
+			pDevice->byQuietStartCount = byQuietCount;
+		}
+	} else {
+		// we can not handle Quiet EID more
+	}
+	return true;
 }
 
-
 /*
  *
  * Description:
- *    Do Quiet, It will be called by either ISR(after start) 
+ *    Do Quiet, It will be called by either ISR(after start)
  *    or VNTWIFI(before start) so we do not need a SPINLOCK
  *
  * Parameters:
@@ -1365,91 +1322,91 @@ CARDbSetQuiet (
  *
  * Return Value: none.
  *
--*/
+ -*/
 bool
-CARDbStartQuiet (
-    void *pDeviceHandler
-    )
+CARDbStartQuiet(
+	void *pDeviceHandler
+)
 {
-    PSDevice    pDevice = (PSDevice) pDeviceHandler;
-    unsigned int ii = 0;
-    unsigned long dwStartTime = 0xFFFFFFFF;
-    unsigned int uCurrentQuietIndex = 0;
-    unsigned long dwNextTime = 0;
-    unsigned long dwGap = 0;
-    unsigned long dwDuration = 0;
-
-    for(ii=0;ii<MAX_QUIET_COUNT;ii++) {
-        if ((pDevice->sQuiet[ii].bEnable == true) &&
-            (dwStartTime > pDevice->sQuiet[ii].dwStartTime)) {
-            dwStartTime = pDevice->sQuiet[ii].dwStartTime;
-            uCurrentQuietIndex = ii;
-        }
-    }
-    if (dwStartTime == 0xFFFFFFFF) {
-        // no more quiet
-        pDevice->bQuietEnable = false;
-        MACvRegBitsOff(pDevice->PortOffset, MAC_REG_MSRCTL, (MSRCTL_QUIETTXCHK | MSRCTL_QUIETEN));
-    } else {
-        if (pDevice->bQuietEnable == false) {
-            // first quiet
-            pDevice->byQuietStartCount--;
-            dwNextTime = pDevice->sQuiet[uCurrentQuietIndex].dwStartTime;
-            dwNextTime %= pDevice->wBeaconInterval;
-            MACvSelectPage1(pDevice->PortOffset);
-            VNSvOutPortW(pDevice->PortOffset + MAC_REG_QUIETINIT, (unsigned short) dwNextTime);
-            VNSvOutPortW(pDevice->PortOffset + MAC_REG_QUIETDUR, (unsigned short) pDevice->sQuiet[uCurrentQuietIndex].wDuration);
-            if (pDevice->byQuietStartCount == 0) {
-                pDevice->bEnableFirstQuiet = false;
-                MACvRegBitsOn(pDevice->PortOffset, MAC_REG_MSRCTL, (MSRCTL_QUIETTXCHK | MSRCTL_QUIETEN));
-            } else {
-                pDevice->bEnableFirstQuiet = true;
-            }
-            MACvSelectPage0(pDevice->PortOffset);
-        } else {
-            if (pDevice->dwCurrentQuietEndTime > pDevice->sQuiet[uCurrentQuietIndex].dwStartTime) {
-                // overlap with previous Quiet
-                dwGap =  pDevice->dwCurrentQuietEndTime - pDevice->sQuiet[uCurrentQuietIndex].dwStartTime;
-                if (dwGap >= pDevice->sQuiet[uCurrentQuietIndex].wDuration) {
-                    // return false to indicate next quiet expired, should call this function again
-                    return (false);
-                }
-                dwDuration = pDevice->sQuiet[uCurrentQuietIndex].wDuration - dwGap;
-                dwGap = 0;
-            } else {
-                dwGap = pDevice->sQuiet[uCurrentQuietIndex].dwStartTime - pDevice->dwCurrentQuietEndTime;
-                dwDuration = pDevice->sQuiet[uCurrentQuietIndex].wDuration;
-            }
-            // set GAP and Next duration
-            MACvSelectPage1(pDevice->PortOffset);
-            VNSvOutPortW(pDevice->PortOffset + MAC_REG_QUIETGAP, (unsigned short) dwGap);
-            VNSvOutPortW(pDevice->PortOffset + MAC_REG_QUIETDUR, (unsigned short) dwDuration);
-            MACvRegBitsOn(pDevice->PortOffset, MAC_REG_MSRCTL, MSRCTL_QUIETRPT);
-            MACvSelectPage0(pDevice->PortOffset);
-        }
-        pDevice->bQuietEnable = true;
-        pDevice->dwCurrentQuietEndTime = pDevice->sQuiet[uCurrentQuietIndex].dwStartTime;
-        pDevice->dwCurrentQuietEndTime += pDevice->sQuiet[uCurrentQuietIndex].wDuration;
-        if (pDevice->sQuiet[uCurrentQuietIndex].byPeriod == 0) {
-            // not period disable current quiet element
-            pDevice->sQuiet[uCurrentQuietIndex].bEnable = false;
-        } else {
-            // set next period start time
-            dwNextTime = (unsigned long) pDevice->sQuiet[uCurrentQuietIndex].byPeriod;
-            dwNextTime *= pDevice->wBeaconInterval;
-            pDevice->sQuiet[uCurrentQuietIndex].dwStartTime = dwNextTime;
-        }
-        if (pDevice->dwCurrentQuietEndTime > 0x80010000) {
-            // decreament all time to avoid wrap around
-            for(ii=0;ii<MAX_QUIET_COUNT;ii++) {
-                if (pDevice->sQuiet[ii].bEnable == true) {
-                    pDevice->sQuiet[ii].dwStartTime -= 0x80000000;
-                }
-            }
-            pDevice->dwCurrentQuietEndTime -= 0x80000000;
-        }
-    }
-    return (true);
+	PSDevice    pDevice = (PSDevice) pDeviceHandler;
+	unsigned int ii = 0;
+	unsigned long dwStartTime = 0xFFFFFFFF;
+	unsigned int uCurrentQuietIndex = 0;
+	unsigned long dwNextTime = 0;
+	unsigned long dwGap = 0;
+	unsigned long dwDuration = 0;
+
+	for (ii = 0; ii < MAX_QUIET_COUNT; ii++) {
+		if ((pDevice->sQuiet[ii].bEnable == true) &&
+		    (dwStartTime > pDevice->sQuiet[ii].dwStartTime)) {
+			dwStartTime = pDevice->sQuiet[ii].dwStartTime;
+			uCurrentQuietIndex = ii;
+		}
+	}
+	if (dwStartTime == 0xFFFFFFFF) {
+		// no more quiet
+		pDevice->bQuietEnable = false;
+		MACvRegBitsOff(pDevice->PortOffset, MAC_REG_MSRCTL, (MSRCTL_QUIETTXCHK | MSRCTL_QUIETEN));
+	} else {
+		if (pDevice->bQuietEnable == false) {
+			// first quiet
+			pDevice->byQuietStartCount--;
+			dwNextTime = pDevice->sQuiet[uCurrentQuietIndex].dwStartTime;
+			dwNextTime %= pDevice->wBeaconInterval;
+			MACvSelectPage1(pDevice->PortOffset);
+			VNSvOutPortW(pDevice->PortOffset + MAC_REG_QUIETINIT, (unsigned short) dwNextTime);
+			VNSvOutPortW(pDevice->PortOffset + MAC_REG_QUIETDUR, (unsigned short) pDevice->sQuiet[uCurrentQuietIndex].wDuration);
+			if (pDevice->byQuietStartCount == 0) {
+				pDevice->bEnableFirstQuiet = false;
+				MACvRegBitsOn(pDevice->PortOffset, MAC_REG_MSRCTL, (MSRCTL_QUIETTXCHK | MSRCTL_QUIETEN));
+			} else {
+				pDevice->bEnableFirstQuiet = true;
+			}
+			MACvSelectPage0(pDevice->PortOffset);
+		} else {
+			if (pDevice->dwCurrentQuietEndTime > pDevice->sQuiet[uCurrentQuietIndex].dwStartTime) {
+				// overlap with previous Quiet
+				dwGap =  pDevice->dwCurrentQuietEndTime - pDevice->sQuiet[uCurrentQuietIndex].dwStartTime;
+				if (dwGap >= pDevice->sQuiet[uCurrentQuietIndex].wDuration) {
+					// return false to indicate next quiet expired, should call this function again
+					return false;
+				}
+				dwDuration = pDevice->sQuiet[uCurrentQuietIndex].wDuration - dwGap;
+				dwGap = 0;
+			} else {
+				dwGap = pDevice->sQuiet[uCurrentQuietIndex].dwStartTime - pDevice->dwCurrentQuietEndTime;
+				dwDuration = pDevice->sQuiet[uCurrentQuietIndex].wDuration;
+			}
+			// set GAP and Next duration
+			MACvSelectPage1(pDevice->PortOffset);
+			VNSvOutPortW(pDevice->PortOffset + MAC_REG_QUIETGAP, (unsigned short) dwGap);
+			VNSvOutPortW(pDevice->PortOffset + MAC_REG_QUIETDUR, (unsigned short) dwDuration);
+			MACvRegBitsOn(pDevice->PortOffset, MAC_REG_MSRCTL, MSRCTL_QUIETRPT);
+			MACvSelectPage0(pDevice->PortOffset);
+		}
+		pDevice->bQuietEnable = true;
+		pDevice->dwCurrentQuietEndTime = pDevice->sQuiet[uCurrentQuietIndex].dwStartTime;
+		pDevice->dwCurrentQuietEndTime += pDevice->sQuiet[uCurrentQuietIndex].wDuration;
+		if (pDevice->sQuiet[uCurrentQuietIndex].byPeriod == 0) {
+			// not period disable current quiet element
+			pDevice->sQuiet[uCurrentQuietIndex].bEnable = false;
+		} else {
+			// set next period start time
+			dwNextTime = (unsigned long) pDevice->sQuiet[uCurrentQuietIndex].byPeriod;
+			dwNextTime *= pDevice->wBeaconInterval;
+			pDevice->sQuiet[uCurrentQuietIndex].dwStartTime = dwNextTime;
+		}
+		if (pDevice->dwCurrentQuietEndTime > 0x80010000) {
+			// decreament all time to avoid wrap around
+			for (ii = 0; ii < MAX_QUIET_COUNT; ii++) {
+				if (pDevice->sQuiet[ii].bEnable == true) {
+					pDevice->sQuiet[ii].dwStartTime -= 0x80000000;
+				}
+			}
+			pDevice->dwCurrentQuietEndTime -= 0x80000000;
+		}
+	}
+	return true;
 }
 
 /*
@@ -1465,28 +1422,27 @@ CARDbStartQuiet (
  *
  * Return Value: none.
  *
--*/
+ -*/
 void
-CARDvSetPowerConstraint (
-    void *pDeviceHandler,
-    unsigned char byChannel,
-    char byPower
-    )
+CARDvSetPowerConstraint(
+	void *pDeviceHandler,
+	unsigned char byChannel,
+	char byPower
+)
 {
-    PSDevice    pDevice = (PSDevice) pDeviceHandler;
-
-    if (byChannel > CB_MAX_CHANNEL_24G) {
-        if (pDevice->bCountryInfo5G == true) {
-            pDevice->abyLocalPwr[byChannel] = pDevice->abyRegPwr[byChannel] - byPower;
-        }
-    } else {
-        if (pDevice->bCountryInfo24G == true) {
-            pDevice->abyLocalPwr[byChannel] = pDevice->abyRegPwr[byChannel] - byPower;
-        }
-    }
+	PSDevice    pDevice = (PSDevice) pDeviceHandler;
+
+	if (byChannel > CB_MAX_CHANNEL_24G) {
+		if (pDevice->bCountryInfo5G == true) {
+			pDevice->abyLocalPwr[byChannel] = pDevice->abyRegPwr[byChannel] - byPower;
+		}
+	} else {
+		if (pDevice->bCountryInfo24G == true) {
+			pDevice->abyLocalPwr[byChannel] = pDevice->abyRegPwr[byChannel] - byPower;
+		}
+	}
 }
 
-
 /*
  *
  * Description:
@@ -1500,26 +1456,26 @@ CARDvSetPowerConstraint (
  *
  * Return Value: none.
  *
--*/
+ -*/
 void
-CARDvGetPowerCapability (
-    void *pDeviceHandler,
-    unsigned char *pbyMinPower,
-    unsigned char *pbyMaxPower
-    )
+CARDvGetPowerCapability(
+	void *pDeviceHandler,
+	unsigned char *pbyMinPower,
+	unsigned char *pbyMaxPower
+)
 {
-    PSDevice    pDevice = (PSDevice) pDeviceHandler;
-    unsigned char byDec = 0;
-
-    *pbyMaxPower = pDevice->abyOFDMDefaultPwr[pDevice->byCurrentCh];
-    byDec = pDevice->abyOFDMPwrTbl[pDevice->byCurrentCh];
-    if (pDevice->byRFType == RF_UW2452) {
-        byDec *= 3;
-        byDec >>= 1;
-    } else {
-        byDec <<= 1;
-    }
-    *pbyMinPower = pDevice->abyOFDMDefaultPwr[pDevice->byCurrentCh] - byDec;
+	PSDevice    pDevice = (PSDevice) pDeviceHandler;
+	unsigned char byDec = 0;
+
+	*pbyMaxPower = pDevice->abyOFDMDefaultPwr[pDevice->byCurrentCh];
+	byDec = pDevice->abyOFDMPwrTbl[pDevice->byCurrentCh];
+	if (pDevice->byRFType == RF_UW2452) {
+		byDec *= 3;
+		byDec >>= 1;
+	} else {
+		byDec <<= 1;
+	}
+	*pbyMinPower = pDevice->abyOFDMDefaultPwr[pDevice->byCurrentCh] - byDec;
 }
 
 /*
@@ -1537,58 +1493,55 @@ CARDvGetPowerCapability (
  *
  */
 char
-CARDbyGetTransmitPower (
-    void *pDeviceHandler
-    )
+CARDbyGetTransmitPower(
+	void *pDeviceHandler
+)
 {
-    PSDevice    pDevice = (PSDevice) pDeviceHandler;
+	PSDevice    pDevice = (PSDevice) pDeviceHandler;
 
-    return (pDevice->byCurPwrdBm);
+	return pDevice->byCurPwrdBm;
 }
 
 //xxx
 void
-CARDvSafeResetTx (
-    void *pDeviceHandler
-    )
+CARDvSafeResetTx(
+	void *pDeviceHandler
+)
 {
-    PSDevice    pDevice = (PSDevice) pDeviceHandler;
-    unsigned int uu;
-    PSTxDesc    pCurrTD;
-
-    // initialize TD index
-    pDevice->apTailTD[0] = pDevice->apCurrTD[0] = &(pDevice->apTD0Rings[0]);
-    pDevice->apTailTD[1] = pDevice->apCurrTD[1] = &(pDevice->apTD1Rings[0]);
-
-    for (uu = 0; uu < TYPE_MAXTD; uu ++)
-        pDevice->iTDUsed[uu] = 0;
-
-    for (uu = 0; uu < pDevice->sOpts.nTxDescs[0]; uu++) {
-        pCurrTD = &(pDevice->apTD0Rings[uu]);
-        pCurrTD->m_td0TD0.f1Owner = OWNED_BY_HOST;
-        // init all Tx Packet pointer to NULL
-    }
-    for (uu = 0; uu < pDevice->sOpts.nTxDescs[1]; uu++) {
-        pCurrTD = &(pDevice->apTD1Rings[uu]);
-        pCurrTD->m_td0TD0.f1Owner = OWNED_BY_HOST;
-        // init all Tx Packet pointer to NULL
-    }
-
-    // set MAC TD pointer
-    MACvSetCurrTXDescAddr(TYPE_TXDMA0, pDevice->PortOffset,
-                        (pDevice->td0_pool_dma));
-
-    MACvSetCurrTXDescAddr(TYPE_AC0DMA, pDevice->PortOffset,
-                        (pDevice->td1_pool_dma));
-
-    // set MAC Beacon TX pointer
-    MACvSetCurrBCNTxDescAddr(pDevice->PortOffset,
-                        (pDevice->tx_beacon_dma));
-
+	PSDevice    pDevice = (PSDevice) pDeviceHandler;
+	unsigned int uu;
+	PSTxDesc    pCurrTD;
+
+	// initialize TD index
+	pDevice->apTailTD[0] = pDevice->apCurrTD[0] = &(pDevice->apTD0Rings[0]);
+	pDevice->apTailTD[1] = pDevice->apCurrTD[1] = &(pDevice->apTD1Rings[0]);
+
+	for (uu = 0; uu < TYPE_MAXTD; uu++)
+		pDevice->iTDUsed[uu] = 0;
+
+	for (uu = 0; uu < pDevice->sOpts.nTxDescs[0]; uu++) {
+		pCurrTD = &(pDevice->apTD0Rings[uu]);
+		pCurrTD->m_td0TD0.f1Owner = OWNED_BY_HOST;
+		// init all Tx Packet pointer to NULL
+	}
+	for (uu = 0; uu < pDevice->sOpts.nTxDescs[1]; uu++) {
+		pCurrTD = &(pDevice->apTD1Rings[uu]);
+		pCurrTD->m_td0TD0.f1Owner = OWNED_BY_HOST;
+		// init all Tx Packet pointer to NULL
+	}
+
+	// set MAC TD pointer
+	MACvSetCurrTXDescAddr(TYPE_TXDMA0, pDevice->PortOffset,
+			      (pDevice->td0_pool_dma));
+
+	MACvSetCurrTXDescAddr(TYPE_AC0DMA, pDevice->PortOffset,
+			      (pDevice->td1_pool_dma));
+
+	// set MAC Beacon TX pointer
+	MACvSetCurrBCNTxDescAddr(pDevice->PortOffset,
+				 (pDevice->tx_beacon_dma));
 }
 
-
-
 /*+
  *
  * Description:
@@ -1602,55 +1555,50 @@ CARDvSafeResetTx (
  *
  * Return Value: none
  *
--*/
+ -*/
 void
-CARDvSafeResetRx (
-    void *pDeviceHandler
-    )
+CARDvSafeResetRx(
+	void *pDeviceHandler
+)
 {
-    PSDevice    pDevice = (PSDevice) pDeviceHandler;
-    unsigned int uu;
-    PSRxDesc    pDesc;
-
-
-
-    // initialize RD index
-    pDevice->pCurrRD[0]=&(pDevice->aRD0Ring[0]);
-    pDevice->pCurrRD[1]=&(pDevice->aRD1Ring[0]);
-
-    // init state, all RD is chip's
-    for (uu = 0; uu < pDevice->sOpts.nRxDescs0; uu++) {
-        pDesc =&(pDevice->aRD0Ring[uu]);
-        pDesc->m_rd0RD0.wResCount = (unsigned short)(pDevice->rx_buf_sz);
-        pDesc->m_rd0RD0.f1Owner=OWNED_BY_NIC;
-        pDesc->m_rd1RD1.wReqCount = (unsigned short)(pDevice->rx_buf_sz);
-    }
-
-    // init state, all RD is chip's
-    for (uu = 0; uu < pDevice->sOpts.nRxDescs1; uu++) {
-        pDesc =&(pDevice->aRD1Ring[uu]);
-        pDesc->m_rd0RD0.wResCount = (unsigned short)(pDevice->rx_buf_sz);
-        pDesc->m_rd0RD0.f1Owner=OWNED_BY_NIC;
-        pDesc->m_rd1RD1.wReqCount = (unsigned short)(pDevice->rx_buf_sz);
-    }
-
-    pDevice->cbDFCB = CB_MAX_RX_FRAG;
-    pDevice->cbFreeDFCB = pDevice->cbDFCB;
-
-    // set perPkt mode
-    MACvRx0PerPktMode(pDevice->PortOffset);
-    MACvRx1PerPktMode(pDevice->PortOffset);
-    // set MAC RD pointer
-    MACvSetCurrRx0DescAddr(pDevice->PortOffset,
-                            pDevice->rd0_pool_dma);
-
-    MACvSetCurrRx1DescAddr(pDevice->PortOffset,
-                            pDevice->rd1_pool_dma);
+	PSDevice    pDevice = (PSDevice) pDeviceHandler;
+	unsigned int uu;
+	PSRxDesc    pDesc;
+
+	// initialize RD index
+	pDevice->pCurrRD[0] = &(pDevice->aRD0Ring[0]);
+	pDevice->pCurrRD[1] = &(pDevice->aRD1Ring[0]);
+
+	// init state, all RD is chip's
+	for (uu = 0; uu < pDevice->sOpts.nRxDescs0; uu++) {
+		pDesc = &(pDevice->aRD0Ring[uu]);
+		pDesc->m_rd0RD0.wResCount = (unsigned short)(pDevice->rx_buf_sz);
+		pDesc->m_rd0RD0.f1Owner = OWNED_BY_NIC;
+		pDesc->m_rd1RD1.wReqCount = (unsigned short)(pDevice->rx_buf_sz);
+	}
+
+	// init state, all RD is chip's
+	for (uu = 0; uu < pDevice->sOpts.nRxDescs1; uu++) {
+		pDesc = &(pDevice->aRD1Ring[uu]);
+		pDesc->m_rd0RD0.wResCount = (unsigned short)(pDevice->rx_buf_sz);
+		pDesc->m_rd0RD0.f1Owner = OWNED_BY_NIC;
+		pDesc->m_rd1RD1.wReqCount = (unsigned short)(pDevice->rx_buf_sz);
+	}
+
+	pDevice->cbDFCB = CB_MAX_RX_FRAG;
+	pDevice->cbFreeDFCB = pDevice->cbDFCB;
+
+	// set perPkt mode
+	MACvRx0PerPktMode(pDevice->PortOffset);
+	MACvRx1PerPktMode(pDevice->PortOffset);
+	// set MAC RD pointer
+	MACvSetCurrRx0DescAddr(pDevice->PortOffset,
+			       pDevice->rd0_pool_dma);
+
+	MACvSetCurrRx1DescAddr(pDevice->PortOffset,
+			       pDevice->rd1_pool_dma);
 }
 
-
-
-
 /*
  * Description: Get response Control frame rate in CCK mode
  *
@@ -1666,16 +1614,16 @@ CARDvSafeResetRx (
  */
 unsigned short CARDwGetCCKControlRate(void *pDeviceHandler, unsigned short wRateIdx)
 {
-    PSDevice    pDevice = (PSDevice) pDeviceHandler;
-    unsigned int ui = (unsigned int) wRateIdx;
-
-    while (ui > RATE_1M) {
-        if (pDevice->wBasicRate & ((unsigned short)1 << ui)) {
-            return (unsigned short)ui;
-        }
-        ui --;
-    }
-    return (unsigned short)RATE_1M;
+	PSDevice    pDevice = (PSDevice) pDeviceHandler;
+	unsigned int ui = (unsigned int) wRateIdx;
+
+	while (ui > RATE_1M) {
+		if (pDevice->wBasicRate & ((unsigned short)1 << ui)) {
+			return (unsigned short)ui;
+		}
+		ui--;
+	}
+	return (unsigned short)RATE_1M;
 }
 
 /*
@@ -1691,31 +1639,30 @@ unsigned short CARDwGetCCKControlRate(void *pDeviceHandler, unsigned short wRate
  * Return Value: response Control frame rate
  *
  */
-unsigned short CARDwGetOFDMControlRate (void *pDeviceHandler, unsigned short wRateIdx)
+unsigned short CARDwGetOFDMControlRate(void *pDeviceHandler, unsigned short wRateIdx)
 {
-    PSDevice pDevice = (PSDevice) pDeviceHandler;
-    unsigned int ui = (unsigned int) wRateIdx;
-
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"BASIC RATE: %X\n", pDevice->wBasicRate);
-
-    if (!CARDbIsOFDMinBasicRate((void *)pDevice)) {
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"CARDwGetOFDMControlRate:(NO OFDM) %d\n", wRateIdx);
-        if (wRateIdx > RATE_24M)
-            wRateIdx = RATE_24M;
-        return wRateIdx;
-    }
-    while (ui > RATE_11M) {
-        if (pDevice->wBasicRate & ((unsigned short)1 << ui)) {
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"CARDwGetOFDMControlRate : %d\n", ui);
-            return (unsigned short)ui;
-        }
-        ui --;
-    }
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"CARDwGetOFDMControlRate: 6M\n");
-    return (unsigned short)RATE_24M;
+	PSDevice pDevice = (PSDevice) pDeviceHandler;
+	unsigned int ui = (unsigned int) wRateIdx;
+
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "BASIC RATE: %X\n", pDevice->wBasicRate);
+
+	if (!CARDbIsOFDMinBasicRate((void *)pDevice)) {
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "CARDwGetOFDMControlRate:(NO OFDM) %d\n", wRateIdx);
+		if (wRateIdx > RATE_24M)
+			wRateIdx = RATE_24M;
+		return wRateIdx;
+	}
+	while (ui > RATE_11M) {
+		if (pDevice->wBasicRate & ((unsigned short)1 << ui)) {
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "CARDwGetOFDMControlRate : %d\n", ui);
+			return (unsigned short)ui;
+		}
+		ui--;
+	}
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "CARDwGetOFDMControlRate: 6M\n");
+	return (unsigned short)RATE_24M;
 }
 
-
 /*
  * Description: Set RSPINF
  *
@@ -1728,117 +1675,117 @@ unsigned short CARDwGetOFDMControlRate (void *pDeviceHandler, unsigned short wRa
  * Return Value: None.
  *
  */
-void CARDvSetRSPINF (void *pDeviceHandler, CARD_PHY_TYPE ePHYType)
+void CARDvSetRSPINF(void *pDeviceHandler, CARD_PHY_TYPE ePHYType)
 {
-    PSDevice pDevice = (PSDevice) pDeviceHandler;
-    unsigned char byServ = 0x00, bySignal = 0x00; //For CCK
-    unsigned short wLen = 0x0000;
-    unsigned char byTxRate, byRsvTime;             //For OFDM
-
-    //Set to Page1
-    MACvSelectPage1(pDevice->PortOffset);
-
-    //RSPINF_b_1
-    BBvCalculateParameter(pDevice,
-                         14,
-                         CARDwGetCCKControlRate((void *)pDevice, RATE_1M),
-                         PK_TYPE_11B,
-                         &wLen,
-                         &byServ,
-                         &bySignal
-    );
-
-    VNSvOutPortD(pDevice->PortOffset + MAC_REG_RSPINF_B_1, MAKEDWORD(wLen,MAKEWORD(bySignal,byServ)));
-    ///RSPINF_b_2
-    BBvCalculateParameter(pDevice,
-                         14,
-                         CARDwGetCCKControlRate((void *)pDevice, RATE_2M),
-                         PK_TYPE_11B,
-                         &wLen,
-                         &byServ,
-                         &bySignal
-    );
-
-    VNSvOutPortD(pDevice->PortOffset + MAC_REG_RSPINF_B_2, MAKEDWORD(wLen,MAKEWORD(bySignal,byServ)));
-    //RSPINF_b_5
-    BBvCalculateParameter(pDevice,
-                         14,
-                         CARDwGetCCKControlRate((void *)pDevice, RATE_5M),
-                         PK_TYPE_11B,
-                         &wLen,
-                         &byServ,
-                         &bySignal
-    );
-
-    VNSvOutPortD(pDevice->PortOffset + MAC_REG_RSPINF_B_5, MAKEDWORD(wLen,MAKEWORD(bySignal,byServ)));
-    //RSPINF_b_11
-    BBvCalculateParameter(pDevice,
-                         14,
-                         CARDwGetCCKControlRate((void *)pDevice, RATE_11M),
-                         PK_TYPE_11B,
-                         &wLen,
-                         &byServ,
-                         &bySignal
-    );
-
-    VNSvOutPortD(pDevice->PortOffset + MAC_REG_RSPINF_B_11, MAKEDWORD(wLen,MAKEWORD(bySignal,byServ)));
-    //RSPINF_a_6
-    s_vCalculateOFDMRParameter(RATE_6M,
-                              ePHYType,
-                              &byTxRate,
-                              &byRsvTime);
-    VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_6, MAKEWORD(byTxRate,byRsvTime));
-    //RSPINF_a_9
-    s_vCalculateOFDMRParameter(RATE_9M,
-                              ePHYType,
-                              &byTxRate,
-                              &byRsvTime);
-    VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_9, MAKEWORD(byTxRate,byRsvTime));
-    //RSPINF_a_12
-    s_vCalculateOFDMRParameter(RATE_12M,
-                              ePHYType,
-                              &byTxRate,
-                              &byRsvTime);
-    VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_12, MAKEWORD(byTxRate,byRsvTime));
-    //RSPINF_a_18
-    s_vCalculateOFDMRParameter(RATE_18M,
-                              ePHYType,
-                              &byTxRate,
-                              &byRsvTime);
-   VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_18, MAKEWORD(byTxRate,byRsvTime));
-    //RSPINF_a_24
-    s_vCalculateOFDMRParameter(RATE_24M,
-                              ePHYType,
-                              &byTxRate,
-                              &byRsvTime);
-    VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_24, MAKEWORD(byTxRate,byRsvTime));
-    //RSPINF_a_36
-    s_vCalculateOFDMRParameter(CARDwGetOFDMControlRate((void *)pDevice, RATE_36M),
-                              ePHYType,
-                              &byTxRate,
-                              &byRsvTime);
-    VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_36, MAKEWORD(byTxRate,byRsvTime));
-    //RSPINF_a_48
-    s_vCalculateOFDMRParameter(CARDwGetOFDMControlRate((void *)pDevice, RATE_48M),
-                              ePHYType,
-                              &byTxRate,
-                              &byRsvTime);
-    VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_48, MAKEWORD(byTxRate,byRsvTime));
-    //RSPINF_a_54
-    s_vCalculateOFDMRParameter(CARDwGetOFDMControlRate((void *)pDevice, RATE_54M),
-                              ePHYType,
-                              &byTxRate,
-                              &byRsvTime);
-    VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_54, MAKEWORD(byTxRate,byRsvTime));
-
-    //RSPINF_a_72
-    s_vCalculateOFDMRParameter(CARDwGetOFDMControlRate((void *)pDevice, RATE_54M),
-                              ePHYType,
-                              &byTxRate,
-                              &byRsvTime);
-    VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_72, MAKEWORD(byTxRate,byRsvTime));
-    //Set to Page0
-    MACvSelectPage0(pDevice->PortOffset);
+	PSDevice pDevice = (PSDevice) pDeviceHandler;
+	unsigned char byServ = 0x00, bySignal = 0x00; //For CCK
+	unsigned short wLen = 0x0000;
+	unsigned char byTxRate, byRsvTime;             //For OFDM
+
+	//Set to Page1
+	MACvSelectPage1(pDevice->PortOffset);
+
+	//RSPINF_b_1
+	BBvCalculateParameter(pDevice,
+			      14,
+			      CARDwGetCCKControlRate((void *)pDevice, RATE_1M),
+			      PK_TYPE_11B,
+			      &wLen,
+			      &byServ,
+			      &bySignal
+);
+
+	VNSvOutPortD(pDevice->PortOffset + MAC_REG_RSPINF_B_1, MAKEDWORD(wLen, MAKEWORD(bySignal, byServ)));
+	///RSPINF_b_2
+	BBvCalculateParameter(pDevice,
+			      14,
+			      CARDwGetCCKControlRate((void *)pDevice, RATE_2M),
+			      PK_TYPE_11B,
+			      &wLen,
+			      &byServ,
+			      &bySignal
+);
+
+	VNSvOutPortD(pDevice->PortOffset + MAC_REG_RSPINF_B_2, MAKEDWORD(wLen, MAKEWORD(bySignal, byServ)));
+	//RSPINF_b_5
+	BBvCalculateParameter(pDevice,
+			      14,
+			      CARDwGetCCKControlRate((void *)pDevice, RATE_5M),
+			      PK_TYPE_11B,
+			      &wLen,
+			      &byServ,
+			      &bySignal
+);
+
+	VNSvOutPortD(pDevice->PortOffset + MAC_REG_RSPINF_B_5, MAKEDWORD(wLen, MAKEWORD(bySignal, byServ)));
+	//RSPINF_b_11
+	BBvCalculateParameter(pDevice,
+			      14,
+			      CARDwGetCCKControlRate((void *)pDevice, RATE_11M),
+			      PK_TYPE_11B,
+			      &wLen,
+			      &byServ,
+			      &bySignal
+);
+
+	VNSvOutPortD(pDevice->PortOffset + MAC_REG_RSPINF_B_11, MAKEDWORD(wLen, MAKEWORD(bySignal, byServ)));
+	//RSPINF_a_6
+	s_vCalculateOFDMRParameter(RATE_6M,
+				   ePHYType,
+				   &byTxRate,
+				   &byRsvTime);
+	VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_6, MAKEWORD(byTxRate, byRsvTime));
+	//RSPINF_a_9
+	s_vCalculateOFDMRParameter(RATE_9M,
+				   ePHYType,
+				   &byTxRate,
+				   &byRsvTime);
+	VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_9, MAKEWORD(byTxRate, byRsvTime));
+	//RSPINF_a_12
+	s_vCalculateOFDMRParameter(RATE_12M,
+				   ePHYType,
+				   &byTxRate,
+				   &byRsvTime);
+	VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_12, MAKEWORD(byTxRate, byRsvTime));
+	//RSPINF_a_18
+	s_vCalculateOFDMRParameter(RATE_18M,
+				   ePHYType,
+				   &byTxRate,
+				   &byRsvTime);
+	VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_18, MAKEWORD(byTxRate, byRsvTime));
+	//RSPINF_a_24
+	s_vCalculateOFDMRParameter(RATE_24M,
+				   ePHYType,
+				   &byTxRate,
+				   &byRsvTime);
+	VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_24, MAKEWORD(byTxRate, byRsvTime));
+	//RSPINF_a_36
+	s_vCalculateOFDMRParameter(CARDwGetOFDMControlRate((void *)pDevice, RATE_36M),
+				   ePHYType,
+				   &byTxRate,
+				   &byRsvTime);
+	VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_36, MAKEWORD(byTxRate, byRsvTime));
+	//RSPINF_a_48
+	s_vCalculateOFDMRParameter(CARDwGetOFDMControlRate((void *)pDevice, RATE_48M),
+				   ePHYType,
+				   &byTxRate,
+				   &byRsvTime);
+	VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_48, MAKEWORD(byTxRate, byRsvTime));
+	//RSPINF_a_54
+	s_vCalculateOFDMRParameter(CARDwGetOFDMControlRate((void *)pDevice, RATE_54M),
+				   ePHYType,
+				   &byTxRate,
+				   &byRsvTime);
+	VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_54, MAKEWORD(byTxRate, byRsvTime));
+
+	//RSPINF_a_72
+	s_vCalculateOFDMRParameter(CARDwGetOFDMControlRate((void *)pDevice, RATE_54M),
+				   ePHYType,
+				   &byTxRate,
+				   &byRsvTime);
+	VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_72, MAKEWORD(byTxRate, byRsvTime));
+	//Set to Page0
+	MACvSelectPage0(pDevice->PortOffset);
 }
 
 /*
@@ -1853,87 +1800,83 @@ void CARDvSetRSPINF (void *pDeviceHandler, CARD_PHY_TYPE ePHYType)
  * Return Value: None.
  *
  */
-void vUpdateIFS (void *pDeviceHandler)
+void vUpdateIFS(void *pDeviceHandler)
 {
-    //Set SIFS, DIFS, EIFS, SlotTime, CwMin
-    PSDevice pDevice = (PSDevice) pDeviceHandler;
-
-    unsigned char byMaxMin = 0;
-    if (pDevice->byPacketType==PK_TYPE_11A) {//0000 0000 0000 0000,11a
-        pDevice->uSlot = C_SLOT_SHORT;
-        pDevice->uSIFS = C_SIFS_A;
-        pDevice->uDIFS = C_SIFS_A + 2*C_SLOT_SHORT;
-        pDevice->uCwMin = C_CWMIN_A;
-        byMaxMin = 4;
-    }
-    else if (pDevice->byPacketType==PK_TYPE_11B) {//0000 0001 0000 0000,11b
-        pDevice->uSlot = C_SLOT_LONG;
-        pDevice->uSIFS = C_SIFS_BG;
-        pDevice->uDIFS = C_SIFS_BG + 2*C_SLOT_LONG;
-	    pDevice->uCwMin = C_CWMIN_B;
-        byMaxMin = 5;
-    }
-    else { // PK_TYPE_11GA & PK_TYPE_11GB
-        pDevice->uSIFS = C_SIFS_BG;
-        if (pDevice->bShortSlotTime) {
-            pDevice->uSlot = C_SLOT_SHORT;
-        } else {
-	        pDevice->uSlot = C_SLOT_LONG;
-	    }
-	    pDevice->uDIFS = C_SIFS_BG + 2*pDevice->uSlot;
-        if (pDevice->wBasicRate & 0x0150) { //0000 0001 0101 0000,24M,12M,6M
-            pDevice->uCwMin = C_CWMIN_A;
-            byMaxMin = 4;
-        }
-        else {
-            pDevice->uCwMin = C_CWMIN_B;
-            byMaxMin = 5;
-        }
-    }
-
-    pDevice->uCwMax = C_CWMAX;
-    pDevice->uEIFS = C_EIFS;
-    if (pDevice->byRFType == RF_RFMD2959) {
-        // bcs TX_PE will reserve 3 us
-        VNSvOutPortB(pDevice->PortOffset + MAC_REG_SIFS, (unsigned char)(pDevice->uSIFS - 3));
-        VNSvOutPortB(pDevice->PortOffset + MAC_REG_DIFS, (unsigned char)(pDevice->uDIFS - 3));
-    } else {
-        VNSvOutPortB(pDevice->PortOffset + MAC_REG_SIFS, (unsigned char)pDevice->uSIFS);
-        VNSvOutPortB(pDevice->PortOffset + MAC_REG_DIFS, (unsigned char)pDevice->uDIFS);
-    }
-    VNSvOutPortB(pDevice->PortOffset + MAC_REG_EIFS, (unsigned char)pDevice->uEIFS);
-    VNSvOutPortB(pDevice->PortOffset + MAC_REG_SLOT, (unsigned char)pDevice->uSlot);
-    byMaxMin |= 0xA0;//1010 1111,C_CWMAX = 1023
-    VNSvOutPortB(pDevice->PortOffset + MAC_REG_CWMAXMIN0, (unsigned char)byMaxMin);
+	//Set SIFS, DIFS, EIFS, SlotTime, CwMin
+	PSDevice pDevice = (PSDevice) pDeviceHandler;
+
+	unsigned char byMaxMin = 0;
+	if (pDevice->byPacketType == PK_TYPE_11A) {//0000 0000 0000 0000,11a
+		pDevice->uSlot = C_SLOT_SHORT;
+		pDevice->uSIFS = C_SIFS_A;
+		pDevice->uDIFS = C_SIFS_A + 2*C_SLOT_SHORT;
+		pDevice->uCwMin = C_CWMIN_A;
+		byMaxMin = 4;
+	} else if (pDevice->byPacketType == PK_TYPE_11B) {//0000 0001 0000 0000,11b
+		pDevice->uSlot = C_SLOT_LONG;
+		pDevice->uSIFS = C_SIFS_BG;
+		pDevice->uDIFS = C_SIFS_BG + 2*C_SLOT_LONG;
+		pDevice->uCwMin = C_CWMIN_B;
+		byMaxMin = 5;
+	} else { // PK_TYPE_11GA & PK_TYPE_11GB
+		pDevice->uSIFS = C_SIFS_BG;
+		if (pDevice->bShortSlotTime) {
+			pDevice->uSlot = C_SLOT_SHORT;
+		} else {
+			pDevice->uSlot = C_SLOT_LONG;
+		}
+		pDevice->uDIFS = C_SIFS_BG + 2*pDevice->uSlot;
+		if (pDevice->wBasicRate & 0x0150) { //0000 0001 0101 0000,24M,12M,6M
+			pDevice->uCwMin = C_CWMIN_A;
+			byMaxMin = 4;
+		} else {
+			pDevice->uCwMin = C_CWMIN_B;
+			byMaxMin = 5;
+		}
+	}
+
+	pDevice->uCwMax = C_CWMAX;
+	pDevice->uEIFS = C_EIFS;
+	if (pDevice->byRFType == RF_RFMD2959) {
+		// bcs TX_PE will reserve 3 us
+		VNSvOutPortB(pDevice->PortOffset + MAC_REG_SIFS, (unsigned char)(pDevice->uSIFS - 3));
+		VNSvOutPortB(pDevice->PortOffset + MAC_REG_DIFS, (unsigned char)(pDevice->uDIFS - 3));
+	} else {
+		VNSvOutPortB(pDevice->PortOffset + MAC_REG_SIFS, (unsigned char)pDevice->uSIFS);
+		VNSvOutPortB(pDevice->PortOffset + MAC_REG_DIFS, (unsigned char)pDevice->uDIFS);
+	}
+	VNSvOutPortB(pDevice->PortOffset + MAC_REG_EIFS, (unsigned char)pDevice->uEIFS);
+	VNSvOutPortB(pDevice->PortOffset + MAC_REG_SLOT, (unsigned char)pDevice->uSlot);
+	byMaxMin |= 0xA0;//1010 1111,C_CWMAX = 1023
+	VNSvOutPortB(pDevice->PortOffset + MAC_REG_CWMAXMIN0, (unsigned char)byMaxMin);
 }
 
-void CARDvUpdateBasicTopRate (void *pDeviceHandler)
+void CARDvUpdateBasicTopRate(void *pDeviceHandler)
 {
-    PSDevice pDevice = (PSDevice) pDeviceHandler;
-    unsigned char byTopOFDM = RATE_24M, byTopCCK = RATE_1M;
-    unsigned char ii;
-
-     //Determines the highest basic rate.
-     for (ii = RATE_54M; ii >= RATE_6M; ii --) {
-         if ( (pDevice->wBasicRate) & ((unsigned short)(1<<ii)) ) {
-             byTopOFDM = ii;
-             break;
-         }
-     }
-     pDevice->byTopOFDMBasicRate = byTopOFDM;
-
-     for (ii = RATE_11M;; ii --) {
-         if ( (pDevice->wBasicRate) & ((unsigned short)(1<<ii)) ) {
-             byTopCCK = ii;
-             break;
-         }
-         if (ii == RATE_1M)
-            break;
-     }
-     pDevice->byTopCCKBasicRate = byTopCCK;
+	PSDevice pDevice = (PSDevice) pDeviceHandler;
+	unsigned char byTopOFDM = RATE_24M, byTopCCK = RATE_1M;
+	unsigned char ii;
+
+	//Determines the highest basic rate.
+	for (ii = RATE_54M; ii >= RATE_6M; ii--) {
+		if ((pDevice->wBasicRate) & ((unsigned short)(1<<ii))) {
+			byTopOFDM = ii;
+			break;
+		}
+	}
+	pDevice->byTopOFDMBasicRate = byTopOFDM;
+
+	for (ii = RATE_11M;; ii--) {
+		if ((pDevice->wBasicRate) & ((unsigned short)(1<<ii))) {
+			byTopCCK = ii;
+			break;
+		}
+		if (ii == RATE_1M)
+			break;
+	}
+	pDevice->byTopCCKBasicRate = byTopCCK;
 }
 
-
 /*
  * Description: Set NIC Tx Basic Rate
  *
@@ -1947,44 +1890,42 @@ void CARDvUpdateBasicTopRate (void *pDeviceHandler)
  * Return Value: true if succeeded; false if failed.
  *
  */
-bool CARDbAddBasicRate (void *pDeviceHandler, unsigned short wRateIdx)
+bool CARDbAddBasicRate(void *pDeviceHandler, unsigned short wRateIdx)
 {
-    PSDevice pDevice = (PSDevice) pDeviceHandler;
-    unsigned short wRate = (unsigned short)(1<<wRateIdx);
+	PSDevice pDevice = (PSDevice) pDeviceHandler;
+	unsigned short wRate = (unsigned short)(1<<wRateIdx);
 
-    pDevice->wBasicRate |= wRate;
+	pDevice->wBasicRate |= wRate;
 
-    //Determines the highest basic rate.
-    CARDvUpdateBasicTopRate((void *)pDevice);
+	//Determines the highest basic rate.
+	CARDvUpdateBasicTopRate((void *)pDevice);
 
-    return(true);
+	return true;
 }
 
-bool CARDbIsOFDMinBasicRate (void *pDeviceHandler)
+bool CARDbIsOFDMinBasicRate(void *pDeviceHandler)
 {
-    PSDevice pDevice = (PSDevice) pDeviceHandler;
-    int ii;
-
-    for (ii = RATE_54M; ii >= RATE_6M; ii --) {
-        if ((pDevice->wBasicRate) & ((unsigned short)(1<<ii)))
-            return true;
-    }
-    return false;
+	PSDevice pDevice = (PSDevice)pDeviceHandler;
+	int ii;
+
+	for (ii = RATE_54M; ii >= RATE_6M; ii--) {
+		if ((pDevice->wBasicRate) & ((unsigned short)(1 << ii)))
+			return true;
+	}
+	return false;
 }
 
-unsigned char CARDbyGetPktType (void *pDeviceHandler)
+unsigned char CARDbyGetPktType(void *pDeviceHandler)
 {
-    PSDevice pDevice = (PSDevice) pDeviceHandler;
-
-    if (pDevice->byBBType == BB_TYPE_11A || pDevice->byBBType == BB_TYPE_11B) {
-        return (unsigned char)pDevice->byBBType;
-    }
-    else if (CARDbIsOFDMinBasicRate((void *)pDevice)) {
-        return PK_TYPE_11GA;
-    }
-    else {
-    	return PK_TYPE_11GB;
-    }
+	PSDevice pDevice = (PSDevice) pDeviceHandler;
+
+	if (pDevice->byBBType == BB_TYPE_11A || pDevice->byBBType == BB_TYPE_11B) {
+		return (unsigned char)pDevice->byBBType;
+	} else if (CARDbIsOFDMinBasicRate((void *)pDevice)) {
+		return PK_TYPE_11GA;
+	} else {
+		return PK_TYPE_11GB;
+	}
 }
 
 /*
@@ -2000,23 +1941,22 @@ unsigned char CARDbyGetPktType (void *pDeviceHandler)
  * Return Value: none
  *
  */
-void CARDvSetLoopbackMode (unsigned long dwIoBase, unsigned short wLoopbackMode)
+void CARDvSetLoopbackMode(unsigned long dwIoBase, unsigned short wLoopbackMode)
 {
-    switch(wLoopbackMode) {
-    case CARD_LB_NONE:
-    case CARD_LB_MAC:
-    case CARD_LB_PHY:
-        break;
-    default:
-        ASSERT(false);
-        break;
-    }
-    // set MAC loopback
-    MACvSetLoopbackMode(dwIoBase, LOBYTE(wLoopbackMode));
-    // set Baseband loopback
+	switch (wLoopbackMode) {
+	case CARD_LB_NONE:
+	case CARD_LB_MAC:
+	case CARD_LB_PHY:
+		break;
+	default:
+		ASSERT(false);
+		break;
+	}
+	// set MAC loopback
+	MACvSetLoopbackMode(dwIoBase, LOBYTE(wLoopbackMode));
+	// set Baseband loopback
 }
 
-
 /*
  * Description: Software Reset NIC
  *
@@ -2029,18 +1969,17 @@ void CARDvSetLoopbackMode (unsigned long dwIoBase, unsigned short wLoopbackMode)
  * Return Value: none
  *
  */
-bool CARDbSoftwareReset (void *pDeviceHandler)
+bool CARDbSoftwareReset(void *pDeviceHandler)
 {
-    PSDevice pDevice = (PSDevice) pDeviceHandler;
+	PSDevice pDevice = (PSDevice) pDeviceHandler;
 
-    // reset MAC
-    if (!MACbSafeSoftwareReset(pDevice->PortOffset))
-        return false;
+	// reset MAC
+	if (!MACbSafeSoftwareReset(pDevice->PortOffset))
+		return false;
 
-    return true;
+	return true;
 }
 
-
 /*
  * Description: Calculate TSF offset of two TSF input
  *              Get TSF Offset from RxBCN's TSF and local TSF
@@ -2056,30 +1995,28 @@ bool CARDbSoftwareReset (void *pDeviceHandler)
  * Return Value: TSF Offset value
  *
  */
-QWORD CARDqGetTSFOffset (unsigned char byRxRate, QWORD qwTSF1, QWORD qwTSF2)
+QWORD CARDqGetTSFOffset(unsigned char byRxRate, QWORD qwTSF1, QWORD qwTSF2)
 {
-    QWORD   qwTSFOffset;
-    unsigned short wRxBcnTSFOffst= 0;
-
-    HIDWORD(qwTSFOffset) = 0;
-    LODWORD(qwTSFOffset) = 0;
-    wRxBcnTSFOffst = cwRXBCNTSFOff[byRxRate%MAX_RATE];
-    (qwTSF2).u.dwLowDword += (unsigned long)(wRxBcnTSFOffst);
-    if ((qwTSF2).u.dwLowDword < (unsigned long)(wRxBcnTSFOffst)) {
-        (qwTSF2).u.dwHighDword++;
-    }
-    LODWORD(qwTSFOffset) = LODWORD(qwTSF1) - LODWORD(qwTSF2);
-    if (LODWORD(qwTSF1) < LODWORD(qwTSF2)) {
-        // if borrow needed
-        HIDWORD(qwTSFOffset) = HIDWORD(qwTSF1) - HIDWORD(qwTSF2) - 1 ;
-    }
-    else {
-        HIDWORD(qwTSFOffset) = HIDWORD(qwTSF1) - HIDWORD(qwTSF2);
-    };
-    return (qwTSFOffset);
+	QWORD   qwTSFOffset;
+	unsigned short wRxBcnTSFOffst = 0;
+
+	HIDWORD(qwTSFOffset) = 0;
+	LODWORD(qwTSFOffset) = 0;
+	wRxBcnTSFOffst = cwRXBCNTSFOff[byRxRate%MAX_RATE];
+	(qwTSF2).u.dwLowDword += (unsigned long)(wRxBcnTSFOffst);
+	if ((qwTSF2).u.dwLowDword < (unsigned long)(wRxBcnTSFOffst)) {
+		(qwTSF2).u.dwHighDword++;
+	}
+	LODWORD(qwTSFOffset) = LODWORD(qwTSF1) - LODWORD(qwTSF2);
+	if (LODWORD(qwTSF1) < LODWORD(qwTSF2)) {
+		// if borrow needed
+		HIDWORD(qwTSFOffset) = HIDWORD(qwTSF1) - HIDWORD(qwTSF2) - 1;
+	} else {
+		HIDWORD(qwTSFOffset) = HIDWORD(qwTSF1) - HIDWORD(qwTSF2);
+	};
+	return qwTSFOffset;
 }
 
-
 /*
  * Description: Read NIC TSF counter
  *              Get local TSF counter
@@ -2093,26 +2030,25 @@ QWORD CARDqGetTSFOffset (unsigned char byRxRate, QWORD qwTSF1, QWORD qwTSF2)
  * Return Value: true if success; otherwise false
  *
  */
-bool CARDbGetCurrentTSF (unsigned long dwIoBase, PQWORD pqwCurrTSF)
+bool CARDbGetCurrentTSF(unsigned long dwIoBase, PQWORD pqwCurrTSF)
 {
-    unsigned short ww;
-    unsigned char byData;
-
-    MACvRegBitsOn(dwIoBase, MAC_REG_TFTCTL, TFTCTL_TSFCNTRRD);
-    for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
-        VNSvInPortB(dwIoBase + MAC_REG_TFTCTL, &byData);
-        if ( !(byData & TFTCTL_TSFCNTRRD))
-            break;
-    }
-    if (ww == W_MAX_TIMEOUT)
-        return(false);
-    VNSvInPortD(dwIoBase + MAC_REG_TSFCNTR, &LODWORD(*pqwCurrTSF));
-    VNSvInPortD(dwIoBase + MAC_REG_TSFCNTR + 4, &HIDWORD(*pqwCurrTSF));
-
-    return(true);
+	unsigned short ww;
+	unsigned char byData;
+
+	MACvRegBitsOn(dwIoBase, MAC_REG_TFTCTL, TFTCTL_TSFCNTRRD);
+	for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
+		VNSvInPortB(dwIoBase + MAC_REG_TFTCTL, &byData);
+		if (!(byData & TFTCTL_TSFCNTRRD))
+			break;
+	}
+	if (ww == W_MAX_TIMEOUT)
+		return false;
+	VNSvInPortD(dwIoBase + MAC_REG_TSFCNTR, &LODWORD(*pqwCurrTSF));
+	VNSvInPortD(dwIoBase + MAC_REG_TSFCNTR + 4, &HIDWORD(*pqwCurrTSF));
+
+	return true;
 }
 
-
 /*
  * Description: Read NIC TSF counter
  *              Get NEXTTBTT from adjusted TSF and Beacon Interval
@@ -2127,36 +2063,34 @@ bool CARDbGetCurrentTSF (unsigned long dwIoBase, PQWORD pqwCurrTSF)
  * Return Value: TSF value of next Beacon
  *
  */
-QWORD CARDqGetNextTBTT (QWORD qwTSF, unsigned short wBeaconInterval)
+QWORD CARDqGetNextTBTT(QWORD qwTSF, unsigned short wBeaconInterval)
 {
-
-    unsigned int uLowNextTBTT;
-    unsigned int uHighRemain, uLowRemain;
-    unsigned int uBeaconInterval;
-
-    uBeaconInterval = wBeaconInterval * 1024;
-    // Next TBTT = ((local_current_TSF / beacon_interval) + 1 ) * beacon_interval
-    uLowNextTBTT = (LODWORD(qwTSF) >> 10) << 10;
-    // low dword (mod) bcn
-    uLowRemain = (uLowNextTBTT) % uBeaconInterval;
+	unsigned int uLowNextTBTT;
+	unsigned int uHighRemain, uLowRemain;
+	unsigned int uBeaconInterval;
+
+	uBeaconInterval = wBeaconInterval * 1024;
+	// Next TBTT = ((local_current_TSF / beacon_interval) + 1) * beacon_interval
+	uLowNextTBTT = (LODWORD(qwTSF) >> 10) << 10;
+	// low dword (mod) bcn
+	uLowRemain = (uLowNextTBTT) % uBeaconInterval;
 //    uHighRemain = ((0x80000000 % uBeaconInterval)* 2 * HIDWORD(qwTSF))
 //                  % uBeaconInterval;
-    // high dword (mod) bcn
-    uHighRemain = (((0xffffffff % uBeaconInterval) + 1) * HIDWORD(qwTSF))
-                  % uBeaconInterval;
-    uLowRemain = (uHighRemain + uLowRemain) % uBeaconInterval;
-    uLowRemain = uBeaconInterval - uLowRemain;
+	// high dword (mod) bcn
+	uHighRemain = (((0xffffffff % uBeaconInterval) + 1) * HIDWORD(qwTSF))
+		% uBeaconInterval;
+	uLowRemain = (uHighRemain + uLowRemain) % uBeaconInterval;
+	uLowRemain = uBeaconInterval - uLowRemain;
 
-    // check if carry when add one beacon interval
-    if ((~uLowNextTBTT) < uLowRemain)
-        HIDWORD(qwTSF) ++ ;
+	// check if carry when add one beacon interval
+	if ((~uLowNextTBTT) < uLowRemain)
+		HIDWORD(qwTSF)++;
 
-    LODWORD(qwTSF) = uLowNextTBTT + uLowRemain;
+	LODWORD(qwTSF) = uLowNextTBTT + uLowRemain;
 
-    return (qwTSF);
+	return qwTSF;
 }
 
-
 /*
  * Description: Set NIC TSF counter for first Beacon time
  *              Get NEXTTBTT from adjusted TSF and Beacon Interval
@@ -2171,24 +2105,22 @@ QWORD CARDqGetNextTBTT (QWORD qwTSF, unsigned short wBeaconInterval)
  * Return Value: none
  *
  */
-void CARDvSetFirstNextTBTT (unsigned long dwIoBase, unsigned short wBeaconInterval)
+void CARDvSetFirstNextTBTT(unsigned long dwIoBase, unsigned short wBeaconInterval)
 {
-
-    QWORD   qwNextTBTT;
-
-    HIDWORD(qwNextTBTT) = 0;
-    LODWORD(qwNextTBTT) = 0;
-    CARDbGetCurrentTSF(dwIoBase, &qwNextTBTT); //Get Local TSF counter
-    qwNextTBTT = CARDqGetNextTBTT(qwNextTBTT, wBeaconInterval);
-    // Set NextTBTT
-    VNSvOutPortD(dwIoBase + MAC_REG_NEXTTBTT, LODWORD(qwNextTBTT));
-    VNSvOutPortD(dwIoBase + MAC_REG_NEXTTBTT + 4, HIDWORD(qwNextTBTT));
-    MACvRegBitsOn(dwIoBase, MAC_REG_TFTCTL, TFTCTL_TBTTSYNCEN);
-    //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Card:First Next TBTT[%8xh:%8xh] \n", HIDWORD(qwNextTBTT), LODWORD(qwNextTBTT));
-    return;
+	QWORD   qwNextTBTT;
+
+	HIDWORD(qwNextTBTT) = 0;
+	LODWORD(qwNextTBTT) = 0;
+	CARDbGetCurrentTSF(dwIoBase, &qwNextTBTT); //Get Local TSF counter
+	qwNextTBTT = CARDqGetNextTBTT(qwNextTBTT, wBeaconInterval);
+	// Set NextTBTT
+	VNSvOutPortD(dwIoBase + MAC_REG_NEXTTBTT, LODWORD(qwNextTBTT));
+	VNSvOutPortD(dwIoBase + MAC_REG_NEXTTBTT + 4, HIDWORD(qwNextTBTT));
+	MACvRegBitsOn(dwIoBase, MAC_REG_TFTCTL, TFTCTL_TBTTSYNCEN);
+	//DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Card:First Next TBTT[%8xh:%8xh] \n", HIDWORD(qwNextTBTT), LODWORD(qwNextTBTT));
+	return;
 }
 
-
 /*
  * Description: Sync NIC TSF counter for Beacon time
  *              Get NEXTTBTT and write to HW
@@ -2204,23 +2136,15 @@ void CARDvSetFirstNextTBTT (unsigned long dwIoBase, unsigned short wBeaconInterv
  * Return Value: none
  *
  */
-void CARDvUpdateNextTBTT (unsigned long dwIoBase, QWORD qwTSF, unsigned short wBeaconInterval)
+void CARDvUpdateNextTBTT(unsigned long dwIoBase, QWORD qwTSF, unsigned short wBeaconInterval)
 {
-
-    qwTSF = CARDqGetNextTBTT(qwTSF, wBeaconInterval);
-    // Set NextTBTT
-    VNSvOutPortD(dwIoBase + MAC_REG_NEXTTBTT, LODWORD(qwTSF));
-    VNSvOutPortD(dwIoBase + MAC_REG_NEXTTBTT + 4, HIDWORD(qwTSF));
-    MACvRegBitsOn(dwIoBase, MAC_REG_TFTCTL, TFTCTL_TBTTSYNCEN);
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Card:Update Next TBTT[%8xh:%8xh] \n",
-		    (unsigned int) HIDWORD(qwTSF), (unsigned int) LODWORD(qwTSF));
-
-    return;
+	qwTSF = CARDqGetNextTBTT(qwTSF, wBeaconInterval);
+	// Set NextTBTT
+	VNSvOutPortD(dwIoBase + MAC_REG_NEXTTBTT, LODWORD(qwTSF));
+	VNSvOutPortD(dwIoBase + MAC_REG_NEXTTBTT + 4, HIDWORD(qwTSF));
+	MACvRegBitsOn(dwIoBase, MAC_REG_TFTCTL, TFTCTL_TBTTSYNCEN);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Card:Update Next TBTT[%8xh:%8xh] \n",
+		(unsigned int) HIDWORD(qwTSF), (unsigned int) LODWORD(qwTSF));
+
+	return;
 }
-
-
-
-
-
-
-
diff --git a/drivers/staging/vt6655/card.h b/drivers/staging/vt6655/card.h
index e0836e1..ac6e2b4 100644
--- a/drivers/staging/vt6655/card.h
+++ b/drivers/staging/vt6655/card.h
@@ -41,7 +41,6 @@
 #define CARD_LB_MAC             MAKEWORD(MAC_LB_INTERNAL, 0)   // PHY must ISO, avoid MAC loopback packet go out
 #define CARD_LB_PHY             MAKEWORD(MAC_LB_EXT, 0)
 
-
 #define DEFAULT_MSDU_LIFETIME           512  // ms
 #define DEFAULT_MSDU_LIFETIME_RES_64us  8000 // 64us
 
@@ -53,34 +52,32 @@
 #define CB_MAX_CHANNEL          (CB_MAX_CHANNEL_24G+CB_MAX_CHANNEL_5G)
 
 typedef enum _CARD_PHY_TYPE {
-    PHY_TYPE_AUTO,
-    PHY_TYPE_11B,
-    PHY_TYPE_11G,
-    PHY_TYPE_11A
+	PHY_TYPE_AUTO,
+	PHY_TYPE_11B,
+	PHY_TYPE_11G,
+	PHY_TYPE_11A
 } CARD_PHY_TYPE, *PCARD_PHY_TYPE;
 
 typedef enum _CARD_PKT_TYPE {
-    PKT_TYPE_802_11_BCN,
-    PKT_TYPE_802_11_MNG,
-    PKT_TYPE_802_11_DATA,
-    PKT_TYPE_802_11_ALL
+	PKT_TYPE_802_11_BCN,
+	PKT_TYPE_802_11_MNG,
+	PKT_TYPE_802_11_DATA,
+	PKT_TYPE_802_11_ALL
 } CARD_PKT_TYPE, *PCARD_PKT_TYPE;
 
 typedef enum _CARD_STATUS_TYPE {
-    CARD_STATUS_MEDIA_CONNECT,
-    CARD_STATUS_MEDIA_DISCONNECT,
-    CARD_STATUS_PMKID
+	CARD_STATUS_MEDIA_CONNECT,
+	CARD_STATUS_MEDIA_DISCONNECT,
+	CARD_STATUS_PMKID
 } CARD_STATUS_TYPE, *PCARD_STATUS_TYPE;
 
 typedef enum _CARD_OP_MODE {
-    OP_MODE_INFRASTRUCTURE,
-    OP_MODE_ADHOC,
-    OP_MODE_AP,
-    OP_MODE_UNKNOWN
+	OP_MODE_INFRASTRUCTURE,
+	OP_MODE_ADHOC,
+	OP_MODE_AP,
+	OP_MODE_UNKNOWN
 } CARD_OP_MODE, *PCARD_OP_MODE;
 
-
-
 /*---------------------  Export Classes  ----------------------------*/
 
 /*---------------------  Export Variables  --------------------------*/
@@ -119,80 +116,76 @@ bool CARDbSetBSSID(void *pDeviceHandler, unsigned char *pbyBSSID, CARD_OP_MODE e
 
 bool
 CARDbPowerDown(
-    void *pDeviceHandler
-    );
+	void *pDeviceHandler
+);
 
 bool CARDbSetTxDataRate(
-    void *pDeviceHandler,
-    unsigned short wDataRate
-    );
-
+	void *pDeviceHandler,
+	unsigned short wDataRate
+);
 
-bool CARDbRemoveKey (void *pDeviceHandler, unsigned char *pbyBSSID);
+bool CARDbRemoveKey(void *pDeviceHandler, unsigned char *pbyBSSID);
 
 bool
-CARDbAdd_PMKID_Candidate (
-    void *pDeviceHandler,
-    unsigned char *pbyBSSID,
-    bool bRSNCapExist,
-    unsigned short wRSNCap
-    );
+CARDbAdd_PMKID_Candidate(
+	void *pDeviceHandler,
+	unsigned char *pbyBSSID,
+	bool bRSNCapExist,
+	unsigned short wRSNCap
+);
 
 void *
-CARDpGetCurrentAddress (
-    void *pDeviceHandler
-    );
+CARDpGetCurrentAddress(
+	void *pDeviceHandler
+);
 
 bool
-CARDbStartMeasure (
-    void *pDeviceHandler,
-    void *pvMeasureEIDs,
-    unsigned int uNumOfMeasureEIDs
-    );
+CARDbStartMeasure(
+	void *pDeviceHandler,
+	void *pvMeasureEIDs,
+	unsigned int uNumOfMeasureEIDs
+);
 
 bool
-CARDbChannelSwitch (
-    void *pDeviceHandler,
-    unsigned char byMode,
-    unsigned char byNewChannel,
-    unsigned char byCount
-    );
+CARDbChannelSwitch(
+	void *pDeviceHandler,
+	unsigned char byMode,
+	unsigned char byNewChannel,
+	unsigned char byCount
+);
 
 bool
-CARDbSetQuiet (
-    void *pDeviceHandler,
-    bool bResetQuiet,
-    unsigned char byQuietCount,
-    unsigned char byQuietPeriod,
-    unsigned short wQuietDuration,
-    unsigned short wQuietOffset
-    );
+CARDbSetQuiet(
+	void *pDeviceHandler,
+	bool bResetQuiet,
+	unsigned char byQuietCount,
+	unsigned char byQuietPeriod,
+	unsigned short wQuietDuration,
+	unsigned short wQuietOffset
+);
 
 bool
-CARDbStartQuiet (
-    void *pDeviceHandler
-    );
+CARDbStartQuiet(
+	void *pDeviceHandler
+);
 
 void
-CARDvSetPowerConstraint (
-    void *pDeviceHandler,
-    unsigned char byChannel,
-    char byPower
-    );
+CARDvSetPowerConstraint(
+	void *pDeviceHandler,
+	unsigned char byChannel,
+	char byPower
+);
 
 void
-CARDvGetPowerCapability (
-    void *pDeviceHandler,
-    unsigned char *pbyMinPower,
-    unsigned char *pbyMaxPower
-    );
+CARDvGetPowerCapability(
+	void *pDeviceHandler,
+	unsigned char *pbyMinPower,
+	unsigned char *pbyMaxPower
+);
 
 char
-CARDbyGetTransmitPower (
-    void *pDeviceHandler
-    );
+CARDbyGetTransmitPower(
+	void *pDeviceHandler
+);
 
 #endif // __CARD_H__
-
-
-
diff --git a/drivers/staging/vt6655/channel.c b/drivers/staging/vt6655/channel.c
index aa76e39..ba9481f 100644
--- a/drivers/staging/vt6655/channel.c
+++ b/drivers/staging/vt6655/channel.c
@@ -37,63 +37,63 @@ static int msglevel = MSG_LEVEL_INFO;
 
 static SChannelTblElement sChannelTbl[CARD_MAX_CHANNEL_TBL + 1] =
 {
-  {0,   0,    false,    0},
-  {1,   2412, true,     0},
-  {2,   2417, true,     0},
-  {3,   2422, true,     0},
-  {4,   2427, true,     0},
-  {5,   2432, true,     0},
-  {6,   2437, true,     0},
-  {7,   2442, true,     0},
-  {8,   2447, true,     0},
-  {9,   2452, true,     0},
-  {10,  2457, true,     0},
-  {11,  2462, true,     0},
-  {12,  2467, true,     0},
-  {13,  2472, true,     0},
-  {14,  2484, true,     0},
-  {183, 4915, true,     0},
-  {184, 4920, true,     0},
-  {185, 4925, true,     0},
-  {187, 4935, true,     0},
-  {188, 4940, true,     0},
-  {189, 4945, true,     0},
-  {192, 4960, true,     0},
-  {196, 4980, true,     0},
-  {7,   5035, true,     0},
-  {8,   5040, true,     0},
-  {9,   5045, true,     0},
-  {11,  5055, true,     0},
-  {12,  5060, true,     0},
-  {16,  5080, true,     0},
-  {34,  5170, true,     0},
-  {36,  5180, true,     0},
-  {38,  5190, true,     0},
-  {40,  5200, true,     0},
-  {42,  5210, true,     0},
-  {44,  5220, true,     0},
-  {46,  5230, true,     0},
-  {48,  5240, true,     0},
-  {52,  5260, true,     0},
-  {56,  5280, true,     0},
-  {60,  5300, true,     0},
-  {64,  5320, true,     0},
-  {100, 5500, true,     0},
-  {104, 5520, true,     0},
-  {108, 5540, true,     0},
-  {112, 5560, true,     0},
-  {116, 5580, true,     0},
-  {120, 5600, true,     0},
-  {124, 5620, true,     0},
-  {128, 5640, true,     0},
-  {132, 5660, true,     0},
-  {136, 5680, true,     0},
-  {140, 5700, true,     0},
-  {149, 5745, true,     0},
-  {153, 5765, true,     0},
-  {157, 5785, true,     0},
-  {161, 5805, true,     0},
-  {165, 5825, true,     0}
+	{0,   0,    false,    0},
+	{1,   2412, true,     0},
+	{2,   2417, true,     0},
+	{3,   2422, true,     0},
+	{4,   2427, true,     0},
+	{5,   2432, true,     0},
+	{6,   2437, true,     0},
+	{7,   2442, true,     0},
+	{8,   2447, true,     0},
+	{9,   2452, true,     0},
+	{10,  2457, true,     0},
+	{11,  2462, true,     0},
+	{12,  2467, true,     0},
+	{13,  2472, true,     0},
+	{14,  2484, true,     0},
+	{183, 4915, true,     0},
+	{184, 4920, true,     0},
+	{185, 4925, true,     0},
+	{187, 4935, true,     0},
+	{188, 4940, true,     0},
+	{189, 4945, true,     0},
+	{192, 4960, true,     0},
+	{196, 4980, true,     0},
+	{7,   5035, true,     0},
+	{8,   5040, true,     0},
+	{9,   5045, true,     0},
+	{11,  5055, true,     0},
+	{12,  5060, true,     0},
+	{16,  5080, true,     0},
+	{34,  5170, true,     0},
+	{36,  5180, true,     0},
+	{38,  5190, true,     0},
+	{40,  5200, true,     0},
+	{42,  5210, true,     0},
+	{44,  5220, true,     0},
+	{46,  5230, true,     0},
+	{48,  5240, true,     0},
+	{52,  5260, true,     0},
+	{56,  5280, true,     0},
+	{60,  5300, true,     0},
+	{64,  5320, true,     0},
+	{100, 5500, true,     0},
+	{104, 5520, true,     0},
+	{108, 5540, true,     0},
+	{112, 5560, true,     0},
+	{116, 5580, true,     0},
+	{120, 5600, true,     0},
+	{124, 5620, true,     0},
+	{128, 5640, true,     0},
+	{132, 5660, true,     0},
+	{136, 5680, true,     0},
+	{140, 5700, true,     0},
+	{149, 5745, true,     0},
+	{153, 5765, true,     0},
+	{157, 5785, true,     0},
+	{161, 5805, true,     0},
+	{165, 5825, true,     0}
 };
 
 /************************************************************************
@@ -112,244 +112,244 @@ static struct
  ************************************************************************/
 /* Country          Available channels, ended with 0                    */
 /*                                              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  44  45  46  47  48  49  50  51  52  53  54  55  56  */
-{CCODE_FCC,                     {'U','S'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1}
-                                         ,  {  27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 17,  0, 17,  0, 17,  0, 17, 23, 23, 23, 23,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 30, 30, 30, 30, 30}  },
-{CCODE_TELEC,                   {'J','P'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  1,  0,  0,  1,  0,  1,  1,  0,  1,  0,  0,  1,  1,  1,  0,  1,  0,  1,  0,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}
-                                         ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0, 23,  0,  0, 23,  0, 23, 23,  0, 23,  0,  0, 23, 23, 23,  0, 23,  0, 23,  0, 23,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
-{CCODE_ETSI,                    {'E','U'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0}
-                                         ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20,  0, 20,  0, 20,  0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,  0,  0,  0}  },
-{CCODE_RESV3,                   {' ',' '},  {   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,  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,  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,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
-{CCODE_RESV4,                   {' ',' '},  {   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,  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,  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,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
-{CCODE_RESV5,                   {' ',' '},  {   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,  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,  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,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
-{CCODE_RESV6,                   {' ',' '},  {   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,  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,  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,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
-{CCODE_RESV7,                   {' ',' '},  {   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,  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,  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,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
-{CCODE_RESV8,                   {' ',' '},  {   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,  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,  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,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
-{CCODE_RESV9,                   {' ',' '},  {   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,  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,  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,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
-{CCODE_RESVa,                   {' ',' '},  {   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,  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,  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,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
-{CCODE_RESVb,                   {' ',' '},  {   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,  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,  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,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
-{CCODE_RESVc,                   {' ',' '},  {   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,  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,  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,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
-{CCODE_RESVd,                   {' ',' '},  {   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,  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,  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,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
-{CCODE_RESVe,                   {' ',' '},  {   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,  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,  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,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
-{CCODE_ALLBAND,                 {' ',' '},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1}
-                                         ,  {   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,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
-{CCODE_ALBANIA,                 {'A','L'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
-{CCODE_ALGERIA,                 {'D','Z'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
-{CCODE_ARGENTINA,               {'A','R'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  0}
-                                         ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 17, 17, 17,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 30, 30, 30, 30,  0}  },
-{CCODE_ARMENIA,                 {'A','M'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}
-                                         ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 18,  0, 18,  0, 18,  0, 18, 18, 18, 18, 18,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
-{CCODE_AUSTRALIA,               {'A','U'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1}
-                                         ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 23,  0, 23,  0, 23,  0, 23, 23, 23, 23, 23,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 30, 30, 30, 30, 30}  },
-{CCODE_AUSTRIA,                 {'A','T'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}
-                                         ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 15,  0, 15,  0, 15,  0, 15,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
-{CCODE_AZERBAIJAN,              {'A','Z'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}
-                                         ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 18,  0, 18,  0, 18,  0, 18, 18, 18, 18, 18,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
-{CCODE_BAHRAIN,                 {'B','H'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
-{CCODE_BELARUS,                 {'B','Y'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
-{CCODE_BELGIUM,                 {'B','E'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}
-                                         ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 18,  0, 18,  0, 18,  0, 18,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
-{CCODE_BELIZE,                  {'B','Z'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1}
-                                         ,  {  30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,  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,  0,  0,  0,  0,  0,  0, 30, 30, 30, 30, 30}  },
-{CCODE_BOLIVIA,                 {'B','O'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1}
-                                         ,  {  30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,  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,  0,  0,  0,  0,  0,  0, 30, 30, 30, 30, 30}  },
-{CCODE_BRAZIL,                  {'B','R'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
-{CCODE_BRUNEI_DARUSSALAM,       {'B','N'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1}
-                                         ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  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,  0,  0,  0,  0,  0,  0, 30, 30, 30, 30, 30}  },
-{CCODE_BULGARIA,                {'B','G'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  0,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0}
-                                         ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 23,  0, 23,  0, 23,  0, 23, 23, 23,  0,  0, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,  0,  0,  0,  0,  0}  },
-{CCODE_CANADA,                  {'C','A'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1}
-                                         ,  {  27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 17,  0, 17,  0, 17,  0, 17, 23, 23, 23, 23,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 30, 30, 30, 30, 30}  },
-{CCODE_CHILE,                   {'C','L'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1}
-                                         ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  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,  0,  0,  0,  0,  0,  0, 17, 17, 17, 17, 17}  },
-{CCODE_CHINA,                   {'C','N'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1}
-                                         ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  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,  0,  0,  0,  0,  0,  0, 30, 30, 30, 30, 30}  },
-{CCODE_COLOMBIA,                {'C','O'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1}
-                                         ,  {  27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 17,  0, 17,  0, 17,  0, 17, 23, 23, 23, 23,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 30, 30, 30, 30, 30}  },
-{CCODE_COSTA_RICA,              {'C','R'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
-{CCODE_CROATIA,                 {'H','R'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}
-                                         ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20,  0, 20,  0, 20,  0, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
-{CCODE_CYPRUS,                  {'C','Y'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0}
-                                         ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20,  0, 20,  0, 20,  0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,  0,  0,  0}  },
-{CCODE_CZECH,                   {'C','Z'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}
-                                         ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20,  0, 20,  0, 20,  0, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
-{CCODE_DENMARK,                 {'D','K'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0}
-                                         ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20,  0, 20,  0, 20,  0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,  0,  0,  0}  },
-{CCODE_DOMINICAN_REPUBLIC,      {'D','O'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1}
-                                         ,  {  27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 17,  0, 17,  0, 17,  0, 17, 23, 23, 23, 23,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 30, 30, 30, 30, 30}  },
-{CCODE_ECUADOR,                 {'E','C'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
-{CCODE_EGYPT,                   {'E','G'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
-{CCODE_EL_SALVADOR,             {'S','V'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
-{CCODE_ESTONIA,                 {'E','E'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0}
-                                         ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20,  0, 20,  0, 20,  0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,  0,  0,  0}  },
-{CCODE_FINLAND,                 {'F','I'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0}
-                                         ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20,  0, 20,  0, 20,  0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,  0,  0,  0}  },
-{CCODE_FRANCE,                  {'F','R'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}
-                                         ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20,  0, 20,  0, 20,  0, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
-{CCODE_GERMANY,                 {'D','E'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0}
-                                         ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20,  0, 20,  0, 20,  0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,  0,  0,  0}  },
-{CCODE_GREECE,                  {'G','R'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
-{CCODE_GEORGIA,                 {'G','E'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}
-                                         ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 18,  0, 18,  0, 18,  0, 18, 18, 18, 18, 18,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
-{CCODE_GUATEMALA,               {'G','T'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1}
-                                         ,  {  27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 17,  0, 17,  0, 17,  0, 17, 23, 23, 23, 23,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 30, 30, 30, 30, 30}  },
-{CCODE_HONDURAS,                {'H','N'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
-{CCODE_HONG_KONG,               {'H','K'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1}
-                                         ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 23,  0, 23,  0, 23,  0, 23, 23, 23, 23, 23,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 30, 30, 30, 30, 30}  },
-{CCODE_HUNGARY,                 {'H','U'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}
-                                         ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 18,  0, 18,  0, 18,  0, 18,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
-{CCODE_ICELAND,                 {'I','S'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0}
-                                         ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20,  0, 20,  0, 20,  0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,  0,  0,  0}  },
-{CCODE_INDIA,                   {'I','N'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
-{CCODE_INDONESIA,               {'I','D'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
-{CCODE_IRAN,                    {'I','R'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1}
-                                         ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  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,  0,  0,  0,  0,  0,  0, 30, 30, 30, 30, 30}  },
-{CCODE_IRELAND,                 {'I','E'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0}
-                                         ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20,  0, 20,  0, 20,  0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,  0,  0,  0}  },
-{CCODE_ITALY,                   {'I','T'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0}
-                                         ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20,  0, 20,  0, 20,  0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,  0,  0,  0}  },
-{CCODE_ISRAEL,                  {'I','L'},  {   0,  0,  0,  0,  1,  1,  1,  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,  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,  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,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
-{CCODE_JAPAN,                   {'J','P'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}
-                                         ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 23,  0, 23,  0, 23,  0, 23,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
-{CCODE_JORDAN,                  {'J','O'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
-{CCODE_KAZAKHSTAN,              {'K','Z'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
-{CCODE_KUWAIT,                  {'K','W'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
-{CCODE_LATVIA,                  {'L','V'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
-{CCODE_LEBANON,                 {'L','B'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
-{CCODE_LEICHTENSTEIN,           {'L','I'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}
-                                         ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 18,  0, 18,  0, 18,  0, 18,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
-{CCODE_LITHUANIA,               {'L','T'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0}
-                                         ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20,  0, 20,  0, 20,  0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,  0,  0,  0}  },
-{CCODE_LUXEMBURG,               {'L','U'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0}
-                                         ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20,  0, 20,  0, 20,  0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,  0,  0,  0}  },
-{CCODE_MACAU,                   {'M','O'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1}
-                                         ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 23,  0, 23,  0, 23,  0, 23, 23, 23, 23, 23,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 30, 30, 30, 30, 30}  },
-{CCODE_MACEDONIA,               {'M','K'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
-{CCODE_MALTA,                   {'M','T'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  0}
-                                         ,  {  23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 16,  0, 16,  0, 16,  0, 16, 16, 16, 16, 16,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 16, 16, 16, 16,  0}  },
-{CCODE_MALAYSIA,                {'M','Y'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
-{CCODE_MEXICO,                  {'M','X'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1}
-                                         ,  {  27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 17,  0, 17,  0, 17,  0, 17, 23, 23, 23, 23,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 30, 30, 30, 30, 30}  },
-{CCODE_MONACO,                  {'M','C'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}
-                                         ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 18,  0, 18,  0, 18,  0, 18, 18, 18, 18, 18,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
-{CCODE_MOROCCO,                 {'M','A'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
-{CCODE_NETHERLANDS,             {'N','L'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0}
-                                         ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20,  0, 20,  0, 20,  0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,  0,  0,  0}  },
-{CCODE_NEW_ZEALAND,             {'N','Z'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1}
-                                         ,  {  30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 23,  0, 23,  0, 23,  0, 23, 23, 23, 23, 23,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 30, 30, 30, 30, 30}  },
-{CCODE_NORTH_KOREA,             {'K','P'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  0}
-                                         ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  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,  0,  0,  0,  0,  0,  0, 23, 23, 23, 23,  0}  },
-{CCODE_NORWAY,                  {'N','O'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0}
-                                         ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20,  0, 20,  0, 20,  0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,  0,  0,  0}  },
-{CCODE_OMAN,                    {'O','M'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
-{CCODE_PAKISTAN,                {'P','K'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
-{CCODE_PANAMA,                  {'P','A'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1}
-                                         ,  {  27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 17,  0, 17,  0, 17,  0, 17, 23, 23, 23, 23,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 30, 30, 30, 30, 30}  },
-{CCODE_PERU,                    {'P','E'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
-{CCODE_PHILIPPINES,             {'P','H'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1}
-                                         ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 17,  0, 17,  0, 17,  0, 17, 23, 23, 23, 23,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 30, 30, 30, 30, 30}  },
-{CCODE_POLAND,                  {'P','L'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0}
-                                         ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20,  0, 20,  0, 20,  0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,  0,  0,  0}  },
-{CCODE_PORTUGAL,                {'P','T'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0}
-                                         ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20,  0, 20,  0, 20,  0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,  0,  0,  0}  },
-{CCODE_PUERTO_RICO,             {'P','R'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1}
-                                         ,  {  27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 17,  0, 17,  0, 17,  0, 17, 23, 23, 23, 23,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 30, 30, 30, 30, 30}  },
-{CCODE_QATAR,                   {'Q','A'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
-{CCODE_ROMANIA,                 {'R','O'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
-{CCODE_RUSSIA,                  {'R','U'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
-{CCODE_SAUDI_ARABIA,            {'S','A'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
-{CCODE_SINGAPORE,               {'S','G'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1}
-                                         ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20,  0, 20,  0, 20,  0, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20, 20, 20, 20, 20}  },
-{CCODE_SLOVAKIA,                {'S','K'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  0}
-                                         ,  {  23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 16,  0, 16,  0, 16,  0, 16, 16, 16, 16, 16,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 16, 16, 16, 16,  0}  },
-{CCODE_SLOVENIA,                {'S','I'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0}
-                                         ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20,  0, 20,  0, 20,  0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,  0,  0,  0}  },
-{CCODE_SOUTH_AFRICA,            {'Z','A'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0}
-                                         ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20,  0, 20,  0, 20,  0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,  0,  0,  0}  },
-{CCODE_SOUTH_KOREA,             {'K','R'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  0}
-                                         ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  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,  0,  0,  0,  0,  0,  0, 23, 23, 23, 23,  0}  },
-{CCODE_SPAIN,                   {'E','S'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  0}
-                                         ,  {  23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 16,  0, 16,  0, 16,  0, 16, 16, 16, 16, 16,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 16, 16, 16, 16,  0}  },
-{CCODE_SWEDEN,                  {'S','E'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0}
-                                         ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20,  0, 20,  0, 20,  0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,  0,  0,  0}  },
-{CCODE_SWITZERLAND,             {'C','H'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}
-                                         ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 18,  0, 18,  0, 18,  0, 18,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
-{CCODE_SYRIA,                   {'S','Y'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
-{CCODE_TAIWAN,                  {'T','W'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  0}
-                                         ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 17, 17, 17,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 30, 30, 30, 30,  0}  },
-{CCODE_THAILAND,                {'T','H'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  0}
-                                         ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  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,  0,  0,  0,  0,  0,  0, 23, 23, 23, 23,  0}  },
-{CCODE_TRINIDAD_TOBAGO,         {'T','T'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}
-                                         ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 18,  0, 18,  0, 18,  0, 18, 18, 18, 18, 18,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
-{CCODE_TUNISIA,                 {'T','N'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}
-                                         ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20,  0, 20,  0, 20,  0, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
-{CCODE_TURKEY,                  {'T','R'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}
-                                         ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20,  0, 20,  0, 20,  0, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
-{CCODE_UK,                      {'G','B'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0}
-                                         ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20,  0, 20,  0, 20,  0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,  0,  0,  0}  },
-{CCODE_UKRAINE,                 {'U','A'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
-{CCODE_UNITED_ARAB_EMIRATES,    {'A','E'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
-{CCODE_UNITED_STATES,           {'U','S'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1}
-                                         ,  {  27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 17,  0, 17,  0, 17,  0, 17, 23, 23, 23, 23,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 30, 30, 30, 30, 30}  },
-{CCODE_URUGUAY,                 {'U','Y'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  0}
-                                         ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  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,  0,  0,  0,  0,  0,  0, 23, 23, 23, 23,  0}  },
-{CCODE_UZBEKISTAN,              {'U','Z'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0,  0,  0}  },
-{CCODE_VENEZUELA,               {'V','E'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  0}
-                                         ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  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,  0,  0,  0,  0,  0,  0, 23, 23, 23, 23,  0}  },
-{CCODE_VIETNAM,                 {'V','N'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
-{CCODE_YEMEN,                   {'Y','E'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
-{CCODE_ZIMBABWE,                {'Z','W'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
-{CCODE_JAPAN_W52_W53,           {'J','J'},  {   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,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  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,  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,  0,  0,  0,  0,  0,  0,  0,  0}  },
-{CCODE_MAX,                     {'U','N'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1}
-                                         ,  {   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,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  }
+	{CCODE_FCC,                     {'U' , 'S'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1}
+	 ,  {  27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 17,  0, 17,  0, 17,  0, 17, 23, 23, 23, 23,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 30, 30, 30, 30, 30}  },
+	{CCODE_TELEC,                   {'J' , 'P'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  1,  0,  0,  1,  0,  1,  1,  0,  1,  0,  0,  1,  1,  1,  0,  1,  0,  1,  0,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}
+	 ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0, 23,  0,  0, 23,  0, 23, 23,  0, 23,  0,  0, 23, 23, 23,  0, 23,  0, 23,  0, 23,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
+	{CCODE_ETSI,                    {'E' , 'U'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0}
+	 ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20,  0, 20,  0, 20,  0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,  0,  0,  0}  },
+	{CCODE_RESV3,                   {' ' , ' '},  {   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,  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,  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,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
+	{CCODE_RESV4,                   {' ' , ' '},  {   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,  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,  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,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
+	{CCODE_RESV5,                   {' ' , ' '},  {   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,  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,  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,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
+	{CCODE_RESV6,                   {' ' , ' '},  {   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,  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,  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,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
+	{CCODE_RESV7,                   {' ' , ' '},  {   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,  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,  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,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
+	{CCODE_RESV8,                   {' ' , ' '},  {   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,  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,  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,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
+	{CCODE_RESV9,                   {' ' , ' '},  {   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,  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,  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,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
+	{CCODE_RESVa,                   {' ' , ' '},  {   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,  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,  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,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
+	{CCODE_RESVb,                   {' ' , ' '},  {   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,  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,  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,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
+	{CCODE_RESVc,                   {' ' , ' '},  {   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,  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,  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,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
+	{CCODE_RESVd,                   {' ' , ' '},  {   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,  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,  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,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
+	{CCODE_RESVe,                   {' ' , ' '},  {   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,  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,  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,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
+	{CCODE_ALLBAND,                 {' ' , ' '},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1}
+	 ,  {   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,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
+	{CCODE_ALBANIA,                 {'A' , 'L'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
+	{CCODE_ALGERIA,                 {'D' , 'Z'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
+	{CCODE_ARGENTINA,               {'A' , 'R'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  0}
+	 ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 17, 17, 17,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 30, 30, 30, 30,  0}  },
+	{CCODE_ARMENIA,                 {'A' , 'M'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}
+	 ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 18,  0, 18,  0, 18,  0, 18, 18, 18, 18, 18,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
+	{CCODE_AUSTRALIA,               {'A' , 'U'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1}
+	 ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 23,  0, 23,  0, 23,  0, 23, 23, 23, 23, 23,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 30, 30, 30, 30, 30}  },
+	{CCODE_AUSTRIA,                 {'A' , 'T'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}
+	 ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 15,  0, 15,  0, 15,  0, 15,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
+	{CCODE_AZERBAIJAN,              {'A' , 'Z'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}
+	 ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 18,  0, 18,  0, 18,  0, 18, 18, 18, 18, 18,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
+	{CCODE_BAHRAIN,                 {'B' , 'H'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
+	{CCODE_BELARUS,                 {'B' , 'Y'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
+	{CCODE_BELGIUM,                 {'B' , 'E'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}
+	 ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 18,  0, 18,  0, 18,  0, 18,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
+	{CCODE_BELIZE,                  {'B' , 'Z'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1}
+	 ,  {  30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,  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,  0,  0,  0,  0,  0,  0, 30, 30, 30, 30, 30}  },
+	{CCODE_BOLIVIA,                 {'B' , 'O'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1}
+	 ,  {  30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,  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,  0,  0,  0,  0,  0,  0, 30, 30, 30, 30, 30}  },
+	{CCODE_BRAZIL,                  {'B' , 'R'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
+	{CCODE_BRUNEI_DARUSSALAM,       {'B' , 'N'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1}
+	 ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  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,  0,  0,  0,  0,  0,  0, 30, 30, 30, 30, 30}  },
+	{CCODE_BULGARIA,                {'B' , 'G'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  0,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0}
+	 ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 23,  0, 23,  0, 23,  0, 23, 23, 23,  0,  0, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,  0,  0,  0,  0,  0}  },
+	{CCODE_CANADA,                  {'C' , 'A'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1}
+	 ,  {  27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 17,  0, 17,  0, 17,  0, 17, 23, 23, 23, 23,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 30, 30, 30, 30, 30}  },
+	{CCODE_CHILE,                   {'C' , 'L'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1}
+	 ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  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,  0,  0,  0,  0,  0,  0, 17, 17, 17, 17, 17}  },
+	{CCODE_CHINA,                   {'C' , 'N'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1}
+	 ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  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,  0,  0,  0,  0,  0,  0, 30, 30, 30, 30, 30}  },
+	{CCODE_COLOMBIA,                {'C' , 'O'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1}
+	 ,  {  27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 17,  0, 17,  0, 17,  0, 17, 23, 23, 23, 23,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 30, 30, 30, 30, 30}  },
+	{CCODE_COSTA_RICA,              {'C' , 'R'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
+	{CCODE_CROATIA,                 {'H' , 'R'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}
+	 ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20,  0, 20,  0, 20,  0, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
+	{CCODE_CYPRUS,                  {'C' , 'Y'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0}
+	 ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20,  0, 20,  0, 20,  0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,  0,  0,  0}  },
+	{CCODE_CZECH,                   {'C' , 'Z'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}
+	 ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20,  0, 20,  0, 20,  0, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
+	{CCODE_DENMARK,                 {'D' , 'K'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0}
+	 ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20,  0, 20,  0, 20,  0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,  0,  0,  0}  },
+	{CCODE_DOMINICAN_REPUBLIC,      {'D' , 'O'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1}
+	 ,  {  27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 17,  0, 17,  0, 17,  0, 17, 23, 23, 23, 23,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 30, 30, 30, 30, 30}  },
+	{CCODE_ECUADOR,                 {'E' , 'C'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
+	{CCODE_EGYPT,                   {'E' , 'G'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
+	{CCODE_EL_SALVADOR,             {'S' , 'V'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
+	{CCODE_ESTONIA,                 {'E' , 'E'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0}
+	 ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20,  0, 20,  0, 20,  0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,  0,  0,  0}  },
+	{CCODE_FINLAND,                 {'F' , 'I'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0}
+	 ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20,  0, 20,  0, 20,  0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,  0,  0,  0}  },
+	{CCODE_FRANCE,                  {'F' , 'R'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}
+	 ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20,  0, 20,  0, 20,  0, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
+	{CCODE_GERMANY,                 {'D' , 'E'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0}
+	 ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20,  0, 20,  0, 20,  0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,  0,  0,  0}  },
+	{CCODE_GREECE,                  {'G' , 'R'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
+	{CCODE_GEORGIA,                 {'G' , 'E'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}
+	 ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 18,  0, 18,  0, 18,  0, 18, 18, 18, 18, 18,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
+	{CCODE_GUATEMALA,               {'G' , 'T'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1}
+	 ,  {  27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 17,  0, 17,  0, 17,  0, 17, 23, 23, 23, 23,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 30, 30, 30, 30, 30}  },
+	{CCODE_HONDURAS,                {'H' , 'N'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
+	{CCODE_HONG_KONG,               {'H' , 'K'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1}
+	 ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 23,  0, 23,  0, 23,  0, 23, 23, 23, 23, 23,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 30, 30, 30, 30, 30}  },
+	{CCODE_HUNGARY,                 {'H' , 'U'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}
+	 ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 18,  0, 18,  0, 18,  0, 18,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
+	{CCODE_ICELAND,                 {'I' , 'S'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0}
+	 ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20,  0, 20,  0, 20,  0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,  0,  0,  0}  },
+	{CCODE_INDIA,                   {'I' , 'N'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
+	{CCODE_INDONESIA,               {'I' , 'D'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
+	{CCODE_IRAN,                    {'I' , 'R'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1}
+	 ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  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,  0,  0,  0,  0,  0,  0, 30, 30, 30, 30, 30}  },
+	{CCODE_IRELAND,                 {'I' , 'E'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0}
+	 ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20,  0, 20,  0, 20,  0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,  0,  0,  0}  },
+	{CCODE_ITALY,                   {'I' , 'T'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0}
+	 ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20,  0, 20,  0, 20,  0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,  0,  0,  0}  },
+	{CCODE_ISRAEL,                  {'I' , 'L'},  {   0,  0,  0,  0,  1,  1,  1,  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,  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,  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,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
+	{CCODE_JAPAN,                   {'J' , 'P'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}
+	 ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 23,  0, 23,  0, 23,  0, 23,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
+	{CCODE_JORDAN,                  {'J' , 'O'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
+	{CCODE_KAZAKHSTAN,              {'K' , 'Z'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
+	{CCODE_KUWAIT,                  {'K' , 'W'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
+	{CCODE_LATVIA,                  {'L' , 'V'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
+	{CCODE_LEBANON,                 {'L' , 'B'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
+	{CCODE_LEICHTENSTEIN,           {'L' , 'I'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}
+	 ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 18,  0, 18,  0, 18,  0, 18,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
+	{CCODE_LITHUANIA,               {'L' , 'T'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0}
+	 ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20,  0, 20,  0, 20,  0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,  0,  0,  0}  },
+	{CCODE_LUXEMBURG,               {'L' , 'U'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0}
+	 ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20,  0, 20,  0, 20,  0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,  0,  0,  0}  },
+	{CCODE_MACAU,                   {'M' , 'O'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1}
+	 ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 23,  0, 23,  0, 23,  0, 23, 23, 23, 23, 23,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 30, 30, 30, 30, 30}  },
+	{CCODE_MACEDONIA,               {'M' , 'K'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
+	{CCODE_MALTA,                   {'M' , 'T'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  0}
+	 ,  {  23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 16,  0, 16,  0, 16,  0, 16, 16, 16, 16, 16,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 16, 16, 16, 16,  0}  },
+	{CCODE_MALAYSIA,                {'M' , 'Y'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
+	{CCODE_MEXICO,                  {'M' , 'X'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1}
+	 ,  {  27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 17,  0, 17,  0, 17,  0, 17, 23, 23, 23, 23,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 30, 30, 30, 30, 30}  },
+	{CCODE_MONACO,                  {'M' , 'C'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}
+	 ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 18,  0, 18,  0, 18,  0, 18, 18, 18, 18, 18,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
+	{CCODE_MOROCCO,                 {'M' , 'A'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
+	{CCODE_NETHERLANDS,             {'N' , 'L'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0}
+	 ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20,  0, 20,  0, 20,  0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,  0,  0,  0}  },
+	{CCODE_NEW_ZEALAND,             {'N' , 'Z'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1}
+	 ,  {  30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 23,  0, 23,  0, 23,  0, 23, 23, 23, 23, 23,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 30, 30, 30, 30, 30}  },
+	{CCODE_NORTH_KOREA,             {'K' , 'P'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  0}
+	 ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  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,  0,  0,  0,  0,  0,  0, 23, 23, 23, 23,  0}  },
+	{CCODE_NORWAY,                  {'N' , 'O'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0}
+	 ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20,  0, 20,  0, 20,  0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,  0,  0,  0}  },
+	{CCODE_OMAN,                    {'O' , 'M'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
+	{CCODE_PAKISTAN,                {'P' , 'K'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
+	{CCODE_PANAMA,                  {'P' , 'A'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1}
+	 ,  {  27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 17,  0, 17,  0, 17,  0, 17, 23, 23, 23, 23,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 30, 30, 30, 30, 30}  },
+	{CCODE_PERU,                    {'P' , 'E'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
+	{CCODE_PHILIPPINES,             {'P' , 'H'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1}
+	 ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 17,  0, 17,  0, 17,  0, 17, 23, 23, 23, 23,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 30, 30, 30, 30, 30}  },
+	{CCODE_POLAND,                  {'P' , 'L'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0}
+	 ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20,  0, 20,  0, 20,  0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,  0,  0,  0}  },
+	{CCODE_PORTUGAL,                {'P' , 'T'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0}
+	 ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20,  0, 20,  0, 20,  0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,  0,  0,  0}  },
+	{CCODE_PUERTO_RICO,             {'P' , 'R'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1}
+	 ,  {  27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 17,  0, 17,  0, 17,  0, 17, 23, 23, 23, 23,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 30, 30, 30, 30, 30}  },
+	{CCODE_QATAR,                   {'Q' , 'A'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
+	{CCODE_ROMANIA,                 {'R' , 'O'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
+	{CCODE_RUSSIA,                  {'R' , 'U'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
+	{CCODE_SAUDI_ARABIA,            {'S' , 'A'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
+	{CCODE_SINGAPORE,               {'S' , 'G'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1}
+	 ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20,  0, 20,  0, 20,  0, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20, 20, 20, 20, 20}  },
+	{CCODE_SLOVAKIA,                {'S' , 'K'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  0}
+	 ,  {  23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 16,  0, 16,  0, 16,  0, 16, 16, 16, 16, 16,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 16, 16, 16, 16,  0}  },
+	{CCODE_SLOVENIA,                {'S' , 'I'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0}
+	 ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20,  0, 20,  0, 20,  0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,  0,  0,  0}  },
+	{CCODE_SOUTH_AFRICA,            {'Z' , 'A'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0}
+	 ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20,  0, 20,  0, 20,  0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,  0,  0,  0}  },
+	{CCODE_SOUTH_KOREA,             {'K' , 'R'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  0}
+	 ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  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,  0,  0,  0,  0,  0,  0, 23, 23, 23, 23,  0}  },
+	{CCODE_SPAIN,                   {'E' , 'S'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  0}
+	 ,  {  23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 16,  0, 16,  0, 16,  0, 16, 16, 16, 16, 16,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 16, 16, 16, 16,  0}  },
+	{CCODE_SWEDEN,                  {'S' , 'E'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0}
+	 ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20,  0, 20,  0, 20,  0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,  0,  0,  0}  },
+	{CCODE_SWITZERLAND,             {'C' , 'H'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}
+	 ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 18,  0, 18,  0, 18,  0, 18,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
+	{CCODE_SYRIA,                   {'S' , 'Y'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
+	{CCODE_TAIWAN,                  {'T' , 'W'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  0}
+	 ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 17, 17, 17,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 30, 30, 30, 30,  0}  },
+	{CCODE_THAILAND,                {'T' , 'H'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  0}
+	 ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  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,  0,  0,  0,  0,  0,  0, 23, 23, 23, 23,  0}  },
+	{CCODE_TRINIDAD_TOBAGO,         {'T' , 'T'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}
+	 ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 18,  0, 18,  0, 18,  0, 18, 18, 18, 18, 18,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
+	{CCODE_TUNISIA,                 {'T' , 'N'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}
+	 ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20,  0, 20,  0, 20,  0, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
+	{CCODE_TURKEY,                  {'T' , 'R'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}
+	 ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20,  0, 20,  0, 20,  0, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  },
+	{CCODE_UK,                      {'G' , 'B'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0}
+	 ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20,  0, 20,  0, 20,  0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,  0,  0,  0}  },
+	{CCODE_UKRAINE,                 {'U' , 'A'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
+	{CCODE_UNITED_ARAB_EMIRATES,    {'A' , 'E'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
+	{CCODE_UNITED_STATES,           {'U' , 'S'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1}
+	 ,  {  27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 17,  0, 17,  0, 17,  0, 17, 23, 23, 23, 23,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 30, 30, 30, 30, 30}  },
+	{CCODE_URUGUAY,                 {'U' , 'Y'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  0}
+	 ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  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,  0,  0,  0,  0,  0,  0, 23, 23, 23, 23,  0}  },
+	{CCODE_UZBEKISTAN,              {'U' , 'Z'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0,  0,  0}  },
+	{CCODE_VENEZUELA,               {'V' , 'E'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  0}
+	 ,  {  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  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,  0,  0,  0,  0,  0,  0, 23, 23, 23, 23,  0}  },
+	{CCODE_VIETNAM,                 {'V' , 'N'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
+	{CCODE_YEMEN,                   {'Y' , 'E'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
+	{CCODE_ZIMBABWE,                {'Z' , 'W'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  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,  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,  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,  0,  0,  0}  },
+	{CCODE_JAPAN_W52_W53,           {'J' , 'J'},  {   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,  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,  1,  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,  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,  0,  0,  0,  0,  0,  0,  0,  0}  },
+	{CCODE_MAX,                     {'U' , 'N'},  {   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1}
+	 ,  {   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,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}  }
 /*                                              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  44  45  46  47  48  49  50  51  52  53  54  55  56  */
 };
 
@@ -382,8 +382,7 @@ bool is_channel_valid(unsigned int ChannelIndex)
 	 * If Channel Index is invalid, return invalid
 	 */
 	if ((ChannelIndex > CB_MAX_CHANNEL) ||
-		(ChannelIndex == 0))
-	{
+	    (ChannelIndex == 0)) {
 		bValid = false;
 		goto exit;
 	}
@@ -391,8 +390,7 @@ bool is_channel_valid(unsigned int ChannelIndex)
 	bValid = sChannelTbl[ChannelIndex].bValid;
 
 exit:
-	return (bValid);
-
+	return bValid;
 }
 
 /**
@@ -410,11 +408,11 @@ exit:
 bool channel_get_list(unsigned int uCountryCodeIdx, unsigned char *pbyChannelTable)
 {
 	if (uCountryCodeIdx >= CCODE_MAX)
-		return (false);
+		return false;
 
 	memcpy(pbyChannelTable, ChannelRuleTab[uCountryCodeIdx].bChannelIdxList, CB_MAX_CHANNEL);
 
-	return (true);
+	return true;
 }
 
 void init_channel_table(void *pDeviceHandler)
@@ -423,75 +421,74 @@ void init_channel_table(void *pDeviceHandler)
 	bool bMultiBand = false;
 	unsigned int ii;
 
-	for(ii = 1 ; ii<=CARD_MAX_CHANNEL_TBL ; ii++) {
+	for (ii = 1; ii <= CARD_MAX_CHANNEL_TBL; ii++) {
 		sChannelTbl[ii].bValid = false;
 	}
 
 	switch (pDevice->byRFType) {
-		case RF_RFMD2959 :
-		case RF_AIROHA :
-		case RF_AL2230S:
-		case RF_UW2451 :
-		case RF_VT3226 :
-			//printk("chester-false\n");
-			bMultiBand = false;
-			break;
-		case RF_AIROHA7230 :
-		case RF_UW2452 :
-		case RF_NOTHING :
-		default :
-			bMultiBand = true;
-			break;
+	case RF_RFMD2959:
+	case RF_AIROHA:
+	case RF_AL2230S:
+	case RF_UW2451:
+	case RF_VT3226:
+		bMultiBand = false;
+		break;
+	case RF_AIROHA7230:
+	case RF_UW2452:
+	case RF_NOTHING:
+	default:
+		bMultiBand = true;
+		break;
 	}
 
 	if ((pDevice->dwDiagRefCount != 0) || (pDevice->b11hEnable == true)) {
 		if (bMultiBand == true) {
-			for(ii = 0 ; ii<CARD_MAX_CHANNEL_TBL ; ii++) {
-				sChannelTbl[ii+1].bValid = true;
-				pDevice->abyRegPwr[ii+1] = pDevice->abyOFDMDefaultPwr[ii+1];
-				pDevice->abyLocalPwr[ii+1] = pDevice->abyOFDMDefaultPwr[ii+1];
+			for (ii = 0; ii < CARD_MAX_CHANNEL_TBL; ii++) {
+				sChannelTbl[ii + 1].bValid = true;
+				pDevice->abyRegPwr[ii + 1] = pDevice->abyOFDMDefaultPwr[ii + 1];
+				pDevice->abyLocalPwr[ii + 1] = pDevice->abyOFDMDefaultPwr[ii + 1];
 			}
-			for(ii = 0 ; ii<CHANNEL_MAX_24G ; ii++) {
-				pDevice->abyRegPwr[ii+1] = pDevice->abyCCKDefaultPwr[ii+1];
-				pDevice->abyLocalPwr[ii+1] = pDevice->abyCCKDefaultPwr[ii+1];
+			for (ii = 0; ii < CHANNEL_MAX_24G; ii++) {
+				pDevice->abyRegPwr[ii + 1] = pDevice->abyCCKDefaultPwr[ii + 1];
+				pDevice->abyLocalPwr[ii + 1] = pDevice->abyCCKDefaultPwr[ii + 1];
 			}
 		} else {
-			for(ii = 0 ; ii<CHANNEL_MAX_24G ; ii++) {
+			for (ii = 0; ii < CHANNEL_MAX_24G; ii++) {
 				//2008-8-4 <add> by chester
 				if (ChannelRuleTab[pDevice->byZoneType].bChannelIdxList[ii] != 0) {
-					sChannelTbl[ii+1].bValid = true;
-					pDevice->abyRegPwr[ii+1] = pDevice->abyCCKDefaultPwr[ii+1];
-					pDevice->abyLocalPwr[ii+1] = pDevice->abyCCKDefaultPwr[ii+1];
+					sChannelTbl[ii + 1].bValid = true;
+					pDevice->abyRegPwr[ii + 1] = pDevice->abyCCKDefaultPwr[ii + 1];
+					pDevice->abyLocalPwr[ii + 1] = pDevice->abyCCKDefaultPwr[ii + 1];
 				}
 			}
 		}
 	} else if (pDevice->byZoneType <= CCODE_MAX) {
 		if (bMultiBand == true) {
-			for(ii = 0 ; ii<CARD_MAX_CHANNEL_TBL ; ii++) {
+			for (ii = 0; ii < CARD_MAX_CHANNEL_TBL; ii++) {
 				if (ChannelRuleTab[pDevice->byZoneType].bChannelIdxList[ii] != 0) {
-					sChannelTbl[ii+1].bValid = true;
-					pDevice->abyRegPwr[ii+1] = ChannelRuleTab[pDevice->byZoneType].byPower[ii];
-					pDevice->abyLocalPwr[ii+1] = ChannelRuleTab[pDevice->byZoneType].byPower[ii];
+					sChannelTbl[ii + 1].bValid = true;
+					pDevice->abyRegPwr[ii + 1] = ChannelRuleTab[pDevice->byZoneType].byPower[ii];
+					pDevice->abyLocalPwr[ii + 1] = ChannelRuleTab[pDevice->byZoneType].byPower[ii];
 				}
 			}
 		} else {
-			for(ii = 0 ; ii<CHANNEL_MAX_24G ; ii++) {
+			for (ii = 0; ii < CHANNEL_MAX_24G; ii++) {
 				if (ChannelRuleTab[pDevice->byZoneType].bChannelIdxList[ii] != 0) {
-					sChannelTbl[ii+1].bValid = true;
-					pDevice->abyRegPwr[ii+1] = ChannelRuleTab[pDevice->byZoneType].byPower[ii];
-					pDevice->abyLocalPwr[ii+1] = ChannelRuleTab[pDevice->byZoneType].byPower[ii];
+					sChannelTbl[ii + 1].bValid = true;
+					pDevice->abyRegPwr[ii + 1] = ChannelRuleTab[pDevice->byZoneType].byPower[ii];
+					pDevice->abyLocalPwr[ii + 1] = ChannelRuleTab[pDevice->byZoneType].byPower[ii];
 				}
 			}
 		}
 	}
 
-	DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO"Zone=[%d][%c][%c]!!\n",pDevice->byZoneType,ChannelRuleTab[pDevice->byZoneType].chCountryCode[0],ChannelRuleTab[pDevice->byZoneType].chCountryCode[1]);
+	DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Zone=[%d][%c][%c]!!\n", pDevice->byZoneType, ChannelRuleTab[pDevice->byZoneType].chCountryCode[0], ChannelRuleTab[pDevice->byZoneType].chCountryCode[1]);
 
-	for(ii = 0 ; ii<CARD_MAX_CHANNEL_TBL ; ii++) {
-		if (pDevice->abyRegPwr[ii+1] == 0)
-			pDevice->abyRegPwr[ii+1] = pDevice->abyOFDMDefaultPwr[ii+1];
-		if (pDevice->abyLocalPwr[ii+1] == 0)
-			pDevice->abyLocalPwr[ii+1] = pDevice->abyOFDMDefaultPwr[ii+1];
+	for (ii = 0; ii < CARD_MAX_CHANNEL_TBL; ii++) {
+		if (pDevice->abyRegPwr[ii + 1] == 0)
+			pDevice->abyRegPwr[ii + 1] = pDevice->abyOFDMDefaultPwr[ii + 1];
+		if (pDevice->abyLocalPwr[ii + 1] == 0)
+			pDevice->abyLocalPwr[ii + 1] = pDevice->abyOFDMDefaultPwr[ii + 1];
 	}
 }
 
@@ -500,11 +497,11 @@ unsigned char get_channel_mapping(void *pDeviceHandler, unsigned char byChannelN
 	unsigned int ii;
 
 	if ((ePhyType == PHY_TYPE_11B) || (ePhyType == PHY_TYPE_11G))
-		return (byChannelNumber);
+		return byChannelNumber;
 
-	for(ii = (CB_MAX_CHANNEL_24G + 1); ii <= CB_MAX_CHANNEL; ) {
+	for (ii = (CB_MAX_CHANNEL_24G + 1); ii <= CB_MAX_CHANNEL;) {
 		if (sChannelTbl[ii].byChannelNumber == byChannelNumber)
-			return ((unsigned char) ii);
+			return (unsigned char) ii;
 		ii++;
 	}
 	return 0;
@@ -513,7 +510,7 @@ unsigned char get_channel_mapping(void *pDeviceHandler, unsigned char byChannelN
 unsigned char get_channel_number(void *pDeviceHandler, unsigned char byChannelIndex)
 {
 	//PSDevice    pDevice = (PSDevice) pDeviceHandler;
-	return(sChannelTbl[byChannelIndex].byChannelNumber);
+	return sChannelTbl[byChannelIndex].byChannelNumber;
 }
 
 /**
@@ -525,25 +522,24 @@ unsigned char get_channel_number(void *pDeviceHandler, unsigned char byChannelIn
  * Return Value: true if succeeded; false if failed.
  *
  */
-bool set_channel (void *pDeviceHandler, unsigned int uConnectionChannel)
+bool set_channel(void *pDeviceHandler, unsigned int uConnectionChannel)
 {
 	PSDevice pDevice = (PSDevice) pDeviceHandler;
 	bool bResult = true;
 
-
 	if (pDevice->byCurrentCh == uConnectionChannel) {
 		return bResult;
 	}
 
 	if (sChannelTbl[uConnectionChannel].bValid == false) {
-		return (false);
+		return false;
 	}
 
 	if ((uConnectionChannel > CB_MAX_CHANNEL_24G) &&
-			(pDevice->eCurrentPHYType != PHY_TYPE_11A)) {
+	    (pDevice->eCurrentPHYType != PHY_TYPE_11A)) {
 		CARDbSetPhyParameter(pDevice, PHY_TYPE_11A, 0, 0, NULL, NULL);
 	} else if ((uConnectionChannel <= CB_MAX_CHANNEL_24G) &&
-			(pDevice->eCurrentPHYType == PHY_TYPE_11A)) {
+		   (pDevice->eCurrentPHYType == PHY_TYPE_11A)) {
 		CARDbSetPhyParameter(pDevice, PHY_TYPE_11G, 0, 0, NULL, NULL);
 	}
 	// clear NAV
@@ -552,13 +548,11 @@ bool set_channel (void *pDeviceHandler, unsigned int uConnectionChannel)
 	//{{ RobertYu: 20041202
 	//// TX_PE will reserve 3 us for MAX2829 A mode only, it is for better TX throughput
 
-	if ( pDevice->byRFType == RF_AIROHA7230 )
-	{
+	if (pDevice->byRFType == RF_AIROHA7230) {
 		RFbAL7230SelectChannelPostProcess(pDevice->PortOffset, pDevice->byCurrentCh, (unsigned char)uConnectionChannel);
 	}
 	//}} RobertYu
 
-
 	pDevice->byCurrentCh = (unsigned char)uConnectionChannel;
 	bResult &= RFbSelectChannel(pDevice->PortOffset, pDevice->byRFType, (unsigned char)uConnectionChannel);
 
@@ -566,8 +560,7 @@ bool set_channel (void *pDeviceHandler, unsigned int uConnectionChannel)
 	if (pDevice->bEnablePSMode == true)
 		RFvWriteWakeProgSyn(pDevice->PortOffset, pDevice->byRFType, uConnectionChannel);
 
-
-	//DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"CARDbSetMediaChannel: %d\n", (unsigned char)uConnectionChannel);
+	//DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "CARDbSetMediaChannel: %d\n", (unsigned char)uConnectionChannel);
 	BBvSoftwareReset(pDevice->PortOffset);
 
 	if (pDevice->byLocalID > REV_ID_VT3253_B1) {
@@ -581,18 +574,12 @@ bool set_channel (void *pDeviceHandler, unsigned int uConnectionChannel)
 	}
 
 	if (pDevice->eCurrentPHYType == PHY_TYPE_11B) {
-#ifdef	PLICE_DEBUG
-		//printk("Func:ChbSetChannel:call RFbSetPower:11B\n");
-#endif
 		RFbSetPower(pDevice, RATE_1M, pDevice->byCurrentCh);
 	} else {
-#ifdef	PLICE_DEBUG
-		//printk("Func:ChbSetChannel:call RFbSetPower\n");
-#endif
 		RFbSetPower(pDevice, RATE_6M, pDevice->byCurrentCh);
 	}
 
-	return(bResult);
+	return bResult;
 }
 
 /**
@@ -612,19 +599,18 @@ void set_country_info(void *pDeviceHandler, CARD_PHY_TYPE ePHYType, void *pIE)
 	unsigned char byCh = 0;
 	PWLAN_IE_COUNTRY pIE_Country = (PWLAN_IE_COUNTRY) pIE;
 
-
 	uNumOfCountryInfo = (pIE_Country->len - 3);
 	uNumOfCountryInfo /= 3;
 
 	if (ePHYType == PHY_TYPE_11A) {
 		pDevice->bCountryInfo5G = true;
-		for(ii = CB_MAX_CHANNEL_24G + 1 ; ii <= CARD_MAX_CHANNEL_TBL ; ii++) {
+		for (ii = CB_MAX_CHANNEL_24G + 1; ii <= CARD_MAX_CHANNEL_TBL; ii++) {
 			sChannelTbl[ii].bValid = false;
 		}
 		step = 4;
 	} else {
 		pDevice->bCountryInfo24G = true;
-		for(ii = 1 ; ii <= CB_MAX_CHANNEL_24G ; ii++) {
+		for (ii = 1; ii <= CB_MAX_CHANNEL_24G; ii++) {
 			sChannelTbl[ii].bValid = false;
 		}
 		step = 1;
@@ -633,8 +619,8 @@ void set_country_info(void *pDeviceHandler, CARD_PHY_TYPE ePHYType, void *pIE)
 	pDevice->abyCountryCode[1] = pIE_Country->abyCountryString[1];
 	pDevice->abyCountryCode[2] = pIE_Country->abyCountryString[2];
 
-	for(ii = 0 ; ii < uNumOfCountryInfo ; ii++) {
-		for(uu = 0 ; uu < pIE_Country->abyCountryInfo[ii*3+1] ; uu++) {
+	for (ii = 0; ii < uNumOfCountryInfo; ii++) {
+		for (uu = 0; uu < pIE_Country->abyCountryInfo[ii*3+1]; uu++) {
 			byCh = get_channel_mapping(pDevice, (unsigned char)(pIE_Country->abyCountryInfo[ii*3]+step*uu), ePHYType);
 			sChannelTbl[byCh].bValid = true;
 			pDevice->abyRegPwr[byCh] = pIE_Country->abyCountryInfo[ii*3+2];
@@ -661,7 +647,6 @@ unsigned char set_support_channels(void *pDeviceHandler, unsigned char *pbyIEs)
 	unsigned char *pbyChTupple;
 	unsigned char byLen = 0;
 
-
 	pIE->byElementID = WLAN_EID_SUPP_CH;
 	pIE->len = 0;
 	pbyChTupple = pIE->abyChannelTuple;
@@ -669,7 +654,7 @@ unsigned char set_support_channels(void *pDeviceHandler, unsigned char *pbyIEs)
 	// lower band
 	byCount = 0;
 	if (ChannelRuleTab[pDevice->byZoneType].bChannelIdxList[28] == true) {
-		for (ii = 28 ; ii < 36 ; ii+= 2) {
+		for (ii = 28; ii < 36; ii += 2) {
 			if (ChannelRuleTab[pDevice->byZoneType].bChannelIdxList[ii] == true) {
 				byCount++;
 			}
@@ -678,7 +663,7 @@ unsigned char set_support_channels(void *pDeviceHandler, unsigned char *pbyIEs)
 		*pbyChTupple++ = byCount;
 		byLen += 2;
 	} else if (ChannelRuleTab[pDevice->byZoneType].bChannelIdxList[29] == true) {
-		for (ii = 29 ; ii < 36 ; ii+= 2) {
+		for (ii = 29; ii < 36; ii += 2) {
 			if (ChannelRuleTab[pDevice->byZoneType].bChannelIdxList[ii] == true) {
 				byCount++;
 			}
@@ -690,7 +675,7 @@ unsigned char set_support_channels(void *pDeviceHandler, unsigned char *pbyIEs)
 	// middle band
 	byCount = 0;
 	if (ChannelRuleTab[pDevice->byZoneType].bChannelIdxList[36] == true) {
-		for (ii = 36 ; ii < 40 ; ii++) {
+		for (ii = 36; ii < 40; ii++) {
 			if (ChannelRuleTab[pDevice->byZoneType].bChannelIdxList[ii] == true) {
 				byCount++;
 			}
@@ -702,7 +687,7 @@ unsigned char set_support_channels(void *pDeviceHandler, unsigned char *pbyIEs)
 	// higher band
 	byCount = 0;
 	if (ChannelRuleTab[pDevice->byZoneType].bChannelIdxList[40] == true) {
-		for (ii = 40 ; ii < 51 ; ii++) {
+		for (ii = 40; ii < 51; ii++) {
 			if (ChannelRuleTab[pDevice->byZoneType].bChannelIdxList[ii] == true) {
 				byCount++;
 			}
@@ -711,7 +696,7 @@ unsigned char set_support_channels(void *pDeviceHandler, unsigned char *pbyIEs)
 		*pbyChTupple++ = byCount;
 		byLen += 2;
 	} else if (ChannelRuleTab[pDevice->byZoneType].bChannelIdxList[51] == true) {
-		for (ii = 51 ; ii < 56 ; ii++) {
+		for (ii = 51; ii < 56; ii++) {
 			if (ChannelRuleTab[pDevice->byZoneType].bChannelIdxList[ii] == true) {
 				byCount++;
 			}
@@ -721,7 +706,7 @@ unsigned char set_support_channels(void *pDeviceHandler, unsigned char *pbyIEs)
 		byLen += 2;
 	}
 	pIE->len += (byLen - 2);
-	return (byLen);
+	return byLen;
 }
 
 void set_country_IE(void *pDeviceHandler, void *pIE)
@@ -735,9 +720,9 @@ void set_country_IE(void *pDeviceHandler, void *pIE)
 	pIECountry->abyCountryString[0] = ChannelRuleTab[pDevice->byZoneType].chCountryCode[0];
 	pIECountry->abyCountryString[1] = ChannelRuleTab[pDevice->byZoneType].chCountryCode[1];
 	pIECountry->abyCountryString[2] = ' ';
-	for (ii = CB_MAX_CHANNEL_24G; ii < CB_MAX_CHANNEL; ii++ ) {
+	for (ii = CB_MAX_CHANNEL_24G; ii < CB_MAX_CHANNEL; ii++) {
 		if (ChannelRuleTab[pDevice->byZoneType].bChannelIdxList[ii] != 0) {
-			pIECountry->abyCountryInfo[pIECountry->len++] = sChannelTbl[ii+1].byChannelNumber;
+			pIECountry->abyCountryInfo[pIECountry->len++] = sChannelTbl[ii + 1].byChannelNumber;
 			pIECountry->abyCountryInfo[pIECountry->len++] = 1;
 			pIECountry->abyCountryInfo[pIECountry->len++] = ChannelRuleTab[pDevice->byZoneType].byPower[ii];
 		}
@@ -746,9 +731,8 @@ void set_country_IE(void *pDeviceHandler, void *pIE)
 }
 
 bool get_channel_map_info(void *pDeviceHandler, unsigned int uChannelIndex,
-		unsigned char *pbyChannelNumber, unsigned char *pbyMap)
+			  unsigned char *pbyChannelNumber, unsigned char *pbyMap)
 {
-
 	if (uChannelIndex > CB_MAX_CHANNEL)
 		return false;
 
@@ -758,9 +742,8 @@ bool get_channel_map_info(void *pDeviceHandler, unsigned int uChannelIndex,
 }
 
 void set_channel_map_info(void *pDeviceHandler, unsigned int uChannelIndex,
-		unsigned char byMap)
+			  unsigned char byMap)
 {
-
 	if (uChannelIndex > CB_MAX_CHANNEL)
 		return;
 
@@ -779,40 +762,40 @@ unsigned char auto_channel_select(void *pDeviceHandler, CARD_PHY_TYPE ePHYType)
 {
 	unsigned int ii = 0;
 	unsigned char byOptionChannel = 0;
-	int aiWeight[CB_MAX_CHANNEL_24G+1] = {-1000,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+	int aiWeight[CB_MAX_CHANNEL_24G + 1] = {-1000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
 
 	if (ePHYType == PHY_TYPE_11A) {
-		for(ii = CB_MAX_CHANNEL_24G + 1 ; ii <= CB_MAX_CHANNEL ; ii++) {
+		for (ii = CB_MAX_CHANNEL_24G + 1; ii <= CB_MAX_CHANNEL; ii++) {
 			if (sChannelTbl[ii].bValid == true) {
 				if (byOptionChannel == 0) {
 					byOptionChannel = (unsigned char) ii;
 				}
 				if (sChannelTbl[ii].byMAP == 0) {
-					return ((unsigned char) ii);
-				} else if ( !(sChannelTbl[ii].byMAP & 0x08)) {
+					return (unsigned char) ii;
+				} else if (!(sChannelTbl[ii].byMAP & 0x08)) {
 					byOptionChannel = (unsigned char) ii;
 				}
 			}
 		}
 	} else {
 		byOptionChannel = 0;
-		for(ii = 1 ; ii <= CB_MAX_CHANNEL_24G ; ii++) {
+		for (ii = 1; ii <= CB_MAX_CHANNEL_24G; ii++) {
 			if (sChannelTbl[ii].bValid == true) {
 				if (sChannelTbl[ii].byMAP == 0) {
 					aiWeight[ii] += 100;
 				} else if (sChannelTbl[ii].byMAP & 0x01) {
 					if (ii > 3) {
-						aiWeight[ii-3] -= 10;
+						aiWeight[ii - 3] -= 10;
 					}
 					if (ii > 2) {
-						aiWeight[ii-2] -= 20;
+						aiWeight[ii - 2] -= 20;
 					}
 					if (ii > 1) {
-						aiWeight[ii-1] -= 40;
+						aiWeight[ii - 1] -= 40;
 					}
 					aiWeight[ii] -= 80;
 					if (ii < CB_MAX_CHANNEL_24G) {
-						aiWeight[ii+1] -= 40;
+						aiWeight[ii + 1] -= 40;
 					}
 					if (ii < (CB_MAX_CHANNEL_24G - 1)) {
 						aiWeight[ii+2] -= 20;
@@ -823,12 +806,12 @@ unsigned char auto_channel_select(void *pDeviceHandler, CARD_PHY_TYPE ePHYType)
 				}
 			}
 		}
-		for(ii = 1 ; ii <= CB_MAX_CHANNEL_24G ; ii++) {
+		for (ii = 1; ii <= CB_MAX_CHANNEL_24G; ii++) {
 			if ((sChannelTbl[ii].bValid == true) &&
-					(aiWeight[ii] > aiWeight[byOptionChannel])) {
+			    (aiWeight[ii] > aiWeight[byOptionChannel])) {
 				byOptionChannel = (unsigned char) ii;
 			}
 		}
 	}
-	return (byOptionChannel);
+	return byOptionChannel;
 }
diff --git a/drivers/staging/vt6655/channel.h b/drivers/staging/vt6655/channel.h
index 7038f0d..c9931d7 100644
--- a/drivers/staging/vt6655/channel.h
+++ b/drivers/staging/vt6655/channel.h
@@ -29,12 +29,11 @@
 /*---------------------  Export Classes  ----------------------------*/
 
 typedef struct tagSChannelTblElement {
-    unsigned char byChannelNumber;
-    unsigned int uFrequency;
-    bool bValid;
-    unsigned char byMAP;
-}SChannelTblElement, *PSChannelTblElement;
-
+	unsigned char byChannelNumber;
+	unsigned int uFrequency;
+	bool bValid;
+	unsigned char byMAP;
+} SChannelTblElement, *PSChannelTblElement;
 
 /*---------------------  Export Functions  --------------------------*/
 
@@ -48,11 +47,10 @@ void set_country_info(void *pDeviceHandler, CARD_PHY_TYPE ePHYType, void *pIE);
 unsigned char set_support_channels(void *pDeviceHandler, unsigned char *pbyIEs);
 void set_country_IE(void *pDeviceHandler, void *pIE);
 bool get_channel_map_info(void *pDeviceHandler, unsigned int uChannelIndex,
-		unsigned char *pbyChannelNumber, unsigned char *pbyMap);
+			  unsigned char *pbyChannelNumber, unsigned char *pbyMap);
 void set_channel_map_info(void *pDeviceHandler, unsigned int uChannelIndex,
-		unsigned char byMap);
+			  unsigned char byMap);
 void clear_channel_map_info(void *pDeviceHandler);
 unsigned char auto_channel_select(void *pDeviceHandler, CARD_PHY_TYPE ePHYType);
 
-
 #endif /* _CHANNEL_H_ */
diff --git a/drivers/staging/vt6655/country.h b/drivers/staging/vt6655/country.h
index 05fda41..415e767 100644
--- a/drivers/staging/vt6655/country.h
+++ b/drivers/staging/vt6655/country.h
@@ -38,125 +38,125 @@
  * Please check with VNWL.inf/VNWL64.inf/VNWL*.inf
  ************************************************************************/
 typedef enum _COUNTRY_CODE {
-    CCODE_FCC = 0,
-    CCODE_TELEC,
-    CCODE_ETSI,
-    CCODE_RESV3,
-    CCODE_RESV4,
-    CCODE_RESV5,
-    CCODE_RESV6,
-    CCODE_RESV7,
-    CCODE_RESV8,
-    CCODE_RESV9,
-    CCODE_RESVa,
-    CCODE_RESVb,
-    CCODE_RESVc,
-    CCODE_RESVd,
-    CCODE_RESVe,
-    CCODE_ALLBAND,
-    CCODE_ALBANIA,
-    CCODE_ALGERIA,
-    CCODE_ARGENTINA,
-    CCODE_ARMENIA,
-    CCODE_AUSTRALIA,
-    CCODE_AUSTRIA,
-    CCODE_AZERBAIJAN,
-    CCODE_BAHRAIN,
-    CCODE_BELARUS,
-    CCODE_BELGIUM,
-    CCODE_BELIZE,
-    CCODE_BOLIVIA,
-    CCODE_BRAZIL,
-    CCODE_BRUNEI_DARUSSALAM,
-    CCODE_BULGARIA,
-    CCODE_CANADA,
-    CCODE_CHILE,
-    CCODE_CHINA,
-    CCODE_COLOMBIA,
-    CCODE_COSTA_RICA,
-    CCODE_CROATIA,
-    CCODE_CYPRUS,
-    CCODE_CZECH,
-    CCODE_DENMARK,
-    CCODE_DOMINICAN_REPUBLIC,
-    CCODE_ECUADOR,
-    CCODE_EGYPT,
-    CCODE_EL_SALVADOR,
-    CCODE_ESTONIA,
-    CCODE_FINLAND,
-    CCODE_FRANCE,
-    CCODE_GERMANY,
-    CCODE_GREECE,
-    CCODE_GEORGIA,
-    CCODE_GUATEMALA,
-    CCODE_HONDURAS,
-    CCODE_HONG_KONG,
-    CCODE_HUNGARY,
-    CCODE_ICELAND,
-    CCODE_INDIA,
-    CCODE_INDONESIA,
-    CCODE_IRAN,
-    CCODE_IRELAND,
-    CCODE_ITALY,
-    CCODE_ISRAEL,
-    CCODE_JAPAN,
-    CCODE_JORDAN,
-    CCODE_KAZAKHSTAN,
-    CCODE_KUWAIT,
-    CCODE_LATVIA,
-    CCODE_LEBANON,
-    CCODE_LEICHTENSTEIN,
-    CCODE_LITHUANIA,
-    CCODE_LUXEMBURG,
-    CCODE_MACAU,
-    CCODE_MACEDONIA,
-    CCODE_MALTA,
-    CCODE_MALAYSIA,
-    CCODE_MEXICO,
-    CCODE_MONACO,
-    CCODE_MOROCCO,
-    CCODE_NETHERLANDS,
-    CCODE_NEW_ZEALAND,
-    CCODE_NORTH_KOREA,
-    CCODE_NORWAY,
-    CCODE_OMAN,
-    CCODE_PAKISTAN,
-    CCODE_PANAMA,
-    CCODE_PERU,
-    CCODE_PHILIPPINES,
-    CCODE_POLAND,
-    CCODE_PORTUGAL,
-    CCODE_PUERTO_RICO,
-    CCODE_QATAR,
-    CCODE_ROMANIA,
-    CCODE_RUSSIA,
-    CCODE_SAUDI_ARABIA,
-    CCODE_SINGAPORE,
-    CCODE_SLOVAKIA,
-    CCODE_SLOVENIA,
-    CCODE_SOUTH_AFRICA,
-    CCODE_SOUTH_KOREA,
-    CCODE_SPAIN,
-    CCODE_SWEDEN,
-    CCODE_SWITZERLAND,
-    CCODE_SYRIA,
-    CCODE_TAIWAN,
-    CCODE_THAILAND,
-    CCODE_TRINIDAD_TOBAGO,
-    CCODE_TUNISIA,
-    CCODE_TURKEY,
-    CCODE_UK,
-    CCODE_UKRAINE,
-    CCODE_UNITED_ARAB_EMIRATES,
-    CCODE_UNITED_STATES,
-    CCODE_URUGUAY,
-    CCODE_UZBEKISTAN,
-    CCODE_VENEZUELA,
-    CCODE_VIETNAM,
-    CCODE_YEMEN,
-    CCODE_ZIMBABWE,
-    CCODE_JAPAN_W52_W53,
-    CCODE_MAX
+	CCODE_FCC = 0,
+	CCODE_TELEC,
+	CCODE_ETSI,
+	CCODE_RESV3,
+	CCODE_RESV4,
+	CCODE_RESV5,
+	CCODE_RESV6,
+	CCODE_RESV7,
+	CCODE_RESV8,
+	CCODE_RESV9,
+	CCODE_RESVa,
+	CCODE_RESVb,
+	CCODE_RESVc,
+	CCODE_RESVd,
+	CCODE_RESVe,
+	CCODE_ALLBAND,
+	CCODE_ALBANIA,
+	CCODE_ALGERIA,
+	CCODE_ARGENTINA,
+	CCODE_ARMENIA,
+	CCODE_AUSTRALIA,
+	CCODE_AUSTRIA,
+	CCODE_AZERBAIJAN,
+	CCODE_BAHRAIN,
+	CCODE_BELARUS,
+	CCODE_BELGIUM,
+	CCODE_BELIZE,
+	CCODE_BOLIVIA,
+	CCODE_BRAZIL,
+	CCODE_BRUNEI_DARUSSALAM,
+	CCODE_BULGARIA,
+	CCODE_CANADA,
+	CCODE_CHILE,
+	CCODE_CHINA,
+	CCODE_COLOMBIA,
+	CCODE_COSTA_RICA,
+	CCODE_CROATIA,
+	CCODE_CYPRUS,
+	CCODE_CZECH,
+	CCODE_DENMARK,
+	CCODE_DOMINICAN_REPUBLIC,
+	CCODE_ECUADOR,
+	CCODE_EGYPT,
+	CCODE_EL_SALVADOR,
+	CCODE_ESTONIA,
+	CCODE_FINLAND,
+	CCODE_FRANCE,
+	CCODE_GERMANY,
+	CCODE_GREECE,
+	CCODE_GEORGIA,
+	CCODE_GUATEMALA,
+	CCODE_HONDURAS,
+	CCODE_HONG_KONG,
+	CCODE_HUNGARY,
+	CCODE_ICELAND,
+	CCODE_INDIA,
+	CCODE_INDONESIA,
+	CCODE_IRAN,
+	CCODE_IRELAND,
+	CCODE_ITALY,
+	CCODE_ISRAEL,
+	CCODE_JAPAN,
+	CCODE_JORDAN,
+	CCODE_KAZAKHSTAN,
+	CCODE_KUWAIT,
+	CCODE_LATVIA,
+	CCODE_LEBANON,
+	CCODE_LEICHTENSTEIN,
+	CCODE_LITHUANIA,
+	CCODE_LUXEMBURG,
+	CCODE_MACAU,
+	CCODE_MACEDONIA,
+	CCODE_MALTA,
+	CCODE_MALAYSIA,
+	CCODE_MEXICO,
+	CCODE_MONACO,
+	CCODE_MOROCCO,
+	CCODE_NETHERLANDS,
+	CCODE_NEW_ZEALAND,
+	CCODE_NORTH_KOREA,
+	CCODE_NORWAY,
+	CCODE_OMAN,
+	CCODE_PAKISTAN,
+	CCODE_PANAMA,
+	CCODE_PERU,
+	CCODE_PHILIPPINES,
+	CCODE_POLAND,
+	CCODE_PORTUGAL,
+	CCODE_PUERTO_RICO,
+	CCODE_QATAR,
+	CCODE_ROMANIA,
+	CCODE_RUSSIA,
+	CCODE_SAUDI_ARABIA,
+	CCODE_SINGAPORE,
+	CCODE_SLOVAKIA,
+	CCODE_SLOVENIA,
+	CCODE_SOUTH_AFRICA,
+	CCODE_SOUTH_KOREA,
+	CCODE_SPAIN,
+	CCODE_SWEDEN,
+	CCODE_SWITZERLAND,
+	CCODE_SYRIA,
+	CCODE_TAIWAN,
+	CCODE_THAILAND,
+	CCODE_TRINIDAD_TOBAGO,
+	CCODE_TUNISIA,
+	CCODE_TURKEY,
+	CCODE_UK,
+	CCODE_UKRAINE,
+	CCODE_UNITED_ARAB_EMIRATES,
+	CCODE_UNITED_STATES,
+	CCODE_URUGUAY,
+	CCODE_UZBEKISTAN,
+	CCODE_VENEZUELA,
+	CCODE_VIETNAM,
+	CCODE_YEMEN,
+	CCODE_ZIMBABWE,
+	CCODE_JAPAN_W52_W53,
+	CCODE_MAX
 } COUNTRY_CODE;
 
 #endif  /* __COUNTRY_H__ */
diff --git a/drivers/staging/vt6655/datarate.c b/drivers/staging/vt6655/datarate.c
index b86ec1b..e7b6bc7 100644
--- a/drivers/staging/vt6655/datarate.c
+++ b/drivers/staging/vt6655/datarate.c
@@ -45,16 +45,12 @@
 
 /*---------------------  Static Definitions -------------------------*/
 
-
-
-
 /*---------------------  Static Classes  ----------------------------*/
 
-
- extern unsigned short TxRate_iwconfig; //2008-5-8 <add> by chester
+extern unsigned short TxRate_iwconfig; //2008-5-8 <add> by chester
 /*---------------------  Static Variables  --------------------------*/
 //static int          msglevel                =MSG_LEVEL_DEBUG;
-static int          msglevel                =MSG_LEVEL_INFO;
+static int msglevel = MSG_LEVEL_INFO;
 const unsigned char acbyIERate[MAX_RATE] =
 {0x02, 0x04, 0x0B, 0x16, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6C};
 
@@ -64,32 +60,28 @@ const unsigned char acbyIERate[MAX_RATE] =
 
 /*---------------------  Static Functions  --------------------------*/
 
-void s_vResetCounter (
-    PKnownNodeDB psNodeDBTable
-    );
-
-
+void s_vResetCounter(
+	PKnownNodeDB psNodeDBTable
+);
 
 void
-s_vResetCounter (
-    PKnownNodeDB psNodeDBTable
-    )
+s_vResetCounter(
+	PKnownNodeDB psNodeDBTable
+)
 {
-    unsigned char ii;
+	unsigned char ii;
 
-    // clear statistic counter for auto_rate
-    for(ii=0;ii<=MAX_RATE;ii++) {
-        psNodeDBTable->uTxOk[ii] = 0;
-        psNodeDBTable->uTxFail[ii] = 0;
-    }
+	// clear statistic counter for auto_rate
+	for (ii = 0; ii <= MAX_RATE; ii++) {
+		psNodeDBTable->uTxOk[ii] = 0;
+		psNodeDBTable->uTxFail[ii] = 0;
+	}
 }
 
 /*---------------------  Export Variables  --------------------------*/
 
-
 /*---------------------  Export Functions  --------------------------*/
 
-
 /*+
  *
  * Description:
@@ -103,26 +95,24 @@ s_vResetCounter (
  *
  * Return Value: RateIdx
  *
--*/
+ -*/
 unsigned char
-DATARATEbyGetRateIdx (
-    unsigned char byRate
-    )
+DATARATEbyGetRateIdx(
+	unsigned char byRate
+)
 {
-    unsigned char ii;
+	unsigned char ii;
 
-    //Erase basicRate flag.
-    byRate = byRate & 0x7F;//0111 1111
+	//Erase basicRate flag.
+	byRate = byRate & 0x7F;//0111 1111
 
-    for (ii = 0; ii < MAX_RATE; ii ++) {
-        if (acbyIERate[ii] == byRate)
-            return ii;
-    }
-    return 0;
+	for (ii = 0; ii < MAX_RATE; ii++) {
+		if (acbyIERate[ii] == byRate)
+			return ii;
+	}
+	return 0;
 }
 
-
-
 /*+
  *
  * Routine Description:
@@ -137,13 +127,10 @@ DATARATEbyGetRateIdx (
  *
  * Return Value: none
  *
--*/
+ -*/
 #define AUTORATE_TXCNT_THRESHOLD        20
 #define AUTORATE_INC_THRESHOLD          30
 
-
-
-
 /*+
  *
  * Description:
@@ -157,22 +144,22 @@ DATARATEbyGetRateIdx (
  *
  * Return Value: RateIdx
  *
--*/
+ -*/
 unsigned short
 wGetRateIdx(
-    unsigned char byRate
-    )
+	unsigned char byRate
+)
 {
-    unsigned short ii;
+	unsigned short ii;
 
-    //Erase basicRate flag.
-    byRate = byRate & 0x7F;//0111 1111
+	//Erase basicRate flag.
+	byRate = byRate & 0x7F;//0111 1111
 
-    for (ii = 0; ii < MAX_RATE; ii ++) {
-        if (acbyIERate[ii] == byRate)
-            return ii;
-    }
-    return 0;
+	for (ii = 0; ii < MAX_RATE; ii++) {
+		if (acbyIERate[ii] == byRate)
+			return ii;
+	}
+	return 0;
 }
 
 /*+
@@ -193,102 +180,99 @@ wGetRateIdx(
  *
  * Return Value: none
  *
--*/
+ -*/
 void
-RATEvParseMaxRate (
-    void *pDeviceHandler,
-    PWLAN_IE_SUPP_RATES pItemRates,
-    PWLAN_IE_SUPP_RATES pItemExtRates,
-    bool bUpdateBasicRate,
-    unsigned short *pwMaxBasicRate,
-    unsigned short *pwMaxSuppRate,
-    unsigned short *pwSuppRate,
-    unsigned char *pbyTopCCKRate,
-    unsigned char *pbyTopOFDMRate
-    )
+RATEvParseMaxRate(
+	void *pDeviceHandler,
+	PWLAN_IE_SUPP_RATES pItemRates,
+	PWLAN_IE_SUPP_RATES pItemExtRates,
+	bool bUpdateBasicRate,
+	unsigned short *pwMaxBasicRate,
+	unsigned short *pwMaxSuppRate,
+	unsigned short *pwSuppRate,
+	unsigned char *pbyTopCCKRate,
+	unsigned char *pbyTopOFDMRate
+)
 {
-PSDevice  pDevice = (PSDevice) pDeviceHandler;
-unsigned int ii;
-unsigned char byHighSuppRate = 0;
-unsigned char byRate = 0;
-unsigned short wOldBasicRate = pDevice->wBasicRate;
-unsigned int uRateLen;
-
-
-    if (pItemRates == NULL)
-        return;
-
-    *pwSuppRate = 0;
-    uRateLen = pItemRates->len;
-
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ParseMaxRate Len: %d\n", uRateLen);
-    if (pDevice->eCurrentPHYType != PHY_TYPE_11B) {
-        if (uRateLen > WLAN_RATES_MAXLEN)
-            uRateLen = WLAN_RATES_MAXLEN;
-    } else {
-        if (uRateLen > WLAN_RATES_MAXLEN_11B)
-            uRateLen = WLAN_RATES_MAXLEN_11B;
-    }
-
-    for (ii = 0; ii < uRateLen; ii++) {
-    	byRate = (unsigned char)(pItemRates->abyRates[ii]);
-        if (WLAN_MGMT_IS_BASICRATE(byRate) &&
-            (bUpdateBasicRate == true))  {
-            // Add to basic rate set, update pDevice->byTopCCKBasicRate and pDevice->byTopOFDMBasicRate
-            CARDbAddBasicRate((void *)pDevice, wGetRateIdx(byRate));
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ParseMaxRate AddBasicRate: %d\n", wGetRateIdx(byRate));
-        }
-        byRate = (unsigned char)(pItemRates->abyRates[ii]&0x7F);
-        if (byHighSuppRate == 0)
-            byHighSuppRate = byRate;
-        if (byRate > byHighSuppRate)
-            byHighSuppRate = byRate;
-        *pwSuppRate |= (1<<wGetRateIdx(byRate));
-    }
-    if ((pItemExtRates != NULL) && (pItemExtRates->byElementID == WLAN_EID_EXTSUPP_RATES) &&
-        (pDevice->eCurrentPHYType != PHY_TYPE_11B)) {
-
-        unsigned int uExtRateLen = pItemExtRates->len;
-
-        if (uExtRateLen > WLAN_RATES_MAXLEN)
-            uExtRateLen = WLAN_RATES_MAXLEN;
-
-        for (ii = 0; ii < uExtRateLen ; ii++) {
-            byRate = (unsigned char)(pItemExtRates->abyRates[ii]);
-            // select highest basic rate
-            if (WLAN_MGMT_IS_BASICRATE(pItemExtRates->abyRates[ii])) {
-            	// Add to basic rate set, update pDevice->byTopCCKBasicRate and pDevice->byTopOFDMBasicRate
-                CARDbAddBasicRate((void *)pDevice, wGetRateIdx(byRate));
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ParseMaxRate AddBasicRate: %d\n", wGetRateIdx(byRate));
-            }
-            byRate = (unsigned char)(pItemExtRates->abyRates[ii]&0x7F);
-            if (byHighSuppRate == 0)
-                byHighSuppRate = byRate;
-            if (byRate > byHighSuppRate)
-                byHighSuppRate = byRate;
-            *pwSuppRate |= (1<<wGetRateIdx(byRate));
-            //DBG_PRN_GRP09(("ParseMaxRate : HighSuppRate: %d, %X\n", wGetRateIdx(byRate), byRate));
-        }
-    } //if(pItemExtRates != NULL)
-
-    if ((pDevice->byPacketType == PK_TYPE_11GB) && CARDbIsOFDMinBasicRate((void *)pDevice)) {
-        pDevice->byPacketType = PK_TYPE_11GA;
-    }
-
-    *pbyTopCCKRate = pDevice->byTopCCKBasicRate;
-    *pbyTopOFDMRate = pDevice->byTopOFDMBasicRate;
-    *pwMaxSuppRate = wGetRateIdx(byHighSuppRate);
-    if ((pDevice->byPacketType==PK_TYPE_11B) || (pDevice->byPacketType==PK_TYPE_11GB))
-       *pwMaxBasicRate = pDevice->byTopCCKBasicRate;
-    else
-       *pwMaxBasicRate = pDevice->byTopOFDMBasicRate;
-    if (wOldBasicRate != pDevice->wBasicRate)
-        CARDvSetRSPINF((void *)pDevice, pDevice->eCurrentPHYType);
-
-     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Exit ParseMaxRate\n");
+	PSDevice  pDevice = (PSDevice) pDeviceHandler;
+	unsigned int ii;
+	unsigned char byHighSuppRate = 0;
+	unsigned char byRate = 0;
+	unsigned short wOldBasicRate = pDevice->wBasicRate;
+	unsigned int uRateLen;
+
+	if (pItemRates == NULL)
+		return;
+
+	*pwSuppRate = 0;
+	uRateLen = pItemRates->len;
+
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ParseMaxRate Len: %d\n", uRateLen);
+	if (pDevice->eCurrentPHYType != PHY_TYPE_11B) {
+		if (uRateLen > WLAN_RATES_MAXLEN)
+			uRateLen = WLAN_RATES_MAXLEN;
+	} else {
+		if (uRateLen > WLAN_RATES_MAXLEN_11B)
+			uRateLen = WLAN_RATES_MAXLEN_11B;
+	}
+
+	for (ii = 0; ii < uRateLen; ii++) {
+		byRate = (unsigned char)(pItemRates->abyRates[ii]);
+		if (WLAN_MGMT_IS_BASICRATE(byRate) &&
+		    (bUpdateBasicRate == true))  {
+			// Add to basic rate set, update pDevice->byTopCCKBasicRate and pDevice->byTopOFDMBasicRate
+			CARDbAddBasicRate((void *)pDevice, wGetRateIdx(byRate));
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ParseMaxRate AddBasicRate: %d\n", wGetRateIdx(byRate));
+		}
+		byRate = (unsigned char)(pItemRates->abyRates[ii]&0x7F);
+		if (byHighSuppRate == 0)
+			byHighSuppRate = byRate;
+		if (byRate > byHighSuppRate)
+			byHighSuppRate = byRate;
+		*pwSuppRate |= (1<<wGetRateIdx(byRate));
+	}
+	if ((pItemExtRates != NULL) && (pItemExtRates->byElementID == WLAN_EID_EXTSUPP_RATES) &&
+	    (pDevice->eCurrentPHYType != PHY_TYPE_11B)) {
+		unsigned int uExtRateLen = pItemExtRates->len;
+
+		if (uExtRateLen > WLAN_RATES_MAXLEN)
+			uExtRateLen = WLAN_RATES_MAXLEN;
+
+		for (ii = 0; ii < uExtRateLen; ii++) {
+			byRate = (unsigned char)(pItemExtRates->abyRates[ii]);
+			// select highest basic rate
+			if (WLAN_MGMT_IS_BASICRATE(pItemExtRates->abyRates[ii])) {
+				// Add to basic rate set, update pDevice->byTopCCKBasicRate and pDevice->byTopOFDMBasicRate
+				CARDbAddBasicRate((void *)pDevice, wGetRateIdx(byRate));
+				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ParseMaxRate AddBasicRate: %d\n", wGetRateIdx(byRate));
+			}
+			byRate = (unsigned char)(pItemExtRates->abyRates[ii]&0x7F);
+			if (byHighSuppRate == 0)
+				byHighSuppRate = byRate;
+			if (byRate > byHighSuppRate)
+				byHighSuppRate = byRate;
+			*pwSuppRate |= (1<<wGetRateIdx(byRate));
+			//DBG_PRN_GRP09(("ParseMaxRate : HighSuppRate: %d, %X\n", wGetRateIdx(byRate), byRate));
+		}
+	} //if (pItemExtRates != NULL)
+
+	if ((pDevice->byPacketType == PK_TYPE_11GB) && CARDbIsOFDMinBasicRate((void *)pDevice)) {
+		pDevice->byPacketType = PK_TYPE_11GA;
+	}
+
+	*pbyTopCCKRate = pDevice->byTopCCKBasicRate;
+	*pbyTopOFDMRate = pDevice->byTopOFDMBasicRate;
+	*pwMaxSuppRate = wGetRateIdx(byHighSuppRate);
+	if ((pDevice->byPacketType == PK_TYPE_11B) || (pDevice->byPacketType == PK_TYPE_11GB))
+		*pwMaxBasicRate = pDevice->byTopCCKBasicRate;
+	else
+		*pwMaxBasicRate = pDevice->byTopOFDMBasicRate;
+	if (wOldBasicRate != pDevice->wBasicRate)
+		CARDvSetRSPINF((void *)pDevice, pDevice->eCurrentPHYType);
+
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Exit ParseMaxRate\n");
 }
 
-
 /*+
  *
  * Routine Description:
@@ -303,97 +287,95 @@ unsigned int uRateLen;
  *
  * Return Value: none
  *
--*/
+ -*/
 #define AUTORATE_TXCNT_THRESHOLD        20
 #define AUTORATE_INC_THRESHOLD          30
 
 void
-RATEvTxRateFallBack (
-    void *pDeviceHandler,
-    PKnownNodeDB psNodeDBTable
-    )
+RATEvTxRateFallBack(
+	void *pDeviceHandler,
+	PKnownNodeDB psNodeDBTable
+)
 {
-PSDevice        pDevice = (PSDevice) pDeviceHandler;
-unsigned short wIdxDownRate = 0;
-unsigned int ii;
+	PSDevice        pDevice = (PSDevice) pDeviceHandler;
+	unsigned short wIdxDownRate = 0;
+	unsigned int ii;
 //unsigned long dwRateTable[MAX_RATE]  = {1,   2,   5,   11,  6,    9,    12,   18,  24,  36,  48,  54};
-bool bAutoRate[MAX_RATE]    = {true,true,true,true,false,false,true,true,true,true,true,true};
+	bool bAutoRate[MAX_RATE]    = {true, true, true, true, false, false, true, true, true, true, true, true};
 	unsigned long dwThroughputTbl[MAX_RATE] = {10, 20, 55, 110, 60, 90, 120, 180, 240, 360, 480, 540};
 	unsigned long dwThroughput = 0;
 	unsigned short wIdxUpRate = 0;
 	unsigned long dwTxDiff = 0;
 
-    if (pDevice->pMgmt->eScanState != WMAC_NO_SCANNING) {
-        // Don't do Fallback when scanning Channel
-        return;
-    }
-
-    psNodeDBTable->uTimeCount ++;
-
-    if (psNodeDBTable->uTxFail[MAX_RATE] > psNodeDBTable->uTxOk[MAX_RATE])
-        dwTxDiff = psNodeDBTable->uTxFail[MAX_RATE] - psNodeDBTable->uTxOk[MAX_RATE];
-
-    if ((psNodeDBTable->uTxOk[MAX_RATE] < AUTORATE_TXOK_CNT) &&
-        (dwTxDiff < AUTORATE_TXFAIL_CNT) &&
-        (psNodeDBTable->uTimeCount < AUTORATE_TIMEOUT)) {
-        return;
-    }
-
-    if (psNodeDBTable->uTimeCount >= AUTORATE_TIMEOUT) {
-        psNodeDBTable->uTimeCount = 0;
-    }
-
-
-    for(ii=0;ii<MAX_RATE;ii++) {
-        if (psNodeDBTable->wSuppRate & (0x0001<<ii)) {
-            if (bAutoRate[ii] == true) {
-                wIdxUpRate = (unsigned short) ii;
-            }
-        } else {
-            bAutoRate[ii] = false;
-        }
-    }
-
-    for(ii=0;ii<=psNodeDBTable->wTxDataRate;ii++) {
-        if ( (psNodeDBTable->uTxOk[ii] != 0) ||
-             (psNodeDBTable->uTxFail[ii] != 0) ) {
-            dwThroughputTbl[ii] *= psNodeDBTable->uTxOk[ii];
-            if (ii < RATE_11M) {
-                psNodeDBTable->uTxFail[ii] *= 4;
-            }
-            dwThroughputTbl[ii] /= (psNodeDBTable->uTxOk[ii] + psNodeDBTable->uTxFail[ii]);
-        }
-//        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Rate %d,Ok: %d, Fail:%d, Throughput:%d\n",
+	if (pDevice->pMgmt->eScanState != WMAC_NO_SCANNING) {
+		// Don't do Fallback when scanning Channel
+		return;
+	}
+
+	psNodeDBTable->uTimeCount++;
+
+	if (psNodeDBTable->uTxFail[MAX_RATE] > psNodeDBTable->uTxOk[MAX_RATE])
+		dwTxDiff = psNodeDBTable->uTxFail[MAX_RATE] - psNodeDBTable->uTxOk[MAX_RATE];
+
+	if ((psNodeDBTable->uTxOk[MAX_RATE] < AUTORATE_TXOK_CNT) &&
+	    (dwTxDiff < AUTORATE_TXFAIL_CNT) &&
+	    (psNodeDBTable->uTimeCount < AUTORATE_TIMEOUT)) {
+		return;
+	}
+
+	if (psNodeDBTable->uTimeCount >= AUTORATE_TIMEOUT) {
+		psNodeDBTable->uTimeCount = 0;
+	}
+
+	for (ii = 0; ii < MAX_RATE; ii++) {
+		if (psNodeDBTable->wSuppRate & (0x0001<<ii)) {
+			if (bAutoRate[ii] == true) {
+				wIdxUpRate = (unsigned short) ii;
+			}
+		} else {
+			bAutoRate[ii] = false;
+		}
+	}
+
+	for (ii = 0; ii <= psNodeDBTable->wTxDataRate; ii++) {
+		if ((psNodeDBTable->uTxOk[ii] != 0) ||
+		    (psNodeDBTable->uTxFail[ii] != 0)) {
+			dwThroughputTbl[ii] *= psNodeDBTable->uTxOk[ii];
+			if (ii < RATE_11M) {
+				psNodeDBTable->uTxFail[ii] *= 4;
+			}
+			dwThroughputTbl[ii] /= (psNodeDBTable->uTxOk[ii] + psNodeDBTable->uTxFail[ii]);
+		}
+//        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Rate %d,Ok: %d, Fail:%d, Throughput:%d\n",
 //                       ii, psNodeDBTable->uTxOk[ii], psNodeDBTable->uTxFail[ii], dwThroughputTbl[ii]);
-    }
-    dwThroughput = dwThroughputTbl[psNodeDBTable->wTxDataRate];
-
-    wIdxDownRate = psNodeDBTable->wTxDataRate;
-    for(ii = psNodeDBTable->wTxDataRate; ii > 0;) {
-        ii--;
-        if ( (dwThroughputTbl[ii] > dwThroughput) &&
-             (bAutoRate[ii]==true) ) {
-            dwThroughput = dwThroughputTbl[ii];
-            wIdxDownRate = (unsigned short) ii;
-        }
-    }
-    psNodeDBTable->wTxDataRate = wIdxDownRate;
-    if (psNodeDBTable->uTxOk[MAX_RATE]) {
-        if (psNodeDBTable->uTxOk[MAX_RATE] >
-           (psNodeDBTable->uTxFail[MAX_RATE] * 4) ) {
-            psNodeDBTable->wTxDataRate = wIdxUpRate;
-        }
-    }else { // adhoc, if uTxOk =0 & uTxFail = 0
-        if (psNodeDBTable->uTxFail[MAX_RATE] == 0)
-            psNodeDBTable->wTxDataRate = wIdxUpRate;
-    }
+	}
+	dwThroughput = dwThroughputTbl[psNodeDBTable->wTxDataRate];
+
+	wIdxDownRate = psNodeDBTable->wTxDataRate;
+	for (ii = psNodeDBTable->wTxDataRate; ii > 0;) {
+		ii--;
+		if ((dwThroughputTbl[ii] > dwThroughput) &&
+		    (bAutoRate[ii] == true)) {
+			dwThroughput = dwThroughputTbl[ii];
+			wIdxDownRate = (unsigned short) ii;
+		}
+	}
+	psNodeDBTable->wTxDataRate = wIdxDownRate;
+	if (psNodeDBTable->uTxOk[MAX_RATE]) {
+		if (psNodeDBTable->uTxOk[MAX_RATE] >
+		    (psNodeDBTable->uTxFail[MAX_RATE] * 4)) {
+			psNodeDBTable->wTxDataRate = wIdxUpRate;
+		}
+	} else { // adhoc, if uTxOk =0 & uTxFail = 0
+		if (psNodeDBTable->uTxFail[MAX_RATE] == 0)
+			psNodeDBTable->wTxDataRate = wIdxUpRate;
+	}
 //2008-5-8 <add> by chester
-TxRate_iwconfig=psNodeDBTable->wTxDataRate;
-    s_vResetCounter(psNodeDBTable);
-//    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Rate: %d, U:%d, D:%d\n", psNodeDBTable->wTxDataRate, wIdxUpRate, wIdxDownRate);
-
-    return;
+	TxRate_iwconfig = psNodeDBTable->wTxDataRate;
+	s_vResetCounter(psNodeDBTable);
+//    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Rate: %d, U:%d, D:%d\n", psNodeDBTable->wTxDataRate, wIdxUpRate, wIdxDownRate);
 
+	return;
 }
 
 /*+
@@ -408,30 +390,29 @@ TxRate_iwconfig=psNodeDBTable->wTxDataRate;
  *
  * Return Value: None
  *
--*/
+ -*/
 unsigned char
-RATEuSetIE (
-    PWLAN_IE_SUPP_RATES pSrcRates,
-    PWLAN_IE_SUPP_RATES pDstRates,
-    unsigned int uRateLen
-    )
+RATEuSetIE(
+	PWLAN_IE_SUPP_RATES pSrcRates,
+	PWLAN_IE_SUPP_RATES pDstRates,
+	unsigned int uRateLen
+)
 {
-    unsigned int ii, uu, uRateCnt = 0;
-
-    if ((pSrcRates == NULL) || (pDstRates == NULL))
-        return 0;
-
-    if (pSrcRates->len == 0)
-        return 0;
-
-    for (ii = 0; ii < uRateLen; ii++) {
-        for (uu = 0; uu < pSrcRates->len; uu++) {
-            if ((pSrcRates->abyRates[uu] & 0x7F) == acbyIERate[ii]) {
-                pDstRates->abyRates[uRateCnt ++] = pSrcRates->abyRates[uu];
-                break;
-            }
-        }
-    }
-    return (unsigned char)uRateCnt;
+	unsigned int ii, uu, uRateCnt = 0;
+
+	if ((pSrcRates == NULL) || (pDstRates == NULL))
+		return 0;
+
+	if (pSrcRates->len == 0)
+		return 0;
+
+	for (ii = 0; ii < uRateLen; ii++) {
+		for (uu = 0; uu < pSrcRates->len; uu++) {
+			if ((pSrcRates->abyRates[uu] & 0x7F) == acbyIERate[ii]) {
+				pDstRates->abyRates[uRateCnt++] = pSrcRates->abyRates[uu];
+				break;
+			}
+		}
+	}
+	return (unsigned char)uRateCnt;
 }
-
diff --git a/drivers/staging/vt6655/datarate.h b/drivers/staging/vt6655/datarate.h
index 4f8ea0b..e4fad05 100644
--- a/drivers/staging/vt6655/datarate.h
+++ b/drivers/staging/vt6655/datarate.h
@@ -41,55 +41,48 @@
 #define RETRY_TIMES_THRD_H         2    // times
 #define RETRY_TIMES_THRD_L         1    // times
 
-
 /*---------------------  Export Classes  ----------------------------*/
 
 /*---------------------  Export Variables  --------------------------*/
 
-
 /*---------------------  Export Types  ------------------------------*/
 
-
 /*---------------------  Export Functions  --------------------------*/
 
-
-
 void
 RATEvParseMaxRate(
-    void *pDeviceHandler,
-    PWLAN_IE_SUPP_RATES pItemRates,
-    PWLAN_IE_SUPP_RATES pItemExtRates,
-    bool bUpdateBasicRate,
-    unsigned short *pwMaxBasicRate,
-    unsigned short *pwMaxSuppRate,
-    unsigned short *pwSuppRate,
-    unsigned char *pbyTopCCKRate,
-    unsigned char *pbyTopOFDMRate
-    );
+	void *pDeviceHandler,
+	PWLAN_IE_SUPP_RATES pItemRates,
+	PWLAN_IE_SUPP_RATES pItemExtRates,
+	bool bUpdateBasicRate,
+	unsigned short *pwMaxBasicRate,
+	unsigned short *pwMaxSuppRate,
+	unsigned short *pwSuppRate,
+	unsigned char *pbyTopCCKRate,
+	unsigned char *pbyTopOFDMRate
+);
 
 void
 RATEvTxRateFallBack(
-    void *pDeviceHandler,
-    PKnownNodeDB psNodeDBTable
-    );
+	void *pDeviceHandler,
+	PKnownNodeDB psNodeDBTable
+);
 
 unsigned char
 RATEuSetIE(
-    PWLAN_IE_SUPP_RATES pSrcRates,
-    PWLAN_IE_SUPP_RATES pDstRates,
-    unsigned int uRateLen
-    );
+	PWLAN_IE_SUPP_RATES pSrcRates,
+	PWLAN_IE_SUPP_RATES pDstRates,
+	unsigned int uRateLen
+);
 
 unsigned short
 wGetRateIdx(
-    unsigned char byRate
-    );
-
+	unsigned char byRate
+);
 
 unsigned char
 DATARATEbyGetRateIdx(
-    unsigned char byRate
-    );
-
+	unsigned char byRate
+);
 
 #endif //__DATARATE_H__
diff --git a/drivers/staging/vt6655/desc.h b/drivers/staging/vt6655/desc.h
index 084a1a5..32d808e 100644
--- a/drivers/staging/vt6655/desc.h
+++ b/drivers/staging/vt6655/desc.h
@@ -89,7 +89,7 @@
 
 // max transmit or receive buffer size
 #define CB_MAX_BUF_SIZE     2900U       // max buffer size
-                                        // NOTE: must be multiple of 4
+					// NOTE: must be multiple of 4
 #define CB_MAX_TX_BUF_SIZE          CB_MAX_BUF_SIZE // max Tx buffer size
 #define CB_MAX_RX_BUF_SIZE_NORMAL   CB_MAX_BUF_SIZE // max Rx buffer size when not use Multi-RD
 
@@ -101,16 +101,15 @@
 #define CB_MIN_TX_DESC      16          // min # of tx descriptor
 
 #define CB_MAX_RECEIVED_PACKETS     16  // max # of received packets at one time
-                                        // limit our receive routine to indicating
-                                        // this many at a time for 2 reasons:
-                                        // 1. driver flow control to protocol layer
-                                        // 2. limit the time used in ISR routine
+					// limit our receive routine to indicating
+					// this many at a time for 2 reasons:
+					// 1. driver flow control to protocol layer
+					// 2. limit the time used in ISR routine
 
 #define CB_EXTRA_RD_NUM     32          // default # of Extra RD
 #define CB_RD_NUM           32          // default # of RD
 #define CB_TD_NUM           32          // default # of TD
 
-
 // max number of physical segments
 // in a single NDIS packet. Above this threshold, the packet
 // is copied into a single physically contiguous buffer
@@ -121,8 +120,6 @@
 
 #define CB_PROTOCOL_RESERVED_SECTION    16
 
-
-
 // if retrys excess 15 times , tx will abort, and
 // if tx fifo underflow, tx will fail
 // we should try to resend it
@@ -199,8 +196,6 @@
 #define TYPE_RXDMA1     1
 #define TYPE_MAXRD      2
 
-
-
 // TD_INFO flags control bit
 #define TD_FLAGS_NETIF_SKB               0x01       // check if need release skb
 #define TD_FLAGS_PRIV_SKB                0x02       // check if called from private skb(hostap)
@@ -213,28 +208,28 @@
 // may link to older skb that leads error.
 
 typedef struct tagDEVICE_RD_INFO {
-    struct sk_buff* skb;
-    dma_addr_t  skb_dma;
-    dma_addr_t  curr_desc;
+	struct sk_buff *skb;
+	dma_addr_t  skb_dma;
+	dma_addr_t  curr_desc;
 } DEVICE_RD_INFO,   *PDEVICE_RD_INFO;
 
 /*
-static inline PDEVICE_RD_INFO alloc_rd_info(void) {
-    PDEVICE_RD_INFO  ptr;
-    ptr = kmalloc(sizeof(DEVICE_RD_INFO), GFP_ATOMIC);
-    if (ptr == NULL)
-        return NULL;
-    else {
-        memset(ptr,0,sizeof(DEVICE_RD_INFO));
-        return ptr;
-    }
-}
+  static inline PDEVICE_RD_INFO alloc_rd_info(void) {
+  PDEVICE_RD_INFO  ptr;
+  ptr = kmalloc(sizeof(DEVICE_RD_INFO), GFP_ATOMIC);
+  if (ptr == NULL)
+  return NULL;
+  else {
+  memset(ptr,0,sizeof(DEVICE_RD_INFO));
+  return ptr;
+  }
+  }
 */
 
 /*
-typedef struct tagRDES0 {
-    unsigned short wResCount;
-    unsigned short wf1Owner ;
+  typedef struct tagRDES0 {
+  unsigned short wResCount;
+  unsigned short wf1Owner;
 //    unsigned short f15Reserved : 15;
 //    unsigned short f1Owner : 1;
 } __attribute__ ((__packed__))
@@ -244,11 +239,11 @@ SRDES0;
 #ifdef __BIG_ENDIAN
 
 typedef struct tagRDES0 {
-   volatile unsigned short wResCount;
+	volatile unsigned short wResCount;
 	union {
 		volatile u16    f15Reserved;
 		struct {
-            volatile u8 f8Reserved1;
+			volatile u8 f8Reserved1;
 			volatile u8 f1Owner:1;
 			volatile u8 f7Reserved:7;
 		} __attribute__ ((__packed__));
@@ -259,18 +254,17 @@ SRDES0, *PSRDES0;
 #else
 
 typedef struct tagRDES0 {
-    unsigned short wResCount;
-    unsigned short f15Reserved : 15;
-    unsigned short f1Owner : 1;
+	unsigned short wResCount;
+	unsigned short f15Reserved:15;
+	unsigned short f1Owner:1;
 } __attribute__ ((__packed__))
 SRDES0;
 
-
 #endif
 
 typedef struct tagRDES1 {
-    unsigned short wReqCount;
-    unsigned short wReserved;
+	unsigned short wReqCount;
+	unsigned short wReserved;
 } __attribute__ ((__packed__))
 SRDES1;
 
@@ -278,13 +272,13 @@ SRDES1;
 // Rx descriptor
 //
 typedef struct tagSRxDesc {
-    volatile SRDES0 m_rd0RD0;
-    volatile SRDES1 m_rd1RD1;
-    volatile u32    buff_addr;
-    volatile u32    next_desc;
-    struct tagSRxDesc   *next;//4 bytes
-    volatile PDEVICE_RD_INFO    pRDInfo;//4 bytes
-    volatile u32    Reserved[2];//8 bytes
+	volatile SRDES0 m_rd0RD0;
+	volatile SRDES1 m_rd1RD1;
+	volatile u32    buff_addr;
+	volatile u32    next_desc;
+	struct tagSRxDesc   *next;//4 bytes
+	volatile PDEVICE_RD_INFO    pRDInfo;//4 bytes
+	volatile u32    Reserved[2];//8 bytes
 } __attribute__ ((__packed__))
 SRxDesc, *PSRxDesc;
 typedef const SRxDesc *PCSRxDesc;
@@ -292,10 +286,10 @@ typedef const SRxDesc *PCSRxDesc;
 #ifdef __BIG_ENDIAN
 
 /*
-typedef struct tagTDES0 {
-    volatile    unsigned char byTSR0;
-    volatile    unsigned char byTSR1;
-    volatile    unsigned short wOwner_Txtime;
+  typedef struct tagTDES0 {
+  volatile    unsigned char byTSR0;
+  volatile    unsigned char byTSR1;
+  volatile    unsigned short wOwner_Txtime;
 //    volatile    unsigned short f15Txtime : 15;
 //    volatile    unsigned short f1Owner:1;
 } __attribute__ ((__packed__))
@@ -303,12 +297,12 @@ STDES0;
 */
 
 typedef struct tagTDES0 {
-    volatile    unsigned char byTSR0;
-    volatile    unsigned char byTSR1;
+	volatile    unsigned char byTSR0;
+	volatile    unsigned char byTSR1;
 	union {
 		volatile u16    f15Txtime;
 		struct {
-            volatile u8 f8Reserved1;
+			volatile u8 f8Reserved1;
 			volatile u8 f1Owner:1;
 			volatile u8 f7Reserved:7;
 		} __attribute__ ((__packed__));
@@ -319,113 +313,109 @@ STDES0, PSTDES0;
 #else
 
 typedef struct tagTDES0 {
-    volatile    unsigned char byTSR0;
-    volatile    unsigned char byTSR1;
-    volatile    unsigned short f15Txtime : 15;
-    volatile    unsigned short f1Owner:1;
+	volatile    unsigned char byTSR0;
+	volatile    unsigned char byTSR1;
+	volatile    unsigned short f15Txtime:15;
+	volatile    unsigned short f1Owner:1;
 } __attribute__ ((__packed__))
 STDES0;
 
 #endif
 
-
 typedef struct tagTDES1 {
-    volatile    unsigned short wReqCount;
-    volatile    unsigned char byTCR;
-    volatile    unsigned char byReserved;
+	volatile    unsigned short wReqCount;
+	volatile    unsigned char byTCR;
+	volatile    unsigned char byReserved;
 } __attribute__ ((__packed__))
 STDES1;
 
-
-typedef struct tagDEVICE_TD_INFO{
-    struct sk_buff*     skb;
-    unsigned char *buf;
-    dma_addr_t          skb_dma;
-    dma_addr_t          buf_dma;
-    dma_addr_t          curr_desc;
-    unsigned long dwReqCount;
-    unsigned long dwHeaderLength;
-    unsigned char byFlags;
+typedef struct tagDEVICE_TD_INFO {
+	struct sk_buff *skb;
+	unsigned char *buf;
+	dma_addr_t          skb_dma;
+	dma_addr_t          buf_dma;
+	dma_addr_t          curr_desc;
+	unsigned long dwReqCount;
+	unsigned long dwHeaderLength;
+	unsigned char byFlags;
 } DEVICE_TD_INFO,    *PDEVICE_TD_INFO;
 
 /*
-static inline PDEVICE_TD_INFO alloc_td_info(void) {
-    PDEVICE_TD_INFO  ptr;
-    ptr = kmalloc(sizeof(DEVICE_TD_INFO),GFP_ATOMIC);
-    if (ptr == NULL)
-        return NULL;
-    else {
-        memset(ptr,0,sizeof(DEVICE_TD_INFO));
-        return ptr;
-    }
-}
+  static inline PDEVICE_TD_INFO alloc_td_info(void) {
+  PDEVICE_TD_INFO  ptr;
+  ptr = kmalloc(sizeof(DEVICE_TD_INFO),GFP_ATOMIC);
+  if (ptr == NULL)
+  return NULL;
+  else {
+  memset(ptr,0,sizeof(DEVICE_TD_INFO));
+  return ptr;
+  }
+  }
 */
 
 //
 // transmit descriptor
 //
 typedef struct tagSTxDesc {
-    volatile    STDES0  m_td0TD0;
-    volatile    STDES1  m_td1TD1;
-    volatile    u32    buff_addr;
-    volatile    u32    next_desc;
-    struct tagSTxDesc*  next; //4 bytes
-    volatile    PDEVICE_TD_INFO pTDInfo;//4 bytes
-    volatile    u32    Reserved[2];//8 bytes
+	volatile    STDES0  m_td0TD0;
+	volatile    STDES1  m_td1TD1;
+	volatile    u32    buff_addr;
+	volatile    u32    next_desc;
+	struct tagSTxDesc *next; //4 bytes
+	volatile    PDEVICE_TD_INFO pTDInfo;//4 bytes
+	volatile    u32    Reserved[2];//8 bytes
 } __attribute__ ((__packed__))
 STxDesc, *PSTxDesc;
 typedef const STxDesc *PCSTxDesc;
 
-
 typedef struct tagSTxSyncDesc {
-    volatile    STDES0  m_td0TD0;
-    volatile    STDES1  m_td1TD1;
-    volatile    u32 buff_addr; // pointer to logical buffer
-    volatile    u32 next_desc; // pointer to next logical descriptor
-    volatile    unsigned short m_wFIFOCtl;
-    volatile    unsigned short m_wTimeStamp;
-    struct tagSTxSyncDesc*  next; //4 bytes
-    volatile    PDEVICE_TD_INFO pTDInfo;//4 bytes
-    volatile    u32 m_dwReserved2;
+	volatile    STDES0  m_td0TD0;
+	volatile    STDES1  m_td1TD1;
+	volatile    u32 buff_addr; // pointer to logical buffer
+	volatile    u32 next_desc; // pointer to next logical descriptor
+	volatile    unsigned short m_wFIFOCtl;
+	volatile    unsigned short m_wTimeStamp;
+	struct tagSTxSyncDesc *next; //4 bytes
+	volatile    PDEVICE_TD_INFO pTDInfo;//4 bytes
+	volatile    u32 m_dwReserved2;
 } __attribute__ ((__packed__))
 STxSyncDesc, *PSTxSyncDesc;
 typedef const STxSyncDesc *PCSTxSyncDesc;
 
-
 //
 // RsvTime buffer header
 //
 typedef struct tagSRrvTime_gRTS {
-    unsigned short wRTSTxRrvTime_ba;
-    unsigned short wRTSTxRrvTime_aa;
-    unsigned short wRTSTxRrvTime_bb;
-    unsigned short wReserved;
-    unsigned short wTxRrvTime_b;
-    unsigned short wTxRrvTime_a;
-}__attribute__ ((__packed__))
+	unsigned short wRTSTxRrvTime_ba;
+	unsigned short wRTSTxRrvTime_aa;
+	unsigned short wRTSTxRrvTime_bb;
+	unsigned short wReserved;
+	unsigned short wTxRrvTime_b;
+	unsigned short wTxRrvTime_a;
+} __attribute__ ((__packed__))
 SRrvTime_gRTS, *PSRrvTime_gRTS;
 typedef const SRrvTime_gRTS *PCSRrvTime_gRTS;
 
 typedef struct tagSRrvTime_gCTS {
-    unsigned short wCTSTxRrvTime_ba;
-    unsigned short wReserved;
-    unsigned short wTxRrvTime_b;
-    unsigned short wTxRrvTime_a;
-}__attribute__ ((__packed__))
+	unsigned short wCTSTxRrvTime_ba;
+	unsigned short wReserved;
+	unsigned short wTxRrvTime_b;
+	unsigned short wTxRrvTime_a;
+} __attribute__ ((__packed__))
 SRrvTime_gCTS, *PSRrvTime_gCTS;
 typedef const SRrvTime_gCTS *PCSRrvTime_gCTS;
 
 typedef struct tagSRrvTime_ab {
-    unsigned short wRTSTxRrvTime;
-    unsigned short wTxRrvTime;
-}__attribute__ ((__packed__))
+	unsigned short wRTSTxRrvTime;
+	unsigned short wTxRrvTime;
+} __attribute__ ((__packed__))
 SRrvTime_ab, *PSRrvTime_ab;
 typedef const SRrvTime_ab *PCSRrvTime_ab;
 
 typedef struct tagSRrvTime_atim {
-    unsigned short wCTSTxRrvTime_ba;
-    unsigned short wTxRrvTime_a;
-}__attribute__ ((__packed__))
+	unsigned short wCTSTxRrvTime_ba;
+	unsigned short wTxRrvTime_a;
+} __attribute__ ((__packed__))
 SRrvTime_atim, *PSRrvTime_atim;
 typedef const SRrvTime_atim *PCSRrvTime_atim;
 
@@ -433,132 +423,127 @@ typedef const SRrvTime_atim *PCSRrvTime_atim;
 // RTS buffer header
 //
 typedef struct tagSRTSData {
-    unsigned short wFrameControl;
-    unsigned short wDurationID;
-    unsigned char abyRA[ETH_ALEN];
-    unsigned char abyTA[ETH_ALEN];
-}__attribute__ ((__packed__))
+	unsigned short wFrameControl;
+	unsigned short wDurationID;
+	unsigned char abyRA[ETH_ALEN];
+	unsigned char abyTA[ETH_ALEN];
+} __attribute__ ((__packed__))
 SRTSData, *PSRTSData;
 typedef const SRTSData *PCSRTSData;
 
 typedef struct tagSRTS_g {
-    unsigned char bySignalField_b;
-    unsigned char byServiceField_b;
-    unsigned short wTransmitLength_b;
-    unsigned char bySignalField_a;
-    unsigned char byServiceField_a;
-    unsigned short wTransmitLength_a;
-    unsigned short wDuration_ba;
-    unsigned short wDuration_aa;
-    unsigned short wDuration_bb;
-    unsigned short wReserved;
-    SRTSData    Data;
-}__attribute__ ((__packed__))
+	unsigned char bySignalField_b;
+	unsigned char byServiceField_b;
+	unsigned short wTransmitLength_b;
+	unsigned char bySignalField_a;
+	unsigned char byServiceField_a;
+	unsigned short wTransmitLength_a;
+	unsigned short wDuration_ba;
+	unsigned short wDuration_aa;
+	unsigned short wDuration_bb;
+	unsigned short wReserved;
+	SRTSData    Data;
+} __attribute__ ((__packed__))
 SRTS_g, *PSRTS_g;
 typedef const SRTS_g *PCSRTS_g;
 
-
 typedef struct tagSRTS_g_FB {
-    unsigned char bySignalField_b;
-    unsigned char byServiceField_b;
-    unsigned short wTransmitLength_b;
-    unsigned char bySignalField_a;
-    unsigned char byServiceField_a;
-    unsigned short wTransmitLength_a;
-    unsigned short wDuration_ba;
-    unsigned short wDuration_aa;
-    unsigned short wDuration_bb;
-    unsigned short wReserved;
-    unsigned short wRTSDuration_ba_f0;
-    unsigned short wRTSDuration_aa_f0;
-    unsigned short wRTSDuration_ba_f1;
-    unsigned short wRTSDuration_aa_f1;
-    SRTSData    Data;
-}__attribute__ ((__packed__))
+	unsigned char bySignalField_b;
+	unsigned char byServiceField_b;
+	unsigned short wTransmitLength_b;
+	unsigned char bySignalField_a;
+	unsigned char byServiceField_a;
+	unsigned short wTransmitLength_a;
+	unsigned short wDuration_ba;
+	unsigned short wDuration_aa;
+	unsigned short wDuration_bb;
+	unsigned short wReserved;
+	unsigned short wRTSDuration_ba_f0;
+	unsigned short wRTSDuration_aa_f0;
+	unsigned short wRTSDuration_ba_f1;
+	unsigned short wRTSDuration_aa_f1;
+	SRTSData    Data;
+} __attribute__ ((__packed__))
 SRTS_g_FB, *PSRTS_g_FB;
 typedef const SRTS_g_FB *PCSRTS_g_FB;
 
-
 typedef struct tagSRTS_ab {
-    unsigned char bySignalField;
-    unsigned char byServiceField;
-    unsigned short wTransmitLength;
-    unsigned short wDuration;
-    unsigned short wReserved;
-    SRTSData    Data;
-}__attribute__ ((__packed__))
+	unsigned char bySignalField;
+	unsigned char byServiceField;
+	unsigned short wTransmitLength;
+	unsigned short wDuration;
+	unsigned short wReserved;
+	SRTSData    Data;
+} __attribute__ ((__packed__))
 SRTS_ab, *PSRTS_ab;
 typedef const SRTS_ab *PCSRTS_ab;
 
-
 typedef struct tagSRTS_a_FB {
-    unsigned char bySignalField;
-    unsigned char byServiceField;
-    unsigned short wTransmitLength;
-    unsigned short wDuration;
-    unsigned short wReserved;
-    unsigned short wRTSDuration_f0;
-    unsigned short wRTSDuration_f1;
-    SRTSData    Data;
-}__attribute__ ((__packed__))
+	unsigned char bySignalField;
+	unsigned char byServiceField;
+	unsigned short wTransmitLength;
+	unsigned short wDuration;
+	unsigned short wReserved;
+	unsigned short wRTSDuration_f0;
+	unsigned short wRTSDuration_f1;
+	SRTSData    Data;
+} __attribute__ ((__packed__))
 SRTS_a_FB, *PSRTS_a_FB;
 typedef const SRTS_a_FB *PCSRTS_a_FB;
 
-
 //
 // CTS buffer header
 //
 typedef struct tagSCTSData {
-    unsigned short wFrameControl;
-    unsigned short wDurationID;
-    unsigned char abyRA[ETH_ALEN];
-    unsigned short wReserved;
-}__attribute__ ((__packed__))
+	unsigned short wFrameControl;
+	unsigned short wDurationID;
+	unsigned char abyRA[ETH_ALEN];
+	unsigned short wReserved;
+} __attribute__ ((__packed__))
 SCTSData, *PSCTSData;
 
 typedef struct tagSCTS {
-    unsigned char bySignalField_b;
-    unsigned char byServiceField_b;
-    unsigned short wTransmitLength_b;
-    unsigned short wDuration_ba;
-    unsigned short wReserved;
-    SCTSData    Data;
-}__attribute__ ((__packed__))
+	unsigned char bySignalField_b;
+	unsigned char byServiceField_b;
+	unsigned short wTransmitLength_b;
+	unsigned short wDuration_ba;
+	unsigned short wReserved;
+	SCTSData    Data;
+} __attribute__ ((__packed__))
 SCTS, *PSCTS;
 typedef const SCTS *PCSCTS;
 
 typedef struct tagSCTS_FB {
-    unsigned char bySignalField_b;
-    unsigned char byServiceField_b;
-    unsigned short wTransmitLength_b;
-    unsigned short wDuration_ba;
-    unsigned short wReserved;
-    unsigned short wCTSDuration_ba_f0;
-    unsigned short wCTSDuration_ba_f1;
-    SCTSData    Data;
-}__attribute__ ((__packed__))
+	unsigned char bySignalField_b;
+	unsigned char byServiceField_b;
+	unsigned short wTransmitLength_b;
+	unsigned short wDuration_ba;
+	unsigned short wReserved;
+	unsigned short wCTSDuration_ba_f0;
+	unsigned short wCTSDuration_ba_f1;
+	SCTSData    Data;
+} __attribute__ ((__packed__))
 SCTS_FB, *PSCTS_FB;
 typedef const SCTS_FB *PCSCTS_FB;
 
-
 //
 // Tx FIFO header
 //
 typedef struct tagSTxBufHead {
-    u32 adwTxKey[4];
-    unsigned short wFIFOCtl;
-    unsigned short wTimeStamp;
-    unsigned short wFragCtl;
-    unsigned char byTxPower;
-    unsigned char wReserved;
-}__attribute__ ((__packed__))
+	u32 adwTxKey[4];
+	unsigned short wFIFOCtl;
+	unsigned short wTimeStamp;
+	unsigned short wFragCtl;
+	unsigned char byTxPower;
+	unsigned char wReserved;
+} __attribute__ ((__packed__))
 STxBufHead, *PSTxBufHead;
 typedef const STxBufHead *PCSTxBufHead;
 
 typedef struct tagSTxShortBufHead {
-    unsigned short wFIFOCtl;
-    unsigned short wTimeStamp;
-}__attribute__ ((__packed__))
+	unsigned short wFIFOCtl;
+	unsigned short wTimeStamp;
+} __attribute__ ((__packed__))
 STxShortBufHead, *PSTxShortBufHead;
 typedef const STxShortBufHead *PCSTxShortBufHead;
 
@@ -566,58 +551,56 @@ typedef const STxShortBufHead *PCSTxShortBufHead;
 // Tx data header
 //
 typedef struct tagSTxDataHead_g {
-    unsigned char bySignalField_b;
-    unsigned char byServiceField_b;
-    unsigned short wTransmitLength_b;
-    unsigned char bySignalField_a;
-    unsigned char byServiceField_a;
-    unsigned short wTransmitLength_a;
-    unsigned short wDuration_b;
-    unsigned short wDuration_a;
-    unsigned short wTimeStampOff_b;
-    unsigned short wTimeStampOff_a;
-}__attribute__ ((__packed__))
+	unsigned char bySignalField_b;
+	unsigned char byServiceField_b;
+	unsigned short wTransmitLength_b;
+	unsigned char bySignalField_a;
+	unsigned char byServiceField_a;
+	unsigned short wTransmitLength_a;
+	unsigned short wDuration_b;
+	unsigned short wDuration_a;
+	unsigned short wTimeStampOff_b;
+	unsigned short wTimeStampOff_a;
+} __attribute__ ((__packed__))
 STxDataHead_g, *PSTxDataHead_g;
 typedef const STxDataHead_g *PCSTxDataHead_g;
 
 typedef struct tagSTxDataHead_g_FB {
-    unsigned char bySignalField_b;
-    unsigned char byServiceField_b;
-    unsigned short wTransmitLength_b;
-    unsigned char bySignalField_a;
-    unsigned char byServiceField_a;
-    unsigned short wTransmitLength_a;
-    unsigned short wDuration_b;
-    unsigned short wDuration_a;
-    unsigned short wDuration_a_f0;
-    unsigned short wDuration_a_f1;
-    unsigned short wTimeStampOff_b;
-    unsigned short wTimeStampOff_a;
-}__attribute__ ((__packed__))
+	unsigned char bySignalField_b;
+	unsigned char byServiceField_b;
+	unsigned short wTransmitLength_b;
+	unsigned char bySignalField_a;
+	unsigned char byServiceField_a;
+	unsigned short wTransmitLength_a;
+	unsigned short wDuration_b;
+	unsigned short wDuration_a;
+	unsigned short wDuration_a_f0;
+	unsigned short wDuration_a_f1;
+	unsigned short wTimeStampOff_b;
+	unsigned short wTimeStampOff_a;
+} __attribute__ ((__packed__))
 STxDataHead_g_FB, *PSTxDataHead_g_FB;
 typedef const STxDataHead_g_FB *PCSTxDataHead_g_FB;
 
-
 typedef struct tagSTxDataHead_ab {
-    unsigned char bySignalField;
-    unsigned char byServiceField;
-    unsigned short wTransmitLength;
-    unsigned short wDuration;
-    unsigned short wTimeStampOff;
-}__attribute__ ((__packed__))
+	unsigned char bySignalField;
+	unsigned char byServiceField;
+	unsigned short wTransmitLength;
+	unsigned short wDuration;
+	unsigned short wTimeStampOff;
+} __attribute__ ((__packed__))
 STxDataHead_ab, *PSTxDataHead_ab;
 typedef const STxDataHead_ab *PCSTxDataHead_ab;
 
-
 typedef struct tagSTxDataHead_a_FB {
-    unsigned char bySignalField;
-    unsigned char byServiceField;
-    unsigned short wTransmitLength;
-    unsigned short wDuration;
-    unsigned short wTimeStampOff;
-    unsigned short wDuration_f0;
-    unsigned short wDuration_f1;
-}__attribute__ ((__packed__))
+	unsigned char bySignalField;
+	unsigned char byServiceField;
+	unsigned short wTransmitLength;
+	unsigned short wDuration;
+	unsigned short wTimeStampOff;
+	unsigned short wDuration_f0;
+	unsigned short wDuration_f1;
+} __attribute__ ((__packed__))
 STxDataHead_a_FB, *PSTxDataHead_a_FB;
 typedef const STxDataHead_a_FB *PCSTxDataHead_a_FB;
 
@@ -625,38 +608,37 @@ typedef const STxDataHead_a_FB *PCSTxDataHead_a_FB;
 // MICHDR data header
 //
 typedef struct tagSMICHDRHead {
-    u32 adwHDR0[4];
-    u32 adwHDR1[4];
-    u32 adwHDR2[4];
-}__attribute__ ((__packed__))
+	u32 adwHDR0[4];
+	u32 adwHDR1[4];
+	u32 adwHDR2[4];
+} __attribute__ ((__packed__))
 SMICHDRHead, *PSMICHDRHead;
 typedef const SMICHDRHead *PCSMICHDRHead;
 
 typedef struct tagSBEACONCtl {
-    u32 BufReady : 1;
-    u32 TSF      : 15;
-    u32 BufLen   : 11;
-    u32 Reserved : 5;
-}__attribute__ ((__packed__))
+	u32 BufReady:1;
+	u32 TSF:15;
+	u32 BufLen:11;
+	u32 Reserved:5;
+} __attribute__ ((__packed__))
 SBEACONCtl;
 
-
 typedef struct tagSSecretKey {
-    u32 dwLowDword;
-    unsigned char byHighByte;
-}__attribute__ ((__packed__))
+	u32 dwLowDword;
+	unsigned char byHighByte;
+} __attribute__ ((__packed__))
 SSecretKey;
 
 typedef struct tagSKeyEntry {
-    unsigned char abyAddrHi[2];
-    unsigned short wKCTL;
-    unsigned char abyAddrLo[4];
-    u32 dwKey0[4];
-    u32 dwKey1[4];
-    u32 dwKey2[4];
-    u32 dwKey3[4];
-    u32 dwKey4[4];
-}__attribute__ ((__packed__))
+	unsigned char abyAddrHi[2];
+	unsigned short wKCTL;
+	unsigned char abyAddrLo[4];
+	u32 dwKey0[4];
+	u32 dwKey1[4];
+	u32 dwKey2[4];
+	u32 dwKey3[4];
+	u32 dwKey4[4];
+} __attribute__ ((__packed__))
 SKeyEntry;
 /*---------------------  Export Macros ------------------------------*/
 
@@ -666,8 +648,4 @@ SKeyEntry;
 
 /*---------------------  Export Functions  --------------------------*/
 
-
-
-
 #endif // __DESC_H__
-
diff --git a/drivers/staging/vt6655/device.h b/drivers/staging/vt6655/device.h
index e27244c..ca1b857 100644
--- a/drivers/staging/vt6655/device.h
+++ b/drivers/staging/vt6655/device.h
@@ -87,7 +87,6 @@
 #include "key.h"
 #include "mac.h"
 
-
 /*---------------------  Export Definitions -------------------------*/
 
 #define MAC_MAX_CONTEXT_REG     (256+128)
@@ -111,8 +110,6 @@
 #define KEYSEL_TKIP                     2
 #define KEYSEL_CCMP                     3
 
-
-
 #define AUTO_FB_NONE            0
 #define AUTO_FB_0               1
 #define AUTO_FB_1               2
@@ -133,8 +130,6 @@
 #define BB_VGA_LEVEL            4
 #define BB_VGA_CHANGE_THRESHOLD 16
 
-
-
 #ifndef RUN_AT
 #define RUN_AT(x)                       (jiffies+(x))
 #endif
@@ -142,59 +137,52 @@
 // DMA related
 #define RESERV_AC0DMA                   4
 
-
 // BUILD OBJ mode
 
-
-#define	AVAIL_TD(p,q)	((p)->sOpts.nTxDescs[(q)]-((p)->iTDUsed[(q)]))
+#define	AVAIL_TD(p, q)	((p)->sOpts.nTxDescs[(q)] - ((p)->iTDUsed[(q)]))
 
 //PLICE_DEBUG ->
 #define	NUM				64
 //PLICE_DEUBG <-
 
-
-
 #define PRIVATE_Message                 0
 
 /*---------------------  Export Types  ------------------------------*/
 
-
-#define DBG_PRT(l, p, args...) {if (l<=msglevel) printk( p ,##args);}
-#define PRINT_K(p, args...) {if (PRIVATE_Message) printk( p ,##args);}
+#define DBG_PRT(l, p, args...) { if (l <= msglevel) printk(p, ##args); }
+#define PRINT_K(p, args...) { if (PRIVATE_Message) printk(p, ##args); }
 
 //0:11A 1:11B 2:11G
 typedef enum _VIA_BB_TYPE
 {
-    BB_TYPE_11A=0,
-    BB_TYPE_11B,
-    BB_TYPE_11G
+	BB_TYPE_11A = 0,
+	BB_TYPE_11B,
+	BB_TYPE_11G
 } VIA_BB_TYPE, *PVIA_BB_TYPE;
 
 //0:11a,1:11b,2:11gb(only CCK in BasicRate),3:11ga(OFDM in Basic Rate)
 typedef enum _VIA_PKT_TYPE
 {
-    PK_TYPE_11A=0,
-    PK_TYPE_11B,
-    PK_TYPE_11GB,
-    PK_TYPE_11GA
+	PK_TYPE_11A = 0,
+	PK_TYPE_11B,
+	PK_TYPE_11GB,
+	PK_TYPE_11GA
 } VIA_PKT_TYPE, *PVIA_PKT_TYPE;
 
-
 typedef enum __device_msg_level {
-    MSG_LEVEL_ERR=0,            //Errors that will cause abnormal operation.
-    MSG_LEVEL_NOTICE=1,         //Some errors need users to be notified.
-    MSG_LEVEL_INFO=2,           //Normal message.
-    MSG_LEVEL_VERBOSE=3,        //Will report all trival errors.
-    MSG_LEVEL_DEBUG=4           //Only for debug purpose.
+	MSG_LEVEL_ERR = 0,            //Errors that will cause abnormal operation.
+	MSG_LEVEL_NOTICE = 1,         //Some errors need users to be notified.
+	MSG_LEVEL_INFO = 2,           //Normal message.
+	MSG_LEVEL_VERBOSE = 3,        //Will report all trival errors.
+	MSG_LEVEL_DEBUG = 4           //Only for debug purpose.
 } DEVICE_MSG_LEVEL, *PDEVICE_MSG_LEVEL;
 
 typedef enum __device_init_type {
-    DEVICE_INIT_COLD=0,         // cold init
-    DEVICE_INIT_RESET,          // reset init or Dx to D0 power remain init
-    DEVICE_INIT_DXPL            // Dx to D0 power lost init
+	DEVICE_INIT_COLD = 0,         // cold init
+	DEVICE_INIT_RESET,          // reset init or Dx to D0 power remain init
+	DEVICE_INIT_DXPL            // Dx to D0 power lost init
 } DEVICE_INIT_TYPE, *PDEVICE_INIT_TYPE;
 
-
 //++ NDIS related
 
 #define MAX_BSSIDINFO_4_PMKID   16
@@ -205,57 +193,54 @@ typedef enum __device_init_type {
 // PMKID Structures
 typedef unsigned char NDIS_802_11_PMKID_VALUE[16];
 
-
 typedef enum _NDIS_802_11_WEP_STATUS
 {
-    Ndis802_11WEPEnabled,
-    Ndis802_11Encryption1Enabled = Ndis802_11WEPEnabled,
-    Ndis802_11WEPDisabled,
-    Ndis802_11EncryptionDisabled = Ndis802_11WEPDisabled,
-    Ndis802_11WEPKeyAbsent,
-    Ndis802_11Encryption1KeyAbsent = Ndis802_11WEPKeyAbsent,
-    Ndis802_11WEPNotSupported,
-    Ndis802_11EncryptionNotSupported = Ndis802_11WEPNotSupported,
-    Ndis802_11Encryption2Enabled,
-    Ndis802_11Encryption2KeyAbsent,
-    Ndis802_11Encryption3Enabled,
-    Ndis802_11Encryption3KeyAbsent
+	Ndis802_11WEPEnabled,
+	Ndis802_11Encryption1Enabled = Ndis802_11WEPEnabled,
+	Ndis802_11WEPDisabled,
+	Ndis802_11EncryptionDisabled = Ndis802_11WEPDisabled,
+	Ndis802_11WEPKeyAbsent,
+	Ndis802_11Encryption1KeyAbsent = Ndis802_11WEPKeyAbsent,
+	Ndis802_11WEPNotSupported,
+	Ndis802_11EncryptionNotSupported = Ndis802_11WEPNotSupported,
+	Ndis802_11Encryption2Enabled,
+	Ndis802_11Encryption2KeyAbsent,
+	Ndis802_11Encryption3Enabled,
+	Ndis802_11Encryption3KeyAbsent
 } NDIS_802_11_WEP_STATUS, *PNDIS_802_11_WEP_STATUS,
-  NDIS_802_11_ENCRYPTION_STATUS, *PNDIS_802_11_ENCRYPTION_STATUS;
-
+	NDIS_802_11_ENCRYPTION_STATUS, *PNDIS_802_11_ENCRYPTION_STATUS;
 
 typedef enum _NDIS_802_11_STATUS_TYPE
 {
-    Ndis802_11StatusType_Authentication,
-    Ndis802_11StatusType_MediaStreamMode,
-    Ndis802_11StatusType_PMKID_CandidateList,
-    Ndis802_11StatusTypeMax    // not a real type, defined as an upper bound
+	Ndis802_11StatusType_Authentication,
+	Ndis802_11StatusType_MediaStreamMode,
+	Ndis802_11StatusType_PMKID_CandidateList,
+	Ndis802_11StatusTypeMax    // not a real type, defined as an upper bound
 } NDIS_802_11_STATUS_TYPE, *PNDIS_802_11_STATUS_TYPE;
 
 //Added new types for PMKID Candidate lists.
 typedef struct _PMKID_CANDIDATE {
-    NDIS_802_11_MAC_ADDRESS BSSID;
-    unsigned long Flags;
+	NDIS_802_11_MAC_ADDRESS BSSID;
+	unsigned long Flags;
 } PMKID_CANDIDATE, *PPMKID_CANDIDATE;
 
-
 typedef struct _BSSID_INFO
 {
-    NDIS_802_11_MAC_ADDRESS BSSID;
-    NDIS_802_11_PMKID_VALUE PMKID;
+	NDIS_802_11_MAC_ADDRESS BSSID;
+	NDIS_802_11_PMKID_VALUE PMKID;
 } BSSID_INFO, *PBSSID_INFO;
 
 typedef struct tagSPMKID {
-    unsigned long Length;
-    unsigned long BSSIDInfoCount;
-    BSSID_INFO BSSIDInfo[MAX_BSSIDINFO_4_PMKID];
+	unsigned long Length;
+	unsigned long BSSIDInfoCount;
+	BSSID_INFO BSSIDInfo[MAX_BSSIDINFO_4_PMKID];
 } SPMKID, *PSPMKID;
 
 typedef struct tagSPMKIDCandidateEvent {
-    NDIS_802_11_STATUS_TYPE     StatusType;
-    unsigned long Version;       // Version of the structure
-    unsigned long NumCandidates; // No. of pmkid candidates
-    PMKID_CANDIDATE CandidateList[MAX_PMKIDLIST];
+	NDIS_802_11_STATUS_TYPE     StatusType;
+	unsigned long Version;       // Version of the structure
+	unsigned long NumCandidates; // No. of pmkid candidates
+	PMKID_CANDIDATE CandidateList[MAX_PMKIDLIST];
 } SPMKIDCandidateEvent, *PSPMKIDCandidateEvent;
 
 //--
@@ -264,58 +249,54 @@ typedef struct tagSPMKIDCandidateEvent {
 #define MAX_QUIET_COUNT     8
 
 typedef struct tagSQuietControl {
-    bool bEnable;
-    unsigned long dwStartTime;
-    unsigned char byPeriod;
-    unsigned short wDuration;
+	bool bEnable;
+	unsigned long dwStartTime;
+	unsigned char byPeriod;
+	unsigned short wDuration;
 } SQuietControl, *PSQuietControl;
 
 //--
-typedef struct __chip_info_tbl{
-    CHIP_TYPE   chip_id;
-    char*       name;
-    int         io_size;
-    int         nTxQueue;
-    u32         flags;
+typedef struct __chip_info_tbl {
+	CHIP_TYPE   chip_id;
+	char *name;
+	int         io_size;
+	int         nTxQueue;
+	u32         flags;
 } CHIP_INFO, *PCHIP_INFO;
 
-
 typedef enum {
-    OWNED_BY_HOST=0,
-    OWNED_BY_NIC=1
+	OWNED_BY_HOST = 0,
+	OWNED_BY_NIC = 1
 } DEVICE_OWNER_TYPE, *PDEVICE_OWNER_TYPE;
 
-
 // The receive duplicate detection cache entry
-typedef struct tagSCacheEntry{
-    unsigned short wFmSequence;
-    unsigned char abyAddr2[ETH_ALEN];
+typedef struct tagSCacheEntry {
+	unsigned short wFmSequence;
+	unsigned char abyAddr2[ETH_ALEN];
 } SCacheEntry, *PSCacheEntry;
 
-typedef struct tagSCache{
+typedef struct tagSCache {
 /* The receive cache is updated circularly.  The next entry to be written is
  * indexed by the "InPtr".
-*/
-    unsigned int uInPtr;         // Place to use next
-    SCacheEntry     asCacheEntry[DUPLICATE_RX_CACHE_LENGTH];
+ */
+	unsigned int uInPtr;         // Place to use next
+	SCacheEntry     asCacheEntry[DUPLICATE_RX_CACHE_LENGTH];
 } SCache, *PSCache;
 
 #define CB_MAX_RX_FRAG                 64
 // DeFragment Control Block, used for collecting fragments prior to reassembly
 typedef struct tagSDeFragControlBlock
 {
-    unsigned short wSequence;
-    unsigned short wFragNum;
-    unsigned char abyAddr2[ETH_ALEN];
-    unsigned int uLifetime;
-    struct sk_buff* skb;
-    unsigned char *pbyRxBuffer;
-    unsigned int cbFrameLength;
-    bool bInUse;
+	unsigned short wSequence;
+	unsigned short wFragNum;
+	unsigned char abyAddr2[ETH_ALEN];
+	unsigned int uLifetime;
+	struct sk_buff *skb;
+	unsigned char *pbyRxBuffer;
+	unsigned int cbFrameLength;
+	bool bInUse;
 } SDeFragControlBlock, *PSDeFragControlBlock;
 
-
-
 //flags for options
 #define     DEVICE_FLAGS_IP_ALIGN        0x00000001UL
 #define     DEVICE_FLAGS_PREAMBLE_TYPE   0x00000002UL
@@ -343,511 +324,474 @@ typedef struct tagSDeFragControlBlock
 //for device_set_media_duplex
 #define     DEVICE_LINK_CHANGE           0x00000001UL
 
-
 //PLICE_DEBUG->
 
-
 typedef	struct _RxManagementQueue
 {
 	int	packet_num;
-	int	head,tail;
+	int	head, tail;
 	PSRxMgmtPacket	Q[NUM];
-} RxManagementQueue,*PSRxManagementQueue;
-
-
+} RxManagementQueue, *PSRxManagementQueue;
 
 //PLICE_DEBUG<-
 
-
 typedef struct __device_opt {
-    int         nRxDescs0;    //Number of RX descriptors0
-    int         nRxDescs1;    //Number of RX descriptors1
-    int         nTxDescs[2];  //Number of TX descriptors 0, 1
-    int         int_works;    //interrupt limits
-    int         rts_thresh;   //rts threshold
-    int         frag_thresh;
-    int         data_rate;
-    int         channel_num;
-    int         short_retry;
-    int         long_retry;
-    int         bbp_type;
-    u32         flags;
+	int         nRxDescs0;    //Number of RX descriptors0
+	int         nRxDescs1;    //Number of RX descriptors1
+	int         nTxDescs[2];  //Number of TX descriptors 0, 1
+	int         int_works;    //interrupt limits
+	int         rts_thresh;   //rts threshold
+	int         frag_thresh;
+	int         data_rate;
+	int         channel_num;
+	int         short_retry;
+	int         long_retry;
+	int         bbp_type;
+	u32         flags;
 } OPTIONS, *POPTIONS;
 
-
 typedef struct __device_info {
-    struct __device_info*        next;
-    struct __device_info*        prev;
+	struct __device_info *next;
+	struct __device_info *prev;
 
-    struct pci_dev*             pcid;
+	struct pci_dev *pcid;
 
 #ifdef CONFIG_PM
-    u32                         pci_state[16];
+	u32                         pci_state[16];
 #endif
 
 // netdev
-    struct net_device*          dev;
-    struct net_device*          next_module;
-    struct net_device_stats     stats;
+	struct net_device *dev;
+	struct net_device *next_module;
+	struct net_device_stats     stats;
 
 //dma addr, rx/tx pool
-    dma_addr_t                  pool_dma;
-    dma_addr_t                  rd0_pool_dma;
-    dma_addr_t                  rd1_pool_dma;
+	dma_addr_t                  pool_dma;
+	dma_addr_t                  rd0_pool_dma;
+	dma_addr_t                  rd1_pool_dma;
 
-    dma_addr_t                  td0_pool_dma;
-    dma_addr_t                  td1_pool_dma;
+	dma_addr_t                  td0_pool_dma;
+	dma_addr_t                  td1_pool_dma;
 
-    dma_addr_t                  tx_bufs_dma0;
-    dma_addr_t                  tx_bufs_dma1;
-    dma_addr_t                  tx_beacon_dma;
+	dma_addr_t                  tx_bufs_dma0;
+	dma_addr_t                  tx_bufs_dma1;
+	dma_addr_t                  tx_beacon_dma;
 
-    unsigned char *tx0_bufs;
-    unsigned char *tx1_bufs;
-    unsigned char *tx_beacon_bufs;
+	unsigned char *tx0_bufs;
+	unsigned char *tx1_bufs;
+	unsigned char *tx_beacon_bufs;
 
-    CHIP_TYPE                   chip_id;
+	CHIP_TYPE                   chip_id;
 
-    unsigned long               PortOffset;
-    unsigned long dwIsr;
-    u32                         memaddr;
-    u32                         ioaddr;
-    u32                         io_size;
+	unsigned long               PortOffset;
+	unsigned long dwIsr;
+	u32                         memaddr;
+	u32                         ioaddr;
+	u32                         io_size;
 
-    unsigned char byRevId;
-    unsigned short SubSystemID;
-    unsigned short SubVendorID;
+	unsigned char byRevId;
+	unsigned short SubSystemID;
+	unsigned short SubVendorID;
 
-    int                         nTxQueues;
-    volatile int                iTDUsed[TYPE_MAXTD];
+	int                         nTxQueues;
+	volatile int                iTDUsed[TYPE_MAXTD];
 
-    volatile PSTxDesc           apCurrTD[TYPE_MAXTD];
-    volatile PSTxDesc           apTailTD[TYPE_MAXTD];
+	volatile PSTxDesc           apCurrTD[TYPE_MAXTD];
+	volatile PSTxDesc           apTailTD[TYPE_MAXTD];
 
-    volatile PSTxDesc           apTD0Rings;
-    volatile PSTxDesc           apTD1Rings;
+	volatile PSTxDesc           apTD0Rings;
+	volatile PSTxDesc           apTD1Rings;
 
-    volatile PSRxDesc           aRD0Ring;
-    volatile PSRxDesc           aRD1Ring;
-    volatile PSRxDesc           pCurrRD[TYPE_MAXRD];
-    SCache                      sDupRxCache;
+	volatile PSRxDesc           aRD0Ring;
+	volatile PSRxDesc           aRD1Ring;
+	volatile PSRxDesc           pCurrRD[TYPE_MAXRD];
+	SCache                      sDupRxCache;
 
-    SDeFragControlBlock         sRxDFCB[CB_MAX_RX_FRAG];
-    unsigned int	cbDFCB;
-    unsigned int	cbFreeDFCB;
-    unsigned int	uCurrentDFCBIdx;
+	SDeFragControlBlock         sRxDFCB[CB_MAX_RX_FRAG];
+	unsigned int	cbDFCB;
+	unsigned int	cbFreeDFCB;
+	unsigned int	uCurrentDFCBIdx;
 
-    OPTIONS                     sOpts;
+	OPTIONS                     sOpts;
 
-    u32                         flags;
+	u32                         flags;
 
-    u32                         rx_buf_sz;
-    int                         multicast_limit;
-    unsigned char byRxMode;
+	u32                         rx_buf_sz;
+	int                         multicast_limit;
+	unsigned char byRxMode;
 
-    spinlock_t                  lock;
+	spinlock_t                  lock;
 //PLICE_DEBUG->
-	struct	tasklet_struct 		RxMngWorkItem;
+	struct	tasklet_struct	RxMngWorkItem;
 	RxManagementQueue	rxManeQueue;
 //PLICE_DEBUG<-
 //PLICE_DEBUG ->
-	pid_t				MLMEThr_pid;
-	struct 	completion	notify;
-	struct 	semaphore	mlme_semaphore;
+	pid_t			MLMEThr_pid;
+	struct completion	notify;
+	struct semaphore	mlme_semaphore;
 //PLICE_DEBUG <-
 
-
-    u32                         rx_bytes;
-
-    // Version control
-    unsigned char byLocalID;
-    unsigned char byRFType;
-
-    unsigned char byMaxPwrLevel;
-    unsigned char byZoneType;
-    bool bZoneRegExist;
-   unsigned char byOriginalZonetype;
-    unsigned char abyMacContext[MAC_MAX_CONTEXT_REG];
-    bool bLinkPass;          // link status: OK or fail
-    unsigned char abyCurrentNetAddr[ETH_ALEN];
-
-    // Adapter statistics
-    SStatCounter                scStatistic;
-    // 802.11 counter
-    SDot11Counters              s802_11Counter;
-
-
-    // 802.11 management
-    PSMgmtObject                pMgmt;
-    SMgmtObject                 sMgmtObj;
-
-    // 802.11 MAC specific
-    unsigned int	uCurrRSSI;
-    unsigned char byCurrSQ;
-
-    unsigned long dwTxAntennaSel;
-    unsigned long dwRxAntennaSel;
-    unsigned char byAntennaCount;
-    unsigned char byRxAntennaMode;
-    unsigned char byTxAntennaMode;
-    bool bTxRxAntInv;
-
-    unsigned char *pbyTmpBuff;
-    unsigned int	uSIFS;    //Current SIFS
-    unsigned int	uDIFS;    //Current DIFS
-    unsigned int	uEIFS;    //Current EIFS
-    unsigned int	uSlot;    //Current SlotTime
-    unsigned int	uCwMin;   //Current CwMin
-    unsigned int	uCwMax;   //CwMax is fixed on 1023.
-    // PHY parameter
-    unsigned char bySIFS;
-    unsigned char byDIFS;
-    unsigned char byEIFS;
-    unsigned char bySlot;
-    unsigned char byCWMaxMin;
-    CARD_PHY_TYPE               eCurrentPHYType;
-
-
-    VIA_BB_TYPE                 byBBType; //0: 11A, 1:11B, 2:11G
-    VIA_PKT_TYPE                byPacketType; //0:11a,1:11b,2:11gb(only CCK in BasicRate),3:11ga(OFDM in Basic Rate)
-    unsigned short wBasicRate;
-    unsigned char byACKRate;
-    unsigned char byTopOFDMBasicRate;
-    unsigned char byTopCCKBasicRate;
-
-    unsigned char byMinChannel;
-    unsigned char byMaxChannel;
-    unsigned int	uConnectionRate;
-
-    unsigned char byPreambleType;
-    unsigned char byShortPreamble;
-
-    unsigned short wCurrentRate;
-    unsigned short wRTSThreshold;
-    unsigned short wFragmentationThreshold;
-    unsigned char byShortRetryLimit;
-    unsigned char byLongRetryLimit;
-    CARD_OP_MODE                eOPMode;
-    unsigned char byOpMode;
-    bool bBSSIDFilter;
-    unsigned short wMaxTransmitMSDULifetime;
-    unsigned char abyBSSID[ETH_ALEN];
-    unsigned char abyDesireBSSID[ETH_ALEN];
-    unsigned short wCTSDuration;       // update while speed change
-    unsigned short wACKDuration;       // update while speed change
-    unsigned short wRTSTransmitLen;    // update while speed change
-    unsigned char byRTSServiceField;  // update while speed change
-    unsigned char byRTSSignalField;   // update while speed change
-
-    unsigned long dwMaxReceiveLifetime;       // dot11MaxReceiveLifetime
-
-    bool bCCK;
-    bool bEncryptionEnable;
-    bool bLongHeader;
-    bool bShortSlotTime;
-    bool bProtectMode;
-    bool bNonERPPresent;
-    bool bBarkerPreambleMd;
-
-    unsigned char byERPFlag;
-    unsigned short wUseProtectCntDown;
-
-    bool bRadioControlOff;
-    bool bRadioOff;
-    bool bEnablePSMode;
-    unsigned short wListenInterval;
-    bool bPWBitOn;
-    WMAC_POWER_MODE         ePSMode;
-
-
-    // GPIO Radio Control
-    unsigned char byRadioCtl;
-    unsigned char byGPIO;
-    bool bHWRadioOff;
-    bool bPrvActive4RadioOFF;
-    bool bGPIOBlockRead;
-
-    // Beacon related
-    unsigned short wSeqCounter;
-    unsigned short wBCNBufLen;
-    bool bBeaconBufReady;
-    bool bBeaconSent;
-    bool bIsBeaconBufReadySet;
-    unsigned int	cbBeaconBufReadySetCnt;
-    bool bFixRate;
-    unsigned char byCurrentCh;
-    unsigned int	uScanTime;
-
-    CMD_STATE               eCommandState;
-
-    CMD_CODE                eCommand;
-    bool bBeaconTx;
-
-    bool bStopBeacon;
-    bool bStopDataPkt;
-    bool bStopTx0Pkt;
-    unsigned int	uAutoReConnectTime;
-
-    // 802.11 counter
-
-    CMD_ITEM                eCmdQueue[CMD_Q_SIZE];
-    unsigned int	uCmdDequeueIdx;
-    unsigned int	uCmdEnqueueIdx;
-    unsigned int	cbFreeCmdQueue;
-    bool bCmdRunning;
-    bool bCmdClear;
-
-
-
-    bool bRoaming;
-    //WOW
-    unsigned char abyIPAddr[4];
-
-    unsigned long ulTxPower;
-    NDIS_802_11_WEP_STATUS  eEncryptionStatus;
-    bool bTransmitKey;
+	u32                         rx_bytes;
+
+	// Version control
+	unsigned char byLocalID;
+	unsigned char byRFType;
+
+	unsigned char byMaxPwrLevel;
+	unsigned char byZoneType;
+	bool bZoneRegExist;
+	unsigned char byOriginalZonetype;
+	unsigned char abyMacContext[MAC_MAX_CONTEXT_REG];
+	bool bLinkPass;          // link status: OK or fail
+	unsigned char abyCurrentNetAddr[ETH_ALEN];
+
+	// Adapter statistics
+	SStatCounter                scStatistic;
+	// 802.11 counter
+	SDot11Counters              s802_11Counter;
+
+	// 802.11 management
+	PSMgmtObject                pMgmt;
+	SMgmtObject                 sMgmtObj;
+
+	// 802.11 MAC specific
+	unsigned int	uCurrRSSI;
+	unsigned char byCurrSQ;
+
+	unsigned long dwTxAntennaSel;
+	unsigned long dwRxAntennaSel;
+	unsigned char byAntennaCount;
+	unsigned char byRxAntennaMode;
+	unsigned char byTxAntennaMode;
+	bool bTxRxAntInv;
+
+	unsigned char *pbyTmpBuff;
+	unsigned int	uSIFS;    //Current SIFS
+	unsigned int	uDIFS;    //Current DIFS
+	unsigned int	uEIFS;    //Current EIFS
+	unsigned int	uSlot;    //Current SlotTime
+	unsigned int	uCwMin;   //Current CwMin
+	unsigned int	uCwMax;   //CwMax is fixed on 1023.
+	// PHY parameter
+	unsigned char bySIFS;
+	unsigned char byDIFS;
+	unsigned char byEIFS;
+	unsigned char bySlot;
+	unsigned char byCWMaxMin;
+	CARD_PHY_TYPE               eCurrentPHYType;
+
+	VIA_BB_TYPE                 byBBType; //0: 11A, 1:11B, 2:11G
+	VIA_PKT_TYPE                byPacketType; //0:11a,1:11b,2:11gb(only CCK in BasicRate),3:11ga(OFDM in Basic Rate)
+	unsigned short wBasicRate;
+	unsigned char byACKRate;
+	unsigned char byTopOFDMBasicRate;
+	unsigned char byTopCCKBasicRate;
+
+	unsigned char byMinChannel;
+	unsigned char byMaxChannel;
+	unsigned int	uConnectionRate;
+
+	unsigned char byPreambleType;
+	unsigned char byShortPreamble;
+
+	unsigned short wCurrentRate;
+	unsigned short wRTSThreshold;
+	unsigned short wFragmentationThreshold;
+	unsigned char byShortRetryLimit;
+	unsigned char byLongRetryLimit;
+	CARD_OP_MODE                eOPMode;
+	unsigned char byOpMode;
+	bool bBSSIDFilter;
+	unsigned short wMaxTransmitMSDULifetime;
+	unsigned char abyBSSID[ETH_ALEN];
+	unsigned char abyDesireBSSID[ETH_ALEN];
+	unsigned short wCTSDuration;       // update while speed change
+	unsigned short wACKDuration;       // update while speed change
+	unsigned short wRTSTransmitLen;    // update while speed change
+	unsigned char byRTSServiceField;  // update while speed change
+	unsigned char byRTSSignalField;   // update while speed change
+
+	unsigned long dwMaxReceiveLifetime;       // dot11MaxReceiveLifetime
+
+	bool bCCK;
+	bool bEncryptionEnable;
+	bool bLongHeader;
+	bool bShortSlotTime;
+	bool bProtectMode;
+	bool bNonERPPresent;
+	bool bBarkerPreambleMd;
+
+	unsigned char byERPFlag;
+	unsigned short wUseProtectCntDown;
+
+	bool bRadioControlOff;
+	bool bRadioOff;
+	bool bEnablePSMode;
+	unsigned short wListenInterval;
+	bool bPWBitOn;
+	WMAC_POWER_MODE         ePSMode;
+
+	// GPIO Radio Control
+	unsigned char byRadioCtl;
+	unsigned char byGPIO;
+	bool bHWRadioOff;
+	bool bPrvActive4RadioOFF;
+	bool bGPIOBlockRead;
+
+	// Beacon related
+	unsigned short wSeqCounter;
+	unsigned short wBCNBufLen;
+	bool bBeaconBufReady;
+	bool bBeaconSent;
+	bool bIsBeaconBufReadySet;
+	unsigned int	cbBeaconBufReadySetCnt;
+	bool bFixRate;
+	unsigned char byCurrentCh;
+	unsigned int	uScanTime;
+
+	CMD_STATE               eCommandState;
+
+	CMD_CODE                eCommand;
+	bool bBeaconTx;
+
+	bool bStopBeacon;
+	bool bStopDataPkt;
+	bool bStopTx0Pkt;
+	unsigned int	uAutoReConnectTime;
+
+	// 802.11 counter
+
+	CMD_ITEM                eCmdQueue[CMD_Q_SIZE];
+	unsigned int	uCmdDequeueIdx;
+	unsigned int	uCmdEnqueueIdx;
+	unsigned int	cbFreeCmdQueue;
+	bool bCmdRunning;
+	bool bCmdClear;
+
+	bool bRoaming;
+	//WOW
+	unsigned char abyIPAddr[4];
+
+	unsigned long ulTxPower;
+	NDIS_802_11_WEP_STATUS  eEncryptionStatus;
+	bool bTransmitKey;
 //2007-0925-01<Add>by MikeLiu
 //mike add :save old Encryption
-    NDIS_802_11_WEP_STATUS  eOldEncryptionStatus;
-
-    SKeyManagement          sKey;
-    unsigned long dwIVCounter;
-
-    QWORD                   qwPacketNumber; //For CCMP and TKIP as TSC(6 bytes)
-    unsigned int	uCurrentWEPMode;
-
-    RC4Ext                  SBox;
-    unsigned char abyPRNG[WLAN_WEPMAX_KEYLEN+3];
-    unsigned char byKeyIndex;
-    unsigned int	uKeyLength;
-    unsigned char abyKey[WLAN_WEP232_KEYLEN];
-
-    bool bAES;
-    unsigned char byCntMeasure;
-
-    // for AP mode
-    unsigned int	uAssocCount;
-    bool bMoreData;
-
-    // QoS
-    bool bGrpAckPolicy;
-
-    // for OID_802_11_ASSOCIATION_INFORMATION
-    bool bAssocInfoSet;
-
-
-    unsigned char byAutoFBCtrl;
-
-    bool bTxMICFail;
-    bool bRxMICFail;
-
-
-    unsigned int	uRATEIdx;
-
-
-    // For Update BaseBand VGA Gain Offset
-    bool bUpdateBBVGA;
-    unsigned int	uBBVGADiffCount;
-    unsigned char byBBVGANew;
-    unsigned char byBBVGACurrent;
-    unsigned char abyBBVGA[BB_VGA_LEVEL];
-    long                    ldBmThreshold[BB_VGA_LEVEL];
-
-    unsigned char byBBPreEDRSSI;
-    unsigned char byBBPreEDIndex;
-
-
-    bool bRadioCmd;
-    unsigned long dwDiagRefCount;
-
-    // For FOE Tuning
-    unsigned char byFOETuning;
-
-    // For Auto Power Tunning
-
-    unsigned char byAutoPwrTunning;
-    short                   sPSetPointCCK;
-    short                   sPSetPointOFDMG;
-    short                   sPSetPointOFDMA;
-    long                    lPFormulaOffset;
-    short                   sPThreshold;
-    char                    cAdjustStep;
-    char                    cMinTxAGC;
-
-    // For RF Power table
-    unsigned char byCCKPwr;
-    unsigned char byOFDMPwrG;
-    unsigned char byCurPwr;
-    char	 byCurPwrdBm;
-    unsigned char abyCCKPwrTbl[CB_MAX_CHANNEL_24G+1];
-    unsigned char abyOFDMPwrTbl[CB_MAX_CHANNEL+1];
-    char	abyCCKDefaultPwr[CB_MAX_CHANNEL_24G+1];
-    char	abyOFDMDefaultPwr[CB_MAX_CHANNEL+1];
-    char	abyRegPwr[CB_MAX_CHANNEL+1];
-    char	abyLocalPwr[CB_MAX_CHANNEL+1];
-
-
-    // BaseBand Loopback Use
-    unsigned char byBBCR4d;
-    unsigned char byBBCRc9;
-    unsigned char byBBCR88;
-    unsigned char byBBCR09;
-
-    // command timer
-    struct timer_list       sTimerCommand;
+	NDIS_802_11_WEP_STATUS  eOldEncryptionStatus;
+
+	SKeyManagement          sKey;
+	unsigned long dwIVCounter;
+
+	QWORD                   qwPacketNumber; //For CCMP and TKIP as TSC(6 bytes)
+	unsigned int	uCurrentWEPMode;
+
+	RC4Ext                  SBox;
+	unsigned char abyPRNG[WLAN_WEPMAX_KEYLEN+3];
+	unsigned char byKeyIndex;
+	unsigned int	uKeyLength;
+	unsigned char abyKey[WLAN_WEP232_KEYLEN];
+
+	bool bAES;
+	unsigned char byCntMeasure;
+
+	// for AP mode
+	unsigned int	uAssocCount;
+	bool bMoreData;
+
+	// QoS
+	bool bGrpAckPolicy;
+
+	// for OID_802_11_ASSOCIATION_INFORMATION
+	bool bAssocInfoSet;
+
+	unsigned char byAutoFBCtrl;
+
+	bool bTxMICFail;
+	bool bRxMICFail;
+
+	unsigned int	uRATEIdx;
+
+	// For Update BaseBand VGA Gain Offset
+	bool bUpdateBBVGA;
+	unsigned int	uBBVGADiffCount;
+	unsigned char byBBVGANew;
+	unsigned char byBBVGACurrent;
+	unsigned char abyBBVGA[BB_VGA_LEVEL];
+	long                    ldBmThreshold[BB_VGA_LEVEL];
+
+	unsigned char byBBPreEDRSSI;
+	unsigned char byBBPreEDIndex;
+
+	bool bRadioCmd;
+	unsigned long dwDiagRefCount;
+
+	// For FOE Tuning
+	unsigned char byFOETuning;
+
+	// For Auto Power Tunning
+
+	unsigned char byAutoPwrTunning;
+	short                   sPSetPointCCK;
+	short                   sPSetPointOFDMG;
+	short                   sPSetPointOFDMA;
+	long                    lPFormulaOffset;
+	short                   sPThreshold;
+	char                    cAdjustStep;
+	char                    cMinTxAGC;
+
+	// For RF Power table
+	unsigned char byCCKPwr;
+	unsigned char byOFDMPwrG;
+	unsigned char byCurPwr;
+	char	 byCurPwrdBm;
+	unsigned char abyCCKPwrTbl[CB_MAX_CHANNEL_24G+1];
+	unsigned char abyOFDMPwrTbl[CB_MAX_CHANNEL+1];
+	char	abyCCKDefaultPwr[CB_MAX_CHANNEL_24G+1];
+	char	abyOFDMDefaultPwr[CB_MAX_CHANNEL+1];
+	char	abyRegPwr[CB_MAX_CHANNEL+1];
+	char	abyLocalPwr[CB_MAX_CHANNEL+1];
+
+	// BaseBand Loopback Use
+	unsigned char byBBCR4d;
+	unsigned char byBBCRc9;
+	unsigned char byBBCR88;
+	unsigned char byBBCR09;
+
+	// command timer
+	struct timer_list       sTimerCommand;
 #ifdef TxInSleep
-     struct timer_list       sTimerTxData;
-     unsigned long nTxDataTimeCout;
-     bool fTxDataInSleep;
-     bool IsTxDataTrigger;
+	struct timer_list       sTimerTxData;
+	unsigned long nTxDataTimeCout;
+	bool fTxDataInSleep;
+	bool IsTxDataTrigger;
 #endif
 
 #ifdef WPA_SM_Transtatus
-    bool fWPA_Authened;           //is WPA/WPA-PSK or WPA2/WPA2-PSK authen??
+	bool fWPA_Authened;           //is WPA/WPA-PSK or WPA2/WPA2-PSK authen??
 #endif
-    unsigned char byReAssocCount;   //mike add:re-association retry times!
-    unsigned char byLinkWaitCount;
+	unsigned char byReAssocCount;   //mike add:re-association retry times!
+	unsigned char byLinkWaitCount;
 
+	unsigned char abyNodeName[17];
 
-    unsigned char abyNodeName[17];
-
-    bool bDiversityRegCtlON;
-    bool bDiversityEnable;
-    unsigned long ulDiversityNValue;
-    unsigned long ulDiversityMValue;
-    unsigned char byTMax;
-    unsigned char byTMax2;
-    unsigned char byTMax3;
-    unsigned long ulSQ3TH;
+	bool bDiversityRegCtlON;
+	bool bDiversityEnable;
+	unsigned long ulDiversityNValue;
+	unsigned long ulDiversityMValue;
+	unsigned char byTMax;
+	unsigned char byTMax2;
+	unsigned char byTMax3;
+	unsigned long ulSQ3TH;
 
 // ANT diversity
-    unsigned long uDiversityCnt;
-    unsigned char byAntennaState;
-    unsigned long ulRatio_State0;
-    unsigned long ulRatio_State1;
-
-    //SQ3 functions for antenna diversity
-    struct timer_list           TimerSQ3Tmax1;
-    struct timer_list           TimerSQ3Tmax2;
-    struct timer_list           TimerSQ3Tmax3;
-
-
-    unsigned long uNumSQ3[MAX_RATE];
-    unsigned short wAntDiversityMaxRate;
-
-
-    SEthernetHeader         sTxEthHeader;
-    SEthernetHeader         sRxEthHeader;
-    unsigned char abyBroadcastAddr[ETH_ALEN];
-    unsigned char abySNAP_RFC1042[ETH_ALEN];
-    unsigned char abySNAP_Bridgetunnel[ETH_ALEN];
-     unsigned char abyEEPROM[EEP_MAX_CONTEXT_SIZE];  //unsigned long alignment
-    // Pre-Authentication & PMK cache
-    SPMKID                  gsPMKID;
-    SPMKIDCandidateEvent    gsPMKIDCandidate;
-
-
-    // for 802.11h
-    bool b11hEnable;
-    unsigned char abyCountryCode[3];
-    // for 802.11h DFS
-    unsigned int	uNumOfMeasureEIDs;
-    PWLAN_IE_MEASURE_REQ    pCurrMeasureEID;
-    bool bMeasureInProgress;
-    unsigned char byOrgChannel;
-    unsigned char byOrgRCR;
-    unsigned long dwOrgMAR0;
-    unsigned long dwOrgMAR4;
-    unsigned char byBasicMap;
-    unsigned char byCCAFraction;
-    unsigned char abyRPIs[8];
-    unsigned long dwRPIs[8];
-    bool bChannelSwitch;
-    unsigned char byNewChannel;
-    unsigned char byChannelSwitchCount;
-    bool bQuietEnable;
-    bool bEnableFirstQuiet;
-    unsigned char byQuietStartCount;
-    unsigned int	uQuietEnqueue;
-    unsigned long dwCurrentQuietEndTime;
-    SQuietControl           sQuiet[MAX_QUIET_COUNT];
-    // for 802.11h TPC
-    bool bCountryInfo5G;
-    bool bCountryInfo24G;
-
-    unsigned short wBeaconInterval;
-
-    //WPA supplicant deamon
+	unsigned long uDiversityCnt;
+	unsigned char byAntennaState;
+	unsigned long ulRatio_State0;
+	unsigned long ulRatio_State1;
+
+	//SQ3 functions for antenna diversity
+	struct timer_list           TimerSQ3Tmax1;
+	struct timer_list           TimerSQ3Tmax2;
+	struct timer_list           TimerSQ3Tmax3;
+
+	unsigned long uNumSQ3[MAX_RATE];
+	unsigned short wAntDiversityMaxRate;
+
+	SEthernetHeader         sTxEthHeader;
+	SEthernetHeader         sRxEthHeader;
+	unsigned char abyBroadcastAddr[ETH_ALEN];
+	unsigned char abySNAP_RFC1042[ETH_ALEN];
+	unsigned char abySNAP_Bridgetunnel[ETH_ALEN];
+	unsigned char abyEEPROM[EEP_MAX_CONTEXT_SIZE];  //unsigned long alignment
+	// Pre-Authentication & PMK cache
+	SPMKID                  gsPMKID;
+	SPMKIDCandidateEvent    gsPMKIDCandidate;
+
+	// for 802.11h
+	bool b11hEnable;
+	unsigned char abyCountryCode[3];
+	// for 802.11h DFS
+	unsigned int	uNumOfMeasureEIDs;
+	PWLAN_IE_MEASURE_REQ    pCurrMeasureEID;
+	bool bMeasureInProgress;
+	unsigned char byOrgChannel;
+	unsigned char byOrgRCR;
+	unsigned long dwOrgMAR0;
+	unsigned long dwOrgMAR4;
+	unsigned char byBasicMap;
+	unsigned char byCCAFraction;
+	unsigned char abyRPIs[8];
+	unsigned long dwRPIs[8];
+	bool bChannelSwitch;
+	unsigned char byNewChannel;
+	unsigned char byChannelSwitchCount;
+	bool bQuietEnable;
+	bool bEnableFirstQuiet;
+	unsigned char byQuietStartCount;
+	unsigned int	uQuietEnqueue;
+	unsigned long dwCurrentQuietEndTime;
+	SQuietControl           sQuiet[MAX_QUIET_COUNT];
+	// for 802.11h TPC
+	bool bCountryInfo5G;
+	bool bCountryInfo24G;
+
+	unsigned short wBeaconInterval;
+
+	//WPA supplicant deamon
 	struct net_device       *wpadev;
 	bool bWPADEVUp;
-    struct sk_buff          *skb;
+	struct sk_buff          *skb;
 #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
 /*
-        bool bwextstep0;
-        bool bwextstep1;
-        bool bwextstep2;
-        bool bwextstep3;
-        */
-        unsigned int	bwextcount;
-        bool bWPASuppWextEnabled;
+  bool bwextstep0;
+  bool bwextstep1;
+  bool bwextstep2;
+  bool bwextstep3;
+*/
+	unsigned int	bwextcount;
+	bool bWPASuppWextEnabled;
 #endif
 
-    //--
+	//--
 #ifdef HOSTAP
-    // user space daemon: hostapd, is used for HOSTAP
+	// user space daemon: hostapd, is used for HOSTAP
 	bool bEnableHostapd;
 	bool bEnable8021x;
 	bool bEnableHostWEP;
 	struct net_device       *apdev;
 	int (*tx_80211)(struct sk_buff *skb, struct net_device *dev);
 #endif
-    unsigned int	uChannel;
-    bool bMACSuspend;
+	unsigned int	uChannel;
+	bool bMACSuspend;
 
 	struct iw_statistics	wstats;		// wireless stats
-    bool bCommit;
-
+	bool bCommit;
 } DEVICE_INFO, *PSDevice;
 
-
 //PLICE_DEBUG->
 
-
- inline  static	void   EnQueue (PSDevice pDevice,PSRxMgmtPacket  pRxMgmtPacket)
+inline  static	void   EnQueue(PSDevice pDevice, PSRxMgmtPacket  pRxMgmtPacket)
 {
-	//printk("Enter EnQueue:tail is %d\n",pDevice->rxManeQueue.tail);
-	if ((pDevice->rxManeQueue.tail+1) % NUM == pDevice->rxManeQueue.head)
-	{
-		//printk("Queue is Full,tail is %d\n",pDevice->rxManeQueue.tail);
-		return ;
-	}
-	else
-	{
-		pDevice->rxManeQueue.tail = (pDevice->rxManeQueue.tail+1)% NUM;
+	if ((pDevice->rxManeQueue.tail+1) % NUM == pDevice->rxManeQueue.head) {
+		return;
+	} else {
+		pDevice->rxManeQueue.tail = (pDevice->rxManeQueue.tail + 1) % NUM;
 		pDevice->rxManeQueue.Q[pDevice->rxManeQueue.tail] = pRxMgmtPacket;
 		pDevice->rxManeQueue.packet_num++;
-		//printk("packet num is %d\n",pDevice->rxManeQueue.packet_num);
 	}
 }
 
-
-
-
-	inline  static  PSRxMgmtPacket DeQueue (PSDevice pDevice)
+inline  static  PSRxMgmtPacket DeQueue(PSDevice pDevice)
 {
 	PSRxMgmtPacket  pRxMgmtPacket;
-	if (pDevice->rxManeQueue.tail == pDevice->rxManeQueue.head)
-	{
+	if (pDevice->rxManeQueue.tail == pDevice->rxManeQueue.head) {
 		printk("Queue is Empty\n");
 		return NULL;
-	}
-	else
-	{
+	} else {
 		int	x;
 		//x=pDevice->rxManeQueue.head = (pDevice->rxManeQueue.head+1)%NUM;
 		pDevice->rxManeQueue.head = (pDevice->rxManeQueue.head+1)%NUM;
 		x = pDevice->rxManeQueue.head;
-		//printk("Enter DeQueue:head is %d\n",x);
 		pRxMgmtPacket = pDevice->rxManeQueue.Q[x];
 		pDevice->rxManeQueue.packet_num--;
 		return pRxMgmtPacket;
@@ -856,31 +800,22 @@ typedef struct __device_info {
 
 void	InitRxManagementQueue(PSDevice   pDevice);
 
-
-
 //PLICE_DEBUG<-
 
-
-
-
-
-
 inline static bool device_get_ip(PSDevice pInfo) {
-    struct in_device* in_dev=(struct in_device*) pInfo->dev->ip_ptr;
-    struct in_ifaddr* ifa;
-
-    if (in_dev!=NULL) {
-        ifa=(struct in_ifaddr*) in_dev->ifa_list;
-        if (ifa!=NULL) {
-            memcpy(pInfo->abyIPAddr,&ifa->ifa_address,4);
-            return true;
-        }
-    }
-    return false;
+	struct in_device *in_dev = (struct in_device *)pInfo->dev->ip_ptr;
+	struct in_ifaddr *ifa;
+
+	if (in_dev != NULL) {
+		ifa = (struct in_ifaddr *)in_dev->ifa_list;
+		if (ifa != NULL) {
+			memcpy(pInfo->abyIPAddr, &ifa->ifa_address, 4);
+			return true;
+		}
+	}
+	return false;
 }
 
-
-
 static inline PDEVICE_RD_INFO alloc_rd_info(void)
 {
 	return kzalloc(sizeof(DEVICE_RD_INFO), GFP_ATOMIC);
@@ -897,5 +832,3 @@ bool device_dma0_xmit(PSDevice pDevice, struct sk_buff *skb, unsigned int uNodeI
 bool device_alloc_frag_buf(PSDevice pDevice, PSDeFragControlBlock pDeF);
 int Config_FileOperation(PSDevice pDevice, bool fwrite, unsigned char *Parameter);
 #endif
-
-
diff --git a/drivers/staging/vt6655/device_cfg.h b/drivers/staging/vt6655/device_cfg.h
index 408edc2..1137ade 100644
--- a/drivers/staging/vt6655/device_cfg.h
+++ b/drivers/staging/vt6655/device_cfg.h
@@ -34,9 +34,9 @@
 
 typedef
 struct _version {
-    unsigned char   major;
-    unsigned char   minor;
-    unsigned char   build;
+	unsigned char   major;
+	unsigned char   minor;
+	unsigned char   build;
 } version_t, *pversion_t;
 
 #define VID_TABLE_SIZE      64
@@ -70,31 +70,26 @@ struct _version {
 //Max: 2378=2312Payload + 30HD +4CRC + 2Padding + 4Len + 8TSF + 4RSR
 #define PKT_BUF_SZ          2390
 
-
 #define MAX_UINTS           8
 #define OPTION_DEFAULT      { [0 ... MAX_UINTS-1] = -1}
 
-
-
-typedef enum  _chip_type{
-    VT3253=1
+typedef enum  _chip_type {
+	VT3253 = 1
 } CHIP_TYPE, *PCHIP_TYPE;
 
-
-
 #ifdef VIAWET_DEBUG
-#define ASSERT(x) { \
-    if (!(x)) { \
-        printk(KERN_ERR "assertion %s failed: file %s line %d\n", #x,\
-        __FUNCTION__, __LINE__);\
-        *(int*) 0=0;\
-    }\
-}
+#define ASSERT(x)							\
+do {									\
+	if (!(x)) {							\
+		printk(KERN_ERR "assertion %s failed: file %s line %d\n", \
+		       #x, __func__, __LINE__);				\
+		*(int *)0 = 0;						\
+	}								\
+} while (0)
 #define DBG_PORT80(value)                   outb(value, 0x80)
 #else
 #define ASSERT(x)
 #define DBG_PORT80(value)
 #endif
 
-
 #endif
diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c
index 453c83d..be4f6c2 100644
--- a/drivers/staging/vt6655/device_main.c
+++ b/drivers/staging/vt6655/device_main.c
@@ -98,52 +98,50 @@ MODULE_AUTHOR("VIA Networking Technologies, Inc., <lyndonchen@vntek.com.tw>");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("VIA Networking Solomon-A/B/G Wireless LAN Adapter Driver");
 
-	static int mlme_kill;
-	//static  struct task_struct * mlme_task;
+static int mlme_kill;
+//static  struct task_struct * mlme_task;
 
-#define DEVICE_PARAM(N,D)
+#define DEVICE_PARAM(N, D)
 /*
-        static const int N[MAX_UINTS]=OPTION_DEFAULT;\
-        MODULE_PARM(N, "1-" __MODULE_STRING(MAX_UINTS) "i");\
-        MODULE_PARM_DESC(N, D);
+  static const int N[MAX_UINTS]=OPTION_DEFAULT;\
+  MODULE_PARM(N, "1-" __MODULE_STRING(MAX_UINTS) "i");\
+  MODULE_PARM_DESC(N, D);
 */
 
 #define RX_DESC_MIN0     16
 #define RX_DESC_MAX0     128
 #define RX_DESC_DEF0     32
-DEVICE_PARAM(RxDescriptors0,"Number of receive descriptors0");
+DEVICE_PARAM(RxDescriptors0, "Number of receive descriptors0");
 
 #define RX_DESC_MIN1     16
 #define RX_DESC_MAX1     128
 #define RX_DESC_DEF1     32
-DEVICE_PARAM(RxDescriptors1,"Number of receive descriptors1");
+DEVICE_PARAM(RxDescriptors1, "Number of receive descriptors1");
 
 #define TX_DESC_MIN0     16
 #define TX_DESC_MAX0     128
 #define TX_DESC_DEF0     32
-DEVICE_PARAM(TxDescriptors0,"Number of transmit descriptors0");
+DEVICE_PARAM(TxDescriptors0, "Number of transmit descriptors0");
 
 #define TX_DESC_MIN1     16
 #define TX_DESC_MAX1     128
 #define TX_DESC_DEF1     64
-DEVICE_PARAM(TxDescriptors1,"Number of transmit descriptors1");
-
+DEVICE_PARAM(TxDescriptors1, "Number of transmit descriptors1");
 
 #define IP_ALIG_DEF     0
 /* IP_byte_align[] is used for IP header unsigned long byte aligned
    0: indicate the IP header won't be unsigned long byte aligned.(Default) .
    1: indicate the IP header will be unsigned long byte aligned.
-      In some environment, the IP header should be unsigned long byte aligned,
-      or the packet will be droped when we receive it. (eg: IPVS)
+   In some environment, the IP header should be unsigned long byte aligned,
+   or the packet will be droped when we receive it. (eg: IPVS)
 */
-DEVICE_PARAM(IP_byte_align,"Enable IP header dword aligned");
-
+DEVICE_PARAM(IP_byte_align, "Enable IP header dword aligned");
 
 #define INT_WORKS_DEF   20
 #define INT_WORKS_MIN   10
 #define INT_WORKS_MAX   64
 
-DEVICE_PARAM(int_works,"Number of packets per interrupt services");
+DEVICE_PARAM(int_works, "Number of packets per interrupt services");
 
 #define CHANNEL_MIN     1
 #define CHANNEL_MAX     14
@@ -151,7 +149,6 @@ DEVICE_PARAM(int_works,"Number of packets per interrupt services");
 
 DEVICE_PARAM(Channel, "Channel number");
 
-
 /* PreambleType[] is the preamble length used for transmit.
    0: indicate allows long preamble type
    1: indicate allows short preamble type
@@ -161,21 +158,18 @@ DEVICE_PARAM(Channel, "Channel number");
 
 DEVICE_PARAM(PreambleType, "Preamble Type");
 
-
 #define RTS_THRESH_MIN     512
 #define RTS_THRESH_MAX     2347
 #define RTS_THRESH_DEF     2347
 
 DEVICE_PARAM(RTSThreshold, "RTS threshold");
 
-
 #define FRAG_THRESH_MIN     256
 #define FRAG_THRESH_MAX     2346
 #define FRAG_THRESH_DEF     2346
 
 DEVICE_PARAM(FragThreshold, "Fragmentation threshold");
 
-
 #define DATA_RATE_MIN     0
 #define DATA_RATE_MAX     13
 #define DATA_RATE_DEF     13
@@ -190,10 +184,10 @@ DEVICE_PARAM(FragThreshold, "Fragmentation threshold");
    7: indicate 18 Mbps  0x24
    8: indicate 24 Mbps  0x30
    9: indicate 36 Mbps  0x48
-  10: indicate 48 Mbps  0x60
-  11: indicate 54 Mbps  0x6c
-  12: indicate 72 Mbps  0x90
-  13: indicate auto rate
+   10: indicate 48 Mbps  0x60
+   11: indicate 54 Mbps  0x6c
+   12: indicate 72 Mbps  0x90
+   13: indicate auto rate
 */
 
 DEVICE_PARAM(ConnectionRate, "Connection data rate");
@@ -208,7 +202,6 @@ DEVICE_PARAM(OPMode, "Infrastruct, adhoc, AP mode ");
    2: indicate AP mode used
 */
 
-
 /* PSMode[]
    0: indicate disable power saving mode
    1: indicate enable power saving mode
@@ -218,22 +211,18 @@ DEVICE_PARAM(OPMode, "Infrastruct, adhoc, AP mode ");
 
 DEVICE_PARAM(PSMode, "Power saving mode");
 
-
 #define SHORT_RETRY_MIN     0
 #define SHORT_RETRY_MAX     31
 #define SHORT_RETRY_DEF     8
 
-
 DEVICE_PARAM(ShortRetryLimit, "Short frame retry limits");
 
 #define LONG_RETRY_MIN     0
 #define LONG_RETRY_MAX     15
 #define LONG_RETRY_DEF     4
 
-
 DEVICE_PARAM(LongRetryLimit, "long frame retry limits");
 
-
 /* BasebandType[] baseband type selected
    0: indicate 802.11a type
    1: indicate 802.11b type
@@ -245,8 +234,6 @@ DEVICE_PARAM(LongRetryLimit, "long frame retry limits");
 
 DEVICE_PARAM(BasebandType, "baseband type");
 
-
-
 /* 80211hEnable[]
    0: indicate disable 802.11h
    1: indicate enable 802.11h
@@ -265,20 +252,18 @@ DEVICE_PARAM(b80211hEnable, "802.11h mode");
 
 DEVICE_PARAM(bDiversityANTEnable, "ANT diversity mode");
 
-
 //
 // Static vars definitions
 //
 
-
-static int          device_nics             =0;
-static PSDevice     pDevice_Infos           =NULL;
+static int          device_nics             = 0;
+static PSDevice     pDevice_Infos           = NULL;
 static struct net_device *root_device_dev = NULL;
 
-static CHIP_INFO chip_info_table[]= {
-    { VT3253,       "VIA Networking Solomon-A/B/G Wireless LAN Adapter ",
-        256, 1,     DEVICE_FLAGS_IP_ALIGN|DEVICE_FLAGS_TX_ALIGN },
-    {0,NULL}
+static CHIP_INFO chip_info_table[] = {
+	{ VT3253,       "VIA Networking Solomon-A/B/G Wireless LAN Adapter ",
+	  256, 1,     DEVICE_FLAGS_IP_ALIGN|DEVICE_FLAGS_TX_ALIGN },
+	{0, NULL}
 };
 
 DEFINE_PCI_DEVICE_TABLE(vt6655_pci_id_table) = {
@@ -288,17 +273,16 @@ DEFINE_PCI_DEVICE_TABLE(vt6655_pci_id_table) = {
 
 /*---------------------  Static Functions  --------------------------*/
 
-
 static int  vt6655_probe(struct pci_dev *pcid, const struct pci_device_id *ent);
-static void vt6655_init_info(struct pci_dev* pcid, PSDevice* ppDevice, PCHIP_INFO);
+static void vt6655_init_info(struct pci_dev *pcid, PSDevice *ppDevice, PCHIP_INFO);
 static void device_free_info(PSDevice pDevice);
-static bool device_get_pci_info(PSDevice, struct pci_dev* pcid);
+static bool device_get_pci_info(PSDevice, struct pci_dev *pcid);
 static void device_print_info(PSDevice pDevice);
 static struct net_device_stats *device_get_stats(struct net_device *dev);
 static void device_init_diversity_timer(PSDevice pDevice);
 static int  device_open(struct net_device *dev);
 static int  device_xmit(struct sk_buff *skb, struct net_device *dev);
-static  irqreturn_t  device_intr(int irq,  void*dev_instance);
+static  irqreturn_t  device_intr(int irq,  void *dev_instance);
 static void device_set_multi(struct net_device *dev);
 static int  device_close(struct net_device *dev);
 static int  device_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
@@ -314,7 +298,6 @@ struct notifier_block device_notifier = {
 };
 #endif
 
-
 static void device_init_rd0_ring(PSDevice pDevice);
 static void device_init_rd1_ring(PSDevice pDevice);
 static void device_init_defrag_cb(PSDevice pDevice);
@@ -338,16 +321,13 @@ static void device_free_rd1_ring(PSDevice pDevice);
 static void device_free_rings(PSDevice pDevice);
 static void device_free_frag_buf(PSDevice pDevice);
 static int Config_FileGetParameter(unsigned char *string,
-		unsigned char *dest, unsigned char *source);
-
+				   unsigned char *dest, unsigned char *source);
 
 /*---------------------  Export Variables  --------------------------*/
 
 /*---------------------  Export Functions  --------------------------*/
 
-
-
-static char* get_chip_name(int chip_id)
+static char *get_chip_name(int chip_id)
 {
 	int i;
 	for (i = 0; chip_info_table[i].name != NULL; i++)
@@ -363,42 +343,41 @@ static void vt6655_remove(struct pci_dev *pcid)
 	if (pDevice == NULL)
 		return;
 	device_free_info(pDevice);
-
 }
 
 /*
-static void
-device_set_int_opt(int *opt, int val, int min, int max, int def,char* name,char* devname) {
-    if (val==-1)
-        *opt=def;
-    else if (val<min || val>max) {
-        DBG_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: the value of parameter %s is invalid, the valid range is (%d-%d)\n" ,
-            devname,name, min,max);
-        *opt=def;
-    } else {
-        DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "%s: set value of parameter %s to %d\n",
-            devname, name, val);
-        *opt=val;
-    }
-}
+  static void
+  device_set_int_opt(int *opt, int val, int min, int max, int def,char* name,char* devname) {
+  if (val==-1)
+  *opt=def;
+  else if (val<min || val>max) {
+  DBG_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: the value of parameter %s is invalid, the valid range is (%d-%d)\n" ,
+  devname,name, min,max);
+  *opt=def;
+  } else {
+  DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "%s: set value of parameter %s to %d\n",
+  devname, name, val);
+  *opt=val;
+  }
+  }
 
-static void
-device_set_bool_opt(unsigned int *opt, int val,bool def,u32 flag, char* name,char* devname) {
-    (*opt)&=(~flag);
-    if (val==-1)
-        *opt|=(def ? flag : 0);
-    else if (val<0 || val>1) {
-        DBG_PRT(MSG_LEVEL_INFO, KERN_NOTICE
-            "%s: the value of parameter %s is invalid, the valid range is (0-1)\n",devname,name);
-        *opt|=(def ? flag : 0);
-    } else {
-        DBG_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: set parameter %s to %s\n",
-            devname,name , val ? "true" : "false");
-        *opt|=(val ? flag : 0);
-    }
-}
+  static void
+  device_set_bool_opt(unsigned int *opt, int val,bool def,u32 flag, char* name,char* devname) {
+  (*opt)&=(~flag);
+  if (val==-1)
+  *opt|=(def ? flag : 0);
+  else if (val<0 || val>1) {
+  DBG_PRT(MSG_LEVEL_INFO, KERN_NOTICE
+  "%s: the value of parameter %s is invalid, the valid range is (0-1)\n",devname,name);
+  *opt|=(def ? flag : 0);
+  } else {
+  DBG_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: set parameter %s to %s\n",
+  devname,name , val ? "true" : "false");
+  *opt|=(val ? flag : 0);
+  }
+  }
 */
-static void device_get_options(PSDevice pDevice, int index, char* devname)
+static void device_get_options(PSDevice pDevice, int index, char *devname)
 {
 	POPTIONS pOpts = &(pDevice->sOpts);
 
@@ -425,472 +404,436 @@ static void device_get_options(PSDevice pDevice, int index, char* devname)
 
 static void
 device_set_options(PSDevice pDevice) {
-
-    unsigned char abyBroadcastAddr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-    unsigned char abySNAP_RFC1042[ETH_ALEN] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00};
-    unsigned char abySNAP_Bridgetunnel[ETH_ALEN] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0xF8};
-
-
-    memcpy(pDevice->abyBroadcastAddr, abyBroadcastAddr, ETH_ALEN);
-    memcpy(pDevice->abySNAP_RFC1042, abySNAP_RFC1042, ETH_ALEN);
-    memcpy(pDevice->abySNAP_Bridgetunnel, abySNAP_Bridgetunnel, ETH_ALEN);
-
-    pDevice->uChannel = pDevice->sOpts.channel_num;
-    pDevice->wRTSThreshold = pDevice->sOpts.rts_thresh;
-    pDevice->wFragmentationThreshold = pDevice->sOpts.frag_thresh;
-    pDevice->byShortRetryLimit = pDevice->sOpts.short_retry;
-    pDevice->byLongRetryLimit = pDevice->sOpts.long_retry;
-    pDevice->wMaxTransmitMSDULifetime = DEFAULT_MSDU_LIFETIME;
-    pDevice->byShortPreamble = (pDevice->sOpts.flags & DEVICE_FLAGS_PREAMBLE_TYPE) ? 1 : 0;
-    pDevice->byOpMode = (pDevice->sOpts.flags & DEVICE_FLAGS_OP_MODE) ? 1 : 0;
-    pDevice->ePSMode = (pDevice->sOpts.flags & DEVICE_FLAGS_PS_MODE) ? 1 : 0;
-    pDevice->b11hEnable = (pDevice->sOpts.flags & DEVICE_FLAGS_80211h_MODE) ? 1 : 0;
-    pDevice->bDiversityRegCtlON = (pDevice->sOpts.flags & DEVICE_FLAGS_DiversityANT) ? 1 : 0;
-    pDevice->uConnectionRate = pDevice->sOpts.data_rate;
-    if (pDevice->uConnectionRate < RATE_AUTO) pDevice->bFixRate = true;
-    pDevice->byBBType = pDevice->sOpts.bbp_type;
-    pDevice->byPacketType = pDevice->byBBType;
+	unsigned char abyBroadcastAddr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+	unsigned char abySNAP_RFC1042[ETH_ALEN] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00};
+	unsigned char abySNAP_Bridgetunnel[ETH_ALEN] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0xF8};
+
+	memcpy(pDevice->abyBroadcastAddr, abyBroadcastAddr, ETH_ALEN);
+	memcpy(pDevice->abySNAP_RFC1042, abySNAP_RFC1042, ETH_ALEN);
+	memcpy(pDevice->abySNAP_Bridgetunnel, abySNAP_Bridgetunnel, ETH_ALEN);
+
+	pDevice->uChannel = pDevice->sOpts.channel_num;
+	pDevice->wRTSThreshold = pDevice->sOpts.rts_thresh;
+	pDevice->wFragmentationThreshold = pDevice->sOpts.frag_thresh;
+	pDevice->byShortRetryLimit = pDevice->sOpts.short_retry;
+	pDevice->byLongRetryLimit = pDevice->sOpts.long_retry;
+	pDevice->wMaxTransmitMSDULifetime = DEFAULT_MSDU_LIFETIME;
+	pDevice->byShortPreamble = (pDevice->sOpts.flags & DEVICE_FLAGS_PREAMBLE_TYPE) ? 1 : 0;
+	pDevice->byOpMode = (pDevice->sOpts.flags & DEVICE_FLAGS_OP_MODE) ? 1 : 0;
+	pDevice->ePSMode = (pDevice->sOpts.flags & DEVICE_FLAGS_PS_MODE) ? 1 : 0;
+	pDevice->b11hEnable = (pDevice->sOpts.flags & DEVICE_FLAGS_80211h_MODE) ? 1 : 0;
+	pDevice->bDiversityRegCtlON = (pDevice->sOpts.flags & DEVICE_FLAGS_DiversityANT) ? 1 : 0;
+	pDevice->uConnectionRate = pDevice->sOpts.data_rate;
+	if (pDevice->uConnectionRate < RATE_AUTO) pDevice->bFixRate = true;
+	pDevice->byBBType = pDevice->sOpts.bbp_type;
+	pDevice->byPacketType = pDevice->byBBType;
 
 //PLICE_DEBUG->
 	pDevice->byAutoFBCtrl = AUTO_FB_0;
 	//pDevice->byAutoFBCtrl = AUTO_FB_1;
 //PLICE_DEBUG<-
-pDevice->bUpdateBBVGA = true;
-    pDevice->byFOETuning = 0;
-    pDevice->wCTSDuration = 0;
-    pDevice->byPreambleType = 0;
-
-
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" uChannel= %d\n",(int)pDevice->uChannel);
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" byOpMode= %d\n",(int)pDevice->byOpMode);
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" ePSMode= %d\n",(int)pDevice->ePSMode);
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" wRTSThreshold= %d\n",(int)pDevice->wRTSThreshold);
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" byShortRetryLimit= %d\n",(int)pDevice->byShortRetryLimit);
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" byLongRetryLimit= %d\n",(int)pDevice->byLongRetryLimit);
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" byPreambleType= %d\n",(int)pDevice->byPreambleType);
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" byShortPreamble= %d\n",(int)pDevice->byShortPreamble);
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" uConnectionRate= %d\n",(int)pDevice->uConnectionRate);
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" byBBType= %d\n",(int)pDevice->byBBType);
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->b11hEnable= %d\n",(int)pDevice->b11hEnable);
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->bDiversityRegCtlON= %d\n",(int)pDevice->bDiversityRegCtlON);
+	pDevice->bUpdateBBVGA = true;
+	pDevice->byFOETuning = 0;
+	pDevice->wCTSDuration = 0;
+	pDevice->byPreambleType = 0;
+
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " uChannel= %d\n", (int)pDevice->uChannel);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " byOpMode= %d\n", (int)pDevice->byOpMode);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " ePSMode= %d\n", (int)pDevice->ePSMode);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " wRTSThreshold= %d\n", (int)pDevice->wRTSThreshold);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " byShortRetryLimit= %d\n", (int)pDevice->byShortRetryLimit);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " byLongRetryLimit= %d\n", (int)pDevice->byLongRetryLimit);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " byPreambleType= %d\n", (int)pDevice->byPreambleType);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " byShortPreamble= %d\n", (int)pDevice->byShortPreamble);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " uConnectionRate= %d\n", (int)pDevice->uConnectionRate);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " byBBType= %d\n", (int)pDevice->byBBType);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " pDevice->b11hEnable= %d\n", (int)pDevice->b11hEnable);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " pDevice->bDiversityRegCtlON= %d\n", (int)pDevice->bDiversityRegCtlON);
 }
 
-static void s_vCompleteCurrentMeasure (PSDevice pDevice, unsigned char byResult)
+static void s_vCompleteCurrentMeasure(PSDevice pDevice, unsigned char byResult)
 {
-    unsigned int ii;
-    unsigned long dwDuration = 0;
-    unsigned char byRPI0 = 0;
-
-    for(ii=1;ii<8;ii++) {
-        pDevice->dwRPIs[ii] *= 255;
-        dwDuration |= *((unsigned short *) (pDevice->pCurrMeasureEID->sReq.abyDuration));
-        dwDuration <<= 10;
-        pDevice->dwRPIs[ii] /= dwDuration;
-        pDevice->abyRPIs[ii] = (unsigned char) pDevice->dwRPIs[ii];
-        byRPI0 += pDevice->abyRPIs[ii];
-    }
-    pDevice->abyRPIs[0] = (0xFF - byRPI0);
-
-     if (pDevice->uNumOfMeasureEIDs == 0) {
-        VNTWIFIbMeasureReport(  pDevice->pMgmt,
-                                true,
-                                pDevice->pCurrMeasureEID,
-                                byResult,
-                                pDevice->byBasicMap,
-                                pDevice->byCCAFraction,
-                                pDevice->abyRPIs
-                                );
-    } else {
-        VNTWIFIbMeasureReport(  pDevice->pMgmt,
-                                false,
-                                pDevice->pCurrMeasureEID,
-                                byResult,
-                                pDevice->byBasicMap,
-                                pDevice->byCCAFraction,
-                                pDevice->abyRPIs
-                                );
-        CARDbStartMeasure (pDevice, pDevice->pCurrMeasureEID++, pDevice->uNumOfMeasureEIDs);
-    }
-
+	unsigned int ii;
+	unsigned long dwDuration = 0;
+	unsigned char byRPI0 = 0;
+
+	for (ii = 1; ii < 8; ii++) {
+		pDevice->dwRPIs[ii] *= 255;
+		dwDuration |= *((unsigned short *)(pDevice->pCurrMeasureEID->sReq.abyDuration));
+		dwDuration <<= 10;
+		pDevice->dwRPIs[ii] /= dwDuration;
+		pDevice->abyRPIs[ii] = (unsigned char)pDevice->dwRPIs[ii];
+		byRPI0 += pDevice->abyRPIs[ii];
+	}
+	pDevice->abyRPIs[0] = (0xFF - byRPI0);
+
+	if (pDevice->uNumOfMeasureEIDs == 0) {
+		VNTWIFIbMeasureReport(pDevice->pMgmt,
+				      true,
+				      pDevice->pCurrMeasureEID,
+				      byResult,
+				      pDevice->byBasicMap,
+				      pDevice->byCCAFraction,
+				      pDevice->abyRPIs
+			);
+	} else {
+		VNTWIFIbMeasureReport(pDevice->pMgmt,
+				      false,
+				      pDevice->pCurrMeasureEID,
+				      byResult,
+				      pDevice->byBasicMap,
+				      pDevice->byCCAFraction,
+				      pDevice->abyRPIs
+			);
+		CARDbStartMeasure(pDevice, pDevice->pCurrMeasureEID++, pDevice->uNumOfMeasureEIDs);
+	}
 }
 
-
-
 //
 // Initialisation of MAC & BBP registers
 //
 
 static void device_init_registers(PSDevice pDevice, DEVICE_INIT_TYPE InitType)
 {
-    unsigned int ii;
-    unsigned char byValue;
-    unsigned char byValue1;
-    unsigned char byCCKPwrdBm = 0;
-    unsigned char byOFDMPwrdBm = 0;
-    int zonetype=0;
-     PSMgmtObject    pMgmt = &(pDevice->sMgmtObj);
-    MACbShutdown(pDevice->PortOffset);
-    BBvSoftwareReset(pDevice->PortOffset);
-
-    if ((InitType == DEVICE_INIT_COLD) ||
-        (InitType == DEVICE_INIT_DXPL)) {
-        // Do MACbSoftwareReset in MACvInitialize
-        MACbSoftwareReset(pDevice->PortOffset);
-        // force CCK
-        pDevice->bCCK = true;
-        pDevice->bAES = false;
-        pDevice->bProtectMode = false;      //Only used in 11g type, sync with ERP IE
-        pDevice->bNonERPPresent = false;
-        pDevice->bBarkerPreambleMd = false;
-        pDevice->wCurrentRate = RATE_1M;
-        pDevice->byTopOFDMBasicRate = RATE_24M;
-        pDevice->byTopCCKBasicRate = RATE_1M;
-
-        pDevice->byRevId = 0;                   //Target to IF pin while programming to RF chip.
-
-        // init MAC
-        MACvInitialize(pDevice->PortOffset);
-
-        // Get Local ID
-        VNSvInPortB(pDevice->PortOffset + MAC_REG_LOCALID, &(pDevice->byLocalID));
-
-           spin_lock_irq(&pDevice->lock);
-	 SROMvReadAllContents(pDevice->PortOffset,pDevice->abyEEPROM);
-
-           spin_unlock_irq(&pDevice->lock);
-
-        // Get Channel range
-
-        pDevice->byMinChannel = 1;
-        pDevice->byMaxChannel = CB_MAX_CHANNEL;
-
-        // Get Antena
-        byValue = SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_ANTENNA);
-        if (byValue & EEP_ANTINV)
-            pDevice->bTxRxAntInv = true;
-        else
-            pDevice->bTxRxAntInv = false;
-#ifdef	PLICE_DEBUG
-	//printk("init_register:TxRxAntInv is %d,byValue is %d\n",pDevice->bTxRxAntInv,byValue);
-#endif
-
-        byValue &= (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN);
-        if (byValue == 0) // if not set default is All
-            byValue = (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN);
-#ifdef	PLICE_DEBUG
-	//printk("init_register:byValue is %d\n",byValue);
-#endif
-        pDevice->ulDiversityNValue = 100*260;//100*SROMbyReadEmbedded(pDevice->PortOffset, 0x51);
-        pDevice->ulDiversityMValue = 100*16;//SROMbyReadEmbedded(pDevice->PortOffset, 0x52);
-        pDevice->byTMax = 1;//SROMbyReadEmbedded(pDevice->PortOffset, 0x53);
-        pDevice->byTMax2 = 4;//SROMbyReadEmbedded(pDevice->PortOffset, 0x54);
-        pDevice->ulSQ3TH = 0;//(unsigned long) SROMbyReadEmbedded(pDevice->PortOffset, 0x55);
-        pDevice->byTMax3 = 64;//SROMbyReadEmbedded(pDevice->PortOffset, 0x56);
-
-        if (byValue == (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN)) {
-            pDevice->byAntennaCount = 2;
-            pDevice->byTxAntennaMode = ANT_B;
-            pDevice->dwTxAntennaSel = 1;
-            pDevice->dwRxAntennaSel = 1;
-            if (pDevice->bTxRxAntInv == true)
-                pDevice->byRxAntennaMode = ANT_A;
-            else
-                pDevice->byRxAntennaMode = ANT_B;
-                // chester for antenna
-byValue1 = SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_ANTENNA);
-          //  if (pDevice->bDiversityRegCtlON)
-          if((byValue1&0x08)==0)
-                pDevice->bDiversityEnable = false;//SROMbyReadEmbedded(pDevice->PortOffset, 0x50);
-            else
-                pDevice->bDiversityEnable = true;
-#ifdef	PLICE_DEBUG
-		//printk("aux |main antenna: RxAntennaMode is %d\n",pDevice->byRxAntennaMode);
-#endif
-	} else  {
-            pDevice->bDiversityEnable = false;
-            pDevice->byAntennaCount = 1;
-            pDevice->dwTxAntennaSel = 0;
-            pDevice->dwRxAntennaSel = 0;
-            if (byValue & EEP_ANTENNA_AUX) {
-                pDevice->byTxAntennaMode = ANT_A;
-                if (pDevice->bTxRxAntInv == true)
-                    pDevice->byRxAntennaMode = ANT_B;
-                else
-                    pDevice->byRxAntennaMode = ANT_A;
-            } else {
-                pDevice->byTxAntennaMode = ANT_B;
-                if (pDevice->bTxRxAntInv == true)
-                    pDevice->byRxAntennaMode = ANT_A;
-                else
-                    pDevice->byRxAntennaMode = ANT_B;
-            }
-        }
-#ifdef	PLICE_DEBUG
-	//printk("init registers: TxAntennaMode is %d\n",pDevice->byTxAntennaMode);
-#endif
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "bDiversityEnable=[%d],NValue=[%d],MValue=[%d],TMax=[%d],TMax2=[%d]\n",
-            pDevice->bDiversityEnable,(int)pDevice->ulDiversityNValue,(int)pDevice->ulDiversityMValue,pDevice->byTMax,pDevice->byTMax2);
-
-//#ifdef ZoneType_DefaultSetting
-//2008-8-4 <add> by chester
-//zonetype initial
- pDevice->byOriginalZonetype = pDevice->abyEEPROM[EEP_OFS_ZONETYPE];
- zonetype = Config_FileOperation(pDevice,false,NULL);
- if (zonetype >= 0) {         //read zonetype file ok!
-  if ((zonetype == 0)&&
-        (pDevice->abyEEPROM[EEP_OFS_ZONETYPE] !=0x00)){          //for USA
-    pDevice->abyEEPROM[EEP_OFS_ZONETYPE] = 0;
-    pDevice->abyEEPROM[EEP_OFS_MAXCHANNEL] = 0x0B;
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Init Zone Type :USA\n");
-  }
- else if((zonetype == 1)&&
- 	     (pDevice->abyEEPROM[EEP_OFS_ZONETYPE]!=0x01)){   //for Japan
-    pDevice->abyEEPROM[EEP_OFS_ZONETYPE] = 0x01;
-    pDevice->abyEEPROM[EEP_OFS_MAXCHANNEL] = 0x0D;
-  }
- else if((zonetype == 2)&&
- 	     (pDevice->abyEEPROM[EEP_OFS_ZONETYPE]!=0x02)){   //for Europe
-    pDevice->abyEEPROM[EEP_OFS_ZONETYPE] = 0x02;
-    pDevice->abyEEPROM[EEP_OFS_MAXCHANNEL] = 0x0D;
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Init Zone Type :Europe\n");
-  }
+	unsigned int ii;
+	unsigned char byValue;
+	unsigned char byValue1;
+	unsigned char byCCKPwrdBm = 0;
+	unsigned char byOFDMPwrdBm = 0;
+	int zonetype = 0;
+	PSMgmtObject    pMgmt = &(pDevice->sMgmtObj);
+	MACbShutdown(pDevice->PortOffset);
+	BBvSoftwareReset(pDevice->PortOffset);
+
+	if ((InitType == DEVICE_INIT_COLD) ||
+	    (InitType == DEVICE_INIT_DXPL)) {
+		// Do MACbSoftwareReset in MACvInitialize
+		MACbSoftwareReset(pDevice->PortOffset);
+		// force CCK
+		pDevice->bCCK = true;
+		pDevice->bAES = false;
+		pDevice->bProtectMode = false;      //Only used in 11g type, sync with ERP IE
+		pDevice->bNonERPPresent = false;
+		pDevice->bBarkerPreambleMd = false;
+		pDevice->wCurrentRate = RATE_1M;
+		pDevice->byTopOFDMBasicRate = RATE_24M;
+		pDevice->byTopCCKBasicRate = RATE_1M;
+
+		pDevice->byRevId = 0;                   //Target to IF pin while programming to RF chip.
+
+		// init MAC
+		MACvInitialize(pDevice->PortOffset);
+
+		// Get Local ID
+		VNSvInPortB(pDevice->PortOffset + MAC_REG_LOCALID, &(pDevice->byLocalID));
 
-else
-{
-   if(zonetype!=pDevice->abyEEPROM[EEP_OFS_ZONETYPE])
-      printk("zonetype in file[%02x] mismatch with in EEPROM[%02x]\n",zonetype,pDevice->abyEEPROM[EEP_OFS_ZONETYPE]);
-   else
-      printk("Read Zonetype file success,use default zonetype setting[%02x]\n",zonetype);
- }
- 	}
-  else
-    printk("Read Zonetype file fail,use default zonetype setting[%02x]\n",SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_ZONETYPE));
-
-        // Get RFType
-        pDevice->byRFType = SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_RFTYPE);
-
-        if ((pDevice->byRFType & RF_EMU) != 0) {
-            // force change RevID for VT3253 emu
-            pDevice->byRevId = 0x80;
-        }
-
-        pDevice->byRFType &= RF_MASK;
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pDevice->byRFType = %x\n", pDevice->byRFType);
-
-        if (pDevice->bZoneRegExist == false) {
-            pDevice->byZoneType = pDevice->abyEEPROM[EEP_OFS_ZONETYPE];
-        }
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pDevice->byZoneType = %x\n", pDevice->byZoneType);
-
-        //Init RF module
-        RFbInit(pDevice);
-
-        //Get Desire Power Value
-        pDevice->byCurPwr = 0xFF;
-        pDevice->byCCKPwr = SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_PWR_CCK);
-        pDevice->byOFDMPwrG = SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_PWR_OFDMG);
-        //byCCKPwrdBm = SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_CCK_PWR_dBm);
-
-	//byOFDMPwrdBm = SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_OFDM_PWR_dBm);
-//printk("CCKPwrdBm is 0x%x,byOFDMPwrdBm is 0x%x\n",byCCKPwrdBm,byOFDMPwrdBm);
-		// Load power Table
+		spin_lock_irq(&pDevice->lock);
+		SROMvReadAllContents(pDevice->PortOffset, pDevice->abyEEPROM);
 
+		spin_unlock_irq(&pDevice->lock);
 
-        for (ii=0;ii<CB_MAX_CHANNEL_24G;ii++) {
-            pDevice->abyCCKPwrTbl[ii+1] = SROMbyReadEmbedded(pDevice->PortOffset, (unsigned char)(ii + EEP_OFS_CCK_PWR_TBL));
-            if (pDevice->abyCCKPwrTbl[ii+1] == 0) {
-                pDevice->abyCCKPwrTbl[ii+1] = pDevice->byCCKPwr;
-            }
-            pDevice->abyOFDMPwrTbl[ii+1] = SROMbyReadEmbedded(pDevice->PortOffset, (unsigned char)(ii + EEP_OFS_OFDM_PWR_TBL));
-            if (pDevice->abyOFDMPwrTbl[ii+1] == 0) {
-                pDevice->abyOFDMPwrTbl[ii+1] = pDevice->byOFDMPwrG;
-            }
-            pDevice->abyCCKDefaultPwr[ii+1] = byCCKPwrdBm;
-            pDevice->abyOFDMDefaultPwr[ii+1] = byOFDMPwrdBm;
-        }
-		//2008-8-4 <add> by chester
-	  //recover 12,13 ,14channel for EUROPE by 11 channel
-          if(((pDevice->abyEEPROM[EEP_OFS_ZONETYPE] == ZoneType_Japan) ||
-	        (pDevice->abyEEPROM[EEP_OFS_ZONETYPE] == ZoneType_Europe))&&
-	     (pDevice->byOriginalZonetype == ZoneType_USA)) {
-	    for(ii=11;ii<14;ii++) {
-                pDevice->abyCCKPwrTbl[ii] = pDevice->abyCCKPwrTbl[10];
-	       pDevice->abyOFDMPwrTbl[ii] = pDevice->abyOFDMPwrTbl[10];
+		// Get Channel range
 
-	    }
-	  }
+		pDevice->byMinChannel = 1;
+		pDevice->byMaxChannel = CB_MAX_CHANNEL;
 
+		// Get Antena
+		byValue = SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_ANTENNA);
+		if (byValue & EEP_ANTINV)
+			pDevice->bTxRxAntInv = true;
+		else
+			pDevice->bTxRxAntInv = false;
+
+		byValue &= (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN);
+		if (byValue == 0) // if not set default is All
+			byValue = (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN);
+
+		pDevice->ulDiversityNValue = 100*260;//100*SROMbyReadEmbedded(pDevice->PortOffset, 0x51);
+		pDevice->ulDiversityMValue = 100*16;//SROMbyReadEmbedded(pDevice->PortOffset, 0x52);
+		pDevice->byTMax = 1;//SROMbyReadEmbedded(pDevice->PortOffset, 0x53);
+		pDevice->byTMax2 = 4;//SROMbyReadEmbedded(pDevice->PortOffset, 0x54);
+		pDevice->ulSQ3TH = 0;//(unsigned long) SROMbyReadEmbedded(pDevice->PortOffset, 0x55);
+		pDevice->byTMax3 = 64;//SROMbyReadEmbedded(pDevice->PortOffset, 0x56);
+
+		if (byValue == (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN)) {
+			pDevice->byAntennaCount = 2;
+			pDevice->byTxAntennaMode = ANT_B;
+			pDevice->dwTxAntennaSel = 1;
+			pDevice->dwRxAntennaSel = 1;
+			if (pDevice->bTxRxAntInv == true)
+				pDevice->byRxAntennaMode = ANT_A;
+			else
+				pDevice->byRxAntennaMode = ANT_B;
+			// chester for antenna
+			byValue1 = SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_ANTENNA);
+			if ((byValue1 & 0x08) == 0)
+				pDevice->bDiversityEnable = false;//SROMbyReadEmbedded(pDevice->PortOffset, 0x50);
+			else
+				pDevice->bDiversityEnable = true;
+		} else  {
+			pDevice->bDiversityEnable = false;
+			pDevice->byAntennaCount = 1;
+			pDevice->dwTxAntennaSel = 0;
+			pDevice->dwRxAntennaSel = 0;
+			if (byValue & EEP_ANTENNA_AUX) {
+				pDevice->byTxAntennaMode = ANT_A;
+				if (pDevice->bTxRxAntInv == true)
+					pDevice->byRxAntennaMode = ANT_B;
+				else
+					pDevice->byRxAntennaMode = ANT_A;
+			} else {
+				pDevice->byTxAntennaMode = ANT_B;
+				if (pDevice->bTxRxAntInv == true)
+					pDevice->byRxAntennaMode = ANT_A;
+				else
+					pDevice->byRxAntennaMode = ANT_B;
+			}
+		}
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "bDiversityEnable=[%d],NValue=[%d],MValue=[%d],TMax=[%d],TMax2=[%d]\n",
+			pDevice->bDiversityEnable, (int)pDevice->ulDiversityNValue, (int)pDevice->ulDiversityMValue, pDevice->byTMax, pDevice->byTMax2);
 
-        // Load OFDM A Power Table
-        for (ii=0;ii<CB_MAX_CHANNEL_5G;ii++) { //RobertYu:20041224, bug using CB_MAX_CHANNEL
-            pDevice->abyOFDMPwrTbl[ii+CB_MAX_CHANNEL_24G+1] = SROMbyReadEmbedded(pDevice->PortOffset, (unsigned char)(ii + EEP_OFS_OFDMA_PWR_TBL));
-            pDevice->abyOFDMDefaultPwr[ii+CB_MAX_CHANNEL_24G+1] = SROMbyReadEmbedded(pDevice->PortOffset, (unsigned char)(ii + EEP_OFS_OFDMA_PWR_dBm));
-        }
-        init_channel_table((void *)pDevice);
+//#ifdef ZoneType_DefaultSetting
+//2008-8-4 <add> by chester
+//zonetype initial
+		pDevice->byOriginalZonetype = pDevice->abyEEPROM[EEP_OFS_ZONETYPE];
+		zonetype = Config_FileOperation(pDevice, false, NULL);
+		if (zonetype >= 0) {         //read zonetype file ok!
+			if ((zonetype == 0) &&
+			    (pDevice->abyEEPROM[EEP_OFS_ZONETYPE] != 0x00)) {          //for USA
+				pDevice->abyEEPROM[EEP_OFS_ZONETYPE] = 0;
+				pDevice->abyEEPROM[EEP_OFS_MAXCHANNEL] = 0x0B;
+				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Init Zone Type :USA\n");
+			} else if ((zonetype == 1) &&
+				 (pDevice->abyEEPROM[EEP_OFS_ZONETYPE] != 0x01)) {   //for Japan
+				pDevice->abyEEPROM[EEP_OFS_ZONETYPE] = 0x01;
+				pDevice->abyEEPROM[EEP_OFS_MAXCHANNEL] = 0x0D;
+			} else if ((zonetype == 2) &&
+				 (pDevice->abyEEPROM[EEP_OFS_ZONETYPE] != 0x02)) {   //for Europe
+				pDevice->abyEEPROM[EEP_OFS_ZONETYPE] = 0x02;
+				pDevice->abyEEPROM[EEP_OFS_MAXCHANNEL] = 0x0D;
+				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Init Zone Type :Europe\n");
+			}
 
+			else {
+				if (zonetype != pDevice->abyEEPROM[EEP_OFS_ZONETYPE])
+					printk("zonetype in file[%02x] mismatch with in EEPROM[%02x]\n", zonetype, pDevice->abyEEPROM[EEP_OFS_ZONETYPE]);
+				else
+					printk("Read Zonetype file success,use default zonetype setting[%02x]\n", zonetype);
+			}
+		} else
+			printk("Read Zonetype file fail,use default zonetype setting[%02x]\n", SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_ZONETYPE));
 
-        if (pDevice->byLocalID > REV_ID_VT3253_B1) {
-            MACvSelectPage1(pDevice->PortOffset);
-            VNSvOutPortB(pDevice->PortOffset + MAC_REG_MSRCTL + 1, (MSRCTL1_TXPWR | MSRCTL1_CSAPAREN));
-            MACvSelectPage0(pDevice->PortOffset);
-        }
+		// Get RFType
+		pDevice->byRFType = SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_RFTYPE);
 
+		if ((pDevice->byRFType & RF_EMU) != 0) {
+			// force change RevID for VT3253 emu
+			pDevice->byRevId = 0x80;
+		}
 
-         // use relative tx timeout and 802.11i D4
-        MACvWordRegBitsOn(pDevice->PortOffset, MAC_REG_CFG, (CFG_TKIPOPT | CFG_NOTXTIMEOUT));
+		pDevice->byRFType &= RF_MASK;
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pDevice->byRFType = %x\n", pDevice->byRFType);
 
-        // set performance parameter by registry
-        MACvSetShortRetryLimit(pDevice->PortOffset, pDevice->byShortRetryLimit);
-        MACvSetLongRetryLimit(pDevice->PortOffset, pDevice->byLongRetryLimit);
+		if (pDevice->bZoneRegExist == false) {
+			pDevice->byZoneType = pDevice->abyEEPROM[EEP_OFS_ZONETYPE];
+		}
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pDevice->byZoneType = %x\n", pDevice->byZoneType);
 
-        // reset TSF counter
-        VNSvOutPortB(pDevice->PortOffset + MAC_REG_TFTCTL, TFTCTL_TSFCNTRST);
-        // enable TSF counter
-        VNSvOutPortB(pDevice->PortOffset + MAC_REG_TFTCTL, TFTCTL_TSFCNTREN);
+		//Init RF module
+		RFbInit(pDevice);
 
-        // initialize BBP registers
-        BBbVT3253Init(pDevice);
+		//Get Desire Power Value
+		pDevice->byCurPwr = 0xFF;
+		pDevice->byCCKPwr = SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_PWR_CCK);
+		pDevice->byOFDMPwrG = SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_PWR_OFDMG);
+		//byCCKPwrdBm = SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_CCK_PWR_dBm);
 
-        if (pDevice->bUpdateBBVGA) {
-            pDevice->byBBVGACurrent = pDevice->abyBBVGA[0];
-            pDevice->byBBVGANew = pDevice->byBBVGACurrent;
-            BBvSetVGAGainOffset(pDevice, pDevice->abyBBVGA[0]);
-        }
-#ifdef	PLICE_DEBUG
-	//printk("init registers:RxAntennaMode is %x,TxAntennaMode is %x\n",pDevice->byRxAntennaMode,pDevice->byTxAntennaMode);
-#endif
-        BBvSetRxAntennaMode(pDevice->PortOffset, pDevice->byRxAntennaMode);
-        BBvSetTxAntennaMode(pDevice->PortOffset, pDevice->byTxAntennaMode);
+		//byOFDMPwrdBm = SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_OFDM_PWR_dBm);
 
-        pDevice->byCurrentCh = 0;
+		// Load power Table
 
-        //pDevice->NetworkType = Ndis802_11Automode;
-        // Set BB and packet type at the same time.
-        // Set Short Slot Time, xIFS, and RSPINF.
-        if (pDevice->uConnectionRate == RATE_AUTO) {
-            pDevice->wCurrentRate = RATE_54M;
-        } else {
-            pDevice->wCurrentRate = (unsigned short)pDevice->uConnectionRate;
-        }
+		for (ii = 0; ii < CB_MAX_CHANNEL_24G; ii++) {
+			pDevice->abyCCKPwrTbl[ii + 1] = SROMbyReadEmbedded(pDevice->PortOffset, (unsigned char)(ii + EEP_OFS_CCK_PWR_TBL));
+			if (pDevice->abyCCKPwrTbl[ii + 1] == 0) {
+				pDevice->abyCCKPwrTbl[ii+1] = pDevice->byCCKPwr;
+			}
+			pDevice->abyOFDMPwrTbl[ii + 1] = SROMbyReadEmbedded(pDevice->PortOffset, (unsigned char)(ii + EEP_OFS_OFDM_PWR_TBL));
+			if (pDevice->abyOFDMPwrTbl[ii + 1] == 0) {
+				pDevice->abyOFDMPwrTbl[ii + 1] = pDevice->byOFDMPwrG;
+			}
+			pDevice->abyCCKDefaultPwr[ii + 1] = byCCKPwrdBm;
+			pDevice->abyOFDMDefaultPwr[ii + 1] = byOFDMPwrdBm;
+		}
+		//2008-8-4 <add> by chester
+		//recover 12,13 ,14channel for EUROPE by 11 channel
+		if (((pDevice->abyEEPROM[EEP_OFS_ZONETYPE] == ZoneType_Japan) ||
+		     (pDevice->abyEEPROM[EEP_OFS_ZONETYPE] == ZoneType_Europe)) &&
+		    (pDevice->byOriginalZonetype == ZoneType_USA)) {
+			for (ii = 11; ii < 14; ii++) {
+				pDevice->abyCCKPwrTbl[ii] = pDevice->abyCCKPwrTbl[10];
+				pDevice->abyOFDMPwrTbl[ii] = pDevice->abyOFDMPwrTbl[10];
 
-        // default G Mode
-        VNTWIFIbConfigPhyMode(pDevice->pMgmt, PHY_TYPE_11G);
-        VNTWIFIbConfigPhyMode(pDevice->pMgmt, PHY_TYPE_AUTO);
+			}
+		}
 
-        pDevice->bRadioOff = false;
+		// Load OFDM A Power Table
+		for (ii = 0; ii < CB_MAX_CHANNEL_5G; ii++) { //RobertYu:20041224, bug using CB_MAX_CHANNEL
+			pDevice->abyOFDMPwrTbl[ii + CB_MAX_CHANNEL_24G + 1] = SROMbyReadEmbedded(pDevice->PortOffset, (unsigned char)(ii + EEP_OFS_OFDMA_PWR_TBL));
+			pDevice->abyOFDMDefaultPwr[ii + CB_MAX_CHANNEL_24G + 1] = SROMbyReadEmbedded(pDevice->PortOffset, (unsigned char)(ii + EEP_OFS_OFDMA_PWR_dBm));
+		}
+		init_channel_table((void *)pDevice);
 
-        pDevice->byRadioCtl = SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_RADIOCTL);
-        pDevice->bHWRadioOff = false;
+		if (pDevice->byLocalID > REV_ID_VT3253_B1) {
+			MACvSelectPage1(pDevice->PortOffset);
+			VNSvOutPortB(pDevice->PortOffset + MAC_REG_MSRCTL + 1, (MSRCTL1_TXPWR | MSRCTL1_CSAPAREN));
+			MACvSelectPage0(pDevice->PortOffset);
+		}
 
-        if (pDevice->byRadioCtl & EEP_RADIOCTL_ENABLE) {
-            // Get GPIO
-            MACvGPIOIn(pDevice->PortOffset, &pDevice->byGPIO);
-//2008-4-14 <add> by chester for led issue
- #ifdef FOR_LED_ON_NOTEBOOK
-if (pDevice->byGPIO & GPIO0_DATA){pDevice->bHWRadioOff = true;}
-if ( !(pDevice->byGPIO & GPIO0_DATA)){pDevice->bHWRadioOff = false;}
-
-            }
-        if ( (pDevice->bRadioControlOff == true)) {
-            CARDbRadioPowerOff(pDevice);
-        }
-else  CARDbRadioPowerOn(pDevice);
-#else
-            if (((pDevice->byGPIO & GPIO0_DATA) && !(pDevice->byRadioCtl & EEP_RADIOCTL_INV)) ||
-                ( !(pDevice->byGPIO & GPIO0_DATA) && (pDevice->byRadioCtl & EEP_RADIOCTL_INV))) {
-                pDevice->bHWRadioOff = true;
-            }
-        }
-        if ((pDevice->bHWRadioOff == true) || (pDevice->bRadioControlOff == true)) {
-            CARDbRadioPowerOff(pDevice);
-        }
+		// use relative tx timeout and 802.11i D4
+		MACvWordRegBitsOn(pDevice->PortOffset, MAC_REG_CFG, (CFG_TKIPOPT | CFG_NOTXTIMEOUT));
 
-#endif
-    }
-            pMgmt->eScanType = WMAC_SCAN_PASSIVE;
-    // get Permanent network address
-    SROMvReadEtherAddress(pDevice->PortOffset, pDevice->abyCurrentNetAddr);
-	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Network address = %pM\n",
-		pDevice->abyCurrentNetAddr);
+		// set performance parameter by registry
+		MACvSetShortRetryLimit(pDevice->PortOffset, pDevice->byShortRetryLimit);
+		MACvSetLongRetryLimit(pDevice->PortOffset, pDevice->byLongRetryLimit);
 
-    // reset Tx pointer
-    CARDvSafeResetRx(pDevice);
-    // reset Rx pointer
-    CARDvSafeResetTx(pDevice);
+		// reset TSF counter
+		VNSvOutPortB(pDevice->PortOffset + MAC_REG_TFTCTL, TFTCTL_TSFCNTRST);
+		// enable TSF counter
+		VNSvOutPortB(pDevice->PortOffset + MAC_REG_TFTCTL, TFTCTL_TSFCNTREN);
 
-    if (pDevice->byLocalID <= REV_ID_VT3253_A1) {
-        MACvRegBitsOn(pDevice->PortOffset, MAC_REG_RCR, RCR_WPAERR);
-    }
+		// initialize BBP registers
+		BBbVT3253Init(pDevice);
 
-    pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled;
+		if (pDevice->bUpdateBBVGA) {
+			pDevice->byBBVGACurrent = pDevice->abyBBVGA[0];
+			pDevice->byBBVGANew = pDevice->byBBVGACurrent;
+			BBvSetVGAGainOffset(pDevice, pDevice->abyBBVGA[0]);
+		}
+		BBvSetRxAntennaMode(pDevice->PortOffset, pDevice->byRxAntennaMode);
+		BBvSetTxAntennaMode(pDevice->PortOffset, pDevice->byTxAntennaMode);
 
-    // Turn On Rx DMA
-    MACvReceive0(pDevice->PortOffset);
-    MACvReceive1(pDevice->PortOffset);
+		pDevice->byCurrentCh = 0;
 
-    // start the adapter
-    MACvStart(pDevice->PortOffset);
+		//pDevice->NetworkType = Ndis802_11Automode;
+		// Set BB and packet type at the same time.
+		// Set Short Slot Time, xIFS, and RSPINF.
+		if (pDevice->uConnectionRate == RATE_AUTO) {
+			pDevice->wCurrentRate = RATE_54M;
+		} else {
+			pDevice->wCurrentRate = (unsigned short)pDevice->uConnectionRate;
+		}
 
-    netif_stop_queue(pDevice->dev);
+		// default G Mode
+		VNTWIFIbConfigPhyMode(pDevice->pMgmt, PHY_TYPE_11G);
+		VNTWIFIbConfigPhyMode(pDevice->pMgmt, PHY_TYPE_AUTO);
 
+		pDevice->bRadioOff = false;
 
-}
+		pDevice->byRadioCtl = SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_RADIOCTL);
+		pDevice->bHWRadioOff = false;
 
+		if (pDevice->byRadioCtl & EEP_RADIOCTL_ENABLE) {
+			// Get GPIO
+			MACvGPIOIn(pDevice->PortOffset, &pDevice->byGPIO);
+//2008-4-14 <add> by chester for led issue
+#ifdef FOR_LED_ON_NOTEBOOK
+			if (pDevice->byGPIO & GPIO0_DATA) { pDevice->bHWRadioOff = true; }
+			if (!(pDevice->byGPIO & GPIO0_DATA)) { pDevice->bHWRadioOff = false; }
 
+		}
+		if ((pDevice->bRadioControlOff == true)) {
+			CARDbRadioPowerOff(pDevice);
+		} else  CARDbRadioPowerOn(pDevice);
+#else
+		if (((pDevice->byGPIO & GPIO0_DATA) && !(pDevice->byRadioCtl & EEP_RADIOCTL_INV)) ||
+		    (!(pDevice->byGPIO & GPIO0_DATA) && (pDevice->byRadioCtl & EEP_RADIOCTL_INV))) {
+			pDevice->bHWRadioOff = true;
+		}
+	}
+	if ((pDevice->bHWRadioOff == true) || (pDevice->bRadioControlOff == true)) {
+		CARDbRadioPowerOff(pDevice);
+	}
 
-static void device_init_diversity_timer(PSDevice pDevice) {
+#endif
+}
+pMgmt->eScanType = WMAC_SCAN_PASSIVE;
+// get Permanent network address
+SROMvReadEtherAddress(pDevice->PortOffset, pDevice->abyCurrentNetAddr);
+DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Network address = %pM\n",
+	pDevice->abyCurrentNetAddr);
+
+// reset Tx pointer
+CARDvSafeResetRx(pDevice);
+// reset Rx pointer
+CARDvSafeResetTx(pDevice);
+
+if (pDevice->byLocalID <= REV_ID_VT3253_A1) {
+	MACvRegBitsOn(pDevice->PortOffset, MAC_REG_RCR, RCR_WPAERR);
+}
 
-    init_timer(&pDevice->TimerSQ3Tmax1);
-    pDevice->TimerSQ3Tmax1.data = (unsigned long) pDevice;
-    pDevice->TimerSQ3Tmax1.function = (TimerFunction)TimerSQ3CallBack;
-    pDevice->TimerSQ3Tmax1.expires = RUN_AT(HZ);
+pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled;
 
-    init_timer(&pDevice->TimerSQ3Tmax2);
-    pDevice->TimerSQ3Tmax2.data = (unsigned long) pDevice;
-    pDevice->TimerSQ3Tmax2.function = (TimerFunction)TimerSQ3CallBack;
-    pDevice->TimerSQ3Tmax2.expires = RUN_AT(HZ);
+// Turn On Rx DMA
+MACvReceive0(pDevice->PortOffset);
+MACvReceive1(pDevice->PortOffset);
 
-    init_timer(&pDevice->TimerSQ3Tmax3);
-    pDevice->TimerSQ3Tmax3.data = (unsigned long) pDevice;
-    pDevice->TimerSQ3Tmax3.function = (TimerFunction)TimerState1CallBack;
-    pDevice->TimerSQ3Tmax3.expires = RUN_AT(HZ);
+// start the adapter
+MACvStart(pDevice->PortOffset);
 
-    return;
+netif_stop_queue(pDevice->dev);
 }
 
+static void device_init_diversity_timer(PSDevice pDevice) {
+	init_timer(&pDevice->TimerSQ3Tmax1);
+	pDevice->TimerSQ3Tmax1.data = (unsigned long) pDevice;
+	pDevice->TimerSQ3Tmax1.function = (TimerFunction)TimerSQ3CallBack;
+	pDevice->TimerSQ3Tmax1.expires = RUN_AT(HZ);
+
+	init_timer(&pDevice->TimerSQ3Tmax2);
+	pDevice->TimerSQ3Tmax2.data = (unsigned long) pDevice;
+	pDevice->TimerSQ3Tmax2.function = (TimerFunction)TimerSQ3CallBack;
+	pDevice->TimerSQ3Tmax2.expires = RUN_AT(HZ);
+
+	init_timer(&pDevice->TimerSQ3Tmax3);
+	pDevice->TimerSQ3Tmax3.data = (unsigned long) pDevice;
+	pDevice->TimerSQ3Tmax3.function = (TimerFunction)TimerState1CallBack;
+	pDevice->TimerSQ3Tmax3.expires = RUN_AT(HZ);
+
+	return;
+}
 
 static bool device_release_WPADEV(PSDevice pDevice)
 {
-  viawget_wpa_header *wpahdr;
-  int ii=0;
- // wait_queue_head_t	Set_wait;
-  //send device close to wpa_supplicnat layer
-    if (pDevice->bWPADEVUp==true) {
-                 wpahdr = (viawget_wpa_header *)pDevice->skb->data;
-                 wpahdr->type = VIAWGET_DEVICECLOSE_MSG;
-                 wpahdr->resp_ie_len = 0;
-                 wpahdr->req_ie_len = 0;
-                 skb_put(pDevice->skb, sizeof(viawget_wpa_header));
-                 pDevice->skb->dev = pDevice->wpadev;
-		 skb_reset_mac_header(pDevice->skb);
-                 pDevice->skb->pkt_type = PACKET_HOST;
-                 pDevice->skb->protocol = htons(ETH_P_802_2);
-                 memset(pDevice->skb->cb, 0, sizeof(pDevice->skb->cb));
-                 netif_rx(pDevice->skb);
-                 pDevice->skb = dev_alloc_skb((int)pDevice->rx_buf_sz);
-
- //wait release WPADEV
-              //    init_waitqueue_head(&Set_wait);
-              //    wait_event_timeout(Set_wait, ((pDevice->wpadev==NULL)&&(pDevice->skb == NULL)),5*HZ);    //1s wait
-              while((pDevice->bWPADEVUp==true)) {
-	        set_current_state(TASK_UNINTERRUPTIBLE);
-                 schedule_timeout (HZ/20);          //wait 50ms
-                 ii++;
-	        if(ii>20)
-		  break;
-              }
-           }
-    return true;
+	viawget_wpa_header *wpahdr;
+	int ii = 0;
+	// wait_queue_head_t	Set_wait;
+	//send device close to wpa_supplicnat layer
+	if (pDevice->bWPADEVUp == true) {
+		wpahdr = (viawget_wpa_header *)pDevice->skb->data;
+		wpahdr->type = VIAWGET_DEVICECLOSE_MSG;
+		wpahdr->resp_ie_len = 0;
+		wpahdr->req_ie_len = 0;
+		skb_put(pDevice->skb, sizeof(viawget_wpa_header));
+		pDevice->skb->dev = pDevice->wpadev;
+		skb_reset_mac_header(pDevice->skb);
+		pDevice->skb->pkt_type = PACKET_HOST;
+		pDevice->skb->protocol = htons(ETH_P_802_2);
+		memset(pDevice->skb->cb, 0, sizeof(pDevice->skb->cb));
+		netif_rx(pDevice->skb);
+		pDevice->skb = dev_alloc_skb((int)pDevice->rx_buf_sz);
+
+		//wait release WPADEV
+		//    init_waitqueue_head(&Set_wait);
+		//    wait_event_timeout(Set_wait, ((pDevice->wpadev==NULL)&&(pDevice->skb == NULL)),5*HZ);    //1s wait
+		while ((pDevice->bWPADEVUp == true)) {
+			set_current_state(TASK_UNINTERRUPTIBLE);
+			schedule_timeout(HZ / 20);          //wait 50ms
+			ii++;
+			if (ii > 20)
+				break;
+		}
+	}
+	return true;
 }
 
 static const struct net_device_ops device_netdev_ops = {
@@ -905,93 +848,88 @@ static const struct net_device_ops device_netdev_ops = {
 static int
 vt6655_probe(struct pci_dev *pcid, const struct pci_device_id *ent)
 {
-    static bool bFirst = true;
-    struct net_device*  dev = NULL;
-    PCHIP_INFO  pChip_info = (PCHIP_INFO)ent->driver_data;
-    PSDevice    pDevice;
-    int         rc;
-    if (device_nics ++>= MAX_UINTS) {
-        printk(KERN_NOTICE DEVICE_NAME ": already found %d NICs\n", device_nics);
-        return -ENODEV;
-    }
-
-
-    dev = alloc_etherdev(sizeof(DEVICE_INFO));
-
-    pDevice = (PSDevice) netdev_priv(dev);
-
-    if (dev == NULL) {
-        printk(KERN_ERR DEVICE_NAME ": allocate net device failed \n");
-        return -ENOMEM;
-    }
-
-    // Chain it all together
-   // SET_MODULE_OWNER(dev);
-    SET_NETDEV_DEV(dev, &pcid->dev);
-
-    if (bFirst) {
-        printk(KERN_NOTICE "%s Ver. %s\n",DEVICE_FULL_DRV_NAM, DEVICE_VERSION);
-        printk(KERN_NOTICE "Copyright (c) 2003 VIA Networking Technologies, Inc.\n");
-        bFirst=false;
-    }
-
-    vt6655_init_info(pcid, &pDevice, pChip_info);
-    pDevice->dev = dev;
-    pDevice->next_module = root_device_dev;
-    root_device_dev = dev;
-
-    if (pci_enable_device(pcid)) {
-        device_free_info(pDevice);
-        return -ENODEV;
-    }
-    dev->irq = pcid->irq;
+	static bool bFirst = true;
+	struct net_device *dev = NULL;
+	PCHIP_INFO  pChip_info = (PCHIP_INFO)ent->driver_data;
+	PSDevice    pDevice;
+	int         rc;
+	if (device_nics++ >= MAX_UINTS) {
+		printk(KERN_NOTICE DEVICE_NAME ": already found %d NICs\n", device_nics);
+		return -ENODEV;
+	}
+
+	dev = alloc_etherdev(sizeof(DEVICE_INFO));
+
+	pDevice = (PSDevice) netdev_priv(dev);
+
+	if (dev == NULL) {
+		printk(KERN_ERR DEVICE_NAME ": allocate net device failed \n");
+		return -ENOMEM;
+	}
+
+	// Chain it all together
+	// SET_MODULE_OWNER(dev);
+	SET_NETDEV_DEV(dev, &pcid->dev);
+
+	if (bFirst) {
+		printk(KERN_NOTICE "%s Ver. %s\n", DEVICE_FULL_DRV_NAM, DEVICE_VERSION);
+		printk(KERN_NOTICE "Copyright (c) 2003 VIA Networking Technologies, Inc.\n");
+		bFirst = false;
+	}
+
+	vt6655_init_info(pcid, &pDevice, pChip_info);
+	pDevice->dev = dev;
+	pDevice->next_module = root_device_dev;
+	root_device_dev = dev;
+
+	if (pci_enable_device(pcid)) {
+		device_free_info(pDevice);
+		return -ENODEV;
+	}
+	dev->irq = pcid->irq;
 
 #ifdef	DEBUG
-	printk("Before get pci_info memaddr is %x\n",pDevice->memaddr);
+	printk("Before get pci_info memaddr is %x\n", pDevice->memaddr);
 #endif
-    if (device_get_pci_info(pDevice,pcid) == false) {
-        printk(KERN_ERR DEVICE_NAME ": Failed to find PCI device.\n");
-        device_free_info(pDevice);
-        return -ENODEV;
-    }
+	if (device_get_pci_info(pDevice, pcid) == false) {
+		printk(KERN_ERR DEVICE_NAME ": Failed to find PCI device.\n");
+		device_free_info(pDevice);
+		return -ENODEV;
+	}
 
 #if 1
 
 #ifdef	DEBUG
 
 	//pci_read_config_byte(pcid, PCI_BASE_ADDRESS_0, &pDevice->byRevId);
-	printk("after get pci_info memaddr is %x, io addr is %x,io_size is %d\n",pDevice->memaddr,pDevice->ioaddr,pDevice->io_size);
+	printk("after get pci_info memaddr is %x, io addr is %x,io_size is %d\n", pDevice->memaddr, pDevice->ioaddr, pDevice->io_size);
 	{
 		int i;
-		u32			bar,len;
+		u32 bar, len;
 		u32 address[] = {
-		PCI_BASE_ADDRESS_0,
-		PCI_BASE_ADDRESS_1,
-		PCI_BASE_ADDRESS_2,
-		PCI_BASE_ADDRESS_3,
-		PCI_BASE_ADDRESS_4,
-		PCI_BASE_ADDRESS_5,
-		0};
-		for (i=0;address[i];i++)
-		{
+			PCI_BASE_ADDRESS_0,
+			PCI_BASE_ADDRESS_1,
+			PCI_BASE_ADDRESS_2,
+			PCI_BASE_ADDRESS_3,
+			PCI_BASE_ADDRESS_4,
+			PCI_BASE_ADDRESS_5,
+			0};
+		for (i = 0; address[i]; i++) {
 			//pci_write_config_dword(pcid,address[i], 0xFFFFFFFF);
 			pci_read_config_dword(pcid, address[i], &bar);
-			printk("bar %d is %x\n",i,bar);
-			if (!bar)
-			{
-				printk("bar %d not implemented\n",i);
+			printk("bar %d is %x\n", i, bar);
+			if (!bar) {
+				printk("bar %d not implemented\n", i);
 				continue;
 			}
 			if (bar & PCI_BASE_ADDRESS_SPACE_IO) {
-			/* This is IO */
+				/* This is IO */
 
-			len = bar & (PCI_BASE_ADDRESS_IO_MASK & 0xFFFF);
-			len = len & ~(len - 1);
+				len = bar & (PCI_BASE_ADDRESS_IO_MASK & 0xFFFF);
+				len = len & ~(len - 1);
 
-			printk("IO space:  len in IO %x, BAR %d\n", len, i);
-			}
-			else
-			{
+				printk("IO space:  len in IO %x, BAR %d\n", len, i);
+			} else {
 				len = bar & 0xFFFFFFF0;
 				len = ~len + 1;
 
@@ -1001,813 +939,745 @@ vt6655_probe(struct pci_dev *pcid, const struct pci_device_id *ent)
 	}
 #endif
 
-
 #endif
 
 #ifdef	DEBUG
-	//return  0  ;
+	//return  0;
 #endif
-    pDevice->PortOffset = (unsigned long)ioremap(pDevice->memaddr & PCI_BASE_ADDRESS_MEM_MASK, pDevice->io_size);
+	pDevice->PortOffset = (unsigned long)ioremap(pDevice->memaddr & PCI_BASE_ADDRESS_MEM_MASK, pDevice->io_size);
 	//pDevice->PortOffset = (unsigned long)ioremap(pDevice->ioaddr & PCI_BASE_ADDRESS_IO_MASK, pDevice->io_size);
 
-	if(pDevice->PortOffset == 0) {
-       printk(KERN_ERR DEVICE_NAME ": Failed to IO remapping ..\n");
-       device_free_info(pDevice);
-        return -ENODEV;
-    }
-
-
-
+	if (pDevice->PortOffset == 0) {
+		printk(KERN_ERR DEVICE_NAME ": Failed to IO remapping ..\n");
+		device_free_info(pDevice);
+		return -ENODEV;
+	}
 
-    rc = pci_request_regions(pcid, DEVICE_NAME);
-    if (rc) {
-        printk(KERN_ERR DEVICE_NAME ": Failed to find PCI device\n");
-        device_free_info(pDevice);
-        return -ENODEV;
-    }
+	rc = pci_request_regions(pcid, DEVICE_NAME);
+	if (rc) {
+		printk(KERN_ERR DEVICE_NAME ": Failed to find PCI device\n");
+		device_free_info(pDevice);
+		return -ENODEV;
+	}
 
-    dev->base_addr = pDevice->ioaddr;
+	dev->base_addr = pDevice->ioaddr;
 #ifdef	PLICE_DEBUG
-	unsigned char 	value;
+	unsigned char value;
 
 	VNSvInPortB(pDevice->PortOffset+0x4F, &value);
-	printk("Before write: value is %x\n",value);
+	printk("Before write: value is %x\n", value);
 	//VNSvInPortB(pDevice->PortOffset+0x3F, 0x00);
-	VNSvOutPortB(pDevice->PortOffset,value);
+	VNSvOutPortB(pDevice->PortOffset, value);
 	VNSvInPortB(pDevice->PortOffset+0x4F, &value);
-	printk("After write: value is %x\n",value);
+	printk("After write: value is %x\n", value);
 #endif
 
-
-
 #ifdef IO_MAP
-    pDevice->PortOffset = pDevice->ioaddr;
+	pDevice->PortOffset = pDevice->ioaddr;
 #endif
-    // do reset
-    if (!MACbSoftwareReset(pDevice->PortOffset)) {
-        printk(KERN_ERR DEVICE_NAME ": Failed to access MAC hardware..\n");
-        device_free_info(pDevice);
-        return -ENODEV;
-    }
-    // initial to reload eeprom
-    MACvInitialize(pDevice->PortOffset);
-    MACvReadEtherAddress(pDevice->PortOffset, dev->dev_addr);
-
-    device_get_options(pDevice, device_nics-1, dev->name);
-    device_set_options(pDevice);
-    //Mask out the options cannot be set to the chip
-    pDevice->sOpts.flags &= pChip_info->flags;
-
-    //Enable the chip specified capabilities
-    pDevice->flags = pDevice->sOpts.flags | (pChip_info->flags & 0xFF000000UL);
-    pDevice->tx_80211 = device_dma0_tx_80211;
-    pDevice->sMgmtObj.pAdapter = (void *)pDevice;
-    pDevice->pMgmt = &(pDevice->sMgmtObj);
-
-    dev->irq                = pcid->irq;
-    dev->netdev_ops         = &device_netdev_ops;
+	// do reset
+	if (!MACbSoftwareReset(pDevice->PortOffset)) {
+		printk(KERN_ERR DEVICE_NAME ": Failed to access MAC hardware..\n");
+		device_free_info(pDevice);
+		return -ENODEV;
+	}
+	// initial to reload eeprom
+	MACvInitialize(pDevice->PortOffset);
+	MACvReadEtherAddress(pDevice->PortOffset, dev->dev_addr);
 
-	dev->wireless_handlers = (struct iw_handler_def *)&iwctl_handler_def;
+	device_get_options(pDevice, device_nics-1, dev->name);
+	device_set_options(pDevice);
+	//Mask out the options cannot be set to the chip
+	pDevice->sOpts.flags &= pChip_info->flags;
 
-    rc = register_netdev(dev);
-    if (rc)
-    {
-        printk(KERN_ERR DEVICE_NAME " Failed to register netdev\n");
-        device_free_info(pDevice);
-        return -ENODEV;
-    }
-    device_print_info(pDevice);
-    pci_set_drvdata(pcid, pDevice);
-    return 0;
+	//Enable the chip specified capabilities
+	pDevice->flags = pDevice->sOpts.flags | (pChip_info->flags & 0xFF000000UL);
+	pDevice->tx_80211 = device_dma0_tx_80211;
+	pDevice->sMgmtObj.pAdapter = (void *)pDevice;
+	pDevice->pMgmt = &(pDevice->sMgmtObj);
 
+	dev->irq                = pcid->irq;
+	dev->netdev_ops         = &device_netdev_ops;
+
+	dev->wireless_handlers = (struct iw_handler_def *)&iwctl_handler_def;
+
+	rc = register_netdev(dev);
+	if (rc) {
+		printk(KERN_ERR DEVICE_NAME " Failed to register netdev\n");
+		device_free_info(pDevice);
+		return -ENODEV;
+	}
+	device_print_info(pDevice);
+	pci_set_drvdata(pcid, pDevice);
+	return 0;
 }
 
 static void device_print_info(PSDevice pDevice)
 {
-    struct net_device* dev=pDevice->dev;
+	struct net_device *dev = pDevice->dev;
 
-    DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "%s: %s\n",dev->name, get_chip_name(pDevice->chip_id));
-    DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "%s: MAC=%pM", dev->name, dev->dev_addr);
+	DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "%s: %s\n", dev->name, get_chip_name(pDevice->chip_id));
+	DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "%s: MAC=%pM", dev->name, dev->dev_addr);
 #ifdef IO_MAP
-    DBG_PRT(MSG_LEVEL_INFO, KERN_INFO" IO=0x%lx  ",(unsigned long) pDevice->ioaddr);
-    DBG_PRT(MSG_LEVEL_INFO, KERN_INFO" IRQ=%d \n", pDevice->dev->irq);
+	DBG_PRT(MSG_LEVEL_INFO, KERN_INFO " IO=0x%lx  ", (unsigned long)pDevice->ioaddr);
+	DBG_PRT(MSG_LEVEL_INFO, KERN_INFO " IRQ=%d \n", pDevice->dev->irq);
 #else
-    DBG_PRT(MSG_LEVEL_INFO, KERN_INFO" IO=0x%lx Mem=0x%lx ",
-		    (unsigned long) pDevice->ioaddr,(unsigned long) pDevice->PortOffset);
-    DBG_PRT(MSG_LEVEL_INFO, KERN_INFO" IRQ=%d \n", pDevice->dev->irq);
+	DBG_PRT(MSG_LEVEL_INFO, KERN_INFO " IO=0x%lx Mem=0x%lx ",
+		(unsigned long)pDevice->ioaddr, (unsigned long)pDevice->PortOffset);
+	DBG_PRT(MSG_LEVEL_INFO, KERN_INFO " IRQ=%d \n", pDevice->dev->irq);
 #endif
-
 }
 
-static void vt6655_init_info(struct pci_dev* pcid, PSDevice* ppDevice,
-    PCHIP_INFO pChip_info) {
+static void vt6655_init_info(struct pci_dev *pcid, PSDevice *ppDevice,
+			     PCHIP_INFO pChip_info) {
+	PSDevice p;
 
-    PSDevice p;
+	memset(*ppDevice, 0, sizeof(DEVICE_INFO));
 
-    memset(*ppDevice,0,sizeof(DEVICE_INFO));
-
-    if (pDevice_Infos == NULL) {
-        pDevice_Infos =*ppDevice;
-    }
-    else {
-        for (p=pDevice_Infos;p->next!=NULL;p=p->next)
-            do {} while (0);
-        p->next = *ppDevice;
-        (*ppDevice)->prev = p;
-    }
+	if (pDevice_Infos == NULL) {
+		pDevice_Infos = *ppDevice;
+	} else {
+		for (p = pDevice_Infos; p->next != NULL; p = p->next)
+			do {} while (0);
+		p->next = *ppDevice;
+		(*ppDevice)->prev = p;
+	}
 
-    (*ppDevice)->pcid = pcid;
-    (*ppDevice)->chip_id = pChip_info->chip_id;
-    (*ppDevice)->io_size = pChip_info->io_size;
-    (*ppDevice)->nTxQueues = pChip_info->nTxQueue;
-    (*ppDevice)->multicast_limit =32;
+	(*ppDevice)->pcid = pcid;
+	(*ppDevice)->chip_id = pChip_info->chip_id;
+	(*ppDevice)->io_size = pChip_info->io_size;
+	(*ppDevice)->nTxQueues = pChip_info->nTxQueue;
+	(*ppDevice)->multicast_limit = 32;
 
-    spin_lock_init(&((*ppDevice)->lock));
+	spin_lock_init(&((*ppDevice)->lock));
 }
 
-static bool device_get_pci_info(PSDevice pDevice, struct pci_dev* pcid) {
-
-    u16 pci_cmd;
-    u8  b;
-    unsigned int cis_addr;
+static bool device_get_pci_info(PSDevice pDevice, struct pci_dev *pcid) {
+	u16 pci_cmd;
+	u8  b;
+	unsigned int cis_addr;
 #ifdef	PLICE_DEBUG
 	unsigned char pci_config[256];
-	unsigned char 	value =0x00;
-	int		ii,j;
-	u16	max_lat=0x0000;
-	memset(pci_config,0x00,256);
+	unsigned char value = 0x00;
+	int		ii, j;
+	u16	max_lat = 0x0000;
+	memset(pci_config, 0x00, 256);
 #endif
 
-    pci_read_config_byte(pcid, PCI_REVISION_ID, &pDevice->byRevId);
-    pci_read_config_word(pcid, PCI_SUBSYSTEM_ID,&pDevice->SubSystemID);
-    pci_read_config_word(pcid, PCI_SUBSYSTEM_VENDOR_ID, &pDevice->SubVendorID);
-    pci_read_config_word(pcid, PCI_COMMAND, (u16 *) & (pci_cmd));
+	pci_read_config_byte(pcid, PCI_REVISION_ID, &pDevice->byRevId);
+	pci_read_config_word(pcid, PCI_SUBSYSTEM_ID, &pDevice->SubSystemID);
+	pci_read_config_word(pcid, PCI_SUBSYSTEM_VENDOR_ID, &pDevice->SubVendorID);
+	pci_read_config_word(pcid, PCI_COMMAND, (u16 *)&(pci_cmd));
 
-    pci_set_master(pcid);
+	pci_set_master(pcid);
 
-    pDevice->memaddr = pci_resource_start(pcid,0);
-    pDevice->ioaddr = pci_resource_start(pcid,1);
+	pDevice->memaddr = pci_resource_start(pcid, 0);
+	pDevice->ioaddr = pci_resource_start(pcid, 1);
 
 #ifdef	DEBUG
 //	pDevice->ioaddr = pci_resource_start(pcid, 0);
 //	pDevice->memaddr = pci_resource_start(pcid,1);
 #endif
 
-    cis_addr = pci_resource_start(pcid,2);
+	cis_addr = pci_resource_start(pcid, 2);
 
-    pDevice->pcid = pcid;
+	pDevice->pcid = pcid;
 
-    pci_read_config_byte(pcid, PCI_COMMAND, &b);
-    pci_write_config_byte(pcid, PCI_COMMAND, (b|PCI_COMMAND_MASTER));
+	pci_read_config_byte(pcid, PCI_COMMAND, &b);
+	pci_write_config_byte(pcid, PCI_COMMAND, (b|PCI_COMMAND_MASTER));
 
 #ifdef	PLICE_DEBUG
-   	//pci_read_config_word(pcid,PCI_MAX_LAT,&max_lat);
-	//printk("max lat is %x,SubSystemID is %x\n",max_lat,pDevice->SubSystemID);
+	//pci_read_config_word(pcid,PCI_MAX_LAT,&max_lat);
 	//for (ii=0;ii<0xFF;ii++)
 	//pci_read_config_word(pcid,PCI_MAX_LAT,&max_lat);
 	//max_lat  = 0x20;
 	//pci_write_config_word(pcid,PCI_MAX_LAT,max_lat);
 	//pci_read_config_word(pcid,PCI_MAX_LAT,&max_lat);
-	//printk("max lat is %x\n",max_lat);
 
-	for (ii=0;ii<0xFF;ii++)
-	{
-		pci_read_config_byte(pcid,ii,&value);
+	for (ii = 0; ii < 0xFF; ii++) {
+		pci_read_config_byte(pcid, ii, &value);
 		pci_config[ii] = value;
 	}
-	for (ii=0,j=1;ii<0x100;ii++,j++)
-	{
-		if (j %16 == 0)
-		{
-			printk("%x:",pci_config[ii]);
+	for (ii = 0, j = 1; ii < 0x100; ii++, j++) {
+		if (j % 16 == 0) {
+			printk("%x:", pci_config[ii]);
 			printk("\n");
-		}
-		else
-		{
-			printk("%x:",pci_config[ii]);
+		} else {
+			printk("%x:", pci_config[ii]);
 		}
 	}
 #endif
-    return true;
+	return true;
 }
 
 static void device_free_info(PSDevice pDevice) {
-    PSDevice         ptr;
-    struct net_device*  dev=pDevice->dev;
+	PSDevice         ptr;
+	struct net_device *dev = pDevice->dev;
 
-    ASSERT(pDevice);
+	ASSERT(pDevice);
 //2008-0714-01<Add>by chester
-device_release_WPADEV(pDevice);
+	device_release_WPADEV(pDevice);
 
 //2008-07-21-01<Add>by MikeLiu
 //unregister wpadev
-   if(wpa_set_wpadev(pDevice, 0)!=0)
-     printk("unregister wpadev fail?\n");
-
-    if (pDevice_Infos==NULL)
-        return;
-
-    for (ptr=pDevice_Infos;ptr && (ptr!=pDevice);ptr=ptr->next)
-            do {} while (0);
-
-    if (ptr==pDevice) {
-        if (ptr==pDevice_Infos)
-            pDevice_Infos=ptr->next;
-        else
-            ptr->prev->next=ptr->next;
-    }
-    else {
-        DBG_PRT(MSG_LEVEL_ERR, KERN_ERR "info struct not found\n");
-        return;
-    }
+	if (wpa_set_wpadev(pDevice, 0) != 0)
+		printk("unregister wpadev fail?\n");
+
+	if (pDevice_Infos == NULL)
+		return;
+
+	for (ptr = pDevice_Infos; ptr && (ptr != pDevice); ptr = ptr->next)
+		do {} while (0);
+
+	if (ptr == pDevice) {
+		if (ptr == pDevice_Infos)
+			pDevice_Infos = ptr->next;
+		else
+			ptr->prev->next = ptr->next;
+	} else {
+		DBG_PRT(MSG_LEVEL_ERR, KERN_ERR "info struct not found\n");
+		return;
+	}
 #ifdef HOSTAP
-    if (dev)
-        vt6655_hostap_set_hostapd(pDevice, 0, 0);
+	if (dev)
+		vt6655_hostap_set_hostapd(pDevice, 0, 0);
 #endif
-    if (dev)
-        unregister_netdev(dev);
+	if (dev)
+		unregister_netdev(dev);
 
-    if (pDevice->PortOffset)
-        iounmap((void *)pDevice->PortOffset);
+	if (pDevice->PortOffset)
+		iounmap((void *)pDevice->PortOffset);
 
-    if (pDevice->pcid)
-        pci_release_regions(pDevice->pcid);
-    if (dev)
-        free_netdev(dev);
+	if (pDevice->pcid)
+		pci_release_regions(pDevice->pcid);
+	if (dev)
+		free_netdev(dev);
 
-    if (pDevice->pcid) {
-        pci_set_drvdata(pDevice->pcid,NULL);
-    }
+	if (pDevice->pcid) {
+		pci_set_drvdata(pDevice->pcid, NULL);
+	}
 }
 
 static bool device_init_rings(PSDevice pDevice) {
-    void*   vir_pool;
-
-
-    /*allocate all RD/TD rings a single pool*/
-    vir_pool = pci_alloc_consistent(pDevice->pcid,
-                    pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc) +
-                    pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc) +
-                    pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc) +
-                    pDevice->sOpts.nTxDescs[1] * sizeof(STxDesc),
-                    &pDevice->pool_dma);
-
-    if (vir_pool == NULL) {
-        DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "%s : allocate desc dma memory failed\n", pDevice->dev->name);
-        return false;
-    }
-
-    memset(vir_pool, 0,
-            pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc) +
-            pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc) +
-            pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc) +
-            pDevice->sOpts.nTxDescs[1] * sizeof(STxDesc)
-          );
-
-    pDevice->aRD0Ring = vir_pool;
-    pDevice->aRD1Ring = vir_pool +
-                        pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc);
-
-
-    pDevice->rd0_pool_dma = pDevice->pool_dma;
-    pDevice->rd1_pool_dma = pDevice->rd0_pool_dma +
-                            pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc);
-
-    pDevice->tx0_bufs = pci_alloc_consistent(pDevice->pcid,
-                    pDevice->sOpts.nTxDescs[0] * PKT_BUF_SZ +
-                    pDevice->sOpts.nTxDescs[1] * PKT_BUF_SZ +
-                    CB_BEACON_BUF_SIZE +
-                    CB_MAX_BUF_SIZE,
-                    &pDevice->tx_bufs_dma0);
-
-    if (pDevice->tx0_bufs == NULL) {
-        DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "%s: allocate buf dma memory failed\n", pDevice->dev->name);
-        pci_free_consistent(pDevice->pcid,
-            pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc) +
-            pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc) +
-            pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc) +
-            pDevice->sOpts.nTxDescs[1] * sizeof(STxDesc),
-            vir_pool, pDevice->pool_dma
-            );
-        return false;
-    }
-
-    memset(pDevice->tx0_bufs, 0,
-           pDevice->sOpts.nTxDescs[0] * PKT_BUF_SZ +
-           pDevice->sOpts.nTxDescs[1] * PKT_BUF_SZ +
-           CB_BEACON_BUF_SIZE +
-           CB_MAX_BUF_SIZE
-          );
-
-    pDevice->td0_pool_dma = pDevice->rd1_pool_dma +
-            pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc);
-
-    pDevice->td1_pool_dma = pDevice->td0_pool_dma +
-            pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc);
-
+	void *vir_pool;
+
+	/*allocate all RD/TD rings a single pool*/
+	vir_pool = pci_alloc_consistent(pDevice->pcid,
+					pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc) +
+					pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc) +
+					pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc) +
+					pDevice->sOpts.nTxDescs[1] * sizeof(STxDesc),
+					&pDevice->pool_dma);
+
+	if (vir_pool == NULL) {
+		DBG_PRT(MSG_LEVEL_ERR, KERN_ERR "%s : allocate desc dma memory failed\n", pDevice->dev->name);
+		return false;
+	}
 
-    // vir_pool: pvoid type
-    pDevice->apTD0Rings = vir_pool
-                          + pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc)
-                          + pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc);
+	memset(vir_pool, 0,
+	       pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc) +
+	       pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc) +
+	       pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc) +
+	       pDevice->sOpts.nTxDescs[1] * sizeof(STxDesc)
+		);
+
+	pDevice->aRD0Ring = vir_pool;
+	pDevice->aRD1Ring = vir_pool +
+		pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc);
+
+	pDevice->rd0_pool_dma = pDevice->pool_dma;
+	pDevice->rd1_pool_dma = pDevice->rd0_pool_dma +
+		pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc);
+
+	pDevice->tx0_bufs = pci_alloc_consistent(pDevice->pcid,
+						 pDevice->sOpts.nTxDescs[0] * PKT_BUF_SZ +
+						 pDevice->sOpts.nTxDescs[1] * PKT_BUF_SZ +
+						 CB_BEACON_BUF_SIZE +
+						 CB_MAX_BUF_SIZE,
+						 &pDevice->tx_bufs_dma0);
+
+	if (pDevice->tx0_bufs == NULL) {
+		DBG_PRT(MSG_LEVEL_ERR, KERN_ERR "%s: allocate buf dma memory failed\n", pDevice->dev->name);
+		pci_free_consistent(pDevice->pcid,
+				    pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc) +
+				    pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc) +
+				    pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc) +
+				    pDevice->sOpts.nTxDescs[1] * sizeof(STxDesc),
+				    vir_pool, pDevice->pool_dma
+			);
+		return false;
+	}
 
-    pDevice->apTD1Rings = vir_pool
-            + pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc)
-            + pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc)
-            + pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc);
+	memset(pDevice->tx0_bufs, 0,
+	       pDevice->sOpts.nTxDescs[0] * PKT_BUF_SZ +
+	       pDevice->sOpts.nTxDescs[1] * PKT_BUF_SZ +
+	       CB_BEACON_BUF_SIZE +
+	       CB_MAX_BUF_SIZE
+		);
 
+	pDevice->td0_pool_dma = pDevice->rd1_pool_dma +
+		pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc);
 
-    pDevice->tx1_bufs = pDevice->tx0_bufs +
-            pDevice->sOpts.nTxDescs[0] * PKT_BUF_SZ;
+	pDevice->td1_pool_dma = pDevice->td0_pool_dma +
+		pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc);
 
+	// vir_pool: pvoid type
+	pDevice->apTD0Rings = vir_pool
+		+ pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc)
+		+ pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc);
 
-    pDevice->tx_beacon_bufs = pDevice->tx1_bufs +
-            pDevice->sOpts.nTxDescs[1] * PKT_BUF_SZ;
+	pDevice->apTD1Rings = vir_pool
+		+ pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc)
+		+ pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc)
+		+ pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc);
 
-    pDevice->pbyTmpBuff = pDevice->tx_beacon_bufs +
-            CB_BEACON_BUF_SIZE;
+	pDevice->tx1_bufs = pDevice->tx0_bufs +
+		pDevice->sOpts.nTxDescs[0] * PKT_BUF_SZ;
 
-    pDevice->tx_bufs_dma1 = pDevice->tx_bufs_dma0 +
-            pDevice->sOpts.nTxDescs[0] * PKT_BUF_SZ;
+	pDevice->tx_beacon_bufs = pDevice->tx1_bufs +
+		pDevice->sOpts.nTxDescs[1] * PKT_BUF_SZ;
 
+	pDevice->pbyTmpBuff = pDevice->tx_beacon_bufs +
+		CB_BEACON_BUF_SIZE;
 
-    pDevice->tx_beacon_dma = pDevice->tx_bufs_dma1 +
-            pDevice->sOpts.nTxDescs[1] * PKT_BUF_SZ;
+	pDevice->tx_bufs_dma1 = pDevice->tx_bufs_dma0 +
+		pDevice->sOpts.nTxDescs[0] * PKT_BUF_SZ;
 
+	pDevice->tx_beacon_dma = pDevice->tx_bufs_dma1 +
+		pDevice->sOpts.nTxDescs[1] * PKT_BUF_SZ;
 
-    return true;
+	return true;
 }
 
 static void device_free_rings(PSDevice pDevice) {
-
-    pci_free_consistent(pDevice->pcid,
-            pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc) +
-            pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc) +
-            pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc) +
-            pDevice->sOpts.nTxDescs[1] * sizeof(STxDesc)
-            ,
-            pDevice->aRD0Ring, pDevice->pool_dma
-        );
-
-    if (pDevice->tx0_bufs)
-        pci_free_consistent(pDevice->pcid,
-           pDevice->sOpts.nTxDescs[0] * PKT_BUF_SZ +
-           pDevice->sOpts.nTxDescs[1] * PKT_BUF_SZ +
-           CB_BEACON_BUF_SIZE +
-           CB_MAX_BUF_SIZE,
-           pDevice->tx0_bufs, pDevice->tx_bufs_dma0
-        );
+	pci_free_consistent(pDevice->pcid,
+			    pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc) +
+			    pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc) +
+			    pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc) +
+			    pDevice->sOpts.nTxDescs[1] * sizeof(STxDesc)
+			    ,
+			    pDevice->aRD0Ring, pDevice->pool_dma
+		);
+
+	if (pDevice->tx0_bufs)
+		pci_free_consistent(pDevice->pcid,
+				    pDevice->sOpts.nTxDescs[0] * PKT_BUF_SZ +
+				    pDevice->sOpts.nTxDescs[1] * PKT_BUF_SZ +
+				    CB_BEACON_BUF_SIZE +
+				    CB_MAX_BUF_SIZE,
+				    pDevice->tx0_bufs, pDevice->tx_bufs_dma0
+			);
 }
 
 static void device_init_rd0_ring(PSDevice pDevice) {
-    int i;
-    dma_addr_t      curr = pDevice->rd0_pool_dma;
-    PSRxDesc        pDesc;
-
-    /* Init the RD0 ring entries */
-    for (i = 0; i < pDevice->sOpts.nRxDescs0; i ++, curr += sizeof(SRxDesc)) {
-        pDesc = &(pDevice->aRD0Ring[i]);
-        pDesc->pRDInfo = alloc_rd_info();
-        ASSERT(pDesc->pRDInfo);
-        if (!device_alloc_rx_buf(pDevice, pDesc)) {
-            DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "%s: can not alloc rx bufs\n",
-            pDevice->dev->name);
-        }
-        pDesc->next = &(pDevice->aRD0Ring[(i+1) % pDevice->sOpts.nRxDescs0]);
-        pDesc->pRDInfo->curr_desc = cpu_to_le32(curr);
-        pDesc->next_desc = cpu_to_le32(curr + sizeof(SRxDesc));
-    }
-
-    if (i > 0)
-        pDevice->aRD0Ring[i-1].next_desc = cpu_to_le32(pDevice->rd0_pool_dma);
-    pDevice->pCurrRD[0] = &(pDevice->aRD0Ring[0]);
-}
+	int i;
+	dma_addr_t      curr = pDevice->rd0_pool_dma;
+	PSRxDesc        pDesc;
+
+	/* Init the RD0 ring entries */
+	for (i = 0; i < pDevice->sOpts.nRxDescs0; i ++, curr += sizeof(SRxDesc)) {
+		pDesc = &(pDevice->aRD0Ring[i]);
+		pDesc->pRDInfo = alloc_rd_info();
+		ASSERT(pDesc->pRDInfo);
+		if (!device_alloc_rx_buf(pDevice, pDesc)) {
+			DBG_PRT(MSG_LEVEL_ERR, KERN_ERR "%s: can not alloc rx bufs\n",
+				pDevice->dev->name);
+		}
+		pDesc->next = &(pDevice->aRD0Ring[(i+1) % pDevice->sOpts.nRxDescs0]);
+		pDesc->pRDInfo->curr_desc = cpu_to_le32(curr);
+		pDesc->next_desc = cpu_to_le32(curr + sizeof(SRxDesc));
+	}
 
+	if (i > 0)
+		pDevice->aRD0Ring[i-1].next_desc = cpu_to_le32(pDevice->rd0_pool_dma);
+	pDevice->pCurrRD[0] = &(pDevice->aRD0Ring[0]);
+}
 
 static void device_init_rd1_ring(PSDevice pDevice) {
-    int i;
-    dma_addr_t      curr = pDevice->rd1_pool_dma;
-    PSRxDesc        pDesc;
-
-    /* Init the RD1 ring entries */
-    for (i = 0; i < pDevice->sOpts.nRxDescs1; i ++, curr += sizeof(SRxDesc)) {
-        pDesc = &(pDevice->aRD1Ring[i]);
-        pDesc->pRDInfo = alloc_rd_info();
-        ASSERT(pDesc->pRDInfo);
-        if (!device_alloc_rx_buf(pDevice, pDesc)) {
-            DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "%s: can not alloc rx bufs\n",
-            pDevice->dev->name);
-        }
-        pDesc->next = &(pDevice->aRD1Ring[(i+1) % pDevice->sOpts.nRxDescs1]);
-        pDesc->pRDInfo->curr_desc = cpu_to_le32(curr);
-        pDesc->next_desc = cpu_to_le32(curr + sizeof(SRxDesc));
-    }
-
-    if (i > 0)
-        pDevice->aRD1Ring[i-1].next_desc = cpu_to_le32(pDevice->rd1_pool_dma);
-    pDevice->pCurrRD[1] = &(pDevice->aRD1Ring[0]);
-}
+	int i;
+	dma_addr_t      curr = pDevice->rd1_pool_dma;
+	PSRxDesc        pDesc;
+
+	/* Init the RD1 ring entries */
+	for (i = 0; i < pDevice->sOpts.nRxDescs1; i ++, curr += sizeof(SRxDesc)) {
+		pDesc = &(pDevice->aRD1Ring[i]);
+		pDesc->pRDInfo = alloc_rd_info();
+		ASSERT(pDesc->pRDInfo);
+		if (!device_alloc_rx_buf(pDevice, pDesc)) {
+			DBG_PRT(MSG_LEVEL_ERR, KERN_ERR "%s: can not alloc rx bufs\n",
+				pDevice->dev->name);
+		}
+		pDesc->next = &(pDevice->aRD1Ring[(i+1) % pDevice->sOpts.nRxDescs1]);
+		pDesc->pRDInfo->curr_desc = cpu_to_le32(curr);
+		pDesc->next_desc = cpu_to_le32(curr + sizeof(SRxDesc));
+	}
 
+	if (i > 0)
+		pDevice->aRD1Ring[i-1].next_desc = cpu_to_le32(pDevice->rd1_pool_dma);
+	pDevice->pCurrRD[1] = &(pDevice->aRD1Ring[0]);
+}
 
 static void device_init_defrag_cb(PSDevice pDevice) {
-    int i;
-    PSDeFragControlBlock pDeF;
-
-    /* Init the fragment ctl entries */
-    for (i = 0; i < CB_MAX_RX_FRAG; i++) {
-        pDeF = &(pDevice->sRxDFCB[i]);
-        if (!device_alloc_frag_buf(pDevice, pDeF)) {
-            DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "%s: can not alloc frag bufs\n",
-                pDevice->dev->name);
-        }
-    }
-    pDevice->cbDFCB = CB_MAX_RX_FRAG;
-    pDevice->cbFreeDFCB = pDevice->cbDFCB;
+	int i;
+	PSDeFragControlBlock pDeF;
+
+	/* Init the fragment ctl entries */
+	for (i = 0; i < CB_MAX_RX_FRAG; i++) {
+		pDeF = &(pDevice->sRxDFCB[i]);
+		if (!device_alloc_frag_buf(pDevice, pDeF)) {
+			DBG_PRT(MSG_LEVEL_ERR, KERN_ERR "%s: can not alloc frag bufs\n",
+				pDevice->dev->name);
+		}
+	}
+	pDevice->cbDFCB = CB_MAX_RX_FRAG;
+	pDevice->cbFreeDFCB = pDevice->cbDFCB;
 }
 
-
-
-
 static void device_free_rd0_ring(PSDevice pDevice) {
-    int i;
-
-    for (i = 0; i < pDevice->sOpts.nRxDescs0; i++) {
-        PSRxDesc        pDesc =&(pDevice->aRD0Ring[i]);
-        PDEVICE_RD_INFO  pRDInfo =pDesc->pRDInfo;
+	int i;
 
-        pci_unmap_single(pDevice->pcid,pRDInfo->skb_dma,
-           pDevice->rx_buf_sz, PCI_DMA_FROMDEVICE);
+	for (i = 0; i < pDevice->sOpts.nRxDescs0; i++) {
+		PSRxDesc        pDesc = &(pDevice->aRD0Ring[i]);
+		PDEVICE_RD_INFO  pRDInfo = pDesc->pRDInfo;
 
-        dev_kfree_skb(pRDInfo->skb);
+		pci_unmap_single(pDevice->pcid, pRDInfo->skb_dma,
+				 pDevice->rx_buf_sz, PCI_DMA_FROMDEVICE);
 
-        kfree((void *)pDesc->pRDInfo);
-    }
+		dev_kfree_skb(pRDInfo->skb);
 
+		kfree((void *)pDesc->pRDInfo);
+	}
 }
 
 static void device_free_rd1_ring(PSDevice pDevice) {
-    int i;
-
-
-    for (i = 0; i < pDevice->sOpts.nRxDescs1; i++) {
-        PSRxDesc        pDesc=&(pDevice->aRD1Ring[i]);
-        PDEVICE_RD_INFO  pRDInfo=pDesc->pRDInfo;
+	int i;
 
-        pci_unmap_single(pDevice->pcid,pRDInfo->skb_dma,
-           pDevice->rx_buf_sz, PCI_DMA_FROMDEVICE);
+	for (i = 0; i < pDevice->sOpts.nRxDescs1; i++) {
+		PSRxDesc        pDesc = &(pDevice->aRD1Ring[i]);
+		PDEVICE_RD_INFO  pRDInfo = pDesc->pRDInfo;
 
-        dev_kfree_skb(pRDInfo->skb);
+		pci_unmap_single(pDevice->pcid, pRDInfo->skb_dma,
+				 pDevice->rx_buf_sz, PCI_DMA_FROMDEVICE);
 
-        kfree((void *)pDesc->pRDInfo);
-    }
+		dev_kfree_skb(pRDInfo->skb);
 
+		kfree((void *)pDesc->pRDInfo);
+	}
 }
 
 static void device_free_frag_buf(PSDevice pDevice) {
-    PSDeFragControlBlock pDeF;
-    int i;
-
-    for (i = 0; i < CB_MAX_RX_FRAG; i++) {
-
-        pDeF = &(pDevice->sRxDFCB[i]);
+	PSDeFragControlBlock pDeF;
+	int i;
 
-        if (pDeF->skb)
-            dev_kfree_skb(pDeF->skb);
+	for (i = 0; i < CB_MAX_RX_FRAG; i++) {
+		pDeF = &(pDevice->sRxDFCB[i]);
 
-    }
+		if (pDeF->skb)
+			dev_kfree_skb(pDeF->skb);
 
+	}
 }
 
 static void device_init_td0_ring(PSDevice pDevice) {
-    int i;
-    dma_addr_t  curr;
-    PSTxDesc        pDesc;
-
-    curr = pDevice->td0_pool_dma;
-    for (i = 0; i < pDevice->sOpts.nTxDescs[0]; i++, curr += sizeof(STxDesc)) {
-        pDesc = &(pDevice->apTD0Rings[i]);
-        pDesc->pTDInfo = alloc_td_info();
-        ASSERT(pDesc->pTDInfo);
-        if (pDevice->flags & DEVICE_FLAGS_TX_ALIGN) {
-            pDesc->pTDInfo->buf = pDevice->tx0_bufs + (i)*PKT_BUF_SZ;
-            pDesc->pTDInfo->buf_dma = pDevice->tx_bufs_dma0 + (i)*PKT_BUF_SZ;
-        }
-        pDesc->next =&(pDevice->apTD0Rings[(i+1) % pDevice->sOpts.nTxDescs[0]]);
-        pDesc->pTDInfo->curr_desc = cpu_to_le32(curr);
-        pDesc->next_desc = cpu_to_le32(curr+sizeof(STxDesc));
-    }
-
-    if (i > 0)
-        pDevice->apTD0Rings[i-1].next_desc = cpu_to_le32(pDevice->td0_pool_dma);
-    pDevice->apTailTD[0] = pDevice->apCurrTD[0] =&(pDevice->apTD0Rings[0]);
+	int i;
+	dma_addr_t  curr;
+	PSTxDesc        pDesc;
+
+	curr = pDevice->td0_pool_dma;
+	for (i = 0; i < pDevice->sOpts.nTxDescs[0]; i++, curr += sizeof(STxDesc)) {
+		pDesc = &(pDevice->apTD0Rings[i]);
+		pDesc->pTDInfo = alloc_td_info();
+		ASSERT(pDesc->pTDInfo);
+		if (pDevice->flags & DEVICE_FLAGS_TX_ALIGN) {
+			pDesc->pTDInfo->buf = pDevice->tx0_bufs + (i)*PKT_BUF_SZ;
+			pDesc->pTDInfo->buf_dma = pDevice->tx_bufs_dma0 + (i)*PKT_BUF_SZ;
+		}
+		pDesc->next = &(pDevice->apTD0Rings[(i+1) % pDevice->sOpts.nTxDescs[0]]);
+		pDesc->pTDInfo->curr_desc = cpu_to_le32(curr);
+		pDesc->next_desc = cpu_to_le32(curr+sizeof(STxDesc));
+	}
 
+	if (i > 0)
+		pDevice->apTD0Rings[i-1].next_desc = cpu_to_le32(pDevice->td0_pool_dma);
+	pDevice->apTailTD[0] = pDevice->apCurrTD[0] = &(pDevice->apTD0Rings[0]);
 }
 
 static void device_init_td1_ring(PSDevice pDevice) {
-    int i;
-    dma_addr_t  curr;
-    PSTxDesc    pDesc;
-
-    /* Init the TD ring entries */
-    curr=pDevice->td1_pool_dma;
-    for (i = 0; i < pDevice->sOpts.nTxDescs[1]; i++, curr+=sizeof(STxDesc)) {
-        pDesc=&(pDevice->apTD1Rings[i]);
-        pDesc->pTDInfo = alloc_td_info();
-        ASSERT(pDesc->pTDInfo);
-        if (pDevice->flags & DEVICE_FLAGS_TX_ALIGN) {
-            pDesc->pTDInfo->buf=pDevice->tx1_bufs+(i)*PKT_BUF_SZ;
-            pDesc->pTDInfo->buf_dma=pDevice->tx_bufs_dma1+(i)*PKT_BUF_SZ;
-        }
-        pDesc->next=&(pDevice->apTD1Rings[(i+1) % pDevice->sOpts.nTxDescs[1]]);
-        pDesc->pTDInfo->curr_desc = cpu_to_le32(curr);
-        pDesc->next_desc = cpu_to_le32(curr+sizeof(STxDesc));
-    }
-
-    if (i > 0)
-        pDevice->apTD1Rings[i-1].next_desc = cpu_to_le32(pDevice->td1_pool_dma);
-    pDevice->apTailTD[1] = pDevice->apCurrTD[1] = &(pDevice->apTD1Rings[0]);
-}
-
+	int i;
+	dma_addr_t  curr;
+	PSTxDesc    pDesc;
+
+	/* Init the TD ring entries */
+	curr = pDevice->td1_pool_dma;
+	for (i = 0; i < pDevice->sOpts.nTxDescs[1]; i++, curr += sizeof(STxDesc)) {
+		pDesc = &(pDevice->apTD1Rings[i]);
+		pDesc->pTDInfo = alloc_td_info();
+		ASSERT(pDesc->pTDInfo);
+		if (pDevice->flags & DEVICE_FLAGS_TX_ALIGN) {
+			pDesc->pTDInfo->buf = pDevice->tx1_bufs + (i) * PKT_BUF_SZ;
+			pDesc->pTDInfo->buf_dma = pDevice->tx_bufs_dma1 + (i) * PKT_BUF_SZ;
+		}
+		pDesc->next = &(pDevice->apTD1Rings[(i + 1) % pDevice->sOpts.nTxDescs[1]]);
+		pDesc->pTDInfo->curr_desc = cpu_to_le32(curr);
+		pDesc->next_desc = cpu_to_le32(curr+sizeof(STxDesc));
+	}
 
+	if (i > 0)
+		pDevice->apTD1Rings[i-1].next_desc = cpu_to_le32(pDevice->td1_pool_dma);
+	pDevice->apTailTD[1] = pDevice->apCurrTD[1] = &(pDevice->apTD1Rings[0]);
+}
 
 static void device_free_td0_ring(PSDevice pDevice) {
-    int i;
-    for (i = 0; i < pDevice->sOpts.nTxDescs[0]; i++) {
-        PSTxDesc        pDesc=&(pDevice->apTD0Rings[i]);
-        PDEVICE_TD_INFO  pTDInfo=pDesc->pTDInfo;
+	int i;
+	for (i = 0; i < pDevice->sOpts.nTxDescs[0]; i++) {
+		PSTxDesc        pDesc = &(pDevice->apTD0Rings[i]);
+		PDEVICE_TD_INFO  pTDInfo = pDesc->pTDInfo;
 
-        if (pTDInfo->skb_dma && (pTDInfo->skb_dma != pTDInfo->buf_dma))
-            pci_unmap_single(pDevice->pcid,pTDInfo->skb_dma,
-               pTDInfo->skb->len, PCI_DMA_TODEVICE);
+		if (pTDInfo->skb_dma && (pTDInfo->skb_dma != pTDInfo->buf_dma))
+			pci_unmap_single(pDevice->pcid, pTDInfo->skb_dma,
+					 pTDInfo->skb->len, PCI_DMA_TODEVICE);
 
-        if (pTDInfo->skb)
-            dev_kfree_skb(pTDInfo->skb);
+		if (pTDInfo->skb)
+			dev_kfree_skb(pTDInfo->skb);
 
-        kfree((void *)pDesc->pTDInfo);
-    }
+		kfree((void *)pDesc->pTDInfo);
+	}
 }
 
 static void device_free_td1_ring(PSDevice pDevice) {
-    int i;
-
-    for (i = 0; i < pDevice->sOpts.nTxDescs[1]; i++) {
-        PSTxDesc        pDesc=&(pDevice->apTD1Rings[i]);
-        PDEVICE_TD_INFO  pTDInfo=pDesc->pTDInfo;
+	int i;
 
-        if (pTDInfo->skb_dma && (pTDInfo->skb_dma != pTDInfo->buf_dma))
-            pci_unmap_single(pDevice->pcid, pTDInfo->skb_dma,
-               pTDInfo->skb->len, PCI_DMA_TODEVICE);
+	for (i = 0; i < pDevice->sOpts.nTxDescs[1]; i++) {
+		PSTxDesc        pDesc = &(pDevice->apTD1Rings[i]);
+		PDEVICE_TD_INFO  pTDInfo = pDesc->pTDInfo;
 
-        if (pTDInfo->skb)
-            dev_kfree_skb(pTDInfo->skb);
+		if (pTDInfo->skb_dma && (pTDInfo->skb_dma != pTDInfo->buf_dma))
+			pci_unmap_single(pDevice->pcid, pTDInfo->skb_dma,
+					 pTDInfo->skb->len, PCI_DMA_TODEVICE);
 
-        kfree((void *)pDesc->pTDInfo);
-    }
+		if (pTDInfo->skb)
+			dev_kfree_skb(pTDInfo->skb);
 
+		kfree((void *)pDesc->pTDInfo);
+	}
 }
 
-
-
 /*-----------------------------------------------------------------*/
 
 static int device_rx_srv(PSDevice pDevice, unsigned int uIdx) {
-    PSRxDesc    pRD;
-    int works = 0;
+	PSRxDesc    pRD;
+	int works = 0;
 
-
-    for (pRD = pDevice->pCurrRD[uIdx];
-         pRD->m_rd0RD0.f1Owner == OWNED_BY_HOST;
-         pRD = pRD->next) {
+	for (pRD = pDevice->pCurrRD[uIdx];
+	     pRD->m_rd0RD0.f1Owner == OWNED_BY_HOST;
+	     pRD = pRD->next) {
 //        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pDevice->pCurrRD = %x, works = %d\n", pRD, works);
-        if (works++>15)
-            break;
-        if (device_receive_frame(pDevice, pRD)) {
-            if (!device_alloc_rx_buf(pDevice,pRD)) {
-                    DBG_PRT(MSG_LEVEL_ERR, KERN_ERR
-                    "%s: can not allocate rx buf\n", pDevice->dev->name);
-                    break;
-            }
-        }
-        pRD->m_rd0RD0.f1Owner = OWNED_BY_NIC;
-        pDevice->dev->last_rx = jiffies;
-    }
-
-    pDevice->pCurrRD[uIdx]=pRD;
-
-    return works;
-}
+		if (works++ > 15)
+			break;
+		if (device_receive_frame(pDevice, pRD)) {
+			if (!device_alloc_rx_buf(pDevice, pRD)) {
+				DBG_PRT(MSG_LEVEL_ERR, KERN_ERR
+					"%s: can not allocate rx buf\n", pDevice->dev->name);
+				break;
+			}
+		}
+		pRD->m_rd0RD0.f1Owner = OWNED_BY_NIC;
+		pDevice->dev->last_rx = jiffies;
+	}
 
+	pDevice->pCurrRD[uIdx] = pRD;
 
-static bool device_alloc_rx_buf(PSDevice pDevice, PSRxDesc pRD) {
+	return works;
+}
 
-    PDEVICE_RD_INFO pRDInfo=pRD->pRDInfo;
+static bool device_alloc_rx_buf(PSDevice pDevice, PSRxDesc pRD) {
+	PDEVICE_RD_INFO pRDInfo = pRD->pRDInfo;
+
+	pRDInfo->skb = dev_alloc_skb((int)pDevice->rx_buf_sz);
+	if (pRDInfo->skb == NULL)
+		return false;
+	ASSERT(pRDInfo->skb);
+	pRDInfo->skb->dev = pDevice->dev;
+	pRDInfo->skb_dma = pci_map_single(pDevice->pcid, skb_tail_pointer(pRDInfo->skb),
+					  pDevice->rx_buf_sz, PCI_DMA_FROMDEVICE);
+	*((unsigned int *)&(pRD->m_rd0RD0)) = 0; /* FIX cast */
+
+	pRD->m_rd0RD0.wResCount = cpu_to_le16(pDevice->rx_buf_sz);
+	pRD->m_rd0RD0.f1Owner = OWNED_BY_NIC;
+	pRD->m_rd1RD1.wReqCount = cpu_to_le16(pDevice->rx_buf_sz);
+	pRD->buff_addr = cpu_to_le32(pRDInfo->skb_dma);
+
+	return true;
+}
 
+bool device_alloc_frag_buf(PSDevice pDevice, PSDeFragControlBlock pDeF) {
+	pDeF->skb = dev_alloc_skb((int)pDevice->rx_buf_sz);
+	if (pDeF->skb == NULL)
+		return false;
+	ASSERT(pDeF->skb);
+	pDeF->skb->dev = pDevice->dev;
 
-    pRDInfo->skb = dev_alloc_skb((int)pDevice->rx_buf_sz);
-#ifdef	PLICE_DEBUG
-	//printk("device_alloc_rx_buf:skb is %x\n",pRDInfo->skb);
-#endif
-    if (pRDInfo->skb==NULL)
-        return false;
-    ASSERT(pRDInfo->skb);
-    pRDInfo->skb->dev = pDevice->dev;
-    pRDInfo->skb_dma = pci_map_single(pDevice->pcid, skb_tail_pointer(pRDInfo->skb),
-				      pDevice->rx_buf_sz, PCI_DMA_FROMDEVICE);
-    *((unsigned int *) &(pRD->m_rd0RD0)) = 0; /* FIX cast */
-
-    pRD->m_rd0RD0.wResCount = cpu_to_le16(pDevice->rx_buf_sz);
-    pRD->m_rd0RD0.f1Owner = OWNED_BY_NIC;
-    pRD->m_rd1RD1.wReqCount = cpu_to_le16(pDevice->rx_buf_sz);
-    pRD->buff_addr = cpu_to_le32(pRDInfo->skb_dma);
-
-    return true;
+	return true;
 }
 
+static int device_tx_srv(PSDevice pDevice, unsigned int uIdx) {
+	PSTxDesc                 pTD;
+	bool bFull = false;
+	int                      works = 0;
+	unsigned char byTsr0;
+	unsigned char byTsr1;
+	unsigned int	uFrameSize, uFIFOHeaderSize;
+	PSTxBufHead              pTxBufHead;
+	struct net_device_stats *pStats = &pDevice->stats;
+	struct sk_buff *skb;
+	unsigned int	uNodeIndex;
+	PSMgmtObject             pMgmt = pDevice->pMgmt;
+
+	for (pTD = pDevice->apTailTD[uIdx]; pDevice->iTDUsed[uIdx] > 0; pTD = pTD->next) {
+		if (pTD->m_td0TD0.f1Owner == OWNED_BY_NIC)
+			break;
+		if (works++ > 15)
+			break;
 
+		byTsr0 = pTD->m_td0TD0.byTSR0;
+		byTsr1 = pTD->m_td0TD0.byTSR1;
+
+		//Only the status of first TD in the chain is correct
+		if (pTD->m_td1TD1.byTCR & TCR_STP) {
+			if ((pTD->pTDInfo->byFlags & TD_FLAGS_NETIF_SKB) != 0) {
+				uFIFOHeaderSize = pTD->pTDInfo->dwHeaderLength;
+				uFrameSize = pTD->pTDInfo->dwReqCount - uFIFOHeaderSize;
+				pTxBufHead = (PSTxBufHead) (pTD->pTDInfo->buf);
+				// Update the statistics based on the Transmit status
+				// now, we DONT check TSR0_CDH
+
+				STAvUpdateTDStatCounter(&pDevice->scStatistic,
+							byTsr0, byTsr1,
+							(unsigned char *)(pTD->pTDInfo->buf + uFIFOHeaderSize),
+							uFrameSize, uIdx);
+
+				BSSvUpdateNodeTxCounter(pDevice,
+							byTsr0, byTsr1,
+							(unsigned char *)(pTD->pTDInfo->buf),
+							uFIFOHeaderSize
+					);
+
+				if (!(byTsr1 & TSR1_TERR)) {
+					if (byTsr0 != 0) {
+						DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " Tx[%d] OK but has error. tsr1[%02X] tsr0[%02X].\n",
+							(int)uIdx, byTsr1, byTsr0);
+					}
+					if ((pTxBufHead->wFragCtl & FRAGCTL_ENDFRAG) != FRAGCTL_NONFRAG) {
+						pDevice->s802_11Counter.TransmittedFragmentCount++;
+					}
+					pStats->tx_packets++;
+					pStats->tx_bytes += pTD->pTDInfo->skb->len;
+				} else {
+					DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " Tx[%d] dropped & tsr1[%02X] tsr0[%02X].\n",
+						(int)uIdx, byTsr1, byTsr0);
+					pStats->tx_errors++;
+					pStats->tx_dropped++;
+				}
+			}
 
-bool device_alloc_frag_buf(PSDevice pDevice, PSDeFragControlBlock pDeF) {
+			if ((pTD->pTDInfo->byFlags & TD_FLAGS_PRIV_SKB) != 0) {
+				if (pDevice->bEnableHostapd) {
+					DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "tx call back netif.. \n");
+					skb = pTD->pTDInfo->skb;
+					skb->dev = pDevice->apdev;
+					skb_reset_mac_header(skb);
+					skb->pkt_type = PACKET_OTHERHOST;
+					//skb->protocol = htons(ETH_P_802_2);
+					memset(skb->cb, 0, sizeof(skb->cb));
+					netif_rx(skb);
+				}
+			}
 
-    pDeF->skb = dev_alloc_skb((int)pDevice->rx_buf_sz);
-    if (pDeF->skb == NULL)
-        return false;
-    ASSERT(pDeF->skb);
-    pDeF->skb->dev = pDevice->dev;
+			if (byTsr1 & TSR1_TERR) {
+				if ((pTD->pTDInfo->byFlags & TD_FLAGS_PRIV_SKB) != 0) {
+					DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " Tx[%d] fail has error. tsr1[%02X] tsr0[%02X].\n",
+						(int)uIdx, byTsr1, byTsr0);
+				}
 
-    return true;
-}
+//                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " Tx[%d] fail has error. tsr1[%02X] tsr0[%02X].\n",
+//                          (int)uIdx, byTsr1, byTsr0);
+
+				if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) &&
+				    (pTD->pTDInfo->byFlags & TD_FLAGS_NETIF_SKB)) {
+					unsigned short wAID;
+					unsigned char byMask[8] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80};
+
+					skb = pTD->pTDInfo->skb;
+					if (BSSDBbIsSTAInNodeDB(pMgmt, (unsigned char *)(skb->data), &uNodeIndex)) {
+						if (pMgmt->sNodeDBTable[uNodeIndex].bPSEnable) {
+							skb_queue_tail(&pMgmt->sNodeDBTable[uNodeIndex].sTxPSQueue, skb);
+							pMgmt->sNodeDBTable[uNodeIndex].wEnQueueCnt++;
+							// set tx map
+							wAID = pMgmt->sNodeDBTable[uNodeIndex].wAID;
+							pMgmt->abyPSTxMap[wAID >> 3] |=  byMask[wAID & 7];
+							pTD->pTDInfo->byFlags &= ~(TD_FLAGS_NETIF_SKB);
+							DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "tx_srv:tx fail re-queue sta index= %d, QueCnt= %d\n"
+								, (int)uNodeIndex, pMgmt->sNodeDBTable[uNodeIndex].wEnQueueCnt);
+							pStats->tx_errors--;
+							pStats->tx_dropped--;
+						}
+					}
+				}
+			}
+			device_free_tx_buf(pDevice, pTD);
+			pDevice->iTDUsed[uIdx]--;
+		}
+	}
 
+	if (uIdx == TYPE_AC0DMA) {
+		// RESERV_AC0DMA reserved for relay
 
+		if (AVAIL_TD(pDevice, uIdx) < RESERV_AC0DMA) {
+			bFull = true;
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " AC0DMA is Full = %d\n", pDevice->iTDUsed[uIdx]);
+		}
+		if (netif_queue_stopped(pDevice->dev) && (bFull == false)) {
+			netif_wake_queue(pDevice->dev);
+		}
+	}
 
-static int device_tx_srv(PSDevice pDevice, unsigned int uIdx) {
-    PSTxDesc                 pTD;
-    bool bFull=false;
-    int                      works = 0;
-    unsigned char byTsr0;
-    unsigned char byTsr1;
-    unsigned int	uFrameSize, uFIFOHeaderSize;
-    PSTxBufHead              pTxBufHead;
-    struct net_device_stats* pStats = &pDevice->stats;
-    struct sk_buff*          skb;
-    unsigned int	uNodeIndex;
-    PSMgmtObject             pMgmt = pDevice->pMgmt;
-
-
-    for (pTD = pDevice->apTailTD[uIdx]; pDevice->iTDUsed[uIdx] >0; pTD = pTD->next) {
-
-        if (pTD->m_td0TD0.f1Owner == OWNED_BY_NIC)
-            break;
-        if (works++>15)
-            break;
-
-        byTsr0 = pTD->m_td0TD0.byTSR0;
-        byTsr1 = pTD->m_td0TD0.byTSR1;
-
-        //Only the status of first TD in the chain is correct
-        if (pTD->m_td1TD1.byTCR & TCR_STP) {
-
-            if ((pTD->pTDInfo->byFlags & TD_FLAGS_NETIF_SKB) != 0) {
-                uFIFOHeaderSize = pTD->pTDInfo->dwHeaderLength;
-                uFrameSize = pTD->pTDInfo->dwReqCount - uFIFOHeaderSize;
-                pTxBufHead = (PSTxBufHead) (pTD->pTDInfo->buf);
-                // Update the statistics based on the Transmit status
-                // now, we DONT check TSR0_CDH
-
-                STAvUpdateTDStatCounter(&pDevice->scStatistic,
-                        byTsr0, byTsr1,
-                        (unsigned char *)(pTD->pTDInfo->buf + uFIFOHeaderSize),
-                        uFrameSize, uIdx);
-
-
-                BSSvUpdateNodeTxCounter(pDevice,
-                         byTsr0, byTsr1,
-                         (unsigned char *)(pTD->pTDInfo->buf),
-                         uFIFOHeaderSize
-                         );
-
-                if ( !(byTsr1 & TSR1_TERR)) {
-                    if (byTsr0 != 0) {
-                        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" Tx[%d] OK but has error. tsr1[%02X] tsr0[%02X].\n",
-                           (int)uIdx, byTsr1, byTsr0);
-                    }
-                    if ((pTxBufHead->wFragCtl & FRAGCTL_ENDFRAG) != FRAGCTL_NONFRAG) {
-                        pDevice->s802_11Counter.TransmittedFragmentCount ++;
-                    }
-                    pStats->tx_packets++;
-                    pStats->tx_bytes += pTD->pTDInfo->skb->len;
-                }
-                else {
-                     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" Tx[%d] dropped & tsr1[%02X] tsr0[%02X].\n",
-                           (int)uIdx, byTsr1, byTsr0);
-                    pStats->tx_errors++;
-                    pStats->tx_dropped++;
-                }
-            }
-
-            if ((pTD->pTDInfo->byFlags & TD_FLAGS_PRIV_SKB) != 0) {
-                if (pDevice->bEnableHostapd) {
-                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "tx call back netif.. \n");
-                    skb = pTD->pTDInfo->skb;
-	                skb->dev = pDevice->apdev;
-			skb_reset_mac_header(skb);
-	                skb->pkt_type = PACKET_OTHERHOST;
-    	            //skb->protocol = htons(ETH_P_802_2);
-	                memset(skb->cb, 0, sizeof(skb->cb));
-	                netif_rx(skb);
-	            }
-            }
-
-            if (byTsr1 & TSR1_TERR) {
-            if ((pTD->pTDInfo->byFlags & TD_FLAGS_PRIV_SKB) != 0) {
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" Tx[%d] fail has error. tsr1[%02X] tsr0[%02X].\n",
-                          (int)uIdx, byTsr1, byTsr0);
-            }
-
-//                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" Tx[%d] fail has error. tsr1[%02X] tsr0[%02X].\n",
-//                          (int)uIdx, byTsr1, byTsr0);
+	pDevice->apTailTD[uIdx] = pTD;
 
-                if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) &&
-                    (pTD->pTDInfo->byFlags & TD_FLAGS_NETIF_SKB)) {
-                    unsigned short wAID;
-                    unsigned char byMask[8] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80};
-
-                    skb = pTD->pTDInfo->skb;
-                    if (BSSDBbIsSTAInNodeDB(pMgmt, (unsigned char *)(skb->data), &uNodeIndex)) {
-                        if (pMgmt->sNodeDBTable[uNodeIndex].bPSEnable) {
-                            skb_queue_tail(&pMgmt->sNodeDBTable[uNodeIndex].sTxPSQueue, skb);
-                            pMgmt->sNodeDBTable[uNodeIndex].wEnQueueCnt++;
-                            // set tx map
-                            wAID = pMgmt->sNodeDBTable[uNodeIndex].wAID;
-                            pMgmt->abyPSTxMap[wAID >> 3] |=  byMask[wAID & 7];
-                            pTD->pTDInfo->byFlags &= ~(TD_FLAGS_NETIF_SKB);
-                            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "tx_srv:tx fail re-queue sta index= %d, QueCnt= %d\n"
-                                    ,(int)uNodeIndex, pMgmt->sNodeDBTable[uNodeIndex].wEnQueueCnt);
-                            pStats->tx_errors--;
-                            pStats->tx_dropped--;
-                        }
-                    }
-                }
-            }
-            device_free_tx_buf(pDevice,pTD);
-            pDevice->iTDUsed[uIdx]--;
-        }
-    }
-
-
-    if (uIdx == TYPE_AC0DMA) {
-        // RESERV_AC0DMA reserved for relay
-
-        if (AVAIL_TD(pDevice, uIdx) < RESERV_AC0DMA) {
-            bFull = true;
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " AC0DMA is Full = %d\n", pDevice->iTDUsed[uIdx]);
-        }
-        if (netif_queue_stopped(pDevice->dev) && (bFull==false)){
-            netif_wake_queue(pDevice->dev);
-        }
-    }
-
-
-    pDevice->apTailTD[uIdx] = pTD;
-
-    return works;
+	return works;
 }
 
-
 static void device_error(PSDevice pDevice, unsigned short status) {
-
-    if (status & ISR_FETALERR) {
-        DBG_PRT(MSG_LEVEL_ERR, KERN_ERR
-            "%s: Hardware fatal error.\n",
-            pDevice->dev->name);
-        netif_stop_queue(pDevice->dev);
-        del_timer(&pDevice->sTimerCommand);
-        del_timer(&(pDevice->pMgmt->sTimerSecondCallback));
-        pDevice->bCmdRunning = false;
-        MACbShutdown(pDevice->PortOffset);
-        return;
-    }
-
+	if (status & ISR_FETALERR) {
+		DBG_PRT(MSG_LEVEL_ERR, KERN_ERR
+			"%s: Hardware fatal error.\n",
+			pDevice->dev->name);
+		netif_stop_queue(pDevice->dev);
+		del_timer(&pDevice->sTimerCommand);
+		del_timer(&(pDevice->pMgmt->sTimerSecondCallback));
+		pDevice->bCmdRunning = false;
+		MACbShutdown(pDevice->PortOffset);
+		return;
+	}
 }
 
 static void device_free_tx_buf(PSDevice pDevice, PSTxDesc pDesc) {
-    PDEVICE_TD_INFO  pTDInfo=pDesc->pTDInfo;
-    struct sk_buff* skb=pTDInfo->skb;
+	PDEVICE_TD_INFO  pTDInfo = pDesc->pTDInfo;
+	struct sk_buff *skb = pTDInfo->skb;
 
-    // pre-allocated buf_dma can't be unmapped.
-    if (pTDInfo->skb_dma && (pTDInfo->skb_dma != pTDInfo->buf_dma)) {
-        pci_unmap_single(pDevice->pcid,pTDInfo->skb_dma,skb->len,
-              PCI_DMA_TODEVICE);
-    }
+	// pre-allocated buf_dma can't be unmapped.
+	if (pTDInfo->skb_dma && (pTDInfo->skb_dma != pTDInfo->buf_dma)) {
+		pci_unmap_single(pDevice->pcid, pTDInfo->skb_dma, skb->len,
+				 PCI_DMA_TODEVICE);
+	}
 
-    if ((pTDInfo->byFlags & TD_FLAGS_NETIF_SKB) != 0)
-        dev_kfree_skb_irq(skb);
+	if ((pTDInfo->byFlags & TD_FLAGS_NETIF_SKB) != 0)
+		dev_kfree_skb_irq(skb);
 
-    pTDInfo->skb_dma = 0;
-    pTDInfo->skb = 0;
-    pTDInfo->byFlags = 0;
+	pTDInfo->skb_dma = 0;
+	pTDInfo->skb = 0;
+	pTDInfo->byFlags = 0;
 }
 
-
-
 //PLICE_DEBUG ->
 void	InitRxManagementQueue(PSDevice  pDevice)
 {
@@ -1816,107 +1686,88 @@ void	InitRxManagementQueue(PSDevice  pDevice)
 }
 //PLICE_DEBUG<-
 
-
-
-
-
 //PLICE_DEBUG ->
 int MlmeThread(
-     void * Context)
+	void *Context)
 {
 	PSDevice	pDevice =  (PSDevice) Context;
 	PSRxMgmtPacket			pRxMgmtPacket;
-	// int i ;
+	// int i;
 	//complete(&pDevice->notify);
-//printk("Enter MngWorkItem,Queue packet num is %d\n",pDevice->rxManeQueue.packet_num);
 
-	//printk("Enter MlmeThread,packet _num is %d\n",pDevice->rxManeQueue.packet_num);
 	//i = 0;
 #if 1
-	while (1)
-	{
-
-	//printk("DDDD\n");
-	//down(&pDevice->mlme_semaphore);
-        // pRxMgmtPacket =  DeQueue(pDevice);
+	while (1) {
+		//down(&pDevice->mlme_semaphore);
+		// pRxMgmtPacket =  DeQueue(pDevice);
 #if 1
 		spin_lock_irq(&pDevice->lock);
-		 while(pDevice->rxManeQueue.packet_num != 0)
-	 	{
-			 pRxMgmtPacket =  DeQueue(pDevice);
-        			//pDevice;
-        			//DequeueManageObject(pDevice->FirstRecvMngList, pDevice->LastRecvMngList);
+		while (pDevice->rxManeQueue.packet_num != 0) {
+			pRxMgmtPacket = DeQueue(pDevice);
+			//pDevice;
+			//DequeueManageObject(pDevice->FirstRecvMngList, pDevice->LastRecvMngList);
 			vMgrRxManagePacket(pDevice, pDevice->pMgmt, pRxMgmtPacket);
-			//printk("packet_num is %d\n",pDevice->rxManeQueue.packet_num);
-
-		 }
+		}
 		spin_unlock_irq(&pDevice->lock);
 		if (mlme_kill == 0)
-		break;
+			break;
 		//udelay(200);
 #endif
-	//printk("Before schedule thread jiffies is %x\n",jiffies);
-	schedule();
-	//printk("after schedule thread jiffies is %x\n",jiffies);
-	if (mlme_kill == 0)
-		break;
-	//printk("i is %d\n",i);
+		schedule();
+		if (mlme_kill == 0)
+			break;
 	}
 
 #endif
 	return 0;
-
 }
 
-
-
 static int  device_open(struct net_device *dev) {
-    PSDevice    pDevice=(PSDevice) netdev_priv(dev);
-    int i;
+	PSDevice pDevice = (PSDevice)netdev_priv(dev);
+	int i;
 #ifdef WPA_SM_Transtatus
-    extern SWPAResult wpa_Result;
+	extern SWPAResult wpa_Result;
 #endif
 
-    pDevice->rx_buf_sz = PKT_BUF_SZ;
-    if (!device_init_rings(pDevice)) {
-        return -ENOMEM;
-    }
+	pDevice->rx_buf_sz = PKT_BUF_SZ;
+	if (!device_init_rings(pDevice)) {
+		return -ENOMEM;
+	}
 //2008-5-13 <add> by chester
-    i=request_irq(pDevice->pcid->irq, &device_intr, IRQF_SHARED, dev->name, dev);
-    if (i)
-        return i;
-	//printk("DEBUG1\n");
+	i = request_irq(pDevice->pcid->irq, &device_intr, IRQF_SHARED, dev->name, dev);
+	if (i)
+		return i;
+
 #ifdef WPA_SM_Transtatus
-     memset(wpa_Result.ifname,0,sizeof(wpa_Result.ifname));
-     wpa_Result.proto = 0;
-     wpa_Result.key_mgmt = 0;
-     wpa_Result.eap_type = 0;
-     wpa_Result.authenticated = false;
-     pDevice->fWPA_Authened = false;
+	memset(wpa_Result.ifname, 0, sizeof(wpa_Result.ifname));
+	wpa_Result.proto = 0;
+	wpa_Result.key_mgmt = 0;
+	wpa_Result.eap_type = 0;
+	wpa_Result.authenticated = false;
+	pDevice->fWPA_Authened = false;
 #endif
-DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "call device init rd0 ring\n");
-device_init_rd0_ring(pDevice);
-    device_init_rd1_ring(pDevice);
-    device_init_defrag_cb(pDevice);
-    device_init_td0_ring(pDevice);
-    device_init_td1_ring(pDevice);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "call device init rd0 ring\n");
+	device_init_rd0_ring(pDevice);
+	device_init_rd1_ring(pDevice);
+	device_init_defrag_cb(pDevice);
+	device_init_td0_ring(pDevice);
+	device_init_td1_ring(pDevice);
 //    VNTWIFIvSet11h(pDevice->pMgmt, pDevice->b11hEnable);
 
-
-    if (pDevice->bDiversityRegCtlON) {
-        device_init_diversity_timer(pDevice);
-    }
-    vMgrObjectInit(pDevice);
-    vMgrTimerInit(pDevice);
+	if (pDevice->bDiversityRegCtlON) {
+		device_init_diversity_timer(pDevice);
+	}
+	vMgrObjectInit(pDevice);
+	vMgrTimerInit(pDevice);
 
 //PLICE_DEBUG->
 #ifdef	TASK_LET
-	tasklet_init (&pDevice->RxMngWorkItem,(void *)MngWorkItem,(unsigned long )pDevice);
+	tasklet_init(&pDevice->RxMngWorkItem, (void *)MngWorkItem, (unsigned long)pDevice);
 #endif
 #ifdef	THREAD
 	InitRxManagementQueue(pDevice);
 	mlme_kill = 0;
-	mlme_task = kthread_run(MlmeThread,(void *) pDevice, "MLME");
+	mlme_task = kthread_run(MlmeThread, (void *)pDevice, "MLME");
 	if (IS_ERR(mlme_task)) {
 		printk("thread create fail\n");
 		return -1;
@@ -1925,1184 +1776,1111 @@ device_init_rd0_ring(pDevice);
 	mlme_kill = 1;
 #endif
 
-
-
-	//printk("thread id is %d\n",pDevice->MLMEThr_pid);
-	//printk("Create thread time is %x\n",jiffies);
 	//wait_for_completion(&pDevice->notify);
 
-
-
-
-  // if (( SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_RADIOCTL)&0x06)==0x04)
-    //    return -ENOMEM;
-DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "call device_init_registers\n");
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "call device_init_registers\n");
 	device_init_registers(pDevice, DEVICE_INIT_COLD);
-    MACvReadEtherAddress(pDevice->PortOffset, pDevice->abyCurrentNetAddr);
-    memcpy(pDevice->pMgmt->abyMACAddr, pDevice->abyCurrentNetAddr, ETH_ALEN);
-    device_set_multi(pDevice->dev);
+	MACvReadEtherAddress(pDevice->PortOffset, pDevice->abyCurrentNetAddr);
+	memcpy(pDevice->pMgmt->abyMACAddr, pDevice->abyCurrentNetAddr, ETH_ALEN);
+	device_set_multi(pDevice->dev);
 
-    // Init for Key Management
-    KeyvInitTable(&pDevice->sKey, pDevice->PortOffset);
-    add_timer(&(pDevice->pMgmt->sTimerSecondCallback));
+	// Init for Key Management
+	KeyvInitTable(&pDevice->sKey, pDevice->PortOffset);
+	add_timer(&(pDevice->pMgmt->sTimerSecondCallback));
 
-	#ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
+#ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
 	/*
-     pDevice->bwextstep0 = false;
-     pDevice->bwextstep1 = false;
-     pDevice->bwextstep2 = false;
-     pDevice->bwextstep3 = false;
-     */
-       pDevice->bwextcount=0;
-     pDevice->bWPASuppWextEnabled = false;
+	  pDevice->bwextstep0 = false;
+	  pDevice->bwextstep1 = false;
+	  pDevice->bwextstep2 = false;
+	  pDevice->bwextstep3 = false;
+	*/
+	pDevice->bwextcount = 0;
+	pDevice->bWPASuppWextEnabled = false;
 #endif
-    pDevice->byReAssocCount = 0;
-   pDevice->bWPADEVUp = false;
-    // Patch: if WEP key already set by iwconfig but device not yet open
-    if ((pDevice->bEncryptionEnable == true) && (pDevice->bTransmitKey == true)) {
-        KeybSetDefaultKey(&(pDevice->sKey),
-                            (unsigned long)(pDevice->byKeyIndex | (1 << 31)),
-                            pDevice->uKeyLength,
-                            NULL,
-                            pDevice->abyKey,
-                            KEY_CTL_WEP,
-                            pDevice->PortOffset,
-                            pDevice->byLocalID
-                          );
-         pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled;
-    }
-
-//printk("DEBUG2\n");
-
-
-DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "call MACvIntEnable\n");
+	pDevice->byReAssocCount = 0;
+	pDevice->bWPADEVUp = false;
+	// Patch: if WEP key already set by iwconfig but device not yet open
+	if ((pDevice->bEncryptionEnable == true) && (pDevice->bTransmitKey == true)) {
+		KeybSetDefaultKey(&(pDevice->sKey),
+				  (unsigned long)(pDevice->byKeyIndex | (1 << 31)),
+				  pDevice->uKeyLength,
+				  NULL,
+				  pDevice->abyKey,
+				  KEY_CTL_WEP,
+				  pDevice->PortOffset,
+				  pDevice->byLocalID
+			);
+		pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled;
+	}
+
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "call MACvIntEnable\n");
 	MACvIntEnable(pDevice->PortOffset, IMR_MASK_VALUE);
 
-    if (pDevice->pMgmt->eConfigMode == WMAC_CONFIG_AP) {
-        bScheduleCommand((void *)pDevice, WLAN_CMD_RUN_AP, NULL);
+	if (pDevice->pMgmt->eConfigMode == WMAC_CONFIG_AP) {
+		bScheduleCommand((void *)pDevice, WLAN_CMD_RUN_AP, NULL);
+	} else {
+		bScheduleCommand((void *)pDevice, WLAN_CMD_BSSID_SCAN, NULL);
+		bScheduleCommand((void *)pDevice, WLAN_CMD_SSID, NULL);
 	}
-	else {
-        bScheduleCommand((void *)pDevice, WLAN_CMD_BSSID_SCAN, NULL);
-        bScheduleCommand((void *)pDevice, WLAN_CMD_SSID, NULL);
-    }
-    pDevice->flags |=DEVICE_FLAGS_OPENED;
+	pDevice->flags |= DEVICE_FLAGS_OPENED;
 
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "device_open success.. \n");
-    return 0;
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "device_open success.. \n");
+	return 0;
 }
 
-
 static int  device_close(struct net_device *dev) {
-    PSDevice  pDevice=(PSDevice) netdev_priv(dev);
-    PSMgmtObject     pMgmt = pDevice->pMgmt;
- //PLICE_DEBUG->
+	PSDevice  pDevice = (PSDevice)netdev_priv(dev);
+	PSMgmtObject     pMgmt = pDevice->pMgmt;
+	//PLICE_DEBUG->
 #ifdef	THREAD
 	mlme_kill = 0;
 #endif
 //PLICE_DEBUG<-
 //2007-1121-02<Add>by EinsnLiu
-    if (pDevice->bLinkPass) {
-	bScheduleCommand((void *)pDevice, WLAN_CMD_DISASSOCIATE, NULL);
-        mdelay(30);
-    }
+	if (pDevice->bLinkPass) {
+		bScheduleCommand((void *)pDevice, WLAN_CMD_DISASSOCIATE, NULL);
+		mdelay(30);
+	}
 #ifdef TxInSleep
-    del_timer(&pDevice->sTimerTxData);
+	del_timer(&pDevice->sTimerTxData);
 #endif
-    del_timer(&pDevice->sTimerCommand);
-    del_timer(&pMgmt->sTimerSecondCallback);
-    if (pDevice->bDiversityRegCtlON) {
-        del_timer(&pDevice->TimerSQ3Tmax1);
-        del_timer(&pDevice->TimerSQ3Tmax2);
-        del_timer(&pDevice->TimerSQ3Tmax3);
-    }
+	del_timer(&pDevice->sTimerCommand);
+	del_timer(&pMgmt->sTimerSecondCallback);
+	if (pDevice->bDiversityRegCtlON) {
+		del_timer(&pDevice->TimerSQ3Tmax1);
+		del_timer(&pDevice->TimerSQ3Tmax2);
+		del_timer(&pDevice->TimerSQ3Tmax3);
+	}
 
 #ifdef	TASK_LET
 	tasklet_kill(&pDevice->RxMngWorkItem);
 #endif
-     netif_stop_queue(dev);
-    pDevice->bCmdRunning = false;
-    MACbShutdown(pDevice->PortOffset);
-    MACbSoftwareReset(pDevice->PortOffset);
-    CARDbRadioPowerOff(pDevice);
-
-    pDevice->bLinkPass = false;
-    memset(pMgmt->abyCurrBSSID, 0, 6);
-    pMgmt->eCurrState = WMAC_STATE_IDLE;
-    device_free_td0_ring(pDevice);
-    device_free_td1_ring(pDevice);
-    device_free_rd0_ring(pDevice);
-    device_free_rd1_ring(pDevice);
-    device_free_frag_buf(pDevice);
-    device_free_rings(pDevice);
-    BSSvClearNodeDBTable(pDevice, 0);
-    free_irq(dev->irq, dev);
-    pDevice->flags &=(~DEVICE_FLAGS_OPENED);
+	netif_stop_queue(dev);
+	pDevice->bCmdRunning = false;
+	MACbShutdown(pDevice->PortOffset);
+	MACbSoftwareReset(pDevice->PortOffset);
+	CARDbRadioPowerOff(pDevice);
+
+	pDevice->bLinkPass = false;
+	memset(pMgmt->abyCurrBSSID, 0, 6);
+	pMgmt->eCurrState = WMAC_STATE_IDLE;
+	device_free_td0_ring(pDevice);
+	device_free_td1_ring(pDevice);
+	device_free_rd0_ring(pDevice);
+	device_free_rd1_ring(pDevice);
+	device_free_frag_buf(pDevice);
+	device_free_rings(pDevice);
+	BSSvClearNodeDBTable(pDevice, 0);
+	free_irq(dev->irq, dev);
+	pDevice->flags &= (~DEVICE_FLAGS_OPENED);
 	//2008-0714-01<Add>by chester
-device_release_WPADEV(pDevice);
+	device_release_WPADEV(pDevice);
 //PLICE_DEBUG->
 	//tasklet_kill(&pDevice->RxMngWorkItem);
 //PLICE_DEBUG<-
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "device_close.. \n");
-    return 0;
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "device_close.. \n");
+	return 0;
 }
 
+static int device_dma0_tx_80211(struct sk_buff *skb, struct net_device *dev) {
+	PSDevice pDevice = netdev_priv(dev);
+	unsigned char *pbMPDU;
+	unsigned int cbMPDULen = 0;
 
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "device_dma0_tx_80211\n");
+	spin_lock_irq(&pDevice->lock);
 
-static int device_dma0_tx_80211(struct sk_buff *skb, struct net_device *dev) {
-    PSDevice        pDevice=netdev_priv(dev);
-    unsigned char *pbMPDU;
-    unsigned int cbMPDULen = 0;
+	if (AVAIL_TD(pDevice, TYPE_TXDMA0) <= 0) {
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "device_dma0_tx_80211, td0 <=0\n");
+		dev_kfree_skb_irq(skb);
+		spin_unlock_irq(&pDevice->lock);
+		return 0;
+	}
+
+	if (pDevice->bStopTx0Pkt == true) {
+		dev_kfree_skb_irq(skb);
+		spin_unlock_irq(&pDevice->lock);
+		return 0;
+	}
+
+	cbMPDULen = skb->len;
+	pbMPDU = skb->data;
+
+	vDMA0_tx_80211(pDevice, skb, pbMPDU, cbMPDULen);
+
+	spin_unlock_irq(&pDevice->lock);
+
+	return 0;
+}
 
+bool device_dma0_xmit(PSDevice pDevice, struct sk_buff *skb, unsigned int uNodeIndex) {
+	PSMgmtObject    pMgmt = pDevice->pMgmt;
+	PSTxDesc        pHeadTD, pLastTD;
+	unsigned int cbFrameBodySize;
+	unsigned int uMACfragNum;
+	unsigned char byPktType;
+	bool bNeedEncryption = false;
+	PSKeyItem       pTransmitKey = NULL;
+	unsigned int cbHeaderSize;
+	unsigned int ii;
+	SKeyItem        STempKey;
+//    unsigned char byKeyIndex = 0;
 
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "device_dma0_tx_80211\n");
-    spin_lock_irq(&pDevice->lock);
+	if (pDevice->bStopTx0Pkt == true) {
+		dev_kfree_skb_irq(skb);
+		return false;
+	}
 
-    if (AVAIL_TD(pDevice, TYPE_TXDMA0) <= 0) {
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "device_dma0_tx_80211, td0 <=0\n");
-        dev_kfree_skb_irq(skb);
-        spin_unlock_irq(&pDevice->lock);
-        return 0;
-    }
+	if (AVAIL_TD(pDevice, TYPE_TXDMA0) <= 0) {
+		dev_kfree_skb_irq(skb);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "device_dma0_xmit, td0 <=0\n");
+		return false;
+	}
 
-    if (pDevice->bStopTx0Pkt == true) {
-        dev_kfree_skb_irq(skb);
-        spin_unlock_irq(&pDevice->lock);
-        return 0;
-    }
+	if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) {
+		if (pDevice->uAssocCount == 0) {
+			dev_kfree_skb_irq(skb);
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "device_dma0_xmit, assocCount = 0\n");
+			return false;
+		}
+	}
 
-    cbMPDULen = skb->len;
-    pbMPDU = skb->data;
+	pHeadTD = pDevice->apCurrTD[TYPE_TXDMA0];
 
-    vDMA0_tx_80211(pDevice, skb, pbMPDU, cbMPDULen);
+	pHeadTD->m_td1TD1.byTCR = (TCR_EDP|TCR_STP);
 
-    spin_unlock_irq(&pDevice->lock);
+	memcpy(pDevice->sTxEthHeader.abyDstAddr, (unsigned char *)(skb->data), ETH_HLEN);
+	cbFrameBodySize = skb->len - ETH_HLEN;
 
-    return 0;
+	// 802.1H
+	if (ntohs(pDevice->sTxEthHeader.wType) > ETH_DATA_LEN) {
+		cbFrameBodySize += 8;
+	}
+	uMACfragNum = cbGetFragCount(pDevice, pTransmitKey, cbFrameBodySize, &pDevice->sTxEthHeader);
 
-}
+	if (uMACfragNum > AVAIL_TD(pDevice, TYPE_TXDMA0)) {
+		dev_kfree_skb_irq(skb);
+		return false;
+	}
+	byPktType = (unsigned char)pDevice->byPacketType;
+
+	if (pDevice->bFixRate) {
+		if (pDevice->eCurrentPHYType == PHY_TYPE_11B) {
+			if (pDevice->uConnectionRate >= RATE_11M) {
+				pDevice->wCurrentRate = RATE_11M;
+			} else {
+				pDevice->wCurrentRate = (unsigned short)pDevice->uConnectionRate;
+			}
+		} else {
+			if (pDevice->uConnectionRate >= RATE_54M)
+				pDevice->wCurrentRate = RATE_54M;
+			else
+				pDevice->wCurrentRate = (unsigned short)pDevice->uConnectionRate;
+		}
+	} else {
+		pDevice->wCurrentRate = pDevice->pMgmt->sNodeDBTable[uNodeIndex].wTxDataRate;
+	}
 
+	//preamble type
+	if (pMgmt->sNodeDBTable[uNodeIndex].bShortPreamble) {
+		pDevice->byPreambleType = pDevice->byShortPreamble;
+	} else {
+		pDevice->byPreambleType = PREAMBLE_LONG;
+	}
 
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dma0: pDevice->wCurrentRate = %d \n", pDevice->wCurrentRate);
 
-bool device_dma0_xmit(PSDevice pDevice, struct sk_buff *skb, unsigned int uNodeIndex) {
-    PSMgmtObject    pMgmt = pDevice->pMgmt;
-    PSTxDesc        pHeadTD, pLastTD;
-    unsigned int cbFrameBodySize;
-    unsigned int uMACfragNum;
-    unsigned char byPktType;
-    bool bNeedEncryption = false;
-    PSKeyItem       pTransmitKey = NULL;
-    unsigned int cbHeaderSize;
-    unsigned int ii;
-    SKeyItem        STempKey;
-//    unsigned char byKeyIndex = 0;
+	if (pDevice->wCurrentRate <= RATE_11M) {
+		byPktType = PK_TYPE_11B;
+	} else if (pDevice->eCurrentPHYType == PHY_TYPE_11A) {
+		byPktType = PK_TYPE_11A;
+	} else {
+		if (pDevice->bProtectMode == true) {
+			byPktType = PK_TYPE_11GB;
+		} else {
+			byPktType = PK_TYPE_11GA;
+		}
+	}
+
+	if (pDevice->bEncryptionEnable == true)
+		bNeedEncryption = true;
+
+	if (pDevice->bEnableHostWEP) {
+		pTransmitKey = &STempKey;
+		pTransmitKey->byCipherSuite = pMgmt->sNodeDBTable[uNodeIndex].byCipherSuite;
+		pTransmitKey->dwKeyIndex = pMgmt->sNodeDBTable[uNodeIndex].dwKeyIndex;
+		pTransmitKey->uKeyLength = pMgmt->sNodeDBTable[uNodeIndex].uWepKeyLength;
+		pTransmitKey->dwTSC47_16 = pMgmt->sNodeDBTable[uNodeIndex].dwTSC47_16;
+		pTransmitKey->wTSC15_0 = pMgmt->sNodeDBTable[uNodeIndex].wTSC15_0;
+		memcpy(pTransmitKey->abyKey,
+		       &pMgmt->sNodeDBTable[uNodeIndex].abyWepKey[0],
+		       pTransmitKey->uKeyLength
+			);
+	}
+	vGenerateFIFOHeader(pDevice, byPktType, pDevice->pbyTmpBuff, bNeedEncryption,
+			    cbFrameBodySize, TYPE_TXDMA0, pHeadTD,
+			    &pDevice->sTxEthHeader, (unsigned char *)skb->data, pTransmitKey, uNodeIndex,
+			    &uMACfragNum,
+			    &cbHeaderSize
+		);
+
+	if (MACbIsRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_PS)) {
+		// Disable PS
+		MACbPSWakeup(pDevice->PortOffset);
+	}
+
+	pDevice->bPWBitOn = false;
+
+	pLastTD = pHeadTD;
+	for (ii = 0; ii < uMACfragNum; ii++) {
+		// Poll Transmit the adapter
+		wmb();
+		pHeadTD->m_td0TD0.f1Owner = OWNED_BY_NIC;
+		wmb();
+		if (ii == (uMACfragNum - 1))
+			pLastTD = pHeadTD;
+		pHeadTD = pHeadTD->next;
+	}
 
+	// Save the information needed by the tx interrupt handler
+	// to complete the Send request
+	pLastTD->pTDInfo->skb = skb;
+	pLastTD->pTDInfo->byFlags = 0;
+	pLastTD->pTDInfo->byFlags |= TD_FLAGS_NETIF_SKB;
 
-    if (pDevice->bStopTx0Pkt == true) {
-        dev_kfree_skb_irq(skb);
-        return false;
-    }
-
-    if (AVAIL_TD(pDevice, TYPE_TXDMA0) <= 0) {
-        dev_kfree_skb_irq(skb);
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "device_dma0_xmit, td0 <=0\n");
-        return false;
-    }
-
-    if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) {
-        if (pDevice->uAssocCount == 0) {
-            dev_kfree_skb_irq(skb);
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "device_dma0_xmit, assocCount = 0\n");
-            return false;
-        }
-    }
-
-    pHeadTD = pDevice->apCurrTD[TYPE_TXDMA0];
-
-    pHeadTD->m_td1TD1.byTCR = (TCR_EDP|TCR_STP);
-
-    memcpy(pDevice->sTxEthHeader.abyDstAddr, (unsigned char *)(skb->data), ETH_HLEN);
-    cbFrameBodySize = skb->len - ETH_HLEN;
-
-    // 802.1H
-    if (ntohs(pDevice->sTxEthHeader.wType) > ETH_DATA_LEN) {
-        cbFrameBodySize += 8;
-    }
-    uMACfragNum = cbGetFragCount(pDevice, pTransmitKey, cbFrameBodySize, &pDevice->sTxEthHeader);
-
-    if ( uMACfragNum > AVAIL_TD(pDevice, TYPE_TXDMA0)) {
-        dev_kfree_skb_irq(skb);
-        return false;
-    }
-    byPktType = (unsigned char)pDevice->byPacketType;
-
-
-    if (pDevice->bFixRate) {
-        if (pDevice->eCurrentPHYType == PHY_TYPE_11B) {
-            if (pDevice->uConnectionRate >= RATE_11M) {
-                pDevice->wCurrentRate = RATE_11M;
-            } else {
-                pDevice->wCurrentRate = (unsigned short)pDevice->uConnectionRate;
-            }
-        } else {
-            if (pDevice->uConnectionRate >= RATE_54M)
-                pDevice->wCurrentRate = RATE_54M;
-            else
-                pDevice->wCurrentRate = (unsigned short)pDevice->uConnectionRate;
-        }
-    }
-    else {
-        pDevice->wCurrentRate = pDevice->pMgmt->sNodeDBTable[uNodeIndex].wTxDataRate;
-    }
-
-    //preamble type
-    if (pMgmt->sNodeDBTable[uNodeIndex].bShortPreamble) {
-        pDevice->byPreambleType = pDevice->byShortPreamble;
-    }
-    else {
-        pDevice->byPreambleType = PREAMBLE_LONG;
-    }
-
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dma0: pDevice->wCurrentRate = %d \n", pDevice->wCurrentRate);
-
-
-    if (pDevice->wCurrentRate <= RATE_11M) {
-        byPktType = PK_TYPE_11B;
-    } else if (pDevice->eCurrentPHYType == PHY_TYPE_11A) {
-        byPktType = PK_TYPE_11A;
-    } else {
-        if (pDevice->bProtectMode == true) {
-            byPktType = PK_TYPE_11GB;
-        } else {
-            byPktType = PK_TYPE_11GA;
-        }
-    }
-
-    if (pDevice->bEncryptionEnable == true)
-        bNeedEncryption = true;
-
-    if (pDevice->bEnableHostWEP) {
-        pTransmitKey = &STempKey;
-        pTransmitKey->byCipherSuite = pMgmt->sNodeDBTable[uNodeIndex].byCipherSuite;
-        pTransmitKey->dwKeyIndex = pMgmt->sNodeDBTable[uNodeIndex].dwKeyIndex;
-        pTransmitKey->uKeyLength = pMgmt->sNodeDBTable[uNodeIndex].uWepKeyLength;
-        pTransmitKey->dwTSC47_16 = pMgmt->sNodeDBTable[uNodeIndex].dwTSC47_16;
-        pTransmitKey->wTSC15_0 = pMgmt->sNodeDBTable[uNodeIndex].wTSC15_0;
-        memcpy(pTransmitKey->abyKey,
-            &pMgmt->sNodeDBTable[uNodeIndex].abyWepKey[0],
-            pTransmitKey->uKeyLength
-            );
-    }
-    vGenerateFIFOHeader(pDevice, byPktType, pDevice->pbyTmpBuff, bNeedEncryption,
-                        cbFrameBodySize, TYPE_TXDMA0, pHeadTD,
-                        &pDevice->sTxEthHeader, (unsigned char *)skb->data, pTransmitKey, uNodeIndex,
-                        &uMACfragNum,
-                        &cbHeaderSize
-                        );
-
-    if (MACbIsRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_PS)) {
-        // Disable PS
-        MACbPSWakeup(pDevice->PortOffset);
-    }
-
-    pDevice->bPWBitOn = false;
-
-    pLastTD = pHeadTD;
-    for (ii = 0; ii < uMACfragNum; ii++) {
-        // Poll Transmit the adapter
-        wmb();
-        pHeadTD->m_td0TD0.f1Owner=OWNED_BY_NIC;
-        wmb();
-        if (ii == (uMACfragNum - 1))
-            pLastTD = pHeadTD;
-        pHeadTD = pHeadTD->next;
-    }
-
-    // Save the information needed by the tx interrupt handler
-    // to complete the Send request
-    pLastTD->pTDInfo->skb = skb;
-    pLastTD->pTDInfo->byFlags = 0;
-    pLastTD->pTDInfo->byFlags |= TD_FLAGS_NETIF_SKB;
-
-    pDevice->apCurrTD[TYPE_TXDMA0] = pHeadTD;
-
-    MACvTransmit0(pDevice->PortOffset);
-
-
-    return true;
+	pDevice->apCurrTD[TYPE_TXDMA0] = pHeadTD;
+
+	MACvTransmit0(pDevice->PortOffset);
+
+	return true;
 }
 
 //TYPE_AC0DMA data tx
 static int  device_xmit(struct sk_buff *skb, struct net_device *dev) {
-    PSDevice pDevice=netdev_priv(dev);
-
-    PSMgmtObject    pMgmt = pDevice->pMgmt;
-    PSTxDesc        pHeadTD, pLastTD;
-    unsigned int uNodeIndex = 0;
-    unsigned char byMask[8] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80};
-    unsigned short wAID;
-    unsigned int uMACfragNum = 1;
-    unsigned int cbFrameBodySize;
-    unsigned char byPktType;
-    unsigned int cbHeaderSize;
-    bool bNeedEncryption = false;
-    PSKeyItem       pTransmitKey = NULL;
-    SKeyItem        STempKey;
-    unsigned int ii;
-    bool bTKIP_UseGTK = false;
-    bool bNeedDeAuth = false;
-    unsigned char *pbyBSSID;
-    bool bNodeExist = false;
-
-
-
-    spin_lock_irq(&pDevice->lock);
-    if (pDevice->bLinkPass == false) {
-        dev_kfree_skb_irq(skb);
-        spin_unlock_irq(&pDevice->lock);
-        return 0;
-    }
-
-    if (pDevice->bStopDataPkt) {
-        dev_kfree_skb_irq(skb);
-        spin_unlock_irq(&pDevice->lock);
-        return 0;
-    }
-
-
-    if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) {
-        if (pDevice->uAssocCount == 0) {
-            dev_kfree_skb_irq(skb);
-            spin_unlock_irq(&pDevice->lock);
-            return 0;
-        }
-        if (is_multicast_ether_addr((unsigned char *)(skb->data))) {
-            uNodeIndex = 0;
-            bNodeExist = true;
-            if (pMgmt->sNodeDBTable[0].bPSEnable) {
-                skb_queue_tail(&(pMgmt->sNodeDBTable[0].sTxPSQueue), skb);
-                pMgmt->sNodeDBTable[0].wEnQueueCnt++;
-                // set tx map
-                pMgmt->abyPSTxMap[0] |= byMask[0];
-                spin_unlock_irq(&pDevice->lock);
-                return 0;
-            }
-}else {
-            if (BSSDBbIsSTAInNodeDB(pMgmt, (unsigned char *)(skb->data), &uNodeIndex)) {
-                if (pMgmt->sNodeDBTable[uNodeIndex].bPSEnable) {
-                    skb_queue_tail(&pMgmt->sNodeDBTable[uNodeIndex].sTxPSQueue, skb);
-                    pMgmt->sNodeDBTable[uNodeIndex].wEnQueueCnt++;
-                    // set tx map
-                    wAID = pMgmt->sNodeDBTable[uNodeIndex].wAID;
-                    pMgmt->abyPSTxMap[wAID >> 3] |=  byMask[wAID & 7];
-                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Set:pMgmt->abyPSTxMap[%d]= %d\n",
-                             (wAID >> 3), pMgmt->abyPSTxMap[wAID >> 3]);
-                    spin_unlock_irq(&pDevice->lock);
-                    return 0;
-                }
-
-                if (pMgmt->sNodeDBTable[uNodeIndex].bShortPreamble) {
-                    pDevice->byPreambleType = pDevice->byShortPreamble;
-
-                }else {
-                    pDevice->byPreambleType = PREAMBLE_LONG;
-                }
-                bNodeExist = true;
-
-            }
-        }
-
-        if (bNodeExist == false) {
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"Unknown STA not found in node DB \n");
-            dev_kfree_skb_irq(skb);
-            spin_unlock_irq(&pDevice->lock);
-            return 0;
-        }
-    }
-
-    pHeadTD = pDevice->apCurrTD[TYPE_AC0DMA];
-
-    pHeadTD->m_td1TD1.byTCR = (TCR_EDP|TCR_STP);
-
-
-    memcpy(pDevice->sTxEthHeader.abyDstAddr, (unsigned char *)(skb->data), ETH_HLEN);
-    cbFrameBodySize = skb->len - ETH_HLEN;
-    // 802.1H
-    if (ntohs(pDevice->sTxEthHeader.wType) > ETH_DATA_LEN) {
-        cbFrameBodySize += 8;
-    }
-
-
-    if (pDevice->bEncryptionEnable == true) {
-        bNeedEncryption = true;
-        // get Transmit key
-        do {
-            if ((pDevice->pMgmt->eCurrMode == WMAC_MODE_ESS_STA) &&
-                (pDevice->pMgmt->eCurrState == WMAC_STATE_ASSOC)) {
-                pbyBSSID = pDevice->abyBSSID;
-                // get pairwise key
-                if (KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, PAIRWISE_KEY, &pTransmitKey) == false) {
-                    // get group key
-                    if(KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, GROUP_KEY, &pTransmitKey) == true) {
-                        bTKIP_UseGTK = true;
-                        DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"Get GTK.\n");
-                        break;
-                    }
-                } else {
-                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"Get PTK.\n");
-                    break;
-                }
-            }else if (pDevice->pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) {
-
-                pbyBSSID = pDevice->sTxEthHeader.abyDstAddr;  //TO_DS = 0 and FROM_DS = 0 --> 802.11 MAC Address1
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"IBSS Serach Key: \n");
-                for (ii = 0; ii< 6; ii++)
-                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"%x \n", *(pbyBSSID+ii));
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"\n");
-
-                // get pairwise key
-                if(KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, PAIRWISE_KEY, &pTransmitKey) == true)
-                    break;
-            }
-            // get group key
-            pbyBSSID = pDevice->abyBroadcastAddr;
-            if(KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, GROUP_KEY, &pTransmitKey) == false) {
-                pTransmitKey = NULL;
-                if (pDevice->pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) {
-                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"IBSS and KEY is NULL. [%d]\n", pDevice->pMgmt->eCurrMode);
-                }
-                else
-                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"NOT IBSS and KEY is NULL. [%d]\n", pDevice->pMgmt->eCurrMode);
-            } else {
-                bTKIP_UseGTK = true;
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"Get GTK.\n");
-            }
-        } while(false);
-    }
-
-    if (pDevice->bEnableHostWEP) {
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"acdma0: STA index %d\n", uNodeIndex);
-        if (pDevice->bEncryptionEnable == true) {
-            pTransmitKey = &STempKey;
-            pTransmitKey->byCipherSuite = pMgmt->sNodeDBTable[uNodeIndex].byCipherSuite;
-            pTransmitKey->dwKeyIndex = pMgmt->sNodeDBTable[uNodeIndex].dwKeyIndex;
-            pTransmitKey->uKeyLength = pMgmt->sNodeDBTable[uNodeIndex].uWepKeyLength;
-            pTransmitKey->dwTSC47_16 = pMgmt->sNodeDBTable[uNodeIndex].dwTSC47_16;
-            pTransmitKey->wTSC15_0 = pMgmt->sNodeDBTable[uNodeIndex].wTSC15_0;
-            memcpy(pTransmitKey->abyKey,
-                &pMgmt->sNodeDBTable[uNodeIndex].abyWepKey[0],
-                pTransmitKey->uKeyLength
-                );
-         }
-    }
-
-    uMACfragNum = cbGetFragCount(pDevice, pTransmitKey, cbFrameBodySize, &pDevice->sTxEthHeader);
-
-    if (uMACfragNum > AVAIL_TD(pDevice, TYPE_AC0DMA)) {
-        DBG_PRT(MSG_LEVEL_ERR, KERN_DEBUG "uMACfragNum > AVAIL_TD(TYPE_AC0DMA) = %d\n", uMACfragNum);
-        dev_kfree_skb_irq(skb);
-        spin_unlock_irq(&pDevice->lock);
-        return 0;
-    }
-
-    if (pTransmitKey != NULL) {
-        if ((pTransmitKey->byCipherSuite == KEY_CTL_WEP) &&
-            (pTransmitKey->uKeyLength == WLAN_WEP232_KEYLEN)) {
-            uMACfragNum = 1; //WEP256 doesn't support fragment
-        }
-    }
-
-    byPktType = (unsigned char)pDevice->byPacketType;
-
-    if (pDevice->bFixRate) {
+	PSDevice pDevice = netdev_priv(dev);
+
+	PSMgmtObject    pMgmt = pDevice->pMgmt;
+	PSTxDesc        pHeadTD, pLastTD;
+	unsigned int uNodeIndex = 0;
+	unsigned char byMask[8] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80};
+	unsigned short wAID;
+	unsigned int uMACfragNum = 1;
+	unsigned int cbFrameBodySize;
+	unsigned char byPktType;
+	unsigned int cbHeaderSize;
+	bool bNeedEncryption = false;
+	PSKeyItem       pTransmitKey = NULL;
+	SKeyItem        STempKey;
+	unsigned int ii;
+	bool bTKIP_UseGTK = false;
+	bool bNeedDeAuth = false;
+	unsigned char *pbyBSSID;
+	bool bNodeExist = false;
+
+	spin_lock_irq(&pDevice->lock);
+	if (pDevice->bLinkPass == false) {
+		dev_kfree_skb_irq(skb);
+		spin_unlock_irq(&pDevice->lock);
+		return 0;
+	}
+
+	if (pDevice->bStopDataPkt) {
+		dev_kfree_skb_irq(skb);
+		spin_unlock_irq(&pDevice->lock);
+		return 0;
+	}
+
+	if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) {
+		if (pDevice->uAssocCount == 0) {
+			dev_kfree_skb_irq(skb);
+			spin_unlock_irq(&pDevice->lock);
+			return 0;
+		}
+		if (is_multicast_ether_addr((unsigned char *)(skb->data))) {
+			uNodeIndex = 0;
+			bNodeExist = true;
+			if (pMgmt->sNodeDBTable[0].bPSEnable) {
+				skb_queue_tail(&(pMgmt->sNodeDBTable[0].sTxPSQueue), skb);
+				pMgmt->sNodeDBTable[0].wEnQueueCnt++;
+				// set tx map
+				pMgmt->abyPSTxMap[0] |= byMask[0];
+				spin_unlock_irq(&pDevice->lock);
+				return 0;
+			}
+		} else {
+			if (BSSDBbIsSTAInNodeDB(pMgmt, (unsigned char *)(skb->data), &uNodeIndex)) {
+				if (pMgmt->sNodeDBTable[uNodeIndex].bPSEnable) {
+					skb_queue_tail(&pMgmt->sNodeDBTable[uNodeIndex].sTxPSQueue, skb);
+					pMgmt->sNodeDBTable[uNodeIndex].wEnQueueCnt++;
+					// set tx map
+					wAID = pMgmt->sNodeDBTable[uNodeIndex].wAID;
+					pMgmt->abyPSTxMap[wAID >> 3] |=  byMask[wAID & 7];
+					DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Set:pMgmt->abyPSTxMap[%d]= %d\n",
+						(wAID >> 3), pMgmt->abyPSTxMap[wAID >> 3]);
+					spin_unlock_irq(&pDevice->lock);
+					return 0;
+				}
+
+				if (pMgmt->sNodeDBTable[uNodeIndex].bShortPreamble) {
+					pDevice->byPreambleType = pDevice->byShortPreamble;
+
+				} else {
+					pDevice->byPreambleType = PREAMBLE_LONG;
+				}
+				bNodeExist = true;
+
+			}
+		}
+
+		if (bNodeExist == false) {
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG "Unknown STA not found in node DB \n");
+			dev_kfree_skb_irq(skb);
+			spin_unlock_irq(&pDevice->lock);
+			return 0;
+		}
+	}
+
+	pHeadTD = pDevice->apCurrTD[TYPE_AC0DMA];
+
+	pHeadTD->m_td1TD1.byTCR = (TCR_EDP|TCR_STP);
+
+	memcpy(pDevice->sTxEthHeader.abyDstAddr, (unsigned char *)(skb->data), ETH_HLEN);
+	cbFrameBodySize = skb->len - ETH_HLEN;
+	// 802.1H
+	if (ntohs(pDevice->sTxEthHeader.wType) > ETH_DATA_LEN) {
+		cbFrameBodySize += 8;
+	}
+
+	if (pDevice->bEncryptionEnable == true) {
+		bNeedEncryption = true;
+		// get Transmit key
+		do {
+			if ((pDevice->pMgmt->eCurrMode == WMAC_MODE_ESS_STA) &&
+			    (pDevice->pMgmt->eCurrState == WMAC_STATE_ASSOC)) {
+				pbyBSSID = pDevice->abyBSSID;
+				// get pairwise key
+				if (KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, PAIRWISE_KEY, &pTransmitKey) == false) {
+					// get group key
+					if (KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, GROUP_KEY, &pTransmitKey) == true) {
+						bTKIP_UseGTK = true;
+						DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG "Get GTK.\n");
+						break;
+					}
+				} else {
+					DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG "Get PTK.\n");
+					break;
+				}
+			} else if (pDevice->pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) {
+				pbyBSSID = pDevice->sTxEthHeader.abyDstAddr;  //TO_DS = 0 and FROM_DS = 0 --> 802.11 MAC Address1
+				DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG "IBSS Serach Key: \n");
+				for (ii = 0; ii < 6; ii++)
+					DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG "%x \n", *(pbyBSSID+ii));
+				DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG "\n");
+
+				// get pairwise key
+				if (KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, PAIRWISE_KEY, &pTransmitKey) == true)
+					break;
+			}
+			// get group key
+			pbyBSSID = pDevice->abyBroadcastAddr;
+			if (KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, GROUP_KEY, &pTransmitKey) == false) {
+				pTransmitKey = NULL;
+				if (pDevice->pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) {
+					DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG "IBSS and KEY is NULL. [%d]\n", pDevice->pMgmt->eCurrMode);
+				} else
+					DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG "NOT IBSS and KEY is NULL. [%d]\n", pDevice->pMgmt->eCurrMode);
+			} else {
+				bTKIP_UseGTK = true;
+				DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG "Get GTK.\n");
+			}
+		} while (false);
+	}
+
+	if (pDevice->bEnableHostWEP) {
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG "acdma0: STA index %d\n", uNodeIndex);
+		if (pDevice->bEncryptionEnable == true) {
+			pTransmitKey = &STempKey;
+			pTransmitKey->byCipherSuite = pMgmt->sNodeDBTable[uNodeIndex].byCipherSuite;
+			pTransmitKey->dwKeyIndex = pMgmt->sNodeDBTable[uNodeIndex].dwKeyIndex;
+			pTransmitKey->uKeyLength = pMgmt->sNodeDBTable[uNodeIndex].uWepKeyLength;
+			pTransmitKey->dwTSC47_16 = pMgmt->sNodeDBTable[uNodeIndex].dwTSC47_16;
+			pTransmitKey->wTSC15_0 = pMgmt->sNodeDBTable[uNodeIndex].wTSC15_0;
+			memcpy(pTransmitKey->abyKey,
+			       &pMgmt->sNodeDBTable[uNodeIndex].abyWepKey[0],
+			       pTransmitKey->uKeyLength
+				);
+		}
+	}
+
+	uMACfragNum = cbGetFragCount(pDevice, pTransmitKey, cbFrameBodySize, &pDevice->sTxEthHeader);
+
+	if (uMACfragNum > AVAIL_TD(pDevice, TYPE_AC0DMA)) {
+		DBG_PRT(MSG_LEVEL_ERR, KERN_DEBUG "uMACfragNum > AVAIL_TD(TYPE_AC0DMA) = %d\n", uMACfragNum);
+		dev_kfree_skb_irq(skb);
+		spin_unlock_irq(&pDevice->lock);
+		return 0;
+	}
+
+	if (pTransmitKey != NULL) {
+		if ((pTransmitKey->byCipherSuite == KEY_CTL_WEP) &&
+		    (pTransmitKey->uKeyLength == WLAN_WEP232_KEYLEN)) {
+			uMACfragNum = 1; //WEP256 doesn't support fragment
+		}
+	}
+
+	byPktType = (unsigned char)pDevice->byPacketType;
+
+	if (pDevice->bFixRate) {
 #ifdef	PLICE_DEBUG
-	printk("Fix Rate: PhyType is %d,ConnectionRate is %d\n",pDevice->eCurrentPHYType,pDevice->uConnectionRate);
+		printk("Fix Rate: PhyType is %d,ConnectionRate is %d\n", pDevice->eCurrentPHYType, pDevice->uConnectionRate);
 #endif
 
-        if (pDevice->eCurrentPHYType == PHY_TYPE_11B) {
-            if (pDevice->uConnectionRate >= RATE_11M) {
-                pDevice->wCurrentRate = RATE_11M;
-            } else {
-                pDevice->wCurrentRate = (unsigned short)pDevice->uConnectionRate;
-            }
-        } else {
-            if ((pDevice->eCurrentPHYType == PHY_TYPE_11A) &&
-                (pDevice->uConnectionRate <= RATE_6M)) {
-                pDevice->wCurrentRate = RATE_6M;
-            } else {
-                if (pDevice->uConnectionRate >= RATE_54M)
-                    pDevice->wCurrentRate = RATE_54M;
-                else
-                    pDevice->wCurrentRate = (unsigned short)pDevice->uConnectionRate;
-
-            }
-        }
-        pDevice->byACKRate = (unsigned char) pDevice->wCurrentRate;
-        pDevice->byTopCCKBasicRate = RATE_1M;
-        pDevice->byTopOFDMBasicRate = RATE_6M;
-    }
-    else {
-        //auto rate
-    if (pDevice->sTxEthHeader.wType == TYPE_PKT_802_1x) {
-            if (pDevice->eCurrentPHYType != PHY_TYPE_11A) {
-                pDevice->wCurrentRate = RATE_1M;
-                pDevice->byACKRate = RATE_1M;
-                pDevice->byTopCCKBasicRate = RATE_1M;
-                pDevice->byTopOFDMBasicRate = RATE_6M;
-            } else {
-                pDevice->wCurrentRate = RATE_6M;
-                pDevice->byACKRate = RATE_6M;
-                pDevice->byTopCCKBasicRate = RATE_1M;
-                pDevice->byTopOFDMBasicRate = RATE_6M;
-            }
-        }
-        else {
-		VNTWIFIvGetTxRate(  pDevice->pMgmt,
-                                pDevice->sTxEthHeader.abyDstAddr,
-                                &(pDevice->wCurrentRate),
-                                &(pDevice->byACKRate),
-                                &(pDevice->byTopCCKBasicRate),
-                                &(pDevice->byTopOFDMBasicRate));
+		if (pDevice->eCurrentPHYType == PHY_TYPE_11B) {
+			if (pDevice->uConnectionRate >= RATE_11M) {
+				pDevice->wCurrentRate = RATE_11M;
+			} else {
+				pDevice->wCurrentRate = (unsigned short)pDevice->uConnectionRate;
+			}
+		} else {
+			if ((pDevice->eCurrentPHYType == PHY_TYPE_11A) &&
+			    (pDevice->uConnectionRate <= RATE_6M)) {
+				pDevice->wCurrentRate = RATE_6M;
+			} else {
+				if (pDevice->uConnectionRate >= RATE_54M)
+					pDevice->wCurrentRate = RATE_54M;
+				else
+					pDevice->wCurrentRate = (unsigned short)pDevice->uConnectionRate;
 
+			}
+		}
+		pDevice->byACKRate = (unsigned char) pDevice->wCurrentRate;
+		pDevice->byTopCCKBasicRate = RATE_1M;
+		pDevice->byTopOFDMBasicRate = RATE_6M;
+	} else {
+		//auto rate
+		if (pDevice->sTxEthHeader.wType == TYPE_PKT_802_1x) {
+			if (pDevice->eCurrentPHYType != PHY_TYPE_11A) {
+				pDevice->wCurrentRate = RATE_1M;
+				pDevice->byACKRate = RATE_1M;
+				pDevice->byTopCCKBasicRate = RATE_1M;
+				pDevice->byTopOFDMBasicRate = RATE_6M;
+			} else {
+				pDevice->wCurrentRate = RATE_6M;
+				pDevice->byACKRate = RATE_6M;
+				pDevice->byTopCCKBasicRate = RATE_1M;
+				pDevice->byTopOFDMBasicRate = RATE_6M;
+			}
+		} else {
+			VNTWIFIvGetTxRate(pDevice->pMgmt,
+					  pDevice->sTxEthHeader.abyDstAddr,
+					  &(pDevice->wCurrentRate),
+					  &(pDevice->byACKRate),
+					  &(pDevice->byTopCCKBasicRate),
+					  &(pDevice->byTopOFDMBasicRate));
 
 		}
-    }
+	}
 
 //    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "acdma0: pDevice->wCurrentRate = %d \n", pDevice->wCurrentRate);
 
-    if (pDevice->wCurrentRate <= RATE_11M) {
-        byPktType = PK_TYPE_11B;
-    } else if (pDevice->eCurrentPHYType == PHY_TYPE_11A) {
-        byPktType = PK_TYPE_11A;
-    } else {
-        if (pDevice->bProtectMode == true) {
-            byPktType = PK_TYPE_11GB;
-        } else {
-            byPktType = PK_TYPE_11GA;
-        }
-    }
+	if (pDevice->wCurrentRate <= RATE_11M) {
+		byPktType = PK_TYPE_11B;
+	} else if (pDevice->eCurrentPHYType == PHY_TYPE_11A) {
+		byPktType = PK_TYPE_11A;
+	} else {
+		if (pDevice->bProtectMode == true) {
+			byPktType = PK_TYPE_11GB;
+		} else {
+			byPktType = PK_TYPE_11GA;
+		}
+	}
 
 //#ifdef	PLICE_DEBUG
 //	printk("FIX RATE:CurrentRate is %d");
 //#endif
 
-    if (bNeedEncryption == true) {
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ntohs Pkt Type=%04x\n", ntohs(pDevice->sTxEthHeader.wType));
-        if ((pDevice->sTxEthHeader.wType) == TYPE_PKT_802_1x) {
-            bNeedEncryption = false;
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Pkt Type=%04x\n", (pDevice->sTxEthHeader.wType));
-            if ((pDevice->pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && (pDevice->pMgmt->eCurrState == WMAC_STATE_ASSOC)) {
-                if (pTransmitKey == NULL) {
-                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Don't Find TX KEY\n");
-                }
-                else {
-                    if (bTKIP_UseGTK == true) {
-                        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"error: KEY is GTK!!~~\n");
-                    }
-                    else {
-                        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Find PTK [%lX]\n", pTransmitKey->dwKeyIndex);
-                        bNeedEncryption = true;
-                    }
-                }
-            }
-
-            if (pDevice->byCntMeasure == 2) {
-                bNeedDeAuth = true;
-                pDevice->s802_11Counter.TKIPCounterMeasuresInvoked++;
-            }
-
-            if (pDevice->bEnableHostWEP) {
-                if ((uNodeIndex != 0) &&
-                    (pMgmt->sNodeDBTable[uNodeIndex].dwKeyIndex & PAIRWISE_KEY)) {
-                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Find PTK [%lX]\n", pTransmitKey->dwKeyIndex);
-                    bNeedEncryption = true;
-                 }
-             }
-        }
-        else {
-            if (pTransmitKey == NULL) {
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"return no tx key\n");
-                dev_kfree_skb_irq(skb);
-                spin_unlock_irq(&pDevice->lock);
-                return 0;
-            }
-        }
-    }
+	if (bNeedEncryption == true) {
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ntohs Pkt Type=%04x\n", ntohs(pDevice->sTxEthHeader.wType));
+		if ((pDevice->sTxEthHeader.wType) == TYPE_PKT_802_1x) {
+			bNeedEncryption = false;
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pkt Type=%04x\n", (pDevice->sTxEthHeader.wType));
+			if ((pDevice->pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && (pDevice->pMgmt->eCurrState == WMAC_STATE_ASSOC)) {
+				if (pTransmitKey == NULL) {
+					DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Don't Find TX KEY\n");
+				} else {
+					if (bTKIP_UseGTK == true) {
+						DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "error: KEY is GTK!!~~\n");
+					} else {
+						DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Find PTK [%lX]\n", pTransmitKey->dwKeyIndex);
+						bNeedEncryption = true;
+					}
+				}
+			}
 
+			if (pDevice->byCntMeasure == 2) {
+				bNeedDeAuth = true;
+				pDevice->s802_11Counter.TKIPCounterMeasuresInvoked++;
+			}
 
-#ifdef	PLICE_DEBUG
-	//if (skb->len == 98)
-	//{
-	//	printk("ping:len is %d\n");
-	//}
-#endif
-    vGenerateFIFOHeader(pDevice, byPktType, pDevice->pbyTmpBuff, bNeedEncryption,
-                        cbFrameBodySize, TYPE_AC0DMA, pHeadTD,
-                        &pDevice->sTxEthHeader, (unsigned char *)skb->data, pTransmitKey, uNodeIndex,
-                        &uMACfragNum,
-                        &cbHeaderSize
-                        );
-
-    if (MACbIsRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_PS)) {
-        // Disable PS
-        MACbPSWakeup(pDevice->PortOffset);
-    }
-    pDevice->bPWBitOn = false;
-
-    pLastTD = pHeadTD;
-    for (ii = 0; ii < uMACfragNum; ii++) {
-        // Poll Transmit the adapter
-        wmb();
-        pHeadTD->m_td0TD0.f1Owner=OWNED_BY_NIC;
-        wmb();
-        if (ii == uMACfragNum - 1)
-            pLastTD = pHeadTD;
-        pHeadTD = pHeadTD->next;
-    }
-
-    // Save the information needed by the tx interrupt handler
-    // to complete the Send request
-    pLastTD->pTDInfo->skb = skb;
-    pLastTD->pTDInfo->byFlags = 0;
-    pLastTD->pTDInfo->byFlags |= TD_FLAGS_NETIF_SKB;
+			if (pDevice->bEnableHostWEP) {
+				if ((uNodeIndex != 0) &&
+				    (pMgmt->sNodeDBTable[uNodeIndex].dwKeyIndex & PAIRWISE_KEY)) {
+					DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Find PTK [%lX]\n", pTransmitKey->dwKeyIndex);
+					bNeedEncryption = true;
+				}
+			}
+		} else {
+			if (pTransmitKey == NULL) {
+				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "return no tx key\n");
+				dev_kfree_skb_irq(skb);
+				spin_unlock_irq(&pDevice->lock);
+				return 0;
+			}
+		}
+	}
+
+	vGenerateFIFOHeader(pDevice, byPktType, pDevice->pbyTmpBuff, bNeedEncryption,
+			    cbFrameBodySize, TYPE_AC0DMA, pHeadTD,
+			    &pDevice->sTxEthHeader, (unsigned char *)skb->data, pTransmitKey, uNodeIndex,
+			    &uMACfragNum,
+			    &cbHeaderSize
+		);
+
+	if (MACbIsRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_PS)) {
+		// Disable PS
+		MACbPSWakeup(pDevice->PortOffset);
+	}
+	pDevice->bPWBitOn = false;
+
+	pLastTD = pHeadTD;
+	for (ii = 0; ii < uMACfragNum; ii++) {
+		// Poll Transmit the adapter
+		wmb();
+		pHeadTD->m_td0TD0.f1Owner = OWNED_BY_NIC;
+		wmb();
+		if (ii == uMACfragNum - 1)
+			pLastTD = pHeadTD;
+		pHeadTD = pHeadTD->next;
+	}
+
+	// Save the information needed by the tx interrupt handler
+	// to complete the Send request
+	pLastTD->pTDInfo->skb = skb;
+	pLastTD->pTDInfo->byFlags = 0;
+	pLastTD->pTDInfo->byFlags |= TD_FLAGS_NETIF_SKB;
 #ifdef TxInSleep
-  pDevice->nTxDataTimeCout=0; //2008-8-21 chester <add> for send null packet
-  #endif
-    if (AVAIL_TD(pDevice, TYPE_AC0DMA) <= 1) {
-        netif_stop_queue(dev);
-    }
+	pDevice->nTxDataTimeCout = 0; //2008-8-21 chester <add> for send null packet
+#endif
+	if (AVAIL_TD(pDevice, TYPE_AC0DMA) <= 1) {
+		netif_stop_queue(dev);
+	}
 
-    pDevice->apCurrTD[TYPE_AC0DMA] = pHeadTD;
+	pDevice->apCurrTD[TYPE_AC0DMA] = pHeadTD;
 //#ifdef	PLICE_DEBUG
-	if (pDevice->bFixRate)
-	{
-		printk("FixRate:Rate is %d,TxPower is %d\n",pDevice->wCurrentRate,pDevice->byCurPwr);
-	}
-	else
-	{
-		//printk("Auto Rate:Rate is %d,TxPower is %d\n",pDevice->wCurrentRate,pDevice->byCurPwr);
+	if (pDevice->bFixRate) {
+		printk("FixRate:Rate is %d,TxPower is %d\n", pDevice->wCurrentRate, pDevice->byCurPwr);
+	} else {
 	}
 //#endif
 
-{
-    unsigned char Protocol_Version;    //802.1x Authentication
-    unsigned char Packet_Type;           //802.1x Authentication
-    unsigned char Descriptor_type;
-    unsigned short Key_info;
-bool bTxeapol_key = false;
-    Protocol_Version = skb->data[ETH_HLEN];
-    Packet_Type = skb->data[ETH_HLEN+1];
-    Descriptor_type = skb->data[ETH_HLEN+1+1+2];
-    Key_info = (skb->data[ETH_HLEN+1+1+2+1] << 8)|(skb->data[ETH_HLEN+1+1+2+2]);
-   if (pDevice->sTxEthHeader.wType == TYPE_PKT_802_1x) {
-           if(((Protocol_Version==1) ||(Protocol_Version==2)) &&
-	        (Packet_Type==3)) {  //802.1x OR eapol-key challenge frame transfer
-                        bTxeapol_key = true;
-		if((Descriptor_type==254)||(Descriptor_type==2)) {       //WPA or RSN
-                       if(!(Key_info & BIT3) &&   //group-key challenge
-			   (Key_info & BIT8) && (Key_info & BIT9)) {    //send 2/2 key
-			  pDevice->fWPA_Authened = true;
-			  if(Descriptor_type==254)
-			      printk("WPA ");
-			  else
-			      printk("WPA2 ");
-			  printk("Authentication completed!!\n");
-                        }
-		 }
-             }
-   }
-}
+	{
+		unsigned char Protocol_Version;    //802.1x Authentication
+		unsigned char Packet_Type;           //802.1x Authentication
+		unsigned char Descriptor_type;
+		unsigned short Key_info;
+		bool bTxeapol_key = false;
+		Protocol_Version = skb->data[ETH_HLEN];
+		Packet_Type = skb->data[ETH_HLEN+1];
+		Descriptor_type = skb->data[ETH_HLEN+1+1+2];
+		Key_info = (skb->data[ETH_HLEN+1+1+2+1] << 8)|(skb->data[ETH_HLEN+1+1+2+2]);
+		if (pDevice->sTxEthHeader.wType == TYPE_PKT_802_1x) {
+			if (((Protocol_Version == 1) || (Protocol_Version == 2)) &&
+			    (Packet_Type == 3)) {  //802.1x OR eapol-key challenge frame transfer
+				bTxeapol_key = true;
+				if ((Descriptor_type == 254) || (Descriptor_type == 2)) {       //WPA or RSN
+					if (!(Key_info & BIT3) &&   //group-key challenge
+					    (Key_info & BIT8) && (Key_info & BIT9)) {    //send 2/2 key
+						pDevice->fWPA_Authened = true;
+						if (Descriptor_type == 254)
+							printk("WPA ");
+						else
+							printk("WPA2 ");
+						printk("Authentication completed!!\n");
+					}
+				}
+			}
+		}
+	}
 
-    MACvTransmitAC0(pDevice->PortOffset);
+	MACvTransmitAC0(pDevice->PortOffset);
 //    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "acdma0:pDevice->apCurrTD= %p\n", pHeadTD);
 
-    dev->trans_start = jiffies;
-
-    spin_unlock_irq(&pDevice->lock);
-    return 0;
+	dev->trans_start = jiffies;
 
+	spin_unlock_irq(&pDevice->lock);
+	return 0;
 }
 
 static  irqreturn_t  device_intr(int irq,  void *dev_instance) {
-    struct net_device* dev=dev_instance;
-    PSDevice     pDevice=(PSDevice) netdev_priv(dev);
-
-    int             max_count=0;
-    unsigned long dwMIBCounter=0;
-    PSMgmtObject    pMgmt = pDevice->pMgmt;
-    unsigned char byOrgPageSel=0;
-    int             handled = 0;
-    unsigned char byData = 0;
-    int             ii= 0;
+	struct net_device *dev = dev_instance;
+	PSDevice     pDevice = (PSDevice)netdev_priv(dev);
+
+	int             max_count = 0;
+	unsigned long dwMIBCounter = 0;
+	PSMgmtObject    pMgmt = pDevice->pMgmt;
+	unsigned char byOrgPageSel = 0;
+	int             handled = 0;
+	unsigned char byData = 0;
+	int             ii = 0;
 //    unsigned char byRSSI;
 
+	MACvReadISR(pDevice->PortOffset, &pDevice->dwIsr);
 
-    MACvReadISR(pDevice->PortOffset, &pDevice->dwIsr);
-
-    if (pDevice->dwIsr == 0)
-        return IRQ_RETVAL(handled);
-
-    if (pDevice->dwIsr == 0xffffffff) {
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dwIsr = 0xffff\n");
-        return IRQ_RETVAL(handled);
-    }
-    /*
-      // 2008-05-21 <mark> by Richardtai, we can't read RSSI here, because no packet bound with RSSI
-
-    	if ((pDevice->dwIsr & ISR_RXDMA0) &&
-        (pDevice->byLocalID != REV_ID_VT3253_B0) &&
-        (pDevice->bBSSIDFilter == true)) {
-        // update RSSI
-        //BBbReadEmbedded(pDevice->PortOffset, 0x3E, &byRSSI);
-        //pDevice->uCurrRSSI = byRSSI;
-    }
-    */
-
-    handled = 1;
-    MACvIntDisable(pDevice->PortOffset);
-    spin_lock_irq(&pDevice->lock);
-
-    //Make sure current page is 0
-    VNSvInPortB(pDevice->PortOffset + MAC_REG_PAGE1SEL, &byOrgPageSel);
-    if (byOrgPageSel == 1) {
-        MACvSelectPage0(pDevice->PortOffset);
-    }
-    else
-        byOrgPageSel = 0;
-
-    MACvReadMIBCounter(pDevice->PortOffset, &dwMIBCounter);
-    // TBD....
-    // Must do this after doing rx/tx, cause ISR bit is slow
-    // than RD/TD write back
-    // update ISR counter
-    STAvUpdate802_11Counter(&pDevice->s802_11Counter, &pDevice->scStatistic , dwMIBCounter);
-    while (pDevice->dwIsr != 0) {
-
-        STAvUpdateIsrStatCounter(&pDevice->scStatistic, pDevice->dwIsr);
-        MACvWriteISR(pDevice->PortOffset, pDevice->dwIsr);
-
-        if (pDevice->dwIsr & ISR_FETALERR){
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " ISR_FETALERR \n");
-            VNSvOutPortB(pDevice->PortOffset + MAC_REG_SOFTPWRCTL, 0);
-            VNSvOutPortW(pDevice->PortOffset + MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPECTI);
-            device_error(pDevice, pDevice->dwIsr);
-        }
-
-        if (pDevice->byLocalID > REV_ID_VT3253_B1) {
-
-            if (pDevice->dwIsr & ISR_MEASURESTART) {
-                // 802.11h measure start
-                pDevice->byOrgChannel = pDevice->byCurrentCh;
-                VNSvInPortB(pDevice->PortOffset + MAC_REG_RCR, &(pDevice->byOrgRCR));
-                VNSvOutPortB(pDevice->PortOffset + MAC_REG_RCR, (RCR_RXALLTYPE | RCR_UNICAST | RCR_BROADCAST | RCR_MULTICAST | RCR_WPAERR));
-                MACvSelectPage1(pDevice->PortOffset);
-                VNSvInPortD(pDevice->PortOffset + MAC_REG_MAR0, &(pDevice->dwOrgMAR0));
-                VNSvInPortD(pDevice->PortOffset + MAC_REG_MAR4, &(pDevice->dwOrgMAR4));
-                MACvSelectPage0(pDevice->PortOffset);
-               //xxxx
-               // WCMDbFlushCommandQueue(pDevice->pMgmt, true);
-                if (set_channel(pDevice, pDevice->pCurrMeasureEID->sReq.byChannel) == true) {
-                    pDevice->bMeasureInProgress = true;
-                    MACvSelectPage1(pDevice->PortOffset);
-                    MACvRegBitsOn(pDevice->PortOffset, MAC_REG_MSRCTL, MSRCTL_READY);
-                    MACvSelectPage0(pDevice->PortOffset);
-                    pDevice->byBasicMap = 0;
-                    pDevice->byCCAFraction = 0;
-                    for(ii=0;ii<8;ii++) {
-                        pDevice->dwRPIs[ii] = 0;
-                    }
-                } else {
-                    // can not measure because set channel fail
-                   // WCMDbResetCommandQueue(pDevice->pMgmt);
-                    // clear measure control
-                    MACvRegBitsOff(pDevice->PortOffset, MAC_REG_MSRCTL, MSRCTL_EN);
-                    s_vCompleteCurrentMeasure(pDevice, MEASURE_MODE_INCAPABLE);
-                    MACvSelectPage1(pDevice->PortOffset);
-                    MACvRegBitsOn(pDevice->PortOffset, MAC_REG_MSRCTL+1, MSRCTL1_TXPAUSE);
-                    MACvSelectPage0(pDevice->PortOffset);
-                }
-            }
-            if (pDevice->dwIsr & ISR_MEASUREEND) {
-                // 802.11h measure end
-                pDevice->bMeasureInProgress = false;
-                VNSvOutPortB(pDevice->PortOffset + MAC_REG_RCR, pDevice->byOrgRCR);
-                MACvSelectPage1(pDevice->PortOffset);
-                VNSvOutPortD(pDevice->PortOffset + MAC_REG_MAR0, pDevice->dwOrgMAR0);
-                VNSvOutPortD(pDevice->PortOffset + MAC_REG_MAR4, pDevice->dwOrgMAR4);
-                VNSvInPortB(pDevice->PortOffset + MAC_REG_MSRBBSTS, &byData);
-                pDevice->byBasicMap |= (byData >> 4);
-                VNSvInPortB(pDevice->PortOffset + MAC_REG_CCAFRACTION, &pDevice->byCCAFraction);
-                VNSvInPortB(pDevice->PortOffset + MAC_REG_MSRCTL, &byData);
-                // clear measure control
-                MACvRegBitsOff(pDevice->PortOffset, MAC_REG_MSRCTL, MSRCTL_EN);
-                MACvSelectPage0(pDevice->PortOffset);
-                set_channel(pDevice, pDevice->byOrgChannel);
-                // WCMDbResetCommandQueue(pDevice->pMgmt);
-                MACvSelectPage1(pDevice->PortOffset);
-                MACvRegBitsOn(pDevice->PortOffset, MAC_REG_MSRCTL+1, MSRCTL1_TXPAUSE);
-                MACvSelectPage0(pDevice->PortOffset);
-                if (byData & MSRCTL_FINISH) {
-                    // measure success
-                    s_vCompleteCurrentMeasure(pDevice, 0);
-                } else {
-                    // can not measure because not ready before end of measure time
-                    s_vCompleteCurrentMeasure(pDevice, MEASURE_MODE_LATE);
-                }
-            }
-            if (pDevice->dwIsr & ISR_QUIETSTART) {
-                do {
-                    ;
-                } while (CARDbStartQuiet(pDevice) == false);
-            }
-        }
-
-        if (pDevice->dwIsr & ISR_TBTT) {
-            if (pDevice->bEnableFirstQuiet == true) {
-                pDevice->byQuietStartCount--;
-                if (pDevice->byQuietStartCount == 0) {
-                    pDevice->bEnableFirstQuiet = false;
-                    MACvSelectPage1(pDevice->PortOffset);
-                    MACvRegBitsOn(pDevice->PortOffset, MAC_REG_MSRCTL, (MSRCTL_QUIETTXCHK | MSRCTL_QUIETEN));
-                    MACvSelectPage0(pDevice->PortOffset);
-                }
-            }
-            if ((pDevice->bChannelSwitch == true) &&
-                (pDevice->eOPMode == OP_MODE_INFRASTRUCTURE)) {
-                pDevice->byChannelSwitchCount--;
-                if (pDevice->byChannelSwitchCount == 0) {
-                    pDevice->bChannelSwitch = false;
-                    set_channel(pDevice, pDevice->byNewChannel);
-                    VNTWIFIbChannelSwitch(pDevice->pMgmt, pDevice->byNewChannel);
-                    MACvSelectPage1(pDevice->PortOffset);
-                    MACvRegBitsOn(pDevice->PortOffset, MAC_REG_MSRCTL+1, MSRCTL1_TXPAUSE);
-                    MACvSelectPage0(pDevice->PortOffset);
-                    CARDbStartTxPacket(pDevice, PKT_TYPE_802_11_ALL);
-
-                }
-            }
-            if (pDevice->eOPMode == OP_MODE_ADHOC) {
-                //pDevice->bBeaconSent = false;
-            } else {
-                if ((pDevice->bUpdateBBVGA) && (pDevice->bLinkPass == true) && (pDevice->uCurrRSSI != 0)) {
-                    long            ldBm;
-
-                    RFvRSSITodBm(pDevice, (unsigned char) pDevice->uCurrRSSI, &ldBm);
-                    for (ii=0;ii<BB_VGA_LEVEL;ii++) {
-                        if (ldBm < pDevice->ldBmThreshold[ii]) {
-                            pDevice->byBBVGANew = pDevice->abyBBVGA[ii];
-                            break;
-                        }
-                    }
-                    if (pDevice->byBBVGANew != pDevice->byBBVGACurrent) {
-                        pDevice->uBBVGADiffCount++;
-                        if (pDevice->uBBVGADiffCount == 1) {
-                            // first VGA diff gain
-                            BBvSetVGAGainOffset(pDevice, pDevice->byBBVGANew);
-                            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"First RSSI[%d] NewGain[%d] OldGain[%d] Count[%d]\n",
-                                            (int)ldBm, pDevice->byBBVGANew, pDevice->byBBVGACurrent, (int)pDevice->uBBVGADiffCount);
-                        }
-                        if (pDevice->uBBVGADiffCount >= BB_VGA_CHANGE_THRESHOLD) {
-                            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"RSSI[%d] NewGain[%d] OldGain[%d] Count[%d]\n",
-                                            (int)ldBm, pDevice->byBBVGANew, pDevice->byBBVGACurrent, (int)pDevice->uBBVGADiffCount);
-                            BBvSetVGAGainOffset(pDevice, pDevice->byBBVGANew);
-                        }
-                    } else {
-                        pDevice->uBBVGADiffCount = 1;
-                    }
-                }
-            }
-
-            pDevice->bBeaconSent = false;
-            if (pDevice->bEnablePSMode) {
-                PSbIsNextTBTTWakeUp((void *)pDevice);
-            }
-
-            if ((pDevice->eOPMode == OP_MODE_AP) ||
-                (pDevice->eOPMode == OP_MODE_ADHOC)) {
-
-                MACvOneShotTimer1MicroSec(pDevice->PortOffset,
-                        (pMgmt->wIBSSBeaconPeriod - MAKE_BEACON_RESERVED) << 10);
-            }
-
-            if (pDevice->eOPMode == OP_MODE_ADHOC && pDevice->pMgmt->wCurrATIMWindow > 0) {
-                // todo adhoc PS mode
-            }
-
-        }
-
-        if (pDevice->dwIsr & ISR_BNTX) {
-
-            if (pDevice->eOPMode == OP_MODE_ADHOC) {
-                pDevice->bIsBeaconBufReadySet = false;
-                pDevice->cbBeaconBufReadySetCnt = 0;
-            }
-
-            if (pDevice->eOPMode == OP_MODE_AP) {
-                if(pMgmt->byDTIMCount > 0) {
-                   pMgmt->byDTIMCount --;
-                   pMgmt->sNodeDBTable[0].bRxPSPoll = false;
-                }
-                else {
-                    if(pMgmt->byDTIMCount == 0) {
-                        // check if mutltcast tx bufferring
-                        pMgmt->byDTIMCount = pMgmt->byDTIMPeriod - 1;
-                        pMgmt->sNodeDBTable[0].bRxPSPoll = true;
-                        bScheduleCommand((void *)pDevice, WLAN_CMD_RX_PSPOLL, NULL);
-                    }
-                }
-            }
-            pDevice->bBeaconSent = true;
-
-            if (pDevice->bChannelSwitch == true) {
-                pDevice->byChannelSwitchCount--;
-                if (pDevice->byChannelSwitchCount == 0) {
-                    pDevice->bChannelSwitch = false;
-                    set_channel(pDevice, pDevice->byNewChannel);
-                    VNTWIFIbChannelSwitch(pDevice->pMgmt, pDevice->byNewChannel);
-                    MACvSelectPage1(pDevice->PortOffset);
-                    MACvRegBitsOn(pDevice->PortOffset, MAC_REG_MSRCTL+1, MSRCTL1_TXPAUSE);
-                    MACvSelectPage0(pDevice->PortOffset);
-                    //VNTWIFIbSendBeacon(pDevice->pMgmt);
-                    CARDbStartTxPacket(pDevice, PKT_TYPE_802_11_ALL);
-                }
-            }
-
-        }
-
-        if (pDevice->dwIsr & ISR_RXDMA0) {
-            max_count += device_rx_srv(pDevice, TYPE_RXDMA0);
-        }
-        if (pDevice->dwIsr & ISR_RXDMA1) {
-            max_count += device_rx_srv(pDevice, TYPE_RXDMA1);
-        }
-        if (pDevice->dwIsr & ISR_TXDMA0){
-            max_count += device_tx_srv(pDevice, TYPE_TXDMA0);
-        }
-        if (pDevice->dwIsr & ISR_AC0DMA){
-            max_count += device_tx_srv(pDevice, TYPE_AC0DMA);
-        }
-        if (pDevice->dwIsr & ISR_SOFTTIMER) {
-
-        }
-        if (pDevice->dwIsr & ISR_SOFTTIMER1) {
-            if (pDevice->eOPMode == OP_MODE_AP) {
-               if (pDevice->bShortSlotTime)
-                   pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SHORTSLOTTIME(1);
-               else
-                   pMgmt->wCurrCapInfo &= ~(WLAN_SET_CAP_INFO_SHORTSLOTTIME(1));
-            }
-            bMgrPrepareBeaconToSend(pDevice, pMgmt);
-            pDevice->byCntMeasure = 0;
-        }
-
-        MACvReadISR(pDevice->PortOffset, &pDevice->dwIsr);
-
-        MACvReceive0(pDevice->PortOffset);
-        MACvReceive1(pDevice->PortOffset);
-
-        if (max_count>pDevice->sOpts.int_works)
-            break;
-    }
-
-    if (byOrgPageSel == 1) {
-        MACvSelectPage1(pDevice->PortOffset);
-    }
-
-    spin_unlock_irq(&pDevice->lock);
-    MACvIntEnable(pDevice->PortOffset, IMR_MASK_VALUE);
-
-    return IRQ_RETVAL(handled);
-}
+	if (pDevice->dwIsr == 0)
+		return IRQ_RETVAL(handled);
+
+	if (pDevice->dwIsr == 0xffffffff) {
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dwIsr = 0xffff\n");
+		return IRQ_RETVAL(handled);
+	}
+	/*
+	// 2008-05-21 <mark> by Richardtai, we can't read RSSI here, because no packet bound with RSSI
+
+	if ((pDevice->dwIsr & ISR_RXDMA0) &&
+	(pDevice->byLocalID != REV_ID_VT3253_B0) &&
+	(pDevice->bBSSIDFilter == true)) {
+	// update RSSI
+	//BBbReadEmbedded(pDevice->PortOffset, 0x3E, &byRSSI);
+	//pDevice->uCurrRSSI = byRSSI;
+	}
+	*/
+
+	handled = 1;
+	MACvIntDisable(pDevice->PortOffset);
+	spin_lock_irq(&pDevice->lock);
+
+	//Make sure current page is 0
+	VNSvInPortB(pDevice->PortOffset + MAC_REG_PAGE1SEL, &byOrgPageSel);
+	if (byOrgPageSel == 1) {
+		MACvSelectPage0(pDevice->PortOffset);
+	} else
+		byOrgPageSel = 0;
+
+	MACvReadMIBCounter(pDevice->PortOffset, &dwMIBCounter);
+	// TBD....
+	// Must do this after doing rx/tx, cause ISR bit is slow
+	// than RD/TD write back
+	// update ISR counter
+	STAvUpdate802_11Counter(&pDevice->s802_11Counter, &pDevice->scStatistic , dwMIBCounter);
+	while (pDevice->dwIsr != 0) {
+		STAvUpdateIsrStatCounter(&pDevice->scStatistic, pDevice->dwIsr);
+		MACvWriteISR(pDevice->PortOffset, pDevice->dwIsr);
+
+		if (pDevice->dwIsr & ISR_FETALERR) {
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " ISR_FETALERR \n");
+			VNSvOutPortB(pDevice->PortOffset + MAC_REG_SOFTPWRCTL, 0);
+			VNSvOutPortW(pDevice->PortOffset + MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPECTI);
+			device_error(pDevice, pDevice->dwIsr);
+		}
+
+		if (pDevice->byLocalID > REV_ID_VT3253_B1) {
+			if (pDevice->dwIsr & ISR_MEASURESTART) {
+				// 802.11h measure start
+				pDevice->byOrgChannel = pDevice->byCurrentCh;
+				VNSvInPortB(pDevice->PortOffset + MAC_REG_RCR, &(pDevice->byOrgRCR));
+				VNSvOutPortB(pDevice->PortOffset + MAC_REG_RCR, (RCR_RXALLTYPE | RCR_UNICAST | RCR_BROADCAST | RCR_MULTICAST | RCR_WPAERR));
+				MACvSelectPage1(pDevice->PortOffset);
+				VNSvInPortD(pDevice->PortOffset + MAC_REG_MAR0, &(pDevice->dwOrgMAR0));
+				VNSvInPortD(pDevice->PortOffset + MAC_REG_MAR4, &(pDevice->dwOrgMAR4));
+				MACvSelectPage0(pDevice->PortOffset);
+				//xxxx
+				// WCMDbFlushCommandQueue(pDevice->pMgmt, true);
+				if (set_channel(pDevice, pDevice->pCurrMeasureEID->sReq.byChannel) == true) {
+					pDevice->bMeasureInProgress = true;
+					MACvSelectPage1(pDevice->PortOffset);
+					MACvRegBitsOn(pDevice->PortOffset, MAC_REG_MSRCTL, MSRCTL_READY);
+					MACvSelectPage0(pDevice->PortOffset);
+					pDevice->byBasicMap = 0;
+					pDevice->byCCAFraction = 0;
+					for (ii = 0; ii < 8; ii++) {
+						pDevice->dwRPIs[ii] = 0;
+					}
+				} else {
+					// can not measure because set channel fail
+					// WCMDbResetCommandQueue(pDevice->pMgmt);
+					// clear measure control
+					MACvRegBitsOff(pDevice->PortOffset, MAC_REG_MSRCTL, MSRCTL_EN);
+					s_vCompleteCurrentMeasure(pDevice, MEASURE_MODE_INCAPABLE);
+					MACvSelectPage1(pDevice->PortOffset);
+					MACvRegBitsOn(pDevice->PortOffset, MAC_REG_MSRCTL+1, MSRCTL1_TXPAUSE);
+					MACvSelectPage0(pDevice->PortOffset);
+				}
+			}
+			if (pDevice->dwIsr & ISR_MEASUREEND) {
+				// 802.11h measure end
+				pDevice->bMeasureInProgress = false;
+				VNSvOutPortB(pDevice->PortOffset + MAC_REG_RCR, pDevice->byOrgRCR);
+				MACvSelectPage1(pDevice->PortOffset);
+				VNSvOutPortD(pDevice->PortOffset + MAC_REG_MAR0, pDevice->dwOrgMAR0);
+				VNSvOutPortD(pDevice->PortOffset + MAC_REG_MAR4, pDevice->dwOrgMAR4);
+				VNSvInPortB(pDevice->PortOffset + MAC_REG_MSRBBSTS, &byData);
+				pDevice->byBasicMap |= (byData >> 4);
+				VNSvInPortB(pDevice->PortOffset + MAC_REG_CCAFRACTION, &pDevice->byCCAFraction);
+				VNSvInPortB(pDevice->PortOffset + MAC_REG_MSRCTL, &byData);
+				// clear measure control
+				MACvRegBitsOff(pDevice->PortOffset, MAC_REG_MSRCTL, MSRCTL_EN);
+				MACvSelectPage0(pDevice->PortOffset);
+				set_channel(pDevice, pDevice->byOrgChannel);
+				// WCMDbResetCommandQueue(pDevice->pMgmt);
+				MACvSelectPage1(pDevice->PortOffset);
+				MACvRegBitsOn(pDevice->PortOffset, MAC_REG_MSRCTL+1, MSRCTL1_TXPAUSE);
+				MACvSelectPage0(pDevice->PortOffset);
+				if (byData & MSRCTL_FINISH) {
+					// measure success
+					s_vCompleteCurrentMeasure(pDevice, 0);
+				} else {
+					// can not measure because not ready before end of measure time
+					s_vCompleteCurrentMeasure(pDevice, MEASURE_MODE_LATE);
+				}
+			}
+			if (pDevice->dwIsr & ISR_QUIETSTART) {
+				do {
+					;
+				} while (CARDbStartQuiet(pDevice) == false);
+			}
+		}
+
+		if (pDevice->dwIsr & ISR_TBTT) {
+			if (pDevice->bEnableFirstQuiet == true) {
+				pDevice->byQuietStartCount--;
+				if (pDevice->byQuietStartCount == 0) {
+					pDevice->bEnableFirstQuiet = false;
+					MACvSelectPage1(pDevice->PortOffset);
+					MACvRegBitsOn(pDevice->PortOffset, MAC_REG_MSRCTL, (MSRCTL_QUIETTXCHK | MSRCTL_QUIETEN));
+					MACvSelectPage0(pDevice->PortOffset);
+				}
+			}
+			if ((pDevice->bChannelSwitch == true) &&
+			    (pDevice->eOPMode == OP_MODE_INFRASTRUCTURE)) {
+				pDevice->byChannelSwitchCount--;
+				if (pDevice->byChannelSwitchCount == 0) {
+					pDevice->bChannelSwitch = false;
+					set_channel(pDevice, pDevice->byNewChannel);
+					VNTWIFIbChannelSwitch(pDevice->pMgmt, pDevice->byNewChannel);
+					MACvSelectPage1(pDevice->PortOffset);
+					MACvRegBitsOn(pDevice->PortOffset, MAC_REG_MSRCTL+1, MSRCTL1_TXPAUSE);
+					MACvSelectPage0(pDevice->PortOffset);
+					CARDbStartTxPacket(pDevice, PKT_TYPE_802_11_ALL);
+
+				}
+			}
+			if (pDevice->eOPMode == OP_MODE_ADHOC) {
+				//pDevice->bBeaconSent = false;
+			} else {
+				if ((pDevice->bUpdateBBVGA) && (pDevice->bLinkPass == true) && (pDevice->uCurrRSSI != 0)) {
+					long            ldBm;
+
+					RFvRSSITodBm(pDevice, (unsigned char) pDevice->uCurrRSSI, &ldBm);
+					for (ii = 0; ii < BB_VGA_LEVEL; ii++) {
+						if (ldBm < pDevice->ldBmThreshold[ii]) {
+							pDevice->byBBVGANew = pDevice->abyBBVGA[ii];
+							break;
+						}
+					}
+					if (pDevice->byBBVGANew != pDevice->byBBVGACurrent) {
+						pDevice->uBBVGADiffCount++;
+						if (pDevice->uBBVGADiffCount == 1) {
+							// first VGA diff gain
+							BBvSetVGAGainOffset(pDevice, pDevice->byBBVGANew);
+							DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "First RSSI[%d] NewGain[%d] OldGain[%d] Count[%d]\n",
+								(int)ldBm, pDevice->byBBVGANew, pDevice->byBBVGACurrent, (int)pDevice->uBBVGADiffCount);
+						}
+						if (pDevice->uBBVGADiffCount >= BB_VGA_CHANGE_THRESHOLD) {
+							DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "RSSI[%d] NewGain[%d] OldGain[%d] Count[%d]\n",
+								(int)ldBm, pDevice->byBBVGANew, pDevice->byBBVGACurrent, (int)pDevice->uBBVGADiffCount);
+							BBvSetVGAGainOffset(pDevice, pDevice->byBBVGANew);
+						}
+					} else {
+						pDevice->uBBVGADiffCount = 1;
+					}
+				}
+			}
+
+			pDevice->bBeaconSent = false;
+			if (pDevice->bEnablePSMode) {
+				PSbIsNextTBTTWakeUp((void *)pDevice);
+			}
+
+			if ((pDevice->eOPMode == OP_MODE_AP) ||
+			    (pDevice->eOPMode == OP_MODE_ADHOC)) {
+				MACvOneShotTimer1MicroSec(pDevice->PortOffset,
+							  (pMgmt->wIBSSBeaconPeriod - MAKE_BEACON_RESERVED) << 10);
+			}
+
+			if (pDevice->eOPMode == OP_MODE_ADHOC && pDevice->pMgmt->wCurrATIMWindow > 0) {
+				// todo adhoc PS mode
+			}
+
+		}
+
+		if (pDevice->dwIsr & ISR_BNTX) {
+			if (pDevice->eOPMode == OP_MODE_ADHOC) {
+				pDevice->bIsBeaconBufReadySet = false;
+				pDevice->cbBeaconBufReadySetCnt = 0;
+			}
+
+			if (pDevice->eOPMode == OP_MODE_AP) {
+				if (pMgmt->byDTIMCount > 0) {
+					pMgmt->byDTIMCount--;
+					pMgmt->sNodeDBTable[0].bRxPSPoll = false;
+				} else {
+					if (pMgmt->byDTIMCount == 0) {
+						// check if mutltcast tx bufferring
+						pMgmt->byDTIMCount = pMgmt->byDTIMPeriod - 1;
+						pMgmt->sNodeDBTable[0].bRxPSPoll = true;
+						bScheduleCommand((void *)pDevice, WLAN_CMD_RX_PSPOLL, NULL);
+					}
+				}
+			}
+			pDevice->bBeaconSent = true;
+
+			if (pDevice->bChannelSwitch == true) {
+				pDevice->byChannelSwitchCount--;
+				if (pDevice->byChannelSwitchCount == 0) {
+					pDevice->bChannelSwitch = false;
+					set_channel(pDevice, pDevice->byNewChannel);
+					VNTWIFIbChannelSwitch(pDevice->pMgmt, pDevice->byNewChannel);
+					MACvSelectPage1(pDevice->PortOffset);
+					MACvRegBitsOn(pDevice->PortOffset, MAC_REG_MSRCTL+1, MSRCTL1_TXPAUSE);
+					MACvSelectPage0(pDevice->PortOffset);
+					//VNTWIFIbSendBeacon(pDevice->pMgmt);
+					CARDbStartTxPacket(pDevice, PKT_TYPE_802_11_ALL);
+				}
+			}
+
+		}
+
+		if (pDevice->dwIsr & ISR_RXDMA0) {
+			max_count += device_rx_srv(pDevice, TYPE_RXDMA0);
+		}
+		if (pDevice->dwIsr & ISR_RXDMA1) {
+			max_count += device_rx_srv(pDevice, TYPE_RXDMA1);
+		}
+		if (pDevice->dwIsr & ISR_TXDMA0) {
+			max_count += device_tx_srv(pDevice, TYPE_TXDMA0);
+		}
+		if (pDevice->dwIsr & ISR_AC0DMA) {
+			max_count += device_tx_srv(pDevice, TYPE_AC0DMA);
+		}
+		if (pDevice->dwIsr & ISR_SOFTTIMER) {
+		}
+		if (pDevice->dwIsr & ISR_SOFTTIMER1) {
+			if (pDevice->eOPMode == OP_MODE_AP) {
+				if (pDevice->bShortSlotTime)
+					pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SHORTSLOTTIME(1);
+				else
+					pMgmt->wCurrCapInfo &= ~(WLAN_SET_CAP_INFO_SHORTSLOTTIME(1));
+			}
+			bMgrPrepareBeaconToSend(pDevice, pMgmt);
+			pDevice->byCntMeasure = 0;
+		}
+
+		MACvReadISR(pDevice->PortOffset, &pDevice->dwIsr);
 
+		MACvReceive0(pDevice->PortOffset);
+		MACvReceive1(pDevice->PortOffset);
+
+		if (max_count > pDevice->sOpts.int_works)
+			break;
+	}
+
+	if (byOrgPageSel == 1) {
+		MACvSelectPage1(pDevice->PortOffset);
+	}
+
+	spin_unlock_irq(&pDevice->lock);
+	MACvIntEnable(pDevice->PortOffset, IMR_MASK_VALUE);
+
+	return IRQ_RETVAL(handled);
+}
 
 static unsigned const ethernet_polynomial = 0x04c11db7U;
 static inline u32 ether_crc(int length, unsigned char *data)
 {
-    int crc = -1;
-
-    while(--length >= 0) {
-        unsigned char current_octet = *data++;
-        int bit;
-        for (bit = 0; bit < 8; bit++, current_octet >>= 1) {
-            crc = (crc << 1) ^
-                ((crc < 0) ^ (current_octet & 1) ? ethernet_polynomial : 0);
-        }
-    }
-    return crc;
+	int crc = -1;
+
+	while (--length >= 0) {
+		unsigned char current_octet = *data++;
+		int bit;
+		for (bit = 0; bit < 8; bit++, current_octet >>= 1) {
+			crc = (crc << 1) ^
+				((crc < 0) ^ (current_octet & 1) ? ethernet_polynomial : 0);
+		}
+	}
+	return crc;
 }
 
 //2008-8-4 <add> by chester
 static int Config_FileGetParameter(unsigned char *string,
-		unsigned char *dest, unsigned char *source)
+				   unsigned char *dest, unsigned char *source)
 {
-  unsigned char buf1[100];
-  int source_len = strlen(source);
+	unsigned char buf1[100];
+	int source_len = strlen(source);
 
-    memset(buf1,0,100);
-    strcat(buf1, string);
-    strcat(buf1, "=");
-    source+=strlen(buf1);
+	memset(buf1, 0, 100);
+	strcat(buf1, string);
+	strcat(buf1, "=");
+	source += strlen(buf1);
 
-   memcpy(dest,source,source_len-strlen(buf1));
- return true;
+	memcpy(dest, source, source_len - strlen(buf1));
+	return true;
 }
 
-int Config_FileOperation(PSDevice pDevice,bool fwrite,unsigned char *Parameter) {
-    unsigned char *config_path = CONFIG_PATH;
-    unsigned char *buffer = NULL;
-    unsigned char tmpbuffer[20];
-    struct file   *filp=NULL;
-    mm_segment_t old_fs = get_fs();
-    //int oldfsuid=0,oldfsgid=0;
-    int result=0;
-
-    set_fs (KERNEL_DS);
-
-    /* Can't do this anymore, so we rely on correct filesystem permissions:
-    //Make sure a caller can read or write power as root
-    oldfsuid=current->cred->fsuid;
-    oldfsgid=current->cred->fsgid;
-    current->cred->fsuid = 0;
-    current->cred->fsgid = 0;
-    */
-
-    //open file
-      filp = filp_open(config_path, O_RDWR, 0);
-        if (IS_ERR(filp)) {
-	     printk("Config_FileOperation:open file fail?\n");
-	     result=-1;
-             goto error2;
-	  }
-
-     if(!(filp->f_op) || !(filp->f_op->read) ||!(filp->f_op->write)) {
-           printk("file %s cann't readable or writable?\n",config_path);
-	  result = -1;
-	  goto error1;
-     	}
-
-buffer = kmalloc(1024, GFP_KERNEL);
-if(buffer==NULL) {
-  printk("allocate mem for file fail?\n");
-  result = -1;
-  goto error1;
-}
+int Config_FileOperation(PSDevice pDevice, bool fwrite, unsigned char *Parameter) {
+	unsigned char *config_path = CONFIG_PATH;
+	unsigned char *buffer = NULL;
+	unsigned char tmpbuffer[20];
+	struct file   *filp = NULL;
+	mm_segment_t old_fs = get_fs();
+	//int oldfsuid=0,oldfsgid=0;
+	int result = 0;
+
+	set_fs(KERNEL_DS);
+
+	/* Can't do this anymore, so we rely on correct filesystem permissions:
+	//Make sure a caller can read or write power as root
+	oldfsuid=current->cred->fsuid;
+	oldfsgid=current->cred->fsgid;
+	current->cred->fsuid = 0;
+	current->cred->fsgid = 0;
+	*/
+
+	//open file
+	filp = filp_open(config_path, O_RDWR, 0);
+	if (IS_ERR(filp)) {
+		printk("Config_FileOperation:open file fail?\n");
+		result = -1;
+		goto error2;
+	}
 
-if(filp->f_op->read(filp, buffer, 1024, &filp->f_pos)<0) {
- printk("read file error?\n");
- result = -1;
- goto error1;
-}
+	if (!(filp->f_op) || !(filp->f_op->read) || !(filp->f_op->write)) {
+		printk("file %s cann't readable or writable?\n", config_path);
+		result = -1;
+		goto error1;
+	}
 
-if(Config_FileGetParameter("ZONETYPE",tmpbuffer,buffer)!=true) {
-  printk("get parameter error?\n");
-  result = -1;
-  goto error1;
-}
+	buffer = kmalloc(1024, GFP_KERNEL);
+	if (buffer == NULL) {
+		printk("allocate mem for file fail?\n");
+		result = -1;
+		goto error1;
+	}
 
-if(memcmp(tmpbuffer,"USA",3)==0) {
-  result=ZoneType_USA;
-}
-else if(memcmp(tmpbuffer,"JAPAN",5)==0) {
-  result=ZoneType_Japan;
-}
-else if(memcmp(tmpbuffer,"EUROPE",5)==0) {
- result=ZoneType_Europe;
-}
-else {
-  result = -1;
-  printk("Unknown Zonetype[%s]?\n",tmpbuffer);
-}
+	if (filp->f_op->read(filp, buffer, 1024, &filp->f_pos) < 0) {
+		printk("read file error?\n");
+		result = -1;
+		goto error1;
+	}
+
+	if (Config_FileGetParameter("ZONETYPE", tmpbuffer, buffer) != true) {
+		printk("get parameter error?\n");
+		result = -1;
+		goto error1;
+	}
+
+	if (memcmp(tmpbuffer, "USA", 3) == 0) {
+		result = ZoneType_USA;
+	} else if (memcmp(tmpbuffer, "JAPAN", 5) == 0) {
+		result = ZoneType_Japan;
+	} else if (memcmp(tmpbuffer, "EUROPE", 5) == 0) {
+		result = ZoneType_Europe;
+	} else {
+		result = -1;
+		printk("Unknown Zonetype[%s]?\n", tmpbuffer);
+	}
 
 error1:
-  kfree(buffer);
+	kfree(buffer);
 
-  if(filp_close(filp,NULL))
-       printk("Config_FileOperation:close file fail\n");
+	if (filp_close(filp, NULL))
+		printk("Config_FileOperation:close file fail\n");
 
 error2:
-  set_fs (old_fs);
+	set_fs(old_fs);
 
-  /*
-  current->cred->fsuid=oldfsuid;
-  current->cred->fsgid=oldfsgid;
-  */
+	/*
+	  current->cred->fsuid=oldfsuid;
+	  current->cred->fsgid=oldfsgid;
+	*/
 
-  return result;
+	return result;
 }
 
+static void device_set_multi(struct net_device *dev) {
+	PSDevice         pDevice = (PSDevice)netdev_priv(dev);
+
+	PSMgmtObject     pMgmt = pDevice->pMgmt;
+	u32              mc_filter[2];
+	struct netdev_hw_addr *ha;
+
+	VNSvInPortB(pDevice->PortOffset + MAC_REG_RCR, &(pDevice->byRxMode));
+
+	if (dev->flags & IFF_PROMISC) {         /* Set promiscuous. */
+		DBG_PRT(MSG_LEVEL_ERR, KERN_NOTICE "%s: Promiscuous mode enabled.\n", dev->name);
+		/* Unconditionally log net taps. */
+		pDevice->byRxMode |= (RCR_MULTICAST|RCR_BROADCAST|RCR_UNICAST);
+	} else if ((netdev_mc_count(dev) > pDevice->multicast_limit)
+		 ||  (dev->flags & IFF_ALLMULTI)) {
+		MACvSelectPage1(pDevice->PortOffset);
+		VNSvOutPortD(pDevice->PortOffset + MAC_REG_MAR0, 0xffffffff);
+		VNSvOutPortD(pDevice->PortOffset + MAC_REG_MAR0 + 4, 0xffffffff);
+		MACvSelectPage0(pDevice->PortOffset);
+		pDevice->byRxMode |= (RCR_MULTICAST|RCR_BROADCAST);
+	} else {
+		memset(mc_filter, 0, sizeof(mc_filter));
+		netdev_for_each_mc_addr(ha, dev) {
+			int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26;
+			mc_filter[bit_nr >> 5] |= cpu_to_le32(1 << (bit_nr & 31));
+		}
+		MACvSelectPage1(pDevice->PortOffset);
+		VNSvOutPortD(pDevice->PortOffset + MAC_REG_MAR0, mc_filter[0]);
+		VNSvOutPortD(pDevice->PortOffset + MAC_REG_MAR0 + 4, mc_filter[1]);
+		MACvSelectPage0(pDevice->PortOffset);
+		pDevice->byRxMode &= ~(RCR_UNICAST);
+		pDevice->byRxMode |= (RCR_MULTICAST|RCR_BROADCAST);
+	}
 
+	if (pMgmt->eConfigMode == WMAC_CONFIG_AP) {
+		// If AP mode, don't enable RCR_UNICAST. Since hw only compare addr1 with local mac.
+		pDevice->byRxMode |= (RCR_MULTICAST|RCR_BROADCAST);
+		pDevice->byRxMode &= ~(RCR_UNICAST);
+	}
 
-static void device_set_multi(struct net_device *dev) {
-    PSDevice         pDevice = (PSDevice) netdev_priv(dev);
-
-    PSMgmtObject     pMgmt = pDevice->pMgmt;
-    u32              mc_filter[2];
-    struct netdev_hw_addr *ha;
-
-
-    VNSvInPortB(pDevice->PortOffset + MAC_REG_RCR, &(pDevice->byRxMode));
-
-    if (dev->flags & IFF_PROMISC) {         /* Set promiscuous. */
-        DBG_PRT(MSG_LEVEL_ERR,KERN_NOTICE "%s: Promiscuous mode enabled.\n", dev->name);
-        /* Unconditionally log net taps. */
-        pDevice->byRxMode |= (RCR_MULTICAST|RCR_BROADCAST|RCR_UNICAST);
-    }
-    else if ((netdev_mc_count(dev) > pDevice->multicast_limit)
-        ||  (dev->flags & IFF_ALLMULTI)) {
-        MACvSelectPage1(pDevice->PortOffset);
-        VNSvOutPortD(pDevice->PortOffset + MAC_REG_MAR0, 0xffffffff);
-        VNSvOutPortD(pDevice->PortOffset + MAC_REG_MAR0 + 4, 0xffffffff);
-        MACvSelectPage0(pDevice->PortOffset);
-        pDevice->byRxMode |= (RCR_MULTICAST|RCR_BROADCAST);
-    }
-    else {
-        memset(mc_filter, 0, sizeof(mc_filter));
-	netdev_for_each_mc_addr(ha, dev) {
-            int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26;
-            mc_filter[bit_nr >> 5] |= cpu_to_le32(1 << (bit_nr & 31));
-        }
-        MACvSelectPage1(pDevice->PortOffset);
-        VNSvOutPortD(pDevice->PortOffset + MAC_REG_MAR0, mc_filter[0]);
-        VNSvOutPortD(pDevice->PortOffset + MAC_REG_MAR0 + 4, mc_filter[1]);
-        MACvSelectPage0(pDevice->PortOffset);
-        pDevice->byRxMode &= ~(RCR_UNICAST);
-        pDevice->byRxMode |= (RCR_MULTICAST|RCR_BROADCAST);
-    }
-
-    if (pMgmt->eConfigMode == WMAC_CONFIG_AP) {
-        // If AP mode, don't enable RCR_UNICAST. Since hw only compare addr1 with local mac.
-        pDevice->byRxMode |= (RCR_MULTICAST|RCR_BROADCAST);
-        pDevice->byRxMode &= ~(RCR_UNICAST);
-    }
-
-    VNSvOutPortB(pDevice->PortOffset + MAC_REG_RCR, pDevice->byRxMode);
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pDevice->byRxMode = %x\n", pDevice->byRxMode );
+	VNSvOutPortB(pDevice->PortOffset + MAC_REG_RCR, pDevice->byRxMode);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pDevice->byRxMode = %x\n", pDevice->byRxMode);
 }
 
-
 static struct net_device_stats *device_get_stats(struct net_device *dev) {
-    PSDevice pDevice=(PSDevice) netdev_priv(dev);
+	PSDevice pDevice = (PSDevice)netdev_priv(dev);
 
-    return &pDevice->stats;
+	return &pDevice->stats;
 }
 
-
-
 static int  device_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) {
 	PSDevice	        pDevice = (PSDevice)netdev_priv(dev);
 
-	struct iwreq *wrq = (struct iwreq *) rq;
-	int                 rc =0;
-    PSMgmtObject        pMgmt = pDevice->pMgmt;
-    PSCmdRequest        pReq;
+	struct iwreq *wrq = (struct iwreq *)rq;
+	int rc = 0;
+	PSMgmtObject pMgmt = pDevice->pMgmt;
+	PSCmdRequest pReq;
 
+	if (pMgmt == NULL) {
+		rc = -EFAULT;
+		return rc;
+	}
 
-    if (pMgmt == NULL) {
-        rc = -EFAULT;
-        return rc;
-    }
-
-    switch(cmd) {
-
+	switch (cmd) {
 	case SIOCGIWNAME:
 		rc = iwctl_giwname(dev, NULL, (char *)&(wrq->u.name), NULL);
 		break;
@@ -3113,7 +2891,7 @@ static int  device_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) {
 
 		// Set frequency/channel
 	case SIOCSIWFREQ:
-	    rc = iwctl_siwfreq(dev, NULL, &(wrq->u.freq), NULL);
+		rc = iwctl_siwfreq(dev, NULL, &(wrq->u.freq), NULL);
 		break;
 
 		// Get frequency/channel
@@ -3124,60 +2902,57 @@ static int  device_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) {
 		// Set desired network name (ESSID)
 	case SIOCSIWESSID:
 
-		{
-			char essid[IW_ESSID_MAX_SIZE+1];
-			if (wrq->u.essid.length > IW_ESSID_MAX_SIZE) {
-				rc = -E2BIG;
-				break;
-			}
-			if (copy_from_user(essid, wrq->u.essid.pointer,
-					   wrq->u.essid.length)) {
-				rc = -EFAULT;
-				break;
-			}
-			rc = iwctl_siwessid(dev, NULL,
-					    &(wrq->u.essid), essid);
+	{
+		char essid[IW_ESSID_MAX_SIZE+1];
+		if (wrq->u.essid.length > IW_ESSID_MAX_SIZE) {
+			rc = -E2BIG;
+			break;
 		}
-		break;
-
+		if (copy_from_user(essid, wrq->u.essid.pointer,
+				   wrq->u.essid.length)) {
+			rc = -EFAULT;
+			break;
+		}
+		rc = iwctl_siwessid(dev, NULL,
+				    &(wrq->u.essid), essid);
+	}
+	break;
 
-		// Get current network name (ESSID)
+	// Get current network name (ESSID)
 	case SIOCGIWESSID:
 
-		{
-			char essid[IW_ESSID_MAX_SIZE+1];
-			if (wrq->u.essid.pointer)
-				rc = iwctl_giwessid(dev, NULL,
-						    &(wrq->u.essid), essid);
-				if (copy_to_user(wrq->u.essid.pointer,
-						         essid,
-						         wrq->u.essid.length) )
-					rc = -EFAULT;
-		}
-		break;
+	{
+		char essid[IW_ESSID_MAX_SIZE+1];
+		if (wrq->u.essid.pointer)
+			rc = iwctl_giwessid(dev, NULL,
+					    &(wrq->u.essid), essid);
+		if (copy_to_user(wrq->u.essid.pointer,
+				 essid,
+				 wrq->u.essid.length))
+			rc = -EFAULT;
+	}
+	break;
 
 	case SIOCSIWAP:
 
 		rc = iwctl_siwap(dev, NULL, &(wrq->u.ap_addr), NULL);
 		break;
 
-
 		// Get current Access Point (BSSID)
 	case SIOCGIWAP:
 		rc = iwctl_giwap(dev, NULL, &(wrq->u.ap_addr), NULL);
 		break;
 
-
 		// Set desired station name
 	case SIOCSIWNICKN:
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWNICKN \n");
-        rc = -EOPNOTSUPP;
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWNICKN \n");
+		rc = -EOPNOTSUPP;
 		break;
 
 		// Get current station name
 	case SIOCGIWNICKN:
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWNICKN \n");
-        rc = -EOPNOTSUPP;
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWNICKN \n");
+		rc = -EOPNOTSUPP;
 		break;
 
 		// Set the desired bit-rate
@@ -3185,19 +2960,19 @@ static int  device_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) {
 		rc = iwctl_siwrate(dev, NULL, &(wrq->u.bitrate), NULL);
 		break;
 
-	// Get the current bit-rate
+		// Get the current bit-rate
 	case SIOCGIWRATE:
 
 		rc = iwctl_giwrate(dev, NULL, &(wrq->u.bitrate), NULL);
 		break;
 
-	// Set the desired RTS threshold
+		// Set the desired RTS threshold
 	case SIOCSIWRTS:
 
 		rc = iwctl_siwrts(dev, NULL, &(wrq->u.rts), NULL);
 		break;
 
-	// Get the current RTS threshold
+		// Get the current RTS threshold
 	case SIOCGIWRTS:
 
 		rc = iwctl_giwrts(dev, NULL, &(wrq->u.rts), NULL);
@@ -3207,9 +2982,9 @@ static int  device_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) {
 	case SIOCSIWFRAG:
 
 		rc = iwctl_siwfrag(dev, NULL, &(wrq->u.frag), NULL);
-	    break;
+		break;
 
-	// Get the current fragmentation threshold
+		// Get the current fragmentation threshold
 	case SIOCGIWFRAG:
 
 		rc = iwctl_giwfrag(dev, NULL, &(wrq->u.frag), NULL);
@@ -3217,7 +2992,7 @@ static int  device_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) {
 
 		// Set mode of operation
 	case SIOCSIWMODE:
-    	rc = iwctl_siwmode(dev, NULL, &(wrq->u.mode), NULL);
+		rc = iwctl_siwmode(dev, NULL, &(wrq->u.mode), NULL);
 		break;
 
 		// Get mode of operation
@@ -3226,33 +3001,30 @@ static int  device_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) {
 		break;
 
 		// Set WEP keys and mode
-	case SIOCSIWENCODE:
-		{
-            char abyKey[WLAN_WEP232_KEYLEN];
-
-			if (wrq->u.encoding.pointer) {
-
+	case SIOCSIWENCODE: {
+		char abyKey[WLAN_WEP232_KEYLEN];
 
-				if (wrq->u.encoding.length > WLAN_WEP232_KEYLEN) {
-					rc = -E2BIG;
-					break;
-				}
-				memset(abyKey, 0, WLAN_WEP232_KEYLEN);
-				if (copy_from_user(abyKey,
-				                  wrq->u.encoding.pointer,
-				                  wrq->u.encoding.length)) {
-					rc = -EFAULT;
-					break;
-				}
-			} else if (wrq->u.encoding.length != 0) {
-				rc = -EINVAL;
+		if (wrq->u.encoding.pointer) {
+			if (wrq->u.encoding.length > WLAN_WEP232_KEYLEN) {
+				rc = -E2BIG;
 				break;
 			}
-			rc = iwctl_siwencode(dev, NULL, &(wrq->u.encoding), abyKey);
+			memset(abyKey, 0, WLAN_WEP232_KEYLEN);
+			if (copy_from_user(abyKey,
+					   wrq->u.encoding.pointer,
+					   wrq->u.encoding.length)) {
+				rc = -EFAULT;
+				break;
+			}
+		} else if (wrq->u.encoding.length != 0) {
+			rc = -EINVAL;
+			break;
 		}
-		break;
+		rc = iwctl_siwencode(dev, NULL, &(wrq->u.encoding), abyKey);
+	}
+	break;
 
-		// Get the WEP keys and mode
+	// Get the WEP keys and mode
 	case SIOCGIWENCODE:
 
 		if (!capable(CAP_NET_ADMIN)) {
@@ -3260,14 +3032,14 @@ static int  device_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) {
 			break;
 		}
 		{
-		    char abyKey[WLAN_WEP232_KEYLEN];
+			char abyKey[WLAN_WEP232_KEYLEN];
 
-		    rc = iwctl_giwencode(dev, NULL, &(wrq->u.encoding), abyKey);
-		    if (rc != 0) break;
+			rc = iwctl_giwencode(dev, NULL, &(wrq->u.encoding), abyKey);
+			if (rc != 0) break;
 			if (wrq->u.encoding.pointer) {
 				if (copy_to_user(wrq->u.encoding.pointer,
-						        abyKey,
-						        wrq->u.encoding.length))
+						 abyKey,
+						 wrq->u.encoding.length))
 					rc = -EFAULT;
 			}
 		}
@@ -3275,13 +3047,13 @@ static int  device_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) {
 
 		// Get the current Tx-Power
 	case SIOCGIWTXPOW:
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWTXPOW \n");
-        rc = -EOPNOTSUPP;
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWTXPOW \n");
+		rc = -EOPNOTSUPP;
 		break;
 
 	case SIOCSIWTXPOW:
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWTXPOW \n");
-        rc = -EOPNOTSUPP;
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWTXPOW \n");
+		rc = -EOPNOTSUPP;
 		break;
 
 	case SIOCSIWRETRY:
@@ -3297,91 +3069,86 @@ static int  device_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) {
 		// Get range of parameters
 	case SIOCGIWRANGE:
 
-		{
-			struct iw_range range;
+	{
+		struct iw_range range;
 
-			rc = iwctl_giwrange(dev, NULL, &(wrq->u.data), (char *) &range);
-			if (copy_to_user(wrq->u.data.pointer, &range, sizeof(struct iw_range)))
-				rc = -EFAULT;
-		}
+		rc = iwctl_giwrange(dev, NULL, &(wrq->u.data), (char *)&range);
+		if (copy_to_user(wrq->u.data.pointer, &range, sizeof(struct iw_range)))
+			rc = -EFAULT;
+	}
 
-		break;
+	break;
 
 	case SIOCGIWPOWER:
 
 		rc = iwctl_giwpower(dev, NULL, &(wrq->u.power), NULL);
 		break;
 
-
 	case SIOCSIWPOWER:
 
 		rc = iwctl_siwpower(dev, NULL, &(wrq->u.power), NULL);
 		break;
 
-
 	case SIOCGIWSENS:
 
-	    rc = iwctl_giwsens(dev, NULL, &(wrq->u.sens), NULL);
+		rc = iwctl_giwsens(dev, NULL, &(wrq->u.sens), NULL);
 		break;
 
 	case SIOCSIWSENS:
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWSENS \n");
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWSENS \n");
 		rc = -EOPNOTSUPP;
 		break;
 
-	case SIOCGIWAPLIST:
-	    {
-            char buffer[IW_MAX_AP * (sizeof(struct sockaddr) + sizeof(struct iw_quality))];
-
-		    if (wrq->u.data.pointer) {
-		        rc = iwctl_giwaplist(dev, NULL, &(wrq->u.data), buffer);
-		        if (rc == 0) {
-                    if (copy_to_user(wrq->u.data.pointer,
-					                buffer,
-					               (wrq->u.data.length * (sizeof(struct sockaddr) +  sizeof(struct iw_quality)))
-				        ))
-				    rc = -EFAULT;
-		        }
-            }
-        }
-		break;
+	case SIOCGIWAPLIST: {
+		char buffer[IW_MAX_AP * (sizeof(struct sockaddr) + sizeof(struct iw_quality))];
 
+		if (wrq->u.data.pointer) {
+			rc = iwctl_giwaplist(dev, NULL, &(wrq->u.data), buffer);
+			if (rc == 0) {
+				if (copy_to_user(wrq->u.data.pointer,
+						 buffer,
+						 (wrq->u.data.length * (sizeof(struct sockaddr) +  sizeof(struct iw_quality)))
+					    ))
+					rc = -EFAULT;
+			}
+		}
+	}
+	break;
 
 #ifdef WIRELESS_SPY
-		// Set the spy list
+	// Set the spy list
 	case SIOCSIWSPY:
 
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWSPY \n");
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWSPY \n");
 		rc = -EOPNOTSUPP;
 		break;
 
 		// Get the spy list
 	case SIOCGIWSPY:
 
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWSPY \n");
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWSPY \n");
 		rc = -EOPNOTSUPP;
 		break;
 
 #endif // WIRELESS_SPY
 
 	case SIOCGIWPRIV:
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWPRIV \n");
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWPRIV \n");
 		rc = -EOPNOTSUPP;
 /*
-		if(wrq->u.data.pointer) {
-			wrq->u.data.length = sizeof(iwctl_private_args) / sizeof( iwctl_private_args[0]);
+  if (wrq->u.data.pointer) {
+  wrq->u.data.length = sizeof(iwctl_private_args) / sizeof(iwctl_private_args[0]);
 
-			if(copy_to_user(wrq->u.data.pointer,
-					(u_char *) iwctl_private_args,
-					sizeof(iwctl_private_args)))
-				rc = -EFAULT;
-		}
+  if (copy_to_user(wrq->u.data.pointer,
+  (u_char *) iwctl_private_args,
+  sizeof(iwctl_private_args)))
+  rc = -EFAULT;
+  }
 */
 		break;
 
-
 //2008-0409-07, <Add> by Einsn Liu
-#ifdef  WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
+#ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
 	case SIOCSIWAUTH:
 		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWAUTH \n");
 		rc = iwctl_siwauth(dev, NULL, &(wrq->u.param), NULL);
@@ -3402,27 +3169,26 @@ static int  device_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) {
 		rc = iwctl_giwgenie(dev, NULL, &(wrq->u.data), wrq->u.data.pointer);
 		break;
 
-	case SIOCSIWENCODEEXT:
-		{
-			char extra[sizeof(struct iw_encode_ext)+MAX_KEY_LEN+1];
-			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWENCODEEXT \n");
-			if(wrq->u.encoding.pointer){
-				memset(extra, 0, sizeof(struct iw_encode_ext)+MAX_KEY_LEN+1);
-				if(wrq->u.encoding.length > (sizeof(struct iw_encode_ext)+ MAX_KEY_LEN)){
-					rc = -E2BIG;
-					break;
-				}
-				if(copy_from_user(extra, wrq->u.encoding.pointer,wrq->u.encoding.length)){
-					rc = -EFAULT;
-					break;
-				}
-			}else if(wrq->u.encoding.length != 0){
-				rc = -EINVAL;
+	case SIOCSIWENCODEEXT: {
+		char extra[sizeof(struct iw_encode_ext)+MAX_KEY_LEN+1];
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWENCODEEXT \n");
+		if (wrq->u.encoding.pointer) {
+			memset(extra, 0, sizeof(struct iw_encode_ext)+MAX_KEY_LEN + 1);
+			if (wrq->u.encoding.length > (sizeof(struct iw_encode_ext) + MAX_KEY_LEN)) {
+				rc = -E2BIG;
+				break;
+			}
+			if (copy_from_user(extra, wrq->u.encoding.pointer, wrq->u.encoding.length)) {
+				rc = -EFAULT;
 				break;
 			}
-			rc = iwctl_siwencodeext(dev, NULL, &(wrq->u.encoding), extra);
+		} else if (wrq->u.encoding.length != 0) {
+			rc = -EINVAL;
+			break;
 		}
-		break;
+		rc = iwctl_siwencodeext(dev, NULL, &(wrq->u.encoding), extra);
+	}
+	break;
 
 	case SIOCGIWENCODEEXT:
 		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWENCODEEXT \n");
@@ -3437,91 +3203,87 @@ static int  device_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) {
 #endif // #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
 //End Add -- //2008-0409-07, <Add> by Einsn Liu
 
-    case IOCTL_CMD_TEST:
+	case IOCTL_CMD_TEST:
 
 		if (!(pDevice->flags & DEVICE_FLAGS_OPENED)) {
-		    rc = -EFAULT;
-		    break;
-		} else {
-		    rc = 0;
-		}
-        pReq = (PSCmdRequest)rq;
-        pReq->wResult = MAGIC_CODE;
-        break;
-
-    case IOCTL_CMD_SET:
-
-               #ifdef SndEvt_ToAPI
-                  if((((PSCmdRequest)rq)->wCmdCode !=WLAN_CMD_SET_EVT) &&
-		       !(pDevice->flags & DEVICE_FLAGS_OPENED))
-	      #else
-		if (!(pDevice->flags & DEVICE_FLAGS_OPENED) &&
-		       (((PSCmdRequest)rq)->wCmdCode !=WLAN_CMD_SET_WPA))
-	      #endif
-		{
-		    rc = -EFAULT;
-		    break;
+			rc = -EFAULT;
+			break;
 		} else {
-		    rc = 0;
+			rc = 0;
 		}
+		pReq = (PSCmdRequest)rq;
+		pReq->wResult = MAGIC_CODE;
+		break;
 
-	    if (test_and_set_bit( 0, (void*)&(pMgmt->uCmdBusy))) {
-		    return -EBUSY;
-	    }
-        rc = private_ioctl(pDevice, rq);
-        clear_bit( 0, (void*)&(pMgmt->uCmdBusy));
-        break;
+	case IOCTL_CMD_SET:
 
-    case IOCTL_CMD_HOSTAPD:
+#ifdef SndEvt_ToAPI
+		if ((((PSCmdRequest)rq)->wCmdCode != WLAN_CMD_SET_EVT) &&
+		    !(pDevice->flags & DEVICE_FLAGS_OPENED))
+#else
+			if (!(pDevice->flags & DEVICE_FLAGS_OPENED) &&
+			    (((PSCmdRequest)rq)->wCmdCode != WLAN_CMD_SET_WPA))
+#endif
+			{
+				rc = -EFAULT;
+				break;
+			} else {
+				rc = 0;
+			}
 
+		if (test_and_set_bit(0, (void *)&(pMgmt->uCmdBusy))) {
+			return -EBUSY;
+		}
+		rc = private_ioctl(pDevice, rq);
+		clear_bit(0, (void *)&(pMgmt->uCmdBusy));
+		break;
 
-	rc = vt6655_hostap_ioctl(pDevice, &wrq->u.data);
-        break;
+	case IOCTL_CMD_HOSTAPD:
 
-    case IOCTL_CMD_WPA:
+		rc = vt6655_hostap_ioctl(pDevice, &wrq->u.data);
+		break;
 
-	rc = wpa_ioctl(pDevice, &wrq->u.data);
-        break;
+	case IOCTL_CMD_WPA:
+
+		rc = wpa_ioctl(pDevice, &wrq->u.data);
+		break;
 
 	case SIOCETHTOOL:
-        return ethtool_ioctl(dev, (void *) rq->ifr_data);
-	// All other calls are currently unsupported
+		return ethtool_ioctl(dev, (void *)rq->ifr_data);
+		// All other calls are currently unsupported
 
 	default:
 		rc = -EOPNOTSUPP;
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Ioctl command not support..%x\n", cmd);
-
-
-    }
-
-    if (pDevice->bCommit) {
-       if (pMgmt->eConfigMode == WMAC_CONFIG_AP) {
-           netif_stop_queue(pDevice->dev);
-           spin_lock_irq(&pDevice->lock);
-           bScheduleCommand((void *)pDevice, WLAN_CMD_RUN_AP, NULL);
-           spin_unlock_irq(&pDevice->lock);
-       }
-       else {
-           DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Commit the settings\n");
-           spin_lock_irq(&pDevice->lock);
-           pDevice->bLinkPass = false;
-           memset(pMgmt->abyCurrBSSID, 0, 6);
-           pMgmt->eCurrState = WMAC_STATE_IDLE;
-           netif_stop_queue(pDevice->dev);
-	#ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
-	      pMgmt->eScanType = WMAC_SCAN_ACTIVE;
-	 if(pDevice->bWPASuppWextEnabled !=true)
-	 #endif
-           bScheduleCommand((void *) pDevice, WLAN_CMD_BSSID_SCAN, pMgmt->abyDesireSSID);
-           bScheduleCommand((void *) pDevice, WLAN_CMD_SSID, NULL);
-           spin_unlock_irq(&pDevice->lock);
-      }
-      pDevice->bCommit = false;
-    }
-
-    return rc;
-}
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Ioctl command not support..%x\n", cmd);
 
+	}
+
+	if (pDevice->bCommit) {
+		if (pMgmt->eConfigMode == WMAC_CONFIG_AP) {
+			netif_stop_queue(pDevice->dev);
+			spin_lock_irq(&pDevice->lock);
+			bScheduleCommand((void *)pDevice, WLAN_CMD_RUN_AP, NULL);
+			spin_unlock_irq(&pDevice->lock);
+		} else {
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Commit the settings\n");
+			spin_lock_irq(&pDevice->lock);
+			pDevice->bLinkPass = false;
+			memset(pMgmt->abyCurrBSSID, 0, 6);
+			pMgmt->eCurrState = WMAC_STATE_IDLE;
+			netif_stop_queue(pDevice->dev);
+#ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
+			pMgmt->eScanType = WMAC_SCAN_ACTIVE;
+			if (pDevice->bWPASuppWextEnabled != true)
+#endif
+				bScheduleCommand((void *)pDevice, WLAN_CMD_BSSID_SCAN, pMgmt->abyDesireSSID);
+			bScheduleCommand((void *)pDevice, WLAN_CMD_SSID, NULL);
+			spin_unlock_irq(&pDevice->lock);
+		}
+		pDevice->bCommit = false;
+	}
+
+	return rc;
+}
 
 static int ethtool_ioctl(struct net_device *dev, void *useraddr)
 {
@@ -3530,7 +3292,7 @@ static int ethtool_ioctl(struct net_device *dev, void *useraddr)
 	if (copy_from_user(&ethcmd, useraddr, sizeof(ethcmd)))
 		return -EFAULT;
 
-        switch (ethcmd) {
+	switch (ethcmd) {
 	case ETHTOOL_GDRVINFO: {
 		struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO};
 		strncpy(info.driver, DEVICE_NAME, sizeof(info.driver)-1);
@@ -3540,7 +3302,7 @@ static int ethtool_ioctl(struct net_device *dev, void *useraddr)
 		return 0;
 	}
 
-        }
+	}
 
 	return -EOPNOTSUPP;
 }
@@ -3562,122 +3324,111 @@ static struct pci_driver device_driver = {
 
 static int __init vt6655_init_module(void)
 {
-    int ret;
-
+	int ret;
 
 //    ret=pci_module_init(&device_driver);
 	//ret = pcie_port_service_register(&device_driver);
 	ret = pci_register_driver(&device_driver);
 #ifdef CONFIG_PM
-    if(ret >= 0)
-        register_reboot_notifier(&device_notifier);
+	if (ret >= 0)
+		register_reboot_notifier(&device_notifier);
 #endif
 
-    return ret;
+	return ret;
 }
 
 static void __exit vt6655_cleanup_module(void)
 {
-
-
 #ifdef CONFIG_PM
-    unregister_reboot_notifier(&device_notifier);
+	unregister_reboot_notifier(&device_notifier);
 #endif
-    pci_unregister_driver(&device_driver);
-
+	pci_unregister_driver(&device_driver);
 }
 
 module_init(vt6655_init_module);
 module_exit(vt6655_cleanup_module);
 
-
 #ifdef CONFIG_PM
 static int
 device_notify_reboot(struct notifier_block *nb, unsigned long event, void *p)
 {
-    struct pci_dev *pdev = NULL;
-    switch(event) {
-    case SYS_DOWN:
-    case SYS_HALT:
-    case SYS_POWER_OFF:
-	for_each_pci_dev(pdev) {
-            if(pci_dev_driver(pdev) == &device_driver) {
-                if (pci_get_drvdata(pdev))
-                    viawget_suspend(pdev, PMSG_HIBERNATE);
-            }
-        }
-    }
-    return NOTIFY_DONE;
+	struct pci_dev *pdev = NULL;
+	switch (event) {
+	case SYS_DOWN:
+	case SYS_HALT:
+	case SYS_POWER_OFF:
+		for_each_pci_dev(pdev) {
+			if (pci_dev_driver(pdev) == &device_driver) {
+				if (pci_get_drvdata(pdev))
+					viawget_suspend(pdev, PMSG_HIBERNATE);
+			}
+		}
+	}
+	return NOTIFY_DONE;
 }
 
 static int
 viawget_suspend(struct pci_dev *pcid, pm_message_t state)
 {
-    int power_status;   // to silence the compiler
-
-    PSDevice pDevice=pci_get_drvdata(pcid);
-    PSMgmtObject  pMgmt = pDevice->pMgmt;
-
-    netif_stop_queue(pDevice->dev);
-    spin_lock_irq(&pDevice->lock);
-    pci_save_state(pcid);
-    del_timer(&pDevice->sTimerCommand);
-    del_timer(&pMgmt->sTimerSecondCallback);
-    pDevice->cbFreeCmdQueue = CMD_Q_SIZE;
-    pDevice->uCmdDequeueIdx = 0;
-    pDevice->uCmdEnqueueIdx = 0;
-    pDevice->bCmdRunning = false;
-    MACbShutdown(pDevice->PortOffset);
-    MACvSaveContext(pDevice->PortOffset, pDevice->abyMacContext);
-    pDevice->bLinkPass = false;
-    memset(pMgmt->abyCurrBSSID, 0, 6);
-    pMgmt->eCurrState = WMAC_STATE_IDLE;
-    pci_disable_device(pcid);
-    power_status = pci_set_power_state(pcid, pci_choose_state(pcid, state));
-    spin_unlock_irq(&pDevice->lock);
-    return 0;
+	int power_status;   // to silence the compiler
+
+	PSDevice pDevice = pci_get_drvdata(pcid);
+	PSMgmtObject  pMgmt = pDevice->pMgmt;
+
+	netif_stop_queue(pDevice->dev);
+	spin_lock_irq(&pDevice->lock);
+	pci_save_state(pcid);
+	del_timer(&pDevice->sTimerCommand);
+	del_timer(&pMgmt->sTimerSecondCallback);
+	pDevice->cbFreeCmdQueue = CMD_Q_SIZE;
+	pDevice->uCmdDequeueIdx = 0;
+	pDevice->uCmdEnqueueIdx = 0;
+	pDevice->bCmdRunning = false;
+	MACbShutdown(pDevice->PortOffset);
+	MACvSaveContext(pDevice->PortOffset, pDevice->abyMacContext);
+	pDevice->bLinkPass = false;
+	memset(pMgmt->abyCurrBSSID, 0, 6);
+	pMgmt->eCurrState = WMAC_STATE_IDLE;
+	pci_disable_device(pcid);
+	power_status = pci_set_power_state(pcid, pci_choose_state(pcid, state));
+	spin_unlock_irq(&pDevice->lock);
+	return 0;
 }
 
 static int
 viawget_resume(struct pci_dev *pcid)
 {
-    PSDevice  pDevice=pci_get_drvdata(pcid);
-    PSMgmtObject  pMgmt = pDevice->pMgmt;
-    int power_status;   // to silence the compiler
-
-
-    power_status = pci_set_power_state(pcid, 0);
-    power_status = pci_enable_wake(pcid, 0, 0);
-    pci_restore_state(pcid);
-    if (netif_running(pDevice->dev)) {
-        spin_lock_irq(&pDevice->lock);
-        MACvRestoreContext(pDevice->PortOffset, pDevice->abyMacContext);
-        device_init_registers(pDevice, DEVICE_INIT_DXPL);
-        if (pMgmt->sNodeDBTable[0].bActive == true) { // Assoc with BSS
-            pMgmt->sNodeDBTable[0].bActive = false;
-            pDevice->bLinkPass = false;
-            if(pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) {
-                // In Adhoc, BSS state set back to started.
-                pMgmt->eCurrState = WMAC_STATE_STARTED;
-           }
-            else {
-                pMgmt->eCurrMode = WMAC_MODE_STANDBY;
-                pMgmt->eCurrState = WMAC_STATE_IDLE;
-            }
-        }
-        init_timer(&pMgmt->sTimerSecondCallback);
-        init_timer(&pDevice->sTimerCommand);
-        MACvIntEnable(pDevice->PortOffset, IMR_MASK_VALUE);
-        BSSvClearBSSList((void *)pDevice, pDevice->bLinkPass);
-        bScheduleCommand((void *) pDevice, WLAN_CMD_BSSID_SCAN, NULL);
-        bScheduleCommand((void *) pDevice, WLAN_CMD_SSID, NULL);
-        spin_unlock_irq(&pDevice->lock);
-    }
-    return 0;
+	PSDevice  pDevice = pci_get_drvdata(pcid);
+	PSMgmtObject  pMgmt = pDevice->pMgmt;
+	int power_status;   // to silence the compiler
+
+	power_status = pci_set_power_state(pcid, 0);
+	power_status = pci_enable_wake(pcid, 0, 0);
+	pci_restore_state(pcid);
+	if (netif_running(pDevice->dev)) {
+		spin_lock_irq(&pDevice->lock);
+		MACvRestoreContext(pDevice->PortOffset, pDevice->abyMacContext);
+		device_init_registers(pDevice, DEVICE_INIT_DXPL);
+		if (pMgmt->sNodeDBTable[0].bActive == true) { // Assoc with BSS
+			pMgmt->sNodeDBTable[0].bActive = false;
+			pDevice->bLinkPass = false;
+			if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) {
+				// In Adhoc, BSS state set back to started.
+				pMgmt->eCurrState = WMAC_STATE_STARTED;
+			} else {
+				pMgmt->eCurrMode = WMAC_MODE_STANDBY;
+				pMgmt->eCurrState = WMAC_STATE_IDLE;
+			}
+		}
+		init_timer(&pMgmt->sTimerSecondCallback);
+		init_timer(&pDevice->sTimerCommand);
+		MACvIntEnable(pDevice->PortOffset, IMR_MASK_VALUE);
+		BSSvClearBSSList((void *)pDevice, pDevice->bLinkPass);
+		bScheduleCommand((void *)pDevice, WLAN_CMD_BSSID_SCAN, NULL);
+		bScheduleCommand((void *)pDevice, WLAN_CMD_SSID, NULL);
+		spin_unlock_irq(&pDevice->lock);
+	}
+	return 0;
 }
 
 #endif
-
-
-
-
diff --git a/drivers/staging/vt6655/dpc.c b/drivers/staging/vt6655/dpc.c
index 373e9e4..a9533f3 100644
--- a/drivers/staging/vt6655/dpc.c
+++ b/drivers/staging/vt6655/dpc.c
@@ -55,20 +55,17 @@
 #include "iowpa.h"
 #include "aes_ccmp.h"
 
-
-
 /*---------------------  Static Definitions -------------------------*/
 
 /*---------------------  Static Classes  ----------------------------*/
 
 /*---------------------  Static Variables  --------------------------*/
 //static int          msglevel                =MSG_LEVEL_DEBUG;
-static int          msglevel                =MSG_LEVEL_INFO;
+static int msglevel = MSG_LEVEL_INFO;
 
 const unsigned char acbyRxRate[MAX_RATE] =
 {2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108};
 
-
 /*---------------------  Static Functions  --------------------------*/
 
 /*---------------------  Static Definitions -------------------------*/
@@ -77,60 +74,56 @@ const unsigned char acbyRxRate[MAX_RATE] =
 
 static unsigned char s_byGetRateIdx(unsigned char byRate);
 
-
 static void
 s_vGetDASA(unsigned char *pbyRxBufferAddr, unsigned int *pcbHeaderSize,
-		PSEthernetHeader psEthHeader);
+	   PSEthernetHeader psEthHeader);
 
 static void
 s_vProcessRxMACHeader(PSDevice pDevice, unsigned char *pbyRxBufferAddr,
-		unsigned int cbPacketSize, bool bIsWEP, bool bExtIV,
-		unsigned int *pcbHeadSize);
+		      unsigned int cbPacketSize, bool bIsWEP, bool bExtIV,
+		      unsigned int *pcbHeadSize);
 
 static bool s_bAPModeRxCtl(
-    PSDevice pDevice,
-    unsigned char *pbyFrame,
-    int      iSANodeIndex
-    );
-
-
-
-static bool s_bAPModeRxData (
-    PSDevice pDevice,
-    struct sk_buff* skb,
-    unsigned int FrameSize,
-    unsigned int cbHeaderOffset,
-    int      iSANodeIndex,
-    int      iDANodeIndex
-    );
-
+	PSDevice pDevice,
+	unsigned char *pbyFrame,
+	int      iSANodeIndex
+);
+
+static bool s_bAPModeRxData(
+	PSDevice pDevice,
+	struct sk_buff *skb,
+	unsigned int FrameSize,
+	unsigned int cbHeaderOffset,
+	int      iSANodeIndex,
+	int      iDANodeIndex
+);
 
 static bool s_bHandleRxEncryption(
-    PSDevice     pDevice,
-    unsigned char *pbyFrame,
-    unsigned int FrameSize,
-    unsigned char *pbyRsr,
-    unsigned char *pbyNewRsr,
-    PSKeyItem   *pKeyOut,
-    bool *pbExtIV,
-    unsigned short *pwRxTSC15_0,
-    unsigned long *pdwRxTSC47_16
-    );
+	PSDevice     pDevice,
+	unsigned char *pbyFrame,
+	unsigned int FrameSize,
+	unsigned char *pbyRsr,
+	unsigned char *pbyNewRsr,
+	PSKeyItem   *pKeyOut,
+	bool *pbExtIV,
+	unsigned short *pwRxTSC15_0,
+	unsigned long *pdwRxTSC47_16
+);
 
 static bool s_bHostWepRxEncryption(
 
-    PSDevice     pDevice,
-    unsigned char *pbyFrame,
-    unsigned int FrameSize,
-    unsigned char *pbyRsr,
-    bool bOnFly,
-    PSKeyItem    pKey,
-    unsigned char *pbyNewRsr,
-    bool *pbExtIV,
-    unsigned short *pwRxTSC15_0,
-    unsigned long *pdwRxTSC47_16
+	PSDevice     pDevice,
+	unsigned char *pbyFrame,
+	unsigned int FrameSize,
+	unsigned char *pbyRsr,
+	bool bOnFly,
+	PSKeyItem    pKey,
+	unsigned char *pbyNewRsr,
+	bool *pbExtIV,
+	unsigned short *pwRxTSC15_0,
+	unsigned long *pdwRxTSC47_16
 
-    );
+);
 
 /*---------------------  Export Variables  --------------------------*/
 
@@ -150,694 +143,647 @@ static bool s_bHostWepRxEncryption(
  *
  * Return Value: None
  *
--*/
+ -*/
 static void
 s_vProcessRxMACHeader(PSDevice pDevice, unsigned char *pbyRxBufferAddr,
-		unsigned int cbPacketSize, bool bIsWEP, bool bExtIV,
-		unsigned int *pcbHeadSize)
+		      unsigned int cbPacketSize, bool bIsWEP, bool bExtIV,
+		      unsigned int *pcbHeadSize)
 {
-    unsigned char *pbyRxBuffer;
-    unsigned int cbHeaderSize = 0;
-    unsigned short *pwType;
-    PS802_11Header  pMACHeader;
-    int             ii;
-
-
-    pMACHeader = (PS802_11Header) (pbyRxBufferAddr + cbHeaderSize);
-
-    s_vGetDASA((unsigned char *)pMACHeader, &cbHeaderSize, &pDevice->sRxEthHeader);
-
-    if (bIsWEP) {
-        if (bExtIV) {
-            // strip IV&ExtIV , add 8 byte
-            cbHeaderSize += (WLAN_HDR_ADDR3_LEN + 8);
-        } else {
-            // strip IV , add 4 byte
-            cbHeaderSize += (WLAN_HDR_ADDR3_LEN + 4);
-        }
-    }
-    else {
-        cbHeaderSize += WLAN_HDR_ADDR3_LEN;
-    };
-
-    pbyRxBuffer = (unsigned char *) (pbyRxBufferAddr + cbHeaderSize);
-    if (!compare_ether_addr(pbyRxBuffer, &pDevice->abySNAP_Bridgetunnel[0])) {
-        cbHeaderSize += 6;
-    }
-    else if (!compare_ether_addr(pbyRxBuffer, &pDevice->abySNAP_RFC1042[0])) {
-        cbHeaderSize += 6;
-        pwType = (unsigned short *) (pbyRxBufferAddr + cbHeaderSize);
-        if ((*pwType!= TYPE_PKT_IPX) && (*pwType != cpu_to_le16(0xF380))) {
-        }
-        else {
-            cbHeaderSize -= 8;
-            pwType = (unsigned short *) (pbyRxBufferAddr + cbHeaderSize);
-            if (bIsWEP) {
-                if (bExtIV) {
-                    *pwType = htons(cbPacketSize - WLAN_HDR_ADDR3_LEN - 8);    // 8 is IV&ExtIV
-                } else {
-                    *pwType = htons(cbPacketSize - WLAN_HDR_ADDR3_LEN - 4);    // 4 is IV
-                }
-            }
-            else {
-                *pwType = htons(cbPacketSize - WLAN_HDR_ADDR3_LEN);
-            }
-        }
-    }
-    else {
-        cbHeaderSize -= 2;
-        pwType = (unsigned short *) (pbyRxBufferAddr + cbHeaderSize);
-        if (bIsWEP) {
-            if (bExtIV) {
-                *pwType = htons(cbPacketSize - WLAN_HDR_ADDR3_LEN - 8);    // 8 is IV&ExtIV
-            } else {
-                *pwType = htons(cbPacketSize - WLAN_HDR_ADDR3_LEN - 4);    // 4 is IV
-            }
-        }
-        else {
-            *pwType = htons(cbPacketSize - WLAN_HDR_ADDR3_LEN);
-        }
-    }
-
-    cbHeaderSize -= (ETH_ALEN * 2);
-    pbyRxBuffer = (unsigned char *) (pbyRxBufferAddr + cbHeaderSize);
-    for(ii=0;ii<ETH_ALEN;ii++)
-        *pbyRxBuffer++ = pDevice->sRxEthHeader.abyDstAddr[ii];
-    for(ii=0;ii<ETH_ALEN;ii++)
-        *pbyRxBuffer++ = pDevice->sRxEthHeader.abySrcAddr[ii];
-
-    *pcbHeadSize = cbHeaderSize;
-}
-
+	unsigned char *pbyRxBuffer;
+	unsigned int cbHeaderSize = 0;
+	unsigned short *pwType;
+	PS802_11Header  pMACHeader;
+	int             ii;
+
+	pMACHeader = (PS802_11Header) (pbyRxBufferAddr + cbHeaderSize);
+
+	s_vGetDASA((unsigned char *)pMACHeader, &cbHeaderSize, &pDevice->sRxEthHeader);
+
+	if (bIsWEP) {
+		if (bExtIV) {
+			// strip IV&ExtIV , add 8 byte
+			cbHeaderSize += (WLAN_HDR_ADDR3_LEN + 8);
+		} else {
+			// strip IV , add 4 byte
+			cbHeaderSize += (WLAN_HDR_ADDR3_LEN + 4);
+		}
+	} else {
+		cbHeaderSize += WLAN_HDR_ADDR3_LEN;
+	};
+
+	pbyRxBuffer = (unsigned char *)(pbyRxBufferAddr + cbHeaderSize);
+	if (!compare_ether_addr(pbyRxBuffer, &pDevice->abySNAP_Bridgetunnel[0])) {
+		cbHeaderSize += 6;
+	} else if (!compare_ether_addr(pbyRxBuffer, &pDevice->abySNAP_RFC1042[0])) {
+		cbHeaderSize += 6;
+		pwType = (unsigned short *)(pbyRxBufferAddr + cbHeaderSize);
+		if ((*pwType != TYPE_PKT_IPX) && (*pwType != cpu_to_le16(0xF380))) {
+		} else {
+			cbHeaderSize -= 8;
+			pwType = (unsigned short *)(pbyRxBufferAddr + cbHeaderSize);
+			if (bIsWEP) {
+				if (bExtIV) {
+					*pwType = htons(cbPacketSize - WLAN_HDR_ADDR3_LEN - 8);    // 8 is IV&ExtIV
+				} else {
+					*pwType = htons(cbPacketSize - WLAN_HDR_ADDR3_LEN - 4);    // 4 is IV
+				}
+			} else {
+				*pwType = htons(cbPacketSize - WLAN_HDR_ADDR3_LEN);
+			}
+		}
+	} else {
+		cbHeaderSize -= 2;
+		pwType = (unsigned short *)(pbyRxBufferAddr + cbHeaderSize);
+		if (bIsWEP) {
+			if (bExtIV) {
+				*pwType = htons(cbPacketSize - WLAN_HDR_ADDR3_LEN - 8);    // 8 is IV&ExtIV
+			} else {
+				*pwType = htons(cbPacketSize - WLAN_HDR_ADDR3_LEN - 4);    // 4 is IV
+			}
+		} else {
+			*pwType = htons(cbPacketSize - WLAN_HDR_ADDR3_LEN);
+		}
+	}
 
+	cbHeaderSize -= (ETH_ALEN * 2);
+	pbyRxBuffer = (unsigned char *)(pbyRxBufferAddr + cbHeaderSize);
+	for (ii = 0; ii < ETH_ALEN; ii++)
+		*pbyRxBuffer++ = pDevice->sRxEthHeader.abyDstAddr[ii];
+	for (ii = 0; ii < ETH_ALEN; ii++)
+		*pbyRxBuffer++ = pDevice->sRxEthHeader.abySrcAddr[ii];
 
+	*pcbHeadSize = cbHeaderSize;
+}
 
-static unsigned char s_byGetRateIdx (unsigned char byRate)
+static unsigned char s_byGetRateIdx(unsigned char byRate)
 {
-    unsigned char byRateIdx;
+	unsigned char byRateIdx;
 
-    for (byRateIdx = 0; byRateIdx <MAX_RATE ; byRateIdx++) {
-        if (acbyRxRate[byRateIdx%MAX_RATE] == byRate)
-            return byRateIdx;
-    }
-    return 0;
+	for (byRateIdx = 0; byRateIdx < MAX_RATE; byRateIdx++) {
+		if (acbyRxRate[byRateIdx % MAX_RATE] == byRate)
+			return byRateIdx;
+	}
+	return 0;
 }
 
-
 static void
 s_vGetDASA(unsigned char *pbyRxBufferAddr, unsigned int *pcbHeaderSize,
-	PSEthernetHeader psEthHeader)
+	   PSEthernetHeader psEthHeader)
 {
-    unsigned int cbHeaderSize = 0;
-    PS802_11Header  pMACHeader;
-    int             ii;
-
-    pMACHeader = (PS802_11Header) (pbyRxBufferAddr + cbHeaderSize);
-
-    if ((pMACHeader->wFrameCtl & FC_TODS) == 0) {
-        if (pMACHeader->wFrameCtl & FC_FROMDS) {
-            for(ii=0;ii<ETH_ALEN;ii++) {
-                psEthHeader->abyDstAddr[ii] = pMACHeader->abyAddr1[ii];
-                psEthHeader->abySrcAddr[ii] = pMACHeader->abyAddr3[ii];
-            }
-        }
-        else {
-            // IBSS mode
-            for(ii=0;ii<ETH_ALEN;ii++) {
-                psEthHeader->abyDstAddr[ii] = pMACHeader->abyAddr1[ii];
-                psEthHeader->abySrcAddr[ii] = pMACHeader->abyAddr2[ii];
-            }
-        }
-    }
-    else {
-        // Is AP mode..
-        if (pMACHeader->wFrameCtl & FC_FROMDS) {
-            for(ii=0;ii<ETH_ALEN;ii++) {
-                psEthHeader->abyDstAddr[ii] = pMACHeader->abyAddr3[ii];
-                psEthHeader->abySrcAddr[ii] = pMACHeader->abyAddr4[ii];
-                cbHeaderSize += 6;
-            }
-        }
-        else {
-            for(ii=0;ii<ETH_ALEN;ii++) {
-                psEthHeader->abyDstAddr[ii] = pMACHeader->abyAddr3[ii];
-                psEthHeader->abySrcAddr[ii] = pMACHeader->abyAddr2[ii];
-            }
-        }
-    };
-    *pcbHeaderSize = cbHeaderSize;
+	unsigned int cbHeaderSize = 0;
+	PS802_11Header  pMACHeader;
+	int             ii;
+
+	pMACHeader = (PS802_11Header) (pbyRxBufferAddr + cbHeaderSize);
+
+	if ((pMACHeader->wFrameCtl & FC_TODS) == 0) {
+		if (pMACHeader->wFrameCtl & FC_FROMDS) {
+			for (ii = 0; ii < ETH_ALEN; ii++) {
+				psEthHeader->abyDstAddr[ii] = pMACHeader->abyAddr1[ii];
+				psEthHeader->abySrcAddr[ii] = pMACHeader->abyAddr3[ii];
+			}
+		} else {
+			// IBSS mode
+			for (ii = 0; ii < ETH_ALEN; ii++) {
+				psEthHeader->abyDstAddr[ii] = pMACHeader->abyAddr1[ii];
+				psEthHeader->abySrcAddr[ii] = pMACHeader->abyAddr2[ii];
+			}
+		}
+	} else {
+		// Is AP mode..
+		if (pMACHeader->wFrameCtl & FC_FROMDS) {
+			for (ii = 0; ii < ETH_ALEN; ii++) {
+				psEthHeader->abyDstAddr[ii] = pMACHeader->abyAddr3[ii];
+				psEthHeader->abySrcAddr[ii] = pMACHeader->abyAddr4[ii];
+				cbHeaderSize += 6;
+			}
+		} else {
+			for (ii = 0; ii < ETH_ALEN; ii++) {
+				psEthHeader->abyDstAddr[ii] = pMACHeader->abyAddr3[ii];
+				psEthHeader->abySrcAddr[ii] = pMACHeader->abyAddr2[ii];
+			}
+		}
+	};
+	*pcbHeaderSize = cbHeaderSize;
 }
 
-
-
-
 //PLICE_DEBUG ->
 
 void	MngWorkItem(void *Context)
 {
 	PSRxMgmtPacket			pRxMgmtPacket;
 	PSDevice	pDevice =  (PSDevice) Context;
-	//printk("Enter MngWorkItem,Queue packet num is %d\n",pDevice->rxManeQueue.packet_num);
+
 	spin_lock_irq(&pDevice->lock);
-	 while(pDevice->rxManeQueue.packet_num != 0)
-	 {
-		 pRxMgmtPacket =  DeQueue(pDevice);
-        		vMgrRxManagePacket(pDevice, pDevice->pMgmt, pRxMgmtPacket);
+	while (pDevice->rxManeQueue.packet_num != 0) {
+		pRxMgmtPacket =  DeQueue(pDevice);
+		vMgrRxManagePacket(pDevice, pDevice->pMgmt, pRxMgmtPacket);
 	}
 	spin_unlock_irq(&pDevice->lock);
 }
 
-
 //PLICE_DEBUG<-
 
-
-
 bool
-device_receive_frame (
-    PSDevice pDevice,
-    PSRxDesc pCurrRD
-    )
+device_receive_frame(
+	PSDevice pDevice,
+	PSRxDesc pCurrRD
+)
 {
-
-    PDEVICE_RD_INFO  pRDInfo = pCurrRD->pRDInfo;
-#ifdef	PLICE_DEBUG
-	//printk("device_receive_frame:pCurrRD is %x,pRDInfo is %x\n",pCurrRD,pCurrRD->pRDInfo);
-#endif
-    struct net_device_stats* pStats=&pDevice->stats;
-    struct sk_buff* skb;
-    PSMgmtObject    pMgmt = pDevice->pMgmt;
-    PSRxMgmtPacket  pRxPacket = &(pDevice->pMgmt->sRxPacket);
-    PS802_11Header  p802_11Header;
-    unsigned char *pbyRsr;
-    unsigned char *pbyNewRsr;
-    unsigned char *pbyRSSI;
-    PQWORD          pqwTSFTime;
-    unsigned short *pwFrameSize;
-    unsigned char *pbyFrame;
-    bool bDeFragRx = false;
-    bool bIsWEP = false;
-    unsigned int cbHeaderOffset;
-    unsigned int FrameSize;
-    unsigned short wEtherType = 0;
-    int             iSANodeIndex = -1;
-    int             iDANodeIndex = -1;
-    unsigned int ii;
-    unsigned int cbIVOffset;
-    bool bExtIV = false;
-    unsigned char *pbyRxSts;
-    unsigned char *pbyRxRate;
-    unsigned char *pbySQ;
-    unsigned int cbHeaderSize;
-    PSKeyItem       pKey = NULL;
-    unsigned short wRxTSC15_0 = 0;
-    unsigned long dwRxTSC47_16 = 0;
-    SKeyItem        STempKey;
-    // 802.11h RPI
-    unsigned long dwDuration = 0;
-    long            ldBm = 0;
-    long            ldBmThreshold = 0;
-    PS802_11Header pMACHeader;
- bool bRxeapol_key = false;
-
-//    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---------- device_receive_frame---\n");
-
-    skb = pRDInfo->skb;
-
+	PDEVICE_RD_INFO  pRDInfo = pCurrRD->pRDInfo;
+	struct net_device_stats *pStats = &pDevice->stats;
+	struct sk_buff *skb;
+	PSMgmtObject    pMgmt = pDevice->pMgmt;
+	PSRxMgmtPacket  pRxPacket = &(pDevice->pMgmt->sRxPacket);
+	PS802_11Header  p802_11Header;
+	unsigned char *pbyRsr;
+	unsigned char *pbyNewRsr;
+	unsigned char *pbyRSSI;
+	PQWORD          pqwTSFTime;
+	unsigned short *pwFrameSize;
+	unsigned char *pbyFrame;
+	bool bDeFragRx = false;
+	bool bIsWEP = false;
+	unsigned int cbHeaderOffset;
+	unsigned int FrameSize;
+	unsigned short wEtherType = 0;
+	int             iSANodeIndex = -1;
+	int             iDANodeIndex = -1;
+	unsigned int ii;
+	unsigned int cbIVOffset;
+	bool bExtIV = false;
+	unsigned char *pbyRxSts;
+	unsigned char *pbyRxRate;
+	unsigned char *pbySQ;
+	unsigned int cbHeaderSize;
+	PSKeyItem       pKey = NULL;
+	unsigned short wRxTSC15_0 = 0;
+	unsigned long dwRxTSC47_16 = 0;
+	SKeyItem        STempKey;
+	// 802.11h RPI
+	unsigned long dwDuration = 0;
+	long            ldBm = 0;
+	long            ldBmThreshold = 0;
+	PS802_11Header pMACHeader;
+	bool bRxeapol_key = false;
+
+//    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "---------- device_receive_frame---\n");
+
+	skb = pRDInfo->skb;
 
 //PLICE_DEBUG->
 #if 1
 	pci_unmap_single(pDevice->pcid, pRDInfo->skb_dma,
-                     pDevice->rx_buf_sz, PCI_DMA_FROMDEVICE);
+			 pDevice->rx_buf_sz, PCI_DMA_FROMDEVICE);
 #endif
 //PLICE_DEBUG<-
-    pwFrameSize = (unsigned short *)(skb->data + 2);
-    FrameSize = cpu_to_le16(pCurrRD->m_rd1RD1.wReqCount) - cpu_to_le16(pCurrRD->m_rd0RD0.wResCount);
-
-    // Max: 2312Payload + 30HD +4CRC + 2Padding + 4Len + 8TSF + 4RSR
-    // Min (ACK): 10HD +4CRC + 2Padding + 4Len + 8TSF + 4RSR
-    if ((FrameSize > 2364)||(FrameSize <= 32)) {
-        // Frame Size error drop this packet.
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---------- WRONG Length 1 \n");
-        return false;
-    }
-
-    pbyRxSts = (unsigned char *) (skb->data);
-    pbyRxRate = (unsigned char *) (skb->data + 1);
-    pbyRsr = (unsigned char *) (skb->data + FrameSize - 1);
-    pbyRSSI = (unsigned char *) (skb->data + FrameSize - 2);
-    pbyNewRsr = (unsigned char *) (skb->data + FrameSize - 3);
-    pbySQ = (unsigned char *) (skb->data + FrameSize - 4);
-    pqwTSFTime = (PQWORD) (skb->data + FrameSize - 12);
-    pbyFrame = (unsigned char *)(skb->data + 4);
-
-    // get packet size
-    FrameSize = cpu_to_le16(*pwFrameSize);
-
-    if ((FrameSize > 2346)|(FrameSize < 14)) { // Max: 2312Payload + 30HD +4CRC
-                                               // Min: 14 bytes ACK
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---------- WRONG Length 2 \n");
-        return false;
-    }
+	pwFrameSize = (unsigned short *)(skb->data + 2);
+	FrameSize = cpu_to_le16(pCurrRD->m_rd1RD1.wReqCount) - cpu_to_le16(pCurrRD->m_rd0RD0.wResCount);
+
+	// Max: 2312Payload + 30HD +4CRC + 2Padding + 4Len + 8TSF + 4RSR
+	// Min (ACK): 10HD +4CRC + 2Padding + 4Len + 8TSF + 4RSR
+	if ((FrameSize > 2364) || (FrameSize <= 32)) {
+		// Frame Size error drop this packet.
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "---------- WRONG Length 1 \n");
+		return false;
+	}
+
+	pbyRxSts = (unsigned char *)(skb->data);
+	pbyRxRate = (unsigned char *)(skb->data + 1);
+	pbyRsr = (unsigned char *)(skb->data + FrameSize - 1);
+	pbyRSSI = (unsigned char *)(skb->data + FrameSize - 2);
+	pbyNewRsr = (unsigned char *)(skb->data + FrameSize - 3);
+	pbySQ = (unsigned char *)(skb->data + FrameSize - 4);
+	pqwTSFTime = (PQWORD)(skb->data + FrameSize - 12);
+	pbyFrame = (unsigned char *)(skb->data + 4);
+
+	// get packet size
+	FrameSize = cpu_to_le16(*pwFrameSize);
+
+	if ((FrameSize > 2346)|(FrameSize < 14)) { // Max: 2312Payload + 30HD +4CRC
+		// Min: 14 bytes ACK
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "---------- WRONG Length 2 \n");
+		return false;
+	}
 //PLICE_DEBUG->
 #if 1
 	// update receive statistic counter
-    STAvUpdateRDStatCounter(&pDevice->scStatistic,
-                            *pbyRsr,
-                            *pbyNewRsr,
-                            *pbyRxRate,
-                            pbyFrame,
-                            FrameSize);
+	STAvUpdateRDStatCounter(&pDevice->scStatistic,
+				*pbyRsr,
+				*pbyNewRsr,
+				*pbyRxRate,
+				pbyFrame,
+				FrameSize);
 
 #endif
 
-  pMACHeader=(PS802_11Header)((unsigned char *) (skb->data)+8);
+	pMACHeader = (PS802_11Header)((unsigned char *)(skb->data) + 8);
 //PLICE_DEBUG<-
 	if (pDevice->bMeasureInProgress == true) {
-        if ((*pbyRsr & RSR_CRCOK) != 0) {
-            pDevice->byBasicMap |= 0x01;
-        }
-        dwDuration = (FrameSize << 4);
-        dwDuration /= acbyRxRate[*pbyRxRate%MAX_RATE];
-        if (*pbyRxRate <= RATE_11M) {
-            if (*pbyRxSts & 0x01) {
-                // long preamble
-                dwDuration += 192;
-            } else {
-                // short preamble
-                dwDuration += 96;
-            }
-        } else {
-            dwDuration += 16;
-        }
-        RFvRSSITodBm(pDevice, *pbyRSSI, &ldBm);
-        ldBmThreshold = -57;
-        for (ii = 7; ii > 0;) {
-            if (ldBm > ldBmThreshold) {
-                break;
-            }
-            ldBmThreshold -= 5;
-            ii--;
-        }
-        pDevice->dwRPIs[ii] += dwDuration;
-        return false;
-    }
-
-    if (!is_multicast_ether_addr(pbyFrame)) {
-        if (WCTLbIsDuplicate(&(pDevice->sDupRxCache), (PS802_11Header) (skb->data + 4))) {
-            pDevice->s802_11Counter.FrameDuplicateCount++;
-            return false;
-        }
-    }
-
-
-    // Use for TKIP MIC
-    s_vGetDASA(skb->data+4, &cbHeaderSize, &pDevice->sRxEthHeader);
-
-    // filter packet send from myself
-    if (!compare_ether_addr((unsigned char *)&(pDevice->sRxEthHeader.abySrcAddr[0]), pDevice->abyCurrentNetAddr))
-        return false;
-
-    if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) || (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA)) {
-        if (IS_CTL_PSPOLL(pbyFrame) || !IS_TYPE_CONTROL(pbyFrame)) {
-            p802_11Header = (PS802_11Header) (pbyFrame);
-            // get SA NodeIndex
-            if (BSSDBbIsSTAInNodeDB(pMgmt, (unsigned char *)(p802_11Header->abyAddr2), &iSANodeIndex)) {
-                pMgmt->sNodeDBTable[iSANodeIndex].ulLastRxJiffer = jiffies;
-                pMgmt->sNodeDBTable[iSANodeIndex].uInActiveCount = 0;
-            }
-        }
-    }
-
-    if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) {
-        if (s_bAPModeRxCtl(pDevice, pbyFrame, iSANodeIndex) == true) {
-            return false;
-        }
-    }
-
-
-    if (IS_FC_WEP(pbyFrame)) {
-        bool bRxDecryOK = false;
-
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"rx WEP pkt\n");
-        bIsWEP = true;
-        if ((pDevice->bEnableHostWEP) && (iSANodeIndex >= 0)) {
-            pKey = &STempKey;
-            pKey->byCipherSuite = pMgmt->sNodeDBTable[iSANodeIndex].byCipherSuite;
-            pKey->dwKeyIndex = pMgmt->sNodeDBTable[iSANodeIndex].dwKeyIndex;
-            pKey->uKeyLength = pMgmt->sNodeDBTable[iSANodeIndex].uWepKeyLength;
-            pKey->dwTSC47_16 = pMgmt->sNodeDBTable[iSANodeIndex].dwTSC47_16;
-            pKey->wTSC15_0 = pMgmt->sNodeDBTable[iSANodeIndex].wTSC15_0;
-            memcpy(pKey->abyKey,
-                &pMgmt->sNodeDBTable[iSANodeIndex].abyWepKey[0],
-                pKey->uKeyLength
-                );
-
-            bRxDecryOK = s_bHostWepRxEncryption(pDevice,
-                                                pbyFrame,
-                                                FrameSize,
-                                                pbyRsr,
-                                                pMgmt->sNodeDBTable[iSANodeIndex].bOnFly,
-                                                pKey,
-                                                pbyNewRsr,
-                                                &bExtIV,
-                                                &wRxTSC15_0,
-                                                &dwRxTSC47_16);
-        } else {
-            bRxDecryOK = s_bHandleRxEncryption(pDevice,
-                                                pbyFrame,
-                                                FrameSize,
-                                                pbyRsr,
-                                                pbyNewRsr,
-                                                &pKey,
-                                                &bExtIV,
-                                                &wRxTSC15_0,
-                                                &dwRxTSC47_16);
-        }
-
-        if (bRxDecryOK) {
-            if ((*pbyNewRsr & NEWRSR_DECRYPTOK) == 0) {
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ICV Fail\n");
-                if ( (pDevice->pMgmt->eAuthenMode == WMAC_AUTH_WPA) ||
-                    (pDevice->pMgmt->eAuthenMode == WMAC_AUTH_WPAPSK) ||
-                    (pDevice->pMgmt->eAuthenMode == WMAC_AUTH_WPANONE) ||
-                    (pDevice->pMgmt->eAuthenMode == WMAC_AUTH_WPA2) ||
-                    (pDevice->pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK)) {
-
-                    if ((pKey != NULL) && (pKey->byCipherSuite == KEY_CTL_TKIP)) {
-                        pDevice->s802_11Counter.TKIPICVErrors++;
-                    } else if ((pKey != NULL) && (pKey->byCipherSuite == KEY_CTL_CCMP)) {
-                        pDevice->s802_11Counter.CCMPDecryptErrors++;
-                    } else if ((pKey != NULL) && (pKey->byCipherSuite == KEY_CTL_WEP)) {
+		if ((*pbyRsr & RSR_CRCOK) != 0) {
+			pDevice->byBasicMap |= 0x01;
+		}
+		dwDuration = (FrameSize << 4);
+		dwDuration /= acbyRxRate[*pbyRxRate%MAX_RATE];
+		if (*pbyRxRate <= RATE_11M) {
+			if (*pbyRxSts & 0x01) {
+				// long preamble
+				dwDuration += 192;
+			} else {
+				// short preamble
+				dwDuration += 96;
+			}
+		} else {
+			dwDuration += 16;
+		}
+		RFvRSSITodBm(pDevice, *pbyRSSI, &ldBm);
+		ldBmThreshold = -57;
+		for (ii = 7; ii > 0;) {
+			if (ldBm > ldBmThreshold) {
+				break;
+			}
+			ldBmThreshold -= 5;
+			ii--;
+		}
+		pDevice->dwRPIs[ii] += dwDuration;
+		return false;
+	}
+
+	if (!is_multicast_ether_addr(pbyFrame)) {
+		if (WCTLbIsDuplicate(&(pDevice->sDupRxCache), (PS802_11Header)(skb->data + 4))) {
+			pDevice->s802_11Counter.FrameDuplicateCount++;
+			return false;
+		}
+	}
+
+	// Use for TKIP MIC
+	s_vGetDASA(skb->data+4, &cbHeaderSize, &pDevice->sRxEthHeader);
+
+	// filter packet send from myself
+	if (!compare_ether_addr((unsigned char *)&(pDevice->sRxEthHeader.abySrcAddr[0]), pDevice->abyCurrentNetAddr))
+		return false;
+
+	if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) || (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA)) {
+		if (IS_CTL_PSPOLL(pbyFrame) || !IS_TYPE_CONTROL(pbyFrame)) {
+			p802_11Header = (PS802_11Header)(pbyFrame);
+			// get SA NodeIndex
+			if (BSSDBbIsSTAInNodeDB(pMgmt, (unsigned char *)(p802_11Header->abyAddr2), &iSANodeIndex)) {
+				pMgmt->sNodeDBTable[iSANodeIndex].ulLastRxJiffer = jiffies;
+				pMgmt->sNodeDBTable[iSANodeIndex].uInActiveCount = 0;
+			}
+		}
+	}
+
+	if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) {
+		if (s_bAPModeRxCtl(pDevice, pbyFrame, iSANodeIndex) == true) {
+			return false;
+		}
+	}
+
+	if (IS_FC_WEP(pbyFrame)) {
+		bool bRxDecryOK = false;
+
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "rx WEP pkt\n");
+		bIsWEP = true;
+		if ((pDevice->bEnableHostWEP) && (iSANodeIndex >= 0)) {
+			pKey = &STempKey;
+			pKey->byCipherSuite = pMgmt->sNodeDBTable[iSANodeIndex].byCipherSuite;
+			pKey->dwKeyIndex = pMgmt->sNodeDBTable[iSANodeIndex].dwKeyIndex;
+			pKey->uKeyLength = pMgmt->sNodeDBTable[iSANodeIndex].uWepKeyLength;
+			pKey->dwTSC47_16 = pMgmt->sNodeDBTable[iSANodeIndex].dwTSC47_16;
+			pKey->wTSC15_0 = pMgmt->sNodeDBTable[iSANodeIndex].wTSC15_0;
+			memcpy(pKey->abyKey,
+			       &pMgmt->sNodeDBTable[iSANodeIndex].abyWepKey[0],
+			       pKey->uKeyLength
+);
+
+			bRxDecryOK = s_bHostWepRxEncryption(pDevice,
+							    pbyFrame,
+							    FrameSize,
+							    pbyRsr,
+							    pMgmt->sNodeDBTable[iSANodeIndex].bOnFly,
+							    pKey,
+							    pbyNewRsr,
+							    &bExtIV,
+							    &wRxTSC15_0,
+							    &dwRxTSC47_16);
+		} else {
+			bRxDecryOK = s_bHandleRxEncryption(pDevice,
+							   pbyFrame,
+							   FrameSize,
+							   pbyRsr,
+							   pbyNewRsr,
+							   &pKey,
+							   &bExtIV,
+							   &wRxTSC15_0,
+							   &dwRxTSC47_16);
+		}
+
+		if (bRxDecryOK) {
+			if ((*pbyNewRsr & NEWRSR_DECRYPTOK) == 0) {
+				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ICV Fail\n");
+				if ((pDevice->pMgmt->eAuthenMode == WMAC_AUTH_WPA) ||
+				    (pDevice->pMgmt->eAuthenMode == WMAC_AUTH_WPAPSK) ||
+				    (pDevice->pMgmt->eAuthenMode == WMAC_AUTH_WPANONE) ||
+				    (pDevice->pMgmt->eAuthenMode == WMAC_AUTH_WPA2) ||
+				    (pDevice->pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK)) {
+					if ((pKey != NULL) && (pKey->byCipherSuite == KEY_CTL_TKIP)) {
+						pDevice->s802_11Counter.TKIPICVErrors++;
+					} else if ((pKey != NULL) && (pKey->byCipherSuite == KEY_CTL_CCMP)) {
+						pDevice->s802_11Counter.CCMPDecryptErrors++;
+					} else if ((pKey != NULL) && (pKey->byCipherSuite == KEY_CTL_WEP)) {
 //                      pDevice->s802_11Counter.WEPICVErrorCount.QuadPart++;
-                    }
-                }
-                return false;
-            }
-        } else {
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"WEP Func Fail\n");
-            return false;
-        }
-        if ((pKey != NULL) && (pKey->byCipherSuite == KEY_CTL_CCMP))
-            FrameSize -= 8;         // Message Integrity Code
-        else
-            FrameSize -= 4;         // 4 is ICV
-    }
-
-
-    //
-    // RX OK
-    //
-    //remove the CRC length
-    FrameSize -= ETH_FCS_LEN;
-
-    if (( !(*pbyRsr & (RSR_ADDRBROAD | RSR_ADDRMULTI))) && // unicast address
-        (IS_FRAGMENT_PKT((skb->data+4)))
-        ) {
-        // defragment
-        bDeFragRx = WCTLbHandleFragment(pDevice, (PS802_11Header) (skb->data+4), FrameSize, bIsWEP, bExtIV);
-        pDevice->s802_11Counter.ReceivedFragmentCount++;
-        if (bDeFragRx) {
-            // defrag complete
-            skb = pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].skb;
-            FrameSize = pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].cbFrameLength;
-
-        }
-        else {
-            return false;
-        }
-    }
+					}
+				}
+				return false;
+			}
+		} else {
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WEP Func Fail\n");
+			return false;
+		}
+		if ((pKey != NULL) && (pKey->byCipherSuite == KEY_CTL_CCMP))
+			FrameSize -= 8;         // Message Integrity Code
+		else
+			FrameSize -= 4;         // 4 is ICV
+	}
 
+	//
+	// RX OK
+	//
+	//remove the CRC length
+	FrameSize -= ETH_FCS_LEN;
+
+	if ((!(*pbyRsr & (RSR_ADDRBROAD | RSR_ADDRMULTI))) && // unicast address
+	    (IS_FRAGMENT_PKT((skb->data+4)))
+) {
+		// defragment
+		bDeFragRx = WCTLbHandleFragment(pDevice, (PS802_11Header)(skb->data+4), FrameSize, bIsWEP, bExtIV);
+		pDevice->s802_11Counter.ReceivedFragmentCount++;
+		if (bDeFragRx) {
+			// defrag complete
+			skb = pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].skb;
+			FrameSize = pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].cbFrameLength;
+
+		} else {
+			return false;
+		}
+	}
 
 // Management & Control frame Handle
-    if ((IS_TYPE_DATA((skb->data+4))) == false) {
-        // Handle Control & Manage Frame
-
-        if (IS_TYPE_MGMT((skb->data+4))) {
-            unsigned char *pbyData1;
-            unsigned char *pbyData2;
-
-            pRxPacket->p80211Header = (PUWLAN_80211HDR)(skb->data+4);
-            pRxPacket->cbMPDULen = FrameSize;
-            pRxPacket->uRSSI = *pbyRSSI;
-            pRxPacket->bySQ = *pbySQ;
-            HIDWORD(pRxPacket->qwLocalTSF) = cpu_to_le32(HIDWORD(*pqwTSFTime));
-            LODWORD(pRxPacket->qwLocalTSF) = cpu_to_le32(LODWORD(*pqwTSFTime));
-            if (bIsWEP) {
-                // strip IV
-                pbyData1 = WLAN_HDR_A3_DATA_PTR(skb->data+4);
-                pbyData2 = WLAN_HDR_A3_DATA_PTR(skb->data+4) + 4;
-                for (ii = 0; ii < (FrameSize - 4); ii++) {
-                    *pbyData1 = *pbyData2;
-                     pbyData1++;
-                     pbyData2++;
-                }
-            }
-            pRxPacket->byRxRate = s_byGetRateIdx(*pbyRxRate);
-            pRxPacket->byRxChannel = (*pbyRxSts) >> 2;
+	if ((IS_TYPE_DATA((skb->data+4))) == false) {
+		// Handle Control & Manage Frame
+
+		if (IS_TYPE_MGMT((skb->data+4))) {
+			unsigned char *pbyData1;
+			unsigned char *pbyData2;
+
+			pRxPacket->p80211Header = (PUWLAN_80211HDR)(skb->data+4);
+			pRxPacket->cbMPDULen = FrameSize;
+			pRxPacket->uRSSI = *pbyRSSI;
+			pRxPacket->bySQ = *pbySQ;
+			HIDWORD(pRxPacket->qwLocalTSF) = cpu_to_le32(HIDWORD(*pqwTSFTime));
+			LODWORD(pRxPacket->qwLocalTSF) = cpu_to_le32(LODWORD(*pqwTSFTime));
+			if (bIsWEP) {
+				// strip IV
+				pbyData1 = WLAN_HDR_A3_DATA_PTR(skb->data+4);
+				pbyData2 = WLAN_HDR_A3_DATA_PTR(skb->data+4) + 4;
+				for (ii = 0; ii < (FrameSize - 4); ii++) {
+					*pbyData1 = *pbyData2;
+					pbyData1++;
+					pbyData2++;
+				}
+			}
+			pRxPacket->byRxRate = s_byGetRateIdx(*pbyRxRate);
+			pRxPacket->byRxChannel = (*pbyRxSts) >> 2;
 //PLICE_DEBUG->
 //EnQueue(pDevice,pRxPacket);
 
 #ifdef	THREAD
-		EnQueue(pDevice,pRxPacket);
+			EnQueue(pDevice, pRxPacket);
 
-		//printk("enque time is %x\n",jiffies);
-		//up(&pDevice->mlme_semaphore);
+			//up(&pDevice->mlme_semaphore);
 			//Enque (pDevice->FirstRecvMngList,pDevice->LastRecvMngList,pMgmt);
 #else
 
 #ifdef	TASK_LET
-		EnQueue(pDevice,pRxPacket);
-		tasklet_schedule(&pDevice->RxMngWorkItem);
+			EnQueue(pDevice, pRxPacket);
+			tasklet_schedule(&pDevice->RxMngWorkItem);
 #else
-//printk("RxMan\n");
-	vMgrRxManagePacket((void *)pDevice, pDevice->pMgmt, pRxPacket);
-           //tasklet_schedule(&pDevice->RxMngWorkItem);
+			vMgrRxManagePacket((void *)pDevice, pDevice->pMgmt, pRxPacket);
+			//tasklet_schedule(&pDevice->RxMngWorkItem);
 #endif
 
 #endif
 //PLICE_DEBUG<-
 			//vMgrRxManagePacket((void *)pDevice, pDevice->pMgmt, pRxPacket);
-            // hostap Deamon handle 802.11 management
-            if (pDevice->bEnableHostapd) {
-	            skb->dev = pDevice->apdev;
-	            skb->data += 4;
-	            skb->tail += 4;
-                     skb_put(skb, FrameSize);
-		skb_reset_mac_header(skb);
-	            skb->pkt_type = PACKET_OTHERHOST;
-    	        skb->protocol = htons(ETH_P_802_2);
-	            memset(skb->cb, 0, sizeof(skb->cb));
-	            netif_rx(skb);
-                return true;
-	        }
-        }
-        else {
-            // Control Frame
-        };
-        return false;
-    }
-    else {
-        if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) {
-            //In AP mode, hw only check addr1(BSSID or RA) if equal to local MAC.
-            if ( !(*pbyRsr & RSR_BSSIDOK)) {
-                if (bDeFragRx) {
-                    if (!device_alloc_frag_buf(pDevice, &pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx])) {
-                        DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "%s: can not alloc more frag bufs\n",
-                        pDevice->dev->name);
-                    }
-                }
-                return false;
-            }
-        }
-        else {
-            // discard DATA packet while not associate || BSSID error
-            if ((pDevice->bLinkPass == false) ||
-                !(*pbyRsr & RSR_BSSIDOK)) {
-                if (bDeFragRx) {
-                    if (!device_alloc_frag_buf(pDevice, &pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx])) {
-                        DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "%s: can not alloc more frag bufs\n",
-                        pDevice->dev->name);
-                    }
-                }
-                return false;
-            }
-   //mike add:station mode check eapol-key challenge--->
-   	  {
-   	    unsigned char Protocol_Version;    //802.1x Authentication
-	    unsigned char Packet_Type;           //802.1x Authentication
-              if (bIsWEP)
-                  cbIVOffset = 8;
-              else
-                  cbIVOffset = 0;
-              wEtherType = (skb->data[cbIVOffset + 8 + 24 + 6] << 8) |
-                          skb->data[cbIVOffset + 8 + 24 + 6 + 1];
-	      Protocol_Version = skb->data[cbIVOffset + 8 + 24 + 6 + 1 +1];
-	      Packet_Type = skb->data[cbIVOffset + 8 + 24 + 6 + 1 +1+1];
-	     if (wEtherType == ETH_P_PAE) {         //Protocol Type in LLC-Header
-                  if(((Protocol_Version==1) ||(Protocol_Version==2)) &&
-		     (Packet_Type==3)) {  //802.1x OR eapol-key challenge frame receive
-                        bRxeapol_key = true;
-                  }
-	      }
-   	  }
-    //mike add:station mode check eapol-key challenge<---
-        }
-    }
-
+			// hostap Deamon handle 802.11 management
+			if (pDevice->bEnableHostapd) {
+				skb->dev = pDevice->apdev;
+				skb->data += 4;
+				skb->tail += 4;
+				skb_put(skb, FrameSize);
+				skb_reset_mac_header(skb);
+				skb->pkt_type = PACKET_OTHERHOST;
+				skb->protocol = htons(ETH_P_802_2);
+				memset(skb->cb, 0, sizeof(skb->cb));
+				netif_rx(skb);
+				return true;
+			}
+		} else {
+			// Control Frame
+		};
+		return false;
+	} else {
+		if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) {
+			//In AP mode, hw only check addr1(BSSID or RA) if equal to local MAC.
+			if (!(*pbyRsr & RSR_BSSIDOK)) {
+				if (bDeFragRx) {
+					if (!device_alloc_frag_buf(pDevice, &pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx])) {
+						DBG_PRT(MSG_LEVEL_ERR, KERN_ERR "%s: can not alloc more frag bufs\n",
+							pDevice->dev->name);
+					}
+				}
+				return false;
+			}
+		} else {
+			// discard DATA packet while not associate || BSSID error
+			if ((pDevice->bLinkPass == false) ||
+			    !(*pbyRsr & RSR_BSSIDOK)) {
+				if (bDeFragRx) {
+					if (!device_alloc_frag_buf(pDevice, &pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx])) {
+						DBG_PRT(MSG_LEVEL_ERR, KERN_ERR "%s: can not alloc more frag bufs\n",
+							pDevice->dev->name);
+					}
+				}
+				return false;
+			}
+			//mike add:station mode check eapol-key challenge--->
+			{
+				unsigned char Protocol_Version;    //802.1x Authentication
+				unsigned char Packet_Type;           //802.1x Authentication
+				if (bIsWEP)
+					cbIVOffset = 8;
+				else
+					cbIVOffset = 0;
+				wEtherType = (skb->data[cbIVOffset + 8 + 24 + 6] << 8) |
+					skb->data[cbIVOffset + 8 + 24 + 6 + 1];
+				Protocol_Version = skb->data[cbIVOffset + 8 + 24 + 6 + 1 + 1];
+				Packet_Type = skb->data[cbIVOffset + 8 + 24 + 6 + 1 + 1 + 1];
+				if (wEtherType == ETH_P_PAE) {         //Protocol Type in LLC-Header
+					if (((Protocol_Version == 1) || (Protocol_Version == 2)) &&
+					    (Packet_Type == 3)) {  //802.1x OR eapol-key challenge frame receive
+						bRxeapol_key = true;
+					}
+				}
+			}
+			//mike add:station mode check eapol-key challenge<---
+		}
+	}
 
 // Data frame Handle
 
+	if (pDevice->bEnablePSMode) {
+		if (IS_FC_MOREDATA((skb->data+4))) {
+			if (*pbyRsr & RSR_ADDROK) {
+				//PSbSendPSPOLL((PSDevice)pDevice);
+			}
+		} else {
+			if (pDevice->pMgmt->bInTIMWake == true) {
+				pDevice->pMgmt->bInTIMWake = false;
+			}
+		}
+	}
 
-    if (pDevice->bEnablePSMode) {
-        if (IS_FC_MOREDATA((skb->data+4))) {
-            if (*pbyRsr & RSR_ADDROK) {
-                //PSbSendPSPOLL((PSDevice)pDevice);
-            }
-        }
-        else {
-            if (pDevice->pMgmt->bInTIMWake == true) {
-                pDevice->pMgmt->bInTIMWake = false;
-            }
-        }
-    }
-
-    // Now it only supports 802.11g Infrastructure Mode, and support rate must up to 54 Mbps
-    if (pDevice->bDiversityEnable && (FrameSize>50) &&
-        (pDevice->eOPMode == OP_MODE_INFRASTRUCTURE) &&
-        (pDevice->bLinkPass == true)) {
-	//printk("device_receive_frame: RxRate is %d\n",*pbyRxRate);
+	// Now it only supports 802.11g Infrastructure Mode, and support rate must up to 54 Mbps
+	if (pDevice->bDiversityEnable && (FrameSize > 50) &&
+	    (pDevice->eOPMode == OP_MODE_INFRASTRUCTURE) &&
+	    (pDevice->bLinkPass == true)) {
 		BBvAntennaDiversity(pDevice, s_byGetRateIdx(*pbyRxRate), 0);
-    }
-
-
-    if (pDevice->byLocalID != REV_ID_VT3253_B1) {
-        pDevice->uCurrRSSI = *pbyRSSI;
-    }
-    pDevice->byCurrSQ = *pbySQ;
-
-    if ((*pbyRSSI != 0) &&
-        (pMgmt->pCurrBSS!=NULL)) {
-        RFvRSSITodBm(pDevice, *pbyRSSI, &ldBm);
-        // Monitor if RSSI is too strong.
-        pMgmt->pCurrBSS->byRSSIStatCnt++;
-        pMgmt->pCurrBSS->byRSSIStatCnt %= RSSI_STAT_COUNT;
-        pMgmt->pCurrBSS->ldBmAverage[pMgmt->pCurrBSS->byRSSIStatCnt] = ldBm;
-        for(ii=0;ii<RSSI_STAT_COUNT;ii++) {
-            if (pMgmt->pCurrBSS->ldBmAverage[ii] != 0) {
-            pMgmt->pCurrBSS->ldBmMAX = max(pMgmt->pCurrBSS->ldBmAverage[ii], ldBm);
-            }
-        }
-    }
-
-    // -----------------------------------------------
-
-    if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) && (pDevice->bEnable8021x == true)){
-        unsigned char abyMacHdr[24];
-
-        // Only 802.1x packet incoming allowed
-        if (bIsWEP)
-            cbIVOffset = 8;
-        else
-            cbIVOffset = 0;
-        wEtherType = (skb->data[cbIVOffset + 4 + 24 + 6] << 8) |
-                    skb->data[cbIVOffset + 4 + 24 + 6 + 1];
-
-	    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"wEtherType = %04x \n", wEtherType);
-        if (wEtherType == ETH_P_PAE) {
-            skb->dev = pDevice->apdev;
-
-            if (bIsWEP == true) {
-                // strip IV header(8)
-                memcpy(&abyMacHdr[0], (skb->data + 4), 24);
-                memcpy((skb->data + 4 + cbIVOffset), &abyMacHdr[0], 24);
-            }
-            skb->data +=  (cbIVOffset + 4);
-            skb->tail +=  (cbIVOffset + 4);
-            skb_put(skb, FrameSize);
-	    skb_reset_mac_header(skb);
-
-	skb->pkt_type = PACKET_OTHERHOST;
-            skb->protocol = htons(ETH_P_802_2);
-            memset(skb->cb, 0, sizeof(skb->cb));
-            netif_rx(skb);
-            return true;
+	}
 
-}
-        // check if 802.1x authorized
-        if (!(pMgmt->sNodeDBTable[iSANodeIndex].dwFlags & WLAN_STA_AUTHORIZED))
-            return false;
-    }
-
-
-    if ((pKey != NULL) && (pKey->byCipherSuite == KEY_CTL_TKIP)) {
-        if (bIsWEP) {
-            FrameSize -= 8;  //MIC
-        }
-    }
-
-    //--------------------------------------------------------------------------------
-    // Soft MIC
-    if ((pKey != NULL) && (pKey->byCipherSuite == KEY_CTL_TKIP)) {
-        if (bIsWEP) {
-            unsigned long *pdwMIC_L;
-            unsigned long *pdwMIC_R;
-            unsigned long dwMIC_Priority;
-            unsigned long dwMICKey0 = 0, dwMICKey1 = 0;
-            unsigned long dwLocalMIC_L = 0;
-            unsigned long dwLocalMIC_R = 0;
-            viawget_wpa_header *wpahdr;
-
-
-            if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) {
-                dwMICKey0 = cpu_to_le32(*(unsigned long *)(&pKey->abyKey[24]));
-                dwMICKey1 = cpu_to_le32(*(unsigned long *)(&pKey->abyKey[28]));
-            }
-            else {
-                if (pDevice->pMgmt->eAuthenMode == WMAC_AUTH_WPANONE) {
-                    dwMICKey0 = cpu_to_le32(*(unsigned long *)(&pKey->abyKey[16]));
-                    dwMICKey1 = cpu_to_le32(*(unsigned long *)(&pKey->abyKey[20]));
-                } else if ((pKey->dwKeyIndex & BIT28) == 0) {
-                    dwMICKey0 = cpu_to_le32(*(unsigned long *)(&pKey->abyKey[16]));
-                    dwMICKey1 = cpu_to_le32(*(unsigned long *)(&pKey->abyKey[20]));
-                } else {
-                    dwMICKey0 = cpu_to_le32(*(unsigned long *)(&pKey->abyKey[24]));
-                    dwMICKey1 = cpu_to_le32(*(unsigned long *)(&pKey->abyKey[28]));
-                }
-            }
-
-            MIC_vInit(dwMICKey0, dwMICKey1);
-            MIC_vAppend((unsigned char *)&(pDevice->sRxEthHeader.abyDstAddr[0]), 12);
-            dwMIC_Priority = 0;
-            MIC_vAppend((unsigned char *)&dwMIC_Priority, 4);
-            // 4 is Rcv buffer header, 24 is MAC Header, and 8 is IV and Ext IV.
-            MIC_vAppend((unsigned char *)(skb->data + 4 + WLAN_HDR_ADDR3_LEN + 8),
-                        FrameSize - WLAN_HDR_ADDR3_LEN - 8);
-            MIC_vGetMIC(&dwLocalMIC_L, &dwLocalMIC_R);
-            MIC_vUnInit();
-
-            pdwMIC_L = (unsigned long *)(skb->data + 4 + FrameSize);
-            pdwMIC_R = (unsigned long *)(skb->data + 4 + FrameSize + 4);
-            //DBG_PRN_GRP12(("RxL: %lx, RxR: %lx\n", *pdwMIC_L, *pdwMIC_R));
-            //DBG_PRN_GRP12(("LocalL: %lx, LocalR: %lx\n", dwLocalMIC_L, dwLocalMIC_R));
-            //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"dwMICKey0= %lx,dwMICKey1= %lx \n", dwMICKey0, dwMICKey1);
-
-
-            if ((cpu_to_le32(*pdwMIC_L) != dwLocalMIC_L) || (cpu_to_le32(*pdwMIC_R) != dwLocalMIC_R) ||
-                (pDevice->bRxMICFail == true)) {
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MIC comparison is fail!\n");
-                pDevice->bRxMICFail = false;
-                //pDevice->s802_11Counter.TKIPLocalMICFailures.QuadPart++;
-                pDevice->s802_11Counter.TKIPLocalMICFailures++;
-                if (bDeFragRx) {
-                    if (!device_alloc_frag_buf(pDevice, &pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx])) {
-                        DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "%s: can not alloc more frag bufs\n",
-                            pDevice->dev->name);
-                    }
-                }
-               //2008-0409-07, <Add> by Einsn Liu
-       #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
+	if (pDevice->byLocalID != REV_ID_VT3253_B1) {
+		pDevice->uCurrRSSI = *pbyRSSI;
+	}
+	pDevice->byCurrSQ = *pbySQ;
+
+	if ((*pbyRSSI != 0) &&
+	    (pMgmt->pCurrBSS != NULL)) {
+		RFvRSSITodBm(pDevice, *pbyRSSI, &ldBm);
+		// Monitor if RSSI is too strong.
+		pMgmt->pCurrBSS->byRSSIStatCnt++;
+		pMgmt->pCurrBSS->byRSSIStatCnt %= RSSI_STAT_COUNT;
+		pMgmt->pCurrBSS->ldBmAverage[pMgmt->pCurrBSS->byRSSIStatCnt] = ldBm;
+		for (ii = 0; ii < RSSI_STAT_COUNT; ii++) {
+			if (pMgmt->pCurrBSS->ldBmAverage[ii] != 0) {
+				pMgmt->pCurrBSS->ldBmMAX = max(pMgmt->pCurrBSS->ldBmAverage[ii], ldBm);
+			}
+		}
+	}
+
+	// -----------------------------------------------
+
+	if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) && (pDevice->bEnable8021x == true)) {
+		unsigned char abyMacHdr[24];
+
+		// Only 802.1x packet incoming allowed
+		if (bIsWEP)
+			cbIVOffset = 8;
+		else
+			cbIVOffset = 0;
+		wEtherType = (skb->data[cbIVOffset + 4 + 24 + 6] << 8) |
+			skb->data[cbIVOffset + 4 + 24 + 6 + 1];
+
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wEtherType = %04x \n", wEtherType);
+		if (wEtherType == ETH_P_PAE) {
+			skb->dev = pDevice->apdev;
+
+			if (bIsWEP == true) {
+				// strip IV header(8)
+				memcpy(&abyMacHdr[0], (skb->data + 4), 24);
+				memcpy((skb->data + 4 + cbIVOffset), &abyMacHdr[0], 24);
+			}
+			skb->data +=  (cbIVOffset + 4);
+			skb->tail +=  (cbIVOffset + 4);
+			skb_put(skb, FrameSize);
+			skb_reset_mac_header(skb);
+
+			skb->pkt_type = PACKET_OTHERHOST;
+			skb->protocol = htons(ETH_P_802_2);
+			memset(skb->cb, 0, sizeof(skb->cb));
+			netif_rx(skb);
+			return true;
+
+		}
+		// check if 802.1x authorized
+		if (!(pMgmt->sNodeDBTable[iSANodeIndex].dwFlags & WLAN_STA_AUTHORIZED))
+			return false;
+	}
+
+	if ((pKey != NULL) && (pKey->byCipherSuite == KEY_CTL_TKIP)) {
+		if (bIsWEP) {
+			FrameSize -= 8;  //MIC
+		}
+	}
+
+	//--------------------------------------------------------------------------------
+	// Soft MIC
+	if ((pKey != NULL) && (pKey->byCipherSuite == KEY_CTL_TKIP)) {
+		if (bIsWEP) {
+			unsigned long *pdwMIC_L;
+			unsigned long *pdwMIC_R;
+			unsigned long dwMIC_Priority;
+			unsigned long dwMICKey0 = 0, dwMICKey1 = 0;
+			unsigned long dwLocalMIC_L = 0;
+			unsigned long dwLocalMIC_R = 0;
+			viawget_wpa_header *wpahdr;
+
+			if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) {
+				dwMICKey0 = cpu_to_le32(*(unsigned long *)(&pKey->abyKey[24]));
+				dwMICKey1 = cpu_to_le32(*(unsigned long *)(&pKey->abyKey[28]));
+			} else {
+				if (pDevice->pMgmt->eAuthenMode == WMAC_AUTH_WPANONE) {
+					dwMICKey0 = cpu_to_le32(*(unsigned long *)(&pKey->abyKey[16]));
+					dwMICKey1 = cpu_to_le32(*(unsigned long *)(&pKey->abyKey[20]));
+				} else if ((pKey->dwKeyIndex & BIT28) == 0) {
+					dwMICKey0 = cpu_to_le32(*(unsigned long *)(&pKey->abyKey[16]));
+					dwMICKey1 = cpu_to_le32(*(unsigned long *)(&pKey->abyKey[20]));
+				} else {
+					dwMICKey0 = cpu_to_le32(*(unsigned long *)(&pKey->abyKey[24]));
+					dwMICKey1 = cpu_to_le32(*(unsigned long *)(&pKey->abyKey[28]));
+				}
+			}
+
+			MIC_vInit(dwMICKey0, dwMICKey1);
+			MIC_vAppend((unsigned char *)&(pDevice->sRxEthHeader.abyDstAddr[0]), 12);
+			dwMIC_Priority = 0;
+			MIC_vAppend((unsigned char *)&dwMIC_Priority, 4);
+			// 4 is Rcv buffer header, 24 is MAC Header, and 8 is IV and Ext IV.
+			MIC_vAppend((unsigned char *)(skb->data + 4 + WLAN_HDR_ADDR3_LEN + 8),
+				    FrameSize - WLAN_HDR_ADDR3_LEN - 8);
+			MIC_vGetMIC(&dwLocalMIC_L, &dwLocalMIC_R);
+			MIC_vUnInit();
+
+			pdwMIC_L = (unsigned long *)(skb->data + 4 + FrameSize);
+			pdwMIC_R = (unsigned long *)(skb->data + 4 + FrameSize + 4);
+			//DBG_PRN_GRP12(("RxL: %lx, RxR: %lx\n", *pdwMIC_L, *pdwMIC_R));
+			//DBG_PRN_GRP12(("LocalL: %lx, LocalR: %lx\n", dwLocalMIC_L, dwLocalMIC_R));
+			//DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dwMICKey0= %lx,dwMICKey1= %lx \n", dwMICKey0, dwMICKey1);
+
+			if ((cpu_to_le32(*pdwMIC_L) != dwLocalMIC_L) || (cpu_to_le32(*pdwMIC_R) != dwLocalMIC_R) ||
+			    (pDevice->bRxMICFail == true)) {
+				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "MIC comparison is fail!\n");
+				pDevice->bRxMICFail = false;
+				//pDevice->s802_11Counter.TKIPLocalMICFailures.QuadPart++;
+				pDevice->s802_11Counter.TKIPLocalMICFailures++;
+				if (bDeFragRx) {
+					if (!device_alloc_frag_buf(pDevice, &pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx])) {
+						DBG_PRT(MSG_LEVEL_ERR, KERN_ERR "%s: can not alloc more frag bufs\n",
+							pDevice->dev->name);
+					}
+				}
+				//2008-0409-07, <Add> by Einsn Liu
+#ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
 				//send event to wpa_supplicant
-				//if(pDevice->bWPADevEnable == true)
 				{
 					union iwreq_data wrqu;
 					struct iw_michaelmicfailure ev;
@@ -845,8 +791,8 @@ device_receive_frame (
 					memset(&ev, 0, sizeof(ev));
 					ev.flags = keyidx & IW_MICFAILURE_KEY_ID;
 					if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) &&
-							(pMgmt->eCurrState == WMAC_STATE_ASSOC) &&
-								(*pbyRsr & (RSR_ADDRBROAD | RSR_ADDRMULTI)) == 0) {
+					    (pMgmt->eCurrState == WMAC_STATE_ASSOC) &&
+					    (*pbyRsr & (RSR_ADDRBROAD | RSR_ADDRMULTI)) == 0) {
 						ev.flags |= IW_MICFAILURE_PAIRWISE;
 					} else {
 						ev.flags |= IW_MICFAILURE_GROUP;
@@ -859,633 +805,596 @@ device_receive_frame (
 					wireless_send_event(pDevice->dev, IWEVMICHAELMICFAILURE, &wrqu, (char *)&ev);
 
 				}
-         #endif
-
-
-                if ((pDevice->bWPADEVUp) && (pDevice->skb != NULL)) {
-                     wpahdr = (viawget_wpa_header *)pDevice->skb->data;
-                     if ((pDevice->pMgmt->eCurrMode == WMAC_MODE_ESS_STA) &&
-                         (pDevice->pMgmt->eCurrState == WMAC_STATE_ASSOC) &&
-                         (*pbyRsr & (RSR_ADDRBROAD | RSR_ADDRMULTI)) == 0) {
-                         //s802_11_Status.Flags = NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR;
-                         wpahdr->type = VIAWGET_PTK_MIC_MSG;
-                     } else {
-                         //s802_11_Status.Flags = NDIS_802_11_AUTH_REQUEST_GROUP_ERROR;
-                         wpahdr->type = VIAWGET_GTK_MIC_MSG;
-                     }
-                     wpahdr->resp_ie_len = 0;
-                     wpahdr->req_ie_len = 0;
-                     skb_put(pDevice->skb, sizeof(viawget_wpa_header));
-                     pDevice->skb->dev = pDevice->wpadev;
-		     skb_reset_mac_header(pDevice->skb);
-                     pDevice->skb->pkt_type = PACKET_HOST;
-                     pDevice->skb->protocol = htons(ETH_P_802_2);
-                     memset(pDevice->skb->cb, 0, sizeof(pDevice->skb->cb));
-                     netif_rx(pDevice->skb);
-                     pDevice->skb = dev_alloc_skb((int)pDevice->rx_buf_sz);
-                 }
-
-                return false;
-
-            }
-        }
-    } //---end of SOFT MIC-----------------------------------------------------------------------
-
-    // ++++++++++ Reply Counter Check +++++++++++++
-
-    if ((pKey != NULL) && ((pKey->byCipherSuite == KEY_CTL_TKIP) ||
-                           (pKey->byCipherSuite == KEY_CTL_CCMP))) {
-        if (bIsWEP) {
-            unsigned short wLocalTSC15_0 = 0;
-            unsigned long dwLocalTSC47_16 = 0;
-            unsigned long long       RSC = 0;
-            // endian issues
-            RSC = *((unsigned long long *) &(pKey->KeyRSC));
-            wLocalTSC15_0 = (unsigned short) RSC;
-            dwLocalTSC47_16 = (unsigned long) (RSC>>16);
-
-            RSC = dwRxTSC47_16;
-            RSC <<= 16;
-            RSC += wRxTSC15_0;
-            memcpy(&(pKey->KeyRSC), &RSC,  sizeof(QWORD));
-
-            if ( (pDevice->sMgmtObj.eCurrMode == WMAC_MODE_ESS_STA) &&
-                 (pDevice->sMgmtObj.eCurrState == WMAC_STATE_ASSOC)) {
-                // check RSC
-                if ( (wRxTSC15_0 < wLocalTSC15_0) &&
-                     (dwRxTSC47_16 <= dwLocalTSC47_16) &&
-                     !((dwRxTSC47_16 == 0) && (dwLocalTSC47_16 == 0xFFFFFFFF))) {
-                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"TSC is illegal~~!\n ");
-                    if (pKey->byCipherSuite == KEY_CTL_TKIP)
-                        //pDevice->s802_11Counter.TKIPReplays.QuadPart++;
-                        pDevice->s802_11Counter.TKIPReplays++;
-                    else
-                        //pDevice->s802_11Counter.CCMPReplays.QuadPart++;
-                        pDevice->s802_11Counter.CCMPReplays++;
-
-                    if (bDeFragRx) {
-                        if (!device_alloc_frag_buf(pDevice, &pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx])) {
-                            DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "%s: can not alloc more frag bufs\n",
-                                pDevice->dev->name);
-                        }
-                    }
-                    return false;
-                }
-            }
-        }
-    } // ----- End of Reply Counter Check --------------------------
-
-
-
-    if ((pKey != NULL) && (bIsWEP)) {
+#endif
+
+				if ((pDevice->bWPADEVUp) && (pDevice->skb != NULL)) {
+					wpahdr = (viawget_wpa_header *)pDevice->skb->data;
+					if ((pDevice->pMgmt->eCurrMode == WMAC_MODE_ESS_STA) &&
+					    (pDevice->pMgmt->eCurrState == WMAC_STATE_ASSOC) &&
+					    (*pbyRsr & (RSR_ADDRBROAD | RSR_ADDRMULTI)) == 0) {
+						//s802_11_Status.Flags = NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR;
+						wpahdr->type = VIAWGET_PTK_MIC_MSG;
+					} else {
+						//s802_11_Status.Flags = NDIS_802_11_AUTH_REQUEST_GROUP_ERROR;
+						wpahdr->type = VIAWGET_GTK_MIC_MSG;
+					}
+					wpahdr->resp_ie_len = 0;
+					wpahdr->req_ie_len = 0;
+					skb_put(pDevice->skb, sizeof(viawget_wpa_header));
+					pDevice->skb->dev = pDevice->wpadev;
+					skb_reset_mac_header(pDevice->skb);
+					pDevice->skb->pkt_type = PACKET_HOST;
+					pDevice->skb->protocol = htons(ETH_P_802_2);
+					memset(pDevice->skb->cb, 0, sizeof(pDevice->skb->cb));
+					netif_rx(pDevice->skb);
+					pDevice->skb = dev_alloc_skb((int)pDevice->rx_buf_sz);
+				}
+
+				return false;
+
+			}
+		}
+	} //---end of SOFT MIC-----------------------------------------------------------------------
+
+	// ++++++++++ Reply Counter Check +++++++++++++
+
+	if ((pKey != NULL) && ((pKey->byCipherSuite == KEY_CTL_TKIP) ||
+			       (pKey->byCipherSuite == KEY_CTL_CCMP))) {
+		if (bIsWEP) {
+			unsigned short wLocalTSC15_0 = 0;
+			unsigned long dwLocalTSC47_16 = 0;
+			unsigned long long       RSC = 0;
+			// endian issues
+			RSC = *((unsigned long long *)&(pKey->KeyRSC));
+			wLocalTSC15_0 = (unsigned short)RSC;
+			dwLocalTSC47_16 = (unsigned long)(RSC>>16);
+
+			RSC = dwRxTSC47_16;
+			RSC <<= 16;
+			RSC += wRxTSC15_0;
+			memcpy(&(pKey->KeyRSC), &RSC,  sizeof(QWORD));
+
+			if ((pDevice->sMgmtObj.eCurrMode == WMAC_MODE_ESS_STA) &&
+			    (pDevice->sMgmtObj.eCurrState == WMAC_STATE_ASSOC)) {
+				// check RSC
+				if ((wRxTSC15_0 < wLocalTSC15_0) &&
+				    (dwRxTSC47_16 <= dwLocalTSC47_16) &&
+				    !((dwRxTSC47_16 == 0) && (dwLocalTSC47_16 == 0xFFFFFFFF))) {
+					DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "TSC is illegal~~!\n ");
+					if (pKey->byCipherSuite == KEY_CTL_TKIP)
+						//pDevice->s802_11Counter.TKIPReplays.QuadPart++;
+						pDevice->s802_11Counter.TKIPReplays++;
+					else
+						//pDevice->s802_11Counter.CCMPReplays.QuadPart++;
+						pDevice->s802_11Counter.CCMPReplays++;
+
+					if (bDeFragRx) {
+						if (!device_alloc_frag_buf(pDevice, &pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx])) {
+							DBG_PRT(MSG_LEVEL_ERR, KERN_ERR "%s: can not alloc more frag bufs\n",
+								pDevice->dev->name);
+						}
+					}
+					return false;
+				}
+			}
+		}
+	} // ----- End of Reply Counter Check --------------------------
+
+	if ((pKey != NULL) && (bIsWEP)) {
 //      pDevice->s802_11Counter.DecryptSuccessCount.QuadPart++;
-    }
-
-
-    s_vProcessRxMACHeader(pDevice, (unsigned char *)(skb->data+4), FrameSize, bIsWEP, bExtIV, &cbHeaderOffset);
-    FrameSize -= cbHeaderOffset;
-    cbHeaderOffset += 4;        // 4 is Rcv buffer header
-
-    // Null data, framesize = 14
-    if (FrameSize < 15)
-        return false;
-
-    if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) {
-        if (s_bAPModeRxData(pDevice,
-                            skb,
-                            FrameSize,
-                            cbHeaderOffset,
-                            iSANodeIndex,
-                            iDANodeIndex
-                            ) == false) {
-
-            if (bDeFragRx) {
-                if (!device_alloc_frag_buf(pDevice, &pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx])) {
-                    DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "%s: can not alloc more frag bufs\n",
-                    pDevice->dev->name);
-                }
-            }
-            return false;
-        }
-
-//        if(pDevice->bRxMICFail == false) {
-//           for (ii =0; ii < 100; ii++)
-//                printk(" %02x", *(skb->data + ii));
-//           printk("\n");
-//	    }
-
-    }
+	}
+
+	s_vProcessRxMACHeader(pDevice, (unsigned char *)(skb->data+4), FrameSize, bIsWEP, bExtIV, &cbHeaderOffset);
+	FrameSize -= cbHeaderOffset;
+	cbHeaderOffset += 4;        // 4 is Rcv buffer header
+
+	// Null data, framesize = 14
+	if (FrameSize < 15)
+		return false;
+
+	if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) {
+		if (s_bAPModeRxData(pDevice,
+				    skb,
+				    FrameSize,
+				    cbHeaderOffset,
+				    iSANodeIndex,
+				    iDANodeIndex
+) == false) {
+			if (bDeFragRx) {
+				if (!device_alloc_frag_buf(pDevice, &pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx])) {
+					DBG_PRT(MSG_LEVEL_ERR, KERN_ERR "%s: can not alloc more frag bufs\n",
+						pDevice->dev->name);
+				}
+			}
+			return false;
+		}
+	}
 
 	skb->data += cbHeaderOffset;
 	skb->tail += cbHeaderOffset;
-    skb_put(skb, FrameSize);
-    skb->protocol=eth_type_trans(skb, skb->dev);
-
+	skb_put(skb, FrameSize);
+	skb->protocol = eth_type_trans(skb, skb->dev);
 
 	//drop frame not met IEEE 802.3
 /*
-	if (pDevice->flags & DEVICE_FLAGS_VAL_PKT_LEN) {
-		if ((skb->protocol==htons(ETH_P_802_3)) &&
-			(skb->len!=htons(skb->mac.ethernet->h_proto))) {
-			pStats->rx_length_errors++;
-			pStats->rx_dropped++;
-            if (bDeFragRx) {
-                if (!device_alloc_frag_buf(pDevice, &pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx])) {
-                    DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "%s: can not alloc more frag bufs\n",
-                    pDevice->dev->name);
-                }
-            }
-			return false;
-		}
-	}
+  if (pDevice->flags & DEVICE_FLAGS_VAL_PKT_LEN) {
+  if ((skb->protocol==htons(ETH_P_802_3)) &&
+  (skb->len!=htons(skb->mac.ethernet->h_proto))) {
+  pStats->rx_length_errors++;
+  pStats->rx_dropped++;
+  if (bDeFragRx) {
+  if (!device_alloc_frag_buf(pDevice, &pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx])) {
+  DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "%s: can not alloc more frag bufs\n",
+  pDevice->dev->name);
+  }
+  }
+  return false;
+  }
+  }
 */
 
-    skb->ip_summed=CHECKSUM_NONE;
-    pStats->rx_bytes +=skb->len;
-    pStats->rx_packets++;
-    netif_rx(skb);
+	skb->ip_summed = CHECKSUM_NONE;
+	pStats->rx_bytes += skb->len;
+	pStats->rx_packets++;
+	netif_rx(skb);
 
-    if (bDeFragRx) {
-        if (!device_alloc_frag_buf(pDevice, &pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx])) {
-            DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "%s: can not alloc more frag bufs\n",
-                pDevice->dev->name);
-        }
-        return false;
-    }
+	if (bDeFragRx) {
+		if (!device_alloc_frag_buf(pDevice, &pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx])) {
+			DBG_PRT(MSG_LEVEL_ERR, KERN_ERR "%s: can not alloc more frag bufs\n",
+				pDevice->dev->name);
+		}
+		return false;
+	}
 
-    return true;
+	return true;
 }
 
-
-static bool s_bAPModeRxCtl (
-    PSDevice pDevice,
-    unsigned char *pbyFrame,
-    int      iSANodeIndex
-    )
+static bool s_bAPModeRxCtl(
+	PSDevice pDevice,
+	unsigned char *pbyFrame,
+	int      iSANodeIndex
+)
 {
-    PS802_11Header      p802_11Header;
-    CMD_STATUS          Status;
-    PSMgmtObject        pMgmt = pDevice->pMgmt;
-
-
-    if (IS_CTL_PSPOLL(pbyFrame) || !IS_TYPE_CONTROL(pbyFrame)) {
-
-        p802_11Header = (PS802_11Header) (pbyFrame);
-        if (!IS_TYPE_MGMT(pbyFrame)) {
-
-            // Data & PS-Poll packet
-            // check frame class
-            if (iSANodeIndex > 0) {
-                // frame class 3 fliter & checking
-                if (pMgmt->sNodeDBTable[iSANodeIndex].eNodeState < NODE_AUTH) {
-                    // send deauth notification
-                    // reason = (6) class 2 received from nonauth sta
-                    vMgrDeAuthenBeginSta(pDevice,
-                                         pMgmt,
-                                         (unsigned char *)(p802_11Header->abyAddr2),
-                                         (WLAN_MGMT_REASON_CLASS2_NONAUTH),
-                                         &Status
-                                         );
-                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dpc: send vMgrDeAuthenBeginSta 1\n");
-                    return true;
-                }
-                if (pMgmt->sNodeDBTable[iSANodeIndex].eNodeState < NODE_ASSOC) {
-                    // send deassoc notification
-                    // reason = (7) class 3 received from nonassoc sta
-                    vMgrDisassocBeginSta(pDevice,
-                                         pMgmt,
-                                         (unsigned char *)(p802_11Header->abyAddr2),
-                                         (WLAN_MGMT_REASON_CLASS3_NONASSOC),
-                                         &Status
-                                         );
-                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dpc: send vMgrDisassocBeginSta 2\n");
-                    return true;
-                }
-
-                if (pMgmt->sNodeDBTable[iSANodeIndex].bPSEnable) {
-                    // delcare received ps-poll event
-                    if (IS_CTL_PSPOLL(pbyFrame)) {
-                        pMgmt->sNodeDBTable[iSANodeIndex].bRxPSPoll = true;
-                        bScheduleCommand((void *)pDevice, WLAN_CMD_RX_PSPOLL, NULL);
-                        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dpc: WLAN_CMD_RX_PSPOLL 1\n");
-                    }
-                    else {
-                        // check Data PS state
-                        // if PW bit off, send out all PS bufferring packets.
-                        if (!IS_FC_POWERMGT(pbyFrame)) {
-                            pMgmt->sNodeDBTable[iSANodeIndex].bPSEnable = false;
-                            pMgmt->sNodeDBTable[iSANodeIndex].bRxPSPoll = true;
-                            bScheduleCommand((void *)pDevice, WLAN_CMD_RX_PSPOLL, NULL);
-                            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dpc: WLAN_CMD_RX_PSPOLL 2\n");
-                        }
-                    }
-                }
-                else {
-                   if (IS_FC_POWERMGT(pbyFrame)) {
-                       pMgmt->sNodeDBTable[iSANodeIndex].bPSEnable = true;
-                       // Once if STA in PS state, enable multicast bufferring
-                       pMgmt->sNodeDBTable[0].bPSEnable = true;
-                   }
-                   else {
-                      // clear all pending PS frame.
-                      if (pMgmt->sNodeDBTable[iSANodeIndex].wEnQueueCnt > 0) {
-                          pMgmt->sNodeDBTable[iSANodeIndex].bPSEnable = false;
-                          pMgmt->sNodeDBTable[iSANodeIndex].bRxPSPoll = true;
-                          bScheduleCommand((void *)pDevice, WLAN_CMD_RX_PSPOLL, NULL);
-                         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dpc: WLAN_CMD_RX_PSPOLL 3\n");
-
-                      }
-                   }
-                }
-            }
-            else {
-                  vMgrDeAuthenBeginSta(pDevice,
-                                       pMgmt,
-                                       (unsigned char *)(p802_11Header->abyAddr2),
-                                       (WLAN_MGMT_REASON_CLASS2_NONAUTH),
-                                       &Status
-                                       );
-                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dpc: send vMgrDeAuthenBeginSta 3\n");
-			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "BSSID:%pM\n",
-				p802_11Header->abyAddr3);
-			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ADDR2:%pM\n",
-				p802_11Header->abyAddr2);
-			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ADDR1:%pM\n",
-				p802_11Header->abyAddr1);
-                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dpc: wFrameCtl= %x\n", p802_11Header->wFrameCtl );
-                    VNSvInPortB(pDevice->PortOffset + MAC_REG_RCR, &(pDevice->byRxMode));
-                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dpc:pDevice->byRxMode = %x\n", pDevice->byRxMode );
-                    return true;
-            }
-        }
-    }
-    return false;
+	PS802_11Header      p802_11Header;
+	CMD_STATUS          Status;
+	PSMgmtObject        pMgmt = pDevice->pMgmt;
+
+	if (IS_CTL_PSPOLL(pbyFrame) || !IS_TYPE_CONTROL(pbyFrame)) {
+		p802_11Header = (PS802_11Header)(pbyFrame);
+		if (!IS_TYPE_MGMT(pbyFrame)) {
+			// Data & PS-Poll packet
+			// check frame class
+			if (iSANodeIndex > 0) {
+				// frame class 3 fliter & checking
+				if (pMgmt->sNodeDBTable[iSANodeIndex].eNodeState < NODE_AUTH) {
+					// send deauth notification
+					// reason = (6) class 2 received from nonauth sta
+					vMgrDeAuthenBeginSta(pDevice,
+							     pMgmt,
+							     (unsigned char *)(p802_11Header->abyAddr2),
+							     (WLAN_MGMT_REASON_CLASS2_NONAUTH),
+							     &Status
+);
+					DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dpc: send vMgrDeAuthenBeginSta 1\n");
+					return true;
+				}
+				if (pMgmt->sNodeDBTable[iSANodeIndex].eNodeState < NODE_ASSOC) {
+					// send deassoc notification
+					// reason = (7) class 3 received from nonassoc sta
+					vMgrDisassocBeginSta(pDevice,
+							     pMgmt,
+							     (unsigned char *)(p802_11Header->abyAddr2),
+							     (WLAN_MGMT_REASON_CLASS3_NONASSOC),
+							     &Status
+);
+					DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dpc: send vMgrDisassocBeginSta 2\n");
+					return true;
+				}
 
+				if (pMgmt->sNodeDBTable[iSANodeIndex].bPSEnable) {
+					// delcare received ps-poll event
+					if (IS_CTL_PSPOLL(pbyFrame)) {
+						pMgmt->sNodeDBTable[iSANodeIndex].bRxPSPoll = true;
+						bScheduleCommand((void *)pDevice, WLAN_CMD_RX_PSPOLL, NULL);
+						DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dpc: WLAN_CMD_RX_PSPOLL 1\n");
+					} else {
+						// check Data PS state
+						// if PW bit off, send out all PS bufferring packets.
+						if (!IS_FC_POWERMGT(pbyFrame)) {
+							pMgmt->sNodeDBTable[iSANodeIndex].bPSEnable = false;
+							pMgmt->sNodeDBTable[iSANodeIndex].bRxPSPoll = true;
+							bScheduleCommand((void *)pDevice, WLAN_CMD_RX_PSPOLL, NULL);
+							DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dpc: WLAN_CMD_RX_PSPOLL 2\n");
+						}
+					}
+				} else {
+					if (IS_FC_POWERMGT(pbyFrame)) {
+						pMgmt->sNodeDBTable[iSANodeIndex].bPSEnable = true;
+						// Once if STA in PS state, enable multicast bufferring
+						pMgmt->sNodeDBTable[0].bPSEnable = true;
+					} else {
+						// clear all pending PS frame.
+						if (pMgmt->sNodeDBTable[iSANodeIndex].wEnQueueCnt > 0) {
+							pMgmt->sNodeDBTable[iSANodeIndex].bPSEnable = false;
+							pMgmt->sNodeDBTable[iSANodeIndex].bRxPSPoll = true;
+							bScheduleCommand((void *)pDevice, WLAN_CMD_RX_PSPOLL, NULL);
+							DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dpc: WLAN_CMD_RX_PSPOLL 3\n");
+
+						}
+					}
+				}
+			} else {
+				vMgrDeAuthenBeginSta(pDevice,
+						     pMgmt,
+						     (unsigned char *)(p802_11Header->abyAddr2),
+						     (WLAN_MGMT_REASON_CLASS2_NONAUTH),
+						     &Status
+);
+				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dpc: send vMgrDeAuthenBeginSta 3\n");
+				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "BSSID:%pM\n",
+					p802_11Header->abyAddr3);
+				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ADDR2:%pM\n",
+					p802_11Header->abyAddr2);
+				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ADDR1:%pM\n",
+					p802_11Header->abyAddr1);
+				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dpc: wFrameCtl= %x\n", p802_11Header->wFrameCtl);
+				VNSvInPortB(pDevice->PortOffset + MAC_REG_RCR, &(pDevice->byRxMode));
+				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dpc:pDevice->byRxMode = %x\n", pDevice->byRxMode);
+				return true;
+			}
+		}
+	}
+	return false;
 }
 
-static bool s_bHandleRxEncryption (
-    PSDevice     pDevice,
-    unsigned char *pbyFrame,
-    unsigned int FrameSize,
-    unsigned char *pbyRsr,
-    unsigned char *pbyNewRsr,
-    PSKeyItem   *pKeyOut,
-    bool *pbExtIV,
-    unsigned short *pwRxTSC15_0,
-    unsigned long *pdwRxTSC47_16
-    )
+static bool s_bHandleRxEncryption(
+	PSDevice     pDevice,
+	unsigned char *pbyFrame,
+	unsigned int FrameSize,
+	unsigned char *pbyRsr,
+	unsigned char *pbyNewRsr,
+	PSKeyItem   *pKeyOut,
+	bool *pbExtIV,
+	unsigned short *pwRxTSC15_0,
+	unsigned long *pdwRxTSC47_16
+)
 {
-    unsigned int PayloadLen = FrameSize;
-    unsigned char *pbyIV;
-    unsigned char byKeyIdx;
-    PSKeyItem       pKey = NULL;
-    unsigned char byDecMode = KEY_CTL_WEP;
-    PSMgmtObject    pMgmt = pDevice->pMgmt;
-
-
-    *pwRxTSC15_0 = 0;
-    *pdwRxTSC47_16 = 0;
-
-    pbyIV = pbyFrame + WLAN_HDR_ADDR3_LEN;
-    if ( WLAN_GET_FC_TODS(*(unsigned short *)pbyFrame) &&
-         WLAN_GET_FC_FROMDS(*(unsigned short *)pbyFrame) ) {
-         pbyIV += 6;             // 6 is 802.11 address4
-         PayloadLen -= 6;
-    }
-    byKeyIdx = (*(pbyIV+3) & 0xc0);
-    byKeyIdx >>= 6;
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\nKeyIdx: %d\n", byKeyIdx);
-
-    if ((pMgmt->eAuthenMode == WMAC_AUTH_WPA) ||
-        (pMgmt->eAuthenMode == WMAC_AUTH_WPAPSK) ||
-        (pMgmt->eAuthenMode == WMAC_AUTH_WPANONE) ||
-        (pMgmt->eAuthenMode == WMAC_AUTH_WPA2) ||
-        (pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK)) {
-        if (((*pbyRsr & (RSR_ADDRBROAD | RSR_ADDRMULTI)) == 0) &&
-            (pDevice->pMgmt->byCSSPK != KEY_CTL_NONE)) {
-            // unicast pkt use pairwise key
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"unicast pkt\n");
-            if (KeybGetKey(&(pDevice->sKey), pDevice->abyBSSID, 0xFFFFFFFF, &pKey) == true) {
-                if (pDevice->pMgmt->byCSSPK == KEY_CTL_TKIP)
-                    byDecMode = KEY_CTL_TKIP;
-                else if (pDevice->pMgmt->byCSSPK == KEY_CTL_CCMP)
-                    byDecMode = KEY_CTL_CCMP;
-            }
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"unicast pkt: %d, %p\n", byDecMode, pKey);
-        } else {
-            // use group key
-            KeybGetKey(&(pDevice->sKey), pDevice->abyBSSID, byKeyIdx, &pKey);
-            if (pDevice->pMgmt->byCSSGK == KEY_CTL_TKIP)
-                byDecMode = KEY_CTL_TKIP;
-            else if (pDevice->pMgmt->byCSSGK == KEY_CTL_CCMP)
-                byDecMode = KEY_CTL_CCMP;
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"group pkt: %d, %d, %p\n", byKeyIdx, byDecMode, pKey);
-        }
-    }
-    // our WEP only support Default Key
-    if (pKey == NULL) {
-        // use default group key
-        KeybGetKey(&(pDevice->sKey), pDevice->abyBroadcastAddr, byKeyIdx, &pKey);
-        if (pDevice->pMgmt->byCSSGK == KEY_CTL_TKIP)
-            byDecMode = KEY_CTL_TKIP;
-        else if (pDevice->pMgmt->byCSSGK == KEY_CTL_CCMP)
-            byDecMode = KEY_CTL_CCMP;
-    }
-    *pKeyOut = pKey;
-
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"AES:%d %d %d\n", pDevice->pMgmt->byCSSPK, pDevice->pMgmt->byCSSGK, byDecMode);
-
-    if (pKey == NULL) {
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey == NULL\n");
-        if (byDecMode == KEY_CTL_WEP) {
+	unsigned int PayloadLen = FrameSize;
+	unsigned char *pbyIV;
+	unsigned char byKeyIdx;
+	PSKeyItem       pKey = NULL;
+	unsigned char byDecMode = KEY_CTL_WEP;
+	PSMgmtObject    pMgmt = pDevice->pMgmt;
+
+	*pwRxTSC15_0 = 0;
+	*pdwRxTSC47_16 = 0;
+
+	pbyIV = pbyFrame + WLAN_HDR_ADDR3_LEN;
+	if (WLAN_GET_FC_TODS(*(unsigned short *)pbyFrame) &&
+	    WLAN_GET_FC_FROMDS(*(unsigned short *)pbyFrame)) {
+		pbyIV += 6;             // 6 is 802.11 address4
+		PayloadLen -= 6;
+	}
+	byKeyIdx = (*(pbyIV+3) & 0xc0);
+	byKeyIdx >>= 6;
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "\nKeyIdx: %d\n", byKeyIdx);
+
+	if ((pMgmt->eAuthenMode == WMAC_AUTH_WPA) ||
+	    (pMgmt->eAuthenMode == WMAC_AUTH_WPAPSK) ||
+	    (pMgmt->eAuthenMode == WMAC_AUTH_WPANONE) ||
+	    (pMgmt->eAuthenMode == WMAC_AUTH_WPA2) ||
+	    (pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK)) {
+		if (((*pbyRsr & (RSR_ADDRBROAD | RSR_ADDRMULTI)) == 0) &&
+		    (pDevice->pMgmt->byCSSPK != KEY_CTL_NONE)) {
+			// unicast pkt use pairwise key
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "unicast pkt\n");
+			if (KeybGetKey(&(pDevice->sKey), pDevice->abyBSSID, 0xFFFFFFFF, &pKey) == true) {
+				if (pDevice->pMgmt->byCSSPK == KEY_CTL_TKIP)
+					byDecMode = KEY_CTL_TKIP;
+				else if (pDevice->pMgmt->byCSSPK == KEY_CTL_CCMP)
+					byDecMode = KEY_CTL_CCMP;
+			}
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "unicast pkt: %d, %p\n", byDecMode, pKey);
+		} else {
+			// use group key
+			KeybGetKey(&(pDevice->sKey), pDevice->abyBSSID, byKeyIdx, &pKey);
+			if (pDevice->pMgmt->byCSSGK == KEY_CTL_TKIP)
+				byDecMode = KEY_CTL_TKIP;
+			else if (pDevice->pMgmt->byCSSGK == KEY_CTL_CCMP)
+				byDecMode = KEY_CTL_CCMP;
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "group pkt: %d, %d, %p\n", byKeyIdx, byDecMode, pKey);
+		}
+	}
+	// our WEP only support Default Key
+	if (pKey == NULL) {
+		// use default group key
+		KeybGetKey(&(pDevice->sKey), pDevice->abyBroadcastAddr, byKeyIdx, &pKey);
+		if (pDevice->pMgmt->byCSSGK == KEY_CTL_TKIP)
+			byDecMode = KEY_CTL_TKIP;
+		else if (pDevice->pMgmt->byCSSGK == KEY_CTL_CCMP)
+			byDecMode = KEY_CTL_CCMP;
+	}
+	*pKeyOut = pKey;
+
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "AES:%d %d %d\n", pDevice->pMgmt->byCSSPK, pDevice->pMgmt->byCSSGK, byDecMode);
+
+	if (pKey == NULL) {
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey == NULL\n");
+		if (byDecMode == KEY_CTL_WEP) {
 //            pDevice->s802_11Counter.WEPUndecryptableCount.QuadPart++;
-        } else if (pDevice->bLinkPass == true) {
+		} else if (pDevice->bLinkPass == true) {
 //            pDevice->s802_11Counter.DecryptFailureCount.QuadPart++;
-        }
-        return false;
-    }
-    if (byDecMode != pKey->byCipherSuite) {
-        if (byDecMode == KEY_CTL_WEP) {
+		}
+		return false;
+	}
+	if (byDecMode != pKey->byCipherSuite) {
+		if (byDecMode == KEY_CTL_WEP) {
 //            pDevice->s802_11Counter.WEPUndecryptableCount.QuadPart++;
-        } else if (pDevice->bLinkPass == true) {
+		} else if (pDevice->bLinkPass == true) {
 //            pDevice->s802_11Counter.DecryptFailureCount.QuadPart++;
-        }
-        *pKeyOut = NULL;
-        return false;
-    }
-    if (byDecMode == KEY_CTL_WEP) {
-        // handle WEP
-        if ((pDevice->byLocalID <= REV_ID_VT3253_A1) ||
-            (((PSKeyTable)(pKey->pvKeyTable))->bSoftWEP == true)) {
-            // Software WEP
-            // 1. 3253A
-            // 2. WEP 256
-
-            PayloadLen -= (WLAN_HDR_ADDR3_LEN + 4 + 4); // 24 is 802.11 header,4 is IV, 4 is crc
-            memcpy(pDevice->abyPRNG, pbyIV, 3);
-            memcpy(pDevice->abyPRNG + 3, pKey->abyKey, pKey->uKeyLength);
-            rc4_init(&pDevice->SBox, pDevice->abyPRNG, pKey->uKeyLength + 3);
-            rc4_encrypt(&pDevice->SBox, pbyIV+4, pbyIV+4, PayloadLen);
-
-            if (ETHbIsBufferCrc32Ok(pbyIV+4, PayloadLen)) {
-                *pbyNewRsr |= NEWRSR_DECRYPTOK;
-            }
-        }
-    } else if ((byDecMode == KEY_CTL_TKIP) ||
-               (byDecMode == KEY_CTL_CCMP)) {
-        // TKIP/AES
-
-        PayloadLen -= (WLAN_HDR_ADDR3_LEN + 8 + 4); // 24 is 802.11 header, 8 is IV&ExtIV, 4 is crc
-        *pdwRxTSC47_16 = cpu_to_le32(*(unsigned long *)(pbyIV + 4));
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ExtIV: %lx\n",*pdwRxTSC47_16);
-        if (byDecMode == KEY_CTL_TKIP) {
-            *pwRxTSC15_0 = cpu_to_le16(MAKEWORD(*(pbyIV+2), *pbyIV));
-        } else {
-            *pwRxTSC15_0 = cpu_to_le16(*(unsigned short *)pbyIV);
-        }
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"TSC0_15: %x\n", *pwRxTSC15_0);
-
-        if ((byDecMode == KEY_CTL_TKIP) &&
-            (pDevice->byLocalID <= REV_ID_VT3253_A1)) {
-            // Software TKIP
-            // 1. 3253 A
-            PS802_11Header  pMACHeader = (PS802_11Header) (pbyFrame);
-            TKIPvMixKey(pKey->abyKey, pMACHeader->abyAddr2, *pwRxTSC15_0, *pdwRxTSC47_16, pDevice->abyPRNG);
-            rc4_init(&pDevice->SBox, pDevice->abyPRNG, TKIP_KEY_LEN);
-            rc4_encrypt(&pDevice->SBox, pbyIV+8, pbyIV+8, PayloadLen);
-            if (ETHbIsBufferCrc32Ok(pbyIV+8, PayloadLen)) {
-                *pbyNewRsr |= NEWRSR_DECRYPTOK;
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ICV OK!\n");
-            } else {
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ICV FAIL!!!\n");
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"PayloadLen = %d\n", PayloadLen);
-            }
-        }
-    }// end of TKIP/AES
-
-    if ((*(pbyIV+3) & 0x20) != 0)
-        *pbExtIV = true;
-    return true;
-}
+		}
+		*pKeyOut = NULL;
+		return false;
+	}
+	if (byDecMode == KEY_CTL_WEP) {
+		// handle WEP
+		if ((pDevice->byLocalID <= REV_ID_VT3253_A1) ||
+		    (((PSKeyTable)(pKey->pvKeyTable))->bSoftWEP == true)) {
+			// Software WEP
+			// 1. 3253A
+			// 2. WEP 256
+
+			PayloadLen -= (WLAN_HDR_ADDR3_LEN + 4 + 4); // 24 is 802.11 header,4 is IV, 4 is crc
+			memcpy(pDevice->abyPRNG, pbyIV, 3);
+			memcpy(pDevice->abyPRNG + 3, pKey->abyKey, pKey->uKeyLength);
+			rc4_init(&pDevice->SBox, pDevice->abyPRNG, pKey->uKeyLength + 3);
+			rc4_encrypt(&pDevice->SBox, pbyIV+4, pbyIV+4, PayloadLen);
+
+			if (ETHbIsBufferCrc32Ok(pbyIV+4, PayloadLen)) {
+				*pbyNewRsr |= NEWRSR_DECRYPTOK;
+			}
+		}
+	} else if ((byDecMode == KEY_CTL_TKIP) ||
+		   (byDecMode == KEY_CTL_CCMP)) {
+		// TKIP/AES
+
+		PayloadLen -= (WLAN_HDR_ADDR3_LEN + 8 + 4); // 24 is 802.11 header, 8 is IV&ExtIV, 4 is crc
+		*pdwRxTSC47_16 = cpu_to_le32(*(unsigned long *)(pbyIV + 4));
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ExtIV: %lx\n", *pdwRxTSC47_16);
+		if (byDecMode == KEY_CTL_TKIP) {
+			*pwRxTSC15_0 = cpu_to_le16(MAKEWORD(*(pbyIV + 2), *pbyIV));
+		} else {
+			*pwRxTSC15_0 = cpu_to_le16(*(unsigned short *)pbyIV);
+		}
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "TSC0_15: %x\n", *pwRxTSC15_0);
+
+		if ((byDecMode == KEY_CTL_TKIP) &&
+		    (pDevice->byLocalID <= REV_ID_VT3253_A1)) {
+			// Software TKIP
+			// 1. 3253 A
+			PS802_11Header  pMACHeader = (PS802_11Header)(pbyFrame);
+			TKIPvMixKey(pKey->abyKey, pMACHeader->abyAddr2, *pwRxTSC15_0, *pdwRxTSC47_16, pDevice->abyPRNG);
+			rc4_init(&pDevice->SBox, pDevice->abyPRNG, TKIP_KEY_LEN);
+			rc4_encrypt(&pDevice->SBox, pbyIV+8, pbyIV+8, PayloadLen);
+			if (ETHbIsBufferCrc32Ok(pbyIV+8, PayloadLen)) {
+				*pbyNewRsr |= NEWRSR_DECRYPTOK;
+				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ICV OK!\n");
+			} else {
+				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ICV FAIL!!!\n");
+				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "PayloadLen = %d\n", PayloadLen);
+			}
+		}
+	}// end of TKIP/AES
 
+	if ((*(pbyIV+3) & 0x20) != 0)
+		*pbExtIV = true;
+	return true;
+}
 
-static bool s_bHostWepRxEncryption (
-    PSDevice     pDevice,
-    unsigned char *pbyFrame,
-    unsigned int FrameSize,
-    unsigned char *pbyRsr,
-    bool bOnFly,
-    PSKeyItem    pKey,
-    unsigned char *pbyNewRsr,
-    bool *pbExtIV,
-    unsigned short *pwRxTSC15_0,
-    unsigned long *pdwRxTSC47_16
-    )
+static bool s_bHostWepRxEncryption(
+	PSDevice     pDevice,
+	unsigned char *pbyFrame,
+	unsigned int FrameSize,
+	unsigned char *pbyRsr,
+	bool bOnFly,
+	PSKeyItem    pKey,
+	unsigned char *pbyNewRsr,
+	bool *pbExtIV,
+	unsigned short *pwRxTSC15_0,
+	unsigned long *pdwRxTSC47_16
+)
 {
-    unsigned int PayloadLen = FrameSize;
-    unsigned char *pbyIV;
-    unsigned char byKeyIdx;
-    unsigned char byDecMode = KEY_CTL_WEP;
-    PS802_11Header  pMACHeader;
-
+	unsigned int PayloadLen = FrameSize;
+	unsigned char *pbyIV;
+	unsigned char byKeyIdx;
+	unsigned char byDecMode = KEY_CTL_WEP;
+	PS802_11Header  pMACHeader;
+
+	*pwRxTSC15_0 = 0;
+	*pdwRxTSC47_16 = 0;
+
+	pbyIV = pbyFrame + WLAN_HDR_ADDR3_LEN;
+	if (WLAN_GET_FC_TODS(*(unsigned short *)pbyFrame) &&
+	    WLAN_GET_FC_FROMDS(*(unsigned short *)pbyFrame)) {
+		pbyIV += 6;             // 6 is 802.11 address4
+		PayloadLen -= 6;
+	}
+	byKeyIdx = (*(pbyIV+3) & 0xc0);
+	byKeyIdx >>= 6;
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "\nKeyIdx: %d\n", byKeyIdx);
 
+	if (pDevice->pMgmt->byCSSGK == KEY_CTL_TKIP)
+		byDecMode = KEY_CTL_TKIP;
+	else if (pDevice->pMgmt->byCSSGK == KEY_CTL_CCMP)
+		byDecMode = KEY_CTL_CCMP;
 
-    *pwRxTSC15_0 = 0;
-    *pdwRxTSC47_16 = 0;
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "AES:%d %d %d\n", pDevice->pMgmt->byCSSPK, pDevice->pMgmt->byCSSGK, byDecMode);
 
-    pbyIV = pbyFrame + WLAN_HDR_ADDR3_LEN;
-    if ( WLAN_GET_FC_TODS(*(unsigned short *)pbyFrame) &&
-         WLAN_GET_FC_FROMDS(*(unsigned short *)pbyFrame) ) {
-         pbyIV += 6;             // 6 is 802.11 address4
-         PayloadLen -= 6;
-    }
-    byKeyIdx = (*(pbyIV+3) & 0xc0);
-    byKeyIdx >>= 6;
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\nKeyIdx: %d\n", byKeyIdx);
+	if (byDecMode != pKey->byCipherSuite) {
+		if (byDecMode == KEY_CTL_WEP) {
+//            pDevice->s802_11Counter.WEPUndecryptableCount.QuadPart++;
+		} else if (pDevice->bLinkPass == true) {
+//            pDevice->s802_11Counter.DecryptFailureCount.QuadPart++;
+		}
+		return false;
+	}
 
+	if (byDecMode == KEY_CTL_WEP) {
+		// handle WEP
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "byDecMode == KEY_CTL_WEP \n");
+		if ((pDevice->byLocalID <= REV_ID_VT3253_A1) ||
+		    (((PSKeyTable)(pKey->pvKeyTable))->bSoftWEP == true) ||
+		    (bOnFly == false)) {
+			// Software WEP
+			// 1. 3253A
+			// 2. WEP 256
+			// 3. NotOnFly
+
+			PayloadLen -= (WLAN_HDR_ADDR3_LEN + 4 + 4); // 24 is 802.11 header,4 is IV, 4 is crc
+			memcpy(pDevice->abyPRNG, pbyIV, 3);
+			memcpy(pDevice->abyPRNG + 3, pKey->abyKey, pKey->uKeyLength);
+			rc4_init(&pDevice->SBox, pDevice->abyPRNG, pKey->uKeyLength + 3);
+			rc4_encrypt(&pDevice->SBox, pbyIV+4, pbyIV+4, PayloadLen);
+
+			if (ETHbIsBufferCrc32Ok(pbyIV+4, PayloadLen)) {
+				*pbyNewRsr |= NEWRSR_DECRYPTOK;
+			}
+		}
+	} else if ((byDecMode == KEY_CTL_TKIP) ||
+		   (byDecMode == KEY_CTL_CCMP)) {
+		// TKIP/AES
+
+		PayloadLen -= (WLAN_HDR_ADDR3_LEN + 8 + 4); // 24 is 802.11 header, 8 is IV&ExtIV, 4 is crc
+		*pdwRxTSC47_16 = cpu_to_le32(*(unsigned long *)(pbyIV + 4));
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ExtIV: %lx\n", *pdwRxTSC47_16);
+
+		if (byDecMode == KEY_CTL_TKIP) {
+			*pwRxTSC15_0 = cpu_to_le16(MAKEWORD(*(pbyIV+2), *pbyIV));
+		} else {
+			*pwRxTSC15_0 = cpu_to_le16(*(unsigned short *)pbyIV);
+		}
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "TSC0_15: %x\n", *pwRxTSC15_0);
+
+		if (byDecMode == KEY_CTL_TKIP) {
+			if ((pDevice->byLocalID <= REV_ID_VT3253_A1) || (bOnFly == false)) {
+				// Software TKIP
+				// 1. 3253 A
+				// 2. NotOnFly
+				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "soft KEY_CTL_TKIP \n");
+				pMACHeader = (PS802_11Header)(pbyFrame);
+				TKIPvMixKey(pKey->abyKey, pMACHeader->abyAddr2, *pwRxTSC15_0, *pdwRxTSC47_16, pDevice->abyPRNG);
+				rc4_init(&pDevice->SBox, pDevice->abyPRNG, TKIP_KEY_LEN);
+				rc4_encrypt(&pDevice->SBox, pbyIV+8, pbyIV+8, PayloadLen);
+				if (ETHbIsBufferCrc32Ok(pbyIV+8, PayloadLen)) {
+					*pbyNewRsr |= NEWRSR_DECRYPTOK;
+					DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ICV OK!\n");
+				} else {
+					DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ICV FAIL!!!\n");
+					DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "PayloadLen = %d\n", PayloadLen);
+				}
+			}
+		}
 
-    if (pDevice->pMgmt->byCSSGK == KEY_CTL_TKIP)
-        byDecMode = KEY_CTL_TKIP;
-    else if (pDevice->pMgmt->byCSSGK == KEY_CTL_CCMP)
-        byDecMode = KEY_CTL_CCMP;
+		if (byDecMode == KEY_CTL_CCMP) {
+			if (bOnFly == false) {
+				// Software CCMP
+				// NotOnFly
+				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "soft KEY_CTL_CCMP\n");
+				if (AESbGenCCMP(pKey->abyKey, pbyFrame, FrameSize)) {
+					*pbyNewRsr |= NEWRSR_DECRYPTOK;
+					DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "CCMP MIC compare OK!\n");
+				} else {
+					DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "CCMP MIC fail!\n");
+				}
+			}
+		}
 
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"AES:%d %d %d\n", pDevice->pMgmt->byCSSPK, pDevice->pMgmt->byCSSGK, byDecMode);
+	}// end of TKIP/AES
 
-    if (byDecMode != pKey->byCipherSuite) {
-        if (byDecMode == KEY_CTL_WEP) {
-//            pDevice->s802_11Counter.WEPUndecryptableCount.QuadPart++;
-        } else if (pDevice->bLinkPass == true) {
-//            pDevice->s802_11Counter.DecryptFailureCount.QuadPart++;
-        }
-        return false;
-    }
-
-    if (byDecMode == KEY_CTL_WEP) {
-        // handle WEP
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"byDecMode == KEY_CTL_WEP \n");
-        if ((pDevice->byLocalID <= REV_ID_VT3253_A1) ||
-            (((PSKeyTable)(pKey->pvKeyTable))->bSoftWEP == true) ||
-            (bOnFly == false)) {
-            // Software WEP
-            // 1. 3253A
-            // 2. WEP 256
-            // 3. NotOnFly
-
-            PayloadLen -= (WLAN_HDR_ADDR3_LEN + 4 + 4); // 24 is 802.11 header,4 is IV, 4 is crc
-            memcpy(pDevice->abyPRNG, pbyIV, 3);
-            memcpy(pDevice->abyPRNG + 3, pKey->abyKey, pKey->uKeyLength);
-            rc4_init(&pDevice->SBox, pDevice->abyPRNG, pKey->uKeyLength + 3);
-            rc4_encrypt(&pDevice->SBox, pbyIV+4, pbyIV+4, PayloadLen);
-
-            if (ETHbIsBufferCrc32Ok(pbyIV+4, PayloadLen)) {
-                *pbyNewRsr |= NEWRSR_DECRYPTOK;
-            }
-        }
-    } else if ((byDecMode == KEY_CTL_TKIP) ||
-               (byDecMode == KEY_CTL_CCMP)) {
-        // TKIP/AES
-
-        PayloadLen -= (WLAN_HDR_ADDR3_LEN + 8 + 4); // 24 is 802.11 header, 8 is IV&ExtIV, 4 is crc
-        *pdwRxTSC47_16 = cpu_to_le32(*(unsigned long *)(pbyIV + 4));
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ExtIV: %lx\n",*pdwRxTSC47_16);
-
-        if (byDecMode == KEY_CTL_TKIP) {
-            *pwRxTSC15_0 = cpu_to_le16(MAKEWORD(*(pbyIV+2), *pbyIV));
-        } else {
-            *pwRxTSC15_0 = cpu_to_le16(*(unsigned short *)pbyIV);
-        }
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"TSC0_15: %x\n", *pwRxTSC15_0);
-
-        if (byDecMode == KEY_CTL_TKIP) {
-
-            if ((pDevice->byLocalID <= REV_ID_VT3253_A1) || (bOnFly == false)) {
-                // Software TKIP
-                // 1. 3253 A
-                // 2. NotOnFly
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"soft KEY_CTL_TKIP \n");
-                pMACHeader = (PS802_11Header) (pbyFrame);
-                TKIPvMixKey(pKey->abyKey, pMACHeader->abyAddr2, *pwRxTSC15_0, *pdwRxTSC47_16, pDevice->abyPRNG);
-                rc4_init(&pDevice->SBox, pDevice->abyPRNG, TKIP_KEY_LEN);
-                rc4_encrypt(&pDevice->SBox, pbyIV+8, pbyIV+8, PayloadLen);
-                if (ETHbIsBufferCrc32Ok(pbyIV+8, PayloadLen)) {
-                    *pbyNewRsr |= NEWRSR_DECRYPTOK;
-                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ICV OK!\n");
-                } else {
-                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ICV FAIL!!!\n");
-                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"PayloadLen = %d\n", PayloadLen);
-                }
-            }
-        }
-
-        if (byDecMode == KEY_CTL_CCMP) {
-            if (bOnFly == false) {
-                // Software CCMP
-                // NotOnFly
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"soft KEY_CTL_CCMP\n");
-                if (AESbGenCCMP(pKey->abyKey, pbyFrame, FrameSize)) {
-                    *pbyNewRsr |= NEWRSR_DECRYPTOK;
-                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"CCMP MIC compare OK!\n");
-                } else {
-                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"CCMP MIC fail!\n");
-                }
-            }
-        }
-
-    }// end of TKIP/AES
-
-    if ((*(pbyIV+3) & 0x20) != 0)
-        *pbExtIV = true;
-    return true;
+	if ((*(pbyIV+3) & 0x20) != 0)
+		*pbExtIV = true;
+	return true;
 }
 
+static bool s_bAPModeRxData(
+	PSDevice pDevice,
+	struct sk_buff *skb,
+	unsigned int FrameSize,
+	unsigned int cbHeaderOffset,
+	int      iSANodeIndex,
+	int      iDANodeIndex
+)
+{
+	PSMgmtObject        pMgmt = pDevice->pMgmt;
+	bool bRelayAndForward = false;
+	bool bRelayOnly = false;
+	unsigned char byMask[8] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80};
+	unsigned short wAID;
+
+	struct sk_buff *skbcpy = NULL;
+
+	if (FrameSize > CB_MAX_BUF_SIZE)
+		return false;
+	// check DA
+	if (is_multicast_ether_addr((unsigned char *)(skb->data+cbHeaderOffset))) {
+		if (pMgmt->sNodeDBTable[0].bPSEnable) {
+			skbcpy = dev_alloc_skb((int)pDevice->rx_buf_sz);
+
+			// if any node in PS mode, buffer packet until DTIM.
+			if (skbcpy == NULL) {
+				DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "relay multicast no skb available \n");
+			} else {
+				skbcpy->dev = pDevice->dev;
+				skbcpy->len = FrameSize;
+				memcpy(skbcpy->data, skb->data+cbHeaderOffset, FrameSize);
+				skb_queue_tail(&(pMgmt->sNodeDBTable[0].sTxPSQueue), skbcpy);
+
+				pMgmt->sNodeDBTable[0].wEnQueueCnt++;
+				// set tx map
+				pMgmt->abyPSTxMap[0] |= byMask[0];
+			}
+		} else {
+			bRelayAndForward = true;
+		}
+	} else {
+		// check if relay
+		if (BSSDBbIsSTAInNodeDB(pMgmt, (unsigned char *)(skb->data+cbHeaderOffset), &iDANodeIndex)) {
+			if (pMgmt->sNodeDBTable[iDANodeIndex].eNodeState >= NODE_ASSOC) {
+				if (pMgmt->sNodeDBTable[iDANodeIndex].bPSEnable) {
+					// queue this skb until next PS tx, and then release.
+
+					skb->data += cbHeaderOffset;
+					skb->tail += cbHeaderOffset;
+					skb_put(skb, FrameSize);
+					skb_queue_tail(&pMgmt->sNodeDBTable[iDANodeIndex].sTxPSQueue, skb);
+					pMgmt->sNodeDBTable[iDANodeIndex].wEnQueueCnt++;
+					wAID = pMgmt->sNodeDBTable[iDANodeIndex].wAID;
+					pMgmt->abyPSTxMap[wAID >> 3] |=  byMask[wAID & 7];
+					DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "relay: index= %d, pMgmt->abyPSTxMap[%d]= %d\n",
+						iDANodeIndex, (wAID >> 3), pMgmt->abyPSTxMap[wAID >> 3]);
+					return true;
+				} else {
+					bRelayOnly = true;
+				}
+			}
+		}
+	}
+
+	if (bRelayOnly || bRelayAndForward) {
+		// relay this packet right now
+		if (bRelayAndForward)
+			iDANodeIndex = 0;
+
+		if ((pDevice->uAssocCount > 1) && (iDANodeIndex >= 0)) {
+			ROUTEbRelay(pDevice, (unsigned char *)(skb->data + cbHeaderOffset), FrameSize, (unsigned int)iDANodeIndex);
+		}
 
+		if (bRelayOnly)
+			return false;
+	}
+	// none associate, don't forward
+	if (pDevice->uAssocCount == 0)
+		return false;
 
-static bool s_bAPModeRxData (
-    PSDevice pDevice,
-    struct sk_buff* skb,
-    unsigned int FrameSize,
-    unsigned int cbHeaderOffset,
-    int      iSANodeIndex,
-    int      iDANodeIndex
-    )
-{
-    PSMgmtObject        pMgmt = pDevice->pMgmt;
-    bool bRelayAndForward = false;
-    bool bRelayOnly = false;
-    unsigned char byMask[8] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80};
-    unsigned short wAID;
-
-
-    struct sk_buff* skbcpy = NULL;
-
-    if (FrameSize > CB_MAX_BUF_SIZE)
-        return false;
-    // check DA
-    if(is_multicast_ether_addr((unsigned char *)(skb->data+cbHeaderOffset))) {
-       if (pMgmt->sNodeDBTable[0].bPSEnable) {
-
-           skbcpy = dev_alloc_skb((int)pDevice->rx_buf_sz);
-
-        // if any node in PS mode, buffer packet until DTIM.
-           if (skbcpy == NULL) {
-               DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "relay multicast no skb available \n");
-           }
-           else {
-               skbcpy->dev = pDevice->dev;
-               skbcpy->len = FrameSize;
-               memcpy(skbcpy->data, skb->data+cbHeaderOffset, FrameSize);
-               skb_queue_tail(&(pMgmt->sNodeDBTable[0].sTxPSQueue), skbcpy);
-
-               pMgmt->sNodeDBTable[0].wEnQueueCnt++;
-               // set tx map
-               pMgmt->abyPSTxMap[0] |= byMask[0];
-           }
-       }
-       else {
-           bRelayAndForward = true;
-       }
-    }
-    else {
-        // check if relay
-        if (BSSDBbIsSTAInNodeDB(pMgmt, (unsigned char *)(skb->data+cbHeaderOffset), &iDANodeIndex)) {
-            if (pMgmt->sNodeDBTable[iDANodeIndex].eNodeState >= NODE_ASSOC) {
-                if (pMgmt->sNodeDBTable[iDANodeIndex].bPSEnable) {
-                    // queue this skb until next PS tx, and then release.
-
-	                skb->data += cbHeaderOffset;
-	                skb->tail += cbHeaderOffset;
-                    skb_put(skb, FrameSize);
-                    skb_queue_tail(&pMgmt->sNodeDBTable[iDANodeIndex].sTxPSQueue, skb);
-                    pMgmt->sNodeDBTable[iDANodeIndex].wEnQueueCnt++;
-                    wAID = pMgmt->sNodeDBTable[iDANodeIndex].wAID;
-                    pMgmt->abyPSTxMap[wAID >> 3] |=  byMask[wAID & 7];
-                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "relay: index= %d, pMgmt->abyPSTxMap[%d]= %d\n",
-                               iDANodeIndex, (wAID >> 3), pMgmt->abyPSTxMap[wAID >> 3]);
-                    return true;
-                }
-                else {
-                    bRelayOnly = true;
-                }
-            }
-        }
-    }
-
-    if (bRelayOnly || bRelayAndForward) {
-        // relay this packet right now
-        if (bRelayAndForward)
-            iDANodeIndex = 0;
-
-        if ((pDevice->uAssocCount > 1) && (iDANodeIndex >= 0)) {
-            ROUTEbRelay(pDevice, (unsigned char *)(skb->data + cbHeaderOffset), FrameSize, (unsigned int)iDANodeIndex);
-        }
-
-        if (bRelayOnly)
-            return false;
-    }
-    // none associate, don't forward
-    if (pDevice->uAssocCount == 0)
-        return false;
-
-    return true;
+	return true;
 }
-
diff --git a/drivers/staging/vt6655/dpc.h b/drivers/staging/vt6655/dpc.h
index c1b6e76..0ce3155 100644
--- a/drivers/staging/vt6655/dpc.h
+++ b/drivers/staging/vt6655/dpc.h
@@ -42,14 +42,11 @@
 /*---------------------  Export Functions  --------------------------*/
 
 bool
-device_receive_frame (
-    PSDevice pDevice,
-    PSRxDesc pCurrRD
-    );
+device_receive_frame(
+	PSDevice pDevice,
+	PSRxDesc pCurrRD
+);
 
 void	MngWorkItem(void *Context);
 
 #endif // __RXTX_H__
-
-
-
diff --git a/drivers/staging/vt6655/hostap.c b/drivers/staging/vt6655/hostap.c
index 5f13890..8417c2f 100644
--- a/drivers/staging/vt6655/hostap.c
+++ b/drivers/staging/vt6655/hostap.c
@@ -49,16 +49,12 @@
 
 /*---------------------  Static Variables  --------------------------*/
 //static int          msglevel                =MSG_LEVEL_DEBUG;
-static int          msglevel                =MSG_LEVEL_INFO;
+static int msglevel = MSG_LEVEL_INFO;
 
 /*---------------------  Static Functions  --------------------------*/
 
-
-
-
 /*---------------------  Export Variables  --------------------------*/
 
-
 /*
  * Description:
  *      register net_device (AP) for hostap deamon
@@ -75,21 +71,21 @@ static int          msglevel                =MSG_LEVEL_INFO;
 
 static int hostap_enable_hostapd(PSDevice pDevice, int rtnl_locked)
 {
-    PSDevice apdev_priv;
+	PSDevice apdev_priv;
 	struct net_device *dev = pDevice->dev;
 	int ret;
 	const struct net_device_ops apdev_netdev_ops = {
 		.ndo_start_xmit         = pDevice->tx_80211,
 	};
 
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: Enabling hostapd mode\n", dev->name);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: Enabling hostapd mode\n", dev->name);
 
 	pDevice->apdev = kzalloc(sizeof(struct net_device), GFP_KERNEL);
 	if (pDevice->apdev == NULL)
 		return -ENOMEM;
 
-    apdev_priv = netdev_priv(pDevice->apdev);
-    *apdev_priv = *pDevice;
+	apdev_priv = netdev_priv(pDevice->apdev);
+	*apdev_priv = *pDevice;
 	memcpy(pDevice->apdev->dev_addr, dev->dev_addr, ETH_ALEN);
 
 	pDevice->apdev->netdev_ops = &apdev_netdev_ops;
@@ -107,14 +103,14 @@ static int hostap_enable_hostapd(PSDevice pDevice, int rtnl_locked)
 		ret = register_netdev(pDevice->apdev);
 	if (ret) {
 		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: register_netdevice(AP) failed!\n",
-		       dev->name);
+			dev->name);
 		return -1;
 	}
 
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: Registered netdevice %s for AP management\n",
-	       dev->name, pDevice->apdev->name);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: Registered netdevice %s for AP management\n",
+		dev->name, pDevice->apdev->name);
 
-    KeyvInitTable(&pDevice->sKey, pDevice->PortOffset);
+	KeyvInitTable(&pDevice->sKey, pDevice->PortOffset);
 
 	return 0;
 }
@@ -135,33 +131,31 @@ static int hostap_enable_hostapd(PSDevice pDevice, int rtnl_locked)
 
 static int hostap_disable_hostapd(PSDevice pDevice, int rtnl_locked)
 {
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: disabling hostapd mode\n", pDevice->dev->name);
 
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: disabling hostapd mode\n", pDevice->dev->name);
-
-    if (pDevice->apdev && pDevice->apdev->name && pDevice->apdev->name[0]) {
+	if (pDevice->apdev && pDevice->apdev->name && pDevice->apdev->name[0]) {
 		if (rtnl_locked)
 			unregister_netdevice(pDevice->apdev);
 		else
 			unregister_netdev(pDevice->apdev);
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: Netdevice %s unregistered\n",
-		       pDevice->dev->name, pDevice->apdev->name);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: Netdevice %s unregistered\n",
+			pDevice->dev->name, pDevice->apdev->name);
 	}
 	kfree(pDevice->apdev);
 	pDevice->apdev = NULL;
-    pDevice->bEnable8021x = false;
-    pDevice->bEnableHostWEP = false;
-    pDevice->bEncryptionEnable = false;
+	pDevice->bEnable8021x = false;
+	pDevice->bEnableHostWEP = false;
+	pDevice->bEncryptionEnable = false;
 
 //4.2007-0118-03,<Add> by EinsnLiu
 //execute some clear work
-pDevice->pMgmt->byCSSPK=KEY_CTL_NONE;
-pDevice->pMgmt->byCSSGK=KEY_CTL_NONE;
-KeyvInitTable(&pDevice->sKey,pDevice->PortOffset);
+	pDevice->pMgmt->byCSSPK = KEY_CTL_NONE;
+	pDevice->pMgmt->byCSSGK = KEY_CTL_NONE;
+	KeyvInitTable(&pDevice->sKey, pDevice->PortOffset);
 
 	return 0;
 }
 
-
 /*
  * Description:
  *      Set enable/disable hostapd mode
@@ -192,7 +186,6 @@ int vt6655_hostap_set_hostapd(PSDevice pDevice, int val, int rtnl_locked)
 		return hostap_disable_hostapd(pDevice, rtnl_locked);
 }
 
-
 /*
  * Description:
  *      remove station function supported for hostap deamon
@@ -207,17 +200,15 @@ int vt6655_hostap_set_hostapd(PSDevice pDevice, int val, int rtnl_locked)
  *
  */
 static int hostap_remove_sta(PSDevice pDevice,
-				     struct viawget_hostapd_param *param)
+			     struct viawget_hostapd_param *param)
 {
 	unsigned int uNodeIndex;
 
-
-    if (BSSDBbIsSTAInNodeDB(pDevice->pMgmt, param->sta_addr, &uNodeIndex)) {
-        BSSvRemoveOneNode(pDevice, uNodeIndex);
-    }
-    else {
-        return -ENOENT;
-    }
+	if (BSSDBbIsSTAInNodeDB(pDevice->pMgmt, param->sta_addr, &uNodeIndex)) {
+		BSSvRemoveOneNode(pDevice, uNodeIndex);
+	} else {
+		return -ENOENT;
+	}
 	return 0;
 }
 
@@ -235,47 +226,46 @@ static int hostap_remove_sta(PSDevice pDevice,
  *
  */
 static int hostap_add_sta(PSDevice pDevice,
-				  struct viawget_hostapd_param *param)
+			  struct viawget_hostapd_param *param)
 {
-    PSMgmtObject    pMgmt = pDevice->pMgmt;
+	PSMgmtObject    pMgmt = pDevice->pMgmt;
 	unsigned int uNodeIndex;
 
-
-    if (!BSSDBbIsSTAInNodeDB(pMgmt, param->sta_addr, &uNodeIndex)) {
-        BSSvCreateOneNode((PSDevice)pDevice, &uNodeIndex);
-    }
-    memcpy(pMgmt->sNodeDBTable[uNodeIndex].abyMACAddr, param->sta_addr, WLAN_ADDR_LEN);
-    pMgmt->sNodeDBTable[uNodeIndex].eNodeState = NODE_ASSOC;
-    pMgmt->sNodeDBTable[uNodeIndex].wCapInfo = param->u.add_sta.capability;
+	if (!BSSDBbIsSTAInNodeDB(pMgmt, param->sta_addr, &uNodeIndex)) {
+		BSSvCreateOneNode((PSDevice)pDevice, &uNodeIndex);
+	}
+	memcpy(pMgmt->sNodeDBTable[uNodeIndex].abyMACAddr, param->sta_addr, WLAN_ADDR_LEN);
+	pMgmt->sNodeDBTable[uNodeIndex].eNodeState = NODE_ASSOC;
+	pMgmt->sNodeDBTable[uNodeIndex].wCapInfo = param->u.add_sta.capability;
 // TODO listenInterval
 //    pMgmt->sNodeDBTable[uNodeIndex].wListenInterval = 1;
-    pMgmt->sNodeDBTable[uNodeIndex].bPSEnable = false;
-    pMgmt->sNodeDBTable[uNodeIndex].bySuppRate = param->u.add_sta.tx_supp_rates;
-
-    // set max tx rate
-    pMgmt->sNodeDBTable[uNodeIndex].wTxDataRate =
-           pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate;
-    // set max basic rate
-    pMgmt->sNodeDBTable[uNodeIndex].wMaxBasicRate = RATE_2M;
-    // Todo: check sta preamble, if ap can't support, set status code
-    pMgmt->sNodeDBTable[uNodeIndex].bShortPreamble =
-            WLAN_GET_CAP_INFO_SHORTPREAMBLE(pMgmt->sNodeDBTable[uNodeIndex].wCapInfo);
-
-    pMgmt->sNodeDBTable[uNodeIndex].wAID = (unsigned short)param->u.add_sta.aid;
-
-    pMgmt->sNodeDBTable[uNodeIndex].ulLastRxJiffer = jiffies;
-
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Add STA AID= %d \n", pMgmt->sNodeDBTable[uNodeIndex].wAID);
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "MAC=%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X \n",
-               param->sta_addr[0],
-               param->sta_addr[1],
-               param->sta_addr[2],
-               param->sta_addr[3],
-               param->sta_addr[4],
-               param->sta_addr[5]
-              ) ;
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Max Support rate = %d \n",
-               pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate);
+	pMgmt->sNodeDBTable[uNodeIndex].bPSEnable = false;
+	pMgmt->sNodeDBTable[uNodeIndex].bySuppRate = param->u.add_sta.tx_supp_rates;
+
+	// set max tx rate
+	pMgmt->sNodeDBTable[uNodeIndex].wTxDataRate =
+		pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate;
+	// set max basic rate
+	pMgmt->sNodeDBTable[uNodeIndex].wMaxBasicRate = RATE_2M;
+	// Todo: check sta preamble, if ap can't support, set status code
+	pMgmt->sNodeDBTable[uNodeIndex].bShortPreamble =
+		WLAN_GET_CAP_INFO_SHORTPREAMBLE(pMgmt->sNodeDBTable[uNodeIndex].wCapInfo);
+
+	pMgmt->sNodeDBTable[uNodeIndex].wAID = (unsigned short)param->u.add_sta.aid;
+
+	pMgmt->sNodeDBTable[uNodeIndex].ulLastRxJiffer = jiffies;
+
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Add STA AID= %d \n", pMgmt->sNodeDBTable[uNodeIndex].wAID);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "MAC=%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X \n",
+		param->sta_addr[0],
+		param->sta_addr[1],
+		param->sta_addr[2],
+		param->sta_addr[3],
+		param->sta_addr[4],
+		param->sta_addr[5]
+		);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Max Support rate = %d \n",
+		pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate);
 
 	return 0;
 }
@@ -295,19 +285,18 @@ static int hostap_add_sta(PSDevice pDevice,
  */
 
 static int hostap_get_info_sta(PSDevice pDevice,
-				       struct viawget_hostapd_param *param)
+			       struct viawget_hostapd_param *param)
 {
-    PSMgmtObject    pMgmt = pDevice->pMgmt;
+	PSMgmtObject    pMgmt = pDevice->pMgmt;
 	unsigned int uNodeIndex;
 
-    if (BSSDBbIsSTAInNodeDB(pMgmt, param->sta_addr, &uNodeIndex)) {
-	    param->u.get_info_sta.inactive_sec =
-	        (jiffies - pMgmt->sNodeDBTable[uNodeIndex].ulLastRxJiffer) / HZ;
+	if (BSSDBbIsSTAInNodeDB(pMgmt, param->sta_addr, &uNodeIndex)) {
+		param->u.get_info_sta.inactive_sec =
+			(jiffies - pMgmt->sNodeDBTable[uNodeIndex].ulLastRxJiffer) / HZ;
 
-	    //param->u.get_info_sta.txexc = pMgmt->sNodeDBTable[uNodeIndex].uTxAttempts;
-	}
-	else {
-	    return -ENOENT;
+		//param->u.get_info_sta.txexc = pMgmt->sNodeDBTable[uNodeIndex].uTxAttempts;
+	} else {
+		return -ENOENT;
 	}
 
 	return 0;
@@ -328,21 +317,20 @@ static int hostap_get_info_sta(PSDevice pDevice,
  *
  */
 /*
-static int hostap_reset_txexc_sta(PSDevice pDevice,
-					  struct viawget_hostapd_param *param)
-{
-    PSMgmtObject    pMgmt = pDevice->pMgmt;
-	unsigned int uNodeIndex;
-
-    if (BSSDBbIsSTAInNodeDB(pMgmt, param->sta_addr, &uNodeIndex)) {
-        pMgmt->sNodeDBTable[uNodeIndex].uTxAttempts = 0;
-	}
-	else {
-	    return -ENOENT;
-	}
-
-	return 0;
-}
+  static int hostap_reset_txexc_sta(PSDevice pDevice,
+  struct viawget_hostapd_param *param)
+  {
+  PSMgmtObject    pMgmt = pDevice->pMgmt;
+  unsigned int uNodeIndex;
+
+  if (BSSDBbIsSTAInNodeDB(pMgmt, param->sta_addr, &uNodeIndex)) {
+  pMgmt->sNodeDBTable[uNodeIndex].uTxAttempts = 0;
+  } else {
+  return -ENOENT;
+  }
+
+  return 0;
+  }
 */
 
 /*
@@ -359,26 +347,23 @@ static int hostap_reset_txexc_sta(PSDevice pDevice,
  *
  */
 static int hostap_set_flags_sta(PSDevice pDevice,
-					struct viawget_hostapd_param *param)
+				struct viawget_hostapd_param *param)
 {
-    PSMgmtObject    pMgmt = pDevice->pMgmt;
+	PSMgmtObject    pMgmt = pDevice->pMgmt;
 	unsigned int uNodeIndex;
 
-    if (BSSDBbIsSTAInNodeDB(pMgmt, param->sta_addr, &uNodeIndex)) {
+	if (BSSDBbIsSTAInNodeDB(pMgmt, param->sta_addr, &uNodeIndex)) {
 		pMgmt->sNodeDBTable[uNodeIndex].dwFlags |= param->u.set_flags_sta.flags_or;
 		pMgmt->sNodeDBTable[uNodeIndex].dwFlags &= param->u.set_flags_sta.flags_and;
 		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " dwFlags = %x \n",
-		            (unsigned int)pMgmt->sNodeDBTable[uNodeIndex].dwFlags);
-	}
-	else {
-	    return -ENOENT;
+			(unsigned int)pMgmt->sNodeDBTable[uNodeIndex].dwFlags);
+	} else {
+		return -ENOENT;
 	}
 
 	return 0;
 }
 
-
-
 /*
  * Description:
  *      set generic element (wpa ie)
@@ -393,34 +378,32 @@ static int hostap_set_flags_sta(PSDevice pDevice,
  *
  */
 static int hostap_set_generic_element(PSDevice pDevice,
-					struct viawget_hostapd_param *param)
+				      struct viawget_hostapd_param *param)
 {
-    PSMgmtObject    pMgmt = pDevice->pMgmt;
-
-
+	PSMgmtObject    pMgmt = pDevice->pMgmt;
 
-    memcpy( pMgmt->abyWPAIE,
-            param->u.generic_elem.data,
-            param->u.generic_elem.len
-           );
+	memcpy(pMgmt->abyWPAIE,
+	       param->u.generic_elem.data,
+	       param->u.generic_elem.len
+		);
 
-    pMgmt->wWPAIELen = 	param->u.generic_elem.len;
+	pMgmt->wWPAIELen = param->u.generic_elem.len;
 
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pMgmt->wWPAIELen = %d\n",  pMgmt->wWPAIELen);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pMgmt->wWPAIELen = %d\n", pMgmt->wWPAIELen);
 
-    // disable wpa
-    if (pMgmt->wWPAIELen == 0) {
-        pMgmt->eAuthenMode = WMAC_AUTH_OPEN;
+	// disable wpa
+	if (pMgmt->wWPAIELen == 0) {
+		pMgmt->eAuthenMode = WMAC_AUTH_OPEN;
 		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " No WPAIE, Disable WPA \n");
-    } else  {
-        // enable wpa
-        if ((pMgmt->abyWPAIE[0] == WLAN_EID_RSN_WPA) ||
-             (pMgmt->abyWPAIE[0] == WLAN_EID_RSN)) {
-              pMgmt->eAuthenMode = WMAC_AUTH_WPANONE;
-               DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Set WPAIE enable WPA\n");
-        } else
-            return -EINVAL;
-    }
+	} else  {
+		// enable wpa
+		if ((pMgmt->abyWPAIE[0] == WLAN_EID_RSN_WPA) ||
+		    (pMgmt->abyWPAIE[0] == WLAN_EID_RSN)) {
+			pMgmt->eAuthenMode = WMAC_AUTH_WPANONE;
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Set WPAIE enable WPA\n");
+		} else
+			return -EINVAL;
+	}
 
 	return 0;
 }
@@ -440,11 +423,11 @@ static int hostap_set_generic_element(PSDevice pDevice,
 
 static void hostap_flush_sta(PSDevice pDevice)
 {
-    // reserved node index =0 for multicast node.
-    BSSvClearNodeDBTable(pDevice, 1);
-    pDevice->uAssocCount = 0;
+	// reserved node index =0 for multicast node.
+	BSSvClearNodeDBTable(pDevice, 1);
+	pDevice->uAssocCount = 0;
 
-    return;
+	return;
 }
 
 /*
@@ -461,34 +444,32 @@ static void hostap_flush_sta(PSDevice pDevice)
  *
  */
 static int hostap_set_encryption(PSDevice pDevice,
-				       struct viawget_hostapd_param *param,
-				       int param_len)
+				 struct viawget_hostapd_param *param,
+				 int param_len)
 {
-    PSMgmtObject    pMgmt = pDevice->pMgmt;
-    unsigned long dwKeyIndex = 0;
-    unsigned char abyKey[MAX_KEY_LEN];
-    unsigned char abySeq[MAX_KEY_LEN];
-    NDIS_802_11_KEY_RSC   KeyRSC;
-    unsigned char byKeyDecMode = KEY_CTL_WEP;
+	PSMgmtObject    pMgmt = pDevice->pMgmt;
+	unsigned long dwKeyIndex = 0;
+	unsigned char abyKey[MAX_KEY_LEN];
+	unsigned char abySeq[MAX_KEY_LEN];
+	NDIS_802_11_KEY_RSC   KeyRSC;
+	unsigned char byKeyDecMode = KEY_CTL_WEP;
 	int     ret = 0;
 	int     iNodeIndex = -1;
 	int     ii;
 	bool bKeyTableFull = false;
 	unsigned short wKeyCtl = 0;
 
-
 	param->u.crypt.err = 0;
 /*
-	if (param_len !=
-	    (int) ((char *) param->u.crypt.key - (char *) param) +
-	    param->u.crypt.key_len)
-		return -EINVAL;
+  if (param_len !=
+  (int) ((char *) param->u.crypt.key - (char *) param) +
+  param->u.crypt.key_len)
+  return -EINVAL;
 */
 
 	if (param->u.crypt.alg > WPA_ALG_CCMP)
 		return -EINVAL;
 
-
 	if ((param->u.crypt.idx > 3) || (param->u.crypt.key_len > MAX_KEY_LEN)) {
 		param->u.crypt.err = HOSTAP_CRYPT_ERR_KEY_SET_FAILED;
 		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " HOSTAP_CRYPT_ERR_KEY_SET_FAILED\n");
@@ -498,105 +479,102 @@ static int hostap_set_encryption(PSDevice pDevice,
 	if (is_broadcast_ether_addr(param->sta_addr)) {
 		if (param->u.crypt.idx >= MAX_GROUP_KEY)
 			return -EINVAL;
-        iNodeIndex = 0;
+		iNodeIndex = 0;
 
 	} else {
-	    if (BSSDBbIsSTAInNodeDB(pMgmt, param->sta_addr, &iNodeIndex) == false) {
-	        param->u.crypt.err = HOSTAP_CRYPT_ERR_UNKNOWN_ADDR;
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " HOSTAP_CRYPT_ERR_UNKNOWN_ADDR\n");
-	        return -EINVAL;
-	    }
+		if (BSSDBbIsSTAInNodeDB(pMgmt, param->sta_addr, &iNodeIndex) == false) {
+			param->u.crypt.err = HOSTAP_CRYPT_ERR_UNKNOWN_ADDR;
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " HOSTAP_CRYPT_ERR_UNKNOWN_ADDR\n");
+			return -EINVAL;
+		}
 	}
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " hostap_set_encryption: sta_index %d \n", iNodeIndex);
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " hostap_set_encryption: alg %d \n", param->u.crypt.alg);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " hostap_set_encryption: sta_index %d \n", iNodeIndex);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " hostap_set_encryption: alg %d \n", param->u.crypt.alg);
 
 	if (param->u.crypt.alg == WPA_ALG_NONE) {
-
-        if (pMgmt->sNodeDBTable[iNodeIndex].bOnFly == true) {
-            if (KeybRemoveKey(&(pDevice->sKey),
-                                param->sta_addr,
-                                pMgmt->sNodeDBTable[iNodeIndex].dwKeyIndex,
-                                pDevice->PortOffset) == false) {
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "KeybRemoveKey fail \n");
-            }
-            pMgmt->sNodeDBTable[iNodeIndex].bOnFly = false;
-        }
-        pMgmt->sNodeDBTable[iNodeIndex].byKeyIndex = 0;
-        pMgmt->sNodeDBTable[iNodeIndex].dwKeyIndex = 0;
-        pMgmt->sNodeDBTable[iNodeIndex].uWepKeyLength = 0;
-        pMgmt->sNodeDBTable[iNodeIndex].KeyRSC = 0;
-        pMgmt->sNodeDBTable[iNodeIndex].dwTSC47_16 = 0;
-        pMgmt->sNodeDBTable[iNodeIndex].wTSC15_0 = 0;
-        pMgmt->sNodeDBTable[iNodeIndex].byCipherSuite = 0;
-        memset(&pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[0],
-                0,
-                MAX_KEY_LEN
-               );
-
-        return ret;
+		if (pMgmt->sNodeDBTable[iNodeIndex].bOnFly == true) {
+			if (KeybRemoveKey(&(pDevice->sKey),
+					  param->sta_addr,
+					  pMgmt->sNodeDBTable[iNodeIndex].dwKeyIndex,
+					  pDevice->PortOffset) == false) {
+				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "KeybRemoveKey fail \n");
+			}
+			pMgmt->sNodeDBTable[iNodeIndex].bOnFly = false;
+		}
+		pMgmt->sNodeDBTable[iNodeIndex].byKeyIndex = 0;
+		pMgmt->sNodeDBTable[iNodeIndex].dwKeyIndex = 0;
+		pMgmt->sNodeDBTable[iNodeIndex].uWepKeyLength = 0;
+		pMgmt->sNodeDBTable[iNodeIndex].KeyRSC = 0;
+		pMgmt->sNodeDBTable[iNodeIndex].dwTSC47_16 = 0;
+		pMgmt->sNodeDBTable[iNodeIndex].wTSC15_0 = 0;
+		pMgmt->sNodeDBTable[iNodeIndex].byCipherSuite = 0;
+		memset(&pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[0],
+		       0,
+		       MAX_KEY_LEN
+);
+
+		return ret;
 	}
 
-    memcpy(abyKey, param->u.crypt.key, param->u.crypt.key_len);
-    // copy to node key tbl
-    pMgmt->sNodeDBTable[iNodeIndex].byKeyIndex = param->u.crypt.idx;
-    pMgmt->sNodeDBTable[iNodeIndex].uWepKeyLength = param->u.crypt.key_len;
-    memcpy(&pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[0],
-            param->u.crypt.key,
-            param->u.crypt.key_len
-           );
-
-    dwKeyIndex = (unsigned long)(param->u.crypt.idx);
-    if (param->u.crypt.flags & HOSTAP_CRYPT_FLAG_SET_TX_KEY) {
-        pDevice->byKeyIndex = (unsigned char)dwKeyIndex;
-        pDevice->bTransmitKey = true;
-        dwKeyIndex |= (1 << 31);
-    }
+	memcpy(abyKey, param->u.crypt.key, param->u.crypt.key_len);
+	// copy to node key tbl
+	pMgmt->sNodeDBTable[iNodeIndex].byKeyIndex = param->u.crypt.idx;
+	pMgmt->sNodeDBTable[iNodeIndex].uWepKeyLength = param->u.crypt.key_len;
+	memcpy(&pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[0],
+	       param->u.crypt.key,
+	       param->u.crypt.key_len
+);
+
+	dwKeyIndex = (unsigned long)(param->u.crypt.idx);
+	if (param->u.crypt.flags & HOSTAP_CRYPT_FLAG_SET_TX_KEY) {
+		pDevice->byKeyIndex = (unsigned char)dwKeyIndex;
+		pDevice->bTransmitKey = true;
+		dwKeyIndex |= (1 << 31);
+	}
 
 	if (param->u.crypt.alg == WPA_ALG_WEP) {
-
-        if ((pDevice->bEnable8021x == false) || (iNodeIndex == 0)) {
-            KeybSetDefaultKey(&(pDevice->sKey),
-                                dwKeyIndex & ~(BIT30 | USE_KEYRSC),
-                                param->u.crypt.key_len,
-                                NULL,
-                                abyKey,
-                                KEY_CTL_WEP,
-                                pDevice->PortOffset,
-                                pDevice->byLocalID);
-
-        } else {
-            // 8021x enable, individual key
-            dwKeyIndex |= (1 << 30); // set pairwise key
-            if (KeybSetKey(&(pDevice->sKey),
-                           &param->sta_addr[0],
-                           dwKeyIndex & ~(USE_KEYRSC),
-                           param->u.crypt.key_len,
-                           (PQWORD) &(KeyRSC),
-                           (unsigned char *)abyKey,
-                            KEY_CTL_WEP,
-                            pDevice->PortOffset,
-                            pDevice->byLocalID) == true) {
-
-                pMgmt->sNodeDBTable[iNodeIndex].bOnFly = true;
-
-            } else {
-                // Key Table Full
-                pMgmt->sNodeDBTable[iNodeIndex].bOnFly = false;
-                bKeyTableFull = true;
-            }
-        }
-        pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled;
-        pDevice->bEncryptionEnable = true;
-        pMgmt->byCSSPK = KEY_CTL_WEP;
-        pMgmt->byCSSGK = KEY_CTL_WEP;
-        pMgmt->sNodeDBTable[iNodeIndex].byCipherSuite = KEY_CTL_WEP;
-        pMgmt->sNodeDBTable[iNodeIndex].dwKeyIndex = dwKeyIndex;
-        return ret;
+		if ((pDevice->bEnable8021x == false) || (iNodeIndex == 0)) {
+			KeybSetDefaultKey(&(pDevice->sKey),
+					  dwKeyIndex & ~(BIT30 | USE_KEYRSC),
+					  param->u.crypt.key_len,
+					  NULL,
+					  abyKey,
+					  KEY_CTL_WEP,
+					  pDevice->PortOffset,
+					  pDevice->byLocalID);
+
+		} else {
+			// 8021x enable, individual key
+			dwKeyIndex |= (1 << 30); // set pairwise key
+			if (KeybSetKey(&(pDevice->sKey),
+				       &param->sta_addr[0],
+				       dwKeyIndex & ~(USE_KEYRSC),
+				       param->u.crypt.key_len,
+				       (PQWORD) &(KeyRSC),
+				       (unsigned char *)abyKey,
+				       KEY_CTL_WEP,
+				       pDevice->PortOffset,
+				       pDevice->byLocalID) == true) {
+				pMgmt->sNodeDBTable[iNodeIndex].bOnFly = true;
+
+			} else {
+				// Key Table Full
+				pMgmt->sNodeDBTable[iNodeIndex].bOnFly = false;
+				bKeyTableFull = true;
+			}
+		}
+		pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled;
+		pDevice->bEncryptionEnable = true;
+		pMgmt->byCSSPK = KEY_CTL_WEP;
+		pMgmt->byCSSGK = KEY_CTL_WEP;
+		pMgmt->sNodeDBTable[iNodeIndex].byCipherSuite = KEY_CTL_WEP;
+		pMgmt->sNodeDBTable[iNodeIndex].dwKeyIndex = dwKeyIndex;
+		return ret;
 	}
 
 	if (param->u.crypt.seq) {
-	    memcpy(&abySeq, param->u.crypt.seq, 8);
-		for (ii = 0 ; ii < 8 ; ii++)
+		memcpy(&abySeq, param->u.crypt.seq, 8);
+		for (ii = 0; ii < 8; ii++)
 			KeyRSC |= (unsigned long)abySeq[ii] << (ii * 8);
 
 		dwKeyIndex |= 1 << 29;
@@ -604,91 +582,87 @@ static int hostap_set_encryption(PSDevice pDevice,
 	}
 
 	if (param->u.crypt.alg == WPA_ALG_TKIP) {
-	    if (param->u.crypt.key_len != MAX_KEY_LEN)
-	        return -EINVAL;
-	    pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled;
-        byKeyDecMode = KEY_CTL_TKIP;
-        pMgmt->byCSSPK = KEY_CTL_TKIP;
-        pMgmt->byCSSGK = KEY_CTL_TKIP;
+		if (param->u.crypt.key_len != MAX_KEY_LEN)
+			return -EINVAL;
+		pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled;
+		byKeyDecMode = KEY_CTL_TKIP;
+		pMgmt->byCSSPK = KEY_CTL_TKIP;
+		pMgmt->byCSSGK = KEY_CTL_TKIP;
 	}
 
 	if (param->u.crypt.alg == WPA_ALG_CCMP) {
-	    if ((param->u.crypt.key_len != AES_KEY_LEN) ||
-	        (pDevice->byLocalID <= REV_ID_VT3253_A1))
-	        return -EINVAL;
-        pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled;
-        byKeyDecMode = KEY_CTL_CCMP;
-        pMgmt->byCSSPK = KEY_CTL_CCMP;
-        pMgmt->byCSSGK = KEY_CTL_CCMP;
-    }
-
-
-    if (iNodeIndex == 0) {
-       KeybSetDefaultKey(&(pDevice->sKey),
-                           dwKeyIndex,
-                           param->u.crypt.key_len,
-                           (PQWORD) &(KeyRSC),
-                           abyKey,
-                           byKeyDecMode,
-                           pDevice->PortOffset,
-                           pDevice->byLocalID);
-       pMgmt->sNodeDBTable[iNodeIndex].bOnFly = true;
-
-    } else {
-        dwKeyIndex |= (1 << 30); // set pairwise key
-        if (KeybSetKey(&(pDevice->sKey),
-                       &param->sta_addr[0],
-                       dwKeyIndex,
-                       param->u.crypt.key_len,
-                       (PQWORD) &(KeyRSC),
-                       (unsigned char *)abyKey,
-                        byKeyDecMode,
-                        pDevice->PortOffset,
-                        pDevice->byLocalID) == true) {
-
-            pMgmt->sNodeDBTable[iNodeIndex].bOnFly = true;
-
-        } else {
-            // Key Table Full
-            pMgmt->sNodeDBTable[iNodeIndex].bOnFly = false;
-            bKeyTableFull = true;
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " Key Table Full\n");
-        }
-
-    }
-
-    if (bKeyTableFull == true) {
-        wKeyCtl &= 0x7F00;              // clear all key control filed
-        wKeyCtl |= (byKeyDecMode << 4);
-        wKeyCtl |= (byKeyDecMode);
-        wKeyCtl |= 0x0044;              // use group key for all address
-        wKeyCtl |= 0x4000;              // disable KeyTable[MAX_KEY_TABLE-1] on-fly to genernate rx int
-        MACvSetDefaultKeyCtl(pDevice->PortOffset, wKeyCtl, MAX_KEY_TABLE-1, pDevice->byLocalID);
-    }
-
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " Set key sta_index= %d \n", iNodeIndex);
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " tx_index=%d len=%d \n", param->u.crypt.idx,
-               param->u.crypt.key_len );
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " key=%x-%x-%x-%x-%x-xxxxx \n",
-               pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[0],
-               pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[1],
-               pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[2],
-               pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[3],
-               pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[4]
-              );
+		if ((param->u.crypt.key_len != AES_KEY_LEN) ||
+		    (pDevice->byLocalID <= REV_ID_VT3253_A1))
+			return -EINVAL;
+		pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled;
+		byKeyDecMode = KEY_CTL_CCMP;
+		pMgmt->byCSSPK = KEY_CTL_CCMP;
+		pMgmt->byCSSGK = KEY_CTL_CCMP;
+	}
+
+	if (iNodeIndex == 0) {
+		KeybSetDefaultKey(&(pDevice->sKey),
+				  dwKeyIndex,
+				  param->u.crypt.key_len,
+				  (PQWORD) &(KeyRSC),
+				  abyKey,
+				  byKeyDecMode,
+				  pDevice->PortOffset,
+				  pDevice->byLocalID);
+		pMgmt->sNodeDBTable[iNodeIndex].bOnFly = true;
+
+	} else {
+		dwKeyIndex |= (1 << 30); // set pairwise key
+		if (KeybSetKey(&(pDevice->sKey),
+			       &param->sta_addr[0],
+			       dwKeyIndex,
+			       param->u.crypt.key_len,
+			       (PQWORD) &(KeyRSC),
+			       (unsigned char *)abyKey,
+			       byKeyDecMode,
+			       pDevice->PortOffset,
+			       pDevice->byLocalID) == true) {
+			pMgmt->sNodeDBTable[iNodeIndex].bOnFly = true;
+
+		} else {
+			// Key Table Full
+			pMgmt->sNodeDBTable[iNodeIndex].bOnFly = false;
+			bKeyTableFull = true;
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " Key Table Full\n");
+		}
+
+	}
+
+	if (bKeyTableFull == true) {
+		wKeyCtl &= 0x7F00;              // clear all key control filed
+		wKeyCtl |= (byKeyDecMode << 4);
+		wKeyCtl |= (byKeyDecMode);
+		wKeyCtl |= 0x0044;              // use group key for all address
+		wKeyCtl |= 0x4000;              // disable KeyTable[MAX_KEY_TABLE-1] on-fly to genernate rx int
+		MACvSetDefaultKeyCtl(pDevice->PortOffset, wKeyCtl, MAX_KEY_TABLE-1, pDevice->byLocalID);
+	}
+
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " Set key sta_index= %d \n", iNodeIndex);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " tx_index=%d len=%d \n", param->u.crypt.idx,
+		param->u.crypt.key_len);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " key=%x-%x-%x-%x-%x-xxxxx \n",
+		pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[0],
+		pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[1],
+		pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[2],
+		pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[3],
+		pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[4]
+);
 
 	// set wep key
-    pDevice->bEncryptionEnable = true;
-    pMgmt->sNodeDBTable[iNodeIndex].byCipherSuite = byKeyDecMode;
-    pMgmt->sNodeDBTable[iNodeIndex].dwKeyIndex = dwKeyIndex;
-    pMgmt->sNodeDBTable[iNodeIndex].dwTSC47_16 = 0;
-    pMgmt->sNodeDBTable[iNodeIndex].wTSC15_0 = 0;
+	pDevice->bEncryptionEnable = true;
+	pMgmt->sNodeDBTable[iNodeIndex].byCipherSuite = byKeyDecMode;
+	pMgmt->sNodeDBTable[iNodeIndex].dwKeyIndex = dwKeyIndex;
+	pMgmt->sNodeDBTable[iNodeIndex].dwTSC47_16 = 0;
+	pMgmt->sNodeDBTable[iNodeIndex].wTSC15_0 = 0;
 
 	return ret;
 }
 
-
-
 /*
  * Description:
  *      get each stations encryption key
@@ -703,36 +677,34 @@ static int hostap_set_encryption(PSDevice pDevice,
  *
  */
 static int hostap_get_encryption(PSDevice pDevice,
-				       struct viawget_hostapd_param *param,
-				       int param_len)
+				 struct viawget_hostapd_param *param,
+				 int param_len)
 {
-    PSMgmtObject    pMgmt = pDevice->pMgmt;
+	PSMgmtObject    pMgmt = pDevice->pMgmt;
 	int     ret = 0;
 	int     ii;
-	int     iNodeIndex =0;
-
+	int     iNodeIndex = 0;
 
 	param->u.crypt.err = 0;
 
 	if (is_broadcast_ether_addr(param->sta_addr)) {
-        iNodeIndex = 0;
+		iNodeIndex = 0;
 	} else {
-	    if (BSSDBbIsSTAInNodeDB(pMgmt, param->sta_addr, &iNodeIndex) == false) {
-	        param->u.crypt.err = HOSTAP_CRYPT_ERR_UNKNOWN_ADDR;
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "hostap_get_encryption: HOSTAP_CRYPT_ERR_UNKNOWN_ADDR\n");
-	        return -EINVAL;
-	    }
+		if (BSSDBbIsSTAInNodeDB(pMgmt, param->sta_addr, &iNodeIndex) == false) {
+			param->u.crypt.err = HOSTAP_CRYPT_ERR_UNKNOWN_ADDR;
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "hostap_get_encryption: HOSTAP_CRYPT_ERR_UNKNOWN_ADDR\n");
+			return -EINVAL;
+		}
 	}
 	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "hostap_get_encryption: %d\n", iNodeIndex);
-    memset(param->u.crypt.seq, 0, 8);
-    for (ii = 0 ; ii < 8 ; ii++) {
-        param->u.crypt.seq[ii] = (unsigned char)pMgmt->sNodeDBTable[iNodeIndex].KeyRSC >> (ii * 8);
-    }
+	memset(param->u.crypt.seq, 0, 8);
+	for (ii = 0; ii < 8; ii++) {
+		param->u.crypt.seq[ii] = (unsigned char)pMgmt->sNodeDBTable[iNodeIndex].KeyRSC >> (ii * 8);
+	}
 
 	return ret;
 }
 
-
 /*
  * Description:
  *      vt6655_hostap_ioctl main function supported for hostap deamon.
@@ -768,80 +740,79 @@ int vt6655_hostap_ioctl(PSDevice pDevice, struct iw_point *p)
 
 	switch (param->cmd) {
 	case VIAWGET_HOSTAPD_SET_ENCRYPTION:
-	    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_SET_ENCRYPTION \n");
-        spin_lock_irq(&pDevice->lock);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_SET_ENCRYPTION \n");
+		spin_lock_irq(&pDevice->lock);
 		ret = hostap_set_encryption(pDevice, param, p->length);
-        spin_unlock_irq(&pDevice->lock);
+		spin_unlock_irq(&pDevice->lock);
 		break;
 	case VIAWGET_HOSTAPD_GET_ENCRYPTION:
-	    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_GET_ENCRYPTION \n");
-        spin_lock_irq(&pDevice->lock);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_GET_ENCRYPTION \n");
+		spin_lock_irq(&pDevice->lock);
 		ret = hostap_get_encryption(pDevice, param, p->length);
-        spin_unlock_irq(&pDevice->lock);
+		spin_unlock_irq(&pDevice->lock);
 		break;
 	case VIAWGET_HOSTAPD_SET_ASSOC_AP_ADDR:
-	    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_SET_ASSOC_AP_ADDR \n");
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_SET_ASSOC_AP_ADDR \n");
 		return -EOPNOTSUPP;
 		break;
 	case VIAWGET_HOSTAPD_FLUSH:
-	    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_FLUSH \n");
-        spin_lock_irq(&pDevice->lock);
-    	hostap_flush_sta(pDevice);
-        spin_unlock_irq(&pDevice->lock);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_FLUSH \n");
+		spin_lock_irq(&pDevice->lock);
+		hostap_flush_sta(pDevice);
+		spin_unlock_irq(&pDevice->lock);
 		break;
 	case VIAWGET_HOSTAPD_ADD_STA:
-	    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_ADD_STA \n");
-         spin_lock_irq(&pDevice->lock);
-		 ret = hostap_add_sta(pDevice, param);
-         spin_unlock_irq(&pDevice->lock);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_ADD_STA \n");
+		spin_lock_irq(&pDevice->lock);
+		ret = hostap_add_sta(pDevice, param);
+		spin_unlock_irq(&pDevice->lock);
 		break;
 	case VIAWGET_HOSTAPD_REMOVE_STA:
-	    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_REMOVE_STA \n");
-         spin_lock_irq(&pDevice->lock);
-		 ret = hostap_remove_sta(pDevice, param);
-         spin_unlock_irq(&pDevice->lock);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_REMOVE_STA \n");
+		spin_lock_irq(&pDevice->lock);
+		ret = hostap_remove_sta(pDevice, param);
+		spin_unlock_irq(&pDevice->lock);
 		break;
 	case VIAWGET_HOSTAPD_GET_INFO_STA:
-	    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_GET_INFO_STA \n");
-		 ret = hostap_get_info_sta(pDevice, param);
-		 ap_ioctl = 1;
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_GET_INFO_STA \n");
+		ret = hostap_get_info_sta(pDevice, param);
+		ap_ioctl = 1;
 		break;
 /*
 	case VIAWGET_HOSTAPD_RESET_TXEXC_STA:
-	    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_RESET_TXEXC_STA \n");
-		 ret = hostap_reset_txexc_sta(pDevice, param);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_RESET_TXEXC_STA \n");
+		ret = hostap_reset_txexc_sta(pDevice, param);
 		break;
 */
 	case VIAWGET_HOSTAPD_SET_FLAGS_STA:
-	    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_SET_FLAGS_STA \n");
-		 ret = hostap_set_flags_sta(pDevice, param);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_SET_FLAGS_STA \n");
+		ret = hostap_set_flags_sta(pDevice, param);
 		break;
 
 	case VIAWGET_HOSTAPD_MLME:
-	    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_MLME \n");
-	    return -EOPNOTSUPP;
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_MLME \n");
+		return -EOPNOTSUPP;
 
 	case VIAWGET_HOSTAPD_SET_GENERIC_ELEMENT:
-	    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_SET_GENERIC_ELEMENT \n");
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_SET_GENERIC_ELEMENT \n");
 		ret = hostap_set_generic_element(pDevice, param);
 		break;
 
 	case VIAWGET_HOSTAPD_SCAN_REQ:
-	    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_SCAN_REQ \n");
-	    return -EOPNOTSUPP;
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_SCAN_REQ \n");
+		return -EOPNOTSUPP;
 
 	case VIAWGET_HOSTAPD_STA_CLEAR_STATS:
-	    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_STA_CLEAR_STATS \n");
-	    return -EOPNOTSUPP;
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_STA_CLEAR_STATS \n");
+		return -EOPNOTSUPP;
 
 	default:
-	    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "vt6655_hostap_ioctl: unknown cmd=%d\n",
-		       (int)param->cmd);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "vt6655_hostap_ioctl: unknown cmd=%d\n",
+			(int)param->cmd);
 		return -EOPNOTSUPP;
 		break;
 	}
 
-
 	if ((ret == 0) && ap_ioctl) {
 		if (copy_to_user(p->pointer, param, p->length)) {
 			ret = -EFAULT;
@@ -849,9 +820,8 @@ int vt6655_hostap_ioctl(PSDevice pDevice, struct iw_point *p)
 		}
 	}
 
- out:
+out:
 	kfree(param);
 
 	return ret;
 }
-
diff --git a/drivers/staging/vt6655/hostap.h b/drivers/staging/vt6655/hostap.h
index 55db555..f1a4f2ef 100644
--- a/drivers/staging/vt6655/hostap.h
+++ b/drivers/staging/vt6655/hostap.h
@@ -46,7 +46,6 @@
 #define WLAN_RATE_48M   BIT10
 #define WLAN_RATE_54M   BIT11
 
-
 /*---------------------  Export Classes  ----------------------------*/
 
 /*---------------------  Export Variables  --------------------------*/
@@ -65,6 +64,3 @@ int vt6655_hostap_set_hostapd(PSDevice pDevice, int val, int rtnl_locked);
 int vt6655_hostap_ioctl(PSDevice pDevice, struct iw_point *p);
 
 #endif // __HOSTAP_H__
-
-
-
diff --git a/drivers/staging/vt6655/iocmd.h b/drivers/staging/vt6655/iocmd.h
index 166351b..e499f1b 100644
--- a/drivers/staging/vt6655/iocmd.h
+++ b/drivers/staging/vt6655/iocmd.h
@@ -37,7 +37,6 @@
 //typedef uint16_t u16;
 //typedef uint8_t u8;
 
-
 // ioctl Command code
 #define MAGIC_CODE	                 0x3142
 #define IOCTL_CMD_TEST	            (SIOCDEVPRIVATE + 0)
@@ -45,37 +44,34 @@
 #define IOCTL_CMD_HOSTAPD           (SIOCDEVPRIVATE + 2)
 #define IOCTL_CMD_WPA               (SIOCDEVPRIVATE + 3)
 
-
 typedef enum tagWMAC_CMD {
-
-    WLAN_CMD_BSS_SCAN,
-    WLAN_CMD_BSS_JOIN,
-    WLAN_CMD_DISASSOC,
-    WLAN_CMD_SET_WEP,
-    WLAN_CMD_GET_LINK,
-    WLAN_CMD_GET_LISTLEN,
-    WLAN_CMD_GET_LIST,
-    WLAN_CMD_GET_MIB,
-    WLAN_CMD_GET_STAT,
-    WLAN_CMD_STOP_MAC,
-    WLAN_CMD_START_MAC,
-    WLAN_CMD_AP_START,
-    WLAN_CMD_SET_HOSTAPD,
-    WLAN_CMD_SET_HOSTAPD_STA,
-    WLAN_CMD_SET_802_1X,
-    WLAN_CMD_SET_HOST_WEP,
-    WLAN_CMD_SET_WPA,
-    WLAN_CMD_GET_NODE_CNT,
-    WLAN_CMD_ZONETYPE_SET,
-    WLAN_CMD_GET_NODE_LIST
-
+	WLAN_CMD_BSS_SCAN,
+	WLAN_CMD_BSS_JOIN,
+	WLAN_CMD_DISASSOC,
+	WLAN_CMD_SET_WEP,
+	WLAN_CMD_GET_LINK,
+	WLAN_CMD_GET_LISTLEN,
+	WLAN_CMD_GET_LIST,
+	WLAN_CMD_GET_MIB,
+	WLAN_CMD_GET_STAT,
+	WLAN_CMD_STOP_MAC,
+	WLAN_CMD_START_MAC,
+	WLAN_CMD_AP_START,
+	WLAN_CMD_SET_HOSTAPD,
+	WLAN_CMD_SET_HOSTAPD_STA,
+	WLAN_CMD_SET_802_1X,
+	WLAN_CMD_SET_HOST_WEP,
+	WLAN_CMD_SET_WPA,
+	WLAN_CMD_GET_NODE_CNT,
+	WLAN_CMD_ZONETYPE_SET,
+	WLAN_CMD_GET_NODE_LIST
 } WMAC_CMD, *PWMAC_CMD;
 
 typedef enum tagWZONETYPE {
-  ZoneType_USA=0,
-  ZoneType_Japan=1,
-  ZoneType_Europe=2
-}WZONETYPE;
+	ZoneType_USA = 0,
+	ZoneType_Japan = 1,
+	ZoneType_Europe = 2
+} WZONETYPE;
 
 #define ADHOC	0
 #define INFRA	1
@@ -85,8 +81,7 @@ typedef enum tagWZONETYPE {
 #define ADHOC_STARTED	   1
 #define ADHOC_JOINTED	   2
 
-
-#define PHY80211a 	    0
+#define PHY80211a       0
 #define PHY80211b       1
 #define PHY80211g       2
 
@@ -115,25 +110,20 @@ typedef struct tagSCmdRequest {
 //
 
 typedef struct tagSCmdScan {
-
 	u8 ssid[SSID_MAXLEN + 2];
-
 } SCmdScan, *PSCmdScan;
 
-
 //
 // BSS Join
 //
 
 typedef struct tagSCmdBSSJoin {
-
-    u16	    wBSSType;
-    u16     wBBPType;
-    u8	    ssid[SSID_MAXLEN + 2];
-    u32	    uChannel;
-    bool bPSEnable;
-    bool bShareKeyAuth;
-
+	u16	    wBSSType;
+	u16     wBBPType;
+	u8	    ssid[SSID_MAXLEN + 2];
+	u32	    uChannel;
+	bool bPSEnable;
+	bool bShareKeyAuth;
 } SCmdBSSJoin, *PSCmdBSSJoin;
 
 //
@@ -141,83 +131,67 @@ typedef struct tagSCmdBSSJoin {
 //
 
 typedef struct tagSCmdZoneTypeSet {
-
- bool bWrite;
- WZONETYPE  ZoneType;
-
+	bool bWrite;
+	WZONETYPE  ZoneType;
 } SCmdZoneTypeSet, *PSCmdZoneTypeSet;
 
 #ifdef WPA_SM_Transtatus
 typedef struct tagSWPAResult {
-         char	ifname[100];
-         u8 proto;
-         u8 key_mgmt;
-         u8 eap_type;
-         bool authenticated;
+	char	ifname[100];
+	u8 proto;
+	u8 key_mgmt;
+	u8 eap_type;
+	bool authenticated;
 } SWPAResult, *PSWPAResult;
 #endif
 
 typedef struct tagSCmdStartAP {
-
-    u16	    wBSSType;
-    u16     wBBPType;
-    u8	    ssid[SSID_MAXLEN + 2];
-    u32	    uChannel;
-    u32     uBeaconInt;
-    bool bShareKeyAuth;
-    u8      byBasicRate;
-
+	u16	    wBSSType;
+	u16     wBBPType;
+	u8	    ssid[SSID_MAXLEN + 2];
+	u32	    uChannel;
+	u32     uBeaconInt;
+	bool bShareKeyAuth;
+	u8      byBasicRate;
 } SCmdStartAP, *PSCmdStartAP;
 
-
 typedef struct tagSCmdSetWEP {
-
-    bool bEnableWep;
-    u8      byKeyIndex;
-    u8      abyWepKey[WEP_NKEYS][WEP_KEYMAXLEN];
-    bool bWepKeyAvailable[WEP_NKEYS];
-    u32     auWepKeyLength[WEP_NKEYS];
-
+	bool bEnableWep;
+	u8      byKeyIndex;
+	u8      abyWepKey[WEP_NKEYS][WEP_KEYMAXLEN];
+	bool bWepKeyAvailable[WEP_NKEYS];
+	u32     auWepKeyLength[WEP_NKEYS];
 } SCmdSetWEP, *PSCmdSetWEP;
 
-
-
 typedef struct tagSBSSIDItem {
-
 	u32	    uChannel;
-    u8      abyBSSID[BSSID_LEN];
-    u8      abySSID[SSID_MAXLEN + 1];
-    //2006-1116-01,<Modify> by NomadZhao
-    //u16	    wBeaconInterval;
-    //u16	    wCapInfo;
-    //u8      byNetType;
-    u8      byNetType;
-    u16	    wBeaconInterval;
-    u16	    wCapInfo;        // for address of byNetType at align 4
-
-    bool bWEPOn;
-    u32     uRSSI;
-
+	u8      abyBSSID[BSSID_LEN];
+	u8      abySSID[SSID_MAXLEN + 1];
+	//2006-1116-01,<Modify> by NomadZhao
+	//u16	    wBeaconInterval;
+	//u16	    wCapInfo;
+	//u8      byNetType;
+	u8      byNetType;
+	u16	    wBeaconInterval;
+	u16	    wCapInfo;        // for address of byNetType at align 4
+
+	bool bWEPOn;
+	u32     uRSSI;
 } SBSSIDItem;
 
-
 typedef struct tagSBSSIDList {
-
 	u32		    uItem;
 	SBSSIDItem	sBSSIDList[0];
 } SBSSIDList, *PSBSSIDList;
 
-
 typedef struct tagSCmdLinkStatus {
-
-    bool bLink;
+	bool bLink;
 	u16   wBSSType;
 	u8      byState;
-    u8      abyBSSID[BSSID_LEN];
-    u8      abySSID[SSID_MAXLEN + 2];
-    u32     uChannel;
-    u32     uLinkRate;
-
+	u8      abyBSSID[BSSID_LEN];
+	u8      abySSID[SSID_MAXLEN + 2];
+	u32     uChannel;
+	u32     uLinkRate;
 } SCmdLinkStatus, *PSCmdLinkStatus;
 
 //
@@ -238,15 +212,13 @@ typedef struct tagSDot11MIBCount {
 	u32 FCSErrorCount;
 } SDot11MIBCount, *PSDot11MIBCount;
 
-
-
 //
 // statistic counter
 //
 typedef struct tagSStatMIBCount {
-    //
-    // ISR status count
-    //
+	//
+	// ISR status count
+	//
 	u32   dwIsrTx0OK;
 	u32   dwIsrTx1OK;
 	u32   dwIsrBeaconTxOK;
@@ -256,12 +228,12 @@ typedef struct tagSStatMIBCount {
 	u32   dwIsrUnrecoverableError;
 	u32   dwIsrSoftInterrupt;
 	u32   dwIsrRxNoBuf;
-    /////////////////////////////////////
+	/////////////////////////////////////
 
 	u32   dwIsrUnknown;               // unknown interrupt count
 
-    // RSR status count
-    //
+	// RSR status count
+	//
 	u32   dwRsrFrmAlgnErr;
 	u32   dwRsrErr;
 	u32   dwRsrCRCErr;
@@ -282,10 +254,10 @@ typedef struct tagSStatMIBCount {
 	u32   dwRsrBroadcast;
 	u32   dwRsrMulticast;
 	u32   dwRsrDirected;
-    // 64-bit OID
+	// 64-bit OID
 	u32   ullRsrOK;
 
-    // for some optional OIDs (64 bits) and DMI support
+	// for some optional OIDs (64 bits) and DMI support
 	u32   ullRxBroadcastBytes;
 	u32   ullRxMulticastBytes;
 	u32   ullRxDirectedBytes;
@@ -301,13 +273,13 @@ typedef struct tagSStatMIBCount {
 	u32   dwRsrRxFrmLen512_1023;
 	u32   dwRsrRxFrmLen1024_1518;
 
-    // TSR0,1 status count
-    //
+	// TSR0,1 status count
+	//
 	u32   dwTsrTotalRetry[2];        // total collision retry count
 	u32   dwTsrOnceRetry[2];         // this packet only occur one collision
 	u32   dwTsrMoreThanOnceRetry[2]; // this packet occur more than one collision
 	u32   dwTsrRetry[2];             // this packet has ever occur collision,
-                                       // that is (dwTsrOnceCollision0 + dwTsrMoreThanOnceCollision0)
+	// that is (dwTsrOnceCollision0 + dwTsrMoreThanOnceCollision0)
 	u32   dwTsrACKData[2];
 	u32   dwTsrErr[2];
 	u32   dwAllTsrOK[2];
@@ -320,23 +292,23 @@ typedef struct tagSStatMIBCount {
 	u32   dwTsrMulticast[2];
 	u32   dwTsrDirected[2];
 
-    // RD/TD count
+	// RD/TD count
 	u32   dwCntRxFrmLength;
 	u32   dwCntTxBufLength;
 
 	u8    abyCntRxPattern[16];
 	u8    abyCntTxPattern[16];
 
-    // Software check....
+	// Software check....
 	u32   dwCntRxDataErr;             // rx buffer data software compare CRC err count
 	u32   dwCntDecryptErr;            // rx buffer data software compare CRC err count
 	u32   dwCntRxICVErr;              // rx buffer data software compare CRC err count
 	u32    idxRxErrorDesc;             // index for rx data error RD
 
-    // 64-bit OID
+	// 64-bit OID
 	u32   ullTsrOK[2];
 
-    // for some optional OIDs (64 bits) and DMI support
+	// for some optional OIDs (64 bits) and DMI support
 	u32   ullTxBroadcastFrames[2];
 	u32   ullTxMulticastFrames[2];
 	u32   ullTxDirectedFrames[2];
@@ -345,49 +317,38 @@ typedef struct tagSStatMIBCount {
 	u32   ullTxDirectedBytes[2];
 } SStatMIBCount, *PSStatMIBCount;
 
-
 typedef struct tagSNodeItem {
-    // STA info
-    u16            wAID;
-    u8             abyMACAddr[6];
-    u16            wTxDataRate;
-    u16            wInActiveCount;
-    u16            wEnQueueCnt;
-    u16            wFlags;
-    bool bPWBitOn;
-    u8             byKeyIndex;
-    u16            wWepKeyLength;
-    u8            abyWepKey[WEP_KEYMAXLEN];
-    // Auto rate fallback vars
-    bool bIsInFallback;
-    u32            uTxFailures;
-    u32            uTxAttempts;
-    u16            wFailureRatio;
-
+	// STA info
+	u16            wAID;
+	u8             abyMACAddr[6];
+	u16            wTxDataRate;
+	u16            wInActiveCount;
+	u16            wEnQueueCnt;
+	u16            wFlags;
+	bool bPWBitOn;
+	u8             byKeyIndex;
+	u16            wWepKeyLength;
+	u8            abyWepKey[WEP_KEYMAXLEN];
+	// Auto rate fallback vars
+	bool bIsInFallback;
+	u32            uTxFailures;
+	u32            uTxAttempts;
+	u16            wFailureRatio;
 } SNodeItem;
 
-
 typedef struct tagSNodeList {
-
 	u32		    uItem;
 	SNodeItem	sNodeList[0];
-
 } SNodeList, *PSNodeList;
 
-
-
 typedef struct tagSCmdValue {
-
 	u32 dwValue;
-
 } SCmdValue,  *PSCmdValue;
 
-
 //
 // hostapd & viawget ioctl related
 //
 
-
 // VIAGWET_IOCTL_HOSTAPD ioctl() cmd:
 enum {
 	VIAWGET_HOSTAPD_FLUSH = 1,
@@ -404,14 +365,11 @@ enum {
 	VIAWGET_HOSTAPD_STA_CLEAR_STATS = 12,
 };
 
-
-#define VIAWGET_HOSTAPD_GENERIC_ELEMENT_HDR_LEN \
-((int) (&((struct viawget_hostapd_param *) 0)->u.generic_elem.data))
+#define VIAWGET_HOSTAPD_GENERIC_ELEMENT_HDR_LEN				\
+	((int)(&((struct viawget_hostapd_param *)0)->u.generic_elem.data))
 
 // Maximum length for algorithm names (-1 for nul termination) used in ioctl()
 
-
-
 struct viawget_hostapd_param {
 	u32 cmd;
 	u8 sta_addr[6];
@@ -464,12 +422,8 @@ struct viawget_hostapd_param {
 
 /*---------------------  Export Variables  --------------------------*/
 
-
 /*---------------------  Export Types  ------------------------------*/
 
-
 /*---------------------  Export Functions  --------------------------*/
 
-
-
 #endif //__IOCMD_H__
diff --git a/drivers/staging/vt6655/ioctl.c b/drivers/staging/vt6655/ioctl.c
index afed6e3..2ae8116 100644
--- a/drivers/staging/vt6655/ioctl.c
+++ b/drivers/staging/vt6655/ioctl.c
@@ -41,7 +41,7 @@
 static int msglevel = MSG_LEVEL_INFO;
 
 #ifdef WPA_SM_Transtatus
-	SWPAResult wpa_Result;
+SWPAResult wpa_Result;
 #endif
 
 int private_ioctl(PSDevice pDevice, struct ifreq *rq)
@@ -104,9 +104,9 @@ int private_ioctl(PSDevice pDevice, struct ifreq *rq)
 			BSSvClearBSSList((void *)pDevice, pDevice->bLinkPass);
 
 		if (pItemSSID->len != 0)
-			bScheduleCommand((void *) pDevice, WLAN_CMD_BSSID_SCAN, abyScanSSID);
+			bScheduleCommand((void *)pDevice, WLAN_CMD_BSSID_SCAN, abyScanSSID);
 		else
-			bScheduleCommand((void *) pDevice, WLAN_CMD_BSSID_SCAN, NULL);
+			bScheduleCommand((void *)pDevice, WLAN_CMD_BSSID_SCAN, NULL);
 		spin_unlock_irq(&pDevice->lock);
 		break;
 
@@ -202,8 +202,8 @@ int private_ioctl(PSDevice pDevice, struct ifreq *rq)
 		netif_stop_queue(pDevice->dev);
 		spin_lock_irq(&pDevice->lock);
 		pMgmt->eCurrState = WMAC_STATE_IDLE;
-		bScheduleCommand((void *) pDevice, WLAN_CMD_BSSID_SCAN, pMgmt->abyDesireSSID);
-		bScheduleCommand((void *) pDevice, WLAN_CMD_SSID, NULL);
+		bScheduleCommand((void *)pDevice, WLAN_CMD_BSSID_SCAN, pMgmt->abyDesireSSID);
+		bScheduleCommand((void *)pDevice, WLAN_CMD_SSID, NULL);
 		spin_unlock_irq(&pDevice->lock);
 		break;
 
@@ -267,7 +267,7 @@ int private_ioctl(PSDevice pDevice, struct ifreq *rq)
 			memcpy(sLinkStatus.abySSID, pItemSSID->abySSID, pItemSSID->len);
 			memcpy(sLinkStatus.abyBSSID, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN);
 			sLinkStatus.uLinkRate = pMgmt->sNodeDBTable[0].wTxDataRate;
-			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" Link Success!\n");
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " Link Success!\n");
 		} else {
 			sLinkStatus.bLink = false;
 			sLinkStatus.uLinkRate = 0;
@@ -311,7 +311,7 @@ int private_ioctl(PSDevice pDevice, struct ifreq *rq)
 		}
 		pList->uItem = sList.uItem;
 		pBSS = &(pMgmt->sBSSList[0]);
-		for (ii = 0, jj = 0; jj < MAX_BSS_NUM ; jj++) {
+		for (ii = 0, jj = 0; jj < MAX_BSS_NUM; jj++) {
 			pBSS = &(pMgmt->sBSSList[jj]);
 			if (pBSS->bActive) {
 				pList->sBSSIDList[ii].uChannel = pBSS->uChannel;
@@ -540,7 +540,7 @@ int private_ioctl(PSDevice pDevice, struct ifreq *rq)
 		}
 
 		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Support Rate= %*ph\n",
-				4, pMgmt->abyIBSSSuppRates + 2);
+			4, pMgmt->abyIBSSSuppRates + 2);
 
 		netif_stop_queue(pDevice->dev);
 		spin_lock_irq(&pDevice->lock);
diff --git a/drivers/staging/vt6655/ioctl.h b/drivers/staging/vt6655/ioctl.h
index ba85015..ae240fd 100644
--- a/drivers/staging/vt6655/ioctl.h
+++ b/drivers/staging/vt6655/ioctl.h
@@ -33,7 +33,6 @@
 
 /*---------------------  Export Definitions -------------------------*/
 
-
 /*---------------------  Export Classes  ----------------------------*/
 
 /*---------------------  Export Variables  --------------------------*/
@@ -43,15 +42,12 @@
 int private_ioctl(PSDevice pDevice, struct ifreq *rq);
 
 /*
-void vConfigWEPKey (
-    PSDevice pDevice,
-    unsigned long dwKeyIndex,
-    unsigned char *pbyKey,
-    unsigned long uKeyLength
-    );
+  void vConfigWEPKey(
+  PSDevice pDevice,
+  unsigned long dwKeyIndex,
+  unsigned char *pbyKey,
+  unsigned long uKeyLength
+);
 */
 
 #endif // __IOCTL_H__
-
-
-
diff --git a/drivers/staging/vt6655/iowpa.h b/drivers/staging/vt6655/iowpa.h
index 33ae054..bfea01f 100644
--- a/drivers/staging/vt6655/iowpa.h
+++ b/drivers/staging/vt6655/iowpa.h
@@ -31,17 +31,15 @@
 
 /*---------------------  Export Definitions -------------------------*/
 
-
 #define WPA_IE_LEN 64
 
-
 //WPA related
 /*
-typedef enum { WPA_ALG_NONE, WPA_ALG_WEP, WPA_ALG_TKIP, WPA_ALG_CCMP } wpa_alg;
-typedef enum { CIPHER_NONE, CIPHER_WEP40, CIPHER_TKIP, CIPHER_CCMP,
-	       CIPHER_WEP104 } wpa_cipher;
-typedef enum { KEY_MGMT_802_1X, KEY_MGMT_PSK, KEY_MGMT_NONE,
-	       KEY_MGMT_802_1X_NO_WPA, KEY_MGMT_WPA_NONE } wpa_key_mgmt;
+  typedef enum { WPA_ALG_NONE, WPA_ALG_WEP, WPA_ALG_TKIP, WPA_ALG_CCMP } wpa_alg;
+  typedef enum { CIPHER_NONE, CIPHER_WEP40, CIPHER_TKIP, CIPHER_CCMP,
+  CIPHER_WEP104 } wpa_cipher;
+  typedef enum { KEY_MGMT_802_1X, KEY_MGMT_PSK, KEY_MGMT_NONE,
+  KEY_MGMT_802_1X_NO_WPA, KEY_MGMT_WPA_NONE } wpa_key_mgmt;
 */
 
 enum {
@@ -54,10 +52,9 @@ enum {
 	VIAWGET_SET_DROP_UNENCRYPT = 7,
 	VIAWGET_SET_DEAUTHENTICATE = 8,
 	VIAWGET_SET_ASSOCIATE = 9,
-	VIAWGET_SET_DISASSOCIATE= 10
+	VIAWGET_SET_DISASSOCIATE = 10
 };
 
-
 enum {
 	VIAWGET_ASSOC_MSG = 1,
 	VIAWGET_DISASSOC_MSG = 2,
@@ -67,8 +64,6 @@ enum {
 	VIAWGET_DEVICECLOSE_MSG = 6
 };
 
-
-
 #pragma pack(1)
 typedef struct viawget_wpa_header {
 	u8 type;
@@ -76,8 +71,6 @@ typedef struct viawget_wpa_header {
 	u16 resp_ie_len;
 } viawget_wpa_header;
 
-
-
 struct viawget_wpa_param {
 	u32 cmd;
 	u8 addr[6];
@@ -88,27 +81,27 @@ struct viawget_wpa_param {
 		} generic_elem;
 
 		struct {
-        	u8 bssid[6];
+			u8 bssid[6];
 			u8 ssid[32];
 			u8 ssid_len;
-        	u8 *wpa_ie;
-        	u16 wpa_ie_len;
-        	int pairwise_suite;
-        	int group_suite;
-        	int key_mgmt_suite;
-        	int auth_alg;
-        	int mode;
+			u8 *wpa_ie;
+			u16 wpa_ie_len;
+			int pairwise_suite;
+			int group_suite;
+			int key_mgmt_suite;
+			int auth_alg;
+			int mode;
 
 		} wpa_associate;
 
 		struct {
-	        int alg_name;
-	        u16 key_index;
-	        u16 set_tx;
-	        u8 *seq;
-	        u16 seq_len;
-	        u8 *key;
-	        u16 key_len;
+			int alg_name;
+			u16 key_index;
+			u16 set_tx;
+			u8 *seq;
+			u16 seq_len;
+			u8 *key;
+			u16 key_len;
 		} wpa_key;
 
 		struct {
@@ -122,7 +115,6 @@ struct viawget_wpa_param {
 		} scan_results;
 
 	} u;
-
 };
 
 #pragma pack(1)
@@ -148,12 +140,8 @@ struct viawget_scan_result {
 
 /*---------------------  Export Variables  --------------------------*/
 
-
 /*---------------------  Export Types  ------------------------------*/
 
-
 /*---------------------  Export Functions  --------------------------*/
 
-
-
 #endif //__IOWPA_H__
diff --git a/drivers/staging/vt6655/iwctl.c b/drivers/staging/vt6655/iwctl.c
index 5cdda8d..9de698e 100644
--- a/drivers/staging/vt6655/iwctl.c
+++ b/drivers/staging/vt6655/iwctl.c
@@ -57,20 +57,17 @@ extern unsigned short TxRate_iwconfig;//2008-5-8 <add> by chester
 #endif
 
 static const long frequency_list[] = {
-    2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447, 2452, 2457, 2462, 2467, 2472, 2484,
-    4915, 4920, 4925, 4935, 4940, 4945, 4960, 4980,
-    5035, 5040, 5045, 5055, 5060, 5080, 5170, 5180, 5190, 5200, 5210, 5220, 5230, 5240,
-    5260, 5280, 5300, 5320, 5500, 5520, 5540, 5560, 5580, 5600, 5620, 5640, 5660, 5680,
-    5700, 5745, 5765, 5785, 5805, 5825
-	};
-
+	2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447, 2452, 2457, 2462, 2467, 2472, 2484,
+	4915, 4920, 4925, 4935, 4940, 4945, 4960, 4980,
+	5035, 5040, 5045, 5055, 5060, 5080, 5170, 5180, 5190, 5200, 5210, 5220, 5230, 5240,
+	5260, 5280, 5300, 5320, 5500, 5520, 5540, 5560, 5580, 5600, 5620, 5640, 5660, 5680,
+	5700, 5745, 5765, 5785, 5805, 5825
+};
 
 /*---------------------  Static Classes  ----------------------------*/
 
-
 //static int          msglevel                =MSG_LEVEL_DEBUG;
-static int          msglevel                =MSG_LEVEL_INFO;
-
+static int msglevel = MSG_LEVEL_INFO;
 
 /*---------------------  Static Variables  --------------------------*/
 /*---------------------  Static Functions  --------------------------*/
@@ -83,13 +80,13 @@ struct iw_statistics *iwctl_get_wireless_stats(struct net_device *dev)
 	long ldBm;
 
 	pDevice->wstats.status = pDevice->eOPMode;
-	#ifdef Calcu_LinkQual
-	   if(pDevice->scStatistic.LinkQuality > 100)
-   	       pDevice->scStatistic.LinkQuality = 100;
-               pDevice->wstats.qual.qual =(unsigned char) pDevice->scStatistic.LinkQuality;
-	#else
+#ifdef Calcu_LinkQual
+	if (pDevice->scStatistic.LinkQuality > 100)
+		pDevice->scStatistic.LinkQuality = 100;
+	pDevice->wstats.qual.qual = (unsigned char)pDevice->scStatistic.LinkQuality;
+#else
 	pDevice->wstats.qual.qual = pDevice->byCurrSQ;
-	#endif
+#endif
 	RFvRSSITodBm(pDevice, (unsigned char)(pDevice->uCurrRSSI), &ldBm);
 	pDevice->wstats.qual.level = ldBm;
 	//pDevice->wstats.qual.level = 0x100 - pDevice->uCurrRSSI;
@@ -105,29 +102,25 @@ struct iw_statistics *iwctl_get_wireless_stats(struct net_device *dev)
 	return &pDevice->wstats;
 }
 
-
-
 /*------------------------------------------------------------------*/
 
-
 static int iwctl_commit(struct net_device *dev,
-			      struct iw_request_info *info,
-			      void *wrq,
-			      char *extra)
+			struct iw_request_info *info,
+			void *wrq,
+			char *extra)
 {
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWCOMMIT \n");
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWCOMMIT \n");
 
 	return 0;
-
 }
 /*
  * Wireless Handler : get protocol name
  */
 
 int iwctl_giwname(struct net_device *dev,
-			 struct iw_request_info *info,
-			 char *wrq,
-			 char *extra)
+		  struct iw_request_info *info,
+		  char *wrq,
+		  char *extra)
 {
 	strcpy(wrq, "802.11-a/b/g");
 	return 0;
@@ -138,83 +131,77 @@ int iwctl_giwname(struct net_device *dev,
  */
 
 int iwctl_siwscan(struct net_device *dev,
-             struct iw_request_info *info,
-			 struct iw_point *wrq,
-             char *extra)
+		  struct iw_request_info *info,
+		  struct iw_point *wrq,
+		  char *extra)
 {
 	PSDevice	        pDevice = (PSDevice)netdev_priv(dev);
-	 PSMgmtObject        pMgmt = &(pDevice->sMgmtObj);
+	PSMgmtObject        pMgmt = &(pDevice->sMgmtObj);
 	struct iw_scan_req  *req = (struct iw_scan_req *)extra;
 	unsigned char abyScanSSID[WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1];
-	PWLAN_IE_SSID       pItemSSID=NULL;
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWSCAN \n");
+	PWLAN_IE_SSID pItemSSID = NULL;
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWSCAN \n");
 
-
-if(pDevice->byReAssocCount > 0) {   //reject scan when re-associating!
+	if (pDevice->byReAssocCount > 0) {   //reject scan when re-associating!
 //send scan event to wpa_Supplicant
-  union iwreq_data wrqu;
- PRINT_K("wireless_send_event--->SIOCGIWSCAN(scan done)\n");
- memset(&wrqu, 0, sizeof(wrqu));
- wireless_send_event(pDevice->dev, SIOCGIWSCAN, &wrqu, NULL);
-  return 0;
-}
+		union iwreq_data wrqu;
+		PRINT_K("wireless_send_event--->SIOCGIWSCAN(scan done)\n");
+		memset(&wrqu, 0, sizeof(wrqu));
+		wireless_send_event(pDevice->dev, SIOCGIWSCAN, &wrqu, NULL);
+		return 0;
+	}
 
 	spin_lock_irq(&pDevice->lock);
-	 BSSvClearBSSList((void *)pDevice, pDevice->bLinkPass);
+	BSSvClearBSSList((void *)pDevice, pDevice->bLinkPass);
 
 //mike add: active scan OR passive scan OR desire_ssid scan
- if(wrq->length == sizeof(struct iw_scan_req)) {
-   if (wrq->flags & IW_SCAN_THIS_ESSID)  {                               //desire_ssid scan
-       memset(abyScanSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
-       pItemSSID = (PWLAN_IE_SSID)abyScanSSID;
-       pItemSSID->byElementID = WLAN_EID_SSID;
-       memcpy(pItemSSID->abySSID, req->essid, (int)req->essid_len);
-         if (pItemSSID->abySSID[req->essid_len - 1] == '\0') {
-           if(req->essid_len>0)
-		pItemSSID->len = req->essid_len - 1;
-         }
-	else
-	  pItemSSID->len = req->essid_len;
-	  pMgmt->eScanType = WMAC_SCAN_PASSIVE;
-         PRINT_K("SIOCSIWSCAN:[desired_ssid=%s,len=%d]\n",((PWLAN_IE_SSID)abyScanSSID)->abySSID,
-		 	                                                                                ((PWLAN_IE_SSID)abyScanSSID)->len);
-	bScheduleCommand((void *) pDevice, WLAN_CMD_BSSID_SCAN, abyScanSSID);
-	spin_unlock_irq(&pDevice->lock);
+	if (wrq->length == sizeof(struct iw_scan_req)) {
+		if (wrq->flags & IW_SCAN_THIS_ESSID)  {                               //desire_ssid scan
+			memset(abyScanSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
+			pItemSSID = (PWLAN_IE_SSID)abyScanSSID;
+			pItemSSID->byElementID = WLAN_EID_SSID;
+			memcpy(pItemSSID->abySSID, req->essid, (int)req->essid_len);
+			if (pItemSSID->abySSID[req->essid_len - 1] == '\0') {
+				if (req->essid_len > 0)
+					pItemSSID->len = req->essid_len - 1;
+			} else
+				pItemSSID->len = req->essid_len;
+			pMgmt->eScanType = WMAC_SCAN_PASSIVE;
+			PRINT_K("SIOCSIWSCAN:[desired_ssid=%s,len=%d]\n", ((PWLAN_IE_SSID)abyScanSSID)->abySSID,
+				((PWLAN_IE_SSID)abyScanSSID)->len);
+			bScheduleCommand((void *)pDevice, WLAN_CMD_BSSID_SCAN, abyScanSSID);
+			spin_unlock_irq(&pDevice->lock);
+
+			return 0;
+		} else if (req->scan_type == IW_SCAN_TYPE_PASSIVE) {          //passive scan
+			pMgmt->eScanType = WMAC_SCAN_PASSIVE;
+		}
+	} else {           //active scan
+		pMgmt->eScanType = WMAC_SCAN_ACTIVE;
+	}
 
-	return 0;
-   }
-   else if(req->scan_type == IW_SCAN_TYPE_PASSIVE) {          //passive scan
-       pMgmt->eScanType = WMAC_SCAN_PASSIVE;
-   }
- }
- else {           //active scan
-     pMgmt->eScanType = WMAC_SCAN_ACTIVE;
- }
-
-	 pMgmt->eScanType = WMAC_SCAN_PASSIVE;
-          //printk("SIOCSIWSCAN:WLAN_CMD_BSSID_SCAN\n");
-	bScheduleCommand((void *) pDevice, WLAN_CMD_BSSID_SCAN, NULL);
+	pMgmt->eScanType = WMAC_SCAN_PASSIVE;
+	bScheduleCommand((void *)pDevice, WLAN_CMD_BSSID_SCAN, NULL);
 	spin_unlock_irq(&pDevice->lock);
 
 	return 0;
 }
 
-
 /*
  * Wireless Handler : get scan results
  */
 
 int iwctl_giwscan(struct net_device *dev,
-             struct iw_request_info *info,
-			 struct iw_point *wrq,
-             char *extra)
+		  struct iw_request_info *info,
+		  struct iw_point *wrq,
+		  char *extra)
 {
-    int ii, jj, kk;
+	int ii, jj, kk;
 	PSDevice	        pDevice = (PSDevice)netdev_priv(dev);
-    PSMgmtObject        pMgmt = &(pDevice->sMgmtObj);
-    PKnownBSS           pBSS;
-    PWLAN_IE_SSID       pItemSSID;
-    PWLAN_IE_SUPP_RATES pSuppRates, pExtSuppRates;
+	PSMgmtObject        pMgmt = &(pDevice->sMgmtObj);
+	PKnownBSS           pBSS;
+	PWLAN_IE_SSID       pItemSSID;
+	PWLAN_IE_SUPP_RATES pSuppRates, pExtSuppRates;
 	char *current_ev = extra;
 	char *end_buf = extra + IW_SCAN_MAX_DATA;
 	char *current_val = NULL;
@@ -222,181 +209,177 @@ int iwctl_giwscan(struct net_device *dev,
 	long ldBm;
 	char buf[MAX_WPA_IE_LEN * 2 + 30];
 
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWSCAN \n");
 
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWSCAN \n");
-
-    if (pMgmt->eScanState ==  WMAC_IS_SCANNING) {
-        // In scanning..
+	if (pMgmt->eScanState ==  WMAC_IS_SCANNING) {
+		// In scanning..
 		return -EAGAIN;
 	}
 	pBSS = &(pMgmt->sBSSList[0]);
-    for (ii = 0, jj = 0; jj < MAX_BSS_NUM ; jj++) {
+	for (ii = 0, jj = 0; jj < MAX_BSS_NUM; jj++) {
 		if (current_ev >= end_buf)
 			break;
-        pBSS = &(pMgmt->sBSSList[jj]);
-        if (pBSS->bActive) {
-		//ADD mac address
-		    memset(&iwe, 0, sizeof(iwe));
-		    iwe.cmd = SIOCGIWAP;
-		    iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
+		pBSS = &(pMgmt->sBSSList[jj]);
+		if (pBSS->bActive) {
+			//ADD mac address
+			memset(&iwe, 0, sizeof(iwe));
+			iwe.cmd = SIOCGIWAP;
+			iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
 			memcpy(iwe.u.ap_addr.sa_data, pBSS->abyBSSID, WLAN_BSSID_LEN);
-                            current_ev = iwe_stream_add_event(info,current_ev,end_buf, &iwe, IW_EV_ADDR_LEN);
-                 //ADD ssid
-	             memset(&iwe, 0, sizeof(iwe));
-                      iwe.cmd = SIOCGIWESSID;
-                      pItemSSID = (PWLAN_IE_SSID)pBSS->abySSID;
-                       iwe.u.data.length = pItemSSID->len;
-                       iwe.u.data.flags = 1;
-                      current_ev = iwe_stream_add_point(info,current_ev,end_buf, &iwe, pItemSSID->abySSID);
-		//ADD mode
-		    memset(&iwe, 0, sizeof(iwe));
-		    iwe.cmd = SIOCGIWMODE;
-            if (WLAN_GET_CAP_INFO_ESS(pBSS->wCapInfo)) {
-		        iwe.u.mode = IW_MODE_INFRA;
-            }
-            else {
-                iwe.u.mode = IW_MODE_ADHOC;
-		    }
-	        iwe.len = IW_EV_UINT_LEN;
-                      current_ev = iwe_stream_add_event(info,current_ev, end_buf, &iwe,  IW_EV_UINT_LEN);
-           //ADD frequency
-            pSuppRates = (PWLAN_IE_SUPP_RATES)pBSS->abySuppRates;
-            pExtSuppRates = (PWLAN_IE_SUPP_RATES)pBSS->abyExtSuppRates;
-            memset(&iwe, 0, sizeof(iwe));
-           	iwe.cmd = SIOCGIWFREQ;
-           	iwe.u.freq.m = pBSS->uChannel;
-           	iwe.u.freq.e = 0;
-           	iwe.u.freq.i = 0;
-                   current_ev = iwe_stream_add_event(info,current_ev,end_buf, &iwe, IW_EV_FREQ_LEN);
-            //2008-0409-04, <Add> by Einsn Liu
+			current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_ADDR_LEN);
+			//ADD ssid
+			memset(&iwe, 0, sizeof(iwe));
+			iwe.cmd = SIOCGIWESSID;
+			pItemSSID = (PWLAN_IE_SSID)pBSS->abySSID;
+			iwe.u.data.length = pItemSSID->len;
+			iwe.u.data.flags = 1;
+			current_ev = iwe_stream_add_point(info, current_ev, end_buf, &iwe, pItemSSID->abySSID);
+			//ADD mode
+			memset(&iwe, 0, sizeof(iwe));
+			iwe.cmd = SIOCGIWMODE;
+			if (WLAN_GET_CAP_INFO_ESS(pBSS->wCapInfo)) {
+				iwe.u.mode = IW_MODE_INFRA;
+			} else {
+				iwe.u.mode = IW_MODE_ADHOC;
+			}
+			iwe.len = IW_EV_UINT_LEN;
+			current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_UINT_LEN);
+			//ADD frequency
+			pSuppRates = (PWLAN_IE_SUPP_RATES)pBSS->abySuppRates;
+			pExtSuppRates = (PWLAN_IE_SUPP_RATES)pBSS->abyExtSuppRates;
+			memset(&iwe, 0, sizeof(iwe));
+			iwe.cmd = SIOCGIWFREQ;
+			iwe.u.freq.m = pBSS->uChannel;
+			iwe.u.freq.e = 0;
+			iwe.u.freq.i = 0;
+			current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_FREQ_LEN);
+			//2008-0409-04, <Add> by Einsn Liu
 			{
-			int f = (int)pBSS->uChannel - 1;
-			if(f < 0)f = 0;
-			iwe.u.freq.m = frequency_list[f] * 100000;
-			iwe.u.freq.e = 1;
+				int f = (int)pBSS->uChannel - 1;
+				if (f < 0)f = 0;
+				iwe.u.freq.m = frequency_list[f] * 100000;
+				iwe.u.freq.e = 1;
 			}
-                   current_ev = iwe_stream_add_event(info,current_ev,end_buf, &iwe, IW_EV_FREQ_LEN);
-       		//ADD quality
-            memset(&iwe, 0, sizeof(iwe));
-	        iwe.cmd = IWEVQUAL;
-	        RFvRSSITodBm(pDevice, (unsigned char)(pBSS->uRSSI), &ldBm);
-		    iwe.u.qual.level = ldBm;
-	        iwe.u.qual.noise = 0;
+			current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_FREQ_LEN);
+			//ADD quality
+			memset(&iwe, 0, sizeof(iwe));
+			iwe.cmd = IWEVQUAL;
+			RFvRSSITodBm(pDevice, (unsigned char)(pBSS->uRSSI), &ldBm);
+			iwe.u.qual.level = ldBm;
+			iwe.u.qual.noise = 0;
 //2008-0409-01, <Add> by Einsn Liu
-			if(-ldBm<50){
+			if (-ldBm < 50) {
 				iwe.u.qual.qual = 100;
-			}else  if(-ldBm > 90) {
-				 iwe.u.qual.qual = 0;
-			}else {
-				iwe.u.qual.qual=(40-(-ldBm-50))*100/40;
+			} else if (-ldBm > 90) {
+				iwe.u.qual.qual = 0;
+			} else {
+				iwe.u.qual.qual = (40 - (-ldBm - 50)) * 100 / 40;
+			}
+			iwe.u.qual.updated = 7;
+
+			//  iwe.u.qual.qual = 0;
+			current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_QUAL_LEN);
+
+			memset(&iwe, 0, sizeof(iwe));
+			iwe.cmd = SIOCGIWENCODE;
+			iwe.u.data.length = 0;
+			if (WLAN_GET_CAP_INFO_PRIVACY(pBSS->wCapInfo)) {
+				iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
+			} else {
+				iwe.u.data.flags = IW_ENCODE_DISABLED;
+			}
+			current_ev = iwe_stream_add_point(info, current_ev, end_buf, &iwe, pItemSSID->abySSID);
+
+			memset(&iwe, 0, sizeof(iwe));
+			iwe.cmd = SIOCGIWRATE;
+			iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
+			current_val = current_ev + IW_EV_LCP_LEN;
+
+			for (kk = 0; kk < 12; kk++) {
+				if (pSuppRates->abyRates[kk] == 0)
+					break;
+				// Bit rate given in 500 kb/s units (+ 0x80)
+				iwe.u.bitrate.value = ((pSuppRates->abyRates[kk] & 0x7f) * 500000);
+				current_val = iwe_stream_add_value(info, current_ev, current_val, end_buf, &iwe, IW_EV_PARAM_LEN);
 			}
-			iwe.u.qual.updated=7;
-
-	      //  iwe.u.qual.qual = 0;
-            current_ev = iwe_stream_add_event(info,current_ev, end_buf, &iwe, IW_EV_QUAL_LEN);
-
-            memset(&iwe, 0, sizeof(iwe));
-            iwe.cmd = SIOCGIWENCODE;
-            iwe.u.data.length = 0;
-            if (WLAN_GET_CAP_INFO_PRIVACY(pBSS->wCapInfo)) {
-                iwe.u.data.flags =IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
-            }else {
-                iwe.u.data.flags = IW_ENCODE_DISABLED;
-            }
-            current_ev = iwe_stream_add_point(info,current_ev,end_buf, &iwe, pItemSSID->abySSID);
-
-            memset(&iwe, 0, sizeof(iwe));
-            iwe.cmd = SIOCGIWRATE;
-           	iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
-      		current_val = current_ev + IW_EV_LCP_LEN;
-
-       		for (kk = 0 ; kk < 12 ; kk++) {
-		        if (pSuppRates->abyRates[kk] == 0)
-			        break;
-		        // Bit rate given in 500 kb/s units (+ 0x80)
-		        iwe.u.bitrate.value = ((pSuppRates->abyRates[kk] & 0x7f) * 500000);
-                           current_val = iwe_stream_add_value(info,current_ev, current_val, end_buf, &iwe, IW_EV_PARAM_LEN);
+			for (kk = 0; kk < 8; kk++) {
+				if (pExtSuppRates->abyRates[kk] == 0)
+					break;
+				// Bit rate given in 500 kb/s units (+ 0x80)
+				iwe.u.bitrate.value = ((pExtSuppRates->abyRates[kk] & 0x7f) * 500000);
+				current_val = iwe_stream_add_value(info, current_ev, current_val, end_buf, &iwe, IW_EV_PARAM_LEN);
+			}
+
+			if ((current_val - current_ev) > IW_EV_LCP_LEN)
+				current_ev = current_val;
+
+			memset(&iwe, 0, sizeof(iwe));
+			iwe.cmd = IWEVCUSTOM;
+			sprintf(buf, "bcn_int=%d", pBSS->wBeaconInterval);
+			iwe.u.data.length = strlen(buf);
+			current_ev = iwe_stream_add_point(info, current_ev, end_buf, &iwe, buf);
+
+			if ((pBSS->wWPALen > 0) && (pBSS->wWPALen <= MAX_WPA_IE_LEN)) {
+				memset(&iwe, 0, sizeof(iwe));
+				iwe.cmd = IWEVGENIE;
+				iwe.u.data.length = pBSS->wWPALen;
+				current_ev = iwe_stream_add_point(info, current_ev, end_buf, &iwe, pBSS->byWPAIE);
+			}
+
+			if ((pBSS->wRSNLen > 0) && (pBSS->wRSNLen <= MAX_WPA_IE_LEN)) {
+				memset(&iwe, 0, sizeof(iwe));
+				iwe.cmd = IWEVGENIE;
+				iwe.u.data.length = pBSS->wRSNLen;
+				current_ev = iwe_stream_add_point(info, current_ev, end_buf, &iwe, pBSS->byRSNIE);
+			}
+
 		}
-       		for (kk = 0 ; kk < 8 ; kk++) {
-		        if (pExtSuppRates->abyRates[kk] == 0)
-			        break;
-		        // Bit rate given in 500 kb/s units (+ 0x80)
-		        iwe.u.bitrate.value = ((pExtSuppRates->abyRates[kk] & 0x7f) * 500000);
-                          current_val = iwe_stream_add_value(info,current_ev, current_val, end_buf, &iwe, IW_EV_PARAM_LEN);
-	        }
-
-	        if((current_val - current_ev) > IW_EV_LCP_LEN)
-		        current_ev = current_val;
-
-            memset(&iwe, 0, sizeof(iwe));
-            iwe.cmd = IWEVCUSTOM;
-            sprintf(buf, "bcn_int=%d", pBSS->wBeaconInterval);
-            iwe.u.data.length = strlen(buf);
-             current_ev = iwe_stream_add_point(info,current_ev, end_buf, &iwe, buf);
-
-            if ((pBSS->wWPALen > 0) && (pBSS->wWPALen <= MAX_WPA_IE_LEN)) {
-                memset(&iwe, 0, sizeof(iwe));
-                iwe.cmd = IWEVGENIE;
-                iwe.u.data.length = pBSS->wWPALen;
-                current_ev = iwe_stream_add_point(info,current_ev, end_buf, &iwe, pBSS->byWPAIE);
-            }
-
-            if ((pBSS->wRSNLen > 0) && (pBSS->wRSNLen <= MAX_WPA_IE_LEN)) {
-                memset(&iwe, 0, sizeof(iwe));
-                iwe.cmd = IWEVGENIE;
-                iwe.u.data.length = pBSS->wRSNLen;
-                current_ev = iwe_stream_add_point(info,current_ev, end_buf, &iwe, pBSS->byRSNIE);
-            }
-
-        }
-    }// for
+	}// for
 
 	wrq->length = current_ev - extra;
 	return 0;
-
 }
 
-
 /*
  * Wireless Handler : set frequency or channel
  */
 
 int iwctl_siwfreq(struct net_device *dev,
-             struct iw_request_info *info,
-             struct iw_freq *wrq,
-             char *extra)
+		  struct iw_request_info *info,
+		  struct iw_freq *wrq,
+		  char *extra)
 {
 	PSDevice	        pDevice = (PSDevice)netdev_priv(dev);
 	int rc = 0;
 
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWFREQ \n");
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWFREQ \n");
 
 	// If setting by frequency, convert to a channel
-	if((wrq->e == 1) &&
-	   (wrq->m >= (int) 2.412e8) &&
-	   (wrq->m <= (int) 2.487e8)) {
+	if ((wrq->e == 1) &&
+	    (wrq->m >= (int) 2.412e8) &&
+	    (wrq->m <= (int) 2.487e8)) {
 		int f = wrq->m / 100000;
 		int c = 0;
-		while((c < 14) && (f != frequency_list[c]))
+		while ((c < 14) && (f != frequency_list[c]))
 			c++;
 		wrq->e = 0;
 		wrq->m = c + 1;
 	}
 	// Setting by channel number
-	if((wrq->m > 14) || (wrq->e > 0))
+	if ((wrq->m > 14) || (wrq->e > 0))
 		rc = -EOPNOTSUPP;
 	else {
 		int channel = wrq->m;
-		if((channel < 1) || (channel > 14)) {
+		if ((channel < 1) || (channel > 14)) {
 			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: New channel value of %d is invalid!\n", dev->name, wrq->m);
 			rc = -EINVAL;
 		} else {
-			  // Yes ! We can set it !!!
-              DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " Set to channel = %d\n", channel);
-			  pDevice->uChannel = channel;
- 			 //2007-0207-04,<Add> by EinsnLiu
-			 //Make change effect at once
-			  pDevice->bCommit = true;
+			// Yes ! We can set it !!!
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " Set to channel = %d\n", channel);
+			pDevice->uChannel = channel;
+			//2007-0207-04,<Add> by EinsnLiu
+			//Make change effect at once
+			pDevice->bCommit = true;
 		}
 	}
 
@@ -408,14 +391,14 @@ int iwctl_siwfreq(struct net_device *dev,
  */
 
 int iwctl_giwfreq(struct net_device *dev,
-             struct iw_request_info *info,
-             struct iw_freq *wrq,
-             char *extra)
+		  struct iw_request_info *info,
+		  struct iw_freq *wrq,
+		  char *extra)
 {
 	PSDevice	        pDevice = (PSDevice)netdev_priv(dev);
-    PSMgmtObject        pMgmt = &(pDevice->sMgmtObj);
+	PSMgmtObject        pMgmt = &(pDevice->sMgmtObj);
 
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWFREQ \n");
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWFREQ \n");
 
 #ifdef WEXT_USECHANNELS
 	wrq->m = (int)pMgmt->uCurrChannel;
@@ -423,8 +406,8 @@ int iwctl_giwfreq(struct net_device *dev,
 #else
 	{
 		int f = (int)pMgmt->uCurrChannel - 1;
-		if(f < 0)
-		   f = 0;
+		if (f < 0)
+			f = 0;
 		wrq->m = frequency_list[f] * 100000;
 		wrq->e = 1;
 	}
@@ -438,59 +421,58 @@ int iwctl_giwfreq(struct net_device *dev,
  */
 
 int iwctl_siwmode(struct net_device *dev,
-             struct iw_request_info *info,
-             __u32 *wmode,
-             char *extra)
+		  struct iw_request_info *info,
+		  __u32 *wmode,
+		  char *extra)
 {
 	PSDevice	        pDevice = (PSDevice)netdev_priv(dev);
-    PSMgmtObject        pMgmt = &(pDevice->sMgmtObj);
-    int rc = 0;
-
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWMODE \n");
+	PSMgmtObject        pMgmt = &(pDevice->sMgmtObj);
+	int rc = 0;
 
-    if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP && pDevice->bEnableHostapd) {
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Can't set operation mode, hostapd is running \n");
-        return rc;
-    }
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWMODE \n");
 
-	switch(*wmode) {
+	if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP && pDevice->bEnableHostapd) {
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Can't set operation mode, hostapd is running \n");
+		return rc;
+	}
 
+	switch (*wmode) {
 	case IW_MODE_ADHOC:
-	    if (pMgmt->eConfigMode != WMAC_CONFIG_IBSS_STA) {
-            pMgmt->eConfigMode = WMAC_CONFIG_IBSS_STA;
-            if (pDevice->flags & DEVICE_FLAGS_OPENED) {
-		        pDevice->bCommit = true;
-   		    }
+		if (pMgmt->eConfigMode != WMAC_CONFIG_IBSS_STA) {
+			pMgmt->eConfigMode = WMAC_CONFIG_IBSS_STA;
+			if (pDevice->flags & DEVICE_FLAGS_OPENED) {
+				pDevice->bCommit = true;
+			}
 		}
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "set mode to ad-hoc \n");
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "set mode to ad-hoc \n");
 		break;
 	case IW_MODE_AUTO:
 	case IW_MODE_INFRA:
-	    if (pMgmt->eConfigMode != WMAC_CONFIG_ESS_STA) {
-            pMgmt->eConfigMode = WMAC_CONFIG_ESS_STA;
-            if (pDevice->flags & DEVICE_FLAGS_OPENED) {
-		        pDevice->bCommit = true;
-   		    }
+		if (pMgmt->eConfigMode != WMAC_CONFIG_ESS_STA) {
+			pMgmt->eConfigMode = WMAC_CONFIG_ESS_STA;
+			if (pDevice->flags & DEVICE_FLAGS_OPENED) {
+				pDevice->bCommit = true;
+			}
 		}
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "set mode to infrastructure \n");
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "set mode to infrastructure \n");
 		break;
 	case IW_MODE_MASTER:
 
-        pMgmt->eConfigMode = WMAC_CONFIG_ESS_STA;
+		pMgmt->eConfigMode = WMAC_CONFIG_ESS_STA;
 		rc = -EOPNOTSUPP;
 		break;
 
-	    if (pMgmt->eConfigMode != WMAC_CONFIG_AP) {
-            pMgmt->eConfigMode = WMAC_CONFIG_AP;
-            if (pDevice->flags & DEVICE_FLAGS_OPENED) {
-		        pDevice->bCommit = true;
-   		    }
+		if (pMgmt->eConfigMode != WMAC_CONFIG_AP) {
+			pMgmt->eConfigMode = WMAC_CONFIG_AP;
+			if (pDevice->flags & DEVICE_FLAGS_OPENED) {
+				pDevice->bCommit = true;
+			}
 		}
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "set mode to Access Point \n");
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "set mode to Access Point \n");
 		break;
 
 	case IW_MODE_REPEAT:
-        pMgmt->eConfigMode = WMAC_CONFIG_ESS_STA;
+		pMgmt->eConfigMode = WMAC_CONFIG_ESS_STA;
 		rc = -EOPNOTSUPP;
 		break;
 	default:
@@ -505,22 +487,21 @@ int iwctl_siwmode(struct net_device *dev,
  */
 
 int iwctl_giwmode(struct net_device *dev,
-             struct iw_request_info *info,
-             __u32 *wmode,
-             char *extra)
+		  struct iw_request_info *info,
+		  __u32 *wmode,
+		  char *extra)
 {
 	PSDevice	        pDevice = (PSDevice)netdev_priv(dev);
-    PSMgmtObject        pMgmt = &(pDevice->sMgmtObj);
-
+	PSMgmtObject        pMgmt = &(pDevice->sMgmtObj);
 
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWMODE \n");
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWMODE \n");
 	// If not managed, assume it's ad-hoc
 	switch (pMgmt->eConfigMode) {
 	case WMAC_CONFIG_ESS_STA:
 		*wmode = IW_MODE_INFRA;
 		break;
 	case WMAC_CONFIG_IBSS_STA:
-        *wmode = IW_MODE_ADHOC;
+		*wmode = IW_MODE_ADHOC;
 		break;
 	case WMAC_CONFIG_AUTO:
 		*wmode = IW_MODE_INFRA;
@@ -535,22 +516,20 @@ int iwctl_giwmode(struct net_device *dev,
 	return 0;
 }
 
-
 /*
  * Wireless Handler : get capability range
  */
 
 int iwctl_giwrange(struct net_device *dev,
-             struct iw_request_info *info,
-             struct iw_point *wrq,
-             char *extra)
+		   struct iw_request_info *info,
+		   struct iw_point *wrq,
+		   char *extra)
 {
-	struct iw_range *range = (struct iw_range *) extra;
-	int		i,k;
-    unsigned char abySupportedRates[13]= {0x02, 0x04, 0x0B, 0x16, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6C, 0x90};
-
+	struct iw_range *range = (struct iw_range *)extra;
+	int i, k;
+	unsigned char abySupportedRates[13] = {0x02, 0x04, 0x0B, 0x16, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6C, 0x90};
 
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWRANGE \n");
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWRANGE \n");
 	if (wrq->pointer) {
 		wrq->length = sizeof(struct iw_range);
 		memset(range, 0, sizeof(struct iw_range));
@@ -560,25 +539,25 @@ int iwctl_giwrange(struct net_device *dev,
 		// Should be based on cap_rid.country to give only
 		//  what the current card support
 		k = 0;
-		for(i = 0; i < 14; i++) {
+		for (i = 0; i < 14; i++) {
 			range->freq[k].i = i + 1; // List index
 			range->freq[k].m = frequency_list[i] * 100000;
 			range->freq[k++].e = 1;	// Values in table in MHz -> * 10^5 * 10
 		}
 		range->num_frequency = k;
 		// Hum... Should put the right values there
-	     #ifdef Calcu_LinkQual
-                 range->max_qual.qual = 100;
-	     #else
+#ifdef Calcu_LinkQual
+		range->max_qual.qual = 100;
+#else
 		range->max_qual.qual = 255;
-	     #endif
+#endif
 		range->max_qual.level = 0;
 		range->max_qual.noise = 0;
 		range->sensitivity = 255;
 
-		for(i = 0 ; i < 13 ; i++) {
+		for (i = 0; i < 13; i++) {
 			range->bitrate[i] = abySupportedRates[i] * 500000;
-			if(range->bitrate[i] == 0)
+			if (range->bitrate[i] == 0)
 				break;
 		}
 		range->num_bitrates = i;
@@ -586,7 +565,7 @@ int iwctl_giwrange(struct net_device *dev,
 		// Set an indication of the max TCP throughput
 		// in bit/s that we can expect using this interface.
 		//  May be use for QoS stuff... Jean II
-		if(i > 2)
+		if (i > 2)
 			range->throughput = 5 * 1000 * 1000;
 		else
 			range->throughput = 1.5 * 1000 * 1000;
@@ -596,20 +575,19 @@ int iwctl_giwrange(struct net_device *dev,
 		range->min_frag = 256;
 		range->max_frag = 2312;
 
+		// the encoding capabilities
+		range->num_encoding_sizes = 3;
+		// 64(40) bits WEP
+		range->encoding_size[0] = 5;
+		// 128(104) bits WEP
+		range->encoding_size[1] = 13;
+		// 256 bits for WPA-PSK
+		range->encoding_size[2] = 32;
+		// 4 keys are allowed
+		range->max_encoding_tokens = 4;
 
-	    // the encoding capabilities
-	    range->num_encoding_sizes = 3;
-	    // 64(40) bits WEP
-	    range->encoding_size[0] = 5;
-	    // 128(104) bits WEP
-	    range->encoding_size[1] = 13;
-	    // 256 bits for WPA-PSK
-	    range->encoding_size[2] = 32;
-	    // 4 keys are allowed
-	    range->max_encoding_tokens = 4;
-
-	    range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
-		    IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
+		range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
+			IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
 
 		range->min_pmp = 0;
 		range->max_pmp = 1000000;// 1 secs
@@ -621,7 +599,7 @@ int iwctl_giwrange(struct net_device *dev,
 
 		// Transmit Power - values are in mW
 
-        range->txpower[0] = 100;
+		range->txpower[0] = 100;
 		range->num_txpower = 1;
 		range->txpower_capa = IW_TXPOW_MWATT;
 		range->we_version_source = SUPPORTED_WIRELESS_EXT;
@@ -641,65 +619,63 @@ int iwctl_giwrange(struct net_device *dev,
 		range->avg_qual.noise = 0;
 	}
 
-
 	return 0;
 }
 
-
 /*
  * Wireless Handler : set ap mac address
  */
 
 int iwctl_siwap(struct net_device *dev,
-             struct iw_request_info *info,
-			 struct sockaddr *wrq,
-             char *extra)
+		struct iw_request_info *info,
+		struct sockaddr *wrq,
+		char *extra)
 {
 	PSDevice	        pDevice = (PSDevice)netdev_priv(dev);
-    PSMgmtObject        pMgmt = &(pDevice->sMgmtObj);
-    int rc = 0;
-    unsigned char ZeroBSSID[WLAN_BSSID_LEN]={0x00,0x00,0x00,0x00,0x00,0x00};
-
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWAP \n");
-if (pMgmt->eScanState ==  WMAC_IS_SCANNING) {
-        // In scanning..
-     printk("SIOCSIWAP(??)-->In scanning...\n");
-   //  return -EAGAIN;
-  }
+	PSMgmtObject        pMgmt = &(pDevice->sMgmtObj);
+	int rc = 0;
+	unsigned char ZeroBSSID[WLAN_BSSID_LEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWAP \n");
+	if (pMgmt->eScanState ==  WMAC_IS_SCANNING) {
+		// In scanning..
+		printk("SIOCSIWAP(??)-->In scanning...\n");
+		//  return -EAGAIN;
+	}
 	if (wrq->sa_family != ARPHRD_ETHER)
 		rc = -EINVAL;
 	else {
 		memcpy(pMgmt->abyDesireBSSID, wrq->sa_data, 6);
-		                //2008-0409-05, <Add> by Einsn Liu
-		if((pDevice->bLinkPass == true) &&
-                     (memcmp(pMgmt->abyDesireBSSID, pMgmt->abyCurrBSSID, 6)== 0)){
+		//2008-0409-05, <Add> by Einsn Liu
+		if ((pDevice->bLinkPass == true) &&
+		    (memcmp(pMgmt->abyDesireBSSID, pMgmt->abyCurrBSSID, 6) == 0)) {
 			return rc;
+		}
+		//mike :add
+		if ((is_broadcast_ether_addr(pMgmt->abyDesireBSSID)) ||
+		    (memcmp(pMgmt->abyDesireBSSID, ZeroBSSID, 6) == 0)) {
+			PRINT_K("SIOCSIWAP:invalid desired BSSID return!\n");
+			return rc;
+		}
+		//mike add: if desired AP is hidden ssid(there are two same BSSID in list),
+		//                  then ignore,because you don't known which one to be connect with??
+		{
+			unsigned int ii, uSameBssidNum = 0;
+			for (ii = 0; ii < MAX_BSS_NUM; ii++) {
+				if (pMgmt->sBSSList[ii].bActive &&
+				    !compare_ether_addr(pMgmt->sBSSList[ii].abyBSSID, pMgmt->abyDesireBSSID)) {
+					uSameBssidNum++;
+				}
+			}
+			if (uSameBssidNum >= 2) {  //hit: desired AP is in hidden ssid mode!!!
+				PRINT_K("SIOCSIWAP:ignore for desired AP in hidden mode\n");
+				return rc;
 			}
-	//mike :add
-	 if ((is_broadcast_ether_addr(pMgmt->abyDesireBSSID)) ||
-	     (memcmp(pMgmt->abyDesireBSSID, ZeroBSSID, 6) == 0)){
-	      PRINT_K("SIOCSIWAP:invalid desired BSSID return!\n");
-               return rc;
-         }
-       //mike add: if desired AP is hidden ssid(there are two same BSSID in list),
-       //                  then ignore,because you don't known which one to be connect with??
-       	{
-           unsigned int ii , uSameBssidNum=0;
-                  for (ii = 0; ii < MAX_BSS_NUM; ii++) {
-                     if (pMgmt->sBSSList[ii].bActive &&
-                        !compare_ether_addr(pMgmt->sBSSList[ii].abyBSSID, pMgmt->abyDesireBSSID)) {
-                        uSameBssidNum++;
-                     }
-                  }
-	     if(uSameBssidNum >= 2) {  //hit: desired AP is in hidden ssid mode!!!
-                 PRINT_K("SIOCSIWAP:ignore for desired AP in hidden mode\n");
-	        return rc;
-	     }
-       	}
-
-        if (pDevice->flags & DEVICE_FLAGS_OPENED) {
-		    pDevice->bCommit = true;
-   		}
+		}
+
+		if (pDevice->flags & DEVICE_FLAGS_OPENED) {
+			pDevice->bCommit = true;
+		}
 	}
 	return rc;
 }
@@ -709,49 +685,45 @@ if (pMgmt->eScanState ==  WMAC_IS_SCANNING) {
  */
 
 int iwctl_giwap(struct net_device *dev,
-             struct iw_request_info *info,
-			 struct sockaddr *wrq,
-             char *extra)
+		struct iw_request_info *info,
+		struct sockaddr *wrq,
+		char *extra)
 {
 	PSDevice	        pDevice = (PSDevice)netdev_priv(dev);
-    PSMgmtObject        pMgmt = &(pDevice->sMgmtObj);
+	PSMgmtObject        pMgmt = &(pDevice->sMgmtObj);
 
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWAP \n");
 
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWAP \n");
+	memcpy(wrq->sa_data, pMgmt->abyCurrBSSID, 6);
+	//2008-0410,<Modify> by Einsn Liu
+	if ((pDevice->bLinkPass == false) && (pMgmt->eCurrMode != WMAC_MODE_ESS_AP))
+		memset(wrq->sa_data, 0, 6);
 
-    memcpy(wrq->sa_data, pMgmt->abyCurrBSSID, 6);
-   //2008-0410,<Modify> by Einsn Liu
-    if ((pDevice->bLinkPass == false) && (pMgmt->eCurrMode != WMAC_MODE_ESS_AP))
-        memset(wrq->sa_data, 0, 6);
-
-    if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) {
-        memcpy(wrq->sa_data, pMgmt->abyCurrBSSID, 6);
-    }
+	if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) {
+		memcpy(wrq->sa_data, pMgmt->abyCurrBSSID, 6);
+	}
 
 	wrq->sa_family = ARPHRD_ETHER;
 
 	return 0;
-
 }
 
-
 /*
  * Wireless Handler : get ap list
  */
 
 int iwctl_giwaplist(struct net_device *dev,
-             struct iw_request_info *info,
-             struct iw_point *wrq,
-             char *extra)
+		    struct iw_request_info *info,
+		    struct iw_point *wrq,
+		    char *extra)
 {
-	int ii,jj, rc = 0;
+	int ii, jj, rc = 0;
 	struct sockaddr sock[IW_MAX_AP];
 	struct iw_quality qual[IW_MAX_AP];
-	PSDevice	        pDevice = (PSDevice)netdev_priv(dev);
-    PSMgmtObject        pMgmt = &(pDevice->sMgmtObj);
-
+	PSDevice pDevice = (PSDevice)netdev_priv(dev);
+	PSMgmtObject pMgmt = &(pDevice->sMgmtObj);
 
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWAPLIST \n");
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWAPLIST \n");
 	// Only super-user can see AP list
 
 	if (!capable(CAP_NET_ADMIN)) {
@@ -760,15 +732,14 @@ int iwctl_giwaplist(struct net_device *dev,
 	}
 
 	if (wrq->pointer) {
-
 		PKnownBSS pBSS = &(pMgmt->sBSSList[0]);
 
-		for (ii = 0, jj= 0; ii < MAX_BSS_NUM; ii++) {
-		    pBSS = &(pMgmt->sBSSList[ii]);
-            if (!pBSS->bActive)
-                continue;
-            if ( jj >= IW_MAX_AP)
-                break;
+		for (ii = 0, jj = 0; ii < MAX_BSS_NUM; ii++) {
+			pBSS = &(pMgmt->sBSSList[ii]);
+			if (!pBSS->bActive)
+				continue;
+			if (jj >= IW_MAX_AP)
+				break;
 			memcpy(sock[jj].sa_data, pBSS->abyBSSID, 6);
 			sock[jj].sa_family = ARPHRD_ETHER;
 			qual[jj].level = pBSS->uRSSI;
@@ -786,155 +757,144 @@ int iwctl_giwaplist(struct net_device *dev,
 	return rc;
 }
 
-
 /*
  * Wireless Handler : set essid
  */
 
 int iwctl_siwessid(struct net_device *dev,
-             struct iw_request_info *info,
-             struct iw_point *wrq,
-             char *extra)
+		   struct iw_request_info *info,
+		   struct iw_point *wrq,
+		   char *extra)
 {
 	PSDevice	        pDevice = (PSDevice)netdev_priv(dev);
-    PSMgmtObject        pMgmt = &(pDevice->sMgmtObj);
-    PWLAN_IE_SSID       pItemSSID;
-  //2008-0409-05, <Add> by Einsn Liu
-    unsigned char len;
-
-
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWESSID \n");
- pDevice->fWPA_Authened = false;
-if (pMgmt->eScanState ==  WMAC_IS_SCANNING) {
-        // In scanning..
-     printk("SIOCSIWESSID(??)-->In scanning...\n");
-   //  return -EAGAIN;
-  }
+	PSMgmtObject        pMgmt = &(pDevice->sMgmtObj);
+	PWLAN_IE_SSID       pItemSSID;
+	//2008-0409-05, <Add> by Einsn Liu
+	unsigned char len;
+
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWESSID \n");
+	pDevice->fWPA_Authened = false;
+	if (pMgmt->eScanState ==  WMAC_IS_SCANNING) {
+		// In scanning..
+		printk("SIOCSIWESSID(??)-->In scanning...\n");
+		//  return -EAGAIN;
+	}
 	// Check if we asked for `any'
-	if(wrq->flags == 0) {
+	if (wrq->flags == 0) {
 		// Just send an empty SSID list
 		memset(pMgmt->abyDesireSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
-                  memset(pMgmt->abyDesireBSSID, 0xFF,6);
-	    PRINT_K("set essid to 'any' \n");
-           #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
-             //Unknown desired AP,so here need not associate??
-            //if(pDevice->bWPASuppWextEnabled == true)  {
-                  return 0;
-            // }
-            #endif
+		memset(pMgmt->abyDesireBSSID, 0xFF, 6);
+		PRINT_K("set essid to 'any' \n");
+#ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
+		return 0;
+#endif
 	} else {
 		// Set the SSID
 		memset(pMgmt->abyDesireSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
-        pItemSSID = (PWLAN_IE_SSID)pMgmt->abyDesireSSID;
-        pItemSSID->byElementID = WLAN_EID_SSID;
+		pItemSSID = (PWLAN_IE_SSID)pMgmt->abyDesireSSID;
+		pItemSSID->byElementID = WLAN_EID_SSID;
 
 		memcpy(pItemSSID->abySSID, extra, wrq->length);
-	 if (pItemSSID->abySSID[wrq->length - 1] == '\0') {
-           if(wrq->length>0)
-		pItemSSID->len = wrq->length - 1;
-         }
-	else
-	  pItemSSID->len = wrq->length;
-	printk("set essid to %s \n",pItemSSID->abySSID);
+		if (pItemSSID->abySSID[wrq->length - 1] == '\0') {
+			if (wrq->length > 0)
+				pItemSSID->len = wrq->length - 1;
+		} else
+			pItemSSID->len = wrq->length;
+		printk("set essid to %s \n", pItemSSID->abySSID);
 		//2008-0409-05, <Add> by Einsn Liu
-       len=(pItemSSID->len > ((PWLAN_IE_SSID)pMgmt->abyCurrSSID)->len)?pItemSSID->len:((PWLAN_IE_SSID)pMgmt->abyCurrSSID)->len;
-   if((pDevice->bLinkPass == true) &&
-  	(memcmp(pItemSSID->abySSID,((PWLAN_IE_SSID)pMgmt->abyCurrSSID)->abySSID,len)==0))
-         return 0;
-
-     //mike:need clear desiredBSSID
-     if(pItemSSID->len==0) {
-        memset(pMgmt->abyDesireBSSID, 0xFF,6);
-        return 0;
-     }
+		len = (pItemSSID->len > ((PWLAN_IE_SSID)pMgmt->abyCurrSSID)->len) ? pItemSSID->len : ((PWLAN_IE_SSID)pMgmt->abyCurrSSID)->len;
+		if ((pDevice->bLinkPass == true) &&
+		    (memcmp(pItemSSID->abySSID, ((PWLAN_IE_SSID)pMgmt->abyCurrSSID)->abySSID, len) == 0))
+			return 0;
+
+		//mike:need clear desiredBSSID
+		if (pItemSSID->len == 0) {
+			memset(pMgmt->abyDesireBSSID, 0xFF, 6);
+			return 0;
+		}
 
 #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
- //Wext wil order another command of siwap to link with desired AP,
- //so here need not associate??
-  if(pDevice->bWPASuppWextEnabled == true)  {
-        /*******search if  in hidden ssid mode ****/
-        {
-           PKnownBSS       pCurr = NULL;
-           unsigned char abyTmpDesireSSID[WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1];
-	  unsigned int ii , uSameBssidNum=0;
-
-	  memcpy(abyTmpDesireSSID,pMgmt->abyDesireSSID,sizeof(abyTmpDesireSSID));
-            pCurr = BSSpSearchBSSList(pDevice,
-                                      NULL,
-                                      abyTmpDesireSSID,
-                                      pMgmt->eConfigPHYMode
-                                      );
-
-            if (pCurr == NULL){
-               PRINT_K("SIOCSIWESSID:hidden ssid site survey before associate.......\n");
-	      vResetCommandTimer((void *) pDevice);
-	      pMgmt->eScanType = WMAC_SCAN_ACTIVE;
-               bScheduleCommand((void *) pDevice, WLAN_CMD_BSSID_SCAN, pMgmt->abyDesireSSID);
-	      bScheduleCommand((void *) pDevice, WLAN_CMD_SSID, pMgmt->abyDesireSSID);
-          }
-	 else {  //mike:to find out if that desired SSID is a hidden-ssid AP ,
-                     //         by means of judging if there are two same BSSID exist in list ?
-                  for (ii = 0; ii < MAX_BSS_NUM; ii++) {
-                     if (pMgmt->sBSSList[ii].bActive &&
-                        !compare_ether_addr(pMgmt->sBSSList[ii].abyBSSID, pCurr->abyBSSID)) {
-                        uSameBssidNum++;
-                     }
-                  }
-	     if(uSameBssidNum >= 2) {  //hit: desired AP is in hidden ssid mode!!!
-                 printk("SIOCSIWESSID:hidden ssid directly associate.......\n");
-	        vResetCommandTimer((void *) pDevice);
-	        pMgmt->eScanType = WMAC_SCAN_PASSIVE;          //this scan type,you'll submit scan result!
-	        bScheduleCommand((void *) pDevice, WLAN_CMD_BSSID_SCAN, pMgmt->abyDesireSSID);
-	        bScheduleCommand((void *) pDevice, WLAN_CMD_SSID, pMgmt->abyDesireSSID);
-	     }
-	 }
-        }
-     return 0;
-  }
-	     #endif
+		//Wext wil order another command of siwap to link with desired AP,
+		//so here need not associate??
+		if (pDevice->bWPASuppWextEnabled == true)  {
+			/*******search if  in hidden ssid mode ****/
+			{
+				PKnownBSS       pCurr = NULL;
+				unsigned char abyTmpDesireSSID[WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1];
+				unsigned int ii, uSameBssidNum = 0;
+
+				memcpy(abyTmpDesireSSID, pMgmt->abyDesireSSID, sizeof(abyTmpDesireSSID));
+				pCurr = BSSpSearchBSSList(pDevice,
+							  NULL,
+							  abyTmpDesireSSID,
+							  pMgmt->eConfigPHYMode
+);
+
+				if (pCurr == NULL) {
+					PRINT_K("SIOCSIWESSID:hidden ssid site survey before associate.......\n");
+					vResetCommandTimer((void *)pDevice);
+					pMgmt->eScanType = WMAC_SCAN_ACTIVE;
+					bScheduleCommand((void *)pDevice, WLAN_CMD_BSSID_SCAN, pMgmt->abyDesireSSID);
+					bScheduleCommand((void *)pDevice, WLAN_CMD_SSID, pMgmt->abyDesireSSID);
+				} else {  //mike:to find out if that desired SSID is a hidden-ssid AP ,
+					//         by means of judging if there are two same BSSID exist in list ?
+					for (ii = 0; ii < MAX_BSS_NUM; ii++) {
+						if (pMgmt->sBSSList[ii].bActive &&
+						    !compare_ether_addr(pMgmt->sBSSList[ii].abyBSSID, pCurr->abyBSSID)) {
+							uSameBssidNum++;
+						}
+					}
+					if (uSameBssidNum >= 2) {  //hit: desired AP is in hidden ssid mode!!!
+						printk("SIOCSIWESSID:hidden ssid directly associate.......\n");
+						vResetCommandTimer((void *)pDevice);
+						pMgmt->eScanType = WMAC_SCAN_PASSIVE;          //this scan type,you'll submit scan result!
+						bScheduleCommand((void *)pDevice, WLAN_CMD_BSSID_SCAN, pMgmt->abyDesireSSID);
+						bScheduleCommand((void *)pDevice, WLAN_CMD_SSID, pMgmt->abyDesireSSID);
+					}
+				}
+			}
+			return 0;
+		}
+#endif
 
-	    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "set essid = %s \n", pItemSSID->abySSID);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "set essid = %s \n", pItemSSID->abySSID);
 	}
 
-    if (pDevice->flags & DEVICE_FLAGS_OPENED) {
-	    pDevice->bCommit = true;
+	if (pDevice->flags & DEVICE_FLAGS_OPENED) {
+		pDevice->bCommit = true;
 	}
 
-
 	return 0;
 }
 
-
 /*
  * Wireless Handler : get essid
  */
 
 int iwctl_giwessid(struct net_device *dev,
-             struct iw_request_info *info,
-             struct iw_point *wrq,
-             char *extra)
+		   struct iw_request_info *info,
+		   struct iw_point *wrq,
+		   char *extra)
 {
-
 	PSDevice	        pDevice = (PSDevice)netdev_priv(dev);
-    PSMgmtObject        pMgmt = &(pDevice->sMgmtObj);
+	PSMgmtObject        pMgmt = &(pDevice->sMgmtObj);
 	PWLAN_IE_SSID       pItemSSID;
 
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWESSID \n");
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWESSID \n");
 
 	// Note : if wrq->u.data.flags != 0, we should
 	// get the relevant SSID from the SSID list...
 
 	// Get the current SSID
-    pItemSSID = (PWLAN_IE_SSID)pMgmt->abyCurrSSID;
+	pItemSSID = (PWLAN_IE_SSID)pMgmt->abyCurrSSID;
 	//pItemSSID = (PWLAN_IE_SSID)pMgmt->abyDesireSSID;
 	memcpy(extra, pItemSSID->abySSID , pItemSSID->len);
 	extra[pItemSSID->len] = '\0';
 	wrq->length = pItemSSID->len + 1;
-	        //2008-0409-03, <Add> by Einsn Liu
-        wrq->length = pItemSSID->len;
+	//2008-0409-03, <Add> by Einsn Liu
+	wrq->length = pItemSSID->len;
 	wrq->flags = 1; // active
 
-
 	return 0;
 }
 
@@ -943,28 +903,27 @@ int iwctl_giwessid(struct net_device *dev,
  */
 
 int iwctl_siwrate(struct net_device *dev,
-             struct iw_request_info *info,
-			 struct iw_param *wrq,
-             char *extra)
+		  struct iw_request_info *info,
+		  struct iw_param *wrq,
+		  char *extra)
 {
 	PSDevice	        pDevice = (PSDevice)netdev_priv(dev);
-    int rc = 0;
+	int rc = 0;
 	u8	brate = 0;
 	int	i;
-	unsigned char abySupportedRates[13]= {0x02, 0x04, 0x0B, 0x16, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6C, 0x90};
-
+	unsigned char abySupportedRates[13] = {0x02, 0x04, 0x0B, 0x16, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6C, 0x90};
 
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWRATE \n");
-    if (!(pDevice->flags & DEVICE_FLAGS_OPENED)) {
-        rc = -EINVAL;
-        return rc;
-    }
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWRATE \n");
+	if (!(pDevice->flags & DEVICE_FLAGS_OPENED)) {
+		rc = -EINVAL;
+		return rc;
+	}
 
 	// First : get a valid bit rate value
 
 	// Which type of value
-	if((wrq->value < 13) &&
-	   (wrq->value >= 0)) {
+	if ((wrq->value < 13) &&
+	    (wrq->value >= 0)) {
 		// Setting by rate index
 		// Find value in the magic rate table
 		brate = wrq->value;
@@ -973,51 +932,49 @@ int iwctl_siwrate(struct net_device *dev,
 		u8	normvalue = (u8) (wrq->value/500000);
 
 		// Check if rate is valid
-		for(i = 0 ; i < 13 ; i++) {
-			if(normvalue == abySupportedRates[i]) {
+		for (i = 0; i < 13; i++) {
+			if (normvalue == abySupportedRates[i]) {
 				brate = i;
 				break;
 			}
 		}
 	}
 	// -1 designed the max rate (mostly auto mode)
-	if(wrq->value == -1) {
+	if (wrq->value == -1) {
 		// Get the highest available rate
-		for(i = 0 ; i < 13 ; i++) {
-			if(abySupportedRates[i] == 0)
+		for (i = 0; i < 13; i++) {
+			if (abySupportedRates[i] == 0)
 				break;
 		}
-		if(i != 0)
+		if (i != 0)
 			brate = i - 1;
 
 	}
 	// Check that it is valid
 	// brate is index of abySupportedRates[]
-	if(brate > 13 ) {
+	if (brate > 13) {
 		rc = -EINVAL;
 		return rc;
 	}
 
 	// Now, check if we want a fixed or auto value
-	if(wrq->fixed != 0) {
+	if (wrq->fixed != 0) {
 		// Fixed mode
 		// One rate, fixed
-	printk("Rate Fix\n");
+		printk("Rate Fix\n");
 		pDevice->bFixRate = true;
-        if ((pDevice->byBBType == BB_TYPE_11B)&& (brate > 3)) {
-	    pDevice->uConnectionRate = 3;
-        }
-        else {
-            pDevice->uConnectionRate = brate;
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Fixed to Rate %d \n", pDevice->uConnectionRate);
-        }
+		if ((pDevice->byBBType == BB_TYPE_11B) && (brate > 3)) {
+			pDevice->uConnectionRate = 3;
+		} else {
+			pDevice->uConnectionRate = brate;
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Fixed to Rate %d \n", pDevice->uConnectionRate);
+		}
 
+	} else {
+		pDevice->bFixRate = false;
+		pDevice->uConnectionRate = 13;
+		printk("auto rate:connection_rate is 13\n");
 	}
-	else {
-        pDevice->bFixRate = false;
-        pDevice->uConnectionRate = 13;
-	printk("auto rate:connection_rate is 13\n");
-     }
 
 	return rc;
 }
@@ -1027,91 +984,84 @@ int iwctl_siwrate(struct net_device *dev,
  */
 
 int iwctl_giwrate(struct net_device *dev,
-             struct iw_request_info *info,
-             struct iw_param *wrq,
-             char *extra)
+		  struct iw_request_info *info,
+		  struct iw_param *wrq,
+		  char *extra)
 {
 	PSDevice	        pDevice = (PSDevice)netdev_priv(dev);
 //2007-0118-05,<Mark> by EinsnLiu
 //Mark the unnecessary sentences.
 //    PSMgmtObject        pMgmt = &(pDevice->sMgmtObj);
 
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWRATE \n");
-    {
-        unsigned char abySupportedRates[13]= {0x02, 0x04, 0x0B, 0x16, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6C, 0x90};
-	    int brate = 0;
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWRATE \n");
+	{
+		unsigned char abySupportedRates[13] = {0x02, 0x04, 0x0B, 0x16, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6C, 0x90};
+		int brate = 0;
 //2008-5-8 <modify> by chester
-if(pDevice->bLinkPass){
-if(pDevice->bFixRate == true){
-		if (pDevice->uConnectionRate < 13) {
-	        brate = abySupportedRates[pDevice->uConnectionRate];
-	    }else {
-            if (pDevice->byBBType == BB_TYPE_11B)
-	            brate = 0x16;
-            if (pDevice->byBBType == BB_TYPE_11G)
-	            brate = 0x6C;
-            if (pDevice->byBBType == BB_TYPE_11A)
-	            brate = 0x6C;
-	    }
-}
-else
-{
-
- brate = abySupportedRates[TxRate_iwconfig];
-}
-}
-else brate =0;
+		if (pDevice->bLinkPass) {
+			if (pDevice->bFixRate == true) {
+				if (pDevice->uConnectionRate < 13) {
+					brate = abySupportedRates[pDevice->uConnectionRate];
+				} else {
+					if (pDevice->byBBType == BB_TYPE_11B)
+						brate = 0x16;
+					if (pDevice->byBBType == BB_TYPE_11G)
+						brate = 0x6C;
+					if (pDevice->byBBType == BB_TYPE_11A)
+						brate = 0x6C;
+				}
+			} else {
+				brate = abySupportedRates[TxRate_iwconfig];
+			}
+		} else brate = 0;
 //2007-0118-05,<Mark> by EinsnLiu
 //Mark the unnecessary sentences.
 /*
-	    if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) {
-            if (pDevice->byBBType == BB_TYPE_11B)
-	            brate = 0x16;
-            if (pDevice->byBBType == BB_TYPE_11G)
-	            brate = 0x6C;
-            if (pDevice->byBBType == BB_TYPE_11A)
-	            brate = 0x6C;
-	    }
+  if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) {
+  if (pDevice->byBBType == BB_TYPE_11B)
+  brate = 0x16;
+  if (pDevice->byBBType == BB_TYPE_11G)
+  brate = 0x6C;
+  if (pDevice->byBBType == BB_TYPE_11A)
+  brate = 0x6C;
+  }
 */
 
-//    		if (pDevice->uConnectionRate == 13)
+//		if (pDevice->uConnectionRate == 13)
 //                brate = abySupportedRates[pDevice->wCurrentRate];
-	    wrq->value = brate * 500000;
-	    // If more than one rate, set auto
-	    if (pDevice->bFixRate == true)
-	        wrq->fixed = true;
-    }
-
+		wrq->value = brate * 500000;
+		// If more than one rate, set auto
+		if (pDevice->bFixRate == true)
+			wrq->fixed = true;
+	}
 
 	return 0;
 }
 
-
-
 /*
  * Wireless Handler : set rts threshold
  */
 
 int iwctl_siwrts(struct net_device *dev,
-             struct iw_request_info *info,
-			 struct iw_param *wrq,
-             char *extra)
+		 struct iw_request_info *info,
+		 struct iw_param *wrq,
+		 char *extra)
 {
 	PSDevice	        pDevice = (PSDevice)netdev_priv(dev);
 	int rc = 0;
 
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWRTS \n");
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWRTS \n");
 
 	{
-	    int rthr = wrq->value;
-	    if(wrq->disabled)
+		int rthr = wrq->value;
+		if (wrq->disabled)
 			rthr = 2312;
-	    if((rthr < 0) || (rthr > 2312)) {
+		if ((rthr < 0) || (rthr > 2312)) {
 			rc = -EINVAL;
-    	}else {
-		    pDevice->wRTSThreshold = rthr;
-	    }
-    }
+		} else {
+			pDevice->wRTSThreshold = rthr;
+		}
+	}
 
 	return 0;
 }
@@ -1121,13 +1071,13 @@ int iwctl_siwrts(struct net_device *dev,
  */
 
 int iwctl_giwrts(struct net_device *dev,
-             struct iw_request_info *info,
-			 struct iw_param *wrq,
-             char *extra)
+		 struct iw_request_info *info,
+		 struct iw_param *wrq,
+		 char *extra)
 {
 	PSDevice	        pDevice = (PSDevice)netdev_priv(dev);
 
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWRTS \n");
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWRTS \n");
 	wrq->value = pDevice->wRTSThreshold;
 	wrq->disabled = (wrq->value >= 2312);
 	wrq->fixed = 1;
@@ -1140,26 +1090,24 @@ int iwctl_giwrts(struct net_device *dev,
  */
 
 int iwctl_siwfrag(struct net_device *dev,
-             struct iw_request_info *info,
-			 struct iw_param *wrq,
-             char *extra)
+		  struct iw_request_info *info,
+		  struct iw_param *wrq,
+		  char *extra)
 {
-    PSDevice	        pDevice = (PSDevice)netdev_priv(dev);
-    int rc = 0;
-    int fthr = wrq->value;
-
-
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWFRAG \n");
+	PSDevice	        pDevice = (PSDevice)netdev_priv(dev);
+	int rc = 0;
+	int fthr = wrq->value;
 
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWFRAG \n");
 
-    if (wrq->disabled)
+	if (wrq->disabled)
 		fthr = 2312;
-    if((fthr < 256) || (fthr > 2312)) {
+	if ((fthr < 256) || (fthr > 2312)) {
 		rc = -EINVAL;
-    }else {
-		 fthr &= ~0x1;	// Get an even value
-	     pDevice->wFragmentationThreshold = (u16)fthr;
-    }
+	} else {
+		fthr &= ~0x1;	// Get an even value
+		pDevice->wFragmentationThreshold = (u16)fthr;
+	}
 
 	return rc;
 }
@@ -1169,13 +1117,13 @@ int iwctl_siwfrag(struct net_device *dev,
  */
 
 int iwctl_giwfrag(struct net_device *dev,
-             struct iw_request_info *info,
-			 struct iw_param *wrq,
-             char *extra)
+		  struct iw_request_info *info,
+		  struct iw_param *wrq,
+		  char *extra)
 {
-    PSDevice	        pDevice = (PSDevice)netdev_priv(dev);
+	PSDevice	        pDevice = (PSDevice)netdev_priv(dev);
 
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWFRAG \n");
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWFRAG \n");
 	wrq->value = pDevice->wFragmentationThreshold;
 	wrq->disabled = (wrq->value >= 2312);
 	wrq->fixed = 1;
@@ -1183,21 +1131,18 @@ int iwctl_giwfrag(struct net_device *dev,
 	return 0;
 }
 
-
-
 /*
  * Wireless Handler : set retry threshold
  */
 int iwctl_siwretry(struct net_device *dev,
-             struct iw_request_info *info,
-			 struct iw_param *wrq,
-             char *extra)
+		   struct iw_request_info *info,
+		   struct iw_param *wrq,
+		   char *extra)
 {
-    PSDevice	        pDevice = (PSDevice)netdev_priv(dev);
-    int rc = 0;
-
+	PSDevice	        pDevice = (PSDevice)netdev_priv(dev);
+	int rc = 0;
 
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWRETRY \n");
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWRETRY \n");
 
 	if (wrq->disabled) {
 		rc = -EINVAL;
@@ -1205,7 +1150,7 @@ int iwctl_siwretry(struct net_device *dev,
 	}
 
 	if (wrq->flags & IW_RETRY_LIMIT) {
-		if(wrq->flags & IW_RETRY_MAX)
+		if (wrq->flags & IW_RETRY_MAX)
 			pDevice->byLongRetryLimit = wrq->value;
 		else if (wrq->flags & IW_RETRY_MIN)
 			pDevice->byShortRetryLimit = wrq->value;
@@ -1219,7 +1164,6 @@ int iwctl_siwretry(struct net_device *dev,
 		pDevice->wMaxTransmitMSDULifetime = wrq->value;
 	}
 
-
 	return rc;
 }
 
@@ -1227,45 +1171,43 @@ int iwctl_siwretry(struct net_device *dev,
  * Wireless Handler : get retry threshold
  */
 int iwctl_giwretry(struct net_device *dev,
-             struct iw_request_info *info,
-			 struct iw_param *wrq,
-             char *extra)
+		   struct iw_request_info *info,
+		   struct iw_param *wrq,
+		   char *extra)
 {
-    PSDevice	        pDevice = (PSDevice)netdev_priv(dev);
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWRETRY \n");
+	PSDevice	        pDevice = (PSDevice)netdev_priv(dev);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWRETRY \n");
 	wrq->disabled = 0;      // Can't be disabled
 
 	// Note : by default, display the min retry number
-	if((wrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) {
+	if ((wrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) {
 		wrq->flags = IW_RETRY_LIFETIME;
 		wrq->value = (int)pDevice->wMaxTransmitMSDULifetime; //ms
-	} else if((wrq->flags & IW_RETRY_MAX)) {
+	} else if ((wrq->flags & IW_RETRY_MAX)) {
 		wrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
 		wrq->value = (int)pDevice->byLongRetryLimit;
 	} else {
 		wrq->flags = IW_RETRY_LIMIT;
 		wrq->value = (int)pDevice->byShortRetryLimit;
-		if((int)pDevice->byShortRetryLimit != (int)pDevice->byLongRetryLimit)
+		if ((int)pDevice->byShortRetryLimit != (int)pDevice->byLongRetryLimit)
 			wrq->flags |= IW_RETRY_MIN;
 	}
 
-
 	return 0;
 }
 
-
 /*
  * Wireless Handler : set encode mode
  */
 int iwctl_siwencode(struct net_device *dev,
-             struct iw_request_info *info,
-             struct iw_point *wrq,
-             char *extra)
+		    struct iw_request_info *info,
+		    struct iw_point *wrq,
+		    char *extra)
 {
-    PSDevice	        pDevice = (PSDevice)netdev_priv(dev);
-    PSMgmtObject        pMgmt = &(pDevice->sMgmtObj);
+	PSDevice	        pDevice = (PSDevice)netdev_priv(dev);
+	PSMgmtObject        pMgmt = &(pDevice->sMgmtObj);
 	unsigned long dwKeyIndex = (unsigned long)(wrq->flags & IW_ENCODE_INDEX);
-	int ii,uu, rc = 0;
+	int ii, uu, rc = 0;
 	int index = (wrq->flags & IW_ENCODE_INDEX);
 
 //2007-0207-07,<Modify> by EinsnLiu
@@ -1281,192 +1223,182 @@ int iwctl_siwencode(struct net_device *dev,
 
 	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWENCODE \n");
 
-if((wrq->flags & IW_ENCODE_DISABLED)==0){
-	//Not disable encryption
+	if ((wrq->flags & IW_ENCODE_DISABLED) == 0) {
+		//Not disable encryption
 
-	if (dwKeyIndex > WLAN_WEP_NKEYS) {
-		rc = -EINVAL;
-        return rc;
-    	}
+		if (dwKeyIndex > WLAN_WEP_NKEYS) {
+			rc = -EINVAL;
+			return rc;
+		}
 
-	if(dwKeyIndex<1&&((wrq->flags&IW_ENCODE_NOKEY)==0)){//set default key
-		if(pDevice->byKeyIndex<WLAN_WEP_NKEYS){
-			dwKeyIndex=pDevice->byKeyIndex;
+		if (dwKeyIndex < 1 && ((wrq->flags & IW_ENCODE_NOKEY) == 0)) {//set default key
+			if (pDevice->byKeyIndex < WLAN_WEP_NKEYS) {
+				dwKeyIndex = pDevice->byKeyIndex;
+			} else dwKeyIndex = 0;
+		} else dwKeyIndex--;
+
+		// Check the size of the key
+		if (wrq->length > WLAN_WEP232_KEYLEN) {
+			rc = -EINVAL;
+			return rc;
+		}
+
+		if (wrq->length > 0) {//have key
+
+			if (wrq->length ==  WLAN_WEP232_KEYLEN) {
+				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Set 232 bit wep key\n");
+			} else if (wrq->length ==  WLAN_WEP104_KEYLEN) {
+				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Set 104 bit wep key\n");
+			} else if (wrq->length == WLAN_WEP40_KEYLEN) {
+				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Set 40 bit wep key, index= %d\n", (int)dwKeyIndex);
+			} else {//no support length
+				rc = -EINVAL;
+				return rc;
 			}
-		else dwKeyIndex=0;
-		}else dwKeyIndex--;
+			memset(pDevice->abyKey, 0, WLAN_WEP232_KEYLEN);
+			memcpy(pDevice->abyKey, extra, wrq->length);
 
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "abyKey: ");
+			for (ii = 0; ii < wrq->length; ii++) {
+				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%02x ", pDevice->abyKey[ii]);
+			}
 
-	// Check the size of the key
-	if (wrq->length > WLAN_WEP232_KEYLEN) {
-		rc = -EINVAL;
-        return rc;
-	}
+			if (pDevice->flags & DEVICE_FLAGS_OPENED) {
+				spin_lock_irq(&pDevice->lock);
+				KeybSetDefaultKey(&(pDevice->sKey),
+						  (unsigned long)(dwKeyIndex | (1 << 31)),
+						  wrq->length,
+						  NULL,
+						  pDevice->abyKey,
+						  KEY_CTL_WEP,
+						  pDevice->PortOffset,
+						  pDevice->byLocalID
+);
+				spin_unlock_irq(&pDevice->lock);
+			}
+			pDevice->byKeyIndex = (unsigned char)dwKeyIndex;
+			pDevice->uKeyLength = wrq->length;
+			pDevice->bTransmitKey = true;
+			pDevice->bEncryptionEnable = true;
+			pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled;
 
-	if(wrq->length>0){//have key
-
-        if (wrq->length ==  WLAN_WEP232_KEYLEN) {
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Set 232 bit wep key\n");
-        }
-        else if (wrq->length ==  WLAN_WEP104_KEYLEN) {
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Set 104 bit wep key\n");
-        }
-        else if (wrq->length == WLAN_WEP40_KEYLEN) {
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Set 40 bit wep key, index= %d\n", (int)dwKeyIndex);
-        }else {//no support length
-		rc = -EINVAL;
-        return rc;
+		} else if (index > 0) {
+			//when the length is 0 the request only changes the default transmit key index
+			//check the new key if it has a non zero length
+			if (pDevice->bEncryptionEnable == false) {
+				rc = -EINVAL;
+				return rc;
+			}
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Just set Default key Index:\n");
+			pkeytab = &(pDevice->sKey.KeyTable[MAX_KEY_TABLE - 1]);
+			if (pkeytab->GroupKey[(unsigned char)dwKeyIndex].uKeyLength == 0) {
+				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Default key len is 0\n");
+				rc = -EINVAL;
+				return rc;
+			}
+			pDevice->byKeyIndex = (unsigned char)dwKeyIndex;
+			pkeytab->dwGTKeyIndex = dwKeyIndex | (1 << 31);
+			pkeytab->GroupKey[(unsigned char)dwKeyIndex].dwKeyIndex = dwKeyIndex | (1 << 31);
 		}
-        memset(pDevice->abyKey, 0, WLAN_WEP232_KEYLEN);
-        memcpy(pDevice->abyKey, extra, wrq->length);
-
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"abyKey: ");
-        for (ii = 0; ii < wrq->length; ii++) {
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%02x ", pDevice->abyKey[ii]);
-        }
-
-        if (pDevice->flags & DEVICE_FLAGS_OPENED) {
-            spin_lock_irq(&pDevice->lock);
-            KeybSetDefaultKey(&(pDevice->sKey),
-                            (unsigned long)(dwKeyIndex | (1 << 31)),
-                           	wrq->length,
-                            NULL,
-                            pDevice->abyKey,
-                            KEY_CTL_WEP,
-                            pDevice->PortOffset,
-                            pDevice->byLocalID
-                          );
-            spin_unlock_irq(&pDevice->lock);
-        }
-        pDevice->byKeyIndex = (unsigned char)dwKeyIndex;
-        pDevice->uKeyLength = wrq->length;
-        pDevice->bTransmitKey = true;
-        pDevice->bEncryptionEnable = true;
-        pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled;
-
-		}else if(index>0){
-	//when the length is 0 the request only changes the default transmit key index
-	//check the new key if it has a non zero length
-	if(pDevice->bEncryptionEnable==false)
-	{
-		rc = -EINVAL;
-        	return rc;
-	}
-	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Just set Default key Index:\n");
-	pkeytab=&(pDevice->sKey.KeyTable[MAX_KEY_TABLE-1]);
-	if(pkeytab->GroupKey[(unsigned char)dwKeyIndex].uKeyLength==0){
-		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Default key len is 0\n");
-		rc = -EINVAL;
-      	  	return rc;
+
+	} else {//disable the key
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Disable WEP function\n");
+		if (pDevice->bEncryptionEnable == false)
+			return 0;
+		pMgmt->bShareKeyAlgorithm = false;
+		pDevice->bEncryptionEnable = false;
+		pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled;
+		if (pDevice->flags & DEVICE_FLAGS_OPENED) {
+			spin_lock_irq(&pDevice->lock);
+			for (uu = 0; uu < MAX_KEY_TABLE; uu++)
+				MACvDisableKeyEntry(pDevice->PortOffset, uu);
+			spin_unlock_irq(&pDevice->lock);
 		}
-	 pDevice->byKeyIndex =(unsigned char)dwKeyIndex;
-	 pkeytab->dwGTKeyIndex =dwKeyIndex | (1 << 31);
-	 pkeytab->GroupKey[(unsigned char)dwKeyIndex].dwKeyIndex=dwKeyIndex | (1 << 31);
 	}
-
-}else {//disable the key
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Disable WEP function\n");
-	if(pDevice->bEncryptionEnable==false)
-		return 0;
-	pMgmt->bShareKeyAlgorithm = false;
-        pDevice->bEncryptionEnable = false;
-        pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled;
-        if (pDevice->flags & DEVICE_FLAGS_OPENED) {
-            spin_lock_irq(&pDevice->lock);
-            for(uu=0;uu<MAX_KEY_TABLE;uu++)
-                MACvDisableKeyEntry(pDevice->PortOffset, uu);
-            spin_unlock_irq(&pDevice->lock);
-        }
-}
 //End Modify,Einsn
 
 /*
-     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWENCODE \n");
+  DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWENCODE \n");
 
-	// Check the size of the key
-	if (wrq->length > WLAN_WEP232_KEYLEN) {
-		rc = -EINVAL;
-        return rc;
-	}
+  // Check the size of the key
+  if (wrq->length > WLAN_WEP232_KEYLEN) {
+  rc = -EINVAL;
+  return rc;
+  }
 
-	if (dwKeyIndex > WLAN_WEP_NKEYS) {
-		rc = -EINVAL;
-        return rc;
-    }
-
-    if (dwKeyIndex > 0)
-		dwKeyIndex--;
-
-	// Send the key to the card
-	if (wrq->length > 0) {
-
-        if (wrq->length ==  WLAN_WEP232_KEYLEN) {
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Set 232 bit wep key\n");
-        }
-        else if (wrq->length ==  WLAN_WEP104_KEYLEN) {
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Set 104 bit wep key\n");
-        }
-        else if (wrq->length == WLAN_WEP40_KEYLEN) {
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Set 40 bit wep key, index= %d\n", (int)dwKeyIndex);
-        }
-        memset(pDevice->abyKey, 0, WLAN_WEP232_KEYLEN);
-        memcpy(pDevice->abyKey, extra, wrq->length);
-
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"abyKey: ");
-        for (ii = 0; ii < wrq->length; ii++) {
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%02x ", pDevice->abyKey[ii]);
-        }
-
-        if (pDevice->flags & DEVICE_FLAGS_OPENED) {
-            spin_lock_irq(&pDevice->lock);
-            KeybSetDefaultKey(&(pDevice->sKey),
-                            (unsigned long)(pDevice->byKeyIndex | (1 << 31)),
-                            pDevice->uKeyLength,
-                            NULL,
-                            pDevice->abyKey,
-                            KEY_CTL_WEP,
-                            pDevice->PortOffset,
-                            pDevice->byLocalID
-                          );
-            spin_unlock_irq(&pDevice->lock);
-        }
-        pDevice->byKeyIndex = (unsigned char)dwKeyIndex;
-        pDevice->uKeyLength = wrq->length;
-        pDevice->bTransmitKey = true;
-        pDevice->bEncryptionEnable = true;
-        pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled;
-
-		// Do we want to just set the transmit key index ?
-		if ( index < 4 ) {
-		    pDevice->byKeyIndex = index;
-		}
-		else if(!(wrq->flags & IW_ENCODE_MODE)) {
-				rc = -EINVAL;
-				return rc;
-	    }
-	}
-	// Read the flags
-	if(wrq->flags & IW_ENCODE_DISABLED){
+  if (dwKeyIndex > WLAN_WEP_NKEYS) {
+  rc = -EINVAL;
+  return rc;
+  }
 
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Disable WEP function\n");
-		pMgmt->bShareKeyAlgorithm = false;
-        pDevice->bEncryptionEnable = false;
-        pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled;
-        if (pDevice->flags & DEVICE_FLAGS_OPENED) {
-            spin_lock_irq(&pDevice->lock);
-            for(uu=0;uu<MAX_KEY_TABLE;uu++)
-                MACvDisableKeyEntry(pDevice->PortOffset, uu);
-            spin_unlock_irq(&pDevice->lock);
-        }
-	}
+  if (dwKeyIndex > 0)
+  dwKeyIndex--;
+
+  // Send the key to the card
+  if (wrq->length > 0) {
+  if (wrq->length ==  WLAN_WEP232_KEYLEN) {
+  DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Set 232 bit wep key\n");
+  } else if (wrq->length ==  WLAN_WEP104_KEYLEN) {
+  DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Set 104 bit wep key\n");
+  } else if (wrq->length == WLAN_WEP40_KEYLEN) {
+  DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Set 40 bit wep key, index= %d\n", (int)dwKeyIndex);
+  }
+  memset(pDevice->abyKey, 0, WLAN_WEP232_KEYLEN);
+  memcpy(pDevice->abyKey, extra, wrq->length);
+
+  DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "abyKey: ");
+  for (ii = 0; ii < wrq->length; ii++) {
+  DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%02x ", pDevice->abyKey[ii]);
+  }
+
+  if (pDevice->flags & DEVICE_FLAGS_OPENED) {
+  spin_lock_irq(&pDevice->lock);
+  KeybSetDefaultKey(&(pDevice->sKey),
+  (unsigned long)(pDevice->byKeyIndex | (1 << 31)),
+  pDevice->uKeyLength,
+  NULL,
+  pDevice->abyKey,
+  KEY_CTL_WEP,
+  pDevice->PortOffset,
+  pDevice->byLocalID
+);
+  spin_unlock_irq(&pDevice->lock);
+  }
+  pDevice->byKeyIndex = (unsigned char)dwKeyIndex;
+  pDevice->uKeyLength = wrq->length;
+  pDevice->bTransmitKey = true;
+  pDevice->bEncryptionEnable = true;
+  pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled;
+
+  // Do we want to just set the transmit key index ?
+  if (index < 4) {
+  pDevice->byKeyIndex = index;
+  } else if (!(wrq->flags & IW_ENCODE_MODE)) {
+  rc = -EINVAL;
+  return rc;
+  }
+  }
+  // Read the flags
+  if (wrq->flags & IW_ENCODE_DISABLED) {
+  DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Disable WEP function\n");
+  pMgmt->bShareKeyAlgorithm = false;
+  pDevice->bEncryptionEnable = false;
+  pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled;
+  if (pDevice->flags & DEVICE_FLAGS_OPENED) {
+  spin_lock_irq(&pDevice->lock);
+  for (uu=0; uu<MAX_KEY_TABLE; uu++)
+  MACvDisableKeyEntry(pDevice->PortOffset, uu);
+  spin_unlock_irq(&pDevice->lock);
+  }
+  }
 */
 
-	if(wrq->flags & IW_ENCODE_RESTRICTED) {
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Enable WEP & ShareKey System\n");
+	if (wrq->flags & IW_ENCODE_RESTRICTED) {
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Enable WEP & ShareKey System\n");
 		pMgmt->bShareKeyAlgorithm = true;
 	}
-	if(wrq->flags & IW_ENCODE_OPEN) {
-	    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Enable WEP & Open System\n");
+	if (wrq->flags & IW_ENCODE_OPEN) {
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Enable WEP & Open System\n");
 		pMgmt->bShareKeyAlgorithm = false;
 	}
 	return rc;
@@ -1475,80 +1407,78 @@ if((wrq->flags & IW_ENCODE_DISABLED)==0){
 /*
  * Wireless Handler : get encode mode
  */
- /*
-int iwctl_giwencode(struct net_device *dev,
-             struct iw_request_info *info,
-             struct iw_point *wrq,
-             char *extra)
-{
-    PSDevice	        pDevice = (PSDevice)netdev_priv(dev);
-    PSMgmtObject        pMgmt = &(pDevice->sMgmtObj);
-    int rc = 0;
-    char abyKey[WLAN_WEP232_KEYLEN];
-	unsigned int index = (unsigned int)(wrq->flags & IW_ENCODE_INDEX);
-	PSKeyItem   pKey = NULL;
-
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWENCODE\n");
+/*
+  int iwctl_giwencode(struct net_device *dev,
+  struct iw_request_info *info,
+  struct iw_point *wrq,
+  char *extra) {
+  PSDevice	        pDevice = (PSDevice)netdev_priv(dev);
+  PSMgmtObject        pMgmt = &(pDevice->sMgmtObj);
+  int rc = 0;
+  char abyKey[WLAN_WEP232_KEYLEN];
+  unsigned int index = (unsigned int)(wrq->flags & IW_ENCODE_INDEX);
+  PSKeyItem   pKey = NULL;
+
+  DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWENCODE\n");
 //2007-0207-06,<Add> by EinsnLiu
 //the key index in iwconfig is 1-4 when our driver is 0-3
 //so it can't be used directly.
 //if the index is 0,we should used the index set by driver.
-	if (index > WLAN_WEP_NKEYS) {
-		rc = -EINVAL;
-        return rc;
-    	}
-	if(index<1){//set default key
-		if(pDevice->byKeyIndex<WLAN_WEP_NKEYS){
-			index=pDevice->byKeyIndex;
-			}
-		else index=0;
-		}else index--;
+if (index > WLAN_WEP_NKEYS) {
+rc = -EINVAL;
+return rc;
+}
+if (index<1) {//set default key
+if (pDevice->byKeyIndex<WLAN_WEP_NKEYS) {
+index=pDevice->byKeyIndex;
+}
+else index=0;
+} else index--;
 //End Add,Einsn
 
-	memset(abyKey, 0, sizeof(abyKey));
-	// Check encryption mode
-	wrq->flags = IW_ENCODE_NOKEY;
-	// Is WEP enabled ???
-	if (pDevice->bEncryptionEnable)
-		wrq->flags |=  IW_ENCODE_ENABLED;
-    else
-		wrq->flags |=  IW_ENCODE_DISABLED;
+memset(abyKey, 0, sizeof(abyKey));
+// Check encryption mode
+wrq->flags = IW_ENCODE_NOKEY;
+// Is WEP enabled ???
+if (pDevice->bEncryptionEnable)
+wrq->flags |=  IW_ENCODE_ENABLED;
+else
+wrq->flags |=  IW_ENCODE_DISABLED;
 
-    if (pMgmt->bShareKeyAlgorithm)
-		wrq->flags |=  IW_ENCODE_RESTRICTED;
-	else
-		wrq->flags |=  IW_ENCODE_OPEN;
+if (pMgmt->bShareKeyAlgorithm)
+wrq->flags |=  IW_ENCODE_RESTRICTED;
+else
+wrq->flags |=  IW_ENCODE_OPEN;
 
-	if (KeybGetKey(&(pDevice->sKey), pDevice->abyBroadcastAddr, (unsigned char)index , &pKey)){
-        wrq->length = pKey->uKeyLength;
-        memcpy(abyKey, pKey->abyKey,  pKey->uKeyLength);
+if (KeybGetKey(&(pDevice->sKey), pDevice->abyBroadcastAddr, (unsigned char)index , &pKey)) {
+wrq->length = pKey->uKeyLength;
+memcpy(abyKey, pKey->abyKey,  pKey->uKeyLength);
 //2007-0207-06,<Modify> by EinsnLiu
 //only get key success need to  copy data
 //index should +1.
 //there is not necessary to return -EINVAL when get key failed
 //if return -EINVAL,the encryption item can't be display by the command "iwconfig".
-	wrq->flags |= index+1;
-	memcpy(extra,  abyKey, WLAN_WEP232_KEYLEN);
-    }
-
-    //else {
-    //    rc = -EINVAL;
-   //     return rc;
-  //  }
+wrq->flags |= index+1;
+memcpy(extra,  abyKey, WLAN_WEP232_KEYLEN);
+}
 
+//else {
+//    rc = -EINVAL;
+//     return rc;
+//  }
 
 //End Modify,Einsn
 
-	return 0;
+return 0;
 }
 */
 
 //2008-0409-06, <Add> by Einsn Liu
 
 int iwctl_giwencode(struct net_device *dev,
-			struct iw_request_info *info,
-			struct iw_point *wrq,
-			char *extra)
+		    struct iw_request_info *info,
+		    struct iw_point *wrq,
+		    char *extra)
 {
 	PSDevice			pDevice = (PSDevice)netdev_priv(dev);
 	PSMgmtObject		pMgmt = &(pDevice->sMgmtObj);
@@ -1562,13 +1492,13 @@ int iwctl_giwencode(struct net_device *dev,
 	if (index > WLAN_WEP_NKEYS) {
 		return	-EINVAL;
 	}
-	if(index<1){//get default key
-		if(pDevice->byKeyIndex<WLAN_WEP_NKEYS){
-			index=pDevice->byKeyIndex;
-         	} else
-                      index=0;
-	}else
-             index--;
+	if (index < 1) {//get default key
+		if (pDevice->byKeyIndex < WLAN_WEP_NKEYS) {
+			index = pDevice->byKeyIndex;
+		} else
+			index = 0;
+	} else
+		index--;
 
 	memset(abyKey, 0, WLAN_WEP232_KEYLEN);
 	// Check encryption mode
@@ -1583,18 +1513,18 @@ int iwctl_giwencode(struct net_device *dev,
 		wrq->flags |=  IW_ENCODE_RESTRICTED;
 	else
 		wrq->flags |=  IW_ENCODE_OPEN;
-		wrq->length=0;
-
-	if((index==0)&&(pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled||
-		pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled)){//get wpa pairwise  key
-			if (KeybGetKey(&(pDevice->sKey),pMgmt->abyCurrBSSID, 0xffffffff, &pKey)){
-			   wrq->length = pKey->uKeyLength;
-				  memcpy(abyKey, pKey->abyKey,	pKey->uKeyLength);
-				  memcpy(extra,  abyKey, WLAN_WEP232_KEYLEN);
-			   }
-	}else if (KeybGetKey(&(pDevice->sKey), pDevice->abyBroadcastAddr, (unsigned char)index , &pKey)){
+	wrq->length = 0;
+
+	if ((index == 0) && (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled ||
+			     pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled)) {//get wpa pairwise  key
+		if (KeybGetKey(&(pDevice->sKey), pMgmt->abyCurrBSSID, 0xffffffff, &pKey)) {
 			wrq->length = pKey->uKeyLength;
-			memcpy(abyKey, pKey->abyKey,  pKey->uKeyLength);
+			memcpy(abyKey, pKey->abyKey,	pKey->uKeyLength);
+			memcpy(extra,  abyKey, WLAN_WEP232_KEYLEN);
+		}
+	} else if (KeybGetKey(&(pDevice->sKey), pDevice->abyBroadcastAddr, (unsigned char)index , &pKey)) {
+		wrq->length = pKey->uKeyLength;
+		memcpy(abyKey, pKey->abyKey,  pKey->uKeyLength);
 		memcpy(extra,  abyKey, WLAN_WEP232_KEYLEN);
 	}
 
@@ -1603,24 +1533,23 @@ int iwctl_giwencode(struct net_device *dev,
 	return 0;
 }
 
-
 /*
  * Wireless Handler : set power mode
  */
 int iwctl_siwpower(struct net_device *dev,
-             struct iw_request_info *info,
-			 struct iw_param *wrq,
-             char *extra)
+		   struct iw_request_info *info,
+		   struct iw_param *wrq,
+		   char *extra)
 {
-    PSDevice            pDevice = (PSDevice)netdev_priv(dev);
-    PSMgmtObject        pMgmt = &(pDevice->sMgmtObj);
-    int rc = 0;
+	PSDevice            pDevice = (PSDevice)netdev_priv(dev);
+	PSMgmtObject        pMgmt = &(pDevice->sMgmtObj);
+	int rc = 0;
 
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWPOWER \n");
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWPOWER \n");
 
-    if (!(pDevice->flags & DEVICE_FLAGS_OPENED)) {
-		 rc = -EINVAL;
-		 return rc;
+	if (!(pDevice->flags & DEVICE_FLAGS_OPENED)) {
+		rc = -EINVAL;
+		return rc;
 	}
 
 	if (wrq->disabled) {
@@ -1629,23 +1558,23 @@ int iwctl_siwpower(struct net_device *dev,
 		return rc;
 	}
 	if ((wrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
-         pDevice->ePSMode = WMAC_POWER_FAST;
-         PSvEnablePowerSaving((void *)pDevice, pMgmt->wListenInterval);
+		pDevice->ePSMode = WMAC_POWER_FAST;
+		PSvEnablePowerSaving((void *)pDevice, pMgmt->wListenInterval);
 
 	} else if ((wrq->flags & IW_POWER_TYPE) == IW_POWER_PERIOD) {
-	     pDevice->ePSMode = WMAC_POWER_FAST;
-         PSvEnablePowerSaving((void *)pDevice, pMgmt->wListenInterval);
+		pDevice->ePSMode = WMAC_POWER_FAST;
+		PSvEnablePowerSaving((void *)pDevice, pMgmt->wListenInterval);
 	}
 	switch (wrq->flags & IW_POWER_MODE) {
 	case IW_POWER_UNICAST_R:
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWPOWER: IW_POWER_UNICAST_R \n");
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWPOWER: IW_POWER_UNICAST_R \n");
 		rc = -EINVAL;
 		break;
 	case IW_POWER_ALL_R:
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWPOWER: IW_POWER_ALL_R \n");
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWPOWER: IW_POWER_ALL_R \n");
 		rc = -EINVAL;
 	case IW_POWER_ON:
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWPOWER: IW_POWER_ON \n");
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWPOWER: IW_POWER_ON \n");
 		break;
 	default:
 		rc = -EINVAL;
@@ -1658,21 +1587,19 @@ int iwctl_siwpower(struct net_device *dev,
  * Wireless Handler : get power mode
  */
 int iwctl_giwpower(struct net_device *dev,
-             struct iw_request_info *info,
-			 struct iw_param *wrq,
-             char *extra)
+		   struct iw_request_info *info,
+		   struct iw_param *wrq,
+		   char *extra)
 {
-    PSDevice            pDevice = (PSDevice)netdev_priv(dev);
-    PSMgmtObject        pMgmt = &(pDevice->sMgmtObj);
-    int mode = pDevice->ePSMode;
-
-
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWPOWER \n");
+	PSDevice            pDevice = (PSDevice)netdev_priv(dev);
+	PSMgmtObject        pMgmt = &(pDevice->sMgmtObj);
+	int mode = pDevice->ePSMode;
 
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWPOWER \n");
 
 	wrq->disabled = (mode == WMAC_POWER_CAM);
 	if (wrq->disabled)
-	    return 0;
+		return 0;
 
 	if ((wrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
 		wrq->value = (int)((pMgmt->wListenInterval * pMgmt->wCurrBeaconPeriod) << 10);
@@ -1686,30 +1613,27 @@ int iwctl_giwpower(struct net_device *dev,
 	return 0;
 }
 
-
 /*
  * Wireless Handler : get Sensitivity
  */
 int iwctl_giwsens(struct net_device *dev,
-			 struct iw_request_info *info,
-			 struct iw_param *wrq,
-			 char *extra)
+		  struct iw_request_info *info,
+		  struct iw_param *wrq,
+		  char *extra)
 {
-    PSDevice	        pDevice = (PSDevice)netdev_priv(dev);
-    long ldBm;
+	PSDevice	        pDevice = (PSDevice)netdev_priv(dev);
+	long ldBm;
 
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWSENS \n");
-    if (pDevice->bLinkPass == true) {
-        RFvRSSITodBm(pDevice, (unsigned char)(pDevice->uCurrRSSI), &ldBm);
-	    wrq->value = ldBm;
-	}
-	else {
-	    wrq->value = 0;
-    };
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWSENS \n");
+	if (pDevice->bLinkPass == true) {
+		RFvRSSITodBm(pDevice, (unsigned char)(pDevice->uCurrRSSI), &ldBm);
+		wrq->value = ldBm;
+	} else {
+		wrq->value = 0;
+	};
 	wrq->disabled = (wrq->value == 0);
 	wrq->fixed = 1;
 
-
 	return 0;
 }
 
@@ -1717,66 +1641,64 @@ int iwctl_giwsens(struct net_device *dev,
 #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
 
 int iwctl_siwauth(struct net_device *dev,
-			  struct iw_request_info *info,
-			  struct iw_param *wrq,
-			  char *extra)
+		  struct iw_request_info *info,
+		  struct iw_param *wrq,
+		  char *extra)
 {
 	PSDevice			pDevice = (PSDevice)netdev_priv(dev);
 	PSMgmtObject	pMgmt = &(pDevice->sMgmtObj);
-	int ret=0;
-	static int wpa_version=0;  //must be static to save the last value,einsn liu
-	static int pairwise=0;
+	int ret = 0;
+	static int wpa_version = 0;  //must be static to save the last value,einsn liu
+	static int pairwise = 0;
 
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWAUTH \n");
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWAUTH \n");
 	switch (wrq->flags & IW_AUTH_INDEX) {
 	case IW_AUTH_WPA_VERSION:
 		wpa_version = wrq->value;
-		if(wrq->value == IW_AUTH_WPA_VERSION_DISABLED) {
-		       PRINT_K("iwctl_siwauth:set WPADEV to disable at 1??????\n");
+		if (wrq->value == IW_AUTH_WPA_VERSION_DISABLED) {
+			PRINT_K("iwctl_siwauth:set WPADEV to disable at 1??????\n");
 			//pDevice->bWPADevEnable = false;
-		}
-		else if(wrq->value == IW_AUTH_WPA_VERSION_WPA) {
-                          PRINT_K("iwctl_siwauth:set WPADEV to WPA1******\n");
-		}
-		else {
-                          PRINT_K("iwctl_siwauth:set WPADEV to WPA2******\n");
+		} else if (wrq->value == IW_AUTH_WPA_VERSION_WPA) {
+			PRINT_K("iwctl_siwauth:set WPADEV to WPA1******\n");
+		} else {
+			PRINT_K("iwctl_siwauth:set WPADEV to WPA2******\n");
 		}
 		//pDevice->bWPASuppWextEnabled =true;
 		break;
 	case IW_AUTH_CIPHER_PAIRWISE:
 		pairwise = wrq->value;
-		if(pairwise == IW_AUTH_CIPHER_CCMP){
+		if (pairwise == IW_AUTH_CIPHER_CCMP) {
 			pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled;
-		}else if(pairwise == IW_AUTH_CIPHER_TKIP){
+		} else if (pairwise == IW_AUTH_CIPHER_TKIP) {
 			pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled;
-		}else if(pairwise == IW_AUTH_CIPHER_WEP40||pairwise == IW_AUTH_CIPHER_WEP104){
+		} else if (pairwise == IW_AUTH_CIPHER_WEP40 || pairwise == IW_AUTH_CIPHER_WEP104) {
 			pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled;
-		}else if(pairwise == IW_AUTH_CIPHER_NONE){
+		} else if (pairwise == IW_AUTH_CIPHER_NONE) {
 			//do nothing,einsn liu
-		}else pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled;
+		} else pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled;
 
 		break;
 	case IW_AUTH_CIPHER_GROUP:
-		if(wpa_version == IW_AUTH_WPA_VERSION_DISABLED)
+		if (wpa_version == IW_AUTH_WPA_VERSION_DISABLED)
 			break;
-		if(pairwise == IW_AUTH_CIPHER_NONE){
-			if(wrq->value == IW_AUTH_CIPHER_CCMP){
+		if (pairwise == IW_AUTH_CIPHER_NONE) {
+			if (wrq->value == IW_AUTH_CIPHER_CCMP) {
 				pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled;
-			}else {
+			} else {
 				pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled;
 			}
 		}
 		break;
 	case IW_AUTH_KEY_MGMT:
 
-		if(wpa_version == IW_AUTH_WPA_VERSION_WPA2){
-			if(wrq->value == IW_AUTH_KEY_MGMT_PSK)
+		if (wpa_version == IW_AUTH_WPA_VERSION_WPA2) {
+			if (wrq->value == IW_AUTH_KEY_MGMT_PSK)
 				pMgmt->eAuthenMode = WMAC_AUTH_WPA2PSK;
 			else pMgmt->eAuthenMode = WMAC_AUTH_WPA2;
-		}else if(wpa_version == IW_AUTH_WPA_VERSION_WPA){
-			if(wrq->value == 0){
+		} else if (wpa_version == IW_AUTH_WPA_VERSION_WPA) {
+			if (wrq->value == 0) {
 				pMgmt->eAuthenMode = WMAC_AUTH_WPANONE;
-			}else if(wrq->value == IW_AUTH_KEY_MGMT_PSK)
+			} else if (wrq->value == IW_AUTH_KEY_MGMT_PSK)
 				pMgmt->eAuthenMode = WMAC_AUTH_WPAPSK;
 			else pMgmt->eAuthenMode = WMAC_AUTH_WPA;
 		}
@@ -1787,10 +1709,10 @@ int iwctl_siwauth(struct net_device *dev,
 	case IW_AUTH_DROP_UNENCRYPTED:
 		break;
 	case IW_AUTH_80211_AUTH_ALG:
-		if(wrq->value==IW_AUTH_ALG_OPEN_SYSTEM){
-			pMgmt->bShareKeyAlgorithm=false;
-		}else if(wrq->value==IW_AUTH_ALG_SHARED_KEY){
-			pMgmt->bShareKeyAlgorithm=true;
+		if (wrq->value == IW_AUTH_ALG_OPEN_SYSTEM) {
+			pMgmt->bShareKeyAlgorithm = false;
+		} else if (wrq->value == IW_AUTH_ALG_SHARED_KEY) {
+			pMgmt->bShareKeyAlgorithm = true;
 		}
 		break;
 	case IW_AUTH_WPA_ENABLED:
@@ -1803,7 +1725,7 @@ int iwctl_siwauth(struct net_device *dev,
 		break;
 	case IW_AUTH_PRIVACY_INVOKED:
 		pDevice->bEncryptionEnable = !!wrq->value;
-		if(pDevice->bEncryptionEnable == false){
+		if (pDevice->bEncryptionEnable == false) {
 			wpa_version = 0;
 			pairwise = 0;
 			pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled;
@@ -1818,220 +1740,214 @@ int iwctl_siwauth(struct net_device *dev,
 		break;
 	}
 /*
-	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wpa_version = %d\n",wpa_version);
-	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pairwise = %d\n",pairwise);
-	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pDevice->eEncryptionStatus = %d\n",pDevice->eEncryptionStatus);
-	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pMgmt->eAuthenMode  = %d\n",pMgmt->eAuthenMode);
-	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pMgmt->bShareKeyAlgorithm = %s\n",pMgmt->bShareKeyAlgorithm?"true":"false");
-	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pDevice->bEncryptionEnable = %s\n",pDevice->bEncryptionEnable?"true":"false");
-	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pDevice->bWPADevEnable = %s\n",pDevice->bWPADevEnable?"true":"false");
+  DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wpa_version = %d\n",wpa_version);
+  DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pairwise = %d\n",pairwise);
+  DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pDevice->eEncryptionStatus = %d\n",pDevice->eEncryptionStatus);
+  DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pMgmt->eAuthenMode  = %d\n",pMgmt->eAuthenMode);
+  DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pMgmt->bShareKeyAlgorithm = %s\n",pMgmt->bShareKeyAlgorithm?"true":"false");
+  DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pDevice->bEncryptionEnable = %s\n",pDevice->bEncryptionEnable?"true":"false");
+  DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pDevice->bWPADevEnable = %s\n",pDevice->bWPADevEnable?"true":"false");
 */
-   return ret;
+	return ret;
 }
 
-
 int iwctl_giwauth(struct net_device *dev,
-			  struct iw_request_info *info,
-			  struct iw_param *wrq,
-			  char *extra)
+		  struct iw_request_info *info,
+		  struct iw_param *wrq,
+		  char *extra)
 {
 	return -EOPNOTSUPP;
 }
 
-
-
 int iwctl_siwgenie(struct net_device *dev,
-			  struct iw_request_info *info,
-			  struct iw_point *wrq,
-			  char *extra)
+		   struct iw_request_info *info,
+		   struct iw_point *wrq,
+		   char *extra)
 {
 	PSDevice			pDevice = (PSDevice)netdev_priv(dev);
 	PSMgmtObject	pMgmt = &(pDevice->sMgmtObj);
-	int ret=0;
+	int ret = 0;
 
-	if(wrq->length){
+	if (wrq->length) {
 		if ((wrq->length < 2) || (extra[1]+2 != wrq->length)) {
 			ret = -EINVAL;
 			goto out;
 		}
-		if(wrq->length > MAX_WPA_IE_LEN){
+		if (wrq->length > MAX_WPA_IE_LEN) {
 			ret = -ENOMEM;
 			goto out;
 		}
 		memset(pMgmt->abyWPAIE, 0, MAX_WPA_IE_LEN);
-		if(copy_from_user(pMgmt->abyWPAIE, extra, wrq->length)){
+		if (copy_from_user(pMgmt->abyWPAIE, extra, wrq->length)) {
 			ret = -EFAULT;
 			goto out;
 		}
 		pMgmt->wWPAIELen = wrq->length;
-	}else {
+	} else {
 		memset(pMgmt->abyWPAIE, 0, MAX_WPA_IE_LEN);
 		pMgmt->wWPAIELen = 0;
 	}
 
-	out://not completely ...not necessary in wpa_supplicant 0.5.8
+out://not completely ...not necessary in wpa_supplicant 0.5.8
 	return ret;
 }
 
 int iwctl_giwgenie(struct net_device *dev,
-			  struct iw_request_info *info,
-			  struct iw_point *wrq,
-			  char *extra)
+		   struct iw_request_info *info,
+		   struct iw_point *wrq,
+		   char *extra)
 {
 	PSDevice			pDevice = (PSDevice)netdev_priv(dev);
 	PSMgmtObject	pMgmt = &(pDevice->sMgmtObj);
-	int ret=0;
+	int ret = 0;
 	int space = wrq->length;
 
 	wrq->length = 0;
-	if(pMgmt->wWPAIELen > 0){
+	if (pMgmt->wWPAIELen > 0) {
 		wrq->length = pMgmt->wWPAIELen;
-		if(pMgmt->wWPAIELen <= space){
-			if(copy_to_user(extra, pMgmt->abyWPAIE, pMgmt->wWPAIELen)){
+		if (pMgmt->wWPAIELen <= space) {
+			if (copy_to_user(extra, pMgmt->abyWPAIE, pMgmt->wWPAIELen)) {
 				ret = -EFAULT;
 			}
-		}else
+		} else
 			ret = -E2BIG;
 	}
 
 	return ret;
 }
 
-
 int iwctl_siwencodeext(struct net_device *dev,
-             struct iw_request_info *info,
-             struct iw_point *wrq,
-             char *extra)
+		       struct iw_request_info *info,
+		       struct iw_point *wrq,
+		       char *extra)
 {
-    PSDevice	        pDevice = (PSDevice)netdev_priv(dev);
-	struct iw_encode_ext *ext = (struct iw_encode_ext*)extra;
-    struct viawget_wpa_param *param=NULL;
+	PSDevice	        pDevice = (PSDevice)netdev_priv(dev);
+	struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
+	struct viawget_wpa_param *param = NULL;
 //original member
-    wpa_alg alg_name;
-    u8  addr[6];
-    int key_idx, set_tx=0;
-    u8  seq[IW_ENCODE_SEQ_MAX_SIZE];
-    u8 key[64];
-    size_t seq_len=0,key_len=0;
+	wpa_alg alg_name;
+	u8  addr[6];
+	int key_idx, set_tx = 0;
+	u8  seq[IW_ENCODE_SEQ_MAX_SIZE];
+	u8 key[64];
+	size_t seq_len = 0, key_len = 0;
 //
-   // int ii;
-    u8 *buf;
-    size_t blen;
-    u8 key_array[64];
-    int ret=0;
+	// int ii;
+	u8 *buf;
+	size_t blen;
+	u8 key_array[64];
+	int ret = 0;
 
-PRINT_K("SIOCSIWENCODEEXT...... \n");
+	PRINT_K("SIOCSIWENCODEEXT...... \n");
 
-blen = sizeof(*param);
-buf = kmalloc((int)blen, (int)GFP_KERNEL);
-if (buf == NULL)
-    return -ENOMEM;
-memset(buf, 0, blen);
-param = (struct viawget_wpa_param *) buf;
+	blen = sizeof(*param);
+	buf = kmalloc((int)blen, (int)GFP_KERNEL);
+	if (buf == NULL)
+		return -ENOMEM;
+	memset(buf, 0, blen);
+	param = (struct viawget_wpa_param *)buf;
 
 //recover alg_name
-switch (ext->alg) {
-    case IW_ENCODE_ALG_NONE:
-                  alg_name = WPA_ALG_NONE;
+	switch (ext->alg) {
+	case IW_ENCODE_ALG_NONE:
+		alg_name = WPA_ALG_NONE;
 		break;
-    case IW_ENCODE_ALG_WEP:
-                  alg_name = WPA_ALG_WEP;
+	case IW_ENCODE_ALG_WEP:
+		alg_name = WPA_ALG_WEP;
 		break;
-    case IW_ENCODE_ALG_TKIP:
-                  alg_name = WPA_ALG_TKIP;
+	case IW_ENCODE_ALG_TKIP:
+		alg_name = WPA_ALG_TKIP;
 		break;
-    case IW_ENCODE_ALG_CCMP:
-                  alg_name = WPA_ALG_CCMP;
+	case IW_ENCODE_ALG_CCMP:
+		alg_name = WPA_ALG_CCMP;
 		break;
-    default:
-		PRINT_K("Unknown alg = %d\n",ext->alg);
-		ret= -ENOMEM;
+	default:
+		PRINT_K("Unknown alg = %d\n", ext->alg);
+		ret = -ENOMEM;
 		goto error;
-		}
+	}
 //recover addr
- memcpy(addr, ext->addr.sa_data, ETH_ALEN);
+	memcpy(addr, ext->addr.sa_data, ETH_ALEN);
 //recover key_idx
-  key_idx = (wrq->flags&IW_ENCODE_INDEX) - 1;
+	key_idx = (wrq->flags&IW_ENCODE_INDEX) - 1;
 //recover set_tx
-if(ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
-   set_tx = 1;
+	if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
+		set_tx = 1;
 //recover seq,seq_len
-	if(ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
-   seq_len=IW_ENCODE_SEQ_MAX_SIZE;
-   memcpy(seq, ext->rx_seq, seq_len);
-		}
+	if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
+		seq_len = IW_ENCODE_SEQ_MAX_SIZE;
+		memcpy(seq, ext->rx_seq, seq_len);
+	}
 //recover key,key_len
-if(ext->key_len) {
-  key_len=ext->key_len;
-  memcpy(key, &ext->key[0], key_len);
+	if (ext->key_len) {
+		key_len = ext->key_len;
+		memcpy(key, &ext->key[0], key_len);
 	}
 
-memset(key_array, 0, 64);
-if ( key_len > 0) {
-     memcpy(key_array, key, key_len);
-    if (key_len == 32) {
-          // notice ! the oder
-	  memcpy(&key_array[16], &key[24], 8);
-	  memcpy(&key_array[24], &key[16], 8);
-	}
+	memset(key_array, 0, 64);
+	if (key_len > 0) {
+		memcpy(key_array, key, key_len);
+		if (key_len == 32) {
+			// notice ! the oder
+			memcpy(&key_array[16], &key[24], 8);
+			memcpy(&key_array[24], &key[16], 8);
+		}
 	}
 
 /**************Translate iw_encode_ext to viawget_wpa_param****************/
-memcpy(param->addr, addr, ETH_ALEN);
-param->u.wpa_key.alg_name = (int)alg_name;
-param->u.wpa_key.set_tx = set_tx;
-param->u.wpa_key.key_index = key_idx;
-param->u.wpa_key.key_len = key_len;
-param->u.wpa_key.key = (u8 *)key_array;
-param->u.wpa_key.seq = (u8 *)seq;
-param->u.wpa_key.seq_len = seq_len;
+	memcpy(param->addr, addr, ETH_ALEN);
+	param->u.wpa_key.alg_name = (int)alg_name;
+	param->u.wpa_key.set_tx = set_tx;
+	param->u.wpa_key.key_index = key_idx;
+	param->u.wpa_key.key_len = key_len;
+	param->u.wpa_key.key = (u8 *)key_array;
+	param->u.wpa_key.seq = (u8 *)seq;
+	param->u.wpa_key.seq_len = seq_len;
 
 //****set if current action is Network Manager count??
 //****this method is so foolish,but there is no other way???
-if(param->u.wpa_key.alg_name == WPA_ALG_NONE) {
-   if(param->u.wpa_key.key_index ==0) {
-     pDevice->bwextcount++;
-    }
-   if((pDevice->bwextcount == 1)&&(param->u.wpa_key.key_index ==1)) {
- pDevice->bwextcount++;
-    }
-   if((pDevice->bwextcount ==2)&&(param->u.wpa_key.key_index ==2)) {
- pDevice->bwextcount++;
+	if (param->u.wpa_key.alg_name == WPA_ALG_NONE) {
+		if (param->u.wpa_key.key_index == 0) {
+			pDevice->bwextcount++;
+		}
+		if ((pDevice->bwextcount == 1) && (param->u.wpa_key.key_index == 1)) {
+			pDevice->bwextcount++;
+		}
+		if ((pDevice->bwextcount == 2) && (param->u.wpa_key.key_index == 2)) {
+			pDevice->bwextcount++;
+		}
+		if ((pDevice->bwextcount == 3) && (param->u.wpa_key.key_index == 3)) {
+			pDevice->bwextcount++;
+		}
+	}
+	if (pDevice->bwextcount == 4) {
+		printk("SIOCSIWENCODEEXT:Enable WPA WEXT SUPPORT!!!!!\n");
+		pDevice->bwextcount = 0;
+		pDevice->bWPASuppWextEnabled = true;
 	}
-   if((pDevice->bwextcount ==3)&&(param->u.wpa_key.key_index ==3)) {
- pDevice->bwextcount++;
-        }
-		 }
-if( pDevice->bwextcount == 4) {
-    printk("SIOCSIWENCODEEXT:Enable WPA WEXT SUPPORT!!!!!\n");
- pDevice->bwextcount=0;
-   pDevice->bWPASuppWextEnabled = true;
-		 }
 //******
 
-		spin_lock_irq(&pDevice->lock);
- ret = wpa_set_keys(pDevice, param, true);
-		spin_unlock_irq(&pDevice->lock);
+	spin_lock_irq(&pDevice->lock);
+	ret = wpa_set_keys(pDevice, param, true);
+	spin_unlock_irq(&pDevice->lock);
 
 error:
-kfree(param);
+	kfree(param);
 	return ret;
 }
 
-
-
 int iwctl_giwencodeext(struct net_device *dev,
-             struct iw_request_info *info,
-             struct iw_point *wrq,
-             char *extra)
+		       struct iw_request_info *info,
+		       struct iw_point *wrq,
+		       char *extra)
 {
-		return -EOPNOTSUPP;
+	return -EOPNOTSUPP;
 }
 
 int iwctl_siwmlme(struct net_device *dev,
-				struct iw_request_info * info,
-				struct iw_point *wrq,
-				char *extra)
+		  struct iw_request_info *info,
+		  struct iw_point *wrq,
+		  char *extra)
 {
 	PSDevice			pDevice = (PSDevice)netdev_priv(dev);
 	PSMgmtObject	pMgmt = &(pDevice->sMgmtObj);
@@ -2039,21 +1955,21 @@ int iwctl_siwmlme(struct net_device *dev,
 	//u16 reason = cpu_to_le16(mlme->reason_code);
 	int ret = 0;
 
-	if(memcmp(pMgmt->abyCurrBSSID, mlme->addr.sa_data, ETH_ALEN)){
+	if (memcmp(pMgmt->abyCurrBSSID, mlme->addr.sa_data, ETH_ALEN)) {
 		ret = -EINVAL;
 		return ret;
 	}
-	switch(mlme->cmd){
+	switch (mlme->cmd) {
 	case IW_MLME_DEAUTH:
 		//this command seems to be not complete,please test it --einsnliu
 		//bScheduleCommand((void *) pDevice, WLAN_CMD_DEAUTH, (unsigned char *)&reason);
 		break;
 	case IW_MLME_DISASSOC:
-		if(pDevice->bLinkPass == true){
-					  printk("iwctl_siwmlme--->send DISASSOCIATE\n");
-		  //clear related flags
-		   memset(pMgmt->abyDesireBSSID, 0xFF,6);
-		KeyvInitTable(&pDevice->sKey, pDevice->PortOffset);
+		if (pDevice->bLinkPass == true) {
+			printk("iwctl_siwmlme--->send DISASSOCIATE\n");
+			//clear related flags
+			memset(pMgmt->abyDesireBSSID, 0xFF, 6);
+			KeyvInitTable(&pDevice->sKey, pDevice->PortOffset);
 			bScheduleCommand((void *)pDevice, WLAN_CMD_DISASSOCIATE, NULL);
 		}
 		break;
@@ -2062,109 +1978,106 @@ int iwctl_siwmlme(struct net_device *dev,
 	}
 
 	return ret;
-
 }
 
 #endif
 
-
 /*------------------------------------------------------------------*/
 /*
  * Structures to export the Wireless Handlers
  */
 
-
 /*
-static const iw_handler		iwctl_handler[] =
-{
-	(iw_handler) iwctl_commit,      // SIOCSIWCOMMIT
-	(iw_handler) iwctl_giwname,     // SIOCGIWNAME
-	(iw_handler) NULL,				// SIOCSIWNWID
-	(iw_handler) NULL,				// SIOCGIWNWID
-	(iw_handler) iwctl_siwfreq,		// SIOCSIWFREQ
-	(iw_handler) iwctl_giwfreq,		// SIOCGIWFREQ
-	(iw_handler) iwctl_siwmode,		// SIOCSIWMODE
-	(iw_handler) iwctl_giwmode,		// SIOCGIWMODE
-	(iw_handler) NULL,		        // SIOCSIWSENS
-	(iw_handler) iwctl_giwsens,		        // SIOCGIWSENS
-	(iw_handler) NULL, 		        // SIOCSIWRANGE
-	(iw_handler) iwctl_giwrange,		// SIOCGIWRANGE
-	(iw_handler) NULL,         		    // SIOCSIWPRIV
-	(iw_handler) NULL,             		// SIOCGIWPRIV
-	(iw_handler) NULL,             		// SIOCSIWSTATS
-	(iw_handler) NULL,                  // SIOCGIWSTATS
-    (iw_handler) NULL,                  // SIOCSIWSPY
-	(iw_handler) NULL,		            // SIOCGIWSPY
-	(iw_handler) NULL,				    // -- hole --
-	(iw_handler) NULL,				    // -- hole --
-	(iw_handler) iwctl_siwap,		    // SIOCSIWAP
-	(iw_handler) iwctl_giwap,		    // SIOCGIWAP
-	(iw_handler) NULL,				    // -- hole -- 0x16
-	(iw_handler) iwctl_giwaplist,       // SIOCGIWAPLIST
-	(iw_handler) iwctl_siwscan,         // SIOCSIWSCAN
-	(iw_handler) iwctl_giwscan,         // SIOCGIWSCAN
-	(iw_handler) iwctl_siwessid,		// SIOCSIWESSID
-	(iw_handler) iwctl_giwessid,		// SIOCGIWESSID
-	(iw_handler) NULL,		// SIOCSIWNICKN
-	(iw_handler) NULL,		// SIOCGIWNICKN
-	(iw_handler) NULL,				    // -- hole --
-	(iw_handler) NULL,				    // -- hole --
-	(iw_handler) iwctl_siwrate,		// SIOCSIWRATE 0x20
-	(iw_handler) iwctl_giwrate,		// SIOCGIWRATE
-	(iw_handler) iwctl_siwrts,		// SIOCSIWRTS
-	(iw_handler) iwctl_giwrts,		// SIOCGIWRTS
-	(iw_handler) iwctl_siwfrag,		// SIOCSIWFRAG
-	(iw_handler) iwctl_giwfrag,		// SIOCGIWFRAG
-	(iw_handler) NULL,		// SIOCSIWTXPOW
-	(iw_handler) NULL,		// SIOCGIWTXPOW
-	(iw_handler) iwctl_siwretry,		// SIOCSIWRETRY
-	(iw_handler) iwctl_giwretry,		// SIOCGIWRETRY
-	(iw_handler) iwctl_siwencode,		// SIOCSIWENCODE
-	(iw_handler) iwctl_giwencode,		// SIOCGIWENCODE
-	(iw_handler) iwctl_siwpower,		// SIOCSIWPOWER
-	(iw_handler) iwctl_giwpower,		// SIOCGIWPOWER
-	(iw_handler) NULL,			// -- hole --
-	(iw_handler) NULL,			// -- hole --
-	(iw_handler) iwctl_siwgenie,    // SIOCSIWGENIE
-	(iw_handler) iwctl_giwgenie,    // SIOCGIWGENIE
-	(iw_handler) iwctl_siwauth,		// SIOCSIWAUTH
-	(iw_handler) iwctl_giwauth,		// SIOCGIWAUTH
-	(iw_handler) iwctl_siwencodeext,		// SIOCSIWENCODEEXT
-	(iw_handler) iwctl_giwencodeext,		// SIOCGIWENCODEEXT
-	(iw_handler) NULL,				// SIOCSIWPMKSA
-	(iw_handler) NULL,				// -- hole --
-
-};
+  static const iw_handler		iwctl_handler[] =
+  {
+  (iw_handler) iwctl_commit,      // SIOCSIWCOMMIT
+  (iw_handler) iwctl_giwname,     // SIOCGIWNAME
+  (iw_handler) NULL,				// SIOCSIWNWID
+  (iw_handler) NULL,				// SIOCGIWNWID
+  (iw_handler) iwctl_siwfreq,		// SIOCSIWFREQ
+  (iw_handler) iwctl_giwfreq,		// SIOCGIWFREQ
+  (iw_handler) iwctl_siwmode,		// SIOCSIWMODE
+  (iw_handler) iwctl_giwmode,		// SIOCGIWMODE
+  (iw_handler) NULL,		        // SIOCSIWSENS
+  (iw_handler) iwctl_giwsens,		        // SIOCGIWSENS
+  (iw_handler) NULL,		        // SIOCSIWRANGE
+  (iw_handler) iwctl_giwrange,		// SIOCGIWRANGE
+  (iw_handler) NULL,			// SIOCSIWPRIV
+  (iw_handler) NULL,			// SIOCGIWPRIV
+  (iw_handler) NULL,			// SIOCSIWSTATS
+  (iw_handler) NULL,                  // SIOCGIWSTATS
+  (iw_handler) NULL,                  // SIOCSIWSPY
+  (iw_handler) NULL,		            // SIOCGIWSPY
+  (iw_handler) NULL,				    // -- hole --
+  (iw_handler) NULL,				    // -- hole --
+  (iw_handler) iwctl_siwap,		    // SIOCSIWAP
+  (iw_handler) iwctl_giwap,		    // SIOCGIWAP
+  (iw_handler) NULL,				    // -- hole -- 0x16
+  (iw_handler) iwctl_giwaplist,       // SIOCGIWAPLIST
+  (iw_handler) iwctl_siwscan,         // SIOCSIWSCAN
+  (iw_handler) iwctl_giwscan,         // SIOCGIWSCAN
+  (iw_handler) iwctl_siwessid,		// SIOCSIWESSID
+  (iw_handler) iwctl_giwessid,		// SIOCGIWESSID
+  (iw_handler) NULL,		// SIOCSIWNICKN
+  (iw_handler) NULL,		// SIOCGIWNICKN
+  (iw_handler) NULL,				    // -- hole --
+  (iw_handler) NULL,				    // -- hole --
+  (iw_handler) iwctl_siwrate,		// SIOCSIWRATE 0x20
+  (iw_handler) iwctl_giwrate,		// SIOCGIWRATE
+  (iw_handler) iwctl_siwrts,		// SIOCSIWRTS
+  (iw_handler) iwctl_giwrts,		// SIOCGIWRTS
+  (iw_handler) iwctl_siwfrag,		// SIOCSIWFRAG
+  (iw_handler) iwctl_giwfrag,		// SIOCGIWFRAG
+  (iw_handler) NULL,		// SIOCSIWTXPOW
+  (iw_handler) NULL,		// SIOCGIWTXPOW
+  (iw_handler) iwctl_siwretry,		// SIOCSIWRETRY
+  (iw_handler) iwctl_giwretry,		// SIOCGIWRETRY
+  (iw_handler) iwctl_siwencode,		// SIOCSIWENCODE
+  (iw_handler) iwctl_giwencode,		// SIOCGIWENCODE
+  (iw_handler) iwctl_siwpower,		// SIOCSIWPOWER
+  (iw_handler) iwctl_giwpower,		// SIOCGIWPOWER
+  (iw_handler) NULL,			// -- hole --
+  (iw_handler) NULL,			// -- hole --
+  (iw_handler) iwctl_siwgenie,    // SIOCSIWGENIE
+  (iw_handler) iwctl_giwgenie,    // SIOCGIWGENIE
+  (iw_handler) iwctl_siwauth,		// SIOCSIWAUTH
+  (iw_handler) iwctl_giwauth,		// SIOCGIWAUTH
+  (iw_handler) iwctl_siwencodeext,		// SIOCSIWENCODEEXT
+  (iw_handler) iwctl_giwencodeext,		// SIOCGIWENCODEEXT
+  (iw_handler) NULL,				// SIOCSIWPMKSA
+  (iw_handler) NULL,				// -- hole --
+
+  };
 */
 
 static const iw_handler		iwctl_handler[] =
 {
 	(iw_handler) iwctl_commit,      // SIOCSIWCOMMIT
-	(iw_handler) NULL,      // SIOCGIWNAME
-	(iw_handler) NULL,				// SIOCSIWNWID
-	(iw_handler) NULL,				// SIOCGIWNWID
+	(iw_handler) NULL,		// SIOCGIWNAME
+	(iw_handler) NULL,		// SIOCSIWNWID
+	(iw_handler) NULL,		// SIOCGIWNWID
 	(iw_handler) NULL,		// SIOCSIWFREQ
 	(iw_handler) NULL,		// SIOCGIWFREQ
 	(iw_handler) NULL,		// SIOCSIWMODE
 	(iw_handler) NULL,		// SIOCGIWMODE
-	(iw_handler) NULL,		        // SIOCSIWSENS
-	(iw_handler) NULL,		        // SIOCGIWSENS
-	(iw_handler) NULL, 		        // SIOCSIWRANGE
-	(iw_handler) iwctl_giwrange,		// SIOCGIWRANGE
-	(iw_handler) NULL,         		    // SIOCSIWPRIV
-	(iw_handler) NULL,             		// SIOCGIWPRIV
-	(iw_handler) NULL,             		// SIOCSIWSTATS
-	(iw_handler) NULL,                  // SIOCGIWSTATS
-    (iw_handler) NULL,                  // SIOCSIWSPY
-	(iw_handler) NULL,		            // SIOCGIWSPY
-	(iw_handler) NULL,				    // -- hole --
-	(iw_handler) NULL,				    // -- hole --
-	(iw_handler) NULL,		    // SIOCSIWAP
-	(iw_handler) NULL,		    // SIOCGIWAP
-	(iw_handler) NULL,				    // -- hole -- 0x16
-	(iw_handler) NULL,       // SIOCGIWAPLIST
-	(iw_handler) iwctl_siwscan,         // SIOCSIWSCAN
-	(iw_handler) iwctl_giwscan,         // SIOCGIWSCAN
+	(iw_handler) NULL,		// SIOCSIWSENS
+	(iw_handler) NULL,		// SIOCGIWSENS
+	(iw_handler) NULL,		// SIOCSIWRANGE
+	(iw_handler) iwctl_giwrange,	// SIOCGIWRANGE
+	(iw_handler) NULL,		// SIOCSIWPRIV
+	(iw_handler) NULL,		// SIOCGIWPRIV
+	(iw_handler) NULL,		// SIOCSIWSTATS
+	(iw_handler) NULL,		// SIOCGIWSTATS
+	(iw_handler) NULL,		// SIOCSIWSPY
+	(iw_handler) NULL,		// SIOCGIWSPY
+	(iw_handler) NULL,		// -- hole --
+	(iw_handler) NULL,		// -- hole --
+	(iw_handler) NULL,		// SIOCSIWAP
+	(iw_handler) NULL,		// SIOCGIWAP
+	(iw_handler) NULL,		// -- hole -- 0x16
+	(iw_handler) NULL,		// SIOCGIWAPLIST
+	(iw_handler) iwctl_siwscan,	// SIOCSIWSCAN
+	(iw_handler) iwctl_giwscan,	// SIOCGIWSCAN
 	(iw_handler) NULL,		// SIOCSIWESSID
 	(iw_handler) NULL,		// SIOCGIWESSID
 	(iw_handler) NULL,		// SIOCSIWNICKN
@@ -2187,33 +2100,29 @@ static const iw_handler		iwctl_handler[] =
 	(iw_handler) NULL,		// SIOCGIWPOWER
 
 //2008-0409-07, <Add> by Einsn Liu
-	(iw_handler) NULL,			// -- hole --
-	(iw_handler) NULL,			// -- hole --
-	(iw_handler) NULL,    // SIOCSIWGENIE
-	(iw_handler) NULL,    // SIOCGIWGENIE
+	(iw_handler) NULL,		// -- hole --
+	(iw_handler) NULL,		// -- hole --
+	(iw_handler) NULL,		// SIOCSIWGENIE
+	(iw_handler) NULL,		// SIOCGIWGENIE
 	(iw_handler) NULL,		// SIOCSIWAUTH
 	(iw_handler) NULL,		// SIOCGIWAUTH
 	(iw_handler) NULL,		// SIOCSIWENCODEEXT
 	(iw_handler) NULL,		// SIOCGIWENCODEEXT
-	(iw_handler) NULL,				// SIOCSIWPMKSA
-	(iw_handler) NULL,				// -- hole --
+	(iw_handler) NULL,		// SIOCSIWPMKSA
+	(iw_handler) NULL,		// -- hole --
 };
 
-
 static const iw_handler		iwctl_private_handler[] =
 {
 	NULL,				// SIOCIWFIRSTPRIV
 };
 
-
 struct iw_priv_args iwctl_private_args[] = {
-{ IOCTL_CMD_SET,
-  IW_PRIV_TYPE_CHAR | 1024, 0,
-  "set"},
+	{ IOCTL_CMD_SET,
+	  IW_PRIV_TYPE_CHAR | 1024, 0,
+	  "set"},
 };
 
-
-
 const struct iw_handler_def	iwctl_handler_def =
 {
 	.get_wireless_stats = &iwctl_get_wireless_stats,
@@ -2222,7 +2131,7 @@ const struct iw_handler_def	iwctl_handler_def =
 //	.num_private_args = sizeof(iwctl_private_args)/sizeof(struct iw_priv_args),
 	.num_private	= 0,
 	.num_private_args = 0,
-	.standard	= (iw_handler *) iwctl_handler,
+	.standard	= (iw_handler *)iwctl_handler,
 //	.private	= (iw_handler *) iwctl_private_handler,
 //	.private_args	= (struct iw_priv_args *)iwctl_private_args,
 	.private	= NULL,
diff --git a/drivers/staging/vt6655/iwctl.h b/drivers/staging/vt6655/iwctl.h
index d224f91..871bd7c 100644
--- a/drivers/staging/vt6655/iwctl.h
+++ b/drivers/staging/vt6655/iwctl.h
@@ -33,192 +33,184 @@
 
 /*---------------------  Export Definitions -------------------------*/
 
-
 /*---------------------  Export Classes  ----------------------------*/
 
 /*---------------------  Export Variables  --------------------------*/
 
 /*---------------------  Export Functions  --------------------------*/
 
-struct iw_statistics *iwctl_get_wireless_stats (struct net_device *dev);
-
+struct iw_statistics *iwctl_get_wireless_stats(struct net_device *dev);
 
 int iwctl_siwap(struct net_device *dev,
-             struct iw_request_info *info,
-			 struct sockaddr *wrq,
-             char *extra);
+		struct iw_request_info *info,
+		struct sockaddr *wrq,
+		char *extra);
 
 int iwctl_giwrange(struct net_device *dev,
-             struct iw_request_info *info,
-             struct iw_point *wrq,
-             char *extra);
-
+		   struct iw_request_info *info,
+		   struct iw_point *wrq,
+		   char *extra);
 
 int iwctl_giwmode(struct net_device *dev,
-             struct iw_request_info *info,
-             __u32 *wmode,
-             char *extra);
+		  struct iw_request_info *info,
+		  __u32 *wmode,
+		  char *extra);
 
 int iwctl_siwmode(struct net_device *dev,
-             struct iw_request_info *info,
-             __u32 *wmode,
-             char *extra);
+		  struct iw_request_info *info,
+		  __u32 *wmode,
+		  char *extra);
 
 int iwctl_giwfreq(struct net_device *dev,
-             struct iw_request_info *info,
-             struct iw_freq *wrq,
-             char *extra);
+		  struct iw_request_info *info,
+		  struct iw_freq *wrq,
+		  char *extra);
 
 int iwctl_siwfreq(struct net_device *dev,
-             struct iw_request_info *info,
-             struct iw_freq *wrq,
-             char *extra);
+		  struct iw_request_info *info,
+		  struct iw_freq *wrq,
+		  char *extra);
 
 int iwctl_giwname(struct net_device *dev,
-			 struct iw_request_info *info,
-			 char *wrq,
-			 char *extra);
+		  struct iw_request_info *info,
+		  char *wrq,
+		  char *extra);
 
 int iwctl_giwsens(struct net_device *dev,
-			 struct iw_request_info *info,
-			 struct iw_param *wrq,
-			 char *extra);
+		  struct iw_request_info *info,
+		  struct iw_param *wrq,
+		  char *extra);
 
 int iwctl_giwap(struct net_device *dev,
-             struct iw_request_info *info,
-			 struct sockaddr *wrq,
-             char *extra);
+		struct iw_request_info *info,
+		struct sockaddr *wrq,
+		char *extra);
 
 int iwctl_giwaplist(struct net_device *dev,
-             struct iw_request_info *info,
-             struct iw_point *wrq,
-             char *extra);
+		    struct iw_request_info *info,
+		    struct iw_point *wrq,
+		    char *extra);
 
 int iwctl_siwessid(struct net_device *dev,
-             struct iw_request_info *info,
-             struct iw_point *wrq,
-             char *extra);
+		   struct iw_request_info *info,
+		   struct iw_point *wrq,
+		   char *extra);
 
 int iwctl_giwessid(struct net_device *dev,
-             struct iw_request_info *info,
-             struct iw_point *wrq,
-             char *extra);
+		   struct iw_request_info *info,
+		   struct iw_point *wrq,
+		   char *extra);
 
 int iwctl_siwrate(struct net_device *dev,
-             struct iw_request_info *info,
-			 struct iw_param *wrq,
-             char *extra);
+		  struct iw_request_info *info,
+		  struct iw_param *wrq,
+		  char *extra);
 
 int iwctl_giwrate(struct net_device *dev,
-             struct iw_request_info *info,
-             struct iw_param *wrq,
-             char *extra);
+		  struct iw_request_info *info,
+		  struct iw_param *wrq,
+		  char *extra);
 
 int iwctl_siwrts(struct net_device *dev,
-             struct iw_request_info *info,
-			 struct iw_param *wrq,
-             char *extra);
-
+		 struct iw_request_info *info,
+		 struct iw_param *wrq,
+		 char *extra);
 
 int iwctl_giwrts(struct net_device *dev,
-             struct iw_request_info *info,
-			 struct iw_param *wrq,
-             char *extra);
+		 struct iw_request_info *info,
+		 struct iw_param *wrq,
+		 char *extra);
 
 int iwctl_siwfrag(struct net_device *dev,
-             struct iw_request_info *info,
-			 struct iw_param *wrq,
-             char *extra);
+		  struct iw_request_info *info,
+		  struct iw_param *wrq,
+		  char *extra);
 
 int iwctl_giwfrag(struct net_device *dev,
-             struct iw_request_info *info,
-			 struct iw_param *wrq,
-             char *extra);
+		  struct iw_request_info *info,
+		  struct iw_param *wrq,
+		  char *extra);
 
 int iwctl_siwretry(struct net_device *dev,
-             struct iw_request_info *info,
-			 struct iw_param *wrq,
-             char *extra);
+		   struct iw_request_info *info,
+		   struct iw_param *wrq,
+		   char *extra);
 
 int iwctl_giwretry(struct net_device *dev,
-             struct iw_request_info *info,
-			 struct iw_param *wrq,
-             char *extra);
+		   struct iw_request_info *info,
+		   struct iw_param *wrq,
+		   char *extra);
 
 int iwctl_siwencode(struct net_device *dev,
-             struct iw_request_info *info,
-             struct iw_point *wrq,
-             char *extra);
+		    struct iw_request_info *info,
+		    struct iw_point *wrq,
+		    char *extra);
 
 int iwctl_giwencode(struct net_device *dev,
-             struct iw_request_info *info,
-             struct iw_point *wrq,
-             char *extra);
+		    struct iw_request_info *info,
+		    struct iw_point *wrq,
+		    char *extra);
 
 int iwctl_siwpower(struct net_device *dev,
-             struct iw_request_info *info,
-			 struct iw_param *wrq,
-             char *extra);
+		   struct iw_request_info *info,
+		   struct iw_param *wrq,
+		   char *extra);
 
 int iwctl_giwpower(struct net_device *dev,
-             struct iw_request_info *info,
-			 struct iw_param *wrq,
-             char *extra);
+		   struct iw_request_info *info,
+		   struct iw_param *wrq,
+		   char *extra);
 
 int iwctl_giwscan(struct net_device *dev,
-             struct iw_request_info *info,
-			 struct iw_point *wrq,
-             char *extra);
+		  struct iw_request_info *info,
+		  struct iw_point *wrq,
+		  char *extra);
 
 int iwctl_siwscan(struct net_device *dev,
-             struct iw_request_info *info,
-			 struct iw_param *wrq,
-             char *extra);
+		  struct iw_request_info *info,
+		  struct iw_param *wrq,
+		  char *extra);
 
 //2008-0409-07, <Add> by Einsn Liu
 #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
 int iwctl_siwauth(struct net_device *dev,
-			  struct iw_request_info *info,
-			  struct iw_param *wrq,
-			  char *extra);
+		  struct iw_request_info *info,
+		  struct iw_param *wrq,
+		  char *extra);
 
 int iwctl_giwauth(struct net_device *dev,
-			  struct iw_request_info *info,
-			  struct iw_param *wrq,
-			  char *extra);
+		  struct iw_request_info *info,
+		  struct iw_param *wrq,
+		  char *extra);
 
 int iwctl_siwgenie(struct net_device *dev,
-			  struct iw_request_info *info,
-			  struct iw_point *wrq,
-			  char *extra);
+		   struct iw_request_info *info,
+		   struct iw_point *wrq,
+		   char *extra);
 
 int iwctl_giwgenie(struct net_device *dev,
-			  struct iw_request_info *info,
-			  struct iw_point *wrq,
-			  char *extra);
+		   struct iw_request_info *info,
+		   struct iw_point *wrq,
+		   char *extra);
 
 int iwctl_siwencodeext(struct net_device *dev,
-             struct iw_request_info *info,
-             struct iw_point *wrq,
-             char *extra);
+		       struct iw_request_info *info,
+		       struct iw_point *wrq,
+		       char *extra);
 
 int iwctl_giwencodeext(struct net_device *dev,
-             struct iw_request_info *info,
-             struct iw_point *wrq,
-             char *extra);
+		       struct iw_request_info *info,
+		       struct iw_point *wrq,
+		       char *extra);
 
 int iwctl_siwmlme(struct net_device *dev,
-			struct iw_request_info * info,
-			struct iw_point *wrq,
-			char *extra);
+		  struct iw_request_info *info,
+		  struct iw_point *wrq,
+		  char *extra);
 #endif // #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
 //End Add -- //2008-0409-07, <Add> by Einsn Liu
 
-
 extern const struct iw_handler_def	iwctl_handler_def;
 extern const struct iw_priv_args	iwctl_private_args;
 
 #endif // __IWCTL_H__
-
-
-
diff --git a/drivers/staging/vt6655/key.c b/drivers/staging/vt6655/key.c
index 194fedc..92b84b5 100644
--- a/drivers/staging/vt6655/key.c
+++ b/drivers/staging/vt6655/key.c
@@ -45,7 +45,7 @@
 /*---------------------  Static Classes  ----------------------------*/
 
 /*---------------------  Static Variables  --------------------------*/
-static int          msglevel                =MSG_LEVEL_INFO;
+static int msglevel = MSG_LEVEL_INFO;
 //static int          msglevel                =MSG_LEVEL_DEBUG;
 /*---------------------  Static Functions  --------------------------*/
 
@@ -59,31 +59,28 @@ static int          msglevel                =MSG_LEVEL_INFO;
 
 /*---------------------  Static Functions  --------------------------*/
 static void
-s_vCheckKeyTableValid (PSKeyManagement pTable, unsigned long dwIoBase)
+s_vCheckKeyTableValid(PSKeyManagement pTable, unsigned long dwIoBase)
 {
-    int i;
-
-    for (i=0;i<MAX_KEY_TABLE;i++) {
-        if ((pTable->KeyTable[i].bInUse == true) &&
-            (pTable->KeyTable[i].PairwiseKey.bKeyValid == false) &&
-            (pTable->KeyTable[i].GroupKey[0].bKeyValid == false) &&
-            (pTable->KeyTable[i].GroupKey[1].bKeyValid == false) &&
-            (pTable->KeyTable[i].GroupKey[2].bKeyValid == false) &&
-            (pTable->KeyTable[i].GroupKey[3].bKeyValid == false)
-            ) {
-
-            pTable->KeyTable[i].bInUse = false;
-            pTable->KeyTable[i].wKeyCtl = 0;
-            pTable->KeyTable[i].bSoftWEP = false;
-            MACvDisableKeyEntry(dwIoBase, i);
-        }
-    }
+	int i;
+
+	for (i = 0; i < MAX_KEY_TABLE; i++) {
+		if ((pTable->KeyTable[i].bInUse == true) &&
+		    (pTable->KeyTable[i].PairwiseKey.bKeyValid == false) &&
+		    (pTable->KeyTable[i].GroupKey[0].bKeyValid == false) &&
+		    (pTable->KeyTable[i].GroupKey[1].bKeyValid == false) &&
+		    (pTable->KeyTable[i].GroupKey[2].bKeyValid == false) &&
+		    (pTable->KeyTable[i].GroupKey[3].bKeyValid == false)
+) {
+			pTable->KeyTable[i].bInUse = false;
+			pTable->KeyTable[i].wKeyCtl = 0;
+			pTable->KeyTable[i].bSoftWEP = false;
+			MACvDisableKeyEntry(dwIoBase, i);
+		}
+	}
 }
 
-
 /*---------------------  Export Functions  --------------------------*/
 
-
 /*
  * Description: Init Key management table
  *
@@ -96,27 +93,26 @@ s_vCheckKeyTableValid (PSKeyManagement pTable, unsigned long dwIoBase)
  * Return Value: none
  *
  */
-void KeyvInitTable (PSKeyManagement pTable, unsigned long dwIoBase)
+void KeyvInitTable(PSKeyManagement pTable, unsigned long dwIoBase)
 {
-    int i;
-    int jj;
-
-    for (i=0;i<MAX_KEY_TABLE;i++) {
-        pTable->KeyTable[i].bInUse = false;
-        pTable->KeyTable[i].PairwiseKey.bKeyValid = false;
-        pTable->KeyTable[i].PairwiseKey.pvKeyTable = (void *)&pTable->KeyTable[i];
-        for (jj=0; jj < MAX_GROUP_KEY; jj++) {
-            pTable->KeyTable[i].GroupKey[jj].bKeyValid = false;
-            pTable->KeyTable[i].GroupKey[jj].pvKeyTable = (void *)&pTable->KeyTable[i];
-        }
-        pTable->KeyTable[i].wKeyCtl = 0;
-        pTable->KeyTable[i].dwGTKeyIndex = 0;
-        pTable->KeyTable[i].bSoftWEP = false;
-        MACvDisableKeyEntry(dwIoBase, i);
-    }
+	int i;
+	int jj;
+
+	for (i = 0; i < MAX_KEY_TABLE; i++) {
+		pTable->KeyTable[i].bInUse = false;
+		pTable->KeyTable[i].PairwiseKey.bKeyValid = false;
+		pTable->KeyTable[i].PairwiseKey.pvKeyTable = (void *)&pTable->KeyTable[i];
+		for (jj = 0; jj < MAX_GROUP_KEY; jj++) {
+			pTable->KeyTable[i].GroupKey[jj].bKeyValid = false;
+			pTable->KeyTable[i].GroupKey[jj].pvKeyTable = (void *)&pTable->KeyTable[i];
+		}
+		pTable->KeyTable[i].wKeyCtl = 0;
+		pTable->KeyTable[i].dwGTKeyIndex = 0;
+		pTable->KeyTable[i].bSoftWEP = false;
+		MACvDisableKeyEntry(dwIoBase, i);
+	}
 }
 
-
 /*
  * Description: Get Key from table
  *
@@ -131,47 +127,43 @@ void KeyvInitTable (PSKeyManagement pTable, unsigned long dwIoBase)
  * Return Value: true if found otherwise false
  *
  */
-bool KeybGetKey (
-    PSKeyManagement pTable,
-    unsigned char *pbyBSSID,
-    unsigned long dwKeyIndex,
-    PSKeyItem       *pKey
-    )
+bool KeybGetKey(
+	PSKeyManagement pTable,
+	unsigned char *pbyBSSID,
+	unsigned long dwKeyIndex,
+	PSKeyItem       *pKey
+)
 {
-    int i;
-
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"KeybGetKey() \n");
-
-    *pKey = NULL;
-    for (i=0;i<MAX_KEY_TABLE;i++) {
-        if ((pTable->KeyTable[i].bInUse == true) &&
-            !compare_ether_addr(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
-            if (dwKeyIndex == 0xFFFFFFFF) {
-                if (pTable->KeyTable[i].PairwiseKey.bKeyValid == true) {
-                    *pKey = &(pTable->KeyTable[i].PairwiseKey);
-                    return (true);
-                }
-                else {
-                    return (false);
-                }
-            } else if (dwKeyIndex < MAX_GROUP_KEY) {
-                if (pTable->KeyTable[i].GroupKey[dwKeyIndex].bKeyValid == true) {
-                    *pKey = &(pTable->KeyTable[i].GroupKey[dwKeyIndex]);
-                    return (true);
-                }
-                else {
-                    return (false);
-                }
-            }
-            else {
-                return (false);
-            }
-        }
-    }
-    return (false);
+	int i;
+
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "KeybGetKey() \n");
+
+	*pKey = NULL;
+	for (i = 0; i < MAX_KEY_TABLE; i++) {
+		if ((pTable->KeyTable[i].bInUse == true) &&
+		    !compare_ether_addr(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
+			if (dwKeyIndex == 0xFFFFFFFF) {
+				if (pTable->KeyTable[i].PairwiseKey.bKeyValid == true) {
+					*pKey = &(pTable->KeyTable[i].PairwiseKey);
+					return true;
+				} else {
+					return false;
+				}
+			} else if (dwKeyIndex < MAX_GROUP_KEY) {
+				if (pTable->KeyTable[i].GroupKey[dwKeyIndex].bKeyValid == true) {
+					*pKey = &(pTable->KeyTable[i].GroupKey[dwKeyIndex]);
+					return true;
+				} else {
+					return false;
+				}
+			} else {
+				return false;
+			}
+		}
+	}
+	return false;
 }
 
-
 /*
  * Description: Set Key to table
  *
@@ -189,165 +181,162 @@ bool KeybGetKey (
  * Return Value: true if success otherwise false
  *
  */
-bool KeybSetKey (
-    PSKeyManagement pTable,
-    unsigned char *pbyBSSID,
-    unsigned long dwKeyIndex,
-    unsigned long uKeyLength,
-    PQWORD          pKeyRSC,
-    unsigned char *pbyKey,
-    unsigned char byKeyDecMode,
-    unsigned long dwIoBase,
-    unsigned char byLocalID
-    )
+bool KeybSetKey(
+	PSKeyManagement pTable,
+	unsigned char *pbyBSSID,
+	unsigned long dwKeyIndex,
+	unsigned long uKeyLength,
+	PQWORD          pKeyRSC,
+	unsigned char *pbyKey,
+	unsigned char byKeyDecMode,
+	unsigned long dwIoBase,
+	unsigned char byLocalID
+)
 {
-    int         i,j;
-    unsigned int ii;
-    PSKeyItem   pKey;
-    unsigned int uKeyIdx;
-
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Enter KeybSetKey: %lX\n", dwKeyIndex);
-
-    j = (MAX_KEY_TABLE-1);
-    for (i=0;i<(MAX_KEY_TABLE-1);i++) {
-        if ((pTable->KeyTable[i].bInUse == false) &&
-            (j == (MAX_KEY_TABLE-1))) {
-            // found empty table
-            j = i;
-        }
-        if ((pTable->KeyTable[i].bInUse == true) &&
-            !compare_ether_addr(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
-            // found table already exist
-            if ((dwKeyIndex & PAIRWISE_KEY) != 0) {
-                // Pairwise key
-                pKey = &(pTable->KeyTable[i].PairwiseKey);
-                pTable->KeyTable[i].wKeyCtl &= 0xFFF0;          // clear pairwise key control filed
-                pTable->KeyTable[i].wKeyCtl |= byKeyDecMode;
-                uKeyIdx = 4;                                    // use HW key entry 4 for pairwise key
-            } else {
-                // Group key
-                if ((dwKeyIndex & 0x000000FF) >= MAX_GROUP_KEY)
-                    return (false);
-                pKey = &(pTable->KeyTable[i].GroupKey[dwKeyIndex & 0x000000FF]);
-                if ((dwKeyIndex & TRANSMIT_KEY) != 0)  {
-                    // Group transmit key
-                    pTable->KeyTable[i].dwGTKeyIndex = dwKeyIndex;
-                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Group transmit key(R)[%lX]: %d\n", pTable->KeyTable[i].dwGTKeyIndex, i);
-                }
-                pTable->KeyTable[i].wKeyCtl &= 0xFF0F;          // clear group key control filed
-                pTable->KeyTable[i].wKeyCtl |= (byKeyDecMode << 4);
-                pTable->KeyTable[i].wKeyCtl |= 0x0040;          // use group key for group address
-                uKeyIdx = (dwKeyIndex & 0x000000FF);
-            }
-            pTable->KeyTable[i].wKeyCtl |= 0x8000;              // enable on-fly
-
-            pKey->bKeyValid = true;
-            pKey->uKeyLength = uKeyLength;
-            pKey->dwKeyIndex = dwKeyIndex;
-            pKey->byCipherSuite = byKeyDecMode;
-            memcpy(pKey->abyKey, pbyKey, uKeyLength);
-            if (byKeyDecMode == KEY_CTL_WEP) {
-                if (uKeyLength == WLAN_WEP40_KEYLEN)
-                    pKey->abyKey[15] &= 0x7F;
-                if (uKeyLength == WLAN_WEP104_KEYLEN)
-                    pKey->abyKey[15] |= 0x80;
-            }
-            MACvSetKeyEntry(dwIoBase, pTable->KeyTable[i].wKeyCtl, i, uKeyIdx, pbyBSSID, (unsigned long *)pKey->abyKey, byLocalID);
-
-            if ((dwKeyIndex & USE_KEYRSC) == 0) {
-                // RSC set by NIC
-		    memset(&(pKey->KeyRSC), 0, sizeof(QWORD));
-            }
-            else {
-                memcpy(&(pKey->KeyRSC), pKeyRSC,  sizeof(QWORD));
-            }
-            pKey->dwTSC47_16 = 0;
-            pKey->wTSC15_0 = 0;
-
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"KeybSetKey(R): \n");
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->bKeyValid: %d\n ", pKey->bKeyValid);
-            //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->uKeyLength: %d\n ", pKey->uKeyLength);
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->abyKey: ");
-            for (ii = 0; ii < pKey->uKeyLength; ii++) {
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%02x ", pKey->abyKey[ii]);
-            }
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n");
-
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwTSC47_16: %lx\n ", pKey->dwTSC47_16);
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->wTSC15_0: %x\n ", pKey->wTSC15_0);
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwKeyIndex: %lx\n ", pKey->dwKeyIndex);
-
-            return (true);
-        }
-    }
-    if (j < (MAX_KEY_TABLE-1)) {
-        memcpy(pTable->KeyTable[j].abyBSSID,pbyBSSID,ETH_ALEN);
-        pTable->KeyTable[j].bInUse = true;
-        if ((dwKeyIndex & PAIRWISE_KEY) != 0)  {
-            // Pairwise key
-            pKey = &(pTable->KeyTable[j].PairwiseKey);
-            pTable->KeyTable[j].wKeyCtl &= 0xFFF0;          // clear pairwise key control filed
-            pTable->KeyTable[j].wKeyCtl |= byKeyDecMode;
-            uKeyIdx = 4;                                    // use HW key entry 4 for pairwise key
-        } else {
-            // Group key
-            if ((dwKeyIndex & 0x000000FF) >= MAX_GROUP_KEY)
-                return (false);
-            pKey = &(pTable->KeyTable[j].GroupKey[dwKeyIndex & 0x000000FF]);
-            if ((dwKeyIndex & TRANSMIT_KEY) != 0)  {
-                // Group transmit key
-                pTable->KeyTable[j].dwGTKeyIndex = dwKeyIndex;
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Group transmit key(N)[%lX]: %d\n", pTable->KeyTable[j].dwGTKeyIndex, j);
-            }
-            pTable->KeyTable[j].wKeyCtl &= 0xFF0F;          // clear group key control filed
-            pTable->KeyTable[j].wKeyCtl |= (byKeyDecMode << 4);
-            pTable->KeyTable[j].wKeyCtl |= 0x0040;          // use group key for group address
-            uKeyIdx = (dwKeyIndex & 0x000000FF);
-        }
-        pTable->KeyTable[j].wKeyCtl |= 0x8000;              // enable on-fly
-
-        pKey->bKeyValid = true;
-        pKey->uKeyLength = uKeyLength;
-        pKey->dwKeyIndex = dwKeyIndex;
-        pKey->byCipherSuite = byKeyDecMode;
-        memcpy(pKey->abyKey, pbyKey, uKeyLength);
-        if (byKeyDecMode == KEY_CTL_WEP) {
-            if (uKeyLength == WLAN_WEP40_KEYLEN)
-                pKey->abyKey[15] &= 0x7F;
-            if (uKeyLength == WLAN_WEP104_KEYLEN)
-                pKey->abyKey[15] |= 0x80;
-        }
-        MACvSetKeyEntry(dwIoBase, pTable->KeyTable[j].wKeyCtl, j, uKeyIdx, pbyBSSID, (unsigned long *)pKey->abyKey, byLocalID);
-
-        if ((dwKeyIndex & USE_KEYRSC) == 0) {
-            // RSC set by NIC
-		memset(&(pKey->KeyRSC), 0, sizeof(QWORD));
-        }
-        else {
-            memcpy(&(pKey->KeyRSC), pKeyRSC,  sizeof(QWORD));
-        }
-        pKey->dwTSC47_16 = 0;
-        pKey->wTSC15_0 = 0;
-
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"KeybSetKey(N): \n");
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->bKeyValid: %d\n ", pKey->bKeyValid);
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->uKeyLength: %d\n ", (int)pKey->uKeyLength);
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->abyKey: ");
-        for (ii = 0; ii < pKey->uKeyLength; ii++) {
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%02x ", pKey->abyKey[ii]);
-        }
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n");
-
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwTSC47_16: %lx\n ", pKey->dwTSC47_16);
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->wTSC15_0: %x\n ", pKey->wTSC15_0);
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwKeyIndex: %lx\n ", pKey->dwKeyIndex);
-
-        return (true);
-    }
-    return (false);
+	int i, j;
+	unsigned int ii;
+	PSKeyItem   pKey;
+	unsigned int uKeyIdx;
+
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Enter KeybSetKey: %lX\n", dwKeyIndex);
+
+	j = (MAX_KEY_TABLE-1);
+	for (i = 0; i < (MAX_KEY_TABLE - 1); i++) {
+		if ((pTable->KeyTable[i].bInUse == false) &&
+		    (j == (MAX_KEY_TABLE-1))) {
+			// found empty table
+			j = i;
+		}
+		if ((pTable->KeyTable[i].bInUse == true) &&
+		    !compare_ether_addr(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
+			// found table already exist
+			if ((dwKeyIndex & PAIRWISE_KEY) != 0) {
+				// Pairwise key
+				pKey = &(pTable->KeyTable[i].PairwiseKey);
+				pTable->KeyTable[i].wKeyCtl &= 0xFFF0;          // clear pairwise key control filed
+				pTable->KeyTable[i].wKeyCtl |= byKeyDecMode;
+				uKeyIdx = 4;                                    // use HW key entry 4 for pairwise key
+			} else {
+				// Group key
+				if ((dwKeyIndex & 0x000000FF) >= MAX_GROUP_KEY)
+					return false;
+				pKey = &(pTable->KeyTable[i].GroupKey[dwKeyIndex & 0x000000FF]);
+				if ((dwKeyIndex & TRANSMIT_KEY) != 0)  {
+					// Group transmit key
+					pTable->KeyTable[i].dwGTKeyIndex = dwKeyIndex;
+					DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Group transmit key(R)[%lX]: %d\n", pTable->KeyTable[i].dwGTKeyIndex, i);
+				}
+				pTable->KeyTable[i].wKeyCtl &= 0xFF0F;          // clear group key control filed
+				pTable->KeyTable[i].wKeyCtl |= (byKeyDecMode << 4);
+				pTable->KeyTable[i].wKeyCtl |= 0x0040;          // use group key for group address
+				uKeyIdx = (dwKeyIndex & 0x000000FF);
+			}
+			pTable->KeyTable[i].wKeyCtl |= 0x8000;              // enable on-fly
+
+			pKey->bKeyValid = true;
+			pKey->uKeyLength = uKeyLength;
+			pKey->dwKeyIndex = dwKeyIndex;
+			pKey->byCipherSuite = byKeyDecMode;
+			memcpy(pKey->abyKey, pbyKey, uKeyLength);
+			if (byKeyDecMode == KEY_CTL_WEP) {
+				if (uKeyLength == WLAN_WEP40_KEYLEN)
+					pKey->abyKey[15] &= 0x7F;
+				if (uKeyLength == WLAN_WEP104_KEYLEN)
+					pKey->abyKey[15] |= 0x80;
+			}
+			MACvSetKeyEntry(dwIoBase, pTable->KeyTable[i].wKeyCtl, i, uKeyIdx, pbyBSSID, (unsigned long *)pKey->abyKey, byLocalID);
+
+			if ((dwKeyIndex & USE_KEYRSC) == 0) {
+				// RSC set by NIC
+				memset(&(pKey->KeyRSC), 0, sizeof(QWORD));
+			} else {
+				memcpy(&(pKey->KeyRSC), pKeyRSC,  sizeof(QWORD));
+			}
+			pKey->dwTSC47_16 = 0;
+			pKey->wTSC15_0 = 0;
+
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "KeybSetKey(R): \n");
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->bKeyValid: %d\n ", pKey->bKeyValid);
+			//DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->uKeyLength: %d\n ", pKey->uKeyLength);
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->abyKey: ");
+			for (ii = 0; ii < pKey->uKeyLength; ii++) {
+				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%02x ", pKey->abyKey[ii]);
+			}
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "\n");
+
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->dwTSC47_16: %lx\n ", pKey->dwTSC47_16);
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->wTSC15_0: %x\n ", pKey->wTSC15_0);
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->dwKeyIndex: %lx\n ", pKey->dwKeyIndex);
+
+			return true;
+		}
+	}
+	if (j < (MAX_KEY_TABLE-1)) {
+		memcpy(pTable->KeyTable[j].abyBSSID, pbyBSSID, ETH_ALEN);
+		pTable->KeyTable[j].bInUse = true;
+		if ((dwKeyIndex & PAIRWISE_KEY) != 0)  {
+			// Pairwise key
+			pKey = &(pTable->KeyTable[j].PairwiseKey);
+			pTable->KeyTable[j].wKeyCtl &= 0xFFF0;          // clear pairwise key control filed
+			pTable->KeyTable[j].wKeyCtl |= byKeyDecMode;
+			uKeyIdx = 4;                                    // use HW key entry 4 for pairwise key
+		} else {
+			// Group key
+			if ((dwKeyIndex & 0x000000FF) >= MAX_GROUP_KEY)
+				return false;
+			pKey = &(pTable->KeyTable[j].GroupKey[dwKeyIndex & 0x000000FF]);
+			if ((dwKeyIndex & TRANSMIT_KEY) != 0)  {
+				// Group transmit key
+				pTable->KeyTable[j].dwGTKeyIndex = dwKeyIndex;
+				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Group transmit key(N)[%lX]: %d\n", pTable->KeyTable[j].dwGTKeyIndex, j);
+			}
+			pTable->KeyTable[j].wKeyCtl &= 0xFF0F;          // clear group key control filed
+			pTable->KeyTable[j].wKeyCtl |= (byKeyDecMode << 4);
+			pTable->KeyTable[j].wKeyCtl |= 0x0040;          // use group key for group address
+			uKeyIdx = (dwKeyIndex & 0x000000FF);
+		}
+		pTable->KeyTable[j].wKeyCtl |= 0x8000;              // enable on-fly
+
+		pKey->bKeyValid = true;
+		pKey->uKeyLength = uKeyLength;
+		pKey->dwKeyIndex = dwKeyIndex;
+		pKey->byCipherSuite = byKeyDecMode;
+		memcpy(pKey->abyKey, pbyKey, uKeyLength);
+		if (byKeyDecMode == KEY_CTL_WEP) {
+			if (uKeyLength == WLAN_WEP40_KEYLEN)
+				pKey->abyKey[15] &= 0x7F;
+			if (uKeyLength == WLAN_WEP104_KEYLEN)
+				pKey->abyKey[15] |= 0x80;
+		}
+		MACvSetKeyEntry(dwIoBase, pTable->KeyTable[j].wKeyCtl, j, uKeyIdx, pbyBSSID, (unsigned long *)pKey->abyKey, byLocalID);
+
+		if ((dwKeyIndex & USE_KEYRSC) == 0) {
+			// RSC set by NIC
+			memset(&(pKey->KeyRSC), 0, sizeof(QWORD));
+		} else {
+			memcpy(&(pKey->KeyRSC), pKeyRSC,  sizeof(QWORD));
+		}
+		pKey->dwTSC47_16 = 0;
+		pKey->wTSC15_0 = 0;
+
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "KeybSetKey(N): \n");
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->bKeyValid: %d\n ", pKey->bKeyValid);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->uKeyLength: %d\n ", (int)pKey->uKeyLength);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->abyKey: ");
+		for (ii = 0; ii < pKey->uKeyLength; ii++) {
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%02x ", pKey->abyKey[ii]);
+		}
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "\n");
+
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->dwTSC47_16: %lx\n ", pKey->dwTSC47_16);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->wTSC15_0: %x\n ", pKey->wTSC15_0);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->dwKeyIndex: %lx\n ", pKey->dwKeyIndex);
+
+		return true;
+	}
+	return false;
 }
 
-
 /*
  * Description: Remove Key from table
  *
@@ -362,66 +351,61 @@ bool KeybSetKey (
  * Return Value: true if success otherwise false
  *
  */
-bool KeybRemoveKey (
-    PSKeyManagement pTable,
-    unsigned char *pbyBSSID,
-    unsigned long dwKeyIndex,
-    unsigned long dwIoBase
-    )
+bool KeybRemoveKey(
+	PSKeyManagement pTable,
+	unsigned char *pbyBSSID,
+	unsigned long dwKeyIndex,
+	unsigned long dwIoBase
+)
 {
-    int  i;
-
-    if (is_broadcast_ether_addr(pbyBSSID)) {
-        // delete all keys
-        if ((dwKeyIndex & PAIRWISE_KEY) != 0) {
-            for (i=0;i<MAX_KEY_TABLE;i++) {
-                pTable->KeyTable[i].PairwiseKey.bKeyValid = false;
-            }
-            s_vCheckKeyTableValid(pTable, dwIoBase);
-            return true;
-        }
-        else if ((dwKeyIndex & 0x000000FF) < MAX_GROUP_KEY) {
-            for (i=0;i<MAX_KEY_TABLE;i++) {
-                pTable->KeyTable[i].GroupKey[dwKeyIndex & 0x000000FF].bKeyValid = false;
-                if ((dwKeyIndex & 0x7FFFFFFF) == (pTable->KeyTable[i].dwGTKeyIndex & 0x7FFFFFFF)) {
-                    // remove Group transmit key
-                    pTable->KeyTable[i].dwGTKeyIndex = 0;
-                }
-            }
-            s_vCheckKeyTableValid(pTable, dwIoBase);
-            return true;
-        }
-        else {
-            return false;
-        }
-    }
-
-    for (i=0;i<MAX_KEY_TABLE;i++) {
-        if ((pTable->KeyTable[i].bInUse == true) &&
-            !compare_ether_addr(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
-            if ((dwKeyIndex & PAIRWISE_KEY) != 0) {
-                pTable->KeyTable[i].PairwiseKey.bKeyValid = false;
-                s_vCheckKeyTableValid(pTable, dwIoBase);
-                return (true);
-            }
-            else if ((dwKeyIndex & 0x000000FF) < MAX_GROUP_KEY) {
-                pTable->KeyTable[i].GroupKey[dwKeyIndex & 0x000000FF].bKeyValid = false;
-                if ((dwKeyIndex & 0x7FFFFFFF) == (pTable->KeyTable[i].dwGTKeyIndex & 0x7FFFFFFF)) {
-                    // remove Group transmit key
-                    pTable->KeyTable[i].dwGTKeyIndex = 0;
-                }
-                s_vCheckKeyTableValid(pTable, dwIoBase);
-                return (true);
-            }
-            else {
-                return (false);
-            }
-        }
-    }
-    return (false);
+	int  i;
+
+	if (is_broadcast_ether_addr(pbyBSSID)) {
+		// delete all keys
+		if ((dwKeyIndex & PAIRWISE_KEY) != 0) {
+			for (i = 0; i < MAX_KEY_TABLE; i++) {
+				pTable->KeyTable[i].PairwiseKey.bKeyValid = false;
+			}
+			s_vCheckKeyTableValid(pTable, dwIoBase);
+			return true;
+		} else if ((dwKeyIndex & 0x000000FF) < MAX_GROUP_KEY) {
+			for (i = 0; i < MAX_KEY_TABLE; i++) {
+				pTable->KeyTable[i].GroupKey[dwKeyIndex & 0x000000FF].bKeyValid = false;
+				if ((dwKeyIndex & 0x7FFFFFFF) == (pTable->KeyTable[i].dwGTKeyIndex & 0x7FFFFFFF)) {
+					// remove Group transmit key
+					pTable->KeyTable[i].dwGTKeyIndex = 0;
+				}
+			}
+			s_vCheckKeyTableValid(pTable, dwIoBase);
+			return true;
+		} else {
+			return false;
+		}
+	}
+
+	for (i = 0; i < MAX_KEY_TABLE; i++) {
+		if ((pTable->KeyTable[i].bInUse == true) &&
+		    !compare_ether_addr(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
+			if ((dwKeyIndex & PAIRWISE_KEY) != 0) {
+				pTable->KeyTable[i].PairwiseKey.bKeyValid = false;
+				s_vCheckKeyTableValid(pTable, dwIoBase);
+				return true;
+			} else if ((dwKeyIndex & 0x000000FF) < MAX_GROUP_KEY) {
+				pTable->KeyTable[i].GroupKey[dwKeyIndex & 0x000000FF].bKeyValid = false;
+				if ((dwKeyIndex & 0x7FFFFFFF) == (pTable->KeyTable[i].dwGTKeyIndex & 0x7FFFFFFF)) {
+					// remove Group transmit key
+					pTable->KeyTable[i].dwGTKeyIndex = 0;
+				}
+				s_vCheckKeyTableValid(pTable, dwIoBase);
+				return true;
+			} else {
+				return false;
+			}
+		}
+	}
+	return false;
 }
 
-
 /*
  * Description: Remove Key from table
  *
@@ -435,27 +419,27 @@ bool KeybRemoveKey (
  * Return Value: true if success otherwise false
  *
  */
-bool KeybRemoveAllKey (
-    PSKeyManagement pTable,
-    unsigned char *pbyBSSID,
-    unsigned long dwIoBase
-    )
+bool KeybRemoveAllKey(
+	PSKeyManagement pTable,
+	unsigned char *pbyBSSID,
+	unsigned long dwIoBase
+)
 {
-    int  i,u;
-
-    for (i=0;i<MAX_KEY_TABLE;i++) {
-        if ((pTable->KeyTable[i].bInUse == true) &&
-            !compare_ether_addr(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
-            pTable->KeyTable[i].PairwiseKey.bKeyValid = false;
-            for(u=0;u<MAX_GROUP_KEY;u++) {
-                pTable->KeyTable[i].GroupKey[u].bKeyValid = false;
-            }
-            pTable->KeyTable[i].dwGTKeyIndex = 0;
-            s_vCheckKeyTableValid(pTable, dwIoBase);
-            return (true);
-        }
-    }
-    return (false);
+	int i, u;
+
+	for (i = 0; i < MAX_KEY_TABLE; i++) {
+		if ((pTable->KeyTable[i].bInUse == true) &&
+		    !compare_ether_addr(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
+			pTable->KeyTable[i].PairwiseKey.bKeyValid = false;
+			for (u = 0; u < MAX_GROUP_KEY; u++) {
+				pTable->KeyTable[i].GroupKey[u].bKeyValid = false;
+			}
+			pTable->KeyTable[i].dwGTKeyIndex = 0;
+			s_vCheckKeyTableValid(pTable, dwIoBase);
+			return true;
+		}
+	}
+	return false;
 }
 
 /*
@@ -470,38 +454,37 @@ bool KeybRemoveAllKey (
  * Return Value: true if success otherwise false
  *
  */
-void KeyvRemoveWEPKey (
-    PSKeyManagement pTable,
-    unsigned long dwKeyIndex,
-    unsigned long dwIoBase
-    )
+void KeyvRemoveWEPKey(
+	PSKeyManagement pTable,
+	unsigned long dwKeyIndex,
+	unsigned long dwIoBase
+)
 {
-
-   if ((dwKeyIndex & 0x000000FF) < MAX_GROUP_KEY) {
-        if (pTable->KeyTable[MAX_KEY_TABLE-1].bInUse == true) {
-            if (pTable->KeyTable[MAX_KEY_TABLE-1].GroupKey[dwKeyIndex & 0x000000FF].byCipherSuite == KEY_CTL_WEP) {
-                pTable->KeyTable[MAX_KEY_TABLE-1].GroupKey[dwKeyIndex & 0x000000FF].bKeyValid = false;
-                if ((dwKeyIndex & 0x7FFFFFFF) == (pTable->KeyTable[MAX_KEY_TABLE-1].dwGTKeyIndex & 0x7FFFFFFF)) {
-                    // remove Group transmit key
-                    pTable->KeyTable[MAX_KEY_TABLE-1].dwGTKeyIndex = 0;
-                }
-            }
-        }
-        s_vCheckKeyTableValid(pTable, dwIoBase);
-    }
-    return;
+	if ((dwKeyIndex & 0x000000FF) < MAX_GROUP_KEY) {
+		if (pTable->KeyTable[MAX_KEY_TABLE-1].bInUse == true) {
+			if (pTable->KeyTable[MAX_KEY_TABLE-1].GroupKey[dwKeyIndex & 0x000000FF].byCipherSuite == KEY_CTL_WEP) {
+				pTable->KeyTable[MAX_KEY_TABLE-1].GroupKey[dwKeyIndex & 0x000000FF].bKeyValid = false;
+				if ((dwKeyIndex & 0x7FFFFFFF) == (pTable->KeyTable[MAX_KEY_TABLE-1].dwGTKeyIndex & 0x7FFFFFFF)) {
+					// remove Group transmit key
+					pTable->KeyTable[MAX_KEY_TABLE-1].dwGTKeyIndex = 0;
+				}
+			}
+		}
+		s_vCheckKeyTableValid(pTable, dwIoBase);
+	}
+	return;
 }
 
-void KeyvRemoveAllWEPKey (
-    PSKeyManagement pTable,
-    unsigned long dwIoBase
-    )
+void KeyvRemoveAllWEPKey(
+	PSKeyManagement pTable,
+	unsigned long dwIoBase
+)
 {
-    int i;
+	int i;
 
-    for(i=0;i<MAX_GROUP_KEY;i++) {
-        KeyvRemoveWEPKey(pTable, i, dwIoBase);
-    }
+	for (i = 0; i < MAX_GROUP_KEY; i++) {
+		KeyvRemoveWEPKey(pTable, i, dwIoBase);
+	}
 }
 
 /*
@@ -517,74 +500,68 @@ void KeyvRemoveAllWEPKey (
  * Return Value: true if found otherwise false
  *
  */
-bool KeybGetTransmitKey (
-    PSKeyManagement pTable,
-    unsigned char *pbyBSSID,
-    unsigned long dwKeyType,
-    PSKeyItem       *pKey
-    )
+bool KeybGetTransmitKey(
+	PSKeyManagement pTable,
+	unsigned char *pbyBSSID,
+	unsigned long dwKeyType,
+	PSKeyItem       *pKey
+)
 {
-    int i, ii;
-
-    *pKey = NULL;
-    for (i=0;i<MAX_KEY_TABLE;i++) {
-        if ((pTable->KeyTable[i].bInUse == true) &&
-            !compare_ether_addr(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
-
-            if (dwKeyType == PAIRWISE_KEY) {
-
-                if (pTable->KeyTable[i].PairwiseKey.bKeyValid == true) {
-                    *pKey = &(pTable->KeyTable[i].PairwiseKey);
-
-                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"KeybGetTransmitKey:");
-                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"PAIRWISE_KEY: KeyTable.abyBSSID: ");
-                    for (ii = 0; ii < 6; ii++) {
-                        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"%x ", pTable->KeyTable[i].abyBSSID[ii]);
-                    }
-                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n");
-
-
-                    return (true);
-                }
-                else {
-                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"PairwiseKey.bKeyValid == false\n");
-                    return (false);
-                }
-            } // End of Type == PAIRWISE
-            else {
-                if (pTable->KeyTable[i].dwGTKeyIndex == 0) {
-                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ERROR: dwGTKeyIndex == 0 !!!\n");
-                    return false;
-                }
-                if (pTable->KeyTable[i].GroupKey[(pTable->KeyTable[i].dwGTKeyIndex&0x000000FF)].bKeyValid == true) {
-                    *pKey = &(pTable->KeyTable[i].GroupKey[(pTable->KeyTable[i].dwGTKeyIndex&0x000000FF)]);
-
-                        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"KeybGetTransmitKey:");
-                        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"GROUP_KEY: KeyTable.abyBSSID\n");
-                        for (ii = 0; ii < 6; ii++) {
-                            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"%x ", pTable->KeyTable[i].abyBSSID[ii]);
-                        }
-                        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n");
-                        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"dwGTKeyIndex: %lX\n", pTable->KeyTable[i].dwGTKeyIndex);
-
-                    return (true);
-                }
-                else {
-                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"GroupKey.bKeyValid == false\n");
-                    return (false);
-                }
-            } // End of Type = GROUP
-        } // BSSID match
-    }
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ERROR: NO Match BSSID !!! ");
-    for (ii = 0; ii < 6; ii++) {
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"%02x ", *(pbyBSSID+ii));
-    }
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n");
-    return (false);
+	int i, ii;
+
+	*pKey = NULL;
+	for (i = 0; i < MAX_KEY_TABLE; i++) {
+		if ((pTable->KeyTable[i].bInUse == true) &&
+		    !compare_ether_addr(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
+			if (dwKeyType == PAIRWISE_KEY) {
+				if (pTable->KeyTable[i].PairwiseKey.bKeyValid == true) {
+					*pKey = &(pTable->KeyTable[i].PairwiseKey);
+
+					DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "KeybGetTransmitKey:");
+					DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "PAIRWISE_KEY: KeyTable.abyBSSID: ");
+					for (ii = 0; ii < 6; ii++) {
+						DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%x ", pTable->KeyTable[i].abyBSSID[ii]);
+					}
+					DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "\n");
+
+					return true;
+				} else {
+					DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "PairwiseKey.bKeyValid == false\n");
+					return false;
+				}
+			} // End of Type == PAIRWISE
+			else {
+				if (pTable->KeyTable[i].dwGTKeyIndex == 0) {
+					DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ERROR: dwGTKeyIndex == 0 !!!\n");
+					return false;
+				}
+				if (pTable->KeyTable[i].GroupKey[(pTable->KeyTable[i].dwGTKeyIndex&0x000000FF)].bKeyValid == true) {
+					*pKey = &(pTable->KeyTable[i].GroupKey[(pTable->KeyTable[i].dwGTKeyIndex&0x000000FF)]);
+
+					DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "KeybGetTransmitKey:");
+					DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "GROUP_KEY: KeyTable.abyBSSID\n");
+					for (ii = 0; ii < 6; ii++) {
+						DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%x ", pTable->KeyTable[i].abyBSSID[ii]);
+					}
+					DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "\n");
+					DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dwGTKeyIndex: %lX\n", pTable->KeyTable[i].dwGTKeyIndex);
+
+					return true;
+				} else {
+					DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "GroupKey.bKeyValid == false\n");
+					return false;
+				}
+			} // End of Type = GROUP
+		} // BSSID match
+	}
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ERROR: NO Match BSSID !!! ");
+	for (ii = 0; ii < 6; ii++) {
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%02x ", *(pbyBSSID+ii));
+	}
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "\n");
+	return false;
 }
 
-
 /*
  * Description: Check Pairewise Key
  *
@@ -597,22 +574,22 @@ bool KeybGetTransmitKey (
  * Return Value: true if found otherwise false
  *
  */
-bool KeybCheckPairewiseKey (
-    PSKeyManagement pTable,
-    PSKeyItem       *pKey
-    )
+bool KeybCheckPairewiseKey(
+	PSKeyManagement pTable,
+	PSKeyItem       *pKey
+)
 {
-    int i;
-
-    *pKey = NULL;
-    for (i=0;i<MAX_KEY_TABLE;i++) {
-        if ((pTable->KeyTable[i].bInUse == true) &&
-            (pTable->KeyTable[i].PairwiseKey.bKeyValid == true)) {
-            *pKey = &(pTable->KeyTable[i].PairwiseKey);
-            return (true);
-        }
-    }
-    return (false);
+	int i;
+
+	*pKey = NULL;
+	for (i = 0; i < MAX_KEY_TABLE; i++) {
+		if ((pTable->KeyTable[i].bInUse == true) &&
+		    (pTable->KeyTable[i].PairwiseKey.bKeyValid == true)) {
+			*pKey = &(pTable->KeyTable[i].PairwiseKey);
+			return true;
+		}
+	}
+	return false;
 }
 
 /*
@@ -631,100 +608,97 @@ bool KeybCheckPairewiseKey (
  * Return Value: true if success otherwise false
  *
  */
-bool KeybSetDefaultKey (
-    PSKeyManagement pTable,
-    unsigned long dwKeyIndex,
-    unsigned long uKeyLength,
-    PQWORD          pKeyRSC,
-    unsigned char *pbyKey,
-    unsigned char byKeyDecMode,
-    unsigned long dwIoBase,
-    unsigned char byLocalID
-    )
+bool KeybSetDefaultKey(
+	PSKeyManagement pTable,
+	unsigned long dwKeyIndex,
+	unsigned long uKeyLength,
+	PQWORD          pKeyRSC,
+	unsigned char *pbyKey,
+	unsigned char byKeyDecMode,
+	unsigned long dwIoBase,
+	unsigned char byLocalID
+)
 {
-    unsigned int ii;
-    PSKeyItem   pKey;
-    unsigned int uKeyIdx;
-
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Enter KeybSetDefaultKey: %1x, %d \n", (int)dwKeyIndex, (int)uKeyLength);
-
-
-    if ((dwKeyIndex & PAIRWISE_KEY) != 0) {                  // Pairwise key
-        return (false);
-    } else if ((dwKeyIndex & 0x000000FF) >= MAX_GROUP_KEY) {
-        return (false);
-    }
-
-    if (uKeyLength > MAX_KEY_LEN)
-	    return false;
-
-    pTable->KeyTable[MAX_KEY_TABLE-1].bInUse = true;
-    for(ii=0;ii<ETH_ALEN;ii++)
-        pTable->KeyTable[MAX_KEY_TABLE-1].abyBSSID[ii] = 0xFF;
-
-    // Group key
-    pKey = &(pTable->KeyTable[MAX_KEY_TABLE-1].GroupKey[dwKeyIndex & 0x000000FF]);
-    if ((dwKeyIndex & TRANSMIT_KEY) != 0)  {
-        // Group transmit key
-        pTable->KeyTable[MAX_KEY_TABLE-1].dwGTKeyIndex = dwKeyIndex;
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Group transmit key(R)[%lX]: %d\n", pTable->KeyTable[MAX_KEY_TABLE-1].dwGTKeyIndex, MAX_KEY_TABLE-1);
-
-    }
-    pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl &= 0x7F00;          // clear all key control filed
-    pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl |= (byKeyDecMode << 4);
-    pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl |= (byKeyDecMode);
-    pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl |= 0x0044;          // use group key for all address
-    uKeyIdx = (dwKeyIndex & 0x000000FF);
-
-    if ((uKeyLength == WLAN_WEP232_KEYLEN) &&
-        (byKeyDecMode == KEY_CTL_WEP)) {
-        pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl |= 0x4000;              // disable on-fly disable address match
-        pTable->KeyTable[MAX_KEY_TABLE-1].bSoftWEP = true;
-    } else {
-        if (pTable->KeyTable[MAX_KEY_TABLE-1].bSoftWEP == false)
-            pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl |= 0xC000;          // enable on-fly disable address match
-    }
-
-    pKey->bKeyValid = true;
-    pKey->uKeyLength = uKeyLength;
-    pKey->dwKeyIndex = dwKeyIndex;
-    pKey->byCipherSuite = byKeyDecMode;
-    memcpy(pKey->abyKey, pbyKey, uKeyLength);
-    if (byKeyDecMode == KEY_CTL_WEP) {
-        if (uKeyLength == WLAN_WEP40_KEYLEN)
-            pKey->abyKey[15] &= 0x7F;
-        if (uKeyLength == WLAN_WEP104_KEYLEN)
-            pKey->abyKey[15] |= 0x80;
-    }
-    MACvSetKeyEntry(dwIoBase, pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl, MAX_KEY_TABLE-1, uKeyIdx, pTable->KeyTable[MAX_KEY_TABLE-1].abyBSSID, (unsigned long *)pKey->abyKey, byLocalID);
-
-    if ((dwKeyIndex & USE_KEYRSC) == 0) {
-        // RSC set by NIC
-	    memset(&(pKey->KeyRSC), 0, sizeof(QWORD));
-    } else {
-        memcpy(&(pKey->KeyRSC), pKeyRSC,  sizeof(QWORD));
-    }
-    pKey->dwTSC47_16 = 0;
-    pKey->wTSC15_0 = 0;
-
-
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"KeybSetKey(R): \n");
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->bKeyValid: %d\n", pKey->bKeyValid);
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->uKeyLength: %d\n", (int)pKey->uKeyLength);
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->abyKey: \n");
-    for (ii = 0; ii < pKey->uKeyLength; ii++) {
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"%x", pKey->abyKey[ii]);
-    }
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n");
-
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwTSC47_16: %lx\n", pKey->dwTSC47_16);
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->wTSC15_0: %x\n", pKey->wTSC15_0);
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwKeyIndex: %lx\n", pKey->dwKeyIndex);
-
-    return (true);
+	unsigned int ii;
+	PSKeyItem   pKey;
+	unsigned int uKeyIdx;
+
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Enter KeybSetDefaultKey: %1x, %d \n", (int)dwKeyIndex, (int)uKeyLength);
+
+	if ((dwKeyIndex & PAIRWISE_KEY) != 0) {                  // Pairwise key
+		return false;
+	} else if ((dwKeyIndex & 0x000000FF) >= MAX_GROUP_KEY) {
+		return false;
+	}
+
+	if (uKeyLength > MAX_KEY_LEN)
+		return false;
+
+	pTable->KeyTable[MAX_KEY_TABLE - 1].bInUse = true;
+	for (ii = 0; ii < ETH_ALEN; ii++)
+		pTable->KeyTable[MAX_KEY_TABLE - 1].abyBSSID[ii] = 0xFF;
+
+	// Group key
+	pKey = &(pTable->KeyTable[MAX_KEY_TABLE - 1].GroupKey[dwKeyIndex & 0x000000FF]);
+	if ((dwKeyIndex & TRANSMIT_KEY) != 0)  {
+		// Group transmit key
+		pTable->KeyTable[MAX_KEY_TABLE-1].dwGTKeyIndex = dwKeyIndex;
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Group transmit key(R)[%lX]: %d\n", pTable->KeyTable[MAX_KEY_TABLE-1].dwGTKeyIndex, MAX_KEY_TABLE-1);
+
+	}
+	pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl &= 0x7F00;          // clear all key control filed
+	pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl |= (byKeyDecMode << 4);
+	pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl |= (byKeyDecMode);
+	pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl |= 0x0044;          // use group key for all address
+	uKeyIdx = (dwKeyIndex & 0x000000FF);
+
+	if ((uKeyLength == WLAN_WEP232_KEYLEN) &&
+	    (byKeyDecMode == KEY_CTL_WEP)) {
+		pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl |= 0x4000;              // disable on-fly disable address match
+		pTable->KeyTable[MAX_KEY_TABLE-1].bSoftWEP = true;
+	} else {
+		if (pTable->KeyTable[MAX_KEY_TABLE-1].bSoftWEP == false)
+			pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl |= 0xC000;          // enable on-fly disable address match
+	}
+
+	pKey->bKeyValid = true;
+	pKey->uKeyLength = uKeyLength;
+	pKey->dwKeyIndex = dwKeyIndex;
+	pKey->byCipherSuite = byKeyDecMode;
+	memcpy(pKey->abyKey, pbyKey, uKeyLength);
+	if (byKeyDecMode == KEY_CTL_WEP) {
+		if (uKeyLength == WLAN_WEP40_KEYLEN)
+			pKey->abyKey[15] &= 0x7F;
+		if (uKeyLength == WLAN_WEP104_KEYLEN)
+			pKey->abyKey[15] |= 0x80;
+	}
+	MACvSetKeyEntry(dwIoBase, pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl, MAX_KEY_TABLE-1, uKeyIdx, pTable->KeyTable[MAX_KEY_TABLE-1].abyBSSID, (unsigned long *)pKey->abyKey, byLocalID);
+
+	if ((dwKeyIndex & USE_KEYRSC) == 0) {
+		// RSC set by NIC
+		memset(&(pKey->KeyRSC), 0, sizeof(QWORD));
+	} else {
+		memcpy(&(pKey->KeyRSC), pKeyRSC,  sizeof(QWORD));
+	}
+	pKey->dwTSC47_16 = 0;
+	pKey->wTSC15_0 = 0;
+
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "KeybSetKey(R): \n");
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->bKeyValid: %d\n", pKey->bKeyValid);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->uKeyLength: %d\n", (int)pKey->uKeyLength);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->abyKey: \n");
+	for (ii = 0; ii < pKey->uKeyLength; ii++) {
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%x", pKey->abyKey[ii]);
+	}
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "\n");
+
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->dwTSC47_16: %lx\n", pKey->dwTSC47_16);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->wTSC15_0: %x\n", pKey->wTSC15_0);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->dwKeyIndex: %lx\n", pKey->dwKeyIndex);
+
+	return true;
 }
 
-
 /*
  * Description: Set Key to table
  *
@@ -741,86 +715,84 @@ bool KeybSetDefaultKey (
  * Return Value: true if success otherwise false
  *
  */
-bool KeybSetAllGroupKey (
-    PSKeyManagement pTable,
-    unsigned long dwKeyIndex,
-    unsigned long uKeyLength,
-    PQWORD          pKeyRSC,
-    unsigned char *pbyKey,
-    unsigned char byKeyDecMode,
-    unsigned long dwIoBase,
-    unsigned char byLocalID
-    )
+bool KeybSetAllGroupKey(
+	PSKeyManagement pTable,
+	unsigned long dwKeyIndex,
+	unsigned long uKeyLength,
+	PQWORD          pKeyRSC,
+	unsigned char *pbyKey,
+	unsigned char byKeyDecMode,
+	unsigned long dwIoBase,
+	unsigned char byLocalID
+)
 {
-    int         i;
-    unsigned int ii;
-    PSKeyItem   pKey;
-    unsigned int uKeyIdx;
-
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Enter KeybSetAllGroupKey: %lX\n", dwKeyIndex);
-
-
-    if ((dwKeyIndex & PAIRWISE_KEY) != 0) {                  // Pairwise key
-        return (false);
-    } else if ((dwKeyIndex & 0x000000FF) >= MAX_GROUP_KEY) {
-        return (false);
-    }
-
-    for (i=0; i < MAX_KEY_TABLE-1; i++) {
-        if (pTable->KeyTable[i].bInUse == true) {
-            // found table already exist
-            // Group key
-            pKey = &(pTable->KeyTable[i].GroupKey[dwKeyIndex & 0x000000FF]);
-            if ((dwKeyIndex & TRANSMIT_KEY) != 0)  {
-                // Group transmit key
-                pTable->KeyTable[i].dwGTKeyIndex = dwKeyIndex;
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Group transmit key(R)[%lX]: %d\n", pTable->KeyTable[i].dwGTKeyIndex, i);
-
-            }
-            pTable->KeyTable[i].wKeyCtl &= 0xFF0F;          // clear group key control filed
-            pTable->KeyTable[i].wKeyCtl |= (byKeyDecMode << 4);
-            pTable->KeyTable[i].wKeyCtl |= 0x0040;          // use group key for group address
-            uKeyIdx = (dwKeyIndex & 0x000000FF);
-
-            pTable->KeyTable[i].wKeyCtl |= 0x8000;              // enable on-fly
-
-            pKey->bKeyValid = true;
-            pKey->uKeyLength = uKeyLength;
-            pKey->dwKeyIndex = dwKeyIndex;
-            pKey->byCipherSuite = byKeyDecMode;
-            memcpy(pKey->abyKey, pbyKey, uKeyLength);
-            if (byKeyDecMode == KEY_CTL_WEP) {
-                if (uKeyLength == WLAN_WEP40_KEYLEN)
-                    pKey->abyKey[15] &= 0x7F;
-                if (uKeyLength == WLAN_WEP104_KEYLEN)
-                    pKey->abyKey[15] |= 0x80;
-            }
-            MACvSetKeyEntry(dwIoBase, pTable->KeyTable[i].wKeyCtl, i, uKeyIdx, pTable->KeyTable[i].abyBSSID, (unsigned long *)pKey->abyKey, byLocalID);
-
-            if ((dwKeyIndex & USE_KEYRSC) == 0) {
-                // RSC set by NIC
-		    memset(&(pKey->KeyRSC), 0, sizeof(QWORD));
-            }
-            else {
-                memcpy(&(pKey->KeyRSC), pKeyRSC,  sizeof(QWORD));
-            }
-            pKey->dwTSC47_16 = 0;
-            pKey->wTSC15_0 = 0;
-
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"KeybSetKey(R): \n");
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->bKeyValid: %d\n ", pKey->bKeyValid);
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->uKeyLength: %d\n ", (int)pKey->uKeyLength);
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->abyKey: ");
-            for (ii = 0; ii < pKey->uKeyLength; ii++) {
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"%02x ", pKey->abyKey[ii]);
-            }
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n");
-
-            //DBG_PRN_GRP12(("pKey->dwTSC47_16: %lX\n ", pKey->dwTSC47_16));
-            //DBG_PRN_GRP12(("pKey->wTSC15_0: %X\n ", pKey->wTSC15_0));
-            //DBG_PRN_GRP12(("pKey->dwKeyIndex: %lX\n ", pKey->dwKeyIndex));
-
-        } // (pTable->KeyTable[i].bInUse == true)
-    }
-    return (true);
+	int         i;
+	unsigned int ii;
+	PSKeyItem   pKey;
+	unsigned int uKeyIdx;
+
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Enter KeybSetAllGroupKey: %lX\n", dwKeyIndex);
+
+	if ((dwKeyIndex & PAIRWISE_KEY) != 0) {                  // Pairwise key
+		return false;
+	} else if ((dwKeyIndex & 0x000000FF) >= MAX_GROUP_KEY) {
+		return false;
+	}
+
+	for (i = 0; i < MAX_KEY_TABLE - 1; i++) {
+		if (pTable->KeyTable[i].bInUse == true) {
+			// found table already exist
+			// Group key
+			pKey = &(pTable->KeyTable[i].GroupKey[dwKeyIndex & 0x000000FF]);
+			if ((dwKeyIndex & TRANSMIT_KEY) != 0)  {
+				// Group transmit key
+				pTable->KeyTable[i].dwGTKeyIndex = dwKeyIndex;
+				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Group transmit key(R)[%lX]: %d\n", pTable->KeyTable[i].dwGTKeyIndex, i);
+
+			}
+			pTable->KeyTable[i].wKeyCtl &= 0xFF0F;          // clear group key control filed
+			pTable->KeyTable[i].wKeyCtl |= (byKeyDecMode << 4);
+			pTable->KeyTable[i].wKeyCtl |= 0x0040;          // use group key for group address
+			uKeyIdx = (dwKeyIndex & 0x000000FF);
+
+			pTable->KeyTable[i].wKeyCtl |= 0x8000;              // enable on-fly
+
+			pKey->bKeyValid = true;
+			pKey->uKeyLength = uKeyLength;
+			pKey->dwKeyIndex = dwKeyIndex;
+			pKey->byCipherSuite = byKeyDecMode;
+			memcpy(pKey->abyKey, pbyKey, uKeyLength);
+			if (byKeyDecMode == KEY_CTL_WEP) {
+				if (uKeyLength == WLAN_WEP40_KEYLEN)
+					pKey->abyKey[15] &= 0x7F;
+				if (uKeyLength == WLAN_WEP104_KEYLEN)
+					pKey->abyKey[15] |= 0x80;
+			}
+			MACvSetKeyEntry(dwIoBase, pTable->KeyTable[i].wKeyCtl, i, uKeyIdx, pTable->KeyTable[i].abyBSSID, (unsigned long *)pKey->abyKey, byLocalID);
+
+			if ((dwKeyIndex & USE_KEYRSC) == 0) {
+				// RSC set by NIC
+				memset(&(pKey->KeyRSC), 0, sizeof(QWORD));
+			} else {
+				memcpy(&(pKey->KeyRSC), pKeyRSC,  sizeof(QWORD));
+			}
+			pKey->dwTSC47_16 = 0;
+			pKey->wTSC15_0 = 0;
+
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "KeybSetKey(R): \n");
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->bKeyValid: %d\n ", pKey->bKeyValid);
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->uKeyLength: %d\n ", (int)pKey->uKeyLength);
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey->abyKey: ");
+			for (ii = 0; ii < pKey->uKeyLength; ii++) {
+				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%02x ", pKey->abyKey[ii]);
+			}
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "\n");
+
+			//DBG_PRN_GRP12(("pKey->dwTSC47_16: %lX\n ", pKey->dwTSC47_16));
+			//DBG_PRN_GRP12(("pKey->wTSC15_0: %X\n ", pKey->wTSC15_0));
+			//DBG_PRN_GRP12(("pKey->dwKeyIndex: %lX\n ", pKey->dwKeyIndex));
+
+		} // (pTable->KeyTable[i].bInUse == true)
+	}
+	return true;
 }
diff --git a/drivers/staging/vt6655/key.h b/drivers/staging/vt6655/key.h
index 6b2dad3..356e6de 100644
--- a/drivers/staging/vt6655/key.h
+++ b/drivers/staging/vt6655/key.h
@@ -40,7 +40,6 @@
 #define MAX_KEY_LEN         32
 #define AES_KEY_LEN         16
 
-
 #define AUTHENTICATOR_KEY   0x10000000
 #define USE_KEYRSC          0x20000000
 #define PAIRWISE_KEY        0x40000000
@@ -54,42 +53,41 @@
 #define KEY_CTL_CCMP        0x03
 #define KEY_CTL_INVALID     0xFF
 
-
 typedef struct tagSKeyItem
 {
-    bool bKeyValid;
-    unsigned long uKeyLength;
-    unsigned char abyKey[MAX_KEY_LEN];
-    QWORD       KeyRSC;
-    unsigned long dwTSC47_16;
-    unsigned short wTSC15_0;
-    unsigned char byCipherSuite;
-    unsigned char byReserved0;
-    unsigned long dwKeyIndex;
-    void *pvKeyTable;
+	bool bKeyValid;
+	unsigned long uKeyLength;
+	unsigned char abyKey[MAX_KEY_LEN];
+	QWORD       KeyRSC;
+	unsigned long dwTSC47_16;
+	unsigned short wTSC15_0;
+	unsigned char byCipherSuite;
+	unsigned char byReserved0;
+	unsigned long dwKeyIndex;
+	void *pvKeyTable;
 } SKeyItem, *PSKeyItem; //64
 
 typedef struct tagSKeyTable
 {
-    unsigned char abyBSSID[ETH_ALEN];  //6
-    unsigned char byReserved0[2];              //8
-    SKeyItem    PairwiseKey;
-    SKeyItem    GroupKey[MAX_GROUP_KEY]; //64*5 = 320, 320+8=328
-    unsigned long dwGTKeyIndex;            // GroupTransmitKey Index
-    bool bInUse;
-    //2006-1116-01,<Modify> by NomadZhao
-    //unsigned short wKeyCtl;
-    //bool bSoftWEP;
-    bool bSoftWEP;
-    unsigned short wKeyCtl;      // for address of wKeyCtl at align 4
-
-    unsigned char byReserved1[6];
+	unsigned char abyBSSID[ETH_ALEN];  //6
+	unsigned char byReserved0[2];              //8
+	SKeyItem    PairwiseKey;
+	SKeyItem    GroupKey[MAX_GROUP_KEY]; //64*5 = 320, 320+8=328
+	unsigned long dwGTKeyIndex;            // GroupTransmitKey Index
+	bool bInUse;
+	//2006-1116-01,<Modify> by NomadZhao
+	//unsigned short wKeyCtl;
+	//bool bSoftWEP;
+	bool bSoftWEP;
+	unsigned short wKeyCtl;      // for address of wKeyCtl at align 4
+
+	unsigned char byReserved1[6];
 } SKeyTable, *PSKeyTable; //348
 
 typedef struct tagSKeyManagement
 {
-    SKeyTable   KeyTable[MAX_KEY_TABLE];
-} SKeyManagement, * PSKeyManagement;
+	SKeyTable   KeyTable[MAX_KEY_TABLE];
+} SKeyManagement, *PSKeyManagement;
 
 /*---------------------  Export Types  ------------------------------*/
 
@@ -104,81 +102,80 @@ typedef struct tagSKeyManagement
 void KeyvInitTable(PSKeyManagement pTable, unsigned long dwIoBase);
 
 bool KeybGetKey(
-    PSKeyManagement pTable,
-    unsigned char *pbyBSSID,
-    unsigned long dwKeyIndex,
-    PSKeyItem       *pKey
-    );
+	PSKeyManagement pTable,
+	unsigned char *pbyBSSID,
+	unsigned long dwKeyIndex,
+	PSKeyItem       *pKey
+);
 
 bool KeybSetKey(
-    PSKeyManagement pTable,
-    unsigned char *pbyBSSID,
-    unsigned long dwKeyIndex,
-    unsigned long uKeyLength,
-    PQWORD          pKeyRSC,
-    unsigned char *pbyKey,
-    unsigned char byKeyDecMode,
-    unsigned long dwIoBase,
-    unsigned char byLocalID
-    );
+	PSKeyManagement pTable,
+	unsigned char *pbyBSSID,
+	unsigned long dwKeyIndex,
+	unsigned long uKeyLength,
+	PQWORD          pKeyRSC,
+	unsigned char *pbyKey,
+	unsigned char byKeyDecMode,
+	unsigned long dwIoBase,
+	unsigned char byLocalID
+);
 
 bool KeybSetDefaultKey(
-    PSKeyManagement pTable,
-    unsigned long dwKeyIndex,
-    unsigned long uKeyLength,
-    PQWORD          pKeyRSC,
-    unsigned char *pbyKey,
-    unsigned char byKeyDecMode,
-    unsigned long dwIoBase,
-    unsigned char byLocalID
-    );
+	PSKeyManagement pTable,
+	unsigned long dwKeyIndex,
+	unsigned long uKeyLength,
+	PQWORD          pKeyRSC,
+	unsigned char *pbyKey,
+	unsigned char byKeyDecMode,
+	unsigned long dwIoBase,
+	unsigned char byLocalID
+);
 
 bool KeybRemoveKey(
-    PSKeyManagement pTable,
-    unsigned char *pbyBSSID,
-    unsigned long dwKeyIndex,
-    unsigned long dwIoBase
-    );
+	PSKeyManagement pTable,
+	unsigned char *pbyBSSID,
+	unsigned long dwKeyIndex,
+	unsigned long dwIoBase
+);
 
 bool KeybGetTransmitKey(
-    PSKeyManagement pTable,
-    unsigned char *pbyBSSID,
-    unsigned long dwKeyType,
-    PSKeyItem       *pKey
-    );
+	PSKeyManagement pTable,
+	unsigned char *pbyBSSID,
+	unsigned long dwKeyType,
+	PSKeyItem       *pKey
+);
 
 bool KeybCheckPairewiseKey(
-    PSKeyManagement pTable,
-    PSKeyItem       *pKey
-    );
+	PSKeyManagement pTable,
+	PSKeyItem       *pKey
+);
 
 bool KeybRemoveAllKey(
-    PSKeyManagement pTable,
-    unsigned char *pbyBSSID,
-    unsigned long dwIoBase
-    );
+	PSKeyManagement pTable,
+	unsigned char *pbyBSSID,
+	unsigned long dwIoBase
+);
 
 void KeyvRemoveWEPKey(
-    PSKeyManagement pTable,
-    unsigned long dwKeyIndex,
-    unsigned long dwIoBase
-    );
+	PSKeyManagement pTable,
+	unsigned long dwKeyIndex,
+	unsigned long dwIoBase
+);
 
 void KeyvRemoveAllWEPKey(
-    PSKeyManagement pTable,
-    unsigned long dwIoBase
-    );
-
-bool KeybSetAllGroupKey (
-    PSKeyManagement pTable,
-    unsigned long dwKeyIndex,
-    unsigned long uKeyLength,
-    PQWORD          pKeyRSC,
-    unsigned char *pbyKey,
-    unsigned char byKeyDecMode,
-    unsigned long dwIoBase,
-    unsigned char byLocalID
-    );
+	PSKeyManagement pTable,
+	unsigned long dwIoBase
+);
+
+bool KeybSetAllGroupKey(
+	PSKeyManagement pTable,
+	unsigned long dwKeyIndex,
+	unsigned long uKeyLength,
+	PQWORD          pKeyRSC,
+	unsigned char *pbyKey,
+	unsigned char byKeyDecMode,
+	unsigned long dwIoBase,
+	unsigned char byLocalID
+);
 
 #endif // __KEY_H__
-
diff --git a/drivers/staging/vt6655/mac.c b/drivers/staging/vt6655/mac.c
index 30c2615..001d15c 100644
--- a/drivers/staging/vt6655/mac.c
+++ b/drivers/staging/vt6655/mac.c
@@ -75,7 +75,7 @@
 unsigned short TxRate_iwconfig;//2008-5-8 <add> by chester
 /*---------------------  Static Definitions -------------------------*/
 //static int          msglevel                =MSG_LEVEL_DEBUG;
-static int          msglevel                =MSG_LEVEL_INFO;
+static int msglevel = MSG_LEVEL_INFO;
 /*---------------------  Static Classes  ----------------------------*/
 
 /*---------------------  Static Variables  --------------------------*/
@@ -86,10 +86,6 @@ static int          msglevel                =MSG_LEVEL_INFO;
 
 /*---------------------  Export Functions  --------------------------*/
 
-
-
-
-
 /*
  * Description:
  *      Read All MAC Registers to buffer
@@ -103,26 +99,25 @@ static int          msglevel                =MSG_LEVEL_INFO;
  * Return Value: none
  *
  */
-void MACvReadAllRegs (unsigned long dwIoBase, unsigned char *pbyMacRegs)
+void MACvReadAllRegs(unsigned long dwIoBase, unsigned char *pbyMacRegs)
 {
-    int ii;
-
-    // read page0 register
-    for (ii = 0; ii < MAC_MAX_CONTEXT_SIZE_PAGE0; ii++) {
-        VNSvInPortB(dwIoBase + ii, pbyMacRegs);
-        pbyMacRegs++;
-    }
+	int ii;
 
-    MACvSelectPage1(dwIoBase);
+	// read page0 register
+	for (ii = 0; ii < MAC_MAX_CONTEXT_SIZE_PAGE0; ii++) {
+		VNSvInPortB(dwIoBase + ii, pbyMacRegs);
+		pbyMacRegs++;
+	}
 
-    // read page1 register
-    for (ii = 0; ii < MAC_MAX_CONTEXT_SIZE_PAGE1; ii++) {
-        VNSvInPortB(dwIoBase + ii, pbyMacRegs);
-        pbyMacRegs++;
-    }
+	MACvSelectPage1(dwIoBase);
 
-    MACvSelectPage0(dwIoBase);
+	// read page1 register
+	for (ii = 0; ii < MAC_MAX_CONTEXT_SIZE_PAGE1; ii++) {
+		VNSvInPortB(dwIoBase + ii, pbyMacRegs);
+		pbyMacRegs++;
+	}
 
+	MACvSelectPage0(dwIoBase);
 }
 
 /*
@@ -140,12 +135,12 @@ void MACvReadAllRegs (unsigned long dwIoBase, unsigned char *pbyMacRegs)
  * Return Value: true if all test bits On; otherwise false
  *
  */
-bool MACbIsRegBitsOn (unsigned long dwIoBase, unsigned char byRegOfs, unsigned char byTestBits)
+bool MACbIsRegBitsOn(unsigned long dwIoBase, unsigned char byRegOfs, unsigned char byTestBits)
 {
-    unsigned char byData;
+	unsigned char byData;
 
-    VNSvInPortB(dwIoBase + byRegOfs, &byData);
-    return (byData & byTestBits) == byTestBits;
+	VNSvInPortB(dwIoBase + byRegOfs, &byData);
+	return (byData & byTestBits) == byTestBits;
 }
 
 /*
@@ -163,12 +158,12 @@ bool MACbIsRegBitsOn (unsigned long dwIoBase, unsigned char byRegOfs, unsigned c
  * Return Value: true if all test bits Off; otherwise false
  *
  */
-bool MACbIsRegBitsOff (unsigned long dwIoBase, unsigned char byRegOfs, unsigned char byTestBits)
+bool MACbIsRegBitsOff(unsigned long dwIoBase, unsigned char byRegOfs, unsigned char byTestBits)
 {
-    unsigned char byData;
+	unsigned char byData;
 
-    VNSvInPortB(dwIoBase + byRegOfs, &byData);
-    return !(byData & byTestBits);
+	VNSvInPortB(dwIoBase + byRegOfs, &byData);
+	return !(byData & byTestBits);
 }
 
 /*
@@ -184,15 +179,15 @@ bool MACbIsRegBitsOff (unsigned long dwIoBase, unsigned char byRegOfs, unsigned
  * Return Value: true if interrupt is disable; otherwise false
  *
  */
-bool MACbIsIntDisable (unsigned long dwIoBase)
+bool MACbIsIntDisable(unsigned long dwIoBase)
 {
-    unsigned long dwData;
+	unsigned long dwData;
 
-    VNSvInPortD(dwIoBase + MAC_REG_IMR, &dwData);
-    if (dwData != 0)
-        return false;
+	VNSvInPortD(dwIoBase + MAC_REG_IMR, &dwData);
+	if (dwData != 0)
+		return false;
 
-    return true;
+	return true;
 }
 
 /*
@@ -209,14 +204,14 @@ bool MACbIsIntDisable (unsigned long dwIoBase)
  * Return Value: Mask Value read
  *
  */
-unsigned char MACbyReadMultiAddr (unsigned long dwIoBase, unsigned int uByteIdx)
+unsigned char MACbyReadMultiAddr(unsigned long dwIoBase, unsigned int uByteIdx)
 {
-    unsigned char byData;
+	unsigned char byData;
 
-    MACvSelectPage1(dwIoBase);
-    VNSvInPortB(dwIoBase + MAC_REG_MAR0 + uByteIdx, &byData);
-    MACvSelectPage0(dwIoBase);
-    return byData;
+	MACvSelectPage1(dwIoBase);
+	VNSvInPortB(dwIoBase + MAC_REG_MAR0 + uByteIdx, &byData);
+	MACvSelectPage0(dwIoBase);
+	return byData;
 }
 
 /*
@@ -234,11 +229,11 @@ unsigned char MACbyReadMultiAddr (unsigned long dwIoBase, unsigned int uByteIdx)
  * Return Value: none
  *
  */
-void MACvWriteMultiAddr (unsigned long dwIoBase, unsigned int uByteIdx, unsigned char byData)
+void MACvWriteMultiAddr(unsigned long dwIoBase, unsigned int uByteIdx, unsigned char byData)
 {
-    MACvSelectPage1(dwIoBase);
-    VNSvOutPortB(dwIoBase + MAC_REG_MAR0 + uByteIdx, byData);
-    MACvSelectPage0(dwIoBase);
+	MACvSelectPage1(dwIoBase);
+	VNSvOutPortB(dwIoBase + MAC_REG_MAR0 + uByteIdx, byData);
+	MACvSelectPage0(dwIoBase);
 }
 
 /*
@@ -255,21 +250,21 @@ void MACvWriteMultiAddr (unsigned long dwIoBase, unsigned int uByteIdx, unsigned
  * Return Value: none
  *
  */
-void MACvSetMultiAddrByHash (unsigned long dwIoBase, unsigned char byHashIdx)
+void MACvSetMultiAddrByHash(unsigned long dwIoBase, unsigned char byHashIdx)
 {
-    unsigned int uByteIdx;
-    unsigned char byBitMask;
-    unsigned char byOrgValue;
-
-    // calculate byte position
-    uByteIdx = byHashIdx / 8;
-    ASSERT(uByteIdx < 8);
-    // calculate bit position
-    byBitMask = 1;
-    byBitMask <<= (byHashIdx % 8);
-    // turn on the bit
-    byOrgValue = MACbyReadMultiAddr(dwIoBase, uByteIdx);
-    MACvWriteMultiAddr(dwIoBase, uByteIdx, (unsigned char)(byOrgValue | byBitMask));
+	unsigned int uByteIdx;
+	unsigned char byBitMask;
+	unsigned char byOrgValue;
+
+	// calculate byte position
+	uByteIdx = byHashIdx / 8;
+	ASSERT(uByteIdx < 8);
+	// calculate bit position
+	byBitMask = 1;
+	byBitMask <<= (byHashIdx % 8);
+	// turn on the bit
+	byOrgValue = MACbyReadMultiAddr(dwIoBase, uByteIdx);
+	MACvWriteMultiAddr(dwIoBase, uByteIdx, (unsigned char)(byOrgValue | byBitMask));
 }
 
 /*
@@ -286,21 +281,21 @@ void MACvSetMultiAddrByHash (unsigned long dwIoBase, unsigned char byHashIdx)
  * Return Value: none
  *
  */
-void MACvResetMultiAddrByHash (unsigned long dwIoBase, unsigned char byHashIdx)
+void MACvResetMultiAddrByHash(unsigned long dwIoBase, unsigned char byHashIdx)
 {
-    unsigned int uByteIdx;
-    unsigned char byBitMask;
-    unsigned char byOrgValue;
-
-    // calculate byte position
-    uByteIdx = byHashIdx / 8;
-    ASSERT(uByteIdx < 8);
-    // calculate bit position
-    byBitMask = 1;
-    byBitMask <<= (byHashIdx % 8);
-    // turn off the bit
-    byOrgValue = MACbyReadMultiAddr(dwIoBase, uByteIdx);
-    MACvWriteMultiAddr(dwIoBase, uByteIdx, (unsigned char)(byOrgValue & (~byBitMask)));
+	unsigned int uByteIdx;
+	unsigned char byBitMask;
+	unsigned char byOrgValue;
+
+	// calculate byte position
+	uByteIdx = byHashIdx / 8;
+	ASSERT(uByteIdx < 8);
+	// calculate bit position
+	byBitMask = 1;
+	byBitMask <<= (byHashIdx % 8);
+	// turn off the bit
+	byOrgValue = MACbyReadMultiAddr(dwIoBase, uByteIdx);
+	MACvWriteMultiAddr(dwIoBase, uByteIdx, (unsigned char)(byOrgValue & (~byBitMask)));
 }
 
 /*
@@ -317,16 +312,16 @@ void MACvResetMultiAddrByHash (unsigned long dwIoBase, unsigned char byHashIdx)
  * Return Value: none
  *
  */
-void MACvSetRxThreshold (unsigned long dwIoBase, unsigned char byThreshold)
+void MACvSetRxThreshold(unsigned long dwIoBase, unsigned char byThreshold)
 {
-    unsigned char byOrgValue;
+	unsigned char byOrgValue;
 
-    ASSERT(byThreshold < 4);
+	ASSERT(byThreshold < 4);
 
-    // set FCR0
-    VNSvInPortB(dwIoBase + MAC_REG_FCR0, &byOrgValue);
-    byOrgValue = (byOrgValue & 0xCF) | (byThreshold << 4);
-    VNSvOutPortB(dwIoBase + MAC_REG_FCR0, byOrgValue);
+	// set FCR0
+	VNSvInPortB(dwIoBase + MAC_REG_FCR0, &byOrgValue);
+	byOrgValue = (byOrgValue & 0xCF) | (byThreshold << 4);
+	VNSvOutPortB(dwIoBase + MAC_REG_FCR0, byOrgValue);
 }
 
 /*
@@ -342,11 +337,11 @@ void MACvSetRxThreshold (unsigned long dwIoBase, unsigned char byThreshold)
  * Return Value: none
  *
  */
-void MACvGetRxThreshold (unsigned long dwIoBase, unsigned char *pbyThreshold)
+void MACvGetRxThreshold(unsigned long dwIoBase, unsigned char *pbyThreshold)
 {
-    // get FCR0
-    VNSvInPortB(dwIoBase + MAC_REG_FCR0, pbyThreshold);
-    *pbyThreshold = (*pbyThreshold >> 4) & 0x03;
+	// get FCR0
+	VNSvInPortB(dwIoBase + MAC_REG_FCR0, pbyThreshold);
+	*pbyThreshold = (*pbyThreshold >> 4) & 0x03;
 }
 
 /*
@@ -363,16 +358,16 @@ void MACvGetRxThreshold (unsigned long dwIoBase, unsigned char *pbyThreshold)
  * Return Value: none
  *
  */
-void MACvSetTxThreshold (unsigned long dwIoBase, unsigned char byThreshold)
+void MACvSetTxThreshold(unsigned long dwIoBase, unsigned char byThreshold)
 {
-    unsigned char byOrgValue;
+	unsigned char byOrgValue;
 
-    ASSERT(byThreshold < 4);
+	ASSERT(byThreshold < 4);
 
-    // set FCR0
-    VNSvInPortB(dwIoBase + MAC_REG_FCR0, &byOrgValue);
-    byOrgValue = (byOrgValue & 0xF3) | (byThreshold << 2);
-    VNSvOutPortB(dwIoBase + MAC_REG_FCR0, byOrgValue);
+	// set FCR0
+	VNSvInPortB(dwIoBase + MAC_REG_FCR0, &byOrgValue);
+	byOrgValue = (byOrgValue & 0xF3) | (byThreshold << 2);
+	VNSvOutPortB(dwIoBase + MAC_REG_FCR0, byOrgValue);
 }
 
 /*
@@ -388,11 +383,11 @@ void MACvSetTxThreshold (unsigned long dwIoBase, unsigned char byThreshold)
  * Return Value: none
  *
  */
-void MACvGetTxThreshold (unsigned long dwIoBase, unsigned char *pbyThreshold)
+void MACvGetTxThreshold(unsigned long dwIoBase, unsigned char *pbyThreshold)
 {
-    // get FCR0
-    VNSvInPortB(dwIoBase + MAC_REG_FCR0, pbyThreshold);
-    *pbyThreshold = (*pbyThreshold >> 2) & 0x03;
+	// get FCR0
+	VNSvInPortB(dwIoBase + MAC_REG_FCR0, pbyThreshold);
+	*pbyThreshold = (*pbyThreshold >> 2) & 0x03;
 }
 
 /*
@@ -409,16 +404,16 @@ void MACvGetTxThreshold (unsigned long dwIoBase, unsigned char *pbyThreshold)
  * Return Value: none
  *
  */
-void MACvSetDmaLength (unsigned long dwIoBase, unsigned char byDmaLength)
+void MACvSetDmaLength(unsigned long dwIoBase, unsigned char byDmaLength)
 {
-    unsigned char byOrgValue;
+	unsigned char byOrgValue;
 
-    ASSERT(byDmaLength < 4);
+	ASSERT(byDmaLength < 4);
 
-    // set FCR0
-    VNSvInPortB(dwIoBase + MAC_REG_FCR0, &byOrgValue);
-    byOrgValue = (byOrgValue & 0xFC) | byDmaLength;
-    VNSvOutPortB(dwIoBase + MAC_REG_FCR0, byOrgValue);
+	// set FCR0
+	VNSvInPortB(dwIoBase + MAC_REG_FCR0, &byOrgValue);
+	byOrgValue = (byOrgValue & 0xFC) | byDmaLength;
+	VNSvOutPortB(dwIoBase + MAC_REG_FCR0, byOrgValue);
 }
 
 /*
@@ -434,11 +429,11 @@ void MACvSetDmaLength (unsigned long dwIoBase, unsigned char byDmaLength)
  * Return Value: none
  *
  */
-void MACvGetDmaLength (unsigned long dwIoBase, unsigned char *pbyDmaLength)
+void MACvGetDmaLength(unsigned long dwIoBase, unsigned char *pbyDmaLength)
 {
-    // get FCR0
-    VNSvInPortB(dwIoBase + MAC_REG_FCR0, pbyDmaLength);
-    *pbyDmaLength &= 0x03;
+	// get FCR0
+	VNSvInPortB(dwIoBase + MAC_REG_FCR0, pbyDmaLength);
+	*pbyDmaLength &= 0x03;
 }
 
 /*
@@ -455,10 +450,10 @@ void MACvGetDmaLength (unsigned long dwIoBase, unsigned char *pbyDmaLength)
  * Return Value: none
  *
  */
-void MACvSetShortRetryLimit (unsigned long dwIoBase, unsigned char byRetryLimit)
+void MACvSetShortRetryLimit(unsigned long dwIoBase, unsigned char byRetryLimit)
 {
-    // set SRT
-    VNSvOutPortB(dwIoBase + MAC_REG_SRT, byRetryLimit);
+	// set SRT
+	VNSvOutPortB(dwIoBase + MAC_REG_SRT, byRetryLimit);
 }
 
 /*
@@ -474,10 +469,10 @@ void MACvSetShortRetryLimit (unsigned long dwIoBase, unsigned char byRetryLimit)
  * Return Value: none
  *
  */
-void MACvGetShortRetryLimit (unsigned long dwIoBase, unsigned char *pbyRetryLimit)
+void MACvGetShortRetryLimit(unsigned long dwIoBase, unsigned char *pbyRetryLimit)
 {
-    // get SRT
-    VNSvInPortB(dwIoBase + MAC_REG_SRT, pbyRetryLimit);
+	// get SRT
+	VNSvInPortB(dwIoBase + MAC_REG_SRT, pbyRetryLimit);
 }
 
 /*
@@ -494,10 +489,10 @@ void MACvGetShortRetryLimit (unsigned long dwIoBase, unsigned char *pbyRetryLimi
  * Return Value: none
  *
  */
-void MACvSetLongRetryLimit (unsigned long dwIoBase, unsigned char byRetryLimit)
+void MACvSetLongRetryLimit(unsigned long dwIoBase, unsigned char byRetryLimit)
 {
-    // set LRT
-    VNSvOutPortB(dwIoBase + MAC_REG_LRT, byRetryLimit);
+	// set LRT
+	VNSvOutPortB(dwIoBase + MAC_REG_LRT, byRetryLimit);
 }
 
 /*
@@ -513,10 +508,10 @@ void MACvSetLongRetryLimit (unsigned long dwIoBase, unsigned char byRetryLimit)
  * Return Value: none
  *
  */
-void MACvGetLongRetryLimit (unsigned long dwIoBase, unsigned char *pbyRetryLimit)
+void MACvGetLongRetryLimit(unsigned long dwIoBase, unsigned char *pbyRetryLimit)
 {
-    // get LRT
-    VNSvInPortB(dwIoBase + MAC_REG_LRT, pbyRetryLimit);
+	// get LRT
+	VNSvInPortB(dwIoBase + MAC_REG_LRT, pbyRetryLimit);
 }
 
 /*
@@ -533,17 +528,17 @@ void MACvGetLongRetryLimit (unsigned long dwIoBase, unsigned char *pbyRetryLimit
  * Return Value: none
  *
  */
-void MACvSetLoopbackMode (unsigned long dwIoBase, unsigned char byLoopbackMode)
+void MACvSetLoopbackMode(unsigned long dwIoBase, unsigned char byLoopbackMode)
 {
-    unsigned char byOrgValue;
-
-    ASSERT(byLoopbackMode < 3);
-    byLoopbackMode <<= 6;
-    // set TCR
-    VNSvInPortB(dwIoBase + MAC_REG_TEST, &byOrgValue);
-    byOrgValue = byOrgValue & 0x3F;
-    byOrgValue = byOrgValue | byLoopbackMode;
-    VNSvOutPortB(dwIoBase + MAC_REG_TEST, byOrgValue);
+	unsigned char byOrgValue;
+
+	ASSERT(byLoopbackMode < 3);
+	byLoopbackMode <<= 6;
+	// set TCR
+	VNSvInPortB(dwIoBase + MAC_REG_TEST, &byOrgValue);
+	byOrgValue = byOrgValue & 0x3F;
+	byOrgValue = byOrgValue | byLoopbackMode;
+	VNSvOutPortB(dwIoBase + MAC_REG_TEST, byOrgValue);
 }
 
 /*
@@ -559,14 +554,14 @@ void MACvSetLoopbackMode (unsigned long dwIoBase, unsigned char byLoopbackMode)
  * Return Value: true if in Loopback mode; otherwise false
  *
  */
-bool MACbIsInLoopbackMode (unsigned long dwIoBase)
+bool MACbIsInLoopbackMode(unsigned long dwIoBase)
 {
-    unsigned char byOrgValue;
+	unsigned char byOrgValue;
 
-    VNSvInPortB(dwIoBase + MAC_REG_TEST, &byOrgValue);
-    if (byOrgValue & (TEST_LBINT | TEST_LBEXT))
-        return true;
-    return false;
+	VNSvInPortB(dwIoBase + MAC_REG_TEST, &byOrgValue);
+	if (byOrgValue & (TEST_LBINT | TEST_LBEXT))
+		return true;
+	return false;
 }
 
 /*
@@ -583,51 +578,50 @@ bool MACbIsInLoopbackMode (unsigned long dwIoBase)
  * Return Value: none
  *
  */
-void MACvSetPacketFilter (unsigned long dwIoBase, unsigned short wFilterType)
+void MACvSetPacketFilter(unsigned long dwIoBase, unsigned short wFilterType)
 {
-    unsigned char byOldRCR;
-    unsigned char byNewRCR = 0;
-
-    // if only in DIRECTED mode, multicast-address will set to zero,
-    // but if other mode exist (e.g. PROMISCUOUS), multicast-address
-    // will be open
-    if (wFilterType & PKT_TYPE_DIRECTED) {
-        // set multicast address to accept none
-        MACvSelectPage1(dwIoBase);
-        VNSvOutPortD(dwIoBase + MAC_REG_MAR0, 0L);
-        VNSvOutPortD(dwIoBase + MAC_REG_MAR0 + sizeof(unsigned long), 0L);
-        MACvSelectPage0(dwIoBase);
-    }
-
-    if (wFilterType & (PKT_TYPE_PROMISCUOUS | PKT_TYPE_ALL_MULTICAST)) {
-        // set multicast address to accept all
-        MACvSelectPage1(dwIoBase);
-        VNSvOutPortD(dwIoBase + MAC_REG_MAR0, 0xFFFFFFFFL);
-        VNSvOutPortD(dwIoBase + MAC_REG_MAR0 + sizeof(unsigned long), 0xFFFFFFFFL);
-        MACvSelectPage0(dwIoBase);
-    }
-
-    if (wFilterType & PKT_TYPE_PROMISCUOUS) {
-
-        byNewRCR |= (RCR_RXALLTYPE | RCR_UNICAST | RCR_MULTICAST | RCR_BROADCAST);
-
-        byNewRCR &= ~RCR_BSSID;
-    }
-
-    if (wFilterType & (PKT_TYPE_ALL_MULTICAST | PKT_TYPE_MULTICAST))
-        byNewRCR |= RCR_MULTICAST;
-
-    if (wFilterType & PKT_TYPE_BROADCAST)
-        byNewRCR |= RCR_BROADCAST;
-
-    if (wFilterType & PKT_TYPE_ERROR_CRC)
-        byNewRCR |= RCR_ERRCRC;
-
-    VNSvInPortB(dwIoBase + MAC_REG_RCR,  &byOldRCR);
-    if (byNewRCR != byOldRCR) {
-        // Modify the Receive Command Register
-        VNSvOutPortB(dwIoBase + MAC_REG_RCR, byNewRCR);
-    }
+	unsigned char byOldRCR;
+	unsigned char byNewRCR = 0;
+
+	// if only in DIRECTED mode, multicast-address will set to zero,
+	// but if other mode exist (e.g. PROMISCUOUS), multicast-address
+	// will be open
+	if (wFilterType & PKT_TYPE_DIRECTED) {
+		// set multicast address to accept none
+		MACvSelectPage1(dwIoBase);
+		VNSvOutPortD(dwIoBase + MAC_REG_MAR0, 0L);
+		VNSvOutPortD(dwIoBase + MAC_REG_MAR0 + sizeof(unsigned long), 0L);
+		MACvSelectPage0(dwIoBase);
+	}
+
+	if (wFilterType & (PKT_TYPE_PROMISCUOUS | PKT_TYPE_ALL_MULTICAST)) {
+		// set multicast address to accept all
+		MACvSelectPage1(dwIoBase);
+		VNSvOutPortD(dwIoBase + MAC_REG_MAR0, 0xFFFFFFFFL);
+		VNSvOutPortD(dwIoBase + MAC_REG_MAR0 + sizeof(unsigned long), 0xFFFFFFFFL);
+		MACvSelectPage0(dwIoBase);
+	}
+
+	if (wFilterType & PKT_TYPE_PROMISCUOUS) {
+		byNewRCR |= (RCR_RXALLTYPE | RCR_UNICAST | RCR_MULTICAST | RCR_BROADCAST);
+
+		byNewRCR &= ~RCR_BSSID;
+	}
+
+	if (wFilterType & (PKT_TYPE_ALL_MULTICAST | PKT_TYPE_MULTICAST))
+		byNewRCR |= RCR_MULTICAST;
+
+	if (wFilterType & PKT_TYPE_BROADCAST)
+		byNewRCR |= RCR_BROADCAST;
+
+	if (wFilterType & PKT_TYPE_ERROR_CRC)
+		byNewRCR |= RCR_ERRCRC;
+
+	VNSvInPortB(dwIoBase + MAC_REG_RCR,  &byOldRCR);
+	if (byNewRCR != byOldRCR) {
+		// Modify the Receive Command Register
+		VNSvOutPortB(dwIoBase + MAC_REG_RCR, byNewRCR);
+	}
 }
 
 /*
@@ -643,23 +637,23 @@ void MACvSetPacketFilter (unsigned long dwIoBase, unsigned short wFilterType)
  * Return Value: none
  *
  */
-void MACvSaveContext (unsigned long dwIoBase, unsigned char *pbyCxtBuf)
+void MACvSaveContext(unsigned long dwIoBase, unsigned char *pbyCxtBuf)
 {
-    int         ii;
+	int         ii;
 
-    // read page0 register
-    for (ii = 0; ii < MAC_MAX_CONTEXT_SIZE_PAGE0; ii++) {
-        VNSvInPortB((dwIoBase + ii), (pbyCxtBuf + ii));
-    }
+	// read page0 register
+	for (ii = 0; ii < MAC_MAX_CONTEXT_SIZE_PAGE0; ii++) {
+		VNSvInPortB((dwIoBase + ii), (pbyCxtBuf + ii));
+	}
 
-    MACvSelectPage1(dwIoBase);
+	MACvSelectPage1(dwIoBase);
 
-    // read page1 register
-    for (ii = 0; ii < MAC_MAX_CONTEXT_SIZE_PAGE1; ii++) {
-        VNSvInPortB((dwIoBase + ii), (pbyCxtBuf + MAC_MAX_CONTEXT_SIZE_PAGE0 + ii));
-    }
+	// read page1 register
+	for (ii = 0; ii < MAC_MAX_CONTEXT_SIZE_PAGE1; ii++) {
+		VNSvInPortB((dwIoBase + ii), (pbyCxtBuf + MAC_MAX_CONTEXT_SIZE_PAGE0 + ii));
+	}
 
-    MACvSelectPage0(dwIoBase);
+	MACvSelectPage0(dwIoBase);
 }
 
 /*
@@ -676,42 +670,40 @@ void MACvSaveContext (unsigned long dwIoBase, unsigned char *pbyCxtBuf)
  * Return Value: none
  *
  */
-void MACvRestoreContext (unsigned long dwIoBase, unsigned char *pbyCxtBuf)
+void MACvRestoreContext(unsigned long dwIoBase, unsigned char *pbyCxtBuf)
 {
-    int         ii;
-
-    MACvSelectPage1(dwIoBase);
-    // restore page1
-    for (ii = 0; ii < MAC_MAX_CONTEXT_SIZE_PAGE1; ii++) {
-        VNSvOutPortB((dwIoBase + ii), *(pbyCxtBuf + MAC_MAX_CONTEXT_SIZE_PAGE0 + ii));
-    }
-    MACvSelectPage0(dwIoBase);
-
-    // restore RCR,TCR,IMR...
-    for (ii = MAC_REG_RCR; ii < MAC_REG_ISR; ii++) {
-        VNSvOutPortB(dwIoBase + ii, *(pbyCxtBuf + ii));
-    }
-    // restore MAC Config.
-    for (ii = MAC_REG_LRT; ii < MAC_REG_PAGE1SEL; ii++) {
-        VNSvOutPortB(dwIoBase + ii, *(pbyCxtBuf + ii));
-    }
-    VNSvOutPortB(dwIoBase + MAC_REG_CFG, *(pbyCxtBuf + MAC_REG_CFG));
-
-    // restore PS Config.
-    for (ii = MAC_REG_PSCFG; ii < MAC_REG_BBREGCTL; ii++) {
-        VNSvOutPortB(dwIoBase + ii, *(pbyCxtBuf + ii));
-    }
-
-    // restore CURR_RX_DESC_ADDR, CURR_TX_DESC_ADDR
-    VNSvOutPortD(dwIoBase + MAC_REG_TXDMAPTR0, *(unsigned long *)(pbyCxtBuf + MAC_REG_TXDMAPTR0));
-    VNSvOutPortD(dwIoBase + MAC_REG_AC0DMAPTR, *(unsigned long *)(pbyCxtBuf + MAC_REG_AC0DMAPTR));
-    VNSvOutPortD(dwIoBase + MAC_REG_BCNDMAPTR, *(unsigned long *)(pbyCxtBuf + MAC_REG_BCNDMAPTR));
-
-
-    VNSvOutPortD(dwIoBase + MAC_REG_RXDMAPTR0, *(unsigned long *)(pbyCxtBuf + MAC_REG_RXDMAPTR0));
-
-    VNSvOutPortD(dwIoBase + MAC_REG_RXDMAPTR1, *(unsigned long *)(pbyCxtBuf + MAC_REG_RXDMAPTR1));
-
+	int         ii;
+
+	MACvSelectPage1(dwIoBase);
+	// restore page1
+	for (ii = 0; ii < MAC_MAX_CONTEXT_SIZE_PAGE1; ii++) {
+		VNSvOutPortB((dwIoBase + ii), *(pbyCxtBuf + MAC_MAX_CONTEXT_SIZE_PAGE0 + ii));
+	}
+	MACvSelectPage0(dwIoBase);
+
+	// restore RCR,TCR,IMR...
+	for (ii = MAC_REG_RCR; ii < MAC_REG_ISR; ii++) {
+		VNSvOutPortB(dwIoBase + ii, *(pbyCxtBuf + ii));
+	}
+	// restore MAC Config.
+	for (ii = MAC_REG_LRT; ii < MAC_REG_PAGE1SEL; ii++) {
+		VNSvOutPortB(dwIoBase + ii, *(pbyCxtBuf + ii));
+	}
+	VNSvOutPortB(dwIoBase + MAC_REG_CFG, *(pbyCxtBuf + MAC_REG_CFG));
+
+	// restore PS Config.
+	for (ii = MAC_REG_PSCFG; ii < MAC_REG_BBREGCTL; ii++) {
+		VNSvOutPortB(dwIoBase + ii, *(pbyCxtBuf + ii));
+	}
+
+	// restore CURR_RX_DESC_ADDR, CURR_TX_DESC_ADDR
+	VNSvOutPortD(dwIoBase + MAC_REG_TXDMAPTR0, *(unsigned long *)(pbyCxtBuf + MAC_REG_TXDMAPTR0));
+	VNSvOutPortD(dwIoBase + MAC_REG_AC0DMAPTR, *(unsigned long *)(pbyCxtBuf + MAC_REG_AC0DMAPTR));
+	VNSvOutPortD(dwIoBase + MAC_REG_BCNDMAPTR, *(unsigned long *)(pbyCxtBuf + MAC_REG_BCNDMAPTR));
+
+	VNSvOutPortD(dwIoBase + MAC_REG_RXDMAPTR0, *(unsigned long *)(pbyCxtBuf + MAC_REG_RXDMAPTR0));
+
+	VNSvOutPortD(dwIoBase + MAC_REG_RXDMAPTR1, *(unsigned long *)(pbyCxtBuf + MAC_REG_RXDMAPTR1));
 }
 
 /*
@@ -728,36 +720,35 @@ void MACvRestoreContext (unsigned long dwIoBase, unsigned char *pbyCxtBuf)
  * Return Value: true if all values are the same; otherwise false
  *
  */
-bool MACbCompareContext (unsigned long dwIoBase, unsigned char *pbyCxtBuf)
+bool MACbCompareContext(unsigned long dwIoBase, unsigned char *pbyCxtBuf)
 {
-    unsigned long dwData;
-
-    // compare MAC context to determine if this is a power lost init,
-    // return true for power remaining init, return false for power lost init
+	unsigned long dwData;
 
-    // compare CURR_RX_DESC_ADDR, CURR_TX_DESC_ADDR
-    VNSvInPortD(dwIoBase + MAC_REG_TXDMAPTR0, &dwData);
-    if (dwData != *(unsigned long *)(pbyCxtBuf + MAC_REG_TXDMAPTR0)) {
-        return false;
-    }
+	// compare MAC context to determine if this is a power lost init,
+	// return true for power remaining init, return false for power lost init
 
-    VNSvInPortD(dwIoBase + MAC_REG_AC0DMAPTR, &dwData);
-    if (dwData != *(unsigned long *)(pbyCxtBuf + MAC_REG_AC0DMAPTR)) {
-        return false;
-    }
+	// compare CURR_RX_DESC_ADDR, CURR_TX_DESC_ADDR
+	VNSvInPortD(dwIoBase + MAC_REG_TXDMAPTR0, &dwData);
+	if (dwData != *(unsigned long *)(pbyCxtBuf + MAC_REG_TXDMAPTR0)) {
+		return false;
+	}
 
-    VNSvInPortD(dwIoBase + MAC_REG_RXDMAPTR0, &dwData);
-    if (dwData != *(unsigned long *)(pbyCxtBuf + MAC_REG_RXDMAPTR0)) {
-        return false;
-    }
+	VNSvInPortD(dwIoBase + MAC_REG_AC0DMAPTR, &dwData);
+	if (dwData != *(unsigned long *)(pbyCxtBuf + MAC_REG_AC0DMAPTR)) {
+		return false;
+	}
 
-    VNSvInPortD(dwIoBase + MAC_REG_RXDMAPTR1, &dwData);
-    if (dwData != *(unsigned long *)(pbyCxtBuf + MAC_REG_RXDMAPTR1)) {
-        return false;
-    }
+	VNSvInPortD(dwIoBase + MAC_REG_RXDMAPTR0, &dwData);
+	if (dwData != *(unsigned long *)(pbyCxtBuf + MAC_REG_RXDMAPTR0)) {
+		return false;
+	}
 
+	VNSvInPortD(dwIoBase + MAC_REG_RXDMAPTR1, &dwData);
+	if (dwData != *(unsigned long *)(pbyCxtBuf + MAC_REG_RXDMAPTR1)) {
+		return false;
+	}
 
-    return true;
+	return true;
 }
 
 /*
@@ -773,24 +764,23 @@ bool MACbCompareContext (unsigned long dwIoBase, unsigned char *pbyCxtBuf)
  * Return Value: true if Reset Success; otherwise false
  *
  */
-bool MACbSoftwareReset (unsigned long dwIoBase)
+bool MACbSoftwareReset(unsigned long dwIoBase)
 {
-    unsigned char byData;
-    unsigned short ww;
-
-    // turn on HOSTCR_SOFTRST, just write 0x01 to reset
-    //MACvRegBitsOn(dwIoBase, MAC_REG_HOSTCR, HOSTCR_SOFTRST);
-    VNSvOutPortB(dwIoBase+ MAC_REG_HOSTCR, 0x01);
-
-    for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
-        VNSvInPortB(dwIoBase + MAC_REG_HOSTCR, &byData);
-        if ( !(byData & HOSTCR_SOFTRST))
-            break;
-    }
-    if (ww == W_MAX_TIMEOUT)
-        return false;
-    return true;
-
+	unsigned char byData;
+	unsigned short ww;
+
+	// turn on HOSTCR_SOFTRST, just write 0x01 to reset
+	//MACvRegBitsOn(dwIoBase, MAC_REG_HOSTCR, HOSTCR_SOFTRST);
+	VNSvOutPortB(dwIoBase + MAC_REG_HOSTCR, 0x01);
+
+	for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
+		VNSvInPortB(dwIoBase + MAC_REG_HOSTCR, &byData);
+		if (!(byData & HOSTCR_SOFTRST))
+			break;
+	}
+	if (ww == W_MAX_TIMEOUT)
+		return false;
+	return true;
 }
 
 /*
@@ -806,24 +796,24 @@ bool MACbSoftwareReset (unsigned long dwIoBase)
  * Return Value: true if success; otherwise false
  *
  */
-bool MACbSafeSoftwareReset (unsigned long dwIoBase)
+bool MACbSafeSoftwareReset(unsigned long dwIoBase)
 {
-    unsigned char abyTmpRegData[MAC_MAX_CONTEXT_SIZE_PAGE0+MAC_MAX_CONTEXT_SIZE_PAGE1];
-    bool bRetVal;
-
-    // PATCH....
-    // save some important register's value, then do
-    // reset, then restore register's value
-
-    // save MAC context
-    MACvSaveContext(dwIoBase, abyTmpRegData);
-    // do reset
-    bRetVal = MACbSoftwareReset(dwIoBase);
-    //BBvSoftwareReset(pDevice->PortOffset);
-    // restore MAC context, except CR0
-    MACvRestoreContext(dwIoBase, abyTmpRegData);
-
-    return bRetVal;
+	unsigned char abyTmpRegData[MAC_MAX_CONTEXT_SIZE_PAGE0+MAC_MAX_CONTEXT_SIZE_PAGE1];
+	bool bRetVal;
+
+	// PATCH....
+	// save some important register's value, then do
+	// reset, then restore register's value
+
+	// save MAC context
+	MACvSaveContext(dwIoBase, abyTmpRegData);
+	// do reset
+	bRetVal = MACbSoftwareReset(dwIoBase);
+	//BBvSoftwareReset(pDevice->PortOffset);
+	// restore MAC context, except CR0
+	MACvRestoreContext(dwIoBase, abyTmpRegData);
+
+	return bRetVal;
 }
 
 /*
@@ -839,52 +829,52 @@ bool MACbSafeSoftwareReset (unsigned long dwIoBase)
  * Return Value: true if success; otherwise false
  *
  */
-bool MACbSafeRxOff (unsigned long dwIoBase)
+bool MACbSafeRxOff(unsigned long dwIoBase)
 {
-    unsigned short ww;
-    unsigned long dwData;
-    unsigned char byData;
-
-    // turn off wow temp for turn off Rx safely
-
-    // Clear RX DMA0,1
-    VNSvOutPortD(dwIoBase + MAC_REG_RXDMACTL0, DMACTL_CLRRUN);
-    VNSvOutPortD(dwIoBase + MAC_REG_RXDMACTL1, DMACTL_CLRRUN);
-    for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
-        VNSvInPortD(dwIoBase + MAC_REG_RXDMACTL0, &dwData);
-        if (!(dwData & DMACTL_RUN))
-            break;
-    }
-    if (ww == W_MAX_TIMEOUT) {
-        DBG_PORT80(0x10);
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" DBG_PORT80(0x10)\n");
-        return(false);
-    }
-    for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
-        VNSvInPortD(dwIoBase + MAC_REG_RXDMACTL1, &dwData);
-        if ( !(dwData & DMACTL_RUN))
-            break;
-    }
-    if (ww == W_MAX_TIMEOUT) {
-        DBG_PORT80(0x11);
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" DBG_PORT80(0x11)\n");
-        return(false);
-    }
-
-    // try to safe shutdown RX
-    MACvRegBitsOff(dwIoBase, MAC_REG_HOSTCR, HOSTCR_RXON);
-    // W_MAX_TIMEOUT is the timeout period
-    for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
-        VNSvInPortB(dwIoBase + MAC_REG_HOSTCR, &byData);
-        if ( !(byData & HOSTCR_RXONST))
-            break;
-    }
-    if (ww == W_MAX_TIMEOUT) {
-        DBG_PORT80(0x12);
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" DBG_PORT80(0x12)\n");
-        return(false);
-    }
-    return true;
+	unsigned short ww;
+	unsigned long dwData;
+	unsigned char byData;
+
+	// turn off wow temp for turn off Rx safely
+
+	// Clear RX DMA0,1
+	VNSvOutPortD(dwIoBase + MAC_REG_RXDMACTL0, DMACTL_CLRRUN);
+	VNSvOutPortD(dwIoBase + MAC_REG_RXDMACTL1, DMACTL_CLRRUN);
+	for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
+		VNSvInPortD(dwIoBase + MAC_REG_RXDMACTL0, &dwData);
+		if (!(dwData & DMACTL_RUN))
+			break;
+	}
+	if (ww == W_MAX_TIMEOUT) {
+		DBG_PORT80(0x10);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " DBG_PORT80(0x10)\n");
+		return false;
+	}
+	for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
+		VNSvInPortD(dwIoBase + MAC_REG_RXDMACTL1, &dwData);
+		if (!(dwData & DMACTL_RUN))
+			break;
+	}
+	if (ww == W_MAX_TIMEOUT) {
+		DBG_PORT80(0x11);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " DBG_PORT80(0x11)\n");
+		return false;
+	}
+
+	// try to safe shutdown RX
+	MACvRegBitsOff(dwIoBase, MAC_REG_HOSTCR, HOSTCR_RXON);
+	// W_MAX_TIMEOUT is the timeout period
+	for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
+		VNSvInPortB(dwIoBase + MAC_REG_HOSTCR, &byData);
+		if (!(byData & HOSTCR_RXONST))
+			break;
+	}
+	if (ww == W_MAX_TIMEOUT) {
+		DBG_PORT80(0x12);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " DBG_PORT80(0x12)\n");
+		return false;
+	}
+	return true;
 }
 
 /*
@@ -900,55 +890,54 @@ bool MACbSafeRxOff (unsigned long dwIoBase)
  * Return Value: true if success; otherwise false
  *
  */
-bool MACbSafeTxOff (unsigned long dwIoBase)
+bool MACbSafeTxOff(unsigned long dwIoBase)
 {
-    unsigned short ww;
-    unsigned long dwData;
-    unsigned char byData;
-
-    // Clear TX DMA
-    //Tx0
-    VNSvOutPortD(dwIoBase + MAC_REG_TXDMACTL0, DMACTL_CLRRUN);
-    //AC0
-    VNSvOutPortD(dwIoBase + MAC_REG_AC0DMACTL, DMACTL_CLRRUN);
-
-
-    for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
-        VNSvInPortD(dwIoBase + MAC_REG_TXDMACTL0, &dwData);
-        if ( !(dwData & DMACTL_RUN))
-            break;
-    }
-    if (ww == W_MAX_TIMEOUT) {
-        DBG_PORT80(0x20);
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" DBG_PORT80(0x20)\n");
-        return(false);
-    }
-    for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
-        VNSvInPortD(dwIoBase + MAC_REG_AC0DMACTL, &dwData);
-        if ( !(dwData & DMACTL_RUN))
-            break;
-    }
-    if (ww == W_MAX_TIMEOUT) {
-        DBG_PORT80(0x21);
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" DBG_PORT80(0x21)\n");
-        return(false);
-    }
-
-    // try to safe shutdown TX
-    MACvRegBitsOff(dwIoBase, MAC_REG_HOSTCR, HOSTCR_TXON);
-
-    // W_MAX_TIMEOUT is the timeout period
-    for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
-        VNSvInPortB(dwIoBase + MAC_REG_HOSTCR, &byData);
-        if ( !(byData & HOSTCR_TXONST))
-            break;
-    }
-    if (ww == W_MAX_TIMEOUT) {
-        DBG_PORT80(0x24);
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" DBG_PORT80(0x24)\n");
-        return(false);
-    }
-    return true;
+	unsigned short ww;
+	unsigned long dwData;
+	unsigned char byData;
+
+	// Clear TX DMA
+	//Tx0
+	VNSvOutPortD(dwIoBase + MAC_REG_TXDMACTL0, DMACTL_CLRRUN);
+	//AC0
+	VNSvOutPortD(dwIoBase + MAC_REG_AC0DMACTL, DMACTL_CLRRUN);
+
+	for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
+		VNSvInPortD(dwIoBase + MAC_REG_TXDMACTL0, &dwData);
+		if (!(dwData & DMACTL_RUN))
+			break;
+	}
+	if (ww == W_MAX_TIMEOUT) {
+		DBG_PORT80(0x20);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " DBG_PORT80(0x20)\n");
+		return false;
+	}
+	for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
+		VNSvInPortD(dwIoBase + MAC_REG_AC0DMACTL, &dwData);
+		if (!(dwData & DMACTL_RUN))
+			break;
+	}
+	if (ww == W_MAX_TIMEOUT) {
+		DBG_PORT80(0x21);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " DBG_PORT80(0x21)\n");
+		return false;
+	}
+
+	// try to safe shutdown TX
+	MACvRegBitsOff(dwIoBase, MAC_REG_HOSTCR, HOSTCR_TXON);
+
+	// W_MAX_TIMEOUT is the timeout period
+	for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
+		VNSvInPortB(dwIoBase + MAC_REG_HOSTCR, &byData);
+		if (!(byData & HOSTCR_TXONST))
+			break;
+	}
+	if (ww == W_MAX_TIMEOUT) {
+		DBG_PORT80(0x24);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " DBG_PORT80(0x24)\n");
+		return false;
+	}
+	return true;
 }
 
 /*
@@ -964,26 +953,26 @@ bool MACbSafeTxOff (unsigned long dwIoBase)
  * Return Value: true if success; otherwise false
  *
  */
-bool MACbSafeStop (unsigned long dwIoBase)
+bool MACbSafeStop(unsigned long dwIoBase)
 {
-    MACvRegBitsOff(dwIoBase, MAC_REG_TCR, TCR_AUTOBCNTX);
-
-    if (MACbSafeRxOff(dwIoBase) == false) {
-        DBG_PORT80(0xA1);
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" MACbSafeRxOff == false)\n");
-        MACbSafeSoftwareReset(dwIoBase);
-        return false;
-    }
-    if (MACbSafeTxOff(dwIoBase) == false) {
-        DBG_PORT80(0xA2);
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" MACbSafeTxOff == false)\n");
-        MACbSafeSoftwareReset(dwIoBase);
-        return false;
-    }
-
-    MACvRegBitsOff(dwIoBase, MAC_REG_HOSTCR, HOSTCR_MACEN);
-
-    return true;
+	MACvRegBitsOff(dwIoBase, MAC_REG_TCR, TCR_AUTOBCNTX);
+
+	if (MACbSafeRxOff(dwIoBase) == false) {
+		DBG_PORT80(0xA1);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " MACbSafeRxOff == false)\n");
+		MACbSafeSoftwareReset(dwIoBase);
+		return false;
+	}
+	if (MACbSafeTxOff(dwIoBase) == false) {
+		DBG_PORT80(0xA2);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " MACbSafeTxOff == false)\n");
+		MACbSafeSoftwareReset(dwIoBase);
+		return false;
+	}
+
+	MACvRegBitsOff(dwIoBase, MAC_REG_HOSTCR, HOSTCR_MACEN);
+
+	return true;
 }
 
 /*
@@ -999,18 +988,18 @@ bool MACbSafeStop (unsigned long dwIoBase)
  * Return Value: true if success; otherwise false
  *
  */
-bool MACbShutdown (unsigned long dwIoBase)
+bool MACbShutdown(unsigned long dwIoBase)
 {
-    // disable MAC IMR
-    MACvIntDisable(dwIoBase);
-    MACvSetLoopbackMode(dwIoBase, MAC_LB_INTERNAL);
-    // stop the adapter
-    if (!MACbSafeStop(dwIoBase)) {
-        MACvSetLoopbackMode(dwIoBase, MAC_LB_NONE);
-        return false;
-    }
-    MACvSetLoopbackMode(dwIoBase, MAC_LB_NONE);
-    return true;
+	// disable MAC IMR
+	MACvIntDisable(dwIoBase);
+	MACvSetLoopbackMode(dwIoBase, MAC_LB_INTERNAL);
+	// stop the adapter
+	if (!MACbSafeStop(dwIoBase)) {
+		MACvSetLoopbackMode(dwIoBase, MAC_LB_NONE);
+		return false;
+	}
+	MACvSetLoopbackMode(dwIoBase, MAC_LB_NONE);
+	return true;
 }
 
 /*
@@ -1026,43 +1015,31 @@ bool MACbShutdown (unsigned long dwIoBase)
  * Return Value: none
  *
  */
-void MACvInitialize (unsigned long dwIoBase)
+void MACvInitialize(unsigned long dwIoBase)
 {
-    // clear sticky bits
-    MACvClearStckDS(dwIoBase);
-    // disable force PME-enable
-    VNSvOutPortB(dwIoBase + MAC_REG_PMC1, PME_OVR);
-    // only 3253 A
-    /*
-    MACvPwrEvntDisable(dwIoBase);
-    // clear power status
-    VNSvOutPortW(dwIoBase + MAC_REG_WAKEUPSR0, 0x0F0F);
-    */
-
-    // do reset
-    MACbSoftwareReset(dwIoBase);
-
-    // issue AUTOLD in EECSR to reload eeprom
-    //MACvRegBitsOn(dwIoBase, MAC_REG_I2MCSR, I2MCSR_AUTOLD);
-    // wait until EEPROM loading complete
-    //while (true) {
-    //    u8 u8Data;
-    //    VNSvInPortB(dwIoBase + MAC_REG_I2MCSR, &u8Data);
-    //    if ( !(u8Data & I2MCSR_AUTOLD))
-    //        break;
-    //}
-
-    // reset TSF counter
-    VNSvOutPortB(dwIoBase + MAC_REG_TFTCTL, TFTCTL_TSFCNTRST);
-    // enable TSF counter
-    VNSvOutPortB(dwIoBase + MAC_REG_TFTCTL, TFTCTL_TSFCNTREN);
-
-
-    // set packet filter
-    // receive directed and broadcast address
-
-    MACvSetPacketFilter(dwIoBase, PKT_TYPE_DIRECTED | PKT_TYPE_BROADCAST);
-
+	// clear sticky bits
+	MACvClearStckDS(dwIoBase);
+	// disable force PME-enable
+	VNSvOutPortB(dwIoBase + MAC_REG_PMC1, PME_OVR);
+	// only 3253 A
+	/*
+	  MACvPwrEvntDisable(dwIoBase);
+	  // clear power status
+	  VNSvOutPortW(dwIoBase + MAC_REG_WAKEUPSR0, 0x0F0F);
+	*/
+
+	// do reset
+	MACbSoftwareReset(dwIoBase);
+
+	// reset TSF counter
+	VNSvOutPortB(dwIoBase + MAC_REG_TFTCTL, TFTCTL_TSFCNTRST);
+	// enable TSF counter
+	VNSvOutPortB(dwIoBase + MAC_REG_TFTCTL, TFTCTL_TSFCNTREN);
+
+	// set packet filter
+	// receive directed and broadcast address
+
+	MACvSetPacketFilter(dwIoBase, PKT_TYPE_DIRECTED | PKT_TYPE_BROADCAST);
 }
 
 /*
@@ -1079,28 +1056,28 @@ void MACvInitialize (unsigned long dwIoBase)
  * Return Value: none
  *
  */
-void MACvSetCurrRx0DescAddr (unsigned long dwIoBase, unsigned long dwCurrDescAddr)
+void MACvSetCurrRx0DescAddr(unsigned long dwIoBase, unsigned long dwCurrDescAddr)
 {
-unsigned short ww;
-unsigned char byData;
-unsigned char byOrgDMACtl;
-
-    VNSvInPortB(dwIoBase + MAC_REG_RXDMACTL0, &byOrgDMACtl);
-    if (byOrgDMACtl & DMACTL_RUN) {
-        VNSvOutPortB(dwIoBase + MAC_REG_RXDMACTL0+2, DMACTL_RUN);
-    }
-    for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
-        VNSvInPortB(dwIoBase + MAC_REG_RXDMACTL0, &byData);
-        if ( !(byData & DMACTL_RUN))
-            break;
-    }
-    if (ww == W_MAX_TIMEOUT) {
-        DBG_PORT80(0x13);
-    }
-    VNSvOutPortD(dwIoBase + MAC_REG_RXDMAPTR0, dwCurrDescAddr);
-    if (byOrgDMACtl & DMACTL_RUN) {
-        VNSvOutPortB(dwIoBase + MAC_REG_RXDMACTL0, DMACTL_RUN);
-    }
+	unsigned short ww;
+	unsigned char byData;
+	unsigned char byOrgDMACtl;
+
+	VNSvInPortB(dwIoBase + MAC_REG_RXDMACTL0, &byOrgDMACtl);
+	if (byOrgDMACtl & DMACTL_RUN) {
+		VNSvOutPortB(dwIoBase + MAC_REG_RXDMACTL0+2, DMACTL_RUN);
+	}
+	for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
+		VNSvInPortB(dwIoBase + MAC_REG_RXDMACTL0, &byData);
+		if (!(byData & DMACTL_RUN))
+			break;
+	}
+	if (ww == W_MAX_TIMEOUT) {
+		DBG_PORT80(0x13);
+	}
+	VNSvOutPortD(dwIoBase + MAC_REG_RXDMAPTR0, dwCurrDescAddr);
+	if (byOrgDMACtl & DMACTL_RUN) {
+		VNSvOutPortB(dwIoBase + MAC_REG_RXDMACTL0, DMACTL_RUN);
+	}
 }
 
 /*
@@ -1117,28 +1094,28 @@ unsigned char byOrgDMACtl;
  * Return Value: none
  *
  */
-void MACvSetCurrRx1DescAddr (unsigned long dwIoBase, unsigned long dwCurrDescAddr)
+void MACvSetCurrRx1DescAddr(unsigned long dwIoBase, unsigned long dwCurrDescAddr)
 {
-unsigned short ww;
-unsigned char byData;
-unsigned char byOrgDMACtl;
-
-    VNSvInPortB(dwIoBase + MAC_REG_RXDMACTL1, &byOrgDMACtl);
-    if (byOrgDMACtl & DMACTL_RUN) {
-        VNSvOutPortB(dwIoBase + MAC_REG_RXDMACTL1+2, DMACTL_RUN);
-    }
-    for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
-        VNSvInPortB(dwIoBase + MAC_REG_RXDMACTL1, &byData);
-        if ( !(byData & DMACTL_RUN))
-            break;
-    }
-    if (ww == W_MAX_TIMEOUT) {
-        DBG_PORT80(0x14);
-    }
-    VNSvOutPortD(dwIoBase + MAC_REG_RXDMAPTR1, dwCurrDescAddr);
-    if (byOrgDMACtl & DMACTL_RUN) {
-        VNSvOutPortB(dwIoBase + MAC_REG_RXDMACTL1, DMACTL_RUN);
-    }
+	unsigned short ww;
+	unsigned char byData;
+	unsigned char byOrgDMACtl;
+
+	VNSvInPortB(dwIoBase + MAC_REG_RXDMACTL1, &byOrgDMACtl);
+	if (byOrgDMACtl & DMACTL_RUN) {
+		VNSvOutPortB(dwIoBase + MAC_REG_RXDMACTL1+2, DMACTL_RUN);
+	}
+	for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
+		VNSvInPortB(dwIoBase + MAC_REG_RXDMACTL1, &byData);
+		if (!(byData & DMACTL_RUN))
+			break;
+	}
+	if (ww == W_MAX_TIMEOUT) {
+		DBG_PORT80(0x14);
+	}
+	VNSvOutPortD(dwIoBase + MAC_REG_RXDMAPTR1, dwCurrDescAddr);
+	if (byOrgDMACtl & DMACTL_RUN) {
+		VNSvOutPortB(dwIoBase + MAC_REG_RXDMACTL1, DMACTL_RUN);
+	}
 }
 
 /*
@@ -1155,28 +1132,28 @@ unsigned char byOrgDMACtl;
  * Return Value: none
  *
  */
-void MACvSetCurrTx0DescAddrEx (unsigned long dwIoBase, unsigned long dwCurrDescAddr)
+void MACvSetCurrTx0DescAddrEx(unsigned long dwIoBase, unsigned long dwCurrDescAddr)
 {
-unsigned short ww;
-unsigned char byData;
-unsigned char byOrgDMACtl;
-
-    VNSvInPortB(dwIoBase + MAC_REG_TXDMACTL0, &byOrgDMACtl);
-    if (byOrgDMACtl & DMACTL_RUN) {
-        VNSvOutPortB(dwIoBase + MAC_REG_TXDMACTL0+2, DMACTL_RUN);
-    }
-    for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
-        VNSvInPortB(dwIoBase + MAC_REG_TXDMACTL0, &byData);
-        if ( !(byData & DMACTL_RUN))
-            break;
-    }
-    if (ww == W_MAX_TIMEOUT) {
-        DBG_PORT80(0x25);
-    }
-    VNSvOutPortD(dwIoBase + MAC_REG_TXDMAPTR0, dwCurrDescAddr);
-    if (byOrgDMACtl & DMACTL_RUN) {
-        VNSvOutPortB(dwIoBase + MAC_REG_TXDMACTL0, DMACTL_RUN);
-    }
+	unsigned short ww;
+	unsigned char byData;
+	unsigned char byOrgDMACtl;
+
+	VNSvInPortB(dwIoBase + MAC_REG_TXDMACTL0, &byOrgDMACtl);
+	if (byOrgDMACtl & DMACTL_RUN) {
+		VNSvOutPortB(dwIoBase + MAC_REG_TXDMACTL0+2, DMACTL_RUN);
+	}
+	for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
+		VNSvInPortB(dwIoBase + MAC_REG_TXDMACTL0, &byData);
+		if (!(byData & DMACTL_RUN))
+			break;
+	}
+	if (ww == W_MAX_TIMEOUT) {
+		DBG_PORT80(0x25);
+	}
+	VNSvOutPortD(dwIoBase + MAC_REG_TXDMAPTR0, dwCurrDescAddr);
+	if (byOrgDMACtl & DMACTL_RUN) {
+		VNSvOutPortB(dwIoBase + MAC_REG_TXDMACTL0, DMACTL_RUN);
+	}
 }
 
 /*
@@ -1193,41 +1170,39 @@ unsigned char byOrgDMACtl;
  * Return Value: none
  *
  */
- //TxDMA1 = AC0DMA
-void MACvSetCurrAC0DescAddrEx (unsigned long dwIoBase, unsigned long dwCurrDescAddr)
+//TxDMA1 = AC0DMA
+void MACvSetCurrAC0DescAddrEx(unsigned long dwIoBase, unsigned long dwCurrDescAddr)
 {
-unsigned short ww;
-unsigned char byData;
-unsigned char byOrgDMACtl;
-
-    VNSvInPortB(dwIoBase + MAC_REG_AC0DMACTL, &byOrgDMACtl);
-    if (byOrgDMACtl & DMACTL_RUN) {
-        VNSvOutPortB(dwIoBase + MAC_REG_AC0DMACTL+2, DMACTL_RUN);
-    }
-    for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
-        VNSvInPortB(dwIoBase + MAC_REG_AC0DMACTL, &byData);
-        if (!(byData & DMACTL_RUN))
-            break;
-    }
-    if (ww == W_MAX_TIMEOUT) {
-        DBG_PORT80(0x26);
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" DBG_PORT80(0x26)\n");
-    }
-    VNSvOutPortD(dwIoBase + MAC_REG_AC0DMAPTR, dwCurrDescAddr);
-    if (byOrgDMACtl & DMACTL_RUN) {
-        VNSvOutPortB(dwIoBase + MAC_REG_AC0DMACTL, DMACTL_RUN);
-    }
+	unsigned short ww;
+	unsigned char byData;
+	unsigned char byOrgDMACtl;
+
+	VNSvInPortB(dwIoBase + MAC_REG_AC0DMACTL, &byOrgDMACtl);
+	if (byOrgDMACtl & DMACTL_RUN) {
+		VNSvOutPortB(dwIoBase + MAC_REG_AC0DMACTL+2, DMACTL_RUN);
+	}
+	for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
+		VNSvInPortB(dwIoBase + MAC_REG_AC0DMACTL, &byData);
+		if (!(byData & DMACTL_RUN))
+			break;
+	}
+	if (ww == W_MAX_TIMEOUT) {
+		DBG_PORT80(0x26);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " DBG_PORT80(0x26)\n");
+	}
+	VNSvOutPortD(dwIoBase + MAC_REG_AC0DMAPTR, dwCurrDescAddr);
+	if (byOrgDMACtl & DMACTL_RUN) {
+		VNSvOutPortB(dwIoBase + MAC_REG_AC0DMACTL, DMACTL_RUN);
+	}
 }
 
-
-
-void MACvSetCurrTXDescAddr (int iTxType, unsigned long dwIoBase, unsigned long dwCurrDescAddr)
+void MACvSetCurrTXDescAddr(int iTxType, unsigned long dwIoBase, unsigned long dwCurrDescAddr)
 {
-    if(iTxType == TYPE_AC0DMA){
-        MACvSetCurrAC0DescAddrEx(dwIoBase, dwCurrDescAddr);
-    }else if(iTxType == TYPE_TXDMA0){
-        MACvSetCurrTx0DescAddrEx(dwIoBase, dwCurrDescAddr);
-    }
+	if (iTxType == TYPE_AC0DMA) {
+		MACvSetCurrAC0DescAddrEx(dwIoBase, dwCurrDescAddr);
+	} else if (iTxType == TYPE_TXDMA0) {
+		MACvSetCurrTx0DescAddrEx(dwIoBase, dwCurrDescAddr);
+	}
 }
 
 /*
@@ -1244,26 +1219,25 @@ void MACvSetCurrTXDescAddr (int iTxType, unsigned long dwIoBase, unsigned long d
  * Return Value: none
  *
  */
-void MACvTimer0MicroSDelay (unsigned long dwIoBase, unsigned int uDelay)
+void MACvTimer0MicroSDelay(unsigned long dwIoBase, unsigned int uDelay)
 {
-unsigned char byValue;
-unsigned int uu,ii;
-
-    VNSvOutPortB(dwIoBase + MAC_REG_TMCTL0, 0);
-    VNSvOutPortD(dwIoBase + MAC_REG_TMDATA0, uDelay);
-    VNSvOutPortB(dwIoBase + MAC_REG_TMCTL0, (TMCTL_TMD | TMCTL_TE));
-    for(ii=0;ii<66;ii++) {  // assume max PCI clock is 66Mhz
-        for (uu = 0; uu < uDelay; uu++) {
-            VNSvInPortB(dwIoBase + MAC_REG_TMCTL0, &byValue);
-            if ((byValue == 0) ||
-                (byValue & TMCTL_TSUSP)) {
-                VNSvOutPortB(dwIoBase + MAC_REG_TMCTL0, 0);
-                return;
-            }
-        }
-    }
-    VNSvOutPortB(dwIoBase + MAC_REG_TMCTL0, 0);
-
+	unsigned char byValue;
+	unsigned int uu, ii;
+
+	VNSvOutPortB(dwIoBase + MAC_REG_TMCTL0, 0);
+	VNSvOutPortD(dwIoBase + MAC_REG_TMDATA0, uDelay);
+	VNSvOutPortB(dwIoBase + MAC_REG_TMCTL0, (TMCTL_TMD | TMCTL_TE));
+	for (ii = 0; ii < 66; ii++) {  // assume max PCI clock is 66Mhz
+		for (uu = 0; uu < uDelay; uu++) {
+			VNSvInPortB(dwIoBase + MAC_REG_TMCTL0, &byValue);
+			if ((byValue == 0) ||
+			    (byValue & TMCTL_TSUSP)) {
+				VNSvOutPortB(dwIoBase + MAC_REG_TMCTL0, 0);
+				return;
+			}
+		}
+	}
+	VNSvOutPortB(dwIoBase + MAC_REG_TMCTL0, 0);
 }
 
 /*
@@ -1280,11 +1254,11 @@ unsigned int uu,ii;
  * Return Value: none
  *
  */
-void MACvOneShotTimer0MicroSec (unsigned long dwIoBase, unsigned int uDelayTime)
+void MACvOneShotTimer0MicroSec(unsigned long dwIoBase, unsigned int uDelayTime)
 {
-    VNSvOutPortB(dwIoBase + MAC_REG_TMCTL0, 0);
-    VNSvOutPortD(dwIoBase + MAC_REG_TMDATA0, uDelayTime);
-    VNSvOutPortB(dwIoBase + MAC_REG_TMCTL0, (TMCTL_TMD | TMCTL_TE));
+	VNSvOutPortB(dwIoBase + MAC_REG_TMCTL0, 0);
+	VNSvOutPortD(dwIoBase + MAC_REG_TMDATA0, uDelayTime);
+	VNSvOutPortB(dwIoBase + MAC_REG_TMCTL0, (TMCTL_TMD | TMCTL_TE));
 }
 
 /*
@@ -1301,143 +1275,141 @@ void MACvOneShotTimer0MicroSec (unsigned long dwIoBase, unsigned int uDelayTime)
  * Return Value: none
  *
  */
-void MACvOneShotTimer1MicroSec (unsigned long dwIoBase, unsigned int uDelayTime)
+void MACvOneShotTimer1MicroSec(unsigned long dwIoBase, unsigned int uDelayTime)
 {
-    VNSvOutPortB(dwIoBase + MAC_REG_TMCTL1, 0);
-    VNSvOutPortD(dwIoBase + MAC_REG_TMDATA1, uDelayTime);
-    VNSvOutPortB(dwIoBase + MAC_REG_TMCTL1, (TMCTL_TMD | TMCTL_TE));
+	VNSvOutPortB(dwIoBase + MAC_REG_TMCTL1, 0);
+	VNSvOutPortD(dwIoBase + MAC_REG_TMDATA1, uDelayTime);
+	VNSvOutPortB(dwIoBase + MAC_REG_TMCTL1, (TMCTL_TMD | TMCTL_TE));
 }
 
-
-void MACvSetMISCFifo (unsigned long dwIoBase, unsigned short wOffset, unsigned long dwData)
+void MACvSetMISCFifo(unsigned long dwIoBase, unsigned short wOffset, unsigned long dwData)
 {
-    if (wOffset > 273)
-        return;
-    VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset);
-    VNSvOutPortD(dwIoBase + MAC_REG_MISCFFDATA, dwData);
-    VNSvOutPortW(dwIoBase + MAC_REG_MISCFFCTL, MISCFFCTL_WRITE);
+	if (wOffset > 273)
+		return;
+	VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset);
+	VNSvOutPortD(dwIoBase + MAC_REG_MISCFFDATA, dwData);
+	VNSvOutPortW(dwIoBase + MAC_REG_MISCFFCTL, MISCFFCTL_WRITE);
 }
 
-
-bool MACbTxDMAOff (unsigned long dwIoBase, unsigned int idx)
+bool MACbTxDMAOff(unsigned long dwIoBase, unsigned int idx)
 {
-unsigned char byData;
-unsigned int ww = 0;
-
-    if (idx == TYPE_TXDMA0) {
-        VNSvOutPortB(dwIoBase + MAC_REG_TXDMACTL0+2, DMACTL_RUN);
-        for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
-            VNSvInPortB(dwIoBase + MAC_REG_TXDMACTL0, &byData);
-            if ( !(byData & DMACTL_RUN))
-                break;
-        }
-    } else if (idx == TYPE_AC0DMA) {
-        VNSvOutPortB(dwIoBase + MAC_REG_AC0DMACTL+2, DMACTL_RUN);
-        for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
-            VNSvInPortB(dwIoBase + MAC_REG_AC0DMACTL, &byData);
-            if ( !(byData & DMACTL_RUN))
-                break;
-        }
-    }
-    if (ww == W_MAX_TIMEOUT) {
-        DBG_PORT80(0x29);
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" DBG_PORT80(0x29)\n");
-        return false;
-    }
-    return true;
+	unsigned char byData;
+	unsigned int ww = 0;
+
+	if (idx == TYPE_TXDMA0) {
+		VNSvOutPortB(dwIoBase + MAC_REG_TXDMACTL0+2, DMACTL_RUN);
+		for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
+			VNSvInPortB(dwIoBase + MAC_REG_TXDMACTL0, &byData);
+			if (!(byData & DMACTL_RUN))
+				break;
+		}
+	} else if (idx == TYPE_AC0DMA) {
+		VNSvOutPortB(dwIoBase + MAC_REG_AC0DMACTL+2, DMACTL_RUN);
+		for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
+			VNSvInPortB(dwIoBase + MAC_REG_AC0DMACTL, &byData);
+			if (!(byData & DMACTL_RUN))
+				break;
+		}
+	}
+	if (ww == W_MAX_TIMEOUT) {
+		DBG_PORT80(0x29);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " DBG_PORT80(0x29)\n");
+		return false;
+	}
+	return true;
 }
 
-void MACvClearBusSusInd (unsigned long dwIoBase)
+void MACvClearBusSusInd(unsigned long dwIoBase)
 {
-    unsigned long dwOrgValue;
-    unsigned int ww;
-    // check if BcnSusInd enabled
-    VNSvInPortD(dwIoBase + MAC_REG_ENCFG , &dwOrgValue);
-    if( !(dwOrgValue & EnCFG_BcnSusInd))
-        return;
-    //Set BcnSusClr
-    dwOrgValue = dwOrgValue | EnCFG_BcnSusClr;
-    VNSvOutPortD(dwIoBase + MAC_REG_ENCFG, dwOrgValue);
-    for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
-        VNSvInPortD(dwIoBase + MAC_REG_ENCFG , &dwOrgValue);
-        if( !(dwOrgValue & EnCFG_BcnSusInd))
-            break;
-    }
-    if (ww == W_MAX_TIMEOUT) {
-        DBG_PORT80(0x33);
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" DBG_PORT80(0x33)\n");
-    }
+	unsigned long dwOrgValue;
+	unsigned int ww;
+	// check if BcnSusInd enabled
+	VNSvInPortD(dwIoBase + MAC_REG_ENCFG , &dwOrgValue);
+	if (!(dwOrgValue & EnCFG_BcnSusInd))
+		return;
+	//Set BcnSusClr
+	dwOrgValue = dwOrgValue | EnCFG_BcnSusClr;
+	VNSvOutPortD(dwIoBase + MAC_REG_ENCFG, dwOrgValue);
+	for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
+		VNSvInPortD(dwIoBase + MAC_REG_ENCFG , &dwOrgValue);
+		if (!(dwOrgValue & EnCFG_BcnSusInd))
+			break;
+	}
+	if (ww == W_MAX_TIMEOUT) {
+		DBG_PORT80(0x33);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " DBG_PORT80(0x33)\n");
+	}
 }
 
-void MACvEnableBusSusEn (unsigned long dwIoBase)
+void MACvEnableBusSusEn(unsigned long dwIoBase)
 {
-    unsigned char byOrgValue;
-    unsigned long dwOrgValue;
-    unsigned int ww;
-    // check if BcnSusInd enabled
-    VNSvInPortB(dwIoBase + MAC_REG_CFG , &byOrgValue);
-
-    //Set BcnSusEn
-    byOrgValue = byOrgValue | CFG_BCNSUSEN;
-    VNSvOutPortB(dwIoBase + MAC_REG_ENCFG, byOrgValue);
-    for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
-        VNSvInPortD(dwIoBase + MAC_REG_ENCFG , &dwOrgValue);
-        if(dwOrgValue & EnCFG_BcnSusInd)
-            break;
-    }
-    if (ww == W_MAX_TIMEOUT) {
-        DBG_PORT80(0x34);
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" DBG_PORT80(0x34)\n");
-    }
+	unsigned char byOrgValue;
+	unsigned long dwOrgValue;
+	unsigned int ww;
+	// check if BcnSusInd enabled
+	VNSvInPortB(dwIoBase + MAC_REG_CFG , &byOrgValue);
+
+	//Set BcnSusEn
+	byOrgValue = byOrgValue | CFG_BCNSUSEN;
+	VNSvOutPortB(dwIoBase + MAC_REG_ENCFG, byOrgValue);
+	for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
+		VNSvInPortD(dwIoBase + MAC_REG_ENCFG , &dwOrgValue);
+		if (dwOrgValue & EnCFG_BcnSusInd)
+			break;
+	}
+	if (ww == W_MAX_TIMEOUT) {
+		DBG_PORT80(0x34);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " DBG_PORT80(0x34)\n");
+	}
 }
 
-bool MACbFlushSYNCFifo (unsigned long dwIoBase)
+bool MACbFlushSYNCFifo(unsigned long dwIoBase)
 {
-    unsigned char byOrgValue;
-    unsigned int ww;
-    // Read MACCR
-    VNSvInPortB(dwIoBase + MAC_REG_MACCR , &byOrgValue);
-
-    // Set SYNCFLUSH
-    byOrgValue = byOrgValue | MACCR_SYNCFLUSH;
-    VNSvOutPortB(dwIoBase + MAC_REG_MACCR, byOrgValue);
-
-    // Check if SyncFlushOK
-    for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
-        VNSvInPortB(dwIoBase + MAC_REG_MACCR , &byOrgValue);
-        if(byOrgValue & MACCR_SYNCFLUSHOK)
-            break;
-    }
-    if (ww == W_MAX_TIMEOUT) {
-        DBG_PORT80(0x35);
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" DBG_PORT80(0x33)\n");
-    }
-    return true;
+	unsigned char byOrgValue;
+	unsigned int ww;
+	// Read MACCR
+	VNSvInPortB(dwIoBase + MAC_REG_MACCR , &byOrgValue);
+
+	// Set SYNCFLUSH
+	byOrgValue = byOrgValue | MACCR_SYNCFLUSH;
+	VNSvOutPortB(dwIoBase + MAC_REG_MACCR, byOrgValue);
+
+	// Check if SyncFlushOK
+	for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
+		VNSvInPortB(dwIoBase + MAC_REG_MACCR , &byOrgValue);
+		if (byOrgValue & MACCR_SYNCFLUSHOK)
+			break;
+	}
+	if (ww == W_MAX_TIMEOUT) {
+		DBG_PORT80(0x35);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " DBG_PORT80(0x33)\n");
+	}
+	return true;
 }
 
-bool MACbPSWakeup (unsigned long dwIoBase)
+bool MACbPSWakeup(unsigned long dwIoBase)
 {
-    unsigned char byOrgValue;
-    unsigned int ww;
-    // Read PSCTL
-    if (MACbIsRegBitsOff(dwIoBase, MAC_REG_PSCTL, PSCTL_PS)) {
-        return true;
-    }
-    // Disable PS
-    MACvRegBitsOff(dwIoBase, MAC_REG_PSCTL, PSCTL_PSEN);
-
-    // Check if SyncFlushOK
-    for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
-        VNSvInPortB(dwIoBase + MAC_REG_PSCTL , &byOrgValue);
-        if(byOrgValue & PSCTL_WAKEDONE)
-            break;
-    }
-    if (ww == W_MAX_TIMEOUT) {
-        DBG_PORT80(0x36);
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" DBG_PORT80(0x33)\n");
-        return false;
-    }
-    return true;
+	unsigned char byOrgValue;
+	unsigned int ww;
+	// Read PSCTL
+	if (MACbIsRegBitsOff(dwIoBase, MAC_REG_PSCTL, PSCTL_PS)) {
+		return true;
+	}
+	// Disable PS
+	MACvRegBitsOff(dwIoBase, MAC_REG_PSCTL, PSCTL_PSEN);
+
+	// Check if SyncFlushOK
+	for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
+		VNSvInPortB(dwIoBase + MAC_REG_PSCTL , &byOrgValue);
+		if (byOrgValue & PSCTL_WAKEDONE)
+			break;
+	}
+	if (ww == W_MAX_TIMEOUT) {
+		DBG_PORT80(0x36);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " DBG_PORT80(0x33)\n");
+		return false;
+	}
+	return true;
 }
 
 /*
@@ -1455,59 +1427,56 @@ bool MACbPSWakeup (unsigned long dwIoBase)
  *
  */
 
-void MACvSetKeyEntry (unsigned long dwIoBase, unsigned short wKeyCtl, unsigned int uEntryIdx,
-		unsigned int uKeyIdx, unsigned char *pbyAddr, unsigned long *pdwKey, unsigned char byLocalID)
+void MACvSetKeyEntry(unsigned long dwIoBase, unsigned short wKeyCtl, unsigned int uEntryIdx,
+		     unsigned int uKeyIdx, unsigned char *pbyAddr, unsigned long *pdwKey, unsigned char byLocalID)
 {
-unsigned short wOffset;
-unsigned long dwData;
-int     ii;
-
-    if (byLocalID <= 1)
-        return;
-
-
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MACvSetKeyEntry\n");
-    wOffset = MISCFIFO_KEYETRY0;
-    wOffset += (uEntryIdx * MISCFIFO_KEYENTRYSIZE);
-
-    dwData = 0;
-    dwData |= wKeyCtl;
-    dwData <<= 16;
-    dwData |= MAKEWORD(*(pbyAddr+4), *(pbyAddr+5));
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"1. wOffset: %d, Data: %lX, KeyCtl:%X\n", wOffset, dwData, wKeyCtl);
-
-    VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset);
-    VNSvOutPortD(dwIoBase + MAC_REG_MISCFFDATA, dwData);
-    VNSvOutPortW(dwIoBase + MAC_REG_MISCFFCTL, MISCFFCTL_WRITE);
-    wOffset++;
-
-    dwData = 0;
-    dwData |= *(pbyAddr+3);
-    dwData <<= 8;
-    dwData |= *(pbyAddr+2);
-    dwData <<= 8;
-    dwData |= *(pbyAddr+1);
-    dwData <<= 8;
-    dwData |= *(pbyAddr+0);
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"2. wOffset: %d, Data: %lX\n", wOffset, dwData);
-
-    VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset);
-    VNSvOutPortD(dwIoBase + MAC_REG_MISCFFDATA, dwData);
-    VNSvOutPortW(dwIoBase + MAC_REG_MISCFFCTL, MISCFFCTL_WRITE);
-    wOffset++;
-
-    wOffset += (uKeyIdx * 4);
-    for (ii=0;ii<4;ii++) {
-        // always push 128 bits
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"3.(%d) wOffset: %d, Data: %lX\n", ii, wOffset+ii, *pdwKey);
-        VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset+ii);
-        VNSvOutPortD(dwIoBase + MAC_REG_MISCFFDATA, *pdwKey++);
-        VNSvOutPortW(dwIoBase + MAC_REG_MISCFFCTL, MISCFFCTL_WRITE);
-    }
+	unsigned short wOffset;
+	unsigned long dwData;
+	int     ii;
+
+	if (byLocalID <= 1)
+		return;
+
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "MACvSetKeyEntry\n");
+	wOffset = MISCFIFO_KEYETRY0;
+	wOffset += (uEntryIdx * MISCFIFO_KEYENTRYSIZE);
+
+	dwData = 0;
+	dwData |= wKeyCtl;
+	dwData <<= 16;
+	dwData |= MAKEWORD(*(pbyAddr+4), *(pbyAddr+5));
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "1. wOffset: %d, Data: %lX, KeyCtl:%X\n", wOffset, dwData, wKeyCtl);
+
+	VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset);
+	VNSvOutPortD(dwIoBase + MAC_REG_MISCFFDATA, dwData);
+	VNSvOutPortW(dwIoBase + MAC_REG_MISCFFCTL, MISCFFCTL_WRITE);
+	wOffset++;
+
+	dwData = 0;
+	dwData |= *(pbyAddr+3);
+	dwData <<= 8;
+	dwData |= *(pbyAddr+2);
+	dwData <<= 8;
+	dwData |= *(pbyAddr+1);
+	dwData <<= 8;
+	dwData |= *(pbyAddr+0);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "2. wOffset: %d, Data: %lX\n", wOffset, dwData);
+
+	VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset);
+	VNSvOutPortD(dwIoBase + MAC_REG_MISCFFDATA, dwData);
+	VNSvOutPortW(dwIoBase + MAC_REG_MISCFFCTL, MISCFFCTL_WRITE);
+	wOffset++;
+
+	wOffset += (uKeyIdx * 4);
+	for (ii = 0; ii < 4; ii++) {
+		// always push 128 bits
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "3.(%d) wOffset: %d, Data: %lX\n", ii, wOffset+ii, *pdwKey);
+		VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset+ii);
+		VNSvOutPortD(dwIoBase + MAC_REG_MISCFFDATA, *pdwKey++);
+		VNSvOutPortW(dwIoBase + MAC_REG_MISCFFCTL, MISCFFCTL_WRITE);
+	}
 }
 
-
-
 /*
  * Description:
  *      Disable the Key Entry by MISCFIFO
@@ -1522,19 +1491,18 @@ int     ii;
  * Return Value: none
  *
  */
-void MACvDisableKeyEntry (unsigned long dwIoBase, unsigned int uEntryIdx)
+void MACvDisableKeyEntry(unsigned long dwIoBase, unsigned int uEntryIdx)
 {
-unsigned short wOffset;
+	unsigned short wOffset;
 
-    wOffset = MISCFIFO_KEYETRY0;
-    wOffset += (uEntryIdx * MISCFIFO_KEYENTRYSIZE);
+	wOffset = MISCFIFO_KEYETRY0;
+	wOffset += (uEntryIdx * MISCFIFO_KEYENTRYSIZE);
 
-    VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset);
-    VNSvOutPortD(dwIoBase + MAC_REG_MISCFFDATA, 0);
-    VNSvOutPortW(dwIoBase + MAC_REG_MISCFFCTL, MISCFFCTL_WRITE);
+	VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset);
+	VNSvOutPortD(dwIoBase + MAC_REG_MISCFFDATA, 0);
+	VNSvOutPortW(dwIoBase + MAC_REG_MISCFFCTL, MISCFFCTL_WRITE);
 }
 
-
 /*
  * Description:
  *      Set the default Key (KeyEntry[10]) by MISCFIFO
@@ -1550,42 +1518,40 @@ unsigned short wOffset;
  *
  */
 
-void MACvSetDefaultKeyEntry (unsigned long dwIoBase, unsigned int uKeyLen,
-		unsigned int uKeyIdx, unsigned long *pdwKey, unsigned char byLocalID)
+void MACvSetDefaultKeyEntry(unsigned long dwIoBase, unsigned int uKeyLen,
+			    unsigned int uKeyIdx, unsigned long *pdwKey, unsigned char byLocalID)
 {
-unsigned short wOffset;
-unsigned long dwData;
-int     ii;
-
-    if (byLocalID <= 1)
-        return;
-
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MACvSetDefaultKeyEntry\n");
-    wOffset = MISCFIFO_KEYETRY0;
-    wOffset += (10 * MISCFIFO_KEYENTRYSIZE);
-
-    wOffset++;
-    wOffset++;
-    wOffset += (uKeyIdx * 4);
-    // always push 128 bits
-    for (ii=0; ii<3; ii++) {
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"(%d) wOffset: %d, Data: %lX\n", ii, wOffset+ii, *pdwKey);
-        VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset+ii);
-        VNSvOutPortD(dwIoBase + MAC_REG_MISCFFDATA, *pdwKey++);
-        VNSvOutPortW(dwIoBase + MAC_REG_MISCFFCTL, MISCFFCTL_WRITE);
-    }
-    dwData = *pdwKey;
-    if (uKeyLen == WLAN_WEP104_KEYLEN) {
-        dwData |= 0x80000000;
-    }
-    VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset+3);
-    VNSvOutPortD(dwIoBase + MAC_REG_MISCFFDATA, dwData);
-    VNSvOutPortW(dwIoBase + MAC_REG_MISCFFCTL, MISCFFCTL_WRITE);
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"End. wOffset: %d, Data: %lX\n", wOffset+3, dwData);
-
+	unsigned short wOffset;
+	unsigned long dwData;
+	int     ii;
+
+	if (byLocalID <= 1)
+		return;
+
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "MACvSetDefaultKeyEntry\n");
+	wOffset = MISCFIFO_KEYETRY0;
+	wOffset += (10 * MISCFIFO_KEYENTRYSIZE);
+
+	wOffset++;
+	wOffset++;
+	wOffset += (uKeyIdx * 4);
+	// always push 128 bits
+	for (ii = 0; ii < 3; ii++) {
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "(%d) wOffset: %d, Data: %lX\n", ii, wOffset+ii, *pdwKey);
+		VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset+ii);
+		VNSvOutPortD(dwIoBase + MAC_REG_MISCFFDATA, *pdwKey++);
+		VNSvOutPortW(dwIoBase + MAC_REG_MISCFFCTL, MISCFFCTL_WRITE);
+	}
+	dwData = *pdwKey;
+	if (uKeyLen == WLAN_WEP104_KEYLEN) {
+		dwData |= 0x80000000;
+	}
+	VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset+3);
+	VNSvOutPortD(dwIoBase + MAC_REG_MISCFFDATA, dwData);
+	VNSvOutPortW(dwIoBase + MAC_REG_MISCFFCTL, MISCFFCTL_WRITE);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "End. wOffset: %d, Data: %lX\n", wOffset+3, dwData);
 }
 
-
 /*
  * Description:
  *      Enable default Key (KeyEntry[10]) by MISCFIFO
@@ -1601,25 +1567,24 @@ int     ii;
  *
  */
 /*
-void MACvEnableDefaultKey (unsigned long dwIoBase, unsigned char byLocalID)
-{
-unsigned short wOffset;
-unsigned long dwData;
+  void MACvEnableDefaultKey(unsigned long dwIoBase, unsigned char byLocalID)
+  {
+  unsigned short wOffset;
+  unsigned long dwData;
 
+  if (byLocalID <= 1)
+  return;
 
-    if (byLocalID <= 1)
-        return;
+  wOffset = MISCFIFO_KEYETRY0;
+  wOffset += (10 * MISCFIFO_KEYENTRYSIZE);
 
-    wOffset = MISCFIFO_KEYETRY0;
-    wOffset += (10 * MISCFIFO_KEYENTRYSIZE);
+  dwData = 0xC0440000;
+  VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset);
+  VNSvOutPortD(dwIoBase + MAC_REG_MISCFFDATA, dwData);
+  VNSvOutPortW(dwIoBase + MAC_REG_MISCFFCTL, MISCFFCTL_WRITE);
+  DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "MACvEnableDefaultKey: wOffset: %d, Data: %lX\n", wOffset, dwData);
 
-    dwData = 0xC0440000;
-    VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset);
-    VNSvOutPortD(dwIoBase + MAC_REG_MISCFFDATA, dwData);
-    VNSvOutPortW(dwIoBase + MAC_REG_MISCFFCTL, MISCFFCTL_WRITE);
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MACvEnableDefaultKey: wOffset: %d, Data: %lX\n", wOffset, dwData);
-
-}
+  }
 */
 
 /*
@@ -1636,20 +1601,19 @@ unsigned long dwData;
  * Return Value: none
  *
  */
-void MACvDisableDefaultKey (unsigned long dwIoBase)
+void MACvDisableDefaultKey(unsigned long dwIoBase)
 {
-unsigned short wOffset;
-unsigned long dwData;
-
+	unsigned short wOffset;
+	unsigned long dwData;
 
-    wOffset = MISCFIFO_KEYETRY0;
-    wOffset += (10 * MISCFIFO_KEYENTRYSIZE);
+	wOffset = MISCFIFO_KEYETRY0;
+	wOffset += (10 * MISCFIFO_KEYENTRYSIZE);
 
-    dwData = 0x0;
-    VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset);
-    VNSvOutPortD(dwIoBase + MAC_REG_MISCFFDATA, dwData);
-    VNSvOutPortW(dwIoBase + MAC_REG_MISCFFCTL, MISCFFCTL_WRITE);
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MACvDisableDefaultKey: wOffset: %d, Data: %lX\n", wOffset, dwData);
+	dwData = 0x0;
+	VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset);
+	VNSvOutPortD(dwIoBase + MAC_REG_MISCFFDATA, dwData);
+	VNSvOutPortW(dwIoBase + MAC_REG_MISCFFCTL, MISCFFCTL_WRITE);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "MACvDisableDefaultKey: wOffset: %d, Data: %lX\n", wOffset, dwData);
 }
 
 /*
@@ -1666,48 +1630,44 @@ unsigned long dwData;
  * Return Value: none
  *
  */
-void MACvSetDefaultTKIPKeyEntry (unsigned long dwIoBase, unsigned int uKeyLen,
-		unsigned int uKeyIdx, unsigned long *pdwKey, unsigned char byLocalID)
+void MACvSetDefaultTKIPKeyEntry(unsigned long dwIoBase, unsigned int uKeyLen,
+				unsigned int uKeyIdx, unsigned long *pdwKey, unsigned char byLocalID)
 {
-unsigned short wOffset;
-unsigned long dwData;
-int     ii;
-
-    if (byLocalID <= 1)
-        return;
-
-
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MACvSetDefaultTKIPKeyEntry\n");
-    wOffset = MISCFIFO_KEYETRY0;
-    // Kyle test : change offset from 10 -> 0
-    wOffset += (10 * MISCFIFO_KEYENTRYSIZE);
-
-    dwData = 0xC0660000;
-    VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset);
-    VNSvOutPortD(dwIoBase + MAC_REG_MISCFFDATA, dwData);
-    VNSvOutPortW(dwIoBase + MAC_REG_MISCFFCTL, MISCFFCTL_WRITE);
-    wOffset++;
-
-    dwData = 0;
-    VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset);
-    VNSvOutPortD(dwIoBase + MAC_REG_MISCFFDATA, dwData);
-    VNSvOutPortW(dwIoBase + MAC_REG_MISCFFCTL, MISCFFCTL_WRITE);
-    wOffset++;
-
-    wOffset += (uKeyIdx * 4);
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"1. wOffset: %d, Data: %lX, idx:%d\n", wOffset, *pdwKey, uKeyIdx);
-    // always push 128 bits
-    for (ii=0; ii<4; ii++) {
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"2.(%d) wOffset: %d, Data: %lX\n", ii, wOffset+ii, *pdwKey);
-        VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset+ii);
-        VNSvOutPortD(dwIoBase + MAC_REG_MISCFFDATA, *pdwKey++);
-        VNSvOutPortW(dwIoBase + MAC_REG_MISCFFCTL, MISCFFCTL_WRITE);
-    }
-
+	unsigned short wOffset;
+	unsigned long dwData;
+	int     ii;
+
+	if (byLocalID <= 1)
+		return;
+
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "MACvSetDefaultTKIPKeyEntry\n");
+	wOffset = MISCFIFO_KEYETRY0;
+	// Kyle test : change offset from 10 -> 0
+	wOffset += (10 * MISCFIFO_KEYENTRYSIZE);
+
+	dwData = 0xC0660000;
+	VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset);
+	VNSvOutPortD(dwIoBase + MAC_REG_MISCFFDATA, dwData);
+	VNSvOutPortW(dwIoBase + MAC_REG_MISCFFCTL, MISCFFCTL_WRITE);
+	wOffset++;
+
+	dwData = 0;
+	VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset);
+	VNSvOutPortD(dwIoBase + MAC_REG_MISCFFDATA, dwData);
+	VNSvOutPortW(dwIoBase + MAC_REG_MISCFFCTL, MISCFFCTL_WRITE);
+	wOffset++;
+
+	wOffset += (uKeyIdx * 4);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "1. wOffset: %d, Data: %lX, idx:%d\n", wOffset, *pdwKey, uKeyIdx);
+	// always push 128 bits
+	for (ii = 0; ii < 4; ii++) {
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "2.(%d) wOffset: %d, Data: %lX\n", ii, wOffset+ii, *pdwKey);
+		VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset+ii);
+		VNSvOutPortD(dwIoBase + MAC_REG_MISCFFDATA, *pdwKey++);
+		VNSvOutPortW(dwIoBase + MAC_REG_MISCFFCTL, MISCFFCTL_WRITE);
+	}
 }
 
-
-
 /*
  * Description:
  *      Set the Key Control by MISCFIFO
@@ -1723,28 +1683,25 @@ int     ii;
  *
  */
 
-void MACvSetDefaultKeyCtl (unsigned long dwIoBase, unsigned short wKeyCtl, unsigned int uEntryIdx, unsigned char byLocalID)
+void MACvSetDefaultKeyCtl(unsigned long dwIoBase, unsigned short wKeyCtl, unsigned int uEntryIdx, unsigned char byLocalID)
 {
-unsigned short wOffset;
-unsigned long dwData;
-
-    if (byLocalID <= 1)
-        return;
+	unsigned short wOffset;
+	unsigned long dwData;
 
+	if (byLocalID <= 1)
+		return;
 
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MACvSetKeyEntry\n");
-    wOffset = MISCFIFO_KEYETRY0;
-    wOffset += (uEntryIdx * MISCFIFO_KEYENTRYSIZE);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "MACvSetKeyEntry\n");
+	wOffset = MISCFIFO_KEYETRY0;
+	wOffset += (uEntryIdx * MISCFIFO_KEYENTRYSIZE);
 
-    dwData = 0;
-    dwData |= wKeyCtl;
-    dwData <<= 16;
-    dwData |= 0xffff;
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"1. wOffset: %d, Data: %lX, KeyCtl:%X\n", wOffset, dwData, wKeyCtl);
-
-    VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset);
-    VNSvOutPortD(dwIoBase + MAC_REG_MISCFFDATA, dwData);
-    VNSvOutPortW(dwIoBase + MAC_REG_MISCFFCTL, MISCFFCTL_WRITE);
+	dwData = 0;
+	dwData |= wKeyCtl;
+	dwData <<= 16;
+	dwData |= 0xffff;
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "1. wOffset: %d, Data: %lX, KeyCtl:%X\n", wOffset, dwData, wKeyCtl);
 
+	VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset);
+	VNSvOutPortD(dwIoBase + MAC_REG_MISCFFDATA, dwData);
+	VNSvOutPortW(dwIoBase + MAC_REG_MISCFFCTL, MISCFFCTL_WRITE);
 }
-
diff --git a/drivers/staging/vt6655/mac.h b/drivers/staging/vt6655/mac.h
index adfb366..3f177f7 100644
--- a/drivers/staging/vt6655/mac.h
+++ b/drivers/staging/vt6655/mac.h
@@ -197,7 +197,6 @@
 #define MAC_REG_PWRCCK      0x73
 #define MAC_REG_PWROFDM     0x7C
 
-
 //
 // Bits in the BCFG0 register
 //
@@ -398,7 +397,6 @@
 #define IMR_AC0DMA          0x00000002      //
 #define IMR_TXDMA0          0x00000001      //
 
-
 //
 // Bits in the ISR register
 //
@@ -422,7 +420,6 @@
 #define ISR_AC0DMA          0x00000002      //
 #define ISR_TXDMA0          0x00000001      //
 
-
 //
 // Bits in the PSCFG register
 //
@@ -513,7 +510,6 @@
 //
 #define MISCFFCTL_WRITE     0x0001      //
 
-
 //
 // Bits in WAKEUPEN0
 //
@@ -557,7 +553,6 @@
 #define GPIO1_MD            0x10        //
 #define GPIO1_DATA          0x20        //
 
-
 //
 // Bits in the MSRCTL register
 //
@@ -576,7 +571,6 @@
 #define MSRCTL1_CSAPAREN    0x04
 #define MSRCTL1_TXPAUSE     0x01
 
-
 // Loopback mode
 #define MAC_LB_EXT          0x02        //
 #define MAC_LB_INTERNAL     0x01        //
@@ -595,7 +589,6 @@
 
 #define Default_BI              0x200
 
-
 // MiscFIFO Offset
 #define MISCFIFO_KEYETRY0       32
 #define MISCFIFO_KEYENTRYSIZE   22
@@ -604,20 +597,20 @@
 #define MISCFIFO_SYNDATASIZE    21
 
 // enabled mask value of irq
-#define IMR_MASK_VALUE     (IMR_SOFTTIMER1 | \
-                            IMR_RXDMA1 | \
-                            IMR_RXNOBUF | \
-                            IMR_MIBNEARFULL | \
-                            IMR_SOFTINT | \
-                            IMR_FETALERR | \
-                            IMR_WATCHDOG | \
-                            IMR_SOFTTIMER | \
-                            IMR_GPIO | \
-                            IMR_TBTT | \
-                            IMR_RXDMA0 | \
-                            IMR_BNTX | \
-                            IMR_AC0DMA | \
-                            IMR_TXDMA0)
+#define IMR_MASK_VALUE     (IMR_SOFTTIMER1 |	\
+			    IMR_RXDMA1 |	\
+			    IMR_RXNOBUF |	\
+			    IMR_MIBNEARFULL |	\
+			    IMR_SOFTINT |	\
+			    IMR_FETALERR |	\
+			    IMR_WATCHDOG |	\
+			    IMR_SOFTTIMER |	\
+			    IMR_GPIO |		\
+			    IMR_TBTT |		\
+			    IMR_RXDMA0 |	\
+			    IMR_BNTX |		\
+			    IMR_AC0DMA |	\
+			    IMR_TXDMA0)
 
 // max time out delay time
 #define W_MAX_TIMEOUT       0xFFF0U     //
@@ -637,412 +630,341 @@
 
 /*---------------------  Export Macros ------------------------------*/
 
-#define MACvRegBitsOn(dwIoBase, byRegOfs, byBits)           \
-{                                                           \
-    unsigned char byData;                                   \
-    VNSvInPortB(dwIoBase + byRegOfs, &byData);              \
-    VNSvOutPortB(dwIoBase + byRegOfs, byData | (byBits));   \
-}
-
-#define MACvWordRegBitsOn(dwIoBase, byRegOfs, wBits)        \
-{                                                           \
-    unsigned short wData;                                   \
-    VNSvInPortW(dwIoBase + byRegOfs, &wData);               \
-    VNSvOutPortW(dwIoBase + byRegOfs, wData | (wBits));     \
-}
-
-#define MACvDWordRegBitsOn(dwIoBase, byRegOfs, dwBits)      \
-{                                                           \
-    unsigned long dwData;                                   \
-    VNSvInPortD(dwIoBase + byRegOfs, &dwData);              \
-    VNSvOutPortD(dwIoBase + byRegOfs, dwData | (dwBits));   \
-}
-
-#define MACvRegBitsOnEx(dwIoBase, byRegOfs, byMask, byBits) \
-{                                                           \
-    unsigned char byData;                                   \
-    VNSvInPortB(dwIoBase + byRegOfs, &byData);              \
-    byData &= byMask;                                       \
-    VNSvOutPortB(dwIoBase + byRegOfs, byData | (byBits));   \
-}
-
-#define MACvRegBitsOff(dwIoBase, byRegOfs, byBits)          \
-{                                                           \
-    unsigned char byData;                                   \
-    VNSvInPortB(dwIoBase + byRegOfs, &byData);              \
-    VNSvOutPortB(dwIoBase + byRegOfs, byData & ~(byBits));  \
-}
-
-#define MACvWordRegBitsOff(dwIoBase, byRegOfs, wBits)       \
-{                                                           \
-    unsigned short wData;                                   \
-    VNSvInPortW(dwIoBase + byRegOfs, &wData);               \
-    VNSvOutPortW(dwIoBase + byRegOfs, wData & ~(wBits));    \
-}
-
-#define MACvDWordRegBitsOff(dwIoBase, byRegOfs, dwBits)     \
-{                                                           \
-    unsigned long dwData;                                   \
-    VNSvInPortD(dwIoBase + byRegOfs, &dwData);              \
-    VNSvOutPortD(dwIoBase + byRegOfs, dwData & ~(dwBits));  \
-}
-
-#define MACvGetCurrRx0DescAddr(dwIoBase, pdwCurrDescAddr)    \
-{                                                           \
-    VNSvInPortD(dwIoBase + MAC_REG_RXDMAPTR0,               \
-                (unsigned long *)pdwCurrDescAddr);          \
-}
-
-#define MACvGetCurrRx1DescAddr(dwIoBase, pdwCurrDescAddr)   \
-{                                                           \
-    VNSvInPortD(dwIoBase + MAC_REG_RXDMAPTR1,               \
-                (unsigned long *)pdwCurrDescAddr);          \
-}
-
-#define MACvGetCurrTx0DescAddr(dwIoBase, pdwCurrDescAddr)   \
-{                                                           \
-    VNSvInPortD(dwIoBase + MAC_REG_TXDMAPTR0,               \
-                (unsigned long *)pdwCurrDescAddr);          \
-}
-
-#define MACvGetCurrAC0DescAddr(dwIoBase, pdwCurrDescAddr)   \
-{                                                           \
-    VNSvInPortD(dwIoBase + MAC_REG_AC0DMAPTR,               \
-                (unsigned long *)pdwCurrDescAddr);          \
-}
-
-#define MACvGetCurrSyncDescAddr(dwIoBase, pdwCurrDescAddr)  \
-{                                                           \
-    VNSvInPortD(dwIoBase + MAC_REG_SYNCDMAPTR,              \
-                (unsigned long *)pdwCurrDescAddr);          \
-}
-
-#define MACvGetCurrATIMDescAddr(dwIoBase, pdwCurrDescAddr)  \
-{                                                           \
-    VNSvInPortD(dwIoBase + MAC_REG_ATIMDMAPTR,              \
-                (unsigned long *)pdwCurrDescAddr);          \
-}                                                           \
+#define MACvRegBitsOn(dwIoBase, byRegOfs, byBits)			\
+do {									\
+	unsigned char byData;						\
+	VNSvInPortB(dwIoBase + byRegOfs, &byData);			\
+	VNSvOutPortB(dwIoBase + byRegOfs, byData | (byBits));		\
+} while (0)
+
+#define MACvWordRegBitsOn(dwIoBase, byRegOfs, wBits)			\
+do {									\
+	unsigned short wData;						\
+	VNSvInPortW(dwIoBase + byRegOfs, &wData);			\
+	VNSvOutPortW(dwIoBase + byRegOfs, wData | (wBits));		\
+} while (0)
+
+#define MACvDWordRegBitsOn(dwIoBase, byRegOfs, dwBits)			\
+do {									\
+	unsigned long dwData;						\
+	VNSvInPortD(dwIoBase + byRegOfs, &dwData);			\
+	VNSvOutPortD(dwIoBase + byRegOfs, dwData | (dwBits));		\
+} while (0)
+
+#define MACvRegBitsOnEx(dwIoBase, byRegOfs, byMask, byBits)		\
+do {									\
+	unsigned char byData;						\
+	VNSvInPortB(dwIoBase + byRegOfs, &byData);			\
+	byData &= byMask;						\
+	VNSvOutPortB(dwIoBase + byRegOfs, byData | (byBits));		\
+} while (0)
+
+#define MACvRegBitsOff(dwIoBase, byRegOfs, byBits)			\
+do {									\
+	unsigned char byData;						\
+	VNSvInPortB(dwIoBase + byRegOfs, &byData);			\
+	VNSvOutPortB(dwIoBase + byRegOfs, byData & ~(byBits));		\
+} while (0)
+
+#define MACvWordRegBitsOff(dwIoBase, byRegOfs, wBits)			\
+do {									\
+	unsigned short wData;						\
+	VNSvInPortW(dwIoBase + byRegOfs, &wData);			\
+	VNSvOutPortW(dwIoBase + byRegOfs, wData & ~(wBits));		\
+} while (0)
+
+#define MACvDWordRegBitsOff(dwIoBase, byRegOfs, dwBits)			\
+do {									\
+	unsigned long dwData;						\
+	VNSvInPortD(dwIoBase + byRegOfs, &dwData);			\
+	VNSvOutPortD(dwIoBase + byRegOfs, dwData & ~(dwBits));		\
+} while (0)
+
+#define MACvGetCurrRx0DescAddr(dwIoBase, pdwCurrDescAddr)	\
+	VNSvInPortD(dwIoBase + MAC_REG_RXDMAPTR0,		\
+		    (unsigned long *)pdwCurrDescAddr)
+
+#define MACvGetCurrRx1DescAddr(dwIoBase, pdwCurrDescAddr)	\
+	VNSvInPortD(dwIoBase + MAC_REG_RXDMAPTR1,		\
+		    (unsigned long *)pdwCurrDescAddr)
+
+#define MACvGetCurrTx0DescAddr(dwIoBase, pdwCurrDescAddr)	\
+	VNSvInPortD(dwIoBase + MAC_REG_TXDMAPTR0,		\
+		    (unsigned long *)pdwCurrDescAddr)
+
+#define MACvGetCurrAC0DescAddr(dwIoBase, pdwCurrDescAddr)	\
+	VNSvInPortD(dwIoBase + MAC_REG_AC0DMAPTR,		\
+		    (unsigned long *)pdwCurrDescAddr)
+
+#define MACvGetCurrSyncDescAddr(dwIoBase, pdwCurrDescAddr)	\
+	VNSvInPortD(dwIoBase + MAC_REG_SYNCDMAPTR,		\
+		    (unsigned long *)pdwCurrDescAddr)
+
+#define MACvGetCurrATIMDescAddr(dwIoBase, pdwCurrDescAddr)	\
+	VNSvInPortD(dwIoBase + MAC_REG_ATIMDMAPTR,		\
+		    (unsigned long *)pdwCurrDescAddr)
 
 // set the chip with current BCN tx descriptor address
-#define MACvSetCurrBCNTxDescAddr(dwIoBase, dwCurrDescAddr)  \
-{                                                           \
-    VNSvOutPortD(dwIoBase + MAC_REG_BCNDMAPTR,              \
-                 dwCurrDescAddr);                           \
-}
+#define MACvSetCurrBCNTxDescAddr(dwIoBase, dwCurrDescAddr)	\
+	VNSvOutPortD(dwIoBase + MAC_REG_BCNDMAPTR,		\
+		     dwCurrDescAddr)
 
 // set the chip with current BCN length
-#define MACvSetCurrBCNLength(dwIoBase, wCurrBCNLength)     \
-{                                                          \
-    VNSvOutPortW(dwIoBase + MAC_REG_BCNDMACTL+2,           \
-                 wCurrBCNLength);                          \
-}
-
-#define MACvReadBSSIDAddress(dwIoBase, pbyEtherAddr)        \
-{                                                           \
-    VNSvOutPortB(dwIoBase + MAC_REG_PAGE1SEL, 1);           \
-    VNSvInPortB(dwIoBase + MAC_REG_BSSID0,                  \
-                (unsigned char *)pbyEtherAddr);             \
-    VNSvInPortB(dwIoBase + MAC_REG_BSSID0 + 1,              \
-                pbyEtherAddr + 1);                          \
-    VNSvInPortB(dwIoBase + MAC_REG_BSSID0 + 2,              \
-                pbyEtherAddr + 2);                          \
-    VNSvInPortB(dwIoBase + MAC_REG_BSSID0 + 3,              \
-                pbyEtherAddr + 3);                          \
-    VNSvInPortB(dwIoBase + MAC_REG_BSSID0 + 4,              \
-                pbyEtherAddr + 4);                          \
-    VNSvInPortB(dwIoBase + MAC_REG_BSSID0 + 5,              \
-                pbyEtherAddr + 5);                          \
-    VNSvOutPortB(dwIoBase + MAC_REG_PAGE1SEL, 0);           \
-}
-
-#define MACvWriteBSSIDAddress(dwIoBase, pbyEtherAddr)       \
-{                                                           \
-    VNSvOutPortB(dwIoBase + MAC_REG_PAGE1SEL, 1);           \
-    VNSvOutPortB(dwIoBase + MAC_REG_BSSID0,                 \
-                *(pbyEtherAddr));                           \
-    VNSvOutPortB(dwIoBase + MAC_REG_BSSID0 + 1,             \
-                *(pbyEtherAddr + 1));                       \
-    VNSvOutPortB(dwIoBase + MAC_REG_BSSID0 + 2,             \
-                *(pbyEtherAddr + 2));                       \
-    VNSvOutPortB(dwIoBase + MAC_REG_BSSID0 + 3,             \
-                *(pbyEtherAddr + 3));                       \
-    VNSvOutPortB(dwIoBase + MAC_REG_BSSID0 + 4,             \
-                *(pbyEtherAddr + 4));                       \
-    VNSvOutPortB(dwIoBase + MAC_REG_BSSID0 + 5,             \
-                *(pbyEtherAddr + 5));                       \
-    VNSvOutPortB(dwIoBase + MAC_REG_PAGE1SEL, 0);           \
-}
-
-#define MACvReadEtherAddress(dwIoBase, pbyEtherAddr)        \
-{                                                           \
-    VNSvOutPortB(dwIoBase + MAC_REG_PAGE1SEL, 1);           \
-    VNSvInPortB(dwIoBase + MAC_REG_PAR0,                    \
-                (unsigned char *)pbyEtherAddr);             \
-    VNSvInPortB(dwIoBase + MAC_REG_PAR0 + 1,                \
-                pbyEtherAddr + 1);                          \
-    VNSvInPortB(dwIoBase + MAC_REG_PAR0 + 2,                \
-                pbyEtherAddr + 2);                          \
-    VNSvInPortB(dwIoBase + MAC_REG_PAR0 + 3,                \
-                pbyEtherAddr + 3);                          \
-    VNSvInPortB(dwIoBase + MAC_REG_PAR0 + 4,                \
-                pbyEtherAddr + 4);                          \
-    VNSvInPortB(dwIoBase + MAC_REG_PAR0 + 5,                \
-                pbyEtherAddr + 5);                          \
-    VNSvOutPortB(dwIoBase + MAC_REG_PAGE1SEL, 0);           \
-}
-
-
-#define MACvWriteEtherAddress(dwIoBase, pbyEtherAddr)       \
-{                                                           \
-    VNSvOutPortB(dwIoBase + MAC_REG_PAGE1SEL, 1);           \
-    VNSvOutPortB(dwIoBase + MAC_REG_PAR0,                   \
-                *pbyEtherAddr);                             \
-    VNSvOutPortB(dwIoBase + MAC_REG_PAR0 + 1,               \
-                *(pbyEtherAddr + 1));                       \
-    VNSvOutPortB(dwIoBase + MAC_REG_PAR0 + 2,               \
-                *(pbyEtherAddr + 2));                       \
-    VNSvOutPortB(dwIoBase + MAC_REG_PAR0 + 3,               \
-                *(pbyEtherAddr + 3));                       \
-    VNSvOutPortB(dwIoBase + MAC_REG_PAR0 + 4,               \
-                *(pbyEtherAddr + 4));                       \
-    VNSvOutPortB(dwIoBase + MAC_REG_PAR0 + 5,               \
-                *(pbyEtherAddr + 5));                       \
-    VNSvOutPortB(dwIoBase + MAC_REG_PAGE1SEL, 0);           \
-}
-
-
-#define MACvClearISR(dwIoBase)                              \
-{                                                           \
-    VNSvOutPortD(dwIoBase + MAC_REG_ISR, IMR_MASK_VALUE);   \
-}
-
-#define MACvStart(dwIoBase)                                      \
-{                                                                \
-    VNSvOutPortB(dwIoBase + MAC_REG_HOSTCR,                      \
-                    (HOSTCR_MACEN | HOSTCR_RXON | HOSTCR_TXON)); \
-}
-
-#define MACvRx0PerPktMode(dwIoBase)                         \
-{                                                           \
-    VNSvOutPortD(dwIoBase + MAC_REG_RXDMACTL0, RX_PERPKT);  \
-}
-
-#define MACvRx0BufferFillMode(dwIoBase)                         \
-{                                                               \
-    VNSvOutPortD(dwIoBase + MAC_REG_RXDMACTL0, RX_PERPKTCLR);   \
-}
-
-#define MACvRx1PerPktMode(dwIoBase)                         \
-{                                                           \
-    VNSvOutPortD(dwIoBase + MAC_REG_RXDMACTL1, RX_PERPKT);  \
-}
-
-#define MACvRx1BufferFillMode(dwIoBase)                         \
-{                                                               \
-    VNSvOutPortD(dwIoBase + MAC_REG_RXDMACTL1, RX_PERPKTCLR);   \
-}
-
-#define MACvRxOn(dwIoBase)                                      \
-{                                                               \
-    MACvRegBitsOn(dwIoBase, MAC_REG_HOSTCR, HOSTCR_RXON);       \
-}
-
-#define MACvReceive0(dwIoBase)                                  \
-{                                                               \
-    unsigned long dwData;                                       \
-    VNSvInPortD(dwIoBase + MAC_REG_RXDMACTL0, &dwData);         \
-    if (dwData & DMACTL_RUN) {                                  \
-        VNSvOutPortD(dwIoBase + MAC_REG_RXDMACTL0, DMACTL_WAKE);\
-    }                                                           \
-    else {                                                      \
-        VNSvOutPortD(dwIoBase + MAC_REG_RXDMACTL0, DMACTL_RUN); \
-    }                                                           \
-}
-
-#define MACvReceive1(dwIoBase)                                  \
-{                                                               \
-    unsigned long dwData;                                       \
-    VNSvInPortD(dwIoBase + MAC_REG_RXDMACTL1, &dwData);         \
-    if (dwData & DMACTL_RUN) {                                  \
-        VNSvOutPortD(dwIoBase + MAC_REG_RXDMACTL1, DMACTL_WAKE);\
-    }                                                           \
-    else {                                                      \
-        VNSvOutPortD(dwIoBase + MAC_REG_RXDMACTL1, DMACTL_RUN); \
-    }                                                           \
-}
-
-#define MACvTxOn(dwIoBase)                                      \
-{                                                               \
-    MACvRegBitsOn(dwIoBase, MAC_REG_HOSTCR, HOSTCR_TXON);       \
-}
-
-#define MACvTransmit0(dwIoBase)                                 \
-{                                                               \
-    unsigned long dwData;                                       \
-    VNSvInPortD(dwIoBase + MAC_REG_TXDMACTL0, &dwData);         \
-    if (dwData & DMACTL_RUN) {                                  \
-        VNSvOutPortD(dwIoBase + MAC_REG_TXDMACTL0, DMACTL_WAKE);\
-    }                                                           \
-    else {                                                      \
-        VNSvOutPortD(dwIoBase + MAC_REG_TXDMACTL0, DMACTL_RUN); \
-    }                                                           \
-}
-
-#define MACvTransmitAC0(dwIoBase)                               \
-{                                                               \
-    unsigned long dwData;                                       \
-    VNSvInPortD(dwIoBase + MAC_REG_AC0DMACTL, &dwData);         \
-    if (dwData & DMACTL_RUN) {                                  \
-        VNSvOutPortD(dwIoBase + MAC_REG_AC0DMACTL, DMACTL_WAKE);\
-    }                                                           \
-    else {                                                      \
-        VNSvOutPortD(dwIoBase + MAC_REG_AC0DMACTL, DMACTL_RUN); \
-    }                                                           \
-}
-
-#define MACvTransmitSYNC(dwIoBase)                               \
-{                                                                \
-    unsigned long dwData;                                        \
-    VNSvInPortD(dwIoBase + MAC_REG_SYNCDMACTL, &dwData);         \
-    if (dwData & DMACTL_RUN) {                                   \
-        VNSvOutPortD(dwIoBase + MAC_REG_SYNCDMACTL, DMACTL_WAKE);\
-    }                                                            \
-    else {                                                       \
-        VNSvOutPortD(dwIoBase + MAC_REG_SYNCDMACTL, DMACTL_RUN); \
-    }                                                            \
-}
-
-#define MACvTransmitATIM(dwIoBase)                               \
-{                                                                \
-    unsigned long dwData;                                        \
-    VNSvInPortD(dwIoBase + MAC_REG_ATIMDMACTL, &dwData);         \
-    if (dwData & DMACTL_RUN) {                                   \
-        VNSvOutPortD(dwIoBase + MAC_REG_ATIMDMACTL, DMACTL_WAKE);\
-    }                                                            \
-    else {                                                       \
-        VNSvOutPortD(dwIoBase + MAC_REG_ATIMDMACTL, DMACTL_RUN); \
-    }                                                            \
-}
-
-#define MACvTransmitBCN(dwIoBase)                               \
-{                                                               \
-    VNSvOutPortB(dwIoBase + MAC_REG_BCNDMACTL, BEACON_READY);   \
-}
-
-#define MACvClearStckDS(dwIoBase)                           \
-{                                                           \
-    unsigned char byOrgValue;                               \
-    VNSvInPortB(dwIoBase + MAC_REG_STICKHW, &byOrgValue);   \
-    byOrgValue = byOrgValue & 0xFC;                         \
-    VNSvOutPortB(dwIoBase + MAC_REG_STICKHW, byOrgValue);   \
-}
-
-#define MACvReadISR(dwIoBase, pdwValue)             \
-{                                                   \
-    VNSvInPortD(dwIoBase + MAC_REG_ISR, pdwValue);  \
-}
-
-#define MACvWriteISR(dwIoBase, dwValue)             \
-{                                                   \
-    VNSvOutPortD(dwIoBase + MAC_REG_ISR, dwValue);  \
-}
-
-#define MACvIntEnable(dwIoBase, dwMask)             \
-{                                                   \
-    VNSvOutPortD(dwIoBase + MAC_REG_IMR, dwMask);   \
-}
-
-#define MACvIntDisable(dwIoBase)                    \
-{                                                   \
-    VNSvOutPortD(dwIoBase + MAC_REG_IMR, 0);        \
-}
-
-#define MACvSelectPage0(dwIoBase)                   \
-{                                                   \
-    VNSvOutPortB(dwIoBase + MAC_REG_PAGE1SEL, 0);   \
-}
-#define MACvSelectPage1(dwIoBase)                   \
-{                                                   \
-    VNSvOutPortB(dwIoBase + MAC_REG_PAGE1SEL, 1);   \
-}
-
-#define MACvReadMIBCounter(dwIoBase, pdwCounter)            \
-{                                                           \
-    VNSvInPortD(dwIoBase + MAC_REG_MIBCNTR , pdwCounter);   \
-}
-
-#define MACvPwrEvntDisable(dwIoBase)                    \
-{                                                       \
-    VNSvOutPortW(dwIoBase + MAC_REG_WAKEUPEN0, 0x0000); \
-}
-
-#define MACvEnableProtectMD(dwIoBase)                    \
-{                                                        \
-    unsigned long dwOrgValue;                            \
-    VNSvInPortD(dwIoBase + MAC_REG_ENCFG , &dwOrgValue); \
-    dwOrgValue = dwOrgValue | EnCFG_ProtectMd;           \
-    VNSvOutPortD(dwIoBase + MAC_REG_ENCFG, dwOrgValue);  \
-}
-
-#define MACvDisableProtectMD(dwIoBase)                   \
-{                                                        \
-    unsigned long dwOrgValue;                            \
-    VNSvInPortD(dwIoBase + MAC_REG_ENCFG , &dwOrgValue); \
-    dwOrgValue = dwOrgValue & ~EnCFG_ProtectMd;          \
-    VNSvOutPortD(dwIoBase + MAC_REG_ENCFG, dwOrgValue);  \
-}
-
-#define MACvEnableBarkerPreambleMd(dwIoBase)             \
-{                                                        \
-    unsigned long dwOrgValue;                            \
-    VNSvInPortD(dwIoBase + MAC_REG_ENCFG , &dwOrgValue); \
-    dwOrgValue = dwOrgValue | EnCFG_BarkerPream;         \
-    VNSvOutPortD(dwIoBase + MAC_REG_ENCFG, dwOrgValue);  \
-}
-
-#define MACvDisableBarkerPreambleMd(dwIoBase)            \
-{                                                        \
-    unsigned long dwOrgValue;                            \
-    VNSvInPortD(dwIoBase + MAC_REG_ENCFG , &dwOrgValue); \
-    dwOrgValue = dwOrgValue & ~EnCFG_BarkerPream;        \
-    VNSvOutPortD(dwIoBase + MAC_REG_ENCFG, dwOrgValue);  \
-}
-
-#define MACvSetBBType(dwIoBase, byTyp)                   \
-{                                                        \
-    unsigned long dwOrgValue;                            \
-    VNSvInPortD(dwIoBase + MAC_REG_ENCFG , &dwOrgValue); \
-    dwOrgValue = dwOrgValue & ~EnCFG_BBType_MASK;        \
-    dwOrgValue = dwOrgValue | (unsigned long) byTyp;     \
-    VNSvOutPortD(dwIoBase + MAC_REG_ENCFG, dwOrgValue);  \
-}
-
-#define MACvReadATIMW(dwIoBase, pwCounter)                 \
-{                                                          \
-    VNSvInPortW(dwIoBase + MAC_REG_AIDATIM , pwCounter);   \
-}
-
-#define MACvWriteATIMW(dwIoBase, wCounter)                 \
-{                                                          \
-    VNSvOutPortW(dwIoBase + MAC_REG_AIDATIM , wCounter);   \
-}
-
-#define MACvWriteCRC16_128(dwIoBase, byRegOfs, wCRC)       \
-{                                                          \
-    VNSvOutPortB(dwIoBase + MAC_REG_PAGE1SEL, 1);          \
-    VNSvOutPortW(dwIoBase + byRegOfs, wCRC);               \
-    VNSvOutPortB(dwIoBase + MAC_REG_PAGE1SEL, 0);          \
-}
-
-#define MACvGPIOIn(dwIoBase, pbyValue)                      \
-{                                                           \
-    VNSvInPortB(dwIoBase + MAC_REG_GPIOCTL1, pbyValue);     \
-}
+#define MACvSetCurrBCNLength(dwIoBase, wCurrBCNLength)		\
+	VNSvOutPortW(dwIoBase + MAC_REG_BCNDMACTL+2,		\
+		     wCurrBCNLength)
+
+#define MACvReadBSSIDAddress(dwIoBase, pbyEtherAddr)		\
+do {								\
+	VNSvOutPortB(dwIoBase + MAC_REG_PAGE1SEL, 1);		\
+	VNSvInPortB(dwIoBase + MAC_REG_BSSID0,			\
+		    (unsigned char *)pbyEtherAddr);		\
+	VNSvInPortB(dwIoBase + MAC_REG_BSSID0 + 1,		\
+		    pbyEtherAddr + 1);				\
+	VNSvInPortB(dwIoBase + MAC_REG_BSSID0 + 2,		\
+		    pbyEtherAddr + 2);				\
+	VNSvInPortB(dwIoBase + MAC_REG_BSSID0 + 3,		\
+		    pbyEtherAddr + 3);				\
+	VNSvInPortB(dwIoBase + MAC_REG_BSSID0 + 4,		\
+		    pbyEtherAddr + 4);				\
+	VNSvInPortB(dwIoBase + MAC_REG_BSSID0 + 5,		\
+		    pbyEtherAddr + 5);				\
+	VNSvOutPortB(dwIoBase + MAC_REG_PAGE1SEL, 0);		\
+} while (0)
+
+#define MACvWriteBSSIDAddress(dwIoBase, pbyEtherAddr)		\
+do {								\
+	VNSvOutPortB(dwIoBase + MAC_REG_PAGE1SEL, 1);		\
+	VNSvOutPortB(dwIoBase + MAC_REG_BSSID0,			\
+		     *(pbyEtherAddr));				\
+	VNSvOutPortB(dwIoBase + MAC_REG_BSSID0 + 1,		\
+		     *(pbyEtherAddr + 1));			\
+	VNSvOutPortB(dwIoBase + MAC_REG_BSSID0 + 2,		\
+		     *(pbyEtherAddr + 2));			\
+	VNSvOutPortB(dwIoBase + MAC_REG_BSSID0 + 3,		\
+		     *(pbyEtherAddr + 3));			\
+	VNSvOutPortB(dwIoBase + MAC_REG_BSSID0 + 4,		\
+		     *(pbyEtherAddr + 4));			\
+	VNSvOutPortB(dwIoBase + MAC_REG_BSSID0 + 5,		\
+		     *(pbyEtherAddr + 5));			\
+	VNSvOutPortB(dwIoBase + MAC_REG_PAGE1SEL, 0);		\
+} while (0)
+
+#define MACvReadEtherAddress(dwIoBase, pbyEtherAddr)		\
+do {								\
+	VNSvOutPortB(dwIoBase + MAC_REG_PAGE1SEL, 1);		\
+	VNSvInPortB(dwIoBase + MAC_REG_PAR0,			\
+		    (unsigned char *)pbyEtherAddr);		\
+	VNSvInPortB(dwIoBase + MAC_REG_PAR0 + 1,		\
+		    pbyEtherAddr + 1);				\
+	VNSvInPortB(dwIoBase + MAC_REG_PAR0 + 2,		\
+		    pbyEtherAddr + 2);				\
+	VNSvInPortB(dwIoBase + MAC_REG_PAR0 + 3,		\
+		    pbyEtherAddr + 3);				\
+	VNSvInPortB(dwIoBase + MAC_REG_PAR0 + 4,		\
+		    pbyEtherAddr + 4);				\
+	VNSvInPortB(dwIoBase + MAC_REG_PAR0 + 5,		\
+		    pbyEtherAddr + 5);				\
+	VNSvOutPortB(dwIoBase + MAC_REG_PAGE1SEL, 0);		\
+} while (0)
+
+#define MACvWriteEtherAddress(dwIoBase, pbyEtherAddr)		\
+do {								\
+	VNSvOutPortB(dwIoBase + MAC_REG_PAGE1SEL, 1);		\
+	VNSvOutPortB(dwIoBase + MAC_REG_PAR0,			\
+		     *pbyEtherAddr);				\
+	VNSvOutPortB(dwIoBase + MAC_REG_PAR0 + 1,		\
+		     *(pbyEtherAddr + 1));			\
+	VNSvOutPortB(dwIoBase + MAC_REG_PAR0 + 2,		\
+		     *(pbyEtherAddr + 2));			\
+	VNSvOutPortB(dwIoBase + MAC_REG_PAR0 + 3,		\
+		     *(pbyEtherAddr + 3));			\
+	VNSvOutPortB(dwIoBase + MAC_REG_PAR0 + 4,		\
+		     *(pbyEtherAddr + 4));			\
+	VNSvOutPortB(dwIoBase + MAC_REG_PAR0 + 5,		\
+		     *(pbyEtherAddr + 5));			\
+	VNSvOutPortB(dwIoBase + MAC_REG_PAGE1SEL, 0);		\
+} while (0)
+
+#define MACvClearISR(dwIoBase)						\
+	VNSvOutPortD(dwIoBase + MAC_REG_ISR, IMR_MASK_VALUE)
+
+#define MACvStart(dwIoBase)						\
+	VNSvOutPortB(dwIoBase + MAC_REG_HOSTCR,				\
+		     (HOSTCR_MACEN | HOSTCR_RXON | HOSTCR_TXON))
+
+#define MACvRx0PerPktMode(dwIoBase)					\
+	VNSvOutPortD(dwIoBase + MAC_REG_RXDMACTL0, RX_PERPKT)
+
+#define MACvRx0BufferFillMode(dwIoBase)					\
+	VNSvOutPortD(dwIoBase + MAC_REG_RXDMACTL0, RX_PERPKTCLR)
+
+#define MACvRx1PerPktMode(dwIoBase)					\
+	VNSvOutPortD(dwIoBase + MAC_REG_RXDMACTL1, RX_PERPKT)
+
+#define MACvRx1BufferFillMode(dwIoBase)					\
+	VNSvOutPortD(dwIoBase + MAC_REG_RXDMACTL1, RX_PERPKTCLR)
+
+#define MACvRxOn(dwIoBase)						\
+	MACvRegBitsOn(dwIoBase, MAC_REG_HOSTCR, HOSTCR_RXON)
+
+#define MACvReceive0(dwIoBase)						\
+do {									\
+	unsigned long dwData;						\
+	VNSvInPortD(dwIoBase + MAC_REG_RXDMACTL0, &dwData);		\
+	if (dwData & DMACTL_RUN)					\
+		VNSvOutPortD(dwIoBase + MAC_REG_RXDMACTL0, DMACTL_WAKE); \
+	else								\
+		VNSvOutPortD(dwIoBase + MAC_REG_RXDMACTL0, DMACTL_RUN); \
+} while (0)
+
+#define MACvReceive1(dwIoBase)						\
+do {									\
+	unsigned long dwData;						\
+	VNSvInPortD(dwIoBase + MAC_REG_RXDMACTL1, &dwData);		\
+	if (dwData & DMACTL_RUN)					\
+		VNSvOutPortD(dwIoBase + MAC_REG_RXDMACTL1, DMACTL_WAKE); \
+	else								\
+		VNSvOutPortD(dwIoBase + MAC_REG_RXDMACTL1, DMACTL_RUN); \
+} while (0)
+
+#define MACvTxOn(dwIoBase)						\
+	MACvRegBitsOn(dwIoBase, MAC_REG_HOSTCR, HOSTCR_TXON)
+
+#define MACvTransmit0(dwIoBase)						\
+do {									\
+	unsigned long dwData;						\
+	VNSvInPortD(dwIoBase + MAC_REG_TXDMACTL0, &dwData);		\
+	if (dwData & DMACTL_RUN)					\
+		VNSvOutPortD(dwIoBase + MAC_REG_TXDMACTL0, DMACTL_WAKE); \
+	else								\
+		VNSvOutPortD(dwIoBase + MAC_REG_TXDMACTL0, DMACTL_RUN); \
+} while (0)
+
+#define MACvTransmitAC0(dwIoBase)					\
+do {									\
+	unsigned long dwData;						\
+	VNSvInPortD(dwIoBase + MAC_REG_AC0DMACTL, &dwData);		\
+	if (dwData & DMACTL_RUN)					\
+		VNSvOutPortD(dwIoBase + MAC_REG_AC0DMACTL, DMACTL_WAKE); \
+	else								\
+		VNSvOutPortD(dwIoBase + MAC_REG_AC0DMACTL, DMACTL_RUN); \
+} while (0)
+
+#define MACvTransmitSYNC(dwIoBase)					\
+do {									\
+	unsigned long dwData;						\
+	VNSvInPortD(dwIoBase + MAC_REG_SYNCDMACTL, &dwData);		\
+	if (dwData & DMACTL_RUN)					\
+		VNSvOutPortD(dwIoBase + MAC_REG_SYNCDMACTL, DMACTL_WAKE); \
+	else								\
+		VNSvOutPortD(dwIoBase + MAC_REG_SYNCDMACTL, DMACTL_RUN); \
+} while (0)
+
+#define MACvTransmitATIM(dwIoBase)					\
+do {									\
+	unsigned long dwData;						\
+	VNSvInPortD(dwIoBase + MAC_REG_ATIMDMACTL, &dwData);		\
+	if (dwData & DMACTL_RUN)					\
+		VNSvOutPortD(dwIoBase + MAC_REG_ATIMDMACTL, DMACTL_WAKE); \
+	else								\
+		VNSvOutPortD(dwIoBase + MAC_REG_ATIMDMACTL, DMACTL_RUN); \
+} while (0)
+
+#define MACvTransmitBCN(dwIoBase)					\
+	VNSvOutPortB(dwIoBase + MAC_REG_BCNDMACTL, BEACON_READY)
+
+#define MACvClearStckDS(dwIoBase)					\
+do {									\
+	unsigned char byOrgValue;					\
+	VNSvInPortB(dwIoBase + MAC_REG_STICKHW, &byOrgValue);		\
+	byOrgValue = byOrgValue & 0xFC;					\
+	VNSvOutPortB(dwIoBase + MAC_REG_STICKHW, byOrgValue);		\
+} while (0)
+
+#define MACvReadISR(dwIoBase, pdwValue)				\
+	VNSvInPortD(dwIoBase + MAC_REG_ISR, pdwValue)
+
+#define MACvWriteISR(dwIoBase, dwValue)				\
+	VNSvOutPortD(dwIoBase + MAC_REG_ISR, dwValue)
+
+#define MACvIntEnable(dwIoBase, dwMask)				\
+	VNSvOutPortD(dwIoBase + MAC_REG_IMR, dwMask)
+
+#define MACvIntDisable(dwIoBase)				\
+	VNSvOutPortD(dwIoBase + MAC_REG_IMR, 0)
+
+#define MACvSelectPage0(dwIoBase)				\
+		VNSvOutPortB(dwIoBase + MAC_REG_PAGE1SEL, 0)
+
+#define MACvSelectPage1(dwIoBase)				\
+	VNSvOutPortB(dwIoBase + MAC_REG_PAGE1SEL, 1)
+
+#define MACvReadMIBCounter(dwIoBase, pdwCounter)			\
+	VNSvInPortD(dwIoBase + MAC_REG_MIBCNTR , pdwCounter)
+
+#define MACvPwrEvntDisable(dwIoBase)					\
+	VNSvOutPortW(dwIoBase + MAC_REG_WAKEUPEN0, 0x0000)
+
+#define MACvEnableProtectMD(dwIoBase)					\
+do {									\
+	unsigned long dwOrgValue;					\
+	VNSvInPortD(dwIoBase + MAC_REG_ENCFG , &dwOrgValue);		\
+	dwOrgValue = dwOrgValue | EnCFG_ProtectMd;			\
+	VNSvOutPortD(dwIoBase + MAC_REG_ENCFG, dwOrgValue);		\
+} while (0)
+
+#define MACvDisableProtectMD(dwIoBase)					\
+do {									\
+	unsigned long dwOrgValue;					\
+	VNSvInPortD(dwIoBase + MAC_REG_ENCFG , &dwOrgValue);		\
+	dwOrgValue = dwOrgValue & ~EnCFG_ProtectMd;			\
+	VNSvOutPortD(dwIoBase + MAC_REG_ENCFG, dwOrgValue);		\
+} while (0)
+
+#define MACvEnableBarkerPreambleMd(dwIoBase)				\
+do {									\
+	unsigned long dwOrgValue;					\
+	VNSvInPortD(dwIoBase + MAC_REG_ENCFG , &dwOrgValue);		\
+	dwOrgValue = dwOrgValue | EnCFG_BarkerPream;			\
+	VNSvOutPortD(dwIoBase + MAC_REG_ENCFG, dwOrgValue);		\
+} while (0)
+
+#define MACvDisableBarkerPreambleMd(dwIoBase)				\
+do {									\
+	unsigned long dwOrgValue;					\
+	VNSvInPortD(dwIoBase + MAC_REG_ENCFG , &dwOrgValue);		\
+	dwOrgValue = dwOrgValue & ~EnCFG_BarkerPream;			\
+	VNSvOutPortD(dwIoBase + MAC_REG_ENCFG, dwOrgValue);		\
+} while (0)
+
+#define MACvSetBBType(dwIoBase, byTyp)					\
+do {									\
+	unsigned long dwOrgValue;					\
+	VNSvInPortD(dwIoBase + MAC_REG_ENCFG , &dwOrgValue);		\
+	dwOrgValue = dwOrgValue & ~EnCFG_BBType_MASK;			\
+	dwOrgValue = dwOrgValue | (unsigned long)byTyp;			\
+	VNSvOutPortD(dwIoBase + MAC_REG_ENCFG, dwOrgValue);		\
+} while (0)
+
+#define MACvReadATIMW(dwIoBase, pwCounter)				\
+	VNSvInPortW(dwIoBase + MAC_REG_AIDATIM, pwCounter)
+
+#define MACvWriteATIMW(dwIoBase, wCounter)				\
+	VNSvOutPortW(dwIoBase + MAC_REG_AIDATIM, wCounter)
+
+#define MACvWriteCRC16_128(dwIoBase, byRegOfs, wCRC)		\
+do {								\
+	VNSvOutPortB(dwIoBase + MAC_REG_PAGE1SEL, 1);		\
+	VNSvOutPortW(dwIoBase + byRegOfs, wCRC);		\
+	VNSvOutPortB(dwIoBase + MAC_REG_PAGE1SEL, 0);		\
+} while (0)
+
+#define MACvGPIOIn(dwIoBase, pbyValue)					\
+	VNSvInPortB(dwIoBase + MAC_REG_GPIOCTL1, pbyValue)
 
 #define MACvSetRFLE_LatchBase(dwIoBase)                                 \
-{                                                                        \
-    MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_RFLEOPT); \
-}
+	MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_RFLEOPT)
 
 /*---------------------  Export Classes  ----------------------------*/
 
@@ -1107,7 +1029,7 @@ void MACvOneShotTimer1MicroSec(unsigned long dwIoBase, unsigned int uDelayTime);
 
 void MACvSetMISCFifo(unsigned long dwIoBase, unsigned short wOffset, unsigned long dwData);
 
-bool MACbTxDMAOff (unsigned long dwIoBase, unsigned int idx);
+bool MACbTxDMAOff(unsigned long dwIoBase, unsigned int idx);
 
 void MACvClearBusSusInd(unsigned long dwIoBase);
 void MACvEnableBusSusEn(unsigned long dwIoBase);
@@ -1116,15 +1038,14 @@ bool MACbFlushSYNCFifo(unsigned long dwIoBase);
 bool MACbPSWakeup(unsigned long dwIoBase);
 
 void MACvSetKeyEntry(unsigned long dwIoBase, unsigned short wKeyCtl, unsigned int uEntryIdx,
-		unsigned int uKeyIdx, unsigned char *pbyAddr, unsigned long *pdwKey, unsigned char byLocalID);
+		     unsigned int uKeyIdx, unsigned char *pbyAddr, unsigned long *pdwKey, unsigned char byLocalID);
 void MACvDisableKeyEntry(unsigned long dwIoBase, unsigned int uEntryIdx);
 void MACvSetDefaultKeyEntry(unsigned long dwIoBase, unsigned int uKeyLen,
-		unsigned int uKeyIdx, unsigned long *pdwKey, unsigned char byLocalID);
+			    unsigned int uKeyIdx, unsigned long *pdwKey, unsigned char byLocalID);
 //void MACvEnableDefaultKey(unsigned long dwIoBase, unsigned char byLocalID);
 void MACvDisableDefaultKey(unsigned long dwIoBase);
 void MACvSetDefaultTKIPKeyEntry(unsigned long dwIoBase, unsigned int uKeyLen,
-		unsigned int uKeyIdx, unsigned long *pdwKey, unsigned char byLocalID);
+				unsigned int uKeyIdx, unsigned long *pdwKey, unsigned char byLocalID);
 void MACvSetDefaultKeyCtl(unsigned long dwIoBase, unsigned short wKeyCtl, unsigned int uEntryIdx, unsigned char byLocalID);
 
 #endif // __MAC_H__
-
diff --git a/drivers/staging/vt6655/mib.c b/drivers/staging/vt6655/mib.c
index 63ae4ad..6a59652 100644
--- a/drivers/staging/vt6655/mib.c
+++ b/drivers/staging/vt6655/mib.c
@@ -45,7 +45,7 @@
 #include "baseband.h"
 
 /*---------------------  Static Definitions -------------------------*/
-static int          msglevel                =MSG_LEVEL_INFO;
+static int msglevel = MSG_LEVEL_INFO;
 /*---------------------  Static Classes  ----------------------------*/
 
 /*---------------------  Static Variables  --------------------------*/
@@ -56,8 +56,6 @@ static int          msglevel                =MSG_LEVEL_INFO;
 
 /*---------------------  Export Functions  --------------------------*/
 
-
-
 /*
  * Description: Clear All Statistic Counter
  *
@@ -70,13 +68,12 @@ static int          msglevel                =MSG_LEVEL_INFO;
  * Return Value: none
  *
  */
-void STAvClearAllCounter (PSStatCounter pStatistic)
+void STAvClearAllCounter(PSStatCounter pStatistic)
 {
-    // set memory to zero
+	// set memory to zero
 	memset(pStatistic, 0, sizeof(SStatCounter));
 }
 
-
 /*
  * Description: Update Isr Statistic Counter
  *
@@ -90,76 +87,59 @@ void STAvClearAllCounter (PSStatCounter pStatistic)
  * Return Value: none
  *
  */
-void STAvUpdateIsrStatCounter (PSStatCounter pStatistic, unsigned long dwIsr)
+void STAvUpdateIsrStatCounter(PSStatCounter pStatistic, unsigned long dwIsr)
 {
-    /**********************/
-    /* ABNORMAL interrupt */
-    /**********************/
-    // not any IMR bit invoke irq
+	/**********************/
+	/* ABNORMAL interrupt */
+	/**********************/
+	// not any IMR bit invoke irq
 
-    if (dwIsr == 0) {
-        pStatistic->ISRStat.dwIsrUnknown++;
-        return;
-    }
+	if (dwIsr == 0) {
+		pStatistic->ISRStat.dwIsrUnknown++;
+		return;
+	}
 
 //Added by Kyle
-    if (dwIsr & ISR_TXDMA0)               // ISR, bit0
-        pStatistic->ISRStat.dwIsrTx0OK++;             // TXDMA0 successful
-
-    if (dwIsr & ISR_AC0DMA)               // ISR, bit1
-        pStatistic->ISRStat.dwIsrAC0TxOK++;           // AC0DMA successful
-
-    if (dwIsr & ISR_BNTX)                 // ISR, bit2
-        pStatistic->ISRStat.dwIsrBeaconTxOK++;        // BeaconTx successful
-
-    if (dwIsr & ISR_RXDMA0)               // ISR, bit3
-        pStatistic->ISRStat.dwIsrRx0OK++;             // Rx0 successful
-
-    if (dwIsr & ISR_TBTT)                 // ISR, bit4
-        pStatistic->ISRStat.dwIsrTBTTInt++;           // TBTT successful
-
-    if (dwIsr & ISR_SOFTTIMER)            // ISR, bit6
-        pStatistic->ISRStat.dwIsrSTIMERInt++;
-
-    if (dwIsr & ISR_WATCHDOG)             // ISR, bit7
-        pStatistic->ISRStat.dwIsrWatchDog++;
+	if (dwIsr & ISR_TXDMA0)               // ISR, bit0
+		pStatistic->ISRStat.dwIsrTx0OK++;             // TXDMA0 successful
 
-    if (dwIsr & ISR_FETALERR)             // ISR, bit8
-        pStatistic->ISRStat.dwIsrUnrecoverableError++;
+	if (dwIsr & ISR_AC0DMA)               // ISR, bit1
+		pStatistic->ISRStat.dwIsrAC0TxOK++;           // AC0DMA successful
 
-    if (dwIsr & ISR_SOFTINT)              // ISR, bit9
-        pStatistic->ISRStat.dwIsrSoftInterrupt++;     // software interrupt
+	if (dwIsr & ISR_BNTX)                 // ISR, bit2
+		pStatistic->ISRStat.dwIsrBeaconTxOK++;        // BeaconTx successful
 
-    if (dwIsr & ISR_MIBNEARFULL)          // ISR, bit10
-        pStatistic->ISRStat.dwIsrMIBNearfull++;
+	if (dwIsr & ISR_RXDMA0)               // ISR, bit3
+		pStatistic->ISRStat.dwIsrRx0OK++;             // Rx0 successful
 
-    if (dwIsr & ISR_RXNOBUF)              // ISR, bit11
-        pStatistic->ISRStat.dwIsrRxNoBuf++;           // Rx No Buff
+	if (dwIsr & ISR_TBTT)                 // ISR, bit4
+		pStatistic->ISRStat.dwIsrTBTTInt++;           // TBTT successful
 
-    if (dwIsr & ISR_RXDMA1)               // ISR, bit12
-        pStatistic->ISRStat.dwIsrRx1OK++;             // Rx1 successful
+	if (dwIsr & ISR_SOFTTIMER)            // ISR, bit6
+		pStatistic->ISRStat.dwIsrSTIMERInt++;
 
-//    if (dwIsr & ISR_ATIMTX)               // ISR, bit13
-//        pStatistic->ISRStat.dwIsrATIMTxOK++;          // ATIMTX successful
+	if (dwIsr & ISR_WATCHDOG)             // ISR, bit7
+		pStatistic->ISRStat.dwIsrWatchDog++;
 
-//    if (dwIsr & ISR_SYNCTX)               // ISR, bit14
-//        pStatistic->ISRStat.dwIsrSYNCTxOK++;          // SYNCTX successful
+	if (dwIsr & ISR_FETALERR)             // ISR, bit8
+		pStatistic->ISRStat.dwIsrUnrecoverableError++;
 
-//    if (dwIsr & ISR_CFPEND)               // ISR, bit18
-//        pStatistic->ISRStat.dwIsrCFPEnd++;
+	if (dwIsr & ISR_SOFTINT)              // ISR, bit9
+		pStatistic->ISRStat.dwIsrSoftInterrupt++;     // software interrupt
 
-//    if (dwIsr & ISR_ATIMEND)              // ISR, bit19
-//        pStatistic->ISRStat.dwIsrATIMEnd++;
+	if (dwIsr & ISR_MIBNEARFULL)          // ISR, bit10
+		pStatistic->ISRStat.dwIsrMIBNearfull++;
 
-//    if (dwIsr & ISR_SYNCFLUSHOK)          // ISR, bit20
-//        pStatistic->ISRStat.dwIsrSYNCFlushOK++;
+	if (dwIsr & ISR_RXNOBUF)              // ISR, bit11
+		pStatistic->ISRStat.dwIsrRxNoBuf++;           // Rx No Buff
 
-    if (dwIsr & ISR_SOFTTIMER1)           // ISR, bit21
-        pStatistic->ISRStat.dwIsrSTIMER1Int++;
+	if (dwIsr & ISR_RXDMA1)               // ISR, bit12
+		pStatistic->ISRStat.dwIsrRx1OK++;             // Rx1 successful
 
+	if (dwIsr & ISR_SOFTTIMER1)           // ISR, bit21
+		pStatistic->ISRStat.dwIsrSTIMER1Int++;
 }
 
-
 /*
  * Description: Update Rx Statistic Counter
  *
@@ -176,199 +156,175 @@ void STAvUpdateIsrStatCounter (PSStatCounter pStatistic, unsigned long dwIsr)
  * Return Value: none
  *
  */
-void STAvUpdateRDStatCounter (PSStatCounter pStatistic,
-                              unsigned char byRSR, unsigned char byNewRSR, unsigned char byRxRate,
-                              unsigned char *pbyBuffer, unsigned int cbFrameLength)
+void STAvUpdateRDStatCounter(PSStatCounter pStatistic,
+			     unsigned char byRSR, unsigned char byNewRSR, unsigned char byRxRate,
+			     unsigned char *pbyBuffer, unsigned int cbFrameLength)
 {
-    //need change
-    PS802_11Header pHeader = (PS802_11Header)pbyBuffer;
-
-    if (byRSR & RSR_ADDROK)
-        pStatistic->dwRsrADDROk++;
-    if (byRSR & RSR_CRCOK) {
-        pStatistic->dwRsrCRCOk++;
-
-        pStatistic->ullRsrOK++;
-
-        if (cbFrameLength >= ETH_ALEN) {
-            // update counters in case of successful transmit
-            if (byRSR & RSR_ADDRBROAD) {
-                pStatistic->ullRxBroadcastFrames++;
-                pStatistic->ullRxBroadcastBytes += (unsigned long long) cbFrameLength;
-            }
-            else if (byRSR & RSR_ADDRMULTI) {
-                pStatistic->ullRxMulticastFrames++;
-                pStatistic->ullRxMulticastBytes += (unsigned long long) cbFrameLength;
-            }
-            else {
-                pStatistic->ullRxDirectedFrames++;
-                pStatistic->ullRxDirectedBytes += (unsigned long long) cbFrameLength;
-            }
-        }
-    }
-
-    if(byRxRate==22) {
-        pStatistic->CustomStat.ullRsr11M++;
-        if(byRSR & RSR_CRCOK) {
-            pStatistic->CustomStat.ullRsr11MCRCOk++;
-        }
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"11M: ALL[%d], OK[%d]:[%02x]\n", (int)pStatistic->CustomStat.ullRsr11M, (int)pStatistic->CustomStat.ullRsr11MCRCOk, byRSR);
-    }
-    else if(byRxRate==11) {
-        pStatistic->CustomStat.ullRsr5M++;
-        if(byRSR & RSR_CRCOK) {
-            pStatistic->CustomStat.ullRsr5MCRCOk++;
-        }
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" 5M: ALL[%d], OK[%d]:[%02x]\n", (int)pStatistic->CustomStat.ullRsr5M, (int)pStatistic->CustomStat.ullRsr5MCRCOk, byRSR);
-    }
-    else if(byRxRate==4) {
-        pStatistic->CustomStat.ullRsr2M++;
-        if(byRSR & RSR_CRCOK) {
-            pStatistic->CustomStat.ullRsr2MCRCOk++;
-        }
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" 2M: ALL[%d], OK[%d]:[%02x]\n", (int)pStatistic->CustomStat.ullRsr2M, (int)pStatistic->CustomStat.ullRsr2MCRCOk, byRSR);
-    }
-    else if(byRxRate==2){
-        pStatistic->CustomStat.ullRsr1M++;
-        if(byRSR & RSR_CRCOK) {
-            pStatistic->CustomStat.ullRsr1MCRCOk++;
-        }
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" 1M: ALL[%d], OK[%d]:[%02x]\n", (int)pStatistic->CustomStat.ullRsr1M, (int)pStatistic->CustomStat.ullRsr1MCRCOk, byRSR);
-    }
-    else if(byRxRate==12){
-        pStatistic->CustomStat.ullRsr6M++;
-        if(byRSR & RSR_CRCOK) {
-            pStatistic->CustomStat.ullRsr6MCRCOk++;
-        }
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" 6M: ALL[%d], OK[%d]\n", (int)pStatistic->CustomStat.ullRsr6M, (int)pStatistic->CustomStat.ullRsr6MCRCOk);
-    }
-    else if(byRxRate==18){
-        pStatistic->CustomStat.ullRsr9M++;
-        if(byRSR & RSR_CRCOK) {
-            pStatistic->CustomStat.ullRsr9MCRCOk++;
-        }
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" 9M: ALL[%d], OK[%d]\n", (int)pStatistic->CustomStat.ullRsr9M, (int)pStatistic->CustomStat.ullRsr9MCRCOk);
-    }
-    else if(byRxRate==24){
-        pStatistic->CustomStat.ullRsr12M++;
-        if(byRSR & RSR_CRCOK) {
-            pStatistic->CustomStat.ullRsr12MCRCOk++;
-        }
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"12M: ALL[%d], OK[%d]\n", (int)pStatistic->CustomStat.ullRsr12M, (int)pStatistic->CustomStat.ullRsr12MCRCOk);
-    }
-    else if(byRxRate==36){
-        pStatistic->CustomStat.ullRsr18M++;
-        if(byRSR & RSR_CRCOK) {
-            pStatistic->CustomStat.ullRsr18MCRCOk++;
-        }
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"18M: ALL[%d], OK[%d]\n", (int)pStatistic->CustomStat.ullRsr18M, (int)pStatistic->CustomStat.ullRsr18MCRCOk);
-    }
-    else if(byRxRate==48){
-        pStatistic->CustomStat.ullRsr24M++;
-        if(byRSR & RSR_CRCOK) {
-            pStatistic->CustomStat.ullRsr24MCRCOk++;
-        }
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"24M: ALL[%d], OK[%d]\n", (int)pStatistic->CustomStat.ullRsr24M, (int)pStatistic->CustomStat.ullRsr24MCRCOk);
-    }
-    else if(byRxRate==72){
-        pStatistic->CustomStat.ullRsr36M++;
-        if(byRSR & RSR_CRCOK) {
-            pStatistic->CustomStat.ullRsr36MCRCOk++;
-        }
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"36M: ALL[%d], OK[%d]\n", (int)pStatistic->CustomStat.ullRsr36M, (int)pStatistic->CustomStat.ullRsr36MCRCOk);
-    }
-    else if(byRxRate==96){
-        pStatistic->CustomStat.ullRsr48M++;
-        if(byRSR & RSR_CRCOK) {
-            pStatistic->CustomStat.ullRsr48MCRCOk++;
-        }
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"48M: ALL[%d], OK[%d]\n", (int)pStatistic->CustomStat.ullRsr48M, (int)pStatistic->CustomStat.ullRsr48MCRCOk);
-    }
-    else if(byRxRate==108){
-        pStatistic->CustomStat.ullRsr54M++;
-        if(byRSR & RSR_CRCOK) {
-            pStatistic->CustomStat.ullRsr54MCRCOk++;
-        }
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"54M: ALL[%d], OK[%d]\n", (int)pStatistic->CustomStat.ullRsr54M, (int)pStatistic->CustomStat.ullRsr54MCRCOk);
-    }
-    else {
-    	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Unknown: Total[%d], CRCOK[%d]\n", (int)pStatistic->dwRsrRxPacket+1, (int)pStatistic->dwRsrCRCOk);
-    }
-
-    if (byRSR & RSR_BSSIDOK)
-        pStatistic->dwRsrBSSIDOk++;
-
-    if (byRSR & RSR_BCNSSIDOK)
-        pStatistic->dwRsrBCNSSIDOk++;
-    if (byRSR & RSR_IVLDLEN)  //invalid len (> 2312 byte)
-        pStatistic->dwRsrLENErr++;
-    if (byRSR & RSR_IVLDTYP)  //invalid packet type
-        pStatistic->dwRsrTYPErr++;
-    if (byRSR & (RSR_IVLDTYP | RSR_IVLDLEN))
-        pStatistic->dwRsrErr++;
-
-    if (byNewRSR & NEWRSR_DECRYPTOK)
-        pStatistic->dwNewRsrDECRYPTOK++;
-    if (byNewRSR & NEWRSR_CFPIND)
-        pStatistic->dwNewRsrCFP++;
-    if (byNewRSR & NEWRSR_HWUTSF)
-        pStatistic->dwNewRsrUTSF++;
-    if (byNewRSR & NEWRSR_BCNHITAID)
-        pStatistic->dwNewRsrHITAID++;
-    if (byNewRSR & NEWRSR_BCNHITAID0)
-        pStatistic->dwNewRsrHITAID0++;
-
-    // increase rx packet count
-    pStatistic->dwRsrRxPacket++;
-    pStatistic->dwRsrRxOctet += cbFrameLength;
-
-
-    if (IS_TYPE_DATA(pbyBuffer)) {
-        pStatistic->dwRsrRxData++;
-    } else if (IS_TYPE_MGMT(pbyBuffer)){
-        pStatistic->dwRsrRxManage++;
-    } else if (IS_TYPE_CONTROL(pbyBuffer)){
-        pStatistic->dwRsrRxControl++;
-    }
-
-    if (byRSR & RSR_ADDRBROAD)
-        pStatistic->dwRsrBroadcast++;
-    else if (byRSR & RSR_ADDRMULTI)
-        pStatistic->dwRsrMulticast++;
-    else
-        pStatistic->dwRsrDirected++;
-
-    if (WLAN_GET_FC_MOREFRAG(pHeader->wFrameCtl))
-        pStatistic->dwRsrRxFragment++;
-
-    if (cbFrameLength < ETH_ZLEN + 4) {
-        pStatistic->dwRsrRunt++;
-    }
-    else if (cbFrameLength == ETH_ZLEN + 4) {
-        pStatistic->dwRsrRxFrmLen64++;
-    }
-    else if ((65 <= cbFrameLength) && (cbFrameLength <= 127)) {
-        pStatistic->dwRsrRxFrmLen65_127++;
-    }
-    else if ((128 <= cbFrameLength) && (cbFrameLength <= 255)) {
-        pStatistic->dwRsrRxFrmLen128_255++;
-    }
-    else if ((256 <= cbFrameLength) && (cbFrameLength <= 511)) {
-        pStatistic->dwRsrRxFrmLen256_511++;
-    }
-    else if ((512 <= cbFrameLength) && (cbFrameLength <= 1023)) {
-        pStatistic->dwRsrRxFrmLen512_1023++;
-    }
-    else if ((1024 <= cbFrameLength) && (cbFrameLength <= ETH_FRAME_LEN + 4)) {
-        pStatistic->dwRsrRxFrmLen1024_1518++;
-    } else if (cbFrameLength > ETH_FRAME_LEN + 4) {
-        pStatistic->dwRsrLong++;
-    }
-
+	//need change
+	PS802_11Header pHeader = (PS802_11Header)pbyBuffer;
+
+	if (byRSR & RSR_ADDROK)
+		pStatistic->dwRsrADDROk++;
+	if (byRSR & RSR_CRCOK) {
+		pStatistic->dwRsrCRCOk++;
+
+		pStatistic->ullRsrOK++;
+
+		if (cbFrameLength >= ETH_ALEN) {
+			// update counters in case of successful transmit
+			if (byRSR & RSR_ADDRBROAD) {
+				pStatistic->ullRxBroadcastFrames++;
+				pStatistic->ullRxBroadcastBytes += (unsigned long long) cbFrameLength;
+			} else if (byRSR & RSR_ADDRMULTI) {
+				pStatistic->ullRxMulticastFrames++;
+				pStatistic->ullRxMulticastBytes += (unsigned long long) cbFrameLength;
+			} else {
+				pStatistic->ullRxDirectedFrames++;
+				pStatistic->ullRxDirectedBytes += (unsigned long long) cbFrameLength;
+			}
+		}
+	}
+
+	if (byRxRate == 22) {
+		pStatistic->CustomStat.ullRsr11M++;
+		if (byRSR & RSR_CRCOK) {
+			pStatistic->CustomStat.ullRsr11MCRCOk++;
+		}
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "11M: ALL[%d], OK[%d]:[%02x]\n", (int)pStatistic->CustomStat.ullRsr11M, (int)pStatistic->CustomStat.ullRsr11MCRCOk, byRSR);
+	} else if (byRxRate == 11) {
+		pStatistic->CustomStat.ullRsr5M++;
+		if (byRSR & RSR_CRCOK) {
+			pStatistic->CustomStat.ullRsr5MCRCOk++;
+		}
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " 5M: ALL[%d], OK[%d]:[%02x]\n", (int)pStatistic->CustomStat.ullRsr5M, (int)pStatistic->CustomStat.ullRsr5MCRCOk, byRSR);
+	} else if (byRxRate == 4) {
+		pStatistic->CustomStat.ullRsr2M++;
+		if (byRSR & RSR_CRCOK) {
+			pStatistic->CustomStat.ullRsr2MCRCOk++;
+		}
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " 2M: ALL[%d], OK[%d]:[%02x]\n", (int)pStatistic->CustomStat.ullRsr2M, (int)pStatistic->CustomStat.ullRsr2MCRCOk, byRSR);
+	} else if (byRxRate == 2) {
+		pStatistic->CustomStat.ullRsr1M++;
+		if (byRSR & RSR_CRCOK) {
+			pStatistic->CustomStat.ullRsr1MCRCOk++;
+		}
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " 1M: ALL[%d], OK[%d]:[%02x]\n", (int)pStatistic->CustomStat.ullRsr1M, (int)pStatistic->CustomStat.ullRsr1MCRCOk, byRSR);
+	} else if (byRxRate == 12) {
+		pStatistic->CustomStat.ullRsr6M++;
+		if (byRSR & RSR_CRCOK) {
+			pStatistic->CustomStat.ullRsr6MCRCOk++;
+		}
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " 6M: ALL[%d], OK[%d]\n", (int)pStatistic->CustomStat.ullRsr6M, (int)pStatistic->CustomStat.ullRsr6MCRCOk);
+	} else if (byRxRate == 18) {
+		pStatistic->CustomStat.ullRsr9M++;
+		if (byRSR & RSR_CRCOK) {
+			pStatistic->CustomStat.ullRsr9MCRCOk++;
+		}
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " 9M: ALL[%d], OK[%d]\n", (int)pStatistic->CustomStat.ullRsr9M, (int)pStatistic->CustomStat.ullRsr9MCRCOk);
+	} else if (byRxRate == 24) {
+		pStatistic->CustomStat.ullRsr12M++;
+		if (byRSR & RSR_CRCOK) {
+			pStatistic->CustomStat.ullRsr12MCRCOk++;
+		}
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "12M: ALL[%d], OK[%d]\n", (int)pStatistic->CustomStat.ullRsr12M, (int)pStatistic->CustomStat.ullRsr12MCRCOk);
+	} else if (byRxRate == 36) {
+		pStatistic->CustomStat.ullRsr18M++;
+		if (byRSR & RSR_CRCOK) {
+			pStatistic->CustomStat.ullRsr18MCRCOk++;
+		}
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "18M: ALL[%d], OK[%d]\n", (int)pStatistic->CustomStat.ullRsr18M, (int)pStatistic->CustomStat.ullRsr18MCRCOk);
+	} else if (byRxRate == 48) {
+		pStatistic->CustomStat.ullRsr24M++;
+		if (byRSR & RSR_CRCOK) {
+			pStatistic->CustomStat.ullRsr24MCRCOk++;
+		}
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "24M: ALL[%d], OK[%d]\n", (int)pStatistic->CustomStat.ullRsr24M, (int)pStatistic->CustomStat.ullRsr24MCRCOk);
+	} else if (byRxRate == 72) {
+		pStatistic->CustomStat.ullRsr36M++;
+		if (byRSR & RSR_CRCOK) {
+			pStatistic->CustomStat.ullRsr36MCRCOk++;
+		}
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "36M: ALL[%d], OK[%d]\n", (int)pStatistic->CustomStat.ullRsr36M, (int)pStatistic->CustomStat.ullRsr36MCRCOk);
+	} else if (byRxRate == 96) {
+		pStatistic->CustomStat.ullRsr48M++;
+		if (byRSR & RSR_CRCOK) {
+			pStatistic->CustomStat.ullRsr48MCRCOk++;
+		}
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "48M: ALL[%d], OK[%d]\n", (int)pStatistic->CustomStat.ullRsr48M, (int)pStatistic->CustomStat.ullRsr48MCRCOk);
+	} else if (byRxRate == 108) {
+		pStatistic->CustomStat.ullRsr54M++;
+		if (byRSR & RSR_CRCOK) {
+			pStatistic->CustomStat.ullRsr54MCRCOk++;
+		}
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "54M: ALL[%d], OK[%d]\n", (int)pStatistic->CustomStat.ullRsr54M, (int)pStatistic->CustomStat.ullRsr54MCRCOk);
+	} else {
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Unknown: Total[%d], CRCOK[%d]\n", (int)pStatistic->dwRsrRxPacket+1, (int)pStatistic->dwRsrCRCOk);
+	}
+
+	if (byRSR & RSR_BSSIDOK)
+		pStatistic->dwRsrBSSIDOk++;
+
+	if (byRSR & RSR_BCNSSIDOK)
+		pStatistic->dwRsrBCNSSIDOk++;
+	if (byRSR & RSR_IVLDLEN)  //invalid len (> 2312 byte)
+		pStatistic->dwRsrLENErr++;
+	if (byRSR & RSR_IVLDTYP)  //invalid packet type
+		pStatistic->dwRsrTYPErr++;
+	if (byRSR & (RSR_IVLDTYP | RSR_IVLDLEN))
+		pStatistic->dwRsrErr++;
+
+	if (byNewRSR & NEWRSR_DECRYPTOK)
+		pStatistic->dwNewRsrDECRYPTOK++;
+	if (byNewRSR & NEWRSR_CFPIND)
+		pStatistic->dwNewRsrCFP++;
+	if (byNewRSR & NEWRSR_HWUTSF)
+		pStatistic->dwNewRsrUTSF++;
+	if (byNewRSR & NEWRSR_BCNHITAID)
+		pStatistic->dwNewRsrHITAID++;
+	if (byNewRSR & NEWRSR_BCNHITAID0)
+		pStatistic->dwNewRsrHITAID0++;
+
+	// increase rx packet count
+	pStatistic->dwRsrRxPacket++;
+	pStatistic->dwRsrRxOctet += cbFrameLength;
+
+	if (IS_TYPE_DATA(pbyBuffer)) {
+		pStatistic->dwRsrRxData++;
+	} else if (IS_TYPE_MGMT(pbyBuffer)) {
+		pStatistic->dwRsrRxManage++;
+	} else if (IS_TYPE_CONTROL(pbyBuffer)) {
+		pStatistic->dwRsrRxControl++;
+	}
+
+	if (byRSR & RSR_ADDRBROAD)
+		pStatistic->dwRsrBroadcast++;
+	else if (byRSR & RSR_ADDRMULTI)
+		pStatistic->dwRsrMulticast++;
+	else
+		pStatistic->dwRsrDirected++;
+
+	if (WLAN_GET_FC_MOREFRAG(pHeader->wFrameCtl))
+		pStatistic->dwRsrRxFragment++;
+
+	if (cbFrameLength < ETH_ZLEN + 4) {
+		pStatistic->dwRsrRunt++;
+	} else if (cbFrameLength == ETH_ZLEN + 4) {
+		pStatistic->dwRsrRxFrmLen64++;
+	} else if ((65 <= cbFrameLength) && (cbFrameLength <= 127)) {
+		pStatistic->dwRsrRxFrmLen65_127++;
+	} else if ((128 <= cbFrameLength) && (cbFrameLength <= 255)) {
+		pStatistic->dwRsrRxFrmLen128_255++;
+	} else if ((256 <= cbFrameLength) && (cbFrameLength <= 511)) {
+		pStatistic->dwRsrRxFrmLen256_511++;
+	} else if ((512 <= cbFrameLength) && (cbFrameLength <= 1023)) {
+		pStatistic->dwRsrRxFrmLen512_1023++;
+	} else if ((1024 <= cbFrameLength) && (cbFrameLength <= ETH_FRAME_LEN + 4)) {
+		pStatistic->dwRsrRxFrmLen1024_1518++;
+	} else if (cbFrameLength > ETH_FRAME_LEN + 4) {
+		pStatistic->dwRsrLong++;
+	}
 }
 
-
-
 /*
  * Description: Update Rx Statistic Counter and copy Rx buffer
  *
@@ -387,31 +343,30 @@ void STAvUpdateRDStatCounter (PSStatCounter pStatistic,
  */
 
 void
-STAvUpdateRDStatCounterEx (
-    PSStatCounter   pStatistic,
-    unsigned char byRSR,
-    unsigned char byNewRSR,
-    unsigned char byRxRate,
-    unsigned char *pbyBuffer,
-    unsigned int cbFrameLength
-    )
+STAvUpdateRDStatCounterEx(
+	PSStatCounter   pStatistic,
+	unsigned char byRSR,
+	unsigned char byNewRSR,
+	unsigned char byRxRate,
+	unsigned char *pbyBuffer,
+	unsigned int cbFrameLength
+)
 {
-    STAvUpdateRDStatCounter(
-                    pStatistic,
-                    byRSR,
-                    byNewRSR,
-                    byRxRate,
-                    pbyBuffer,
-                    cbFrameLength
-                    );
-
-    // rx length
-    pStatistic->dwCntRxFrmLength = cbFrameLength;
-    // rx pattern, we just see 10 bytes for sample
-    memcpy(pStatistic->abyCntRxPattern, (unsigned char *)pbyBuffer, 10);
+	STAvUpdateRDStatCounter(
+		pStatistic,
+		byRSR,
+		byNewRSR,
+		byRxRate,
+		pbyBuffer,
+		cbFrameLength
+);
+
+	// rx length
+	pStatistic->dwCntRxFrmLength = cbFrameLength;
+	// rx pattern, we just see 10 bytes for sample
+	memcpy(pStatistic->abyCntRxPattern, (unsigned char *)pbyBuffer, 10);
 }
 
-
 /*
  * Description: Update Tx Statistic Counter
  *
@@ -430,81 +385,73 @@ STAvUpdateRDStatCounterEx (
  *
  */
 void
-STAvUpdateTDStatCounter (
-    PSStatCounter   pStatistic,
-    unsigned char byTSR0,
-    unsigned char byTSR1,
-    unsigned char *pbyBuffer,
-    unsigned int cbFrameLength,
-    unsigned int uIdx
-    )
+STAvUpdateTDStatCounter(
+	PSStatCounter   pStatistic,
+	unsigned char byTSR0,
+	unsigned char byTSR1,
+	unsigned char *pbyBuffer,
+	unsigned int cbFrameLength,
+	unsigned int uIdx
+)
 {
-    PWLAN_80211HDR_A4   pHeader;
-    unsigned char *pbyDestAddr;
-    unsigned char byTSR0_NCR = byTSR0 & TSR0_NCR;
-
-
-
-    pHeader = (PWLAN_80211HDR_A4) pbyBuffer;
-    if (WLAN_GET_FC_TODS(pHeader->wFrameCtl) == 0) {
-        pbyDestAddr = &(pHeader->abyAddr1[0]);
-    }
-    else {
-        pbyDestAddr = &(pHeader->abyAddr3[0]);
-    }
-    // increase tx packet count
-    pStatistic->dwTsrTxPacket[uIdx]++;
-    pStatistic->dwTsrTxOctet[uIdx] += cbFrameLength;
-
-    if (byTSR0_NCR != 0) {
-        pStatistic->dwTsrRetry[uIdx]++;
-        pStatistic->dwTsrTotalRetry[uIdx] += byTSR0_NCR;
-
-        if (byTSR0_NCR == 1)
-            pStatistic->dwTsrOnceRetry[uIdx]++;
-        else
-            pStatistic->dwTsrMoreThanOnceRetry[uIdx]++;
-    }
-
-    if ((byTSR1&(TSR1_TERR|TSR1_RETRYTMO|TSR1_TMO|ACK_DATA)) == 0) {
-        pStatistic->ullTsrOK[uIdx]++;
-        pStatistic->CustomStat.ullTsrAllOK =
-            (pStatistic->ullTsrOK[TYPE_AC0DMA] + pStatistic->ullTsrOK[TYPE_TXDMA0]);
-        // update counters in case that successful transmit
-        if (is_broadcast_ether_addr(pbyDestAddr)) {
-            pStatistic->ullTxBroadcastFrames[uIdx]++;
-            pStatistic->ullTxBroadcastBytes[uIdx] += (unsigned long long) cbFrameLength;
-        }
-        else if (is_multicast_ether_addr(pbyDestAddr)) {
-            pStatistic->ullTxMulticastFrames[uIdx]++;
-            pStatistic->ullTxMulticastBytes[uIdx] += (unsigned long long) cbFrameLength;
-        }
-        else {
-            pStatistic->ullTxDirectedFrames[uIdx]++;
-            pStatistic->ullTxDirectedBytes[uIdx] += (unsigned long long) cbFrameLength;
-        }
-    }
-    else {
-        if (byTSR1 & TSR1_TERR)
-            pStatistic->dwTsrErr[uIdx]++;
-        if (byTSR1 & TSR1_RETRYTMO)
-            pStatistic->dwTsrRetryTimeout[uIdx]++;
-        if (byTSR1 & TSR1_TMO)
-            pStatistic->dwTsrTransmitTimeout[uIdx]++;
-        if (byTSR1 & ACK_DATA)
-            pStatistic->dwTsrACKData[uIdx]++;
-    }
-
-    if (is_broadcast_ether_addr(pbyDestAddr))
-        pStatistic->dwTsrBroadcast[uIdx]++;
-    else if (is_multicast_ether_addr(pbyDestAddr))
-        pStatistic->dwTsrMulticast[uIdx]++;
-    else
-        pStatistic->dwTsrDirected[uIdx]++;
-
+	PWLAN_80211HDR_A4   pHeader;
+	unsigned char *pbyDestAddr;
+	unsigned char byTSR0_NCR = byTSR0 & TSR0_NCR;
+
+	pHeader = (PWLAN_80211HDR_A4) pbyBuffer;
+	if (WLAN_GET_FC_TODS(pHeader->wFrameCtl) == 0) {
+		pbyDestAddr = &(pHeader->abyAddr1[0]);
+	} else {
+		pbyDestAddr = &(pHeader->abyAddr3[0]);
+	}
+	// increase tx packet count
+	pStatistic->dwTsrTxPacket[uIdx]++;
+	pStatistic->dwTsrTxOctet[uIdx] += cbFrameLength;
+
+	if (byTSR0_NCR != 0) {
+		pStatistic->dwTsrRetry[uIdx]++;
+		pStatistic->dwTsrTotalRetry[uIdx] += byTSR0_NCR;
+
+		if (byTSR0_NCR == 1)
+			pStatistic->dwTsrOnceRetry[uIdx]++;
+		else
+			pStatistic->dwTsrMoreThanOnceRetry[uIdx]++;
+	}
+
+	if ((byTSR1&(TSR1_TERR|TSR1_RETRYTMO|TSR1_TMO|ACK_DATA)) == 0) {
+		pStatistic->ullTsrOK[uIdx]++;
+		pStatistic->CustomStat.ullTsrAllOK =
+			(pStatistic->ullTsrOK[TYPE_AC0DMA] + pStatistic->ullTsrOK[TYPE_TXDMA0]);
+		// update counters in case that successful transmit
+		if (is_broadcast_ether_addr(pbyDestAddr)) {
+			pStatistic->ullTxBroadcastFrames[uIdx]++;
+			pStatistic->ullTxBroadcastBytes[uIdx] += (unsigned long long) cbFrameLength;
+		} else if (is_multicast_ether_addr(pbyDestAddr)) {
+			pStatistic->ullTxMulticastFrames[uIdx]++;
+			pStatistic->ullTxMulticastBytes[uIdx] += (unsigned long long) cbFrameLength;
+		} else {
+			pStatistic->ullTxDirectedFrames[uIdx]++;
+			pStatistic->ullTxDirectedBytes[uIdx] += (unsigned long long) cbFrameLength;
+		}
+	} else {
+		if (byTSR1 & TSR1_TERR)
+			pStatistic->dwTsrErr[uIdx]++;
+		if (byTSR1 & TSR1_RETRYTMO)
+			pStatistic->dwTsrRetryTimeout[uIdx]++;
+		if (byTSR1 & TSR1_TMO)
+			pStatistic->dwTsrTransmitTimeout[uIdx]++;
+		if (byTSR1 & ACK_DATA)
+			pStatistic->dwTsrACKData[uIdx]++;
+	}
+
+	if (is_broadcast_ether_addr(pbyDestAddr))
+		pStatistic->dwTsrBroadcast[uIdx]++;
+	else if (is_multicast_ether_addr(pbyDestAddr))
+		pStatistic->dwTsrMulticast[uIdx]++;
+	else
+		pStatistic->dwTsrDirected[uIdx]++;
 }
 
-
 /*
  * Description: Update Tx Statistic Counter and copy Tx buffer
  *
@@ -520,23 +467,22 @@ STAvUpdateTDStatCounter (
  *
  */
 void
-STAvUpdateTDStatCounterEx (
-    PSStatCounter   pStatistic,
-    unsigned char *pbyBuffer,
-    unsigned long cbFrameLength
-    )
+STAvUpdateTDStatCounterEx(
+	PSStatCounter   pStatistic,
+	unsigned char *pbyBuffer,
+	unsigned long cbFrameLength
+)
 {
-    unsigned int uPktLength;
+	unsigned int uPktLength;
 
-    uPktLength = (unsigned int)cbFrameLength;
+	uPktLength = (unsigned int)cbFrameLength;
 
-    // tx length
-    pStatistic->dwCntTxBufLength = uPktLength;
-    // tx pattern, we just see 16 bytes for sample
-    memcpy(pStatistic->abyCntTxPattern, pbyBuffer, 16);
+	// tx length
+	pStatistic->dwCntTxBufLength = uPktLength;
+	// tx pattern, we just see 16 bytes for sample
+	memcpy(pStatistic->abyCntTxPattern, pbyBuffer, 16);
 }
 
-
 /*
  * Description: Update 802.11 mib counter
  *
@@ -553,28 +499,28 @@ STAvUpdateTDStatCounterEx (
  */
 void
 STAvUpdate802_11Counter(
-    PSDot11Counters         p802_11Counter,
-    PSStatCounter           pStatistic,
-    unsigned long dwCounter
-    )
+	PSDot11Counters         p802_11Counter,
+	PSStatCounter           pStatistic,
+	unsigned long dwCounter
+)
 {
-    //p802_11Counter->TransmittedFragmentCount
-    p802_11Counter->MulticastTransmittedFrameCount = (unsigned long long) (pStatistic->dwTsrBroadcast[TYPE_AC0DMA] +
-                                                                  pStatistic->dwTsrBroadcast[TYPE_TXDMA0] +
-                                                                  pStatistic->dwTsrMulticast[TYPE_AC0DMA] +
-                                                                  pStatistic->dwTsrMulticast[TYPE_TXDMA0]);
-    p802_11Counter->FailedCount = (unsigned long long) (pStatistic->dwTsrErr[TYPE_AC0DMA] + pStatistic->dwTsrErr[TYPE_TXDMA0]);
-    p802_11Counter->RetryCount = (unsigned long long) (pStatistic->dwTsrRetry[TYPE_AC0DMA] + pStatistic->dwTsrRetry[TYPE_TXDMA0]);
-    p802_11Counter->MultipleRetryCount = (unsigned long long) (pStatistic->dwTsrMoreThanOnceRetry[TYPE_AC0DMA] +
-                                                          pStatistic->dwTsrMoreThanOnceRetry[TYPE_TXDMA0]);
-    //p802_11Counter->FrameDuplicateCount
-    p802_11Counter->RTSSuccessCount += (unsigned long long)  (dwCounter & 0x000000ff);
-    p802_11Counter->RTSFailureCount += (unsigned long long) ((dwCounter & 0x0000ff00) >> 8);
-    p802_11Counter->ACKFailureCount += (unsigned long long) ((dwCounter & 0x00ff0000) >> 16);
-    p802_11Counter->FCSErrorCount +=   (unsigned long long) ((dwCounter & 0xff000000) >> 24);
-    //p802_11Counter->ReceivedFragmentCount
-    p802_11Counter->MulticastReceivedFrameCount = (unsigned long long) (pStatistic->dwRsrBroadcast +
-                                                               pStatistic->dwRsrMulticast);
+	//p802_11Counter->TransmittedFragmentCount
+	p802_11Counter->MulticastTransmittedFrameCount = (unsigned long long) (pStatistic->dwTsrBroadcast[TYPE_AC0DMA] +
+									       pStatistic->dwTsrBroadcast[TYPE_TXDMA0] +
+									       pStatistic->dwTsrMulticast[TYPE_AC0DMA] +
+									       pStatistic->dwTsrMulticast[TYPE_TXDMA0]);
+	p802_11Counter->FailedCount = (unsigned long long) (pStatistic->dwTsrErr[TYPE_AC0DMA] + pStatistic->dwTsrErr[TYPE_TXDMA0]);
+	p802_11Counter->RetryCount = (unsigned long long) (pStatistic->dwTsrRetry[TYPE_AC0DMA] + pStatistic->dwTsrRetry[TYPE_TXDMA0]);
+	p802_11Counter->MultipleRetryCount = (unsigned long long) (pStatistic->dwTsrMoreThanOnceRetry[TYPE_AC0DMA] +
+								   pStatistic->dwTsrMoreThanOnceRetry[TYPE_TXDMA0]);
+	//p802_11Counter->FrameDuplicateCount
+	p802_11Counter->RTSSuccessCount += (unsigned long long)  (dwCounter & 0x000000ff);
+	p802_11Counter->RTSFailureCount += (unsigned long long) ((dwCounter & 0x0000ff00) >> 8);
+	p802_11Counter->ACKFailureCount += (unsigned long long) ((dwCounter & 0x00ff0000) >> 16);
+	p802_11Counter->FCSErrorCount +=   (unsigned long long) ((dwCounter & 0xff000000) >> 24);
+	//p802_11Counter->ReceivedFragmentCount
+	p802_11Counter->MulticastReceivedFrameCount = (unsigned long long) (pStatistic->dwRsrBroadcast +
+									    pStatistic->dwRsrMulticast);
 }
 
 /*
@@ -592,6 +538,6 @@ STAvUpdate802_11Counter(
 void
 STAvClear802_11Counter(PSDot11Counters p802_11Counter)
 {
-    // set memory to zero
+	// set memory to zero
 	memset(p802_11Counter, 0, sizeof(SDot11Counters));
 }
diff --git a/drivers/staging/vt6655/mib.h b/drivers/staging/vt6655/mib.h
index 5cd697a..6b99c11 100644
--- a/drivers/staging/vt6655/mib.h
+++ b/drivers/staging/vt6655/mib.h
@@ -39,62 +39,61 @@
 //
 
 typedef struct tagSDot11Counters {
-    unsigned long Length;             // Length of structure
-    unsigned long long   TransmittedFragmentCount;
-    unsigned long long   MulticastTransmittedFrameCount;
-    unsigned long long   FailedCount;
-    unsigned long long   RetryCount;
-    unsigned long long   MultipleRetryCount;
-    unsigned long long   RTSSuccessCount;
-    unsigned long long   RTSFailureCount;
-    unsigned long long   ACKFailureCount;
-    unsigned long long   FrameDuplicateCount;
-    unsigned long long   ReceivedFragmentCount;
-    unsigned long long   MulticastReceivedFrameCount;
-    unsigned long long   FCSErrorCount;
-    unsigned long long   TKIPLocalMICFailures;
-    unsigned long long   TKIPRemoteMICFailures;
-    unsigned long long   TKIPICVErrors;
-    unsigned long long   TKIPCounterMeasuresInvoked;
-    unsigned long long   TKIPReplays;
-    unsigned long long   CCMPFormatErrors;
-    unsigned long long   CCMPReplays;
-    unsigned long long   CCMPDecryptErrors;
-    unsigned long long   FourWayHandshakeFailures;
+	unsigned long Length;             // Length of structure
+	unsigned long long   TransmittedFragmentCount;
+	unsigned long long   MulticastTransmittedFrameCount;
+	unsigned long long   FailedCount;
+	unsigned long long   RetryCount;
+	unsigned long long   MultipleRetryCount;
+	unsigned long long   RTSSuccessCount;
+	unsigned long long   RTSFailureCount;
+	unsigned long long   ACKFailureCount;
+	unsigned long long   FrameDuplicateCount;
+	unsigned long long   ReceivedFragmentCount;
+	unsigned long long   MulticastReceivedFrameCount;
+	unsigned long long   FCSErrorCount;
+	unsigned long long   TKIPLocalMICFailures;
+	unsigned long long   TKIPRemoteMICFailures;
+	unsigned long long   TKIPICVErrors;
+	unsigned long long   TKIPCounterMeasuresInvoked;
+	unsigned long long   TKIPReplays;
+	unsigned long long   CCMPFormatErrors;
+	unsigned long long   CCMPReplays;
+	unsigned long long   CCMPDecryptErrors;
+	unsigned long long   FourWayHandshakeFailures;
 //    unsigned long long   WEPUndecryptableCount;
 //    unsigned long long   WEPICVErrorCount;
 //    unsigned long long   DecryptSuccessCount;
 //    unsigned long long   DecryptFailureCount;
 } SDot11Counters, *PSDot11Counters;
 
-
 //
 // MIB2 counter
 //
 typedef struct tagSMib2Counter {
-    long    ifIndex;
-    char    ifDescr[256];               // max size 255 plus zero ending
-                                        // e.g. "interface 1"
-    long    ifType;
-    long    ifMtu;
-    unsigned long ifSpeed;
-    unsigned char ifPhysAddress[ETH_ALEN];
-    long    ifAdminStatus;
-    long    ifOperStatus;
-    unsigned long ifLastChange;
-    unsigned long ifInOctets;
-    unsigned long ifInUcastPkts;
-    unsigned long ifInNUcastPkts;
-    unsigned long ifInDiscards;
-    unsigned long ifInErrors;
-    unsigned long ifInUnknownProtos;
-    unsigned long ifOutOctets;
-    unsigned long ifOutUcastPkts;
-    unsigned long ifOutNUcastPkts;
-    unsigned long ifOutDiscards;
-    unsigned long ifOutErrors;
-    unsigned long ifOutQLen;
-    unsigned long ifSpecific;
+	long    ifIndex;
+	char    ifDescr[256];               // max size 255 plus zero ending
+	// e.g. "interface 1"
+	long    ifType;
+	long    ifMtu;
+	unsigned long ifSpeed;
+	unsigned char ifPhysAddress[ETH_ALEN];
+	long    ifAdminStatus;
+	long    ifOperStatus;
+	unsigned long ifLastChange;
+	unsigned long ifInOctets;
+	unsigned long ifInUcastPkts;
+	unsigned long ifInNUcastPkts;
+	unsigned long ifInDiscards;
+	unsigned long ifInErrors;
+	unsigned long ifInUnknownProtos;
+	unsigned long ifOutOctets;
+	unsigned long ifOutUcastPkts;
+	unsigned long ifOutNUcastPkts;
+	unsigned long ifOutDiscards;
+	unsigned long ifOutErrors;
+	unsigned long ifOutQLen;
+	unsigned long ifSpecific;
 } SMib2Counter, *PSMib2Counter;
 
 // Value in the ifType entry
@@ -105,104 +104,100 @@ typedef struct tagSMib2Counter {
 #define DOWN                2           //
 #define TESTING             3           //
 
-
 //
 // RMON counter
 //
 typedef struct tagSRmonCounter {
-    long    etherStatsIndex;
-    unsigned long etherStatsDataSource;
-    unsigned long etherStatsDropEvents;
-    unsigned long etherStatsOctets;
-    unsigned long etherStatsPkts;
-    unsigned long etherStatsBroadcastPkts;
-    unsigned long etherStatsMulticastPkts;
-    unsigned long etherStatsCRCAlignErrors;
-    unsigned long etherStatsUndersizePkts;
-    unsigned long etherStatsOversizePkts;
-    unsigned long etherStatsFragments;
-    unsigned long etherStatsJabbers;
-    unsigned long etherStatsCollisions;
-    unsigned long etherStatsPkt64Octets;
-    unsigned long etherStatsPkt65to127Octets;
-    unsigned long etherStatsPkt128to255Octets;
-    unsigned long etherStatsPkt256to511Octets;
-    unsigned long etherStatsPkt512to1023Octets;
-    unsigned long etherStatsPkt1024to1518Octets;
-    unsigned long etherStatsOwners;
-    unsigned long etherStatsStatus;
+	long    etherStatsIndex;
+	unsigned long etherStatsDataSource;
+	unsigned long etherStatsDropEvents;
+	unsigned long etherStatsOctets;
+	unsigned long etherStatsPkts;
+	unsigned long etherStatsBroadcastPkts;
+	unsigned long etherStatsMulticastPkts;
+	unsigned long etherStatsCRCAlignErrors;
+	unsigned long etherStatsUndersizePkts;
+	unsigned long etherStatsOversizePkts;
+	unsigned long etherStatsFragments;
+	unsigned long etherStatsJabbers;
+	unsigned long etherStatsCollisions;
+	unsigned long etherStatsPkt64Octets;
+	unsigned long etherStatsPkt65to127Octets;
+	unsigned long etherStatsPkt128to255Octets;
+	unsigned long etherStatsPkt256to511Octets;
+	unsigned long etherStatsPkt512to1023Octets;
+	unsigned long etherStatsPkt1024to1518Octets;
+	unsigned long etherStatsOwners;
+	unsigned long etherStatsStatus;
 } SRmonCounter, *PSRmonCounter;
 
 //
 // Custom counter
 //
 typedef struct tagSCustomCounters {
-    unsigned long Length;
-
-    unsigned long long   ullTsrAllOK;
-
-    unsigned long long   ullRsr11M;
-    unsigned long long   ullRsr5M;
-    unsigned long long   ullRsr2M;
-    unsigned long long   ullRsr1M;
-
-    unsigned long long   ullRsr11MCRCOk;
-    unsigned long long   ullRsr5MCRCOk;
-    unsigned long long   ullRsr2MCRCOk;
-    unsigned long long   ullRsr1MCRCOk;
-
-    unsigned long long   ullRsr54M;
-    unsigned long long   ullRsr48M;
-    unsigned long long   ullRsr36M;
-    unsigned long long   ullRsr24M;
-    unsigned long long   ullRsr18M;
-    unsigned long long   ullRsr12M;
-    unsigned long long   ullRsr9M;
-    unsigned long long   ullRsr6M;
-
-    unsigned long long   ullRsr54MCRCOk;
-    unsigned long long   ullRsr48MCRCOk;
-    unsigned long long   ullRsr36MCRCOk;
-    unsigned long long   ullRsr24MCRCOk;
-    unsigned long long   ullRsr18MCRCOk;
-    unsigned long long   ullRsr12MCRCOk;
-    unsigned long long   ullRsr9MCRCOk;
-    unsigned long long   ullRsr6MCRCOk;
-
+	unsigned long Length;
+
+	unsigned long long   ullTsrAllOK;
+
+	unsigned long long   ullRsr11M;
+	unsigned long long   ullRsr5M;
+	unsigned long long   ullRsr2M;
+	unsigned long long   ullRsr1M;
+
+	unsigned long long   ullRsr11MCRCOk;
+	unsigned long long   ullRsr5MCRCOk;
+	unsigned long long   ullRsr2MCRCOk;
+	unsigned long long   ullRsr1MCRCOk;
+
+	unsigned long long   ullRsr54M;
+	unsigned long long   ullRsr48M;
+	unsigned long long   ullRsr36M;
+	unsigned long long   ullRsr24M;
+	unsigned long long   ullRsr18M;
+	unsigned long long   ullRsr12M;
+	unsigned long long   ullRsr9M;
+	unsigned long long   ullRsr6M;
+
+	unsigned long long   ullRsr54MCRCOk;
+	unsigned long long   ullRsr48MCRCOk;
+	unsigned long long   ullRsr36MCRCOk;
+	unsigned long long   ullRsr24MCRCOk;
+	unsigned long long   ullRsr18MCRCOk;
+	unsigned long long   ullRsr12MCRCOk;
+	unsigned long long   ullRsr9MCRCOk;
+	unsigned long long   ullRsr6MCRCOk;
 } SCustomCounters, *PSCustomCounters;
 
-
 //
 // Custom counter
 //
 typedef struct tagSISRCounters {
-    unsigned long Length;
-
-    unsigned long dwIsrTx0OK;
-    unsigned long dwIsrAC0TxOK;
-    unsigned long dwIsrBeaconTxOK;
-    unsigned long dwIsrRx0OK;
-    unsigned long dwIsrTBTTInt;
-    unsigned long dwIsrSTIMERInt;
-    unsigned long dwIsrWatchDog;
-    unsigned long dwIsrUnrecoverableError;
-    unsigned long dwIsrSoftInterrupt;
-    unsigned long dwIsrMIBNearfull;
-    unsigned long dwIsrRxNoBuf;
-
-    unsigned long dwIsrUnknown;               // unknown interrupt count
-
-    unsigned long dwIsrRx1OK;
-    unsigned long dwIsrATIMTxOK;
-    unsigned long dwIsrSYNCTxOK;
-    unsigned long dwIsrCFPEnd;
-    unsigned long dwIsrATIMEnd;
-    unsigned long dwIsrSYNCFlushOK;
-    unsigned long dwIsrSTIMER1Int;
-    /////////////////////////////////////
+	unsigned long Length;
+
+	unsigned long dwIsrTx0OK;
+	unsigned long dwIsrAC0TxOK;
+	unsigned long dwIsrBeaconTxOK;
+	unsigned long dwIsrRx0OK;
+	unsigned long dwIsrTBTTInt;
+	unsigned long dwIsrSTIMERInt;
+	unsigned long dwIsrWatchDog;
+	unsigned long dwIsrUnrecoverableError;
+	unsigned long dwIsrSoftInterrupt;
+	unsigned long dwIsrMIBNearfull;
+	unsigned long dwIsrRxNoBuf;
+
+	unsigned long dwIsrUnknown;               // unknown interrupt count
+
+	unsigned long dwIsrRx1OK;
+	unsigned long dwIsrATIMTxOK;
+	unsigned long dwIsrSYNCTxOK;
+	unsigned long dwIsrCFPEnd;
+	unsigned long dwIsrATIMEnd;
+	unsigned long dwIsrSYNCFlushOK;
+	unsigned long dwIsrSTIMER1Int;
+	/////////////////////////////////////
 } SISRCounters, *PSISRCounters;
 
-
 // Value in the etherStatsStatus entry
 #define VALID               1           //
 #define CREATE_REQUEST      2           //
@@ -213,125 +208,122 @@ typedef struct tagSISRCounters {
 // statistic counter
 //
 typedef struct tagSStatCounter {
-    //
-    // ISR status count
-    //
-
-
-    // RSR status count
-    //
-    unsigned long dwRsrFrmAlgnErr;
-    unsigned long dwRsrErr;
-    unsigned long dwRsrCRCErr;
-    unsigned long dwRsrCRCOk;
-    unsigned long dwRsrBSSIDOk;
-    unsigned long dwRsrADDROk;
-    unsigned long dwRsrBCNSSIDOk;
-    unsigned long dwRsrLENErr;
-    unsigned long dwRsrTYPErr;
-
-    unsigned long dwNewRsrDECRYPTOK;
-    unsigned long dwNewRsrCFP;
-    unsigned long dwNewRsrUTSF;
-    unsigned long dwNewRsrHITAID;
-    unsigned long dwNewRsrHITAID0;
-
-    unsigned long dwRsrLong;
-    unsigned long dwRsrRunt;
-
-    unsigned long dwRsrRxControl;
-    unsigned long dwRsrRxData;
-    unsigned long dwRsrRxManage;
-
-    unsigned long dwRsrRxPacket;
-    unsigned long dwRsrRxOctet;
-    unsigned long dwRsrBroadcast;
-    unsigned long dwRsrMulticast;
-    unsigned long dwRsrDirected;
-    // 64-bit OID
-    unsigned long long   ullRsrOK;
-
-    // for some optional OIDs (64 bits) and DMI support
-    unsigned long long   ullRxBroadcastBytes;
-    unsigned long long   ullRxMulticastBytes;
-    unsigned long long   ullRxDirectedBytes;
-    unsigned long long   ullRxBroadcastFrames;
-    unsigned long long   ullRxMulticastFrames;
-    unsigned long long   ullRxDirectedFrames;
-
-    unsigned long dwRsrRxFragment;
-    unsigned long dwRsrRxFrmLen64;
-    unsigned long dwRsrRxFrmLen65_127;
-    unsigned long dwRsrRxFrmLen128_255;
-    unsigned long dwRsrRxFrmLen256_511;
-    unsigned long dwRsrRxFrmLen512_1023;
-    unsigned long dwRsrRxFrmLen1024_1518;
-
-    // TSR status count
-    //
-    unsigned long dwTsrTotalRetry[TYPE_MAXTD];        // total collision retry count
-    unsigned long dwTsrOnceRetry[TYPE_MAXTD];         // this packet only occur one collision
-    unsigned long dwTsrMoreThanOnceRetry[TYPE_MAXTD]; // this packet occur more than one collision
-    unsigned long dwTsrRetry[TYPE_MAXTD];             // this packet has ever occur collision,
-                                         // that is (dwTsrOnceCollision0 + dwTsrMoreThanOnceCollision0)
-    unsigned long dwTsrACKData[TYPE_MAXTD];
-    unsigned long dwTsrErr[TYPE_MAXTD];
-    unsigned long dwAllTsrOK[TYPE_MAXTD];
-    unsigned long dwTsrRetryTimeout[TYPE_MAXTD];
-    unsigned long dwTsrTransmitTimeout[TYPE_MAXTD];
-
-    unsigned long dwTsrTxPacket[TYPE_MAXTD];
-    unsigned long dwTsrTxOctet[TYPE_MAXTD];
-    unsigned long dwTsrBroadcast[TYPE_MAXTD];
-    unsigned long dwTsrMulticast[TYPE_MAXTD];
-    unsigned long dwTsrDirected[TYPE_MAXTD];
-
-    // RD/TD count
-    unsigned long dwCntRxFrmLength;
-    unsigned long dwCntTxBufLength;
-
-    unsigned char abyCntRxPattern[16];
-    unsigned char abyCntTxPattern[16];
-
-
-
-    // Software check....
-    unsigned long dwCntRxDataErr;             // rx buffer data software compare CRC err count
-    unsigned long dwCntDecryptErr;            // rx buffer data software compare CRC err count
-    unsigned long dwCntRxICVErr;              // rx buffer data software compare CRC err count
-    unsigned int idxRxErrorDesc[TYPE_MAXRD]; // index for rx data error RD
-
-    // 64-bit OID
-    unsigned long long   ullTsrOK[TYPE_MAXTD];
-
-    // for some optional OIDs (64 bits) and DMI support
-    unsigned long long   ullTxBroadcastFrames[TYPE_MAXTD];
-    unsigned long long   ullTxMulticastFrames[TYPE_MAXTD];
-    unsigned long long   ullTxDirectedFrames[TYPE_MAXTD];
-    unsigned long long   ullTxBroadcastBytes[TYPE_MAXTD];
-    unsigned long long   ullTxMulticastBytes[TYPE_MAXTD];
-    unsigned long long   ullTxDirectedBytes[TYPE_MAXTD];
+	//
+	// ISR status count
+	//
+
+	// RSR status count
+	//
+	unsigned long dwRsrFrmAlgnErr;
+	unsigned long dwRsrErr;
+	unsigned long dwRsrCRCErr;
+	unsigned long dwRsrCRCOk;
+	unsigned long dwRsrBSSIDOk;
+	unsigned long dwRsrADDROk;
+	unsigned long dwRsrBCNSSIDOk;
+	unsigned long dwRsrLENErr;
+	unsigned long dwRsrTYPErr;
+
+	unsigned long dwNewRsrDECRYPTOK;
+	unsigned long dwNewRsrCFP;
+	unsigned long dwNewRsrUTSF;
+	unsigned long dwNewRsrHITAID;
+	unsigned long dwNewRsrHITAID0;
+
+	unsigned long dwRsrLong;
+	unsigned long dwRsrRunt;
+
+	unsigned long dwRsrRxControl;
+	unsigned long dwRsrRxData;
+	unsigned long dwRsrRxManage;
+
+	unsigned long dwRsrRxPacket;
+	unsigned long dwRsrRxOctet;
+	unsigned long dwRsrBroadcast;
+	unsigned long dwRsrMulticast;
+	unsigned long dwRsrDirected;
+	// 64-bit OID
+	unsigned long long   ullRsrOK;
+
+	// for some optional OIDs (64 bits) and DMI support
+	unsigned long long   ullRxBroadcastBytes;
+	unsigned long long   ullRxMulticastBytes;
+	unsigned long long   ullRxDirectedBytes;
+	unsigned long long   ullRxBroadcastFrames;
+	unsigned long long   ullRxMulticastFrames;
+	unsigned long long   ullRxDirectedFrames;
+
+	unsigned long dwRsrRxFragment;
+	unsigned long dwRsrRxFrmLen64;
+	unsigned long dwRsrRxFrmLen65_127;
+	unsigned long dwRsrRxFrmLen128_255;
+	unsigned long dwRsrRxFrmLen256_511;
+	unsigned long dwRsrRxFrmLen512_1023;
+	unsigned long dwRsrRxFrmLen1024_1518;
+
+	// TSR status count
+	//
+	unsigned long dwTsrTotalRetry[TYPE_MAXTD];        // total collision retry count
+	unsigned long dwTsrOnceRetry[TYPE_MAXTD];         // this packet only occur one collision
+	unsigned long dwTsrMoreThanOnceRetry[TYPE_MAXTD]; // this packet occur more than one collision
+	unsigned long dwTsrRetry[TYPE_MAXTD];             // this packet has ever occur collision,
+	// that is (dwTsrOnceCollision0 + dwTsrMoreThanOnceCollision0)
+	unsigned long dwTsrACKData[TYPE_MAXTD];
+	unsigned long dwTsrErr[TYPE_MAXTD];
+	unsigned long dwAllTsrOK[TYPE_MAXTD];
+	unsigned long dwTsrRetryTimeout[TYPE_MAXTD];
+	unsigned long dwTsrTransmitTimeout[TYPE_MAXTD];
+
+	unsigned long dwTsrTxPacket[TYPE_MAXTD];
+	unsigned long dwTsrTxOctet[TYPE_MAXTD];
+	unsigned long dwTsrBroadcast[TYPE_MAXTD];
+	unsigned long dwTsrMulticast[TYPE_MAXTD];
+	unsigned long dwTsrDirected[TYPE_MAXTD];
+
+	// RD/TD count
+	unsigned long dwCntRxFrmLength;
+	unsigned long dwCntTxBufLength;
+
+	unsigned char abyCntRxPattern[16];
+	unsigned char abyCntTxPattern[16];
+
+	// Software check....
+	unsigned long dwCntRxDataErr;             // rx buffer data software compare CRC err count
+	unsigned long dwCntDecryptErr;            // rx buffer data software compare CRC err count
+	unsigned long dwCntRxICVErr;              // rx buffer data software compare CRC err count
+	unsigned int idxRxErrorDesc[TYPE_MAXRD]; // index for rx data error RD
+
+	// 64-bit OID
+	unsigned long long   ullTsrOK[TYPE_MAXTD];
+
+	// for some optional OIDs (64 bits) and DMI support
+	unsigned long long   ullTxBroadcastFrames[TYPE_MAXTD];
+	unsigned long long   ullTxMulticastFrames[TYPE_MAXTD];
+	unsigned long long   ullTxDirectedFrames[TYPE_MAXTD];
+	unsigned long long   ullTxBroadcastBytes[TYPE_MAXTD];
+	unsigned long long   ullTxMulticastBytes[TYPE_MAXTD];
+	unsigned long long   ullTxDirectedBytes[TYPE_MAXTD];
 
 //    unsigned long dwTxRetryCount[8];
-    //
-    // ISR status count
-    //
-    SISRCounters ISRStat;
-
-    SCustomCounters CustomStat;
-
-   #ifdef Calcu_LinkQual
-       //Tx count:
-    unsigned long TxNoRetryOkCount;         //success tx no retry !
-    unsigned long TxRetryOkCount;              //success tx but retry !
-    unsigned long TxFailCount;                      //fail tx ?
-      //Rx count:
-    unsigned long RxOkCnt;                          //success rx !
-    unsigned long RxFcsErrCnt;                    //fail rx ?
-      //statistic
-    unsigned long SignalStren;
-    unsigned long LinkQuality;
-   #endif
+	//
+	// ISR status count
+	//
+	SISRCounters ISRStat;
+
+	SCustomCounters CustomStat;
+
+#ifdef Calcu_LinkQual
+	//Tx count:
+	unsigned long TxNoRetryOkCount;         //success tx no retry !
+	unsigned long TxRetryOkCount;              //success tx but retry !
+	unsigned long TxFailCount;                      //fail tx ?
+	//Rx count:
+	unsigned long RxOkCnt;                          //success rx !
+	unsigned long RxFcsErrCnt;                    //fail rx ?
+	//statistic
+	unsigned long SignalStren;
+	unsigned long LinkQuality;
+#endif
 } SStatCounter, *PSStatCounter;
 
 /*---------------------  Export Classes  ----------------------------*/
@@ -345,31 +337,28 @@ void STAvClearAllCounter(PSStatCounter pStatistic);
 void STAvUpdateIsrStatCounter(PSStatCounter pStatistic, unsigned long dwIsr);
 
 void STAvUpdateRDStatCounter(PSStatCounter pStatistic,
-                              unsigned char byRSR, unsigned char byNewRSR, unsigned char byRxRate,
-                              unsigned char *pbyBuffer, unsigned int cbFrameLength);
+			     unsigned char byRSR, unsigned char byNewRSR, unsigned char byRxRate,
+			     unsigned char *pbyBuffer, unsigned int cbFrameLength);
 
 void STAvUpdateRDStatCounterEx(PSStatCounter pStatistic,
-                              unsigned char byRSR, unsigned char byNewRsr, unsigned char byRxRate,
-                              unsigned char *pbyBuffer, unsigned int cbFrameLength);
+			       unsigned char byRSR, unsigned char byNewRsr, unsigned char byRxRate,
+			       unsigned char *pbyBuffer, unsigned int cbFrameLength);
 
 void STAvUpdateTDStatCounter(PSStatCounter pStatistic, unsigned char byTSR0, unsigned char byTSR1,
-		unsigned char *pbyBuffer, unsigned int cbFrameLength, unsigned int uIdx);
+			     unsigned char *pbyBuffer, unsigned int cbFrameLength, unsigned int uIdx);
 
 void STAvUpdateTDStatCounterEx(
-    PSStatCounter   pStatistic,
-    unsigned char *pbyBuffer,
-    unsigned long cbFrameLength
-    );
+	PSStatCounter   pStatistic,
+	unsigned char *pbyBuffer,
+	unsigned long cbFrameLength
+);
 
 void STAvUpdate802_11Counter(
-    PSDot11Counters p802_11Counter,
-    PSStatCounter   pStatistic,
-    unsigned long dwCounter
-    );
+	PSDot11Counters p802_11Counter,
+	PSStatCounter   pStatistic,
+	unsigned long dwCounter
+);
 
 void STAvClear802_11Counter(PSDot11Counters p802_11Counter);
 
 #endif // __MIB_H__
-
-
-
diff --git a/drivers/staging/vt6655/michael.c b/drivers/staging/vt6655/michael.c
index 67618f0..7ea5f7f 100644
--- a/drivers/staging/vt6655/michael.c
+++ b/drivers/staging/vt6655/michael.c
@@ -48,11 +48,11 @@
 
 /*---------------------  Static Functions  --------------------------*/
 /*
-static unsigned long s_dwGetUINT32(unsigned char *p);         // Get unsigned long from 4 bytes LSByte first
-static void s_vPutUINT32(unsigned char *p, unsigned long val); // Put unsigned long into 4 bytes LSByte first
+  static unsigned long s_dwGetUINT32(unsigned char *p);         // Get unsigned long from 4 bytes LSByte first
+  static void s_vPutUINT32(unsigned char *p, unsigned long val); // Put unsigned long into 4 bytes LSByte first
 */
 static void s_vClear(void);                       // Clear the internal message,
-                                              // resets the object to the state just after construction.
+// resets the object to the state just after construction.
 static void s_vSetKey(unsigned long dwK0, unsigned long dwK1);
 static void s_vAppendByte(unsigned char b);            // Add a single byte to the internal message
 
@@ -66,116 +66,110 @@ static unsigned int nBytesInM;      // # bytes in M
 /*---------------------  Export Functions  --------------------------*/
 
 /*
-static unsigned long s_dwGetUINT32 (unsigned char *p)
+  static unsigned long s_dwGetUINT32 (unsigned char *p)
 // Convert from unsigned char [] to unsigned long in a portable way
 {
-    unsigned long res = 0;
-    unsigned int i;
-    for(i=0; i<4; i++ )
-    {
-        res |= (*p++) << (8*i);
-    }
-    return res;
+unsigned long res = 0;
+unsigned int i;
+for (i=0; i<4; i++)
+{
+	res |= (*p++) << (8 * i);
+}
+return res;
 }
 
 static void s_vPutUINT32 (unsigned char *p, unsigned long val)
 // Convert from unsigned long to unsigned char [] in a portable way
 {
-    unsigned int i;
-    for(i=0; i<4; i++ )
-    {
-        *p++ = (unsigned char) (val & 0xff);
-        val >>= 8;
-    }
+	unsigned int i;
+	for (i=0; i<4; i++) {
+		*p++ = (unsigned char) (val & 0xff);
+		val >>= 8;
+	}
 }
 */
 
-static void s_vClear (void)
+static void s_vClear(void)
 {
-    // Reset the state to the empty message.
-    L = K0;
-    R = K1;
-    nBytesInM = 0;
-    M = 0;
+	// Reset the state to the empty message.
+	L = K0;
+	R = K1;
+	nBytesInM = 0;
+	M = 0;
 }
 
-static void s_vSetKey (unsigned long dwK0, unsigned long dwK1)
+static void s_vSetKey(unsigned long dwK0, unsigned long dwK1)
 {
-    // Set the key
-    K0 = dwK0;
-    K1 = dwK1;
-    // and reset the message
-    s_vClear();
+	// Set the key
+	K0 = dwK0;
+	K1 = dwK1;
+	// and reset the message
+	s_vClear();
 }
 
-static void s_vAppendByte (unsigned char b)
+static void s_vAppendByte(unsigned char b)
 {
-    // Append the byte to our word-sized buffer
-    M |= b << (8*nBytesInM);
-    nBytesInM++;
-    // Process the word if it is full.
-    if( nBytesInM >= 4 )
-    {
-        L ^= M;
-        R ^= ROL32( L, 17 );
-        L += R;
-        R ^= ((L & 0xff00ff00) >> 8) | ((L & 0x00ff00ff) << 8);
-        L += R;
-        R ^= ROL32( L, 3 );
-        L += R;
-        R ^= ROR32( L, 2 );
-        L += R;
-        // Clear the buffer
-        M = 0;
-        nBytesInM = 0;
-    }
+	// Append the byte to our word-sized buffer
+	M |= b << (8*nBytesInM);
+	nBytesInM++;
+	// Process the word if it is full.
+	if (nBytesInM >= 4) {
+		L ^= M;
+		R ^= ROL32(L, 17);
+		L += R;
+		R ^= ((L & 0xff00ff00) >> 8) | ((L & 0x00ff00ff) << 8);
+		L += R;
+		R ^= ROL32(L, 3);
+		L += R;
+		R ^= ROR32(L, 2);
+		L += R;
+		// Clear the buffer
+		M = 0;
+		nBytesInM = 0;
+	}
 }
 
-void MIC_vInit (unsigned long dwK0, unsigned long dwK1)
+void MIC_vInit(unsigned long dwK0, unsigned long dwK1)
 {
-    // Set the key
-    s_vSetKey(dwK0, dwK1);
+	// Set the key
+	s_vSetKey(dwK0, dwK1);
 }
 
-
-void MIC_vUnInit (void)
+void MIC_vUnInit(void)
 {
-    // Wipe the key material
-    K0 = 0;
-    K1 = 0;
+	// Wipe the key material
+	K0 = 0;
+	K1 = 0;
 
-    // And the other fields as well.
-    //Note that this sets (L,R) to (K0,K1) which is just fine.
-    s_vClear();
+	// And the other fields as well.
+	//Note that this sets (L,R) to (K0,K1) which is just fine.
+	s_vClear();
 }
 
-void MIC_vAppend (unsigned char *src, unsigned int nBytes)
+void MIC_vAppend(unsigned char *src, unsigned int nBytes)
 {
-    // This is simple
-    while (nBytes > 0)
-    {
-        s_vAppendByte(*src++);
-        nBytes--;
-    }
+	// This is simple
+	while (nBytes > 0) {
+		s_vAppendByte(*src++);
+		nBytes--;
+	}
 }
 
-void MIC_vGetMIC (unsigned long *pdwL, unsigned long *pdwR)
+void MIC_vGetMIC(unsigned long *pdwL, unsigned long *pdwR)
 {
-    // Append the minimum padding
-    s_vAppendByte(0x5a);
-    s_vAppendByte(0);
-    s_vAppendByte(0);
-    s_vAppendByte(0);
-    s_vAppendByte(0);
-    // and then zeroes until the length is a multiple of 4
-    while( nBytesInM != 0 )
-    {
-        s_vAppendByte(0);
-    }
-    // The s_vAppendByte function has already computed the result.
-    *pdwL = L;
-    *pdwR = R;
-    // Reset to the empty message.
-    s_vClear();
+	// Append the minimum padding
+	s_vAppendByte(0x5a);
+	s_vAppendByte(0);
+	s_vAppendByte(0);
+	s_vAppendByte(0);
+	s_vAppendByte(0);
+	// and then zeroes until the length is a multiple of 4
+	while (nBytesInM != 0) {
+		s_vAppendByte(0);
+	}
+	// The s_vAppendByte function has already computed the result.
+	*pdwL = L;
+	*pdwR = R;
+	// Reset to the empty message.
+	s_vClear();
 }
-
diff --git a/drivers/staging/vt6655/michael.h b/drivers/staging/vt6655/michael.h
index 3131b16..0828d18 100644
--- a/drivers/staging/vt6655/michael.h
+++ b/drivers/staging/vt6655/michael.h
@@ -49,10 +49,8 @@ void MIC_vGetMIC(unsigned long *pdwL, unsigned long *pdwR);
 /*---------------------  Export Macros ------------------------------*/
 
 // Rotation functions on 32 bit values
-#define ROL32( A, n ) \
- ( ((A) << (n)) | ( ((A)>>(32-(n)))  & ( (1UL << (n)) - 1 ) ) )
-#define ROR32( A, n ) ROL32( (A), 32-(n) )
+#define ROL32(A, n)							\
+	(((A) << (n)) | (((A)>>(32-(n)))  & ((1UL << (n)) - 1)))
+#define ROR32(A, n) ROL32((A), 32-(n))
 
 #endif //__MICHAEL_H__
-
-
diff --git a/drivers/staging/vt6655/power.c b/drivers/staging/vt6655/power.c
index 661d534..2340d2f 100644
--- a/drivers/staging/vt6655/power.c
+++ b/drivers/staging/vt6655/power.c
@@ -48,19 +48,14 @@
 
 /*---------------------  Static Definitions -------------------------*/
 
-
-
-
 /*---------------------  Static Classes  ----------------------------*/
 
 /*---------------------  Static Variables  --------------------------*/
-static int          msglevel                =MSG_LEVEL_INFO;
+static int msglevel = MSG_LEVEL_INFO;
 /*---------------------  Static Functions  --------------------------*/
 
-
 /*---------------------  Export Variables  --------------------------*/
 
-
 /*---------------------  Export Functions  --------------------------*/
 
 /*+
@@ -71,69 +66,62 @@ static int          msglevel                =MSG_LEVEL_INFO;
  * Return Value:
  *    None.
  *
--*/
-
+ -*/
 
 void
 PSvEnablePowerSaving(
-    void *hDeviceContext,
-    unsigned short wListenInterval
-    )
+	void *hDeviceContext,
+	unsigned short wListenInterval
+)
 {
-    PSDevice        pDevice = (PSDevice)hDeviceContext;
-    PSMgmtObject    pMgmt = pDevice->pMgmt;
-    unsigned short wAID = pMgmt->wCurrAID | BIT14 | BIT15;
-
-    // set period of power up before TBTT
-    VNSvOutPortW(pDevice->PortOffset + MAC_REG_PWBT, C_PWBT);
-    if (pDevice->eOPMode != OP_MODE_ADHOC) {
-        // set AID
-        VNSvOutPortW(pDevice->PortOffset + MAC_REG_AIDATIM, wAID);
-    } else {
-    	// set ATIM Window
-        MACvWriteATIMW(pDevice->PortOffset, pMgmt->wCurrATIMWindow);
-    }
-    // Set AutoSleep
-    MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCFG, PSCFG_AUTOSLEEP);
-    // Set HWUTSF
-    MACvRegBitsOn(pDevice->PortOffset, MAC_REG_TFTCTL, TFTCTL_HWUTSF);
-
-    if (wListenInterval >= 2) {
-        // clear always listen beacon
-        MACvRegBitsOff(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_ALBCN);
-        //pDevice->wCFG &= ~CFG_ALB;
-        // first time set listen next beacon
-        MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_LNBCN);
-        pMgmt->wCountToWakeUp = wListenInterval;
-    }
-    else {
-        // always listen beacon
-        MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_ALBCN);
-        //pDevice->wCFG |= CFG_ALB;
-        pMgmt->wCountToWakeUp = 0;
-    }
-
-    // enable power saving hw function
-    MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_PSEN);
-    pDevice->bEnablePSMode = true;
-
-    if (pDevice->eOPMode == OP_MODE_ADHOC) {
+	PSDevice        pDevice = (PSDevice)hDeviceContext;
+	PSMgmtObject    pMgmt = pDevice->pMgmt;
+	unsigned short wAID = pMgmt->wCurrAID | BIT14 | BIT15;
+
+	// set period of power up before TBTT
+	VNSvOutPortW(pDevice->PortOffset + MAC_REG_PWBT, C_PWBT);
+	if (pDevice->eOPMode != OP_MODE_ADHOC) {
+		// set AID
+		VNSvOutPortW(pDevice->PortOffset + MAC_REG_AIDATIM, wAID);
+	} else {
+		// set ATIM Window
+		MACvWriteATIMW(pDevice->PortOffset, pMgmt->wCurrATIMWindow);
+	}
+	// Set AutoSleep
+	MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCFG, PSCFG_AUTOSLEEP);
+	// Set HWUTSF
+	MACvRegBitsOn(pDevice->PortOffset, MAC_REG_TFTCTL, TFTCTL_HWUTSF);
+
+	if (wListenInterval >= 2) {
+		// clear always listen beacon
+		MACvRegBitsOff(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_ALBCN);
+		//pDevice->wCFG &= ~CFG_ALB;
+		// first time set listen next beacon
+		MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_LNBCN);
+		pMgmt->wCountToWakeUp = wListenInterval;
+	} else {
+		// always listen beacon
+		MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_ALBCN);
+		//pDevice->wCFG |= CFG_ALB;
+		pMgmt->wCountToWakeUp = 0;
+	}
+
+	// enable power saving hw function
+	MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_PSEN);
+	pDevice->bEnablePSMode = true;
+
+	if (pDevice->eOPMode == OP_MODE_ADHOC) {
 //        bMgrPrepareBeaconToSend((void *)pDevice, pMgmt);
-    }
-    // We don't send null pkt in ad hoc mode since beacon will handle this.
-    else if (pDevice->eOPMode == OP_MODE_INFRASTRUCTURE) {
-        PSbSendNullPacket(pDevice);
-    }
-    pDevice->bPWBitOn = true;
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "PS:Power Saving Mode Enable... \n");
-    return;
+	}
+	// We don't send null pkt in ad hoc mode since beacon will handle this.
+	else if (pDevice->eOPMode == OP_MODE_INFRASTRUCTURE) {
+		PSbSendNullPacket(pDevice);
+	}
+	pDevice->bPWBitOn = true;
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "PS:Power Saving Mode Enable... \n");
+	return;
 }
 
-
-
-
-
-
 /*+
  *
  * Routine Description:
@@ -142,35 +130,34 @@ PSvEnablePowerSaving(
  * Return Value:
  *    None.
  *
--*/
+ -*/
 
 void
 PSvDisablePowerSaving(
-    void *hDeviceContext
-    )
+	void *hDeviceContext
+)
 {
-    PSDevice        pDevice = (PSDevice)hDeviceContext;
+	PSDevice        pDevice = (PSDevice)hDeviceContext;
 //    PSMgmtObject    pMgmt = pDevice->pMgmt;
 
-    // disable power saving hw function
-    MACbPSWakeup(pDevice->PortOffset);
-    //clear AutoSleep
-    MACvRegBitsOff(pDevice->PortOffset, MAC_REG_PSCFG, PSCFG_AUTOSLEEP);
-    //clear HWUTSF
-    MACvRegBitsOff(pDevice->PortOffset, MAC_REG_TFTCTL, TFTCTL_HWUTSF);
-    // set always listen beacon
-    MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_ALBCN);
-
-    pDevice->bEnablePSMode = false;
-
-    if (pDevice->eOPMode == OP_MODE_INFRASTRUCTURE) {
-        PSbSendNullPacket(pDevice);
-    }
-    pDevice->bPWBitOn = false;
-    return;
+	// disable power saving hw function
+	MACbPSWakeup(pDevice->PortOffset);
+	//clear AutoSleep
+	MACvRegBitsOff(pDevice->PortOffset, MAC_REG_PSCFG, PSCFG_AUTOSLEEP);
+	//clear HWUTSF
+	MACvRegBitsOff(pDevice->PortOffset, MAC_REG_TFTCTL, TFTCTL_HWUTSF);
+	// set always listen beacon
+	MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_ALBCN);
+
+	pDevice->bEnablePSMode = false;
+
+	if (pDevice->eOPMode == OP_MODE_INFRASTRUCTURE) {
+		PSbSendNullPacket(pDevice);
+	}
+	pDevice->bPWBitOn = false;
+	return;
 }
 
-
 /*+
  *
  * Routine Description:
@@ -179,65 +166,62 @@ PSvDisablePowerSaving(
  * Return Value:
  *    true, if power down success
  *    false, if fail
--*/
-
+ -*/
 
 bool
 PSbConsiderPowerDown(
-    void *hDeviceContext,
-    bool bCheckRxDMA,
-    bool bCheckCountToWakeUp
-    )
+	void *hDeviceContext,
+	bool bCheckRxDMA,
+	bool bCheckCountToWakeUp
+)
 {
-    PSDevice        pDevice = (PSDevice)hDeviceContext;
-    PSMgmtObject    pMgmt = pDevice->pMgmt;
-    unsigned int uIdx;
-
-    // check if already in Doze mode
-    if (MACbIsRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_PS))
-        return true;
-
-    if (pMgmt->eCurrMode != WMAC_MODE_IBSS_STA) {
-        // check if in TIM wake period
-        if (pMgmt->bInTIMWake)
-            return false;
-    }
-
-    // check scan state
-    if (pDevice->bCmdRunning)
-        return false;
-
-    // Force PSEN on
-    MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_PSEN);
-
-    // check if all TD are empty,
-    for (uIdx = 0; uIdx < TYPE_MAXTD; uIdx ++) {
-        if (pDevice->iTDUsed[uIdx] != 0)
-            return false;
-    }
-
-    // check if rx isr is clear
-    if (bCheckRxDMA &&
-        ((pDevice->dwIsr& ISR_RXDMA0) != 0) &&
-        ((pDevice->dwIsr & ISR_RXDMA1) != 0)){
-        return false;
-    }
-
-    if (pMgmt->eCurrMode != WMAC_MODE_IBSS_STA) {
-        if (bCheckCountToWakeUp &&
-           (pMgmt->wCountToWakeUp == 0 || pMgmt->wCountToWakeUp == 1)) {
-             return false;
-        }
-    }
-
-    // no Tx, no Rx isr, now go to Doze
-    MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_GO2DOZE);
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Go to Doze ZZZZZZZZZZZZZZZ\n");
-    return true;
+	PSDevice        pDevice = (PSDevice)hDeviceContext;
+	PSMgmtObject    pMgmt = pDevice->pMgmt;
+	unsigned int uIdx;
+
+	// check if already in Doze mode
+	if (MACbIsRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_PS))
+		return true;
+
+	if (pMgmt->eCurrMode != WMAC_MODE_IBSS_STA) {
+		// check if in TIM wake period
+		if (pMgmt->bInTIMWake)
+			return false;
+	}
+
+	// check scan state
+	if (pDevice->bCmdRunning)
+		return false;
+
+	// Force PSEN on
+	MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_PSEN);
+
+	// check if all TD are empty,
+	for (uIdx = 0; uIdx < TYPE_MAXTD; uIdx++) {
+		if (pDevice->iTDUsed[uIdx] != 0)
+			return false;
+	}
+
+	// check if rx isr is clear
+	if (bCheckRxDMA &&
+	    ((pDevice->dwIsr & ISR_RXDMA0) != 0) &&
+	    ((pDevice->dwIsr & ISR_RXDMA1) != 0)) {
+		return false;
+	}
+
+	if (pMgmt->eCurrMode != WMAC_MODE_IBSS_STA) {
+		if (bCheckCountToWakeUp &&
+		    (pMgmt->wCountToWakeUp == 0 || pMgmt->wCountToWakeUp == 1)) {
+			return false;
+		}
+	}
+
+	// no Tx, no Rx isr, now go to Doze
+	MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_GO2DOZE);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Go to Doze ZZZZZZZZZZZZZZZ\n");
+	return true;
 }
 
-
-
 /*+
  *
  * Routine Description:
@@ -246,47 +230,41 @@ PSbConsiderPowerDown(
  * Return Value:
  *    None.
  *
--*/
-
-
+ -*/
 
 void
 PSvSendPSPOLL(
-    void *hDeviceContext
-    )
+	void *hDeviceContext
+)
 {
-    PSDevice            pDevice = (PSDevice)hDeviceContext;
-    PSMgmtObject        pMgmt = pDevice->pMgmt;
-    PSTxMgmtPacket      pTxPacket = NULL;
-
-
-    memset(pMgmt->pbyPSPacketPool, 0, sizeof(STxMgmtPacket) + WLAN_HDR_ADDR2_LEN);
-    pTxPacket = (PSTxMgmtPacket)pMgmt->pbyPSPacketPool;
-    pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket));
-    pTxPacket->p80211Header->sA2.wFrameCtl = cpu_to_le16(
-         (
-         WLAN_SET_FC_FTYPE(WLAN_TYPE_CTL) |
-         WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_PSPOLL) |
-         WLAN_SET_FC_PWRMGT(0)
-         ));
-    pTxPacket->p80211Header->sA2.wDurationID = pMgmt->wCurrAID | BIT14 | BIT15;
-    memcpy(pTxPacket->p80211Header->sA2.abyAddr1, pMgmt->abyCurrBSSID, WLAN_ADDR_LEN);
-    memcpy(pTxPacket->p80211Header->sA2.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN);
-    pTxPacket->cbMPDULen = WLAN_HDR_ADDR2_LEN;
-    pTxPacket->cbPayloadLen = 0;
-    // send the frame
-    if (csMgmt_xmit(pDevice, pTxPacket) != CMD_STATUS_PENDING) {
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Send PS-Poll packet failed..\n");
-    }
-    else {
+	PSDevice            pDevice = (PSDevice)hDeviceContext;
+	PSMgmtObject        pMgmt = pDevice->pMgmt;
+	PSTxMgmtPacket      pTxPacket = NULL;
+
+	memset(pMgmt->pbyPSPacketPool, 0, sizeof(STxMgmtPacket) + WLAN_HDR_ADDR2_LEN);
+	pTxPacket = (PSTxMgmtPacket)pMgmt->pbyPSPacketPool;
+	pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket));
+	pTxPacket->p80211Header->sA2.wFrameCtl = cpu_to_le16(
+		(
+			WLAN_SET_FC_FTYPE(WLAN_TYPE_CTL) |
+			WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_PSPOLL) |
+			WLAN_SET_FC_PWRMGT(0)
+));
+	pTxPacket->p80211Header->sA2.wDurationID = pMgmt->wCurrAID | BIT14 | BIT15;
+	memcpy(pTxPacket->p80211Header->sA2.abyAddr1, pMgmt->abyCurrBSSID, WLAN_ADDR_LEN);
+	memcpy(pTxPacket->p80211Header->sA2.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN);
+	pTxPacket->cbMPDULen = WLAN_HDR_ADDR2_LEN;
+	pTxPacket->cbPayloadLen = 0;
+	// send the frame
+	if (csMgmt_xmit(pDevice, pTxPacket) != CMD_STATUS_PENDING) {
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Send PS-Poll packet failed..\n");
+	} else {
 //        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Send PS-Poll packet success..\n");
-    };
+	};
 
-    return;
+	return;
 }
 
-
-
 /*+
  *
  * Routine Description:
@@ -295,81 +273,75 @@ PSvSendPSPOLL(
  * Return Value:
  *    None.
  *
--*/
+ -*/
 bool
 PSbSendNullPacket(
-    void *hDeviceContext
-    )
+	void *hDeviceContext
+)
 {
-    PSDevice            pDevice = (PSDevice)hDeviceContext;
-    PSTxMgmtPacket      pTxPacket = NULL;
-    PSMgmtObject        pMgmt = pDevice->pMgmt;
-    unsigned int uIdx;
-
-
-    if (pDevice->bLinkPass == false) {
-        return false;
-    }
-    #ifdef TxInSleep
-     if ((pDevice->bEnablePSMode == false) &&
-	  (pDevice->fTxDataInSleep == false)){
-        return false;
-    }
+	PSDevice            pDevice = (PSDevice)hDeviceContext;
+	PSTxMgmtPacket      pTxPacket = NULL;
+	PSMgmtObject        pMgmt = pDevice->pMgmt;
+	unsigned int uIdx;
+
+	if (pDevice->bLinkPass == false) {
+		return false;
+	}
+#ifdef TxInSleep
+	if ((pDevice->bEnablePSMode == false) &&
+	    (pDevice->fTxDataInSleep == false)) {
+		return false;
+	}
 #else
-    if (pDevice->bEnablePSMode == false) {
-        return false;
-    }
+	if (pDevice->bEnablePSMode == false) {
+		return false;
+	}
 #endif
-    if (pDevice->bEnablePSMode) {
-        for (uIdx = 0; uIdx < TYPE_MAXTD; uIdx ++) {
-            if (pDevice->iTDUsed[uIdx] != 0)
-                return false;
-        }
-    }
-
-    memset(pMgmt->pbyPSPacketPool, 0, sizeof(STxMgmtPacket) + WLAN_NULLDATA_FR_MAXLEN);
-    pTxPacket = (PSTxMgmtPacket)pMgmt->pbyPSPacketPool;
-    pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket));
-
-    if (pDevice->bEnablePSMode) {
-
-        pTxPacket->p80211Header->sA3.wFrameCtl = cpu_to_le16(
-             (
-            WLAN_SET_FC_FTYPE(WLAN_TYPE_DATA) |
-            WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_NULL) |
-            WLAN_SET_FC_PWRMGT(1)
-            ));
-    }
-    else {
-        pTxPacket->p80211Header->sA3.wFrameCtl = cpu_to_le16(
-             (
-            WLAN_SET_FC_FTYPE(WLAN_TYPE_DATA) |
-            WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_NULL) |
-            WLAN_SET_FC_PWRMGT(0)
-            ));
-    }
-
-    if(pMgmt->eCurrMode != WMAC_MODE_IBSS_STA) {
-        pTxPacket->p80211Header->sA3.wFrameCtl |= cpu_to_le16((unsigned short)WLAN_SET_FC_TODS(1));
-    }
-
-    memcpy(pTxPacket->p80211Header->sA3.abyAddr1, pMgmt->abyCurrBSSID, WLAN_ADDR_LEN);
-    memcpy(pTxPacket->p80211Header->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN);
-    memcpy(pTxPacket->p80211Header->sA3.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN);
-    pTxPacket->cbMPDULen = WLAN_HDR_ADDR3_LEN;
-    pTxPacket->cbPayloadLen = 0;
-    // send the frame
-    if (csMgmt_xmit(pDevice, pTxPacket) != CMD_STATUS_PENDING) {
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Send Null Packet failed !\n");
-        return false;
-    }
-    else {
-
+	if (pDevice->bEnablePSMode) {
+		for (uIdx = 0; uIdx < TYPE_MAXTD; uIdx++) {
+			if (pDevice->iTDUsed[uIdx] != 0)
+				return false;
+		}
+	}
+
+	memset(pMgmt->pbyPSPacketPool, 0, sizeof(STxMgmtPacket) + WLAN_NULLDATA_FR_MAXLEN);
+	pTxPacket = (PSTxMgmtPacket)pMgmt->pbyPSPacketPool;
+	pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket));
+
+	if (pDevice->bEnablePSMode) {
+		pTxPacket->p80211Header->sA3.wFrameCtl = cpu_to_le16(
+			(
+				WLAN_SET_FC_FTYPE(WLAN_TYPE_DATA) |
+				WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_NULL) |
+				WLAN_SET_FC_PWRMGT(1)
+));
+	} else {
+		pTxPacket->p80211Header->sA3.wFrameCtl = cpu_to_le16(
+			(
+				WLAN_SET_FC_FTYPE(WLAN_TYPE_DATA) |
+				WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_NULL) |
+				WLAN_SET_FC_PWRMGT(0)
+));
+	}
+
+	if (pMgmt->eCurrMode != WMAC_MODE_IBSS_STA) {
+		pTxPacket->p80211Header->sA3.wFrameCtl |= cpu_to_le16((unsigned short)WLAN_SET_FC_TODS(1));
+	}
+
+	memcpy(pTxPacket->p80211Header->sA3.abyAddr1, pMgmt->abyCurrBSSID, WLAN_ADDR_LEN);
+	memcpy(pTxPacket->p80211Header->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN);
+	memcpy(pTxPacket->p80211Header->sA3.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN);
+	pTxPacket->cbMPDULen = WLAN_HDR_ADDR3_LEN;
+	pTxPacket->cbPayloadLen = 0;
+	// send the frame
+	if (csMgmt_xmit(pDevice, pTxPacket) != CMD_STATUS_PENDING) {
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Send Null Packet failed !\n");
+		return false;
+	} else {
 //            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Send Null Packet success....\n");
-    }
-
+	}
 
-    return true ;
+	return true;
 }
 
 /*+
@@ -380,33 +352,31 @@ PSbSendNullPacket(
  * Return Value:
  *    None.
  *
--*/
+ -*/
 
 bool
 PSbIsNextTBTTWakeUp(
-    void *hDeviceContext
-    )
+	void *hDeviceContext
+)
 {
+	PSDevice         pDevice = (PSDevice)hDeviceContext;
+	PSMgmtObject        pMgmt = pDevice->pMgmt;
+	bool bWakeUp = false;
 
-    PSDevice         pDevice = (PSDevice)hDeviceContext;
-    PSMgmtObject        pMgmt = pDevice->pMgmt;
-    bool bWakeUp = false;
+	if (pMgmt->wListenInterval >= 2) {
+		if (pMgmt->wCountToWakeUp == 0) {
+			pMgmt->wCountToWakeUp = pMgmt->wListenInterval;
+		}
 
-    if (pMgmt->wListenInterval >= 2) {
-        if (pMgmt->wCountToWakeUp == 0) {
-            pMgmt->wCountToWakeUp = pMgmt->wListenInterval;
-        }
+		pMgmt->wCountToWakeUp--;
 
-        pMgmt->wCountToWakeUp --;
+		if (pMgmt->wCountToWakeUp == 1) {
+			// Turn on wake up to listen next beacon
+			MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_LNBCN);
+			bWakeUp = true;
+		}
 
-        if (pMgmt->wCountToWakeUp == 1) {
-            // Turn on wake up to listen next beacon
-            MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_LNBCN);
-            bWakeUp = true;
-        }
+	}
 
-    }
-
-    return bWakeUp;
+	return bWakeUp;
 }
-
diff --git a/drivers/staging/vt6655/power.h b/drivers/staging/vt6655/power.h
index 01013b5..337dd65 100644
--- a/drivers/staging/vt6655/power.h
+++ b/drivers/staging/vt6655/power.h
@@ -29,7 +29,6 @@
 #ifndef __POWER_H__
 #define __POWER_H__
 
-
 /*---------------------  Export Definitions -------------------------*/
 #define     C_PWBT                   1000      // micro sec. power up before TBTT
 #define     PS_FAST_INTERVAL         1         // Fast power saving listen interval
@@ -39,10 +38,8 @@
 
 /*---------------------  Export Variables  --------------------------*/
 
-
 /*---------------------  Export Types  ------------------------------*/
 
-
 /*---------------------  Export Functions  --------------------------*/
 
 // PSDevice pDevice
@@ -50,35 +47,35 @@
 
 bool
 PSbConsiderPowerDown(
-    void *hDeviceContext,
-    bool bCheckRxDMA,
-    bool bCheckCountToWakeUp
-    );
+	void *hDeviceContext,
+	bool bCheckRxDMA,
+	bool bCheckCountToWakeUp
+);
 
 void
 PSvDisablePowerSaving(
-    void *hDeviceContext
-    );
+	void *hDeviceContext
+);
 
 void
 PSvEnablePowerSaving(
-    void *hDeviceContext,
-    unsigned short wListenInterval
-    );
+	void *hDeviceContext,
+	unsigned short wListenInterval
+);
 
 void
 PSvSendPSPOLL(
-    void *hDeviceContext
-    );
+	void *hDeviceContext
+);
 
 bool
 PSbSendNullPacket(
-    void *hDeviceContext
-    );
+	void *hDeviceContext
+);
 
 bool
 PSbIsNextTBTTWakeUp(
-    void *hDeviceContext
-    );
+	void *hDeviceContext
+);
 
 #endif //__POWER_H__
diff --git a/drivers/staging/vt6655/rc4.c b/drivers/staging/vt6655/rc4.c
index 9856c08..343b815 100644
--- a/drivers/staging/vt6655/rc4.c
+++ b/drivers/staging/vt6655/rc4.c
@@ -34,54 +34,54 @@
 
 void rc4_init(PRC4Ext pRC4, unsigned char *pbyKey, unsigned int cbKey_len)
 {
-    unsigned int ust1, ust2;
-    unsigned int keyindex;
-    unsigned int stateindex;
-    unsigned char *pbyst;
-    unsigned int idx;
+	unsigned int ust1, ust2;
+	unsigned int keyindex;
+	unsigned int stateindex;
+	unsigned char *pbyst;
+	unsigned int idx;
 
-    pbyst = pRC4->abystate;
-    pRC4->ux = 0;
-    pRC4->uy = 0;
-    for (idx = 0; idx < 256; idx++)
-        pbyst[idx] = (unsigned char)idx;
-    keyindex = 0;
-    stateindex = 0;
-    for (idx = 0; idx < 256; idx++) {
-        ust1 = pbyst[idx];
-        stateindex = (stateindex + pbyKey[keyindex] + ust1) & 0xff;
-        ust2 = pbyst[stateindex];
-        pbyst[stateindex] = (unsigned char)ust1;
-        pbyst[idx] = (unsigned char)ust2;
-        if (++keyindex >= cbKey_len)
-            keyindex = 0;
-    }
+	pbyst = pRC4->abystate;
+	pRC4->ux = 0;
+	pRC4->uy = 0;
+	for (idx = 0; idx < 256; idx++)
+		pbyst[idx] = (unsigned char)idx;
+	keyindex = 0;
+	stateindex = 0;
+	for (idx = 0; idx < 256; idx++) {
+		ust1 = pbyst[idx];
+		stateindex = (stateindex + pbyKey[keyindex] + ust1) & 0xff;
+		ust2 = pbyst[stateindex];
+		pbyst[stateindex] = (unsigned char)ust1;
+		pbyst[idx] = (unsigned char)ust2;
+		if (++keyindex >= cbKey_len)
+			keyindex = 0;
+	}
 }
 
 unsigned int rc4_byte(PRC4Ext pRC4)
 {
-    unsigned int ux;
-    unsigned int uy;
-    unsigned int ustx, usty;
-    unsigned char *pbyst;
+	unsigned int ux;
+	unsigned int uy;
+	unsigned int ustx, usty;
+	unsigned char *pbyst;
 
-    pbyst = pRC4->abystate;
-    ux = (pRC4->ux + 1) & 0xff;
-    ustx = pbyst[ux];
-    uy = (ustx + pRC4->uy) & 0xff;
-    usty = pbyst[uy];
-    pRC4->ux = ux;
-    pRC4->uy = uy;
-    pbyst[uy] = (unsigned char)ustx;
-    pbyst[ux] = (unsigned char)usty;
+	pbyst = pRC4->abystate;
+	ux = (pRC4->ux + 1) & 0xff;
+	ustx = pbyst[ux];
+	uy = (ustx + pRC4->uy) & 0xff;
+	usty = pbyst[uy];
+	pRC4->ux = ux;
+	pRC4->uy = uy;
+	pbyst[uy] = (unsigned char)ustx;
+	pbyst[ux] = (unsigned char)usty;
 
-    return pbyst[(ustx + usty) & 0xff];
+	return pbyst[(ustx + usty) & 0xff];
 }
 
 void rc4_encrypt(PRC4Ext pRC4, unsigned char *pbyDest,
-                     unsigned char *pbySrc, unsigned int cbData_len)
+		 unsigned char *pbySrc, unsigned int cbData_len)
 {
-    unsigned int ii;
-    for (ii = 0; ii < cbData_len; ii++)
-        pbyDest[ii] = (unsigned char)(pbySrc[ii] ^ rc4_byte(pRC4));
+	unsigned int ii;
+	for (ii = 0; ii < cbData_len; ii++)
+		pbyDest[ii] = (unsigned char)(pbySrc[ii] ^ rc4_byte(pRC4));
 }
diff --git a/drivers/staging/vt6655/rc4.h b/drivers/staging/vt6655/rc4.h
index ad04e35..74b2eed 100644
--- a/drivers/staging/vt6655/rc4.h
+++ b/drivers/staging/vt6655/rc4.h
@@ -35,9 +35,9 @@
 /*---------------------  Export Definitions -------------------------*/
 /*---------------------  Export Types  ------------------------------*/
 typedef struct {
-    unsigned int ux;
-    unsigned int uy;
-    unsigned char abystate[256];
+	unsigned int ux;
+	unsigned int uy;
+	unsigned char abystate[256];
 } RC4Ext, *PRC4Ext;
 
 void rc4_init(PRC4Ext pRC4, unsigned char *pbyKey, unsigned int cbKey_len);
diff --git a/drivers/staging/vt6655/rf.c b/drivers/staging/vt6655/rf.c
index aaa231a..6948984 100644
--- a/drivers/staging/vt6655/rf.c
+++ b/drivers/staging/vt6655/rf.c
@@ -46,7 +46,6 @@
 #define SWITCH_CHANNEL_DELAY_AL2230 200 //us
 #define AL2230_PWR_IDX_LEN    64
 
-
 #define BY_AL7230_REG_LEN     23 //24bit
 #define CB_AL7230_INIT_SEQ    16
 #define SWITCH_CHANNEL_DELAY_AL7230 200 //us
@@ -56,376 +55,367 @@
 
 /*---------------------  Static Variables  --------------------------*/
 
-
-
 const unsigned long dwAL2230InitTable[CB_AL2230_INIT_SEQ] = {
-    0x03F79000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, //
-    0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, //
-    0x01A00200+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, //
-    0x00FFF300+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, //
-    0x0005A400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, //
-    0x0F4DC500+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, //
-    0x0805B600+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, //
-    0x0146C700+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, //
-    0x00068800+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, //
-    0x0403B900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, //
-    0x00DBBA00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, //
-    0x00099B00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, //
-    0x0BDFFC00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x00000D00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x00580F00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW
-    };
+	0x03F79000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, //
+	0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, //
+	0x01A00200+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, //
+	0x00FFF300+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, //
+	0x0005A400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, //
+	0x0F4DC500+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, //
+	0x0805B600+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, //
+	0x0146C700+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, //
+	0x00068800+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, //
+	0x0403B900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, //
+	0x00DBBA00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, //
+	0x00099B00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, //
+	0x0BDFFC00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x00000D00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x00580F00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW
+};
 
 const unsigned long dwAL2230ChannelTable0[CB_MAX_CHANNEL] = {
-    0x03F79000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 1, Tf = 2412MHz
-    0x03F79000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 2, Tf = 2417MHz
-    0x03E79000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 3, Tf = 2422MHz
-    0x03E79000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 4, Tf = 2427MHz
-    0x03F7A000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 5, Tf = 2432MHz
-    0x03F7A000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 6, Tf = 2437MHz
-    0x03E7A000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 7, Tf = 2442MHz
-    0x03E7A000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 8, Tf = 2447MHz
-    0x03F7B000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 9, Tf = 2452MHz
-    0x03F7B000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 10, Tf = 2457MHz
-    0x03E7B000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 11, Tf = 2462MHz
-    0x03E7B000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 12, Tf = 2467MHz
-    0x03F7C000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 13, Tf = 2472MHz
-    0x03E7C000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW  // channel = 14, Tf = 2412M
-    };
+	0x03F79000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 1, Tf = 2412MHz
+	0x03F79000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 2, Tf = 2417MHz
+	0x03E79000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 3, Tf = 2422MHz
+	0x03E79000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 4, Tf = 2427MHz
+	0x03F7A000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 5, Tf = 2432MHz
+	0x03F7A000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 6, Tf = 2437MHz
+	0x03E7A000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 7, Tf = 2442MHz
+	0x03E7A000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 8, Tf = 2447MHz
+	0x03F7B000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 9, Tf = 2452MHz
+	0x03F7B000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 10, Tf = 2457MHz
+	0x03E7B000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 11, Tf = 2462MHz
+	0x03E7B000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 12, Tf = 2467MHz
+	0x03F7C000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 13, Tf = 2472MHz
+	0x03E7C000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW  // channel = 14, Tf = 2412M
+};
 
 const unsigned long dwAL2230ChannelTable1[CB_MAX_CHANNEL] = {
-    0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 1, Tf = 2412MHz
-    0x0B333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 2, Tf = 2417MHz
-    0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 3, Tf = 2422MHz
-    0x0B333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 4, Tf = 2427MHz
-    0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 5, Tf = 2432MHz
-    0x0B333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 6, Tf = 2437MHz
-    0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 7, Tf = 2442MHz
-    0x0B333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 8, Tf = 2447MHz
-    0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 9, Tf = 2452MHz
-    0x0B333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 10, Tf = 2457MHz
-    0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 11, Tf = 2462MHz
-    0x0B333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 12, Tf = 2467MHz
-    0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 13, Tf = 2472MHz
-    0x06666100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW  // channel = 14, Tf = 2412M
-    };
+	0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 1, Tf = 2412MHz
+	0x0B333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 2, Tf = 2417MHz
+	0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 3, Tf = 2422MHz
+	0x0B333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 4, Tf = 2427MHz
+	0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 5, Tf = 2432MHz
+	0x0B333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 6, Tf = 2437MHz
+	0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 7, Tf = 2442MHz
+	0x0B333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 8, Tf = 2447MHz
+	0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 9, Tf = 2452MHz
+	0x0B333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 10, Tf = 2457MHz
+	0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 11, Tf = 2462MHz
+	0x0B333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 12, Tf = 2467MHz
+	0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 13, Tf = 2472MHz
+	0x06666100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW  // channel = 14, Tf = 2412M
+};
 
 unsigned long dwAL2230PowerTable[AL2230_PWR_IDX_LEN] = {
-    0x04040900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x04041900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x04042900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x04043900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x04044900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x04045900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x04046900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x04047900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x04048900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x04049900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x0404A900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x0404B900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x0404C900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x0404D900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x0404E900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x0404F900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x04050900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x04051900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x04052900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x04053900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x04054900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x04055900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x04056900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x04057900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x04058900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x04059900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x0405A900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x0405B900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x0405C900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x0405D900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x0405E900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x0405F900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x04060900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x04061900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x04062900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x04063900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x04064900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x04065900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x04066900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x04067900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x04068900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x04069900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x0406A900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x0406B900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x0406C900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x0406D900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x0406E900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x0406F900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x04070900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x04071900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x04072900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x04073900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x04074900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x04075900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x04076900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x04077900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x04078900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x04079900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x0407A900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x0407B900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x0407C900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x0407D900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x0407E900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x0407F900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW
-    };
+	0x04040900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x04041900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x04042900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x04043900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x04044900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x04045900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x04046900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x04047900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x04048900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x04049900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x0404A900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x0404B900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x0404C900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x0404D900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x0404E900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x0404F900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x04050900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x04051900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x04052900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x04053900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x04054900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x04055900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x04056900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x04057900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x04058900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x04059900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x0405A900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x0405B900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x0405C900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x0405D900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x0405E900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x0405F900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x04060900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x04061900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x04062900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x04063900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x04064900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x04065900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x04066900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x04067900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x04068900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x04069900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x0406A900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x0406B900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x0406C900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x0406D900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x0406E900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x0406F900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x04070900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x04071900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x04072900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x04073900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x04074900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x04075900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x04076900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x04077900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x04078900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x04079900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x0407A900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x0407B900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x0407C900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x0407D900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x0407E900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x0407F900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW
+};
 
 //{{ RobertYu:20050104
 // 40MHz reference frequency
 // Need to Pull PLLON(PE3) low when writing channel registers through 3-wire.
 const unsigned long dwAL7230InitTable[CB_AL7230_INIT_SEQ] = {
-    0x00379000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Channel1 // Need modify for 11a
-    0x13333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Channel1 // Need modify for 11a
-    0x841FF200+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11a: 451FE2
-    0x3FDFA300+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11a: 5FDFA3
-    0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // 11b/g    // Need modify for 11a
-    //0x802B4500+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11a: 8D1B45
-    // RoberYu:20050113, Rev0.47 Regsiter Setting Guide
-    0x802B5500+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11a: 8D1B55
-    0x56AF3600+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW,
-    0xCE020700+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11a: 860207
-    0x6EBC0800+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x221BB900+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW,
-    0xE0000A00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11a: E0600A
-    0x08031B00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // init 0x080B1B00 => 0x080F1B00 for 3 wire control TxGain(D10)
-    //0x00093C00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11a: 00143C
-    // RoberYu:20050113, Rev0.47 Regsiter Setting Guide
-    0x000A3C00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11a: 00143C
-    0xFFFFFD00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x00000E00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x1ABA8F00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW  // Need modify for 11a: 12BACF
-    };
+	0x00379000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Channel1 // Need modify for 11a
+	0x13333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Channel1 // Need modify for 11a
+	0x841FF200+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11a: 451FE2
+	0x3FDFA300+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11a: 5FDFA3
+	0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // 11b/g    // Need modify for 11a
+	//0x802B4500+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11a: 8D1B45
+	// RoberYu:20050113, Rev0.47 Regsiter Setting Guide
+	0x802B5500+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11a: 8D1B55
+	0x56AF3600+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW,
+	0xCE020700+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11a: 860207
+	0x6EBC0800+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x221BB900+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW,
+	0xE0000A00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11a: E0600A
+	0x08031B00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // init 0x080B1B00 => 0x080F1B00 for 3 wire control TxGain(D10)
+	//0x00093C00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11a: 00143C
+	// RoberYu:20050113, Rev0.47 Regsiter Setting Guide
+	0x000A3C00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11a: 00143C
+	0xFFFFFD00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x00000E00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x1ABA8F00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW  // Need modify for 11a: 12BACF
+};
 
 const unsigned long dwAL7230InitTableAMode[CB_AL7230_INIT_SEQ] = {
-    0x0FF52000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Channel184 // Need modify for 11b/g
-    0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Channel184 // Need modify for 11b/g
-    0x451FE200+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11b/g
-    0x5FDFA300+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11b/g
-    0x67F78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // 11a    // Need modify for 11b/g
-    0x853F5500+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11b/g, RoberYu:20050113
-    0x56AF3600+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW,
-    0xCE020700+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11b/g
-    0x6EBC0800+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x221BB900+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW,
-    0xE0600A00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11b/g
-    0x08031B00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // init 0x080B1B00 => 0x080F1B00 for 3 wire control TxGain(D10)
-    0x00147C00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11b/g
-    0xFFFFFD00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x00000E00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW,
-    0x12BACF00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW  // Need modify for 11b/g
-    };
-
+	0x0FF52000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Channel184 // Need modify for 11b/g
+	0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Channel184 // Need modify for 11b/g
+	0x451FE200+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11b/g
+	0x5FDFA300+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11b/g
+	0x67F78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // 11a    // Need modify for 11b/g
+	0x853F5500+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11b/g, RoberYu:20050113
+	0x56AF3600+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW,
+	0xCE020700+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11b/g
+	0x6EBC0800+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x221BB900+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW,
+	0xE0600A00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11b/g
+	0x08031B00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // init 0x080B1B00 => 0x080F1B00 for 3 wire control TxGain(D10)
+	0x00147C00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11b/g
+	0xFFFFFD00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x00000E00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW,
+	0x12BACF00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW  // Need modify for 11b/g
+};
 
 const unsigned long dwAL7230ChannelTable0[CB_MAX_CHANNEL] = {
-    0x00379000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  1, Tf = 2412MHz
-    0x00379000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  2, Tf = 2417MHz
-    0x00379000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  3, Tf = 2422MHz
-    0x00379000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  4, Tf = 2427MHz
-    0x0037A000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  5, Tf = 2432MHz
-    0x0037A000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  6, Tf = 2437MHz
-    0x0037A000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  7, Tf = 2442MHz
-    0x0037A000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  8, Tf = 2447MHz //RobertYu: 20050218, update for APNode 0.49
-    0x0037B000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  9, Tf = 2452MHz //RobertYu: 20050218, update for APNode 0.49
-    0x0037B000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 10, Tf = 2457MHz //RobertYu: 20050218, update for APNode 0.49
-    0x0037B000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 11, Tf = 2462MHz //RobertYu: 20050218, update for APNode 0.49
-    0x0037B000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 12, Tf = 2467MHz //RobertYu: 20050218, update for APNode 0.49
-    0x0037C000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 13, Tf = 2472MHz //RobertYu: 20050218, update for APNode 0.49
-    0x0037C000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 14, Tf = 2484MHz
-
-    // 4.9G => Ch 183, 184, 185, 187, 188, 189, 192, 196  (Value:15 ~ 22)
-    0x0FF52000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 183, Tf = 4915MHz (15)
-    0x0FF52000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 184, Tf = 4920MHz (16)
-    0x0FF52000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 185, Tf = 4925MHz (17)
-    0x0FF52000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 187, Tf = 4935MHz (18)
-    0x0FF52000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 188, Tf = 4940MHz (19)
-    0x0FF52000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 189, Tf = 4945MHz (20)
-    0x0FF53000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 192, Tf = 4960MHz (21)
-    0x0FF53000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 196, Tf = 4980MHz (22)
-
-    // 5G => Ch 7, 8, 9, 11, 12, 16, 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64,
-    // 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165  (Value 23 ~ 56)
-
-    0x0FF54000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =   7, Tf = 5035MHz (23)
-    0x0FF54000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =   8, Tf = 5040MHz (24)
-    0x0FF54000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =   9, Tf = 5045MHz (25)
-    0x0FF54000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  11, Tf = 5055MHz (26)
-    0x0FF54000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  12, Tf = 5060MHz (27)
-    0x0FF55000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  16, Tf = 5080MHz (28)
-    0x0FF56000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  34, Tf = 5170MHz (29)
-    0x0FF56000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  36, Tf = 5180MHz (30)
-    0x0FF57000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  38, Tf = 5190MHz (31) //RobertYu: 20050218, update for APNode 0.49
-    0x0FF57000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  40, Tf = 5200MHz (32)
-    0x0FF57000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  42, Tf = 5210MHz (33)
-    0x0FF57000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  44, Tf = 5220MHz (34)
-    0x0FF57000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  46, Tf = 5230MHz (35)
-    0x0FF57000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  48, Tf = 5240MHz (36)
-    0x0FF58000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  52, Tf = 5260MHz (37)
-    0x0FF58000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  56, Tf = 5280MHz (38)
-    0x0FF58000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  60, Tf = 5300MHz (39)
-    0x0FF59000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  64, Tf = 5320MHz (40)
-
-    0x0FF5C000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 100, Tf = 5500MHz (41)
-    0x0FF5C000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 104, Tf = 5520MHz (42)
-    0x0FF5C000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 108, Tf = 5540MHz (43)
-    0x0FF5D000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 112, Tf = 5560MHz (44)
-    0x0FF5D000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 116, Tf = 5580MHz (45)
-    0x0FF5D000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 120, Tf = 5600MHz (46)
-    0x0FF5E000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 124, Tf = 5620MHz (47)
-    0x0FF5E000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 128, Tf = 5640MHz (48)
-    0x0FF5E000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 132, Tf = 5660MHz (49)
-    0x0FF5F000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 136, Tf = 5680MHz (50)
-    0x0FF5F000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 140, Tf = 5700MHz (51)
-    0x0FF60000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 149, Tf = 5745MHz (52)
-    0x0FF60000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 153, Tf = 5765MHz (53)
-    0x0FF60000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 157, Tf = 5785MHz (54)
-    0x0FF61000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 161, Tf = 5805MHz (55)
-    0x0FF61000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW  // channel = 165, Tf = 5825MHz (56)
-    };
+	0x00379000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  1, Tf = 2412MHz
+	0x00379000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  2, Tf = 2417MHz
+	0x00379000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  3, Tf = 2422MHz
+	0x00379000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  4, Tf = 2427MHz
+	0x0037A000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  5, Tf = 2432MHz
+	0x0037A000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  6, Tf = 2437MHz
+	0x0037A000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  7, Tf = 2442MHz
+	0x0037A000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  8, Tf = 2447MHz //RobertYu: 20050218, update for APNode 0.49
+	0x0037B000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  9, Tf = 2452MHz //RobertYu: 20050218, update for APNode 0.49
+	0x0037B000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 10, Tf = 2457MHz //RobertYu: 20050218, update for APNode 0.49
+	0x0037B000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 11, Tf = 2462MHz //RobertYu: 20050218, update for APNode 0.49
+	0x0037B000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 12, Tf = 2467MHz //RobertYu: 20050218, update for APNode 0.49
+	0x0037C000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 13, Tf = 2472MHz //RobertYu: 20050218, update for APNode 0.49
+	0x0037C000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 14, Tf = 2484MHz
+
+	// 4.9G => Ch 183, 184, 185, 187, 188, 189, 192, 196  (Value:15 ~ 22)
+	0x0FF52000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 183, Tf = 4915MHz (15)
+	0x0FF52000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 184, Tf = 4920MHz (16)
+	0x0FF52000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 185, Tf = 4925MHz (17)
+	0x0FF52000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 187, Tf = 4935MHz (18)
+	0x0FF52000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 188, Tf = 4940MHz (19)
+	0x0FF52000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 189, Tf = 4945MHz (20)
+	0x0FF53000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 192, Tf = 4960MHz (21)
+	0x0FF53000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 196, Tf = 4980MHz (22)
+
+	// 5G => Ch 7, 8, 9, 11, 12, 16, 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64,
+	// 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165  (Value 23 ~ 56)
+
+	0x0FF54000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =   7, Tf = 5035MHz (23)
+	0x0FF54000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =   8, Tf = 5040MHz (24)
+	0x0FF54000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =   9, Tf = 5045MHz (25)
+	0x0FF54000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  11, Tf = 5055MHz (26)
+	0x0FF54000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  12, Tf = 5060MHz (27)
+	0x0FF55000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  16, Tf = 5080MHz (28)
+	0x0FF56000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  34, Tf = 5170MHz (29)
+	0x0FF56000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  36, Tf = 5180MHz (30)
+	0x0FF57000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  38, Tf = 5190MHz (31) //RobertYu: 20050218, update for APNode 0.49
+	0x0FF57000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  40, Tf = 5200MHz (32)
+	0x0FF57000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  42, Tf = 5210MHz (33)
+	0x0FF57000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  44, Tf = 5220MHz (34)
+	0x0FF57000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  46, Tf = 5230MHz (35)
+	0x0FF57000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  48, Tf = 5240MHz (36)
+	0x0FF58000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  52, Tf = 5260MHz (37)
+	0x0FF58000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  56, Tf = 5280MHz (38)
+	0x0FF58000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  60, Tf = 5300MHz (39)
+	0x0FF59000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  64, Tf = 5320MHz (40)
+
+	0x0FF5C000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 100, Tf = 5500MHz (41)
+	0x0FF5C000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 104, Tf = 5520MHz (42)
+	0x0FF5C000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 108, Tf = 5540MHz (43)
+	0x0FF5D000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 112, Tf = 5560MHz (44)
+	0x0FF5D000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 116, Tf = 5580MHz (45)
+	0x0FF5D000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 120, Tf = 5600MHz (46)
+	0x0FF5E000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 124, Tf = 5620MHz (47)
+	0x0FF5E000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 128, Tf = 5640MHz (48)
+	0x0FF5E000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 132, Tf = 5660MHz (49)
+	0x0FF5F000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 136, Tf = 5680MHz (50)
+	0x0FF5F000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 140, Tf = 5700MHz (51)
+	0x0FF60000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 149, Tf = 5745MHz (52)
+	0x0FF60000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 153, Tf = 5765MHz (53)
+	0x0FF60000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 157, Tf = 5785MHz (54)
+	0x0FF61000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 161, Tf = 5805MHz (55)
+	0x0FF61000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW  // channel = 165, Tf = 5825MHz (56)
+};
 
 const unsigned long dwAL7230ChannelTable1[CB_MAX_CHANNEL] = {
-    0x13333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  1, Tf = 2412MHz
-    0x1B333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  2, Tf = 2417MHz
-    0x03333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  3, Tf = 2422MHz
-    0x0B333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  4, Tf = 2427MHz
-    0x13333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  5, Tf = 2432MHz
-    0x1B333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  6, Tf = 2437MHz
-    0x03333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  7, Tf = 2442MHz
-    0x0B333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  8, Tf = 2447MHz
-    0x13333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  9, Tf = 2452MHz
-    0x1B333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 10, Tf = 2457MHz
-    0x03333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 11, Tf = 2462MHz
-    0x0B333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 12, Tf = 2467MHz
-    0x13333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 13, Tf = 2472MHz
-    0x06666100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 14, Tf = 2484MHz
-
-    // 4.9G => Ch 183, 184, 185, 187, 188, 189, 192, 196  (Value:15 ~ 22)
-    0x1D555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 183, Tf = 4915MHz (15)
-    0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 184, Tf = 4920MHz (16)
-    0x02AAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 185, Tf = 4925MHz (17)
-    0x08000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 187, Tf = 4935MHz (18)
-    0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 188, Tf = 4940MHz (19)
-    0x0D555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 189, Tf = 4945MHz (20)
-    0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 192, Tf = 4960MHz (21)
-    0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 196, Tf = 4980MHz (22)
-
-    // 5G => Ch 7, 8, 9, 11, 12, 16, 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64,
-    // 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165  (Value 23 ~ 56)
-    0x1D555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =   7, Tf = 5035MHz (23)
-    0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =   8, Tf = 5040MHz (24)
-    0x02AAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =   9, Tf = 5045MHz (25)
-    0x08000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  11, Tf = 5055MHz (26)
-    0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  12, Tf = 5060MHz (27)
-    0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  16, Tf = 5080MHz (28)
-    0x05555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  34, Tf = 5170MHz (29)
-    0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  36, Tf = 5180MHz (30)
-    0x10000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  38, Tf = 5190MHz (31)
-    0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  40, Tf = 5200MHz (32)
-    0x1AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  42, Tf = 5210MHz (33)
-    0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  44, Tf = 5220MHz (34)
-    0x05555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  46, Tf = 5230MHz (35)
-    0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  48, Tf = 5240MHz (36)
-    0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  52, Tf = 5260MHz (37)
-    0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  56, Tf = 5280MHz (38)
-    0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  60, Tf = 5300MHz (39)
-    0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  64, Tf = 5320MHz (40)
-    0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 100, Tf = 5500MHz (41)
-    0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 104, Tf = 5520MHz (42)
-    0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 108, Tf = 5540MHz (43)
-    0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 112, Tf = 5560MHz (44)
-    0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 116, Tf = 5580MHz (45)
-    0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 120, Tf = 5600MHz (46)
-    0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 124, Tf = 5620MHz (47)
-    0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 128, Tf = 5640MHz (48)
-    0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 132, Tf = 5660MHz (49)
-    0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 136, Tf = 5680MHz (50)
-    0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 140, Tf = 5700MHz (51)
-    0x18000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 149, Tf = 5745MHz (52)
-    0x02AAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 153, Tf = 5765MHz (53)
-    0x0D555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 157, Tf = 5785MHz (54)
-    0x18000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 161, Tf = 5805MHz (55)
-    0x02AAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW  // channel = 165, Tf = 5825MHz (56)
-    };
+	0x13333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  1, Tf = 2412MHz
+	0x1B333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  2, Tf = 2417MHz
+	0x03333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  3, Tf = 2422MHz
+	0x0B333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  4, Tf = 2427MHz
+	0x13333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  5, Tf = 2432MHz
+	0x1B333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  6, Tf = 2437MHz
+	0x03333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  7, Tf = 2442MHz
+	0x0B333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  8, Tf = 2447MHz
+	0x13333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  9, Tf = 2452MHz
+	0x1B333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 10, Tf = 2457MHz
+	0x03333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 11, Tf = 2462MHz
+	0x0B333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 12, Tf = 2467MHz
+	0x13333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 13, Tf = 2472MHz
+	0x06666100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 14, Tf = 2484MHz
+
+	// 4.9G => Ch 183, 184, 185, 187, 188, 189, 192, 196  (Value:15 ~ 22)
+	0x1D555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 183, Tf = 4915MHz (15)
+	0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 184, Tf = 4920MHz (16)
+	0x02AAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 185, Tf = 4925MHz (17)
+	0x08000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 187, Tf = 4935MHz (18)
+	0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 188, Tf = 4940MHz (19)
+	0x0D555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 189, Tf = 4945MHz (20)
+	0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 192, Tf = 4960MHz (21)
+	0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 196, Tf = 4980MHz (22)
+
+	// 5G => Ch 7, 8, 9, 11, 12, 16, 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64,
+	// 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165  (Value 23 ~ 56)
+	0x1D555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =   7, Tf = 5035MHz (23)
+	0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =   8, Tf = 5040MHz (24)
+	0x02AAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =   9, Tf = 5045MHz (25)
+	0x08000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  11, Tf = 5055MHz (26)
+	0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  12, Tf = 5060MHz (27)
+	0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  16, Tf = 5080MHz (28)
+	0x05555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  34, Tf = 5170MHz (29)
+	0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  36, Tf = 5180MHz (30)
+	0x10000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  38, Tf = 5190MHz (31)
+	0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  40, Tf = 5200MHz (32)
+	0x1AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  42, Tf = 5210MHz (33)
+	0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  44, Tf = 5220MHz (34)
+	0x05555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  46, Tf = 5230MHz (35)
+	0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  48, Tf = 5240MHz (36)
+	0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  52, Tf = 5260MHz (37)
+	0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  56, Tf = 5280MHz (38)
+	0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  60, Tf = 5300MHz (39)
+	0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  64, Tf = 5320MHz (40)
+	0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 100, Tf = 5500MHz (41)
+	0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 104, Tf = 5520MHz (42)
+	0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 108, Tf = 5540MHz (43)
+	0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 112, Tf = 5560MHz (44)
+	0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 116, Tf = 5580MHz (45)
+	0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 120, Tf = 5600MHz (46)
+	0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 124, Tf = 5620MHz (47)
+	0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 128, Tf = 5640MHz (48)
+	0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 132, Tf = 5660MHz (49)
+	0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 136, Tf = 5680MHz (50)
+	0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 140, Tf = 5700MHz (51)
+	0x18000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 149, Tf = 5745MHz (52)
+	0x02AAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 153, Tf = 5765MHz (53)
+	0x0D555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 157, Tf = 5785MHz (54)
+	0x18000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 161, Tf = 5805MHz (55)
+	0x02AAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW  // channel = 165, Tf = 5825MHz (56)
+};
 
 const unsigned long dwAL7230ChannelTable2[CB_MAX_CHANNEL] = {
-    0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  1, Tf = 2412MHz
-    0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  2, Tf = 2417MHz
-    0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  3, Tf = 2422MHz
-    0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  4, Tf = 2427MHz
-    0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  5, Tf = 2432MHz
-    0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  6, Tf = 2437MHz
-    0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  7, Tf = 2442MHz
-    0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  8, Tf = 2447MHz
-    0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  9, Tf = 2452MHz
-    0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 10, Tf = 2457MHz
-    0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 11, Tf = 2462MHz
-    0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 12, Tf = 2467MHz
-    0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 13, Tf = 2472MHz
-    0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 14, Tf = 2484MHz
-
-    // 4.9G => Ch 183, 184, 185, 187, 188, 189, 192, 196  (Value:15 ~ 22)
-    0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 183, Tf = 4915MHz (15)
-    0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 184, Tf = 4920MHz (16)
-    0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 185, Tf = 4925MHz (17)
-    0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 187, Tf = 4935MHz (18)
-    0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 188, Tf = 4940MHz (19)
-    0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 189, Tf = 4945MHz (20)
-    0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 192, Tf = 4960MHz (21)
-    0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 196, Tf = 4980MHz (22)
-
-    // 5G => Ch 7, 8, 9, 11, 12, 16, 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64,
-    // 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165  (Value 23 ~ 56)
-    0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =   7, Tf = 5035MHz (23)
-    0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =   8, Tf = 5040MHz (24)
-    0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =   9, Tf = 5045MHz (25)
-    0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  11, Tf = 5055MHz (26)
-    0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  12, Tf = 5060MHz (27)
-    0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  16, Tf = 5080MHz (28)
-    0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  34, Tf = 5170MHz (29)
-    0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  36, Tf = 5180MHz (30)
-    0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  38, Tf = 5190MHz (31)
-    0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  40, Tf = 5200MHz (32)
-    0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  42, Tf = 5210MHz (33)
-    0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  44, Tf = 5220MHz (34)
-    0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  46, Tf = 5230MHz (35)
-    0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  48, Tf = 5240MHz (36)
-    0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  52, Tf = 5260MHz (37)
-    0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  56, Tf = 5280MHz (38)
-    0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  60, Tf = 5300MHz (39)
-    0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  64, Tf = 5320MHz (40)
-    0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 100, Tf = 5500MHz (41)
-    0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 104, Tf = 5520MHz (42)
-    0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 108, Tf = 5540MHz (43)
-    0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 112, Tf = 5560MHz (44)
-    0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 116, Tf = 5580MHz (45)
-    0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 120, Tf = 5600MHz (46)
-    0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 124, Tf = 5620MHz (47)
-    0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 128, Tf = 5640MHz (48)
-    0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 132, Tf = 5660MHz (49)
-    0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 136, Tf = 5680MHz (50)
-    0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 140, Tf = 5700MHz (51)
-    0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 149, Tf = 5745MHz (52)
-    0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 153, Tf = 5765MHz (53)
-    0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 157, Tf = 5785MHz (54)
-    0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 161, Tf = 5805MHz (55)
-    0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW  // channel = 165, Tf = 5825MHz (56)
-    };
+	0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  1, Tf = 2412MHz
+	0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  2, Tf = 2417MHz
+	0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  3, Tf = 2422MHz
+	0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  4, Tf = 2427MHz
+	0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  5, Tf = 2432MHz
+	0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  6, Tf = 2437MHz
+	0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  7, Tf = 2442MHz
+	0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  8, Tf = 2447MHz
+	0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  9, Tf = 2452MHz
+	0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 10, Tf = 2457MHz
+	0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 11, Tf = 2462MHz
+	0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 12, Tf = 2467MHz
+	0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 13, Tf = 2472MHz
+	0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 14, Tf = 2484MHz
+
+	// 4.9G => Ch 183, 184, 185, 187, 188, 189, 192, 196  (Value:15 ~ 22)
+	0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 183, Tf = 4915MHz (15)
+	0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 184, Tf = 4920MHz (16)
+	0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 185, Tf = 4925MHz (17)
+	0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 187, Tf = 4935MHz (18)
+	0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 188, Tf = 4940MHz (19)
+	0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 189, Tf = 4945MHz (20)
+	0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 192, Tf = 4960MHz (21)
+	0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 196, Tf = 4980MHz (22)
+
+	// 5G => Ch 7, 8, 9, 11, 12, 16, 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64,
+	// 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165  (Value 23 ~ 56)
+	0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =   7, Tf = 5035MHz (23)
+	0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =   8, Tf = 5040MHz (24)
+	0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =   9, Tf = 5045MHz (25)
+	0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  11, Tf = 5055MHz (26)
+	0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  12, Tf = 5060MHz (27)
+	0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  16, Tf = 5080MHz (28)
+	0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  34, Tf = 5170MHz (29)
+	0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  36, Tf = 5180MHz (30)
+	0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  38, Tf = 5190MHz (31)
+	0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  40, Tf = 5200MHz (32)
+	0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  42, Tf = 5210MHz (33)
+	0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  44, Tf = 5220MHz (34)
+	0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  46, Tf = 5230MHz (35)
+	0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  48, Tf = 5240MHz (36)
+	0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  52, Tf = 5260MHz (37)
+	0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  56, Tf = 5280MHz (38)
+	0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  60, Tf = 5300MHz (39)
+	0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  64, Tf = 5320MHz (40)
+	0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 100, Tf = 5500MHz (41)
+	0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 104, Tf = 5520MHz (42)
+	0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 108, Tf = 5540MHz (43)
+	0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 112, Tf = 5560MHz (44)
+	0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 116, Tf = 5580MHz (45)
+	0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 120, Tf = 5600MHz (46)
+	0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 124, Tf = 5620MHz (47)
+	0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 128, Tf = 5640MHz (48)
+	0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 132, Tf = 5660MHz (49)
+	0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 136, Tf = 5680MHz (50)
+	0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 140, Tf = 5700MHz (51)
+	0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 149, Tf = 5745MHz (52)
+	0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 153, Tf = 5765MHz (53)
+	0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 157, Tf = 5785MHz (54)
+	0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 161, Tf = 5805MHz (55)
+	0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW  // channel = 165, Tf = 5825MHz (56)
+};
 //}} RobertYu
 
-
-
-
 /*---------------------  Static Functions  --------------------------*/
 
-
-
-
 /*
  * Description: AIROHA IFRF chip init function
  *
@@ -438,72 +428,72 @@ const unsigned long dwAL7230ChannelTable2[CB_MAX_CHANNEL] = {
  * Return Value: true if succeeded; false if failed.
  *
  */
-bool s_bAL7230Init (unsigned long dwIoBase)
+bool s_bAL7230Init(unsigned long dwIoBase)
 {
-    int     ii;
-    bool bResult;
+	int     ii;
+	bool bResult;
 
-    bResult = true;
+	bResult = true;
 
-    //3-wire control for normal mode
-    VNSvOutPortB(dwIoBase + MAC_REG_SOFTPWRCTL, 0);
+	//3-wire control for normal mode
+	VNSvOutPortB(dwIoBase + MAC_REG_SOFTPWRCTL, 0);
 
-    MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, (SOFTPWRCTL_SWPECTI  |
-                                                     SOFTPWRCTL_TXPEINV));
-    BBvPowerSaveModeOFF(dwIoBase); //RobertYu:20050106, have DC value for Calibration
+	MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, (SOFTPWRCTL_SWPECTI  |
+							 SOFTPWRCTL_TXPEINV));
+	BBvPowerSaveModeOFF(dwIoBase); //RobertYu:20050106, have DC value for Calibration
 
-    for (ii = 0; ii < CB_AL7230_INIT_SEQ; ii++)
-        bResult &= IFRFbWriteEmbedded(dwIoBase, dwAL7230InitTable[ii]);
+	for (ii = 0; ii < CB_AL7230_INIT_SEQ; ii++)
+		bResult &= IFRFbWriteEmbedded(dwIoBase, dwAL7230InitTable[ii]);
 
-    // PLL On
-    MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3);
+	// PLL On
+	MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3);
 
-    //Calibration
-    MACvTimer0MicroSDelay(dwIoBase, 150);//150us
-    bResult &= IFRFbWriteEmbedded(dwIoBase, (0x9ABA8F00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW)); //TXDCOC:active, RCK:disable
-    MACvTimer0MicroSDelay(dwIoBase, 30);//30us
-    bResult &= IFRFbWriteEmbedded(dwIoBase, (0x3ABA8F00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW)); //TXDCOC:disable, RCK:active
-    MACvTimer0MicroSDelay(dwIoBase, 30);//30us
-    bResult &= IFRFbWriteEmbedded(dwIoBase, dwAL7230InitTable[CB_AL7230_INIT_SEQ-1]); //TXDCOC:disable, RCK:disable
+	//Calibration
+	MACvTimer0MicroSDelay(dwIoBase, 150);//150us
+	bResult &= IFRFbWriteEmbedded(dwIoBase, (0x9ABA8F00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW)); //TXDCOC:active, RCK:disable
+	MACvTimer0MicroSDelay(dwIoBase, 30);//30us
+	bResult &= IFRFbWriteEmbedded(dwIoBase, (0x3ABA8F00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW)); //TXDCOC:disable, RCK:active
+	MACvTimer0MicroSDelay(dwIoBase, 30);//30us
+	bResult &= IFRFbWriteEmbedded(dwIoBase, dwAL7230InitTable[CB_AL7230_INIT_SEQ-1]); //TXDCOC:disable, RCK:disable
 
-    MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, (SOFTPWRCTL_SWPE3    |
-                                                     SOFTPWRCTL_SWPE2    |
-                                                     SOFTPWRCTL_SWPECTI  |
-                                                     SOFTPWRCTL_TXPEINV));
+	MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, (SOFTPWRCTL_SWPE3    |
+							 SOFTPWRCTL_SWPE2    |
+							 SOFTPWRCTL_SWPECTI  |
+							 SOFTPWRCTL_TXPEINV));
 
-    BBvPowerSaveModeON(dwIoBase); // RobertYu:20050106
+	BBvPowerSaveModeON(dwIoBase); // RobertYu:20050106
 
-    // PE1: TX_ON, PE2: RX_ON, PE3: PLLON
-    //3-wire control for power saving mode
-    VNSvOutPortB(dwIoBase + MAC_REG_PSPWRSIG, (PSSIG_WPE3 | PSSIG_WPE2)); //1100 0000
+	// PE1: TX_ON, PE2: RX_ON, PE3: PLLON
+	//3-wire control for power saving mode
+	VNSvOutPortB(dwIoBase + MAC_REG_PSPWRSIG, (PSSIG_WPE3 | PSSIG_WPE2)); //1100 0000
 
-    return bResult;
+	return bResult;
 }
 
 // Need to Pull PLLON low when writing channel registers through 3-wire interface
-bool s_bAL7230SelectChannel (unsigned long dwIoBase, unsigned char byChannel)
+bool s_bAL7230SelectChannel(unsigned long dwIoBase, unsigned char byChannel)
 {
-    bool bResult;
+	bool bResult;
 
-    bResult = true;
+	bResult = true;
 
-    // PLLON Off
-    MACvWordRegBitsOff(dwIoBase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3);
+	// PLLON Off
+	MACvWordRegBitsOff(dwIoBase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3);
 
-    bResult &= IFRFbWriteEmbedded (dwIoBase, dwAL7230ChannelTable0[byChannel-1]); //Reg0
-    bResult &= IFRFbWriteEmbedded (dwIoBase, dwAL7230ChannelTable1[byChannel-1]); //Reg1
-    bResult &= IFRFbWriteEmbedded (dwIoBase, dwAL7230ChannelTable2[byChannel-1]); //Reg4
+	bResult &= IFRFbWriteEmbedded(dwIoBase, dwAL7230ChannelTable0[byChannel - 1]); //Reg0
+	bResult &= IFRFbWriteEmbedded(dwIoBase, dwAL7230ChannelTable1[byChannel - 1]); //Reg1
+	bResult &= IFRFbWriteEmbedded(dwIoBase, dwAL7230ChannelTable2[byChannel - 1]); //Reg4
 
-    // PLLOn On
-    MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3);
+	// PLLOn On
+	MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3);
 
-    // Set Channel[7] = 0 to tell H/W channel is changing now.
-    VNSvOutPortB(dwIoBase + MAC_REG_CHANNEL, (byChannel & 0x7F));
-    MACvTimer0MicroSDelay(dwIoBase, SWITCH_CHANNEL_DELAY_AL7230);
-    // Set Channel[7] = 1 to tell H/W channel change is done.
-    VNSvOutPortB(dwIoBase + MAC_REG_CHANNEL, (byChannel | 0x80));
+	// Set Channel[7] = 0 to tell H/W channel is changing now.
+	VNSvOutPortB(dwIoBase + MAC_REG_CHANNEL, (byChannel & 0x7F));
+	MACvTimer0MicroSDelay(dwIoBase, SWITCH_CHANNEL_DELAY_AL7230);
+	// Set Channel[7] = 1 to tell H/W channel change is done.
+	VNSvOutPortB(dwIoBase + MAC_REG_CHANNEL, (byChannel | 0x80));
 
-    return bResult;
+	return bResult;
 }
 
 /*
@@ -520,7 +510,6 @@ bool s_bAL7230SelectChannel (unsigned long dwIoBase, unsigned char byChannel)
  *
  */
 
-
 //{{ RobertYu: 20041210
 /*
  * Description: UW2452 IFRF chip init function
@@ -535,8 +524,6 @@ bool s_bAL7230SelectChannel (unsigned long dwIoBase, unsigned char byChannel)
  *
  */
 
-
-
 //}} RobertYu
 ////////////////////////////////////////////////////////////////////////////////
 
@@ -567,8 +554,6 @@ bool s_bAL7230SelectChannel (unsigned long dwIoBase, unsigned char byChannel)
  *
  */
 
-
-
 /*---------------------  Export Variables  --------------------------*/
 
 /*---------------------  Export Functions  --------------------------*/
@@ -586,29 +571,27 @@ bool s_bAL7230SelectChannel (unsigned long dwIoBase, unsigned char byChannel)
  * Return Value: true if succeeded; false if failed.
  *
  */
-bool IFRFbWriteEmbedded (unsigned long dwIoBase, unsigned long dwData)
+bool IFRFbWriteEmbedded(unsigned long dwIoBase, unsigned long dwData)
 {
-    unsigned short ww;
-    unsigned long dwValue;
+	unsigned short ww;
+	unsigned long dwValue;
 
-    VNSvOutPortD(dwIoBase + MAC_REG_IFREGCTL, dwData);
+	VNSvOutPortD(dwIoBase + MAC_REG_IFREGCTL, dwData);
 
-    // W_MAX_TIMEOUT is the timeout period
-    for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
-        VNSvInPortD(dwIoBase + MAC_REG_IFREGCTL, &dwValue);
-        if (dwValue & IFREGCTL_DONE)
-            break;
-    }
+	// W_MAX_TIMEOUT is the timeout period
+	for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
+		VNSvInPortD(dwIoBase + MAC_REG_IFREGCTL, &dwValue);
+		if (dwValue & IFREGCTL_DONE)
+			break;
+	}
 
-    if (ww == W_MAX_TIMEOUT) {
+	if (ww == W_MAX_TIMEOUT) {
 //        DBG_PORT80_ALWAYS(0x32);
-        return false;
-    }
-    return true;
+		return false;
+	}
+	return true;
 }
 
-
-
 /*
  * Description: RFMD RF2959 IFRF chip init function
  *
@@ -648,72 +631,69 @@ bool IFRFbWriteEmbedded (unsigned long dwIoBase, unsigned long dwData)
  * Return Value: true if succeeded; false if failed.
  *
  */
-bool RFbAL2230Init (unsigned long dwIoBase)
+bool RFbAL2230Init(unsigned long dwIoBase)
 {
-    int     ii;
-    bool bResult;
+	int     ii;
+	bool bResult;
 
-    bResult = true;
+	bResult = true;
 
-    //3-wire control for normal mode
-    VNSvOutPortB(dwIoBase + MAC_REG_SOFTPWRCTL, 0);
+	//3-wire control for normal mode
+	VNSvOutPortB(dwIoBase + MAC_REG_SOFTPWRCTL, 0);
 
-    MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, (SOFTPWRCTL_SWPECTI  |
-                                                     SOFTPWRCTL_TXPEINV));
+	MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, (SOFTPWRCTL_SWPECTI  |
+							 SOFTPWRCTL_TXPEINV));
 //2008-8-21 chester <add>
-    // PLL  Off
-
-    MACvWordRegBitsOff(dwIoBase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3);
-
+	// PLL  Off
 
+	MACvWordRegBitsOff(dwIoBase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3);
 
-    //patch abnormal AL2230 frequency output
+	//patch abnormal AL2230 frequency output
 //2008-8-21 chester <add>
-    IFRFbWriteEmbedded(dwIoBase, (0x07168700+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW));
+	IFRFbWriteEmbedded(dwIoBase, (0x07168700+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW));
 
-
-    for (ii = 0; ii < CB_AL2230_INIT_SEQ; ii++)
-        bResult &= IFRFbWriteEmbedded(dwIoBase, dwAL2230InitTable[ii]);
+	for (ii = 0; ii < CB_AL2230_INIT_SEQ; ii++)
+		bResult &= IFRFbWriteEmbedded(dwIoBase, dwAL2230InitTable[ii]);
 //2008-8-21 chester <add>
-MACvTimer0MicroSDelay(dwIoBase, 30); //delay 30 us
+	MACvTimer0MicroSDelay(dwIoBase, 30); //delay 30 us
 
-    // PLL On
-    MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3);
+	// PLL On
+	MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3);
 
-    MACvTimer0MicroSDelay(dwIoBase, 150);//150us
-    bResult &= IFRFbWriteEmbedded(dwIoBase, (0x00d80f00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW));
-    MACvTimer0MicroSDelay(dwIoBase, 30);//30us
-    bResult &= IFRFbWriteEmbedded(dwIoBase, (0x00780f00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW));
-    MACvTimer0MicroSDelay(dwIoBase, 30);//30us
-    bResult &= IFRFbWriteEmbedded(dwIoBase, dwAL2230InitTable[CB_AL2230_INIT_SEQ-1]);
+	MACvTimer0MicroSDelay(dwIoBase, 150);//150us
+	bResult &= IFRFbWriteEmbedded(dwIoBase, (0x00d80f00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW));
+	MACvTimer0MicroSDelay(dwIoBase, 30);//30us
+	bResult &= IFRFbWriteEmbedded(dwIoBase, (0x00780f00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW));
+	MACvTimer0MicroSDelay(dwIoBase, 30);//30us
+	bResult &= IFRFbWriteEmbedded(dwIoBase, dwAL2230InitTable[CB_AL2230_INIT_SEQ-1]);
 
-    MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, (SOFTPWRCTL_SWPE3    |
-                                                     SOFTPWRCTL_SWPE2    |
-                                                     SOFTPWRCTL_SWPECTI  |
-                                                     SOFTPWRCTL_TXPEINV));
+	MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, (SOFTPWRCTL_SWPE3    |
+							 SOFTPWRCTL_SWPE2    |
+							 SOFTPWRCTL_SWPECTI  |
+							 SOFTPWRCTL_TXPEINV));
 
-    //3-wire control for power saving mode
-    VNSvOutPortB(dwIoBase + MAC_REG_PSPWRSIG, (PSSIG_WPE3 | PSSIG_WPE2)); //1100 0000
+	//3-wire control for power saving mode
+	VNSvOutPortB(dwIoBase + MAC_REG_PSPWRSIG, (PSSIG_WPE3 | PSSIG_WPE2)); //1100 0000
 
-    return bResult;
+	return bResult;
 }
 
-bool RFbAL2230SelectChannel (unsigned long dwIoBase, unsigned char byChannel)
+bool RFbAL2230SelectChannel(unsigned long dwIoBase, unsigned char byChannel)
 {
-    bool bResult;
+	bool bResult;
 
-    bResult = true;
+	bResult = true;
 
-    bResult &= IFRFbWriteEmbedded (dwIoBase, dwAL2230ChannelTable0[byChannel-1]);
-    bResult &= IFRFbWriteEmbedded (dwIoBase, dwAL2230ChannelTable1[byChannel-1]);
+	bResult &= IFRFbWriteEmbedded(dwIoBase, dwAL2230ChannelTable0[byChannel - 1]);
+	bResult &= IFRFbWriteEmbedded(dwIoBase, dwAL2230ChannelTable1[byChannel - 1]);
 
-    // Set Channel[7] = 0 to tell H/W channel is changing now.
-    VNSvOutPortB(dwIoBase + MAC_REG_CHANNEL, (byChannel & 0x7F));
-    MACvTimer0MicroSDelay(dwIoBase, SWITCH_CHANNEL_DELAY_AL2230);
-    // Set Channel[7] = 1 to tell H/W channel change is done.
-    VNSvOutPortB(dwIoBase + MAC_REG_CHANNEL, (byChannel | 0x80));
+	// Set Channel[7] = 0 to tell H/W channel is changing now.
+	VNSvOutPortB(dwIoBase + MAC_REG_CHANNEL, (byChannel & 0x7F));
+	MACvTimer0MicroSDelay(dwIoBase, SWITCH_CHANNEL_DELAY_AL2230);
+	// Set Channel[7] = 1 to tell H/W channel change is done.
+	VNSvOutPortB(dwIoBase + MAC_REG_CHANNEL, (byChannel | 0x80));
 
-    return bResult;
+	return bResult;
 }
 
 /*
@@ -729,7 +709,6 @@ bool RFbAL2230SelectChannel (unsigned long dwIoBase, unsigned char byChannel)
  *
  */
 
-
 /*
  * Description: Select channel with UW2451 chip
  *
@@ -771,29 +750,29 @@ bool RFbAL2230SelectChannel (unsigned long dwIoBase, unsigned char byChannel)
  * Return Value: true if succeeded; false if failed.
  *
  */
-bool RFbInit (
-    PSDevice  pDevice
-    )
+bool RFbInit(
+	PSDevice  pDevice
+)
 {
-bool bResult = true;
-    switch (pDevice->byRFType) {
-        case RF_AIROHA :
-        case RF_AL2230S:
-            pDevice->byMaxPwrLevel = AL2230_PWR_IDX_LEN;
-            bResult = RFbAL2230Init(pDevice->PortOffset);
-            break;
-        case RF_AIROHA7230 :
-            pDevice->byMaxPwrLevel = AL7230_PWR_IDX_LEN;
-            bResult = s_bAL7230Init(pDevice->PortOffset);
-            break;
-        case RF_NOTHING :
-            bResult = true;
-            break;
-        default :
-            bResult = false;
-            break;
-    }
-    return bResult;
+	bool bResult = true;
+	switch (pDevice->byRFType) {
+	case RF_AIROHA:
+	case RF_AL2230S:
+		pDevice->byMaxPwrLevel = AL2230_PWR_IDX_LEN;
+		bResult = RFbAL2230Init(pDevice->PortOffset);
+		break;
+	case RF_AIROHA7230:
+		pDevice->byMaxPwrLevel = AL7230_PWR_IDX_LEN;
+		bResult = s_bAL7230Init(pDevice->PortOffset);
+		break;
+	case RF_NOTHING:
+		bResult = true;
+		break;
+	default:
+		bResult = false;
+		break;
+	}
+	return bResult;
 }
 
 /*
@@ -809,21 +788,21 @@ bool bResult = true;
  * Return Value: true if succeeded; false if failed.
  *
  */
-bool RFbShutDown (
-    PSDevice  pDevice
-    )
+bool RFbShutDown(
+	PSDevice  pDevice
+)
 {
-bool bResult = true;
-
-    switch (pDevice->byRFType) {
-        case RF_AIROHA7230 :
-            bResult = IFRFbWriteEmbedded (pDevice->PortOffset, 0x1ABAEF00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW);
-            break;
-        default :
-            bResult = true;
-            break;
-    }
-    return bResult;
+	bool bResult = true;
+
+	switch (pDevice->byRFType) {
+	case RF_AIROHA7230:
+		bResult = IFRFbWriteEmbedded(pDevice->PortOffset, 0x1ABAEF00 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW);
+		break;
+	default:
+		bResult = true;
+		break;
+	}
+	return bResult;
 }
 
 /*
@@ -839,28 +818,27 @@ bool bResult = true;
  * Return Value: true if succeeded; false if failed.
  *
  */
-bool RFbSelectChannel (unsigned long dwIoBase, unsigned char byRFType, unsigned char byChannel)
+bool RFbSelectChannel(unsigned long dwIoBase, unsigned char byRFType, unsigned char byChannel)
 {
-bool bResult = true;
-    switch (byRFType) {
-
-        case RF_AIROHA :
-        case RF_AL2230S:
-            bResult = RFbAL2230SelectChannel(dwIoBase, byChannel);
-            break;
-        //{{ RobertYu: 20050104
-        case RF_AIROHA7230 :
-            bResult = s_bAL7230SelectChannel(dwIoBase, byChannel);
-            break;
-        //}} RobertYu
-        case RF_NOTHING :
-            bResult = true;
-            break;
-        default:
-            bResult = false;
-            break;
-    }
-    return bResult;
+	bool bResult = true;
+	switch (byRFType) {
+	case RF_AIROHA:
+	case RF_AL2230S:
+		bResult = RFbAL2230SelectChannel(dwIoBase, byChannel);
+		break;
+		//{{ RobertYu: 20050104
+	case RF_AIROHA7230:
+		bResult = s_bAL7230SelectChannel(dwIoBase, byChannel);
+		break;
+		//}} RobertYu
+	case RF_NOTHING:
+		bResult = true;
+		break;
+	default:
+		bResult = false;
+		break;
+	}
+	return bResult;
 }
 
 /*
@@ -875,76 +853,73 @@ bool bResult = true;
  * Return Value: None.
  *
  */
-bool RFvWriteWakeProgSyn (unsigned long dwIoBase, unsigned char byRFType, unsigned int uChannel)
+bool RFvWriteWakeProgSyn(unsigned long dwIoBase, unsigned char byRFType, unsigned int uChannel)
 {
-    int   ii;
-    unsigned char byInitCount = 0;
-    unsigned char bySleepCount = 0;
-
-    VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, 0);
-    switch (byRFType) {
-        case RF_AIROHA:
-        case RF_AL2230S:
-
-            if (uChannel > CB_MAX_CHANNEL_24G)
-                return false;
-
-            byInitCount = CB_AL2230_INIT_SEQ + 2; // Init Reg + Channel Reg (2)
-            bySleepCount = 0;
-            if (byInitCount > (MISCFIFO_SYNDATASIZE - bySleepCount)) {
-                return false;
-            }
-
-            for (ii = 0; ii < CB_AL2230_INIT_SEQ; ii++ ) {
-                MACvSetMISCFifo(dwIoBase, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL2230InitTable[ii]);
-            }
-            MACvSetMISCFifo(dwIoBase, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL2230ChannelTable0[uChannel-1]);
-            ii ++;
-            MACvSetMISCFifo(dwIoBase, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL2230ChannelTable1[uChannel-1]);
-            break;
-
-        //{{ RobertYu: 20050104
-        // Need to check, PLLON need to be low for channel setting
-        case RF_AIROHA7230:
-            byInitCount = CB_AL7230_INIT_SEQ + 3; // Init Reg + Channel Reg (3)
-            bySleepCount = 0;
-            if (byInitCount > (MISCFIFO_SYNDATASIZE - bySleepCount)) {
-                return false;
-            }
-
-            if (uChannel <= CB_MAX_CHANNEL_24G)
-            {
-                for (ii = 0; ii < CB_AL7230_INIT_SEQ; ii++ ) {
-                    MACvSetMISCFifo(dwIoBase, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL7230InitTable[ii]);
-                }
-            }
-            else
-            {
-                for (ii = 0; ii < CB_AL7230_INIT_SEQ; ii++ ) {
-                    MACvSetMISCFifo(dwIoBase, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL7230InitTableAMode[ii]);
-                }
-            }
-
-            MACvSetMISCFifo(dwIoBase, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL7230ChannelTable0[uChannel-1]);
-            ii ++;
-            MACvSetMISCFifo(dwIoBase, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL7230ChannelTable1[uChannel-1]);
-            ii ++;
-            MACvSetMISCFifo(dwIoBase, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL7230ChannelTable2[uChannel-1]);
-            break;
-        //}} RobertYu
-
-        case RF_NOTHING :
-            return true;
-            break;
-
-        default:
-            return false;
-            break;
-    }
-
-    MACvSetMISCFifo(dwIoBase, MISCFIFO_SYNINFO_IDX, (unsigned long )MAKEWORD(bySleepCount, byInitCount));
-
-    return true;
+	int   ii;
+	unsigned char byInitCount = 0;
+	unsigned char bySleepCount = 0;
+
+	VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, 0);
+	switch (byRFType) {
+	case RF_AIROHA:
+	case RF_AL2230S:
+
+		if (uChannel > CB_MAX_CHANNEL_24G)
+			return false;
+
+		byInitCount = CB_AL2230_INIT_SEQ + 2; // Init Reg + Channel Reg (2)
+		bySleepCount = 0;
+		if (byInitCount > (MISCFIFO_SYNDATASIZE - bySleepCount)) {
+			return false;
+		}
+
+		for (ii = 0; ii < CB_AL2230_INIT_SEQ; ii++) {
+			MACvSetMISCFifo(dwIoBase, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL2230InitTable[ii]);
+		}
+		MACvSetMISCFifo(dwIoBase, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL2230ChannelTable0[uChannel-1]);
+		ii++;
+		MACvSetMISCFifo(dwIoBase, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL2230ChannelTable1[uChannel-1]);
+		break;
+
+		//{{ RobertYu: 20050104
+		// Need to check, PLLON need to be low for channel setting
+	case RF_AIROHA7230:
+		byInitCount = CB_AL7230_INIT_SEQ + 3; // Init Reg + Channel Reg (3)
+		bySleepCount = 0;
+		if (byInitCount > (MISCFIFO_SYNDATASIZE - bySleepCount)) {
+			return false;
+		}
+
+		if (uChannel <= CB_MAX_CHANNEL_24G) {
+			for (ii = 0; ii < CB_AL7230_INIT_SEQ; ii++) {
+				MACvSetMISCFifo(dwIoBase, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL7230InitTable[ii]);
+			}
+		} else {
+			for (ii = 0; ii < CB_AL7230_INIT_SEQ; ii++) {
+				MACvSetMISCFifo(dwIoBase, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL7230InitTableAMode[ii]);
+			}
+		}
+
+		MACvSetMISCFifo(dwIoBase, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL7230ChannelTable0[uChannel-1]);
+		ii++;
+		MACvSetMISCFifo(dwIoBase, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL7230ChannelTable1[uChannel-1]);
+		ii++;
+		MACvSetMISCFifo(dwIoBase, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL7230ChannelTable2[uChannel-1]);
+		break;
+		//}} RobertYu
+
+	case RF_NOTHING:
+		return true;
+		break;
+
+	default:
+		return false;
+		break;
+	}
+
+	MACvSetMISCFifo(dwIoBase, MISCFIFO_SYNINFO_IDX, (unsigned long)MAKEWORD(bySleepCount, byInitCount));
+
+	return true;
 }
 
 /*
@@ -960,87 +935,81 @@ bool RFvWriteWakeProgSyn (unsigned long dwIoBase, unsigned char byRFType, unsign
  * Return Value: true if succeeded; false if failed.
  *
  */
-bool RFbSetPower (
-    PSDevice  pDevice,
-    unsigned int uRATE,
-    unsigned int uCH
-    )
+bool RFbSetPower(
+	PSDevice  pDevice,
+	unsigned int uRATE,
+	unsigned int uCH
+)
 {
-bool bResult = true;
-unsigned char byPwr = 0;
-unsigned char byDec = 0;
-unsigned char byPwrdBm = 0;
-
-    if (pDevice->dwDiagRefCount != 0) {
-        return true;
-    }
-    if ((uCH < 1) || (uCH > CB_MAX_CHANNEL)) {
-        return false;
-    }
-
-    switch (uRATE) {
-    case RATE_1M:
-    case RATE_2M:
-    case RATE_5M:
-    case RATE_11M:
-        byPwr = pDevice->abyCCKPwrTbl[uCH];
-        byPwrdBm = pDevice->abyCCKDefaultPwr[uCH];
+	bool bResult = true;
+	unsigned char byPwr = 0;
+	unsigned char byDec = 0;
+	unsigned char byPwrdBm = 0;
+
+	if (pDevice->dwDiagRefCount != 0) {
+		return true;
+	}
+	if ((uCH < 1) || (uCH > CB_MAX_CHANNEL)) {
+		return false;
+	}
+
+	switch (uRATE) {
+	case RATE_1M:
+	case RATE_2M:
+	case RATE_5M:
+	case RATE_11M:
+		byPwr = pDevice->abyCCKPwrTbl[uCH];
+		byPwrdBm = pDevice->abyCCKDefaultPwr[uCH];
 //PLICE_DEBUG->
-	//byPwr+=5;
+		//byPwr+=5;
 //PLICE_DEBUG <-
-
-//printk("Rate <11:byPwr is %d\n",byPwr);
 		break;
-    case RATE_6M:
-    case RATE_9M:
-    case RATE_18M:
-        byPwr = pDevice->abyOFDMPwrTbl[uCH];
-        if (pDevice->byRFType == RF_UW2452) {
-            byDec = byPwr + 14;
-        } else {
-            byDec = byPwr + 10;
-        }
-        if (byDec >= pDevice->byMaxPwrLevel) {
-            byDec = pDevice->byMaxPwrLevel-1;
-        }
-        if (pDevice->byRFType == RF_UW2452) {
-            byPwrdBm = byDec - byPwr;
-            byPwrdBm /= 3;
-        } else {
-            byPwrdBm = byDec - byPwr;
-            byPwrdBm >>= 1;
-        }
-        byPwrdBm += pDevice->abyOFDMDefaultPwr[uCH];
-        byPwr = byDec;
+	case RATE_6M:
+	case RATE_9M:
+	case RATE_18M:
+		byPwr = pDevice->abyOFDMPwrTbl[uCH];
+		if (pDevice->byRFType == RF_UW2452) {
+			byDec = byPwr + 14;
+		} else {
+			byDec = byPwr + 10;
+		}
+		if (byDec >= pDevice->byMaxPwrLevel) {
+			byDec = pDevice->byMaxPwrLevel-1;
+		}
+		if (pDevice->byRFType == RF_UW2452) {
+			byPwrdBm = byDec - byPwr;
+			byPwrdBm /= 3;
+		} else {
+			byPwrdBm = byDec - byPwr;
+			byPwrdBm >>= 1;
+		}
+		byPwrdBm += pDevice->abyOFDMDefaultPwr[uCH];
+		byPwr = byDec;
 //PLICE_DEBUG->
-	//byPwr+=5;
+		//byPwr+=5;
 //PLICE_DEBUG<-
-
-//printk("Rate <24:byPwr is %d\n",byPwr);
 		break;
-    case RATE_24M:
-    case RATE_36M:
-    case RATE_48M:
-    case RATE_54M:
-        byPwr = pDevice->abyOFDMPwrTbl[uCH];
-        byPwrdBm = pDevice->abyOFDMDefaultPwr[uCH];
+	case RATE_24M:
+	case RATE_36M:
+	case RATE_48M:
+	case RATE_54M:
+		byPwr = pDevice->abyOFDMPwrTbl[uCH];
+		byPwrdBm = pDevice->abyOFDMDefaultPwr[uCH];
 //PLICE_DEBUG->
-	//byPwr+=5;
+		//byPwr+=5;
 //PLICE_DEBUG<-
-//printk("Rate < 54:byPwr is %d\n",byPwr);
 		break;
-    }
-
-//    if (pDevice->byLocalID <= REV_ID_VT3253_B1) {
-    if (pDevice->byCurPwr == byPwr) {
-        return true;
-    }
-    bResult = RFbRawSetPower(pDevice, byPwr, uRATE);
-//    }
-    if (bResult == true) {
-       pDevice->byCurPwr = byPwr;
-    }
-    return bResult;
+	}
+
+	if (pDevice->byCurPwr == byPwr) {
+		return true;
+	}
+
+	bResult = RFbRawSetPower(pDevice, byPwr, uRATE);
+	if (bResult == true) {
+		pDevice->byCurPwr = byPwr;
+	}
+	return bResult;
 }
 
 /*
@@ -1057,55 +1026,52 @@ unsigned char byPwrdBm = 0;
  *
  */
 
-bool RFbRawSetPower (
-    PSDevice  pDevice,
-    unsigned char byPwr,
-    unsigned int uRATE
-    )
+bool RFbRawSetPower(
+	PSDevice  pDevice,
+	unsigned char byPwr,
+	unsigned int uRATE
+)
 {
-bool bResult = true;
-unsigned long dwMax7230Pwr = 0;
-
-    if (byPwr >=  pDevice->byMaxPwrLevel) {
-        return (false);
-    }
-    switch (pDevice->byRFType) {
-
-        case RF_AIROHA :
-            bResult &= IFRFbWriteEmbedded(pDevice->PortOffset, dwAL2230PowerTable[byPwr]);
-            if (uRATE <= RATE_11M) {
-                bResult &= IFRFbWriteEmbedded(pDevice->PortOffset, 0x0001B400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW);
-            } else {
-                bResult &= IFRFbWriteEmbedded(pDevice->PortOffset, 0x0005A400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW);
-            }
-            break;
-
-
-        case RF_AL2230S :
-            bResult &= IFRFbWriteEmbedded(pDevice->PortOffset, dwAL2230PowerTable[byPwr]);
-            if (uRATE <= RATE_11M) {
-                bResult &= IFRFbWriteEmbedded(pDevice->PortOffset, 0x040C1400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW);
-                bResult &= IFRFbWriteEmbedded(pDevice->PortOffset, 0x00299B00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW);
-            }else {
-                bResult &= IFRFbWriteEmbedded(pDevice->PortOffset, 0x0005A400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW);
-                bResult &= IFRFbWriteEmbedded(pDevice->PortOffset, 0x00099B00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW);
-            }
-
-            break;
-
-        case RF_AIROHA7230:
-            //  0x080F1B00 for 3 wire control TxGain(D10) and 0x31 as TX Gain value
-            dwMax7230Pwr = 0x080C0B00 | ( (byPwr) << 12 ) |
-                           (BY_AL7230_REG_LEN << 3 )  | IFREGCTL_REGW;
-
-            bResult &= IFRFbWriteEmbedded(pDevice->PortOffset, dwMax7230Pwr);
-            break;
-
-
-        default :
-            break;
-    }
-    return bResult;
+	bool bResult = true;
+	unsigned long dwMax7230Pwr = 0;
+
+	if (byPwr >=  pDevice->byMaxPwrLevel) {
+		return false;
+	}
+	switch (pDevice->byRFType) {
+	case RF_AIROHA:
+		bResult &= IFRFbWriteEmbedded(pDevice->PortOffset, dwAL2230PowerTable[byPwr]);
+		if (uRATE <= RATE_11M) {
+			bResult &= IFRFbWriteEmbedded(pDevice->PortOffset, 0x0001B400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW);
+		} else {
+			bResult &= IFRFbWriteEmbedded(pDevice->PortOffset, 0x0005A400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW);
+		}
+		break;
+
+	case RF_AL2230S:
+		bResult &= IFRFbWriteEmbedded(pDevice->PortOffset, dwAL2230PowerTable[byPwr]);
+		if (uRATE <= RATE_11M) {
+			bResult &= IFRFbWriteEmbedded(pDevice->PortOffset, 0x040C1400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW);
+			bResult &= IFRFbWriteEmbedded(pDevice->PortOffset, 0x00299B00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW);
+		} else {
+			bResult &= IFRFbWriteEmbedded(pDevice->PortOffset, 0x0005A400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW);
+			bResult &= IFRFbWriteEmbedded(pDevice->PortOffset, 0x00099B00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW);
+		}
+
+		break;
+
+	case RF_AIROHA7230:
+		//  0x080F1B00 for 3 wire control TxGain(D10) and 0x31 as TX Gain value
+		dwMax7230Pwr = 0x080C0B00 | ((byPwr) << 12) |
+			(BY_AL7230_REG_LEN << 3)  | IFREGCTL_REGW;
+
+		bResult &= IFRFbWriteEmbedded(pDevice->PortOffset, dwMax7230Pwr);
+		break;
+
+	default:
+		break;
+	}
+	return bResult;
 }
 
 /*+
@@ -1122,74 +1088,68 @@ unsigned long dwMax7230Pwr = 0;
  *
  * Return Value: none
  *
--*/
+ -*/
 void
-RFvRSSITodBm (
-    PSDevice pDevice,
-    unsigned char byCurrRSSI,
-    long *    pldBm
-    )
+RFvRSSITodBm(
+	PSDevice pDevice,
+	unsigned char byCurrRSSI,
+	long *pldBm
+	)
 {
-    unsigned char byIdx = (((byCurrRSSI & 0xC0) >> 6) & 0x03);
-    long b = (byCurrRSSI & 0x3F);
-    long a = 0;
-    unsigned char abyAIROHARF[4] = {0, 18, 0, 40};
-
-    switch (pDevice->byRFType) {
-        case RF_AIROHA:
-        case RF_AL2230S:
-        case RF_AIROHA7230: //RobertYu: 20040104
-            a = abyAIROHARF[byIdx];
-            break;
-        default:
-            break;
-    }
-
-    *pldBm = -1 * (a + b * 2);
+	unsigned char byIdx = (((byCurrRSSI & 0xC0) >> 6) & 0x03);
+	long b = (byCurrRSSI & 0x3F);
+	long a = 0;
+	unsigned char abyAIROHARF[4] = {0, 18, 0, 40};
+
+	switch (pDevice->byRFType) {
+	case RF_AIROHA:
+	case RF_AL2230S:
+	case RF_AIROHA7230: //RobertYu: 20040104
+		a = abyAIROHARF[byIdx];
+		break;
+	default:
+		break;
+	}
+
+	*pldBm = -1 * (a + b * 2);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 //{{ RobertYu: 20050104
 
-
 // Post processing for the 11b/g and 11a.
 // for save time on changing Reg2,3,5,7,10,12,15
-bool RFbAL7230SelectChannelPostProcess (unsigned long dwIoBase, unsigned char byOldChannel, unsigned char byNewChannel)
+bool RFbAL7230SelectChannelPostProcess(unsigned long dwIoBase, unsigned char byOldChannel, unsigned char byNewChannel)
 {
-    bool bResult;
-
-    bResult = true;
-
-    // if change between 11 b/g and 11a need to update the following register
-    // Channel Index 1~14
-
-    if( (byOldChannel <= CB_MAX_CHANNEL_24G) && (byNewChannel > CB_MAX_CHANNEL_24G) )
-    {
-        // Change from 2.4G to 5G
-        bResult &= IFRFbWriteEmbedded(dwIoBase, dwAL7230InitTableAMode[2]); //Reg2
-        bResult &= IFRFbWriteEmbedded(dwIoBase, dwAL7230InitTableAMode[3]); //Reg3
-        bResult &= IFRFbWriteEmbedded(dwIoBase, dwAL7230InitTableAMode[5]); //Reg5
-        bResult &= IFRFbWriteEmbedded(dwIoBase, dwAL7230InitTableAMode[7]); //Reg7
-        bResult &= IFRFbWriteEmbedded(dwIoBase, dwAL7230InitTableAMode[10]);//Reg10
-        bResult &= IFRFbWriteEmbedded(dwIoBase, dwAL7230InitTableAMode[12]);//Reg12
-        bResult &= IFRFbWriteEmbedded(dwIoBase, dwAL7230InitTableAMode[15]);//Reg15
-    }
-    else if( (byOldChannel > CB_MAX_CHANNEL_24G) && (byNewChannel <= CB_MAX_CHANNEL_24G) )
-    {
-        // change from 5G to 2.4G
-        bResult &= IFRFbWriteEmbedded(dwIoBase, dwAL7230InitTable[2]); //Reg2
-        bResult &= IFRFbWriteEmbedded(dwIoBase, dwAL7230InitTable[3]); //Reg3
-        bResult &= IFRFbWriteEmbedded(dwIoBase, dwAL7230InitTable[5]); //Reg5
-        bResult &= IFRFbWriteEmbedded(dwIoBase, dwAL7230InitTable[7]); //Reg7
-        bResult &= IFRFbWriteEmbedded(dwIoBase, dwAL7230InitTable[10]);//Reg10
-        bResult &= IFRFbWriteEmbedded(dwIoBase, dwAL7230InitTable[12]);//Reg12
-        bResult &= IFRFbWriteEmbedded(dwIoBase, dwAL7230InitTable[15]);//Reg15
-    }
-
-    return bResult;
+	bool bResult;
+
+	bResult = true;
+
+	// if change between 11 b/g and 11a need to update the following register
+	// Channel Index 1~14
+
+	if ((byOldChannel <= CB_MAX_CHANNEL_24G) && (byNewChannel > CB_MAX_CHANNEL_24G)) {
+		// Change from 2.4G to 5G
+		bResult &= IFRFbWriteEmbedded(dwIoBase, dwAL7230InitTableAMode[2]); //Reg2
+		bResult &= IFRFbWriteEmbedded(dwIoBase, dwAL7230InitTableAMode[3]); //Reg3
+		bResult &= IFRFbWriteEmbedded(dwIoBase, dwAL7230InitTableAMode[5]); //Reg5
+		bResult &= IFRFbWriteEmbedded(dwIoBase, dwAL7230InitTableAMode[7]); //Reg7
+		bResult &= IFRFbWriteEmbedded(dwIoBase, dwAL7230InitTableAMode[10]);//Reg10
+		bResult &= IFRFbWriteEmbedded(dwIoBase, dwAL7230InitTableAMode[12]);//Reg12
+		bResult &= IFRFbWriteEmbedded(dwIoBase, dwAL7230InitTableAMode[15]);//Reg15
+	} else if ((byOldChannel > CB_MAX_CHANNEL_24G) && (byNewChannel <= CB_MAX_CHANNEL_24G)) {
+		// change from 5G to 2.4G
+		bResult &= IFRFbWriteEmbedded(dwIoBase, dwAL7230InitTable[2]); //Reg2
+		bResult &= IFRFbWriteEmbedded(dwIoBase, dwAL7230InitTable[3]); //Reg3
+		bResult &= IFRFbWriteEmbedded(dwIoBase, dwAL7230InitTable[5]); //Reg5
+		bResult &= IFRFbWriteEmbedded(dwIoBase, dwAL7230InitTable[7]); //Reg7
+		bResult &= IFRFbWriteEmbedded(dwIoBase, dwAL7230InitTable[10]);//Reg10
+		bResult &= IFRFbWriteEmbedded(dwIoBase, dwAL7230InitTable[12]);//Reg12
+		bResult &= IFRFbWriteEmbedded(dwIoBase, dwAL7230InitTable[15]);//Reg15
+	}
+
+	return bResult;
 }
 
-
 //}} RobertYu
 ////////////////////////////////////////////////////////////////////////////////
-
diff --git a/drivers/staging/vt6655/rf.h b/drivers/staging/vt6655/rf.h
index 1da0fde..ef3c6de 100644
--- a/drivers/staging/vt6655/rf.h
+++ b/drivers/staging/vt6655/rf.h
@@ -68,7 +68,6 @@
 #define CB_MAXIM2829_CHANNEL_5G_HIGH    41 //Index41: channel = 100, Tf = 5500MHz, set the (A3:A0=0101) D6=1
 #define CB_UW2452_CHANNEL_5G_HIGH       41 //[20041210] Index41: channel = 100, Tf = 5500MHz, change VCO2->VCO3
 
-
 /*---------------------  Export Classes  ----------------------------*/
 
 /*---------------------  Export Variables  --------------------------*/
@@ -77,29 +76,26 @@
 
 bool IFRFbWriteEmbedded(unsigned long dwIoBase, unsigned long dwData);
 bool RFbSelectChannel(unsigned long dwIoBase, unsigned char byRFType, unsigned char byChannel);
-bool RFbInit (
-    PSDevice  pDevice
-    );
+bool RFbInit(
+	PSDevice  pDevice
+);
 bool RFvWriteWakeProgSyn(unsigned long dwIoBase, unsigned char byRFType, unsigned int uChannel);
 bool RFbSetPower(PSDevice pDevice, unsigned int uRATE, unsigned int uCH);
 bool RFbRawSetPower(
-    PSDevice  pDevice,
-    unsigned char byPwr,
-    unsigned int uRATE
-    );
+	PSDevice  pDevice,
+	unsigned char byPwr,
+	unsigned int uRATE
+);
 
 void
 RFvRSSITodBm(
-    PSDevice pDevice,
-    unsigned char byCurrRSSI,
-    long    *pldBm
-    );
+	PSDevice pDevice,
+	unsigned char byCurrRSSI,
+	long    *pldBm
+);
 
 //{{ RobertYu: 20050104
 bool RFbAL7230SelectChannelPostProcess(unsigned long dwIoBase, unsigned char byOldChannel, unsigned char byNewChannel);
 //}} RobertYu
 
 #endif // __RF_H__
-
-
-
diff --git a/drivers/staging/vt6655/rxtx.c b/drivers/staging/vt6655/rxtx.c
index d66854f..3a2661e 100644
--- a/drivers/staging/vt6655/rxtx.c
+++ b/drivers/staging/vt6655/rxtx.c
@@ -69,11 +69,10 @@
 
 /*---------------------  Static Variables  --------------------------*/
 //static int          msglevel                =MSG_LEVEL_DEBUG;
-static int          msglevel                =MSG_LEVEL_INFO;
+static int msglevel = MSG_LEVEL_INFO;
 
 #define	PLICE_DEBUG
 
-
 /*---------------------  Static Functions  --------------------------*/
 
 /*---------------------  Static Definitions -------------------------*/
@@ -81,19 +80,18 @@ static int          msglevel                =MSG_LEVEL_INFO;
                                         //    packet size >= 256 -> direct send
 
 const unsigned short wTimeStampOff[2][MAX_RATE] = {
-        {384, 288, 226, 209, 54, 43, 37, 31, 28, 25, 24, 23}, // Long Preamble
-        {384, 192, 130, 113, 54, 43, 37, 31, 28, 25, 24, 23}, // Short Preamble
-    };
+	{384, 288, 226, 209, 54, 43, 37, 31, 28, 25, 24, 23}, // Long Preamble
+	{384, 192, 130, 113, 54, 43, 37, 31, 28, 25, 24, 23}, // Short Preamble
+};
 
 const unsigned short wFB_Opt0[2][5] = {
-        {RATE_12M, RATE_18M, RATE_24M, RATE_36M, RATE_48M}, // fallback_rate0
-        {RATE_12M, RATE_12M, RATE_18M, RATE_24M, RATE_36M}, // fallback_rate1
-    };
+	{RATE_12M, RATE_18M, RATE_24M, RATE_36M, RATE_48M}, // fallback_rate0
+	{RATE_12M, RATE_12M, RATE_18M, RATE_24M, RATE_36M}, // fallback_rate1
+};
 const unsigned short wFB_Opt1[2][5] = {
-        {RATE_12M, RATE_18M, RATE_24M, RATE_24M, RATE_36M}, // fallback_rate0
-        {RATE_6M , RATE_6M,  RATE_12M, RATE_12M, RATE_18M}, // fallback_rate1
-    };
-
+	{RATE_12M, RATE_18M, RATE_24M, RATE_24M, RATE_36M}, // fallback_rate0
+	{RATE_6M , RATE_6M,  RATE_12M, RATE_12M, RATE_18M}, // fallback_rate1
+};
 
 #define RTSDUR_BB       0
 #define RTSDUR_BA       1
@@ -112,1009 +110,946 @@ const unsigned short wFB_Opt1[2][5] = {
 
 /*---------------------  Static Functions  --------------------------*/
 
-
-
 static
 void
 s_vFillTxKey(
-    PSDevice   pDevice,
-    unsigned char *pbyBuf,
-    unsigned char *pbyIVHead,
-    PSKeyItem  pTransmitKey,
-    unsigned char *pbyHdrBuf,
-    unsigned short wPayloadLen,
-    unsigned char *pMICHDR
-    );
-
-
+	PSDevice   pDevice,
+	unsigned char *pbyBuf,
+	unsigned char *pbyIVHead,
+	PSKeyItem  pTransmitKey,
+	unsigned char *pbyHdrBuf,
+	unsigned short wPayloadLen,
+	unsigned char *pMICHDR
+);
 
 static
 void
 s_vFillRTSHead(
-    PSDevice         pDevice,
-    unsigned char byPktType,
-    void *           pvRTS,
-    unsigned int	cbFrameLength,
-    bool bNeedAck,
-    bool bDisCRC,
-    PSEthernetHeader psEthHeader,
-    unsigned short wCurrentRate,
-    unsigned char byFBOption
-    );
+	PSDevice         pDevice,
+	unsigned char byPktType,
+	void *pvRTS,
+	unsigned int	cbFrameLength,
+	bool bNeedAck,
+	bool bDisCRC,
+	PSEthernetHeader psEthHeader,
+	unsigned short wCurrentRate,
+	unsigned char byFBOption
+);
 
 static
 void
 s_vGenerateTxParameter(
-    PSDevice         pDevice,
-    unsigned char byPktType,
-    void *           pTxBufHead,
-    void *           pvRrvTime,
-    void *           pvRTS,
-    void *           pvCTS,
-    unsigned int	cbFrameSize,
-    bool bNeedACK,
-    unsigned int	uDMAIdx,
-    PSEthernetHeader psEthHeader,
-    unsigned short wCurrentRate
-    );
-
-
+	PSDevice         pDevice,
+	unsigned char byPktType,
+	void *pTxBufHead,
+	void *pvRrvTime,
+	void *pvRTS,
+	void *pvCTS,
+	unsigned int	cbFrameSize,
+	bool bNeedACK,
+	unsigned int	uDMAIdx,
+	PSEthernetHeader psEthHeader,
+	unsigned short wCurrentRate
+);
 
 static void s_vFillFragParameter(
-    PSDevice pDevice,
-    unsigned char *pbyBuffer,
-    unsigned int	uTxType,
-    void *   pvtdCurr,
-    unsigned short wFragType,
-    unsigned int	cbReqCount
-    );
-
+	PSDevice pDevice,
+	unsigned char *pbyBuffer,
+	unsigned int	uTxType,
+	void *pvtdCurr,
+	unsigned short wFragType,
+	unsigned int	cbReqCount
+);
 
 static unsigned int
 s_cbFillTxBufHead(PSDevice pDevice, unsigned char byPktType, unsigned char *pbyTxBufferAddr,
-	unsigned int cbFrameBodySize, unsigned int uDMAIdx, PSTxDesc pHeadTD,
-	PSEthernetHeader psEthHeader, unsigned char *pPacket, bool bNeedEncrypt,
-	PSKeyItem pTransmitKey, unsigned int uNodeIndex, unsigned int *puMACfragNum);
-
+		  unsigned int cbFrameBodySize, unsigned int uDMAIdx, PSTxDesc pHeadTD,
+		  PSEthernetHeader psEthHeader, unsigned char *pPacket, bool bNeedEncrypt,
+		  PSKeyItem pTransmitKey, unsigned int uNodeIndex, unsigned int *puMACfragNum);
 
 static
 unsigned int
-s_uFillDataHead (
-    PSDevice pDevice,
-    unsigned char byPktType,
-    void *   pTxDataHead,
-    unsigned int cbFrameLength,
-    unsigned int uDMAIdx,
-    bool bNeedAck,
-    unsigned int uFragIdx,
-    unsigned int cbLastFragmentSize,
-    unsigned int uMACfragNum,
-    unsigned char byFBOption,
-    unsigned short wCurrentRate
-    );
-
+s_uFillDataHead(
+	PSDevice pDevice,
+	unsigned char byPktType,
+	void *pTxDataHead,
+	unsigned int cbFrameLength,
+	unsigned int uDMAIdx,
+	bool bNeedAck,
+	unsigned int uFragIdx,
+	unsigned int cbLastFragmentSize,
+	unsigned int uMACfragNum,
+	unsigned char byFBOption,
+	unsigned short wCurrentRate
+);
 
 /*---------------------  Export Variables  --------------------------*/
 
-
-
 static
 void
-s_vFillTxKey (
-    PSDevice   pDevice,
-    unsigned char *pbyBuf,
-    unsigned char *pbyIVHead,
-    PSKeyItem  pTransmitKey,
-    unsigned char *pbyHdrBuf,
-    unsigned short wPayloadLen,
-    unsigned char *pMICHDR
-    )
+s_vFillTxKey(
+	PSDevice   pDevice,
+	unsigned char *pbyBuf,
+	unsigned char *pbyIVHead,
+	PSKeyItem  pTransmitKey,
+	unsigned char *pbyHdrBuf,
+	unsigned short wPayloadLen,
+	unsigned char *pMICHDR
+)
 {
-    unsigned long *pdwIV = (unsigned long *) pbyIVHead;
-    unsigned long *pdwExtIV = (unsigned long *) ((unsigned char *)pbyIVHead+4);
-    unsigned short wValue;
-    PS802_11Header  pMACHeader = (PS802_11Header)pbyHdrBuf;
-    unsigned long dwRevIVCounter;
-    unsigned char byKeyIndex = 0;
-
-
-
-    //Fill TXKEY
-    if (pTransmitKey == NULL)
-        return;
-
-    dwRevIVCounter = cpu_to_le32(pDevice->dwIVCounter);
-    *pdwIV = pDevice->dwIVCounter;
-    byKeyIndex = pTransmitKey->dwKeyIndex & 0xf;
-
-    if (pTransmitKey->byCipherSuite == KEY_CTL_WEP) {
-        if (pTransmitKey->uKeyLength == WLAN_WEP232_KEYLEN ){
-            memcpy(pDevice->abyPRNG, (unsigned char *)&(dwRevIVCounter), 3);
-            memcpy(pDevice->abyPRNG+3, pTransmitKey->abyKey, pTransmitKey->uKeyLength);
-        } else {
-            memcpy(pbyBuf, (unsigned char *)&(dwRevIVCounter), 3);
-            memcpy(pbyBuf+3, pTransmitKey->abyKey, pTransmitKey->uKeyLength);
-            if(pTransmitKey->uKeyLength == WLAN_WEP40_KEYLEN) {
-                memcpy(pbyBuf+8, (unsigned char *)&(dwRevIVCounter), 3);
-                memcpy(pbyBuf+11, pTransmitKey->abyKey, pTransmitKey->uKeyLength);
-            }
-            memcpy(pDevice->abyPRNG, pbyBuf, 16);
-        }
-        // Append IV after Mac Header
-        *pdwIV &= WEP_IV_MASK;//00000000 11111111 11111111 11111111
-        *pdwIV |= (unsigned long)byKeyIndex << 30;
-        *pdwIV = cpu_to_le32(*pdwIV);
-        pDevice->dwIVCounter++;
-        if (pDevice->dwIVCounter > WEP_IV_MASK) {
-            pDevice->dwIVCounter = 0;
-        }
-    } else if (pTransmitKey->byCipherSuite == KEY_CTL_TKIP) {
-        pTransmitKey->wTSC15_0++;
-        if (pTransmitKey->wTSC15_0 == 0) {
-            pTransmitKey->dwTSC47_16++;
-        }
-        TKIPvMixKey(pTransmitKey->abyKey, pDevice->abyCurrentNetAddr,
-                    pTransmitKey->wTSC15_0, pTransmitKey->dwTSC47_16, pDevice->abyPRNG);
-        memcpy(pbyBuf, pDevice->abyPRNG, 16);
-        // Make IV
-        memcpy(pdwIV, pDevice->abyPRNG, 3);
-
-        *(pbyIVHead+3) = (unsigned char)(((byKeyIndex << 6) & 0xc0) | 0x20); // 0x20 is ExtIV
-        // Append IV&ExtIV after Mac Header
-        *pdwExtIV = cpu_to_le32(pTransmitKey->dwTSC47_16);
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"vFillTxKey()---- pdwExtIV: %lx\n", *pdwExtIV);
-
-    } else if (pTransmitKey->byCipherSuite == KEY_CTL_CCMP) {
-        pTransmitKey->wTSC15_0++;
-        if (pTransmitKey->wTSC15_0 == 0) {
-            pTransmitKey->dwTSC47_16++;
-        }
-        memcpy(pbyBuf, pTransmitKey->abyKey, 16);
-
-        // Make IV
-        *pdwIV = 0;
-        *(pbyIVHead+3) = (unsigned char)(((byKeyIndex << 6) & 0xc0) | 0x20); // 0x20 is ExtIV
-        *pdwIV |= cpu_to_le16((unsigned short)(pTransmitKey->wTSC15_0));
-        //Append IV&ExtIV after Mac Header
-        *pdwExtIV = cpu_to_le32(pTransmitKey->dwTSC47_16);
-
-        //Fill MICHDR0
-        *pMICHDR = 0x59;
-        *((unsigned char *)(pMICHDR+1)) = 0; // TxPriority
-        memcpy(pMICHDR+2, &(pMACHeader->abyAddr2[0]), 6);
-        *((unsigned char *)(pMICHDR+8)) = HIBYTE(HIWORD(pTransmitKey->dwTSC47_16));
-        *((unsigned char *)(pMICHDR+9)) = LOBYTE(HIWORD(pTransmitKey->dwTSC47_16));
-        *((unsigned char *)(pMICHDR+10)) = HIBYTE(LOWORD(pTransmitKey->dwTSC47_16));
-        *((unsigned char *)(pMICHDR+11)) = LOBYTE(LOWORD(pTransmitKey->dwTSC47_16));
-        *((unsigned char *)(pMICHDR+12)) = HIBYTE(pTransmitKey->wTSC15_0);
-        *((unsigned char *)(pMICHDR+13)) = LOBYTE(pTransmitKey->wTSC15_0);
-        *((unsigned char *)(pMICHDR+14)) = HIBYTE(wPayloadLen);
-        *((unsigned char *)(pMICHDR+15)) = LOBYTE(wPayloadLen);
-
-        //Fill MICHDR1
-        *((unsigned char *)(pMICHDR+16)) = 0; // HLEN[15:8]
-        if (pDevice->bLongHeader) {
-            *((unsigned char *)(pMICHDR+17)) = 28; // HLEN[7:0]
-        } else {
-            *((unsigned char *)(pMICHDR+17)) = 22; // HLEN[7:0]
-        }
-        wValue = cpu_to_le16(pMACHeader->wFrameCtl & 0xC78F);
-        memcpy(pMICHDR+18, (unsigned char *)&wValue, 2); // MSKFRACTL
-        memcpy(pMICHDR+20, &(pMACHeader->abyAddr1[0]), 6);
-        memcpy(pMICHDR+26, &(pMACHeader->abyAddr2[0]), 6);
-
-        //Fill MICHDR2
-        memcpy(pMICHDR+32, &(pMACHeader->abyAddr3[0]), 6);
-        wValue = pMACHeader->wSeqCtl;
-        wValue &= 0x000F;
-        wValue = cpu_to_le16(wValue);
-        memcpy(pMICHDR+38, (unsigned char *)&wValue, 2); // MSKSEQCTL
-        if (pDevice->bLongHeader) {
-            memcpy(pMICHDR+40, &(pMACHeader->abyAddr4[0]), 6);
-        }
-    }
+	unsigned long *pdwIV = (unsigned long *)pbyIVHead;
+	unsigned long *pdwExtIV = (unsigned long *)((unsigned char *)pbyIVHead+4);
+	unsigned short wValue;
+	PS802_11Header  pMACHeader = (PS802_11Header)pbyHdrBuf;
+	unsigned long dwRevIVCounter;
+	unsigned char byKeyIndex = 0;
+
+	//Fill TXKEY
+	if (pTransmitKey == NULL)
+		return;
+
+	dwRevIVCounter = cpu_to_le32(pDevice->dwIVCounter);
+	*pdwIV = pDevice->dwIVCounter;
+	byKeyIndex = pTransmitKey->dwKeyIndex & 0xf;
+
+	if (pTransmitKey->byCipherSuite == KEY_CTL_WEP) {
+		if (pTransmitKey->uKeyLength == WLAN_WEP232_KEYLEN) {
+			memcpy(pDevice->abyPRNG, (unsigned char *)&(dwRevIVCounter), 3);
+			memcpy(pDevice->abyPRNG+3, pTransmitKey->abyKey, pTransmitKey->uKeyLength);
+		} else {
+			memcpy(pbyBuf, (unsigned char *)&(dwRevIVCounter), 3);
+			memcpy(pbyBuf+3, pTransmitKey->abyKey, pTransmitKey->uKeyLength);
+			if (pTransmitKey->uKeyLength == WLAN_WEP40_KEYLEN) {
+				memcpy(pbyBuf+8, (unsigned char *)&(dwRevIVCounter), 3);
+				memcpy(pbyBuf+11, pTransmitKey->abyKey, pTransmitKey->uKeyLength);
+			}
+			memcpy(pDevice->abyPRNG, pbyBuf, 16);
+		}
+		// Append IV after Mac Header
+		*pdwIV &= WEP_IV_MASK;//00000000 11111111 11111111 11111111
+		*pdwIV |= (unsigned long)byKeyIndex << 30;
+		*pdwIV = cpu_to_le32(*pdwIV);
+		pDevice->dwIVCounter++;
+		if (pDevice->dwIVCounter > WEP_IV_MASK) {
+			pDevice->dwIVCounter = 0;
+		}
+	} else if (pTransmitKey->byCipherSuite == KEY_CTL_TKIP) {
+		pTransmitKey->wTSC15_0++;
+		if (pTransmitKey->wTSC15_0 == 0) {
+			pTransmitKey->dwTSC47_16++;
+		}
+		TKIPvMixKey(pTransmitKey->abyKey, pDevice->abyCurrentNetAddr,
+			    pTransmitKey->wTSC15_0, pTransmitKey->dwTSC47_16, pDevice->abyPRNG);
+		memcpy(pbyBuf, pDevice->abyPRNG, 16);
+		// Make IV
+		memcpy(pdwIV, pDevice->abyPRNG, 3);
+
+		*(pbyIVHead+3) = (unsigned char)(((byKeyIndex << 6) & 0xc0) | 0x20); // 0x20 is ExtIV
+		// Append IV&ExtIV after Mac Header
+		*pdwExtIV = cpu_to_le32(pTransmitKey->dwTSC47_16);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "vFillTxKey()---- pdwExtIV: %lx\n", *pdwExtIV);
+
+	} else if (pTransmitKey->byCipherSuite == KEY_CTL_CCMP) {
+		pTransmitKey->wTSC15_0++;
+		if (pTransmitKey->wTSC15_0 == 0) {
+			pTransmitKey->dwTSC47_16++;
+		}
+		memcpy(pbyBuf, pTransmitKey->abyKey, 16);
+
+		// Make IV
+		*pdwIV = 0;
+		*(pbyIVHead+3) = (unsigned char)(((byKeyIndex << 6) & 0xc0) | 0x20); // 0x20 is ExtIV
+		*pdwIV |= cpu_to_le16((unsigned short)(pTransmitKey->wTSC15_0));
+		//Append IV&ExtIV after Mac Header
+		*pdwExtIV = cpu_to_le32(pTransmitKey->dwTSC47_16);
+
+		//Fill MICHDR0
+		*pMICHDR = 0x59;
+		*((unsigned char *)(pMICHDR+1)) = 0; // TxPriority
+		memcpy(pMICHDR+2, &(pMACHeader->abyAddr2[0]), 6);
+		*((unsigned char *)(pMICHDR+8)) = HIBYTE(HIWORD(pTransmitKey->dwTSC47_16));
+		*((unsigned char *)(pMICHDR+9)) = LOBYTE(HIWORD(pTransmitKey->dwTSC47_16));
+		*((unsigned char *)(pMICHDR+10)) = HIBYTE(LOWORD(pTransmitKey->dwTSC47_16));
+		*((unsigned char *)(pMICHDR+11)) = LOBYTE(LOWORD(pTransmitKey->dwTSC47_16));
+		*((unsigned char *)(pMICHDR+12)) = HIBYTE(pTransmitKey->wTSC15_0);
+		*((unsigned char *)(pMICHDR+13)) = LOBYTE(pTransmitKey->wTSC15_0);
+		*((unsigned char *)(pMICHDR+14)) = HIBYTE(wPayloadLen);
+		*((unsigned char *)(pMICHDR+15)) = LOBYTE(wPayloadLen);
+
+		//Fill MICHDR1
+		*((unsigned char *)(pMICHDR+16)) = 0; // HLEN[15:8]
+		if (pDevice->bLongHeader) {
+			*((unsigned char *)(pMICHDR+17)) = 28; // HLEN[7:0]
+		} else {
+			*((unsigned char *)(pMICHDR+17)) = 22; // HLEN[7:0]
+		}
+		wValue = cpu_to_le16(pMACHeader->wFrameCtl & 0xC78F);
+		memcpy(pMICHDR+18, (unsigned char *)&wValue, 2); // MSKFRACTL
+		memcpy(pMICHDR+20, &(pMACHeader->abyAddr1[0]), 6);
+		memcpy(pMICHDR+26, &(pMACHeader->abyAddr2[0]), 6);
+
+		//Fill MICHDR2
+		memcpy(pMICHDR+32, &(pMACHeader->abyAddr3[0]), 6);
+		wValue = pMACHeader->wSeqCtl;
+		wValue &= 0x000F;
+		wValue = cpu_to_le16(wValue);
+		memcpy(pMICHDR+38, (unsigned char *)&wValue, 2); // MSKSEQCTL
+		if (pDevice->bLongHeader) {
+			memcpy(pMICHDR+40, &(pMACHeader->abyAddr4[0]), 6);
+		}
+	}
 }
 
-
 static
 void
-s_vSWencryption (
-    PSDevice            pDevice,
-    PSKeyItem           pTransmitKey,
-    unsigned char *pbyPayloadHead,
-    unsigned short wPayloadSize
-    )
+s_vSWencryption(
+	PSDevice            pDevice,
+	PSKeyItem           pTransmitKey,
+	unsigned char *pbyPayloadHead,
+	unsigned short wPayloadSize
+)
 {
-    unsigned int cbICVlen = 4;
-    unsigned long dwICV = 0xFFFFFFFFL;
-    unsigned long *pdwICV;
-
-    if (pTransmitKey == NULL)
-        return;
-
-    if (pTransmitKey->byCipherSuite == KEY_CTL_WEP) {
-        //=======================================================================
-        // Append ICV after payload
-        dwICV = CRCdwGetCrc32Ex(pbyPayloadHead, wPayloadSize, dwICV);//ICV(Payload)
-        pdwICV = (unsigned long *)(pbyPayloadHead + wPayloadSize);
-        // finally, we must invert dwCRC to get the correct answer
-        *pdwICV = cpu_to_le32(~dwICV);
-        // RC4 encryption
-        rc4_init(&pDevice->SBox, pDevice->abyPRNG, pTransmitKey->uKeyLength + 3);
-        rc4_encrypt(&pDevice->SBox, pbyPayloadHead, pbyPayloadHead, wPayloadSize+cbICVlen);
-        //=======================================================================
-    } else if (pTransmitKey->byCipherSuite == KEY_CTL_TKIP) {
-        //=======================================================================
-        //Append ICV after payload
-        dwICV = CRCdwGetCrc32Ex(pbyPayloadHead, wPayloadSize, dwICV);//ICV(Payload)
-        pdwICV = (unsigned long *)(pbyPayloadHead + wPayloadSize);
-        // finally, we must invert dwCRC to get the correct answer
-        *pdwICV = cpu_to_le32(~dwICV);
-        // RC4 encryption
-        rc4_init(&pDevice->SBox, pDevice->abyPRNG, TKIP_KEY_LEN);
-        rc4_encrypt(&pDevice->SBox, pbyPayloadHead, pbyPayloadHead, wPayloadSize+cbICVlen);
-        //=======================================================================
-    }
+	unsigned int cbICVlen = 4;
+	unsigned long dwICV = 0xFFFFFFFFL;
+	unsigned long *pdwICV;
+
+	if (pTransmitKey == NULL)
+		return;
+
+	if (pTransmitKey->byCipherSuite == KEY_CTL_WEP) {
+		//=======================================================================
+		// Append ICV after payload
+		dwICV = CRCdwGetCrc32Ex(pbyPayloadHead, wPayloadSize, dwICV);//ICV(Payload)
+		pdwICV = (unsigned long *)(pbyPayloadHead + wPayloadSize);
+		// finally, we must invert dwCRC to get the correct answer
+		*pdwICV = cpu_to_le32(~dwICV);
+		// RC4 encryption
+		rc4_init(&pDevice->SBox, pDevice->abyPRNG, pTransmitKey->uKeyLength + 3);
+		rc4_encrypt(&pDevice->SBox, pbyPayloadHead, pbyPayloadHead, wPayloadSize+cbICVlen);
+		//=======================================================================
+	} else if (pTransmitKey->byCipherSuite == KEY_CTL_TKIP) {
+		//=======================================================================
+		//Append ICV after payload
+		dwICV = CRCdwGetCrc32Ex(pbyPayloadHead, wPayloadSize, dwICV);//ICV(Payload)
+		pdwICV = (unsigned long *)(pbyPayloadHead + wPayloadSize);
+		// finally, we must invert dwCRC to get the correct answer
+		*pdwICV = cpu_to_le32(~dwICV);
+		// RC4 encryption
+		rc4_init(&pDevice->SBox, pDevice->abyPRNG, TKIP_KEY_LEN);
+		rc4_encrypt(&pDevice->SBox, pbyPayloadHead, pbyPayloadHead, wPayloadSize+cbICVlen);
+		//=======================================================================
+	}
 }
 
-
-
-
 /*byPktType : PK_TYPE_11A     0
-             PK_TYPE_11B     1
-             PK_TYPE_11GB    2
-             PK_TYPE_11GA    3
+  PK_TYPE_11B     1
+  PK_TYPE_11GB    2
+  PK_TYPE_11GA    3
 */
 static
 unsigned int
-s_uGetTxRsvTime (
-    PSDevice pDevice,
-    unsigned char byPktType,
-    unsigned int cbFrameLength,
-    unsigned short wRate,
-    bool bNeedAck
-    )
+s_uGetTxRsvTime(
+	PSDevice pDevice,
+	unsigned char byPktType,
+	unsigned int cbFrameLength,
+	unsigned short wRate,
+	bool bNeedAck
+)
 {
-    unsigned int uDataTime, uAckTime;
-
-    uDataTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, cbFrameLength, wRate);
-#ifdef	PLICE_DEBUG
-	//printk("s_uGetTxRsvTime is %d\n",uDataTime);
-#endif
-    if (byPktType == PK_TYPE_11B) {//llb,CCK mode
-        uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, (unsigned short)pDevice->byTopCCKBasicRate);
-    } else {//11g 2.4G OFDM mode & 11a 5G OFDM mode
-        uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, (unsigned short)pDevice->byTopOFDMBasicRate);
-    }
-
-    if (bNeedAck) {
-        return (uDataTime + pDevice->uSIFS + uAckTime);
-    }
-    else {
-        return uDataTime;
-    }
+	unsigned int uDataTime, uAckTime;
+
+	uDataTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, cbFrameLength, wRate);
+	if (byPktType == PK_TYPE_11B) {//llb,CCK mode
+		uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, (unsigned short)pDevice->byTopCCKBasicRate);
+	} else {//11g 2.4G OFDM mode & 11a 5G OFDM mode
+		uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, (unsigned short)pDevice->byTopOFDMBasicRate);
+	}
+
+	if (bNeedAck) {
+		return uDataTime + pDevice->uSIFS + uAckTime;
+	} else {
+		return uDataTime;
+	}
 }
 
 //byFreqType: 0=>5GHZ 1=>2.4GHZ
 static
 unsigned int
-s_uGetRTSCTSRsvTime (
-    PSDevice pDevice,
-    unsigned char byRTSRsvType,
-    unsigned char byPktType,
-    unsigned int cbFrameLength,
-    unsigned short wCurrentRate
-    )
+s_uGetRTSCTSRsvTime(
+	PSDevice pDevice,
+	unsigned char byRTSRsvType,
+	unsigned char byPktType,
+	unsigned int cbFrameLength,
+	unsigned short wCurrentRate
+)
 {
-    unsigned int uRrvTime  , uRTSTime, uCTSTime, uAckTime, uDataTime;
-
-    uRrvTime = uRTSTime = uCTSTime = uAckTime = uDataTime = 0;
-
-
-    uDataTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, cbFrameLength, wCurrentRate);
-    if (byRTSRsvType == 0) { //RTSTxRrvTime_bb
-        uRTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 20, pDevice->byTopCCKBasicRate);
-        uCTSTime = uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate);
-    }
-    else if (byRTSRsvType == 1){ //RTSTxRrvTime_ba, only in 2.4GHZ
-        uRTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 20, pDevice->byTopCCKBasicRate);
-        uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate);
-        uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
-    }
-    else if (byRTSRsvType == 2) { //RTSTxRrvTime_aa
-        uRTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 20, pDevice->byTopOFDMBasicRate);
-        uCTSTime = uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
-    }
-    else if (byRTSRsvType == 3) { //CTSTxRrvTime_ba, only in 2.4GHZ
-        uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate);
-        uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
-        uRrvTime = uCTSTime + uAckTime + uDataTime + 2*pDevice->uSIFS;
-        return uRrvTime;
-    }
-
-    //RTSRrvTime
-    uRrvTime = uRTSTime + uCTSTime + uAckTime + uDataTime + 3*pDevice->uSIFS;
-    return uRrvTime;
+	unsigned int uRrvTime  , uRTSTime, uCTSTime, uAckTime, uDataTime;
+
+	uRrvTime = uRTSTime = uCTSTime = uAckTime = uDataTime = 0;
+
+	uDataTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, cbFrameLength, wCurrentRate);
+	if (byRTSRsvType == 0) { //RTSTxRrvTime_bb
+		uRTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 20, pDevice->byTopCCKBasicRate);
+		uCTSTime = uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate);
+	} else if (byRTSRsvType == 1) { //RTSTxRrvTime_ba, only in 2.4GHZ
+		uRTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 20, pDevice->byTopCCKBasicRate);
+		uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate);
+		uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
+	} else if (byRTSRsvType == 2) { //RTSTxRrvTime_aa
+		uRTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 20, pDevice->byTopOFDMBasicRate);
+		uCTSTime = uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
+	} else if (byRTSRsvType == 3) { //CTSTxRrvTime_ba, only in 2.4GHZ
+		uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate);
+		uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
+		uRrvTime = uCTSTime + uAckTime + uDataTime + 2*pDevice->uSIFS;
+		return uRrvTime;
+	}
+
+	//RTSRrvTime
+	uRrvTime = uRTSTime + uCTSTime + uAckTime + uDataTime + 3*pDevice->uSIFS;
+	return uRrvTime;
 }
 
 //byFreqType 0: 5GHz, 1:2.4Ghz
 static
 unsigned int
-s_uGetDataDuration (
-    PSDevice pDevice,
-    unsigned char byDurType,
-    unsigned int cbFrameLength,
-    unsigned char byPktType,
-    unsigned short wRate,
-    bool bNeedAck,
-    unsigned int uFragIdx,
-    unsigned int cbLastFragmentSize,
-    unsigned int uMACfragNum,
-    unsigned char byFBOption
-    )
+s_uGetDataDuration(
+	PSDevice pDevice,
+	unsigned char byDurType,
+	unsigned int cbFrameLength,
+	unsigned char byPktType,
+	unsigned short wRate,
+	bool bNeedAck,
+	unsigned int uFragIdx,
+	unsigned int cbLastFragmentSize,
+	unsigned int uMACfragNum,
+	unsigned char byFBOption
+)
 {
-    bool bLastFrag = 0;
-    unsigned int uAckTime =0, uNextPktTime = 0;
-
-
-
-    if (uFragIdx == (uMACfragNum-1)) {
-        bLastFrag = 1;
-    }
-
-
-    switch (byDurType) {
-
-    case DATADUR_B:    //DATADUR_B
-        if (((uMACfragNum == 1)) || (bLastFrag == 1)) {//Non Frag or Last Frag
-            if (bNeedAck) {
-            	uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate);
-                return (pDevice->uSIFS + uAckTime);
-            } else {
-                return 0;
-            }
-        }
-        else {//First Frag or Mid Frag
-            if (uFragIdx == (uMACfragNum-2)) {
-            	uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbLastFragmentSize, wRate, bNeedAck);
-            } else {
-                uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck);
-            }
-            if (bNeedAck) {
-            	uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate);
-                return (pDevice->uSIFS + uAckTime + uNextPktTime);
-            } else {
-                return (pDevice->uSIFS + uNextPktTime);
-            }
-        }
-        break;
-
-    case DATADUR_A:    //DATADUR_A
-        if (((uMACfragNum==1)) || (bLastFrag==1)) {//Non Frag or Last Frag
-            if(bNeedAck){
-            	uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
-                return (pDevice->uSIFS + uAckTime);
-            } else {
-                return 0;
-            }
-        }
-        else {//First Frag or Mid Frag
-            if(uFragIdx == (uMACfragNum-2)){
-            	uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbLastFragmentSize, wRate, bNeedAck);
-            } else {
-                uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck);
-            }
-            if(bNeedAck){
-            	uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
-                return (pDevice->uSIFS + uAckTime + uNextPktTime);
-            } else {
-                return (pDevice->uSIFS + uNextPktTime);
-            }
-        }
-        break;
-
-    case DATADUR_A_F0:    //DATADUR_A_F0
-	    if (((uMACfragNum==1)) || (bLastFrag==1)) {//Non Frag or Last Frag
-            if(bNeedAck){
-            	uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
-                return (pDevice->uSIFS + uAckTime);
-            } else {
-                return 0;
-            }
-        }
-	    else { //First Frag or Mid Frag
-	        if (byFBOption == AUTO_FB_0) {
-                if (wRate < RATE_18M)
-                    wRate = RATE_18M;
-                else if (wRate > RATE_54M)
-                    wRate = RATE_54M;
-
-	            if(uFragIdx == (uMACfragNum-2)){
-            	    uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbLastFragmentSize, wFB_Opt0[FB_RATE0][wRate-RATE_18M], bNeedAck);
-                } else {
-                    uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE0][wRate-RATE_18M], bNeedAck);
-                }
-	        } else { // (byFBOption == AUTO_FB_1)
-                if (wRate < RATE_18M)
-                    wRate = RATE_18M;
-                else if (wRate > RATE_54M)
-                    wRate = RATE_54M;
-
-	            if(uFragIdx == (uMACfragNum-2)){
-            	    uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbLastFragmentSize, wFB_Opt1[FB_RATE0][wRate-RATE_18M], bNeedAck);
-                } else {
-                    uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE0][wRate-RATE_18M], bNeedAck);
-                }
-	        }
-
-	        if(bNeedAck){
-            	uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
-                return (pDevice->uSIFS + uAckTime + uNextPktTime);
-            } else {
-                return (pDevice->uSIFS + uNextPktTime);
-            }
-	    }
-        break;
-
-    case DATADUR_A_F1:    //DATADUR_A_F1
-        if (((uMACfragNum==1)) || (bLastFrag==1)) {//Non Frag or Last Frag
-            if(bNeedAck){
-            	uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
-                return (pDevice->uSIFS + uAckTime);
-            } else {
-                return 0;
-            }
-        }
-	    else { //First Frag or Mid Frag
-	        if (byFBOption == AUTO_FB_0) {
-                if (wRate < RATE_18M)
-                    wRate = RATE_18M;
-                else if (wRate > RATE_54M)
-                    wRate = RATE_54M;
-
-	            if(uFragIdx == (uMACfragNum-2)){
-            	    uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbLastFragmentSize, wFB_Opt0[FB_RATE1][wRate-RATE_18M], bNeedAck);
-                } else {
-                    uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE1][wRate-RATE_18M], bNeedAck);
-                }
-
-	        } else { // (byFBOption == AUTO_FB_1)
-                if (wRate < RATE_18M)
-                    wRate = RATE_18M;
-                else if (wRate > RATE_54M)
-                    wRate = RATE_54M;
-
-	            if(uFragIdx == (uMACfragNum-2)){
-            	    uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbLastFragmentSize, wFB_Opt1[FB_RATE1][wRate-RATE_18M], bNeedAck);
-                } else {
-                    uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE1][wRate-RATE_18M], bNeedAck);
-                }
-	        }
-	        if(bNeedAck){
-            	uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
-                return (pDevice->uSIFS + uAckTime + uNextPktTime);
-            } else {
-                return (pDevice->uSIFS + uNextPktTime);
-            }
-	    }
-        break;
-
-    default:
-        break;
-    }
+	bool bLastFrag = 0;
+	unsigned int uAckTime = 0, uNextPktTime = 0;
+
+	if (uFragIdx == (uMACfragNum-1)) {
+		bLastFrag = 1;
+	}
+
+	switch (byDurType) {
+	case DATADUR_B:    //DATADUR_B
+		if (((uMACfragNum == 1)) || (bLastFrag == 1)) {//Non Frag or Last Frag
+			if (bNeedAck) {
+				uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate);
+				return pDevice->uSIFS + uAckTime;
+			} else {
+				return 0;
+			}
+		} else {//First Frag or Mid Frag
+			if (uFragIdx == (uMACfragNum-2)) {
+				uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbLastFragmentSize, wRate, bNeedAck);
+			} else {
+				uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck);
+			}
+			if (bNeedAck) {
+				uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate);
+				return pDevice->uSIFS + uAckTime + uNextPktTime;
+			} else {
+				return pDevice->uSIFS + uNextPktTime;
+			}
+		}
+		break;
+
+	case DATADUR_A:    //DATADUR_A
+		if (((uMACfragNum == 1)) || (bLastFrag == 1)) {//Non Frag or Last Frag
+			if (bNeedAck) {
+				uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
+				return pDevice->uSIFS + uAckTime;
+			} else {
+				return 0;
+			}
+		} else {//First Frag or Mid Frag
+			if (uFragIdx == (uMACfragNum-2)) {
+				uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbLastFragmentSize, wRate, bNeedAck);
+			} else {
+				uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck);
+			}
+			if (bNeedAck) {
+				uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
+				return pDevice->uSIFS + uAckTime + uNextPktTime;
+			} else {
+				return pDevice->uSIFS + uNextPktTime;
+			}
+		}
+		break;
+
+	case DATADUR_A_F0:    //DATADUR_A_F0
+		if (((uMACfragNum == 1)) || (bLastFrag == 1)) {//Non Frag or Last Frag
+			if (bNeedAck) {
+				uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
+				return pDevice->uSIFS + uAckTime;
+			} else {
+				return 0;
+			}
+		} else { //First Frag or Mid Frag
+			if (byFBOption == AUTO_FB_0) {
+				if (wRate < RATE_18M)
+					wRate = RATE_18M;
+				else if (wRate > RATE_54M)
+					wRate = RATE_54M;
+
+				if (uFragIdx == (uMACfragNum-2)) {
+					uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbLastFragmentSize, wFB_Opt0[FB_RATE0][wRate-RATE_18M], bNeedAck);
+				} else {
+					uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE0][wRate-RATE_18M], bNeedAck);
+				}
+			} else { // (byFBOption == AUTO_FB_1)
+				if (wRate < RATE_18M)
+					wRate = RATE_18M;
+				else if (wRate > RATE_54M)
+					wRate = RATE_54M;
+
+				if (uFragIdx == (uMACfragNum-2)) {
+					uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbLastFragmentSize, wFB_Opt1[FB_RATE0][wRate-RATE_18M], bNeedAck);
+				} else {
+					uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE0][wRate-RATE_18M], bNeedAck);
+				}
+			}
+
+			if (bNeedAck) {
+				uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
+				return pDevice->uSIFS + uAckTime + uNextPktTime;
+			} else {
+				return pDevice->uSIFS + uNextPktTime;
+			}
+		}
+		break;
+
+	case DATADUR_A_F1:    //DATADUR_A_F1
+		if (((uMACfragNum == 1)) || (bLastFrag == 1)) {//Non Frag or Last Frag
+			if (bNeedAck) {
+				uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
+				return pDevice->uSIFS + uAckTime;
+			} else {
+				return 0;
+			}
+		} else { //First Frag or Mid Frag
+			if (byFBOption == AUTO_FB_0) {
+				if (wRate < RATE_18M)
+					wRate = RATE_18M;
+				else if (wRate > RATE_54M)
+					wRate = RATE_54M;
+
+				if (uFragIdx == (uMACfragNum-2)) {
+					uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbLastFragmentSize, wFB_Opt0[FB_RATE1][wRate-RATE_18M], bNeedAck);
+				} else {
+					uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE1][wRate-RATE_18M], bNeedAck);
+				}
+
+			} else { // (byFBOption == AUTO_FB_1)
+				if (wRate < RATE_18M)
+					wRate = RATE_18M;
+				else if (wRate > RATE_54M)
+					wRate = RATE_54M;
+
+				if (uFragIdx == (uMACfragNum-2)) {
+					uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbLastFragmentSize, wFB_Opt1[FB_RATE1][wRate-RATE_18M], bNeedAck);
+				} else {
+					uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE1][wRate-RATE_18M], bNeedAck);
+				}
+			}
+			if (bNeedAck) {
+				uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
+				return pDevice->uSIFS + uAckTime + uNextPktTime;
+			} else {
+				return pDevice->uSIFS + uNextPktTime;
+			}
+		}
+		break;
+
+	default:
+		break;
+	}
 
 	ASSERT(false);
 	return 0;
 }
 
-
 //byFreqType: 0=>5GHZ 1=>2.4GHZ
 static
 unsigned int
-s_uGetRTSCTSDuration (
-    PSDevice pDevice,
-    unsigned char byDurType,
-    unsigned int cbFrameLength,
-    unsigned char byPktType,
-    unsigned short wRate,
-    bool bNeedAck,
-    unsigned char byFBOption
-    )
+s_uGetRTSCTSDuration(
+	PSDevice pDevice,
+	unsigned char byDurType,
+	unsigned int cbFrameLength,
+	unsigned char byPktType,
+	unsigned short wRate,
+	bool bNeedAck,
+	unsigned char byFBOption
+)
 {
-    unsigned int uCTSTime = 0, uDurTime = 0;
-
-
-    switch (byDurType) {
-
-    case RTSDUR_BB:    //RTSDuration_bb
-        uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate);
-        uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck);
-        break;
-
-    case RTSDUR_BA:    //RTSDuration_ba
-        uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate);
-        uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck);
-        break;
-
-    case RTSDUR_AA:    //RTSDuration_aa
-        uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
-        uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck);
-        break;
-
-    case CTSDUR_BA:    //CTSDuration_ba
-        uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck);
-        break;
-
-    case RTSDUR_BA_F0: //RTSDuration_ba_f0
-        uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate);
-        if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) {
-            uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE0][wRate-RATE_18M], bNeedAck);
-        } else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) {
-            uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE0][wRate-RATE_18M], bNeedAck);
-        }
-        break;
-
-    case RTSDUR_AA_F0: //RTSDuration_aa_f0
-        uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
-        if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) {
-            uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE0][wRate-RATE_18M], bNeedAck);
-        } else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) {
-            uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE0][wRate-RATE_18M], bNeedAck);
-        }
-        break;
-
-    case RTSDUR_BA_F1: //RTSDuration_ba_f1
-        uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate);
-        if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) {
-            uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE1][wRate-RATE_18M], bNeedAck);
-        } else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) {
-            uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE1][wRate-RATE_18M], bNeedAck);
-        }
-        break;
-
-    case RTSDUR_AA_F1: //RTSDuration_aa_f1
-        uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
-        if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) {
-            uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE1][wRate-RATE_18M], bNeedAck);
-        } else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) {
-            uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE1][wRate-RATE_18M], bNeedAck);
-        }
-        break;
-
-    case CTSDUR_BA_F0: //CTSDuration_ba_f0
-        if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) {
-            uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE0][wRate-RATE_18M], bNeedAck);
-        } else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) {
-            uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE0][wRate-RATE_18M], bNeedAck);
-        }
-        break;
-
-    case CTSDUR_BA_F1: //CTSDuration_ba_f1
-        if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) {
-            uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE1][wRate-RATE_18M], bNeedAck);
-        } else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) {
-            uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE1][wRate-RATE_18M], bNeedAck);
-        }
-        break;
-
-    default:
-        break;
-    }
-
-    return uDurTime;
-
+	unsigned int uCTSTime = 0, uDurTime = 0;
+
+	switch (byDurType) {
+	case RTSDUR_BB:    //RTSDuration_bb
+		uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate);
+		uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck);
+		break;
+
+	case RTSDUR_BA:    //RTSDuration_ba
+		uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate);
+		uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck);
+		break;
+
+	case RTSDUR_AA:    //RTSDuration_aa
+		uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
+		uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck);
+		break;
+
+	case CTSDUR_BA:    //CTSDuration_ba
+		uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck);
+		break;
+
+	case RTSDUR_BA_F0: //RTSDuration_ba_f0
+		uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate);
+		if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <= RATE_54M)) {
+			uDurTime = uCTSTime + 2 * pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE0][wRate-RATE_18M], bNeedAck);
+		} else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <= RATE_54M)) {
+			uDurTime = uCTSTime + 2 * pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE0][wRate-RATE_18M], bNeedAck);
+		}
+		break;
+
+	case RTSDUR_AA_F0: //RTSDuration_aa_f0
+		uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
+		if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <= RATE_54M)) {
+			uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE0][wRate-RATE_18M], bNeedAck);
+		} else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <= RATE_54M)) {
+			uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE0][wRate-RATE_18M], bNeedAck);
+		}
+		break;
+
+	case RTSDUR_BA_F1: //RTSDuration_ba_f1
+		uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate);
+		if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <= RATE_54M)) {
+			uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE1][wRate-RATE_18M], bNeedAck);
+		} else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <= RATE_54M)) {
+			uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE1][wRate-RATE_18M], bNeedAck);
+		}
+		break;
+
+	case RTSDUR_AA_F1: //RTSDuration_aa_f1
+		uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
+		if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <= RATE_54M)) {
+			uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE1][wRate-RATE_18M], bNeedAck);
+		} else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <= RATE_54M)) {
+			uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE1][wRate-RATE_18M], bNeedAck);
+		}
+		break;
+
+	case CTSDUR_BA_F0: //CTSDuration_ba_f0
+		if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <= RATE_54M)) {
+			uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE0][wRate-RATE_18M], bNeedAck);
+		} else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <= RATE_54M)) {
+			uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE0][wRate-RATE_18M], bNeedAck);
+		}
+		break;
+
+	case CTSDUR_BA_F1: //CTSDuration_ba_f1
+		if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <= RATE_54M)) {
+			uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE1][wRate-RATE_18M], bNeedAck);
+		} else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <= RATE_54M)) {
+			uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE1][wRate-RATE_18M], bNeedAck);
+		}
+		break;
+
+	default:
+		break;
+	}
+
+	return uDurTime;
 }
 
-
-
 static
 unsigned int
-s_uFillDataHead (
-    PSDevice pDevice,
-    unsigned char byPktType,
-    void *   pTxDataHead,
-    unsigned int cbFrameLength,
-    unsigned int uDMAIdx,
-    bool bNeedAck,
-    unsigned int uFragIdx,
-    unsigned int cbLastFragmentSize,
-    unsigned int uMACfragNum,
-    unsigned char byFBOption,
-    unsigned short wCurrentRate
-    )
+s_uFillDataHead(
+	PSDevice pDevice,
+	unsigned char byPktType,
+	void *pTxDataHead,
+	unsigned int cbFrameLength,
+	unsigned int uDMAIdx,
+	bool bNeedAck,
+	unsigned int uFragIdx,
+	unsigned int cbLastFragmentSize,
+	unsigned int uMACfragNum,
+	unsigned char byFBOption,
+	unsigned short wCurrentRate
+)
 {
-    unsigned short wLen = 0x0000;
-
-    if (pTxDataHead == NULL) {
-        return 0;
-    }
-
-    if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {
-        if (byFBOption == AUTO_FB_NONE) {
-            PSTxDataHead_g pBuf = (PSTxDataHead_g)pTxDataHead;
-            //Get SignalField,ServiceField,Length
-            BBvCalculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType,
-                (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField_a), (unsigned char *)&(pBuf->bySignalField_a)
-            );
-            pBuf->wTransmitLength_a = cpu_to_le16(wLen);
-            BBvCalculateParameter(pDevice, cbFrameLength, pDevice->byTopCCKBasicRate, PK_TYPE_11B,
-                (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField_b), (unsigned char *)&(pBuf->bySignalField_b)
-            );
-            pBuf->wTransmitLength_b = cpu_to_le16(wLen);
-            //Get Duration and TimeStamp
-            pBuf->wDuration_a = cpu_to_le16((unsigned short)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameLength,
-                                                         byPktType, wCurrentRate, bNeedAck, uFragIdx,
-                                                         cbLastFragmentSize, uMACfragNum,
-                                                         byFBOption)); //1: 2.4GHz
-            pBuf->wDuration_b = cpu_to_le16((unsigned short)s_uGetDataDuration(pDevice, DATADUR_B, cbFrameLength,
-                                                         PK_TYPE_11B, pDevice->byTopCCKBasicRate,
-                                                         bNeedAck, uFragIdx, cbLastFragmentSize,
-                                                         uMACfragNum, byFBOption)); //1: 2.4
-
-            pBuf->wTimeStampOff_a = cpu_to_le16(wTimeStampOff[pDevice->byPreambleType%2][wCurrentRate%MAX_RATE]);
-            pBuf->wTimeStampOff_b = cpu_to_le16(wTimeStampOff[pDevice->byPreambleType%2][pDevice->byTopCCKBasicRate%MAX_RATE]);
-
-            return (pBuf->wDuration_a);
-         } else {
-            // Auto Fallback
-            PSTxDataHead_g_FB pBuf = (PSTxDataHead_g_FB)pTxDataHead;
-            //Get SignalField,ServiceField,Length
-            BBvCalculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType,
-                (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField_a), (unsigned char *)&(pBuf->bySignalField_a)
-            );
-            pBuf->wTransmitLength_a = cpu_to_le16(wLen);
-            BBvCalculateParameter(pDevice, cbFrameLength, pDevice->byTopCCKBasicRate, PK_TYPE_11B,
-                (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField_b), (unsigned char *)&(pBuf->bySignalField_b)
-            );
-            pBuf->wTransmitLength_b = cpu_to_le16(wLen);
-            //Get Duration and TimeStamp
-            pBuf->wDuration_a = cpu_to_le16((unsigned short)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameLength, byPktType,
-                                         wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption)); //1: 2.4GHz
-            pBuf->wDuration_b = cpu_to_le16((unsigned short)s_uGetDataDuration(pDevice, DATADUR_B, cbFrameLength, PK_TYPE_11B,
-                                         pDevice->byTopCCKBasicRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption)); //1: 2.4GHz
-            pBuf->wDuration_a_f0 = cpu_to_le16((unsigned short)s_uGetDataDuration(pDevice, DATADUR_A_F0, cbFrameLength, byPktType,
-                                         wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption)); //1: 2.4GHz
-            pBuf->wDuration_a_f1 = cpu_to_le16((unsigned short)s_uGetDataDuration(pDevice, DATADUR_A_F1, cbFrameLength, byPktType,
-                                         wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption)); //1: 2.4GHz
-
-            pBuf->wTimeStampOff_a = cpu_to_le16(wTimeStampOff[pDevice->byPreambleType%2][wCurrentRate%MAX_RATE]);
-            pBuf->wTimeStampOff_b = cpu_to_le16(wTimeStampOff[pDevice->byPreambleType%2][pDevice->byTopCCKBasicRate%MAX_RATE]);
-
-            return (pBuf->wDuration_a);
-        } //if (byFBOption == AUTO_FB_NONE)
-    }
-    else if (byPktType == PK_TYPE_11A) {
-        if ((byFBOption != AUTO_FB_NONE)) {
-            // Auto Fallback
-            PSTxDataHead_a_FB pBuf = (PSTxDataHead_a_FB)pTxDataHead;
-            //Get SignalField,ServiceField,Length
-            BBvCalculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType,
-                (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField), (unsigned char *)&(pBuf->bySignalField)
-            );
-            pBuf->wTransmitLength = cpu_to_le16(wLen);
-            //Get Duration and TimeStampOff
-
-            pBuf->wDuration = cpu_to_le16((unsigned short)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameLength, byPktType,
-                                        wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption)); //0: 5GHz
-            pBuf->wDuration_f0 = cpu_to_le16((unsigned short)s_uGetDataDuration(pDevice, DATADUR_A_F0, cbFrameLength, byPktType,
-                                        wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption)); //0: 5GHz
-            pBuf->wDuration_f1 = cpu_to_le16((unsigned short)s_uGetDataDuration(pDevice, DATADUR_A_F1, cbFrameLength, byPktType,
-                                        wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption)); //0: 5GHz
-            pBuf->wTimeStampOff = cpu_to_le16(wTimeStampOff[pDevice->byPreambleType%2][wCurrentRate%MAX_RATE]);
-            return (pBuf->wDuration);
-        } else {
-            PSTxDataHead_ab pBuf = (PSTxDataHead_ab)pTxDataHead;
-            //Get SignalField,ServiceField,Length
-            BBvCalculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType,
-                (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField), (unsigned char *)&(pBuf->bySignalField)
-            );
-            pBuf->wTransmitLength = cpu_to_le16(wLen);
-            //Get Duration and TimeStampOff
-
-            pBuf->wDuration = cpu_to_le16((unsigned short)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameLength, byPktType,
-                                                       wCurrentRate, bNeedAck, uFragIdx,
-                                                       cbLastFragmentSize, uMACfragNum,
-                                                       byFBOption));
-
-            pBuf->wTimeStampOff = cpu_to_le16(wTimeStampOff[pDevice->byPreambleType%2][wCurrentRate%MAX_RATE]);
-            return (pBuf->wDuration);
-        }
-    }
-    else {
-            PSTxDataHead_ab pBuf = (PSTxDataHead_ab)pTxDataHead;
-            //Get SignalField,ServiceField,Length
-            BBvCalculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType,
-                (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField), (unsigned char *)&(pBuf->bySignalField)
-            );
-            pBuf->wTransmitLength = cpu_to_le16(wLen);
-            //Get Duration and TimeStampOff
-            pBuf->wDuration = cpu_to_le16((unsigned short)s_uGetDataDuration(pDevice, DATADUR_B, cbFrameLength, byPktType,
-                                                       wCurrentRate, bNeedAck, uFragIdx,
-                                                       cbLastFragmentSize, uMACfragNum,
-                                                       byFBOption));
-            pBuf->wTimeStampOff = cpu_to_le16(wTimeStampOff[pDevice->byPreambleType%2][wCurrentRate%MAX_RATE]);
-            return (pBuf->wDuration);
-    }
-    return 0;
+	unsigned short wLen = 0x0000;
+
+	if (pTxDataHead == NULL) {
+		return 0;
+	}
+
+	if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {
+		if (byFBOption == AUTO_FB_NONE) {
+			PSTxDataHead_g pBuf = (PSTxDataHead_g)pTxDataHead;
+			//Get SignalField,ServiceField,Length
+			BBvCalculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType,
+					      (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField_a), (unsigned char *)&(pBuf->bySignalField_a)
+);
+			pBuf->wTransmitLength_a = cpu_to_le16(wLen);
+			BBvCalculateParameter(pDevice, cbFrameLength, pDevice->byTopCCKBasicRate, PK_TYPE_11B,
+					      (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField_b), (unsigned char *)&(pBuf->bySignalField_b)
+);
+			pBuf->wTransmitLength_b = cpu_to_le16(wLen);
+			//Get Duration and TimeStamp
+			pBuf->wDuration_a = cpu_to_le16((unsigned short)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameLength,
+											   byPktType, wCurrentRate, bNeedAck, uFragIdx,
+											   cbLastFragmentSize, uMACfragNum,
+											   byFBOption)); //1: 2.4GHz
+			pBuf->wDuration_b = cpu_to_le16((unsigned short)s_uGetDataDuration(pDevice, DATADUR_B, cbFrameLength,
+											   PK_TYPE_11B, pDevice->byTopCCKBasicRate,
+											   bNeedAck, uFragIdx, cbLastFragmentSize,
+											   uMACfragNum, byFBOption)); //1: 2.4
+
+			pBuf->wTimeStampOff_a = cpu_to_le16(wTimeStampOff[pDevice->byPreambleType%2][wCurrentRate%MAX_RATE]);
+			pBuf->wTimeStampOff_b = cpu_to_le16(wTimeStampOff[pDevice->byPreambleType%2][pDevice->byTopCCKBasicRate%MAX_RATE]);
+
+			return pBuf->wDuration_a;
+		} else {
+			// Auto Fallback
+			PSTxDataHead_g_FB pBuf = (PSTxDataHead_g_FB)pTxDataHead;
+			//Get SignalField,ServiceField,Length
+			BBvCalculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType,
+					      (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField_a), (unsigned char *)&(pBuf->bySignalField_a)
+);
+			pBuf->wTransmitLength_a = cpu_to_le16(wLen);
+			BBvCalculateParameter(pDevice, cbFrameLength, pDevice->byTopCCKBasicRate, PK_TYPE_11B,
+					      (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField_b), (unsigned char *)&(pBuf->bySignalField_b)
+);
+			pBuf->wTransmitLength_b = cpu_to_le16(wLen);
+			//Get Duration and TimeStamp
+			pBuf->wDuration_a = cpu_to_le16((unsigned short)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameLength, byPktType,
+											   wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption)); //1: 2.4GHz
+			pBuf->wDuration_b = cpu_to_le16((unsigned short)s_uGetDataDuration(pDevice, DATADUR_B, cbFrameLength, PK_TYPE_11B,
+											   pDevice->byTopCCKBasicRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption)); //1: 2.4GHz
+			pBuf->wDuration_a_f0 = cpu_to_le16((unsigned short)s_uGetDataDuration(pDevice, DATADUR_A_F0, cbFrameLength, byPktType,
+											      wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption)); //1: 2.4GHz
+			pBuf->wDuration_a_f1 = cpu_to_le16((unsigned short)s_uGetDataDuration(pDevice, DATADUR_A_F1, cbFrameLength, byPktType,
+											      wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption)); //1: 2.4GHz
+
+			pBuf->wTimeStampOff_a = cpu_to_le16(wTimeStampOff[pDevice->byPreambleType%2][wCurrentRate%MAX_RATE]);
+			pBuf->wTimeStampOff_b = cpu_to_le16(wTimeStampOff[pDevice->byPreambleType%2][pDevice->byTopCCKBasicRate%MAX_RATE]);
+
+			return pBuf->wDuration_a;
+		} //if (byFBOption == AUTO_FB_NONE)
+	} else if (byPktType == PK_TYPE_11A) {
+		if ((byFBOption != AUTO_FB_NONE)) {
+			// Auto Fallback
+			PSTxDataHead_a_FB pBuf = (PSTxDataHead_a_FB)pTxDataHead;
+			//Get SignalField,ServiceField,Length
+			BBvCalculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType,
+					      (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField), (unsigned char *)&(pBuf->bySignalField)
+);
+			pBuf->wTransmitLength = cpu_to_le16(wLen);
+			//Get Duration and TimeStampOff
+
+			pBuf->wDuration = cpu_to_le16((unsigned short)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameLength, byPktType,
+											 wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption)); //0: 5GHz
+			pBuf->wDuration_f0 = cpu_to_le16((unsigned short)s_uGetDataDuration(pDevice, DATADUR_A_F0, cbFrameLength, byPktType,
+											    wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption)); //0: 5GHz
+			pBuf->wDuration_f1 = cpu_to_le16((unsigned short)s_uGetDataDuration(pDevice, DATADUR_A_F1, cbFrameLength, byPktType,
+											    wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption)); //0: 5GHz
+			pBuf->wTimeStampOff = cpu_to_le16(wTimeStampOff[pDevice->byPreambleType%2][wCurrentRate%MAX_RATE]);
+			return pBuf->wDuration;
+		} else {
+			PSTxDataHead_ab pBuf = (PSTxDataHead_ab)pTxDataHead;
+			//Get SignalField,ServiceField,Length
+			BBvCalculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType,
+					      (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField), (unsigned char *)&(pBuf->bySignalField)
+);
+			pBuf->wTransmitLength = cpu_to_le16(wLen);
+			//Get Duration and TimeStampOff
+
+			pBuf->wDuration = cpu_to_le16((unsigned short)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameLength, byPktType,
+											 wCurrentRate, bNeedAck, uFragIdx,
+											 cbLastFragmentSize, uMACfragNum,
+											 byFBOption));
+
+			pBuf->wTimeStampOff = cpu_to_le16(wTimeStampOff[pDevice->byPreambleType%2][wCurrentRate%MAX_RATE]);
+			return pBuf->wDuration;
+		}
+	} else {
+		PSTxDataHead_ab pBuf = (PSTxDataHead_ab)pTxDataHead;
+		//Get SignalField,ServiceField,Length
+		BBvCalculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType,
+				      (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField), (unsigned char *)&(pBuf->bySignalField)
+);
+		pBuf->wTransmitLength = cpu_to_le16(wLen);
+		//Get Duration and TimeStampOff
+		pBuf->wDuration = cpu_to_le16((unsigned short)s_uGetDataDuration(pDevice, DATADUR_B, cbFrameLength, byPktType,
+										 wCurrentRate, bNeedAck, uFragIdx,
+										 cbLastFragmentSize, uMACfragNum,
+										 byFBOption));
+		pBuf->wTimeStampOff = cpu_to_le16(wTimeStampOff[pDevice->byPreambleType%2][wCurrentRate%MAX_RATE]);
+		return pBuf->wDuration;
+	}
+	return 0;
 }
 
-
 static
 void
-s_vFillRTSHead (
-    PSDevice         pDevice,
-    unsigned char byPktType,
-    void *           pvRTS,
-    unsigned int cbFrameLength,
-    bool bNeedAck,
-    bool bDisCRC,
-    PSEthernetHeader psEthHeader,
-    unsigned short wCurrentRate,
-    unsigned char byFBOption
-    )
+s_vFillRTSHead(
+	PSDevice         pDevice,
+	unsigned char byPktType,
+	void *pvRTS,
+	unsigned int cbFrameLength,
+	bool bNeedAck,
+	bool bDisCRC,
+	PSEthernetHeader psEthHeader,
+	unsigned short wCurrentRate,
+	unsigned char byFBOption
+)
 {
-    unsigned int uRTSFrameLen = 20;
-    unsigned short wLen = 0x0000;
-
-    if (pvRTS == NULL)
-    	return;
-
-    if (bDisCRC) {
-        // When CRCDIS bit is on, H/W forgot to generate FCS for RTS frame,
-        // in this case we need to decrease its length by 4.
-        uRTSFrameLen -= 4;
-    }
-
-    // Note: So far RTSHead dosen't appear in ATIM & Beacom DMA, so we don't need to take them into account.
-    //       Otherwise, we need to modify codes for them.
-    if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {
-        if (byFBOption == AUTO_FB_NONE) {
-            PSRTS_g pBuf = (PSRTS_g)pvRTS;
-            //Get SignalField,ServiceField,Length
-            BBvCalculateParameter(pDevice, uRTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B,
-                (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField_b), (unsigned char *)&(pBuf->bySignalField_b)
-            );
-            pBuf->wTransmitLength_b = cpu_to_le16(wLen);
-            BBvCalculateParameter(pDevice, uRTSFrameLen, pDevice->byTopOFDMBasicRate, byPktType,
-                (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField_a), (unsigned char *)&(pBuf->bySignalField_a)
-            );
-            pBuf->wTransmitLength_a = cpu_to_le16(wLen);
-            //Get Duration
-            pBuf->wDuration_bb = cpu_to_le16((unsigned short)s_uGetRTSCTSDuration(pDevice, RTSDUR_BB, cbFrameLength, PK_TYPE_11B, pDevice->byTopCCKBasicRate, bNeedAck, byFBOption));    //0:RTSDuration_bb, 1:2.4G, 1:CCKData
-            pBuf->wDuration_aa = cpu_to_le16((unsigned short)s_uGetRTSCTSDuration(pDevice, RTSDUR_AA, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //2:RTSDuration_aa, 1:2.4G, 2,3: 2.4G OFDMData
-            pBuf->wDuration_ba = cpu_to_le16((unsigned short)s_uGetRTSCTSDuration(pDevice, RTSDUR_BA, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //1:RTSDuration_ba, 1:2.4G, 2,3:2.4G OFDM Data
-
-            pBuf->Data.wDurationID = pBuf->wDuration_aa;
-            //Get RTS Frame body
-            pBuf->Data.wFrameControl = TYPE_CTL_RTS;//0x00B4
-            if ((pDevice->eOPMode == OP_MODE_ADHOC) ||
-                (pDevice->eOPMode == OP_MODE_AP)) {
-                memcpy(&(pBuf->Data.abyRA[0]), &(psEthHeader->abyDstAddr[0]), ETH_ALEN);
-            }
-            else {
-                memcpy(&(pBuf->Data.abyRA[0]), &(pDevice->abyBSSID[0]), ETH_ALEN);
-            }
-            if (pDevice->eOPMode == OP_MODE_AP) {
-                memcpy(&(pBuf->Data.abyTA[0]), &(pDevice->abyBSSID[0]), ETH_ALEN);
-            }
-            else {
-                memcpy(&(pBuf->Data.abyTA[0]), &(psEthHeader->abySrcAddr[0]), ETH_ALEN);
-            }
-        }
-        else {
-           PSRTS_g_FB pBuf = (PSRTS_g_FB)pvRTS;
-            //Get SignalField,ServiceField,Length
-            BBvCalculateParameter(pDevice, uRTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B,
-                (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField_b), (unsigned char *)&(pBuf->bySignalField_b)
-            );
-            pBuf->wTransmitLength_b = cpu_to_le16(wLen);
-            BBvCalculateParameter(pDevice, uRTSFrameLen, pDevice->byTopOFDMBasicRate, byPktType,
-                (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField_a), (unsigned char *)&(pBuf->bySignalField_a)
-            );
-            pBuf->wTransmitLength_a = cpu_to_le16(wLen);
-
-            //Get Duration
-            pBuf->wDuration_bb = cpu_to_le16((unsigned short)s_uGetRTSCTSDuration(pDevice, RTSDUR_BB, cbFrameLength, PK_TYPE_11B, pDevice->byTopCCKBasicRate, bNeedAck, byFBOption));    //0:RTSDuration_bb, 1:2.4G, 1:CCKData
-            pBuf->wDuration_aa = cpu_to_le16((unsigned short)s_uGetRTSCTSDuration(pDevice, RTSDUR_AA, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //2:RTSDuration_aa, 1:2.4G, 2,3:2.4G OFDMData
-            pBuf->wDuration_ba = cpu_to_le16((unsigned short)s_uGetRTSCTSDuration(pDevice, RTSDUR_BA, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //1:RTSDuration_ba, 1:2.4G, 2,3:2.4G OFDMData
-            pBuf->wRTSDuration_ba_f0 = cpu_to_le16((unsigned short)s_uGetRTSCTSDuration(pDevice, RTSDUR_BA_F0, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption));    //4:wRTSDuration_ba_f0, 1:2.4G, 1:CCKData
-            pBuf->wRTSDuration_aa_f0 = cpu_to_le16((unsigned short)s_uGetRTSCTSDuration(pDevice, RTSDUR_AA_F0, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption));    //5:wRTSDuration_aa_f0, 1:2.4G, 1:CCKData
-            pBuf->wRTSDuration_ba_f1 = cpu_to_le16((unsigned short)s_uGetRTSCTSDuration(pDevice, RTSDUR_BA_F1, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption));    //6:wRTSDuration_ba_f1, 1:2.4G, 1:CCKData
-            pBuf->wRTSDuration_aa_f1 = cpu_to_le16((unsigned short)s_uGetRTSCTSDuration(pDevice, RTSDUR_AA_F1, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption));    //7:wRTSDuration_aa_f1, 1:2.4G, 1:CCKData
-            pBuf->Data.wDurationID = pBuf->wDuration_aa;
-            //Get RTS Frame body
-            pBuf->Data.wFrameControl = TYPE_CTL_RTS;//0x00B4
-
-            if ((pDevice->eOPMode == OP_MODE_ADHOC) ||
-                (pDevice->eOPMode == OP_MODE_AP)) {
-                memcpy(&(pBuf->Data.abyRA[0]), &(psEthHeader->abyDstAddr[0]), ETH_ALEN);
-            }
-            else {
-                memcpy(&(pBuf->Data.abyRA[0]), &(pDevice->abyBSSID[0]), ETH_ALEN);
-            }
-
-            if (pDevice->eOPMode == OP_MODE_AP) {
-                memcpy(&(pBuf->Data.abyTA[0]), &(pDevice->abyBSSID[0]), ETH_ALEN);
-            }
-            else {
-                memcpy(&(pBuf->Data.abyTA[0]), &(psEthHeader->abySrcAddr[0]), ETH_ALEN);
-            }
-
-        } // if (byFBOption == AUTO_FB_NONE)
-    }
-    else if (byPktType == PK_TYPE_11A) {
-        if (byFBOption == AUTO_FB_NONE) {
-            PSRTS_ab pBuf = (PSRTS_ab)pvRTS;
-            //Get SignalField,ServiceField,Length
-            BBvCalculateParameter(pDevice, uRTSFrameLen, pDevice->byTopOFDMBasicRate, byPktType,
-                (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField), (unsigned char *)&(pBuf->bySignalField)
-            );
-            pBuf->wTransmitLength = cpu_to_le16(wLen);
-            //Get Duration
-            pBuf->wDuration = cpu_to_le16((unsigned short)s_uGetRTSCTSDuration(pDevice, RTSDUR_AA, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //0:RTSDuration_aa, 0:5G, 0: 5G OFDMData
-    	    pBuf->Data.wDurationID = pBuf->wDuration;
-            //Get RTS Frame body
-            pBuf->Data.wFrameControl = TYPE_CTL_RTS;//0x00B4
-
-            if ((pDevice->eOPMode == OP_MODE_ADHOC) ||
-                (pDevice->eOPMode == OP_MODE_AP)) {
-                memcpy(&(pBuf->Data.abyRA[0]), &(psEthHeader->abyDstAddr[0]), ETH_ALEN);
-            }
-            else {
-                memcpy(&(pBuf->Data.abyRA[0]), &(pDevice->abyBSSID[0]), ETH_ALEN);
-            }
-
-            if (pDevice->eOPMode == OP_MODE_AP) {
-                memcpy(&(pBuf->Data.abyTA[0]), &(pDevice->abyBSSID[0]), ETH_ALEN);
-            }
-            else {
-                memcpy(&(pBuf->Data.abyTA[0]), &(psEthHeader->abySrcAddr[0]), ETH_ALEN);
-            }
-
-        }
-        else {
-            PSRTS_a_FB pBuf = (PSRTS_a_FB)pvRTS;
-            //Get SignalField,ServiceField,Length
-            BBvCalculateParameter(pDevice, uRTSFrameLen, pDevice->byTopOFDMBasicRate, byPktType,
-                (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField), (unsigned char *)&(pBuf->bySignalField)
-            );
-            pBuf->wTransmitLength = cpu_to_le16(wLen);
-            //Get Duration
-            pBuf->wDuration = cpu_to_le16((unsigned short)s_uGetRTSCTSDuration(pDevice, RTSDUR_AA, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //0:RTSDuration_aa, 0:5G, 0: 5G OFDMData
-    	    pBuf->wRTSDuration_f0 = cpu_to_le16((unsigned short)s_uGetRTSCTSDuration(pDevice, RTSDUR_AA_F0, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //5:RTSDuration_aa_f0, 0:5G, 0: 5G OFDMData
-    	    pBuf->wRTSDuration_f1 = cpu_to_le16((unsigned short)s_uGetRTSCTSDuration(pDevice, RTSDUR_AA_F1, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //7:RTSDuration_aa_f1, 0:5G, 0:
-    	    pBuf->Data.wDurationID = pBuf->wDuration;
-    	    //Get RTS Frame body
-            pBuf->Data.wFrameControl = TYPE_CTL_RTS;//0x00B4
-
-            if ((pDevice->eOPMode == OP_MODE_ADHOC) ||
-                (pDevice->eOPMode == OP_MODE_AP)) {
-                memcpy(&(pBuf->Data.abyRA[0]), &(psEthHeader->abyDstAddr[0]), ETH_ALEN);
-            }
-            else {
-                memcpy(&(pBuf->Data.abyRA[0]), &(pDevice->abyBSSID[0]), ETH_ALEN);
-            }
-            if (pDevice->eOPMode == OP_MODE_AP) {
-                memcpy(&(pBuf->Data.abyTA[0]), &(pDevice->abyBSSID[0]), ETH_ALEN);
-            }
-            else {
-                memcpy(&(pBuf->Data.abyTA[0]), &(psEthHeader->abySrcAddr[0]), ETH_ALEN);
-            }
-        }
-    }
-    else if (byPktType == PK_TYPE_11B) {
-        PSRTS_ab pBuf = (PSRTS_ab)pvRTS;
-        //Get SignalField,ServiceField,Length
-        BBvCalculateParameter(pDevice, uRTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B,
-            (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField), (unsigned char *)&(pBuf->bySignalField)
-        );
-        pBuf->wTransmitLength = cpu_to_le16(wLen);
-        //Get Duration
-        pBuf->wDuration = cpu_to_le16((unsigned short)s_uGetRTSCTSDuration(pDevice, RTSDUR_BB, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //0:RTSDuration_bb, 1:2.4G, 1:CCKData
-        pBuf->Data.wDurationID = pBuf->wDuration;
-        //Get RTS Frame body
-        pBuf->Data.wFrameControl = TYPE_CTL_RTS;//0x00B4
-
-
-        if ((pDevice->eOPMode == OP_MODE_ADHOC) ||
-            (pDevice->eOPMode == OP_MODE_AP)) {
-            memcpy(&(pBuf->Data.abyRA[0]), &(psEthHeader->abyDstAddr[0]), ETH_ALEN);
-        }
-        else {
-            memcpy(&(pBuf->Data.abyRA[0]), &(pDevice->abyBSSID[0]), ETH_ALEN);
-        }
-
-        if (pDevice->eOPMode == OP_MODE_AP) {
-            memcpy(&(pBuf->Data.abyTA[0]), &(pDevice->abyBSSID[0]), ETH_ALEN);
-        }
-        else {
-            memcpy(&(pBuf->Data.abyTA[0]), &(psEthHeader->abySrcAddr[0]), ETH_ALEN);
-        }
-    }
+	unsigned int uRTSFrameLen = 20;
+	unsigned short wLen = 0x0000;
+
+	if (pvRTS == NULL)
+		return;
+
+	if (bDisCRC) {
+		// When CRCDIS bit is on, H/W forgot to generate FCS for RTS frame,
+		// in this case we need to decrease its length by 4.
+		uRTSFrameLen -= 4;
+	}
+
+	// Note: So far RTSHead dosen't appear in ATIM & Beacom DMA, so we don't need to take them into account.
+	//       Otherwise, we need to modify codes for them.
+	if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {
+		if (byFBOption == AUTO_FB_NONE) {
+			PSRTS_g pBuf = (PSRTS_g)pvRTS;
+			//Get SignalField,ServiceField,Length
+			BBvCalculateParameter(pDevice, uRTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B,
+					      (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField_b), (unsigned char *)&(pBuf->bySignalField_b)
+);
+			pBuf->wTransmitLength_b = cpu_to_le16(wLen);
+			BBvCalculateParameter(pDevice, uRTSFrameLen, pDevice->byTopOFDMBasicRate, byPktType,
+					      (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField_a), (unsigned char *)&(pBuf->bySignalField_a)
+);
+			pBuf->wTransmitLength_a = cpu_to_le16(wLen);
+			//Get Duration
+			pBuf->wDuration_bb = cpu_to_le16((unsigned short)s_uGetRTSCTSDuration(pDevice, RTSDUR_BB, cbFrameLength, PK_TYPE_11B, pDevice->byTopCCKBasicRate, bNeedAck, byFBOption));    //0:RTSDuration_bb, 1:2.4G, 1:CCKData
+			pBuf->wDuration_aa = cpu_to_le16((unsigned short)s_uGetRTSCTSDuration(pDevice, RTSDUR_AA, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //2:RTSDuration_aa, 1:2.4G, 2,3: 2.4G OFDMData
+			pBuf->wDuration_ba = cpu_to_le16((unsigned short)s_uGetRTSCTSDuration(pDevice, RTSDUR_BA, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //1:RTSDuration_ba, 1:2.4G, 2,3:2.4G OFDM Data
+
+			pBuf->Data.wDurationID = pBuf->wDuration_aa;
+			//Get RTS Frame body
+			pBuf->Data.wFrameControl = TYPE_CTL_RTS;//0x00B4
+			if ((pDevice->eOPMode == OP_MODE_ADHOC) ||
+			    (pDevice->eOPMode == OP_MODE_AP)) {
+				memcpy(&(pBuf->Data.abyRA[0]), &(psEthHeader->abyDstAddr[0]), ETH_ALEN);
+			} else {
+				memcpy(&(pBuf->Data.abyRA[0]), &(pDevice->abyBSSID[0]), ETH_ALEN);
+			}
+			if (pDevice->eOPMode == OP_MODE_AP) {
+				memcpy(&(pBuf->Data.abyTA[0]), &(pDevice->abyBSSID[0]), ETH_ALEN);
+			} else {
+				memcpy(&(pBuf->Data.abyTA[0]), &(psEthHeader->abySrcAddr[0]), ETH_ALEN);
+			}
+		} else {
+			PSRTS_g_FB pBuf = (PSRTS_g_FB)pvRTS;
+			//Get SignalField,ServiceField,Length
+			BBvCalculateParameter(pDevice, uRTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B,
+					      (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField_b), (unsigned char *)&(pBuf->bySignalField_b)
+);
+			pBuf->wTransmitLength_b = cpu_to_le16(wLen);
+			BBvCalculateParameter(pDevice, uRTSFrameLen, pDevice->byTopOFDMBasicRate, byPktType,
+					      (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField_a), (unsigned char *)&(pBuf->bySignalField_a)
+);
+			pBuf->wTransmitLength_a = cpu_to_le16(wLen);
+
+			//Get Duration
+			pBuf->wDuration_bb = cpu_to_le16((unsigned short)s_uGetRTSCTSDuration(pDevice, RTSDUR_BB, cbFrameLength, PK_TYPE_11B, pDevice->byTopCCKBasicRate, bNeedAck, byFBOption));    //0:RTSDuration_bb, 1:2.4G, 1:CCKData
+			pBuf->wDuration_aa = cpu_to_le16((unsigned short)s_uGetRTSCTSDuration(pDevice, RTSDUR_AA, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //2:RTSDuration_aa, 1:2.4G, 2,3:2.4G OFDMData
+			pBuf->wDuration_ba = cpu_to_le16((unsigned short)s_uGetRTSCTSDuration(pDevice, RTSDUR_BA, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //1:RTSDuration_ba, 1:2.4G, 2,3:2.4G OFDMData
+			pBuf->wRTSDuration_ba_f0 = cpu_to_le16((unsigned short)s_uGetRTSCTSDuration(pDevice, RTSDUR_BA_F0, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption));    //4:wRTSDuration_ba_f0, 1:2.4G, 1:CCKData
+			pBuf->wRTSDuration_aa_f0 = cpu_to_le16((unsigned short)s_uGetRTSCTSDuration(pDevice, RTSDUR_AA_F0, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption));    //5:wRTSDuration_aa_f0, 1:2.4G, 1:CCKData
+			pBuf->wRTSDuration_ba_f1 = cpu_to_le16((unsigned short)s_uGetRTSCTSDuration(pDevice, RTSDUR_BA_F1, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption));    //6:wRTSDuration_ba_f1, 1:2.4G, 1:CCKData
+			pBuf->wRTSDuration_aa_f1 = cpu_to_le16((unsigned short)s_uGetRTSCTSDuration(pDevice, RTSDUR_AA_F1, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption));    //7:wRTSDuration_aa_f1, 1:2.4G, 1:CCKData
+			pBuf->Data.wDurationID = pBuf->wDuration_aa;
+			//Get RTS Frame body
+			pBuf->Data.wFrameControl = TYPE_CTL_RTS;//0x00B4
+
+			if ((pDevice->eOPMode == OP_MODE_ADHOC) ||
+			    (pDevice->eOPMode == OP_MODE_AP)) {
+				memcpy(&(pBuf->Data.abyRA[0]), &(psEthHeader->abyDstAddr[0]), ETH_ALEN);
+			} else {
+				memcpy(&(pBuf->Data.abyRA[0]), &(pDevice->abyBSSID[0]), ETH_ALEN);
+			}
+
+			if (pDevice->eOPMode == OP_MODE_AP) {
+				memcpy(&(pBuf->Data.abyTA[0]), &(pDevice->abyBSSID[0]), ETH_ALEN);
+			} else {
+				memcpy(&(pBuf->Data.abyTA[0]), &(psEthHeader->abySrcAddr[0]), ETH_ALEN);
+			}
+
+		} // if (byFBOption == AUTO_FB_NONE)
+	} else if (byPktType == PK_TYPE_11A) {
+		if (byFBOption == AUTO_FB_NONE) {
+			PSRTS_ab pBuf = (PSRTS_ab)pvRTS;
+			//Get SignalField,ServiceField,Length
+			BBvCalculateParameter(pDevice, uRTSFrameLen, pDevice->byTopOFDMBasicRate, byPktType,
+					      (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField), (unsigned char *)&(pBuf->bySignalField)
+);
+			pBuf->wTransmitLength = cpu_to_le16(wLen);
+			//Get Duration
+			pBuf->wDuration = cpu_to_le16((unsigned short)s_uGetRTSCTSDuration(pDevice, RTSDUR_AA, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //0:RTSDuration_aa, 0:5G, 0: 5G OFDMData
+			pBuf->Data.wDurationID = pBuf->wDuration;
+			//Get RTS Frame body
+			pBuf->Data.wFrameControl = TYPE_CTL_RTS;//0x00B4
+
+			if ((pDevice->eOPMode == OP_MODE_ADHOC) ||
+			    (pDevice->eOPMode == OP_MODE_AP)) {
+				memcpy(&(pBuf->Data.abyRA[0]), &(psEthHeader->abyDstAddr[0]), ETH_ALEN);
+			} else {
+				memcpy(&(pBuf->Data.abyRA[0]), &(pDevice->abyBSSID[0]), ETH_ALEN);
+			}
+
+			if (pDevice->eOPMode == OP_MODE_AP) {
+				memcpy(&(pBuf->Data.abyTA[0]), &(pDevice->abyBSSID[0]), ETH_ALEN);
+			} else {
+				memcpy(&(pBuf->Data.abyTA[0]), &(psEthHeader->abySrcAddr[0]), ETH_ALEN);
+			}
+
+		} else {
+			PSRTS_a_FB pBuf = (PSRTS_a_FB)pvRTS;
+			//Get SignalField,ServiceField,Length
+			BBvCalculateParameter(pDevice, uRTSFrameLen, pDevice->byTopOFDMBasicRate, byPktType,
+					      (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField), (unsigned char *)&(pBuf->bySignalField)
+);
+			pBuf->wTransmitLength = cpu_to_le16(wLen);
+			//Get Duration
+			pBuf->wDuration = cpu_to_le16((unsigned short)s_uGetRTSCTSDuration(pDevice, RTSDUR_AA, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //0:RTSDuration_aa, 0:5G, 0: 5G OFDMData
+			pBuf->wRTSDuration_f0 = cpu_to_le16((unsigned short)s_uGetRTSCTSDuration(pDevice, RTSDUR_AA_F0, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //5:RTSDuration_aa_f0, 0:5G, 0: 5G OFDMData
+			pBuf->wRTSDuration_f1 = cpu_to_le16((unsigned short)s_uGetRTSCTSDuration(pDevice, RTSDUR_AA_F1, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //7:RTSDuration_aa_f1, 0:5G, 0:
+			pBuf->Data.wDurationID = pBuf->wDuration;
+			//Get RTS Frame body
+			pBuf->Data.wFrameControl = TYPE_CTL_RTS;//0x00B4
+
+			if ((pDevice->eOPMode == OP_MODE_ADHOC) ||
+			    (pDevice->eOPMode == OP_MODE_AP)) {
+				memcpy(&(pBuf->Data.abyRA[0]), &(psEthHeader->abyDstAddr[0]), ETH_ALEN);
+			} else {
+				memcpy(&(pBuf->Data.abyRA[0]), &(pDevice->abyBSSID[0]), ETH_ALEN);
+			}
+			if (pDevice->eOPMode == OP_MODE_AP) {
+				memcpy(&(pBuf->Data.abyTA[0]), &(pDevice->abyBSSID[0]), ETH_ALEN);
+			} else {
+				memcpy(&(pBuf->Data.abyTA[0]), &(psEthHeader->abySrcAddr[0]), ETH_ALEN);
+			}
+		}
+	} else if (byPktType == PK_TYPE_11B) {
+		PSRTS_ab pBuf = (PSRTS_ab)pvRTS;
+		//Get SignalField,ServiceField,Length
+		BBvCalculateParameter(pDevice, uRTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B,
+				      (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField), (unsigned char *)&(pBuf->bySignalField)
+);
+		pBuf->wTransmitLength = cpu_to_le16(wLen);
+		//Get Duration
+		pBuf->wDuration = cpu_to_le16((unsigned short)s_uGetRTSCTSDuration(pDevice, RTSDUR_BB, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //0:RTSDuration_bb, 1:2.4G, 1:CCKData
+		pBuf->Data.wDurationID = pBuf->wDuration;
+		//Get RTS Frame body
+		pBuf->Data.wFrameControl = TYPE_CTL_RTS;//0x00B4
+
+		if ((pDevice->eOPMode == OP_MODE_ADHOC) ||
+		    (pDevice->eOPMode == OP_MODE_AP)) {
+			memcpy(&(pBuf->Data.abyRA[0]), &(psEthHeader->abyDstAddr[0]), ETH_ALEN);
+		} else {
+			memcpy(&(pBuf->Data.abyRA[0]), &(pDevice->abyBSSID[0]), ETH_ALEN);
+		}
+
+		if (pDevice->eOPMode == OP_MODE_AP) {
+			memcpy(&(pBuf->Data.abyTA[0]), &(pDevice->abyBSSID[0]), ETH_ALEN);
+		} else {
+			memcpy(&(pBuf->Data.abyTA[0]), &(psEthHeader->abySrcAddr[0]), ETH_ALEN);
+		}
+	}
 }
 
 static
 void
-s_vFillCTSHead (
-    PSDevice pDevice,
-    unsigned int uDMAIdx,
-    unsigned char byPktType,
-    void *   pvCTS,
-    unsigned int cbFrameLength,
-    bool bNeedAck,
-    bool bDisCRC,
-    unsigned short wCurrentRate,
-    unsigned char byFBOption
-    )
+s_vFillCTSHead(
+	PSDevice pDevice,
+	unsigned int uDMAIdx,
+	unsigned char byPktType,
+	void *pvCTS,
+	unsigned int cbFrameLength,
+	bool bNeedAck,
+	bool bDisCRC,
+	unsigned short wCurrentRate,
+	unsigned char byFBOption
+)
 {
-    unsigned int uCTSFrameLen = 14;
-    unsigned short wLen = 0x0000;
-
-    if (pvCTS == NULL) {
-        return;
-    }
-
-    if (bDisCRC) {
-        // When CRCDIS bit is on, H/W forgot to generate FCS for CTS frame,
-        // in this case we need to decrease its length by 4.
-        uCTSFrameLen -= 4;
-    }
-
-    if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {
-        if (byFBOption != AUTO_FB_NONE && uDMAIdx != TYPE_ATIMDMA && uDMAIdx != TYPE_BEACONDMA) {
-            // Auto Fall back
-            PSCTS_FB pBuf = (PSCTS_FB)pvCTS;
-            //Get SignalField,ServiceField,Length
-            BBvCalculateParameter(pDevice, uCTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B,
-                (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField_b), (unsigned char *)&(pBuf->bySignalField_b)
-            );
-
-
-            pBuf->wTransmitLength_b = cpu_to_le16(wLen);
-
-            pBuf->wDuration_ba = (unsigned short)s_uGetRTSCTSDuration(pDevice, CTSDUR_BA, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption); //3:CTSDuration_ba, 1:2.4G, 2,3:2.4G OFDM Data
-            pBuf->wDuration_ba += pDevice->wCTSDuration;
-            pBuf->wDuration_ba = cpu_to_le16(pBuf->wDuration_ba);
-            //Get CTSDuration_ba_f0
-            pBuf->wCTSDuration_ba_f0 = (unsigned short)s_uGetRTSCTSDuration(pDevice, CTSDUR_BA_F0, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption); //8:CTSDuration_ba_f0, 1:2.4G, 2,3:2.4G OFDM Data
-            pBuf->wCTSDuration_ba_f0 += pDevice->wCTSDuration;
-            pBuf->wCTSDuration_ba_f0 = cpu_to_le16(pBuf->wCTSDuration_ba_f0);
-            //Get CTSDuration_ba_f1
-            pBuf->wCTSDuration_ba_f1 = (unsigned short)s_uGetRTSCTSDuration(pDevice, CTSDUR_BA_F1, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption); //9:CTSDuration_ba_f1, 1:2.4G, 2,3:2.4G OFDM Data
-            pBuf->wCTSDuration_ba_f1 += pDevice->wCTSDuration;
-            pBuf->wCTSDuration_ba_f1 = cpu_to_le16(pBuf->wCTSDuration_ba_f1);
-            //Get CTS Frame body
-            pBuf->Data.wDurationID = pBuf->wDuration_ba;
-            pBuf->Data.wFrameControl = TYPE_CTL_CTS;//0x00C4
-            pBuf->Data.wReserved = 0x0000;
-            memcpy(&(pBuf->Data.abyRA[0]), &(pDevice->abyCurrentNetAddr[0]), ETH_ALEN);
-
-        } else { //if (byFBOption != AUTO_FB_NONE && uDMAIdx != TYPE_ATIMDMA && uDMAIdx != TYPE_BEACONDMA)
-            PSCTS pBuf = (PSCTS)pvCTS;
-            //Get SignalField,ServiceField,Length
-            BBvCalculateParameter(pDevice, uCTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B,
-                (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField_b), (unsigned char *)&(pBuf->bySignalField_b)
-            );
-            pBuf->wTransmitLength_b = cpu_to_le16(wLen);
-            //Get CTSDuration_ba
-            pBuf->wDuration_ba = cpu_to_le16((unsigned short)s_uGetRTSCTSDuration(pDevice, CTSDUR_BA, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //3:CTSDuration_ba, 1:2.4G, 2,3:2.4G OFDM Data
-            pBuf->wDuration_ba += pDevice->wCTSDuration;
-            pBuf->wDuration_ba = cpu_to_le16(pBuf->wDuration_ba);
-
-            //Get CTS Frame body
-            pBuf->Data.wDurationID = pBuf->wDuration_ba;
-            pBuf->Data.wFrameControl = TYPE_CTL_CTS;//0x00C4
-            pBuf->Data.wReserved = 0x0000;
-            memcpy(&(pBuf->Data.abyRA[0]), &(pDevice->abyCurrentNetAddr[0]), ETH_ALEN);
-        }
-    }
+	unsigned int uCTSFrameLen = 14;
+	unsigned short wLen = 0x0000;
+
+	if (pvCTS == NULL) {
+		return;
+	}
+
+	if (bDisCRC) {
+		// When CRCDIS bit is on, H/W forgot to generate FCS for CTS frame,
+		// in this case we need to decrease its length by 4.
+		uCTSFrameLen -= 4;
+	}
+
+	if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {
+		if (byFBOption != AUTO_FB_NONE && uDMAIdx != TYPE_ATIMDMA && uDMAIdx != TYPE_BEACONDMA) {
+			// Auto Fall back
+			PSCTS_FB pBuf = (PSCTS_FB)pvCTS;
+			//Get SignalField,ServiceField,Length
+			BBvCalculateParameter(pDevice, uCTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B,
+					      (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField_b), (unsigned char *)&(pBuf->bySignalField_b)
+);
+
+			pBuf->wTransmitLength_b = cpu_to_le16(wLen);
+
+			pBuf->wDuration_ba = (unsigned short)s_uGetRTSCTSDuration(pDevice, CTSDUR_BA, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption); //3:CTSDuration_ba, 1:2.4G, 2,3:2.4G OFDM Data
+			pBuf->wDuration_ba += pDevice->wCTSDuration;
+			pBuf->wDuration_ba = cpu_to_le16(pBuf->wDuration_ba);
+			//Get CTSDuration_ba_f0
+			pBuf->wCTSDuration_ba_f0 = (unsigned short)s_uGetRTSCTSDuration(pDevice, CTSDUR_BA_F0, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption); //8:CTSDuration_ba_f0, 1:2.4G, 2,3:2.4G OFDM Data
+			pBuf->wCTSDuration_ba_f0 += pDevice->wCTSDuration;
+			pBuf->wCTSDuration_ba_f0 = cpu_to_le16(pBuf->wCTSDuration_ba_f0);
+			//Get CTSDuration_ba_f1
+			pBuf->wCTSDuration_ba_f1 = (unsigned short)s_uGetRTSCTSDuration(pDevice, CTSDUR_BA_F1, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption); //9:CTSDuration_ba_f1, 1:2.4G, 2,3:2.4G OFDM Data
+			pBuf->wCTSDuration_ba_f1 += pDevice->wCTSDuration;
+			pBuf->wCTSDuration_ba_f1 = cpu_to_le16(pBuf->wCTSDuration_ba_f1);
+			//Get CTS Frame body
+			pBuf->Data.wDurationID = pBuf->wDuration_ba;
+			pBuf->Data.wFrameControl = TYPE_CTL_CTS;//0x00C4
+			pBuf->Data.wReserved = 0x0000;
+			memcpy(&(pBuf->Data.abyRA[0]), &(pDevice->abyCurrentNetAddr[0]), ETH_ALEN);
+
+		} else { //if (byFBOption != AUTO_FB_NONE && uDMAIdx != TYPE_ATIMDMA && uDMAIdx != TYPE_BEACONDMA)
+			PSCTS pBuf = (PSCTS)pvCTS;
+			//Get SignalField,ServiceField,Length
+			BBvCalculateParameter(pDevice, uCTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B,
+					      (unsigned short *)&(wLen), (unsigned char *)&(pBuf->byServiceField_b), (unsigned char *)&(pBuf->bySignalField_b)
+);
+			pBuf->wTransmitLength_b = cpu_to_le16(wLen);
+			//Get CTSDuration_ba
+			pBuf->wDuration_ba = cpu_to_le16((unsigned short)s_uGetRTSCTSDuration(pDevice, CTSDUR_BA, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //3:CTSDuration_ba, 1:2.4G, 2,3:2.4G OFDM Data
+			pBuf->wDuration_ba += pDevice->wCTSDuration;
+			pBuf->wDuration_ba = cpu_to_le16(pBuf->wDuration_ba);
+
+			//Get CTS Frame body
+			pBuf->Data.wDurationID = pBuf->wDuration_ba;
+			pBuf->Data.wFrameControl = TYPE_CTL_CTS;//0x00C4
+			pBuf->Data.wReserved = 0x0000;
+			memcpy(&(pBuf->Data.abyRA[0]), &(pDevice->abyCurrentNetAddr[0]), ETH_ALEN);
+		}
+	}
 }
 
-
-
-
-
-
 /*+
  *
  * Description:
@@ -1136,1079 +1071,977 @@ s_vFillCTSHead (
  *
  * Return Value: none
  *
--*/
+ -*/
 // unsigned int cbFrameSize,//Hdr+Payload+FCS
 static
 void
-s_vGenerateTxParameter (
-    PSDevice         pDevice,
-    unsigned char byPktType,
-    void *           pTxBufHead,
-    void *           pvRrvTime,
-    void *           pvRTS,
-    void *           pvCTS,
-    unsigned int cbFrameSize,
-    bool bNeedACK,
-    unsigned int uDMAIdx,
-    PSEthernetHeader psEthHeader,
-    unsigned short wCurrentRate
-    )
+s_vGenerateTxParameter(
+	PSDevice         pDevice,
+	unsigned char byPktType,
+	void *pTxBufHead,
+	void *pvRrvTime,
+	void *pvRTS,
+	void *pvCTS,
+	unsigned int cbFrameSize,
+	bool bNeedACK,
+	unsigned int uDMAIdx,
+	PSEthernetHeader psEthHeader,
+	unsigned short wCurrentRate
+)
 {
-    unsigned int cbMACHdLen = WLAN_HDR_ADDR3_LEN; //24
-    unsigned short wFifoCtl;
-    bool bDisCRC = false;
-    unsigned char byFBOption = AUTO_FB_NONE;
+	unsigned int cbMACHdLen = WLAN_HDR_ADDR3_LEN; //24
+	unsigned short wFifoCtl;
+	bool bDisCRC = false;
+	unsigned char byFBOption = AUTO_FB_NONE;
 //    unsigned short wCurrentRate = pDevice->wCurrentRate;
 
-    //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"s_vGenerateTxParameter...\n");
-    PSTxBufHead pFifoHead = (PSTxBufHead)pTxBufHead;
-    pFifoHead->wReserved = wCurrentRate;
-    wFifoCtl = pFifoHead->wFIFOCtl;
-
-    if (wFifoCtl & FIFOCTL_CRCDIS) {
-        bDisCRC = true;
-    }
-
-    if (wFifoCtl & FIFOCTL_AUTO_FB_0) {
-        byFBOption = AUTO_FB_0;
-    }
-    else if (wFifoCtl & FIFOCTL_AUTO_FB_1) {
-        byFBOption = AUTO_FB_1;
-    }
-
-    if (pDevice->bLongHeader)
-        cbMACHdLen = WLAN_HDR_ADDR3_LEN + 6;
-
-    if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {
-
-        if (pvRTS != NULL) { //RTS_need
-            //Fill RsvTime
-            if (pvRrvTime) {
-                PSRrvTime_gRTS pBuf = (PSRrvTime_gRTS)pvRrvTime;
-                pBuf->wRTSTxRrvTime_aa = cpu_to_le16((unsigned short)s_uGetRTSCTSRsvTime(pDevice, 2, byPktType, cbFrameSize, wCurrentRate));//2:RTSTxRrvTime_aa, 1:2.4GHz
-                pBuf->wRTSTxRrvTime_ba = cpu_to_le16((unsigned short)s_uGetRTSCTSRsvTime(pDevice, 1, byPktType, cbFrameSize, wCurrentRate));//1:RTSTxRrvTime_ba, 1:2.4GHz
-                pBuf->wRTSTxRrvTime_bb = cpu_to_le16((unsigned short)s_uGetRTSCTSRsvTime(pDevice, 0, byPktType, cbFrameSize, wCurrentRate));//0:RTSTxRrvTime_bb, 1:2.4GHz
-                pBuf->wTxRrvTime_a = cpu_to_le16((unsigned short) s_uGetTxRsvTime(pDevice, byPktType, cbFrameSize, wCurrentRate, bNeedACK));//2.4G OFDM
-                pBuf->wTxRrvTime_b = cpu_to_le16((unsigned short) s_uGetTxRsvTime(pDevice, PK_TYPE_11B, cbFrameSize, pDevice->byTopCCKBasicRate, bNeedACK));//1:CCK
-            }
-            //Fill RTS
-            s_vFillRTSHead(pDevice, byPktType, pvRTS, cbFrameSize, bNeedACK, bDisCRC, psEthHeader, wCurrentRate, byFBOption);
-        }
-        else {//RTS_needless, PCF mode
-
-            //Fill RsvTime
-            if (pvRrvTime) {
-                PSRrvTime_gCTS pBuf = (PSRrvTime_gCTS)pvRrvTime;
-                pBuf->wTxRrvTime_a = cpu_to_le16((unsigned short)s_uGetTxRsvTime(pDevice, byPktType, cbFrameSize, wCurrentRate, bNeedACK));//2.4G OFDM
-                pBuf->wTxRrvTime_b = cpu_to_le16((unsigned short)s_uGetTxRsvTime(pDevice, PK_TYPE_11B, cbFrameSize, pDevice->byTopCCKBasicRate, bNeedACK));//1:CCK
-                pBuf->wCTSTxRrvTime_ba = cpu_to_le16((unsigned short)s_uGetRTSCTSRsvTime(pDevice, 3, byPktType, cbFrameSize, wCurrentRate));//3:CTSTxRrvTime_Ba, 1:2.4GHz
-            }
-
-
-            //Fill CTS
-            s_vFillCTSHead(pDevice, uDMAIdx, byPktType, pvCTS, cbFrameSize, bNeedACK, bDisCRC, wCurrentRate, byFBOption);
-        }
-    }
-    else if (byPktType == PK_TYPE_11A) {
-
-        if (pvRTS != NULL) {//RTS_need, non PCF mode
-            //Fill RsvTime
-            if (pvRrvTime) {
-                PSRrvTime_ab pBuf = (PSRrvTime_ab)pvRrvTime;
-                pBuf->wRTSTxRrvTime = cpu_to_le16((unsigned short)s_uGetRTSCTSRsvTime(pDevice, 2, byPktType, cbFrameSize, wCurrentRate));//2:RTSTxRrvTime_aa, 0:5GHz
-                pBuf->wTxRrvTime = cpu_to_le16((unsigned short)s_uGetTxRsvTime(pDevice, byPktType, cbFrameSize, wCurrentRate, bNeedACK));//0:OFDM
-            }
-            //Fill RTS
-            s_vFillRTSHead(pDevice, byPktType, pvRTS, cbFrameSize, bNeedACK, bDisCRC, psEthHeader, wCurrentRate, byFBOption);
-        }
-        else if (pvRTS == NULL) {//RTS_needless, non PCF mode
-            //Fill RsvTime
-            if (pvRrvTime) {
-                PSRrvTime_ab pBuf = (PSRrvTime_ab)pvRrvTime;
-                pBuf->wTxRrvTime = cpu_to_le16((unsigned short)s_uGetTxRsvTime(pDevice, PK_TYPE_11A, cbFrameSize, wCurrentRate, bNeedACK)); //0:OFDM
-            }
-        }
-    }
-    else if (byPktType == PK_TYPE_11B) {
-
-        if ((pvRTS != NULL)) {//RTS_need, non PCF mode
-            //Fill RsvTime
-            if (pvRrvTime) {
-                PSRrvTime_ab pBuf = (PSRrvTime_ab)pvRrvTime;
-                pBuf->wRTSTxRrvTime = cpu_to_le16((unsigned short)s_uGetRTSCTSRsvTime(pDevice, 0, byPktType, cbFrameSize, wCurrentRate));//0:RTSTxRrvTime_bb, 1:2.4GHz
-                pBuf->wTxRrvTime = cpu_to_le16((unsigned short)s_uGetTxRsvTime(pDevice, PK_TYPE_11B, cbFrameSize, wCurrentRate, bNeedACK));//1:CCK
-            }
-            //Fill RTS
-            s_vFillRTSHead(pDevice, byPktType, pvRTS, cbFrameSize, bNeedACK, bDisCRC, psEthHeader, wCurrentRate, byFBOption);
-        }
-        else { //RTS_needless, non PCF mode
-            //Fill RsvTime
-            if (pvRrvTime) {
-                PSRrvTime_ab pBuf = (PSRrvTime_ab)pvRrvTime;
-                pBuf->wTxRrvTime = cpu_to_le16((unsigned short)s_uGetTxRsvTime(pDevice, PK_TYPE_11B, cbFrameSize, wCurrentRate, bNeedACK)); //1:CCK
-            }
-        }
-    }
-    //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"s_vGenerateTxParameter END.\n");
+	//DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "s_vGenerateTxParameter...\n");
+	PSTxBufHead pFifoHead = (PSTxBufHead)pTxBufHead;
+	pFifoHead->wReserved = wCurrentRate;
+	wFifoCtl = pFifoHead->wFIFOCtl;
+
+	if (wFifoCtl & FIFOCTL_CRCDIS) {
+		bDisCRC = true;
+	}
+
+	if (wFifoCtl & FIFOCTL_AUTO_FB_0) {
+		byFBOption = AUTO_FB_0;
+	} else if (wFifoCtl & FIFOCTL_AUTO_FB_1) {
+		byFBOption = AUTO_FB_1;
+	}
+
+	if (pDevice->bLongHeader)
+		cbMACHdLen = WLAN_HDR_ADDR3_LEN + 6;
+
+	if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {
+		if (pvRTS != NULL) { //RTS_need
+			//Fill RsvTime
+			if (pvRrvTime) {
+				PSRrvTime_gRTS pBuf = (PSRrvTime_gRTS)pvRrvTime;
+				pBuf->wRTSTxRrvTime_aa = cpu_to_le16((unsigned short)s_uGetRTSCTSRsvTime(pDevice, 2, byPktType, cbFrameSize, wCurrentRate));//2:RTSTxRrvTime_aa, 1:2.4GHz
+				pBuf->wRTSTxRrvTime_ba = cpu_to_le16((unsigned short)s_uGetRTSCTSRsvTime(pDevice, 1, byPktType, cbFrameSize, wCurrentRate));//1:RTSTxRrvTime_ba, 1:2.4GHz
+				pBuf->wRTSTxRrvTime_bb = cpu_to_le16((unsigned short)s_uGetRTSCTSRsvTime(pDevice, 0, byPktType, cbFrameSize, wCurrentRate));//0:RTSTxRrvTime_bb, 1:2.4GHz
+				pBuf->wTxRrvTime_a = cpu_to_le16((unsigned short) s_uGetTxRsvTime(pDevice, byPktType, cbFrameSize, wCurrentRate, bNeedACK));//2.4G OFDM
+				pBuf->wTxRrvTime_b = cpu_to_le16((unsigned short) s_uGetTxRsvTime(pDevice, PK_TYPE_11B, cbFrameSize, pDevice->byTopCCKBasicRate, bNeedACK));//1:CCK
+			}
+			//Fill RTS
+			s_vFillRTSHead(pDevice, byPktType, pvRTS, cbFrameSize, bNeedACK, bDisCRC, psEthHeader, wCurrentRate, byFBOption);
+		} else {//RTS_needless, PCF mode
+
+			//Fill RsvTime
+			if (pvRrvTime) {
+				PSRrvTime_gCTS pBuf = (PSRrvTime_gCTS)pvRrvTime;
+				pBuf->wTxRrvTime_a = cpu_to_le16((unsigned short)s_uGetTxRsvTime(pDevice, byPktType, cbFrameSize, wCurrentRate, bNeedACK));//2.4G OFDM
+				pBuf->wTxRrvTime_b = cpu_to_le16((unsigned short)s_uGetTxRsvTime(pDevice, PK_TYPE_11B, cbFrameSize, pDevice->byTopCCKBasicRate, bNeedACK));//1:CCK
+				pBuf->wCTSTxRrvTime_ba = cpu_to_le16((unsigned short)s_uGetRTSCTSRsvTime(pDevice, 3, byPktType, cbFrameSize, wCurrentRate));//3:CTSTxRrvTime_Ba, 1:2.4GHz
+			}
+
+			//Fill CTS
+			s_vFillCTSHead(pDevice, uDMAIdx, byPktType, pvCTS, cbFrameSize, bNeedACK, bDisCRC, wCurrentRate, byFBOption);
+		}
+	} else if (byPktType == PK_TYPE_11A) {
+		if (pvRTS != NULL) {//RTS_need, non PCF mode
+			//Fill RsvTime
+			if (pvRrvTime) {
+				PSRrvTime_ab pBuf = (PSRrvTime_ab)pvRrvTime;
+				pBuf->wRTSTxRrvTime = cpu_to_le16((unsigned short)s_uGetRTSCTSRsvTime(pDevice, 2, byPktType, cbFrameSize, wCurrentRate));//2:RTSTxRrvTime_aa, 0:5GHz
+				pBuf->wTxRrvTime = cpu_to_le16((unsigned short)s_uGetTxRsvTime(pDevice, byPktType, cbFrameSize, wCurrentRate, bNeedACK));//0:OFDM
+			}
+			//Fill RTS
+			s_vFillRTSHead(pDevice, byPktType, pvRTS, cbFrameSize, bNeedACK, bDisCRC, psEthHeader, wCurrentRate, byFBOption);
+		} else if (pvRTS == NULL) {//RTS_needless, non PCF mode
+			//Fill RsvTime
+			if (pvRrvTime) {
+				PSRrvTime_ab pBuf = (PSRrvTime_ab)pvRrvTime;
+				pBuf->wTxRrvTime = cpu_to_le16((unsigned short)s_uGetTxRsvTime(pDevice, PK_TYPE_11A, cbFrameSize, wCurrentRate, bNeedACK)); //0:OFDM
+			}
+		}
+	} else if (byPktType == PK_TYPE_11B) {
+		if ((pvRTS != NULL)) {//RTS_need, non PCF mode
+			//Fill RsvTime
+			if (pvRrvTime) {
+				PSRrvTime_ab pBuf = (PSRrvTime_ab)pvRrvTime;
+				pBuf->wRTSTxRrvTime = cpu_to_le16((unsigned short)s_uGetRTSCTSRsvTime(pDevice, 0, byPktType, cbFrameSize, wCurrentRate));//0:RTSTxRrvTime_bb, 1:2.4GHz
+				pBuf->wTxRrvTime = cpu_to_le16((unsigned short)s_uGetTxRsvTime(pDevice, PK_TYPE_11B, cbFrameSize, wCurrentRate, bNeedACK));//1:CCK
+			}
+			//Fill RTS
+			s_vFillRTSHead(pDevice, byPktType, pvRTS, cbFrameSize, bNeedACK, bDisCRC, psEthHeader, wCurrentRate, byFBOption);
+		} else { //RTS_needless, non PCF mode
+			//Fill RsvTime
+			if (pvRrvTime) {
+				PSRrvTime_ab pBuf = (PSRrvTime_ab)pvRrvTime;
+				pBuf->wTxRrvTime = cpu_to_le16((unsigned short)s_uGetTxRsvTime(pDevice, PK_TYPE_11B, cbFrameSize, wCurrentRate, bNeedACK)); //1:CCK
+			}
+		}
+	}
+	//DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "s_vGenerateTxParameter END.\n");
 }
 /*
-    unsigned char *pbyBuffer,//point to pTxBufHead
-    unsigned short wFragType,//00:Non-Frag, 01:Start, 02:Mid, 03:Last
-    unsigned int cbFragmentSize,//Hdr+payoad+FCS
+  unsigned char *pbyBuffer,//point to pTxBufHead
+  unsigned short wFragType,//00:Non-Frag, 01:Start, 02:Mid, 03:Last
+  unsigned int cbFragmentSize,//Hdr+payoad+FCS
 */
 static
 void
 s_vFillFragParameter(
-    PSDevice pDevice,
-    unsigned char *pbyBuffer,
-    unsigned int uTxType,
-    void *   pvtdCurr,
-    unsigned short wFragType,
-    unsigned int cbReqCount
-    )
+	PSDevice pDevice,
+	unsigned char *pbyBuffer,
+	unsigned int uTxType,
+	void *pvtdCurr,
+	unsigned short wFragType,
+	unsigned int cbReqCount
+)
 {
-    PSTxBufHead pTxBufHead = (PSTxBufHead) pbyBuffer;
-    //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"s_vFillFragParameter...\n");
-
-    if (uTxType == TYPE_SYNCDMA) {
-        //PSTxSyncDesc ptdCurr = (PSTxSyncDesc)s_pvGetTxDescHead(pDevice, uTxType, uCurIdx);
-        PSTxSyncDesc ptdCurr = (PSTxSyncDesc)pvtdCurr;
-
-         //Set FIFOCtl & TimeStamp in TxSyncDesc
-        ptdCurr->m_wFIFOCtl = pTxBufHead->wFIFOCtl;
-        ptdCurr->m_wTimeStamp = pTxBufHead->wTimeStamp;
-        //Set TSR1 & ReqCount in TxDescHead
-        ptdCurr->m_td1TD1.wReqCount = cpu_to_le16((unsigned short)(cbReqCount));
-        if (wFragType == FRAGCTL_ENDFRAG) { //Last Fragmentation
-            ptdCurr->m_td1TD1.byTCR |= (TCR_STP | TCR_EDP | EDMSDU);
-        }
-        else {
-            ptdCurr->m_td1TD1.byTCR |= (TCR_STP | TCR_EDP);
-        }
-    }
-    else {
-        //PSTxDesc ptdCurr = (PSTxDesc)s_pvGetTxDescHead(pDevice, uTxType, uCurIdx);
-        PSTxDesc ptdCurr = (PSTxDesc)pvtdCurr;
-        //Set TSR1 & ReqCount in TxDescHead
-        ptdCurr->m_td1TD1.wReqCount = cpu_to_le16((unsigned short)(cbReqCount));
-        if (wFragType == FRAGCTL_ENDFRAG) { //Last Fragmentation
-            ptdCurr->m_td1TD1.byTCR |= (TCR_STP | TCR_EDP | EDMSDU);
-        }
-        else {
-            ptdCurr->m_td1TD1.byTCR |= (TCR_STP | TCR_EDP);
-        }
-    }
-
-    pTxBufHead->wFragCtl |= (unsigned short)wFragType;//0x0001; //0000 0000 0000 0001
-
-    //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"s_vFillFragParameter END\n");
+	PSTxBufHead pTxBufHead = (PSTxBufHead) pbyBuffer;
+	//DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "s_vFillFragParameter...\n");
+
+	if (uTxType == TYPE_SYNCDMA) {
+		//PSTxSyncDesc ptdCurr = (PSTxSyncDesc)s_pvGetTxDescHead(pDevice, uTxType, uCurIdx);
+		PSTxSyncDesc ptdCurr = (PSTxSyncDesc)pvtdCurr;
+
+		//Set FIFOCtl & TimeStamp in TxSyncDesc
+		ptdCurr->m_wFIFOCtl = pTxBufHead->wFIFOCtl;
+		ptdCurr->m_wTimeStamp = pTxBufHead->wTimeStamp;
+		//Set TSR1 & ReqCount in TxDescHead
+		ptdCurr->m_td1TD1.wReqCount = cpu_to_le16((unsigned short)(cbReqCount));
+		if (wFragType == FRAGCTL_ENDFRAG) { //Last Fragmentation
+			ptdCurr->m_td1TD1.byTCR |= (TCR_STP | TCR_EDP | EDMSDU);
+		} else {
+			ptdCurr->m_td1TD1.byTCR |= (TCR_STP | TCR_EDP);
+		}
+	} else {
+		//PSTxDesc ptdCurr = (PSTxDesc)s_pvGetTxDescHead(pDevice, uTxType, uCurIdx);
+		PSTxDesc ptdCurr = (PSTxDesc)pvtdCurr;
+		//Set TSR1 & ReqCount in TxDescHead
+		ptdCurr->m_td1TD1.wReqCount = cpu_to_le16((unsigned short)(cbReqCount));
+		if (wFragType == FRAGCTL_ENDFRAG) { //Last Fragmentation
+			ptdCurr->m_td1TD1.byTCR |= (TCR_STP | TCR_EDP | EDMSDU);
+		} else {
+			ptdCurr->m_td1TD1.byTCR |= (TCR_STP | TCR_EDP);
+		}
+	}
+
+	pTxBufHead->wFragCtl |= (unsigned short)wFragType;//0x0001; //0000 0000 0000 0001
+
+	//DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "s_vFillFragParameter END\n");
 }
 
 static unsigned int
 s_cbFillTxBufHead(PSDevice pDevice, unsigned char byPktType, unsigned char *pbyTxBufferAddr,
-	unsigned int cbFrameBodySize, unsigned int uDMAIdx, PSTxDesc pHeadTD,
-	PSEthernetHeader psEthHeader, unsigned char *pPacket, bool bNeedEncrypt,
-	PSKeyItem pTransmitKey, unsigned int uNodeIndex, unsigned int *puMACfragNum)
+		  unsigned int cbFrameBodySize, unsigned int uDMAIdx, PSTxDesc pHeadTD,
+		  PSEthernetHeader psEthHeader, unsigned char *pPacket, bool bNeedEncrypt,
+		  PSKeyItem pTransmitKey, unsigned int uNodeIndex, unsigned int *puMACfragNum)
 {
-    unsigned int cbMACHdLen;
-    unsigned int cbFrameSize;
-    unsigned int cbFragmentSize; //Hdr+(IV)+payoad+(MIC)+(ICV)+FCS
-    unsigned int cbFragPayloadSize;
-    unsigned int cbLastFragmentSize; //Hdr+(IV)+payoad+(MIC)+(ICV)+FCS
-    unsigned int cbLastFragPayloadSize;
-    unsigned int uFragIdx;
-    unsigned char *pbyPayloadHead;
-    unsigned char *pbyIVHead;
-    unsigned char *pbyMacHdr;
-    unsigned short wFragType; //00:Non-Frag, 01:Start, 10:Mid, 11:Last
-    unsigned int uDuration;
-    unsigned char *pbyBuffer;
+	unsigned int cbMACHdLen;
+	unsigned int cbFrameSize;
+	unsigned int cbFragmentSize; //Hdr+(IV)+payoad+(MIC)+(ICV)+FCS
+	unsigned int cbFragPayloadSize;
+	unsigned int cbLastFragmentSize; //Hdr+(IV)+payoad+(MIC)+(ICV)+FCS
+	unsigned int cbLastFragPayloadSize;
+	unsigned int uFragIdx;
+	unsigned char *pbyPayloadHead;
+	unsigned char *pbyIVHead;
+	unsigned char *pbyMacHdr;
+	unsigned short wFragType; //00:Non-Frag, 01:Start, 10:Mid, 11:Last
+	unsigned int uDuration;
+	unsigned char *pbyBuffer;
 //    unsigned int uKeyEntryIdx = NUM_KEY_ENTRY+1;
 //    unsigned char byKeySel = 0xFF;
-    unsigned int cbIVlen = 0;
-    unsigned int cbICVlen = 0;
-    unsigned int cbMIClen = 0;
-    unsigned int cbFCSlen = 4;
-    unsigned int cb802_1_H_len = 0;
-    unsigned int uLength = 0;
-    unsigned int uTmpLen = 0;
+	unsigned int cbIVlen = 0;
+	unsigned int cbICVlen = 0;
+	unsigned int cbMIClen = 0;
+	unsigned int cbFCSlen = 4;
+	unsigned int cb802_1_H_len = 0;
+	unsigned int uLength = 0;
+	unsigned int uTmpLen = 0;
 //    unsigned char abyTmp[8];
 //    unsigned long dwCRC;
-    unsigned int cbMICHDR = 0;
-    unsigned long dwMICKey0, dwMICKey1;
-    unsigned long dwMIC_Priority;
-    unsigned long *pdwMIC_L;
-    unsigned long *pdwMIC_R;
-    unsigned long dwSafeMIC_L, dwSafeMIC_R; //Fix "Last Frag Size" < "MIC length".
-    bool bMIC2Frag = false;
-    unsigned int uMICFragLen = 0;
-    unsigned int uMACfragNum = 1;
-    unsigned int uPadding = 0;
-    unsigned int cbReqCount = 0;
-
-    bool bNeedACK;
-    bool bRTS;
-    bool bIsAdhoc;
-    unsigned char *pbyType;
-    PSTxDesc       ptdCurr;
-    PSTxBufHead    psTxBufHd = (PSTxBufHead) pbyTxBufferAddr;
+	unsigned int cbMICHDR = 0;
+	unsigned long dwMICKey0, dwMICKey1;
+	unsigned long dwMIC_Priority;
+	unsigned long *pdwMIC_L;
+	unsigned long *pdwMIC_R;
+	unsigned long dwSafeMIC_L, dwSafeMIC_R; //Fix "Last Frag Size" < "MIC length".
+	bool bMIC2Frag = false;
+	unsigned int uMICFragLen = 0;
+	unsigned int uMACfragNum = 1;
+	unsigned int uPadding = 0;
+	unsigned int cbReqCount = 0;
+
+	bool bNeedACK;
+	bool bRTS;
+	bool bIsAdhoc;
+	unsigned char *pbyType;
+	PSTxDesc       ptdCurr;
+	PSTxBufHead    psTxBufHd = (PSTxBufHead) pbyTxBufferAddr;
 //    unsigned int tmpDescIdx;
-    unsigned int cbHeaderLength = 0;
-    void *         pvRrvTime;
-    PSMICHDRHead   pMICHDR;
-    void *         pvRTS;
-    void *         pvCTS;
-    void *         pvTxDataHd;
-    unsigned short wTxBufSize;   // FFinfo size
-    unsigned int uTotalCopyLength = 0;
-    unsigned char byFBOption = AUTO_FB_NONE;
-    bool bIsWEP256 = false;
-    PSMgmtObject    pMgmt = pDevice->pMgmt;
-
-
-    pvRrvTime = pMICHDR = pvRTS = pvCTS = pvTxDataHd = NULL;
-
-    //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"s_cbFillTxBufHead...\n");
-    if ((pDevice->eOPMode == OP_MODE_ADHOC) ||
-        (pDevice->eOPMode == OP_MODE_AP)) {
-
-	if (is_multicast_ether_addr(&(psEthHeader->abyDstAddr[0])))
-		bNeedACK = false;
-        else
-            bNeedACK = true;
-        bIsAdhoc = true;
-    }
-    else {
-        // MSDUs in Infra mode always need ACK
-        bNeedACK = true;
-        bIsAdhoc = false;
-    }
-
-    if (pDevice->bLongHeader)
-        cbMACHdLen = WLAN_HDR_ADDR3_LEN + 6;
-    else
-        cbMACHdLen = WLAN_HDR_ADDR3_LEN;
-
-
-    if ((bNeedEncrypt == true) && (pTransmitKey != NULL)) {
-        if (pTransmitKey->byCipherSuite == KEY_CTL_WEP) {
-            cbIVlen = 4;
-            cbICVlen = 4;
-            if (pTransmitKey->uKeyLength == WLAN_WEP232_KEYLEN) {
-                bIsWEP256 = true;
-            }
-        }
-        if (pTransmitKey->byCipherSuite == KEY_CTL_TKIP) {
-            cbIVlen = 8;//IV+ExtIV
-            cbMIClen = 8;
-            cbICVlen = 4;
-        }
-        if (pTransmitKey->byCipherSuite == KEY_CTL_CCMP) {
-            cbIVlen = 8;//RSN Header
-            cbICVlen = 8;//MIC
-            cbMICHDR = sizeof(SMICHDRHead);
-        }
-        if (pDevice->byLocalID > REV_ID_VT3253_A1) {
-            //MAC Header should be padding 0 to DW alignment.
-            uPadding = 4 - (cbMACHdLen%4);
-            uPadding %= 4;
-        }
-    }
-
-
-    cbFrameSize = cbMACHdLen + cbIVlen + (cbFrameBodySize + cbMIClen) + cbICVlen + cbFCSlen;
-
-    if ((bNeedACK == false) ||
-        (cbFrameSize < pDevice->wRTSThreshold) ||
-        ((cbFrameSize >= pDevice->wFragmentationThreshold) && (pDevice->wFragmentationThreshold <= pDevice->wRTSThreshold))
-        ) {
-        bRTS = false;
-    }
-    else {
-        bRTS = true;
-        psTxBufHd->wFIFOCtl |= (FIFOCTL_RTS | FIFOCTL_LRETRY);
-    }
-    //
-    // Use for AUTO FALL BACK
-    //
-    if (psTxBufHd->wFIFOCtl & FIFOCTL_AUTO_FB_0) {
-        byFBOption = AUTO_FB_0;
-    }
-    else if (psTxBufHd->wFIFOCtl & FIFOCTL_AUTO_FB_1) {
-        byFBOption = AUTO_FB_1;
-    }
-
-    //////////////////////////////////////////////////////
-    //Set RrvTime/RTS/CTS Buffer
-    wTxBufSize = sizeof(STxBufHead);
-    if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {//802.11g packet
-
-        if (byFBOption == AUTO_FB_NONE) {
-            if (bRTS == true) {//RTS_need
-                pvRrvTime = (PSRrvTime_gRTS) (pbyTxBufferAddr + wTxBufSize);
-                pMICHDR = (PSMICHDRHead) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gRTS));
-                pvRTS = (PSRTS_g) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gRTS) + cbMICHDR);
-                pvCTS = NULL;
-                pvTxDataHd = (PSTxDataHead_g) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gRTS) + cbMICHDR + sizeof(SRTS_g));
-                cbHeaderLength = wTxBufSize + sizeof(SRrvTime_gRTS) + cbMICHDR + sizeof(SRTS_g) + sizeof(STxDataHead_g);
-            }
-            else { //RTS_needless
-                pvRrvTime = (PSRrvTime_gCTS) (pbyTxBufferAddr + wTxBufSize);
-                pMICHDR = (PSMICHDRHead) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gCTS));
-                pvRTS = NULL;
-                pvCTS = (PSCTS) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gCTS) + cbMICHDR);
-                pvTxDataHd = (PSTxDataHead_g) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gCTS) + cbMICHDR + sizeof(SCTS));
-                cbHeaderLength = wTxBufSize + sizeof(SRrvTime_gCTS) + cbMICHDR + sizeof(SCTS) + sizeof(STxDataHead_g);
-            }
-        } else {
-            // Auto Fall Back
-            if (bRTS == true) {//RTS_need
-                pvRrvTime = (PSRrvTime_gRTS) (pbyTxBufferAddr + wTxBufSize);
-                pMICHDR = (PSMICHDRHead) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gRTS));
-                pvRTS = (PSRTS_g_FB) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gRTS) + cbMICHDR);
-                pvCTS = NULL;
-                pvTxDataHd = (PSTxDataHead_g_FB) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gRTS) + cbMICHDR + sizeof(SRTS_g_FB));
-                cbHeaderLength = wTxBufSize + sizeof(SRrvTime_gRTS) + cbMICHDR + sizeof(SRTS_g_FB) + sizeof(STxDataHead_g_FB);
-            }
-            else { //RTS_needless
-                pvRrvTime = (PSRrvTime_gCTS) (pbyTxBufferAddr + wTxBufSize);
-                pMICHDR = (PSMICHDRHead) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gCTS));
-                pvRTS = NULL;
-                pvCTS = (PSCTS_FB) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gCTS) + cbMICHDR);
-                pvTxDataHd = (PSTxDataHead_g_FB) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gCTS) + cbMICHDR + sizeof(SCTS_FB));
-                cbHeaderLength = wTxBufSize + sizeof(SRrvTime_gCTS) + cbMICHDR + sizeof(SCTS_FB) + sizeof(STxDataHead_g_FB);
-            }
-        } // Auto Fall Back
-    }
-    else {//802.11a/b packet
-
-        if (byFBOption == AUTO_FB_NONE) {
-            if (bRTS == true) {
-                pvRrvTime = (PSRrvTime_ab) (pbyTxBufferAddr + wTxBufSize);
-                pMICHDR = (PSMICHDRHead) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_ab));
-                pvRTS = (PSRTS_ab) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_ab) + cbMICHDR);
-                pvCTS = NULL;
-                pvTxDataHd = (PSTxDataHead_ab) (pbyTxBufferAddr + wTxBufSize + sizeof(PSRrvTime_ab) + cbMICHDR + sizeof(SRTS_ab));
-                cbHeaderLength = wTxBufSize + sizeof(PSRrvTime_ab) + cbMICHDR + sizeof(SRTS_ab) + sizeof(STxDataHead_ab);
-            }
-            else { //RTS_needless, need MICHDR
-                pvRrvTime = (PSRrvTime_ab) (pbyTxBufferAddr + wTxBufSize);
-                pMICHDR = (PSMICHDRHead) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_ab));
-                pvRTS = NULL;
-                pvCTS = NULL;
-                pvTxDataHd = (PSTxDataHead_ab) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_ab) + cbMICHDR);
-                cbHeaderLength = wTxBufSize + sizeof(SRrvTime_ab) + cbMICHDR + sizeof(STxDataHead_ab);
-            }
-        } else {
-            // Auto Fall Back
-            if (bRTS == true) {//RTS_need
-                pvRrvTime = (PSRrvTime_ab) (pbyTxBufferAddr + wTxBufSize);
-                pMICHDR = (PSMICHDRHead) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_ab));
-                pvRTS = (PSRTS_a_FB) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_ab) + cbMICHDR);
-                pvCTS = NULL;
-                pvTxDataHd = (PSTxDataHead_a_FB) (pbyTxBufferAddr + wTxBufSize + sizeof(PSRrvTime_ab) + cbMICHDR + sizeof(SRTS_a_FB));
-                cbHeaderLength = wTxBufSize + sizeof(PSRrvTime_ab) + cbMICHDR + sizeof(SRTS_a_FB) + sizeof(STxDataHead_a_FB);
-            }
-            else { //RTS_needless
-                pvRrvTime = (PSRrvTime_ab) (pbyTxBufferAddr + wTxBufSize);
-                pMICHDR = (PSMICHDRHead) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_ab));
-                pvRTS = NULL;
-                pvCTS = NULL;
-                pvTxDataHd = (PSTxDataHead_a_FB) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_ab) + cbMICHDR);
-                cbHeaderLength = wTxBufSize + sizeof(SRrvTime_ab) + cbMICHDR + sizeof(STxDataHead_a_FB);
-            }
-        } // Auto Fall Back
-    }
-    memset((void *)(pbyTxBufferAddr + wTxBufSize), 0, (cbHeaderLength - wTxBufSize));
+	unsigned int cbHeaderLength = 0;
+	void *pvRrvTime;
+	PSMICHDRHead   pMICHDR;
+	void *pvRTS;
+	void *pvCTS;
+	void *pvTxDataHd;
+	unsigned short wTxBufSize;   // FFinfo size
+	unsigned int uTotalCopyLength = 0;
+	unsigned char byFBOption = AUTO_FB_NONE;
+	bool bIsWEP256 = false;
+	PSMgmtObject    pMgmt = pDevice->pMgmt;
+
+	pvRrvTime = pMICHDR = pvRTS = pvCTS = pvTxDataHd = NULL;
+
+	//DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "s_cbFillTxBufHead...\n");
+	if ((pDevice->eOPMode == OP_MODE_ADHOC) ||
+	    (pDevice->eOPMode == OP_MODE_AP)) {
+		if (is_multicast_ether_addr(&(psEthHeader->abyDstAddr[0])))
+			bNeedACK = false;
+		else
+			bNeedACK = true;
+		bIsAdhoc = true;
+	} else {
+		// MSDUs in Infra mode always need ACK
+		bNeedACK = true;
+		bIsAdhoc = false;
+	}
+
+	if (pDevice->bLongHeader)
+		cbMACHdLen = WLAN_HDR_ADDR3_LEN + 6;
+	else
+		cbMACHdLen = WLAN_HDR_ADDR3_LEN;
+
+	if ((bNeedEncrypt == true) && (pTransmitKey != NULL)) {
+		if (pTransmitKey->byCipherSuite == KEY_CTL_WEP) {
+			cbIVlen = 4;
+			cbICVlen = 4;
+			if (pTransmitKey->uKeyLength == WLAN_WEP232_KEYLEN) {
+				bIsWEP256 = true;
+			}
+		}
+		if (pTransmitKey->byCipherSuite == KEY_CTL_TKIP) {
+			cbIVlen = 8;//IV+ExtIV
+			cbMIClen = 8;
+			cbICVlen = 4;
+		}
+		if (pTransmitKey->byCipherSuite == KEY_CTL_CCMP) {
+			cbIVlen = 8;//RSN Header
+			cbICVlen = 8;//MIC
+			cbMICHDR = sizeof(SMICHDRHead);
+		}
+		if (pDevice->byLocalID > REV_ID_VT3253_A1) {
+			//MAC Header should be padding 0 to DW alignment.
+			uPadding = 4 - (cbMACHdLen%4);
+			uPadding %= 4;
+		}
+	}
+
+	cbFrameSize = cbMACHdLen + cbIVlen + (cbFrameBodySize + cbMIClen) + cbICVlen + cbFCSlen;
+
+	if ((bNeedACK == false) ||
+	    (cbFrameSize < pDevice->wRTSThreshold) ||
+	    ((cbFrameSize >= pDevice->wFragmentationThreshold) && (pDevice->wFragmentationThreshold <= pDevice->wRTSThreshold))
+) {
+		bRTS = false;
+	} else {
+		bRTS = true;
+		psTxBufHd->wFIFOCtl |= (FIFOCTL_RTS | FIFOCTL_LRETRY);
+	}
+	//
+	// Use for AUTO FALL BACK
+	//
+	if (psTxBufHd->wFIFOCtl & FIFOCTL_AUTO_FB_0) {
+		byFBOption = AUTO_FB_0;
+	} else if (psTxBufHd->wFIFOCtl & FIFOCTL_AUTO_FB_1) {
+		byFBOption = AUTO_FB_1;
+	}
+
+	//////////////////////////////////////////////////////
+	//Set RrvTime/RTS/CTS Buffer
+	wTxBufSize = sizeof(STxBufHead);
+	if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {//802.11g packet
+
+		if (byFBOption == AUTO_FB_NONE) {
+			if (bRTS == true) {//RTS_need
+				pvRrvTime = (PSRrvTime_gRTS) (pbyTxBufferAddr + wTxBufSize);
+				pMICHDR = (PSMICHDRHead) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gRTS));
+				pvRTS = (PSRTS_g) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gRTS) + cbMICHDR);
+				pvCTS = NULL;
+				pvTxDataHd = (PSTxDataHead_g) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gRTS) + cbMICHDR + sizeof(SRTS_g));
+				cbHeaderLength = wTxBufSize + sizeof(SRrvTime_gRTS) + cbMICHDR + sizeof(SRTS_g) + sizeof(STxDataHead_g);
+			} else { //RTS_needless
+				pvRrvTime = (PSRrvTime_gCTS) (pbyTxBufferAddr + wTxBufSize);
+				pMICHDR = (PSMICHDRHead) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gCTS));
+				pvRTS = NULL;
+				pvCTS = (PSCTS) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gCTS) + cbMICHDR);
+				pvTxDataHd = (PSTxDataHead_g) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gCTS) + cbMICHDR + sizeof(SCTS));
+				cbHeaderLength = wTxBufSize + sizeof(SRrvTime_gCTS) + cbMICHDR + sizeof(SCTS) + sizeof(STxDataHead_g);
+			}
+		} else {
+			// Auto Fall Back
+			if (bRTS == true) {//RTS_need
+				pvRrvTime = (PSRrvTime_gRTS) (pbyTxBufferAddr + wTxBufSize);
+				pMICHDR = (PSMICHDRHead) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gRTS));
+				pvRTS = (PSRTS_g_FB) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gRTS) + cbMICHDR);
+				pvCTS = NULL;
+				pvTxDataHd = (PSTxDataHead_g_FB) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gRTS) + cbMICHDR + sizeof(SRTS_g_FB));
+				cbHeaderLength = wTxBufSize + sizeof(SRrvTime_gRTS) + cbMICHDR + sizeof(SRTS_g_FB) + sizeof(STxDataHead_g_FB);
+			} else { //RTS_needless
+				pvRrvTime = (PSRrvTime_gCTS) (pbyTxBufferAddr + wTxBufSize);
+				pMICHDR = (PSMICHDRHead) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gCTS));
+				pvRTS = NULL;
+				pvCTS = (PSCTS_FB) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gCTS) + cbMICHDR);
+				pvTxDataHd = (PSTxDataHead_g_FB) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gCTS) + cbMICHDR + sizeof(SCTS_FB));
+				cbHeaderLength = wTxBufSize + sizeof(SRrvTime_gCTS) + cbMICHDR + sizeof(SCTS_FB) + sizeof(STxDataHead_g_FB);
+			}
+		} // Auto Fall Back
+	} else {//802.11a/b packet
+
+		if (byFBOption == AUTO_FB_NONE) {
+			if (bRTS == true) {
+				pvRrvTime = (PSRrvTime_ab) (pbyTxBufferAddr + wTxBufSize);
+				pMICHDR = (PSMICHDRHead) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_ab));
+				pvRTS = (PSRTS_ab) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_ab) + cbMICHDR);
+				pvCTS = NULL;
+				pvTxDataHd = (PSTxDataHead_ab) (pbyTxBufferAddr + wTxBufSize + sizeof(PSRrvTime_ab) + cbMICHDR + sizeof(SRTS_ab));
+				cbHeaderLength = wTxBufSize + sizeof(PSRrvTime_ab) + cbMICHDR + sizeof(SRTS_ab) + sizeof(STxDataHead_ab);
+			} else { //RTS_needless, need MICHDR
+				pvRrvTime = (PSRrvTime_ab) (pbyTxBufferAddr + wTxBufSize);
+				pMICHDR = (PSMICHDRHead) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_ab));
+				pvRTS = NULL;
+				pvCTS = NULL;
+				pvTxDataHd = (PSTxDataHead_ab) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_ab) + cbMICHDR);
+				cbHeaderLength = wTxBufSize + sizeof(SRrvTime_ab) + cbMICHDR + sizeof(STxDataHead_ab);
+			}
+		} else {
+			// Auto Fall Back
+			if (bRTS == true) {//RTS_need
+				pvRrvTime = (PSRrvTime_ab) (pbyTxBufferAddr + wTxBufSize);
+				pMICHDR = (PSMICHDRHead) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_ab));
+				pvRTS = (PSRTS_a_FB) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_ab) + cbMICHDR);
+				pvCTS = NULL;
+				pvTxDataHd = (PSTxDataHead_a_FB) (pbyTxBufferAddr + wTxBufSize + sizeof(PSRrvTime_ab) + cbMICHDR + sizeof(SRTS_a_FB));
+				cbHeaderLength = wTxBufSize + sizeof(PSRrvTime_ab) + cbMICHDR + sizeof(SRTS_a_FB) + sizeof(STxDataHead_a_FB);
+			} else { //RTS_needless
+				pvRrvTime = (PSRrvTime_ab) (pbyTxBufferAddr + wTxBufSize);
+				pMICHDR = (PSMICHDRHead) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_ab));
+				pvRTS = NULL;
+				pvCTS = NULL;
+				pvTxDataHd = (PSTxDataHead_a_FB) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_ab) + cbMICHDR);
+				cbHeaderLength = wTxBufSize + sizeof(SRrvTime_ab) + cbMICHDR + sizeof(STxDataHead_a_FB);
+			}
+		} // Auto Fall Back
+	}
+	memset((void *)(pbyTxBufferAddr + wTxBufSize), 0, (cbHeaderLength - wTxBufSize));
 
 //////////////////////////////////////////////////////////////////
-    if ((bNeedEncrypt == true) && (pTransmitKey != NULL) && (pTransmitKey->byCipherSuite == KEY_CTL_TKIP)) {
-        if (pDevice->pMgmt->eAuthenMode == WMAC_AUTH_WPANONE) {
-            dwMICKey0 = *(unsigned long *)(&pTransmitKey->abyKey[16]);
-            dwMICKey1 = *(unsigned long *)(&pTransmitKey->abyKey[20]);
-        }
-        else if ((pTransmitKey->dwKeyIndex & AUTHENTICATOR_KEY) != 0) {
-            dwMICKey0 = *(unsigned long *)(&pTransmitKey->abyKey[16]);
-            dwMICKey1 = *(unsigned long *)(&pTransmitKey->abyKey[20]);
-        }
-        else {
-            dwMICKey0 = *(unsigned long *)(&pTransmitKey->abyKey[24]);
-            dwMICKey1 = *(unsigned long *)(&pTransmitKey->abyKey[28]);
-        }
-        // DO Software Michael
-        MIC_vInit(dwMICKey0, dwMICKey1);
-        MIC_vAppend((unsigned char *)&(psEthHeader->abyDstAddr[0]), 12);
-        dwMIC_Priority = 0;
-        MIC_vAppend((unsigned char *)&dwMIC_Priority, 4);
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MIC KEY: %lX, %lX\n", dwMICKey0, dwMICKey1);
-    }
+	if ((bNeedEncrypt == true) && (pTransmitKey != NULL) && (pTransmitKey->byCipherSuite == KEY_CTL_TKIP)) {
+		if (pDevice->pMgmt->eAuthenMode == WMAC_AUTH_WPANONE) {
+			dwMICKey0 = *(unsigned long *)(&pTransmitKey->abyKey[16]);
+			dwMICKey1 = *(unsigned long *)(&pTransmitKey->abyKey[20]);
+		} else if ((pTransmitKey->dwKeyIndex & AUTHENTICATOR_KEY) != 0) {
+			dwMICKey0 = *(unsigned long *)(&pTransmitKey->abyKey[16]);
+			dwMICKey1 = *(unsigned long *)(&pTransmitKey->abyKey[20]);
+		} else {
+			dwMICKey0 = *(unsigned long *)(&pTransmitKey->abyKey[24]);
+			dwMICKey1 = *(unsigned long *)(&pTransmitKey->abyKey[28]);
+		}
+		// DO Software Michael
+		MIC_vInit(dwMICKey0, dwMICKey1);
+		MIC_vAppend((unsigned char *)&(psEthHeader->abyDstAddr[0]), 12);
+		dwMIC_Priority = 0;
+		MIC_vAppend((unsigned char *)&dwMIC_Priority, 4);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "MIC KEY: %lX, %lX\n", dwMICKey0, dwMICKey1);
+	}
 
 ///////////////////////////////////////////////////////////////////
 
-    pbyMacHdr = (unsigned char *)(pbyTxBufferAddr + cbHeaderLength);
-    pbyPayloadHead = (unsigned char *)(pbyMacHdr + cbMACHdLen + uPadding + cbIVlen);
-    pbyIVHead = (unsigned char *)(pbyMacHdr + cbMACHdLen + uPadding);
-
-    if ((cbFrameSize > pDevice->wFragmentationThreshold) && (bNeedACK == true) && (bIsWEP256 == false)) {
-        // Fragmentation
-        // FragThreshold = Fragment size(Hdr+(IV)+fragment payload+(MIC)+(ICV)+FCS)
-        cbFragmentSize = pDevice->wFragmentationThreshold;
-        cbFragPayloadSize = cbFragmentSize - cbMACHdLen - cbIVlen - cbICVlen - cbFCSlen;
-        //FragNum = (FrameSize-(Hdr+FCS))/(Fragment Size -(Hrd+FCS)))
-        uMACfragNum = (unsigned short) ((cbFrameBodySize + cbMIClen) / cbFragPayloadSize);
-        cbLastFragPayloadSize = (cbFrameBodySize + cbMIClen) % cbFragPayloadSize;
-        if (cbLastFragPayloadSize == 0) {
-            cbLastFragPayloadSize = cbFragPayloadSize;
-        } else {
-            uMACfragNum++;
-        }
-        //[Hdr+(IV)+last fragment payload+(MIC)+(ICV)+FCS]
-        cbLastFragmentSize = cbMACHdLen + cbLastFragPayloadSize + cbIVlen + cbICVlen + cbFCSlen;
-
-        for (uFragIdx = 0; uFragIdx < uMACfragNum; uFragIdx ++) {
-            if (uFragIdx == 0) {
-                //=========================
-                //    Start Fragmentation
-                //=========================
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Start Fragmentation...\n");
-                wFragType = FRAGCTL_STAFRAG;
-
-
-                //Fill FIFO,RrvTime,RTS,and CTS
-                s_vGenerateTxParameter(pDevice, byPktType, (void *)psTxBufHd, pvRrvTime, pvRTS, pvCTS,
-                                       cbFragmentSize, bNeedACK, uDMAIdx, psEthHeader, pDevice->wCurrentRate);
-                //Fill DataHead
-                uDuration = s_uFillDataHead(pDevice, byPktType, pvTxDataHd, cbFragmentSize, uDMAIdx, bNeedACK,
-                                            uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption, pDevice->wCurrentRate);
-                // Generate TX MAC Header
-                vGenerateMACHeader(pDevice, pbyMacHdr, (unsigned short)uDuration, psEthHeader, bNeedEncrypt,
-                                   wFragType, uDMAIdx, uFragIdx);
-
-                if (bNeedEncrypt == true) {
-                    //Fill TXKEY
-                    s_vFillTxKey(pDevice, (unsigned char *)(psTxBufHd->adwTxKey), pbyIVHead, pTransmitKey,
-                                 pbyMacHdr, (unsigned short)cbFragPayloadSize, (unsigned char *)pMICHDR);
-                    //Fill IV(ExtIV,RSNHDR)
-                    if (pDevice->bEnableHostWEP) {
-                        pMgmt->sNodeDBTable[uNodeIndex].dwTSC47_16 = pTransmitKey->dwTSC47_16;
-                        pMgmt->sNodeDBTable[uNodeIndex].wTSC15_0 = pTransmitKey->wTSC15_0;
-                    }
-                }
-
-
-                // 802.1H
-                if (ntohs(psEthHeader->wType) > ETH_DATA_LEN) {
-                    if ((psEthHeader->wType == TYPE_PKT_IPX) ||
-                        (psEthHeader->wType == cpu_to_le16(0xF380))) {
-                        memcpy((unsigned char *) (pbyPayloadHead), &pDevice->abySNAP_Bridgetunnel[0], 6);
-                    }
-                    else {
-                        memcpy((unsigned char *) (pbyPayloadHead), &pDevice->abySNAP_RFC1042[0], 6);
-                    }
-                    pbyType = (unsigned char *) (pbyPayloadHead + 6);
-                    memcpy(pbyType, &(psEthHeader->wType), sizeof(unsigned short));
-                    cb802_1_H_len = 8;
-                }
-
-                cbReqCount = cbHeaderLength + cbMACHdLen + uPadding + cbIVlen + cbFragPayloadSize;
-                //---------------------------
-                // S/W or H/W Encryption
-                //---------------------------
-                //Fill MICHDR
-                //if (pDevice->bAES) {
-                //    s_vFillMICHDR(pDevice, (unsigned char *)pMICHDR, pbyMacHdr, (unsigned short)cbFragPayloadSize);
-                //}
-                //cbReqCount += s_uDoEncryption(pDevice, psEthHeader, (void *)psTxBufHd, byKeySel,
-                //                                pbyPayloadHead, (unsigned short)cbFragPayloadSize, uDMAIdx);
-
-
-
-                //pbyBuffer = (unsigned char *)pDevice->aamTxBuf[uDMAIdx][uDescIdx].pbyVAddr;
-                pbyBuffer = (unsigned char *)pHeadTD->pTDInfo->buf;
-
-                uLength = cbHeaderLength + cbMACHdLen + uPadding + cbIVlen + cb802_1_H_len;
-                //copy TxBufferHeader + MacHeader to desc
-                memcpy(pbyBuffer, (void *)psTxBufHd, uLength);
-
-                // Copy the Packet into a tx Buffer
-                memcpy((pbyBuffer + uLength), (pPacket + 14), (cbFragPayloadSize - cb802_1_H_len));
-
-
-                uTotalCopyLength += cbFragPayloadSize - cb802_1_H_len;
-
-                if ((bNeedEncrypt == true) && (pTransmitKey != NULL) && (pTransmitKey->byCipherSuite == KEY_CTL_TKIP)) {
-                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Start MIC: %d\n", cbFragPayloadSize);
-                    MIC_vAppend((pbyBuffer + uLength - cb802_1_H_len), cbFragPayloadSize);
-
-                }
-
-                //---------------------------
-                // S/W Encryption
-                //---------------------------
-                if ((pDevice->byLocalID <= REV_ID_VT3253_A1)) {
-                    if (bNeedEncrypt) {
-                        s_vSWencryption(pDevice, pTransmitKey, (pbyBuffer + uLength - cb802_1_H_len), (unsigned short)cbFragPayloadSize);
-                        cbReqCount += cbICVlen;
-                    }
-                }
-
-                ptdCurr = (PSTxDesc)pHeadTD;
-                //--------------------
-                //1.Set TSR1 & ReqCount in TxDescHead
-                //2.Set FragCtl in TxBufferHead
-                //3.Set Frame Control
-                //4.Set Sequence Control
-                //5.Get S/W generate FCS
-                //--------------------
-                s_vFillFragParameter(pDevice, pbyBuffer, uDMAIdx, (void *)ptdCurr, wFragType, cbReqCount);
-
-                ptdCurr->pTDInfo->dwReqCount = cbReqCount - uPadding;
-                ptdCurr->pTDInfo->dwHeaderLength = cbHeaderLength;
-                ptdCurr->pTDInfo->skb_dma = ptdCurr->pTDInfo->buf_dma;
-                ptdCurr->buff_addr = cpu_to_le32(ptdCurr->pTDInfo->skb_dma);
-                pDevice->iTDUsed[uDMAIdx]++;
-                pHeadTD = ptdCurr->next;
-            }
-            else if (uFragIdx == (uMACfragNum-1)) {
-                //=========================
-                //    Last Fragmentation
-                //=========================
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Last Fragmentation...\n");
-                //tmpDescIdx = (uDescIdx + uFragIdx) % pDevice->cbTD[uDMAIdx];
-
-                wFragType = FRAGCTL_ENDFRAG;
-
-                //Fill FIFO,RrvTime,RTS,and CTS
-                s_vGenerateTxParameter(pDevice, byPktType, (void *)psTxBufHd, pvRrvTime, pvRTS, pvCTS,
-                                       cbLastFragmentSize, bNeedACK, uDMAIdx, psEthHeader, pDevice->wCurrentRate);
-                //Fill DataHead
-                uDuration = s_uFillDataHead(pDevice, byPktType, pvTxDataHd, cbLastFragmentSize, uDMAIdx, bNeedACK,
-                                            uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption, pDevice->wCurrentRate);
-
-                // Generate TX MAC Header
-                vGenerateMACHeader(pDevice, pbyMacHdr, (unsigned short)uDuration, psEthHeader, bNeedEncrypt,
-                                   wFragType, uDMAIdx, uFragIdx);
-
-                if (bNeedEncrypt == true) {
-                    //Fill TXKEY
-                    s_vFillTxKey(pDevice, (unsigned char *)(psTxBufHd->adwTxKey), pbyIVHead, pTransmitKey,
-                                 pbyMacHdr, (unsigned short)cbLastFragPayloadSize, (unsigned char *)pMICHDR);
-
-                    if (pDevice->bEnableHostWEP) {
-                        pMgmt->sNodeDBTable[uNodeIndex].dwTSC47_16 = pTransmitKey->dwTSC47_16;
-                        pMgmt->sNodeDBTable[uNodeIndex].wTSC15_0 = pTransmitKey->wTSC15_0;
-                    }
-
-                }
-
-
-                cbReqCount = cbHeaderLength + cbMACHdLen + uPadding + cbIVlen + cbLastFragPayloadSize;
-                //---------------------------
-                // S/W or H/W Encryption
-                //---------------------------
-
-
-
-                pbyBuffer = (unsigned char *)pHeadTD->pTDInfo->buf;
-                //pbyBuffer = (unsigned char *)pDevice->aamTxBuf[uDMAIdx][tmpDescIdx].pbyVAddr;
-
-                uLength = cbHeaderLength + cbMACHdLen + uPadding + cbIVlen;
-
-                //copy TxBufferHeader + MacHeader to desc
-                memcpy(pbyBuffer, (void *)psTxBufHd, uLength);
-
-                // Copy the Packet into a tx Buffer
-                if (bMIC2Frag == false) {
-
-                    memcpy((pbyBuffer + uLength),
-                             (pPacket + 14 + uTotalCopyLength),
-                             (cbLastFragPayloadSize - cbMIClen)
-                             );
-                    //TODO check uTmpLen !
-                    uTmpLen = cbLastFragPayloadSize - cbMIClen;
-
-                }
-                if ((bNeedEncrypt == true) && (pTransmitKey != NULL) && (pTransmitKey->byCipherSuite == KEY_CTL_TKIP)) {
-                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"LAST: uMICFragLen:%d, cbLastFragPayloadSize:%d, uTmpLen:%d\n",
-                                   uMICFragLen, cbLastFragPayloadSize, uTmpLen);
-
-                    if (bMIC2Frag == false) {
-                        if (uTmpLen != 0)
-                            MIC_vAppend((pbyBuffer + uLength), uTmpLen);
-                        pdwMIC_L = (unsigned long *)(pbyBuffer + uLength + uTmpLen);
-                        pdwMIC_R = (unsigned long *)(pbyBuffer + uLength + uTmpLen + 4);
-                        MIC_vGetMIC(pdwMIC_L, pdwMIC_R);
-                        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Last MIC:%lX, %lX\n", *pdwMIC_L, *pdwMIC_R);
-                    } else {
-                        if (uMICFragLen >= 4) {
-                            memcpy((pbyBuffer + uLength), ((unsigned char *)&dwSafeMIC_R + (uMICFragLen - 4)),
-                                     (cbMIClen - uMICFragLen));
-                            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"LAST: uMICFragLen >= 4: %X, %d\n",
-                                           *(unsigned char *)((unsigned char *)&dwSafeMIC_R + (uMICFragLen - 4)),
-                                           (cbMIClen - uMICFragLen));
-
-                        } else {
-                            memcpy((pbyBuffer + uLength), ((unsigned char *)&dwSafeMIC_L + uMICFragLen),
-                                     (4 - uMICFragLen));
-                            memcpy((pbyBuffer + uLength + (4 - uMICFragLen)), &dwSafeMIC_R, 4);
-                            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"LAST: uMICFragLen < 4: %X, %d\n",
-                                           *(unsigned char *)((unsigned char *)&dwSafeMIC_R + uMICFragLen - 4),
-                                           (cbMIClen - uMICFragLen));
-                        }
-                        /*
-                        for (ii = 0; ii < cbLastFragPayloadSize + 8 + 24; ii++) {
-                            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"%02x ", *((unsigned char *)((pbyBuffer + uLength) + ii - 8 - 24)));
-                        }
-                        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n\n");
-                        */
-                    }
-                    MIC_vUnInit();
-                } else {
-                    ASSERT(uTmpLen == (cbLastFragPayloadSize - cbMIClen));
-                }
-
-
-                //---------------------------
-                // S/W Encryption
-                //---------------------------
-                if ((pDevice->byLocalID <= REV_ID_VT3253_A1)) {
-                    if (bNeedEncrypt) {
-                        s_vSWencryption(pDevice, pTransmitKey, (pbyBuffer + uLength), (unsigned short)cbLastFragPayloadSize);
-                        cbReqCount += cbICVlen;
-                    }
-                }
-
-                ptdCurr = (PSTxDesc)pHeadTD;
-
-                //--------------------
-                //1.Set TSR1 & ReqCount in TxDescHead
-                //2.Set FragCtl in TxBufferHead
-                //3.Set Frame Control
-                //4.Set Sequence Control
-                //5.Get S/W generate FCS
-                //--------------------
-
-
-                s_vFillFragParameter(pDevice, pbyBuffer, uDMAIdx, (void *)ptdCurr, wFragType, cbReqCount);
-
-                ptdCurr->pTDInfo->dwReqCount = cbReqCount - uPadding;
-                ptdCurr->pTDInfo->dwHeaderLength = cbHeaderLength;
-                ptdCurr->pTDInfo->skb_dma = ptdCurr->pTDInfo->buf_dma;
-                ptdCurr->buff_addr = cpu_to_le32(ptdCurr->pTDInfo->skb_dma);
-                pDevice->iTDUsed[uDMAIdx]++;
-                pHeadTD = ptdCurr->next;
-
-            }
-            else {
-                //=========================
-                //    Middle Fragmentation
-                //=========================
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Middle Fragmentation...\n");
-                //tmpDescIdx = (uDescIdx + uFragIdx) % pDevice->cbTD[uDMAIdx];
-
-                wFragType = FRAGCTL_MIDFRAG;
-
-                //Fill FIFO,RrvTime,RTS,and CTS
-                s_vGenerateTxParameter(pDevice, byPktType, (void *)psTxBufHd, pvRrvTime, pvRTS, pvCTS,
-                                       cbFragmentSize, bNeedACK, uDMAIdx, psEthHeader, pDevice->wCurrentRate);
-                //Fill DataHead
-                uDuration = s_uFillDataHead(pDevice, byPktType, pvTxDataHd, cbFragmentSize, uDMAIdx, bNeedACK,
-                                            uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption, pDevice->wCurrentRate);
-
-                // Generate TX MAC Header
-                vGenerateMACHeader(pDevice, pbyMacHdr, (unsigned short)uDuration, psEthHeader, bNeedEncrypt,
-                                   wFragType, uDMAIdx, uFragIdx);
-
-
-                if (bNeedEncrypt == true) {
-                    //Fill TXKEY
-                    s_vFillTxKey(pDevice, (unsigned char *)(psTxBufHd->adwTxKey), pbyIVHead, pTransmitKey,
-                                 pbyMacHdr, (unsigned short)cbFragPayloadSize, (unsigned char *)pMICHDR);
-
-                    if (pDevice->bEnableHostWEP) {
-                        pMgmt->sNodeDBTable[uNodeIndex].dwTSC47_16 = pTransmitKey->dwTSC47_16;
-                        pMgmt->sNodeDBTable[uNodeIndex].wTSC15_0 = pTransmitKey->wTSC15_0;
-                    }
-                }
-
-                cbReqCount = cbHeaderLength + cbMACHdLen + uPadding + cbIVlen + cbFragPayloadSize;
-                //---------------------------
-                // S/W or H/W Encryption
-                //---------------------------
-                //Fill MICHDR
-                //if (pDevice->bAES) {
-                //    s_vFillMICHDR(pDevice, (unsigned char *)pMICHDR, pbyMacHdr, (unsigned short)cbFragPayloadSize);
-                //}
-                //cbReqCount += s_uDoEncryption(pDevice, psEthHeader, (void *)psTxBufHd, byKeySel,
-                //                              pbyPayloadHead, (unsigned short)cbFragPayloadSize, uDMAIdx);
-
-
-                pbyBuffer = (unsigned char *)pHeadTD->pTDInfo->buf;
-                //pbyBuffer = (unsigned char *)pDevice->aamTxBuf[uDMAIdx][tmpDescIdx].pbyVAddr;
-
-
-                uLength = cbHeaderLength + cbMACHdLen + uPadding + cbIVlen;
-
-                //copy TxBufferHeader + MacHeader to desc
-                memcpy(pbyBuffer, (void *)psTxBufHd, uLength);
-
-                // Copy the Packet into a tx Buffer
-                memcpy((pbyBuffer + uLength),
-                         (pPacket + 14 + uTotalCopyLength),
-                         cbFragPayloadSize
-                        );
-                uTmpLen = cbFragPayloadSize;
-
-                uTotalCopyLength += uTmpLen;
-
-                if ((bNeedEncrypt == true) && (pTransmitKey != NULL) && (pTransmitKey->byCipherSuite == KEY_CTL_TKIP)) {
-
-                    MIC_vAppend((pbyBuffer + uLength), uTmpLen);
-
-                    if (uTmpLen < cbFragPayloadSize) {
-                        bMIC2Frag = true;
-                        uMICFragLen = cbFragPayloadSize - uTmpLen;
-                        ASSERT(uMICFragLen < cbMIClen);
-
-                        pdwMIC_L = (unsigned long *)(pbyBuffer + uLength + uTmpLen);
-                        pdwMIC_R = (unsigned long *)(pbyBuffer + uLength + uTmpLen + 4);
-                        MIC_vGetMIC(pdwMIC_L, pdwMIC_R);
-                        dwSafeMIC_L = *pdwMIC_L;
-                        dwSafeMIC_R = *pdwMIC_R;
-
-                        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MIDDLE: uMICFragLen:%d, cbFragPayloadSize:%d, uTmpLen:%d\n",
-                                       uMICFragLen, cbFragPayloadSize, uTmpLen);
-                        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Fill MIC in Middle frag [%d]\n", uMICFragLen);
-                        /*
-                        for (ii = 0; ii < uMICFragLen; ii++) {
-                            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"%02x ", *((unsigned char *)((pbyBuffer + uLength + uTmpLen) + ii)));
-                        }
-                        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n");
-                        */
-                        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Get MIC:%lX, %lX\n", *pdwMIC_L, *pdwMIC_R);
-                    }
-                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Middle frag len: %d\n", uTmpLen);
-                    /*
-                    for (ii = 0; ii < uTmpLen; ii++) {
-                        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"%02x ", *((unsigned char *)((pbyBuffer + uLength) + ii)));
-                    }
-                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n\n");
-                    */
-
-                } else {
-                    ASSERT(uTmpLen == (cbFragPayloadSize));
-                }
-
-                if ((pDevice->byLocalID <= REV_ID_VT3253_A1)) {
-                    if (bNeedEncrypt) {
-                        s_vSWencryption(pDevice, pTransmitKey, (pbyBuffer + uLength), (unsigned short)cbFragPayloadSize);
-                        cbReqCount += cbICVlen;
-                    }
-                }
-
-                ptdCurr = (PSTxDesc)pHeadTD;
-
-                //--------------------
-                //1.Set TSR1 & ReqCount in TxDescHead
-                //2.Set FragCtl in TxBufferHead
-                //3.Set Frame Control
-                //4.Set Sequence Control
-                //5.Get S/W generate FCS
-                //--------------------
-
-                s_vFillFragParameter(pDevice, pbyBuffer, uDMAIdx, (void *)ptdCurr, wFragType, cbReqCount);
-
-                ptdCurr->pTDInfo->dwReqCount = cbReqCount - uPadding;
-                ptdCurr->pTDInfo->dwHeaderLength = cbHeaderLength;
-                ptdCurr->pTDInfo->skb_dma = ptdCurr->pTDInfo->buf_dma;
-                ptdCurr->buff_addr = cpu_to_le32(ptdCurr->pTDInfo->skb_dma);
-                pDevice->iTDUsed[uDMAIdx]++;
-                pHeadTD = ptdCurr->next;
-            }
-        }  // for (uMACfragNum)
-    }
-    else {
-        //=========================
-        //    No Fragmentation
-        //=========================
-        //DBG_PRTGRP03(("No Fragmentation...\n"));
-        //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"No Fragmentation...\n");
-        wFragType = FRAGCTL_NONFRAG;
-
-        //Set FragCtl in TxBufferHead
-        psTxBufHd->wFragCtl |= (unsigned short)wFragType;
-
-        //Fill FIFO,RrvTime,RTS,and CTS
-        s_vGenerateTxParameter(pDevice, byPktType, (void *)psTxBufHd, pvRrvTime, pvRTS, pvCTS,
-                               cbFrameSize, bNeedACK, uDMAIdx, psEthHeader, pDevice->wCurrentRate);
-        //Fill DataHead
-        uDuration = s_uFillDataHead(pDevice, byPktType, pvTxDataHd, cbFrameSize, uDMAIdx, bNeedACK,
-                                    0, 0, uMACfragNum, byFBOption, pDevice->wCurrentRate);
-
-        // Generate TX MAC Header
-        vGenerateMACHeader(pDevice, pbyMacHdr, (unsigned short)uDuration, psEthHeader, bNeedEncrypt,
-                           wFragType, uDMAIdx, 0);
-
-        if (bNeedEncrypt == true) {
-            //Fill TXKEY
-            s_vFillTxKey(pDevice, (unsigned char *)(psTxBufHd->adwTxKey), pbyIVHead, pTransmitKey,
-                         pbyMacHdr, (unsigned short)cbFrameBodySize, (unsigned char *)pMICHDR);
-
-            if (pDevice->bEnableHostWEP) {
-                pMgmt->sNodeDBTable[uNodeIndex].dwTSC47_16 = pTransmitKey->dwTSC47_16;
-                pMgmt->sNodeDBTable[uNodeIndex].wTSC15_0 = pTransmitKey->wTSC15_0;
-            }
-        }
-
-        // 802.1H
-        if (ntohs(psEthHeader->wType) > ETH_DATA_LEN) {
-            if ((psEthHeader->wType == TYPE_PKT_IPX) ||
-                (psEthHeader->wType == cpu_to_le16(0xF380))) {
-                memcpy((unsigned char *) (pbyPayloadHead), &pDevice->abySNAP_Bridgetunnel[0], 6);
-            }
-            else {
-                memcpy((unsigned char *) (pbyPayloadHead), &pDevice->abySNAP_RFC1042[0], 6);
-            }
-            pbyType = (unsigned char *) (pbyPayloadHead + 6);
-            memcpy(pbyType, &(psEthHeader->wType), sizeof(unsigned short));
-            cb802_1_H_len = 8;
-        }
-
-        cbReqCount = cbHeaderLength + cbMACHdLen + uPadding + cbIVlen + (cbFrameBodySize + cbMIClen);
-        //---------------------------
-        // S/W or H/W Encryption
-        //---------------------------
-        //Fill MICHDR
-        //if (pDevice->bAES) {
-        //    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Fill MICHDR...\n");
-        //    s_vFillMICHDR(pDevice, (unsigned char *)pMICHDR, pbyMacHdr, (unsigned short)cbFrameBodySize);
-        //}
-
-        pbyBuffer = (unsigned char *)pHeadTD->pTDInfo->buf;
-        //pbyBuffer = (unsigned char *)pDevice->aamTxBuf[uDMAIdx][uDescIdx].pbyVAddr;
-
-        uLength = cbHeaderLength + cbMACHdLen + uPadding + cbIVlen + cb802_1_H_len;
-
-        //copy TxBufferHeader + MacHeader to desc
-        memcpy(pbyBuffer, (void *)psTxBufHd, uLength);
-
-        // Copy the Packet into a tx Buffer
-        memcpy((pbyBuffer + uLength),
-                 (pPacket + 14),
-                 cbFrameBodySize - cb802_1_H_len
-                 );
-
-        if ((bNeedEncrypt == true) && (pTransmitKey != NULL) && (pTransmitKey->byCipherSuite == KEY_CTL_TKIP)){
-
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Length:%d, %d\n", cbFrameBodySize - cb802_1_H_len, uLength);
-            /*
-            for (ii = 0; ii < (cbFrameBodySize - cb802_1_H_len); ii++) {
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"%02x ", *((unsigned char *)((pbyBuffer + uLength) + ii)));
-            }
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n");
-            */
-
-            MIC_vAppend((pbyBuffer + uLength - cb802_1_H_len), cbFrameBodySize);
-
-            pdwMIC_L = (unsigned long *)(pbyBuffer + uLength - cb802_1_H_len + cbFrameBodySize);
-            pdwMIC_R = (unsigned long *)(pbyBuffer + uLength - cb802_1_H_len + cbFrameBodySize + 4);
-
-            MIC_vGetMIC(pdwMIC_L, pdwMIC_R);
-            MIC_vUnInit();
-
-
-            if (pDevice->bTxMICFail == true) {
-                *pdwMIC_L = 0;
-                *pdwMIC_R = 0;
-                pDevice->bTxMICFail = false;
-            }
-
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"uLength: %d, %d\n", uLength, cbFrameBodySize);
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"cbReqCount:%d, %d, %d, %d\n", cbReqCount, cbHeaderLength, uPadding, cbIVlen);
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MIC:%lx, %lx\n", *pdwMIC_L, *pdwMIC_R);
+	pbyMacHdr = (unsigned char *)(pbyTxBufferAddr + cbHeaderLength);
+	pbyPayloadHead = (unsigned char *)(pbyMacHdr + cbMACHdLen + uPadding + cbIVlen);
+	pbyIVHead = (unsigned char *)(pbyMacHdr + cbMACHdLen + uPadding);
+
+	if ((cbFrameSize > pDevice->wFragmentationThreshold) && (bNeedACK == true) && (bIsWEP256 == false)) {
+		// Fragmentation
+		// FragThreshold = Fragment size(Hdr+(IV)+fragment payload+(MIC)+(ICV)+FCS)
+		cbFragmentSize = pDevice->wFragmentationThreshold;
+		cbFragPayloadSize = cbFragmentSize - cbMACHdLen - cbIVlen - cbICVlen - cbFCSlen;
+		//FragNum = (FrameSize-(Hdr+FCS))/(Fragment Size -(Hrd+FCS)))
+		uMACfragNum = (unsigned short) ((cbFrameBodySize + cbMIClen) / cbFragPayloadSize);
+		cbLastFragPayloadSize = (cbFrameBodySize + cbMIClen) % cbFragPayloadSize;
+		if (cbLastFragPayloadSize == 0) {
+			cbLastFragPayloadSize = cbFragPayloadSize;
+		} else {
+			uMACfragNum++;
+		}
+		//[Hdr+(IV)+last fragment payload+(MIC)+(ICV)+FCS]
+		cbLastFragmentSize = cbMACHdLen + cbLastFragPayloadSize + cbIVlen + cbICVlen + cbFCSlen;
+
+		for (uFragIdx = 0; uFragIdx < uMACfragNum; uFragIdx++) {
+			if (uFragIdx == 0) {
+				//=========================
+				//    Start Fragmentation
+				//=========================
+				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Start Fragmentation...\n");
+				wFragType = FRAGCTL_STAFRAG;
+
+				//Fill FIFO,RrvTime,RTS,and CTS
+				s_vGenerateTxParameter(pDevice, byPktType, (void *)psTxBufHd, pvRrvTime, pvRTS, pvCTS,
+						       cbFragmentSize, bNeedACK, uDMAIdx, psEthHeader, pDevice->wCurrentRate);
+				//Fill DataHead
+				uDuration = s_uFillDataHead(pDevice, byPktType, pvTxDataHd, cbFragmentSize, uDMAIdx, bNeedACK,
+							    uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption, pDevice->wCurrentRate);
+				// Generate TX MAC Header
+				vGenerateMACHeader(pDevice, pbyMacHdr, (unsigned short)uDuration, psEthHeader, bNeedEncrypt,
+						   wFragType, uDMAIdx, uFragIdx);
+
+				if (bNeedEncrypt == true) {
+					//Fill TXKEY
+					s_vFillTxKey(pDevice, (unsigned char *)(psTxBufHd->adwTxKey), pbyIVHead, pTransmitKey,
+						     pbyMacHdr, (unsigned short)cbFragPayloadSize, (unsigned char *)pMICHDR);
+					//Fill IV(ExtIV,RSNHDR)
+					if (pDevice->bEnableHostWEP) {
+						pMgmt->sNodeDBTable[uNodeIndex].dwTSC47_16 = pTransmitKey->dwTSC47_16;
+						pMgmt->sNodeDBTable[uNodeIndex].wTSC15_0 = pTransmitKey->wTSC15_0;
+					}
+				}
+
+				// 802.1H
+				if (ntohs(psEthHeader->wType) > ETH_DATA_LEN) {
+					if ((psEthHeader->wType == TYPE_PKT_IPX) ||
+					    (psEthHeader->wType == cpu_to_le16(0xF380))) {
+						memcpy((unsigned char *)(pbyPayloadHead), &pDevice->abySNAP_Bridgetunnel[0], 6);
+					} else {
+						memcpy((unsigned char *)(pbyPayloadHead), &pDevice->abySNAP_RFC1042[0], 6);
+					}
+					pbyType = (unsigned char *)(pbyPayloadHead + 6);
+					memcpy(pbyType, &(psEthHeader->wType), sizeof(unsigned short));
+					cb802_1_H_len = 8;
+				}
+
+				cbReqCount = cbHeaderLength + cbMACHdLen + uPadding + cbIVlen + cbFragPayloadSize;
+				//---------------------------
+				// S/W or H/W Encryption
+				//---------------------------
+				pbyBuffer = (unsigned char *)pHeadTD->pTDInfo->buf;
+
+				uLength = cbHeaderLength + cbMACHdLen + uPadding + cbIVlen + cb802_1_H_len;
+				//copy TxBufferHeader + MacHeader to desc
+				memcpy(pbyBuffer, (void *)psTxBufHd, uLength);
+
+				// Copy the Packet into a tx Buffer
+				memcpy((pbyBuffer + uLength), (pPacket + 14), (cbFragPayloadSize - cb802_1_H_len));
+
+				uTotalCopyLength += cbFragPayloadSize - cb802_1_H_len;
+
+				if ((bNeedEncrypt == true) && (pTransmitKey != NULL) && (pTransmitKey->byCipherSuite == KEY_CTL_TKIP)) {
+					DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Start MIC: %d\n", cbFragPayloadSize);
+					MIC_vAppend((pbyBuffer + uLength - cb802_1_H_len), cbFragPayloadSize);
+
+				}
+
+				//---------------------------
+				// S/W Encryption
+				//---------------------------
+				if ((pDevice->byLocalID <= REV_ID_VT3253_A1)) {
+					if (bNeedEncrypt) {
+						s_vSWencryption(pDevice, pTransmitKey, (pbyBuffer + uLength - cb802_1_H_len), (unsigned short)cbFragPayloadSize);
+						cbReqCount += cbICVlen;
+					}
+				}
+
+				ptdCurr = (PSTxDesc)pHeadTD;
+				//--------------------
+				//1.Set TSR1 & ReqCount in TxDescHead
+				//2.Set FragCtl in TxBufferHead
+				//3.Set Frame Control
+				//4.Set Sequence Control
+				//5.Get S/W generate FCS
+				//--------------------
+				s_vFillFragParameter(pDevice, pbyBuffer, uDMAIdx, (void *)ptdCurr, wFragType, cbReqCount);
+
+				ptdCurr->pTDInfo->dwReqCount = cbReqCount - uPadding;
+				ptdCurr->pTDInfo->dwHeaderLength = cbHeaderLength;
+				ptdCurr->pTDInfo->skb_dma = ptdCurr->pTDInfo->buf_dma;
+				ptdCurr->buff_addr = cpu_to_le32(ptdCurr->pTDInfo->skb_dma);
+				pDevice->iTDUsed[uDMAIdx]++;
+				pHeadTD = ptdCurr->next;
+			} else if (uFragIdx == (uMACfragNum-1)) {
+				//=========================
+				//    Last Fragmentation
+				//=========================
+				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Last Fragmentation...\n");
+				//tmpDescIdx = (uDescIdx + uFragIdx) % pDevice->cbTD[uDMAIdx];
+
+				wFragType = FRAGCTL_ENDFRAG;
+
+				//Fill FIFO,RrvTime,RTS,and CTS
+				s_vGenerateTxParameter(pDevice, byPktType, (void *)psTxBufHd, pvRrvTime, pvRTS, pvCTS,
+						       cbLastFragmentSize, bNeedACK, uDMAIdx, psEthHeader, pDevice->wCurrentRate);
+				//Fill DataHead
+				uDuration = s_uFillDataHead(pDevice, byPktType, pvTxDataHd, cbLastFragmentSize, uDMAIdx, bNeedACK,
+							    uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption, pDevice->wCurrentRate);
+
+				// Generate TX MAC Header
+				vGenerateMACHeader(pDevice, pbyMacHdr, (unsigned short)uDuration, psEthHeader, bNeedEncrypt,
+						   wFragType, uDMAIdx, uFragIdx);
+
+				if (bNeedEncrypt == true) {
+					//Fill TXKEY
+					s_vFillTxKey(pDevice, (unsigned char *)(psTxBufHd->adwTxKey), pbyIVHead, pTransmitKey,
+						     pbyMacHdr, (unsigned short)cbLastFragPayloadSize, (unsigned char *)pMICHDR);
+
+					if (pDevice->bEnableHostWEP) {
+						pMgmt->sNodeDBTable[uNodeIndex].dwTSC47_16 = pTransmitKey->dwTSC47_16;
+						pMgmt->sNodeDBTable[uNodeIndex].wTSC15_0 = pTransmitKey->wTSC15_0;
+					}
+
+				}
+
+				cbReqCount = cbHeaderLength + cbMACHdLen + uPadding + cbIVlen + cbLastFragPayloadSize;
+				//---------------------------
+				// S/W or H/W Encryption
+				//---------------------------
+
+				pbyBuffer = (unsigned char *)pHeadTD->pTDInfo->buf;
+				//pbyBuffer = (unsigned char *)pDevice->aamTxBuf[uDMAIdx][tmpDescIdx].pbyVAddr;
+
+				uLength = cbHeaderLength + cbMACHdLen + uPadding + cbIVlen;
+
+				//copy TxBufferHeader + MacHeader to desc
+				memcpy(pbyBuffer, (void *)psTxBufHd, uLength);
+
+				// Copy the Packet into a tx Buffer
+				if (bMIC2Frag == false) {
+					memcpy((pbyBuffer + uLength),
+					       (pPacket + 14 + uTotalCopyLength),
+					       (cbLastFragPayloadSize - cbMIClen)
+);
+					//TODO check uTmpLen !
+					uTmpLen = cbLastFragPayloadSize - cbMIClen;
+
+				}
+				if ((bNeedEncrypt == true) && (pTransmitKey != NULL) && (pTransmitKey->byCipherSuite == KEY_CTL_TKIP)) {
+					DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "LAST: uMICFragLen:%d, cbLastFragPayloadSize:%d, uTmpLen:%d\n",
+						uMICFragLen, cbLastFragPayloadSize, uTmpLen);
+
+					if (bMIC2Frag == false) {
+						if (uTmpLen != 0)
+							MIC_vAppend((pbyBuffer + uLength), uTmpLen);
+						pdwMIC_L = (unsigned long *)(pbyBuffer + uLength + uTmpLen);
+						pdwMIC_R = (unsigned long *)(pbyBuffer + uLength + uTmpLen + 4);
+						MIC_vGetMIC(pdwMIC_L, pdwMIC_R);
+						DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Last MIC:%lX, %lX\n", *pdwMIC_L, *pdwMIC_R);
+					} else {
+						if (uMICFragLen >= 4) {
+							memcpy((pbyBuffer + uLength), ((unsigned char *)&dwSafeMIC_R + (uMICFragLen - 4)),
+							       (cbMIClen - uMICFragLen));
+							DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "LAST: uMICFragLen >= 4: %X, %d\n",
+								*(unsigned char *)((unsigned char *)&dwSafeMIC_R + (uMICFragLen - 4)),
+								(cbMIClen - uMICFragLen));
+
+						} else {
+							memcpy((pbyBuffer + uLength), ((unsigned char *)&dwSafeMIC_L + uMICFragLen),
+							       (4 - uMICFragLen));
+							memcpy((pbyBuffer + uLength + (4 - uMICFragLen)), &dwSafeMIC_R, 4);
+							DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "LAST: uMICFragLen < 4: %X, %d\n",
+								*(unsigned char *)((unsigned char *)&dwSafeMIC_R + uMICFragLen - 4),
+								(cbMIClen - uMICFragLen));
+						}
+						/*
+						  for (ii = 0; ii < cbLastFragPayloadSize + 8 + 24; ii++) {
+						  DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%02x ", *((unsigned char *)((pbyBuffer + uLength) + ii - 8 - 24)));
+						  }
+						  DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "\n\n");
+						*/
+					}
+					MIC_vUnInit();
+				} else {
+					ASSERT(uTmpLen == (cbLastFragPayloadSize - cbMIClen));
+				}
+
+				//---------------------------
+				// S/W Encryption
+				//---------------------------
+				if ((pDevice->byLocalID <= REV_ID_VT3253_A1)) {
+					if (bNeedEncrypt) {
+						s_vSWencryption(pDevice, pTransmitKey, (pbyBuffer + uLength), (unsigned short)cbLastFragPayloadSize);
+						cbReqCount += cbICVlen;
+					}
+				}
+
+				ptdCurr = (PSTxDesc)pHeadTD;
+
+				//--------------------
+				//1.Set TSR1 & ReqCount in TxDescHead
+				//2.Set FragCtl in TxBufferHead
+				//3.Set Frame Control
+				//4.Set Sequence Control
+				//5.Get S/W generate FCS
+				//--------------------
+
+				s_vFillFragParameter(pDevice, pbyBuffer, uDMAIdx, (void *)ptdCurr, wFragType, cbReqCount);
+
+				ptdCurr->pTDInfo->dwReqCount = cbReqCount - uPadding;
+				ptdCurr->pTDInfo->dwHeaderLength = cbHeaderLength;
+				ptdCurr->pTDInfo->skb_dma = ptdCurr->pTDInfo->buf_dma;
+				ptdCurr->buff_addr = cpu_to_le32(ptdCurr->pTDInfo->skb_dma);
+				pDevice->iTDUsed[uDMAIdx]++;
+				pHeadTD = ptdCurr->next;
+
+			} else {
+				//=========================
+				//    Middle Fragmentation
+				//=========================
+				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Middle Fragmentation...\n");
+				//tmpDescIdx = (uDescIdx + uFragIdx) % pDevice->cbTD[uDMAIdx];
+
+				wFragType = FRAGCTL_MIDFRAG;
+
+				//Fill FIFO,RrvTime,RTS,and CTS
+				s_vGenerateTxParameter(pDevice, byPktType, (void *)psTxBufHd, pvRrvTime, pvRTS, pvCTS,
+						       cbFragmentSize, bNeedACK, uDMAIdx, psEthHeader, pDevice->wCurrentRate);
+				//Fill DataHead
+				uDuration = s_uFillDataHead(pDevice, byPktType, pvTxDataHd, cbFragmentSize, uDMAIdx, bNeedACK,
+							    uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption, pDevice->wCurrentRate);
+
+				// Generate TX MAC Header
+				vGenerateMACHeader(pDevice, pbyMacHdr, (unsigned short)uDuration, psEthHeader, bNeedEncrypt,
+						   wFragType, uDMAIdx, uFragIdx);
+
+				if (bNeedEncrypt == true) {
+					//Fill TXKEY
+					s_vFillTxKey(pDevice, (unsigned char *)(psTxBufHd->adwTxKey), pbyIVHead, pTransmitKey,
+						     pbyMacHdr, (unsigned short)cbFragPayloadSize, (unsigned char *)pMICHDR);
+
+					if (pDevice->bEnableHostWEP) {
+						pMgmt->sNodeDBTable[uNodeIndex].dwTSC47_16 = pTransmitKey->dwTSC47_16;
+						pMgmt->sNodeDBTable[uNodeIndex].wTSC15_0 = pTransmitKey->wTSC15_0;
+					}
+				}
+
+				cbReqCount = cbHeaderLength + cbMACHdLen + uPadding + cbIVlen + cbFragPayloadSize;
+				//---------------------------
+				// S/W or H/W Encryption
+				//---------------------------
+
+				pbyBuffer = (unsigned char *)pHeadTD->pTDInfo->buf;
+				uLength = cbHeaderLength + cbMACHdLen + uPadding + cbIVlen;
+
+				//copy TxBufferHeader + MacHeader to desc
+				memcpy(pbyBuffer, (void *)psTxBufHd, uLength);
+
+				// Copy the Packet into a tx Buffer
+				memcpy((pbyBuffer + uLength),
+				       (pPacket + 14 + uTotalCopyLength),
+				       cbFragPayloadSize
+);
+				uTmpLen = cbFragPayloadSize;
+
+				uTotalCopyLength += uTmpLen;
+
+				if ((bNeedEncrypt == true) && (pTransmitKey != NULL) && (pTransmitKey->byCipherSuite == KEY_CTL_TKIP)) {
+					MIC_vAppend((pbyBuffer + uLength), uTmpLen);
+
+					if (uTmpLen < cbFragPayloadSize) {
+						bMIC2Frag = true;
+						uMICFragLen = cbFragPayloadSize - uTmpLen;
+						ASSERT(uMICFragLen < cbMIClen);
+
+						pdwMIC_L = (unsigned long *)(pbyBuffer + uLength + uTmpLen);
+						pdwMIC_R = (unsigned long *)(pbyBuffer + uLength + uTmpLen + 4);
+						MIC_vGetMIC(pdwMIC_L, pdwMIC_R);
+						dwSafeMIC_L = *pdwMIC_L;
+						dwSafeMIC_R = *pdwMIC_R;
+
+						DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "MIDDLE: uMICFragLen:%d, cbFragPayloadSize:%d, uTmpLen:%d\n",
+							uMICFragLen, cbFragPayloadSize, uTmpLen);
+						DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Fill MIC in Middle frag [%d]\n", uMICFragLen);
+						/*
+						  for (ii = 0; ii < uMICFragLen; ii++) {
+						  DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%02x ", *((unsigned char *)((pbyBuffer + uLength + uTmpLen) + ii)));
+						  }
+						  DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "\n");
+						*/
+						DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Get MIC:%lX, %lX\n", *pdwMIC_L, *pdwMIC_R);
+					}
+					DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Middle frag len: %d\n", uTmpLen);
+					/*
+					  for (ii = 0; ii < uTmpLen; ii++) {
+					  DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%02x ", *((unsigned char *)((pbyBuffer + uLength) + ii)));
+					  }
+					  DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "\n\n");
+					*/
+
+				} else {
+					ASSERT(uTmpLen == (cbFragPayloadSize));
+				}
+
+				if ((pDevice->byLocalID <= REV_ID_VT3253_A1)) {
+					if (bNeedEncrypt) {
+						s_vSWencryption(pDevice, pTransmitKey, (pbyBuffer + uLength), (unsigned short)cbFragPayloadSize);
+						cbReqCount += cbICVlen;
+					}
+				}
+
+				ptdCurr = (PSTxDesc)pHeadTD;
+
+				//--------------------
+				//1.Set TSR1 & ReqCount in TxDescHead
+				//2.Set FragCtl in TxBufferHead
+				//3.Set Frame Control
+				//4.Set Sequence Control
+				//5.Get S/W generate FCS
+				//--------------------
+
+				s_vFillFragParameter(pDevice, pbyBuffer, uDMAIdx, (void *)ptdCurr, wFragType, cbReqCount);
+
+				ptdCurr->pTDInfo->dwReqCount = cbReqCount - uPadding;
+				ptdCurr->pTDInfo->dwHeaderLength = cbHeaderLength;
+				ptdCurr->pTDInfo->skb_dma = ptdCurr->pTDInfo->buf_dma;
+				ptdCurr->buff_addr = cpu_to_le32(ptdCurr->pTDInfo->skb_dma);
+				pDevice->iTDUsed[uDMAIdx]++;
+				pHeadTD = ptdCurr->next;
+			}
+		}  // for (uMACfragNum)
+	} else {
+		//=========================
+		//    No Fragmentation
+		//=========================
+		//DBG_PRTGRP03(("No Fragmentation...\n"));
+		//DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "No Fragmentation...\n");
+		wFragType = FRAGCTL_NONFRAG;
+
+		//Set FragCtl in TxBufferHead
+		psTxBufHd->wFragCtl |= (unsigned short)wFragType;
+
+		//Fill FIFO,RrvTime,RTS,and CTS
+		s_vGenerateTxParameter(pDevice, byPktType, (void *)psTxBufHd, pvRrvTime, pvRTS, pvCTS,
+				       cbFrameSize, bNeedACK, uDMAIdx, psEthHeader, pDevice->wCurrentRate);
+		//Fill DataHead
+		uDuration = s_uFillDataHead(pDevice, byPktType, pvTxDataHd, cbFrameSize, uDMAIdx, bNeedACK,
+					    0, 0, uMACfragNum, byFBOption, pDevice->wCurrentRate);
+
+		// Generate TX MAC Header
+		vGenerateMACHeader(pDevice, pbyMacHdr, (unsigned short)uDuration, psEthHeader, bNeedEncrypt,
+				   wFragType, uDMAIdx, 0);
+
+		if (bNeedEncrypt == true) {
+			//Fill TXKEY
+			s_vFillTxKey(pDevice, (unsigned char *)(psTxBufHd->adwTxKey), pbyIVHead, pTransmitKey,
+				     pbyMacHdr, (unsigned short)cbFrameBodySize, (unsigned char *)pMICHDR);
+
+			if (pDevice->bEnableHostWEP) {
+				pMgmt->sNodeDBTable[uNodeIndex].dwTSC47_16 = pTransmitKey->dwTSC47_16;
+				pMgmt->sNodeDBTable[uNodeIndex].wTSC15_0 = pTransmitKey->wTSC15_0;
+			}
+		}
+
+		// 802.1H
+		if (ntohs(psEthHeader->wType) > ETH_DATA_LEN) {
+			if ((psEthHeader->wType == TYPE_PKT_IPX) ||
+			    (psEthHeader->wType == cpu_to_le16(0xF380))) {
+				memcpy((unsigned char *)(pbyPayloadHead), &pDevice->abySNAP_Bridgetunnel[0], 6);
+			} else {
+				memcpy((unsigned char *)(pbyPayloadHead), &pDevice->abySNAP_RFC1042[0], 6);
+			}
+			pbyType = (unsigned char *)(pbyPayloadHead + 6);
+			memcpy(pbyType, &(psEthHeader->wType), sizeof(unsigned short));
+			cb802_1_H_len = 8;
+		}
+
+		cbReqCount = cbHeaderLength + cbMACHdLen + uPadding + cbIVlen + (cbFrameBodySize + cbMIClen);
+		//---------------------------
+		// S/W or H/W Encryption
+		//---------------------------
+		pbyBuffer = (unsigned char *)pHeadTD->pTDInfo->buf;
+		uLength = cbHeaderLength + cbMACHdLen + uPadding + cbIVlen + cb802_1_H_len;
+
+		//copy TxBufferHeader + MacHeader to desc
+		memcpy(pbyBuffer, (void *)psTxBufHd, uLength);
+
+		// Copy the Packet into a tx Buffer
+		memcpy((pbyBuffer + uLength),
+		       (pPacket + 14),
+		       cbFrameBodySize - cb802_1_H_len
+);
+
+		if ((bNeedEncrypt == true) && (pTransmitKey != NULL) && (pTransmitKey->byCipherSuite == KEY_CTL_TKIP)) {
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Length:%d, %d\n", cbFrameBodySize - cb802_1_H_len, uLength);
+			/*
+			  for (ii = 0; ii < (cbFrameBodySize - cb802_1_H_len); ii++) {
+			  DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%02x ", *((unsigned char *)((pbyBuffer + uLength) + ii)));
+			  }
+			  DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "\n");
+			*/
+
+			MIC_vAppend((pbyBuffer + uLength - cb802_1_H_len), cbFrameBodySize);
+
+			pdwMIC_L = (unsigned long *)(pbyBuffer + uLength - cb802_1_H_len + cbFrameBodySize);
+			pdwMIC_R = (unsigned long *)(pbyBuffer + uLength - cb802_1_H_len + cbFrameBodySize + 4);
+
+			MIC_vGetMIC(pdwMIC_L, pdwMIC_R);
+			MIC_vUnInit();
+
+			if (pDevice->bTxMICFail == true) {
+				*pdwMIC_L = 0;
+				*pdwMIC_R = 0;
+				pDevice->bTxMICFail = false;
+			}
+
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "uLength: %d, %d\n", uLength, cbFrameBodySize);
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "cbReqCount:%d, %d, %d, %d\n", cbReqCount, cbHeaderLength, uPadding, cbIVlen);
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "MIC:%lx, %lx\n", *pdwMIC_L, *pdwMIC_R);
 /*
-            for (ii = 0; ii < 8; ii++) {
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"%02x ", *(((unsigned char *)(pdwMIC_L) + ii)));
-            }
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n");
+  for (ii = 0; ii < 8; ii++) {
+  DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%02x ", *(((unsigned char *)(pdwMIC_L) + ii)));
+  }
+  DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "\n");
 */
 
-        }
-
-
-        if ((pDevice->byLocalID <= REV_ID_VT3253_A1)){
-            if (bNeedEncrypt) {
-                s_vSWencryption(pDevice, pTransmitKey, (pbyBuffer + uLength - cb802_1_H_len),
-                                (unsigned short)(cbFrameBodySize + cbMIClen));
-                cbReqCount += cbICVlen;
-            }
-        }
+		}
 
+		if ((pDevice->byLocalID <= REV_ID_VT3253_A1)) {
+			if (bNeedEncrypt) {
+				s_vSWencryption(pDevice, pTransmitKey, (pbyBuffer + uLength - cb802_1_H_len),
+						(unsigned short)(cbFrameBodySize + cbMIClen));
+				cbReqCount += cbICVlen;
+			}
+		}
 
-        ptdCurr = (PSTxDesc)pHeadTD;
+		ptdCurr = (PSTxDesc)pHeadTD;
 
-        ptdCurr->pTDInfo->dwReqCount = cbReqCount - uPadding;
-        ptdCurr->pTDInfo->dwHeaderLength = cbHeaderLength;
-        ptdCurr->pTDInfo->skb_dma = ptdCurr->pTDInfo->buf_dma;
-        ptdCurr->buff_addr = cpu_to_le32(ptdCurr->pTDInfo->skb_dma);
-  	    //Set TSR1 & ReqCount in TxDescHead
-        ptdCurr->m_td1TD1.byTCR |= (TCR_STP | TCR_EDP | EDMSDU);
-        ptdCurr->m_td1TD1.wReqCount = cpu_to_le16((unsigned short)(cbReqCount));
+		ptdCurr->pTDInfo->dwReqCount = cbReqCount - uPadding;
+		ptdCurr->pTDInfo->dwHeaderLength = cbHeaderLength;
+		ptdCurr->pTDInfo->skb_dma = ptdCurr->pTDInfo->buf_dma;
+		ptdCurr->buff_addr = cpu_to_le32(ptdCurr->pTDInfo->skb_dma);
+		//Set TSR1 & ReqCount in TxDescHead
+		ptdCurr->m_td1TD1.byTCR |= (TCR_STP | TCR_EDP | EDMSDU);
+		ptdCurr->m_td1TD1.wReqCount = cpu_to_le16((unsigned short)(cbReqCount));
 
-        pDevice->iTDUsed[uDMAIdx]++;
+		pDevice->iTDUsed[uDMAIdx]++;
 
+//   DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " ptdCurr->m_dwReserved0[%d] ptdCurr->m_dwReserved1[%d].\n", ptdCurr->pTDInfo->dwReqCount, ptdCurr->pTDInfo->dwHeaderLength);
+//   DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " cbHeaderLength[%d]\n", cbHeaderLength);
 
-//   DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" ptdCurr->m_dwReserved0[%d] ptdCurr->m_dwReserved1[%d].\n", ptdCurr->pTDInfo->dwReqCount, ptdCurr->pTDInfo->dwHeaderLength);
-//   DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" cbHeaderLength[%d]\n", cbHeaderLength);
-
-    }
-    *puMACfragNum = uMACfragNum;
-    //DBG_PRTGRP03(("s_cbFillTxBufHead END\n"));
-    return cbHeaderLength;
+	}
+	*puMACfragNum = uMACfragNum;
+	//DBG_PRTGRP03(("s_cbFillTxBufHead END\n"));
+	return cbHeaderLength;
 }
 
-
 void
 vGenerateFIFOHeader(PSDevice pDevice, unsigned char byPktType, unsigned char *pbyTxBufferAddr,
-	bool bNeedEncrypt, unsigned int cbPayloadSize, unsigned int uDMAIdx,
-	PSTxDesc pHeadTD, PSEthernetHeader psEthHeader, unsigned char *pPacket,
-	PSKeyItem pTransmitKey, unsigned int uNodeIndex, unsigned int *puMACfragNum,
-	unsigned int *pcbHeaderSize)
+		    bool bNeedEncrypt, unsigned int cbPayloadSize, unsigned int uDMAIdx,
+		    PSTxDesc pHeadTD, PSEthernetHeader psEthHeader, unsigned char *pPacket,
+		    PSKeyItem pTransmitKey, unsigned int uNodeIndex, unsigned int *puMACfragNum,
+		    unsigned int *pcbHeaderSize)
 {
-    unsigned int wTxBufSize;       // FFinfo size
-    bool bNeedACK;
-    bool bIsAdhoc;
-    unsigned short cbMacHdLen;
-    PSTxBufHead     pTxBufHead = (PSTxBufHead) pbyTxBufferAddr;
-
-    wTxBufSize = sizeof(STxBufHead);
-
-    memset(pTxBufHead, 0, wTxBufSize);
-    //Set FIFOCTL_NEEDACK
-
-    if ((pDevice->eOPMode == OP_MODE_ADHOC) ||
-        (pDevice->eOPMode == OP_MODE_AP)) {
-        if (is_multicast_ether_addr(&(psEthHeader->abyDstAddr[0]))) {
-            bNeedACK = false;
-            pTxBufHead->wFIFOCtl = pTxBufHead->wFIFOCtl & (~FIFOCTL_NEEDACK);
-        }
-        else {
-            bNeedACK = true;
-            pTxBufHead->wFIFOCtl |= FIFOCTL_NEEDACK;
-        }
-        bIsAdhoc = true;
-    }
-    else {
-        // MSDUs in Infra mode always need ACK
-        bNeedACK = true;
-        pTxBufHead->wFIFOCtl |= FIFOCTL_NEEDACK;
-        bIsAdhoc = false;
-    }
-
-
-    pTxBufHead->wFIFOCtl |= FIFOCTL_TMOEN;
-    pTxBufHead->wTimeStamp = cpu_to_le16(DEFAULT_MSDU_LIFETIME_RES_64us);
-
-    //Set FIFOCTL_LHEAD
-    if (pDevice->bLongHeader)
-        pTxBufHead->wFIFOCtl |= FIFOCTL_LHEAD;
-
-    //Set FIFOCTL_GENINT
-
-    pTxBufHead->wFIFOCtl |= FIFOCTL_GENINT;
-
-
-    //Set FIFOCTL_ISDMA0
-    if (TYPE_TXDMA0 == uDMAIdx) {
-        pTxBufHead->wFIFOCtl |= FIFOCTL_ISDMA0;
-    }
-
-    //Set FRAGCTL_MACHDCNT
-    if (pDevice->bLongHeader) {
-        cbMacHdLen = WLAN_HDR_ADDR3_LEN + 6;
-    } else {
-        cbMacHdLen = WLAN_HDR_ADDR3_LEN;
-    }
-    pTxBufHead->wFragCtl |= cpu_to_le16((unsigned short)(cbMacHdLen << 10));
-
-    //Set packet type
-    if (byPktType == PK_TYPE_11A) {//0000 0000 0000 0000
-        ;
-    }
-    else if (byPktType == PK_TYPE_11B) {//0000 0001 0000 0000
-        pTxBufHead->wFIFOCtl |= FIFOCTL_11B;
-    }
-    else if (byPktType == PK_TYPE_11GB) {//0000 0010 0000 0000
-        pTxBufHead->wFIFOCtl |= FIFOCTL_11GB;
-    }
-    else if (byPktType == PK_TYPE_11GA) {//0000 0011 0000 0000
-        pTxBufHead->wFIFOCtl |= FIFOCTL_11GA;
-    }
-    //Set FIFOCTL_GrpAckPolicy
-    if (pDevice->bGrpAckPolicy == true) {//0000 0100 0000 0000
-        pTxBufHead->wFIFOCtl |=	FIFOCTL_GRPACK;
-    }
-
-    //Set Auto Fallback Ctl
-    if (pDevice->wCurrentRate >= RATE_18M) {
-        if (pDevice->byAutoFBCtrl == AUTO_FB_0) {
-            pTxBufHead->wFIFOCtl |= FIFOCTL_AUTO_FB_0;
-        } else if (pDevice->byAutoFBCtrl == AUTO_FB_1) {
-            pTxBufHead->wFIFOCtl |= FIFOCTL_AUTO_FB_1;
-        }
-    }
-
-    //Set FRAGCTL_WEPTYP
-    pDevice->bAES = false;
-
-    //Set FRAGCTL_WEPTYP
-    if (pDevice->byLocalID > REV_ID_VT3253_A1) {
-        if ((bNeedEncrypt) && (pTransmitKey != NULL))  { //WEP enabled
-            if (pTransmitKey->byCipherSuite == KEY_CTL_TKIP) {
-                pTxBufHead->wFragCtl |= FRAGCTL_TKIP;
-            }
-            else if (pTransmitKey->byCipherSuite == KEY_CTL_WEP) { //WEP40 or WEP104
-                if (pTransmitKey->uKeyLength != WLAN_WEP232_KEYLEN)
-                    pTxBufHead->wFragCtl |= FRAGCTL_LEGACY;
-            }
-            else if (pTransmitKey->byCipherSuite == KEY_CTL_CCMP) { //CCMP
-                pTxBufHead->wFragCtl |= FRAGCTL_AES;
-            }
-        }
-    }
+	unsigned int wTxBufSize;       // FFinfo size
+	bool bNeedACK;
+	bool bIsAdhoc;
+	unsigned short cbMacHdLen;
+	PSTxBufHead     pTxBufHead = (PSTxBufHead) pbyTxBufferAddr;
+
+	wTxBufSize = sizeof(STxBufHead);
+
+	memset(pTxBufHead, 0, wTxBufSize);
+	//Set FIFOCTL_NEEDACK
+
+	if ((pDevice->eOPMode == OP_MODE_ADHOC) ||
+	    (pDevice->eOPMode == OP_MODE_AP)) {
+		if (is_multicast_ether_addr(&(psEthHeader->abyDstAddr[0]))) {
+			bNeedACK = false;
+			pTxBufHead->wFIFOCtl = pTxBufHead->wFIFOCtl & (~FIFOCTL_NEEDACK);
+		} else {
+			bNeedACK = true;
+			pTxBufHead->wFIFOCtl |= FIFOCTL_NEEDACK;
+		}
+		bIsAdhoc = true;
+	} else {
+		// MSDUs in Infra mode always need ACK
+		bNeedACK = true;
+		pTxBufHead->wFIFOCtl |= FIFOCTL_NEEDACK;
+		bIsAdhoc = false;
+	}
+
+	pTxBufHead->wFIFOCtl |= FIFOCTL_TMOEN;
+	pTxBufHead->wTimeStamp = cpu_to_le16(DEFAULT_MSDU_LIFETIME_RES_64us);
+
+	//Set FIFOCTL_LHEAD
+	if (pDevice->bLongHeader)
+		pTxBufHead->wFIFOCtl |= FIFOCTL_LHEAD;
+
+	//Set FIFOCTL_GENINT
+
+	pTxBufHead->wFIFOCtl |= FIFOCTL_GENINT;
+
+	//Set FIFOCTL_ISDMA0
+	if (TYPE_TXDMA0 == uDMAIdx) {
+		pTxBufHead->wFIFOCtl |= FIFOCTL_ISDMA0;
+	}
+
+	//Set FRAGCTL_MACHDCNT
+	if (pDevice->bLongHeader) {
+		cbMacHdLen = WLAN_HDR_ADDR3_LEN + 6;
+	} else {
+		cbMacHdLen = WLAN_HDR_ADDR3_LEN;
+	}
+	pTxBufHead->wFragCtl |= cpu_to_le16((unsigned short)(cbMacHdLen << 10));
+
+	//Set packet type
+	if (byPktType == PK_TYPE_11A) {//0000 0000 0000 0000
+		;
+	} else if (byPktType == PK_TYPE_11B) {//0000 0001 0000 0000
+		pTxBufHead->wFIFOCtl |= FIFOCTL_11B;
+	} else if (byPktType == PK_TYPE_11GB) {//0000 0010 0000 0000
+		pTxBufHead->wFIFOCtl |= FIFOCTL_11GB;
+	} else if (byPktType == PK_TYPE_11GA) {//0000 0011 0000 0000
+		pTxBufHead->wFIFOCtl |= FIFOCTL_11GA;
+	}
+	//Set FIFOCTL_GrpAckPolicy
+	if (pDevice->bGrpAckPolicy == true) {//0000 0100 0000 0000
+		pTxBufHead->wFIFOCtl |=	FIFOCTL_GRPACK;
+	}
+
+	//Set Auto Fallback Ctl
+	if (pDevice->wCurrentRate >= RATE_18M) {
+		if (pDevice->byAutoFBCtrl == AUTO_FB_0) {
+			pTxBufHead->wFIFOCtl |= FIFOCTL_AUTO_FB_0;
+		} else if (pDevice->byAutoFBCtrl == AUTO_FB_1) {
+			pTxBufHead->wFIFOCtl |= FIFOCTL_AUTO_FB_1;
+		}
+	}
+
+	//Set FRAGCTL_WEPTYP
+	pDevice->bAES = false;
+
+	//Set FRAGCTL_WEPTYP
+	if (pDevice->byLocalID > REV_ID_VT3253_A1) {
+		if ((bNeedEncrypt) && (pTransmitKey != NULL))  { //WEP enabled
+			if (pTransmitKey->byCipherSuite == KEY_CTL_TKIP) {
+				pTxBufHead->wFragCtl |= FRAGCTL_TKIP;
+			} else if (pTransmitKey->byCipherSuite == KEY_CTL_WEP) { //WEP40 or WEP104
+				if (pTransmitKey->uKeyLength != WLAN_WEP232_KEYLEN)
+					pTxBufHead->wFragCtl |= FRAGCTL_LEGACY;
+			} else if (pTransmitKey->byCipherSuite == KEY_CTL_CCMP) { //CCMP
+				pTxBufHead->wFragCtl |= FRAGCTL_AES;
+			}
+		}
+	}
 
 #ifdef	PLICE_DEBUG
-	//printk("Func:vGenerateFIFOHeader:TxDataRate is %d,TxPower is %d\n",pDevice->wCurrentRate,pDevice->byCurPwr);
-
-	//if (pDevice->wCurrentRate <= 3)
-	//{
-	//	RFbRawSetPower(pDevice,36,pDevice->wCurrentRate);
-	//}
-	//else
-
 	RFbSetPower(pDevice, pDevice->wCurrentRate, pDevice->byCurrentCh);
 #endif
-		//if (pDevice->wCurrentRate == 3)
-		//pDevice->byCurPwr = 46;
-		pTxBufHead->byTxPower = pDevice->byCurPwr;
-
-
-
+	pTxBufHead->byTxPower = pDevice->byCurPwr;
 
 /*
-    if(pDevice->bEnableHostWEP)
-        pTxBufHead->wFragCtl &=  ~(FRAGCTL_TKIP | FRAGCTL_LEGACY |FRAGCTL_AES);
+  if (pDevice->bEnableHostWEP)
+  pTxBufHead->wFragCtl &=  ~(FRAGCTL_TKIP | FRAGCTL_LEGACY |FRAGCTL_AES);
 */
-    *pcbHeaderSize = s_cbFillTxBufHead(pDevice, byPktType, pbyTxBufferAddr, cbPayloadSize,
-                                   uDMAIdx, pHeadTD, psEthHeader, pPacket, bNeedEncrypt,
-                                   pTransmitKey, uNodeIndex, puMACfragNum);
+	*pcbHeaderSize = s_cbFillTxBufHead(pDevice, byPktType, pbyTxBufferAddr, cbPayloadSize,
+					   uDMAIdx, pHeadTD, psEthHeader, pPacket, bNeedEncrypt,
+					   pTransmitKey, uNodeIndex, puMACfragNum);
 
-    return;
+	return;
 }
 
-
-
-
 /*+
  *
  * Description:
@@ -2226,964 +2059,882 @@ vGenerateFIFOHeader(PSDevice pDevice, unsigned char byPktType, unsigned char *pb
  *
  * Return Value: none
  *
--*/
+ -*/
 
 void
-vGenerateMACHeader (
-    PSDevice         pDevice,
-    unsigned char *pbyBufferAddr,
-    unsigned short wDuration,
-    PSEthernetHeader psEthHeader,
-    bool bNeedEncrypt,
-    unsigned short wFragType,
-    unsigned int uDMAIdx,
-    unsigned int uFragIdx
-    )
+vGenerateMACHeader(
+	PSDevice         pDevice,
+	unsigned char *pbyBufferAddr,
+	unsigned short wDuration,
+	PSEthernetHeader psEthHeader,
+	bool bNeedEncrypt,
+	unsigned short wFragType,
+	unsigned int uDMAIdx,
+	unsigned int uFragIdx
+)
 {
-    PS802_11Header  pMACHeader = (PS802_11Header)pbyBufferAddr;
-
-    memset(pMACHeader, 0, (sizeof(S802_11Header)));  //- sizeof(pMACHeader->dwIV)));
-
-    if (uDMAIdx == TYPE_ATIMDMA) {
-    	pMACHeader->wFrameCtl = TYPE_802_11_ATIM;
-    } else {
-        pMACHeader->wFrameCtl = TYPE_802_11_DATA;
-    }
-
-    if (pDevice->eOPMode == OP_MODE_AP) {
-        memcpy(&(pMACHeader->abyAddr1[0]), &(psEthHeader->abyDstAddr[0]), ETH_ALEN);
-        memcpy(&(pMACHeader->abyAddr2[0]), &(pDevice->abyBSSID[0]), ETH_ALEN);
-        memcpy(&(pMACHeader->abyAddr3[0]), &(psEthHeader->abySrcAddr[0]), ETH_ALEN);
-        pMACHeader->wFrameCtl |= FC_FROMDS;
-    }
-    else {
-        if (pDevice->eOPMode == OP_MODE_ADHOC) {
-            memcpy(&(pMACHeader->abyAddr1[0]), &(psEthHeader->abyDstAddr[0]), ETH_ALEN);
-            memcpy(&(pMACHeader->abyAddr2[0]), &(psEthHeader->abySrcAddr[0]), ETH_ALEN);
-            memcpy(&(pMACHeader->abyAddr3[0]), &(pDevice->abyBSSID[0]), ETH_ALEN);
-        }
-        else {
-            memcpy(&(pMACHeader->abyAddr3[0]), &(psEthHeader->abyDstAddr[0]), ETH_ALEN);
-            memcpy(&(pMACHeader->abyAddr2[0]), &(psEthHeader->abySrcAddr[0]), ETH_ALEN);
-            memcpy(&(pMACHeader->abyAddr1[0]), &(pDevice->abyBSSID[0]), ETH_ALEN);
-            pMACHeader->wFrameCtl |= FC_TODS;
-        }
-    }
-
-    if (bNeedEncrypt)
-        pMACHeader->wFrameCtl |= cpu_to_le16((unsigned short)WLAN_SET_FC_ISWEP(1));
-
-    pMACHeader->wDurationID = cpu_to_le16(wDuration);
-
-    if (pDevice->bLongHeader) {
-        PWLAN_80211HDR_A4 pMACA4Header  = (PWLAN_80211HDR_A4) pbyBufferAddr;
-        pMACHeader->wFrameCtl |= (FC_TODS | FC_FROMDS);
-        memcpy(pMACA4Header->abyAddr4, pDevice->abyBSSID, WLAN_ADDR_LEN);
-    }
-    pMACHeader->wSeqCtl = cpu_to_le16(pDevice->wSeqCounter << 4);
-
-    //Set FragNumber in Sequence Control
-    pMACHeader->wSeqCtl |= cpu_to_le16((unsigned short)uFragIdx);
-
-    if ((wFragType == FRAGCTL_ENDFRAG) || (wFragType == FRAGCTL_NONFRAG)) {
-        pDevice->wSeqCounter++;
-        if (pDevice->wSeqCounter > 0x0fff)
-            pDevice->wSeqCounter = 0;
-    }
-
-    if ((wFragType == FRAGCTL_STAFRAG) || (wFragType == FRAGCTL_MIDFRAG)) { //StartFrag or MidFrag
-        pMACHeader->wFrameCtl |= FC_MOREFRAG;
-    }
+	PS802_11Header  pMACHeader = (PS802_11Header)pbyBufferAddr;
+
+	memset(pMACHeader, 0, (sizeof(S802_11Header)));  //- sizeof(pMACHeader->dwIV)));
+
+	if (uDMAIdx == TYPE_ATIMDMA) {
+		pMACHeader->wFrameCtl = TYPE_802_11_ATIM;
+	} else {
+		pMACHeader->wFrameCtl = TYPE_802_11_DATA;
+	}
+
+	if (pDevice->eOPMode == OP_MODE_AP) {
+		memcpy(&(pMACHeader->abyAddr1[0]), &(psEthHeader->abyDstAddr[0]), ETH_ALEN);
+		memcpy(&(pMACHeader->abyAddr2[0]), &(pDevice->abyBSSID[0]), ETH_ALEN);
+		memcpy(&(pMACHeader->abyAddr3[0]), &(psEthHeader->abySrcAddr[0]), ETH_ALEN);
+		pMACHeader->wFrameCtl |= FC_FROMDS;
+	} else {
+		if (pDevice->eOPMode == OP_MODE_ADHOC) {
+			memcpy(&(pMACHeader->abyAddr1[0]), &(psEthHeader->abyDstAddr[0]), ETH_ALEN);
+			memcpy(&(pMACHeader->abyAddr2[0]), &(psEthHeader->abySrcAddr[0]), ETH_ALEN);
+			memcpy(&(pMACHeader->abyAddr3[0]), &(pDevice->abyBSSID[0]), ETH_ALEN);
+		} else {
+			memcpy(&(pMACHeader->abyAddr3[0]), &(psEthHeader->abyDstAddr[0]), ETH_ALEN);
+			memcpy(&(pMACHeader->abyAddr2[0]), &(psEthHeader->abySrcAddr[0]), ETH_ALEN);
+			memcpy(&(pMACHeader->abyAddr1[0]), &(pDevice->abyBSSID[0]), ETH_ALEN);
+			pMACHeader->wFrameCtl |= FC_TODS;
+		}
+	}
+
+	if (bNeedEncrypt)
+		pMACHeader->wFrameCtl |= cpu_to_le16((unsigned short)WLAN_SET_FC_ISWEP(1));
+
+	pMACHeader->wDurationID = cpu_to_le16(wDuration);
+
+	if (pDevice->bLongHeader) {
+		PWLAN_80211HDR_A4 pMACA4Header  = (PWLAN_80211HDR_A4) pbyBufferAddr;
+		pMACHeader->wFrameCtl |= (FC_TODS | FC_FROMDS);
+		memcpy(pMACA4Header->abyAddr4, pDevice->abyBSSID, WLAN_ADDR_LEN);
+	}
+	pMACHeader->wSeqCtl = cpu_to_le16(pDevice->wSeqCounter << 4);
+
+	//Set FragNumber in Sequence Control
+	pMACHeader->wSeqCtl |= cpu_to_le16((unsigned short)uFragIdx);
+
+	if ((wFragType == FRAGCTL_ENDFRAG) || (wFragType == FRAGCTL_NONFRAG)) {
+		pDevice->wSeqCounter++;
+		if (pDevice->wSeqCounter > 0x0fff)
+			pDevice->wSeqCounter = 0;
+	}
+
+	if ((wFragType == FRAGCTL_STAFRAG) || (wFragType == FRAGCTL_MIDFRAG)) { //StartFrag or MidFrag
+		pMACHeader->wFrameCtl |= FC_MOREFRAG;
+	}
 }
 
-
-
-
-
-
 CMD_STATUS csMgmt_xmit(PSDevice pDevice, PSTxMgmtPacket pPacket) {
-
-    PSTxDesc        pFrstTD;
-    unsigned char byPktType;
-    unsigned char *pbyTxBufferAddr;
-    void *          pvRTS;
-    PSCTS           pCTS;
-    void *          pvTxDataHd;
-    unsigned int uDuration;
-    unsigned int cbReqCount;
-    PS802_11Header  pMACHeader;
-    unsigned int cbHeaderSize;
-    unsigned int cbFrameBodySize;
-    bool bNeedACK;
-    bool bIsPSPOLL = false;
-    PSTxBufHead     pTxBufHead;
-    unsigned int cbFrameSize;
-    unsigned int cbIVlen = 0;
-    unsigned int cbICVlen = 0;
-    unsigned int cbMIClen = 0;
-    unsigned int cbFCSlen = 4;
-    unsigned int uPadding = 0;
-    unsigned short wTxBufSize;
-    unsigned int cbMacHdLen;
-    SEthernetHeader sEthHeader;
-    void *          pvRrvTime;
-    void *          pMICHDR;
-    PSMgmtObject    pMgmt = pDevice->pMgmt;
-    unsigned short wCurrentRate = RATE_1M;
-
-
-    if (AVAIL_TD(pDevice, TYPE_TXDMA0) <= 0) {
-        return CMD_STATUS_RESOURCES;
-    }
-
-    pFrstTD = pDevice->apCurrTD[TYPE_TXDMA0];
-    pbyTxBufferAddr = (unsigned char *)pFrstTD->pTDInfo->buf;
-    cbFrameBodySize = pPacket->cbPayloadLen;
-    pTxBufHead = (PSTxBufHead) pbyTxBufferAddr;
-    wTxBufSize = sizeof(STxBufHead);
-    memset(pTxBufHead, 0, wTxBufSize);
-
-    if (pDevice->eCurrentPHYType == PHY_TYPE_11A) {
-        wCurrentRate = RATE_6M;
-        byPktType = PK_TYPE_11A;
-    } else {
-        wCurrentRate = RATE_1M;
-        byPktType = PK_TYPE_11B;
-    }
-
-    // SetPower will cause error power TX state for OFDM Date packet in TX buffer.
-    // 2004.11.11 Kyle -- Using OFDM power to tx MngPkt will decrease the connection capability.
-    //                    And cmd timer will wait data pkt TX finish before scanning so it's OK
-    //                    to set power here.
-    if (pDevice->pMgmt->eScanState != WMAC_NO_SCANNING) {
-
+	PSTxDesc        pFrstTD;
+	unsigned char byPktType;
+	unsigned char *pbyTxBufferAddr;
+	void *pvRTS;
+	PSCTS           pCTS;
+	void *pvTxDataHd;
+	unsigned int uDuration;
+	unsigned int cbReqCount;
+	PS802_11Header  pMACHeader;
+	unsigned int cbHeaderSize;
+	unsigned int cbFrameBodySize;
+	bool bNeedACK;
+	bool bIsPSPOLL = false;
+	PSTxBufHead     pTxBufHead;
+	unsigned int cbFrameSize;
+	unsigned int cbIVlen = 0;
+	unsigned int cbICVlen = 0;
+	unsigned int cbMIClen = 0;
+	unsigned int cbFCSlen = 4;
+	unsigned int uPadding = 0;
+	unsigned short wTxBufSize;
+	unsigned int cbMacHdLen;
+	SEthernetHeader sEthHeader;
+	void *pvRrvTime;
+	void *pMICHDR;
+	PSMgmtObject    pMgmt = pDevice->pMgmt;
+	unsigned short wCurrentRate = RATE_1M;
+
+	if (AVAIL_TD(pDevice, TYPE_TXDMA0) <= 0) {
+		return CMD_STATUS_RESOURCES;
+	}
+
+	pFrstTD = pDevice->apCurrTD[TYPE_TXDMA0];
+	pbyTxBufferAddr = (unsigned char *)pFrstTD->pTDInfo->buf;
+	cbFrameBodySize = pPacket->cbPayloadLen;
+	pTxBufHead = (PSTxBufHead) pbyTxBufferAddr;
+	wTxBufSize = sizeof(STxBufHead);
+	memset(pTxBufHead, 0, wTxBufSize);
+
+	if (pDevice->eCurrentPHYType == PHY_TYPE_11A) {
+		wCurrentRate = RATE_6M;
+		byPktType = PK_TYPE_11A;
+	} else {
+		wCurrentRate = RATE_1M;
+		byPktType = PK_TYPE_11B;
+	}
+
+	// SetPower will cause error power TX state for OFDM Date packet in TX buffer.
+	// 2004.11.11 Kyle -- Using OFDM power to tx MngPkt will decrease the connection capability.
+	//                    And cmd timer will wait data pkt TX finish before scanning so it's OK
+	//                    to set power here.
+	if (pDevice->pMgmt->eScanState != WMAC_NO_SCANNING) {
 		RFbSetPower(pDevice, wCurrentRate, pDevice->byCurrentCh);
-    } else {
-        RFbSetPower(pDevice, wCurrentRate, pMgmt->uCurrChannel);
-    }
-    pTxBufHead->byTxPower = pDevice->byCurPwr;
-    //+++++++++++++++++++++ Patch VT3253 A1 performance +++++++++++++++++++++++++++
-    if (pDevice->byFOETuning) {
-        if ((pPacket->p80211Header->sA3.wFrameCtl & TYPE_DATE_NULL) == TYPE_DATE_NULL) {
-            wCurrentRate = RATE_24M;
-            byPktType = PK_TYPE_11GA;
-        }
-    }
-
-    //Set packet type
-    if (byPktType == PK_TYPE_11A) {//0000 0000 0000 0000
-        pTxBufHead->wFIFOCtl = 0;
-    }
-    else if (byPktType == PK_TYPE_11B) {//0000 0001 0000 0000
-        pTxBufHead->wFIFOCtl |= FIFOCTL_11B;
-    }
-    else if (byPktType == PK_TYPE_11GB) {//0000 0010 0000 0000
-        pTxBufHead->wFIFOCtl |= FIFOCTL_11GB;
-    }
-    else if (byPktType == PK_TYPE_11GA) {//0000 0011 0000 0000
-        pTxBufHead->wFIFOCtl |= FIFOCTL_11GA;
-    }
-
-    pTxBufHead->wFIFOCtl |= FIFOCTL_TMOEN;
-    pTxBufHead->wTimeStamp = cpu_to_le16(DEFAULT_MGN_LIFETIME_RES_64us);
-
-
-    if (is_multicast_ether_addr(&(pPacket->p80211Header->sA3.abyAddr1[0])))
-        bNeedACK = false;
-    else {
-        bNeedACK = true;
-        pTxBufHead->wFIFOCtl |= FIFOCTL_NEEDACK;
-    };
-
-    if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) ||
-        (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) ) {
-
-        pTxBufHead->wFIFOCtl |= FIFOCTL_LRETRY;
-        //Set Preamble type always long
-        //pDevice->byPreambleType = PREAMBLE_LONG;
-        // probe-response don't retry
-        //if ((pPacket->p80211Header->sA4.wFrameCtl & TYPE_SUBTYPE_MASK) == TYPE_MGMT_PROBE_RSP) {
-        //     bNeedACK = false;
-        //     pTxBufHead->wFIFOCtl  &= (~FIFOCTL_NEEDACK);
-        //}
-    }
-
-    pTxBufHead->wFIFOCtl |= (FIFOCTL_GENINT | FIFOCTL_ISDMA0);
-
-    if ((pPacket->p80211Header->sA4.wFrameCtl & TYPE_SUBTYPE_MASK) == TYPE_CTL_PSPOLL) {
-        bIsPSPOLL = true;
-        cbMacHdLen = WLAN_HDR_ADDR2_LEN;
-    } else {
-        cbMacHdLen = WLAN_HDR_ADDR3_LEN;
-    }
-
-    //Set FRAGCTL_MACHDCNT
-    pTxBufHead->wFragCtl |= cpu_to_le16((unsigned short)(cbMacHdLen << 10));
-
-    // Notes:
-    // Although spec says MMPDU can be fragmented; In most cases,
-    // no one will send a MMPDU under fragmentation. With RTS may occur.
-    pDevice->bAES = false;  //Set FRAGCTL_WEPTYP
-
-    if (WLAN_GET_FC_ISWEP(pPacket->p80211Header->sA4.wFrameCtl) != 0) {
-        if (pDevice->eEncryptionStatus == Ndis802_11Encryption1Enabled) {
-            cbIVlen = 4;
-            cbICVlen = 4;
-    	    pTxBufHead->wFragCtl |= FRAGCTL_LEGACY;
-        }
-        else if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) {
-            cbIVlen = 8;//IV+ExtIV
-            cbMIClen = 8;
-            cbICVlen = 4;
-    	    pTxBufHead->wFragCtl |= FRAGCTL_TKIP;
-    	    //We need to get seed here for filling TxKey entry.
-            //TKIPvMixKey(pTransmitKey->abyKey, pDevice->abyCurrentNetAddr,
-            //            pTransmitKey->wTSC15_0, pTransmitKey->dwTSC47_16, pDevice->abyPRNG);
-        }
-        else if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) {
-            cbIVlen = 8;//RSN Header
-            cbICVlen = 8;//MIC
-            pTxBufHead->wFragCtl |= FRAGCTL_AES;
-            pDevice->bAES = true;
-        }
-        //MAC Header should be padding 0 to DW alignment.
-        uPadding = 4 - (cbMacHdLen%4);
-        uPadding %= 4;
-    }
-
-    cbFrameSize = cbMacHdLen + cbFrameBodySize + cbIVlen + cbMIClen + cbICVlen + cbFCSlen;
-
-    //Set FIFOCTL_GrpAckPolicy
-    if (pDevice->bGrpAckPolicy == true) {//0000 0100 0000 0000
-        pTxBufHead->wFIFOCtl |=	FIFOCTL_GRPACK;
-    }
-    //the rest of pTxBufHead->wFragCtl:FragTyp will be set later in s_vFillFragParameter()
-
-    //Set RrvTime/RTS/CTS Buffer
-    if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {//802.11g packet
-
-        pvRrvTime = (PSRrvTime_gCTS) (pbyTxBufferAddr + wTxBufSize);
-        pMICHDR = NULL;
-        pvRTS = NULL;
-        pCTS = (PSCTS) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gCTS));
-        pvTxDataHd = (PSTxDataHead_g) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gCTS) + sizeof(SCTS));
-        cbHeaderSize = wTxBufSize + sizeof(SRrvTime_gCTS) + sizeof(SCTS) + sizeof(STxDataHead_g);
-    }
-    else { // 802.11a/b packet
-        pvRrvTime = (PSRrvTime_ab) (pbyTxBufferAddr + wTxBufSize);
-        pMICHDR = NULL;
-        pvRTS = NULL;
-        pCTS = NULL;
-        pvTxDataHd = (PSTxDataHead_ab) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_ab));
-        cbHeaderSize = wTxBufSize + sizeof(SRrvTime_ab) + sizeof(STxDataHead_ab);
-    }
-
-    memset((void *)(pbyTxBufferAddr + wTxBufSize), 0, (cbHeaderSize - wTxBufSize));
-
-    memcpy(&(sEthHeader.abyDstAddr[0]), &(pPacket->p80211Header->sA3.abyAddr1[0]), ETH_ALEN);
-    memcpy(&(sEthHeader.abySrcAddr[0]), &(pPacket->p80211Header->sA3.abyAddr2[0]), ETH_ALEN);
-    //=========================
-    //    No Fragmentation
-    //=========================
-    pTxBufHead->wFragCtl |= (unsigned short)FRAGCTL_NONFRAG;
-
-
-    //Fill FIFO,RrvTime,RTS,and CTS
-    s_vGenerateTxParameter(pDevice, byPktType, pbyTxBufferAddr, pvRrvTime, pvRTS, pCTS,
-                           cbFrameSize, bNeedACK, TYPE_TXDMA0, &sEthHeader, wCurrentRate);
-
-    //Fill DataHead
-    uDuration = s_uFillDataHead(pDevice, byPktType, pvTxDataHd, cbFrameSize, TYPE_TXDMA0, bNeedACK,
-                                0, 0, 1, AUTO_FB_NONE, wCurrentRate);
-
-    pMACHeader = (PS802_11Header) (pbyTxBufferAddr + cbHeaderSize);
-
-    cbReqCount = cbHeaderSize + cbMacHdLen + uPadding + cbIVlen + cbFrameBodySize;
-
-    if (WLAN_GET_FC_ISWEP(pPacket->p80211Header->sA4.wFrameCtl) != 0) {
-        unsigned char *pbyIVHead;
-        unsigned char *pbyPayloadHead;
-        unsigned char *pbyBSSID;
-        PSKeyItem       pTransmitKey = NULL;
-
-        pbyIVHead = (unsigned char *)(pbyTxBufferAddr + cbHeaderSize + cbMacHdLen + uPadding);
-        pbyPayloadHead = (unsigned char *)(pbyTxBufferAddr + cbHeaderSize + cbMacHdLen + uPadding + cbIVlen);
-
-        //Fill TXKEY
-        //Kyle: Need fix: TKIP and AES did't encrypt Mnt Packet.
-        //s_vFillTxKey(pDevice, (unsigned char *)pTxBufHead->adwTxKey, NULL);
-
-        //Fill IV(ExtIV,RSNHDR)
-        //s_vFillPrePayload(pDevice, pbyIVHead, NULL);
-        //---------------------------
-        // S/W or H/W Encryption
-        //---------------------------
-        //Fill MICHDR
-        //if (pDevice->bAES) {
-        //    s_vFillMICHDR(pDevice, (unsigned char *)pMICHDR, (unsigned char *)pMACHeader, (unsigned short)cbFrameBodySize);
-        //}
-        do {
-            if ((pDevice->eOPMode == OP_MODE_INFRASTRUCTURE) &&
-                (pDevice->bLinkPass == true)) {
-                pbyBSSID = pDevice->abyBSSID;
-                // get pairwise key
-                if (KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, PAIRWISE_KEY, &pTransmitKey) == false) {
-                    // get group key
-                    if(KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, GROUP_KEY, &pTransmitKey) == true) {
-                        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Get GTK.\n");
-                        break;
-                    }
-                } else {
-                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Get PTK.\n");
-                    break;
-                }
-            }
-            // get group key
-            pbyBSSID = pDevice->abyBroadcastAddr;
-            if(KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, GROUP_KEY, &pTransmitKey) == false) {
-                pTransmitKey = NULL;
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"KEY is NULL. OP Mode[%d]\n", pDevice->eOPMode);
-            } else {
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Get GTK.\n");
-            }
-        } while(false);
-        //Fill TXKEY
-        s_vFillTxKey(pDevice, (unsigned char *)(pTxBufHead->adwTxKey), pbyIVHead, pTransmitKey,
-                     (unsigned char *)pMACHeader, (unsigned short)cbFrameBodySize, NULL);
-
-        memcpy(pMACHeader, pPacket->p80211Header, cbMacHdLen);
-        memcpy(pbyPayloadHead, ((unsigned char *)(pPacket->p80211Header) + cbMacHdLen),
-                 cbFrameBodySize);
-    }
-    else {
-        // Copy the Packet into a tx Buffer
-        memcpy(pMACHeader, pPacket->p80211Header, pPacket->cbMPDULen);
-    }
-
-    pMACHeader->wSeqCtl = cpu_to_le16(pDevice->wSeqCounter << 4);
-    pDevice->wSeqCounter++ ;
-    if (pDevice->wSeqCounter > 0x0fff)
-        pDevice->wSeqCounter = 0;
-
-    if (bIsPSPOLL) {
-        // The MAC will automatically replace the Duration-field of MAC header by Duration-field
-        // of  FIFO control header.
-        // This will cause AID-field of PS-POLL packet to be incorrect (Because PS-POLL's AID field is
-        // in the same place of other packet's Duration-field).
-        // And it will cause Cisco-AP to issue Disassociation-packet
-        if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {
-            ((PSTxDataHead_g)pvTxDataHd)->wDuration_a = cpu_to_le16(pPacket->p80211Header->sA2.wDurationID);
-            ((PSTxDataHead_g)pvTxDataHd)->wDuration_b = cpu_to_le16(pPacket->p80211Header->sA2.wDurationID);
-        } else {
-            ((PSTxDataHead_ab)pvTxDataHd)->wDuration = cpu_to_le16(pPacket->p80211Header->sA2.wDurationID);
-        }
-    }
-
-
-    // first TD is the only TD
-    //Set TSR1 & ReqCount in TxDescHead
-    pFrstTD->m_td1TD1.byTCR = (TCR_STP | TCR_EDP | EDMSDU);
-    pFrstTD->pTDInfo->skb_dma = pFrstTD->pTDInfo->buf_dma;
-    pFrstTD->m_td1TD1.wReqCount = cpu_to_le16((unsigned short)(cbReqCount));
-    pFrstTD->buff_addr = cpu_to_le32(pFrstTD->pTDInfo->skb_dma);
-    pFrstTD->pTDInfo->byFlags = 0;
-
-    if (MACbIsRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_PS)) {
-        // Disable PS
-        MACbPSWakeup(pDevice->PortOffset);
-    }
-    pDevice->bPWBitOn = false;
-
-    wmb();
-    pFrstTD->m_td0TD0.f1Owner = OWNED_BY_NIC;
-    wmb();
-
-    pDevice->iTDUsed[TYPE_TXDMA0]++;
-
-    if (AVAIL_TD(pDevice, TYPE_TXDMA0) <= 1) {
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " available td0 <= 1\n");
-    }
-
-    pDevice->apCurrTD[TYPE_TXDMA0] = pFrstTD->next;
-#ifdef	PLICE_DEBUG
-		//printk("SCAN:CurrentRate is  %d,TxPower is %d\n",wCurrentRate,pTxBufHead->byTxPower);
-#endif
+	} else {
+		RFbSetPower(pDevice, wCurrentRate, pMgmt->uCurrChannel);
+	}
+	pTxBufHead->byTxPower = pDevice->byCurPwr;
+	//+++++++++++++++++++++ Patch VT3253 A1 performance +++++++++++++++++++++++++++
+	if (pDevice->byFOETuning) {
+		if ((pPacket->p80211Header->sA3.wFrameCtl & TYPE_DATE_NULL) == TYPE_DATE_NULL) {
+			wCurrentRate = RATE_24M;
+			byPktType = PK_TYPE_11GA;
+		}
+	}
+
+	//Set packet type
+	if (byPktType == PK_TYPE_11A) {//0000 0000 0000 0000
+		pTxBufHead->wFIFOCtl = 0;
+	} else if (byPktType == PK_TYPE_11B) {//0000 0001 0000 0000
+		pTxBufHead->wFIFOCtl |= FIFOCTL_11B;
+	} else if (byPktType == PK_TYPE_11GB) {//0000 0010 0000 0000
+		pTxBufHead->wFIFOCtl |= FIFOCTL_11GB;
+	} else if (byPktType == PK_TYPE_11GA) {//0000 0011 0000 0000
+		pTxBufHead->wFIFOCtl |= FIFOCTL_11GA;
+	}
+
+	pTxBufHead->wFIFOCtl |= FIFOCTL_TMOEN;
+	pTxBufHead->wTimeStamp = cpu_to_le16(DEFAULT_MGN_LIFETIME_RES_64us);
+
+	if (is_multicast_ether_addr(&(pPacket->p80211Header->sA3.abyAddr1[0])))
+		bNeedACK = false;
+	else {
+		bNeedACK = true;
+		pTxBufHead->wFIFOCtl |= FIFOCTL_NEEDACK;
+	};
+
+	if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) ||
+	    (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA)) {
+		pTxBufHead->wFIFOCtl |= FIFOCTL_LRETRY;
+	}
+
+	pTxBufHead->wFIFOCtl |= (FIFOCTL_GENINT | FIFOCTL_ISDMA0);
+
+	if ((pPacket->p80211Header->sA4.wFrameCtl & TYPE_SUBTYPE_MASK) == TYPE_CTL_PSPOLL) {
+		bIsPSPOLL = true;
+		cbMacHdLen = WLAN_HDR_ADDR2_LEN;
+	} else {
+		cbMacHdLen = WLAN_HDR_ADDR3_LEN;
+	}
+
+	//Set FRAGCTL_MACHDCNT
+	pTxBufHead->wFragCtl |= cpu_to_le16((unsigned short)(cbMacHdLen << 10));
+
+	// Notes:
+	// Although spec says MMPDU can be fragmented; In most cases,
+	// no one will send a MMPDU under fragmentation. With RTS may occur.
+	pDevice->bAES = false;  //Set FRAGCTL_WEPTYP
+
+	if (WLAN_GET_FC_ISWEP(pPacket->p80211Header->sA4.wFrameCtl) != 0) {
+		if (pDevice->eEncryptionStatus == Ndis802_11Encryption1Enabled) {
+			cbIVlen = 4;
+			cbICVlen = 4;
+			pTxBufHead->wFragCtl |= FRAGCTL_LEGACY;
+		} else if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) {
+			cbIVlen = 8;//IV+ExtIV
+			cbMIClen = 8;
+			cbICVlen = 4;
+			pTxBufHead->wFragCtl |= FRAGCTL_TKIP;
+			//We need to get seed here for filling TxKey entry.
+			//TKIPvMixKey(pTransmitKey->abyKey, pDevice->abyCurrentNetAddr,
+			//            pTransmitKey->wTSC15_0, pTransmitKey->dwTSC47_16, pDevice->abyPRNG);
+		} else if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) {
+			cbIVlen = 8;//RSN Header
+			cbICVlen = 8;//MIC
+			pTxBufHead->wFragCtl |= FRAGCTL_AES;
+			pDevice->bAES = true;
+		}
+		//MAC Header should be padding 0 to DW alignment.
+		uPadding = 4 - (cbMacHdLen%4);
+		uPadding %= 4;
+	}
+
+	cbFrameSize = cbMacHdLen + cbFrameBodySize + cbIVlen + cbMIClen + cbICVlen + cbFCSlen;
+
+	//Set FIFOCTL_GrpAckPolicy
+	if (pDevice->bGrpAckPolicy == true) {//0000 0100 0000 0000
+		pTxBufHead->wFIFOCtl |=	FIFOCTL_GRPACK;
+	}
+	//the rest of pTxBufHead->wFragCtl:FragTyp will be set later in s_vFillFragParameter()
+
+	//Set RrvTime/RTS/CTS Buffer
+	if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {//802.11g packet
+
+		pvRrvTime = (PSRrvTime_gCTS) (pbyTxBufferAddr + wTxBufSize);
+		pMICHDR = NULL;
+		pvRTS = NULL;
+		pCTS = (PSCTS) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gCTS));
+		pvTxDataHd = (PSTxDataHead_g) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gCTS) + sizeof(SCTS));
+		cbHeaderSize = wTxBufSize + sizeof(SRrvTime_gCTS) + sizeof(SCTS) + sizeof(STxDataHead_g);
+	} else { // 802.11a/b packet
+		pvRrvTime = (PSRrvTime_ab) (pbyTxBufferAddr + wTxBufSize);
+		pMICHDR = NULL;
+		pvRTS = NULL;
+		pCTS = NULL;
+		pvTxDataHd = (PSTxDataHead_ab) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_ab));
+		cbHeaderSize = wTxBufSize + sizeof(SRrvTime_ab) + sizeof(STxDataHead_ab);
+	}
+
+	memset((void *)(pbyTxBufferAddr + wTxBufSize), 0, (cbHeaderSize - wTxBufSize));
+
+	memcpy(&(sEthHeader.abyDstAddr[0]), &(pPacket->p80211Header->sA3.abyAddr1[0]), ETH_ALEN);
+	memcpy(&(sEthHeader.abySrcAddr[0]), &(pPacket->p80211Header->sA3.abyAddr2[0]), ETH_ALEN);
+	//=========================
+	//    No Fragmentation
+	//=========================
+	pTxBufHead->wFragCtl |= (unsigned short)FRAGCTL_NONFRAG;
+
+	//Fill FIFO,RrvTime,RTS,and CTS
+	s_vGenerateTxParameter(pDevice, byPktType, pbyTxBufferAddr, pvRrvTime, pvRTS, pCTS,
+			       cbFrameSize, bNeedACK, TYPE_TXDMA0, &sEthHeader, wCurrentRate);
+
+	//Fill DataHead
+	uDuration = s_uFillDataHead(pDevice, byPktType, pvTxDataHd, cbFrameSize, TYPE_TXDMA0, bNeedACK,
+				    0, 0, 1, AUTO_FB_NONE, wCurrentRate);
+
+	pMACHeader = (PS802_11Header) (pbyTxBufferAddr + cbHeaderSize);
+
+	cbReqCount = cbHeaderSize + cbMacHdLen + uPadding + cbIVlen + cbFrameBodySize;
+
+	if (WLAN_GET_FC_ISWEP(pPacket->p80211Header->sA4.wFrameCtl) != 0) {
+		unsigned char *pbyIVHead;
+		unsigned char *pbyPayloadHead;
+		unsigned char *pbyBSSID;
+		PSKeyItem       pTransmitKey = NULL;
+
+		pbyIVHead = (unsigned char *)(pbyTxBufferAddr + cbHeaderSize + cbMacHdLen + uPadding);
+		pbyPayloadHead = (unsigned char *)(pbyTxBufferAddr + cbHeaderSize + cbMacHdLen + uPadding + cbIVlen);
+
+		//Fill TXKEY
+		//Kyle: Need fix: TKIP and AES did't encrypt Mnt Packet.
+		//s_vFillTxKey(pDevice, (unsigned char *)pTxBufHead->adwTxKey, NULL);
+
+		//Fill IV(ExtIV,RSNHDR)
+		//s_vFillPrePayload(pDevice, pbyIVHead, NULL);
+		//---------------------------
+		// S/W or H/W Encryption
+		//---------------------------
+		do {
+			if ((pDevice->eOPMode == OP_MODE_INFRASTRUCTURE) &&
+			    (pDevice->bLinkPass == true)) {
+				pbyBSSID = pDevice->abyBSSID;
+				// get pairwise key
+				if (KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, PAIRWISE_KEY, &pTransmitKey) == false) {
+					// get group key
+					if (KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, GROUP_KEY, &pTransmitKey) == true) {
+						DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Get GTK.\n");
+						break;
+					}
+				} else {
+					DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Get PTK.\n");
+					break;
+				}
+			}
+			// get group key
+			pbyBSSID = pDevice->abyBroadcastAddr;
+			if (KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, GROUP_KEY, &pTransmitKey) == false) {
+				pTransmitKey = NULL;
+				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "KEY is NULL. OP Mode[%d]\n", pDevice->eOPMode);
+			} else {
+				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Get GTK.\n");
+			}
+		} while (false);
+		//Fill TXKEY
+		s_vFillTxKey(pDevice, (unsigned char *)(pTxBufHead->adwTxKey), pbyIVHead, pTransmitKey,
+			     (unsigned char *)pMACHeader, (unsigned short)cbFrameBodySize, NULL);
+
+		memcpy(pMACHeader, pPacket->p80211Header, cbMacHdLen);
+		memcpy(pbyPayloadHead, ((unsigned char *)(pPacket->p80211Header) + cbMacHdLen),
+		       cbFrameBodySize);
+	} else {
+		// Copy the Packet into a tx Buffer
+		memcpy(pMACHeader, pPacket->p80211Header, pPacket->cbMPDULen);
+	}
+
+	pMACHeader->wSeqCtl = cpu_to_le16(pDevice->wSeqCounter << 4);
+	pDevice->wSeqCounter++;
+	if (pDevice->wSeqCounter > 0x0fff)
+		pDevice->wSeqCounter = 0;
+
+	if (bIsPSPOLL) {
+		// The MAC will automatically replace the Duration-field of MAC header by Duration-field
+		// of  FIFO control header.
+		// This will cause AID-field of PS-POLL packet to be incorrect (Because PS-POLL's AID field is
+		// in the same place of other packet's Duration-field).
+		// And it will cause Cisco-AP to issue Disassociation-packet
+		if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {
+			((PSTxDataHead_g)pvTxDataHd)->wDuration_a = cpu_to_le16(pPacket->p80211Header->sA2.wDurationID);
+			((PSTxDataHead_g)pvTxDataHd)->wDuration_b = cpu_to_le16(pPacket->p80211Header->sA2.wDurationID);
+		} else {
+			((PSTxDataHead_ab)pvTxDataHd)->wDuration = cpu_to_le16(pPacket->p80211Header->sA2.wDurationID);
+		}
+	}
+
+	// first TD is the only TD
+	//Set TSR1 & ReqCount in TxDescHead
+	pFrstTD->m_td1TD1.byTCR = (TCR_STP | TCR_EDP | EDMSDU);
+	pFrstTD->pTDInfo->skb_dma = pFrstTD->pTDInfo->buf_dma;
+	pFrstTD->m_td1TD1.wReqCount = cpu_to_le16((unsigned short)(cbReqCount));
+	pFrstTD->buff_addr = cpu_to_le32(pFrstTD->pTDInfo->skb_dma);
+	pFrstTD->pTDInfo->byFlags = 0;
+
+	if (MACbIsRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_PS)) {
+		// Disable PS
+		MACbPSWakeup(pDevice->PortOffset);
+	}
+	pDevice->bPWBitOn = false;
+
+	wmb();
+	pFrstTD->m_td0TD0.f1Owner = OWNED_BY_NIC;
+	wmb();
+
+	pDevice->iTDUsed[TYPE_TXDMA0]++;
+
+	if (AVAIL_TD(pDevice, TYPE_TXDMA0) <= 1) {
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " available td0 <= 1\n");
+	}
+
+	pDevice->apCurrTD[TYPE_TXDMA0] = pFrstTD->next;
 
 #ifdef TxInSleep
-  pDevice->nTxDataTimeCout=0; //2008-8-21 chester <add> for send null packet
-  #endif
-
-    // Poll Transmit the adapter
-    MACvTransmit0(pDevice->PortOffset);
+	pDevice->nTxDataTimeCout = 0; //2008-8-21 chester <add> for send null packet
+#endif
 
-    return CMD_STATUS_PENDING;
+	// Poll Transmit the adapter
+	MACvTransmit0(pDevice->PortOffset);
 
+	return CMD_STATUS_PENDING;
 }
 
-
 CMD_STATUS csBeacon_xmit(PSDevice pDevice, PSTxMgmtPacket pPacket) {
-
-    unsigned char byPktType;
-    unsigned char *pbyBuffer = (unsigned char *)pDevice->tx_beacon_bufs;
-    unsigned int cbFrameSize = pPacket->cbMPDULen + WLAN_FCS_LEN;
-    unsigned int cbHeaderSize = 0;
-    unsigned short wTxBufSize = sizeof(STxShortBufHead);
-    PSTxShortBufHead pTxBufHead = (PSTxShortBufHead) pbyBuffer;
-    PSTxDataHead_ab  pTxDataHead = (PSTxDataHead_ab) (pbyBuffer + wTxBufSize);
-    PS802_11Header   pMACHeader;
-    unsigned short wCurrentRate;
-    unsigned short wLen = 0x0000;
-
-
-    memset(pTxBufHead, 0, wTxBufSize);
-
-    if (pDevice->eCurrentPHYType == PHY_TYPE_11A) {
-        wCurrentRate = RATE_6M;
-        byPktType = PK_TYPE_11A;
-    } else {
-        wCurrentRate = RATE_2M;
-        byPktType = PK_TYPE_11B;
-    }
-
-    //Set Preamble type always long
-    pDevice->byPreambleType = PREAMBLE_LONG;
-
-    //Set FIFOCTL_GENINT
-
-    pTxBufHead->wFIFOCtl |= FIFOCTL_GENINT;
-
-
-    //Set packet type & Get Duration
-    if (byPktType == PK_TYPE_11A) {//0000 0000 0000 0000
-        pTxDataHead->wDuration = cpu_to_le16((unsigned short)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameSize, byPktType,
-                                                          wCurrentRate, false, 0, 0, 1, AUTO_FB_NONE));
-    }
-    else if (byPktType == PK_TYPE_11B) {//0000 0001 0000 0000
-        pTxBufHead->wFIFOCtl |= FIFOCTL_11B;
-        pTxDataHead->wDuration = cpu_to_le16((unsigned short)s_uGetDataDuration(pDevice, DATADUR_B, cbFrameSize, byPktType,
-                                                          wCurrentRate, false, 0, 0, 1, AUTO_FB_NONE));
-    }
-
-    BBvCalculateParameter(pDevice, cbFrameSize, wCurrentRate, byPktType,
-        (unsigned short *)&(wLen), (unsigned char *)&(pTxDataHead->byServiceField), (unsigned char *)&(pTxDataHead->bySignalField)
-    );
-    pTxDataHead->wTransmitLength = cpu_to_le16(wLen);
-    //Get TimeStampOff
-    pTxDataHead->wTimeStampOff = cpu_to_le16(wTimeStampOff[pDevice->byPreambleType%2][wCurrentRate%MAX_RATE]);
-    cbHeaderSize = wTxBufSize + sizeof(STxDataHead_ab);
-
-   //Generate Beacon Header
-    pMACHeader = (PS802_11Header)(pbyBuffer + cbHeaderSize);
-    memcpy(pMACHeader, pPacket->p80211Header, pPacket->cbMPDULen);
-
-    pMACHeader->wDurationID = 0;
-    pMACHeader->wSeqCtl = cpu_to_le16(pDevice->wSeqCounter << 4);
-    pDevice->wSeqCounter++ ;
-    if (pDevice->wSeqCounter > 0x0fff)
-        pDevice->wSeqCounter = 0;
-
-    // Set Beacon buffer length
-    pDevice->wBCNBufLen = pPacket->cbMPDULen + cbHeaderSize;
-
-    MACvSetCurrBCNTxDescAddr(pDevice->PortOffset, (pDevice->tx_beacon_dma));
-
-    MACvSetCurrBCNLength(pDevice->PortOffset, pDevice->wBCNBufLen);
-    // Set auto Transmit on
-    MACvRegBitsOn(pDevice->PortOffset, MAC_REG_TCR, TCR_AUTOBCNTX);
-    // Poll Transmit the adapter
-    MACvTransmitBCN(pDevice->PortOffset);
-
-    return CMD_STATUS_PENDING;
+	unsigned char byPktType;
+	unsigned char *pbyBuffer = (unsigned char *)pDevice->tx_beacon_bufs;
+	unsigned int cbFrameSize = pPacket->cbMPDULen + WLAN_FCS_LEN;
+	unsigned int cbHeaderSize = 0;
+	unsigned short wTxBufSize = sizeof(STxShortBufHead);
+	PSTxShortBufHead pTxBufHead = (PSTxShortBufHead) pbyBuffer;
+	PSTxDataHead_ab  pTxDataHead = (PSTxDataHead_ab) (pbyBuffer + wTxBufSize);
+	PS802_11Header   pMACHeader;
+	unsigned short wCurrentRate;
+	unsigned short wLen = 0x0000;
+
+	memset(pTxBufHead, 0, wTxBufSize);
+
+	if (pDevice->eCurrentPHYType == PHY_TYPE_11A) {
+		wCurrentRate = RATE_6M;
+		byPktType = PK_TYPE_11A;
+	} else {
+		wCurrentRate = RATE_2M;
+		byPktType = PK_TYPE_11B;
+	}
+
+	//Set Preamble type always long
+	pDevice->byPreambleType = PREAMBLE_LONG;
+
+	//Set FIFOCTL_GENINT
+
+	pTxBufHead->wFIFOCtl |= FIFOCTL_GENINT;
+
+	//Set packet type & Get Duration
+	if (byPktType == PK_TYPE_11A) {//0000 0000 0000 0000
+		pTxDataHead->wDuration = cpu_to_le16((unsigned short)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameSize, byPktType,
+											wCurrentRate, false, 0, 0, 1, AUTO_FB_NONE));
+	} else if (byPktType == PK_TYPE_11B) {//0000 0001 0000 0000
+		pTxBufHead->wFIFOCtl |= FIFOCTL_11B;
+		pTxDataHead->wDuration = cpu_to_le16((unsigned short)s_uGetDataDuration(pDevice, DATADUR_B, cbFrameSize, byPktType,
+											wCurrentRate, false, 0, 0, 1, AUTO_FB_NONE));
+	}
+
+	BBvCalculateParameter(pDevice, cbFrameSize, wCurrentRate, byPktType,
+			      (unsigned short *)&(wLen), (unsigned char *)&(pTxDataHead->byServiceField), (unsigned char *)&(pTxDataHead->bySignalField)
+);
+	pTxDataHead->wTransmitLength = cpu_to_le16(wLen);
+	//Get TimeStampOff
+	pTxDataHead->wTimeStampOff = cpu_to_le16(wTimeStampOff[pDevice->byPreambleType%2][wCurrentRate%MAX_RATE]);
+	cbHeaderSize = wTxBufSize + sizeof(STxDataHead_ab);
+
+	//Generate Beacon Header
+	pMACHeader = (PS802_11Header)(pbyBuffer + cbHeaderSize);
+	memcpy(pMACHeader, pPacket->p80211Header, pPacket->cbMPDULen);
+
+	pMACHeader->wDurationID = 0;
+	pMACHeader->wSeqCtl = cpu_to_le16(pDevice->wSeqCounter << 4);
+	pDevice->wSeqCounter++;
+	if (pDevice->wSeqCounter > 0x0fff)
+		pDevice->wSeqCounter = 0;
+
+	// Set Beacon buffer length
+	pDevice->wBCNBufLen = pPacket->cbMPDULen + cbHeaderSize;
+
+	MACvSetCurrBCNTxDescAddr(pDevice->PortOffset, (pDevice->tx_beacon_dma));
+
+	MACvSetCurrBCNLength(pDevice->PortOffset, pDevice->wBCNBufLen);
+	// Set auto Transmit on
+	MACvRegBitsOn(pDevice->PortOffset, MAC_REG_TCR, TCR_AUTOBCNTX);
+	// Poll Transmit the adapter
+	MACvTransmitBCN(pDevice->PortOffset);
+
+	return CMD_STATUS_PENDING;
 }
 
-
-
 unsigned int
-cbGetFragCount (
-    PSDevice         pDevice,
-    PSKeyItem        pTransmitKey,
-    unsigned int cbFrameBodySize,
-    PSEthernetHeader psEthHeader
-    )
+cbGetFragCount(
+	PSDevice         pDevice,
+	PSKeyItem        pTransmitKey,
+	unsigned int cbFrameBodySize,
+	PSEthernetHeader psEthHeader
+)
 {
-    unsigned int cbMACHdLen;
-    unsigned int cbFrameSize;
-    unsigned int cbFragmentSize; //Hdr+(IV)+payoad+(MIC)+(ICV)+FCS
-    unsigned int cbFragPayloadSize;
-    unsigned int cbLastFragPayloadSize;
-    unsigned int cbIVlen = 0;
-    unsigned int cbICVlen = 0;
-    unsigned int cbMIClen = 0;
-    unsigned int cbFCSlen = 4;
-    unsigned int uMACfragNum = 1;
-    bool bNeedACK;
-
-
-
-    if ((pDevice->eOPMode == OP_MODE_ADHOC) ||
-        (pDevice->eOPMode == OP_MODE_AP)) {
-        if (is_multicast_ether_addr(&(psEthHeader->abyDstAddr[0])))
-            bNeedACK = false;
-        else
-            bNeedACK = true;
-    }
-    else {
-        // MSDUs in Infra mode always need ACK
-        bNeedACK = true;
-    }
-
-    if (pDevice->bLongHeader)
-        cbMACHdLen = WLAN_HDR_ADDR3_LEN + 6;
-    else
-        cbMACHdLen = WLAN_HDR_ADDR3_LEN;
-
-
-    if (pDevice->bEncryptionEnable == true) {
-
-        if (pTransmitKey == NULL) {
-            if ((pDevice->eEncryptionStatus == Ndis802_11Encryption1Enabled) ||
-                (pDevice->pMgmt->eAuthenMode < WMAC_AUTH_WPA)) {
-                cbIVlen = 4;
-                cbICVlen = 4;
-            } else if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) {
-                cbIVlen = 8;//IV+ExtIV
-                cbMIClen = 8;
-                cbICVlen = 4;
-            } else if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) {
-                cbIVlen = 8;//RSN Header
-                cbICVlen = 8;//MIC
-            }
-        } else if (pTransmitKey->byCipherSuite == KEY_CTL_WEP) {
-            cbIVlen = 4;
-            cbICVlen = 4;
-        } else if (pTransmitKey->byCipherSuite == KEY_CTL_TKIP) {
-            cbIVlen = 8;//IV+ExtIV
-            cbMIClen = 8;
-            cbICVlen = 4;
-        } else if (pTransmitKey->byCipherSuite == KEY_CTL_CCMP) {
-            cbIVlen = 8;//RSN Header
-            cbICVlen = 8;//MIC
-        }
-    }
-
-    cbFrameSize = cbMACHdLen + cbIVlen + (cbFrameBodySize + cbMIClen) + cbICVlen + cbFCSlen;
-
-    if ((cbFrameSize > pDevice->wFragmentationThreshold) && (bNeedACK == true)) {
-        // Fragmentation
-        cbFragmentSize = pDevice->wFragmentationThreshold;
-        cbFragPayloadSize = cbFragmentSize - cbMACHdLen - cbIVlen - cbICVlen - cbFCSlen;
-        uMACfragNum = (unsigned short) ((cbFrameBodySize + cbMIClen) / cbFragPayloadSize);
-        cbLastFragPayloadSize = (cbFrameBodySize + cbMIClen) % cbFragPayloadSize;
-        if (cbLastFragPayloadSize == 0) {
-            cbLastFragPayloadSize = cbFragPayloadSize;
-        } else {
-            uMACfragNum++;
-        }
-    }
-    return uMACfragNum;
+	unsigned int cbMACHdLen;
+	unsigned int cbFrameSize;
+	unsigned int cbFragmentSize; //Hdr+(IV)+payoad+(MIC)+(ICV)+FCS
+	unsigned int cbFragPayloadSize;
+	unsigned int cbLastFragPayloadSize;
+	unsigned int cbIVlen = 0;
+	unsigned int cbICVlen = 0;
+	unsigned int cbMIClen = 0;
+	unsigned int cbFCSlen = 4;
+	unsigned int uMACfragNum = 1;
+	bool bNeedACK;
+
+	if ((pDevice->eOPMode == OP_MODE_ADHOC) ||
+	    (pDevice->eOPMode == OP_MODE_AP)) {
+		if (is_multicast_ether_addr(&(psEthHeader->abyDstAddr[0])))
+			bNeedACK = false;
+		else
+			bNeedACK = true;
+	} else {
+		// MSDUs in Infra mode always need ACK
+		bNeedACK = true;
+	}
+
+	if (pDevice->bLongHeader)
+		cbMACHdLen = WLAN_HDR_ADDR3_LEN + 6;
+	else
+		cbMACHdLen = WLAN_HDR_ADDR3_LEN;
+
+	if (pDevice->bEncryptionEnable == true) {
+		if (pTransmitKey == NULL) {
+			if ((pDevice->eEncryptionStatus == Ndis802_11Encryption1Enabled) ||
+			    (pDevice->pMgmt->eAuthenMode < WMAC_AUTH_WPA)) {
+				cbIVlen = 4;
+				cbICVlen = 4;
+			} else if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) {
+				cbIVlen = 8;//IV+ExtIV
+				cbMIClen = 8;
+				cbICVlen = 4;
+			} else if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) {
+				cbIVlen = 8;//RSN Header
+				cbICVlen = 8;//MIC
+			}
+		} else if (pTransmitKey->byCipherSuite == KEY_CTL_WEP) {
+			cbIVlen = 4;
+			cbICVlen = 4;
+		} else if (pTransmitKey->byCipherSuite == KEY_CTL_TKIP) {
+			cbIVlen = 8;//IV+ExtIV
+			cbMIClen = 8;
+			cbICVlen = 4;
+		} else if (pTransmitKey->byCipherSuite == KEY_CTL_CCMP) {
+			cbIVlen = 8;//RSN Header
+			cbICVlen = 8;//MIC
+		}
+	}
+
+	cbFrameSize = cbMACHdLen + cbIVlen + (cbFrameBodySize + cbMIClen) + cbICVlen + cbFCSlen;
+
+	if ((cbFrameSize > pDevice->wFragmentationThreshold) && (bNeedACK == true)) {
+		// Fragmentation
+		cbFragmentSize = pDevice->wFragmentationThreshold;
+		cbFragPayloadSize = cbFragmentSize - cbMACHdLen - cbIVlen - cbICVlen - cbFCSlen;
+		uMACfragNum = (unsigned short) ((cbFrameBodySize + cbMIClen) / cbFragPayloadSize);
+		cbLastFragPayloadSize = (cbFrameBodySize + cbMIClen) % cbFragPayloadSize;
+		if (cbLastFragPayloadSize == 0) {
+			cbLastFragPayloadSize = cbFragPayloadSize;
+		} else {
+			uMACfragNum++;
+		}
+	}
+	return uMACfragNum;
 }
 
-
 void
 vDMA0_tx_80211(PSDevice  pDevice, struct sk_buff *skb, unsigned char *pbMPDU, unsigned int cbMPDULen) {
-
-    PSTxDesc        pFrstTD;
-    unsigned char byPktType;
-    unsigned char *pbyTxBufferAddr;
-    void *          pvRTS;
-    void *          pvCTS;
-    void *          pvTxDataHd;
-    unsigned int uDuration;
-    unsigned int cbReqCount;
-    PS802_11Header  pMACHeader;
-    unsigned int cbHeaderSize;
-    unsigned int cbFrameBodySize;
-    bool bNeedACK;
-    bool bIsPSPOLL = false;
-    PSTxBufHead     pTxBufHead;
-    unsigned int cbFrameSize;
-    unsigned int cbIVlen = 0;
-    unsigned int cbICVlen = 0;
-    unsigned int cbMIClen = 0;
-    unsigned int cbFCSlen = 4;
-    unsigned int uPadding = 0;
-    unsigned int cbMICHDR = 0;
-    unsigned int uLength = 0;
-    unsigned long dwMICKey0, dwMICKey1;
-    unsigned long dwMIC_Priority;
-    unsigned long *pdwMIC_L;
-    unsigned long *pdwMIC_R;
-    unsigned short wTxBufSize;
-    unsigned int cbMacHdLen;
-    SEthernetHeader sEthHeader;
-    void *          pvRrvTime;
-    void *          pMICHDR;
-    PSMgmtObject    pMgmt = pDevice->pMgmt;
-    unsigned short wCurrentRate = RATE_1M;
-    PUWLAN_80211HDR  p80211Header;
-    unsigned int uNodeIndex = 0;
-    bool bNodeExist = false;
-    SKeyItem        STempKey;
-    PSKeyItem       pTransmitKey = NULL;
-    unsigned char *pbyIVHead;
-    unsigned char *pbyPayloadHead;
-    unsigned char *pbyMacHdr;
-
-    unsigned int cbExtSuppRate = 0;
+	PSTxDesc        pFrstTD;
+	unsigned char byPktType;
+	unsigned char *pbyTxBufferAddr;
+	void *pvRTS;
+	void *pvCTS;
+	void *pvTxDataHd;
+	unsigned int uDuration;
+	unsigned int cbReqCount;
+	PS802_11Header  pMACHeader;
+	unsigned int cbHeaderSize;
+	unsigned int cbFrameBodySize;
+	bool bNeedACK;
+	bool bIsPSPOLL = false;
+	PSTxBufHead     pTxBufHead;
+	unsigned int cbFrameSize;
+	unsigned int cbIVlen = 0;
+	unsigned int cbICVlen = 0;
+	unsigned int cbMIClen = 0;
+	unsigned int cbFCSlen = 4;
+	unsigned int uPadding = 0;
+	unsigned int cbMICHDR = 0;
+	unsigned int uLength = 0;
+	unsigned long dwMICKey0, dwMICKey1;
+	unsigned long dwMIC_Priority;
+	unsigned long *pdwMIC_L;
+	unsigned long *pdwMIC_R;
+	unsigned short wTxBufSize;
+	unsigned int cbMacHdLen;
+	SEthernetHeader sEthHeader;
+	void *pvRrvTime;
+	void *pMICHDR;
+	PSMgmtObject    pMgmt = pDevice->pMgmt;
+	unsigned short wCurrentRate = RATE_1M;
+	PUWLAN_80211HDR  p80211Header;
+	unsigned int uNodeIndex = 0;
+	bool bNodeExist = false;
+	SKeyItem        STempKey;
+	PSKeyItem       pTransmitKey = NULL;
+	unsigned char *pbyIVHead;
+	unsigned char *pbyPayloadHead;
+	unsigned char *pbyMacHdr;
+
+	unsigned int cbExtSuppRate = 0;
 //    PWLAN_IE        pItem;
 
-
-    pvRrvTime = pMICHDR = pvRTS = pvCTS = pvTxDataHd = NULL;
-
-    if(cbMPDULen <= WLAN_HDR_ADDR3_LEN) {
-       cbFrameBodySize = 0;
-    }
-    else {
-       cbFrameBodySize = cbMPDULen - WLAN_HDR_ADDR3_LEN;
-    }
-    p80211Header = (PUWLAN_80211HDR)pbMPDU;
-
-
-    pFrstTD = pDevice->apCurrTD[TYPE_TXDMA0];
-    pbyTxBufferAddr = (unsigned char *)pFrstTD->pTDInfo->buf;
-    pTxBufHead = (PSTxBufHead) pbyTxBufferAddr;
-    wTxBufSize = sizeof(STxBufHead);
-    memset(pTxBufHead, 0, wTxBufSize);
-
-    if (pDevice->eCurrentPHYType == PHY_TYPE_11A) {
-        wCurrentRate = RATE_6M;
-        byPktType = PK_TYPE_11A;
-    } else {
-        wCurrentRate = RATE_1M;
-        byPktType = PK_TYPE_11B;
-    }
-
-    // SetPower will cause error power TX state for OFDM Date packet in TX buffer.
-    // 2004.11.11 Kyle -- Using OFDM power to tx MngPkt will decrease the connection capability.
-    //                    And cmd timer will wait data pkt TX to finish before scanning so it's OK
-    //                    to set power here.
-    if (pDevice->pMgmt->eScanState != WMAC_NO_SCANNING) {
-        RFbSetPower(pDevice, wCurrentRate, pDevice->byCurrentCh);
-    } else {
-        RFbSetPower(pDevice, wCurrentRate, pMgmt->uCurrChannel);
-    }
-    pTxBufHead->byTxPower = pDevice->byCurPwr;
-
-    //+++++++++++++++++++++ Patch VT3253 A1 performance +++++++++++++++++++++++++++
-    if (pDevice->byFOETuning) {
-        if ((p80211Header->sA3.wFrameCtl & TYPE_DATE_NULL) == TYPE_DATE_NULL) {
-            wCurrentRate = RATE_24M;
-            byPktType = PK_TYPE_11GA;
-        }
-    }
-
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"vDMA0_tx_80211: p80211Header->sA3.wFrameCtl = %x \n", p80211Header->sA3.wFrameCtl);
-
-    //Set packet type
-    if (byPktType == PK_TYPE_11A) {//0000 0000 0000 0000
-        pTxBufHead->wFIFOCtl = 0;
-    }
-    else if (byPktType == PK_TYPE_11B) {//0000 0001 0000 0000
-        pTxBufHead->wFIFOCtl |= FIFOCTL_11B;
-    }
-    else if (byPktType == PK_TYPE_11GB) {//0000 0010 0000 0000
-        pTxBufHead->wFIFOCtl |= FIFOCTL_11GB;
-    }
-    else if (byPktType == PK_TYPE_11GA) {//0000 0011 0000 0000
-        pTxBufHead->wFIFOCtl |= FIFOCTL_11GA;
-    }
-
-    pTxBufHead->wFIFOCtl |= FIFOCTL_TMOEN;
-    pTxBufHead->wTimeStamp = cpu_to_le16(DEFAULT_MGN_LIFETIME_RES_64us);
-
-
-    if (is_multicast_ether_addr(&(p80211Header->sA3.abyAddr1[0]))) {
-        bNeedACK = false;
-        if (pDevice->bEnableHostWEP) {
-            uNodeIndex = 0;
-            bNodeExist = true;
-        }
-    }
-    else {
-        if (pDevice->bEnableHostWEP) {
-            if (BSSDBbIsSTAInNodeDB(pDevice->pMgmt, (unsigned char *)(p80211Header->sA3.abyAddr1), &uNodeIndex))
-                bNodeExist = true;
-        }
-        bNeedACK = true;
-        pTxBufHead->wFIFOCtl |= FIFOCTL_NEEDACK;
-    };
-
-    if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) ||
-        (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) ) {
-
-        pTxBufHead->wFIFOCtl |= FIFOCTL_LRETRY;
-        //Set Preamble type always long
-        //pDevice->byPreambleType = PREAMBLE_LONG;
-
-        // probe-response don't retry
-        //if ((p80211Header->sA4.wFrameCtl & TYPE_SUBTYPE_MASK) == TYPE_MGMT_PROBE_RSP) {
-        //     bNeedACK = false;
-        //     pTxBufHead->wFIFOCtl  &= (~FIFOCTL_NEEDACK);
-        //}
-    }
-
-    pTxBufHead->wFIFOCtl |= (FIFOCTL_GENINT | FIFOCTL_ISDMA0);
-
-    if ((p80211Header->sA4.wFrameCtl & TYPE_SUBTYPE_MASK) == TYPE_CTL_PSPOLL) {
-        bIsPSPOLL = true;
-        cbMacHdLen = WLAN_HDR_ADDR2_LEN;
-    } else {
-        cbMacHdLen = WLAN_HDR_ADDR3_LEN;
-    }
-
-    // hostapd deamon ext support rate patch
-    if (WLAN_GET_FC_FSTYPE(p80211Header->sA4.wFrameCtl) == WLAN_FSTYPE_ASSOCRESP) {
-
-        if (((PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates)->len != 0) {
-            cbExtSuppRate += ((PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates)->len + WLAN_IEHDR_LEN;
-         }
-
-        if (((PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates)->len != 0) {
-            cbExtSuppRate += ((PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates)->len + WLAN_IEHDR_LEN;
-         }
-
-         if (cbExtSuppRate >0) {
-            cbFrameBodySize = WLAN_ASSOCRESP_OFF_SUPP_RATES;
-         }
-    }
-
-
-    //Set FRAGCTL_MACHDCNT
-    pTxBufHead->wFragCtl |= cpu_to_le16((unsigned short)cbMacHdLen << 10);
-
-    // Notes:
-    // Although spec says MMPDU can be fragmented; In most cases,
-    // no one will send a MMPDU under fragmentation. With RTS may occur.
-    pDevice->bAES = false;  //Set FRAGCTL_WEPTYP
-
-
-    if (WLAN_GET_FC_ISWEP(p80211Header->sA4.wFrameCtl) != 0) {
-        if (pDevice->eEncryptionStatus == Ndis802_11Encryption1Enabled) {
-            cbIVlen = 4;
-            cbICVlen = 4;
-    	    pTxBufHead->wFragCtl |= FRAGCTL_LEGACY;
-        }
-        else if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) {
-            cbIVlen = 8;//IV+ExtIV
-            cbMIClen = 8;
-            cbICVlen = 4;
-    	    pTxBufHead->wFragCtl |= FRAGCTL_TKIP;
-    	    //We need to get seed here for filling TxKey entry.
-            //TKIPvMixKey(pTransmitKey->abyKey, pDevice->abyCurrentNetAddr,
-            //            pTransmitKey->wTSC15_0, pTransmitKey->dwTSC47_16, pDevice->abyPRNG);
-        }
-        else if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) {
-            cbIVlen = 8;//RSN Header
-            cbICVlen = 8;//MIC
-            cbMICHDR = sizeof(SMICHDRHead);
-            pTxBufHead->wFragCtl |= FRAGCTL_AES;
-            pDevice->bAES = true;
-        }
-        //MAC Header should be padding 0 to DW alignment.
-        uPadding = 4 - (cbMacHdLen%4);
-        uPadding %= 4;
-    }
-
-    cbFrameSize = cbMacHdLen + cbFrameBodySize + cbIVlen + cbMIClen + cbICVlen + cbFCSlen + cbExtSuppRate;
-
-    //Set FIFOCTL_GrpAckPolicy
-    if (pDevice->bGrpAckPolicy == true) {//0000 0100 0000 0000
-        pTxBufHead->wFIFOCtl |=	FIFOCTL_GRPACK;
-    }
-    //the rest of pTxBufHead->wFragCtl:FragTyp will be set later in s_vFillFragParameter()
-
-
-    if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {//802.11g packet
-
-        pvRrvTime = (PSRrvTime_gCTS) (pbyTxBufferAddr + wTxBufSize);
-        pMICHDR = (PSMICHDRHead) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gCTS));
-        pvRTS = NULL;
-        pvCTS = (PSCTS) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gCTS) + cbMICHDR);
-        pvTxDataHd = (PSTxDataHead_g) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gCTS) + cbMICHDR + sizeof(SCTS));
-        cbHeaderSize = wTxBufSize + sizeof(SRrvTime_gCTS) + cbMICHDR + sizeof(SCTS) + sizeof(STxDataHead_g);
-
-    }
-    else {//802.11a/b packet
-
-        pvRrvTime = (PSRrvTime_ab) (pbyTxBufferAddr + wTxBufSize);
-        pMICHDR = (PSMICHDRHead) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_ab));
-        pvRTS = NULL;
-        pvCTS = NULL;
-        pvTxDataHd = (PSTxDataHead_ab) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_ab) + cbMICHDR);
-        cbHeaderSize = wTxBufSize + sizeof(SRrvTime_ab) + cbMICHDR + sizeof(STxDataHead_ab);
-
-    }
-
-    memset((void *)(pbyTxBufferAddr + wTxBufSize), 0, (cbHeaderSize - wTxBufSize));
-    memcpy(&(sEthHeader.abyDstAddr[0]), &(p80211Header->sA3.abyAddr1[0]), ETH_ALEN);
-    memcpy(&(sEthHeader.abySrcAddr[0]), &(p80211Header->sA3.abyAddr2[0]), ETH_ALEN);
-    //=========================
-    //    No Fragmentation
-    //=========================
-    pTxBufHead->wFragCtl |= (unsigned short)FRAGCTL_NONFRAG;
-
-
-    //Fill FIFO,RrvTime,RTS,and CTS
-    s_vGenerateTxParameter(pDevice, byPktType, pbyTxBufferAddr, pvRrvTime, pvRTS, pvCTS,
-                           cbFrameSize, bNeedACK, TYPE_TXDMA0, &sEthHeader, wCurrentRate);
-
-    //Fill DataHead
-    uDuration = s_uFillDataHead(pDevice, byPktType, pvTxDataHd, cbFrameSize, TYPE_TXDMA0, bNeedACK,
-                                0, 0, 1, AUTO_FB_NONE, wCurrentRate);
-
-    pMACHeader = (PS802_11Header) (pbyTxBufferAddr + cbHeaderSize);
-
-    cbReqCount = cbHeaderSize + cbMacHdLen + uPadding + cbIVlen + (cbFrameBodySize + cbMIClen) + cbExtSuppRate;
-
-    pbyMacHdr = (unsigned char *)(pbyTxBufferAddr + cbHeaderSize);
-    pbyPayloadHead = (unsigned char *)(pbyMacHdr + cbMacHdLen + uPadding + cbIVlen);
-    pbyIVHead = (unsigned char *)(pbyMacHdr + cbMacHdLen + uPadding);
-
-    // Copy the Packet into a tx Buffer
-    memcpy(pbyMacHdr, pbMPDU, cbMacHdLen);
-
-    // version set to 0, patch for hostapd deamon
-    pMACHeader->wFrameCtl &= cpu_to_le16(0xfffc);
-    memcpy(pbyPayloadHead, (pbMPDU + cbMacHdLen), cbFrameBodySize);
-
-    // replace support rate, patch for hostapd deamon( only support 11M)
-    if (WLAN_GET_FC_FSTYPE(p80211Header->sA4.wFrameCtl) == WLAN_FSTYPE_ASSOCRESP) {
-        if (cbExtSuppRate != 0) {
-            if (((PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates)->len != 0)
-                memcpy((pbyPayloadHead + cbFrameBodySize),
-                        pMgmt->abyCurrSuppRates,
-                        ((PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates)->len + WLAN_IEHDR_LEN
-                       );
-             if (((PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates)->len != 0)
-                memcpy((pbyPayloadHead + cbFrameBodySize) + ((PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates)->len + WLAN_IEHDR_LEN,
-                        pMgmt->abyCurrExtSuppRates,
-                        ((PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates)->len + WLAN_IEHDR_LEN
-                       );
-         }
-    }
-
-    // Set wep
-    if (WLAN_GET_FC_ISWEP(p80211Header->sA4.wFrameCtl) != 0) {
-
-        if (pDevice->bEnableHostWEP) {
-            pTransmitKey = &STempKey;
-            pTransmitKey->byCipherSuite = pMgmt->sNodeDBTable[uNodeIndex].byCipherSuite;
-            pTransmitKey->dwKeyIndex = pMgmt->sNodeDBTable[uNodeIndex].dwKeyIndex;
-            pTransmitKey->uKeyLength = pMgmt->sNodeDBTable[uNodeIndex].uWepKeyLength;
-            pTransmitKey->dwTSC47_16 = pMgmt->sNodeDBTable[uNodeIndex].dwTSC47_16;
-            pTransmitKey->wTSC15_0 = pMgmt->sNodeDBTable[uNodeIndex].wTSC15_0;
-            memcpy(pTransmitKey->abyKey,
-                &pMgmt->sNodeDBTable[uNodeIndex].abyWepKey[0],
-                pTransmitKey->uKeyLength
-                );
-        }
-
-        if ((pTransmitKey != NULL) && (pTransmitKey->byCipherSuite == KEY_CTL_TKIP)) {
-
-            dwMICKey0 = *(unsigned long *)(&pTransmitKey->abyKey[16]);
-            dwMICKey1 = *(unsigned long *)(&pTransmitKey->abyKey[20]);
-
-            // DO Software Michael
-            MIC_vInit(dwMICKey0, dwMICKey1);
-            MIC_vAppend((unsigned char *)&(sEthHeader.abyDstAddr[0]), 12);
-            dwMIC_Priority = 0;
-            MIC_vAppend((unsigned char *)&dwMIC_Priority, 4);
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"DMA0_tx_8021:MIC KEY: %lX, %lX\n", dwMICKey0, dwMICKey1);
-
-            uLength = cbHeaderSize + cbMacHdLen + uPadding + cbIVlen;
-
-            MIC_vAppend((pbyTxBufferAddr + uLength), cbFrameBodySize);
-
-            pdwMIC_L = (unsigned long *)(pbyTxBufferAddr + uLength + cbFrameBodySize);
-            pdwMIC_R = (unsigned long *)(pbyTxBufferAddr + uLength + cbFrameBodySize + 4);
-
-            MIC_vGetMIC(pdwMIC_L, pdwMIC_R);
-            MIC_vUnInit();
-
-            if (pDevice->bTxMICFail == true) {
-                *pdwMIC_L = 0;
-                *pdwMIC_R = 0;
-                pDevice->bTxMICFail = false;
-            }
-
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"uLength: %d, %d\n", uLength, cbFrameBodySize);
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"cbReqCount:%d, %d, %d, %d\n", cbReqCount, cbHeaderSize, uPadding, cbIVlen);
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MIC:%lx, %lx\n", *pdwMIC_L, *pdwMIC_R);
-
-        }
-
-
-        s_vFillTxKey(pDevice, (unsigned char *)(pTxBufHead->adwTxKey), pbyIVHead, pTransmitKey,
-                     pbyMacHdr, (unsigned short)cbFrameBodySize, (unsigned char *)pMICHDR);
-
-        if (pDevice->bEnableHostWEP) {
-            pMgmt->sNodeDBTable[uNodeIndex].dwTSC47_16 = pTransmitKey->dwTSC47_16;
-            pMgmt->sNodeDBTable[uNodeIndex].wTSC15_0 = pTransmitKey->wTSC15_0;
-        }
-
-        if ((pDevice->byLocalID <= REV_ID_VT3253_A1)) {
-            s_vSWencryption(pDevice, pTransmitKey, pbyPayloadHead, (unsigned short)(cbFrameBodySize + cbMIClen));
-        }
-    }
-
-    pMACHeader->wSeqCtl = cpu_to_le16(pDevice->wSeqCounter << 4);
-    pDevice->wSeqCounter++ ;
-    if (pDevice->wSeqCounter > 0x0fff)
-        pDevice->wSeqCounter = 0;
-
-
-    if (bIsPSPOLL) {
-        // The MAC will automatically replace the Duration-field of MAC header by Duration-field
-        // of  FIFO control header.
-        // This will cause AID-field of PS-POLL packet be incorrect (Because PS-POLL's AID field is
-        // in the same place of other packet's Duration-field).
-        // And it will cause Cisco-AP to issue Disassociation-packet
-        if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {
-            ((PSTxDataHead_g)pvTxDataHd)->wDuration_a = cpu_to_le16(p80211Header->sA2.wDurationID);
-            ((PSTxDataHead_g)pvTxDataHd)->wDuration_b = cpu_to_le16(p80211Header->sA2.wDurationID);
-        } else {
-            ((PSTxDataHead_ab)pvTxDataHd)->wDuration = cpu_to_le16(p80211Header->sA2.wDurationID);
-        }
-    }
-
-
-    // first TD is the only TD
-    //Set TSR1 & ReqCount in TxDescHead
-    pFrstTD->pTDInfo->skb = skb;
-    pFrstTD->m_td1TD1.byTCR = (TCR_STP | TCR_EDP | EDMSDU);
-    pFrstTD->pTDInfo->skb_dma = pFrstTD->pTDInfo->buf_dma;
-    pFrstTD->m_td1TD1.wReqCount = cpu_to_le16(cbReqCount);
-    pFrstTD->buff_addr = cpu_to_le32(pFrstTD->pTDInfo->skb_dma);
-    pFrstTD->pTDInfo->byFlags = 0;
-    pFrstTD->pTDInfo->byFlags |= TD_FLAGS_PRIV_SKB;
-
-    if (MACbIsRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_PS)) {
-        // Disable PS
-        MACbPSWakeup(pDevice->PortOffset);
-    }
-    pDevice->bPWBitOn = false;
-
-    wmb();
-    pFrstTD->m_td0TD0.f1Owner = OWNED_BY_NIC;
-    wmb();
-
-    pDevice->iTDUsed[TYPE_TXDMA0]++;
-
-    if (AVAIL_TD(pDevice, TYPE_TXDMA0) <= 1) {
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " available td0 <= 1\n");
-    }
-
-    pDevice->apCurrTD[TYPE_TXDMA0] = pFrstTD->next;
-
-    // Poll Transmit the adapter
-    MACvTransmit0(pDevice->PortOffset);
-
-    return;
+	pvRrvTime = pMICHDR = pvRTS = pvCTS = pvTxDataHd = NULL;
+
+	if (cbMPDULen <= WLAN_HDR_ADDR3_LEN) {
+		cbFrameBodySize = 0;
+	} else {
+		cbFrameBodySize = cbMPDULen - WLAN_HDR_ADDR3_LEN;
+	}
+	p80211Header = (PUWLAN_80211HDR)pbMPDU;
+
+	pFrstTD = pDevice->apCurrTD[TYPE_TXDMA0];
+	pbyTxBufferAddr = (unsigned char *)pFrstTD->pTDInfo->buf;
+	pTxBufHead = (PSTxBufHead) pbyTxBufferAddr;
+	wTxBufSize = sizeof(STxBufHead);
+	memset(pTxBufHead, 0, wTxBufSize);
+
+	if (pDevice->eCurrentPHYType == PHY_TYPE_11A) {
+		wCurrentRate = RATE_6M;
+		byPktType = PK_TYPE_11A;
+	} else {
+		wCurrentRate = RATE_1M;
+		byPktType = PK_TYPE_11B;
+	}
+
+	// SetPower will cause error power TX state for OFDM Date packet in TX buffer.
+	// 2004.11.11 Kyle -- Using OFDM power to tx MngPkt will decrease the connection capability.
+	//                    And cmd timer will wait data pkt TX to finish before scanning so it's OK
+	//                    to set power here.
+	if (pDevice->pMgmt->eScanState != WMAC_NO_SCANNING) {
+		RFbSetPower(pDevice, wCurrentRate, pDevice->byCurrentCh);
+	} else {
+		RFbSetPower(pDevice, wCurrentRate, pMgmt->uCurrChannel);
+	}
+	pTxBufHead->byTxPower = pDevice->byCurPwr;
+
+	//+++++++++++++++++++++ Patch VT3253 A1 performance +++++++++++++++++++++++++++
+	if (pDevice->byFOETuning) {
+		if ((p80211Header->sA3.wFrameCtl & TYPE_DATE_NULL) == TYPE_DATE_NULL) {
+			wCurrentRate = RATE_24M;
+			byPktType = PK_TYPE_11GA;
+		}
+	}
+
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "vDMA0_tx_80211: p80211Header->sA3.wFrameCtl = %x \n", p80211Header->sA3.wFrameCtl);
+
+	//Set packet type
+	if (byPktType == PK_TYPE_11A) {//0000 0000 0000 0000
+		pTxBufHead->wFIFOCtl = 0;
+	} else if (byPktType == PK_TYPE_11B) {//0000 0001 0000 0000
+		pTxBufHead->wFIFOCtl |= FIFOCTL_11B;
+	} else if (byPktType == PK_TYPE_11GB) {//0000 0010 0000 0000
+		pTxBufHead->wFIFOCtl |= FIFOCTL_11GB;
+	} else if (byPktType == PK_TYPE_11GA) {//0000 0011 0000 0000
+		pTxBufHead->wFIFOCtl |= FIFOCTL_11GA;
+	}
+
+	pTxBufHead->wFIFOCtl |= FIFOCTL_TMOEN;
+	pTxBufHead->wTimeStamp = cpu_to_le16(DEFAULT_MGN_LIFETIME_RES_64us);
+
+	if (is_multicast_ether_addr(&(p80211Header->sA3.abyAddr1[0]))) {
+		bNeedACK = false;
+		if (pDevice->bEnableHostWEP) {
+			uNodeIndex = 0;
+			bNodeExist = true;
+		}
+	} else {
+		if (pDevice->bEnableHostWEP) {
+			if (BSSDBbIsSTAInNodeDB(pDevice->pMgmt, (unsigned char *)(p80211Header->sA3.abyAddr1), &uNodeIndex))
+				bNodeExist = true;
+		}
+		bNeedACK = true;
+		pTxBufHead->wFIFOCtl |= FIFOCTL_NEEDACK;
+	};
+
+	if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) ||
+	    (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA)) {
+		pTxBufHead->wFIFOCtl |= FIFOCTL_LRETRY;
+	}
+
+	pTxBufHead->wFIFOCtl |= (FIFOCTL_GENINT | FIFOCTL_ISDMA0);
+
+	if ((p80211Header->sA4.wFrameCtl & TYPE_SUBTYPE_MASK) == TYPE_CTL_PSPOLL) {
+		bIsPSPOLL = true;
+		cbMacHdLen = WLAN_HDR_ADDR2_LEN;
+	} else {
+		cbMacHdLen = WLAN_HDR_ADDR3_LEN;
+	}
+
+	// hostapd deamon ext support rate patch
+	if (WLAN_GET_FC_FSTYPE(p80211Header->sA4.wFrameCtl) == WLAN_FSTYPE_ASSOCRESP) {
+		if (((PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates)->len != 0) {
+			cbExtSuppRate += ((PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates)->len + WLAN_IEHDR_LEN;
+		}
+
+		if (((PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates)->len != 0) {
+			cbExtSuppRate += ((PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates)->len + WLAN_IEHDR_LEN;
+		}
+
+		if (cbExtSuppRate > 0) {
+			cbFrameBodySize = WLAN_ASSOCRESP_OFF_SUPP_RATES;
+		}
+	}
+
+	//Set FRAGCTL_MACHDCNT
+	pTxBufHead->wFragCtl |= cpu_to_le16((unsigned short)cbMacHdLen << 10);
+
+	// Notes:
+	// Although spec says MMPDU can be fragmented; In most cases,
+	// no one will send a MMPDU under fragmentation. With RTS may occur.
+	pDevice->bAES = false;  //Set FRAGCTL_WEPTYP
+
+	if (WLAN_GET_FC_ISWEP(p80211Header->sA4.wFrameCtl) != 0) {
+		if (pDevice->eEncryptionStatus == Ndis802_11Encryption1Enabled) {
+			cbIVlen = 4;
+			cbICVlen = 4;
+			pTxBufHead->wFragCtl |= FRAGCTL_LEGACY;
+		} else if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) {
+			cbIVlen = 8;//IV+ExtIV
+			cbMIClen = 8;
+			cbICVlen = 4;
+			pTxBufHead->wFragCtl |= FRAGCTL_TKIP;
+			//We need to get seed here for filling TxKey entry.
+			//TKIPvMixKey(pTransmitKey->abyKey, pDevice->abyCurrentNetAddr,
+			//            pTransmitKey->wTSC15_0, pTransmitKey->dwTSC47_16, pDevice->abyPRNG);
+		} else if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) {
+			cbIVlen = 8;//RSN Header
+			cbICVlen = 8;//MIC
+			cbMICHDR = sizeof(SMICHDRHead);
+			pTxBufHead->wFragCtl |= FRAGCTL_AES;
+			pDevice->bAES = true;
+		}
+		//MAC Header should be padding 0 to DW alignment.
+		uPadding = 4 - (cbMacHdLen%4);
+		uPadding %= 4;
+	}
+
+	cbFrameSize = cbMacHdLen + cbFrameBodySize + cbIVlen + cbMIClen + cbICVlen + cbFCSlen + cbExtSuppRate;
+
+	//Set FIFOCTL_GrpAckPolicy
+	if (pDevice->bGrpAckPolicy == true) {//0000 0100 0000 0000
+		pTxBufHead->wFIFOCtl |=	FIFOCTL_GRPACK;
+	}
+	//the rest of pTxBufHead->wFragCtl:FragTyp will be set later in s_vFillFragParameter()
+
+	if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {//802.11g packet
+
+		pvRrvTime = (PSRrvTime_gCTS) (pbyTxBufferAddr + wTxBufSize);
+		pMICHDR = (PSMICHDRHead) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gCTS));
+		pvRTS = NULL;
+		pvCTS = (PSCTS) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gCTS) + cbMICHDR);
+		pvTxDataHd = (PSTxDataHead_g) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gCTS) + cbMICHDR + sizeof(SCTS));
+		cbHeaderSize = wTxBufSize + sizeof(SRrvTime_gCTS) + cbMICHDR + sizeof(SCTS) + sizeof(STxDataHead_g);
+
+	} else {//802.11a/b packet
+
+		pvRrvTime = (PSRrvTime_ab) (pbyTxBufferAddr + wTxBufSize);
+		pMICHDR = (PSMICHDRHead) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_ab));
+		pvRTS = NULL;
+		pvCTS = NULL;
+		pvTxDataHd = (PSTxDataHead_ab) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_ab) + cbMICHDR);
+		cbHeaderSize = wTxBufSize + sizeof(SRrvTime_ab) + cbMICHDR + sizeof(STxDataHead_ab);
+
+	}
+
+	memset((void *)(pbyTxBufferAddr + wTxBufSize), 0, (cbHeaderSize - wTxBufSize));
+	memcpy(&(sEthHeader.abyDstAddr[0]), &(p80211Header->sA3.abyAddr1[0]), ETH_ALEN);
+	memcpy(&(sEthHeader.abySrcAddr[0]), &(p80211Header->sA3.abyAddr2[0]), ETH_ALEN);
+	//=========================
+	//    No Fragmentation
+	//=========================
+	pTxBufHead->wFragCtl |= (unsigned short)FRAGCTL_NONFRAG;
+
+	//Fill FIFO,RrvTime,RTS,and CTS
+	s_vGenerateTxParameter(pDevice, byPktType, pbyTxBufferAddr, pvRrvTime, pvRTS, pvCTS,
+			       cbFrameSize, bNeedACK, TYPE_TXDMA0, &sEthHeader, wCurrentRate);
+
+	//Fill DataHead
+	uDuration = s_uFillDataHead(pDevice, byPktType, pvTxDataHd, cbFrameSize, TYPE_TXDMA0, bNeedACK,
+				    0, 0, 1, AUTO_FB_NONE, wCurrentRate);
+
+	pMACHeader = (PS802_11Header) (pbyTxBufferAddr + cbHeaderSize);
+
+	cbReqCount = cbHeaderSize + cbMacHdLen + uPadding + cbIVlen + (cbFrameBodySize + cbMIClen) + cbExtSuppRate;
+
+	pbyMacHdr = (unsigned char *)(pbyTxBufferAddr + cbHeaderSize);
+	pbyPayloadHead = (unsigned char *)(pbyMacHdr + cbMacHdLen + uPadding + cbIVlen);
+	pbyIVHead = (unsigned char *)(pbyMacHdr + cbMacHdLen + uPadding);
+
+	// Copy the Packet into a tx Buffer
+	memcpy(pbyMacHdr, pbMPDU, cbMacHdLen);
+
+	// version set to 0, patch for hostapd deamon
+	pMACHeader->wFrameCtl &= cpu_to_le16(0xfffc);
+	memcpy(pbyPayloadHead, (pbMPDU + cbMacHdLen), cbFrameBodySize);
+
+	// replace support rate, patch for hostapd deamon(only support 11M)
+	if (WLAN_GET_FC_FSTYPE(p80211Header->sA4.wFrameCtl) == WLAN_FSTYPE_ASSOCRESP) {
+		if (cbExtSuppRate != 0) {
+			if (((PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates)->len != 0)
+				memcpy((pbyPayloadHead + cbFrameBodySize),
+				       pMgmt->abyCurrSuppRates,
+				       ((PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates)->len + WLAN_IEHDR_LEN
+);
+			if (((PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates)->len != 0)
+				memcpy((pbyPayloadHead + cbFrameBodySize) + ((PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates)->len + WLAN_IEHDR_LEN,
+				       pMgmt->abyCurrExtSuppRates,
+				       ((PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates)->len + WLAN_IEHDR_LEN
+);
+		}
+	}
+
+	// Set wep
+	if (WLAN_GET_FC_ISWEP(p80211Header->sA4.wFrameCtl) != 0) {
+		if (pDevice->bEnableHostWEP) {
+			pTransmitKey = &STempKey;
+			pTransmitKey->byCipherSuite = pMgmt->sNodeDBTable[uNodeIndex].byCipherSuite;
+			pTransmitKey->dwKeyIndex = pMgmt->sNodeDBTable[uNodeIndex].dwKeyIndex;
+			pTransmitKey->uKeyLength = pMgmt->sNodeDBTable[uNodeIndex].uWepKeyLength;
+			pTransmitKey->dwTSC47_16 = pMgmt->sNodeDBTable[uNodeIndex].dwTSC47_16;
+			pTransmitKey->wTSC15_0 = pMgmt->sNodeDBTable[uNodeIndex].wTSC15_0;
+			memcpy(pTransmitKey->abyKey,
+			       &pMgmt->sNodeDBTable[uNodeIndex].abyWepKey[0],
+			       pTransmitKey->uKeyLength
+);
+		}
+
+		if ((pTransmitKey != NULL) && (pTransmitKey->byCipherSuite == KEY_CTL_TKIP)) {
+			dwMICKey0 = *(unsigned long *)(&pTransmitKey->abyKey[16]);
+			dwMICKey1 = *(unsigned long *)(&pTransmitKey->abyKey[20]);
+
+			// DO Software Michael
+			MIC_vInit(dwMICKey0, dwMICKey1);
+			MIC_vAppend((unsigned char *)&(sEthHeader.abyDstAddr[0]), 12);
+			dwMIC_Priority = 0;
+			MIC_vAppend((unsigned char *)&dwMIC_Priority, 4);
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "DMA0_tx_8021:MIC KEY: %lX, %lX\n", dwMICKey0, dwMICKey1);
+
+			uLength = cbHeaderSize + cbMacHdLen + uPadding + cbIVlen;
+
+			MIC_vAppend((pbyTxBufferAddr + uLength), cbFrameBodySize);
+
+			pdwMIC_L = (unsigned long *)(pbyTxBufferAddr + uLength + cbFrameBodySize);
+			pdwMIC_R = (unsigned long *)(pbyTxBufferAddr + uLength + cbFrameBodySize + 4);
+
+			MIC_vGetMIC(pdwMIC_L, pdwMIC_R);
+			MIC_vUnInit();
+
+			if (pDevice->bTxMICFail == true) {
+				*pdwMIC_L = 0;
+				*pdwMIC_R = 0;
+				pDevice->bTxMICFail = false;
+			}
+
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "uLength: %d, %d\n", uLength, cbFrameBodySize);
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "cbReqCount:%d, %d, %d, %d\n", cbReqCount, cbHeaderSize, uPadding, cbIVlen);
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "MIC:%lx, %lx\n", *pdwMIC_L, *pdwMIC_R);
+
+		}
+
+		s_vFillTxKey(pDevice, (unsigned char *)(pTxBufHead->adwTxKey), pbyIVHead, pTransmitKey,
+			     pbyMacHdr, (unsigned short)cbFrameBodySize, (unsigned char *)pMICHDR);
+
+		if (pDevice->bEnableHostWEP) {
+			pMgmt->sNodeDBTable[uNodeIndex].dwTSC47_16 = pTransmitKey->dwTSC47_16;
+			pMgmt->sNodeDBTable[uNodeIndex].wTSC15_0 = pTransmitKey->wTSC15_0;
+		}
+
+		if ((pDevice->byLocalID <= REV_ID_VT3253_A1)) {
+			s_vSWencryption(pDevice, pTransmitKey, pbyPayloadHead, (unsigned short)(cbFrameBodySize + cbMIClen));
+		}
+	}
+
+	pMACHeader->wSeqCtl = cpu_to_le16(pDevice->wSeqCounter << 4);
+	pDevice->wSeqCounter++;
+	if (pDevice->wSeqCounter > 0x0fff)
+		pDevice->wSeqCounter = 0;
+
+	if (bIsPSPOLL) {
+		// The MAC will automatically replace the Duration-field of MAC header by Duration-field
+		// of  FIFO control header.
+		// This will cause AID-field of PS-POLL packet be incorrect (Because PS-POLL's AID field is
+		// in the same place of other packet's Duration-field).
+		// And it will cause Cisco-AP to issue Disassociation-packet
+		if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {
+			((PSTxDataHead_g)pvTxDataHd)->wDuration_a = cpu_to_le16(p80211Header->sA2.wDurationID);
+			((PSTxDataHead_g)pvTxDataHd)->wDuration_b = cpu_to_le16(p80211Header->sA2.wDurationID);
+		} else {
+			((PSTxDataHead_ab)pvTxDataHd)->wDuration = cpu_to_le16(p80211Header->sA2.wDurationID);
+		}
+	}
+
+	// first TD is the only TD
+	//Set TSR1 & ReqCount in TxDescHead
+	pFrstTD->pTDInfo->skb = skb;
+	pFrstTD->m_td1TD1.byTCR = (TCR_STP | TCR_EDP | EDMSDU);
+	pFrstTD->pTDInfo->skb_dma = pFrstTD->pTDInfo->buf_dma;
+	pFrstTD->m_td1TD1.wReqCount = cpu_to_le16(cbReqCount);
+	pFrstTD->buff_addr = cpu_to_le32(pFrstTD->pTDInfo->skb_dma);
+	pFrstTD->pTDInfo->byFlags = 0;
+	pFrstTD->pTDInfo->byFlags |= TD_FLAGS_PRIV_SKB;
+
+	if (MACbIsRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_PS)) {
+		// Disable PS
+		MACbPSWakeup(pDevice->PortOffset);
+	}
+	pDevice->bPWBitOn = false;
+
+	wmb();
+	pFrstTD->m_td0TD0.f1Owner = OWNED_BY_NIC;
+	wmb();
+
+	pDevice->iTDUsed[TYPE_TXDMA0]++;
+
+	if (AVAIL_TD(pDevice, TYPE_TXDMA0) <= 1) {
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " available td0 <= 1\n");
+	}
+
+	pDevice->apCurrTD[TYPE_TXDMA0] = pFrstTD->next;
+
+	// Poll Transmit the adapter
+	MACvTransmit0(pDevice->PortOffset);
+
+	return;
 }
-
-
diff --git a/drivers/staging/vt6655/rxtx.h b/drivers/staging/vt6655/rxtx.h
index fa827b8..4f2cf34 100644
--- a/drivers/staging/vt6655/rxtx.h
+++ b/drivers/staging/vt6655/rxtx.h
@@ -40,45 +40,41 @@
 /*---------------------  Export Functions  --------------------------*/
 
 /*
-void
-vGenerateMACHeader(PSDevice pDevice, unsigned long dwTxBufferAddr, unsigned char *pbySkbData,
-	unsigned int cbPacketSize, bool bDMA0Used, unsigned int *pcbHeadSize,
-	unsigned int *pcbAppendPayload);
-
-void
-vProcessRxMACHeader(PSDevice pDevice, unsigned long dwRxBufferAddr, unsigned int cbPacketSize,
-	bool bIsWEP, unsigned int *pcbHeadSize);
+  void
+  vGenerateMACHeader(PSDevice pDevice, unsigned long dwTxBufferAddr, unsigned char *pbySkbData,
+  unsigned int cbPacketSize, bool bDMA0Used, unsigned int *pcbHeadSize,
+  unsigned int *pcbAppendPayload);
+
+  void
+  vProcessRxMACHeader(PSDevice pDevice, unsigned long dwRxBufferAddr, unsigned int cbPacketSize,
+  bool bIsWEP, unsigned int *pcbHeadSize);
 */
 
-
 void
-vGenerateMACHeader (
-    PSDevice         pDevice,
-    unsigned char *pbyBufferAddr,
-    unsigned short wDuration,
-    PSEthernetHeader psEthHeader,
-    bool bNeedEncrypt,
-    unsigned short wFragType,
-    unsigned int uDMAIdx,
-    unsigned int uFragIdx
-    );
-
+vGenerateMACHeader(
+	PSDevice         pDevice,
+	unsigned char *pbyBufferAddr,
+	unsigned short wDuration,
+	PSEthernetHeader psEthHeader,
+	bool bNeedEncrypt,
+	unsigned short wFragType,
+	unsigned int uDMAIdx,
+	unsigned int uFragIdx
+);
 
 unsigned int
 cbGetFragCount(
-    PSDevice         pDevice,
-    PSKeyItem        pTransmitKey,
-    unsigned int	cbFrameBodySize,
-    PSEthernetHeader psEthHeader
-    );
-
+	PSDevice         pDevice,
+	PSKeyItem        pTransmitKey,
+	unsigned int	cbFrameBodySize,
+	PSEthernetHeader psEthHeader
+);
 
 void
 vGenerateFIFOHeader(PSDevice pDevice, unsigned char byPktTyp, unsigned char *pbyTxBufferAddr,
-	bool bNeedEncrypt, unsigned int	cbPayloadSize, unsigned int uDMAIdx, PSTxDesc pHeadTD,
-	PSEthernetHeader psEthHeader, unsigned char *pPacket, PSKeyItem pTransmitKey,
-	unsigned int uNodeIndex, unsigned int *puMACfragNum, unsigned int *pcbHeaderSize);
-
+		    bool bNeedEncrypt, unsigned int	cbPayloadSize, unsigned int uDMAIdx, PSTxDesc pHeadTD,
+		    PSEthernetHeader psEthHeader, unsigned char *pPacket, PSKeyItem pTransmitKey,
+		    unsigned int uNodeIndex, unsigned int *puMACfragNum, unsigned int *pcbHeaderSize);
 
 void vDMA0_tx_80211(PSDevice  pDevice, struct sk_buff *skb, unsigned char *pbMPDU, unsigned int cbMPDULen);
 CMD_STATUS csMgmt_xmit(PSDevice pDevice, PSTxMgmtPacket pPacket);
diff --git a/drivers/staging/vt6655/srom.c b/drivers/staging/vt6655/srom.c
index 6a0a232..eaddc33 100644
--- a/drivers/staging/vt6655/srom.c
+++ b/drivers/staging/vt6655/srom.c
@@ -60,9 +60,6 @@
 
 /*---------------------  Export Functions  --------------------------*/
 
-
-
-
 /*
  * Description: Read a byte from EEPROM, by MAC I2C
  *
@@ -78,39 +75,38 @@
  */
 unsigned char SROMbyReadEmbedded(unsigned long dwIoBase, unsigned char byContntOffset)
 {
-    unsigned short wDelay, wNoACK;
-    unsigned char byWait;
-    unsigned char byData;
-    unsigned char byOrg;
-
-    byData = 0xFF;
-    VNSvInPortB(dwIoBase + MAC_REG_I2MCFG, &byOrg);
-    /* turn off hardware retry for getting NACK */
-    VNSvOutPortB(dwIoBase + MAC_REG_I2MCFG, (byOrg & (~I2MCFG_NORETRY)));
-    for (wNoACK = 0; wNoACK < W_MAX_I2CRETRY; wNoACK++) {
-        VNSvOutPortB(dwIoBase + MAC_REG_I2MTGID, EEP_I2C_DEV_ID);
-        VNSvOutPortB(dwIoBase + MAC_REG_I2MTGAD, byContntOffset);
-
-        /* issue read command */
-        VNSvOutPortB(dwIoBase + MAC_REG_I2MCSR, I2MCSR_EEMR);
-        /* wait DONE be set */
-        for (wDelay = 0; wDelay < W_MAX_TIMEOUT; wDelay++) {
-            VNSvInPortB(dwIoBase + MAC_REG_I2MCSR, &byWait);
-            if (byWait & (I2MCSR_DONE | I2MCSR_NACK))
-                break;
-            PCAvDelayByIO(CB_DELAY_LOOP_WAIT);
-        }
-        if ((wDelay < W_MAX_TIMEOUT) &&
-             ( !(byWait & I2MCSR_NACK))) {
-            break;
-        }
-    }
-    VNSvInPortB(dwIoBase + MAC_REG_I2MDIPT, &byData);
-    VNSvOutPortB(dwIoBase + MAC_REG_I2MCFG, byOrg);
-    return byData;
+	unsigned short wDelay, wNoACK;
+	unsigned char byWait;
+	unsigned char byData;
+	unsigned char byOrg;
+
+	byData = 0xFF;
+	VNSvInPortB(dwIoBase + MAC_REG_I2MCFG, &byOrg);
+	/* turn off hardware retry for getting NACK */
+	VNSvOutPortB(dwIoBase + MAC_REG_I2MCFG, (byOrg & (~I2MCFG_NORETRY)));
+	for (wNoACK = 0; wNoACK < W_MAX_I2CRETRY; wNoACK++) {
+		VNSvOutPortB(dwIoBase + MAC_REG_I2MTGID, EEP_I2C_DEV_ID);
+		VNSvOutPortB(dwIoBase + MAC_REG_I2MTGAD, byContntOffset);
+
+		/* issue read command */
+		VNSvOutPortB(dwIoBase + MAC_REG_I2MCSR, I2MCSR_EEMR);
+		/* wait DONE be set */
+		for (wDelay = 0; wDelay < W_MAX_TIMEOUT; wDelay++) {
+			VNSvInPortB(dwIoBase + MAC_REG_I2MCSR, &byWait);
+			if (byWait & (I2MCSR_DONE | I2MCSR_NACK))
+				break;
+			PCAvDelayByIO(CB_DELAY_LOOP_WAIT);
+		}
+		if ((wDelay < W_MAX_TIMEOUT) &&
+		    (!(byWait & I2MCSR_NACK))) {
+			break;
+		}
+	}
+	VNSvInPortB(dwIoBase + MAC_REG_I2MDIPT, &byData);
+	VNSvOutPortB(dwIoBase + MAC_REG_I2MCFG, byOrg);
+	return byData;
 }
 
-
 /*
  * Description: Write a byte to EEPROM, by MAC I2C
  *
@@ -127,43 +123,42 @@ unsigned char SROMbyReadEmbedded(unsigned long dwIoBase, unsigned char byContntO
  */
 bool SROMbWriteEmbedded(unsigned long dwIoBase, unsigned char byContntOffset, unsigned char byData)
 {
-    unsigned short wDelay, wNoACK;
-    unsigned char byWait;
-
-    unsigned char byOrg;
-
-    VNSvInPortB(dwIoBase + MAC_REG_I2MCFG, &byOrg);
-    /* turn off hardware retry for getting NACK */
-    VNSvOutPortB(dwIoBase + MAC_REG_I2MCFG, (byOrg & (~I2MCFG_NORETRY)));
-    for (wNoACK = 0; wNoACK < W_MAX_I2CRETRY; wNoACK++) {
-        VNSvOutPortB(dwIoBase + MAC_REG_I2MTGID, EEP_I2C_DEV_ID);
-        VNSvOutPortB(dwIoBase + MAC_REG_I2MTGAD, byContntOffset);
-        VNSvOutPortB(dwIoBase + MAC_REG_I2MDOPT, byData);
-
-        /* issue write command */
-        VNSvOutPortB(dwIoBase + MAC_REG_I2MCSR, I2MCSR_EEMW);
-        /* wait DONE be set */
-        for (wDelay = 0; wDelay < W_MAX_TIMEOUT; wDelay++) {
-            VNSvInPortB(dwIoBase + MAC_REG_I2MCSR, &byWait);
-            if (byWait & (I2MCSR_DONE | I2MCSR_NACK))
-                break;
-            PCAvDelayByIO(CB_DELAY_LOOP_WAIT);
-        }
-
-        if ((wDelay < W_MAX_TIMEOUT) &&
-             ( !(byWait & I2MCSR_NACK))) {
-            break;
-        }
-    }
-    if (wNoACK == W_MAX_I2CRETRY) {
-        VNSvOutPortB(dwIoBase + MAC_REG_I2MCFG, byOrg);
-        return false;
-    }
-    VNSvOutPortB(dwIoBase + MAC_REG_I2MCFG, byOrg);
-    return true;
+	unsigned short wDelay, wNoACK;
+	unsigned char byWait;
+
+	unsigned char byOrg;
+
+	VNSvInPortB(dwIoBase + MAC_REG_I2MCFG, &byOrg);
+	/* turn off hardware retry for getting NACK */
+	VNSvOutPortB(dwIoBase + MAC_REG_I2MCFG, (byOrg & (~I2MCFG_NORETRY)));
+	for (wNoACK = 0; wNoACK < W_MAX_I2CRETRY; wNoACK++) {
+		VNSvOutPortB(dwIoBase + MAC_REG_I2MTGID, EEP_I2C_DEV_ID);
+		VNSvOutPortB(dwIoBase + MAC_REG_I2MTGAD, byContntOffset);
+		VNSvOutPortB(dwIoBase + MAC_REG_I2MDOPT, byData);
+
+		/* issue write command */
+		VNSvOutPortB(dwIoBase + MAC_REG_I2MCSR, I2MCSR_EEMW);
+		/* wait DONE be set */
+		for (wDelay = 0; wDelay < W_MAX_TIMEOUT; wDelay++) {
+			VNSvInPortB(dwIoBase + MAC_REG_I2MCSR, &byWait);
+			if (byWait & (I2MCSR_DONE | I2MCSR_NACK))
+				break;
+			PCAvDelayByIO(CB_DELAY_LOOP_WAIT);
+		}
+
+		if ((wDelay < W_MAX_TIMEOUT) &&
+		    (!(byWait & I2MCSR_NACK))) {
+			break;
+		}
+	}
+	if (wNoACK == W_MAX_I2CRETRY) {
+		VNSvOutPortB(dwIoBase + MAC_REG_I2MCFG, byOrg);
+		return false;
+	}
+	VNSvOutPortB(dwIoBase + MAC_REG_I2MCFG, byOrg);
+	return true;
 }
 
-
 /*
  * Description: Turn bits on in eeprom
  *
@@ -180,13 +175,12 @@ bool SROMbWriteEmbedded(unsigned long dwIoBase, unsigned char byContntOffset, un
  */
 void SROMvRegBitsOn(unsigned long dwIoBase, unsigned char byContntOffset, unsigned char byBits)
 {
-    unsigned char byOrgData;
+	unsigned char byOrgData;
 
-    byOrgData = SROMbyReadEmbedded(dwIoBase, byContntOffset);
-    SROMbWriteEmbedded(dwIoBase, byContntOffset,(unsigned char)(byOrgData | byBits));
+	byOrgData = SROMbyReadEmbedded(dwIoBase, byContntOffset);
+	SROMbWriteEmbedded(dwIoBase, byContntOffset, (unsigned char)(byOrgData | byBits));
 }
 
-
 /*
  * Description: Turn bits off in eeprom
  *
@@ -201,13 +195,12 @@ void SROMvRegBitsOn(unsigned long dwIoBase, unsigned char byContntOffset, unsign
  */
 void SROMvRegBitsOff(unsigned long dwIoBase, unsigned char byContntOffset, unsigned char byBits)
 {
-    unsigned char byOrgData;
+	unsigned char byOrgData;
 
-    byOrgData = SROMbyReadEmbedded(dwIoBase, byContntOffset);
-    SROMbWriteEmbedded(dwIoBase, byContntOffset,(unsigned char)(byOrgData & (~byBits)));
+	byOrgData = SROMbyReadEmbedded(dwIoBase, byContntOffset);
+	SROMbWriteEmbedded(dwIoBase, byContntOffset, (unsigned char)(byOrgData & (~byBits)));
 }
 
-
 /*
  * Description: Test if bits on in eeprom
  *
@@ -224,13 +217,12 @@ void SROMvRegBitsOff(unsigned long dwIoBase, unsigned char byContntOffset, unsig
  */
 bool SROMbIsRegBitsOn(unsigned long dwIoBase, unsigned char byContntOffset, unsigned char byTestBits)
 {
-    unsigned char byOrgData;
+	unsigned char byOrgData;
 
-    byOrgData = SROMbyReadEmbedded(dwIoBase, byContntOffset);
-    return (byOrgData & byTestBits) == byTestBits;
+	byOrgData = SROMbyReadEmbedded(dwIoBase, byContntOffset);
+	return (byOrgData & byTestBits) == byTestBits;
 }
 
-
 /*
  * Description: Test if bits off in eeprom
  *
@@ -247,13 +239,12 @@ bool SROMbIsRegBitsOn(unsigned long dwIoBase, unsigned char byContntOffset, unsi
  */
 bool SROMbIsRegBitsOff(unsigned long dwIoBase, unsigned char byContntOffset, unsigned char byTestBits)
 {
-    unsigned char byOrgData;
+	unsigned char byOrgData;
 
-    byOrgData = SROMbyReadEmbedded(dwIoBase, byContntOffset);
-    return !(byOrgData & byTestBits);
+	byOrgData = SROMbyReadEmbedded(dwIoBase, byContntOffset);
+	return !(byOrgData & byTestBits);
 }
 
-
 /*
  * Description: Read all contents of eeprom to buffer
  *
@@ -268,16 +259,15 @@ bool SROMbIsRegBitsOff(unsigned long dwIoBase, unsigned char byContntOffset, uns
  */
 void SROMvReadAllContents(unsigned long dwIoBase, unsigned char *pbyEepromRegs)
 {
-    int     ii;
+	int     ii;
 
-    /* ii = Rom Address */
-    for (ii = 0; ii < EEP_MAX_CONTEXT_SIZE; ii++) {
-        *pbyEepromRegs = SROMbyReadEmbedded(dwIoBase,(unsigned char) ii);
-        pbyEepromRegs++;
-    }
+	/* ii = Rom Address */
+	for (ii = 0; ii < EEP_MAX_CONTEXT_SIZE; ii++) {
+		*pbyEepromRegs = SROMbyReadEmbedded(dwIoBase, (unsigned char)ii);
+		pbyEepromRegs++;
+	}
 }
 
-
 /*
  * Description: Write all contents of buffer to eeprom
  *
@@ -293,16 +283,15 @@ void SROMvReadAllContents(unsigned long dwIoBase, unsigned char *pbyEepromRegs)
  */
 void SROMvWriteAllContents(unsigned long dwIoBase, unsigned char *pbyEepromRegs)
 {
-    int     ii;
+	int     ii;
 
-    /* ii = Rom Address */
-    for (ii = 0; ii < EEP_MAX_CONTEXT_SIZE; ii++) {
-        SROMbWriteEmbedded(dwIoBase,(unsigned char) ii, *pbyEepromRegs);
-        pbyEepromRegs++;
-    }
+	/* ii = Rom Address */
+	for (ii = 0; ii < EEP_MAX_CONTEXT_SIZE; ii++) {
+		SROMbWriteEmbedded(dwIoBase, (unsigned char)ii, *pbyEepromRegs);
+		pbyEepromRegs++;
+	}
 }
 
-
 /*
  * Description: Read Ethernet Address from eeprom to buffer
  *
@@ -317,16 +306,15 @@ void SROMvWriteAllContents(unsigned long dwIoBase, unsigned char *pbyEepromRegs)
  */
 void SROMvReadEtherAddress(unsigned long dwIoBase, unsigned char *pbyEtherAddress)
 {
-    unsigned char ii;
+	unsigned char ii;
 
-    /* ii = Rom Address */
-    for (ii = 0; ii < ETH_ALEN; ii++) {
-        *pbyEtherAddress = SROMbyReadEmbedded(dwIoBase, ii);
-        pbyEtherAddress++;
-    }
+	/* ii = Rom Address */
+	for (ii = 0; ii < ETH_ALEN; ii++) {
+		*pbyEtherAddress = SROMbyReadEmbedded(dwIoBase, ii);
+		pbyEtherAddress++;
+	}
 }
 
-
 /*
  * Description: Write Ethernet Address from buffer to eeprom
  *
@@ -342,16 +330,15 @@ void SROMvReadEtherAddress(unsigned long dwIoBase, unsigned char *pbyEtherAddres
  */
 void SROMvWriteEtherAddress(unsigned long dwIoBase, unsigned char *pbyEtherAddress)
 {
-    unsigned char ii;
+	unsigned char ii;
 
-    /* ii = Rom Address */
-    for (ii = 0; ii < ETH_ALEN; ii++) {
-        SROMbWriteEmbedded(dwIoBase, ii, *pbyEtherAddress);
-        pbyEtherAddress++;
-    }
+	/* ii = Rom Address */
+	for (ii = 0; ii < ETH_ALEN; ii++) {
+		SROMbWriteEmbedded(dwIoBase, ii, *pbyEtherAddress);
+		pbyEtherAddress++;
+	}
 }
 
-
 /*
  * Description: Read Sub_VID and Sub_SysId from eeprom to buffer
  *
@@ -366,15 +353,15 @@ void SROMvWriteEtherAddress(unsigned long dwIoBase, unsigned char *pbyEtherAddre
  */
 void SROMvReadSubSysVenId(unsigned long dwIoBase, unsigned long *pdwSubSysVenId)
 {
-    unsigned char *pbyData;
-
-    pbyData = (unsigned char *)pdwSubSysVenId;
-    /* sub vendor */
-    *pbyData = SROMbyReadEmbedded(dwIoBase, 6);
-    *(pbyData+1) = SROMbyReadEmbedded(dwIoBase, 7);
-    /* sub system */
-    *(pbyData+2) = SROMbyReadEmbedded(dwIoBase, 8);
-    *(pbyData+3) = SROMbyReadEmbedded(dwIoBase, 9);
+	unsigned char *pbyData;
+
+	pbyData = (unsigned char *)pdwSubSysVenId;
+	/* sub vendor */
+	*pbyData = SROMbyReadEmbedded(dwIoBase, 6);
+	*(pbyData+1) = SROMbyReadEmbedded(dwIoBase, 7);
+	/* sub system */
+	*(pbyData+2) = SROMbyReadEmbedded(dwIoBase, 8);
+	*(pbyData+3) = SROMbyReadEmbedded(dwIoBase, 9);
 }
 
 /*
@@ -391,30 +378,28 @@ void SROMvReadSubSysVenId(unsigned long dwIoBase, unsigned long *pdwSubSysVenId)
  */
 bool SROMbAutoLoad(unsigned long dwIoBase)
 {
-    unsigned char byWait;
-    int     ii;
+	unsigned char byWait;
+	int     ii;
 
-    unsigned char byOrg;
+	unsigned char byOrg;
 
-    VNSvInPortB(dwIoBase + MAC_REG_I2MCFG, &byOrg);
-    /* turn on hardware retry */
-    VNSvOutPortB(dwIoBase + MAC_REG_I2MCFG, (byOrg | I2MCFG_NORETRY));
+	VNSvInPortB(dwIoBase + MAC_REG_I2MCFG, &byOrg);
+	/* turn on hardware retry */
+	VNSvOutPortB(dwIoBase + MAC_REG_I2MCFG, (byOrg | I2MCFG_NORETRY));
 
-    MACvRegBitsOn(dwIoBase, MAC_REG_I2MCSR, I2MCSR_AUTOLD);
+	MACvRegBitsOn(dwIoBase, MAC_REG_I2MCSR, I2MCSR_AUTOLD);
 
-    /* ii = Rom Address */
-    for (ii = 0; ii < EEP_MAX_CONTEXT_SIZE; ii++) {
-        MACvTimer0MicroSDelay(dwIoBase, CB_EEPROM_READBYTE_WAIT);
-        VNSvInPortB(dwIoBase + MAC_REG_I2MCSR, &byWait);
-        if ( !(byWait & I2MCSR_AUTOLD))
-            break;
-    }
+	/* ii = Rom Address */
+	for (ii = 0; ii < EEP_MAX_CONTEXT_SIZE; ii++) {
+		MACvTimer0MicroSDelay(dwIoBase, CB_EEPROM_READBYTE_WAIT);
+		VNSvInPortB(dwIoBase + MAC_REG_I2MCSR, &byWait);
+		if (!(byWait & I2MCSR_AUTOLD))
+			break;
+	}
 
-    VNSvOutPortB(dwIoBase + MAC_REG_I2MCFG, byOrg);
+	VNSvOutPortB(dwIoBase + MAC_REG_I2MCFG, byOrg);
 
-    if (ii == EEP_MAX_CONTEXT_SIZE)
-        return false;
-    return true;
+	if (ii == EEP_MAX_CONTEXT_SIZE)
+		return false;
+	return true;
 }
-
-
diff --git a/drivers/staging/vt6655/srom.h b/drivers/staging/vt6655/srom.h
index 4c261da..1df58c5 100644
--- a/drivers/staging/vt6655/srom.h
+++ b/drivers/staging/vt6655/srom.h
@@ -69,7 +69,6 @@
 //}}
 #define EEP_OFS_OFDMA_PWR_dBm       0xD2
 
-
 //----------need to remove --------------------
 #define EEP_OFS_BBTAB_LEN   0x70        // BB Table Length
 #define EEP_OFS_BBTAB_ADR   0x71        // BB Table Offset
@@ -77,7 +76,6 @@
 
 #define EEP_I2C_DEV_ID      0x50        // EEPROM device address on the I2C bus
 
-
 //
 // Bits in EEP_OFS_ANTENNA
 //
@@ -97,34 +95,34 @@
 //      2048 bits = 256 bytes = 128 words
 //
 typedef struct tagSSromReg {
-    unsigned char abyPAR[6];                  // 0x00 (unsigned short)
-
-    unsigned short wSUB_VID;                   // 0x03 (unsigned short)
-    unsigned short wSUB_SID;
-
-    unsigned char byBCFG0;                    // 0x05 (unsigned short)
-    unsigned char byBCFG1;
-
-    unsigned char byFCR0;                     // 0x06 (unsigned short)
-    unsigned char byFCR1;
-    unsigned char byPMC0;                     // 0x07 (unsigned short)
-    unsigned char byPMC1;
-    unsigned char byMAXLAT;                   // 0x08 (unsigned short)
-    unsigned char byMINGNT;
-    unsigned char byCFG0;                     // 0x09 (unsigned short)
-    unsigned char byCFG1;
-    unsigned short wCISPTR;                    // 0x0A (unsigned short)
-    unsigned short wRsv0;                      // 0x0B (unsigned short)
-    unsigned short wRsv1;                      // 0x0C (unsigned short)
-    unsigned char byBBPAIR;                   // 0x0D (unsigned short)
-    unsigned char byRFTYPE;
-    unsigned char byMinChannel;               // 0x0E (unsigned short)
-    unsigned char byMaxChannel;
-    unsigned char bySignature;                // 0x0F (unsigned short)
-    unsigned char byCheckSum;
-
-    unsigned char abyReserved0[96];           // 0x10 (unsigned short)
-    unsigned char abyCIS[128];                // 0x80 (unsigned short)
+	unsigned char abyPAR[6];                  // 0x00 (unsigned short)
+
+	unsigned short wSUB_VID;                   // 0x03 (unsigned short)
+	unsigned short wSUB_SID;
+
+	unsigned char byBCFG0;                    // 0x05 (unsigned short)
+	unsigned char byBCFG1;
+
+	unsigned char byFCR0;                     // 0x06 (unsigned short)
+	unsigned char byFCR1;
+	unsigned char byPMC0;                     // 0x07 (unsigned short)
+	unsigned char byPMC1;
+	unsigned char byMAXLAT;                   // 0x08 (unsigned short)
+	unsigned char byMINGNT;
+	unsigned char byCFG0;                     // 0x09 (unsigned short)
+	unsigned char byCFG1;
+	unsigned short wCISPTR;                    // 0x0A (unsigned short)
+	unsigned short wRsv0;                      // 0x0B (unsigned short)
+	unsigned short wRsv1;                      // 0x0C (unsigned short)
+	unsigned char byBBPAIR;                   // 0x0D (unsigned short)
+	unsigned char byRFTYPE;
+	unsigned char byMinChannel;               // 0x0E (unsigned short)
+	unsigned char byMaxChannel;
+	unsigned char bySignature;                // 0x0F (unsigned short)
+	unsigned char byCheckSum;
+
+	unsigned char abyReserved0[96];           // 0x10 (unsigned short)
+	unsigned char abyCIS[128];                // 0x80 (unsigned short)
 } SSromReg, *PSSromReg;
 
 /*---------------------  Export Macros ------------------------------*/
@@ -152,6 +150,6 @@ void SROMvWriteEtherAddress(unsigned long dwIoBase, unsigned char *pbyEtherAddre
 
 void SROMvReadSubSysVenId(unsigned long dwIoBase, unsigned long *pdwSubSysVenId);
 
-bool SROMbAutoLoad (unsigned long dwIoBase);
+bool SROMbAutoLoad(unsigned long dwIoBase);
 
 #endif // __EEPROM_H__
diff --git a/drivers/staging/vt6655/tcrc.c b/drivers/staging/vt6655/tcrc.c
index 1313c4c..ed6868a 100644
--- a/drivers/staging/vt6655/tcrc.c
+++ b/drivers/staging/vt6655/tcrc.c
@@ -43,79 +43,76 @@
 
 // 32-bit CRC table
 static const unsigned long s_adwCrc32Table[256] = {
-    0x00000000L, 0x77073096L, 0xEE0E612CL, 0x990951BAL,
-    0x076DC419L, 0x706AF48FL, 0xE963A535L, 0x9E6495A3L,
-    0x0EDB8832L, 0x79DCB8A4L, 0xE0D5E91EL, 0x97D2D988L,
-    0x09B64C2BL, 0x7EB17CBDL, 0xE7B82D07L, 0x90BF1D91L,
-    0x1DB71064L, 0x6AB020F2L, 0xF3B97148L, 0x84BE41DEL,
-    0x1ADAD47DL, 0x6DDDE4EBL, 0xF4D4B551L, 0x83D385C7L,
-    0x136C9856L, 0x646BA8C0L, 0xFD62F97AL, 0x8A65C9ECL,
-    0x14015C4FL, 0x63066CD9L, 0xFA0F3D63L, 0x8D080DF5L,
-    0x3B6E20C8L, 0x4C69105EL, 0xD56041E4L, 0xA2677172L,
-    0x3C03E4D1L, 0x4B04D447L, 0xD20D85FDL, 0xA50AB56BL,
-    0x35B5A8FAL, 0x42B2986CL, 0xDBBBC9D6L, 0xACBCF940L,
-    0x32D86CE3L, 0x45DF5C75L, 0xDCD60DCFL, 0xABD13D59L,
-    0x26D930ACL, 0x51DE003AL, 0xC8D75180L, 0xBFD06116L,
-    0x21B4F4B5L, 0x56B3C423L, 0xCFBA9599L, 0xB8BDA50FL,
-    0x2802B89EL, 0x5F058808L, 0xC60CD9B2L, 0xB10BE924L,
-    0x2F6F7C87L, 0x58684C11L, 0xC1611DABL, 0xB6662D3DL,
-    0x76DC4190L, 0x01DB7106L, 0x98D220BCL, 0xEFD5102AL,
-    0x71B18589L, 0x06B6B51FL, 0x9FBFE4A5L, 0xE8B8D433L,
-    0x7807C9A2L, 0x0F00F934L, 0x9609A88EL, 0xE10E9818L,
-    0x7F6A0DBBL, 0x086D3D2DL, 0x91646C97L, 0xE6635C01L,
-    0x6B6B51F4L, 0x1C6C6162L, 0x856530D8L, 0xF262004EL,
-    0x6C0695EDL, 0x1B01A57BL, 0x8208F4C1L, 0xF50FC457L,
-    0x65B0D9C6L, 0x12B7E950L, 0x8BBEB8EAL, 0xFCB9887CL,
-    0x62DD1DDFL, 0x15DA2D49L, 0x8CD37CF3L, 0xFBD44C65L,
-    0x4DB26158L, 0x3AB551CEL, 0xA3BC0074L, 0xD4BB30E2L,
-    0x4ADFA541L, 0x3DD895D7L, 0xA4D1C46DL, 0xD3D6F4FBL,
-    0x4369E96AL, 0x346ED9FCL, 0xAD678846L, 0xDA60B8D0L,
-    0x44042D73L, 0x33031DE5L, 0xAA0A4C5FL, 0xDD0D7CC9L,
-    0x5005713CL, 0x270241AAL, 0xBE0B1010L, 0xC90C2086L,
-    0x5768B525L, 0x206F85B3L, 0xB966D409L, 0xCE61E49FL,
-    0x5EDEF90EL, 0x29D9C998L, 0xB0D09822L, 0xC7D7A8B4L,
-    0x59B33D17L, 0x2EB40D81L, 0xB7BD5C3BL, 0xC0BA6CADL,
-    0xEDB88320L, 0x9ABFB3B6L, 0x03B6E20CL, 0x74B1D29AL,
-    0xEAD54739L, 0x9DD277AFL, 0x04DB2615L, 0x73DC1683L,
-    0xE3630B12L, 0x94643B84L, 0x0D6D6A3EL, 0x7A6A5AA8L,
-    0xE40ECF0BL, 0x9309FF9DL, 0x0A00AE27L, 0x7D079EB1L,
-    0xF00F9344L, 0x8708A3D2L, 0x1E01F268L, 0x6906C2FEL,
-    0xF762575DL, 0x806567CBL, 0x196C3671L, 0x6E6B06E7L,
-    0xFED41B76L, 0x89D32BE0L, 0x10DA7A5AL, 0x67DD4ACCL,
-    0xF9B9DF6FL, 0x8EBEEFF9L, 0x17B7BE43L, 0x60B08ED5L,
-    0xD6D6A3E8L, 0xA1D1937EL, 0x38D8C2C4L, 0x4FDFF252L,
-    0xD1BB67F1L, 0xA6BC5767L, 0x3FB506DDL, 0x48B2364BL,
-    0xD80D2BDAL, 0xAF0A1B4CL, 0x36034AF6L, 0x41047A60L,
-    0xDF60EFC3L, 0xA867DF55L, 0x316E8EEFL, 0x4669BE79L,
-    0xCB61B38CL, 0xBC66831AL, 0x256FD2A0L, 0x5268E236L,
-    0xCC0C7795L, 0xBB0B4703L, 0x220216B9L, 0x5505262FL,
-    0xC5BA3BBEL, 0xB2BD0B28L, 0x2BB45A92L, 0x5CB36A04L,
-    0xC2D7FFA7L, 0xB5D0CF31L, 0x2CD99E8BL, 0x5BDEAE1DL,
-    0x9B64C2B0L, 0xEC63F226L, 0x756AA39CL, 0x026D930AL,
-    0x9C0906A9L, 0xEB0E363FL, 0x72076785L, 0x05005713L,
-    0x95BF4A82L, 0xE2B87A14L, 0x7BB12BAEL, 0x0CB61B38L,
-    0x92D28E9BL, 0xE5D5BE0DL, 0x7CDCEFB7L, 0x0BDBDF21L,
-    0x86D3D2D4L, 0xF1D4E242L, 0x68DDB3F8L, 0x1FDA836EL,
-    0x81BE16CDL, 0xF6B9265BL, 0x6FB077E1L, 0x18B74777L,
-    0x88085AE6L, 0xFF0F6A70L, 0x66063BCAL, 0x11010B5CL,
-    0x8F659EFFL, 0xF862AE69L, 0x616BFFD3L, 0x166CCF45L,
-    0xA00AE278L, 0xD70DD2EEL, 0x4E048354L, 0x3903B3C2L,
-    0xA7672661L, 0xD06016F7L, 0x4969474DL, 0x3E6E77DBL,
-    0xAED16A4AL, 0xD9D65ADCL, 0x40DF0B66L, 0x37D83BF0L,
-    0xA9BCAE53L, 0xDEBB9EC5L, 0x47B2CF7FL, 0x30B5FFE9L,
-    0xBDBDF21CL, 0xCABAC28AL, 0x53B39330L, 0x24B4A3A6L,
-    0xBAD03605L, 0xCDD70693L, 0x54DE5729L, 0x23D967BFL,
-    0xB3667A2EL, 0xC4614AB8L, 0x5D681B02L, 0x2A6F2B94L,
-    0xB40BBE37L, 0xC30C8EA1L, 0x5A05DF1BL, 0x2D02EF8DL
+	0x00000000L, 0x77073096L, 0xEE0E612CL, 0x990951BAL,
+	0x076DC419L, 0x706AF48FL, 0xE963A535L, 0x9E6495A3L,
+	0x0EDB8832L, 0x79DCB8A4L, 0xE0D5E91EL, 0x97D2D988L,
+	0x09B64C2BL, 0x7EB17CBDL, 0xE7B82D07L, 0x90BF1D91L,
+	0x1DB71064L, 0x6AB020F2L, 0xF3B97148L, 0x84BE41DEL,
+	0x1ADAD47DL, 0x6DDDE4EBL, 0xF4D4B551L, 0x83D385C7L,
+	0x136C9856L, 0x646BA8C0L, 0xFD62F97AL, 0x8A65C9ECL,
+	0x14015C4FL, 0x63066CD9L, 0xFA0F3D63L, 0x8D080DF5L,
+	0x3B6E20C8L, 0x4C69105EL, 0xD56041E4L, 0xA2677172L,
+	0x3C03E4D1L, 0x4B04D447L, 0xD20D85FDL, 0xA50AB56BL,
+	0x35B5A8FAL, 0x42B2986CL, 0xDBBBC9D6L, 0xACBCF940L,
+	0x32D86CE3L, 0x45DF5C75L, 0xDCD60DCFL, 0xABD13D59L,
+	0x26D930ACL, 0x51DE003AL, 0xC8D75180L, 0xBFD06116L,
+	0x21B4F4B5L, 0x56B3C423L, 0xCFBA9599L, 0xB8BDA50FL,
+	0x2802B89EL, 0x5F058808L, 0xC60CD9B2L, 0xB10BE924L,
+	0x2F6F7C87L, 0x58684C11L, 0xC1611DABL, 0xB6662D3DL,
+	0x76DC4190L, 0x01DB7106L, 0x98D220BCL, 0xEFD5102AL,
+	0x71B18589L, 0x06B6B51FL, 0x9FBFE4A5L, 0xE8B8D433L,
+	0x7807C9A2L, 0x0F00F934L, 0x9609A88EL, 0xE10E9818L,
+	0x7F6A0DBBL, 0x086D3D2DL, 0x91646C97L, 0xE6635C01L,
+	0x6B6B51F4L, 0x1C6C6162L, 0x856530D8L, 0xF262004EL,
+	0x6C0695EDL, 0x1B01A57BL, 0x8208F4C1L, 0xF50FC457L,
+	0x65B0D9C6L, 0x12B7E950L, 0x8BBEB8EAL, 0xFCB9887CL,
+	0x62DD1DDFL, 0x15DA2D49L, 0x8CD37CF3L, 0xFBD44C65L,
+	0x4DB26158L, 0x3AB551CEL, 0xA3BC0074L, 0xD4BB30E2L,
+	0x4ADFA541L, 0x3DD895D7L, 0xA4D1C46DL, 0xD3D6F4FBL,
+	0x4369E96AL, 0x346ED9FCL, 0xAD678846L, 0xDA60B8D0L,
+	0x44042D73L, 0x33031DE5L, 0xAA0A4C5FL, 0xDD0D7CC9L,
+	0x5005713CL, 0x270241AAL, 0xBE0B1010L, 0xC90C2086L,
+	0x5768B525L, 0x206F85B3L, 0xB966D409L, 0xCE61E49FL,
+	0x5EDEF90EL, 0x29D9C998L, 0xB0D09822L, 0xC7D7A8B4L,
+	0x59B33D17L, 0x2EB40D81L, 0xB7BD5C3BL, 0xC0BA6CADL,
+	0xEDB88320L, 0x9ABFB3B6L, 0x03B6E20CL, 0x74B1D29AL,
+	0xEAD54739L, 0x9DD277AFL, 0x04DB2615L, 0x73DC1683L,
+	0xE3630B12L, 0x94643B84L, 0x0D6D6A3EL, 0x7A6A5AA8L,
+	0xE40ECF0BL, 0x9309FF9DL, 0x0A00AE27L, 0x7D079EB1L,
+	0xF00F9344L, 0x8708A3D2L, 0x1E01F268L, 0x6906C2FEL,
+	0xF762575DL, 0x806567CBL, 0x196C3671L, 0x6E6B06E7L,
+	0xFED41B76L, 0x89D32BE0L, 0x10DA7A5AL, 0x67DD4ACCL,
+	0xF9B9DF6FL, 0x8EBEEFF9L, 0x17B7BE43L, 0x60B08ED5L,
+	0xD6D6A3E8L, 0xA1D1937EL, 0x38D8C2C4L, 0x4FDFF252L,
+	0xD1BB67F1L, 0xA6BC5767L, 0x3FB506DDL, 0x48B2364BL,
+	0xD80D2BDAL, 0xAF0A1B4CL, 0x36034AF6L, 0x41047A60L,
+	0xDF60EFC3L, 0xA867DF55L, 0x316E8EEFL, 0x4669BE79L,
+	0xCB61B38CL, 0xBC66831AL, 0x256FD2A0L, 0x5268E236L,
+	0xCC0C7795L, 0xBB0B4703L, 0x220216B9L, 0x5505262FL,
+	0xC5BA3BBEL, 0xB2BD0B28L, 0x2BB45A92L, 0x5CB36A04L,
+	0xC2D7FFA7L, 0xB5D0CF31L, 0x2CD99E8BL, 0x5BDEAE1DL,
+	0x9B64C2B0L, 0xEC63F226L, 0x756AA39CL, 0x026D930AL,
+	0x9C0906A9L, 0xEB0E363FL, 0x72076785L, 0x05005713L,
+	0x95BF4A82L, 0xE2B87A14L, 0x7BB12BAEL, 0x0CB61B38L,
+	0x92D28E9BL, 0xE5D5BE0DL, 0x7CDCEFB7L, 0x0BDBDF21L,
+	0x86D3D2D4L, 0xF1D4E242L, 0x68DDB3F8L, 0x1FDA836EL,
+	0x81BE16CDL, 0xF6B9265BL, 0x6FB077E1L, 0x18B74777L,
+	0x88085AE6L, 0xFF0F6A70L, 0x66063BCAL, 0x11010B5CL,
+	0x8F659EFFL, 0xF862AE69L, 0x616BFFD3L, 0x166CCF45L,
+	0xA00AE278L, 0xD70DD2EEL, 0x4E048354L, 0x3903B3C2L,
+	0xA7672661L, 0xD06016F7L, 0x4969474DL, 0x3E6E77DBL,
+	0xAED16A4AL, 0xD9D65ADCL, 0x40DF0B66L, 0x37D83BF0L,
+	0xA9BCAE53L, 0xDEBB9EC5L, 0x47B2CF7FL, 0x30B5FFE9L,
+	0xBDBDF21CL, 0xCABAC28AL, 0x53B39330L, 0x24B4A3A6L,
+	0xBAD03605L, 0xCDD70693L, 0x54DE5729L, 0x23D967BFL,
+	0xB3667A2EL, 0xC4614AB8L, 0x5D681B02L, 0x2A6F2B94L,
+	0xB40BBE37L, 0xC30C8EA1L, 0x5A05DF1BL, 0x2D02EF8DL
 };
 
 /*---------------------  Static Functions  --------------------------*/
 
 /*---------------------  Export Variables  --------------------------*/
 
-
-
-
 /*+
  *
  * Description:
@@ -131,21 +128,20 @@ static const unsigned long s_adwCrc32Table[256] = {
  *
  * Return Value: CRC-32
  *
--*/
-unsigned long CRCdwCrc32 (unsigned char *pbyData, unsigned int cbByte, unsigned long dwCrcSeed)
+ -*/
+unsigned long CRCdwCrc32(unsigned char *pbyData, unsigned int cbByte, unsigned long dwCrcSeed)
 {
-    unsigned long dwCrc;
+	unsigned long dwCrc;
 
-    dwCrc = dwCrcSeed;
-    while (cbByte--) {
-        dwCrc = s_adwCrc32Table[(unsigned char)((dwCrc ^ (*pbyData)) & 0xFF)] ^ (dwCrc >> 8);
-        pbyData++;
-    }
+	dwCrc = dwCrcSeed;
+	while (cbByte--) {
+		dwCrc = s_adwCrc32Table[(unsigned char)((dwCrc ^ (*pbyData)) & 0xFF)] ^ (dwCrc >> 8);
+		pbyData++;
+	}
 
-    return dwCrc;
+	return dwCrc;
 }
 
-
 /*+
  *
  * Description:
@@ -163,13 +159,12 @@ unsigned long CRCdwCrc32 (unsigned char *pbyData, unsigned int cbByte, unsigned
  *
  * Return Value: CRC-32
  *
--*/
-unsigned long CRCdwGetCrc32 (unsigned char *pbyData, unsigned int cbByte)
+ -*/
+unsigned long CRCdwGetCrc32(unsigned char *pbyData, unsigned int cbByte)
 {
-    return ~CRCdwCrc32(pbyData, cbByte, 0xFFFFFFFFL);
+	return ~CRCdwCrc32(pbyData, cbByte, 0xFFFFFFFFL);
 }
 
-
 /*+
  *
  * Description:
@@ -189,10 +184,8 @@ unsigned long CRCdwGetCrc32 (unsigned char *pbyData, unsigned int cbByte)
  *
  * Return Value: CRC-32
  *
--*/
+ -*/
 unsigned long CRCdwGetCrc32Ex(unsigned char *pbyData, unsigned int cbByte, unsigned long dwPreCRC)
 {
-    return CRCdwCrc32(pbyData, cbByte, dwPreCRC);
+	return CRCdwCrc32(pbyData, cbByte, dwPreCRC);
 }
-
-
diff --git a/drivers/staging/vt6655/tcrc.h b/drivers/staging/vt6655/tcrc.h
index a204421..82b5dda 100644
--- a/drivers/staging/vt6655/tcrc.h
+++ b/drivers/staging/vt6655/tcrc.h
@@ -48,6 +48,3 @@ unsigned long CRCdwGetCrc32(unsigned char *pbyData, unsigned int cbByte);
 unsigned long CRCdwGetCrc32Ex(unsigned char *pbyData, unsigned int cbByte, unsigned long dwPreCRC);
 
 #endif // __TCRC_H__
-
-
-
diff --git a/drivers/staging/vt6655/tether.c b/drivers/staging/vt6655/tether.c
index 28554bf..a5dc3c09 100644
--- a/drivers/staging/vt6655/tether.c
+++ b/drivers/staging/vt6655/tether.c
@@ -47,8 +47,6 @@
 
 /*---------------------  Export Variables  --------------------------*/
 
-
-
 /*
  * Description: Calculate multicast hash value by CRC32
  *
@@ -61,28 +59,27 @@
  * Return Value: Hash value
  *
  */
-unsigned char ETHbyGetHashIndexByCrc32 (unsigned char *pbyMultiAddr)
+unsigned char ETHbyGetHashIndexByCrc32(unsigned char *pbyMultiAddr)
 {
-    int     ii;
-    unsigned char byTmpHash;
-    unsigned char byHash = 0;
+	int     ii;
+	unsigned char byTmpHash;
+	unsigned char byHash = 0;
 
-    // get the least 6-bits from CRC generator
-    byTmpHash = (unsigned char)(CRCdwCrc32(pbyMultiAddr, ETH_ALEN,
-            0xFFFFFFFFL) & 0x3F);
-    // reverse most bit to least bit
-    for (ii = 0; ii < (sizeof(byTmpHash) * 8); ii++) {
-        byHash <<= 1;
-        if (byTmpHash & 0x01)
-            byHash |= 1;
-        byTmpHash >>= 1;
-    }
+	// get the least 6-bits from CRC generator
+	byTmpHash = (unsigned char)(CRCdwCrc32(pbyMultiAddr, ETH_ALEN,
+					       0xFFFFFFFFL) & 0x3F);
+	// reverse most bit to least bit
+	for (ii = 0; ii < (sizeof(byTmpHash) * 8); ii++) {
+		byHash <<= 1;
+		if (byTmpHash & 0x01)
+			byHash |= 1;
+		byTmpHash >>= 1;
+	}
 
-    // adjust 6-bits to the right most
-    return (byHash >> 2);
+	// adjust 6-bits to the right most
+	return byHash >> 2;
 }
 
-
 /*
  * Description: Check CRC value of the buffer if Ok or not
  *
@@ -96,14 +93,13 @@ unsigned char ETHbyGetHashIndexByCrc32 (unsigned char *pbyMultiAddr)
  * Return Value: true if ok; false if error.
  *
  */
-bool ETHbIsBufferCrc32Ok (unsigned char *pbyBuffer, unsigned int cbFrameLength)
+bool ETHbIsBufferCrc32Ok(unsigned char *pbyBuffer, unsigned int cbFrameLength)
 {
-    unsigned long dwCRC;
+	unsigned long dwCRC;
 
-    dwCRC = CRCdwGetCrc32(pbyBuffer, cbFrameLength - 4);
-    if (cpu_to_le32(*((unsigned long *)(pbyBuffer + cbFrameLength - 4))) != dwCRC) {
-        return false;
-    }
-    return true;
+	dwCRC = CRCdwGetCrc32(pbyBuffer, cbFrameLength - 4);
+	if (cpu_to_le32(*((unsigned long *)(pbyBuffer + cbFrameLength - 4))) != dwCRC) {
+		return false;
+	}
+	return true;
 }
-
diff --git a/drivers/staging/vt6655/tether.h b/drivers/staging/vt6655/tether.h
index 6a68f97..94cc883 100644
--- a/drivers/staging/vt6655/tether.h
+++ b/drivers/staging/vt6655/tether.h
@@ -37,13 +37,12 @@
 // constants
 //
 #define U_ETHER_ADDR_STR_LEN (ETH_ALEN * 2 + 1)
-                                        // Ethernet address string length
+// Ethernet address string length
 
 #define MAX_LOOKAHEAD_SIZE  ETH_FRAME_LEN
 
 #define U_MULTI_ADDR_LEN    8           // multicast address length
 
-
 #ifdef __BIG_ENDIAN
 
 #define TYPE_PKT_IP         0x0800      //
@@ -89,7 +88,6 @@
 #define TYPE_CTL_CTS        0xc400
 #define TYPE_CTL_ACK        0xd400
 
-
 #else //if LITTLE_ENDIAN
 //
 // wType field in the SEthernetHeader
@@ -140,8 +138,6 @@
 #define TYPE_CTL_CTS        0x00c4
 #define TYPE_CTL_ACK        0x00d4
 
-
-
 #endif //#ifdef __BIG_ENDIAN
 
 #define WEP_IV_MASK         0x00FFFFFF
@@ -151,35 +147,34 @@
 // Ethernet packet
 //
 typedef struct tagSEthernetHeader {
-    unsigned char abyDstAddr[ETH_ALEN];
-    unsigned char abySrcAddr[ETH_ALEN];
-    unsigned short wType;
-}__attribute__ ((__packed__))
+	unsigned char abyDstAddr[ETH_ALEN];
+	unsigned char abySrcAddr[ETH_ALEN];
+	unsigned short wType;
+} __attribute__ ((__packed__))
 SEthernetHeader, *PSEthernetHeader;
 
-
 //
 // 802_3 packet
 //
 typedef struct tagS802_3Header {
-    unsigned char abyDstAddr[ETH_ALEN];
-    unsigned char abySrcAddr[ETH_ALEN];
-    unsigned short wLen;
-}__attribute__ ((__packed__))
+	unsigned char abyDstAddr[ETH_ALEN];
+	unsigned char abySrcAddr[ETH_ALEN];
+	unsigned short wLen;
+} __attribute__ ((__packed__))
 S802_3Header, *PS802_3Header;
 
 //
 // 802_11 packet
 //
 typedef struct tagS802_11Header {
-    unsigned short wFrameCtl;
-    unsigned short wDurationID;
-    unsigned char abyAddr1[ETH_ALEN];
-    unsigned char abyAddr2[ETH_ALEN];
-    unsigned char abyAddr3[ETH_ALEN];
-    unsigned short wSeqCtl;
-    unsigned char abyAddr4[ETH_ALEN];
-}__attribute__ ((__packed__))
+	unsigned short wFrameCtl;
+	unsigned short wDurationID;
+	unsigned char abyAddr1[ETH_ALEN];
+	unsigned char abyAddr2[ETH_ALEN];
+	unsigned char abyAddr3[ETH_ALEN];
+	unsigned short wSeqCtl;
+	unsigned char abyAddr4[ETH_ALEN];
+} __attribute__ ((__packed__))
 S802_11Header, *PS802_11Header;
 
 /*---------------------  Export Macros ------------------------------*/
@@ -195,6 +190,3 @@ unsigned char ETHbyGetHashIndexByCrc32(unsigned char *pbyMultiAddr);
 bool ETHbIsBufferCrc32Ok(unsigned char *pbyBuffer, unsigned int cbFrameLength);
 
 #endif // __TETHER_H__
-
-
-
diff --git a/drivers/staging/vt6655/tkip.c b/drivers/staging/vt6655/tkip.c
index f141ba1..b3e087e 100644
--- a/drivers/staging/vt6655/tkip.c
+++ b/drivers/staging/vt6655/tkip.c
@@ -56,76 +56,75 @@
 /* bytes swapped. To allow an endian tolerant implementation, the byte */
 /* halves have been expressed independently here.                      */
 const unsigned char TKIP_Sbox_Lower[256] = {
-    0xA5,0x84,0x99,0x8D,0x0D,0xBD,0xB1,0x54,
-    0x50,0x03,0xA9,0x7D,0x19,0x62,0xE6,0x9A,
-    0x45,0x9D,0x40,0x87,0x15,0xEB,0xC9,0x0B,
-    0xEC,0x67,0xFD,0xEA,0xBF,0xF7,0x96,0x5B,
-    0xC2,0x1C,0xAE,0x6A,0x5A,0x41,0x02,0x4F,
-    0x5C,0xF4,0x34,0x08,0x93,0x73,0x53,0x3F,
-    0x0C,0x52,0x65,0x5E,0x28,0xA1,0x0F,0xB5,
-    0x09,0x36,0x9B,0x3D,0x26,0x69,0xCD,0x9F,
-    0x1B,0x9E,0x74,0x2E,0x2D,0xB2,0xEE,0xFB,
-    0xF6,0x4D,0x61,0xCE,0x7B,0x3E,0x71,0x97,
-    0xF5,0x68,0x00,0x2C,0x60,0x1F,0xC8,0xED,
-    0xBE,0x46,0xD9,0x4B,0xDE,0xD4,0xE8,0x4A,
-    0x6B,0x2A,0xE5,0x16,0xC5,0xD7,0x55,0x94,
-    0xCF,0x10,0x06,0x81,0xF0,0x44,0xBA,0xE3,
-    0xF3,0xFE,0xC0,0x8A,0xAD,0xBC,0x48,0x04,
-    0xDF,0xC1,0x75,0x63,0x30,0x1A,0x0E,0x6D,
-    0x4C,0x14,0x35,0x2F,0xE1,0xA2,0xCC,0x39,
-    0x57,0xF2,0x82,0x47,0xAC,0xE7,0x2B,0x95,
-    0xA0,0x98,0xD1,0x7F,0x66,0x7E,0xAB,0x83,
-    0xCA,0x29,0xD3,0x3C,0x79,0xE2,0x1D,0x76,
-    0x3B,0x56,0x4E,0x1E,0xDB,0x0A,0x6C,0xE4,
-    0x5D,0x6E,0xEF,0xA6,0xA8,0xA4,0x37,0x8B,
-    0x32,0x43,0x59,0xB7,0x8C,0x64,0xD2,0xE0,
-    0xB4,0xFA,0x07,0x25,0xAF,0x8E,0xE9,0x18,
-    0xD5,0x88,0x6F,0x72,0x24,0xF1,0xC7,0x51,
-    0x23,0x7C,0x9C,0x21,0xDD,0xDC,0x86,0x85,
-    0x90,0x42,0xC4,0xAA,0xD8,0x05,0x01,0x12,
-    0xA3,0x5F,0xF9,0xD0,0x91,0x58,0x27,0xB9,
-    0x38,0x13,0xB3,0x33,0xBB,0x70,0x89,0xA7,
-    0xB6,0x22,0x92,0x20,0x49,0xFF,0x78,0x7A,
-    0x8F,0xF8,0x80,0x17,0xDA,0x31,0xC6,0xB8,
-    0xC3,0xB0,0x77,0x11,0xCB,0xFC,0xD6,0x3A
+	0xA5, 0x84, 0x99, 0x8D, 0x0D, 0xBD, 0xB1, 0x54,
+	0x50, 0x03, 0xA9, 0x7D, 0x19, 0x62, 0xE6, 0x9A,
+	0x45, 0x9D, 0x40, 0x87, 0x15, 0xEB, 0xC9, 0x0B,
+	0xEC, 0x67, 0xFD, 0xEA, 0xBF, 0xF7, 0x96, 0x5B,
+	0xC2, 0x1C, 0xAE, 0x6A, 0x5A, 0x41, 0x02, 0x4F,
+	0x5C, 0xF4, 0x34, 0x08, 0x93, 0x73, 0x53, 0x3F,
+	0x0C, 0x52, 0x65, 0x5E, 0x28, 0xA1, 0x0F, 0xB5,
+	0x09, 0x36, 0x9B, 0x3D, 0x26, 0x69, 0xCD, 0x9F,
+	0x1B, 0x9E, 0x74, 0x2E, 0x2D, 0xB2, 0xEE, 0xFB,
+	0xF6, 0x4D, 0x61, 0xCE, 0x7B, 0x3E, 0x71, 0x97,
+	0xF5, 0x68, 0x00, 0x2C, 0x60, 0x1F, 0xC8, 0xED,
+	0xBE, 0x46, 0xD9, 0x4B, 0xDE, 0xD4, 0xE8, 0x4A,
+	0x6B, 0x2A, 0xE5, 0x16, 0xC5, 0xD7, 0x55, 0x94,
+	0xCF, 0x10, 0x06, 0x81, 0xF0, 0x44, 0xBA, 0xE3,
+	0xF3, 0xFE, 0xC0, 0x8A, 0xAD, 0xBC, 0x48, 0x04,
+	0xDF, 0xC1, 0x75, 0x63, 0x30, 0x1A, 0x0E, 0x6D,
+	0x4C, 0x14, 0x35, 0x2F, 0xE1, 0xA2, 0xCC, 0x39,
+	0x57, 0xF2, 0x82, 0x47, 0xAC, 0xE7, 0x2B, 0x95,
+	0xA0, 0x98, 0xD1, 0x7F, 0x66, 0x7E, 0xAB, 0x83,
+	0xCA, 0x29, 0xD3, 0x3C, 0x79, 0xE2, 0x1D, 0x76,
+	0x3B, 0x56, 0x4E, 0x1E, 0xDB, 0x0A, 0x6C, 0xE4,
+	0x5D, 0x6E, 0xEF, 0xA6, 0xA8, 0xA4, 0x37, 0x8B,
+	0x32, 0x43, 0x59, 0xB7, 0x8C, 0x64, 0xD2, 0xE0,
+	0xB4, 0xFA, 0x07, 0x25, 0xAF, 0x8E, 0xE9, 0x18,
+	0xD5, 0x88, 0x6F, 0x72, 0x24, 0xF1, 0xC7, 0x51,
+	0x23, 0x7C, 0x9C, 0x21, 0xDD, 0xDC, 0x86, 0x85,
+	0x90, 0x42, 0xC4, 0xAA, 0xD8, 0x05, 0x01, 0x12,
+	0xA3, 0x5F, 0xF9, 0xD0, 0x91, 0x58, 0x27, 0xB9,
+	0x38, 0x13, 0xB3, 0x33, 0xBB, 0x70, 0x89, 0xA7,
+	0xB6, 0x22, 0x92, 0x20, 0x49, 0xFF, 0x78, 0x7A,
+	0x8F, 0xF8, 0x80, 0x17, 0xDA, 0x31, 0xC6, 0xB8,
+	0xC3, 0xB0, 0x77, 0x11, 0xCB, 0xFC, 0xD6, 0x3A
 };
 
 const unsigned char TKIP_Sbox_Upper[256] = {
-    0xC6,0xF8,0xEE,0xF6,0xFF,0xD6,0xDE,0x91,
-    0x60,0x02,0xCE,0x56,0xE7,0xB5,0x4D,0xEC,
-    0x8F,0x1F,0x89,0xFA,0xEF,0xB2,0x8E,0xFB,
-    0x41,0xB3,0x5F,0x45,0x23,0x53,0xE4,0x9B,
-    0x75,0xE1,0x3D,0x4C,0x6C,0x7E,0xF5,0x83,
-    0x68,0x51,0xD1,0xF9,0xE2,0xAB,0x62,0x2A,
-    0x08,0x95,0x46,0x9D,0x30,0x37,0x0A,0x2F,
-    0x0E,0x24,0x1B,0xDF,0xCD,0x4E,0x7F,0xEA,
-    0x12,0x1D,0x58,0x34,0x36,0xDC,0xB4,0x5B,
-    0xA4,0x76,0xB7,0x7D,0x52,0xDD,0x5E,0x13,
-    0xA6,0xB9,0x00,0xC1,0x40,0xE3,0x79,0xB6,
-    0xD4,0x8D,0x67,0x72,0x94,0x98,0xB0,0x85,
-    0xBB,0xC5,0x4F,0xED,0x86,0x9A,0x66,0x11,
-    0x8A,0xE9,0x04,0xFE,0xA0,0x78,0x25,0x4B,
-    0xA2,0x5D,0x80,0x05,0x3F,0x21,0x70,0xF1,
-    0x63,0x77,0xAF,0x42,0x20,0xE5,0xFD,0xBF,
-    0x81,0x18,0x26,0xC3,0xBE,0x35,0x88,0x2E,
-    0x93,0x55,0xFC,0x7A,0xC8,0xBA,0x32,0xE6,
-    0xC0,0x19,0x9E,0xA3,0x44,0x54,0x3B,0x0B,
-    0x8C,0xC7,0x6B,0x28,0xA7,0xBC,0x16,0xAD,
-    0xDB,0x64,0x74,0x14,0x92,0x0C,0x48,0xB8,
-    0x9F,0xBD,0x43,0xC4,0x39,0x31,0xD3,0xF2,
-    0xD5,0x8B,0x6E,0xDA,0x01,0xB1,0x9C,0x49,
-    0xD8,0xAC,0xF3,0xCF,0xCA,0xF4,0x47,0x10,
-    0x6F,0xF0,0x4A,0x5C,0x38,0x57,0x73,0x97,
-    0xCB,0xA1,0xE8,0x3E,0x96,0x61,0x0D,0x0F,
-    0xE0,0x7C,0x71,0xCC,0x90,0x06,0xF7,0x1C,
-    0xC2,0x6A,0xAE,0x69,0x17,0x99,0x3A,0x27,
-    0xD9,0xEB,0x2B,0x22,0xD2,0xA9,0x07,0x33,
-    0x2D,0x3C,0x15,0xC9,0x87,0xAA,0x50,0xA5,
-    0x03,0x59,0x09,0x1A,0x65,0xD7,0x84,0xD0,
-    0x82,0x29,0x5A,0x1E,0x7B,0xA8,0x6D,0x2C
+	0xC6, 0xF8, 0xEE, 0xF6, 0xFF, 0xD6, 0xDE, 0x91,
+	0x60, 0x02, 0xCE, 0x56, 0xE7, 0xB5, 0x4D, 0xEC,
+	0x8F, 0x1F, 0x89, 0xFA, 0xEF, 0xB2, 0x8E, 0xFB,
+	0x41, 0xB3, 0x5F, 0x45, 0x23, 0x53, 0xE4, 0x9B,
+	0x75, 0xE1, 0x3D, 0x4C, 0x6C, 0x7E, 0xF5, 0x83,
+	0x68, 0x51, 0xD1, 0xF9, 0xE2, 0xAB, 0x62, 0x2A,
+	0x08, 0x95, 0x46, 0x9D, 0x30, 0x37, 0x0A, 0x2F,
+	0x0E, 0x24, 0x1B, 0xDF, 0xCD, 0x4E, 0x7F, 0xEA,
+	0x12, 0x1D, 0x58, 0x34, 0x36, 0xDC, 0xB4, 0x5B,
+	0xA4, 0x76, 0xB7, 0x7D, 0x52, 0xDD, 0x5E, 0x13,
+	0xA6, 0xB9, 0x00, 0xC1, 0x40, 0xE3, 0x79, 0xB6,
+	0xD4, 0x8D, 0x67, 0x72, 0x94, 0x98, 0xB0, 0x85,
+	0xBB, 0xC5, 0x4F, 0xED, 0x86, 0x9A, 0x66, 0x11,
+	0x8A, 0xE9, 0x04, 0xFE, 0xA0, 0x78, 0x25, 0x4B,
+	0xA2, 0x5D, 0x80, 0x05, 0x3F, 0x21, 0x70, 0xF1,
+	0x63, 0x77, 0xAF, 0x42, 0x20, 0xE5, 0xFD, 0xBF,
+	0x81, 0x18, 0x26, 0xC3, 0xBE, 0x35, 0x88, 0x2E,
+	0x93, 0x55, 0xFC, 0x7A, 0xC8, 0xBA, 0x32, 0xE6,
+	0xC0, 0x19, 0x9E, 0xA3, 0x44, 0x54, 0x3B, 0x0B,
+	0x8C, 0xC7, 0x6B, 0x28, 0xA7, 0xBC, 0x16, 0xAD,
+	0xDB, 0x64, 0x74, 0x14, 0x92, 0x0C, 0x48, 0xB8,
+	0x9F, 0xBD, 0x43, 0xC4, 0x39, 0x31, 0xD3, 0xF2,
+	0xD5, 0x8B, 0x6E, 0xDA, 0x01, 0xB1, 0x9C, 0x49,
+	0xD8, 0xAC, 0xF3, 0xCF, 0xCA, 0xF4, 0x47, 0x10,
+	0x6F, 0xF0, 0x4A, 0x5C, 0x38, 0x57, 0x73, 0x97,
+	0xCB, 0xA1, 0xE8, 0x3E, 0x96, 0x61, 0x0D, 0x0F,
+	0xE0, 0x7C, 0x71, 0xCC, 0x90, 0x06, 0xF7, 0x1C,
+	0xC2, 0x6A, 0xAE, 0x69, 0x17, 0x99, 0x3A, 0x27,
+	0xD9, 0xEB, 0x2B, 0x22, 0xD2, 0xA9, 0x07, 0x33,
+	0x2D, 0x3C, 0x15, 0xC9, 0x87, 0xAA, 0x50, 0xA5,
+	0x03, 0x59, 0x09, 0x1A, 0x65, 0xD7, 0x84, 0xD0,
+	0x82, 0x29, 0x5A, 0x1E, 0x7B, 0xA8, 0x6D, 0x2C
 };
 
-
 //STKIPKeyManagement  sTKIPKeyTable[MAX_TKIP_KEY];
 
 /*---------------------  Static Functions  --------------------------*/
@@ -141,34 +140,32 @@ unsigned int rotr1(unsigned int a);
 /************************************************************/
 unsigned int tkip_sbox(unsigned int index)
 {
-    unsigned int index_low;
-    unsigned int index_high;
-    unsigned int left, right;
+	unsigned int index_low;
+	unsigned int index_high;
+	unsigned int left, right;
 
-    index_low = (index % 256);
-    index_high = ((index >> 8) % 256);
+	index_low = (index % 256);
+	index_high = ((index >> 8) % 256);
 
-    left = TKIP_Sbox_Lower[index_low] + (TKIP_Sbox_Upper[index_low] * 256);
-    right = TKIP_Sbox_Upper[index_high] + (TKIP_Sbox_Lower[index_high] * 256);
+	left = TKIP_Sbox_Lower[index_low] + (TKIP_Sbox_Upper[index_low] * 256);
+	right = TKIP_Sbox_Upper[index_high] + (TKIP_Sbox_Lower[index_high] * 256);
 
-    return (left ^ right);
+	return left ^ right;
 };
 
-
 unsigned int rotr1(unsigned int a)
 {
-    unsigned int b;
-
-    if ((a & 0x01) == 0x01) {
-        b = (a >> 1) | 0x8000;
-    } else {
-        b = (a >> 1) & 0x7fff;
-    }
-    b = b % 65536;
-    return b;
+	unsigned int b;
+
+	if ((a & 0x01) == 0x01) {
+		b = (a >> 1) | 0x8000;
+	} else {
+		b = (a >> 1) & 0x7fff;
+	}
+	b = b % 65536;
+	return b;
 }
 
-
 /*
  * Description: Calculate RC4Key fom TK, TA, and TSC
  *
@@ -184,89 +181,89 @@ unsigned int rotr1(unsigned int a)
  *
  */
 void TKIPvMixKey(
-    unsigned char *pbyTKey,
-    unsigned char *pbyTA,
-    unsigned short wTSC15_0,
-    unsigned long dwTSC47_16,
-    unsigned char *pbyRC4Key
-    )
+	unsigned char *pbyTKey,
+	unsigned char *pbyTA,
+	unsigned short wTSC15_0,
+	unsigned long dwTSC47_16,
+	unsigned char *pbyRC4Key
+)
 {
-    unsigned int p1k[5];
+	unsigned int p1k[5];
 //    unsigned int ttak0, ttak1, ttak2, ttak3, ttak4;
-    unsigned int tsc0, tsc1, tsc2;
-    unsigned int ppk0, ppk1, ppk2, ppk3, ppk4, ppk5;
-    unsigned long int pnl,pnh;
-
-    int i, j;
-
-    pnl = wTSC15_0;
-    pnh = dwTSC47_16;
-
-    tsc0 = (unsigned int)((pnh >> 16) % 65536); /* msb */
-    tsc1 = (unsigned int)(pnh % 65536);
-    tsc2 = (unsigned int)(pnl % 65536); /* lsb */
-
-    /* Phase 1, step 1 */
-    p1k[0] = tsc1;
-    p1k[1] = tsc0;
-    p1k[2] = (unsigned int)(pbyTA[0] + (pbyTA[1]*256));
-    p1k[3] = (unsigned int)(pbyTA[2] + (pbyTA[3]*256));
-    p1k[4] = (unsigned int)(pbyTA[4] + (pbyTA[5]*256));
-
-    /* Phase 1, step 2 */
-    for (i=0; i<8; i++) {
-        j = 2*(i & 1);
-        p1k[0] = (p1k[0] + tkip_sbox( (p1k[4] ^ ((256*pbyTKey[1+j]) + pbyTKey[j])) % 65536 )) % 65536;
-        p1k[1] = (p1k[1] + tkip_sbox( (p1k[0] ^ ((256*pbyTKey[5+j]) + pbyTKey[4+j])) % 65536 )) % 65536;
-        p1k[2] = (p1k[2] + tkip_sbox( (p1k[1] ^ ((256*pbyTKey[9+j]) + pbyTKey[8+j])) % 65536 )) % 65536;
-        p1k[3] = (p1k[3] + tkip_sbox( (p1k[2] ^ ((256*pbyTKey[13+j]) + pbyTKey[12+j])) % 65536 )) % 65536;
-        p1k[4] = (p1k[4] + tkip_sbox( (p1k[3] ^ (((256*pbyTKey[1+j]) + pbyTKey[j]))) % 65536 )) % 65536;
-        p1k[4] = (p1k[4] + i) % 65536;
-    }
-    /* Phase 2, Step 1 */
-    ppk0 = p1k[0];
-    ppk1 = p1k[1];
-    ppk2 = p1k[2];
-    ppk3 = p1k[3];
-    ppk4 = p1k[4];
-    ppk5 = (p1k[4] + tsc2) % 65536;
-
-    /* Phase2, Step 2 */
-    ppk0 = ppk0 + tkip_sbox( (ppk5 ^ ((256*pbyTKey[1]) + pbyTKey[0])) % 65536);
-    ppk1 = ppk1 + tkip_sbox( (ppk0 ^ ((256*pbyTKey[3]) + pbyTKey[2])) % 65536);
-    ppk2 = ppk2 + tkip_sbox( (ppk1 ^ ((256*pbyTKey[5]) + pbyTKey[4])) % 65536);
-    ppk3 = ppk3 + tkip_sbox( (ppk2 ^ ((256*pbyTKey[7]) + pbyTKey[6])) % 65536);
-    ppk4 = ppk4 + tkip_sbox( (ppk3 ^ ((256*pbyTKey[9]) + pbyTKey[8])) % 65536);
-    ppk5 = ppk5 + tkip_sbox( (ppk4 ^ ((256*pbyTKey[11]) + pbyTKey[10])) % 65536);
-
-    ppk0 = ppk0 + rotr1(ppk5 ^ ((256*pbyTKey[13]) + pbyTKey[12]));
-    ppk1 = ppk1 + rotr1(ppk0 ^ ((256*pbyTKey[15]) + pbyTKey[14]));
-    ppk2 = ppk2 + rotr1(ppk1);
-    ppk3 = ppk3 + rotr1(ppk2);
-    ppk4 = ppk4 + rotr1(ppk3);
-    ppk5 = ppk5 + rotr1(ppk4);
-
-    /* Phase 2, Step 3 */
-    pbyRC4Key[0] = (tsc2 >> 8) % 256;
-    pbyRC4Key[1] = (((tsc2 >> 8) % 256) | 0x20) & 0x7f;
-    pbyRC4Key[2] = tsc2 % 256;
-    pbyRC4Key[3] = ((ppk5 ^ ((256*pbyTKey[1]) + pbyTKey[0])) >> 1) % 256;
-
-    pbyRC4Key[4] = ppk0 % 256;
-    pbyRC4Key[5] = (ppk0 >> 8) % 256;
-
-    pbyRC4Key[6] = ppk1 % 256;
-    pbyRC4Key[7] = (ppk1 >> 8) % 256;
-
-    pbyRC4Key[8] = ppk2 % 256;
-    pbyRC4Key[9] = (ppk2 >> 8) % 256;
-
-    pbyRC4Key[10] = ppk3 % 256;
-    pbyRC4Key[11] = (ppk3 >> 8) % 256;
-
-    pbyRC4Key[12] = ppk4 % 256;
-    pbyRC4Key[13] = (ppk4 >> 8) % 256;
-
-    pbyRC4Key[14] = ppk5 % 256;
-    pbyRC4Key[15] = (ppk5 >> 8) % 256;
+	unsigned int tsc0, tsc1, tsc2;
+	unsigned int ppk0, ppk1, ppk2, ppk3, ppk4, ppk5;
+	unsigned long int pnl, pnh;
+
+	int i, j;
+
+	pnl = wTSC15_0;
+	pnh = dwTSC47_16;
+
+	tsc0 = (unsigned int)((pnh >> 16) % 65536); /* msb */
+	tsc1 = (unsigned int)(pnh % 65536);
+	tsc2 = (unsigned int)(pnl % 65536); /* lsb */
+
+	/* Phase 1, step 1 */
+	p1k[0] = tsc1;
+	p1k[1] = tsc0;
+	p1k[2] = (unsigned int)(pbyTA[0] + (pbyTA[1]*256));
+	p1k[3] = (unsigned int)(pbyTA[2] + (pbyTA[3]*256));
+	p1k[4] = (unsigned int)(pbyTA[4] + (pbyTA[5]*256));
+
+	/* Phase 1, step 2 */
+	for (i = 0; i < 8; i++) {
+		j = 2 * (i & 1);
+		p1k[0] = (p1k[0] + tkip_sbox((p1k[4] ^ ((256*pbyTKey[1+j]) + pbyTKey[j])) % 65536)) % 65536;
+		p1k[1] = (p1k[1] + tkip_sbox((p1k[0] ^ ((256*pbyTKey[5+j]) + pbyTKey[4+j])) % 65536)) % 65536;
+		p1k[2] = (p1k[2] + tkip_sbox((p1k[1] ^ ((256*pbyTKey[9+j]) + pbyTKey[8+j])) % 65536)) % 65536;
+		p1k[3] = (p1k[3] + tkip_sbox((p1k[2] ^ ((256*pbyTKey[13+j]) + pbyTKey[12+j])) % 65536)) % 65536;
+		p1k[4] = (p1k[4] + tkip_sbox((p1k[3] ^ (((256*pbyTKey[1+j]) + pbyTKey[j]))) % 65536)) % 65536;
+		p1k[4] = (p1k[4] + i) % 65536;
+	}
+	/* Phase 2, Step 1 */
+	ppk0 = p1k[0];
+	ppk1 = p1k[1];
+	ppk2 = p1k[2];
+	ppk3 = p1k[3];
+	ppk4 = p1k[4];
+	ppk5 = (p1k[4] + tsc2) % 65536;
+
+	/* Phase2, Step 2 */
+	ppk0 = ppk0 + tkip_sbox((ppk5 ^ ((256*pbyTKey[1]) + pbyTKey[0])) % 65536);
+	ppk1 = ppk1 + tkip_sbox((ppk0 ^ ((256*pbyTKey[3]) + pbyTKey[2])) % 65536);
+	ppk2 = ppk2 + tkip_sbox((ppk1 ^ ((256*pbyTKey[5]) + pbyTKey[4])) % 65536);
+	ppk3 = ppk3 + tkip_sbox((ppk2 ^ ((256*pbyTKey[7]) + pbyTKey[6])) % 65536);
+	ppk4 = ppk4 + tkip_sbox((ppk3 ^ ((256*pbyTKey[9]) + pbyTKey[8])) % 65536);
+	ppk5 = ppk5 + tkip_sbox((ppk4 ^ ((256*pbyTKey[11]) + pbyTKey[10])) % 65536);
+
+	ppk0 = ppk0 + rotr1(ppk5 ^ ((256*pbyTKey[13]) + pbyTKey[12]));
+	ppk1 = ppk1 + rotr1(ppk0 ^ ((256*pbyTKey[15]) + pbyTKey[14]));
+	ppk2 = ppk2 + rotr1(ppk1);
+	ppk3 = ppk3 + rotr1(ppk2);
+	ppk4 = ppk4 + rotr1(ppk3);
+	ppk5 = ppk5 + rotr1(ppk4);
+
+	/* Phase 2, Step 3 */
+	pbyRC4Key[0] = (tsc2 >> 8) % 256;
+	pbyRC4Key[1] = (((tsc2 >> 8) % 256) | 0x20) & 0x7f;
+	pbyRC4Key[2] = tsc2 % 256;
+	pbyRC4Key[3] = ((ppk5 ^ ((256*pbyTKey[1]) + pbyTKey[0])) >> 1) % 256;
+
+	pbyRC4Key[4] = ppk0 % 256;
+	pbyRC4Key[5] = (ppk0 >> 8) % 256;
+
+	pbyRC4Key[6] = ppk1 % 256;
+	pbyRC4Key[7] = (ppk1 >> 8) % 256;
+
+	pbyRC4Key[8] = ppk2 % 256;
+	pbyRC4Key[9] = (ppk2 >> 8) % 256;
+
+	pbyRC4Key[10] = ppk3 % 256;
+	pbyRC4Key[11] = (ppk3 >> 8) % 256;
+
+	pbyRC4Key[12] = ppk4 % 256;
+	pbyRC4Key[13] = (ppk4 >> 8) % 256;
+
+	pbyRC4Key[14] = ppk5 % 256;
+	pbyRC4Key[15] = (ppk5 >> 8) % 256;
 }
diff --git a/drivers/staging/vt6655/tkip.h b/drivers/staging/vt6655/tkip.h
index eb5951d..3b6357a 100644
--- a/drivers/staging/vt6655/tkip.h
+++ b/drivers/staging/vt6655/tkip.h
@@ -47,14 +47,11 @@
 /*---------------------  Export Functions  --------------------------*/
 
 void TKIPvMixKey(
-    unsigned char *pbyTKey,
-    unsigned char *pbyTA,
-    unsigned short wTSC15_0,
-    unsigned long dwTSC47_16,
-    unsigned char *pbyRC4Key
-    );
+	unsigned char *pbyTKey,
+	unsigned char *pbyTA,
+	unsigned short wTSC15_0,
+	unsigned long dwTSC47_16,
+	unsigned char *pbyRC4Key
+);
 
 #endif // __TKIP_H__
-
-
-
diff --git a/drivers/staging/vt6655/tmacro.h b/drivers/staging/vt6655/tmacro.h
index e8b177d..59c6e72 100644
--- a/drivers/staging/vt6655/tmacro.h
+++ b/drivers/staging/vt6655/tmacro.h
@@ -58,5 +58,3 @@
 #endif
 
 #endif // __TMACRO_H__
-
-
diff --git a/drivers/staging/vt6655/ttype.h b/drivers/staging/vt6655/ttype.h
index be223bd..b1d8ae7 100644
--- a/drivers/staging/vt6655/ttype.h
+++ b/drivers/staging/vt6655/ttype.h
@@ -26,11 +26,9 @@
  *
  */
 
-
 #ifndef __TTYPE_H__
 #define __TTYPE_H__
 
-
 /******* Common definitions and typedefs ***********************************/
 
 #ifndef TxInSleep
@@ -56,16 +54,16 @@
 // an 8-byte-aligned 8 byte long structure
 // which is NOT really a floating point number.
 typedef union tagUQuadWord {
-    struct {
-        unsigned int dwLowDword;
-        unsigned int dwHighDword;
-    } u;
-    double      DoNotUseThisField;
+	struct {
+		unsigned int dwLowDword;
+		unsigned int dwHighDword;
+	} u;
+	double      DoNotUseThisField;
 } UQuadWord;
 typedef UQuadWord       QWORD;          // 64-bit
 
 /****** Common pointer types ***********************************************/
 
-typedef QWORD *          PQWORD;
+typedef QWORD *PQWORD;
 
 #endif // __TTYPE_H__
diff --git a/drivers/staging/vt6655/upc.h b/drivers/staging/vt6655/upc.h
index 9596fde..155e664 100644
--- a/drivers/staging/vt6655/upc.h
+++ b/drivers/staging/vt6655/upc.h
@@ -34,39 +34,35 @@
 
 /*---------------------  Export Definitions -------------------------*/
 
-
 //
 //  For IO mapped
 //
 
 #ifdef IO_MAP
 
-#define VNSvInPortB(dwIOAddress, pbyData) {                     \
-	*(pbyData) = inb(dwIOAddress);                              \
-}
-
-
-#define VNSvInPortW(dwIOAddress, pwData) {                      \
-	    *(pwData) = inw(dwIOAddress);                           \
-}
-
-#define VNSvInPortD(dwIOAddress, pdwData) {                     \
-	    *(pdwData) = inl(dwIOAddress);                          \
-}
+#define VNSvInPortB(dwIOAddress, pbyData)	\
+do {						\
+	*(pbyData) = inb(dwIOAddress);		\
+} while (0)
 
+#define VNSvInPortW(dwIOAddress, pwData)	\
+do {						\
+	*(pwData) = inw(dwIOAddress);		\
+} while (0)
 
-#define VNSvOutPortB(dwIOAddress, byData) {                     \
-        outb(byData, dwIOAddress);                              \
-}
+#define VNSvInPortD(dwIOAddress, pdwData)	\
+do {						\
+	*(pdwData) = inl(dwIOAddress);		\
+} while (0)
 
+#define VNSvOutPortB(dwIOAddress, byData)	\
+	outb(byData, dwIOAddress)
 
-#define VNSvOutPortW(dwIOAddress, wData) {                      \
-        outw(wData, dwIOAddress);                               \
-}
+#define VNSvOutPortW(dwIOAddress, wData)	\
+	outw(wData, dwIOAddress)
 
-#define VNSvOutPortD(dwIOAddress, dwData) {                     \
-        outl(dwData, dwIOAddress);                              \
-}
+#define VNSvOutPortD(dwIOAddress, dwData)	\
+	outl(dwData, dwIOAddress)
 
 #else
 
@@ -74,84 +70,83 @@
 //  For memory mapped IO
 //
 
-
-#define VNSvInPortB(dwIOAddress, pbyData) {                     \
-	volatile unsigned char * pbyAddr = ((unsigned char *)(dwIOAddress));            \
-	*(pbyData) = readb(pbyAddr);                           \
-}
-
-
-#define VNSvInPortW(dwIOAddress, pwData) {                      \
-	volatile unsigned short *pwAddr = ((unsigned short *)(dwIOAddress));             \
-	*(pwData) = readw(pwAddr);                             \
-}
-
-#define VNSvInPortD(dwIOAddress, pdwData) {                     \
-	volatile unsigned long *pdwAddr = ((unsigned long *)(dwIOAddress));          \
-	*(pdwData) = readl(pdwAddr);                           \
-}
-
-
-#define VNSvOutPortB(dwIOAddress, byData) {                     \
-    volatile unsigned char * pbyAddr = ((unsigned char *)(dwIOAddress));            \
-    writeb((unsigned char)byData, pbyAddr);							\
-}
-
-
-#define VNSvOutPortW(dwIOAddress, wData) {                      \
-    volatile unsigned short *pwAddr = ((unsigned short *)(dwIOAddress));             \
-    writew((unsigned short)wData, pwAddr);							\
-}
-
-#define VNSvOutPortD(dwIOAddress, dwData) {                     \
-    volatile unsigned long *pdwAddr = ((unsigned long *)(dwIOAddress));          \
-    writel((unsigned long)dwData, pdwAddr);					    \
-}
+#define VNSvInPortB(dwIOAddress, pbyData)				\
+do {									\
+	volatile unsigned char *pbyAddr = (unsigned char *)(dwIOAddress); \
+	*(pbyData) = readb(pbyAddr);					\
+} while (0)
+
+#define VNSvInPortW(dwIOAddress, pwData)				\
+do {									\
+	volatile unsigned short *pwAddr = (unsigned short *)(dwIOAddress); \
+	*(pwData) = readw(pwAddr);					\
+} while (0)
+
+#define VNSvInPortD(dwIOAddress, pdwData)				\
+do {									\
+	volatile unsigned long *pdwAddr = (unsigned long *)(dwIOAddress); \
+	*(pdwData) = readl(pdwAddr);					\
+} while (0)
+
+#define VNSvOutPortB(dwIOAddress, byData)				\
+do {									\
+	volatile unsigned char *pbyAddr = (unsigned char *)(dwIOAddress); \
+	writeb((unsigned char)byData, pbyAddr);				\
+} while (0)
+
+#define VNSvOutPortW(dwIOAddress, wData)				\
+do {									\
+	volatile unsigned short *pwAddr = ((unsigned short *)(dwIOAddress)); \
+	writew((unsigned short)wData, pwAddr);				\
+} while (0)
+
+#define VNSvOutPortD(dwIOAddress, dwData)				\
+do {									\
+	volatile unsigned long *pdwAddr = (unsigned long *)(dwIOAddress); \
+	writel((unsigned long)dwData, pdwAddr);				\
+} while (0)
 
 #endif
 
-
 //
 // ALWAYS IO-Mapped IO when in 16-bit/32-bit environment
 //
-#define PCBvInPortB(dwIOAddress, pbyData) {     \
-	    *(pbyData) = inb(dwIOAddress);          \
-}
-
-#define PCBvInPortW(dwIOAddress, pwData) {      \
-	    *(pwData) = inw(dwIOAddress);           \
-}
-
-#define PCBvInPortD(dwIOAddress, pdwData) {     \
-	    *(pdwData) = inl(dwIOAddress);          \
-}
-
-#define PCBvOutPortB(dwIOAddress, byData) {     \
-        outb(byData, dwIOAddress);              \
-}
-
-#define PCBvOutPortW(dwIOAddress, wData) {      \
-        outw(wData, dwIOAddress);               \
-}
-
-#define PCBvOutPortD(dwIOAddress, dwData) {     \
-        outl(dwData, dwIOAddress);              \
-}
-
-
-#define PCAvDelayByIO(uDelayUnit) {             \
-    unsigned char byData;                       \
-    unsigned long ii;                           \
-                                                \
-    if (uDelayUnit <= 50) {                     \
-        udelay(uDelayUnit);                     \
-    }                                           \
-    else {                                      \
-        for (ii = 0; ii < (uDelayUnit); ii++)   \
-		     byData = inb(0x61);				\
-    }                                           \
-}
-
+#define PCBvInPortB(dwIOAddress, pbyData)	\
+do {						\
+	*(pbyData) = inb(dwIOAddress);		\
+} while (0)
+
+#define PCBvInPortW(dwIOAddress, pwData)	\
+do {						\
+	*(pwData) = inw(dwIOAddress);		\
+} while (0)
+
+#define PCBvInPortD(dwIOAddress, pdwData)	\
+do {						\
+	*(pdwData) = inl(dwIOAddress);		\
+} while (0)
+
+#define PCBvOutPortB(dwIOAddress, byData)	\
+	outb(byData, dwIOAddress)
+
+#define PCBvOutPortW(dwIOAddress, wData)	\
+	outw(wData, dwIOAddress)
+
+#define PCBvOutPortD(dwIOAddress, dwData)	\
+	outl(dwData, dwIOAddress)
+
+#define PCAvDelayByIO(uDelayUnit)				\
+do {								\
+	unsigned char byData;					\
+	unsigned long ii;					\
+								\
+	if (uDelayUnit <= 50) {					\
+		udelay(uDelayUnit);				\
+	} else {						\
+		for (ii = 0; ii < (uDelayUnit); ii++)		\
+			byData = inb(0x61);			\
+	}							\
+} while (0)
 
 /*---------------------  Export Classes  ----------------------------*/
 
@@ -159,8 +154,4 @@
 
 /*---------------------  Export Functions  --------------------------*/
 
-
-
-
 #endif // __UPC_H__
-
diff --git a/drivers/staging/vt6655/vntwifi.c b/drivers/staging/vt6655/vntwifi.c
index 62c44b8..d8f4f8e 100644
--- a/drivers/staging/vt6655/vntwifi.c
+++ b/drivers/staging/vt6655/vntwifi.c
@@ -66,19 +66,18 @@
  *
  * Return Value: none
  *
--*/
+ -*/
 void
-VNTWIFIvSetOPMode (
-    void *pMgmtHandle,
-    WMAC_CONFIG_MODE eOPMode
-    )
+VNTWIFIvSetOPMode(
+	void *pMgmtHandle,
+	WMAC_CONFIG_MODE eOPMode
+)
 {
-    PSMgmtObject        pMgmt = (PSMgmtObject)pMgmtHandle;
+	PSMgmtObject        pMgmt = (PSMgmtObject)pMgmtHandle;
 
-    pMgmt->eConfigMode = eOPMode;
+	pMgmt->eConfigMode = eOPMode;
 }
 
-
 /*+
  *
  * Description:
@@ -95,20 +94,20 @@ VNTWIFIvSetOPMode (
  *
  * Return Value: none
  *
--*/
+ -*/
 void
-VNTWIFIvSetIBSSParameter (
-    void *pMgmtHandle,
-    unsigned short wBeaconPeriod,
-    unsigned short wATIMWindow,
-    unsigned int uChannel
-    )
+VNTWIFIvSetIBSSParameter(
+	void *pMgmtHandle,
+	unsigned short wBeaconPeriod,
+	unsigned short wATIMWindow,
+	unsigned int uChannel
+)
 {
-    PSMgmtObject        pMgmt = (PSMgmtObject)pMgmtHandle;
+	PSMgmtObject        pMgmt = (PSMgmtObject)pMgmtHandle;
 
-    pMgmt->wIBSSBeaconPeriod = wBeaconPeriod;
-    pMgmt->wIBSSATIMWindow = wATIMWindow;
-    pMgmt->uIBSSChannel = uChannel;
+	pMgmt->wIBSSBeaconPeriod = wBeaconPeriod;
+	pMgmt->wIBSSATIMWindow = wATIMWindow;
+	pMgmt->uIBSSChannel = uChannel;
 }
 
 /*+
@@ -124,14 +123,14 @@ VNTWIFIvSetIBSSParameter (
  *
  * Return Value: current SSID pointer.
  *
--*/
+ -*/
 PWLAN_IE_SSID
-VNTWIFIpGetCurrentSSID (
-    void *pMgmtHandle
-    )
+VNTWIFIpGetCurrentSSID(
+	void *pMgmtHandle
+)
 {
-    PSMgmtObject        pMgmt = (PSMgmtObject)pMgmtHandle;
-    return((PWLAN_IE_SSID) pMgmt->abyCurrSSID);
+	PSMgmtObject        pMgmt = (PSMgmtObject)pMgmtHandle;
+	return (PWLAN_IE_SSID) pMgmt->abyCurrSSID;
 }
 
 /*+
@@ -147,17 +146,17 @@ VNTWIFIpGetCurrentSSID (
  *
  * Return Value: current Channel.
  *
--*/
+ -*/
 unsigned int
-VNTWIFIpGetCurrentChannel (
-    void *pMgmtHandle
-    )
+VNTWIFIpGetCurrentChannel(
+	void *pMgmtHandle
+)
 {
-    PSMgmtObject        pMgmt = (PSMgmtObject)pMgmtHandle;
-    if (pMgmtHandle != NULL) {
-        return (pMgmt->uCurrChannel);
-    }
-    return 0;
+	PSMgmtObject        pMgmt = (PSMgmtObject)pMgmtHandle;
+	if (pMgmtHandle != NULL) {
+		return pMgmt->uCurrChannel;
+	}
+	return 0;
 }
 
 /*+
@@ -173,18 +172,16 @@ VNTWIFIpGetCurrentChannel (
  *
  * Return Value: current Assoc ID
  *
--*/
+ -*/
 unsigned short
-VNTWIFIwGetAssocID (
-    void *pMgmtHandle
-    )
+VNTWIFIwGetAssocID(
+	void *pMgmtHandle
+)
 {
-    PSMgmtObject        pMgmt = (PSMgmtObject)pMgmtHandle;
-    return(pMgmt->wCurrAID);
+	PSMgmtObject        pMgmt = (PSMgmtObject)pMgmtHandle;
+	return pMgmt->wCurrAID;
 }
 
-
-
 /*+
  *
  * Description:
@@ -199,35 +196,35 @@ VNTWIFIwGetAssocID (
  *
  * Return Value: max support rate
  *
--*/
+ -*/
 unsigned char
-VNTWIFIbyGetMaxSupportRate (
-    PWLAN_IE_SUPP_RATES pSupportRateIEs,
-    PWLAN_IE_SUPP_RATES pExtSupportRateIEs
-    )
+VNTWIFIbyGetMaxSupportRate(
+	PWLAN_IE_SUPP_RATES pSupportRateIEs,
+	PWLAN_IE_SUPP_RATES pExtSupportRateIEs
+)
 {
-    unsigned char byMaxSupportRate = RATE_1M;
-    unsigned char bySupportRate = RATE_1M;
-    unsigned int ii = 0;
-
-    if (pSupportRateIEs) {
-        for (ii = 0; ii < pSupportRateIEs->len; ii++) {
-            bySupportRate = DATARATEbyGetRateIdx(pSupportRateIEs->abyRates[ii]);
-            if (bySupportRate > byMaxSupportRate) {
-                byMaxSupportRate = bySupportRate;
-            }
-        }
-    }
-    if (pExtSupportRateIEs) {
-        for (ii = 0; ii < pExtSupportRateIEs->len; ii++) {
-            bySupportRate = DATARATEbyGetRateIdx(pExtSupportRateIEs->abyRates[ii]);
-            if (bySupportRate > byMaxSupportRate) {
-                byMaxSupportRate = bySupportRate;
-            }
-        }
-    }
-
-    return byMaxSupportRate;
+	unsigned char byMaxSupportRate = RATE_1M;
+	unsigned char bySupportRate = RATE_1M;
+	unsigned int ii = 0;
+
+	if (pSupportRateIEs) {
+		for (ii = 0; ii < pSupportRateIEs->len; ii++) {
+			bySupportRate = DATARATEbyGetRateIdx(pSupportRateIEs->abyRates[ii]);
+			if (bySupportRate > byMaxSupportRate) {
+				byMaxSupportRate = bySupportRate;
+			}
+		}
+	}
+	if (pExtSupportRateIEs) {
+		for (ii = 0; ii < pExtSupportRateIEs->len; ii++) {
+			bySupportRate = DATARATEbyGetRateIdx(pExtSupportRateIEs->abyRates[ii]);
+			if (bySupportRate > byMaxSupportRate) {
+				byMaxSupportRate = bySupportRate;
+			}
+		}
+	}
+
+	return byMaxSupportRate;
 }
 
 /*+
@@ -245,48 +242,48 @@ VNTWIFIbyGetMaxSupportRate (
  *
  * Return Value: max support rate
  *
--*/
+ -*/
 unsigned char
-VNTWIFIbyGetACKTxRate (
-    unsigned char byRxDataRate,
-    PWLAN_IE_SUPP_RATES pSupportRateIEs,
-    PWLAN_IE_SUPP_RATES pExtSupportRateIEs
-    )
+VNTWIFIbyGetACKTxRate(
+	unsigned char byRxDataRate,
+	PWLAN_IE_SUPP_RATES pSupportRateIEs,
+	PWLAN_IE_SUPP_RATES pExtSupportRateIEs
+)
 {
-    unsigned char byMaxAckRate;
-    unsigned char byBasicRate;
-    unsigned int ii;
-
-    if (byRxDataRate <= RATE_11M) {
-        byMaxAckRate = RATE_1M;
-    } else  {
-        // 24M is mandatory for 802.11a and 802.11g
-        byMaxAckRate = RATE_24M;
-    }
-    if (pSupportRateIEs) {
-        for (ii = 0; ii < pSupportRateIEs->len; ii++) {
-            if (pSupportRateIEs->abyRates[ii] & 0x80) {
-                byBasicRate = DATARATEbyGetRateIdx(pSupportRateIEs->abyRates[ii]);
-                if ((byBasicRate <= byRxDataRate) &&
-                    (byBasicRate > byMaxAckRate))  {
-                    byMaxAckRate = byBasicRate;
-                }
-            }
-        }
-    }
-    if (pExtSupportRateIEs) {
-        for (ii = 0; ii < pExtSupportRateIEs->len; ii++) {
-            if (pExtSupportRateIEs->abyRates[ii] & 0x80) {
-                byBasicRate = DATARATEbyGetRateIdx(pExtSupportRateIEs->abyRates[ii]);
-                if ((byBasicRate <= byRxDataRate) &&
-                    (byBasicRate > byMaxAckRate))  {
-                    byMaxAckRate = byBasicRate;
-                }
-            }
-        }
-    }
-
-    return byMaxAckRate;
+	unsigned char byMaxAckRate;
+	unsigned char byBasicRate;
+	unsigned int ii;
+
+	if (byRxDataRate <= RATE_11M) {
+		byMaxAckRate = RATE_1M;
+	} else  {
+		// 24M is mandatory for 802.11a and 802.11g
+		byMaxAckRate = RATE_24M;
+	}
+	if (pSupportRateIEs) {
+		for (ii = 0; ii < pSupportRateIEs->len; ii++) {
+			if (pSupportRateIEs->abyRates[ii] & 0x80) {
+				byBasicRate = DATARATEbyGetRateIdx(pSupportRateIEs->abyRates[ii]);
+				if ((byBasicRate <= byRxDataRate) &&
+				    (byBasicRate > byMaxAckRate))  {
+					byMaxAckRate = byBasicRate;
+				}
+			}
+		}
+	}
+	if (pExtSupportRateIEs) {
+		for (ii = 0; ii < pExtSupportRateIEs->len; ii++) {
+			if (pExtSupportRateIEs->abyRates[ii] & 0x80) {
+				byBasicRate = DATARATEbyGetRateIdx(pExtSupportRateIEs->abyRates[ii]);
+				if ((byBasicRate <= byRxDataRate) &&
+				    (byBasicRate > byMaxAckRate))  {
+					byMaxAckRate = byBasicRate;
+				}
+			}
+		}
+	}
+
+	return byMaxAckRate;
 }
 
 /*+
@@ -303,22 +300,22 @@ VNTWIFIbyGetACKTxRate (
  *
  * Return Value: none
  *
--*/
+ -*/
 void
-VNTWIFIvSetAuthenticationMode (
-    void *pMgmtHandle,
-    WMAC_AUTHENTICATION_MODE eAuthMode
-    )
+VNTWIFIvSetAuthenticationMode(
+	void *pMgmtHandle,
+	WMAC_AUTHENTICATION_MODE eAuthMode
+)
 {
-    PSMgmtObject        pMgmt = (PSMgmtObject)pMgmtHandle;
-
-    pMgmt->eAuthenMode = eAuthMode;
-    if ((eAuthMode == WMAC_AUTH_SHAREKEY) ||
-        (eAuthMode == WMAC_AUTH_AUTO)) {
-        pMgmt->bShareKeyAlgorithm = true;
-    } else {
-        pMgmt->bShareKeyAlgorithm = false;
-    }
+	PSMgmtObject        pMgmt = (PSMgmtObject)pMgmtHandle;
+
+	pMgmt->eAuthenMode = eAuthMode;
+	if ((eAuthMode == WMAC_AUTH_SHAREKEY) ||
+	    (eAuthMode == WMAC_AUTH_AUTO)) {
+		pMgmt->bShareKeyAlgorithm = true;
+	} else {
+		pMgmt->bShareKeyAlgorithm = false;
+	}
 }
 
 /*+
@@ -335,59 +332,56 @@ VNTWIFIvSetAuthenticationMode (
  *
  * Return Value: none
  *
--*/
+ -*/
 void
-VNTWIFIvSetEncryptionMode (
-    void *pMgmtHandle,
-    WMAC_ENCRYPTION_MODE eEncryptionMode
-    )
+VNTWIFIvSetEncryptionMode(
+	void *pMgmtHandle,
+	WMAC_ENCRYPTION_MODE eEncryptionMode
+)
 {
-    PSMgmtObject        pMgmt = (PSMgmtObject)pMgmtHandle;
-
-    pMgmt->eEncryptionMode = eEncryptionMode;
-    if ((eEncryptionMode == WMAC_ENCRYPTION_WEPEnabled) ||
-        (eEncryptionMode == WMAC_ENCRYPTION_TKIPEnabled) ||
-        (eEncryptionMode == WMAC_ENCRYPTION_AESEnabled) ) {
-        pMgmt->bPrivacyInvoked = true;
-    } else {
-        pMgmt->bPrivacyInvoked = false;
-    }
+	PSMgmtObject        pMgmt = (PSMgmtObject)pMgmtHandle;
+
+	pMgmt->eEncryptionMode = eEncryptionMode;
+	if ((eEncryptionMode == WMAC_ENCRYPTION_WEPEnabled) ||
+	    (eEncryptionMode == WMAC_ENCRYPTION_TKIPEnabled) ||
+	    (eEncryptionMode == WMAC_ENCRYPTION_AESEnabled)) {
+		pMgmt->bPrivacyInvoked = true;
+	} else {
+		pMgmt->bPrivacyInvoked = false;
+	}
 }
 
-
-
 bool
-VNTWIFIbConfigPhyMode (
-    void *pMgmtHandle,
-    CARD_PHY_TYPE ePhyType
-    )
+VNTWIFIbConfigPhyMode(
+	void *pMgmtHandle,
+	CARD_PHY_TYPE ePhyType
+)
 {
-    PSMgmtObject        pMgmt = (PSMgmtObject)pMgmtHandle;
-
-    if ((ePhyType != PHY_TYPE_AUTO) &&
-        (ePhyType != pMgmt->eCurrentPHYMode)) {
-        if (CARDbSetPhyParameter(pMgmt->pAdapter, ePhyType, 0, 0, NULL, NULL)==true) {
-            pMgmt->eCurrentPHYMode = ePhyType;
-        } else {
-            return(false);
-        }
-    }
-    pMgmt->eConfigPHYMode = ePhyType;
-    return(true);
+	PSMgmtObject        pMgmt = (PSMgmtObject)pMgmtHandle;
+
+	if ((ePhyType != PHY_TYPE_AUTO) &&
+	    (ePhyType != pMgmt->eCurrentPHYMode)) {
+		if (CARDbSetPhyParameter(pMgmt->pAdapter, ePhyType, 0, 0, NULL, NULL) == true) {
+			pMgmt->eCurrentPHYMode = ePhyType;
+		} else {
+			return false;
+		}
+	}
+	pMgmt->eConfigPHYMode = ePhyType;
+	return true;
 }
 
-
 void
-VNTWIFIbGetConfigPhyMode (
-    void *pMgmtHandle,
-    void *pePhyType
-    )
+VNTWIFIbGetConfigPhyMode(
+	void *pMgmtHandle,
+	void *pePhyType
+)
 {
-    PSMgmtObject        pMgmt = (PSMgmtObject)pMgmtHandle;
+	PSMgmtObject        pMgmt = (PSMgmtObject)pMgmtHandle;
 
-    if ((pMgmt != NULL) && (pePhyType != NULL)) {
-        *(PCARD_PHY_TYPE)pePhyType = pMgmt->eConfigPHYMode;
-    }
+	if ((pMgmt != NULL) && (pePhyType != NULL)) {
+		*(PCARD_PHY_TYPE)pePhyType = pMgmt->eConfigPHYMode;
+	}
 }
 
 /*+
@@ -403,8 +397,7 @@ VNTWIFIbGetConfigPhyMode (
  *
  * Return Value: None.
  *
--*/
-
+ -*/
 
 /*+
  *
@@ -420,62 +413,55 @@ VNTWIFIbGetConfigPhyMode (
  *
  * Return Value: None.
  *
--*/
+ -*/
 
 void
 VNTWIFIvQueryBSSList(void *pMgmtHandle, unsigned int *puBSSCount, void **pvFirstBSS)
 {
-    unsigned int ii = 0;
-    PSMgmtObject    pMgmt = (PSMgmtObject)pMgmtHandle;
-    PKnownBSS       pBSS = NULL;
-    unsigned int uCount = 0;
-
-    *pvFirstBSS = NULL;
-
-    for (ii = 0; ii < MAX_BSS_NUM; ii++) {
-        pBSS = &(pMgmt->sBSSList[ii]);
-        if (!pBSS->bActive) {
-            continue;
-        }
-        if (*pvFirstBSS == NULL) {
-            *pvFirstBSS = &(pMgmt->sBSSList[ii]);
-        }
-        uCount++;
-    }
-    *puBSSCount = uCount;
+	unsigned int ii = 0;
+	PSMgmtObject    pMgmt = (PSMgmtObject)pMgmtHandle;
+	PKnownBSS       pBSS = NULL;
+	unsigned int uCount = 0;
+
+	*pvFirstBSS = NULL;
+
+	for (ii = 0; ii < MAX_BSS_NUM; ii++) {
+		pBSS = &(pMgmt->sBSSList[ii]);
+		if (!pBSS->bActive) {
+			continue;
+		}
+		if (*pvFirstBSS == NULL) {
+			*pvFirstBSS = &(pMgmt->sBSSList[ii]);
+		}
+		uCount++;
+	}
+	*puBSSCount = uCount;
 }
 
-
-
-
 void
-VNTWIFIvGetNextBSS (
-    void *pMgmtHandle,
-    void *pvCurrentBSS,
-    void **pvNextBSS
-    )
+VNTWIFIvGetNextBSS(
+	void *pMgmtHandle,
+	void *pvCurrentBSS,
+	void **pvNextBSS
+)
 {
-    PKnownBSS       pBSS = (PKnownBSS) pvCurrentBSS;
-    PSMgmtObject    pMgmt = (PSMgmtObject)pMgmtHandle;
-
-    *pvNextBSS = NULL;
-
-    while (*pvNextBSS == NULL) {
-        pBSS++;
-        if (pBSS > &(pMgmt->sBSSList[MAX_BSS_NUM])) {
-            return;
-        }
-        if (pBSS->bActive == true) {
-            *pvNextBSS = pBSS;
-            return;
-        }
-    }
+	PKnownBSS       pBSS = (PKnownBSS) pvCurrentBSS;
+	PSMgmtObject    pMgmt = (PSMgmtObject)pMgmtHandle;
+
+	*pvNextBSS = NULL;
+
+	while (*pvNextBSS == NULL) {
+		pBSS++;
+		if (pBSS > &(pMgmt->sBSSList[MAX_BSS_NUM])) {
+			return;
+		}
+		if (pBSS->bActive == true) {
+			*pvNextBSS = pBSS;
+			return;
+		}
+	}
 }
 
-
-
-
-
 /*+
  *
  * Description:
@@ -487,319 +473,304 @@ VNTWIFIvGetNextBSS (
  *
  * Return Value: none
  *
--*/
+ -*/
 void
 VNTWIFIvUpdateNodeTxCounter(
-    void *pMgmtHandle,
-    unsigned char *pbyDestAddress,
-    bool bTxOk,
-    unsigned short wRate,
-    unsigned char *pbyTxFailCount
-    )
+	void *pMgmtHandle,
+	unsigned char *pbyDestAddress,
+	bool bTxOk,
+	unsigned short wRate,
+	unsigned char *pbyTxFailCount
+)
 {
-    PSMgmtObject    pMgmt = (PSMgmtObject)pMgmtHandle;
-    unsigned int uNodeIndex = 0;
-    unsigned int ii;
-
-    if ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) ||
-        (pMgmt->eCurrMode == WMAC_MODE_ESS_AP)) {
-        if (BSSDBbIsSTAInNodeDB(pMgmt, pbyDestAddress, &uNodeIndex) == false) {
-            return;
-        }
-    }
-    pMgmt->sNodeDBTable[uNodeIndex].uTxAttempts++;
-    if (bTxOk == true) {
-        // transmit success, TxAttempts at least plus one
-        pMgmt->sNodeDBTable[uNodeIndex].uTxOk[MAX_RATE]++;
-        pMgmt->sNodeDBTable[uNodeIndex].uTxOk[wRate]++;
-    } else {
-        pMgmt->sNodeDBTable[uNodeIndex].uTxFailures++;
-    }
-    pMgmt->sNodeDBTable[uNodeIndex].uTxRetry += pbyTxFailCount[MAX_RATE];
-    for(ii=0;ii<MAX_RATE;ii++) {
-        pMgmt->sNodeDBTable[uNodeIndex].uTxFail[ii] += pbyTxFailCount[ii];
-    }
-    return;
+	PSMgmtObject    pMgmt = (PSMgmtObject)pMgmtHandle;
+	unsigned int uNodeIndex = 0;
+	unsigned int ii;
+
+	if ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) ||
+	    (pMgmt->eCurrMode == WMAC_MODE_ESS_AP)) {
+		if (BSSDBbIsSTAInNodeDB(pMgmt, pbyDestAddress, &uNodeIndex) == false) {
+			return;
+		}
+	}
+	pMgmt->sNodeDBTable[uNodeIndex].uTxAttempts++;
+	if (bTxOk == true) {
+		// transmit success, TxAttempts at least plus one
+		pMgmt->sNodeDBTable[uNodeIndex].uTxOk[MAX_RATE]++;
+		pMgmt->sNodeDBTable[uNodeIndex].uTxOk[wRate]++;
+	} else {
+		pMgmt->sNodeDBTable[uNodeIndex].uTxFailures++;
+	}
+	pMgmt->sNodeDBTable[uNodeIndex].uTxRetry += pbyTxFailCount[MAX_RATE];
+	for (ii = 0; ii < MAX_RATE; ii++) {
+		pMgmt->sNodeDBTable[uNodeIndex].uTxFail[ii] += pbyTxFailCount[ii];
+	}
+	return;
 }
 
-
 void
 VNTWIFIvGetTxRate(
-    void *pMgmtHandle,
-    unsigned char *pbyDestAddress,
-    unsigned short *pwTxDataRate,
-    unsigned char *pbyACKRate,
-    unsigned char *pbyCCKBasicRate,
-    unsigned char *pbyOFDMBasicRate
-    )
+	void *pMgmtHandle,
+	unsigned char *pbyDestAddress,
+	unsigned short *pwTxDataRate,
+	unsigned char *pbyACKRate,
+	unsigned char *pbyCCKBasicRate,
+	unsigned char *pbyOFDMBasicRate
+)
 {
-    PSMgmtObject        pMgmt = (PSMgmtObject)pMgmtHandle;
-    unsigned int uNodeIndex = 0;
-    unsigned short wTxDataRate = RATE_1M;
-    unsigned char byACKRate = RATE_1M;
-    unsigned char byCCKBasicRate = RATE_1M;
-    unsigned char byOFDMBasicRate = RATE_24M;
-    PWLAN_IE_SUPP_RATES pSupportRateIEs = NULL;
-    PWLAN_IE_SUPP_RATES pExtSupportRateIEs = NULL;
-
-
-    if ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) ||
-        (pMgmt->eCurrMode == WMAC_MODE_ESS_AP)) {
-        // Adhoc Tx rate decided from node DB
-        if(BSSDBbIsSTAInNodeDB(pMgmt, pbyDestAddress, &uNodeIndex)) {
-            wTxDataRate = (pMgmt->sNodeDBTable[uNodeIndex].wTxDataRate);
-            pSupportRateIEs = (PWLAN_IE_SUPP_RATES) (pMgmt->sNodeDBTable[uNodeIndex].abyCurrSuppRates);
-            pExtSupportRateIEs = (PWLAN_IE_SUPP_RATES) (pMgmt->sNodeDBTable[uNodeIndex].abyCurrExtSuppRates);
-        } else {
-            if (pMgmt->eCurrentPHYMode != PHY_TYPE_11A) {
-                wTxDataRate = RATE_2M;
-            } else {
-                wTxDataRate = RATE_24M;
-            }
-            pSupportRateIEs = (PWLAN_IE_SUPP_RATES) pMgmt->abyCurrSuppRates;
-            pExtSupportRateIEs = (PWLAN_IE_SUPP_RATES) pMgmt->abyCurrExtSuppRates;
-        }
-    } else { // Infrastructure: rate decided from AP Node, index = 0
+	PSMgmtObject        pMgmt = (PSMgmtObject)pMgmtHandle;
+	unsigned int uNodeIndex = 0;
+	unsigned short wTxDataRate = RATE_1M;
+	unsigned char byACKRate = RATE_1M;
+	unsigned char byCCKBasicRate = RATE_1M;
+	unsigned char byOFDMBasicRate = RATE_24M;
+	PWLAN_IE_SUPP_RATES pSupportRateIEs = NULL;
+	PWLAN_IE_SUPP_RATES pExtSupportRateIEs = NULL;
+
+	if ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) ||
+	    (pMgmt->eCurrMode == WMAC_MODE_ESS_AP)) {
+		// Adhoc Tx rate decided from node DB
+		if (BSSDBbIsSTAInNodeDB(pMgmt, pbyDestAddress, &uNodeIndex)) {
+			wTxDataRate = (pMgmt->sNodeDBTable[uNodeIndex].wTxDataRate);
+			pSupportRateIEs = (PWLAN_IE_SUPP_RATES) (pMgmt->sNodeDBTable[uNodeIndex].abyCurrSuppRates);
+			pExtSupportRateIEs = (PWLAN_IE_SUPP_RATES) (pMgmt->sNodeDBTable[uNodeIndex].abyCurrExtSuppRates);
+		} else {
+			if (pMgmt->eCurrentPHYMode != PHY_TYPE_11A) {
+				wTxDataRate = RATE_2M;
+			} else {
+				wTxDataRate = RATE_24M;
+			}
+			pSupportRateIEs = (PWLAN_IE_SUPP_RATES) pMgmt->abyCurrSuppRates;
+			pExtSupportRateIEs = (PWLAN_IE_SUPP_RATES) pMgmt->abyCurrExtSuppRates;
+		}
+	} else { // Infrastructure: rate decided from AP Node, index = 0
 
 		wTxDataRate = (pMgmt->sNodeDBTable[0].wTxDataRate);
 #ifdef	PLICE_DEBUG
 		printk(KERN_DEBUG "GetTxRate:AP MAC is %pM,TxRate is %d\n",
-				pMgmt->sNodeDBTable[0].abyMACAddr, wTxDataRate);
+		       pMgmt->sNodeDBTable[0].abyMACAddr, wTxDataRate);
 #endif
 
-
-        pSupportRateIEs = (PWLAN_IE_SUPP_RATES) pMgmt->abyCurrSuppRates;
-        pExtSupportRateIEs = (PWLAN_IE_SUPP_RATES) pMgmt->abyCurrExtSuppRates;
-    }
-    byACKRate = VNTWIFIbyGetACKTxRate(  (unsigned char) wTxDataRate,
-                                        pSupportRateIEs,
-                                        pExtSupportRateIEs
-                                        );
-    if (byACKRate > (unsigned char) wTxDataRate) {
-        byACKRate = (unsigned char) wTxDataRate;
-    }
-    byCCKBasicRate = VNTWIFIbyGetACKTxRate( RATE_11M,
-                                            pSupportRateIEs,
-                                            pExtSupportRateIEs
-                                            );
-    byOFDMBasicRate = VNTWIFIbyGetACKTxRate(RATE_54M,
-                                            pSupportRateIEs,
-                                            pExtSupportRateIEs
-                                            );
-    *pwTxDataRate = wTxDataRate;
-    *pbyACKRate = byACKRate;
-    *pbyCCKBasicRate = byCCKBasicRate;
-    *pbyOFDMBasicRate = byOFDMBasicRate;
-    return;
+		pSupportRateIEs = (PWLAN_IE_SUPP_RATES) pMgmt->abyCurrSuppRates;
+		pExtSupportRateIEs = (PWLAN_IE_SUPP_RATES) pMgmt->abyCurrExtSuppRates;
+	}
+	byACKRate = VNTWIFIbyGetACKTxRate((unsigned char) wTxDataRate,
+					    pSupportRateIEs,
+					    pExtSupportRateIEs
+);
+	if (byACKRate > (unsigned char) wTxDataRate) {
+		byACKRate = (unsigned char) wTxDataRate;
+	}
+	byCCKBasicRate = VNTWIFIbyGetACKTxRate(RATE_11M,
+						pSupportRateIEs,
+						pExtSupportRateIEs
+);
+	byOFDMBasicRate = VNTWIFIbyGetACKTxRate(RATE_54M,
+						pSupportRateIEs,
+						pExtSupportRateIEs
+);
+	*pwTxDataRate = wTxDataRate;
+	*pbyACKRate = byACKRate;
+	*pbyCCKBasicRate = byCCKBasicRate;
+	*pbyOFDMBasicRate = byOFDMBasicRate;
+	return;
 }
 
 unsigned char
 VNTWIFIbyGetKeyCypher(
-    void *pMgmtHandle,
-    bool bGroupKey
-    )
+	void *pMgmtHandle,
+	bool bGroupKey
+)
 {
-    PSMgmtObject    pMgmt = (PSMgmtObject)pMgmtHandle;
+	PSMgmtObject    pMgmt = (PSMgmtObject)pMgmtHandle;
 
-    if (bGroupKey == true) {
-        return (pMgmt->byCSSGK);
-    } else {
-        return (pMgmt->byCSSPK);
-    }
+	if (bGroupKey == true) {
+		return pMgmt->byCSSGK;
+	} else {
+		return pMgmt->byCSSPK;
+	}
 }
 
-
 /*
-bool
-VNTWIFIbInit(
-    void *pAdapterHandler,
-    void **pMgmtHandler
-    )
-{
-
-    PSMgmtObject        pMgmt = NULL;
-    unsigned int ii;
-
-
-    pMgmt = (PSMgmtObject)kmalloc(sizeof(SMgmtObject), (int)GFP_ATOMIC);
-    if (pMgmt == NULL) {
-        *pMgmtHandler = NULL;
-        return false;
-    }
-
-    memset(pMgmt, 0, sizeof(SMgmtObject));
-    pMgmt->pAdapter = (void *) pAdapterHandler;
-
-    // should initial MAC address abyMACAddr
-    for(ii=0;ii<WLAN_BSSID_LEN;ii++) {
-        pMgmt->abyDesireBSSID[ii] = 0xFF;
-    }
-    pMgmt->pbyPSPacketPool = &pMgmt->byPSPacketPool[0];
-    pMgmt->pbyMgmtPacketPool = &pMgmt->byMgmtPacketPool[0];
-    pMgmt->byCSSPK = KEY_CTL_NONE;
-    pMgmt->byCSSGK = KEY_CTL_NONE;
-    pMgmt->wIBSSBeaconPeriod = DEFAULT_IBSS_BI;
-
-    pMgmt->cbFreeCmdQueue = CMD_Q_SIZE;
-    pMgmt->uCmdDequeueIdx = 0;
-    pMgmt->uCmdEnqueueIdx = 0;
-    pMgmt->eCommandState = WLAN_CMD_STATE_IDLE;
-    pMgmt->bCmdStop = false;
-    pMgmt->bCmdRunning = false;
-
-    *pMgmtHandler = pMgmt;
-    return true;
-}
+  bool
+  VNTWIFIbInit(
+  void *pAdapterHandler,
+  void **pMgmtHandler
+) {
+  PSMgmtObject        pMgmt = NULL;
+  unsigned int ii;
+
+  pMgmt = (PSMgmtObject)kmalloc(sizeof(SMgmtObject), (int)GFP_ATOMIC);
+  if (pMgmt == NULL) {
+  *pMgmtHandler = NULL;
+  return false;
+  }
+
+  memset(pMgmt, 0, sizeof(SMgmtObject));
+  pMgmt->pAdapter = (void *) pAdapterHandler;
+
+  // should initial MAC address abyMACAddr
+  for (ii=0; ii<WLAN_BSSID_LEN; ii++) {
+  pMgmt->abyDesireBSSID[ii] = 0xFF;
+  }
+  pMgmt->pbyPSPacketPool = &pMgmt->byPSPacketPool[0];
+  pMgmt->pbyMgmtPacketPool = &pMgmt->byMgmtPacketPool[0];
+  pMgmt->byCSSPK = KEY_CTL_NONE;
+  pMgmt->byCSSGK = KEY_CTL_NONE;
+  pMgmt->wIBSSBeaconPeriod = DEFAULT_IBSS_BI;
+
+  pMgmt->cbFreeCmdQueue = CMD_Q_SIZE;
+  pMgmt->uCmdDequeueIdx = 0;
+  pMgmt->uCmdEnqueueIdx = 0;
+  pMgmt->eCommandState = WLAN_CMD_STATE_IDLE;
+  pMgmt->bCmdStop = false;
+  pMgmt->bCmdRunning = false;
+
+  *pMgmtHandler = pMgmt;
+  return true;
+  }
 */
 
-
-
 bool
-VNTWIFIbSetPMKIDCache (
-    void *pMgmtObject,
-    unsigned long ulCount,
-    void *pPMKIDInfo
-    )
+VNTWIFIbSetPMKIDCache(
+	void *pMgmtObject,
+	unsigned long ulCount,
+	void *pPMKIDInfo
+)
 {
-    PSMgmtObject    pMgmt = (PSMgmtObject) pMgmtObject;
-
-    if (ulCount > MAX_PMKID_CACHE) {
-        return (false);
-    }
-    pMgmt->gsPMKIDCache.BSSIDInfoCount = ulCount;
-    memcpy(pMgmt->gsPMKIDCache.BSSIDInfo, pPMKIDInfo, (ulCount*sizeof(PMKIDInfo)));
-    return (true);
+	PSMgmtObject    pMgmt = (PSMgmtObject) pMgmtObject;
+
+	if (ulCount > MAX_PMKID_CACHE) {
+		return false;
+	}
+	pMgmt->gsPMKIDCache.BSSIDInfoCount = ulCount;
+	memcpy(pMgmt->gsPMKIDCache.BSSIDInfo, pPMKIDInfo, (ulCount*sizeof(PMKIDInfo)));
+	return true;
 }
 
-
-
 unsigned short
 VNTWIFIwGetMaxSupportRate(
-    void *pMgmtObject
-    )
+	void *pMgmtObject
+)
 {
-    unsigned short wRate = RATE_54M;
-    PSMgmtObject    pMgmt = (PSMgmtObject) pMgmtObject;
-
-    for(wRate = RATE_54M; wRate > RATE_1M; wRate--) {
-        if (pMgmt->sNodeDBTable[0].wSuppRate & (1<<wRate)) {
-            return (wRate);
-        }
-    }
-    if (pMgmt->eCurrentPHYMode == PHY_TYPE_11A) {
-        return (RATE_6M);
-    } else {
-        return (RATE_1M);
-    }
+	unsigned short wRate = RATE_54M;
+	PSMgmtObject    pMgmt = (PSMgmtObject) pMgmtObject;
+
+	for (wRate = RATE_54M; wRate > RATE_1M; wRate--) {
+		if (pMgmt->sNodeDBTable[0].wSuppRate & (1<<wRate)) {
+			return wRate;
+		}
+	}
+	if (pMgmt->eCurrentPHYMode == PHY_TYPE_11A) {
+		return RATE_6M;
+	} else {
+		return RATE_1M;
+	}
 }
 
-
 void
-VNTWIFIvSet11h (
-    void *pMgmtObject,
-    bool b11hEnable
-    )
+VNTWIFIvSet11h(
+	void *pMgmtObject,
+	bool b11hEnable
+)
 {
-    PSMgmtObject    pMgmt = (PSMgmtObject) pMgmtObject;
+	PSMgmtObject    pMgmt = (PSMgmtObject) pMgmtObject;
 
-    pMgmt->b11hEnable = b11hEnable;
+	pMgmt->b11hEnable = b11hEnable;
 }
 
 bool
 VNTWIFIbMeasureReport(
-    void *pMgmtObject,
-    bool bEndOfReport,
-    void *pvMeasureEID,
-    unsigned char byReportMode,
-    unsigned char byBasicMap,
-    unsigned char byCCAFraction,
-    unsigned char *pbyRPIs
-    )
+	void *pMgmtObject,
+	bool bEndOfReport,
+	void *pvMeasureEID,
+	unsigned char byReportMode,
+	unsigned char byBasicMap,
+	unsigned char byCCAFraction,
+	unsigned char *pbyRPIs
+)
 {
-    PSMgmtObject    pMgmt = (PSMgmtObject) pMgmtObject;
-    unsigned char *pbyCurrentEID = (unsigned char *) (pMgmt->pCurrMeasureEIDRep);
-
-    //spin_lock_irq(&pDevice->lock);
-    if ((pvMeasureEID != NULL) &&
-        (pMgmt->uLengthOfRepEIDs < (WLAN_A3FR_MAXLEN - sizeof(MEASEURE_REP) - sizeof(WLAN_80211HDR_A3) - 3))
-        ) {
-        pMgmt->pCurrMeasureEIDRep->byElementID = WLAN_EID_MEASURE_REP;
-        pMgmt->pCurrMeasureEIDRep->len = 3;
-        pMgmt->pCurrMeasureEIDRep->byToken = ((PWLAN_IE_MEASURE_REQ) pvMeasureEID)->byToken;
-        pMgmt->pCurrMeasureEIDRep->byMode = byReportMode;
-        pMgmt->pCurrMeasureEIDRep->byType = ((PWLAN_IE_MEASURE_REQ) pvMeasureEID)->byType;
-        switch (pMgmt->pCurrMeasureEIDRep->byType) {
-            case MEASURE_TYPE_BASIC :
-                pMgmt->pCurrMeasureEIDRep->len += sizeof(MEASEURE_REP_BASIC);
-                memcpy(   &(pMgmt->pCurrMeasureEIDRep->sRep.sBasic),
-                            &(((PWLAN_IE_MEASURE_REQ) pvMeasureEID)->sReq),
-                            sizeof(MEASEURE_REQ));
-                pMgmt->pCurrMeasureEIDRep->sRep.sBasic.byMap = byBasicMap;
-                break;
-            case MEASURE_TYPE_CCA :
-                pMgmt->pCurrMeasureEIDRep->len += sizeof(MEASEURE_REP_CCA);
-                memcpy(   &(pMgmt->pCurrMeasureEIDRep->sRep.sCCA),
-                            &(((PWLAN_IE_MEASURE_REQ) pvMeasureEID)->sReq),
-                            sizeof(MEASEURE_REQ));
-                pMgmt->pCurrMeasureEIDRep->sRep.sCCA.byCCABusyFraction = byCCAFraction;
-                break;
-            case MEASURE_TYPE_RPI :
-                pMgmt->pCurrMeasureEIDRep->len += sizeof(MEASEURE_REP_RPI);
-                memcpy(   &(pMgmt->pCurrMeasureEIDRep->sRep.sRPI),
-                            &(((PWLAN_IE_MEASURE_REQ) pvMeasureEID)->sReq),
-                            sizeof(MEASEURE_REQ));
-                memcpy(pMgmt->pCurrMeasureEIDRep->sRep.sRPI.abyRPIdensity, pbyRPIs, 8);
-                break;
-            default :
-                break;
-        }
-        pbyCurrentEID += (2 + pMgmt->pCurrMeasureEIDRep->len);
-        pMgmt->uLengthOfRepEIDs += (2 + pMgmt->pCurrMeasureEIDRep->len);
-        pMgmt->pCurrMeasureEIDRep = (PWLAN_IE_MEASURE_REP) pbyCurrentEID;
-    }
-    if (bEndOfReport == true) {
-        IEEE11hbMSRRepTx(pMgmt);
-    }
-    //spin_unlock_irq(&pDevice->lock);
-    return (true);
+	PSMgmtObject    pMgmt = (PSMgmtObject) pMgmtObject;
+	unsigned char *pbyCurrentEID = (unsigned char *)(pMgmt->pCurrMeasureEIDRep);
+
+	//spin_lock_irq(&pDevice->lock);
+	if ((pvMeasureEID != NULL) &&
+	    (pMgmt->uLengthOfRepEIDs < (WLAN_A3FR_MAXLEN - sizeof(MEASEURE_REP) - sizeof(WLAN_80211HDR_A3) - 3))
+) {
+		pMgmt->pCurrMeasureEIDRep->byElementID = WLAN_EID_MEASURE_REP;
+		pMgmt->pCurrMeasureEIDRep->len = 3;
+		pMgmt->pCurrMeasureEIDRep->byToken = ((PWLAN_IE_MEASURE_REQ)pvMeasureEID)->byToken;
+		pMgmt->pCurrMeasureEIDRep->byMode = byReportMode;
+		pMgmt->pCurrMeasureEIDRep->byType = ((PWLAN_IE_MEASURE_REQ) pvMeasureEID)->byType;
+		switch (pMgmt->pCurrMeasureEIDRep->byType) {
+		case MEASURE_TYPE_BASIC:
+			pMgmt->pCurrMeasureEIDRep->len += sizeof(MEASEURE_REP_BASIC);
+			memcpy(&(pMgmt->pCurrMeasureEIDRep->sRep.sBasic),
+			       &(((PWLAN_IE_MEASURE_REQ) pvMeasureEID)->sReq),
+			       sizeof(MEASEURE_REQ));
+			pMgmt->pCurrMeasureEIDRep->sRep.sBasic.byMap = byBasicMap;
+			break;
+		case MEASURE_TYPE_CCA:
+			pMgmt->pCurrMeasureEIDRep->len += sizeof(MEASEURE_REP_CCA);
+			memcpy(&(pMgmt->pCurrMeasureEIDRep->sRep.sCCA),
+			       &(((PWLAN_IE_MEASURE_REQ) pvMeasureEID)->sReq),
+			       sizeof(MEASEURE_REQ));
+			pMgmt->pCurrMeasureEIDRep->sRep.sCCA.byCCABusyFraction = byCCAFraction;
+			break;
+		case MEASURE_TYPE_RPI:
+			pMgmt->pCurrMeasureEIDRep->len += sizeof(MEASEURE_REP_RPI);
+			memcpy(&(pMgmt->pCurrMeasureEIDRep->sRep.sRPI),
+			       &(((PWLAN_IE_MEASURE_REQ) pvMeasureEID)->sReq),
+			       sizeof(MEASEURE_REQ));
+			memcpy(pMgmt->pCurrMeasureEIDRep->sRep.sRPI.abyRPIdensity, pbyRPIs, 8);
+			break;
+		default:
+			break;
+		}
+		pbyCurrentEID += (2 + pMgmt->pCurrMeasureEIDRep->len);
+		pMgmt->uLengthOfRepEIDs += (2 + pMgmt->pCurrMeasureEIDRep->len);
+		pMgmt->pCurrMeasureEIDRep = (PWLAN_IE_MEASURE_REP) pbyCurrentEID;
+	}
+	if (bEndOfReport == true) {
+		IEEE11hbMSRRepTx(pMgmt);
+	}
+	//spin_unlock_irq(&pDevice->lock);
+	return true;
 }
 
-
 bool
 VNTWIFIbChannelSwitch(
-    void *pMgmtObject,
-    unsigned char byNewChannel
-    )
+	void *pMgmtObject,
+	unsigned char byNewChannel
+)
 {
-    PSMgmtObject    pMgmt = (PSMgmtObject) pMgmtObject;
+	PSMgmtObject    pMgmt = (PSMgmtObject) pMgmtObject;
 
-    //spin_lock_irq(&pDevice->lock);
-    pMgmt->uCurrChannel = byNewChannel;
-    pMgmt->bSwitchChannel = false;
-    //spin_unlock_irq(&pDevice->lock);
-    return true;
+	//spin_lock_irq(&pDevice->lock);
+	pMgmt->uCurrChannel = byNewChannel;
+	pMgmt->bSwitchChannel = false;
+	//spin_unlock_irq(&pDevice->lock);
+	return true;
 }
 
 /*
-bool
-VNTWIFIbRadarPresent(
-    void *pMgmtObject,
-    unsigned char byChannel
-    )
-{
-    PSMgmtObject    pMgmt = (PSMgmtObject) pMgmtObject;
-    if ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) &&
-        (byChannel == (unsigned char) pMgmt->uCurrChannel) &&
-        (pMgmt->bSwitchChannel != true) &&
-        (pMgmt->b11hEnable == true)) {
-        if (!compare_ether_addr(pMgmt->abyIBSSDFSOwner, CARDpGetCurrentAddress(pMgmt->pAdapter))) {
-            pMgmt->byNewChannel = CARDbyAutoChannelSelect(pMgmt->pAdapter,(unsigned char) pMgmt->uCurrChannel);
-            pMgmt->bSwitchChannel = true;
-        }
-        BEACONbSendBeacon(pMgmt);
-        CARDbChannelSwitch(pMgmt->pAdapter, 0, pMgmt->byNewChannel, 10);
-    }
-    return true;
-}
+  bool
+  VNTWIFIbRadarPresent(
+  void *pMgmtObject,
+  unsigned char byChannel
+) {
+  PSMgmtObject    pMgmt = (PSMgmtObject) pMgmtObject;
+  if ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) &&
+  (byChannel == (unsigned char) pMgmt->uCurrChannel) &&
+  (pMgmt->bSwitchChannel != true) &&
+  (pMgmt->b11hEnable == true)) {
+  if (!compare_ether_addr(pMgmt->abyIBSSDFSOwner, CARDpGetCurrentAddress(pMgmt->pAdapter))) {
+  pMgmt->byNewChannel = CARDbyAutoChannelSelect(pMgmt->pAdapter,(unsigned char) pMgmt->uCurrChannel);
+  pMgmt->bSwitchChannel = true;
+  }
+  BEACONbSendBeacon(pMgmt);
+  CARDbChannelSwitch(pMgmt->pAdapter, 0, pMgmt->byNewChannel, 10);
+  }
+  return true;
+  }
 */
-
diff --git a/drivers/staging/vt6655/vntwifi.h b/drivers/staging/vt6655/vntwifi.h
index f4327ab..4b01ebd 100644
--- a/drivers/staging/vt6655/vntwifi.h
+++ b/drivers/staging/vt6655/vntwifi.h
@@ -64,244 +64,224 @@
 
 // Pre-configured Authenticaiton Mode (from XP)
 typedef enum tagWMAC_AUTHENTICATION_MODE {
-
-    WMAC_AUTH_OPEN,
-    WMAC_AUTH_SHAREKEY,
-    WMAC_AUTH_AUTO,
-    WMAC_AUTH_WPA,
-    WMAC_AUTH_WPAPSK,
-    WMAC_AUTH_WPANONE,
-    WMAC_AUTH_WPA2,
-    WMAC_AUTH_WPA2PSK,
-    WMAC_AUTH_MAX       // Not a real mode, defined as upper bound
-
+	WMAC_AUTH_OPEN,
+	WMAC_AUTH_SHAREKEY,
+	WMAC_AUTH_AUTO,
+	WMAC_AUTH_WPA,
+	WMAC_AUTH_WPAPSK,
+	WMAC_AUTH_WPANONE,
+	WMAC_AUTH_WPA2,
+	WMAC_AUTH_WPA2PSK,
+	WMAC_AUTH_MAX       // Not a real mode, defined as upper bound
 } WMAC_AUTHENTICATION_MODE, *PWMAC_AUTHENTICATION_MODE;
 
 typedef enum tagWMAC_ENCRYPTION_MODE {
-
-    WMAC_ENCRYPTION_WEPEnabled,
-    WMAC_ENCRYPTION_WEPDisabled,
-    WMAC_ENCRYPTION_WEPKeyAbsent,
-    WMAC_ENCRYPTION_WEPNotSupported,
-    WMAC_ENCRYPTION_TKIPEnabled,
-    WMAC_ENCRYPTION_TKIPKeyAbsent,
-    WMAC_ENCRYPTION_AESEnabled,
-    WMAC_ENCRYPTION_AESKeyAbsent
-
+	WMAC_ENCRYPTION_WEPEnabled,
+	WMAC_ENCRYPTION_WEPDisabled,
+	WMAC_ENCRYPTION_WEPKeyAbsent,
+	WMAC_ENCRYPTION_WEPNotSupported,
+	WMAC_ENCRYPTION_TKIPEnabled,
+	WMAC_ENCRYPTION_TKIPKeyAbsent,
+	WMAC_ENCRYPTION_AESEnabled,
+	WMAC_ENCRYPTION_AESKeyAbsent
 } WMAC_ENCRYPTION_MODE, *PWMAC_ENCRYPTION_MODE;
 
 // Pre-configured Mode (from XP)
 
 typedef enum tagWMAC_CONFIG_MODE {
-
-    WMAC_CONFIG_ESS_STA = 0,
-    WMAC_CONFIG_IBSS_STA,
-    WMAC_CONFIG_AUTO,
-    WMAC_CONFIG_AP
-
+	WMAC_CONFIG_ESS_STA = 0,
+	WMAC_CONFIG_IBSS_STA,
+	WMAC_CONFIG_AUTO,
+	WMAC_CONFIG_AP
 } WMAC_CONFIG_MODE, *PWMAC_CONFIG_MODE;
 
-
-
 typedef enum tagWMAC_POWER_MODE {
-
-    WMAC_POWER_CAM,
-    WMAC_POWER_FAST,
-    WMAC_POWER_MAX
-
+	WMAC_POWER_CAM,
+	WMAC_POWER_FAST,
+	WMAC_POWER_MAX
 } WMAC_POWER_MODE, *PWMAC_POWER_MODE;
 
 #define VNTWIFIbIsShortSlotTime(wCapInfo)               \
-        WLAN_GET_CAP_INFO_SHORTSLOTTIME(wCapInfo)       \
+	WLAN_GET_CAP_INFO_SHORTSLOTTIME(wCapInfo)       \
 
 #define VNTWIFIbIsProtectMode(byERP)                    \
-        ((byERP & WLAN_EID_ERP_USE_PROTECTION) != 0)    \
+	((byERP & WLAN_EID_ERP_USE_PROTECTION) != 0)    \
 
 #define VNTWIFIbIsBarkerMode(byERP)                     \
-        ((byERP & WLAN_EID_ERP_BARKER_MODE) != 0)       \
+	((byERP & WLAN_EID_ERP_BARKER_MODE) != 0)       \
 
 #define VNTWIFIbIsShortPreamble(wCapInfo)               \
-        WLAN_GET_CAP_INFO_SHORTPREAMBLE(wCapInfo)       \
-
-#define VNTWIFIbIsEncryption(wCapInfo)                  \
-        WLAN_GET_CAP_INFO_PRIVACY(wCapInfo)             \
+	WLAN_GET_CAP_INFO_SHORTPREAMBLE(wCapInfo)       \
 
-#define VNTWIFIbIsESS(wCapInfo)                         \
-        WLAN_GET_CAP_INFO_ESS(wCapInfo)                 \
+#define VNTWIFIbIsEncryption(wCapInfo)		\
+	WLAN_GET_CAP_INFO_PRIVACY(wCapInfo)	\
 
+#define VNTWIFIbIsESS(wCapInfo)			\
+	WLAN_GET_CAP_INFO_ESS(wCapInfo)		\
 
 /*---------------------  Export Classes  ----------------------------*/
 
 /*---------------------  Export Variables  --------------------------*/
 
-
 /*---------------------  Export Types  ------------------------------*/
 
-
 /*---------------------  Export Functions  --------------------------*/
 
 void
-VNTWIFIvSetIBSSParameter (
-    void *pMgmtHandle,
-    unsigned short wBeaconPeriod,
-    unsigned short wATIMWindow,
-    unsigned int uChannel
-    );
+VNTWIFIvSetIBSSParameter(
+	void *pMgmtHandle,
+	unsigned short wBeaconPeriod,
+	unsigned short wATIMWindow,
+	unsigned int uChannel
+);
 
 void
-VNTWIFIvSetOPMode (
-    void *pMgmtHandle,
-    WMAC_CONFIG_MODE eOPMode
-    );
+VNTWIFIvSetOPMode(
+	void *pMgmtHandle,
+	WMAC_CONFIG_MODE eOPMode
+);
 
 PWLAN_IE_SSID
 VNTWIFIpGetCurrentSSID(
-    void *pMgmtHandle
-    );
+	void *pMgmtHandle
+);
 
 unsigned int
 VNTWIFIpGetCurrentChannel(
-    void *pMgmtHandle
-    );
+	void *pMgmtHandle
+);
 
 unsigned short
-VNTWIFIwGetAssocID (
-    void *pMgmtHandle
-    );
+VNTWIFIwGetAssocID(
+	void *pMgmtHandle
+);
 
 unsigned char
-VNTWIFIbyGetMaxSupportRate (
-    PWLAN_IE_SUPP_RATES pSupportRateIEs,
-    PWLAN_IE_SUPP_RATES pExtSupportRateIEs
-    );
+VNTWIFIbyGetMaxSupportRate(
+	PWLAN_IE_SUPP_RATES pSupportRateIEs,
+	PWLAN_IE_SUPP_RATES pExtSupportRateIEs
+);
 
 unsigned char
-VNTWIFIbyGetACKTxRate (
-    unsigned char byRxDataRate,
-    PWLAN_IE_SUPP_RATES pSupportRateIEs,
-    PWLAN_IE_SUPP_RATES pExtSupportRateIEs
-    );
+VNTWIFIbyGetACKTxRate(
+	unsigned char byRxDataRate,
+	PWLAN_IE_SUPP_RATES pSupportRateIEs,
+	PWLAN_IE_SUPP_RATES pExtSupportRateIEs
+);
 
 void
-VNTWIFIvSetAuthenticationMode (
-    void *pMgmtHandle,
-    WMAC_AUTHENTICATION_MODE eAuthMode
-    );
+VNTWIFIvSetAuthenticationMode(
+	void *pMgmtHandle,
+	WMAC_AUTHENTICATION_MODE eAuthMode
+);
 
 void
-VNTWIFIvSetEncryptionMode (
-    void *pMgmtHandle,
-    WMAC_ENCRYPTION_MODE eEncryptionMode
-    );
-
+VNTWIFIvSetEncryptionMode(
+	void *pMgmtHandle,
+	WMAC_ENCRYPTION_MODE eEncryptionMode
+);
 
 bool
 VNTWIFIbConfigPhyMode(
-    void *pMgmtHandle,
-    CARD_PHY_TYPE ePhyType
-    );
+	void *pMgmtHandle,
+	CARD_PHY_TYPE ePhyType
+);
 
 void
 VNTWIFIbGetConfigPhyMode(
-    void *pMgmtHandle,
-    void *pePhyType
-    );
+	void *pMgmtHandle,
+	void *pePhyType
+);
 
 void
 VNTWIFIvQueryBSSList(void *pMgmtHandle, unsigned int *puBSSCount,
-		void **pvFirstBSS);
+		     void **pvFirstBSS);
 
 void
-VNTWIFIvGetNextBSS (
-    void *pMgmtHandle,
-    void *pvCurrentBSS,
-    void **pvNextBSS
-    );
-
-
+VNTWIFIvGetNextBSS(
+	void *pMgmtHandle,
+	void *pvCurrentBSS,
+	void **pvNextBSS
+);
 
 void
 VNTWIFIvUpdateNodeTxCounter(
-    void *pMgmtHandle,
-    unsigned char *pbyDestAddress,
-    bool bTxOk,
-    unsigned short wRate,
-    unsigned char *pbyTxFailCount
-    );
-
+	void *pMgmtHandle,
+	unsigned char *pbyDestAddress,
+	bool bTxOk,
+	unsigned short wRate,
+	unsigned char *pbyTxFailCount
+);
 
 void
 VNTWIFIvGetTxRate(
-    void *pMgmtHandle,
-    unsigned char *pbyDestAddress,
-    unsigned short *pwTxDataRate,
-    unsigned char *pbyACKRate,
-    unsigned char *pbyCCKBasicRate,
-    unsigned char *pbyOFDMBasicRate
-    );
+	void *pMgmtHandle,
+	unsigned char *pbyDestAddress,
+	unsigned short *pwTxDataRate,
+	unsigned char *pbyACKRate,
+	unsigned char *pbyCCKBasicRate,
+	unsigned char *pbyOFDMBasicRate
+);
 /*
-bool
-VNTWIFIbInit(
-    void *pAdapterHandler,
-    void **pMgmtHandler
-    );
+  bool
+  VNTWIFIbInit(
+  void *pAdapterHandler,
+  void **pMgmtHandler
+);
 */
 
 unsigned char
 VNTWIFIbyGetKeyCypher(
-    void *pMgmtHandle,
-    bool bGroupKey
-    );
-
-
-
+	void *pMgmtHandle,
+	bool bGroupKey
+);
 
 bool
-VNTWIFIbSetPMKIDCache (
-    void *pMgmtObject,
-    unsigned long ulCount,
-    void *pPMKIDInfo
-    );
+VNTWIFIbSetPMKIDCache(
+	void *pMgmtObject,
+	unsigned long ulCount,
+	void *pPMKIDInfo
+);
 
 bool
-VNTWIFIbCommandRunning (
-    void *pMgmtObject
-    );
+VNTWIFIbCommandRunning(
+	void *pMgmtObject
+);
 
 unsigned short
 VNTWIFIwGetMaxSupportRate(
-    void *pMgmtObject
-    );
+	void *pMgmtObject
+);
 
 // for 802.11h
 void
-VNTWIFIvSet11h (
-    void *pMgmtObject,
-    bool b11hEnable
-    );
+VNTWIFIvSet11h(
+	void *pMgmtObject,
+	bool b11hEnable
+);
 
 bool
 VNTWIFIbMeasureReport(
-    void *pMgmtObject,
-    bool bEndOfReport,
-    void *pvMeasureEID,
-    unsigned char byReportMode,
-    unsigned char byBasicMap,
-    unsigned char byCCAFraction,
-    unsigned char *pbyRPIs
-    );
+	void *pMgmtObject,
+	bool bEndOfReport,
+	void *pvMeasureEID,
+	unsigned char byReportMode,
+	unsigned char byBasicMap,
+	unsigned char byCCAFraction,
+	unsigned char *pbyRPIs
+);
 
 bool
 VNTWIFIbChannelSwitch(
-    void *pMgmtObject,
-    unsigned char byNewChannel
-    );
+	void *pMgmtObject,
+	unsigned char byNewChannel
+);
 /*
-bool
-VNTWIFIbRadarPresent(
-    void *pMgmtObject,
-    unsigned char byChannel
-    );
+  bool
+  VNTWIFIbRadarPresent(
+  void *pMgmtObject,
+  unsigned char byChannel
+);
 */
 
 #endif //__VNTWIFI_H__
diff --git a/drivers/staging/vt6655/wcmd.c b/drivers/staging/vt6655/wcmd.c
index 101c735..d551653 100644
--- a/drivers/staging/vt6655/wcmd.c
+++ b/drivers/staging/vt6655/wcmd.c
@@ -56,48 +56,40 @@
 
 /*---------------------  Static Definitions -------------------------*/
 
-
-
-
 /*---------------------  Static Classes  ----------------------------*/
 
 /*---------------------  Static Variables  --------------------------*/
-static int          msglevel                =MSG_LEVEL_INFO;
+static int msglevel = MSG_LEVEL_INFO;
 //static int          msglevel                =MSG_LEVEL_DEBUG;
 /*---------------------  Static Functions  --------------------------*/
 
 static
 void
 s_vProbeChannel(
-    PSDevice pDevice
-    );
-
+	PSDevice pDevice
+);
 
 static
 PSTxMgmtPacket
 s_MgrMakeProbeRequest(
-    PSDevice pDevice,
-    PSMgmtObject pMgmt,
-    unsigned char *pScanBSSID,
-    PWLAN_IE_SSID pSSID,
-    PWLAN_IE_SUPP_RATES pCurrRates,
-    PWLAN_IE_SUPP_RATES pCurrExtSuppRates
-    );
-
+	PSDevice pDevice,
+	PSMgmtObject pMgmt,
+	unsigned char *pScanBSSID,
+	PWLAN_IE_SSID pSSID,
+	PWLAN_IE_SUPP_RATES pCurrRates,
+	PWLAN_IE_SUPP_RATES pCurrExtSuppRates
+);
 
 static
 bool
-s_bCommandComplete (
-    PSDevice pDevice
-    );
+s_bCommandComplete(
+	PSDevice pDevice
+);
 
 /*---------------------  Export Variables  --------------------------*/
 
-
 /*---------------------  Export Functions  --------------------------*/
 
-
-
 /*
  * Description:
  *      Stop AdHoc beacon during scan process
@@ -115,44 +107,37 @@ static
 void
 vAdHocBeaconStop(PSDevice  pDevice)
 {
-
-    PSMgmtObject    pMgmt = &(pDevice->sMgmtObj);
-    bool bStop;
-
-    /*
-     * temporarily stop Beacon packet for AdHoc Server
-     * if all of the following conditions are met:
-     *  (1) STA is in AdHoc mode
-     *  (2) VT3253 is programmed as automatic Beacon Transmitting
-     *  (3) One of the following conditions is met
-     *      (3.1) AdHoc channel is in B/G band and the
-     *      current scan channel is in A band
-     *      or
-     *      (3.2) AdHoc channel is in A mode
-     */
-    bStop = false;
-    if ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) &&
-    (pMgmt->eCurrState >= WMAC_STATE_STARTED))
-    {
-        if ((pMgmt->uIBSSChannel <=  CB_MAX_CHANNEL_24G) &&
-             (pMgmt->uScanChannel > CB_MAX_CHANNEL_24G))
-        {
-            bStop = true;
-        }
-        if (pMgmt->uIBSSChannel >  CB_MAX_CHANNEL_24G)
-        {
-            bStop = true;
-        }
-    }
-
-    if (bStop)
-    {
-        MACvRegBitsOff(pDevice->PortOffset, MAC_REG_TCR, TCR_AUTOBCNTX);
-    }
-
+	PSMgmtObject    pMgmt = &(pDevice->sMgmtObj);
+	bool bStop;
+
+	/*
+	 * temporarily stop Beacon packet for AdHoc Server
+	 * if all of the following conditions are met:
+	 *  (1) STA is in AdHoc mode
+	 *  (2) VT3253 is programmed as automatic Beacon Transmitting
+	 *  (3) One of the following conditions is met
+	 *      (3.1) AdHoc channel is in B/G band and the
+	 *      current scan channel is in A band
+	 *      or
+	 *      (3.2) AdHoc channel is in A mode
+	 */
+	bStop = false;
+	if ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) &&
+	    (pMgmt->eCurrState >= WMAC_STATE_STARTED)) {
+		if ((pMgmt->uIBSSChannel <=  CB_MAX_CHANNEL_24G) &&
+		    (pMgmt->uScanChannel > CB_MAX_CHANNEL_24G)) {
+			bStop = true;
+		}
+		if (pMgmt->uIBSSChannel >  CB_MAX_CHANNEL_24G) {
+			bStop = true;
+		}
+	}
+
+	if (bStop) {
+		MACvRegBitsOff(pDevice->PortOffset, MAC_REG_TCR, TCR_AUTOBCNTX);
+	}
 } /* vAdHocBeaconStop */
 
-
 /*
  * Description:
  *      Restart AdHoc beacon after scan process complete
@@ -170,27 +155,20 @@ static
 void
 vAdHocBeaconRestart(PSDevice pDevice)
 {
-    PSMgmtObject    pMgmt = &(pDevice->sMgmtObj);
-
-    /*
-     * Restart Beacon packet for AdHoc Server
-     * if all of the following coditions are met:
-     *  (1) STA is in AdHoc mode
-     *  (2) VT3253 is programmed as automatic Beacon Transmitting
-     */
-    if ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) &&
-    (pMgmt->eCurrState >= WMAC_STATE_STARTED))
-    {
-         MACvRegBitsOn(pDevice->PortOffset, MAC_REG_TCR, TCR_AUTOBCNTX);
-    }
-
+	PSMgmtObject    pMgmt = &(pDevice->sMgmtObj);
+
+	/*
+	 * Restart Beacon packet for AdHoc Server
+	 * if all of the following coditions are met:
+	 *  (1) STA is in AdHoc mode
+	 *  (2) VT3253 is programmed as automatic Beacon Transmitting
+	 */
+	if ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) &&
+	    (pMgmt->eCurrState >= WMAC_STATE_STARTED)) {
+		MACvRegBitsOn(pDevice->PortOffset, MAC_REG_TCR, TCR_AUTOBCNTX);
+	}
 }
 
-
-
-
-
-
 /*+
  *
  * Routine Description:
@@ -200,60 +178,54 @@ vAdHocBeaconRestart(PSDevice pDevice)
  * Return Value:
  *    none.
  *
--*/
+ -*/
 
 static
 void
 s_vProbeChannel(
-    PSDevice pDevice
-    )
+	PSDevice pDevice
+)
 {
-                                                     //1M,   2M,   5M,   11M,  18M,  24M,  36M,  54M
-    unsigned char abyCurrSuppRatesG[] = {WLAN_EID_SUPP_RATES, 8, 0x02, 0x04, 0x0B, 0x16, 0x24, 0x30, 0x48, 0x6C};
-    unsigned char abyCurrExtSuppRatesG[] = {WLAN_EID_EXTSUPP_RATES, 4, 0x0C, 0x12, 0x18, 0x60};
-                                                           //6M,   9M,   12M,  48M
-    unsigned char abyCurrSuppRatesA[] = {WLAN_EID_SUPP_RATES, 8, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6C};
-    unsigned char abyCurrSuppRatesB[] = {WLAN_EID_SUPP_RATES, 4, 0x02, 0x04, 0x0B, 0x16};
-    unsigned char *pbyRate;
-    PSTxMgmtPacket  pTxPacket;
-    PSMgmtObject    pMgmt = pDevice->pMgmt;
-    unsigned int ii;
-
-
-    if (pDevice->eCurrentPHYType == PHY_TYPE_11A) {
-        pbyRate = &abyCurrSuppRatesA[0];
-    } else if (pDevice->eCurrentPHYType == PHY_TYPE_11B) {
-        pbyRate = &abyCurrSuppRatesB[0];
-    } else {
-        pbyRate = &abyCurrSuppRatesG[0];
-    }
-    // build an assocreq frame and send it
-    pTxPacket = s_MgrMakeProbeRequest
-                (
-                  pDevice,
-                  pMgmt,
-                  pMgmt->abyScanBSSID,
-                  (PWLAN_IE_SSID)pMgmt->abyScanSSID,
-                  (PWLAN_IE_SUPP_RATES)pbyRate,
-                  (PWLAN_IE_SUPP_RATES)abyCurrExtSuppRatesG
-                );
-
-    if (pTxPacket != NULL ){
-        for (ii = 0; ii < 2 ; ii++) {
-            if (csMgmt_xmit(pDevice, pTxPacket) != CMD_STATUS_PENDING) {
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Probe request sending fail.. \n");
-            }
-            else {
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Probe request is sending.. \n");
-            }
-        }
-    }
-
+	//1M,   2M,   5M,   11M,  18M,  24M,  36M,  54M
+	unsigned char abyCurrSuppRatesG[] = {WLAN_EID_SUPP_RATES, 8, 0x02, 0x04, 0x0B, 0x16, 0x24, 0x30, 0x48, 0x6C};
+	unsigned char abyCurrExtSuppRatesG[] = {WLAN_EID_EXTSUPP_RATES, 4, 0x0C, 0x12, 0x18, 0x60};
+	//6M,   9M,   12M,  48M
+	unsigned char abyCurrSuppRatesA[] = {WLAN_EID_SUPP_RATES, 8, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6C};
+	unsigned char abyCurrSuppRatesB[] = {WLAN_EID_SUPP_RATES, 4, 0x02, 0x04, 0x0B, 0x16};
+	unsigned char *pbyRate;
+	PSTxMgmtPacket  pTxPacket;
+	PSMgmtObject    pMgmt = pDevice->pMgmt;
+	unsigned int ii;
+
+	if (pDevice->eCurrentPHYType == PHY_TYPE_11A) {
+		pbyRate = &abyCurrSuppRatesA[0];
+	} else if (pDevice->eCurrentPHYType == PHY_TYPE_11B) {
+		pbyRate = &abyCurrSuppRatesB[0];
+	} else {
+		pbyRate = &abyCurrSuppRatesG[0];
+	}
+	// build an assocreq frame and send it
+	pTxPacket = s_MgrMakeProbeRequest
+		(
+			pDevice,
+			pMgmt,
+			pMgmt->abyScanBSSID,
+			(PWLAN_IE_SSID)pMgmt->abyScanSSID,
+			(PWLAN_IE_SUPP_RATES)pbyRate,
+			(PWLAN_IE_SUPP_RATES)abyCurrExtSuppRatesG
+			);
+
+	if (pTxPacket != NULL) {
+		for (ii = 0; ii < 2; ii++) {
+			if (csMgmt_xmit(pDevice, pTxPacket) != CMD_STATUS_PENDING) {
+				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Probe request sending fail.. \n");
+			} else {
+				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Probe request is sending.. \n");
+			}
+		}
+	}
 }
 
-
-
-
 /*+
  *
  * Routine Description:
@@ -263,765 +235,724 @@ s_vProbeChannel(
  * Return Value:
  *    A ptr to Tx frame or NULL on allocation failue
  *
--*/
-
+ -*/
 
 PSTxMgmtPacket
 s_MgrMakeProbeRequest(
-    PSDevice pDevice,
-    PSMgmtObject pMgmt,
-    unsigned char *pScanBSSID,
-    PWLAN_IE_SSID pSSID,
-    PWLAN_IE_SUPP_RATES pCurrRates,
-    PWLAN_IE_SUPP_RATES pCurrExtSuppRates
-
-    )
+	PSDevice pDevice,
+	PSMgmtObject pMgmt,
+	unsigned char *pScanBSSID,
+	PWLAN_IE_SSID pSSID,
+	PWLAN_IE_SUPP_RATES pCurrRates,
+	PWLAN_IE_SUPP_RATES pCurrExtSuppRates
+
+)
 {
-    PSTxMgmtPacket      pTxPacket = NULL;
-    WLAN_FR_PROBEREQ    sFrame;
-
-
-    pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool;
-    memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_PROBEREQ_FR_MAXLEN);
-    pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket));
-    sFrame.pBuf = (unsigned char *)pTxPacket->p80211Header;
-    sFrame.len = WLAN_PROBEREQ_FR_MAXLEN;
-    vMgrEncodeProbeRequest(&sFrame);
-    sFrame.pHdr->sA3.wFrameCtl = cpu_to_le16(
-        (
-        WLAN_SET_FC_FTYPE(WLAN_TYPE_MGR) |
-        WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_PROBEREQ)
-        ));
-    memcpy( sFrame.pHdr->sA3.abyAddr1, pScanBSSID, WLAN_ADDR_LEN);
-    memcpy( sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN);
-    memcpy( sFrame.pHdr->sA3.abyAddr3, pScanBSSID, WLAN_BSSID_LEN);
-    // Copy the SSID, pSSID->len=0 indicate broadcast SSID
-    sFrame.pSSID = (PWLAN_IE_SSID)(sFrame.pBuf + sFrame.len);
-    sFrame.len += pSSID->len + WLAN_IEHDR_LEN;
-    memcpy(sFrame.pSSID, pSSID, pSSID->len + WLAN_IEHDR_LEN);
-    sFrame.pSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len);
-    sFrame.len += pCurrRates->len + WLAN_IEHDR_LEN;
-    memcpy(sFrame.pSuppRates, pCurrRates, pCurrRates->len + WLAN_IEHDR_LEN);
-    // Copy the extension rate set
-    if (pDevice->eCurrentPHYType == PHY_TYPE_11G) {
-        sFrame.pExtSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len);
-        sFrame.len += pCurrExtSuppRates->len + WLAN_IEHDR_LEN;
-        memcpy(sFrame.pExtSuppRates, pCurrExtSuppRates, pCurrExtSuppRates->len + WLAN_IEHDR_LEN);
-    }
-    pTxPacket->cbMPDULen = sFrame.len;
-    pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN;
-
-    return pTxPacket;
+	PSTxMgmtPacket      pTxPacket = NULL;
+	WLAN_FR_PROBEREQ    sFrame;
+
+	pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool;
+	memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_PROBEREQ_FR_MAXLEN);
+	pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket));
+	sFrame.pBuf = (unsigned char *)pTxPacket->p80211Header;
+	sFrame.len = WLAN_PROBEREQ_FR_MAXLEN;
+	vMgrEncodeProbeRequest(&sFrame);
+	sFrame.pHdr->sA3.wFrameCtl = cpu_to_le16(
+		(
+			WLAN_SET_FC_FTYPE(WLAN_TYPE_MGR) |
+			WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_PROBEREQ)
+));
+	memcpy(sFrame.pHdr->sA3.abyAddr1, pScanBSSID, WLAN_ADDR_LEN);
+	memcpy(sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN);
+	memcpy(sFrame.pHdr->sA3.abyAddr3, pScanBSSID, WLAN_BSSID_LEN);
+	// Copy the SSID, pSSID->len=0 indicate broadcast SSID
+	sFrame.pSSID = (PWLAN_IE_SSID)(sFrame.pBuf + sFrame.len);
+	sFrame.len += pSSID->len + WLAN_IEHDR_LEN;
+	memcpy(sFrame.pSSID, pSSID, pSSID->len + WLAN_IEHDR_LEN);
+	sFrame.pSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len);
+	sFrame.len += pCurrRates->len + WLAN_IEHDR_LEN;
+	memcpy(sFrame.pSuppRates, pCurrRates, pCurrRates->len + WLAN_IEHDR_LEN);
+	// Copy the extension rate set
+	if (pDevice->eCurrentPHYType == PHY_TYPE_11G) {
+		sFrame.pExtSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len);
+		sFrame.len += pCurrExtSuppRates->len + WLAN_IEHDR_LEN;
+		memcpy(sFrame.pExtSuppRates, pCurrExtSuppRates, pCurrExtSuppRates->len + WLAN_IEHDR_LEN);
+	}
+	pTxPacket->cbMPDULen = sFrame.len;
+	pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN;
+
+	return pTxPacket;
 }
 
-
-
-
-
 void
 vCommandTimerWait(
-    void *hDeviceContext,
-    unsigned int MSecond
-    )
+	void *hDeviceContext,
+	unsigned int MSecond
+)
 {
-    PSDevice        pDevice = (PSDevice)hDeviceContext;
-
-    init_timer(&pDevice->sTimerCommand);
-    pDevice->sTimerCommand.data = (unsigned long) pDevice;
-    pDevice->sTimerCommand.function = (TimerFunction)vCommandTimer;
-    // RUN_AT :1 msec ~= (HZ/1024)
-    pDevice->sTimerCommand.expires = (unsigned int)RUN_AT((MSecond * HZ) >> 10);
-    add_timer(&pDevice->sTimerCommand);
-    return;
+	PSDevice        pDevice = (PSDevice)hDeviceContext;
+
+	init_timer(&pDevice->sTimerCommand);
+	pDevice->sTimerCommand.data = (unsigned long) pDevice;
+	pDevice->sTimerCommand.function = (TimerFunction)vCommandTimer;
+	// RUN_AT :1 msec ~= (HZ/1024)
+	pDevice->sTimerCommand.expires = (unsigned int)RUN_AT((MSecond * HZ) >> 10);
+	add_timer(&pDevice->sTimerCommand);
+	return;
 }
 
-
-
-
 void
-vCommandTimer (
-    void *hDeviceContext
-    )
+vCommandTimer(
+	void *hDeviceContext
+)
 {
-    PSDevice        pDevice = (PSDevice)hDeviceContext;
-    PSMgmtObject    pMgmt = pDevice->pMgmt;
-    PWLAN_IE_SSID   pItemSSID;
-    PWLAN_IE_SSID   pItemSSIDCurr;
-    CMD_STATUS      Status;
-    unsigned int ii;
-    unsigned char byMask[8] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80};
-    struct sk_buff  *skb;
-
-
-    if (pDevice->dwDiagRefCount != 0)
-        return;
-    if (pDevice->bCmdRunning != true)
-        return;
-
-    spin_lock_irq(&pDevice->lock);
-
-    switch ( pDevice->eCommandState ) {
-
-        case WLAN_CMD_SCAN_START:
-
-	pDevice->byReAssocCount = 0;
-            if (pDevice->bRadioOff == true) {
-                s_bCommandComplete(pDevice);
-                spin_unlock_irq(&pDevice->lock);
-                return;
-            }
-
-            if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) {
-                s_bCommandComplete(pDevice);
-                CARDbSetBSSID(pMgmt->pAdapter, pMgmt->abyCurrBSSID, OP_MODE_AP);
-                spin_unlock_irq(&pDevice->lock);
-                return;
-            }
-
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCommandState= WLAN_CMD_SCAN_START\n");
-            pItemSSID = (PWLAN_IE_SSID)pMgmt->abyScanSSID;
-            // wait all Data TD complete
-            if (pDevice->iTDUsed[TYPE_AC0DMA] != 0){
-                spin_unlock_irq(&pDevice->lock);
-                vCommandTimerWait((void *)pDevice, 10);
-                return;
-            }
-
-            if (pMgmt->uScanChannel == 0 ) {
-                pMgmt->uScanChannel = pDevice->byMinChannel;
-                // Set Baseband to be more sensitive.
-
-            }
-            if (pMgmt->uScanChannel > pDevice->byMaxChannel) {
-                pMgmt->eScanState = WMAC_NO_SCANNING;
-
-                // Set Baseband's sensitivity back.
-                // Set channel back
-                set_channel(pMgmt->pAdapter, pMgmt->uCurrChannel);
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Scanning, set back to channel: [%d]\n", pMgmt->uCurrChannel);
-                if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) {
-                    CARDbSetBSSID(pMgmt->pAdapter, pMgmt->abyCurrBSSID, OP_MODE_ADHOC);
-                } else {
-                    CARDbSetBSSID(pMgmt->pAdapter, pMgmt->abyCurrBSSID, OP_MODE_INFRASTRUCTURE);
-                }
-                vAdHocBeaconRestart(pDevice);
-                s_bCommandComplete(pDevice);
-
-            } else {
+	PSDevice        pDevice = (PSDevice)hDeviceContext;
+	PSMgmtObject    pMgmt = pDevice->pMgmt;
+	PWLAN_IE_SSID   pItemSSID;
+	PWLAN_IE_SSID   pItemSSIDCurr;
+	CMD_STATUS      Status;
+	unsigned int ii;
+	unsigned char byMask[8] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80};
+	struct sk_buff  *skb;
+
+	if (pDevice->dwDiagRefCount != 0)
+		return;
+	if (pDevice->bCmdRunning != true)
+		return;
+
+	spin_lock_irq(&pDevice->lock);
+
+	switch (pDevice->eCommandState) {
+	case WLAN_CMD_SCAN_START:
+
+		pDevice->byReAssocCount = 0;
+		if (pDevice->bRadioOff == true) {
+			s_bCommandComplete(pDevice);
+			spin_unlock_irq(&pDevice->lock);
+			return;
+		}
+
+		if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) {
+			s_bCommandComplete(pDevice);
+			CARDbSetBSSID(pMgmt->pAdapter, pMgmt->abyCurrBSSID, OP_MODE_AP);
+			spin_unlock_irq(&pDevice->lock);
+			return;
+		}
+
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "eCommandState= WLAN_CMD_SCAN_START\n");
+		pItemSSID = (PWLAN_IE_SSID)pMgmt->abyScanSSID;
+		// wait all Data TD complete
+		if (pDevice->iTDUsed[TYPE_AC0DMA] != 0) {
+			spin_unlock_irq(&pDevice->lock);
+			vCommandTimerWait((void *)pDevice, 10);
+			return;
+		}
+
+		if (pMgmt->uScanChannel == 0) {
+			pMgmt->uScanChannel = pDevice->byMinChannel;
+			// Set Baseband to be more sensitive.
+
+		}
+		if (pMgmt->uScanChannel > pDevice->byMaxChannel) {
+			pMgmt->eScanState = WMAC_NO_SCANNING;
+
+			// Set Baseband's sensitivity back.
+			// Set channel back
+			set_channel(pMgmt->pAdapter, pMgmt->uCurrChannel);
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Scanning, set back to channel: [%d]\n", pMgmt->uCurrChannel);
+			if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) {
+				CARDbSetBSSID(pMgmt->pAdapter, pMgmt->abyCurrBSSID, OP_MODE_ADHOC);
+			} else {
+				CARDbSetBSSID(pMgmt->pAdapter, pMgmt->abyCurrBSSID, OP_MODE_INFRASTRUCTURE);
+			}
+			vAdHocBeaconRestart(pDevice);
+			s_bCommandComplete(pDevice);
+
+		} else {
 //2008-8-4 <add> by chester
-		if (!is_channel_valid(pMgmt->uScanChannel)) {
-                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Invalid channel pMgmt->uScanChannel = %d \n",pMgmt->uScanChannel);
-                    s_bCommandComplete(pDevice);
-                    spin_unlock_irq(&pDevice->lock);
-                    return;
-                }
-//printk("chester-pMgmt->uScanChannel=%d,pDevice->byMaxChannel=%d\n",pMgmt->uScanChannel,pDevice->byMaxChannel);
-                if (pMgmt->uScanChannel == pDevice->byMinChannel) {
-                    //pMgmt->eScanType = WMAC_SCAN_ACTIVE;
-                    pMgmt->abyScanBSSID[0] = 0xFF;
-                    pMgmt->abyScanBSSID[1] = 0xFF;
-                    pMgmt->abyScanBSSID[2] = 0xFF;
-                    pMgmt->abyScanBSSID[3] = 0xFF;
-                    pMgmt->abyScanBSSID[4] = 0xFF;
-                    pMgmt->abyScanBSSID[5] = 0xFF;
-                    pItemSSID->byElementID = WLAN_EID_SSID;
-                    // clear bssid list
-                    // BSSvClearBSSList((void *)pDevice, pDevice->bLinkPass);
-                    pMgmt->eScanState = WMAC_IS_SCANNING;
-
-                }
-
-                vAdHocBeaconStop(pDevice);
-
-                if (set_channel(pMgmt->pAdapter, pMgmt->uScanChannel) == true) {
-                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"SCAN Channel: %d\n", pMgmt->uScanChannel);
-                } else {
-                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"SET SCAN Channel Fail: %d\n", pMgmt->uScanChannel);
-                }
-                CARDbSetBSSID(pMgmt->pAdapter, pMgmt->abyCurrBSSID, OP_MODE_UNKNOWN);
-//	printk("chester-mxch=%d\n",pDevice->byMaxChannel);
-      //          printk("chester-ch=%d\n",pMgmt->uScanChannel);
-	pMgmt->uScanChannel++;
+			if (!is_channel_valid(pMgmt->uScanChannel)) {
+				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Invalid channel pMgmt->uScanChannel = %d \n", pMgmt->uScanChannel);
+				s_bCommandComplete(pDevice);
+				spin_unlock_irq(&pDevice->lock);
+				return;
+			}
+			if (pMgmt->uScanChannel == pDevice->byMinChannel) {
+				//pMgmt->eScanType = WMAC_SCAN_ACTIVE;
+				pMgmt->abyScanBSSID[0] = 0xFF;
+				pMgmt->abyScanBSSID[1] = 0xFF;
+				pMgmt->abyScanBSSID[2] = 0xFF;
+				pMgmt->abyScanBSSID[3] = 0xFF;
+				pMgmt->abyScanBSSID[4] = 0xFF;
+				pMgmt->abyScanBSSID[5] = 0xFF;
+				pItemSSID->byElementID = WLAN_EID_SSID;
+				// clear bssid list
+				// BSSvClearBSSList((void *)pDevice, pDevice->bLinkPass);
+				pMgmt->eScanState = WMAC_IS_SCANNING;
+
+			}
+
+			vAdHocBeaconStop(pDevice);
+
+			if (set_channel(pMgmt->pAdapter, pMgmt->uScanChannel) == true) {
+				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "SCAN Channel: %d\n", pMgmt->uScanChannel);
+			} else {
+				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "SET SCAN Channel Fail: %d\n", pMgmt->uScanChannel);
+			}
+			CARDbSetBSSID(pMgmt->pAdapter, pMgmt->abyCurrBSSID, OP_MODE_UNKNOWN);
+			pMgmt->uScanChannel++;
 //2008-8-4 <modify> by chester
-		if (!is_channel_valid(pMgmt->uScanChannel) &&
-                        pMgmt->uScanChannel <= pDevice->byMaxChannel ){
-                    pMgmt->uScanChannel=pDevice->byMaxChannel+1;
-		 pMgmt->eCommandState = WLAN_CMD_SCAN_END;
-
-                }
-
-
-                if ((pMgmt->b11hEnable == false) ||
-                    (pMgmt->uScanChannel < CB_MAX_CHANNEL_24G)) {
-                    s_vProbeChannel(pDevice);
-                    spin_unlock_irq(&pDevice->lock);
-                    vCommandTimerWait((void *)pDevice, WCMD_ACTIVE_SCAN_TIME);
-                    return;
-                } else {
-                    spin_unlock_irq(&pDevice->lock);
-                    vCommandTimerWait((void *)pDevice, WCMD_PASSIVE_SCAN_TIME);
-                    return;
-                }
-
-            }
-
-            break;
-
-        case WLAN_CMD_SCAN_END:
-
-            // Set Baseband's sensitivity back.
-            // Set channel back
-            set_channel(pMgmt->pAdapter, pMgmt->uCurrChannel);
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Scanning, set back to channel: [%d]\n", pMgmt->uCurrChannel);
-            if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) {
-                CARDbSetBSSID(pMgmt->pAdapter, pMgmt->abyCurrBSSID, OP_MODE_ADHOC);
-            } else {
-                CARDbSetBSSID(pMgmt->pAdapter, pMgmt->abyCurrBSSID, OP_MODE_INFRASTRUCTURE);
-            }
-
-            pMgmt->eScanState = WMAC_NO_SCANNING;
-            vAdHocBeaconRestart(pDevice);
+			if (!is_channel_valid(pMgmt->uScanChannel) &&
+			    pMgmt->uScanChannel <= pDevice->byMaxChannel) {
+				pMgmt->uScanChannel = pDevice->byMaxChannel + 1;
+				pMgmt->eCommandState = WLAN_CMD_SCAN_END;
+
+			}
+
+			if ((pMgmt->b11hEnable == false) ||
+			    (pMgmt->uScanChannel < CB_MAX_CHANNEL_24G)) {
+				s_vProbeChannel(pDevice);
+				spin_unlock_irq(&pDevice->lock);
+				vCommandTimerWait((void *)pDevice, WCMD_ACTIVE_SCAN_TIME);
+				return;
+			} else {
+				spin_unlock_irq(&pDevice->lock);
+				vCommandTimerWait((void *)pDevice, WCMD_PASSIVE_SCAN_TIME);
+				return;
+			}
+
+		}
+
+		break;
+
+	case WLAN_CMD_SCAN_END:
+
+		// Set Baseband's sensitivity back.
+		// Set channel back
+		set_channel(pMgmt->pAdapter, pMgmt->uCurrChannel);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Scanning, set back to channel: [%d]\n", pMgmt->uCurrChannel);
+		if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) {
+			CARDbSetBSSID(pMgmt->pAdapter, pMgmt->abyCurrBSSID, OP_MODE_ADHOC);
+		} else {
+			CARDbSetBSSID(pMgmt->pAdapter, pMgmt->abyCurrBSSID, OP_MODE_INFRASTRUCTURE);
+		}
+
+		pMgmt->eScanState = WMAC_NO_SCANNING;
+		vAdHocBeaconRestart(pDevice);
 //2008-0409-07, <Add> by Einsn Liu
 #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
-	if(pMgmt->eScanType == WMAC_SCAN_PASSIVE)
-			{//send scan event to wpa_Supplicant
-				union iwreq_data wrqu;
-				memset(&wrqu, 0, sizeof(wrqu));
-				wireless_send_event(pDevice->dev, SIOCGIWSCAN, &wrqu, NULL);
-			}
+		if (pMgmt->eScanType == WMAC_SCAN_PASSIVE)
+		{//send scan event to wpa_Supplicant
+			union iwreq_data wrqu;
+			memset(&wrqu, 0, sizeof(wrqu));
+			wireless_send_event(pDevice->dev, SIOCGIWSCAN, &wrqu, NULL);
+		}
 #endif
-            s_bCommandComplete(pDevice);
-            break;
-
-        case WLAN_CMD_DISASSOCIATE_START :
-	pDevice->byReAssocCount = 0;
-            if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) &&
-                (pMgmt->eCurrState != WMAC_STATE_ASSOC)) {
-                s_bCommandComplete(pDevice);
-                spin_unlock_irq(&pDevice->lock);
-                return;
-            } else {
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Send Disassociation Packet..\n");
-                // reason = 8 : disassoc because sta has left
-                vMgrDisassocBeginSta((void *)pDevice, pMgmt, pMgmt->abyCurrBSSID, (8), &Status);
-                pDevice->bLinkPass = false;
-                // unlock command busy
-                pItemSSID = (PWLAN_IE_SSID)pMgmt->abyCurrSSID;
-                pItemSSID->len = 0;
-                memset(pItemSSID->abySSID, 0, WLAN_SSID_MAXLEN);
-                pMgmt->eCurrState = WMAC_STATE_IDLE;
-                pMgmt->sNodeDBTable[0].bActive = false;
+		s_bCommandComplete(pDevice);
+		break;
+
+	case WLAN_CMD_DISASSOCIATE_START:
+		pDevice->byReAssocCount = 0;
+		if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) &&
+		    (pMgmt->eCurrState != WMAC_STATE_ASSOC)) {
+			s_bCommandComplete(pDevice);
+			spin_unlock_irq(&pDevice->lock);
+			return;
+		} else {
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Send Disassociation Packet..\n");
+			// reason = 8 : disassoc because sta has left
+			vMgrDisassocBeginSta((void *)pDevice, pMgmt, pMgmt->abyCurrBSSID, (8), &Status);
+			pDevice->bLinkPass = false;
+			// unlock command busy
+			pItemSSID = (PWLAN_IE_SSID)pMgmt->abyCurrSSID;
+			pItemSSID->len = 0;
+			memset(pItemSSID->abySSID, 0, WLAN_SSID_MAXLEN);
+			pMgmt->eCurrState = WMAC_STATE_IDLE;
+			pMgmt->sNodeDBTable[0].bActive = false;
 //                pDevice->bBeaconBufReady = false;
-            }
-            netif_stop_queue(pDevice->dev);
-            pDevice->eCommandState = WLAN_DISASSOCIATE_WAIT;
-            // wait all Control TD complete
-            if (pDevice->iTDUsed[TYPE_TXDMA0] != 0){
-                vCommandTimerWait((void *)pDevice, 10);
-                spin_unlock_irq(&pDevice->lock);
-                return;
-            }
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" CARDbRadioPowerOff\n");
-	//2008-09-02  <mark>	by chester
-           // CARDbRadioPowerOff(pDevice);
-            s_bCommandComplete(pDevice);
-            break;
-
-        case WLAN_DISASSOCIATE_WAIT :
-            // wait all Control TD complete
-            if (pDevice->iTDUsed[TYPE_TXDMA0] != 0){
-                vCommandTimerWait((void *)pDevice, 10);
-                spin_unlock_irq(&pDevice->lock);
-                return;
-            }
+		}
+		netif_stop_queue(pDevice->dev);
+		pDevice->eCommandState = WLAN_DISASSOCIATE_WAIT;
+		// wait all Control TD complete
+		if (pDevice->iTDUsed[TYPE_TXDMA0] != 0) {
+			vCommandTimerWait((void *)pDevice, 10);
+			spin_unlock_irq(&pDevice->lock);
+			return;
+		}
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " CARDbRadioPowerOff\n");
+		//2008-09-02  <mark>	by chester
+		// CARDbRadioPowerOff(pDevice);
+		s_bCommandComplete(pDevice);
+		break;
+
+	case WLAN_DISASSOCIATE_WAIT:
+		// wait all Control TD complete
+		if (pDevice->iTDUsed[TYPE_TXDMA0] != 0) {
+			vCommandTimerWait((void *)pDevice, 10);
+			spin_unlock_irq(&pDevice->lock);
+			return;
+		}
 //2008-09-02  <mark> by chester
-           // CARDbRadioPowerOff(pDevice);
-            s_bCommandComplete(pDevice);
-            break;
-
-        case WLAN_CMD_SSID_START:
-        	pDevice->byReAssocCount = 0;
-            if (pDevice->bRadioOff == true) {
-                s_bCommandComplete(pDevice);
-                spin_unlock_irq(&pDevice->lock);
-                return;
-            }
-//printk("chester-currmode=%d\n",pMgmt->eCurrMode);
-printk("chester-abyDesireSSID=%s\n",((PWLAN_IE_SSID)pMgmt->abyDesireSSID)->abySSID);
-                     //memcpy(pMgmt->abyAdHocSSID,pMgmt->abyDesireSSID,
-                              //((PWLAN_IE_SSID)pMgmt->abyDesireSSID)->len + WLAN_IEHDR_LEN);
-            pItemSSID = (PWLAN_IE_SSID)pMgmt->abyDesireSSID;
-            pItemSSIDCurr = (PWLAN_IE_SSID)pMgmt->abyCurrSSID;
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" cmd: desire ssid = %s\n", pItemSSID->abySSID);
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" cmd: curr ssid = %s\n", pItemSSIDCurr->abySSID);
-
-            if (pMgmt->eCurrState == WMAC_STATE_ASSOC) {
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" Cmd pMgmt->eCurrState == WMAC_STATE_ASSOC\n");
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pItemSSID->len =%d\n",pItemSSID->len);
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pItemSSIDCurr->len = %d\n",pItemSSIDCurr->len);
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" desire ssid = %s\n", pItemSSID->abySSID);
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" curr ssid = %s\n", pItemSSIDCurr->abySSID);
-            }
-
-            if ((pMgmt->eCurrState == WMAC_STATE_ASSOC) ||
-                ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA)&& (pMgmt->eCurrState == WMAC_STATE_JOINTED))) {
-
-                if (pItemSSID->len == pItemSSIDCurr->len) {
-                    if (memcmp(pItemSSID->abySSID, pItemSSIDCurr->abySSID, pItemSSID->len) == 0) {
-                        s_bCommandComplete(pDevice);
-                        spin_unlock_irq(&pDevice->lock);
-                        return;
-                    }
-                }
-
-                netif_stop_queue(pDevice->dev);
-                pDevice->bLinkPass = false;
-            }
-            // set initial state
-            pMgmt->eCurrState = WMAC_STATE_IDLE;
-            pMgmt->eCurrMode = WMAC_MODE_STANDBY;
-            PSvDisablePowerSaving((void *)pDevice);
-            BSSvClearNodeDBTable(pDevice, 0);
-
-            vMgrJoinBSSBegin((void *)pDevice, &Status);
-            // if Infra mode
-            if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && (pMgmt->eCurrState == WMAC_STATE_JOINTED)) {
-
-		// Call mgr to begin the deauthentication
-                // reason = (3) because sta has left ESS
-                if (pMgmt->eCurrState>= WMAC_STATE_AUTH) {
-                    vMgrDeAuthenBeginSta((void *)pDevice, pMgmt, pMgmt->abyCurrBSSID, (3), &Status);
-                }
-                // Call mgr to begin the authentication
-                vMgrAuthenBeginSta((void *)pDevice, pMgmt, &Status);
-                if (Status == CMD_STATUS_SUCCESS) {
+		// CARDbRadioPowerOff(pDevice);
+		s_bCommandComplete(pDevice);
+		break;
+
+	case WLAN_CMD_SSID_START:
+		pDevice->byReAssocCount = 0;
+		if (pDevice->bRadioOff == true) {
+			s_bCommandComplete(pDevice);
+			spin_unlock_irq(&pDevice->lock);
+			return;
+		}
+		printk("chester-abyDesireSSID=%s\n", ((PWLAN_IE_SSID)pMgmt->abyDesireSSID)->abySSID);
+		//memcpy(pMgmt->abyAdHocSSID,pMgmt->abyDesireSSID,
+		//((PWLAN_IE_SSID)pMgmt->abyDesireSSID)->len + WLAN_IEHDR_LEN);
+		pItemSSID = (PWLAN_IE_SSID)pMgmt->abyDesireSSID;
+		pItemSSIDCurr = (PWLAN_IE_SSID)pMgmt->abyCurrSSID;
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " cmd: desire ssid = %s\n", pItemSSID->abySSID);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " cmd: curr ssid = %s\n", pItemSSIDCurr->abySSID);
+
+		if (pMgmt->eCurrState == WMAC_STATE_ASSOC) {
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " Cmd pMgmt->eCurrState == WMAC_STATE_ASSOC\n");
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " pItemSSID->len =%d\n", pItemSSID->len);
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " pItemSSIDCurr->len = %d\n", pItemSSIDCurr->len);
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " desire ssid = %s\n", pItemSSID->abySSID);
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " curr ssid = %s\n", pItemSSIDCurr->abySSID);
+		}
+
+		if ((pMgmt->eCurrState == WMAC_STATE_ASSOC) ||
+		    ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) && (pMgmt->eCurrState == WMAC_STATE_JOINTED))) {
+			if (pItemSSID->len == pItemSSIDCurr->len) {
+				if (memcmp(pItemSSID->abySSID, pItemSSIDCurr->abySSID, pItemSSID->len) == 0) {
+					s_bCommandComplete(pDevice);
+					spin_unlock_irq(&pDevice->lock);
+					return;
+				}
+			}
+
+			netif_stop_queue(pDevice->dev);
+			pDevice->bLinkPass = false;
+		}
+		// set initial state
+		pMgmt->eCurrState = WMAC_STATE_IDLE;
+		pMgmt->eCurrMode = WMAC_MODE_STANDBY;
+		PSvDisablePowerSaving((void *)pDevice);
+		BSSvClearNodeDBTable(pDevice, 0);
+
+		vMgrJoinBSSBegin((void *)pDevice, &Status);
+		// if Infra mode
+		if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && (pMgmt->eCurrState == WMAC_STATE_JOINTED)) {
+			// Call mgr to begin the deauthentication
+			// reason = (3) because sta has left ESS
+			if (pMgmt->eCurrState >= WMAC_STATE_AUTH) {
+				vMgrDeAuthenBeginSta((void *)pDevice, pMgmt, pMgmt->abyCurrBSSID, (3), &Status);
+			}
+			// Call mgr to begin the authentication
+			vMgrAuthenBeginSta((void *)pDevice, pMgmt, &Status);
+			if (Status == CMD_STATUS_SUCCESS) {
+				pDevice->byLinkWaitCount = 0;
+				pDevice->eCommandState = WLAN_AUTHENTICATE_WAIT;
+				vCommandTimerWait((void *)pDevice, AUTHENTICATE_TIMEOUT);
+				spin_unlock_irq(&pDevice->lock);
+				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " Set eCommandState = WLAN_AUTHENTICATE_WAIT\n");
+				return;
+			}
+		}
+		// if Adhoc mode
+		else if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) {
+			if (pMgmt->eCurrState == WMAC_STATE_JOINTED) {
+				if (netif_queue_stopped(pDevice->dev)) {
+					netif_wake_queue(pDevice->dev);
+				}
+				pDevice->bLinkPass = true;
+
+				pMgmt->sNodeDBTable[0].bActive = true;
+				pMgmt->sNodeDBTable[0].uInActiveCount = 0;
+				bClearBSSID_SCAN(pDevice);
+			} else {
+				// start own IBSS
+				vMgrCreateOwnIBSS((void *)pDevice, &Status);
+				if (Status != CMD_STATUS_SUCCESS) {
+					DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " WLAN_CMD_IBSS_CREATE fail ! \n");
+				}
+				BSSvAddMulticastNode(pDevice);
+			}
+		}
+		// if SSID not found
+		else if (pMgmt->eCurrMode == WMAC_MODE_STANDBY) {
+			if (pMgmt->eConfigMode == WMAC_CONFIG_IBSS_STA ||
+			    pMgmt->eConfigMode == WMAC_CONFIG_AUTO) {
+				// start own IBSS
+				vMgrCreateOwnIBSS((void *)pDevice, &Status);
+				if (Status != CMD_STATUS_SUCCESS) {
+					DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " WLAN_CMD_IBSS_CREATE fail ! \n");
+				}
+				BSSvAddMulticastNode(pDevice);
+				if (netif_queue_stopped(pDevice->dev)) {
+					netif_wake_queue(pDevice->dev);
+				}
+				pDevice->bLinkPass = true;
+			} else {
+				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Disconnect SSID none\n");
+#ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
+				{
+					union iwreq_data  wrqu;
+					memset(&wrqu, 0, sizeof(wrqu));
+					wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+					printk("wireless_send_event--->SIOCGIWAP(disassociated:vMgrJoinBSSBegin Fail !!)\n");
+					wireless_send_event(pDevice->dev, SIOCGIWAP, &wrqu, NULL);
+				}
+#endif
+
+			}
+		}
+		s_bCommandComplete(pDevice);
+		break;
+
+	case WLAN_AUTHENTICATE_WAIT:
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "eCommandState == WLAN_AUTHENTICATE_WAIT\n");
+		if (pMgmt->eCurrState == WMAC_STATE_AUTH) {
+			// Call mgr to begin the association
+			pDevice->byLinkWaitCount = 0;
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "eCurrState == WMAC_STATE_AUTH\n");
+			vMgrAssocBeginSta((void *)pDevice, pMgmt, &Status);
+			if (Status == CMD_STATUS_SUCCESS) {
+				pDevice->byLinkWaitCount = 0;
+				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "eCommandState = WLAN_ASSOCIATE_WAIT\n");
+				pDevice->eCommandState = WLAN_ASSOCIATE_WAIT;
+				vCommandTimerWait((void *)pDevice, ASSOCIATE_TIMEOUT);
+				spin_unlock_irq(&pDevice->lock);
+				return;
+			}
+		}
+
+		else if (pMgmt->eCurrState < WMAC_STATE_AUTHPENDING) {
+			printk("WLAN_AUTHENTICATE_WAIT:Authen Fail???\n");
+		} else if (pDevice->byLinkWaitCount <= 4) {    //mike add:wait another 2 sec if authenticated_frame delay!
+			pDevice->byLinkWaitCount++;
+			printk("WLAN_AUTHENTICATE_WAIT:wait %d times!!\n", pDevice->byLinkWaitCount);
+			spin_unlock_irq(&pDevice->lock);
+			vCommandTimerWait((void *)pDevice, AUTHENTICATE_TIMEOUT/2);
+			return;
+		}
 		pDevice->byLinkWaitCount = 0;
-                    pDevice->eCommandState = WLAN_AUTHENTICATE_WAIT;
-                    vCommandTimerWait((void *)pDevice, AUTHENTICATE_TIMEOUT);
-                    spin_unlock_irq(&pDevice->lock);
-                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" Set eCommandState = WLAN_AUTHENTICATE_WAIT\n");
-                    return;
-                }
-            }
-            // if Adhoc mode
-            else if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) {
-                if (pMgmt->eCurrState == WMAC_STATE_JOINTED) {
-                    if (netif_queue_stopped(pDevice->dev)){
-                        netif_wake_queue(pDevice->dev);
-                    }
-                    pDevice->bLinkPass = true;
-
-                    pMgmt->sNodeDBTable[0].bActive = true;
-                    pMgmt->sNodeDBTable[0].uInActiveCount = 0;
-                    bClearBSSID_SCAN(pDevice);
-                }
-                else {
-                    // start own IBSS
-                    vMgrCreateOwnIBSS((void *)pDevice, &Status);
-                    if (Status != CMD_STATUS_SUCCESS){
-                        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " WLAN_CMD_IBSS_CREATE fail ! \n");
-                    }
-                    BSSvAddMulticastNode(pDevice);
-                }
-            }
-            // if SSID not found
-            else if (pMgmt->eCurrMode == WMAC_MODE_STANDBY) {
-                if (pMgmt->eConfigMode == WMAC_CONFIG_IBSS_STA ||
-                    pMgmt->eConfigMode == WMAC_CONFIG_AUTO) {
-                    // start own IBSS
-                    vMgrCreateOwnIBSS((void *)pDevice, &Status);
-                    if (Status != CMD_STATUS_SUCCESS){
-                        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" WLAN_CMD_IBSS_CREATE fail ! \n");
-                    }
-                    BSSvAddMulticastNode(pDevice);
-                    if (netif_queue_stopped(pDevice->dev)){
-                        netif_wake_queue(pDevice->dev);
-                    }
-                    pDevice->bLinkPass = true;
-                }
-                else {
-                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Disconnect SSID none\n");
-		  #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
-                    // if(pDevice->bWPASuppWextEnabled == true)
-                        {
-                  	union iwreq_data  wrqu;
-                  	memset(&wrqu, 0, sizeof (wrqu));
-                          wrqu.ap_addr.sa_family = ARPHRD_ETHER;
-                  	printk("wireless_send_event--->SIOCGIWAP(disassociated:vMgrJoinBSSBegin Fail !!)\n");
-                  	wireless_send_event(pDevice->dev, SIOCGIWAP, &wrqu, NULL);
-                       }
-                    #endif
-
-                }
-            }
-            s_bCommandComplete(pDevice);
-            break;
-
-        case WLAN_AUTHENTICATE_WAIT :
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCommandState == WLAN_AUTHENTICATE_WAIT\n");
-            if (pMgmt->eCurrState == WMAC_STATE_AUTH) {
-                // Call mgr to begin the association
-                	pDevice->byLinkWaitCount = 0;
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCurrState == WMAC_STATE_AUTH\n");
-                vMgrAssocBeginSta((void *)pDevice, pMgmt, &Status);
-                if (Status == CMD_STATUS_SUCCESS) {
+		s_bCommandComplete(pDevice);
+		break;
+
+	case WLAN_ASSOCIATE_WAIT:
+		if (pMgmt->eCurrState == WMAC_STATE_ASSOC) {
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "eCurrState == WMAC_STATE_ASSOC\n");
+			if (pDevice->ePSMode != WMAC_POWER_CAM) {
+				PSvEnablePowerSaving((void *)pDevice, pMgmt->wListenInterval);
+			}
+			if (pMgmt->eAuthenMode >= WMAC_AUTH_WPA) {
+				KeybRemoveAllKey(&(pDevice->sKey), pDevice->abyBSSID, pDevice->PortOffset);
+			}
+			pDevice->bLinkPass = true;
+			pDevice->byLinkWaitCount = 0;
+			pDevice->byReAssocCount = 0;
+			bClearBSSID_SCAN(pDevice);
+			if (pDevice->byFOETuning) {
+				BBvSetFOE(pDevice->PortOffset);
+				PSbSendNullPacket(pDevice);
+			}
+			if (netif_queue_stopped(pDevice->dev)) {
+				netif_wake_queue(pDevice->dev);
+			}
+#ifdef TxInSleep
+			if (pDevice->IsTxDataTrigger != false)   {    //TxDataTimer is not triggered at the first time
+				del_timer(&pDevice->sTimerTxData);
+				init_timer(&pDevice->sTimerTxData);
+				pDevice->sTimerTxData.data = (unsigned long) pDevice;
+				pDevice->sTimerTxData.function = (TimerFunction)BSSvSecondTxData;
+				pDevice->sTimerTxData.expires = RUN_AT(10*HZ);      //10s callback
+				pDevice->fTxDataInSleep = false;
+				pDevice->nTxDataTimeCout = 0;
+			} else {
+			}
+			pDevice->IsTxDataTrigger = true;
+			add_timer(&pDevice->sTimerTxData);
+#endif
+		} else if (pMgmt->eCurrState < WMAC_STATE_ASSOCPENDING) {
+			printk("WLAN_ASSOCIATE_WAIT:Association Fail???\n");
+		} else if (pDevice->byLinkWaitCount <= 4) {    //mike add:wait another 2 sec if associated_frame delay!
+			pDevice->byLinkWaitCount++;
+			printk("WLAN_ASSOCIATE_WAIT:wait %d times!!\n", pDevice->byLinkWaitCount);
+			spin_unlock_irq(&pDevice->lock);
+			vCommandTimerWait((void *)pDevice, ASSOCIATE_TIMEOUT/2);
+			return;
+		}
 		pDevice->byLinkWaitCount = 0;
-                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCommandState = WLAN_ASSOCIATE_WAIT\n");
-                    pDevice->eCommandState = WLAN_ASSOCIATE_WAIT;
-                    vCommandTimerWait((void *)pDevice, ASSOCIATE_TIMEOUT);
-                    spin_unlock_irq(&pDevice->lock);
-                    return;
-                }
-            }
-
-	else if(pMgmt->eCurrState < WMAC_STATE_AUTHPENDING) {
-               printk("WLAN_AUTHENTICATE_WAIT:Authen Fail???\n");
-	   }
-	   else  if(pDevice->byLinkWaitCount <= 4){    //mike add:wait another 2 sec if authenticated_frame delay!
-                pDevice->byLinkWaitCount ++;
-	       printk("WLAN_AUTHENTICATE_WAIT:wait %d times!!\n",pDevice->byLinkWaitCount);
-	       spin_unlock_irq(&pDevice->lock);
-	       vCommandTimerWait((void *)pDevice, AUTHENTICATE_TIMEOUT/2);
-	       return;
-	   }
-	          pDevice->byLinkWaitCount = 0;
-            s_bCommandComplete(pDevice);
-            break;
-
-        case WLAN_ASSOCIATE_WAIT :
-            if (pMgmt->eCurrState == WMAC_STATE_ASSOC) {
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCurrState == WMAC_STATE_ASSOC\n");
-                if (pDevice->ePSMode != WMAC_POWER_CAM) {
-                    PSvEnablePowerSaving((void *)pDevice, pMgmt->wListenInterval);
-                }
-                if (pMgmt->eAuthenMode >= WMAC_AUTH_WPA) {
-                    KeybRemoveAllKey(&(pDevice->sKey), pDevice->abyBSSID, pDevice->PortOffset);
-                }
-                pDevice->bLinkPass = true;
-                pDevice->byLinkWaitCount = 0;
-                pDevice->byReAssocCount = 0;
-                bClearBSSID_SCAN(pDevice);
-                if (pDevice->byFOETuning) {
-                    BBvSetFOE(pDevice->PortOffset);
-                    PSbSendNullPacket(pDevice);
-                }
-                if (netif_queue_stopped(pDevice->dev)){
-                    netif_wake_queue(pDevice->dev);
-                }
-	     #ifdef TxInSleep
-		 if(pDevice->IsTxDataTrigger != false)   {    //TxDataTimer is not triggered at the first time
-                     // printk("Re-initial TxDataTimer****\n");
-		    del_timer(&pDevice->sTimerTxData);
-                      init_timer(&pDevice->sTimerTxData);
-                      pDevice->sTimerTxData.data = (unsigned long) pDevice;
-                      pDevice->sTimerTxData.function = (TimerFunction)BSSvSecondTxData;
-                      pDevice->sTimerTxData.expires = RUN_AT(10*HZ);      //10s callback
-                      pDevice->fTxDataInSleep = false;
-                      pDevice->nTxDataTimeCout = 0;
-		 }
-		 else {
-		   // printk("mike:-->First time trigger TimerTxData InSleep\n");
-		 }
-		pDevice->IsTxDataTrigger = true;
-                add_timer(&pDevice->sTimerTxData);
-             #endif
-            }
-		   else if(pMgmt->eCurrState < WMAC_STATE_ASSOCPENDING) {
-               printk("WLAN_ASSOCIATE_WAIT:Association Fail???\n");
-	   }
-	   else  if(pDevice->byLinkWaitCount <= 4){    //mike add:wait another 2 sec if associated_frame delay!
-                pDevice->byLinkWaitCount ++;
-	       printk("WLAN_ASSOCIATE_WAIT:wait %d times!!\n",pDevice->byLinkWaitCount);
-	       spin_unlock_irq(&pDevice->lock);
-	       vCommandTimerWait((void *)pDevice, ASSOCIATE_TIMEOUT/2);
-	       return;
-	   }
-	          pDevice->byLinkWaitCount = 0;
-
-            s_bCommandComplete(pDevice);
-            break;
-
-        case WLAN_CMD_AP_MODE_START :
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCommandState == WLAN_CMD_AP_MODE_START\n");
-
-            if (pMgmt->eConfigMode == WMAC_CONFIG_AP) {
-                del_timer(&pMgmt->sTimerSecondCallback);
-                pMgmt->eCurrState = WMAC_STATE_IDLE;
-                pMgmt->eCurrMode = WMAC_MODE_STANDBY;
-                pDevice->bLinkPass = false;
-                if (pDevice->bEnableHostWEP == true)
-                    BSSvClearNodeDBTable(pDevice, 1);
-                else
-                    BSSvClearNodeDBTable(pDevice, 0);
-                pDevice->uAssocCount = 0;
-                pMgmt->eCurrState = WMAC_STATE_IDLE;
-                pDevice->bFixRate = false;
-
-                vMgrCreateOwnIBSS((void *)pDevice, &Status);
-                if (Status != CMD_STATUS_SUCCESS){
-                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " vMgrCreateOwnIBSS fail ! \n");
-                }
-                // alway turn off unicast bit
-                MACvRegBitsOff(pDevice->PortOffset, MAC_REG_RCR, RCR_UNICAST);
-                pDevice->byRxMode &= ~RCR_UNICAST;
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wcmd: rx_mode = %x\n", pDevice->byRxMode );
-                BSSvAddMulticastNode(pDevice);
-                if (netif_queue_stopped(pDevice->dev)){
-                    netif_wake_queue(pDevice->dev);
-                }
-                pDevice->bLinkPass = true;
-                add_timer(&pMgmt->sTimerSecondCallback);
-            }
-            s_bCommandComplete(pDevice);
-            break;
-
-        case WLAN_CMD_TX_PSPACKET_START :
-            // DTIM Multicast tx
-            if (pMgmt->sNodeDBTable[0].bRxPSPoll) {
-                while ((skb = skb_dequeue(&pMgmt->sNodeDBTable[0].sTxPSQueue)) != NULL) {
-                    if (skb_queue_empty(&pMgmt->sNodeDBTable[0].sTxPSQueue)) {
-                        pMgmt->abyPSTxMap[0] &= ~byMask[0];
-                        pDevice->bMoreData = false;
-                    }
-                    else {
-                        pDevice->bMoreData = true;
-                    }
-                    if (!device_dma0_xmit(pDevice, skb, 0)) {
-                        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Multicast ps tx fail \n");
-                    }
-                    pMgmt->sNodeDBTable[0].wEnQueueCnt--;
-                }
-            }
-
-            // PS nodes tx
-            for (ii = 1; ii < (MAX_NODE_NUM + 1); ii++) {
-                if (pMgmt->sNodeDBTable[ii].bActive &&
-                    pMgmt->sNodeDBTable[ii].bRxPSPoll) {
-                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Index=%d Enqueu Cnt= %d\n",
-                               ii, pMgmt->sNodeDBTable[ii].wEnQueueCnt);
-                    while ((skb = skb_dequeue(&pMgmt->sNodeDBTable[ii].sTxPSQueue)) != NULL) {
-                        if (skb_queue_empty(&pMgmt->sNodeDBTable[ii].sTxPSQueue)) {
-                            // clear tx map
-                            pMgmt->abyPSTxMap[pMgmt->sNodeDBTable[ii].wAID >> 3] &=
-                                    ~byMask[pMgmt->sNodeDBTable[ii].wAID & 7];
-                            pDevice->bMoreData = false;
-                        }
-                        else {
-                            pDevice->bMoreData = true;
-                        }
-                        if (!device_dma0_xmit(pDevice, skb, ii)) {
-                            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "sta ps tx fail \n");
-                        }
-                        pMgmt->sNodeDBTable[ii].wEnQueueCnt--;
-                        // check if sta ps enabled, and wait next pspoll.
-                        // if sta ps disable, then send all pending buffers.
-                        if (pMgmt->sNodeDBTable[ii].bPSEnable)
-                            break;
-                    }
-                    if (skb_queue_empty(&pMgmt->sNodeDBTable[ii].sTxPSQueue)) {
-                        // clear tx map
-                        pMgmt->abyPSTxMap[pMgmt->sNodeDBTable[ii].wAID >> 3] &=
-                                    ~byMask[pMgmt->sNodeDBTable[ii].wAID & 7];
-                        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Index=%d PS queue clear \n", ii);
-                    }
-                    pMgmt->sNodeDBTable[ii].bRxPSPoll = false;
-                }
-            }
-
-            s_bCommandComplete(pDevice);
-            break;
-
-
-        case WLAN_CMD_RADIO_START :
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCommandState == WLAN_CMD_RADIO_START\n");
-            if (pDevice->bRadioCmd == true)
-                CARDbRadioPowerOn(pDevice);
-            else
-                CARDbRadioPowerOff(pDevice);
-
-            s_bCommandComplete(pDevice);
-            break;
-
-
-        case WLAN_CMD_CHECK_BBSENSITIVITY_CHANGE :
-            //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCommandState == WLAN_CMD_CHECK_BBSENSITIVITY_START\n");
-            // wait all TD complete
-            if (pDevice->iTDUsed[TYPE_AC0DMA] != 0){
-                vCommandTimerWait((void *)pDevice, 10);
-                spin_unlock_irq(&pDevice->lock);
-                return;
-            }
-            if (pDevice->iTDUsed[TYPE_TXDMA0] != 0){
-                vCommandTimerWait((void *)pDevice, 10);
-                spin_unlock_irq(&pDevice->lock);
-                return;
-            }
-            pDevice->byBBVGACurrent = pDevice->byBBVGANew;
-            BBvSetVGAGainOffset(pDevice, pDevice->byBBVGACurrent);
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"SetVGAGainOffset %02X\n", pDevice->byBBVGACurrent);
-            s_bCommandComplete(pDevice);
-            break;
-
-        default :
-            s_bCommandComplete(pDevice);
-            break;
-
-    } //switch
-    spin_unlock_irq(&pDevice->lock);
-    return;
 
+		s_bCommandComplete(pDevice);
+		break;
+
+	case WLAN_CMD_AP_MODE_START:
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "eCommandState == WLAN_CMD_AP_MODE_START\n");
+
+		if (pMgmt->eConfigMode == WMAC_CONFIG_AP) {
+			del_timer(&pMgmt->sTimerSecondCallback);
+			pMgmt->eCurrState = WMAC_STATE_IDLE;
+			pMgmt->eCurrMode = WMAC_MODE_STANDBY;
+			pDevice->bLinkPass = false;
+			if (pDevice->bEnableHostWEP == true)
+				BSSvClearNodeDBTable(pDevice, 1);
+			else
+				BSSvClearNodeDBTable(pDevice, 0);
+			pDevice->uAssocCount = 0;
+			pMgmt->eCurrState = WMAC_STATE_IDLE;
+			pDevice->bFixRate = false;
+
+			vMgrCreateOwnIBSS((void *)pDevice, &Status);
+			if (Status != CMD_STATUS_SUCCESS) {
+				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " vMgrCreateOwnIBSS fail ! \n");
+			}
+			// alway turn off unicast bit
+			MACvRegBitsOff(pDevice->PortOffset, MAC_REG_RCR, RCR_UNICAST);
+			pDevice->byRxMode &= ~RCR_UNICAST;
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wcmd: rx_mode = %x\n", pDevice->byRxMode);
+			BSSvAddMulticastNode(pDevice);
+			if (netif_queue_stopped(pDevice->dev)) {
+				netif_wake_queue(pDevice->dev);
+			}
+			pDevice->bLinkPass = true;
+			add_timer(&pMgmt->sTimerSecondCallback);
+		}
+		s_bCommandComplete(pDevice);
+		break;
+
+	case WLAN_CMD_TX_PSPACKET_START:
+		// DTIM Multicast tx
+		if (pMgmt->sNodeDBTable[0].bRxPSPoll) {
+			while ((skb = skb_dequeue(&pMgmt->sNodeDBTable[0].sTxPSQueue)) != NULL) {
+				if (skb_queue_empty(&pMgmt->sNodeDBTable[0].sTxPSQueue)) {
+					pMgmt->abyPSTxMap[0] &= ~byMask[0];
+					pDevice->bMoreData = false;
+				} else {
+					pDevice->bMoreData = true;
+				}
+				if (!device_dma0_xmit(pDevice, skb, 0)) {
+					DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Multicast ps tx fail \n");
+				}
+				pMgmt->sNodeDBTable[0].wEnQueueCnt--;
+			}
+		}
+
+		// PS nodes tx
+		for (ii = 1; ii < (MAX_NODE_NUM + 1); ii++) {
+			if (pMgmt->sNodeDBTable[ii].bActive &&
+			    pMgmt->sNodeDBTable[ii].bRxPSPoll) {
+				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Index=%d Enqueu Cnt= %d\n",
+					ii, pMgmt->sNodeDBTable[ii].wEnQueueCnt);
+				while ((skb = skb_dequeue(&pMgmt->sNodeDBTable[ii].sTxPSQueue)) != NULL) {
+					if (skb_queue_empty(&pMgmt->sNodeDBTable[ii].sTxPSQueue)) {
+						// clear tx map
+						pMgmt->abyPSTxMap[pMgmt->sNodeDBTable[ii].wAID >> 3] &=
+							~byMask[pMgmt->sNodeDBTable[ii].wAID & 7];
+						pDevice->bMoreData = false;
+					} else {
+						pDevice->bMoreData = true;
+					}
+					if (!device_dma0_xmit(pDevice, skb, ii)) {
+						DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "sta ps tx fail \n");
+					}
+					pMgmt->sNodeDBTable[ii].wEnQueueCnt--;
+					// check if sta ps enabled, and wait next pspoll.
+					// if sta ps disable, then send all pending buffers.
+					if (pMgmt->sNodeDBTable[ii].bPSEnable)
+						break;
+				}
+				if (skb_queue_empty(&pMgmt->sNodeDBTable[ii].sTxPSQueue)) {
+					// clear tx map
+					pMgmt->abyPSTxMap[pMgmt->sNodeDBTable[ii].wAID >> 3] &=
+						~byMask[pMgmt->sNodeDBTable[ii].wAID & 7];
+					DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Index=%d PS queue clear \n", ii);
+				}
+				pMgmt->sNodeDBTable[ii].bRxPSPoll = false;
+			}
+		}
+
+		s_bCommandComplete(pDevice);
+		break;
+
+	case WLAN_CMD_RADIO_START:
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "eCommandState == WLAN_CMD_RADIO_START\n");
+		if (pDevice->bRadioCmd == true)
+			CARDbRadioPowerOn(pDevice);
+		else
+			CARDbRadioPowerOff(pDevice);
+
+		s_bCommandComplete(pDevice);
+		break;
+
+	case WLAN_CMD_CHECK_BBSENSITIVITY_CHANGE:
+		//DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "eCommandState == WLAN_CMD_CHECK_BBSENSITIVITY_START\n");
+		// wait all TD complete
+		if (pDevice->iTDUsed[TYPE_AC0DMA] != 0) {
+			vCommandTimerWait((void *)pDevice, 10);
+			spin_unlock_irq(&pDevice->lock);
+			return;
+		}
+		if (pDevice->iTDUsed[TYPE_TXDMA0] != 0) {
+			vCommandTimerWait((void *)pDevice, 10);
+			spin_unlock_irq(&pDevice->lock);
+			return;
+		}
+		pDevice->byBBVGACurrent = pDevice->byBBVGANew;
+		BBvSetVGAGainOffset(pDevice, pDevice->byBBVGACurrent);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "SetVGAGainOffset %02X\n", pDevice->byBBVGACurrent);
+		s_bCommandComplete(pDevice);
+		break;
+
+	default:
+		s_bCommandComplete(pDevice);
+		break;
+
+	} //switch
+	spin_unlock_irq(&pDevice->lock);
+	return;
 }
 
-
 static
 bool
-s_bCommandComplete (
-    PSDevice pDevice
-    )
+s_bCommandComplete(
+	PSDevice pDevice
+)
 {
-    PWLAN_IE_SSID pSSID;
-    bool bRadioCmd = false;
-    //unsigned short wDeAuthenReason = 0;
-    bool bForceSCAN = true;
-    PSMgmtObject  pMgmt = pDevice->pMgmt;
-
-
-    pDevice->eCommandState = WLAN_CMD_IDLE;
-    if (pDevice->cbFreeCmdQueue == CMD_Q_SIZE) {
-        //Command Queue Empty
-        pDevice->bCmdRunning = false;
-        return true;
-    }
-    else {
-        pDevice->eCommand = pDevice->eCmdQueue[pDevice->uCmdDequeueIdx].eCmd;
-        pSSID = (PWLAN_IE_SSID)pDevice->eCmdQueue[pDevice->uCmdDequeueIdx].abyCmdDesireSSID;
-        bRadioCmd = pDevice->eCmdQueue[pDevice->uCmdDequeueIdx].bRadioCmd;
-        bForceSCAN = pDevice->eCmdQueue[pDevice->uCmdDequeueIdx].bForceSCAN;
-        ADD_ONE_WITH_WRAP_AROUND(pDevice->uCmdDequeueIdx, CMD_Q_SIZE);
-        pDevice->cbFreeCmdQueue++;
-        pDevice->bCmdRunning = true;
-        switch ( pDevice->eCommand ) {
-            case WLAN_CMD_BSSID_SCAN:
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCommandState= WLAN_CMD_BSSID_SCAN\n");
-                pDevice->eCommandState = WLAN_CMD_SCAN_START;
-                pMgmt->uScanChannel = 0;
-                if (pSSID->len != 0) {
-                    memcpy(pMgmt->abyScanSSID, pSSID, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
-                } else {
-                    memset(pMgmt->abyScanSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
-                }
+	PWLAN_IE_SSID pSSID;
+	bool bRadioCmd = false;
+	//unsigned short wDeAuthenReason = 0;
+	bool bForceSCAN = true;
+	PSMgmtObject  pMgmt = pDevice->pMgmt;
+
+	pDevice->eCommandState = WLAN_CMD_IDLE;
+	if (pDevice->cbFreeCmdQueue == CMD_Q_SIZE) {
+		//Command Queue Empty
+		pDevice->bCmdRunning = false;
+		return true;
+	} else {
+		pDevice->eCommand = pDevice->eCmdQueue[pDevice->uCmdDequeueIdx].eCmd;
+		pSSID = (PWLAN_IE_SSID)pDevice->eCmdQueue[pDevice->uCmdDequeueIdx].abyCmdDesireSSID;
+		bRadioCmd = pDevice->eCmdQueue[pDevice->uCmdDequeueIdx].bRadioCmd;
+		bForceSCAN = pDevice->eCmdQueue[pDevice->uCmdDequeueIdx].bForceSCAN;
+		ADD_ONE_WITH_WRAP_AROUND(pDevice->uCmdDequeueIdx, CMD_Q_SIZE);
+		pDevice->cbFreeCmdQueue++;
+		pDevice->bCmdRunning = true;
+		switch (pDevice->eCommand) {
+		case WLAN_CMD_BSSID_SCAN:
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "eCommandState= WLAN_CMD_BSSID_SCAN\n");
+			pDevice->eCommandState = WLAN_CMD_SCAN_START;
+			pMgmt->uScanChannel = 0;
+			if (pSSID->len != 0) {
+				memcpy(pMgmt->abyScanSSID, pSSID, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
+			} else {
+				memset(pMgmt->abyScanSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
+			}
 /*
-                if ((bForceSCAN == false) && (pDevice->bLinkPass == true)) {
-                    if ((pSSID->len == ((PWLAN_IE_SSID)pMgmt->abyCurrSSID)->len) &&
-                        ( !memcmp(pSSID->abySSID, ((PWLAN_IE_SSID)pMgmt->abyCurrSSID)->abySSID, pSSID->len))) {
-                        pDevice->eCommandState = WLAN_CMD_IDLE;
-                    }
-                }
+  if ((bForceSCAN == false) && (pDevice->bLinkPass == true)) {
+  if ((pSSID->len == ((PWLAN_IE_SSID)pMgmt->abyCurrSSID)->len) &&
+  (!memcmp(pSSID->abySSID, ((PWLAN_IE_SSID)pMgmt->abyCurrSSID)->abySSID, pSSID->len))) {
+  pDevice->eCommandState = WLAN_CMD_IDLE;
+  }
+  }
 */
-                break;
-            case WLAN_CMD_SSID:
-                pDevice->eCommandState = WLAN_CMD_SSID_START;
-                if (pSSID->len > WLAN_SSID_MAXLEN)
-                    pSSID->len = WLAN_SSID_MAXLEN;
-                if (pSSID->len != 0)
-                    memcpy(pDevice->pMgmt->abyDesireSSID, pSSID, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCommandState= WLAN_CMD_SSID_START\n");
-                break;
-            case WLAN_CMD_DISASSOCIATE:
-                pDevice->eCommandState = WLAN_CMD_DISASSOCIATE_START;
-                break;
-            case WLAN_CMD_RX_PSPOLL:
-                pDevice->eCommandState = WLAN_CMD_TX_PSPACKET_START;
-                break;
-            case WLAN_CMD_RUN_AP:
-                pDevice->eCommandState = WLAN_CMD_AP_MODE_START;
-                break;
-            case WLAN_CMD_RADIO:
-                pDevice->eCommandState = WLAN_CMD_RADIO_START;
-                pDevice->bRadioCmd = bRadioCmd;
-                break;
-            case WLAN_CMD_CHANGE_BBSENSITIVITY:
-                pDevice->eCommandState = WLAN_CMD_CHECK_BBSENSITIVITY_CHANGE;
-                break;
-
-            default:
-                break;
-
-        }
-
-        vCommandTimerWait((void *)pDevice, 0);
-    }
-
-    return true;
+			break;
+		case WLAN_CMD_SSID:
+			pDevice->eCommandState = WLAN_CMD_SSID_START;
+			if (pSSID->len > WLAN_SSID_MAXLEN)
+				pSSID->len = WLAN_SSID_MAXLEN;
+			if (pSSID->len != 0)
+				memcpy(pDevice->pMgmt->abyDesireSSID, pSSID, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "eCommandState= WLAN_CMD_SSID_START\n");
+			break;
+		case WLAN_CMD_DISASSOCIATE:
+			pDevice->eCommandState = WLAN_CMD_DISASSOCIATE_START;
+			break;
+		case WLAN_CMD_RX_PSPOLL:
+			pDevice->eCommandState = WLAN_CMD_TX_PSPACKET_START;
+			break;
+		case WLAN_CMD_RUN_AP:
+			pDevice->eCommandState = WLAN_CMD_AP_MODE_START;
+			break;
+		case WLAN_CMD_RADIO:
+			pDevice->eCommandState = WLAN_CMD_RADIO_START;
+			pDevice->bRadioCmd = bRadioCmd;
+			break;
+		case WLAN_CMD_CHANGE_BBSENSITIVITY:
+			pDevice->eCommandState = WLAN_CMD_CHECK_BBSENSITIVITY_CHANGE;
+			break;
+
+		default:
+			break;
+
+		}
+
+		vCommandTimerWait((void *)pDevice, 0);
+	}
+
+	return true;
 }
 
-
-
-bool bScheduleCommand (
-    void *hDeviceContext,
-    CMD_CODE    eCommand,
-    unsigned char *pbyItem0
-    )
+bool bScheduleCommand(
+	void *hDeviceContext,
+	CMD_CODE    eCommand,
+	unsigned char *pbyItem0
+)
 {
-    PSDevice        pDevice = (PSDevice)hDeviceContext;
-
-
-    if (pDevice->cbFreeCmdQueue == 0) {
-        return (false);
-    }
-    pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].eCmd = eCommand;
-    pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].bForceSCAN = true;
-    memset(pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].abyCmdDesireSSID, 0 , WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
-
-    if (pbyItem0 != NULL) {
-        switch (eCommand) {
-
-            case WLAN_CMD_BSSID_SCAN:
-                memcpy(pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].abyCmdDesireSSID,
-                         pbyItem0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
-                pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].bForceSCAN = false;
-                break;
-
-            case WLAN_CMD_SSID:
-                memcpy(pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].abyCmdDesireSSID,
-                         pbyItem0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
-                break;
-
-            case WLAN_CMD_DISASSOCIATE:
-                pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].bNeedRadioOFF = *((int *)pbyItem0);
-                break;
+	PSDevice        pDevice = (PSDevice)hDeviceContext;
+
+	if (pDevice->cbFreeCmdQueue == 0) {
+		return false;
+	}
+	pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].eCmd = eCommand;
+	pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].bForceSCAN = true;
+	memset(pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].abyCmdDesireSSID, 0 , WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
+
+	if (pbyItem0 != NULL) {
+		switch (eCommand) {
+		case WLAN_CMD_BSSID_SCAN:
+			memcpy(pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].abyCmdDesireSSID,
+			       pbyItem0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
+			pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].bForceSCAN = false;
+			break;
+
+		case WLAN_CMD_SSID:
+			memcpy(pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].abyCmdDesireSSID,
+			       pbyItem0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
+			break;
+
+		case WLAN_CMD_DISASSOCIATE:
+			pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].bNeedRadioOFF = *((int *)pbyItem0);
+			break;
 /*
-            case WLAN_CMD_DEAUTH:
-                pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].wDeAuthenReason = *((unsigned short *)pbyItem0);
-                break;
+  case WLAN_CMD_DEAUTH:
+  pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].wDeAuthenReason = *((unsigned short *)pbyItem0);
+  break;
 */
 
-            case WLAN_CMD_RX_PSPOLL:
-                break;
+		case WLAN_CMD_RX_PSPOLL:
+			break;
 
-            case WLAN_CMD_RADIO:
-                pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].bRadioCmd = *((int *)pbyItem0);
-                break;
+		case WLAN_CMD_RADIO:
+			pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].bRadioCmd = *((int *)pbyItem0);
+			break;
 
-            case WLAN_CMD_CHANGE_BBSENSITIVITY:
-                pDevice->eCommandState = WLAN_CMD_CHECK_BBSENSITIVITY_CHANGE;
-                break;
+		case WLAN_CMD_CHANGE_BBSENSITIVITY:
+			pDevice->eCommandState = WLAN_CMD_CHECK_BBSENSITIVITY_CHANGE;
+			break;
 
-            default:
-                break;
-        }
-    }
+		default:
+			break;
+		}
+	}
 
-    ADD_ONE_WITH_WRAP_AROUND(pDevice->uCmdEnqueueIdx, CMD_Q_SIZE);
-    pDevice->cbFreeCmdQueue--;
-
-    if (pDevice->bCmdRunning == false) {
-        s_bCommandComplete(pDevice);
-    }
-    else {
-    }
-    return (true);
+	ADD_ONE_WITH_WRAP_AROUND(pDevice->uCmdEnqueueIdx, CMD_Q_SIZE);
+	pDevice->cbFreeCmdQueue--;
 
+	if (pDevice->bCmdRunning == false) {
+		s_bCommandComplete(pDevice);
+	} else {
+	}
+	return true;
 }
 
 /*
@@ -1038,87 +969,81 @@ bool bScheduleCommand (
  * Return Value: true if success; otherwise false
  *
  */
-bool bClearBSSID_SCAN (
-    void *hDeviceContext
-    )
+bool bClearBSSID_SCAN(
+	void *hDeviceContext
+)
 {
-    PSDevice        pDevice = (PSDevice)hDeviceContext;
-    unsigned int uCmdDequeueIdx = pDevice->uCmdDequeueIdx;
-    unsigned int ii;
-
-    if ((pDevice->cbFreeCmdQueue < CMD_Q_SIZE) && (uCmdDequeueIdx != pDevice->uCmdEnqueueIdx)) {
-        for (ii = 0; ii < (CMD_Q_SIZE - pDevice->cbFreeCmdQueue); ii ++) {
-            if (pDevice->eCmdQueue[uCmdDequeueIdx].eCmd == WLAN_CMD_BSSID_SCAN)
-                pDevice->eCmdQueue[uCmdDequeueIdx].eCmd = WLAN_CMD_IDLE;
-            ADD_ONE_WITH_WRAP_AROUND(uCmdDequeueIdx, CMD_Q_SIZE);
-            if (uCmdDequeueIdx == pDevice->uCmdEnqueueIdx)
-                break;
-        }
-    }
-    return true;
+	PSDevice        pDevice = (PSDevice)hDeviceContext;
+	unsigned int uCmdDequeueIdx = pDevice->uCmdDequeueIdx;
+	unsigned int ii;
+
+	if ((pDevice->cbFreeCmdQueue < CMD_Q_SIZE) && (uCmdDequeueIdx != pDevice->uCmdEnqueueIdx)) {
+		for (ii = 0; ii < (CMD_Q_SIZE - pDevice->cbFreeCmdQueue); ii++) {
+			if (pDevice->eCmdQueue[uCmdDequeueIdx].eCmd == WLAN_CMD_BSSID_SCAN)
+				pDevice->eCmdQueue[uCmdDequeueIdx].eCmd = WLAN_CMD_IDLE;
+			ADD_ONE_WITH_WRAP_AROUND(uCmdDequeueIdx, CMD_Q_SIZE);
+			if (uCmdDequeueIdx == pDevice->uCmdEnqueueIdx)
+				break;
+		}
+	}
+	return true;
 }
 
 //mike add:reset command timer
 void
 vResetCommandTimer(
-    void *hDeviceContext
-    )
+	void *hDeviceContext
+)
 {
-  PSDevice        pDevice = (PSDevice)hDeviceContext;
-
-  //delete timer
-      del_timer(&pDevice->sTimerCommand);
-  //init timer
-      init_timer(&pDevice->sTimerCommand);
-    pDevice->sTimerCommand.data = (unsigned long) pDevice;
-    pDevice->sTimerCommand.function = (TimerFunction)vCommandTimer;
-    pDevice->sTimerCommand.expires = RUN_AT(HZ);
-    pDevice->cbFreeCmdQueue = CMD_Q_SIZE;
-    pDevice->uCmdDequeueIdx = 0;
-    pDevice->uCmdEnqueueIdx = 0;
-    pDevice->eCommandState = WLAN_CMD_IDLE;
-    pDevice->bCmdRunning = false;
-    pDevice->bCmdClear = false;
+	PSDevice        pDevice = (PSDevice)hDeviceContext;
+
+	//delete timer
+	del_timer(&pDevice->sTimerCommand);
+	//init timer
+	init_timer(&pDevice->sTimerCommand);
+	pDevice->sTimerCommand.data = (unsigned long) pDevice;
+	pDevice->sTimerCommand.function = (TimerFunction)vCommandTimer;
+	pDevice->sTimerCommand.expires = RUN_AT(HZ);
+	pDevice->cbFreeCmdQueue = CMD_Q_SIZE;
+	pDevice->uCmdDequeueIdx = 0;
+	pDevice->uCmdEnqueueIdx = 0;
+	pDevice->eCommandState = WLAN_CMD_IDLE;
+	pDevice->bCmdRunning = false;
+	pDevice->bCmdClear = false;
 }
 
-
 #ifdef TxInSleep
 void
 BSSvSecondTxData(
-    void *hDeviceContext
-    )
+	void *hDeviceContext
+)
 {
-  PSDevice        pDevice = (PSDevice)hDeviceContext;
-  PSMgmtObject  pMgmt = &(pDevice->sMgmtObj);
-  pDevice->nTxDataTimeCout++;
-
-  if(pDevice->nTxDataTimeCout<4)     //don't tx data if timer less than 40s
-    {
-     // printk("mike:%s-->no data Tx not exceed the desired Time as %d\n",__FUNCTION__,
-	//  	(int)pDevice->nTxDataTimeCout);
-     pDevice->sTimerTxData.expires = RUN_AT(10*HZ);      //10s callback
-     add_timer(&pDevice->sTimerTxData);
-      return;
-    }
-
-  spin_lock_irq(&pDevice->lock);
-  #if 1
-  if(((pDevice->bLinkPass ==true)&&(pMgmt->eAuthenMode < WMAC_AUTH_WPA)) ||  //open && sharekey linking
-      (pDevice->fWPA_Authened == true)) {   //wpa linking
- #else
-  if(pDevice->bLinkPass ==true) {
- #endif
-
-        //   printk("mike:%s-->InSleep Tx Data Procedure\n",__FUNCTION__);
-	  pDevice->fTxDataInSleep = true;
-	  PSbSendNullPacket(pDevice);      //send null packet
-	  pDevice->fTxDataInSleep = false;
-  	}
-  spin_unlock_irq(&pDevice->lock);
-
-  pDevice->sTimerTxData.expires = RUN_AT(10*HZ);      //10s callback
-  add_timer(&pDevice->sTimerTxData);
-  return;
-}
+	PSDevice        pDevice = (PSDevice)hDeviceContext;
+	PSMgmtObject  pMgmt = &(pDevice->sMgmtObj);
+	pDevice->nTxDataTimeCout++;
+
+	if (pDevice->nTxDataTimeCout < 4)     //don't tx data if timer less than 40s
+	{
+		pDevice->sTimerTxData.expires = RUN_AT(10*HZ);      //10s callback
+		add_timer(&pDevice->sTimerTxData);
+		return;
+	}
+
+	spin_lock_irq(&pDevice->lock);
+#if 1
+	if (((pDevice->bLinkPass == true) && (pMgmt->eAuthenMode < WMAC_AUTH_WPA)) ||  //open && sharekey linking
+	   (pDevice->fWPA_Authened == true)) {   //wpa linking
+#else
+		if (pDevice->bLinkPass == true) {
+#endif
+			pDevice->fTxDataInSleep = true;
+			PSbSendNullPacket(pDevice);      //send null packet
+			pDevice->fTxDataInSleep = false;
+		}
+		spin_unlock_irq(&pDevice->lock);
+
+		pDevice->sTimerTxData.expires = RUN_AT(10*HZ);      //10s callback
+		add_timer(&pDevice->sTimerTxData);
+		return;
+	}
 #endif
-
diff --git a/drivers/staging/vt6655/wcmd.h b/drivers/staging/vt6655/wcmd.h
index 69d4fc5..2844476 100644
--- a/drivers/staging/vt6655/wcmd.h
+++ b/drivers/staging/vt6655/wcmd.h
@@ -35,111 +35,101 @@
 
 /*---------------------  Export Definitions -------------------------*/
 
-
-
 #define AUTHENTICATE_TIMEOUT   1000 //ms
 #define ASSOCIATE_TIMEOUT      1000 //ms
 
-
 // Command code
 typedef enum tagCMD_CODE {
-    WLAN_CMD_BSSID_SCAN,
-    WLAN_CMD_SSID,
-    WLAN_CMD_DISASSOCIATE,
-    WLAN_CMD_DEAUTH,
-    WLAN_CMD_RX_PSPOLL,
-    WLAN_CMD_RADIO,
-    WLAN_CMD_CHANGE_BBSENSITIVITY,
-    WLAN_CMD_SETPOWER,
-    WLAN_CMD_TBTT_WAKEUP,
-    WLAN_CMD_BECON_SEND,
-    WLAN_CMD_CHANGE_ANTENNA,
-    WLAN_CMD_REMOVE_ALLKEY,
-    WLAN_CMD_MAC_DISPOWERSAVING,
-    WLAN_CMD_11H_CHSW,
-    WLAN_CMD_RUN_AP
+	WLAN_CMD_BSSID_SCAN,
+	WLAN_CMD_SSID,
+	WLAN_CMD_DISASSOCIATE,
+	WLAN_CMD_DEAUTH,
+	WLAN_CMD_RX_PSPOLL,
+	WLAN_CMD_RADIO,
+	WLAN_CMD_CHANGE_BBSENSITIVITY,
+	WLAN_CMD_SETPOWER,
+	WLAN_CMD_TBTT_WAKEUP,
+	WLAN_CMD_BECON_SEND,
+	WLAN_CMD_CHANGE_ANTENNA,
+	WLAN_CMD_REMOVE_ALLKEY,
+	WLAN_CMD_MAC_DISPOWERSAVING,
+	WLAN_CMD_11H_CHSW,
+	WLAN_CMD_RUN_AP
 } CMD_CODE, *PCMD_CODE;
 
 #define CMD_Q_SIZE              32
 
 typedef enum tagCMD_STATUS {
-
-    CMD_STATUS_SUCCESS = 0,
-    CMD_STATUS_FAILURE,
-    CMD_STATUS_RESOURCES,
-    CMD_STATUS_TIMEOUT,
-    CMD_STATUS_PENDING
-
+	CMD_STATUS_SUCCESS = 0,
+	CMD_STATUS_FAILURE,
+	CMD_STATUS_RESOURCES,
+	CMD_STATUS_TIMEOUT,
+	CMD_STATUS_PENDING
 } CMD_STATUS, *PCMD_STATUS;
 
-
 typedef struct tagCMD_ITEM {
-    CMD_CODE eCmd;
-    unsigned char abyCmdDesireSSID[WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1];
-    bool bNeedRadioOFF;
-    unsigned short wDeAuthenReason;
-    bool bRadioCmd;
-    bool bForceSCAN;
+	CMD_CODE eCmd;
+	unsigned char abyCmdDesireSSID[WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1];
+	bool bNeedRadioOFF;
+	unsigned short wDeAuthenReason;
+	bool bRadioCmd;
+	bool bForceSCAN;
 } CMD_ITEM, *PCMD_ITEM;
 
 // Command state
 typedef enum tagCMD_STATE {
-    WLAN_CMD_SCAN_START,
-    WLAN_CMD_SCAN_END,
-    WLAN_CMD_DISASSOCIATE_START,
-    WLAN_CMD_SSID_START,
-    WLAN_AUTHENTICATE_WAIT,
-    WLAN_ASSOCIATE_WAIT,
-    WLAN_DISASSOCIATE_WAIT,
-    WLAN_CMD_TX_PSPACKET_START,
-    WLAN_CMD_AP_MODE_START,
-    WLAN_CMD_RADIO_START,
-    WLAN_CMD_CHECK_BBSENSITIVITY_CHANGE,
-    WLAN_CMD_IDLE
+	WLAN_CMD_SCAN_START,
+	WLAN_CMD_SCAN_END,
+	WLAN_CMD_DISASSOCIATE_START,
+	WLAN_CMD_SSID_START,
+	WLAN_AUTHENTICATE_WAIT,
+	WLAN_ASSOCIATE_WAIT,
+	WLAN_DISASSOCIATE_WAIT,
+	WLAN_CMD_TX_PSPACKET_START,
+	WLAN_CMD_AP_MODE_START,
+	WLAN_CMD_RADIO_START,
+	WLAN_CMD_CHECK_BBSENSITIVITY_CHANGE,
+	WLAN_CMD_IDLE
 } CMD_STATE, *PCMD_STATE;
 
-
-
 /*---------------------  Export Classes  ----------------------------*/
 
 /*---------------------  Export Variables  --------------------------*/
 
-
 /*---------------------  Export Types  ------------------------------*/
 
-
 /*---------------------  Export Functions  --------------------------*/
 void
 vResetCommandTimer(
-    void *hDeviceContext
-    );
+	void *hDeviceContext
+);
 
 void
-vCommandTimer (
-    void *hDeviceContext
-    );
+vCommandTimer(
+	void *hDeviceContext
+);
 
 bool bClearBSSID_SCAN(
-    void *hDeviceContext
-    );
+	void *hDeviceContext
+);
 
 bool
 bScheduleCommand(
-    void *hDeviceContext,
-    CMD_CODE    eCommand,
-    unsigned char *pbyItem0
-    );
+	void *hDeviceContext,
+	CMD_CODE    eCommand,
+	unsigned char *pbyItem0
+);
 
 void
 vCommandTimerWait(
-    void *hDeviceContext,
-    unsigned int MSecond
-    );
+	void *hDeviceContext,
+	unsigned int MSecond
+);
 #ifdef TxInSleep
 void
 BSSvSecondTxData(
-    void *hDeviceContext
-    );
+	void *hDeviceContext
+);
 #endif
 
 #endif //__WCMD_H__
diff --git a/drivers/staging/vt6655/wctl.c b/drivers/staging/vt6655/wctl.c
index c096583..9eb81b4 100644
--- a/drivers/staging/vt6655/wctl.c
+++ b/drivers/staging/vt6655/wctl.c
@@ -48,8 +48,6 @@
 
 /*---------------------  Export Variables  --------------------------*/
 
-
-
 /*
  * Description:
  *      Scan Rx cache.  Return true if packet is duplicate, else
@@ -66,32 +64,31 @@
  *
  */
 
-bool WCTLbIsDuplicate (PSCache pCache, PS802_11Header pMACHeader)
+bool WCTLbIsDuplicate(PSCache pCache, PS802_11Header pMACHeader)
 {
-    unsigned int uIndex;
-    unsigned int ii;
-    PSCacheEntry    pCacheEntry;
-
-    if (IS_FC_RETRY(pMACHeader)) {
-
-        uIndex = pCache->uInPtr;
-        for (ii = 0; ii < DUPLICATE_RX_CACHE_LENGTH; ii++) {
-            pCacheEntry = &(pCache->asCacheEntry[uIndex]);
-            if ((pCacheEntry->wFmSequence == pMACHeader->wSeqCtl) &&
-                (!compare_ether_addr(&(pCacheEntry->abyAddr2[0]), &(pMACHeader->abyAddr2[0])))
-                ) {
-                /* Duplicate match */
-                return true;
-            }
-            ADD_ONE_WITH_WRAP_AROUND(uIndex, DUPLICATE_RX_CACHE_LENGTH);
-        }
-    }
-    /* Not fount in cache - insert */
-    pCacheEntry = &pCache->asCacheEntry[pCache->uInPtr];
-    pCacheEntry->wFmSequence = pMACHeader->wSeqCtl;
-    memcpy(&(pCacheEntry->abyAddr2[0]), &(pMACHeader->abyAddr2[0]), ETH_ALEN);
-    ADD_ONE_WITH_WRAP_AROUND(pCache->uInPtr, DUPLICATE_RX_CACHE_LENGTH);
-    return false;
+	unsigned int uIndex;
+	unsigned int ii;
+	PSCacheEntry    pCacheEntry;
+
+	if (IS_FC_RETRY(pMACHeader)) {
+		uIndex = pCache->uInPtr;
+		for (ii = 0; ii < DUPLICATE_RX_CACHE_LENGTH; ii++) {
+			pCacheEntry = &(pCache->asCacheEntry[uIndex]);
+			if ((pCacheEntry->wFmSequence == pMACHeader->wSeqCtl) &&
+			    (!compare_ether_addr(&(pCacheEntry->abyAddr2[0]), &(pMACHeader->abyAddr2[0])))
+) {
+				/* Duplicate match */
+				return true;
+			}
+			ADD_ONE_WITH_WRAP_AROUND(uIndex, DUPLICATE_RX_CACHE_LENGTH);
+		}
+	}
+	/* Not fount in cache - insert */
+	pCacheEntry = &pCache->asCacheEntry[pCache->uInPtr];
+	pCacheEntry->wFmSequence = pMACHeader->wSeqCtl;
+	memcpy(&(pCacheEntry->abyAddr2[0]), &(pMACHeader->abyAddr2[0]), ETH_ALEN);
+	ADD_ONE_WITH_WRAP_AROUND(pCache->uInPtr, DUPLICATE_RX_CACHE_LENGTH);
+	return false;
 }
 
 /*
@@ -108,22 +105,21 @@ bool WCTLbIsDuplicate (PSCache pCache, PS802_11Header pMACHeader)
  * Return Value: index number in Defragment Database
  *
  */
-unsigned int WCTLuSearchDFCB (PSDevice pDevice, PS802_11Header pMACHeader)
+unsigned int WCTLuSearchDFCB(PSDevice pDevice, PS802_11Header pMACHeader)
 {
-unsigned int ii;
-
-    for(ii=0;ii<pDevice->cbDFCB;ii++) {
-        if ((pDevice->sRxDFCB[ii].bInUse == true) &&
-            (!compare_ether_addr(&(pDevice->sRxDFCB[ii].abyAddr2[0]), &(pMACHeader->abyAddr2[0])))
-            ) {
-            //
-            return(ii);
-        }
-    }
-    return(pDevice->cbDFCB);
+	unsigned int ii;
+
+	for (ii = 0; ii < pDevice->cbDFCB; ii++) {
+		if ((pDevice->sRxDFCB[ii].bInUse == true) &&
+		    (!compare_ether_addr(&(pDevice->sRxDFCB[ii].abyAddr2[0]), &(pMACHeader->abyAddr2[0])))
+) {
+			//
+			return ii;
+		}
+	}
+	return pDevice->cbDFCB;
 }
 
-
 /*
  * Description:
  *      Insert received fragment packet in Defragment Database
@@ -138,27 +134,26 @@ unsigned int ii;
  * Return Value: index number in Defragment Database
  *
  */
-unsigned int WCTLuInsertDFCB (PSDevice pDevice, PS802_11Header pMACHeader)
+unsigned int WCTLuInsertDFCB(PSDevice pDevice, PS802_11Header pMACHeader)
 {
-unsigned int ii;
-
-    if (pDevice->cbFreeDFCB == 0)
-        return(pDevice->cbDFCB);
-    for(ii=0;ii<pDevice->cbDFCB;ii++) {
-        if (pDevice->sRxDFCB[ii].bInUse == false) {
-            pDevice->cbFreeDFCB--;
-            pDevice->sRxDFCB[ii].uLifetime = pDevice->dwMaxReceiveLifetime;
-            pDevice->sRxDFCB[ii].bInUse = true;
-            pDevice->sRxDFCB[ii].wSequence = (pMACHeader->wSeqCtl >> 4);
-            pDevice->sRxDFCB[ii].wFragNum = (pMACHeader->wSeqCtl & 0x000F);
-            memcpy(&(pDevice->sRxDFCB[ii].abyAddr2[0]), &(pMACHeader->abyAddr2[0]), ETH_ALEN);
-            return(ii);
-        }
-    }
-    return(pDevice->cbDFCB);
+	unsigned int ii;
+
+	if (pDevice->cbFreeDFCB == 0)
+		return pDevice->cbDFCB;
+	for (ii = 0; ii < pDevice->cbDFCB; ii++) {
+		if (pDevice->sRxDFCB[ii].bInUse == false) {
+			pDevice->cbFreeDFCB--;
+			pDevice->sRxDFCB[ii].uLifetime = pDevice->dwMaxReceiveLifetime;
+			pDevice->sRxDFCB[ii].bInUse = true;
+			pDevice->sRxDFCB[ii].wSequence = (pMACHeader->wSeqCtl >> 4);
+			pDevice->sRxDFCB[ii].wFragNum = (pMACHeader->wSeqCtl & 0x000F);
+			memcpy(&(pDevice->sRxDFCB[ii].abyAddr2[0]), &(pMACHeader->abyAddr2[0]), ETH_ALEN);
+			return ii;
+		}
+	}
+	return pDevice->cbDFCB;
 }
 
-
 /*
  * Description:
  *      Handle received fragment packet
@@ -175,76 +170,67 @@ unsigned int ii;
  * Return Value: true if it is valid fragment packet and we have resource to defragment; otherwise false
  *
  */
-bool WCTLbHandleFragment (PSDevice pDevice, PS802_11Header pMACHeader, unsigned int cbFrameLength, bool bWEP, bool bExtIV)
+bool WCTLbHandleFragment(PSDevice pDevice, PS802_11Header pMACHeader, unsigned int cbFrameLength, bool bWEP, bool bExtIV)
 {
-unsigned int uHeaderSize;
-
-
-    if (bWEP == true) {
-        uHeaderSize = 28;
-        if (bExtIV)
-        // ExtIV
-            uHeaderSize +=4;
-    }
-    else {
-        uHeaderSize = 24;
-    }
-
-    if (IS_FIRST_FRAGMENT_PKT(pMACHeader)) {
-        pDevice->uCurrentDFCBIdx = WCTLuSearchDFCB(pDevice, pMACHeader);
-        if (pDevice->uCurrentDFCBIdx < pDevice->cbDFCB) {
-            // duplicate, we must flush previous DCB
-            pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].uLifetime = pDevice->dwMaxReceiveLifetime;
-            pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wSequence = (pMACHeader->wSeqCtl >> 4);
-            pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wFragNum = (pMACHeader->wSeqCtl & 0x000F);
-        }
-        else {
-            pDevice->uCurrentDFCBIdx = WCTLuInsertDFCB(pDevice, pMACHeader);
-            if (pDevice->uCurrentDFCBIdx == pDevice->cbDFCB) {
-                return(false);
-            }
-        }
-        // reserve 4 byte to match MAC RX Buffer
-        pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer = (unsigned char *) (pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].skb->data + 4);
-        memcpy(pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer, pMACHeader, cbFrameLength);
-        pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].cbFrameLength = cbFrameLength;
-        pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer += cbFrameLength;
-        pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wFragNum++;
-        //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "First pDevice->uCurrentDFCBIdx= %d\n", pDevice->uCurrentDFCBIdx);
-        return(false);
-    }
-    else {
-        pDevice->uCurrentDFCBIdx = WCTLuSearchDFCB(pDevice, pMACHeader);
-        if (pDevice->uCurrentDFCBIdx != pDevice->cbDFCB) {
-            if ((pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wSequence == (pMACHeader->wSeqCtl >> 4)) &&
-                (pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wFragNum == (pMACHeader->wSeqCtl & 0x000F)) &&
-                ((pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].cbFrameLength + cbFrameLength - uHeaderSize) < 2346)) {
-
-                memcpy(pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer, ((unsigned char *) (pMACHeader) + uHeaderSize), (cbFrameLength - uHeaderSize));
-                pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].cbFrameLength += (cbFrameLength - uHeaderSize);
-                pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer += (cbFrameLength - uHeaderSize);
-                pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wFragNum++;
-                //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Second pDevice->uCurrentDFCBIdx= %d\n", pDevice->uCurrentDFCBIdx);
-            }
-            else {
-                // seq error or frag # error flush DFCB
-                pDevice->cbFreeDFCB++;
-                pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].bInUse = false;
-                return(false);
-            }
-        }
-        else {
-            return(false);
-        }
-        if (IS_LAST_FRAGMENT_PKT(pMACHeader)) {
-            //enq defragcontrolblock
-            pDevice->cbFreeDFCB++;
-            pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].bInUse = false;
-            //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Last pDevice->uCurrentDFCBIdx= %d\n", pDevice->uCurrentDFCBIdx);
-            return(true);
-        }
-        return(false);
-    }
+	unsigned int uHeaderSize;
+
+	if (bWEP == true) {
+		uHeaderSize = 28;
+		if (bExtIV)
+			// ExtIV
+			uHeaderSize += 4;
+	} else {
+		uHeaderSize = 24;
+	}
+
+	if (IS_FIRST_FRAGMENT_PKT(pMACHeader)) {
+		pDevice->uCurrentDFCBIdx = WCTLuSearchDFCB(pDevice, pMACHeader);
+		if (pDevice->uCurrentDFCBIdx < pDevice->cbDFCB) {
+			// duplicate, we must flush previous DCB
+			pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].uLifetime = pDevice->dwMaxReceiveLifetime;
+			pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wSequence = (pMACHeader->wSeqCtl >> 4);
+			pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wFragNum = (pMACHeader->wSeqCtl & 0x000F);
+		} else {
+			pDevice->uCurrentDFCBIdx = WCTLuInsertDFCB(pDevice, pMACHeader);
+			if (pDevice->uCurrentDFCBIdx == pDevice->cbDFCB) {
+				return false;
+			}
+		}
+		// reserve 4 byte to match MAC RX Buffer
+		pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer = (unsigned char *)(pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].skb->data + 4);
+		memcpy(pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer, pMACHeader, cbFrameLength);
+		pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].cbFrameLength = cbFrameLength;
+		pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer += cbFrameLength;
+		pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wFragNum++;
+		//DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "First pDevice->uCurrentDFCBIdx= %d\n", pDevice->uCurrentDFCBIdx);
+		return false;
+	} else {
+		pDevice->uCurrentDFCBIdx = WCTLuSearchDFCB(pDevice, pMACHeader);
+		if (pDevice->uCurrentDFCBIdx != pDevice->cbDFCB) {
+			if ((pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wSequence == (pMACHeader->wSeqCtl >> 4)) &&
+			    (pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wFragNum == (pMACHeader->wSeqCtl & 0x000F)) &&
+			    ((pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].cbFrameLength + cbFrameLength - uHeaderSize) < 2346)) {
+				memcpy(pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer, ((unsigned char *)(pMACHeader) + uHeaderSize), (cbFrameLength - uHeaderSize));
+				pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].cbFrameLength += (cbFrameLength - uHeaderSize);
+				pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer += (cbFrameLength - uHeaderSize);
+				pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wFragNum++;
+				//DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Second pDevice->uCurrentDFCBIdx= %d\n", pDevice->uCurrentDFCBIdx);
+			} else {
+				// seq error or frag # error flush DFCB
+				pDevice->cbFreeDFCB++;
+				pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].bInUse = false;
+				return false;
+			}
+		} else {
+			return false;
+		}
+		if (IS_LAST_FRAGMENT_PKT(pMACHeader)) {
+			//enq defragcontrolblock
+			pDevice->cbFreeDFCB++;
+			pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].bInUse = false;
+			//DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Last pDevice->uCurrentDFCBIdx= %d\n", pDevice->uCurrentDFCBIdx);
+			return true;
+		}
+		return false;
+	}
 }
-
-
diff --git a/drivers/staging/vt6655/wctl.h b/drivers/staging/vt6655/wctl.h
index a92bb6d..1ffb273 100644
--- a/drivers/staging/vt6655/wctl.h
+++ b/drivers/staging/vt6655/wctl.h
@@ -35,61 +35,60 @@
 
 /*---------------------  Export Definitions -------------------------*/
 
-#define IS_TYPE_DATA(pMACHeader)                                                        \
-    ((((PS802_11Header) pMACHeader)->wFrameCtl & TYPE_802_11_MASK) == TYPE_802_11_DATA)
+#define IS_TYPE_DATA(pMACHeader)					\
+	((((PS802_11Header) pMACHeader)->wFrameCtl & TYPE_802_11_MASK) == TYPE_802_11_DATA)
 
-#define IS_TYPE_MGMT(pMACHeader)                                                        \
-    ((((PS802_11Header) pMACHeader)->wFrameCtl & TYPE_802_11_MASK) == TYPE_802_11_MGMT)
+#define IS_TYPE_MGMT(pMACHeader)					\
+	((((PS802_11Header) pMACHeader)->wFrameCtl & TYPE_802_11_MASK) == TYPE_802_11_MGMT)
 
-#define IS_TYPE_CONTROL(pMACHeader)                                                     \
-    ((((PS802_11Header) pMACHeader)->wFrameCtl & TYPE_802_11_MASK) == TYPE_802_11_CTL)
+#define IS_TYPE_CONTROL(pMACHeader)					\
+	((((PS802_11Header) pMACHeader)->wFrameCtl & TYPE_802_11_MASK) == TYPE_802_11_CTL)
 
-#define IS_FC_MOREDATA(pMACHeader)                                                      \
-    ((((PS802_11Header) pMACHeader)->wFrameCtl & FC_MOREDATA) == FC_MOREDATA)
+#define IS_FC_MOREDATA(pMACHeader)					\
+	((((PS802_11Header) pMACHeader)->wFrameCtl & FC_MOREDATA) == FC_MOREDATA)
 
-#define IS_FC_POWERMGT(pMACHeader)                                                      \
-    ((((PS802_11Header) pMACHeader)->wFrameCtl & FC_POWERMGT) == FC_POWERMGT)
+#define IS_FC_POWERMGT(pMACHeader)					\
+	((((PS802_11Header) pMACHeader)->wFrameCtl & FC_POWERMGT) == FC_POWERMGT)
 
-#define IS_FC_RETRY(pMACHeader)                                                         \
-    ((((PS802_11Header) pMACHeader)->wFrameCtl & FC_RETRY) == FC_RETRY)
+#define IS_FC_RETRY(pMACHeader)						\
+	((((PS802_11Header) pMACHeader)->wFrameCtl & FC_RETRY) == FC_RETRY)
 
-#define IS_FC_WEP(pMACHeader)                                                           \
-    ((((PS802_11Header) pMACHeader)->wFrameCtl & FC_WEP) == FC_WEP)
+#define IS_FC_WEP(pMACHeader)						\
+	((((PS802_11Header) pMACHeader)->wFrameCtl & FC_WEP) == FC_WEP)
 
 #ifdef __BIG_ENDIAN
 
-#define IS_FRAGMENT_PKT(pMACHeader)                                                     \
-    (((((PS802_11Header) pMACHeader)->wFrameCtl & FC_MOREFRAG) != 0) |                  \
-     ((((PS802_11Header) pMACHeader)->wSeqCtl & 0x0F00) != 0))
+#define IS_FRAGMENT_PKT(pMACHeader)					\
+	(((((PS802_11Header) pMACHeader)->wFrameCtl & FC_MOREFRAG) != 0) | \
+	 ((((PS802_11Header) pMACHeader)->wSeqCtl & 0x0F00) != 0))
 
-#define IS_FIRST_FRAGMENT_PKT(pMACHeader)                                               \
-    ((((PS802_11Header) pMACHeader)->wSeqCtl & 0x0F00) == 0)
+#define IS_FIRST_FRAGMENT_PKT(pMACHeader)				\
+	((((PS802_11Header) pMACHeader)->wSeqCtl & 0x0F00) == 0)
 
 #else
 
-#define IS_FRAGMENT_PKT(pMACHeader)                                                     \
-    (((((PS802_11Header) pMACHeader)->wFrameCtl & FC_MOREFRAG) != 0) |                  \
-     ((((PS802_11Header) pMACHeader)->wSeqCtl & 0x000F) != 0))
+#define IS_FRAGMENT_PKT(pMACHeader)					\
+	(((((PS802_11Header) pMACHeader)->wFrameCtl & FC_MOREFRAG) != 0) | \
+	 ((((PS802_11Header) pMACHeader)->wSeqCtl & 0x000F) != 0))
 
-#define IS_FIRST_FRAGMENT_PKT(pMACHeader)                                               \
-    ((((PS802_11Header) pMACHeader)->wSeqCtl & 0x000F) == 0)
+#define IS_FIRST_FRAGMENT_PKT(pMACHeader)				\
+	((((PS802_11Header) pMACHeader)->wSeqCtl & 0x000F) == 0)
 
 #endif//#ifdef __BIG_ENDIAN
 
-#define IS_LAST_FRAGMENT_PKT(pMACHeader)                                                \
-    ((((PS802_11Header) pMACHeader)->wFrameCtl & FC_MOREFRAG) == 0)
+#define IS_LAST_FRAGMENT_PKT(pMACHeader)				\
+	((((PS802_11Header) pMACHeader)->wFrameCtl & FC_MOREFRAG) == 0)
 
-#define IS_CTL_PSPOLL(pMACHeader)                                                       \
-    ((((PS802_11Header) pMACHeader)->wFrameCtl & TYPE_SUBTYPE_MASK) == TYPE_CTL_PSPOLL)
-
-
-#define ADD_ONE_WITH_WRAP_AROUND(uVar, uModulo) {   \
-    if ((uVar) >= ((uModulo) - 1))                  \
-        (uVar) = 0;                                 \
-    else                                            \
-        (uVar)++;                                   \
-}
+#define IS_CTL_PSPOLL(pMACHeader)					\
+	((((PS802_11Header) pMACHeader)->wFrameCtl & TYPE_SUBTYPE_MASK) == TYPE_CTL_PSPOLL)
 
+#define ADD_ONE_WITH_WRAP_AROUND(uVar, uModulo)		\
+do {							\
+	if ((uVar) >= ((uModulo) - 1))			\
+		(uVar) = 0;				\
+	else						\
+		(uVar)++;				\
+} while (0)
 
 /*---------------------  Export Classes  ----------------------------*/
 
@@ -99,11 +98,8 @@
 
 bool WCTLbIsDuplicate(PSCache pCache, PS802_11Header pMACHeader);
 bool WCTLbHandleFragment(PSDevice pDevice, PS802_11Header pMACHeader,
-		unsigned int cbFrameLength, bool bWEP, bool bExtIV);
+			 unsigned int cbFrameLength, bool bWEP, bool bExtIV);
 unsigned int WCTLuSearchDFCB(PSDevice pDevice, PS802_11Header pMACHeader);
 unsigned int WCTLuInsertDFCB(PSDevice pDevice, PS802_11Header pMACHeader);
 
 #endif // __WCTL_H__
-
-
-
diff --git a/drivers/staging/vt6655/wmgr.c b/drivers/staging/vt6655/wmgr.c
index b08a611..9938813 100644
--- a/drivers/staging/vt6655/wmgr.c
+++ b/drivers/staging/vt6655/wmgr.c
@@ -84,260 +84,251 @@
 
 /*---------------------  Static Definitions -------------------------*/
 
-
-
 /*---------------------  Static Classes  ----------------------------*/
 
 /*---------------------  Static Variables  --------------------------*/
-static int          msglevel                =MSG_LEVEL_INFO;
+static int msglevel = MSG_LEVEL_INFO;
 //static int          msglevel                =MSG_LEVEL_DEBUG;
 
 /*---------------------  Static Functions  --------------------------*/
 //2008-8-4 <add> by chester
 static bool ChannelExceedZoneType(
-    PSDevice pDevice,
-    unsigned char byCurrChannel
-    );
+	PSDevice pDevice,
+	unsigned char byCurrChannel
+);
 
 // Association/diassociation functions
 static
 PSTxMgmtPacket
 s_MgrMakeAssocRequest(
-    PSDevice pDevice,
-    PSMgmtObject pMgmt,
-    unsigned char *pDAddr,
-    unsigned short wCurrCapInfo,
-    unsigned short wListenInterval,
-    PWLAN_IE_SSID pCurrSSID,
-    PWLAN_IE_SUPP_RATES pCurrRates,
-    PWLAN_IE_SUPP_RATES pCurrExtSuppRates
-    );
+	PSDevice pDevice,
+	PSMgmtObject pMgmt,
+	unsigned char *pDAddr,
+	unsigned short wCurrCapInfo,
+	unsigned short wListenInterval,
+	PWLAN_IE_SSID pCurrSSID,
+	PWLAN_IE_SUPP_RATES pCurrRates,
+	PWLAN_IE_SUPP_RATES pCurrExtSuppRates
+);
 
 static
 void
 s_vMgrRxAssocRequest(
-    PSDevice pDevice,
-    PSMgmtObject pMgmt,
-    PSRxMgmtPacket pRxPacket,
-    unsigned int uNodeIndex
-    );
+	PSDevice pDevice,
+	PSMgmtObject pMgmt,
+	PSRxMgmtPacket pRxPacket,
+	unsigned int uNodeIndex
+);
 
 static
 PSTxMgmtPacket
 s_MgrMakeReAssocRequest(
-    PSDevice pDevice,
-    PSMgmtObject pMgmt,
-    unsigned char *pDAddr,
-    unsigned short wCurrCapInfo,
-    unsigned short wListenInterval,
-    PWLAN_IE_SSID pCurrSSID,
-    PWLAN_IE_SUPP_RATES pCurrRates,
-    PWLAN_IE_SUPP_RATES pCurrExtSuppRates
-    );
+	PSDevice pDevice,
+	PSMgmtObject pMgmt,
+	unsigned char *pDAddr,
+	unsigned short wCurrCapInfo,
+	unsigned short wListenInterval,
+	PWLAN_IE_SSID pCurrSSID,
+	PWLAN_IE_SUPP_RATES pCurrRates,
+	PWLAN_IE_SUPP_RATES pCurrExtSuppRates
+);
 
 static
 void
 s_vMgrRxAssocResponse(
-    PSDevice pDevice,
-    PSMgmtObject pMgmt,
-    PSRxMgmtPacket pRxPacket,
-    bool bReAssocType
-    );
+	PSDevice pDevice,
+	PSMgmtObject pMgmt,
+	PSRxMgmtPacket pRxPacket,
+	bool bReAssocType
+);
 
 static
 void
 s_vMgrRxDisassociation(
-    PSDevice pDevice,
-    PSMgmtObject pMgmt,
-    PSRxMgmtPacket pRxPacket
-    );
+	PSDevice pDevice,
+	PSMgmtObject pMgmt,
+	PSRxMgmtPacket pRxPacket
+);
 
 // Authentication/deauthen functions
 static
 void
 s_vMgrRxAuthenSequence_1(
-    PSDevice pDevice,
-    PSMgmtObject pMgmt,
-    PWLAN_FR_AUTHEN pFrame
-    );
+	PSDevice pDevice,
+	PSMgmtObject pMgmt,
+	PWLAN_FR_AUTHEN pFrame
+);
 
 static
 void
 s_vMgrRxAuthenSequence_2(
-    PSDevice pDevice,
-    PSMgmtObject pMgmt,
-    PWLAN_FR_AUTHEN pFrame
-    );
+	PSDevice pDevice,
+	PSMgmtObject pMgmt,
+	PWLAN_FR_AUTHEN pFrame
+);
 
 static
 void
 s_vMgrRxAuthenSequence_3(
-    PSDevice pDevice,
-    PSMgmtObject pMgmt,
-    PWLAN_FR_AUTHEN pFrame
-    );
+	PSDevice pDevice,
+	PSMgmtObject pMgmt,
+	PWLAN_FR_AUTHEN pFrame
+);
 
 static
 void
 s_vMgrRxAuthenSequence_4(
-    PSDevice pDevice,
-    PSMgmtObject pMgmt,
-    PWLAN_FR_AUTHEN pFrame
-    );
+	PSDevice pDevice,
+	PSMgmtObject pMgmt,
+	PWLAN_FR_AUTHEN pFrame
+);
 
 static
 void
 s_vMgrRxAuthentication(
-    PSDevice pDevice,
-    PSMgmtObject pMgmt,
-    PSRxMgmtPacket pRxPacket
-    );
+	PSDevice pDevice,
+	PSMgmtObject pMgmt,
+	PSRxMgmtPacket pRxPacket
+);
 
 static
 void
 s_vMgrRxDeauthentication(
-    PSDevice pDevice,
-    PSMgmtObject pMgmt,
-    PSRxMgmtPacket pRxPacket
-    );
+	PSDevice pDevice,
+	PSMgmtObject pMgmt,
+	PSRxMgmtPacket pRxPacket
+);
 
 // Scan functions
 // probe request/response functions
 static
 void
 s_vMgrRxProbeRequest(
-    PSDevice pDevice,
-    PSMgmtObject pMgmt,
-    PSRxMgmtPacket pRxPacket
-    );
+	PSDevice pDevice,
+	PSMgmtObject pMgmt,
+	PSRxMgmtPacket pRxPacket
+);
 
 static
 void
 s_vMgrRxProbeResponse(
-    PSDevice pDevice,
-    PSMgmtObject pMgmt,
-    PSRxMgmtPacket pRxPacket
-    );
+	PSDevice pDevice,
+	PSMgmtObject pMgmt,
+	PSRxMgmtPacket pRxPacket
+);
 
 // beacon functions
 static
 void
 s_vMgrRxBeacon(
-    PSDevice pDevice,
-    PSMgmtObject pMgmt,
-    PSRxMgmtPacket pRxPacket,
-    bool bInScan
-    );
+	PSDevice pDevice,
+	PSMgmtObject pMgmt,
+	PSRxMgmtPacket pRxPacket,
+	bool bInScan
+);
 
 static
 void
 s_vMgrFormatTIM(
-    PSMgmtObject pMgmt,
-    PWLAN_IE_TIM pTIM
-    );
+	PSMgmtObject pMgmt,
+	PWLAN_IE_TIM pTIM
+);
 
 static
 PSTxMgmtPacket
 s_MgrMakeBeacon(
-    PSDevice pDevice,
-    PSMgmtObject pMgmt,
-    unsigned short wCurrCapInfo,
-    unsigned short wCurrBeaconPeriod,
-    unsigned int uCurrChannel,
-    unsigned short wCurrATIMWinodw,
-    PWLAN_IE_SSID pCurrSSID,
-    unsigned char *pCurrBSSID,
-    PWLAN_IE_SUPP_RATES pCurrSuppRates,
-    PWLAN_IE_SUPP_RATES pCurrExtSuppRates
-    );
-
+	PSDevice pDevice,
+	PSMgmtObject pMgmt,
+	unsigned short wCurrCapInfo,
+	unsigned short wCurrBeaconPeriod,
+	unsigned int uCurrChannel,
+	unsigned short wCurrATIMWinodw,
+	PWLAN_IE_SSID pCurrSSID,
+	unsigned char *pCurrBSSID,
+	PWLAN_IE_SUPP_RATES pCurrSuppRates,
+	PWLAN_IE_SUPP_RATES pCurrExtSuppRates
+);
 
 // Association response
 static
 PSTxMgmtPacket
 s_MgrMakeAssocResponse(
-    PSDevice pDevice,
-    PSMgmtObject pMgmt,
-    unsigned short wCurrCapInfo,
-    unsigned short wAssocStatus,
-    unsigned short wAssocAID,
-    unsigned char *pDstAddr,
-    PWLAN_IE_SUPP_RATES pCurrSuppRates,
-    PWLAN_IE_SUPP_RATES pCurrExtSuppRates
-    );
+	PSDevice pDevice,
+	PSMgmtObject pMgmt,
+	unsigned short wCurrCapInfo,
+	unsigned short wAssocStatus,
+	unsigned short wAssocAID,
+	unsigned char *pDstAddr,
+	PWLAN_IE_SUPP_RATES pCurrSuppRates,
+	PWLAN_IE_SUPP_RATES pCurrExtSuppRates
+);
 
 // ReAssociation response
 static
 PSTxMgmtPacket
 s_MgrMakeReAssocResponse(
-    PSDevice pDevice,
-    PSMgmtObject pMgmt,
-    unsigned short wCurrCapInfo,
-    unsigned short wAssocStatus,
-    unsigned short wAssocAID,
-    unsigned char *pDstAddr,
-    PWLAN_IE_SUPP_RATES pCurrSuppRates,
-    PWLAN_IE_SUPP_RATES pCurrExtSuppRates
-    );
+	PSDevice pDevice,
+	PSMgmtObject pMgmt,
+	unsigned short wCurrCapInfo,
+	unsigned short wAssocStatus,
+	unsigned short wAssocAID,
+	unsigned char *pDstAddr,
+	PWLAN_IE_SUPP_RATES pCurrSuppRates,
+	PWLAN_IE_SUPP_RATES pCurrExtSuppRates
+);
 
 // Probe response
 static
 PSTxMgmtPacket
 s_MgrMakeProbeResponse(
-    PSDevice pDevice,
-    PSMgmtObject pMgmt,
-    unsigned short wCurrCapInfo,
-    unsigned short wCurrBeaconPeriod,
-    unsigned int uCurrChannel,
-    unsigned short wCurrATIMWinodw,
-    unsigned char *pDstAddr,
-    PWLAN_IE_SSID pCurrSSID,
-    unsigned char *pCurrBSSID,
-    PWLAN_IE_SUPP_RATES pCurrSuppRates,
-    PWLAN_IE_SUPP_RATES pCurrExtSuppRates,
-    unsigned char byPHYType
-    );
+	PSDevice pDevice,
+	PSMgmtObject pMgmt,
+	unsigned short wCurrCapInfo,
+	unsigned short wCurrBeaconPeriod,
+	unsigned int uCurrChannel,
+	unsigned short wCurrATIMWinodw,
+	unsigned char *pDstAddr,
+	PWLAN_IE_SSID pCurrSSID,
+	unsigned char *pCurrBSSID,
+	PWLAN_IE_SUPP_RATES pCurrSuppRates,
+	PWLAN_IE_SUPP_RATES pCurrExtSuppRates,
+	unsigned char byPHYType
+);
 
 // received status
 static
 void
 s_vMgrLogStatus(
-    PSMgmtObject pMgmt,
-    unsigned short wStatus
-    );
-
+	PSMgmtObject pMgmt,
+	unsigned short wStatus
+);
 
 static
 void
-s_vMgrSynchBSS (
-    PSDevice      pDevice,
-    unsigned int uBSSMode,
-    PKnownBSS     pCurr,
-    PCMD_STATUS  pStatus
-    );
-
+s_vMgrSynchBSS(
+	PSDevice      pDevice,
+	unsigned int uBSSMode,
+	PKnownBSS     pCurr,
+	PCMD_STATUS  pStatus
+);
 
 static bool
-s_bCipherMatch (
-    PKnownBSS                        pBSSNode,
-    NDIS_802_11_ENCRYPTION_STATUS    EncStatus,
-    unsigned char *pbyCCSPK,
-    unsigned char *pbyCCSGK
-    );
-
- static void  Encyption_Rebuild(
-    PSDevice pDevice,
-    PKnownBSS pCurr
- );
-
-
+s_bCipherMatch(
+	PKnownBSS                        pBSSNode,
+	NDIS_802_11_ENCRYPTION_STATUS    EncStatus,
+	unsigned char *pbyCCSPK,
+	unsigned char *pbyCCSGK
+);
+
+static void  Encyption_Rebuild(
+	PSDevice pDevice,
+	PKnownBSS pCurr
+);
 
 /*---------------------  Export Variables  --------------------------*/
 
-
 /*---------------------  Export Functions  --------------------------*/
 
-
 /*+
  *
  * Routine Description:
@@ -346,32 +337,31 @@ s_bCipherMatch (
  * Return Value:
  *    Ndis_staus.
  *
--*/
+ -*/
 
 void
 vMgrObjectInit(
-    void *hDeviceContext
-    )
+	void *hDeviceContext
+)
 {
-    PSDevice     pDevice = (PSDevice)hDeviceContext;
-    PSMgmtObject    pMgmt = pDevice->pMgmt;
-    int ii;
-
-
-    pMgmt->pbyPSPacketPool = &pMgmt->byPSPacketPool[0];
-    pMgmt->pbyMgmtPacketPool = &pMgmt->byMgmtPacketPool[0];
-    pMgmt->uCurrChannel = pDevice->uChannel;
-    for(ii=0;ii<WLAN_BSSID_LEN;ii++) {
-        pMgmt->abyDesireBSSID[ii] = 0xFF;
-    }
-    pMgmt->sAssocInfo.AssocInfo.Length = sizeof(NDIS_802_11_ASSOCIATION_INFORMATION);
-    //memset(pMgmt->abyDesireSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN +1);
-    pMgmt->byCSSPK = KEY_CTL_NONE;
-    pMgmt->byCSSGK = KEY_CTL_NONE;
-    pMgmt->wIBSSBeaconPeriod = DEFAULT_IBSS_BI;
-    BSSvClearBSSList((void *)pDevice, false);
-
-    return;
+	PSDevice     pDevice = (PSDevice)hDeviceContext;
+	PSMgmtObject    pMgmt = pDevice->pMgmt;
+	int ii;
+
+	pMgmt->pbyPSPacketPool = &pMgmt->byPSPacketPool[0];
+	pMgmt->pbyMgmtPacketPool = &pMgmt->byMgmtPacketPool[0];
+	pMgmt->uCurrChannel = pDevice->uChannel;
+	for (ii = 0; ii < WLAN_BSSID_LEN; ii++) {
+		pMgmt->abyDesireBSSID[ii] = 0xFF;
+	}
+	pMgmt->sAssocInfo.AssocInfo.Length = sizeof(NDIS_802_11_ASSOCIATION_INFORMATION);
+	//memset(pMgmt->abyDesireSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN +1);
+	pMgmt->byCSSPK = KEY_CTL_NONE;
+	pMgmt->byCSSGK = KEY_CTL_NONE;
+	pMgmt->wIBSSBeaconPeriod = DEFAULT_IBSS_BI;
+	BSSvClearBSSList((void *)pDevice, false);
+
+	return;
 }
 
 /*+
@@ -382,45 +372,42 @@ vMgrObjectInit(
  * Return Value:
  *    Ndis_staus.
  *
--*/
+ -*/
 
 void
 vMgrTimerInit(
-    void *hDeviceContext
-    )
+	void *hDeviceContext
+)
 {
-    PSDevice     pDevice = (PSDevice)hDeviceContext;
-    PSMgmtObject    pMgmt = pDevice->pMgmt;
-
-
-    init_timer(&pMgmt->sTimerSecondCallback);
-    pMgmt->sTimerSecondCallback.data = (unsigned long) pDevice;
-    pMgmt->sTimerSecondCallback.function = (TimerFunction)BSSvSecondCallBack;
-    pMgmt->sTimerSecondCallback.expires = RUN_AT(HZ);
-
-    init_timer(&pDevice->sTimerCommand);
-    pDevice->sTimerCommand.data = (unsigned long) pDevice;
-    pDevice->sTimerCommand.function = (TimerFunction)vCommandTimer;
-    pDevice->sTimerCommand.expires = RUN_AT(HZ);
-
-   #ifdef TxInSleep
-    init_timer(&pDevice->sTimerTxData);
-    pDevice->sTimerTxData.data = (unsigned long) pDevice;
-    pDevice->sTimerTxData.function = (TimerFunction)BSSvSecondTxData;
-    pDevice->sTimerTxData.expires = RUN_AT(10*HZ);      //10s callback
-    pDevice->fTxDataInSleep = false;
-    pDevice->IsTxDataTrigger = false;
-    pDevice->nTxDataTimeCout = 0;
-   #endif
-
-    pDevice->cbFreeCmdQueue = CMD_Q_SIZE;
-    pDevice->uCmdDequeueIdx = 0;
-    pDevice->uCmdEnqueueIdx = 0;
-
-    return;
-}
+	PSDevice     pDevice = (PSDevice)hDeviceContext;
+	PSMgmtObject    pMgmt = pDevice->pMgmt;
+
+	init_timer(&pMgmt->sTimerSecondCallback);
+	pMgmt->sTimerSecondCallback.data = (unsigned long) pDevice;
+	pMgmt->sTimerSecondCallback.function = (TimerFunction)BSSvSecondCallBack;
+	pMgmt->sTimerSecondCallback.expires = RUN_AT(HZ);
+
+	init_timer(&pDevice->sTimerCommand);
+	pDevice->sTimerCommand.data = (unsigned long) pDevice;
+	pDevice->sTimerCommand.function = (TimerFunction)vCommandTimer;
+	pDevice->sTimerCommand.expires = RUN_AT(HZ);
+
+#ifdef TxInSleep
+	init_timer(&pDevice->sTimerTxData);
+	pDevice->sTimerTxData.data = (unsigned long) pDevice;
+	pDevice->sTimerTxData.function = (TimerFunction)BSSvSecondTxData;
+	pDevice->sTimerTxData.expires = RUN_AT(10*HZ);      //10s callback
+	pDevice->fTxDataInSleep = false;
+	pDevice->IsTxDataTrigger = false;
+	pDevice->nTxDataTimeCout = 0;
+#endif
 
+	pDevice->cbFreeCmdQueue = CMD_Q_SIZE;
+	pDevice->uCmdDequeueIdx = 0;
+	pDevice->uCmdEnqueueIdx = 0;
 
+	return;
+}
 
 /*+
  *
@@ -430,25 +417,24 @@ vMgrTimerInit(
  * Return Value:
  *    None.
  *
--*/
+ -*/
 
 void
 vMgrObjectReset(
-    void *hDeviceContext
-    )
+	void *hDeviceContext
+)
 {
-    PSDevice         pDevice = (PSDevice)hDeviceContext;
-    PSMgmtObject        pMgmt = pDevice->pMgmt;
+	PSDevice         pDevice = (PSDevice)hDeviceContext;
+	PSMgmtObject        pMgmt = pDevice->pMgmt;
 
-    pMgmt->eCurrMode = WMAC_MODE_STANDBY;
-    pMgmt->eCurrState = WMAC_STATE_IDLE;
-    pDevice->bEnablePSMode = false;
-    // TODO: timer
+	pMgmt->eCurrMode = WMAC_MODE_STANDBY;
+	pMgmt->eCurrState = WMAC_STATE_IDLE;
+	pDevice->bEnablePSMode = false;
+	// TODO: timer
 
-    return;
+	return;
 }
 
-
 /*+
  *
  * Routine Description:
@@ -458,74 +444,66 @@ vMgrObjectReset(
  * Return Value:
  *    None.
  *
--*/
-
+ -*/
 
 void
 vMgrAssocBeginSta(
-    void *hDeviceContext,
-    PSMgmtObject pMgmt,
-    PCMD_STATUS pStatus
-    )
+	void *hDeviceContext,
+	PSMgmtObject pMgmt,
+	PCMD_STATUS pStatus
+)
 {
-    PSDevice             pDevice = (PSDevice)hDeviceContext;
-    PSTxMgmtPacket          pTxPacket;
-
-
-    pMgmt->wCurrCapInfo = 0;
-    pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_ESS(1);
-    if (pDevice->bEncryptionEnable) {
-        pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_PRIVACY(1);
-    }
-    // always allow receive short preamble
-    //if (pDevice->byPreambleType == 1) {
-    //    pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SHORTPREAMBLE(1);
-    //}
-    pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SHORTPREAMBLE(1);
-    if (pMgmt->wListenInterval == 0)
-        pMgmt->wListenInterval = 1;    // at least one.
-
-    // ERP Phy (802.11g) should support short preamble.
-    if (pMgmt->eCurrentPHYMode == PHY_TYPE_11G) {
-        pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SHORTPREAMBLE(1);
-        if (CARDbIsShorSlotTime(pMgmt->pAdapter) == true) {
-            pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SHORTSLOTTIME(1);
-        }
-    } else if (pMgmt->eCurrentPHYMode == PHY_TYPE_11B) {
-        if (CARDbIsShortPreamble(pMgmt->pAdapter) == true) {
-            pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SHORTPREAMBLE(1);
-        }
-    }
-    if (pMgmt->b11hEnable == true)
-        pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SPECTRUMMNG(1);
-
-    /* build an assocreq frame and send it */
-    pTxPacket = s_MgrMakeAssocRequest
-                (
-                  pDevice,
-                  pMgmt,
-                  pMgmt->abyCurrBSSID,
-                  pMgmt->wCurrCapInfo,
-                  pMgmt->wListenInterval,
-                  (PWLAN_IE_SSID)pMgmt->abyCurrSSID,
-                  (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates,
-                  (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates
-                );
-
-    if (pTxPacket != NULL ){
-        /* send the frame */
-        *pStatus = csMgmt_xmit(pDevice, pTxPacket);
-        if (*pStatus == CMD_STATUS_PENDING) {
-            pMgmt->eCurrState = WMAC_STATE_ASSOCPENDING;
-            *pStatus = CMD_STATUS_SUCCESS;
-        }
-    }
-    else
-        *pStatus = CMD_STATUS_RESOURCES;
-
-    return ;
-}
+	PSDevice             pDevice = (PSDevice)hDeviceContext;
+	PSTxMgmtPacket          pTxPacket;
+
+	pMgmt->wCurrCapInfo = 0;
+	pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_ESS(1);
+	if (pDevice->bEncryptionEnable) {
+		pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_PRIVACY(1);
+	}
+	pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SHORTPREAMBLE(1);
+	if (pMgmt->wListenInterval == 0)
+		pMgmt->wListenInterval = 1;    // at least one.
+
+	// ERP Phy (802.11g) should support short preamble.
+	if (pMgmt->eCurrentPHYMode == PHY_TYPE_11G) {
+		pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SHORTPREAMBLE(1);
+		if (CARDbIsShorSlotTime(pMgmt->pAdapter) == true) {
+			pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SHORTSLOTTIME(1);
+		}
+	} else if (pMgmt->eCurrentPHYMode == PHY_TYPE_11B) {
+		if (CARDbIsShortPreamble(pMgmt->pAdapter) == true) {
+			pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SHORTPREAMBLE(1);
+		}
+	}
+	if (pMgmt->b11hEnable == true)
+		pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SPECTRUMMNG(1);
+
+	/* build an assocreq frame and send it */
+	pTxPacket = s_MgrMakeAssocRequest
+		(
+			pDevice,
+			pMgmt,
+			pMgmt->abyCurrBSSID,
+			pMgmt->wCurrCapInfo,
+			pMgmt->wListenInterval,
+			(PWLAN_IE_SSID)pMgmt->abyCurrSSID,
+			(PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates,
+			(PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates
+);
+
+	if (pTxPacket != NULL) {
+		/* send the frame */
+		*pStatus = csMgmt_xmit(pDevice, pTxPacket);
+		if (*pStatus == CMD_STATUS_PENDING) {
+			pMgmt->eCurrState = WMAC_STATE_ASSOCPENDING;
+			*pStatus = CMD_STATUS_SUCCESS;
+		}
+	} else
+		*pStatus = CMD_STATUS_RESOURCES;
 
+	return;
+}
 
 /*+
  *
@@ -535,75 +513,66 @@ vMgrAssocBeginSta(
  * Return Value:
  *    None.
  *
--*/
+ -*/
 
 void
 vMgrReAssocBeginSta(
-    void *hDeviceContext,
-    PSMgmtObject pMgmt,
-    PCMD_STATUS pStatus
-    )
+	void *hDeviceContext,
+	PSMgmtObject pMgmt,
+	PCMD_STATUS pStatus
+)
 {
-    PSDevice             pDevice = (PSDevice)hDeviceContext;
-    PSTxMgmtPacket          pTxPacket;
-
-
-
-    pMgmt->wCurrCapInfo = 0;
-    pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_ESS(1);
-    if (pDevice->bEncryptionEnable) {
-        pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_PRIVACY(1);
-    }
-
-    //if (pDevice->byPreambleType == 1) {
-    //    pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SHORTPREAMBLE(1);
-    //}
-    pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SHORTPREAMBLE(1);
-
-    if (pMgmt->wListenInterval == 0)
-        pMgmt->wListenInterval = 1;    // at least one.
-
-
-    // ERP Phy (802.11g) should support short preamble.
-    if (pMgmt->eCurrentPHYMode == PHY_TYPE_11G) {
-        pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SHORTPREAMBLE(1);
-        if (CARDbIsShorSlotTime(pMgmt->pAdapter) == true) {
-            pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SHORTSLOTTIME(1);
-        }
-    } else if (pMgmt->eCurrentPHYMode == PHY_TYPE_11B) {
-        if (CARDbIsShortPreamble(pMgmt->pAdapter) == true) {
-            pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SHORTPREAMBLE(1);
-        }
-    }
-    if (pMgmt->b11hEnable == true)
-        pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SPECTRUMMNG(1);
-
-
-    pTxPacket = s_MgrMakeReAssocRequest
-                (
-                  pDevice,
-                  pMgmt,
-                  pMgmt->abyCurrBSSID,
-                  pMgmt->wCurrCapInfo,
-                  pMgmt->wListenInterval,
-                  (PWLAN_IE_SSID)pMgmt->abyCurrSSID,
-                  (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates,
-                  (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates
-                );
-
-    if (pTxPacket != NULL ){
-        /* send the frame */
-        *pStatus = csMgmt_xmit(pDevice, pTxPacket);
-        if (*pStatus != CMD_STATUS_PENDING) {
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt:Reassociation tx failed.\n");
-        }
-        else {
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt:Reassociation tx sending.\n");
-        }
-    }
-
-
-    return ;
+	PSDevice             pDevice = (PSDevice)hDeviceContext;
+	PSTxMgmtPacket          pTxPacket;
+
+	pMgmt->wCurrCapInfo = 0;
+	pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_ESS(1);
+	if (pDevice->bEncryptionEnable) {
+		pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_PRIVACY(1);
+	}
+
+	pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SHORTPREAMBLE(1);
+
+	if (pMgmt->wListenInterval == 0)
+		pMgmt->wListenInterval = 1;    // at least one.
+
+	// ERP Phy (802.11g) should support short preamble.
+	if (pMgmt->eCurrentPHYMode == PHY_TYPE_11G) {
+		pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SHORTPREAMBLE(1);
+		if (CARDbIsShorSlotTime(pMgmt->pAdapter) == true) {
+			pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SHORTSLOTTIME(1);
+		}
+	} else if (pMgmt->eCurrentPHYMode == PHY_TYPE_11B) {
+		if (CARDbIsShortPreamble(pMgmt->pAdapter) == true) {
+			pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SHORTPREAMBLE(1);
+		}
+	}
+	if (pMgmt->b11hEnable == true)
+		pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SPECTRUMMNG(1);
+
+	pTxPacket = s_MgrMakeReAssocRequest
+		(
+			pDevice,
+			pMgmt,
+			pMgmt->abyCurrBSSID,
+			pMgmt->wCurrCapInfo,
+			pMgmt->wListenInterval,
+			(PWLAN_IE_SSID)pMgmt->abyCurrSSID,
+			(PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates,
+			(PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates
+);
+
+	if (pTxPacket != NULL) {
+		/* send the frame */
+		*pStatus = csMgmt_xmit(pDevice, pTxPacket);
+		if (*pStatus != CMD_STATUS_PENDING) {
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt:Reassociation tx failed.\n");
+		} else {
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt:Reassociation tx sending.\n");
+		}
+	}
+
+	return;
 }
 
 /*+
@@ -614,59 +583,57 @@ vMgrReAssocBeginSta(
  * Return Value:
  *    None.
  *
--*/
+ -*/
 
 void
 vMgrDisassocBeginSta(
-    void *hDeviceContext,
-    PSMgmtObject pMgmt,
-    unsigned char *abyDestAddress,
-    unsigned short wReason,
-    PCMD_STATUS pStatus
-    )
+	void *hDeviceContext,
+	PSMgmtObject pMgmt,
+	unsigned char *abyDestAddress,
+	unsigned short wReason,
+	PCMD_STATUS pStatus
+)
 {
-    PSDevice            pDevice = (PSDevice)hDeviceContext;
-    PSTxMgmtPacket      pTxPacket = NULL;
-    WLAN_FR_DISASSOC    sFrame;
-
-    pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool;
-    memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_DISASSOC_FR_MAXLEN);
-    pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket));
-
-    // Setup the sFrame structure
-    sFrame.pBuf = (unsigned char *)pTxPacket->p80211Header;
-    sFrame.len = WLAN_DISASSOC_FR_MAXLEN;
-
-    // format fixed field frame structure
-    vMgrEncodeDisassociation(&sFrame);
-
-    // Setup the header
-    sFrame.pHdr->sA3.wFrameCtl = cpu_to_le16(
-        (
-        WLAN_SET_FC_FTYPE(WLAN_TYPE_MGR) |
-        WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_DISASSOC)
-        ));
-
-    memcpy( sFrame.pHdr->sA3.abyAddr1, abyDestAddress, WLAN_ADDR_LEN);
-    memcpy( sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN);
-    memcpy( sFrame.pHdr->sA3.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN);
-
-    // Set reason code
-    *(sFrame.pwReason) = cpu_to_le16(wReason);
-    pTxPacket->cbMPDULen = sFrame.len;
-    pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN;
-
-    // send the frame
-    *pStatus = csMgmt_xmit(pDevice, pTxPacket);
-    if (*pStatus == CMD_STATUS_PENDING) {
-        pMgmt->eCurrState = WMAC_STATE_IDLE;
-        *pStatus = CMD_STATUS_SUCCESS;
-    }
-
-    return;
-}
-
+	PSDevice            pDevice = (PSDevice)hDeviceContext;
+	PSTxMgmtPacket      pTxPacket = NULL;
+	WLAN_FR_DISASSOC    sFrame;
+
+	pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool;
+	memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_DISASSOC_FR_MAXLEN);
+	pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket));
+
+	// Setup the sFrame structure
+	sFrame.pBuf = (unsigned char *)pTxPacket->p80211Header;
+	sFrame.len = WLAN_DISASSOC_FR_MAXLEN;
+
+	// format fixed field frame structure
+	vMgrEncodeDisassociation(&sFrame);
+
+	// Setup the header
+	sFrame.pHdr->sA3.wFrameCtl = cpu_to_le16(
+		(
+			WLAN_SET_FC_FTYPE(WLAN_TYPE_MGR) |
+			WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_DISASSOC)
+));
+
+	memcpy(sFrame.pHdr->sA3.abyAddr1, abyDestAddress, WLAN_ADDR_LEN);
+	memcpy(sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN);
+	memcpy(sFrame.pHdr->sA3.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN);
+
+	// Set reason code
+	*(sFrame.pwReason) = cpu_to_le16(wReason);
+	pTxPacket->cbMPDULen = sFrame.len;
+	pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN;
+
+	// send the frame
+	*pStatus = csMgmt_xmit(pDevice, pTxPacket);
+	if (*pStatus == CMD_STATUS_PENDING) {
+		pMgmt->eCurrState = WMAC_STATE_IDLE;
+		*pStatus = CMD_STATUS_SUCCESS;
+	}
 
+	return;
+}
 
 /*+
  *
@@ -676,153 +643,147 @@ vMgrDisassocBeginSta(
  * Return Value:
  *    None.
  *
--*/
+ -*/
 
 static
 void
 s_vMgrRxAssocRequest(
-    PSDevice pDevice,
-    PSMgmtObject pMgmt,
-    PSRxMgmtPacket pRxPacket,
-    unsigned int uNodeIndex
-    )
+	PSDevice pDevice,
+	PSMgmtObject pMgmt,
+	PSRxMgmtPacket pRxPacket,
+	unsigned int uNodeIndex
+)
 {
-    WLAN_FR_ASSOCREQ    sFrame;
-    CMD_STATUS          Status;
-    PSTxMgmtPacket      pTxPacket;
-    unsigned short wAssocStatus = 0;
-    unsigned short wAssocAID = 0;
-    unsigned int uRateLen = WLAN_RATES_MAXLEN;
-    unsigned char abyCurrSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1];
-    unsigned char abyCurrExtSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1];
-
-
-    if (pMgmt->eCurrMode != WMAC_MODE_ESS_AP)
-        return;
-    //  node index not found
-    if (!uNodeIndex)
-        return;
-
-    //check if node is authenticated
-    //decode the frame
-    memset(&sFrame, 0, sizeof(WLAN_FR_ASSOCREQ));
-    memset(abyCurrSuppRates, 0, WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1);
-    memset(abyCurrExtSuppRates, 0, WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1);
-    sFrame.len = pRxPacket->cbMPDULen;
-    sFrame.pBuf = (unsigned char *)pRxPacket->p80211Header;
-
-    vMgrDecodeAssocRequest(&sFrame);
-
-    if (pMgmt->sNodeDBTable[uNodeIndex].eNodeState >= NODE_AUTH) {
-        pMgmt->sNodeDBTable[uNodeIndex].eNodeState = NODE_ASSOC;
-        pMgmt->sNodeDBTable[uNodeIndex].wCapInfo = cpu_to_le16(*sFrame.pwCapInfo);
-        pMgmt->sNodeDBTable[uNodeIndex].wListenInterval = cpu_to_le16(*sFrame.pwListenInterval);
-        pMgmt->sNodeDBTable[uNodeIndex].bPSEnable =
-                WLAN_GET_FC_PWRMGT(sFrame.pHdr->sA3.wFrameCtl) ? true : false;
-        // Todo: check sta basic rate, if ap can't support, set status code
-        if (pDevice->eCurrentPHYType == PHY_TYPE_11B) {
-            uRateLen = WLAN_RATES_MAXLEN_11B;
-        }
-        abyCurrSuppRates[0] = WLAN_EID_SUPP_RATES;
-        abyCurrSuppRates[1] = RATEuSetIE((PWLAN_IE_SUPP_RATES)sFrame.pSuppRates,
-                                         (PWLAN_IE_SUPP_RATES)abyCurrSuppRates,
-                                         uRateLen);
-        abyCurrExtSuppRates[0] = WLAN_EID_EXTSUPP_RATES;
-        if (pDevice->eCurrentPHYType == PHY_TYPE_11G) {
-            abyCurrExtSuppRates[1] = RATEuSetIE((PWLAN_IE_SUPP_RATES)sFrame.pExtSuppRates,
-                                                (PWLAN_IE_SUPP_RATES)abyCurrExtSuppRates,
-                                                uRateLen);
-        } else {
-            abyCurrExtSuppRates[1] = 0;
-        }
-
-
-        RATEvParseMaxRate((void *)pDevice,
-                           (PWLAN_IE_SUPP_RATES)abyCurrSuppRates,
-                           (PWLAN_IE_SUPP_RATES)abyCurrExtSuppRates,
-                           false, // do not change our basic rate
-                           &(pMgmt->sNodeDBTable[uNodeIndex].wMaxBasicRate),
-                           &(pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate),
-                           &(pMgmt->sNodeDBTable[uNodeIndex].wSuppRate),
-                           &(pMgmt->sNodeDBTable[uNodeIndex].byTopCCKBasicRate),
-                           &(pMgmt->sNodeDBTable[uNodeIndex].byTopOFDMBasicRate)
-                          );
-
-        // set max tx rate
-        pMgmt->sNodeDBTable[uNodeIndex].wTxDataRate =
-                pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate;
+	WLAN_FR_ASSOCREQ    sFrame;
+	CMD_STATUS          Status;
+	PSTxMgmtPacket      pTxPacket;
+	unsigned short wAssocStatus = 0;
+	unsigned short wAssocAID = 0;
+	unsigned int uRateLen = WLAN_RATES_MAXLEN;
+	unsigned char abyCurrSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1];
+	unsigned char abyCurrExtSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1];
+
+	if (pMgmt->eCurrMode != WMAC_MODE_ESS_AP)
+		return;
+	//  node index not found
+	if (!uNodeIndex)
+		return;
+
+	//check if node is authenticated
+	//decode the frame
+	memset(&sFrame, 0, sizeof(WLAN_FR_ASSOCREQ));
+	memset(abyCurrSuppRates, 0, WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1);
+	memset(abyCurrExtSuppRates, 0, WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1);
+	sFrame.len = pRxPacket->cbMPDULen;
+	sFrame.pBuf = (unsigned char *)pRxPacket->p80211Header;
+
+	vMgrDecodeAssocRequest(&sFrame);
+
+	if (pMgmt->sNodeDBTable[uNodeIndex].eNodeState >= NODE_AUTH) {
+		pMgmt->sNodeDBTable[uNodeIndex].eNodeState = NODE_ASSOC;
+		pMgmt->sNodeDBTable[uNodeIndex].wCapInfo = cpu_to_le16(*sFrame.pwCapInfo);
+		pMgmt->sNodeDBTable[uNodeIndex].wListenInterval = cpu_to_le16(*sFrame.pwListenInterval);
+		pMgmt->sNodeDBTable[uNodeIndex].bPSEnable =
+			WLAN_GET_FC_PWRMGT(sFrame.pHdr->sA3.wFrameCtl) ? true : false;
+		// Todo: check sta basic rate, if ap can't support, set status code
+		if (pDevice->eCurrentPHYType == PHY_TYPE_11B) {
+			uRateLen = WLAN_RATES_MAXLEN_11B;
+		}
+		abyCurrSuppRates[0] = WLAN_EID_SUPP_RATES;
+		abyCurrSuppRates[1] = RATEuSetIE((PWLAN_IE_SUPP_RATES)sFrame.pSuppRates,
+						 (PWLAN_IE_SUPP_RATES)abyCurrSuppRates,
+						 uRateLen);
+		abyCurrExtSuppRates[0] = WLAN_EID_EXTSUPP_RATES;
+		if (pDevice->eCurrentPHYType == PHY_TYPE_11G) {
+			abyCurrExtSuppRates[1] = RATEuSetIE((PWLAN_IE_SUPP_RATES)sFrame.pExtSuppRates,
+							    (PWLAN_IE_SUPP_RATES)abyCurrExtSuppRates,
+							    uRateLen);
+		} else {
+			abyCurrExtSuppRates[1] = 0;
+		}
+
+		RATEvParseMaxRate((void *)pDevice,
+				  (PWLAN_IE_SUPP_RATES)abyCurrSuppRates,
+				  (PWLAN_IE_SUPP_RATES)abyCurrExtSuppRates,
+				  false, // do not change our basic rate
+				  &(pMgmt->sNodeDBTable[uNodeIndex].wMaxBasicRate),
+				  &(pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate),
+				  &(pMgmt->sNodeDBTable[uNodeIndex].wSuppRate),
+				  &(pMgmt->sNodeDBTable[uNodeIndex].byTopCCKBasicRate),
+				  &(pMgmt->sNodeDBTable[uNodeIndex].byTopOFDMBasicRate)
+);
+
+		// set max tx rate
+		pMgmt->sNodeDBTable[uNodeIndex].wTxDataRate =
+			pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate;
 #ifdef	PLICE_DEBUG
-	printk("RxAssocRequest:wTxDataRate is %d\n",pMgmt->sNodeDBTable[uNodeIndex].wTxDataRate);
+		printk("RxAssocRequest:wTxDataRate is %d\n", pMgmt->sNodeDBTable[uNodeIndex].wTxDataRate);
 #endif
 		// Todo: check sta preamble, if ap can't support, set status code
-        pMgmt->sNodeDBTable[uNodeIndex].bShortPreamble =
-                WLAN_GET_CAP_INFO_SHORTPREAMBLE(*sFrame.pwCapInfo);
-        pMgmt->sNodeDBTable[uNodeIndex].bShortSlotTime =
-                WLAN_GET_CAP_INFO_SHORTSLOTTIME(*sFrame.pwCapInfo);
-        pMgmt->sNodeDBTable[uNodeIndex].wAID = (unsigned short)uNodeIndex;
-        wAssocStatus = WLAN_MGMT_STATUS_SUCCESS;
-        wAssocAID = (unsigned short)uNodeIndex;
-        // check if ERP support
-        if(pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate > RATE_11M)
-           pMgmt->sNodeDBTable[uNodeIndex].bERPExist = true;
-
-        if (pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate <= RATE_11M) {
-            // B only STA join
-            pDevice->bProtectMode = true;
-            pDevice->bNonERPPresent = true;
-        }
-        if (pMgmt->sNodeDBTable[uNodeIndex].bShortPreamble == false) {
-            pDevice->bBarkerPreambleMd = true;
-        }
-
-        DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "Associate AID= %d \n", wAssocAID);
-        DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "MAC=%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X \n",
-                   sFrame.pHdr->sA3.abyAddr2[0],
-                   sFrame.pHdr->sA3.abyAddr2[1],
-                   sFrame.pHdr->sA3.abyAddr2[2],
-                   sFrame.pHdr->sA3.abyAddr2[3],
-                   sFrame.pHdr->sA3.abyAddr2[4],
-                   sFrame.pHdr->sA3.abyAddr2[5]
-                  ) ;
-        DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "Max Support rate = %d \n",
-                   pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate);
-    }//else { TODO: received STA under state1 handle }
-    else {
-        return;
-    }
-
-
-    // assoc response reply..
-    pTxPacket = s_MgrMakeAssocResponse
-                (
-                  pDevice,
-                  pMgmt,
-                  pMgmt->wCurrCapInfo,
-                  wAssocStatus,
-                  wAssocAID,
-                  sFrame.pHdr->sA3.abyAddr2,
-                  (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates,
-                  (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates
-                );
-    if (pTxPacket != NULL ){
-
-        if (pDevice->bEnableHostapd) {
-            return;
-        }
-        /* send the frame */
-        Status = csMgmt_xmit(pDevice, pTxPacket);
-        if (Status != CMD_STATUS_PENDING) {
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt:Assoc response tx failed\n");
-        }
-        else {
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt:Assoc response tx sending..\n");
-        }
-
-    }
-
-    return;
-}
+		pMgmt->sNodeDBTable[uNodeIndex].bShortPreamble =
+			WLAN_GET_CAP_INFO_SHORTPREAMBLE(*sFrame.pwCapInfo);
+		pMgmt->sNodeDBTable[uNodeIndex].bShortSlotTime =
+			WLAN_GET_CAP_INFO_SHORTSLOTTIME(*sFrame.pwCapInfo);
+		pMgmt->sNodeDBTable[uNodeIndex].wAID = (unsigned short)uNodeIndex;
+		wAssocStatus = WLAN_MGMT_STATUS_SUCCESS;
+		wAssocAID = (unsigned short)uNodeIndex;
+		// check if ERP support
+		if (pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate > RATE_11M)
+			pMgmt->sNodeDBTable[uNodeIndex].bERPExist = true;
+
+		if (pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate <= RATE_11M) {
+			// B only STA join
+			pDevice->bProtectMode = true;
+			pDevice->bNonERPPresent = true;
+		}
+		if (pMgmt->sNodeDBTable[uNodeIndex].bShortPreamble == false) {
+			pDevice->bBarkerPreambleMd = true;
+		}
+
+		DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "Associate AID= %d \n", wAssocAID);
+		DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "MAC=%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X \n",
+			sFrame.pHdr->sA3.abyAddr2[0],
+			sFrame.pHdr->sA3.abyAddr2[1],
+			sFrame.pHdr->sA3.abyAddr2[2],
+			sFrame.pHdr->sA3.abyAddr2[3],
+			sFrame.pHdr->sA3.abyAddr2[4],
+			sFrame.pHdr->sA3.abyAddr2[5]
+			);
+		DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "Max Support rate = %d \n",
+			pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate);
+	}//else { TODO: received STA under state1 handle }
+	else {
+		return;
+	}
+
+	// assoc response reply..
+	pTxPacket = s_MgrMakeAssocResponse
+		(
+			pDevice,
+			pMgmt,
+			pMgmt->wCurrCapInfo,
+			wAssocStatus,
+			wAssocAID,
+			sFrame.pHdr->sA3.abyAddr2,
+			(PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates,
+			(PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates
+);
+	if (pTxPacket != NULL) {
+		if (pDevice->bEnableHostapd) {
+			return;
+		}
+		/* send the frame */
+		Status = csMgmt_xmit(pDevice, pTxPacket);
+		if (Status != CMD_STATUS_PENDING) {
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt:Assoc response tx failed\n");
+		} else {
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt:Assoc response tx sending..\n");
+		}
 
+	}
+
+	return;
+}
 
 /*+
  *
@@ -838,147 +799,143 @@ s_vMgrRxAssocRequest(
  *
  * Return Value: None.
  *
--*/
+ -*/
 
 static
 void
 s_vMgrRxReAssocRequest(
-    PSDevice pDevice,
-    PSMgmtObject pMgmt,
-    PSRxMgmtPacket pRxPacket,
-    unsigned int uNodeIndex
-    )
+	PSDevice pDevice,
+	PSMgmtObject pMgmt,
+	PSRxMgmtPacket pRxPacket,
+	unsigned int uNodeIndex
+)
 {
-    WLAN_FR_REASSOCREQ    sFrame;
-    CMD_STATUS          Status;
-    PSTxMgmtPacket      pTxPacket;
-    unsigned short wAssocStatus = 0;
-    unsigned short wAssocAID = 0;
-    unsigned int	uRateLen = WLAN_RATES_MAXLEN;
-    unsigned char abyCurrSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1];
-    unsigned char abyCurrExtSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1];
-
-    if (pMgmt->eCurrMode != WMAC_MODE_ESS_AP)
-        return;
-    //  node index not found
-    if (!uNodeIndex)
-        return;
-    //check if node is authenticated
-    //decode the frame
-    memset(&sFrame, 0, sizeof(WLAN_FR_REASSOCREQ));
-    sFrame.len = pRxPacket->cbMPDULen;
-    sFrame.pBuf = (unsigned char *)pRxPacket->p80211Header;
-    vMgrDecodeReassocRequest(&sFrame);
-
-    if (pMgmt->sNodeDBTable[uNodeIndex].eNodeState >= NODE_AUTH) {
-        pMgmt->sNodeDBTable[uNodeIndex].eNodeState = NODE_ASSOC;
-        pMgmt->sNodeDBTable[uNodeIndex].wCapInfo = cpu_to_le16(*sFrame.pwCapInfo);
-        pMgmt->sNodeDBTable[uNodeIndex].wListenInterval = cpu_to_le16(*sFrame.pwListenInterval);
-        pMgmt->sNodeDBTable[uNodeIndex].bPSEnable =
-                WLAN_GET_FC_PWRMGT(sFrame.pHdr->sA3.wFrameCtl) ? true : false;
-        // Todo: check sta basic rate, if ap can't support, set status code
-
-        if (pDevice->eCurrentPHYType == PHY_TYPE_11B) {
-            uRateLen = WLAN_RATES_MAXLEN_11B;
-        }
-
-        abyCurrSuppRates[0] = WLAN_EID_SUPP_RATES;
-        abyCurrSuppRates[1] = RATEuSetIE((PWLAN_IE_SUPP_RATES)sFrame.pSuppRates,
-                                         (PWLAN_IE_SUPP_RATES)abyCurrSuppRates,
-                                         uRateLen);
-        abyCurrExtSuppRates[0] = WLAN_EID_EXTSUPP_RATES;
-        if (pDevice->eCurrentPHYType == PHY_TYPE_11G) {
-            abyCurrExtSuppRates[1] = RATEuSetIE((PWLAN_IE_SUPP_RATES)sFrame.pExtSuppRates,
-                                                (PWLAN_IE_SUPP_RATES)abyCurrExtSuppRates,
-                                                uRateLen);
-        } else {
-            abyCurrExtSuppRates[1] = 0;
-        }
-
-
-        RATEvParseMaxRate((void *)pDevice,
-                          (PWLAN_IE_SUPP_RATES)abyCurrSuppRates,
-                          (PWLAN_IE_SUPP_RATES)abyCurrExtSuppRates,
-                           false, // do not change our basic rate
-                           &(pMgmt->sNodeDBTable[uNodeIndex].wMaxBasicRate),
-                           &(pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate),
-                           &(pMgmt->sNodeDBTable[uNodeIndex].wSuppRate),
-                           &(pMgmt->sNodeDBTable[uNodeIndex].byTopCCKBasicRate),
-                           &(pMgmt->sNodeDBTable[uNodeIndex].byTopOFDMBasicRate)
-                          );
-
-        // set max tx rate
-        pMgmt->sNodeDBTable[uNodeIndex].wTxDataRate =
-                pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate;
+	WLAN_FR_REASSOCREQ    sFrame;
+	CMD_STATUS          Status;
+	PSTxMgmtPacket      pTxPacket;
+	unsigned short wAssocStatus = 0;
+	unsigned short wAssocAID = 0;
+	unsigned int	uRateLen = WLAN_RATES_MAXLEN;
+	unsigned char abyCurrSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1];
+	unsigned char abyCurrExtSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1];
+
+	if (pMgmt->eCurrMode != WMAC_MODE_ESS_AP)
+		return;
+	//  node index not found
+	if (!uNodeIndex)
+		return;
+	//check if node is authenticated
+	//decode the frame
+	memset(&sFrame, 0, sizeof(WLAN_FR_REASSOCREQ));
+	sFrame.len = pRxPacket->cbMPDULen;
+	sFrame.pBuf = (unsigned char *)pRxPacket->p80211Header;
+	vMgrDecodeReassocRequest(&sFrame);
+
+	if (pMgmt->sNodeDBTable[uNodeIndex].eNodeState >= NODE_AUTH) {
+		pMgmt->sNodeDBTable[uNodeIndex].eNodeState = NODE_ASSOC;
+		pMgmt->sNodeDBTable[uNodeIndex].wCapInfo = cpu_to_le16(*sFrame.pwCapInfo);
+		pMgmt->sNodeDBTable[uNodeIndex].wListenInterval = cpu_to_le16(*sFrame.pwListenInterval);
+		pMgmt->sNodeDBTable[uNodeIndex].bPSEnable =
+			WLAN_GET_FC_PWRMGT(sFrame.pHdr->sA3.wFrameCtl) ? true : false;
+		// Todo: check sta basic rate, if ap can't support, set status code
+
+		if (pDevice->eCurrentPHYType == PHY_TYPE_11B) {
+			uRateLen = WLAN_RATES_MAXLEN_11B;
+		}
+
+		abyCurrSuppRates[0] = WLAN_EID_SUPP_RATES;
+		abyCurrSuppRates[1] = RATEuSetIE((PWLAN_IE_SUPP_RATES)sFrame.pSuppRates,
+						 (PWLAN_IE_SUPP_RATES)abyCurrSuppRates,
+						 uRateLen);
+		abyCurrExtSuppRates[0] = WLAN_EID_EXTSUPP_RATES;
+		if (pDevice->eCurrentPHYType == PHY_TYPE_11G) {
+			abyCurrExtSuppRates[1] = RATEuSetIE((PWLAN_IE_SUPP_RATES)sFrame.pExtSuppRates,
+							    (PWLAN_IE_SUPP_RATES)abyCurrExtSuppRates,
+							    uRateLen);
+		} else {
+			abyCurrExtSuppRates[1] = 0;
+		}
+
+		RATEvParseMaxRate((void *)pDevice,
+				  (PWLAN_IE_SUPP_RATES)abyCurrSuppRates,
+				  (PWLAN_IE_SUPP_RATES)abyCurrExtSuppRates,
+				  false, // do not change our basic rate
+				  &(pMgmt->sNodeDBTable[uNodeIndex].wMaxBasicRate),
+				  &(pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate),
+				  &(pMgmt->sNodeDBTable[uNodeIndex].wSuppRate),
+				  &(pMgmt->sNodeDBTable[uNodeIndex].byTopCCKBasicRate),
+				  &(pMgmt->sNodeDBTable[uNodeIndex].byTopOFDMBasicRate)
+);
+
+		// set max tx rate
+		pMgmt->sNodeDBTable[uNodeIndex].wTxDataRate =
+			pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate;
 #ifdef	PLICE_DEBUG
-	printk("RxReAssocRequest:TxDataRate is %d\n",pMgmt->sNodeDBTable[uNodeIndex].wTxDataRate);
+		printk("RxReAssocRequest:TxDataRate is %d\n", pMgmt->sNodeDBTable[uNodeIndex].wTxDataRate);
 #endif
 		// Todo: check sta preamble, if ap can't support, set status code
-        pMgmt->sNodeDBTable[uNodeIndex].bShortPreamble =
-                WLAN_GET_CAP_INFO_SHORTPREAMBLE(*sFrame.pwCapInfo);
-        pMgmt->sNodeDBTable[uNodeIndex].bShortSlotTime =
-                WLAN_GET_CAP_INFO_SHORTSLOTTIME(*sFrame.pwCapInfo);
-        pMgmt->sNodeDBTable[uNodeIndex].wAID = (unsigned short)uNodeIndex;
-        wAssocStatus = WLAN_MGMT_STATUS_SUCCESS;
-        wAssocAID = (unsigned short)uNodeIndex;
-
-        // if suppurt ERP
-        if(pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate > RATE_11M)
-           pMgmt->sNodeDBTable[uNodeIndex].bERPExist = true;
-
-        if (pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate <= RATE_11M) {
-            // B only STA join
-            pDevice->bProtectMode = true;
-            pDevice->bNonERPPresent = true;
-        }
-        if (pMgmt->sNodeDBTable[uNodeIndex].bShortPreamble == false) {
-            pDevice->bBarkerPreambleMd = true;
-        }
-
-        DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "Rx ReAssociate AID= %d \n", wAssocAID);
-        DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "MAC=%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X \n",
-                   sFrame.pHdr->sA3.abyAddr2[0],
-                   sFrame.pHdr->sA3.abyAddr2[1],
-                   sFrame.pHdr->sA3.abyAddr2[2],
-                   sFrame.pHdr->sA3.abyAddr2[3],
-                   sFrame.pHdr->sA3.abyAddr2[4],
-                   sFrame.pHdr->sA3.abyAddr2[5]
-                  ) ;
-        DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "Max Support rate = %d \n",
-                   pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate);
-
-    }
-
-
-    // assoc response reply..
-    pTxPacket = s_MgrMakeReAssocResponse
-                (
-                  pDevice,
-                  pMgmt,
-                  pMgmt->wCurrCapInfo,
-                  wAssocStatus,
-                  wAssocAID,
-                  sFrame.pHdr->sA3.abyAddr2,
-                  (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates,
-                  (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates
-                );
-
-    if (pTxPacket != NULL ){
-        /* send the frame */
-        if (pDevice->bEnableHostapd) {
-            return;
-        }
-        Status = csMgmt_xmit(pDevice, pTxPacket);
-        if (Status != CMD_STATUS_PENDING) {
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt:ReAssoc response tx failed\n");
-        }
-        else {
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt:ReAssoc response tx sending..\n");
-        }
-    }
-    return;
-}
+		pMgmt->sNodeDBTable[uNodeIndex].bShortPreamble =
+			WLAN_GET_CAP_INFO_SHORTPREAMBLE(*sFrame.pwCapInfo);
+		pMgmt->sNodeDBTable[uNodeIndex].bShortSlotTime =
+			WLAN_GET_CAP_INFO_SHORTSLOTTIME(*sFrame.pwCapInfo);
+		pMgmt->sNodeDBTable[uNodeIndex].wAID = (unsigned short)uNodeIndex;
+		wAssocStatus = WLAN_MGMT_STATUS_SUCCESS;
+		wAssocAID = (unsigned short)uNodeIndex;
+
+		// if suppurt ERP
+		if (pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate > RATE_11M)
+			pMgmt->sNodeDBTable[uNodeIndex].bERPExist = true;
+
+		if (pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate <= RATE_11M) {
+			// B only STA join
+			pDevice->bProtectMode = true;
+			pDevice->bNonERPPresent = true;
+		}
+		if (pMgmt->sNodeDBTable[uNodeIndex].bShortPreamble == false) {
+			pDevice->bBarkerPreambleMd = true;
+		}
+
+		DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "Rx ReAssociate AID= %d \n", wAssocAID);
+		DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "MAC=%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X \n",
+			sFrame.pHdr->sA3.abyAddr2[0],
+			sFrame.pHdr->sA3.abyAddr2[1],
+			sFrame.pHdr->sA3.abyAddr2[2],
+			sFrame.pHdr->sA3.abyAddr2[3],
+			sFrame.pHdr->sA3.abyAddr2[4],
+			sFrame.pHdr->sA3.abyAddr2[5]
+			);
+		DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "Max Support rate = %d \n",
+			pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate);
 
+	}
+
+	// assoc response reply..
+	pTxPacket = s_MgrMakeReAssocResponse
+		(
+			pDevice,
+			pMgmt,
+			pMgmt->wCurrCapInfo,
+			wAssocStatus,
+			wAssocAID,
+			sFrame.pHdr->sA3.abyAddr2,
+			(PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates,
+			(PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates
+			);
+
+	if (pTxPacket != NULL) {
+		/* send the frame */
+		if (pDevice->bEnableHostapd) {
+			return;
+		}
+		Status = csMgmt_xmit(pDevice, pTxPacket);
+		if (Status != CMD_STATUS_PENDING) {
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt:ReAssoc response tx failed\n");
+		} else {
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt:ReAssoc response tx sending..\n");
+		}
+	}
+	return;
+}
 
 /*+
  *
@@ -988,158 +945,147 @@ s_vMgrRxReAssocRequest(
  * Return Value:
  *    None.
  *
--*/
+ -*/
 
 static
 void
 s_vMgrRxAssocResponse(
-    PSDevice pDevice,
-    PSMgmtObject pMgmt,
-    PSRxMgmtPacket pRxPacket,
-    bool bReAssocType
-    )
+	PSDevice pDevice,
+	PSMgmtObject pMgmt,
+	PSRxMgmtPacket pRxPacket,
+	bool bReAssocType
+)
 {
-    WLAN_FR_ASSOCRESP   sFrame;
-    PWLAN_IE_SSID   pItemSSID;
-    unsigned char *pbyIEs;
-    viawget_wpa_header *wpahdr;
-
-
-
-    if (pMgmt->eCurrState == WMAC_STATE_ASSOCPENDING ||
-         pMgmt->eCurrState == WMAC_STATE_ASSOC) {
-
-        sFrame.len = pRxPacket->cbMPDULen;
-        sFrame.pBuf = (unsigned char *)pRxPacket->p80211Header;
-        // decode the frame
-        vMgrDecodeAssocResponse(&sFrame);
-        if ((sFrame.pwCapInfo == 0) ||
-            (sFrame.pwStatus == 0) ||
-            (sFrame.pwAid == 0) ||
-            (sFrame.pSuppRates == 0)){
-            DBG_PORT80(0xCC);
-            return;
-        }
-
-        pMgmt->sAssocInfo.AssocInfo.ResponseFixedIEs.Capabilities = *(sFrame.pwCapInfo);
-        pMgmt->sAssocInfo.AssocInfo.ResponseFixedIEs.StatusCode = *(sFrame.pwStatus);
-        pMgmt->sAssocInfo.AssocInfo.ResponseFixedIEs.AssociationId = *(sFrame.pwAid);
-        pMgmt->sAssocInfo.AssocInfo.AvailableResponseFixedIEs |= 0x07;
-
-        pMgmt->sAssocInfo.AssocInfo.ResponseIELength = sFrame.len - 24 - 6;
-        pMgmt->sAssocInfo.AssocInfo.OffsetResponseIEs = pMgmt->sAssocInfo.AssocInfo.OffsetRequestIEs + pMgmt->sAssocInfo.AssocInfo.RequestIELength;
-        pbyIEs = pMgmt->sAssocInfo.abyIEs;
-        pbyIEs += pMgmt->sAssocInfo.AssocInfo.RequestIELength;
-        memcpy(pbyIEs, (sFrame.pBuf + 24 +6), pMgmt->sAssocInfo.AssocInfo.ResponseIELength);
-
-        // save values and set current BSS state
-        if (cpu_to_le16((*(sFrame.pwStatus))) == WLAN_MGMT_STATUS_SUCCESS ){
-            // set AID
-            pMgmt->wCurrAID = cpu_to_le16((*(sFrame.pwAid)));
-            if ( (pMgmt->wCurrAID >> 14) != (BIT0 | BIT1) )
-            {
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "AID from AP, has two msb clear.\n");
-            }
-            DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "Association Successful, AID=%d.\n", pMgmt->wCurrAID & ~(BIT14|BIT15));
-            pMgmt->eCurrState = WMAC_STATE_ASSOC;
-            BSSvUpdateAPNode((void *)pDevice, sFrame.pwCapInfo, sFrame.pSuppRates, sFrame.pExtSuppRates);
-            pItemSSID = (PWLAN_IE_SSID)pMgmt->abyCurrSSID;
-            DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "Link with AP(SSID): %s\n", pItemSSID->abySSID);
-            pDevice->bLinkPass = true;
-            pDevice->uBBVGADiffCount = 0;
-            if ((pDevice->bWPADEVUp) && (pDevice->skb != NULL)) {
-	  if(skb_tailroom(pDevice->skb) <(sizeof(viawget_wpa_header)+pMgmt->sAssocInfo.AssocInfo.ResponseIELength+
-		   	                                                 pMgmt->sAssocInfo.AssocInfo.RequestIELength)) {    //data room not enough
-                     dev_kfree_skb(pDevice->skb);
-		   pDevice->skb = dev_alloc_skb((int)pDevice->rx_buf_sz);
-	       	}
-                wpahdr = (viawget_wpa_header *)pDevice->skb->data;
-                wpahdr->type = VIAWGET_ASSOC_MSG;
-                wpahdr->resp_ie_len = pMgmt->sAssocInfo.AssocInfo.ResponseIELength;
-                wpahdr->req_ie_len = pMgmt->sAssocInfo.AssocInfo.RequestIELength;
-                memcpy(pDevice->skb->data + sizeof(viawget_wpa_header), pMgmt->sAssocInfo.abyIEs, wpahdr->req_ie_len);
-                memcpy(pDevice->skb->data + sizeof(viawget_wpa_header) + wpahdr->req_ie_len,
-                       pbyIEs,
-                       wpahdr->resp_ie_len
-                       );
-                skb_put(pDevice->skb, sizeof(viawget_wpa_header) + wpahdr->resp_ie_len + wpahdr->req_ie_len);
-                pDevice->skb->dev = pDevice->wpadev;
-		skb_reset_mac_header(pDevice->skb);
-                pDevice->skb->pkt_type = PACKET_HOST;
-                pDevice->skb->protocol = htons(ETH_P_802_2);
-                memset(pDevice->skb->cb, 0, sizeof(pDevice->skb->cb));
-                netif_rx(pDevice->skb);
-                pDevice->skb = dev_alloc_skb((int)pDevice->rx_buf_sz);
-            }
-
-//2008-0409-07, <Add> by Einsn Liu
-#ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
-	//if(pDevice->bWPADevEnable == true)
-		{
-		unsigned char buf[512];
-		size_t len;
-		union iwreq_data  wrqu;
-		int we_event;
-
-		memset(buf, 0, 512);
-
-		len = pMgmt->sAssocInfo.AssocInfo.RequestIELength;
-		if(len)	{
-			memcpy(buf, pMgmt->sAssocInfo.abyIEs, len);
-			memset(&wrqu, 0, sizeof (wrqu));
-			wrqu.data.length = len;
-			we_event = IWEVASSOCREQIE;
-			wireless_send_event(pDevice->dev, we_event, &wrqu, buf);
-		}
-
-		memset(buf, 0, 512);
-		len = pMgmt->sAssocInfo.AssocInfo.ResponseIELength;
-
-		if(len)	{
-			memcpy(buf, pbyIEs, len);
-			memset(&wrqu, 0, sizeof (wrqu));
-			wrqu.data.length = len;
-			we_event = IWEVASSOCRESPIE;
-			wireless_send_event(pDevice->dev, we_event, &wrqu, buf);
+	WLAN_FR_ASSOCRESP   sFrame;
+	PWLAN_IE_SSID   pItemSSID;
+	unsigned char *pbyIEs;
+	viawget_wpa_header *wpahdr;
+
+	if (pMgmt->eCurrState == WMAC_STATE_ASSOCPENDING ||
+	    pMgmt->eCurrState == WMAC_STATE_ASSOC) {
+		sFrame.len = pRxPacket->cbMPDULen;
+		sFrame.pBuf = (unsigned char *)pRxPacket->p80211Header;
+		// decode the frame
+		vMgrDecodeAssocResponse(&sFrame);
+		if ((sFrame.pwCapInfo == 0) ||
+		    (sFrame.pwStatus == 0) ||
+		    (sFrame.pwAid == 0) ||
+		    (sFrame.pSuppRates == 0)) {
+			DBG_PORT80(0xCC);
+			return;
 		}
 
+		pMgmt->sAssocInfo.AssocInfo.ResponseFixedIEs.Capabilities = *(sFrame.pwCapInfo);
+		pMgmt->sAssocInfo.AssocInfo.ResponseFixedIEs.StatusCode = *(sFrame.pwStatus);
+		pMgmt->sAssocInfo.AssocInfo.ResponseFixedIEs.AssociationId = *(sFrame.pwAid);
+		pMgmt->sAssocInfo.AssocInfo.AvailableResponseFixedIEs |= 0x07;
+
+		pMgmt->sAssocInfo.AssocInfo.ResponseIELength = sFrame.len - 24 - 6;
+		pMgmt->sAssocInfo.AssocInfo.OffsetResponseIEs = pMgmt->sAssocInfo.AssocInfo.OffsetRequestIEs + pMgmt->sAssocInfo.AssocInfo.RequestIELength;
+		pbyIEs = pMgmt->sAssocInfo.abyIEs;
+		pbyIEs += pMgmt->sAssocInfo.AssocInfo.RequestIELength;
+		memcpy(pbyIEs, (sFrame.pBuf + 24 + 6), pMgmt->sAssocInfo.AssocInfo.ResponseIELength);
+
+		// save values and set current BSS state
+		if (cpu_to_le16((*(sFrame.pwStatus))) == WLAN_MGMT_STATUS_SUCCESS) {
+			// set AID
+			pMgmt->wCurrAID = cpu_to_le16((*(sFrame.pwAid)));
+			if ((pMgmt->wCurrAID >> 14) != (BIT0 | BIT1)) {
+				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "AID from AP, has two msb clear.\n");
+			}
+			DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "Association Successful, AID=%d.\n", pMgmt->wCurrAID & ~(BIT14 | BIT15));
+			pMgmt->eCurrState = WMAC_STATE_ASSOC;
+			BSSvUpdateAPNode((void *)pDevice, sFrame.pwCapInfo, sFrame.pSuppRates, sFrame.pExtSuppRates);
+			pItemSSID = (PWLAN_IE_SSID)pMgmt->abyCurrSSID;
+			DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "Link with AP(SSID): %s\n", pItemSSID->abySSID);
+			pDevice->bLinkPass = true;
+			pDevice->uBBVGADiffCount = 0;
+			if ((pDevice->bWPADEVUp) && (pDevice->skb != NULL)) {
+				if (skb_tailroom(pDevice->skb) < (sizeof(viawget_wpa_header) + pMgmt->sAssocInfo.AssocInfo.ResponseIELength +
+								  pMgmt->sAssocInfo.AssocInfo.RequestIELength)) {    //data room not enough
+					dev_kfree_skb(pDevice->skb);
+					pDevice->skb = dev_alloc_skb((int)pDevice->rx_buf_sz);
+				}
+				wpahdr = (viawget_wpa_header *)pDevice->skb->data;
+				wpahdr->type = VIAWGET_ASSOC_MSG;
+				wpahdr->resp_ie_len = pMgmt->sAssocInfo.AssocInfo.ResponseIELength;
+				wpahdr->req_ie_len = pMgmt->sAssocInfo.AssocInfo.RequestIELength;
+				memcpy(pDevice->skb->data + sizeof(viawget_wpa_header), pMgmt->sAssocInfo.abyIEs, wpahdr->req_ie_len);
+				memcpy(pDevice->skb->data + sizeof(viawget_wpa_header) + wpahdr->req_ie_len,
+				       pbyIEs,
+				       wpahdr->resp_ie_len
+);
+				skb_put(pDevice->skb, sizeof(viawget_wpa_header) + wpahdr->resp_ie_len + wpahdr->req_ie_len);
+				pDevice->skb->dev = pDevice->wpadev;
+				skb_reset_mac_header(pDevice->skb);
+				pDevice->skb->pkt_type = PACKET_HOST;
+				pDevice->skb->protocol = htons(ETH_P_802_2);
+				memset(pDevice->skb->cb, 0, sizeof(pDevice->skb->cb));
+				netif_rx(pDevice->skb);
+				pDevice->skb = dev_alloc_skb((int)pDevice->rx_buf_sz);
+			}
 
-  memset(&wrqu, 0, sizeof (wrqu));
-	memcpy(wrqu.ap_addr.sa_data, &pMgmt->abyCurrBSSID[0], ETH_ALEN);
-        wrqu.ap_addr.sa_family = ARPHRD_ETHER;
-	wireless_send_event(pDevice->dev, SIOCGIWAP, &wrqu, NULL);
-	}
+//2008-0409-07, <Add> by Einsn Liu
+#ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
+			{
+				unsigned char buf[512];
+				size_t len;
+				union iwreq_data  wrqu;
+				int we_event;
+
+				memset(buf, 0, 512);
+
+				len = pMgmt->sAssocInfo.AssocInfo.RequestIELength;
+				if (len)	{
+					memcpy(buf, pMgmt->sAssocInfo.abyIEs, len);
+					memset(&wrqu, 0, sizeof(wrqu));
+					wrqu.data.length = len;
+					we_event = IWEVASSOCREQIE;
+					wireless_send_event(pDevice->dev, we_event, &wrqu, buf);
+				}
+
+				memset(buf, 0, 512);
+				len = pMgmt->sAssocInfo.AssocInfo.ResponseIELength;
+
+				if (len)	{
+					memcpy(buf, pbyIEs, len);
+					memset(&wrqu, 0, sizeof(wrqu));
+					wrqu.data.length = len;
+					we_event = IWEVASSOCRESPIE;
+					wireless_send_event(pDevice->dev, we_event, &wrqu, buf);
+				}
+
+				memset(&wrqu, 0, sizeof(wrqu));
+				memcpy(wrqu.ap_addr.sa_data, &pMgmt->abyCurrBSSID[0], ETH_ALEN);
+				wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+				wireless_send_event(pDevice->dev, SIOCGIWAP, &wrqu, NULL);
+			}
 #endif //#ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
 //End Add -- //2008-0409-07, <Add> by Einsn Liu
+		} else {
+			if (bReAssocType) {
+				pMgmt->eCurrState = WMAC_STATE_IDLE;
+			} else {
+				// jump back to the auth state and indicate the error
+				pMgmt->eCurrState = WMAC_STATE_AUTH;
+			}
+			s_vMgrLogStatus(pMgmt, cpu_to_le16((*(sFrame.pwStatus))));
 		}
-        else {
-            if (bReAssocType) {
-                pMgmt->eCurrState = WMAC_STATE_IDLE;
-            }
-            else {
-                // jump back to the auth state and indicate the error
-                pMgmt->eCurrState = WMAC_STATE_AUTH;
-            }
-            s_vMgrLogStatus(pMgmt,cpu_to_le16((*(sFrame.pwStatus))));
-        }
-
-    }
+
+	}
 
 #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
 //need clear flags related to Networkmanager
 
-              pDevice->bwextcount = 0;
-              pDevice->bWPASuppWextEnabled = false;
+	pDevice->bwextcount = 0;
+	pDevice->bWPASuppWextEnabled = false;
 #endif
 
-
-if(pMgmt->eCurrState == WMAC_STATE_ASSOC)
-      timer_expire(pDevice->sTimerCommand, 0);
-    return;
+	if (pMgmt->eCurrState == WMAC_STATE_ASSOC)
+		timer_expire(pDevice->sTimerCommand, 0);
+	return;
 }
 
-
-
 /*+
  *
  * Routine Description:
@@ -1149,54 +1095,52 @@ if(pMgmt->eCurrState == WMAC_STATE_ASSOC)
  * Return Value:
  *    None.
  *
--*/
+ -*/
 
 void
 vMgrAuthenBeginSta(
-    void *hDeviceContext,
-    PSMgmtObject  pMgmt,
-    PCMD_STATUS pStatus
-    )
+	void *hDeviceContext,
+	PSMgmtObject  pMgmt,
+	PCMD_STATUS pStatus
+)
 {
-    PSDevice     pDevice = (PSDevice)hDeviceContext;
-    WLAN_FR_AUTHEN  sFrame;
-    PSTxMgmtPacket  pTxPacket = NULL;
-
-    pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool;
-    memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_AUTHEN_FR_MAXLEN);
-    pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket));
-    sFrame.pBuf = (unsigned char *)pTxPacket->p80211Header;
-    sFrame.len = WLAN_AUTHEN_FR_MAXLEN;
-    vMgrEncodeAuthen(&sFrame);
-    /* insert values */
-    sFrame.pHdr->sA3.wFrameCtl = cpu_to_le16(
-        (
-        WLAN_SET_FC_FTYPE(WLAN_TYPE_MGR) |
-        WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_AUTHEN)
-        ));
-    memcpy( sFrame.pHdr->sA3.abyAddr1, pMgmt->abyCurrBSSID, WLAN_ADDR_LEN);
-    memcpy( sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN);
-    memcpy( sFrame.pHdr->sA3.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN);
-    if (pMgmt->bShareKeyAlgorithm)
-        *(sFrame.pwAuthAlgorithm) = cpu_to_le16(WLAN_AUTH_ALG_SHAREDKEY);
-    else
-        *(sFrame.pwAuthAlgorithm) = cpu_to_le16(WLAN_AUTH_ALG_OPENSYSTEM);
-
-    *(sFrame.pwAuthSequence) = cpu_to_le16(1);
-    /* Adjust the length fields */
-    pTxPacket->cbMPDULen = sFrame.len;
-    pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN;
-
-    *pStatus = csMgmt_xmit(pDevice, pTxPacket);
-    if (*pStatus == CMD_STATUS_PENDING){
-        pMgmt->eCurrState = WMAC_STATE_AUTHPENDING;
-        *pStatus = CMD_STATUS_SUCCESS;
-    }
-
-    return ;
-}
-
+	PSDevice     pDevice = (PSDevice)hDeviceContext;
+	WLAN_FR_AUTHEN  sFrame;
+	PSTxMgmtPacket  pTxPacket = NULL;
+
+	pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool;
+	memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_AUTHEN_FR_MAXLEN);
+	pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket));
+	sFrame.pBuf = (unsigned char *)pTxPacket->p80211Header;
+	sFrame.len = WLAN_AUTHEN_FR_MAXLEN;
+	vMgrEncodeAuthen(&sFrame);
+	/* insert values */
+	sFrame.pHdr->sA3.wFrameCtl = cpu_to_le16(
+		(
+			WLAN_SET_FC_FTYPE(WLAN_TYPE_MGR) |
+			WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_AUTHEN)
+));
+	memcpy(sFrame.pHdr->sA3.abyAddr1, pMgmt->abyCurrBSSID, WLAN_ADDR_LEN);
+	memcpy(sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN);
+	memcpy(sFrame.pHdr->sA3.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN);
+	if (pMgmt->bShareKeyAlgorithm)
+		*(sFrame.pwAuthAlgorithm) = cpu_to_le16(WLAN_AUTH_ALG_SHAREDKEY);
+	else
+		*(sFrame.pwAuthAlgorithm) = cpu_to_le16(WLAN_AUTH_ALG_OPENSYSTEM);
+
+	*(sFrame.pwAuthSequence) = cpu_to_le16(1);
+	/* Adjust the length fields */
+	pTxPacket->cbMPDULen = sFrame.len;
+	pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN;
+
+	*pStatus = csMgmt_xmit(pDevice, pTxPacket);
+	if (*pStatus == CMD_STATUS_PENDING) {
+		pMgmt->eCurrState = WMAC_STATE_AUTHPENDING;
+		*pStatus = CMD_STATUS_SUCCESS;
+	}
 
+	return;
+}
 
 /*+
  *
@@ -1207,53 +1151,50 @@ vMgrAuthenBeginSta(
  * Return Value:
  *    None.
  *
--*/
+ -*/
 
 void
 vMgrDeAuthenBeginSta(
-    void *hDeviceContext,
-    PSMgmtObject  pMgmt,
-    unsigned char *abyDestAddress,
-    unsigned short wReason,
-    PCMD_STATUS pStatus
-    )
+	void *hDeviceContext,
+	PSMgmtObject  pMgmt,
+	unsigned char *abyDestAddress,
+	unsigned short wReason,
+	PCMD_STATUS pStatus
+)
 {
-    PSDevice            pDevice = (PSDevice)hDeviceContext;
-    WLAN_FR_DEAUTHEN    sFrame;
-    PSTxMgmtPacket      pTxPacket = NULL;
-
-
-    pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool;
-    memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_DEAUTHEN_FR_MAXLEN);
-    pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket));
-    sFrame.pBuf = (unsigned char *)pTxPacket->p80211Header;
-    sFrame.len = WLAN_DEAUTHEN_FR_MAXLEN;
-    vMgrEncodeDeauthen(&sFrame);
-    /* insert values */
-    sFrame.pHdr->sA3.wFrameCtl = cpu_to_le16(
-        (
-        WLAN_SET_FC_FTYPE(WLAN_TYPE_MGR) |
-        WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_DEAUTHEN)
-        ));
-
-    memcpy( sFrame.pHdr->sA3.abyAddr1, abyDestAddress, WLAN_ADDR_LEN);
-    memcpy( sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN);
-    memcpy( sFrame.pHdr->sA3.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN);
-
-    *(sFrame.pwReason) = cpu_to_le16(wReason);       // deauthen. bcs left BSS
-    /* Adjust the length fields */
-    pTxPacket->cbMPDULen = sFrame.len;
-    pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN;
-
-    *pStatus = csMgmt_xmit(pDevice, pTxPacket);
-    if (*pStatus == CMD_STATUS_PENDING){
-        *pStatus = CMD_STATUS_SUCCESS;
-    }
-
-
-    return ;
-}
+	PSDevice            pDevice = (PSDevice)hDeviceContext;
+	WLAN_FR_DEAUTHEN    sFrame;
+	PSTxMgmtPacket      pTxPacket = NULL;
+
+	pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool;
+	memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_DEAUTHEN_FR_MAXLEN);
+	pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket));
+	sFrame.pBuf = (unsigned char *)pTxPacket->p80211Header;
+	sFrame.len = WLAN_DEAUTHEN_FR_MAXLEN;
+	vMgrEncodeDeauthen(&sFrame);
+	/* insert values */
+	sFrame.pHdr->sA3.wFrameCtl = cpu_to_le16(
+		(
+			WLAN_SET_FC_FTYPE(WLAN_TYPE_MGR) |
+			WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_DEAUTHEN)
+));
+
+	memcpy(sFrame.pHdr->sA3.abyAddr1, abyDestAddress, WLAN_ADDR_LEN);
+	memcpy(sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN);
+	memcpy(sFrame.pHdr->sA3.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN);
+
+	*(sFrame.pwReason) = cpu_to_le16(wReason);       // deauthen. bcs left BSS
+	/* Adjust the length fields */
+	pTxPacket->cbMPDULen = sFrame.len;
+	pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN;
+
+	*pStatus = csMgmt_xmit(pDevice, pTxPacket);
+	if (*pStatus == CMD_STATUS_PENDING) {
+		*pStatus = CMD_STATUS_SUCCESS;
+	}
 
+	return;
+}
 
 /*+
  *
@@ -1263,52 +1204,50 @@ vMgrDeAuthenBeginSta(
  * Return Value:
  *    None.
  *
--*/
+ -*/
 
 static
 void
 s_vMgrRxAuthentication(
-    PSDevice pDevice,
-    PSMgmtObject pMgmt,
-    PSRxMgmtPacket pRxPacket
-    )
+	PSDevice pDevice,
+	PSMgmtObject pMgmt,
+	PSRxMgmtPacket pRxPacket
+)
 {
-    WLAN_FR_AUTHEN  sFrame;
-
-    // we better be an AP or a STA in AUTHPENDING otherwise ignore
-    if (!(pMgmt->eCurrMode == WMAC_MODE_ESS_AP ||
-          pMgmt->eCurrState == WMAC_STATE_AUTHPENDING)) {
-        return;
-    }
-
-    // decode the frame
-    sFrame.len = pRxPacket->cbMPDULen;
-    sFrame.pBuf = (unsigned char *)pRxPacket->p80211Header;
-    vMgrDecodeAuthen(&sFrame);
-    switch (cpu_to_le16((*(sFrame.pwAuthSequence )))){
-        case 1:
-            //AP function
-            s_vMgrRxAuthenSequence_1(pDevice,pMgmt, &sFrame);
-            break;
-        case 2:
-            s_vMgrRxAuthenSequence_2(pDevice, pMgmt, &sFrame);
-            break;
-        case 3:
-            //AP function
-            s_vMgrRxAuthenSequence_3(pDevice, pMgmt, &sFrame);
-            break;
-        case 4:
-            s_vMgrRxAuthenSequence_4(pDevice, pMgmt, &sFrame);
-            break;
-        default:
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Auth Sequence error, seq = %d\n",
-                        cpu_to_le16((*(sFrame.pwAuthSequence))));
-            break;
-    }
-    return;
-}
+	WLAN_FR_AUTHEN  sFrame;
 
+	// we better be an AP or a STA in AUTHPENDING otherwise ignore
+	if (!(pMgmt->eCurrMode == WMAC_MODE_ESS_AP ||
+	      pMgmt->eCurrState == WMAC_STATE_AUTHPENDING)) {
+		return;
+	}
 
+	// decode the frame
+	sFrame.len = pRxPacket->cbMPDULen;
+	sFrame.pBuf = (unsigned char *)pRxPacket->p80211Header;
+	vMgrDecodeAuthen(&sFrame);
+	switch (cpu_to_le16((*(sFrame.pwAuthSequence)))) {
+	case 1:
+		//AP function
+		s_vMgrRxAuthenSequence_1(pDevice, pMgmt, &sFrame);
+		break;
+	case 2:
+		s_vMgrRxAuthenSequence_2(pDevice, pMgmt, &sFrame);
+		break;
+	case 3:
+		//AP function
+		s_vMgrRxAuthenSequence_3(pDevice, pMgmt, &sFrame);
+		break;
+	case 4:
+		s_vMgrRxAuthenSequence_4(pDevice, pMgmt, &sFrame);
+		break;
+	default:
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Auth Sequence error, seq = %d\n",
+			cpu_to_le16((*(sFrame.pwAuthSequence))));
+		break;
+	}
+	return;
+}
 
 /*+
  *
@@ -1320,102 +1259,96 @@ s_vMgrRxAuthentication(
  * Return Value:
  *    None.
  *
--*/
-
+ -*/
 
 static
 void
 s_vMgrRxAuthenSequence_1(
-    PSDevice pDevice,
-    PSMgmtObject pMgmt,
-    PWLAN_FR_AUTHEN pFrame
-     )
+	PSDevice pDevice,
+	PSMgmtObject pMgmt,
+	PWLAN_FR_AUTHEN pFrame
+)
 {
-    PSTxMgmtPacket      pTxPacket = NULL;
-    unsigned int	uNodeIndex;
-    WLAN_FR_AUTHEN      sFrame;
-    PSKeyItem           pTransmitKey;
-
-    // Insert a Node entry
-    if (!BSSDBbIsSTAInNodeDB(pMgmt, pFrame->pHdr->sA3.abyAddr2, &uNodeIndex)) {
-        BSSvCreateOneNode((PSDevice)pDevice, &uNodeIndex);
-        memcpy(pMgmt->sNodeDBTable[uNodeIndex].abyMACAddr, pFrame->pHdr->sA3.abyAddr2,
-               WLAN_ADDR_LEN);
-    }
-
-    if (pMgmt->bShareKeyAlgorithm) {
-        pMgmt->sNodeDBTable[uNodeIndex].eNodeState = NODE_KNOWN;
-        pMgmt->sNodeDBTable[uNodeIndex].byAuthSequence = 1;
-    }
-    else {
-        pMgmt->sNodeDBTable[uNodeIndex].eNodeState = NODE_AUTH;
-    }
-
-    // send auth reply
-    pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool;
-    memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_AUTHEN_FR_MAXLEN);
-    pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket));
-    sFrame.pBuf = (unsigned char *)pTxPacket->p80211Header;
-    sFrame.len = WLAN_AUTHEN_FR_MAXLEN;
-    // format buffer structure
-    vMgrEncodeAuthen(&sFrame);
-    // insert values
-    sFrame.pHdr->sA3.wFrameCtl = cpu_to_le16(
-         (
-         WLAN_SET_FC_FTYPE(WLAN_TYPE_MGR) |
-         WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_AUTHEN)|
-         WLAN_SET_FC_ISWEP(0)
-         ));
-    memcpy( sFrame.pHdr->sA3.abyAddr1, pFrame->pHdr->sA3.abyAddr2, WLAN_ADDR_LEN);
-    memcpy( sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN);
-    memcpy( sFrame.pHdr->sA3.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN);
-    *(sFrame.pwAuthAlgorithm) = *(pFrame->pwAuthAlgorithm);
-    *(sFrame.pwAuthSequence) = cpu_to_le16(2);
-
-    if (cpu_to_le16(*(pFrame->pwAuthAlgorithm)) == WLAN_AUTH_ALG_SHAREDKEY) {
-        if (pMgmt->bShareKeyAlgorithm)
-            *(sFrame.pwStatus) = cpu_to_le16(WLAN_MGMT_STATUS_SUCCESS);
-        else
-            *(sFrame.pwStatus) = cpu_to_le16(WLAN_MGMT_STATUS_UNSUPPORTED_AUTHALG);
-    }
-    else {
-        if (pMgmt->bShareKeyAlgorithm)
-            *(sFrame.pwStatus) = cpu_to_le16(WLAN_MGMT_STATUS_UNSUPPORTED_AUTHALG);
-        else
-            *(sFrame.pwStatus) = cpu_to_le16(WLAN_MGMT_STATUS_SUCCESS);
-    }
-
-    if (pMgmt->bShareKeyAlgorithm &&
-        (cpu_to_le16(*(sFrame.pwStatus)) == WLAN_MGMT_STATUS_SUCCESS)) {
-
-        sFrame.pChallenge = (PWLAN_IE_CHALLENGE)(sFrame.pBuf + sFrame.len);
-        sFrame.len += WLAN_CHALLENGE_IE_LEN;
-        sFrame.pChallenge->byElementID = WLAN_EID_CHALLENGE;
-        sFrame.pChallenge->len = WLAN_CHALLENGE_LEN;
-        memset(pMgmt->abyChallenge, 0, WLAN_CHALLENGE_LEN);
-        // get group key
-        if(KeybGetTransmitKey(&(pDevice->sKey), pDevice->abyBroadcastAddr, GROUP_KEY, &pTransmitKey) == true) {
-            rc4_init(&pDevice->SBox, pDevice->abyPRNG, pTransmitKey->uKeyLength+3);
-            rc4_encrypt(&pDevice->SBox, pMgmt->abyChallenge, pMgmt->abyChallenge, WLAN_CHALLENGE_LEN);
-        }
-        memcpy(sFrame.pChallenge->abyChallenge, pMgmt->abyChallenge , WLAN_CHALLENGE_LEN);
-    }
-
-    /* Adjust the length fields */
-    pTxPacket->cbMPDULen = sFrame.len;
-    pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN;
-    // send the frame
-    if (pDevice->bEnableHostapd) {
-        return;
-    }
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt:Authreq_reply sequence_1 tx.. \n");
-    if (csMgmt_xmit(pDevice, pTxPacket) != CMD_STATUS_PENDING) {
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt:Authreq_reply sequence_1 tx failed.\n");
-    }
-    return;
-}
+	PSTxMgmtPacket      pTxPacket = NULL;
+	unsigned int	uNodeIndex;
+	WLAN_FR_AUTHEN      sFrame;
+	PSKeyItem           pTransmitKey;
+
+	// Insert a Node entry
+	if (!BSSDBbIsSTAInNodeDB(pMgmt, pFrame->pHdr->sA3.abyAddr2, &uNodeIndex)) {
+		BSSvCreateOneNode((PSDevice)pDevice, &uNodeIndex);
+		memcpy(pMgmt->sNodeDBTable[uNodeIndex].abyMACAddr, pFrame->pHdr->sA3.abyAddr2,
+		       WLAN_ADDR_LEN);
+	}
+
+	if (pMgmt->bShareKeyAlgorithm) {
+		pMgmt->sNodeDBTable[uNodeIndex].eNodeState = NODE_KNOWN;
+		pMgmt->sNodeDBTable[uNodeIndex].byAuthSequence = 1;
+	} else {
+		pMgmt->sNodeDBTable[uNodeIndex].eNodeState = NODE_AUTH;
+	}
 
+	// send auth reply
+	pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool;
+	memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_AUTHEN_FR_MAXLEN);
+	pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket));
+	sFrame.pBuf = (unsigned char *)pTxPacket->p80211Header;
+	sFrame.len = WLAN_AUTHEN_FR_MAXLEN;
+	// format buffer structure
+	vMgrEncodeAuthen(&sFrame);
+	// insert values
+	sFrame.pHdr->sA3.wFrameCtl = cpu_to_le16(
+		(
+			WLAN_SET_FC_FTYPE(WLAN_TYPE_MGR) |
+			WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_AUTHEN)|
+			WLAN_SET_FC_ISWEP(0)
+));
+	memcpy(sFrame.pHdr->sA3.abyAddr1, pFrame->pHdr->sA3.abyAddr2, WLAN_ADDR_LEN);
+	memcpy(sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN);
+	memcpy(sFrame.pHdr->sA3.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN);
+	*(sFrame.pwAuthAlgorithm) = *(pFrame->pwAuthAlgorithm);
+	*(sFrame.pwAuthSequence) = cpu_to_le16(2);
+
+	if (cpu_to_le16(*(pFrame->pwAuthAlgorithm)) == WLAN_AUTH_ALG_SHAREDKEY) {
+		if (pMgmt->bShareKeyAlgorithm)
+			*(sFrame.pwStatus) = cpu_to_le16(WLAN_MGMT_STATUS_SUCCESS);
+		else
+			*(sFrame.pwStatus) = cpu_to_le16(WLAN_MGMT_STATUS_UNSUPPORTED_AUTHALG);
+	} else {
+		if (pMgmt->bShareKeyAlgorithm)
+			*(sFrame.pwStatus) = cpu_to_le16(WLAN_MGMT_STATUS_UNSUPPORTED_AUTHALG);
+		else
+			*(sFrame.pwStatus) = cpu_to_le16(WLAN_MGMT_STATUS_SUCCESS);
+	}
+
+	if (pMgmt->bShareKeyAlgorithm &&
+	    (cpu_to_le16(*(sFrame.pwStatus)) == WLAN_MGMT_STATUS_SUCCESS)) {
+		sFrame.pChallenge = (PWLAN_IE_CHALLENGE)(sFrame.pBuf + sFrame.len);
+		sFrame.len += WLAN_CHALLENGE_IE_LEN;
+		sFrame.pChallenge->byElementID = WLAN_EID_CHALLENGE;
+		sFrame.pChallenge->len = WLAN_CHALLENGE_LEN;
+		memset(pMgmt->abyChallenge, 0, WLAN_CHALLENGE_LEN);
+		// get group key
+		if (KeybGetTransmitKey(&(pDevice->sKey), pDevice->abyBroadcastAddr, GROUP_KEY, &pTransmitKey) == true) {
+			rc4_init(&pDevice->SBox, pDevice->abyPRNG, pTransmitKey->uKeyLength+3);
+			rc4_encrypt(&pDevice->SBox, pMgmt->abyChallenge, pMgmt->abyChallenge, WLAN_CHALLENGE_LEN);
+		}
+		memcpy(sFrame.pChallenge->abyChallenge, pMgmt->abyChallenge , WLAN_CHALLENGE_LEN);
+	}
 
+	/* Adjust the length fields */
+	pTxPacket->cbMPDULen = sFrame.len;
+	pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN;
+	// send the frame
+	if (pDevice->bEnableHostapd) {
+		return;
+	}
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt:Authreq_reply sequence_1 tx.. \n");
+	if (csMgmt_xmit(pDevice, pTxPacket) != CMD_STATUS_PENDING) {
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt:Authreq_reply sequence_1 tx failed.\n");
+	}
+	return;
+}
 
 /*+
  *
@@ -1427,97 +1360,91 @@ s_vMgrRxAuthenSequence_1(
  * Return Value:
  *    None.
  *
--*/
+ -*/
 
 static
 void
 s_vMgrRxAuthenSequence_2(
-    PSDevice pDevice,
-    PSMgmtObject pMgmt,
-    PWLAN_FR_AUTHEN pFrame
-    )
+	PSDevice pDevice,
+	PSMgmtObject pMgmt,
+	PWLAN_FR_AUTHEN pFrame
+)
 {
-    WLAN_FR_AUTHEN      sFrame;
-    PSTxMgmtPacket      pTxPacket = NULL;
-
-
-    switch (cpu_to_le16((*(pFrame->pwAuthAlgorithm))))
-    {
-        case WLAN_AUTH_ALG_OPENSYSTEM:
-            if ( cpu_to_le16((*(pFrame->pwStatus))) == WLAN_MGMT_STATUS_SUCCESS ){
-                DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "802.11 Authen (OPEN) Successful.\n");
-                pMgmt->eCurrState = WMAC_STATE_AUTH;
-	 timer_expire(pDevice->sTimerCommand, 0);
-            }
-            else {
-                DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "802.11 Authen (OPEN) Failed.\n");
-                s_vMgrLogStatus(pMgmt, cpu_to_le16((*(pFrame->pwStatus))));
-                pMgmt->eCurrState = WMAC_STATE_IDLE;
-            }
-            if (pDevice->eCommandState == WLAN_AUTHENTICATE_WAIT ) {
+	WLAN_FR_AUTHEN      sFrame;
+	PSTxMgmtPacket      pTxPacket = NULL;
+
+	switch (cpu_to_le16((*(pFrame->pwAuthAlgorithm)))) {
+	case WLAN_AUTH_ALG_OPENSYSTEM:
+		if (cpu_to_le16((*(pFrame->pwStatus))) == WLAN_MGMT_STATUS_SUCCESS) {
+			DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "802.11 Authen (OPEN) Successful.\n");
+			pMgmt->eCurrState = WMAC_STATE_AUTH;
+			timer_expire(pDevice->sTimerCommand, 0);
+		} else {
+			DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "802.11 Authen (OPEN) Failed.\n");
+			s_vMgrLogStatus(pMgmt, cpu_to_le16((*(pFrame->pwStatus))));
+			pMgmt->eCurrState = WMAC_STATE_IDLE;
+		}
+		if (pDevice->eCommandState == WLAN_AUTHENTICATE_WAIT) {
 //                spin_unlock_irq(&pDevice->lock);
 //                vCommandTimerWait((void *)pDevice, 0);
 //                spin_lock_irq(&pDevice->lock);
-            }
-
-            break;
-
-        case WLAN_AUTH_ALG_SHAREDKEY:
-
-            if (cpu_to_le16((*(pFrame->pwStatus))) == WLAN_MGMT_STATUS_SUCCESS) {
-                pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool;
-                memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_AUTHEN_FR_MAXLEN);
-                pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket));
-                sFrame.pBuf = (unsigned char *)pTxPacket->p80211Header;
-                sFrame.len = WLAN_AUTHEN_FR_MAXLEN;
-                // format buffer structure
-                vMgrEncodeAuthen(&sFrame);
-                // insert values
-                sFrame.pHdr->sA3.wFrameCtl = cpu_to_le16(
-                     (
-                     WLAN_SET_FC_FTYPE(WLAN_TYPE_MGR) |
-                     WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_AUTHEN)|
-                     WLAN_SET_FC_ISWEP(1)
-                     ));
-                memcpy( sFrame.pHdr->sA3.abyAddr1, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN);
-                memcpy( sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN);
-                memcpy( sFrame.pHdr->sA3.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN);
-                *(sFrame.pwAuthAlgorithm) = *(pFrame->pwAuthAlgorithm);
-                *(sFrame.pwAuthSequence) = cpu_to_le16(3);
-                *(sFrame.pwStatus) = cpu_to_le16(WLAN_MGMT_STATUS_SUCCESS);
-                sFrame.pChallenge = (PWLAN_IE_CHALLENGE)(sFrame.pBuf + sFrame.len);
-                sFrame.len += WLAN_CHALLENGE_IE_LEN;
-                sFrame.pChallenge->byElementID = WLAN_EID_CHALLENGE;
-                sFrame.pChallenge->len = WLAN_CHALLENGE_LEN;
-                memcpy( sFrame.pChallenge->abyChallenge, pFrame->pChallenge->abyChallenge, WLAN_CHALLENGE_LEN);
-                // Adjust the length fields
-                pTxPacket->cbMPDULen = sFrame.len;
-                pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN;
-                // send the frame
-                if (csMgmt_xmit(pDevice, pTxPacket) != CMD_STATUS_PENDING) {
-                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt:Auth_reply sequence_2 tx failed.\n");
-                }
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt:Auth_reply sequence_2 tx ...\n");
-            }
-            else {
-            	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt:rx Auth_reply sequence_2 status error ...\n");
-                if ( pDevice->eCommandState == WLAN_AUTHENTICATE_WAIT ) {
+		}
+
+		break;
+
+	case WLAN_AUTH_ALG_SHAREDKEY:
+
+		if (cpu_to_le16((*(pFrame->pwStatus))) == WLAN_MGMT_STATUS_SUCCESS) {
+			pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool;
+			memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_AUTHEN_FR_MAXLEN);
+			pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket));
+			sFrame.pBuf = (unsigned char *)pTxPacket->p80211Header;
+			sFrame.len = WLAN_AUTHEN_FR_MAXLEN;
+			// format buffer structure
+			vMgrEncodeAuthen(&sFrame);
+			// insert values
+			sFrame.pHdr->sA3.wFrameCtl = cpu_to_le16(
+				(
+					WLAN_SET_FC_FTYPE(WLAN_TYPE_MGR) |
+					WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_AUTHEN)|
+					WLAN_SET_FC_ISWEP(1)
+));
+			memcpy(sFrame.pHdr->sA3.abyAddr1, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN);
+			memcpy(sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN);
+			memcpy(sFrame.pHdr->sA3.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN);
+			*(sFrame.pwAuthAlgorithm) = *(pFrame->pwAuthAlgorithm);
+			*(sFrame.pwAuthSequence) = cpu_to_le16(3);
+			*(sFrame.pwStatus) = cpu_to_le16(WLAN_MGMT_STATUS_SUCCESS);
+			sFrame.pChallenge = (PWLAN_IE_CHALLENGE)(sFrame.pBuf + sFrame.len);
+			sFrame.len += WLAN_CHALLENGE_IE_LEN;
+			sFrame.pChallenge->byElementID = WLAN_EID_CHALLENGE;
+			sFrame.pChallenge->len = WLAN_CHALLENGE_LEN;
+			memcpy(sFrame.pChallenge->abyChallenge, pFrame->pChallenge->abyChallenge, WLAN_CHALLENGE_LEN);
+			// Adjust the length fields
+			pTxPacket->cbMPDULen = sFrame.len;
+			pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN;
+			// send the frame
+			if (csMgmt_xmit(pDevice, pTxPacket) != CMD_STATUS_PENDING) {
+				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt:Auth_reply sequence_2 tx failed.\n");
+			}
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt:Auth_reply sequence_2 tx ...\n");
+		} else {
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt:rx Auth_reply sequence_2 status error ...\n");
+			if (pDevice->eCommandState == WLAN_AUTHENTICATE_WAIT) {
 //                    spin_unlock_irq(&pDevice->lock);
 //                    vCommandTimerWait((void *)pDevice, 0);
 //                    spin_lock_irq(&pDevice->lock);
-                }
-                s_vMgrLogStatus(pMgmt, cpu_to_le16((*(pFrame->pwStatus))));
-            }
-            break;
-        default:
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt: rx auth.seq = 2 unknown AuthAlgorithm=%d\n", cpu_to_le16((*(pFrame->pwAuthAlgorithm))));
-            break;
-    }
-    return;
+			}
+			s_vMgrLogStatus(pMgmt, cpu_to_le16((*(pFrame->pwStatus))));
+		}
+		break;
+	default:
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt: rx auth.seq = 2 unknown AuthAlgorithm=%d\n", cpu_to_le16((*(pFrame->pwAuthAlgorithm))));
+		break;
+	}
+	return;
 }
 
-
-
 /*+
  *
  * Routine Description:
@@ -1529,86 +1456,82 @@ s_vMgrRxAuthenSequence_2(
  * Return Value:
  *    None.
  *
--*/
+ -*/
 
 static
 void
 s_vMgrRxAuthenSequence_3(
-    PSDevice pDevice,
-    PSMgmtObject pMgmt,
-    PWLAN_FR_AUTHEN pFrame
-    )
+	PSDevice pDevice,
+	PSMgmtObject pMgmt,
+	PWLAN_FR_AUTHEN pFrame
+)
 {
-    PSTxMgmtPacket      pTxPacket = NULL;
-    unsigned int uStatusCode = 0 ;
-    unsigned int uNodeIndex = 0;
-    WLAN_FR_AUTHEN      sFrame;
-
-    if (!WLAN_GET_FC_ISWEP(pFrame->pHdr->sA3.wFrameCtl)) {
-        uStatusCode = WLAN_MGMT_STATUS_CHALLENGE_FAIL;
-        goto reply;
-    }
-    if (BSSDBbIsSTAInNodeDB(pMgmt, pFrame->pHdr->sA3.abyAddr2, &uNodeIndex)) {
-         if (pMgmt->sNodeDBTable[uNodeIndex].byAuthSequence != 1) {
-            uStatusCode = WLAN_MGMT_STATUS_RX_AUTH_NOSEQ;
-            goto reply;
-         }
-         if (memcmp(pMgmt->abyChallenge, pFrame->pChallenge->abyChallenge, WLAN_CHALLENGE_LEN) != 0) {
-            uStatusCode = WLAN_MGMT_STATUS_CHALLENGE_FAIL;
-            goto reply;
-         }
-    }
-    else {
-        uStatusCode = WLAN_MGMT_STATUS_UNSPEC_FAILURE;
-        goto reply;
-    }
-
-    if (uNodeIndex) {
-        pMgmt->sNodeDBTable[uNodeIndex].eNodeState = NODE_AUTH;
-        pMgmt->sNodeDBTable[uNodeIndex].byAuthSequence = 0;
-    }
-    uStatusCode = WLAN_MGMT_STATUS_SUCCESS;
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Challenge text check ok..\n");
+	PSTxMgmtPacket      pTxPacket = NULL;
+	unsigned int uStatusCode = 0;
+	unsigned int uNodeIndex = 0;
+	WLAN_FR_AUTHEN      sFrame;
+
+	if (!WLAN_GET_FC_ISWEP(pFrame->pHdr->sA3.wFrameCtl)) {
+		uStatusCode = WLAN_MGMT_STATUS_CHALLENGE_FAIL;
+		goto reply;
+	}
+	if (BSSDBbIsSTAInNodeDB(pMgmt, pFrame->pHdr->sA3.abyAddr2, &uNodeIndex)) {
+		if (pMgmt->sNodeDBTable[uNodeIndex].byAuthSequence != 1) {
+			uStatusCode = WLAN_MGMT_STATUS_RX_AUTH_NOSEQ;
+			goto reply;
+		}
+		if (memcmp(pMgmt->abyChallenge, pFrame->pChallenge->abyChallenge, WLAN_CHALLENGE_LEN) != 0) {
+			uStatusCode = WLAN_MGMT_STATUS_CHALLENGE_FAIL;
+			goto reply;
+		}
+	} else {
+		uStatusCode = WLAN_MGMT_STATUS_UNSPEC_FAILURE;
+		goto reply;
+	}
 
-reply:
-    // send auth reply
-    pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool;
-    memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_AUTHEN_FR_MAXLEN);
-    pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket));
-    sFrame.pBuf = (unsigned char *)pTxPacket->p80211Header;
-    sFrame.len = WLAN_AUTHEN_FR_MAXLEN;
-    // format buffer structure
-    vMgrEncodeAuthen(&sFrame);
-    /* insert values */
-    sFrame.pHdr->sA3.wFrameCtl = cpu_to_le16(
-         (
-         WLAN_SET_FC_FTYPE(WLAN_TYPE_MGR) |
-         WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_AUTHEN)|
-         WLAN_SET_FC_ISWEP(0)
-         ));
-    memcpy( sFrame.pHdr->sA3.abyAddr1, pFrame->pHdr->sA3.abyAddr2, WLAN_ADDR_LEN);
-    memcpy( sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN);
-    memcpy( sFrame.pHdr->sA3.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN);
-    *(sFrame.pwAuthAlgorithm) = *(pFrame->pwAuthAlgorithm);
-    *(sFrame.pwAuthSequence) = cpu_to_le16(4);
-    *(sFrame.pwStatus) = cpu_to_le16(uStatusCode);
-
-    /* Adjust the length fields */
-    pTxPacket->cbMPDULen = sFrame.len;
-    pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN;
-    // send the frame
-    if (pDevice->bEnableHostapd) {
-        return;
-    }
-    if (csMgmt_xmit(pDevice, pTxPacket) != CMD_STATUS_PENDING) {
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt:Authreq_reply sequence_4 tx failed.\n");
-    }
-    return;
+	if (uNodeIndex) {
+		pMgmt->sNodeDBTable[uNodeIndex].eNodeState = NODE_AUTH;
+		pMgmt->sNodeDBTable[uNodeIndex].byAuthSequence = 0;
+	}
+	uStatusCode = WLAN_MGMT_STATUS_SUCCESS;
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Challenge text check ok..\n");
 
+reply:
+	// send auth reply
+	pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool;
+	memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_AUTHEN_FR_MAXLEN);
+	pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket));
+	sFrame.pBuf = (unsigned char *)pTxPacket->p80211Header;
+	sFrame.len = WLAN_AUTHEN_FR_MAXLEN;
+	// format buffer structure
+	vMgrEncodeAuthen(&sFrame);
+	/* insert values */
+	sFrame.pHdr->sA3.wFrameCtl = cpu_to_le16(
+		(
+			WLAN_SET_FC_FTYPE(WLAN_TYPE_MGR) |
+			WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_AUTHEN)|
+			WLAN_SET_FC_ISWEP(0)
+));
+	memcpy(sFrame.pHdr->sA3.abyAddr1, pFrame->pHdr->sA3.abyAddr2, WLAN_ADDR_LEN);
+	memcpy(sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN);
+	memcpy(sFrame.pHdr->sA3.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN);
+	*(sFrame.pwAuthAlgorithm) = *(pFrame->pwAuthAlgorithm);
+	*(sFrame.pwAuthSequence) = cpu_to_le16(4);
+	*(sFrame.pwStatus) = cpu_to_le16(uStatusCode);
+
+	/* Adjust the length fields */
+	pTxPacket->cbMPDULen = sFrame.len;
+	pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN;
+	// send the frame
+	if (pDevice->bEnableHostapd) {
+		return;
+	}
+	if (csMgmt_xmit(pDevice, pTxPacket) != CMD_STATUS_PENDING) {
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt:Authreq_reply sequence_4 tx failed.\n");
+	}
+	return;
 }
 
-
-
 /*+
  *
  * Routine Description:
@@ -1618,33 +1541,30 @@ reply:
  * Return Value:
  *    None.
  *
--*/
+ -*/
 static
 void
 s_vMgrRxAuthenSequence_4(
-    PSDevice pDevice,
-    PSMgmtObject pMgmt,
-    PWLAN_FR_AUTHEN pFrame
-    )
+	PSDevice pDevice,
+	PSMgmtObject pMgmt,
+	PWLAN_FR_AUTHEN pFrame
+)
 {
+	if (cpu_to_le16((*(pFrame->pwStatus))) == WLAN_MGMT_STATUS_SUCCESS) {
+		DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "802.11 Authen (SHAREDKEY) Successful.\n");
+		pMgmt->eCurrState = WMAC_STATE_AUTH;
+		timer_expire(pDevice->sTimerCommand, 0);
+	} else{
+		DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "802.11 Authen (SHAREDKEY) Failed.\n");
+		s_vMgrLogStatus(pMgmt, cpu_to_le16((*(pFrame->pwStatus))));
+		pMgmt->eCurrState = WMAC_STATE_IDLE;
+	}
 
-    if ( cpu_to_le16((*(pFrame->pwStatus))) == WLAN_MGMT_STATUS_SUCCESS ){
-        DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "802.11 Authen (SHAREDKEY) Successful.\n");
-        pMgmt->eCurrState = WMAC_STATE_AUTH;
-	  timer_expire(pDevice->sTimerCommand, 0);
-    }
-    else{
-        DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "802.11 Authen (SHAREDKEY) Failed.\n");
-        s_vMgrLogStatus(pMgmt, cpu_to_le16((*(pFrame->pwStatus))) );
-        pMgmt->eCurrState = WMAC_STATE_IDLE;
-    }
-
-    if ( pDevice->eCommandState == WLAN_AUTHENTICATE_WAIT ) {
+	if (pDevice->eCommandState == WLAN_AUTHENTICATE_WAIT) {
 //        spin_unlock_irq(&pDevice->lock);
 //        vCommandTimerWait((void *)pDevice, 0);
 //        spin_lock_irq(&pDevice->lock);
-    }
-
+	}
 }
 
 /*+
@@ -1656,75 +1576,68 @@ s_vMgrRxAuthenSequence_4(
  * Return Value:
  *    None.
  *
--*/
+ -*/
 
 static
 void
 s_vMgrRxDisassociation(
-    PSDevice pDevice,
-    PSMgmtObject pMgmt,
-    PSRxMgmtPacket pRxPacket
-    )
+	PSDevice pDevice,
+	PSMgmtObject pMgmt,
+	PSRxMgmtPacket pRxPacket
+)
 {
-    WLAN_FR_DISASSOC    sFrame;
-    unsigned int uNodeIndex = 0;
+	WLAN_FR_DISASSOC    sFrame;
+	unsigned int uNodeIndex = 0;
 //    CMD_STATUS          CmdStatus;
-    viawget_wpa_header *wpahdr;
-
-    if ( pMgmt->eCurrMode == WMAC_MODE_ESS_AP ){
-        // if is acting an AP..
-        // a STA is leaving this BSS..
-        sFrame.len = pRxPacket->cbMPDULen;
-        sFrame.pBuf = (unsigned char *)pRxPacket->p80211Header;
-        if (BSSDBbIsSTAInNodeDB(pMgmt, pRxPacket->p80211Header->sA3.abyAddr2, &uNodeIndex)) {
-            BSSvRemoveOneNode(pDevice, uNodeIndex);
-        }
-        else {
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Rx disassoc, sta not found\n");
-        }
-    }
-    else if (pMgmt->eCurrMode == WMAC_MODE_ESS_STA ){
-        sFrame.len = pRxPacket->cbMPDULen;
-        sFrame.pBuf = (unsigned char *)pRxPacket->p80211Header;
-        vMgrDecodeDisassociation(&sFrame);
-        DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "AP disassociated me, reason=%d.\n", cpu_to_le16(*(sFrame.pwReason)));
-        //TODO: do something let upper layer know or
-        //try to send associate packet again because of inactivity timeout
-      //  if (pMgmt->eCurrState == WMAC_STATE_ASSOC) {
-       //     vMgrReAssocBeginSta((PSDevice)pDevice, pMgmt, &CmdStatus);
-      //  }
-        if ((pDevice->bWPADEVUp) && (pDevice->skb != NULL)) {
-             wpahdr = (viawget_wpa_header *)pDevice->skb->data;
-             wpahdr->type = VIAWGET_DISASSOC_MSG;
-             wpahdr->resp_ie_len = 0;
-             wpahdr->req_ie_len = 0;
-             skb_put(pDevice->skb, sizeof(viawget_wpa_header));
-             pDevice->skb->dev = pDevice->wpadev;
-	     skb_reset_mac_header(pDevice->skb);
-
-             pDevice->skb->pkt_type = PACKET_HOST;
-             pDevice->skb->protocol = htons(ETH_P_802_2);
-             memset(pDevice->skb->cb, 0, sizeof(pDevice->skb->cb));
-             netif_rx(pDevice->skb);
-             pDevice->skb = dev_alloc_skb((int)pDevice->rx_buf_sz);
-         }
-
- #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
-  // if(pDevice->bWPASuppWextEnabled == true)
-      {
-	union iwreq_data  wrqu;
-	memset(&wrqu, 0, sizeof (wrqu));
-        wrqu.ap_addr.sa_family = ARPHRD_ETHER;
-	printk("wireless_send_event--->SIOCGIWAP(disassociated)\n");
-	wireless_send_event(pDevice->dev, SIOCGIWAP, &wrqu, NULL);
-     }
-  #endif
-    }
-    /* else, ignore it */
-
-    return;
-}
+	viawget_wpa_header *wpahdr;
+
+	if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) {
+		// if is acting an AP..
+		// a STA is leaving this BSS..
+		sFrame.len = pRxPacket->cbMPDULen;
+		sFrame.pBuf = (unsigned char *)pRxPacket->p80211Header;
+		if (BSSDBbIsSTAInNodeDB(pMgmt, pRxPacket->p80211Header->sA3.abyAddr2, &uNodeIndex)) {
+			BSSvRemoveOneNode(pDevice, uNodeIndex);
+		} else {
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Rx disassoc, sta not found\n");
+		}
+	} else if (pMgmt->eCurrMode == WMAC_MODE_ESS_STA) {
+		sFrame.len = pRxPacket->cbMPDULen;
+		sFrame.pBuf = (unsigned char *)pRxPacket->p80211Header;
+		vMgrDecodeDisassociation(&sFrame);
+		DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "AP disassociated me, reason=%d.\n", cpu_to_le16(*(sFrame.pwReason)));
+		//TODO: do something let upper layer know or
+		//try to send associate packet again because of inactivity timeout
+		if ((pDevice->bWPADEVUp) && (pDevice->skb != NULL)) {
+			wpahdr = (viawget_wpa_header *)pDevice->skb->data;
+			wpahdr->type = VIAWGET_DISASSOC_MSG;
+			wpahdr->resp_ie_len = 0;
+			wpahdr->req_ie_len = 0;
+			skb_put(pDevice->skb, sizeof(viawget_wpa_header));
+			pDevice->skb->dev = pDevice->wpadev;
+			skb_reset_mac_header(pDevice->skb);
+
+			pDevice->skb->pkt_type = PACKET_HOST;
+			pDevice->skb->protocol = htons(ETH_P_802_2);
+			memset(pDevice->skb->cb, 0, sizeof(pDevice->skb->cb));
+			netif_rx(pDevice->skb);
+			pDevice->skb = dev_alloc_skb((int)pDevice->rx_buf_sz);
+		}
 
+#ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
+		{
+			union iwreq_data  wrqu;
+			memset(&wrqu, 0, sizeof(wrqu));
+			wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+			printk("wireless_send_event--->SIOCGIWAP(disassociated)\n");
+			wireless_send_event(pDevice->dev, SIOCGIWAP, &wrqu, NULL);
+		}
+#endif
+	}
+	/* else, ignore it */
+
+	return;
+}
 
 /*+
  *
@@ -1735,84 +1648,79 @@ s_vMgrRxDisassociation(
  * Return Value:
  *    None.
  *
--*/
+ -*/
 
 static
 void
 s_vMgrRxDeauthentication(
-    PSDevice pDevice,
-    PSMgmtObject pMgmt,
-    PSRxMgmtPacket pRxPacket
-    )
+	PSDevice pDevice,
+	PSMgmtObject pMgmt,
+	PSRxMgmtPacket pRxPacket
+)
 {
-    WLAN_FR_DEAUTHEN    sFrame;
-    unsigned int uNodeIndex = 0;
-    viawget_wpa_header *wpahdr;
-
-
-    if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP ){
-        //Todo:
-        // if is acting an AP..
-        // a STA is leaving this BSS..
-        sFrame.len = pRxPacket->cbMPDULen;
-        sFrame.pBuf = (unsigned char *)pRxPacket->p80211Header;
-        if (BSSDBbIsSTAInNodeDB(pMgmt, pRxPacket->p80211Header->sA3.abyAddr2, &uNodeIndex)) {
-            BSSvRemoveOneNode(pDevice, uNodeIndex);
-        }
-        else {
-            DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Rx deauth, sta not found\n");
-        }
-    }
-    else {
-        if (pMgmt->eCurrMode == WMAC_MODE_ESS_STA ) {
-            sFrame.len = pRxPacket->cbMPDULen;
-            sFrame.pBuf = (unsigned char *)pRxPacket->p80211Header;
-            vMgrDecodeDeauthen(&sFrame);
-            DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO  "AP deauthed me, reason=%d.\n", cpu_to_le16((*(sFrame.pwReason))));
-            // TODO: update BSS list for specific BSSID if pre-authentication case
-            if (!compare_ether_addr(sFrame.pHdr->sA3.abyAddr3, pMgmt->abyCurrBSSID)) {
-                if (pMgmt->eCurrState >= WMAC_STATE_AUTHPENDING) {
-                    pMgmt->sNodeDBTable[0].bActive = false;
-                    pMgmt->eCurrMode = WMAC_MODE_STANDBY;
-                    pMgmt->eCurrState = WMAC_STATE_IDLE;
-                    netif_stop_queue(pDevice->dev);
-                    pDevice->bLinkPass = false;
-                }
-            }
-
-            if ((pDevice->bWPADEVUp) && (pDevice->skb != NULL)) {
-                 wpahdr = (viawget_wpa_header *)pDevice->skb->data;
-                 wpahdr->type = VIAWGET_DISASSOC_MSG;
-                 wpahdr->resp_ie_len = 0;
-                 wpahdr->req_ie_len = 0;
-                 skb_put(pDevice->skb, sizeof(viawget_wpa_header));
-                 pDevice->skb->dev = pDevice->wpadev;
-		 skb_reset_mac_header(pDevice->skb);
-                 pDevice->skb->pkt_type = PACKET_HOST;
-                 pDevice->skb->protocol = htons(ETH_P_802_2);
-                 memset(pDevice->skb->cb, 0, sizeof(pDevice->skb->cb));
-                 netif_rx(pDevice->skb);
-                 pDevice->skb = dev_alloc_skb((int)pDevice->rx_buf_sz);
-           }
-
-   #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
-  // if(pDevice->bWPASuppWextEnabled == true)
-      {
-	union iwreq_data  wrqu;
-	memset(&wrqu, 0, sizeof (wrqu));
-        wrqu.ap_addr.sa_family = ARPHRD_ETHER;
-	PRINT_K("wireless_send_event--->SIOCGIWAP(disauthen)\n");
-	wireless_send_event(pDevice->dev, SIOCGIWAP, &wrqu, NULL);
-     }
-  #endif
-
-        }
-        /* else, ignore it.  TODO: IBSS authentication service
-            would be implemented here */
-    };
-    return;
-}
+	WLAN_FR_DEAUTHEN    sFrame;
+	unsigned int uNodeIndex = 0;
+	viawget_wpa_header *wpahdr;
+
+	if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) {
+		//Todo:
+		// if is acting an AP..
+		// a STA is leaving this BSS..
+		sFrame.len = pRxPacket->cbMPDULen;
+		sFrame.pBuf = (unsigned char *)pRxPacket->p80211Header;
+		if (BSSDBbIsSTAInNodeDB(pMgmt, pRxPacket->p80211Header->sA3.abyAddr2, &uNodeIndex)) {
+			BSSvRemoveOneNode(pDevice, uNodeIndex);
+		} else {
+			DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Rx deauth, sta not found\n");
+		}
+	} else {
+		if (pMgmt->eCurrMode == WMAC_MODE_ESS_STA) {
+			sFrame.len = pRxPacket->cbMPDULen;
+			sFrame.pBuf = (unsigned char *)pRxPacket->p80211Header;
+			vMgrDecodeDeauthen(&sFrame);
+			DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO  "AP deauthed me, reason=%d.\n", cpu_to_le16((*(sFrame.pwReason))));
+			// TODO: update BSS list for specific BSSID if pre-authentication case
+			if (!compare_ether_addr(sFrame.pHdr->sA3.abyAddr3, pMgmt->abyCurrBSSID)) {
+				if (pMgmt->eCurrState >= WMAC_STATE_AUTHPENDING) {
+					pMgmt->sNodeDBTable[0].bActive = false;
+					pMgmt->eCurrMode = WMAC_MODE_STANDBY;
+					pMgmt->eCurrState = WMAC_STATE_IDLE;
+					netif_stop_queue(pDevice->dev);
+					pDevice->bLinkPass = false;
+				}
+			}
+
+			if ((pDevice->bWPADEVUp) && (pDevice->skb != NULL)) {
+				wpahdr = (viawget_wpa_header *)pDevice->skb->data;
+				wpahdr->type = VIAWGET_DISASSOC_MSG;
+				wpahdr->resp_ie_len = 0;
+				wpahdr->req_ie_len = 0;
+				skb_put(pDevice->skb, sizeof(viawget_wpa_header));
+				pDevice->skb->dev = pDevice->wpadev;
+				skb_reset_mac_header(pDevice->skb);
+				pDevice->skb->pkt_type = PACKET_HOST;
+				pDevice->skb->protocol = htons(ETH_P_802_2);
+				memset(pDevice->skb->cb, 0, sizeof(pDevice->skb->cb));
+				netif_rx(pDevice->skb);
+				pDevice->skb = dev_alloc_skb((int)pDevice->rx_buf_sz);
+			}
 
+#ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
+			{
+				union iwreq_data  wrqu;
+				memset(&wrqu, 0, sizeof(wrqu));
+				wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+				PRINT_K("wireless_send_event--->SIOCGIWAP(disauthen)\n");
+				wireless_send_event(pDevice->dev, SIOCGIWAP, &wrqu, NULL);
+			}
+#endif
+
+		}
+		/* else, ignore it.  TODO: IBSS authentication service
+		   would be implemented here */
+	};
+	return;
+}
 
 //2008-8-4 <add> by chester
 /*+
@@ -1825,33 +1733,32 @@ s_vMgrRxDeauthentication(
  * Return Value:
  *               True:exceed;
  *                False:normal case
--*/
+ -*/
 static bool
 ChannelExceedZoneType(
-    PSDevice pDevice,
-    unsigned char byCurrChannel
-    )
+	PSDevice pDevice,
+	unsigned char byCurrChannel
+)
 {
-  bool exceed=false;
+	bool exceed = false;
 
-  switch(pDevice->byZoneType) {
-  	case 0x00:                  //USA:1~11
-                     if((byCurrChannel<1) ||(byCurrChannel>11))
-	                exceed = true;
-	         break;
+	switch (pDevice->byZoneType) {
+	case 0x00:                  //USA:1~11
+		if ((byCurrChannel < 1) || (byCurrChannel > 11))
+			exceed = true;
+		break;
 	case 0x01:                  //Japan:1~13
 	case 0x02:                  //Europe:1~13
-                     if((byCurrChannel<1) ||(byCurrChannel>13))
-	                exceed = true;
-	         break;
+		if ((byCurrChannel < 1) || (byCurrChannel > 13))
+			exceed = true;
+		break;
 	default:                    //reserve for other zonetype
 		break;
-  }
+	}
 
-  return exceed;
+	return exceed;
 }
 
-
 /*+
  *
  * Routine Description:
@@ -1861,517 +1768,487 @@ ChannelExceedZoneType(
  * Return Value:
  *    None.
  *
--*/
+ -*/
 
 static
 void
 s_vMgrRxBeacon(
-    PSDevice pDevice,
-    PSMgmtObject pMgmt,
-    PSRxMgmtPacket pRxPacket,
-    bool bInScan
-    )
+	PSDevice pDevice,
+	PSMgmtObject pMgmt,
+	PSRxMgmtPacket pRxPacket,
+	bool bInScan
+)
 {
+	PKnownBSS           pBSSList;
+	WLAN_FR_BEACON      sFrame;
+	QWORD               qwTSFOffset;
+	bool bIsBSSIDEqual = false;
+	bool bIsSSIDEqual = false;
+	bool bTSFLargeDiff = false;
+	bool bTSFOffsetPostive = false;
+	bool bUpdateTSF = false;
+	bool bIsAPBeacon = false;
+	bool bIsChannelEqual = false;
+	unsigned int uLocateByteIndex;
+	unsigned char byTIMBitOn = 0;
+	unsigned short wAIDNumber = 0;
+	unsigned int uNodeIndex;
+	QWORD               qwTimestamp, qwLocalTSF;
+	QWORD               qwCurrTSF;
+	unsigned short wStartIndex = 0;
+	unsigned short wAIDIndex = 0;
+	unsigned char byCurrChannel = pRxPacket->byRxChannel;
+	ERPObject           sERP;
+	unsigned int uRateLen = WLAN_RATES_MAXLEN;
+	bool bChannelHit = false;
+	bool bUpdatePhyParameter = false;
+	unsigned char byIEChannel = 0;
+
+	memset(&sFrame, 0, sizeof(WLAN_FR_BEACON));
+	sFrame.len = pRxPacket->cbMPDULen;
+	sFrame.pBuf = (unsigned char *)pRxPacket->p80211Header;
+
+	// decode the beacon frame
+	vMgrDecodeBeacon(&sFrame);
+
+	if ((sFrame.pwBeaconInterval == 0) ||
+	    (sFrame.pwCapInfo == 0) ||
+	    (sFrame.pSSID == 0) ||
+	    (sFrame.pSuppRates == 0)) {
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Rx beacon frame error\n");
+		return;
+	}
 
-    PKnownBSS           pBSSList;
-    WLAN_FR_BEACON      sFrame;
-    QWORD               qwTSFOffset;
-    bool bIsBSSIDEqual = false;
-    bool bIsSSIDEqual = false;
-    bool bTSFLargeDiff = false;
-    bool bTSFOffsetPostive = false;
-    bool bUpdateTSF = false;
-    bool bIsAPBeacon = false;
-    bool bIsChannelEqual = false;
-    unsigned int uLocateByteIndex;
-    unsigned char byTIMBitOn = 0;
-    unsigned short wAIDNumber = 0;
-    unsigned int uNodeIndex;
-    QWORD               qwTimestamp, qwLocalTSF;
-    QWORD               qwCurrTSF;
-    unsigned short wStartIndex = 0;
-    unsigned short wAIDIndex = 0;
-    unsigned char byCurrChannel = pRxPacket->byRxChannel;
-    ERPObject           sERP;
-    unsigned int uRateLen = WLAN_RATES_MAXLEN;
-    bool bChannelHit = false;
-    bool bUpdatePhyParameter = false;
-    unsigned char byIEChannel = 0;
-
-
-    memset(&sFrame, 0, sizeof(WLAN_FR_BEACON));
-    sFrame.len = pRxPacket->cbMPDULen;
-    sFrame.pBuf = (unsigned char *)pRxPacket->p80211Header;
-
-    // decode the beacon frame
-    vMgrDecodeBeacon(&sFrame);
-
-    if ((sFrame.pwBeaconInterval == 0) ||
-        (sFrame.pwCapInfo == 0) ||
-        (sFrame.pSSID == 0) ||
-        (sFrame.pSuppRates == 0) ) {
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Rx beacon frame error\n");
-        return;
-    }
-
-
-    if (sFrame.pDSParms != NULL) {
-        if (byCurrChannel > CB_MAX_CHANNEL_24G) {
-            // channel remapping to
-            byIEChannel = get_channel_mapping(pDevice, sFrame.pDSParms->byCurrChannel, PHY_TYPE_11A);
-        } else {
-            byIEChannel = sFrame.pDSParms->byCurrChannel;
-        }
-        if (byCurrChannel != byIEChannel) {
-            // adjust channel info. bcs we rcv adjacent channel packets
-            bChannelHit = false;
-            byCurrChannel = byIEChannel;
-        }
-    } else {
-        // no DS channel info
-        bChannelHit = true;
-    }
+	if (sFrame.pDSParms != NULL) {
+		if (byCurrChannel > CB_MAX_CHANNEL_24G) {
+			// channel remapping to
+			byIEChannel = get_channel_mapping(pDevice, sFrame.pDSParms->byCurrChannel, PHY_TYPE_11A);
+		} else {
+			byIEChannel = sFrame.pDSParms->byCurrChannel;
+		}
+		if (byCurrChannel != byIEChannel) {
+			// adjust channel info. bcs we rcv adjacent channel packets
+			bChannelHit = false;
+			byCurrChannel = byIEChannel;
+		}
+	} else {
+		// no DS channel info
+		bChannelHit = true;
+	}
 //2008-0730-01<Add>by MikeLiu
-if(ChannelExceedZoneType(pDevice,byCurrChannel)==true)
-      return;
-
-    if (sFrame.pERP != NULL) {
-        sERP.byERP = sFrame.pERP->byContext;
-        sERP.bERPExist = true;
-
-    } else {
-        sERP.bERPExist = false;
-        sERP.byERP = 0;
-    }
-
-    pBSSList = BSSpAddrIsInBSSList((void *)pDevice, sFrame.pHdr->sA3.abyAddr3, sFrame.pSSID);
-    if (pBSSList == NULL) {
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Beacon/insert: RxChannel = : %d\n", byCurrChannel);
-        BSSbInsertToBSSList((void *)pDevice,
-                            sFrame.pHdr->sA3.abyAddr3,
-                            *sFrame.pqwTimestamp,
-                            *sFrame.pwBeaconInterval,
-                            *sFrame.pwCapInfo,
-                            byCurrChannel,
-                            sFrame.pSSID,
-                            sFrame.pSuppRates,
-                            sFrame.pExtSuppRates,
-                            &sERP,
-                            sFrame.pRSN,
-                            sFrame.pRSNWPA,
-                            sFrame.pIE_Country,
-                            sFrame.pIE_Quiet,
-                            sFrame.len - WLAN_HDR_ADDR3_LEN,
-                            sFrame.pHdr->sA4.abyAddr4,   // payload of beacon
-                            (void *)pRxPacket
-                           );
-    }
-    else {
-//        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"update bcn: RxChannel = : %d\n", byCurrChannel);
-        BSSbUpdateToBSSList((void *)pDevice,
-                            *sFrame.pqwTimestamp,
-                            *sFrame.pwBeaconInterval,
-                            *sFrame.pwCapInfo,
-                            byCurrChannel,
-                            bChannelHit,
-                            sFrame.pSSID,
-                            sFrame.pSuppRates,
-                            sFrame.pExtSuppRates,
-                            &sERP,
-                            sFrame.pRSN,
-                            sFrame.pRSNWPA,
-                            sFrame.pIE_Country,
-                            sFrame.pIE_Quiet,
-                            pBSSList,
-                            sFrame.len - WLAN_HDR_ADDR3_LEN,
-                            sFrame.pHdr->sA4.abyAddr4,   // payload of probresponse
-                            (void *)pRxPacket
-                           );
-
-    }
-
-    if (bInScan) {
-        return;
-    }
-
-    if(byCurrChannel == (unsigned char)pMgmt->uCurrChannel)
-       bIsChannelEqual = true;
-
-    if (bIsChannelEqual && (pMgmt->eCurrMode == WMAC_MODE_ESS_AP)) {
-
-        // if rx beacon without ERP field
-        if (sERP.bERPExist) {
-            if (WLAN_GET_ERP_USE_PROTECTION(sERP.byERP)){
-                pDevice->byERPFlag |= WLAN_SET_ERP_USE_PROTECTION(1);
-                pDevice->wUseProtectCntDown = USE_PROTECT_PERIOD;
-            }
-        }
-        else {
-            pDevice->byERPFlag |= WLAN_SET_ERP_USE_PROTECTION(1);
-            pDevice->wUseProtectCntDown = USE_PROTECT_PERIOD;
-        }
-
-        if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) {
-            if(!WLAN_GET_CAP_INFO_SHORTPREAMBLE(*sFrame.pwCapInfo))
-                pDevice->byERPFlag |= WLAN_SET_ERP_BARKER_MODE(1);
-            if(!sERP.bERPExist)
-                pDevice->byERPFlag |= WLAN_SET_ERP_NONERP_PRESENT(1);
-        }
-
-        // set to MAC&BBP
-        if (WLAN_GET_ERP_USE_PROTECTION(pDevice->byERPFlag)){
-            if (!pDevice->bProtectMode) {
-                 MACvEnableProtectMD(pDevice->PortOffset);
-                 pDevice->bProtectMode = true;
-            }
-        }
-    }
-
-
-    if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP)
-        return;
-
-    // check if BSSID the same
-    if (memcmp(sFrame.pHdr->sA3.abyAddr3,
-               pMgmt->abyCurrBSSID,
-               WLAN_BSSID_LEN) == 0) {
-
-        bIsBSSIDEqual = true;
+	if (ChannelExceedZoneType(pDevice, byCurrChannel) == true)
+		return;
+
+	if (sFrame.pERP != NULL) {
+		sERP.byERP = sFrame.pERP->byContext;
+		sERP.bERPExist = true;
+
+	} else {
+		sERP.bERPExist = false;
+		sERP.byERP = 0;
+	}
+
+	pBSSList = BSSpAddrIsInBSSList((void *)pDevice, sFrame.pHdr->sA3.abyAddr3, sFrame.pSSID);
+	if (pBSSList == NULL) {
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Beacon/insert: RxChannel = : %d\n", byCurrChannel);
+		BSSbInsertToBSSList((void *)pDevice,
+				    sFrame.pHdr->sA3.abyAddr3,
+				    *sFrame.pqwTimestamp,
+				    *sFrame.pwBeaconInterval,
+				    *sFrame.pwCapInfo,
+				    byCurrChannel,
+				    sFrame.pSSID,
+				    sFrame.pSuppRates,
+				    sFrame.pExtSuppRates,
+				    &sERP,
+				    sFrame.pRSN,
+				    sFrame.pRSNWPA,
+				    sFrame.pIE_Country,
+				    sFrame.pIE_Quiet,
+				    sFrame.len - WLAN_HDR_ADDR3_LEN,
+				    sFrame.pHdr->sA4.abyAddr4,   // payload of beacon
+				    (void *)pRxPacket
+);
+	} else {
+//        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "update bcn: RxChannel = : %d\n", byCurrChannel);
+		BSSbUpdateToBSSList((void *)pDevice,
+				    *sFrame.pqwTimestamp,
+				    *sFrame.pwBeaconInterval,
+				    *sFrame.pwCapInfo,
+				    byCurrChannel,
+				    bChannelHit,
+				    sFrame.pSSID,
+				    sFrame.pSuppRates,
+				    sFrame.pExtSuppRates,
+				    &sERP,
+				    sFrame.pRSN,
+				    sFrame.pRSNWPA,
+				    sFrame.pIE_Country,
+				    sFrame.pIE_Quiet,
+				    pBSSList,
+				    sFrame.len - WLAN_HDR_ADDR3_LEN,
+				    sFrame.pHdr->sA4.abyAddr4,   // payload of probresponse
+				    (void *)pRxPacket
+);
+
+	}
+
+	if (bInScan) {
+		return;
+	}
+
+	if (byCurrChannel == (unsigned char)pMgmt->uCurrChannel)
+		bIsChannelEqual = true;
+
+	if (bIsChannelEqual && (pMgmt->eCurrMode == WMAC_MODE_ESS_AP)) {
+		// if rx beacon without ERP field
+		if (sERP.bERPExist) {
+			if (WLAN_GET_ERP_USE_PROTECTION(sERP.byERP)) {
+				pDevice->byERPFlag |= WLAN_SET_ERP_USE_PROTECTION(1);
+				pDevice->wUseProtectCntDown = USE_PROTECT_PERIOD;
+			}
+		} else {
+			pDevice->byERPFlag |= WLAN_SET_ERP_USE_PROTECTION(1);
+			pDevice->wUseProtectCntDown = USE_PROTECT_PERIOD;
+		}
+
+		if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) {
+			if (!WLAN_GET_CAP_INFO_SHORTPREAMBLE(*sFrame.pwCapInfo))
+				pDevice->byERPFlag |= WLAN_SET_ERP_BARKER_MODE(1);
+			if (!sERP.bERPExist)
+				pDevice->byERPFlag |= WLAN_SET_ERP_NONERP_PRESENT(1);
+		}
+
+		// set to MAC&BBP
+		if (WLAN_GET_ERP_USE_PROTECTION(pDevice->byERPFlag)) {
+			if (!pDevice->bProtectMode) {
+				MACvEnableProtectMD(pDevice->PortOffset);
+				pDevice->bProtectMode = true;
+			}
+		}
+	}
+
+	if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP)
+		return;
+
+	// check if BSSID the same
+	if (memcmp(sFrame.pHdr->sA3.abyAddr3,
+		   pMgmt->abyCurrBSSID,
+		   WLAN_BSSID_LEN) == 0) {
+		bIsBSSIDEqual = true;
 
 // 2008-05-21 <add> by Richardtai
-        pDevice->uCurrRSSI = pRxPacket->uRSSI;
-        pDevice->byCurrSQ = pRxPacket->bySQ;
-
-        if (pMgmt->sNodeDBTable[0].uInActiveCount != 0) {
-            pMgmt->sNodeDBTable[0].uInActiveCount = 0;
-            //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"BCN:Wake Count= [%d]\n", pMgmt->wCountToWakeUp);
-        }
-    }
-    // check if SSID the same
-    if (sFrame.pSSID->len == ((PWLAN_IE_SSID)pMgmt->abyCurrSSID)->len) {
-        if (memcmp(sFrame.pSSID->abySSID,
-                   ((PWLAN_IE_SSID)pMgmt->abyCurrSSID)->abySSID,
-                   sFrame.pSSID->len
-                   ) == 0) {
-            bIsSSIDEqual = true;
-        }
-    }
-
-    if ((WLAN_GET_CAP_INFO_ESS(*sFrame.pwCapInfo)== true) &&
-        (bIsBSSIDEqual == true) &&
-        (bIsSSIDEqual == true) &&
-        (pMgmt->eCurrMode == WMAC_MODE_ESS_STA) &&
-        (pMgmt->eCurrState == WMAC_STATE_ASSOC)) {
-        // add state check to prevent reconnect fail since we'll receive Beacon
-
-        bIsAPBeacon = true;
-
-        if (pBSSList != NULL) {
-
-            // Compare PHY parameter setting
-            if (pMgmt->wCurrCapInfo != pBSSList->wCapInfo) {
-                bUpdatePhyParameter = true;
-                pMgmt->wCurrCapInfo = pBSSList->wCapInfo;
-            }
-            if (sFrame.pERP != NULL) {
-                if ((sFrame.pERP->byElementID == WLAN_EID_ERP) &&
-                    (pMgmt->byERPContext != sFrame.pERP->byContext)) {
-                    bUpdatePhyParameter = true;
-                    pMgmt->byERPContext = sFrame.pERP->byContext;
-                }
-            }
-            //
-            // Basic Rate Set may change dynamically
-            //
-            if (pBSSList->eNetworkTypeInUse == PHY_TYPE_11B) {
-                uRateLen = WLAN_RATES_MAXLEN_11B;
-            }
-            pMgmt->abyCurrSuppRates[1] = RATEuSetIE((PWLAN_IE_SUPP_RATES)pBSSList->abySuppRates,
-                                                    (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates,
-                                                    uRateLen);
-            pMgmt->abyCurrExtSuppRates[1] = RATEuSetIE((PWLAN_IE_SUPP_RATES)pBSSList->abyExtSuppRates,
-                                                    (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates,
-                                                    uRateLen);
-            RATEvParseMaxRate( (void *)pDevice,
-                               (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates,
-                               (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates,
-                               true,
-                               &(pMgmt->sNodeDBTable[0].wMaxBasicRate),
-                               &(pMgmt->sNodeDBTable[0].wMaxSuppRate),
-                               &(pMgmt->sNodeDBTable[0].wSuppRate),
-                               &(pMgmt->sNodeDBTable[0].byTopCCKBasicRate),
-                               &(pMgmt->sNodeDBTable[0].byTopOFDMBasicRate)
-                              );
-#ifdef	PLICE_DEBUG
-		//printk("RxBeacon:MaxSuppRate is %d\n",pMgmt->sNodeDBTable[0].wMaxSuppRate);
-#endif
+		pDevice->uCurrRSSI = pRxPacket->uRSSI;
+		pDevice->byCurrSQ = pRxPacket->bySQ;
+
+		if (pMgmt->sNodeDBTable[0].uInActiveCount != 0) {
+			pMgmt->sNodeDBTable[0].uInActiveCount = 0;
+			//DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "BCN:Wake Count= [%d]\n", pMgmt->wCountToWakeUp);
+		}
+	}
+	// check if SSID the same
+	if (sFrame.pSSID->len == ((PWLAN_IE_SSID)pMgmt->abyCurrSSID)->len) {
+		if (memcmp(sFrame.pSSID->abySSID,
+			   ((PWLAN_IE_SSID)pMgmt->abyCurrSSID)->abySSID,
+			   sFrame.pSSID->len
+) == 0) {
+			bIsSSIDEqual = true;
+		}
+	}
+
+	if ((WLAN_GET_CAP_INFO_ESS(*sFrame.pwCapInfo) == true) &&
+	    (bIsBSSIDEqual == true) &&
+	    (bIsSSIDEqual == true) &&
+	    (pMgmt->eCurrMode == WMAC_MODE_ESS_STA) &&
+	    (pMgmt->eCurrState == WMAC_STATE_ASSOC)) {
+		// add state check to prevent reconnect fail since we'll receive Beacon
+
+		bIsAPBeacon = true;
+
+		if (pBSSList != NULL) {
+			// Compare PHY parameter setting
+			if (pMgmt->wCurrCapInfo != pBSSList->wCapInfo) {
+				bUpdatePhyParameter = true;
+				pMgmt->wCurrCapInfo = pBSSList->wCapInfo;
+			}
+			if (sFrame.pERP != NULL) {
+				if ((sFrame.pERP->byElementID == WLAN_EID_ERP) &&
+				    (pMgmt->byERPContext != sFrame.pERP->byContext)) {
+					bUpdatePhyParameter = true;
+					pMgmt->byERPContext = sFrame.pERP->byContext;
+				}
+			}
+			//
+			// Basic Rate Set may change dynamically
+			//
+			if (pBSSList->eNetworkTypeInUse == PHY_TYPE_11B) {
+				uRateLen = WLAN_RATES_MAXLEN_11B;
+			}
+			pMgmt->abyCurrSuppRates[1] = RATEuSetIE((PWLAN_IE_SUPP_RATES)pBSSList->abySuppRates,
+								(PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates,
+								uRateLen);
+			pMgmt->abyCurrExtSuppRates[1] = RATEuSetIE((PWLAN_IE_SUPP_RATES)pBSSList->abyExtSuppRates,
+								   (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates,
+								   uRateLen);
+			RATEvParseMaxRate((void *)pDevice,
+					  (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates,
+					  (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates,
+					  true,
+					  &(pMgmt->sNodeDBTable[0].wMaxBasicRate),
+					  &(pMgmt->sNodeDBTable[0].wMaxSuppRate),
+					  &(pMgmt->sNodeDBTable[0].wSuppRate),
+					  &(pMgmt->sNodeDBTable[0].byTopCCKBasicRate),
+					  &(pMgmt->sNodeDBTable[0].byTopOFDMBasicRate)
+				);
 			if (bUpdatePhyParameter == true) {
-                CARDbSetPhyParameter( pMgmt->pAdapter,
-                                      pMgmt->eCurrentPHYMode,
-                                      pMgmt->wCurrCapInfo,
-                                      pMgmt->byERPContext,
-                                      pMgmt->abyCurrSuppRates,
-                                      pMgmt->abyCurrExtSuppRates
-                                      );
-            }
-            if (sFrame.pIE_PowerConstraint != NULL) {
-                CARDvSetPowerConstraint(pMgmt->pAdapter,
-                                        (unsigned char) pBSSList->uChannel,
-                                        sFrame.pIE_PowerConstraint->byPower
-                                        );
-            }
-            if (sFrame.pIE_CHSW != NULL) {
-                CARDbChannelSwitch( pMgmt->pAdapter,
-                                    sFrame.pIE_CHSW->byMode,
-                                    get_channel_mapping(pMgmt->pAdapter, sFrame.pIE_CHSW->byMode, pMgmt->eCurrentPHYMode),
-                                    sFrame.pIE_CHSW->byCount
-                                    );
-
-            } else if (bIsChannelEqual == false) {
-                set_channel(pMgmt->pAdapter, pBSSList->uChannel);
-            }
-        }
-    }
-
-//    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Beacon 2 \n");
-    // check if CF field exists
-    if (WLAN_GET_CAP_INFO_ESS(*sFrame.pwCapInfo)) {
-        if (sFrame.pCFParms->wCFPDurRemaining > 0) {
-            // TODO: deal with CFP period to set NAV
-        }
-    }
-
-    HIDWORD(qwTimestamp) = cpu_to_le32(HIDWORD(*sFrame.pqwTimestamp));
-    LODWORD(qwTimestamp) = cpu_to_le32(LODWORD(*sFrame.pqwTimestamp));
-    HIDWORD(qwLocalTSF) = HIDWORD(pRxPacket->qwLocalTSF);
-    LODWORD(qwLocalTSF) = LODWORD(pRxPacket->qwLocalTSF);
-
-    // check if beacon TSF larger or small than our local TSF
-    if (HIDWORD(qwTimestamp) == HIDWORD(qwLocalTSF)) {
-        if (LODWORD(qwTimestamp) >= LODWORD(qwLocalTSF)) {
-            bTSFOffsetPostive = true;
-        }
-        else {
-            bTSFOffsetPostive = false;
-        }
-    }
-    else if (HIDWORD(qwTimestamp) > HIDWORD(qwLocalTSF)) {
-        bTSFOffsetPostive = true;
-    }
-    else if (HIDWORD(qwTimestamp) < HIDWORD(qwLocalTSF)) {
-        bTSFOffsetPostive = false;
-    }
-
-    if (bTSFOffsetPostive) {
-        qwTSFOffset = CARDqGetTSFOffset(pRxPacket->byRxRate, (qwTimestamp), (qwLocalTSF));
-    }
-    else {
-        qwTSFOffset = CARDqGetTSFOffset(pRxPacket->byRxRate, (qwLocalTSF), (qwTimestamp));
-    }
-
-    if (HIDWORD(qwTSFOffset) != 0 ||
-        (LODWORD(qwTSFOffset) > TRIVIAL_SYNC_DIFFERENCE )) {
-         bTSFLargeDiff = true;
-    }
-
-
-    // if infra mode
-    if (bIsAPBeacon == true) {
-
-        // Infra mode: Local TSF always follow AP's TSF if Difference huge.
-        if (bTSFLargeDiff)
-            bUpdateTSF = true;
-
-        if ((pDevice->bEnablePSMode == true) &&(sFrame.pTIM != 0)) {
-
-            // deal with DTIM, analysis TIM
-            pMgmt->bMulticastTIM = WLAN_MGMT_IS_MULTICAST_TIM(sFrame.pTIM->byBitMapCtl) ? true : false ;
-            pMgmt->byDTIMCount = sFrame.pTIM->byDTIMCount;
-            pMgmt->byDTIMPeriod = sFrame.pTIM->byDTIMPeriod;
-            wAIDNumber = pMgmt->wCurrAID & ~(BIT14|BIT15);
-
-            // check if AID in TIM field bit on
-            // wStartIndex = N1
-            wStartIndex = WLAN_MGMT_GET_TIM_OFFSET(sFrame.pTIM->byBitMapCtl) << 1;
-            // AIDIndex = N2
-            wAIDIndex = (wAIDNumber >> 3);
-            if ((wAIDNumber > 0) && (wAIDIndex >= wStartIndex)) {
-                uLocateByteIndex = wAIDIndex - wStartIndex;
-                // len = byDTIMCount + byDTIMPeriod + byDTIMPeriod + byVirtBitMap[0~250]
-                if (sFrame.pTIM->len >= (uLocateByteIndex + 4)) {
-                    byTIMBitOn  = (0x01) << ((wAIDNumber) % 8);
-                    pMgmt->bInTIM = sFrame.pTIM->byVirtBitMap[uLocateByteIndex] & byTIMBitOn ? true : false;
-                }
-                else {
-                    pMgmt->bInTIM = false;
-                };
-            }
-            else {
-                pMgmt->bInTIM = false;
-            };
-
-            if (pMgmt->bInTIM ||
-                (pMgmt->bMulticastTIM && (pMgmt->byDTIMCount == 0))) {
-                pMgmt->bInTIMWake = true;
-                // send out ps-poll packet
+				CARDbSetPhyParameter(pMgmt->pAdapter,
+						     pMgmt->eCurrentPHYMode,
+						     pMgmt->wCurrCapInfo,
+						     pMgmt->byERPContext,
+						     pMgmt->abyCurrSuppRates,
+						     pMgmt->abyCurrExtSuppRates
+					);
+			}
+			if (sFrame.pIE_PowerConstraint != NULL) {
+				CARDvSetPowerConstraint(pMgmt->pAdapter,
+							(unsigned char) pBSSList->uChannel,
+							sFrame.pIE_PowerConstraint->byPower
+);
+			}
+			if (sFrame.pIE_CHSW != NULL) {
+				CARDbChannelSwitch(pMgmt->pAdapter,
+						   sFrame.pIE_CHSW->byMode,
+						   get_channel_mapping(pMgmt->pAdapter, sFrame.pIE_CHSW->byMode, pMgmt->eCurrentPHYMode),
+						   sFrame.pIE_CHSW->byCount
+					);
+
+			} else if (bIsChannelEqual == false) {
+				set_channel(pMgmt->pAdapter, pBSSList->uChannel);
+			}
+		}
+	}
+
+//    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Beacon 2 \n");
+	// check if CF field exists
+	if (WLAN_GET_CAP_INFO_ESS(*sFrame.pwCapInfo)) {
+		if (sFrame.pCFParms->wCFPDurRemaining > 0) {
+			// TODO: deal with CFP period to set NAV
+		}
+	}
+
+	HIDWORD(qwTimestamp) = cpu_to_le32(HIDWORD(*sFrame.pqwTimestamp));
+	LODWORD(qwTimestamp) = cpu_to_le32(LODWORD(*sFrame.pqwTimestamp));
+	HIDWORD(qwLocalTSF) = HIDWORD(pRxPacket->qwLocalTSF);
+	LODWORD(qwLocalTSF) = LODWORD(pRxPacket->qwLocalTSF);
+
+	// check if beacon TSF larger or small than our local TSF
+	if (HIDWORD(qwTimestamp) == HIDWORD(qwLocalTSF)) {
+		if (LODWORD(qwTimestamp) >= LODWORD(qwLocalTSF)) {
+			bTSFOffsetPostive = true;
+		} else {
+			bTSFOffsetPostive = false;
+		}
+	} else if (HIDWORD(qwTimestamp) > HIDWORD(qwLocalTSF)) {
+		bTSFOffsetPostive = true;
+	} else if (HIDWORD(qwTimestamp) < HIDWORD(qwLocalTSF)) {
+		bTSFOffsetPostive = false;
+	}
+
+	if (bTSFOffsetPostive) {
+		qwTSFOffset = CARDqGetTSFOffset(pRxPacket->byRxRate, (qwTimestamp), (qwLocalTSF));
+	} else {
+		qwTSFOffset = CARDqGetTSFOffset(pRxPacket->byRxRate, (qwLocalTSF), (qwTimestamp));
+	}
+
+	if (HIDWORD(qwTSFOffset) != 0 ||
+	    (LODWORD(qwTSFOffset) > TRIVIAL_SYNC_DIFFERENCE)) {
+		bTSFLargeDiff = true;
+	}
+
+	// if infra mode
+	if (bIsAPBeacon == true) {
+		// Infra mode: Local TSF always follow AP's TSF if Difference huge.
+		if (bTSFLargeDiff)
+			bUpdateTSF = true;
+
+		if ((pDevice->bEnablePSMode == true) && (sFrame.pTIM != 0)) {
+			// deal with DTIM, analysis TIM
+			pMgmt->bMulticastTIM = WLAN_MGMT_IS_MULTICAST_TIM(sFrame.pTIM->byBitMapCtl) ? true : false;
+			pMgmt->byDTIMCount = sFrame.pTIM->byDTIMCount;
+			pMgmt->byDTIMPeriod = sFrame.pTIM->byDTIMPeriod;
+			wAIDNumber = pMgmt->wCurrAID & ~(BIT14|BIT15);
+
+			// check if AID in TIM field bit on
+			// wStartIndex = N1
+			wStartIndex = WLAN_MGMT_GET_TIM_OFFSET(sFrame.pTIM->byBitMapCtl) << 1;
+			// AIDIndex = N2
+			wAIDIndex = (wAIDNumber >> 3);
+			if ((wAIDNumber > 0) && (wAIDIndex >= wStartIndex)) {
+				uLocateByteIndex = wAIDIndex - wStartIndex;
+				// len = byDTIMCount + byDTIMPeriod + byDTIMPeriod + byVirtBitMap[0~250]
+				if (sFrame.pTIM->len >= (uLocateByteIndex + 4)) {
+					byTIMBitOn  = (0x01) << ((wAIDNumber) % 8);
+					pMgmt->bInTIM = sFrame.pTIM->byVirtBitMap[uLocateByteIndex] & byTIMBitOn ? true : false;
+				} else {
+					pMgmt->bInTIM = false;
+				};
+			} else {
+				pMgmt->bInTIM = false;
+			};
+
+			if (pMgmt->bInTIM ||
+			    (pMgmt->bMulticastTIM && (pMgmt->byDTIMCount == 0))) {
+				pMgmt->bInTIMWake = true;
+				// send out ps-poll packet
 //                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "BCN:In TIM\n");
-                if (pMgmt->bInTIM) {
-                    PSvSendPSPOLL((PSDevice)pDevice);
+				if (pMgmt->bInTIM) {
+					PSvSendPSPOLL((PSDevice)pDevice);
 //                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "BCN:PS-POLL sent..\n");
-                }
-
-            }
-            else {
-                pMgmt->bInTIMWake = false;
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "BCN: Not In TIM..\n");
-                if (pDevice->bPWBitOn == false) {
-                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "BCN: Send Null Packet\n");
-                    if (PSbSendNullPacket(pDevice))
-                        pDevice->bPWBitOn = true;
-                }
-                if(PSbConsiderPowerDown(pDevice, false, false)) {
-                   DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "BCN: Power down now...\n");
-                }
-            }
-
-        }
-
-    }
-    // if adhoc mode
-    if ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) && !bIsAPBeacon && bIsChannelEqual) {
-        if (bIsBSSIDEqual) {
-            // Use sNodeDBTable[0].uInActiveCount as IBSS beacons received count.
-		    if (pMgmt->sNodeDBTable[0].uInActiveCount != 0)
-		 	    pMgmt->sNodeDBTable[0].uInActiveCount = 0;
-
-            // adhoc mode:TSF updated only when beacon larger than local TSF
-            if (bTSFLargeDiff && bTSFOffsetPostive &&
-                (pMgmt->eCurrState == WMAC_STATE_JOINTED))
-                bUpdateTSF = true;
-
-            // During dpc, already in spinlocked.
-            if (BSSDBbIsSTAInNodeDB(pMgmt, sFrame.pHdr->sA3.abyAddr2, &uNodeIndex)) {
-
-                // Update the STA, (Technically the Beacons of all the IBSS nodes
-		        // should be identical, but that's not happening in practice.
-                pMgmt->abyCurrSuppRates[1] = RATEuSetIE((PWLAN_IE_SUPP_RATES)sFrame.pSuppRates,
-                                                        (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates,
-                                                        WLAN_RATES_MAXLEN_11B);
-                RATEvParseMaxRate( (void *)pDevice,
-                                   (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates,
-                                   NULL,
-                                   true,
-                                   &(pMgmt->sNodeDBTable[uNodeIndex].wMaxBasicRate),
-                                   &(pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate),
-                                   &(pMgmt->sNodeDBTable[uNodeIndex].wSuppRate),
-                                   &(pMgmt->sNodeDBTable[uNodeIndex].byTopCCKBasicRate),
-                                   &(pMgmt->sNodeDBTable[uNodeIndex].byTopOFDMBasicRate)
-                                  );
-                pMgmt->sNodeDBTable[uNodeIndex].bShortPreamble = WLAN_GET_CAP_INFO_SHORTPREAMBLE(*sFrame.pwCapInfo);
-                pMgmt->sNodeDBTable[uNodeIndex].bShortSlotTime = WLAN_GET_CAP_INFO_SHORTSLOTTIME(*sFrame.pwCapInfo);
-                pMgmt->sNodeDBTable[uNodeIndex].uInActiveCount = 0;
-            }
-            else {
-                // Todo, initial Node content
-                BSSvCreateOneNode((PSDevice)pDevice, &uNodeIndex);
-
-                pMgmt->abyCurrSuppRates[1] = RATEuSetIE((PWLAN_IE_SUPP_RATES)sFrame.pSuppRates,
-                                                        (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates,
-                                                        WLAN_RATES_MAXLEN_11B);
-                RATEvParseMaxRate( (void *)pDevice,
-                                   (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates,
-                                   NULL,
-                                   true,
-                                   &(pMgmt->sNodeDBTable[uNodeIndex].wMaxBasicRate),
-                                   &(pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate),
-                                   &(pMgmt->sNodeDBTable[uNodeIndex].wSuppRate),
-                                   &(pMgmt->sNodeDBTable[uNodeIndex].byTopCCKBasicRate),
-                                   &(pMgmt->sNodeDBTable[uNodeIndex].byTopOFDMBasicRate)
-                                 );
-
-                memcpy(pMgmt->sNodeDBTable[uNodeIndex].abyMACAddr, sFrame.pHdr->sA3.abyAddr2, WLAN_ADDR_LEN);
-                pMgmt->sNodeDBTable[uNodeIndex].bShortPreamble = WLAN_GET_CAP_INFO_SHORTPREAMBLE(*sFrame.pwCapInfo);
-                pMgmt->sNodeDBTable[uNodeIndex].wTxDataRate = pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate;
-#ifdef	PLICE_DEBUG
-		//if (uNodeIndex == 0)
-		{
-			printk("s_vMgrRxBeacon:TxDataRate is %d,Index is %d\n",pMgmt->sNodeDBTable[uNodeIndex].wTxDataRate,uNodeIndex);
+				}
+
+			} else {
+				pMgmt->bInTIMWake = false;
+				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "BCN: Not In TIM..\n");
+				if (pDevice->bPWBitOn == false) {
+					DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "BCN: Send Null Packet\n");
+					if (PSbSendNullPacket(pDevice))
+						pDevice->bPWBitOn = true;
+				}
+				if (PSbConsiderPowerDown(pDevice, false, false)) {
+					DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "BCN: Power down now...\n");
+				}
+			}
+
 		}
+
+	}
+	// if adhoc mode
+	if ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) && !bIsAPBeacon && bIsChannelEqual) {
+		if (bIsBSSIDEqual) {
+			// Use sNodeDBTable[0].uInActiveCount as IBSS beacons received count.
+			if (pMgmt->sNodeDBTable[0].uInActiveCount != 0)
+				pMgmt->sNodeDBTable[0].uInActiveCount = 0;
+
+			// adhoc mode:TSF updated only when beacon larger than local TSF
+			if (bTSFLargeDiff && bTSFOffsetPostive &&
+			    (pMgmt->eCurrState == WMAC_STATE_JOINTED))
+				bUpdateTSF = true;
+
+			// During dpc, already in spinlocked.
+			if (BSSDBbIsSTAInNodeDB(pMgmt, sFrame.pHdr->sA3.abyAddr2, &uNodeIndex)) {
+				// Update the STA, (Technically the Beacons of all the IBSS nodes
+				// should be identical, but that's not happening in practice.
+				pMgmt->abyCurrSuppRates[1] = RATEuSetIE((PWLAN_IE_SUPP_RATES)sFrame.pSuppRates,
+									(PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates,
+									WLAN_RATES_MAXLEN_11B);
+				RATEvParseMaxRate((void *)pDevice,
+						  (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates,
+						  NULL,
+						  true,
+						  &(pMgmt->sNodeDBTable[uNodeIndex].wMaxBasicRate),
+						  &(pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate),
+						  &(pMgmt->sNodeDBTable[uNodeIndex].wSuppRate),
+						  &(pMgmt->sNodeDBTable[uNodeIndex].byTopCCKBasicRate),
+						  &(pMgmt->sNodeDBTable[uNodeIndex].byTopOFDMBasicRate)
+					);
+				pMgmt->sNodeDBTable[uNodeIndex].bShortPreamble = WLAN_GET_CAP_INFO_SHORTPREAMBLE(*sFrame.pwCapInfo);
+				pMgmt->sNodeDBTable[uNodeIndex].bShortSlotTime = WLAN_GET_CAP_INFO_SHORTSLOTTIME(*sFrame.pwCapInfo);
+				pMgmt->sNodeDBTable[uNodeIndex].uInActiveCount = 0;
+			} else {
+				// Todo, initial Node content
+				BSSvCreateOneNode((PSDevice)pDevice, &uNodeIndex);
+
+				pMgmt->abyCurrSuppRates[1] = RATEuSetIE((PWLAN_IE_SUPP_RATES)sFrame.pSuppRates,
+									(PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates,
+									WLAN_RATES_MAXLEN_11B);
+				RATEvParseMaxRate((void *)pDevice,
+						  (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates,
+						  NULL,
+						  true,
+						  &(pMgmt->sNodeDBTable[uNodeIndex].wMaxBasicRate),
+						  &(pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate),
+						  &(pMgmt->sNodeDBTable[uNodeIndex].wSuppRate),
+						  &(pMgmt->sNodeDBTable[uNodeIndex].byTopCCKBasicRate),
+						  &(pMgmt->sNodeDBTable[uNodeIndex].byTopOFDMBasicRate)
+					);
+
+				memcpy(pMgmt->sNodeDBTable[uNodeIndex].abyMACAddr, sFrame.pHdr->sA3.abyAddr2, WLAN_ADDR_LEN);
+				pMgmt->sNodeDBTable[uNodeIndex].bShortPreamble = WLAN_GET_CAP_INFO_SHORTPREAMBLE(*sFrame.pwCapInfo);
+				pMgmt->sNodeDBTable[uNodeIndex].wTxDataRate = pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate;
+#ifdef	PLICE_DEBUG
+				{
+					printk("s_vMgrRxBeacon:TxDataRate is %d,Index is %d\n", pMgmt->sNodeDBTable[uNodeIndex].wTxDataRate, uNodeIndex);
+				}
 #endif
 /*
-                pMgmt->sNodeDBTable[uNodeIndex].bShortSlotTime = WLAN_GET_CAP_INFO_SHORTSLOTTIME(*sFrame.pwCapInfo);
-                if(pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate > RATE_11M)
-                       pMgmt->sNodeDBTable[uNodeIndex].bERPExist = true;
+  pMgmt->sNodeDBTable[uNodeIndex].bShortSlotTime = WLAN_GET_CAP_INFO_SHORTSLOTTIME(*sFrame.pwCapInfo);
+  if (pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate > RATE_11M)
+  pMgmt->sNodeDBTable[uNodeIndex].bERPExist = true;
 */
-            }
-
-            // if other stations joined, indicate connection to upper layer..
-            if (pMgmt->eCurrState == WMAC_STATE_STARTED) {
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Current IBSS State: [Started]........to: [Jointed] \n");
-                pMgmt->eCurrState = WMAC_STATE_JOINTED;
-                pDevice->bLinkPass = true;
-                if (netif_queue_stopped(pDevice->dev)){
-                    netif_wake_queue(pDevice->dev);
-                }
-                pMgmt->sNodeDBTable[0].bActive = true;
-                pMgmt->sNodeDBTable[0].uInActiveCount = 0;
-
-            }
-        }
-        else if (bIsSSIDEqual) {
-
-            // See other adhoc sta with the same SSID but BSSID is different.
-            // adpot this vars only when TSF larger then us.
-            if (bTSFLargeDiff && bTSFOffsetPostive) {
-                 // we don't support ATIM under adhoc mode
-               // if ( sFrame.pIBSSParms->wATIMWindow == 0) {
-                     // adpot this vars
-                     // TODO: check sFrame cap if privacy on, and support rate syn
-                     memcpy(pMgmt->abyCurrBSSID, sFrame.pHdr->sA3.abyAddr3, WLAN_BSSID_LEN);
-                     memcpy(pDevice->abyBSSID, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN);
-                     pMgmt->wCurrATIMWindow = cpu_to_le16(sFrame.pIBSSParms->wATIMWindow);
-                     pMgmt->wCurrBeaconPeriod = cpu_to_le16(*sFrame.pwBeaconInterval);
-                     pMgmt->abyCurrSuppRates[1] = RATEuSetIE((PWLAN_IE_SUPP_RATES)sFrame.pSuppRates,
-                                                      (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates,
-                                                      WLAN_RATES_MAXLEN_11B);
-                     // set HW beacon interval and re-synchronizing....
-                     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Rejoining to Other Adhoc group with same SSID........\n");
-                     VNSvOutPortW(pDevice->PortOffset + MAC_REG_BI, pMgmt->wCurrBeaconPeriod);
-                     CARDbUpdateTSF(pDevice, pRxPacket->byRxRate, qwTimestamp, qwLocalTSF);
-                     CARDvUpdateNextTBTT(pDevice->PortOffset, qwTimestamp, pMgmt->wCurrBeaconPeriod);
-                     // Turn off bssid filter to avoid filter others adhoc station which bssid is different.
-                     MACvWriteBSSIDAddress(pDevice->PortOffset, pMgmt->abyCurrBSSID);
-
-                     CARDbSetPhyParameter (  pMgmt->pAdapter,
-                                            pMgmt->eCurrentPHYMode,
-                                            pMgmt->wCurrCapInfo,
-                                            pMgmt->byERPContext,
-                                            pMgmt->abyCurrSuppRates,
-                                            pMgmt->abyCurrExtSuppRates);
-
-
-                     // MACvRegBitsOff(pDevice->PortOffset, MAC_REG_RCR, RCR_BSSID);
-                     // set highest basic rate
-                     // s_vSetHighestBasicRate(pDevice, (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates);
-                     // Prepare beacon frame
-                     bMgrPrepareBeaconToSend((void *)pDevice, pMgmt);
-              //  }
-            }
-        }
-    }
-    // endian issue ???
-    // Update TSF
-    if (bUpdateTSF) {
-        CARDbGetCurrentTSF(pDevice->PortOffset, &qwCurrTSF);
-        CARDbUpdateTSF(pDevice, pRxPacket->byRxRate, qwTimestamp, pRxPacket->qwLocalTSF);
-        CARDbGetCurrentTSF(pDevice->PortOffset, &qwCurrTSF);
-        CARDvUpdateNextTBTT(pDevice->PortOffset, qwTimestamp, pMgmt->wCurrBeaconPeriod);
-    }
-
-    return;
-}
-
+			}
+
+			// if other stations joined, indicate connection to upper layer..
+			if (pMgmt->eCurrState == WMAC_STATE_STARTED) {
+				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Current IBSS State: [Started]........to: [Jointed] \n");
+				pMgmt->eCurrState = WMAC_STATE_JOINTED;
+				pDevice->bLinkPass = true;
+				if (netif_queue_stopped(pDevice->dev)) {
+					netif_wake_queue(pDevice->dev);
+				}
+				pMgmt->sNodeDBTable[0].bActive = true;
+				pMgmt->sNodeDBTable[0].uInActiveCount = 0;
+
+			}
+		} else if (bIsSSIDEqual) {
+			// See other adhoc sta with the same SSID but BSSID is different.
+			// adpot this vars only when TSF larger then us.
+			if (bTSFLargeDiff && bTSFOffsetPostive) {
+				// we don't support ATIM under adhoc mode
+				// if (sFrame.pIBSSParms->wATIMWindow == 0) {
+				// adpot this vars
+				// TODO: check sFrame cap if privacy on, and support rate syn
+				memcpy(pMgmt->abyCurrBSSID, sFrame.pHdr->sA3.abyAddr3, WLAN_BSSID_LEN);
+				memcpy(pDevice->abyBSSID, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN);
+				pMgmt->wCurrATIMWindow = cpu_to_le16(sFrame.pIBSSParms->wATIMWindow);
+				pMgmt->wCurrBeaconPeriod = cpu_to_le16(*sFrame.pwBeaconInterval);
+				pMgmt->abyCurrSuppRates[1] = RATEuSetIE((PWLAN_IE_SUPP_RATES)sFrame.pSuppRates,
+									(PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates,
+									WLAN_RATES_MAXLEN_11B);
+				// set HW beacon interval and re-synchronizing....
+				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Rejoining to Other Adhoc group with same SSID........\n");
+				VNSvOutPortW(pDevice->PortOffset + MAC_REG_BI, pMgmt->wCurrBeaconPeriod);
+				CARDbUpdateTSF(pDevice, pRxPacket->byRxRate, qwTimestamp, qwLocalTSF);
+				CARDvUpdateNextTBTT(pDevice->PortOffset, qwTimestamp, pMgmt->wCurrBeaconPeriod);
+				// Turn off bssid filter to avoid filter others adhoc station which bssid is different.
+				MACvWriteBSSIDAddress(pDevice->PortOffset, pMgmt->abyCurrBSSID);
+
+				CARDbSetPhyParameter(pMgmt->pAdapter,
+						     pMgmt->eCurrentPHYMode,
+						     pMgmt->wCurrCapInfo,
+						     pMgmt->byERPContext,
+						     pMgmt->abyCurrSuppRates,
+						     pMgmt->abyCurrExtSuppRates);
+
+				// MACvRegBitsOff(pDevice->PortOffset, MAC_REG_RCR, RCR_BSSID);
+				// set highest basic rate
+				// s_vSetHighestBasicRate(pDevice, (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates);
+				// Prepare beacon frame
+				bMgrPrepareBeaconToSend((void *)pDevice, pMgmt);
+				//  }
+			}
+		}
+	}
+	// endian issue ???
+	// Update TSF
+if (bUpdateTSF) {
+		CARDbGetCurrentTSF(pDevice->PortOffset, &qwCurrTSF);
+		CARDbUpdateTSF(pDevice, pRxPacket->byRxRate, qwTimestamp, pRxPacket->qwLocalTSF);
+		CARDbGetCurrentTSF(pDevice->PortOffset, &qwCurrTSF);
+		CARDvUpdateNextTBTT(pDevice->PortOffset, qwTimestamp, pMgmt->wCurrBeaconPeriod);
+	}
 
+	return;
+}
 
 /*+
  *
@@ -2384,248 +2261,239 @@ if(ChannelExceedZoneType(pDevice,byCurrChannel)==true)
  * Return Value:
  *    CMD_STATUS
  *
--*/
+ -*/
 void
 vMgrCreateOwnIBSS(
-    void *hDeviceContext,
-    PCMD_STATUS pStatus
-    )
+	void *hDeviceContext,
+	PCMD_STATUS pStatus
+)
 {
-    PSDevice            pDevice = (PSDevice)hDeviceContext;
-    PSMgmtObject        pMgmt = pDevice->pMgmt;
-    unsigned short wMaxBasicRate;
-    unsigned short wMaxSuppRate;
-    unsigned char byTopCCKBasicRate;
-    unsigned char byTopOFDMBasicRate;
-    QWORD               qwCurrTSF;
-    unsigned int ii;
-    unsigned char abyRATE[] = {0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, 0x0C, 0x12, 0x18, 0x60};
-    unsigned char abyCCK_RATE[] = {0x82, 0x84, 0x8B, 0x96};
-    unsigned char abyOFDM_RATE[] = {0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6C};
-    unsigned short wSuppRate;
-
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Create Basic Service Set .......\n");
-
-    if (pMgmt->eConfigMode == WMAC_CONFIG_IBSS_STA) {
-        if ((pMgmt->eAuthenMode == WMAC_AUTH_WPANONE) &&
-            (pDevice->eEncryptionStatus != Ndis802_11Encryption2Enabled) &&
-            (pDevice->eEncryptionStatus != Ndis802_11Encryption3Enabled)) {
-            // encryption mode error
-            *pStatus = CMD_STATUS_FAILURE;
-            return;
-        }
-    }
-
-    pMgmt->abyCurrSuppRates[0] = WLAN_EID_SUPP_RATES;
-    pMgmt->abyCurrExtSuppRates[0] = WLAN_EID_EXTSUPP_RATES;
-
-    if (pMgmt->eConfigMode == WMAC_CONFIG_AP) {
-        pMgmt->eCurrentPHYMode = pMgmt->byAPBBType;
-    } else {
-        if (pDevice->byBBType == BB_TYPE_11G)
-            pMgmt->eCurrentPHYMode = PHY_TYPE_11G;
-        if (pDevice->byBBType == BB_TYPE_11B)
-            pMgmt->eCurrentPHYMode = PHY_TYPE_11B;
-        if (pDevice->byBBType == BB_TYPE_11A)
-            pMgmt->eCurrentPHYMode = PHY_TYPE_11A;
-    }
-
-    if (pMgmt->eCurrentPHYMode != PHY_TYPE_11A) {
-        pMgmt->abyCurrSuppRates[1] = WLAN_RATES_MAXLEN_11B;
-        pMgmt->abyCurrExtSuppRates[1] = 0;
-        for (ii = 0; ii < 4; ii++)
-            pMgmt->abyCurrSuppRates[2+ii] = abyRATE[ii];
-    } else {
-        pMgmt->abyCurrSuppRates[1] = 8;
-        pMgmt->abyCurrExtSuppRates[1] = 0;
-        for (ii = 0; ii < 8; ii++)
-            pMgmt->abyCurrSuppRates[2+ii] = abyRATE[ii];
-    }
-
-
-    if (pMgmt->eCurrentPHYMode == PHY_TYPE_11G) {
-        pMgmt->abyCurrSuppRates[1] = 8;
-        pMgmt->abyCurrExtSuppRates[1] = 4;
-        for (ii = 0; ii < 4; ii++)
-            pMgmt->abyCurrSuppRates[2+ii] =  abyCCK_RATE[ii];
-        for (ii = 4; ii < 8; ii++)
-            pMgmt->abyCurrSuppRates[2+ii] =  abyOFDM_RATE[ii-4];
-        for (ii = 0; ii < 4; ii++)
-            pMgmt->abyCurrExtSuppRates[2+ii] =  abyOFDM_RATE[ii+4];
-    }
-
-
-    // Disable Protect Mode
-    pDevice->bProtectMode = 0;
-    MACvDisableProtectMD(pDevice->PortOffset);
-
-    pDevice->bBarkerPreambleMd = 0;
-    MACvDisableBarkerPreambleMd(pDevice->PortOffset);
-
-    // Kyle Test 2003.11.04
-
-    // set HW beacon interval
-    if (pMgmt->wIBSSBeaconPeriod == 0)
-        pMgmt->wIBSSBeaconPeriod = DEFAULT_IBSS_BI;
-
-
-    CARDbGetCurrentTSF(pDevice->PortOffset, &qwCurrTSF);
-    // clear TSF counter
-    VNSvOutPortB(pDevice->PortOffset + MAC_REG_TFTCTL, TFTCTL_TSFCNTRST);
-    // enable TSF counter
-    VNSvOutPortB(pDevice->PortOffset + MAC_REG_TFTCTL, TFTCTL_TSFCNTREN);
-
-    // set Next TBTT
-    CARDvSetFirstNextTBTT(pDevice->PortOffset, pMgmt->wIBSSBeaconPeriod);
-
-    pMgmt->uIBSSChannel = pDevice->uChannel;
-
-    if (pMgmt->uIBSSChannel == 0)
-        pMgmt->uIBSSChannel = DEFAULT_IBSS_CHANNEL;
-
-
-    // set basic rate
-
-    RATEvParseMaxRate((void *)pDevice, (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates,
-                      (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates, true,
-                      &wMaxBasicRate, &wMaxSuppRate, &wSuppRate,
-                      &byTopCCKBasicRate, &byTopOFDMBasicRate);
-
-
-    if (pMgmt->eConfigMode == WMAC_CONFIG_AP) {
-        pMgmt->eCurrMode = WMAC_MODE_ESS_AP;
-    }
-
-    if (pMgmt->eConfigMode == WMAC_CONFIG_IBSS_STA) {
-        memcpy(pMgmt->abyIBSSDFSOwner, pDevice->abyCurrentNetAddr, 6);
-        pMgmt->byIBSSDFSRecovery = 10;
-        pMgmt->eCurrMode = WMAC_MODE_IBSS_STA;
-    }
-
-    // Adopt pre-configured IBSS vars to current vars
-    pMgmt->eCurrState = WMAC_STATE_STARTED;
-    pMgmt->wCurrBeaconPeriod = pMgmt->wIBSSBeaconPeriod;
-    pMgmt->uCurrChannel = pMgmt->uIBSSChannel;
-    pMgmt->wCurrATIMWindow = pMgmt->wIBSSATIMWindow;
-    MACvWriteATIMW(pDevice->PortOffset, pMgmt->wCurrATIMWindow);
-    pDevice->uCurrRSSI = 0;
-    pDevice->byCurrSQ = 0;
-    //memcpy(pMgmt->abyDesireSSID,pMgmt->abyAdHocSSID,
-                     // ((PWLAN_IE_SSID)pMgmt->abyAdHocSSID)->len + WLAN_IEHDR_LEN);
-    memset(pMgmt->abyCurrSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
-    memcpy(pMgmt->abyCurrSSID,
-           pMgmt->abyDesireSSID,
-           ((PWLAN_IE_SSID)pMgmt->abyDesireSSID)->len + WLAN_IEHDR_LEN
-          );
-
-    if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) {
-        // AP mode BSSID = MAC addr
-        memcpy(pMgmt->abyCurrBSSID, pMgmt->abyMACAddr, WLAN_ADDR_LEN);
-	DBG_PRT(MSG_LEVEL_INFO, KERN_INFO"AP beacon created BSSID:%pM\n",
-		pMgmt->abyCurrBSSID);
-    }
-
-    if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) {
-
-        // BSSID selected must be randomized as spec 11.1.3
-        pMgmt->abyCurrBSSID[5] = (unsigned char) (LODWORD(qwCurrTSF)& 0x000000ff);
-        pMgmt->abyCurrBSSID[4] = (unsigned char)((LODWORD(qwCurrTSF)& 0x0000ff00) >> 8);
-        pMgmt->abyCurrBSSID[3] = (unsigned char)((LODWORD(qwCurrTSF)& 0x00ff0000) >> 16);
-        pMgmt->abyCurrBSSID[2] = (unsigned char)((LODWORD(qwCurrTSF)& 0x00000ff0) >> 4);
-        pMgmt->abyCurrBSSID[1] = (unsigned char)((LODWORD(qwCurrTSF)& 0x000ff000) >> 12);
-        pMgmt->abyCurrBSSID[0] = (unsigned char)((LODWORD(qwCurrTSF)& 0x0ff00000) >> 20);
-        pMgmt->abyCurrBSSID[5] ^= pMgmt->abyMACAddr[0];
-        pMgmt->abyCurrBSSID[4] ^= pMgmt->abyMACAddr[1];
-        pMgmt->abyCurrBSSID[3] ^= pMgmt->abyMACAddr[2];
-        pMgmt->abyCurrBSSID[2] ^= pMgmt->abyMACAddr[3];
-        pMgmt->abyCurrBSSID[1] ^= pMgmt->abyMACAddr[4];
-        pMgmt->abyCurrBSSID[0] ^= pMgmt->abyMACAddr[5];
-        pMgmt->abyCurrBSSID[0] &= ~IEEE_ADDR_GROUP;
-        pMgmt->abyCurrBSSID[0] |= IEEE_ADDR_UNIVERSAL;
-
-
-	DBG_PRT(MSG_LEVEL_INFO, KERN_INFO"Adhoc beacon created bssid:%pM\n",
-		pMgmt->abyCurrBSSID);
-    }
-
-    // Set Capability Info
-    pMgmt->wCurrCapInfo = 0;
-
-    if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) {
-        pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_ESS(1);
-        pMgmt->byDTIMPeriod = DEFAULT_DTIM_PERIOD;
-        pMgmt->byDTIMCount = pMgmt->byDTIMPeriod - 1;
-    }
-
-    if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) {
-        pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_IBSS(1);
-    }
-
-    if (pDevice->bEncryptionEnable) {
-        pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_PRIVACY(1);
-        if (pMgmt->eAuthenMode == WMAC_AUTH_WPANONE) {
-            if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) {
-                pMgmt->byCSSPK = KEY_CTL_CCMP;
-                pMgmt->byCSSGK = KEY_CTL_CCMP;
-            } else if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) {
-                pMgmt->byCSSPK = KEY_CTL_TKIP;
-                pMgmt->byCSSGK = KEY_CTL_TKIP;
-            } else {
-                pMgmt->byCSSPK = KEY_CTL_NONE;
-                pMgmt->byCSSGK = KEY_CTL_WEP;
-            }
-        } else {
-            pMgmt->byCSSPK = KEY_CTL_WEP;
-            pMgmt->byCSSGK = KEY_CTL_WEP;
-        }
-    }
-
-    pMgmt->byERPContext = 0;
+	PSDevice            pDevice = (PSDevice)hDeviceContext;
+	PSMgmtObject        pMgmt = pDevice->pMgmt;
+	unsigned short wMaxBasicRate;
+	unsigned short wMaxSuppRate;
+	unsigned char byTopCCKBasicRate;
+	unsigned char byTopOFDMBasicRate;
+	QWORD               qwCurrTSF;
+	unsigned int ii;
+	unsigned char abyRATE[] = {0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, 0x0C, 0x12, 0x18, 0x60};
+	unsigned char abyCCK_RATE[] = {0x82, 0x84, 0x8B, 0x96};
+	unsigned char abyOFDM_RATE[] = {0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6C};
+	unsigned short wSuppRate;
+
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Create Basic Service Set .......\n");
+
+	if (pMgmt->eConfigMode == WMAC_CONFIG_IBSS_STA) {
+		if ((pMgmt->eAuthenMode == WMAC_AUTH_WPANONE) &&
+		    (pDevice->eEncryptionStatus != Ndis802_11Encryption2Enabled) &&
+		    (pDevice->eEncryptionStatus != Ndis802_11Encryption3Enabled)) {
+			// encryption mode error
+			*pStatus = CMD_STATUS_FAILURE;
+			return;
+		}
+	}
+
+	pMgmt->abyCurrSuppRates[0] = WLAN_EID_SUPP_RATES;
+	pMgmt->abyCurrExtSuppRates[0] = WLAN_EID_EXTSUPP_RATES;
+
+	if (pMgmt->eConfigMode == WMAC_CONFIG_AP) {
+		pMgmt->eCurrentPHYMode = pMgmt->byAPBBType;
+	} else {
+		if (pDevice->byBBType == BB_TYPE_11G)
+			pMgmt->eCurrentPHYMode = PHY_TYPE_11G;
+		if (pDevice->byBBType == BB_TYPE_11B)
+			pMgmt->eCurrentPHYMode = PHY_TYPE_11B;
+		if (pDevice->byBBType == BB_TYPE_11A)
+			pMgmt->eCurrentPHYMode = PHY_TYPE_11A;
+	}
+
+	if (pMgmt->eCurrentPHYMode != PHY_TYPE_11A) {
+		pMgmt->abyCurrSuppRates[1] = WLAN_RATES_MAXLEN_11B;
+		pMgmt->abyCurrExtSuppRates[1] = 0;
+		for (ii = 0; ii < 4; ii++)
+			pMgmt->abyCurrSuppRates[2+ii] = abyRATE[ii];
+	} else {
+		pMgmt->abyCurrSuppRates[1] = 8;
+		pMgmt->abyCurrExtSuppRates[1] = 0;
+		for (ii = 0; ii < 8; ii++)
+			pMgmt->abyCurrSuppRates[2+ii] = abyRATE[ii];
+	}
+
+	if (pMgmt->eCurrentPHYMode == PHY_TYPE_11G) {
+		pMgmt->abyCurrSuppRates[1] = 8;
+		pMgmt->abyCurrExtSuppRates[1] = 4;
+		for (ii = 0; ii < 4; ii++)
+			pMgmt->abyCurrSuppRates[2+ii] =  abyCCK_RATE[ii];
+		for (ii = 4; ii < 8; ii++)
+			pMgmt->abyCurrSuppRates[2+ii] =  abyOFDM_RATE[ii-4];
+		for (ii = 0; ii < 4; ii++)
+			pMgmt->abyCurrExtSuppRates[2+ii] =  abyOFDM_RATE[ii+4];
+	}
+
+	// Disable Protect Mode
+	pDevice->bProtectMode = 0;
+	MACvDisableProtectMD(pDevice->PortOffset);
+
+	pDevice->bBarkerPreambleMd = 0;
+	MACvDisableBarkerPreambleMd(pDevice->PortOffset);
+
+	// Kyle Test 2003.11.04
+
+	// set HW beacon interval
+	if (pMgmt->wIBSSBeaconPeriod == 0)
+		pMgmt->wIBSSBeaconPeriod = DEFAULT_IBSS_BI;
+
+	CARDbGetCurrentTSF(pDevice->PortOffset, &qwCurrTSF);
+	// clear TSF counter
+	VNSvOutPortB(pDevice->PortOffset + MAC_REG_TFTCTL, TFTCTL_TSFCNTRST);
+	// enable TSF counter
+	VNSvOutPortB(pDevice->PortOffset + MAC_REG_TFTCTL, TFTCTL_TSFCNTREN);
+
+	// set Next TBTT
+	CARDvSetFirstNextTBTT(pDevice->PortOffset, pMgmt->wIBSSBeaconPeriod);
+
+	pMgmt->uIBSSChannel = pDevice->uChannel;
+
+	if (pMgmt->uIBSSChannel == 0)
+		pMgmt->uIBSSChannel = DEFAULT_IBSS_CHANNEL;
+
+	// set basic rate
+
+	RATEvParseMaxRate((void *)pDevice, (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates,
+			  (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates, true,
+			  &wMaxBasicRate, &wMaxSuppRate, &wSuppRate,
+			  &byTopCCKBasicRate, &byTopOFDMBasicRate);
+
+	if (pMgmt->eConfigMode == WMAC_CONFIG_AP) {
+		pMgmt->eCurrMode = WMAC_MODE_ESS_AP;
+	}
+
+	if (pMgmt->eConfigMode == WMAC_CONFIG_IBSS_STA) {
+		memcpy(pMgmt->abyIBSSDFSOwner, pDevice->abyCurrentNetAddr, 6);
+		pMgmt->byIBSSDFSRecovery = 10;
+		pMgmt->eCurrMode = WMAC_MODE_IBSS_STA;
+	}
+
+	// Adopt pre-configured IBSS vars to current vars
+	pMgmt->eCurrState = WMAC_STATE_STARTED;
+	pMgmt->wCurrBeaconPeriod = pMgmt->wIBSSBeaconPeriod;
+	pMgmt->uCurrChannel = pMgmt->uIBSSChannel;
+	pMgmt->wCurrATIMWindow = pMgmt->wIBSSATIMWindow;
+	MACvWriteATIMW(pDevice->PortOffset, pMgmt->wCurrATIMWindow);
+	pDevice->uCurrRSSI = 0;
+	pDevice->byCurrSQ = 0;
+	//memcpy(pMgmt->abyDesireSSID,pMgmt->abyAdHocSSID,
+	// ((PWLAN_IE_SSID)pMgmt->abyAdHocSSID)->len + WLAN_IEHDR_LEN);
+	memset(pMgmt->abyCurrSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
+	memcpy(pMgmt->abyCurrSSID,
+	       pMgmt->abyDesireSSID,
+	       ((PWLAN_IE_SSID)pMgmt->abyDesireSSID)->len + WLAN_IEHDR_LEN
+);
+
+	if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) {
+		// AP mode BSSID = MAC addr
+		memcpy(pMgmt->abyCurrBSSID, pMgmt->abyMACAddr, WLAN_ADDR_LEN);
+		DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "AP beacon created BSSID:%pM\n",
+			pMgmt->abyCurrBSSID);
+	}
+
+	if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) {
+		// BSSID selected must be randomized as spec 11.1.3
+		pMgmt->abyCurrBSSID[5] = (unsigned char) (LODWORD(qwCurrTSF) & 0x000000ff);
+		pMgmt->abyCurrBSSID[4] = (unsigned char)((LODWORD(qwCurrTSF) & 0x0000ff00) >> 8);
+		pMgmt->abyCurrBSSID[3] = (unsigned char)((LODWORD(qwCurrTSF) & 0x00ff0000) >> 16);
+		pMgmt->abyCurrBSSID[2] = (unsigned char)((LODWORD(qwCurrTSF) & 0x00000ff0) >> 4);
+		pMgmt->abyCurrBSSID[1] = (unsigned char)((LODWORD(qwCurrTSF) & 0x000ff000) >> 12);
+		pMgmt->abyCurrBSSID[0] = (unsigned char)((LODWORD(qwCurrTSF) & 0x0ff00000) >> 20);
+		pMgmt->abyCurrBSSID[5] ^= pMgmt->abyMACAddr[0];
+		pMgmt->abyCurrBSSID[4] ^= pMgmt->abyMACAddr[1];
+		pMgmt->abyCurrBSSID[3] ^= pMgmt->abyMACAddr[2];
+		pMgmt->abyCurrBSSID[2] ^= pMgmt->abyMACAddr[3];
+		pMgmt->abyCurrBSSID[1] ^= pMgmt->abyMACAddr[4];
+		pMgmt->abyCurrBSSID[0] ^= pMgmt->abyMACAddr[5];
+		pMgmt->abyCurrBSSID[0] &= ~IEEE_ADDR_GROUP;
+		pMgmt->abyCurrBSSID[0] |= IEEE_ADDR_UNIVERSAL;
+
+		DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "Adhoc beacon created bssid:%pM\n",
+			pMgmt->abyCurrBSSID);
+	}
+
+	// Set Capability Info
+	pMgmt->wCurrCapInfo = 0;
+
+	if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) {
+		pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_ESS(1);
+		pMgmt->byDTIMPeriod = DEFAULT_DTIM_PERIOD;
+		pMgmt->byDTIMCount = pMgmt->byDTIMPeriod - 1;
+	}
+
+	if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) {
+		pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_IBSS(1);
+	}
+
+	if (pDevice->bEncryptionEnable) {
+		pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_PRIVACY(1);
+		if (pMgmt->eAuthenMode == WMAC_AUTH_WPANONE) {
+			if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) {
+				pMgmt->byCSSPK = KEY_CTL_CCMP;
+				pMgmt->byCSSGK = KEY_CTL_CCMP;
+			} else if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) {
+				pMgmt->byCSSPK = KEY_CTL_TKIP;
+				pMgmt->byCSSGK = KEY_CTL_TKIP;
+			} else {
+				pMgmt->byCSSPK = KEY_CTL_NONE;
+				pMgmt->byCSSGK = KEY_CTL_WEP;
+			}
+		} else {
+			pMgmt->byCSSPK = KEY_CTL_WEP;
+			pMgmt->byCSSGK = KEY_CTL_WEP;
+		}
+	}
+
+	pMgmt->byERPContext = 0;
 
 //    memcpy(pDevice->abyBSSID, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN);
 
-    if (pMgmt->eConfigMode == WMAC_CONFIG_AP) {
-        CARDbSetBSSID(pMgmt->pAdapter, pMgmt->abyCurrBSSID, OP_MODE_AP);
-    } else {
-        CARDbSetBSSID(pMgmt->pAdapter, pMgmt->abyCurrBSSID, OP_MODE_ADHOC);
-    }
-
-    CARDbSetPhyParameter(   pMgmt->pAdapter,
-                            pMgmt->eCurrentPHYMode,
-                            pMgmt->wCurrCapInfo,
-                            pMgmt->byERPContext,
-                            pMgmt->abyCurrSuppRates,
-                            pMgmt->abyCurrExtSuppRates
-                            );
-
-    CARDbSetBeaconPeriod(pMgmt->pAdapter, pMgmt->wIBSSBeaconPeriod);
-    // set channel and clear NAV
-    set_channel(pMgmt->pAdapter, pMgmt->uIBSSChannel);
-    pMgmt->uCurrChannel = pMgmt->uIBSSChannel;
-
-    if (CARDbIsShortPreamble(pMgmt->pAdapter)) {
-        pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SHORTPREAMBLE(1);
-    } else {
-        pMgmt->wCurrCapInfo &= (~WLAN_SET_CAP_INFO_SHORTPREAMBLE(1));
-    }
-
-    if ((pMgmt->b11hEnable == true) &&
-        (pMgmt->eCurrentPHYMode == PHY_TYPE_11A)) {
-        pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SPECTRUMMNG(1);
-    } else {
-        pMgmt->wCurrCapInfo &= (~WLAN_SET_CAP_INFO_SPECTRUMMNG(1));
-    }
-
-    pMgmt->eCurrState = WMAC_STATE_STARTED;
-    // Prepare beacon to send
-    if (bMgrPrepareBeaconToSend((void *)pDevice, pMgmt)) {
-        *pStatus = CMD_STATUS_SUCCESS;
-    }
-
-    return ;
-}
+	if (pMgmt->eConfigMode == WMAC_CONFIG_AP) {
+		CARDbSetBSSID(pMgmt->pAdapter, pMgmt->abyCurrBSSID, OP_MODE_AP);
+	} else {
+		CARDbSetBSSID(pMgmt->pAdapter, pMgmt->abyCurrBSSID, OP_MODE_ADHOC);
+	}
+
+	CARDbSetPhyParameter(pMgmt->pAdapter,
+			     pMgmt->eCurrentPHYMode,
+			     pMgmt->wCurrCapInfo,
+			     pMgmt->byERPContext,
+			     pMgmt->abyCurrSuppRates,
+			     pMgmt->abyCurrExtSuppRates
+		);
+
+	CARDbSetBeaconPeriod(pMgmt->pAdapter, pMgmt->wIBSSBeaconPeriod);
+	// set channel and clear NAV
+	set_channel(pMgmt->pAdapter, pMgmt->uIBSSChannel);
+	pMgmt->uCurrChannel = pMgmt->uIBSSChannel;
+
+	if (CARDbIsShortPreamble(pMgmt->pAdapter)) {
+		pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SHORTPREAMBLE(1);
+	} else {
+		pMgmt->wCurrCapInfo &= (~WLAN_SET_CAP_INFO_SHORTPREAMBLE(1));
+	}
 
+	if ((pMgmt->b11hEnable == true) &&
+	    (pMgmt->eCurrentPHYMode == PHY_TYPE_11A)) {
+		pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SPECTRUMMNG(1);
+	} else {
+		pMgmt->wCurrCapInfo &= (~WLAN_SET_CAP_INFO_SPECTRUMMNG(1));
+	}
+
+	pMgmt->eCurrState = WMAC_STATE_STARTED;
+	// Prepare beacon to send
+	if (bMgrPrepareBeaconToSend((void *)pDevice, pMgmt)) {
+		*pStatus = CMD_STATUS_SUCCESS;
+	}
 
+	return;
+}
 
 /*+
  *
@@ -2638,260 +2506,244 @@ vMgrCreateOwnIBSS(
  * Return Value:
  *    None.
  *
--*/
+ -*/
 
 void
 vMgrJoinBSSBegin(
-    void *hDeviceContext,
-    PCMD_STATUS pStatus
-    )
+	void *hDeviceContext,
+	PCMD_STATUS pStatus
+)
 {
+	PSDevice     pDevice = (PSDevice)hDeviceContext;
+	PSMgmtObject    pMgmt = pDevice->pMgmt;
+	PKnownBSS       pCurr = NULL;
+	unsigned int ii, uu;
+	PWLAN_IE_SUPP_RATES pItemRates = NULL;
+	PWLAN_IE_SUPP_RATES pItemExtRates = NULL;
+	PWLAN_IE_SSID   pItemSSID;
+	unsigned int uRateLen = WLAN_RATES_MAXLEN;
+	unsigned short wMaxBasicRate = RATE_1M;
+	unsigned short wMaxSuppRate = RATE_1M;
+	unsigned short wSuppRate;
+	unsigned char byTopCCKBasicRate = RATE_1M;
+	unsigned char byTopOFDMBasicRate = RATE_1M;
+
+	for (ii = 0; ii < MAX_BSS_NUM; ii++) {
+		if (pMgmt->sBSSList[ii].bActive == true)
+			break;
+	}
+
+	if (ii == MAX_BSS_NUM) {
+		*pStatus = CMD_STATUS_RESOURCES;
+		DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "BSS finding:BSS list is empty.\n");
+		return;
+	}
+
+	// memset(pMgmt->abyDesireBSSID, 0,  WLAN_BSSID_LEN);
+	// Search known BSS list for prefer BSSID or SSID
 
-    PSDevice     pDevice = (PSDevice)hDeviceContext;
-    PSMgmtObject    pMgmt = pDevice->pMgmt;
-    PKnownBSS       pCurr = NULL;
-    unsigned int ii, uu;
-    PWLAN_IE_SUPP_RATES pItemRates = NULL;
-    PWLAN_IE_SUPP_RATES pItemExtRates = NULL;
-    PWLAN_IE_SSID   pItemSSID;
-    unsigned int uRateLen = WLAN_RATES_MAXLEN;
-    unsigned short wMaxBasicRate = RATE_1M;
-    unsigned short wMaxSuppRate = RATE_1M;
-    unsigned short wSuppRate;
-    unsigned char byTopCCKBasicRate = RATE_1M;
-    unsigned char byTopOFDMBasicRate = RATE_1M;
-
-
-    for (ii = 0; ii < MAX_BSS_NUM; ii++) {
-        if (pMgmt->sBSSList[ii].bActive == true)
-            break;
-    }
-
-    if (ii == MAX_BSS_NUM) {
-       *pStatus = CMD_STATUS_RESOURCES;
-        DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "BSS finding:BSS list is empty.\n");
-       return;
-    }
-
-    // memset(pMgmt->abyDesireBSSID, 0,  WLAN_BSSID_LEN);
-    // Search known BSS list for prefer BSSID or SSID
-
-    pCurr = BSSpSearchBSSList(pDevice,
-                              pMgmt->abyDesireBSSID,
-                              pMgmt->abyDesireSSID,
-                              pMgmt->eConfigPHYMode
-                              );
-
-    if (pCurr == NULL){
-       *pStatus = CMD_STATUS_RESOURCES;
-       pItemSSID = (PWLAN_IE_SSID)pMgmt->abyDesireSSID;
-       DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Scanning [%s] not found, disconnected !\n", pItemSSID->abySSID);
-       return;
-    }
-
-    DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "AP(BSS) finding:Found a AP(BSS)..\n");
-    if (WLAN_GET_CAP_INFO_ESS(cpu_to_le16(pCurr->wCapInfo))){
-
-        if ((pMgmt->eAuthenMode == WMAC_AUTH_WPA)||(pMgmt->eAuthenMode == WMAC_AUTH_WPAPSK)) {
-
-    // patch for CISCO migration mode
+	pCurr = BSSpSearchBSSList(pDevice,
+				  pMgmt->abyDesireBSSID,
+				  pMgmt->abyDesireSSID,
+				  pMgmt->eConfigPHYMode
+);
+
+	if (pCurr == NULL) {
+		*pStatus = CMD_STATUS_RESOURCES;
+		pItemSSID = (PWLAN_IE_SSID)pMgmt->abyDesireSSID;
+		DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Scanning [%s] not found, disconnected !\n", pItemSSID->abySSID);
+		return;
+	}
+
+	DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "AP(BSS) finding:Found a AP(BSS)..\n");
+	if (WLAN_GET_CAP_INFO_ESS(cpu_to_le16(pCurr->wCapInfo))) {
+		if ((pMgmt->eAuthenMode == WMAC_AUTH_WPA) || (pMgmt->eAuthenMode == WMAC_AUTH_WPAPSK)) {
+			// patch for CISCO migration mode
 /*
-            if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) {
-                if (WPA_SearchRSN(0, WPA_TKIP, pCurr) == false) {
-                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"No match RSN info. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
-                    // encryption mode error
-                    pMgmt->eCurrState = WMAC_STATE_IDLE;
-                    return;
-                }
-            } else if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) {
-                if (WPA_SearchRSN(0, WPA_AESCCMP, pCurr) == false) {
-                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"No match RSN info. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
-                    // encryption mode error
-                    pMgmt->eCurrState = WMAC_STATE_IDLE;
-                    return;
-                }
-            }
+  if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) {
+  if (WPA_SearchRSN(0, WPA_TKIP, pCurr) == false) {
+  DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "No match RSN info. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
+  // encryption mode error
+  pMgmt->eCurrState = WMAC_STATE_IDLE;
+  return;
+  }
+  } else if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) {
+  if (WPA_SearchRSN(0, WPA_AESCCMP, pCurr) == false) {
+  DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "No match RSN info. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
+  // encryption mode error
+  pMgmt->eCurrState = WMAC_STATE_IDLE;
+  return;
+  }
+  }
 */
-        }
+		}
 
 #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
-	//if(pDevice->bWPASuppWextEnabled == true)
-            Encyption_Rebuild(pDevice, pCurr);
+		Encyption_Rebuild(pDevice, pCurr);
 #endif
-        // Infrastructure BSS
-        s_vMgrSynchBSS(pDevice,
-                       WMAC_MODE_ESS_STA,
-                       pCurr,
-                       pStatus
-                       );
-
-        if (*pStatus == CMD_STATUS_SUCCESS){
-
-            // Adopt this BSS state vars in Mgmt Object
-            pMgmt->uCurrChannel = pCurr->uChannel;
-
-            memset(pMgmt->abyCurrSuppRates, 0 , WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1);
-            memset(pMgmt->abyCurrExtSuppRates, 0 , WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1);
-
-            if (pCurr->eNetworkTypeInUse == PHY_TYPE_11B) {
-                uRateLen = WLAN_RATES_MAXLEN_11B;
-            }
-
-            pItemRates = (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates;
-            pItemExtRates = (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates;
-
-            // Parse Support Rate IE
-            pItemRates->byElementID = WLAN_EID_SUPP_RATES;
-            pItemRates->len = RATEuSetIE((PWLAN_IE_SUPP_RATES)pCurr->abySuppRates,
-                                         pItemRates,
-                                         uRateLen);
-
-            // Parse Extension Support Rate IE
-            pItemExtRates->byElementID = WLAN_EID_EXTSUPP_RATES;
-            pItemExtRates->len = RATEuSetIE((PWLAN_IE_SUPP_RATES)pCurr->abyExtSuppRates,
-                                            pItemExtRates,
-                                            uRateLen);
-            // Stuffing Rate IE
-            if ((pItemExtRates->len > 0) && (pItemRates->len < 8)) {
-                for (ii = 0; ii < (unsigned int)(8 - pItemRates->len); ) {
-                    pItemRates->abyRates[pItemRates->len + ii] = pItemExtRates->abyRates[ii];
-                    ii ++;
-                    if (pItemExtRates->len <= ii)
-                        break;
-                }
-                pItemRates->len += (unsigned char)ii;
-                if (pItemExtRates->len - ii > 0) {
-                    pItemExtRates->len -= (unsigned char)ii;
-                    for (uu = 0; uu < pItemExtRates->len; uu ++) {
-                        pItemExtRates->abyRates[uu] = pItemExtRates->abyRates[uu + ii];
-                    }
-                } else {
-                    pItemExtRates->len = 0;
-                }
-            }
-
-            RATEvParseMaxRate((void *)pDevice, pItemRates, pItemExtRates, true,
-                              &wMaxBasicRate, &wMaxSuppRate, &wSuppRate,
-                              &byTopCCKBasicRate, &byTopOFDMBasicRate);
-
-            // TODO: deal with if wCapInfo the privacy is on, but station WEP is off
-            // TODO: deal with if wCapInfo the PS-Pollable is on.
-            pMgmt->wCurrBeaconPeriod = pCurr->wBeaconInterval;
-            memset(pMgmt->abyCurrSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
-            memcpy(pMgmt->abyCurrBSSID, pCurr->abyBSSID, WLAN_BSSID_LEN);
-            memcpy(pMgmt->abyCurrSSID, pCurr->abySSID, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
-
-            pMgmt->eCurrMode = WMAC_MODE_ESS_STA;
-
-            pMgmt->eCurrState = WMAC_STATE_JOINTED;
-            // Adopt BSS state in Adapter Device Object
-            //pDevice->byOpMode = OP_MODE_INFRASTRUCTURE;
+		// Infrastructure BSS
+		s_vMgrSynchBSS(pDevice,
+			       WMAC_MODE_ESS_STA,
+			       pCurr,
+			       pStatus
+);
+
+		if (*pStatus == CMD_STATUS_SUCCESS) {
+			// Adopt this BSS state vars in Mgmt Object
+			pMgmt->uCurrChannel = pCurr->uChannel;
+
+			memset(pMgmt->abyCurrSuppRates, 0 , WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1);
+			memset(pMgmt->abyCurrExtSuppRates, 0 , WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1);
+
+			if (pCurr->eNetworkTypeInUse == PHY_TYPE_11B) {
+				uRateLen = WLAN_RATES_MAXLEN_11B;
+			}
+
+			pItemRates = (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates;
+			pItemExtRates = (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates;
+
+			// Parse Support Rate IE
+			pItemRates->byElementID = WLAN_EID_SUPP_RATES;
+			pItemRates->len = RATEuSetIE((PWLAN_IE_SUPP_RATES)pCurr->abySuppRates,
+						     pItemRates,
+						     uRateLen);
+
+			// Parse Extension Support Rate IE
+			pItemExtRates->byElementID = WLAN_EID_EXTSUPP_RATES;
+			pItemExtRates->len = RATEuSetIE((PWLAN_IE_SUPP_RATES)pCurr->abyExtSuppRates,
+							pItemExtRates,
+							uRateLen);
+			// Stuffing Rate IE
+			if ((pItemExtRates->len > 0) && (pItemRates->len < 8)) {
+				for (ii = 0; ii < (unsigned int)(8 - pItemRates->len);) {
+					pItemRates->abyRates[pItemRates->len + ii] = pItemExtRates->abyRates[ii];
+					ii++;
+					if (pItemExtRates->len <= ii)
+						break;
+				}
+				pItemRates->len += (unsigned char)ii;
+				if (pItemExtRates->len - ii > 0) {
+					pItemExtRates->len -= (unsigned char)ii;
+					for (uu = 0; uu < pItemExtRates->len; uu++) {
+						pItemExtRates->abyRates[uu] = pItemExtRates->abyRates[uu + ii];
+					}
+				} else {
+					pItemExtRates->len = 0;
+				}
+			}
+
+			RATEvParseMaxRate((void *)pDevice, pItemRates, pItemExtRates, true,
+					  &wMaxBasicRate, &wMaxSuppRate, &wSuppRate,
+					  &byTopCCKBasicRate, &byTopOFDMBasicRate);
+
+			// TODO: deal with if wCapInfo the privacy is on, but station WEP is off
+			// TODO: deal with if wCapInfo the PS-Pollable is on.
+			pMgmt->wCurrBeaconPeriod = pCurr->wBeaconInterval;
+			memset(pMgmt->abyCurrSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
+			memcpy(pMgmt->abyCurrBSSID, pCurr->abyBSSID, WLAN_BSSID_LEN);
+			memcpy(pMgmt->abyCurrSSID, pCurr->abySSID, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
+
+			pMgmt->eCurrMode = WMAC_MODE_ESS_STA;
+
+			pMgmt->eCurrState = WMAC_STATE_JOINTED;
+			// Adopt BSS state in Adapter Device Object
+			//pDevice->byOpMode = OP_MODE_INFRASTRUCTURE;
 //            memcpy(pDevice->abyBSSID, pCurr->abyBSSID, WLAN_BSSID_LEN);
 
-            // Add current BSS to Candidate list
-            // This should only works for WPA2 BSS, and WPA2 BSS check must be done before.
-            if (pMgmt->eAuthenMode == WMAC_AUTH_WPA2) {
-                bool bResult = bAdd_PMKID_Candidate((void *)pDevice, pMgmt->abyCurrBSSID, &pCurr->sRSNCapObj);
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"bAdd_PMKID_Candidate: 1(%d)\n", bResult);
-                if (bResult == false) {
-                    vFlush_PMKID_Candidate((void *)pDevice);
-                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"vFlush_PMKID_Candidate: 4\n");
-                    bAdd_PMKID_Candidate((void *)pDevice, pMgmt->abyCurrBSSID, &pCurr->sRSNCapObj);
-                }
-            }
-
-            // Preamble type auto-switch: if AP can receive short-preamble cap,
-            // we can turn on too.
-
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Join ESS\n");
-
-
-
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"End of Join AP -- A/B/G Action\n");
-        }
-        else {
-            pMgmt->eCurrState = WMAC_STATE_IDLE;
-        };
-
-
-     }
-     else {
-        // ad-hoc mode BSS
-        if (pMgmt->eAuthenMode == WMAC_AUTH_WPANONE) {
-
-            if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) {
-                if (WPA_SearchRSN(0, WPA_TKIP, pCurr) == false) {
-                    // encryption mode error
-                    pMgmt->eCurrState = WMAC_STATE_IDLE;
-                    return;
-                }
-            } else if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) {
-                if (WPA_SearchRSN(0, WPA_AESCCMP, pCurr) == false) {
-                    // encryption mode error
-                    pMgmt->eCurrState = WMAC_STATE_IDLE;
-                    return;
-                }
-            } else {
-                // encryption mode error
-                pMgmt->eCurrState = WMAC_STATE_IDLE;
-                return;
-            }
-        }
-
-        s_vMgrSynchBSS(pDevice,
-                       WMAC_MODE_IBSS_STA,
-                       pCurr,
-                       pStatus
-                       );
-
-        if (*pStatus == CMD_STATUS_SUCCESS){
-            // Adopt this BSS state vars in Mgmt Object
-            // TODO: check if CapInfo privacy on, but we don't..
-            pMgmt->uCurrChannel = pCurr->uChannel;
-
-
-            // Parse Support Rate IE
-            pMgmt->abyCurrSuppRates[0] = WLAN_EID_SUPP_RATES;
-            pMgmt->abyCurrSuppRates[1] = RATEuSetIE((PWLAN_IE_SUPP_RATES)pCurr->abySuppRates,
-                                                    (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates,
-                                                    WLAN_RATES_MAXLEN_11B);
-            // set basic rate
-            RATEvParseMaxRate((void *)pDevice, (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates,
-                              NULL, true, &wMaxBasicRate, &wMaxSuppRate, &wSuppRate,
-                              &byTopCCKBasicRate, &byTopOFDMBasicRate);
-
-            pMgmt->wCurrCapInfo = pCurr->wCapInfo;
-            pMgmt->wCurrBeaconPeriod = pCurr->wBeaconInterval;
-            memset(pMgmt->abyCurrSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN);
-            memcpy(pMgmt->abyCurrBSSID, pCurr->abyBSSID, WLAN_BSSID_LEN);
-            memcpy(pMgmt->abyCurrSSID, pCurr->abySSID, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN);
+			// Add current BSS to Candidate list
+			// This should only works for WPA2 BSS, and WPA2 BSS check must be done before.
+			if (pMgmt->eAuthenMode == WMAC_AUTH_WPA2) {
+				bool bResult = bAdd_PMKID_Candidate((void *)pDevice, pMgmt->abyCurrBSSID, &pCurr->sRSNCapObj);
+				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "bAdd_PMKID_Candidate: 1(%d)\n", bResult);
+				if (bResult == false) {
+					vFlush_PMKID_Candidate((void *)pDevice);
+					DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "vFlush_PMKID_Candidate: 4\n");
+					bAdd_PMKID_Candidate((void *)pDevice, pMgmt->abyCurrBSSID, &pCurr->sRSNCapObj);
+				}
+			}
+
+			// Preamble type auto-switch: if AP can receive short-preamble cap,
+			// we can turn on too.
+
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Join ESS\n");
+
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "End of Join AP -- A/B/G Action\n");
+		} else {
+			pMgmt->eCurrState = WMAC_STATE_IDLE;
+		};
+
+	} else {
+		// ad-hoc mode BSS
+		if (pMgmt->eAuthenMode == WMAC_AUTH_WPANONE) {
+			if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) {
+				if (WPA_SearchRSN(0, WPA_TKIP, pCurr) == false) {
+					// encryption mode error
+					pMgmt->eCurrState = WMAC_STATE_IDLE;
+					return;
+				}
+			} else if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) {
+				if (WPA_SearchRSN(0, WPA_AESCCMP, pCurr) == false) {
+					// encryption mode error
+					pMgmt->eCurrState = WMAC_STATE_IDLE;
+					return;
+				}
+			} else {
+				// encryption mode error
+				pMgmt->eCurrState = WMAC_STATE_IDLE;
+				return;
+			}
+		}
+
+		s_vMgrSynchBSS(pDevice,
+			       WMAC_MODE_IBSS_STA,
+			       pCurr,
+			       pStatus
+);
+
+		if (*pStatus == CMD_STATUS_SUCCESS) {
+			// Adopt this BSS state vars in Mgmt Object
+			// TODO: check if CapInfo privacy on, but we don't..
+			pMgmt->uCurrChannel = pCurr->uChannel;
+
+			// Parse Support Rate IE
+			pMgmt->abyCurrSuppRates[0] = WLAN_EID_SUPP_RATES;
+			pMgmt->abyCurrSuppRates[1] = RATEuSetIE((PWLAN_IE_SUPP_RATES)pCurr->abySuppRates,
+								(PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates,
+								WLAN_RATES_MAXLEN_11B);
+			// set basic rate
+			RATEvParseMaxRate((void *)pDevice, (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates,
+					  NULL, true, &wMaxBasicRate, &wMaxSuppRate, &wSuppRate,
+					  &byTopCCKBasicRate, &byTopOFDMBasicRate);
+
+			pMgmt->wCurrCapInfo = pCurr->wCapInfo;
+			pMgmt->wCurrBeaconPeriod = pCurr->wBeaconInterval;
+			memset(pMgmt->abyCurrSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN);
+			memcpy(pMgmt->abyCurrBSSID, pCurr->abyBSSID, WLAN_BSSID_LEN);
+			memcpy(pMgmt->abyCurrSSID, pCurr->abySSID, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN);
 //          pMgmt->wCurrATIMWindow = pCurr->wATIMWindow;
-            MACvWriteATIMW(pDevice->PortOffset, pMgmt->wCurrATIMWindow);
-            pMgmt->eCurrMode = WMAC_MODE_IBSS_STA;
+			MACvWriteATIMW(pDevice->PortOffset, pMgmt->wCurrATIMWindow);
+			pMgmt->eCurrMode = WMAC_MODE_IBSS_STA;
 
-            pMgmt->eCurrState = WMAC_STATE_STARTED;
-            // Adopt BSS state in Adapter Device Object
-            //pDevice->byOpMode = OP_MODE_ADHOC;
+			pMgmt->eCurrState = WMAC_STATE_STARTED;
+			// Adopt BSS state in Adapter Device Object
+			//pDevice->byOpMode = OP_MODE_ADHOC;
 //            pDevice->bLinkPass = true;
 //            memcpy(pDevice->abyBSSID, pCurr->abyBSSID, WLAN_BSSID_LEN);
 
-		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Join IBSS ok:%pM\n",
-			pMgmt->abyCurrBSSID);
-            // Preamble type auto-switch: if AP can receive short-preamble cap,
-            // and if registry setting is short preamble we can turn on too.
-
-            // Prepare beacon
-            bMgrPrepareBeaconToSend((void *)pDevice, pMgmt);
-        }
-        else {
-            pMgmt->eCurrState = WMAC_STATE_IDLE;
-        };
-     };
-    return;
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Join IBSS ok:%pM\n",
+				pMgmt->abyCurrBSSID);
+			// Preamble type auto-switch: if AP can receive short-preamble cap,
+			// and if registry setting is short preamble we can turn on too.
+
+			// Prepare beacon
+			bMgrPrepareBeaconToSend((void *)pDevice, pMgmt);
+		} else {
+			pMgmt->eCurrState = WMAC_STATE_IDLE;
+		};
+	};
+	return;
 }
 
-
-
 /*+
  *
  * Routine Description:
@@ -2901,215 +2753,199 @@ vMgrJoinBSSBegin(
  * Return Value:
  *    PCM_STATUS
  *
--*/
+ -*/
 static
 void
-s_vMgrSynchBSS (
-    PSDevice      pDevice,
-    unsigned int uBSSMode,
-    PKnownBSS     pCurr,
-    PCMD_STATUS  pStatus
-    )
+s_vMgrSynchBSS(
+	PSDevice      pDevice,
+	unsigned int uBSSMode,
+	PKnownBSS     pCurr,
+	PCMD_STATUS  pStatus
+)
 {
-    CARD_PHY_TYPE   ePhyType = PHY_TYPE_11B;
-    PSMgmtObject  pMgmt = pDevice->pMgmt;
+	CARD_PHY_TYPE   ePhyType = PHY_TYPE_11B;
+	PSMgmtObject  pMgmt = pDevice->pMgmt;
 //    int     ii;
-                                                     //1M,   2M,   5M,   11M,  18M,  24M,  36M,  54M
-    unsigned char abyCurrSuppRatesG[] = {WLAN_EID_SUPP_RATES, 8, 0x02, 0x04, 0x0B, 0x16, 0x24, 0x30, 0x48, 0x6C};
-    unsigned char abyCurrExtSuppRatesG[] = {WLAN_EID_EXTSUPP_RATES, 4, 0x0C, 0x12, 0x18, 0x60};
-                                                           //6M,   9M,   12M,  48M
-    unsigned char abyCurrSuppRatesA[] = {WLAN_EID_SUPP_RATES, 8, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6C};
-    unsigned char abyCurrSuppRatesB[] = {WLAN_EID_SUPP_RATES, 4, 0x02, 0x04, 0x0B, 0x16};
-
-
-    *pStatus = CMD_STATUS_FAILURE;
-
-    if (s_bCipherMatch(pCurr,
-                       pDevice->eEncryptionStatus,
-                       &(pMgmt->byCSSPK),
-                       &(pMgmt->byCSSGK)) == false) {
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "s_bCipherMatch Fail .......\n");
-        return;
-    }
-
-    pMgmt->pCurrBSS = pCurr;
-
-    // if previous mode is IBSS.
-    if(pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) {
-        MACvRegBitsOff(pDevice->PortOffset, MAC_REG_BCNDMACTL, BEACON_READY);
-        MACvRegBitsOff(pDevice->PortOffset, MAC_REG_TCR, TCR_AUTOBCNTX);
-    }
-
-    // Init the BSS informations
-    pDevice->bCCK = true;
-    pDevice->bProtectMode = false;
-    MACvDisableProtectMD(pDevice->PortOffset);
-    pDevice->bBarkerPreambleMd = false;
-    MACvDisableBarkerPreambleMd(pDevice->PortOffset);
-    pDevice->bNonERPPresent = false;
-    pDevice->byPreambleType = 0;
-    pDevice->wBasicRate = 0;
-    // Set Basic Rate
-    CARDbAddBasicRate((void *)pDevice, RATE_1M);
-    // calculate TSF offset
-    // TSF Offset = Received Timestamp TSF - Marked Local's TSF
-    CARDbUpdateTSF(pDevice, pCurr->byRxRate, pCurr->qwBSSTimestamp, pCurr->qwLocalTSF);
-
-    CARDbSetBeaconPeriod(pDevice, pCurr->wBeaconInterval);
-
-    // set Next TBTT
-    // Next TBTT = ((local_current_TSF / beacon_interval) + 1 ) * beacon_interval
-    CARDvSetFirstNextTBTT(pDevice->PortOffset, pCurr->wBeaconInterval);
-
-    // set BSSID
-    MACvWriteBSSIDAddress(pDevice->PortOffset, pCurr->abyBSSID);
-
-    MACvReadBSSIDAddress(pDevice->PortOffset, pMgmt->abyCurrBSSID);
+	//1M,   2M,   5M,   11M,  18M,  24M,  36M,  54M
+	unsigned char abyCurrSuppRatesG[] = {WLAN_EID_SUPP_RATES, 8, 0x02, 0x04, 0x0B, 0x16, 0x24, 0x30, 0x48, 0x6C};
+	unsigned char abyCurrExtSuppRatesG[] = {WLAN_EID_EXTSUPP_RATES, 4, 0x0C, 0x12, 0x18, 0x60};
+	//6M,   9M,   12M,  48M
+	unsigned char abyCurrSuppRatesA[] = {WLAN_EID_SUPP_RATES, 8, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6C};
+	unsigned char abyCurrSuppRatesB[] = {WLAN_EID_SUPP_RATES, 4, 0x02, 0x04, 0x0B, 0x16};
+
+	*pStatus = CMD_STATUS_FAILURE;
+
+	if (s_bCipherMatch(pCurr,
+			   pDevice->eEncryptionStatus,
+			   &(pMgmt->byCSSPK),
+			   &(pMgmt->byCSSGK)) == false) {
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "s_bCipherMatch Fail .......\n");
+		return;
+	}
+
+	pMgmt->pCurrBSS = pCurr;
+
+	// if previous mode is IBSS.
+	if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) {
+		MACvRegBitsOff(pDevice->PortOffset, MAC_REG_BCNDMACTL, BEACON_READY);
+		MACvRegBitsOff(pDevice->PortOffset, MAC_REG_TCR, TCR_AUTOBCNTX);
+	}
+
+	// Init the BSS informations
+	pDevice->bCCK = true;
+	pDevice->bProtectMode = false;
+	MACvDisableProtectMD(pDevice->PortOffset);
+	pDevice->bBarkerPreambleMd = false;
+	MACvDisableBarkerPreambleMd(pDevice->PortOffset);
+	pDevice->bNonERPPresent = false;
+	pDevice->byPreambleType = 0;
+	pDevice->wBasicRate = 0;
+	// Set Basic Rate
+	CARDbAddBasicRate((void *)pDevice, RATE_1M);
+	// calculate TSF offset
+	// TSF Offset = Received Timestamp TSF - Marked Local's TSF
+	CARDbUpdateTSF(pDevice, pCurr->byRxRate, pCurr->qwBSSTimestamp, pCurr->qwLocalTSF);
+
+	CARDbSetBeaconPeriod(pDevice, pCurr->wBeaconInterval);
+
+	// set Next TBTT
+	// Next TBTT = ((local_current_TSF / beacon_interval) + 1) * beacon_interval
+	CARDvSetFirstNextTBTT(pDevice->PortOffset, pCurr->wBeaconInterval);
+
+	// set BSSID
+	MACvWriteBSSIDAddress(pDevice->PortOffset, pCurr->abyBSSID);
+
+	MACvReadBSSIDAddress(pDevice->PortOffset, pMgmt->abyCurrBSSID);
 
 	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Sync:set CurrBSSID address = "
 		"%pM\n", pMgmt->abyCurrBSSID);
 
-    if (pCurr->eNetworkTypeInUse == PHY_TYPE_11A) {
-        if ((pMgmt->eConfigPHYMode == PHY_TYPE_11A) ||
-            (pMgmt->eConfigPHYMode == PHY_TYPE_AUTO)) {
-            ePhyType = PHY_TYPE_11A;
-        } else {
-            return;
-        }
-    } else if (pCurr->eNetworkTypeInUse == PHY_TYPE_11B) {
-        if ((pMgmt->eConfigPHYMode == PHY_TYPE_11B) ||
-            (pMgmt->eConfigPHYMode == PHY_TYPE_11G) ||
-            (pMgmt->eConfigPHYMode == PHY_TYPE_AUTO)) {
-            ePhyType = PHY_TYPE_11B;
-        } else {
-            return;
-        }
-    } else {
-        if ((pMgmt->eConfigPHYMode == PHY_TYPE_11G) ||
-            (pMgmt->eConfigPHYMode == PHY_TYPE_AUTO)) {
-            ePhyType = PHY_TYPE_11G;
-        } else if (pMgmt->eConfigPHYMode == PHY_TYPE_11B) {
-            ePhyType = PHY_TYPE_11B;
-        } else {
-            return;
-        }
-    }
-
-    if (ePhyType == PHY_TYPE_11A) {
-        memcpy(pMgmt->abyCurrSuppRates, &abyCurrSuppRatesA[0], sizeof(abyCurrSuppRatesA));
-        pMgmt->abyCurrExtSuppRates[1] = 0;
-    } else if (ePhyType == PHY_TYPE_11B) {
-        memcpy(pMgmt->abyCurrSuppRates, &abyCurrSuppRatesB[0], sizeof(abyCurrSuppRatesB));
-        pMgmt->abyCurrExtSuppRates[1] = 0;
-    } else {
-        memcpy(pMgmt->abyCurrSuppRates, &abyCurrSuppRatesG[0], sizeof(abyCurrSuppRatesG));
-        memcpy(pMgmt->abyCurrExtSuppRates, &abyCurrExtSuppRatesG[0], sizeof(abyCurrExtSuppRatesG));
-    }
-
-
-    if (WLAN_GET_CAP_INFO_ESS(pCurr->wCapInfo)) {
-        CARDbSetBSSID(pMgmt->pAdapter, pCurr->abyBSSID, OP_MODE_INFRASTRUCTURE);
-        // Add current BSS to Candidate list
-        // This should only works for WPA2 BSS, and WPA2 BSS check must be done before.
-        if (pMgmt->eAuthenMode == WMAC_AUTH_WPA2) {
-            CARDbAdd_PMKID_Candidate(pMgmt->pAdapter, pMgmt->abyCurrBSSID, pCurr->sRSNCapObj.bRSNCapExist, pCurr->sRSNCapObj.wRSNCap);
-        }
-    } else {
-        CARDbSetBSSID(pMgmt->pAdapter, pCurr->abyBSSID, OP_MODE_ADHOC);
-    }
-
-    if (CARDbSetPhyParameter(   pMgmt->pAdapter,
-                                ePhyType,
-                                pCurr->wCapInfo,
-                                pCurr->sERP.byERP,
-                                pMgmt->abyCurrSuppRates,
-                                pMgmt->abyCurrExtSuppRates
-                            ) != true) {
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "<----s_bSynchBSS Set Phy Mode Fail [%d]\n", ePhyType);
-        return;
-    }
-    // set channel and clear NAV
-    if (set_channel(pMgmt->pAdapter, pCurr->uChannel) == false) {
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "<----s_bSynchBSS Set Channel [%d]\n", pCurr->uChannel);
-        return;
-    }
+	if (pCurr->eNetworkTypeInUse == PHY_TYPE_11A) {
+		if ((pMgmt->eConfigPHYMode == PHY_TYPE_11A) ||
+		    (pMgmt->eConfigPHYMode == PHY_TYPE_AUTO)) {
+			ePhyType = PHY_TYPE_11A;
+		} else {
+			return;
+		}
+	} else if (pCurr->eNetworkTypeInUse == PHY_TYPE_11B) {
+		if ((pMgmt->eConfigPHYMode == PHY_TYPE_11B) ||
+		    (pMgmt->eConfigPHYMode == PHY_TYPE_11G) ||
+		    (pMgmt->eConfigPHYMode == PHY_TYPE_AUTO)) {
+			ePhyType = PHY_TYPE_11B;
+		} else {
+			return;
+		}
+	} else {
+		if ((pMgmt->eConfigPHYMode == PHY_TYPE_11G) ||
+		    (pMgmt->eConfigPHYMode == PHY_TYPE_AUTO)) {
+			ePhyType = PHY_TYPE_11G;
+		} else if (pMgmt->eConfigPHYMode == PHY_TYPE_11B) {
+			ePhyType = PHY_TYPE_11B;
+		} else {
+			return;
+		}
+	}
 
-/*
-    for (ii=0;ii<BB_VGA_LEVEL;ii++) {
-        if (pCurr->ldBmMAX< pDevice->ldBmThreshold[ii]) {
-            pDevice->byBBVGANew = pDevice->abyBBVGA[ii];
-            break;
-        }
-    }
-
-    if (pDevice->byBBVGANew != pDevice->byBBVGACurrent) {
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"RSSI[%d] NewGain[%d] OldGain[%d] \n",
-                        (int)pCurr->ldBmMAX, pDevice->byBBVGANew, pDevice->byBBVGACurrent);
-        printk("RSSI[%d] NewGain[%d] OldGain[%d] \n",
-                        (int)pCurr->ldBmMAX, pDevice->byBBVGANew, pDevice->byBBVGACurrent);
-        BBvSetVGAGainOffset(pDevice, pDevice->byBBVGANew);
-    }
-    printk("ldBmMAX[%d] NewGain[%d] OldGain[%d] \n",
-           (int)pCurr->ldBmMAX, pDevice->byBBVGANew, pDevice->byBBVGACurrent);
-*/
-    pMgmt->uCurrChannel = pCurr->uChannel;
-    pMgmt->eCurrentPHYMode = ePhyType;
-    pMgmt->byERPContext = pCurr->sERP.byERP;
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Sync:Set to channel = [%d]\n", (int)pCurr->uChannel);
+	if (ePhyType == PHY_TYPE_11A) {
+		memcpy(pMgmt->abyCurrSuppRates, &abyCurrSuppRatesA[0], sizeof(abyCurrSuppRatesA));
+		pMgmt->abyCurrExtSuppRates[1] = 0;
+	} else if (ePhyType == PHY_TYPE_11B) {
+		memcpy(pMgmt->abyCurrSuppRates, &abyCurrSuppRatesB[0], sizeof(abyCurrSuppRatesB));
+		pMgmt->abyCurrExtSuppRates[1] = 0;
+	} else {
+		memcpy(pMgmt->abyCurrSuppRates, &abyCurrSuppRatesG[0], sizeof(abyCurrSuppRatesG));
+		memcpy(pMgmt->abyCurrExtSuppRates, &abyCurrExtSuppRatesG[0], sizeof(abyCurrExtSuppRatesG));
+	}
+
+	if (WLAN_GET_CAP_INFO_ESS(pCurr->wCapInfo)) {
+		CARDbSetBSSID(pMgmt->pAdapter, pCurr->abyBSSID, OP_MODE_INFRASTRUCTURE);
+		// Add current BSS to Candidate list
+		// This should only works for WPA2 BSS, and WPA2 BSS check must be done before.
+		if (pMgmt->eAuthenMode == WMAC_AUTH_WPA2) {
+			CARDbAdd_PMKID_Candidate(pMgmt->pAdapter, pMgmt->abyCurrBSSID, pCurr->sRSNCapObj.bRSNCapExist, pCurr->sRSNCapObj.wRSNCap);
+		}
+	} else {
+		CARDbSetBSSID(pMgmt->pAdapter, pCurr->abyBSSID, OP_MODE_ADHOC);
+	}
 
+	if (CARDbSetPhyParameter(pMgmt->pAdapter,
+				 ePhyType,
+				 pCurr->wCapInfo,
+				 pCurr->sERP.byERP,
+				 pMgmt->abyCurrSuppRates,
+				 pMgmt->abyCurrExtSuppRates
+		    ) != true) {
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "<----s_bSynchBSS Set Phy Mode Fail [%d]\n", ePhyType);
+		return;
+	}
+	// set channel and clear NAV
+	if (set_channel(pMgmt->pAdapter, pCurr->uChannel) == false) {
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "<----s_bSynchBSS Set Channel [%d]\n", pCurr->uChannel);
+		return;
+	}
 
-    *pStatus = CMD_STATUS_SUCCESS;
+/*
+  for (ii=0; ii<BB_VGA_LEVEL; ii++) {
+  if (pCurr->ldBmMAX< pDevice->ldBmThreshold[ii]) {
+  pDevice->byBBVGANew = pDevice->abyBBVGA[ii];
+  break;
+  }
+  }
 
+  if (pDevice->byBBVGANew != pDevice->byBBVGACurrent) {
+  DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "RSSI[%d] NewGain[%d] OldGain[%d] \n",
+  (int)pCurr->ldBmMAX, pDevice->byBBVGANew, pDevice->byBBVGACurrent);
+  printk("RSSI[%d] NewGain[%d] OldGain[%d] \n",
+  (int)pCurr->ldBmMAX, pDevice->byBBVGANew, pDevice->byBBVGACurrent);
+  BBvSetVGAGainOffset(pDevice, pDevice->byBBVGANew);
+  }
+  printk("ldBmMAX[%d] NewGain[%d] OldGain[%d] \n",
+  (int)pCurr->ldBmMAX, pDevice->byBBVGANew, pDevice->byBBVGACurrent);
+*/
+	pMgmt->uCurrChannel = pCurr->uChannel;
+	pMgmt->eCurrentPHYMode = ePhyType;
+	pMgmt->byERPContext = pCurr->sERP.byERP;
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Sync:Set to channel = [%d]\n", (int)pCurr->uChannel);
 
-    return;
+	*pStatus = CMD_STATUS_SUCCESS;
+
+	return;
 };
 
 //mike add: fix NetworkManager 0.7.0 hidden ssid mode in WPA encryption
 //                   ,need reset eAuthenMode and eEncryptionStatus
- static void  Encyption_Rebuild(
-    PSDevice pDevice,
-    PKnownBSS pCurr
- )
- {
-  PSMgmtObject  pMgmt = &(pDevice->sMgmtObj);
- // unsigned int ii , uSameBssidNum=0;
-
-        //  for (ii = 0; ii < MAX_BSS_NUM; ii++) {
-          //   if (pMgmt->sBSSList[ii].bActive &&
-            //      !compare_ether_addr(pMgmt->sBSSList[ii].abyBSSID, pCurr->abyBSSID)) {
-             //       uSameBssidNum++;
-               //   }
-           // }
-  //   if( uSameBssidNum>=2) {	 //we only check AP in hidden sssid  mode
-        if ((pMgmt->eAuthenMode == WMAC_AUTH_WPAPSK) ||           //networkmanager 0.7.0 does not give the pairwise-key selection,
-             (pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK)) {         // so we need re-select it according to real pairwise-key info.
-               if(pCurr->bWPAValid == true)  {   //WPA-PSK
-                          pMgmt->eAuthenMode = WMAC_AUTH_WPAPSK;
-		    if(pCurr->abyPKType[0] == WPA_TKIP) {
-     		        pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled;    //TKIP
-     		        PRINT_K("Encyption_Rebuild--->ssid reset config to [WPAPSK-TKIP]\n");
-		      }
-     		   else if(pCurr->abyPKType[0] == WPA_AESCCMP) {
-		        pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled;    //AES
-                          PRINT_K("Encyption_Rebuild--->ssid reset config to [WPAPSK-AES]\n");
-     		     }
-               	}
-               else if(pCurr->bWPA2Valid == true) {  //WPA2-PSK
-                         pMgmt->eAuthenMode = WMAC_AUTH_WPA2PSK;
-		       if(pCurr->abyCSSPK[0] == WLAN_11i_CSS_TKIP) {
-      		           pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled;     //TKIP
-                             PRINT_K("Encyption_Rebuild--->ssid reset config to [WPA2PSK-TKIP]\n");
-		       	}
-      		       else if(pCurr->abyCSSPK[0] == WLAN_11i_CSS_CCMP) {
-		           pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled;    //AES
-                            PRINT_K("Encyption_Rebuild--->ssid reset config to [WPA2PSK-AES]\n");
-      		       	}
-               	}
-              }
-        //  }
-      return;
- }
-
+static void  Encyption_Rebuild(
+	PSDevice pDevice,
+	PKnownBSS pCurr
+)
+{
+	PSMgmtObject  pMgmt = &(pDevice->sMgmtObj);
+
+	if ((pMgmt->eAuthenMode == WMAC_AUTH_WPAPSK) ||           //networkmanager 0.7.0 does not give the pairwise-key selection,
+	    (pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK)) {         // so we need re-select it according to real pairwise-key info.
+		if (pCurr->bWPAValid == true)  {   //WPA-PSK
+			pMgmt->eAuthenMode = WMAC_AUTH_WPAPSK;
+			if (pCurr->abyPKType[0] == WPA_TKIP) {
+				pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled;    //TKIP
+				PRINT_K("Encyption_Rebuild--->ssid reset config to [WPAPSK-TKIP]\n");
+			} else if (pCurr->abyPKType[0] == WPA_AESCCMP) {
+				pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled;    //AES
+				PRINT_K("Encyption_Rebuild--->ssid reset config to [WPAPSK-AES]\n");
+			}
+		} else if (pCurr->bWPA2Valid == true) {  //WPA2-PSK
+			pMgmt->eAuthenMode = WMAC_AUTH_WPA2PSK;
+			if (pCurr->abyCSSPK[0] == WLAN_11i_CSS_TKIP) {
+				pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled;     //TKIP
+				PRINT_K("Encyption_Rebuild--->ssid reset config to [WPA2PSK-TKIP]\n");
+			} else if (pCurr->abyCSSPK[0] == WLAN_11i_CSS_CCMP) {
+				pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled;    //AES
+				PRINT_K("Encyption_Rebuild--->ssid reset config to [WPA2PSK-AES]\n");
+			}
+		}
+	}
+	//  }
+	return;
+}
 
 /*+
  *
@@ -3120,298 +2956,290 @@ s_vMgrSynchBSS (
  * Return Value:
  *    void
  *
--*/
+ -*/
 
 static
 void
 s_vMgrFormatTIM(
-    PSMgmtObject pMgmt,
-    PWLAN_IE_TIM pTIM
-    )
+	PSMgmtObject pMgmt,
+	PWLAN_IE_TIM pTIM
+)
 {
-    unsigned char byMask[8] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80};
-    unsigned char byMap;
-    unsigned int ii, jj;
-    bool bStartFound = false;
-    bool bMulticast = false;
-    unsigned short wStartIndex = 0;
-    unsigned short wEndIndex = 0;
-
-
-    // Find size of partial virtual bitmap
-    for (ii = 0; ii < (MAX_NODE_NUM + 1); ii++) {
-        byMap = pMgmt->abyPSTxMap[ii];
-        if (!ii) {
-            // Mask out the broadcast bit which is indicated separately.
-            bMulticast = (byMap & byMask[0]) != 0;
-            if(bMulticast) {
-               pMgmt->sNodeDBTable[0].bRxPSPoll = true;
-            }
-            byMap = 0;
-        }
-        if (byMap) {
-            if (!bStartFound) {
-                bStartFound = true;
-                wStartIndex = ii;
-            }
-            wEndIndex = ii;
-        }
-    }
-
-
-    // Round start index down to nearest even number
-    wStartIndex &=  ~BIT0;
-
-    // Round end index up to nearest even number
-    wEndIndex = ((wEndIndex + 1) & ~BIT0);
-
-    // Size of element payload
-
-    pTIM->len =  3 + (wEndIndex - wStartIndex) + 1;
-
-    // Fill in the Fixed parts of the TIM
-    pTIM->byDTIMCount = pMgmt->byDTIMCount;
-    pTIM->byDTIMPeriod = pMgmt->byDTIMPeriod;
-    pTIM->byBitMapCtl = (bMulticast ? TIM_MULTICAST_MASK : 0) |
-        (((wStartIndex >> 1) << 1) & TIM_BITMAPOFFSET_MASK);
-
-    // Append variable part of TIM
-
-    for (ii = wStartIndex, jj =0 ; ii <= wEndIndex; ii++, jj++) {
-         pTIM->byVirtBitMap[jj] = pMgmt->abyPSTxMap[ii];
-    }
-
-    // Aid = 0 don't used.
-    pTIM->byVirtBitMap[0]  &= ~BIT0;
-}
+	unsigned char byMask[8] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80};
+	unsigned char byMap;
+	unsigned int ii, jj;
+	bool bStartFound = false;
+	bool bMulticast = false;
+	unsigned short wStartIndex = 0;
+	unsigned short wEndIndex = 0;
+
+	// Find size of partial virtual bitmap
+	for (ii = 0; ii < (MAX_NODE_NUM + 1); ii++) {
+		byMap = pMgmt->abyPSTxMap[ii];
+		if (!ii) {
+			// Mask out the broadcast bit which is indicated separately.
+			bMulticast = (byMap & byMask[0]) != 0;
+			if (bMulticast) {
+				pMgmt->sNodeDBTable[0].bRxPSPoll = true;
+			}
+			byMap = 0;
+		}
+		if (byMap) {
+			if (!bStartFound) {
+				bStartFound = true;
+				wStartIndex = ii;
+			}
+			wEndIndex = ii;
+		}
+	}
+
+	// Round start index down to nearest even number
+	wStartIndex &=  ~BIT0;
+
+	// Round end index up to nearest even number
+	wEndIndex = ((wEndIndex + 1) & ~BIT0);
+
+	// Size of element payload
+
+	pTIM->len =  3 + (wEndIndex - wStartIndex) + 1;
+
+	// Fill in the Fixed parts of the TIM
+	pTIM->byDTIMCount = pMgmt->byDTIMCount;
+	pTIM->byDTIMPeriod = pMgmt->byDTIMPeriod;
+	pTIM->byBitMapCtl = (bMulticast ? TIM_MULTICAST_MASK : 0) |
+		(((wStartIndex >> 1) << 1) & TIM_BITMAPOFFSET_MASK);
 
+	// Append variable part of TIM
+
+	for (ii = wStartIndex, jj = 0; ii <= wEndIndex; ii++, jj++) {
+		pTIM->byVirtBitMap[jj] = pMgmt->abyPSTxMap[ii];
+	}
+
+	// Aid = 0 don't used.
+	pTIM->byVirtBitMap[0]  &= ~BIT0;
+}
 
 /*+
  *
  * Routine Description:
- *  Constructs an Beacon frame( Ad-hoc mode)
+ *  Constructs an Beacon frame(Ad-hoc mode)
  *
  *
  * Return Value:
  *    PTR to frame; or NULL on allocation failure
  *
--*/
+ -*/
 
 static
 PSTxMgmtPacket
 s_MgrMakeBeacon(
-    PSDevice pDevice,
-    PSMgmtObject pMgmt,
-    unsigned short wCurrCapInfo,
-    unsigned short wCurrBeaconPeriod,
-    unsigned int uCurrChannel,
-    unsigned short wCurrATIMWinodw,
-    PWLAN_IE_SSID pCurrSSID,
-    unsigned char *pCurrBSSID,
-    PWLAN_IE_SUPP_RATES pCurrSuppRates,
-    PWLAN_IE_SUPP_RATES pCurrExtSuppRates
-    )
+	PSDevice pDevice,
+	PSMgmtObject pMgmt,
+	unsigned short wCurrCapInfo,
+	unsigned short wCurrBeaconPeriod,
+	unsigned int uCurrChannel,
+	unsigned short wCurrATIMWinodw,
+	PWLAN_IE_SSID pCurrSSID,
+	unsigned char *pCurrBSSID,
+	PWLAN_IE_SUPP_RATES pCurrSuppRates,
+	PWLAN_IE_SUPP_RATES pCurrExtSuppRates
+)
 {
-    PSTxMgmtPacket      pTxPacket = NULL;
-    WLAN_FR_BEACON      sFrame;
-    unsigned char abyBroadcastAddr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-    unsigned char *pbyBuffer;
-    unsigned int uLength = 0;
-    PWLAN_IE_IBSS_DFS   pIBSSDFS = NULL;
-    unsigned int ii;
-
-    // prepare beacon frame
-    pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool;
-    memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_BEACON_FR_MAXLEN);
-    pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket));
-    // Setup the sFrame structure.
-    sFrame.pBuf = (unsigned char *)pTxPacket->p80211Header;
-    sFrame.len = WLAN_BEACON_FR_MAXLEN;
-    vMgrEncodeBeacon(&sFrame);
-    // Setup the header
-    sFrame.pHdr->sA3.wFrameCtl = cpu_to_le16(
-        (
-        WLAN_SET_FC_FTYPE(WLAN_TYPE_MGR) |
-        WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_BEACON)
-        ));
-
-    if (pDevice->bEnablePSMode) {
-        sFrame.pHdr->sA3.wFrameCtl |= cpu_to_le16((unsigned short)WLAN_SET_FC_PWRMGT(1));
-    }
-
-    memcpy( sFrame.pHdr->sA3.abyAddr1, abyBroadcastAddr, WLAN_ADDR_LEN);
-    memcpy( sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN);
-    memcpy( sFrame.pHdr->sA3.abyAddr3, pCurrBSSID, WLAN_BSSID_LEN);
-    *sFrame.pwBeaconInterval = cpu_to_le16(wCurrBeaconPeriod);
-    *sFrame.pwCapInfo = cpu_to_le16(wCurrCapInfo);
-    // Copy SSID
-    sFrame.pSSID = (PWLAN_IE_SSID)(sFrame.pBuf + sFrame.len);
-    sFrame.len += ((PWLAN_IE_SSID)pMgmt->abyCurrSSID)->len + WLAN_IEHDR_LEN;
-    memcpy(sFrame.pSSID,
-             pCurrSSID,
-             ((PWLAN_IE_SSID)pCurrSSID)->len + WLAN_IEHDR_LEN
-            );
-    // Copy the rate set
-    sFrame.pSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len);
-    sFrame.len += ((PWLAN_IE_SUPP_RATES)pCurrSuppRates)->len + WLAN_IEHDR_LEN;
-    memcpy(sFrame.pSuppRates,
-           pCurrSuppRates,
-           ((PWLAN_IE_SUPP_RATES)pCurrSuppRates)->len + WLAN_IEHDR_LEN
-          );
-    // DS parameter
-    if (pDevice->eCurrentPHYType != PHY_TYPE_11A) {
-        sFrame.pDSParms = (PWLAN_IE_DS_PARMS)(sFrame.pBuf + sFrame.len);
-        sFrame.len += (1) + WLAN_IEHDR_LEN;
-        sFrame.pDSParms->byElementID = WLAN_EID_DS_PARMS;
-        sFrame.pDSParms->len = 1;
-        sFrame.pDSParms->byCurrChannel = (unsigned char)uCurrChannel;
-    }
-    // TIM field
-    if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) {
-        sFrame.pTIM = (PWLAN_IE_TIM)(sFrame.pBuf + sFrame.len);
-        sFrame.pTIM->byElementID = WLAN_EID_TIM;
-        s_vMgrFormatTIM(pMgmt, sFrame.pTIM);
-        sFrame.len += (WLAN_IEHDR_LEN + sFrame.pTIM->len);
-    }
-
-    if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) {
-
-        // IBSS parameter
-        sFrame.pIBSSParms = (PWLAN_IE_IBSS_PARMS)(sFrame.pBuf + sFrame.len);
-        sFrame.len += (2) + WLAN_IEHDR_LEN;
-        sFrame.pIBSSParms->byElementID = WLAN_EID_IBSS_PARMS;
-        sFrame.pIBSSParms->len = 2;
-        sFrame.pIBSSParms->wATIMWindow = wCurrATIMWinodw;
-        if (pMgmt->eAuthenMode == WMAC_AUTH_WPANONE) {
-            /* RSN parameter */
-            sFrame.pRSNWPA = (PWLAN_IE_RSN_EXT)(sFrame.pBuf + sFrame.len);
-            sFrame.pRSNWPA->byElementID = WLAN_EID_RSN_WPA;
-            sFrame.pRSNWPA->len = 12;
-            sFrame.pRSNWPA->abyOUI[0] = 0x00;
-            sFrame.pRSNWPA->abyOUI[1] = 0x50;
-            sFrame.pRSNWPA->abyOUI[2] = 0xf2;
-            sFrame.pRSNWPA->abyOUI[3] = 0x01;
-            sFrame.pRSNWPA->wVersion = 1;
-            sFrame.pRSNWPA->abyMulticast[0] = 0x00;
-            sFrame.pRSNWPA->abyMulticast[1] = 0x50;
-            sFrame.pRSNWPA->abyMulticast[2] = 0xf2;
-            if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled)
-                sFrame.pRSNWPA->abyMulticast[3] = 0x04;//AES
-            else if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled)
-                sFrame.pRSNWPA->abyMulticast[3] = 0x02;//TKIP
-            else if (pDevice->eEncryptionStatus == Ndis802_11Encryption1Enabled)
-                sFrame.pRSNWPA->abyMulticast[3] = 0x01;//WEP40
-            else
-                sFrame.pRSNWPA->abyMulticast[3] = 0x00;//NONE
-
-            // Pairwise Key Cipher Suite
-            sFrame.pRSNWPA->wPKCount = 0;
-            // Auth Key Management Suite
-            *((unsigned short *)(sFrame.pBuf + sFrame.len + sFrame.pRSNWPA->len))=0;
-            sFrame.pRSNWPA->len +=2;
-
-            // RSN Capabilities
-            *((unsigned short *)(sFrame.pBuf + sFrame.len + sFrame.pRSNWPA->len))=0;
-            sFrame.pRSNWPA->len +=2;
-            sFrame.len += sFrame.pRSNWPA->len + WLAN_IEHDR_LEN;
-        }
-    }
-
-    if ((pMgmt->b11hEnable == true) &&
-        (pMgmt->eCurrentPHYMode == PHY_TYPE_11A)) {
-        // Country IE
-        pbyBuffer = (unsigned char *)(sFrame.pBuf + sFrame.len);
-        set_country_IE(pMgmt->pAdapter, pbyBuffer);
-        set_country_info(pMgmt->pAdapter, PHY_TYPE_11A, pbyBuffer);
-        uLength += ((PWLAN_IE_COUNTRY) pbyBuffer)->len + WLAN_IEHDR_LEN;
-        pbyBuffer += (((PWLAN_IE_COUNTRY) pbyBuffer)->len + WLAN_IEHDR_LEN);
-        // Power Constrain IE
-        ((PWLAN_IE_PW_CONST) pbyBuffer)->byElementID = WLAN_EID_PWR_CONSTRAINT;
-        ((PWLAN_IE_PW_CONST) pbyBuffer)->len = 1;
-        ((PWLAN_IE_PW_CONST) pbyBuffer)->byPower = 0;
-        pbyBuffer += (1) + WLAN_IEHDR_LEN;
-        uLength += (1) + WLAN_IEHDR_LEN;
-        if (pMgmt->bSwitchChannel == true) {
-            // Channel Switch IE
-            ((PWLAN_IE_CH_SW) pbyBuffer)->byElementID = WLAN_EID_CH_SWITCH;
-            ((PWLAN_IE_CH_SW) pbyBuffer)->len = 3;
-            ((PWLAN_IE_CH_SW) pbyBuffer)->byMode = 1;
-            ((PWLAN_IE_CH_SW) pbyBuffer)->byChannel = get_channel_number(pMgmt->pAdapter, pMgmt->byNewChannel);
-            ((PWLAN_IE_CH_SW) pbyBuffer)->byCount = 0;
-            pbyBuffer += (3) + WLAN_IEHDR_LEN;
-            uLength += (3) + WLAN_IEHDR_LEN;
-        }
-        // TPC report
-        ((PWLAN_IE_TPC_REP) pbyBuffer)->byElementID = WLAN_EID_TPC_REP;
-        ((PWLAN_IE_TPC_REP) pbyBuffer)->len = 2;
-        ((PWLAN_IE_TPC_REP) pbyBuffer)->byTxPower = CARDbyGetTransmitPower(pMgmt->pAdapter);
-        ((PWLAN_IE_TPC_REP) pbyBuffer)->byLinkMargin = 0;
-        pbyBuffer += (2) + WLAN_IEHDR_LEN;
-        uLength += (2) + WLAN_IEHDR_LEN;
-        // IBSS DFS
-        if (pMgmt->eCurrMode != WMAC_MODE_ESS_AP) {
-            pIBSSDFS = (PWLAN_IE_IBSS_DFS) pbyBuffer;
-            pIBSSDFS->byElementID = WLAN_EID_IBSS_DFS;
-            pIBSSDFS->len = 7;
-            memcpy(   pIBSSDFS->abyDFSOwner,
-                        pMgmt->abyIBSSDFSOwner,
-                        6);
-            pIBSSDFS->byDFSRecovery = pMgmt->byIBSSDFSRecovery;
-            pbyBuffer += (7) + WLAN_IEHDR_LEN;
-            uLength += (7) + WLAN_IEHDR_LEN;
-            for(ii=CB_MAX_CHANNEL_24G+1; ii<=CB_MAX_CHANNEL; ii++ ) {
-                if (get_channel_map_info(pMgmt->pAdapter, ii, pbyBuffer, pbyBuffer+1) == true) {
-                    pbyBuffer += 2;
-                    uLength += 2;
-                    pIBSSDFS->len += 2;
-                }
-            }
-        }
-        sFrame.len += uLength;
-    }
-
-    if (pMgmt->eCurrentPHYMode == PHY_TYPE_11G) {
-        sFrame.pERP = (PWLAN_IE_ERP)(sFrame.pBuf + sFrame.len);
-        sFrame.len += 1 + WLAN_IEHDR_LEN;
-        sFrame.pERP->byElementID = WLAN_EID_ERP;
-        sFrame.pERP->len = 1;
-        sFrame.pERP->byContext = 0;
-        if (pDevice->bProtectMode == true)
-            sFrame.pERP->byContext |= WLAN_EID_ERP_USE_PROTECTION;
-        if (pDevice->bNonERPPresent == true)
-            sFrame.pERP->byContext |= WLAN_EID_ERP_NONERP_PRESENT;
-        if (pDevice->bBarkerPreambleMd == true)
-            sFrame.pERP->byContext |= WLAN_EID_ERP_BARKER_MODE;
-    }
-    if (((PWLAN_IE_SUPP_RATES)pCurrExtSuppRates)->len != 0) {
-        sFrame.pExtSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len);
-        sFrame.len += ((PWLAN_IE_SUPP_RATES)pCurrExtSuppRates)->len + WLAN_IEHDR_LEN;
-        memcpy(sFrame.pExtSuppRates,
-             pCurrExtSuppRates,
-             ((PWLAN_IE_SUPP_RATES)pCurrExtSuppRates)->len + WLAN_IEHDR_LEN
-             );
-    }
-    // hostapd wpa/wpa2 IE
-    if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) && (pDevice->bEnableHostapd == true)) {
-         if (pMgmt->eAuthenMode == WMAC_AUTH_WPANONE) {
-             if (pMgmt->wWPAIELen != 0) {
-                 sFrame.pRSN = (PWLAN_IE_RSN)(sFrame.pBuf + sFrame.len);
-                 memcpy(sFrame.pRSN, pMgmt->abyWPAIE, pMgmt->wWPAIELen);
-                 sFrame.len += pMgmt->wWPAIELen;
-             }
-         }
-    }
-
-    /* Adjust the length fields */
-    pTxPacket->cbMPDULen = sFrame.len;
-    pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN;
-
-    return pTxPacket;
-}
+	PSTxMgmtPacket      pTxPacket = NULL;
+	WLAN_FR_BEACON      sFrame;
+	unsigned char abyBroadcastAddr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+	unsigned char *pbyBuffer;
+	unsigned int uLength = 0;
+	PWLAN_IE_IBSS_DFS   pIBSSDFS = NULL;
+	unsigned int ii;
+
+	// prepare beacon frame
+	pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool;
+	memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_BEACON_FR_MAXLEN);
+	pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket));
+	// Setup the sFrame structure.
+	sFrame.pBuf = (unsigned char *)pTxPacket->p80211Header;
+	sFrame.len = WLAN_BEACON_FR_MAXLEN;
+	vMgrEncodeBeacon(&sFrame);
+	// Setup the header
+	sFrame.pHdr->sA3.wFrameCtl = cpu_to_le16(
+		(
+			WLAN_SET_FC_FTYPE(WLAN_TYPE_MGR) |
+			WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_BEACON)
+));
+
+	if (pDevice->bEnablePSMode) {
+		sFrame.pHdr->sA3.wFrameCtl |= cpu_to_le16((unsigned short)WLAN_SET_FC_PWRMGT(1));
+	}
 
+	memcpy(sFrame.pHdr->sA3.abyAddr1, abyBroadcastAddr, WLAN_ADDR_LEN);
+	memcpy(sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN);
+	memcpy(sFrame.pHdr->sA3.abyAddr3, pCurrBSSID, WLAN_BSSID_LEN);
+	*sFrame.pwBeaconInterval = cpu_to_le16(wCurrBeaconPeriod);
+	*sFrame.pwCapInfo = cpu_to_le16(wCurrCapInfo);
+	// Copy SSID
+	sFrame.pSSID = (PWLAN_IE_SSID)(sFrame.pBuf + sFrame.len);
+	sFrame.len += ((PWLAN_IE_SSID)pMgmt->abyCurrSSID)->len + WLAN_IEHDR_LEN;
+	memcpy(sFrame.pSSID,
+	       pCurrSSID,
+	       ((PWLAN_IE_SSID)pCurrSSID)->len + WLAN_IEHDR_LEN
+);
+	// Copy the rate set
+	sFrame.pSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len);
+	sFrame.len += ((PWLAN_IE_SUPP_RATES)pCurrSuppRates)->len + WLAN_IEHDR_LEN;
+	memcpy(sFrame.pSuppRates,
+	       pCurrSuppRates,
+	       ((PWLAN_IE_SUPP_RATES)pCurrSuppRates)->len + WLAN_IEHDR_LEN
+);
+	// DS parameter
+	if (pDevice->eCurrentPHYType != PHY_TYPE_11A) {
+		sFrame.pDSParms = (PWLAN_IE_DS_PARMS)(sFrame.pBuf + sFrame.len);
+		sFrame.len += (1) + WLAN_IEHDR_LEN;
+		sFrame.pDSParms->byElementID = WLAN_EID_DS_PARMS;
+		sFrame.pDSParms->len = 1;
+		sFrame.pDSParms->byCurrChannel = (unsigned char)uCurrChannel;
+	}
+	// TIM field
+	if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) {
+		sFrame.pTIM = (PWLAN_IE_TIM)(sFrame.pBuf + sFrame.len);
+		sFrame.pTIM->byElementID = WLAN_EID_TIM;
+		s_vMgrFormatTIM(pMgmt, sFrame.pTIM);
+		sFrame.len += (WLAN_IEHDR_LEN + sFrame.pTIM->len);
+	}
 
+	if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) {
+		// IBSS parameter
+		sFrame.pIBSSParms = (PWLAN_IE_IBSS_PARMS)(sFrame.pBuf + sFrame.len);
+		sFrame.len += (2) + WLAN_IEHDR_LEN;
+		sFrame.pIBSSParms->byElementID = WLAN_EID_IBSS_PARMS;
+		sFrame.pIBSSParms->len = 2;
+		sFrame.pIBSSParms->wATIMWindow = wCurrATIMWinodw;
+		if (pMgmt->eAuthenMode == WMAC_AUTH_WPANONE) {
+			/* RSN parameter */
+			sFrame.pRSNWPA = (PWLAN_IE_RSN_EXT)(sFrame.pBuf + sFrame.len);
+			sFrame.pRSNWPA->byElementID = WLAN_EID_RSN_WPA;
+			sFrame.pRSNWPA->len = 12;
+			sFrame.pRSNWPA->abyOUI[0] = 0x00;
+			sFrame.pRSNWPA->abyOUI[1] = 0x50;
+			sFrame.pRSNWPA->abyOUI[2] = 0xf2;
+			sFrame.pRSNWPA->abyOUI[3] = 0x01;
+			sFrame.pRSNWPA->wVersion = 1;
+			sFrame.pRSNWPA->abyMulticast[0] = 0x00;
+			sFrame.pRSNWPA->abyMulticast[1] = 0x50;
+			sFrame.pRSNWPA->abyMulticast[2] = 0xf2;
+			if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled)
+				sFrame.pRSNWPA->abyMulticast[3] = 0x04;//AES
+			else if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled)
+				sFrame.pRSNWPA->abyMulticast[3] = 0x02;//TKIP
+			else if (pDevice->eEncryptionStatus == Ndis802_11Encryption1Enabled)
+				sFrame.pRSNWPA->abyMulticast[3] = 0x01;//WEP40
+			else
+				sFrame.pRSNWPA->abyMulticast[3] = 0x00;//NONE
+
+			// Pairwise Key Cipher Suite
+			sFrame.pRSNWPA->wPKCount = 0;
+			// Auth Key Management Suite
+			*((unsigned short *)(sFrame.pBuf + sFrame.len + sFrame.pRSNWPA->len)) = 0;
+			sFrame.pRSNWPA->len += 2;
+
+			// RSN Capabilities
+			*((unsigned short *)(sFrame.pBuf + sFrame.len + sFrame.pRSNWPA->len)) = 0;
+			sFrame.pRSNWPA->len += 2;
+			sFrame.len += sFrame.pRSNWPA->len + WLAN_IEHDR_LEN;
+		}
+	}
 
+	if ((pMgmt->b11hEnable == true) &&
+	    (pMgmt->eCurrentPHYMode == PHY_TYPE_11A)) {
+		// Country IE
+		pbyBuffer = (unsigned char *)(sFrame.pBuf + sFrame.len);
+		set_country_IE(pMgmt->pAdapter, pbyBuffer);
+		set_country_info(pMgmt->pAdapter, PHY_TYPE_11A, pbyBuffer);
+		uLength += ((PWLAN_IE_COUNTRY) pbyBuffer)->len + WLAN_IEHDR_LEN;
+		pbyBuffer += (((PWLAN_IE_COUNTRY) pbyBuffer)->len + WLAN_IEHDR_LEN);
+		// Power Constrain IE
+		((PWLAN_IE_PW_CONST) pbyBuffer)->byElementID = WLAN_EID_PWR_CONSTRAINT;
+		((PWLAN_IE_PW_CONST) pbyBuffer)->len = 1;
+		((PWLAN_IE_PW_CONST) pbyBuffer)->byPower = 0;
+		pbyBuffer += (1) + WLAN_IEHDR_LEN;
+		uLength += (1) + WLAN_IEHDR_LEN;
+		if (pMgmt->bSwitchChannel == true) {
+			// Channel Switch IE
+			((PWLAN_IE_CH_SW) pbyBuffer)->byElementID = WLAN_EID_CH_SWITCH;
+			((PWLAN_IE_CH_SW) pbyBuffer)->len = 3;
+			((PWLAN_IE_CH_SW) pbyBuffer)->byMode = 1;
+			((PWLAN_IE_CH_SW) pbyBuffer)->byChannel = get_channel_number(pMgmt->pAdapter, pMgmt->byNewChannel);
+			((PWLAN_IE_CH_SW) pbyBuffer)->byCount = 0;
+			pbyBuffer += (3) + WLAN_IEHDR_LEN;
+			uLength += (3) + WLAN_IEHDR_LEN;
+		}
+		// TPC report
+		((PWLAN_IE_TPC_REP) pbyBuffer)->byElementID = WLAN_EID_TPC_REP;
+		((PWLAN_IE_TPC_REP) pbyBuffer)->len = 2;
+		((PWLAN_IE_TPC_REP) pbyBuffer)->byTxPower = CARDbyGetTransmitPower(pMgmt->pAdapter);
+		((PWLAN_IE_TPC_REP) pbyBuffer)->byLinkMargin = 0;
+		pbyBuffer += (2) + WLAN_IEHDR_LEN;
+		uLength += (2) + WLAN_IEHDR_LEN;
+		// IBSS DFS
+		if (pMgmt->eCurrMode != WMAC_MODE_ESS_AP) {
+			pIBSSDFS = (PWLAN_IE_IBSS_DFS) pbyBuffer;
+			pIBSSDFS->byElementID = WLAN_EID_IBSS_DFS;
+			pIBSSDFS->len = 7;
+			memcpy(pIBSSDFS->abyDFSOwner,
+			       pMgmt->abyIBSSDFSOwner,
+			       6);
+			pIBSSDFS->byDFSRecovery = pMgmt->byIBSSDFSRecovery;
+			pbyBuffer += (7) + WLAN_IEHDR_LEN;
+			uLength += (7) + WLAN_IEHDR_LEN;
+			for (ii = CB_MAX_CHANNEL_24G+1; ii <= CB_MAX_CHANNEL; ii++) {
+				if (get_channel_map_info(pMgmt->pAdapter, ii, pbyBuffer, pbyBuffer+1) == true) {
+					pbyBuffer += 2;
+					uLength += 2;
+					pIBSSDFS->len += 2;
+				}
+			}
+		}
+		sFrame.len += uLength;
+	}
 
+	if (pMgmt->eCurrentPHYMode == PHY_TYPE_11G) {
+		sFrame.pERP = (PWLAN_IE_ERP)(sFrame.pBuf + sFrame.len);
+		sFrame.len += 1 + WLAN_IEHDR_LEN;
+		sFrame.pERP->byElementID = WLAN_EID_ERP;
+		sFrame.pERP->len = 1;
+		sFrame.pERP->byContext = 0;
+		if (pDevice->bProtectMode == true)
+			sFrame.pERP->byContext |= WLAN_EID_ERP_USE_PROTECTION;
+		if (pDevice->bNonERPPresent == true)
+			sFrame.pERP->byContext |= WLAN_EID_ERP_NONERP_PRESENT;
+		if (pDevice->bBarkerPreambleMd == true)
+			sFrame.pERP->byContext |= WLAN_EID_ERP_BARKER_MODE;
+	}
+	if (((PWLAN_IE_SUPP_RATES)pCurrExtSuppRates)->len != 0) {
+		sFrame.pExtSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len);
+		sFrame.len += ((PWLAN_IE_SUPP_RATES)pCurrExtSuppRates)->len + WLAN_IEHDR_LEN;
+		memcpy(sFrame.pExtSuppRates,
+		       pCurrExtSuppRates,
+		       ((PWLAN_IE_SUPP_RATES)pCurrExtSuppRates)->len + WLAN_IEHDR_LEN
+);
+	}
+	// hostapd wpa/wpa2 IE
+	if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) && (pDevice->bEnableHostapd == true)) {
+		if (pMgmt->eAuthenMode == WMAC_AUTH_WPANONE) {
+			if (pMgmt->wWPAIELen != 0) {
+				sFrame.pRSN = (PWLAN_IE_RSN)(sFrame.pBuf + sFrame.len);
+				memcpy(sFrame.pRSN, pMgmt->abyWPAIE, pMgmt->wWPAIELen);
+				sFrame.len += pMgmt->wWPAIELen;
+			}
+		}
+	}
+
+	/* Adjust the length fields */
+	pTxPacket->cbMPDULen = sFrame.len;
+	pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN;
+
+	return pTxPacket;
+}
 
 /*+
  *
@@ -3422,187 +3250,180 @@ s_MgrMakeBeacon(
  * Return Value:
  *    PTR to frame; or NULL on allocation failure
  *
--*/
-
-
-
+ -*/
 
 PSTxMgmtPacket
 s_MgrMakeProbeResponse(
-    PSDevice pDevice,
-    PSMgmtObject pMgmt,
-    unsigned short wCurrCapInfo,
-    unsigned short wCurrBeaconPeriod,
-    unsigned int uCurrChannel,
-    unsigned short wCurrATIMWinodw,
-    unsigned char *pDstAddr,
-    PWLAN_IE_SSID pCurrSSID,
-    unsigned char *pCurrBSSID,
-    PWLAN_IE_SUPP_RATES pCurrSuppRates,
-    PWLAN_IE_SUPP_RATES pCurrExtSuppRates,
-    unsigned char byPHYType
-    )
+	PSDevice pDevice,
+	PSMgmtObject pMgmt,
+	unsigned short wCurrCapInfo,
+	unsigned short wCurrBeaconPeriod,
+	unsigned int uCurrChannel,
+	unsigned short wCurrATIMWinodw,
+	unsigned char *pDstAddr,
+	PWLAN_IE_SSID pCurrSSID,
+	unsigned char *pCurrBSSID,
+	PWLAN_IE_SUPP_RATES pCurrSuppRates,
+	PWLAN_IE_SUPP_RATES pCurrExtSuppRates,
+	unsigned char byPHYType
+)
 {
-    PSTxMgmtPacket      pTxPacket = NULL;
-    WLAN_FR_PROBERESP   sFrame;
-    unsigned char *pbyBuffer;
-    unsigned int uLength = 0;
-    PWLAN_IE_IBSS_DFS   pIBSSDFS = NULL;
-    unsigned int ii;
-
-
-    pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool;
-    memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_PROBERESP_FR_MAXLEN);
-    pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket));
-    // Setup the sFrame structure.
-    sFrame.pBuf = (unsigned char *)pTxPacket->p80211Header;
-    sFrame.len = WLAN_PROBERESP_FR_MAXLEN;
-    vMgrEncodeProbeResponse(&sFrame);
-    // Setup the header
-    sFrame.pHdr->sA3.wFrameCtl = cpu_to_le16(
-        (
-        WLAN_SET_FC_FTYPE(WLAN_TYPE_MGR) |
-        WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_PROBERESP)
-        ));
-    memcpy( sFrame.pHdr->sA3.abyAddr1, pDstAddr, WLAN_ADDR_LEN);
-    memcpy( sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN);
-    memcpy( sFrame.pHdr->sA3.abyAddr3, pCurrBSSID, WLAN_BSSID_LEN);
-    *sFrame.pwBeaconInterval = cpu_to_le16(wCurrBeaconPeriod);
-    *sFrame.pwCapInfo = cpu_to_le16(wCurrCapInfo);
-
-    if (byPHYType == BB_TYPE_11B) {
-        *sFrame.pwCapInfo &= cpu_to_le16((unsigned short)~(WLAN_SET_CAP_INFO_SHORTSLOTTIME(1)));
-    }
-
-    // Copy SSID
-    sFrame.pSSID = (PWLAN_IE_SSID)(sFrame.pBuf + sFrame.len);
-    sFrame.len += ((PWLAN_IE_SSID)pMgmt->abyCurrSSID)->len + WLAN_IEHDR_LEN;
-    memcpy(sFrame.pSSID,
-           pCurrSSID,
-           ((PWLAN_IE_SSID)pCurrSSID)->len + WLAN_IEHDR_LEN
-           );
-    // Copy the rate set
-    sFrame.pSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len);
-
-    sFrame.len += ((PWLAN_IE_SUPP_RATES)pCurrSuppRates)->len + WLAN_IEHDR_LEN;
-    memcpy(sFrame.pSuppRates,
-           pCurrSuppRates,
-           ((PWLAN_IE_SUPP_RATES)pCurrSuppRates)->len + WLAN_IEHDR_LEN
-          );
-
-    // DS parameter
-    if (pDevice->eCurrentPHYType != PHY_TYPE_11A) {
-        sFrame.pDSParms = (PWLAN_IE_DS_PARMS)(sFrame.pBuf + sFrame.len);
-        sFrame.len += (1) + WLAN_IEHDR_LEN;
-        sFrame.pDSParms->byElementID = WLAN_EID_DS_PARMS;
-        sFrame.pDSParms->len = 1;
-        sFrame.pDSParms->byCurrChannel = (unsigned char)uCurrChannel;
-    }
-
-    if (pMgmt->eCurrMode != WMAC_MODE_ESS_AP) {
-        // IBSS parameter
-        sFrame.pIBSSParms = (PWLAN_IE_IBSS_PARMS)(sFrame.pBuf + sFrame.len);
-        sFrame.len += (2) + WLAN_IEHDR_LEN;
-        sFrame.pIBSSParms->byElementID = WLAN_EID_IBSS_PARMS;
-        sFrame.pIBSSParms->len = 2;
-        sFrame.pIBSSParms->wATIMWindow = 0;
-    }
-    if (pDevice->eCurrentPHYType == PHY_TYPE_11G) {
-        sFrame.pERP = (PWLAN_IE_ERP)(sFrame.pBuf + sFrame.len);
-        sFrame.len += 1 + WLAN_IEHDR_LEN;
-        sFrame.pERP->byElementID = WLAN_EID_ERP;
-        sFrame.pERP->len = 1;
-        sFrame.pERP->byContext = 0;
-        if (pDevice->bProtectMode == true)
-            sFrame.pERP->byContext |= WLAN_EID_ERP_USE_PROTECTION;
-        if (pDevice->bNonERPPresent == true)
-            sFrame.pERP->byContext |= WLAN_EID_ERP_NONERP_PRESENT;
-        if (pDevice->bBarkerPreambleMd == true)
-            sFrame.pERP->byContext |= WLAN_EID_ERP_BARKER_MODE;
-    }
-
-    if ((pMgmt->b11hEnable == true) &&
-        (pMgmt->eCurrentPHYMode == PHY_TYPE_11A)) {
-        // Country IE
-        pbyBuffer = (unsigned char *)(sFrame.pBuf + sFrame.len);
-        set_country_IE(pMgmt->pAdapter, pbyBuffer);
-        set_country_info(pMgmt->pAdapter, PHY_TYPE_11A, pbyBuffer);
-        uLength += ((PWLAN_IE_COUNTRY) pbyBuffer)->len + WLAN_IEHDR_LEN;
-        pbyBuffer += (((PWLAN_IE_COUNTRY) pbyBuffer)->len + WLAN_IEHDR_LEN);
-        // Power Constrain IE
-        ((PWLAN_IE_PW_CONST) pbyBuffer)->byElementID = WLAN_EID_PWR_CONSTRAINT;
-        ((PWLAN_IE_PW_CONST) pbyBuffer)->len = 1;
-        ((PWLAN_IE_PW_CONST) pbyBuffer)->byPower = 0;
-        pbyBuffer += (1) + WLAN_IEHDR_LEN;
-        uLength += (1) + WLAN_IEHDR_LEN;
-        if (pMgmt->bSwitchChannel == true) {
-            // Channel Switch IE
-            ((PWLAN_IE_CH_SW) pbyBuffer)->byElementID = WLAN_EID_CH_SWITCH;
-            ((PWLAN_IE_CH_SW) pbyBuffer)->len = 3;
-            ((PWLAN_IE_CH_SW) pbyBuffer)->byMode = 1;
-            ((PWLAN_IE_CH_SW) pbyBuffer)->byChannel = get_channel_number(pMgmt->pAdapter, pMgmt->byNewChannel);
-            ((PWLAN_IE_CH_SW) pbyBuffer)->byCount = 0;
-            pbyBuffer += (3) + WLAN_IEHDR_LEN;
-            uLength += (3) + WLAN_IEHDR_LEN;
-        }
-        // TPC report
-        ((PWLAN_IE_TPC_REP) pbyBuffer)->byElementID = WLAN_EID_TPC_REP;
-        ((PWLAN_IE_TPC_REP) pbyBuffer)->len = 2;
-        ((PWLAN_IE_TPC_REP) pbyBuffer)->byTxPower = CARDbyGetTransmitPower(pMgmt->pAdapter);
-        ((PWLAN_IE_TPC_REP) pbyBuffer)->byLinkMargin = 0;
-        pbyBuffer += (2) + WLAN_IEHDR_LEN;
-        uLength += (2) + WLAN_IEHDR_LEN;
-        // IBSS DFS
-        if (pMgmt->eCurrMode != WMAC_MODE_ESS_AP) {
-            pIBSSDFS = (PWLAN_IE_IBSS_DFS) pbyBuffer;
-            pIBSSDFS->byElementID = WLAN_EID_IBSS_DFS;
-            pIBSSDFS->len = 7;
-            memcpy(   pIBSSDFS->abyDFSOwner,
-                        pMgmt->abyIBSSDFSOwner,
-                        6);
-            pIBSSDFS->byDFSRecovery = pMgmt->byIBSSDFSRecovery;
-            pbyBuffer += (7) + WLAN_IEHDR_LEN;
-            uLength += (7) + WLAN_IEHDR_LEN;
-            for(ii=CB_MAX_CHANNEL_24G+1; ii<=CB_MAX_CHANNEL; ii++ ) {
-                if (get_channel_map_info(pMgmt->pAdapter, ii, pbyBuffer, pbyBuffer+1) == true) {
-                    pbyBuffer += 2;
-                    uLength += 2;
-                    pIBSSDFS->len += 2;
-                }
-            }
-        }
-        sFrame.len += uLength;
-    }
-
-
-    if (((PWLAN_IE_SUPP_RATES)pCurrExtSuppRates)->len != 0) {
-        sFrame.pExtSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len);
-        sFrame.len += ((PWLAN_IE_SUPP_RATES)pCurrExtSuppRates)->len + WLAN_IEHDR_LEN;
-        memcpy(sFrame.pExtSuppRates,
-             pCurrExtSuppRates,
-             ((PWLAN_IE_SUPP_RATES)pCurrExtSuppRates)->len + WLAN_IEHDR_LEN
-             );
-    }
-
-    // hostapd wpa/wpa2 IE
-    if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) && (pDevice->bEnableHostapd == true)) {
-         if (pMgmt->eAuthenMode == WMAC_AUTH_WPANONE) {
-             if (pMgmt->wWPAIELen != 0) {
-                 sFrame.pRSN = (PWLAN_IE_RSN)(sFrame.pBuf + sFrame.len);
-                 memcpy(sFrame.pRSN, pMgmt->abyWPAIE, pMgmt->wWPAIELen);
-                 sFrame.len += pMgmt->wWPAIELen;
-             }
-         }
-    }
-
-    // Adjust the length fields
-    pTxPacket->cbMPDULen = sFrame.len;
-    pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN;
-
-    return pTxPacket;
-}
+	PSTxMgmtPacket      pTxPacket = NULL;
+	WLAN_FR_PROBERESP   sFrame;
+	unsigned char *pbyBuffer;
+	unsigned int uLength = 0;
+	PWLAN_IE_IBSS_DFS   pIBSSDFS = NULL;
+	unsigned int ii;
+
+	pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool;
+	memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_PROBERESP_FR_MAXLEN);
+	pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket));
+	// Setup the sFrame structure.
+	sFrame.pBuf = (unsigned char *)pTxPacket->p80211Header;
+	sFrame.len = WLAN_PROBERESP_FR_MAXLEN;
+	vMgrEncodeProbeResponse(&sFrame);
+	// Setup the header
+	sFrame.pHdr->sA3.wFrameCtl = cpu_to_le16(
+		(
+			WLAN_SET_FC_FTYPE(WLAN_TYPE_MGR) |
+			WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_PROBERESP)
+));
+	memcpy(sFrame.pHdr->sA3.abyAddr1, pDstAddr, WLAN_ADDR_LEN);
+	memcpy(sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN);
+	memcpy(sFrame.pHdr->sA3.abyAddr3, pCurrBSSID, WLAN_BSSID_LEN);
+	*sFrame.pwBeaconInterval = cpu_to_le16(wCurrBeaconPeriod);
+	*sFrame.pwCapInfo = cpu_to_le16(wCurrCapInfo);
+
+	if (byPHYType == BB_TYPE_11B) {
+		*sFrame.pwCapInfo &= cpu_to_le16((unsigned short)~(WLAN_SET_CAP_INFO_SHORTSLOTTIME(1)));
+	}
+
+	// Copy SSID
+	sFrame.pSSID = (PWLAN_IE_SSID)(sFrame.pBuf + sFrame.len);
+	sFrame.len += ((PWLAN_IE_SSID)pMgmt->abyCurrSSID)->len + WLAN_IEHDR_LEN;
+	memcpy(sFrame.pSSID,
+	       pCurrSSID,
+	       ((PWLAN_IE_SSID)pCurrSSID)->len + WLAN_IEHDR_LEN
+);
+	// Copy the rate set
+	sFrame.pSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len);
+
+	sFrame.len += ((PWLAN_IE_SUPP_RATES)pCurrSuppRates)->len + WLAN_IEHDR_LEN;
+	memcpy(sFrame.pSuppRates,
+	       pCurrSuppRates,
+	       ((PWLAN_IE_SUPP_RATES)pCurrSuppRates)->len + WLAN_IEHDR_LEN
+);
+
+	// DS parameter
+	if (pDevice->eCurrentPHYType != PHY_TYPE_11A) {
+		sFrame.pDSParms = (PWLAN_IE_DS_PARMS)(sFrame.pBuf + sFrame.len);
+		sFrame.len += (1) + WLAN_IEHDR_LEN;
+		sFrame.pDSParms->byElementID = WLAN_EID_DS_PARMS;
+		sFrame.pDSParms->len = 1;
+		sFrame.pDSParms->byCurrChannel = (unsigned char)uCurrChannel;
+	}
+
+	if (pMgmt->eCurrMode != WMAC_MODE_ESS_AP) {
+		// IBSS parameter
+		sFrame.pIBSSParms = (PWLAN_IE_IBSS_PARMS)(sFrame.pBuf + sFrame.len);
+		sFrame.len += (2) + WLAN_IEHDR_LEN;
+		sFrame.pIBSSParms->byElementID = WLAN_EID_IBSS_PARMS;
+		sFrame.pIBSSParms->len = 2;
+		sFrame.pIBSSParms->wATIMWindow = 0;
+	}
+	if (pDevice->eCurrentPHYType == PHY_TYPE_11G) {
+		sFrame.pERP = (PWLAN_IE_ERP)(sFrame.pBuf + sFrame.len);
+		sFrame.len += 1 + WLAN_IEHDR_LEN;
+		sFrame.pERP->byElementID = WLAN_EID_ERP;
+		sFrame.pERP->len = 1;
+		sFrame.pERP->byContext = 0;
+		if (pDevice->bProtectMode == true)
+			sFrame.pERP->byContext |= WLAN_EID_ERP_USE_PROTECTION;
+		if (pDevice->bNonERPPresent == true)
+			sFrame.pERP->byContext |= WLAN_EID_ERP_NONERP_PRESENT;
+		if (pDevice->bBarkerPreambleMd == true)
+			sFrame.pERP->byContext |= WLAN_EID_ERP_BARKER_MODE;
+	}
+
+	if ((pMgmt->b11hEnable == true) &&
+	    (pMgmt->eCurrentPHYMode == PHY_TYPE_11A)) {
+		// Country IE
+		pbyBuffer = (unsigned char *)(sFrame.pBuf + sFrame.len);
+		set_country_IE(pMgmt->pAdapter, pbyBuffer);
+		set_country_info(pMgmt->pAdapter, PHY_TYPE_11A, pbyBuffer);
+		uLength += ((PWLAN_IE_COUNTRY) pbyBuffer)->len + WLAN_IEHDR_LEN;
+		pbyBuffer += (((PWLAN_IE_COUNTRY) pbyBuffer)->len + WLAN_IEHDR_LEN);
+		// Power Constrain IE
+		((PWLAN_IE_PW_CONST) pbyBuffer)->byElementID = WLAN_EID_PWR_CONSTRAINT;
+		((PWLAN_IE_PW_CONST) pbyBuffer)->len = 1;
+		((PWLAN_IE_PW_CONST) pbyBuffer)->byPower = 0;
+		pbyBuffer += (1) + WLAN_IEHDR_LEN;
+		uLength += (1) + WLAN_IEHDR_LEN;
+		if (pMgmt->bSwitchChannel == true) {
+			// Channel Switch IE
+			((PWLAN_IE_CH_SW) pbyBuffer)->byElementID = WLAN_EID_CH_SWITCH;
+			((PWLAN_IE_CH_SW) pbyBuffer)->len = 3;
+			((PWLAN_IE_CH_SW) pbyBuffer)->byMode = 1;
+			((PWLAN_IE_CH_SW) pbyBuffer)->byChannel = get_channel_number(pMgmt->pAdapter, pMgmt->byNewChannel);
+			((PWLAN_IE_CH_SW) pbyBuffer)->byCount = 0;
+			pbyBuffer += (3) + WLAN_IEHDR_LEN;
+			uLength += (3) + WLAN_IEHDR_LEN;
+		}
+		// TPC report
+		((PWLAN_IE_TPC_REP) pbyBuffer)->byElementID = WLAN_EID_TPC_REP;
+		((PWLAN_IE_TPC_REP) pbyBuffer)->len = 2;
+		((PWLAN_IE_TPC_REP) pbyBuffer)->byTxPower = CARDbyGetTransmitPower(pMgmt->pAdapter);
+		((PWLAN_IE_TPC_REP) pbyBuffer)->byLinkMargin = 0;
+		pbyBuffer += (2) + WLAN_IEHDR_LEN;
+		uLength += (2) + WLAN_IEHDR_LEN;
+		// IBSS DFS
+		if (pMgmt->eCurrMode != WMAC_MODE_ESS_AP) {
+			pIBSSDFS = (PWLAN_IE_IBSS_DFS) pbyBuffer;
+			pIBSSDFS->byElementID = WLAN_EID_IBSS_DFS;
+			pIBSSDFS->len = 7;
+			memcpy(pIBSSDFS->abyDFSOwner,
+			       pMgmt->abyIBSSDFSOwner,
+			       6);
+			pIBSSDFS->byDFSRecovery = pMgmt->byIBSSDFSRecovery;
+			pbyBuffer += (7) + WLAN_IEHDR_LEN;
+			uLength += (7) + WLAN_IEHDR_LEN;
+			for (ii = CB_MAX_CHANNEL_24G + 1; ii <= CB_MAX_CHANNEL; ii++) {
+				if (get_channel_map_info(pMgmt->pAdapter, ii, pbyBuffer, pbyBuffer+1) == true) {
+					pbyBuffer += 2;
+					uLength += 2;
+					pIBSSDFS->len += 2;
+				}
+			}
+		}
+		sFrame.len += uLength;
+	}
+
+	if (((PWLAN_IE_SUPP_RATES)pCurrExtSuppRates)->len != 0) {
+		sFrame.pExtSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len);
+		sFrame.len += ((PWLAN_IE_SUPP_RATES)pCurrExtSuppRates)->len + WLAN_IEHDR_LEN;
+		memcpy(sFrame.pExtSuppRates,
+		       pCurrExtSuppRates,
+		       ((PWLAN_IE_SUPP_RATES)pCurrExtSuppRates)->len + WLAN_IEHDR_LEN
+);
+	}
+
+	// hostapd wpa/wpa2 IE
+	if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) && (pDevice->bEnableHostapd == true)) {
+		if (pMgmt->eAuthenMode == WMAC_AUTH_WPANONE) {
+			if (pMgmt->wWPAIELen != 0) {
+				sFrame.pRSN = (PWLAN_IE_RSN)(sFrame.pBuf + sFrame.len);
+				memcpy(sFrame.pRSN, pMgmt->abyWPAIE, pMgmt->wWPAIELen);
+				sFrame.len += pMgmt->wWPAIELen;
+			}
+		}
+	}
 
+	// Adjust the length fields
+	pTxPacket->cbMPDULen = sFrame.len;
+	pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN;
 
+	return pTxPacket;
+}
 
 /*+
  *
@@ -3613,271 +3434,259 @@ s_MgrMakeProbeResponse(
  * Return Value:
  *    A ptr to frame or NULL on allocation failure
  *
--*/
-
+ -*/
 
 PSTxMgmtPacket
 s_MgrMakeAssocRequest(
-    PSDevice pDevice,
-    PSMgmtObject pMgmt,
-    unsigned char *pDAddr,
-    unsigned short wCurrCapInfo,
-    unsigned short wListenInterval,
-    PWLAN_IE_SSID pCurrSSID,
-    PWLAN_IE_SUPP_RATES pCurrRates,
-    PWLAN_IE_SUPP_RATES pCurrExtSuppRates
-    )
+	PSDevice pDevice,
+	PSMgmtObject pMgmt,
+	unsigned char *pDAddr,
+	unsigned short wCurrCapInfo,
+	unsigned short wListenInterval,
+	PWLAN_IE_SSID pCurrSSID,
+	PWLAN_IE_SUPP_RATES pCurrRates,
+	PWLAN_IE_SUPP_RATES pCurrExtSuppRates
+)
 {
-    PSTxMgmtPacket      pTxPacket = NULL;
-    WLAN_FR_ASSOCREQ    sFrame;
-    unsigned char *pbyIEs;
-    unsigned char *pbyRSN;
-
-
-    pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool;
-    memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_ASSOCREQ_FR_MAXLEN);
-    pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket));
-    // Setup the sFrame structure.
-    sFrame.pBuf = (unsigned char *)pTxPacket->p80211Header;
-    sFrame.len = WLAN_ASSOCREQ_FR_MAXLEN;
-    // format fixed field frame structure
-    vMgrEncodeAssocRequest(&sFrame);
-    // Setup the header
-    sFrame.pHdr->sA3.wFrameCtl = cpu_to_le16(
-        (
-        WLAN_SET_FC_FTYPE(WLAN_TYPE_MGR) |
-        WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_ASSOCREQ)
-        ));
-    memcpy( sFrame.pHdr->sA3.abyAddr1, pDAddr, WLAN_ADDR_LEN);
-    memcpy( sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN);
-    memcpy( sFrame.pHdr->sA3.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN);
-
-    // Set the capability and listen interval
-    *(sFrame.pwCapInfo) = cpu_to_le16(wCurrCapInfo);
-    *(sFrame.pwListenInterval) = cpu_to_le16(wListenInterval);
-
-    // sFrame.len point to end of fixed field
-    sFrame.pSSID = (PWLAN_IE_SSID)(sFrame.pBuf + sFrame.len);
-    sFrame.len += pCurrSSID->len + WLAN_IEHDR_LEN;
-    memcpy(sFrame.pSSID, pCurrSSID, pCurrSSID->len + WLAN_IEHDR_LEN);
-
-    pMgmt->sAssocInfo.AssocInfo.RequestIELength = pCurrSSID->len + WLAN_IEHDR_LEN;
-    pMgmt->sAssocInfo.AssocInfo.OffsetRequestIEs = sizeof(NDIS_802_11_ASSOCIATION_INFORMATION);
-    pbyIEs = pMgmt->sAssocInfo.abyIEs;
-    memcpy(pbyIEs, pCurrSSID, pCurrSSID->len + WLAN_IEHDR_LEN);
-    pbyIEs += pCurrSSID->len + WLAN_IEHDR_LEN;
-
-    // Copy the rate set
-    sFrame.pSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len);
-    if ((pDevice->eCurrentPHYType == PHY_TYPE_11B) && (pCurrRates->len > 4))
-        sFrame.len += 4 + WLAN_IEHDR_LEN;
-    else
-        sFrame.len += pCurrRates->len + WLAN_IEHDR_LEN;
-    memcpy(sFrame.pSuppRates, pCurrRates, pCurrRates->len + WLAN_IEHDR_LEN);
-
-    // Copy the extension rate set
-    if ((pDevice->eCurrentPHYType == PHY_TYPE_11G) && (pCurrExtSuppRates->len > 0)) {
-        sFrame.pExtSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len);
-        sFrame.len += pCurrExtSuppRates->len + WLAN_IEHDR_LEN;
-        memcpy(sFrame.pExtSuppRates, pCurrExtSuppRates, pCurrExtSuppRates->len + WLAN_IEHDR_LEN);
-    }
-
-    pMgmt->sAssocInfo.AssocInfo.RequestIELength += pCurrRates->len + WLAN_IEHDR_LEN;
-    memcpy(pbyIEs, pCurrRates, pCurrRates->len + WLAN_IEHDR_LEN);
-    pbyIEs += pCurrRates->len + WLAN_IEHDR_LEN;
-
-    // for 802.11h
-    if (pMgmt->b11hEnable == true) {
-        if (sFrame.pCurrPowerCap == NULL) {
-            sFrame.pCurrPowerCap = (PWLAN_IE_PW_CAP)(sFrame.pBuf + sFrame.len);
-            sFrame.len += (2 + WLAN_IEHDR_LEN);
-            sFrame.pCurrPowerCap->byElementID = WLAN_EID_PWR_CAPABILITY;
-            sFrame.pCurrPowerCap->len = 2;
-            CARDvGetPowerCapability(pMgmt->pAdapter,
-                                    &(sFrame.pCurrPowerCap->byMinPower),
-                                    &(sFrame.pCurrPowerCap->byMaxPower)
-                                    );
-        }
-        if (sFrame.pCurrSuppCh == NULL) {
-            sFrame.pCurrSuppCh = (PWLAN_IE_SUPP_CH)(sFrame.pBuf + sFrame.len);
-            sFrame.len += set_support_channels(pMgmt->pAdapter,(unsigned char *)sFrame.pCurrSuppCh);
-        }
-    }
-
-    if (((pMgmt->eAuthenMode == WMAC_AUTH_WPA) ||
-         (pMgmt->eAuthenMode == WMAC_AUTH_WPAPSK) ||
-         (pMgmt->eAuthenMode == WMAC_AUTH_WPANONE)) &&
-        (pMgmt->pCurrBSS != NULL)) {
-        /* WPA IE */
-        sFrame.pRSNWPA = (PWLAN_IE_RSN_EXT)(sFrame.pBuf + sFrame.len);
-        sFrame.pRSNWPA->byElementID = WLAN_EID_RSN_WPA;
-        sFrame.pRSNWPA->len = 16;
-        sFrame.pRSNWPA->abyOUI[0] = 0x00;
-        sFrame.pRSNWPA->abyOUI[1] = 0x50;
-        sFrame.pRSNWPA->abyOUI[2] = 0xf2;
-        sFrame.pRSNWPA->abyOUI[3] = 0x01;
-        sFrame.pRSNWPA->wVersion = 1;
-        //Group Key Cipher Suite
-        sFrame.pRSNWPA->abyMulticast[0] = 0x00;
-        sFrame.pRSNWPA->abyMulticast[1] = 0x50;
-        sFrame.pRSNWPA->abyMulticast[2] = 0xf2;
-        if (pMgmt->byCSSGK == KEY_CTL_WEP) {
-            sFrame.pRSNWPA->abyMulticast[3] = pMgmt->pCurrBSS->byGKType;
-        } else if (pMgmt->byCSSGK == KEY_CTL_TKIP) {
-            sFrame.pRSNWPA->abyMulticast[3] = WPA_TKIP;
-        } else if (pMgmt->byCSSGK == KEY_CTL_CCMP) {
-            sFrame.pRSNWPA->abyMulticast[3] = WPA_AESCCMP;
-        } else {
-            sFrame.pRSNWPA->abyMulticast[3] = WPA_NONE;
-        }
-        // Pairwise Key Cipher Suite
-        sFrame.pRSNWPA->wPKCount = 1;
-        sFrame.pRSNWPA->PKSList[0].abyOUI[0] = 0x00;
-        sFrame.pRSNWPA->PKSList[0].abyOUI[1] = 0x50;
-        sFrame.pRSNWPA->PKSList[0].abyOUI[2] = 0xf2;
-        if (pMgmt->byCSSPK == KEY_CTL_TKIP) {
-            sFrame.pRSNWPA->PKSList[0].abyOUI[3] = WPA_TKIP;
-        } else if (pMgmt->byCSSPK == KEY_CTL_CCMP) {
-            sFrame.pRSNWPA->PKSList[0].abyOUI[3] = WPA_AESCCMP;
-        } else {
-            sFrame.pRSNWPA->PKSList[0].abyOUI[3] = WPA_NONE;
-        }
-        // Auth Key Management Suite
-        pbyRSN = (unsigned char *)(sFrame.pBuf + sFrame.len + 2 + sFrame.pRSNWPA->len);
-        *pbyRSN++=0x01;
-        *pbyRSN++=0x00;
-        *pbyRSN++=0x00;
-
-        *pbyRSN++=0x50;
-        *pbyRSN++=0xf2;
-        if (pMgmt->eAuthenMode == WMAC_AUTH_WPAPSK) {
-            *pbyRSN++=WPA_AUTH_PSK;
-        }
-        else if (pMgmt->eAuthenMode == WMAC_AUTH_WPA) {
-            *pbyRSN++=WPA_AUTH_IEEE802_1X;
-        }
-        else {
-            *pbyRSN++=WPA_NONE;
-        }
-
-        sFrame.pRSNWPA->len +=6;
-
-        // RSN Capabilities
-
-        *pbyRSN++=0x00;
-        *pbyRSN++=0x00;
-        sFrame.pRSNWPA->len +=2;
-
-        sFrame.len += sFrame.pRSNWPA->len + WLAN_IEHDR_LEN;
-        // copy to AssocInfo. for OID_802_11_ASSOCIATION_INFORMATION
-        pMgmt->sAssocInfo.AssocInfo.RequestIELength += sFrame.pRSNWPA->len + WLAN_IEHDR_LEN;
-        memcpy(pbyIEs, sFrame.pRSNWPA, sFrame.pRSNWPA->len + WLAN_IEHDR_LEN);
-        pbyIEs += sFrame.pRSNWPA->len + WLAN_IEHDR_LEN;
-
-    } else if (((pMgmt->eAuthenMode == WMAC_AUTH_WPA2) ||
-                (pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK)) &&
-               (pMgmt->pCurrBSS != NULL)) {
-        unsigned int ii;
-        unsigned short *pwPMKID;
-
-        // WPA IE
-        sFrame.pRSN = (PWLAN_IE_RSN)(sFrame.pBuf + sFrame.len);
-        sFrame.pRSN->byElementID = WLAN_EID_RSN;
-        sFrame.pRSN->len = 6; //Version(2)+GK(4)
-        sFrame.pRSN->wVersion = 1;
-        //Group Key Cipher Suite
-        sFrame.pRSN->abyRSN[0] = 0x00;
-        sFrame.pRSN->abyRSN[1] = 0x0F;
-        sFrame.pRSN->abyRSN[2] = 0xAC;
-        if (pMgmt->byCSSGK == KEY_CTL_WEP) {
-            sFrame.pRSN->abyRSN[3] = pMgmt->pCurrBSS->byCSSGK;
-        } else if (pMgmt->byCSSGK == KEY_CTL_TKIP) {
-            sFrame.pRSN->abyRSN[3] = WLAN_11i_CSS_TKIP;
-        } else if (pMgmt->byCSSGK == KEY_CTL_CCMP) {
-            sFrame.pRSN->abyRSN[3] = WLAN_11i_CSS_CCMP;
-        } else {
-            sFrame.pRSN->abyRSN[3] = WLAN_11i_CSS_UNKNOWN;
-        }
-
-        // Pairwise Key Cipher Suite
-        sFrame.pRSN->abyRSN[4] = 1;
-        sFrame.pRSN->abyRSN[5] = 0;
-        sFrame.pRSN->abyRSN[6] = 0x00;
-        sFrame.pRSN->abyRSN[7] = 0x0F;
-        sFrame.pRSN->abyRSN[8] = 0xAC;
-        if (pMgmt->byCSSPK == KEY_CTL_TKIP) {
-            sFrame.pRSN->abyRSN[9] = WLAN_11i_CSS_TKIP;
-        } else if (pMgmt->byCSSPK == KEY_CTL_CCMP) {
-            sFrame.pRSN->abyRSN[9] = WLAN_11i_CSS_CCMP;
-        } else if (pMgmt->byCSSPK == KEY_CTL_NONE) {
-            sFrame.pRSN->abyRSN[9] = WLAN_11i_CSS_USE_GROUP;
-        } else {
-            sFrame.pRSN->abyRSN[9] = WLAN_11i_CSS_UNKNOWN;
-        }
-        sFrame.pRSN->len += 6;
-
-        // Auth Key Management Suite
-        sFrame.pRSN->abyRSN[10] = 1;
-        sFrame.pRSN->abyRSN[11] = 0;
-        sFrame.pRSN->abyRSN[12] = 0x00;
-        sFrame.pRSN->abyRSN[13] = 0x0F;
-        sFrame.pRSN->abyRSN[14] = 0xAC;
-        if (pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK) {
-            sFrame.pRSN->abyRSN[15] = WLAN_11i_AKMSS_PSK;
-        } else if (pMgmt->eAuthenMode == WMAC_AUTH_WPA2) {
-            sFrame.pRSN->abyRSN[15] = WLAN_11i_AKMSS_802_1X;
-        } else {
-            sFrame.pRSN->abyRSN[15] = WLAN_11i_AKMSS_UNKNOWN;
-        }
-        sFrame.pRSN->len +=6;
-
-        // RSN Capabilities
-        if (pMgmt->pCurrBSS->sRSNCapObj.bRSNCapExist == true) {
-            memcpy(&sFrame.pRSN->abyRSN[16], &pMgmt->pCurrBSS->sRSNCapObj.wRSNCap, 2);
-        } else {
-            sFrame.pRSN->abyRSN[16] = 0;
-            sFrame.pRSN->abyRSN[17] = 0;
-        }
-        sFrame.pRSN->len +=2;
-
-        if ((pDevice->gsPMKID.BSSIDInfoCount > 0) && (pDevice->bRoaming == true) && (pMgmt->eAuthenMode == WMAC_AUTH_WPA2)) {
-            // RSN PMKID
-            pbyRSN = &sFrame.pRSN->abyRSN[18];
-            pwPMKID = (unsigned short *)pbyRSN; // Point to PMKID count
-            *pwPMKID = 0;            // Initialize PMKID count
-            pbyRSN += 2;             // Point to PMKID list
-            for (ii = 0; ii < pDevice->gsPMKID.BSSIDInfoCount; ii++) {
-                if ( !memcmp(&pDevice->gsPMKID.BSSIDInfo[ii].BSSID[0], pMgmt->abyCurrBSSID, ETH_ALEN)) {
-                    (*pwPMKID) ++;
-                    memcpy(pbyRSN, pDevice->gsPMKID.BSSIDInfo[ii].PMKID, 16);
-                    pbyRSN += 16;
-                }
-            }
-            if (*pwPMKID != 0) {
-                sFrame.pRSN->len += (2 + (*pwPMKID)*16);
-            }
-        }
-
-        sFrame.len += sFrame.pRSN->len + WLAN_IEHDR_LEN;
-        // copy to AssocInfo. for OID_802_11_ASSOCIATION_INFORMATION
-        pMgmt->sAssocInfo.AssocInfo.RequestIELength += sFrame.pRSN->len + WLAN_IEHDR_LEN;
-        memcpy(pbyIEs, sFrame.pRSN, sFrame.pRSN->len + WLAN_IEHDR_LEN);
-        pbyIEs += sFrame.pRSN->len + WLAN_IEHDR_LEN;
-    }
-
-
-    // Adjust the length fields
-    pTxPacket->cbMPDULen = sFrame.len;
-    pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN;
-    return pTxPacket;
-}
-
+	PSTxMgmtPacket      pTxPacket = NULL;
+	WLAN_FR_ASSOCREQ    sFrame;
+	unsigned char *pbyIEs;
+	unsigned char *pbyRSN;
+
+	pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool;
+	memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_ASSOCREQ_FR_MAXLEN);
+	pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket));
+	// Setup the sFrame structure.
+	sFrame.pBuf = (unsigned char *)pTxPacket->p80211Header;
+	sFrame.len = WLAN_ASSOCREQ_FR_MAXLEN;
+	// format fixed field frame structure
+	vMgrEncodeAssocRequest(&sFrame);
+	// Setup the header
+	sFrame.pHdr->sA3.wFrameCtl = cpu_to_le16(
+		(
+			WLAN_SET_FC_FTYPE(WLAN_TYPE_MGR) |
+			WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_ASSOCREQ)
+));
+	memcpy(sFrame.pHdr->sA3.abyAddr1, pDAddr, WLAN_ADDR_LEN);
+	memcpy(sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN);
+	memcpy(sFrame.pHdr->sA3.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN);
+
+	// Set the capability and listen interval
+	*(sFrame.pwCapInfo) = cpu_to_le16(wCurrCapInfo);
+	*(sFrame.pwListenInterval) = cpu_to_le16(wListenInterval);
+
+	// sFrame.len point to end of fixed field
+	sFrame.pSSID = (PWLAN_IE_SSID)(sFrame.pBuf + sFrame.len);
+	sFrame.len += pCurrSSID->len + WLAN_IEHDR_LEN;
+	memcpy(sFrame.pSSID, pCurrSSID, pCurrSSID->len + WLAN_IEHDR_LEN);
+
+	pMgmt->sAssocInfo.AssocInfo.RequestIELength = pCurrSSID->len + WLAN_IEHDR_LEN;
+	pMgmt->sAssocInfo.AssocInfo.OffsetRequestIEs = sizeof(NDIS_802_11_ASSOCIATION_INFORMATION);
+	pbyIEs = pMgmt->sAssocInfo.abyIEs;
+	memcpy(pbyIEs, pCurrSSID, pCurrSSID->len + WLAN_IEHDR_LEN);
+	pbyIEs += pCurrSSID->len + WLAN_IEHDR_LEN;
+
+	// Copy the rate set
+	sFrame.pSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len);
+	if ((pDevice->eCurrentPHYType == PHY_TYPE_11B) && (pCurrRates->len > 4))
+		sFrame.len += 4 + WLAN_IEHDR_LEN;
+	else
+		sFrame.len += pCurrRates->len + WLAN_IEHDR_LEN;
+	memcpy(sFrame.pSuppRates, pCurrRates, pCurrRates->len + WLAN_IEHDR_LEN);
+
+	// Copy the extension rate set
+	if ((pDevice->eCurrentPHYType == PHY_TYPE_11G) && (pCurrExtSuppRates->len > 0)) {
+		sFrame.pExtSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len);
+		sFrame.len += pCurrExtSuppRates->len + WLAN_IEHDR_LEN;
+		memcpy(sFrame.pExtSuppRates, pCurrExtSuppRates, pCurrExtSuppRates->len + WLAN_IEHDR_LEN);
+	}
 
+	pMgmt->sAssocInfo.AssocInfo.RequestIELength += pCurrRates->len + WLAN_IEHDR_LEN;
+	memcpy(pbyIEs, pCurrRates, pCurrRates->len + WLAN_IEHDR_LEN);
+	pbyIEs += pCurrRates->len + WLAN_IEHDR_LEN;
+
+	// for 802.11h
+	if (pMgmt->b11hEnable == true) {
+		if (sFrame.pCurrPowerCap == NULL) {
+			sFrame.pCurrPowerCap = (PWLAN_IE_PW_CAP)(sFrame.pBuf + sFrame.len);
+			sFrame.len += (2 + WLAN_IEHDR_LEN);
+			sFrame.pCurrPowerCap->byElementID = WLAN_EID_PWR_CAPABILITY;
+			sFrame.pCurrPowerCap->len = 2;
+			CARDvGetPowerCapability(pMgmt->pAdapter,
+						&(sFrame.pCurrPowerCap->byMinPower),
+						&(sFrame.pCurrPowerCap->byMaxPower)
+);
+		}
+		if (sFrame.pCurrSuppCh == NULL) {
+			sFrame.pCurrSuppCh = (PWLAN_IE_SUPP_CH)(sFrame.pBuf + sFrame.len);
+			sFrame.len += set_support_channels(pMgmt->pAdapter, (unsigned char *)sFrame.pCurrSuppCh);
+		}
+	}
 
+	if (((pMgmt->eAuthenMode == WMAC_AUTH_WPA) ||
+	     (pMgmt->eAuthenMode == WMAC_AUTH_WPAPSK) ||
+	     (pMgmt->eAuthenMode == WMAC_AUTH_WPANONE)) &&
+	    (pMgmt->pCurrBSS != NULL)) {
+		/* WPA IE */
+		sFrame.pRSNWPA = (PWLAN_IE_RSN_EXT)(sFrame.pBuf + sFrame.len);
+		sFrame.pRSNWPA->byElementID = WLAN_EID_RSN_WPA;
+		sFrame.pRSNWPA->len = 16;
+		sFrame.pRSNWPA->abyOUI[0] = 0x00;
+		sFrame.pRSNWPA->abyOUI[1] = 0x50;
+		sFrame.pRSNWPA->abyOUI[2] = 0xf2;
+		sFrame.pRSNWPA->abyOUI[3] = 0x01;
+		sFrame.pRSNWPA->wVersion = 1;
+		//Group Key Cipher Suite
+		sFrame.pRSNWPA->abyMulticast[0] = 0x00;
+		sFrame.pRSNWPA->abyMulticast[1] = 0x50;
+		sFrame.pRSNWPA->abyMulticast[2] = 0xf2;
+		if (pMgmt->byCSSGK == KEY_CTL_WEP) {
+			sFrame.pRSNWPA->abyMulticast[3] = pMgmt->pCurrBSS->byGKType;
+		} else if (pMgmt->byCSSGK == KEY_CTL_TKIP) {
+			sFrame.pRSNWPA->abyMulticast[3] = WPA_TKIP;
+		} else if (pMgmt->byCSSGK == KEY_CTL_CCMP) {
+			sFrame.pRSNWPA->abyMulticast[3] = WPA_AESCCMP;
+		} else {
+			sFrame.pRSNWPA->abyMulticast[3] = WPA_NONE;
+		}
+		// Pairwise Key Cipher Suite
+		sFrame.pRSNWPA->wPKCount = 1;
+		sFrame.pRSNWPA->PKSList[0].abyOUI[0] = 0x00;
+		sFrame.pRSNWPA->PKSList[0].abyOUI[1] = 0x50;
+		sFrame.pRSNWPA->PKSList[0].abyOUI[2] = 0xf2;
+		if (pMgmt->byCSSPK == KEY_CTL_TKIP) {
+			sFrame.pRSNWPA->PKSList[0].abyOUI[3] = WPA_TKIP;
+		} else if (pMgmt->byCSSPK == KEY_CTL_CCMP) {
+			sFrame.pRSNWPA->PKSList[0].abyOUI[3] = WPA_AESCCMP;
+		} else {
+			sFrame.pRSNWPA->PKSList[0].abyOUI[3] = WPA_NONE;
+		}
+		// Auth Key Management Suite
+		pbyRSN = (unsigned char *)(sFrame.pBuf + sFrame.len + 2 + sFrame.pRSNWPA->len);
+		*pbyRSN++ = 0x01;
+		*pbyRSN++ = 0x00;
+		*pbyRSN++ = 0x00;
+
+		*pbyRSN++ = 0x50;
+		*pbyRSN++ = 0xf2;
+		if (pMgmt->eAuthenMode == WMAC_AUTH_WPAPSK) {
+			*pbyRSN++ = WPA_AUTH_PSK;
+		} else if (pMgmt->eAuthenMode == WMAC_AUTH_WPA) {
+			*pbyRSN++ = WPA_AUTH_IEEE802_1X;
+		} else {
+			*pbyRSN++ = WPA_NONE;
+		}
 
+		sFrame.pRSNWPA->len += 6;
+
+		// RSN Capabilities
+
+		*pbyRSN++ = 0x00;
+		*pbyRSN++ = 0x00;
+		sFrame.pRSNWPA->len += 2;
+
+		sFrame.len += sFrame.pRSNWPA->len + WLAN_IEHDR_LEN;
+		// copy to AssocInfo. for OID_802_11_ASSOCIATION_INFORMATION
+		pMgmt->sAssocInfo.AssocInfo.RequestIELength += sFrame.pRSNWPA->len + WLAN_IEHDR_LEN;
+		memcpy(pbyIEs, sFrame.pRSNWPA, sFrame.pRSNWPA->len + WLAN_IEHDR_LEN);
+		pbyIEs += sFrame.pRSNWPA->len + WLAN_IEHDR_LEN;
+
+	} else if (((pMgmt->eAuthenMode == WMAC_AUTH_WPA2) ||
+		    (pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK)) &&
+		   (pMgmt->pCurrBSS != NULL)) {
+		unsigned int ii;
+		unsigned short *pwPMKID;
+
+		// WPA IE
+		sFrame.pRSN = (PWLAN_IE_RSN)(sFrame.pBuf + sFrame.len);
+		sFrame.pRSN->byElementID = WLAN_EID_RSN;
+		sFrame.pRSN->len = 6; //Version(2)+GK(4)
+		sFrame.pRSN->wVersion = 1;
+		//Group Key Cipher Suite
+		sFrame.pRSN->abyRSN[0] = 0x00;
+		sFrame.pRSN->abyRSN[1] = 0x0F;
+		sFrame.pRSN->abyRSN[2] = 0xAC;
+		if (pMgmt->byCSSGK == KEY_CTL_WEP) {
+			sFrame.pRSN->abyRSN[3] = pMgmt->pCurrBSS->byCSSGK;
+		} else if (pMgmt->byCSSGK == KEY_CTL_TKIP) {
+			sFrame.pRSN->abyRSN[3] = WLAN_11i_CSS_TKIP;
+		} else if (pMgmt->byCSSGK == KEY_CTL_CCMP) {
+			sFrame.pRSN->abyRSN[3] = WLAN_11i_CSS_CCMP;
+		} else {
+			sFrame.pRSN->abyRSN[3] = WLAN_11i_CSS_UNKNOWN;
+		}
 
+		// Pairwise Key Cipher Suite
+		sFrame.pRSN->abyRSN[4] = 1;
+		sFrame.pRSN->abyRSN[5] = 0;
+		sFrame.pRSN->abyRSN[6] = 0x00;
+		sFrame.pRSN->abyRSN[7] = 0x0F;
+		sFrame.pRSN->abyRSN[8] = 0xAC;
+		if (pMgmt->byCSSPK == KEY_CTL_TKIP) {
+			sFrame.pRSN->abyRSN[9] = WLAN_11i_CSS_TKIP;
+		} else if (pMgmt->byCSSPK == KEY_CTL_CCMP) {
+			sFrame.pRSN->abyRSN[9] = WLAN_11i_CSS_CCMP;
+		} else if (pMgmt->byCSSPK == KEY_CTL_NONE) {
+			sFrame.pRSN->abyRSN[9] = WLAN_11i_CSS_USE_GROUP;
+		} else {
+			sFrame.pRSN->abyRSN[9] = WLAN_11i_CSS_UNKNOWN;
+		}
+		sFrame.pRSN->len += 6;
+
+		// Auth Key Management Suite
+		sFrame.pRSN->abyRSN[10] = 1;
+		sFrame.pRSN->abyRSN[11] = 0;
+		sFrame.pRSN->abyRSN[12] = 0x00;
+		sFrame.pRSN->abyRSN[13] = 0x0F;
+		sFrame.pRSN->abyRSN[14] = 0xAC;
+		if (pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK) {
+			sFrame.pRSN->abyRSN[15] = WLAN_11i_AKMSS_PSK;
+		} else if (pMgmt->eAuthenMode == WMAC_AUTH_WPA2) {
+			sFrame.pRSN->abyRSN[15] = WLAN_11i_AKMSS_802_1X;
+		} else {
+			sFrame.pRSN->abyRSN[15] = WLAN_11i_AKMSS_UNKNOWN;
+		}
+		sFrame.pRSN->len += 6;
+
+		// RSN Capabilities
+		if (pMgmt->pCurrBSS->sRSNCapObj.bRSNCapExist == true) {
+			memcpy(&sFrame.pRSN->abyRSN[16], &pMgmt->pCurrBSS->sRSNCapObj.wRSNCap, 2);
+		} else {
+			sFrame.pRSN->abyRSN[16] = 0;
+			sFrame.pRSN->abyRSN[17] = 0;
+		}
+		sFrame.pRSN->len += 2;
+
+		if ((pDevice->gsPMKID.BSSIDInfoCount > 0) && (pDevice->bRoaming == true) && (pMgmt->eAuthenMode == WMAC_AUTH_WPA2)) {
+			// RSN PMKID
+			pbyRSN = &sFrame.pRSN->abyRSN[18];
+			pwPMKID = (unsigned short *)pbyRSN; // Point to PMKID count
+			*pwPMKID = 0;            // Initialize PMKID count
+			pbyRSN += 2;             // Point to PMKID list
+			for (ii = 0; ii < pDevice->gsPMKID.BSSIDInfoCount; ii++) {
+				if (!memcmp(&pDevice->gsPMKID.BSSIDInfo[ii].BSSID[0], pMgmt->abyCurrBSSID, ETH_ALEN)) {
+					(*pwPMKID)++;
+					memcpy(pbyRSN, pDevice->gsPMKID.BSSIDInfo[ii].PMKID, 16);
+					pbyRSN += 16;
+				}
+			}
+			if (*pwPMKID != 0) {
+				sFrame.pRSN->len += (2 + (*pwPMKID)*16);
+			}
+		}
 
+		sFrame.len += sFrame.pRSN->len + WLAN_IEHDR_LEN;
+		// copy to AssocInfo. for OID_802_11_ASSOCIATION_INFORMATION
+		pMgmt->sAssocInfo.AssocInfo.RequestIELength += sFrame.pRSN->len + WLAN_IEHDR_LEN;
+		memcpy(pbyIEs, sFrame.pRSN, sFrame.pRSN->len + WLAN_IEHDR_LEN);
+		pbyIEs += sFrame.pRSN->len + WLAN_IEHDR_LEN;
+	}
 
+	// Adjust the length fields
+	pTxPacket->cbMPDULen = sFrame.len;
+	pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN;
+	return pTxPacket;
+}
 
 /*+
  *
@@ -3888,248 +3697,243 @@ s_MgrMakeAssocRequest(
  * Return Value:
  *    A ptr to frame or NULL on allocation failure
  *
--*/
-
+ -*/
 
 PSTxMgmtPacket
 s_MgrMakeReAssocRequest(
-    PSDevice pDevice,
-    PSMgmtObject pMgmt,
-    unsigned char *pDAddr,
-    unsigned short wCurrCapInfo,
-    unsigned short wListenInterval,
-    PWLAN_IE_SSID pCurrSSID,
-    PWLAN_IE_SUPP_RATES pCurrRates,
-    PWLAN_IE_SUPP_RATES pCurrExtSuppRates
-    )
+	PSDevice pDevice,
+	PSMgmtObject pMgmt,
+	unsigned char *pDAddr,
+	unsigned short wCurrCapInfo,
+	unsigned short wListenInterval,
+	PWLAN_IE_SSID pCurrSSID,
+	PWLAN_IE_SUPP_RATES pCurrRates,
+	PWLAN_IE_SUPP_RATES pCurrExtSuppRates
+)
 {
-    PSTxMgmtPacket      pTxPacket = NULL;
-    WLAN_FR_REASSOCREQ  sFrame;
-    unsigned char *pbyIEs;
-    unsigned char *pbyRSN;
-
-
-    pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool;
-    memset( pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_REASSOCREQ_FR_MAXLEN);
-    pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket));
-    /* Setup the sFrame structure. */
-    sFrame.pBuf = (unsigned char *)pTxPacket->p80211Header;
-    sFrame.len = WLAN_REASSOCREQ_FR_MAXLEN;
-
-    // format fixed field frame structure
-    vMgrEncodeReassocRequest(&sFrame);
-
-    /* Setup the header */
-    sFrame.pHdr->sA3.wFrameCtl = cpu_to_le16(
-        (
-        WLAN_SET_FC_FTYPE(WLAN_TYPE_MGR) |
-        WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_REASSOCREQ)
-        ));
-    memcpy( sFrame.pHdr->sA3.abyAddr1, pDAddr, WLAN_ADDR_LEN);
-    memcpy( sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN);
-    memcpy( sFrame.pHdr->sA3.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN);
-
-    /* Set the capability and listen interval */
-    *(sFrame.pwCapInfo) = cpu_to_le16(wCurrCapInfo);
-    *(sFrame.pwListenInterval) = cpu_to_le16(wListenInterval);
-
-    memcpy(sFrame.pAddrCurrAP, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN);
-    /* Copy the SSID */
-    /* sFrame.len point to end of fixed field */
-    sFrame.pSSID = (PWLAN_IE_SSID)(sFrame.pBuf + sFrame.len);
-    sFrame.len += pCurrSSID->len + WLAN_IEHDR_LEN;
-    memcpy(sFrame.pSSID, pCurrSSID, pCurrSSID->len + WLAN_IEHDR_LEN);
-
-    pMgmt->sAssocInfo.AssocInfo.RequestIELength = pCurrSSID->len + WLAN_IEHDR_LEN;
-    pMgmt->sAssocInfo.AssocInfo.OffsetRequestIEs = sizeof(NDIS_802_11_ASSOCIATION_INFORMATION);
-    pbyIEs = pMgmt->sAssocInfo.abyIEs;
-    memcpy(pbyIEs, pCurrSSID, pCurrSSID->len + WLAN_IEHDR_LEN);
-    pbyIEs += pCurrSSID->len + WLAN_IEHDR_LEN;
-
-    /* Copy the rate set */
-    /* sFrame.len point to end of SSID */
-    sFrame.pSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len);
-    sFrame.len += pCurrRates->len + WLAN_IEHDR_LEN;
-    memcpy(sFrame.pSuppRates, pCurrRates, pCurrRates->len + WLAN_IEHDR_LEN);
-
-    // Copy the extension rate set
-    if ((pMgmt->eCurrentPHYMode == PHY_TYPE_11G) && (pCurrExtSuppRates->len > 0)) {
-        sFrame.pExtSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len);
-        sFrame.len += pCurrExtSuppRates->len + WLAN_IEHDR_LEN;
-        memcpy(sFrame.pExtSuppRates, pCurrExtSuppRates, pCurrExtSuppRates->len + WLAN_IEHDR_LEN);
-    }
-
-    pMgmt->sAssocInfo.AssocInfo.RequestIELength += pCurrRates->len + WLAN_IEHDR_LEN;
-    memcpy(pbyIEs, pCurrRates, pCurrRates->len + WLAN_IEHDR_LEN);
-    pbyIEs += pCurrRates->len + WLAN_IEHDR_LEN;
-
-    if (((pMgmt->eAuthenMode == WMAC_AUTH_WPA) ||
-         (pMgmt->eAuthenMode == WMAC_AUTH_WPAPSK) ||
-         (pMgmt->eAuthenMode == WMAC_AUTH_WPANONE)) &&
-        (pMgmt->pCurrBSS != NULL)) {
-        /* WPA IE */
-        sFrame.pRSNWPA = (PWLAN_IE_RSN_EXT)(sFrame.pBuf + sFrame.len);
-        sFrame.pRSNWPA->byElementID = WLAN_EID_RSN_WPA;
-        sFrame.pRSNWPA->len = 16;
-        sFrame.pRSNWPA->abyOUI[0] = 0x00;
-        sFrame.pRSNWPA->abyOUI[1] = 0x50;
-        sFrame.pRSNWPA->abyOUI[2] = 0xf2;
-        sFrame.pRSNWPA->abyOUI[3] = 0x01;
-        sFrame.pRSNWPA->wVersion = 1;
-        //Group Key Cipher Suite
-        sFrame.pRSNWPA->abyMulticast[0] = 0x00;
-        sFrame.pRSNWPA->abyMulticast[1] = 0x50;
-        sFrame.pRSNWPA->abyMulticast[2] = 0xf2;
-        if (pMgmt->byCSSGK == KEY_CTL_WEP) {
-            sFrame.pRSNWPA->abyMulticast[3] = pMgmt->pCurrBSS->byGKType;
-        } else if (pMgmt->byCSSGK == KEY_CTL_TKIP) {
-            sFrame.pRSNWPA->abyMulticast[3] = WPA_TKIP;
-        } else if (pMgmt->byCSSGK == KEY_CTL_CCMP) {
-            sFrame.pRSNWPA->abyMulticast[3] = WPA_AESCCMP;
-        } else {
-            sFrame.pRSNWPA->abyMulticast[3] = WPA_NONE;
-        }
-        // Pairwise Key Cipher Suite
-        sFrame.pRSNWPA->wPKCount = 1;
-        sFrame.pRSNWPA->PKSList[0].abyOUI[0] = 0x00;
-        sFrame.pRSNWPA->PKSList[0].abyOUI[1] = 0x50;
-        sFrame.pRSNWPA->PKSList[0].abyOUI[2] = 0xf2;
-        if (pMgmt->byCSSPK == KEY_CTL_TKIP) {
-            sFrame.pRSNWPA->PKSList[0].abyOUI[3] = WPA_TKIP;
-        } else if (pMgmt->byCSSPK == KEY_CTL_CCMP) {
-            sFrame.pRSNWPA->PKSList[0].abyOUI[3] = WPA_AESCCMP;
-        } else {
-            sFrame.pRSNWPA->PKSList[0].abyOUI[3] = WPA_NONE;
-        }
-        // Auth Key Management Suite
-        pbyRSN = (unsigned char *)(sFrame.pBuf + sFrame.len + 2 + sFrame.pRSNWPA->len);
-        *pbyRSN++=0x01;
-        *pbyRSN++=0x00;
-        *pbyRSN++=0x00;
-
-        *pbyRSN++=0x50;
-        *pbyRSN++=0xf2;
-        if (pMgmt->eAuthenMode == WMAC_AUTH_WPAPSK) {
-            *pbyRSN++=WPA_AUTH_PSK;
-        } else if (pMgmt->eAuthenMode == WMAC_AUTH_WPA) {
-            *pbyRSN++=WPA_AUTH_IEEE802_1X;
-        } else {
-            *pbyRSN++=WPA_NONE;
-        }
-
-        sFrame.pRSNWPA->len +=6;
-
-        // RSN Capabilities
-        *pbyRSN++=0x00;
-        *pbyRSN++=0x00;
-        sFrame.pRSNWPA->len +=2;
-
-        sFrame.len += sFrame.pRSNWPA->len + WLAN_IEHDR_LEN;
-        // copy to AssocInfo. for OID_802_11_ASSOCIATION_INFORMATION
-        pMgmt->sAssocInfo.AssocInfo.RequestIELength += sFrame.pRSNWPA->len + WLAN_IEHDR_LEN;
-        memcpy(pbyIEs, sFrame.pRSNWPA, sFrame.pRSNWPA->len + WLAN_IEHDR_LEN);
-        pbyIEs += sFrame.pRSNWPA->len + WLAN_IEHDR_LEN;
-
-    } else if (((pMgmt->eAuthenMode == WMAC_AUTH_WPA2) ||
-                (pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK)) &&
-               (pMgmt->pCurrBSS != NULL)) {
-        unsigned int ii;
-        unsigned short *pwPMKID;
-
-        /* WPA IE */
-        sFrame.pRSN = (PWLAN_IE_RSN)(sFrame.pBuf + sFrame.len);
-        sFrame.pRSN->byElementID = WLAN_EID_RSN;
-        sFrame.pRSN->len = 6; //Version(2)+GK(4)
-        sFrame.pRSN->wVersion = 1;
-        //Group Key Cipher Suite
-        sFrame.pRSN->abyRSN[0] = 0x00;
-        sFrame.pRSN->abyRSN[1] = 0x0F;
-        sFrame.pRSN->abyRSN[2] = 0xAC;
-        if (pMgmt->byCSSGK == KEY_CTL_WEP) {
-            sFrame.pRSN->abyRSN[3] = pMgmt->pCurrBSS->byCSSGK;
-        } else if (pMgmt->byCSSGK == KEY_CTL_TKIP) {
-            sFrame.pRSN->abyRSN[3] = WLAN_11i_CSS_TKIP;
-        } else if (pMgmt->byCSSGK == KEY_CTL_CCMP) {
-            sFrame.pRSN->abyRSN[3] = WLAN_11i_CSS_CCMP;
-        } else {
-            sFrame.pRSN->abyRSN[3] = WLAN_11i_CSS_UNKNOWN;
-        }
-
-        // Pairwise Key Cipher Suite
-        sFrame.pRSN->abyRSN[4] = 1;
-        sFrame.pRSN->abyRSN[5] = 0;
-        sFrame.pRSN->abyRSN[6] = 0x00;
-        sFrame.pRSN->abyRSN[7] = 0x0F;
-        sFrame.pRSN->abyRSN[8] = 0xAC;
-        if (pMgmt->byCSSPK == KEY_CTL_TKIP) {
-            sFrame.pRSN->abyRSN[9] = WLAN_11i_CSS_TKIP;
-        } else if (pMgmt->byCSSPK == KEY_CTL_CCMP) {
-            sFrame.pRSN->abyRSN[9] = WLAN_11i_CSS_CCMP;
-        } else if (pMgmt->byCSSPK == KEY_CTL_NONE) {
-            sFrame.pRSN->abyRSN[9] = WLAN_11i_CSS_USE_GROUP;
-        } else {
-            sFrame.pRSN->abyRSN[9] = WLAN_11i_CSS_UNKNOWN;
-        }
-        sFrame.pRSN->len += 6;
-
-        // Auth Key Management Suite
-        sFrame.pRSN->abyRSN[10] = 1;
-        sFrame.pRSN->abyRSN[11] = 0;
-        sFrame.pRSN->abyRSN[12] = 0x00;
-        sFrame.pRSN->abyRSN[13] = 0x0F;
-        sFrame.pRSN->abyRSN[14] = 0xAC;
-        if (pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK) {
-            sFrame.pRSN->abyRSN[15] = WLAN_11i_AKMSS_PSK;
-        } else if (pMgmt->eAuthenMode == WMAC_AUTH_WPA2) {
-            sFrame.pRSN->abyRSN[15] = WLAN_11i_AKMSS_802_1X;
-        } else {
-            sFrame.pRSN->abyRSN[15] = WLAN_11i_AKMSS_UNKNOWN;
-        }
-        sFrame.pRSN->len +=6;
-
-        // RSN Capabilities
-        if (pMgmt->pCurrBSS->sRSNCapObj.bRSNCapExist == true) {
-            memcpy(&sFrame.pRSN->abyRSN[16], &pMgmt->pCurrBSS->sRSNCapObj.wRSNCap, 2);
-        } else {
-            sFrame.pRSN->abyRSN[16] = 0;
-            sFrame.pRSN->abyRSN[17] = 0;
-        }
-        sFrame.pRSN->len +=2;
-
-        if ((pDevice->gsPMKID.BSSIDInfoCount > 0) && (pDevice->bRoaming == true) && (pMgmt->eAuthenMode == WMAC_AUTH_WPA2)) {
-            // RSN PMKID
-            pbyRSN = &sFrame.pRSN->abyRSN[18];
-            pwPMKID = (unsigned short *)pbyRSN; // Point to PMKID count
-            *pwPMKID = 0;            // Initialize PMKID count
-            pbyRSN += 2;             // Point to PMKID list
-            for (ii = 0; ii < pDevice->gsPMKID.BSSIDInfoCount; ii++) {
-                if ( !memcmp(&pDevice->gsPMKID.BSSIDInfo[ii].BSSID[0], pMgmt->abyCurrBSSID, ETH_ALEN)) {
-                    (*pwPMKID) ++;
-                    memcpy(pbyRSN, pDevice->gsPMKID.BSSIDInfo[ii].PMKID, 16);
-                    pbyRSN += 16;
-                }
-            }
-            if (*pwPMKID != 0) {
-                sFrame.pRSN->len += (2 + (*pwPMKID)*16);
-            }
-        }
-
-        sFrame.len += sFrame.pRSN->len + WLAN_IEHDR_LEN;
-        // copy to AssocInfo. for OID_802_11_ASSOCIATION_INFORMATION
-        pMgmt->sAssocInfo.AssocInfo.RequestIELength += sFrame.pRSN->len + WLAN_IEHDR_LEN;
-        memcpy(pbyIEs, sFrame.pRSN, sFrame.pRSN->len + WLAN_IEHDR_LEN);
-        pbyIEs += sFrame.pRSN->len + WLAN_IEHDR_LEN;
-    }
-
-
-    /* Adjust the length fields */
-    pTxPacket->cbMPDULen = sFrame.len;
-    pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN;
-
-    return pTxPacket;
-}
+	PSTxMgmtPacket      pTxPacket = NULL;
+	WLAN_FR_REASSOCREQ  sFrame;
+	unsigned char *pbyIEs;
+	unsigned char *pbyRSN;
+
+	pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool;
+	memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_REASSOCREQ_FR_MAXLEN);
+	pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket));
+	/* Setup the sFrame structure. */
+	sFrame.pBuf = (unsigned char *)pTxPacket->p80211Header;
+	sFrame.len = WLAN_REASSOCREQ_FR_MAXLEN;
+
+	// format fixed field frame structure
+	vMgrEncodeReassocRequest(&sFrame);
+
+	/* Setup the header */
+	sFrame.pHdr->sA3.wFrameCtl = cpu_to_le16(
+		(
+			WLAN_SET_FC_FTYPE(WLAN_TYPE_MGR) |
+			WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_REASSOCREQ)
+));
+	memcpy(sFrame.pHdr->sA3.abyAddr1, pDAddr, WLAN_ADDR_LEN);
+	memcpy(sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN);
+	memcpy(sFrame.pHdr->sA3.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN);
+
+	/* Set the capability and listen interval */
+	*(sFrame.pwCapInfo) = cpu_to_le16(wCurrCapInfo);
+	*(sFrame.pwListenInterval) = cpu_to_le16(wListenInterval);
+
+	memcpy(sFrame.pAddrCurrAP, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN);
+	/* Copy the SSID */
+	/* sFrame.len point to end of fixed field */
+	sFrame.pSSID = (PWLAN_IE_SSID)(sFrame.pBuf + sFrame.len);
+	sFrame.len += pCurrSSID->len + WLAN_IEHDR_LEN;
+	memcpy(sFrame.pSSID, pCurrSSID, pCurrSSID->len + WLAN_IEHDR_LEN);
+
+	pMgmt->sAssocInfo.AssocInfo.RequestIELength = pCurrSSID->len + WLAN_IEHDR_LEN;
+	pMgmt->sAssocInfo.AssocInfo.OffsetRequestIEs = sizeof(NDIS_802_11_ASSOCIATION_INFORMATION);
+	pbyIEs = pMgmt->sAssocInfo.abyIEs;
+	memcpy(pbyIEs, pCurrSSID, pCurrSSID->len + WLAN_IEHDR_LEN);
+	pbyIEs += pCurrSSID->len + WLAN_IEHDR_LEN;
+
+	/* Copy the rate set */
+	/* sFrame.len point to end of SSID */
+	sFrame.pSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len);
+	sFrame.len += pCurrRates->len + WLAN_IEHDR_LEN;
+	memcpy(sFrame.pSuppRates, pCurrRates, pCurrRates->len + WLAN_IEHDR_LEN);
+
+	// Copy the extension rate set
+	if ((pMgmt->eCurrentPHYMode == PHY_TYPE_11G) && (pCurrExtSuppRates->len > 0)) {
+		sFrame.pExtSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len);
+		sFrame.len += pCurrExtSuppRates->len + WLAN_IEHDR_LEN;
+		memcpy(sFrame.pExtSuppRates, pCurrExtSuppRates, pCurrExtSuppRates->len + WLAN_IEHDR_LEN);
+	}
+
+	pMgmt->sAssocInfo.AssocInfo.RequestIELength += pCurrRates->len + WLAN_IEHDR_LEN;
+	memcpy(pbyIEs, pCurrRates, pCurrRates->len + WLAN_IEHDR_LEN);
+	pbyIEs += pCurrRates->len + WLAN_IEHDR_LEN;
+
+	if (((pMgmt->eAuthenMode == WMAC_AUTH_WPA) ||
+	     (pMgmt->eAuthenMode == WMAC_AUTH_WPAPSK) ||
+	     (pMgmt->eAuthenMode == WMAC_AUTH_WPANONE)) &&
+	    (pMgmt->pCurrBSS != NULL)) {
+		/* WPA IE */
+		sFrame.pRSNWPA = (PWLAN_IE_RSN_EXT)(sFrame.pBuf + sFrame.len);
+		sFrame.pRSNWPA->byElementID = WLAN_EID_RSN_WPA;
+		sFrame.pRSNWPA->len = 16;
+		sFrame.pRSNWPA->abyOUI[0] = 0x00;
+		sFrame.pRSNWPA->abyOUI[1] = 0x50;
+		sFrame.pRSNWPA->abyOUI[2] = 0xf2;
+		sFrame.pRSNWPA->abyOUI[3] = 0x01;
+		sFrame.pRSNWPA->wVersion = 1;
+		//Group Key Cipher Suite
+		sFrame.pRSNWPA->abyMulticast[0] = 0x00;
+		sFrame.pRSNWPA->abyMulticast[1] = 0x50;
+		sFrame.pRSNWPA->abyMulticast[2] = 0xf2;
+		if (pMgmt->byCSSGK == KEY_CTL_WEP) {
+			sFrame.pRSNWPA->abyMulticast[3] = pMgmt->pCurrBSS->byGKType;
+		} else if (pMgmt->byCSSGK == KEY_CTL_TKIP) {
+			sFrame.pRSNWPA->abyMulticast[3] = WPA_TKIP;
+		} else if (pMgmt->byCSSGK == KEY_CTL_CCMP) {
+			sFrame.pRSNWPA->abyMulticast[3] = WPA_AESCCMP;
+		} else {
+			sFrame.pRSNWPA->abyMulticast[3] = WPA_NONE;
+		}
+		// Pairwise Key Cipher Suite
+		sFrame.pRSNWPA->wPKCount = 1;
+		sFrame.pRSNWPA->PKSList[0].abyOUI[0] = 0x00;
+		sFrame.pRSNWPA->PKSList[0].abyOUI[1] = 0x50;
+		sFrame.pRSNWPA->PKSList[0].abyOUI[2] = 0xf2;
+		if (pMgmt->byCSSPK == KEY_CTL_TKIP) {
+			sFrame.pRSNWPA->PKSList[0].abyOUI[3] = WPA_TKIP;
+		} else if (pMgmt->byCSSPK == KEY_CTL_CCMP) {
+			sFrame.pRSNWPA->PKSList[0].abyOUI[3] = WPA_AESCCMP;
+		} else {
+			sFrame.pRSNWPA->PKSList[0].abyOUI[3] = WPA_NONE;
+		}
+		// Auth Key Management Suite
+		pbyRSN = (unsigned char *)(sFrame.pBuf + sFrame.len + 2 + sFrame.pRSNWPA->len);
+		*pbyRSN++ = 0x01;
+		*pbyRSN++ = 0x00;
+		*pbyRSN++ = 0x00;
+
+		*pbyRSN++ = 0x50;
+		*pbyRSN++ = 0xf2;
+		if (pMgmt->eAuthenMode == WMAC_AUTH_WPAPSK) {
+			*pbyRSN++ = WPA_AUTH_PSK;
+		} else if (pMgmt->eAuthenMode == WMAC_AUTH_WPA) {
+			*pbyRSN++ = WPA_AUTH_IEEE802_1X;
+		} else {
+			*pbyRSN++ = WPA_NONE;
+		}
 
+		sFrame.pRSNWPA->len += 6;
+
+		// RSN Capabilities
+		*pbyRSN++ = 0x00;
+		*pbyRSN++ = 0x00;
+		sFrame.pRSNWPA->len += 2;
+
+		sFrame.len += sFrame.pRSNWPA->len + WLAN_IEHDR_LEN;
+		// copy to AssocInfo. for OID_802_11_ASSOCIATION_INFORMATION
+		pMgmt->sAssocInfo.AssocInfo.RequestIELength += sFrame.pRSNWPA->len + WLAN_IEHDR_LEN;
+		memcpy(pbyIEs, sFrame.pRSNWPA, sFrame.pRSNWPA->len + WLAN_IEHDR_LEN);
+		pbyIEs += sFrame.pRSNWPA->len + WLAN_IEHDR_LEN;
+
+	} else if (((pMgmt->eAuthenMode == WMAC_AUTH_WPA2) ||
+		    (pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK)) &&
+		   (pMgmt->pCurrBSS != NULL)) {
+		unsigned int ii;
+		unsigned short *pwPMKID;
+
+		/* WPA IE */
+		sFrame.pRSN = (PWLAN_IE_RSN)(sFrame.pBuf + sFrame.len);
+		sFrame.pRSN->byElementID = WLAN_EID_RSN;
+		sFrame.pRSN->len = 6; //Version(2)+GK(4)
+		sFrame.pRSN->wVersion = 1;
+		//Group Key Cipher Suite
+		sFrame.pRSN->abyRSN[0] = 0x00;
+		sFrame.pRSN->abyRSN[1] = 0x0F;
+		sFrame.pRSN->abyRSN[2] = 0xAC;
+		if (pMgmt->byCSSGK == KEY_CTL_WEP) {
+			sFrame.pRSN->abyRSN[3] = pMgmt->pCurrBSS->byCSSGK;
+		} else if (pMgmt->byCSSGK == KEY_CTL_TKIP) {
+			sFrame.pRSN->abyRSN[3] = WLAN_11i_CSS_TKIP;
+		} else if (pMgmt->byCSSGK == KEY_CTL_CCMP) {
+			sFrame.pRSN->abyRSN[3] = WLAN_11i_CSS_CCMP;
+		} else {
+			sFrame.pRSN->abyRSN[3] = WLAN_11i_CSS_UNKNOWN;
+		}
 
+		// Pairwise Key Cipher Suite
+		sFrame.pRSN->abyRSN[4] = 1;
+		sFrame.pRSN->abyRSN[5] = 0;
+		sFrame.pRSN->abyRSN[6] = 0x00;
+		sFrame.pRSN->abyRSN[7] = 0x0F;
+		sFrame.pRSN->abyRSN[8] = 0xAC;
+		if (pMgmt->byCSSPK == KEY_CTL_TKIP) {
+			sFrame.pRSN->abyRSN[9] = WLAN_11i_CSS_TKIP;
+		} else if (pMgmt->byCSSPK == KEY_CTL_CCMP) {
+			sFrame.pRSN->abyRSN[9] = WLAN_11i_CSS_CCMP;
+		} else if (pMgmt->byCSSPK == KEY_CTL_NONE) {
+			sFrame.pRSN->abyRSN[9] = WLAN_11i_CSS_USE_GROUP;
+		} else {
+			sFrame.pRSN->abyRSN[9] = WLAN_11i_CSS_UNKNOWN;
+		}
+		sFrame.pRSN->len += 6;
+
+		// Auth Key Management Suite
+		sFrame.pRSN->abyRSN[10] = 1;
+		sFrame.pRSN->abyRSN[11] = 0;
+		sFrame.pRSN->abyRSN[12] = 0x00;
+		sFrame.pRSN->abyRSN[13] = 0x0F;
+		sFrame.pRSN->abyRSN[14] = 0xAC;
+		if (pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK) {
+			sFrame.pRSN->abyRSN[15] = WLAN_11i_AKMSS_PSK;
+		} else if (pMgmt->eAuthenMode == WMAC_AUTH_WPA2) {
+			sFrame.pRSN->abyRSN[15] = WLAN_11i_AKMSS_802_1X;
+		} else {
+			sFrame.pRSN->abyRSN[15] = WLAN_11i_AKMSS_UNKNOWN;
+		}
+		sFrame.pRSN->len += 6;
+
+		// RSN Capabilities
+		if (pMgmt->pCurrBSS->sRSNCapObj.bRSNCapExist == true) {
+			memcpy(&sFrame.pRSN->abyRSN[16], &pMgmt->pCurrBSS->sRSNCapObj.wRSNCap, 2);
+		} else {
+			sFrame.pRSN->abyRSN[16] = 0;
+			sFrame.pRSN->abyRSN[17] = 0;
+		}
+		sFrame.pRSN->len += 2;
+
+		if ((pDevice->gsPMKID.BSSIDInfoCount > 0) && (pDevice->bRoaming == true) && (pMgmt->eAuthenMode == WMAC_AUTH_WPA2)) {
+			// RSN PMKID
+			pbyRSN = &sFrame.pRSN->abyRSN[18];
+			pwPMKID = (unsigned short *)pbyRSN; // Point to PMKID count
+			*pwPMKID = 0;            // Initialize PMKID count
+			pbyRSN += 2;             // Point to PMKID list
+			for (ii = 0; ii < pDevice->gsPMKID.BSSIDInfoCount; ii++) {
+				if (!memcmp(&pDevice->gsPMKID.BSSIDInfo[ii].BSSID[0], pMgmt->abyCurrBSSID, ETH_ALEN)) {
+					(*pwPMKID)++;
+					memcpy(pbyRSN, pDevice->gsPMKID.BSSIDInfo[ii].PMKID, 16);
+					pbyRSN += 16;
+				}
+			}
+			if (*pwPMKID != 0) {
+				sFrame.pRSN->len += (2 + (*pwPMKID) * 16);
+			}
+		}
+
+		sFrame.len += sFrame.pRSN->len + WLAN_IEHDR_LEN;
+		// copy to AssocInfo. for OID_802_11_ASSOCIATION_INFORMATION
+		pMgmt->sAssocInfo.AssocInfo.RequestIELength += sFrame.pRSN->len + WLAN_IEHDR_LEN;
+		memcpy(pbyIEs, sFrame.pRSN, sFrame.pRSN->len + WLAN_IEHDR_LEN);
+		pbyIEs += sFrame.pRSN->len + WLAN_IEHDR_LEN;
+	}
+
+	/* Adjust the length fields */
+	pTxPacket->cbMPDULen = sFrame.len;
+	pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN;
+
+	return pTxPacket;
+}
 
 /*+
  *
@@ -4140,70 +3944,67 @@ s_MgrMakeReAssocRequest(
  * Return Value:
  *    PTR to frame; or NULL on allocation failure
  *
--*/
-
+ -*/
 
 PSTxMgmtPacket
 s_MgrMakeAssocResponse(
-    PSDevice pDevice,
-    PSMgmtObject pMgmt,
-    unsigned short wCurrCapInfo,
-    unsigned short wAssocStatus,
-    unsigned short wAssocAID,
-    unsigned char *pDstAddr,
-    PWLAN_IE_SUPP_RATES pCurrSuppRates,
-    PWLAN_IE_SUPP_RATES pCurrExtSuppRates
-    )
+	PSDevice pDevice,
+	PSMgmtObject pMgmt,
+	unsigned short wCurrCapInfo,
+	unsigned short wAssocStatus,
+	unsigned short wAssocAID,
+	unsigned char *pDstAddr,
+	PWLAN_IE_SUPP_RATES pCurrSuppRates,
+	PWLAN_IE_SUPP_RATES pCurrExtSuppRates
+)
 {
-    PSTxMgmtPacket      pTxPacket = NULL;
-    WLAN_FR_ASSOCRESP   sFrame;
-
-
-    pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool;
-    memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_ASSOCREQ_FR_MAXLEN);
-    pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket));
-    // Setup the sFrame structure
-    sFrame.pBuf = (unsigned char *)pTxPacket->p80211Header;
-    sFrame.len = WLAN_REASSOCRESP_FR_MAXLEN;
-    vMgrEncodeAssocResponse(&sFrame);
-    // Setup the header
-    sFrame.pHdr->sA3.wFrameCtl = cpu_to_le16(
-        (
-        WLAN_SET_FC_FTYPE(WLAN_TYPE_MGR) |
-        WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_ASSOCRESP)
-        ));
-    memcpy( sFrame.pHdr->sA3.abyAddr1, pDstAddr, WLAN_ADDR_LEN);
-    memcpy( sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN);
-    memcpy( sFrame.pHdr->sA3.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN);
-
-    *sFrame.pwCapInfo = cpu_to_le16(wCurrCapInfo);
-    *sFrame.pwStatus = cpu_to_le16(wAssocStatus);
-    *sFrame.pwAid = cpu_to_le16((unsigned short)(wAssocAID | BIT14 | BIT15));
-
-    // Copy the rate set
-    sFrame.pSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len);
-    sFrame.len += ((PWLAN_IE_SUPP_RATES)pCurrSuppRates)->len + WLAN_IEHDR_LEN;
-    memcpy(sFrame.pSuppRates,
-           pCurrSuppRates,
-           ((PWLAN_IE_SUPP_RATES)pCurrSuppRates)->len + WLAN_IEHDR_LEN
-          );
-
-    if (((PWLAN_IE_SUPP_RATES)pCurrExtSuppRates)->len != 0) {
-        sFrame.pExtSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len);
-        sFrame.len += ((PWLAN_IE_SUPP_RATES)pCurrExtSuppRates)->len + WLAN_IEHDR_LEN;
-        memcpy(sFrame.pExtSuppRates,
-             pCurrExtSuppRates,
-             ((PWLAN_IE_SUPP_RATES)pCurrExtSuppRates)->len + WLAN_IEHDR_LEN
-             );
-    }
-
-    // Adjust the length fields
-    pTxPacket->cbMPDULen = sFrame.len;
-    pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN;
-
-    return pTxPacket;
-}
+	PSTxMgmtPacket      pTxPacket = NULL;
+	WLAN_FR_ASSOCRESP   sFrame;
+
+	pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool;
+	memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_ASSOCREQ_FR_MAXLEN);
+	pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket));
+	// Setup the sFrame structure
+	sFrame.pBuf = (unsigned char *)pTxPacket->p80211Header;
+	sFrame.len = WLAN_REASSOCRESP_FR_MAXLEN;
+	vMgrEncodeAssocResponse(&sFrame);
+	// Setup the header
+	sFrame.pHdr->sA3.wFrameCtl = cpu_to_le16(
+		(
+			WLAN_SET_FC_FTYPE(WLAN_TYPE_MGR) |
+			WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_ASSOCRESP)
+));
+	memcpy(sFrame.pHdr->sA3.abyAddr1, pDstAddr, WLAN_ADDR_LEN);
+	memcpy(sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN);
+	memcpy(sFrame.pHdr->sA3.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN);
+
+	*sFrame.pwCapInfo = cpu_to_le16(wCurrCapInfo);
+	*sFrame.pwStatus = cpu_to_le16(wAssocStatus);
+	*sFrame.pwAid = cpu_to_le16((unsigned short)(wAssocAID | BIT14 | BIT15));
+
+	// Copy the rate set
+	sFrame.pSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len);
+	sFrame.len += ((PWLAN_IE_SUPP_RATES)pCurrSuppRates)->len + WLAN_IEHDR_LEN;
+	memcpy(sFrame.pSuppRates,
+	       pCurrSuppRates,
+	       ((PWLAN_IE_SUPP_RATES)pCurrSuppRates)->len + WLAN_IEHDR_LEN
+);
+
+	if (((PWLAN_IE_SUPP_RATES)pCurrExtSuppRates)->len != 0) {
+		sFrame.pExtSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len);
+		sFrame.len += ((PWLAN_IE_SUPP_RATES)pCurrExtSuppRates)->len + WLAN_IEHDR_LEN;
+		memcpy(sFrame.pExtSuppRates,
+		       pCurrExtSuppRates,
+		       ((PWLAN_IE_SUPP_RATES)pCurrExtSuppRates)->len + WLAN_IEHDR_LEN
+);
+	}
 
+	// Adjust the length fields
+	pTxPacket->cbMPDULen = sFrame.len;
+	pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN;
+
+	return pTxPacket;
+}
 
 /*+
  *
@@ -4214,70 +4015,67 @@ s_MgrMakeAssocResponse(
  * Return Value:
  *    PTR to frame; or NULL on allocation failure
  *
--*/
-
+ -*/
 
 PSTxMgmtPacket
 s_MgrMakeReAssocResponse(
-    PSDevice pDevice,
-    PSMgmtObject pMgmt,
-    unsigned short wCurrCapInfo,
-    unsigned short wAssocStatus,
-    unsigned short wAssocAID,
-    unsigned char *pDstAddr,
-    PWLAN_IE_SUPP_RATES pCurrSuppRates,
-    PWLAN_IE_SUPP_RATES pCurrExtSuppRates
-    )
+	PSDevice pDevice,
+	PSMgmtObject pMgmt,
+	unsigned short wCurrCapInfo,
+	unsigned short wAssocStatus,
+	unsigned short wAssocAID,
+	unsigned char *pDstAddr,
+	PWLAN_IE_SUPP_RATES pCurrSuppRates,
+	PWLAN_IE_SUPP_RATES pCurrExtSuppRates
+)
 {
-    PSTxMgmtPacket      pTxPacket = NULL;
-    WLAN_FR_REASSOCRESP   sFrame;
-
-
-    pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool;
-    memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_ASSOCREQ_FR_MAXLEN);
-    pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket));
-    // Setup the sFrame structure
-    sFrame.pBuf = (unsigned char *)pTxPacket->p80211Header;
-    sFrame.len = WLAN_REASSOCRESP_FR_MAXLEN;
-    vMgrEncodeReassocResponse(&sFrame);
-    // Setup the header
-    sFrame.pHdr->sA3.wFrameCtl = cpu_to_le16(
-        (
-        WLAN_SET_FC_FTYPE(WLAN_TYPE_MGR) |
-        WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_REASSOCRESP)
-        ));
-    memcpy( sFrame.pHdr->sA3.abyAddr1, pDstAddr, WLAN_ADDR_LEN);
-    memcpy( sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN);
-    memcpy( sFrame.pHdr->sA3.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN);
-
-    *sFrame.pwCapInfo = cpu_to_le16(wCurrCapInfo);
-    *sFrame.pwStatus = cpu_to_le16(wAssocStatus);
-    *sFrame.pwAid = cpu_to_le16((unsigned short)(wAssocAID | BIT14 | BIT15));
-
-    // Copy the rate set
-    sFrame.pSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len);
-    sFrame.len += ((PWLAN_IE_SUPP_RATES)pCurrSuppRates)->len + WLAN_IEHDR_LEN;
-    memcpy(sFrame.pSuppRates,
-             pCurrSuppRates,
-             ((PWLAN_IE_SUPP_RATES)pCurrSuppRates)->len + WLAN_IEHDR_LEN
-             );
-
-    if (((PWLAN_IE_SUPP_RATES)pCurrExtSuppRates)->len != 0) {
-        sFrame.pExtSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len);
-        sFrame.len += ((PWLAN_IE_SUPP_RATES)pCurrExtSuppRates)->len + WLAN_IEHDR_LEN;
-        memcpy(sFrame.pExtSuppRates,
-             pCurrExtSuppRates,
-             ((PWLAN_IE_SUPP_RATES)pCurrExtSuppRates)->len + WLAN_IEHDR_LEN
-             );
-    }
-
-    // Adjust the length fields
-    pTxPacket->cbMPDULen = sFrame.len;
-    pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN;
-
-    return pTxPacket;
-}
+	PSTxMgmtPacket      pTxPacket = NULL;
+	WLAN_FR_REASSOCRESP   sFrame;
+
+	pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool;
+	memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_ASSOCREQ_FR_MAXLEN);
+	pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket));
+	// Setup the sFrame structure
+	sFrame.pBuf = (unsigned char *)pTxPacket->p80211Header;
+	sFrame.len = WLAN_REASSOCRESP_FR_MAXLEN;
+	vMgrEncodeReassocResponse(&sFrame);
+	// Setup the header
+	sFrame.pHdr->sA3.wFrameCtl = cpu_to_le16(
+		(
+			WLAN_SET_FC_FTYPE(WLAN_TYPE_MGR) |
+			WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_REASSOCRESP)
+));
+	memcpy(sFrame.pHdr->sA3.abyAddr1, pDstAddr, WLAN_ADDR_LEN);
+	memcpy(sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN);
+	memcpy(sFrame.pHdr->sA3.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN);
+
+	*sFrame.pwCapInfo = cpu_to_le16(wCurrCapInfo);
+	*sFrame.pwStatus = cpu_to_le16(wAssocStatus);
+	*sFrame.pwAid = cpu_to_le16((unsigned short)(wAssocAID | BIT14 | BIT15));
+
+	// Copy the rate set
+	sFrame.pSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len);
+	sFrame.len += ((PWLAN_IE_SUPP_RATES)pCurrSuppRates)->len + WLAN_IEHDR_LEN;
+	memcpy(sFrame.pSuppRates,
+	       pCurrSuppRates,
+	       ((PWLAN_IE_SUPP_RATES)pCurrSuppRates)->len + WLAN_IEHDR_LEN
+);
+
+	if (((PWLAN_IE_SUPP_RATES)pCurrExtSuppRates)->len != 0) {
+		sFrame.pExtSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len);
+		sFrame.len += ((PWLAN_IE_SUPP_RATES)pCurrExtSuppRates)->len + WLAN_IEHDR_LEN;
+		memcpy(sFrame.pExtSuppRates,
+		       pCurrExtSuppRates,
+		       ((PWLAN_IE_SUPP_RATES)pCurrExtSuppRates)->len + WLAN_IEHDR_LEN
+);
+	}
+
+	// Adjust the length fields
+	pTxPacket->cbMPDULen = sFrame.len;
+	pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN;
 
+	return pTxPacket;
+}
 
 /*+
  *
@@ -4288,119 +4086,115 @@ s_MgrMakeReAssocResponse(
  * Return Value:
  *    none.
  *
--*/
+ -*/
 
 static
 void
 s_vMgrRxProbeResponse(
-    PSDevice pDevice,
-    PSMgmtObject pMgmt,
-    PSRxMgmtPacket pRxPacket
-    )
+	PSDevice pDevice,
+	PSMgmtObject pMgmt,
+	PSRxMgmtPacket pRxPacket
+)
 {
-    PKnownBSS           pBSSList = NULL;
-    WLAN_FR_PROBERESP   sFrame;
-    unsigned char byCurrChannel = pRxPacket->byRxChannel;
-    ERPObject           sERP;
-    unsigned char byIEChannel = 0;
-    bool bChannelHit = true;
-
-
-    memset(&sFrame, 0, sizeof(WLAN_FR_PROBERESP));
-    // decode the frame
-    sFrame.len = pRxPacket->cbMPDULen;
-    sFrame.pBuf = (unsigned char *)pRxPacket->p80211Header;
-    vMgrDecodeProbeResponse(&sFrame);
-
-    if ((sFrame.pqwTimestamp == 0) ||
-        (sFrame.pwBeaconInterval == 0) ||
-        (sFrame.pwCapInfo == 0) ||
-        (sFrame.pSSID == 0) ||
-        (sFrame.pSuppRates == 0)) {
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Probe resp:Fail addr:[%p] \n", pRxPacket->p80211Header);
-        DBG_PORT80(0xCC);
-        return;
-    }
-
-    if(sFrame.pSSID->len == 0)
-       DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Rx Probe resp: SSID len = 0 \n");
-
-    if (sFrame.pDSParms != 0) {
-        if (byCurrChannel > CB_MAX_CHANNEL_24G) {
-            // channel remapping to
-            byIEChannel = get_channel_mapping(pMgmt->pAdapter, sFrame.pDSParms->byCurrChannel, PHY_TYPE_11A);
-        } else {
-            byIEChannel = sFrame.pDSParms->byCurrChannel;
-        }
-        if (byCurrChannel != byIEChannel) {
-            // adjust channel info. bcs we rcv adjacent channel packets
-            bChannelHit = false;
-            byCurrChannel = byIEChannel;
-        }
-    } else {
-        // no DS channel info
-        bChannelHit = true;
-    }
+	PKnownBSS           pBSSList = NULL;
+	WLAN_FR_PROBERESP   sFrame;
+	unsigned char byCurrChannel = pRxPacket->byRxChannel;
+	ERPObject           sERP;
+	unsigned char byIEChannel = 0;
+	bool bChannelHit = true;
+
+	memset(&sFrame, 0, sizeof(WLAN_FR_PROBERESP));
+	// decode the frame
+	sFrame.len = pRxPacket->cbMPDULen;
+	sFrame.pBuf = (unsigned char *)pRxPacket->p80211Header;
+	vMgrDecodeProbeResponse(&sFrame);
+
+	if ((sFrame.pqwTimestamp == 0) ||
+	    (sFrame.pwBeaconInterval == 0) ||
+	    (sFrame.pwCapInfo == 0) ||
+	    (sFrame.pSSID == 0) ||
+	    (sFrame.pSuppRates == 0)) {
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Probe resp:Fail addr:[%p] \n", pRxPacket->p80211Header);
+		DBG_PORT80(0xCC);
+		return;
+	}
+
+	if (sFrame.pSSID->len == 0)
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Rx Probe resp: SSID len = 0 \n");
+
+	if (sFrame.pDSParms != 0) {
+		if (byCurrChannel > CB_MAX_CHANNEL_24G) {
+			// channel remapping to
+			byIEChannel = get_channel_mapping(pMgmt->pAdapter, sFrame.pDSParms->byCurrChannel, PHY_TYPE_11A);
+		} else {
+			byIEChannel = sFrame.pDSParms->byCurrChannel;
+		}
+		if (byCurrChannel != byIEChannel) {
+			// adjust channel info. bcs we rcv adjacent channel packets
+			bChannelHit = false;
+			byCurrChannel = byIEChannel;
+		}
+	} else {
+		// no DS channel info
+		bChannelHit = true;
+	}
 
 //2008-0730-01<Add>by MikeLiu
-if(ChannelExceedZoneType(pDevice,byCurrChannel)==true)
-      return;
-
-    if (sFrame.pERP != NULL) {
-        sERP.byERP = sFrame.pERP->byContext;
-        sERP.bERPExist = true;
-    } else {
-        sERP.bERPExist = false;
-        sERP.byERP = 0;
-    }
-
-
-    // update or insert the bss
-    pBSSList = BSSpAddrIsInBSSList((void *)pDevice, sFrame.pHdr->sA3.abyAddr3, sFrame.pSSID);
-    if (pBSSList) {
-        BSSbUpdateToBSSList((void *)pDevice,
-                            *sFrame.pqwTimestamp,
-                            *sFrame.pwBeaconInterval,
-                            *sFrame.pwCapInfo,
-                            byCurrChannel,
-                            bChannelHit,
-                            sFrame.pSSID,
-                            sFrame.pSuppRates,
-                            sFrame.pExtSuppRates,
-                            &sERP,
-                            sFrame.pRSN,
-                            sFrame.pRSNWPA,
-                            sFrame.pIE_Country,
-                            sFrame.pIE_Quiet,
-                            pBSSList,
-                            sFrame.len - WLAN_HDR_ADDR3_LEN,
-                            sFrame.pHdr->sA4.abyAddr4,   // payload of probresponse
-                            (void *)pRxPacket
-                           );
-    }
-    else {
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Probe resp/insert: RxChannel = : %d\n", byCurrChannel);
-        BSSbInsertToBSSList((void *)pDevice,
-                            sFrame.pHdr->sA3.abyAddr3,
-                            *sFrame.pqwTimestamp,
-                            *sFrame.pwBeaconInterval,
-                            *sFrame.pwCapInfo,
-                            byCurrChannel,
-                            sFrame.pSSID,
-                            sFrame.pSuppRates,
-                            sFrame.pExtSuppRates,
-                            &sERP,
-                            sFrame.pRSN,
-                            sFrame.pRSNWPA,
-                            sFrame.pIE_Country,
-                            sFrame.pIE_Quiet,
-                            sFrame.len - WLAN_HDR_ADDR3_LEN,
-                            sFrame.pHdr->sA4.abyAddr4,   // payload of beacon
-                            (void *)pRxPacket
-                           );
-    }
-    return;
+	if (ChannelExceedZoneType(pDevice, byCurrChannel) == true)
+		return;
+
+	if (sFrame.pERP != NULL) {
+		sERP.byERP = sFrame.pERP->byContext;
+		sERP.bERPExist = true;
+	} else {
+		sERP.bERPExist = false;
+		sERP.byERP = 0;
+	}
 
+	// update or insert the bss
+	pBSSList = BSSpAddrIsInBSSList((void *)pDevice, sFrame.pHdr->sA3.abyAddr3, sFrame.pSSID);
+	if (pBSSList) {
+		BSSbUpdateToBSSList((void *)pDevice,
+				    *sFrame.pqwTimestamp,
+				    *sFrame.pwBeaconInterval,
+				    *sFrame.pwCapInfo,
+				    byCurrChannel,
+				    bChannelHit,
+				    sFrame.pSSID,
+				    sFrame.pSuppRates,
+				    sFrame.pExtSuppRates,
+				    &sERP,
+				    sFrame.pRSN,
+				    sFrame.pRSNWPA,
+				    sFrame.pIE_Country,
+				    sFrame.pIE_Quiet,
+				    pBSSList,
+				    sFrame.len - WLAN_HDR_ADDR3_LEN,
+				    sFrame.pHdr->sA4.abyAddr4,   // payload of probresponse
+				    (void *)pRxPacket
+);
+	} else {
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Probe resp/insert: RxChannel = : %d\n", byCurrChannel);
+		BSSbInsertToBSSList((void *)pDevice,
+				    sFrame.pHdr->sA3.abyAddr3,
+				    *sFrame.pqwTimestamp,
+				    *sFrame.pwBeaconInterval,
+				    *sFrame.pwCapInfo,
+				    byCurrChannel,
+				    sFrame.pSSID,
+				    sFrame.pSuppRates,
+				    sFrame.pExtSuppRates,
+				    &sERP,
+				    sFrame.pRSN,
+				    sFrame.pRSNWPA,
+				    sFrame.pIE_Country,
+				    sFrame.pIE_Quiet,
+				    sFrame.len - WLAN_HDR_ADDR3_LEN,
+				    sFrame.pHdr->sA4.abyAddr4,   // payload of beacon
+				    (void *)pRxPacket
+);
+	}
+	return;
 }
 
 /*+
@@ -4412,84 +4206,77 @@ if(ChannelExceedZoneType(pDevice,byCurrChannel)==true)
  * Return Value:
  *    none.
  *
--*/
-
+ -*/
 
 static
 void
 s_vMgrRxProbeRequest(
-    PSDevice pDevice,
-    PSMgmtObject pMgmt,
-    PSRxMgmtPacket pRxPacket
-    )
+	PSDevice pDevice,
+	PSMgmtObject pMgmt,
+	PSRxMgmtPacket pRxPacket
+)
 {
-    WLAN_FR_PROBEREQ    sFrame;
-    CMD_STATUS          Status;
-    PSTxMgmtPacket      pTxPacket;
-    unsigned char byPHYType = BB_TYPE_11B;
-
-    // STA in Ad-hoc mode: when latest TBTT beacon transmit success,
-    // STA have to response this request.
-    if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) ||
-        ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) && pDevice->bBeaconSent)) {
-
-        memset(&sFrame, 0, sizeof(WLAN_FR_PROBEREQ));
-        // decode the frame
-        sFrame.len = pRxPacket->cbMPDULen;
-        sFrame.pBuf = (unsigned char *)pRxPacket->p80211Header;
-        vMgrDecodeProbeRequest(&sFrame);
+	WLAN_FR_PROBEREQ    sFrame;
+	CMD_STATUS          Status;
+	PSTxMgmtPacket      pTxPacket;
+	unsigned char byPHYType = BB_TYPE_11B;
+
+	// STA in Ad-hoc mode: when latest TBTT beacon transmit success,
+	// STA have to response this request.
+	if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) ||
+	    ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) && pDevice->bBeaconSent)) {
+		memset(&sFrame, 0, sizeof(WLAN_FR_PROBEREQ));
+		// decode the frame
+		sFrame.len = pRxPacket->cbMPDULen;
+		sFrame.pBuf = (unsigned char *)pRxPacket->p80211Header;
+		vMgrDecodeProbeRequest(&sFrame);
 /*
-	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Probe request rx:MAC addr:%pM\n",
-		sFrame.pHdr->sA3.abyAddr2);
+  DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Probe request rx:MAC addr:%pM\n",
+  sFrame.pHdr->sA3.abyAddr2);
 */
-        if (sFrame.pSSID->len != 0) {
-            if (sFrame.pSSID->len != ((PWLAN_IE_SSID)pMgmt->abyCurrSSID)->len)
-                return;
-            if (memcmp(sFrame.pSSID->abySSID,
-                       ((PWLAN_IE_SSID)pMgmt->abyCurrSSID)->abySSID,
-                       ((PWLAN_IE_SSID)pMgmt->abyCurrSSID)->len) != 0) {
-                       return;
-            }
-        }
-
-        if ((sFrame.pSuppRates->len > 4) || (sFrame.pExtSuppRates != NULL)) {
-            byPHYType = BB_TYPE_11G;
-        }
-
-        // Probe response reply..
-        pTxPacket = s_MgrMakeProbeResponse
-                    (
-                      pDevice,
-                      pMgmt,
-                      pMgmt->wCurrCapInfo,
-                      pMgmt->wCurrBeaconPeriod,
-                      pMgmt->uCurrChannel,
-                      0,
-                      sFrame.pHdr->sA3.abyAddr2,
-                      (PWLAN_IE_SSID)pMgmt->abyCurrSSID,
-                      (unsigned char *)pMgmt->abyCurrBSSID,
-                      (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates,
-                      (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates,
-                       byPHYType
-                    );
-        if (pTxPacket != NULL ){
-            /* send the frame */
-            Status = csMgmt_xmit(pDevice, pTxPacket);
-            if (Status != CMD_STATUS_PENDING) {
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt:Probe response tx failed\n");
-            }
-            else {
-//                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt:Probe response tx sending..\n");
-            }
-        }
-    }
-
-    return;
-}
-
+		if (sFrame.pSSID->len != 0) {
+			if (sFrame.pSSID->len != ((PWLAN_IE_SSID)pMgmt->abyCurrSSID)->len)
+				return;
+			if (memcmp(sFrame.pSSID->abySSID,
+				   ((PWLAN_IE_SSID)pMgmt->abyCurrSSID)->abySSID,
+				   ((PWLAN_IE_SSID)pMgmt->abyCurrSSID)->len) != 0) {
+				return;
+			}
+		}
 
+		if ((sFrame.pSuppRates->len > 4) || (sFrame.pExtSuppRates != NULL)) {
+			byPHYType = BB_TYPE_11G;
+		}
 
+		// Probe response reply..
+		pTxPacket = s_MgrMakeProbeResponse
+			(
+				pDevice,
+				pMgmt,
+				pMgmt->wCurrCapInfo,
+				pMgmt->wCurrBeaconPeriod,
+				pMgmt->uCurrChannel,
+				0,
+				sFrame.pHdr->sA3.abyAddr2,
+				(PWLAN_IE_SSID)pMgmt->abyCurrSSID,
+				(unsigned char *)pMgmt->abyCurrBSSID,
+				(PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates,
+				(PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates,
+				byPHYType
+);
+		if (pTxPacket != NULL) {
+			/* send the frame */
+			Status = csMgmt_xmit(pDevice, pTxPacket);
+			if (Status != CMD_STATUS_PENDING) {
+				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt:Probe response tx failed\n");
+			} else {
+//                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt:Probe response tx sending..\n");
+			}
+		}
+	}
 
+	return;
+}
 
 /*+
  *
@@ -4503,146 +4290,139 @@ s_vMgrRxProbeRequest(
  * Return Value:
  *    none.
  *
--*/
-
+ -*/
 
 void
 vMgrRxManagePacket(
-    void *hDeviceContext,
-    PSMgmtObject pMgmt,
-    PSRxMgmtPacket pRxPacket
-     )
+	void *hDeviceContext,
+	PSMgmtObject pMgmt,
+	PSRxMgmtPacket pRxPacket
+)
 {
-    PSDevice    pDevice = (PSDevice)hDeviceContext;
-    bool bInScan = false;
-    unsigned int uNodeIndex = 0;
-    NODE_STATE  eNodeState = 0;
-    CMD_STATUS  Status;
-
-
-    if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) {
-        if (BSSDBbIsSTAInNodeDB(pMgmt, pRxPacket->p80211Header->sA3.abyAddr2, &uNodeIndex))
-            eNodeState = pMgmt->sNodeDBTable[uNodeIndex].eNodeState;
-    }
-
-    switch( WLAN_GET_FC_FSTYPE((pRxPacket->p80211Header->sA3.wFrameCtl)) ){
-
-        case WLAN_FSTYPE_ASSOCREQ:
-            // Frame Clase = 2
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "rx assocreq\n");
-            if (eNodeState < NODE_AUTH) {
-                // send deauth notification
-                // reason = (6) class 2 received from nonauth sta
-                vMgrDeAuthenBeginSta(pDevice,
-                                     pMgmt,
-                                     pRxPacket->p80211Header->sA3.abyAddr2,
-                                     (6),
-                                     &Status
-                                     );
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wmgr: send vMgrDeAuthenBeginSta 1\n");
-            }
-            else {
-                s_vMgrRxAssocRequest(pDevice, pMgmt, pRxPacket, uNodeIndex);
-            }
-            break;
-
-        case WLAN_FSTYPE_ASSOCRESP:
-            // Frame Clase = 2
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "rx assocresp1\n");
-            s_vMgrRxAssocResponse(pDevice, pMgmt, pRxPacket, false);
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "rx assocresp2\n");
-            break;
-
-        case WLAN_FSTYPE_REASSOCREQ:
-            // Frame Clase = 2
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "rx reassocreq\n");
-            // Todo: reassoc
-            if (eNodeState < NODE_AUTH) {
-                // send deauth notification
-                // reason = (6) class 2 received from nonauth sta
-                vMgrDeAuthenBeginSta(pDevice,
-                                     pMgmt,
-                                     pRxPacket->p80211Header->sA3.abyAddr2,
-                                     (6),
-                                     &Status
-                                     );
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wmgr: send vMgrDeAuthenBeginSta 2\n");
-
-            }
-            s_vMgrRxReAssocRequest(pDevice, pMgmt, pRxPacket, uNodeIndex);
-            break;
-
-        case WLAN_FSTYPE_REASSOCRESP:
-            // Frame Clase = 2
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "rx reassocresp\n");
-            s_vMgrRxAssocResponse(pDevice, pMgmt, pRxPacket, true);
-            break;
-
-        case WLAN_FSTYPE_PROBEREQ:
-            // Frame Clase = 0
-            //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "rx probereq\n");
-            s_vMgrRxProbeRequest(pDevice, pMgmt, pRxPacket);
-            break;
-
-        case WLAN_FSTYPE_PROBERESP:
-            // Frame Clase = 0
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "rx proberesp\n");
-
-            s_vMgrRxProbeResponse(pDevice, pMgmt, pRxPacket);
-            break;
-
-        case WLAN_FSTYPE_BEACON:
-            // Frame Clase = 0
-            //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "rx beacon\n");
-            if (pMgmt->eScanState != WMAC_NO_SCANNING) {
-                bInScan = true;
-            }
-            s_vMgrRxBeacon(pDevice, pMgmt, pRxPacket, bInScan);
-            break;
-
-        case WLAN_FSTYPE_ATIM:
-            // Frame Clase = 1
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "rx atim\n");
-            break;
-
-        case WLAN_FSTYPE_DISASSOC:
-            // Frame Clase = 2
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "rx disassoc\n");
-            if (eNodeState < NODE_AUTH) {
-                // send deauth notification
-                // reason = (6) class 2 received from nonauth sta
-                vMgrDeAuthenBeginSta(pDevice,
-                                     pMgmt,
-                                     pRxPacket->p80211Header->sA3.abyAddr2,
-                                     (6),
-                                     &Status
-                                     );
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wmgr: send vMgrDeAuthenBeginSta 3\n");
-            }
-            s_vMgrRxDisassociation(pDevice, pMgmt, pRxPacket);
-            break;
-
-        case WLAN_FSTYPE_AUTHEN:
-            // Frame Clase = 1
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO  "rx authen\n");
-            s_vMgrRxAuthentication(pDevice, pMgmt, pRxPacket);
-            break;
-
-        case WLAN_FSTYPE_DEAUTHEN:
-            // Frame Clase = 1
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "rx deauthen\n");
-            s_vMgrRxDeauthentication(pDevice, pMgmt, pRxPacket);
-            break;
-
-        default:
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "rx unknown mgmt\n");
-    }
-
-    return;
-}
+	PSDevice    pDevice = (PSDevice)hDeviceContext;
+	bool bInScan = false;
+	unsigned int uNodeIndex = 0;
+	NODE_STATE  eNodeState = 0;
+	CMD_STATUS  Status;
+
+	if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) {
+		if (BSSDBbIsSTAInNodeDB(pMgmt, pRxPacket->p80211Header->sA3.abyAddr2, &uNodeIndex))
+			eNodeState = pMgmt->sNodeDBTable[uNodeIndex].eNodeState;
+	}
+
+	switch (WLAN_GET_FC_FSTYPE((pRxPacket->p80211Header->sA3.wFrameCtl))) {
+	case WLAN_FSTYPE_ASSOCREQ:
+		// Frame Clase = 2
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "rx assocreq\n");
+		if (eNodeState < NODE_AUTH) {
+			// send deauth notification
+			// reason = (6) class 2 received from nonauth sta
+			vMgrDeAuthenBeginSta(pDevice,
+					     pMgmt,
+					     pRxPacket->p80211Header->sA3.abyAddr2,
+					     (6),
+					     &Status
+);
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wmgr: send vMgrDeAuthenBeginSta 1\n");
+		} else {
+			s_vMgrRxAssocRequest(pDevice, pMgmt, pRxPacket, uNodeIndex);
+		}
+		break;
+
+	case WLAN_FSTYPE_ASSOCRESP:
+		// Frame Clase = 2
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "rx assocresp1\n");
+		s_vMgrRxAssocResponse(pDevice, pMgmt, pRxPacket, false);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "rx assocresp2\n");
+		break;
+
+	case WLAN_FSTYPE_REASSOCREQ:
+		// Frame Clase = 2
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "rx reassocreq\n");
+		// Todo: reassoc
+		if (eNodeState < NODE_AUTH) {
+			// send deauth notification
+			// reason = (6) class 2 received from nonauth sta
+			vMgrDeAuthenBeginSta(pDevice,
+					     pMgmt,
+					     pRxPacket->p80211Header->sA3.abyAddr2,
+					     (6),
+					     &Status
+);
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wmgr: send vMgrDeAuthenBeginSta 2\n");
+
+		}
+		s_vMgrRxReAssocRequest(pDevice, pMgmt, pRxPacket, uNodeIndex);
+		break;
+
+	case WLAN_FSTYPE_REASSOCRESP:
+		// Frame Clase = 2
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "rx reassocresp\n");
+		s_vMgrRxAssocResponse(pDevice, pMgmt, pRxPacket, true);
+		break;
+
+	case WLAN_FSTYPE_PROBEREQ:
+		// Frame Clase = 0
+		//DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "rx probereq\n");
+		s_vMgrRxProbeRequest(pDevice, pMgmt, pRxPacket);
+		break;
+
+	case WLAN_FSTYPE_PROBERESP:
+		// Frame Clase = 0
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "rx proberesp\n");
+
+		s_vMgrRxProbeResponse(pDevice, pMgmt, pRxPacket);
+		break;
 
+	case WLAN_FSTYPE_BEACON:
+		// Frame Clase = 0
+		//DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "rx beacon\n");
+		if (pMgmt->eScanState != WMAC_NO_SCANNING) {
+			bInScan = true;
+		}
+		s_vMgrRxBeacon(pDevice, pMgmt, pRxPacket, bInScan);
+		break;
+
+	case WLAN_FSTYPE_ATIM:
+		// Frame Clase = 1
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "rx atim\n");
+		break;
 
+	case WLAN_FSTYPE_DISASSOC:
+		// Frame Clase = 2
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "rx disassoc\n");
+		if (eNodeState < NODE_AUTH) {
+			// send deauth notification
+			// reason = (6) class 2 received from nonauth sta
+			vMgrDeAuthenBeginSta(pDevice,
+					     pMgmt,
+					     pRxPacket->p80211Header->sA3.abyAddr2,
+					     (6),
+					     &Status
+);
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wmgr: send vMgrDeAuthenBeginSta 3\n");
+		}
+		s_vMgrRxDisassociation(pDevice, pMgmt, pRxPacket);
+		break;
 
+	case WLAN_FSTYPE_AUTHEN:
+		// Frame Clase = 1
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO  "rx authen\n");
+		s_vMgrRxAuthentication(pDevice, pMgmt, pRxPacket);
+		break;
+
+	case WLAN_FSTYPE_DEAUTHEN:
+		// Frame Clase = 1
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "rx deauthen\n");
+		s_vMgrRxDeauthentication(pDevice, pMgmt, pRxPacket);
+		break;
+
+	default:
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "rx unknown mgmt\n");
+	}
+
+	return;
+}
 
 /*+
  *
@@ -4654,49 +4434,45 @@ vMgrRxManagePacket(
  * Return Value:
  *    true if success; false if failed.
  *
--*/
+ -*/
 bool
 bMgrPrepareBeaconToSend(
-    void *hDeviceContext,
-    PSMgmtObject pMgmt
-    )
+	void *hDeviceContext,
+	PSMgmtObject pMgmt
+)
 {
-    PSDevice            pDevice = (PSDevice)hDeviceContext;
-    PSTxMgmtPacket      pTxPacket;
+	PSDevice            pDevice = (PSDevice)hDeviceContext;
+	PSTxMgmtPacket      pTxPacket;
 
 //    pDevice->bBeaconBufReady = false;
-    if (pDevice->bEncryptionEnable || pDevice->bEnable8021x){
-        pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_PRIVACY(1);
-    }
-    else {
-        pMgmt->wCurrCapInfo &= ~WLAN_SET_CAP_INFO_PRIVACY(1);
-    }
-    pTxPacket = s_MgrMakeBeacon
-                (
-                  pDevice,
-                  pMgmt,
-                  pMgmt->wCurrCapInfo,
-                  pMgmt->wCurrBeaconPeriod,
-                  pMgmt->uCurrChannel,
-                  pMgmt->wCurrATIMWindow, //0,
-                  (PWLAN_IE_SSID)pMgmt->abyCurrSSID,
-                  (unsigned char *)pMgmt->abyCurrBSSID,
-                  (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates,
-                  (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates
-                );
-
-    if ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) &&
-        (pMgmt->abyCurrBSSID[0] == 0))
-        return false;
-
-    csBeacon_xmit(pDevice, pTxPacket);
-
-    return true;
+	if (pDevice->bEncryptionEnable || pDevice->bEnable8021x) {
+		pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_PRIVACY(1);
+	} else {
+		pMgmt->wCurrCapInfo &= ~WLAN_SET_CAP_INFO_PRIVACY(1);
+	}
+	pTxPacket = s_MgrMakeBeacon
+		(
+			pDevice,
+			pMgmt,
+			pMgmt->wCurrCapInfo,
+			pMgmt->wCurrBeaconPeriod,
+			pMgmt->uCurrChannel,
+			pMgmt->wCurrATIMWindow, //0,
+			(PWLAN_IE_SSID)pMgmt->abyCurrSSID,
+			(unsigned char *)pMgmt->abyCurrBSSID,
+			(PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates,
+			(PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates
+);
+
+	if ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) &&
+	    (pMgmt->abyCurrBSSID[0] == 0))
+		return false;
+
+	csBeacon_xmit(pDevice, pTxPacket);
+
+	return true;
 }
 
-
-
-
 /*+
  *
  * Routine Description:
@@ -4708,61 +4484,60 @@ bMgrPrepareBeaconToSend(
  * Return Value:
  *    none.
  *
--*/
+ -*/
 static
 void
 s_vMgrLogStatus(
-    PSMgmtObject pMgmt,
-    unsigned short wStatus
-    )
+	PSMgmtObject pMgmt,
+	unsigned short wStatus
+)
 {
-    switch( wStatus ){
-        case WLAN_MGMT_STATUS_UNSPEC_FAILURE:
-            DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Status code == Unspecified error.\n");
-            break;
-        case WLAN_MGMT_STATUS_CAPS_UNSUPPORTED:
-            DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Status code == Can't support all requested capabilities.\n");
-            break;
-        case WLAN_MGMT_STATUS_REASSOC_NO_ASSOC:
-            DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Status code == Reassoc denied, can't confirm original Association.\n");
-            break;
-        case WLAN_MGMT_STATUS_ASSOC_DENIED_UNSPEC:
-            DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Status code == Assoc denied, undefine in spec\n");
-            break;
-        case WLAN_MGMT_STATUS_UNSUPPORTED_AUTHALG:
-            DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Status code == Peer doesn't support authen algorithm.\n");
-            break;
-        case WLAN_MGMT_STATUS_RX_AUTH_NOSEQ:
-            DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Status code == Authen frame received out of sequence.\n");
-            break;
-        case WLAN_MGMT_STATUS_CHALLENGE_FAIL:
-            DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Status code == Authen rejected, challenge  failure.\n");
-            break;
-        case WLAN_MGMT_STATUS_AUTH_TIMEOUT:
-            DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Status code == Authen rejected, timeout waiting for next frame.\n");
-            break;
-        case WLAN_MGMT_STATUS_ASSOC_DENIED_BUSY:
-            DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Status code == Assoc denied, AP too busy.\n");
-            break;
-        case WLAN_MGMT_STATUS_ASSOC_DENIED_RATES:
-            DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Status code == Assoc denied, we haven't enough basic rates.\n");
-            break;
-        case WLAN_MGMT_STATUS_ASSOC_DENIED_SHORTPREAMBLE:
-            DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Status code == Assoc denied, we do not support short preamble.\n");
-            break;
-        case WLAN_MGMT_STATUS_ASSOC_DENIED_PBCC:
-            DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Status code == Assoc denied, we do not support PBCC.\n");
-            break;
-        case WLAN_MGMT_STATUS_ASSOC_DENIED_AGILITY:
-            DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Status code == Assoc denied, we do not support channel agility.\n");
-            break;
-        default:
-            DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Unknown status code %d.\n", wStatus);
-            break;
-    }
+	switch (wStatus) {
+	case WLAN_MGMT_STATUS_UNSPEC_FAILURE:
+		DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Status code == Unspecified error.\n");
+		break;
+	case WLAN_MGMT_STATUS_CAPS_UNSUPPORTED:
+		DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Status code == Can't support all requested capabilities.\n");
+		break;
+	case WLAN_MGMT_STATUS_REASSOC_NO_ASSOC:
+		DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Status code == Reassoc denied, can't confirm original Association.\n");
+		break;
+	case WLAN_MGMT_STATUS_ASSOC_DENIED_UNSPEC:
+		DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Status code == Assoc denied, undefine in spec\n");
+		break;
+	case WLAN_MGMT_STATUS_UNSUPPORTED_AUTHALG:
+		DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Status code == Peer doesn't support authen algorithm.\n");
+		break;
+	case WLAN_MGMT_STATUS_RX_AUTH_NOSEQ:
+		DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Status code == Authen frame received out of sequence.\n");
+		break;
+	case WLAN_MGMT_STATUS_CHALLENGE_FAIL:
+		DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Status code == Authen rejected, challenge  failure.\n");
+		break;
+	case WLAN_MGMT_STATUS_AUTH_TIMEOUT:
+		DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Status code == Authen rejected, timeout waiting for next frame.\n");
+		break;
+	case WLAN_MGMT_STATUS_ASSOC_DENIED_BUSY:
+		DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Status code == Assoc denied, AP too busy.\n");
+		break;
+	case WLAN_MGMT_STATUS_ASSOC_DENIED_RATES:
+		DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Status code == Assoc denied, we haven't enough basic rates.\n");
+		break;
+	case WLAN_MGMT_STATUS_ASSOC_DENIED_SHORTPREAMBLE:
+		DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Status code == Assoc denied, we do not support short preamble.\n");
+		break;
+	case WLAN_MGMT_STATUS_ASSOC_DENIED_PBCC:
+		DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Status code == Assoc denied, we do not support PBCC.\n");
+		break;
+	case WLAN_MGMT_STATUS_ASSOC_DENIED_AGILITY:
+		DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Status code == Assoc denied, we do not support channel agility.\n");
+		break;
+	default:
+		DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Unknown status code %d.\n", wStatus);
+		break;
+	}
 }
 
-
 /*
  *
  * Description:
@@ -4778,52 +4553,50 @@ s_vMgrLogStatus(
  *
  * Return Value: none.
  *
--*/
+ -*/
 bool
-bAdd_PMKID_Candidate (
-    void *hDeviceContext,
-    unsigned char *pbyBSSID,
-    PSRSNCapObject psRSNCapObj
-    )
+bAdd_PMKID_Candidate(
+	void *hDeviceContext,
+	unsigned char *pbyBSSID,
+	PSRSNCapObject psRSNCapObj
+)
 {
-    PSDevice         pDevice = (PSDevice)hDeviceContext;
-    PPMKID_CANDIDATE pCandidateList;
-    unsigned int ii = 0;
-
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"bAdd_PMKID_Candidate START: (%d)\n", (int)pDevice->gsPMKIDCandidate.NumCandidates);
-
-    if ((pDevice == NULL) || (pbyBSSID == NULL) || (psRSNCapObj == NULL))
-        return false;
-
-    if (pDevice->gsPMKIDCandidate.NumCandidates >= MAX_PMKIDLIST)
-        return false;
-
-
-
-    // Update Old Candidate
-    for (ii = 0; ii < pDevice->gsPMKIDCandidate.NumCandidates; ii++) {
-        pCandidateList = &pDevice->gsPMKIDCandidate.CandidateList[ii];
-        if ( !memcmp(pCandidateList->BSSID, pbyBSSID, ETH_ALEN)) {
-            if ((psRSNCapObj->bRSNCapExist == true) && (psRSNCapObj->wRSNCap & BIT0)) {
-                pCandidateList->Flags |= NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED;
-            } else {
-                pCandidateList->Flags &= ~(NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED);
-            }
-            return true;
-        }
-    }
-
-    // New Candidate
-    pCandidateList = &pDevice->gsPMKIDCandidate.CandidateList[pDevice->gsPMKIDCandidate.NumCandidates];
-    if ((psRSNCapObj->bRSNCapExist == true) && (psRSNCapObj->wRSNCap & BIT0)) {
-        pCandidateList->Flags |= NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED;
-    } else {
-        pCandidateList->Flags &= ~(NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED);
-    }
-    memcpy(pCandidateList->BSSID, pbyBSSID, ETH_ALEN);
-    pDevice->gsPMKIDCandidate.NumCandidates++;
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"NumCandidates:%d\n", (int)pDevice->gsPMKIDCandidate.NumCandidates);
-    return true;
+	PSDevice         pDevice = (PSDevice)hDeviceContext;
+	PPMKID_CANDIDATE pCandidateList;
+	unsigned int ii = 0;
+
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "bAdd_PMKID_Candidate START: (%d)\n", (int)pDevice->gsPMKIDCandidate.NumCandidates);
+
+	if ((pDevice == NULL) || (pbyBSSID == NULL) || (psRSNCapObj == NULL))
+		return false;
+
+	if (pDevice->gsPMKIDCandidate.NumCandidates >= MAX_PMKIDLIST)
+		return false;
+
+	// Update Old Candidate
+	for (ii = 0; ii < pDevice->gsPMKIDCandidate.NumCandidates; ii++) {
+		pCandidateList = &pDevice->gsPMKIDCandidate.CandidateList[ii];
+		if (!memcmp(pCandidateList->BSSID, pbyBSSID, ETH_ALEN)) {
+			if ((psRSNCapObj->bRSNCapExist == true) && (psRSNCapObj->wRSNCap & BIT0)) {
+				pCandidateList->Flags |= NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED;
+			} else {
+				pCandidateList->Flags &= ~(NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED);
+			}
+			return true;
+		}
+	}
+
+	// New Candidate
+	pCandidateList = &pDevice->gsPMKIDCandidate.CandidateList[pDevice->gsPMKIDCandidate.NumCandidates];
+	if ((psRSNCapObj->bRSNCapExist == true) && (psRSNCapObj->wRSNCap & BIT0)) {
+		pCandidateList->Flags |= NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED;
+	} else {
+		pCandidateList->Flags &= ~(NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED);
+	}
+	memcpy(pCandidateList->BSSID, pbyBSSID, ETH_ALEN);
+	pDevice->gsPMKIDCandidate.NumCandidates++;
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "NumCandidates:%d\n", (int)pDevice->gsPMKIDCandidate.NumCandidates);
+	return true;
 }
 
 /*
@@ -4839,166 +4612,163 @@ bAdd_PMKID_Candidate (
  *
  * Return Value: none.
  *
--*/
+ -*/
 void
-vFlush_PMKID_Candidate (
-    void *hDeviceContext
-    )
+vFlush_PMKID_Candidate(
+	void *hDeviceContext
+)
 {
-    PSDevice        pDevice = (PSDevice)hDeviceContext;
+	PSDevice        pDevice = (PSDevice)hDeviceContext;
 
-    if (pDevice == NULL)
-        return;
+	if (pDevice == NULL)
+		return;
 
-    memset(&pDevice->gsPMKIDCandidate, 0, sizeof(SPMKIDCandidateEvent));
+	memset(&pDevice->gsPMKIDCandidate, 0, sizeof(SPMKIDCandidateEvent));
 }
 
 static bool
-s_bCipherMatch (
-    PKnownBSS                        pBSSNode,
-    NDIS_802_11_ENCRYPTION_STATUS    EncStatus,
-    unsigned char *pbyCCSPK,
-    unsigned char *pbyCCSGK
-    )
+s_bCipherMatch(
+	PKnownBSS                        pBSSNode,
+	NDIS_802_11_ENCRYPTION_STATUS    EncStatus,
+	unsigned char *pbyCCSPK,
+	unsigned char *pbyCCSGK
+)
 {
-    unsigned char byMulticastCipher = KEY_CTL_INVALID;
-    unsigned char byCipherMask = 0x00;
-    int i;
-
-    if (pBSSNode == NULL)
-        return false;
-
-    // check cap. of BSS
-    if ((WLAN_GET_CAP_INFO_PRIVACY(pBSSNode->wCapInfo) != 0) &&
-         (EncStatus == Ndis802_11Encryption1Enabled)) {
-        // default is WEP only
-        byMulticastCipher = KEY_CTL_WEP;
-    }
-
-    if ((WLAN_GET_CAP_INFO_PRIVACY(pBSSNode->wCapInfo) != 0) &&
-        (pBSSNode->bWPA2Valid == true) &&
-          //20080123-01,<Add> by Einsn Liu
-        ((EncStatus == Ndis802_11Encryption3Enabled)||(EncStatus == Ndis802_11Encryption2Enabled))) {
-        //WPA2
-        // check Group Key Cipher
-        if ((pBSSNode->byCSSGK == WLAN_11i_CSS_WEP40) ||
-            (pBSSNode->byCSSGK == WLAN_11i_CSS_WEP104)) {
-            byMulticastCipher = KEY_CTL_WEP;
-        } else if (pBSSNode->byCSSGK == WLAN_11i_CSS_TKIP) {
-            byMulticastCipher = KEY_CTL_TKIP;
-        } else if (pBSSNode->byCSSGK == WLAN_11i_CSS_CCMP) {
-            byMulticastCipher = KEY_CTL_CCMP;
-        } else {
-            byMulticastCipher = KEY_CTL_INVALID;
-        }
-
-        // check Pairwise Key Cipher
-        for(i=0;i<pBSSNode->wCSSPKCount;i++) {
-            if ((pBSSNode->abyCSSPK[i] == WLAN_11i_CSS_WEP40) ||
-                (pBSSNode->abyCSSPK[i] == WLAN_11i_CSS_WEP104)) {
-                // this should not happen as defined 802.11i
-                byCipherMask |= 0x01;
-            } else if (pBSSNode->abyCSSPK[i] == WLAN_11i_CSS_TKIP) {
-                byCipherMask |= 0x02;
-            } else if (pBSSNode->abyCSSPK[i] == WLAN_11i_CSS_CCMP) {
-                byCipherMask |= 0x04;
-            } else if (pBSSNode->abyCSSPK[i] == WLAN_11i_CSS_USE_GROUP) {
-                // use group key only ignore all others
-                byCipherMask = 0;
-                i = pBSSNode->wCSSPKCount;
-            }
-        }
-
-    } else if ((WLAN_GET_CAP_INFO_PRIVACY(pBSSNode->wCapInfo) != 0) &&
-                (pBSSNode->bWPAValid == true) &&
-                ((EncStatus == Ndis802_11Encryption3Enabled) || (EncStatus == Ndis802_11Encryption2Enabled))) {
-        //WPA
-        // check Group Key Cipher
-        if ((pBSSNode->byGKType == WPA_WEP40) ||
-            (pBSSNode->byGKType == WPA_WEP104)) {
-            byMulticastCipher = KEY_CTL_WEP;
-        } else if (pBSSNode->byGKType == WPA_TKIP) {
-            byMulticastCipher = KEY_CTL_TKIP;
-        } else if (pBSSNode->byGKType == WPA_AESCCMP) {
-            byMulticastCipher = KEY_CTL_CCMP;
-        } else {
-            byMulticastCipher = KEY_CTL_INVALID;
-        }
-
-        // check Pairwise Key Cipher
-        for(i=0;i<pBSSNode->wPKCount;i++) {
-            if (pBSSNode->abyPKType[i] == WPA_TKIP) {
-                byCipherMask |= 0x02;
-            } else if (pBSSNode->abyPKType[i] == WPA_AESCCMP) {
-                byCipherMask |= 0x04;
-            } else if (pBSSNode->abyPKType[i] == WPA_NONE) {
-                // use group key only ignore all others
-                byCipherMask = 0;
-                i = pBSSNode->wPKCount;
-            }
-        }
-    }
-
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"%d, %d, %d, %d, EncStatus:%d\n",
-        byMulticastCipher, byCipherMask, pBSSNode->bWPAValid, pBSSNode->bWPA2Valid, EncStatus);
-
-    // mask our cap. with BSS
-    if (EncStatus == Ndis802_11Encryption1Enabled) {
-
-        // For supporting Cisco migration mode, don't care pairwise key cipher
-        if ((byMulticastCipher == KEY_CTL_WEP) &&
-            (byCipherMask == 0)) {
-            *pbyCCSGK = KEY_CTL_WEP;
-            *pbyCCSPK = KEY_CTL_NONE;
-            return true;
-        } else {
-            return false;
-        }
-
-    } else if (EncStatus == Ndis802_11Encryption2Enabled) {
-        if ((byMulticastCipher == KEY_CTL_TKIP) &&
-            (byCipherMask == 0)) {
-            *pbyCCSGK = KEY_CTL_TKIP;
-            *pbyCCSPK = KEY_CTL_NONE;
-            return true;
-        } else if ((byMulticastCipher == KEY_CTL_WEP) &&
-                   ((byCipherMask & 0x02) != 0)) {
-            *pbyCCSGK = KEY_CTL_WEP;
-            *pbyCCSPK = KEY_CTL_TKIP;
-            return true;
-        } else if ((byMulticastCipher == KEY_CTL_TKIP) &&
-                   ((byCipherMask & 0x02) != 0)) {
-            *pbyCCSGK = KEY_CTL_TKIP;
-            *pbyCCSPK = KEY_CTL_TKIP;
-            return true;
-        } else {
-            return false;
-        }
-    } else if (EncStatus == Ndis802_11Encryption3Enabled) {
-        if ((byMulticastCipher == KEY_CTL_CCMP) &&
-            (byCipherMask == 0)) {
-            // When CCMP is enable, "Use group cipher suite" shall not be a valid option.
-            return false;
-        } else if ((byMulticastCipher == KEY_CTL_WEP) &&
-                   ((byCipherMask & 0x04) != 0)) {
-            *pbyCCSGK = KEY_CTL_WEP;
-            *pbyCCSPK = KEY_CTL_CCMP;
-            return true;
-        } else if ((byMulticastCipher == KEY_CTL_TKIP) &&
-                   ((byCipherMask & 0x04) != 0)) {
-            *pbyCCSGK = KEY_CTL_TKIP;
-            *pbyCCSPK = KEY_CTL_CCMP;
-            return true;
-        } else if ((byMulticastCipher == KEY_CTL_CCMP) &&
-                   ((byCipherMask & 0x04) != 0)) {
-            *pbyCCSGK = KEY_CTL_CCMP;
-            *pbyCCSPK = KEY_CTL_CCMP;
-            return true;
-        } else {
-            return false;
-        }
-    }
-    return true;
-}
+	unsigned char byMulticastCipher = KEY_CTL_INVALID;
+	unsigned char byCipherMask = 0x00;
+	int i;
+
+	if (pBSSNode == NULL)
+		return false;
+
+	// check cap. of BSS
+	if ((WLAN_GET_CAP_INFO_PRIVACY(pBSSNode->wCapInfo) != 0) &&
+	    (EncStatus == Ndis802_11Encryption1Enabled)) {
+		// default is WEP only
+		byMulticastCipher = KEY_CTL_WEP;
+	}
+
+	if ((WLAN_GET_CAP_INFO_PRIVACY(pBSSNode->wCapInfo) != 0) &&
+	    (pBSSNode->bWPA2Valid == true) &&
+	    //20080123-01,<Add> by Einsn Liu
+	    ((EncStatus == Ndis802_11Encryption3Enabled) || (EncStatus == Ndis802_11Encryption2Enabled))) {
+		//WPA2
+		// check Group Key Cipher
+		if ((pBSSNode->byCSSGK == WLAN_11i_CSS_WEP40) ||
+		    (pBSSNode->byCSSGK == WLAN_11i_CSS_WEP104)) {
+			byMulticastCipher = KEY_CTL_WEP;
+		} else if (pBSSNode->byCSSGK == WLAN_11i_CSS_TKIP) {
+			byMulticastCipher = KEY_CTL_TKIP;
+		} else if (pBSSNode->byCSSGK == WLAN_11i_CSS_CCMP) {
+			byMulticastCipher = KEY_CTL_CCMP;
+		} else {
+			byMulticastCipher = KEY_CTL_INVALID;
+		}
+
+		// check Pairwise Key Cipher
+		for (i = 0; i < pBSSNode->wCSSPKCount; i++) {
+			if ((pBSSNode->abyCSSPK[i] == WLAN_11i_CSS_WEP40) ||
+			    (pBSSNode->abyCSSPK[i] == WLAN_11i_CSS_WEP104)) {
+				// this should not happen as defined 802.11i
+				byCipherMask |= 0x01;
+			} else if (pBSSNode->abyCSSPK[i] == WLAN_11i_CSS_TKIP) {
+				byCipherMask |= 0x02;
+			} else if (pBSSNode->abyCSSPK[i] == WLAN_11i_CSS_CCMP) {
+				byCipherMask |= 0x04;
+			} else if (pBSSNode->abyCSSPK[i] == WLAN_11i_CSS_USE_GROUP) {
+				// use group key only ignore all others
+				byCipherMask = 0;
+				i = pBSSNode->wCSSPKCount;
+			}
+		}
 
+	} else if ((WLAN_GET_CAP_INFO_PRIVACY(pBSSNode->wCapInfo) != 0) &&
+		   (pBSSNode->bWPAValid == true) &&
+		   ((EncStatus == Ndis802_11Encryption3Enabled) || (EncStatus == Ndis802_11Encryption2Enabled))) {
+		//WPA
+		// check Group Key Cipher
+		if ((pBSSNode->byGKType == WPA_WEP40) ||
+		    (pBSSNode->byGKType == WPA_WEP104)) {
+			byMulticastCipher = KEY_CTL_WEP;
+		} else if (pBSSNode->byGKType == WPA_TKIP) {
+			byMulticastCipher = KEY_CTL_TKIP;
+		} else if (pBSSNode->byGKType == WPA_AESCCMP) {
+			byMulticastCipher = KEY_CTL_CCMP;
+		} else {
+			byMulticastCipher = KEY_CTL_INVALID;
+		}
 
+		// check Pairwise Key Cipher
+		for (i = 0; i < pBSSNode->wPKCount; i++) {
+			if (pBSSNode->abyPKType[i] == WPA_TKIP) {
+				byCipherMask |= 0x02;
+			} else if (pBSSNode->abyPKType[i] == WPA_AESCCMP) {
+				byCipherMask |= 0x04;
+			} else if (pBSSNode->abyPKType[i] == WPA_NONE) {
+				// use group key only ignore all others
+				byCipherMask = 0;
+				i = pBSSNode->wPKCount;
+			}
+		}
+	}
+
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%d, %d, %d, %d, EncStatus:%d\n",
+		byMulticastCipher, byCipherMask, pBSSNode->bWPAValid, pBSSNode->bWPA2Valid, EncStatus);
+
+	// mask our cap. with BSS
+	if (EncStatus == Ndis802_11Encryption1Enabled) {
+		// For supporting Cisco migration mode, don't care pairwise key cipher
+		if ((byMulticastCipher == KEY_CTL_WEP) &&
+		    (byCipherMask == 0)) {
+			*pbyCCSGK = KEY_CTL_WEP;
+			*pbyCCSPK = KEY_CTL_NONE;
+			return true;
+		} else {
+			return false;
+		}
+
+	} else if (EncStatus == Ndis802_11Encryption2Enabled) {
+		if ((byMulticastCipher == KEY_CTL_TKIP) &&
+		    (byCipherMask == 0)) {
+			*pbyCCSGK = KEY_CTL_TKIP;
+			*pbyCCSPK = KEY_CTL_NONE;
+			return true;
+		} else if ((byMulticastCipher == KEY_CTL_WEP) &&
+			   ((byCipherMask & 0x02) != 0)) {
+			*pbyCCSGK = KEY_CTL_WEP;
+			*pbyCCSPK = KEY_CTL_TKIP;
+			return true;
+		} else if ((byMulticastCipher == KEY_CTL_TKIP) &&
+			   ((byCipherMask & 0x02) != 0)) {
+			*pbyCCSGK = KEY_CTL_TKIP;
+			*pbyCCSPK = KEY_CTL_TKIP;
+			return true;
+		} else {
+			return false;
+		}
+	} else if (EncStatus == Ndis802_11Encryption3Enabled) {
+		if ((byMulticastCipher == KEY_CTL_CCMP) &&
+		    (byCipherMask == 0)) {
+			// When CCMP is enable, "Use group cipher suite" shall not be a valid option.
+			return false;
+		} else if ((byMulticastCipher == KEY_CTL_WEP) &&
+			   ((byCipherMask & 0x04) != 0)) {
+			*pbyCCSGK = KEY_CTL_WEP;
+			*pbyCCSPK = KEY_CTL_CCMP;
+			return true;
+		} else if ((byMulticastCipher == KEY_CTL_TKIP) &&
+			   ((byCipherMask & 0x04) != 0)) {
+			*pbyCCSGK = KEY_CTL_TKIP;
+			*pbyCCSPK = KEY_CTL_CCMP;
+			return true;
+		} else if ((byMulticastCipher == KEY_CTL_CCMP) &&
+			   ((byCipherMask & 0x04) != 0)) {
+			*pbyCCSGK = KEY_CTL_CCMP;
+			*pbyCCSPK = KEY_CTL_CCMP;
+			return true;
+		} else {
+			return false;
+		}
+	}
+	return true;
+}
diff --git a/drivers/staging/vt6655/wmgr.h b/drivers/staging/vt6655/wmgr.h
index bfa67ae..b91f1f8 100644
--- a/drivers/staging/vt6655/wmgr.h
+++ b/drivers/staging/vt6655/wmgr.h
@@ -45,8 +45,6 @@
 
 /*---------------------  Export Definitions -------------------------*/
 
-
-
 // Scan time
 #define PROBE_DELAY                  100  // (us)
 #define SWITCH_CHANNEL_DELAY         200 // (us)
@@ -58,7 +56,6 @@
 #define WCMD_ACTIVE_SCAN_TIME   50 //(ms)
 #define WCMD_PASSIVE_SCAN_TIME  100 //(ms)
 
-
 #define DEFAULT_MSDU_LIFETIME           512  // ms
 #define DEFAULT_MSDU_LIFETIME_RES_64us  8000 // 64us
 
@@ -67,7 +64,6 @@
 
 #define MAKE_BEACON_RESERVED            10  //(us)
 
-
 #define TIM_MULTICAST_MASK           0x01
 #define TIM_BITMAPOFFSET_MASK        0xFE
 #define DEFAULT_DTIM_PERIOD             1
@@ -76,107 +72,91 @@
 
 #define DEFAULT_IBSS_CHANNEL            6  //2.4G
 
-
 /*---------------------  Export Classes  ----------------------------*/
 
 /*---------------------  Export Variables  --------------------------*/
 
 /*---------------------  Export Types  ------------------------------*/
-#define timer_expire(timer,next_tick)   mod_timer(&timer, RUN_AT(next_tick))
+#define timer_expire(timer, next_tick)   mod_timer(&timer, RUN_AT(next_tick))
 typedef void (*TimerFunction)(unsigned long);
 
-
 //+++ NDIS related
 
 typedef unsigned char NDIS_802_11_MAC_ADDRESS[6];
 typedef struct _NDIS_802_11_AI_REQFI
 {
-    unsigned short Capabilities;
-    unsigned short ListenInterval;
-    NDIS_802_11_MAC_ADDRESS  CurrentAPAddress;
+	unsigned short Capabilities;
+	unsigned short ListenInterval;
+	NDIS_802_11_MAC_ADDRESS  CurrentAPAddress;
 } NDIS_802_11_AI_REQFI, *PNDIS_802_11_AI_REQFI;
 
 typedef struct _NDIS_802_11_AI_RESFI
 {
-    unsigned short Capabilities;
-    unsigned short StatusCode;
-    unsigned short AssociationId;
+	unsigned short Capabilities;
+	unsigned short StatusCode;
+	unsigned short AssociationId;
 } NDIS_802_11_AI_RESFI, *PNDIS_802_11_AI_RESFI;
 
 typedef struct _NDIS_802_11_ASSOCIATION_INFORMATION
 {
-    unsigned long Length;
-    unsigned short          AvailableRequestFixedIEs;
-    NDIS_802_11_AI_REQFI    RequestFixedIEs;
-    unsigned long RequestIELength;
-    unsigned long OffsetRequestIEs;
-    unsigned short          AvailableResponseFixedIEs;
-    NDIS_802_11_AI_RESFI    ResponseFixedIEs;
-    unsigned long ResponseIELength;
-    unsigned long OffsetResponseIEs;
+	unsigned long Length;
+	unsigned short          AvailableRequestFixedIEs;
+	NDIS_802_11_AI_REQFI    RequestFixedIEs;
+	unsigned long RequestIELength;
+	unsigned long OffsetRequestIEs;
+	unsigned short          AvailableResponseFixedIEs;
+	NDIS_802_11_AI_RESFI    ResponseFixedIEs;
+	unsigned long ResponseIELength;
+	unsigned long OffsetResponseIEs;
 } NDIS_802_11_ASSOCIATION_INFORMATION, *PNDIS_802_11_ASSOCIATION_INFORMATION;
 
-
-
 typedef struct tagSAssocInfo {
-    NDIS_802_11_ASSOCIATION_INFORMATION     AssocInfo;
-    unsigned char abyIEs[WLAN_BEACON_FR_MAXLEN+WLAN_BEACON_FR_MAXLEN];
-    // store ReqIEs set by OID_802_11_ASSOCIATION_INFORMATION
-    unsigned long RequestIELength;
-    unsigned char abyReqIEs[WLAN_BEACON_FR_MAXLEN];
+	NDIS_802_11_ASSOCIATION_INFORMATION     AssocInfo;
+	unsigned char abyIEs[WLAN_BEACON_FR_MAXLEN+WLAN_BEACON_FR_MAXLEN];
+	// store ReqIEs set by OID_802_11_ASSOCIATION_INFORMATION
+	unsigned long RequestIELength;
+	unsigned char abyReqIEs[WLAN_BEACON_FR_MAXLEN];
 } SAssocInfo, *PSAssocInfo;
 //---
 
-
 /*
-typedef enum tagWMAC_AUTHENTICATION_MODE {
-
-
-    WMAC_AUTH_OPEN,
-    WMAC_AUTH_SHAREKEY,
-    WMAC_AUTH_AUTO,
-    WMAC_AUTH_WPA,
-    WMAC_AUTH_WPAPSK,
-    WMAC_AUTH_WPANONE,
-    WMAC_AUTH_WPA2,
-    WMAC_AUTH_WPA2PSK,
-    WMAC_AUTH_MAX       // Not a real mode, defined as upper bound
-
-
-} WMAC_AUTHENTICATION_MODE, *PWMAC_AUTHENTICATION_MODE;
+  typedef enum tagWMAC_AUTHENTICATION_MODE {
+  WMAC_AUTH_OPEN,
+  WMAC_AUTH_SHAREKEY,
+  WMAC_AUTH_AUTO,
+  WMAC_AUTH_WPA,
+  WMAC_AUTH_WPAPSK,
+  WMAC_AUTH_WPANONE,
+  WMAC_AUTH_WPA2,
+  WMAC_AUTH_WPA2PSK,
+  WMAC_AUTH_MAX       // Not a real mode, defined as upper bound
+
+  } WMAC_AUTHENTICATION_MODE, *PWMAC_AUTHENTICATION_MODE;
 */
 
-
 // Pre-configured Mode (from XP)
 /*
-typedef enum tagWMAC_CONFIG_MODE {
-    WMAC_CONFIG_ESS_STA,
-    WMAC_CONFIG_IBSS_STA,
-    WMAC_CONFIG_AUTO,
-    WMAC_CONFIG_AP
+  typedef enum tagWMAC_CONFIG_MODE {
+  WMAC_CONFIG_ESS_STA,
+  WMAC_CONFIG_IBSS_STA,
+  WMAC_CONFIG_AUTO,
+  WMAC_CONFIG_AP
 
-} WMAC_CONFIG_MODE, *PWMAC_CONFIG_MODE;
+  } WMAC_CONFIG_MODE, *PWMAC_CONFIG_MODE;
 */
 
 typedef enum tagWMAC_SCAN_TYPE {
-
-    WMAC_SCAN_ACTIVE,
-    WMAC_SCAN_PASSIVE,
-    WMAC_SCAN_HYBRID
-
+	WMAC_SCAN_ACTIVE,
+	WMAC_SCAN_PASSIVE,
+	WMAC_SCAN_HYBRID
 } WMAC_SCAN_TYPE, *PWMAC_SCAN_TYPE;
 
-
 typedef enum tagWMAC_SCAN_STATE {
-
-    WMAC_NO_SCANNING,
-    WMAC_IS_SCANNING,
-    WMAC_IS_PROBEPENDING
-
+	WMAC_NO_SCANNING,
+	WMAC_IS_SCANNING,
+	WMAC_IS_PROBEPENDING
 } WMAC_SCAN_STATE, *PWMAC_SCAN_STATE;
 
-
-
 // Notes:
 // Basic Service Set state explained as following:
 // WMAC_STATE_IDLE          : no BSS is selected (Adhoc or Infra)
@@ -188,315 +168,287 @@ typedef enum tagWMAC_SCAN_STATE {
 // WMAC_STATE_ASSOC         : Associated (Infra)
 
 typedef enum tagWMAC_BSS_STATE {
-
-    WMAC_STATE_IDLE,
-    WMAC_STATE_STARTED,
-    WMAC_STATE_JOINTED,
-    WMAC_STATE_AUTHPENDING,
-    WMAC_STATE_AUTH,
-    WMAC_STATE_ASSOCPENDING,
-    WMAC_STATE_ASSOC
-
+	WMAC_STATE_IDLE,
+	WMAC_STATE_STARTED,
+	WMAC_STATE_JOINTED,
+	WMAC_STATE_AUTHPENDING,
+	WMAC_STATE_AUTH,
+	WMAC_STATE_ASSOCPENDING,
+	WMAC_STATE_ASSOC
 } WMAC_BSS_STATE, *PWMAC_BSS_STATE;
 
 // WMAC selected running mode
 typedef enum tagWMAC_CURRENT_MODE {
-
-    WMAC_MODE_STANDBY,
-    WMAC_MODE_ESS_STA,
-    WMAC_MODE_IBSS_STA,
-    WMAC_MODE_ESS_AP
-
+	WMAC_MODE_STANDBY,
+	WMAC_MODE_ESS_STA,
+	WMAC_MODE_IBSS_STA,
+	WMAC_MODE_ESS_AP
 } WMAC_CURRENT_MODE, *PWMAC_CURRENT_MODE;
 
 /*
-typedef enum tagWMAC_POWER_MODE {
+  typedef enum tagWMAC_POWER_MODE {
+  WMAC_POWER_CAM,
+  WMAC_POWER_FAST,
+  WMAC_POWER_MAX
 
-    WMAC_POWER_CAM,
-    WMAC_POWER_FAST,
-    WMAC_POWER_MAX
-
-} WMAC_POWER_MODE, *PWMAC_POWER_MODE;
+  } WMAC_POWER_MODE, *PWMAC_POWER_MODE;
 */
 
-
 // Tx Management Packet descriptor
 typedef struct tagSTxMgmtPacket {
-
-    PUWLAN_80211HDR     p80211Header;
-    unsigned int cbMPDULen;
-    unsigned int cbPayloadLen;
-
+	PUWLAN_80211HDR     p80211Header;
+	unsigned int cbMPDULen;
+	unsigned int cbPayloadLen;
 } STxMgmtPacket, *PSTxMgmtPacket;
 
-
 // Rx Management Packet descriptor
 typedef struct tagSRxMgmtPacket {
-
-    PUWLAN_80211HDR     p80211Header;
-    QWORD               qwLocalTSF;
-    unsigned int cbMPDULen;
-    unsigned int cbPayloadLen;
-    unsigned int uRSSI;
-    unsigned char bySQ;
-    unsigned char byRxRate;
-    unsigned char byRxChannel;
-
+	PUWLAN_80211HDR     p80211Header;
+	QWORD               qwLocalTSF;
+	unsigned int cbMPDULen;
+	unsigned int cbPayloadLen;
+	unsigned int uRSSI;
+	unsigned char bySQ;
+	unsigned char byRxRate;
+	unsigned char byRxChannel;
 } SRxMgmtPacket, *PSRxMgmtPacket;
 
-
-
 typedef struct tagSMgmtObject
 {
+	void *pAdapter;
+	// MAC address
+	unsigned char abyMACAddr[WLAN_ADDR_LEN];
 
-    void *                   pAdapter;
-    // MAC address
-    unsigned char abyMACAddr[WLAN_ADDR_LEN];
-
-    // Configuration Mode
-    WMAC_CONFIG_MODE        eConfigMode; // MAC pre-configed mode
-    CARD_PHY_TYPE           eCurrentPHYMode;
-    CARD_PHY_TYPE           eConfigPHYMode;
-
+	// Configuration Mode
+	WMAC_CONFIG_MODE        eConfigMode; // MAC pre-configed mode
+	CARD_PHY_TYPE           eCurrentPHYMode;
+	CARD_PHY_TYPE           eConfigPHYMode;
 
-    // Operation state variables
-    WMAC_CURRENT_MODE       eCurrMode;   // MAC current connection mode
-    WMAC_BSS_STATE          eCurrState;  // MAC current BSS state
+	// Operation state variables
+	WMAC_CURRENT_MODE       eCurrMode;   // MAC current connection mode
+	WMAC_BSS_STATE          eCurrState;  // MAC current BSS state
 
-    PKnownBSS               pCurrBSS;
-    unsigned char byCSSGK;
-    unsigned char byCSSPK;
+	PKnownBSS               pCurrBSS;
+	unsigned char byCSSGK;
+	unsigned char byCSSPK;
 
 //    unsigned char abyNewSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN];
 //    unsigned char abyNewExtSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN];
 
-    // Current state vars
-    unsigned int	uCurrChannel;
-    unsigned char abyCurrSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1];
-    unsigned char abyCurrExtSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1];
-    unsigned char abyCurrSSID[WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1];
-    unsigned char abyCurrBSSID[WLAN_BSSID_LEN];
-    unsigned short wCurrCapInfo;
-    unsigned short wCurrAID;
-    unsigned short wCurrATIMWindow;
-    unsigned short wCurrBeaconPeriod;
-    bool bIsDS;
-    unsigned char byERPContext;
-
-    CMD_STATE               eCommandState;
-    unsigned int	uScanChannel;
-
-    // Desire joining BSS vars
-    unsigned char abyDesireSSID[WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1];
-    unsigned char abyDesireBSSID[WLAN_BSSID_LEN];
-
-    // Adhoc or AP configuration vars
-  //unsigned char abyAdHocSSID[WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1];
-    unsigned short wIBSSBeaconPeriod;
-    unsigned short wIBSSATIMWindow;
-    unsigned int	uIBSSChannel;
-    unsigned char abyIBSSSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1];
-    unsigned char byAPBBType;
-    unsigned char abyWPAIE[MAX_WPA_IE_LEN];
-    unsigned short wWPAIELen;
-
-    unsigned int	uAssocCount;
-    bool bMoreData;
-
-    // Scan state vars
-    WMAC_SCAN_STATE         eScanState;
-    WMAC_SCAN_TYPE          eScanType;
-    unsigned int	uScanStartCh;
-    unsigned int	uScanEndCh;
-    unsigned short wScanSteps;
-    unsigned int	uScanBSSType;
-    // Desire scanning vars
-    unsigned char abyScanSSID[WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1];
-    unsigned char abyScanBSSID[WLAN_BSSID_LEN];
-
-    // Privacy
-    WMAC_AUTHENTICATION_MODE eAuthenMode;
-    WMAC_ENCRYPTION_MODE    eEncryptionMode;
-    bool bShareKeyAlgorithm;
-    unsigned char abyChallenge[WLAN_CHALLENGE_LEN];
-    bool bPrivacyInvoked;
-
-    // Received beacon state vars
-    bool bInTIM;
-    bool bMulticastTIM;
-    unsigned char byDTIMCount;
-    unsigned char byDTIMPeriod;
-
-    // Power saving state vars
-    WMAC_POWER_MODE         ePSMode;
-    unsigned short wListenInterval;
-    unsigned short wCountToWakeUp;
-    bool bInTIMWake;
-    unsigned char *pbyPSPacketPool;
-    unsigned char byPSPacketPool[sizeof(STxMgmtPacket) + WLAN_NULLDATA_FR_MAXLEN];
-    bool bRxBeaconInTBTTWake;
-    unsigned char abyPSTxMap[MAX_NODE_NUM + 1];
-
-    // management command related
-    unsigned int	uCmdBusy;
-    unsigned int	uCmdHostAPBusy;
-
-    // management packet pool
-    unsigned char *pbyMgmtPacketPool;
-    unsigned char byMgmtPacketPool[sizeof(STxMgmtPacket) + WLAN_A3FR_MAXLEN];
-
-
-    // One second callback timer
-    struct timer_list	    sTimerSecondCallback;
-
-    // Temporarily Rx Mgmt Packet Descriptor
-    SRxMgmtPacket           sRxPacket;
-
-    // link list of known bss's (scan results)
-    KnownBSS                sBSSList[MAX_BSS_NUM];
-
-
-
-    // table list of known node
-    // sNodeDBList[0] is reserved for AP under Infra mode
-    // sNodeDBList[0] is reserved for Multicast under adhoc/AP mode
-    KnownNodeDB             sNodeDBTable[MAX_NODE_NUM + 1];
-
-
-
-    // WPA2 PMKID Cache
-    SPMKIDCache             gsPMKIDCache;
-    bool bRoaming;
-
-    // rate fall back vars
-
-
-
-    // associate info
-    SAssocInfo              sAssocInfo;
-
-
-    // for 802.11h
-    bool b11hEnable;
-    bool bSwitchChannel;
-    unsigned char byNewChannel;
-    PWLAN_IE_MEASURE_REP    pCurrMeasureEIDRep;
-    unsigned int	uLengthOfRepEIDs;
-    unsigned char abyCurrentMSRReq[sizeof(STxMgmtPacket) + WLAN_A3FR_MAXLEN];
-    unsigned char abyCurrentMSRRep[sizeof(STxMgmtPacket) + WLAN_A3FR_MAXLEN];
-    unsigned char abyIECountry[WLAN_A3FR_MAXLEN];
-    unsigned char abyIBSSDFSOwner[6];
-    unsigned char byIBSSDFSRecovery;
-
-    struct sk_buff  skb;
-
+	// Current state vars
+	unsigned int	uCurrChannel;
+	unsigned char abyCurrSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1];
+	unsigned char abyCurrExtSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1];
+	unsigned char abyCurrSSID[WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1];
+	unsigned char abyCurrBSSID[WLAN_BSSID_LEN];
+	unsigned short wCurrCapInfo;
+	unsigned short wCurrAID;
+	unsigned short wCurrATIMWindow;
+	unsigned short wCurrBeaconPeriod;
+	bool bIsDS;
+	unsigned char byERPContext;
+
+	CMD_STATE               eCommandState;
+	unsigned int	uScanChannel;
+
+	// Desire joining BSS vars
+	unsigned char abyDesireSSID[WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1];
+	unsigned char abyDesireBSSID[WLAN_BSSID_LEN];
+
+	// Adhoc or AP configuration vars
+	//unsigned char abyAdHocSSID[WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1];
+	unsigned short wIBSSBeaconPeriod;
+	unsigned short wIBSSATIMWindow;
+	unsigned int	uIBSSChannel;
+	unsigned char abyIBSSSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1];
+	unsigned char byAPBBType;
+	unsigned char abyWPAIE[MAX_WPA_IE_LEN];
+	unsigned short wWPAIELen;
+
+	unsigned int	uAssocCount;
+	bool bMoreData;
+
+	// Scan state vars
+	WMAC_SCAN_STATE         eScanState;
+	WMAC_SCAN_TYPE          eScanType;
+	unsigned int	uScanStartCh;
+	unsigned int	uScanEndCh;
+	unsigned short wScanSteps;
+	unsigned int	uScanBSSType;
+	// Desire scanning vars
+	unsigned char abyScanSSID[WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1];
+	unsigned char abyScanBSSID[WLAN_BSSID_LEN];
+
+	// Privacy
+	WMAC_AUTHENTICATION_MODE eAuthenMode;
+	WMAC_ENCRYPTION_MODE    eEncryptionMode;
+	bool bShareKeyAlgorithm;
+	unsigned char abyChallenge[WLAN_CHALLENGE_LEN];
+	bool bPrivacyInvoked;
+
+	// Received beacon state vars
+	bool bInTIM;
+	bool bMulticastTIM;
+	unsigned char byDTIMCount;
+	unsigned char byDTIMPeriod;
+
+	// Power saving state vars
+	WMAC_POWER_MODE         ePSMode;
+	unsigned short wListenInterval;
+	unsigned short wCountToWakeUp;
+	bool bInTIMWake;
+	unsigned char *pbyPSPacketPool;
+	unsigned char byPSPacketPool[sizeof(STxMgmtPacket) + WLAN_NULLDATA_FR_MAXLEN];
+	bool bRxBeaconInTBTTWake;
+	unsigned char abyPSTxMap[MAX_NODE_NUM + 1];
+
+	// management command related
+	unsigned int	uCmdBusy;
+	unsigned int	uCmdHostAPBusy;
+
+	// management packet pool
+	unsigned char *pbyMgmtPacketPool;
+	unsigned char byMgmtPacketPool[sizeof(STxMgmtPacket) + WLAN_A3FR_MAXLEN];
+
+	// One second callback timer
+	struct timer_list	    sTimerSecondCallback;
+
+	// Temporarily Rx Mgmt Packet Descriptor
+	SRxMgmtPacket           sRxPacket;
+
+	// link list of known bss's (scan results)
+	KnownBSS                sBSSList[MAX_BSS_NUM];
+
+	// table list of known node
+	// sNodeDBList[0] is reserved for AP under Infra mode
+	// sNodeDBList[0] is reserved for Multicast under adhoc/AP mode
+	KnownNodeDB             sNodeDBTable[MAX_NODE_NUM + 1];
+
+	// WPA2 PMKID Cache
+	SPMKIDCache             gsPMKIDCache;
+	bool bRoaming;
+
+	// rate fall back vars
+
+	// associate info
+	SAssocInfo              sAssocInfo;
+
+	// for 802.11h
+	bool b11hEnable;
+	bool bSwitchChannel;
+	unsigned char byNewChannel;
+	PWLAN_IE_MEASURE_REP    pCurrMeasureEIDRep;
+	unsigned int	uLengthOfRepEIDs;
+	unsigned char abyCurrentMSRReq[sizeof(STxMgmtPacket) + WLAN_A3FR_MAXLEN];
+	unsigned char abyCurrentMSRRep[sizeof(STxMgmtPacket) + WLAN_A3FR_MAXLEN];
+	unsigned char abyIECountry[WLAN_A3FR_MAXLEN];
+	unsigned char abyIBSSDFSOwner[6];
+	unsigned char byIBSSDFSRecovery;
+
+	struct sk_buff  skb;
 } SMgmtObject, *PSMgmtObject;
 
-
 /*---------------------  Export Macros ------------------------------*/
 
-
 /*---------------------  Export Functions  --------------------------*/
 
-
 void
 vMgrObjectInit(
-    void *hDeviceContext
-    );
+	void *hDeviceContext
+);
 
 void
 vMgrTimerInit(
-    void *hDeviceContext
-    );
+	void *hDeviceContext
+);
 
 void
 vMgrObjectReset(
-    void *hDeviceContext
-    );
+	void *hDeviceContext
+);
 
 void
 vMgrAssocBeginSta(
-    void *hDeviceContext,
-    PSMgmtObject pMgmt,
-    PCMD_STATUS pStatus
-    );
+	void *hDeviceContext,
+	PSMgmtObject pMgmt,
+	PCMD_STATUS pStatus
+);
 
 void
 vMgrReAssocBeginSta(
-    void *hDeviceContext,
-    PSMgmtObject pMgmt,
-    PCMD_STATUS pStatus
-    );
+	void *hDeviceContext,
+	PSMgmtObject pMgmt,
+	PCMD_STATUS pStatus
+);
 
 void
 vMgrDisassocBeginSta(
-    void *hDeviceContext,
-    PSMgmtObject pMgmt,
-    unsigned char *abyDestAddress,
-    unsigned short wReason,
-    PCMD_STATUS pStatus
-    );
+	void *hDeviceContext,
+	PSMgmtObject pMgmt,
+	unsigned char *abyDestAddress,
+	unsigned short wReason,
+	PCMD_STATUS pStatus
+);
 
 void
 vMgrAuthenBeginSta(
-    void *hDeviceContext,
-    PSMgmtObject pMgmt,
-    PCMD_STATUS pStatus
-    );
+	void *hDeviceContext,
+	PSMgmtObject pMgmt,
+	PCMD_STATUS pStatus
+);
 
 void
 vMgrCreateOwnIBSS(
-    void *hDeviceContext,
-    PCMD_STATUS pStatus
-    );
+	void *hDeviceContext,
+	PCMD_STATUS pStatus
+);
 
 void
 vMgrJoinBSSBegin(
-    void *hDeviceContext,
-    PCMD_STATUS pStatus
-    );
+	void *hDeviceContext,
+	PCMD_STATUS pStatus
+);
 
 void
 vMgrRxManagePacket(
-    void *hDeviceContext,
-    PSMgmtObject pMgmt,
-    PSRxMgmtPacket pRxPacket
-    );
+	void *hDeviceContext,
+	PSMgmtObject pMgmt,
+	PSRxMgmtPacket pRxPacket
+);
 
 /*
-void
-vMgrScanBegin(
-    void *hDeviceContext,
-    PCMD_STATUS pStatus
-    );
+  void
+  vMgrScanBegin(
+  void *hDeviceContext,
+  PCMD_STATUS pStatus
+);
 */
 
 void
 vMgrDeAuthenBeginSta(
-    void *hDeviceContext,
-    PSMgmtObject  pMgmt,
-    unsigned char *abyDestAddress,
-    unsigned short wReason,
-    PCMD_STATUS pStatus
-    );
+	void *hDeviceContext,
+	PSMgmtObject  pMgmt,
+	unsigned char *abyDestAddress,
+	unsigned short wReason,
+	PCMD_STATUS pStatus
+);
 
 bool
 bMgrPrepareBeaconToSend(
-    void *hDeviceContext,
-    PSMgmtObject pMgmt
-    );
-
+	void *hDeviceContext,
+	PSMgmtObject pMgmt
+);
 
 bool
-bAdd_PMKID_Candidate (
-    void *hDeviceContext,
-    unsigned char *pbyBSSID,
-    PSRSNCapObject psRSNCapObj
-    );
+bAdd_PMKID_Candidate(
+	void *hDeviceContext,
+	unsigned char *pbyBSSID,
+	PSRSNCapObject psRSNCapObj
+);
 
 void
-vFlush_PMKID_Candidate (
-    void *hDeviceContext
-    );
+vFlush_PMKID_Candidate(
+	void *hDeviceContext
+);
 
 #endif // __WMGR_H__
diff --git a/drivers/staging/vt6655/wpa.c b/drivers/staging/vt6655/wpa.c
index 4412fe9..c5293bb 100644
--- a/drivers/staging/vt6655/wpa.c
+++ b/drivers/staging/vt6655/wpa.c
@@ -43,7 +43,7 @@
 #include "80211mgr.h"
 
 /*---------------------  Static Variables  --------------------------*/
-static int          msglevel                =MSG_LEVEL_INFO;
+static int msglevel = MSG_LEVEL_INFO;
 
 const unsigned char abyOUI00[4] = { 0x00, 0x50, 0xf2, 0x00 };
 const unsigned char abyOUI01[4] = { 0x00, 0x50, 0xf2, 0x01 };
@@ -52,7 +52,6 @@ const unsigned char abyOUI03[4] = { 0x00, 0x50, 0xf2, 0x03 };
 const unsigned char abyOUI04[4] = { 0x00, 0x50, 0xf2, 0x04 };
 const unsigned char abyOUI05[4] = { 0x00, 0x50, 0xf2, 0x05 };
 
-
 /*+
  *
  * Description:
@@ -66,29 +65,28 @@ const unsigned char abyOUI05[4] = { 0x00, 0x50, 0xf2, 0x05 };
  *
  * Return Value: none.
  *
--*/
+ -*/
 
 void
-WPA_ClearRSN (
-    PKnownBSS        pBSSList
-    )
+WPA_ClearRSN(
+	PKnownBSS        pBSSList
+)
 {
-    int ii;
-    pBSSList->byGKType = WPA_TKIP;
-    for (ii=0; ii < 4; ii ++)
-        pBSSList->abyPKType[ii] = WPA_TKIP;
-    pBSSList->wPKCount = 0;
-    for (ii=0; ii < 4; ii ++)
-        pBSSList->abyAuthType[ii] = WPA_AUTH_IEEE802_1X;
-    pBSSList->wAuthCount = 0;
-    pBSSList->byDefaultK_as_PK = 0;
-    pBSSList->byReplayIdx = 0;
-    pBSSList->sRSNCapObj.bRSNCapExist = false;
-    pBSSList->sRSNCapObj.wRSNCap = 0;
-    pBSSList->bWPAValid = false;
+	int ii;
+	pBSSList->byGKType = WPA_TKIP;
+	for (ii = 0; ii < 4; ii++)
+		pBSSList->abyPKType[ii] = WPA_TKIP;
+	pBSSList->wPKCount = 0;
+	for (ii = 0; ii < 4; ii++)
+		pBSSList->abyAuthType[ii] = WPA_AUTH_IEEE802_1X;
+	pBSSList->wAuthCount = 0;
+	pBSSList->byDefaultK_as_PK = 0;
+	pBSSList->byReplayIdx = 0;
+	pBSSList->sRSNCapObj.bRSNCapExist = false;
+	pBSSList->sRSNCapObj.wRSNCap = 0;
+	pBSSList->bWPAValid = false;
 }
 
-
 /*+
  *
  * Description:
@@ -103,122 +101,118 @@ WPA_ClearRSN (
  *
  * Return Value: none.
  *
--*/
+ -*/
 void
-WPA_ParseRSN (
-    PKnownBSS        pBSSList,
-    PWLAN_IE_RSN_EXT pRSN
-    )
+WPA_ParseRSN(
+	PKnownBSS        pBSSList,
+	PWLAN_IE_RSN_EXT pRSN
+)
 {
-    PWLAN_IE_RSN_AUTH  pIE_RSN_Auth = NULL;
-    int                i, j, m, n = 0;
-    unsigned char *pbyCaps;
-
-    WPA_ClearRSN(pBSSList);
+	PWLAN_IE_RSN_AUTH  pIE_RSN_Auth = NULL;
+	int                i, j, m, n = 0;
+	unsigned char *pbyCaps;
 
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"WPA_ParseRSN: [%d]\n", pRSN->len);
+	WPA_ClearRSN(pBSSList);
 
-    // information element header makes sense
-    if ((pRSN->len >= 6) // oui1(4)+ver(2)
-         && (pRSN->byElementID == WLAN_EID_RSN_WPA) &&  !memcmp(pRSN->abyOUI, abyOUI01, 4)
-         && (pRSN->wVersion == 1)) {
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WPA_ParseRSN: [%d]\n", pRSN->len);
 
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Legal RSN\n");
-        // update each variable if pRSN is long enough to contain the variable
-        if (pRSN->len >= 10) //oui1(4)+ver(2)+GKSuite(4)
-        {
-            if ( !memcmp(pRSN->abyMulticast, abyOUI01, 4))
-                pBSSList->byGKType = WPA_WEP40;
-            else if ( !memcmp(pRSN->abyMulticast, abyOUI02, 4))
-                pBSSList->byGKType = WPA_TKIP;
-            else if ( !memcmp(pRSN->abyMulticast, abyOUI03, 4))
-                pBSSList->byGKType = WPA_AESWRAP;
-            else if ( !memcmp(pRSN->abyMulticast, abyOUI04, 4))
-                pBSSList->byGKType = WPA_AESCCMP;
-            else if ( !memcmp(pRSN->abyMulticast, abyOUI05, 4))
-                pBSSList->byGKType = WPA_WEP104;
-            else
-                // any vendor checks here
-                pBSSList->byGKType = WPA_NONE;
+	// information element header makes sense
+	if ((pRSN->len >= 6) // oui1(4)+ver(2)
+	    && (pRSN->byElementID == WLAN_EID_RSN_WPA) && !memcmp(pRSN->abyOUI, abyOUI01, 4)
+	    && (pRSN->wVersion == 1)) {
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Legal RSN\n");
+		// update each variable if pRSN is long enough to contain the variable
+		if (pRSN->len >= 10) //oui1(4)+ver(2)+GKSuite(4)
+		{
+			if (!memcmp(pRSN->abyMulticast, abyOUI01, 4))
+				pBSSList->byGKType = WPA_WEP40;
+			else if (!memcmp(pRSN->abyMulticast, abyOUI02, 4))
+				pBSSList->byGKType = WPA_TKIP;
+			else if (!memcmp(pRSN->abyMulticast, abyOUI03, 4))
+				pBSSList->byGKType = WPA_AESWRAP;
+			else if (!memcmp(pRSN->abyMulticast, abyOUI04, 4))
+				pBSSList->byGKType = WPA_AESCCMP;
+			else if (!memcmp(pRSN->abyMulticast, abyOUI05, 4))
+				pBSSList->byGKType = WPA_WEP104;
+			else
+				// any vendor checks here
+				pBSSList->byGKType = WPA_NONE;
 
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"byGKType: %x\n", pBSSList->byGKType);
-        }
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "byGKType: %x\n", pBSSList->byGKType);
+		}
 
-        if (pRSN->len >= 12) //oui1(4)+ver(2)+GKS(4)+PKSCnt(2)
-        {
-            j = 0;
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"wPKCount: %d, sizeof(pBSSList->abyPKType): %zu\n", pRSN->wPKCount, sizeof(pBSSList->abyPKType));
-            for(i = 0; (i < pRSN->wPKCount) && (j < ARRAY_SIZE(pBSSList->abyPKType)); i++) {
-                if(pRSN->len >= 12+i*4+4) { //oui1(4)+ver(2)+GKS(4)+PKSCnt(2)+PKS(4*i)
-                    if ( !memcmp(pRSN->PKSList[i].abyOUI, abyOUI00, 4))
-                        pBSSList->abyPKType[j++] = WPA_NONE;
-                    else if ( !memcmp(pRSN->PKSList[i].abyOUI, abyOUI02, 4))
-                        pBSSList->abyPKType[j++] = WPA_TKIP;
-                    else if ( !memcmp(pRSN->PKSList[i].abyOUI, abyOUI03, 4))
-                        pBSSList->abyPKType[j++] = WPA_AESWRAP;
-                    else if ( !memcmp(pRSN->PKSList[i].abyOUI, abyOUI04, 4))
-                        pBSSList->abyPKType[j++] = WPA_AESCCMP;
-                    else
-                        // any vendor checks here
-                        ;
-                }
-                else
-                    break;
-                //DBG_PRN_GRP14(("abyPKType[%d]: %X\n", j-1, pBSSList->abyPKType[j-1]));
-            } //for
-            pBSSList->wPKCount = (unsigned short)j;
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"wPKCount: %d\n", pBSSList->wPKCount);
-        }
+		if (pRSN->len >= 12) //oui1(4)+ver(2)+GKS(4)+PKSCnt(2)
+		{
+			j = 0;
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wPKCount: %d, sizeof(pBSSList->abyPKType): %zu\n", pRSN->wPKCount, sizeof(pBSSList->abyPKType));
+			for (i = 0; (i < pRSN->wPKCount) && (j < ARRAY_SIZE(pBSSList->abyPKType)); i++) {
+				if (pRSN->len >= 12+i*4+4) { //oui1(4)+ver(2)+GKS(4)+PKSCnt(2)+PKS(4*i)
+					if (!memcmp(pRSN->PKSList[i].abyOUI, abyOUI00, 4))
+						pBSSList->abyPKType[j++] = WPA_NONE;
+					else if (!memcmp(pRSN->PKSList[i].abyOUI, abyOUI02, 4))
+						pBSSList->abyPKType[j++] = WPA_TKIP;
+					else if (!memcmp(pRSN->PKSList[i].abyOUI, abyOUI03, 4))
+						pBSSList->abyPKType[j++] = WPA_AESWRAP;
+					else if (!memcmp(pRSN->PKSList[i].abyOUI, abyOUI04, 4))
+						pBSSList->abyPKType[j++] = WPA_AESCCMP;
+					else
+						// any vendor checks here
+						;
+				} else
+					break;
+				//DBG_PRN_GRP14(("abyPKType[%d]: %X\n", j-1, pBSSList->abyPKType[j-1]));
+			} //for
+			pBSSList->wPKCount = (unsigned short)j;
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wPKCount: %d\n", pBSSList->wPKCount);
+		}
 
-        m = pRSN->wPKCount;
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"m: %d\n", m);
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"14+m*4: %d\n", 14+m*4);
+		m = pRSN->wPKCount;
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "m: %d\n", m);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "14+m*4: %d\n", 14+m*4);
 
-        if (pRSN->len >= 14+m*4) { //oui1(4)+ver(2)+GKS(4)+PKSCnt(2)+PKS(4*m)+AKC(2)
-            // overlay IE_RSN_Auth structure into correct place
-            pIE_RSN_Auth = (PWLAN_IE_RSN_AUTH) pRSN->PKSList[m].abyOUI;
-            j = 0;
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"wAuthCount: %d, sizeof(pBSSList->abyAuthType): %zu\n",
-                          pIE_RSN_Auth->wAuthCount, sizeof(pBSSList->abyAuthType));
-            for(i = 0; (i < pIE_RSN_Auth->wAuthCount) && (j < ARRAY_SIZE(pBSSList->abyAuthType)); i++) {
-                if(pRSN->len >= 14+4+(m+i)*4) { //oui1(4)+ver(2)+GKS(4)+PKSCnt(2)+PKS(4*m)+AKC(2)+AKS(4*i)
-                    if ( !memcmp(pIE_RSN_Auth->AuthKSList[i].abyOUI, abyOUI01, 4))
-                        pBSSList->abyAuthType[j++] = WPA_AUTH_IEEE802_1X;
-                    else if ( !memcmp(pIE_RSN_Auth->AuthKSList[i].abyOUI, abyOUI02, 4))
-                        pBSSList->abyAuthType[j++] = WPA_AUTH_PSK;
-                    else
-                    // any vendor checks here
-                    ;
-                }
-                else
-                    break;
-                //DBG_PRN_GRP14(("abyAuthType[%d]: %X\n", j-1, pBSSList->abyAuthType[j-1]));
-            }
-            if(j > 0)
-                pBSSList->wAuthCount = (unsigned short)j;
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"wAuthCount: %d\n", pBSSList->wAuthCount);
-        }
+		if (pRSN->len >= 14+m*4) { //oui1(4)+ver(2)+GKS(4)+PKSCnt(2)+PKS(4*m)+AKC(2)
+			// overlay IE_RSN_Auth structure into correct place
+			pIE_RSN_Auth = (PWLAN_IE_RSN_AUTH) pRSN->PKSList[m].abyOUI;
+			j = 0;
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wAuthCount: %d, sizeof(pBSSList->abyAuthType): %zu\n",
+				pIE_RSN_Auth->wAuthCount, sizeof(pBSSList->abyAuthType));
+			for (i = 0; (i < pIE_RSN_Auth->wAuthCount) && (j < ARRAY_SIZE(pBSSList->abyAuthType)); i++) {
+				if (pRSN->len >= 14+4+(m+i)*4) { //oui1(4)+ver(2)+GKS(4)+PKSCnt(2)+PKS(4*m)+AKC(2)+AKS(4*i)
+					if (!memcmp(pIE_RSN_Auth->AuthKSList[i].abyOUI, abyOUI01, 4))
+						pBSSList->abyAuthType[j++] = WPA_AUTH_IEEE802_1X;
+					else if (!memcmp(pIE_RSN_Auth->AuthKSList[i].abyOUI, abyOUI02, 4))
+						pBSSList->abyAuthType[j++] = WPA_AUTH_PSK;
+					else
+						// any vendor checks here
+						;
+				} else
+					break;
+				//DBG_PRN_GRP14(("abyAuthType[%d]: %X\n", j-1, pBSSList->abyAuthType[j-1]));
+			}
+			if (j > 0)
+				pBSSList->wAuthCount = (unsigned short)j;
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wAuthCount: %d\n", pBSSList->wAuthCount);
+		}
 
-        if (pIE_RSN_Auth != NULL) {
+		if (pIE_RSN_Auth != NULL) {
+			n = pIE_RSN_Auth->wAuthCount;
 
-            n = pIE_RSN_Auth->wAuthCount;
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "n: %d\n", n);
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "14+4+(m+n)*4: %d\n", 14+4+(m+n)*4);
 
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"n: %d\n", n);
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"14+4+(m+n)*4: %d\n", 14+4+(m+n)*4);
-
-            if(pRSN->len+2 >= 14+4+(m+n)*4) { //oui1(4)+ver(2)+GKS(4)+PKSCnt(2)+PKS(4*m)+AKC(2)+AKS(4*n)+Cap(2)
-                pbyCaps = (unsigned char *)pIE_RSN_Auth->AuthKSList[n].abyOUI;
-                pBSSList->byDefaultK_as_PK = (*pbyCaps) & WPA_GROUPFLAG;
-                pBSSList->byReplayIdx = 2 << ((*pbyCaps >> WPA_REPLAYBITSSHIFT) & WPA_REPLAYBITS);
-                pBSSList->sRSNCapObj.bRSNCapExist = true;
-                pBSSList->sRSNCapObj.wRSNCap = *(unsigned short *)pbyCaps;
-                //DBG_PRN_GRP14(("pbyCaps: %X\n", *pbyCaps));
-                //DBG_PRN_GRP14(("byDefaultK_as_PK: %X\n", pBSSList->byDefaultK_as_PK));
-                //DBG_PRN_GRP14(("byReplayIdx: %X\n", pBSSList->byReplayIdx));
-            }
-        }
-        pBSSList->bWPAValid = true;
-    }
+			if (pRSN->len+2 >= 14+4+(m+n)*4) { //oui1(4)+ver(2)+GKS(4)+PKSCnt(2)+PKS(4*m)+AKC(2)+AKS(4*n)+Cap(2)
+				pbyCaps = (unsigned char *)pIE_RSN_Auth->AuthKSList[n].abyOUI;
+				pBSSList->byDefaultK_as_PK = (*pbyCaps) & WPA_GROUPFLAG;
+				pBSSList->byReplayIdx = 2 << ((*pbyCaps >> WPA_REPLAYBITSSHIFT) & WPA_REPLAYBITS);
+				pBSSList->sRSNCapObj.bRSNCapExist = true;
+				pBSSList->sRSNCapObj.wRSNCap = *(unsigned short *)pbyCaps;
+				//DBG_PRN_GRP14(("pbyCaps: %X\n", *pbyCaps));
+				//DBG_PRN_GRP14(("byDefaultK_as_PK: %X\n", pBSSList->byDefaultK_as_PK));
+				//DBG_PRN_GRP14(("byReplayIdx: %X\n", pBSSList->byReplayIdx));
+			}
+		}
+		pBSSList->bWPAValid = true;
+	}
 }
 
 /*+
@@ -236,51 +230,47 @@ WPA_ParseRSN (
  *
  * Return Value: none.
  *
--*/
+ -*/
 bool
-WPA_SearchRSN (
-    unsigned char byCmd,
-    unsigned char byEncrypt,
-    PKnownBSS        pBSSList
-    )
+WPA_SearchRSN(
+	unsigned char byCmd,
+	unsigned char byEncrypt,
+	PKnownBSS        pBSSList
+)
 {
-    int ii;
-    unsigned char byPKType = WPA_NONE;
+	int ii;
+	unsigned char byPKType = WPA_NONE;
 
-    if (pBSSList->bWPAValid == false)
-        return false;
+	if (pBSSList->bWPAValid == false)
+		return false;
 
-    switch(byCmd) {
-    case 0:
+	switch (byCmd) {
+	case 0:
 
-        if (byEncrypt != pBSSList->byGKType)
-            return false;
+		if (byEncrypt != pBSSList->byGKType)
+			return false;
 
-        if (pBSSList->wPKCount > 0) {
-            for (ii = 0; ii < pBSSList->wPKCount; ii ++) {
-                if (pBSSList->abyPKType[ii] == WPA_AESCCMP)
-                    byPKType = WPA_AESCCMP;
-                else if ((pBSSList->abyPKType[ii] == WPA_TKIP) && (byPKType != WPA_AESCCMP))
-                     byPKType = WPA_TKIP;
-                else if ((pBSSList->abyPKType[ii] == WPA_WEP40) && (byPKType != WPA_AESCCMP) && (byPKType != WPA_TKIP))
-                     byPKType = WPA_WEP40;
-                else if ((pBSSList->abyPKType[ii] == WPA_WEP104) && (byPKType != WPA_AESCCMP) && (byPKType != WPA_TKIP))
-                     byPKType = WPA_WEP104;
-            }
-            if (byEncrypt != byPKType)
-                return false;
-        }
-        return true;
-//        if (pBSSList->wAuthCount > 0)
-//            for (ii=0; ii < pBSSList->wAuthCount; ii ++)
-//                if (byAuth == pBSSList->abyAuthType[ii])
-//                    break;
-        break;
+		if (pBSSList->wPKCount > 0) {
+			for (ii = 0; ii < pBSSList->wPKCount; ii++) {
+				if (pBSSList->abyPKType[ii] == WPA_AESCCMP)
+					byPKType = WPA_AESCCMP;
+				else if ((pBSSList->abyPKType[ii] == WPA_TKIP) && (byPKType != WPA_AESCCMP))
+					byPKType = WPA_TKIP;
+				else if ((pBSSList->abyPKType[ii] == WPA_WEP40) && (byPKType != WPA_AESCCMP) && (byPKType != WPA_TKIP))
+					byPKType = WPA_WEP40;
+				else if ((pBSSList->abyPKType[ii] == WPA_WEP104) && (byPKType != WPA_AESCCMP) && (byPKType != WPA_TKIP))
+					byPKType = WPA_WEP104;
+			}
+			if (byEncrypt != byPKType)
+				return false;
+		}
+		return true;
+		break;
 
-    default:
-        break;
-    }
-    return false;
+	default:
+		break;
+	}
+	return false;
 }
 
 /*+
@@ -296,21 +286,19 @@ WPA_SearchRSN (
  *
  * Return Value: none.
  *
--*/
+ -*/
 bool
-WPAb_Is_RSN (
-    PWLAN_IE_RSN_EXT pRSN
-    )
+WPAb_Is_RSN(
+	PWLAN_IE_RSN_EXT pRSN
+)
 {
-    if (pRSN == NULL)
-        return false;
+	if (pRSN == NULL)
+		return false;
 
-    if ((pRSN->len >= 6) && // oui1(4)+ver(2)
-        (pRSN->byElementID == WLAN_EID_RSN_WPA) &&  !memcmp(pRSN->abyOUI, abyOUI01, 4) &&
-        (pRSN->wVersion == 1)) {
-        return true;
-    }
-    else
-        return false;
+	if ((pRSN->len >= 6) && // oui1(4)+ver(2)
+	    (pRSN->byElementID == WLAN_EID_RSN_WPA) &&  !memcmp(pRSN->abyOUI, abyOUI01, 4) &&
+	    (pRSN->wVersion == 1)) {
+		return true;
+	} else
+		return false;
 }
-
diff --git a/drivers/staging/vt6655/wpa.h b/drivers/staging/vt6655/wpa.h
index 921fd7a..1d1918a 100644
--- a/drivers/staging/vt6655/wpa.h
+++ b/drivers/staging/vt6655/wpa.h
@@ -55,30 +55,29 @@
 
 /*---------------------  Export Types  ------------------------------*/
 
-
 /*---------------------  Export Functions  --------------------------*/
 
 void
 WPA_ClearRSN(
-    PKnownBSS        pBSSList
-    );
+	PKnownBSS        pBSSList
+);
 
 void
 WPA_ParseRSN(
-    PKnownBSS        pBSSList,
-    PWLAN_IE_RSN_EXT pRSN
-    );
+	PKnownBSS        pBSSList,
+	PWLAN_IE_RSN_EXT pRSN
+);
 
 bool
 WPA_SearchRSN(
-    unsigned char byCmd,
-    unsigned char byEncrypt,
-    PKnownBSS        pBSSList
-    );
+	unsigned char byCmd,
+	unsigned char byEncrypt,
+	PKnownBSS        pBSSList
+);
 
 bool
 WPAb_Is_RSN(
-    PWLAN_IE_RSN_EXT pRSN
-    );
+	PWLAN_IE_RSN_EXT pRSN
+);
 
 #endif // __WPA_H__
diff --git a/drivers/staging/vt6655/wpa2.c b/drivers/staging/vt6655/wpa2.c
index 884db1a..089788d 100644
--- a/drivers/staging/vt6655/wpa2.c
+++ b/drivers/staging/vt6655/wpa2.c
@@ -36,7 +36,7 @@
 #include "wmgr.h"
 
 /*---------------------  Static Definitions -------------------------*/
-static int          msglevel                =MSG_LEVEL_INFO;
+static int msglevel = MSG_LEVEL_INFO;
 //static int          msglevel                =MSG_LEVEL_DEBUG;
 /*---------------------  Static Classes  ----------------------------*/
 
@@ -51,7 +51,6 @@ const unsigned char abyOUICCMP[4]    = { 0x00, 0x0F, 0xAC, 0x04 };
 const unsigned char abyOUI8021X[4]   = { 0x00, 0x0F, 0xAC, 0x01 };
 const unsigned char abyOUIPSK[4]     = { 0x00, 0x0F, 0xAC, 0x02 };
 
-
 /*---------------------  Static Functions  --------------------------*/
 
 /*---------------------  Export Variables  --------------------------*/
@@ -71,25 +70,25 @@ const unsigned char abyOUIPSK[4]     = { 0x00, 0x0F, 0xAC, 0x02 };
  *
  * Return Value: none.
  *
--*/
+ -*/
 void
-WPA2_ClearRSN (
-    PKnownBSS        pBSSNode
-    )
+WPA2_ClearRSN(
+	PKnownBSS        pBSSNode
+)
 {
-    int ii;
-
-    pBSSNode->bWPA2Valid = false;
-
-    pBSSNode->byCSSGK = WLAN_11i_CSS_CCMP;
-    for (ii=0; ii < 4; ii ++)
-        pBSSNode->abyCSSPK[ii] = WLAN_11i_CSS_CCMP;
-    pBSSNode->wCSSPKCount = 1;
-    for (ii=0; ii < 4; ii ++)
-        pBSSNode->abyAKMSSAuthType[ii] = WLAN_11i_AKMSS_802_1X;
-    pBSSNode->wAKMSSAuthCount = 1;
-    pBSSNode->sRSNCapObj.bRSNCapExist = false;
-    pBSSNode->sRSNCapObj.wRSNCap = 0;
+	int ii;
+
+	pBSSNode->bWPA2Valid = false;
+
+	pBSSNode->byCSSGK = WLAN_11i_CSS_CCMP;
+	for (ii = 0; ii < 4; ii++)
+		pBSSNode->abyCSSPK[ii] = WLAN_11i_CSS_CCMP;
+	pBSSNode->wCSSPKCount = 1;
+	for (ii = 0; ii < 4; ii++)
+		pBSSNode->abyAKMSSAuthType[ii] = WLAN_11i_AKMSS_802_1X;
+	pBSSNode->wAKMSSAuthCount = 1;
+	pBSSNode->sRSNCapObj.bRSNCapExist = false;
+	pBSSNode->sRSNCapObj.wRSNCap = 0;
 }
 
 /*+
@@ -106,147 +105,144 @@ WPA2_ClearRSN (
  *
  * Return Value: none.
  *
--*/
+ -*/
 void
-WPA2vParseRSN (
-    PKnownBSS        pBSSNode,
-    PWLAN_IE_RSN     pRSN
-    )
+WPA2vParseRSN(
+	PKnownBSS        pBSSNode,
+	PWLAN_IE_RSN     pRSN
+)
 {
-    int                 i, j;
-    unsigned short m = 0, n = 0;
-    unsigned char *pbyOUI;
-    bool bUseGK = false;
-
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"WPA2_ParseRSN: [%d]\n", pRSN->len);
-
-    WPA2_ClearRSN(pBSSNode);
-
-    if (pRSN->len == 2) { // ver(2)
-        if ((pRSN->byElementID == WLAN_EID_RSN) && (pRSN->wVersion == 1)) {
-            pBSSNode->bWPA2Valid = true;
-        }
-        return;
-    }
-
-    if (pRSN->len < 6) { // ver(2) + GK(4)
-        // invalid CSS, P802.11i/D10.0, p31
-        return;
-    }
-
-    // information element header makes sense
-    if ((pRSN->byElementID == WLAN_EID_RSN) &&
-        (pRSN->wVersion == 1)) {
-
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Legal 802.11i RSN\n");
-
-        pbyOUI = &(pRSN->abyRSN[0]);
-        if ( !memcmp(pbyOUI, abyOUIWEP40, 4))
-            pBSSNode->byCSSGK = WLAN_11i_CSS_WEP40;
-        else if ( !memcmp(pbyOUI, abyOUITKIP, 4))
-            pBSSNode->byCSSGK = WLAN_11i_CSS_TKIP;
-        else if ( !memcmp(pbyOUI, abyOUICCMP, 4))
-            pBSSNode->byCSSGK = WLAN_11i_CSS_CCMP;
-        else if ( !memcmp(pbyOUI, abyOUIWEP104, 4))
-            pBSSNode->byCSSGK = WLAN_11i_CSS_WEP104;
-        else if ( !memcmp(pbyOUI, abyOUIGK, 4)) {
-            // invalid CSS, P802.11i/D10.0, p32
-            return;
-        } else
-            // any vendor checks here
-            pBSSNode->byCSSGK = WLAN_11i_CSS_UNKNOWN;
-
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"802.11i CSS: %X\n", pBSSNode->byCSSGK);
-
-        if (pRSN->len == 6) {
-            pBSSNode->bWPA2Valid = true;
-            return;
-        }
-
-        if (pRSN->len >= 8) { // ver(2) + GK(4) + PK count(2)
-            pBSSNode->wCSSPKCount = *((unsigned short *) &(pRSN->abyRSN[4]));
-            j = 0;
-            pbyOUI = &(pRSN->abyRSN[6]);
-
-            for (i = 0; (i < pBSSNode->wCSSPKCount) && (j < sizeof(pBSSNode->abyCSSPK)/sizeof(unsigned char)); i++) {
-
-                if (pRSN->len >= 8+i*4+4) { // ver(2)+GK(4)+PKCnt(2)+PKS(4*i)
-                    if ( !memcmp(pbyOUI, abyOUIGK, 4)) {
-                        pBSSNode->abyCSSPK[j++] = WLAN_11i_CSS_USE_GROUP;
-                        bUseGK = true;
-                    } else if ( !memcmp(pbyOUI, abyOUIWEP40, 4)) {
-                        // Invalid CSS, continue to parsing
-                    } else if ( !memcmp(pbyOUI, abyOUITKIP, 4)) {
-                        if (pBSSNode->byCSSGK != WLAN_11i_CSS_CCMP)
-                            pBSSNode->abyCSSPK[j++] = WLAN_11i_CSS_TKIP;
-                        else
-                            ; // Invalid CSS, continue to parsing
-                    } else if ( !memcmp(pbyOUI, abyOUICCMP, 4)) {
-                        pBSSNode->abyCSSPK[j++] = WLAN_11i_CSS_CCMP;
-                    } else if ( !memcmp(pbyOUI, abyOUIWEP104, 4)) {
-                        // Invalid CSS, continue to parsing
-                    } else {
-                        // any vendor checks here
-                        pBSSNode->abyCSSPK[j++] = WLAN_11i_CSS_UNKNOWN;
-                    }
-                    pbyOUI += 4;
-                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"abyCSSPK[%d]: %X\n", j-1, pBSSNode->abyCSSPK[j-1]);
-                } else
-                    break;
-            } //for
-
-            if (bUseGK == true) {
-                if (j != 1) {
-                    // invalid CSS, This should be only PK CSS.
-                    return;
-                }
-                if (pBSSNode->byCSSGK == WLAN_11i_CSS_CCMP) {
-                    // invalid CSS, If CCMP is enable , PK can't be CSSGK.
-                    return;
-                }
-            }
-            if ((pBSSNode->wCSSPKCount != 0) && (j == 0)) {
-                // invalid CSS, No valid PK.
-                return;
-            }
-            pBSSNode->wCSSPKCount = (unsigned short)j;
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"wCSSPKCount: %d\n", pBSSNode->wCSSPKCount);
-        }
-
-        m = *((unsigned short *) &(pRSN->abyRSN[4]));
-
-        if (pRSN->len >= 10+m*4) { // ver(2) + GK(4) + PK count(2) + PKS(4*m) + AKMSS count(2)
-            pBSSNode->wAKMSSAuthCount = *((unsigned short *) &(pRSN->abyRSN[6+4*m]));
-            j = 0;
-            pbyOUI = &(pRSN->abyRSN[8+4*m]);
-            for (i = 0; (i < pBSSNode->wAKMSSAuthCount) && (j < sizeof(pBSSNode->abyAKMSSAuthType)/sizeof(unsigned char)); i++) {
-                if (pRSN->len >= 10+(m+i)*4+4) { // ver(2)+GK(4)+PKCnt(2)+PKS(4*m)+AKMSS(2)+AKS(4*i)
-                    if ( !memcmp(pbyOUI, abyOUI8021X, 4))
-                        pBSSNode->abyAKMSSAuthType[j++] = WLAN_11i_AKMSS_802_1X;
-                    else if ( !memcmp(pbyOUI, abyOUIPSK, 4))
-                        pBSSNode->abyAKMSSAuthType[j++] = WLAN_11i_AKMSS_PSK;
-                    else
-                        // any vendor checks here
-                        pBSSNode->abyAKMSSAuthType[j++] = WLAN_11i_AKMSS_UNKNOWN;
-                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"abyAKMSSAuthType[%d]: %X\n", j-1, pBSSNode->abyAKMSSAuthType[j-1]);
-                } else
-                    break;
-            }
-            pBSSNode->wAKMSSAuthCount = (unsigned short)j;
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"wAKMSSAuthCount: %d\n", pBSSNode->wAKMSSAuthCount);
-
-            n = *((unsigned short *) &(pRSN->abyRSN[6+4*m]));
-            if (pRSN->len >= 12+4*m+4*n) { // ver(2)+GK(4)+PKCnt(2)+PKS(4*m)+AKMSSCnt(2)+AKMSS(4*n)+Cap(2)
-                pBSSNode->sRSNCapObj.bRSNCapExist = true;
-                pBSSNode->sRSNCapObj.wRSNCap = *((unsigned short *) &(pRSN->abyRSN[8+4*m+4*n]));
-            }
-        }
-        //ignore PMKID lists bcs only (Re)Assocrequest has this field
-        pBSSNode->bWPA2Valid = true;
-    }
+	int                 i, j;
+	unsigned short m = 0, n = 0;
+	unsigned char *pbyOUI;
+	bool bUseGK = false;
+
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WPA2_ParseRSN: [%d]\n", pRSN->len);
+
+	WPA2_ClearRSN(pBSSNode);
+
+	if (pRSN->len == 2) { // ver(2)
+		if ((pRSN->byElementID == WLAN_EID_RSN) && (pRSN->wVersion == 1)) {
+			pBSSNode->bWPA2Valid = true;
+		}
+		return;
+	}
+
+	if (pRSN->len < 6) { // ver(2) + GK(4)
+		// invalid CSS, P802.11i/D10.0, p31
+		return;
+	}
+
+	// information element header makes sense
+	if ((pRSN->byElementID == WLAN_EID_RSN) &&
+	    (pRSN->wVersion == 1)) {
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Legal 802.11i RSN\n");
+
+		pbyOUI = &(pRSN->abyRSN[0]);
+		if (!memcmp(pbyOUI, abyOUIWEP40, 4))
+			pBSSNode->byCSSGK = WLAN_11i_CSS_WEP40;
+		else if (!memcmp(pbyOUI, abyOUITKIP, 4))
+			pBSSNode->byCSSGK = WLAN_11i_CSS_TKIP;
+		else if (!memcmp(pbyOUI, abyOUICCMP, 4))
+			pBSSNode->byCSSGK = WLAN_11i_CSS_CCMP;
+		else if (!memcmp(pbyOUI, abyOUIWEP104, 4))
+			pBSSNode->byCSSGK = WLAN_11i_CSS_WEP104;
+		else if (!memcmp(pbyOUI, abyOUIGK, 4)) {
+			// invalid CSS, P802.11i/D10.0, p32
+			return;
+		} else
+			// any vendor checks here
+			pBSSNode->byCSSGK = WLAN_11i_CSS_UNKNOWN;
+
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "802.11i CSS: %X\n", pBSSNode->byCSSGK);
+
+		if (pRSN->len == 6) {
+			pBSSNode->bWPA2Valid = true;
+			return;
+		}
+
+		if (pRSN->len >= 8) { // ver(2) + GK(4) + PK count(2)
+			pBSSNode->wCSSPKCount = *((unsigned short *)&(pRSN->abyRSN[4]));
+			j = 0;
+			pbyOUI = &(pRSN->abyRSN[6]);
+
+			for (i = 0; (i < pBSSNode->wCSSPKCount) && (j < sizeof(pBSSNode->abyCSSPK)/sizeof(unsigned char)); i++) {
+				if (pRSN->len >= 8+i*4+4) { // ver(2)+GK(4)+PKCnt(2)+PKS(4*i)
+					if (!memcmp(pbyOUI, abyOUIGK, 4)) {
+						pBSSNode->abyCSSPK[j++] = WLAN_11i_CSS_USE_GROUP;
+						bUseGK = true;
+					} else if (!memcmp(pbyOUI, abyOUIWEP40, 4)) {
+						// Invalid CSS, continue to parsing
+					} else if (!memcmp(pbyOUI, abyOUITKIP, 4)) {
+						if (pBSSNode->byCSSGK != WLAN_11i_CSS_CCMP)
+							pBSSNode->abyCSSPK[j++] = WLAN_11i_CSS_TKIP;
+						else
+							; // Invalid CSS, continue to parsing
+					} else if (!memcmp(pbyOUI, abyOUICCMP, 4)) {
+						pBSSNode->abyCSSPK[j++] = WLAN_11i_CSS_CCMP;
+					} else if (!memcmp(pbyOUI, abyOUIWEP104, 4)) {
+						// Invalid CSS, continue to parsing
+					} else {
+						// any vendor checks here
+						pBSSNode->abyCSSPK[j++] = WLAN_11i_CSS_UNKNOWN;
+					}
+					pbyOUI += 4;
+					DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "abyCSSPK[%d]: %X\n", j-1, pBSSNode->abyCSSPK[j-1]);
+				} else
+					break;
+			} //for
+
+			if (bUseGK == true) {
+				if (j != 1) {
+					// invalid CSS, This should be only PK CSS.
+					return;
+				}
+				if (pBSSNode->byCSSGK == WLAN_11i_CSS_CCMP) {
+					// invalid CSS, If CCMP is enable , PK can't be CSSGK.
+					return;
+				}
+			}
+			if ((pBSSNode->wCSSPKCount != 0) && (j == 0)) {
+				// invalid CSS, No valid PK.
+				return;
+			}
+			pBSSNode->wCSSPKCount = (unsigned short)j;
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wCSSPKCount: %d\n", pBSSNode->wCSSPKCount);
+		}
+
+		m = *((unsigned short *)&(pRSN->abyRSN[4]));
+
+		if (pRSN->len >= 10+m*4) { // ver(2) + GK(4) + PK count(2) + PKS(4*m) + AKMSS count(2)
+			pBSSNode->wAKMSSAuthCount = *((unsigned short *)&(pRSN->abyRSN[6+4*m]));
+			j = 0;
+			pbyOUI = &(pRSN->abyRSN[8+4*m]);
+			for (i = 0; (i < pBSSNode->wAKMSSAuthCount) && (j < sizeof(pBSSNode->abyAKMSSAuthType)/sizeof(unsigned char)); i++) {
+				if (pRSN->len >= 10+(m+i)*4+4) { // ver(2)+GK(4)+PKCnt(2)+PKS(4*m)+AKMSS(2)+AKS(4*i)
+					if (!memcmp(pbyOUI, abyOUI8021X, 4))
+						pBSSNode->abyAKMSSAuthType[j++] = WLAN_11i_AKMSS_802_1X;
+					else if (!memcmp(pbyOUI, abyOUIPSK, 4))
+						pBSSNode->abyAKMSSAuthType[j++] = WLAN_11i_AKMSS_PSK;
+					else
+						// any vendor checks here
+						pBSSNode->abyAKMSSAuthType[j++] = WLAN_11i_AKMSS_UNKNOWN;
+					DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "abyAKMSSAuthType[%d]: %X\n", j-1, pBSSNode->abyAKMSSAuthType[j-1]);
+				} else
+					break;
+			}
+			pBSSNode->wAKMSSAuthCount = (unsigned short)j;
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wAKMSSAuthCount: %d\n", pBSSNode->wAKMSSAuthCount);
+
+			n = *((unsigned short *)&(pRSN->abyRSN[6+4*m]));
+			if (pRSN->len >= 12 + 4 * m + 4 * n) { // ver(2)+GK(4)+PKCnt(2)+PKS(4*m)+AKMSSCnt(2)+AKMSS(4*n)+Cap(2)
+				pBSSNode->sRSNCapObj.bRSNCapExist = true;
+				pBSSNode->sRSNCapObj.wRSNCap = *((unsigned short *)&(pRSN->abyRSN[8+4*m+4*n]));
+			}
+		}
+		//ignore PMKID lists bcs only (Re)Assocrequest has this field
+		pBSSNode->bWPA2Valid = true;
+	}
 }
 
-
 /*+
  *
  * Description:
@@ -260,105 +256,105 @@ WPA2vParseRSN (
  *
  * Return Value: length of IEs.
  *
--*/
+ -*/
 unsigned int
 WPA2uSetIEs(
-    void *pMgmtHandle,
-    PWLAN_IE_RSN pRSNIEs
-    )
+	void *pMgmtHandle,
+	PWLAN_IE_RSN pRSNIEs
+)
 {
-    PSMgmtObject    pMgmt = (PSMgmtObject) pMgmtHandle;
-    unsigned char *pbyBuffer = NULL;
-    unsigned int ii = 0;
-    unsigned short *pwPMKID = NULL;
-
-    if (pRSNIEs == NULL) {
-        return(0);
-    }
-    if (((pMgmt->eAuthenMode == WMAC_AUTH_WPA2) ||
-         (pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK)) &&
-        (pMgmt->pCurrBSS != NULL)) {
-        /* WPA2 IE */
-        pbyBuffer = (unsigned char *) pRSNIEs;
-        pRSNIEs->byElementID = WLAN_EID_RSN;
-        pRSNIEs->len = 6; //Version(2)+GK(4)
-        pRSNIEs->wVersion = 1;
-        //Group Key Cipher Suite
-        pRSNIEs->abyRSN[0] = 0x00;
-        pRSNIEs->abyRSN[1] = 0x0F;
-        pRSNIEs->abyRSN[2] = 0xAC;
-        if (pMgmt->byCSSGK == KEY_CTL_WEP) {
-            pRSNIEs->abyRSN[3] = pMgmt->pCurrBSS->byCSSGK;
-        } else if (pMgmt->byCSSGK == KEY_CTL_TKIP) {
-            pRSNIEs->abyRSN[3] = WLAN_11i_CSS_TKIP;
-        } else if (pMgmt->byCSSGK == KEY_CTL_CCMP) {
-            pRSNIEs->abyRSN[3] = WLAN_11i_CSS_CCMP;
-        } else {
-            pRSNIEs->abyRSN[3] = WLAN_11i_CSS_UNKNOWN;
-        }
-
-        // Pairwise Key Cipher Suite
-        pRSNIEs->abyRSN[4] = 1;
-        pRSNIEs->abyRSN[5] = 0;
-        pRSNIEs->abyRSN[6] = 0x00;
-        pRSNIEs->abyRSN[7] = 0x0F;
-        pRSNIEs->abyRSN[8] = 0xAC;
-        if (pMgmt->byCSSPK == KEY_CTL_TKIP) {
-            pRSNIEs->abyRSN[9] = WLAN_11i_CSS_TKIP;
-        } else if (pMgmt->byCSSPK == KEY_CTL_CCMP) {
-            pRSNIEs->abyRSN[9] = WLAN_11i_CSS_CCMP;
-        } else if (pMgmt->byCSSPK == KEY_CTL_NONE) {
-            pRSNIEs->abyRSN[9] = WLAN_11i_CSS_USE_GROUP;
-        } else {
-            pRSNIEs->abyRSN[9] = WLAN_11i_CSS_UNKNOWN;
-        }
-        pRSNIEs->len += 6;
-
-        // Auth Key Management Suite
-        pRSNIEs->abyRSN[10] = 1;
-        pRSNIEs->abyRSN[11] = 0;
-        pRSNIEs->abyRSN[12] = 0x00;
-        pRSNIEs->abyRSN[13] = 0x0F;
-        pRSNIEs->abyRSN[14] = 0xAC;
-        if (pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK) {
-            pRSNIEs->abyRSN[15] = WLAN_11i_AKMSS_PSK;
-        } else if (pMgmt->eAuthenMode == WMAC_AUTH_WPA2) {
-            pRSNIEs->abyRSN[15] = WLAN_11i_AKMSS_802_1X;
-        } else {
-            pRSNIEs->abyRSN[15] = WLAN_11i_AKMSS_UNKNOWN;
-        }
-        pRSNIEs->len +=6;
-
-        // RSN Capabilities
-        if (pMgmt->pCurrBSS->sRSNCapObj.bRSNCapExist == true) {
-            memcpy(&pRSNIEs->abyRSN[16], &pMgmt->pCurrBSS->sRSNCapObj.wRSNCap, 2);
-        } else {
-            pRSNIEs->abyRSN[16] = 0;
-            pRSNIEs->abyRSN[17] = 0;
-        }
-        pRSNIEs->len +=2;
-
-        if ((pMgmt->gsPMKIDCache.BSSIDInfoCount > 0) &&
-            (pMgmt->bRoaming == true) &&
-            (pMgmt->eAuthenMode == WMAC_AUTH_WPA2)) {
-            // RSN PMKID
-            pwPMKID = (unsigned short *)(&pRSNIEs->abyRSN[18]);  // Point to PMKID count
-            *pwPMKID = 0;                               // Initialize PMKID count
-            pbyBuffer = &pRSNIEs->abyRSN[20];           // Point to PMKID list
-            for (ii = 0; ii < pMgmt->gsPMKIDCache.BSSIDInfoCount; ii++) {
-                if ( !memcmp(&pMgmt->gsPMKIDCache.BSSIDInfo[ii].abyBSSID[0], pMgmt->abyCurrBSSID, ETH_ALEN)) {
-                    (*pwPMKID) ++;
-                    memcpy(pbyBuffer, pMgmt->gsPMKIDCache.BSSIDInfo[ii].abyPMKID, 16);
-                    pbyBuffer += 16;
-                }
-            }
-            if (*pwPMKID != 0) {
-                pRSNIEs->len += (2 + (*pwPMKID)*16);
-            } else {
-                pbyBuffer = &pRSNIEs->abyRSN[18];
-            }
-        }
-        return(pRSNIEs->len + WLAN_IEHDR_LEN);
-    }
-    return(0);
+	PSMgmtObject    pMgmt = (PSMgmtObject) pMgmtHandle;
+	unsigned char *pbyBuffer = NULL;
+	unsigned int ii = 0;
+	unsigned short *pwPMKID = NULL;
+
+	if (pRSNIEs == NULL) {
+		return 0;
+	}
+	if (((pMgmt->eAuthenMode == WMAC_AUTH_WPA2) ||
+	     (pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK)) &&
+	    (pMgmt->pCurrBSS != NULL)) {
+		/* WPA2 IE */
+		pbyBuffer = (unsigned char *)pRSNIEs;
+		pRSNIEs->byElementID = WLAN_EID_RSN;
+		pRSNIEs->len = 6; //Version(2)+GK(4)
+		pRSNIEs->wVersion = 1;
+		//Group Key Cipher Suite
+		pRSNIEs->abyRSN[0] = 0x00;
+		pRSNIEs->abyRSN[1] = 0x0F;
+		pRSNIEs->abyRSN[2] = 0xAC;
+		if (pMgmt->byCSSGK == KEY_CTL_WEP) {
+			pRSNIEs->abyRSN[3] = pMgmt->pCurrBSS->byCSSGK;
+		} else if (pMgmt->byCSSGK == KEY_CTL_TKIP) {
+			pRSNIEs->abyRSN[3] = WLAN_11i_CSS_TKIP;
+		} else if (pMgmt->byCSSGK == KEY_CTL_CCMP) {
+			pRSNIEs->abyRSN[3] = WLAN_11i_CSS_CCMP;
+		} else {
+			pRSNIEs->abyRSN[3] = WLAN_11i_CSS_UNKNOWN;
+		}
+
+		// Pairwise Key Cipher Suite
+		pRSNIEs->abyRSN[4] = 1;
+		pRSNIEs->abyRSN[5] = 0;
+		pRSNIEs->abyRSN[6] = 0x00;
+		pRSNIEs->abyRSN[7] = 0x0F;
+		pRSNIEs->abyRSN[8] = 0xAC;
+		if (pMgmt->byCSSPK == KEY_CTL_TKIP) {
+			pRSNIEs->abyRSN[9] = WLAN_11i_CSS_TKIP;
+		} else if (pMgmt->byCSSPK == KEY_CTL_CCMP) {
+			pRSNIEs->abyRSN[9] = WLAN_11i_CSS_CCMP;
+		} else if (pMgmt->byCSSPK == KEY_CTL_NONE) {
+			pRSNIEs->abyRSN[9] = WLAN_11i_CSS_USE_GROUP;
+		} else {
+			pRSNIEs->abyRSN[9] = WLAN_11i_CSS_UNKNOWN;
+		}
+		pRSNIEs->len += 6;
+
+		// Auth Key Management Suite
+		pRSNIEs->abyRSN[10] = 1;
+		pRSNIEs->abyRSN[11] = 0;
+		pRSNIEs->abyRSN[12] = 0x00;
+		pRSNIEs->abyRSN[13] = 0x0F;
+		pRSNIEs->abyRSN[14] = 0xAC;
+		if (pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK) {
+			pRSNIEs->abyRSN[15] = WLAN_11i_AKMSS_PSK;
+		} else if (pMgmt->eAuthenMode == WMAC_AUTH_WPA2) {
+			pRSNIEs->abyRSN[15] = WLAN_11i_AKMSS_802_1X;
+		} else {
+			pRSNIEs->abyRSN[15] = WLAN_11i_AKMSS_UNKNOWN;
+		}
+		pRSNIEs->len += 6;
+
+		// RSN Capabilities
+		if (pMgmt->pCurrBSS->sRSNCapObj.bRSNCapExist == true) {
+			memcpy(&pRSNIEs->abyRSN[16], &pMgmt->pCurrBSS->sRSNCapObj.wRSNCap, 2);
+		} else {
+			pRSNIEs->abyRSN[16] = 0;
+			pRSNIEs->abyRSN[17] = 0;
+		}
+		pRSNIEs->len += 2;
+
+		if ((pMgmt->gsPMKIDCache.BSSIDInfoCount > 0) &&
+		    (pMgmt->bRoaming == true) &&
+		    (pMgmt->eAuthenMode == WMAC_AUTH_WPA2)) {
+			// RSN PMKID
+			pwPMKID = (unsigned short *)(&pRSNIEs->abyRSN[18]);  // Point to PMKID count
+			*pwPMKID = 0;                               // Initialize PMKID count
+			pbyBuffer = &pRSNIEs->abyRSN[20];           // Point to PMKID list
+			for (ii = 0; ii < pMgmt->gsPMKIDCache.BSSIDInfoCount; ii++) {
+				if (!memcmp(&pMgmt->gsPMKIDCache.BSSIDInfo[ii].abyBSSID[0], pMgmt->abyCurrBSSID, ETH_ALEN)) {
+					(*pwPMKID)++;
+					memcpy(pbyBuffer, pMgmt->gsPMKIDCache.BSSIDInfo[ii].abyPMKID, 16);
+					pbyBuffer += 16;
+				}
+			}
+			if (*pwPMKID != 0) {
+				pRSNIEs->len += (2 + (*pwPMKID)*16);
+			} else {
+				pbyBuffer = &pRSNIEs->abyRSN[18];
+			}
+		}
+		return pRSNIEs->len + WLAN_IEHDR_LEN;
+	}
+	return 0;
 }
diff --git a/drivers/staging/vt6655/wpa2.h b/drivers/staging/vt6655/wpa2.h
index 718208b..2d0bd2e 100644
--- a/drivers/staging/vt6655/wpa2.h
+++ b/drivers/staging/vt6655/wpa2.h
@@ -40,16 +40,15 @@
 #define MAX_PMKID_CACHE         16
 
 typedef struct tagsPMKIDInfo {
-    unsigned char abyBSSID[6];
-    unsigned char abyPMKID[16];
+	unsigned char abyBSSID[6];
+	unsigned char abyPMKID[16];
 } PMKIDInfo, *PPMKIDInfo;
 
 typedef struct tagSPMKIDCache {
-    unsigned long BSSIDInfoCount;
-    PMKIDInfo   BSSIDInfo[MAX_PMKID_CACHE];
+	unsigned long BSSIDInfoCount;
+	PMKIDInfo   BSSIDInfo[MAX_PMKID_CACHE];
 } SPMKIDCache, *PSPMKIDCache;
 
-
 /*---------------------  Export Classes  ----------------------------*/
 
 /*---------------------  Export Variables  --------------------------*/
@@ -59,20 +58,20 @@ typedef struct tagSPMKIDCache {
 /*---------------------  Export Functions  --------------------------*/
 
 void
-WPA2_ClearRSN (
-    PKnownBSS        pBSSNode
-    );
+WPA2_ClearRSN(
+	PKnownBSS        pBSSNode
+);
 
 void
-WPA2vParseRSN (
-    PKnownBSS        pBSSNode,
-    PWLAN_IE_RSN     pRSN
-    );
+WPA2vParseRSN(
+	PKnownBSS        pBSSNode,
+	PWLAN_IE_RSN     pRSN
+);
 
 unsigned int
 WPA2uSetIEs(
-    void *pMgmtHandle,
-    PWLAN_IE_RSN pRSNIEs
-    );
+	void *pMgmtHandle,
+	PWLAN_IE_RSN pRSNIEs
+);
 
 #endif // __WPA2_H__
diff --git a/drivers/staging/vt6655/wpactl.c b/drivers/staging/vt6655/wpactl.c
index 2b6ae1e..869f62c 100644
--- a/drivers/staging/vt6655/wpactl.c
+++ b/drivers/staging/vt6655/wpactl.c
@@ -44,8 +44,6 @@
 
 #define VIAWGET_WPA_MAX_BUF_SIZE 1024
 
-
-
 static const int frequency_list[] = {
 	2412, 2417, 2422, 2427, 2432, 2437, 2442,
 	2447, 2452, 2457, 2462, 2467, 2472, 2484
@@ -54,13 +52,10 @@ static const int frequency_list[] = {
 
 /*---------------------  Static Variables  --------------------------*/
 //static int          msglevel                =MSG_LEVEL_DEBUG;
-static int          msglevel                =MSG_LEVEL_INFO;
+static int msglevel = MSG_LEVEL_INFO;
 
 /*---------------------  Static Functions  --------------------------*/
 
-
-
-
 /*---------------------  Export Variables  --------------------------*/
 static void wpadev_setup(struct net_device *dev)
 {
@@ -70,7 +65,7 @@ static void wpadev_setup(struct net_device *dev)
 	dev->addr_len           = ETH_ALEN;
 	dev->tx_queue_len       = 1000;
 
-	memset(dev->broadcast,0xFF, ETH_ALEN);
+	memset(dev->broadcast, 0xFF, ETH_ALEN);
 
 	dev->flags              = IFF_BROADCAST|IFF_MULTICAST;
 }
@@ -91,42 +86,41 @@ static void wpadev_setup(struct net_device *dev)
 
 static int wpa_init_wpadev(PSDevice pDevice)
 {
-    PSDevice wpadev_priv;
+	PSDevice wpadev_priv;
 	struct net_device *dev = pDevice->dev;
-         int ret=0;
+	int ret = 0;
 
 	pDevice->wpadev = alloc_netdev(sizeof(PSDevice), "vntwpa", wpadev_setup);
 	if (pDevice->wpadev == NULL)
 		return -ENOMEM;
 
-    wpadev_priv = netdev_priv(pDevice->wpadev);
-    *wpadev_priv = *pDevice;
+	wpadev_priv = netdev_priv(pDevice->wpadev);
+	*wpadev_priv = *pDevice;
 	memcpy(pDevice->wpadev->dev_addr, dev->dev_addr, ETH_ALEN);
-         pDevice->wpadev->base_addr = dev->base_addr;
+	pDevice->wpadev->base_addr = dev->base_addr;
 	pDevice->wpadev->irq = dev->irq;
 	pDevice->wpadev->mem_start = dev->mem_start;
 	pDevice->wpadev->mem_end = dev->mem_end;
 	ret = register_netdev(pDevice->wpadev);
 	if (ret) {
 		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: register_netdev(WPA) failed!\n",
-		       dev->name);
+			dev->name);
 		free_netdev(pDevice->wpadev);
 		return -1;
 	}
 
 	if (pDevice->skb == NULL) {
-        pDevice->skb = dev_alloc_skb((int)pDevice->rx_buf_sz);
-        if (pDevice->skb == NULL)
-		    return -ENOMEM;
-    }
+		pDevice->skb = dev_alloc_skb((int)pDevice->rx_buf_sz);
+		if (pDevice->skb == NULL)
+			return -ENOMEM;
+	}
 
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: Registered netdev %s for WPA management\n",
-	       dev->name, pDevice->wpadev->name);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: Registered netdev %s for WPA management\n",
+		dev->name, pDevice->wpadev->name);
 
 	return 0;
 }
 
-
 /*
  * Description:
  *      unregister net_device (wpadev)
@@ -142,26 +136,22 @@ static int wpa_init_wpadev(PSDevice pDevice)
 
 static int wpa_release_wpadev(PSDevice pDevice)
 {
-    if (pDevice->skb) {
-        dev_kfree_skb(pDevice->skb);
-        pDevice->skb = NULL;
-    }
-
-    if (pDevice->wpadev) {
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: Netdevice %s unregistered\n",
-	       pDevice->dev->name, pDevice->wpadev->name);
-	unregister_netdev(pDevice->wpadev);
-	free_netdev(pDevice->wpadev);
-         pDevice->wpadev = NULL;
-    }
+	if (pDevice->skb) {
+		dev_kfree_skb(pDevice->skb);
+		pDevice->skb = NULL;
+	}
+
+	if (pDevice->wpadev) {
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: Netdevice %s unregistered\n",
+			pDevice->dev->name, pDevice->wpadev->name);
+		unregister_netdev(pDevice->wpadev);
+		free_netdev(pDevice->wpadev);
+		pDevice->wpadev = NULL;
+	}
 
 	return 0;
 }
 
-
-
-
-
 /*
  * Description:
  *      Set enable/disable dev for wpa supplicant daemon
@@ -184,7 +174,6 @@ int wpa_set_wpadev(PSDevice pDevice, int val)
 		return wpa_release_wpadev(pDevice);
 }
 
-
 /*
  * Description:
  *      Set WPA algorithm & keys
@@ -199,252 +188,245 @@ int wpa_set_wpadev(PSDevice pDevice, int val)
  *
  */
 
- int wpa_set_keys(PSDevice pDevice, void *ctx, bool fcpfkernel)
+int wpa_set_keys(PSDevice pDevice, void *ctx, bool fcpfkernel)
 {
-    struct viawget_wpa_param *param=ctx;
-    PSMgmtObject pMgmt = pDevice->pMgmt;
-    unsigned long dwKeyIndex = 0;
-    unsigned char abyKey[MAX_KEY_LEN];
-    unsigned char abySeq[MAX_KEY_LEN];
-    QWORD   KeyRSC;
+	struct viawget_wpa_param *param = ctx;
+	PSMgmtObject pMgmt = pDevice->pMgmt;
+	unsigned long dwKeyIndex = 0;
+	unsigned char abyKey[MAX_KEY_LEN];
+	unsigned char abySeq[MAX_KEY_LEN];
+	QWORD   KeyRSC;
 //    NDIS_802_11_KEY_RSC KeyRSC;
-    unsigned char byKeyDecMode = KEY_CTL_WEP;
+	unsigned char byKeyDecMode = KEY_CTL_WEP;
 	int ret = 0;
 	int uu, ii;
 
-
 	if (param->u.wpa_key.alg_name > WPA_ALG_CCMP ||
-			param->u.wpa_key.key_len >= MAX_KEY_LEN ||
-			param->u.wpa_key.seq_len >= MAX_KEY_LEN)
+	    param->u.wpa_key.key_len >= MAX_KEY_LEN ||
+	    param->u.wpa_key.seq_len >= MAX_KEY_LEN)
 		return -EINVAL;
 
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "param->u.wpa_key.alg_name = %d \n", param->u.wpa_key.alg_name);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "param->u.wpa_key.alg_name = %d \n", param->u.wpa_key.alg_name);
 	if (param->u.wpa_key.alg_name == WPA_ALG_NONE) {
-        pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled;
-        pDevice->bEncryptionEnable = false;
-        pDevice->byKeyIndex = 0;
-        pDevice->bTransmitKey = false;
-        KeyvRemoveAllWEPKey(&(pDevice->sKey), pDevice->PortOffset);
-        for (uu=0; uu<MAX_KEY_TABLE; uu++) {
-            MACvDisableKeyEntry(pDevice->PortOffset, uu);
-        }
-        return ret;
-    }
-
-    //spin_unlock_irq(&pDevice->lock);
-    if(param->u.wpa_key.key && fcpfkernel) {
-       memcpy(&abyKey[0], param->u.wpa_key.key, param->u.wpa_key.key_len);
-     }
-    else {
-	spin_unlock_irq(&pDevice->lock);
-	if (param->u.wpa_key.key &&
-	    copy_from_user(&abyKey[0], param->u.wpa_key.key, param->u.wpa_key.key_len)) {
-	    spin_lock_irq(&pDevice->lock);
-	    return -EINVAL;
-    	}
-spin_lock_irq(&pDevice->lock);
-    	}
+		pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled;
+		pDevice->bEncryptionEnable = false;
+		pDevice->byKeyIndex = 0;
+		pDevice->bTransmitKey = false;
+		KeyvRemoveAllWEPKey(&(pDevice->sKey), pDevice->PortOffset);
+		for (uu = 0; uu < MAX_KEY_TABLE; uu++) {
+			MACvDisableKeyEntry(pDevice->PortOffset, uu);
+		}
+		return ret;
+	}
+
+	//spin_unlock_irq(&pDevice->lock);
+	if (param->u.wpa_key.key && fcpfkernel) {
+		memcpy(&abyKey[0], param->u.wpa_key.key, param->u.wpa_key.key_len);
+	} else {
+		spin_unlock_irq(&pDevice->lock);
+		if (param->u.wpa_key.key &&
+		    copy_from_user(&abyKey[0], param->u.wpa_key.key, param->u.wpa_key.key_len)) {
+			spin_lock_irq(&pDevice->lock);
+			return -EINVAL;
+		}
+		spin_lock_irq(&pDevice->lock);
+	}
 
-    dwKeyIndex = (unsigned long)(param->u.wpa_key.key_index);
+	dwKeyIndex = (unsigned long)(param->u.wpa_key.key_index);
 
 	if (param->u.wpa_key.alg_name == WPA_ALG_WEP) {
-        if (dwKeyIndex > 3) {
-            return -EINVAL;
-        }
-        else {
-            if (param->u.wpa_key.set_tx) {
-                pDevice->byKeyIndex = (unsigned char)dwKeyIndex;
-                pDevice->bTransmitKey = true;
-		        dwKeyIndex |= (1 << 31);
-            }
-            KeybSetDefaultKey(&(pDevice->sKey),
-                                dwKeyIndex & ~(BIT30 | USE_KEYRSC),
-                                param->u.wpa_key.key_len,
-                                NULL,
-                                abyKey,
-                                KEY_CTL_WEP,
-                                pDevice->PortOffset,
-                                pDevice->byLocalID);
-
-        }
-        pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled;
-        pDevice->bEncryptionEnable = true;
-        return ret;
-	}
-
-	    //spin_unlock_irq(&pDevice->lock);
-        if(param->u.wpa_key.seq && fcpfkernel) {
-           memcpy(&abySeq[0], param->u.wpa_key.seq, param->u.wpa_key.seq_len);
-        	}
-       else {
-	   	spin_unlock_irq(&pDevice->lock);
-	if (param->u.wpa_key.seq &&
-	    copy_from_user(&abySeq[0], param->u.wpa_key.seq, param->u.wpa_key.seq_len)) {
-	    spin_lock_irq(&pDevice->lock);
-	    return -EINVAL;
-       	}
-spin_lock_irq(&pDevice->lock);
-}
+		if (dwKeyIndex > 3) {
+			return -EINVAL;
+		} else {
+			if (param->u.wpa_key.set_tx) {
+				pDevice->byKeyIndex = (unsigned char)dwKeyIndex;
+				pDevice->bTransmitKey = true;
+				dwKeyIndex |= (1 << 31);
+			}
+			KeybSetDefaultKey(&(pDevice->sKey),
+					  dwKeyIndex & ~(BIT30 | USE_KEYRSC),
+					  param->u.wpa_key.key_len,
+					  NULL,
+					  abyKey,
+					  KEY_CTL_WEP,
+					  pDevice->PortOffset,
+					  pDevice->byLocalID);
+
+		}
+		pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled;
+		pDevice->bEncryptionEnable = true;
+		return ret;
+	}
+
+	//spin_unlock_irq(&pDevice->lock);
+	if (param->u.wpa_key.seq && fcpfkernel) {
+		memcpy(&abySeq[0], param->u.wpa_key.seq, param->u.wpa_key.seq_len);
+	} else {
+		spin_unlock_irq(&pDevice->lock);
+		if (param->u.wpa_key.seq &&
+		    copy_from_user(&abySeq[0], param->u.wpa_key.seq, param->u.wpa_key.seq_len)) {
+			spin_lock_irq(&pDevice->lock);
+			return -EINVAL;
+		}
+		spin_lock_irq(&pDevice->lock);
+	}
 
 	if (param->u.wpa_key.seq_len > 0) {
-		for (ii = 0 ; ii < param->u.wpa_key.seq_len ; ii++) {
-		     if (ii < 4)
-			    LODWORD(KeyRSC) |= (abySeq[ii] << (ii * 8));
-			 else
-			    HIDWORD(KeyRSC) |= (abySeq[ii] << ((ii-4) * 8));
-	         //KeyRSC |= (abySeq[ii] << (ii * 8));
+		for (ii = 0; ii < param->u.wpa_key.seq_len; ii++) {
+			if (ii < 4)
+				LODWORD(KeyRSC) |= (abySeq[ii] << (ii * 8));
+			else
+				HIDWORD(KeyRSC) |= (abySeq[ii] << ((ii-4) * 8));
+			//KeyRSC |= (abySeq[ii] << (ii * 8));
 		}
 		dwKeyIndex |= 1 << 29;
 	}
 
-    if (param->u.wpa_key.key_index >= MAX_GROUP_KEY) {
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "return  dwKeyIndex > 3\n");
-        return -EINVAL;
-    }
+	if (param->u.wpa_key.key_index >= MAX_GROUP_KEY) {
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "return  dwKeyIndex > 3\n");
+		return -EINVAL;
+	}
 
 	if (param->u.wpa_key.alg_name == WPA_ALG_TKIP) {
-        pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled;
-    }
+		pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled;
+	}
 
 	if (param->u.wpa_key.alg_name == WPA_ALG_CCMP) {
-        pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled;
-    }
+		pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled;
+	}
 
 	if (param->u.wpa_key.set_tx)
 		dwKeyIndex |= (1 << 31);
 
+	if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled)
+		byKeyDecMode = KEY_CTL_CCMP;
+	else if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled)
+		byKeyDecMode = KEY_CTL_TKIP;
+	else
+		byKeyDecMode = KEY_CTL_WEP;
+
+	// Fix HCT test that set 256 bits KEY and Ndis802_11Encryption3Enabled
+	if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) {
+		if (param->u.wpa_key.key_len == MAX_KEY_LEN)
+			byKeyDecMode = KEY_CTL_TKIP;
+		else if (param->u.wpa_key.key_len == WLAN_WEP40_KEYLEN)
+			byKeyDecMode = KEY_CTL_WEP;
+		else if (param->u.wpa_key.key_len == WLAN_WEP104_KEYLEN)
+			byKeyDecMode = KEY_CTL_WEP;
+	} else if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) {
+		if (param->u.wpa_key.key_len == WLAN_WEP40_KEYLEN)
+			byKeyDecMode = KEY_CTL_WEP;
+		else if (param->u.wpa_key.key_len == WLAN_WEP104_KEYLEN)
+			byKeyDecMode = KEY_CTL_WEP;
+	}
+
+	// Check TKIP key length
+	if ((byKeyDecMode == KEY_CTL_TKIP) &&
+	    (param->u.wpa_key.key_len != MAX_KEY_LEN)) {
+		// TKIP Key must be 256 bits
+		//DBG_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA - TKIP Key must be 256 bits\n"));
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "return- TKIP Key must be 256 bits!\n");
+		return -EINVAL;
+	}
+	// Check AES key length
+	if ((byKeyDecMode == KEY_CTL_CCMP) &&
+	    (param->u.wpa_key.key_len != AES_KEY_LEN)) {
+		// AES Key must be 128 bits
+		//DBG_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA - AES Key must be 128 bits\n"));
+		return -EINVAL;
+	}
+
+	// spin_lock_irq(&pDevice->lock);
+	if (is_broadcast_ether_addr(&param->addr[0]) || (param->addr == NULL)) {
+		// If is_broadcast_ether_addr, set the key as every key entry's group key.
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Groupe Key Assign.\n");
+
+		if ((KeybSetAllGroupKey(&(pDevice->sKey),
+					dwKeyIndex,
+					param->u.wpa_key.key_len,
+					(PQWORD) &(KeyRSC),
+					(unsigned char *)abyKey,
+					byKeyDecMode,
+					pDevice->PortOffset,
+					pDevice->byLocalID) == true) &&
+		    (KeybSetDefaultKey(&(pDevice->sKey),
+				       dwKeyIndex,
+				       param->u.wpa_key.key_len,
+				       (PQWORD) &(KeyRSC),
+				       (unsigned char *)abyKey,
+				       byKeyDecMode,
+				       pDevice->PortOffset,
+				       pDevice->byLocalID) == true)) {
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "GROUP Key Assign.\n");
+
+		} else {
+			//DBG_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA -KeybSetDefaultKey Fail.0\n"));
+			// spin_unlock_irq(&pDevice->lock);
+			return -EINVAL;
+		}
+
+	} else {
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pairwise Key Assign.\n");
+		// BSSID not 0xffffffffffff
+		// Pairwise Key can't be WEP
+		if (byKeyDecMode == KEY_CTL_WEP) {
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pairwise Key can't be WEP\n");
+			//spin_unlock_irq(&pDevice->lock);
+			return -EINVAL;
+		}
 
-    if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled)
-        byKeyDecMode = KEY_CTL_CCMP;
-    else if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled)
-        byKeyDecMode = KEY_CTL_TKIP;
-    else
-        byKeyDecMode = KEY_CTL_WEP;
-
-    // Fix HCT test that set 256 bits KEY and Ndis802_11Encryption3Enabled
-    if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) {
-        if (param->u.wpa_key.key_len == MAX_KEY_LEN)
-            byKeyDecMode = KEY_CTL_TKIP;
-        else if (param->u.wpa_key.key_len == WLAN_WEP40_KEYLEN)
-            byKeyDecMode = KEY_CTL_WEP;
-        else if (param->u.wpa_key.key_len == WLAN_WEP104_KEYLEN)
-            byKeyDecMode = KEY_CTL_WEP;
-    } else if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) {
-        if (param->u.wpa_key.key_len == WLAN_WEP40_KEYLEN)
-            byKeyDecMode = KEY_CTL_WEP;
-        else if (param->u.wpa_key.key_len == WLAN_WEP104_KEYLEN)
-            byKeyDecMode = KEY_CTL_WEP;
-    }
-
-    // Check TKIP key length
-    if ((byKeyDecMode == KEY_CTL_TKIP) &&
-        (param->u.wpa_key.key_len != MAX_KEY_LEN)) {
-        // TKIP Key must be 256 bits
-        //DBG_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA - TKIP Key must be 256 bits\n"));
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "return- TKIP Key must be 256 bits!\n");
-        return -EINVAL;
-    }
-    // Check AES key length
-    if ((byKeyDecMode == KEY_CTL_CCMP) &&
-        (param->u.wpa_key.key_len != AES_KEY_LEN)) {
-        // AES Key must be 128 bits
-        //DBG_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA - AES Key must be 128 bits\n"));
-        return -EINVAL;
-    }
-
-   // spin_lock_irq(&pDevice->lock);
-    if (is_broadcast_ether_addr(&param->addr[0]) || (param->addr == NULL)) {
-        // If is_broadcast_ether_addr, set the key as every key entry's group key.
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Groupe Key Assign.\n");
-
-        if ((KeybSetAllGroupKey(&(pDevice->sKey),
-                            dwKeyIndex,
-                            param->u.wpa_key.key_len,
-                            (PQWORD) &(KeyRSC),
-                            (unsigned char *)abyKey,
-                            byKeyDecMode,
-                            pDevice->PortOffset,
-                            pDevice->byLocalID) == true) &&
-            (KeybSetDefaultKey(&(pDevice->sKey),
-                            dwKeyIndex,
-                            param->u.wpa_key.key_len,
-                            (PQWORD) &(KeyRSC),
-                            (unsigned char *)abyKey,
-                            byKeyDecMode,
-                            pDevice->PortOffset,
-                            pDevice->byLocalID) == true) ) {
-             DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "GROUP Key Assign.\n");
-
-        } else {
-            //DBG_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA -KeybSetDefaultKey Fail.0\n"));
-           // spin_unlock_irq(&pDevice->lock);
-            return -EINVAL;
-        }
-
-    } else {
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pairwise Key Assign.\n");
-        // BSSID not 0xffffffffffff
-        // Pairwise Key can't be WEP
-        if (byKeyDecMode == KEY_CTL_WEP) {
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pairwise Key can't be WEP\n");
-            //spin_unlock_irq(&pDevice->lock);
-            return -EINVAL;
-        }
-
-        dwKeyIndex |= (1 << 30); // set pairwise key
-        if (pMgmt->eConfigMode == WMAC_CONFIG_IBSS_STA) {
-            //DBG_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA - WMAC_CONFIG_IBSS_STA\n"));
-            //spin_unlock_irq(&pDevice->lock);
-            return -EINVAL;
-        }
-        if (KeybSetKey(&(pDevice->sKey),
-                       &param->addr[0],
-                       dwKeyIndex,
-                       param->u.wpa_key.key_len,
-                       (PQWORD) &(KeyRSC),
-                       (unsigned char *)abyKey,
-                        byKeyDecMode,
-                        pDevice->PortOffset,
-                        pDevice->byLocalID) == true) {
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pairwise Key Set\n");
-
-        } else {
-            // Key Table Full
-            if (!compare_ether_addr(&param->addr[0], pDevice->abyBSSID)) {
-                //DBG_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA -Key Table Full.2\n"));
-                //spin_unlock_irq(&pDevice->lock);
-                return -EINVAL;
-
-            } else {
-                // Save Key and configure just before associate/reassociate to BSSID
-                // we do not implement now
-                //spin_unlock_irq(&pDevice->lock);
-                return -EINVAL;
-            }
-        }
-    } // BSSID not 0xffffffffffff
-    if ((ret == 0) && ((param->u.wpa_key.set_tx) != 0)) {
-        pDevice->byKeyIndex = (unsigned char)param->u.wpa_key.key_index;
-        pDevice->bTransmitKey = true;
-    }
-    pDevice->bEncryptionEnable = true;
-    //spin_unlock_irq(&pDevice->lock);
+		dwKeyIndex |= (1 << 30); // set pairwise key
+		if (pMgmt->eConfigMode == WMAC_CONFIG_IBSS_STA) {
+			//DBG_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA - WMAC_CONFIG_IBSS_STA\n"));
+			//spin_unlock_irq(&pDevice->lock);
+			return -EINVAL;
+		}
+		if (KeybSetKey(&(pDevice->sKey),
+			       &param->addr[0],
+			       dwKeyIndex,
+			       param->u.wpa_key.key_len,
+			       (PQWORD) &(KeyRSC),
+			       (unsigned char *)abyKey,
+			       byKeyDecMode,
+			       pDevice->PortOffset,
+			       pDevice->byLocalID) == true) {
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pairwise Key Set\n");
+
+		} else {
+			// Key Table Full
+			if (!compare_ether_addr(&param->addr[0], pDevice->abyBSSID)) {
+				//DBG_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA -Key Table Full.2\n"));
+				//spin_unlock_irq(&pDevice->lock);
+				return -EINVAL;
+
+			} else {
+				// Save Key and configure just before associate/reassociate to BSSID
+				// we do not implement now
+				//spin_unlock_irq(&pDevice->lock);
+				return -EINVAL;
+			}
+		}
+	} // BSSID not 0xffffffffffff
+	if ((ret == 0) && ((param->u.wpa_key.set_tx) != 0)) {
+		pDevice->byKeyIndex = (unsigned char)param->u.wpa_key.key_index;
+		pDevice->bTransmitKey = true;
+	}
+	pDevice->bEncryptionEnable = true;
+	//spin_unlock_irq(&pDevice->lock);
 
 /*
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " key=%x-%x-%x-%x-%x-xxxxx \n",
-               pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[byKeyIndex][0],
-               pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[byKeyIndex][1],
-               pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[byKeyIndex][2],
-               pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[byKeyIndex][3],
-               pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[byKeyIndex][4]
-              );
+  DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " key=%x-%x-%x-%x-%x-xxxxx \n",
+  pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[byKeyIndex][0],
+  pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[byKeyIndex][1],
+  pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[byKeyIndex][2],
+  pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[byKeyIndex][3],
+  pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[byKeyIndex][4]
+);
 */
 
 	return ret;
-
 }
 
-
 /*
  * Description:
  *      enable wpa auth & mode
@@ -460,22 +442,18 @@ spin_lock_irq(&pDevice->lock);
  */
 
 static int wpa_set_wpa(PSDevice pDevice,
-				     struct viawget_wpa_param *param)
+		       struct viawget_wpa_param *param)
 {
-
-    PSMgmtObject    pMgmt = pDevice->pMgmt;
+	PSMgmtObject    pMgmt = pDevice->pMgmt;
 	int ret = 0;
 
-    pMgmt->eAuthenMode = WMAC_AUTH_OPEN;
-    pMgmt->bShareKeyAlgorithm = false;
+	pMgmt->eAuthenMode = WMAC_AUTH_OPEN;
+	pMgmt->bShareKeyAlgorithm = false;
 
-    return ret;
+	return ret;
 }
 
-
-
-
- /*
+/*
  * Description:
  *      set disassociate
  *
@@ -490,23 +468,21 @@ static int wpa_set_wpa(PSDevice pDevice,
  */
 
 static int wpa_set_disassociate(PSDevice pDevice,
-				     struct viawget_wpa_param *param)
+				struct viawget_wpa_param *param)
 {
-    PSMgmtObject    pMgmt = pDevice->pMgmt;
+	PSMgmtObject    pMgmt = pDevice->pMgmt;
 	int ret = 0;
 
-    spin_lock_irq(&pDevice->lock);
-    if (pDevice->bLinkPass) {
-        if (!memcmp(param->addr, pMgmt->abyCurrBSSID, 6))
-            bScheduleCommand((void *)pDevice, WLAN_CMD_DISASSOCIATE, NULL);
-    }
-    spin_unlock_irq(&pDevice->lock);
+	spin_lock_irq(&pDevice->lock);
+	if (pDevice->bLinkPass) {
+		if (!memcmp(param->addr, pMgmt->abyCurrBSSID, 6))
+			bScheduleCommand((void *)pDevice, WLAN_CMD_DISASSOCIATE, NULL);
+	}
+	spin_unlock_irq(&pDevice->lock);
 
-    return ret;
+	return ret;
 }
 
-
-
 /*
  * Description:
  *      enable scan process
@@ -522,20 +498,18 @@ static int wpa_set_disassociate(PSDevice pDevice,
  */
 
 static int wpa_set_scan(PSDevice pDevice,
-				     struct viawget_wpa_param *param)
+			struct viawget_wpa_param *param)
 {
 	int ret = 0;
 
-    spin_lock_irq(&pDevice->lock);
-    BSSvClearBSSList((void *)pDevice, pDevice->bLinkPass);
-    bScheduleCommand((void *) pDevice, WLAN_CMD_BSSID_SCAN, NULL);
-    spin_unlock_irq(&pDevice->lock);
+	spin_lock_irq(&pDevice->lock);
+	BSSvClearBSSList((void *)pDevice, pDevice->bLinkPass);
+	bScheduleCommand((void *)pDevice, WLAN_CMD_BSSID_SCAN, NULL);
+	spin_unlock_irq(&pDevice->lock);
 
-    return ret;
+	return ret;
 }
 
-
-
 /*
  * Description:
  *      get bssid
@@ -551,18 +525,16 @@ static int wpa_set_scan(PSDevice pDevice,
  */
 
 static int wpa_get_bssid(PSDevice pDevice,
-				     struct viawget_wpa_param *param)
+			 struct viawget_wpa_param *param)
 {
-    PSMgmtObject        pMgmt = pDevice->pMgmt;
+	PSMgmtObject        pMgmt = pDevice->pMgmt;
 	int ret = 0;
 
 	memcpy(param->u.wpa_associate.bssid, pMgmt->abyCurrBSSID , 6);
 
-    return ret;
-
+	return ret;
 }
 
-
 /*
  * Description:
  *      get bssid
@@ -578,22 +550,20 @@ static int wpa_get_bssid(PSDevice pDevice,
  */
 
 static int wpa_get_ssid(PSDevice pDevice,
-				     struct viawget_wpa_param *param)
+			struct viawget_wpa_param *param)
 {
-    PSMgmtObject        pMgmt = pDevice->pMgmt;
+	PSMgmtObject        pMgmt = pDevice->pMgmt;
 	PWLAN_IE_SSID       pItemSSID;
 	int ret = 0;
 
-    pItemSSID = (PWLAN_IE_SSID)pMgmt->abyCurrSSID;
+	pItemSSID = (PWLAN_IE_SSID)pMgmt->abyCurrSSID;
 
 	memcpy(param->u.wpa_associate.ssid, pItemSSID->abySSID , pItemSSID->len);
 	param->u.wpa_associate.ssid_len = pItemSSID->len;
 
-    return ret;
+	return ret;
 }
 
-
-
 /*
  * Description:
  *      get scan results
@@ -609,132 +579,112 @@ static int wpa_get_ssid(PSDevice pDevice,
  */
 
 static int wpa_get_scan(PSDevice pDevice,
-				     struct viawget_wpa_param *param)
+			struct viawget_wpa_param *param)
 {
 	struct viawget_scan_result *scan_buf;
-    PSMgmtObject    pMgmt = pDevice->pMgmt;
-    PWLAN_IE_SSID   pItemSSID;
-    PKnownBSS pBSS;
+	PSMgmtObject    pMgmt = pDevice->pMgmt;
+	PWLAN_IE_SSID   pItemSSID;
+	PKnownBSS pBSS;
 	unsigned char *pBuf;
 	int ret = 0;
 	u16 count = 0;
 	u16 ii, jj;
 #if 1
 
-    unsigned char *ptempBSS;
-
-
-
-    ptempBSS = kmalloc(sizeof(KnownBSS), (int)GFP_ATOMIC);
-
-    if (ptempBSS == NULL) {
-
-       printk("bubble sort kmalloc memory fail@@@\n");
+	unsigned char *ptempBSS;
 
-        ret = -ENOMEM;
+	ptempBSS = kmalloc(sizeof(KnownBSS), (int)GFP_ATOMIC);
 
-        return ret;
+	if (ptempBSS == NULL) {
+		printk("bubble sort kmalloc memory fail@@@\n");
 
-    }
+		ret = -ENOMEM;
 
-    for (ii = 0; ii < MAX_BSS_NUM; ii++) {
+		return ret;
 
-         for(jj=0;jj<MAX_BSS_NUM-ii-1;jj++) {
-
-           if((pMgmt->sBSSList[jj].bActive!=true) ||
-
-                ((pMgmt->sBSSList[jj].uRSSI>pMgmt->sBSSList[jj+1].uRSSI) &&(pMgmt->sBSSList[jj+1].bActive!=false))) {
-
-                 memcpy(ptempBSS,&pMgmt->sBSSList[jj],sizeof(KnownBSS));
-
-                 memcpy(&pMgmt->sBSSList[jj],&pMgmt->sBSSList[jj+1],sizeof(KnownBSS));
-
-                 memcpy(&pMgmt->sBSSList[jj+1],ptempBSS,sizeof(KnownBSS));
-
-              }
+	}
 
-         }
+	for (ii = 0; ii < MAX_BSS_NUM; ii++) {
+		for (jj = 0; jj < MAX_BSS_NUM - ii - 1; jj++) {
+			if ((pMgmt->sBSSList[jj].bActive != true) ||
 
-    }
+			    ((pMgmt->sBSSList[jj].uRSSI > pMgmt->sBSSList[jj + 1].uRSSI) && (pMgmt->sBSSList[jj + 1].bActive != false))) {
+				memcpy(ptempBSS, &pMgmt->sBSSList[jj], sizeof(KnownBSS));
 
-  kfree(ptempBSS);
+				memcpy(&pMgmt->sBSSList[jj], &pMgmt->sBSSList[jj + 1], sizeof(KnownBSS));
 
- // printk("bubble sort result:\n");
+				memcpy(&pMgmt->sBSSList[jj + 1], ptempBSS, sizeof(KnownBSS));
 
-  //for (ii = 0; ii < MAX_BSS_NUM; ii++)
+			}
 
-  //    printk("%d [%s]:RSSI=%d\n",ii,((PWLAN_IE_SSID)(pMgmt->sBSSList[ii].abySSID))->abySSID,
+		}
 
-  //                                                                 pMgmt->sBSSList[ii].uRSSI);
+	}
 
- #endif
+	kfree(ptempBSS);
+#endif
 
 //******mike:bubble sort by stronger RSSI*****//
 
-
-
-
 	count = 0;
 	pBSS = &(pMgmt->sBSSList[0]);
-    for (ii = 0; ii < MAX_BSS_NUM; ii++) {
-        pBSS = &(pMgmt->sBSSList[ii]);
-        if (!pBSS->bActive)
-            continue;
-        count++;
-    }
-
-    pBuf = kcalloc(count, sizeof(struct viawget_scan_result), (int)GFP_ATOMIC);
-
-    if (pBuf == NULL) {
-        ret = -ENOMEM;
-        return ret;
-    }
-    scan_buf = (struct viawget_scan_result *)pBuf;
+	for (ii = 0; ii < MAX_BSS_NUM; ii++) {
+		pBSS = &(pMgmt->sBSSList[ii]);
+		if (!pBSS->bActive)
+			continue;
+		count++;
+	}
+
+	pBuf = kcalloc(count, sizeof(struct viawget_scan_result), (int)GFP_ATOMIC);
+
+	if (pBuf == NULL) {
+		ret = -ENOMEM;
+		return ret;
+	}
+	scan_buf = (struct viawget_scan_result *)pBuf;
 	pBSS = &(pMgmt->sBSSList[0]);
-    for (ii = 0, jj = 0; ii < MAX_BSS_NUM ; ii++) {
-        pBSS = &(pMgmt->sBSSList[ii]);
-        if (pBSS->bActive) {
-            if (jj >= count)
-                break;
-            memcpy(scan_buf->bssid, pBSS->abyBSSID, WLAN_BSSID_LEN);
-            pItemSSID = (PWLAN_IE_SSID)pBSS->abySSID;
-   		    memcpy(scan_buf->ssid, pItemSSID->abySSID, pItemSSID->len);
-   		    scan_buf->ssid_len = pItemSSID->len;
-            scan_buf->freq = frequency_list[pBSS->uChannel-1];
-	  scan_buf->caps = pBSS->wCapInfo;
-            //scan_buf->caps = pBSS->wCapInfo;
-            //scan_buf->qual =
-            //scan_buf->noise =
-            //scan_buf->level =
-            //scan_buf->maxrate =
-            if (pBSS->wWPALen != 0) {
-                scan_buf->wpa_ie_len = pBSS->wWPALen;
-                memcpy(scan_buf->wpa_ie, pBSS->byWPAIE, pBSS->wWPALen);
-            }
-            if (pBSS->wRSNLen != 0) {
-                scan_buf->rsn_ie_len = pBSS->wRSNLen;
-                memcpy(scan_buf->rsn_ie, pBSS->byRSNIE, pBSS->wRSNLen);
-            }
-            scan_buf = (struct viawget_scan_result *)((unsigned char *)scan_buf + sizeof(struct viawget_scan_result));
-            jj ++;
-        }
-    }
-
-    if (jj < count)
-        count = jj;
-
-    if (copy_to_user(param->u.scan_results.buf, pBuf, sizeof(struct viawget_scan_result) * count)) {
+	for (ii = 0, jj = 0; ii < MAX_BSS_NUM; ii++) {
+		pBSS = &(pMgmt->sBSSList[ii]);
+		if (pBSS->bActive) {
+			if (jj >= count)
+				break;
+			memcpy(scan_buf->bssid, pBSS->abyBSSID, WLAN_BSSID_LEN);
+			pItemSSID = (PWLAN_IE_SSID)pBSS->abySSID;
+			memcpy(scan_buf->ssid, pItemSSID->abySSID, pItemSSID->len);
+			scan_buf->ssid_len = pItemSSID->len;
+			scan_buf->freq = frequency_list[pBSS->uChannel-1];
+			scan_buf->caps = pBSS->wCapInfo;
+			//scan_buf->caps = pBSS->wCapInfo;
+			//scan_buf->qual =
+			//scan_buf->noise =
+			//scan_buf->level =
+			//scan_buf->maxrate =
+			if (pBSS->wWPALen != 0) {
+				scan_buf->wpa_ie_len = pBSS->wWPALen;
+				memcpy(scan_buf->wpa_ie, pBSS->byWPAIE, pBSS->wWPALen);
+			}
+			if (pBSS->wRSNLen != 0) {
+				scan_buf->rsn_ie_len = pBSS->wRSNLen;
+				memcpy(scan_buf->rsn_ie, pBSS->byRSNIE, pBSS->wRSNLen);
+			}
+			scan_buf = (struct viawget_scan_result *)((unsigned char *)scan_buf + sizeof(struct viawget_scan_result));
+			jj++;
+		}
+	}
+
+	if (jj < count)
+		count = jj;
+
+	if (copy_to_user(param->u.scan_results.buf, pBuf, sizeof(struct viawget_scan_result) * count)) {
 		ret = -EFAULT;
 	}
 	param->u.scan_results.scan_count = count;
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " param->u.scan_results.scan_count = %d\n", count)
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " param->u.scan_results.scan_count = %d\n", count)
 
-    kfree(pBuf);
-    return ret;
+		kfree(pBuf);
+	return ret;
 }
 
-
-
 /*
  * Description:
  *      set associate with AP
@@ -750,23 +700,22 @@ static int wpa_get_scan(PSDevice pDevice,
  */
 
 static int wpa_set_associate(PSDevice pDevice,
-				     struct viawget_wpa_param *param)
+			     struct viawget_wpa_param *param)
 {
-    PSMgmtObject    pMgmt = pDevice->pMgmt;
-    PWLAN_IE_SSID   pItemSSID;
-    unsigned char abyNullAddr[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-    unsigned char abyWPAIE[64];
-    int ret = 0;
-    bool bWepEnabled=false;
+	PSMgmtObject    pMgmt = pDevice->pMgmt;
+	PWLAN_IE_SSID   pItemSSID;
+	unsigned char abyNullAddr[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+	unsigned char abyWPAIE[64];
+	int ret = 0;
+	bool bWepEnabled = false;
 
 	// set key type & algorithm
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pairwise_suite = %d\n", param->u.wpa_associate.pairwise_suite);
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "group_suite = %d\n", param->u.wpa_associate.group_suite);
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "key_mgmt_suite = %d\n", param->u.wpa_associate.key_mgmt_suite);
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "auth_alg = %d\n", param->u.wpa_associate.auth_alg);
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "mode = %d\n", param->u.wpa_associate.mode);
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wpa_ie_len = %d\n", param->u.wpa_associate.wpa_ie_len);
-
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pairwise_suite = %d\n", param->u.wpa_associate.pairwise_suite);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "group_suite = %d\n", param->u.wpa_associate.group_suite);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "key_mgmt_suite = %d\n", param->u.wpa_associate.key_mgmt_suite);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "auth_alg = %d\n", param->u.wpa_associate.auth_alg);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "mode = %d\n", param->u.wpa_associate.mode);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wpa_ie_len = %d\n", param->u.wpa_associate.wpa_ie_len);
 
 	if (param->u.wpa_associate.wpa_ie_len) {
 		if (!param->u.wpa_associate.wpa_ie)
@@ -778,28 +727,27 @@ static int wpa_set_associate(PSDevice pDevice,
 	}
 
 	if (param->u.wpa_associate.mode == 1)
-	    pMgmt->eConfigMode = WMAC_CONFIG_IBSS_STA;
+		pMgmt->eConfigMode = WMAC_CONFIG_IBSS_STA;
 	else
-	    pMgmt->eConfigMode = WMAC_CONFIG_ESS_STA;
-    // set ssid
+		pMgmt->eConfigMode = WMAC_CONFIG_ESS_STA;
+	// set ssid
 	memset(pMgmt->abyDesireSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
-    pItemSSID = (PWLAN_IE_SSID)pMgmt->abyDesireSSID;
-    pItemSSID->byElementID = WLAN_EID_SSID;
+	pItemSSID = (PWLAN_IE_SSID)pMgmt->abyDesireSSID;
+	pItemSSID->byElementID = WLAN_EID_SSID;
 	pItemSSID->len = param->u.wpa_associate.ssid_len;
 	memcpy(pItemSSID->abySSID, param->u.wpa_associate.ssid, pItemSSID->len);
 	// set bssid
-    if (memcmp(param->u.wpa_associate.bssid, &abyNullAddr[0], 6) != 0)
-        memcpy(pMgmt->abyDesireBSSID, param->u.wpa_associate.bssid, 6);
-else
-{
-   bScheduleCommand((void *) pDevice, WLAN_CMD_BSSID_SCAN, pItemSSID->abySSID);
-}
+	if (memcmp(param->u.wpa_associate.bssid, &abyNullAddr[0], 6) != 0)
+		memcpy(pMgmt->abyDesireBSSID, param->u.wpa_associate.bssid, 6);
+	else {
+		bScheduleCommand((void *)pDevice, WLAN_CMD_BSSID_SCAN, pItemSSID->abySSID);
+	}
 
-    if (param->u.wpa_associate.wpa_ie_len == 0) {
-	    if (param->u.wpa_associate.auth_alg & AUTH_ALG_SHARED_KEY)
-            pMgmt->eAuthenMode = WMAC_AUTH_SHAREKEY;
-	    else
-            pMgmt->eAuthenMode = WMAC_AUTH_OPEN;
+	if (param->u.wpa_associate.wpa_ie_len == 0) {
+		if (param->u.wpa_associate.auth_alg & AUTH_ALG_SHARED_KEY)
+			pMgmt->eAuthenMode = WMAC_AUTH_SHAREKEY;
+		else
+			pMgmt->eAuthenMode = WMAC_AUTH_OPEN;
 	} else if (abyWPAIE[0] == RSN_INFO_ELEM) {
 		if (param->u.wpa_associate.key_mgmt_suite == KEY_MGMT_PSK)
 			pMgmt->eAuthenMode = WMAC_AUTH_WPA2PSK;
@@ -809,9 +757,9 @@ else
 		if (param->u.wpa_associate.key_mgmt_suite == KEY_MGMT_WPA_NONE)
 			pMgmt->eAuthenMode = WMAC_AUTH_WPANONE;
 		else if (param->u.wpa_associate.key_mgmt_suite == KEY_MGMT_PSK)
-		    pMgmt->eAuthenMode = WMAC_AUTH_WPAPSK;
+			pMgmt->eAuthenMode = WMAC_AUTH_WPAPSK;
 		else
-		    pMgmt->eAuthenMode = WMAC_AUTH_WPA;
+			pMgmt->eAuthenMode = WMAC_AUTH_WPA;
 	}
 
 	switch (param->u.wpa_associate.pairwise_suite) {
@@ -824,7 +772,7 @@ else
 	case CIPHER_WEP40:
 	case CIPHER_WEP104:
 		pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled;
-		bWepEnabled=true;
+		bWepEnabled = true;
 		break;
 	case CIPHER_NONE:
 		if (param->u.wpa_associate.group_suite == CIPHER_CCMP)
@@ -838,55 +786,53 @@ else
 
 //DavidWang add for WPA_supplicant support open/share mode
 
-      if (pMgmt->eAuthenMode == WMAC_AUTH_SHAREKEY) {
-            pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled;
-            //pMgmt->eAuthenMode = WMAC_AUTH_SHAREKEY;
-            pMgmt->bShareKeyAlgorithm = true;
-             }
-     else if (pMgmt->eAuthenMode == WMAC_AUTH_OPEN) {
-          if(!bWepEnabled)  pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled;
-	else pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled;
-            //pMgmt->eAuthenMode = WMAC_AUTH_OPEN;
-            //pMgmt->bShareKeyAlgorithm = false; //20080717-06,<Modify> by chester//Fix Open mode, WEP encryption
-           }
+	if (pMgmt->eAuthenMode == WMAC_AUTH_SHAREKEY) {
+		pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled;
+		//pMgmt->eAuthenMode = WMAC_AUTH_SHAREKEY;
+		pMgmt->bShareKeyAlgorithm = true;
+	} else if (pMgmt->eAuthenMode == WMAC_AUTH_OPEN) {
+		if (!bWepEnabled)  pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled;
+		else pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled;
+		//pMgmt->eAuthenMode = WMAC_AUTH_OPEN;
+		//pMgmt->bShareKeyAlgorithm = false; //20080717-06,<Modify> by chester//Fix Open mode, WEP encryption
+	}
 //mike save old encryption status
 	pDevice->eOldEncryptionStatus = pDevice->eEncryptionStatus;
 
-    if (pDevice->eEncryptionStatus !=  Ndis802_11EncryptionDisabled)
-        pDevice->bEncryptionEnable = true;
-    else
-        pDevice->bEncryptionEnable = false;
-if (!((pMgmt->eAuthenMode == WMAC_AUTH_SHAREKEY) ||
-      ((pMgmt->eAuthenMode == WMAC_AUTH_OPEN) && (bWepEnabled==true))) )  //DavidWang  //20080717-06,<Modify> by chester//Not to initial WEP
-    KeyvInitTable(&pDevice->sKey, pDevice->PortOffset);
-    spin_lock_irq(&pDevice->lock);
-    pDevice->bLinkPass = false;
-    memset(pMgmt->abyCurrBSSID, 0, 6);
-    pMgmt->eCurrState = WMAC_STATE_IDLE;
-    netif_stop_queue(pDevice->dev);
+	if (pDevice->eEncryptionStatus !=  Ndis802_11EncryptionDisabled)
+		pDevice->bEncryptionEnable = true;
+	else
+		pDevice->bEncryptionEnable = false;
+	if (!((pMgmt->eAuthenMode == WMAC_AUTH_SHAREKEY) ||
+	      ((pMgmt->eAuthenMode == WMAC_AUTH_OPEN) && (bWepEnabled == true))))  //DavidWang  //20080717-06,<Modify> by chester//Not to initial WEP
+		KeyvInitTable(&pDevice->sKey, pDevice->PortOffset);
+	spin_lock_irq(&pDevice->lock);
+	pDevice->bLinkPass = false;
+	memset(pMgmt->abyCurrBSSID, 0, 6);
+	pMgmt->eCurrState = WMAC_STATE_IDLE;
+	netif_stop_queue(pDevice->dev);
 	//20080701-02,<Add> by Mike Liu
 /*******search if ap_scan=2 ,which is associating request in hidden ssid mode ****/
-{
-   PKnownBSS       pCurr = NULL;
-    pCurr = BSSpSearchBSSList(pDevice,
-                              pMgmt->abyDesireBSSID,
-                              pMgmt->abyDesireSSID,
-                              pMgmt->eConfigPHYMode
-                              );
-
-    if (pCurr == NULL){
-    printk("wpa_set_associate---->hidden mode site survey before associate.......\n");
-    bScheduleCommand((void *) pDevice, WLAN_CMD_BSSID_SCAN, pMgmt->abyDesireSSID);
-  }
-}
+	{
+		PKnownBSS       pCurr = NULL;
+		pCurr = BSSpSearchBSSList(pDevice,
+					  pMgmt->abyDesireBSSID,
+					  pMgmt->abyDesireSSID,
+					  pMgmt->eConfigPHYMode
+);
+
+		if (pCurr == NULL) {
+			printk("wpa_set_associate---->hidden mode site survey before associate.......\n");
+			bScheduleCommand((void *)pDevice, WLAN_CMD_BSSID_SCAN, pMgmt->abyDesireSSID);
+		}
+	}
 /****************************************************************/
-    bScheduleCommand((void *) pDevice, WLAN_CMD_SSID, NULL);
-    spin_unlock_irq(&pDevice->lock);
+	bScheduleCommand((void *)pDevice, WLAN_CMD_SSID, NULL);
+	spin_unlock_irq(&pDevice->lock);
 
-    return ret;
+	return ret;
 }
 
-
 /*
  * Description:
  *      wpa_ioctl main function supported for wpa supplicant
@@ -922,61 +868,61 @@ int wpa_ioctl(PSDevice pDevice, struct iw_point *p)
 
 	switch (param->cmd) {
 	case VIAWGET_SET_WPA:
-        ret = wpa_set_wpa(pDevice, param);
-	    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_WPA \n");
+		ret = wpa_set_wpa(pDevice, param);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_WPA \n");
 		break;
 
 	case VIAWGET_SET_KEY:
-	    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_KEY \n");
-	    spin_lock_irq(&pDevice->lock);
-        ret = wpa_set_keys(pDevice, param, false);
-        spin_unlock_irq(&pDevice->lock);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_KEY \n");
+		spin_lock_irq(&pDevice->lock);
+		ret = wpa_set_keys(pDevice, param, false);
+		spin_unlock_irq(&pDevice->lock);
 		break;
 
 	case VIAWGET_SET_SCAN:
-	    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_SCAN \n");
-        ret = wpa_set_scan(pDevice, param);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_SCAN \n");
+		ret = wpa_set_scan(pDevice, param);
 		break;
 
 	case VIAWGET_GET_SCAN:
-	    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_GET_SCAN\n");
-        ret = wpa_get_scan(pDevice, param);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_GET_SCAN\n");
+		ret = wpa_get_scan(pDevice, param);
 		wpa_ioctl = 1;
 		break;
 
 	case VIAWGET_GET_SSID:
-	    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_GET_SSID \n");
-        ret = wpa_get_ssid(pDevice, param);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_GET_SSID \n");
+		ret = wpa_get_ssid(pDevice, param);
 		wpa_ioctl = 1;
 		break;
 
 	case VIAWGET_GET_BSSID:
-	    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_GET_BSSID \n");
-        ret = wpa_get_bssid(pDevice, param);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_GET_BSSID \n");
+		ret = wpa_get_bssid(pDevice, param);
 		wpa_ioctl = 1;
 		break;
 
 	case VIAWGET_SET_ASSOCIATE:
-	    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_ASSOCIATE \n");
-        ret = wpa_set_associate(pDevice, param);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_ASSOCIATE \n");
+		ret = wpa_set_associate(pDevice, param);
 		break;
 
 	case VIAWGET_SET_DISASSOCIATE:
-	    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_DISASSOCIATE \n");
-        ret = wpa_set_disassociate(pDevice, param);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_DISASSOCIATE \n");
+		ret = wpa_set_disassociate(pDevice, param);
 		break;
 
 	case VIAWGET_SET_DROP_UNENCRYPT:
-	    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_DROP_UNENCRYPT \n");
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_DROP_UNENCRYPT \n");
 		break;
 
-    case VIAWGET_SET_DEAUTHENTICATE:
-	    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_DEAUTHENTICATE \n");
+	case VIAWGET_SET_DEAUTHENTICATE:
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_DEAUTHENTICATE \n");
 		break;
 
 	default:
-	    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wpa_ioctl: unknown cmd=%d\n",
-		       param->cmd);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wpa_ioctl: unknown cmd=%d\n",
+			param->cmd);
 		return -EOPNOTSUPP;
 		break;
 	}
@@ -993,4 +939,3 @@ out:
 
 	return ret;
 }
-
diff --git a/drivers/staging/vt6655/wpactl.h b/drivers/staging/vt6655/wpactl.h
index dbe8e861..b9e2ab2 100644
--- a/drivers/staging/vt6655/wpactl.h
+++ b/drivers/staging/vt6655/wpactl.h
@@ -36,13 +36,12 @@
 
 /*---------------------  Export Definitions -------------------------*/
 
-
 //WPA related
 
 typedef enum { WPA_ALG_NONE, WPA_ALG_WEP, WPA_ALG_TKIP, WPA_ALG_CCMP } wpa_alg;
 typedef enum { CIPHER_NONE, CIPHER_WEP40, CIPHER_TKIP, CIPHER_CCMP,
 	       CIPHER_WEP104 } wpa_cipher;
-typedef enum { KEY_MGMT_802_1X, KEY_MGMT_CCKM,KEY_MGMT_PSK, KEY_MGMT_NONE,
+typedef enum { KEY_MGMT_802_1X, KEY_MGMT_CCKM, KEY_MGMT_PSK, KEY_MGMT_NONE,
 	       KEY_MGMT_802_1X_NO_WPA, KEY_MGMT_WPA_NONE } wpa_key_mgmt;
 
 #define AUTH_ALG_OPEN_SYSTEM	0x01
@@ -52,8 +51,6 @@ typedef enum { KEY_MGMT_802_1X, KEY_MGMT_CCKM,KEY_MGMT_PSK, KEY_MGMT_NONE,
 #define GENERIC_INFO_ELEM 0xdd
 #define RSN_INFO_ELEM 0x30
 
-
-
 typedef unsigned long long   NDIS_802_11_KEY_RSC;
 
 /*---------------------  Export Classes  ----------------------------*/
@@ -67,6 +64,3 @@ int wpa_ioctl(PSDevice pDevice, struct iw_point *p);
 int wpa_set_keys(PSDevice pDevice, void *ctx, bool fcpfkernel);
 
 #endif // __WPACL_H__
-
-
-
diff --git a/drivers/staging/vt6655/wroute.c b/drivers/staging/vt6655/wroute.c
index 82e93cb..b61328f 100644
--- a/drivers/staging/vt6655/wroute.c
+++ b/drivers/staging/vt6655/wroute.c
@@ -43,14 +43,12 @@
 /*---------------------  Static Classes  ----------------------------*/
 
 /*---------------------  Static Variables  --------------------------*/
-static int          msglevel                =MSG_LEVEL_INFO;
+static int msglevel = MSG_LEVEL_INFO;
 //static int          msglevel                =MSG_LEVEL_DEBUG;
 /*---------------------  Static Functions  --------------------------*/
 
 /*---------------------  Export Variables  --------------------------*/
 
-
-
 /*
  * Description:
  *      Relay packet.  Return true if packet is copy to DMA1
@@ -65,135 +63,128 @@ static int          msglevel                =MSG_LEVEL_INFO;
  * Return Value: true if packet duplicate; otherwise false
  *
  */
-bool ROUTEbRelay (PSDevice pDevice, unsigned char *pbySkbData, unsigned int uDataLen, unsigned int uNodeIndex)
+bool ROUTEbRelay(PSDevice pDevice, unsigned char *pbySkbData, unsigned int uDataLen, unsigned int uNodeIndex)
 {
-    PSMgmtObject    pMgmt = pDevice->pMgmt;
-    PSTxDesc        pHeadTD, pLastTD;
-    unsigned int cbFrameBodySize;
-    unsigned int uMACfragNum;
-    unsigned char byPktType;
-    bool bNeedEncryption = false;
-    SKeyItem        STempKey;
-    PSKeyItem       pTransmitKey = NULL;
-    unsigned int cbHeaderSize;
-    unsigned int ii;
-    unsigned char *pbyBSSID;
-
-
-
-
-    if (AVAIL_TD(pDevice, TYPE_AC0DMA)<=0) {
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Relay can't allocate TD1..\n");
-        return false;
-    }
-
-    pHeadTD = pDevice->apCurrTD[TYPE_AC0DMA];
-
-    pHeadTD->m_td1TD1.byTCR = (TCR_EDP|TCR_STP);
-
-    memcpy(pDevice->sTxEthHeader.abyDstAddr, (unsigned char *)pbySkbData, ETH_HLEN);
-
-    cbFrameBodySize = uDataLen - ETH_HLEN;
-
-    if (ntohs(pDevice->sTxEthHeader.wType) > ETH_DATA_LEN) {
-        cbFrameBodySize += 8;
-    }
-
-    if (pDevice->bEncryptionEnable == true) {
-        bNeedEncryption = true;
-
-        // get group key
-        pbyBSSID = pDevice->abyBroadcastAddr;
-        if(KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, GROUP_KEY, &pTransmitKey) == false) {
-            pTransmitKey = NULL;
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"KEY is NULL. [%d]\n", pDevice->pMgmt->eCurrMode);
-        } else {
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"Get GTK.\n");
-        }
-    }
-
-    if (pDevice->bEnableHostWEP) {
-	if (uNodeIndex < MAX_NODE_NUM + 1) {
-            pTransmitKey = &STempKey;
-            pTransmitKey->byCipherSuite = pMgmt->sNodeDBTable[uNodeIndex].byCipherSuite;
-            pTransmitKey->dwKeyIndex = pMgmt->sNodeDBTable[uNodeIndex].dwKeyIndex;
-            pTransmitKey->uKeyLength = pMgmt->sNodeDBTable[uNodeIndex].uWepKeyLength;
-            pTransmitKey->dwTSC47_16 = pMgmt->sNodeDBTable[uNodeIndex].dwTSC47_16;
-            pTransmitKey->wTSC15_0 = pMgmt->sNodeDBTable[uNodeIndex].wTSC15_0;
-            memcpy(pTransmitKey->abyKey,
-                &pMgmt->sNodeDBTable[uNodeIndex].abyWepKey[0],
-                pTransmitKey->uKeyLength
-                );
-        }
-    }
-
-    uMACfragNum = cbGetFragCount(pDevice, pTransmitKey, cbFrameBodySize, &pDevice->sTxEthHeader);
-
-    if (uMACfragNum > AVAIL_TD(pDevice,TYPE_AC0DMA)) {
-        return false;
-    }
-    byPktType = (unsigned char)pDevice->byPacketType;
-
-    if (pDevice->bFixRate) {
-        if (pDevice->eCurrentPHYType == PHY_TYPE_11B) {
-            if (pDevice->uConnectionRate >= RATE_11M) {
-                pDevice->wCurrentRate = RATE_11M;
-            } else {
-                pDevice->wCurrentRate = (unsigned short)pDevice->uConnectionRate;
-            }
-        } else {
-            if ((pDevice->eCurrentPHYType == PHY_TYPE_11A) &&
-                (pDevice->uConnectionRate <= RATE_6M)) {
-                pDevice->wCurrentRate = RATE_6M;
-            } else {
-                if (pDevice->uConnectionRate >= RATE_54M)
-                    pDevice->wCurrentRate = RATE_54M;
-                else
-                    pDevice->wCurrentRate = (unsigned short)pDevice->uConnectionRate;
-            }
-        }
-    }
-    else {
-        pDevice->wCurrentRate = pDevice->pMgmt->sNodeDBTable[uNodeIndex].wTxDataRate;
-    }
-
-    if (pDevice->wCurrentRate <= RATE_11M)
-        byPktType = PK_TYPE_11B;
-
-    vGenerateFIFOHeader(pDevice, byPktType, pDevice->pbyTmpBuff, bNeedEncryption,
-                        cbFrameBodySize, TYPE_AC0DMA, pHeadTD,
-                        &pDevice->sTxEthHeader, pbySkbData, pTransmitKey, uNodeIndex,
-                        &uMACfragNum,
-                        &cbHeaderSize
-                        );
-
-    if (MACbIsRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_PS)) {
-        // Disable PS
-        MACbPSWakeup(pDevice->PortOffset);
-    }
-
-    pDevice->bPWBitOn = false;
-
-    pLastTD = pHeadTD;
-    for (ii = 0; ii < uMACfragNum; ii++) {
-        // Poll Transmit the adapter
-        wmb();
-        pHeadTD->m_td0TD0.f1Owner=OWNED_BY_NIC;
-        wmb();
-        if (ii == (uMACfragNum - 1))
-            pLastTD = pHeadTD;
-        pHeadTD = pHeadTD->next;
-    }
-
-    pLastTD->pTDInfo->skb = 0;
-    pLastTD->pTDInfo->byFlags = 0;
-
-    pDevice->apCurrTD[TYPE_AC0DMA] = pHeadTD;
-
-    MACvTransmitAC0(pDevice->PortOffset);
-
-    return true;
+	PSMgmtObject    pMgmt = pDevice->pMgmt;
+	PSTxDesc        pHeadTD, pLastTD;
+	unsigned int cbFrameBodySize;
+	unsigned int uMACfragNum;
+	unsigned char byPktType;
+	bool bNeedEncryption = false;
+	SKeyItem        STempKey;
+	PSKeyItem       pTransmitKey = NULL;
+	unsigned int cbHeaderSize;
+	unsigned int ii;
+	unsigned char *pbyBSSID;
+
+	if (AVAIL_TD(pDevice, TYPE_AC0DMA) <= 0) {
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Relay can't allocate TD1..\n");
+		return false;
+	}
+
+	pHeadTD = pDevice->apCurrTD[TYPE_AC0DMA];
+
+	pHeadTD->m_td1TD1.byTCR = (TCR_EDP | TCR_STP);
+
+	memcpy(pDevice->sTxEthHeader.abyDstAddr, (unsigned char *)pbySkbData, ETH_HLEN);
+
+	cbFrameBodySize = uDataLen - ETH_HLEN;
+
+	if (ntohs(pDevice->sTxEthHeader.wType) > ETH_DATA_LEN) {
+		cbFrameBodySize += 8;
+	}
+
+	if (pDevice->bEncryptionEnable == true) {
+		bNeedEncryption = true;
+
+		// get group key
+		pbyBSSID = pDevice->abyBroadcastAddr;
+		if (KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, GROUP_KEY, &pTransmitKey) == false) {
+			pTransmitKey = NULL;
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG "KEY is NULL. [%d]\n", pDevice->pMgmt->eCurrMode);
+		} else {
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG "Get GTK.\n");
+		}
+	}
+
+	if (pDevice->bEnableHostWEP) {
+		if (uNodeIndex < MAX_NODE_NUM + 1) {
+			pTransmitKey = &STempKey;
+			pTransmitKey->byCipherSuite = pMgmt->sNodeDBTable[uNodeIndex].byCipherSuite;
+			pTransmitKey->dwKeyIndex = pMgmt->sNodeDBTable[uNodeIndex].dwKeyIndex;
+			pTransmitKey->uKeyLength = pMgmt->sNodeDBTable[uNodeIndex].uWepKeyLength;
+			pTransmitKey->dwTSC47_16 = pMgmt->sNodeDBTable[uNodeIndex].dwTSC47_16;
+			pTransmitKey->wTSC15_0 = pMgmt->sNodeDBTable[uNodeIndex].wTSC15_0;
+			memcpy(pTransmitKey->abyKey,
+			       &pMgmt->sNodeDBTable[uNodeIndex].abyWepKey[0],
+			       pTransmitKey->uKeyLength
+);
+		}
+	}
+
+	uMACfragNum = cbGetFragCount(pDevice, pTransmitKey, cbFrameBodySize, &pDevice->sTxEthHeader);
+
+	if (uMACfragNum > AVAIL_TD(pDevice, TYPE_AC0DMA)) {
+		return false;
+	}
+	byPktType = (unsigned char)pDevice->byPacketType;
+
+	if (pDevice->bFixRate) {
+		if (pDevice->eCurrentPHYType == PHY_TYPE_11B) {
+			if (pDevice->uConnectionRate >= RATE_11M) {
+				pDevice->wCurrentRate = RATE_11M;
+			} else {
+				pDevice->wCurrentRate = (unsigned short)pDevice->uConnectionRate;
+			}
+		} else {
+			if ((pDevice->eCurrentPHYType == PHY_TYPE_11A) &&
+			    (pDevice->uConnectionRate <= RATE_6M)) {
+				pDevice->wCurrentRate = RATE_6M;
+			} else {
+				if (pDevice->uConnectionRate >= RATE_54M)
+					pDevice->wCurrentRate = RATE_54M;
+				else
+					pDevice->wCurrentRate = (unsigned short)pDevice->uConnectionRate;
+			}
+		}
+	} else {
+		pDevice->wCurrentRate = pDevice->pMgmt->sNodeDBTable[uNodeIndex].wTxDataRate;
+	}
+
+	if (pDevice->wCurrentRate <= RATE_11M)
+		byPktType = PK_TYPE_11B;
+
+	vGenerateFIFOHeader(pDevice, byPktType, pDevice->pbyTmpBuff, bNeedEncryption,
+			    cbFrameBodySize, TYPE_AC0DMA, pHeadTD,
+			    &pDevice->sTxEthHeader, pbySkbData, pTransmitKey, uNodeIndex,
+			    &uMACfragNum,
+			    &cbHeaderSize
+);
+
+	if (MACbIsRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_PS)) {
+		// Disable PS
+		MACbPSWakeup(pDevice->PortOffset);
+	}
+
+	pDevice->bPWBitOn = false;
+
+	pLastTD = pHeadTD;
+	for (ii = 0; ii < uMACfragNum; ii++) {
+		// Poll Transmit the adapter
+		wmb();
+		pHeadTD->m_td0TD0.f1Owner = OWNED_BY_NIC;
+		wmb();
+		if (ii == (uMACfragNum - 1))
+			pLastTD = pHeadTD;
+		pHeadTD = pHeadTD->next;
+	}
+
+	pLastTD->pTDInfo->skb = 0;
+	pLastTD->pTDInfo->byFlags = 0;
+
+	pDevice->apCurrTD[TYPE_AC0DMA] = pHeadTD;
+
+	MACvTransmitAC0(pDevice->PortOffset);
+
+	return true;
 }
-
-
-
diff --git a/drivers/staging/vt6655/wroute.h b/drivers/staging/vt6655/wroute.h
index 34f9e43..5ecc190 100644
--- a/drivers/staging/vt6655/wroute.h
+++ b/drivers/staging/vt6655/wroute.h
@@ -39,9 +39,6 @@
 
 /*---------------------  Export Functions  --------------------------*/
 
-bool ROUTEbRelay (PSDevice pDevice, unsigned char *pbySkbData, unsigned int uDataLen, unsigned int uNodeIndex);
+bool ROUTEbRelay(PSDevice pDevice, unsigned char *pbySkbData, unsigned int uDataLen, unsigned int uNodeIndex);
 
 #endif // __WROUTE_H__
-
-
-
diff --git a/drivers/staging/vt6656/80211hdr.h b/drivers/staging/vt6656/80211hdr.h
index b87d543..000304f 100644
--- a/drivers/staging/vt6656/80211hdr.h
+++ b/drivers/staging/vt6656/80211hdr.h
@@ -28,10 +28,6 @@
 #ifndef __80211HDR_H__
 #define __80211HDR_H__
 
-#include "ttype.h"
-
-/*---------------------  Export Definitions -------------------------*/
-
 /* bit type */
 #define BIT0	0x00000001
 #define BIT1	0x00000002
@@ -155,22 +151,22 @@
 #ifdef __BIG_ENDIAN
 
 /* GET & SET Frame Control bit */
-#define WLAN_GET_FC_PRVER(n)    ((((WORD)(n) >> 8) & (BIT0 | BIT1))
-#define WLAN_GET_FC_FTYPE(n)    ((((WORD)(n) >> 8) & (BIT2 | BIT3)) >> 2)
-#define WLAN_GET_FC_FSTYPE(n)   ((((WORD)(n) >> 8) \
+#define WLAN_GET_FC_PRVER(n)    ((((u16)(n) >> 8) & (BIT0 | BIT1))
+#define WLAN_GET_FC_FTYPE(n)    ((((u16)(n) >> 8) & (BIT2 | BIT3)) >> 2)
+#define WLAN_GET_FC_FSTYPE(n)   ((((u16)(n) >> 8) \
 				  & (BIT4|BIT5|BIT6|BIT7)) >> 4)
-#define WLAN_GET_FC_TODS(n)     ((((WORD)(n) << 8) & (BIT8)) >> 8)
-#define WLAN_GET_FC_FROMDS(n)   ((((WORD)(n) << 8) & (BIT9)) >> 9)
-#define WLAN_GET_FC_MOREFRAG(n) ((((WORD)(n) << 8) & (BIT10)) >> 10)
-#define WLAN_GET_FC_RETRY(n)    ((((WORD)(n) << 8) & (BIT11)) >> 11)
-#define WLAN_GET_FC_PWRMGT(n)   ((((WORD)(n) << 8) & (BIT12)) >> 12)
-#define WLAN_GET_FC_MOREDATA(n) ((((WORD)(n) << 8) & (BIT13)) >> 13)
-#define WLAN_GET_FC_ISWEP(n)    ((((WORD)(n) << 8) & (BIT14)) >> 14)
-#define WLAN_GET_FC_ORDER(n)    ((((WORD)(n) << 8) & (BIT15)) >> 15)
+#define WLAN_GET_FC_TODS(n)     ((((u16)(n) << 8) & (BIT8)) >> 8)
+#define WLAN_GET_FC_FROMDS(n)   ((((u16)(n) << 8) & (BIT9)) >> 9)
+#define WLAN_GET_FC_MOREFRAG(n) ((((u16)(n) << 8) & (BIT10)) >> 10)
+#define WLAN_GET_FC_RETRY(n)    ((((u16)(n) << 8) & (BIT11)) >> 11)
+#define WLAN_GET_FC_PWRMGT(n)   ((((u16)(n) << 8) & (BIT12)) >> 12)
+#define WLAN_GET_FC_MOREDATA(n) ((((u16)(n) << 8) & (BIT13)) >> 13)
+#define WLAN_GET_FC_ISWEP(n)    ((((u16)(n) << 8) & (BIT14)) >> 14)
+#define WLAN_GET_FC_ORDER(n)    ((((u16)(n) << 8) & (BIT15)) >> 15)
 
 /* Sequence Field bit */
-#define WLAN_GET_SEQ_FRGNUM(n) (((WORD)(n) >> 8) & (BIT0|BIT1|BIT2|BIT3))
-#define WLAN_GET_SEQ_SEQNUM(n) ((((WORD)(n) >> 8) \
+#define WLAN_GET_SEQ_FRGNUM(n) (((u16)(n) >> 8) & (BIT0|BIT1|BIT2|BIT3))
+#define WLAN_GET_SEQ_SEQNUM(n) ((((u16)(n) >> 8) \
 				 & (~(BIT0|BIT1|BIT2|BIT3))) >> 4)
 
 /* Capability Field bit */
@@ -190,21 +186,21 @@
 #else
 
 /* GET & SET Frame Control bit */
-#define WLAN_GET_FC_PRVER(n)    (((WORD)(n)) & (BIT0 | BIT1))
-#define WLAN_GET_FC_FTYPE(n)    ((((WORD)(n)) & (BIT2 | BIT3)) >> 2)
-#define WLAN_GET_FC_FSTYPE(n)   ((((WORD)(n)) & (BIT4|BIT5|BIT6|BIT7)) >> 4)
-#define WLAN_GET_FC_TODS(n)     ((((WORD)(n)) & (BIT8)) >> 8)
-#define WLAN_GET_FC_FROMDS(n)   ((((WORD)(n)) & (BIT9)) >> 9)
-#define WLAN_GET_FC_MOREFRAG(n) ((((WORD)(n)) & (BIT10)) >> 10)
-#define WLAN_GET_FC_RETRY(n)    ((((WORD)(n)) & (BIT11)) >> 11)
-#define WLAN_GET_FC_PWRMGT(n)   ((((WORD)(n)) & (BIT12)) >> 12)
-#define WLAN_GET_FC_MOREDATA(n) ((((WORD)(n)) & (BIT13)) >> 13)
-#define WLAN_GET_FC_ISWEP(n)    ((((WORD)(n)) & (BIT14)) >> 14)
-#define WLAN_GET_FC_ORDER(n)    ((((WORD)(n)) & (BIT15)) >> 15)
+#define WLAN_GET_FC_PRVER(n)    (((u16)(n)) & (BIT0 | BIT1))
+#define WLAN_GET_FC_FTYPE(n)    ((((u16)(n)) & (BIT2 | BIT3)) >> 2)
+#define WLAN_GET_FC_FSTYPE(n)   ((((u16)(n)) & (BIT4|BIT5|BIT6|BIT7)) >> 4)
+#define WLAN_GET_FC_TODS(n)     ((((u16)(n)) & (BIT8)) >> 8)
+#define WLAN_GET_FC_FROMDS(n)   ((((u16)(n)) & (BIT9)) >> 9)
+#define WLAN_GET_FC_MOREFRAG(n) ((((u16)(n)) & (BIT10)) >> 10)
+#define WLAN_GET_FC_RETRY(n)    ((((u16)(n)) & (BIT11)) >> 11)
+#define WLAN_GET_FC_PWRMGT(n)   ((((u16)(n)) & (BIT12)) >> 12)
+#define WLAN_GET_FC_MOREDATA(n) ((((u16)(n)) & (BIT13)) >> 13)
+#define WLAN_GET_FC_ISWEP(n)    ((((u16)(n)) & (BIT14)) >> 14)
+#define WLAN_GET_FC_ORDER(n)    ((((u16)(n)) & (BIT15)) >> 15)
 
 /* Sequence Field bit */
-#define WLAN_GET_SEQ_FRGNUM(n) (((WORD)(n)) & (BIT0|BIT1|BIT2|BIT3))
-#define WLAN_GET_SEQ_SEQNUM(n) ((((WORD)(n)) & (~(BIT0|BIT1|BIT2|BIT3))) >> 4)
+#define WLAN_GET_SEQ_FRGNUM(n) (((u16)(n)) & (BIT0|BIT1|BIT2|BIT3))
+#define WLAN_GET_SEQ_SEQNUM(n) ((((u16)(n)) & (~(BIT0|BIT1|BIT2|BIT3))) >> 4)
 
 /* Capability Field bit */
 #define WLAN_GET_CAP_INFO_ESS(n)           ((n) & BIT0)
@@ -235,20 +231,20 @@
 #define WLAN_SET_CAP_INFO_DSSSOFDM(n)      ((n) << 13)
 #define WLAN_SET_CAP_INFO_GRPACK(n)        ((n) << 14)
 
-#define WLAN_SET_FC_PRVER(n)    ((WORD)(n))
-#define WLAN_SET_FC_FTYPE(n)    (((WORD)(n)) << 2)
-#define WLAN_SET_FC_FSTYPE(n)   (((WORD)(n)) << 4)
-#define WLAN_SET_FC_TODS(n)     (((WORD)(n)) << 8)
-#define WLAN_SET_FC_FROMDS(n)   (((WORD)(n)) << 9)
-#define WLAN_SET_FC_MOREFRAG(n) (((WORD)(n)) << 10)
-#define WLAN_SET_FC_RETRY(n)    (((WORD)(n)) << 11)
-#define WLAN_SET_FC_PWRMGT(n)   (((WORD)(n)) << 12)
-#define WLAN_SET_FC_MOREDATA(n) (((WORD)(n)) << 13)
-#define WLAN_SET_FC_ISWEP(n)    (((WORD)(n)) << 14)
-#define WLAN_SET_FC_ORDER(n)    (((WORD)(n)) << 15)
-
-#define WLAN_SET_SEQ_FRGNUM(n) ((WORD)(n))
-#define WLAN_SET_SEQ_SEQNUM(n) (((WORD)(n)) << 4)
+#define WLAN_SET_FC_PRVER(n)    ((u16)(n))
+#define WLAN_SET_FC_FTYPE(n)    (((u16)(n)) << 2)
+#define WLAN_SET_FC_FSTYPE(n)   (((u16)(n)) << 4)
+#define WLAN_SET_FC_TODS(n)     (((u16)(n)) << 8)
+#define WLAN_SET_FC_FROMDS(n)   (((u16)(n)) << 9)
+#define WLAN_SET_FC_MOREFRAG(n) (((u16)(n)) << 10)
+#define WLAN_SET_FC_RETRY(n)    (((u16)(n)) << 11)
+#define WLAN_SET_FC_PWRMGT(n)   (((u16)(n)) << 12)
+#define WLAN_SET_FC_MOREDATA(n) (((u16)(n)) << 13)
+#define WLAN_SET_FC_ISWEP(n)    (((u16)(n)) << 14)
+#define WLAN_SET_FC_ORDER(n)    (((u16)(n)) << 15)
+
+#define WLAN_SET_SEQ_FRGNUM(n) ((u16)(n))
+#define WLAN_SET_SEQ_SEQNUM(n) (((u16)(n)) << 4)
 
 /* ERP Field bit */
 
@@ -269,50 +265,50 @@
 #define WLAN_MGMT_GET_TIM_OFFSET(b)     (((b) & ~BIT0) >> 1)
 
 /* 3-Addr & 4-Addr */
-#define WLAN_HDR_A3_DATA_PTR(p) (((PBYTE)(p)) + WLAN_HDR_ADDR3_LEN)
-#define WLAN_HDR_A4_DATA_PTR(p) (((PBYTE)(p)) + WLAN_HDR_ADDR4_LEN)
+#define WLAN_HDR_A3_DATA_PTR(p) (((u8 *)(p)) + WLAN_HDR_ADDR3_LEN)
+#define WLAN_HDR_A4_DATA_PTR(p) (((u8 *)(p)) + WLAN_HDR_ADDR4_LEN)
 
 /* IEEE ADDR */
 #define IEEE_ADDR_UNIVERSAL         0x02
 #define IEEE_ADDR_GROUP             0x01
 
 typedef struct {
-    BYTE            abyAddr[6];
+    u8            abyAddr[6];
 } IEEE_ADDR, *PIEEE_ADDR;
 
 /* 802.11 Header Format */
 
 typedef struct tagWLAN_80211HDR_A2 {
 
-    WORD    wFrameCtl;
-    WORD    wDurationID;
-    BYTE    abyAddr1[WLAN_ADDR_LEN];
-    BYTE    abyAddr2[WLAN_ADDR_LEN];
+    u16    wFrameCtl;
+    u16    wDurationID;
+    u8    abyAddr1[WLAN_ADDR_LEN];
+    u8    abyAddr2[WLAN_ADDR_LEN];
 
 } __attribute__ ((__packed__))
 WLAN_80211HDR_A2, *PWLAN_80211HDR_A2;
 
 typedef struct tagWLAN_80211HDR_A3 {
 
-    WORD    wFrameCtl;
-    WORD    wDurationID;
-    BYTE    abyAddr1[WLAN_ADDR_LEN];
-    BYTE    abyAddr2[WLAN_ADDR_LEN];
-    BYTE    abyAddr3[WLAN_ADDR_LEN];
-    WORD    wSeqCtl;
+    u16    wFrameCtl;
+    u16    wDurationID;
+    u8    abyAddr1[WLAN_ADDR_LEN];
+    u8    abyAddr2[WLAN_ADDR_LEN];
+    u8    abyAddr3[WLAN_ADDR_LEN];
+    u16    wSeqCtl;
 
 } __attribute__ ((__packed__))
 WLAN_80211HDR_A3, *PWLAN_80211HDR_A3;
 
 typedef struct tagWLAN_80211HDR_A4 {
 
-    WORD    wFrameCtl;
-    WORD    wDurationID;
-    BYTE    abyAddr1[WLAN_ADDR_LEN];
-    BYTE    abyAddr2[WLAN_ADDR_LEN];
-    BYTE    abyAddr3[WLAN_ADDR_LEN];
-    WORD    wSeqCtl;
-    BYTE    abyAddr4[WLAN_ADDR_LEN];
+    u16    wFrameCtl;
+    u16    wDurationID;
+    u8    abyAddr1[WLAN_ADDR_LEN];
+    u8    abyAddr2[WLAN_ADDR_LEN];
+    u8    abyAddr3[WLAN_ADDR_LEN];
+    u16    wSeqCtl;
+    u8    abyAddr4[WLAN_ADDR_LEN];
 
 } __attribute__ ((__packed__))
 WLAN_80211HDR_A4, *PWLAN_80211HDR_A4;
@@ -325,10 +321,4 @@ typedef union tagUWLAN_80211HDR {
 
 } UWLAN_80211HDR, *PUWLAN_80211HDR;
 
-/*---------------------  Export Classes  ----------------------------*/
-
-/*---------------------  Export Variables  --------------------------*/
-
-/*---------------------  Export Functions  --------------------------*/
-
 #endif /* __80211HDR_H__ */
diff --git a/drivers/staging/vt6656/80211mgr.c b/drivers/staging/vt6656/80211mgr.c
index 534d490..61edb51 100644
--- a/drivers/staging/vt6656/80211mgr.c
+++ b/drivers/staging/vt6656/80211mgr.c
@@ -27,8 +27,6 @@
  * Functions:
  *      vMgrEncodeBeacon - Encode the Beacon frame
  *      vMgrDecodeBeacon - Decode the Beacon frame
- *      vMgrEncodeIBSSATIM - Encode the IBSS ATIM frame
- *      vMgrDecodeIBSSATIM - Decode the IBSS ATIM frame
  *      vMgrEncodeDisassociation - Encode the Disassociation frame
  *      vMgrDecodeDisassociation - Decode the Disassociation frame
  *      vMgrEncodeAssocRequest - Encode the Association request frame
@@ -46,7 +44,6 @@
  *      vMgrEncodeDeauthen - Encode the DeAuthentication frame
  *      vMgrDecodeDeauthen - Decode the DeAuthentication frame
  *      vMgrEncodeReassocResponse - Encode the Reassociation response frame
- *      vMgrDecodeReassocResponse - Decode the Reassociation response frame
  *
  * Revision History:
  *
@@ -59,25 +56,8 @@
 #include "80211hdr.h"
 #include "wpa.h"
 
-/*---------------------  Static Definitions -------------------------*/
-
-
-
-/*---------------------  Static Classes  ----------------------------*/
-
-/*---------------------  Static Variables  --------------------------*/
-
 static int          msglevel                = MSG_LEVEL_INFO;
 /*static int          msglevel                =MSG_LEVEL_DEBUG;*/
-/*---------------------  Static Functions  --------------------------*/
-
-
-
-/*---------------------  Export Variables  --------------------------*/
-
-
-/*---------------------  Export Functions  --------------------------*/
-
 
 /*+
  *
@@ -100,9 +80,9 @@ vMgrEncodeBeacon(
 	pFrame->pqwTimestamp =
 		(u64 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) +
 			WLAN_BEACON_OFF_TS);
-    pFrame->pwBeaconInterval = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+    pFrame->pwBeaconInterval = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
                                        + WLAN_BEACON_OFF_BCN_INT);
-    pFrame->pwCapInfo = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+    pFrame->pwCapInfo = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
                                 + WLAN_BEACON_OFF_CAPINFO);
 
     pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_BEACON_OFF_SSID;
@@ -121,7 +101,6 @@ vMgrEncodeBeacon(
  *
 -*/
 
-
 void
 vMgrDecodeBeacon(
       PWLAN_FR_BEACON  pFrame
@@ -135,15 +114,15 @@ vMgrDecodeBeacon(
 	pFrame->pqwTimestamp =
 		(u64 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) +
 			WLAN_BEACON_OFF_TS);
-    pFrame->pwBeaconInterval = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+    pFrame->pwBeaconInterval = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
                                        + WLAN_BEACON_OFF_BCN_INT);
-    pFrame->pwCapInfo = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+    pFrame->pwCapInfo = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
                                 + WLAN_BEACON_OFF_CAPINFO);
 
     /* Information elements */
-    pItem = (PWLAN_IE)((PBYTE)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)))
+    pItem = (PWLAN_IE)((u8 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)))
                        + WLAN_BEACON_OFF_SSID);
-    while (((PBYTE)pItem) < (pFrame->pBuf + pFrame->len)) {
+    while (((u8 *)pItem) < (pFrame->pBuf + pFrame->len)) {
 
         switch (pItem->byElementID) {
         case WLAN_EID_SSID:
@@ -224,53 +203,10 @@ vMgrDecodeBeacon(
                 break;
 
         }
-        pItem = (PWLAN_IE)(((PBYTE)pItem) + 2 + pItem->len);
+        pItem = (PWLAN_IE)(((u8 *)pItem) + 2 + pItem->len);
     }
 }
 
-
-/*+
- *
- * Routine Description:
- *  Encode IBSS ATIM
- *
- *
- * Return Value:
- *    None.
- *
--*/
-
-
-void
-vMgrEncodeIBSSATIM(
-      PWLAN_FR_IBSSATIM   pFrame
-    )
-{
-    pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
-    pFrame->len = WLAN_HDR_ADDR3_LEN;
-}
-
-
-/*+
- *
- * Routine Description:
- *  Decode IBSS ATIM
- *
- *
- * Return Value:
- *    None.
- *
--*/
-
-void
-vMgrDecodeIBSSATIM(
-      PWLAN_FR_IBSSATIM   pFrame
-    )
-{
-    pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
-}
-
-
 /*+
  *
  * Routine Description:
@@ -289,14 +225,12 @@ vMgrEncodeDisassociation(
 {
     pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
 
-
     /* Fixed Fields */
-    pFrame->pwReason = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+    pFrame->pwReason = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
                                + WLAN_DISASSOC_OFF_REASON);
     pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_DISASSOC_OFF_REASON + sizeof(*(pFrame->pwReason));
 }
 
-
 /*+
  *
  * Routine Description:
@@ -316,7 +250,7 @@ vMgrDecodeDisassociation(
     pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
 
     /* Fixed Fields */
-    pFrame->pwReason = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+    pFrame->pwReason = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
                                + WLAN_DISASSOC_OFF_REASON);
 }
 
@@ -331,7 +265,6 @@ vMgrDecodeDisassociation(
  *
 -*/
 
-
 void
 vMgrEncodeAssocRequest(
       PWLAN_FR_ASSOCREQ  pFrame
@@ -339,14 +272,13 @@ vMgrEncodeAssocRequest(
 {
     pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
     /* Fixed Fields */
-    pFrame->pwCapInfo = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+    pFrame->pwCapInfo = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
                                 + WLAN_ASSOCREQ_OFF_CAP_INFO);
-    pFrame->pwListenInterval = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+    pFrame->pwListenInterval = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
                                        + WLAN_ASSOCREQ_OFF_LISTEN_INT);
     pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_ASSOCREQ_OFF_LISTEN_INT + sizeof(*(pFrame->pwListenInterval));
 }
 
-
 /*+
  *
  * Routine Description: (AP)
@@ -367,16 +299,16 @@ vMgrDecodeAssocRequest(
 
     pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
     /* Fixed Fields */
-    pFrame->pwCapInfo = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+    pFrame->pwCapInfo = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
                                 + WLAN_ASSOCREQ_OFF_CAP_INFO);
-    pFrame->pwListenInterval = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+    pFrame->pwListenInterval = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
                                 + WLAN_ASSOCREQ_OFF_LISTEN_INT);
 
     /* Information elements */
     pItem = (PWLAN_IE)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
                             + WLAN_ASSOCREQ_OFF_SSID);
 
-    while (((PBYTE)pItem) < (pFrame->pBuf + pFrame->len)) {
+    while (((u8 *)pItem) < (pFrame->pBuf + pFrame->len)) {
         switch (pItem->byElementID) {
         case WLAN_EID_SSID:
             if (pFrame->pSSID == NULL)
@@ -407,7 +339,7 @@ vMgrDecodeAssocRequest(
                     pItem->byElementID);
             break;
         }
-        pItem = (PWLAN_IE)(((PBYTE)pItem) + 2 + pItem->len);
+        pItem = (PWLAN_IE)(((u8 *)pItem) + 2 + pItem->len);
     }
 }
 
@@ -430,17 +362,16 @@ vMgrEncodeAssocResponse(
     pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
 
     /* Fixed Fields */
-    pFrame->pwCapInfo = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+    pFrame->pwCapInfo = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
                                 + WLAN_ASSOCRESP_OFF_CAP_INFO);
-    pFrame->pwStatus = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+    pFrame->pwStatus = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
                                + WLAN_ASSOCRESP_OFF_STATUS);
-    pFrame->pwAid = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+    pFrame->pwAid = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
                             + WLAN_ASSOCRESP_OFF_AID);
     pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_ASSOCRESP_OFF_AID
                   + sizeof(*(pFrame->pwAid));
 }
 
-
 /*+
  *
  * Routine Description:
@@ -462,11 +393,11 @@ vMgrDecodeAssocResponse(
     pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
 
     /* Fixed Fields */
-    pFrame->pwCapInfo = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+    pFrame->pwCapInfo = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
                                 + WLAN_ASSOCRESP_OFF_CAP_INFO);
-    pFrame->pwStatus = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+    pFrame->pwStatus = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
                                + WLAN_ASSOCRESP_OFF_STATUS);
-    pFrame->pwAid = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+    pFrame->pwAid = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
                             + WLAN_ASSOCRESP_OFF_AID);
 
     /* Information elements */
@@ -474,16 +405,15 @@ vMgrDecodeAssocResponse(
                            + WLAN_ASSOCRESP_OFF_SUPP_RATES);
 
     pItem = (PWLAN_IE)(pFrame->pSuppRates);
-    pItem = (PWLAN_IE)(((PBYTE)pItem) + 2 + pItem->len);
+    pItem = (PWLAN_IE)(((u8 *)pItem) + 2 + pItem->len);
 
-    if ((((PBYTE)pItem) < (pFrame->pBuf + pFrame->len)) && (pItem->byElementID == WLAN_EID_EXTSUPP_RATES)) {
+    if ((((u8 *)pItem) < (pFrame->pBuf + pFrame->len)) && (pItem->byElementID == WLAN_EID_EXTSUPP_RATES)) {
         pFrame->pExtSuppRates = (PWLAN_IE_SUPP_RATES)pItem;
         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pFrame->pExtSuppRates=[%p].\n", pItem);
 	} else
         pFrame->pExtSuppRates = NULL;
 }
 
-
 /*+
  *
  * Routine Description:
@@ -503,16 +433,15 @@ vMgrEncodeReassocRequest(
     pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
 
     /* Fixed Fields */
-    pFrame->pwCapInfo = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+    pFrame->pwCapInfo = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
                                 + WLAN_REASSOCREQ_OFF_CAP_INFO);
-    pFrame->pwListenInterval = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+    pFrame->pwListenInterval = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
                                       + WLAN_REASSOCREQ_OFF_LISTEN_INT);
     pFrame->pAddrCurrAP = (PIEEE_ADDR)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
                                        + WLAN_REASSOCREQ_OFF_CURR_AP);
     pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_REASSOCREQ_OFF_CURR_AP + sizeof(*(pFrame->pAddrCurrAP));
 }
 
-
 /*+
  *
  * Routine Description: (AP)
@@ -524,7 +453,6 @@ vMgrEncodeReassocRequest(
  *
 -*/
 
-
 void
 vMgrDecodeReassocRequest(
       PWLAN_FR_REASSOCREQ  pFrame
@@ -534,9 +462,9 @@ vMgrDecodeReassocRequest(
     pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
 
     /* Fixed Fields */
-    pFrame->pwCapInfo = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+    pFrame->pwCapInfo = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
                                 + WLAN_REASSOCREQ_OFF_CAP_INFO);
-    pFrame->pwListenInterval = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+    pFrame->pwListenInterval = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
                                       + WLAN_REASSOCREQ_OFF_LISTEN_INT);
     pFrame->pAddrCurrAP = (PIEEE_ADDR)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
                                        + WLAN_REASSOCREQ_OFF_CURR_AP);
@@ -545,7 +473,7 @@ vMgrDecodeReassocRequest(
     pItem = (PWLAN_IE)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
                        + WLAN_REASSOCREQ_OFF_SSID);
 
-    while (((PBYTE)pItem) < (pFrame->pBuf + pFrame->len)) {
+    while (((u8 *)pItem) < (pFrame->pBuf + pFrame->len)) {
 
         switch (pItem->byElementID) {
         case WLAN_EID_SSID:
@@ -576,12 +504,10 @@ vMgrDecodeReassocRequest(
                         pItem->byElementID);
             break;
         }
-        pItem = (PWLAN_IE)(((PBYTE)pItem) + 2 + pItem->len);
+        pItem = (PWLAN_IE)(((u8 *)pItem) + 2 + pItem->len);
     }
 }
 
-
-
 /*+
  *
  * Routine Description:
@@ -593,7 +519,6 @@ vMgrDecodeReassocRequest(
  *
 -*/
 
-
 void
 vMgrEncodeProbeRequest(
      PWLAN_FR_PROBEREQ  pFrame
@@ -626,7 +551,7 @@ vMgrDecodeProbeRequest(
     /* Information elements */
     pItem = (PWLAN_IE)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)));
 
-    while (((PBYTE)pItem) < (pFrame->pBuf + pFrame->len)) {
+    while (((u8 *)pItem) < (pFrame->pBuf + pFrame->len)) {
 
         switch (pItem->byElementID) {
         case WLAN_EID_SSID:
@@ -649,11 +574,10 @@ vMgrDecodeProbeRequest(
             break;
         }
 
-        pItem = (PWLAN_IE)(((PBYTE)pItem) + 2 +  pItem->len);
+        pItem = (PWLAN_IE)(((u8 *)pItem) + 2 +  pItem->len);
     }
 }
 
-
 /*+
  *
  * Routine Description:
@@ -665,7 +589,6 @@ vMgrDecodeProbeRequest(
  *
 -*/
 
-
 void
 vMgrEncodeProbeResponse(
      PWLAN_FR_PROBERESP  pFrame
@@ -677,17 +600,15 @@ vMgrEncodeProbeResponse(
 	pFrame->pqwTimestamp =
 		(u64 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) +
 			WLAN_PROBERESP_OFF_TS);
-    pFrame->pwBeaconInterval = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+    pFrame->pwBeaconInterval = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
                                        + WLAN_PROBERESP_OFF_BCN_INT);
-    pFrame->pwCapInfo = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+    pFrame->pwCapInfo = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
                                 + WLAN_PROBERESP_OFF_CAP_INFO);
 
     pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_PROBERESP_OFF_CAP_INFO +
                   sizeof(*(pFrame->pwCapInfo));
 }
 
-
-
 /*+
  *
  * Routine Description:
@@ -706,23 +627,22 @@ vMgrDecodeProbeResponse(
 {
     PWLAN_IE    pItem;
 
-
     pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
 
 	/* Fixed Fields */
 	pFrame->pqwTimestamp =
 		(u64 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) +
 			WLAN_PROBERESP_OFF_TS);
-    pFrame->pwBeaconInterval = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+    pFrame->pwBeaconInterval = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
                                        + WLAN_PROBERESP_OFF_BCN_INT);
-    pFrame->pwCapInfo = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+    pFrame->pwCapInfo = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
                                 + WLAN_PROBERESP_OFF_CAP_INFO);
 
     /* Information elements */
     pItem = (PWLAN_IE)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
                        + WLAN_PROBERESP_OFF_SSID);
 
-    while (((PBYTE)pItem) < (pFrame->pBuf + pFrame->len)) {
+    while (((u8 *)pItem) < (pFrame->pBuf + pFrame->len)) {
         switch (pItem->byElementID) {
         case WLAN_EID_SSID:
             if (pFrame->pSSID == NULL)
@@ -796,11 +716,10 @@ vMgrDecodeProbeResponse(
             break;
         }
 
-        pItem = (PWLAN_IE)(((PBYTE)pItem) + 2 +  pItem->len);
+        pItem = (PWLAN_IE)(((u8 *)pItem) + 2 +  pItem->len);
     }
 }
 
-
 /*+
  *
  * Routine Description:
@@ -820,16 +739,15 @@ vMgrEncodeAuthen(
     pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
 
     /* Fixed Fields */
-    pFrame->pwAuthAlgorithm = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+    pFrame->pwAuthAlgorithm = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
                                       + WLAN_AUTHEN_OFF_AUTH_ALG);
-    pFrame->pwAuthSequence = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+    pFrame->pwAuthSequence = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
                                      + WLAN_AUTHEN_OFF_AUTH_SEQ);
-    pFrame->pwStatus = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+    pFrame->pwStatus = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
                                + WLAN_AUTHEN_OFF_STATUS);
     pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_AUTHEN_OFF_STATUS + sizeof(*(pFrame->pwStatus));
 }
 
-
 /*+
  *
  * Routine Description:
@@ -851,22 +769,21 @@ vMgrDecodeAuthen(
     pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
 
     /* Fixed Fields */
-    pFrame->pwAuthAlgorithm = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+    pFrame->pwAuthAlgorithm = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
                                       + WLAN_AUTHEN_OFF_AUTH_ALG);
-    pFrame->pwAuthSequence = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+    pFrame->pwAuthSequence = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
                                      + WLAN_AUTHEN_OFF_AUTH_SEQ);
-    pFrame->pwStatus = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+    pFrame->pwStatus = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
                                + WLAN_AUTHEN_OFF_STATUS);
 
     /* Information elements */
     pItem = (PWLAN_IE)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
                        + WLAN_AUTHEN_OFF_CHALLENGE);
 
-    if ((((PBYTE)pItem) < (pFrame->pBuf + pFrame->len)) && (pItem->byElementID == WLAN_EID_CHALLENGE))
+    if ((((u8 *)pItem) < (pFrame->pBuf + pFrame->len)) && (pItem->byElementID == WLAN_EID_CHALLENGE))
         pFrame->pChallenge = (PWLAN_IE_CHALLENGE)pItem;
 }
 
-
 /*+
  *
  * Routine Description:
@@ -886,12 +803,11 @@ vMgrEncodeDeauthen(
     pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
 
     /* Fixed Fields */
-    pFrame->pwReason = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+    pFrame->pwReason = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
                                + WLAN_DEAUTHEN_OFF_REASON);
     pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_DEAUTHEN_OFF_REASON + sizeof(*(pFrame->pwReason));
 }
 
-
 /*+
  *
  * Routine Description:
@@ -911,11 +827,10 @@ vMgrDecodeDeauthen(
     pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
 
     /* Fixed Fields */
-    pFrame->pwReason = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+    pFrame->pwReason = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
                                + WLAN_DEAUTHEN_OFF_REASON);
 }
 
-
 /*+
  *
  * Routine Description: (AP)
@@ -935,53 +850,12 @@ vMgrEncodeReassocResponse(
     pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
 
     /* Fixed Fields */
-    pFrame->pwCapInfo = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+    pFrame->pwCapInfo = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
                                 + WLAN_REASSOCRESP_OFF_CAP_INFO);
-    pFrame->pwStatus = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+    pFrame->pwStatus = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
                                + WLAN_REASSOCRESP_OFF_STATUS);
-    pFrame->pwAid = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
+    pFrame->pwAid = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
                             + WLAN_REASSOCRESP_OFF_AID);
 
     pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_REASSOCRESP_OFF_AID + sizeof(*(pFrame->pwAid));
 }
-
-
-/*+
- *
- * Routine Description:
- *   Decode Reassociation Response
- *
- *
- * Return Value:
- *    None.
- *
--*/
-
-
-void
-vMgrDecodeReassocResponse(
-      PWLAN_FR_REASSOCRESP  pFrame
-     )
-{
-    PWLAN_IE   pItem;
-
-    pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf;
-
-    /* Fixed Fields */
-    pFrame->pwCapInfo = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
-                                + WLAN_REASSOCRESP_OFF_CAP_INFO);
-    pFrame->pwStatus = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
-                               + WLAN_REASSOCRESP_OFF_STATUS);
-    pFrame->pwAid = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
-                            + WLAN_REASSOCRESP_OFF_AID);
-
-    /* Information elements */
-    pFrame->pSuppRates = (PWLAN_IE_SUPP_RATES)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
-                                               + WLAN_REASSOCRESP_OFF_SUPP_RATES);
-
-    pItem = (PWLAN_IE)(pFrame->pSuppRates);
-    pItem = (PWLAN_IE)(((PBYTE)pItem) + 2 + pItem->len);
-
-    if ((((PBYTE)pItem) < (pFrame->pBuf + pFrame->len)) && (pItem->byElementID == WLAN_EID_EXTSUPP_RATES))
-        pFrame->pExtSuppRates = (PWLAN_IE_SUPP_RATES)pItem;
-}
diff --git a/drivers/staging/vt6656/80211mgr.h b/drivers/staging/vt6656/80211mgr.h
index f8e16d8..39cde1a 100644
--- a/drivers/staging/vt6656/80211mgr.h
+++ b/drivers/staging/vt6656/80211mgr.h
@@ -31,11 +31,8 @@
 #ifndef __80211MGR_H__
 #define __80211MGR_H__
 
-#include "ttype.h"
 #include "80211hdr.h"
 
-/*---------------------  Export Definitions -------------------------*/
-
 #define WLAN_MIN_ARRAY          1
 
 /* Information Element ID value */
@@ -213,192 +210,186 @@
 #define MEASURE_MODE_INCAPABLE  0x02
 #define MEASURE_MODE_REFUSED    0x04
 
-/*---------------------  Export Classes  ----------------------------*/
-
-/*---------------------  Export Variables  --------------------------*/
-
-/*---------------------  Export Types  ------------------------------*/
-
 /* Information Element types */
 
 #pragma pack(1)
 typedef struct tagWLAN_IE {
-    BYTE   byElementID;
-    BYTE   len;
+    u8   byElementID;
+    u8   len;
 } __attribute__ ((__packed__))
 WLAN_IE, *PWLAN_IE;
 
 /* Service Set IDentity (SSID) */
 #pragma pack(1)
 typedef struct tagWLAN_IE_SSID {
-    BYTE   byElementID;
-    BYTE   len;
-    BYTE   abySSID[1];
+    u8   byElementID;
+    u8   len;
+    u8   abySSID[1];
 } __attribute__ ((__packed__))
 WLAN_IE_SSID, *PWLAN_IE_SSID;
 
 /* Supported Rates */
 #pragma pack(1)
 typedef struct tagWLAN_IE_SUPP_RATES {
-    BYTE   byElementID;
-    BYTE   len;
-    BYTE   abyRates[1];
+    u8   byElementID;
+    u8   len;
+    u8   abyRates[1];
 } __attribute__ ((__packed__))
 WLAN_IE_SUPP_RATES,  *PWLAN_IE_SUPP_RATES;
 
 /* FH Parameter Set */
 #pragma pack(1)
 typedef struct _WLAN_IE_FH_PARMS {
-    BYTE    byElementID;
-    BYTE    len;
-    WORD    wDwellTime;
-    BYTE    byHopSet;
-    BYTE    byHopPattern;
-    BYTE    byHopIndex;
+    u8    byElementID;
+    u8    len;
+    u16    wDwellTime;
+    u8    byHopSet;
+    u8    byHopPattern;
+    u8    byHopIndex;
 } WLAN_IE_FH_PARMS,  *PWLAN_IE_FH_PARMS;
 
 /* DS Parameter Set */
 #pragma pack(1)
 typedef struct tagWLAN_IE_DS_PARMS {
-    BYTE   byElementID;
-    BYTE   len;
-    BYTE   byCurrChannel;
+    u8   byElementID;
+    u8   len;
+    u8   byCurrChannel;
 } __attribute__ ((__packed__))
 WLAN_IE_DS_PARMS,  *PWLAN_IE_DS_PARMS;
 
 /* CF Parameter Set */
 #pragma pack(1)
 typedef struct tagWLAN_IE_CF_PARMS {
-    BYTE   byElementID;
-    BYTE   len;
-    BYTE   byCFPCount;
-    BYTE   byCFPPeriod;
-    WORD   wCFPMaxDuration;
-    WORD   wCFPDurRemaining;
+    u8   byElementID;
+    u8   len;
+    u8   byCFPCount;
+    u8   byCFPPeriod;
+    u16   wCFPMaxDuration;
+    u16   wCFPDurRemaining;
 } __attribute__ ((__packed__))
 WLAN_IE_CF_PARMS,  *PWLAN_IE_CF_PARMS;
 
 /* TIM */
 #pragma pack(1)
 typedef struct tagWLAN_IE_TIM {
-    BYTE   byElementID;
-    BYTE   len;
-    BYTE   byDTIMCount;
-    BYTE   byDTIMPeriod;
-    BYTE   byBitMapCtl;
-    BYTE   byVirtBitMap[1];
+    u8   byElementID;
+    u8   len;
+    u8   byDTIMCount;
+    u8   byDTIMPeriod;
+    u8   byBitMapCtl;
+    u8   byVirtBitMap[1];
 } __attribute__ ((__packed__))
 WLAN_IE_TIM,  *PWLAN_IE_TIM;
 
 /* IBSS Parameter Set */
 #pragma pack(1)
 typedef struct tagWLAN_IE_IBSS_PARMS {
-    BYTE   byElementID;
-    BYTE   len;
-    WORD   wATIMWindow;
+    u8   byElementID;
+    u8   len;
+    u16   wATIMWindow;
 } __attribute__ ((__packed__))
 WLAN_IE_IBSS_PARMS, *PWLAN_IE_IBSS_PARMS;
 
 /* Challenge Text */
 #pragma pack(1)
 typedef struct tagWLAN_IE_CHALLENGE {
-    BYTE   byElementID;
-    BYTE   len;
-    BYTE   abyChallenge[1];
+    u8   byElementID;
+    u8   len;
+    u8   abyChallenge[1];
 } __attribute__ ((__packed__))
 WLAN_IE_CHALLENGE,  *PWLAN_IE_CHALLENGE;
 
 #pragma pack(1)
 typedef struct tagWLAN_IE_RSN_EXT {
-    BYTE byElementID;
-    BYTE len;
-    BYTE abyOUI[4];
-    WORD wVersion;
-    BYTE abyMulticast[4];
-    WORD wPKCount;
+    u8 byElementID;
+    u8 len;
+    u8 abyOUI[4];
+    u16 wVersion;
+    u8 abyMulticast[4];
+    u16 wPKCount;
 	struct {
-		BYTE abyOUI[4];
+		u8 abyOUI[4];
 	} PKSList[1];
 	/* the rest is variable so need to overlay ieauth structure */
 } WLAN_IE_RSN_EXT, *PWLAN_IE_RSN_EXT;
 
 #pragma pack(1)
 typedef struct tagWLAN_IE_RSN_AUTH {
-    WORD wAuthCount;
+    u16 wAuthCount;
     struct {
-        BYTE abyOUI[4];
+        u8 abyOUI[4];
     } AuthKSList[1];
 } WLAN_IE_RSN_AUTH, *PWLAN_IE_RSN_AUTH;
 
 /* RSN Identity */
 #pragma pack(1)
 typedef struct tagWLAN_IE_RSN {
-    BYTE   byElementID;
-    BYTE   len;
-    WORD   wVersion;
-    BYTE   abyRSN[WLAN_MIN_ARRAY];
+    u8   byElementID;
+    u8   len;
+    u16   wVersion;
+    u8   abyRSN[WLAN_MIN_ARRAY];
 } WLAN_IE_RSN, *PWLAN_IE_RSN;
 
 /* CCX Identity DavidWang */
 #pragma pack(1)
 typedef struct tagWLAN_IE_CCX {
-BYTE   byElementID;
-BYTE   len;
-BYTE   abyCCX[30];
+u8   byElementID;
+u8   len;
+u8   abyCCX[30];
 } WLAN_IE_CCX, *PWLAN_IE_CCX;
 #pragma pack(1)
 typedef struct tagWLAN_IE_CCX_IP {
-BYTE   byElementID;
-BYTE   len;
-BYTE   abyCCXOUI[4];
-BYTE   abyCCXIP[4];
-BYTE   abyCCXREV[2];
+u8   byElementID;
+u8   len;
+u8   abyCCXOUI[4];
+u8   abyCCXIP[4];
+u8   abyCCXREV[2];
 } WLAN_IE_CCX_IP, *PWLAN_IE_CCX_IP;
 #pragma pack(1)
 typedef struct tagWLAN_IE_CCX_Ver {
-BYTE   byElementID;
-BYTE   len;
-BYTE   abyCCXVer[5];
+u8   byElementID;
+u8   len;
+u8   abyCCXVer[5];
 } WLAN_IE_CCX_Ver, *PWLAN_IE_CCX_Ver;
 
 /* ERP */
 #pragma pack(1)
 typedef struct tagWLAN_IE_ERP {
-    BYTE   byElementID;
-    BYTE   len;
-    BYTE   byContext;
+    u8   byElementID;
+    u8   len;
+    u8   byContext;
 } __attribute__ ((__packed__))
 WLAN_IE_ERP,  *PWLAN_IE_ERP;
 
 #pragma pack(1)
 typedef struct _MEASEURE_REQ {
-    BYTE                byChannel;
-    BYTE                abyStartTime[8];
-    BYTE                abyDuration[2];
+    u8                byChannel;
+    u8                abyStartTime[8];
+    u8                abyDuration[2];
 } MEASEURE_REQ, *PMEASEURE_REQ,
   MEASEURE_REQ_BASIC, *PMEASEURE_REQ_BASIC,
   MEASEURE_REQ_CCA, *PMEASEURE_REQ_CCA,
   MEASEURE_REQ_RPI, *PMEASEURE_REQ_RPI;
 
 typedef struct _MEASEURE_REP_BASIC {
-    BYTE                byChannel;
-    BYTE                abyStartTime[8];
-    BYTE                abyDuration[2];
-    BYTE                byMap;
+    u8                byChannel;
+    u8                abyStartTime[8];
+    u8                abyDuration[2];
+    u8                byMap;
 } MEASEURE_REP_BASIC, *PMEASEURE_REP_BASIC;
 
 typedef struct _MEASEURE_REP_CCA {
-    BYTE                byChannel;
-    BYTE                abyStartTime[8];
-    BYTE                abyDuration[2];
-    BYTE                byCCABusyFraction;
+    u8                byChannel;
+    u8                abyStartTime[8];
+    u8                abyDuration[2];
+    u8                byCCABusyFraction;
 } MEASEURE_REP_CCA, *PMEASEURE_REP_CCA;
 
 typedef struct _MEASEURE_REP_RPI {
-    BYTE                byChannel;
-    BYTE                abyStartTime[8];
-    BYTE                abyDuration[2];
-    BYTE                abyRPIdensity[8];
+    u8                byChannel;
+    u8                abyStartTime[8];
+    u8                abyDuration[2];
+    u8                abyRPIdensity[8];
 } MEASEURE_REP_RPI, *PMEASEURE_REP_RPI;
 
 typedef union _MEASEURE_REP {
@@ -410,85 +401,84 @@ typedef union _MEASEURE_REP {
 } MEASEURE_REP, *PMEASEURE_REP;
 
 typedef struct _WLAN_IE_MEASURE_REQ {
-    BYTE                byElementID;
-    BYTE                len;
-    BYTE                byToken;
-    BYTE                byMode;
-    BYTE                byType;
+    u8                byElementID;
+    u8                len;
+    u8                byToken;
+    u8                byMode;
+    u8                byType;
     MEASEURE_REQ        sReq;
 } WLAN_IE_MEASURE_REQ, *PWLAN_IE_MEASURE_REQ;
 
 typedef struct _WLAN_IE_MEASURE_REP {
-    BYTE                byElementID;
-    BYTE                len;
-    BYTE                byToken;
-    BYTE                byMode;
-    BYTE                byType;
+    u8                byElementID;
+    u8                len;
+    u8                byToken;
+    u8                byMode;
+    u8                byType;
     MEASEURE_REP        sRep;
 } WLAN_IE_MEASURE_REP, *PWLAN_IE_MEASURE_REP;
 
 typedef struct _WLAN_IE_CH_SW {
-    BYTE                byElementID;
-    BYTE                len;
-    BYTE                byMode;
-    BYTE                byChannel;
-    BYTE                byCount;
+    u8                byElementID;
+    u8                len;
+    u8                byMode;
+    u8                byChannel;
+    u8                byCount;
 } WLAN_IE_CH_SW, *PWLAN_IE_CH_SW;
 
 typedef struct _WLAN_IE_QUIET {
-    BYTE                byElementID;
-    BYTE                len;
-    BYTE                byQuietCount;
-    BYTE                byQuietPeriod;
-    BYTE                abyQuietDuration[2];
-    BYTE                abyQuietOffset[2];
+    u8                byElementID;
+    u8                len;
+    u8                byQuietCount;
+    u8                byQuietPeriod;
+    u8                abyQuietDuration[2];
+    u8                abyQuietOffset[2];
 } WLAN_IE_QUIET, *PWLAN_IE_QUIET;
 
 typedef struct _WLAN_IE_COUNTRY {
-    BYTE                byElementID;
-    BYTE                len;
-    BYTE                abyCountryString[3];
-    BYTE                abyCountryInfo[3];
+    u8                byElementID;
+    u8                len;
+    u8                abyCountryString[3];
+    u8                abyCountryInfo[3];
 } WLAN_IE_COUNTRY, *PWLAN_IE_COUNTRY;
 
 typedef struct _WLAN_IE_PW_CONST {
-    BYTE                byElementID;
-    BYTE                len;
-    BYTE                byPower;
+    u8                byElementID;
+    u8                len;
+    u8                byPower;
 } WLAN_IE_PW_CONST, *PWLAN_IE_PW_CONST;
 
 typedef struct _WLAN_IE_PW_CAP {
-    BYTE                byElementID;
-    BYTE                len;
-    BYTE                byMinPower;
-    BYTE                byMaxPower;
+    u8                byElementID;
+    u8                len;
+    u8                byMinPower;
+    u8                byMaxPower;
 } WLAN_IE_PW_CAP, *PWLAN_IE_PW_CAP;
 
 typedef struct _WLAN_IE_SUPP_CH {
-    BYTE                byElementID;
-    BYTE                len;
-    BYTE                abyChannelTuple[2];
+    u8                byElementID;
+    u8                len;
+    u8                abyChannelTuple[2];
 } WLAN_IE_SUPP_CH, *PWLAN_IE_SUPP_CH;
 
 typedef struct _WLAN_IE_TPC_REQ {
-    BYTE                byElementID;
-    BYTE                len;
+    u8                byElementID;
+    u8                len;
 } WLAN_IE_TPC_REQ, *PWLAN_IE_TPC_REQ;
 
 typedef struct _WLAN_IE_TPC_REP {
-    BYTE                byElementID;
-    BYTE                len;
-    BYTE                byTxPower;
-    BYTE                byLinkMargin;
+    u8                byElementID;
+    u8                len;
+    u8                byTxPower;
+    u8                byLinkMargin;
 } WLAN_IE_TPC_REP, *PWLAN_IE_TPC_REP;
 
-
 typedef struct _WLAN_IE_IBSS_DFS {
-    BYTE                byElementID;
-    BYTE                len;
-    BYTE                abyDFSOwner[6];
-    BYTE                byDFSRecovery;
-    BYTE                abyChannelMap[2];
+    u8                byElementID;
+    u8                len;
+    u8                abyDFSOwner[6];
+    u8                byDFSRecovery;
+    u8                abyChannelMap[2];
 } WLAN_IE_IBSS_DFS, *PWLAN_IE_IBSS_DFS;
 
 #pragma pack()
@@ -500,7 +490,7 @@ typedef struct tagWLAN_FR_MGMT {
 
     unsigned int                  uType;
     unsigned int                  len;
-    PBYTE                 pBuf;
+    u8 *                 pBuf;
     PUWLAN_80211HDR       pHdr;
 
 } WLAN_FR_MGMT,  *PWLAN_FR_MGMT;
@@ -510,12 +500,12 @@ typedef struct tagWLAN_FR_BEACON {
 
     unsigned int                    uType;
     unsigned int                    len;
-    PBYTE                   pBuf;
+    u8 *                   pBuf;
     PUWLAN_80211HDR         pHdr;
 	/* fixed fields */
 	u64 *pqwTimestamp;
-    PWORD                   pwBeaconInterval;
-    PWORD                   pwCapInfo;
+    u16 *                   pwBeaconInterval;
+    u16 *                   pwCapInfo;
     /* info elements */
     PWLAN_IE_SSID           pSSID;
     PWLAN_IE_SUPP_RATES     pSuppRates;
@@ -541,7 +531,7 @@ typedef struct tagWLAN_FR_IBSSATIM {
 
     unsigned int                    uType;
     unsigned int                    len;
-    PBYTE                   pBuf;
+    u8 *                   pBuf;
     PUWLAN_80211HDR         pHdr;
 
 	/* fixed fields */
@@ -555,10 +545,10 @@ typedef struct tagWLAN_FR_DISASSOC {
 
     unsigned int                    uType;
     unsigned int                    len;
-    PBYTE                   pBuf;
+    u8 *                   pBuf;
     PUWLAN_80211HDR         pHdr;
     /* fixed fields */
-    PWORD                   pwReason;
+    u16 *                   pwReason;
     /* info elements */
 
 } WLAN_FR_DISASSOC, *PWLAN_FR_DISASSOC;
@@ -568,11 +558,11 @@ typedef struct tagWLAN_FR_ASSOCREQ {
 
     unsigned int                    uType;
     unsigned int                    len;
-    PBYTE                   pBuf;
+    u8 *                   pBuf;
     PUWLAN_80211HDR         pHdr;
     /* fixed fields */
-    PWORD                   pwCapInfo;
-    PWORD                   pwListenInterval;
+    u16 *                   pwCapInfo;
+    u16 *                   pwListenInterval;
     /* info elements */
     PWLAN_IE_SSID           pSSID;
     PWLAN_IE_SUPP_RATES     pSuppRates;
@@ -592,12 +582,12 @@ typedef struct tagWLAN_FR_ASSOCRESP {
 
     unsigned int                    uType;
     unsigned int                    len;
-    PBYTE                   pBuf;
+    u8 *                   pBuf;
     PUWLAN_80211HDR         pHdr;
     /* fixed fields */
-    PWORD                   pwCapInfo;
-    PWORD                   pwStatus;
-    PWORD                   pwAid;
+    u16 *                   pwCapInfo;
+    u16 *                   pwStatus;
+    u16 *                   pwAid;
     /* info elements */
     PWLAN_IE_SUPP_RATES     pSuppRates;
     PWLAN_IE_SUPP_RATES     pExtSuppRates;
@@ -609,12 +599,12 @@ typedef struct tagWLAN_FR_REASSOCREQ {
 
     unsigned int                    uType;
     unsigned int                    len;
-    PBYTE                   pBuf;
+    u8 *                   pBuf;
     PUWLAN_80211HDR         pHdr;
 
     /* fixed fields */
-    PWORD                   pwCapInfo;
-    PWORD                   pwListenInterval;
+    u16 *                   pwCapInfo;
+    u16 *                   pwListenInterval;
     PIEEE_ADDR              pAddrCurrAP;
 
     /* info elements */
@@ -634,12 +624,12 @@ typedef struct tagWLAN_FR_REASSOCRESP {
 
     unsigned int                    uType;
     unsigned int                    len;
-    PBYTE                   pBuf;
+    u8 *                   pBuf;
     PUWLAN_80211HDR         pHdr;
     /* fixed fields */
-    PWORD                   pwCapInfo;
-    PWORD                   pwStatus;
-    PWORD                   pwAid;
+    u16 *                   pwCapInfo;
+    u16 *                   pwStatus;
+    u16 *                   pwAid;
     /* info elements */
     PWLAN_IE_SUPP_RATES     pSuppRates;
     PWLAN_IE_SUPP_RATES     pExtSuppRates;
@@ -651,7 +641,7 @@ typedef struct tagWLAN_FR_PROBEREQ {
 
     unsigned int                    uType;
     unsigned int                    len;
-    PBYTE                   pBuf;
+    u8 *                   pBuf;
     PUWLAN_80211HDR         pHdr;
     /* fixed fields */
     /* info elements */
@@ -666,12 +656,12 @@ typedef struct tagWLAN_FR_PROBERESP {
 
     unsigned int                    uType;
     unsigned int                    len;
-    PBYTE                   pBuf;
+    u8 *                   pBuf;
     PUWLAN_80211HDR         pHdr;
     /* fixed fields */
 	u64 *pqwTimestamp;
-    PWORD                   pwBeaconInterval;
-    PWORD                   pwCapInfo;
+    u16 *                   pwBeaconInterval;
+    u16 *                   pwCapInfo;
     /* info elements */
     PWLAN_IE_SSID           pSSID;
     PWLAN_IE_SUPP_RATES     pSuppRates;
@@ -695,12 +685,12 @@ typedef struct tagWLAN_FR_AUTHEN {
 
     unsigned int                    uType;
     unsigned int                    len;
-    PBYTE                   pBuf;
+    u8 *                   pBuf;
     PUWLAN_80211HDR         pHdr;
     /* fixed fields */
-    PWORD                   pwAuthAlgorithm;
-    PWORD                   pwAuthSequence;
-    PWORD                   pwStatus;
+    u16 *                   pwAuthAlgorithm;
+    u16 *                   pwAuthSequence;
+    u16 *                   pwStatus;
     /* info elements */
     PWLAN_IE_CHALLENGE      pChallenge;
 
@@ -711,17 +701,15 @@ typedef struct tagWLAN_FR_DEAUTHEN {
 
     unsigned int                    uType;
     unsigned int                    len;
-    PBYTE                   pBuf;
+    u8 *                   pBuf;
     PUWLAN_80211HDR         pHdr;
     /* fixed fields */
-    PWORD                   pwReason;
+    u16 *                   pwReason;
 
     /* info elements */
 
 } WLAN_FR_DEAUTHEN, *PWLAN_FR_DEAUTHEN;
 
-/*---------------------  Export Functions  --------------------------*/
-
 void
 vMgrEncodeBeacon(
       PWLAN_FR_BEACON  pFrame
@@ -733,16 +721,6 @@ vMgrDecodeBeacon(
     );
 
 void
-vMgrEncodeIBSSATIM(
-      PWLAN_FR_IBSSATIM   pFrame
-    );
-
-void
-vMgrDecodeIBSSATIM(
-      PWLAN_FR_IBSSATIM   pFrame
-    );
-
-void
 vMgrEncodeDisassociation(
       PWLAN_FR_DISASSOC  pFrame
     );
@@ -827,9 +805,4 @@ vMgrEncodeReassocResponse(
       PWLAN_FR_REASSOCRESP  pFrame
     );
 
-void
-vMgrDecodeReassocResponse(
-      PWLAN_FR_REASSOCRESP  pFrame
-    );
-
 #endif /* __80211MGR_H__ */
diff --git a/drivers/staging/vt6656/TODO b/drivers/staging/vt6656/TODO
index a318995..e154b2f 100644
--- a/drivers/staging/vt6656/TODO
+++ b/drivers/staging/vt6656/TODO
@@ -7,7 +7,7 @@ TODO:
   - split rf.c
   - abstract VT3184 chipset specific code
 - add common vt665x infrastructure
-- kill ttype.h
+- kill ttype.h -- done
 - switch to use LIB80211
 - switch to use MAC80211
 - use kernel coding style
diff --git a/drivers/staging/vt6656/aes_ccmp.c b/drivers/staging/vt6656/aes_ccmp.c
index fb6124d..28a4c4c 100644
--- a/drivers/staging/vt6656/aes_ccmp.c
+++ b/drivers/staging/vt6656/aes_ccmp.c
@@ -33,17 +33,11 @@
 #include "device.h"
 #include "80211hdr.h"
 
-/*---------------------  Static Definitions -------------------------*/
-
-/*---------------------  Static Classes  ----------------------------*/
-
-/*---------------------  Static Variables  --------------------------*/
-
 /*
  * SBOX Table
  */
 
-BYTE sbox_table[256] = {
+u8 sbox_table[256] = {
 	0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
 	0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
 	0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
@@ -62,7 +56,7 @@ BYTE sbox_table[256] = {
 	0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
 };
 
-BYTE dot2_table[256] = {
+u8 dot2_table[256] = {
 	0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
 	0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e,
 	0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e,
@@ -81,7 +75,7 @@ BYTE dot2_table[256] = {
 	0xfb, 0xf9, 0xff, 0xfd, 0xf3, 0xf1, 0xf7, 0xf5, 0xeb, 0xe9, 0xef, 0xed, 0xe3, 0xe1, 0xe7, 0xe5
 };
 
-BYTE dot3_table[256] = {
+u8 dot3_table[256] = {
 	0x00, 0x03, 0x06, 0x05, 0x0c, 0x0f, 0x0a, 0x09, 0x18, 0x1b, 0x1e, 0x1d, 0x14, 0x17, 0x12, 0x11,
 	0x30, 0x33, 0x36, 0x35, 0x3c, 0x3f, 0x3a, 0x39, 0x28, 0x2b, 0x2e, 0x2d, 0x24, 0x27, 0x22, 0x21,
 	0x60, 0x63, 0x66, 0x65, 0x6c, 0x6f, 0x6a, 0x69, 0x78, 0x7b, 0x7e, 0x7d, 0x74, 0x77, 0x72, 0x71,
@@ -100,17 +94,11 @@ BYTE dot3_table[256] = {
 	0x0b, 0x08, 0x0d, 0x0e, 0x07, 0x04, 0x01, 0x02, 0x13, 0x10, 0x15, 0x16, 0x1f, 0x1c, 0x19, 0x1a
 };
 
-/*---------------------  Static Functions  --------------------------*/
-
-/*---------------------  Export Variables  --------------------------*/
-
-/*---------------------  Export Functions  --------------------------*/
-
-static void xor_128(BYTE *a, BYTE *b, BYTE *out)
+static void xor_128(u8 *a, u8 *b, u8 *out)
 {
-	PDWORD dwPtrA = (PDWORD) a;
-	PDWORD dwPtrB = (PDWORD) b;
-	PDWORD dwPtrOut = (PDWORD) out;
+	u32 * dwPtrA = (u32 *) a;
+	u32 * dwPtrB = (u32 *) b;
+	u32 * dwPtrOut = (u32 *) out;
 
 	(*dwPtrOut++) = (*dwPtrA++) ^ (*dwPtrB++);
 	(*dwPtrOut++) = (*dwPtrA++) ^ (*dwPtrB++);
@@ -118,20 +106,19 @@ static void xor_128(BYTE *a, BYTE *b, BYTE *out)
 	(*dwPtrOut++) = (*dwPtrA++) ^ (*dwPtrB++);
 }
 
-
-static void xor_32(BYTE *a, BYTE *b, BYTE *out)
+static void xor_32(u8 *a, u8 *b, u8 *out)
 {
-	PDWORD dwPtrA = (PDWORD) a;
-	PDWORD dwPtrB = (PDWORD) b;
-	PDWORD dwPtrOut = (PDWORD) out;
+	u32 * dwPtrA = (u32 *) a;
+	u32 * dwPtrB = (u32 *) b;
+	u32 * dwPtrOut = (u32 *) out;
 
 	(*dwPtrOut++) = (*dwPtrA++) ^ (*dwPtrB++);
 }
 
-void AddRoundKey(BYTE *key, int round)
+void AddRoundKey(u8 *key, int round)
 {
-	BYTE sbox_key[4];
-	BYTE rcon_table[10] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36};
+	u8 sbox_key[4];
+	u8 rcon_table[10] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36};
 
 	sbox_key[0] = sbox_table[key[13]];
 	sbox_key[1] = sbox_table[key[14]];
@@ -146,7 +133,7 @@ void AddRoundKey(BYTE *key, int round)
 	xor_32(&key[12], &key[8], &key[12]);
 }
 
-void SubBytes(BYTE *in, BYTE *out)
+void SubBytes(u8 *in, u8 *out)
 {
 	int i;
 
@@ -154,7 +141,7 @@ void SubBytes(BYTE *in, BYTE *out)
 		out[i] = sbox_table[in[i]];
 }
 
-void ShiftRows(BYTE *in, BYTE *out)
+void ShiftRows(u8 *in, u8 *out)
 {
 	out[0]  = in[0];
 	out[1]  = in[5];
@@ -174,7 +161,7 @@ void ShiftRows(BYTE *in, BYTE *out)
 	out[15] = in[11];
 }
 
-void MixColumns(BYTE *in, BYTE *out)
+void MixColumns(u8 *in, u8 *out)
 {
 
 	out[0] = dot2_table[in[0]] ^ dot3_table[in[1]] ^ in[2] ^ in[3];
@@ -183,13 +170,13 @@ void MixColumns(BYTE *in, BYTE *out)
 	out[3] = dot3_table[in[0]] ^ in[1] ^ in[2] ^ dot2_table[in[3]];
 }
 
-void AESv128(BYTE *key, BYTE *data, BYTE *ciphertext)
+void AESv128(u8 *key, u8 *data, u8 *ciphertext)
 {
 	int  i;
 	int  round;
-	BYTE TmpdataA[16];
-	BYTE TmpdataB[16];
-	BYTE abyRoundKey[16];
+	u8 TmpdataA[16];
+	u8 TmpdataB[16];
+	u8 abyRoundKey[16];
 
 	for (i = 0; i < 16; i++)
 		abyRoundKey[i] = key[i];
@@ -231,32 +218,32 @@ void AESv128(BYTE *key, BYTE *data, BYTE *ciphertext)
  *
  */
 
-bool AESbGenCCMP(PBYTE pbyRxKey, PBYTE pbyFrame, WORD wFrameSize)
+bool AESbGenCCMP(u8 * pbyRxKey, u8 * pbyFrame, u16 wFrameSize)
 {
-	BYTE            abyNonce[13];
-	BYTE            MIC_IV[16];
-	BYTE            MIC_HDR1[16];
-	BYTE            MIC_HDR2[16];
-	BYTE            abyMIC[16];
-	BYTE            abyCTRPLD[16];
-	BYTE            abyTmp[16];
-	BYTE            abyPlainText[16];
-	BYTE            abyLastCipher[16];
-
-	PS802_11Header  pMACHeader = (PS802_11Header) pbyFrame;
-	PBYTE           pbyIV;
-	PBYTE           pbyPayload;
-	WORD            wHLen = 22;
+	u8            abyNonce[13];
+	u8            MIC_IV[16];
+	u8            MIC_HDR1[16];
+	u8            MIC_HDR2[16];
+	u8            abyMIC[16];
+	u8            abyCTRPLD[16];
+	u8            abyTmp[16];
+	u8            abyPlainText[16];
+	u8            abyLastCipher[16];
+
+	struct ieee80211_hdr *pMACHeader = (struct ieee80211_hdr *) pbyFrame;
+	u8 *           pbyIV;
+	u8 *           pbyPayload;
+	u16            wHLen = 22;
 	/* 8 is IV, 8 is MIC, 4 is CRC */
-	WORD            wPayloadSize = wFrameSize - 8 - 8 - 4 - WLAN_HDR_ADDR3_LEN;
+	u16            wPayloadSize = wFrameSize - 8 - 8 - 4 - WLAN_HDR_ADDR3_LEN;
 	bool            bA4 = false;
-	BYTE            byTmp;
-	WORD            wCnt;
+	u8            byTmp;
+	u16            wCnt;
 	int             ii, jj, kk;
 
 	pbyIV = pbyFrame + WLAN_HDR_ADDR3_LEN;
-	if (WLAN_GET_FC_TODS(*(PWORD) pbyFrame) &&
-	    WLAN_GET_FC_FROMDS(*(PWORD) pbyFrame)) {
+	if (WLAN_GET_FC_TODS(*(u16 *) pbyFrame) &&
+	    WLAN_GET_FC_FROMDS(*(u16 *) pbyFrame)) {
 		bA4 = true;
 		pbyIV += 6;             /* 6 is 802.11 address4 */
 		wHLen += 6;
@@ -265,7 +252,7 @@ bool AESbGenCCMP(PBYTE pbyRxKey, PBYTE pbyFrame, WORD wFrameSize)
 	pbyPayload = pbyIV + 8; /* IV-length */
 
 	abyNonce[0]  = 0x00; /* now is 0, if Qos here will be priority */
-	memcpy(&(abyNonce[1]), pMACHeader->abyAddr2, ETH_ALEN);
+	memcpy(&(abyNonce[1]), pMACHeader->addr2, ETH_ALEN);
 	abyNonce[7]  = pbyIV[7];
 	abyNonce[8]  = pbyIV[6];
 	abyNonce[9]  = pbyIV[5];
@@ -276,28 +263,28 @@ bool AESbGenCCMP(PBYTE pbyRxKey, PBYTE pbyFrame, WORD wFrameSize)
 	/* MIC_IV */
 	MIC_IV[0] = 0x59;
 	memcpy(&(MIC_IV[1]), &(abyNonce[0]), 13);
-	MIC_IV[14] = (BYTE)(wPayloadSize >> 8);
-	MIC_IV[15] = (BYTE)(wPayloadSize & 0xff);
+	MIC_IV[14] = (u8)(wPayloadSize >> 8);
+	MIC_IV[15] = (u8)(wPayloadSize & 0xff);
 
 	/* MIC_HDR1 */
-	MIC_HDR1[0] = (BYTE)(wHLen >> 8);
-	MIC_HDR1[1] = (BYTE)(wHLen & 0xff);
-	byTmp = (BYTE)(pMACHeader->wFrameCtl & 0xff);
+	MIC_HDR1[0] = (u8)(wHLen >> 8);
+	MIC_HDR1[1] = (u8)(wHLen & 0xff);
+	byTmp = (u8)(pMACHeader->frame_control & 0xff);
 	MIC_HDR1[2] = byTmp & 0x8f;
-	byTmp = (BYTE)(pMACHeader->wFrameCtl >> 8);
+	byTmp = (u8)(pMACHeader->frame_control >> 8);
 	byTmp &= 0x87;
 	MIC_HDR1[3] = byTmp | 0x40;
-	memcpy(&(MIC_HDR1[4]), pMACHeader->abyAddr1, ETH_ALEN);
-	memcpy(&(MIC_HDR1[10]), pMACHeader->abyAddr2, ETH_ALEN);
+	memcpy(&(MIC_HDR1[4]), pMACHeader->addr1, ETH_ALEN);
+	memcpy(&(MIC_HDR1[10]), pMACHeader->addr2, ETH_ALEN);
 
 	/* MIC_HDR2 */
-	memcpy(&(MIC_HDR2[0]), pMACHeader->abyAddr3, ETH_ALEN);
-	byTmp = (BYTE)(pMACHeader->wSeqCtl & 0xff);
+	memcpy(&(MIC_HDR2[0]), pMACHeader->addr3, ETH_ALEN);
+	byTmp = (u8)(pMACHeader->seq_ctrl & 0xff);
 	MIC_HDR2[6] = byTmp & 0x0f;
 	MIC_HDR2[7] = 0;
 
 	if (bA4) {
-		memcpy(&(MIC_HDR2[8]), pMACHeader->abyAddr4, ETH_ALEN);
+		memcpy(&(MIC_HDR2[8]), pMACHeader->addr4, ETH_ALEN);
 	} else {
 		MIC_HDR2[8]  = 0x00;
 		MIC_HDR2[9]  = 0x00;
@@ -326,8 +313,8 @@ bool AESbGenCCMP(PBYTE pbyRxKey, PBYTE pbyFrame, WORD wFrameSize)
 
 	for (jj = wPayloadSize; jj > 16; jj = jj-16) {
 
-		abyCTRPLD[14] = (BYTE) (wCnt >> 8);
-		abyCTRPLD[15] = (BYTE) (wCnt & 0xff);
+		abyCTRPLD[14] = (u8) (wCnt >> 8);
+		abyCTRPLD[15] = (u8) (wCnt & 0xff);
 
 		AESv128(pbyRxKey, abyCTRPLD, abyTmp);
 
@@ -349,8 +336,8 @@ bool AESbGenCCMP(PBYTE pbyRxKey, PBYTE pbyFrame, WORD wFrameSize)
 	for (ii = jj; ii < 16; ii++)
 		abyLastCipher[ii] = 0x00;
 
-	abyCTRPLD[14] = (BYTE) (wCnt >> 8);
-	abyCTRPLD[15] = (BYTE) (wCnt & 0xff);
+	abyCTRPLD[14] = (u8) (wCnt >> 8);
+	abyCTRPLD[15] = (u8) (wCnt & 0xff);
 
 	AESv128(pbyRxKey, abyCTRPLD, abyTmp);
 	for (kk = 0; kk < 16; kk++)
@@ -370,8 +357,8 @@ bool AESbGenCCMP(PBYTE pbyRxKey, PBYTE pbyFrame, WORD wFrameSize)
 	/* => above is the calculated MIC */
 
 	wCnt = 0;
-	abyCTRPLD[14] = (BYTE) (wCnt >> 8);
-	abyCTRPLD[15] = (BYTE) (wCnt & 0xff);
+	abyCTRPLD[14] = (u8) (wCnt >> 8);
+	abyCTRPLD[15] = (u8) (wCnt & 0xff);
 	AESv128(pbyRxKey, abyCTRPLD, abyTmp);
 
 	for (kk = 0; kk < 8; kk++)
diff --git a/drivers/staging/vt6656/aes_ccmp.h b/drivers/staging/vt6656/aes_ccmp.h
index a2e2c4e..ed6a9ae 100644
--- a/drivers/staging/vt6656/aes_ccmp.h
+++ b/drivers/staging/vt6656/aes_ccmp.h
@@ -30,17 +30,6 @@
 #ifndef __AES_H__
 #define __AES_H__
 
-#include "ttype.h"
-
-/*---------------------  Export Definitions -------------------------*/
-
-/*---------------------  Export Types  ------------------------------*/
-
-/*---------------------  Export Classes  ----------------------------*/
-
-/*---------------------  Export Variables  --------------------------*/
-
-/*---------------------  Export Functions  --------------------------*/
-bool AESbGenCCMP(PBYTE pbyRxKey, PBYTE pbyFrame, WORD wFrameSize);
+bool AESbGenCCMP(u8 * pbyRxKey, u8 * pbyFrame, u16 wFrameSize);
 
 #endif /* __AES_CCMP_H__ */
diff --git a/drivers/staging/vt6656/baseband.c b/drivers/staging/vt6656/baseband.c
index a9f525e..33fa767 100644
--- a/drivers/staging/vt6656/baseband.c
+++ b/drivers/staging/vt6656/baseband.c
@@ -29,8 +29,6 @@
  *      BBuGetFrameTime        - Calculate data frame transmitting time
  *      BBvCalculateParameter   - Calculate PhyLength, PhyService and Phy Signal parameter for baseband Tx
  *      BBbVT3184Init          - VIA VT3184 baseband chip init code
- *      BBvLoopbackOn          - Turn on BaseBand Loopback mode
- *      BBvLoopbackOff         - Turn off BaseBand Loopback mode
  *
  * Revision History:
  *
@@ -47,26 +45,10 @@
 #include "datarate.h"
 #include "rndis.h"
 
-/*---------------------  Static Definitions -------------------------*/
 static int          msglevel                =MSG_LEVEL_INFO;
 //static int          msglevel                =MSG_LEVEL_DEBUG;
 
-/*---------------------  Static Classes  ----------------------------*/
-
-/*---------------------  Static Variables  --------------------------*/
-
-/*---------------------  Static Functions  --------------------------*/
-
-/*---------------------  Export Variables  --------------------------*/
-
-/*---------------------  Static Definitions -------------------------*/
-
-/*---------------------  Static Classes  ----------------------------*/
-
-/*---------------------  Static Variables  --------------------------*/
-
-
-BYTE abyVT3184_AGC[] = {
+u8 abyVT3184_AGC[] = {
     0x00,   //0
     0x00,   //1
     0x02,   //2
@@ -133,8 +115,7 @@ BYTE abyVT3184_AGC[] = {
     0x3E    //3F
 };
 
-
-BYTE abyVT3184_AL2230[] = {
+u8 abyVT3184_AL2230[] = {
         0x31,//00
         0x00,
         0x00,
@@ -393,10 +374,8 @@ BYTE abyVT3184_AL2230[] = {
         0x00
 };
 
-
-
 //{{RobertYu:20060515, new BB setting for VT3226D0
-BYTE abyVT3184_VT3226D0[] = {
+u8 abyVT3184_VT3226D0[] = {
         0x31,//00
         0x00,
         0x00,
@@ -655,11 +634,9 @@ BYTE abyVT3184_VT3226D0[] = {
         0x00,
 };
 
-const WORD awcFrameTime[MAX_RATE] =
+const u16 awcFrameTime[MAX_RATE] =
 {10, 20, 55, 110, 24, 36, 48, 72, 96, 144, 192, 216};
 
-/*---------------------  Static Functions  --------------------------*/
-
 /*
 static
 unsigned long
@@ -674,7 +651,6 @@ void
 s_vClearSQ3Value(PSDevice pDevice);
 */
 
-/*---------------------  Export Variables  --------------------------*/
 /*
  * Description: Calculate data frame transmitting time
  *
@@ -691,10 +667,10 @@ s_vClearSQ3Value(PSDevice pDevice);
  */
 unsigned int
 BBuGetFrameTime(
-     BYTE byPreambleType,
-     BYTE byPktType,
+     u8 byPreambleType,
+     u8 byPktType,
      unsigned int cbFrameLength,
-     WORD wRate
+     u16 wRate
     )
 {
     unsigned int uFrameTime;
@@ -703,7 +679,6 @@ BBuGetFrameTime(
     unsigned int uRateIdx = (unsigned int)wRate;
     unsigned int uRate = 0;
 
-
     if (uRateIdx > RATE_54M) {
         ASSERT(0);
         return 0;
@@ -900,15 +875,14 @@ void BBvCalculateParameter(struct vnt_private *pDevice, u32 cbFrameLength,
         *pbyPhySrv = 0x00;
         if (bExtBit)
             *pbyPhySrv = *pbyPhySrv | 0x80;
-        *pwPhyLen = (WORD) cbUsCount;
+        *pwPhyLen = (u16) cbUsCount;
     }
     else {
         *pbyPhySrv = 0x00;
-        *pwPhyLen = (WORD)cbFrameLength;
+        *pwPhyLen = (u16)cbFrameLength;
     }
 }
 
-
 /*
  * Description: Set Antenna mode
  *
@@ -937,10 +911,9 @@ void BBvSetAntennaMode(struct vnt_private *pDevice, u8 byAntennaMode)
             break;
     }
 
-
     CONTROLnsRequestOut(pDevice,
                     MESSAGE_TYPE_SET_ANTMD,
-                    (WORD) byAntennaMode,
+                    (u16) byAntennaMode,
                     0,
                     0,
                     NULL);
@@ -963,11 +936,11 @@ void BBvSetAntennaMode(struct vnt_private *pDevice, u8 byAntennaMode)
 int BBbVT3184Init(struct vnt_private *pDevice)
 {
 	int ntStatus;
-    WORD                    wLength;
-    PBYTE                   pbyAddr;
-    PBYTE                   pbyAgc;
-    WORD                    wLengthAgc;
-    BYTE                    abyArray[256];
+    u16                    wLength;
+    u8 *                   pbyAddr;
+    u8 *                   pbyAgc;
+    u16                    wLengthAgc;
+    u8                    abyArray[256];
 
     ntStatus = CONTROLnsRequestIn(pDevice,
                                   MESSAGE_TYPE_READ,
@@ -979,7 +952,6 @@ int BBbVT3184Init(struct vnt_private *pDevice)
         return false;
     }
 
-
 //    if ((pDevice->abyEEPROM[EEP_OFS_RADIOCTL]&0x06)==0x04)
 //        return false;
 
@@ -1118,7 +1090,6 @@ else {
                     abyArray
                     );
 
-
     if ((pDevice->byRFType == RF_VT3226) || //RobertYu:20051116, 20060111 remove VT3226D0
          (pDevice->byRFType == RF_VT3342A0)  //RobertYu:20060609
          ) {
@@ -1131,7 +1102,6 @@ else {
         MACvRegBitsOn(pDevice,MAC_REG_PAPEDELAY,0x01);
     }
 
-
     ControlvWriteByte(pDevice,MESSAGE_REQUEST_BBREG,0x04,0x7F);
     ControlvWriteByte(pDevice,MESSAGE_REQUEST_BBREG,0x0D,0x01);
 
@@ -1139,96 +1109,6 @@ else {
     return true;//ntStatus;
 }
 
-
-/*
- * Description: Turn on BaseBand Loopback mode
- *
- * Parameters:
- *  In:
- *      pDevice         - Device Structure
- *
- *  Out:
- *      none
- *
- * Return Value: none
- *
- */
-void BBvLoopbackOn(struct vnt_private *pDevice)
-{
-    BYTE      byData;
-
-    //CR C9 = 0x00
-    ControlvReadByte (pDevice, MESSAGE_REQUEST_BBREG, 0xC9, &pDevice->byBBCRc9);//CR201
-    ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0);
-    ControlvReadByte (pDevice, MESSAGE_REQUEST_BBREG, 0x4D, &pDevice->byBBCR4d);//CR77
-    ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0x4D, 0x90);
-
-    //CR 88 = 0x02(CCK), 0x03(OFDM)
-    ControlvReadByte (pDevice, MESSAGE_REQUEST_BBREG, 0x88, &pDevice->byBBCR88);//CR136
-
-    if (pDevice->wCurrentRate <= RATE_11M) { //CCK
-        // Enable internal digital loopback: CR33 |= 0000 0001
-        ControlvReadByte (pDevice, MESSAGE_REQUEST_BBREG, 0x21, &byData);//CR33
-        ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0x21, (BYTE)(byData | 0x01));//CR33
-        // CR154 = 0x00
-        ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0x9A, 0);   //CR154
-
-        ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0x88, 0x02);//CR239
-    }
-    else { //OFDM
-        // Enable internal digital loopback:CR154 |= 0000 0001
-        ControlvReadByte (pDevice, MESSAGE_REQUEST_BBREG, 0x9A, &byData);//CR154
-        ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0x9A, (BYTE)(byData | 0x01));//CR154
-        // CR33 = 0x00
-        ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0x21, 0);   //CR33
-
-        ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0x88, 0x03);//CR239
-    }
-
-    //CR14 = 0x00
-    ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0x0E, 0);//CR14
-
-    // Disable TX_IQUN
-    ControlvReadByte (pDevice, MESSAGE_REQUEST_BBREG, 0x09, &pDevice->byBBCR09);
-    ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0x09, (BYTE)(pDevice->byBBCR09 & 0xDE));
-}
-
-/*
- * Description: Turn off BaseBand Loopback mode
- *
- * Parameters:
- *  In:
- *      pDevice         - Device Structure
- *
- *  Out:
- *      none
- *
- * Return Value: none
- *
- */
-void BBvLoopbackOff(struct vnt_private *pDevice)
-{
-	u8 byData;
-
-    ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, pDevice->byBBCRc9);//CR201
-    ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0x88, pDevice->byBBCR88);//CR136
-    ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0x09, pDevice->byBBCR09);//CR136
-    ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0x4D, pDevice->byBBCR4d);//CR77
-
-    if (pDevice->wCurrentRate <= RATE_11M) { // CCK
-        // Set the CR33 Bit2 to disable internal Loopback.
-        ControlvReadByte (pDevice, MESSAGE_REQUEST_BBREG, 0x21, &byData);//CR33
-        ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0x21, (BYTE)(byData & 0xFE));//CR33
-	} else { /* OFDM */
-        ControlvReadByte (pDevice, MESSAGE_REQUEST_BBREG, 0x9A, &byData);//CR154
-        ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0x9A, (BYTE)(byData & 0xFE));//CR154
-    }
-    ControlvReadByte (pDevice, MESSAGE_REQUEST_BBREG, 0x0E, &byData);//CR14
-    ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0x0E, (BYTE)(byData | 0x80));//CR14
-
-}
-
-
 /*
  * Description: Set ShortSlotTime mode
  *
@@ -1243,7 +1123,7 @@ void BBvLoopbackOff(struct vnt_private *pDevice)
  */
 void BBvSetShortSlotTime(struct vnt_private *pDevice)
 {
-    BYTE byBBVGA=0;
+    u8 byBBVGA=0;
 
 	if (pDevice->bShortSlotTime)
         pDevice->byBBRxConf &= 0xDF;//1101 1111
@@ -1257,8 +1137,7 @@ void BBvSetShortSlotTime(struct vnt_private *pDevice)
     ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0x0A, pDevice->byBBRxConf);
 }
 
-
-void BBvSetVGAGainOffset(struct vnt_private *pDevice, BYTE byData)
+void BBvSetVGAGainOffset(struct vnt_private *pDevice, u8 byData)
 {
 
     ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xE7, byData);
@@ -1272,27 +1151,6 @@ void BBvSetVGAGainOffset(struct vnt_private *pDevice, BYTE byData)
     ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0x0A, pDevice->byBBRxConf);//CR10
 }
 
-
-/*
- * Description: Baseband SoftwareReset
- *
- * Parameters:
- *  In:
- *      dwIoBase    - I/O base address
- *  Out:
- *      none
- *
- * Return Value: none
- *
- */
-void BBvSoftwareReset(struct vnt_private *pDevice)
-{
-    ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0x50, 0x40);
-    ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0x50, 0);
-    ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0x9C, 0x01);
-    ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0x9C, 0);
-}
-
 /*
  * Description: BBvSetDeepSleep
  *
@@ -1317,7 +1175,6 @@ void BBvExitDeepSleep(struct vnt_private *pDevice)
     ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0x0D, 0x01);//CR13
 }
 
-
 static unsigned long s_ulGetLowSQ3(struct vnt_private *pDevice)
 {
 	int ii;
@@ -1364,7 +1221,6 @@ static unsigned long s_ulGetRatio(struct vnt_private *pDevice)
     return ulRatio;
 }
 
-
 static void s_vClearSQ3Value(struct vnt_private *pDevice)
 {
     int ii;
@@ -1376,7 +1232,6 @@ static void s_vClearSQ3Value(struct vnt_private *pDevice)
     }
 }
 
-
 /*
  * Description: Antenna Diversity
  *
@@ -1508,7 +1363,6 @@ void BBvAntennaDiversity(struct vnt_private *pDevice,
     } //byAntennaState
 }
 
-
 /*+
  *
  * Description:
@@ -1541,11 +1395,9 @@ void TimerSQ3CallBack(struct vnt_private *pDevice)
     add_timer(&pDevice->TimerSQ3Tmax3);
     add_timer(&pDevice->TimerSQ3Tmax2);
 
-
     spin_unlock_irq(&pDevice->lock);
 }
 
-
 /*+
  *
  * Description:
@@ -1594,7 +1446,6 @@ void TimerSQ3Tmax3CallBack(struct vnt_private *pDevice)
 void BBvUpdatePreEDThreshold(struct vnt_private *pDevice, int bScanning)
 {
 
-
     switch(pDevice->byRFType)
     {
         case RF_AL2230:
diff --git a/drivers/staging/vt6656/baseband.h b/drivers/staging/vt6656/baseband.h
index fba6160..0a634ad 100644
--- a/drivers/staging/vt6656/baseband.h
+++ b/drivers/staging/vt6656/baseband.h
@@ -33,12 +33,9 @@
 #ifndef __BASEBAND_H__
 #define __BASEBAND_H__
 
-#include "ttype.h"
 #include "tether.h"
 #include "device.h"
 
-/*---------------------  Export Definitions -------------------------*/
-
 #define PREAMBLE_LONG   0
 #define PREAMBLE_SHORT  1
 
@@ -84,23 +81,12 @@
 #define TOP_RATE_2M         0x00200000
 #define TOP_RATE_1M         0x00100000
 
-
-/*---------------------  Export Types  ------------------------------*/
-
-/*---------------------  Export Macros ------------------------------*/
-
-/*---------------------  Export Classes  ----------------------------*/
-
-/*---------------------  Export Variables  --------------------------*/
-
-/*---------------------  Export Functions  --------------------------*/
-
 unsigned int
 BBuGetFrameTime(
-     BYTE byPreambleType,
-     BYTE byFreqType,
+     u8 byPreambleType,
+     u8 byFreqType,
      unsigned int cbFrameLength,
-     WORD wRate
+     u16 wRate
     );
 
 void BBvCalculateParameter(struct vnt_private *, u32 cbFrameLength,
@@ -113,9 +99,6 @@ void TimerSQ3CallBack(struct vnt_private *);
 void TimerSQ3Tmax3CallBack(struct vnt_private *);
 
 void BBvAntennaDiversity(struct vnt_private *, u8 byRxRate, u8 bySQ3);
-void BBvLoopbackOn(struct vnt_private *);
-void BBvLoopbackOff(struct vnt_private *);
-void BBvSoftwareReset(struct vnt_private *);
 
 void BBvSetShortSlotTime(struct vnt_private *);
 void BBvSetVGAGainOffset(struct vnt_private *, u8 byData);
diff --git a/drivers/staging/vt6656/bssdb.c b/drivers/staging/vt6656/bssdb.c
index e214fcf..ee79bbd 100644
--- a/drivers/staging/vt6656/bssdb.c
+++ b/drivers/staging/vt6656/bssdb.c
@@ -39,7 +39,6 @@
  *
  */
 
-#include "ttype.h"
 #include "tmacro.h"
 #include "tether.h"
 #include "device.h"
@@ -59,27 +58,17 @@
 #include "rndis.h"
 #include "iowpa.h"
 
-/*---------------------  Static Definitions -------------------------*/
-
-
-
-
-/*---------------------  Static Classes  ----------------------------*/
-
-/*---------------------  Static Variables  --------------------------*/
 static int          msglevel                =MSG_LEVEL_INFO;
 //static int          msglevel                =MSG_LEVEL_DEBUG;
 
-
-
-const WORD             awHWRetry0[5][5] = {
+const u16             awHWRetry0[5][5] = {
                                             {RATE_18M, RATE_18M, RATE_12M, RATE_12M, RATE_12M},
                                             {RATE_24M, RATE_24M, RATE_18M, RATE_12M, RATE_12M},
                                             {RATE_36M, RATE_36M, RATE_24M, RATE_18M, RATE_18M},
                                             {RATE_48M, RATE_48M, RATE_36M, RATE_24M, RATE_24M},
                                             {RATE_54M, RATE_54M, RATE_48M, RATE_36M, RATE_36M}
                                            };
-const WORD             awHWRetry1[5][5] = {
+const u16             awHWRetry1[5][5] = {
                                             {RATE_18M, RATE_18M, RATE_12M, RATE_6M, RATE_6M},
                                             {RATE_24M, RATE_24M, RATE_18M, RATE_6M, RATE_6M},
                                             {RATE_36M, RATE_36M, RATE_24M, RATE_12M, RATE_12M},
@@ -87,23 +76,10 @@ const WORD             awHWRetry1[5][5] = {
                                             {RATE_54M, RATE_54M, RATE_36M, RATE_18M, RATE_18M}
                                            };
 
-
-
-/*---------------------  Static Functions  --------------------------*/
-
 static void s_vCheckSensitivity(struct vnt_private *pDevice);
 static void s_vCheckPreEDThreshold(struct vnt_private *pDevice);
 static void s_uCalculateLinkQual(struct vnt_private *pDevice);
 
-/*---------------------  Export Variables  --------------------------*/
-
-
-/*---------------------  Export Functions  --------------------------*/
-
-
-
-
-
 /*+
  *
  * Routine Description:
@@ -221,7 +197,6 @@ PKnownBSS BSSpSearchBSSList(struct vnt_private *pDevice,
 			pCurrBSS->abyBSSID);
         jj++;
 
-
                 if (pSelect == NULL) {
                     pSelect = pCurrBSS;
                 } else {
@@ -249,7 +224,6 @@ pDevice->bSameBSSMaxNum = jj;
 
 }
 
-
 /*+
  *
  * Routine Description:
@@ -260,7 +234,6 @@ pDevice->bSameBSSMaxNum = jj;
  *
 -*/
 
-
 void BSSvClearBSSList(struct vnt_private *pDevice, int bKeepCurrBSSID)
 {
 	struct vnt_manager *pMgmt = &pDevice->vnt_mgmt;
@@ -285,8 +258,6 @@ void BSSvClearBSSList(struct vnt_private *pDevice, int bKeepCurrBSSID)
     BSSvClearAnyBSSJoinRecord(pDevice);
 }
 
-
-
 /*+
  *
  * Routine Description:
@@ -320,8 +291,6 @@ PKnownBSS BSSpAddrIsInBSSList(struct vnt_private *pDevice,
     return NULL;
 };
 
-
-
 /*+
  *
  * Routine Description:
@@ -357,7 +326,6 @@ int BSSbInsertToBSSList(struct vnt_private *pDevice,
 	unsigned int ii;
 	bool bParsingQuiet = false;
 
-
     pBSSList = (PKnownBSS)&(pMgmt->sBSSList[0]);
 
     for (ii = 0; ii < MAX_BSS_NUM; ii++) {
@@ -430,7 +398,7 @@ int BSSbInsertToBSSList(struct vnt_private *pDevice,
 	unsigned int uLen = pRSNWPA->len + 2;
 
 	if (uLen <= (uIELength -
-		     (unsigned int) (ULONG_PTR) ((PBYTE) pRSNWPA - pbyIEs))) {
+		     (unsigned int) (u32) ((u8 *) pRSNWPA - pbyIEs))) {
 		pBSSList->wWPALen = uLen;
 		memcpy(pBSSList->byWPAIE, pRSNWPA, uLen);
 		WPA_ParseRSN(pBSSList, pRSNWPA);
@@ -443,7 +411,7 @@ int BSSbInsertToBSSList(struct vnt_private *pDevice,
 	unsigned int uLen = pRSN->len + 2;
 
 	if (uLen <= (uIELength -
-		     (unsigned int) (ULONG_PTR) ((PBYTE) pRSN - pbyIEs))) {
+		     (unsigned int) (u32) ((u8 *) pRSN - pbyIEs))) {
 		pBSSList->wRSNLen = uLen;
 		memcpy(pBSSList->byRSNIE, pRSN, uLen);
 		WPA2vParseRSN(pBSSList, pRSN);
@@ -483,7 +451,7 @@ int BSSbInsertToBSSList(struct vnt_private *pDevice,
     if (pDevice->bUpdateBBVGA) {
         // Monitor if RSSI is too strong.
         pBSSList->byRSSIStatCnt = 0;
-        RFvRSSITodBm(pDevice, (BYTE)(pRxPacket->uRSSI), &pBSSList->ldBmMAX);
+        RFvRSSITodBm(pDevice, (u8)(pRxPacket->uRSSI), &pBSSList->ldBmMAX);
         pBSSList->ldBmAverage[0] = pBSSList->ldBmMAX;
         pBSSList->ldBmAverRange = pBSSList->ldBmMAX;
         for (ii = 1; ii < RSSI_STAT_COUNT; ii++)
@@ -498,7 +466,6 @@ int BSSbInsertToBSSList(struct vnt_private *pDevice,
     return true;
 }
 
-
 /*+
  *
  * Routine Description:
@@ -539,7 +506,6 @@ int BSSbUpdateToBSSList(struct vnt_private *pDevice,
     if (pBSSList == NULL)
         return false;
 
-
 	pBSSList->qwBSSTimestamp = cpu_to_le64(qwTimestamp);
 
     pBSSList->wBeaconInterval = cpu_to_le16(wBeaconInterval);
@@ -592,7 +558,7 @@ int BSSbUpdateToBSSList(struct vnt_private *pDevice,
    if (pRSNWPA != NULL) {
 	unsigned int uLen = pRSNWPA->len + 2;
 	if (uLen <= (uIELength -
-		     (unsigned int) (ULONG_PTR) ((PBYTE) pRSNWPA - pbyIEs))) {
+		     (unsigned int) (u32) ((u8 *) pRSNWPA - pbyIEs))) {
 		pBSSList->wWPALen = uLen;
 		memcpy(pBSSList->byWPAIE, pRSNWPA, uLen);
 		WPA_ParseRSN(pBSSList, pRSNWPA);
@@ -604,7 +570,7 @@ int BSSbUpdateToBSSList(struct vnt_private *pDevice,
     if (pRSN != NULL) {
 	unsigned int uLen = pRSN->len + 2;
 	if (uLen <= (uIELength -
-			(unsigned int) (ULONG_PTR) ((PBYTE) pRSN - pbyIEs))) {
+			(unsigned int) (u32) ((u8 *) pRSN - pbyIEs))) {
 		pBSSList->wRSNLen = uLen;
 		memcpy(pBSSList->byRSNIE, pRSN, uLen);
 		WPA2vParseRSN(pBSSList, pRSN);
@@ -612,7 +578,7 @@ int BSSbUpdateToBSSList(struct vnt_private *pDevice,
     }
 
     if (pRxPacket->uRSSI != 0) {
-        RFvRSSITodBm(pDevice, (BYTE)(pRxPacket->uRSSI), &ldBm);
+        RFvRSSITodBm(pDevice, (u8)(pRxPacket->uRSSI), &ldBm);
         // Monitor if RSSI is too strong.
         pBSSList->byRSSIStatCnt++;
         pBSSList->byRSSIStatCnt %= RSSI_STAT_COUNT;
@@ -638,10 +604,6 @@ int BSSbUpdateToBSSList(struct vnt_private *pDevice,
     return true;
 }
 
-
-
-
-
 /*+
  *
  * Routine Description:
@@ -672,8 +634,6 @@ int BSSbIsSTAInNodeDB(struct vnt_private *pDevice,
    return false;
 };
 
-
-
 /*+
  *
  * Routine Description:
@@ -731,8 +691,6 @@ void BSSvCreateOneNode(struct vnt_private *pDevice, u32 *puNodeIndex)
     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Create node index = %d\n", ii);
 };
 
-
-
 /*+
  *
  * Routine Description:
@@ -750,7 +708,6 @@ void BSSvRemoveOneNode(struct vnt_private *pDevice, u32 uNodeIndex)
 	u8 byMask[8] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80};
 	struct sk_buff  *skb;
 
-
     while ((skb = skb_dequeue(&pMgmt->sNodeDBTable[uNodeIndex].sTxPSQueue)) != NULL)
             dev_kfree_skb(skb);
     // clear context
@@ -948,7 +905,6 @@ if(pDevice->byReAssocCount > 0) {
                 if (pMgmt->sNodeDBTable[ii].bPSEnable)
                     uSleepySTACnt++;
 
-
             }
 
             // Rate fallback check
@@ -981,7 +937,6 @@ if(pDevice->byReAssocCount > 0) {
 
     }
 
-
     if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) && (pDevice->byBBType == BB_TYPE_11G)) {
 
         // on/off protect mode
@@ -1031,7 +986,6 @@ if(pDevice->byReAssocCount > 0) {
 
     }
 
-
     // Check if any STA in PS mode, enable DTIM multicast deliver
     if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) {
         if (uSleepySTACnt > 0)
@@ -1205,9 +1159,9 @@ void BSSvUpdateNodeTxCounter(struct vnt_private *pDevice,
 
     byPktNum = (byPktNO & 0x0F) >> 4;
     byTxRetry = (byTSR & 0xF0) >> 4;
-    wRate = (WORD) (byPktNO & 0xF0) >> 4;
+    wRate = (u16) (byPktNO & 0xF0) >> 4;
     wFIFOCtl = pStatistic->abyTxPktInfo[byPktNum].wFIFOCtl;
-    pbyDestAddr = (PBYTE) &( pStatistic->abyTxPktInfo[byPktNum].abyDestAddr[0]);
+    pbyDestAddr = (u8 *) &( pStatistic->abyTxPktInfo[byPktNum].abyDestAddr[0]);
 
     if (wFIFOCtl & FIFOCTL_AUTO_FB_0) {
         byFallBack = AUTO_FB_0;
@@ -1433,7 +1387,7 @@ if(pDevice->bLinkPass !=true)
 }
 else
 {
-   RFvRSSITodBm(pDevice, (BYTE)(pDevice->uCurrRSSI), &ldBm);
+   RFvRSSITodBm(pDevice, (u8)(pDevice->uCurrRSSI), &ldBm);
    if(-ldBm < 50)  {
    	RssiRatio = 4000;
      }
@@ -1473,7 +1427,7 @@ static void s_vCheckPreEDThreshold(struct vnt_private *pDevice)
         ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) && (pMgmt->eCurrState == WMAC_STATE_JOINTED))) {
         pBSSList = BSSpAddrIsInBSSList(pDevice, pMgmt->abyCurrBSSID, (PWLAN_IE_SSID)pMgmt->abyCurrSSID);
         if (pBSSList != NULL) {
-            pDevice->byBBPreEDRSSI = (BYTE) (~(pBSSList->ldBmAverRange) + 1);
+            pDevice->byBBPreEDRSSI = (u8) (~(pBSSList->ldBmAverRange) + 1);
             BBvUpdatePreEDThreshold(pDevice, false);
         }
     }
diff --git a/drivers/staging/vt6656/bssdb.h b/drivers/staging/vt6656/bssdb.h
index 08091a0..bce3b46 100644
--- a/drivers/staging/vt6656/bssdb.h
+++ b/drivers/staging/vt6656/bssdb.h
@@ -36,8 +36,6 @@
 #include "card.h"
 #include "mib.h"
 
-/*---------------------  Export Definitions -------------------------*/
-
 #define MAX_NODE_NUM             64
 #define MAX_BSS_NUM              42
 #define LOST_BEACON_COUNT        10   /* 10 sec, XP defined */
@@ -66,46 +64,37 @@
 
 #define MAX_WPA_IE_LEN      64
 
-
-/*---------------------  Export Classes  ----------------------------*/
-
-/*---------------------  Export Variables  --------------------------*/
-
-
-/*---------------------  Export Types  ------------------------------*/
-
 //
 // IEEE 802.11 Structures and definitions
 //
 
 typedef struct tagSERPObject {
     bool    bERPExist;
-    BYTE    byERP;
+    u8    byERP;
 } ERPObject, *PERPObject;
 
-
 typedef struct tagSRSNCapObject {
     bool    bRSNCapExist;
-    WORD    wRSNCap;
+    u16    wRSNCap;
 } SRSNCapObject, *PSRSNCapObject;
 
 // BSS info(AP)
 typedef struct tagKnownBSS {
     // BSS info
     bool            bActive;
-    BYTE            abyBSSID[WLAN_BSSID_LEN];
+    u8            abyBSSID[WLAN_BSSID_LEN];
     unsigned int            uChannel;
-    BYTE            abySuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1];
-    BYTE            abyExtSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1];
+    u8            abySuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1];
+    u8            abyExtSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1];
     unsigned int            uRSSI;
-    BYTE            bySQ;
-    WORD            wBeaconInterval;
-    WORD            wCapInfo;
-    BYTE            abySSID[WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1];
-    BYTE            byRxRate;
-
-//    WORD            wATIMWindow;
-    BYTE            byRSSIStatCnt;
+    u8            bySQ;
+    u16            wBeaconInterval;
+    u16            wCapInfo;
+    u8            abySSID[WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1];
+    u8            byRxRate;
+
+//    u16            wATIMWindow;
+    u8            byRSSIStatCnt;
     signed long            ldBmMAX;
     signed long            ldBmAverage[RSSI_STAT_COUNT];
     signed long            ldBmAverRange;
@@ -114,32 +103,32 @@ typedef struct tagKnownBSS {
 
     //++ WPA informations
     bool            bWPAValid;
-    BYTE            byGKType;
-    BYTE            abyPKType[4];
-    WORD            wPKCount;
-    BYTE            abyAuthType[4];
-    WORD            wAuthCount;
-    BYTE            byDefaultK_as_PK;
-    BYTE            byReplayIdx;
+    u8            byGKType;
+    u8            abyPKType[4];
+    u16            wPKCount;
+    u8            abyAuthType[4];
+    u16            wAuthCount;
+    u8            byDefaultK_as_PK;
+    u8            byReplayIdx;
     //--
 
     //++ WPA2 informations
     bool            bWPA2Valid;
-    BYTE            byCSSGK;
-    WORD            wCSSPKCount;
-    BYTE            abyCSSPK[4];
-    WORD            wAKMSSAuthCount;
-    BYTE            abyAKMSSAuthType[4];
+    u8            byCSSGK;
+    u16            wCSSPKCount;
+    u8            abyCSSPK[4];
+    u16            wAKMSSAuthCount;
+    u8            abyAKMSSAuthType[4];
 
     //++  wpactl
-    BYTE            byWPAIE[MAX_WPA_IE_LEN];
-    BYTE            byRSNIE[MAX_WPA_IE_LEN];
-    WORD            wWPALen;
-    WORD            wRSNLen;
+    u8            byWPAIE[MAX_WPA_IE_LEN];
+    u8            byRSNIE[MAX_WPA_IE_LEN];
+    u16            wWPALen;
+    u16            wRSNLen;
 
     // Clear count
     unsigned int            uClearCount;
-//    BYTE            abyIEs[WLAN_BEACON_FR_MAXLEN];
+//    u8            abyIEs[WLAN_BEACON_FR_MAXLEN];
     unsigned int            uIELength;
 	u64 qwBSSTimestamp;
 	u64 qwLocalTSF;/* local TSF timer */
@@ -148,13 +137,11 @@ typedef struct tagKnownBSS {
 
     ERPObject       sERP;
     SRSNCapObject   sRSNCapObj;
-    BYTE            abyIEs[1024];   // don't move this field !!
+    u8            abyIEs[1024];   // don't move this field !!
 
 } __attribute__ ((__packed__))
 KnownBSS , *PKnownBSS;
 
-
-
 typedef enum tagNODE_STATE {
     NODE_FREE,
     NODE_AGED,
@@ -163,48 +150,47 @@ typedef enum tagNODE_STATE {
     NODE_ASSOC
 } NODE_STATE, *PNODE_STATE;
 
-
 // STA node info
 typedef struct tagKnownNodeDB {
     // STA info
     bool            bActive;
-    BYTE            abyMACAddr[WLAN_ADDR_LEN];
-    BYTE            abyCurrSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN];
-    BYTE            abyCurrExtSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN];
-    WORD            wTxDataRate;
+    u8            abyMACAddr[WLAN_ADDR_LEN];
+    u8            abyCurrSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN];
+    u8            abyCurrExtSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN];
+    u16            wTxDataRate;
     bool            bShortPreamble;
     bool            bERPExist;
     bool            bShortSlotTime;
     unsigned int            uInActiveCount;
-    WORD            wMaxBasicRate;     //Get from byTopOFDMBasicRate or byTopCCKBasicRate which depends on packetTyp.
-    WORD            wMaxSuppRate;      //Records the highest supported rate getting from SuppRates IE and ExtSuppRates IE in Beacon.
-    WORD            wSuppRate;
-    BYTE            byTopOFDMBasicRate;//Records the highest basic rate in OFDM mode
-    BYTE            byTopCCKBasicRate; //Records the highest basic rate in CCK mode
+    u16            wMaxBasicRate;     //Get from byTopOFDMBasicRate or byTopCCKBasicRate which depends on packetTyp.
+    u16            wMaxSuppRate;      //Records the highest supported rate getting from SuppRates IE and ExtSuppRates IE in Beacon.
+    u16            wSuppRate;
+    u8            byTopOFDMBasicRate;//Records the highest basic rate in OFDM mode
+    u8            byTopCCKBasicRate; //Records the highest basic rate in CCK mode
 
     // For AP mode
     struct sk_buff_head sTxPSQueue;
-    WORD            wCapInfo;
-    WORD            wListenInterval;
-    WORD            wAID;
+    u16            wCapInfo;
+    u16            wListenInterval;
+    u16            wAID;
     NODE_STATE      eNodeState;
     bool            bPSEnable;
     bool            bRxPSPoll;
-    BYTE            byAuthSequence;
+    u8            byAuthSequence;
     unsigned long           ulLastRxJiffer;
-    BYTE            bySuppRate;
-    DWORD           dwFlags;
-    WORD            wEnQueueCnt;
+    u8            bySuppRate;
+    u32           dwFlags;
+    u16            wEnQueueCnt;
 
     bool            bOnFly;
     unsigned long long       KeyRSC;
-    BYTE            byKeyIndex;
-    DWORD           dwKeyIndex;
-    BYTE            byCipherSuite;
-    DWORD           dwTSC47_16;
-    WORD            wTSC15_0;
+    u8            byKeyIndex;
+    u32           dwKeyIndex;
+    u8            byCipherSuite;
+    u32           dwTSC47_16;
+    u16            wTSC15_0;
     unsigned int            uWepKeyLength;
-    BYTE            abyWepKey[WLAN_WEPMAX_KEYLEN];
+    u8            abyWepKey[WLAN_WEPMAX_KEYLEN];
     //
     // Auto rate fallback vars
     bool            bIsInFallback;
@@ -223,8 +209,6 @@ typedef struct tagKnownNodeDB {
 
 } KnownNodeDB, *PKnownNodeDB;
 
-/*---------------------  Export Functions  --------------------------*/
-
 PKnownBSS BSSpSearchBSSList(struct vnt_private *, u8 *pbyDesireBSSID,
 	u8 *pbyDesireSSID, CARD_PHY_TYPE ePhyType);
 
@@ -270,7 +254,7 @@ int BSSbUpdateToBSSList(struct vnt_private *,
 			u8 *pbyIEs,
 			void *pRxPacketContext);
 
-int BSSbIsSTAInNodeDB(struct vnt_private *, PBYTE abyDstAddr,
+int BSSbIsSTAInNodeDB(struct vnt_private *, u8 * abyDstAddr,
 	u32 *puNodeIndex);
 
 void BSSvCreateOneNode(struct vnt_private *, u32 *puNodeIndex);
diff --git a/drivers/staging/vt6656/card.c b/drivers/staging/vt6656/card.c
index d2479b7..24291ae 100644
--- a/drivers/staging/vt6656/card.c
+++ b/drivers/staging/vt6656/card.c
@@ -60,28 +60,15 @@
 #include "rndis.h"
 #include "control.h"
 
-/*---------------------  Static Definitions -------------------------*/
-
 //static int          msglevel                =MSG_LEVEL_DEBUG;
 static int          msglevel                =MSG_LEVEL_INFO;
 
-
-/*---------------------  Static Definitions -------------------------*/
-
-/*---------------------  Static Classes  ----------------------------*/
-
-/*---------------------  Static Variables  --------------------------*/
-//const WORD cwRXBCNTSFOff[MAX_RATE] =
+//const u16 cwRXBCNTSFOff[MAX_RATE] =
 //{17, 34, 96, 192, 34, 23, 17, 11, 8, 5, 4, 3};
 
-const WORD cwRXBCNTSFOff[MAX_RATE] =
+const u16 cwRXBCNTSFOff[MAX_RATE] =
 {192, 96, 34, 17, 34, 23, 17, 11, 8, 5, 4, 3};
 
-/*---------------------  Static Functions  --------------------------*/
-
-/*---------------------  Export Variables  --------------------------*/
-
-/*---------------------  Export Functions  --------------------------*/
 /*
  * Description: Set NIC media channel
  *
@@ -114,7 +101,7 @@ void CARDbSetMediaChannel(struct vnt_private *pDevice, u32 uConnectionChannel)
 
     CONTROLnsRequestOut(pDevice,
                         MESSAGE_TYPE_SELECT_CHANNLE,
-                        (WORD) uConnectionChannel,
+                        (u16) uConnectionChannel,
                         0,
                         0,
                         NULL
@@ -133,7 +120,7 @@ void CARDbSetMediaChannel(struct vnt_private *pDevice, u32 uConnectionChannel)
         pDevice->byCurPwr = 0xFF;
         RFbRawSetPower(pDevice, pDevice->abyCCKPwrTbl[uConnectionChannel-1], RATE_1M);
     }
-    ControlvWriteByte(pDevice,MESSAGE_REQUEST_MACREG,MAC_REG_CHANNEL,(BYTE)(uConnectionChannel|0x80));
+    ControlvWriteByte(pDevice,MESSAGE_REQUEST_MACREG,MAC_REG_CHANNEL,(u8)(uConnectionChannel|0x80));
 }
 
 /*
@@ -220,10 +207,10 @@ static u16 swGetOFDMControlRate(struct vnt_private *pDevice, u16 wRateIdx)
  */
 void
 CARDvCalculateOFDMRParameter (
-      WORD wRate,
-      BYTE byBBType,
-     PBYTE pbyTxRate,
-     PBYTE pbyRsvTime
+      u16 wRate,
+      u8 byBBType,
+     u8 * pbyTxRate,
+     u8 * pbyRsvTime
     )
 {
     switch (wRate) {
@@ -434,23 +421,23 @@ void CARDvSetRSPINF(struct vnt_private *pDevice, u8 byBBType)
                                  &abyTxRate[8],
                                  &abyRsvTime[8]);
 
-    abyData[0] = (BYTE)(awLen[0]&0xFF);
-    abyData[1] = (BYTE)(awLen[0]>>8);
+    abyData[0] = (u8)(awLen[0]&0xFF);
+    abyData[1] = (u8)(awLen[0]>>8);
     abyData[2] = abySignal[0];
     abyData[3] = abyServ[0];
 
-    abyData[4] = (BYTE)(awLen[1]&0xFF);
-    abyData[5] = (BYTE)(awLen[1]>>8);
+    abyData[4] = (u8)(awLen[1]&0xFF);
+    abyData[5] = (u8)(awLen[1]>>8);
     abyData[6] = abySignal[1];
     abyData[7] = abyServ[1];
 
-    abyData[8] = (BYTE)(awLen[2]&0xFF);
-    abyData[9] = (BYTE)(awLen[2]>>8);
+    abyData[8] = (u8)(awLen[2]&0xFF);
+    abyData[9] = (u8)(awLen[2]>>8);
     abyData[10] = abySignal[2];
     abyData[11] = abyServ[2];
 
-    abyData[12] = (BYTE)(awLen[3]&0xFF);
-    abyData[13] = (BYTE)(awLen[3]>>8);
+    abyData[12] = (u8)(awLen[3]&0xFF);
+    abyData[13] = (u8)(awLen[3]>>8);
     abyData[14] = abySignal[3];
     abyData[15] = abyServ[3];
 
@@ -500,7 +487,7 @@ void vUpdateIFS(struct vnt_private *pDevice)
         byMaxMin = 5;
     }
     else {// PK_TYPE_11GA & PK_TYPE_11GB
-        BYTE byRate = 0;
+        u8 byRate = 0;
         bool bOFDMRate = false;
 	unsigned int ii = 0;
         PWLAN_IE_SUPP_RATES pItemRates = NULL;
@@ -515,7 +502,7 @@ void vUpdateIFS(struct vnt_private *pDevice)
 
 	pItemRates = (PWLAN_IE_SUPP_RATES)pDevice->vnt_mgmt.abyCurrSuppRates;
         for (ii = 0; ii < pItemRates->len; ii++) {
-            byRate = (BYTE)(pItemRates->abyRates[ii]&0x7F);
+            byRate = (u8)(pItemRates->abyRates[ii]&0x7F);
             if (RATEwGetRateIdx(byRate) > RATE_11M) {
                 bOFDMRate = true;
                 break;
@@ -525,7 +512,7 @@ void vUpdateIFS(struct vnt_private *pDevice)
 		pItemRates = (PWLAN_IE_SUPP_RATES)pDevice->vnt_mgmt
 			.abyCurrExtSuppRates;
             for (ii = 0; ii < pItemRates->len; ii++) {
-                byRate = (BYTE)(pItemRates->abyRates[ii]&0x7F);
+                byRate = (u8)(pItemRates->abyRates[ii]&0x7F);
                 if (RATEwGetRateIdx(byRate) > RATE_11M) {
                     bOFDMRate = true;
                     break;
@@ -544,10 +531,10 @@ void vUpdateIFS(struct vnt_private *pDevice)
     pDevice->uCwMax = C_CWMAX;
     pDevice->uEIFS = C_EIFS;
 
-    byData[0] = (BYTE)pDevice->uSIFS;
-    byData[1] = (BYTE)pDevice->uDIFS;
-    byData[2] = (BYTE)pDevice->uEIFS;
-    byData[3] = (BYTE)pDevice->uSlot;
+    byData[0] = (u8)pDevice->uSIFS;
+    byData[1] = (u8)pDevice->uDIFS;
+    byData[2] = (u8)pDevice->uEIFS;
+    byData[3] = (u8)pDevice->uSlot;
     CONTROLnsRequestOut(pDevice,
                         MESSAGE_TYPE_WRITE,
                         MAC_REG_SIFS,
@@ -571,7 +558,7 @@ void CARDvUpdateBasicTopRate(struct vnt_private *pDevice)
 
      //Determines the highest basic rate.
      for (ii = RATE_54M; ii >= RATE_6M; ii --) {
-         if ( (pDevice->wBasicRate) & ((WORD)(1<<ii)) ) {
+         if ( (pDevice->wBasicRate) & ((u16)(1<<ii)) ) {
              byTopOFDM = ii;
              break;
          }
@@ -579,7 +566,7 @@ void CARDvUpdateBasicTopRate(struct vnt_private *pDevice)
      pDevice->byTopOFDMBasicRate = byTopOFDM;
 
      for (ii = RATE_11M;; ii --) {
-         if ( (pDevice->wBasicRate) & ((WORD)(1<<ii)) ) {
+         if ( (pDevice->wBasicRate) & ((u16)(1<<ii)) ) {
              byTopCCK = ii;
              break;
          }
@@ -617,7 +604,7 @@ int CARDbIsOFDMinBasicRate(struct vnt_private *pDevice)
 	int ii;
 
     for (ii = RATE_54M; ii >= RATE_6M; ii --) {
-        if ((pDevice->wBasicRate) & ((WORD)(1<<ii)))
+        if ((pDevice->wBasicRate) & ((u16)(1<<ii)))
             return true;
     }
     return false;
@@ -627,7 +614,7 @@ u8 CARDbyGetPktType(struct vnt_private *pDevice)
 {
 
     if (pDevice->byBBType == BB_TYPE_11A || pDevice->byBBType == BB_TYPE_11B) {
-        return (BYTE)pDevice->byBBType;
+        return (u8)pDevice->byBBType;
     }
     else if (CARDbIsOFDMinBasicRate(pDevice)) {
         return PK_TYPE_11GA;
@@ -637,7 +624,6 @@ u8 CARDbyGetPktType(struct vnt_private *pDevice)
     }
 }
 
-
 /*
  * Description: Calculate TSF offset of two TSF input
  *              Get TSF Offset from RxBCN's TSF and local TSF
@@ -653,10 +639,10 @@ u8 CARDbyGetPktType(struct vnt_private *pDevice)
  * Return Value: TSF Offset value
  *
  */
-u64 CARDqGetTSFOffset(BYTE byRxRate, u64 qwTSF1, u64 qwTSF2)
+u64 CARDqGetTSFOffset(u8 byRxRate, u64 qwTSF1, u64 qwTSF2)
 {
 	u64 qwTSFOffset = 0;
-	WORD wRxBcnTSFOffst = 0;
+	u16 wRxBcnTSFOffst = 0;
 
 	wRxBcnTSFOffst = cwRXBCNTSFOff[byRxRate % MAX_RATE];
 
@@ -667,8 +653,6 @@ u64 CARDqGetTSFOffset(BYTE byRxRate, u64 qwTSF1, u64 qwTSF2)
 	return qwTSFOffset;
 }
 
-
-
 /*
  * Description: Sync. TSF counter to BSS
  *              Get TSF offset and write to HW
@@ -690,7 +674,6 @@ void CARDvAdjustTSF(struct vnt_private *pDevice, u8 byRxRate,
 	u64 qwTSFOffset = 0;
 	u8 pbyData[8];
 
-
     qwTSFOffset = CARDqGetTSFOffset(byRxRate, qwBSSTimestamp, qwLocalTSF);
     // adjust TSF
     // HW's TSF add TSF Offset reg
@@ -734,7 +717,6 @@ bool CARDbGetCurrentTSF(struct vnt_private *pDevice, u64 *pqwCurrTSF)
 	return true;
 }
 
-
 /*
  * Description: Clear NIC TSF counter
  *              Clear local TSF counter
@@ -770,7 +752,7 @@ bool CARDbClearCurrentTSF(struct vnt_private *pDevice)
  * Return Value: TSF value of next Beacon
  *
  */
-u64 CARDqGetNextTBTT(u64 qwTSF, WORD wBeaconInterval)
+u64 CARDqGetNextTBTT(u64 qwTSF, u16 wBeaconInterval)
 {
 
     unsigned int    uLowNextTBTT;
@@ -796,7 +778,6 @@ u64 CARDqGetNextTBTT(u64 qwTSF, WORD wBeaconInterval)
     return (qwTSF);
 }
 
-
 /*
  * Description: Set NIC TSF counter for first Beacon time
  *              Get NEXTTBTT from adjusted TSF and Beacon Interval
@@ -811,7 +792,7 @@ u64 CARDqGetNextTBTT(u64 qwTSF, WORD wBeaconInterval)
  * Return Value: none
  *
  */
-void CARDvSetFirstNextTBTT(struct vnt_private *pDevice, WORD wBeaconInterval)
+void CARDvSetFirstNextTBTT(struct vnt_private *pDevice, u16 wBeaconInterval)
 {
 	u64 qwNextTBTT = 0;
 	u8 pbyData[8];
@@ -841,7 +822,6 @@ void CARDvSetFirstNextTBTT(struct vnt_private *pDevice, WORD wBeaconInterval)
     return;
 }
 
-
 /*
  * Description: Sync NIC TSF counter for Beacon time
  *              Get NEXTTBTT and write to HW
@@ -883,7 +863,6 @@ void CARDvUpdateNextTBTT(struct vnt_private *pDevice, u64 qwTSF,
                         pbyData
                         );
 
-
 	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
 		"Card:Update Next TBTT[%8lx]\n", (unsigned long)qwTSF);
 
@@ -929,7 +908,6 @@ int CARDbRadioPowerOff(struct vnt_private *pDevice)
     return bResult;
 }
 
-
 /*
  * Description: Turn on Radio power
  *
@@ -996,7 +974,7 @@ void CARDvSetBSSMode(struct vnt_private *pDevice)
     }
 
     vUpdateIFS(pDevice);
-    CARDvSetRSPINF(pDevice, (BYTE)pDevice->byBBType);
+    CARDvSetRSPINF(pDevice, (u8)pDevice->byBBType);
 
     if ( pDevice->byBBType == BB_TYPE_11A ) {
         //request by Jack 2005-04-26
@@ -1016,44 +994,3 @@ void CARDvSetBSSMode(struct vnt_private *pDevice)
         pDevice->abyBBVGA[3] = 0x0;
     }
 }
-
-/*
- *
- * Description:
- *    Do Channel Switch defined in 802.11h
- *
- * Parameters:
- *  In:
- *      hDeviceContext - device structure point
- *  Out:
- *      none
- *
- * Return Value: none.
- *
--*/
-int CARDbChannelSwitch(struct vnt_private *pDevice, u8 byMode,
-	u8 byNewChannel, u8 byCount)
-{
-	int bResult = true;
-
-	if (byCount == 0) {
-		pDevice->vnt_mgmt.uCurrChannel = byNewChannel;
-		CARDbSetMediaChannel(pDevice, byNewChannel);
-		return bResult;
-	}
-    pDevice->byChannelSwitchCount = byCount;
-    pDevice->byNewChannel = byNewChannel;
-    pDevice->bChannelSwitch = true;
-
-    if (byMode == 1) {
-        //bResult=CARDbStopTxPacket(pDevice, PKT_TYPE_802_11_ALL);
-        pDevice->bStopDataPkt = true;
-    }
-	return bResult;
-}
-
-
-
-
-
-
diff --git a/drivers/staging/vt6656/card.h b/drivers/staging/vt6656/card.h
index 5123bc7..c3017a7 100644
--- a/drivers/staging/vt6656/card.h
+++ b/drivers/staging/vt6656/card.h
@@ -29,11 +29,6 @@
 #ifndef __CARD_H__
 #define __CARD_H__
 #include "device.h"
-#include "ttype.h"
-
-/*---------------------  Export Definitions -------------------------*/
-
-/*---------------------  Export Classes  ----------------------------*/
 
 /* init card type */
 
@@ -55,9 +50,6 @@ typedef enum _CARD_OP_MODE {
 #define CB_MAX_CHANNEL_5G       42 /* add channel9(5045MHz), 41==>42 */
 #define CB_MAX_CHANNEL      (CB_MAX_CHANNEL_24G+CB_MAX_CHANNEL_5G)
 
-/*---------------------  Export Variables  --------------------------*/
-
-/*---------------------  Export Functions  --------------------------*/
 struct vnt_private;
 
 void CARDbSetMediaChannel(struct vnt_private *pDevice, u32 uConnectionChannel);
@@ -70,16 +62,14 @@ void CARDvAdjustTSF(struct vnt_private *pDevice, u8 byRxRate,
 		u64 qwBSSTimestamp, u64 qwLocalTSF);
 bool CARDbGetCurrentTSF(struct vnt_private *pDevice, u64 *pqwCurrTSF);
 bool CARDbClearCurrentTSF(struct vnt_private *pDevice);
-void CARDvSetFirstNextTBTT(struct vnt_private *pDevice, WORD wBeaconInterval);
+void CARDvSetFirstNextTBTT(struct vnt_private *pDevice, u16 wBeaconInterval);
 void CARDvUpdateNextTBTT(struct vnt_private *pDevice, u64 qwTSF,
-			 WORD wBeaconInterval);
-u64 CARDqGetNextTBTT(u64 qwTSF, WORD wBeaconInterval);
-u64 CARDqGetTSFOffset(BYTE byRxRate, u64 qwTSF1, u64 qwTSF2);
+			 u16 wBeaconInterval);
+u64 CARDqGetNextTBTT(u64 qwTSF, u16 wBeaconInterval);
+u64 CARDqGetTSFOffset(u8 byRxRate, u64 qwTSF1, u64 qwTSF2);
 int CARDbRadioPowerOff(struct vnt_private *pDevice);
 int CARDbRadioPowerOn(struct vnt_private *pDevice);
 u8 CARDbyGetPktType(struct vnt_private *pDevice);
 void CARDvSetBSSMode(struct vnt_private *pDevice);
-int CARDbChannelSwitch(struct vnt_private *pDevice, u8 byMode,
-	u8 byNewChannel, u8 byCount);
 
 #endif /* __CARD_H__ */
diff --git a/drivers/staging/vt6656/channel.c b/drivers/staging/vt6656/channel.c
index 4181e3e..5158ff4 100644
--- a/drivers/staging/vt6656/channel.c
+++ b/drivers/staging/vt6656/channel.c
@@ -39,15 +39,9 @@
 #include "channel.h"
 #include "rf.h"
 
-/*---------------------  Static Definitions -------------------------*/
 static int          msglevel                = MSG_LEVEL_INFO;
 //static int          msglevel                =MSG_LEVEL_DEBUG;
 
-/*---------------------  Static Classes  ----------------------------*/
-
-/*---------------------  Export Definitions -------------------------*/
-
-
 static SChannelTblElement sChannelTbl[CB_MAX_CHANNEL+1] =
 {
   {0,   0,    false},
@@ -109,17 +103,15 @@ static SChannelTblElement sChannelTbl[CB_MAX_CHANNEL+1] =
   {165, 5825, true}  //56
 };
 
-
-
 /************************************************************************
  * The Radar regulation rules for each country
  ************************************************************************/
 static  struct
 {
-    BYTE    byChannelCountryCode;             /* The country code         */
+    u8    byChannelCountryCode;             /* The country code         */
     char    chCountryCode[2];
-    BYTE    bChannelIdxList[CB_MAX_CHANNEL];  /* Available channels Index */
-    BYTE    byPower[CB_MAX_CHANNEL];
+    u8    bChannelIdxList[CB_MAX_CHANNEL];  /* Available channels Index */
+    u8    byPower[CB_MAX_CHANNEL];
 }   ChannelRuleTab[] =
 {
 /************************************************************************
@@ -368,7 +360,6 @@ static  struct
 /*                                           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  44  45  46  47  48  49  50  51  52  53  54  55  56  */
 };
 
-/*---------------------  Export function  -------------------------*/
 /************************************************************************
  * Country Channel Valid
  *  Input:  CountryCode, ChannelNum
@@ -410,32 +401,6 @@ exit:
 
 } /* end ChannelValid */
 
-/************************************************************************
- * CHvChannelGetList
- * Get Available Channel List for a given country
- * Input:
- *      CountryCode     =   The country code defined in country.h
- * Output:
- *      ChannelBitMask  =   (QWORD *) correspondent bit mask
- *                          of available channels
- *                          0x0000000000000001 means channel 1 is supported
- *                          0x0000000000000003 means channel 1,2 are supported
- *                          0x000000000000000F means channel 1,2,..15 are supported
- ************************************************************************/
-bool
-CHvChannelGetList (
-      unsigned int       uCountryCodeIdx,
-     PBYTE      pbyChannelTable
-    )
-{
-    if (uCountryCodeIdx >= CCODE_MAX) {
-        return (false);
-    }
-    memcpy(pbyChannelTable, ChannelRuleTab[uCountryCodeIdx].bChannelIdxList, CB_MAX_CHANNEL);
-    return (true);
-}
-
-
 void CHvInitChannelTable(struct vnt_private *pDevice)
 {
 	int bMultiBand = false;
@@ -507,15 +472,3 @@ void CHvInitChannelTable(struct vnt_private *pDevice)
         }*/
     }
 }
-
-BYTE CHbyGetChannelMapping(BYTE byChannelNumber)
-{
-BYTE    ii;
-BYTE    byCHMapping = 0;
-
-	for (ii = 1; ii <= CB_MAX_CHANNEL; ii++) {
-		if (sChannelTbl[ii].byChannelNumber == byChannelNumber)
-			byCHMapping = ii;
-    }
-    return byCHMapping;
-}
diff --git a/drivers/staging/vt6656/channel.h b/drivers/staging/vt6656/channel.h
index 9914dba..95701e0 100644
--- a/drivers/staging/vt6656/channel.h
+++ b/drivers/staging/vt6656/channel.h
@@ -31,26 +31,14 @@
 #define _CHANNEL_H_
 
 #include "device.h"
-#include "ttype.h"
-
-/*---------------------  Export Definitions -------------------------*/
-
-/*---------------------  Export Classes  ----------------------------*/
 
 typedef struct tagSChannelTblElement {
-    BYTE    byChannelNumber;
+    u8    byChannelNumber;
     unsigned int    uFrequency;
     bool    bValid;
 } SChannelTblElement, *PSChannelTblElement;
 
-/*---------------------  Export Variables  --------------------------*/
-
-/*---------------------  Export Functions  --------------------------*/
-
 bool    ChannelValid(unsigned int CountryCode, unsigned int ChannelNum);
 void    CHvInitChannelTable(struct vnt_private *pDevice);
-BYTE    CHbyGetChannelMapping(BYTE byChannelNumber);
-
-bool CHvChannelGetList(unsigned int uCountryCodeIdx, PBYTE pbyChannelTable);
 
 #endif  /* _CHANNEL_H_ */
diff --git a/drivers/staging/vt6656/control.c b/drivers/staging/vt6656/control.c
index 743ef5f..026784f 100644
--- a/drivers/staging/vt6656/control.c
+++ b/drivers/staging/vt6656/control.c
@@ -43,18 +43,8 @@
 #include "control.h"
 #include "rndis.h"
 
-/*---------------------  Static Definitions -------------------------*/
 /* static int          msglevel                =MSG_LEVEL_INFO;  */
 /* static int          msglevel                =MSG_LEVEL_DEBUG; */
-/*---------------------  Static Classes  ----------------------------*/
-
-/*---------------------  Static Variables  --------------------------*/
-
-/*---------------------  Static Functions  --------------------------*/
-
-/*---------------------  Export Variables  --------------------------*/
-
-/*---------------------  Export Functions  --------------------------*/
 
 void ControlvWriteByte(struct vnt_private *pDevice, u8 reg, u8 reg_off,
 			u8 data)
diff --git a/drivers/staging/vt6656/control.h b/drivers/staging/vt6656/control.h
index 76ce024..9da9b96 100644
--- a/drivers/staging/vt6656/control.h
+++ b/drivers/staging/vt6656/control.h
@@ -30,12 +30,9 @@
 #ifndef __CONTROL_H__
 #define __CONTROL_H__
 
-#include "ttype.h"
 #include "device.h"
 #include "usbpipe.h"
 
-/*---------------------  Export Definitions -------------------------*/
-
 #define CONTROLnsRequestOut(Device, Request, Value, Index, Length, Buffer) \
 	PIPEnsControlOut(Device, Request, Value, Index, Length, Buffer)
 
@@ -45,12 +42,6 @@
 #define CONTROLnsRequestIn(Device, Request, Value, Index, Length, Buffer) \
 	PIPEnsControlIn(Device, Request, Value, Index, Length, Buffer)
 
-/*---------------------  Export Classes  ----------------------------*/
-
-/*---------------------  Export Variables  --------------------------*/
-
-/*---------------------  Export Functions  --------------------------*/
-
 void ControlvWriteByte(struct vnt_private *pDevice, u8 reg, u8 reg_off,
 			u8 data);
 
@@ -60,5 +51,4 @@ void ControlvReadByte(struct vnt_private *pDevice, u8 reg, u8 reg_off,
 void ControlvMaskByte(struct vnt_private *pDevice, u8 reg_type, u8 reg_off,
 			u8 reg_mask, u8 data);
 
-
 #endif /* __CONTROL_H__ */
diff --git a/drivers/staging/vt6656/country.h b/drivers/staging/vt6656/country.h
index 7bdc8d4..a0320d8 100644
--- a/drivers/staging/vt6656/country.h
+++ b/drivers/staging/vt6656/country.h
@@ -156,7 +156,6 @@ typedef enum _COUNTRY_CODE {
     CCODE_MAX
 } COUNTRY_CODE;
 
-
 /************************************************************************
  * Function prototype
  ************************************************************************/
diff --git a/drivers/staging/vt6656/datarate.c b/drivers/staging/vt6656/datarate.c
index 77464e8..17fbc35 100644
--- a/drivers/staging/vt6656/datarate.c
+++ b/drivers/staging/vt6656/datarate.c
@@ -33,7 +33,6 @@
  *
  */
 
-#include "ttype.h"
 #include "tmacro.h"
 #include "mac.h"
 #include "80211mgr.h"
@@ -44,33 +43,20 @@
 #include "srom.h"
 #include "rf.h"
 
-/*---------------------  Static Definitions -------------------------*/
-
-
-
-
-/*---------------------  Static Classes  ----------------------------*/
-
-
-
-/*---------------------  Static Variables  --------------------------*/
-
 /* static int msglevel = MSG_LEVEL_DEBUG; */
 static int          msglevel                =MSG_LEVEL_INFO;
-const BYTE acbyIERate[MAX_RATE] =
+const u8 acbyIERate[MAX_RATE] =
 {0x02, 0x04, 0x0B, 0x16, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6C};
 
 #define AUTORATE_TXOK_CNT       0x0400
 #define AUTORATE_TXFAIL_CNT     0x0064
 #define AUTORATE_TIMEOUT        10
 
-/*---------------------  Static Functions  --------------------------*/
-
 void s_vResetCounter(PKnownNodeDB psNodeDBTable);
 
 void s_vResetCounter(PKnownNodeDB psNodeDBTable)
 {
-    BYTE            ii;
+    u8            ii;
 
     /* clear statistics counter for auto_rate */
     for (ii = 0; ii <= MAX_RATE; ii++) {
@@ -79,45 +65,6 @@ void s_vResetCounter(PKnownNodeDB psNodeDBTable)
     }
 }
 
-/*---------------------  Export Variables  --------------------------*/
-
-
-/*---------------------  Export Functions  --------------------------*/
-
-
-/*+
- *
- * Description:
- *      Get RateIdx from the value in SuppRates IE or ExtSuppRates IE
- *
- * Parameters:
- *  In:
- *      BYTE    - Rate value in SuppRates IE or ExtSuppRates IE
- *  Out:
- *      none
- *
- * Return Value: RateIdx
- *
--*/
-BYTE
-DATARATEbyGetRateIdx (
-     BYTE byRate
-    )
-{
-    BYTE    ii;
-
-    /* erase BasicRate flag */
-    byRate = byRate & 0x7F;
-
-    for (ii = 0; ii < MAX_RATE; ii ++) {
-        if (acbyIERate[ii] == byRate)
-            return ii;
-    }
-    return 0;
-}
-
-
-
 /*+
  *
  * Routine Description:
@@ -136,9 +83,6 @@ DATARATEbyGetRateIdx (
 #define AUTORATE_TXCNT_THRESHOLD        20
 #define AUTORATE_INC_THRESHOLD          30
 
-
-
-
 /*+
  *
  * Description:
@@ -146,19 +90,19 @@ DATARATEbyGetRateIdx (
  *
  * Parameters:
  *  In:
- *      BYTE    - Rate value in SuppRates IE or ExtSuppRates IE
+ *      u8    - Rate value in SuppRates IE or ExtSuppRates IE
  *  Out:
  *      none
  *
  * Return Value: RateIdx
  *
 -*/
-WORD
+u16
 RATEwGetRateIdx(
-     BYTE byRate
+     u8 byRate
     )
 {
-    WORD    ii;
+    u16    ii;
 
     /* erase BasicRate flag */
     byRate = byRate & 0x7F;
@@ -216,7 +160,7 @@ void RATEvParseMaxRate(struct vnt_private *pDevice,
     }
 
     for (ii = 0; ii < uRateLen; ii++) {
-    	byRate = (BYTE)(pItemRates->abyRates[ii]);
+    	byRate = (u8)(pItemRates->abyRates[ii]);
         if (WLAN_MGMT_IS_BASICRATE(byRate) &&
             (bUpdateBasicRate == true))  {
 	  /*
@@ -226,7 +170,7 @@ void RATEvParseMaxRate(struct vnt_private *pDevice,
 		CARDbAddBasicRate((void *)pDevice, RATEwGetRateIdx(byRate));
             DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ParseMaxRate AddBasicRate: %d\n", RATEwGetRateIdx(byRate));
         }
-        byRate = (BYTE)(pItemRates->abyRates[ii]&0x7F);
+        byRate = (u8)(pItemRates->abyRates[ii]&0x7F);
         if (byHighSuppRate == 0)
             byHighSuppRate = byRate;
         if (byRate > byHighSuppRate)
@@ -242,7 +186,7 @@ void RATEvParseMaxRate(struct vnt_private *pDevice,
             uExtRateLen = WLAN_RATES_MAXLEN;
 
         for (ii = 0; ii < uExtRateLen ; ii++) {
-            byRate = (BYTE)(pItemExtRates->abyRates[ii]);
+            byRate = (u8)(pItemExtRates->abyRates[ii]);
 	    /* select highest basic rate */
             if (WLAN_MGMT_IS_BASICRATE(pItemExtRates->abyRates[ii])) {
 	      /*
@@ -252,7 +196,7 @@ void RATEvParseMaxRate(struct vnt_private *pDevice,
 		    CARDbAddBasicRate((void *)pDevice, RATEwGetRateIdx(byRate));
                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ParseMaxRate AddBasicRate: %d\n", RATEwGetRateIdx(byRate));
             }
-            byRate = (BYTE)(pItemExtRates->abyRates[ii]&0x7F);
+            byRate = (u8)(pItemExtRates->abyRates[ii]&0x7F);
             if (byHighSuppRate == 0)
                 byHighSuppRate = byRate;
             if (byRate > byHighSuppRate)
@@ -282,7 +226,6 @@ void RATEvParseMaxRate(struct vnt_private *pDevice,
      DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Exit ParseMaxRate\n");
 }
 
-
 /*+
  *
  * Routine Description:
@@ -336,7 +279,7 @@ void RATEvTxRateFallBack(struct vnt_private *pDevice,
     for (ii = 0; ii < MAX_RATE; ii++) {
         if (psNodeDBTable->wSuppRate & (0x0001<<ii)) {
             if (bAutoRate[ii] == true) {
-                wIdxUpRate = (WORD) ii;
+                wIdxUpRate = (u16) ii;
             }
         } else {
             bAutoRate[ii] = false;
@@ -363,7 +306,7 @@ void RATEvTxRateFallBack(struct vnt_private *pDevice,
         if ( (dwThroughputTbl[ii] > dwThroughput) &&
              (bAutoRate[ii]==true) ) {
             dwThroughput = dwThroughputTbl[ii];
-            wIdxDownRate = (WORD) ii;
+            wIdxDownRate = (u16) ii;
         }
     }
     psNodeDBTable->wTxDataRate = wIdxDownRate;
@@ -400,7 +343,7 @@ void RATEvTxRateFallBack(struct vnt_private *pDevice,
  * Return Value: None
  *
 -*/
-BYTE
+u8
 RATEuSetIE (
      PWLAN_IE_SUPP_RATES pSrcRates,
      PWLAN_IE_SUPP_RATES pDstRates,
@@ -423,6 +366,6 @@ RATEuSetIE (
             }
         }
     }
-    return (BYTE)uRateCnt;
+    return (u8)uRateCnt;
 }
 
diff --git a/drivers/staging/vt6656/datarate.h b/drivers/staging/vt6656/datarate.h
index 8dc55bd..43cb778 100644
--- a/drivers/staging/vt6656/datarate.h
+++ b/drivers/staging/vt6656/datarate.h
@@ -29,9 +29,6 @@
 #ifndef __DATARATE_H__
 #define __DATARATE_H__
 
-
-/*---------------------  Export Definitions -------------------------*/
-
 #define FALLBACK_PKT_COLLECT_TR_H  50   /* pkts */
 #define FALLBACK_PKT_COLLECT_TR_L  10   /* pkts */
 #define FALLBACK_POLL_SECOND       5    /* 5 sec */
@@ -57,18 +54,6 @@
 #define RATE_AUTO      12
 #define MAX_RATE       12
 
-/*---------------------  Export Classes  ----------------------------*/
-
-/*---------------------  Export Variables  --------------------------*/
-
-
-/*---------------------  Export Types  ------------------------------*/
-
-
-/*---------------------  Export Functions  --------------------------*/
-
-
-
 void RATEvParseMaxRate(struct vnt_private *, PWLAN_IE_SUPP_RATES pItemRates,
 	PWLAN_IE_SUPP_RATES pItemExtRates, int bUpdateBasicRate,
 	u16 *pwMaxBasicRate, u16 *pwMaxSuppRate, u16 *pwSuppRate,
@@ -77,22 +62,16 @@ void RATEvParseMaxRate(struct vnt_private *, PWLAN_IE_SUPP_RATES pItemRates,
 void RATEvTxRateFallBack(struct vnt_private *pDevice,
 	PKnownNodeDB psNodeDBTable);
 
-BYTE
+u8
 RATEuSetIE(
      PWLAN_IE_SUPP_RATES pSrcRates,
      PWLAN_IE_SUPP_RATES pDstRates,
      unsigned int                uRateLen
     );
 
-WORD
+u16
 RATEwGetRateIdx(
-     BYTE byRate
-    );
-
-
-BYTE
-DATARATEbyGetRateIdx(
-     BYTE byRate
+     u8 byRate
     );
 
 #endif /* __DATARATE_H__ */
diff --git a/drivers/staging/vt6656/desc.h b/drivers/staging/vt6656/desc.h
index 0c0b614..64cb046 100644
--- a/drivers/staging/vt6656/desc.h
+++ b/drivers/staging/vt6656/desc.h
@@ -33,7 +33,7 @@
 
 #include <linux/types.h>
 #include <linux/mm.h>
-#include "ttype.h"
+
 #include "tether.h"
 
 /* max transmit or receive buffer size */
@@ -147,38 +147,38 @@
  * RsvTime buffer header
  */
 typedef struct tagSRrvTime_gRTS {
-    WORD        wRTSTxRrvTime_ba;
-    WORD        wRTSTxRrvTime_aa;
-    WORD        wRTSTxRrvTime_bb;
-    WORD        wReserved;
-    WORD        wTxRrvTime_b;
-    WORD        wTxRrvTime_a;
+    u16        wRTSTxRrvTime_ba;
+    u16        wRTSTxRrvTime_aa;
+    u16        wRTSTxRrvTime_bb;
+    u16        wReserved;
+    u16        wTxRrvTime_b;
+    u16        wTxRrvTime_a;
 } __attribute__ ((__packed__))
 SRrvTime_gRTS, *PSRrvTime_gRTS;
 
 typedef const SRrvTime_gRTS *PCSRrvTime_gRTS;
 
 typedef struct tagSRrvTime_gCTS {
-    WORD        wCTSTxRrvTime_ba;
-    WORD        wReserved;
-    WORD        wTxRrvTime_b;
-    WORD        wTxRrvTime_a;
+    u16        wCTSTxRrvTime_ba;
+    u16        wReserved;
+    u16        wTxRrvTime_b;
+    u16        wTxRrvTime_a;
 } __attribute__ ((__packed__))
 SRrvTime_gCTS, *PSRrvTime_gCTS;
 
 typedef const SRrvTime_gCTS *PCSRrvTime_gCTS;
 
 typedef struct tagSRrvTime_ab {
-    WORD        wRTSTxRrvTime;
-    WORD        wTxRrvTime;
+    u16        wRTSTxRrvTime;
+    u16        wTxRrvTime;
 } __attribute__ ((__packed__))
 SRrvTime_ab, *PSRrvTime_ab;
 
 typedef const SRrvTime_ab *PCSRrvTime_ab;
 
 typedef struct tagSRrvTime_atim {
-    WORD        wCTSTxRrvTime_ba;
-    WORD        wTxRrvTime_a;
+    u16        wCTSTxRrvTime_ba;
+    u16        wTxRrvTime_a;
 } __attribute__ ((__packed__))
 SRrvTime_atim, *PSRrvTime_atim;
 
@@ -188,46 +188,46 @@ typedef const SRrvTime_atim *PCSRrvTime_atim;
  * RTS buffer header
  */
 typedef struct tagSRTSData {
-    WORD    wFrameControl;
-    WORD    wDurationID;
-    BYTE    abyRA[ETH_ALEN];
-    BYTE    abyTA[ETH_ALEN];
+    u16    wFrameControl;
+    u16    wDurationID;
+    u8    abyRA[ETH_ALEN];
+    u8    abyTA[ETH_ALEN];
 } __attribute__ ((__packed__))
 SRTSData, *PSRTSData;
 
 typedef const SRTSData *PCSRTSData;
 
 typedef struct tagSRTS_g {
-    BYTE        bySignalField_b;
-    BYTE        byServiceField_b;
-    WORD        wTransmitLength_b;
-    BYTE        bySignalField_a;
-    BYTE        byServiceField_a;
-    WORD        wTransmitLength_a;
-    WORD        wDuration_ba;
-    WORD        wDuration_aa;
-    WORD        wDuration_bb;
-    WORD        wReserved;
+    u8        bySignalField_b;
+    u8        byServiceField_b;
+    u16        wTransmitLength_b;
+    u8        bySignalField_a;
+    u8        byServiceField_a;
+    u16        wTransmitLength_a;
+    u16        wDuration_ba;
+    u16        wDuration_aa;
+    u16        wDuration_bb;
+    u16        wReserved;
     SRTSData    Data;
 } __attribute__ ((__packed__))
 SRTS_g, *PSRTS_g;
 typedef const SRTS_g *PCSRTS_g;
 
 typedef struct tagSRTS_g_FB {
-    BYTE        bySignalField_b;
-    BYTE        byServiceField_b;
-    WORD        wTransmitLength_b;
-    BYTE        bySignalField_a;
-    BYTE        byServiceField_a;
-    WORD        wTransmitLength_a;
-    WORD        wDuration_ba;
-    WORD        wDuration_aa;
-    WORD        wDuration_bb;
-    WORD        wReserved;
-    WORD        wRTSDuration_ba_f0;
-    WORD        wRTSDuration_aa_f0;
-    WORD        wRTSDuration_ba_f1;
-    WORD        wRTSDuration_aa_f1;
+    u8        bySignalField_b;
+    u8        byServiceField_b;
+    u16        wTransmitLength_b;
+    u8        bySignalField_a;
+    u8        byServiceField_a;
+    u16        wTransmitLength_a;
+    u16        wDuration_ba;
+    u16        wDuration_aa;
+    u16        wDuration_bb;
+    u16        wReserved;
+    u16        wRTSDuration_ba_f0;
+    u16        wRTSDuration_aa_f0;
+    u16        wRTSDuration_ba_f1;
+    u16        wRTSDuration_aa_f1;
     SRTSData    Data;
 } __attribute__ ((__packed__))
 SRTS_g_FB, *PSRTS_g_FB;
@@ -235,11 +235,11 @@ SRTS_g_FB, *PSRTS_g_FB;
 typedef const SRTS_g_FB *PCSRTS_g_FB;
 
 typedef struct tagSRTS_ab {
-    BYTE        bySignalField;
-    BYTE        byServiceField;
-    WORD        wTransmitLength;
-    WORD        wDuration;
-    WORD        wReserved;
+    u8        bySignalField;
+    u8        byServiceField;
+    u16        wTransmitLength;
+    u16        wDuration;
+    u16        wReserved;
     SRTSData    Data;
 } __attribute__ ((__packed__))
 SRTS_ab, *PSRTS_ab;
@@ -247,13 +247,13 @@ SRTS_ab, *PSRTS_ab;
 typedef const SRTS_ab *PCSRTS_ab;
 
 typedef struct tagSRTS_a_FB {
-    BYTE        bySignalField;
-    BYTE        byServiceField;
-    WORD        wTransmitLength;
-    WORD        wDuration;
-    WORD        wReserved;
-    WORD        wRTSDuration_f0;
-    WORD        wRTSDuration_f1;
+    u8        bySignalField;
+    u8        byServiceField;
+    u16        wTransmitLength;
+    u16        wDuration;
+    u16        wReserved;
+    u16        wRTSDuration_f0;
+    u16        wRTSDuration_f1;
     SRTSData    Data;
 } __attribute__ ((__packed__))
 SRTS_a_FB, *PSRTS_a_FB;
@@ -264,19 +264,19 @@ typedef const SRTS_a_FB *PCSRTS_a_FB;
  * CTS buffer header
  */
 typedef struct tagSCTSData {
-    WORD    wFrameControl;
-    WORD    wDurationID;
-    BYTE    abyRA[ETH_ALEN];
-    WORD    wReserved;
+    u16    wFrameControl;
+    u16    wDurationID;
+    u8    abyRA[ETH_ALEN];
+    u16    wReserved;
 } __attribute__ ((__packed__))
 SCTSData, *PSCTSData;
 
 typedef struct tagSCTS {
-    BYTE        bySignalField_b;
-    BYTE        byServiceField_b;
-    WORD        wTransmitLength_b;
-    WORD        wDuration_ba;
-    WORD        wReserved;
+    u8        bySignalField_b;
+    u8        byServiceField_b;
+    u16        wTransmitLength_b;
+    u16        wDuration_ba;
+    u16        wReserved;
     SCTSData    Data;
 } __attribute__ ((__packed__))
 SCTS, *PSCTS;
@@ -284,13 +284,13 @@ SCTS, *PSCTS;
 typedef const SCTS *PCSCTS;
 
 typedef struct tagSCTS_FB {
-    BYTE        bySignalField_b;
-    BYTE        byServiceField_b;
-    WORD        wTransmitLength_b;
-    WORD        wDuration_ba;
-    WORD        wReserved;
-    WORD        wCTSDuration_ba_f0;
-    WORD        wCTSDuration_ba_f1;
+    u8        bySignalField_b;
+    u8        byServiceField_b;
+    u16        wTransmitLength_b;
+    u16        wDuration_ba;
+    u16        wReserved;
+    u16        wCTSDuration_ba_f0;
+    u16        wCTSDuration_ba_f1;
     SCTSData    Data;
 } __attribute__ ((__packed__))
 SCTS_FB, *PSCTS_FB;
@@ -302,17 +302,17 @@ typedef const SCTS_FB *PCSCTS_FB;
  */
 typedef struct tagSTxBufHead {
 	u32 adwTxKey[4];
-    WORD    wFIFOCtl;
-    WORD    wTimeStamp;
-    WORD    wFragCtl;
-    WORD    wReserved;
+    u16    wFIFOCtl;
+    u16    wTimeStamp;
+    u16    wFragCtl;
+    u16    wReserved;
 } __attribute__ ((__packed__))
 STxBufHead, *PSTxBufHead;
 typedef const STxBufHead *PCSTxBufHead;
 
 typedef struct tagSTxShortBufHead {
-    WORD    wFIFOCtl;
-    WORD    wTimeStamp;
+    u16    wFIFOCtl;
+    u16    wTimeStamp;
 } __attribute__ ((__packed__))
 STxShortBufHead, *PSTxShortBufHead;
 typedef const STxShortBufHead *PCSTxShortBufHead;
@@ -321,56 +321,56 @@ typedef const STxShortBufHead *PCSTxShortBufHead;
  * TX data header
  */
 typedef struct tagSTxDataHead_g {
-    BYTE    bySignalField_b;
-    BYTE    byServiceField_b;
-    WORD    wTransmitLength_b;
-    BYTE    bySignalField_a;
-    BYTE    byServiceField_a;
-    WORD    wTransmitLength_a;
-    WORD    wDuration_b;
-    WORD    wDuration_a;
-    WORD    wTimeStampOff_b;
-    WORD    wTimeStampOff_a;
+    u8    bySignalField_b;
+    u8    byServiceField_b;
+    u16    wTransmitLength_b;
+    u8    bySignalField_a;
+    u8    byServiceField_a;
+    u16    wTransmitLength_a;
+    u16    wDuration_b;
+    u16    wDuration_a;
+    u16    wTimeStampOff_b;
+    u16    wTimeStampOff_a;
 } __attribute__ ((__packed__))
 STxDataHead_g, *PSTxDataHead_g;
 
 typedef const STxDataHead_g *PCSTxDataHead_g;
 
 typedef struct tagSTxDataHead_g_FB {
-    BYTE    bySignalField_b;
-    BYTE    byServiceField_b;
-    WORD    wTransmitLength_b;
-    BYTE    bySignalField_a;
-    BYTE    byServiceField_a;
-    WORD    wTransmitLength_a;
-    WORD    wDuration_b;
-    WORD    wDuration_a;
-    WORD    wDuration_a_f0;
-    WORD    wDuration_a_f1;
-    WORD    wTimeStampOff_b;
-    WORD    wTimeStampOff_a;
+    u8    bySignalField_b;
+    u8    byServiceField_b;
+    u16    wTransmitLength_b;
+    u8    bySignalField_a;
+    u8    byServiceField_a;
+    u16    wTransmitLength_a;
+    u16    wDuration_b;
+    u16    wDuration_a;
+    u16    wDuration_a_f0;
+    u16    wDuration_a_f1;
+    u16    wTimeStampOff_b;
+    u16    wTimeStampOff_a;
 } __attribute__ ((__packed__))
 STxDataHead_g_FB, *PSTxDataHead_g_FB;
 typedef const STxDataHead_g_FB *PCSTxDataHead_g_FB;
 
 typedef struct tagSTxDataHead_ab {
-    BYTE    bySignalField;
-    BYTE    byServiceField;
-    WORD    wTransmitLength;
-    WORD    wDuration;
-    WORD    wTimeStampOff;
+    u8    bySignalField;
+    u8    byServiceField;
+    u16    wTransmitLength;
+    u16    wDuration;
+    u16    wTimeStampOff;
 } __attribute__ ((__packed__))
 STxDataHead_ab, *PSTxDataHead_ab;
 typedef const STxDataHead_ab *PCSTxDataHead_ab;
 
 typedef struct tagSTxDataHead_a_FB {
-    BYTE    bySignalField;
-    BYTE    byServiceField;
-    WORD    wTransmitLength;
-    WORD    wDuration;
-    WORD    wTimeStampOff;
-    WORD    wDuration_f0;
-    WORD    wDuration_f1;
+    u8    bySignalField;
+    u8    byServiceField;
+    u16    wTransmitLength;
+    u16    wDuration;
+    u16    wTimeStampOff;
+    u16    wDuration_f0;
+    u16    wDuration_f1;
 } __attribute__ ((__packed__))
 STxDataHead_a_FB, *PSTxDataHead_a_FB;
 typedef const STxDataHead_a_FB *PCSTxDataHead_a_FB;
@@ -397,14 +397,14 @@ SBEACONCtl;
 
 typedef struct tagSSecretKey {
 	u32 dwLowDword;
-    BYTE    byHighByte;
+    u8    byHighByte;
 } __attribute__ ((__packed__))
 SSecretKey;
 
 typedef struct tagSKeyEntry {
-    BYTE  abyAddrHi[2];
-    WORD  wKCTL;
-    BYTE  abyAddrLo[4];
+    u8  abyAddrHi[2];
+    u16  wKCTL;
+    u8  abyAddrLo[4];
 	u32 dwKey0[4];
 	u32 dwKey1[4];
 	u32 dwKey2[4];
diff --git a/drivers/staging/vt6656/device.h b/drivers/staging/vt6656/device.h
index 6bba2e0..f07ba24 100644
--- a/drivers/staging/vt6656/device.h
+++ b/drivers/staging/vt6656/device.h
@@ -45,7 +45,6 @@
 #include <linux/timer.h>
 #include <linux/usb.h>
 
-
 #ifdef SIOCETHTOOL
 #define DEVICE_ETHTOOL_IOCTL_SUPPORT
 #include <linux/ethtool.h>
@@ -66,7 +65,6 @@
  */
 
 #include "device_cfg.h"
-#include "ttype.h"
 #include "80211hdr.h"
 #include "tether.h"
 #include "wmgr.h"
@@ -78,7 +76,6 @@
 #include "key.h"
 #include "card.h"
 
-/*---------------------  Export Definitions -------------------------*/
 #define VNT_USB_VENDOR_ID                     0x160a
 #define VNT_USB_PRODUCT_ID                    0x3184
 
@@ -122,7 +119,6 @@
 #define ANT_RXA                 2
 #define ANT_RXB                 3
 
-
 #define MAXCHECKHANGCNT         4
 
 /* Packet type */
@@ -142,8 +138,6 @@
 
 #define PRIVATE_Message                 0
 
-/*---------------------  Export Types  ------------------------------*/
-
 #define DBG_PRT(l, p, args...) { if (l <= msglevel) printk(p, ##args); }
 #define PRINT_K(p, args...) { if (PRIVATE_Message) printk(p, ##args); }
 
@@ -191,7 +185,7 @@ typedef struct _USB_SEND_CONTEXT {
     struct urb      *pUrb;
     unsigned int            uBufLen;
     CONTEXT_TYPE    Type;
-    SEthernetHeader sEthHeader;
+    struct ethhdr sEthHeader;
     void *Next;
     bool            bBoolInUse;
     unsigned char           Data[MAX_TOTAL_SIZE_WITH_ALL_HEADERS];
@@ -212,7 +206,7 @@ typedef struct _DEFAULT_CONFIG {
  */
 typedef struct {
     unsigned int            uDataLen;
-    PBYTE           pDataBuf;
+    u8 *           pDataBuf;
   /* struct urb *pUrb; */
     bool            bInUse;
 } INT_BUFFER, *PINT_BUFFER;
@@ -251,7 +245,6 @@ typedef enum __DEVICE_NDIS_STATUS {
 /* PMKID Structures */
 typedef unsigned char   NDIS_802_11_PMKID_VALUE[16];
 
-
 typedef enum _NDIS_802_11_WEP_STATUS
 {
     Ndis802_11WEPEnabled,
@@ -269,7 +262,6 @@ typedef enum _NDIS_802_11_WEP_STATUS
 } NDIS_802_11_WEP_STATUS, *PNDIS_802_11_WEP_STATUS,
   NDIS_802_11_ENCRYPTION_STATUS, *PNDIS_802_11_ENCRYPTION_STATUS;
 
-
 typedef enum _NDIS_802_11_STATUS_TYPE
 {
 	Ndis802_11StatusType_Authentication,
@@ -284,7 +276,6 @@ typedef struct _PMKID_CANDIDATE {
     unsigned long Flags;
 } PMKID_CANDIDATE, *PPMKID_CANDIDATE;
 
-
 typedef struct _BSSID_INFO
 {
     NDIS_802_11_MAC_ADDRESS BSSID;
@@ -309,16 +300,16 @@ typedef struct tagSPMKIDCandidateEvent {
 
 typedef struct tagSQuietControl {
     bool        bEnable;
-    DWORD       dwStartTime;
-    BYTE        byPeriod;
-    WORD        wDuration;
+    u32       dwStartTime;
+    u8        byPeriod;
+    u16        wDuration;
 } SQuietControl, *PSQuietControl;
 
 /* The receive duplicate detection cache entry */
 typedef struct tagSCacheEntry{
-    WORD        wFmSequence;
-    BYTE        abyAddr2[ETH_ALEN];
-    WORD        wFrameCtl;
+    u16        wFmSequence;
+    u8        abyAddr2[ETH_ALEN];
+    u16        wFrameCtl;
 } SCacheEntry, *PSCacheEntry;
 
 typedef struct tagSCache{
@@ -335,12 +326,12 @@ typedef struct tagSCache{
  */
 typedef struct tagSDeFragControlBlock
 {
-    WORD            wSequence;
-    WORD            wFragNum;
-    BYTE            abyAddr2[ETH_ALEN];
+    u16            wSequence;
+    u16            wFragNum;
+    u8            abyAddr2[ETH_ALEN];
 	unsigned int            uLifetime;
     struct sk_buff* skb;
-    PBYTE           pbyRxBuffer;
+    u8 *           pbyRxBuffer;
     unsigned int            cbFrameLength;
     bool            bInUse;
 } SDeFragControlBlock, *PSDeFragControlBlock;
@@ -371,7 +362,6 @@ typedef struct tagSDeFragControlBlock
 /* for device_set_media_duplex */
 #define     DEVICE_LINK_CHANGE           0x00000001UL
 
-
 typedef struct __device_opt {
 	int nRxDescs0;  /* number of RX descriptors 0 */
 	int nTxDescs0;  /* number of TX descriptors 0, 1, 2, 3 */
@@ -386,7 +376,6 @@ typedef struct __device_opt {
     u32         flags;
 } OPTIONS, *POPTIONS;
 
-
 struct vnt_private {
 	/* netdev */
 	struct usb_device *usb;
@@ -420,7 +409,6 @@ struct vnt_private {
 	u32 cbFreeDFCB;
 	u32 uCurrentDFCBIdx;
 
-
 	/* USB */
 	struct urb *pControlURB;
 	struct urb *pInterruptURB;
@@ -453,7 +441,6 @@ struct vnt_private {
 	/* default config from file by user setting */
 	DEFAULT_CONFIG config_file;
 
-
 	/* Statistic for USB */
 	unsigned long ulBulkInPosted;
 	unsigned long ulBulkInError;
@@ -470,14 +457,12 @@ struct vnt_private {
 	unsigned long ulIntInContCRCError;
 	unsigned long ulIntInBytesRead;
 
-
 	/* Version control */
 	u16 wFirmwareVersion;
 	u8 byLocalID;
 	u8 byRFType;
 	u8 byBBRxConf;
 
-
 	u8 byZoneType;
 	int bZoneRegExist;
 
@@ -571,7 +556,6 @@ struct vnt_private {
 	u8 byTopOFDMBasicRate;
 	u8 byTopCCKBasicRate;
 
-
 	u32 dwAotoRateTxOkCnt;
 	u32 dwAotoRateTxFailCnt;
 	u32 dwErrorRateThreshold[13];
@@ -684,7 +668,6 @@ struct vnt_private {
 	SKeyManagement sKey;
 	u32 dwIVCounter;
 
-
 	RC4Ext SBox;
 	u8 abyPRNG[WLAN_WEPMAX_KEYLEN+3];
 	u8 byKeyIndex;
@@ -701,13 +684,11 @@ struct vnt_private {
 	/* QoS */
 	int bGrpAckPolicy;
 
-
 	u8 byAutoFBCtrl;
 
 	int bTxMICFail;
 	int bRxMICFail;
 
-
 	/* For Update BaseBand VGA Gain Offset */
 	int bUpdateBBVGA;
 	u32 uBBVGADiffCount;
@@ -719,7 +700,6 @@ struct vnt_private {
 	u8 byBBPreEDRSSI;
 	u8 byBBPreEDIndex;
 
-
 	int bRadioCmd;
 	u32 dwDiagRefCount;
 
@@ -747,8 +727,8 @@ struct vnt_private {
 	u8 byReAssocCount;
 	u8 byLinkWaitCount;
 
-	SEthernetHeader sTxEthHeader;
-	SEthernetHeader sRxEthHeader;
+	struct ethhdr sTxEthHeader;
+	struct ethhdr sRxEthHeader;
 	u8 abyBroadcastAddr[ETH_ALEN];
 	u8 abySNAP_RFC1042[ETH_ALEN];
 	u8 abySNAP_Bridgetunnel[ETH_ALEN];
@@ -757,7 +737,6 @@ struct vnt_private {
 	SPMKID gsPMKID;
 	SPMKIDCandidateEvent gsPMKIDCandidate;
 
-
 	/* for 802.11h */
 	int b11hEnable;
 
@@ -788,9 +767,6 @@ struct vnt_private {
 
 };
 
-
-
-
 #define EnqueueRCB(_Head, _Tail, _RCB)                  \
 {                                                       \
     if (!_Head) {                                       \
@@ -812,7 +788,6 @@ struct vnt_private {
     Head = RCB->Next;                                   \
 }
 
-
 #define ADD_ONE_WITH_WRAP_AROUND(uVar, uModulo) {   \
     if ((uVar) >= ((uModulo) - 1))                  \
         (uVar) = 0;                                 \
@@ -820,7 +795,6 @@ struct vnt_private {
         (uVar)++;                                   \
 }
 
-
 #define fMP_RESET_IN_PROGRESS               0x00000001
 #define fMP_DISCONNECTED                    0x00000002
 #define fMP_HALT_IN_PROGRESS                0x00000004
@@ -841,8 +815,6 @@ struct vnt_private {
 #define MP_IS_READY(_M)        (((_M)->Flags & \
                                  (fMP_DISCONNECTED | fMP_RESET_IN_PROGRESS | fMP_HALT_IN_PROGRESS | fMP_INIT_IN_PROGRESS | fMP_SURPRISE_REMOVED)) == 0)
 
-/*---------------------  Export Functions  --------------------------*/
-
 int device_alloc_frag_buf(struct vnt_private *, PSDeFragControlBlock pDeF);
 
 #endif
diff --git a/drivers/staging/vt6656/device_cfg.h b/drivers/staging/vt6656/device_cfg.h
index 62290d0..ea66b97 100644
--- a/drivers/staging/vt6656/device_cfg.h
+++ b/drivers/staging/vt6656/device_cfg.h
@@ -29,8 +29,6 @@
 
 #include <linux/types.h>
 
-#include "ttype.h"
-
 typedef
 struct _version {
     unsigned char   major;
diff --git a/drivers/staging/vt6656/dpc.c b/drivers/staging/vt6656/dpc.c
index e83f95e..7ec166a 100644
--- a/drivers/staging/vt6656/dpc.c
+++ b/drivers/staging/vt6656/dpc.c
@@ -56,32 +56,20 @@
 #include "datarate.h"
 #include "usbpipe.h"
 
-/*---------------------  Static Definitions -------------------------*/
-
-/*---------------------  Static Classes  ----------------------------*/
-
-/*---------------------  Static Variables  --------------------------*/
 //static int          msglevel                =MSG_LEVEL_DEBUG;
 static int          msglevel                =MSG_LEVEL_INFO;
 
-const BYTE acbyRxRate[MAX_RATE] =
+const u8 acbyRxRate[MAX_RATE] =
 {2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108};
 
-
-/*---------------------  Static Functions  --------------------------*/
-
-/*---------------------  Static Definitions -------------------------*/
-
-/*---------------------  Static Functions  --------------------------*/
-
-static BYTE s_byGetRateIdx(BYTE byRate);
+static u8 s_byGetRateIdx(u8 byRate);
 
 static
 void
 s_vGetDASA(
-      PBYTE pbyRxBufferAddr,
+      u8 * pbyRxBufferAddr,
      unsigned int *pcbHeaderSize,
-     PSEthernetHeader psEthHeader
+     struct ethhdr *psEthHeader
     );
 
 static void s_vProcessRxMACHeader(struct vnt_private *pDevice,
@@ -102,8 +90,6 @@ static int s_bHostWepRxEncryption(struct vnt_private *pDevice, u8 *pbyFrame,
 	u32 FrameSize, u8 *pbyRsr, int bOnFly, PSKeyItem pKey, u8 *pbyNewRsr,
 	s32 *pbExtIV, u16 *pwRxTSC15_0, u32 *pdwRxTSC47_16);
 
-/*---------------------  Export Variables  --------------------------*/
-
 /*+
  *
  * Description:
@@ -129,13 +115,12 @@ static void s_vProcessRxMACHeader(struct vnt_private *pDevice,
 	u8 *pbyRxBuffer;
 	u32 cbHeaderSize = 0;
 	u16 *pwType;
-	PS802_11Header pMACHeader;
+	struct ieee80211_hdr *pMACHeader;
 	int ii;
 
+    pMACHeader = (struct ieee80211_hdr *) (pbyRxBufferAddr + cbHeaderSize);
 
-    pMACHeader = (PS802_11Header) (pbyRxBufferAddr + cbHeaderSize);
-
-    s_vGetDASA((PBYTE)pMACHeader, &cbHeaderSize, &pDevice->sRxEthHeader);
+    s_vGetDASA((u8 *)pMACHeader, &cbHeaderSize, &pDevice->sRxEthHeader);
 
     if (bIsWEP) {
         if (bExtIV) {
@@ -150,16 +135,16 @@ static void s_vProcessRxMACHeader(struct vnt_private *pDevice,
         cbHeaderSize += WLAN_HDR_ADDR3_LEN;
     };
 
-    pbyRxBuffer = (PBYTE) (pbyRxBufferAddr + cbHeaderSize);
+    pbyRxBuffer = (u8 *) (pbyRxBufferAddr + cbHeaderSize);
     if (!compare_ether_addr(pbyRxBuffer, &pDevice->abySNAP_Bridgetunnel[0])) {
         cbHeaderSize += 6;
     } else if (!compare_ether_addr(pbyRxBuffer, &pDevice->abySNAP_RFC1042[0])) {
         cbHeaderSize += 6;
-        pwType = (PWORD) (pbyRxBufferAddr + cbHeaderSize);
+        pwType = (u16 *) (pbyRxBufferAddr + cbHeaderSize);
 	if ((*pwType == cpu_to_be16(ETH_P_IPX)) ||
 	    (*pwType == cpu_to_le16(0xF380))) {
 		cbHeaderSize -= 8;
-            pwType = (PWORD) (pbyRxBufferAddr + cbHeaderSize);
+            pwType = (u16 *) (pbyRxBufferAddr + cbHeaderSize);
             if (bIsWEP) {
                 if (bExtIV) {
                     *pwType = htons(cbPacketSize - WLAN_HDR_ADDR3_LEN - 8);    // 8 is IV&ExtIV
@@ -174,7 +159,7 @@ static void s_vProcessRxMACHeader(struct vnt_private *pDevice,
     }
     else {
         cbHeaderSize -= 2;
-        pwType = (PWORD) (pbyRxBufferAddr + cbHeaderSize);
+        pwType = (u16 *) (pbyRxBufferAddr + cbHeaderSize);
         if (bIsWEP) {
             if (bExtIV) {
                 *pwType = htons(cbPacketSize - WLAN_HDR_ADDR3_LEN - 8);    // 8 is IV&ExtIV
@@ -188,21 +173,18 @@ static void s_vProcessRxMACHeader(struct vnt_private *pDevice,
     }
 
     cbHeaderSize -= (ETH_ALEN * 2);
-    pbyRxBuffer = (PBYTE) (pbyRxBufferAddr + cbHeaderSize);
+    pbyRxBuffer = (u8 *) (pbyRxBufferAddr + cbHeaderSize);
     for (ii = 0; ii < ETH_ALEN; ii++)
-        *pbyRxBuffer++ = pDevice->sRxEthHeader.abyDstAddr[ii];
+        *pbyRxBuffer++ = pDevice->sRxEthHeader.h_dest[ii];
     for (ii = 0; ii < ETH_ALEN; ii++)
-        *pbyRxBuffer++ = pDevice->sRxEthHeader.abySrcAddr[ii];
+        *pbyRxBuffer++ = pDevice->sRxEthHeader.h_source[ii];
 
     *pcbHeadSize = cbHeaderSize;
 }
 
-
-
-
-static BYTE s_byGetRateIdx(BYTE byRate)
+static u8 s_byGetRateIdx(u8 byRate)
 {
-    BYTE    byRateIdx;
+    u8    byRateIdx;
 
     for (byRateIdx = 0; byRateIdx <MAX_RATE ; byRateIdx++) {
         if (acbyRxRate[byRateIdx%MAX_RATE] == byRate)
@@ -211,61 +193,59 @@ static BYTE s_byGetRateIdx(BYTE byRate)
     return 0;
 }
 
-
 static
 void
 s_vGetDASA (
-      PBYTE pbyRxBufferAddr,
+      u8 * pbyRxBufferAddr,
      unsigned int *pcbHeaderSize,
-     PSEthernetHeader psEthHeader
+     struct ethhdr *psEthHeader
     )
 {
 	unsigned int            cbHeaderSize = 0;
-	PS802_11Header  pMACHeader;
+	struct ieee80211_hdr *pMACHeader;
 	int             ii;
 
-	pMACHeader = (PS802_11Header) (pbyRxBufferAddr + cbHeaderSize);
+	pMACHeader = (struct ieee80211_hdr *) (pbyRxBufferAddr + cbHeaderSize);
 
-	if ((pMACHeader->wFrameCtl & FC_TODS) == 0) {
-		if (pMACHeader->wFrameCtl & FC_FROMDS) {
+	if ((pMACHeader->frame_control & FC_TODS) == 0) {
+		if (pMACHeader->frame_control & FC_FROMDS) {
 			for (ii = 0; ii < ETH_ALEN; ii++) {
-				psEthHeader->abyDstAddr[ii] =
-					pMACHeader->abyAddr1[ii];
-				psEthHeader->abySrcAddr[ii] =
-					pMACHeader->abyAddr3[ii];
+				psEthHeader->h_dest[ii] =
+					pMACHeader->addr1[ii];
+				psEthHeader->h_source[ii] =
+					pMACHeader->addr3[ii];
 			}
 		} else {
 			/* IBSS mode */
 			for (ii = 0; ii < ETH_ALEN; ii++) {
-				psEthHeader->abyDstAddr[ii] =
-					pMACHeader->abyAddr1[ii];
-				psEthHeader->abySrcAddr[ii] =
-					pMACHeader->abyAddr2[ii];
+				psEthHeader->h_dest[ii] =
+					pMACHeader->addr1[ii];
+				psEthHeader->h_source[ii] =
+					pMACHeader->addr2[ii];
 			}
 		}
 	} else {
 		/* Is AP mode.. */
-		if (pMACHeader->wFrameCtl & FC_FROMDS) {
+		if (pMACHeader->frame_control & FC_FROMDS) {
 			for (ii = 0; ii < ETH_ALEN; ii++) {
-				psEthHeader->abyDstAddr[ii] =
-					pMACHeader->abyAddr3[ii];
-				psEthHeader->abySrcAddr[ii] =
-					pMACHeader->abyAddr4[ii];
+				psEthHeader->h_dest[ii] =
+					pMACHeader->addr3[ii];
+				psEthHeader->h_source[ii] =
+					pMACHeader->addr4[ii];
 				cbHeaderSize += 6;
 			}
 		} else {
 			for (ii = 0; ii < ETH_ALEN; ii++) {
-				psEthHeader->abyDstAddr[ii] =
-					pMACHeader->abyAddr3[ii];
-				psEthHeader->abySrcAddr[ii] =
-					pMACHeader->abyAddr2[ii];
+				psEthHeader->h_dest[ii] =
+					pMACHeader->addr3[ii];
+				psEthHeader->h_source[ii] =
+					pMACHeader->addr2[ii];
 			}
 		}
 	};
     *pcbHeaderSize = cbHeaderSize;
 }
 
-
 int RXbBulkInProcessData(struct vnt_private *pDevice, PRCB pRCB,
 	unsigned long BytesToIndicate)
 {
@@ -273,7 +253,7 @@ int RXbBulkInProcessData(struct vnt_private *pDevice, PRCB pRCB,
 	struct sk_buff *skb;
 	struct vnt_manager *pMgmt = &pDevice->vnt_mgmt;
 	struct vnt_rx_mgmt *pRxPacket = &pMgmt->sRxPacket;
-	PS802_11Header p802_11Header;
+	struct ieee80211_hdr *p802_11Header;
 	u8 *pbyRsr, *pbyNewRsr, *pbyRSSI, *pbyFrame;
 	u64 *pqwTSFTime;
 	u32 bDeFragRx = false;
@@ -297,10 +277,9 @@ int RXbBulkInProcessData(struct vnt_private *pDevice, PRCB pRCB,
 	u8 abyVaildRate[MAX_RATE]
 		= {2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108};
 	u16 wPLCPwithPadding;
-	PS802_11Header pMACHeader;
+	struct ieee80211_hdr *pMACHeader;
 	int bRxeapol_key = false;
 
-
     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---------- RXbBulkInProcessData---\n");
 
     skb = pRCB->skb;
@@ -321,14 +300,14 @@ int RXbBulkInProcessData(struct vnt_private *pDevice, PRCB pRCB,
         return false;
     }
 
-    pbyDAddress = (PBYTE)(skb->data);
+    pbyDAddress = (u8 *)(skb->data);
     pbyRxSts = pbyDAddress+4;
     pbyRxRate = pbyDAddress+5;
 
     //real Frame Size = USBFrameSize -4WbkStatus - 4RxStatus - 8TSF - 4RSR - 4SQ3 - ?Padding
     //if SQ3 the range is 24~27, if no SQ3 the range is 20~23
     //real Frame size in PLCPLength field.
-    pwPLCP_Length = (PWORD) (pbyDAddress + 6);
+    pwPLCP_Length = (u16 *) (pbyDAddress + 6);
     //Fix hardware bug => PLCP_Length error
     if ( ((BytesToIndicate - (*pwPLCP_Length)) > 27) ||
          ((BytesToIndicate - (*pwPLCP_Length)) < 24) ||
@@ -377,45 +356,43 @@ int RXbBulkInProcessData(struct vnt_private *pDevice, PRCB pRCB,
                             FrameSize
                             );
 
-
-    pMACHeader = (PS802_11Header) pbyFrame;
+    pMACHeader = (struct ieee80211_hdr *) pbyFrame;
 
 //mike add: to judge if current AP is activated?
     if ((pMgmt->eCurrMode == WMAC_MODE_STANDBY) ||
         (pMgmt->eCurrMode == WMAC_MODE_ESS_STA)) {
        if (pMgmt->sNodeDBTable[0].bActive) {
-	 if (!compare_ether_addr(pMgmt->abyCurrBSSID, pMACHeader->abyAddr2)) {
+	 if (!compare_ether_addr(pMgmt->abyCurrBSSID, pMACHeader->addr2)) {
 	    if (pMgmt->sNodeDBTable[0].uInActiveCount != 0)
                   pMgmt->sNodeDBTable[0].uInActiveCount = 0;
            }
        }
     }
 
-    if (!is_multicast_ether_addr(pMACHeader->abyAddr1)) {
-        if ( WCTLbIsDuplicate(&(pDevice->sDupRxCache), (PS802_11Header) pbyFrame) ) {
+    if (!is_multicast_ether_addr(pMACHeader->addr1)) {
+        if (WCTLbIsDuplicate(&(pDevice->sDupRxCache), (struct ieee80211_hdr *) pbyFrame)) {
             pDevice->s802_11Counter.FrameDuplicateCount++;
             return false;
         }
 
 	if (compare_ether_addr(pDevice->abyCurrentNetAddr,
-			       pMACHeader->abyAddr1)) {
+			       pMACHeader->addr1)) {
 		return false;
         }
     }
 
-
     // Use for TKIP MIC
     s_vGetDASA(pbyFrame, &cbHeaderSize, &pDevice->sRxEthHeader);
 
-    if (!compare_ether_addr((PBYTE)&(pDevice->sRxEthHeader.abySrcAddr[0]),
+    if (!compare_ether_addr((u8 *)&(pDevice->sRxEthHeader.h_source[0]),
 			    pDevice->abyCurrentNetAddr))
         return false;
 
     if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) || (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA)) {
         if (IS_CTL_PSPOLL(pbyFrame) || !IS_TYPE_CONTROL(pbyFrame)) {
-            p802_11Header = (PS802_11Header) (pbyFrame);
+            p802_11Header = (struct ieee80211_hdr *) (pbyFrame);
             // get SA NodeIndex
-            if (BSSbIsSTAInNodeDB(pDevice, (PBYTE)(p802_11Header->abyAddr2), &iSANodeIndex)) {
+            if (BSSbIsSTAInNodeDB(pDevice, (u8 *)(p802_11Header->addr2), &iSANodeIndex)) {
                 pMgmt->sNodeDBTable[iSANodeIndex].ulLastRxJiffer = jiffies;
                 pMgmt->sNodeDBTable[iSANodeIndex].uInActiveCount = 0;
             }
@@ -428,7 +405,6 @@ int RXbBulkInProcessData(struct vnt_private *pDevice, PRCB pRCB,
         }
     }
 
-
     if (IS_FC_WEP(pbyFrame)) {
         bool     bRxDecryOK = false;
 
@@ -497,7 +473,6 @@ int RXbBulkInProcessData(struct vnt_private *pDevice, PRCB pRCB,
             FrameSize -= 4;         // 4 is ICV
     }
 
-
     //
     // RX OK
     //
@@ -508,7 +483,7 @@ int RXbBulkInProcessData(struct vnt_private *pDevice, PRCB pRCB,
         (IS_FRAGMENT_PKT((pbyFrame)))
         ) {
         // defragment
-        bDeFragRx = WCTLbHandleFragment(pDevice, (PS802_11Header) (pbyFrame), FrameSize, bIsWEP, bExtIV);
+        bDeFragRx = WCTLbHandleFragment(pDevice, (struct ieee80211_hdr *) (pbyFrame), FrameSize, bIsWEP, bExtIV);
         pDevice->s802_11Counter.ReceivedFragmentCount++;
         if (bDeFragRx) {
             // defrag complete
@@ -529,8 +504,8 @@ int RXbBulkInProcessData(struct vnt_private *pDevice, PRCB pRCB,
         // Handle Control & Manage Frame
 
         if (IS_TYPE_MGMT((pbyFrame))) {
-            PBYTE pbyData1;
-            PBYTE pbyData2;
+            u8 * pbyData1;
+            u8 * pbyData2;
 
             pRxPacket = &(pRCB->sMngPacket);
             pRxPacket->p80211Header = (PUWLAN_80211HDR)(pbyFrame);
@@ -622,10 +597,10 @@ int RXbBulkInProcessData(struct vnt_private *pDevice, PRCB pRCB,
             }
    //mike add:station mode check eapol-key challenge--->
    	  {
-   	    BYTE  Protocol_Version;    //802.1x Authentication
-	    BYTE  Packet_Type;           //802.1x Authentication
-	    BYTE  Descriptor_type;
-             WORD Key_info;
+   	    u8  Protocol_Version;    //802.1x Authentication
+	    u8  Packet_Type;           //802.1x Authentication
+	    u8  Descriptor_type;
+             u16 Key_info;
               if (bIsWEP)
                   cbIVOffset = 8;
               else
@@ -653,10 +628,8 @@ int RXbBulkInProcessData(struct vnt_private *pDevice, PRCB pRCB,
         }
     }
 
-
 // Data frame Handle
 
-
     if (pDevice->bEnablePSMode) {
         if (IS_FC_MOREDATA((pbyFrame))) {
             if (*pbyRsr & RSR_ADDROK) {
@@ -699,11 +672,10 @@ int RXbBulkInProcessData(struct vnt_private *pDevice, PRCB pRCB,
     }
 */
 
-
     // -----------------------------------------------
 
     if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) && (pDevice->bEnable8021x == true)){
-        BYTE    abyMacHdr[24];
+        u8    abyMacHdr[24];
 
         // Only 802.1x packet incoming allowed
         if (bIsWEP)
@@ -739,7 +711,6 @@ int RXbBulkInProcessData(struct vnt_private *pDevice, PRCB pRCB,
             return false;
     }
 
-
     if ((pKey != NULL) && (pKey->byCipherSuite == KEY_CTL_TKIP)) {
         if (bIsWEP) {
             FrameSize -= 8;  //MIC
@@ -750,44 +721,42 @@ int RXbBulkInProcessData(struct vnt_private *pDevice, PRCB pRCB,
     // Soft MIC
     if ((pKey != NULL) && (pKey->byCipherSuite == KEY_CTL_TKIP)) {
         if (bIsWEP) {
-            PDWORD          pdwMIC_L;
-            PDWORD          pdwMIC_R;
-            DWORD           dwMIC_Priority;
-            DWORD           dwMICKey0 = 0, dwMICKey1 = 0;
-            DWORD           dwLocalMIC_L = 0;
-            DWORD           dwLocalMIC_R = 0;
-
+            u32 *          pdwMIC_L;
+            u32 *          pdwMIC_R;
+            u32           dwMIC_Priority;
+            u32           dwMICKey0 = 0, dwMICKey1 = 0;
+            u32           dwLocalMIC_L = 0;
+            u32           dwLocalMIC_R = 0;
 
             if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) {
-                dwMICKey0 = cpu_to_le32(*(PDWORD)(&pKey->abyKey[24]));
-                dwMICKey1 = cpu_to_le32(*(PDWORD)(&pKey->abyKey[28]));
+                dwMICKey0 = cpu_to_le32(*(u32 *)(&pKey->abyKey[24]));
+                dwMICKey1 = cpu_to_le32(*(u32 *)(&pKey->abyKey[28]));
             }
             else {
                 if (pMgmt->eAuthenMode == WMAC_AUTH_WPANONE) {
-                    dwMICKey0 = cpu_to_le32(*(PDWORD)(&pKey->abyKey[16]));
-                    dwMICKey1 = cpu_to_le32(*(PDWORD)(&pKey->abyKey[20]));
+                    dwMICKey0 = cpu_to_le32(*(u32 *)(&pKey->abyKey[16]));
+                    dwMICKey1 = cpu_to_le32(*(u32 *)(&pKey->abyKey[20]));
                 } else if ((pKey->dwKeyIndex & BIT28) == 0) {
-                    dwMICKey0 = cpu_to_le32(*(PDWORD)(&pKey->abyKey[16]));
-                    dwMICKey1 = cpu_to_le32(*(PDWORD)(&pKey->abyKey[20]));
+                    dwMICKey0 = cpu_to_le32(*(u32 *)(&pKey->abyKey[16]));
+                    dwMICKey1 = cpu_to_le32(*(u32 *)(&pKey->abyKey[20]));
                 } else {
-                    dwMICKey0 = cpu_to_le32(*(PDWORD)(&pKey->abyKey[24]));
-                    dwMICKey1 = cpu_to_le32(*(PDWORD)(&pKey->abyKey[28]));
+                    dwMICKey0 = cpu_to_le32(*(u32 *)(&pKey->abyKey[24]));
+                    dwMICKey1 = cpu_to_le32(*(u32 *)(&pKey->abyKey[28]));
                 }
             }
 
             MIC_vInit(dwMICKey0, dwMICKey1);
-            MIC_vAppend((PBYTE)&(pDevice->sRxEthHeader.abyDstAddr[0]), 12);
+            MIC_vAppend((u8 *)&(pDevice->sRxEthHeader.h_dest[0]), 12);
             dwMIC_Priority = 0;
-            MIC_vAppend((PBYTE)&dwMIC_Priority, 4);
+            MIC_vAppend((u8 *)&dwMIC_Priority, 4);
             // 4 is Rcv buffer header, 24 is MAC Header, and 8 is IV and Ext IV.
-            MIC_vAppend((PBYTE)(skb->data + 8 + WLAN_HDR_ADDR3_LEN + 8),
+            MIC_vAppend((u8 *)(skb->data + 8 + WLAN_HDR_ADDR3_LEN + 8),
                         FrameSize - WLAN_HDR_ADDR3_LEN - 8);
             MIC_vGetMIC(&dwLocalMIC_L, &dwLocalMIC_R);
             MIC_vUnInit();
 
-            pdwMIC_L = (PDWORD)(skb->data + 8 + FrameSize);
-            pdwMIC_R = (PDWORD)(skb->data + 8 + FrameSize + 4);
-
+            pdwMIC_L = (u32 *)(skb->data + 8 + FrameSize);
+            pdwMIC_R = (u32 *)(skb->data + 8 + FrameSize + 4);
 
             if ((cpu_to_le32(*pdwMIC_L) != dwLocalMIC_L) || (cpu_to_le32(*pdwMIC_R) != dwLocalMIC_R) ||
                 (pDevice->bRxMICFail == true)) {
@@ -818,7 +787,7 @@ int RXbBulkInProcessData(struct vnt_private *pDevice, PRCB pRCB,
 					}
 
 					ev.src_addr.sa_family = ARPHRD_ETHER;
-					memcpy(ev.src_addr.sa_data, pMACHeader->abyAddr2, ETH_ALEN);
+					memcpy(ev.src_addr.sa_data, pMACHeader->addr2, ETH_ALEN);
 					memset(&wrqu, 0, sizeof(wrqu));
 					wrqu.data.length = sizeof(ev);
 			PRINT_K("wireless_send_event--->IWEVMICHAELMICFAILURE\n");
@@ -837,13 +806,13 @@ int RXbBulkInProcessData(struct vnt_private *pDevice, PRCB pRCB,
     if ((pKey != NULL) && ((pKey->byCipherSuite == KEY_CTL_TKIP) ||
                            (pKey->byCipherSuite == KEY_CTL_CCMP))) {
         if (bIsWEP) {
-            WORD        wLocalTSC15_0 = 0;
-            DWORD       dwLocalTSC47_16 = 0;
+            u16        wLocalTSC15_0 = 0;
+            u32       dwLocalTSC47_16 = 0;
 	    unsigned long long       RSC = 0;
             // endian issues
 	    RSC = *((unsigned long long *) &(pKey->KeyRSC));
-            wLocalTSC15_0 = (WORD) RSC;
-            dwLocalTSC47_16 = (DWORD) (RSC>>16);
+            wLocalTSC15_0 = (u16) RSC;
+            dwLocalTSC47_16 = (u32) (RSC>>16);
 
             RSC = dwRxTSC47_16;
             RSC <<= 16;
@@ -876,8 +845,7 @@ int RXbBulkInProcessData(struct vnt_private *pDevice, PRCB pRCB,
         }
     } // ----- End of Reply Counter Check --------------------------
 
-
-    s_vProcessRxMACHeader(pDevice, (PBYTE)(skb->data+8), FrameSize, bIsWEP, bExtIV, &cbHeaderOffset);
+    s_vProcessRxMACHeader(pDevice, (u8 *)(skb->data+8), FrameSize, bIsWEP, bExtIV, &cbHeaderOffset);
     FrameSize -= cbHeaderOffset;
     cbHeaderOffset += 8;        // 8 is Rcv buffer header
 
@@ -928,13 +896,12 @@ static int s_bAPModeRxCtl(struct vnt_private *pDevice, u8 *pbyFrame,
 	s32 iSANodeIndex)
 {
 	struct vnt_manager *pMgmt = &pDevice->vnt_mgmt;
-	PS802_11Header p802_11Header;
+	struct ieee80211_hdr *p802_11Header;
 	CMD_STATUS Status;
 
-
     if (IS_CTL_PSPOLL(pbyFrame) || !IS_TYPE_CONTROL(pbyFrame)) {
 
-        p802_11Header = (PS802_11Header) (pbyFrame);
+        p802_11Header = (struct ieee80211_hdr *) (pbyFrame);
         if (!IS_TYPE_MGMT(pbyFrame)) {
 
             // Data & PS-Poll packet
@@ -946,7 +913,7 @@ static int s_bAPModeRxCtl(struct vnt_private *pDevice, u8 *pbyFrame,
                     // reason = (6) class 2 received from nonauth sta
                     vMgrDeAuthenBeginSta(pDevice,
                                          pMgmt,
-                                         (PBYTE)(p802_11Header->abyAddr2),
+                                         (u8 *)(p802_11Header->addr2),
                                          (WLAN_MGMT_REASON_CLASS2_NONAUTH),
                                          &Status
                                          );
@@ -958,7 +925,7 @@ static int s_bAPModeRxCtl(struct vnt_private *pDevice, u8 *pbyFrame,
                     // reason = (7) class 3 received from nonassoc sta
                     vMgrDisassocBeginSta(pDevice,
                                          pMgmt,
-                                         (PBYTE)(p802_11Header->abyAddr2),
+                                         (u8 *)(p802_11Header->addr2),
                                          (WLAN_MGMT_REASON_CLASS3_NONASSOC),
                                          &Status
                                          );
@@ -1011,18 +978,18 @@ static int s_bAPModeRxCtl(struct vnt_private *pDevice, u8 *pbyFrame,
             else {
                   vMgrDeAuthenBeginSta(pDevice,
                                        pMgmt,
-                                       (PBYTE)(p802_11Header->abyAddr2),
+                                       (u8 *)(p802_11Header->addr2),
                                        (WLAN_MGMT_REASON_CLASS2_NONAUTH),
                                        &Status
                                        );
                     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dpc: send vMgrDeAuthenBeginSta 3\n");
 			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "BSSID:%pM\n",
-				p802_11Header->abyAddr3);
+				p802_11Header->addr3);
 			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ADDR2:%pM\n",
-				p802_11Header->abyAddr2);
+				p802_11Header->addr2);
 			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ADDR1:%pM\n",
-				p802_11Header->abyAddr1);
-                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dpc: wFrameCtl= %x\n", p802_11Header->wFrameCtl );
+				p802_11Header->addr1);
+                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dpc: frame_control= %x\n", p802_11Header->frame_control);
                     return true;
             }
         }
@@ -1042,13 +1009,12 @@ static int s_bHandleRxEncryption(struct vnt_private *pDevice, u8 *pbyFrame,
 	PSKeyItem pKey = NULL;
 	u8 byDecMode = KEY_CTL_WEP;
 
-
     *pwRxTSC15_0 = 0;
     *pdwRxTSC47_16 = 0;
 
     pbyIV = pbyFrame + WLAN_HDR_ADDR3_LEN;
-    if ( WLAN_GET_FC_TODS(*(PWORD)pbyFrame) &&
-         WLAN_GET_FC_FROMDS(*(PWORD)pbyFrame) ) {
+    if ( WLAN_GET_FC_TODS(*(u16 *)pbyFrame) &&
+         WLAN_GET_FC_FROMDS(*(u16 *)pbyFrame) ) {
          pbyIV += 6;             // 6 is 802.11 address4
          PayloadLen -= 6;
     }
@@ -1136,12 +1102,12 @@ static int s_bHandleRxEncryption(struct vnt_private *pDevice, u8 *pbyFrame,
         // TKIP/AES
 
         PayloadLen -= (WLAN_HDR_ADDR3_LEN + 8 + 4); // 24 is 802.11 header, 8 is IV&ExtIV, 4 is crc
-        *pdwRxTSC47_16 = cpu_to_le32(*(PDWORD)(pbyIV + 4));
+        *pdwRxTSC47_16 = cpu_to_le32(*(u32 *)(pbyIV + 4));
 	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ExtIV: %x\n", *pdwRxTSC47_16);
         if (byDecMode == KEY_CTL_TKIP) {
             *pwRxTSC15_0 = cpu_to_le16(MAKEWORD(*(pbyIV+2), *pbyIV));
         } else {
-            *pwRxTSC15_0 = cpu_to_le16(*(PWORD)pbyIV);
+            *pwRxTSC15_0 = cpu_to_le16(*(u16 *)pbyIV);
         }
         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"TSC0_15: %x\n", *pwRxTSC15_0);
 
@@ -1149,8 +1115,8 @@ static int s_bHandleRxEncryption(struct vnt_private *pDevice, u8 *pbyFrame,
             (pDevice->byLocalID <= REV_ID_VT3253_A1)) {
             // Software TKIP
             // 1. 3253 A
-            PS802_11Header  pMACHeader = (PS802_11Header) (pbyFrame);
-            TKIPvMixKey(pKey->abyKey, pMACHeader->abyAddr2, *pwRxTSC15_0, *pdwRxTSC47_16, pDevice->abyPRNG);
+            struct ieee80211_hdr *pMACHeader = (struct ieee80211_hdr *) (pbyFrame);
+            TKIPvMixKey(pKey->abyKey, pMACHeader->addr2, *pwRxTSC15_0, *pdwRxTSC47_16, pDevice->abyPRNG);
             rc4_init(&pDevice->SBox, pDevice->abyPRNG, TKIP_KEY_LEN);
             rc4_encrypt(&pDevice->SBox, pbyIV+8, pbyIV+8, PayloadLen);
             if (ETHbIsBufferCrc32Ok(pbyIV+8, PayloadLen)) {
@@ -1173,7 +1139,7 @@ static int s_bHostWepRxEncryption(struct vnt_private *pDevice, u8 *pbyFrame,
 	s32 *pbExtIV, u16 *pwRxTSC15_0, u32 *pdwRxTSC47_16)
 {
 	struct vnt_manager *pMgmt = &pDevice->vnt_mgmt;
-	PS802_11Header  pMACHeader;
+	struct ieee80211_hdr *pMACHeader;
 	u32 PayloadLen = FrameSize;
 	u8 *pbyIV;
 	u8 byKeyIdx;
@@ -1183,8 +1149,8 @@ static int s_bHostWepRxEncryption(struct vnt_private *pDevice, u8 *pbyFrame,
 	*pdwRxTSC47_16 = 0;
 
     pbyIV = pbyFrame + WLAN_HDR_ADDR3_LEN;
-    if ( WLAN_GET_FC_TODS(*(PWORD)pbyFrame) &&
-         WLAN_GET_FC_FROMDS(*(PWORD)pbyFrame) ) {
+    if ( WLAN_GET_FC_TODS(*(u16 *)pbyFrame) &&
+         WLAN_GET_FC_FROMDS(*(u16 *)pbyFrame) ) {
          pbyIV += 6;             // 6 is 802.11 address4
          PayloadLen -= 6;
     }
@@ -1192,7 +1158,6 @@ static int s_bHostWepRxEncryption(struct vnt_private *pDevice, u8 *pbyFrame,
     byKeyIdx >>= 6;
     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\nKeyIdx: %d\n", byKeyIdx);
 
-
     if (pMgmt->byCSSGK == KEY_CTL_TKIP)
         byDecMode = KEY_CTL_TKIP;
     else if (pMgmt->byCSSGK == KEY_CTL_CCMP)
@@ -1235,13 +1200,13 @@ static int s_bHostWepRxEncryption(struct vnt_private *pDevice, u8 *pbyFrame,
         // TKIP/AES
 
         PayloadLen -= (WLAN_HDR_ADDR3_LEN + 8 + 4); // 24 is 802.11 header, 8 is IV&ExtIV, 4 is crc
-        *pdwRxTSC47_16 = cpu_to_le32(*(PDWORD)(pbyIV + 4));
+        *pdwRxTSC47_16 = cpu_to_le32(*(u32 *)(pbyIV + 4));
 	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ExtIV: %x\n", *pdwRxTSC47_16);
 
         if (byDecMode == KEY_CTL_TKIP) {
             *pwRxTSC15_0 = cpu_to_le16(MAKEWORD(*(pbyIV+2), *pbyIV));
         } else {
-            *pwRxTSC15_0 = cpu_to_le16(*(PWORD)pbyIV);
+            *pwRxTSC15_0 = cpu_to_le16(*(u16 *)pbyIV);
         }
         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"TSC0_15: %x\n", *pwRxTSC15_0);
 
@@ -1252,8 +1217,8 @@ static int s_bHostWepRxEncryption(struct vnt_private *pDevice, u8 *pbyFrame,
                 // 1. 3253 A
                 // 2. NotOnFly
                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"soft KEY_CTL_TKIP \n");
-                pMACHeader = (PS802_11Header) (pbyFrame);
-                TKIPvMixKey(pKey->abyKey, pMACHeader->abyAddr2, *pwRxTSC15_0, *pdwRxTSC47_16, pDevice->abyPRNG);
+                pMACHeader = (struct ieee80211_hdr *) (pbyFrame);
+                TKIPvMixKey(pKey->abyKey, pMACHeader->addr2, *pwRxTSC15_0, *pdwRxTSC47_16, pDevice->abyPRNG);
                 rc4_init(&pDevice->SBox, pDevice->abyPRNG, TKIP_KEY_LEN);
                 rc4_encrypt(&pDevice->SBox, pbyIV+8, pbyIV+8, PayloadLen);
                 if (ETHbIsBufferCrc32Ok(pbyIV+8, PayloadLen)) {
@@ -1297,11 +1262,10 @@ static int s_bAPModeRxData(struct vnt_private *pDevice, struct sk_buff *skb,
 	u8 byMask[8] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80};
 	u16 wAID;
 
-
     if (FrameSize > CB_MAX_BUF_SIZE)
         return false;
     // check DA
-    if (is_multicast_ether_addr((PBYTE)(skb->data+cbHeaderOffset))) {
+    if (is_multicast_ether_addr((u8 *)(skb->data+cbHeaderOffset))) {
        if (pMgmt->sNodeDBTable[0].bPSEnable) {
 
            skbcpy = dev_alloc_skb((int)pDevice->rx_buf_sz);
@@ -1326,7 +1290,7 @@ static int s_bAPModeRxData(struct vnt_private *pDevice, struct sk_buff *skb,
     }
     else {
         // check if relay
-        if (BSSbIsSTAInNodeDB(pDevice, (PBYTE)(skb->data+cbHeaderOffset), &iDANodeIndex)) {
+        if (BSSbIsSTAInNodeDB(pDevice, (u8 *)(skb->data+cbHeaderOffset), &iDANodeIndex)) {
             if (pMgmt->sNodeDBTable[iDANodeIndex].eNodeState >= NODE_ASSOC) {
                 if (pMgmt->sNodeDBTable[iDANodeIndex].bPSEnable) {
                     // queue this skb until next PS tx, and then release.
@@ -1356,7 +1320,7 @@ static int s_bAPModeRxData(struct vnt_private *pDevice, struct sk_buff *skb,
             iDANodeIndex = 0;
 
         if ((pDevice->uAssocCount > 1) && (iDANodeIndex >= 0)) {
-		bRelayPacketSend(pDevice, (PBYTE) (skb->data + cbHeaderOffset),
+		bRelayPacketSend(pDevice, (u8 *) (skb->data + cbHeaderOffset),
 				 FrameSize, (unsigned int) iDANodeIndex);
         }
 
@@ -1370,9 +1334,6 @@ static int s_bAPModeRxData(struct vnt_private *pDevice, struct sk_buff *skb,
     return true;
 }
 
-
-
-
 void RXvWorkItem(struct vnt_private *pDevice)
 {
 	int ntStatus;
@@ -1395,12 +1356,10 @@ void RXvWorkItem(struct vnt_private *pDevice)
 
 }
 
-
 void RXvFreeRCB(PRCB pRCB, int bReAllocSkb)
 {
 	struct vnt_private *pDevice = pRCB->pDevice;
 
-
     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->RXvFreeRCB\n");
 
     ASSERT(!pRCB->Ref);     // should be 0
@@ -1426,7 +1385,6 @@ void RXvFreeRCB(PRCB pRCB, int bReAllocSkb)
     EnqueueRCB(pDevice->FirstRecvFreeList, pDevice->LastRecvFreeList, pRCB);
     pDevice->NumRecvFreeList++;
 
-
     if ((pDevice->Flags & fMP_POST_READS) && MP_IS_READY(pDevice) &&
         (pDevice->bIsRxWorkItemQueued == false) ) {
 
@@ -1436,7 +1394,6 @@ void RXvFreeRCB(PRCB pRCB, int bReAllocSkb)
     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"<----RXFreeRCB %d %d\n",pDevice->NumRecvFreeList, pDevice->NumRecvMngList);
 }
 
-
 void RXvMngWorkItem(struct vnt_private *pDevice)
 {
 	PRCB pRCB = NULL;
@@ -1471,4 +1428,3 @@ void RXvMngWorkItem(struct vnt_private *pDevice)
 
 }
 
-
diff --git a/drivers/staging/vt6656/dpc.h b/drivers/staging/vt6656/dpc.h
index 786c523..876468f 100644
--- a/drivers/staging/vt6656/dpc.h
+++ b/drivers/staging/vt6656/dpc.h
@@ -29,18 +29,9 @@
 #ifndef __DPC_H__
 #define __DPC_H__
 
-#include "ttype.h"
 #include "device.h"
 #include "wcmd.h"
 
-/*---------------------  Export Definitions -------------------------*/
-
-/*---------------------  Export Classes  ----------------------------*/
-
-/*---------------------  Export Variables  --------------------------*/
-
-/*---------------------  Export Functions  --------------------------*/
-
 void RXvWorkItem(void *Context);
 
 void RXvMngWorkItem(void *Context);
diff --git a/drivers/staging/vt6656/firmware.c b/drivers/staging/vt6656/firmware.c
index 4371a77..a1dc3a4 100644
--- a/drivers/staging/vt6656/firmware.c
+++ b/drivers/staging/vt6656/firmware.c
@@ -35,8 +35,6 @@
 #include "control.h"
 #include "rndis.h"
 
-/*---------------------  Static Definitions -------------------------*/
-
 static int          msglevel                =MSG_LEVEL_INFO;
 //static int          msglevel                =MSG_LEVEL_DEBUG;
 
@@ -45,17 +43,6 @@ static int          msglevel                =MSG_LEVEL_INFO;
 
 #define FIRMWARE_CHUNK_SIZE	0x400
 
-/*---------------------  Static Classes  ----------------------------*/
-
-/*---------------------  Static Variables  --------------------------*/
-
-/*---------------------  Static Functions  --------------------------*/
-
-/*---------------------  Export Variables  --------------------------*/
-
-/*---------------------  Export Functions  --------------------------*/
-
-
 int FIRMWAREbDownload(struct vnt_private *pDevice)
 {
 	struct device *dev = &pDevice->usb->dev;
@@ -66,7 +53,6 @@ int FIRMWAREbDownload(struct vnt_private *pDevice)
 	u16 wLength;
 	int ii, rc;
 
-
 	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->Download firmware\n");
 	spin_unlock_irq(&pDevice->lock);
 
@@ -132,7 +118,6 @@ int FIRMWAREbBrach2Sram(struct vnt_private *pDevice)
     }
 }
 
-
 int FIRMWAREbCheckVersion(struct vnt_private *pDevice)
 {
 	int ntStatus;
@@ -142,7 +127,7 @@ int FIRMWAREbCheckVersion(struct vnt_private *pDevice)
                                     0,
                                     MESSAGE_REQUEST_VERSION,
                                     2,
-                                    (PBYTE) &(pDevice->wFirmwareVersion));
+                                    (u8 *) &(pDevice->wFirmwareVersion));
 
     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Firmware Version [%04x]\n", pDevice->wFirmwareVersion);
     if (ntStatus != STATUS_SUCCESS) {
diff --git a/drivers/staging/vt6656/firmware.h b/drivers/staging/vt6656/firmware.h
index ebab3a6..e3b08db 100644
--- a/drivers/staging/vt6656/firmware.h
+++ b/drivers/staging/vt6656/firmware.h
@@ -30,17 +30,8 @@
 #ifndef __FIRMWARE_H__
 #define __FIRMWARE_H__
 
-#include "ttype.h"
 #include "device.h"
 
-/*---------------------  Export Definitions -------------------------*/
-
-/*---------------------  Export Classes  ----------------------------*/
-
-/*---------------------  Export Variables  --------------------------*/
-
-/*---------------------  Export Functions  --------------------------*/
-
 int FIRMWAREbDownload(struct vnt_private *);
 int FIRMWAREbBrach2Sram(struct vnt_private *);
 int FIRMWAREbCheckVersion(struct vnt_private *);
diff --git a/drivers/staging/vt6656/hostap.c b/drivers/staging/vt6656/hostap.c
index bc5e9da..f4f1bf7 100644
--- a/drivers/staging/vt6656/hostap.c
+++ b/drivers/staging/vt6656/hostap.c
@@ -142,7 +142,6 @@ static int hostap_disable_hostapd(struct vnt_private *pDevice, int rtnl_locked)
 	return 0;
 }
 
-
 /*
  * Description:
  *      Set enable/disable hostapd mode
@@ -174,7 +173,6 @@ int vt6656_hostap_set_hostapd(struct vnt_private *pDevice,
 		return hostap_disable_hostapd(pDevice, rtnl_locked);
 }
 
-
 /*
  * Description:
  *      remove station function supported for hostap daemon
@@ -193,7 +191,6 @@ static int hostap_remove_sta(struct vnt_private *pDevice,
 {
 	unsigned int uNodeIndex;
 
-
     if (BSSbIsSTAInNodeDB(pDevice, param->sta_addr, &uNodeIndex)) {
         BSSvRemoveOneNode(pDevice, uNodeIndex);
     }
@@ -242,7 +239,7 @@ static int hostap_add_sta(struct vnt_private *pDevice,
     pMgmt->sNodeDBTable[uNodeIndex].bShortPreamble =
             WLAN_GET_CAP_INFO_SHORTPREAMBLE(pMgmt->sNodeDBTable[uNodeIndex].wCapInfo);
 
-    pMgmt->sNodeDBTable[uNodeIndex].wAID = (WORD)param->u.add_sta.aid;
+    pMgmt->sNodeDBTable[uNodeIndex].wAID = (u16)param->u.add_sta.aid;
 
     pMgmt->sNodeDBTable[uNodeIndex].ulLastRxJiffer = jiffies;
 
@@ -294,7 +291,6 @@ static int hostap_get_info_sta(struct vnt_private *pDevice,
 	return 0;
 }
 
-
 /*
  * Description:
  *      set station flag
@@ -327,8 +323,6 @@ static int hostap_set_flags_sta(struct vnt_private *pDevice,
 	return 0;
 }
 
-
-
 /*
  * Description:
  *      set generic element (wpa ie)
@@ -347,8 +341,6 @@ static int hostap_set_generic_element(struct vnt_private *pDevice,
 {
 	struct vnt_manager *pMgmt = &pDevice->vnt_mgmt;
 
-
-
     memcpy( pMgmt->abyWPAIE,
             param->u.generic_elem.data,
             param->u.generic_elem.len
@@ -425,13 +417,11 @@ static int hostap_set_encryption(struct vnt_private *pDevice,
 	int bKeyTableFull = false;
 	u16 wKeyCtl = 0;
 
-
 	param->u.crypt.err = 0;
 
 	if (param->u.crypt.alg > WPA_ALG_CCMP)
 		return -EINVAL;
 
-
 	if ((param->u.crypt.idx > 3) || (param->u.crypt.key_len > MAX_KEY_LEN)) {
 		param->u.crypt.err = HOSTAP_CRYPT_ERR_KEY_SET_FAILED;
 		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " HOSTAP_CRYPT_ERR_KEY_SET_FAILED\n");
@@ -489,9 +479,9 @@ static int hostap_set_encryption(struct vnt_private *pDevice,
             param->u.crypt.key_len
            );
 
-    dwKeyIndex = (DWORD)(param->u.crypt.idx);
+    dwKeyIndex = (u32)(param->u.crypt.idx);
     if (param->u.crypt.flags & HOSTAP_CRYPT_FLAG_SET_TX_KEY) {
-        pDevice->byKeyIndex = (BYTE)dwKeyIndex;
+        pDevice->byKeyIndex = (u8)dwKeyIndex;
         pDevice->bTransmitKey = true;
         dwKeyIndex |= (1 << 31);
     }
@@ -515,11 +505,10 @@ static int hostap_set_encryption(struct vnt_private *pDevice,
 			&param->sta_addr[0],
 			dwKeyIndex & ~(USE_KEYRSC),
 			param->u.crypt.key_len,
-			&KeyRSC, (PBYTE)abyKey,
+			&KeyRSC, (u8 *)abyKey,
 			KEY_CTL_WEP
                            ) == true) {
 
-
                 pMgmt->sNodeDBTable[iNodeIndex].bOnFly = true;
 
             } else {
@@ -565,7 +554,6 @@ static int hostap_set_encryption(struct vnt_private *pDevice,
         pMgmt->byCSSGK = KEY_CTL_CCMP;
     }
 
-
     if (iNodeIndex == 0) {
        KeybSetDefaultKey(  pDevice,
                            &(pDevice->sKey),
@@ -585,7 +573,7 @@ static int hostap_set_encryption(struct vnt_private *pDevice,
                        dwKeyIndex,
                        param->u.crypt.key_len,
 			&KeyRSC,
-                       (PBYTE)abyKey,
+                       (u8 *)abyKey,
                         byKeyDecMode
                        ) == true) {
 
@@ -631,8 +619,6 @@ static int hostap_set_encryption(struct vnt_private *pDevice,
 	return ret;
 }
 
-
-
 /*
  * Description:
  *      get each stations encryption key
@@ -655,7 +641,6 @@ static int hostap_get_encryption(struct vnt_private *pDevice,
 	int ii;
 	s32 iNodeIndex = 0;
 
-
 	param->u.crypt.err = 0;
 
 	if (is_broadcast_ether_addr(param->sta_addr)) {
@@ -670,13 +655,12 @@ static int hostap_get_encryption(struct vnt_private *pDevice,
 	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "hostap_get_encryption: %d\n", iNodeIndex);
     memset(param->u.crypt.seq, 0, 8);
     for (ii = 0 ; ii < 8 ; ii++) {
-        param->u.crypt.seq[ii] = (BYTE)pMgmt->sNodeDBTable[iNodeIndex].KeyRSC >> (ii * 8);
+        param->u.crypt.seq[ii] = (u8)pMgmt->sNodeDBTable[iNodeIndex].KeyRSC >> (ii * 8);
     }
 
 	return ret;
 }
 
-
 /*
  * Description:
  *      vt6656_hostap_ioctl main function supported for hostap daemon.
@@ -779,7 +763,6 @@ int vt6656_hostap_ioctl(struct vnt_private *pDevice, struct iw_point *p)
 		goto out;
 	}
 
-
 	if ((ret == 0) && ap_ioctl) {
 		if (copy_to_user(p->pointer, param, p->length)) {
 			ret = -EFAULT;
diff --git a/drivers/staging/vt6656/hostap.h b/drivers/staging/vt6656/hostap.h
index f5656cd..6a68f7e 100644
--- a/drivers/staging/vt6656/hostap.h
+++ b/drivers/staging/vt6656/hostap.h
@@ -31,8 +31,6 @@
 
 #include "device.h"
 
-/*---------------------  Export Definitions -------------------------*/
-
 #define WLAN_RATE_1M    BIT0
 #define WLAN_RATE_2M    BIT1
 #define WLAN_RATE_5M5   BIT2
@@ -46,13 +44,6 @@
 #define WLAN_RATE_48M   BIT10
 #define WLAN_RATE_54M   BIT11
 
-
-/*---------------------  Export Classes  ----------------------------*/
-
-/*---------------------  Export Variables  --------------------------*/
-
-/*---------------------  Export Functions  --------------------------*/
-
 #ifndef ETH_P_PAE
 #define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */
 #endif /* ETH_P_PAE */
diff --git a/drivers/staging/vt6656/int.c b/drivers/staging/vt6656/int.c
index 51990bd..a2b4ba6 100644
--- a/drivers/staging/vt6656/int.c
+++ b/drivers/staging/vt6656/int.c
@@ -40,19 +40,8 @@
 #include "bssdb.h"
 #include "usbpipe.h"
 
-/*---------------------  Static Definitions -------------------------*/
 static int msglevel = MSG_LEVEL_INFO; /* MSG_LEVEL_DEBUG */
 
-/*---------------------  Static Classes  ----------------------------*/
-
-/*---------------------  Static Variables  --------------------------*/
-
-/*---------------------  Static Functions  --------------------------*/
-
-/*---------------------  Export Variables  --------------------------*/
-
-/*---------------------  Export Functions  --------------------------*/
-
 /*+
  *
  *  Function:   InterruptPollingThread
@@ -98,8 +87,8 @@ void INTnsProcessData(struct vnt_private *pDevice)
 	pINTData = (PSINTData) pDevice->intBuf.pDataBuf;
 	if (pINTData->byTSR0 & TSR_VALID) {
 		STAvUpdateTDStatCounter(&(pDevice->scStatistic),
-					(BYTE)(pINTData->byPkt0 & 0x0F),
-					(BYTE)(pINTData->byPkt0>>4),
+					(u8)(pINTData->byPkt0 & 0x0F),
+					(u8)(pINTData->byPkt0>>4),
 					pINTData->byTSR0);
 		BSSvUpdateNodeTxCounter(pDevice,
 					&(pDevice->scStatistic),
@@ -109,8 +98,8 @@ void INTnsProcessData(struct vnt_private *pDevice)
 	}
 	if (pINTData->byTSR1 & TSR_VALID) {
 		STAvUpdateTDStatCounter(&(pDevice->scStatistic),
-					(BYTE)(pINTData->byPkt1 & 0x0F),
-					(BYTE)(pINTData->byPkt1>>4),
+					(u8)(pINTData->byPkt1 & 0x0F),
+					(u8)(pINTData->byPkt1>>4),
 					pINTData->byTSR1);
 		BSSvUpdateNodeTxCounter(pDevice,
 					&(pDevice->scStatistic),
@@ -120,8 +109,8 @@ void INTnsProcessData(struct vnt_private *pDevice)
 	}
 	if (pINTData->byTSR2 & TSR_VALID) {
 		STAvUpdateTDStatCounter(&(pDevice->scStatistic),
-					(BYTE)(pINTData->byPkt2 & 0x0F),
-					(BYTE)(pINTData->byPkt2>>4),
+					(u8)(pINTData->byPkt2 & 0x0F),
+					(u8)(pINTData->byPkt2>>4),
 					pINTData->byTSR2);
 		BSSvUpdateNodeTxCounter(pDevice,
 					&(pDevice->scStatistic),
@@ -131,8 +120,8 @@ void INTnsProcessData(struct vnt_private *pDevice)
 	}
 	if (pINTData->byTSR3 & TSR_VALID) {
 		STAvUpdateTDStatCounter(&(pDevice->scStatistic),
-					(BYTE)(pINTData->byPkt3 & 0x0F),
-					(BYTE)(pINTData->byPkt3>>4),
+					(u8)(pINTData->byPkt3 & 0x0F),
+					(u8)(pINTData->byPkt3>>4),
 					pINTData->byTSR3);
 		BSSvUpdateNodeTxCounter(pDevice,
 					&(pDevice->scStatistic),
diff --git a/drivers/staging/vt6656/int.h b/drivers/staging/vt6656/int.h
index 27c725f..8e6e217 100644
--- a/drivers/staging/vt6656/int.h
+++ b/drivers/staging/vt6656/int.h
@@ -30,40 +30,32 @@
 #ifndef __INT_H__
 #define __INT_H__
 
-#include "ttype.h"
 #include "device.h"
 
-/*---------------------  Export Definitions -------------------------*/
 typedef struct tagSINTData {
-	BYTE byTSR0;
-	BYTE byPkt0;
-	WORD wTime0;
-	BYTE byTSR1;
-	BYTE byPkt1;
-	WORD wTime1;
-	BYTE byTSR2;
-	BYTE byPkt2;
-	WORD wTime2;
-	BYTE byTSR3;
-	BYTE byPkt3;
-	WORD wTime3;
+	u8 byTSR0;
+	u8 byPkt0;
+	u16 wTime0;
+	u8 byTSR1;
+	u8 byPkt1;
+	u16 wTime1;
+	u8 byTSR2;
+	u8 byPkt2;
+	u16 wTime2;
+	u8 byTSR3;
+	u8 byPkt3;
+	u16 wTime3;
 	u64 qwTSF;
-	BYTE byISR0;
-	BYTE byISR1;
-	BYTE byRTSSuccess;
-	BYTE byRTSFail;
-	BYTE byACKFail;
-	BYTE byFCSErr;
-	BYTE abySW[2];
+	u8 byISR0;
+	u8 byISR1;
+	u8 byRTSSuccess;
+	u8 byRTSFail;
+	u8 byACKFail;
+	u8 byFCSErr;
+	u8 abySW[2];
 } __attribute__ ((__packed__))
 SINTData, *PSINTData;
 
-/*---------------------  Export Classes  ----------------------------*/
-
-/*---------------------  Export Variables  --------------------------*/
-
-/*---------------------  Export Functions  --------------------------*/
-
 void INTvWorkItem(struct vnt_private *);
 void INTnsProcessData(struct vnt_private *);
 
diff --git a/drivers/staging/vt6656/iocmd.h b/drivers/staging/vt6656/iocmd.h
index c354a77..f3406da 100644
--- a/drivers/staging/vt6656/iocmd.h
+++ b/drivers/staging/vt6656/iocmd.h
@@ -29,10 +29,6 @@
 #ifndef __IOCMD_H__
 #define __IOCMD_H__
 
-#include "ttype.h"
-
-/*---------------------  Export Definitions -------------------------*/
-
 // ioctl Command code
 #define MAGIC_CODE	                 0x3142
 #define IOCTL_CMD_TEST	            (SIOCDEVPRIVATE + 0)
@@ -181,14 +177,12 @@ typedef struct tagSBSSIDItem {
 
 } __packed SBSSIDItem;
 
-
 typedef struct tagSBSSIDList {
 
 	u32		    uItem;
 	SBSSIDItem	sBSSIDList[0];
 } __packed SBSSIDList, *PSBSSIDList;
 
-
 typedef struct tagSNodeItem {
     // STA info
     u16            wAID;
@@ -209,7 +203,6 @@ typedef struct tagSNodeItem {
 
 } __packed SNodeItem;
 
-
 typedef struct tagSNodeList {
 
 	u32		    uItem;
@@ -217,7 +210,6 @@ typedef struct tagSNodeList {
 
 } __packed SNodeList, *PSNodeList;
 
-
 typedef struct tagSCmdLinkStatus {
 
     bool    bLink;
@@ -248,8 +240,6 @@ typedef struct tagSDot11MIBCount {
     u32 FCSErrorCount;
 } __packed SDot11MIBCount, *PSDot11MIBCount;
 
-
-
 //
 // statistic counter
 //
@@ -432,12 +422,4 @@ struct viawget_hostapd_param {
 	} u;
 } __packed;
 
-/*---------------------  Export Classes  ----------------------------*/
-
-/*---------------------  Export Variables  --------------------------*/
-
-/*---------------------  Export Types  ------------------------------*/
-
-/*---------------------  Export Functions  --------------------------*/
-
 #endif /* __IOCMD_H__ */
diff --git a/drivers/staging/vt6656/iowpa.h b/drivers/staging/vt6656/iowpa.h
index 2522dde..97af32e 100644
--- a/drivers/staging/vt6656/iowpa.h
+++ b/drivers/staging/vt6656/iowpa.h
@@ -29,8 +29,6 @@
 #ifndef __IOWPA_H__
 #define __IOWPA_H__
 
-/*---------------------  Export Definitions -------------------------*/
-
 #define WPA_IE_LEN 64
 
 //WPA related
@@ -55,7 +53,6 @@ enum {
 	VIAWGET_SET_DISASSOCIATE = 10
 };
 
-
 enum {
 	VIAWGET_ASSOC_MSG = 1,
 	VIAWGET_DISASSOC_MSG = 2,
@@ -65,8 +62,6 @@ enum {
 	VIAWGET_DEVICECLOSE_MSG = 6
 };
 
-
-
 typedef struct viawget_wpa_header {
 	u8 type;
 	u16 req_ie_len;
@@ -130,12 +125,4 @@ struct viawget_scan_result {
 	int maxrate;
 } __packed;
 
-/*---------------------  Export Classes  ----------------------------*/
-
-/*---------------------  Export Variables  --------------------------*/
-
-/*---------------------  Export Types  ------------------------------*/
-
-/*---------------------  Export Functions  --------------------------*/
-
 #endif /* __IOWPA_H__ */
diff --git a/drivers/staging/vt6656/iwctl.c b/drivers/staging/vt6656/iwctl.c
index 69971f3..c335808 100644
--- a/drivers/staging/vt6656/iwctl.c
+++ b/drivers/staging/vt6656/iwctl.c
@@ -42,7 +42,6 @@
 #include "control.h"
 #include "rndis.h"
 
-
 static const long frequency_list[] = {
 	2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447, 2452, 2457, 2462, 2467, 2472, 2484,
 	4915, 4920, 4925, 4935, 4940, 4945, 4960, 4980,
@@ -61,8 +60,8 @@ struct iw_statistics *iwctl_get_wireless_stats(struct net_device *dev)
 	pDevice->wstats.status = pDevice->eOPMode;
 	if (pDevice->scStatistic.LinkQuality > 100)
 		pDevice->scStatistic.LinkQuality = 100;
-	pDevice->wstats.qual.qual =(BYTE)pDevice->scStatistic.LinkQuality;
-	RFvRSSITodBm(pDevice, (BYTE)(pDevice->uCurrRSSI), &ldBm);
+	pDevice->wstats.qual.qual =(u8)pDevice->scStatistic.LinkQuality;
+	RFvRSSITodBm(pDevice, (u8)(pDevice->uCurrRSSI), &ldBm);
 	pDevice->wstats.qual.level = ldBm;
 	pDevice->wstats.qual.noise = 0;
 	pDevice->wstats.qual.updated = 1;
@@ -95,7 +94,7 @@ int iwctl_siwscan(struct net_device *dev, struct iw_request_info *info,
 	struct iw_point *wrq = &wrqu->data;
 	struct vnt_manager *pMgmt = &pDevice->vnt_mgmt;
 	struct iw_scan_req *req = (struct iw_scan_req *)extra;
-	BYTE abyScanSSID[WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1];
+	u8 abyScanSSID[WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1];
 	PWLAN_IE_SSID pItemSSID = NULL;
 
 	if (!(pDevice->flags & DEVICE_FLAGS_OPENED))
@@ -238,7 +237,7 @@ int iwctl_giwscan(struct net_device *dev, struct iw_request_info *info,
 			// ADD quality
 			memset(&iwe, 0, sizeof(iwe));
 			iwe.cmd = IWEVQUAL;
-			RFvRSSITodBm(pDevice, (BYTE)(pBSS->uRSSI), &ldBm);
+			RFvRSSITodBm(pDevice, (u8)(pBSS->uRSSI), &ldBm);
 			iwe.u.qual.level = ldBm;
 			iwe.u.qual.noise = 0;
 
@@ -357,7 +356,6 @@ int iwctl_giwfreq(struct net_device *dev, struct iw_request_info *info,
 	if (pMgmt == NULL)
 		return -EFAULT;
 
-
 #ifdef WEXT_USECHANNELS
 	wrq->m = (int)pMgmt->uCurrChannel;
 	wrq->e = 0;
@@ -482,7 +480,6 @@ int iwctl_siwmode(struct net_device *dev, struct iw_request_info *info,
 		pDevice->bCommit = false;
 	}
 
-
 	return rc;
 }
 
@@ -532,7 +529,7 @@ int iwctl_giwrange(struct net_device *dev, struct iw_request_info *info,
 	struct iw_range *range = (struct iw_range *)extra;
 	int i;
 	int k;
-	BYTE abySupportedRates[13] = {
+	u8 abySupportedRates[13] = {
 		0x02, 0x04, 0x0B, 0x16, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48,
 		0x60, 0x6C, 0x90
 	};
@@ -635,7 +632,7 @@ int iwctl_siwap(struct net_device *dev, struct iw_request_info *info,
 	struct sockaddr *wrq = &wrqu->ap_addr;
 	struct vnt_manager *pMgmt = &pDevice->vnt_mgmt;
 	int rc = 0;
-	BYTE ZeroBSSID[WLAN_BSSID_LEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+	u8 ZeroBSSID[WLAN_BSSID_LEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
 
 	PRINT_K(" SIOCSIWAP\n");
 
@@ -819,7 +816,7 @@ int iwctl_siwessid(struct net_device *dev, struct iw_request_info *info,
 		if (pDevice->bWPASuppWextEnabled == true)  {
 			/*******search if  in hidden ssid mode ****/
 			PKnownBSS pCurr = NULL;
-			BYTE abyTmpDesireSSID[WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1];
+			u8 abyTmpDesireSSID[WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1];
 			unsigned ii;
 			unsigned uSameBssidNum = 0;
 
@@ -913,7 +910,7 @@ int iwctl_siwrate(struct net_device *dev, struct iw_request_info *info,
 	int rc = 0;
 	u8 brate = 0;
 	int i;
-	BYTE abySupportedRates[13] = {
+	u8 abySupportedRates[13] = {
 		0x02, 0x04, 0x0B, 0x16, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48,
 		0x60, 0x6C, 0x90
 	};
@@ -996,7 +993,7 @@ int iwctl_giwrate(struct net_device *dev, struct iw_request_info *info,
 		return -EFAULT;
 
 	{
-		BYTE abySupportedRates[13] = {
+		u8 abySupportedRates[13] = {
 			0x02, 0x04, 0x0B, 0x16, 0x0c, 0x12, 0x18, 0x24, 0x30,
 			0x48, 0x60, 0x6C, 0x90
 		};
@@ -1227,7 +1224,7 @@ int iwctl_siwencode(struct net_device *dev, struct iw_request_info *info,
 					KEY_CTL_WEP);
 			spin_unlock_irq(&pDevice->lock);
 		}
-		pDevice->byKeyIndex = (BYTE)dwKeyIndex;
+		pDevice->byKeyIndex = (u8)dwKeyIndex;
 		pDevice->uKeyLength = wrq->length;
 		pDevice->bTransmitKey = true;
 		pDevice->bEncryptionEnable = true;
@@ -1317,7 +1314,7 @@ int iwctl_giwencode(struct net_device *dev, struct iw_request_info *info,
 			memcpy(abyKey, pKey->abyKey,	pKey->uKeyLength);
 			memcpy(extra,  abyKey, WLAN_WEP232_KEYLEN);
 		}
-	} else if (KeybGetKey(&(pDevice->sKey), pDevice->abyBroadcastAddr, (BYTE)index, &pKey)) {
+	} else if (KeybGetKey(&(pDevice->sKey), pDevice->abyBroadcastAddr, (u8)index, &pKey)) {
 		wrq->length = pKey->uKeyLength;
 		memcpy(abyKey, pKey->abyKey, pKey->uKeyLength);
 		memcpy(extra, abyKey, WLAN_WEP232_KEYLEN);
@@ -1424,7 +1421,7 @@ int iwctl_giwsens(struct net_device *dev, struct iw_request_info *info,
 
 	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWSENS\n");
 	if (pDevice->bLinkPass == true) {
-		RFvRSSITodBm(pDevice, (BYTE)(pDevice->uCurrRSSI), &ldBm);
+		RFvRSSITodBm(pDevice, (u8)(pDevice->uCurrRSSI), &ldBm);
 		wrq->value = ldBm;
 	} else {
 		wrq->value = 0;
diff --git a/drivers/staging/vt6656/iwctl.h b/drivers/staging/vt6656/iwctl.h
index b594a10..dceda0d 100644
--- a/drivers/staging/vt6656/iwctl.h
+++ b/drivers/staging/vt6656/iwctl.h
@@ -31,14 +31,6 @@
 
 #include "device.h"
 
-/*---------------------  Export Definitions -------------------------*/
-
-/*---------------------  Export Classes  ----------------------------*/
-
-/*---------------------  Export Variables  --------------------------*/
-
-/*---------------------  Export Functions  --------------------------*/
-
 struct iw_statistics *iwctl_get_wireless_stats(struct net_device *dev);
 
 int iwctl_siwap(struct net_device *dev, struct iw_request_info *info,
diff --git a/drivers/staging/vt6656/key.c b/drivers/staging/vt6656/key.c
index 416175e..205590b 100644
--- a/drivers/staging/vt6656/key.c
+++ b/drivers/staging/vt6656/key.c
@@ -42,24 +42,9 @@
 #include "rndis.h"
 #include "control.h"
 
-/*---------------------  Static Definitions -------------------------*/
-
-/*---------------------  Static Classes  ----------------------------*/
-
-/*---------------------  Static Variables  --------------------------*/
 static int          msglevel                =MSG_LEVEL_INFO;
 //static int          msglevel                =MSG_LEVEL_DEBUG;
-/*---------------------  Static Functions  --------------------------*/
-
-/*---------------------  Export Variables  --------------------------*/
-
-/*---------------------  Static Definitions -------------------------*/
-
-/*---------------------  Static Classes  ----------------------------*/
 
-/*---------------------  Static Variables  --------------------------*/
-
-/*---------------------  Static Functions  --------------------------*/
 static void s_vCheckKeyTableValid(struct vnt_private *pDevice,
 	PSKeyManagement pTable)
 {
@@ -79,7 +64,7 @@ static void s_vCheckKeyTableValid(struct vnt_private *pDevice,
             pTable->KeyTable[i].bInUse = false;
             pTable->KeyTable[i].wKeyCtl = 0;
             pTable->KeyTable[i].bSoftWEP = false;
-            pbyData[wLength++] = (BYTE) i;
+            pbyData[wLength++] = (u8) i;
             //MACvDisableKeyEntry(pDevice, i);
         }
     }
@@ -95,10 +80,6 @@ static void s_vCheckKeyTableValid(struct vnt_private *pDevice,
 
 }
 
-
-/*---------------------  Export Functions  --------------------------*/
-
-
 /*
  * Description: Init Key management table
  *
@@ -130,9 +111,9 @@ void KeyvInitTable(struct vnt_private *pDevice, PSKeyManagement pTable)
         pTable->KeyTable[i].wKeyCtl = 0;
         pTable->KeyTable[i].dwGTKeyIndex = 0;
         pTable->KeyTable[i].bSoftWEP = false;
-        pbyData[i] = (BYTE) i;
+        pbyData[i] = (u8) i;
     }
-    pbyData[i] = (BYTE) i;
+    pbyData[i] = (u8) i;
     CONTROLnsRequestOut(pDevice,
                         MESSAGE_TYPE_CLRKEYENTRY,
                         0,
@@ -146,7 +127,6 @@ void KeyvInitTable(struct vnt_private *pDevice, PSKeyManagement pTable)
     return;
 }
 
-
 /*
  * Description: Get Key from table
  *
@@ -197,7 +177,6 @@ int KeybGetKey(PSKeyManagement pTable, u8 *pbyBSSID, u32 dwKeyIndex,
     return (false);
 }
 
-
 /*
  * Description: Set Key to table
  *
@@ -272,7 +251,7 @@ int KeybSetKey(struct vnt_private *pDevice, PSKeyManagement pTable,
                 if (uKeyLength == WLAN_WEP104_KEYLEN)
                     pKey->abyKey[15] |= 0x80;
             }
-            MACvSetKeyEntry(pDevice, pTable->KeyTable[i].wKeyCtl, i, uKeyIdx, pbyBSSID, (PDWORD)pKey->abyKey);
+            MACvSetKeyEntry(pDevice, pTable->KeyTable[i].wKeyCtl, i, uKeyIdx, pbyBSSID, (u32 *)pKey->abyKey);
 
 		if ((dwKeyIndex & USE_KEYRSC) == 0)
 			pKey->KeyRSC = 0; /* RSC set by NIC */
@@ -340,7 +319,7 @@ int KeybSetKey(struct vnt_private *pDevice, PSKeyManagement pTable,
             if (uKeyLength == WLAN_WEP104_KEYLEN)
                 pKey->abyKey[15] |= 0x80;
         }
-        MACvSetKeyEntry(pDevice, pTable->KeyTable[j].wKeyCtl, j, uKeyIdx, pbyBSSID, (PDWORD)pKey->abyKey);
+        MACvSetKeyEntry(pDevice, pTable->KeyTable[j].wKeyCtl, j, uKeyIdx, pbyBSSID, (u32 *)pKey->abyKey);
 
 		if ((dwKeyIndex & USE_KEYRSC) == 0)
 			pKey->KeyRSC = 0; /* RSC set by NIC */
@@ -370,7 +349,6 @@ int KeybSetKey(struct vnt_private *pDevice, PSKeyManagement pTable,
     return (false);
 }
 
-
 /*
  * Description: Remove Key from table
  *
@@ -445,10 +423,8 @@ int KeybRemoveKey(struct vnt_private *pDevice, PSKeyManagement pTable,
     s_vCheckKeyTableValid(pDevice,pTable);
     return bReturnValue;
 
-
 }
 
-
 /*
  * Description: Remove Key from table
  *
@@ -483,45 +459,6 @@ int KeybRemoveAllKey(struct vnt_private *pDevice, PSKeyManagement pTable,
 }
 
 /*
- * Description: Remove WEP Key from table
- *
- * Parameters:
- *  In:
- *      pTable          - Pointer to Key table
- *  Out:
- *      none
- *
- * Return Value: true if success otherwise false
- *
- */
-void KeyvRemoveWEPKey(struct vnt_private *pDevice, PSKeyManagement pTable,
-	u32 dwKeyIndex)
-{
-
-   if ((dwKeyIndex & 0x000000FF) < MAX_GROUP_KEY) {
-        if (pTable->KeyTable[MAX_KEY_TABLE-1].bInUse == true) {
-            if (pTable->KeyTable[MAX_KEY_TABLE-1].GroupKey[dwKeyIndex & 0x000000FF].byCipherSuite == KEY_CTL_WEP) {
-                pTable->KeyTable[MAX_KEY_TABLE-1].GroupKey[dwKeyIndex & 0x000000FF].bKeyValid = false;
-                if ((dwKeyIndex & 0x7FFFFFFF) == (pTable->KeyTable[MAX_KEY_TABLE-1].dwGTKeyIndex & 0x7FFFFFFF)) {
-                    // remove Group transmit key
-                    pTable->KeyTable[MAX_KEY_TABLE-1].dwGTKeyIndex = 0;
-                }
-            }
-        }
-        s_vCheckKeyTableValid(pDevice, pTable);
-    }
-    return;
-}
-
-void KeyvRemoveAllWEPKey(struct vnt_private *pDevice, PSKeyManagement pTable)
-{
-	int i;
-
-	for (i = 0; i < MAX_GROUP_KEY; i++)
-		KeyvRemoveWEPKey(pDevice, pTable, i);
-}
-
-/*
  * Description: Get Transmit Key from table
  *
  * Parameters:
@@ -557,7 +494,6 @@ int KeybGetTransmitKey(PSKeyManagement pTable, u8 *pbyBSSID, u32 dwKeyType,
                     }
                     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n");
 
-
                     return (true);
                 }
                 else {
@@ -599,35 +535,6 @@ int KeybGetTransmitKey(PSKeyManagement pTable, u8 *pbyBSSID, u32 dwKeyType,
     return (false);
 }
 
-
-/*
- * Description: Check Pairwise Key
- *
- * Parameters:
- *  In:
- *      pTable          - Pointer to Key table
- *  Out:
- *      none
- *
- * Return Value: true if found otherwise false
- *
- */
-int KeybCheckPairewiseKey(PSKeyManagement pTable, PSKeyItem *pKey)
-{
-	int i;
-
-	*pKey = NULL;
-
-    for (i=0;i<MAX_KEY_TABLE;i++) {
-        if ((pTable->KeyTable[i].bInUse == true) &&
-            (pTable->KeyTable[i].PairwiseKey.bKeyValid == true)) {
-            *pKey = &(pTable->KeyTable[i].PairwiseKey);
-            return (true);
-        }
-    }
-    return (false);
-}
-
 /*
  * Description: Set Key to table
  *
@@ -707,18 +614,16 @@ int KeybSetDefaultKey(struct vnt_private *pDevice, PSKeyManagement pTable,
             pKey->abyKey[15] |= 0x80;
     }
 
-    MACvSetKeyEntry(pDevice, pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl, MAX_KEY_TABLE-1, uKeyIdx, pTable->KeyTable[MAX_KEY_TABLE-1].abyBSSID, (PDWORD) pKey->abyKey);
+    MACvSetKeyEntry(pDevice, pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl, MAX_KEY_TABLE-1, uKeyIdx, pTable->KeyTable[MAX_KEY_TABLE-1].abyBSSID, (u32 *) pKey->abyKey);
 
 		if ((dwKeyIndex & USE_KEYRSC) == 0)
 			pKey->KeyRSC = 0; /* RSC set by NIC */
 		else
 			pKey->KeyRSC = *KeyRSC;
 
-
     pKey->dwTSC47_16 = 0;
     pKey->wTSC15_0 = 0;
 
-
     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"KeybSetKey(R): \n");
     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->bKeyValid: %d\n", pKey->bKeyValid);
     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->uKeyLength: %d\n", (int)pKey->uKeyLength);
@@ -737,7 +642,6 @@ int KeybSetDefaultKey(struct vnt_private *pDevice, PSKeyManagement pTable,
     return (true);
 }
 
-
 /*
  * Description: Set Key to table
  *
@@ -766,7 +670,6 @@ int KeybSetAllGroupKey(struct vnt_private *pDevice, PSKeyManagement pTable,
 	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Enter KeybSetAllGroupKey: %X\n",
 		dwKeyIndex);
 
-
     if ((dwKeyIndex & PAIRWISE_KEY) != 0) {                  // Pairwise key
         return (false);
     } else if ((dwKeyIndex & 0x000000FF) >= MAX_GROUP_KEY) {
@@ -805,7 +708,7 @@ int KeybSetAllGroupKey(struct vnt_private *pDevice, PSKeyManagement pTable,
                     pKey->abyKey[15] |= 0x80;
             }
 
-            MACvSetKeyEntry(pDevice, pTable->KeyTable[i].wKeyCtl, i, uKeyIdx, pTable->KeyTable[i].abyBSSID, (PDWORD) pKey->abyKey);
+            MACvSetKeyEntry(pDevice, pTable->KeyTable[i].wKeyCtl, i, uKeyIdx, pTable->KeyTable[i].abyBSSID, (u32 *) pKey->abyKey);
 
 		if ((dwKeyIndex & USE_KEYRSC) == 0)
 			pKey->KeyRSC = 0; /* RSC set by NIC */
diff --git a/drivers/staging/vt6656/key.h b/drivers/staging/vt6656/key.h
index 7ecddcd..23e188d 100644
--- a/drivers/staging/vt6656/key.h
+++ b/drivers/staging/vt6656/key.h
@@ -30,17 +30,14 @@
 #ifndef __KEY_H__
 #define __KEY_H__
 
-#include "ttype.h"
 #include "tether.h"
 #include "80211mgr.h"
 
-/*---------------------  Export Definitions -------------------------*/
 #define MAX_GROUP_KEY       4
 #define MAX_KEY_TABLE       11
 #define MAX_KEY_LEN         32
 #define AES_KEY_LEN         16
 
-
 #define AUTHENTICATOR_KEY   0x10000000
 #define USE_KEYRSC          0x20000000
 #define PAIRWISE_KEY        0x40000000
@@ -54,32 +51,31 @@
 #define KEY_CTL_CCMP        0x03
 #define KEY_CTL_INVALID     0xFF
 
-
 typedef struct tagSKeyItem
 {
     bool        bKeyValid;
 	u32 uKeyLength;
-    BYTE        abyKey[MAX_KEY_LEN];
+    u8        abyKey[MAX_KEY_LEN];
 	u64 KeyRSC;
-    DWORD       dwTSC47_16;
-    WORD        wTSC15_0;
-    BYTE        byCipherSuite;
-    BYTE        byReserved0;
-    DWORD       dwKeyIndex;
+    u32       dwTSC47_16;
+    u16        wTSC15_0;
+    u8        byCipherSuite;
+    u8        byReserved0;
+    u32       dwKeyIndex;
     void *pvKeyTable;
 } SKeyItem, *PSKeyItem; //64
 
 typedef struct tagSKeyTable
 {
-    BYTE        abyBSSID[ETH_ALEN];  /* 6 */
-    BYTE        byReserved0[2];              //8
+    u8        abyBSSID[ETH_ALEN];  /* 6 */
+    u8        byReserved0[2];              //8
     SKeyItem    PairwiseKey;
     SKeyItem    GroupKey[MAX_GROUP_KEY]; //64*5 = 320, 320+8=328
-    DWORD       dwGTKeyIndex;            // GroupTransmitKey Index
+    u32       dwGTKeyIndex;            // GroupTransmitKey Index
     bool        bInUse;
-    WORD        wKeyCtl;
+    u16        wKeyCtl;
     bool        bSoftWEP;
-    BYTE        byReserved1[6];
+    u8        byReserved1[6];
 } SKeyTable, *PSKeyTable; //352
 
 typedef struct tagSKeyManagement
@@ -87,16 +83,6 @@ typedef struct tagSKeyManagement
     SKeyTable   KeyTable[MAX_KEY_TABLE];
 } SKeyManagement, *PSKeyManagement;
 
-/*---------------------  Export Types  ------------------------------*/
-
-/*---------------------  Export Macros ------------------------------*/
-
-/*---------------------  Export Classes  ----------------------------*/
-
-/*---------------------  Export Variables  --------------------------*/
-
-/*---------------------  Export Functions  --------------------------*/
-
 void KeyvInitTable(struct vnt_private *, PSKeyManagement pTable);
 
 int KeybGetKey(PSKeyManagement pTable, u8 *pbyBSSID, u32 dwKeyIndex,
@@ -112,16 +98,9 @@ int KeybRemoveKey(struct vnt_private *, PSKeyManagement pTable,
 int KeybRemoveAllKey(struct vnt_private *, PSKeyManagement pTable,
 	u8 *pbyBSSID);
 
-void KeyvRemoveWEPKey(struct vnt_private *, PSKeyManagement pTable,
-	u32 dwKeyIndex);
-
-void KeyvRemoveAllWEPKey(struct vnt_private *, PSKeyManagement pTable);
-
 int KeybGetTransmitKey(PSKeyManagement pTable, u8 *pbyBSSID, u32 dwKeyType,
 	PSKeyItem *pKey);
 
-int KeybCheckPairewiseKey(PSKeyManagement pTable, PSKeyItem *pKey);
-
 int KeybSetDefaultKey(struct vnt_private *, PSKeyManagement pTable,
 	u32 dwKeyIndex, u32 uKeyLength, u64 *KeyRSC, u8 *pbyKey,
 	u8 byKeyDecMode);
diff --git a/drivers/staging/vt6656/mac.c b/drivers/staging/vt6656/mac.c
index 76d307b..343db19 100644
--- a/drivers/staging/vt6656/mac.c
+++ b/drivers/staging/vt6656/mac.c
@@ -38,63 +38,8 @@
 #include "rndis.h"
 #include "control.h"
 
-/*---------------------  Static Definitions -------------------------*/
 //static int          msglevel                =MSG_LEVEL_DEBUG;
 static int          msglevel                =MSG_LEVEL_INFO;
-/*---------------------  Static Classes  ----------------------------*/
-
-/*---------------------  Static Variables  --------------------------*/
-
-/*---------------------  Static Functions  --------------------------*/
-
-/*---------------------  Export Variables  --------------------------*/
-
-/*---------------------  Export Functions  --------------------------*/
-
-
-
-
-
-/*
- * Description:
- *      Set this hash index into multicast address register bit
- *
- * Parameters:
- *  In:
- *      byHashIdx   - Hash index to set
- *  Out:
- *      none
- *
- * Return Value: none
- *
- */
-void MACvSetMultiAddrByHash(struct vnt_private *pDevice, u8 byHashIdx)
-{
-	u8 uByteIdx;
-	u8 byBitMask;
-	u8 pbyData[2];
-
-
-    // calculate byte position
-    uByteIdx = byHashIdx / 8;
-
-    // calculate bit position
-    byBitMask = 1;
-    byBitMask <<= (byHashIdx % 8);
-    // turn on the bit
-
-    pbyData[0] = byBitMask;
-    pbyData[1] = byBitMask;
-
-    CONTROLnsRequestOut(pDevice,
-                        MESSAGE_TYPE_WRITE_MASK,
-                        (WORD) (MAC_REG_MAR0 + uByteIdx),
-                        MESSAGE_REQUEST_MACREG,
-                        2,
-                        pbyData);
-}
-
-
 
 /*
  * Description:
@@ -117,13 +62,12 @@ void MACvWriteMultiAddr(struct vnt_private *pDevice, u32 uByteIdx, u8 byData)
     byData1 = byData;
     CONTROLnsRequestOut(pDevice,
                         MESSAGE_TYPE_WRITE,
-                        (WORD) (MAC_REG_MAR0 + uByteIdx),
+                        (u16) (MAC_REG_MAR0 + uByteIdx),
                         MESSAGE_REQUEST_MACREG,
                         1,
                         &byData1);
 }
 
-
 /*
  * Description:
  *      Shut Down MAC
@@ -150,7 +94,6 @@ void MACvSetBBType(struct vnt_private *pDevice, u8 byType)
 {
 	u8 pbyData[2];
 
-
     pbyData[0] = byType;
     pbyData[1] = EnCFG_BBType_MASK;
 
@@ -163,26 +106,6 @@ void MACvSetBBType(struct vnt_private *pDevice, u8 byType)
                         );
 }
 
-void MACvSetMISCFifo(struct vnt_private *pDevice, u16 wOffset, u32 dwData)
-{
-	u8 pbyData[4];
-
-    if (wOffset > 273)
-        return;
-    pbyData[0] = (BYTE)dwData;
-    pbyData[1] = (BYTE)(dwData>>8);
-    pbyData[2] = (BYTE)(dwData>>16);
-    pbyData[3] = (BYTE)(dwData>>24);
-
-    CONTROLnsRequestOut(pDevice,
-                        MESSAGE_TYPE_WRITE_MISCFF,
-                        wOffset,
-                        0,
-                        4,
-                        pbyData
-                        );
-}
-
 /*
  * Description:
  *      Disable the Key Entry by MISCFIFO
@@ -202,8 +125,7 @@ void MACvDisableKeyEntry(struct vnt_private *pDevice, u32 uEntryIdx)
 	u16 wOffset;
 	u8 byData;
 
-
-    byData = (BYTE) uEntryIdx;
+    byData = (u8) uEntryIdx;
 
     wOffset = MISCFIFO_KEYETRY0;
     wOffset += (uEntryIdx * MISCFIFO_KEYENTRYSIZE);
@@ -222,7 +144,6 @@ void MACvDisableKeyEntry(struct vnt_private *pDevice, u32 uEntryIdx)
                         );
 }
 
-
 /*
  * Description:
  *      Set the Key by MISCFIFO
@@ -294,31 +215,29 @@ void MACvSetKeyEntry(struct vnt_private *pDevice, u16 wKeyCtl, u32 uEntryIdx,
         VNSvOutPortW(dwIoBase + MAC_REG_MISCFFCTL, MISCFFCTL_WRITE);
     }
 */
-    pbyKey = (PBYTE)pdwKey;
-
-    pbyData[0] = (BYTE)dwData1;
-    pbyData[1] = (BYTE)(dwData1>>8);
-    pbyData[2] = (BYTE)(dwData1>>16);
-    pbyData[3] = (BYTE)(dwData1>>24);
-    pbyData[4] = (BYTE)dwData2;
-    pbyData[5] = (BYTE)(dwData2>>8);
-    pbyData[6] = (BYTE)(dwData2>>16);
-    pbyData[7] = (BYTE)(dwData2>>24);
+    pbyKey = (u8 *)pdwKey;
+
+    pbyData[0] = (u8)dwData1;
+    pbyData[1] = (u8)(dwData1>>8);
+    pbyData[2] = (u8)(dwData1>>16);
+    pbyData[3] = (u8)(dwData1>>24);
+    pbyData[4] = (u8)dwData2;
+    pbyData[5] = (u8)(dwData2>>8);
+    pbyData[6] = (u8)(dwData2>>16);
+    pbyData[7] = (u8)(dwData2>>24);
     for (ii = 8; ii < 24; ii++)
 	pbyData[ii] = *pbyKey++;
 
     CONTROLnsRequestOut(pDevice,
                         MESSAGE_TYPE_SETKEY,
                         wOffset,
-                        (WORD)uKeyIdx,
+                        (u16)uKeyIdx,
                         24,
                         pbyData
                         );
 
-
 }
 
-
 void MACvRegBitsOff(struct vnt_private *pDevice, u8 byRegOfs, u8 byBits)
 {
 	u8 pbyData[2];
@@ -335,12 +254,10 @@ void MACvRegBitsOff(struct vnt_private *pDevice, u8 byRegOfs, u8 byBits)
                         );
 }
 
-
 void MACvRegBitsOn(struct vnt_private *pDevice, u8 byRegOfs, u8 byBits)
 {
 	u8 pbyData[2];
 
-
     pbyData[0] = byBits;
     pbyData[1] = byBits;
 
@@ -357,9 +274,8 @@ void MACvWriteWord(struct vnt_private *pDevice, u8 byRegOfs, u16 wData)
 {
 	u8 pbyData[2];
 
-
-    pbyData[0] = (BYTE)(wData & 0xff);
-    pbyData[1] = (BYTE)(wData >> 8);
+    pbyData[0] = (u8)(wData & 0xff);
+    pbyData[1] = (u8)(wData >> 8);
 
     CONTROLnsRequestOut(pDevice,
                         MESSAGE_TYPE_WRITE,
@@ -375,13 +291,12 @@ void MACvWriteBSSIDAddress(struct vnt_private *pDevice, u8 *pbyEtherAddr)
 {
 	u8 pbyData[6];
 
-
-    pbyData[0] = *((PBYTE)pbyEtherAddr);
-    pbyData[1] = *((PBYTE)pbyEtherAddr+1);
-    pbyData[2] = *((PBYTE)pbyEtherAddr+2);
-    pbyData[3] = *((PBYTE)pbyEtherAddr+3);
-    pbyData[4] = *((PBYTE)pbyEtherAddr+4);
-    pbyData[5] = *((PBYTE)pbyEtherAddr+5);
+    pbyData[0] = *((u8 *)pbyEtherAddr);
+    pbyData[1] = *((u8 *)pbyEtherAddr+1);
+    pbyData[2] = *((u8 *)pbyEtherAddr+2);
+    pbyData[3] = *((u8 *)pbyEtherAddr+3);
+    pbyData[4] = *((u8 *)pbyEtherAddr+4);
+    pbyData[5] = *((u8 *)pbyEtherAddr+5);
 
     CONTROLnsRequestOut(pDevice,
                         MESSAGE_TYPE_WRITE,
@@ -396,7 +311,6 @@ void MACvEnableProtectMD(struct vnt_private *pDevice)
 {
 	u8 pbyData[2];
 
-
     pbyData[0] = EnCFG_ProtectMd;
     pbyData[1] = EnCFG_ProtectMd;
 
@@ -413,7 +327,6 @@ void MACvDisableProtectMD(struct vnt_private *pDevice)
 {
 	u8 pbyData[2];
 
-
     pbyData[0] = 0;
     pbyData[1] = EnCFG_ProtectMd;
 
@@ -430,7 +343,6 @@ void MACvEnableBarkerPreambleMd(struct vnt_private *pDevice)
 {
 	u8 pbyData[2];
 
-
     pbyData[0] = EnCFG_BarkerPream;
     pbyData[1] = EnCFG_BarkerPream;
 
@@ -447,7 +359,6 @@ void MACvDisableBarkerPreambleMd(struct vnt_private *pDevice)
 {
 	u8 pbyData[2];
 
-
     pbyData[0] = 0;
     pbyData[1] = EnCFG_BarkerPream;
 
@@ -460,7 +371,6 @@ void MACvDisableBarkerPreambleMd(struct vnt_private *pDevice)
                         );
 }
 
-
 void MACvWriteBeaconInterval(struct vnt_private *pDevice, u16 wInterval)
 {
 	u8 pbyData[2];
diff --git a/drivers/staging/vt6656/mac.h b/drivers/staging/vt6656/mac.h
index 6e28500..0db1be5 100644
--- a/drivers/staging/vt6656/mac.h
+++ b/drivers/staging/vt6656/mac.h
@@ -34,12 +34,9 @@
 #ifndef __MAC_H__
 #define __MAC_H__
 
-#include "ttype.h"
 #include "device.h"
 #include "tmacro.h"
 
-/*---------------------  Export Definitions -------------------------*/
-
 #define REV_ID_VT3253_A0    0x00
 #define REV_ID_VT3253_A1    0x01
 #define REV_ID_VT3253_B0    0x08
@@ -156,7 +153,6 @@
 #define MAC_REG_RSPINF_A_54 0xFA
 #define MAC_REG_RSPINF_A_72 0xFC
 
-
 //
 // Bits in the I2MCFG EEPROM register
 //
@@ -281,7 +277,6 @@
 #define TCR_SYNCDCFOPT      0x02        //
 #define TCR_AUTOBCNTX       0x01        // Beacon automatically transmit enable
 
-
 //ISR1
 #define ISR_GPIO3           0x40
 #define ISR_RXNOBUF         0x08
@@ -377,7 +372,6 @@
 //
 #define MISCFFCTL_WRITE     0x0001      //
 
-
 // Loopback mode
 #define MAC_LB_EXT          0x02        //
 #define MAC_LB_INTERNAL     0x01        //
@@ -409,22 +403,9 @@
 #define MAC_REVISION_A0     0x00
 #define MAC_REVISION_A1     0x01
 
-
-/*---------------------  Export Types  ------------------------------*/
-
-/*---------------------  Export Macros ------------------------------*/
-
-/*---------------------  Export Classes  ----------------------------*/
-
-/*---------------------  Export Variables  --------------------------*/
-
-/*---------------------  Export Functions  --------------------------*/
-
-void MACvSetMultiAddrByHash(struct vnt_private *, u8);
 void MACvWriteMultiAddr(struct vnt_private *, u32, u8);
 void MACbShutdown(struct vnt_private *);
 void MACvSetBBType(struct vnt_private *, u8);
-void MACvSetMISCFifo(struct vnt_private *pDevice, u16, u32);
 void MACvDisableKeyEntry(struct vnt_private *, u32);
 void MACvSetKeyEntry(struct vnt_private *, u16, u32, u32, u8 *, u32 *);
 void MACvRegBitsOff(struct vnt_private *, u8, u8);
diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c
index a5063a6..2161af8 100644
--- a/drivers/staging/vt6656/main_usb.c
+++ b/drivers/staging/vt6656/main_usb.c
@@ -72,7 +72,6 @@
 #include "int.h"
 #include "iowpa.h"
 
-/*---------------------  Static Definitions -------------------------*/
 /* static int msglevel = MSG_LEVEL_DEBUG; */
 static int          msglevel                =MSG_LEVEL_INFO;
 
@@ -95,14 +94,12 @@ MODULE_DESCRIPTION(DEVICE_FULL_DRV_NAM);
 #define RX_DESC_DEF0     64
 DEVICE_PARAM(RxDescriptors0,"Number of receive usb desc buffer");
 
-
 #define TX_DESC_DEF0     64
 DEVICE_PARAM(TxDescriptors0,"Number of transmit usb desc buffer");
 
 #define CHANNEL_DEF     6
 DEVICE_PARAM(Channel, "Channel number");
 
-
 /* PreambleType[] is the preamble length used for transmit.
    0: indicate allows long preamble type
    1: indicate allows short preamble type
@@ -118,7 +115,6 @@ DEVICE_PARAM(RTSThreshold, "RTS threshold");
 #define FRAG_THRESH_DEF     2346
 DEVICE_PARAM(FragThreshold, "Fragmentation threshold");
 
-
 #define DATA_RATE_DEF     13
 /* datarate[] index
    0: indicate 1 Mbps   0x02
@@ -148,7 +144,6 @@ DEVICE_PARAM(OPMode, "Infrastruct, adhoc, AP mode ");
    2: indicate AP mode used
 */
 
-
 /* PSMode[]
    0: indicate disable power saving mode
    1: indicate enable power saving mode
@@ -157,7 +152,6 @@ DEVICE_PARAM(OPMode, "Infrastruct, adhoc, AP mode ");
 #define PS_MODE_DEF     0
 DEVICE_PARAM(PSMode, "Power saving mode");
 
-
 #define SHORT_RETRY_DEF     8
 DEVICE_PARAM(ShortRetryLimit, "Short frame retry limits");
 
@@ -173,8 +167,6 @@ DEVICE_PARAM(LongRetryLimit, "long frame retry limits");
 #define BBP_TYPE_DEF     2
 DEVICE_PARAM(BasebandType, "baseband type");
 
-
-
 /* 80211hEnable[]
    0: indicate disable 802.11h
    1: indicate enable 802.11h
@@ -184,7 +176,6 @@ DEVICE_PARAM(BasebandType, "baseband type");
 
 DEVICE_PARAM(b80211hEnable, "802.11h mode");
 
-
 /*
  * Static vars definitions
  */
@@ -204,12 +195,9 @@ static const long frequency_list[] = {
     5700, 5745, 5765, 5785, 5805, 5825
 	};
 
-
 static const struct iw_handler_def	iwctl_handler_def;
 */
 
-/*---------------------  Static Functions  --------------------------*/
-
 static int vt6656_probe(struct usb_interface *intf,
 			const struct usb_device_id *id);
 static void vt6656_disconnect(struct usb_interface *intf);
@@ -245,21 +233,13 @@ static int Config_FileGetParameter(unsigned char *string,
 				   unsigned char *dest,
 				   unsigned char *source);
 
-
 static void usb_device_reset(struct vnt_private *pDevice);
 
-
-
-/*---------------------  Export Variables  --------------------------*/
-
-/*---------------------  Export Functions  --------------------------*/
-
-
 static void
 device_set_options(struct vnt_private *pDevice) {
 
-    BYTE    abyBroadcastAddr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-    BYTE    abySNAP_RFC1042[ETH_ALEN] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00};
+    u8    abyBroadcastAddr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+    u8    abySNAP_RFC1042[ETH_ALEN] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00};
     u8 abySNAP_Bridgetunnel[ETH_ALEN] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0xF8};
 
     memcpy(pDevice->abyBroadcastAddr, abyBroadcastAddr, ETH_ALEN);
@@ -293,7 +273,6 @@ device_set_options(struct vnt_private *pDevice) {
     pDevice->bDiversityRegCtlON = false;
 }
 
-
 static void device_init_diversity_timer(struct vnt_private *pDevice)
 {
     init_timer(&pDevice->TimerSQ3Tmax1);
@@ -314,7 +293,6 @@ static void device_init_diversity_timer(struct vnt_private *pDevice)
     return;
 }
 
-
 /*
  * initialization of MAC & BBP registers
  */
@@ -366,8 +344,8 @@ static int device_init_registers(struct vnt_private *pDevice,
         }
     }
 
-    sInitCmd.byInitClass = (BYTE)InitType;
-    sInitCmd.bExistSWNetAddr = (BYTE) pDevice->bExistSWNetAddr;
+    sInitCmd.byInitClass = (u8)InitType;
+    sInitCmd.bExistSWNetAddr = (u8) pDevice->bExistSWNetAddr;
     for (ii = 0; ii < 6; ii++)
 	sInitCmd.bySWNetAddr[ii] = pDevice->abyCurrentNetAddr[ii];
     sInitCmd.byShortRetryLimit = pDevice->byShortRetryLimit;
@@ -379,7 +357,7 @@ static int device_init_registers(struct vnt_private *pDevice,
                                     0,
                                     0,
                                     sizeof(CMD_CARD_INIT),
-                                    (PBYTE) &(sInitCmd));
+                                    (u8 *) &(sInitCmd));
 
     if ( ntStatus != STATUS_SUCCESS ) {
         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" Issue Card init fail \n");
@@ -388,7 +366,7 @@ static int device_init_registers(struct vnt_private *pDevice,
     }
     if (InitType == DEVICE_INIT_COLD) {
 
-        ntStatus = CONTROLnsRequestIn(pDevice,MESSAGE_TYPE_INIT_RSP,0,0,sizeof(RSP_CARD_INIT), (PBYTE) &(sInitRsp));
+        ntStatus = CONTROLnsRequestIn(pDevice,MESSAGE_TYPE_INIT_RSP,0,0,sizeof(RSP_CARD_INIT), (u8 *) &(sInitRsp));
 
         if (ntStatus != STATUS_SUCCESS) {
             DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Cardinit request in status fail!\n");
@@ -418,7 +396,7 @@ static int device_init_registers(struct vnt_private *pDevice,
         pDevice->bNonERPPresent = false;
         pDevice->bBarkerPreambleMd = false;
         if ( pDevice->bFixRate ) {
-            pDevice->wCurrentRate = (WORD) pDevice->uConnectionRate;
+            pDevice->wCurrentRate = (u16) pDevice->uConnectionRate;
         } else {
             if ( pDevice->byBBType == BB_TYPE_11B )
                 pDevice->wCurrentRate = RATE_11M;
@@ -771,7 +749,6 @@ static void device_free_tx_bufs(struct vnt_private *pDevice)
     return;
 }
 
-
 static void device_free_rx_bufs(struct vnt_private *pDevice)
 {
     PRCB pRCB;
@@ -809,7 +786,6 @@ static void device_free_int_bufs(struct vnt_private *pDevice)
     return;
 }
 
-
 static bool device_alloc_bufs(struct vnt_private *pDevice)
 {
 
@@ -817,7 +793,6 @@ static bool device_alloc_bufs(struct vnt_private *pDevice)
     PRCB pRCB;
     int ii;
 
-
     for (ii = 0; ii < pDevice->cbTD; ii++) {
 
         pTxContext = kmalloc(sizeof(USB_SEND_CONTEXT), GFP_KERNEL);
@@ -843,7 +818,6 @@ static bool device_alloc_bufs(struct vnt_private *pDevice)
         goto free_tx;
     }
 
-
     pDevice->FirstRecvFreeList = NULL;
     pDevice->LastRecvFreeList = NULL;
     pDevice->FirstRecvMngList = NULL;
@@ -874,7 +848,6 @@ static bool device_alloc_bufs(struct vnt_private *pDevice)
         pRCB++;
     }
 
-
 	pDevice->pControlURB = usb_alloc_urb(0, GFP_ATOMIC);
 	if (pDevice->pControlURB == NULL) {
 	    DBG_PRT(MSG_LEVEL_ERR,KERN_ERR"Failed to alloc control urb\n");
@@ -907,9 +880,6 @@ free_tx:
 	return false;
 }
 
-
-
-
 static bool device_init_defrag_cb(struct vnt_private *pDevice)
 {
 	int i;
@@ -933,8 +903,6 @@ free_frag:
     return false;
 }
 
-
-
 static void device_free_frag_bufs(struct vnt_private *pDevice)
 {
 	PSDeFragControlBlock pDeF;
@@ -949,8 +917,6 @@ static void device_free_frag_bufs(struct vnt_private *pDevice)
     }
 }
 
-
-
 int device_alloc_frag_buf(struct vnt_private *pDevice,
 		PSDeFragControlBlock pDeF)
 {
@@ -964,9 +930,6 @@ int device_alloc_frag_buf(struct vnt_private *pDevice,
     return true;
 }
 
-
-/*-----------------------------------------------------------------*/
-
 static int  device_open(struct net_device *dev)
 {
 	struct vnt_private *pDevice = netdev_priv(dev);
@@ -975,7 +938,6 @@ static int  device_open(struct net_device *dev)
 
     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " device_open...\n");
 
-
     pDevice->rx_buf_sz = MAX_TOTAL_SIZE_WITH_ALL_HEADERS;
 
     if (device_alloc_bufs(pDevice) == false) {
@@ -1061,7 +1023,6 @@ static int  device_open(struct net_device *dev)
 	else
 		bScheduleCommand((void *) pDevice, WLAN_CMD_BSSID_SCAN, NULL);
 
-
     netif_stop_queue(pDevice->dev);
     pDevice->flags |= DEVICE_FLAGS_OPENED;
 
@@ -1083,8 +1044,6 @@ free_rx_tx:
     return -ENOMEM;
 }
 
-
-
 static int device_close(struct net_device *dev)
 {
 	struct vnt_private *pDevice = netdev_priv(dev);
@@ -1100,7 +1059,6 @@ static int device_close(struct net_device *dev)
         mdelay(30);
     }
 
-
         memset(pMgmt->abyDesireSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
         pMgmt->bShareKeyAlgorithm = false;
         pDevice->bEncryptionEnable = false;
@@ -1165,7 +1123,6 @@ static void vt6656_disconnect(struct usb_interface *intf)
 	if (!device)
 		return;
 
-
 	usb_set_intfdata(intf, NULL);
 	usb_put_dev(interface_to_usbdev(intf));
 
@@ -1430,7 +1387,6 @@ static void device_set_multi(struct net_device *dev)
 	u8 byTmpMode = 0;
 	int rc;
 
-
 	spin_lock_irq(&pDevice->lock);
     rc = CONTROLnsRequestIn(pDevice,
                             MESSAGE_TYPE_READ,
@@ -1466,8 +1422,8 @@ static void device_set_multi(struct net_device *dev)
             mc_filter[bit_nr >> 5] |= cpu_to_le32(1 << (bit_nr & 31));
         }
         for (ii = 0; ii < 4; ii++) {
-             MACvWriteMultiAddr(pDevice, ii, *((PBYTE)&mc_filter[0] + ii));
-             MACvWriteMultiAddr(pDevice, ii+ 4, *((PBYTE)&mc_filter[1] + ii));
+             MACvWriteMultiAddr(pDevice, ii, *((u8 *)&mc_filter[0] + ii));
+             MACvWriteMultiAddr(pDevice, ii+ 4, *((u8 *)&mc_filter[1] + ii));
         }
         pDevice->byRxMode &= ~(RCR_UNICAST);
         pDevice->byRxMode |= (RCR_MULTICAST|RCR_BROADCAST);
@@ -1518,7 +1474,6 @@ static int device_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 	return rc;
 }
 
-
 static int ethtool_ioctl(struct net_device *dev, void *useraddr)
 {
 	u32 ethcmd;
diff --git a/drivers/staging/vt6656/mib.c b/drivers/staging/vt6656/mib.c
index d4c7b0c..12333cd 100644
--- a/drivers/staging/vt6656/mib.c
+++ b/drivers/staging/vt6656/mib.c
@@ -25,10 +25,8 @@
  * Date: May 21, 1996
  *
  * Functions:
- *      STAvClearAllCounter - Clear All MIB Counter
  *      STAvUpdateIstStatCounter - Update ISR statistic counter
  *      STAvUpdateRDStatCounter - Update Rx statistic counter
- *      STAvUpdateRDStatCounterEx - Update Rx statistic counter and copy rcv data
  *      STAvUpdateTDStatCounter - Update Tx statistic counter
  *      STAvUpdateTDStatCounterEx - Update Tx statistic counter and copy tx data
  *      STAvUpdate802_11Counter - Update 802.11 mib counter
@@ -43,38 +41,7 @@
 #include "wctl.h"
 #include "baseband.h"
 
-/*---------------------  Static Definitions -------------------------*/
 static int          msglevel                =MSG_LEVEL_INFO;
-/*---------------------  Static Classes  ----------------------------*/
-
-/*---------------------  Static Variables  --------------------------*/
-
-/*---------------------  Static Functions  --------------------------*/
-
-/*---------------------  Export Variables  --------------------------*/
-
-/*---------------------  Export Functions  --------------------------*/
-
-
-
-/*
- * Description: Clear All Statistic Counter
- *
- * Parameters:
- *  In:
- *      pStatistic  - Pointer to Statistic Counter Data Structure
- *  Out:
- *      none
- *
- * Return Value: none
- *
- */
-void STAvClearAllCounter (PSStatCounter pStatistic)
-{
-    // set memory to zero
-	memset(pStatistic, 0, sizeof(SStatCounter));
-}
-
 
 /*
  * Description: Update Isr Statistic Counter
@@ -89,7 +56,7 @@ void STAvClearAllCounter (PSStatCounter pStatistic)
  * Return Value: none
  *
  */
-void STAvUpdateIsrStatCounter (PSStatCounter pStatistic, BYTE byIsr0, BYTE byIsr1)
+void STAvUpdateIsrStatCounter (PSStatCounter pStatistic, u8 byIsr0, u8 byIsr1)
 {
     /**********************/
     /* ABNORMAL interrupt */
@@ -100,7 +67,6 @@ void STAvUpdateIsrStatCounter (PSStatCounter pStatistic, BYTE byIsr0, BYTE byIsr
         return;
     }
 
-
     if (byIsr0 & ISR_ACTX)              // ISR, bit0
         pStatistic->ISRStat.dwIsrTx0OK++;           // TXDMA0 successful
 
@@ -119,7 +85,6 @@ void STAvUpdateIsrStatCounter (PSStatCounter pStatistic, BYTE byIsr0, BYTE byIsr
     if (byIsr0 & ISR_WATCHDOG)          // ISR, bit7
         pStatistic->ISRStat.dwIsrWatchDog++;
 
-
     if (byIsr1 & ISR_FETALERR)              // ISR, bit8
         pStatistic->ISRStat.dwIsrUnrecoverableError++;
 
@@ -134,7 +99,6 @@ void STAvUpdateIsrStatCounter (PSStatCounter pStatistic, BYTE byIsr0, BYTE byIsr
 
 }
 
-
 /*
  * Description: Update Rx Statistic Counter
  *
@@ -152,12 +116,12 @@ void STAvUpdateIsrStatCounter (PSStatCounter pStatistic, BYTE byIsr0, BYTE byIsr
  *
  */
 void STAvUpdateRDStatCounter(PSStatCounter pStatistic,
-			     BYTE byRSR, BYTE byNewRSR,
-			     BYTE byRxSts, BYTE byRxRate,
-			     PBYTE pbyBuffer, unsigned int cbFrameLength)
+			     u8 byRSR, u8 byNewRSR,
+			     u8 byRxSts, u8 byRxRate,
+			     u8 * pbyBuffer, unsigned int cbFrameLength)
 {
 	/* need change */
-	PS802_11Header pHeader = (PS802_11Header)pbyBuffer;
+	struct ieee80211_hdr *pHeader = (struct ieee80211_hdr *)pbyBuffer;
 
 	if (byRSR & RSR_ADDROK)
 		pStatistic->dwRsrADDROk++;
@@ -327,7 +291,6 @@ void STAvUpdateRDStatCounter(PSStatCounter pStatistic,
     pStatistic->dwRsrRxPacket++;
     pStatistic->dwRsrRxOctet += cbFrameLength;
 
-
     if (IS_TYPE_DATA(pbyBuffer)) {
         pStatistic->dwRsrRxData++;
     } else if (IS_TYPE_MGMT(pbyBuffer)){
@@ -343,7 +306,7 @@ void STAvUpdateRDStatCounter(PSStatCounter pStatistic,
     else
         pStatistic->dwRsrDirected++;
 
-    if (WLAN_GET_FC_MOREFRAG(pHeader->wFrameCtl))
+    if (WLAN_GET_FC_MOREFRAG(pHeader->frame_control))
         pStatistic->dwRsrRxFragment++;
 
     if (cbFrameLength < ETH_ZLEN + 4) {
@@ -371,51 +334,6 @@ void STAvUpdateRDStatCounter(PSStatCounter pStatistic,
 }
 
 /*
- * Description: Update Rx Statistic Counter and copy Rx buffer
- *
- * Parameters:
- *  In:
- *      pStatistic      - Pointer to Statistic Counter Data Structure
- *      byRSR           - Rx Status
- *      byNewRSR        - Rx Status
- *      pbyBuffer       - Rx Buffer
- *      cbFrameLength   - Rx Length
- *  Out:
- *      none
- *
- * Return Value: none
- *
- */
-
-void
-STAvUpdateRDStatCounterEx (
-    PSStatCounter   pStatistic,
-    BYTE            byRSR,
-    BYTE            byNewRSR,
-    BYTE            byRxSts,
-    BYTE            byRxRate,
-    PBYTE           pbyBuffer,
-    unsigned int            cbFrameLength
-    )
-{
-    STAvUpdateRDStatCounter(
-                    pStatistic,
-                    byRSR,
-                    byNewRSR,
-                    byRxSts,
-                    byRxRate,
-                    pbyBuffer,
-                    cbFrameLength
-                    );
-
-    // rx length
-    pStatistic->dwCntRxFrmLength = cbFrameLength;
-    // rx pattern, we just see 10 bytes for sample
-    memcpy(pStatistic->abyCntRxPattern, (PBYTE)pbyBuffer, 10);
-}
-
-
-/*
  * Description: Update Tx Statistic Counter
  *
  * Parameters:
@@ -435,12 +353,12 @@ STAvUpdateRDStatCounterEx (
 void
 STAvUpdateTDStatCounter (
     PSStatCounter   pStatistic,
-    BYTE            byPktNum,
-    BYTE            byRate,
-    BYTE            byTSR
+    u8            byPktNum,
+    u8            byRate,
+    u8            byTSR
     )
 {
-    BYTE    byRetyCnt;
+    u8    byRetyCnt;
     // increase tx packet count
     pStatistic->dwTsrTxPacket++;
 
@@ -504,8 +422,6 @@ STAvUpdateTDStatCounter (
     }
 }
 
-
-
 /*
  * Description: Update 802.11 mib counter
  *
@@ -524,10 +440,10 @@ void
 STAvUpdate802_11Counter(
     PSDot11Counters         p802_11Counter,
     PSStatCounter           pStatistic,
-    BYTE                    byRTSSuccess,
-    BYTE                    byRTSFail,
-    BYTE                    byACKFail,
-    BYTE                    byFCSErr
+    u8                    byRTSSuccess,
+    u8                    byRTSFail,
+    u8                    byACKFail,
+    u8                    byFCSErr
     )
 {
     //p802_11Counter->TransmittedFragmentCount
@@ -554,25 +470,6 @@ STAvUpdate802_11Counter(
  *
  * Parameters:
  *  In:
- *      p802_11Counter  - Pointer to 802.11 mib counter
- *  Out:
- *      none
- *
- * Return Value: none
- *
- */
-void
-STAvClear802_11Counter(PSDot11Counters p802_11Counter)
-{
-    // set memory to zero
-	memset(p802_11Counter, 0, sizeof(SDot11Counters));
-}
-
-/*
- * Description: Clear 802.11 mib counter
- *
- * Parameters:
- *  In:
  *      pUsbCounter  - Pointer to USB mib counter
  *      ntStatus - URB status
  *  Out:
diff --git a/drivers/staging/vt6656/mib.h b/drivers/staging/vt6656/mib.h
index 85c28e9..3537532 100644
--- a/drivers/staging/vt6656/mib.h
+++ b/drivers/staging/vt6656/mib.h
@@ -29,28 +29,21 @@
 #ifndef __MIB_H__
 #define __MIB_H__
 
-#include "ttype.h"
 #include "tether.h"
 #include "desc.h"
 
-/*---------------------  Export Definitions -------------------------*/
-
-
 //
 // USB counter
 //
 typedef struct tagSUSBCounter {
-    DWORD dwCrc;
+    u32 dwCrc;
 
 } SUSBCounter, *PSUSBCounter;
 
-
-
 //
 // 802.11 counter
 //
 
-
 typedef struct tagSDot11Counters {
   /* unsigned long Length; // Length of structure */
     unsigned long long   TransmittedFragmentCount;
@@ -81,7 +74,6 @@ typedef struct tagSDot11Counters {
    */
 } SDot11Counters, *PSDot11Counters;
 
-
 //
 // MIB2 counter
 //
@@ -91,24 +83,24 @@ typedef struct tagSMib2Counter {
                                         // e.g. "interface 1"
     signed long    ifType;
     signed long    ifMtu;
-    DWORD   ifSpeed;
-    BYTE    ifPhysAddress[ETH_ALEN];
+    u32   ifSpeed;
+    u8    ifPhysAddress[ETH_ALEN];
     signed long    ifAdminStatus;
     signed long    ifOperStatus;
-    DWORD   ifLastChange;
-    DWORD   ifInOctets;
-    DWORD   ifInUcastPkts;
-    DWORD   ifInNUcastPkts;
-    DWORD   ifInDiscards;
-    DWORD   ifInErrors;
-    DWORD   ifInUnknownProtos;
-    DWORD   ifOutOctets;
-    DWORD   ifOutUcastPkts;
-    DWORD   ifOutNUcastPkts;
-    DWORD   ifOutDiscards;
-    DWORD   ifOutErrors;
-    DWORD   ifOutQLen;
-    DWORD   ifSpecific;
+    u32   ifLastChange;
+    u32   ifInOctets;
+    u32   ifInUcastPkts;
+    u32   ifInNUcastPkts;
+    u32   ifInDiscards;
+    u32   ifInErrors;
+    u32   ifInUnknownProtos;
+    u32   ifOutOctets;
+    u32   ifOutUcastPkts;
+    u32   ifOutNUcastPkts;
+    u32   ifOutDiscards;
+    u32   ifOutErrors;
+    u32   ifOutQLen;
+    u32   ifSpecific;
 } SMib2Counter, *PSMib2Counter;
 
 // Value in the ifType entry
@@ -119,32 +111,31 @@ typedef struct tagSMib2Counter {
 #define DOWN                2           //
 #define TESTING             3           //
 
-
 //
 // RMON counter
 //
 typedef struct tagSRmonCounter {
     signed long    etherStatsIndex;
-    DWORD   etherStatsDataSource;
-    DWORD   etherStatsDropEvents;
-    DWORD   etherStatsOctets;
-    DWORD   etherStatsPkts;
-    DWORD   etherStatsBroadcastPkts;
-    DWORD   etherStatsMulticastPkts;
-    DWORD   etherStatsCRCAlignErrors;
-    DWORD   etherStatsUndersizePkts;
-    DWORD   etherStatsOversizePkts;
-    DWORD   etherStatsFragments;
-    DWORD   etherStatsJabbers;
-    DWORD   etherStatsCollisions;
-    DWORD   etherStatsPkt64Octets;
-    DWORD   etherStatsPkt65to127Octets;
-    DWORD   etherStatsPkt128to255Octets;
-    DWORD   etherStatsPkt256to511Octets;
-    DWORD   etherStatsPkt512to1023Octets;
-    DWORD   etherStatsPkt1024to1518Octets;
-    DWORD   etherStatsOwners;
-    DWORD   etherStatsStatus;
+    u32   etherStatsDataSource;
+    u32   etherStatsDropEvents;
+    u32   etherStatsOctets;
+    u32   etherStatsPkts;
+    u32   etherStatsBroadcastPkts;
+    u32   etherStatsMulticastPkts;
+    u32   etherStatsCRCAlignErrors;
+    u32   etherStatsUndersizePkts;
+    u32   etherStatsOversizePkts;
+    u32   etherStatsFragments;
+    u32   etherStatsJabbers;
+    u32   etherStatsCollisions;
+    u32   etherStatsPkt64Octets;
+    u32   etherStatsPkt65to127Octets;
+    u32   etherStatsPkt128to255Octets;
+    u32   etherStatsPkt256to511Octets;
+    u32   etherStatsPkt512to1023Octets;
+    u32   etherStatsPkt1024to1518Octets;
+    u32   etherStatsOwners;
+    u32   etherStatsStatus;
 } SRmonCounter, *PSRmonCounter;
 
 //
@@ -185,56 +176,52 @@ typedef struct tagSCustomCounters {
 
 } SCustomCounters, *PSCustomCounters;
 
-
 //
 // Custom counter
 //
 typedef struct tagSISRCounters {
     unsigned long   Length;
 
-    DWORD   dwIsrTx0OK;
-    DWORD   dwIsrAC0TxOK;
-    DWORD   dwIsrBeaconTxOK;
-    DWORD   dwIsrRx0OK;
-    DWORD   dwIsrTBTTInt;
-    DWORD   dwIsrSTIMERInt;
-    DWORD   dwIsrWatchDog;
-    DWORD   dwIsrUnrecoverableError;
-    DWORD   dwIsrSoftInterrupt;
-    DWORD   dwIsrMIBNearfull;
-    DWORD   dwIsrRxNoBuf;
-
-    DWORD   dwIsrUnknown;               // unknown interrupt count
-
-    DWORD   dwIsrRx1OK;
-    DWORD   dwIsrATIMTxOK;
-    DWORD   dwIsrSYNCTxOK;
-    DWORD   dwIsrCFPEnd;
-    DWORD   dwIsrATIMEnd;
-    DWORD   dwIsrSYNCFlushOK;
-    DWORD   dwIsrSTIMER1Int;
+    u32   dwIsrTx0OK;
+    u32   dwIsrAC0TxOK;
+    u32   dwIsrBeaconTxOK;
+    u32   dwIsrRx0OK;
+    u32   dwIsrTBTTInt;
+    u32   dwIsrSTIMERInt;
+    u32   dwIsrWatchDog;
+    u32   dwIsrUnrecoverableError;
+    u32   dwIsrSoftInterrupt;
+    u32   dwIsrMIBNearfull;
+    u32   dwIsrRxNoBuf;
+
+    u32   dwIsrUnknown;               // unknown interrupt count
+
+    u32   dwIsrRx1OK;
+    u32   dwIsrATIMTxOK;
+    u32   dwIsrSYNCTxOK;
+    u32   dwIsrCFPEnd;
+    u32   dwIsrATIMEnd;
+    u32   dwIsrSYNCFlushOK;
+    u32   dwIsrSTIMER1Int;
     /////////////////////////////////////
 } SISRCounters, *PSISRCounters;
 
-
 // Value in the etherStatsStatus entry
 #define VALID               1           //
 #define CREATE_REQUEST      2           //
 #define UNDER_CREATION      3           //
 #define INVALID             4           //
 
-
 //
 // Tx packet information
 //
 typedef struct tagSTxPktInfo {
-    BYTE    byBroadMultiUni;
-    WORD    wLength;
-    WORD    wFIFOCtl;
-    BYTE    abyDestAddr[ETH_ALEN];
+    u8    byBroadMultiUni;
+    u16    wLength;
+    u16    wFIFOCtl;
+    u8    abyDestAddr[ETH_ALEN];
 } STxPktInfo, *PSTxPktInfo;
 
-
 #define MAX_RATE            12
 //
 // statistic counter
@@ -248,34 +235,34 @@ typedef struct tagSStatCounter {
 
     // RSR status count
     //
-    DWORD   dwRsrFrmAlgnErr;
-    DWORD   dwRsrErr;
-    DWORD   dwRsrCRCErr;
-    DWORD   dwRsrCRCOk;
-    DWORD   dwRsrBSSIDOk;
-    DWORD   dwRsrADDROk;
-    DWORD   dwRsrBCNSSIDOk;
-    DWORD   dwRsrLENErr;
-    DWORD   dwRsrTYPErr;
-
-    DWORD   dwNewRsrDECRYPTOK;
-    DWORD   dwNewRsrCFP;
-    DWORD   dwNewRsrUTSF;
-    DWORD   dwNewRsrHITAID;
-    DWORD   dwNewRsrHITAID0;
-
-    DWORD   dwRsrLong;
-    DWORD   dwRsrRunt;
-
-    DWORD   dwRsrRxControl;
-    DWORD   dwRsrRxData;
-    DWORD   dwRsrRxManage;
-
-    DWORD   dwRsrRxPacket;
-    DWORD   dwRsrRxOctet;
-    DWORD   dwRsrBroadcast;
-    DWORD   dwRsrMulticast;
-    DWORD   dwRsrDirected;
+    u32   dwRsrFrmAlgnErr;
+    u32   dwRsrErr;
+    u32   dwRsrCRCErr;
+    u32   dwRsrCRCOk;
+    u32   dwRsrBSSIDOk;
+    u32   dwRsrADDROk;
+    u32   dwRsrBCNSSIDOk;
+    u32   dwRsrLENErr;
+    u32   dwRsrTYPErr;
+
+    u32   dwNewRsrDECRYPTOK;
+    u32   dwNewRsrCFP;
+    u32   dwNewRsrUTSF;
+    u32   dwNewRsrHITAID;
+    u32   dwNewRsrHITAID0;
+
+    u32   dwRsrLong;
+    u32   dwRsrRunt;
+
+    u32   dwRsrRxControl;
+    u32   dwRsrRxData;
+    u32   dwRsrRxManage;
+
+    u32   dwRsrRxPacket;
+    u32   dwRsrRxOctet;
+    u32   dwRsrBroadcast;
+    u32   dwRsrMulticast;
+    u32   dwRsrDirected;
     // 64-bit OID
     unsigned long long   ullRsrOK;
 
@@ -287,47 +274,44 @@ typedef struct tagSStatCounter {
     unsigned long long   ullRxMulticastFrames;
     unsigned long long   ullRxDirectedFrames;
 
-    DWORD   dwRsrRxFragment;
-    DWORD   dwRsrRxFrmLen64;
-    DWORD   dwRsrRxFrmLen65_127;
-    DWORD   dwRsrRxFrmLen128_255;
-    DWORD   dwRsrRxFrmLen256_511;
-    DWORD   dwRsrRxFrmLen512_1023;
-    DWORD   dwRsrRxFrmLen1024_1518;
+    u32   dwRsrRxFragment;
+    u32   dwRsrRxFrmLen64;
+    u32   dwRsrRxFrmLen65_127;
+    u32   dwRsrRxFrmLen128_255;
+    u32   dwRsrRxFrmLen256_511;
+    u32   dwRsrRxFrmLen512_1023;
+    u32   dwRsrRxFrmLen1024_1518;
 
     // TSR status count
     //
-    DWORD   dwTsrTotalRetry;        // total collision retry count
-    DWORD   dwTsrOnceRetry;         // this packet only occur one collision
-    DWORD   dwTsrMoreThanOnceRetry; // this packet occur more than one collision
-    DWORD   dwTsrRetry;             // this packet has ever occur collision,
+    u32   dwTsrTotalRetry;        // total collision retry count
+    u32   dwTsrOnceRetry;         // this packet only occur one collision
+    u32   dwTsrMoreThanOnceRetry; // this packet occur more than one collision
+    u32   dwTsrRetry;             // this packet has ever occur collision,
                                          // that is (dwTsrOnceCollision0 + dwTsrMoreThanOnceCollision0)
-    DWORD   dwTsrACKData;
-    DWORD   dwTsrErr;
-    DWORD   dwAllTsrOK;
-    DWORD   dwTsrRetryTimeout;
-    DWORD   dwTsrTransmitTimeout;
-
-    DWORD   dwTsrTxPacket;
-    DWORD   dwTsrTxOctet;
-    DWORD   dwTsrBroadcast;
-    DWORD   dwTsrMulticast;
-    DWORD   dwTsrDirected;
+    u32   dwTsrACKData;
+    u32   dwTsrErr;
+    u32   dwAllTsrOK;
+    u32   dwTsrRetryTimeout;
+    u32   dwTsrTransmitTimeout;
+
+    u32   dwTsrTxPacket;
+    u32   dwTsrTxOctet;
+    u32   dwTsrBroadcast;
+    u32   dwTsrMulticast;
+    u32   dwTsrDirected;
 
     // RD/TD count
-    DWORD   dwCntRxFrmLength;
-    DWORD   dwCntTxBufLength;
-
-    BYTE    abyCntRxPattern[16];
-    BYTE    abyCntTxPattern[16];
-
+    u32   dwCntRxFrmLength;
+    u32   dwCntTxBufLength;
 
+    u8    abyCntRxPattern[16];
+    u8    abyCntTxPattern[16];
 
     // Software check....
-    DWORD   dwCntRxDataErr;             // rx buffer data software compare CRC err count
-    DWORD   dwCntDecryptErr;            // rx buffer data software compare CRC err count
-    DWORD   dwCntRxICVErr;              // rx buffer data software compare CRC err count
-
+    u32   dwCntRxDataErr;             // rx buffer data software compare CRC err count
+    u32   dwCntDecryptErr;            // rx buffer data software compare CRC err count
+    u32   dwCntRxICVErr;              // rx buffer data software compare CRC err count
 
     // 64-bit OID
     unsigned long long   ullTsrOK;
@@ -341,9 +325,9 @@ typedef struct tagSStatCounter {
     unsigned long long   ullTxDirectedBytes;
 
     // for autorate
-    DWORD   dwTxOk[MAX_RATE+1];
-    DWORD   dwTxFail[MAX_RATE+1];
-    DWORD   dwTxRetryCount[8];
+    u32   dwTxOk[MAX_RATE+1];
+    u32   dwTxFail[MAX_RATE+1];
+    u32   dwTxRetryCount[8];
 
     STxPktInfo  abyTxPktInfo[16];
 
@@ -367,42 +351,28 @@ typedef struct tagSStatCounter {
 
 } SStatCounter, *PSStatCounter;
 
-/*---------------------  Export Classes  ----------------------------*/
-
-/*---------------------  Export Variables  --------------------------*/
-
-/*---------------------  Export Functions  --------------------------*/
-
-void STAvClearAllCounter(PSStatCounter pStatistic);
-
 void STAvUpdateIsrStatCounter(PSStatCounter pStatistic,
-			      BYTE byIsr0,
-			      BYTE byIsr1);
+			      u8 byIsr0,
+			      u8 byIsr1);
 
 void STAvUpdateRDStatCounter(PSStatCounter pStatistic,
-			     BYTE byRSR, BYTE byNewRSR, BYTE byRxSts,
-			     BYTE byRxRate, PBYTE pbyBuffer,
+			     u8 byRSR, u8 byNewRSR, u8 byRxSts,
+			     u8 byRxRate, u8 * pbyBuffer,
 			     unsigned int cbFrameLength);
 
-void STAvUpdateRDStatCounterEx(PSStatCounter pStatistic,
-			       BYTE byRSR, BYTE byNewRSR, BYTE byRxSts,
-			       BYTE byRxRate, PBYTE pbyBuffer,
-			       unsigned int cbFrameLength);
-
-void STAvUpdateTDStatCounter(PSStatCounter pStatistic, BYTE byPktNum,
-			     BYTE byRate, BYTE byTSR);
+void STAvUpdateTDStatCounter(PSStatCounter pStatistic, u8 byPktNum,
+			     u8 byRate, u8 byTSR);
 
 void
 STAvUpdate802_11Counter(
     PSDot11Counters         p802_11Counter,
     PSStatCounter           pStatistic,
-    BYTE                    byRTSSuccess,
-    BYTE                    byRTSFail,
-    BYTE                    byACKFail,
-    BYTE                    byFCSErr
+    u8                    byRTSSuccess,
+    u8                    byRTSFail,
+    u8                    byACKFail,
+    u8                    byFCSErr
     );
 
-void STAvClear802_11Counter(PSDot11Counters p802_11Counter);
 void STAvUpdateUSBCounter(PSUSBCounter pUsbCounter, int ntStatus);
 
 #endif /* __MIB_H__ */
diff --git a/drivers/staging/vt6656/michael.c b/drivers/staging/vt6656/michael.c
index 4d41981..9a5a0b6 100644
--- a/drivers/staging/vt6656/michael.c
+++ b/drivers/staging/vt6656/michael.c
@@ -26,8 +26,8 @@
  * Date: Sep 4, 2002
  *
  * Functions:
- *      s_dwGetUINT32 - Convert from BYTE[] to DWORD in a portable way
- *      s_vPutUINT32 - Convert from DWORD to BYTE[] in a portable way
+ *      s_dwGetUINT32 - Convert from u8[] to u32 in a portable way
+ *      s_vPutUINT32 - Convert from u32 to u8[] in a portable way
  *      s_vClear - Reset the state to the empty message.
  *      s_vSetKey - Set the key.
  *      MIC_vInit - Set the key.
@@ -42,49 +42,41 @@
 #include "tmacro.h"
 #include "michael.h"
 
-/*---------------------  Static Definitions -------------------------*/
-
-/*---------------------  Static Variables  --------------------------*/
-
-/*---------------------  Static Functions  --------------------------*/
 /*
- * static DWORD s_dwGetUINT32(BYTE * p);         Get DWORD from
+ * static u32 s_dwGetUINT32(u8 * p);         Get u32 from
  *							4 bytes LSByte first
- * static void s_vPutUINT32(BYTE* p, DWORD val); Put DWORD into
+ * static void s_vPutUINT32(u8* p, u32 val); Put u32 into
  *							4 bytes LSByte first
  */
 static void s_vClear(void);		/* Clear the internal message,
 					 * resets the object to the
 					 * state just after construction. */
-static void s_vSetKey(DWORD dwK0, DWORD dwK1);
-static void s_vAppendByte(BYTE b);	/* Add a single byte to the internal
+static void s_vSetKey(u32 dwK0, u32 dwK1);
+static void s_vAppendByte(u8 b);	/* Add a single byte to the internal
 					 * message */
 
-/*---------------------  Export Variables  --------------------------*/
-static DWORD  L, R;		/* Current state */
-static DWORD  K0, K1;		/* Key */
-static DWORD  M;		/* Message accumulator (single word) */
+static u32  L, R;		/* Current state */
+static u32  K0, K1;		/* Key */
+static u32  M;		/* Message accumulator (single word) */
 static unsigned int   nBytesInM;	/* # bytes in M */
 
-/*---------------------  Export Functions  --------------------------*/
-
 /*
-static DWORD s_dwGetUINT32 (BYTE * p)
-// Convert from BYTE[] to DWORD in a portable way
+static u32 s_dwGetUINT32 (u8 * p)
+// Convert from u8[] to u32 in a portable way
 {
-	DWORD res = 0;
+	u32 res = 0;
 	unsigned int i;
 	for (i = 0; i < 4; i++)
 		res |= (*p++) << (8*i);
 	return res;
 }
 
-static void s_vPutUINT32(BYTE *p, DWORD val)
-// Convert from DWORD to BYTE[] in a portable way
+static void s_vPutUINT32(u8 *p, u32 val)
+// Convert from u32 to u8[] in a portable way
 {
 	unsigned int i;
 	for (i = 0; i < 4; i++) {
-		*p++ = (BYTE) (val & 0xff);
+		*p++ = (u8) (val & 0xff);
 		val >>= 8;
 	}
 }
@@ -99,7 +91,7 @@ static void s_vClear(void)
 	M = 0;
 }
 
-static void s_vSetKey(DWORD dwK0, DWORD dwK1)
+static void s_vSetKey(u32 dwK0, u32 dwK1)
 {
 	/* Set the key */
 	K0 = dwK0;
@@ -108,7 +100,7 @@ static void s_vSetKey(DWORD dwK0, DWORD dwK1)
 	s_vClear();
 }
 
-static void s_vAppendByte(BYTE b)
+static void s_vAppendByte(u8 b)
 {
 	/* Append the byte to our word-sized buffer */
 	M |= b << (8*nBytesInM);
@@ -130,13 +122,12 @@ static void s_vAppendByte(BYTE b)
 	}
 }
 
-void MIC_vInit(DWORD dwK0, DWORD dwK1)
+void MIC_vInit(u32 dwK0, u32 dwK1)
 {
 	/* Set the key */
 	s_vSetKey(dwK0, dwK1);
 }
 
-
 void MIC_vUnInit(void)
 {
 	/* Wipe the key material */
@@ -148,7 +139,7 @@ void MIC_vUnInit(void)
 	s_vClear();
 }
 
-void MIC_vAppend(PBYTE src, unsigned int nBytes)
+void MIC_vAppend(u8 * src, unsigned int nBytes)
 {
     /* This is simple */
 	while (nBytes > 0) {
@@ -157,7 +148,7 @@ void MIC_vAppend(PBYTE src, unsigned int nBytes)
 	}
 }
 
-void MIC_vGetMIC(PDWORD pdwL, PDWORD pdwR)
+void MIC_vGetMIC(u32 * pdwL, u32 * pdwR)
 {
 	/* Append the minimum padding */
 	s_vAppendByte(0x5a);
diff --git a/drivers/staging/vt6656/michael.h b/drivers/staging/vt6656/michael.h
index 81351f5..9c69a42 100644
--- a/drivers/staging/vt6656/michael.h
+++ b/drivers/staging/vt6656/michael.h
@@ -31,22 +31,18 @@
 #ifndef __MICHAEL_H__
 #define __MICHAEL_H__
 
-/*---------------------  Export Definitions -------------------------*/
+#include <linux/types.h>
 
-/*---------------------  Export Types  ------------------------------*/
-
-void MIC_vInit(DWORD dwK0, DWORD dwK1);
+void MIC_vInit(u32 dwK0, u32 dwK1);
 
 void MIC_vUnInit(void);
 
 // Append bytes to the message to be MICed
-void MIC_vAppend(PBYTE src, unsigned int nBytes);
+void MIC_vAppend(u8 * src, unsigned int nBytes);
 
 // Get the MIC result. Destination should accept 8 bytes of result.
 // This also resets the message to empty.
-void MIC_vGetMIC(PDWORD pdwL, PDWORD pdwR);
-
-/*---------------------  Export Macros ------------------------------*/
+void MIC_vGetMIC(u32 * pdwL, u32 * pdwR);
 
 // Rotation functions on 32 bit values
 #define ROL32(A, n) \
diff --git a/drivers/staging/vt6656/power.c b/drivers/staging/vt6656/power.c
index 527c259f..edc8975 100644
--- a/drivers/staging/vt6656/power.c
+++ b/drivers/staging/vt6656/power.c
@@ -37,7 +37,6 @@
  *
  */
 
-#include "ttype.h"
 #include "mac.h"
 #include "device.h"
 #include "wmgr.h"
@@ -48,17 +47,7 @@
 #include "control.h"
 #include "rndis.h"
 
-/*---------------------  Static Definitions -------------------------*/
-
-/*---------------------  Static Classes  ----------------------------*/
-
-/*---------------------  Static Variables  --------------------------*/
 static int msglevel = MSG_LEVEL_INFO;
-/*---------------------  Static Functions  --------------------------*/
-
-/*---------------------  Export Variables  --------------------------*/
-
-/*---------------------  Export Functions  --------------------------*/
 
 /*
  *
@@ -290,7 +279,7 @@ int PSbSendNullPacket(struct vnt_private *pDevice)
 	pTxPacket->p80211Header->sA3.wFrameCtl = cpu_to_le16(flags);
 
 	if (pMgmt->eCurrMode != WMAC_MODE_IBSS_STA)
-		pTxPacket->p80211Header->sA3.wFrameCtl |= cpu_to_le16((WORD)WLAN_SET_FC_TODS(1));
+		pTxPacket->p80211Header->sA3.wFrameCtl |= cpu_to_le16((u16)WLAN_SET_FC_TODS(1));
 
 	memcpy(pTxPacket->p80211Header->sA3.abyAddr1, pMgmt->abyCurrBSSID, WLAN_ADDR_LEN);
 	memcpy(pTxPacket->p80211Header->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN);
diff --git a/drivers/staging/vt6656/power.h b/drivers/staging/vt6656/power.h
index 879b10c..7783582 100644
--- a/drivers/staging/vt6656/power.h
+++ b/drivers/staging/vt6656/power.h
@@ -29,22 +29,10 @@
 #ifndef __POWER_H__
 #define __POWER_H__
 
-
-/*---------------------  Export Definitions -------------------------*/
 #define     C_PWBT                   1000      // micro sec. power up before TBTT
 #define     PS_FAST_INTERVAL         1         // Fast power saving listen interval
 #define     PS_MAX_INTERVAL          4         // MAX power saving listen interval
 
-/*---------------------  Export Classes  ----------------------------*/
-
-/*---------------------  Export Variables  --------------------------*/
-
-
-/*---------------------  Export Types  ------------------------------*/
-
-
-/*---------------------  Export Functions  --------------------------*/
-
 /*  PSDevice pDevice */
 /*  PSDevice hDeviceContext */
 
diff --git a/drivers/staging/vt6656/rc4.c b/drivers/staging/vt6656/rc4.c
index 5c3c2d0..2fd836f 100644
--- a/drivers/staging/vt6656/rc4.c
+++ b/drivers/staging/vt6656/rc4.c
@@ -32,27 +32,27 @@
 
 #include "rc4.h"
 
-void rc4_init(PRC4Ext pRC4, PBYTE pbyKey, unsigned int cbKey_len)
+void rc4_init(PRC4Ext pRC4, u8 * pbyKey, unsigned int cbKey_len)
 {
 	unsigned int  ust1, ust2;
 	unsigned int  keyindex;
 	unsigned int  stateindex;
-	PBYTE pbyst;
+	u8 * pbyst;
 	unsigned int  idx;
 
 	pbyst = pRC4->abystate;
 	pRC4->ux = 0;
 	pRC4->uy = 0;
 	for (idx = 0; idx < 256; idx++)
-		pbyst[idx] = (BYTE)idx;
+		pbyst[idx] = (u8)idx;
 	keyindex = 0;
 	stateindex = 0;
 	for (idx = 0; idx < 256; idx++) {
 		ust1 = pbyst[idx];
 		stateindex = (stateindex + pbyKey[keyindex] + ust1) & 0xff;
 		ust2 = pbyst[stateindex];
-		pbyst[stateindex] = (BYTE)ust1;
-		pbyst[idx] = (BYTE)ust2;
+		pbyst[stateindex] = (u8)ust1;
+		pbyst[idx] = (u8)ust2;
 		if (++keyindex >= cbKey_len)
 			keyindex = 0;
 	}
@@ -63,7 +63,7 @@ unsigned int rc4_byte(PRC4Ext pRC4)
 	unsigned int ux;
 	unsigned int uy;
 	unsigned int ustx, usty;
-	PBYTE pbyst;
+	u8 * pbyst;
 
 	pbyst = pRC4->abystate;
 	ux = (pRC4->ux + 1) & 0xff;
@@ -72,16 +72,16 @@ unsigned int rc4_byte(PRC4Ext pRC4)
 	usty = pbyst[uy];
 	pRC4->ux = ux;
 	pRC4->uy = uy;
-	pbyst[uy] = (BYTE)ustx;
-	pbyst[ux] = (BYTE)usty;
+	pbyst[uy] = (u8)ustx;
+	pbyst[ux] = (u8)usty;
 
 	return pbyst[(ustx + usty) & 0xff];
 }
 
-void rc4_encrypt(PRC4Ext pRC4, PBYTE pbyDest,
-			PBYTE pbySrc, unsigned int cbData_len)
+void rc4_encrypt(PRC4Ext pRC4, u8 * pbyDest,
+			u8 * pbySrc, unsigned int cbData_len)
 {
 	unsigned int ii;
 	for (ii = 0; ii < cbData_len; ii++)
-		pbyDest[ii] = (BYTE)(pbySrc[ii] ^ rc4_byte(pRC4));
+		pbyDest[ii] = (u8)(pbySrc[ii] ^ rc4_byte(pRC4));
 }
diff --git a/drivers/staging/vt6656/rc4.h b/drivers/staging/vt6656/rc4.h
index d447879c..d376e1a 100644
--- a/drivers/staging/vt6656/rc4.h
+++ b/drivers/staging/vt6656/rc4.h
@@ -30,19 +30,17 @@
 #ifndef __RC4_H__
 #define __RC4_H__
 
-#include "ttype.h"
+#include <linux/types.h>
 
-/*---------------------  Export Definitions -------------------------*/
-/*---------------------  Export Types  ------------------------------*/
 typedef struct {
     unsigned int ux;
     unsigned int uy;
-    BYTE abystate[256];
+    u8 abystate[256];
 } RC4Ext, *PRC4Ext;
 
-void rc4_init(PRC4Ext pRC4, PBYTE pbyKey, unsigned int cbKey_len);
+void rc4_init(PRC4Ext pRC4, u8 * pbyKey, unsigned int cbKey_len);
 unsigned int rc4_byte(PRC4Ext pRC4);
-void rc4_encrypt(PRC4Ext pRC4, PBYTE pbyDest, PBYTE pbySrc,
+void rc4_encrypt(PRC4Ext pRC4, u8 * pbyDest, u8 * pbySrc,
 		 unsigned int cbData_len);
 
 #endif /* __RC4_H__ */
diff --git a/drivers/staging/vt6656/rf.c b/drivers/staging/vt6656/rf.c
index a415705..44cfe0b 100644
--- a/drivers/staging/vt6656/rf.c
+++ b/drivers/staging/vt6656/rf.c
@@ -41,7 +41,6 @@
 
 static int          msglevel                =MSG_LEVEL_INFO;
 //static int          msglevel                =MSG_LEVEL_DEBUG;
-/*---------------------  Static Definitions -------------------------*/
 #define BY_AL2230_REG_LEN     23 //24bit
 #define CB_AL2230_INIT_SEQ    15
 #define AL2230_PWR_IDX_LEN    64
@@ -62,13 +61,6 @@ static int          msglevel                =MSG_LEVEL_INFO;
 #define VT3342_PWR_IDX_LEN    64
 //}}
 
-/*---------------------  Static Classes  ----------------------------*/
-
-/*---------------------  Static Variables  --------------------------*/
-
-
-
-
 u8 abyAL2230InitTable[CB_AL2230_INIT_SEQ][3] = {
     {0x03, 0xF7, 0x90},
     {0x03, 0x33, 0x31},
@@ -388,7 +380,6 @@ u8 abyVT3226D0_InitTable[CB_VT3226_INIT_SEQ][3] = {
     {0x02, 0x01, 0xAA}  //RobertYu:20060523
     };
 
-
 u8 abyVT3226_ChannelTable0[CB_MAX_CHANNEL_24G][3] = {
     {0x01, 0x97, 0x83}, // channel = 1, Tf = 2412MHz
     {0x01, 0x97, 0x83}, // channel = 2, Tf = 2417MHz
@@ -424,7 +415,6 @@ u8 abyVT3226_ChannelTable1[CB_MAX_CHANNEL_24G][3] = {
     };
 ///}}RobertYu
 
-
 //{{RobertYu:20060502, TWIF 1.14, LO Current for 11b mode
 u32 dwVT3226D0LoCurrentTable[CB_MAX_CHANNEL_24G] = {
     0x0135C600+(BY_VT3226_REG_LEN<<3)+IFREGCTL_REGW, // channel = 1, Tf = 2412MHz
@@ -444,7 +434,6 @@ u32 dwVT3226D0LoCurrentTable[CB_MAX_CHANNEL_24G] = {
 };
 //}}
 
-
 //{{RobertYu:20060609
 u8 abyVT3342A0_InitTable[CB_VT3342_INIT_SEQ][3] = { /* 11b/g mode */
     {0x03, 0xFF, 0x80}, //update for mode//
@@ -599,7 +588,6 @@ u8 abyVT3342_ChannelTable1[CB_MAX_CHANNEL][3] = {
     {0x03, 0x00, 0x04}  // channel = 165, Tf = 5825MHz (56), TBD
     };
 
-
 /*+
  *
  * Power Table
@@ -673,10 +661,6 @@ const u32 dwAL2230PowerTable[AL2230_PWR_IDX_LEN] = {
     0x0407F900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW
     };
 
-/*---------------------  Static Functions  --------------------------*/
-
-/*---------------------  Export Variables  --------------------------*/
-
 //{{ RobertYu:20050103, Channel 11a Number To Index
 // 4.9G => Ch 183, 184, 185, 187, 188, 189, 192, 196  (Value:15 ~ 22)
 // 5G => Ch 7, 8, 9, 11, 12, 16, 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64,
@@ -708,8 +692,6 @@ const u8 RFaby11aChannelIndex[200] = {
 };
 //}} RobertYu
 
-/*---------------------  Export Functions  --------------------------*/
-
 /*
  * Description: Write to IF/RF, by embedded programming
  *
@@ -734,11 +716,9 @@ int IFRFbWriteEmbedded(struct vnt_private *pDevice, u32 dwData)
 	CONTROLnsRequestOut(pDevice,
 		MESSAGE_TYPE_WRITE_IFRF, 0, 0, 4, pbyData);
 
-
 	return true;
 }
 
-
 /*
  * Description: Set Tx power
  *
@@ -790,7 +770,6 @@ int RFbSetPower(struct vnt_private *pDevice, u32 uRATE, u32 uCH)
     return bResult;
 }
 
-
 /*
  * Description: Set Tx power
  *
@@ -839,10 +818,9 @@ int RFbRawSetPower(struct vnt_private *pDevice, u8 byPwr, u32 uRATE)
             }
             break;
 
-
         case RF_AIROHA7230:
             {
-                DWORD       dwMax7230Pwr;
+                u32       dwMax7230Pwr;
 
                 if (uRATE <= RATE_11M) { //RobertYu:20060426, for better 11b mask
                     bResult &= IFRFbWriteEmbedded(pDevice, 0x111BB900+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW);
@@ -864,7 +842,7 @@ int RFbRawSetPower(struct vnt_private *pDevice, u8 byPwr, u32 uRATE)
 
         case RF_VT3226: //RobertYu:20051111, VT3226C0 and before
         {
-            DWORD       dwVT3226Pwr;
+            u32       dwVT3226Pwr;
 
             if (pDevice->byCurPwr >= VT3226_PWR_IDX_LEN)
                 return false;
@@ -876,7 +854,7 @@ int RFbRawSetPower(struct vnt_private *pDevice, u8 byPwr, u32 uRATE)
 
         case RF_VT3226D0: //RobertYu:20051228
         {
-            DWORD       dwVT3226Pwr;
+            u32       dwVT3226Pwr;
 
             if (pDevice->byCurPwr >= VT3226_PWR_IDX_LEN)
                 return false;
@@ -921,7 +899,7 @@ int RFbRawSetPower(struct vnt_private *pDevice, u8 byPwr, u32 uRATE)
         //{{RobertYu:20060609
         case RF_VT3342A0:
         {
-            DWORD       dwVT3342Pwr;
+            u32       dwVT3342Pwr;
 
             if (pDevice->byCurPwr >= VT3342_PWR_IDX_LEN)
                 return false;
@@ -976,8 +954,6 @@ void RFvRSSITodBm(struct vnt_private *pDevice, u8 byCurrRSSI, long *pldBm)
     *pldBm = -1 * (a + b * 2);
 }
 
-
-
 void RFbRFTableDownload(struct vnt_private *pDevice)
 {
 	u16 wLength1 = 0, wLength2 = 0, wLength3 = 0;
@@ -1121,20 +1097,3 @@ void RFbRFTableDownload(struct vnt_private *pDevice)
     }
 
 }
-
-int s_bVT3226D0_11bLoCurrentAdjust(struct vnt_private *pDevice, u8 byChannel,
-	int b11bMode)
-{
-	int bResult = true;
-
-	if (b11bMode)
-		bResult &= IFRFbWriteEmbedded(pDevice,
-			dwVT3226D0LoCurrentTable[byChannel-1]);
-	else
-		bResult &= IFRFbWriteEmbedded(pDevice, 0x016bc600 +
-			(BY_VT3226_REG_LEN << 3) + IFREGCTL_REGW);
-
-	return bResult;
-}
-
-
diff --git a/drivers/staging/vt6656/rf.h b/drivers/staging/vt6656/rf.h
index 9f70cf7..de5c613 100644
--- a/drivers/staging/vt6656/rf.h
+++ b/drivers/staging/vt6656/rf.h
@@ -30,10 +30,8 @@
 #ifndef __RF_H__
 #define __RF_H__
 
-#include "ttype.h"
 #include "device.h"
 
-/*---------------------  Export Definitions -------------------------*/
 //
 // Baseband RF pair definition in eeprom (Bits 6..0)
 //
@@ -55,20 +53,12 @@
 #define RF_EMU              0x80
 #define RF_MASK             0x7F
 
-
-
-/*---------------------  Export Classes  ----------------------------*/
-
-/*---------------------  Export Variables  --------------------------*/
 extern const u8 RFaby11aChannelIndex[200];
-/*---------------------  Export Functions  --------------------------*/
 
 int IFRFbWriteEmbedded(struct vnt_private *, u32 dwData);
 int RFbSetPower(struct vnt_private *, u32 uRATE, u32 uCH);
 int RFbRawSetPower(struct vnt_private *, u8 byPwr, u32 uRATE);
 void RFvRSSITodBm(struct vnt_private *, u8 byCurrRSSI, long *pldBm);
 void RFbRFTableDownload(struct vnt_private *pDevice);
-int s_bVT3226D0_11bLoCurrentAdjust(struct vnt_private *, u8 byChannel,
-	int b11bMode);
 
 #endif /* __RF_H__ */
diff --git a/drivers/staging/vt6656/rndis.h b/drivers/staging/vt6656/rndis.h
index fccf7e9..5e07306 100644
--- a/drivers/staging/vt6656/rndis.h
+++ b/drivers/staging/vt6656/rndis.h
@@ -27,11 +27,9 @@
  *
  */
 
-
 #ifndef __RNDIS_H__
 #define __RNDIS_H__
 
-/*---------------------  Export Definitions -------------------------*/
 #define MESSAGE_TYPE_READ               0x01
 #define MESSAGE_TYPE_WRITE              0x00
 #define MESSAGE_TYPE_LOCK_OR            0x02
@@ -66,96 +64,86 @@
 #define MESSAGE_REQUEST_RF_CH1          0x0C
 #define MESSAGE_REQUEST_RF_CH2          0x0D
 
-
 #define VIAUSB20_PACKET_HEADER          0x04
 
-
-/*---------------------  Export Classes  ----------------------------*/
-
 typedef struct _CMD_MESSAGE
 {
-    BYTE        byData[256];
+    u8        byData[256];
 } CMD_MESSAGE, *PCMD_MESSAGE;
 
 typedef struct _CMD_WRITE_MASK
 {
-    BYTE        byData;
-    BYTE        byMask;
+    u8        byData;
+    u8        byMask;
 } CMD_WRITE_MASK, *PCMD_WRITE_MASK;
 
 typedef struct _CMD_CARD_INIT
 {
-    BYTE        byInitClass;
-    BYTE        bExistSWNetAddr;
-    BYTE        bySWNetAddr[6];
-    BYTE        byShortRetryLimit;
-    BYTE        byLongRetryLimit;
+    u8        byInitClass;
+    u8        bExistSWNetAddr;
+    u8        bySWNetAddr[6];
+    u8        byShortRetryLimit;
+    u8        byLongRetryLimit;
 } CMD_CARD_INIT, *PCMD_CARD_INIT;
 
 typedef struct _RSP_CARD_INIT
 {
-    BYTE        byStatus;
-    BYTE        byNetAddr[6];
-    BYTE        byRFType;
-    BYTE        byMinChannel;
-    BYTE        byMaxChannel;
+    u8        byStatus;
+    u8        byNetAddr[6];
+    u8        byRFType;
+    u8        byMinChannel;
+    u8        byMaxChannel;
 } RSP_CARD_INIT, *PRSP_CARD_INIT;
 
 typedef struct _CMD_SET_KEY
 {
-    WORD        wKCTL;
-    BYTE        abyMacAddr[6];
-    BYTE        abyKey[16];
+    u16        wKCTL;
+    u8        abyMacAddr[6];
+    u8        abyKey[16];
 } CMD_SET_KEY, *PCMD_SET_KEY;
 
 typedef struct _CMD_CLRKEY_ENTRY
 {
-    BYTE        abyKeyEntry[11];
+    u8        abyKeyEntry[11];
 } CMD_CLRKEY_ENTRY, *PCMD_CLRKEY_ENTRY;
 
 typedef struct _CMD_WRITE_MISCFF
 {
-    DWORD       adwMiscFFData[22][4];  //a key entry has only 22 dwords
+    u32       adwMiscFFData[22][4];  //a key entry has only 22 dwords
 } CMD_WRITE_MISCFF, *PCMD_WRITE_MISCFF;
 
 typedef struct _CMD_SET_TSFTBTT
 {
-    BYTE        abyTSF_TBTT[8];
+    u8        abyTSF_TBTT[8];
 } CMD_SET_TSFTBTT, *PCMD_SET_TSFTBTT;
 
 typedef struct _CMD_SET_SSTIFS
 {
-    BYTE        bySIFS;
-    BYTE        byDIFS;
-    BYTE        byEIFS;
-    BYTE        bySlotTime;
-    BYTE        byCwMax_Min;
-    BYTE        byBBCR10;
+    u8        bySIFS;
+    u8        byDIFS;
+    u8        byEIFS;
+    u8        bySlotTime;
+    u8        byCwMax_Min;
+    u8        byBBCR10;
 } CMD_SET_SSTIFS, *PCMD_SET_SSTIFS;
 
 typedef struct _CMD_CHANGE_BBTYPE
 {
-    BYTE        bySIFS;
-    BYTE        byDIFS;
-    BYTE        byEIFS;
-    BYTE        bySlotTime;
-    BYTE        byCwMax_Min;
-    BYTE        byBBCR10;
-    BYTE        byBB_BBType;    //CR88
-    BYTE        byMAC_BBType;
-    DWORD       dwRSPINF_b_1;
-    DWORD       dwRSPINF_b_2;
-    DWORD       dwRSPINF_b_55;
-    DWORD       dwRSPINF_b_11;
-    WORD        wRSPINF_a[9];
+    u8        bySIFS;
+    u8        byDIFS;
+    u8        byEIFS;
+    u8        bySlotTime;
+    u8        byCwMax_Min;
+    u8        byBBCR10;
+    u8        byBB_BBType;    //CR88
+    u8        byMAC_BBType;
+    u32       dwRSPINF_b_1;
+    u32       dwRSPINF_b_2;
+    u32       dwRSPINF_b_55;
+    u32       dwRSPINF_b_11;
+    u16        wRSPINF_a[9];
 } CMD_CHANGE_BBTYPE, *PCMD_CHANGE_BBTYPE;
 
-/*---------------------  Export Macros -------------------------*/
-
-#define EXCH_WORD(w) ((WORD)((WORD)(w)<<8) | (WORD)((WORD)(w)>>8))
-
-/*---------------------  Export Variables  --------------------------*/
-
-/*---------------------  Export Functions  --------------------------*/
+#define EXCH_WORD(w) ((u16)((u16)(w)<<8) | (u16)((u16)(w)>>8))
 
 #endif /* _RNDIS_H_ */
diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c
index b939dcf..9bf2f8d 100644
--- a/drivers/staging/vt6656/rxtx.c
+++ b/drivers/staging/vt6656/rxtx.c
@@ -63,32 +63,22 @@
 #include "usbpipe.h"
 #include "iocmd.h"
 
-/*---------------------  Static Definitions -------------------------*/
-
-/*---------------------  Static Classes  ----------------------------*/
-
-/*---------------------  Static Variables  --------------------------*/
 static int          msglevel                = MSG_LEVEL_INFO;
 
-/*---------------------  Static Functions  --------------------------*/
-
-/*---------------------  Static Definitions -------------------------*/
-
-const WORD wTimeStampOff[2][MAX_RATE] = {
+const u16 wTimeStampOff[2][MAX_RATE] = {
         {384, 288, 226, 209, 54, 43, 37, 31, 28, 25, 24, 23}, // Long Preamble
         {384, 192, 130, 113, 54, 43, 37, 31, 28, 25, 24, 23}, // Short Preamble
     };
 
-const WORD wFB_Opt0[2][5] = {
+const u16 wFB_Opt0[2][5] = {
         {RATE_12M, RATE_18M, RATE_24M, RATE_36M, RATE_48M}, // fallback_rate0
         {RATE_12M, RATE_12M, RATE_18M, RATE_24M, RATE_36M}, // fallback_rate1
     };
-const WORD wFB_Opt1[2][5] = {
+const u16 wFB_Opt1[2][5] = {
         {RATE_12M, RATE_18M, RATE_24M, RATE_24M, RATE_36M}, // fallback_rate0
         {RATE_6M , RATE_6M,  RATE_12M, RATE_12M, RATE_18M}, // fallback_rate1
     };
 
-
 #define RTSDUR_BB       0
 #define RTSDUR_BA       1
 #define RTSDUR_AA       2
@@ -104,8 +94,6 @@ const WORD wFB_Opt1[2][5] = {
 #define DATADUR_A_F0    12
 #define DATADUR_A_F1    13
 
-/*---------------------  Static Functions  --------------------------*/
-
 static void s_vSaveTxPktInfo(struct vnt_private *pDevice, u8 byPktNum,
 	u8 *pbyDestAddr, u16 wPktLength, u16 wFIFOCtl);
 
@@ -114,16 +102,15 @@ static void *s_vGetFreeContext(struct vnt_private *pDevice);
 static void s_vGenerateTxParameter(struct vnt_private *pDevice,
 	u8 byPktType, u16 wCurrentRate,	void *pTxBufHead, void *pvRrvTime,
 	void *pvRTS, void *pvCTS, u32 cbFrameSize, int bNeedACK, u32 uDMAIdx,
-	PSEthernetHeader psEthHeader);
+	struct ethhdr *psEthHeader);
 
 static u32 s_uFillDataHead(struct vnt_private *pDevice,
 	u8 byPktType, u16 wCurrentRate, void *pTxDataHead, u32 cbFrameLength,
 	u32 uDMAIdx, int bNeedAck, u32 uFragIdx, u32 cbLastFragmentSize,
 	u32 uMACfragNum, u8 byFBOption);
 
-
 static void s_vGenerateMACHeader(struct vnt_private *pDevice,
-	u8 *pbyBufferAddr, u16 wDuration, PSEthernetHeader psEthHeader,
+	u8 *pbyBufferAddr, u16 wDuration, struct ethhdr *psEthHeader,
 	int bNeedEncrypt, u16 wFragType, u32 uDMAIdx, u32 uFragIdx);
 
 static void s_vFillTxKey(struct vnt_private *pDevice, u8 *pbyBuf,
@@ -145,7 +132,7 @@ static void s_vFillCTSHead(struct vnt_private *pDevice, u32 uDMAIdx,
 
 static void s_vFillRTSHead(struct vnt_private *pDevice, u8 byPktType,
 	void *pvRTS, u32 cbFrameLength, int bNeedAck, int bDisCRC,
-	PSEthernetHeader psEthHeader, u16 wCurrentRate, u8 byFBOption);
+	struct ethhdr *psEthHeader, u16 wCurrentRate, u8 byFBOption);
 
 static u32 s_uGetDataDuration(struct vnt_private *pDevice, u8 byDurType,
 	u32 cbFrameLength, u8 byPktType, u16 wRate, int bNeedAck,
@@ -156,9 +143,6 @@ static unsigned int s_uGetRTSCTSDuration(struct vnt_private *pDevice,
 	u8 byDurType, u32 cbFrameLength, u8 byPktType, u16 wRate,
 	int bNeedAck, u8 byFBOption);
 
-
-/*---------------------  Export Variables  --------------------------*/
-
 static void *s_vGetFreeContext(struct vnt_private *pDevice)
 {
 	PUSB_SEND_CONTEXT pContext = NULL;
@@ -181,7 +165,6 @@ static void *s_vGetFreeContext(struct vnt_private *pDevice)
     return (void *) pReturnContext;
 }
 
-
 static void s_vSaveTxPktInfo(struct vnt_private *pDevice, u8 byPktNum,
 	u8 *pbyDestAddr, u16 wPktLength, u16 wFIFOCtl)
 {
@@ -208,10 +191,9 @@ static void s_vFillTxKey(struct vnt_private *pDevice, u8 *pbyBuf,
 	u32 *pdwIV = (u32 *)pbyIVHead;
 	u32 *pdwExtIV = (u32 *)((u8 *)pbyIVHead + 4);
 	u16 wValue;
-	PS802_11Header pMACHeader = (PS802_11Header)pbyHdrBuf;
+	struct ieee80211_hdr *pMACHeader = (struct ieee80211_hdr *)pbyHdrBuf;
 	u32 dwRevIVCounter;
 
-
     //Fill TXKEY
     if (pTransmitKey == NULL)
         return;
@@ -222,13 +204,13 @@ static void s_vFillTxKey(struct vnt_private *pDevice, u8 *pbyBuf,
 
     if (pTransmitKey->byCipherSuite == KEY_CTL_WEP) {
         if (pTransmitKey->uKeyLength == WLAN_WEP232_KEYLEN ){
-            memcpy(pDevice->abyPRNG, (PBYTE)&(dwRevIVCounter), 3);
+            memcpy(pDevice->abyPRNG, (u8 *)&(dwRevIVCounter), 3);
             memcpy(pDevice->abyPRNG+3, pTransmitKey->abyKey, pTransmitKey->uKeyLength);
         } else {
-            memcpy(pbyBuf, (PBYTE)&(dwRevIVCounter), 3);
+            memcpy(pbyBuf, (u8 *)&(dwRevIVCounter), 3);
             memcpy(pbyBuf+3, pTransmitKey->abyKey, pTransmitKey->uKeyLength);
             if(pTransmitKey->uKeyLength == WLAN_WEP40_KEYLEN) {
-                memcpy(pbyBuf+8, (PBYTE)&(dwRevIVCounter), 3);
+                memcpy(pbyBuf+8, (u8 *)&(dwRevIVCounter), 3);
                 memcpy(pbyBuf+11, pTransmitKey->abyKey, pTransmitKey->uKeyLength);
             }
             memcpy(pDevice->abyPRNG, pbyBuf, 16);
@@ -252,7 +234,7 @@ static void s_vFillTxKey(struct vnt_private *pDevice, u8 *pbyBuf,
         // Make IV
         memcpy(pdwIV, pDevice->abyPRNG, 3);
 
-        *(pbyIVHead+3) = (BYTE)(((pDevice->byKeyIndex << 6) & 0xc0) | 0x20); // 0x20 is ExtIV
+        *(pbyIVHead+3) = (u8)(((pDevice->byKeyIndex << 6) & 0xc0) | 0x20); // 0x20 is ExtIV
         // Append IV&ExtIV after Mac Header
         *pdwExtIV = cpu_to_le32(pTransmitKey->dwTSC47_16);
 	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"vFillTxKey()---- pdwExtIV: %x\n",
@@ -267,49 +249,48 @@ static void s_vFillTxKey(struct vnt_private *pDevice, u8 *pbyBuf,
 
         // Make IV
         *pdwIV = 0;
-        *(pbyIVHead+3) = (BYTE)(((pDevice->byKeyIndex << 6) & 0xc0) | 0x20); // 0x20 is ExtIV
-        *pdwIV |= cpu_to_le16((WORD)(pTransmitKey->wTSC15_0));
+        *(pbyIVHead+3) = (u8)(((pDevice->byKeyIndex << 6) & 0xc0) | 0x20); // 0x20 is ExtIV
+        *pdwIV |= cpu_to_le16((u16)(pTransmitKey->wTSC15_0));
         //Append IV&ExtIV after Mac Header
         *pdwExtIV = cpu_to_le32(pTransmitKey->dwTSC47_16);
 
         //Fill MICHDR0
         *pMICHDR = 0x59;
-        *((PBYTE)(pMICHDR+1)) = 0; // TxPriority
-        memcpy(pMICHDR+2, &(pMACHeader->abyAddr2[0]), 6);
-        *((PBYTE)(pMICHDR+8)) = HIBYTE(HIWORD(pTransmitKey->dwTSC47_16));
-        *((PBYTE)(pMICHDR+9)) = LOBYTE(HIWORD(pTransmitKey->dwTSC47_16));
-        *((PBYTE)(pMICHDR+10)) = HIBYTE(LOWORD(pTransmitKey->dwTSC47_16));
-        *((PBYTE)(pMICHDR+11)) = LOBYTE(LOWORD(pTransmitKey->dwTSC47_16));
-        *((PBYTE)(pMICHDR+12)) = HIBYTE(pTransmitKey->wTSC15_0);
-        *((PBYTE)(pMICHDR+13)) = LOBYTE(pTransmitKey->wTSC15_0);
-        *((PBYTE)(pMICHDR+14)) = HIBYTE(wPayloadLen);
-        *((PBYTE)(pMICHDR+15)) = LOBYTE(wPayloadLen);
+        *((u8 *)(pMICHDR+1)) = 0; // TxPriority
+        memcpy(pMICHDR+2, &(pMACHeader->addr2[0]), 6);
+        *((u8 *)(pMICHDR+8)) = HIBYTE(HIWORD(pTransmitKey->dwTSC47_16));
+        *((u8 *)(pMICHDR+9)) = LOBYTE(HIWORD(pTransmitKey->dwTSC47_16));
+        *((u8 *)(pMICHDR+10)) = HIBYTE(LOWORD(pTransmitKey->dwTSC47_16));
+        *((u8 *)(pMICHDR+11)) = LOBYTE(LOWORD(pTransmitKey->dwTSC47_16));
+        *((u8 *)(pMICHDR+12)) = HIBYTE(pTransmitKey->wTSC15_0);
+        *((u8 *)(pMICHDR+13)) = LOBYTE(pTransmitKey->wTSC15_0);
+        *((u8 *)(pMICHDR+14)) = HIBYTE(wPayloadLen);
+        *((u8 *)(pMICHDR+15)) = LOBYTE(wPayloadLen);
 
         //Fill MICHDR1
-        *((PBYTE)(pMICHDR+16)) = 0; // HLEN[15:8]
+        *((u8 *)(pMICHDR+16)) = 0; // HLEN[15:8]
         if (pDevice->bLongHeader) {
-            *((PBYTE)(pMICHDR+17)) = 28; // HLEN[7:0]
+            *((u8 *)(pMICHDR+17)) = 28; // HLEN[7:0]
         } else {
-            *((PBYTE)(pMICHDR+17)) = 22; // HLEN[7:0]
+            *((u8 *)(pMICHDR+17)) = 22; // HLEN[7:0]
         }
-        wValue = cpu_to_le16(pMACHeader->wFrameCtl & 0xC78F);
-        memcpy(pMICHDR+18, (PBYTE)&wValue, 2); // MSKFRACTL
-        memcpy(pMICHDR+20, &(pMACHeader->abyAddr1[0]), 6);
-        memcpy(pMICHDR+26, &(pMACHeader->abyAddr2[0]), 6);
+        wValue = cpu_to_le16(pMACHeader->frame_control & 0xC78F);
+        memcpy(pMICHDR+18, (u8 *)&wValue, 2); // MSKFRACTL
+        memcpy(pMICHDR+20, &(pMACHeader->addr1[0]), 6);
+        memcpy(pMICHDR+26, &(pMACHeader->addr2[0]), 6);
 
         //Fill MICHDR2
-        memcpy(pMICHDR+32, &(pMACHeader->abyAddr3[0]), 6);
-        wValue = pMACHeader->wSeqCtl;
+        memcpy(pMICHDR+32, &(pMACHeader->addr3[0]), 6);
+        wValue = pMACHeader->seq_ctrl;
         wValue &= 0x000F;
         wValue = cpu_to_le16(wValue);
-        memcpy(pMICHDR+38, (PBYTE)&wValue, 2); // MSKSEQCTL
+        memcpy(pMICHDR+38, (u8 *)&wValue, 2); // MSKSEQCTL
         if (pDevice->bLongHeader) {
-            memcpy(pMICHDR+40, &(pMACHeader->abyAddr4[0]), 6);
+            memcpy(pMICHDR+40, &(pMACHeader->addr4[0]), 6);
         }
     }
 }
 
-
 static void s_vSWencryption(struct vnt_private *pDevice,
 	PSKeyItem pTransmitKey, u8 *pbyPayloadHead, u16 wPayloadSize)
 {
@@ -324,7 +305,7 @@ static void s_vSWencryption(struct vnt_private *pDevice,
         //=======================================================================
         // Append ICV after payload
         dwICV = CRCdwGetCrc32Ex(pbyPayloadHead, wPayloadSize, dwICV);//ICV(Payload)
-        pdwICV = (PDWORD)(pbyPayloadHead + wPayloadSize);
+        pdwICV = (u32 *)(pbyPayloadHead + wPayloadSize);
         // finally, we must invert dwCRC to get the correct answer
         *pdwICV = cpu_to_le32(~dwICV);
         // RC4 encryption
@@ -335,7 +316,7 @@ static void s_vSWencryption(struct vnt_private *pDevice,
         //=======================================================================
         //Append ICV after payload
         dwICV = CRCdwGetCrc32Ex(pbyPayloadHead, wPayloadSize, dwICV);//ICV(Payload)
-        pdwICV = (PDWORD)(pbyPayloadHead + wPayloadSize);
+        pdwICV = (u32 *)(pbyPayloadHead + wPayloadSize);
         // finally, we must invert dwCRC to get the correct answer
         *pdwICV = cpu_to_le32(~dwICV);
         // RC4 encryption
@@ -345,9 +326,6 @@ static void s_vSWencryption(struct vnt_private *pDevice,
     }
 }
 
-
-
-
 /*byPktType : PK_TYPE_11A     0
              PK_TYPE_11B     1
              PK_TYPE_11GB    2
@@ -360,9 +338,9 @@ static u32 s_uGetTxRsvTime(struct vnt_private *pDevice, u8 byPktType,
 
     uDataTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, cbFrameLength, wRate);
     if (byPktType == PK_TYPE_11B) {//llb,CCK mode
-        uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, (WORD)pDevice->byTopCCKBasicRate);
+        uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, (u16)pDevice->byTopCCKBasicRate);
     } else {//11g 2.4G OFDM mode & 11a 5G OFDM mode
-        uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, (WORD)pDevice->byTopOFDMBasicRate);
+        uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, (u16)pDevice->byTopOFDMBasicRate);
     }
 
     if (bNeedAck) {
@@ -381,7 +359,6 @@ static u32 s_uGetRTSCTSRsvTime(struct vnt_private *pDevice,
 
     uRrvTime = uRTSTime = uCTSTime = uAckTime = uDataTime = 0;
 
-
     uDataTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, cbFrameLength, wCurrentRate);
     if (byRTSRsvType == 0) { //RTSTxRrvTime_bb
         uRTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 20, pDevice->byTopCCKBasicRate);
@@ -447,7 +424,6 @@ static u32 s_uGetDataDuration(struct vnt_private *pDevice, u8 byDurType,
         }
         break;
 
-
     case DATADUR_A:    //DATADUR_A
         if (((uMACfragNum==1)) || (bLastFrag==1)) {//Non Frag or Last Frag
             if(bNeedAck){
@@ -566,7 +542,6 @@ static u32 s_uGetDataDuration(struct vnt_private *pDevice, u8 byDurType,
 	return 0;
 }
 
-
 //byFreqType: 0=>5GHZ 1=>2.4GHZ
 static u32 s_uGetRTSCTSDuration(struct vnt_private *pDevice, u8 byDurType,
 	u32 cbFrameLength, u8 byPktType, u16 wRate, int bNeedAck,
@@ -574,7 +549,6 @@ static u32 s_uGetRTSCTSDuration(struct vnt_private *pDevice, u8 byDurType,
 {
 	u32 uCTSTime = 0, uDurTime = 0;
 
-
     switch (byDurType) {
 
     case RTSDUR_BB:    //RTSDuration_bb
@@ -671,10 +645,10 @@ static u32 s_uFillDataHead(struct vnt_private *pDevice,
 		PSTxDataHead_ab pBuf = (PSTxDataHead_ab) pTxDataHead;
             //Get SignalField,ServiceField,Length
             BBvCalculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType,
-                (PWORD)&(pBuf->wTransmitLength), (PBYTE)&(pBuf->byServiceField), (PBYTE)&(pBuf->bySignalField)
+                (u16 *)&(pBuf->wTransmitLength), (u8 *)&(pBuf->byServiceField), (u8 *)&(pBuf->bySignalField)
             );
             //Get Duration and TimeStampOff
-            pBuf->wDuration = (WORD)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameLength, byPktType,
+            pBuf->wDuration = (u16)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameLength, byPktType,
                                                        wCurrentRate, bNeedAck, uFragIdx,
                                                        cbLastFragmentSize, uMACfragNum,
                                                        byFBOption); //1: 2.4GHz
@@ -688,17 +662,17 @@ static u32 s_uFillDataHead(struct vnt_private *pDevice,
                 PSTxDataHead_g pBuf = (PSTxDataHead_g)pTxDataHead;
                 //Get SignalField,ServiceField,Length
                 BBvCalculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType,
-                    (PWORD)&(pBuf->wTransmitLength_a), (PBYTE)&(pBuf->byServiceField_a), (PBYTE)&(pBuf->bySignalField_a)
+                    (u16 *)&(pBuf->wTransmitLength_a), (u8 *)&(pBuf->byServiceField_a), (u8 *)&(pBuf->bySignalField_a)
                 );
                 BBvCalculateParameter(pDevice, cbFrameLength, pDevice->byTopCCKBasicRate, PK_TYPE_11B,
-                    (PWORD)&(pBuf->wTransmitLength_b), (PBYTE)&(pBuf->byServiceField_b), (PBYTE)&(pBuf->bySignalField_b)
+                    (u16 *)&(pBuf->wTransmitLength_b), (u8 *)&(pBuf->byServiceField_b), (u8 *)&(pBuf->bySignalField_b)
                 );
                 //Get Duration and TimeStamp
-                pBuf->wDuration_a = (WORD)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameLength,
+                pBuf->wDuration_a = (u16)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameLength,
                                                              byPktType, wCurrentRate, bNeedAck, uFragIdx,
                                                              cbLastFragmentSize, uMACfragNum,
                                                              byFBOption); //1: 2.4GHz
-                pBuf->wDuration_b = (WORD)s_uGetDataDuration(pDevice, DATADUR_B, cbFrameLength,
+                pBuf->wDuration_b = (u16)s_uGetDataDuration(pDevice, DATADUR_B, cbFrameLength,
                                                              PK_TYPE_11B, pDevice->byTopCCKBasicRate,
                                                              bNeedAck, uFragIdx, cbLastFragmentSize,
                                                              uMACfragNum, byFBOption); //1: 2.4GHz
@@ -711,19 +685,19 @@ static u32 s_uFillDataHead(struct vnt_private *pDevice,
                 PSTxDataHead_g_FB pBuf = (PSTxDataHead_g_FB)pTxDataHead;
                 //Get SignalField,ServiceField,Length
                 BBvCalculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType,
-                    (PWORD)&(pBuf->wTransmitLength_a), (PBYTE)&(pBuf->byServiceField_a), (PBYTE)&(pBuf->bySignalField_a)
+                    (u16 *)&(pBuf->wTransmitLength_a), (u8 *)&(pBuf->byServiceField_a), (u8 *)&(pBuf->bySignalField_a)
                 );
                 BBvCalculateParameter(pDevice, cbFrameLength, pDevice->byTopCCKBasicRate, PK_TYPE_11B,
-                    (PWORD)&(pBuf->wTransmitLength_b), (PBYTE)&(pBuf->byServiceField_b), (PBYTE)&(pBuf->bySignalField_b)
+                    (u16 *)&(pBuf->wTransmitLength_b), (u8 *)&(pBuf->byServiceField_b), (u8 *)&(pBuf->bySignalField_b)
                 );
                 //Get Duration and TimeStamp
-                pBuf->wDuration_a = (WORD)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameLength, byPktType,
+                pBuf->wDuration_a = (u16)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameLength, byPktType,
                                              wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption); //1: 2.4GHz
-                pBuf->wDuration_b = (WORD)s_uGetDataDuration(pDevice, DATADUR_B, cbFrameLength, PK_TYPE_11B,
+                pBuf->wDuration_b = (u16)s_uGetDataDuration(pDevice, DATADUR_B, cbFrameLength, PK_TYPE_11B,
                                              pDevice->byTopCCKBasicRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption); //1: 2.4GHz
-                pBuf->wDuration_a_f0 = (WORD)s_uGetDataDuration(pDevice, DATADUR_A_F0, cbFrameLength, byPktType,
+                pBuf->wDuration_a_f0 = (u16)s_uGetDataDuration(pDevice, DATADUR_A_F0, cbFrameLength, byPktType,
                                              wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption); //1: 2.4GHz
-                pBuf->wDuration_a_f1 = (WORD)s_uGetDataDuration(pDevice, DATADUR_A_F1, cbFrameLength, byPktType,
+                pBuf->wDuration_a_f1 = (u16)s_uGetDataDuration(pDevice, DATADUR_A_F1, cbFrameLength, byPktType,
                                              wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption); //1: 2.4GHz
                 pBuf->wTimeStampOff_a = wTimeStampOff[pDevice->byPreambleType%2][wCurrentRate%MAX_RATE];
                 pBuf->wTimeStampOff_b = wTimeStampOff[pDevice->byPreambleType%2][pDevice->byTopCCKBasicRate%MAX_RATE];
@@ -737,14 +711,14 @@ static u32 s_uFillDataHead(struct vnt_private *pDevice,
             PSTxDataHead_a_FB pBuf = (PSTxDataHead_a_FB)pTxDataHead;
             //Get SignalField,ServiceField,Length
             BBvCalculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType,
-                (PWORD)&(pBuf->wTransmitLength), (PBYTE)&(pBuf->byServiceField), (PBYTE)&(pBuf->bySignalField)
+                (u16 *)&(pBuf->wTransmitLength), (u8 *)&(pBuf->byServiceField), (u8 *)&(pBuf->bySignalField)
             );
             //Get Duration and TimeStampOff
-            pBuf->wDuration = (WORD)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameLength, byPktType,
+            pBuf->wDuration = (u16)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameLength, byPktType,
                                         wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption); //0: 5GHz
-            pBuf->wDuration_f0 = (WORD)s_uGetDataDuration(pDevice, DATADUR_A_F0, cbFrameLength, byPktType,
+            pBuf->wDuration_f0 = (u16)s_uGetDataDuration(pDevice, DATADUR_A_F0, cbFrameLength, byPktType,
                                         wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption); //0: 5GHz
-            pBuf->wDuration_f1 = (WORD)s_uGetDataDuration(pDevice, DATADUR_A_F1, cbFrameLength, byPktType,
+            pBuf->wDuration_f1 = (u16)s_uGetDataDuration(pDevice, DATADUR_A_F1, cbFrameLength, byPktType,
                                         wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption); //0: 5GHz
             if(uDMAIdx!=TYPE_ATIMDMA) {
                 pBuf->wTimeStampOff = wTimeStampOff[pDevice->byPreambleType%2][wCurrentRate%MAX_RATE];
@@ -754,10 +728,10 @@ static u32 s_uFillDataHead(struct vnt_private *pDevice,
             PSTxDataHead_ab pBuf = (PSTxDataHead_ab)pTxDataHead;
             //Get SignalField,ServiceField,Length
             BBvCalculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType,
-                (PWORD)&(pBuf->wTransmitLength), (PBYTE)&(pBuf->byServiceField), (PBYTE)&(pBuf->bySignalField)
+                (u16 *)&(pBuf->wTransmitLength), (u8 *)&(pBuf->byServiceField), (u8 *)&(pBuf->bySignalField)
             );
             //Get Duration and TimeStampOff
-            pBuf->wDuration = (WORD)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameLength, byPktType,
+            pBuf->wDuration = (u16)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameLength, byPktType,
                                                        wCurrentRate, bNeedAck, uFragIdx,
                                                        cbLastFragmentSize, uMACfragNum,
                                                        byFBOption);
@@ -772,10 +746,10 @@ static u32 s_uFillDataHead(struct vnt_private *pDevice,
             PSTxDataHead_ab pBuf = (PSTxDataHead_ab)pTxDataHead;
             //Get SignalField,ServiceField,Length
             BBvCalculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType,
-                (PWORD)&(pBuf->wTransmitLength), (PBYTE)&(pBuf->byServiceField), (PBYTE)&(pBuf->bySignalField)
+                (u16 *)&(pBuf->wTransmitLength), (u8 *)&(pBuf->byServiceField), (u8 *)&(pBuf->bySignalField)
             );
             //Get Duration and TimeStampOff
-            pBuf->wDuration = (WORD)s_uGetDataDuration(pDevice, DATADUR_B, cbFrameLength, byPktType,
+            pBuf->wDuration = (u16)s_uGetDataDuration(pDevice, DATADUR_B, cbFrameLength, byPktType,
                                                        wCurrentRate, bNeedAck, uFragIdx,
                                                        cbLastFragmentSize, uMACfragNum,
                                                        byFBOption);
@@ -789,7 +763,7 @@ static u32 s_uFillDataHead(struct vnt_private *pDevice,
 
 static void s_vFillRTSHead(struct vnt_private *pDevice, u8 byPktType,
 	void *pvRTS, u32 cbFrameLength, int bNeedAck, int bDisCRC,
-	PSEthernetHeader psEthHeader, u16 wCurrentRate, u8 byFBOption)
+	struct ethhdr *psEthHeader, u16 wCurrentRate, u8 byFBOption)
 {
 	u32 uRTSFrameLen = 20;
 	u16 wLen = 0;
@@ -810,17 +784,17 @@ static void s_vFillRTSHead(struct vnt_private *pDevice, u8 byPktType,
             PSRTS_g pBuf = (PSRTS_g)pvRTS;
             //Get SignalField,ServiceField,Length
             BBvCalculateParameter(pDevice, uRTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B,
-                (PWORD)&(wLen), (PBYTE)&(pBuf->byServiceField_b), (PBYTE)&(pBuf->bySignalField_b)
+                (u16 *)&(wLen), (u8 *)&(pBuf->byServiceField_b), (u8 *)&(pBuf->bySignalField_b)
             );
             pBuf->wTransmitLength_b = cpu_to_le16(wLen);
             BBvCalculateParameter(pDevice, uRTSFrameLen, pDevice->byTopOFDMBasicRate, byPktType,
-                (PWORD)&(wLen), (PBYTE)&(pBuf->byServiceField_a), (PBYTE)&(pBuf->bySignalField_a)
+                (u16 *)&(wLen), (u8 *)&(pBuf->byServiceField_a), (u8 *)&(pBuf->bySignalField_a)
             );
             pBuf->wTransmitLength_a = cpu_to_le16(wLen);
             //Get Duration
-            pBuf->wDuration_bb = cpu_to_le16((WORD)s_uGetRTSCTSDuration(pDevice, RTSDUR_BB, cbFrameLength, PK_TYPE_11B, pDevice->byTopCCKBasicRate, bNeedAck, byFBOption));    //0:RTSDuration_bb, 1:2.4G, 1:CCKData
-            pBuf->wDuration_aa = cpu_to_le16((WORD)s_uGetRTSCTSDuration(pDevice, RTSDUR_AA, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //2:RTSDuration_aa, 1:2.4G, 2,3: 2.4G OFDMData
-            pBuf->wDuration_ba = cpu_to_le16((WORD)s_uGetRTSCTSDuration(pDevice, RTSDUR_BA, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //1:RTSDuration_ba, 1:2.4G, 2,3:2.4G OFDM Data
+            pBuf->wDuration_bb = cpu_to_le16((u16)s_uGetRTSCTSDuration(pDevice, RTSDUR_BB, cbFrameLength, PK_TYPE_11B, pDevice->byTopCCKBasicRate, bNeedAck, byFBOption));    //0:RTSDuration_bb, 1:2.4G, 1:CCKData
+            pBuf->wDuration_aa = cpu_to_le16((u16)s_uGetRTSCTSDuration(pDevice, RTSDUR_AA, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //2:RTSDuration_aa, 1:2.4G, 2,3: 2.4G OFDMData
+            pBuf->wDuration_ba = cpu_to_le16((u16)s_uGetRTSCTSDuration(pDevice, RTSDUR_BA, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //1:RTSDuration_ba, 1:2.4G, 2,3:2.4G OFDM Data
 
             pBuf->Data.wDurationID = pBuf->wDuration_aa;
             //Get RTS Frame body
@@ -829,7 +803,7 @@ static void s_vFillRTSHead(struct vnt_private *pDevice, u8 byPktType,
 	if ((pDevice->eOPMode == OP_MODE_ADHOC) ||
 	    (pDevice->eOPMode == OP_MODE_AP)) {
 		memcpy(&(pBuf->Data.abyRA[0]),
-		       &(psEthHeader->abyDstAddr[0]),
+		       &(psEthHeader->h_dest[0]),
 		       ETH_ALEN);
 	}
             else {
@@ -844,7 +818,7 @@ static void s_vFillRTSHead(struct vnt_private *pDevice, u8 byPktType,
 	}
             else {
 		    memcpy(&(pBuf->Data.abyTA[0]),
-			   &(psEthHeader->abySrcAddr[0]),
+			   &(psEthHeader->h_source[0]),
 			   ETH_ALEN);
             }
         }
@@ -852,21 +826,21 @@ static void s_vFillRTSHead(struct vnt_private *pDevice, u8 byPktType,
            PSRTS_g_FB pBuf = (PSRTS_g_FB)pvRTS;
             //Get SignalField,ServiceField,Length
             BBvCalculateParameter(pDevice, uRTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B,
-                (PWORD)&(wLen), (PBYTE)&(pBuf->byServiceField_b), (PBYTE)&(pBuf->bySignalField_b)
+                (u16 *)&(wLen), (u8 *)&(pBuf->byServiceField_b), (u8 *)&(pBuf->bySignalField_b)
             );
             pBuf->wTransmitLength_b = cpu_to_le16(wLen);
             BBvCalculateParameter(pDevice, uRTSFrameLen, pDevice->byTopOFDMBasicRate, byPktType,
-                (PWORD)&(wLen), (PBYTE)&(pBuf->byServiceField_a), (PBYTE)&(pBuf->bySignalField_a)
+                (u16 *)&(wLen), (u8 *)&(pBuf->byServiceField_a), (u8 *)&(pBuf->bySignalField_a)
             );
             pBuf->wTransmitLength_a = cpu_to_le16(wLen);
             //Get Duration
-            pBuf->wDuration_bb = cpu_to_le16((WORD)s_uGetRTSCTSDuration(pDevice, RTSDUR_BB, cbFrameLength, PK_TYPE_11B, pDevice->byTopCCKBasicRate, bNeedAck, byFBOption));    //0:RTSDuration_bb, 1:2.4G, 1:CCKData
-            pBuf->wDuration_aa = cpu_to_le16((WORD)s_uGetRTSCTSDuration(pDevice, RTSDUR_AA, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //2:RTSDuration_aa, 1:2.4G, 2,3:2.4G OFDMData
-            pBuf->wDuration_ba = cpu_to_le16((WORD)s_uGetRTSCTSDuration(pDevice, RTSDUR_BA, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //1:RTSDuration_ba, 1:2.4G, 2,3:2.4G OFDMData
-            pBuf->wRTSDuration_ba_f0 = cpu_to_le16((WORD)s_uGetRTSCTSDuration(pDevice, RTSDUR_BA_F0, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption));    //4:wRTSDuration_ba_f0, 1:2.4G, 1:CCKData
-            pBuf->wRTSDuration_aa_f0 = cpu_to_le16((WORD)s_uGetRTSCTSDuration(pDevice, RTSDUR_AA_F0, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption));    //5:wRTSDuration_aa_f0, 1:2.4G, 1:CCKData
-            pBuf->wRTSDuration_ba_f1 = cpu_to_le16((WORD)s_uGetRTSCTSDuration(pDevice, RTSDUR_BA_F1, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption));    //6:wRTSDuration_ba_f1, 1:2.4G, 1:CCKData
-            pBuf->wRTSDuration_aa_f1 = cpu_to_le16((WORD)s_uGetRTSCTSDuration(pDevice, RTSDUR_AA_F1, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption));    //7:wRTSDuration_aa_f1, 1:2.4G, 1:CCKData
+            pBuf->wDuration_bb = cpu_to_le16((u16)s_uGetRTSCTSDuration(pDevice, RTSDUR_BB, cbFrameLength, PK_TYPE_11B, pDevice->byTopCCKBasicRate, bNeedAck, byFBOption));    //0:RTSDuration_bb, 1:2.4G, 1:CCKData
+            pBuf->wDuration_aa = cpu_to_le16((u16)s_uGetRTSCTSDuration(pDevice, RTSDUR_AA, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //2:RTSDuration_aa, 1:2.4G, 2,3:2.4G OFDMData
+            pBuf->wDuration_ba = cpu_to_le16((u16)s_uGetRTSCTSDuration(pDevice, RTSDUR_BA, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //1:RTSDuration_ba, 1:2.4G, 2,3:2.4G OFDMData
+            pBuf->wRTSDuration_ba_f0 = cpu_to_le16((u16)s_uGetRTSCTSDuration(pDevice, RTSDUR_BA_F0, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption));    //4:wRTSDuration_ba_f0, 1:2.4G, 1:CCKData
+            pBuf->wRTSDuration_aa_f0 = cpu_to_le16((u16)s_uGetRTSCTSDuration(pDevice, RTSDUR_AA_F0, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption));    //5:wRTSDuration_aa_f0, 1:2.4G, 1:CCKData
+            pBuf->wRTSDuration_ba_f1 = cpu_to_le16((u16)s_uGetRTSCTSDuration(pDevice, RTSDUR_BA_F1, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption));    //6:wRTSDuration_ba_f1, 1:2.4G, 1:CCKData
+            pBuf->wRTSDuration_aa_f1 = cpu_to_le16((u16)s_uGetRTSCTSDuration(pDevice, RTSDUR_AA_F1, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption));    //7:wRTSDuration_aa_f1, 1:2.4G, 1:CCKData
             pBuf->Data.wDurationID = pBuf->wDuration_aa;
             //Get RTS Frame body
             pBuf->Data.wFrameControl = TYPE_CTL_RTS;//0x00B4
@@ -874,7 +848,7 @@ static void s_vFillRTSHead(struct vnt_private *pDevice, u8 byPktType,
 	if ((pDevice->eOPMode == OP_MODE_ADHOC) ||
 	    (pDevice->eOPMode == OP_MODE_AP)) {
 		memcpy(&(pBuf->Data.abyRA[0]),
-		       &(psEthHeader->abyDstAddr[0]),
+		       &(psEthHeader->h_dest[0]),
 		       ETH_ALEN);
 	}
             else {
@@ -890,7 +864,7 @@ static void s_vFillRTSHead(struct vnt_private *pDevice, u8 byPktType,
 	}
             else {
 		    memcpy(&(pBuf->Data.abyTA[0]),
-			   &(psEthHeader->abySrcAddr[0]),
+			   &(psEthHeader->h_source[0]),
 			   ETH_ALEN);
             }
 
@@ -901,11 +875,11 @@ static void s_vFillRTSHead(struct vnt_private *pDevice, u8 byPktType,
             PSRTS_ab pBuf = (PSRTS_ab)pvRTS;
             //Get SignalField,ServiceField,Length
             BBvCalculateParameter(pDevice, uRTSFrameLen, pDevice->byTopOFDMBasicRate, byPktType,
-                (PWORD)&(wLen), (PBYTE)&(pBuf->byServiceField), (PBYTE)&(pBuf->bySignalField)
+                (u16 *)&(wLen), (u8 *)&(pBuf->byServiceField), (u8 *)&(pBuf->bySignalField)
             );
             pBuf->wTransmitLength = cpu_to_le16(wLen);
             //Get Duration
-            pBuf->wDuration = cpu_to_le16((WORD)s_uGetRTSCTSDuration(pDevice, RTSDUR_AA, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //0:RTSDuration_aa, 0:5G, 0: 5G OFDMData
+            pBuf->wDuration = cpu_to_le16((u16)s_uGetRTSCTSDuration(pDevice, RTSDUR_AA, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //0:RTSDuration_aa, 0:5G, 0: 5G OFDMData
     	    pBuf->Data.wDurationID = pBuf->wDuration;
             //Get RTS Frame body
             pBuf->Data.wFrameControl = TYPE_CTL_RTS;//0x00B4
@@ -913,7 +887,7 @@ static void s_vFillRTSHead(struct vnt_private *pDevice, u8 byPktType,
 	if ((pDevice->eOPMode == OP_MODE_ADHOC) ||
 	    (pDevice->eOPMode == OP_MODE_AP)) {
 		memcpy(&(pBuf->Data.abyRA[0]),
-		       &(psEthHeader->abyDstAddr[0]),
+		       &(psEthHeader->h_dest[0]),
 		       ETH_ALEN);
 	} else {
 		memcpy(&(pBuf->Data.abyRA[0]),
@@ -927,7 +901,7 @@ static void s_vFillRTSHead(struct vnt_private *pDevice, u8 byPktType,
 		       ETH_ALEN);
 	} else {
 		memcpy(&(pBuf->Data.abyTA[0]),
-		       &(psEthHeader->abySrcAddr[0]),
+		       &(psEthHeader->h_source[0]),
 		       ETH_ALEN);
 	}
 
@@ -936,13 +910,13 @@ static void s_vFillRTSHead(struct vnt_private *pDevice, u8 byPktType,
             PSRTS_a_FB pBuf = (PSRTS_a_FB)pvRTS;
             //Get SignalField,ServiceField,Length
             BBvCalculateParameter(pDevice, uRTSFrameLen, pDevice->byTopOFDMBasicRate, byPktType,
-                (PWORD)&(wLen), (PBYTE)&(pBuf->byServiceField), (PBYTE)&(pBuf->bySignalField)
+                (u16 *)&(wLen), (u8 *)&(pBuf->byServiceField), (u8 *)&(pBuf->bySignalField)
             );
             pBuf->wTransmitLength = cpu_to_le16(wLen);
             //Get Duration
-            pBuf->wDuration = cpu_to_le16((WORD)s_uGetRTSCTSDuration(pDevice, RTSDUR_AA, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //0:RTSDuration_aa, 0:5G, 0: 5G OFDMData
-    	    pBuf->wRTSDuration_f0 = cpu_to_le16((WORD)s_uGetRTSCTSDuration(pDevice, RTSDUR_AA_F0, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //5:RTSDuration_aa_f0, 0:5G, 0: 5G OFDMData
-    	    pBuf->wRTSDuration_f1 = cpu_to_le16((WORD)s_uGetRTSCTSDuration(pDevice, RTSDUR_AA_F1, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //7:RTSDuration_aa_f1, 0:5G, 0:
+            pBuf->wDuration = cpu_to_le16((u16)s_uGetRTSCTSDuration(pDevice, RTSDUR_AA, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //0:RTSDuration_aa, 0:5G, 0: 5G OFDMData
+    	    pBuf->wRTSDuration_f0 = cpu_to_le16((u16)s_uGetRTSCTSDuration(pDevice, RTSDUR_AA_F0, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //5:RTSDuration_aa_f0, 0:5G, 0: 5G OFDMData
+    	    pBuf->wRTSDuration_f1 = cpu_to_le16((u16)s_uGetRTSCTSDuration(pDevice, RTSDUR_AA_F1, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //7:RTSDuration_aa_f1, 0:5G, 0:
     	    pBuf->Data.wDurationID = pBuf->wDuration;
     	    //Get RTS Frame body
             pBuf->Data.wFrameControl = TYPE_CTL_RTS;//0x00B4
@@ -950,7 +924,7 @@ static void s_vFillRTSHead(struct vnt_private *pDevice, u8 byPktType,
 	if ((pDevice->eOPMode == OP_MODE_ADHOC) ||
 	    (pDevice->eOPMode == OP_MODE_AP)) {
 		memcpy(&(pBuf->Data.abyRA[0]),
-		       &(psEthHeader->abyDstAddr[0]),
+		       &(psEthHeader->h_dest[0]),
 		       ETH_ALEN);
 	} else {
 		memcpy(&(pBuf->Data.abyRA[0]),
@@ -963,7 +937,7 @@ static void s_vFillRTSHead(struct vnt_private *pDevice, u8 byPktType,
 		       ETH_ALEN);
 	} else {
 		memcpy(&(pBuf->Data.abyTA[0]),
-		       &(psEthHeader->abySrcAddr[0]),
+		       &(psEthHeader->h_source[0]),
 		       ETH_ALEN);
 	}
         }
@@ -972,11 +946,11 @@ static void s_vFillRTSHead(struct vnt_private *pDevice, u8 byPktType,
         PSRTS_ab pBuf = (PSRTS_ab)pvRTS;
         //Get SignalField,ServiceField,Length
         BBvCalculateParameter(pDevice, uRTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B,
-            (PWORD)&(wLen), (PBYTE)&(pBuf->byServiceField), (PBYTE)&(pBuf->bySignalField)
+            (u16 *)&(wLen), (u8 *)&(pBuf->byServiceField), (u8 *)&(pBuf->bySignalField)
         );
         pBuf->wTransmitLength = cpu_to_le16(wLen);
         //Get Duration
-        pBuf->wDuration = cpu_to_le16((WORD)s_uGetRTSCTSDuration(pDevice, RTSDUR_BB, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //0:RTSDuration_bb, 1:2.4G, 1:CCKData
+        pBuf->wDuration = cpu_to_le16((u16)s_uGetRTSCTSDuration(pDevice, RTSDUR_BB, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //0:RTSDuration_bb, 1:2.4G, 1:CCKData
         pBuf->Data.wDurationID = pBuf->wDuration;
         //Get RTS Frame body
         pBuf->Data.wFrameControl = TYPE_CTL_RTS;//0x00B4
@@ -984,7 +958,7 @@ static void s_vFillRTSHead(struct vnt_private *pDevice, u8 byPktType,
 	if ((pDevice->eOPMode == OP_MODE_ADHOC) ||
             (pDevice->eOPMode == OP_MODE_AP)) {
 		memcpy(&(pBuf->Data.abyRA[0]),
-		       &(psEthHeader->abyDstAddr[0]),
+		       &(psEthHeader->h_dest[0]),
 		       ETH_ALEN);
         }
         else {
@@ -999,7 +973,7 @@ static void s_vFillRTSHead(struct vnt_private *pDevice, u8 byPktType,
 		       ETH_ALEN);
 	} else {
 		memcpy(&(pBuf->Data.abyTA[0]),
-		       &(psEthHeader->abySrcAddr[0]),
+		       &(psEthHeader->h_source[0]),
 		       ETH_ALEN);
         }
     }
@@ -1028,18 +1002,18 @@ static void s_vFillCTSHead(struct vnt_private *pDevice, u32 uDMAIdx,
             PSCTS_FB pBuf = (PSCTS_FB)pvCTS;
             //Get SignalField,ServiceField,Length
             BBvCalculateParameter(pDevice, uCTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B,
-                (PWORD)&(wLen), (PBYTE)&(pBuf->byServiceField_b), (PBYTE)&(pBuf->bySignalField_b)
+                (u16 *)&(wLen), (u8 *)&(pBuf->byServiceField_b), (u8 *)&(pBuf->bySignalField_b)
             );
             pBuf->wTransmitLength_b = cpu_to_le16(wLen);
-            pBuf->wDuration_ba = (WORD)s_uGetRTSCTSDuration(pDevice, CTSDUR_BA, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption); //3:CTSDuration_ba, 1:2.4G, 2,3:2.4G OFDM Data
+            pBuf->wDuration_ba = (u16)s_uGetRTSCTSDuration(pDevice, CTSDUR_BA, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption); //3:CTSDuration_ba, 1:2.4G, 2,3:2.4G OFDM Data
             pBuf->wDuration_ba += pDevice->wCTSDuration;
             pBuf->wDuration_ba = cpu_to_le16(pBuf->wDuration_ba);
             //Get CTSDuration_ba_f0
-            pBuf->wCTSDuration_ba_f0 = (WORD)s_uGetRTSCTSDuration(pDevice, CTSDUR_BA_F0, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption); //8:CTSDuration_ba_f0, 1:2.4G, 2,3:2.4G OFDM Data
+            pBuf->wCTSDuration_ba_f0 = (u16)s_uGetRTSCTSDuration(pDevice, CTSDUR_BA_F0, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption); //8:CTSDuration_ba_f0, 1:2.4G, 2,3:2.4G OFDM Data
             pBuf->wCTSDuration_ba_f0 += pDevice->wCTSDuration;
             pBuf->wCTSDuration_ba_f0 = cpu_to_le16(pBuf->wCTSDuration_ba_f0);
             //Get CTSDuration_ba_f1
-            pBuf->wCTSDuration_ba_f1 = (WORD)s_uGetRTSCTSDuration(pDevice, CTSDUR_BA_F1, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption); //9:CTSDuration_ba_f1, 1:2.4G, 2,3:2.4G OFDM Data
+            pBuf->wCTSDuration_ba_f1 = (u16)s_uGetRTSCTSDuration(pDevice, CTSDUR_BA_F1, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption); //9:CTSDuration_ba_f1, 1:2.4G, 2,3:2.4G OFDM Data
             pBuf->wCTSDuration_ba_f1 += pDevice->wCTSDuration;
             pBuf->wCTSDuration_ba_f1 = cpu_to_le16(pBuf->wCTSDuration_ba_f1);
             //Get CTS Frame body
@@ -1053,11 +1027,11 @@ static void s_vFillCTSHead(struct vnt_private *pDevice, u32 uDMAIdx,
             PSCTS pBuf = (PSCTS)pvCTS;
             //Get SignalField,ServiceField,Length
             BBvCalculateParameter(pDevice, uCTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B,
-                (PWORD)&(wLen), (PBYTE)&(pBuf->byServiceField_b), (PBYTE)&(pBuf->bySignalField_b)
+                (u16 *)&(wLen), (u8 *)&(pBuf->byServiceField_b), (u8 *)&(pBuf->bySignalField_b)
             );
             pBuf->wTransmitLength_b = cpu_to_le16(wLen);
             //Get CTSDuration_ba
-            pBuf->wDuration_ba = cpu_to_le16((WORD)s_uGetRTSCTSDuration(pDevice, CTSDUR_BA, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //3:CTSDuration_ba, 1:2.4G, 2,3:2.4G OFDM Data
+            pBuf->wDuration_ba = cpu_to_le16((u16)s_uGetRTSCTSDuration(pDevice, CTSDUR_BA, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //3:CTSDuration_ba, 1:2.4G, 2,3:2.4G OFDM Data
             pBuf->wDuration_ba += pDevice->wCTSDuration;
             pBuf->wDuration_ba = cpu_to_le16(pBuf->wDuration_ba);
 
@@ -1098,7 +1072,7 @@ static void s_vFillCTSHead(struct vnt_private *pDevice, u32 uDMAIdx,
 static void s_vGenerateTxParameter(struct vnt_private *pDevice,
 	u8 byPktType, u16 wCurrentRate,	void *pTxBufHead, void *pvRrvTime,
 	void *pvRTS, void *pvCTS, u32 cbFrameSize, int bNeedACK, u32 uDMAIdx,
-	PSEthernetHeader psEthHeader)
+	struct ethhdr *psEthHeader)
 {
 	u32 cbMACHdLen = WLAN_HDR_ADDR3_LEN; /* 24 */
 	u16 wFifoCtl;
@@ -1130,11 +1104,11 @@ static void s_vGenerateTxParameter(struct vnt_private *pDevice,
             //Fill RsvTime
             if (pvRrvTime) {
                 PSRrvTime_gRTS pBuf = (PSRrvTime_gRTS)pvRrvTime;
-                pBuf->wRTSTxRrvTime_aa = cpu_to_le16((WORD)s_uGetRTSCTSRsvTime(pDevice, 2, byPktType, cbFrameSize, wCurrentRate));//2:RTSTxRrvTime_aa, 1:2.4GHz
-                pBuf->wRTSTxRrvTime_ba = cpu_to_le16((WORD)s_uGetRTSCTSRsvTime(pDevice, 1, byPktType, cbFrameSize, wCurrentRate));//1:RTSTxRrvTime_ba, 1:2.4GHz
-                pBuf->wRTSTxRrvTime_bb = cpu_to_le16((WORD)s_uGetRTSCTSRsvTime(pDevice, 0, byPktType, cbFrameSize, wCurrentRate));//0:RTSTxRrvTime_bb, 1:2.4GHz
-                pBuf->wTxRrvTime_a = cpu_to_le16((WORD) s_uGetTxRsvTime(pDevice, byPktType, cbFrameSize, wCurrentRate, bNeedACK));//2.4G OFDM
-                pBuf->wTxRrvTime_b = cpu_to_le16((WORD) s_uGetTxRsvTime(pDevice, PK_TYPE_11B, cbFrameSize, pDevice->byTopCCKBasicRate, bNeedACK));//1:CCK
+                pBuf->wRTSTxRrvTime_aa = cpu_to_le16((u16)s_uGetRTSCTSRsvTime(pDevice, 2, byPktType, cbFrameSize, wCurrentRate));//2:RTSTxRrvTime_aa, 1:2.4GHz
+                pBuf->wRTSTxRrvTime_ba = cpu_to_le16((u16)s_uGetRTSCTSRsvTime(pDevice, 1, byPktType, cbFrameSize, wCurrentRate));//1:RTSTxRrvTime_ba, 1:2.4GHz
+                pBuf->wRTSTxRrvTime_bb = cpu_to_le16((u16)s_uGetRTSCTSRsvTime(pDevice, 0, byPktType, cbFrameSize, wCurrentRate));//0:RTSTxRrvTime_bb, 1:2.4GHz
+                pBuf->wTxRrvTime_a = cpu_to_le16((u16) s_uGetTxRsvTime(pDevice, byPktType, cbFrameSize, wCurrentRate, bNeedACK));//2.4G OFDM
+                pBuf->wTxRrvTime_b = cpu_to_le16((u16) s_uGetTxRsvTime(pDevice, PK_TYPE_11B, cbFrameSize, pDevice->byTopCCKBasicRate, bNeedACK));//1:CCK
             }
             //Fill RTS
             s_vFillRTSHead(pDevice, byPktType, pvRTS, cbFrameSize, bNeedACK, bDisCRC, psEthHeader, wCurrentRate, byFBOption);
@@ -1144,9 +1118,9 @@ static void s_vGenerateTxParameter(struct vnt_private *pDevice,
             //Fill RsvTime
             if (pvRrvTime) {
                 PSRrvTime_gCTS pBuf = (PSRrvTime_gCTS)pvRrvTime;
-                pBuf->wTxRrvTime_a = cpu_to_le16((WORD)s_uGetTxRsvTime(pDevice, byPktType, cbFrameSize, wCurrentRate, bNeedACK));//2.4G OFDM
-                pBuf->wTxRrvTime_b = cpu_to_le16((WORD)s_uGetTxRsvTime(pDevice, PK_TYPE_11B, cbFrameSize, pDevice->byTopCCKBasicRate, bNeedACK));//1:CCK
-                pBuf->wCTSTxRrvTime_ba = cpu_to_le16((WORD)s_uGetRTSCTSRsvTime(pDevice, 3, byPktType, cbFrameSize, wCurrentRate));//3:CTSTxRrvTime_Ba, 1:2.4GHz
+                pBuf->wTxRrvTime_a = cpu_to_le16((u16)s_uGetTxRsvTime(pDevice, byPktType, cbFrameSize, wCurrentRate, bNeedACK));//2.4G OFDM
+                pBuf->wTxRrvTime_b = cpu_to_le16((u16)s_uGetTxRsvTime(pDevice, PK_TYPE_11B, cbFrameSize, pDevice->byTopCCKBasicRate, bNeedACK));//1:CCK
+                pBuf->wCTSTxRrvTime_ba = cpu_to_le16((u16)s_uGetRTSCTSRsvTime(pDevice, 3, byPktType, cbFrameSize, wCurrentRate));//3:CTSTxRrvTime_Ba, 1:2.4GHz
             }
             //Fill CTS
             s_vFillCTSHead(pDevice, uDMAIdx, byPktType, pvCTS, cbFrameSize, bNeedACK, bDisCRC, wCurrentRate, byFBOption);
@@ -1158,8 +1132,8 @@ static void s_vGenerateTxParameter(struct vnt_private *pDevice,
             //Fill RsvTime
             if (pvRrvTime) {
                 PSRrvTime_ab pBuf = (PSRrvTime_ab)pvRrvTime;
-                pBuf->wRTSTxRrvTime = cpu_to_le16((WORD)s_uGetRTSCTSRsvTime(pDevice, 2, byPktType, cbFrameSize, wCurrentRate));//2:RTSTxRrvTime_aa, 0:5GHz
-                pBuf->wTxRrvTime = cpu_to_le16((WORD)s_uGetTxRsvTime(pDevice, byPktType, cbFrameSize, wCurrentRate, bNeedACK));//0:OFDM
+                pBuf->wRTSTxRrvTime = cpu_to_le16((u16)s_uGetRTSCTSRsvTime(pDevice, 2, byPktType, cbFrameSize, wCurrentRate));//2:RTSTxRrvTime_aa, 0:5GHz
+                pBuf->wTxRrvTime = cpu_to_le16((u16)s_uGetTxRsvTime(pDevice, byPktType, cbFrameSize, wCurrentRate, bNeedACK));//0:OFDM
             }
             //Fill RTS
             s_vFillRTSHead(pDevice, byPktType, pvRTS, cbFrameSize, bNeedACK, bDisCRC, psEthHeader, wCurrentRate, byFBOption);
@@ -1168,7 +1142,7 @@ static void s_vGenerateTxParameter(struct vnt_private *pDevice,
             //Fill RsvTime
             if (pvRrvTime) {
                 PSRrvTime_ab pBuf = (PSRrvTime_ab)pvRrvTime;
-                pBuf->wTxRrvTime = cpu_to_le16((WORD)s_uGetTxRsvTime(pDevice, PK_TYPE_11A, cbFrameSize, wCurrentRate, bNeedACK)); //0:OFDM
+                pBuf->wTxRrvTime = cpu_to_le16((u16)s_uGetTxRsvTime(pDevice, PK_TYPE_11A, cbFrameSize, wCurrentRate, bNeedACK)); //0:OFDM
             }
         }
     }
@@ -1178,8 +1152,8 @@ static void s_vGenerateTxParameter(struct vnt_private *pDevice,
             //Fill RsvTime
             if (pvRrvTime) {
                 PSRrvTime_ab pBuf = (PSRrvTime_ab)pvRrvTime;
-                pBuf->wRTSTxRrvTime = cpu_to_le16((WORD)s_uGetRTSCTSRsvTime(pDevice, 0, byPktType, cbFrameSize, wCurrentRate));//0:RTSTxRrvTime_bb, 1:2.4GHz
-                pBuf->wTxRrvTime = cpu_to_le16((WORD)s_uGetTxRsvTime(pDevice, PK_TYPE_11B, cbFrameSize, wCurrentRate, bNeedACK));//1:CCK
+                pBuf->wRTSTxRrvTime = cpu_to_le16((u16)s_uGetRTSCTSRsvTime(pDevice, 0, byPktType, cbFrameSize, wCurrentRate));//0:RTSTxRrvTime_bb, 1:2.4GHz
+                pBuf->wTxRrvTime = cpu_to_le16((u16)s_uGetTxRsvTime(pDevice, PK_TYPE_11B, cbFrameSize, wCurrentRate, bNeedACK));//1:CCK
             }
             //Fill RTS
             s_vFillRTSHead(pDevice, byPktType, pvRTS, cbFrameSize, bNeedACK, bDisCRC, psEthHeader, wCurrentRate, byFBOption);
@@ -1188,21 +1162,21 @@ static void s_vGenerateTxParameter(struct vnt_private *pDevice,
             //Fill RsvTime
             if (pvRrvTime) {
                 PSRrvTime_ab pBuf = (PSRrvTime_ab)pvRrvTime;
-                pBuf->wTxRrvTime = cpu_to_le16((WORD)s_uGetTxRsvTime(pDevice, PK_TYPE_11B, cbFrameSize, wCurrentRate, bNeedACK)); //1:CCK
+                pBuf->wTxRrvTime = cpu_to_le16((u16)s_uGetTxRsvTime(pDevice, PK_TYPE_11B, cbFrameSize, wCurrentRate, bNeedACK)); //1:CCK
             }
         }
     }
     //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"s_vGenerateTxParameter END.\n");
 }
 /*
-    PBYTE pbyBuffer,//point to pTxBufHead
-    WORD  wFragType,//00:Non-Frag, 01:Start, 02:Mid, 03:Last
+    u8 * pbyBuffer,//point to pTxBufHead
+    u16  wFragType,//00:Non-Frag, 01:Start, 02:Mid, 03:Last
     unsigned int  cbFragmentSize,//Hdr+payoad+FCS
 */
 
 static int s_bPacketToWirelessUsb(struct vnt_private *pDevice, u8 byPktType,
 	u8 *usbPacketBuf, int bNeedEncryption, u32 uSkbPacketLen, u32 uDMAIdx,
-	PSEthernetHeader psEthHeader, u8 *pPacket, PSKeyItem pTransmitKey,
+	struct ethhdr *psEthHeader, u8 *pPacket, PSKeyItem pTransmitKey,
 	u32 uNodeIndex, u16 wCurrentRate, u32 *pcbHeaderLen, u32 *pcbTotalLen)
 {
 	struct vnt_manager *pMgmt = &pDevice->vnt_mgmt;
@@ -1240,7 +1214,7 @@ static int s_bPacketToWirelessUsb(struct vnt_private *pDevice, u8 byPktType,
     memset(pTxBufHead, 0, sizeof(TX_BUFFER));
 
     // Get pkt type
-    if (ntohs(psEthHeader->wType) > ETH_DATA_LEN) {
+    if (ntohs(psEthHeader->h_proto) > ETH_DATA_LEN) {
         if (pDevice->dwDiagRefCount == 0) {
             cb802_1_H_len = 8;
         } else {
@@ -1253,7 +1227,7 @@ static int s_bPacketToWirelessUsb(struct vnt_private *pDevice, u8 byPktType,
     cbFrameBodySize = uSkbPacketLen - ETH_HLEN + cb802_1_H_len;
 
     //Set packet type
-    pTxBufHead->wFIFOCtl |= (WORD)(byPktType<<8);
+    pTxBufHead->wFIFOCtl |= (u16)(byPktType<<8);
 
     if (pDevice->dwDiagRefCount != 0) {
         bNeedACK = false;
@@ -1261,7 +1235,7 @@ static int s_bPacketToWirelessUsb(struct vnt_private *pDevice, u8 byPktType,
     } else { //if (pDevice->dwDiagRefCount != 0) {
 	if ((pDevice->eOPMode == OP_MODE_ADHOC) ||
 	    (pDevice->eOPMode == OP_MODE_AP)) {
-		if (is_multicast_ether_addr(psEthHeader->abyDstAddr)) {
+		if (is_multicast_ether_addr(psEthHeader->h_dest)) {
 			bNeedACK = false;
 			pTxBufHead->wFIFOCtl =
 				pTxBufHead->wFIFOCtl & (~FIFOCTL_NEEDACK);
@@ -1293,7 +1267,7 @@ static int s_bPacketToWirelessUsb(struct vnt_private *pDevice, u8 byPktType,
     } else {
         cbMACHdLen = WLAN_HDR_ADDR3_LEN;
     }
-    pTxBufHead->wFragCtl |= (WORD)(cbMACHdLen << 10);
+    pTxBufHead->wFragCtl |= (u16)(cbMACHdLen << 10);
 
     //Set FIFOCTL_GrpAckPolicy
     if (pDevice->bGrpAckPolicy == true) {//0000 0100 0000 0000
@@ -1326,7 +1300,6 @@ static int s_bPacketToWirelessUsb(struct vnt_private *pDevice, u8 byPktType,
         }
     }
 
-
     if ((bNeedEncryption) && (pTransmitKey != NULL))  {
         if (pTransmitKey->byCipherSuite == KEY_CTL_WEP) {
             cbIVlen = 4;
@@ -1358,7 +1331,7 @@ static int s_bPacketToWirelessUsb(struct vnt_private *pDevice, u8 byPktType,
         pTxBufHead->wFIFOCtl |= (FIFOCTL_RTS | FIFOCTL_LRETRY);
     }
 
-    pbyTxBufferAddr = (PBYTE) &(pTxBufHead->adwTxKey[0]);
+    pbyTxBufferAddr = (u8 *) &(pTxBufHead->adwTxKey[0]);
     wTxBufSize = sizeof(STxBufHead);
     if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {//802.11g packet
         if (byFBOption == AUTO_FB_NONE) {
@@ -1437,10 +1410,9 @@ static int s_bPacketToWirelessUsb(struct vnt_private *pDevice, u8 byPktType,
         } // Auto Fall Back
     }
 
-    pbyMacHdr = (PBYTE)(pbyTxBufferAddr + cbHeaderLength);
-    pbyIVHead = (PBYTE)(pbyMacHdr + cbMACHdLen + uPadding);
-    pbyPayloadHead = (PBYTE)(pbyMacHdr + cbMACHdLen + uPadding + cbIVlen);
-
+    pbyMacHdr = (u8 *)(pbyTxBufferAddr + cbHeaderLength);
+    pbyIVHead = (u8 *)(pbyMacHdr + cbMACHdLen + uPadding);
+    pbyPayloadHead = (u8 *)(pbyMacHdr + cbMACHdLen + uPadding + cbIVlen);
 
     //=========================
     //    No Fragmentation
@@ -1450,7 +1422,6 @@ static int s_bPacketToWirelessUsb(struct vnt_private *pDevice, u8 byPktType,
     //uDMAIdx = TYPE_AC0DMA;
     //pTxBufHead = (PSTxBufHead) &(pTxBufHead->adwTxKey[0]);
 
-
     //Fill FIFO,RrvTime,RTS,and CTS
     s_vGenerateTxParameter(pDevice, byPktType, wCurrentRate,
 			   (void *)pbyTxBufferAddr, pvRrvTime, pvRTS, pvCTS,
@@ -1459,13 +1430,13 @@ static int s_bPacketToWirelessUsb(struct vnt_private *pDevice, u8 byPktType,
     uDuration = s_uFillDataHead(pDevice, byPktType, wCurrentRate, pvTxDataHd, cbFrameSize, uDMAIdx, bNeedACK,
                                     0, 0, 1/*uMACfragNum*/, byFBOption);
     // Generate TX MAC Header
-    s_vGenerateMACHeader(pDevice, pbyMacHdr, (WORD)uDuration, psEthHeader, bNeedEncryption,
+    s_vGenerateMACHeader(pDevice, pbyMacHdr, (u16)uDuration, psEthHeader, bNeedEncryption,
                            byFragType, uDMAIdx, 0);
 
     if (bNeedEncryption == true) {
         //Fill TXKEY
-        s_vFillTxKey(pDevice, (PBYTE)(pTxBufHead->adwTxKey), pbyIVHead, pTransmitKey,
-                         pbyMacHdr, (WORD)cbFrameBodySize, (PBYTE)pMICHDR);
+        s_vFillTxKey(pDevice, (u8 *)(pTxBufHead->adwTxKey), pbyIVHead, pTransmitKey,
+                         pbyMacHdr, (u16)cbFrameBodySize, (u8 *)pMICHDR);
 
         if (pDevice->bEnableHostWEP) {
             pMgmt->sNodeDBTable[uNodeIndex].dwTSC47_16 = pTransmitKey->dwTSC47_16;
@@ -1474,25 +1445,24 @@ static int s_bPacketToWirelessUsb(struct vnt_private *pDevice, u8 byPktType,
     }
 
     // 802.1H
-    if (ntohs(psEthHeader->wType) > ETH_DATA_LEN) {
+    if (ntohs(psEthHeader->h_proto) > ETH_DATA_LEN) {
 	if (pDevice->dwDiagRefCount == 0) {
-		if ((psEthHeader->wType == cpu_to_be16(ETH_P_IPX)) ||
-		    (psEthHeader->wType == cpu_to_le16(0xF380))) {
-			memcpy((PBYTE) (pbyPayloadHead),
+		if ((psEthHeader->h_proto == cpu_to_be16(ETH_P_IPX)) ||
+		    (psEthHeader->h_proto == cpu_to_le16(0xF380))) {
+			memcpy((u8 *) (pbyPayloadHead),
 			       abySNAP_Bridgetunnel, 6);
             } else {
-                memcpy((PBYTE) (pbyPayloadHead), &abySNAP_RFC1042[0], 6);
+                memcpy((u8 *) (pbyPayloadHead), &abySNAP_RFC1042[0], 6);
             }
-            pbyType = (PBYTE) (pbyPayloadHead + 6);
-            memcpy(pbyType, &(psEthHeader->wType), sizeof(WORD));
+            pbyType = (u8 *) (pbyPayloadHead + 6);
+            memcpy(pbyType, &(psEthHeader->h_proto), sizeof(u16));
         } else {
-            memcpy((PBYTE) (pbyPayloadHead), &(psEthHeader->wType), sizeof(WORD));
+            memcpy((u8 *) (pbyPayloadHead), &(psEthHeader->h_proto), sizeof(u16));
 
         }
 
     }
 
-
     if (pPacket != NULL) {
         // Copy the Packet into a tx Buffer
         memcpy((pbyPayloadHead + cb802_1_H_len),
@@ -1502,7 +1472,7 @@ static int s_bPacketToWirelessUsb(struct vnt_private *pDevice, u8 byPktType,
 
     } else {
         // while bRelayPacketSend psEthHeader is point to header+payload
-        memcpy((pbyPayloadHead + cb802_1_H_len), ((PBYTE)psEthHeader) + ETH_HLEN, uSkbPacketLen - ETH_HLEN);
+        memcpy((pbyPayloadHead + cb802_1_H_len), ((u8 *)psEthHeader) + ETH_HLEN, uSkbPacketLen - ETH_HLEN);
     }
 
     ASSERT(uLength == cbNdisBodySize);
@@ -1516,18 +1486,18 @@ static int s_bPacketToWirelessUsb(struct vnt_private *pDevice, u8 byPktType,
 		dwMICKey1 = *(u32 *)(&pTransmitKey->abyKey[20]);
 	}
         else if ((pTransmitKey->dwKeyIndex & AUTHENTICATOR_KEY) != 0) {
-            dwMICKey0 = *(PDWORD)(&pTransmitKey->abyKey[16]);
-            dwMICKey1 = *(PDWORD)(&pTransmitKey->abyKey[20]);
+            dwMICKey0 = *(u32 *)(&pTransmitKey->abyKey[16]);
+            dwMICKey1 = *(u32 *)(&pTransmitKey->abyKey[20]);
         }
         else {
-            dwMICKey0 = *(PDWORD)(&pTransmitKey->abyKey[24]);
-            dwMICKey1 = *(PDWORD)(&pTransmitKey->abyKey[28]);
+            dwMICKey0 = *(u32 *)(&pTransmitKey->abyKey[24]);
+            dwMICKey1 = *(u32 *)(&pTransmitKey->abyKey[28]);
         }
         // DO Software Michael
         MIC_vInit(dwMICKey0, dwMICKey1);
-        MIC_vAppend((PBYTE)&(psEthHeader->abyDstAddr[0]), 12);
+        MIC_vAppend((u8 *)&(psEthHeader->h_dest[0]), 12);
         dwMIC_Priority = 0;
-        MIC_vAppend((PBYTE)&dwMIC_Priority, 4);
+        MIC_vAppend((u8 *)&dwMIC_Priority, 4);
 	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MIC KEY: %X, %X\n",
 		dwMICKey0, dwMICKey1);
 
@@ -1535,14 +1505,14 @@ static int s_bPacketToWirelessUsb(struct vnt_private *pDevice, u8 byPktType,
 
         //DBG_PRN_GRP12(("Length:%d, %d\n", cbFrameBodySize, uFromHDtoPLDLength));
         //for (ii = 0; ii < cbFrameBodySize; ii++) {
-        //    DBG_PRN_GRP12(("%02x ", *((PBYTE)((pbyPayloadHead + cb802_1_H_len) + ii))));
+        //    DBG_PRN_GRP12(("%02x ", *((u8 *)((pbyPayloadHead + cb802_1_H_len) + ii))));
         //}
         //DBG_PRN_GRP12(("\n\n\n"));
 
         MIC_vAppend(pbyPayloadHead, cbFrameBodySize);
 
-        pdwMIC_L = (PDWORD)(pbyPayloadHead + cbFrameBodySize);
-        pdwMIC_R = (PDWORD)(pbyPayloadHead + cbFrameBodySize + 4);
+        pdwMIC_L = (u32 *)(pbyPayloadHead + cbFrameBodySize);
+        pdwMIC_R = (u32 *)(pbyPayloadHead + cbFrameBodySize + 4);
 
         MIC_vGetMIC(pdwMIC_L, pdwMIC_R);
         MIC_vUnInit();
@@ -1557,10 +1527,9 @@ static int s_bPacketToWirelessUsb(struct vnt_private *pDevice, u8 byPktType,
         //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MIC:%lX, %lX\n", *pdwMIC_L, *pdwMIC_R);
     }
 
-
     if (bSoftWEP == true) {
 
-        s_vSWencryption(pDevice, pTransmitKey, (pbyPayloadHead), (WORD)(cbFrameBodySize + cbMIClen));
+        s_vSWencryption(pDevice, pTransmitKey, (pbyPayloadHead), (u16)(cbFrameBodySize + cbMIClen));
 
     } else if (  ((pDevice->eEncryptionStatus == Ndis802_11Encryption1Enabled) && (bNeedEncryption == true))  ||
           ((pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) && (bNeedEncryption == true))   ||
@@ -1570,13 +1539,13 @@ static int s_bPacketToWirelessUsb(struct vnt_private *pDevice, u8 byPktType,
 
     if (pDevice->bSoftwareGenCrcErr == true) {
 	unsigned int cbLen;
-        PDWORD pdwCRC;
+        u32 * pdwCRC;
 
         dwCRC = 0xFFFFFFFFL;
         cbLen = cbFrameSize - cbFCSlen;
         // calculate CRC, and wrtie CRC value to end of TD
         dwCRC = CRCdwGetCrc32Ex(pbyMacHdr, cbLen, dwCRC);
-        pdwCRC = (PDWORD)(pbyMacHdr + cbLen);
+        pdwCRC = (u32 *)(pbyMacHdr + cbLen);
         // finally, we must invert dwCRC to get the correct answer
         *pdwCRC = ~dwCRC;
         // Force Error
@@ -1588,16 +1557,13 @@ static int s_bPacketToWirelessUsb(struct vnt_private *pDevice, u8 byPktType,
     *pcbHeaderLen = cbHeaderLength;
     *pcbTotalLen = cbHeaderLength + cbFrameSize ;
 
-
     //Set FragCtl in TxBufferHead
-    pTxBufHead->wFragCtl |= (WORD)byFragType;
-
+    pTxBufHead->wFragCtl |= (u16)byFragType;
 
     return true;
 
 }
 
-
 /*+
  *
  * Description:
@@ -1618,67 +1584,67 @@ static int s_bPacketToWirelessUsb(struct vnt_private *pDevice, u8 byPktType,
 -*/
 
 static void s_vGenerateMACHeader(struct vnt_private *pDevice,
-	u8 *pbyBufferAddr, u16 wDuration, PSEthernetHeader psEthHeader,
+	u8 *pbyBufferAddr, u16 wDuration, struct ethhdr *psEthHeader,
 	int bNeedEncrypt, u16 wFragType, u32 uDMAIdx, u32 uFragIdx)
 {
-	PS802_11Header pMACHeader = (PS802_11Header)pbyBufferAddr;
+	struct ieee80211_hdr *pMACHeader = (struct ieee80211_hdr *)pbyBufferAddr;
 
-    memset(pMACHeader, 0, (sizeof(S802_11Header)));  //- sizeof(pMACHeader->dwIV)));
+    memset(pMACHeader, 0, (sizeof(struct ieee80211_hdr)));
 
     if (uDMAIdx == TYPE_ATIMDMA) {
-    	pMACHeader->wFrameCtl = TYPE_802_11_ATIM;
+    	pMACHeader->frame_control = TYPE_802_11_ATIM;
     } else {
-        pMACHeader->wFrameCtl = TYPE_802_11_DATA;
+        pMACHeader->frame_control = TYPE_802_11_DATA;
     }
 
     if (pDevice->eOPMode == OP_MODE_AP) {
-	memcpy(&(pMACHeader->abyAddr1[0]),
-	       &(psEthHeader->abyDstAddr[0]),
+	memcpy(&(pMACHeader->addr1[0]),
+	       &(psEthHeader->h_dest[0]),
 	       ETH_ALEN);
-	memcpy(&(pMACHeader->abyAddr2[0]), &(pDevice->abyBSSID[0]), ETH_ALEN);
-	memcpy(&(pMACHeader->abyAddr3[0]),
-	       &(psEthHeader->abySrcAddr[0]),
+	memcpy(&(pMACHeader->addr2[0]), &(pDevice->abyBSSID[0]), ETH_ALEN);
+	memcpy(&(pMACHeader->addr3[0]),
+	       &(psEthHeader->h_source[0]),
 	       ETH_ALEN);
-        pMACHeader->wFrameCtl |= FC_FROMDS;
+        pMACHeader->frame_control |= FC_FROMDS;
     } else {
 	if (pDevice->eOPMode == OP_MODE_ADHOC) {
-		memcpy(&(pMACHeader->abyAddr1[0]),
-		       &(psEthHeader->abyDstAddr[0]),
+		memcpy(&(pMACHeader->addr1[0]),
+		       &(psEthHeader->h_dest[0]),
 		       ETH_ALEN);
-		memcpy(&(pMACHeader->abyAddr2[0]),
-		       &(psEthHeader->abySrcAddr[0]),
+		memcpy(&(pMACHeader->addr2[0]),
+		       &(psEthHeader->h_source[0]),
 		       ETH_ALEN);
-		memcpy(&(pMACHeader->abyAddr3[0]),
+		memcpy(&(pMACHeader->addr3[0]),
 		       &(pDevice->abyBSSID[0]),
 		       ETH_ALEN);
 	} else {
-		memcpy(&(pMACHeader->abyAddr3[0]),
-		       &(psEthHeader->abyDstAddr[0]),
+		memcpy(&(pMACHeader->addr3[0]),
+		       &(psEthHeader->h_dest[0]),
 		       ETH_ALEN);
-		memcpy(&(pMACHeader->abyAddr2[0]),
-		       &(psEthHeader->abySrcAddr[0]),
+		memcpy(&(pMACHeader->addr2[0]),
+		       &(psEthHeader->h_source[0]),
 		       ETH_ALEN);
-		memcpy(&(pMACHeader->abyAddr1[0]),
+		memcpy(&(pMACHeader->addr1[0]),
 		       &(pDevice->abyBSSID[0]),
 		       ETH_ALEN);
-            pMACHeader->wFrameCtl |= FC_TODS;
+            pMACHeader->frame_control |= FC_TODS;
         }
     }
 
     if (bNeedEncrypt)
-        pMACHeader->wFrameCtl |= cpu_to_le16((WORD)WLAN_SET_FC_ISWEP(1));
+        pMACHeader->frame_control |= cpu_to_le16((u16)WLAN_SET_FC_ISWEP(1));
 
-    pMACHeader->wDurationID = cpu_to_le16(wDuration);
+    pMACHeader->duration_id = cpu_to_le16(wDuration);
 
     if (pDevice->bLongHeader) {
         PWLAN_80211HDR_A4 pMACA4Header  = (PWLAN_80211HDR_A4) pbyBufferAddr;
-        pMACHeader->wFrameCtl |= (FC_TODS | FC_FROMDS);
+        pMACHeader->frame_control |= (FC_TODS | FC_FROMDS);
         memcpy(pMACA4Header->abyAddr4, pDevice->abyBSSID, WLAN_ADDR_LEN);
     }
-    pMACHeader->wSeqCtl = cpu_to_le16(pDevice->wSeqCounter << 4);
+    pMACHeader->seq_ctrl = cpu_to_le16(pDevice->wSeqCounter << 4);
 
     //Set FragNumber in Sequence Control
-    pMACHeader->wSeqCtl |= cpu_to_le16((WORD)uFragIdx);
+    pMACHeader->seq_ctrl |= cpu_to_le16((u16)uFragIdx);
 
     if ((wFragType == FRAGCTL_ENDFRAG) || (wFragType == FRAGCTL_NONFRAG)) {
         pDevice->wSeqCounter++;
@@ -1687,12 +1653,10 @@ static void s_vGenerateMACHeader(struct vnt_private *pDevice,
     }
 
     if ((wFragType == FRAGCTL_STAFRAG) || (wFragType == FRAGCTL_MIDFRAG)) { //StartFrag or MidFrag
-        pMACHeader->wFrameCtl |= FC_MOREFRAG;
+        pMACHeader->frame_control |= FC_MOREFRAG;
     }
 }
 
-
-
 /*+
  *
  * Description:
@@ -1717,9 +1681,9 @@ CMD_STATUS csMgmt_xmit(struct vnt_private *pDevice,
 	PTX_BUFFER pTX_Buffer;
 	PSTxBufHead pTxBufHead;
 	PUSB_SEND_CONTEXT pContext;
-	PS802_11Header pMACHeader;
+	struct ieee80211_hdr *pMACHeader;
 	PSCTS pCTS;
-	SEthernetHeader sEthHeader;
+	struct ethhdr sEthHeader;
 	u8 byPktType, *pbyTxBufferAddr;
 	void *pvRTS, *pvTxDataHd, *pvRrvTime, *pMICHDR;
 	u32 uDuration, cbReqCount, cbHeaderSize, cbFrameBodySize, cbFrameSize;
@@ -1730,8 +1694,6 @@ CMD_STATUS csMgmt_xmit(struct vnt_private *pDevice,
 	u32 cbMacHdLen;
 	u16 wCurrentRate = RATE_1M;
 
-
-
     pContext = (PUSB_SEND_CONTEXT)s_vGetFreeContext(pDevice);
 
     if (NULL == pContext) {
@@ -1740,7 +1702,7 @@ CMD_STATUS csMgmt_xmit(struct vnt_private *pDevice,
     }
 
     pTX_Buffer = (PTX_BUFFER) (&pContext->Data[0]);
-    pbyTxBufferAddr = (PBYTE)&(pTX_Buffer->adwTxKey[0]);
+    pbyTxBufferAddr = (u8 *)&(pTX_Buffer->adwTxKey[0]);
     cbFrameBodySize = pPacket->cbPayloadLen;
     pTxBufHead = (PSTxBufHead) pbyTxBufferAddr;
     wTxBufSize = sizeof(STxBufHead);
@@ -1765,7 +1727,6 @@ CMD_STATUS csMgmt_xmit(struct vnt_private *pDevice,
     }
     pDevice->wCurrentRate = wCurrentRate;
 
-
     //Set packet type
     if (byPktType == PK_TYPE_11A) {//0000 0000 0000 0000
         pTxBufHead->wFIFOCtl = 0;
@@ -1814,7 +1775,7 @@ CMD_STATUS csMgmt_xmit(struct vnt_private *pDevice,
     }
 
     //Set FRAGCTL_MACHDCNT
-    pTxBufHead->wFragCtl |= cpu_to_le16((WORD)(cbMacHdLen << 10));
+    pTxBufHead->wFragCtl |= cpu_to_le16((u16)(cbMacHdLen << 10));
 
     // Notes:
     // Although spec says MMPDU can be fragmented; In most case,
@@ -1877,17 +1838,16 @@ CMD_STATUS csMgmt_xmit(struct vnt_private *pDevice,
     memset((void *)(pbyTxBufferAddr + wTxBufSize), 0,
 	   (cbHeaderSize - wTxBufSize));
 
-    memcpy(&(sEthHeader.abyDstAddr[0]),
+    memcpy(&(sEthHeader.h_dest[0]),
 	   &(pPacket->p80211Header->sA3.abyAddr1[0]),
 	   ETH_ALEN);
-    memcpy(&(sEthHeader.abySrcAddr[0]),
+    memcpy(&(sEthHeader.h_source[0]),
 	   &(pPacket->p80211Header->sA3.abyAddr2[0]),
 	   ETH_ALEN);
     //=========================
     //    No Fragmentation
     //=========================
-    pTxBufHead->wFragCtl |= (WORD)FRAGCTL_NONFRAG;
-
+    pTxBufHead->wFragCtl |= (u16)FRAGCTL_NONFRAG;
 
     //Fill FIFO,RrvTime,RTS,and CTS
     s_vGenerateTxParameter(pDevice, byPktType, wCurrentRate,  pbyTxBufferAddr, pvRrvTime, pvRTS, pCTS,
@@ -1897,18 +1857,18 @@ CMD_STATUS csMgmt_xmit(struct vnt_private *pDevice,
     uDuration = s_uFillDataHead(pDevice, byPktType, wCurrentRate, pvTxDataHd, cbFrameSize, TYPE_TXDMA0, bNeedACK,
                                 0, 0, 1, AUTO_FB_NONE);
 
-    pMACHeader = (PS802_11Header) (pbyTxBufferAddr + cbHeaderSize);
+    pMACHeader = (struct ieee80211_hdr *) (pbyTxBufferAddr + cbHeaderSize);
 
     cbReqCount = cbHeaderSize + cbMacHdLen + uPadding + cbIVlen + cbFrameBodySize;
 
     if (WLAN_GET_FC_ISWEP(pPacket->p80211Header->sA4.wFrameCtl) != 0) {
-        PBYTE           pbyIVHead;
-        PBYTE           pbyPayloadHead;
-        PBYTE           pbyBSSID;
+        u8 *           pbyIVHead;
+        u8 *           pbyPayloadHead;
+        u8 *           pbyBSSID;
         PSKeyItem       pTransmitKey = NULL;
 
-        pbyIVHead = (PBYTE)(pbyTxBufferAddr + cbHeaderSize + cbMacHdLen + uPadding);
-        pbyPayloadHead = (PBYTE)(pbyTxBufferAddr + cbHeaderSize + cbMacHdLen + uPadding + cbIVlen);
+        pbyIVHead = (u8 *)(pbyTxBufferAddr + cbHeaderSize + cbMacHdLen + uPadding);
+        pbyPayloadHead = (u8 *)(pbyTxBufferAddr + cbHeaderSize + cbMacHdLen + uPadding + cbIVlen);
         do {
             if ((pDevice->eOPMode == OP_MODE_INFRASTRUCTURE) &&
                 (pDevice->bLinkPass == true)) {
@@ -1935,11 +1895,11 @@ CMD_STATUS csMgmt_xmit(struct vnt_private *pDevice,
             }
         } while(false);
         //Fill TXKEY
-        s_vFillTxKey(pDevice, (PBYTE)(pTxBufHead->adwTxKey), pbyIVHead, pTransmitKey,
-                     (PBYTE)pMACHeader, (WORD)cbFrameBodySize, NULL);
+        s_vFillTxKey(pDevice, (u8 *)(pTxBufHead->adwTxKey), pbyIVHead, pTransmitKey,
+                     (u8 *)pMACHeader, (u16)cbFrameBodySize, NULL);
 
         memcpy(pMACHeader, pPacket->p80211Header, cbMacHdLen);
-        memcpy(pbyPayloadHead, ((PBYTE)(pPacket->p80211Header) + cbMacHdLen),
+        memcpy(pbyPayloadHead, ((u8 *)(pPacket->p80211Header) + cbMacHdLen),
                  cbFrameBodySize);
     }
     else {
@@ -1947,7 +1907,7 @@ CMD_STATUS csMgmt_xmit(struct vnt_private *pDevice,
         memcpy(pMACHeader, pPacket->p80211Header, pPacket->cbMPDULen);
     }
 
-    pMACHeader->wSeqCtl = cpu_to_le16(pDevice->wSeqCounter << 4);
+    pMACHeader->seq_ctrl = cpu_to_le16(pDevice->wSeqCounter << 4);
     pDevice->wSeqCounter++ ;
     if (pDevice->wSeqCounter > 0x0fff)
         pDevice->wSeqCounter = 0;
@@ -1966,27 +1926,25 @@ CMD_STATUS csMgmt_xmit(struct vnt_private *pDevice,
         }
     }
 
-
-    pTX_Buffer->wTxByteCount = cpu_to_le16((WORD)(cbReqCount));
-    pTX_Buffer->byPKTNO = (BYTE) (((wCurrentRate<<4) &0x00F0) | ((pDevice->wSeqCounter - 1) & 0x000F));
+    pTX_Buffer->wTxByteCount = cpu_to_le16((u16)(cbReqCount));
+    pTX_Buffer->byPKTNO = (u8) (((wCurrentRate<<4) &0x00F0) | ((pDevice->wSeqCounter - 1) & 0x000F));
     pTX_Buffer->byType = 0x00;
 
     pContext->pPacket = NULL;
     pContext->Type = CONTEXT_MGMT_PACKET;
-    pContext->uBufLen = (WORD)cbReqCount + 4;  //USB header
+    pContext->uBufLen = (u16)cbReqCount + 4;  //USB header
 
-    if (WLAN_GET_FC_TODS(pMACHeader->wFrameCtl) == 0) {
-        s_vSaveTxPktInfo(pDevice, (BYTE) (pTX_Buffer->byPKTNO & 0x0F), &(pMACHeader->abyAddr1[0]),(WORD)cbFrameSize,pTX_Buffer->wFIFOCtl);
+    if (WLAN_GET_FC_TODS(pMACHeader->frame_control) == 0) {
+        s_vSaveTxPktInfo(pDevice, (u8) (pTX_Buffer->byPKTNO & 0x0F), &(pMACHeader->addr1[0]), (u16)cbFrameSize, pTX_Buffer->wFIFOCtl);
     }
     else {
-        s_vSaveTxPktInfo(pDevice, (BYTE) (pTX_Buffer->byPKTNO & 0x0F), &(pMACHeader->abyAddr3[0]),(WORD)cbFrameSize,pTX_Buffer->wFIFOCtl);
+        s_vSaveTxPktInfo(pDevice, (u8) (pTX_Buffer->byPKTNO & 0x0F), &(pMACHeader->addr3[0]), (u16)cbFrameSize, pTX_Buffer->wFIFOCtl);
     }
 
     PIPEnsSendBulkOut(pDevice,pContext);
     return CMD_STATUS_PENDING;
 }
 
-
 CMD_STATUS csBeacon_xmit(struct vnt_private *pDevice,
 	struct vnt_tx_mgmt *pPacket)
 {
@@ -1994,7 +1952,7 @@ CMD_STATUS csBeacon_xmit(struct vnt_private *pDevice,
 	u32 cbHeaderSize = 0;
 	u16 wTxBufSize = sizeof(STxShortBufHead);
 	PSTxShortBufHead pTxBufHead;
-	PS802_11Header pMACHeader;
+	struct ieee80211_hdr *pMACHeader;
 	PSTxDataHead_ab pTxDataHead;
 	u16 wCurrentRate;
 	u32 cbFrameBodySize;
@@ -2004,7 +1962,6 @@ CMD_STATUS csBeacon_xmit(struct vnt_private *pDevice,
 	PUSB_SEND_CONTEXT pContext;
 	CMD_STATUS status;
 
-
     pContext = (PUSB_SEND_CONTEXT)s_vGetFreeContext(pDevice);
     if (NULL == pContext) {
         status = CMD_STATUS_RESOURCES;
@@ -2012,7 +1969,7 @@ CMD_STATUS csBeacon_xmit(struct vnt_private *pDevice,
         return status ;
     }
     pTX_Buffer = (PBEACON_BUFFER) (&pContext->Data[0]);
-    pbyTxBufferAddr = (PBYTE)&(pTX_Buffer->wFIFOCtl);
+    pbyTxBufferAddr = (u8 *)&(pTX_Buffer->wFIFOCtl);
 
     cbFrameBodySize = pPacket->cbPayloadLen;
 
@@ -2025,10 +1982,10 @@ CMD_STATUS csBeacon_xmit(struct vnt_private *pDevice,
         pTxDataHead = (PSTxDataHead_ab) (pbyTxBufferAddr + wTxBufSize);
         //Get SignalField,ServiceField,Length
         BBvCalculateParameter(pDevice, cbFrameSize, wCurrentRate, PK_TYPE_11A,
-            (PWORD)&(pTxDataHead->wTransmitLength), (PBYTE)&(pTxDataHead->byServiceField), (PBYTE)&(pTxDataHead->bySignalField)
+            (u16 *)&(pTxDataHead->wTransmitLength), (u8 *)&(pTxDataHead->byServiceField), (u8 *)&(pTxDataHead->bySignalField)
         );
         //Get Duration and TimeStampOff
-        pTxDataHead->wDuration = cpu_to_le16((WORD)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameSize, PK_TYPE_11A,
+        pTxDataHead->wDuration = cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameSize, PK_TYPE_11A,
                                                           wCurrentRate, false, 0, 0, 1, AUTO_FB_NONE));
         pTxDataHead->wTimeStampOff = wTimeStampOff[pDevice->byPreambleType%2][wCurrentRate%MAX_RATE];
         cbHeaderSize = wTxBufSize + sizeof(STxDataHead_ab);
@@ -2038,41 +1995,40 @@ CMD_STATUS csBeacon_xmit(struct vnt_private *pDevice,
         pTxDataHead = (PSTxDataHead_ab) (pbyTxBufferAddr + wTxBufSize);
         //Get SignalField,ServiceField,Length
         BBvCalculateParameter(pDevice, cbFrameSize, wCurrentRate, PK_TYPE_11B,
-            (PWORD)&(pTxDataHead->wTransmitLength), (PBYTE)&(pTxDataHead->byServiceField), (PBYTE)&(pTxDataHead->bySignalField)
+            (u16 *)&(pTxDataHead->wTransmitLength), (u8 *)&(pTxDataHead->byServiceField), (u8 *)&(pTxDataHead->bySignalField)
         );
         //Get Duration and TimeStampOff
-        pTxDataHead->wDuration = cpu_to_le16((WORD)s_uGetDataDuration(pDevice, DATADUR_B, cbFrameSize, PK_TYPE_11B,
+        pTxDataHead->wDuration = cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_B, cbFrameSize, PK_TYPE_11B,
                                                           wCurrentRate, false, 0, 0, 1, AUTO_FB_NONE));
         pTxDataHead->wTimeStampOff = wTimeStampOff[pDevice->byPreambleType%2][wCurrentRate%MAX_RATE];
         cbHeaderSize = wTxBufSize + sizeof(STxDataHead_ab);
     }
 
     //Generate Beacon Header
-    pMACHeader = (PS802_11Header)(pbyTxBufferAddr + cbHeaderSize);
+    pMACHeader = (struct ieee80211_hdr *)(pbyTxBufferAddr + cbHeaderSize);
     memcpy(pMACHeader, pPacket->p80211Header, pPacket->cbMPDULen);
 
-    pMACHeader->wDurationID = 0;
-    pMACHeader->wSeqCtl = cpu_to_le16(pDevice->wSeqCounter << 4);
+    pMACHeader->duration_id = 0;
+    pMACHeader->seq_ctrl = cpu_to_le16(pDevice->wSeqCounter << 4);
     pDevice->wSeqCounter++ ;
     if (pDevice->wSeqCounter > 0x0fff)
         pDevice->wSeqCounter = 0;
 
     cbReqCount = cbHeaderSize + WLAN_HDR_ADDR3_LEN + cbFrameBodySize;
 
-    pTX_Buffer->wTxByteCount = (WORD)cbReqCount;
-    pTX_Buffer->byPKTNO = (BYTE) (((wCurrentRate<<4) &0x00F0) | ((pDevice->wSeqCounter - 1) & 0x000F));
+    pTX_Buffer->wTxByteCount = (u16)cbReqCount;
+    pTX_Buffer->byPKTNO = (u8) (((wCurrentRate<<4) &0x00F0) | ((pDevice->wSeqCounter - 1) & 0x000F));
     pTX_Buffer->byType = 0x01;
 
     pContext->pPacket = NULL;
     pContext->Type = CONTEXT_MGMT_PACKET;
-    pContext->uBufLen = (WORD)cbReqCount + 4;  //USB header
+    pContext->uBufLen = (u16)cbReqCount + 4;  //USB header
 
     PIPEnsSendBulkOut(pDevice,pContext);
     return CMD_STATUS_PENDING;
 
 }
 
-
 void vDMA0_tx_80211(struct vnt_private *pDevice, struct sk_buff *skb)
 {
 	struct vnt_manager *pMgmt = &pDevice->vnt_mgmt;
@@ -2080,7 +2036,7 @@ void vDMA0_tx_80211(struct vnt_private *pDevice, struct sk_buff *skb)
 	u8 *pbyTxBufferAddr;
 	void *pvRTS, *pvCTS, *pvTxDataHd;
 	u32 uDuration, cbReqCount;
-	PS802_11Header  pMACHeader;
+	struct ieee80211_hdr *pMACHeader;
 	u32 cbHeaderSize, cbFrameBodySize;
 	int bNeedACK, bIsPSPOLL = false;
 	PSTxBufHead pTxBufHead;
@@ -2093,7 +2049,7 @@ void vDMA0_tx_80211(struct vnt_private *pDevice, struct sk_buff *skb)
 	u32 *pdwMIC_L, *pdwMIC_R;
 	u16 wTxBufSize;
 	u32 cbMacHdLen;
-	SEthernetHeader sEthHeader;
+	struct ethhdr sEthHeader;
 	void *pvRrvTime, *pMICHDR;
 	u32 wCurrentRate = RATE_1M;
 	PUWLAN_80211HDR  p80211Header;
@@ -2106,7 +2062,6 @@ void vDMA0_tx_80211(struct vnt_private *pDevice, struct sk_buff *skb)
 	PTX_BUFFER pTX_Buffer;
 	PUSB_SEND_CONTEXT pContext;
 
-
     pvRrvTime = pMICHDR = pvRTS = pvCTS = pvTxDataHd = NULL;
 
     if(skb->len <= WLAN_HDR_ADDR3_LEN) {
@@ -2126,7 +2081,7 @@ void vDMA0_tx_80211(struct vnt_private *pDevice, struct sk_buff *skb)
     }
 
     pTX_Buffer = (PTX_BUFFER)(&pContext->Data[0]);
-    pbyTxBufferAddr = (PBYTE)(&pTX_Buffer->adwTxKey[0]);
+    pbyTxBufferAddr = (u8 *)(&pTX_Buffer->adwTxKey[0]);
     pTxBufHead = (PSTxBufHead) pbyTxBufferAddr;
     wTxBufSize = sizeof(STxBufHead);
     memset(pTxBufHead, 0, wTxBufSize);
@@ -2177,7 +2132,7 @@ void vDMA0_tx_80211(struct vnt_private *pDevice, struct sk_buff *skb)
     }
     else {
         if (pDevice->bEnableHostWEP) {
-            if (BSSbIsSTAInNodeDB(pDevice, (PBYTE)(p80211Header->sA3.abyAddr1), &uNodeIndex))
+            if (BSSbIsSTAInNodeDB(pDevice, (u8 *)(p80211Header->sA3.abyAddr1), &uNodeIndex))
                 bNodeExist = true;
         }
         bNeedACK = true;
@@ -2223,16 +2178,14 @@ void vDMA0_tx_80211(struct vnt_private *pDevice, struct sk_buff *skb)
          }
     }
 
-
     //Set FRAGCTL_MACHDCNT
-    pTxBufHead->wFragCtl |= cpu_to_le16((WORD)cbMacHdLen << 10);
+    pTxBufHead->wFragCtl |= cpu_to_le16((u16)cbMacHdLen << 10);
 
     // Notes:
     // Although spec says MMPDU can be fragmented; In most case,
     // no one will send a MMPDU under fragmentation. With RTS may occur.
     pDevice->bAES = false;  //Set FRAGCTL_WEPTYP
 
-
     if (WLAN_GET_FC_ISWEP(p80211Header->sA4.wFrameCtl) != 0) {
         if (pDevice->eEncryptionStatus == Ndis802_11Encryption1Enabled) {
             cbIVlen = 4;
@@ -2268,7 +2221,6 @@ void vDMA0_tx_80211(struct vnt_private *pDevice, struct sk_buff *skb)
     }
     //the rest of pTxBufHead->wFragCtl:FragTyp will be set later in s_vFillFragParameter()
 
-
     if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {//802.11g packet
 
         pvRrvTime = (PSRrvTime_gCTS) (pbyTxBufferAddr + wTxBufSize);
@@ -2290,17 +2242,16 @@ void vDMA0_tx_80211(struct vnt_private *pDevice, struct sk_buff *skb)
     }
     memset((void *)(pbyTxBufferAddr + wTxBufSize), 0,
 	   (cbHeaderSize - wTxBufSize));
-    memcpy(&(sEthHeader.abyDstAddr[0]),
+    memcpy(&(sEthHeader.h_dest[0]),
 	   &(p80211Header->sA3.abyAddr1[0]),
 	   ETH_ALEN);
-    memcpy(&(sEthHeader.abySrcAddr[0]),
+    memcpy(&(sEthHeader.h_source[0]),
 	   &(p80211Header->sA3.abyAddr2[0]),
 	   ETH_ALEN);
     //=========================
     //    No Fragmentation
     //=========================
-    pTxBufHead->wFragCtl |= (WORD)FRAGCTL_NONFRAG;
-
+    pTxBufHead->wFragCtl |= (u16)FRAGCTL_NONFRAG;
 
     //Fill FIFO,RrvTime,RTS,and CTS
     s_vGenerateTxParameter(pDevice, byPktType, wCurrentRate, pbyTxBufferAddr, pvRrvTime, pvRTS, pvCTS,
@@ -2310,19 +2261,19 @@ void vDMA0_tx_80211(struct vnt_private *pDevice, struct sk_buff *skb)
     uDuration = s_uFillDataHead(pDevice, byPktType, wCurrentRate, pvTxDataHd, cbFrameSize, TYPE_TXDMA0, bNeedACK,
                                 0, 0, 1, AUTO_FB_NONE);
 
-    pMACHeader = (PS802_11Header) (pbyTxBufferAddr + cbHeaderSize);
+    pMACHeader = (struct ieee80211_hdr *) (pbyTxBufferAddr + cbHeaderSize);
 
     cbReqCount = cbHeaderSize + cbMacHdLen + uPadding + cbIVlen + (cbFrameBodySize + cbMIClen) + cbExtSuppRate;
 
-    pbyMacHdr = (PBYTE)(pbyTxBufferAddr + cbHeaderSize);
-    pbyPayloadHead = (PBYTE)(pbyMacHdr + cbMacHdLen + uPadding + cbIVlen);
-    pbyIVHead = (PBYTE)(pbyMacHdr + cbMacHdLen + uPadding);
+    pbyMacHdr = (u8 *)(pbyTxBufferAddr + cbHeaderSize);
+    pbyPayloadHead = (u8 *)(pbyMacHdr + cbMacHdLen + uPadding + cbIVlen);
+    pbyIVHead = (u8 *)(pbyMacHdr + cbMacHdLen + uPadding);
 
     // Copy the Packet into a tx Buffer
     memcpy(pbyMacHdr, skb->data, cbMacHdLen);
 
     // version set to 0, patch for hostapd deamon
-    pMACHeader->wFrameCtl &= cpu_to_le16(0xfffc);
+    pMACHeader->frame_control &= cpu_to_le16(0xfffc);
     memcpy(pbyPayloadHead, (skb->data + cbMacHdLen), cbFrameBodySize);
 
     // replace support rate, patch for hostapd daemon( only support 11M)
@@ -2359,14 +2310,14 @@ void vDMA0_tx_80211(struct vnt_private *pDevice, struct sk_buff *skb)
 
         if ((pTransmitKey != NULL) && (pTransmitKey->byCipherSuite == KEY_CTL_TKIP)) {
 
-            dwMICKey0 = *(PDWORD)(&pTransmitKey->abyKey[16]);
-            dwMICKey1 = *(PDWORD)(&pTransmitKey->abyKey[20]);
+            dwMICKey0 = *(u32 *)(&pTransmitKey->abyKey[16]);
+            dwMICKey1 = *(u32 *)(&pTransmitKey->abyKey[20]);
 
             // DO Software Michael
             MIC_vInit(dwMICKey0, dwMICKey1);
-            MIC_vAppend((PBYTE)&(sEthHeader.abyDstAddr[0]), 12);
+            MIC_vAppend((u8 *)&(sEthHeader.h_dest[0]), 12);
             dwMIC_Priority = 0;
-            MIC_vAppend((PBYTE)&dwMIC_Priority, 4);
+            MIC_vAppend((u8 *)&dwMIC_Priority, 4);
 		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"DMA0_tx_8021:MIC KEY:"\
 			" %X, %X\n", dwMICKey0, dwMICKey1);
 
@@ -2374,8 +2325,8 @@ void vDMA0_tx_80211(struct vnt_private *pDevice, struct sk_buff *skb)
 
             MIC_vAppend((pbyTxBufferAddr + uLength), cbFrameBodySize);
 
-            pdwMIC_L = (PDWORD)(pbyTxBufferAddr + uLength + cbFrameBodySize);
-            pdwMIC_R = (PDWORD)(pbyTxBufferAddr + uLength + cbFrameBodySize + 4);
+            pdwMIC_L = (u32 *)(pbyTxBufferAddr + uLength + cbFrameBodySize);
+            pdwMIC_R = (u32 *)(pbyTxBufferAddr + uLength + cbFrameBodySize + 4);
 
             MIC_vGetMIC(pdwMIC_L, pdwMIC_R);
             MIC_vUnInit();
@@ -2393,8 +2344,8 @@ void vDMA0_tx_80211(struct vnt_private *pDevice, struct sk_buff *skb)
 
         }
 
-        s_vFillTxKey(pDevice, (PBYTE)(pTxBufHead->adwTxKey), pbyIVHead, pTransmitKey,
-                     pbyMacHdr, (WORD)cbFrameBodySize, (PBYTE)pMICHDR);
+        s_vFillTxKey(pDevice, (u8 *)(pTxBufHead->adwTxKey), pbyIVHead, pTransmitKey,
+                     pbyMacHdr, (u16)cbFrameBodySize, (u8 *)pMICHDR);
 
         if (pDevice->bEnableHostWEP) {
             pMgmt->sNodeDBTable[uNodeIndex].dwTSC47_16 = pTransmitKey->dwTSC47_16;
@@ -2402,16 +2353,15 @@ void vDMA0_tx_80211(struct vnt_private *pDevice, struct sk_buff *skb)
         }
 
         if ((pDevice->byLocalID <= REV_ID_VT3253_A1)) {
-            s_vSWencryption(pDevice, pTransmitKey, pbyPayloadHead, (WORD)(cbFrameBodySize + cbMIClen));
+            s_vSWencryption(pDevice, pTransmitKey, pbyPayloadHead, (u16)(cbFrameBodySize + cbMIClen));
         }
     }
 
-    pMACHeader->wSeqCtl = cpu_to_le16(pDevice->wSeqCounter << 4);
+    pMACHeader->seq_ctrl = cpu_to_le16(pDevice->wSeqCounter << 4);
     pDevice->wSeqCounter++ ;
     if (pDevice->wSeqCounter > 0x0fff)
         pDevice->wSeqCounter = 0;
 
-
     if (bIsPSPOLL) {
         // The MAC will automatically replace the Duration-field of MAC header by Duration-field
         // of  FIFO control header.
@@ -2426,28 +2376,25 @@ void vDMA0_tx_80211(struct vnt_private *pDevice, struct sk_buff *skb)
         }
     }
 
-    pTX_Buffer->wTxByteCount = cpu_to_le16((WORD)(cbReqCount));
-    pTX_Buffer->byPKTNO = (BYTE) (((wCurrentRate<<4) &0x00F0) | ((pDevice->wSeqCounter - 1) & 0x000F));
+    pTX_Buffer->wTxByteCount = cpu_to_le16((u16)(cbReqCount));
+    pTX_Buffer->byPKTNO = (u8) (((wCurrentRate<<4) &0x00F0) | ((pDevice->wSeqCounter - 1) & 0x000F));
     pTX_Buffer->byType = 0x00;
 
     pContext->pPacket = skb;
     pContext->Type = CONTEXT_MGMT_PACKET;
-    pContext->uBufLen = (WORD)cbReqCount + 4;  //USB header
+    pContext->uBufLen = (u16)cbReqCount + 4;  //USB header
 
-    if (WLAN_GET_FC_TODS(pMACHeader->wFrameCtl) == 0) {
-        s_vSaveTxPktInfo(pDevice, (BYTE) (pTX_Buffer->byPKTNO & 0x0F), &(pMACHeader->abyAddr1[0]),(WORD)cbFrameSize,pTX_Buffer->wFIFOCtl);
+    if (WLAN_GET_FC_TODS(pMACHeader->frame_control) == 0) {
+        s_vSaveTxPktInfo(pDevice, (u8) (pTX_Buffer->byPKTNO & 0x0F), &(pMACHeader->addr1[0]), (u16)cbFrameSize, pTX_Buffer->wFIFOCtl);
     }
     else {
-        s_vSaveTxPktInfo(pDevice, (BYTE) (pTX_Buffer->byPKTNO & 0x0F), &(pMACHeader->abyAddr3[0]),(WORD)cbFrameSize,pTX_Buffer->wFIFOCtl);
+        s_vSaveTxPktInfo(pDevice, (u8) (pTX_Buffer->byPKTNO & 0x0F), &(pMACHeader->addr3[0]), (u16)cbFrameSize, pTX_Buffer->wFIFOCtl);
     }
     PIPEnsSendBulkOut(pDevice,pContext);
     return ;
 
 }
 
-
-
-
 //TYPE_AC0DMA data tx
 /*
  * Description:
@@ -2488,7 +2435,6 @@ int nsDMA_tx_packet(struct vnt_private *pDevice,
 	u16 wKeepRate = pDevice->wCurrentRate;
 	int bTxeapol_key = false;
 
-
     if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) {
 
         if (pDevice->uAssocCount == 0) {
@@ -2496,7 +2442,7 @@ int nsDMA_tx_packet(struct vnt_private *pDevice,
             return 0;
         }
 
-	if (is_multicast_ether_addr((PBYTE)(skb->data))) {
+	if (is_multicast_ether_addr((u8 *)(skb->data))) {
             uNodeIndex = 0;
             bNodeExist = true;
             if (pMgmt->sNodeDBTable[0].bPSEnable) {
@@ -2518,7 +2464,7 @@ int nsDMA_tx_packet(struct vnt_private *pDevice,
 
         }else {
 
-            if (BSSbIsSTAInNodeDB(pDevice, (PBYTE)(skb->data), &uNodeIndex)) {
+            if (BSSbIsSTAInNodeDB(pDevice, (u8 *)(skb->data), &uNodeIndex)) {
 
                 if (pMgmt->sNodeDBTable[uNodeIndex].bPSEnable) {
 
@@ -2562,20 +2508,20 @@ int nsDMA_tx_packet(struct vnt_private *pDevice,
         return STATUS_RESOURCES;
     }
 
-    memcpy(pDevice->sTxEthHeader.abyDstAddr, (PBYTE)(skb->data), ETH_HLEN);
+    memcpy(pDevice->sTxEthHeader.h_dest, (u8 *)(skb->data), ETH_HLEN);
 
 //mike add:station mode check eapol-key challenge--->
 {
-    BYTE  Protocol_Version;    //802.1x Authentication
-    BYTE  Packet_Type;           //802.1x Authentication
-    BYTE  Descriptor_type;
-    WORD Key_info;
+    u8  Protocol_Version;    //802.1x Authentication
+    u8  Packet_Type;           //802.1x Authentication
+    u8  Descriptor_type;
+    u16 Key_info;
 
     Protocol_Version = skb->data[ETH_HLEN];
     Packet_Type = skb->data[ETH_HLEN+1];
     Descriptor_type = skb->data[ETH_HLEN+1+1+2];
     Key_info = (skb->data[ETH_HLEN+1+1+2+1] << 8)|(skb->data[ETH_HLEN+1+1+2+2]);
-	if (pDevice->sTxEthHeader.wType == cpu_to_be16(ETH_P_PAE)) {
+	if (pDevice->sTxEthHeader.h_proto == cpu_to_be16(ETH_P_PAE)) {
 		/* 802.1x OR eapol-key challenge frame transfer */
 		if (((Protocol_Version == 1) || (Protocol_Version == 2)) &&
 			(Packet_Type == 3)) {
@@ -2622,8 +2568,8 @@ int nsDMA_tx_packet(struct vnt_private *pDevice,
                     break;
                 }
             }else if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) {
-
-                pbyBSSID = pDevice->sTxEthHeader.abyDstAddr;  //TO_DS = 0 and FROM_DS = 0 --> 802.11 MAC Address1
+	      /* TO_DS = 0 and FROM_DS = 0 --> 802.11 MAC Address1 */
+                pbyBSSID = pDevice->sTxEthHeader.h_dest;
                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"IBSS Serach Key: \n");
                 for (ii = 0; ii< 6; ii++)
                     DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"%x \n", *(pbyBSSID+ii));
@@ -2665,14 +2611,14 @@ int nsDMA_tx_packet(struct vnt_private *pDevice,
          }
     }
 
-    byPktType = (BYTE)pDevice->byPacketType;
+    byPktType = (u8)pDevice->byPacketType;
 
     if (pDevice->bFixRate) {
         if (pDevice->byBBType == BB_TYPE_11B) {
             if (pDevice->uConnectionRate >= RATE_11M) {
                 pDevice->wCurrentRate = RATE_11M;
             } else {
-                pDevice->wCurrentRate = (WORD)pDevice->uConnectionRate;
+                pDevice->wCurrentRate = (u16)pDevice->uConnectionRate;
             }
         } else {
             if ((pDevice->byBBType == BB_TYPE_11A) &&
@@ -2682,21 +2628,21 @@ int nsDMA_tx_packet(struct vnt_private *pDevice,
                 if (pDevice->uConnectionRate >= RATE_54M)
                     pDevice->wCurrentRate = RATE_54M;
                 else
-                    pDevice->wCurrentRate = (WORD)pDevice->uConnectionRate;
+                    pDevice->wCurrentRate = (u16)pDevice->uConnectionRate;
             }
         }
     }
     else {
         if (pDevice->eOPMode == OP_MODE_ADHOC) {
             // Adhoc Tx rate decided from node DB
-	    if (is_multicast_ether_addr(pDevice->sTxEthHeader.abyDstAddr)) {
+	    if (is_multicast_ether_addr(pDevice->sTxEthHeader.h_dest)) {
                 // Multicast use highest data rate
                 pDevice->wCurrentRate = pMgmt->sNodeDBTable[0].wTxDataRate;
                 // preamble type
                 pDevice->byPreambleType = pDevice->byShortPreamble;
             }
             else {
-                if(BSSbIsSTAInNodeDB(pDevice, &(pDevice->sTxEthHeader.abyDstAddr[0]), &uNodeIndex)) {
+                if (BSSbIsSTAInNodeDB(pDevice, &(pDevice->sTxEthHeader.h_dest[0]), &uNodeIndex)) {
                     pDevice->wCurrentRate = pMgmt->sNodeDBTable[uNodeIndex].wTxDataRate;
                     if (pMgmt->sNodeDBTable[uNodeIndex].bShortPreamble) {
                         pDevice->byPreambleType = pDevice->byShortPreamble;
@@ -2724,7 +2670,7 @@ int nsDMA_tx_packet(struct vnt_private *pDevice,
         }
     }
 
-	if (pDevice->sTxEthHeader.wType == cpu_to_be16(ETH_P_PAE)) {
+	if (pDevice->sTxEthHeader.h_proto == cpu_to_be16(ETH_P_PAE)) {
 		if (pDevice->byBBType != BB_TYPE_11A) {
 			pDevice->wCurrentRate = RATE_1M;
 			pDevice->byACKRate = RATE_1M;
@@ -2751,10 +2697,10 @@ int nsDMA_tx_packet(struct vnt_private *pDevice,
     }
 
     if (bNeedEncryption == true) {
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ntohs Pkt Type=%04x\n", ntohs(pDevice->sTxEthHeader.wType));
-	if ((pDevice->sTxEthHeader.wType) == cpu_to_be16(ETH_P_PAE)) {
+        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ntohs Pkt Type=%04x\n", ntohs(pDevice->sTxEthHeader.h_proto));
+	if ((pDevice->sTxEthHeader.h_proto) == cpu_to_be16(ETH_P_PAE)) {
 		bNeedEncryption = false;
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Pkt Type=%04x\n", (pDevice->sTxEthHeader.wType));
+            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Pkt Type=%04x\n", (pDevice->sTxEthHeader.h_proto));
             if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && (pMgmt->eCurrState == WMAC_STATE_ASSOC)) {
                 if (pTransmitKey == NULL) {
                     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Don't Find TX KEY\n");
@@ -2793,9 +2739,9 @@ int nsDMA_tx_packet(struct vnt_private *pDevice,
     }
 
     fConvertedPacket = s_bPacketToWirelessUsb(pDevice, byPktType,
-                        (PBYTE)(&pContext->Data[0]), bNeedEncryption,
+                        (u8 *)(&pContext->Data[0]), bNeedEncryption,
                         skb->len, uDMAIdx, &pDevice->sTxEthHeader,
-                        (PBYTE)skb->data, pTransmitKey, uNodeIndex,
+                        (u8 *)skb->data, pTransmitKey, uNodeIndex,
                         pDevice->wCurrentRate,
                         &uHeaderLen, &BytesToWrite
                        );
@@ -2816,21 +2762,21 @@ int nsDMA_tx_packet(struct vnt_private *pDevice,
     }
 
     pTX_Buffer = (PTX_BUFFER)&(pContext->Data[0]);
-    pTX_Buffer->byPKTNO = (BYTE) (((pDevice->wCurrentRate<<4) &0x00F0) | ((pDevice->wSeqCounter - 1) & 0x000F));
-    pTX_Buffer->wTxByteCount = (WORD)BytesToWrite;
+    pTX_Buffer->byPKTNO = (u8) (((pDevice->wCurrentRate<<4) &0x00F0) | ((pDevice->wSeqCounter - 1) & 0x000F));
+    pTX_Buffer->wTxByteCount = (u16)BytesToWrite;
 
     pContext->pPacket = skb;
     pContext->Type = CONTEXT_DATA_PACKET;
-    pContext->uBufLen = (WORD)BytesToWrite + 4 ; //USB header
+    pContext->uBufLen = (u16)BytesToWrite + 4 ; //USB header
 
-    s_vSaveTxPktInfo(pDevice, (BYTE) (pTX_Buffer->byPKTNO & 0x0F), &(pContext->sEthHeader.abyDstAddr[0]),(WORD) (BytesToWrite-uHeaderLen),pTX_Buffer->wFIFOCtl);
+    s_vSaveTxPktInfo(pDevice, (u8) (pTX_Buffer->byPKTNO & 0x0F), &(pContext->sEthHeader.h_dest[0]), (u16) (BytesToWrite-uHeaderLen), pTX_Buffer->wFIFOCtl);
 
     status = PIPEnsSendBulkOut(pDevice,pContext);
 
     if (bNeedDeAuth == true) {
-        WORD wReason = WLAN_MGMT_REASON_MIC_FAILURE;
+        u16 wReason = WLAN_MGMT_REASON_MIC_FAILURE;
 
-	bScheduleCommand((void *) pDevice, WLAN_CMD_DEAUTH, (PBYTE) &wReason);
+	bScheduleCommand((void *) pDevice, WLAN_CMD_DEAUTH, (u8 *) &wReason);
     }
 
   if(status!=STATUS_PENDING) {
@@ -2843,8 +2789,6 @@ int nsDMA_tx_packet(struct vnt_private *pDevice,
 
 }
 
-
-
 /*
  * Description:
  *      Relay packet send (AC1DMA) from rx dpc.
@@ -2877,15 +2821,13 @@ int bRelayPacketSend(struct vnt_private *pDevice, u8 *pbySkbData, u32 uDataLen,
 	u32 status;
 	u16 wKeepRate = pDevice->wCurrentRate;
 
-
-
     pContext = (PUSB_SEND_CONTEXT)s_vGetFreeContext(pDevice);
 
     if (NULL == pContext) {
         return false;
     }
 
-    memcpy(pDevice->sTxEthHeader.abyDstAddr, (PBYTE)pbySkbData, ETH_HLEN);
+    memcpy(pDevice->sTxEthHeader.h_dest, (u8 *)pbySkbData, ETH_HLEN);
 
     if (pDevice->bEncryptionEnable == true) {
         bNeedEncryption = true;
@@ -2919,14 +2861,14 @@ int bRelayPacketSend(struct vnt_private *pDevice, u8 *pbySkbData, u32 uDataLen,
         return false;
     }
 
-    byPktTyp = (BYTE)pDevice->byPacketType;
+    byPktTyp = (u8)pDevice->byPacketType;
 
     if (pDevice->bFixRate) {
         if (pDevice->byBBType == BB_TYPE_11B) {
             if (pDevice->uConnectionRate >= RATE_11M) {
                 pDevice->wCurrentRate = RATE_11M;
             } else {
-                pDevice->wCurrentRate = (WORD)pDevice->uConnectionRate;
+                pDevice->wCurrentRate = (u16)pDevice->uConnectionRate;
             }
         } else {
             if ((pDevice->byBBType == BB_TYPE_11A) &&
@@ -2936,7 +2878,7 @@ int bRelayPacketSend(struct vnt_private *pDevice, u8 *pbySkbData, u32 uDataLen,
                 if (pDevice->uConnectionRate >= RATE_54M)
                     pDevice->wCurrentRate = RATE_54M;
                 else
-                    pDevice->wCurrentRate = (WORD)pDevice->uConnectionRate;
+                    pDevice->wCurrentRate = (u16)pDevice->uConnectionRate;
             }
         }
     }
@@ -2957,7 +2899,7 @@ int bRelayPacketSend(struct vnt_private *pDevice, u8 *pbySkbData, u32 uDataLen,
     // and send the irp.
 
     fConvertedPacket = s_bPacketToWirelessUsb(pDevice, byPktType,
-                         (PBYTE)(&pContext->Data[0]), bNeedEncryption,
+                         (u8 *)(&pContext->Data[0]), bNeedEncryption,
                          uDataLen, TYPE_AC0DMA, &pDevice->sTxEthHeader,
                          pbySkbData, pTransmitKey, uNodeIndex,
                          pDevice->wCurrentRate,
@@ -2970,14 +2912,14 @@ int bRelayPacketSend(struct vnt_private *pDevice, u8 *pbySkbData, u32 uDataLen,
     }
 
     pTX_Buffer = (PTX_BUFFER)&(pContext->Data[0]);
-    pTX_Buffer->byPKTNO = (BYTE) (((pDevice->wCurrentRate<<4) &0x00F0) | ((pDevice->wSeqCounter - 1) & 0x000F));
-    pTX_Buffer->wTxByteCount = (WORD)BytesToWrite;
+    pTX_Buffer->byPKTNO = (u8) (((pDevice->wCurrentRate<<4) &0x00F0) | ((pDevice->wSeqCounter - 1) & 0x000F));
+    pTX_Buffer->wTxByteCount = (u16)BytesToWrite;
 
     pContext->pPacket = NULL;
     pContext->Type = CONTEXT_DATA_PACKET;
-    pContext->uBufLen = (WORD)BytesToWrite + 4 ; //USB header
+    pContext->uBufLen = (u16)BytesToWrite + 4 ; //USB header
 
-    s_vSaveTxPktInfo(pDevice, (BYTE) (pTX_Buffer->byPKTNO & 0x0F), &(pContext->sEthHeader.abyDstAddr[0]),(WORD) (BytesToWrite-uHeaderLen),pTX_Buffer->wFIFOCtl);
+    s_vSaveTxPktInfo(pDevice, (u8) (pTX_Buffer->byPKTNO & 0x0F), &(pContext->sEthHeader.h_dest[0]), (u16) (BytesToWrite-uHeaderLen), pTX_Buffer->wFIFOCtl);
 
     status = PIPEnsSendBulkOut(pDevice,pContext);
 
diff --git a/drivers/staging/vt6656/rxtx.h b/drivers/staging/vt6656/rxtx.h
index 9f53702..dd7e85d 100644
--- a/drivers/staging/vt6656/rxtx.h
+++ b/drivers/staging/vt6656/rxtx.h
@@ -29,32 +29,27 @@
 #ifndef __RXTX_H__
 #define __RXTX_H__
 
-#include "ttype.h"
 #include "device.h"
 #include "wcmd.h"
 
-/*---------------------  Export Definitions -------------------------*/
-
-/*---------------------  Export Classes  ----------------------------*/
-
 //
 // RTS buffer header
 //
 typedef struct tagSRTSDataF {
-    WORD    wFrameControl;
-    WORD    wDurationID;
-    BYTE    abyRA[ETH_ALEN];
-    BYTE    abyTA[ETH_ALEN];
+    u16    wFrameControl;
+    u16    wDurationID;
+    u8    abyRA[ETH_ALEN];
+    u8    abyTA[ETH_ALEN];
 } SRTSDataF, *PSRTSDataF;
 
 //
 // CTS buffer header
 //
 typedef struct tagSCTSDataF {
-    WORD    wFrameControl;
-    WORD    wDurationID;
-    BYTE    abyRA[ETH_ALEN];
-    WORD    wReserved;
+    u16    wFrameControl;
+    u16    wDurationID;
+    u8    abyRA[ETH_ALEN];
+    u16    wReserved;
 } SCTSDataF, *PSCTSDataF;
 
 //
@@ -66,534 +61,510 @@ typedef struct tagSMICHDR {
 	u32 adwHDR2[4];
 } SMICHDR, *PSMICHDR;
 
-
 typedef struct tagSTX_NAF_G_RTS
 {
     //RsvTime
-    WORD            wRTSTxRrvTime_ba;
-    WORD            wRTSTxRrvTime_aa;
-    WORD            wRTSTxRrvTime_bb;
-    WORD            wReserved2;
-    WORD            wTxRrvTime_b;
-    WORD            wTxRrvTime_a;
+    u16            wRTSTxRrvTime_ba;
+    u16            wRTSTxRrvTime_aa;
+    u16            wRTSTxRrvTime_bb;
+    u16            wReserved2;
+    u16            wTxRrvTime_b;
+    u16            wTxRrvTime_a;
 
     //RTS
-    BYTE            byRTSSignalField_b;
-    BYTE            byRTSServiceField_b;
-    WORD            wRTSTransmitLength_b;
-    BYTE            byRTSSignalField_a;
-    BYTE            byRTSServiceField_a;
-    WORD            wRTSTransmitLength_a;
-    WORD            wRTSDuration_ba;
-    WORD            wRTSDuration_aa;
-    WORD            wRTSDuration_bb;
-    WORD            wReserved3;
+    u8            byRTSSignalField_b;
+    u8            byRTSServiceField_b;
+    u16            wRTSTransmitLength_b;
+    u8            byRTSSignalField_a;
+    u8            byRTSServiceField_a;
+    u16            wRTSTransmitLength_a;
+    u16            wRTSDuration_ba;
+    u16            wRTSDuration_aa;
+    u16            wRTSDuration_bb;
+    u16            wReserved3;
     SRTSDataF       sRTS;
 
     //Data
-    BYTE            bySignalField_b;
-    BYTE            byServiceField_b;
-    WORD            wTransmitLength_b;
-    BYTE            bySignalField_a;
-    BYTE            byServiceField_a;
-    WORD            wTransmitLength_a;
-    WORD            wDuration_b;
-    WORD            wDuration_a;
-    WORD            wTimeStampOff_b;
-    WORD            wTimeStampOff_a;
+    u8            bySignalField_b;
+    u8            byServiceField_b;
+    u16            wTransmitLength_b;
+    u8            bySignalField_a;
+    u8            byServiceField_a;
+    u16            wTransmitLength_a;
+    u16            wDuration_b;
+    u16            wDuration_a;
+    u16            wTimeStampOff_b;
+    u16            wTimeStampOff_a;
 
 } TX_NAF_G_RTS, *PTX_NAF_G_RTS;
 
 typedef struct tagSTX_NAF_G_RTS_MIC
 {
     //RsvTime
-    WORD            wRTSTxRrvTime_ba;
-    WORD            wRTSTxRrvTime_aa;
-    WORD            wRTSTxRrvTime_bb;
-    WORD            wReserved2;
-    WORD            wTxRrvTime_b;
-    WORD            wTxRrvTime_a;
+    u16            wRTSTxRrvTime_ba;
+    u16            wRTSTxRrvTime_aa;
+    u16            wRTSTxRrvTime_bb;
+    u16            wReserved2;
+    u16            wTxRrvTime_b;
+    u16            wTxRrvTime_a;
 
     SMICHDR         sMICHDR;
 
     //RTS
-    BYTE            byRTSSignalField_b;
-    BYTE            byRTSServiceField_b;
-    WORD            wRTSTransmitLength_b;
-    BYTE            byRTSSignalField_a;
-    BYTE            byRTSServiceField_a;
-    WORD            wRTSTransmitLength_a;
-    WORD            wRTSDuration_ba;
-    WORD            wRTSDuration_aa;
-    WORD            wRTSDuration_bb;
-    WORD            wReserved3;
+    u8            byRTSSignalField_b;
+    u8            byRTSServiceField_b;
+    u16            wRTSTransmitLength_b;
+    u8            byRTSSignalField_a;
+    u8            byRTSServiceField_a;
+    u16            wRTSTransmitLength_a;
+    u16            wRTSDuration_ba;
+    u16            wRTSDuration_aa;
+    u16            wRTSDuration_bb;
+    u16            wReserved3;
     SRTSDataF       sRTS;
 
     //Data
-    BYTE            bySignalField_b;
-    BYTE            byServiceField_b;
-    WORD            wTransmitLength_b;
-    BYTE            bySignalField_a;
-    BYTE            byServiceField_a;
-    WORD            wTransmitLength_a;
-    WORD            wDuration_b;
-    WORD            wDuration_a;
-    WORD            wTimeStampOff_b;
-    WORD            wTimeStampOff_a;
+    u8            bySignalField_b;
+    u8            byServiceField_b;
+    u16            wTransmitLength_b;
+    u8            bySignalField_a;
+    u8            byServiceField_a;
+    u16            wTransmitLength_a;
+    u16            wDuration_b;
+    u16            wDuration_a;
+    u16            wTimeStampOff_b;
+    u16            wTimeStampOff_a;
 
 } TX_NAF_G_RTS_MIC, *PTX_NAF_G_RTS_MIC;
 
 typedef struct tagSTX_NAF_G_CTS
 {
     //RsvTime
-    WORD            wCTSTxRrvTime_ba;
-    WORD            wReserved2;
-    WORD            wTxRrvTime_b;
-    WORD            wTxRrvTime_a;
+    u16            wCTSTxRrvTime_ba;
+    u16            wReserved2;
+    u16            wTxRrvTime_b;
+    u16            wTxRrvTime_a;
 
     //CTS
-    BYTE            byCTSSignalField_b;
-    BYTE            byCTSServiceField_b;
-    WORD            wCTSTransmitLength_b;
-    WORD            wCTSDuration_ba;
-    WORD            wReserved3;
+    u8            byCTSSignalField_b;
+    u8            byCTSServiceField_b;
+    u16            wCTSTransmitLength_b;
+    u16            wCTSDuration_ba;
+    u16            wReserved3;
     SCTSDataF       sCTS;
 
     //Data
-    BYTE            bySignalField_b;
-    BYTE            byServiceField_b;
-    WORD            wTransmitLength_b;
-    BYTE            bySignalField_a;
-    BYTE            byServiceField_a;
-    WORD            wTransmitLength_a;
-    WORD            wDuration_b;
-    WORD            wDuration_a;
-    WORD            wTimeStampOff_b;
-    WORD            wTimeStampOff_a;
+    u8            bySignalField_b;
+    u8            byServiceField_b;
+    u16            wTransmitLength_b;
+    u8            bySignalField_a;
+    u8            byServiceField_a;
+    u16            wTransmitLength_a;
+    u16            wDuration_b;
+    u16            wDuration_a;
+    u16            wTimeStampOff_b;
+    u16            wTimeStampOff_a;
 
 } TX_NAF_G_CTS, *PTX_NAF_G_CTS;
 
-
 typedef struct tagSTX_NAF_G_CTS_MIC
 {
     //RsvTime
-    WORD            wCTSTxRrvTime_ba;
-    WORD            wReserved2;
-    WORD            wTxRrvTime_b;
-    WORD            wTxRrvTime_a;
-
+    u16            wCTSTxRrvTime_ba;
+    u16            wReserved2;
+    u16            wTxRrvTime_b;
+    u16            wTxRrvTime_a;
 
     SMICHDR         sMICHDR;
 
     //CTS
-    BYTE            byCTSSignalField_b;
-    BYTE            byCTSServiceField_b;
-    WORD            wCTSTransmitLength_b;
-    WORD            wCTSDuration_ba;
-    WORD            wReserved3;
+    u8            byCTSSignalField_b;
+    u8            byCTSServiceField_b;
+    u16            wCTSTransmitLength_b;
+    u16            wCTSDuration_ba;
+    u16            wReserved3;
     SCTSDataF       sCTS;
 
     //Data
-    BYTE            bySignalField_b;
-    BYTE            byServiceField_b;
-    WORD            wTransmitLength_b;
-    BYTE            bySignalField_a;
-    BYTE            byServiceField_a;
-    WORD            wTransmitLength_a;
-    WORD            wDuration_b;
-    WORD            wDuration_a;
-    WORD            wTimeStampOff_b;
-    WORD            wTimeStampOff_a;
+    u8            bySignalField_b;
+    u8            byServiceField_b;
+    u16            wTransmitLength_b;
+    u8            bySignalField_a;
+    u8            byServiceField_a;
+    u16            wTransmitLength_a;
+    u16            wDuration_b;
+    u16            wDuration_a;
+    u16            wTimeStampOff_b;
+    u16            wTimeStampOff_a;
 
 } TX_NAF_G_CTS_MIC, *PTX_NAF_G_CTS_MIC;
 
-
 typedef struct tagSTX_NAF_G_BEACON
 {
-    WORD            wFIFOCtl;
-    WORD            wTimeStamp;
+    u16            wFIFOCtl;
+    u16            wTimeStamp;
 
     //CTS
-    BYTE            byCTSSignalField_b;
-    BYTE            byCTSServiceField_b;
-    WORD            wCTSTransmitLength_b;
-    WORD            wCTSDuration_ba;
-    WORD            wReserved1;
+    u8            byCTSSignalField_b;
+    u8            byCTSServiceField_b;
+    u16            wCTSTransmitLength_b;
+    u16            wCTSDuration_ba;
+    u16            wReserved1;
     SCTSDataF       sCTS;
 
     //Data
-    BYTE            bySignalField_a;
-    BYTE            byServiceField_a;
-    WORD            wTransmitLength_a;
-    WORD            wDuration_a;
-    WORD            wTimeStampOff_a;
-
+    u8            bySignalField_a;
+    u8            byServiceField_a;
+    u16            wTransmitLength_a;
+    u16            wDuration_a;
+    u16            wTimeStampOff_a;
 
 } TX_NAF_G_BEACON, *PTX_NAF_G_BEACON;
 
-
 typedef struct tagSTX_NAF_AB_RTS
 {
     //RsvTime
-    WORD            wRTSTxRrvTime_ab;
-    WORD            wTxRrvTime_ab;
+    u16            wRTSTxRrvTime_ab;
+    u16            wTxRrvTime_ab;
 
     //RTS
-    BYTE            byRTSSignalField_ab;
-    BYTE            byRTSServiceField_ab;
-    WORD            wRTSTransmitLength_ab;
-    WORD            wRTSDuration_ab;
-    WORD            wReserved2;
+    u8            byRTSSignalField_ab;
+    u8            byRTSServiceField_ab;
+    u16            wRTSTransmitLength_ab;
+    u16            wRTSDuration_ab;
+    u16            wReserved2;
     SRTSDataF       sRTS;
 
     //Data
-    BYTE            bySignalField_ab;
-    BYTE            byServiceField_ab;
-    WORD            wTransmitLength_ab;
-    WORD            wDuration_ab;
-    WORD            wTimeStampOff_ab;
-
+    u8            bySignalField_ab;
+    u8            byServiceField_ab;
+    u16            wTransmitLength_ab;
+    u16            wDuration_ab;
+    u16            wTimeStampOff_ab;
 
 } TX_NAF_AB_RTS, *PTX_NAF_AB_RTS;
 
-
 typedef struct tagSTX_NAF_AB_RTS_MIC
 {
     //RsvTime
-    WORD            wRTSTxRrvTime_ab;
-    WORD            wTxRrvTime_ab;
+    u16            wRTSTxRrvTime_ab;
+    u16            wTxRrvTime_ab;
 
     SMICHDR         sMICHDR;
 
     //RTS
-    BYTE            byRTSSignalField_ab;
-    BYTE            byRTSServiceField_ab;
-    WORD            wRTSTransmitLength_ab;
-    WORD            wRTSDuration_ab;
-    WORD            wReserved2;
+    u8            byRTSSignalField_ab;
+    u8            byRTSServiceField_ab;
+    u16            wRTSTransmitLength_ab;
+    u16            wRTSDuration_ab;
+    u16            wReserved2;
     SRTSDataF       sRTS;
 
     //Data
-    BYTE            bySignalField_ab;
-    BYTE            byServiceField_ab;
-    WORD            wTransmitLength_ab;
-    WORD            wDuration_ab;
-    WORD            wTimeStampOff_ab;
-
+    u8            bySignalField_ab;
+    u8            byServiceField_ab;
+    u16            wTransmitLength_ab;
+    u16            wDuration_ab;
+    u16            wTimeStampOff_ab;
 
 } TX_NAF_AB_RTS_MIC, *PTX_NAF_AB_RTS_MIC;
 
-
-
 typedef struct tagSTX_NAF_AB_CTS
 {
     //RsvTime
-    WORD            wReserved2;
-    WORD            wTxRrvTime_ab;
+    u16            wReserved2;
+    u16            wTxRrvTime_ab;
 
     //Data
-    BYTE            bySignalField_ab;
-    BYTE            byServiceField_ab;
-    WORD            wTransmitLength_ab;
-    WORD            wDuration_ab;
-    WORD            wTimeStampOff_ab;
+    u8            bySignalField_ab;
+    u8            byServiceField_ab;
+    u16            wTransmitLength_ab;
+    u16            wDuration_ab;
+    u16            wTimeStampOff_ab;
 
 } TX_NAF_AB_CTS, *PTX_NAF_AB_CTS;
 
 typedef struct tagSTX_NAF_AB_CTS_MIC
 {
     //RsvTime
-    WORD            wReserved2;
-    WORD            wTxRrvTime_ab;
+    u16            wReserved2;
+    u16            wTxRrvTime_ab;
 
     SMICHDR         sMICHDR;
 
     //Data
-    BYTE            bySignalField_ab;
-    BYTE            byServiceField_ab;
-    WORD            wTransmitLength_ab;
-    WORD            wDuration_ab;
-    WORD            wTimeStampOff_ab;
+    u8            bySignalField_ab;
+    u8            byServiceField_ab;
+    u16            wTransmitLength_ab;
+    u16            wDuration_ab;
+    u16            wTimeStampOff_ab;
 
 } TX_NAF_AB_CTS_MIC, *PTX_NAF_AB_CTS_MIC;
 
-
 typedef struct tagSTX_NAF_AB_BEACON
 {
-    WORD            wFIFOCtl;
-    WORD            wTimeStamp;
+    u16            wFIFOCtl;
+    u16            wTimeStamp;
 
    //Data
-    BYTE            bySignalField_ab;
-    BYTE            byServiceField_ab;
-    WORD            wTransmitLength_ab;
-    WORD            wDuration_ab;
-    WORD            wTimeStampOff_ab;
+    u8            bySignalField_ab;
+    u8            byServiceField_ab;
+    u16            wTransmitLength_ab;
+    u16            wDuration_ab;
+    u16            wTimeStampOff_ab;
 
 } TX_NAF_AB_BEACON, *PTX_NAF_AB_BEACON;
 
 typedef struct tagSTX_AF_G_RTS
 {
     //RsvTime
-    WORD            wRTSTxRrvTime_ba;
-    WORD            wRTSTxRrvTime_aa;
-    WORD            wRTSTxRrvTime_bb;
-    WORD            wReserved2;
-    WORD            wTxRrvTime_b;
-    WORD            wTxRrvTime_a;
+    u16            wRTSTxRrvTime_ba;
+    u16            wRTSTxRrvTime_aa;
+    u16            wRTSTxRrvTime_bb;
+    u16            wReserved2;
+    u16            wTxRrvTime_b;
+    u16            wTxRrvTime_a;
 
     //RTS
-    BYTE            byRTSSignalField_b;
-    BYTE            byRTSServiceField_b;
-    WORD            wRTSTransmitLength_b;
-    BYTE            byRTSSignalField_a;
-    BYTE            byRTSServiceField_a;
-    WORD            wRTSTransmitLength_a;
-    WORD            wRTSDuration_ba;
-    WORD            wRTSDuration_aa;
-    WORD            wRTSDuration_bb;
-    WORD            wReserved3;
-    WORD            wRTSDuration_ba_f0;
-    WORD            wRTSDuration_aa_f0;
-    WORD            wRTSDuration_ba_f1;
-    WORD            wRTSDuration_aa_f1;
+    u8            byRTSSignalField_b;
+    u8            byRTSServiceField_b;
+    u16            wRTSTransmitLength_b;
+    u8            byRTSSignalField_a;
+    u8            byRTSServiceField_a;
+    u16            wRTSTransmitLength_a;
+    u16            wRTSDuration_ba;
+    u16            wRTSDuration_aa;
+    u16            wRTSDuration_bb;
+    u16            wReserved3;
+    u16            wRTSDuration_ba_f0;
+    u16            wRTSDuration_aa_f0;
+    u16            wRTSDuration_ba_f1;
+    u16            wRTSDuration_aa_f1;
     SRTSDataF       sRTS;
 
     //Data
-    BYTE            bySignalField_b;
-    BYTE            byServiceField_b;
-    WORD            wTransmitLength_b;
-    BYTE            bySignalField_a;
-    BYTE            byServiceField_a;
-    WORD            wTransmitLength_a;
-    WORD            wDuration_b;
-    WORD            wDuration_a;
-    WORD            wDuration_a_f0;
-    WORD            wDuration_a_f1;
-    WORD            wTimeStampOff_b;
-    WORD            wTimeStampOff_a;
+    u8            bySignalField_b;
+    u8            byServiceField_b;
+    u16            wTransmitLength_b;
+    u8            bySignalField_a;
+    u8            byServiceField_a;
+    u16            wTransmitLength_a;
+    u16            wDuration_b;
+    u16            wDuration_a;
+    u16            wDuration_a_f0;
+    u16            wDuration_a_f1;
+    u16            wTimeStampOff_b;
+    u16            wTimeStampOff_a;
 
 } TX_AF_G_RTS, *PTX_AF_G_RTS;
 
-
 typedef struct tagSTX_AF_G_RTS_MIC
 {
     //RsvTime
-    WORD            wRTSTxRrvTime_ba;
-    WORD            wRTSTxRrvTime_aa;
-    WORD            wRTSTxRrvTime_bb;
-    WORD            wReserved2;
-    WORD            wTxRrvTime_b;
-    WORD            wTxRrvTime_a;
+    u16            wRTSTxRrvTime_ba;
+    u16            wRTSTxRrvTime_aa;
+    u16            wRTSTxRrvTime_bb;
+    u16            wReserved2;
+    u16            wTxRrvTime_b;
+    u16            wTxRrvTime_a;
 
     SMICHDR         sMICHDR;
 
     //RTS
-    BYTE            byRTSSignalField_b;
-    BYTE            byRTSServiceField_b;
-    WORD            wRTSTransmitLength_b;
-    BYTE            byRTSSignalField_a;
-    BYTE            byRTSServiceField_a;
-    WORD            wRTSTransmitLength_a;
-    WORD            wRTSDuration_ba;
-    WORD            wRTSDuration_aa;
-    WORD            wRTSDuration_bb;
-    WORD            wReserved3;
-    WORD            wRTSDuration_ba_f0;
-    WORD            wRTSDuration_aa_f0;
-    WORD            wRTSDuration_ba_f1;
-    WORD            wRTSDuration_aa_f1;
+    u8            byRTSSignalField_b;
+    u8            byRTSServiceField_b;
+    u16            wRTSTransmitLength_b;
+    u8            byRTSSignalField_a;
+    u8            byRTSServiceField_a;
+    u16            wRTSTransmitLength_a;
+    u16            wRTSDuration_ba;
+    u16            wRTSDuration_aa;
+    u16            wRTSDuration_bb;
+    u16            wReserved3;
+    u16            wRTSDuration_ba_f0;
+    u16            wRTSDuration_aa_f0;
+    u16            wRTSDuration_ba_f1;
+    u16            wRTSDuration_aa_f1;
     SRTSDataF       sRTS;
 
     //Data
-    BYTE            bySignalField_b;
-    BYTE            byServiceField_b;
-    WORD            wTransmitLength_b;
-    BYTE            bySignalField_a;
-    BYTE            byServiceField_a;
-    WORD            wTransmitLength_a;
-    WORD            wDuration_b;
-    WORD            wDuration_a;
-    WORD            wDuration_a_f0;
-    WORD            wDuration_a_f1;
-    WORD            wTimeStampOff_b;
-    WORD            wTimeStampOff_a;
+    u8            bySignalField_b;
+    u8            byServiceField_b;
+    u16            wTransmitLength_b;
+    u8            bySignalField_a;
+    u8            byServiceField_a;
+    u16            wTransmitLength_a;
+    u16            wDuration_b;
+    u16            wDuration_a;
+    u16            wDuration_a_f0;
+    u16            wDuration_a_f1;
+    u16            wTimeStampOff_b;
+    u16            wTimeStampOff_a;
 
 } TX_AF_G_RTS_MIC, *PTX_AF_G_RTS_MIC;
 
-
-
 typedef struct tagSTX_AF_G_CTS
 {
     //RsvTime
-    WORD            wCTSTxRrvTime_ba;
-    WORD            wReserved2;
-    WORD            wTxRrvTime_b;
-    WORD            wTxRrvTime_a;
+    u16            wCTSTxRrvTime_ba;
+    u16            wReserved2;
+    u16            wTxRrvTime_b;
+    u16            wTxRrvTime_a;
 
     //CTS
-    BYTE            byCTSSignalField_b;
-    BYTE            byCTSServiceField_b;
-    WORD            wCTSTransmitLength_b;
-    WORD            wCTSDuration_ba;
-    WORD            wReserved3;
-    WORD            wCTSDuration_ba_f0;
-    WORD            wCTSDuration_ba_f1;
+    u8            byCTSSignalField_b;
+    u8            byCTSServiceField_b;
+    u16            wCTSTransmitLength_b;
+    u16            wCTSDuration_ba;
+    u16            wReserved3;
+    u16            wCTSDuration_ba_f0;
+    u16            wCTSDuration_ba_f1;
     SCTSDataF       sCTS;
 
     //Data
-    BYTE            bySignalField_b;
-    BYTE            byServiceField_b;
-    WORD            wTransmitLength_b;
-    BYTE            bySignalField_a;
-    BYTE            byServiceField_a;
-    WORD            wTransmitLength_a;
-    WORD            wDuration_b;
-    WORD            wDuration_a;
-    WORD            wDuration_a_f0;
-    WORD            wDuration_a_f1;
-    WORD            wTimeStampOff_b;
-    WORD            wTimeStampOff_a;
+    u8            bySignalField_b;
+    u8            byServiceField_b;
+    u16            wTransmitLength_b;
+    u8            bySignalField_a;
+    u8            byServiceField_a;
+    u16            wTransmitLength_a;
+    u16            wDuration_b;
+    u16            wDuration_a;
+    u16            wDuration_a_f0;
+    u16            wDuration_a_f1;
+    u16            wTimeStampOff_b;
+    u16            wTimeStampOff_a;
 
 } TX_AF_G_CTS, *PTX_AF_G_CTS;
 
-
 typedef struct tagSTX_AF_G_CTS_MIC
 {
     //RsvTime
-    WORD            wCTSTxRrvTime_ba;
-    WORD            wReserved2;
-    WORD            wTxRrvTime_b;
-    WORD            wTxRrvTime_a;
-
+    u16            wCTSTxRrvTime_ba;
+    u16            wReserved2;
+    u16            wTxRrvTime_b;
+    u16            wTxRrvTime_a;
 
     SMICHDR         sMICHDR;
 
     //CTS
-    BYTE            byCTSSignalField_b;
-    BYTE            byCTSServiceField_b;
-    WORD            wCTSTransmitLength_b;
-    WORD            wCTSDuration_ba;
-    WORD            wReserved3;
-    WORD            wCTSDuration_ba_f0;
-    WORD            wCTSDuration_ba_f1;
+    u8            byCTSSignalField_b;
+    u8            byCTSServiceField_b;
+    u16            wCTSTransmitLength_b;
+    u16            wCTSDuration_ba;
+    u16            wReserved3;
+    u16            wCTSDuration_ba_f0;
+    u16            wCTSDuration_ba_f1;
     SCTSDataF       sCTS;
 
     //Data
-    BYTE            bySignalField_b;
-    BYTE            byServiceField_b;
-    WORD            wTransmitLength_b;
-    BYTE            bySignalField_a;
-    BYTE            byServiceField_a;
-    WORD            wTransmitLength_a;
-    WORD            wDuration_b;
-    WORD            wDuration_a;
-    WORD            wDuration_a_f0;
-    WORD            wDuration_a_f1;
-    WORD            wTimeStampOff_b;
-    WORD            wTimeStampOff_a;
+    u8            bySignalField_b;
+    u8            byServiceField_b;
+    u16            wTransmitLength_b;
+    u8            bySignalField_a;
+    u8            byServiceField_a;
+    u16            wTransmitLength_a;
+    u16            wDuration_b;
+    u16            wDuration_a;
+    u16            wDuration_a_f0;
+    u16            wDuration_a_f1;
+    u16            wTimeStampOff_b;
+    u16            wTimeStampOff_a;
 
 } TX_AF_G_CTS_MIC, *PTX_AF_G_CTS_MIC;
 
-
-
 typedef struct tagSTX_AF_A_RTS
 {
     //RsvTime
-    WORD            wRTSTxRrvTime_a;
-    WORD            wTxRrvTime_a;
+    u16            wRTSTxRrvTime_a;
+    u16            wTxRrvTime_a;
 
     //RTS
-    BYTE            byRTSSignalField_a;
-    BYTE            byRTSServiceField_a;
-    WORD            wRTSTransmitLength_a;
-    WORD            wRTSDuration_a;
-    WORD            wReserved2;
-    WORD            wRTSDuration_a_f0;
-    WORD            wRTSDuration_a_f1;
+    u8            byRTSSignalField_a;
+    u8            byRTSServiceField_a;
+    u16            wRTSTransmitLength_a;
+    u16            wRTSDuration_a;
+    u16            wReserved2;
+    u16            wRTSDuration_a_f0;
+    u16            wRTSDuration_a_f1;
     SRTSDataF       sRTS;
 
     //Data
-    BYTE            bySignalField_a;
-    BYTE            byServiceField_a;
-    WORD            wTransmitLength_a;
-    WORD            wDuration_a;
-    WORD            wTimeStampOff_a;
-    WORD            wDuration_a_f0;
-    WORD            wDuration_a_f1;
+    u8            bySignalField_a;
+    u8            byServiceField_a;
+    u16            wTransmitLength_a;
+    u16            wDuration_a;
+    u16            wTimeStampOff_a;
+    u16            wDuration_a_f0;
+    u16            wDuration_a_f1;
 
 } TX_AF_A_RTS, *PTX_AF_A_RTS;
 
-
 typedef struct tagSTX_AF_A_RTS_MIC
 {
     //RsvTime
-    WORD            wRTSTxRrvTime_a;
-    WORD            wTxRrvTime_a;
+    u16            wRTSTxRrvTime_a;
+    u16            wTxRrvTime_a;
 
     SMICHDR         sMICHDR;
 
     //RTS
-    BYTE            byRTSSignalField_a;
-    BYTE            byRTSServiceField_a;
-    WORD            wRTSTransmitLength_a;
-    WORD            wRTSDuration_a;
-    WORD            wReserved2;
-    WORD            wRTSDuration_a_f0;
-    WORD            wRTSDuration_a_f1;
+    u8            byRTSSignalField_a;
+    u8            byRTSServiceField_a;
+    u16            wRTSTransmitLength_a;
+    u16            wRTSDuration_a;
+    u16            wReserved2;
+    u16            wRTSDuration_a_f0;
+    u16            wRTSDuration_a_f1;
     SRTSDataF       sRTS;
 
     //Data
-    BYTE            bySignalField_a;
-    BYTE            byServiceField_a;
-    WORD            wTransmitLength_a;
-    WORD            wDuration_a;
-    WORD            wTimeStampOff_a;
-    WORD            wDuration_a_f0;
-    WORD            wDuration_a_f1;
+    u8            bySignalField_a;
+    u8            byServiceField_a;
+    u16            wTransmitLength_a;
+    u16            wDuration_a;
+    u16            wTimeStampOff_a;
+    u16            wDuration_a_f0;
+    u16            wDuration_a_f1;
 
 } TX_AF_A_RTS_MIC, *PTX_AF_A_RTS_MIC;
 
-
-
 typedef struct tagSTX_AF_A_CTS
 {
     //RsvTime
-    WORD            wReserved2;
-    WORD            wTxRrvTime_a;
+    u16            wReserved2;
+    u16            wTxRrvTime_a;
 
     //Data
-    BYTE            bySignalField_a;
-    BYTE            byServiceField_a;
-    WORD            wTransmitLength_a;
-    WORD            wDuration_a;
-    WORD            wTimeStampOff_a;
-    WORD            wDuration_a_f0;
-    WORD            wDuration_a_f1;
+    u8            bySignalField_a;
+    u8            byServiceField_a;
+    u16            wTransmitLength_a;
+    u16            wDuration_a;
+    u16            wTimeStampOff_a;
+    u16            wDuration_a_f0;
+    u16            wDuration_a_f1;
 
 } TX_AF_A_CTS, *PTX_AF_A_CTS;
 
-
 typedef struct tagSTX_AF_A_CTS_MIC
 {
     //RsvTime
-    WORD            wReserved2;
-    WORD            wTxRrvTime_a;
+    u16            wReserved2;
+    u16            wTxRrvTime_a;
 
     SMICHDR         sMICHDR;
 
     //Data
-    BYTE            bySignalField_a;
-    BYTE            byServiceField_a;
-    WORD            wTransmitLength_a;
-    WORD            wDuration_a;
-    WORD            wTimeStampOff_a;
-    WORD            wDuration_a_f0;
-    WORD            wDuration_a_f1;
+    u8            bySignalField_a;
+    u8            byServiceField_a;
+    u16            wTransmitLength_a;
+    u16            wDuration_a;
+    u16            wTimeStampOff_a;
+    u16            wDuration_a_f0;
+    u16            wDuration_a_f1;
 
 } TX_AF_A_CTS_MIC, *PTX_AF_A_CTS_MIC;
 
-
 //
 // union with all of the TX Buffer Type
 //
@@ -620,51 +591,43 @@ typedef union tagUTX_BUFFER_CONTAINER
 
 } TX_BUFFER_CONTAINER, *PTX_BUFFER_CONTAINER;
 
-
 //
 // Remote NDIS message format
 //
 typedef struct tagSTX_BUFFER
 {
-    BYTE                            byType;
-    BYTE                            byPKTNO;
-    WORD                            wTxByteCount;
+    u8                            byType;
+    u8                            byPKTNO;
+    u16                            wTxByteCount;
 
 	u32 adwTxKey[4];
-    WORD                            wFIFOCtl;
-    WORD                            wTimeStamp;
-    WORD                            wFragCtl;
-    WORD                            wReserved;
-
+    u16                            wFIFOCtl;
+    u16                            wTimeStamp;
+    u16                            wFragCtl;
+    u16                            wReserved;
 
     // Actual message
     TX_BUFFER_CONTAINER             BufferHeader;
 
 } TX_BUFFER, *PTX_BUFFER;
 
-
 //
 // Remote NDIS message format
 //
 typedef struct tagSBEACON_BUFFER
 {
-    BYTE                            byType;
-    BYTE                            byPKTNO;
-    WORD                            wTxByteCount;
+    u8                            byType;
+    u8                            byPKTNO;
+    u16                            wTxByteCount;
 
-    WORD                            wFIFOCtl;
-    WORD                            wTimeStamp;
+    u16                            wFIFOCtl;
+    u16                            wTimeStamp;
 
     // Actual message
     TX_BUFFER_CONTAINER             BufferHeader;
 
 } BEACON_BUFFER, *PBEACON_BUFFER;
 
-
-/*---------------------  Export Variables  --------------------------*/
-
-/*---------------------  Export Functions  --------------------------*/
-
 void vDMA0_tx_80211(struct vnt_private *, struct sk_buff *skb);
 int nsDMA_tx_packet(struct vnt_private *, u32 uDMAIdx, struct sk_buff *skb);
 CMD_STATUS csMgmt_xmit(struct vnt_private *, struct vnt_tx_mgmt *);
diff --git a/drivers/staging/vt6656/srom.h b/drivers/staging/vt6656/srom.h
index dba21a5..488192d 100644
--- a/drivers/staging/vt6656/srom.h
+++ b/drivers/staging/vt6656/srom.h
@@ -30,10 +30,6 @@
 #ifndef __SROM_H__
 #define __SROM_H__
 
-#include "ttype.h"
-
-/*---------------------  Export Definitions -------------------------*/
-
 #define EEP_MAX_CONTEXT_SIZE    256
 
 #define CB_EEPROM_READBYTE_WAIT 900     //us
@@ -56,7 +52,6 @@
 #define EEP_OFS_SETPT_CCK   0x21
 #define EEP_OFS_PWR_OFDMG   0x23
 
-
 #define EEP_OFS_CALIB_TX_IQ 0x24
 #define EEP_OFS_CALIB_TX_DC 0x25
 #define EEP_OFS_CALIB_RX_IQ 0x26
@@ -80,48 +75,38 @@
 //
 #define EEP_RADIOCTL_ENABLE 0x80
 
-/*---------------------  Export Types  ------------------------------*/
-
 // AT24C02 eeprom contents
 //      2048 bits = 256 bytes = 128 words
 //
 typedef struct tagSSromReg {
-    BYTE    abyPAR[6];                  // 0x00 (WORD)
-
-    WORD    wSUB_VID;                   // 0x03 (WORD)
-    WORD    wSUB_SID;
-
-    BYTE    byBCFG0;                    // 0x05 (WORD)
-    BYTE    byBCFG1;
-
-    BYTE    byFCR0;                     // 0x06 (WORD)
-    BYTE    byFCR1;
-    BYTE    byPMC0;                     // 0x07 (WORD)
-    BYTE    byPMC1;
-    BYTE    byMAXLAT;                   // 0x08 (WORD)
-    BYTE    byMINGNT;
-    BYTE    byCFG0;                     // 0x09 (WORD)
-    BYTE    byCFG1;
-    WORD    wCISPTR;                    // 0x0A (WORD)
-    WORD    wRsv0;                      // 0x0B (WORD)
-    WORD    wRsv1;                      // 0x0C (WORD)
-    BYTE    byBBPAIR;                   // 0x0D (WORD)
-    BYTE    byRFTYPE;
-    BYTE    byMinChannel;               // 0x0E (WORD)
-    BYTE    byMaxChannel;
-    BYTE    bySignature;                // 0x0F (WORD)
-    BYTE    byCheckSum;
-
-    BYTE    abyReserved0[96];           // 0x10 (WORD)
-    BYTE    abyCIS[128];                // 0x80 (WORD)
+    u8    abyPAR[6];                  // 0x00 (u16)
+
+    u16    wSUB_VID;                   // 0x03 (u16)
+    u16    wSUB_SID;
+
+    u8    byBCFG0;                    // 0x05 (u16)
+    u8    byBCFG1;
+
+    u8    byFCR0;                     // 0x06 (u16)
+    u8    byFCR1;
+    u8    byPMC0;                     // 0x07 (u16)
+    u8    byPMC1;
+    u8    byMAXLAT;                   // 0x08 (u16)
+    u8    byMINGNT;
+    u8    byCFG0;                     // 0x09 (u16)
+    u8    byCFG1;
+    u16    wCISPTR;                    // 0x0A (u16)
+    u16    wRsv0;                      // 0x0B (u16)
+    u16    wRsv1;                      // 0x0C (u16)
+    u8    byBBPAIR;                   // 0x0D (u16)
+    u8    byRFTYPE;
+    u8    byMinChannel;               // 0x0E (u16)
+    u8    byMaxChannel;
+    u8    bySignature;                // 0x0F (u16)
+    u8    byCheckSum;
+
+    u8    abyReserved0[96];           // 0x10 (u16)
+    u8    abyCIS[128];                // 0x80 (u16)
 } SSromReg, *PSSromReg;
 
-/*---------------------  Export Macros ------------------------------*/
-
-/*---------------------  Export Classes  ----------------------------*/
-
-/*---------------------  Export Variables  --------------------------*/
-
-/*---------------------  Export Functions  --------------------------*/
-
 #endif /* __EEPROM_H__ */
diff --git a/drivers/staging/vt6656/tcrc.c b/drivers/staging/vt6656/tcrc.c
index 2237eeb..7229f26 100644
--- a/drivers/staging/vt6656/tcrc.c
+++ b/drivers/staging/vt6656/tcrc.c
@@ -35,14 +35,8 @@
 
 #include "tcrc.h"
 
-/*---------------------  Static Definitions -------------------------*/
-
-/*---------------------  Static Classes  ----------------------------*/
-
-/*---------------------  Static Variables  --------------------------*/
-
 /* 32-bit CRC table */
-static const DWORD s_adwCrc32Table[256] = {
+static const u32 s_adwCrc32Table[256] = {
     0x00000000L, 0x77073096L, 0xEE0E612CL, 0x990951BAL,
     0x076DC419L, 0x706AF48FL, 0xE963A535L, 0x9E6495A3L,
     0x0EDB8832L, 0x79DCB8A4L, 0xE0D5E91EL, 0x97D2D988L,
@@ -109,13 +103,6 @@ static const DWORD s_adwCrc32Table[256] = {
     0xB40BBE37L, 0xC30C8EA1L, 0x5A05DF1BL, 0x2D02EF8DL
 };
 
-/*---------------------  Static Functions  --------------------------*/
-
-/*---------------------  Export Variables  --------------------------*/
-
-
-
-
 /*+
  *
  * Description:
@@ -132,13 +119,13 @@ static const DWORD s_adwCrc32Table[256] = {
  * Return Value: CRC-32
  *
 -*/
-DWORD CRCdwCrc32(PBYTE pbyData, unsigned int cbByte, DWORD dwCrcSeed)
+u32 CRCdwCrc32(u8 * pbyData, unsigned int cbByte, u32 dwCrcSeed)
 {
-	DWORD dwCrc;
+	u32 dwCrc;
 
 	dwCrc = dwCrcSeed;
 	while (cbByte--) {
-		dwCrc = s_adwCrc32Table[(BYTE)((dwCrc ^ (*pbyData)) & 0xFF)] ^
+		dwCrc = s_adwCrc32Table[(u8)((dwCrc ^ (*pbyData)) & 0xFF)] ^
 			(dwCrc >> 8);
 		pbyData++;
 	}
@@ -146,7 +133,6 @@ DWORD CRCdwCrc32(PBYTE pbyData, unsigned int cbByte, DWORD dwCrcSeed)
 	return dwCrc;
 }
 
-
 /*+
  *
  * Description:
@@ -165,12 +151,11 @@ DWORD CRCdwCrc32(PBYTE pbyData, unsigned int cbByte, DWORD dwCrcSeed)
  * Return Value: CRC-32
  *
 -*/
-DWORD CRCdwGetCrc32(PBYTE pbyData, unsigned int cbByte)
+u32 CRCdwGetCrc32(u8 * pbyData, unsigned int cbByte)
 {
     return ~CRCdwCrc32(pbyData, cbByte, 0xFFFFFFFFL);
 }
 
-
 /*+
  *
  * Description:
@@ -191,9 +176,8 @@ DWORD CRCdwGetCrc32(PBYTE pbyData, unsigned int cbByte)
  * Return Value: CRC-32
  *
 -*/
-DWORD CRCdwGetCrc32Ex(PBYTE pbyData, unsigned int cbByte, DWORD dwPreCRC)
+u32 CRCdwGetCrc32Ex(u8 * pbyData, unsigned int cbByte, u32 dwPreCRC)
 {
     return CRCdwCrc32(pbyData, cbByte, dwPreCRC);
 }
 
-
diff --git a/drivers/staging/vt6656/tcrc.h b/drivers/staging/vt6656/tcrc.h
index dc54bd8..5b1f368 100644
--- a/drivers/staging/vt6656/tcrc.h
+++ b/drivers/staging/vt6656/tcrc.h
@@ -29,22 +29,10 @@
 #ifndef __TCRC_H__
 #define __TCRC_H__
 
-#include "ttype.h"
+#include <linux/types.h>
 
-/*---------------------  Export Definitions -------------------------*/
-
-/*---------------------  Export Types  ------------------------------*/
-
-/*---------------------  Export Macros ------------------------------*/
-
-/*---------------------  Export Classes  ----------------------------*/
-
-/*---------------------  Export Variables  --------------------------*/
-
-/*---------------------  Export Functions  --------------------------*/
-
-DWORD CRCdwCrc32(PBYTE pbyData, unsigned int cbByte, DWORD dwCrcSeed);
-DWORD CRCdwGetCrc32(PBYTE pbyData, unsigned int cbByte);
-DWORD CRCdwGetCrc32Ex(PBYTE pbyData, unsigned int cbByte, DWORD dwPreCRC);
+u32 CRCdwCrc32(u8 * pbyData, unsigned int cbByte, u32 dwCrcSeed);
+u32 CRCdwGetCrc32(u8 * pbyData, unsigned int cbByte);
+u32 CRCdwGetCrc32Ex(u8 * pbyData, unsigned int cbByte, u32 dwPreCRC);
 
 #endif /* __TCRC_H__ */
diff --git a/drivers/staging/vt6656/tether.c b/drivers/staging/vt6656/tether.c
index 95286c4..1db1e84 100644
--- a/drivers/staging/vt6656/tether.c
+++ b/drivers/staging/vt6656/tether.c
@@ -25,7 +25,6 @@
  * Date: May 21, 1996
  *
  * Functions:
- *      ETHbyGetHashIndexByCrc32 - Calculate multicast hash value by CRC32
  *      ETHbIsBufferCrc32Ok - Check CRC value of the buffer if Ok or not
  *
  * Revision History:
@@ -37,52 +36,6 @@
 #include "tcrc.h"
 #include "tether.h"
 
-/*---------------------  Static Definitions -------------------------*/
-
-/*---------------------  Static Classes  ----------------------------*/
-
-/*---------------------  Static Variables  --------------------------*/
-
-/*---------------------  Static Functions  --------------------------*/
-
-/*---------------------  Export Variables  --------------------------*/
-
-
-
-/*
- * Description: Calculate multicast hash value by CRC32
- *
- * Parameters:
- *  In:
- *		pbyMultiAddr    - Multicast Address
- *  Out:
- *      none
- *
- * Return Value: Hash value
- *
- */
-BYTE ETHbyGetHashIndexByCrc32(PBYTE pbyMultiAddr)
-{
-	int     ii;
-	BYTE    byTmpHash;
-	BYTE    byHash = 0;
-
-	/* get the least 6-bits from CRC generator */
-	byTmpHash = (BYTE)(CRCdwCrc32(pbyMultiAddr, ETH_ALEN,
-			0xFFFFFFFFL) & 0x3F);
-	/* reverse most bit to least bit */
-	for (ii = 0; ii < (sizeof(byTmpHash) * 8); ii++) {
-		byHash <<= 1;
-		if (byTmpHash & 0x01)
-			byHash |= 1;
-		byTmpHash >>= 1;
-	}
-
-	/* adjust 6-bits to the right most */
-	return byHash >> 2;
-}
-
-
 /*
  * Description: Check CRC value of the buffer if Ok or not
  *
@@ -96,12 +49,12 @@ BYTE ETHbyGetHashIndexByCrc32(PBYTE pbyMultiAddr)
  * Return Value: true if ok; false if error.
  *
  */
-bool ETHbIsBufferCrc32Ok(PBYTE pbyBuffer, unsigned int cbFrameLength)
+bool ETHbIsBufferCrc32Ok(u8 * pbyBuffer, unsigned int cbFrameLength)
 {
-	DWORD dwCRC;
+	u32 dwCRC;
 
 	dwCRC = CRCdwGetCrc32(pbyBuffer, cbFrameLength - 4);
-	if (cpu_to_le32(*((PDWORD)(pbyBuffer + cbFrameLength - 4))) != dwCRC)
+	if (cpu_to_le32(*((u32 *)(pbyBuffer + cbFrameLength - 4))) != dwCRC)
 		return false;
 	return true;
 }
diff --git a/drivers/staging/vt6656/tether.h b/drivers/staging/vt6656/tether.h
index 2f8f485..24465cf 100644
--- a/drivers/staging/vt6656/tether.h
+++ b/drivers/staging/vt6656/tether.h
@@ -30,9 +30,7 @@
 #define __TETHER_H__
 
 #include <linux/if_ether.h>
-#include "ttype.h"
 
-/*---------------------  Export Definitions -------------------------*/
 //
 // constants
 //
@@ -44,11 +42,6 @@
 
 #define TYPE_MGMT_PROBE_RSP 0x5000
 
-//
-// wFrameCtl field in the S802_11Header
-//
-// NOTE....
-//   in network byte order, high byte is going first
 #define FC_TODS             0x0001
 #define FC_FROMDS           0x0002
 #define FC_MOREFRAG         0x0004
@@ -71,8 +64,6 @@
 #define TYPE_CTL_CTS        0xc400
 #define TYPE_CTL_ACK        0xd400
 
-
-
 #else //if LITTLE_ENDIAN
 //
 // wType field in the SEthernetHeader
@@ -82,11 +73,6 @@
 
 #define TYPE_MGMT_PROBE_RSP 0x0050
 
-//
-// wFrameCtl field in the S802_11Header
-//
-// NOTE....
-//   in network byte order, high byte is going first
 #define FC_TODS             0x0100
 #define FC_FROMDS           0x0200
 #define FC_MOREFRAG         0x0400
@@ -109,58 +95,21 @@
 #define TYPE_CTL_CTS        0x00c4
 #define TYPE_CTL_ACK        0x00d4
 
-
-
 #endif //#ifdef __BIG_ENDIAN
 
 #define WEP_IV_MASK         0x00FFFFFF
 
-/*---------------------  Export Types  ------------------------------*/
-//
-// Ethernet packet
-//
-typedef struct tagSEthernetHeader {
-    BYTE    abyDstAddr[ETH_ALEN];
-    BYTE    abySrcAddr[ETH_ALEN];
-    WORD    wType;
-} __attribute__ ((__packed__))
-SEthernetHeader, *PSEthernetHeader;
-
-
 //
 // 802_3 packet
 //
 typedef struct tagS802_3Header {
-    BYTE    abyDstAddr[ETH_ALEN];
-    BYTE    abySrcAddr[ETH_ALEN];
-    WORD    wLen;
+    u8    abyDstAddr[ETH_ALEN];
+    u8    abySrcAddr[ETH_ALEN];
+    u16    wLen;
 } __attribute__ ((__packed__))
 S802_3Header, *PS802_3Header;
 
-//
-// 802_11 packet
-//
-typedef struct tagS802_11Header {
-    WORD    wFrameCtl;
-    WORD    wDurationID;
-    BYTE    abyAddr1[ETH_ALEN];
-    BYTE    abyAddr2[ETH_ALEN];
-    BYTE    abyAddr3[ETH_ALEN];
-    WORD    wSeqCtl;
-    BYTE    abyAddr4[ETH_ALEN];
-} __attribute__ ((__packed__))
-S802_11Header, *PS802_11Header;
-
-/*---------------------  Export Macros ------------------------------*/
-
-/*---------------------  Export Classes  ----------------------------*/
-
-/*---------------------  Export Variables  --------------------------*/
-
-/*---------------------  Export Functions  --------------------------*/
-
-BYTE ETHbyGetHashIndexByCrc32(PBYTE pbyMultiAddr);
-//BYTE ETHbyGetHashIndexByCrc(PBYTE pbyMultiAddr);
-bool ETHbIsBufferCrc32Ok(PBYTE pbyBuffer, unsigned int cbFrameLength);
+//u8 ETHbyGetHashIndexByCrc(u8 * pbyMultiAddr);
+bool ETHbIsBufferCrc32Ok(u8 * pbyBuffer, unsigned int cbFrameLength);
 
 #endif /* __TETHER_H__ */
diff --git a/drivers/staging/vt6656/tkip.c b/drivers/staging/vt6656/tkip.c
index 282c08d..9d643e4 100644
--- a/drivers/staging/vt6656/tkip.c
+++ b/drivers/staging/vt6656/tkip.c
@@ -35,27 +35,11 @@
 #include "tmacro.h"
 #include "tkip.h"
 
-/*---------------------  Static Definitions -------------------------*/
-
-/*---------------------  Static Classes  ----------------------------*/
-
-/*---------------------  Static Variables  --------------------------*/
-
-/*---------------------  Static Functions  --------------------------*/
-
-/*---------------------  Export Variables  --------------------------*/
-
-/*---------------------  Static Definitions -------------------------*/
-
-/*---------------------  Static Classes  ----------------------------*/
-
-/*---------------------  Static Variables  --------------------------*/
-
 /* The Sbox is reduced to 2 16-bit wide tables, each with 256 entries. */
 /* The 2nd table is the same as the 1st but with the upper and lower   */
 /* bytes swapped. To allow an endian tolerant implementation, the byte */
 /* halves have been expressed independently here.                      */
-const BYTE TKIP_Sbox_Lower[256] = {
+const u8 TKIP_Sbox_Lower[256] = {
     0xA5,0x84,0x99,0x8D,0x0D,0xBD,0xB1,0x54,
     0x50,0x03,0xA9,0x7D,0x19,0x62,0xE6,0x9A,
     0x45,0x9D,0x40,0x87,0x15,0xEB,0xC9,0x0B,
@@ -90,7 +74,7 @@ const BYTE TKIP_Sbox_Lower[256] = {
     0xC3,0xB0,0x77,0x11,0xCB,0xFC,0xD6,0x3A
 };
 
-const BYTE TKIP_Sbox_Upper[256] = {
+const u8 TKIP_Sbox_Upper[256] = {
     0xC6,0xF8,0xEE,0xF6,0xFF,0xD6,0xDE,0x91,
     0x60,0x02,0xCE,0x56,0xE7,0xB5,0x4D,0xEC,
     0x8F,0x1F,0x89,0xFA,0xEF,0xB2,0x8E,0xFB,
@@ -125,13 +109,8 @@ const BYTE TKIP_Sbox_Upper[256] = {
     0x82,0x29,0x5A,0x1E,0x7B,0xA8,0x6D,0x2C
 };
 
-
 //STKIPKeyManagement  sTKIPKeyTable[MAX_TKIP_KEY];
 
-/*---------------------  Static Functions  --------------------------*/
-
-/*---------------------  Export Variables  --------------------------*/
-
 /************************************************************/
 /* tkip_sbox()                                              */
 /* Returns a 16 bit value from a 64K entry table. The Table */
@@ -152,7 +131,6 @@ static unsigned int tkip_sbox(unsigned int index)
     return (left ^ right);
 };
 
-
 static unsigned int rotr1(unsigned int a)
 {
     unsigned int b;
@@ -166,7 +144,6 @@ static unsigned int rotr1(unsigned int a)
     return b;
 }
 
-
 /*
  * Description: Calculate RC4Key fom TK, TA, and TSC
  *
@@ -182,11 +159,11 @@ static unsigned int rotr1(unsigned int a)
  *
  */
 void TKIPvMixKey(
-    PBYTE   pbyTKey,
-    PBYTE   pbyTA,
-    WORD    wTSC15_0,
-    DWORD   dwTSC47_16,
-    PBYTE   pbyRC4Key
+    u8 *   pbyTKey,
+    u8 *   pbyTA,
+    u16    wTSC15_0,
+    u32   dwTSC47_16,
+    u8 *   pbyRC4Key
     )
 {
 	u32 p1k[5];
diff --git a/drivers/staging/vt6656/tkip.h b/drivers/staging/vt6656/tkip.h
index 47c3a85..4fba7ef 100644
--- a/drivers/staging/vt6656/tkip.h
+++ b/drivers/staging/vt6656/tkip.h
@@ -30,28 +30,16 @@
 #ifndef __TKIP_H__
 #define __TKIP_H__
 
-#include "ttype.h"
 #include "tether.h"
 
-/*---------------------  Export Definitions -------------------------*/
 #define TKIP_KEY_LEN        16
 
-/*---------------------  Export Types  ------------------------------*/
-
-/*---------------------  Export Macros ------------------------------*/
-
-/*---------------------  Export Classes  ----------------------------*/
-
-/*---------------------  Export Variables  --------------------------*/
-
-/*---------------------  Export Functions  --------------------------*/
-
 void TKIPvMixKey(
-    PBYTE   pbyTKey,
-    PBYTE   pbyTA,
-    WORD    wTSC15_0,
-    DWORD   dwTSC47_16,
-    PBYTE   pbyRC4Key
+    u8 *   pbyTKey,
+    u8 *   pbyTA,
+    u16    wTSC15_0,
+    u32   dwTSC47_16,
+    u8 *   pbyRC4Key
     );
 
 #endif /* __TKIP_H__ */
diff --git a/drivers/staging/vt6656/tmacro.h b/drivers/staging/vt6656/tmacro.h
index 3c81e2b..15cd5ab 100644
--- a/drivers/staging/vt6656/tmacro.h
+++ b/drivers/staging/vt6656/tmacro.h
@@ -29,32 +29,30 @@
 #ifndef __TMACRO_H__
 #define __TMACRO_H__
 
-#include "ttype.h"
-
 /****** Common helper macros ***********************************************/
 
 #if !defined(LOBYTE)
-#define LOBYTE(w)           ((BYTE)(w))
+#define LOBYTE(w)           ((u8)(w))
 #endif
 #if !defined(HIBYTE)
-#define HIBYTE(w)           ((BYTE)(((WORD)(w) >> 8) & 0xFF))
+#define HIBYTE(w)           ((u8)(((u16)(w) >> 8) & 0xFF))
 #endif
 
 #if !defined(LOWORD)
-#define LOWORD(d)           ((WORD)(d))
+#define LOWORD(d)           ((u16)(d))
 #endif
 #if !defined(HIWORD)
-#define HIWORD(d)           ((WORD)((((DWORD)(d)) >> 16) & 0xFFFF))
+#define HIWORD(d)           ((u16)((((u32)(d)) >> 16) & 0xFFFF))
 #endif
 
 #define LODWORD(q)          ((q).u.dwLowDword)
 #define HIDWORD(q)          ((q).u.dwHighDword)
 
 #if !defined(MAKEWORD)
-#define MAKEWORD(lb, hb)    ((WORD)(((BYTE)(lb)) | (((WORD)((BYTE)(hb))) << 8)))
+#define MAKEWORD(lb, hb)    ((u16)(((u8)(lb)) | (((u16)((u8)(hb))) << 8)))
 #endif
 #if !defined(MAKEDWORD)
-#define MAKEDWORD(lw, hw)   ((DWORD)(((WORD)(lw)) | (((DWORD)((WORD)(hw))) << 16)))
+#define MAKEDWORD(lw, hw)   ((u32)(((u16)(lw)) | (((u32)((u16)(hw))) << 16)))
 #endif
 
 #endif /* __TMACRO_H__ */
diff --git a/drivers/staging/vt6656/ttype.h b/drivers/staging/vt6656/ttype.h
deleted file mode 100644
index d7b6489..0000000
--- a/drivers/staging/vt6656/ttype.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, 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.
- *
- * File: ttype.h
- *
- * Purpose: define basic common types and macros
- *
- * Author: Tevin Chen
- *
- * Date: May 21, 1996
- *
- */
-
-#ifndef __TTYPE_H__
-#define __TTYPE_H__
-
-#include <linux/types.h>
-
-/******* Common definitions and typedefs ***********************************/
-
-/****** Simple typedefs  ***************************************************/
-
-typedef u8 BYTE;
-typedef u16 WORD;
-typedef u32 DWORD;
-
-/****** Common pointer types ***********************************************/
-
-typedef u32 ULONG_PTR;
-typedef u32 DWORD_PTR;
-
-// boolean pointer
-
-typedef BYTE *           PBYTE;
-
-typedef WORD *           PWORD;
-
-typedef DWORD *          PDWORD;
-
-#endif /* __TTYPE_H__ */
diff --git a/drivers/staging/vt6656/usbpipe.c b/drivers/staging/vt6656/usbpipe.c
index 00fd0f8..098be60 100644
--- a/drivers/staging/vt6656/usbpipe.c
+++ b/drivers/staging/vt6656/usbpipe.c
@@ -45,7 +45,6 @@
 #include "desc.h"
 #include "device.h"
 
-/*---------------------  Static Definitions -------------------------*/
 //endpoint def
 //endpoint 0: control
 //endpoint 1: interrupt
@@ -55,28 +54,18 @@
 //static int          msglevel                =MSG_LEVEL_DEBUG;
 static int          msglevel                =MSG_LEVEL_INFO;
 
-
 #define USB_CTL_WAIT   500 //ms
 
 #ifndef URB_ASYNC_UNLINK
 #define URB_ASYNC_UNLINK    0
 #endif
 
-/*---------------------  Static Classes  ----------------------------*/
-
-/*---------------------  Static Variables  --------------------------*/
-
-/*---------------------  Static Functions  --------------------------*/
 static void s_nsInterruptUsbIoCompleteRead(struct urb *urb);
 static void s_nsBulkInUsbIoCompleteRead(struct urb *urb);
 static void s_nsBulkOutIoCompleteWrite(struct urb *urb);
 static void s_nsControlInUsbIoCompleteRead(struct urb *urb);
 static void s_nsControlInUsbIoCompleteWrite(struct urb *urb);
 
-/*---------------------  Export Variables  --------------------------*/
-
-/*---------------------  Export Functions  --------------------------*/
-
 int PIPEnsControlOutAsyn(struct vnt_private *pDevice, u8 byRequest,
 	u16 wValue, u16 wIndex, u16 wLength, u8 *pbyBuffer)
 {
@@ -251,8 +240,6 @@ static void s_nsControlInUsbIoCompleteWrite(struct urb *urb)
     MP_CLEAR_FLAG(pDevice, fMP_CONTROL_WRITES);
 }
 
-
-
 /*
  * Description:
  *      Complete function of usb Control callback
@@ -288,9 +275,6 @@ static void s_nsControlInUsbIoCompleteRead(struct urb *urb)
     MP_CLEAR_FLAG(pDevice, fMP_CONTROL_READS);
 }
 
-
-
-
 /*
  * Description:
  *      Allocates an usb interrupt in irp and calls USBD.
@@ -341,7 +325,6 @@ usb_fill_bulk_urb(pDevice->pInterruptURB,
     return ntStatus;
 }
 
-
 /*
  * Description:
  *      Complete function of usb interrupt in irp.
@@ -403,7 +386,6 @@ static void s_nsInterruptUsbIoCompleteRead(struct urb *urb)
 
     STAvUpdateUSBCounter(&pDevice->scStatistic.USB_InterruptStat, ntStatus);
 
-
     if (pDevice->fKillEventPollingThread != true) {
        usb_fill_bulk_urb(pDevice->pInterruptURB,
 		      pDevice->usb,
@@ -444,7 +426,6 @@ int PIPEnsBulkInUsbRead(struct vnt_private *pDevice, PRCB pRCB)
 	int ntStatus = 0;
 	struct urb *pUrb;
 
-
     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsStartBulkInUsbRead\n");
 
     if (pDevice->Flags & fMP_DISCONNECTED)
@@ -452,7 +433,6 @@ int PIPEnsBulkInUsbRead(struct vnt_private *pDevice, PRCB pRCB)
 
     pDevice->ulBulkInPosted++;
 
-
 	pUrb = pRCB->pUrb;
     //
     // Now that we have created the urb, we will send a
@@ -482,9 +462,6 @@ int PIPEnsBulkInUsbRead(struct vnt_private *pDevice, PRCB pRCB)
     return ntStatus;
 }
 
-
-
-
 /*
  * Description:
  *      Complete function of usb BulkIn irp.
@@ -535,7 +512,6 @@ static void s_nsBulkInUsbIoCompleteRead(struct urb *urb)
            pDevice->scStatistic.RxOkCnt ++;
     }
 
-
     STAvUpdateUSBCounter(&pDevice->scStatistic.USB_BulkInStat, status);
 
     if (bIndicateReceive) {
@@ -553,7 +529,6 @@ static void s_nsBulkInUsbIoCompleteRead(struct urb *urb)
         spin_unlock(&pDevice->lock);
     }
 
-
     return;
 }
 
@@ -576,8 +551,6 @@ int PIPEnsSendBulkOut(struct vnt_private *pDevice, PUSB_SEND_CONTEXT pContext)
 	int status;
 	struct urb          *pUrb;
 
-
-
     pDevice->bPWBitOn = false;
 
 /*
@@ -657,7 +630,6 @@ static void s_nsBulkOutIoCompleteWrite(struct urb *urb)
 	unsigned long ulBufLen;
 	PUSB_SEND_CONTEXT pContext;
 
-
     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsBulkOutIoCompleteWrite\n");
     //
     // The context given to IoSetCompletionRoutine is an USB_CONTEXT struct
@@ -705,7 +677,6 @@ static void s_nsBulkOutIoCompleteWrite(struct urb *urb)
 
         pDevice->dev->trans_start = jiffies;
 
-
         if (status == STATUS_SUCCESS) {
             pDevice->packetsSent++;
         }
diff --git a/drivers/staging/vt6656/usbpipe.h b/drivers/staging/vt6656/usbpipe.h
index b302355..bb7a611 100644
--- a/drivers/staging/vt6656/usbpipe.h
+++ b/drivers/staging/vt6656/usbpipe.h
@@ -30,17 +30,8 @@
 #ifndef __USBPIPE_H__
 #define __USBPIPE_H__
 
-#include "ttype.h"
 #include "device.h"
 
-/*---------------------  Export Definitions -------------------------*/
-
-/*---------------------  Export Classes  ----------------------------*/
-
-/*---------------------  Export Variables  --------------------------*/
-
-/*---------------------  Export Functions  --------------------------*/
-
 int PIPEnsControlOut(struct vnt_private *, u8 byRequest, u16 wValue,
 		u16 wIndex, u16 wLength, u8 *pbyBuffer);
 int PIPEnsControlOutAsyn(struct vnt_private *, u8 byRequest,
diff --git a/drivers/staging/vt6656/wcmd.c b/drivers/staging/vt6656/wcmd.c
index 4bb652b..0013cb7 100644
--- a/drivers/staging/vt6656/wcmd.c
+++ b/drivers/staging/vt6656/wcmd.c
@@ -38,7 +38,6 @@
  *
  */
 
-#include "ttype.h"
 #include "tmacro.h"
 #include "device.h"
 #include "mac.h"
@@ -56,17 +55,8 @@
 #include "channel.h"
 #include "iowpa.h"
 
-/*---------------------  Static Definitions -------------------------*/
-
-
-
-
-/*---------------------  Static Classes  ----------------------------*/
-
-/*---------------------  Static Variables  --------------------------*/
 static int          msglevel                =MSG_LEVEL_INFO;
 //static int          msglevel                =MSG_LEVEL_DEBUG;
-/*---------------------  Static Functions  --------------------------*/
 
 static void s_vProbeChannel(struct vnt_private *);
 
@@ -74,16 +64,10 @@ static struct vnt_tx_mgmt *s_MgrMakeProbeRequest(struct vnt_private *,
 	struct vnt_manager *pMgmt, u8 *pScanBSSID, PWLAN_IE_SSID pSSID,
 	PWLAN_IE_SUPP_RATES pCurrRates, PWLAN_IE_SUPP_RATES pCurrExtSuppRates);
 
-
 static int s_bCommandComplete(struct vnt_private *);
 
-
 static int s_bClearBSSID_SCAN(struct vnt_private *);
 
-/*---------------------  Export Variables  --------------------------*/
-
-/*---------------------  Export Functions  --------------------------*/
-
 /*
  * Description:
  *      Stop AdHoc beacon during scan process
@@ -138,7 +122,6 @@ static void vAdHocBeaconStop(struct vnt_private *pDevice)
 
 } /* vAdHocBeaconStop */
 
-
 /*
  * Description:
  *      Restart AdHoc beacon after scan process complete
@@ -171,7 +154,6 @@ static void vAdHocBeaconRestart(struct vnt_private *pDevice)
 
 }
 
-
 /*+
  *
  * Routine Description:
@@ -200,7 +182,6 @@ static void s_vProbeChannel(struct vnt_private *pDevice)
 	u8 *pbyRate;
 	int ii;
 
-
     if (pDevice->byBBType == BB_TYPE_11A) {
         pbyRate = &abyCurrSuppRatesA[0];
     } else if (pDevice->byBBType == BB_TYPE_11B) {
@@ -232,9 +213,6 @@ static void s_vProbeChannel(struct vnt_private *pDevice)
 
 }
 
-
-
-
 /*+
  *
  * Routine Description:
@@ -246,7 +224,6 @@ static void s_vProbeChannel(struct vnt_private *pDevice)
  *
 -*/
 
-
 struct vnt_tx_mgmt *s_MgrMakeProbeRequest(struct vnt_private *pDevice,
 	struct vnt_manager *pMgmt, u8 *pScanBSSID, PWLAN_IE_SSID pSSID,
 	PWLAN_IE_SUPP_RATES pCurrRates, PWLAN_IE_SUPP_RATES pCurrExtSuppRates)
@@ -254,13 +231,12 @@ struct vnt_tx_mgmt *s_MgrMakeProbeRequest(struct vnt_private *pDevice,
 	struct vnt_tx_mgmt *pTxPacket = NULL;
 	WLAN_FR_PROBEREQ sFrame;
 
-
 	pTxPacket = (struct vnt_tx_mgmt *)pMgmt->pbyMgmtPacketPool;
 	memset(pTxPacket, 0, sizeof(struct vnt_tx_mgmt)
 		+ WLAN_PROBEREQ_FR_MAXLEN);
 	pTxPacket->p80211Header = (PUWLAN_80211HDR)((u8 *)pTxPacket
 		+ sizeof(struct vnt_tx_mgmt));
-    sFrame.pBuf = (PBYTE)pTxPacket->p80211Header;
+    sFrame.pBuf = (u8 *)pTxPacket->p80211Header;
     sFrame.len = WLAN_PROBEREQ_FR_MAXLEN;
     vMgrEncodeProbeRequest(&sFrame);
     sFrame.pHdr->sA3.wFrameCtl = cpu_to_le16(
@@ -316,7 +292,6 @@ void vRunCommand(struct vnt_private *pDevice)
 	u8 byMask[8] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80};
 	u8 byData;
 
-
     if (pDevice->dwDiagRefCount != 0)
         return;
     if (pDevice->bCmdRunning != true)
@@ -347,29 +322,7 @@ void vRunCommand(struct vnt_private *pDevice)
                 pMgmt->uScanChannel = pDevice->byMinChannel;
             }
             if (pMgmt->uScanChannel > pDevice->byMaxChannel) {
-                pMgmt->eScanState = WMAC_NO_SCANNING;
-
-                if (pDevice->byBBType != pDevice->byScanBBType) {
-                    pDevice->byBBType = pDevice->byScanBBType;
-                    CARDvSetBSSMode(pDevice);
-                }
-
-                if (pDevice->bUpdateBBVGA) {
-                    BBvSetShortSlotTime(pDevice);
-                    BBvSetVGAGainOffset(pDevice, pDevice->byBBVGACurrent);
-                    BBvUpdatePreEDThreshold(pDevice, false);
-                }
-                // Set channel back
-                vAdHocBeaconRestart(pDevice);
-                // Set channel back
-                CARDbSetMediaChannel(pDevice, pMgmt->uCurrChannel);
-                // Set Filter
-                if (pMgmt->bCurrBSSIDFilterOn) {
-                    MACvRegBitsOn(pDevice, MAC_REG_RCR, RCR_BSSID);
-                    pDevice->byRxMode |= RCR_BSSID;
-                }
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Scanning, set back to channel: [%d]\n", pMgmt->uCurrChannel);
-                pDevice->bStopDataPkt = false;
+		pDevice->eCommandState = WLAN_CMD_SCAN_END;
                 s_bCommandComplete(pDevice);
                 spin_unlock_irq(&pDevice->lock);
                 return;
@@ -377,6 +330,7 @@ void vRunCommand(struct vnt_private *pDevice)
             } else {
                 if (!ChannelValid(pDevice->byZoneType, pMgmt->uScanChannel)) {
                     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Invalid channel pMgmt->uScanChannel = %d \n",pMgmt->uScanChannel);
+			pMgmt->uScanChannel++;
                     s_bCommandComplete(pDevice);
                     spin_unlock_irq(&pDevice->lock);
                     return;
@@ -473,6 +427,7 @@ void vRunCommand(struct vnt_private *pDevice)
                 pDevice->byRxMode |= RCR_BSSID;
             }
             DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Scanning, set back to channel: [%d]\n", pMgmt->uCurrChannel);
+		pMgmt->uScanChannel = 0;
             pMgmt->eScanState = WMAC_NO_SCANNING;
             pDevice->bStopDataPkt = false;
 
@@ -523,7 +478,6 @@ void vRunCommand(struct vnt_private *pDevice)
             s_bCommandComplete(pDevice);
             break;
 
-
         case WLAN_CMD_SSID_START:
 
 		pDevice->byReAssocCount = 0;
@@ -845,7 +799,7 @@ void vRunCommand(struct vnt_private *pDevice)
 
        {
 	       int ntStatus = STATUS_SUCCESS;
-        BYTE            byTmp;
+        u8            byTmp;
 
         ntStatus = CONTROLnsRequestIn(pDevice,
                                     MESSAGE_TYPE_READ,
@@ -930,7 +884,6 @@ void vRunCommand(struct vnt_private *pDevice)
             s_bCommandComplete(pDevice);
             break;
 
-
         case WLAN_CMD_CHANGE_BBSENSITIVITY_START:
 
             pDevice->bStopDataPkt = true;
@@ -981,7 +934,6 @@ void vRunCommand(struct vnt_private *pDevice)
             s_bCommandComplete(pDevice);
             break;
 
-
         case WLAN_CMD_MAC_DISPOWERSAVING_START:
             ControlvReadByte (pDevice, MESSAGE_REQUEST_MACREG, MAC_REG_PSCTL, &byData);
             if ( (byData & PSCTL_PS) != 0 ) {
@@ -1014,7 +966,6 @@ void vRunCommand(struct vnt_private *pDevice)
     return;
 }
 
-
 static int s_bCommandComplete(struct vnt_private *pDevice)
 {
 	struct vnt_manager *pMgmt = &pDevice->vnt_mgmt;
@@ -1022,7 +973,6 @@ static int s_bCommandComplete(struct vnt_private *pDevice)
 	int bRadioCmd = false;
 	int bForceSCAN = true;
 
-
     pDevice->eCommandState = WLAN_CMD_IDLE;
     if (pDevice->cbFreeCmdQueue == CMD_Q_SIZE) {
         //Command Queue Empty
@@ -1147,7 +1097,7 @@ int bScheduleCommand(struct vnt_private *pDevice,
                 break;
 /*
             case WLAN_CMD_DEAUTH:
-                pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].wDeAuthenReason = *((PWORD)pbyItem0);
+                pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].wDeAuthenReason = *((u16 *)pbyItem0);
                 break;
 */
 
@@ -1203,7 +1153,6 @@ static int s_bClearBSSID_SCAN(struct vnt_private *pDevice)
     return true;
 }
 
-
 //mike add:reset command timer
 void vResetCommandTimer(struct vnt_private *pDevice)
 {
diff --git a/drivers/staging/vt6656/wcmd.h b/drivers/staging/vt6656/wcmd.h
index c40e6ba..db8b4cf 100644
--- a/drivers/staging/vt6656/wcmd.h
+++ b/drivers/staging/vt6656/wcmd.h
@@ -28,18 +28,13 @@
 
 #ifndef __WCMD_H__
 #define __WCMD_H__
-#include "ttype.h"
+
 #include "80211hdr.h"
 #include "80211mgr.h"
 
-/*---------------------  Export Definitions -------------------------*/
-
-
-
 #define AUTHENTICATE_TIMEOUT   1000 //ms
 #define ASSOCIATE_TIMEOUT      1000 //ms
 
-
 // Command code
 typedef enum tagCMD_CODE {
     WLAN_CMD_BSSID_SCAN,
@@ -73,11 +68,11 @@ typedef enum tagCMD_STATUS {
 
 typedef struct tagCMD_ITEM {
     CMD_CODE eCmd;
-    BYTE     abyCmdDesireSSID[WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1];
+    u8     abyCmdDesireSSID[WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1];
     bool     bNeedRadioOFF;
     bool     bRadioCmd;
     bool     bForceSCAN;
-    WORD     wDeAuthenReason;
+    u16     wDeAuthenReason;
 } CMD_ITEM, *PCMD_ITEM;
 
 // Command state
@@ -104,13 +99,6 @@ typedef enum tagCMD_STATE {
     WLAN_CMD_IDLE
 } CMD_STATE, *PCMD_STATE;
 
-/*---------------------  Export Classes  ----------------------------*/
-
-/*---------------------  Export Variables  --------------------------*/
-
-/*---------------------  Export Types  ------------------------------*/
-
-/*---------------------  Export Functions  --------------------------*/
 struct vnt_private;
 
 void vResetCommandTimer(struct vnt_private *);
diff --git a/drivers/staging/vt6656/wctl.c b/drivers/staging/vt6656/wctl.c
index baa48a1..47a655d 100644
--- a/drivers/staging/vt6656/wctl.c
+++ b/drivers/staging/vt6656/wctl.c
@@ -39,17 +39,7 @@
 #include "card.h"
 #include "tmacro.h"
 
-/*---------------------  Static Definitions -------------------------*/
-
-/*---------------------  Static Classes  ----------------------------*/
-
-/*---------------------  Static Variables  --------------------------*/
 // static int          msglevel                =MSG_LEVEL_INFO;
-/*---------------------  Static Functions  --------------------------*/
-
-/*---------------------  Export Variables  --------------------------*/
-
-
 
 /*
  * Description:
@@ -67,7 +57,7 @@
  *
  */
 
-bool WCTLbIsDuplicate (PSCache pCache, PS802_11Header pMACHeader)
+bool WCTLbIsDuplicate (PSCache pCache, struct ieee80211_hdr *pMACHeader)
 {
     unsigned int            uIndex;
     unsigned int            ii;
@@ -78,10 +68,10 @@ bool WCTLbIsDuplicate (PSCache pCache, PS802_11Header pMACHeader)
         uIndex = pCache->uInPtr;
         for (ii = 0; ii < DUPLICATE_RX_CACHE_LENGTH; ii++) {
             pCacheEntry = &(pCache->asCacheEntry[uIndex]);
-            if ((pCacheEntry->wFmSequence == pMACHeader->wSeqCtl) &&
+            if ((pCacheEntry->wFmSequence == pMACHeader->seq_ctrl) &&
 		(!compare_ether_addr(&(pCacheEntry->abyAddr2[0]),
-				     &(pMACHeader->abyAddr2[0]))) &&
-                (LOBYTE(pCacheEntry->wFrameCtl) == LOBYTE(pMACHeader->wFrameCtl))
+				     &(pMACHeader->addr2[0]))) &&
+                (LOBYTE(pCacheEntry->wFrameCtl) == LOBYTE(pMACHeader->frame_control))
                 ) {
                 /* Duplicate match */
                 return true;
@@ -91,9 +81,9 @@ bool WCTLbIsDuplicate (PSCache pCache, PS802_11Header pMACHeader)
     }
     /* Not found in cache - insert */
     pCacheEntry = &pCache->asCacheEntry[pCache->uInPtr];
-    pCacheEntry->wFmSequence = pMACHeader->wSeqCtl;
-    memcpy(&(pCacheEntry->abyAddr2[0]), &(pMACHeader->abyAddr2[0]), ETH_ALEN);
-    pCacheEntry->wFrameCtl = pMACHeader->wFrameCtl;
+    pCacheEntry->wFmSequence = pMACHeader->seq_ctrl;
+    memcpy(&(pCacheEntry->abyAddr2[0]), &(pMACHeader->addr2[0]), ETH_ALEN);
+    pCacheEntry->wFrameCtl = pMACHeader->frame_control;
     ADD_ONE_WITH_WRAP_AROUND(pCache->uInPtr, DUPLICATE_RX_CACHE_LENGTH);
     return false;
 }
@@ -114,14 +104,14 @@ bool WCTLbIsDuplicate (PSCache pCache, PS802_11Header pMACHeader)
  */
 
 unsigned int WCTLuSearchDFCB(struct vnt_private *pDevice,
-	PS802_11Header pMACHeader)
+			     struct ieee80211_hdr *pMACHeader)
 {
 	unsigned int ii;
 
 	for (ii = 0; ii < pDevice->cbDFCB; ii++) {
 		if ((pDevice->sRxDFCB[ii].bInUse == true) &&
 		    (!compare_ether_addr(&(pDevice->sRxDFCB[ii].abyAddr2[0]),
-					  &(pMACHeader->abyAddr2[0])))) {
+					  &(pMACHeader->addr2[0])))) {
 			return ii;
 		}
 	}
@@ -143,7 +133,7 @@ unsigned int WCTLuSearchDFCB(struct vnt_private *pDevice,
  *
  */
 unsigned int WCTLuInsertDFCB(struct vnt_private *pDevice,
-	PS802_11Header pMACHeader)
+			     struct ieee80211_hdr *pMACHeader)
 {
 	unsigned int ii;
 
@@ -154,10 +144,10 @@ unsigned int WCTLuInsertDFCB(struct vnt_private *pDevice,
             pDevice->cbFreeDFCB--;
             pDevice->sRxDFCB[ii].uLifetime = pDevice->dwMaxReceiveLifetime;
             pDevice->sRxDFCB[ii].bInUse = true;
-            pDevice->sRxDFCB[ii].wSequence = (pMACHeader->wSeqCtl >> 4);
-            pDevice->sRxDFCB[ii].wFragNum = (pMACHeader->wSeqCtl & 0x000F);
+            pDevice->sRxDFCB[ii].wSequence = (pMACHeader->seq_ctrl >> 4);
+            pDevice->sRxDFCB[ii].wFragNum = (pMACHeader->seq_ctrl & 0x000F);
 	    memcpy(&(pDevice->sRxDFCB[ii].abyAddr2[0]),
-		   &(pMACHeader->abyAddr2[0]),
+		   &(pMACHeader->addr2[0]),
 		   ETH_ALEN);
             return(ii);
         }
@@ -165,7 +155,6 @@ unsigned int WCTLuInsertDFCB(struct vnt_private *pDevice,
     return(pDevice->cbDFCB);
 }
 
-
 /*
  * Description:
  *      Handle received fragment packet
@@ -182,12 +171,10 @@ unsigned int WCTLuInsertDFCB(struct vnt_private *pDevice,
  * Return Value: true if it is valid fragment packet and we have resource to defragment; otherwise false
  *
  */
-bool WCTLbHandleFragment(struct vnt_private *pDevice, PS802_11Header pMACHeader,
-	unsigned int cbFrameLength, bool bWEP, bool bExtIV)
+bool WCTLbHandleFragment(struct vnt_private *pDevice, struct ieee80211_hdr *pMACHeader,	unsigned int cbFrameLength, bool bWEP, bool bExtIV)
 {
 	unsigned int uHeaderSize;
 
-
     if (bWEP == true) {
         uHeaderSize = 28;
         if (bExtIV)
@@ -203,8 +190,8 @@ bool WCTLbHandleFragment(struct vnt_private *pDevice, PS802_11Header pMACHeader,
         if (pDevice->uCurrentDFCBIdx < pDevice->cbDFCB) {
             // duplicate, we must flush previous DCB
             pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].uLifetime = pDevice->dwMaxReceiveLifetime;
-            pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wSequence = (pMACHeader->wSeqCtl >> 4);
-            pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wFragNum = (pMACHeader->wSeqCtl & 0x000F);
+            pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wSequence = (pMACHeader->seq_ctrl >> 4);
+            pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wFragNum = (pMACHeader->seq_ctrl & 0x000F);
         }
         else {
             pDevice->uCurrentDFCBIdx = WCTLuInsertDFCB(pDevice, pMACHeader);
@@ -213,8 +200,8 @@ bool WCTLbHandleFragment(struct vnt_private *pDevice, PS802_11Header pMACHeader,
             }
         }
         // reserve 8 byte to match MAC RX Buffer
-        pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer = (PBYTE) (pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].skb->data + 8);
-//        pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer = (PBYTE) (pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].skb->data + 4);
+        pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer = (u8 *) (pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].skb->data + 8);
+//        pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer = (u8 *) (pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].skb->data + 4);
         memcpy(pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer, pMACHeader, cbFrameLength);
         pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].cbFrameLength = cbFrameLength;
         pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer += cbFrameLength;
@@ -225,11 +212,11 @@ bool WCTLbHandleFragment(struct vnt_private *pDevice, PS802_11Header pMACHeader,
     else {
         pDevice->uCurrentDFCBIdx = WCTLuSearchDFCB(pDevice, pMACHeader);
         if (pDevice->uCurrentDFCBIdx != pDevice->cbDFCB) {
-            if ((pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wSequence == (pMACHeader->wSeqCtl >> 4)) &&
-                (pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wFragNum == (pMACHeader->wSeqCtl & 0x000F)) &&
+            if ((pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wSequence == (pMACHeader->seq_ctrl >> 4)) &&
+                (pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wFragNum == (pMACHeader->seq_ctrl & 0x000F)) &&
                 ((pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].cbFrameLength + cbFrameLength - uHeaderSize) < 2346)) {
 
-                memcpy(pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer, ((PBYTE) (pMACHeader) + uHeaderSize), (cbFrameLength - uHeaderSize));
+                memcpy(pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer, ((u8 *) (pMACHeader) + uHeaderSize), (cbFrameLength - uHeaderSize));
                 pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].cbFrameLength += (cbFrameLength - uHeaderSize);
                 pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer += (cbFrameLength - uHeaderSize);
                 pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wFragNum++;
@@ -256,4 +243,3 @@ bool WCTLbHandleFragment(struct vnt_private *pDevice, PS802_11Header pMACHeader,
     }
 }
 
-
diff --git a/drivers/staging/vt6656/wctl.h b/drivers/staging/vt6656/wctl.h
index 1b21e32e..14cb411 100644
--- a/drivers/staging/vt6656/wctl.h
+++ b/drivers/staging/vt6656/wctl.h
@@ -29,59 +29,55 @@
 #ifndef __WCTL_H__
 #define __WCTL_H__
 
-#include "ttype.h"
 #include "tether.h"
 #include "device.h"
 
-/*---------------------  Export Definitions -------------------------*/
-
 #define IS_TYPE_DATA(pMACHeader)                                                        \
-    ((((PS802_11Header) pMACHeader)->wFrameCtl & TYPE_802_11_MASK) == TYPE_802_11_DATA)
+    ((((struct ieee80211_hdr *) pMACHeader)->frame_control & TYPE_802_11_MASK) == TYPE_802_11_DATA)
 
 #define IS_TYPE_MGMT(pMACHeader)                                                        \
-    ((((PS802_11Header) pMACHeader)->wFrameCtl & TYPE_802_11_MASK) == TYPE_802_11_MGMT)
+    ((((struct ieee80211_hdr *) pMACHeader)->frame_control & TYPE_802_11_MASK) == TYPE_802_11_MGMT)
 
 #define IS_TYPE_CONTROL(pMACHeader)                                                     \
-    ((((PS802_11Header) pMACHeader)->wFrameCtl & TYPE_802_11_MASK) == TYPE_802_11_CTL)
+    ((((struct ieee80211_hdr *) pMACHeader)->frame_control & TYPE_802_11_MASK) == TYPE_802_11_CTL)
 
 #define IS_FC_MOREDATA(pMACHeader)                                                      \
-    ((((PS802_11Header) pMACHeader)->wFrameCtl & FC_MOREDATA) == FC_MOREDATA)
+    ((((struct ieee80211_hdr *) pMACHeader)->frame_control & FC_MOREDATA) == FC_MOREDATA)
 
 #define IS_FC_POWERMGT(pMACHeader)                                                      \
-    ((((PS802_11Header) pMACHeader)->wFrameCtl & FC_POWERMGT) == FC_POWERMGT)
+    ((((struct ieee80211_hdr *) pMACHeader)->frame_control & FC_POWERMGT) == FC_POWERMGT)
 
 #define IS_FC_RETRY(pMACHeader)                                                         \
-    ((((PS802_11Header) pMACHeader)->wFrameCtl & FC_RETRY) == FC_RETRY)
+    ((((struct ieee80211_hdr *) pMACHeader)->frame_control & FC_RETRY) == FC_RETRY)
 
 #define IS_FC_WEP(pMACHeader)                                                           \
-    ((((PS802_11Header) pMACHeader)->wFrameCtl & FC_WEP) == FC_WEP)
+    ((((struct ieee80211_hdr *) pMACHeader)->frame_control & FC_WEP) == FC_WEP)
 
 #ifdef __BIG_ENDIAN
 
 #define IS_FRAGMENT_PKT(pMACHeader)                                                     \
-    (((((PS802_11Header) pMACHeader)->wFrameCtl & FC_MOREFRAG) != 0) |                  \
-     ((((PS802_11Header) pMACHeader)->wSeqCtl & 0x0F00) != 0))
+    (((((struct ieee80211_hdr *) pMACHeader)->frame_control & FC_MOREFRAG) != 0) |                  \
+     ((((struct ieee80211_hdr *) pMACHeader)->seq_ctrl & 0x0F00) != 0))
 
 #define IS_FIRST_FRAGMENT_PKT(pMACHeader)                                               \
-    ((((PS802_11Header) pMACHeader)->wSeqCtl & 0x0F00) == 0)
+    ((((struct ieee80211_hdr *) pMACHeader)->seq_ctrl & 0x0F00) == 0)
 
 #else
 
 #define IS_FRAGMENT_PKT(pMACHeader)                                                     \
-    (((((PS802_11Header) pMACHeader)->wFrameCtl & FC_MOREFRAG) != 0) |                  \
-     ((((PS802_11Header) pMACHeader)->wSeqCtl & 0x000F) != 0))
+    (((((struct ieee80211_hdr *) pMACHeader)->frame_control & FC_MOREFRAG) != 0) |                  \
+     ((((struct ieee80211_hdr *) pMACHeader)->seq_ctrl & 0x000F) != 0))
 
 #define IS_FIRST_FRAGMENT_PKT(pMACHeader)                                               \
-    ((((PS802_11Header) pMACHeader)->wSeqCtl & 0x000F) == 0)
+    ((((struct ieee80211_hdr *) pMACHeader)->seq_ctrl & 0x000F) == 0)
 
 #endif//#ifdef __BIG_ENDIAN
 
 #define IS_LAST_FRAGMENT_PKT(pMACHeader)                                                \
-    ((((PS802_11Header) pMACHeader)->wFrameCtl & FC_MOREFRAG) == 0)
+    ((((struct ieee80211_hdr *) pMACHeader)->frame_control & FC_MOREFRAG) == 0)
 
 #define IS_CTL_PSPOLL(pMACHeader)                                                       \
-    ((((PS802_11Header) pMACHeader)->wFrameCtl & TYPE_SUBTYPE_MASK) == TYPE_CTL_PSPOLL)
-
+    ((((struct ieee80211_hdr *) pMACHeader)->frame_control & TYPE_SUBTYPE_MASK) == TYPE_CTL_PSPOLL)
 
 #define ADD_ONE_WITH_WRAP_AROUND(uVar, uModulo) {   \
     if ((uVar) >= ((uModulo) - 1))                  \
@@ -90,16 +86,9 @@
         (uVar)++;                                   \
 }
 
-/*---------------------  Export Classes  ----------------------------*/
-
-/*---------------------  Export Variables  --------------------------*/
-
-/*---------------------  Export Functions  --------------------------*/
-
-bool WCTLbIsDuplicate(PSCache pCache, PS802_11Header pMACHeader);
-bool WCTLbHandleFragment(struct vnt_private *, PS802_11Header pMACHeader,
-	unsigned int cbFrameLength, bool bWEP, bool bExtIV);
-unsigned int WCTLuSearchDFCB(struct vnt_private *, PS802_11Header pMACHeader);
-unsigned int WCTLuInsertDFCB(struct vnt_private *, PS802_11Header pMACHeader);
+bool WCTLbIsDuplicate(PSCache pCache, struct ieee80211_hdr *pMACHeader);
+bool WCTLbHandleFragment(struct vnt_private *, struct ieee80211_hdr *pMACHeader, unsigned int cbFrameLength, bool bWEP, bool bExtIV);
+unsigned int WCTLuSearchDFCB(struct vnt_private *, struct ieee80211_hdr *pMACHeader);
+unsigned int WCTLuInsertDFCB(struct vnt_private *, struct ieee80211_hdr *pMACHeader);
 
 #endif /* __WCTL_H__ */
diff --git a/drivers/staging/vt6656/wmgr.c b/drivers/staging/vt6656/wmgr.c
index 5dced0a..6d1ff5e 100644
--- a/drivers/staging/vt6656/wmgr.c
+++ b/drivers/staging/vt6656/wmgr.c
@@ -81,18 +81,9 @@
 #include "control.h"
 #include "rndis.h"
 
-/*---------------------  Static Definitions -------------------------*/
-
-
-
-/*---------------------  Static Classes  ----------------------------*/
-
-/*---------------------  Static Variables  --------------------------*/
 static int          msglevel                =MSG_LEVEL_INFO;
 //static int          msglevel                =MSG_LEVEL_DEBUG;
 
-/*---------------------  Static Functions  --------------------------*/
-
 static int ChannelExceedZoneType(struct vnt_private *, u8 byCurrChannel);
 
 /* Association/diassociation functions */
@@ -158,7 +149,6 @@ static struct vnt_tx_mgmt *s_MgrMakeBeacon(struct vnt_private *pDevice,
 	u8 *pCurrBSSID, PWLAN_IE_SUPP_RATES pCurrSuppRates,
 	PWLAN_IE_SUPP_RATES pCurrExtSuppRates);
 
-
 /* Association response */
 static struct vnt_tx_mgmt *s_MgrMakeAssocResponse(struct vnt_private *,
 	struct vnt_manager *pMgmt, u16 wCurrCapInfo, u16 wAssocStatus,
@@ -182,25 +172,19 @@ static struct vnt_tx_mgmt *s_MgrMakeProbeResponse(struct vnt_private *,
 /* received status */
 static void s_vMgrLogStatus(struct vnt_manager *pMgmt, u16 wStatus);
 
-
 static void s_vMgrSynchBSS(struct vnt_private *, u32 uBSSMode,
 	PKnownBSS pCurr, PCMD_STATUS  pStatus);
 
-
 static bool
 s_bCipherMatch (
      PKnownBSS                        pBSSNode,
      NDIS_802_11_ENCRYPTION_STATUS    EncStatus,
-     PBYTE                           pbyCCSPK,
-     PBYTE                           pbyCCSGK
+     u8 *                           pbyCCSPK,
+     u8 *                           pbyCCSGK
     );
 
 static void Encyption_Rebuild(struct vnt_private *, PKnownBSS pCurr);
 
-/*---------------------  Export Variables  --------------------------*/
-
-/*---------------------  Export Functions  --------------------------*/
-
 /*+
  *
  * Routine Description:
@@ -216,7 +200,6 @@ void vMgrObjectInit(struct vnt_private *pDevice)
 	struct vnt_manager *pMgmt = &pDevice->vnt_mgmt;
 	int ii;
 
-
     pMgmt->pbyPSPacketPool = &pMgmt->byPSPacketPool[0];
     pMgmt->pbyMgmtPacketPool = &pMgmt->byMgmtPacketPool[0];
     pMgmt->uCurrChannel = pDevice->uChannel;
@@ -274,7 +257,6 @@ void vMgrAssocBeginSta(struct vnt_private *pDevice,
 {
 	struct vnt_tx_mgmt *pTxPacket;
 
-
     pMgmt->wCurrCapInfo = 0;
     pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_ESS(1);
     if (pDevice->bEncryptionEnable) {
@@ -329,7 +311,6 @@ void vMgrAssocBeginSta(struct vnt_private *pDevice,
     return ;
 }
 
-
 /*+
  *
  * Routine Description:
@@ -359,7 +340,6 @@ void vMgrReAssocBeginSta(struct vnt_private *pDevice,
     if (pMgmt->wListenInterval == 0)
         pMgmt->wListenInterval = 1;    // at least one.
 
-
     // ERP Phy (802.11g) should support short preamble.
     if (pMgmt->eCurrentPHYMode == PHY_TYPE_11G) {
         pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SHORTPREAMBLE(1);
@@ -374,7 +354,6 @@ void vMgrReAssocBeginSta(struct vnt_private *pDevice,
     if (pMgmt->b11hEnable == true)
         pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SPECTRUMMNG(1);
 
-
     pTxPacket = s_MgrMakeReAssocRequest
                 (
                   pDevice,
@@ -398,7 +377,6 @@ void vMgrReAssocBeginSta(struct vnt_private *pDevice,
         }
     }
 
-
     return ;
 }
 
@@ -426,7 +404,7 @@ void vMgrDisassocBeginSta(struct vnt_private *pDevice,
 		+ sizeof(struct vnt_tx_mgmt));
 
     // Setup the sFrame structure
-    sFrame.pBuf = (PBYTE)pTxPacket->p80211Header;
+    sFrame.pBuf = (u8 *)pTxPacket->p80211Header;
     sFrame.len = WLAN_DISASSOC_FR_MAXLEN;
 
     // format fixed field frame structure
@@ -458,8 +436,6 @@ void vMgrDisassocBeginSta(struct vnt_private *pDevice,
     return;
 }
 
-
-
 /*+
  *
  * Routine Description:(AP function)
@@ -483,7 +459,6 @@ static void s_vMgrRxAssocRequest(struct vnt_private *pDevice,
 	u8 abyCurrSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1];
 	u8 abyCurrExtSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1];
 
-
     if (pMgmt->eCurrMode != WMAC_MODE_ESS_AP)
         return;
     //  node index not found
@@ -496,7 +471,7 @@ static void s_vMgrRxAssocRequest(struct vnt_private *pDevice,
     memset(abyCurrSuppRates, 0, WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1);
     memset(abyCurrExtSuppRates, 0, WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1);
     sFrame.len = pRxPacket->cbMPDULen;
-    sFrame.pBuf = (PBYTE)pRxPacket->p80211Header;
+    sFrame.pBuf = (u8 *)pRxPacket->p80211Header;
 
     vMgrDecodeAssocRequest(&sFrame);
 
@@ -523,7 +498,6 @@ static void s_vMgrRxAssocRequest(struct vnt_private *pDevice,
             abyCurrExtSuppRates[1] = 0;
         }
 
-
 	RATEvParseMaxRate((void *)pDevice,
                            (PWLAN_IE_SUPP_RATES)abyCurrSuppRates,
                            (PWLAN_IE_SUPP_RATES)abyCurrExtSuppRates,
@@ -543,9 +517,9 @@ static void s_vMgrRxAssocRequest(struct vnt_private *pDevice,
                 WLAN_GET_CAP_INFO_SHORTPREAMBLE(*sFrame.pwCapInfo);
         pMgmt->sNodeDBTable[uNodeIndex].bShortSlotTime =
                 WLAN_GET_CAP_INFO_SHORTSLOTTIME(*sFrame.pwCapInfo);
-        pMgmt->sNodeDBTable[uNodeIndex].wAID = (WORD)uNodeIndex;
+        pMgmt->sNodeDBTable[uNodeIndex].wAID = (u16)uNodeIndex;
         wAssocStatus = WLAN_MGMT_STATUS_SUCCESS;
-        wAssocAID = (WORD)uNodeIndex;
+        wAssocAID = (u16)uNodeIndex;
         // check if ERP support
         if(pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate > RATE_11M)
            pMgmt->sNodeDBTable[uNodeIndex].bERPExist = true;
@@ -572,7 +546,6 @@ static void s_vMgrRxAssocRequest(struct vnt_private *pDevice,
                    pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate);
     }
 
-
     // assoc response reply..
     pTxPacket = s_MgrMakeAssocResponse
                 (
@@ -604,7 +577,6 @@ static void s_vMgrRxAssocRequest(struct vnt_private *pDevice,
     return;
 }
 
-
 /*+
  *
  * Description:(AP function)
@@ -643,7 +615,7 @@ static void s_vMgrRxReAssocRequest(struct vnt_private *pDevice,
     //decode the frame
     memset(&sFrame, 0, sizeof(WLAN_FR_REASSOCREQ));
     sFrame.len = pRxPacket->cbMPDULen;
-    sFrame.pBuf = (PBYTE)pRxPacket->p80211Header;
+    sFrame.pBuf = (u8 *)pRxPacket->p80211Header;
     vMgrDecodeReassocRequest(&sFrame);
 
     if (pMgmt->sNodeDBTable[uNodeIndex].eNodeState >= NODE_AUTH) {
@@ -671,7 +643,6 @@ static void s_vMgrRxReAssocRequest(struct vnt_private *pDevice,
             abyCurrExtSuppRates[1] = 0;
         }
 
-
 	RATEvParseMaxRate((void *)pDevice,
                           (PWLAN_IE_SUPP_RATES)abyCurrSuppRates,
                           (PWLAN_IE_SUPP_RATES)abyCurrExtSuppRates,
@@ -691,9 +662,9 @@ static void s_vMgrRxReAssocRequest(struct vnt_private *pDevice,
                 WLAN_GET_CAP_INFO_SHORTPREAMBLE(*sFrame.pwCapInfo);
         pMgmt->sNodeDBTable[uNodeIndex].bShortSlotTime =
                 WLAN_GET_CAP_INFO_SHORTSLOTTIME(*sFrame.pwCapInfo);
-        pMgmt->sNodeDBTable[uNodeIndex].wAID = (WORD)uNodeIndex;
+        pMgmt->sNodeDBTable[uNodeIndex].wAID = (u16)uNodeIndex;
         wAssocStatus = WLAN_MGMT_STATUS_SUCCESS;
-        wAssocAID = (WORD)uNodeIndex;
+        wAssocAID = (u16)uNodeIndex;
 
         // if suppurt ERP
         if(pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate > RATE_11M)
@@ -722,7 +693,6 @@ static void s_vMgrRxReAssocRequest(struct vnt_private *pDevice,
 
     }
 
-
     // assoc response reply..
     pTxPacket = s_MgrMakeReAssocResponse
                 (
@@ -752,7 +722,6 @@ static void s_vMgrRxReAssocRequest(struct vnt_private *pDevice,
     return;
 }
 
-
 /*+
  *
  * Routine Description:
@@ -771,13 +740,11 @@ static void s_vMgrRxAssocResponse(struct vnt_private *pDevice,
 	PWLAN_IE_SSID   pItemSSID;
 	u8 *pbyIEs;
 
-
-
     if (pMgmt->eCurrState == WMAC_STATE_ASSOCPENDING ||
          pMgmt->eCurrState == WMAC_STATE_ASSOC) {
 
         sFrame.len = pRxPacket->cbMPDULen;
-        sFrame.pBuf = (PBYTE)pRxPacket->p80211Header;
+        sFrame.pBuf = (u8 *)pRxPacket->p80211Header;
         // decode the frame
         vMgrDecodeAssocResponse(&sFrame);
 	if ((sFrame.pwCapInfo == NULL)
@@ -820,7 +787,7 @@ static void s_vMgrRxAssocResponse(struct vnt_private *pDevice,
 
 	//if(pDevice->bWPASuppWextEnabled == true)
 	   {
-		BYTE buf[512];
+		u8 buf[512];
 		size_t len;
 		union iwreq_data  wrqu;
 		int we_event;
@@ -906,7 +873,7 @@ void vMgrAuthenBeginSta(struct vnt_private *pDevice,
 		+ WLAN_AUTHEN_FR_MAXLEN);
 	pTxPacket->p80211Header = (PUWLAN_80211HDR)((u8 *)pTxPacket
 		+ sizeof(struct vnt_tx_mgmt));
-    sFrame.pBuf = (PBYTE)pTxPacket->p80211Header;
+    sFrame.pBuf = (u8 *)pTxPacket->p80211Header;
     sFrame.len = WLAN_AUTHEN_FR_MAXLEN;
     vMgrEncodeAuthen(&sFrame);
     /* insert values */
@@ -960,7 +927,7 @@ void vMgrDeAuthenBeginSta(struct vnt_private *pDevice,
 		+ WLAN_DEAUTHEN_FR_MAXLEN);
 	pTxPacket->p80211Header = (PUWLAN_80211HDR)((u8 *)pTxPacket
 		+ sizeof(struct vnt_tx_mgmt));
-    sFrame.pBuf = (PBYTE)pTxPacket->p80211Header;
+    sFrame.pBuf = (u8 *)pTxPacket->p80211Header;
     sFrame.len = WLAN_DEAUTHEN_FR_MAXLEN;
     vMgrEncodeDeauthen(&sFrame);
     /* insert values */
@@ -984,11 +951,9 @@ void vMgrDeAuthenBeginSta(struct vnt_private *pDevice,
         *pStatus = CMD_STATUS_SUCCESS;
     }
 
-
     return ;
 }
 
-
 /*+
  *
  * Routine Description:
@@ -1012,7 +977,7 @@ static void s_vMgrRxAuthentication(struct vnt_private *pDevice,
 
     // decode the frame
     sFrame.len = pRxPacket->cbMPDULen;
-    sFrame.pBuf = (PBYTE)pRxPacket->p80211Header;
+    sFrame.pBuf = (u8 *)pRxPacket->p80211Header;
     vMgrDecodeAuthen(&sFrame);
     switch (cpu_to_le16((*(sFrame.pwAuthSequence )))){
         case 1:
@@ -1037,8 +1002,6 @@ static void s_vMgrRxAuthentication(struct vnt_private *pDevice,
     return;
 }
 
-
-
 /*+
  *
  * Routine Description:
@@ -1051,7 +1014,6 @@ static void s_vMgrRxAuthentication(struct vnt_private *pDevice,
  *
 -*/
 
-
 static void s_vMgrRxAuthenSequence_1(struct vnt_private *pDevice,
 	struct vnt_manager *pMgmt, PWLAN_FR_AUTHEN pFrame)
 {
@@ -1082,7 +1044,7 @@ static void s_vMgrRxAuthenSequence_1(struct vnt_private *pDevice,
 		+ WLAN_AUTHEN_FR_MAXLEN);
 	pTxPacket->p80211Header = (PUWLAN_80211HDR)((u8 *)pTxPacket
 		+ sizeof(struct vnt_tx_mgmt));
-    sFrame.pBuf = (PBYTE)pTxPacket->p80211Header;
+    sFrame.pBuf = (u8 *)pTxPacket->p80211Header;
     sFrame.len = WLAN_AUTHEN_FR_MAXLEN;
     // format buffer structure
     vMgrEncodeAuthen(&sFrame);
@@ -1142,8 +1104,6 @@ static void s_vMgrRxAuthenSequence_1(struct vnt_private *pDevice,
     return;
 }
 
-
-
 /*+
  *
  * Routine Description:
@@ -1162,7 +1122,6 @@ static void s_vMgrRxAuthenSequence_2(struct vnt_private *pDevice,
 	WLAN_FR_AUTHEN sFrame;
 	struct vnt_tx_mgmt *pTxPacket = NULL;
 
-
     switch (cpu_to_le16((*(pFrame->pwAuthAlgorithm))))
     {
         case WLAN_AUTH_ALG_OPENSYSTEM:
@@ -1193,7 +1152,7 @@ static void s_vMgrRxAuthenSequence_2(struct vnt_private *pDevice,
 			pTxPacket->p80211Header
 				= (PUWLAN_80211HDR)((u8 *)pTxPacket
 					+ sizeof(struct vnt_tx_mgmt));
-                sFrame.pBuf = (PBYTE)pTxPacket->p80211Header;
+                sFrame.pBuf = (u8 *)pTxPacket->p80211Header;
                 sFrame.len = WLAN_AUTHEN_FR_MAXLEN;
                 // format buffer structure
                 vMgrEncodeAuthen(&sFrame);
@@ -1241,8 +1200,6 @@ static void s_vMgrRxAuthenSequence_2(struct vnt_private *pDevice,
     return;
 }
 
-
-
 /*+
  *
  * Routine Description:
@@ -1297,7 +1254,7 @@ reply:
 		+ WLAN_AUTHEN_FR_MAXLEN);
 	pTxPacket->p80211Header = (PUWLAN_80211HDR)((u8 *)pTxPacket
 		+ sizeof(struct vnt_tx_mgmt));
-    sFrame.pBuf = (PBYTE)pTxPacket->p80211Header;
+    sFrame.pBuf = (u8 *)pTxPacket->p80211Header;
     sFrame.len = WLAN_AUTHEN_FR_MAXLEN;
     // format buffer structure
     vMgrEncodeAuthen(&sFrame);
@@ -1329,8 +1286,6 @@ reply:
 
 }
 
-
-
 /*+
  *
  * Routine Description:
@@ -1385,7 +1340,7 @@ static void s_vMgrRxDisassociation(struct vnt_private *pDevice,
         // if is acting an AP..
         // a STA is leaving this BSS..
         sFrame.len = pRxPacket->cbMPDULen;
-        sFrame.pBuf = (PBYTE)pRxPacket->p80211Header;
+        sFrame.pBuf = (u8 *)pRxPacket->p80211Header;
         if (BSSbIsSTAInNodeDB(pDevice, pRxPacket->p80211Header->sA3.abyAddr2, &uNodeIndex)) {
             BSSvRemoveOneNode(pDevice, uNodeIndex);
         }
@@ -1395,7 +1350,7 @@ static void s_vMgrRxDisassociation(struct vnt_private *pDevice,
     }
     else if (pMgmt->eCurrMode == WMAC_MODE_ESS_STA ){
         sFrame.len = pRxPacket->cbMPDULen;
-        sFrame.pBuf = (PBYTE)pRxPacket->p80211Header;
+        sFrame.pBuf = (u8 *)pRxPacket->p80211Header;
         vMgrDecodeDisassociation(&sFrame);
         DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "AP disassociated me, reason=%d.\n", cpu_to_le16(*(sFrame.pwReason)));
 
@@ -1430,7 +1385,6 @@ static void s_vMgrRxDisassociation(struct vnt_private *pDevice,
     return;
 }
 
-
 /*+
  *
  * Routine Description:
@@ -1448,13 +1402,12 @@ static void s_vMgrRxDeauthentication(struct vnt_private *pDevice,
 	WLAN_FR_DEAUTHEN sFrame;
 	u32 uNodeIndex = 0;
 
-
     if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP ){
         //Todo:
         // if is acting an AP..
         // a STA is leaving this BSS..
         sFrame.len = pRxPacket->cbMPDULen;
-        sFrame.pBuf = (PBYTE)pRxPacket->p80211Header;
+        sFrame.pBuf = (u8 *)pRxPacket->p80211Header;
         if (BSSbIsSTAInNodeDB(pDevice, pRxPacket->p80211Header->sA3.abyAddr2, &uNodeIndex)) {
             BSSvRemoveOneNode(pDevice, uNodeIndex);
         }
@@ -1465,7 +1418,7 @@ static void s_vMgrRxDeauthentication(struct vnt_private *pDevice,
     else {
         if (pMgmt->eCurrMode == WMAC_MODE_ESS_STA ) {
             sFrame.len = pRxPacket->cbMPDULen;
-            sFrame.pBuf = (PBYTE)pRxPacket->p80211Header;
+            sFrame.pBuf = (u8 *)pRxPacket->p80211Header;
             vMgrDecodeDeauthen(&sFrame);
 	   pDevice->fWPA_Authened = false;
             DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO  "AP deauthed me, reason=%d.\n", cpu_to_le16((*(sFrame.pwReason))));
@@ -1569,14 +1522,12 @@ static void s_vMgrRxBeacon(struct vnt_private *pDevice,
 	int bChannelHit = false;
 	u8 byOldPreambleType;
 
-
-
      if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP)
         return;
 
     memset(&sFrame, 0, sizeof(WLAN_FR_BEACON));
     sFrame.len = pRxPacket->cbMPDULen;
-    sFrame.pBuf = (PBYTE)pRxPacket->p80211Header;
+    sFrame.pBuf = (u8 *)pRxPacket->p80211Header;
 
     // decode the beacon frame
     vMgrDecodeBeacon(&sFrame);
@@ -1672,7 +1623,7 @@ if(ChannelExceedZoneType(pDevice,byCurrChannel)==true)
         return;
     }
 
-    if(byCurrChannel == (BYTE)pMgmt->uCurrChannel)
+    if(byCurrChannel == (u8)pMgmt->uCurrChannel)
        bIsChannelEqual = true;
 
     if (bIsChannelEqual && (pMgmt->eCurrMode == WMAC_MODE_ESS_AP)) {
@@ -1785,7 +1736,7 @@ if(ChannelExceedZoneType(pDevice,byCurrChannel)==true)
                     pDevice->byPreambleType = 0;
                 }
                 if (pDevice->byPreambleType != byOldPreambleType)
-                    CARDvSetRSPINF(pDevice, (BYTE)pDevice->byBBType);
+                    CARDvSetRSPINF(pDevice, (u8)pDevice->byBBType);
             //
             // Basic Rate Set may change dynamically
             //
@@ -1839,7 +1790,6 @@ if(ChannelExceedZoneType(pDevice,byCurrChannel)==true)
 	if (qwTSFOffset > TRIVIAL_SYNC_DIFFERENCE)
 		bTSFLargeDiff = true;
 
-
     // if infra mode
     if (bIsAPBeacon == true) {
 
@@ -2009,8 +1959,7 @@ if(ChannelExceedZoneType(pDevice,byCurrChannel)==true)
                         pDevice->byPreambleType = 0;
                     }
                     if (pDevice->byPreambleType != byOldPreambleType)
-                        CARDvSetRSPINF(pDevice, (BYTE)pDevice->byBBType);
-
+                        CARDvSetRSPINF(pDevice, (u8)pDevice->byBBType);
 
                      // MACvRegBitsOff(pDevice->PortOffset, MAC_REG_RCR, RCR_BSSID);
                      // set highest basic rate
@@ -2061,8 +2010,6 @@ void vMgrCreateOwnIBSS(struct vnt_private *pDevice, PCMD_STATUS pStatus)
 	u8 abyOFDM_RATE[] = {0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6C};
 	u16 wSuppRate;
 
-
-
     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Create Basic Service Set .......\n");
 
     if (pMgmt->eConfigMode == WMAC_CONFIG_IBSS_STA) {
@@ -2101,7 +2048,6 @@ void vMgrCreateOwnIBSS(struct vnt_private *pDevice, PCMD_STATUS pStatus)
             pMgmt->abyCurrSuppRates[2+ii] = abyRATE[ii];
     }
 
-
     if (pMgmt->eCurrentPHYMode == PHY_TYPE_11G) {
         pMgmt->abyCurrSuppRates[1] = 8;
         pMgmt->abyCurrExtSuppRates[1] = 4;
@@ -2113,7 +2059,6 @@ void vMgrCreateOwnIBSS(struct vnt_private *pDevice, PCMD_STATUS pStatus)
             pMgmt->abyCurrExtSuppRates[2+ii] =  abyOFDM_RATE[ii+4];
     }
 
-
     // Disable Protect Mode
     pDevice->bProtectMode = 0;
     MACvDisableProtectMD(pDevice);
@@ -2156,8 +2101,6 @@ void vMgrCreateOwnIBSS(struct vnt_private *pDevice, PCMD_STATUS pStatus)
                       &wMaxBasicRate, &wMaxSuppRate, &wSuppRate,
                       &byTopCCKBasicRate, &byTopOFDMBasicRate);
 
-
-
     if (pDevice->byBBType == BB_TYPE_11A) {
         pDevice->bShortSlotTime = true;
     } else {
@@ -2221,7 +2164,6 @@ void vMgrCreateOwnIBSS(struct vnt_private *pDevice, PCMD_STATUS pStatus)
         pMgmt->abyCurrBSSID[0] &= ~IEEE_ADDR_GROUP;
         pMgmt->abyCurrBSSID[0] |= IEEE_ADDR_UNIVERSAL;
 
-
 		DBG_PRT(MSG_LEVEL_INFO, KERN_INFO"Adhoc beacon created bssid:"
 			"%pM\n", pMgmt->abyCurrBSSID);
     }
@@ -2313,7 +2255,6 @@ void vMgrJoinBSSBegin(struct vnt_private *pDevice, PCMD_STATUS pStatus)
 	u8 byTopOFDMBasicRate = RATE_1M;
 	u8 bShortSlotTime = false;
 
-
     for (ii = 0; ii < MAX_BSS_NUM; ii++) {
         if (pMgmt->sBSSList[ii].bActive == true)
             break;
@@ -2411,9 +2352,9 @@ void vMgrJoinBSSBegin(struct vnt_private *pDevice, PCMD_STATUS pStatus)
                     if (pItemExtRates->len <= ii)
                         break;
                 }
-                pItemRates->len += (BYTE)ii;
+                pItemRates->len += (u8)ii;
                 if (pItemExtRates->len - ii > 0) {
-                    pItemExtRates->len -= (BYTE)ii;
+                    pItemExtRates->len -= (u8)ii;
                     for (uu = 0; uu < pItemExtRates->len; uu ++) {
                         pItemExtRates->abyRates[uu] = pItemExtRates->abyRates[uu + ii];
                     }
@@ -2466,7 +2407,7 @@ void vMgrJoinBSSBegin(struct vnt_private *pDevice, PCMD_STATUS pStatus)
                 pDevice->byPreambleType = 0;
             }
             // Change PreambleType must set RSPINF again
-            CARDvSetRSPINF(pDevice, (BYTE)pDevice->byBBType);
+            CARDvSetRSPINF(pDevice, (u8)pDevice->byBBType);
 
             DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Join ESS\n");
 
@@ -2519,7 +2460,6 @@ void vMgrJoinBSSBegin(struct vnt_private *pDevice, PCMD_STATUS pStatus)
             pMgmt->eCurrState = WMAC_STATE_IDLE;
         };
 
-
      }
      else {
         // ad-hoc mode BSS
@@ -2559,7 +2499,6 @@ void vMgrJoinBSSBegin(struct vnt_private *pDevice, PCMD_STATUS pStatus)
             // TODO: check if CapInfo privacy on, but we don't..
             pMgmt->uCurrChannel = pCurr->uChannel;
 
-
             // Parse Support Rate IE
             pMgmt->abyCurrSuppRates[0] = WLAN_EID_SUPP_RATES;
             pMgmt->abyCurrSuppRates[1] = RATEuSetIE((PWLAN_IE_SUPP_RATES)pCurr->abySuppRates,
@@ -2597,7 +2536,7 @@ void vMgrJoinBSSBegin(struct vnt_private *pDevice, PCMD_STATUS pStatus)
                 pDevice->byPreambleType = 0;
             }
             // Change PreambleType must set RSPINF again
-            CARDvSetRSPINF(pDevice, (BYTE)pDevice->byBBType);
+            CARDvSetRSPINF(pDevice, (u8)pDevice->byBBType);
 
             // Prepare beacon
 		bMgrPrepareBeaconToSend((void *) pDevice, pMgmt);
@@ -2609,8 +2548,6 @@ void vMgrJoinBSSBegin(struct vnt_private *pDevice, PCMD_STATUS pStatus)
     return;
 }
 
-
-
 /*+
  *
  * Routine Description:
@@ -2806,7 +2743,6 @@ static void Encyption_Rebuild(struct vnt_private *pDevice, PKnownBSS pCurr)
       return;
  }
 
-
 /*+
  *
  * Routine Description:
@@ -2828,7 +2764,6 @@ static void s_vMgrFormatTIM(struct vnt_manager *pMgmt, PWLAN_IE_TIM pTIM)
 	u16 wStartIndex = 0;
 	u16 wEndIndex = 0;
 
-
     // Find size of partial virtual bitmap
     for (ii = 0; ii < (MAX_NODE_NUM + 1); ii++) {
         byMap = pMgmt->abyPSTxMap[ii];
@@ -2843,13 +2778,12 @@ static void s_vMgrFormatTIM(struct vnt_manager *pMgmt, PWLAN_IE_TIM pTIM)
         if (byMap) {
             if (!bStartFound) {
                 bStartFound = true;
-                wStartIndex = (WORD)ii;
+                wStartIndex = (u16)ii;
             }
-            wEndIndex = (WORD)ii;
+            wEndIndex = (u16)ii;
         }
     }
 
-
     // Round start index down to nearest even number
     wStartIndex &=  ~BIT0;
 
@@ -2876,7 +2810,6 @@ static void s_vMgrFormatTIM(struct vnt_manager *pMgmt, PWLAN_IE_TIM pTIM)
     pTIM->byVirtBitMap[0]  &= ~BIT0;
 }
 
-
 /*+
  *
  * Routine Description:
@@ -2898,7 +2831,6 @@ static struct vnt_tx_mgmt *s_MgrMakeBeacon(struct vnt_private *pDevice,
 	WLAN_FR_BEACON sFrame;
 	u8 abyBroadcastAddr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 
-
 	/* prepare beacon frame */
 	pTxPacket = (struct vnt_tx_mgmt *)pMgmt->pbyMgmtPacketPool;
 	memset(pTxPacket, 0, sizeof(struct vnt_tx_mgmt)
@@ -2906,7 +2838,7 @@ static struct vnt_tx_mgmt *s_MgrMakeBeacon(struct vnt_private *pDevice,
 	pTxPacket->p80211Header = (PUWLAN_80211HDR)((u8 *)pTxPacket
 		+ sizeof(struct vnt_tx_mgmt));
     // Setup the sFrame structure.
-    sFrame.pBuf = (PBYTE)pTxPacket->p80211Header;
+    sFrame.pBuf = (u8 *)pTxPacket->p80211Header;
     sFrame.len = WLAN_BEACON_FR_MAXLEN;
     vMgrEncodeBeacon(&sFrame);
     // Setup the header
@@ -2917,7 +2849,7 @@ static struct vnt_tx_mgmt *s_MgrMakeBeacon(struct vnt_private *pDevice,
         ));
 
     if (pDevice->bEnablePSMode) {
-        sFrame.pHdr->sA3.wFrameCtl |= cpu_to_le16((WORD)WLAN_SET_FC_PWRMGT(1));
+        sFrame.pHdr->sA3.wFrameCtl |= cpu_to_le16((u16)WLAN_SET_FC_PWRMGT(1));
     }
 
     memcpy( sFrame.pHdr->sA3.abyAddr1, abyBroadcastAddr, WLAN_ADDR_LEN);
@@ -2945,7 +2877,7 @@ static struct vnt_tx_mgmt *s_MgrMakeBeacon(struct vnt_private *pDevice,
         sFrame.len += (1) + WLAN_IEHDR_LEN;
         sFrame.pDSParms->byElementID = WLAN_EID_DS_PARMS;
         sFrame.pDSParms->len = 1;
-        sFrame.pDSParms->byCurrChannel = (BYTE)uCurrChannel;
+        sFrame.pDSParms->byCurrChannel = (u8)uCurrChannel;
     }
     // TIM field
     if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) {
@@ -2988,17 +2920,16 @@ static struct vnt_tx_mgmt *s_MgrMakeBeacon(struct vnt_private *pDevice,
             // Pairwise Key Cipher Suite
             sFrame.pRSNWPA->wPKCount = 0;
             // Auth Key Management Suite
-            *((PWORD)(sFrame.pBuf + sFrame.len + sFrame.pRSNWPA->len))=0;
+            *((u16 *)(sFrame.pBuf + sFrame.len + sFrame.pRSNWPA->len))=0;
             sFrame.pRSNWPA->len +=2;
 
             // RSN Capabilites
-            *((PWORD)(sFrame.pBuf + sFrame.len + sFrame.pRSNWPA->len))=0;
+            *((u16 *)(sFrame.pBuf + sFrame.len + sFrame.pRSNWPA->len))=0;
             sFrame.pRSNWPA->len +=2;
             sFrame.len += sFrame.pRSNWPA->len + WLAN_IEHDR_LEN;
         }
     }
 
-
     if (pMgmt->eCurrentPHYMode == PHY_TYPE_11G) {
         sFrame.pERP = (PWLAN_IE_ERP)(sFrame.pBuf + sFrame.len);
         sFrame.len += 1 + WLAN_IEHDR_LEN;
@@ -3038,10 +2969,6 @@ static struct vnt_tx_mgmt *s_MgrMakeBeacon(struct vnt_private *pDevice,
     return pTxPacket;
 }
 
-
-
-
-
 /*+
  *
  * Routine Description:
@@ -3053,9 +2980,6 @@ static struct vnt_tx_mgmt *s_MgrMakeBeacon(struct vnt_private *pDevice,
  *
 -*/
 
-
-
-
 struct vnt_tx_mgmt *s_MgrMakeProbeResponse(struct vnt_private *pDevice,
 	struct vnt_manager *pMgmt, u16 wCurrCapInfo, u16 wCurrBeaconPeriod,
 	u32 uCurrChannel, u16 wCurrATIMWinodw, u8 *pDstAddr,
@@ -3066,14 +2990,13 @@ struct vnt_tx_mgmt *s_MgrMakeProbeResponse(struct vnt_private *pDevice,
 	struct vnt_tx_mgmt *pTxPacket = NULL;
 	WLAN_FR_PROBERESP sFrame;
 
-
 	pTxPacket = (struct vnt_tx_mgmt *)pMgmt->pbyMgmtPacketPool;
 	memset(pTxPacket, 0, sizeof(struct vnt_tx_mgmt)
 		+ WLAN_PROBERESP_FR_MAXLEN);
 	pTxPacket->p80211Header = (PUWLAN_80211HDR)((u8 *)pTxPacket
 		+ sizeof(struct vnt_tx_mgmt));
     // Setup the sFrame structure.
-    sFrame.pBuf = (PBYTE)pTxPacket->p80211Header;
+    sFrame.pBuf = (u8 *)pTxPacket->p80211Header;
     sFrame.len = WLAN_PROBERESP_FR_MAXLEN;
     vMgrEncodeProbeResponse(&sFrame);
     // Setup the header
@@ -3089,7 +3012,7 @@ struct vnt_tx_mgmt *s_MgrMakeProbeResponse(struct vnt_private *pDevice,
     *sFrame.pwCapInfo = cpu_to_le16(wCurrCapInfo);
 
     if (byPHYType == BB_TYPE_11B) {
-        *sFrame.pwCapInfo &= cpu_to_le16((WORD)~(WLAN_SET_CAP_INFO_SHORTSLOTTIME(1)));
+        *sFrame.pwCapInfo &= cpu_to_le16((u16)~(WLAN_SET_CAP_INFO_SHORTSLOTTIME(1)));
     }
 
     // Copy SSID
@@ -3114,7 +3037,7 @@ struct vnt_tx_mgmt *s_MgrMakeProbeResponse(struct vnt_private *pDevice,
         sFrame.len += (1) + WLAN_IEHDR_LEN;
         sFrame.pDSParms->byElementID = WLAN_EID_DS_PARMS;
         sFrame.pDSParms->len = 1;
-        sFrame.pDSParms->byCurrChannel = (BYTE)uCurrChannel;
+        sFrame.pDSParms->byCurrChannel = (u8)uCurrChannel;
     }
 
     if (pMgmt->eCurrMode != WMAC_MODE_ESS_AP) {
@@ -3166,8 +3089,6 @@ struct vnt_tx_mgmt *s_MgrMakeProbeResponse(struct vnt_private *pDevice,
     return pTxPacket;
 }
 
-
-
 /*+
  *
  * Routine Description:
@@ -3179,7 +3100,6 @@ struct vnt_tx_mgmt *s_MgrMakeProbeResponse(struct vnt_private *pDevice,
  *
 -*/
 
-
 struct vnt_tx_mgmt *s_MgrMakeAssocRequest(struct vnt_private *pDevice,
 	struct vnt_manager *pMgmt, u8 *pDAddr, u16 wCurrCapInfo,
 	u16 wListenInterval,
@@ -3192,14 +3112,13 @@ struct vnt_tx_mgmt *s_MgrMakeAssocRequest(struct vnt_private *pDevice,
 	u8 *pbyIEs;
 	u8 *pbyRSN;
 
-
 	pTxPacket = (struct vnt_tx_mgmt *)pMgmt->pbyMgmtPacketPool;
 	memset(pTxPacket, 0, sizeof(struct vnt_tx_mgmt)
 		+ WLAN_ASSOCREQ_FR_MAXLEN);
 	pTxPacket->p80211Header = (PUWLAN_80211HDR)((u8 *)pTxPacket
 		+ sizeof(struct vnt_tx_mgmt));
     // Setup the sFrame structure.
-    sFrame.pBuf = (PBYTE)pTxPacket->p80211Header;
+    sFrame.pBuf = (u8 *)pTxPacket->p80211Header;
     sFrame.len = WLAN_ASSOCREQ_FR_MAXLEN;
     // format fixed field frame structure
     vMgrEncodeAssocRequest(&sFrame);
@@ -3247,7 +3166,6 @@ struct vnt_tx_mgmt *s_MgrMakeAssocRequest(struct vnt_private *pDevice,
     memcpy(pbyIEs, pCurrRates, pCurrRates->len + WLAN_IEHDR_LEN);
     pbyIEs += pCurrRates->len + WLAN_IEHDR_LEN;
 
-
     if (((pMgmt->eAuthenMode == WMAC_AUTH_WPA) ||
          (pMgmt->eAuthenMode == WMAC_AUTH_WPAPSK) ||
          (pMgmt->eAuthenMode == WMAC_AUTH_WPANONE)) &&
@@ -3287,7 +3205,7 @@ struct vnt_tx_mgmt *s_MgrMakeAssocRequest(struct vnt_private *pDevice,
             sFrame.pRSNWPA->PKSList[0].abyOUI[3] = WPA_NONE;
         }
         // Auth Key Management Suite
-        pbyRSN = (PBYTE)(sFrame.pBuf + sFrame.len + 2 + sFrame.pRSNWPA->len);
+        pbyRSN = (u8 *)(sFrame.pBuf + sFrame.len + 2 + sFrame.pRSNWPA->len);
         *pbyRSN++=0x01;
         *pbyRSN++=0x00;
         *pbyRSN++=0x00;
@@ -3322,7 +3240,7 @@ struct vnt_tx_mgmt *s_MgrMakeAssocRequest(struct vnt_private *pDevice,
                 (pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK)) &&
                (pMgmt->pCurrBSS != NULL)) {
 	unsigned int ii;
-        PWORD               pwPMKID;
+        u16 *               pwPMKID;
 
         // WPA IE
         sFrame.pRSN = (PWLAN_IE_RSN)(sFrame.pBuf + sFrame.len);
@@ -3387,7 +3305,7 @@ struct vnt_tx_mgmt *s_MgrMakeAssocRequest(struct vnt_private *pDevice,
         if ((pDevice->gsPMKID.BSSIDInfoCount > 0) && (pDevice->bRoaming == true) && (pMgmt->eAuthenMode == WMAC_AUTH_WPA2)) {
             // RSN PMKID
             pbyRSN = &sFrame.pRSN->abyRSN[18];
-            pwPMKID = (PWORD)pbyRSN; // Point to PMKID count
+            pwPMKID = (u16 *)pbyRSN; // Point to PMKID count
             *pwPMKID = 0;            // Initialize PMKID count
             pbyRSN += 2;             // Point to PMKID list
 	for (ii = 0; ii < pDevice->gsPMKID.BSSIDInfoCount; ii++) {
@@ -3413,20 +3331,12 @@ struct vnt_tx_mgmt *s_MgrMakeAssocRequest(struct vnt_private *pDevice,
         pbyIEs += sFrame.pRSN->len + WLAN_IEHDR_LEN;
     }
 
-
     // Adjust the length fields
     pTxPacket->cbMPDULen = sFrame.len;
     pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN;
     return pTxPacket;
 }
 
-
-
-
-
-
-
-
 /*+
  *
  * Routine Description:
@@ -3438,7 +3348,6 @@ struct vnt_tx_mgmt *s_MgrMakeAssocRequest(struct vnt_private *pDevice,
  *
 -*/
 
-
 struct vnt_tx_mgmt *s_MgrMakeReAssocRequest(struct vnt_private *pDevice,
 	struct vnt_manager *pMgmt, u8 *pDAddr, u16 wCurrCapInfo,
 	u16 wListenInterval, PWLAN_IE_SSID pCurrSSID,
@@ -3450,14 +3359,13 @@ struct vnt_tx_mgmt *s_MgrMakeReAssocRequest(struct vnt_private *pDevice,
 	u8 *pbyIEs;
 	u8 *pbyRSN;
 
-
 	pTxPacket = (struct vnt_tx_mgmt *)pMgmt->pbyMgmtPacketPool;
 	memset(pTxPacket, 0, sizeof(struct vnt_tx_mgmt)
 		+ WLAN_REASSOCREQ_FR_MAXLEN);
 	pTxPacket->p80211Header = (PUWLAN_80211HDR)((u8 *)pTxPacket
 		+ sizeof(struct vnt_tx_mgmt));
     /* Setup the sFrame structure. */
-    sFrame.pBuf = (PBYTE)pTxPacket->p80211Header;
+    sFrame.pBuf = (u8 *)pTxPacket->p80211Header;
     sFrame.len = WLAN_REASSOCREQ_FR_MAXLEN;
 
     // format fixed field frame structure
@@ -3546,7 +3454,7 @@ struct vnt_tx_mgmt *s_MgrMakeReAssocRequest(struct vnt_private *pDevice,
             sFrame.pRSNWPA->PKSList[0].abyOUI[3] = WPA_NONE;
         }
         // Auth Key Management Suite
-        pbyRSN = (PBYTE)(sFrame.pBuf + sFrame.len + 2 + sFrame.pRSNWPA->len);
+        pbyRSN = (u8 *)(sFrame.pBuf + sFrame.len + 2 + sFrame.pRSNWPA->len);
         *pbyRSN++=0x01;
         *pbyRSN++=0x00;
         *pbyRSN++=0x00;
@@ -3578,7 +3486,7 @@ struct vnt_tx_mgmt *s_MgrMakeReAssocRequest(struct vnt_private *pDevice,
                 (pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK)) &&
                (pMgmt->pCurrBSS != NULL)) {
 	unsigned int ii;
-        PWORD               pwPMKID;
+        u16 *               pwPMKID;
 
         /* WPA IE */
         sFrame.pRSN = (PWLAN_IE_RSN)(sFrame.pBuf + sFrame.len);
@@ -3643,7 +3551,7 @@ struct vnt_tx_mgmt *s_MgrMakeReAssocRequest(struct vnt_private *pDevice,
         if ((pDevice->gsPMKID.BSSIDInfoCount > 0) && (pDevice->bRoaming == true) && (pMgmt->eAuthenMode == WMAC_AUTH_WPA2)) {
             // RSN PMKID
             pbyRSN = &sFrame.pRSN->abyRSN[18];
-            pwPMKID = (PWORD)pbyRSN; // Point to PMKID count
+            pwPMKID = (u16 *)pbyRSN; // Point to PMKID count
             *pwPMKID = 0;            // Initialize PMKID count
             pbyRSN += 2;             // Point to PMKID list
             for (ii = 0; ii < pDevice->gsPMKID.BSSIDInfoCount; ii++) {
@@ -3669,8 +3577,6 @@ struct vnt_tx_mgmt *s_MgrMakeReAssocRequest(struct vnt_private *pDevice,
         pbyIEs += sFrame.pRSN->len + WLAN_IEHDR_LEN;
     }
 
-
-
     /* Adjust the length fields */
     pTxPacket->cbMPDULen = sFrame.len;
     pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN;
@@ -3697,14 +3603,13 @@ struct vnt_tx_mgmt *s_MgrMakeAssocResponse(struct vnt_private *pDevice,
 	struct vnt_tx_mgmt *pTxPacket = NULL;
 	WLAN_FR_ASSOCRESP   sFrame;
 
-
 	pTxPacket = (struct vnt_tx_mgmt *)pMgmt->pbyMgmtPacketPool;
 	memset(pTxPacket, 0, sizeof(struct vnt_tx_mgmt)
 		+ WLAN_ASSOCREQ_FR_MAXLEN);
 	pTxPacket->p80211Header = (PUWLAN_80211HDR)((u8 *)pTxPacket
 		+ sizeof(struct vnt_tx_mgmt));
     // Setup the sFrame structure
-    sFrame.pBuf = (PBYTE)pTxPacket->p80211Header;
+    sFrame.pBuf = (u8 *)pTxPacket->p80211Header;
     sFrame.len = WLAN_REASSOCRESP_FR_MAXLEN;
     vMgrEncodeAssocResponse(&sFrame);
     // Setup the header
@@ -3719,7 +3624,7 @@ struct vnt_tx_mgmt *s_MgrMakeAssocResponse(struct vnt_private *pDevice,
 
     *sFrame.pwCapInfo = cpu_to_le16(wCurrCapInfo);
     *sFrame.pwStatus = cpu_to_le16(wAssocStatus);
-    *sFrame.pwAid = cpu_to_le16((WORD)(wAssocAID | BIT14 | BIT15));
+    *sFrame.pwAid = cpu_to_le16((u16)(wAssocAID | BIT14 | BIT15));
 
     // Copy the rate set
     sFrame.pSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len);
@@ -3745,7 +3650,6 @@ struct vnt_tx_mgmt *s_MgrMakeAssocResponse(struct vnt_private *pDevice,
     return pTxPacket;
 }
 
-
 /*+
  *
  * Routine Description:
@@ -3757,7 +3661,6 @@ struct vnt_tx_mgmt *s_MgrMakeAssocResponse(struct vnt_private *pDevice,
  *
 -*/
 
-
 struct vnt_tx_mgmt *s_MgrMakeReAssocResponse(struct vnt_private *pDevice,
 	struct vnt_manager *pMgmt, u16 wCurrCapInfo, u16 wAssocStatus,
 	u16 wAssocAID, u8 *pDstAddr, PWLAN_IE_SUPP_RATES pCurrSuppRates,
@@ -3766,14 +3669,13 @@ struct vnt_tx_mgmt *s_MgrMakeReAssocResponse(struct vnt_private *pDevice,
 	struct vnt_tx_mgmt *pTxPacket = NULL;
 	WLAN_FR_REASSOCRESP sFrame;
 
-
 	pTxPacket = (struct vnt_tx_mgmt *)pMgmt->pbyMgmtPacketPool;
 	memset(pTxPacket, 0, sizeof(struct vnt_tx_mgmt)
 		+ WLAN_ASSOCREQ_FR_MAXLEN);
 	pTxPacket->p80211Header = (PUWLAN_80211HDR)((u8 *)pTxPacket
 		+ sizeof(struct vnt_tx_mgmt));
     // Setup the sFrame structure
-    sFrame.pBuf = (PBYTE)pTxPacket->p80211Header;
+    sFrame.pBuf = (u8 *)pTxPacket->p80211Header;
     sFrame.len = WLAN_REASSOCRESP_FR_MAXLEN;
     vMgrEncodeReassocResponse(&sFrame);
     // Setup the header
@@ -3788,7 +3690,7 @@ struct vnt_tx_mgmt *s_MgrMakeReAssocResponse(struct vnt_private *pDevice,
 
     *sFrame.pwCapInfo = cpu_to_le16(wCurrCapInfo);
     *sFrame.pwStatus = cpu_to_le16(wAssocStatus);
-    *sFrame.pwAid = cpu_to_le16((WORD)(wAssocAID | BIT14 | BIT15));
+    *sFrame.pwAid = cpu_to_le16((u16)(wAssocAID | BIT14 | BIT15));
 
     // Copy the rate set
     sFrame.pSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len);
@@ -3814,7 +3716,6 @@ struct vnt_tx_mgmt *s_MgrMakeReAssocResponse(struct vnt_private *pDevice,
     return pTxPacket;
 }
 
-
 /*+
  *
  * Routine Description:
@@ -3835,11 +3736,10 @@ static void s_vMgrRxProbeResponse(struct vnt_private *pDevice,
 	ERPObject sERP;
 	int bChannelHit = true;
 
-
     memset(&sFrame, 0, sizeof(WLAN_FR_PROBERESP));
     // decode the frame
     sFrame.len = pRxPacket->cbMPDULen;
-    sFrame.pBuf = (PBYTE)pRxPacket->p80211Header;
+    sFrame.pBuf = (u8 *)pRxPacket->p80211Header;
     vMgrDecodeProbeResponse(&sFrame);
 
     if ((sFrame.pqwTimestamp == NULL)
@@ -3857,7 +3757,6 @@ static void s_vMgrRxProbeResponse(struct vnt_private *pDevice,
     if(sFrame.pSSID->len == 0)
        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Rx Probe resp: SSID len = 0 \n");
 
-
     //{{ RobertYu:20050201, 11a  byCurrChannel != sFrame.pDSParms->byCurrChannel mapping
     if( byCurrChannel > CB_MAX_CHANNEL_24G )
     {
@@ -3892,7 +3791,6 @@ if(ChannelExceedZoneType(pDevice,byCurrChannel)==true)
         sERP.byERP = 0;
     }
 
-
     // update or insert the bss
     pBSSList = BSSpAddrIsInBSSList((void *) pDevice,
 				   sFrame.pHdr->sA3.abyAddr3,
@@ -3952,7 +3850,6 @@ if(ChannelExceedZoneType(pDevice,byCurrChannel)==true)
  *
 -*/
 
-
 static void s_vMgrRxProbeRequest(struct vnt_private *pDevice,
 	struct vnt_manager *pMgmt, struct vnt_rx_mgmt *pRxPacket)
 {
@@ -3969,7 +3866,7 @@ static void s_vMgrRxProbeRequest(struct vnt_private *pDevice,
         memset(&sFrame, 0, sizeof(WLAN_FR_PROBEREQ));
         // decode the frame
         sFrame.len = pRxPacket->cbMPDULen;
-        sFrame.pBuf = (PBYTE)pRxPacket->p80211Header;
+        sFrame.pBuf = (u8 *)pRxPacket->p80211Header;
         vMgrDecodeProbeRequest(&sFrame);
 /*
 	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Probe request rx:MAC addr:%pM\n",
@@ -4000,7 +3897,7 @@ static void s_vMgrRxProbeRequest(struct vnt_private *pDevice,
                       0,
                       sFrame.pHdr->sA3.abyAddr2,
                       (PWLAN_IE_SSID)pMgmt->abyCurrSSID,
-                      (PBYTE)pMgmt->abyCurrBSSID,
+                      (u8 *)pMgmt->abyCurrBSSID,
                       (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates,
                       (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates,
                        byPHYType
@@ -4042,7 +3939,6 @@ void vMgrRxManagePacket(struct vnt_private *pDevice, struct vnt_manager *pMgmt,
 	NODE_STATE eNodeState = 0;
 	CMD_STATUS Status;
 
-
     if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) {
         if (BSSbIsSTAInNodeDB(pDevice, pRxPacket->p80211Header->sA3.abyAddr2, &uNodeIndex))
             eNodeState = pMgmt->sNodeDBTable[uNodeIndex].eNodeState;
@@ -4199,7 +4095,7 @@ int bMgrPrepareBeaconToSend(struct vnt_private *pDevice,
                   pMgmt->uCurrChannel,
                   pMgmt->wCurrATIMWindow, //0,
                   (PWLAN_IE_SSID)pMgmt->abyCurrSSID,
-                  (PBYTE)pMgmt->abyCurrBSSID,
+                  (u8 *)pMgmt->abyCurrBSSID,
                   (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates,
                   (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates
                 );
@@ -4214,9 +4110,6 @@ int bMgrPrepareBeaconToSend(struct vnt_private *pDevice,
     return true;
 }
 
-
-
-
 /*+
  *
  * Routine Description:
@@ -4308,8 +4201,6 @@ int bAdd_PMKID_Candidate(struct vnt_private *pDevice, u8 *pbyBSSID,
     if (pDevice->gsPMKIDCandidate.NumCandidates >= MAX_PMKIDLIST)
         return false;
 
-
-
     // Update Old Candidate
     for (ii = 0; ii < pDevice->gsPMKIDCandidate.NumCandidates; ii++) {
 	pCandidateList = &pDevice->gsPMKIDCandidate.CandidateList[ii];
@@ -4368,12 +4259,12 @@ static bool
 s_bCipherMatch (
      PKnownBSS                        pBSSNode,
      NDIS_802_11_ENCRYPTION_STATUS    EncStatus,
-     PBYTE                           pbyCCSPK,
-     PBYTE                           pbyCCSGK
+     u8 *                           pbyCCSPK,
+     u8 *                           pbyCCSGK
     )
 {
-    BYTE byMulticastCipher = KEY_CTL_INVALID;
-    BYTE byCipherMask = 0x00;
+    u8 byMulticastCipher = KEY_CTL_INVALID;
+    u8 byCipherMask = 0x00;
     int i;
 
     if (pBSSNode == NULL)
@@ -4515,4 +4406,3 @@ s_bCipherMatch (
     return true;
 }
 
-
diff --git a/drivers/staging/vt6656/wmgr.h b/drivers/staging/vt6656/wmgr.h
index 83aed45..5424c7f 100644
--- a/drivers/staging/vt6656/wmgr.h
+++ b/drivers/staging/vt6656/wmgr.h
@@ -34,7 +34,6 @@
 #ifndef __WMGR_H__
 #define __WMGR_H__
 
-#include "ttype.h"
 #include "80211mgr.h"
 #include "80211hdr.h"
 #include "wcmd.h"
@@ -42,10 +41,6 @@
 #include "wpa2.h"
 #include "card.h"
 
-/*---------------------  Export Definitions -------------------------*/
-
-
-
 // Scan time
 #define PROBE_DELAY                  100  // (us)
 #define SWITCH_CHANNEL_DELAY         200 // (us)
@@ -57,7 +52,6 @@
 #define WCMD_ACTIVE_SCAN_TIME   20 //(ms)
 #define WCMD_PASSIVE_SCAN_TIME  100 //(ms)
 
-
 #define DEFAULT_MSDU_LIFETIME           512  // ms
 #define DEFAULT_MSDU_LIFETIME_RES_64us  8000 // 64us
 
@@ -66,7 +60,6 @@
 
 #define MAKE_BEACON_RESERVED            10  //(us)
 
-
 #define TIM_MULTICAST_MASK           0x01
 #define TIM_BITMAPOFFSET_MASK        0xFE
 #define DEFAULT_DTIM_PERIOD             1
@@ -75,18 +68,11 @@
 
 #define DEFAULT_IBSS_CHANNEL            6  //2.4G
 
-
-/*---------------------  Export Classes  ----------------------------*/
-
-/*---------------------  Export Variables  --------------------------*/
-
-/*---------------------  Export Types  ------------------------------*/
 //mike define: make timer  to expire after desired times
 #define timer_expire(timer, next_tick) mod_timer(&timer, RUN_AT(next_tick))
 
 typedef void (*TimerFunction)(unsigned long);
 
-
 //+++ NDIS related
 
 typedef u8 NDIS_802_11_MAC_ADDRESS[ETH_ALEN];
@@ -117,8 +103,6 @@ typedef struct _NDIS_802_11_ASSOCIATION_INFORMATION
 	u32 OffsetResponseIEs;
 } NDIS_802_11_ASSOCIATION_INFORMATION, *PNDIS_802_11_ASSOCIATION_INFORMATION;
 
-
-
 typedef struct tagSAssocInfo {
 	NDIS_802_11_ASSOCIATION_INFORMATION AssocInfo;
 	u8 abyIEs[WLAN_BEACON_FR_MAXLEN+WLAN_BEACON_FR_MAXLEN];
@@ -127,9 +111,6 @@ typedef struct tagSAssocInfo {
 	u8 abyReqIEs[WLAN_BEACON_FR_MAXLEN];
 } SAssocInfo, *PSAssocInfo;
 
-
-
-
 typedef enum tagWMAC_AUTHENTICATION_MODE {
 
     WMAC_AUTH_OPEN,
@@ -143,8 +124,6 @@ typedef enum tagWMAC_AUTHENTICATION_MODE {
     WMAC_AUTH_MAX       // Not a real mode, defined as upper bound
 } WMAC_AUTHENTICATION_MODE, *PWMAC_AUTHENTICATION_MODE;
 
-
-
 // Pre-configured Mode (from XP)
 
 typedef enum tagWMAC_CONFIG_MODE {
@@ -155,7 +134,6 @@ typedef enum tagWMAC_CONFIG_MODE {
 
 } WMAC_CONFIG_MODE, *PWMAC_CONFIG_MODE;
 
-
 typedef enum tagWMAC_SCAN_TYPE {
 
     WMAC_SCAN_ACTIVE,
@@ -164,7 +142,6 @@ typedef enum tagWMAC_SCAN_TYPE {
 
 } WMAC_SCAN_TYPE, *PWMAC_SCAN_TYPE;
 
-
 typedef enum tagWMAC_SCAN_STATE {
 
     WMAC_NO_SCANNING,
@@ -173,8 +150,6 @@ typedef enum tagWMAC_SCAN_STATE {
 
 } WMAC_SCAN_STATE, *PWMAC_SCAN_STATE;
 
-
-
 // Notes:
 // Basic Service Set state explained as following:
 // WMAC_STATE_IDLE          : no BSS is selected (Adhoc or Infra)
@@ -207,7 +182,6 @@ typedef enum tagWMAC_CURRENT_MODE {
 
 } WMAC_CURRENT_MODE, *PWMAC_CURRENT_MODE;
 
-
 typedef enum tagWMAC_POWER_MODE {
 
     WMAC_POWER_CAM,
@@ -216,8 +190,6 @@ typedef enum tagWMAC_POWER_MODE {
 
 } WMAC_POWER_MODE, *PWMAC_POWER_MODE;
 
-
-
 /* Tx Management Packet descriptor */
 struct vnt_tx_mgmt {
 	PUWLAN_80211HDR p80211Header;
@@ -225,7 +197,6 @@ struct vnt_tx_mgmt {
 	u32 cbPayloadLen;
 };
 
-
 /* Rx Management Packet descriptor */
 struct vnt_rx_mgmt {
 	PUWLAN_80211HDR p80211Header;
@@ -238,7 +209,6 @@ struct vnt_rx_mgmt {
 	u8 byRxChannel;
 };
 
-
 struct vnt_manager {
 	void *pAdapter;
 
@@ -340,7 +310,6 @@ struct vnt_manager {
 	u8 byMgmtPacketPool[sizeof(struct vnt_tx_mgmt)
 		+ WLAN_A3FR_MAXLEN];
 
-
 	/* One second callback timer */
 	struct timer_list sTimerSecondCallback;
 
@@ -384,10 +353,6 @@ struct vnt_manager {
 
 };
 
-/*---------------------  Export Macros ------------------------------*/
-
-/*---------------------  Export Functions  --------------------------*/
-
 void vMgrObjectInit(struct vnt_private *pDevice);
 
 void vMgrAssocBeginSta(struct vnt_private *pDevice,
diff --git a/drivers/staging/vt6656/wpa.c b/drivers/staging/vt6656/wpa.c
index f037be3..01db4e7 100644
--- a/drivers/staging/vt6656/wpa.c
+++ b/drivers/staging/vt6656/wpa.c
@@ -32,7 +32,6 @@
  *
  */
 
-#include "ttype.h"
 #include "tmacro.h"
 #include "tether.h"
 #include "device.h"
@@ -42,16 +41,14 @@
 #include "wpa.h"
 #include "80211mgr.h"
 
-/*---------------------  Static Variables  --------------------------*/
 static int          msglevel                =MSG_LEVEL_INFO;
 
-const BYTE abyOUI00[4] = { 0x00, 0x50, 0xf2, 0x00 };
-const BYTE abyOUI01[4] = { 0x00, 0x50, 0xf2, 0x01 };
-const BYTE abyOUI02[4] = { 0x00, 0x50, 0xf2, 0x02 };
-const BYTE abyOUI03[4] = { 0x00, 0x50, 0xf2, 0x03 };
-const BYTE abyOUI04[4] = { 0x00, 0x50, 0xf2, 0x04 };
-const BYTE abyOUI05[4] = { 0x00, 0x50, 0xf2, 0x05 };
-
+const u8 abyOUI00[4] = { 0x00, 0x50, 0xf2, 0x00 };
+const u8 abyOUI01[4] = { 0x00, 0x50, 0xf2, 0x01 };
+const u8 abyOUI02[4] = { 0x00, 0x50, 0xf2, 0x02 };
+const u8 abyOUI03[4] = { 0x00, 0x50, 0xf2, 0x03 };
+const u8 abyOUI04[4] = { 0x00, 0x50, 0xf2, 0x04 };
+const u8 abyOUI05[4] = { 0x00, 0x50, 0xf2, 0x05 };
 
 /*+
  *
@@ -88,7 +85,6 @@ WPA_ClearRSN(
     pBSSList->bWPAValid = false;
 }
 
-
 /*+
  *
  * Description:
@@ -112,7 +108,7 @@ WPA_ParseRSN(
 {
     PWLAN_IE_RSN_AUTH  pIE_RSN_Auth = NULL;
     int                i, j, m, n = 0;
-    PBYTE              pbyCaps;
+    u8 *              pbyCaps;
 
     WPA_ClearRSN(pBSSList);
 
@@ -167,7 +163,7 @@ WPA_ParseRSN(
                     break;
                 //DBG_PRN_GRP14(("abyPKType[%d]: %X\n", j-1, pBSSList->abyPKType[j-1]));
             } //for
-            pBSSList->wPKCount = (WORD)j;
+            pBSSList->wPKCount = (u16)j;
             DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"wPKCount: %d\n", pBSSList->wPKCount);
         }
 
@@ -197,7 +193,7 @@ WPA_ParseRSN(
                 //DBG_PRN_GRP14(("abyAuthType[%d]: %X\n", j-1, pBSSList->abyAuthType[j-1]));
             }
             if(j > 0)
-                pBSSList->wAuthCount = (WORD)j;
+                pBSSList->wAuthCount = (u16)j;
             DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"wAuthCount: %d\n", pBSSList->wAuthCount);
         }
 
@@ -209,11 +205,11 @@ WPA_ParseRSN(
             DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"14+4+(m+n)*4: %d\n", 14+4+(m+n)*4);
 
             if(pRSN->len+2 >= 14+4+(m+n)*4) { //oui1(4)+ver(2)+GKS(4)+PKSCnt(2)+PKS(4*m)+AKC(2)+AKS(4*n)+Cap(2)
-                pbyCaps = (PBYTE)pIE_RSN_Auth->AuthKSList[n].abyOUI;
+                pbyCaps = (u8 *)pIE_RSN_Auth->AuthKSList[n].abyOUI;
                 pBSSList->byDefaultK_as_PK = (*pbyCaps) & WPA_GROUPFLAG;
                 pBSSList->byReplayIdx = 2 << ((*pbyCaps >> WPA_REPLAYBITSSHIFT) & WPA_REPLAYBITS);
                 pBSSList->sRSNCapObj.bRSNCapExist = true;
-                pBSSList->sRSNCapObj.wRSNCap = *(PWORD)pbyCaps;
+                pBSSList->sRSNCapObj.wRSNCap = *(u16 *)pbyCaps;
                 //DBG_PRN_GRP14(("pbyCaps: %X\n", *pbyCaps));
                 //DBG_PRN_GRP14(("byDefaultK_as_PK: %X\n", pBSSList->byDefaultK_as_PK));
                 //DBG_PRN_GRP14(("byReplayIdx: %X\n", pBSSList->byReplayIdx));
@@ -241,13 +237,13 @@ WPA_ParseRSN(
 -*/
 bool
 WPA_SearchRSN(
-    BYTE                byCmd,
-    BYTE                byEncrypt,
+    u8                byCmd,
+    u8                byEncrypt,
      PKnownBSS        pBSSList
     )
 {
     int ii;
-    BYTE byPKType = WPA_NONE;
+    u8 byPKType = WPA_NONE;
 
     if (pBSSList->bWPAValid == false)
         return false;
diff --git a/drivers/staging/vt6656/wpa.h b/drivers/staging/vt6656/wpa.h
index 0369cbf..2a724c0 100644
--- a/drivers/staging/vt6656/wpa.h
+++ b/drivers/staging/vt6656/wpa.h
@@ -31,11 +31,8 @@
 #ifndef __WPA_H__
 #define __WPA_H__
 
-#include "ttype.h"
 #include "80211hdr.h"
 
-/*---------------------  Export Definitions -------------------------*/
-
 #define WPA_NONE            0
 #define WPA_WEP40           1
 #define WPA_TKIP            2
@@ -49,15 +46,6 @@
 #define WPA_REPLAYBITSSHIFT 2
 #define WPA_REPLAYBITS      0x03
 
-/*---------------------  Export Classes  ----------------------------*/
-
-/*---------------------  Export Variables  --------------------------*/
-
-/*---------------------  Export Types  ------------------------------*/
-
-
-/*---------------------  Export Functions  --------------------------*/
-
 void
 WPA_ClearRSN(
      PKnownBSS        pBSSList
@@ -71,8 +59,8 @@ WPA_ParseRSN(
 
 bool
 WPA_SearchRSN(
-    BYTE                byCmd,
-    BYTE                byEncrypt,
+    u8                byCmd,
+    u8                byEncrypt,
      PKnownBSS        pBSSList
     );
 
diff --git a/drivers/staging/vt6656/wpa2.c b/drivers/staging/vt6656/wpa2.c
index a89456a..aa221618 100644
--- a/drivers/staging/vt6656/wpa2.c
+++ b/drivers/staging/vt6656/wpa2.c
@@ -34,28 +34,17 @@
 #include "device.h"
 #include "wpa2.h"
 
-/*---------------------  Static Definitions -------------------------*/
 static int          msglevel                =MSG_LEVEL_INFO;
 //static int          msglevel                =MSG_LEVEL_DEBUG;
-/*---------------------  Static Classes  ----------------------------*/
 
-/*---------------------  Static Variables  --------------------------*/
+const u8 abyOUIGK[4]      = { 0x00, 0x0F, 0xAC, 0x00 };
+const u8 abyOUIWEP40[4]   = { 0x00, 0x0F, 0xAC, 0x01 };
+const u8 abyOUIWEP104[4]  = { 0x00, 0x0F, 0xAC, 0x05 };
+const u8 abyOUITKIP[4]    = { 0x00, 0x0F, 0xAC, 0x02 };
+const u8 abyOUICCMP[4]    = { 0x00, 0x0F, 0xAC, 0x04 };
 
-const BYTE abyOUIGK[4]      = { 0x00, 0x0F, 0xAC, 0x00 };
-const BYTE abyOUIWEP40[4]   = { 0x00, 0x0F, 0xAC, 0x01 };
-const BYTE abyOUIWEP104[4]  = { 0x00, 0x0F, 0xAC, 0x05 };
-const BYTE abyOUITKIP[4]    = { 0x00, 0x0F, 0xAC, 0x02 };
-const BYTE abyOUICCMP[4]    = { 0x00, 0x0F, 0xAC, 0x04 };
-
-const BYTE abyOUI8021X[4]   = { 0x00, 0x0F, 0xAC, 0x01 };
-const BYTE abyOUIPSK[4]     = { 0x00, 0x0F, 0xAC, 0x02 };
-
-
-/*---------------------  Static Functions  --------------------------*/
-
-/*---------------------  Export Variables  --------------------------*/
-
-/*---------------------  Export Functions  --------------------------*/
+const u8 abyOUI8021X[4]   = { 0x00, 0x0F, 0xAC, 0x01 };
+const u8 abyOUIPSK[4]     = { 0x00, 0x0F, 0xAC, 0x02 };
 
 /*+
  *
@@ -113,8 +102,8 @@ WPA2vParseRSN (
     )
 {
     int                 i, j;
-    WORD                m = 0, n = 0;
-    PBYTE               pbyOUI;
+    u16                m = 0, n = 0;
+    u8 *               pbyOUI;
     bool                bUseGK = false;
 
     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"WPA2_ParseRSN: [%d]\n", pRSN->len);
@@ -163,11 +152,11 @@ WPA2vParseRSN (
         }
 
         if (pRSN->len >= 8) { // ver(2) + GK(4) + PK count(2)
-            pBSSNode->wCSSPKCount = *((PWORD) &(pRSN->abyRSN[4]));
+            pBSSNode->wCSSPKCount = *((u16 *) &(pRSN->abyRSN[4]));
             j = 0;
             pbyOUI = &(pRSN->abyRSN[6]);
 
-            for (i = 0; (i < pBSSNode->wCSSPKCount) && (j < sizeof(pBSSNode->abyCSSPK)/sizeof(BYTE)); i++) {
+            for (i = 0; (i < pBSSNode->wCSSPKCount) && (j < sizeof(pBSSNode->abyCSSPK)/sizeof(u8)); i++) {
 
                 if (pRSN->len >= 8+i*4+4) { // ver(2)+GK(4)+PKCnt(2)+PKS(4*i)
                     if ( !memcmp(pbyOUI, abyOUIGK, 4)) {
@@ -208,17 +197,17 @@ WPA2vParseRSN (
                 // invalid CSS, No valid PK.
                 return;
             }
-            pBSSNode->wCSSPKCount = (WORD)j;
+            pBSSNode->wCSSPKCount = (u16)j;
             DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"wCSSPKCount: %d\n", pBSSNode->wCSSPKCount);
         }
 
-        m = *((PWORD) &(pRSN->abyRSN[4]));
+        m = *((u16 *) &(pRSN->abyRSN[4]));
 
         if (pRSN->len >= 10+m*4) { // ver(2) + GK(4) + PK count(2) + PKS(4*m) + AKMSS count(2)
-            pBSSNode->wAKMSSAuthCount = *((PWORD) &(pRSN->abyRSN[6+4*m]));
+            pBSSNode->wAKMSSAuthCount = *((u16 *) &(pRSN->abyRSN[6+4*m]));
             j = 0;
             pbyOUI = &(pRSN->abyRSN[8+4*m]);
-            for (i = 0; (i < pBSSNode->wAKMSSAuthCount) && (j < sizeof(pBSSNode->abyAKMSSAuthType)/sizeof(BYTE)); i++) {
+            for (i = 0; (i < pBSSNode->wAKMSSAuthCount) && (j < sizeof(pBSSNode->abyAKMSSAuthType)/sizeof(u8)); i++) {
                 if (pRSN->len >= 10+(m+i)*4+4) { // ver(2)+GK(4)+PKCnt(2)+PKS(4*m)+AKMSS(2)+AKS(4*i)
                     if ( !memcmp(pbyOUI, abyOUI8021X, 4))
                         pBSSNode->abyAKMSSAuthType[j++] = WLAN_11i_AKMSS_802_1X;
@@ -231,134 +220,16 @@ WPA2vParseRSN (
                 } else
                     break;
             }
-            pBSSNode->wAKMSSAuthCount = (WORD)j;
+            pBSSNode->wAKMSSAuthCount = (u16)j;
             DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"wAKMSSAuthCount: %d\n", pBSSNode->wAKMSSAuthCount);
 
-            n = *((PWORD) &(pRSN->abyRSN[6+4*m]));
+            n = *((u16 *) &(pRSN->abyRSN[6+4*m]));
             if (pRSN->len >= 12+4*m+4*n) { // ver(2)+GK(4)+PKCnt(2)+PKS(4*m)+AKMSSCnt(2)+AKMSS(4*n)+Cap(2)
                 pBSSNode->sRSNCapObj.bRSNCapExist = true;
-                pBSSNode->sRSNCapObj.wRSNCap = *((PWORD) &(pRSN->abyRSN[8+4*m+4*n]));
+                pBSSNode->sRSNCapObj.wRSNCap = *((u16 *) &(pRSN->abyRSN[8+4*m+4*n]));
             }
         }
         //ignore PMKID lists bcs only (Re)Assocrequest has this field
         pBSSNode->bWPA2Valid = true;
     }
 }
-
-
-/*+
- *
- * Description:
- *    Set WPA IEs
- *
- * Parameters:
- *  In:
- *      pMgmtHandle - Pointer to management object
- *  Out:
- *      pRSNIEs     - Pointer to the RSN IE to set.
- *
- * Return Value: length of IEs.
- *
--*/
-unsigned int WPA2uSetIEs(void *pMgmtHandle, PWLAN_IE_RSN pRSNIEs)
-{
-	struct vnt_manager *pMgmt = (struct vnt_manager *)pMgmtHandle;
-	u8 *pbyBuffer = NULL;
-	int ii = 0;
-	u16 *pwPMKID = NULL;
-
-	if (pRSNIEs == NULL)
-		return 0;
-
-    if (((pMgmt->eAuthenMode == WMAC_AUTH_WPA2) ||
-         (pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK)) &&
-        (pMgmt->pCurrBSS != NULL)) {
-        /* WPA2 IE */
-        pbyBuffer = (PBYTE) pRSNIEs;
-        pRSNIEs->byElementID = WLAN_EID_RSN;
-        pRSNIEs->len = 6; //Version(2)+GK(4)
-        pRSNIEs->wVersion = 1;
-        //Group Key Cipher Suite
-        pRSNIEs->abyRSN[0] = 0x00;
-        pRSNIEs->abyRSN[1] = 0x0F;
-        pRSNIEs->abyRSN[2] = 0xAC;
-        if (pMgmt->byCSSGK == KEY_CTL_WEP) {
-            pRSNIEs->abyRSN[3] = pMgmt->pCurrBSS->byCSSGK;
-        } else if (pMgmt->byCSSGK == KEY_CTL_TKIP) {
-            pRSNIEs->abyRSN[3] = WLAN_11i_CSS_TKIP;
-        } else if (pMgmt->byCSSGK == KEY_CTL_CCMP) {
-            pRSNIEs->abyRSN[3] = WLAN_11i_CSS_CCMP;
-        } else {
-            pRSNIEs->abyRSN[3] = WLAN_11i_CSS_UNKNOWN;
-        }
-
-        // Pairwise Key Cipher Suite
-        pRSNIEs->abyRSN[4] = 1;
-        pRSNIEs->abyRSN[5] = 0;
-        pRSNIEs->abyRSN[6] = 0x00;
-        pRSNIEs->abyRSN[7] = 0x0F;
-        pRSNIEs->abyRSN[8] = 0xAC;
-        if (pMgmt->byCSSPK == KEY_CTL_TKIP) {
-            pRSNIEs->abyRSN[9] = WLAN_11i_CSS_TKIP;
-        } else if (pMgmt->byCSSPK == KEY_CTL_CCMP) {
-            pRSNIEs->abyRSN[9] = WLAN_11i_CSS_CCMP;
-        } else if (pMgmt->byCSSPK == KEY_CTL_NONE) {
-            pRSNIEs->abyRSN[9] = WLAN_11i_CSS_USE_GROUP;
-        } else {
-            pRSNIEs->abyRSN[9] = WLAN_11i_CSS_UNKNOWN;
-        }
-        pRSNIEs->len += 6;
-
-        // Auth Key Management Suite
-        pRSNIEs->abyRSN[10] = 1;
-        pRSNIEs->abyRSN[11] = 0;
-        pRSNIEs->abyRSN[12] = 0x00;
-        pRSNIEs->abyRSN[13] = 0x0F;
-        pRSNIEs->abyRSN[14] = 0xAC;
-        if (pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK) {
-            pRSNIEs->abyRSN[15] = WLAN_11i_AKMSS_PSK;
-        } else if (pMgmt->eAuthenMode == WMAC_AUTH_WPA2) {
-            pRSNIEs->abyRSN[15] = WLAN_11i_AKMSS_802_1X;
-        } else {
-            pRSNIEs->abyRSN[15] = WLAN_11i_AKMSS_UNKNOWN;
-        }
-        pRSNIEs->len +=6;
-
-        // RSN Capabilites
-        if (pMgmt->pCurrBSS->sRSNCapObj.bRSNCapExist == true) {
-            memcpy(&pRSNIEs->abyRSN[16], &pMgmt->pCurrBSS->sRSNCapObj.wRSNCap, 2);
-        } else {
-            pRSNIEs->abyRSN[16] = 0;
-            pRSNIEs->abyRSN[17] = 0;
-        }
-        pRSNIEs->len +=2;
-
-	if ((pMgmt->gsPMKIDCache.BSSIDInfoCount > 0) &&
-	    (pMgmt->bRoaming == true) &&
-            (pMgmt->eAuthenMode == WMAC_AUTH_WPA2)) {
-		/* RSN PMKID, pointer to PMKID count */
-		pwPMKID = (PWORD)(&pRSNIEs->abyRSN[18]);
-		*pwPMKID = 0;                     /* Initialize PMKID count */
-		pbyBuffer = &pRSNIEs->abyRSN[20];    /* Point to PMKID list */
-		for (ii = 0; ii < pMgmt->gsPMKIDCache.BSSIDInfoCount; ii++) {
-			if (!memcmp(&pMgmt->
-				    gsPMKIDCache.BSSIDInfo[ii].abyBSSID[0],
-				    pMgmt->abyCurrBSSID,
-				    ETH_ALEN)) {
-				(*pwPMKID)++;
-				memcpy(pbyBuffer,
-			pMgmt->gsPMKIDCache.BSSIDInfo[ii].abyPMKID,
-				       16);
-				pbyBuffer += 16;
-			}
-		}
-            if (*pwPMKID != 0) {
-                pRSNIEs->len += (2 + (*pwPMKID)*16);
-            } else {
-                pbyBuffer = &pRSNIEs->abyRSN[18];
-            }
-        }
-        return(pRSNIEs->len + WLAN_IEHDR_LEN);
-    }
-    return(0);
-}
diff --git a/drivers/staging/vt6656/wpa2.h b/drivers/staging/vt6656/wpa2.h
index c359252..dc505ce 100644
--- a/drivers/staging/vt6656/wpa2.h
+++ b/drivers/staging/vt6656/wpa2.h
@@ -31,17 +31,15 @@
 #ifndef __WPA2_H__
 #define __WPA2_H__
 
-#include "ttype.h"
 #include "80211mgr.h"
 #include "80211hdr.h"
 #include "bssdb.h"
 
-/*---------------------  Export Definitions -------------------------*/
 #define MAX_PMKID_CACHE         16
 
 typedef struct tagsPMKIDInfo {
-    BYTE    abyBSSID[6];
-    BYTE    abyPMKID[16];
+    u8    abyBSSID[6];
+    u8    abyPMKID[16];
 } PMKIDInfo, *PPMKIDInfo;
 
 typedef struct tagSPMKIDCache {
@@ -49,18 +47,7 @@ typedef struct tagSPMKIDCache {
 	PMKIDInfo BSSIDInfo[MAX_PMKID_CACHE];
 } SPMKIDCache, *PSPMKIDCache;
 
-
-/*---------------------  Export Classes  ----------------------------*/
-
-/*---------------------  Export Variables  --------------------------*/
-
-/*---------------------  Export Types  ------------------------------*/
-
-/*---------------------  Export Functions  --------------------------*/
-
 void WPA2_ClearRSN(PKnownBSS pBSSNode);
 void WPA2vParseRSN(PKnownBSS pBSSNode, PWLAN_IE_RSN pRSN);
 
-unsigned int WPA2uSetIEs(void *pMgmtHandle, PWLAN_IE_RSN pRSNIEs);
-
 #endif /* __WPA2_H__ */
diff --git a/drivers/staging/vt6656/wpactl.c b/drivers/staging/vt6656/wpactl.c
index 53629b2..9f1b413 100644
--- a/drivers/staging/vt6656/wpactl.c
+++ b/drivers/staging/vt6656/wpactl.c
@@ -42,18 +42,8 @@
 #include "rndis.h"
 #include "rf.h"
 
-/*---------------------  Static Definitions -------------------------*/
-
-/*---------------------  Static Classes  ----------------------------*/
-
-/*---------------------  Static Variables  --------------------------*/
 static int msglevel = MSG_LEVEL_INFO;
 
-/*---------------------  Static Functions  --------------------------*/
-
-/*---------------------  Export Variables  --------------------------*/
-
-
 /*
  * Description:
  *      Set WPA algorithm & keys
@@ -71,11 +61,11 @@ int wpa_set_keys(struct vnt_private *pDevice, void *ctx)
 {
 	struct viawget_wpa_param *param = ctx;
 	struct vnt_manager *pMgmt = &pDevice->vnt_mgmt;
-	DWORD dwKeyIndex = 0;
-	BYTE abyKey[MAX_KEY_LEN];
-	BYTE abySeq[MAX_KEY_LEN];
+	u32 dwKeyIndex = 0;
+	u8 abyKey[MAX_KEY_LEN];
+	u8 abySeq[MAX_KEY_LEN];
 	u64 KeyRSC;
-	BYTE byKeyDecMode = KEY_CTL_WEP;
+	u8 byKeyDecMode = KEY_CTL_WEP;
 	int ret = 0;
 	int uu;
 	int ii;
@@ -101,14 +91,14 @@ int wpa_set_keys(struct vnt_private *pDevice, void *ctx)
 
 	memcpy(&abyKey[0], param->u.wpa_key.key, param->u.wpa_key.key_len);
 
-	dwKeyIndex = (DWORD)(param->u.wpa_key.key_index);
+	dwKeyIndex = (u32)(param->u.wpa_key.key_index);
 
 	if (param->u.wpa_key.alg_name == WPA_ALG_WEP) {
 		if (dwKeyIndex > 3) {
 			return -EINVAL;
 		} else {
 			if (param->u.wpa_key.set_tx) {
-				pDevice->byKeyIndex = (BYTE)dwKeyIndex;
+				pDevice->byKeyIndex = (u8)dwKeyIndex;
 				pDevice->bTransmitKey = true;
 				dwKeyIndex |= (1 << 31);
 			}
@@ -127,7 +117,6 @@ int wpa_set_keys(struct vnt_private *pDevice, void *ctx)
 		return ret;
 	}
 
-
 	if (param->u.wpa_key.seq && param->u.wpa_key.seq_len > sizeof(abySeq))
 		return -EINVAL;
 
@@ -159,7 +148,6 @@ int wpa_set_keys(struct vnt_private *pDevice, void *ctx)
 	if (param->u.wpa_key.set_tx)
 		dwKeyIndex |= (1 << 31);
 
-
 	if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled)
 		byKeyDecMode = KEY_CTL_CCMP;
 	else if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled)
@@ -204,7 +192,7 @@ int wpa_set_keys(struct vnt_private *pDevice, void *ctx)
 		if ((KeybSetAllGroupKey(pDevice, &(pDevice->sKey), dwKeyIndex,
 							param->u.wpa_key.key_len,
 							&KeyRSC,
-							(PBYTE)abyKey,
+							(u8 *)abyKey,
 							byKeyDecMode
 					) == true) &&
 			(KeybSetDefaultKey(pDevice,
@@ -212,7 +200,7 @@ int wpa_set_keys(struct vnt_private *pDevice, void *ctx)
 					dwKeyIndex,
 					param->u.wpa_key.key_len,
 					&KeyRSC,
-					(PBYTE)abyKey,
+					(u8 *)abyKey,
 					byKeyDecMode
 				) == true) ) {
 			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "GROUP Key Assign.\n");
@@ -234,7 +222,7 @@ int wpa_set_keys(struct vnt_private *pDevice, void *ctx)
 		}
 		if (KeybSetKey(pDevice, &(pDevice->sKey), &param->addr[0],
 				dwKeyIndex, param->u.wpa_key.key_len,
-				&KeyRSC, (PBYTE)abyKey, byKeyDecMode
+				&KeyRSC, (u8 *)abyKey, byKeyDecMode
 				) == true) {
 			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pairwise Key Set\n");
 		} else {
@@ -250,7 +238,7 @@ int wpa_set_keys(struct vnt_private *pDevice, void *ctx)
 		}
 	} // BSSID not 0xffffffffffff
 	if ((ret == 0) && ((param->u.wpa_key.set_tx) != 0)) {
-		pDevice->byKeyIndex = (BYTE)param->u.wpa_key.key_index;
+		pDevice->byKeyIndex = (u8)param->u.wpa_key.key_index;
 		pDevice->bTransmitKey = true;
 	}
 	pDevice->bEncryptionEnable = true;
@@ -258,4 +246,3 @@ int wpa_set_keys(struct vnt_private *pDevice, void *ctx)
 	return ret;
 }
 
-
diff --git a/drivers/staging/vt6656/wpactl.h b/drivers/staging/vt6656/wpactl.h
index 2235ee9..e032a1b 100644
--- a/drivers/staging/vt6656/wpactl.h
+++ b/drivers/staging/vt6656/wpactl.h
@@ -32,9 +32,6 @@
 #include "device.h"
 #include "iowpa.h"
 
-/*---------------------  Export Definitions -------------------------*/
-
-
 //WPA related
 
 typedef enum { WPA_ALG_NONE, WPA_ALG_WEP, WPA_ALG_TKIP, WPA_ALG_CCMP } wpa_alg;
@@ -43,15 +40,8 @@ typedef enum { WPA_ALG_NONE, WPA_ALG_WEP, WPA_ALG_TKIP, WPA_ALG_CCMP } wpa_alg;
 #define AUTH_ALG_SHARED_KEY	0x02
 #define AUTH_ALG_LEAP		0x04
 
-
 typedef unsigned long long NDIS_802_11_KEY_RSC;
 
-/*---------------------  Export Classes  ----------------------------*/
-
-/*---------------------  Export Variables  --------------------------*/
-
-/*---------------------  Export Functions  --------------------------*/
-
 int wpa_set_keys(struct vnt_private *, void *ctx);
 
 #endif /* __WPACL_H__ */
diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c
index 8d2277b..428a9be 100644
--- a/drivers/staging/wlan-ng/prism2sta.c
+++ b/drivers/staging/wlan-ng/prism2sta.c
@@ -1160,30 +1160,33 @@ static void prism2sta_inf_chinforesults(wlandevice_t *wlandev,
 	    le16_to_cpu(inf->info.chinforesult.scanchannels);
 
 	for (i = 0, n = 0; i < HFA384x_CHINFORESULT_MAX; i++) {
-		if (hw->channel_info.results.scanchannels & (1 << i)) {
-			int channel =
-			    le16_to_cpu(inf->info.chinforesult.result[n].chid) -
-			    1;
-			hfa384x_ChInfoResultSub_t *chinforesult =
-			    &hw->channel_info.results.result[channel];
-			chinforesult->chid = channel;
-			chinforesult->anl =
-			    le16_to_cpu(inf->info.chinforesult.result[n].anl);
-			chinforesult->pnl =
-			    le16_to_cpu(inf->info.chinforesult.result[n].pnl);
-			chinforesult->active =
-			    le16_to_cpu(inf->info.chinforesult.result[n].
-					active);
-	pr_debug
-		("chinfo: channel %d, %s level (avg/peak)=%d/%d dB, pcf %d\n",
-			     channel + 1,
-			     chinforesult->
-			     active & HFA384x_CHINFORESULT_BSSACTIVE ? "signal"
-			     : "noise", chinforesult->anl, chinforesult->pnl,
-			     chinforesult->
-			     active & HFA384x_CHINFORESULT_PCFACTIVE ? 1 : 0);
-			n++;
-		}
+		hfa384x_ChInfoResultSub_t *result;
+		hfa384x_ChInfoResultSub_t *chinforesult;
+		int chan;
+
+		if (!(hw->channel_info.results.scanchannels & (1 << i)))
+			continue;
+
+		result = &inf->info.chinforesult.result[n];
+		chan = le16_to_cpu(result->chid) - 1;
+
+		if (chan < 0 || chan >= HFA384x_CHINFORESULT_MAX)
+			continue;
+
+		chinforesult = &hw->channel_info.results.result[chan];
+		chinforesult->chid = chan;
+		chinforesult->anl = le16_to_cpu(result->anl);
+		chinforesult->pnl = le16_to_cpu(result->pnl);
+		chinforesult->active = le16_to_cpu(result->active);
+
+		pr_debug("chinfo: channel %d, %s level (avg/peak)=%d/%d dB, pcf %d\n",
+			 chan + 1,
+			 (chinforesult->active & HFA384x_CHINFORESULT_BSSACTIVE)
+				? "signal" : "noise",
+			 chinforesult->anl, chinforesult->pnl,
+			 (chinforesult->active & HFA384x_CHINFORESULT_PCFACTIVE)
+				? 1 : 0);
+		n++;
 	}
 	atomic_set(&hw->channel_info.done, 2);
 
diff --git a/drivers/staging/wlan-ng/prism2usb.c b/drivers/staging/wlan-ng/prism2usb.c
index b1aed1f..b401974 100644
--- a/drivers/staging/wlan-ng/prism2usb.c
+++ b/drivers/staging/wlan-ng/prism2usb.c
@@ -113,14 +113,14 @@ static int prism2sta_probe_usb(struct usb_interface *interface,
 	dev = interface_to_usbdev(interface);
 	wlandev = create_wlan();
 	if (wlandev == NULL) {
-		printk(KERN_ERR "%s: Memory allocation failure.\n", dev_info);
+		dev_err(&interface->dev, "Memory allocation failure.\n");
 		result = -EIO;
 		goto failed;
 	}
 	hw = wlandev->priv;
 
 	if (wlan_setup(wlandev, &(interface->dev)) != 0) {
-		printk(KERN_ERR "%s: wlan_setup() failed.\n", dev_info);
+		dev_err(&interface->dev, "wlan_setup() failed.\n");
 		result = -EIO;
 		goto failed;
 	}
@@ -143,8 +143,7 @@ static int prism2sta_probe_usb(struct usb_interface *interface,
 			unregister_wlandev(wlandev);
 			hfa384x_destroy(hw);
 			result = -EIO;
-			printk(KERN_ERR
-			       "%s: hfa384x_corereset() failed.\n", dev_info);
+			dev_err(&interface->dev, "hfa384x_corereset() failed.\n");
 			goto failed;
 		}
 	}
@@ -158,7 +157,7 @@ static int prism2sta_probe_usb(struct usb_interface *interface,
 	prism2sta_ifstate(wlandev, P80211ENUM_ifstate_enable);
 
 	if (register_wlandev(wlandev) != 0) {
-		printk(KERN_ERR "%s: register_wlandev() failed.\n", dev_info);
+		dev_err(&interface->dev, "register_wlandev() failed.\n");
 		result = -EIO;
 		goto failed;
 	}
@@ -329,8 +328,7 @@ static int prism2sta_resume(struct usb_interface *interface)
 		if (result != 0) {
 			unregister_wlandev(wlandev);
 			hfa384x_destroy(hw);
-			printk(KERN_ERR
-			       "%s: hfa384x_corereset() failed.\n", dev_info);
+			dev_err(&interface->dev, "hfa384x_corereset() failed.\n");
 			kfree(wlandev);
 			kfree(hw);
 			wlandev = NULL;
diff --git a/drivers/staging/xgifb/vb_def.h b/drivers/staging/xgifb/vb_def.h
index 148f637..80c9723 100644
--- a/drivers/staging/xgifb/vb_def.h
+++ b/drivers/staging/xgifb/vb_def.h
@@ -62,10 +62,6 @@
 #define EnableVBCLKDRVLOW    0x4000
 #define EnablePLLSPLOW       0x8000
 
-#define LCDBToA              0x20   /* LCD SetFlag */
-#define StLCDBToA            0x40
-#define LockLCDBToA          0x80
-#define   LCDToFull          0x10
 #define AVIDEOSense          0x01   /* CR32 */
 #define SVIDEOSense          0x02
 #define SCARTSense           0x04
diff --git a/drivers/staging/xgifb/vb_init.c b/drivers/staging/xgifb/vb_init.c
index df127e4..19ce5a9 100644
--- a/drivers/staging/xgifb/vb_init.c
+++ b/drivers/staging/xgifb/vb_init.c
@@ -90,18 +90,14 @@ static void XGINew_DDR1x_MRS_340(unsigned long P3c4,
 	xgifb_reg_set(P3c4, 0x16, 0x80);
 
 	udelay(60);
-	xgifb_reg_set(P3c4,
-		      0x18,
-		      pVBInfo->SR15[2][pVBInfo->ram_type]); /* SR18 */
+	xgifb_reg_set(P3c4, 0x18, pVBInfo->SR18[pVBInfo->ram_type]); /* SR18 */
 	xgifb_reg_set(P3c4, 0x19, 0x01);
 	xgifb_reg_set(P3c4, 0x16, 0x03);
 	xgifb_reg_set(P3c4, 0x16, 0x83);
 	mdelay(1);
 	xgifb_reg_set(P3c4, 0x1B, 0x03);
 	udelay(500);
-	xgifb_reg_set(P3c4,
-		      0x18,
-		      pVBInfo->SR15[2][pVBInfo->ram_type]); /* SR18 */
+	xgifb_reg_set(P3c4, 0x18, pVBInfo->SR18[pVBInfo->ram_type]); /* SR18 */
 	xgifb_reg_set(P3c4, 0x19, 0x00);
 	xgifb_reg_set(P3c4, 0x16, 0x03);
 	xgifb_reg_set(P3c4, 0x16, 0x83);
@@ -265,18 +261,14 @@ static void XGINew_DDR1x_MRS_XG20(unsigned long P3c4,
 	xgifb_reg_set(P3c4, 0x16, 0x00);
 	xgifb_reg_set(P3c4, 0x16, 0x80);
 	udelay(60);
-	xgifb_reg_set(P3c4,
-		      0x18,
-		      pVBInfo->SR15[2][pVBInfo->ram_type]); /* SR18 */
+	xgifb_reg_set(P3c4, 0x18, pVBInfo->SR18[pVBInfo->ram_type]); /* SR18 */
 	xgifb_reg_set(P3c4, 0x19, 0x01);
 	xgifb_reg_set(P3c4, 0x16, 0x03);
 	xgifb_reg_set(P3c4, 0x16, 0x83);
 	mdelay(1);
 	xgifb_reg_set(P3c4, 0x1B, 0x03);
 	udelay(500);
-	xgifb_reg_set(P3c4,
-		      0x18,
-		      pVBInfo->SR15[2][pVBInfo->ram_type]); /* SR18 */
+	xgifb_reg_set(P3c4, 0x18, pVBInfo->SR18[pVBInfo->ram_type]); /* SR18 */
 	xgifb_reg_set(P3c4, 0x19, 0x00);
 	xgifb_reg_set(P3c4, 0x16, 0x03);
 	xgifb_reg_set(P3c4, 0x16, 0x83);
@@ -507,9 +499,7 @@ static void XGINew_SetDRAMDefaultRegister340(
 		xgifb_reg_set(P3d4, 0xB0, 0x80); /* DDRII Dual frequency mode */
 		XGINew_DDR2_DefaultRegister(HwDeviceExtension, P3d4, pVBInfo);
 	}
-	xgifb_reg_set(P3c4,
-		      0x1B,
-		      pVBInfo->SR15[3][pVBInfo->ram_type]); /* SR1B */
+	xgifb_reg_set(P3c4, 0x1B, 0x03); /* SR1B */
 }
 
 
@@ -888,7 +878,7 @@ done:
 	return rom_copy;
 }
 
-static void xgifb_read_vbios(struct pci_dev *pdev,
+static bool xgifb_read_vbios(struct pci_dev *pdev,
 			      struct vb_device_info *pVBInfo)
 {
 	struct xgifb_video_info *xgifb_info = pci_get_drvdata(pdev);
@@ -899,13 +889,10 @@ static void xgifb_read_vbios(struct pci_dev *pdev,
 	size_t vbios_size;
 	int entry;
 
-	if (xgifb_info->chip != XG21)
-		return;
-	pVBInfo->IF_DEF_LVDS = 0;
 	vbios = xgifb_copy_rom(pdev, &vbios_size);
 	if (vbios == NULL) {
 		dev_err(&pdev->dev, "Video BIOS not available\n");
-		return;
+		return false;
 	}
 	if (vbios_size <= 0x65)
 		goto error;
@@ -917,7 +904,7 @@ static void xgifb_read_vbios(struct pci_dev *pdev,
 	    (!xgifb_info->display2_force ||
 	     xgifb_info->display2 != XGIFB_DISP_LCD)) {
 		vfree(vbios);
-		return;
+		return false;
 	}
 	if (vbios_size <= 0x317)
 		goto error;
@@ -956,11 +943,11 @@ static void xgifb_read_vbios(struct pci_dev *pdev,
 	lvds->PSC_S4		= vbios[i + 23];
 	lvds->PSC_S5		= vbios[i + 24];
 	vfree(vbios);
-	pVBInfo->IF_DEF_LVDS = 1;
-	return;
+	return true;
 error:
 	dev_err(&pdev->dev, "Video BIOS corrupted\n");
 	vfree(vbios);
+	return false;
 }
 
 static void XGINew_ChkSenseStatus(struct xgi_hw_device_info *HwDeviceExtension,
@@ -1132,12 +1119,13 @@ static unsigned short XGINew_SenseLCD(struct xgi_hw_device_info
 	}
 }
 
-static void XGINew_GetXG21Sense(struct xgi_hw_device_info *HwDeviceExtension,
+static void XGINew_GetXG21Sense(struct pci_dev *pdev,
 		struct vb_device_info *pVBInfo)
 {
+	struct xgifb_video_info *xgifb_info = pci_get_drvdata(pdev);
 	unsigned char Temp;
 
-	if (pVBInfo->IF_DEF_LVDS) { /* For XG21 LVDS */
+	if (xgifb_read_vbios(pdev, pVBInfo)) { /* For XG21 LVDS */
 		xgifb_reg_or(pVBInfo->P3d4, 0x32, LCDSense);
 		/* LVDS on chip */
 		xgifb_reg_and_or(pVBInfo->P3d4, 0x38, ~0xE0, 0xC0);
@@ -1146,7 +1134,7 @@ static void XGINew_GetXG21Sense(struct xgi_hw_device_info *HwDeviceExtension,
 		xgifb_reg_and_or(pVBInfo->P3d4, 0x4A, ~0x03, 0x03);
 		Temp = xgifb_reg_get(pVBInfo->P3d4, 0x48) & 0xC0;
 		if (Temp == 0xC0) { /* DVI & DVO GPIOA/B pull high */
-			XGINew_SenseLCD(HwDeviceExtension, pVBInfo);
+			XGINew_SenseLCD(&xgifb_info->hw_info, pVBInfo);
 			xgifb_reg_or(pVBInfo->P3d4, 0x32, LCDSense);
 			/* Enable read GPIOF */
 			xgifb_reg_and_or(pVBInfo->P3d4, 0x4A, ~0x20, 0x20);
@@ -1172,7 +1160,6 @@ static void XGINew_GetXG27Sense(struct xgi_hw_device_info *HwDeviceExtension,
 {
 	unsigned char Temp, bCR4A;
 
-	pVBInfo->IF_DEF_LVDS = 0;
 	bCR4A = xgifb_reg_get(pVBInfo->P3d4, 0x4A);
 	/* Enable GPIOA/B/C read  */
 	xgifb_reg_and_or(pVBInfo->P3d4, 0x4A, ~0x07, 0x07);
@@ -1254,14 +1241,12 @@ unsigned char XGIInitNew(struct pci_dev *pdev)
 
 	InitTo330Pointer(HwDeviceExtension->jChipType, pVBInfo);
 
-	xgifb_read_vbios(pdev, pVBInfo);
-
 	/* Openkey */
 	xgifb_reg_set(pVBInfo->P3c4, 0x05, 0x86);
 
 	/* GetXG21Sense (GPIO) */
 	if (HwDeviceExtension->jChipType == XG21)
-		XGINew_GetXG21Sense(HwDeviceExtension, pVBInfo);
+		XGINew_GetXG21Sense(pdev, pVBInfo);
 
 	if (HwDeviceExtension->jChipType == XG27)
 		XGINew_GetXG27Sense(HwDeviceExtension, pVBInfo);
@@ -1369,17 +1354,14 @@ unsigned char XGIInitNew(struct pci_dev *pdev)
 
 	if (HwDeviceExtension->jChipType < XG20) {
 		if (XGI_BridgeIsOn(pVBInfo) == 1) {
-			if (pVBInfo->IF_DEF_LVDS == 0) {
-				xgifb_reg_set(pVBInfo->Part2Port, 0x00, 0x1C);
-				xgifb_reg_set(pVBInfo->Part4Port,
-					      0x0D, XGI330_CRT2Data_4_D);
-				xgifb_reg_set(pVBInfo->Part4Port,
-					      0x0E, XGI330_CRT2Data_4_E);
-				xgifb_reg_set(pVBInfo->Part4Port,
-					      0x10, XGI330_CRT2Data_4_10);
-				xgifb_reg_set(pVBInfo->Part4Port, 0x0F, 0x3F);
-			}
-
+			xgifb_reg_set(pVBInfo->Part2Port, 0x00, 0x1C);
+			xgifb_reg_set(pVBInfo->Part4Port,
+				      0x0D, XGI330_CRT2Data_4_D);
+			xgifb_reg_set(pVBInfo->Part4Port,
+				      0x0E, XGI330_CRT2Data_4_E);
+			xgifb_reg_set(pVBInfo->Part4Port,
+				      0x10, XGI330_CRT2Data_4_10);
+			xgifb_reg_set(pVBInfo->Part4Port, 0x0F, 0x3F);
 			XGI_LockCRT2(HwDeviceExtension, pVBInfo);
 		}
 	} /* != XG20 */
diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c
index dfa5303..3adec3f 100644
--- a/drivers/staging/xgifb/vb_setmode.c
+++ b/drivers/staging/xgifb/vb_setmode.c
@@ -32,7 +32,7 @@ void InitTo330Pointer(unsigned char ChipType, struct vb_device_info *pVBInfo)
 	pVBInfo->VBInfo = 0;
 	pVBInfo->TVInfo = 0;
 
-	pVBInfo->SR15 = XGI340_SR13;
+	pVBInfo->SR18 = XGI340_SR18;
 	pVBInfo->CR40 = XGI340_cr41;
 
 	/* 310 customization related */
@@ -49,7 +49,7 @@ void InitTo330Pointer(unsigned char ChipType, struct vb_device_info *pVBInfo)
 		pVBInfo->MCLKData = XGI27New_MCLKData;
 		pVBInfo->CR40 = XGI27_cr41;
 		pVBInfo->XGINew_CR97 = 0xc1;
-		pVBInfo->SR15 = XG27_SR13;
+		pVBInfo->SR18 = XG27_SR18;
 
 		/*Z11m DDR*/
 		temp = xgifb_reg_get(pVBInfo->P3c4, 0x3B);
diff --git a/drivers/staging/xgifb/vb_struct.h b/drivers/staging/xgifb/vb_struct.h
index ae0c18b..c08ff5b 100644
--- a/drivers/staging/xgifb/vb_struct.h
+++ b/drivers/staging/xgifb/vb_struct.h
@@ -81,7 +81,6 @@ struct XGI_XG21CRT1Struct {
 struct XGI330_LCDCapStruct {
 	unsigned char	LCD_ID;
 	unsigned short	LCD_Capability;
-	unsigned char	LCD_SetFlag;
 	unsigned char	LCD_HSyncWidth;
 	unsigned char	LCD_VSyncWidth;
 	unsigned char	LCD_VCLK;
@@ -89,16 +88,6 @@ struct XGI330_LCDCapStruct {
 	unsigned char	LCDA_VCLKData2;
 	unsigned char	LCUCHAR_VCLKData1;
 	unsigned char	LCUCHAR_VCLKData2;
-	unsigned char	PSC_S1;
-	unsigned char	PSC_S2;
-	unsigned char	PSC_S3;
-	unsigned char	PSC_S4;
-	unsigned char	PSC_S5;
-	unsigned char	PWD_2B;
-	unsigned char	PWD_2C;
-	unsigned char	PWD_2D;
-	unsigned char	PWD_2E;
-	unsigned char	PWD_2F;
 	unsigned char	Spectrum_31;
 	unsigned char	Spectrum_32;
 	unsigned char	Spectrum_33;
@@ -145,7 +134,7 @@ struct vb_device_info {
 	unsigned short   LCDHRS, LCDVRS, LCDHDES, LCDVDES;
 
 	unsigned short   ModeType;
-	unsigned short   IF_DEF_LVDS, IF_DEF_TRUMPION, IF_DEF_DSTN;
+	unsigned short   IF_DEF_LVDS;
 	unsigned short   IF_DEF_CRT2Monitor;
 	unsigned short   IF_DEF_YPbPr;
 	unsigned short   IF_DEF_HiVision;
@@ -157,12 +146,11 @@ struct vb_device_info {
 
 	void __iomem *FBAddr;
 
-	unsigned char const (*SR15)[3];
+	unsigned char const *SR18;
 	unsigned char const (*CR40)[3];
 
 	struct SiS_MCLKData const *MCLKData;
 
-	unsigned char   *pXGINew_DRAMTypeDefinition;
 	unsigned char   XGINew_CR97;
 
 	struct XGI330_LCDCapStruct const *LCDCapList;
diff --git a/drivers/staging/xgifb/vb_table.h b/drivers/staging/xgifb/vb_table.h
index b4c05c8..7168eed 100644
--- a/drivers/staging/xgifb/vb_table.h
+++ b/drivers/staging/xgifb/vb_table.h
@@ -18,18 +18,12 @@ const struct XGI_ECLKDataStruct XGI340_ECLKData[] = {
 	{0x7C, 0x08, 0x01, 200},
 };
 
-static const unsigned char XG27_SR13[4][3] = {
-	{0x35, 0x45, 0xb1}, /* SR13 */
-	{0x41, 0x51, 0x5c}, /* SR14 */
-	{0x32, 0x32, 0x42}, /* SR18 */
-	{0x03, 0x03, 0x03}  /* SR1B */
+static const unsigned char XG27_SR18[3] = {
+	0x32, 0x32, 0x42 /* SR18 */
 };
 
-static const unsigned char XGI340_SR13[4][3] = {
-	{0x35, 0x45, 0xb1}, /* SR13 */
-	{0x41, 0x51, 0x5c}, /* SR14 */
-	{0x31, 0x42, 0x42}, /* SR18 */
-	{0x03, 0x03, 0x03}  /* SR1B */
+static const unsigned char XGI340_SR18[3] = {
+	0x31, 0x42, 0x42 /* SR18 */
 };
 
 static const unsigned char XGI340_cr41[24][3] = {
@@ -1867,72 +1861,72 @@ static const struct XGI330_TVDataTablStruct XGI_TVDataTable[] = {
 /* Dual link only */
 static const struct XGI330_LCDCapStruct XGI_LCDDLCapList[] = {
 /* LCDCap1024x768 */
-	{Panel_1024x768, DefaultLCDCap, 0, 0x88, 0x06, VCLK65_315,
-	0x6C, 0xC3, 0x35, 0x62, 0x02, 0x14, 0x0A, 0x02, 0x00,
-	0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10},
+	{Panel_1024x768, DefaultLCDCap, 0x88, 0x06, VCLK65_315,
+	0x6C, 0xC3, 0x35, 0x62,
+	0x0A, 0xC0, 0x28, 0x10},
 /* LCDCap1280x1024 */
-	{Panel_1280x1024, XGI_LCDDualLink+DefaultLCDCap, StLCDBToA,
+	{Panel_1280x1024, XGI_LCDDualLink+DefaultLCDCap,
 	0x70, 0x03, VCLK108_2_315,
-	0x70, 0x44, 0xF8, 0x2F, 0x02, 0x14, 0x0A, 0x02, 0x00,
-	0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
+	0x70, 0x44, 0xF8, 0x2F,
+	0x0A, 0xC0, 0x30, 0x10},
 /* LCDCap1400x1050 */
-	{Panel_1400x1050, XGI_LCDDualLink+DefaultLCDCap, StLCDBToA,
+	{Panel_1400x1050, XGI_LCDDualLink+DefaultLCDCap,
 	0x70, 0x03, VCLK108_2_315,
-	 0x70, 0x44, 0xF8, 0x2F, 0x02, 0x14, 0x0A, 0x02, 0x00,
-	 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
+	 0x70, 0x44, 0xF8, 0x2F,
+	 0x0A, 0xC0, 0x30, 0x10},
 /* LCDCap1600x1200 */
-	{Panel_1600x1200, XGI_LCDDualLink+DefaultLCDCap, LCDToFull,
+	{Panel_1600x1200, XGI_LCDDualLink+DefaultLCDCap,
 	0xC0, 0x03, VCLK162,
-	 0x43, 0x22, 0x70, 0x24, 0x02, 0x14, 0x0A, 0x02, 0x00,
-	 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
+	 0x43, 0x22, 0x70, 0x24,
+	 0x0A, 0xC0, 0x30, 0x10},
 /* LCDCap1024x768x75 */
-	{Panel_1024x768x75, DefaultLCDCap, 0, 0x60, 0, VCLK78_75,
-	 0x2B, 0x61, 0x2B, 0x61, 0x02, 0x14, 0x0A, 0x02, 0x00,
-	 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10},
+	{Panel_1024x768x75, DefaultLCDCap, 0x60, 0, VCLK78_75,
+	 0x2B, 0x61, 0x2B, 0x61,
+	 0x0A, 0xC0, 0x28, 0x10},
 /* LCDCap1280x1024x75 */
-	{Panel_1280x1024x75, XGI_LCDDualLink+DefaultLCDCap, StLCDBToA,
+	{Panel_1280x1024x75, XGI_LCDDualLink+DefaultLCDCap,
 	 0x90, 0x03, VCLK135_5,
-	 0x54, 0x42, 0x4A, 0x61, 0x02, 0x14, 0x0A, 0x02, 0x00,
-	 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
+	 0x54, 0x42, 0x4A, 0x61,
+	 0x0A, 0xC0, 0x30, 0x10},
 /* LCDCapDefault */
-	{0xFF, DefaultLCDCap, 0, 0x88, 0x06, VCLK65_315,
-	0x6C, 0xC3, 0x35, 0x62, 0x02, 0x14, 0x0A, 0x02, 0x00,
-	0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10}
+	{0xFF, DefaultLCDCap, 0x88, 0x06, VCLK65_315,
+	0x6C, 0xC3, 0x35, 0x62,
+	0x0A, 0xC0, 0x28, 0x10}
 };
 
 static const struct XGI330_LCDCapStruct XGI_LCDCapList[] = {
 /* LCDCap1024x768 */
-	{Panel_1024x768, DefaultLCDCap, 0, 0x88, 0x06, VCLK65_315,
-	0x6C, 0xC3, 0x35, 0x62, 0x02, 0x14, 0x0A, 0x02, 0x00,
-	0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10},
+	{Panel_1024x768, DefaultLCDCap, 0x88, 0x06, VCLK65_315,
+	0x6C, 0xC3, 0x35, 0x62,
+	0x0A, 0xC0, 0x28, 0x10},
 /* LCDCap1280x1024 */
-	{Panel_1280x1024, DefaultLCDCap, StLCDBToA,
+	{Panel_1280x1024, DefaultLCDCap,
 	0x70, 0x03, VCLK108_2_315,
-	0x70, 0x44, 0xF8, 0x2F, 0x02, 0x14, 0x0A, 0x02, 0x00,
-	0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
+	0x70, 0x44, 0xF8, 0x2F,
+	0x0A, 0xC0, 0x30, 0x10},
 /* LCDCap1400x1050 */
-	{Panel_1400x1050, DefaultLCDCap, StLCDBToA,
+	{Panel_1400x1050, DefaultLCDCap,
 	 0x70, 0x03, VCLK108_2_315,
-	 0x70, 0x44, 0xF8, 0x2F, 0x02, 0x14, 0x0A, 0x02, 0x00,
-	 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
+	 0x70, 0x44, 0xF8, 0x2F,
+	 0x0A, 0xC0, 0x30, 0x10},
 /* LCDCap1600x1200 */
-	{Panel_1600x1200, DefaultLCDCap, LCDToFull,
+	{Panel_1600x1200, DefaultLCDCap,
 	 0xC0, 0x03, VCLK162,
-	 0x5A, 0x23, 0x5A, 0x23, 0x02, 0x14, 0x0A, 0x02, 0x00,
-	 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
+	 0x5A, 0x23, 0x5A, 0x23,
+	 0x0A, 0xC0, 0x30, 0x10},
 /* LCDCap1024x768x75 */
-	{Panel_1024x768x75, DefaultLCDCap, 0, 0x60, 0, VCLK78_75,
-	 0x2B, 0x61, 0x2B, 0x61, 0x02, 0x14, 0x0A, 0x02, 0x00,
-	 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10},
+	{Panel_1024x768x75, DefaultLCDCap, 0x60, 0, VCLK78_75,
+	 0x2B, 0x61, 0x2B, 0x61,
+	 0x0A, 0xC0, 0x28, 0x10},
 /* LCDCap1280x1024x75 */
-	{Panel_1280x1024x75, DefaultLCDCap, StLCDBToA,
+	{Panel_1280x1024x75, DefaultLCDCap,
 	 0x90, 0x03, VCLK135_5,
-	 0x54, 0x42, 0x4A, 0x61, 0x02, 0x14, 0x0A, 0x02, 0x00,
-	 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
+	 0x54, 0x42, 0x4A, 0x61,
+	 0x0A, 0xC0, 0x30, 0x10},
 /* LCDCapDefault */
-	{0xFF, DefaultLCDCap, 0, 0x88, 0x06, VCLK65_315,
-	0x6C, 0xC3, 0x35, 0x62, 0x02, 0x14, 0x0A, 0x02, 0x00,
-	0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10}
+	{0xFF, DefaultLCDCap, 0x88, 0x06, VCLK65_315,
+	0x6C, 0xC3, 0x35, 0x62,
+	0x0A, 0xC0, 0x28, 0x10}
 };
 
 const struct XGI_Ext2Struct XGI330_RefIndex[] = {
diff --git a/drivers/staging/zcache/Kconfig b/drivers/staging/zcache/Kconfig
index 5c37145..d30722f 100644
--- a/drivers/staging/zcache/Kconfig
+++ b/drivers/staging/zcache/Kconfig
@@ -1,5 +1,5 @@
 config ZCACHE
-	bool "Dynamic compression of swap pages and clean pagecache pages"
+	tristate "Dynamic compression of swap pages and clean pagecache pages"
 	depends on CRYPTO=y && SWAP=y && CLEANCACHE && FRONTSWAP
 	select CRYPTO_LZO
 	default n
@@ -10,9 +10,17 @@ config ZCACHE
 	  memory to store clean page cache pages and swap in RAM,
 	  providing a noticeable reduction in disk I/O.
 
+config ZCACHE_DEBUG
+	bool "Enable debug statistics"
+	depends on DEBUG_FS && ZCACHE
+	default n
+	help
+	  This is used to provide an debugfs directory with counters of
+	  how zcache is doing. You probably want to set this to 'N'.
+
 config RAMSTER
-	bool "Cross-machine RAM capacity sharing, aka peer-to-peer tmem"
-	depends on CONFIGFS_FS=y && SYSFS=y && !HIGHMEM && ZCACHE=y
+	tristate "Cross-machine RAM capacity sharing, aka peer-to-peer tmem"
+	depends on CONFIGFS_FS=y && SYSFS=y && !HIGHMEM && ZCACHE
 	depends on NET
 	# must ensure struct page is 8-byte aligned
 	select HAVE_ALIGNED_STRUCT_PAGE if !64BIT
diff --git a/drivers/staging/zcache/Makefile b/drivers/staging/zcache/Makefile
index 4711049..24fd6aa 100644
--- a/drivers/staging/zcache/Makefile
+++ b/drivers/staging/zcache/Makefile
@@ -1,4 +1,5 @@
 zcache-y	:=		zcache-main.o tmem.o zbud.o
+zcache-$(CONFIG_ZCACHE_DEBUG) += debug.o
 zcache-$(CONFIG_RAMSTER)	+=	ramster/ramster.o ramster/r2net.o
 zcache-$(CONFIG_RAMSTER)	+=	ramster/nodemanager.o ramster/tcp.o
 zcache-$(CONFIG_RAMSTER)	+=	ramster/heartbeat.o ramster/masklog.o
diff --git a/drivers/staging/zcache/TODO b/drivers/staging/zcache/TODO
index c1e26d4..d0c18fa 100644
--- a/drivers/staging/zcache/TODO
+++ b/drivers/staging/zcache/TODO
@@ -41,14 +41,10 @@ STATUS/OWNERSHIP
     for 3.9, see https://lkml.org/lkml/2013/2/6/437;
 7. PROTOTYPED as part of "new" zcache; in staging/zcache for 3.9;
     needs more review (plan to discuss at LSF/MM 2013)
-8. IN PROGRESS; owned by Konrad Wilk; v2 recently posted
-   http://lkml.org/lkml/2013/2/1/542
 9. IN PROGRESS; owned by Konrad Wilk; Mel Gorman provided
    great feedback in August 2012 (unfortunately of "old"
    zcache)
-10. Konrad posted series of fixes (that now need rebasing)
-    https://lkml.org/lkml/2013/2/1/566 
-11. NOT DONE; owned by Konrad Wilk
+11. NOT DONE; owned by Konrad Wilk and Bob Liu
 12. TBD (depends on quantity of feedback)
 13. PROPOSED; one suggestion proposed by Dan; needs more ideas/feedback
 14. TBD (depends on feedback)
@@ -65,5 +61,4 @@ ZCACHE FUTURE NEW FUNCTIONALITY
 
 A. Support zsmalloc as an alternative high-density allocator
     (See https://lkml.org/lkml/2013/1/23/511)
-B. Support zero-filled pages more efficiently
-C. Possibly support three zbuds per pageframe when space allows
+B. Possibly support three zbuds per pageframe when space allows
diff --git a/drivers/staging/zcache/debug.c b/drivers/staging/zcache/debug.c
new file mode 100644
index 0000000..daa2691
--- /dev/null
+++ b/drivers/staging/zcache/debug.c
@@ -0,0 +1,107 @@
+#include <linux/atomic.h>
+#include "debug.h"
+
+#ifdef CONFIG_ZCACHE_DEBUG
+#include <linux/debugfs.h>
+
+ssize_t zcache_obj_count;
+ssize_t zcache_obj_count_max;
+ssize_t zcache_objnode_count;
+ssize_t zcache_objnode_count_max;
+u64 zcache_eph_zbytes;
+u64 zcache_eph_zbytes_max;
+u64 zcache_pers_zbytes_max;
+ssize_t zcache_eph_pageframes_max;
+ssize_t zcache_pers_pageframes_max;
+ssize_t zcache_pageframes_alloced;
+ssize_t zcache_pageframes_freed;
+ssize_t zcache_eph_zpages;
+ssize_t zcache_eph_zpages_max;
+ssize_t zcache_pers_zpages_max;
+ssize_t zcache_flush_total;
+ssize_t zcache_flush_found;
+ssize_t zcache_flobj_total;
+ssize_t zcache_flobj_found;
+ssize_t zcache_failed_eph_puts;
+ssize_t zcache_failed_pers_puts;
+ssize_t zcache_failed_getfreepages;
+ssize_t zcache_failed_alloc;
+ssize_t zcache_put_to_flush;
+ssize_t zcache_compress_poor;
+ssize_t zcache_mean_compress_poor;
+ssize_t zcache_eph_ate_tail;
+ssize_t zcache_eph_ate_tail_failed;
+ssize_t zcache_pers_ate_eph;
+ssize_t zcache_pers_ate_eph_failed;
+ssize_t zcache_evicted_eph_zpages;
+ssize_t zcache_evicted_eph_pageframes;
+ssize_t zcache_zero_filled_pages;
+ssize_t zcache_zero_filled_pages_max;
+
+#define ATTR(x)  { .name = #x, .val = &zcache_##x, }
+static struct debug_entry {
+	const char *name;
+	ssize_t *val;
+} attrs[] = {
+	ATTR(obj_count), ATTR(obj_count_max),
+	ATTR(objnode_count), ATTR(objnode_count_max),
+	ATTR(flush_total), ATTR(flush_found),
+	ATTR(flobj_total), ATTR(flobj_found),
+	ATTR(failed_eph_puts), ATTR(failed_pers_puts),
+	ATTR(failed_getfreepages), ATTR(failed_alloc),
+	ATTR(put_to_flush),
+	ATTR(compress_poor), ATTR(mean_compress_poor),
+	ATTR(eph_ate_tail), ATTR(eph_ate_tail_failed),
+	ATTR(pers_ate_eph), ATTR(pers_ate_eph_failed),
+	ATTR(evicted_eph_zpages), ATTR(evicted_eph_pageframes),
+	ATTR(eph_pageframes), ATTR(eph_pageframes_max),
+	ATTR(pers_pageframes), ATTR(pers_pageframes_max),
+	ATTR(eph_zpages), ATTR(eph_zpages_max),
+	ATTR(pers_zpages), ATTR(pers_zpages_max),
+	ATTR(last_active_file_pageframes),
+	ATTR(last_inactive_file_pageframes),
+	ATTR(last_active_anon_pageframes),
+	ATTR(last_inactive_anon_pageframes),
+	ATTR(eph_nonactive_puts_ignored),
+	ATTR(pers_nonactive_puts_ignored),
+	ATTR(zero_filled_pages),
+#ifdef CONFIG_ZCACHE_WRITEBACK
+	ATTR(outstanding_writeback_pages),
+	ATTR(writtenback_pages),
+#endif
+};
+#undef ATTR
+int zcache_debugfs_init(void)
+{
+	unsigned int i;
+	struct dentry *root = debugfs_create_dir("zcache", NULL);
+	if (root == NULL)
+		return -ENXIO;
+
+	for (i = 0; i < ARRAY_SIZE(attrs); i++)
+		if (!debugfs_create_size_t(attrs[i].name, S_IRUGO, root, attrs[i].val))
+			goto out;
+
+	debugfs_create_u64("eph_zbytes", S_IRUGO, root, &zcache_eph_zbytes);
+	debugfs_create_u64("eph_zbytes_max", S_IRUGO, root, &zcache_eph_zbytes_max);
+	debugfs_create_u64("pers_zbytes", S_IRUGO, root, &zcache_pers_zbytes);
+	debugfs_create_u64("pers_zbytes_max", S_IRUGO, root, &zcache_pers_zbytes_max);
+
+	return 0;
+out:
+	return -ENODEV;
+}
+
+/* developers can call this in case of ooms, e.g. to find memory leaks */
+void zcache_dump(void)
+{
+	unsigned int i;
+	for (i = 0; i < ARRAY_SIZE(attrs); i++)
+		pr_debug("zcache: %s=%zu\n", attrs[i].name, *attrs[i].val);
+
+	pr_debug("zcache: eph_zbytes=%llu\n", (unsigned long long)zcache_eph_zbytes);
+	pr_debug("zcache: eph_zbytes_max=%llu\n", (unsigned long long)zcache_eph_zbytes_max);
+	pr_debug("zcache: pers_zbytes=%llu\n", (unsigned long long)zcache_pers_zbytes);
+	pr_debug("zcache: pers_zbytes_max=%llu\n", (unsigned long long)zcache_pers_zbytes_max);
+}
+#endif
diff --git a/drivers/staging/zcache/debug.h b/drivers/staging/zcache/debug.h
new file mode 100644
index 0000000..ddad92f
--- /dev/null
+++ b/drivers/staging/zcache/debug.h
@@ -0,0 +1,248 @@
+#include <linux/bug.h>
+
+#ifdef CONFIG_ZCACHE_DEBUG
+
+/* we try to keep these statistics SMP-consistent */
+extern ssize_t zcache_obj_count;
+static atomic_t zcache_obj_atomic = ATOMIC_INIT(0);
+extern ssize_t zcache_obj_count_max;
+static inline void inc_zcache_obj_count(void)
+{
+	zcache_obj_count = atomic_inc_return(&zcache_obj_atomic);
+	if (zcache_obj_count > zcache_obj_count_max)
+		zcache_obj_count_max = zcache_obj_count;
+}
+static inline void dec_zcache_obj_count(void)
+{
+	zcache_obj_count = atomic_dec_return(&zcache_obj_atomic);
+	BUG_ON(zcache_obj_count < 0);
+};
+extern ssize_t zcache_objnode_count;
+static atomic_t zcache_objnode_atomic = ATOMIC_INIT(0);
+extern ssize_t zcache_objnode_count_max;
+static inline void inc_zcache_objnode_count(void)
+{
+	zcache_objnode_count = atomic_inc_return(&zcache_objnode_atomic);
+	if (zcache_objnode_count > zcache_objnode_count_max)
+		zcache_objnode_count_max = zcache_objnode_count;
+};
+static inline void dec_zcache_objnode_count(void)
+{
+	zcache_objnode_count = atomic_dec_return(&zcache_objnode_atomic);
+	BUG_ON(zcache_objnode_count < 0);
+};
+extern u64 zcache_eph_zbytes;
+static atomic_long_t zcache_eph_zbytes_atomic = ATOMIC_INIT(0);
+extern u64 zcache_eph_zbytes_max;
+static inline void inc_zcache_eph_zbytes(unsigned clen)
+{
+	zcache_eph_zbytes = atomic_long_add_return(clen, &zcache_eph_zbytes_atomic);
+	if (zcache_eph_zbytes > zcache_eph_zbytes_max)
+		zcache_eph_zbytes_max = zcache_eph_zbytes;
+};
+static inline void dec_zcache_eph_zbytes(unsigned zsize)
+{
+	zcache_eph_zbytes = atomic_long_sub_return(zsize, &zcache_eph_zbytes_atomic);
+};
+extern  u64 zcache_pers_zbytes;
+static atomic_long_t zcache_pers_zbytes_atomic = ATOMIC_INIT(0);
+extern u64 zcache_pers_zbytes_max;
+static inline void inc_zcache_pers_zbytes(unsigned clen)
+{
+	zcache_pers_zbytes = atomic_long_add_return(clen, &zcache_pers_zbytes_atomic);
+	if (zcache_pers_zbytes > zcache_pers_zbytes_max)
+		zcache_pers_zbytes_max = zcache_pers_zbytes;
+}
+static inline void dec_zcache_pers_zbytes(unsigned zsize)
+{
+	zcache_pers_zbytes = atomic_long_sub_return(zsize, &zcache_pers_zbytes_atomic);
+}
+extern ssize_t zcache_eph_pageframes;
+static atomic_t zcache_eph_pageframes_atomic = ATOMIC_INIT(0);
+extern ssize_t zcache_eph_pageframes_max;
+static inline void inc_zcache_eph_pageframes(void)
+{
+	zcache_eph_pageframes = atomic_inc_return(&zcache_eph_pageframes_atomic);
+	if (zcache_eph_pageframes > zcache_eph_pageframes_max)
+		zcache_eph_pageframes_max = zcache_eph_pageframes;
+};
+static inline void dec_zcache_eph_pageframes(void)
+{
+	zcache_eph_pageframes = atomic_dec_return(&zcache_eph_pageframes_atomic);
+};
+extern ssize_t zcache_pers_pageframes;
+static atomic_t zcache_pers_pageframes_atomic = ATOMIC_INIT(0);
+extern ssize_t zcache_pers_pageframes_max;
+static inline void inc_zcache_pers_pageframes(void)
+{
+	zcache_pers_pageframes = atomic_inc_return(&zcache_pers_pageframes_atomic);
+	if (zcache_pers_pageframes > zcache_pers_pageframes_max)
+		zcache_pers_pageframes_max = zcache_pers_pageframes;
+}
+static inline void dec_zcache_pers_pageframes(void)
+{
+	zcache_pers_pageframes = atomic_dec_return(&zcache_pers_pageframes_atomic);
+}
+extern ssize_t zcache_pageframes_alloced;
+static atomic_t zcache_pageframes_alloced_atomic = ATOMIC_INIT(0);
+static inline void inc_zcache_pageframes_alloced(void)
+{
+	zcache_pageframes_alloced = atomic_inc_return(&zcache_pageframes_alloced_atomic);
+};
+extern ssize_t zcache_pageframes_freed;
+static atomic_t zcache_pageframes_freed_atomic = ATOMIC_INIT(0);
+static inline void inc_zcache_pageframes_freed(void)
+{
+	zcache_pageframes_freed = atomic_inc_return(&zcache_pageframes_freed_atomic);
+}
+extern ssize_t zcache_eph_zpages;
+static atomic_t zcache_eph_zpages_atomic = ATOMIC_INIT(0);
+extern ssize_t zcache_eph_zpages_max;
+static inline void inc_zcache_eph_zpages(void)
+{
+	zcache_eph_zpages = atomic_inc_return(&zcache_eph_zpages_atomic);
+	if (zcache_eph_zpages > zcache_eph_zpages_max)
+		zcache_eph_zpages_max = zcache_eph_zpages;
+}
+static inline void dec_zcache_eph_zpages(unsigned zpages)
+{
+	zcache_eph_zpages = atomic_sub_return(zpages, &zcache_eph_zpages_atomic);
+}
+extern ssize_t zcache_pers_zpages;
+static atomic_t zcache_pers_zpages_atomic = ATOMIC_INIT(0);
+extern ssize_t zcache_pers_zpages_max;
+static inline void inc_zcache_pers_zpages(void)
+{
+	zcache_pers_zpages = atomic_inc_return(&zcache_pers_zpages_atomic);
+	if (zcache_pers_zpages > zcache_pers_zpages_max)
+		zcache_pers_zpages_max = zcache_pers_zpages;
+}
+static inline void dec_zcache_pers_zpages(unsigned zpages)
+{
+	zcache_pers_zpages = atomic_sub_return(zpages, &zcache_pers_zpages_atomic);
+}
+
+extern ssize_t zcache_zero_filled_pages;
+static atomic_t zcache_zero_filled_pages_atomic = ATOMIC_INIT(0);
+extern ssize_t zcache_zero_filled_pages_max;
+static inline void inc_zcache_zero_filled_pages(void)
+{
+	zcache_zero_filled_pages = atomic_inc_return(
+					&zcache_zero_filled_pages_atomic);
+	if (zcache_zero_filled_pages > zcache_zero_filled_pages_max)
+		zcache_zero_filled_pages_max = zcache_zero_filled_pages;
+}
+static inline void dec_zcache_zero_filled_pages(void)
+{
+	zcache_zero_filled_pages = atomic_dec_return(
+					&zcache_zero_filled_pages_atomic);
+}
+static inline unsigned long curr_pageframes_count(void)
+{
+	return zcache_pageframes_alloced -
+		atomic_read(&zcache_pageframes_freed_atomic) -
+		atomic_read(&zcache_eph_pageframes_atomic) -
+		atomic_read(&zcache_pers_pageframes_atomic);
+};
+/* but for the rest of these, counting races are ok */
+extern ssize_t zcache_flush_total;
+extern ssize_t zcache_flush_found;
+extern ssize_t zcache_flobj_total;
+extern ssize_t zcache_flobj_found;
+extern ssize_t zcache_failed_eph_puts;
+extern ssize_t zcache_failed_pers_puts;
+extern ssize_t zcache_failed_getfreepages;
+extern ssize_t zcache_failed_alloc;
+extern ssize_t zcache_put_to_flush;
+extern ssize_t zcache_compress_poor;
+extern ssize_t zcache_mean_compress_poor;
+extern ssize_t zcache_eph_ate_tail;
+extern ssize_t zcache_eph_ate_tail_failed;
+extern ssize_t zcache_pers_ate_eph;
+extern ssize_t zcache_pers_ate_eph_failed;
+extern ssize_t zcache_evicted_eph_zpages;
+extern ssize_t zcache_evicted_eph_pageframes;
+
+extern ssize_t zcache_last_active_file_pageframes;
+extern ssize_t zcache_last_inactive_file_pageframes;
+extern ssize_t zcache_last_active_anon_pageframes;
+extern ssize_t zcache_last_inactive_anon_pageframes;
+static ssize_t zcache_eph_nonactive_puts_ignored;
+static ssize_t zcache_pers_nonactive_puts_ignored;
+#ifdef CONFIG_ZCACHE_WRITEBACK
+extern ssize_t zcache_writtenback_pages;
+extern ssize_t zcache_outstanding_writeback_pages;
+#endif
+
+static inline void inc_zcache_flush_total(void) { zcache_flush_total ++; };
+static inline void inc_zcache_flush_found(void) { zcache_flush_found ++; };
+static inline void inc_zcache_flobj_total(void) { zcache_flobj_total ++; };
+static inline void inc_zcache_flobj_found(void) { zcache_flobj_found ++; };
+static inline void inc_zcache_failed_eph_puts(void) { zcache_failed_eph_puts ++; };
+static inline void inc_zcache_failed_pers_puts(void) { zcache_failed_pers_puts ++; };
+static inline void inc_zcache_failed_getfreepages(void) { zcache_failed_getfreepages ++; };
+static inline void inc_zcache_failed_alloc(void) { zcache_failed_alloc ++; };
+static inline void inc_zcache_put_to_flush(void) { zcache_put_to_flush ++; };
+static inline void inc_zcache_compress_poor(void) { zcache_compress_poor ++; };
+static inline void inc_zcache_mean_compress_poor(void) { zcache_mean_compress_poor ++; };
+static inline void inc_zcache_eph_ate_tail(void) { zcache_eph_ate_tail ++; };
+static inline void inc_zcache_eph_ate_tail_failed(void) { zcache_eph_ate_tail_failed ++; };
+static inline void inc_zcache_pers_ate_eph(void) { zcache_pers_ate_eph ++; };
+static inline void inc_zcache_pers_ate_eph_failed(void) { zcache_pers_ate_eph_failed ++; };
+static inline void inc_zcache_evicted_eph_zpages(unsigned zpages) { zcache_evicted_eph_zpages += zpages; };
+static inline void inc_zcache_evicted_eph_pageframes(void) { zcache_evicted_eph_pageframes ++; };
+
+static inline void inc_zcache_eph_nonactive_puts_ignored(void) { zcache_eph_nonactive_puts_ignored ++; };
+static inline void inc_zcache_pers_nonactive_puts_ignored(void) { zcache_pers_nonactive_puts_ignored ++; };
+
+int zcache_debugfs_init(void);
+#else
+static inline void inc_zcache_obj_count(void) { };
+static inline void dec_zcache_obj_count(void) { };
+static inline void inc_zcache_objnode_count(void) { };
+static inline void dec_zcache_objnode_count(void) { };
+static inline void inc_zcache_eph_zbytes(unsigned clen) { };
+static inline void dec_zcache_eph_zbytes(unsigned zsize) { };
+static inline void inc_zcache_pers_zbytes(unsigned clen) { };
+static inline void dec_zcache_pers_zbytes(unsigned zsize) { };
+static inline void inc_zcache_eph_pageframes(void) { };
+static inline void dec_zcache_eph_pageframes(void) { };
+static inline void inc_zcache_pers_pageframes(void) { };
+static inline void dec_zcache_pers_pageframes(void) { };
+static inline void inc_zcache_pageframes_alloced(void) { };
+static inline void inc_zcache_pageframes_freed(void) { };
+static inline void inc_zcache_eph_zpages(void) { };
+static inline void dec_zcache_eph_zpages(unsigned zpages) { };
+static inline void inc_zcache_pers_zpages(void) { };
+static inline void dec_zcache_pers_zpages(unsigned zpages) { };
+static inline void inc_zcache_zero_filled_pages(void) { };
+static inline void dec_zcache_zero_filled_pages(void) { };
+static inline unsigned long curr_pageframes_count(void)
+{
+	return 0;
+};
+static inline int zcache_debugfs_init(void)
+{
+	return 0;
+};
+static inline void inc_zcache_flush_total(void) { };
+static inline void inc_zcache_flush_found(void) { };
+static inline void inc_zcache_flobj_total(void) { };
+static inline void inc_zcache_flobj_found(void) { };
+static inline void inc_zcache_failed_eph_puts(void) { };
+static inline void inc_zcache_failed_pers_puts(void) { };
+static inline void inc_zcache_failed_getfreepages(void) { };
+static inline void inc_zcache_failed_alloc(void) { };
+static inline void inc_zcache_put_to_flush(void) { };
+static inline void inc_zcache_compress_poor(void) { };
+static inline void inc_zcache_mean_compress_poor(void) { };
+static inline void inc_zcache_eph_ate_tail(void) { };
+static inline void inc_zcache_eph_ate_tail_failed(void) { };
+static inline void inc_zcache_pers_ate_eph(void) { };
+static inline void inc_zcache_pers_ate_eph_failed(void) { };
+static inline void inc_zcache_evicted_eph_zpages(unsigned zpages) { };
+static inline void inc_zcache_evicted_eph_pageframes(void) { };
+
+static inline void inc_zcache_eph_nonactive_puts_ignored(void) { };
+static inline void inc_zcache_pers_nonactive_puts_ignored(void) { };
+#endif
diff --git a/drivers/staging/zcache/ramster.h b/drivers/staging/zcache/ramster.h
index 1b71aea..e1f91d5 100644
--- a/drivers/staging/zcache/ramster.h
+++ b/drivers/staging/zcache/ramster.h
@@ -11,10 +11,14 @@
 #ifndef _ZCACHE_RAMSTER_H_
 #define _ZCACHE_RAMSTER_H_
 
+#ifdef CONFIG_RAMSTER_MODULE
+#define CONFIG_RAMSTER
+#endif
+
 #ifdef CONFIG_RAMSTER
 #include "ramster/ramster.h"
 #else
-static inline void ramster_init(bool x, bool y, bool z)
+static inline void ramster_init(bool x, bool y, bool z, bool w)
 {
 }
 
diff --git a/drivers/staging/zcache/ramster/nodemanager.c b/drivers/staging/zcache/ramster/nodemanager.c
index c0f4815..2cfe933 100644
--- a/drivers/staging/zcache/ramster/nodemanager.c
+++ b/drivers/staging/zcache/ramster/nodemanager.c
@@ -949,7 +949,7 @@ static void __exit exit_r2nm(void)
 	r2hb_exit();
 }
 
-static int __init init_r2nm(void)
+int r2nm_init(void)
 {
 	int ret = -1;
 
@@ -986,10 +986,11 @@ out_r2hb:
 out:
 	return ret;
 }
+EXPORT_SYMBOL_GPL(r2nm_init);
 
 MODULE_AUTHOR("Oracle");
 MODULE_LICENSE("GPL");
 
-/* module_init(init_r2nm) */
-late_initcall(init_r2nm);
-/* module_exit(exit_r2nm) */
+#ifndef CONFIG_RAMSTER_MODULE
+late_initcall(r2nm_init);
+#endif
diff --git a/drivers/staging/zcache/ramster/ramster.c b/drivers/staging/zcache/ramster/ramster.c
index bf96a1c..5617590 100644
--- a/drivers/staging/zcache/ramster/ramster.c
+++ b/drivers/staging/zcache/ramster/ramster.c
@@ -92,7 +92,7 @@ static ssize_t ramster_remote_page_flushes_failed;
 #include <linux/debugfs.h>
 #define	zdfs	debugfs_create_size_t
 #define	zdfs64	debugfs_create_u64
-static int __init ramster_debugfs_init(void)
+static int ramster_debugfs_init(void)
 {
 	struct dentry *root = debugfs_create_dir("ramster", NULL);
 	if (root == NULL)
@@ -134,6 +134,11 @@ static int __init ramster_debugfs_init(void)
 }
 #undef	zdebugfs
 #undef	zdfs64
+#else
+static inline int ramster_debugfs_init(void)
+{
+	return 0;
+}
 #endif
 
 static LIST_HEAD(ramster_rem_op_list);
@@ -191,6 +196,7 @@ int ramster_do_preload_flnode(struct tmem_pool *pool)
 		kmem_cache_free(ramster_flnode_cache, flnode);
 	return ret;
 }
+EXPORT_SYMBOL_GPL(ramster_do_preload_flnode);
 
 /*
  * Called by the message handler after a (still compressed) page has been
@@ -458,6 +464,7 @@ void *ramster_pampd_free(void *pampd, struct tmem_pool *pool,
 	}
 	return local_pampd;
 }
+EXPORT_SYMBOL_GPL(ramster_pampd_free);
 
 void ramster_count_foreign_pages(bool eph, int count)
 {
@@ -489,6 +496,7 @@ void ramster_count_foreign_pages(bool eph, int count)
 		ramster_foreign_pers_pages = c;
 	}
 }
+EXPORT_SYMBOL_GPL(ramster_count_foreign_pages);
 
 /*
  * For now, just push over a few pages every few seconds to
@@ -674,7 +682,7 @@ requeue:
 	ramster_remotify_queue_delayed_work(HZ);
 }
 
-void __init ramster_remotify_init(void)
+void ramster_remotify_init(void)
 {
 	unsigned long n = 60UL;
 	ramster_remotify_workqueue =
@@ -849,8 +857,10 @@ static bool frontswap_selfshrinking __read_mostly;
 static void selfshrink_process(struct work_struct *work);
 static DECLARE_DELAYED_WORK(selfshrink_worker, selfshrink_process);
 
+#ifndef CONFIG_RAMSTER_MODULE
 /* Enable/disable with kernel boot option. */
 static bool use_frontswap_selfshrink __initdata = true;
+#endif
 
 /*
  * The default values for the following parameters were deemed reasonable
@@ -905,6 +915,7 @@ static void frontswap_selfshrink(void)
 	frontswap_shrink(tgt_frontswap_pages);
 }
 
+#ifndef CONFIG_RAMSTER_MODULE
 static int __init ramster_nofrontswap_selfshrink_setup(char *s)
 {
 	use_frontswap_selfshrink = false;
@@ -912,6 +923,7 @@ static int __init ramster_nofrontswap_selfshrink_setup(char *s)
 }
 
 __setup("noselfshrink", ramster_nofrontswap_selfshrink_setup);
+#endif
 
 static void selfshrink_process(struct work_struct *work)
 {
@@ -930,6 +942,7 @@ void ramster_cpu_up(int cpu)
 	per_cpu(ramster_remoteputmem1, cpu) = p1;
 	per_cpu(ramster_remoteputmem2, cpu) = p2;
 }
+EXPORT_SYMBOL_GPL(ramster_cpu_up);
 
 void ramster_cpu_down(int cpu)
 {
@@ -945,6 +958,7 @@ void ramster_cpu_down(int cpu)
 		kp->flnode = NULL;
 	}
 }
+EXPORT_SYMBOL_GPL(ramster_cpu_down);
 
 void ramster_register_pamops(struct tmem_pamops *pamops)
 {
@@ -955,9 +969,11 @@ void ramster_register_pamops(struct tmem_pamops *pamops)
 	pamops->repatriate = ramster_pampd_repatriate;
 	pamops->repatriate_preload = ramster_pampd_repatriate_preload;
 }
+EXPORT_SYMBOL_GPL(ramster_register_pamops);
 
-void __init ramster_init(bool cleancache, bool frontswap,
-				bool frontswap_exclusive_gets)
+void ramster_init(bool cleancache, bool frontswap,
+				bool frontswap_exclusive_gets,
+				bool frontswap_selfshrink)
 {
 	int ret = 0;
 
@@ -972,10 +988,17 @@ void __init ramster_init(bool cleancache, bool frontswap,
 	if (ret)
 		pr_err("ramster: can't create sysfs for ramster\n");
 	(void)r2net_register_handlers();
+#ifdef CONFIG_RAMSTER_MODULE
+	ret = r2nm_init();
+	if (ret)
+		pr_err("ramster: can't init r2net\n");
+	frontswap_selfshrinking = frontswap_selfshrink;
+#else
+	frontswap_selfshrinking = use_frontswap_selfshrink;
+#endif
 	INIT_LIST_HEAD(&ramster_rem_op_list);
 	ramster_flnode_cache = kmem_cache_create("ramster_flnode",
 				sizeof(struct flushlist_node), 0, 0, NULL);
-	frontswap_selfshrinking = use_frontswap_selfshrink;
 	if (frontswap_selfshrinking) {
 		pr_info("ramster: Initializing frontswap selfshrink driver.\n");
 		schedule_delayed_work(&selfshrink_worker,
@@ -983,3 +1006,4 @@ void __init ramster_init(bool cleancache, bool frontswap,
 	}
 	ramster_remotify_init();
 }
+EXPORT_SYMBOL_GPL(ramster_init);
diff --git a/drivers/staging/zcache/ramster/ramster.h b/drivers/staging/zcache/ramster/ramster.h
index 12ae56f..6d41a7a 100644
--- a/drivers/staging/zcache/ramster/ramster.h
+++ b/drivers/staging/zcache/ramster/ramster.h
@@ -147,7 +147,7 @@ extern int r2net_register_handlers(void);
 extern int r2net_remote_target_node_set(int);
 
 extern int ramster_remotify_pageframe(bool);
-extern void ramster_init(bool, bool, bool);
+extern void ramster_init(bool, bool, bool, bool);
 extern void ramster_register_pamops(struct tmem_pamops *);
 extern int ramster_localify(int, struct tmem_oid *oidp, uint32_t, char *,
 				unsigned int, void *);
diff --git a/drivers/staging/zcache/ramster/ramster_nodemanager.h b/drivers/staging/zcache/ramster/ramster_nodemanager.h
index 49f879d..dbaae34 100644
--- a/drivers/staging/zcache/ramster/ramster_nodemanager.h
+++ b/drivers/staging/zcache/ramster/ramster_nodemanager.h
@@ -36,4 +36,6 @@
 /* host name, group name, cluster name all 64 bytes */
 #define R2NM_MAX_NAME_LEN        64    /* __NEW_UTS_LEN */
 
+extern int r2nm_init(void);
+
 #endif /* _RAMSTER_NODEMANAGER_H */
diff --git a/drivers/staging/zcache/tmem.c b/drivers/staging/zcache/tmem.c
index a2b7e03..d7e51e4 100644
--- a/drivers/staging/zcache/tmem.c
+++ b/drivers/staging/zcache/tmem.c
@@ -35,7 +35,8 @@
 #include <linux/list.h>
 #include <linux/spinlock.h>
 #include <linux/atomic.h>
-#ifdef CONFIG_RAMSTER
+#include <linux/export.h>
+#if defined(CONFIG_RAMSTER) || defined(CONFIG_RAMSTER_MODULE)
 #include <linux/delay.h>
 #endif
 
@@ -641,6 +642,7 @@ void *tmem_localify_get_pampd(struct tmem_pool *pool, struct tmem_oid *oidp,
 	/* note, hashbucket remains locked */
 	return pampd;
 }
+EXPORT_SYMBOL_GPL(tmem_localify_get_pampd);
 
 void tmem_localify_finish(struct tmem_obj *obj, uint32_t index,
 			  void *pampd, void *saved_hb, bool delete)
@@ -658,6 +660,7 @@ void tmem_localify_finish(struct tmem_obj *obj, uint32_t index,
 	}
 	spin_unlock(&hb->lock);
 }
+EXPORT_SYMBOL_GPL(tmem_localify_finish);
 
 /*
  * For ramster only.  Helper function to support asynchronous tmem_get.
@@ -719,6 +722,7 @@ out:
 	spin_unlock(&hb->lock);
 	return ret;
 }
+EXPORT_SYMBOL_GPL(tmem_replace);
 #endif
 
 /*
diff --git a/drivers/staging/zcache/tmem.h b/drivers/staging/zcache/tmem.h
index adbe5a8..d128ce2 100644
--- a/drivers/staging/zcache/tmem.h
+++ b/drivers/staging/zcache/tmem.h
@@ -126,7 +126,7 @@ static inline unsigned tmem_oid_hash(struct tmem_oid *oidp)
 				TMEM_HASH_BUCKET_BITS);
 }
 
-#ifdef CONFIG_RAMSTER
+#if defined(CONFIG_RAMSTER) || defined(CONFIG_RAMSTER_MODULE)
 struct tmem_xhandle {
 	uint8_t client_id;
 	uint8_t xh_data_cksum;
@@ -171,7 +171,7 @@ struct tmem_obj {
 	unsigned int objnode_tree_height;
 	unsigned long objnode_count;
 	long pampd_count;
-#ifdef CONFIG_RAMSTER
+#if defined(CONFIG_RAMSTER) || defined(CONFIG_RAMSTER_MODULE)
 	/*
 	 * for current design of ramster, all pages belonging to
 	 * an object reside on the same remotenode and extra is
@@ -215,7 +215,7 @@ struct tmem_pamops {
 				uint32_t);
 	void (*free)(void *, struct tmem_pool *,
 				struct tmem_oid *, uint32_t, bool);
-#ifdef CONFIG_RAMSTER
+#if defined(CONFIG_RAMSTER) || defined(CONFIG_RAMSTER_MODULE)
 	void (*new_obj)(struct tmem_obj *);
 	void (*free_obj)(struct tmem_pool *, struct tmem_obj *, bool);
 	void *(*repatriate_preload)(void *, struct tmem_pool *,
@@ -247,7 +247,7 @@ extern int tmem_flush_page(struct tmem_pool *, struct tmem_oid *,
 extern int tmem_flush_object(struct tmem_pool *, struct tmem_oid *);
 extern int tmem_destroy_pool(struct tmem_pool *);
 extern void tmem_new_pool(struct tmem_pool *, uint32_t);
-#ifdef CONFIG_RAMSTER
+#if defined(CONFIG_RAMSTER) || defined(CONFIG_RAMSTER_MODULE)
 extern int tmem_replace(struct tmem_pool *, struct tmem_oid *, uint32_t index,
 			void *);
 extern void *tmem_localify_get_pampd(struct tmem_pool *, struct tmem_oid *,
diff --git a/drivers/staging/zcache/zbud.c b/drivers/staging/zcache/zbud.c
index fdff5c6..6cda4ed 100644
--- a/drivers/staging/zcache/zbud.c
+++ b/drivers/staging/zcache/zbud.c
@@ -342,6 +342,11 @@ static int zbud_debugfs_init(void)
 }
 #undef	zdfs
 #undef	zdfs64
+#else
+static inline int zbud_debugfs_init(void)
+{
+	return 0;
+}
 #endif
 
 /* protects the buddied list and all unbuddied lists */
@@ -1051,9 +1056,7 @@ void zbud_init(void)
 {
 	int i;
 
-#ifdef CONFIG_DEBUG_FS
 	zbud_debugfs_init();
-#endif
 	BUG_ON((sizeof(struct tmem_handle) * 2 > CHUNK_SIZE));
 	BUG_ON(sizeof(struct zbudpage) > sizeof(struct page));
 	for (i = 0; i < NCHUNKS; i++) {
diff --git a/drivers/staging/zcache/zcache-main.c b/drivers/staging/zcache/zcache-main.c
index 328898e..fed553c 100644
--- a/drivers/staging/zcache/zcache-main.c
+++ b/drivers/staging/zcache/zcache-main.c
@@ -19,6 +19,7 @@
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/types.h>
+#include <linux/string.h>
 #include <linux/atomic.h>
 #include <linux/math64.h>
 #include <linux/crypto.h>
@@ -33,10 +34,13 @@
 #include "zcache.h"
 #include "zbud.h"
 #include "ramster.h"
+#include "debug.h"
 #ifdef CONFIG_RAMSTER
-static int ramster_enabled;
+static bool ramster_enabled __read_mostly;
+static int disable_frontswap_selfshrink;
 #else
-#define ramster_enabled 0
+#define ramster_enabled false
+#define disable_frontswap_selfshrink 0
 #endif
 
 #ifndef __PG_WAS_ACTIVE
@@ -59,24 +63,32 @@ static inline void frontswap_tmem_exclusive_gets(bool b)
 }
 #endif
 
+/*
+ * mark pampd to special value in order that later
+ * retrieve will identify zero-filled pages
+ */
+#define ZERO_FILLED 0x2
+
 /* enable (or fix code) when Seth's patches are accepted upstream */
 #define zcache_writeback_enabled 0
 
-static int zcache_enabled __read_mostly;
-static int disable_cleancache __read_mostly;
-static int disable_frontswap __read_mostly;
-static int disable_frontswap_ignore_nonactive __read_mostly;
-static int disable_cleancache_ignore_nonactive __read_mostly;
+static bool zcache_enabled __read_mostly;
+static bool disable_cleancache __read_mostly;
+static bool disable_frontswap __read_mostly;
+static bool disable_frontswap_ignore_nonactive __read_mostly;
+static bool disable_cleancache_ignore_nonactive __read_mostly;
 static char *namestr __read_mostly = "zcache";
 
 #define ZCACHE_GFP_MASK \
 	(__GFP_FS | __GFP_NORETRY | __GFP_NOWARN | __GFP_NOMEMALLOC)
 
-MODULE_LICENSE("GPL");
-
 /* crypto API for zcache  */
+#ifdef CONFIG_ZCACHE_MODULE
+static char *zcache_comp_name = "lzo";
+#else
 #define ZCACHE_COMP_NAME_SZ CRYPTO_MAX_ALG_NAME
 static char zcache_comp_name[ZCACHE_COMP_NAME_SZ] __read_mostly;
+#endif
 static struct crypto_comp * __percpu *zcache_comp_pcpu_tfms __read_mostly;
 
 enum comp_op {
@@ -134,196 +146,21 @@ static struct kmem_cache *zcache_obj_cache;
 
 static DEFINE_PER_CPU(struct zcache_preload, zcache_preloads) = { 0, };
 
-/* we try to keep these statistics SMP-consistent */
-static ssize_t zcache_obj_count;
-static atomic_t zcache_obj_atomic = ATOMIC_INIT(0);
-static ssize_t zcache_obj_count_max;
-static ssize_t zcache_objnode_count;
-static atomic_t zcache_objnode_atomic = ATOMIC_INIT(0);
-static ssize_t zcache_objnode_count_max;
-static u64 zcache_eph_zbytes;
-static atomic_long_t zcache_eph_zbytes_atomic = ATOMIC_INIT(0);
-static u64 zcache_eph_zbytes_max;
-static u64 zcache_pers_zbytes;
-static atomic_long_t zcache_pers_zbytes_atomic = ATOMIC_INIT(0);
-static u64 zcache_pers_zbytes_max;
-static ssize_t zcache_eph_pageframes;
-static atomic_t zcache_eph_pageframes_atomic = ATOMIC_INIT(0);
-static ssize_t zcache_eph_pageframes_max;
-static ssize_t zcache_pers_pageframes;
-static atomic_t zcache_pers_pageframes_atomic = ATOMIC_INIT(0);
-static ssize_t zcache_pers_pageframes_max;
-static ssize_t zcache_pageframes_alloced;
-static atomic_t zcache_pageframes_alloced_atomic = ATOMIC_INIT(0);
-static ssize_t zcache_pageframes_freed;
-static atomic_t zcache_pageframes_freed_atomic = ATOMIC_INIT(0);
-static ssize_t zcache_eph_zpages;
-static ssize_t zcache_eph_zpages;
-static atomic_t zcache_eph_zpages_atomic = ATOMIC_INIT(0);
-static ssize_t zcache_eph_zpages_max;
-static ssize_t zcache_pers_zpages;
-static atomic_t zcache_pers_zpages_atomic = ATOMIC_INIT(0);
-static ssize_t zcache_pers_zpages_max;
-
-/* but for the rest of these, counting races are ok */
-static ssize_t zcache_flush_total;
-static ssize_t zcache_flush_found;
-static ssize_t zcache_flobj_total;
-static ssize_t zcache_flobj_found;
-static ssize_t zcache_failed_eph_puts;
-static ssize_t zcache_failed_pers_puts;
-static ssize_t zcache_failed_getfreepages;
-static ssize_t zcache_failed_alloc;
-static ssize_t zcache_put_to_flush;
-static ssize_t zcache_compress_poor;
-static ssize_t zcache_mean_compress_poor;
-static ssize_t zcache_eph_ate_tail;
-static ssize_t zcache_eph_ate_tail_failed;
-static ssize_t zcache_pers_ate_eph;
-static ssize_t zcache_pers_ate_eph_failed;
-static ssize_t zcache_evicted_eph_zpages;
-static ssize_t zcache_evicted_eph_pageframes;
-static ssize_t zcache_last_active_file_pageframes;
-static ssize_t zcache_last_inactive_file_pageframes;
-static ssize_t zcache_last_active_anon_pageframes;
-static ssize_t zcache_last_inactive_anon_pageframes;
-static ssize_t zcache_eph_nonactive_puts_ignored;
-static ssize_t zcache_pers_nonactive_puts_ignored;
-static ssize_t zcache_writtenback_pages;
-static ssize_t zcache_outstanding_writeback_pages;
-
-#ifdef CONFIG_DEBUG_FS
-#include <linux/debugfs.h>
-#define	zdfs	debugfs_create_size_t
-#define	zdfs64	debugfs_create_u64
-static int zcache_debugfs_init(void)
-{
-	struct dentry *root = debugfs_create_dir("zcache", NULL);
-	if (root == NULL)
-		return -ENXIO;
-
-	zdfs("obj_count", S_IRUGO, root, &zcache_obj_count);
-	zdfs("obj_count_max", S_IRUGO, root, &zcache_obj_count_max);
-	zdfs("objnode_count", S_IRUGO, root, &zcache_objnode_count);
-	zdfs("objnode_count_max", S_IRUGO, root, &zcache_objnode_count_max);
-	zdfs("flush_total", S_IRUGO, root, &zcache_flush_total);
-	zdfs("flush_found", S_IRUGO, root, &zcache_flush_found);
-	zdfs("flobj_total", S_IRUGO, root, &zcache_flobj_total);
-	zdfs("flobj_found", S_IRUGO, root, &zcache_flobj_found);
-	zdfs("failed_eph_puts", S_IRUGO, root, &zcache_failed_eph_puts);
-	zdfs("failed_pers_puts", S_IRUGO, root, &zcache_failed_pers_puts);
-	zdfs("failed_get_free_pages", S_IRUGO, root,
-				&zcache_failed_getfreepages);
-	zdfs("failed_alloc", S_IRUGO, root, &zcache_failed_alloc);
-	zdfs("put_to_flush", S_IRUGO, root, &zcache_put_to_flush);
-	zdfs("compress_poor", S_IRUGO, root, &zcache_compress_poor);
-	zdfs("mean_compress_poor", S_IRUGO, root, &zcache_mean_compress_poor);
-	zdfs("eph_ate_tail", S_IRUGO, root, &zcache_eph_ate_tail);
-	zdfs("eph_ate_tail_failed", S_IRUGO, root, &zcache_eph_ate_tail_failed);
-	zdfs("pers_ate_eph", S_IRUGO, root, &zcache_pers_ate_eph);
-	zdfs("pers_ate_eph_failed", S_IRUGO, root, &zcache_pers_ate_eph_failed);
-	zdfs("evicted_eph_zpages", S_IRUGO, root, &zcache_evicted_eph_zpages);
-	zdfs("evicted_eph_pageframes", S_IRUGO, root,
-				&zcache_evicted_eph_pageframes);
-	zdfs("eph_pageframes", S_IRUGO, root, &zcache_eph_pageframes);
-	zdfs("eph_pageframes_max", S_IRUGO, root, &zcache_eph_pageframes_max);
-	zdfs("pers_pageframes", S_IRUGO, root, &zcache_pers_pageframes);
-	zdfs("pers_pageframes_max", S_IRUGO, root, &zcache_pers_pageframes_max);
-	zdfs("eph_zpages", S_IRUGO, root, &zcache_eph_zpages);
-	zdfs("eph_zpages_max", S_IRUGO, root, &zcache_eph_zpages_max);
-	zdfs("pers_zpages", S_IRUGO, root, &zcache_pers_zpages);
-	zdfs("pers_zpages_max", S_IRUGO, root, &zcache_pers_zpages_max);
-	zdfs("last_active_file_pageframes", S_IRUGO, root,
-				&zcache_last_active_file_pageframes);
-	zdfs("last_inactive_file_pageframes", S_IRUGO, root,
-				&zcache_last_inactive_file_pageframes);
-	zdfs("last_active_anon_pageframes", S_IRUGO, root,
-				&zcache_last_active_anon_pageframes);
-	zdfs("last_inactive_anon_pageframes", S_IRUGO, root,
-				&zcache_last_inactive_anon_pageframes);
-	zdfs("eph_nonactive_puts_ignored", S_IRUGO, root,
-				&zcache_eph_nonactive_puts_ignored);
-	zdfs("pers_nonactive_puts_ignored", S_IRUGO, root,
-				&zcache_pers_nonactive_puts_ignored);
-	zdfs64("eph_zbytes", S_IRUGO, root, &zcache_eph_zbytes);
-	zdfs64("eph_zbytes_max", S_IRUGO, root, &zcache_eph_zbytes_max);
-	zdfs64("pers_zbytes", S_IRUGO, root, &zcache_pers_zbytes);
-	zdfs64("pers_zbytes_max", S_IRUGO, root, &zcache_pers_zbytes_max);
-	zdfs("outstanding_writeback_pages", S_IRUGO, root,
-				&zcache_outstanding_writeback_pages);
-	zdfs("writtenback_pages", S_IRUGO, root, &zcache_writtenback_pages);
-	return 0;
-}
-#undef	zdebugfs
-#undef	zdfs64
-#endif
-
-#define ZCACHE_DEBUG
-#ifdef ZCACHE_DEBUG
-/* developers can call this in case of ooms, e.g. to find memory leaks */
-void zcache_dump(void)
-{
-	pr_info("zcache: obj_count=%zd\n", zcache_obj_count);
-	pr_info("zcache: obj_count_max=%zd\n", zcache_obj_count_max);
-	pr_info("zcache: objnode_count=%zd\n", zcache_objnode_count);
-	pr_info("zcache: objnode_count_max=%zd\n", zcache_objnode_count_max);
-	pr_info("zcache: flush_total=%zd\n", zcache_flush_total);
-	pr_info("zcache: flush_found=%zd\n", zcache_flush_found);
-	pr_info("zcache: flobj_total=%zd\n", zcache_flobj_total);
-	pr_info("zcache: flobj_found=%zd\n", zcache_flobj_found);
-	pr_info("zcache: failed_eph_puts=%zd\n", zcache_failed_eph_puts);
-	pr_info("zcache: failed_pers_puts=%zd\n", zcache_failed_pers_puts);
-	pr_info("zcache: failed_get_free_pages=%zd\n",
-				zcache_failed_getfreepages);
-	pr_info("zcache: failed_alloc=%zd\n", zcache_failed_alloc);
-	pr_info("zcache: put_to_flush=%zd\n", zcache_put_to_flush);
-	pr_info("zcache: compress_poor=%zd\n", zcache_compress_poor);
-	pr_info("zcache: mean_compress_poor=%zd\n",
-				zcache_mean_compress_poor);
-	pr_info("zcache: eph_ate_tail=%zd\n", zcache_eph_ate_tail);
-	pr_info("zcache: eph_ate_tail_failed=%zd\n",
-				zcache_eph_ate_tail_failed);
-	pr_info("zcache: pers_ate_eph=%zd\n", zcache_pers_ate_eph);
-	pr_info("zcache: pers_ate_eph_failed=%zd\n",
-				zcache_pers_ate_eph_failed);
-	pr_info("zcache: evicted_eph_zpages=%zd\n", zcache_evicted_eph_zpages);
-	pr_info("zcache: evicted_eph_pageframes=%zd\n",
-				zcache_evicted_eph_pageframes);
-	pr_info("zcache: eph_pageframes=%zd\n", zcache_eph_pageframes);
-	pr_info("zcache: eph_pageframes_max=%zd\n", zcache_eph_pageframes_max);
-	pr_info("zcache: pers_pageframes=%zd\n", zcache_pers_pageframes);
-	pr_info("zcache: pers_pageframes_max=%zd\n",
-				zcache_pers_pageframes_max);
-	pr_info("zcache: eph_zpages=%zd\n", zcache_eph_zpages);
-	pr_info("zcache: eph_zpages_max=%zd\n", zcache_eph_zpages_max);
-	pr_info("zcache: pers_zpages=%zd\n", zcache_pers_zpages);
-	pr_info("zcache: pers_zpages_max=%zd\n", zcache_pers_zpages_max);
-	pr_info("zcache: last_active_file_pageframes=%zd\n",
-				zcache_last_active_file_pageframes);
-	pr_info("zcache: last_inactive_file_pageframes=%zd\n",
-				zcache_last_inactive_file_pageframes);
-	pr_info("zcache: last_active_anon_pageframes=%zd\n",
-				zcache_last_active_anon_pageframes);
-	pr_info("zcache: last_inactive_anon_pageframes=%zd\n",
-				zcache_last_inactive_anon_pageframes);
-	pr_info("zcache: eph_nonactive_puts_ignored=%zd\n",
-				zcache_eph_nonactive_puts_ignored);
-	pr_info("zcache: pers_nonactive_puts_ignored=%zd\n",
-				zcache_pers_nonactive_puts_ignored);
-	pr_info("zcache: eph_zbytes=%llu\n",
-				zcache_eph_zbytes);
-	pr_info("zcache: eph_zbytes_max=%llu\n",
-				zcache_eph_zbytes_max);
-	pr_info("zcache: pers_zbytes=%llu\n",
-				zcache_pers_zbytes);
-	pr_info("zcache: pers_zbytes_max=%llu\n",
-				zcache_pers_zbytes_max);
-	pr_info("zcache: outstanding_writeback_pages=%zd\n",
-				zcache_outstanding_writeback_pages);
-	pr_info("zcache: writtenback_pages=%zd\n", zcache_writtenback_pages);
-}
+/* Used by debug.c */
+ssize_t zcache_pers_zpages;
+u64 zcache_pers_zbytes;
+ssize_t zcache_eph_pageframes;
+ssize_t zcache_pers_pageframes;
+
+/* Used by this code. */
+ssize_t zcache_last_active_file_pageframes;
+ssize_t zcache_last_inactive_file_pageframes;
+ssize_t zcache_last_active_anon_pageframes;
+ssize_t zcache_last_inactive_anon_pageframes;
+#ifdef CONFIG_ZCACHE_WRITEBACK
+ssize_t zcache_writtenback_pages;
+ssize_t zcache_outstanding_writeback_pages;
 #endif
-
 /*
  * zcache core code starts here
  */
@@ -422,18 +259,14 @@ static struct tmem_objnode *zcache_objnode_alloc(struct tmem_pool *pool)
 		}
 	}
 	BUG_ON(objnode == NULL);
-	zcache_objnode_count = atomic_inc_return(&zcache_objnode_atomic);
-	if (zcache_objnode_count > zcache_objnode_count_max)
-		zcache_objnode_count_max = zcache_objnode_count;
+	inc_zcache_objnode_count();
 	return objnode;
 }
 
 static void zcache_objnode_free(struct tmem_objnode *objnode,
 					struct tmem_pool *pool)
 {
-	zcache_objnode_count =
-		atomic_dec_return(&zcache_objnode_atomic);
-	BUG_ON(zcache_objnode_count < 0);
+	dec_zcache_objnode_count();
 	kmem_cache_free(zcache_objnode_cache, objnode);
 }
 
@@ -446,20 +279,49 @@ static struct tmem_obj *zcache_obj_alloc(struct tmem_pool *pool)
 	obj = kp->obj;
 	BUG_ON(obj == NULL);
 	kp->obj = NULL;
-	zcache_obj_count = atomic_inc_return(&zcache_obj_atomic);
-	if (zcache_obj_count > zcache_obj_count_max)
-		zcache_obj_count_max = zcache_obj_count;
+	inc_zcache_obj_count();
 	return obj;
 }
 
 static void zcache_obj_free(struct tmem_obj *obj, struct tmem_pool *pool)
 {
-	zcache_obj_count =
-		atomic_dec_return(&zcache_obj_atomic);
-	BUG_ON(zcache_obj_count < 0);
+	dec_zcache_obj_count();
 	kmem_cache_free(zcache_obj_cache, obj);
 }
 
+/*
+ * Compressing zero-filled pages will waste memory and introduce
+ * serious fragmentation, skip it to avoid overhead.
+ */
+static bool page_is_zero_filled(struct page *p)
+{
+	unsigned int pos;
+	char *page;
+
+	page = kmap_atomic(p);
+	for (pos = 0; pos < PAGE_SIZE / sizeof(*page); pos++) {
+		if (page[pos]) {
+			kunmap_atomic(page);
+			return false;
+		}
+	}
+	kunmap_atomic(page);
+
+	return true;
+}
+
+static void handle_zero_filled_page(void *p)
+{
+	void *user_mem;
+	struct page *page = (struct page *)p;
+
+	user_mem = kmap_atomic(page);
+	memset(user_mem, 0, PAGE_SIZE);
+	kunmap_atomic(user_mem);
+
+	flush_dcache_page(page);
+}
+
 static struct tmem_hostops zcache_hostops = {
 	.obj_alloc = zcache_obj_alloc,
 	.obj_free = zcache_obj_free,
@@ -472,8 +334,7 @@ static struct page *zcache_alloc_page(void)
 	struct page *page = alloc_page(ZCACHE_GFP_MASK);
 
 	if (page != NULL)
-		zcache_pageframes_alloced =
-			atomic_inc_return(&zcache_pageframes_alloced_atomic);
+		inc_zcache_pageframes_alloced();
 	return page;
 }
 
@@ -485,17 +346,13 @@ static void zcache_free_page(struct page *page)
 	if (page == NULL)
 		BUG();
 	__free_page(page);
-	zcache_pageframes_freed =
-		atomic_inc_return(&zcache_pageframes_freed_atomic);
-	curr_pageframes = zcache_pageframes_alloced -
-			atomic_read(&zcache_pageframes_freed_atomic) -
-			atomic_read(&zcache_eph_pageframes_atomic) -
-			atomic_read(&zcache_pers_pageframes_atomic);
+	inc_zcache_pageframes_freed();
+	curr_pageframes = curr_pageframes_count();
 	if (curr_pageframes > max_pageframes)
 		max_pageframes = curr_pageframes;
 	if (curr_pageframes < min_pageframes)
 		min_pageframes = curr_pageframes;
-#ifdef ZCACHE_DEBUG
+#ifdef CONFIG_ZCACHE_DEBUG
 	if (curr_pageframes > 2L || curr_pageframes < -2L) {
 		/* pr_info here */
 	}
@@ -517,12 +374,20 @@ static void *zcache_pampd_eph_create(char *data, size_t size, bool raw,
 {
 	void *pampd = NULL, *cdata = data;
 	unsigned clen = size;
+	bool zero_filled = false;
 	struct page *page = (struct page *)(data), *newpage;
 
+	if (page_is_zero_filled(page)) {
+		clen = 0;
+		zero_filled = true;
+		inc_zcache_zero_filled_pages();
+		goto got_pampd;
+	}
+
 	if (!raw) {
 		zcache_compress(page, &cdata, &clen);
 		if (clen > zbud_max_buddy_size()) {
-			zcache_compress_poor++;
+			inc_zcache_compress_poor();
 			goto out;
 		}
 	} else {
@@ -539,33 +404,27 @@ static void *zcache_pampd_eph_create(char *data, size_t size, bool raw,
 	if (newpage != NULL)
 		goto create_in_new_page;
 
-	zcache_failed_getfreepages++;
+	inc_zcache_failed_getfreepages();
 	/* can't allocate a page, evict an ephemeral page via LRU */
 	newpage = zcache_evict_eph_pageframe();
 	if (newpage == NULL) {
-		zcache_eph_ate_tail_failed++;
+		inc_zcache_eph_ate_tail_failed();
 		goto out;
 	}
-	zcache_eph_ate_tail++;
+	inc_zcache_eph_ate_tail();
 
 create_in_new_page:
 	pampd = (void *)zbud_create_prep(th, true, cdata, clen, newpage);
 	BUG_ON(pampd == NULL);
-	zcache_eph_pageframes =
-		atomic_inc_return(&zcache_eph_pageframes_atomic);
-	if (zcache_eph_pageframes > zcache_eph_pageframes_max)
-		zcache_eph_pageframes_max = zcache_eph_pageframes;
+	inc_zcache_eph_pageframes();
 
 got_pampd:
-	zcache_eph_zbytes =
-		atomic_long_add_return(clen, &zcache_eph_zbytes_atomic);
-	if (zcache_eph_zbytes > zcache_eph_zbytes_max)
-		zcache_eph_zbytes_max = zcache_eph_zbytes;
-	zcache_eph_zpages = atomic_inc_return(&zcache_eph_zpages_atomic);
-	if (zcache_eph_zpages > zcache_eph_zpages_max)
-		zcache_eph_zpages_max = zcache_eph_zpages;
+	inc_zcache_eph_zbytes(clen);
+	inc_zcache_eph_zpages();
 	if (ramster_enabled && raw)
 		ramster_count_foreign_pages(true, 1);
+	if (zero_filled)
+		pampd = (void *)ZERO_FILLED;
 out:
 	return pampd;
 }
@@ -575,6 +434,7 @@ static void *zcache_pampd_pers_create(char *data, size_t size, bool raw,
 {
 	void *pampd = NULL, *cdata = data;
 	unsigned clen = size;
+	bool zero_filled = false;
 	struct page *page = (struct page *)(data), *newpage;
 	unsigned long zbud_mean_zsize;
 	unsigned long curr_pers_zpages, total_zsize;
@@ -583,13 +443,21 @@ static void *zcache_pampd_pers_create(char *data, size_t size, bool raw,
 		BUG_ON(!ramster_enabled);
 		goto create_pampd;
 	}
+
+	if (page_is_zero_filled(page)) {
+		clen = 0;
+		zero_filled = true;
+		inc_zcache_zero_filled_pages();
+		goto got_pampd;
+	}
+
 	curr_pers_zpages = zcache_pers_zpages;
 /* FIXME CONFIG_RAMSTER... subtract atomic remote_pers_pages here? */
 	if (!raw)
 		zcache_compress(page, &cdata, &clen);
 	/* reject if compression is too poor */
 	if (clen > zbud_max_zsize) {
-		zcache_compress_poor++;
+		inc_zcache_compress_poor();
 		goto out;
 	}
 	/* reject if mean compression is too poor */
@@ -600,7 +468,7 @@ static void *zcache_pampd_pers_create(char *data, size_t size, bool raw,
 		zbud_mean_zsize = div_u64(total_zsize,
 					curr_pers_zpages);
 		if (zbud_mean_zsize > zbud_max_mean_zsize) {
-			zcache_mean_compress_poor++;
+			inc_zcache_mean_compress_poor();
 			goto out;
 		}
 	}
@@ -621,33 +489,27 @@ create_pampd:
 	 * (global_page_state(NR_LRU_BASE + LRU_ACTIVE_FILE) +
 	 * global_page_state(NR_LRU_BASE + LRU_INACTIVE_FILE)))
 	 */
-	zcache_failed_getfreepages++;
+	inc_zcache_failed_getfreepages();
 	/* can't allocate a page, evict an ephemeral page via LRU */
 	newpage = zcache_evict_eph_pageframe();
 	if (newpage == NULL) {
-		zcache_pers_ate_eph_failed++;
+		inc_zcache_pers_ate_eph_failed();
 		goto out;
 	}
-	zcache_pers_ate_eph++;
+	inc_zcache_pers_ate_eph();
 
 create_in_new_page:
 	pampd = (void *)zbud_create_prep(th, false, cdata, clen, newpage);
 	BUG_ON(pampd == NULL);
-	zcache_pers_pageframes =
-		atomic_inc_return(&zcache_pers_pageframes_atomic);
-	if (zcache_pers_pageframes > zcache_pers_pageframes_max)
-		zcache_pers_pageframes_max = zcache_pers_pageframes;
+	inc_zcache_pers_pageframes();
 
 got_pampd:
-	zcache_pers_zpages = atomic_inc_return(&zcache_pers_zpages_atomic);
-	if (zcache_pers_zpages > zcache_pers_zpages_max)
-		zcache_pers_zpages_max = zcache_pers_zpages;
-	zcache_pers_zbytes =
-		atomic_long_add_return(clen, &zcache_pers_zbytes_atomic);
-	if (zcache_pers_zbytes > zcache_pers_zbytes_max)
-		zcache_pers_zbytes_max = zcache_pers_zbytes;
+	inc_zcache_pers_zpages();
+	inc_zcache_pers_zbytes(clen);
 	if (ramster_enabled && raw)
 		ramster_count_foreign_pages(false, 1);
+	if (zero_filled)
+		pampd = (void *)ZERO_FILLED;
 out:
 	return pampd;
 }
@@ -676,7 +538,7 @@ void *zcache_pampd_create(char *data, unsigned int size, bool raw,
 			objnode = kmem_cache_alloc(zcache_objnode_cache,
 							ZCACHE_GFP_MASK);
 			if (unlikely(objnode == NULL)) {
-				zcache_failed_alloc++;
+				inc_zcache_failed_alloc();
 				goto out;
 			}
 			kp->objnodes[i] = objnode;
@@ -687,7 +549,7 @@ void *zcache_pampd_create(char *data, unsigned int size, bool raw,
 		kp->obj = obj;
 	}
 	if (unlikely(kp->obj == NULL)) {
-		zcache_failed_alloc++;
+		inc_zcache_failed_alloc();
 		goto out;
 	}
 	/*
@@ -709,7 +571,8 @@ out:
  */
 void zcache_pampd_create_finish(void *pampd, bool eph)
 {
-	zbud_create_finish((struct zbudref *)pampd, eph);
+	if (pampd != (void *)ZERO_FILLED)
+		zbud_create_finish((struct zbudref *)pampd, eph);
 }
 
 /*
@@ -754,6 +617,14 @@ static int zcache_pampd_get_data(char *data, size_t *sizep, bool raw,
 	BUG_ON(preemptible());
 	BUG_ON(eph);	/* fix later if shared pools get implemented */
 	BUG_ON(pampd_is_remote(pampd));
+
+	if (pampd == (void *)ZERO_FILLED) {
+		handle_zero_filled_page(data);
+		if (!raw)
+			*sizep = PAGE_SIZE;
+		return 0;
+	}
+
 	if (raw)
 		ret = zbud_copy_from_zbud(data, (struct zbudref *)pampd,
 						sizep, eph);
@@ -774,13 +645,25 @@ static int zcache_pampd_get_data_and_free(char *data, size_t *sizep, bool raw,
 					void *pampd, struct tmem_pool *pool,
 					struct tmem_oid *oid, uint32_t index)
 {
-	int ret;
-	bool eph = !is_persistent(pool);
+	int ret = 0;
+	bool eph = !is_persistent(pool), zero_filled = false;
 	struct page *page = NULL;
 	unsigned int zsize, zpages;
 
 	BUG_ON(preemptible());
 	BUG_ON(pampd_is_remote(pampd));
+
+	if (pampd == (void *)ZERO_FILLED) {
+		handle_zero_filled_page(data);
+		zero_filled = true;
+		zsize = 0;
+		zpages = 1;
+		if (!raw)
+			*sizep = PAGE_SIZE;
+		dec_zcache_zero_filled_pages();
+		goto zero_fill;
+	}
+
 	if (raw)
 		ret = zbud_copy_from_zbud(data, (struct zbudref *)pampd,
 						sizep, eph);
@@ -792,26 +675,21 @@ static int zcache_pampd_get_data_and_free(char *data, size_t *sizep, bool raw,
 	}
 	page = zbud_free_and_delist((struct zbudref *)pampd, eph,
 					&zsize, &zpages);
+zero_fill:
 	if (eph) {
 		if (page)
-			zcache_eph_pageframes =
-			    atomic_dec_return(&zcache_eph_pageframes_atomic);
-		zcache_eph_zpages =
-		    atomic_sub_return(zpages, &zcache_eph_zpages_atomic);
-		zcache_eph_zbytes =
-		    atomic_long_sub_return(zsize, &zcache_eph_zbytes_atomic);
+			dec_zcache_eph_pageframes();
+		dec_zcache_eph_zpages(zpages);
+		dec_zcache_eph_zbytes(zsize);
 	} else {
 		if (page)
-			zcache_pers_pageframes =
-			    atomic_dec_return(&zcache_pers_pageframes_atomic);
-		zcache_pers_zpages =
-		    atomic_sub_return(zpages, &zcache_pers_zpages_atomic);
-		zcache_pers_zbytes =
-		    atomic_long_sub_return(zsize, &zcache_pers_zbytes_atomic);
+			dec_zcache_pers_pageframes();
+		dec_zcache_pers_zpages(zpages);
+		dec_zcache_pers_zbytes(zsize);
 	}
 	if (!is_local_client(pool->client))
 		ramster_count_foreign_pages(eph, -1);
-	if (page)
+	if (page && !zero_filled)
 		zcache_free_page(page);
 	return ret;
 }
@@ -825,39 +703,44 @@ static void zcache_pampd_free(void *pampd, struct tmem_pool *pool,
 {
 	struct page *page = NULL;
 	unsigned int zsize, zpages;
+	bool zero_filled = false;
 
 	BUG_ON(preemptible());
-	if (pampd_is_remote(pampd)) {
+
+	if (pampd == (void *)ZERO_FILLED) {
+		zero_filled = true;
+		zsize = 0;
+		zpages = 1;
+		dec_zcache_zero_filled_pages();
+	}
+
+	if (pampd_is_remote(pampd) && !zero_filled) {
 		BUG_ON(!ramster_enabled);
 		pampd = ramster_pampd_free(pampd, pool, oid, index, acct);
 		if (pampd == NULL)
 			return;
 	}
 	if (is_ephemeral(pool)) {
-		page = zbud_free_and_delist((struct zbudref *)pampd,
+		if (!zero_filled)
+			page = zbud_free_and_delist((struct zbudref *)pampd,
 						true, &zsize, &zpages);
 		if (page)
-			zcache_eph_pageframes =
-			    atomic_dec_return(&zcache_eph_pageframes_atomic);
-		zcache_eph_zpages =
-		    atomic_sub_return(zpages, &zcache_eph_zpages_atomic);
-		zcache_eph_zbytes =
-		    atomic_long_sub_return(zsize, &zcache_eph_zbytes_atomic);
+			dec_zcache_eph_pageframes();
+		dec_zcache_eph_zpages(zpages);
+		dec_zcache_eph_zbytes(zsize);
 		/* FIXME CONFIG_RAMSTER... check acct parameter? */
 	} else {
-		page = zbud_free_and_delist((struct zbudref *)pampd,
+		if (!zero_filled)
+			page = zbud_free_and_delist((struct zbudref *)pampd,
 						false, &zsize, &zpages);
 		if (page)
-			zcache_pers_pageframes =
-			    atomic_dec_return(&zcache_pers_pageframes_atomic);
-		zcache_pers_zpages =
-		     atomic_sub_return(zpages, &zcache_pers_zpages_atomic);
-		zcache_pers_zbytes =
-		    atomic_long_sub_return(zsize, &zcache_pers_zbytes_atomic);
+			dec_zcache_pers_pageframes();
+		dec_zcache_pers_zpages(zpages);
+		dec_zcache_pers_zbytes(zsize);
 	}
 	if (!is_local_client(pool->client))
 		ramster_count_foreign_pages(is_ephemeral(pool), -1);
-	if (page)
+	if (page && !zero_filled)
 		zcache_free_page(page);
 }
 
@@ -975,14 +858,11 @@ static struct page *zcache_evict_eph_pageframe(void)
 	page = zbud_evict_pageframe_lru(&zsize, &zpages);
 	if (page == NULL)
 		goto out;
-	zcache_eph_zbytes = atomic_long_sub_return(zsize,
-					&zcache_eph_zbytes_atomic);
-	zcache_eph_zpages = atomic_sub_return(zpages,
-					&zcache_eph_zpages_atomic);
-	zcache_evicted_eph_zpages += zpages;
-	zcache_eph_pageframes =
-		atomic_dec_return(&zcache_eph_pageframes_atomic);
-	zcache_evicted_eph_pageframes++;
+	dec_zcache_eph_zbytes(zsize);
+	dec_zcache_eph_zpages(zpages);
+	inc_zcache_evicted_eph_zpages(zpages);
+	dec_zcache_eph_pageframes();
+	inc_zcache_evicted_eph_pageframes();
 out:
 	return page;
 }
@@ -991,6 +871,16 @@ out:
 
 static atomic_t zcache_outstanding_writeback_pages_atomic = ATOMIC_INIT(0);
 
+static inline void inc_zcache_outstanding_writeback_pages(void)
+{
+	zcache_outstanding_writeback_pages =
+	    atomic_inc_return(&zcache_outstanding_writeback_pages_atomic);
+}
+static inline void dec_zcache_outstanding_writeback_pages(void)
+{
+	zcache_outstanding_writeback_pages =
+	  atomic_dec_return(&zcache_outstanding_writeback_pages_atomic);
+};
 static void unswiz(struct tmem_oid oid, u32 index,
 				unsigned *type, pgoff_t *offset);
 
@@ -1004,8 +894,7 @@ static void unswiz(struct tmem_oid oid, u32 index,
 static void zcache_end_swap_write(struct bio *bio, int err)
 {
 	end_swap_bio_write(bio, err);
-	zcache_outstanding_writeback_pages =
-	  atomic_dec_return(&zcache_outstanding_writeback_pages_atomic);
+	dec_zcache_outstanding_writeback_pages();
 	zcache_writtenback_pages++;
 }
 
@@ -1120,8 +1009,7 @@ static int zcache_frontswap_writeback_zpage(int type, pgoff_t offset,
 	 */
 	(void)__swap_writepage(page, &wbc, zcache_end_swap_write);
 	page_cache_release(page);
-	zcache_outstanding_writeback_pages =
-	    atomic_inc_return(&zcache_outstanding_writeback_pages_atomic);
+	inc_zcache_outstanding_writeback_pages();
 
 	return 0;
 }
@@ -1357,9 +1245,9 @@ int zcache_put_page(int cli_id, int pool_id, struct tmem_oid *oidp,
 		if (pampd == NULL) {
 			ret = -ENOMEM;
 			if (ephemeral)
-				zcache_failed_eph_puts++;
+				inc_zcache_failed_eph_puts();
 			else
-				zcache_failed_pers_puts++;
+				inc_zcache_failed_pers_puts();
 		} else {
 			if (ramster_enabled)
 				ramster_do_preload_flnode(pool);
@@ -1369,7 +1257,7 @@ int zcache_put_page(int cli_id, int pool_id, struct tmem_oid *oidp,
 		}
 		zcache_put_pool(pool);
 	} else {
-		zcache_put_to_flush++;
+		inc_zcache_put_to_flush();
 		if (ramster_enabled)
 			ramster_do_preload_flnode(pool);
 		if (atomic_read(&pool->obj_count) > 0)
@@ -1419,7 +1307,7 @@ int zcache_flush_page(int cli_id, int pool_id,
 	unsigned long flags;
 
 	local_irq_save(flags);
-	zcache_flush_total++;
+	inc_zcache_flush_total();
 	pool = zcache_get_pool_by_id(cli_id, pool_id);
 	if (ramster_enabled)
 		ramster_do_preload_flnode(pool);
@@ -1429,7 +1317,7 @@ int zcache_flush_page(int cli_id, int pool_id,
 		zcache_put_pool(pool);
 	}
 	if (ret >= 0)
-		zcache_flush_found++;
+		inc_zcache_flush_found();
 	local_irq_restore(flags);
 	return ret;
 }
@@ -1442,7 +1330,7 @@ int zcache_flush_object(int cli_id, int pool_id,
 	unsigned long flags;
 
 	local_irq_save(flags);
-	zcache_flobj_total++;
+	inc_zcache_flobj_total();
 	pool = zcache_get_pool_by_id(cli_id, pool_id);
 	if (ramster_enabled)
 		ramster_do_preload_flnode(pool);
@@ -1452,7 +1340,7 @@ int zcache_flush_object(int cli_id, int pool_id,
 		zcache_put_pool(pool);
 	}
 	if (ret >= 0)
-		zcache_flobj_found++;
+		inc_zcache_flobj_found();
 	local_irq_restore(flags);
 	return ret;
 }
@@ -1546,7 +1434,7 @@ static int zcache_local_new_pool(uint32_t flags)
 int zcache_autocreate_pool(unsigned int cli_id, unsigned int pool_id, bool eph)
 {
 	struct tmem_pool *pool;
-	struct zcache_client *cli;
+	struct zcache_client *cli = NULL;
 	uint32_t flags = eph ? 0 : TMEM_POOL_PERSIST;
 	int ret = -1;
 
@@ -1615,7 +1503,7 @@ static void zcache_cleancache_put_page(int pool_id,
 	struct tmem_oid oid = *(struct tmem_oid *)&key;
 
 	if (!disable_cleancache_ignore_nonactive && !PageWasActive(page)) {
-		zcache_eph_nonactive_puts_ignored++;
+		inc_zcache_eph_nonactive_puts_ignored();
 		return;
 	}
 	if (likely(ind == index))
@@ -1694,9 +1582,9 @@ static struct cleancache_ops zcache_cleancache_ops = {
 	.init_fs = zcache_cleancache_init_fs
 };
 
-struct cleancache_ops zcache_cleancache_register_ops(void)
+struct cleancache_ops *zcache_cleancache_register_ops(void)
 {
-	struct cleancache_ops old_ops =
+	struct cleancache_ops *old_ops =
 		cleancache_register_ops(&zcache_cleancache_ops);
 
 	return old_ops;
@@ -1744,7 +1632,7 @@ static int zcache_frontswap_put_page(unsigned type, pgoff_t offset,
 
 	BUG_ON(!PageLocked(page));
 	if (!disable_frontswap_ignore_nonactive && !PageWasActive(page)) {
-		zcache_pers_nonactive_puts_ignored++;
+		inc_zcache_pers_nonactive_puts_ignored();
 		ret = -ERANGE;
 		goto out;
 	}
@@ -1825,9 +1713,9 @@ static struct frontswap_ops zcache_frontswap_ops = {
 	.init = zcache_frontswap_init
 };
 
-struct frontswap_ops zcache_frontswap_register_ops(void)
+struct frontswap_ops *zcache_frontswap_register_ops(void)
 {
-	struct frontswap_ops old_ops =
+	struct frontswap_ops *old_ops =
 		frontswap_register_ops(&zcache_frontswap_ops);
 
 	return old_ops;
@@ -1839,18 +1727,19 @@ struct frontswap_ops zcache_frontswap_register_ops(void)
  * OR NOTHING HAPPENS!
  */
 
+#ifndef CONFIG_ZCACHE_MODULE
 static int __init enable_zcache(char *s)
 {
-	zcache_enabled = 1;
+	zcache_enabled = true;
 	return 1;
 }
 __setup("zcache", enable_zcache);
 
 static int __init enable_ramster(char *s)
 {
-	zcache_enabled = 1;
+	zcache_enabled = true;
 #ifdef CONFIG_RAMSTER
-	ramster_enabled = 1;
+	ramster_enabled = true;
 #endif
 	return 1;
 }
@@ -1860,7 +1749,7 @@ __setup("ramster", enable_ramster);
 
 static int __init no_cleancache(char *s)
 {
-	disable_cleancache = 1;
+	disable_cleancache = true;
 	return 1;
 }
 
@@ -1868,7 +1757,7 @@ __setup("nocleancache", no_cleancache);
 
 static int __init no_frontswap(char *s)
 {
-	disable_frontswap = 1;
+	disable_frontswap = true;
 	return 1;
 }
 
@@ -1884,7 +1773,7 @@ __setup("nofrontswapexclusivegets", no_frontswap_exclusive_gets);
 
 static int __init no_frontswap_ignore_nonactive(char *s)
 {
-	disable_frontswap_ignore_nonactive = 1;
+	disable_frontswap_ignore_nonactive = true;
 	return 1;
 }
 
@@ -1892,7 +1781,7 @@ __setup("nofrontswapignorenonactive", no_frontswap_ignore_nonactive);
 
 static int __init no_cleancache_ignore_nonactive(char *s)
 {
-	disable_cleancache_ignore_nonactive = 1;
+	disable_cleancache_ignore_nonactive = true;
 	return 1;
 }
 
@@ -1900,23 +1789,32 @@ __setup("nocleancacheignorenonactive", no_cleancache_ignore_nonactive);
 
 static int __init enable_zcache_compressor(char *s)
 {
-	strncpy(zcache_comp_name, s, ZCACHE_COMP_NAME_SZ);
-	zcache_enabled = 1;
+	strlcpy(zcache_comp_name, s, sizeof(zcache_comp_name));
+	zcache_enabled = true;
 	return 1;
 }
 __setup("zcache=", enable_zcache_compressor);
+#endif
 
 
-static int __init zcache_comp_init(void)
+static int zcache_comp_init(void)
 {
 	int ret = 0;
 
 	/* check crypto algorithm */
+#ifdef CONFIG_ZCACHE_MODULE
+	ret = crypto_has_comp(zcache_comp_name, 0, 0);
+	if (!ret) {
+		ret = -1;
+		goto out;
+	}
+#else
 	if (*zcache_comp_name != '\0') {
 		ret = crypto_has_comp(zcache_comp_name, 0, 0);
 		if (!ret)
 			pr_info("zcache: %s not supported\n",
 					zcache_comp_name);
+		goto out;
 	}
 	if (!ret)
 		strcpy(zcache_comp_name, "lzo");
@@ -1925,6 +1823,7 @@ static int __init zcache_comp_init(void)
 		ret = 1;
 		goto out;
 	}
+#endif
 	pr_info("zcache: using %s compressor\n", zcache_comp_name);
 
 	/* alloc percpu transforms */
@@ -1936,17 +1835,18 @@ out:
 	return ret;
 }
 
-static int __init zcache_init(void)
+static int zcache_init(void)
 {
 	int ret = 0;
 
+#ifdef CONFIG_ZCACHE_MODULE
+	zcache_enabled = 1;
+#endif
 	if (ramster_enabled) {
 		namestr = "ramster";
 		ramster_register_pamops(&zcache_pamops);
 	}
-#ifdef CONFIG_DEBUG_FS
 	zcache_debugfs_init();
-#endif
 	if (zcache_enabled) {
 		unsigned int cpu;
 
@@ -1980,40 +1880,62 @@ static int __init zcache_init(void)
 	}
 	zbud_init();
 	if (zcache_enabled && !disable_cleancache) {
-		struct cleancache_ops old_ops;
+		struct cleancache_ops *old_ops;
 
 		register_shrinker(&zcache_shrinker);
 		old_ops = zcache_cleancache_register_ops();
 		pr_info("%s: cleancache enabled using kernel transcendent "
 			"memory and compression buddies\n", namestr);
-#ifdef ZCACHE_DEBUG
+#ifdef CONFIG_ZCACHE_DEBUG
 		pr_info("%s: cleancache: ignorenonactive = %d\n",
 			namestr, !disable_cleancache_ignore_nonactive);
 #endif
-		if (old_ops.init_fs != NULL)
+		if (old_ops != NULL)
 			pr_warn("%s: cleancache_ops overridden\n", namestr);
 	}
 	if (zcache_enabled && !disable_frontswap) {
-		struct frontswap_ops old_ops;
+		struct frontswap_ops *old_ops;
 
 		old_ops = zcache_frontswap_register_ops();
 		if (frontswap_has_exclusive_gets)
 			frontswap_tmem_exclusive_gets(true);
 		pr_info("%s: frontswap enabled using kernel transcendent "
 			"memory and compression buddies\n", namestr);
-#ifdef ZCACHE_DEBUG
+#ifdef CONFIG_ZCACHE_DEBUG
 		pr_info("%s: frontswap: excl gets = %d active only = %d\n",
 			namestr, frontswap_has_exclusive_gets,
 			!disable_frontswap_ignore_nonactive);
 #endif
-		if (old_ops.init != NULL)
+		if (IS_ERR(old_ops) || old_ops) {
+			if (IS_ERR(old_ops))
+				return PTR_RET(old_ops);
 			pr_warn("%s: frontswap_ops overridden\n", namestr);
+		}
 	}
 	if (ramster_enabled)
 		ramster_init(!disable_cleancache, !disable_frontswap,
-				frontswap_has_exclusive_gets);
+				frontswap_has_exclusive_gets,
+				!disable_frontswap_selfshrink);
 out:
 	return ret;
 }
 
+#ifdef CONFIG_ZCACHE_MODULE
+#ifdef CONFIG_RAMSTER
+module_param(ramster_enabled, int, S_IRUGO);
+module_param(disable_frontswap_selfshrink, int, S_IRUGO);
+#endif
+module_param(disable_cleancache, int, S_IRUGO);
+module_param(disable_frontswap, int, S_IRUGO);
+#ifdef FRONTSWAP_HAS_EXCLUSIVE_GETS
+module_param(frontswap_has_exclusive_gets, bool, S_IRUGO);
+#endif
+module_param(disable_frontswap_ignore_nonactive, int, S_IRUGO);
+module_param(zcache_comp_name, charp, S_IRUGO);
+module_init(zcache_init);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Dan Magenheimer <dan.magenheimer@oracle.com>");
+MODULE_DESCRIPTION("In-kernel compression of cleancache/frontswap pages");
+#else
 late_initcall(zcache_init);
+#endif
diff --git a/drivers/staging/zcache/zcache.h b/drivers/staging/zcache/zcache.h
index 81722b3..8491200 100644
--- a/drivers/staging/zcache/zcache.h
+++ b/drivers/staging/zcache/zcache.h
@@ -39,7 +39,7 @@ extern int zcache_flush_page(int, int, struct tmem_oid *, uint32_t);
 extern int zcache_flush_object(int, int, struct tmem_oid *);
 extern void zcache_decompress_to_page(char *, unsigned int, struct page *);
 
-#ifdef CONFIG_RAMSTER
+#if defined(CONFIG_RAMSTER) || defined(CONFIG_RAMSTER_MODULE)
 extern void *zcache_pampd_create(char *, unsigned int, bool, int,
 				struct tmem_handle *);
 int zcache_autocreate_pool(unsigned int cli_id, unsigned int pool_id, bool eph);
diff --git a/drivers/staging/zram/zram_drv.c b/drivers/staging/zram/zram_drv.c
index 5918fd7..e34e3fe 100644
--- a/drivers/staging/zram/zram_drv.c
+++ b/drivers/staging/zram/zram_drv.c
@@ -207,11 +207,8 @@ static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec,
 
 	ret = zram_decompress_page(zram, uncmem, 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);
+	if (unlikely(ret != LZO_E_OK))
 		goto out_cleanup;
-	}
 
 	if (is_partial_io(bvec))
 		memcpy(user_mem + bvec->bv_offset, uncmem + offset,
diff --git a/drivers/staging/zsmalloc/Kconfig b/drivers/staging/zsmalloc/Kconfig
index 9084565..7fab032 100644
--- a/drivers/staging/zsmalloc/Kconfig
+++ b/drivers/staging/zsmalloc/Kconfig
@@ -1,5 +1,5 @@
 config ZSMALLOC
-	tristate "Memory allocator for compressed pages"
+	bool "Memory allocator for compressed pages"
 	default n
 	help
 	  zsmalloc is a slab-based memory allocator designed to store
diff --git a/drivers/staging/zsmalloc/zsmalloc-main.c b/drivers/staging/zsmalloc/zsmalloc-main.c
index e78d262..324e123 100644
--- a/drivers/staging/zsmalloc/zsmalloc-main.c
+++ b/drivers/staging/zsmalloc/zsmalloc-main.c
@@ -656,11 +656,8 @@ static inline void __zs_unmap_object(struct mapping_area *area,
 				struct page *pages[2], int off, int size)
 {
 	unsigned long addr = (unsigned long)area->vm_addr;
-	unsigned long end = addr + (PAGE_SIZE * 2);
 
-	flush_cache_vunmap(addr, end);
-	unmap_kernel_range_noflush(addr, PAGE_SIZE * 2);
-	flush_tlb_kernel_range(addr, end);
+	unmap_kernel_range(addr, PAGE_SIZE * 2);
 }
 
 #else /* USE_PGTABLE_MAPPING */
diff --git a/drivers/target/iscsi/Makefile b/drivers/target/iscsi/Makefile
index 5b9a2cf..13a9240 100644
--- a/drivers/target/iscsi/Makefile
+++ b/drivers/target/iscsi/Makefile
@@ -15,6 +15,7 @@ iscsi_target_mod-y +=		iscsi_target_parameters.o \
 				iscsi_target_util.o \
 				iscsi_target.o \
 				iscsi_target_configfs.o \
-				iscsi_target_stat.o
+				iscsi_target_stat.o \
+				iscsi_target_transport.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
index 7ea246a..3948aa1 100644
--- a/drivers/target/iscsi/iscsi_target.c
+++ b/drivers/target/iscsi/iscsi_target.c
@@ -49,6 +49,8 @@
 #include "iscsi_target_device.h"
 #include "iscsi_target_stat.h"
 
+#include <target/iscsi/iscsi_transport.h>
+
 static LIST_HEAD(g_tiqn_list);
 static LIST_HEAD(g_np_list);
 static DEFINE_SPINLOCK(tiqn_lock);
@@ -68,8 +70,7 @@ 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_scsi_req *, u32);
 
 struct iscsi_tiqn *iscsit_get_tiqn_for_login(unsigned char *buf)
 {
@@ -401,8 +402,7 @@ struct iscsi_np *iscsit_add_np(
 	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");
+		np->np_ip, np->np_port, np->np_transport->name);
 
 	return np;
 }
@@ -441,11 +441,10 @@ int iscsit_reset_np_thread(
 	return 0;
 }
 
-static int iscsit_del_np_comm(struct iscsi_np *np)
+static void iscsit_free_np(struct iscsi_np *np)
 {
 	if (np->np_socket)
 		sock_release(np->np_socket);
-	return 0;
 }
 
 int iscsit_del_np(struct iscsi_np *np)
@@ -467,20 +466,47 @@ int iscsit_del_np(struct iscsi_np *np)
 		send_sig(SIGINT, np->np_thread, 1);
 		kthread_stop(np->np_thread);
 	}
-	iscsit_del_np_comm(np);
+
+	np->np_transport->iscsit_free_np(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");
+		np->np_ip, np->np_port, np->np_transport->name);
 
+	iscsit_put_transport(np->np_transport);
 	kfree(np);
 	return 0;
 }
 
+static int iscsit_immediate_queue(struct iscsi_conn *, struct iscsi_cmd *, int);
+static int iscsit_response_queue(struct iscsi_conn *, struct iscsi_cmd *, int);
+
+static int iscsit_queue_rsp(struct iscsi_conn *conn, struct iscsi_cmd *cmd)
+{
+	iscsit_add_cmd_to_response_queue(cmd, cmd->conn, cmd->i_state);
+	return 0;
+}
+
+static struct iscsit_transport iscsi_target_transport = {
+	.name			= "iSCSI/TCP",
+	.transport_type		= ISCSI_TCP,
+	.owner			= NULL,
+	.iscsit_setup_np	= iscsit_setup_np,
+	.iscsit_accept_np	= iscsit_accept_np,
+	.iscsit_free_np		= iscsit_free_np,
+	.iscsit_alloc_cmd	= iscsit_alloc_cmd,
+	.iscsit_get_login_rx	= iscsit_get_login_rx,
+	.iscsit_put_login_tx	= iscsit_put_login_tx,
+	.iscsit_get_dataout	= iscsit_build_r2ts_for_cmd,
+	.iscsit_immediate_queue	= iscsit_immediate_queue,
+	.iscsit_response_queue	= iscsit_response_queue,
+	.iscsit_queue_data_in	= iscsit_queue_rsp,
+	.iscsit_queue_status	= iscsit_queue_rsp,
+};
+
 static int __init iscsi_target_init_module(void)
 {
 	int ret = 0;
@@ -557,6 +583,8 @@ static int __init iscsi_target_init_module(void)
 		goto ooo_out;
 	}
 
+	iscsit_register_transport(&iscsi_target_transport);
+
 	if (iscsit_load_discovery_tpg() < 0)
 		goto r2t_out;
 
@@ -587,6 +615,7 @@ static void __exit iscsi_target_cleanup_module(void)
 	iscsi_deallocate_thread_sets();
 	iscsi_thread_set_free();
 	iscsit_release_discovery_tpg();
+	iscsit_unregister_transport(&iscsi_target_transport);
 	kmem_cache_destroy(lio_cmd_cache);
 	kmem_cache_destroy(lio_qr_cache);
 	kmem_cache_destroy(lio_dr_cache);
@@ -682,11 +711,20 @@ int iscsit_add_reject_from_cmd(
 	iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
 
 	ret = wait_for_completion_interruptible(&cmd->reject_comp);
+	/*
+	 * Perform the kref_put now if se_cmd has already been setup by
+	 * scsit_setup_scsi_cmd()
+	 */
+	if (cmd->se_cmd.se_tfo != NULL) {
+		pr_debug("iscsi reject: calling target_put_sess_cmd >>>>>>\n");
+		target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd);
+	}
 	if (ret != 0)
 		return -1;
 
 	return (!fail_conn) ? 0 : -1;
 }
+EXPORT_SYMBOL(iscsit_add_reject_from_cmd);
 
 /*
  * Map some portion of the allocated scatterlist to an iovec, suitable for
@@ -745,6 +783,9 @@ static void iscsit_ack_from_expstatsn(struct iscsi_conn *conn, u32 exp_statsn)
 
 	conn->exp_statsn = exp_statsn;
 
+	if (conn->sess->sess_ops->RDMAExtensions)
+		return;
+
 	spin_lock_bh(&conn->cmd_lock);
 	list_for_each_entry(cmd, &conn->conn_cmd_list, i_conn_node) {
 		spin_lock(&cmd->istate_lock);
@@ -777,12 +818,10 @@ static int iscsit_allocate_iovecs(struct iscsi_cmd *cmd)
 	return 0;
 }
 
-static int iscsit_handle_scsi_cmd(
-	struct iscsi_conn *conn,
-	unsigned char *buf)
+int iscsit_setup_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
+			  unsigned char *buf)
 {
-	int data_direction, payload_length, cmdsn_ret = 0, immed_ret;
-	struct iscsi_cmd *cmd = NULL;
+	int data_direction, payload_length;
 	struct iscsi_scsi_req *hdr;
 	int iscsi_task_attr;
 	int sam_task_attr;
@@ -805,8 +844,8 @@ static int iscsit_handle_scsi_cmd(
 	    !(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);
+		return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID,
+				1, 1, buf, cmd);
 	}
 
 	if (((hdr->flags & ISCSI_FLAG_CMD_READ) ||
@@ -826,8 +865,8 @@ static int iscsit_handle_scsi_cmd(
 		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);
+		return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID,
+				1, 1, buf, cmd);
 	}
 done:
 
@@ -836,29 +875,29 @@ done:
 		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);
+		return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID,
+				1, 1, buf, cmd);
 	}
 
 	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);
+		return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID,
+				1, 1, buf, cmd);
 	}
 
 	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);
+		return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID,
+				1, 1, buf, cmd);
 	}
 
 	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);
+		return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR,
+				1, 1, buf, cmd);
 	}
 
 	if ((be32_to_cpu(hdr->data_length )== payload_length) &&
@@ -866,43 +905,38 @@ done:
 		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);
+		return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR,
+				1, 1, buf, cmd);
 	}
 
 	if (payload_length > be32_to_cpu(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);
+		return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR,
+				1, 1, buf, cmd);
 	}
 
 	if (payload_length > conn->conn_ops->MaxXmitDataSegmentLength) {
 		pr_err("DataSegmentLength: %u is greater than"
 			" MaxXmitDataSegmentLength: %u, protocol error.\n",
 			payload_length, conn->conn_ops->MaxXmitDataSegmentLength);
-		return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1,
-				buf, conn);
+		return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR,
+				1, 1, buf, cmd);
 	}
 
 	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);
+		return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID,
+				1, 1, buf, cmd);
 	}
 
 	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_cmd(conn, GFP_KERNEL);
-	if (!cmd)
-		return iscsit_add_reject(ISCSI_REASON_BOOKMARK_NO_RESOURCES, 1,
-					 buf, conn);
-
 	cmd->data_direction = data_direction;
 	iscsi_task_attr = hdr->flags & ISCSI_FLAG_CMD_ATTR_MASK;
 	/*
@@ -945,7 +979,8 @@ done:
 	cmd->exp_stat_sn	= be32_to_cpu(hdr->exp_statsn);
 	cmd->first_burst_len	= payload_length;
 
-	if (cmd->data_direction == DMA_FROM_DEVICE) {
+	if (!conn->sess->sess_ops->RDMAExtensions &&
+	     cmd->data_direction == DMA_FROM_DEVICE) {
 		struct iscsi_datain_req *dr;
 
 		dr = iscsit_allocate_datain_req();
@@ -967,7 +1002,10 @@ done:
 
 	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);
+		hdr->cmdsn, be32_to_cpu(hdr->data_length), payload_length,
+		conn->cid);
+
+	target_get_sess_cmd(conn->sess->se_sess, &cmd->se_cmd, true);
 
 	cmd->sense_reason = transport_lookup_cmd_lun(&cmd->se_cmd,
 						     scsilun_to_int(&hdr->lun));
@@ -1001,12 +1039,24 @@ attach_cmd:
 	 */
 	core_alua_check_nonop_delay(&cmd->se_cmd);
 
-	if (iscsit_allocate_iovecs(cmd) < 0) {
-		return iscsit_add_reject_from_cmd(
-				ISCSI_REASON_BOOKMARK_NO_RESOURCES,
-				1, 0, buf, cmd);
-	}
+	return 0;
+}
+EXPORT_SYMBOL(iscsit_setup_scsi_cmd);
+
+void iscsit_set_unsoliticed_dataout(struct iscsi_cmd *cmd)
+{
+	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);
+}
+EXPORT_SYMBOL(iscsit_set_unsoliticed_dataout);
+
+int iscsit_process_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
+			    struct iscsi_scsi_req *hdr)
+{
+	int cmdsn_ret = 0;
 	/*
 	 * Check the CmdSN against ExpCmdSN/MaxCmdSN here if
 	 * the Immediate Bit is not set, and no Immediate
@@ -1024,7 +1074,7 @@ attach_cmd:
 		else if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
 			return iscsit_add_reject_from_cmd(
 				ISCSI_REASON_PROTOCOL_ERROR,
-				1, 0, buf, cmd);
+				1, 0, (unsigned char *)hdr, cmd);
 	}
 
 	iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn));
@@ -1033,13 +1083,8 @@ attach_cmd:
 	 * If no Immediate Data is attached, it's OK to return now.
 	 */
 	if (!cmd->immediate_data) {
-		if (!cmd->sense_reason && 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 (!cmd->sense_reason && cmd->unsolicited_data)
+			iscsit_set_unsoliticed_dataout(cmd);
 
 		return 0;
 	}
@@ -1049,21 +1094,33 @@ attach_cmd:
 	 * thread.  They are processed in CmdSN order by
 	 * iscsit_check_received_cmdsn() below.
 	 */
-	if (cmd->sense_reason) {
-		immed_ret = IMMEDIATE_DATA_NORMAL_OPERATION;
-		goto after_immediate_data;
-	}
+	if (cmd->sense_reason)
+		return 1;
 	/*
 	 * Call directly into transport_generic_new_cmd() to perform
 	 * the backend memory allocation.
 	 */
 	cmd->sense_reason = transport_generic_new_cmd(&cmd->se_cmd);
-	if (cmd->sense_reason) {
-		immed_ret = IMMEDIATE_DATA_NORMAL_OPERATION;
+	if (cmd->sense_reason)
+		return 1;
+
+	return 0;
+}
+EXPORT_SYMBOL(iscsit_process_scsi_cmd);
+
+static int
+iscsit_get_immediate_data(struct iscsi_cmd *cmd, struct iscsi_scsi_req *hdr,
+			  bool dump_payload)
+{
+	int cmdsn_ret = 0, immed_ret = IMMEDIATE_DATA_NORMAL_OPERATION;
+	/*
+	 * Special case for Unsupported SAM WRITE Opcodes and ImmediateData=Yes.
+	 */
+	if (dump_payload == true)
 		goto after_immediate_data;
-	}
 
-	immed_ret = iscsit_handle_immediate_data(cmd, buf, payload_length);
+	immed_ret = iscsit_handle_immediate_data(cmd, hdr,
+					cmd->first_burst_len);
 after_immediate_data:
 	if (immed_ret == IMMEDIATE_DATA_NORMAL_OPERATION) {
 		/*
@@ -1071,26 +1128,19 @@ after_immediate_data:
 		 * 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.
-		 */
+		cmdsn_ret = iscsit_sequence_cmd(cmd->conn, cmd, hdr->cmdsn);
+
 		if (cmd->sense_reason) {
-			if (iscsit_dump_data_payload(conn, payload_length, 1) < 0)
+			if (iscsit_dump_data_payload(cmd->conn,
+					cmd->first_burst_len, 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);
-		}
+		} else if (cmd->unsolicited_data)
+			iscsit_set_unsoliticed_dataout(cmd);
 
 		if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
 			return iscsit_add_reject_from_cmd(
 				ISCSI_REASON_PROTOCOL_ERROR,
-				1, 0, buf, cmd);
+				1, 0, (unsigned char *)hdr, cmd);
 
 	} else if (immed_ret == IMMEDIATE_DATA_ERL1_CRC_FAILURE) {
 		/*
@@ -1105,13 +1155,46 @@ after_immediate_data:
 		 * 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);
+		iscsit_add_cmd_to_immediate_queue(cmd, cmd->conn, cmd->i_state);
 	} else /* immed_ret == IMMEDIATE_DATA_CANNOT_RECOVER */
 		return -1;
 
 	return 0;
 }
 
+int iscsit_handle_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
+			   unsigned char *buf)
+{
+	struct iscsi_scsi_req *hdr = (struct iscsi_scsi_req *)buf;
+	int rc, immed_data;
+	bool dump_payload = false;
+
+	rc = iscsit_setup_scsi_cmd(conn, cmd, buf);
+	if (rc < 0)
+		return rc;
+	/*
+	 * Allocation iovecs needed for struct socket operations for
+	 * traditional iSCSI block I/O.
+	 */
+	if (iscsit_allocate_iovecs(cmd) < 0) {
+		return iscsit_add_reject_from_cmd(
+				ISCSI_REASON_BOOKMARK_NO_RESOURCES,
+				1, 0, buf, cmd);
+	}
+	immed_data = cmd->immediate_data;
+
+	rc = iscsit_process_scsi_cmd(conn, cmd, hdr);
+	if (rc < 0)
+		return rc;
+	else if (rc > 0)
+		dump_payload = true;
+
+	if (!immed_data)
+		return 0;
+
+	return iscsit_get_immediate_data(cmd, hdr, dump_payload);
+}
+
 static u32 iscsit_do_crypto_hash_sg(
 	struct hash_desc *hash,
 	struct iscsi_cmd *cmd,
@@ -1174,20 +1257,16 @@ static void iscsit_do_crypto_hash_buf(
 	crypto_hash_final(hash, data_crc);
 }
 
-static int iscsit_handle_data_out(struct iscsi_conn *conn, unsigned char *buf)
+int
+iscsit_check_dataout_hdr(struct iscsi_conn *conn, unsigned char *buf,
+			  struct iscsi_cmd **out_cmd)
 {
-	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_data *hdr = (struct iscsi_data *)buf;
 	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);
+	u32 payload_length = ntoh24(hdr->dlength);
+	int rc;
 
 	if (!payload_length) {
 		pr_err("DataOUT payload is ZERO, protocol error.\n");
@@ -1220,7 +1299,7 @@ static int iscsit_handle_data_out(struct iscsi_conn *conn, unsigned char *buf)
 
 	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,
+		hdr->itt, hdr->ttt, hdr->datasn, ntohl(hdr->offset),
 		payload_length, conn->cid);
 
 	if (cmd->cmd_flags & ICF_GOT_LAST_DATAOUT) {
@@ -1312,12 +1391,26 @@ static int iscsit_handle_data_out(struct iscsi_conn *conn, unsigned char *buf)
 	 * 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)
+	rc = iscsit_check_pre_dataout(cmd, buf);
+	if (rc == DATAOUT_WITHIN_COMMAND_RECOVERY)
 		return 0;
-	else if (ret == DATAOUT_CANNOT_RECOVER)
+	else if (rc == DATAOUT_CANNOT_RECOVER)
 		return -1;
 
+	*out_cmd = cmd;
+	return 0;
+}
+EXPORT_SYMBOL(iscsit_check_dataout_hdr);
+
+static int
+iscsit_get_dataout(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
+		   struct iscsi_data *hdr)
+{
+	struct kvec *iov;
+	u32 checksum, iov_count = 0, padding = 0, rx_got = 0, rx_size = 0;
+	u32 payload_length = ntoh24(hdr->dlength);
+	int iov_ret, data_crc_failed = 0;
+
 	rx_size += payload_length;
 	iov = &cmd->iov_data[0];
 
@@ -1370,17 +1463,27 @@ static int iscsit_handle_data_out(struct iscsi_conn *conn, unsigned char *buf)
 				payload_length);
 		}
 	}
+
+	return data_crc_failed;
+}
+
+int
+iscsit_check_dataout_payload(struct iscsi_cmd *cmd, struct iscsi_data *hdr,
+			     bool data_crc_failed)
+{
+	struct iscsi_conn *conn = cmd->conn;
+	int rc, ooo_cmdsn;
 	/*
 	 * 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))
+	rc = iscsit_check_post_dataout(cmd, (unsigned char *)hdr, data_crc_failed);
+	if ((rc == DATAOUT_NORMAL) || (rc == DATAOUT_WITHIN_COMMAND_RECOVERY))
 		return 0;
-	else if (ret == DATAOUT_SEND_R2T) {
+	else if (rc == DATAOUT_SEND_R2T) {
 		iscsit_set_dataout_sequence_values(cmd);
-		iscsit_build_r2ts_for_cmd(cmd, conn, false);
-	} else if (ret == DATAOUT_SEND_TO_TRANSPORT) {
+		conn->conn_transport->iscsit_get_dataout(conn, cmd, false);
+	} else if (rc == DATAOUT_SEND_TO_TRANSPORT) {
 		/*
 		 * Handle extra special case for out of order
 		 * Unsolicited Data Out.
@@ -1401,15 +1504,37 @@ static int iscsit_handle_data_out(struct iscsi_conn *conn, unsigned char *buf)
 
 	return 0;
 }
+EXPORT_SYMBOL(iscsit_check_dataout_payload);
 
-static int iscsit_handle_nop_out(
-	struct iscsi_conn *conn,
-	unsigned char *buf)
+static int iscsit_handle_data_out(struct iscsi_conn *conn, unsigned char *buf)
+{
+	struct iscsi_cmd *cmd;
+	struct iscsi_data *hdr = (struct iscsi_data *)buf;
+	int rc;
+	bool data_crc_failed = false;
+
+	rc = iscsit_check_dataout_hdr(conn, buf, &cmd);
+	if (rc < 0)
+		return rc;
+	else if (!cmd)
+		return 0;
+
+	rc = iscsit_get_dataout(conn, cmd, hdr);
+	if (rc < 0)
+		return rc;
+	else if (rc > 0)
+		data_crc_failed = true;
+
+	return iscsit_check_dataout_payload(cmd, hdr, data_crc_failed);
+}
+
+int iscsit_handle_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
+			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;
-	struct iscsi_cmd *cmd = NULL;
+	struct iscsi_cmd *cmd_p = NULL;
 	struct kvec *iov = NULL;
 	struct iscsi_nopout *hdr;
 
@@ -1432,7 +1557,7 @@ static int iscsit_handle_nop_out(
 					buf, conn);
 	}
 
-	pr_debug("Got NOPOUT Ping %s ITT: 0x%08x, TTT: 0x%09x,"
+	pr_debug("Got NOPOUT Ping %s ITT: 0x%08x, TTT: 0x%08x,"
 		" CmdSN: 0x%08x, ExpStatSN: 0x%08x, Length: %u\n",
 		hdr->itt == RESERVED_ITT ? "Response" : "Request",
 		hdr->itt, hdr->ttt, hdr->cmdsn, hdr->exp_statsn,
@@ -1445,7 +1570,6 @@ static int iscsit_handle_nop_out(
 	 * can contain ping data.
 	 */
 	if (hdr->ttt == cpu_to_be32(0xFFFFFFFF)) {
-		cmd = iscsit_allocate_cmd(conn, GFP_KERNEL);
 		if (!cmd)
 			return iscsit_add_reject(
 					ISCSI_REASON_BOOKMARK_NO_RESOURCES,
@@ -1580,14 +1704,14 @@ static int iscsit_handle_nop_out(
 		/*
 		 * This was a response to a unsolicited NOPIN ping.
 		 */
-		cmd = iscsit_find_cmd_from_ttt(conn, be32_to_cpu(hdr->ttt));
-		if (!cmd)
+		cmd_p = iscsit_find_cmd_from_ttt(conn, be32_to_cpu(hdr->ttt));
+		if (!cmd_p)
 			return -1;
 
 		iscsit_stop_nopin_response_timer(conn);
 
-		cmd->i_state = ISTATE_REMOVE;
-		iscsit_add_cmd_to_immediate_queue(cmd, conn, cmd->i_state);
+		cmd_p->i_state = ISTATE_REMOVE;
+		iscsit_add_cmd_to_immediate_queue(cmd_p, conn, cmd_p->i_state);
 		iscsit_start_nopin_timer(conn);
 	} else {
 		/*
@@ -1611,12 +1735,12 @@ ping_out:
 	kfree(ping_data);
 	return ret;
 }
+EXPORT_SYMBOL(iscsit_handle_nop_out);
 
-static int iscsit_handle_task_mgt_cmd(
-	struct iscsi_conn *conn,
-	unsigned char *buf)
+int
+iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
+			   unsigned char *buf)
 {
-	struct iscsi_cmd *cmd;
 	struct se_tmr_req *se_tmr;
 	struct iscsi_tmr_req *tmr_req;
 	struct iscsi_tm *hdr;
@@ -1645,18 +1769,13 @@ static int iscsit_handle_task_mgt_cmd(
 		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);
+		return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR,
+					1, 1, buf, cmd);
 	}
 	if ((function != ISCSI_TM_FUNC_ABORT_TASK) &&
 	    be32_to_cpu(hdr->refcmdsn) != ISCSI_RESERVED_TAG)
 		hdr->refcmdsn = cpu_to_be32(ISCSI_RESERVED_TAG);
 
-	cmd = iscsit_allocate_cmd(conn, GFP_KERNEL);
-	if (!cmd)
-		return iscsit_add_reject(ISCSI_REASON_BOOKMARK_NO_RESOURCES,
-					 1, buf, conn);
-
 	cmd->data_direction = DMA_NONE;
 
 	cmd->tmr_req = kzalloc(sizeof(struct iscsi_tmr_req), GFP_KERNEL);
@@ -1827,6 +1946,7 @@ attach:
 	iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
 	return 0;
 }
+EXPORT_SYMBOL(iscsit_handle_task_mgt_cmd);
 
 /* #warning FIXME: Support Text Command parameters besides SendTargets */
 static int iscsit_handle_text_cmd(
@@ -2089,13 +2209,12 @@ int iscsit_logout_removeconnforrecovery(struct iscsi_cmd *cmd, struct iscsi_conn
 	return 0;
 }
 
-static int iscsit_handle_logout_cmd(
-	struct iscsi_conn *conn,
-	unsigned char *buf)
+int
+iscsit_handle_logout_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
+			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);
 
@@ -2119,14 +2238,10 @@ static int iscsit_handle_logout_cmd(
 	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");
+		iscsit_release_cmd(cmd);
 		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);
@@ -2176,6 +2291,7 @@ static int iscsit_handle_logout_cmd(
 
 	return logout_remove;
 }
+EXPORT_SYMBOL(iscsit_handle_logout_cmd);
 
 static int iscsit_handle_snack(
 	struct iscsi_conn *conn,
@@ -2243,7 +2359,7 @@ static void iscsit_rx_thread_wait_for_tcp(struct iscsi_conn *conn)
 
 static int iscsit_handle_immediate_data(
 	struct iscsi_cmd *cmd,
-	unsigned char *buf,
+	struct iscsi_scsi_req *hdr,
 	u32 length)
 {
 	int iov_ret, rx_got = 0, rx_size = 0;
@@ -2299,12 +2415,12 @@ static int iscsit_handle_immediate_data(
 					" in ERL=0.\n");
 				iscsit_add_reject_from_cmd(
 						ISCSI_REASON_DATA_DIGEST_ERROR,
-						1, 0, buf, cmd);
+						1, 0, (unsigned char *)hdr, cmd);
 				return IMMEDIATE_DATA_CANNOT_RECOVER;
 			} else {
 				iscsit_add_reject_from_cmd(
 						ISCSI_REASON_DATA_DIGEST_ERROR,
-						0, 0, buf, cmd);
+						0, 0, (unsigned char *)hdr, cmd);
 				return IMMEDIATE_DATA_ERL1_CRC_FAILURE;
 			}
 		} else {
@@ -2424,18 +2540,60 @@ static void iscsit_tx_thread_wait_for_tcp(struct iscsi_conn *conn)
 	}
 }
 
-static int iscsit_send_data_in(
-	struct iscsi_cmd *cmd,
-	struct iscsi_conn *conn)
+static void
+iscsit_build_datain_pdu(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
+			struct iscsi_datain *datain, struct iscsi_data_rsp *hdr,
+			bool set_statsn)
 {
-	int iov_ret = 0, set_statsn = 0;
-	u32 iov_count = 0, tx_size = 0;
+	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->se_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->se_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		= cmd->init_task_tag;
+
+	if (hdr->flags & ISCSI_FLAG_DATA_ACK)
+		hdr->ttt		= cpu_to_be32(cmd->targ_xfer_tag);
+	else
+		hdr->ttt		= cpu_to_be32(0xFFFFFFFF);
+	if (set_statsn)
+		hdr->statsn		= cpu_to_be32(cmd->stat_sn);
+	else
+		hdr->statsn		= cpu_to_be32(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);
+
+	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);
+}
+
+static int iscsit_send_datain(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
+{
+	struct iscsi_data_rsp *hdr = (struct iscsi_data_rsp *)&cmd->pdu[0];
 	struct iscsi_datain datain;
 	struct iscsi_datain_req *dr;
-	struct iscsi_data_rsp *hdr;
 	struct kvec *iov;
-	int eodr = 0;
-	int ret;
+	u32 iov_count = 0, tx_size = 0;
+	int eodr = 0, ret, iov_ret;
+	bool set_statsn = false;
 
 	memset(&datain, 0, sizeof(struct iscsi_datain));
 	dr = iscsit_get_datain_values(cmd, &datain);
@@ -2444,7 +2602,6 @@ static int iscsit_send_data_in(
 				cmd->init_task_tag);
 		return -1;
 	}
-
 	/*
 	 * Be paranoid and double check the logic for now.
 	 */
@@ -2452,7 +2609,7 @@ static int iscsit_send_data_in(
 		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->se_cmd.data_length);
+			cmd->se_cmd.data_length);
 		return -1;
 	}
 
@@ -2476,47 +2633,13 @@ static int iscsit_send_data_in(
 		    (dr->dr_complete == DATAIN_COMPLETE_CONNECTION_RECOVERY)) {
 			iscsit_increment_maxcmdsn(cmd, conn->sess);
 			cmd->stat_sn = conn->stat_sn++;
-			set_statsn = 1;
+			set_statsn = true;
 		} 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->se_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->se_cmd.residual_count);
-		}
+			   DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY)
+			set_statsn = true;
 	}
-	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		= cmd->init_task_tag;
-
-	if (hdr->flags & ISCSI_FLAG_DATA_ACK)
-		hdr->ttt		= cpu_to_be32(cmd->targ_xfer_tag);
-	else
-		hdr->ttt		= cpu_to_be32(0xFFFFFFFF);
-	if (set_statsn)
-		hdr->statsn		= cpu_to_be32(cmd->stat_sn);
-	else
-		hdr->statsn		= cpu_to_be32(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);
+	iscsit_build_datain_pdu(cmd, conn, &datain, hdr, set_statsn);
 
 	iov = &cmd->iov_data[0];
 	iov[iov_count].iov_base	= cmd->pdu;
@@ -2527,7 +2650,7 @@ static int iscsit_send_data_in(
 		u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN];
 
 		iscsit_do_crypto_hash_buf(&conn->conn_tx_hash,
-				(unsigned char *)hdr, ISCSI_HDR_LEN,
+				(unsigned char *)cmd->pdu, ISCSI_HDR_LEN,
 				0, NULL, (u8 *)header_digest);
 
 		iov[0].iov_len += ISCSI_CRC_LEN;
@@ -2537,7 +2660,8 @@ static int iscsit_send_data_in(
 			" for DataIN PDU 0x%08x\n", *header_digest);
 	}
 
-	iov_ret = iscsit_map_iovec(cmd, &cmd->iov_data[1], datain.offset, datain.length);
+	iov_ret = iscsit_map_iovec(cmd, &cmd->iov_data[1],
+				datain.offset, datain.length);
 	if (iov_ret < 0)
 		return -1;
 
@@ -2568,11 +2692,6 @@ static int iscsit_send_data_in(
 	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);
-
 	/* sendpage is preferred but can't insert markers */
 	if (!conn->conn_ops->IFMarker)
 		ret = iscsit_fe_sendpage_sg(cmd, conn);
@@ -2595,16 +2714,13 @@ static int iscsit_send_data_in(
 	return eodr;
 }
 
-static int iscsit_send_logout_response(
-	struct iscsi_cmd *cmd,
-	struct iscsi_conn *conn)
+int
+iscsit_build_logout_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
+			struct iscsi_logout_rsp *hdr)
 {
-	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
@@ -2673,9 +2789,6 @@ static int iscsit_send_logout_response(
 		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;
@@ -2687,6 +2800,27 @@ static int iscsit_send_logout_response(
 	hdr->exp_cmdsn		= cpu_to_be32(conn->sess->exp_cmd_sn);
 	hdr->max_cmdsn		= cpu_to_be32(conn->sess->max_cmd_sn);
 
+	pr_debug("Built 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;
+}
+EXPORT_SYMBOL(iscsit_build_logout_rsp);
+
+static int
+iscsit_send_logout(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
+{
+	struct kvec *iov;
+	int niov = 0, tx_size, rc;
+
+	rc = iscsit_build_logout_rsp(cmd, conn,
+			(struct iscsi_logout_rsp *)&cmd->pdu[0]);
+	if (rc < 0)
+		return rc;
+
+	tx_size = ISCSI_HDR_LEN;
 	iov = &cmd->iov_misc[0];
 	iov[niov].iov_base	= cmd->pdu;
 	iov[niov++].iov_len	= ISCSI_HDR_LEN;
@@ -2695,7 +2829,7 @@ static int iscsit_send_logout_response(
 		u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN];
 
 		iscsit_do_crypto_hash_buf(&conn->conn_tx_hash,
-				(unsigned char *)hdr, ISCSI_HDR_LEN,
+				(unsigned char *)&cmd->pdu[0], ISCSI_HDR_LEN,
 				0, NULL, (u8 *)header_digest);
 
 		iov[0].iov_len += ISCSI_CRC_LEN;
@@ -2706,37 +2840,50 @@ static int iscsit_send_logout_response(
 	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)
+void
+iscsit_build_nopin_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
+		       struct iscsi_nopin *hdr, bool nopout_response)
 {
-	int tx_size = ISCSI_HDR_LEN;
-	struct iscsi_nopin *hdr;
-	int ret;
-
-	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);
+	if (nopout_response)
+		put_unaligned_le64(0xFFFFFFFFFFFFFFFFULL, &hdr->lun);
 	hdr->itt		= cmd->init_task_tag;
 	hdr->ttt		= cpu_to_be32(cmd->targ_xfer_tag);
-	cmd->stat_sn		= conn->stat_sn;
+	cmd->stat_sn		= (nopout_response) ? conn->stat_sn++ :
+				  conn->stat_sn;
 	hdr->statsn		= cpu_to_be32(cmd->stat_sn);
+
+	if (nopout_response)
+		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);
 
+	pr_debug("Built NOPIN %s Response ITT: 0x%08x, TTT: 0x%08x,"
+		" StatSN: 0x%08x, Length %u\n", (nopout_response) ?
+		"Solicitied" : "Unsolicitied", cmd->init_task_tag,
+		cmd->targ_xfer_tag, cmd->stat_sn, cmd->buf_ptr_size);
+}
+EXPORT_SYMBOL(iscsit_build_nopin_rsp);
+
+/*
+ *	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)
+{
+	struct iscsi_nopin *hdr = (struct iscsi_nopin *)&cmd->pdu[0];
+	int tx_size = ISCSI_HDR_LEN, ret;
+
+	iscsit_build_nopin_rsp(cmd, conn, hdr, false);
+
 	if (conn->conn_ops->HeaderDigest) {
 		u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN];
 
@@ -2771,31 +2918,17 @@ static int iscsit_send_unsolicited_nopin(
 	return 0;
 }
 
-static int iscsit_send_nopin_response(
-	struct iscsi_cmd *cmd,
-	struct iscsi_conn *conn)
+static int
+iscsit_send_nopin(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
 {
-	int niov = 0, tx_size;
-	u32 padding = 0;
+	struct iscsi_nopin *hdr = (struct iscsi_nopin *)&cmd->pdu[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		= 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);
+	u32 padding = 0;
+	int niov = 0, tx_size;
 
-	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);
+	iscsit_build_nopin_rsp(cmd, conn, hdr, true);
 
+	tx_size = ISCSI_HDR_LEN;
 	iov = &cmd->iov_misc[0];
 	iov[niov].iov_base	= cmd->pdu;
 	iov[niov++].iov_len	= ISCSI_HDR_LEN;
@@ -2851,10 +2984,6 @@ static int iscsit_send_nopin_response(
 	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;
 }
 
@@ -2939,8 +3068,8 @@ static int iscsit_send_r2t(
  *		connection recovery.
  */
 int iscsit_build_r2ts_for_cmd(
-	struct iscsi_cmd *cmd,
 	struct iscsi_conn *conn,
+	struct iscsi_cmd *cmd,
 	bool recovery)
 {
 	int first_r2t = 1;
@@ -3015,24 +3144,16 @@ int iscsit_build_r2ts_for_cmd(
 	return 0;
 }
 
-static int iscsit_send_status(
-	struct iscsi_cmd *cmd,
-	struct iscsi_conn *conn)
+void iscsit_build_rsp_pdu(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
+			bool inc_stat_sn, struct iscsi_scsi_rsp *hdr)
 {
-	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)
+	if (inc_stat_sn)
 		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;
@@ -3052,6 +3173,23 @@ static int iscsit_send_status(
 	hdr->exp_cmdsn		= cpu_to_be32(conn->sess->exp_cmd_sn);
 	hdr->max_cmdsn		= cpu_to_be32(conn->sess->max_cmd_sn);
 
+	pr_debug("Built SCSI Response, ITT: 0x%08x, StatSN: 0x%08x,"
+		" Response: 0x%02x, SAM Status: 0x%02x, CID: %hu\n",
+		cmd->init_task_tag, cmd->stat_sn, cmd->se_cmd.scsi_status,
+		cmd->se_cmd.scsi_status, conn->cid);
+}
+EXPORT_SYMBOL(iscsit_build_rsp_pdu);
+
+static int iscsit_send_response(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
+{
+	struct iscsi_scsi_rsp *hdr = (struct iscsi_scsi_rsp *)&cmd->pdu[0];
+	struct kvec *iov;
+	u32 padding = 0, tx_size = 0;
+	int iov_count = 0;
+	bool inc_stat_sn = (cmd->i_state == ISTATE_SEND_STATUS);
+
+	iscsit_build_rsp_pdu(cmd, conn, inc_stat_sn, hdr);
+
 	iov = &cmd->iov_misc[0];
 	iov[iov_count].iov_base	= cmd->pdu;
 	iov[iov_count++].iov_len = ISCSI_HDR_LEN;
@@ -3106,7 +3244,7 @@ static int iscsit_send_status(
 		u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN];
 
 		iscsit_do_crypto_hash_buf(&conn->conn_tx_hash,
-				(unsigned char *)hdr, ISCSI_HDR_LEN,
+				(unsigned char *)cmd->pdu, ISCSI_HDR_LEN,
 				0, NULL, (u8 *)header_digest);
 
 		iov[0].iov_len += ISCSI_CRC_LEN;
@@ -3118,11 +3256,6 @@ static int iscsit_send_status(
 	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;
 }
 
@@ -3145,16 +3278,12 @@ static u8 iscsit_convert_tcm_tmr_rsp(struct se_tmr_req *se_tmr)
 	}
 }
 
-static int iscsit_send_task_mgt_rsp(
-	struct iscsi_cmd *cmd,
-	struct iscsi_conn *conn)
+void
+iscsit_build_task_mgt_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
+			  struct iscsi_tm_rsp *hdr)
 {
 	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->flags		= ISCSI_FLAG_CMD_FINAL;
 	hdr->response		= iscsit_convert_tcm_tmr_rsp(se_tmr);
@@ -3166,6 +3295,20 @@ static int iscsit_send_task_mgt_rsp(
 	hdr->exp_cmdsn		= cpu_to_be32(conn->sess->exp_cmd_sn);
 	hdr->max_cmdsn		= cpu_to_be32(conn->sess->max_cmd_sn);
 
+	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);
+}
+EXPORT_SYMBOL(iscsit_build_task_mgt_rsp);
+
+static int
+iscsit_send_task_mgt_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
+{
+	struct iscsi_tm_rsp *hdr = (struct iscsi_tm_rsp *)&cmd->pdu[0];
+	u32 tx_size = 0;
+
+	iscsit_build_task_mgt_rsp(cmd, conn, hdr);
+
 	cmd->iov_misc[0].iov_base	= cmd->pdu;
 	cmd->iov_misc[0].iov_len	= ISCSI_HDR_LEN;
 	tx_size += ISCSI_HDR_LEN;
@@ -3186,10 +3329,6 @@ static int iscsit_send_task_mgt_rsp(
 	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;
 }
 
@@ -3385,6 +3524,22 @@ static int iscsit_send_text_rsp(
 	return 0;
 }
 
+void
+iscsit_build_reject(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
+		    struct iscsi_reject *hdr)
+{
+	hdr->opcode		= ISCSI_OP_REJECT;
+	hdr->flags		|= ISCSI_FLAG_CMD_FINAL;
+	hton24(hdr->dlength, ISCSI_HDR_LEN);
+	hdr->ffffffff		= cpu_to_be32(0xffffffff);
+	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);
+
+}
+EXPORT_SYMBOL(iscsit_build_reject);
+
 static int iscsit_send_reject(
 	struct iscsi_cmd *cmd,
 	struct iscsi_conn *conn)
@@ -3393,18 +3548,9 @@ static int iscsit_send_reject(
 	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);
-	hdr->ffffffff		= cpu_to_be32(0xffffffff);
-	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);
+	iscsit_build_reject(cmd, conn, (struct iscsi_reject *)&cmd->pdu[0]);
 
 	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;
@@ -3501,55 +3647,41 @@ static inline void iscsit_thread_check_cpumask(
 	set_cpus_allowed_ptr(p, conn->conn_cpumask);
 }
 
-static int handle_immediate_queue(struct iscsi_conn *conn)
+static int
+iscsit_immediate_queue(struct iscsi_conn *conn, struct iscsi_cmd *cmd, int state)
 {
-	struct iscsi_queue_req *qr;
-	struct iscsi_cmd *cmd;
-	u8 state;
 	int ret;
 
-	while ((qr = iscsit_get_cmd_from_immediate_queue(conn))) {
-		atomic_set(&conn->check_immediate_queue, 0);
-		cmd = qr->cmd;
-		state = qr->state;
-		kmem_cache_free(lio_qr_cache, qr);
-
-		switch (state) {
-		case ISTATE_SEND_R2T:
-			ret = iscsit_send_r2t(cmd, conn);
-			if (ret < 0)
-				goto err;
-			break;
-		case ISTATE_REMOVE:
-			if (cmd->data_direction == DMA_TO_DEVICE)
-				iscsit_stop_dataout_timer(cmd);
-
-			spin_lock_bh(&conn->cmd_lock);
-			list_del(&cmd->i_conn_node);
-			spin_unlock_bh(&conn->cmd_lock);
+	switch (state) {
+	case ISTATE_SEND_R2T:
+		ret = iscsit_send_r2t(cmd, conn);
+		if (ret < 0)
+			goto err;
+		break;
+	case ISTATE_REMOVE:
+		spin_lock_bh(&conn->cmd_lock);
+		list_del(&cmd->i_conn_node);
+		spin_unlock_bh(&conn->cmd_lock);
 
-			iscsit_free_cmd(cmd);
-			continue;
-		case ISTATE_SEND_NOPIN_WANT_RESPONSE:
-			iscsit_mod_nopin_response_timer(conn);
-			ret = iscsit_send_unsolicited_nopin(cmd,
-							    conn, 1);
-			if (ret < 0)
-				goto err;
-			break;
-		case ISTATE_SEND_NOPIN_NO_RESPONSE:
-			ret = iscsit_send_unsolicited_nopin(cmd,
-							    conn, 0);
-			if (ret < 0)
-				goto err;
-			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);
+		iscsit_free_cmd(cmd);
+		break;
+	case ISTATE_SEND_NOPIN_WANT_RESPONSE:
+		iscsit_mod_nopin_response_timer(conn);
+		ret = iscsit_send_unsolicited_nopin(cmd, conn, 1);
+		if (ret < 0)
 			goto err;
-		}
+		break;
+	case ISTATE_SEND_NOPIN_NO_RESPONSE:
+		ret = iscsit_send_unsolicited_nopin(cmd, conn, 0);
+		if (ret < 0)
+			goto err;
+		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);
+		goto err;
 	}
 
 	return 0;
@@ -3558,128 +3690,149 @@ err:
 	return -1;
 }
 
-static int handle_response_queue(struct iscsi_conn *conn)
+static int
+iscsit_handle_immediate_queue(struct iscsi_conn *conn)
 {
+	struct iscsit_transport *t = conn->conn_transport;
 	struct iscsi_queue_req *qr;
 	struct iscsi_cmd *cmd;
 	u8 state;
 	int ret;
 
-	while ((qr = iscsit_get_cmd_from_response_queue(conn))) {
+	while ((qr = iscsit_get_cmd_from_immediate_queue(conn))) {
+		atomic_set(&conn->check_immediate_queue, 0);
 		cmd = qr->cmd;
 		state = qr->state;
 		kmem_cache_free(lio_qr_cache, qr);
 
-check_rsp_state:
-		switch (state) {
-		case ISTATE_SEND_DATAIN:
-			ret = iscsit_send_data_in(cmd, conn);
-			if (ret < 0)
-				goto err;
-			else if (!ret)
-				/* more drs */
-				goto check_rsp_state;
-			else if (ret == 1) {
-				/* all done */
-				spin_lock_bh(&cmd->istate_lock);
-				cmd->i_state = ISTATE_SENT_STATUS;
-				spin_unlock_bh(&cmd->istate_lock);
-
-				if (atomic_read(&conn->check_immediate_queue))
-					return 1;
+		ret = t->iscsit_immediate_queue(conn, cmd, state);
+		if (ret < 0)
+			return ret;
+	}
 
-				continue;
-			} else if (ret == 2) {
-				/* Still must send status,
-				   SCF_TRANSPORT_TASK_SENSE was set */
-				spin_lock_bh(&cmd->istate_lock);
-				cmd->i_state = ISTATE_SEND_STATUS;
-				spin_unlock_bh(&cmd->istate_lock);
-				state = ISTATE_SEND_STATUS;
-				goto check_rsp_state;
-			}
+	return 0;
+}
 
-			break;
-		case ISTATE_SEND_STATUS:
-		case ISTATE_SEND_STATUS_RECOVERY:
-			ret = iscsit_send_status(cmd, conn);
-			break;
-		case ISTATE_SEND_LOGOUTRSP:
-			ret = iscsit_send_logout_response(cmd, conn);
-			break;
-		case ISTATE_SEND_ASYNCMSG:
-			ret = iscsit_send_conn_drop_async_message(
-				cmd, conn);
-			break;
-		case ISTATE_SEND_NOPIN:
-			ret = iscsit_send_nopin_response(cmd, conn);
-			break;
-		case ISTATE_SEND_REJECT:
-			ret = iscsit_send_reject(cmd, conn);
-			break;
-		case ISTATE_SEND_TASKMGTRSP:
-			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:
-			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);
-			goto err;
-		}
+static int
+iscsit_response_queue(struct iscsi_conn *conn, struct iscsi_cmd *cmd, int state)
+{
+	int ret;
+
+check_rsp_state:
+	switch (state) {
+	case ISTATE_SEND_DATAIN:
+		ret = iscsit_send_datain(cmd, conn);
 		if (ret < 0)
 			goto err;
+		else if (!ret)
+			/* more drs */
+			goto check_rsp_state;
+		else if (ret == 1) {
+			/* all done */
+			spin_lock_bh(&cmd->istate_lock);
+			cmd->i_state = ISTATE_SENT_STATUS;
+			spin_unlock_bh(&cmd->istate_lock);
 
-		if (iscsit_send_tx_data(cmd, conn, 1) < 0) {
-			iscsit_tx_thread_wait_for_tcp(conn);
-			iscsit_unmap_iovec(cmd);
-			goto err;
+			if (atomic_read(&conn->check_immediate_queue))
+				return 1;
+
+			return 0;
+		} else if (ret == 2) {
+			/* Still must send status,
+			   SCF_TRANSPORT_TASK_SENSE was set */
+			spin_lock_bh(&cmd->istate_lock);
+			cmd->i_state = ISTATE_SEND_STATUS;
+			spin_unlock_bh(&cmd->istate_lock);
+			state = ISTATE_SEND_STATUS;
+			goto check_rsp_state;
 		}
-		iscsit_unmap_iovec(cmd);
 
-		switch (state) {
-		case ISTATE_SEND_LOGOUTRSP:
-			if (!iscsit_logout_post_handler(cmd, conn))
-				goto restart;
-			/* fall through */
-		case ISTATE_SEND_STATUS:
-		case ISTATE_SEND_ASYNCMSG:
-		case ISTATE_SEND_NOPIN:
-		case ISTATE_SEND_STATUS_RECOVERY:
-		case ISTATE_SEND_TEXTRSP:
-		case ISTATE_SEND_TASKMGTRSP:
+		break;
+	case ISTATE_SEND_STATUS:
+	case ISTATE_SEND_STATUS_RECOVERY:
+		ret = iscsit_send_response(cmd, conn);
+		break;
+	case ISTATE_SEND_LOGOUTRSP:
+		ret = iscsit_send_logout(cmd, conn);
+		break;
+	case ISTATE_SEND_ASYNCMSG:
+		ret = iscsit_send_conn_drop_async_message(
+			cmd, conn);
+		break;
+	case ISTATE_SEND_NOPIN:
+		ret = iscsit_send_nopin(cmd, conn);
+		if (!ret) {
 			spin_lock_bh(&cmd->istate_lock);
 			cmd->i_state = ISTATE_SENT_STATUS;
 			spin_unlock_bh(&cmd->istate_lock);
+			return 0;
+		}
+		break;
+	case ISTATE_SEND_REJECT:
+		ret = iscsit_send_reject(cmd, conn);
+		break;
+	case ISTATE_SEND_TASKMGTRSP:
+		ret = iscsit_send_task_mgt_rsp(cmd, conn);
+		if (ret != 0)
 			break;
-		case ISTATE_SEND_REJECT:
-			if (cmd->cmd_flags & ICF_REJECT_FAIL_CONN) {
-				cmd->cmd_flags &= ~ICF_REJECT_FAIL_CONN;
-				complete(&cmd->reject_comp);
-				goto err;
-			}
+		ret = iscsit_tmr_post_handler(cmd, conn);
+		if (ret != 0)
+			iscsit_fall_back_to_erl0(conn->sess);
+		break;
+	case ISTATE_SEND_TEXTRSP:
+		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);
+		goto err;
+	}
+	if (ret < 0)
+		goto err;
+
+	if (iscsit_send_tx_data(cmd, conn, 1) < 0) {
+		iscsit_tx_thread_wait_for_tcp(conn);
+		iscsit_unmap_iovec(cmd);
+		goto err;
+	}
+	iscsit_unmap_iovec(cmd);
+
+	switch (state) {
+	case ISTATE_SEND_LOGOUTRSP:
+		if (!iscsit_logout_post_handler(cmd, conn))
+			goto restart;
+		/* fall through */
+	case ISTATE_SEND_STATUS:
+	case ISTATE_SEND_ASYNCMSG:
+	case ISTATE_SEND_NOPIN:
+	case ISTATE_SEND_STATUS_RECOVERY:
+	case ISTATE_SEND_TEXTRSP:
+	case ISTATE_SEND_TASKMGTRSP:
+		spin_lock_bh(&cmd->istate_lock);
+		cmd->i_state = ISTATE_SENT_STATUS;
+		spin_unlock_bh(&cmd->istate_lock);
+		break;
+	case ISTATE_SEND_REJECT:
+		if (cmd->cmd_flags & ICF_REJECT_FAIL_CONN) {
+			cmd->cmd_flags &= ~ICF_REJECT_FAIL_CONN;
 			complete(&cmd->reject_comp);
-			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);
 			goto err;
 		}
-
-		if (atomic_read(&conn->check_immediate_queue))
-			return 1;
+		complete(&cmd->reject_comp);
+		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);
+		goto err;
 	}
 
+	if (atomic_read(&conn->check_immediate_queue))
+		return 1;
+
 	return 0;
 
 err:
@@ -3688,6 +3841,27 @@ restart:
 	return -EAGAIN;
 }
 
+static int iscsit_handle_response_queue(struct iscsi_conn *conn)
+{
+	struct iscsit_transport *t = conn->conn_transport;
+	struct iscsi_queue_req *qr;
+	struct iscsi_cmd *cmd;
+	u8 state;
+	int ret;
+
+	while ((qr = iscsit_get_cmd_from_response_queue(conn))) {
+		cmd = qr->cmd;
+		state = qr->state;
+		kmem_cache_free(lio_qr_cache, qr);
+
+		ret = t->iscsit_response_queue(conn, cmd, state);
+		if (ret == 1 || ret < 0)
+			return ret;
+	}
+
+	return 0;
+}
+
 int iscsi_target_tx_thread(void *arg)
 {
 	int ret = 0;
@@ -3722,11 +3896,11 @@ restart:
 			goto transport_err;
 
 get_immediate:
-		ret = handle_immediate_queue(conn);
+		ret = iscsit_handle_immediate_queue(conn);
 		if (ret < 0)
 			goto transport_err;
 
-		ret = handle_response_queue(conn);
+		ret = iscsit_handle_response_queue(conn);
 		if (ret == 1)
 			goto get_immediate;
 		else if (ret == -EAGAIN)
@@ -3742,6 +3916,83 @@ out:
 	return 0;
 }
 
+static int iscsi_target_rx_opcode(struct iscsi_conn *conn, unsigned char *buf)
+{
+	struct iscsi_hdr *hdr = (struct iscsi_hdr *)buf;
+	struct iscsi_cmd *cmd;
+	int ret = 0;
+
+	switch (hdr->opcode & ISCSI_OPCODE_MASK) {
+	case ISCSI_OP_SCSI_CMD:
+		cmd = iscsit_allocate_cmd(conn, GFP_KERNEL);
+		if (!cmd)
+			return iscsit_add_reject(ISCSI_REASON_BOOKMARK_NO_RESOURCES,
+						1, buf, conn);
+
+		ret = iscsit_handle_scsi_cmd(conn, cmd, buf);
+		break;
+	case ISCSI_OP_SCSI_DATA_OUT:
+		ret = iscsit_handle_data_out(conn, buf);
+		break;
+	case ISCSI_OP_NOOP_OUT:
+		cmd = NULL;
+		if (hdr->ttt == cpu_to_be32(0xFFFFFFFF)) {
+			cmd = iscsit_allocate_cmd(conn, GFP_KERNEL);
+			if (!cmd)
+				return iscsit_add_reject(ISCSI_REASON_BOOKMARK_NO_RESOURCES,
+						1, buf, conn);
+		}
+		ret = iscsit_handle_nop_out(conn, cmd, buf);
+		break;
+	case ISCSI_OP_SCSI_TMFUNC:
+		cmd = iscsit_allocate_cmd(conn, GFP_KERNEL);
+		if (!cmd)
+			return iscsit_add_reject(ISCSI_REASON_BOOKMARK_NO_RESOURCES,
+						1, buf, conn);
+
+		ret = iscsit_handle_task_mgt_cmd(conn, cmd, buf);
+		break;
+	case ISCSI_OP_TEXT:
+		ret = iscsit_handle_text_cmd(conn, buf);
+		break;
+	case ISCSI_OP_LOGOUT:
+		cmd = iscsit_allocate_cmd(conn, GFP_KERNEL);
+		if (!cmd)
+			return iscsit_add_reject(ISCSI_REASON_BOOKMARK_NO_RESOURCES,
+						1, buf, conn);
+
+		ret = iscsit_handle_logout_cmd(conn, cmd, buf);
+		if (ret > 0)
+			wait_for_completion_timeout(&conn->conn_logout_comp,
+					SECONDS_FOR_LOGOUT_COMP * HZ);
+		break;
+	case ISCSI_OP_SNACK:
+		ret = iscsit_handle_snack(conn, buf);
+		break;
+	default:
+		pr_err("Got unknown iSCSI OpCode: 0x%02x\n", hdr->opcode);
+		if (!conn->sess->sess_ops->ErrorRecoveryLevel) {
+			pr_err("Cannot recover from unknown"
+			" opcode while ERL=0, closing iSCSI connection.\n");
+			return -1;
+		}
+		if (!conn->conn_ops->OFMarker) {
+			pr_err("Unable to recover from unknown"
+			" opcode while OFMarker=No, closing iSCSI"
+				" connection.\n");
+			return -1;
+		}
+		if (iscsit_recover_from_unknown_opcode(conn) < 0) {
+			pr_err("Unable to recover from unknown"
+				" opcode, closing iSCSI connection.\n");
+			return -1;
+		}
+		break;
+	}
+
+	return ret;
+}
+
 int iscsi_target_rx_thread(void *arg)
 {
 	int ret;
@@ -3761,6 +4012,18 @@ restart:
 	if (!conn)
 		goto out;
 
+	if (conn->conn_transport->transport_type == ISCSI_INFINIBAND) {
+		struct completion comp;
+		int rc;
+
+		init_completion(&comp);
+		rc = wait_for_completion_interruptible(&comp);
+		if (rc < 0)
+			goto transport_err;
+
+		goto out;
+	}
+
 	while (!kthread_should_stop()) {
 		/*
 		 * Ensure that both TX and RX per connection kthreads
@@ -3832,62 +4095,9 @@ restart:
 			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;
-		}
+		ret = iscsi_target_rx_opcode(conn, buffer);
+		if (ret < 0)
+			goto transport_err;
 	}
 
 transport_err:
@@ -4053,6 +4263,12 @@ int iscsit_close_connection(
 
 	if (conn->sock)
 		sock_release(conn->sock);
+
+	if (conn->conn_transport->iscsit_free_conn)
+		conn->conn_transport->iscsit_free_conn(conn);
+
+	iscsit_put_transport(conn->conn_transport);
+
 	conn->thread_set = NULL;
 
 	pr_debug("Moving to TARG_CONN_STATE_FREE.\n");
@@ -4284,7 +4500,7 @@ static void iscsit_logout_post_handler_diffcid(
 /*
  *	Return of 0 causes the TX thread to restart.
  */
-static int iscsit_logout_post_handler(
+int iscsit_logout_post_handler(
 	struct iscsi_cmd *cmd,
 	struct iscsi_conn *conn)
 {
@@ -4342,6 +4558,7 @@ static int iscsit_logout_post_handler(
 	}
 	return ret;
 }
+EXPORT_SYMBOL(iscsit_logout_post_handler);
 
 void iscsit_fail_session(struct iscsi_session *sess)
 {
diff --git a/drivers/target/iscsi/iscsi_target.h b/drivers/target/iscsi/iscsi_target.h
index b1a1e63..a0050b2 100644
--- a/drivers/target/iscsi/iscsi_target.h
+++ b/drivers/target/iscsi/iscsi_target.h
@@ -16,11 +16,12 @@ 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 void iscsit_set_unsoliticed_dataout(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_build_r2ts_for_cmd(struct iscsi_cmd *, struct iscsi_conn *, bool recovery);
+extern int iscsit_build_r2ts_for_cmd(struct iscsi_conn *, struct iscsi_cmd *, bool recovery);
 extern void iscsit_thread_get_cpumask(struct iscsi_conn *);
 extern int iscsi_target_tx_thread(void *);
 extern int iscsi_target_rx_thread(void *);
diff --git a/drivers/target/iscsi/iscsi_target_auth.c b/drivers/target/iscsi/iscsi_target_auth.c
index a0fc7b9..cee1754 100644
--- a/drivers/target/iscsi/iscsi_target_auth.c
+++ b/drivers/target/iscsi/iscsi_target_auth.c
@@ -49,32 +49,6 @@ static void chap_binaryhex_to_asciihex(char *dst, char *src, int src_len)
 	}
 }
 
-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,
@@ -86,7 +60,7 @@ static void chap_gen_challenge(
 
 	memset(challenge_asciihex, 0, CHAP_CHALLENGE_LENGTH * 2 + 1);
 
-	chap_set_random(chap->challenge, CHAP_CHALLENGE_LENGTH);
+	get_random_bytes(chap->challenge, CHAP_CHALLENGE_LENGTH);
 	chap_binaryhex_to_asciihex(challenge_asciihex, chap->challenge,
 				CHAP_CHALLENGE_LENGTH);
 	/*
diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c
index 78d75c8..9763fec 100644
--- a/drivers/target/iscsi/iscsi_target_configfs.c
+++ b/drivers/target/iscsi/iscsi_target_configfs.c
@@ -27,6 +27,7 @@
 #include <target/target_core_fabric_configfs.h>
 #include <target/target_core_configfs.h>
 #include <target/configfs_macros.h>
+#include <target/iscsi/iscsi_transport.h>
 
 #include "iscsi_target_core.h"
 #include "iscsi_target_parameters.h"
@@ -124,8 +125,83 @@ out:
 
 TF_NP_BASE_ATTR(lio_target, sctp, S_IRUGO | S_IWUSR);
 
+static ssize_t lio_target_np_show_iser(
+	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_iser;
+	ssize_t rb;
+
+	tpg_np_iser = iscsit_tpg_locate_child_np(tpg_np, ISCSI_INFINIBAND);
+	if (tpg_np_iser)
+		rb = sprintf(page, "1\n");
+	else
+		rb = sprintf(page, "0\n");
+
+	return rb;
+}
+
+static ssize_t lio_target_np_store_iser(
+	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_iser = NULL;
+	char *endptr;
+	u32 op;
+	int rc;
+
+	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) {
+		tpg_np_iser = iscsit_tpg_add_network_portal(tpg, &np->np_sockaddr,
+				np->np_ip, tpg_np, ISCSI_INFINIBAND);
+		if (!tpg_np_iser || IS_ERR(tpg_np_iser))
+			goto out;
+	} else {
+		tpg_np_iser = iscsit_tpg_locate_child_np(tpg_np, ISCSI_INFINIBAND);
+		if (!tpg_np_iser)
+			goto out;
+
+		rc = iscsit_tpg_del_network_portal(tpg, tpg_np_iser);
+		if (rc < 0)
+			goto out;
+	}
+
+	printk("lio_target_np_store_iser() done, op: %d\n", op);
+
+	iscsit_put_tpg(tpg);
+	return count;
+out:
+	iscsit_put_tpg(tpg);
+	return -EINVAL;
+}
+
+TF_NP_BASE_ATTR(lio_target, iser, S_IRUGO | S_IWUSR);
+
 static struct configfs_attribute *lio_target_portal_attrs[] = {
 	&lio_target_np_sctp.attr,
+	&lio_target_np_iser.attr,
 	NULL,
 };
 
@@ -1536,16 +1612,18 @@ 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);
+	cmd->conn->conn_transport->iscsit_queue_data_in(cmd->conn, cmd);
+
 	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);
+	struct iscsi_conn *conn = cmd->conn;
 
 	if (!cmd->immediate_data && !cmd->unsolicited_data)
-		return iscsit_build_r2ts_for_cmd(cmd, cmd->conn, false);
+		return conn->conn_transport->iscsit_get_dataout(conn, cmd, false);
 
 	return 0;
 }
@@ -1567,7 +1645,8 @@ 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);
+	cmd->conn->conn_transport->iscsit_queue_status(cmd->conn, cmd);
+
 	return 0;
 }
 
@@ -1696,11 +1775,17 @@ static void lio_set_default_node_attributes(struct se_node_acl *se_acl)
 	iscsit_set_default_node_attribues(acl);
 }
 
+static int lio_check_stop_free(struct se_cmd *se_cmd)
+{
+	return target_put_sess_cmd(se_cmd->se_sess, se_cmd);
+}
+
 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);
+	pr_debug("Entering lio_release_cmd for se_cmd: %p\n", se_cmd);
+	cmd->release_cmd(cmd);
 }
 
 /* End functions for target_core_fabric_ops */
@@ -1740,6 +1825,7 @@ int iscsi_target_register_configfs(void)
 	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.check_stop_free = &lio_check_stop_free,
 	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;
diff --git a/drivers/target/iscsi/iscsi_target_core.h b/drivers/target/iscsi/iscsi_target_core.h
index 7a333d2..60ec4b9 100644
--- a/drivers/target/iscsi/iscsi_target_core.h
+++ b/drivers/target/iscsi/iscsi_target_core.h
@@ -60,7 +60,7 @@
 
 #define ISCSI_IOV_DATA_BUFFER		5
 
-enum tpg_np_network_transport_table {
+enum iscsit_transport_type {
 	ISCSI_TCP				= 0,
 	ISCSI_SCTP_TCP				= 1,
 	ISCSI_SCTP_UDP				= 2,
@@ -244,6 +244,11 @@ struct iscsi_conn_ops {
 	u8	IFMarker;			/* [0,1] == [No,Yes] */
 	u32	OFMarkInt;			/* [1..65535] */
 	u32	IFMarkInt;			/* [1..65535] */
+	/*
+	 * iSER specific connection parameters
+	 */
+	u32	InitiatorRecvDataSegmentLength;	/* [512..2**24-1] */
+	u32	TargetRecvDataSegmentLength;	/* [512..2**24-1] */
 };
 
 struct iscsi_sess_ops {
@@ -265,6 +270,10 @@ struct iscsi_sess_ops {
 	u8	DataSequenceInOrder;		/* [0,1] == [No,Yes] */
 	u8	ErrorRecoveryLevel;		/* [0..2] */
 	u8	SessionType;			/* [0,1] == [Normal,Discovery]*/
+	/*
+	 * iSER specific session parameters
+	 */
+	u8	RDMAExtensions;			/* [0,1] == [No,Yes] */
 };
 
 struct iscsi_queue_req {
@@ -284,6 +293,7 @@ struct iscsi_data_count {
 };
 
 struct iscsi_param_list {
+	bool			iser;
 	struct list_head	param_list;
 	struct list_head	extra_response_list;
 };
@@ -475,6 +485,7 @@ struct iscsi_cmd {
 	u32			first_data_sg_off;
 	u32			kmapped_nents;
 	sense_reason_t		sense_reason;
+	void (*release_cmd)(struct iscsi_cmd *);
 }  ____cacheline_aligned;
 
 struct iscsi_tmr_req {
@@ -503,6 +514,7 @@ struct iscsi_conn {
 	u16			login_port;
 	u16			local_port;
 	int			net_size;
+	int			login_family;
 	u32			auth_id;
 	u32			conn_flags;
 	/* Used for iscsi_tx_login_rsp() */
@@ -562,9 +574,12 @@ struct iscsi_conn {
 	struct list_head	immed_queue_list;
 	struct list_head	response_queue_list;
 	struct iscsi_conn_ops	*conn_ops;
+	struct iscsi_login	*conn_login;
+	struct iscsit_transport *conn_transport;
 	struct iscsi_param_list	*param_list;
 	/* Used for per connection auth state machine */
 	void			*auth_protocol;
+	void			*context;
 	struct iscsi_login_thread_s *login_thread;
 	struct iscsi_portal_group *tpg;
 	/* Pointer to parent session */
@@ -663,6 +678,8 @@ struct iscsi_login {
 	u8 first_request;
 	u8 version_min;
 	u8 version_max;
+	u8 login_complete;
+	u8 login_failed;
 	char isid[6];
 	u32 cmd_sn;
 	itt_t init_task_tag;
@@ -670,10 +687,11 @@ struct iscsi_login {
 	u32 rsp_length;
 	u16 cid;
 	u16 tsih;
-	char *req;
-	char *rsp;
+	char req[ISCSI_HDR_LEN];
+	char rsp[ISCSI_HDR_LEN];
 	char *req_buf;
 	char *rsp_buf;
+	struct iscsi_conn *conn;
 } ____cacheline_aligned;
 
 struct iscsi_node_attrib {
@@ -754,6 +772,8 @@ struct iscsi_np {
 	struct task_struct	*np_thread;
 	struct timer_list	np_login_timer;
 	struct iscsi_portal_group *np_login_tpg;
+	void			*np_context;
+	struct iscsit_transport *np_transport;
 	struct list_head	np_list;
 } ____cacheline_aligned;
 
diff --git a/drivers/target/iscsi/iscsi_target_device.c b/drivers/target/iscsi/iscsi_target_device.c
index bcc4098..1b74033 100644
--- a/drivers/target/iscsi/iscsi_target_device.c
+++ b/drivers/target/iscsi/iscsi_target_device.c
@@ -60,8 +60,13 @@ void iscsit_increment_maxcmdsn(struct iscsi_cmd *cmd, struct iscsi_session *sess
 
 	cmd->maxcmdsn_inc = 1;
 
-	mutex_lock(&sess->cmdsn_mutex);
+	if (!mutex_trylock(&sess->cmdsn_mutex)) {
+		sess->max_cmd_sn += 1;
+		pr_debug("Updated MaxCmdSN to 0x%08x\n", sess->max_cmd_sn);
+		return;
+	}
 	sess->max_cmd_sn += 1;
 	pr_debug("Updated MaxCmdSN to 0x%08x\n", sess->max_cmd_sn);
 	mutex_unlock(&sess->cmdsn_mutex);
 }
+EXPORT_SYMBOL(iscsit_increment_maxcmdsn);
diff --git a/drivers/target/iscsi/iscsi_target_erl1.c b/drivers/target/iscsi/iscsi_target_erl1.c
index 0b52a23..7816af6 100644
--- a/drivers/target/iscsi/iscsi_target_erl1.c
+++ b/drivers/target/iscsi/iscsi_target_erl1.c
@@ -22,6 +22,7 @@
 #include <scsi/iscsi_proto.h>
 #include <target/target_core_base.h>
 #include <target/target_core_fabric.h>
+#include <target/iscsi/iscsi_transport.h>
 
 #include "iscsi_target_core.h"
 #include "iscsi_target_seq_pdu_list.h"
@@ -53,6 +54,9 @@ int iscsit_dump_data_payload(
 	u32 length, padding, offset = 0, size;
 	struct kvec iov;
 
+	if (conn->sess->sess_ops->RDMAExtensions)
+		return 0;
+
 	length = (buf_len > OFFLOAD_BUF_SIZE) ? OFFLOAD_BUF_SIZE : buf_len;
 
 	buf = kzalloc(length, GFP_ATOMIC);
@@ -919,6 +923,7 @@ int iscsit_execute_ooo_cmdsns(struct iscsi_session *sess)
 int iscsit_execute_cmd(struct iscsi_cmd *cmd, int ooo)
 {
 	struct se_cmd *se_cmd = &cmd->se_cmd;
+	struct iscsi_conn *conn = cmd->conn;
 	int lr = 0;
 
 	spin_lock_bh(&cmd->istate_lock);
@@ -981,7 +986,7 @@ int iscsit_execute_cmd(struct iscsi_cmd *cmd, int ooo)
 					return 0;
 
 				iscsit_set_dataout_sequence_values(cmd);
-				iscsit_build_r2ts_for_cmd(cmd, cmd->conn, false);
+				conn->conn_transport->iscsit_get_dataout(conn, cmd, false);
 			}
 			return 0;
 		}
@@ -999,10 +1004,7 @@ int iscsit_execute_cmd(struct iscsi_cmd *cmd, int ooo)
 			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);
+			iscsit_set_unsoliticed_dataout(cmd);
 		}
 		return transport_handle_cdb_direct(&cmd->se_cmd);
 
@@ -1290,3 +1292,4 @@ void iscsit_stop_dataout_timer(struct iscsi_cmd *cmd)
 			cmd->init_task_tag);
 	spin_unlock_bh(&cmd->dataout_timeout_lock);
 }
+EXPORT_SYMBOL(iscsit_stop_dataout_timer);
diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c
index 2535d4d..1232043 100644
--- a/drivers/target/iscsi/iscsi_target_login.c
+++ b/drivers/target/iscsi/iscsi_target_login.c
@@ -39,8 +39,39 @@
 #include "iscsi_target.h"
 #include "iscsi_target_parameters.h"
 
-static int iscsi_login_init_conn(struct iscsi_conn *conn)
+#include <target/iscsi/iscsi_transport.h>
+
+static struct iscsi_login *iscsi_login_init_conn(struct iscsi_conn *conn)
 {
+	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");
+		return NULL;
+	}
+	login->conn = conn;
+	login->first_request = 1;
+
+	login->req_buf = kzalloc(MAX_KEY_VALUE_PAIRS, GFP_KERNEL);
+	if (!login->req_buf) {
+		pr_err("Unable to allocate memory for response buffer.\n");
+		goto out_login;
+	}
+
+	login->rsp_buf = kzalloc(MAX_KEY_VALUE_PAIRS, GFP_KERNEL);
+	if (!login->rsp_buf) {
+		pr_err("Unable to allocate memory for request buffer.\n");
+		goto out_req_buf;
+	}
+
+	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 out_rsp_buf;
+	}
+
 	init_waitqueue_head(&conn->queues_wq);
 	INIT_LIST_HEAD(&conn->conn_list);
 	INIT_LIST_HEAD(&conn->conn_cmd_list);
@@ -62,10 +93,21 @@ static int iscsi_login_init_conn(struct iscsi_conn *conn)
 
 	if (!zalloc_cpumask_var(&conn->conn_cpumask, GFP_KERNEL)) {
 		pr_err("Unable to allocate conn->conn_cpumask\n");
-		return -ENOMEM;
+		goto out_conn_ops;
 	}
+	conn->conn_login = login;
 
-	return 0;
+	return login;
+
+out_conn_ops:
+	kfree(conn->conn_ops);
+out_rsp_buf:
+	kfree(login->rsp_buf);
+out_req_buf:
+	kfree(login->req_buf);
+out_login:
+	kfree(login);
+	return NULL;
 }
 
 /*
@@ -298,6 +340,7 @@ static int iscsi_login_zero_tsih_s2(
 	struct iscsi_node_attrib *na;
 	struct iscsi_session *sess = conn->sess;
 	unsigned char buf[32];
+	bool iser = false;
 
 	sess->tpg = conn->tpg;
 
@@ -319,7 +362,10 @@ static int iscsi_login_zero_tsih_s2(
 		return -1;
 	}
 
-	iscsi_set_keys_to_negotiate(0, conn->param_list);
+	if (conn->conn_transport->transport_type == ISCSI_INFINIBAND)
+		iser = true;
+
+	iscsi_set_keys_to_negotiate(conn->param_list, iser);
 
 	if (sess->sess_ops->SessionType)
 		return iscsi_set_keys_irrelevant_for_discovery(
@@ -357,6 +403,56 @@ static int iscsi_login_zero_tsih_s2(
 
 	if (iscsi_login_disable_FIM_keys(conn->param_list, conn) < 0)
 		return -1;
+	/*
+	 * Set RDMAExtensions=Yes by default for iSER enabled network portals
+	 */
+	if (iser) {
+		struct iscsi_param *param;
+		unsigned long mrdsl, off;
+		int rc;
+
+		sprintf(buf, "RDMAExtensions=Yes");
+		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;
+		}
+		/*
+		 * Make MaxRecvDataSegmentLength PAGE_SIZE aligned for
+		 * Immediate Data + Unsolicitied Data-OUT if necessary..
+		 */
+		param = iscsi_find_param_from_key("MaxRecvDataSegmentLength",
+						  conn->param_list);
+		if (!param) {
+			iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
+				ISCSI_LOGIN_STATUS_NO_RESOURCES);
+			return -1;
+		}
+		rc = strict_strtoul(param->value, 0, &mrdsl);
+		if (rc < 0) {
+			iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
+				ISCSI_LOGIN_STATUS_NO_RESOURCES);
+			return -1;
+		}
+		off = mrdsl % PAGE_SIZE;
+		if (!off)
+			return 0;
+
+		if (mrdsl < PAGE_SIZE)
+			mrdsl = PAGE_SIZE;
+		else
+			mrdsl -= off;
+
+		pr_warn("Aligning ISER MaxRecvDataSegmentLength: %lu down"
+			" to PAGE_SIZE\n", mrdsl);
+
+		sprintf(buf, "MaxRecvDataSegmentLength=%lu\n", mrdsl);
+		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 0;
 }
@@ -436,6 +532,7 @@ static int iscsi_login_non_zero_tsih_s2(
 	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;
+	bool iser = false;
 
 	spin_lock_bh(&se_tpg->session_lock);
 	list_for_each_entry_safe(se_sess, se_sess_tmp, &se_tpg->tpg_sess_list,
@@ -485,7 +582,10 @@ static int iscsi_login_non_zero_tsih_s2(
 		return -1;
 	}
 
-	iscsi_set_keys_to_negotiate(0, conn->param_list);
+	if (conn->conn_transport->transport_type == ISCSI_INFINIBAND)
+		iser = true;
+
+	iscsi_set_keys_to_negotiate(conn->param_list, iser);
 	/*
 	 * Need to send TargetPortalGroupTag back in first login response
 	 * on any iSCSI connection where the Initiator provides TargetName.
@@ -574,6 +674,11 @@ int iscsi_login_post_auth_non_zero_tsih(
 static void iscsi_post_login_start_timers(struct iscsi_conn *conn)
 {
 	struct iscsi_session *sess = conn->sess;
+	/*
+	 * FIXME: Unsolicitied NopIN support for ISER
+	 */
+	if (conn->conn_transport->transport_type == ISCSI_INFINIBAND)
+		return;
 
 	if (!sess->sess_ops->SessionType)
 		iscsit_start_nopin_timer(conn);
@@ -632,6 +737,7 @@ static int iscsi_post_login_handler(
 		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
@@ -761,11 +867,11 @@ static void iscsi_stop_login_thread_timer(struct iscsi_np *np)
 	spin_unlock_bh(&np->np_thread_lock);
 }
 
-int iscsi_target_setup_login_socket(
+int iscsit_setup_np(
 	struct iscsi_np *np,
 	struct __kernel_sockaddr_storage *sockaddr)
 {
-	struct socket *sock;
+	struct socket *sock = NULL;
 	int backlog = 5, ret, opt = 0, len;
 
 	switch (np->np_network_transport) {
@@ -781,15 +887,15 @@ int iscsi_target_setup_login_socket(
 		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;
 	}
 
+	np->np_ip_proto = IPPROTO_TCP;
+	np->np_sock_type = SOCK_STREAM;
+
 	ret = sock_create(sockaddr->ss_family, np->np_sock_type,
 			np->np_ip_proto, &sock);
 	if (ret < 0) {
@@ -853,7 +959,6 @@ int iscsi_target_setup_login_socket(
 	}
 
 	return 0;
-
 fail:
 	np->np_socket = NULL;
 	if (sock)
@@ -861,21 +966,167 @@ fail:
 	return ret;
 }
 
+int iscsi_target_setup_login_socket(
+	struct iscsi_np *np,
+	struct __kernel_sockaddr_storage *sockaddr)
+{
+	struct iscsit_transport *t;
+	int rc;
+
+	t = iscsit_get_transport(np->np_network_transport);
+	if (!t)
+		return -EINVAL;
+
+	rc = t->iscsit_setup_np(np, sockaddr);
+	if (rc < 0)
+		return rc;
+
+	np->np_transport = t;
+	printk("Set np->np_transport to %p -> %s\n", np->np_transport,
+				np->np_transport->name);
+	return 0;
+}
+
+int iscsit_accept_np(struct iscsi_np *np, struct iscsi_conn *conn)
+{
+	struct socket *new_sock, *sock = np->np_socket;
+	struct sockaddr_in sock_in;
+	struct sockaddr_in6 sock_in6;
+	int rc, err;
+
+	rc = kernel_accept(sock, &new_sock, 0);
+	if (rc < 0)
+		return rc;
+
+	conn->sock = new_sock;
+	conn->login_family = np->np_sockaddr.ss_family;
+	printk("iSCSI/TCP: Setup conn->sock from new_sock: %p\n", new_sock);
+
+	if (np->np_sockaddr.ss_family == AF_INET6) {
+		memset(&sock_in6, 0, sizeof(struct sockaddr_in6));
+
+		rc = conn->sock->ops->getname(conn->sock,
+				(struct sockaddr *)&sock_in6, &err, 1);
+		if (!rc) {
+			snprintf(conn->login_ip, sizeof(conn->login_ip), "%pI6c",
+				&sock_in6.sin6_addr.in6_u);
+			conn->login_port = ntohs(sock_in6.sin6_port);
+		}
+
+		rc = conn->sock->ops->getname(conn->sock,
+				(struct sockaddr *)&sock_in6, &err, 0);
+		if (!rc) {
+			snprintf(conn->local_ip, sizeof(conn->local_ip), "%pI6c",
+				&sock_in6.sin6_addr.in6_u);
+			conn->local_port = ntohs(sock_in6.sin6_port);
+		}
+	} else {
+		memset(&sock_in, 0, sizeof(struct sockaddr_in));
+
+		rc = conn->sock->ops->getname(conn->sock,
+				(struct sockaddr *)&sock_in, &err, 1);
+		if (!rc) {
+			sprintf(conn->login_ip, "%pI4",
+					&sock_in.sin_addr.s_addr);
+			conn->login_port = ntohs(sock_in.sin_port);
+		}
+
+		rc = conn->sock->ops->getname(conn->sock,
+				(struct sockaddr *)&sock_in, &err, 0);
+		if (!rc) {
+			sprintf(conn->local_ip, "%pI4",
+					&sock_in.sin_addr.s_addr);
+			conn->local_port = ntohs(sock_in.sin_port);
+		}
+	}
+
+	return 0;
+}
+
+int iscsit_get_login_rx(struct iscsi_conn *conn, struct iscsi_login *login)
+{
+	struct iscsi_login_req *login_req;
+	u32 padding = 0, payload_length;
+
+	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);
+	padding = ((-payload_length) & 3);
+
+	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);
+	/*
+	 * Setup the initial iscsi_login values from the leading
+	 * login request PDU.
+	 */
+	if (login->first_request) {
+		login_req = (struct iscsi_login_req *)login->req;
+		login->leading_connection = (!login_req->tsih) ? 1 : 0;
+		login->current_stage	= ISCSI_LOGIN_CURRENT_STAGE(login_req->flags);
+		login->version_min	= login_req->min_version;
+		login->version_max	= login_req->max_version;
+		memcpy(login->isid, login_req->isid, 6);
+		login->cmd_sn		= be32_to_cpu(login_req->cmdsn);
+		login->init_task_tag	= login_req->itt;
+		login->initial_exp_statsn = be32_to_cpu(login_req->exp_statsn);
+		login->cid		= be16_to_cpu(login_req->cid);
+		login->tsih		= be16_to_cpu(login_req->tsih);
+	}
+
+	if (iscsi_target_check_login_request(conn, login) < 0)
+		return -1;
+
+	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;
+}
+
+int iscsit_put_login_tx(struct iscsi_conn *conn, struct iscsi_login *login,
+			u32 length)
+{
+	if (iscsi_login_tx_data(conn, login->rsp, login->rsp_buf, length) < 0)
+		return -1;
+
+	return 0;
+}
+
+static int
+iscsit_conn_set_transport(struct iscsi_conn *conn, struct iscsit_transport *t)
+{
+	int rc;
+
+	if (!t->owner) {
+		conn->conn_transport = t;
+		return 0;
+	}
+
+	rc = try_module_get(t->owner);
+	if (!rc) {
+		pr_err("try_module_get() failed for %s\n", t->name);
+		return -EINVAL;
+	}
+
+	conn->conn_transport = t;
+	return 0;
+}
+
 static int __iscsi_target_login_thread(struct iscsi_np *np)
 {
-	u8 buffer[ISCSI_HDR_LEN], iscsi_opcode, zero_tsih = 0;
-	int err, ret = 0, stop;
+	u8 *buffer, zero_tsih = 0;
+	int ret = 0, rc, 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);
-	sock = np->np_socket;
 
 	spin_lock_bh(&np->np_thread_lock);
 	if (np->np_thread_state == ISCSI_NP_THREAD_RESET) {
@@ -886,75 +1137,76 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
 	}
 	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;
-	}
-	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");
-		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;
 
-	pr_debug("Moving to TARG_CONN_STATE_XPT_UP.\n");
-	conn->conn_state = TARG_CONN_STATE_XPT_UP;
+	if (iscsit_conn_set_transport(conn, np->np_transport) < 0) {
+		kfree(conn);
+		return 1;
+	}
 
-	/*
-	 * 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;
+	rc = np->np_transport->iscsit_accept_np(np, conn);
+	if (rc == -ENOSYS) {
+		complete(&np->np_restart_comp);
+		iscsit_put_transport(conn->conn_transport);
+		kfree(conn);
+		conn = NULL;
+		goto exit;
+	} else if (rc < 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);
+			if (ret == -ENODEV) {
+				iscsit_put_transport(conn->conn_transport);
+				kfree(conn);
+				conn = NULL;
+				goto out;
+			}
+			/* Get another socket */
+			return 1;
+		}
+		spin_unlock_bh(&np->np_thread_lock);
+		iscsit_put_transport(conn->conn_transport);
+		kfree(conn);
+		conn = NULL;
+		goto 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");
+	login = iscsi_login_init_conn(conn);
+	if (!login) {
 		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;
-	}
+	iscsi_start_login_thread_timer(np);
 
-	pdu			= (struct iscsi_login_req *) buffer;
+	pr_debug("Moving to TARG_CONN_STATE_XPT_UP.\n");
+	conn->conn_state = TARG_CONN_STATE_XPT_UP;
+	/*
+	 * This will process the first login request + payload..
+	 */
+	rc = np->np_transport->iscsit_get_login_rx(conn, login);
+	if (rc == 1)
+		return 1;
+	else if (rc < 0)
+		goto new_sess_out;
 
+	buffer = &login->req[0];
+	pdu = (struct iscsi_login_req *)buffer;
 	/*
 	 * Used by iscsit_tx_login_rsp() for Login Resonses PDUs
 	 * when Status-Class != 0.
 	*/
-	conn->login_itt		= pdu->itt;
+	conn->login_itt	= pdu->itt;
 
 	spin_lock_bh(&np->np_thread_lock);
 	if (np->np_thread_state != ISCSI_NP_THREAD_ACTIVE) {
@@ -967,61 +1219,11 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
 	}
 	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;
-		}
-		snprintf(conn->login_ip, sizeof(conn->login_ip), "%pI6c",
-				&sock_in6.sin6_addr.in6_u);
-		conn->login_port = ntohs(sock_in6.sin6_port);
-
-		if (conn->sock->ops->getname(conn->sock,
-				(struct sockaddr *)&sock_in6, &err, 0) < 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;
-		}
-		snprintf(conn->local_ip, sizeof(conn->local_ip), "%pI6c",
-				&sock_in6.sin6_addr.in6_u);
-		conn->local_port = ntohs(sock_in6.sin6_port);
-
-	} 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);
-
-		if (conn->sock->ops->getname(conn->sock,
-				(struct sockaddr *)&sock_in, &err, 0) < 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->local_ip, "%pI4", &sock_in.sin_addr.s_addr);
-		conn->local_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",
-			conn->local_ip, conn->local_port);
+		" Portal %s:%hu\n", conn->login_ip, np->np_transport->name,
+		conn->local_ip, conn->local_port);
 
 	pr_debug("Moving to TARG_CONN_STATE_IN_LOGIN.\n");
 	conn->conn_state	= TARG_CONN_STATE_IN_LOGIN;
@@ -1050,13 +1252,17 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
 		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.
+	 * SessionType: Discovery
+	 *
+	 * 	Locates Default Portal
+	 *
+	 * SessionType: Normal
+	 *
+	 * 	Locates Target Portal from NP -> Target IQN
 	 */
-	login = iscsi_target_init_negotiation(np, conn, buffer);
-	if (!login) {
+	rc = iscsi_target_locate_portal(np, conn, login);
+	if (rc < 0) {
 		tpg = conn->tpg;
 		goto new_sess_out;
 	}
@@ -1068,15 +1274,11 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
 	}
 
 	if (zero_tsih) {
-		if (iscsi_login_zero_tsih_s2(conn) < 0) {
-			iscsi_target_nego_release(login, conn);
+		if (iscsi_login_zero_tsih_s2(conn) < 0)
 			goto new_sess_out;
-		}
 	} else {
-		if (iscsi_login_non_zero_tsih_s2(conn, buffer) < 0) {
-			iscsi_target_nego_release(login, conn);
+		if (iscsi_login_non_zero_tsih_s2(conn, buffer) < 0)
 			goto old_sess_out;
-		}
 	}
 
 	if (iscsi_target_start_negotiation(login, conn) < 0)
@@ -1153,8 +1355,18 @@ old_sess_out:
 		iscsi_release_param_list(conn->param_list);
 		conn->param_list = NULL;
 	}
-	if (conn->sock)
+	iscsi_target_nego_release(conn);
+
+	if (conn->sock) {
 		sock_release(conn->sock);
+		conn->sock = NULL;
+	}
+
+	if (conn->conn_transport->iscsit_free_conn)
+		conn->conn_transport->iscsit_free_conn(conn);
+
+	iscsit_put_transport(conn->conn_transport);
+
 	kfree(conn);
 
 	if (tpg) {
@@ -1172,11 +1384,13 @@ out:
 	/* Wait for another socket.. */
 	if (!stop)
 		return 1;
-
+exit:
 	iscsi_stop_login_thread_timer(np);
 	spin_lock_bh(&np->np_thread_lock);
 	np->np_thread_state = ISCSI_NP_THREAD_EXIT;
+	np->np_thread = NULL;
 	spin_unlock_bh(&np->np_thread_lock);
+
 	return 0;
 }
 
diff --git a/drivers/target/iscsi/iscsi_target_login.h b/drivers/target/iscsi/iscsi_target_login.h
index 091dcae..63efd28 100644
--- a/drivers/target/iscsi/iscsi_target_login.h
+++ b/drivers/target/iscsi/iscsi_target_login.h
@@ -4,8 +4,14 @@
 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 iscsit_setup_np(struct iscsi_np *,
+				struct __kernel_sockaddr_storage *);
 extern int iscsi_target_setup_login_socket(struct iscsi_np *,
 				struct __kernel_sockaddr_storage *);
+extern int iscsit_accept_np(struct iscsi_np *, struct iscsi_conn *);
+extern int iscsit_get_login_rx(struct iscsi_conn *, struct iscsi_login *);
+extern int iscsit_put_login_tx(struct iscsi_conn *, struct iscsi_login *, u32);
+extern void iscsit_free_conn(struct iscsi_np *, struct iscsi_conn *);
 extern int iscsi_target_login_thread(void *);
 extern int iscsi_login_disable_FIM_keys(struct iscsi_param_list *, struct iscsi_conn *);
 
diff --git a/drivers/target/iscsi/iscsi_target_nego.c b/drivers/target/iscsi/iscsi_target_nego.c
index 9d902ae..7ad9120 100644
--- a/drivers/target/iscsi/iscsi_target_nego.c
+++ b/drivers/target/iscsi/iscsi_target_nego.c
@@ -22,6 +22,7 @@
 #include <scsi/iscsi_proto.h>
 #include <target/target_core_base.h>
 #include <target/target_core_fabric.h>
+#include <target/iscsi/iscsi_transport.h>
 
 #include "iscsi_target_core.h"
 #include "iscsi_target_parameters.h"
@@ -169,7 +170,7 @@ static void iscsi_remove_failed_auth_entry(struct iscsi_conn *conn)
 	kfree(conn->auth_protocol);
 }
 
-static int iscsi_target_check_login_request(
+int iscsi_target_check_login_request(
 	struct iscsi_conn *conn,
 	struct iscsi_login *login)
 {
@@ -200,8 +201,8 @@ static int iscsi_target_check_login_request(
 		return -1;
 	}
 
-	req_csg = (login_req->flags & ISCSI_FLAG_LOGIN_CURRENT_STAGE_MASK) >> 2;
-	req_nsg = (login_req->flags & ISCSI_FLAG_LOGIN_NEXT_STAGE_MASK);
+	req_csg = ISCSI_LOGIN_CURRENT_STAGE(login_req->flags);
+	req_nsg = ISCSI_LOGIN_NEXT_STAGE(login_req->flags);
 
 	if (req_csg != login->current_stage) {
 		pr_err("Initiator unexpectedly changed login stage"
@@ -352,11 +353,8 @@ static int iscsi_target_do_tx_login_io(struct iscsi_conn *conn, struct iscsi_log
 
 	padding = ((-login->rsp_length) & 3);
 
-	if (iscsi_login_tx_data(
-			conn,
-			login->rsp,
-			login->rsp_buf,
-			login->rsp_length + padding) < 0)
+	if (conn->conn_transport->iscsit_put_login_tx(conn, login,
+					login->rsp_length + padding) < 0)
 		return -1;
 
 	login->rsp_length		= 0;
@@ -368,72 +366,12 @@ static int iscsi_target_do_tx_login_io(struct iscsi_conn *conn, struct iscsi_log
 	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);
-
-	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)
+	if (conn->conn_transport->iscsit_get_login_rx(conn, login) < 0)
 		return -1;
 
 	return 0;
@@ -681,9 +619,9 @@ static int iscsi_target_do_login(struct iscsi_conn *conn, struct iscsi_login *lo
 			return -1;
 		}
 
-		switch ((login_req->flags & ISCSI_FLAG_LOGIN_CURRENT_STAGE_MASK) >> 2) {
+		switch (ISCSI_LOGIN_CURRENT_STAGE(login_req->flags)) {
 		case 0:
-			login_rsp->flags |= (0 & ISCSI_FLAG_LOGIN_CURRENT_STAGE_MASK);
+			login_rsp->flags &= ~ISCSI_FLAG_LOGIN_CURRENT_STAGE_MASK;
 			if (iscsi_target_handle_csg_zero(conn, login) < 0)
 				return -1;
 			break;
@@ -693,6 +631,7 @@ static int iscsi_target_do_login(struct iscsi_conn *conn, struct iscsi_login *lo
 				return -1;
 			if (login_rsp->flags & ISCSI_FLAG_LOGIN_TRANSIT) {
 				login->tsih = conn->sess->tsih;
+				login->login_complete = 1;
 				if (iscsi_target_do_tx_login_io(conn,
 						login) < 0)
 					return -1;
@@ -702,8 +641,7 @@ static int iscsi_target_do_login(struct iscsi_conn *conn, struct iscsi_login *lo
 		default:
 			pr_err("Illegal CSG: %d received from"
 				" Initiator, protocol error.\n",
-				(login_req->flags & ISCSI_FLAG_LOGIN_CURRENT_STAGE_MASK)
-				>> 2);
+				ISCSI_LOGIN_CURRENT_STAGE(login_req->flags));
 			break;
 		}
 
@@ -737,7 +675,7 @@ static void iscsi_initiatorname_tolower(
 /*
  * Processes the first Login Request..
  */
-static int iscsi_target_locate_portal(
+int iscsi_target_locate_portal(
 	struct iscsi_np *np,
 	struct iscsi_conn *conn,
 	struct iscsi_login *login)
@@ -753,22 +691,6 @@ static int iscsi_target_locate_portal(
 	login_req = (struct iscsi_login_req *) login->req;
 	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		= be32_to_cpu(login_req->cmdsn);
-	login->init_task_tag	= login_req->itt;
-	login->initial_exp_statsn = be32_to_cpu(login_req->exp_statsn);
-	login->cid		= be16_to_cpu(login_req->cid);
-	login->tsih		= be16_to_cpu(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");
@@ -800,6 +722,8 @@ static int iscsi_target_locate_portal(
 		start += strlen(key) + strlen(value) + 2;
 	}
 
+	printk("i_buf: %s, s_buf: %s, t_buf: %s\n", i_buf, s_buf, t_buf);
+
 	/*
 	 * See 5.3.  Login Phase.
 	 */
@@ -958,100 +882,30 @@ out:
 	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);
-		return NULL;
-	}
-
-	login->req = kmemdup(login_pdu, 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;
-	}
-
-	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) {
-		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;
-	}
+	int ret;
 
 	ret = iscsi_target_do_login(conn, login);
-out:
 	if (ret != 0)
 		iscsi_remove_failed_auth_entry(conn);
 
-	iscsi_target_nego_release(login, conn);
+	iscsi_target_nego_release(conn);
 	return ret;
 }
 
-void iscsi_target_nego_release(
-	struct iscsi_login *login,
-	struct iscsi_conn *conn)
+void iscsi_target_nego_release(struct iscsi_conn *conn)
 {
-	kfree(login->req);
-	kfree(login->rsp);
+	struct iscsi_login *login = conn->conn_login;
+
+	if (!login)
+		return;
+
 	kfree(login->req_buf);
 	kfree(login->rsp_buf);
 	kfree(login);
+
+	conn->conn_login = NULL;
 }
diff --git a/drivers/target/iscsi/iscsi_target_nego.h b/drivers/target/iscsi/iscsi_target_nego.h
index 92e133a..f021cbd 100644
--- a/drivers/target/iscsi/iscsi_target_nego.h
+++ b/drivers/target/iscsi/iscsi_target_nego.h
@@ -7,11 +7,14 @@
 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_check_login_request(struct iscsi_conn *,
+		struct iscsi_login *);
+extern int iscsi_target_get_initial_payload(struct iscsi_conn *,
+		struct iscsi_login *);
+extern int iscsi_target_locate_portal(struct iscsi_np *, struct iscsi_conn *,
+		struct iscsi_login *);
 extern int iscsi_target_start_negotiation(
 		struct iscsi_login *, struct iscsi_conn *);
-extern void iscsi_target_nego_release(
-		struct iscsi_login *, struct iscsi_conn *);
+extern void iscsi_target_nego_release(struct iscsi_conn *);
 
 #endif /* ISCSI_TARGET_NEGO_H */
diff --git a/drivers/target/iscsi/iscsi_target_parameters.c b/drivers/target/iscsi/iscsi_target_parameters.c
index ca2be40..f690be9 100644
--- a/drivers/target/iscsi/iscsi_target_parameters.c
+++ b/drivers/target/iscsi/iscsi_target_parameters.c
@@ -59,7 +59,7 @@ int iscsi_login_tx_data(
 	char *text_buf,
 	int text_length)
 {
-	int length, tx_sent;
+	int length, tx_sent, iov_cnt = 1;
 	struct kvec iov[2];
 
 	length = (ISCSI_HDR_LEN + text_length);
@@ -67,8 +67,12 @@ int iscsi_login_tx_data(
 	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;
+
+	if (text_buf && text_length) {
+		iov[1].iov_len	= text_length;
+		iov[1].iov_base	= text_buf;
+		iov_cnt++;
+	}
 
 	/*
 	 * Initial Marker-less Interval.
@@ -77,7 +81,7 @@ int iscsi_login_tx_data(
 	 */
 	conn->if_marker += length;
 
-	tx_sent = tx_data(conn, &iov[0], 2, length);
+	tx_sent = tx_data(conn, &iov[0], iov_cnt, length);
 	if (tx_sent != length) {
 		pr_err("tx_data returned %d, expecting %d.\n",
 				tx_sent, length);
@@ -429,6 +433,28 @@ int iscsi_create_default_params(struct iscsi_param_list **param_list_ptr)
 			TYPERANGE_MARKINT, USE_INITIAL_ONLY);
 	if (!param)
 		goto out;
+	/*
+	 * Extra parameters for ISER from RFC-5046
+	 */
+	param = iscsi_set_default_param(pl, RDMAEXTENTIONS, INITIAL_RDMAEXTENTIONS,
+			PHASE_OPERATIONAL, SCOPE_SESSION_WIDE, SENDER_BOTH,
+			TYPERANGE_BOOL_AND, USE_LEADING_ONLY);
+	if (!param)
+		goto out;
+
+	param = iscsi_set_default_param(pl, INITIATORRECVDATASEGMENTLENGTH,
+			INITIAL_INITIATORRECVDATASEGMENTLENGTH,
+			PHASE_OPERATIONAL, SCOPE_CONNECTION_ONLY, SENDER_BOTH,
+			TYPERANGE_512_TO_16777215, USE_ALL);
+	if (!param)
+		goto out;
+
+	param = iscsi_set_default_param(pl, TARGETRECVDATASEGMENTLENGTH,
+			INITIAL_TARGETRECVDATASEGMENTLENGTH,
+			PHASE_OPERATIONAL, SCOPE_CONNECTION_ONLY, SENDER_BOTH,
+			TYPERANGE_512_TO_16777215, USE_ALL);
+	if (!param)
+		goto out;
 
 	*param_list_ptr = pl;
 	return 0;
@@ -438,19 +464,23 @@ out:
 }
 
 int iscsi_set_keys_to_negotiate(
-	int sessiontype,
-	struct iscsi_param_list *param_list)
+	struct iscsi_param_list *param_list,
+	bool iser)
 {
 	struct iscsi_param *param;
 
+	param_list->iser = iser;
+
 	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);
+			if (iser == false)
+				SET_PSTATE_NEGOTIATE(param);
 		} else if (!strcmp(param->name, DATADIGEST)) {
-			SET_PSTATE_NEGOTIATE(param);
+			if (iser == false)
+				SET_PSTATE_NEGOTIATE(param);
 		} else if (!strcmp(param->name, MAXCONNECTIONS)) {
 			SET_PSTATE_NEGOTIATE(param);
 		} else if (!strcmp(param->name, TARGETNAME)) {
@@ -469,7 +499,8 @@ int iscsi_set_keys_to_negotiate(
 		} else if (!strcmp(param->name, IMMEDIATEDATA)) {
 			SET_PSTATE_NEGOTIATE(param);
 		} else if (!strcmp(param->name, MAXRECVDATASEGMENTLENGTH)) {
-			SET_PSTATE_NEGOTIATE(param);
+			if (iser == false)
+				SET_PSTATE_NEGOTIATE(param);
 		} else if (!strcmp(param->name, MAXXMITDATASEGMENTLENGTH)) {
 			continue;
 		} else if (!strcmp(param->name, MAXBURSTLENGTH)) {
@@ -498,6 +529,15 @@ int iscsi_set_keys_to_negotiate(
 			SET_PSTATE_NEGOTIATE(param);
 		} else if (!strcmp(param->name, OFMARKINT)) {
 			SET_PSTATE_NEGOTIATE(param);
+		} else if (!strcmp(param->name, RDMAEXTENTIONS)) {
+			if (iser == true)
+				SET_PSTATE_NEGOTIATE(param);
+		} else if (!strcmp(param->name, INITIATORRECVDATASEGMENTLENGTH)) {
+			if (iser == true)
+				SET_PSTATE_NEGOTIATE(param);
+		} else if (!strcmp(param->name, TARGETRECVDATASEGMENTLENGTH)) {
+			if (iser == true)
+				SET_PSTATE_NEGOTIATE(param);
 		}
 	}
 
@@ -540,6 +580,12 @@ int iscsi_set_keys_irrelevant_for_discovery(
 			param->state &= ~PSTATE_NEGOTIATE;
 		else if (!strcmp(param->name, OFMARKINT))
 			param->state &= ~PSTATE_NEGOTIATE;
+		else if (!strcmp(param->name, RDMAEXTENTIONS))
+			param->state &= ~PSTATE_NEGOTIATE;
+		else if (!strcmp(param->name, INITIATORRECVDATASEGMENTLENGTH))
+			param->state &= ~PSTATE_NEGOTIATE;
+		else if (!strcmp(param->name, TARGETRECVDATASEGMENTLENGTH))
+			param->state &= ~PSTATE_NEGOTIATE;
 	}
 
 	return 0;
@@ -1755,6 +1801,9 @@ void iscsi_set_connection_parameters(
 		 * this key is not sent over the wire.
 		 */
 		if (!strcmp(param->name, MAXXMITDATASEGMENTLENGTH)) {
+			if (param_list->iser == true)
+				continue;
+
 			ops->MaxXmitDataSegmentLength =
 				simple_strtoul(param->value, &tmpptr, 0);
 			pr_debug("MaxXmitDataSegmentLength:     %s\n",
@@ -1800,6 +1849,22 @@ void iscsi_set_connection_parameters(
 				simple_strtoul(param->value, &tmpptr, 0);
 			pr_debug("IFMarkInt:                    %s\n",
 				param->value);
+		} else if (!strcmp(param->name, INITIATORRECVDATASEGMENTLENGTH)) {
+			ops->InitiatorRecvDataSegmentLength =
+				simple_strtoul(param->value, &tmpptr, 0);
+			pr_debug("InitiatorRecvDataSegmentLength: %s\n",
+				param->value);
+			ops->MaxRecvDataSegmentLength =
+					ops->InitiatorRecvDataSegmentLength;
+			pr_debug("Set MRDSL from InitiatorRecvDataSegmentLength\n");
+		} else if (!strcmp(param->name, TARGETRECVDATASEGMENTLENGTH)) {
+			ops->TargetRecvDataSegmentLength =
+				simple_strtoul(param->value, &tmpptr, 0);
+			pr_debug("TargetRecvDataSegmentLength:  %s\n",
+				param->value);
+			ops->MaxXmitDataSegmentLength =
+					ops->TargetRecvDataSegmentLength;
+			pr_debug("Set MXDSL from TargetRecvDataSegmentLength\n");
 		}
 	}
 	pr_debug("----------------------------------------------------"
@@ -1912,6 +1977,10 @@ void iscsi_set_session_parameters(
 			ops->SessionType = !strcmp(param->value, DISCOVERY);
 			pr_debug("SessionType:                  %s\n",
 				param->value);
+		} else if (!strcmp(param->name, RDMAEXTENTIONS)) {
+			ops->RDMAExtensions = !strcmp(param->value, YES);
+			pr_debug("RDMAExtensions:               %s\n",
+				param->value);
 		}
 	}
 	pr_debug("----------------------------------------------------"
diff --git a/drivers/target/iscsi/iscsi_target_parameters.h b/drivers/target/iscsi/iscsi_target_parameters.h
index 1e1b750..f31b9c4 100644
--- a/drivers/target/iscsi/iscsi_target_parameters.h
+++ b/drivers/target/iscsi/iscsi_target_parameters.h
@@ -27,7 +27,7 @@ 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_to_negotiate(struct iscsi_param_list *, bool);
 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);
@@ -89,6 +89,13 @@ extern void iscsi_set_session_parameters(struct iscsi_sess_ops *,
 #define X_EXTENSIONKEY_CISCO_OLD	"X-com.cisco.iscsi.draft"
 
 /*
+ * Parameter names of iSCSI Extentions for RDMA (iSER).  See RFC-5046
+ */
+#define RDMAEXTENTIONS			"RDMAExtensions"
+#define INITIATORRECVDATASEGMENTLENGTH	"InitiatorRecvDataSegmentLength"
+#define TARGETRECVDATASEGMENTLENGTH	"TargetRecvDataSegmentLength"
+
+/*
  * For AuthMethod.
  */
 #define KRB5				"KRB5"
@@ -133,6 +140,13 @@ extern void iscsi_set_session_parameters(struct iscsi_sess_ops *,
 #define INITIAL_OFMARKINT			"2048~65535"
 
 /*
+ * Initial values for iSER parameters following RFC-5046 Section 6
+ */
+#define INITIAL_RDMAEXTENTIONS			NO
+#define INITIAL_INITIATORRECVDATASEGMENTLENGTH	"262144"
+#define INITIAL_TARGETRECVDATASEGMENTLENGTH	"8192"
+
+/*
  * For [Header,Data]Digests.
  */
 #define CRC32C				"CRC32C"
diff --git a/drivers/target/iscsi/iscsi_target_tmr.c b/drivers/target/iscsi/iscsi_target_tmr.c
index 9d4417a..b997e5d 100644
--- a/drivers/target/iscsi/iscsi_target_tmr.c
+++ b/drivers/target/iscsi/iscsi_target_tmr.c
@@ -23,6 +23,7 @@
 #include <scsi/iscsi_proto.h>
 #include <target/target_core_base.h>
 #include <target/target_core_fabric.h>
+#include <target/iscsi/iscsi_transport.h>
 
 #include "iscsi_target_core.h"
 #include "iscsi_target_seq_pdu_list.h"
@@ -301,7 +302,7 @@ static int iscsit_task_reassign_complete_write(
 	/*
 	 * iscsit_build_r2ts_for_cmd() can handle the rest from here.
 	 */
-	return iscsit_build_r2ts_for_cmd(cmd, conn, true);
+	return conn->conn_transport->iscsit_get_dataout(conn, cmd, true);
 }
 
 static int iscsit_task_reassign_complete_read(
@@ -471,6 +472,7 @@ int iscsit_tmr_post_handler(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
 
 	return 0;
 }
+EXPORT_SYMBOL(iscsit_tmr_post_handler);
 
 /*
  *	Nothing to do here, but leave it for good measure. :-)
diff --git a/drivers/target/iscsi/iscsi_target_tpg.c b/drivers/target/iscsi/iscsi_target_tpg.c
index ee8f8c6..439260b 100644
--- a/drivers/target/iscsi/iscsi_target_tpg.c
+++ b/drivers/target/iscsi/iscsi_target_tpg.c
@@ -31,6 +31,8 @@
 #include "iscsi_target.h"
 #include "iscsi_target_parameters.h"
 
+#include <target/iscsi/iscsi_transport.h>
+
 struct iscsi_portal_group *iscsit_alloc_portal_group(struct iscsi_tiqn *tiqn, u16 tpgt)
 {
 	struct iscsi_portal_group *tpg;
@@ -508,7 +510,7 @@ struct iscsi_tpg_np *iscsit_tpg_add_network_portal(
 
 	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");
+		np->np_transport->name);
 
 	return tpg_np;
 }
@@ -522,7 +524,7 @@ static int iscsit_tpg_release_np(
 
 	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");
+		np->np_transport->name);
 
 	tpg_np->tpg_np = NULL;
 	tpg_np->tpg = NULL;
diff --git a/drivers/target/iscsi/iscsi_target_transport.c b/drivers/target/iscsi/iscsi_target_transport.c
new file mode 100644
index 0000000..882728f
--- /dev/null
+++ b/drivers/target/iscsi/iscsi_target_transport.c
@@ -0,0 +1,55 @@
+#include <linux/spinlock.h>
+#include <linux/list.h>
+#include <target/iscsi/iscsi_transport.h>
+
+static LIST_HEAD(g_transport_list);
+static DEFINE_MUTEX(transport_mutex);
+
+struct iscsit_transport *iscsit_get_transport(int type)
+{
+	struct iscsit_transport *t;
+
+	mutex_lock(&transport_mutex);
+	list_for_each_entry(t, &g_transport_list, t_node) {
+		if (t->transport_type == type) {
+			if (t->owner && !try_module_get(t->owner)) {
+				t = NULL;
+			}
+			mutex_unlock(&transport_mutex);
+			return t;
+		}
+	}
+	mutex_unlock(&transport_mutex);
+
+	return NULL;
+}
+
+void iscsit_put_transport(struct iscsit_transport *t)
+{
+	if (t->owner)
+		module_put(t->owner);
+}
+
+int iscsit_register_transport(struct iscsit_transport *t)
+{
+	INIT_LIST_HEAD(&t->t_node);
+
+	mutex_lock(&transport_mutex);
+	list_add_tail(&t->t_node, &g_transport_list);
+	mutex_unlock(&transport_mutex);
+
+	pr_debug("Registered iSCSI transport: %s\n", t->name);
+
+	return 0;
+}
+EXPORT_SYMBOL(iscsit_register_transport);
+
+void iscsit_unregister_transport(struct iscsit_transport *t)
+{
+	mutex_lock(&transport_mutex);
+	list_del(&t->t_node);
+	mutex_unlock(&transport_mutex);
+
+	pr_debug("Unregistered iSCSI transport: %s\n", t->name);
+}
+EXPORT_SYMBOL(iscsit_unregister_transport);
diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c
index 7ce3505..2cc6c9a 100644
--- a/drivers/target/iscsi/iscsi_target_util.c
+++ b/drivers/target/iscsi/iscsi_target_util.c
@@ -24,6 +24,7 @@
 #include <target/target_core_base.h>
 #include <target/target_core_fabric.h>
 #include <target/target_core_configfs.h>
+#include <target/iscsi/iscsi_transport.h>
 
 #include "iscsi_target_core.h"
 #include "iscsi_target_parameters.h"
@@ -148,6 +149,18 @@ void iscsit_free_r2ts_from_list(struct iscsi_cmd *cmd)
 	spin_unlock_bh(&cmd->r2t_lock);
 }
 
+struct iscsi_cmd *iscsit_alloc_cmd(struct iscsi_conn *conn, gfp_t gfp_mask)
+{
+	struct iscsi_cmd *cmd;
+
+	cmd = kmem_cache_zalloc(lio_cmd_cache, gfp_mask);
+	if (!cmd)
+		return NULL;
+
+	cmd->release_cmd = &iscsit_release_cmd;
+	return cmd;
+}
+
 /*
  * May be called from software interrupt (timer) context for allocating
  * iSCSI NopINs.
@@ -156,13 +169,12 @@ 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);
+	cmd = conn->conn_transport->iscsit_alloc_cmd(conn, gfp_mask);
 	if (!cmd) {
 		pr_err("Unable to allocate memory for struct iscsi_cmd.\n");
 		return NULL;
 	}
-
-	cmd->conn	= conn;
+	cmd->conn = conn;
 	INIT_LIST_HEAD(&cmd->i_conn_node);
 	INIT_LIST_HEAD(&cmd->datain_list);
 	INIT_LIST_HEAD(&cmd->cmd_r2t_list);
@@ -175,6 +187,7 @@ struct iscsi_cmd *iscsit_allocate_cmd(struct iscsi_conn *conn, gfp_t gfp_mask)
 
 	return cmd;
 }
+EXPORT_SYMBOL(iscsit_allocate_cmd);
 
 struct iscsi_seq *iscsit_get_seq_holder_for_datain(
 	struct iscsi_cmd *cmd,
@@ -304,6 +317,7 @@ int iscsit_sequence_cmd(
 
 	return ret;
 }
+EXPORT_SYMBOL(iscsit_sequence_cmd);
 
 int iscsit_check_unsolicited_dataout(struct iscsi_cmd *cmd, unsigned char *buf)
 {
@@ -689,6 +703,11 @@ void iscsit_free_cmd(struct iscsi_cmd *cmd)
 	 */
 	switch (cmd->iscsi_opcode) {
 	case ISCSI_OP_SCSI_CMD:
+		if (cmd->data_direction == DMA_TO_DEVICE)
+			iscsit_stop_dataout_timer(cmd);
+		/*
+		 * Fallthrough
+		 */
 	case ISCSI_OP_SCSI_TMFUNC:
 		transport_generic_free_cmd(&cmd->se_cmd, 1);
 		break;
@@ -704,7 +723,7 @@ void iscsit_free_cmd(struct iscsi_cmd *cmd)
 		}
 		/* Fall-through */
 	default:
-		iscsit_release_cmd(cmd);
+		cmd->release_cmd(cmd);
 		break;
 	}
 }
@@ -1226,34 +1245,19 @@ send_datacrc:
  */
 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;
+	struct iscsi_login *login = conn->conn_login;
 
+	login->login_failed = 1;
 	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	= (struct iscsi_login_rsp *)&login->rsp[0];
 	hdr->opcode		= ISCSI_OP_LOGIN_RSP;
 	hdr->status_class	= status_class;
 	hdr->status_detail	= status_detail;
 	hdr->itt		= 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;
+	return conn->conn_transport->iscsit_put_login_tx(conn, login, 0);
 }
 
 void iscsit_print_session_params(struct iscsi_session *sess)
@@ -1432,7 +1436,8 @@ void iscsit_collect_login_stats(
 		strcpy(ls->last_intr_fail_name,
 		       (intrname ? intrname->value : "Unknown"));
 
-		ls->last_intr_fail_ip_family = conn->sock->sk->sk_family;
+		ls->last_intr_fail_ip_family = conn->login_family;
+
 		snprintf(ls->last_intr_fail_ip_addr, IPV6_ADDRESS_SPACE,
 				"%s", conn->login_ip);
 		ls->last_fail_time = get_jiffies_64();
diff --git a/drivers/target/iscsi/iscsi_target_util.h b/drivers/target/iscsi/iscsi_target_util.h
index 894d0f8..4f8e01a 100644
--- a/drivers/target/iscsi/iscsi_target_util.h
+++ b/drivers/target/iscsi/iscsi_target_util.h
@@ -8,6 +8,7 @@ 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_alloc_cmd(struct iscsi_conn *, gfp_t);
 extern struct iscsi_cmd *iscsit_allocate_cmd(struct iscsi_conn *, gfp_t);
 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 *);
diff --git a/drivers/target/loopback/tcm_loop.c b/drivers/target/loopback/tcm_loop.c
index 2d444b1..7c90814 100644
--- a/drivers/target/loopback/tcm_loop.c
+++ b/drivers/target/loopback/tcm_loop.c
@@ -79,11 +79,10 @@ static void tcm_loop_release_cmd(struct se_cmd *se_cmd)
 	kmem_cache_free(tcm_loop_cmd_cache, tl_cmd);
 }
 
-static int tcm_loop_proc_info(struct Scsi_Host *host, char *buffer,
-				char **start, off_t offset,
-				int length, int inout)
+static int tcm_loop_show_info(struct seq_file *m, struct Scsi_Host *host)
 {
-	return sprintf(buffer, "tcm_loop_proc_info()\n");
+	seq_printf(m, "tcm_loop_proc_info()\n");
+	return 0;
 }
 
 static int tcm_loop_driver_probe(struct device *);
@@ -336,7 +335,7 @@ static int tcm_loop_slave_configure(struct scsi_device *sd)
 }
 
 static struct scsi_host_template tcm_loop_driver_template = {
-	.proc_info		= tcm_loop_proc_info,
+	.show_info		= tcm_loop_show_info,
 	.proc_name		= "tcm_loopback",
 	.name			= "TCM_Loopback",
 	.queuecommand		= tcm_loop_queuecommand,
diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c
index 8bcc514..c2e5ca9 100644
--- a/drivers/target/target_core_iblock.c
+++ b/drivers/target/target_core_iblock.c
@@ -271,7 +271,8 @@ static void iblock_complete_cmd(struct se_cmd *cmd)
 	kfree(ibr);
 }
 
-static void iblock_bio_done(struct bio *bio, int err)
+static void iblock_bio_done(struct bio *bio, int err,
+			    struct batch_complete *batch)
 {
 	struct se_cmd *cmd = bio->bi_private;
 	struct iblock_req *ibr = cmd->priv;
@@ -335,7 +336,8 @@ static void iblock_submit_bios(struct bio_list *list, int rw)
 	blk_finish_plug(&plug);
 }
 
-static void iblock_end_io_flush(struct bio *bio, int err)
+static void iblock_end_io_flush(struct bio *bio, int err,
+				struct batch_complete *batch)
 {
 	struct se_cmd *cmd = bio->bi_private;
 
diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c
index e992b27..1e98731 100644
--- a/drivers/target/target_core_pscsi.c
+++ b/drivers/target/target_core_pscsi.c
@@ -835,7 +835,8 @@ static ssize_t pscsi_show_configfs_dev_params(struct se_device *dev, char *b)
 	return bl;
 }
 
-static void pscsi_bi_endio(struct bio *bio, int error)
+static void pscsi_bi_endio(struct bio *bio, int error,
+			   struct batch_complete *batch)
 {
 	bio_put(bio);
 }
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index 3243ea7..f8388b4 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -65,7 +65,6 @@ static void transport_complete_task_attr(struct se_cmd *cmd);
 static void transport_handle_queue_full(struct se_cmd *cmd,
 		struct se_device *dev);
 static int transport_generic_get_mem(struct se_cmd *cmd);
-static int target_get_sess_cmd(struct se_session *, struct se_cmd *, bool);
 static void transport_put_cmd(struct se_cmd *cmd);
 static void target_complete_ok_work(struct work_struct *work);
 
@@ -2179,7 +2178,7 @@ EXPORT_SYMBOL(transport_generic_free_cmd);
  * @se_cmd:	command descriptor to add
  * @ack_kref:	Signal that fabric will perform an ack target_put_sess_cmd()
  */
-static int target_get_sess_cmd(struct se_session *se_sess, struct se_cmd *se_cmd,
+int target_get_sess_cmd(struct se_session *se_sess, struct se_cmd *se_cmd,
 			       bool ack_kref)
 {
 	unsigned long flags;
@@ -2208,6 +2207,7 @@ out:
 	spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
 	return ret;
 }
+EXPORT_SYMBOL(target_get_sess_cmd);
 
 static void target_release_cmd_kref(struct kref *kref)
 {
@@ -2765,8 +2765,13 @@ transport_send_check_condition_and_sense(struct se_cmd *cmd,
 		/* CURRENT ERROR */
 		buffer[0] = 0x70;
 		buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
-		/* ILLEGAL REQUEST */
-		buffer[SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
+		/*
+		 * Returning ILLEGAL REQUEST would cause immediate IO errors on
+		 * Solaris initiators.  Returning NOT READY instead means the
+		 * operations will be retried a finite number of times and we
+		 * can survive intermittent errors.
+		 */
+		buffer[SPC_SENSE_KEY_OFFSET] = NOT_READY;
 		/* LOGICAL UNIT COMMUNICATION FAILURE */
 		buffer[SPC_ASC_KEY_OFFSET] = 0x08;
 		break;
diff --git a/drivers/target/tcm_fc/tfc_sess.c b/drivers/target/tcm_fc/tfc_sess.c
index 113f335..4859505 100644
--- a/drivers/target/tcm_fc/tfc_sess.c
+++ b/drivers/target/tcm_fc/tfc_sess.c
@@ -428,19 +428,12 @@ static int ft_prli(struct fc_rport_priv *rdata, u32 spp_len,
 	return ret;
 }
 
-static void ft_sess_rcu_free(struct rcu_head *rcu)
-{
-	struct ft_sess *sess = container_of(rcu, struct ft_sess, rcu);
-
-	kfree(sess);
-}
-
 static void ft_sess_free(struct kref *kref)
 {
 	struct ft_sess *sess = container_of(kref, struct ft_sess, kref);
 
 	transport_deregister_session(sess->se_sess);
-	call_rcu(&sess->rcu, ft_sess_rcu_free);
+	kfree_rcu(sess, rcu);
 }
 
 void ft_sess_put(struct ft_sess *sess)
diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index 8dc44cb..be2e6b0 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -168,8 +168,8 @@ static int cpufreq_apply_cooling(struct cpufreq_cooling_device *cpufreq_device,
 				unsigned long cooling_state)
 {
 	unsigned int cpuid, clip_freq;
-	struct cpumask *maskPtr = &cpufreq_device->allowed_cpus;
-	unsigned int cpu = cpumask_any(maskPtr);
+	struct cpumask *mask = &cpufreq_device->allowed_cpus;
+	unsigned int cpu = cpumask_any(mask);
 
 
 	/* Check if the old cooling action is same as new cooling action */
@@ -184,7 +184,7 @@ static int cpufreq_apply_cooling(struct cpufreq_cooling_device *cpufreq_device,
 	cpufreq_device->cpufreq_val = clip_freq;
 	notify_device = cpufreq_device;
 
-	for_each_cpu(cpuid, maskPtr) {
+	for_each_cpu(cpuid, mask) {
 		if (is_cpufreq_valid(cpuid))
 			cpufreq_update_policy(cpuid);
 	}
@@ -235,13 +235,13 @@ static int cpufreq_get_max_state(struct thermal_cooling_device *cdev,
 				 unsigned long *state)
 {
 	struct cpufreq_cooling_device *cpufreq_device = cdev->devdata;
-	struct cpumask *maskPtr = &cpufreq_device->allowed_cpus;
+	struct cpumask *mask = &cpufreq_device->allowed_cpus;
 	unsigned int cpu;
 	struct cpufreq_frequency_table *table;
 	unsigned long count = 0;
 	int i = 0;
 
-	cpu = cpumask_any(maskPtr);
+	cpu = cpumask_any(mask);
 	table = cpufreq_frequency_get_table(cpu);
 	if (!table) {
 		*state = 0;
diff --git a/drivers/thermal/db8500_thermal.c b/drivers/thermal/db8500_thermal.c
index 61ce60a..1e3b3bf 100644
--- a/drivers/thermal/db8500_thermal.c
+++ b/drivers/thermal/db8500_thermal.c
@@ -419,7 +419,8 @@ static int db8500_thermal_probe(struct platform_device *pdev)
 	low_irq = platform_get_irq_byname(pdev, "IRQ_HOTMON_LOW");
 	if (low_irq < 0) {
 		dev_err(&pdev->dev, "Get IRQ_HOTMON_LOW failed.\n");
-		return low_irq;
+		ret = low_irq;
+		goto out_unlock;
 	}
 
 	ret = devm_request_threaded_irq(&pdev->dev, low_irq, NULL,
@@ -427,13 +428,14 @@ static int db8500_thermal_probe(struct platform_device *pdev)
 		"dbx500_temp_low", pzone);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "Failed to allocate temp low irq.\n");
-		return ret;
+		goto out_unlock;
 	}
 
 	high_irq = platform_get_irq_byname(pdev, "IRQ_HOTMON_HIGH");
 	if (high_irq < 0) {
 		dev_err(&pdev->dev, "Get IRQ_HOTMON_HIGH failed.\n");
-		return high_irq;
+		ret = high_irq;
+		goto out_unlock;
 	}
 
 	ret = devm_request_threaded_irq(&pdev->dev, high_irq, NULL,
@@ -441,15 +443,16 @@ static int db8500_thermal_probe(struct platform_device *pdev)
 		"dbx500_temp_high", pzone);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "Failed to allocate temp high irq.\n");
-		return ret;
+		goto out_unlock;
 	}
 
 	pzone->therm_dev = thermal_zone_device_register("db8500_thermal_zone",
 		ptrips->num_trips, 0, pzone, &thdev_ops, NULL, 0, 0);
 
-	if (IS_ERR_OR_NULL(pzone->therm_dev)) {
+	if (IS_ERR(pzone->therm_dev)) {
 		dev_err(&pdev->dev, "Register thermal zone device failed.\n");
-		return PTR_ERR(pzone->therm_dev);
+		ret = PTR_ERR(pzone->therm_dev);
+		goto out_unlock;
 	}
 	dev_info(&pdev->dev, "Thermal zone device registered.\n");
 
@@ -461,9 +464,11 @@ static int db8500_thermal_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, pzone);
 	pzone->mode = THERMAL_DEVICE_ENABLED;
+
+out_unlock:
 	mutex_unlock(&pzone->th_lock);
 
-	return 0;
+	return ret;
 }
 
 static int db8500_thermal_remove(struct platform_device *pdev)
diff --git a/drivers/thermal/dove_thermal.c b/drivers/thermal/dove_thermal.c
index 3078c40..4b15a5f 100644
--- a/drivers/thermal/dove_thermal.c
+++ b/drivers/thermal/dove_thermal.c
@@ -107,12 +107,13 @@ static int dove_get_temp(struct thermal_zone_device *thermal,
 	}
 
 	/*
-	 * Calculate temperature. See Section 8.10.1 of 88AP510,
-	 * Documentation/arm/Marvell/README
+	 * Calculate temperature. According to Marvell internal
+	 * documentation the formula for this is:
+	 * Celsius = (322-reg)/1.3625
 	 */
 	reg = readl_relaxed(priv->sensor);
 	reg = (reg >> DOVE_THERMAL_TEMP_OFFSET) & DOVE_THERMAL_TEMP_MASK;
-	*temp = ((2281638UL - (7298*reg)) / 10);
+	*temp = ((3220000000UL - (10000000UL * reg)) / 13625);
 
 	return 0;
 }
diff --git a/drivers/thermal/kirkwood_thermal.c b/drivers/thermal/kirkwood_thermal.c
index e5500ed..dfeceaf 100644
--- a/drivers/thermal/kirkwood_thermal.c
+++ b/drivers/thermal/kirkwood_thermal.c
@@ -41,21 +41,21 @@ static int kirkwood_get_temp(struct thermal_zone_device *thermal,
 	reg = readl_relaxed(priv->sensor);
 
 	/* Valid check */
-	if (!(reg >> KIRKWOOD_THERMAL_VALID_OFFSET) &
-	    KIRKWOOD_THERMAL_VALID_MASK) {
+	if (!((reg >> KIRKWOOD_THERMAL_VALID_OFFSET) &
+	    KIRKWOOD_THERMAL_VALID_MASK)) {
 		dev_err(&thermal->device,
 			"Temperature sensor reading not valid\n");
 		return -EIO;
 	}
 
 	/*
-	 * Calculate temperature. See Section 8.10.1 of the 88AP510,
-	 * datasheet, which has the same sensor.
-	 * Documentation/arm/Marvell/README
+	 * Calculate temperature. According to Marvell internal
+	 * documentation the formula for this is:
+	 * Celsius = (322-reg)/1.3625
 	 */
 	reg = (reg >> KIRKWOOD_THERMAL_TEMP_OFFSET) &
 		KIRKWOOD_THERMAL_TEMP_MASK;
-	*temp = ((2281638UL - (7298*reg)) / 10);
+	*temp = ((3220000000UL - (10000000UL * reg)) / 13625);
 
 	return 0;
 }
diff --git a/drivers/tty/amiserial.c b/drivers/tty/amiserial.c
index fc70034..083710e 100644
--- a/drivers/tty/amiserial.c
+++ b/drivers/tty/amiserial.c
@@ -1798,19 +1798,7 @@ static struct platform_driver amiga_serial_driver = {
 	},
 };
 
-static int __init amiga_serial_init(void)
-{
-	return platform_driver_probe(&amiga_serial_driver, amiga_serial_probe);
-}
-
-module_init(amiga_serial_init);
-
-static void __exit amiga_serial_exit(void)
-{
-	platform_driver_unregister(&amiga_serial_driver);
-}
-
-module_exit(amiga_serial_exit);
+module_platform_driver_probe(amiga_serial_driver, amiga_serial_probe);
 
 
 #if defined(CONFIG_SERIAL_CONSOLE) && !defined(MODULE)
diff --git a/drivers/tty/cyclades.c b/drivers/tty/cyclades.c
index 345bd0e..33f83fe 100644
--- a/drivers/tty/cyclades.c
+++ b/drivers/tty/cyclades.c
@@ -1124,14 +1124,8 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo)
 					readl(&info->u.cyz.ch_ctrl->rs_status);
 				if (dcd & C_RS_DCD)
 					wake_up_interruptible(&info->port.open_wait);
-				else {
-					struct tty_struct *tty;
-					tty = tty_port_tty_get(&info->port);
-					if (tty) {
-						tty_hangup(tty);
-						tty_kref_put(tty);
-					}
-				}
+				else
+					tty_port_tty_hangup(&info->port, false);
 			}
 			break;
 		case C_CM_MCTS:
diff --git a/drivers/tty/ehv_bytechan.c b/drivers/tty/ehv_bytechan.c
index ed92622..6d0c27c 100644
--- a/drivers/tty/ehv_bytechan.c
+++ b/drivers/tty/ehv_bytechan.c
@@ -472,13 +472,9 @@ static void ehv_bc_tx_dequeue(struct ehv_bc_data *bc)
 static irqreturn_t ehv_bc_tty_tx_isr(int irq, void *data)
 {
 	struct ehv_bc_data *bc = data;
-	struct tty_struct *ttys = tty_port_tty_get(&bc->port);
 
 	ehv_bc_tx_dequeue(bc);
-	if (ttys) {
-		tty_wakeup(ttys);
-		tty_kref_put(ttys);
-	}
+	tty_port_tty_wakeup(&bc->port);
 
 	return IRQ_HANDLED;
 }
diff --git a/drivers/tty/hvc/hvsi.c b/drivers/tty/hvc/hvsi.c
index ef95a15..4190199 100644
--- a/drivers/tty/hvc/hvsi.c
+++ b/drivers/tty/hvc/hvsi.c
@@ -861,7 +861,6 @@ static void hvsi_write_worker(struct work_struct *work)
 {
 	struct hvsi_struct *hp =
 		container_of(work, struct hvsi_struct, writer.work);
-	struct tty_struct *tty;
 	unsigned long flags;
 #ifdef DEBUG
 	static long start_j = 0;
@@ -895,11 +894,7 @@ static void hvsi_write_worker(struct work_struct *work)
 		start_j = 0;
 #endif /* DEBUG */
 		wake_up_all(&hp->emptyq);
-		tty = tty_port_tty_get(&hp->port);
-		if (tty) {
-			tty_wakeup(tty);
-			tty_kref_put(tty);
-		}
+		tty_port_tty_wakeup(&hp->port);
 	}
 
 out:
diff --git a/drivers/tty/ipwireless/hardware.c b/drivers/tty/ipwireless/hardware.c
index 97a511f..2c14842 100644
--- a/drivers/tty/ipwireless/hardware.c
+++ b/drivers/tty/ipwireless/hardware.c
@@ -1732,8 +1732,7 @@ void ipwireless_hardware_free(struct ipw_hardware *hw)
 	flush_work(&hw->work_rx);
 
 	for (i = 0; i < NL_NUM_OF_ADDRESSES; i++)
-		if (hw->packet_assembler[i] != NULL)
-			kfree(hw->packet_assembler[i]);
+		kfree(hw->packet_assembler[i]);
 
 	for (i = 0; i < NL_NUM_OF_PRIORITIES; i++)
 		list_for_each_entry_safe(tp, tq, &hw->tx_queue[i], queue) {
diff --git a/drivers/tty/moxa.c b/drivers/tty/moxa.c
index adeac25..1deaca4 100644
--- a/drivers/tty/moxa.c
+++ b/drivers/tty/moxa.c
@@ -913,16 +913,12 @@ static void moxa_board_deinit(struct moxa_board_conf *brd)
 
 	/* pci hot-un-plug support */
 	for (a = 0; a < brd->numPorts; a++)
-		if (brd->ports[a].port.flags & ASYNC_INITIALIZED) {
-			struct tty_struct *tty = tty_port_tty_get(
-						&brd->ports[a].port);
-			if (tty) {
-				tty_hangup(tty);
-				tty_kref_put(tty);
-			}
-		}
+		if (brd->ports[a].port.flags & ASYNC_INITIALIZED)
+			tty_port_tty_hangup(&brd->ports[a].port, false);
+
 	for (a = 0; a < MAX_PORTS_PER_BOARD; a++)
 		tty_port_destroy(&brd->ports[a].port);
+
 	while (1) {
 		opened = 0;
 		for (a = 0; a < brd->numPorts; a++)
@@ -1365,7 +1361,6 @@ static void moxa_hangup(struct tty_struct *tty)
 
 static void moxa_new_dcdstate(struct moxa_port *p, u8 dcd)
 {
-	struct tty_struct *tty;
 	unsigned long flags;
 	dcd = !!dcd;
 
@@ -1373,10 +1368,8 @@ static void moxa_new_dcdstate(struct moxa_port *p, u8 dcd)
 	if (dcd != p->DCDState) {
         	p->DCDState = dcd;
         	spin_unlock_irqrestore(&p->port.lock, flags);
-		tty = tty_port_tty_get(&p->port);
-		if (tty && !C_CLOCAL(tty) && !dcd)
-			tty_hangup(tty);
-		tty_kref_put(tty);
+		if (!dcd)
+			tty_port_tty_hangup(&p->port, true);
 	}
 	else
 		spin_unlock_irqrestore(&p->port.lock, flags);
diff --git a/drivers/tty/mxser.c b/drivers/tty/mxser.c
index 484b6a3..d996038 100644
--- a/drivers/tty/mxser.c
+++ b/drivers/tty/mxser.c
@@ -1084,6 +1084,10 @@ static void mxser_close(struct tty_struct *tty, struct file *filp)
 	mutex_lock(&port->mutex);
 	mxser_close_port(port);
 	mxser_flush_buffer(tty);
+	if (test_bit(ASYNCB_INITIALIZED, &port->flags)) {
+		if (C_HUPCL(tty))
+			tty_port_lower_dtr_rts(port);
+	}
 	mxser_shutdown_port(port);
 	clear_bit(ASYNCB_INITIALIZED, &port->flags);
 	mutex_unlock(&port->mutex);
diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c
index 4a43ef5d7..6422390 100644
--- a/drivers/tty/n_gsm.c
+++ b/drivers/tty/n_gsm.c
@@ -1418,11 +1418,7 @@ static void gsm_dlci_close(struct gsm_dlci *dlci)
 		pr_debug("DLCI %d goes closed.\n", dlci->addr);
 	dlci->state = DLCI_CLOSED;
 	if (dlci->addr != 0) {
-		struct tty_struct  *tty = tty_port_tty_get(&dlci->port);
-		if (tty) {
-			tty_hangup(tty);
-			tty_kref_put(tty);
-		}
+		tty_port_tty_hangup(&dlci->port, false);
 		kfifo_reset(dlci->fifo);
 	} else
 		dlci->gsm->dead = 1;
@@ -2968,6 +2964,10 @@ static void gsmtty_close(struct tty_struct *tty, struct file *filp)
 	if (tty_port_close_start(&dlci->port, tty, filp) == 0)
 		goto out;
 	gsm_dlci_begin_close(dlci);
+	if (test_bit(ASYNCB_INITIALIZED, &dlci->port.flags)) {
+		if (C_HUPCL(tty))
+			tty_port_lower_dtr_rts(&dlci->port);
+	}
 	tty_port_close_end(&dlci->port, tty);
 	tty_port_tty_set(&dlci->port, NULL);
 out:
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c
index 05e72be..d655416 100644
--- a/drivers/tty/n_tty.c
+++ b/drivers/tty/n_tty.c
@@ -153,6 +153,12 @@ static void n_tty_set_room(struct tty_struct *tty)
 	if (left && !old_left) {
 		WARN_RATELIMIT(tty->port->itty == NULL,
 				"scheduling with invalid itty\n");
+		/* see if ldisc has been killed - if so, this means that
+		 * even though the ldisc has been halted and ->buf.work
+		 * cancelled, ->buf.work is about to be rescheduled
+		 */
+		WARN_RATELIMIT(test_bit(TTY_LDISC_HALTED, &tty->flags),
+			       "scheduling buffer work for halted ldisc\n");
 		schedule_work(&tty->port->buf.work);
 	}
 }
@@ -189,34 +195,17 @@ static void put_tty_queue(unsigned char c, struct n_tty_data *ldata)
 }
 
 /**
- *	check_unthrottle	-	allow new receive data
- *	@tty; tty device
- *
- *	Check whether to call the driver unthrottle functions
- *
- *	Can sleep, may be called under the atomic_read_lock mutex but
- *	this is not guaranteed.
- */
-static void check_unthrottle(struct tty_struct *tty)
-{
-	if (tty->count)
-		tty_unthrottle(tty);
-}
-
-/**
  *	reset_buffer_flags	-	reset buffer state
  *	@tty: terminal to reset
  *
- *	Reset the read buffer counters, clear the flags,
- *	and make sure the driver is unthrottled. Called
- *	from n_tty_open() and n_tty_flush_buffer().
+ *	Reset the read buffer counters and clear the flags.
+ *	Called from n_tty_open() and n_tty_flush_buffer().
  *
  *	Locking: tty_read_lock for read fields.
  */
 
-static void reset_buffer_flags(struct tty_struct *tty)
+static void reset_buffer_flags(struct n_tty_data *ldata)
 {
-	struct n_tty_data *ldata = tty->disc_data;
 	unsigned long flags;
 
 	raw_spin_lock_irqsave(&ldata->read_lock, flags);
@@ -229,36 +218,38 @@ static void reset_buffer_flags(struct tty_struct *tty)
 
 	ldata->canon_head = ldata->canon_data = ldata->erasing = 0;
 	bitmap_zero(ldata->read_flags, N_TTY_BUF_SIZE);
-	n_tty_set_room(tty);
+}
+
+static void n_tty_packet_mode_flush(struct tty_struct *tty)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&tty->ctrl_lock, flags);
+	if (tty->link->packet) {
+		tty->ctrl_status |= TIOCPKT_FLUSHREAD;
+		wake_up_interruptible(&tty->link->read_wait);
+	}
+	spin_unlock_irqrestore(&tty->ctrl_lock, flags);
 }
 
 /**
  *	n_tty_flush_buffer	-	clean input queue
  *	@tty:	terminal device
  *
- *	Flush the input buffer. Called when the line discipline is
- *	being closed, when the tty layer wants the buffer flushed (eg
- *	at hangup) or when the N_TTY line discipline internally has to
- *	clean the pending queue (for example some signals).
+ *	Flush the input buffer. Called when the tty layer wants the
+ *	buffer flushed (eg at hangup) or when the N_TTY line discipline
+ *	internally has to clean the pending queue (for example some signals).
  *
  *	Locking: ctrl_lock, read_lock.
  */
 
 static void n_tty_flush_buffer(struct tty_struct *tty)
 {
-	unsigned long flags;
-	/* clear everything and unthrottle the driver */
-	reset_buffer_flags(tty);
-
-	if (!tty->link)
-		return;
+	reset_buffer_flags(tty->disc_data);
+	n_tty_set_room(tty);
 
-	spin_lock_irqsave(&tty->ctrl_lock, flags);
-	if (tty->link->packet) {
-		tty->ctrl_status |= TIOCPKT_FLUSHREAD;
-		wake_up_interruptible(&tty->link->read_wait);
-	}
-	spin_unlock_irqrestore(&tty->ctrl_lock, flags);
+	if (tty->link)
+		n_tty_packet_mode_flush(tty);
 }
 
 /**
@@ -1032,23 +1023,19 @@ static void eraser(unsigned char c, struct tty_struct *tty)
  *	isig		-	handle the ISIG optio
  *	@sig: signal
  *	@tty: terminal
- *	@flush: force flush
  *
- *	Called when a signal is being sent due to terminal input. This
- *	may caus terminal flushing to take place according to the termios
- *	settings and character used. Called from the driver receive_buf
- *	path so serialized.
+ *	Called when a signal is being sent due to terminal input.
+ *	Called from the driver receive_buf path so serialized.
  *
- *	Locking: ctrl_lock, read_lock (both via flush buffer)
+ *	Locking: ctrl_lock
  */
 
-static inline void isig(int sig, struct tty_struct *tty, int flush)
+static inline void isig(int sig, struct tty_struct *tty)
 {
-	if (tty->pgrp)
-		kill_pgrp(tty->pgrp, sig, 1);
-	if (flush || !L_NOFLSH(tty)) {
-		n_tty_flush_buffer(tty);
-		tty_driver_flush_buffer(tty);
+	struct pid *tty_pgrp = tty_get_pgrp(tty);
+	if (tty_pgrp) {
+		kill_pgrp(tty_pgrp, sig, 1);
+		put_pid(tty_pgrp);
 	}
 }
 
@@ -1069,7 +1056,11 @@ static inline void n_tty_receive_break(struct tty_struct *tty)
 	if (I_IGNBRK(tty))
 		return;
 	if (I_BRKINT(tty)) {
-		isig(SIGINT, tty, 1);
+		isig(SIGINT, tty);
+		if (!L_NOFLSH(tty)) {
+			n_tty_flush_buffer(tty);
+			tty_driver_flush_buffer(tty);
+		}
 		return;
 	}
 	if (I_PARMRK(tty)) {
@@ -1236,11 +1227,6 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
 		signal = SIGTSTP;
 		if (c == SUSP_CHAR(tty)) {
 send_signal:
-			/*
-			 * Note that we do not use isig() here because we want
-			 * the order to be:
-			 * 1) flush, 2) echo, 3) signal
-			 */
 			if (!L_NOFLSH(tty)) {
 				n_tty_flush_buffer(tty);
 				tty_driver_flush_buffer(tty);
@@ -1251,8 +1237,7 @@ send_signal:
 				echo_char(c, tty);
 				process_echoes(tty);
 			}
-			if (tty->pgrp)
-				kill_pgrp(tty->pgrp, signal, 1);
+			isig(signal, tty);
 			return;
 		}
 	}
@@ -1483,14 +1468,14 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
 	 * mode.  We don't want to throttle the driver if we're in
 	 * canonical mode and don't have a newline yet!
 	 */
-	if (tty->receive_room < TTY_THRESHOLD_THROTTLE)
-		tty_throttle(tty);
-
-        /* FIXME: there is a tiny race here if the receive room check runs
-           before the other work executes and empties the buffer (upping
-           the receiving room and unthrottling. We then throttle and get
-           stuck. This has been observed and traced down by Vincent Pillet/
-           We need to address this when we sort out out the rx path locking */
+	while (1) {
+		tty_set_flow_change(tty, TTY_THROTTLE_SAFE);
+		if (tty->receive_room >= TTY_THRESHOLD_THROTTLE)
+			break;
+		if (!tty_throttle_safe(tty))
+			break;
+	}
+	__tty_set_flow_change(tty, 0);
 }
 
 int is_ignored(int sig)
@@ -1607,7 +1592,9 @@ static void n_tty_close(struct tty_struct *tty)
 {
 	struct n_tty_data *ldata = tty->disc_data;
 
-	n_tty_flush_buffer(tty);
+	if (tty->link)
+		n_tty_packet_mode_flush(tty);
+
 	kfree(ldata->read_buf);
 	kfree(ldata->echo_buf);
 	kfree(ldata);
@@ -1645,12 +1632,14 @@ static int n_tty_open(struct tty_struct *tty)
 		goto err_free_bufs;
 
 	tty->disc_data = ldata;
-	reset_buffer_flags(tty);
-	tty_unthrottle(tty);
+	reset_buffer_flags(tty->disc_data);
 	ldata->column = 0;
-	n_tty_set_termios(tty, NULL);
 	tty->minimum_to_wake = 1;
 	tty->closing = 0;
+	/* indicate buffer work may resume */
+	clear_bit(TTY_LDISC_HALTED, &tty->flags);
+	n_tty_set_termios(tty, NULL);
+	tty_unthrottle(tty);
 
 	return 0;
 err_free_bufs:
@@ -1740,10 +1729,9 @@ extern ssize_t redirected_tty_write(struct file *, const char __user *,
  *	and if appropriate send any needed signals and return a negative
  *	error code if action should be taken.
  *
- *	FIXME:
- *	Locking: None - redirected write test is safe, testing
- *	current->signal should possibly lock current->sighand
- *	pgrp locking ?
+ *	Locking: redirected write test is safe
+ *		 current->signal->tty check is safe
+ *		 ctrl_lock to safely reference tty->pgrp
  */
 
 static int job_control(struct tty_struct *tty, struct file *file)
@@ -1753,19 +1741,22 @@ static int job_control(struct tty_struct *tty, struct file *file)
 	/* NOTE: not yet done after every sleep pending a thorough
 	   check of the logic of this change. -- jlc */
 	/* don't stop on /dev/console */
-	if (file->f_op->write != redirected_tty_write &&
-	    current->signal->tty == tty) {
-		if (!tty->pgrp)
-			printk(KERN_ERR "n_tty_read: no tty->pgrp!\n");
-		else if (task_pgrp(current) != tty->pgrp) {
-			if (is_ignored(SIGTTIN) ||
-			    is_current_pgrp_orphaned())
-				return -EIO;
-			kill_pgrp(task_pgrp(current), SIGTTIN, 1);
-			set_thread_flag(TIF_SIGPENDING);
-			return -ERESTARTSYS;
-		}
+	if (file->f_op->write == redirected_tty_write ||
+	    current->signal->tty != tty)
+		return 0;
+
+	spin_lock_irq(&tty->ctrl_lock);
+	if (!tty->pgrp)
+		printk(KERN_ERR "n_tty_read: no tty->pgrp!\n");
+	else if (task_pgrp(current) != tty->pgrp) {
+		spin_unlock_irq(&tty->ctrl_lock);
+		if (is_ignored(SIGTTIN) || is_current_pgrp_orphaned())
+			return -EIO;
+		kill_pgrp(task_pgrp(current), SIGTTIN, 1);
+		set_thread_flag(TIF_SIGPENDING);
+		return -ERESTARTSYS;
 	}
+	spin_unlock_irq(&tty->ctrl_lock);
 	return 0;
 }
 
@@ -1959,10 +1950,17 @@ do_it_again:
 		 * longer than TTY_THRESHOLD_UNTHROTTLE in canonical mode,
 		 * we won't get any more characters.
 		 */
-		if (n_tty_chars_in_buffer(tty) <= TTY_THRESHOLD_UNTHROTTLE) {
+		while (1) {
+			tty_set_flow_change(tty, TTY_UNTHROTTLE_SAFE);
+			if (n_tty_chars_in_buffer(tty) > TTY_THRESHOLD_UNTHROTTLE)
+				break;
+			if (!tty->count)
+				break;
 			n_tty_set_room(tty);
-			check_unthrottle(tty);
+			if (!tty_unthrottle_safe(tty))
+				break;
 		}
+		__tty_set_flow_change(tty, 0);
 
 		if (b - buf >= minimum)
 			break;
diff --git a/drivers/tty/nozomi.c b/drivers/tty/nozomi.c
index 2dff197..d6080c3 100644
--- a/drivers/tty/nozomi.c
+++ b/drivers/tty/nozomi.c
@@ -791,7 +791,6 @@ static int send_data(enum port_type index, struct nozomi *dc)
 	const u8 toggle = port->toggle_ul;
 	void __iomem *addr = port->ul_addr[toggle];
 	const u32 ul_size = port->ul_size[toggle];
-	struct tty_struct *tty = tty_port_tty_get(&port->port);
 
 	/* Get data from tty and place in buf for now */
 	size = kfifo_out(&port->fifo_ul, dc->send_buf,
@@ -799,7 +798,6 @@ static int send_data(enum port_type index, struct nozomi *dc)
 
 	if (size == 0) {
 		DBG4("No more data to send, disable link:");
-		tty_kref_put(tty);
 		return 0;
 	}
 
@@ -809,10 +807,8 @@ static int send_data(enum port_type index, struct nozomi *dc)
 	write_mem32(addr, (u32 *) &size, 4);
 	write_mem32(addr + 4, (u32 *) dc->send_buf, size);
 
-	if (tty)
-		tty_wakeup(tty);
+	tty_port_tty_wakeup(&port->port);
 
-	tty_kref_put(tty);
 	return 1;
 }
 
@@ -1505,12 +1501,9 @@ static void tty_exit(struct nozomi *dc)
 
 	DBG1(" ");
 
-	for (i = 0; i < MAX_PORT; ++i) {
-		struct tty_struct *tty = tty_port_tty_get(&dc->port[i].port);
-		if (tty && list_empty(&tty->hangup_work.entry))
-			tty_hangup(tty);
-		tty_kref_put(tty);
-	}
+	for (i = 0; i < MAX_PORT; ++i)
+		tty_port_tty_hangup(&dc->port[i].port, false);
+
 	/* Racy below - surely should wait for scheduled work to be done or
 	   complete off a hangup method ? */
 	while (dc->open_ttys)
diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c
index c24b4db..71e456a 100644
--- a/drivers/tty/pty.c
+++ b/drivers/tty/pty.c
@@ -413,7 +413,6 @@ static void pty_unix98_shutdown(struct tty_struct *tty)
 
 static void pty_cleanup(struct tty_struct *tty)
 {
-	tty->port->itty = NULL;
 	tty_port_put(tty->port);
 }
 
diff --git a/drivers/tty/rocket.c b/drivers/tty/rocket.c
index 1d27003..f5abc28 100644
--- a/drivers/tty/rocket.c
+++ b/drivers/tty/rocket.c
@@ -449,7 +449,7 @@ static void rp_do_transmit(struct r_port *info)
 
 	/*  Loop sending data to FIFO until done or FIFO full */
 	while (1) {
-		if (tty->stopped || tty->hw_stopped)
+		if (tty->stopped)
 			break;
 		c = min(info->xmit_fifo_room, info->xmit_cnt);
 		c = min(c, XMIT_BUF_SIZE - info->xmit_tail);
@@ -521,15 +521,10 @@ static void rp_handle_port(struct r_port *info)
 		       (ChanStatus & CD_ACT) ? "on" : "off");
 #endif
 		if (!(ChanStatus & CD_ACT) && info->cd_status) {
-			struct tty_struct *tty;
 #ifdef ROCKET_DEBUG_HANGUP
 			printk(KERN_INFO "CD drop, calling hangup.\n");
 #endif
-			tty = tty_port_tty_get(&info->port);
-			if (tty) {
-				tty_hangup(tty);
-				tty_kref_put(tty);
-			}
+			tty_port_tty_hangup(&info->port, false);
 		}
 		info->cd_status = (ChanStatus & CD_ACT) ? 1 : 0;
 		wake_up_interruptible(&info->port.open_wait);
@@ -1111,15 +1106,12 @@ static void rp_set_termios(struct tty_struct *tty,
 
 	/* Handle transition away from B0 status */
 	if (!(old_termios->c_cflag & CBAUD) && (tty->termios.c_cflag & CBAUD)) {
-		if (!tty->hw_stopped || !(tty->termios.c_cflag & CRTSCTS))
-			sSetRTS(cp);
+		sSetRTS(cp);
 		sSetDTR(cp);
 	}
 
-	if ((old_termios->c_cflag & CRTSCTS) && !(tty->termios.c_cflag & CRTSCTS)) {
-		tty->hw_stopped = 0;
+	if ((old_termios->c_cflag & CRTSCTS) && !(tty->termios.c_cflag & CRTSCTS))
 		rp_start(tty);
-	}
 }
 
 static int rp_break(struct tty_struct *tty, int break_state)
@@ -1575,10 +1567,10 @@ static int rp_put_char(struct tty_struct *tty, unsigned char ch)
 	spin_lock_irqsave(&info->slock, flags);
 	cp = &info->channel;
 
-	if (!tty->stopped && !tty->hw_stopped && info->xmit_fifo_room == 0)
+	if (!tty->stopped && info->xmit_fifo_room == 0)
 		info->xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
 
-	if (tty->stopped || tty->hw_stopped || info->xmit_fifo_room == 0 || info->xmit_cnt != 0) {
+	if (tty->stopped || info->xmit_fifo_room == 0 || info->xmit_cnt != 0) {
 		info->xmit_buf[info->xmit_head++] = ch;
 		info->xmit_head &= XMIT_BUF_SIZE - 1;
 		info->xmit_cnt++;
@@ -1619,14 +1611,14 @@ static int rp_write(struct tty_struct *tty,
 #endif
 	cp = &info->channel;
 
-	if (!tty->stopped && !tty->hw_stopped && info->xmit_fifo_room < count)
+	if (!tty->stopped && info->xmit_fifo_room < count)
 		info->xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
 
         /*
 	 *  If the write queue for the port is empty, and there is FIFO space, stuff bytes 
 	 *  into FIFO.  Use the write queue for temp storage.
          */
-	if (!tty->stopped && !tty->hw_stopped && info->xmit_cnt == 0 && info->xmit_fifo_room > 0) {
+	if (!tty->stopped && info->xmit_cnt == 0 && info->xmit_fifo_room > 0) {
 		c = min(count, info->xmit_fifo_room);
 		b = buf;
 
@@ -1674,7 +1666,7 @@ static int rp_write(struct tty_struct *tty,
 		retval += c;
 	}
 
-	if ((retval > 0) && !tty->stopped && !tty->hw_stopped)
+	if ((retval > 0) && !tty->stopped)
 		set_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
 	
 end:
diff --git a/drivers/tty/serial/68328serial.c b/drivers/tty/serial/68328serial.c
index 4939947..ef2e08e 100644
--- a/drivers/tty/serial/68328serial.c
+++ b/drivers/tty/serial/68328serial.c
@@ -630,8 +630,7 @@ static void rs_flush_chars(struct tty_struct *tty)
 	/* Enable transmitter */
 	local_irq_save(flags);
 
-	if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
-			!info->xmit_buf) {
+	if (info->xmit_cnt <= 0 || tty->stopped || !info->xmit_buf) {
 		local_irq_restore(flags);
 		return;
 	}
@@ -697,7 +696,7 @@ static int rs_write(struct tty_struct * tty,
 		total += c;
 	}
 
-	if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped) {
+	if (info->xmit_cnt && !tty->stopped) {
 		/* Enable transmitter */
 		local_irq_disable();		
 #ifndef USE_INTS
@@ -978,10 +977,8 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 	change_speed(info, tty);
 
 	if ((old_termios->c_cflag & CRTSCTS) &&
-	    !(tty->termios.c_cflag & CRTSCTS)) {
-		tty->hw_stopped = 0;
+	    !(tty->termios.c_cflag & CRTSCTS))
 		rs_start(tty);
-	}
 	
 }
 
diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h
index 34eb676..1ebf853 100644
--- a/drivers/tty/serial/8250/8250.h
+++ b/drivers/tty/serial/8250/8250.h
@@ -117,13 +117,6 @@ static inline void serial_dl_write(struct uart_8250_port *up, int value)
  * is cleared, the machine locks up with endless interrupts.
  */
 #define ALPHA_KLUDGE_MCR  (UART_MCR_OUT2 | UART_MCR_OUT1)
-#elif defined(CONFIG_SBC8560)
-/*
- * WindRiver did something similarly broken on their SBC8560 board. The
- * UART tristates its IRQ output while OUT2 is clear, but they pulled
- * the interrupt line _up_ instead of down, so if we register the IRQ
- * while the UART is in that state, we die in an IRQ storm. */
-#define ALPHA_KLUDGE_MCR (UART_MCR_OUT2)
 #else
 #define ALPHA_KLUDGE_MCR 0
 #endif
diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
index 35f9c96..46528d5 100644
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -2755,7 +2755,7 @@ static void __init serial8250_isa_init_ports(void)
 	if (nr_uarts > UART_NR)
 		nr_uarts = UART_NR;
 
-	for (i = 0; i < nr_uarts; i++) {
+	for (i = 0; i < UART_NR; i++) {
 		struct uart_8250_port *up = &serial8250_ports[i];
 		struct uart_port *port = &up->port;
 
@@ -2916,7 +2916,7 @@ static int __init serial8250_console_setup(struct console *co, char *options)
 	 * if so, search for the first available port that does have
 	 * console support.
 	 */
-	if (co->index >= nr_uarts)
+	if (co->index >= UART_NR)
 		co->index = 0;
 	port = &serial8250_ports[co->index].port;
 	if (!port->iobase && !port->membase)
@@ -2957,7 +2957,7 @@ int serial8250_find_port(struct uart_port *p)
 	int line;
 	struct uart_port *port;
 
-	for (line = 0; line < nr_uarts; line++) {
+	for (line = 0; line < UART_NR; line++) {
 		port = &serial8250_ports[line].port;
 		if (uart_match_port(p, port))
 			return line;
@@ -3110,7 +3110,7 @@ static int serial8250_remove(struct platform_device *dev)
 {
 	int i;
 
-	for (i = 0; i < nr_uarts; i++) {
+	for (i = 0; i < UART_NR; i++) {
 		struct uart_8250_port *up = &serial8250_ports[i];
 
 		if (up->port.dev == &dev->dev)
@@ -3178,7 +3178,7 @@ static struct uart_8250_port *serial8250_find_match_or_unused(struct uart_port *
 	/*
 	 * First, find a port entry which matches.
 	 */
-	for (i = 0; i < nr_uarts; i++)
+	for (i = 0; i < UART_NR; i++)
 		if (uart_match_port(&serial8250_ports[i].port, port))
 			return &serial8250_ports[i];
 
@@ -3187,7 +3187,7 @@ static struct uart_8250_port *serial8250_find_match_or_unused(struct uart_port *
 	 * free entry.  We look for one which hasn't been previously
 	 * used (indicated by zero iobase).
 	 */
-	for (i = 0; i < nr_uarts; i++)
+	for (i = 0; i < UART_NR; i++)
 		if (serial8250_ports[i].port.type == PORT_UNKNOWN &&
 		    serial8250_ports[i].port.iobase == 0)
 			return &serial8250_ports[i];
@@ -3196,7 +3196,7 @@ static struct uart_8250_port *serial8250_find_match_or_unused(struct uart_port *
 	 * That also failed.  Last resort is to find any entry which
 	 * doesn't have a real port associated with it.
 	 */
-	for (i = 0; i < nr_uarts; i++)
+	for (i = 0; i < UART_NR; i++)
 		if (serial8250_ports[i].port.type == PORT_UNKNOWN)
 			return &serial8250_ports[i];
 
@@ -3247,6 +3247,10 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
 		uart->tx_loadsz		= up->tx_loadsz;
 		uart->capabilities	= up->capabilities;
 
+		/* Take tx_loadsz from fifosize if it wasn't set separately */
+		if (uart->port.fifosize && !uart->tx_loadsz)
+			uart->tx_loadsz = uart->port.fifosize;
+
 		if (up->port.dev)
 			uart->port.dev = up->port.dev;
 
diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
index db0e66f..3dedd24 100644
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -26,6 +26,7 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/acpi.h>
+#include <linux/clk.h>
 
 #include "8250.h"
 
@@ -55,8 +56,9 @@
 
 
 struct dw8250_data {
-	int	last_lcr;
-	int	line;
+	int		last_lcr;
+	int		line;
+	struct clk	*clk;
 };
 
 static void dw8250_serial_out(struct uart_port *p, int offset, int value)
@@ -136,8 +138,13 @@ static int dw8250_probe_of(struct uart_port *p)
 	if (!of_property_read_u32(np, "reg-shift", &val))
 		p->regshift = val;
 
+	/* clock got configured through clk api, all done */
+	if (p->uartclk)
+		return 0;
+
+	/* try to find out clock frequency from DT as fallback */
 	if (of_property_read_u32(np, "clock-frequency", &val)) {
-		dev_err(p->dev, "no clock-frequency property set\n");
+		dev_err(p->dev, "clk or clock-frequency not defined\n");
 		return -EINVAL;
 	}
 	p->uartclk = val;
@@ -294,9 +301,20 @@ static int dw8250_probe(struct platform_device *pdev)
 	if (!uart.port.membase)
 		return -ENOMEM;
 
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->clk = devm_clk_get(&pdev->dev, NULL);
+	if (!IS_ERR(data->clk)) {
+		clk_prepare_enable(data->clk);
+		uart.port.uartclk = clk_get_rate(data->clk);
+	}
+
 	uart.port.iotype = UPIO_MEM;
 	uart.port.serial_in = dw8250_serial_in;
 	uart.port.serial_out = dw8250_serial_out;
+	uart.port.private_data = data;
 
 	dw8250_setup_port(&uart);
 
@@ -312,12 +330,6 @@ static int dw8250_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
-	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
-	if (!data)
-		return -ENOMEM;
-
-	uart.port.private_data = data;
-
 	data->line = serial8250_register_8250_port(&uart);
 	if (data->line < 0)
 		return data->line;
@@ -333,6 +345,9 @@ static int dw8250_remove(struct platform_device *pdev)
 
 	serial8250_unregister_port(data->line);
 
+	if (!IS_ERR(data->clk))
+		clk_disable_unprepare(data->clk);
+
 	return 0;
 }
 
diff --git a/drivers/tty/serial/8250/serial_cs.c b/drivers/tty/serial/8250/serial_cs.c
index b7d48b3..1b74b88 100644
--- a/drivers/tty/serial/8250/serial_cs.c
+++ b/drivers/tty/serial/8250/serial_cs.c
@@ -852,18 +852,6 @@ static struct pcmcia_driver serial_cs_driver = {
 	.suspend	= serial_suspend,
 	.resume		= serial_resume,
 };
-
-static int __init init_serial_cs(void)
-{
-	return pcmcia_register_driver(&serial_cs_driver);
-}
-
-static void __exit exit_serial_cs(void)
-{
-	pcmcia_unregister_driver(&serial_cs_driver);
-}
-
-module_init(init_serial_cs);
-module_exit(exit_serial_cs);
+module_pcmcia_driver(serial_cs_driver);
 
 MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index 3ea5408..6cf861e 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -29,6 +29,7 @@
  * and hooked into this driver.
  */
 
+
 #if defined(CONFIG_SERIAL_AMBA_PL011_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
 #define SUPPORT_SYSRQ
 #endif
@@ -117,6 +118,12 @@ struct pl011_dmarx_data {
 	struct pl011_sgbuf	sgbuf_b;
 	dma_cookie_t		cookie;
 	bool			running;
+	struct timer_list	timer;
+	unsigned int last_residue;
+	unsigned long last_jiffies;
+	bool auto_poll_rate;
+	unsigned int poll_rate;
+	unsigned int poll_timeout;
 };
 
 struct pl011_dmatx_data {
@@ -223,16 +230,18 @@ static int pl011_fifo_to_tty(struct uart_amba_port *uap)
 static int pl011_sgbuf_init(struct dma_chan *chan, struct pl011_sgbuf *sg,
 	enum dma_data_direction dir)
 {
-	sg->buf = kmalloc(PL011_DMA_BUFFER_SIZE, GFP_KERNEL);
+	dma_addr_t dma_addr;
+
+	sg->buf = dma_alloc_coherent(chan->device->dev,
+		PL011_DMA_BUFFER_SIZE, &dma_addr, GFP_KERNEL);
 	if (!sg->buf)
 		return -ENOMEM;
 
-	sg_init_one(&sg->sg, sg->buf, PL011_DMA_BUFFER_SIZE);
+	sg_init_table(&sg->sg, 1);
+	sg_set_page(&sg->sg, phys_to_page(dma_addr),
+		PL011_DMA_BUFFER_SIZE, offset_in_page(dma_addr));
+	sg_dma_address(&sg->sg) = dma_addr;
 
-	if (dma_map_sg(chan->device->dev, &sg->sg, 1, dir) != 1) {
-		kfree(sg->buf);
-		return -EINVAL;
-	}
 	return 0;
 }
 
@@ -240,8 +249,9 @@ static void pl011_sgbuf_free(struct dma_chan *chan, struct pl011_sgbuf *sg,
 	enum dma_data_direction dir)
 {
 	if (sg->buf) {
-		dma_unmap_sg(chan->device->dev, &sg->sg, 1, dir);
-		kfree(sg->buf);
+		dma_free_coherent(chan->device->dev,
+			PL011_DMA_BUFFER_SIZE, sg->buf,
+			sg_dma_address(&sg->sg));
 	}
 }
 
@@ -300,6 +310,29 @@ static void pl011_dma_probe_initcall(struct uart_amba_port *uap)
 		dmaengine_slave_config(chan, &rx_conf);
 		uap->dmarx.chan = chan;
 
+		if (plat->dma_rx_poll_enable) {
+			/* Set poll rate if specified. */
+			if (plat->dma_rx_poll_rate) {
+				uap->dmarx.auto_poll_rate = false;
+				uap->dmarx.poll_rate = plat->dma_rx_poll_rate;
+			} else {
+				/*
+				 * 100 ms defaults to poll rate if not
+				 * specified. This will be adjusted with
+				 * the baud rate at set_termios.
+				 */
+				uap->dmarx.auto_poll_rate = true;
+				uap->dmarx.poll_rate =  100;
+			}
+			/* 3 secs defaults poll_timeout if not specified. */
+			if (plat->dma_rx_poll_timeout)
+				uap->dmarx.poll_timeout =
+					plat->dma_rx_poll_timeout;
+			else
+				uap->dmarx.poll_timeout = 3000;
+		} else
+			uap->dmarx.auto_poll_rate = false;
+
 		dev_info(uap->port.dev, "DMA channel RX %s\n",
 			 dma_chan_name(uap->dmarx.chan));
 	}
@@ -701,24 +734,30 @@ static void pl011_dma_rx_chars(struct uart_amba_port *uap,
 	struct tty_port *port = &uap->port.state->port;
 	struct pl011_sgbuf *sgbuf = use_buf_b ?
 		&uap->dmarx.sgbuf_b : &uap->dmarx.sgbuf_a;
-	struct device *dev = uap->dmarx.chan->device->dev;
 	int dma_count = 0;
 	u32 fifotaken = 0; /* only used for vdbg() */
 
-	/* Pick everything from the DMA first */
+	struct pl011_dmarx_data *dmarx = &uap->dmarx;
+	int dmataken = 0;
+
+	if (uap->dmarx.poll_rate) {
+		/* The data can be taken by polling */
+		dmataken = sgbuf->sg.length - dmarx->last_residue;
+		/* Recalculate the pending size */
+		if (pending >= dmataken)
+			pending -= dmataken;
+	}
+
+	/* Pick the remain data from the DMA */
 	if (pending) {
-		/* Sync in buffer */
-		dma_sync_sg_for_cpu(dev, &sgbuf->sg, 1, DMA_FROM_DEVICE);
 
 		/*
 		 * First take all chars in the DMA pipe, then look in the FIFO.
 		 * Note that tty_insert_flip_buf() tries to take as many chars
 		 * as it can.
 		 */
-		dma_count = tty_insert_flip_string(port, sgbuf->buf, pending);
-
-		/* Return buffer to device */
-		dma_sync_sg_for_device(dev, &sgbuf->sg, 1, DMA_FROM_DEVICE);
+		dma_count = tty_insert_flip_string(port, sgbuf->buf + dmataken,
+				pending);
 
 		uap->port.icount.rx += dma_count;
 		if (dma_count < pending)
@@ -726,6 +765,10 @@ static void pl011_dma_rx_chars(struct uart_amba_port *uap,
 				 "couldn't insert all characters (TTY is full?)\n");
 	}
 
+	/* Reset the last_residue for Rx DMA poll */
+	if (uap->dmarx.poll_rate)
+		dmarx->last_residue = sgbuf->sg.length;
+
 	/*
 	 * Only continue with trying to read the FIFO if all DMA chars have
 	 * been taken first.
@@ -865,6 +908,57 @@ static inline void pl011_dma_rx_stop(struct uart_amba_port *uap)
 	writew(uap->dmacr, uap->port.membase + UART011_DMACR);
 }
 
+/*
+ * Timer handler for Rx DMA polling.
+ * Every polling, It checks the residue in the dma buffer and transfer
+ * data to the tty. Also, last_residue is updated for the next polling.
+ */
+static void pl011_dma_rx_poll(unsigned long args)
+{
+	struct uart_amba_port *uap = (struct uart_amba_port *)args;
+	struct tty_port *port = &uap->port.state->port;
+	struct pl011_dmarx_data *dmarx = &uap->dmarx;
+	struct dma_chan *rxchan = uap->dmarx.chan;
+	unsigned long flags = 0;
+	unsigned int dmataken = 0;
+	unsigned int size = 0;
+	struct pl011_sgbuf *sgbuf;
+	int dma_count;
+	struct dma_tx_state state;
+
+	sgbuf = dmarx->use_buf_b ? &uap->dmarx.sgbuf_b : &uap->dmarx.sgbuf_a;
+	rxchan->device->device_tx_status(rxchan, dmarx->cookie, &state);
+	if (likely(state.residue < dmarx->last_residue)) {
+		dmataken = sgbuf->sg.length - dmarx->last_residue;
+		size = dmarx->last_residue - state.residue;
+		dma_count = tty_insert_flip_string(port, sgbuf->buf + dmataken,
+				size);
+		if (dma_count == size)
+			dmarx->last_residue =  state.residue;
+		dmarx->last_jiffies = jiffies;
+	}
+	tty_flip_buffer_push(port);
+
+	/*
+	 * If no data is received in poll_timeout, the driver will fall back
+	 * to interrupt mode. We will retrigger DMA at the first interrupt.
+	 */
+	if (jiffies_to_msecs(jiffies - dmarx->last_jiffies)
+			> uap->dmarx.poll_timeout) {
+
+		spin_lock_irqsave(&uap->port.lock, flags);
+		pl011_dma_rx_stop(uap);
+		spin_unlock_irqrestore(&uap->port.lock, flags);
+
+		uap->dmarx.running = false;
+		dmaengine_terminate_all(rxchan);
+		del_timer(&uap->dmarx.timer);
+	} else {
+		mod_timer(&uap->dmarx.timer,
+			jiffies + msecs_to_jiffies(uap->dmarx.poll_rate));
+	}
+}
+
 static void pl011_dma_startup(struct uart_amba_port *uap)
 {
 	int ret;
@@ -927,6 +1021,16 @@ skip_rx:
 		if (pl011_dma_rx_trigger_dma(uap))
 			dev_dbg(uap->port.dev, "could not trigger initial "
 				"RX DMA job, fall back to interrupt mode\n");
+		if (uap->dmarx.poll_rate) {
+			init_timer(&(uap->dmarx.timer));
+			uap->dmarx.timer.function = pl011_dma_rx_poll;
+			uap->dmarx.timer.data = (unsigned long)uap;
+			mod_timer(&uap->dmarx.timer,
+				jiffies +
+				msecs_to_jiffies(uap->dmarx.poll_rate));
+			uap->dmarx.last_residue = PL011_DMA_BUFFER_SIZE;
+			uap->dmarx.last_jiffies = jiffies;
+		}
 	}
 }
 
@@ -962,6 +1066,8 @@ static void pl011_dma_shutdown(struct uart_amba_port *uap)
 		/* Clean up the RX DMA */
 		pl011_sgbuf_free(uap->dmarx.chan, &uap->dmarx.sgbuf_a, DMA_FROM_DEVICE);
 		pl011_sgbuf_free(uap->dmarx.chan, &uap->dmarx.sgbuf_b, DMA_FROM_DEVICE);
+		if (uap->dmarx.poll_rate)
+			del_timer_sync(&uap->dmarx.timer);
 		uap->using_rx_dma = false;
 	}
 }
@@ -976,7 +1082,6 @@ static inline bool pl011_dma_rx_running(struct uart_amba_port *uap)
 	return uap->using_rx_dma && uap->dmarx.running;
 }
 
-
 #else
 /* Blank functions if the DMA engine is not available */
 static inline void pl011_dma_probe(struct uart_amba_port *uap)
@@ -1088,8 +1193,20 @@ static void pl011_rx_chars(struct uart_amba_port *uap)
 			dev_dbg(uap->port.dev, "could not trigger RX DMA job "
 				"fall back to interrupt mode again\n");
 			uap->im |= UART011_RXIM;
-		} else
+		} else {
 			uap->im &= ~UART011_RXIM;
+#ifdef CONFIG_DMA_ENGINE
+			/* Start Rx DMA poll */
+			if (uap->dmarx.poll_rate) {
+				uap->dmarx.last_jiffies = jiffies;
+				uap->dmarx.last_residue	= PL011_DMA_BUFFER_SIZE;
+				mod_timer(&uap->dmarx.timer,
+					jiffies +
+					msecs_to_jiffies(uap->dmarx.poll_rate));
+			}
+#endif
+		}
+
 		writew(uap->im, uap->port.membase + UART011_IMSC);
 	}
 	spin_lock(&uap->port.lock);
@@ -1164,7 +1281,6 @@ static irqreturn_t pl011_int(int irq, void *dev_id)
 	unsigned int dummy_read;
 
 	spin_lock_irqsave(&uap->port.lock, flags);
-
 	status = readw(uap->port.membase + UART011_MIS);
 	if (status) {
 		do {
@@ -1551,6 +1667,13 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
 	 */
 	baud = uart_get_baud_rate(port, termios, old, 0,
 				  port->uartclk / clkdiv);
+#ifdef CONFIG_DMA_ENGINE
+	/*
+	 * Adjust RX DMA polling rate with baud rate if not specified.
+	 */
+	if (uap->dmarx.auto_poll_rate)
+		uap->dmarx.poll_rate = DIV_ROUND_UP(10000000, baud);
+#endif
 
 	if (baud > port->uartclk/16)
 		quot = DIV_ROUND_CLOSEST(port->uartclk * 8, baud);
diff --git a/drivers/tty/serial/arc_uart.c b/drivers/tty/serial/arc_uart.c
index d97e194..cbf1d15 100644
--- a/drivers/tty/serial/arc_uart.c
+++ b/drivers/tty/serial/arc_uart.c
@@ -162,7 +162,7 @@ static unsigned int arc_serial_tx_empty(struct uart_port *port)
 /*
  * Driver internal routine, used by both tty(serial core) as well as tx-isr
  *  -Called under spinlock in either cases
- *  -also tty->stopped / tty->hw_stopped has already been checked
+ *  -also tty->stopped has already been checked
  *     = by uart_start( ) before calling us
  *     = tx_ist checks that too before calling
  */
diff --git a/drivers/tty/serial/bfin_uart.c b/drivers/tty/serial/bfin_uart.c
index 12dceda..26a3be7 100644
--- a/drivers/tty/serial/bfin_uart.c
+++ b/drivers/tty/serial/bfin_uart.c
@@ -1011,24 +1011,6 @@ static int bfin_serial_poll_get_char(struct uart_port *port)
 }
 #endif
 
-#if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \
-	defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE)
-static void bfin_kgdboc_port_shutdown(struct uart_port *port)
-{
-	if (kgdboc_break_enabled) {
-		kgdboc_break_enabled = 0;
-		bfin_serial_shutdown(port);
-	}
-}
-
-static int bfin_kgdboc_port_startup(struct uart_port *port)
-{
-	kgdboc_port_line = port->line;
-	kgdboc_break_enabled = !bfin_serial_startup(port);
-	return 0;
-}
-#endif
-
 static struct uart_ops bfin_serial_pops = {
 	.tx_empty	= bfin_serial_tx_empty,
 	.set_mctrl	= bfin_serial_set_mctrl,
@@ -1047,11 +1029,6 @@ static struct uart_ops bfin_serial_pops = {
 	.request_port	= bfin_serial_request_port,
 	.config_port	= bfin_serial_config_port,
 	.verify_port	= bfin_serial_verify_port,
-#if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \
-	defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE)
-	.kgdboc_port_startup	= bfin_kgdboc_port_startup,
-	.kgdboc_port_shutdown	= bfin_kgdboc_port_shutdown,
-#endif
 #ifdef CONFIG_CONSOLE_POLL
 	.poll_put_char	= bfin_serial_poll_put_char,
 	.poll_get_char	= bfin_serial_poll_get_char,
diff --git a/drivers/tty/serial/crisv10.c b/drivers/tty/serial/crisv10.c
index 5f37c31..477f22f 100644
--- a/drivers/tty/serial/crisv10.c
+++ b/drivers/tty/serial/crisv10.c
@@ -169,7 +169,6 @@ static int get_lsr_info(struct e100_serial *info, unsigned int *value);
 
 
 #define DEF_BAUD 115200   /* 115.2 kbit/s */
-#define STD_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
 #define DEF_RX 0x20  /* or SERIAL_CTRL_W >> 8 */
 /* Default value of tx_ctrl register: has txd(bit 7)=1 (idle) as default */
 #define DEF_TX 0x80  /* or SERIAL_CTRL_B */
@@ -246,7 +245,6 @@ static struct e100_serial rs_table[] = {
 	  .ifirstadr   = R_DMA_CH7_FIRST,
 	  .icmdadr     = R_DMA_CH7_CMD,
 	  .idescradr   = R_DMA_CH7_DESCR,
-	  .flags       = STD_FLAGS,
 	  .rx_ctrl     = DEF_RX,
 	  .tx_ctrl     = DEF_TX,
 	  .iseteop     = 2,
@@ -300,7 +298,6 @@ static struct e100_serial rs_table[] = {
 	  .ifirstadr   = R_DMA_CH9_FIRST,
 	  .icmdadr     = R_DMA_CH9_CMD,
 	  .idescradr   = R_DMA_CH9_DESCR,
-	  .flags       = STD_FLAGS,
 	  .rx_ctrl     = DEF_RX,
 	  .tx_ctrl     = DEF_TX,
 	  .iseteop     = 3,
@@ -356,7 +353,6 @@ static struct e100_serial rs_table[] = {
 	  .ifirstadr   = R_DMA_CH3_FIRST,
 	  .icmdadr     = R_DMA_CH3_CMD,
 	  .idescradr   = R_DMA_CH3_DESCR,
-	  .flags       = STD_FLAGS,
 	  .rx_ctrl     = DEF_RX,
 	  .tx_ctrl     = DEF_TX,
 	  .iseteop     = 0,
@@ -410,7 +406,6 @@ static struct e100_serial rs_table[] = {
 	  .ifirstadr   = R_DMA_CH5_FIRST,
 	  .icmdadr     = R_DMA_CH5_CMD,
 	  .idescradr   = R_DMA_CH5_DESCR,
-	  .flags       = STD_FLAGS,
 	  .rx_ctrl     = DEF_RX,
 	  .tx_ctrl     = DEF_TX,
 	  .iseteop     = 1,
@@ -2263,8 +2258,7 @@ TODO: The break will be delayed until an F or V character is received.
 
 */
 
-static
-struct e100_serial * handle_ser_rx_interrupt_no_dma(struct e100_serial *info)
+static void handle_ser_rx_interrupt_no_dma(struct e100_serial *info)
 {
 	unsigned long data_read;
 
@@ -2370,10 +2364,9 @@ more_data:
 	}
 
 	tty_flip_buffer_push(&info->port);
-	return info;
 }
 
-static struct e100_serial* handle_ser_rx_interrupt(struct e100_serial *info)
+static void handle_ser_rx_interrupt(struct e100_serial *info)
 {
 	unsigned char rstat;
 
@@ -2382,7 +2375,8 @@ static struct e100_serial* handle_ser_rx_interrupt(struct e100_serial *info)
 #endif
 /*	DEBUG_LOG(info->line, "ser_interrupt stat %03X\n", rstat | (i << 8)); */
 	if (!info->uses_dma_in) {
-		return handle_ser_rx_interrupt_no_dma(info);
+		handle_ser_rx_interrupt_no_dma(info);
+		return;
 	}
 	/* DMA is used */
 	rstat = info->ioport[REG_STATUS];
@@ -2489,7 +2483,6 @@ static struct e100_serial* handle_ser_rx_interrupt(struct e100_serial *info)
 	/* Restarting the DMA never hurts */
 	*info->icmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, restart);
 	START_FLUSH_FAST_TIMER(info, "ser_int");
-	return info;
 } /* handle_ser_rx_interrupt */
 
 static void handle_ser_tx_interrupt(struct e100_serial *info)
@@ -2534,8 +2527,7 @@ static void handle_ser_tx_interrupt(struct e100_serial *info)
 	}
 	/* Normal char-by-char interrupt */
 	if (info->xmit.head == info->xmit.tail
-	    || info->port.tty->stopped
-	    || info->port.tty->hw_stopped) {
+	    || info->port.tty->stopped) {
 		DFLOW(DEBUG_LOG(info->line, "tx_int: stopped %i\n",
 				info->port.tty->stopped));
 		e100_disable_serial_tx_ready_irq(info);
@@ -2722,7 +2714,7 @@ startup(struct e100_serial * info)
 
 	/* if it was already initialized, skip this */
 
-	if (info->flags & ASYNC_INITIALIZED) {
+	if (info->port.flags & ASYNC_INITIALIZED) {
 		local_irq_restore(flags);
 		free_page(xmit_page);
 		return 0;
@@ -2847,7 +2839,7 @@ startup(struct e100_serial * info)
 
 #endif /* CONFIG_SVINTO_SIM */
 
-	info->flags |= ASYNC_INITIALIZED;
+	info->port.flags |= ASYNC_INITIALIZED;
 
 	local_irq_restore(flags);
 	return 0;
@@ -2892,7 +2884,7 @@ shutdown(struct e100_serial * info)
 
 #endif /* CONFIG_SVINTO_SIM */
 
-	if (!(info->flags & ASYNC_INITIALIZED))
+	if (!(info->port.flags & ASYNC_INITIALIZED))
 		return;
 
 #ifdef SERIAL_DEBUG_OPEN
@@ -2923,7 +2915,7 @@ shutdown(struct e100_serial * info)
 	if (info->port.tty)
 		set_bit(TTY_IO_ERROR, &info->port.tty->flags);
 
-	info->flags &= ~ASYNC_INITIALIZED;
+	info->port.flags &= ~ASYNC_INITIALIZED;
 	local_irq_restore(flags);
 }
 
@@ -2948,7 +2940,7 @@ change_speed(struct e100_serial *info)
 	/* possibly, the tx/rx should be disabled first to do this safely */
 
 	/* change baud-rate and write it to the hardware */
-	if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) {
+	if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) {
 		/* Special baudrate */
 		u32 mask = 0xFF << (info->line*8); /* Each port has 8 bits */
 		unsigned long alt_source =
@@ -3098,7 +3090,6 @@ rs_flush_chars(struct tty_struct *tty)
 	if (info->tr_running ||
 	    info->xmit.head == info->xmit.tail ||
 	    tty->stopped ||
-	    tty->hw_stopped ||
 	    !info->xmit.buf)
 		return;
 
@@ -3176,7 +3167,6 @@ static int rs_raw_write(struct tty_struct *tty,
 
 	if (info->xmit.head != info->xmit.tail &&
 	    !tty->stopped &&
-	    !tty->hw_stopped &&
 	    !info->tr_running) {
 		start_transmit(info);
 	}
@@ -3400,10 +3390,10 @@ get_serial_info(struct e100_serial * info,
 	tmp.line = info->line;
 	tmp.port = (int)info->ioport;
 	tmp.irq = info->irq;
-	tmp.flags = info->flags;
+	tmp.flags = info->port.flags;
 	tmp.baud_base = info->baud_base;
-	tmp.close_delay = info->close_delay;
-	tmp.closing_wait = info->closing_wait;
+	tmp.close_delay = info->port.close_delay;
+	tmp.closing_wait = info->port.closing_wait;
 	tmp.custom_divisor = info->custom_divisor;
 	if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
 		return -EFAULT;
@@ -3425,16 +3415,16 @@ set_serial_info(struct e100_serial *info,
 
 	if (!capable(CAP_SYS_ADMIN)) {
 		if ((new_serial.type != info->type) ||
-		    (new_serial.close_delay != info->close_delay) ||
+		    (new_serial.close_delay != info->port.close_delay) ||
 		    ((new_serial.flags & ~ASYNC_USR_MASK) !=
-		     (info->flags & ~ASYNC_USR_MASK)))
+		     (info->port.flags & ~ASYNC_USR_MASK)))
 			return -EPERM;
-		info->flags = ((info->flags & ~ASYNC_USR_MASK) |
+		info->port.flags = ((info->port.flags & ~ASYNC_USR_MASK) |
 			       (new_serial.flags & ASYNC_USR_MASK));
 		goto check_and_exit;
 	}
 
-	if (info->count > 1)
+	if (info->port.count > 1)
 		return -EBUSY;
 
 	/*
@@ -3443,16 +3433,16 @@ set_serial_info(struct e100_serial *info,
 	 */
 
 	info->baud_base = new_serial.baud_base;
-	info->flags = ((info->flags & ~ASYNC_FLAGS) |
+	info->port.flags = ((info->port.flags & ~ASYNC_FLAGS) |
 		       (new_serial.flags & ASYNC_FLAGS));
 	info->custom_divisor = new_serial.custom_divisor;
 	info->type = new_serial.type;
-	info->close_delay = new_serial.close_delay;
-	info->closing_wait = new_serial.closing_wait;
-	info->port.low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+	info->port.close_delay = new_serial.close_delay;
+	info->port.closing_wait = new_serial.closing_wait;
+	info->port.low_latency = (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0;
 
  check_and_exit:
-	if (info->flags & ASYNC_INITIALIZED) {
+	if (info->port.flags & ASYNC_INITIALIZED) {
 		change_speed(info);
 	} else
 		retval = startup(info);
@@ -3733,10 +3723,8 @@ rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 
 	/* Handle turning off CRTSCTS */
 	if ((old_termios->c_cflag & CRTSCTS) &&
-	    !(tty->termios.c_cflag & CRTSCTS)) {
-		tty->hw_stopped = 0;
+	    !(tty->termios.c_cflag & CRTSCTS))
 		rs_start(tty);
-	}
 
 }
 
@@ -3772,7 +3760,7 @@ rs_close(struct tty_struct *tty, struct file * filp)
 	printk("[%d] rs_close ttyS%d, count = %d\n", current->pid,
 	       info->line, info->count);
 #endif
-	if ((tty->count == 1) && (info->count != 1)) {
+	if ((tty->count == 1) && (info->port.count != 1)) {
 		/*
 		 * Uh, oh.  tty->count is 1, which means that the tty
 		 * structure will be freed.  Info->count should always
@@ -3782,32 +3770,32 @@ rs_close(struct tty_struct *tty, struct file * filp)
 		 */
 		printk(KERN_ERR
 		       "rs_close: bad serial port count; tty->count is 1, "
-		       "info->count is %d\n", info->count);
-		info->count = 1;
+		       "info->count is %d\n", info->port.count);
+		info->port.count = 1;
 	}
-	if (--info->count < 0) {
+	if (--info->port.count < 0) {
 		printk(KERN_ERR "rs_close: bad serial port count for ttyS%d: %d\n",
-		       info->line, info->count);
-		info->count = 0;
+		       info->line, info->port.count);
+		info->port.count = 0;
 	}
-	if (info->count) {
+	if (info->port.count) {
 		local_irq_restore(flags);
 		return;
 	}
-	info->flags |= ASYNC_CLOSING;
+	info->port.flags |= ASYNC_CLOSING;
 	/*
 	 * Save the termios structure, since this port may have
 	 * separate termios for callout and dialin.
 	 */
-	if (info->flags & ASYNC_NORMAL_ACTIVE)
+	if (info->port.flags & ASYNC_NORMAL_ACTIVE)
 		info->normal_termios = tty->termios;
 	/*
 	 * 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 (info->closing_wait != ASYNC_CLOSING_WAIT_NONE)
-		tty_wait_until_sent(tty, info->closing_wait);
+	if (info->port.closing_wait != ASYNC_CLOSING_WAIT_NONE)
+		tty_wait_until_sent(tty, info->port.closing_wait);
 	/*
 	 * At this point we stop accepting input.  To do this, we
 	 * disable the serial receiver and the DMA receive interrupt.
@@ -3820,7 +3808,7 @@ rs_close(struct tty_struct *tty, struct file * filp)
 	e100_disable_rx(info);
 	e100_disable_rx_irq(info);
 
-	if (info->flags & ASYNC_INITIALIZED) {
+	if (info->port.flags & ASYNC_INITIALIZED) {
 		/*
 		 * Before we drop DTR, make sure the UART transmitter
 		 * has completely drained; this is especially
@@ -3836,13 +3824,13 @@ rs_close(struct tty_struct *tty, struct file * filp)
 	tty->closing = 0;
 	info->event = 0;
 	info->port.tty = NULL;
-	if (info->blocked_open) {
-		if (info->close_delay)
-			schedule_timeout_interruptible(info->close_delay);
-		wake_up_interruptible(&info->open_wait);
+	if (info->port.blocked_open) {
+		if (info->port.close_delay)
+			schedule_timeout_interruptible(info->port.close_delay);
+		wake_up_interruptible(&info->port.open_wait);
 	}
-	info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
-	wake_up_interruptible(&info->close_wait);
+	info->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
+	wake_up_interruptible(&info->port.close_wait);
 	local_irq_restore(flags);
 
 	/* port closed */
@@ -3935,10 +3923,10 @@ rs_hangup(struct tty_struct *tty)
 	rs_flush_buffer(tty);
 	shutdown(info);
 	info->event = 0;
-	info->count = 0;
-	info->flags &= ~ASYNC_NORMAL_ACTIVE;
+	info->port.count = 0;
+	info->port.flags &= ~ASYNC_NORMAL_ACTIVE;
 	info->port.tty = NULL;
-	wake_up_interruptible(&info->open_wait);
+	wake_up_interruptible(&info->port.open_wait);
 }
 
 /*
@@ -3960,11 +3948,11 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
 	 * until it's done, and then try again.
 	 */
 	if (tty_hung_up_p(filp) ||
-	    (info->flags & ASYNC_CLOSING)) {
-		wait_event_interruptible_tty(tty, info->close_wait,
-			!(info->flags & ASYNC_CLOSING));
+	    (info->port.flags & ASYNC_CLOSING)) {
+		wait_event_interruptible_tty(tty, info->port.close_wait,
+			!(info->port.flags & ASYNC_CLOSING));
 #ifdef SERIAL_DO_RESTART
-		if (info->flags & ASYNC_HUP_NOTIFY)
+		if (info->port.flags & ASYNC_HUP_NOTIFY)
 			return -EAGAIN;
 		else
 			return -ERESTARTSYS;
@@ -3979,7 +3967,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
 	 */
 	if ((filp->f_flags & O_NONBLOCK) ||
 	    (tty->flags & (1 << TTY_IO_ERROR))) {
-		info->flags |= ASYNC_NORMAL_ACTIVE;
+		info->port.flags |= ASYNC_NORMAL_ACTIVE;
 		return 0;
 	}
 
@@ -3990,23 +3978,23 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
 	/*
 	 * 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
+	 * this loop, info->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(&info->open_wait, &wait);
+	add_wait_queue(&info->port.open_wait, &wait);
 #ifdef SERIAL_DEBUG_OPEN
 	printk("block_til_ready before block: ttyS%d, count = %d\n",
-	       info->line, info->count);
+	       info->line, info->port.count);
 #endif
 	local_irq_save(flags);
 	if (!tty_hung_up_p(filp)) {
 		extra_count++;
-		info->count--;
+		info->port.count--;
 	}
 	local_irq_restore(flags);
-	info->blocked_open++;
+	info->port.blocked_open++;
 	while (1) {
 		local_irq_save(flags);
 		/* assert RTS and DTR */
@@ -4015,9 +4003,9 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
 		local_irq_restore(flags);
 		set_current_state(TASK_INTERRUPTIBLE);
 		if (tty_hung_up_p(filp) ||
-		    !(info->flags & ASYNC_INITIALIZED)) {
+		    !(info->port.flags & ASYNC_INITIALIZED)) {
 #ifdef SERIAL_DO_RESTART
-			if (info->flags & ASYNC_HUP_NOTIFY)
+			if (info->port.flags & ASYNC_HUP_NOTIFY)
 				retval = -EAGAIN;
 			else
 				retval = -ERESTARTSYS;
@@ -4026,7 +4014,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
 #endif
 			break;
 		}
-		if (!(info->flags & ASYNC_CLOSING) && do_clocal)
+		if (!(info->port.flags & ASYNC_CLOSING) && do_clocal)
 			/* && (do_clocal || DCD_IS_ASSERTED) */
 			break;
 		if (signal_pending(current)) {
@@ -4035,24 +4023,24 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
 		}
 #ifdef SERIAL_DEBUG_OPEN
 		printk("block_til_ready blocking: ttyS%d, count = %d\n",
-		       info->line, info->count);
+		       info->line, info->port.count);
 #endif
 		tty_unlock(tty);
 		schedule();
 		tty_lock(tty);
 	}
 	set_current_state(TASK_RUNNING);
-	remove_wait_queue(&info->open_wait, &wait);
+	remove_wait_queue(&info->port.open_wait, &wait);
 	if (extra_count)
-		info->count++;
-	info->blocked_open--;
+		info->port.count++;
+	info->port.blocked_open--;
 #ifdef SERIAL_DEBUG_OPEN
 	printk("block_til_ready after blocking: ttyS%d, count = %d\n",
-	       info->line, info->count);
+	       info->line, info->port.count);
 #endif
 	if (retval)
 		return retval;
-	info->flags |= ASYNC_NORMAL_ACTIVE;
+	info->port.flags |= ASYNC_NORMAL_ACTIVE;
 	return 0;
 }
 
@@ -4086,24 +4074,24 @@ rs_open(struct tty_struct *tty, struct file * filp)
 
 #ifdef SERIAL_DEBUG_OPEN
         printk("[%d] rs_open %s, count = %d\n", current->pid, tty->name,
- 	       info->count);
+ 	       info->port.count);
 #endif
 
-	info->count++;
+	info->port.count++;
 	tty->driver_data = info;
 	info->port.tty = tty;
 
-	info->port.low_latency = !!(info->flags & ASYNC_LOW_LATENCY);
+	info->port.low_latency = !!(info->port.flags & ASYNC_LOW_LATENCY);
 
 	/*
 	 * If the port is in the middle of closing, bail out now
 	 */
 	if (tty_hung_up_p(filp) ||
-	    (info->flags & ASYNC_CLOSING)) {
-		wait_event_interruptible_tty(tty, info->close_wait,
-			!(info->flags & ASYNC_CLOSING));
+	    (info->port.flags & ASYNC_CLOSING)) {
+		wait_event_interruptible_tty(tty, info->port.close_wait,
+			!(info->port.flags & ASYNC_CLOSING));
 #ifdef SERIAL_DO_RESTART
-		return ((info->flags & ASYNC_HUP_NOTIFY) ?
+		return ((info->port.flags & ASYNC_HUP_NOTIFY) ?
 			-EAGAIN : -ERESTARTSYS);
 #else
 		return -EAGAIN;
@@ -4113,7 +4101,7 @@ rs_open(struct tty_struct *tty, struct file * filp)
 	/*
 	 * If DMA is enabled try to allocate the irq's.
 	 */
-	if (info->count == 1) {
+	if (info->port.count == 1) {
 		allocated_resources = 1;
 		if (info->dma_in_enabled) {
 			if (request_irq(info->dma_in_irq_nbr,
@@ -4186,7 +4174,7 @@ rs_open(struct tty_struct *tty, struct file * filp)
 		if (allocated_resources)
 			deinit_port(info);
 
-		/* FIXME Decrease count info->count here too? */
+		/* FIXME Decrease count info->port.count here too? */
 		return retval;
 	}
 
@@ -4203,7 +4191,7 @@ rs_open(struct tty_struct *tty, struct file * filp)
 		return retval;
 	}
 
-	if ((info->count == 1) && (info->flags & ASYNC_SPLIT_TERMIOS)) {
+	if ((info->port.count == 1) && (info->port.flags & ASYNC_SPLIT_TERMIOS)) {
 		tty->termios = info->normal_termios;
 		change_speed(info);
 	}
@@ -4256,9 +4244,6 @@ static void seq_line_info(struct seq_file *m, struct e100_serial *info)
 		if (info->port.tty->stopped)
 			seq_printf(m, " stopped:%i",
 				   (int)info->port.tty->stopped);
-		if (info->port.tty->hw_stopped)
-			seq_printf(m, " hw_stopped:%i",
-				   (int)info->port.tty->hw_stopped);
 	}
 
 	{
@@ -4455,16 +4440,9 @@ static int __init rs_init(void)
 		info->forced_eop = 0;
 		info->baud_base = DEF_BAUD_BASE;
 		info->custom_divisor = 0;
-		info->flags = 0;
-		info->close_delay = 5*HZ/10;
-		info->closing_wait = 30*HZ;
 		info->x_char = 0;
 		info->event = 0;
-		info->count = 0;
-		info->blocked_open = 0;
 		info->normal_termios = driver->init_termios;
-		init_waitqueue_head(&info->open_wait);
-		init_waitqueue_head(&info->close_wait);
 		info->xmit.buf = NULL;
 		info->xmit.tail = info->xmit.head = 0;
 		info->first_recv_buffer = info->last_recv_buffer = NULL;
diff --git a/drivers/tty/serial/crisv10.h b/drivers/tty/serial/crisv10.h
index ea0beb4..7599014 100644
--- a/drivers/tty/serial/crisv10.h
+++ b/drivers/tty/serial/crisv10.h
@@ -53,8 +53,6 @@ struct e100_serial {
 	volatile u8 *icmdadr;		/* adr to R_DMA_CHx_CMD */
 	volatile u32 *idescradr;	/* adr to R_DMA_CHx_DESCR */
 
-	int flags;	/* defined in tty.h */
-
 	u8 rx_ctrl;	/* shadow for R_SERIALx_REC_CTRL */
 	u8 tx_ctrl;	/* shadow for R_SERIALx_TR_CTRL */
 	u8 iseteop;	/* bit number for R_SET_EOP for the input dma */
@@ -88,19 +86,10 @@ struct e100_serial {
 
 	volatile int		tr_running; /* 1 if output is running */
 
-	struct tty_struct	*tty;
-	int			read_status_mask;
-	int			ignore_status_mask;
 	int			x_char;	/* xon/xoff character */
-	int			close_delay;
-	unsigned short		closing_wait;
-	unsigned short		closing_wait2;
 	unsigned long		event;
-	unsigned long		last_active;
 	int			line;
 	int			type;  /* PORT_ETRAX */
-	int			count;	    /* # of fd on device */
-	int			blocked_open; /* # of blocked opens */
 	struct circ_buf		xmit;
 	struct etrax_recv_buffer *first_recv_buffer;
 	struct etrax_recv_buffer *last_recv_buffer;
@@ -110,9 +99,6 @@ struct e100_serial {
 	struct work_struct	work;
 	struct async_icount	icount;   /* error-statistics etc.*/
 	struct ktermios		normal_termios;
-	struct ktermios		callout_termios;
-	wait_queue_head_t	open_wait;
-	wait_queue_head_t	close_wait;
 
 	unsigned long char_time_usec;       /* The time for 1 char, in usecs */
 	unsigned long flush_time_usec;      /* How often we should flush */
diff --git a/drivers/tty/serial/icom.c b/drivers/tty/serial/icom.c
index bc9e6b01..18ed5ae 100644
--- a/drivers/tty/serial/icom.c
+++ b/drivers/tty/serial/icom.c
@@ -1415,8 +1415,7 @@ static int icom_alloc_adapter(struct icom_adapter
 	struct icom_adapter *cur_adapter_entry;
 	struct list_head *tmp;
 
-	icom_adapter = (struct icom_adapter *)
-	    kzalloc(sizeof(struct icom_adapter), GFP_KERNEL);
+	icom_adapter = kzalloc(sizeof(struct icom_adapter), GFP_KERNEL);
 
 	if (!icom_adapter) {
 		return -ENOMEM;
diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c
index 68d7ce9..8b1534c 100644
--- a/drivers/tty/serial/ifx6x60.c
+++ b/drivers/tty/serial/ifx6x60.c
@@ -270,23 +270,6 @@ static void mrdy_assert(struct ifx_spi_device *ifx_dev)
 }
 
 /**
- *	ifx_spi_hangup		-	hang up an IFX device
- *	@ifx_dev: our SPI device
- *
- *	Hang up the tty attached to the IFX device if one is currently
- *	open. If not take no action
- */
-static void ifx_spi_ttyhangup(struct ifx_spi_device *ifx_dev)
-{
-	struct tty_port *pport = &ifx_dev->tty_port;
-	struct tty_struct *tty = tty_port_tty_get(pport);
-	if (tty) {
-		tty_hangup(tty);
-		tty_kref_put(tty);
-	}
-}
-
-/**
  *	ifx_spi_timeout		-	SPI timeout
  *	@arg: our SPI device
  *
@@ -298,7 +281,7 @@ static void ifx_spi_timeout(unsigned long arg)
 	struct ifx_spi_device *ifx_dev = (struct ifx_spi_device *)arg;
 
 	dev_warn(&ifx_dev->spi_dev->dev, "*** SPI Timeout ***");
-	ifx_spi_ttyhangup(ifx_dev);
+	tty_port_tty_hangup(&ifx_dev->tty_port, false);
 	mrdy_set_low(ifx_dev);
 	clear_bit(IFX_SPI_STATE_TIMER_PENDING, &ifx_dev->flags);
 }
@@ -443,25 +426,6 @@ static void ifx_spi_setup_spi_header(unsigned char *txbuffer, int tx_count,
 }
 
 /**
- *	ifx_spi_wakeup_serial	-	SPI space made
- *	@port_data: our SPI device
- *
- *	We have emptied the FIFO enough that we want to get more data
- *	queued into it. Poke the line discipline via tty_wakeup so that
- *	it will feed us more bits
- */
-static void ifx_spi_wakeup_serial(struct ifx_spi_device *ifx_dev)
-{
-	struct tty_struct *tty;
-
-	tty = tty_port_tty_get(&ifx_dev->tty_port);
-	if (!tty)
-		return;
-	tty_wakeup(tty);
-	tty_kref_put(tty);
-}
-
-/**
  *	ifx_spi_prepare_tx_buffer	-	prepare transmit frame
  *	@ifx_dev: our SPI device
  *
@@ -506,7 +470,7 @@ static int ifx_spi_prepare_tx_buffer(struct ifx_spi_device *ifx_dev)
 			tx_count += temp_count;
 			if (temp_count == queue_length)
 				/* poke port to get more data */
-				ifx_spi_wakeup_serial(ifx_dev);
+				tty_port_tty_wakeup(&ifx_dev->tty_port);
 			else /* more data in port, use next SPI message */
 				ifx_dev->spi_more = 1;
 		}
@@ -683,8 +647,6 @@ static void ifx_spi_insert_flip_string(struct ifx_spi_device *ifx_dev,
 static void ifx_spi_complete(void *ctx)
 {
 	struct ifx_spi_device *ifx_dev = ctx;
-	struct tty_struct *tty;
-	struct tty_ldisc *ldisc = NULL;
 	int length;
 	int actual_length;
 	unsigned char more;
@@ -762,15 +724,7 @@ complete_exit:
 			 */
 			ifx_spi_power_state_clear(ifx_dev,
 						  IFX_SPI_POWER_DATA_PENDING);
-			tty = tty_port_tty_get(&ifx_dev->tty_port);
-			if (tty) {
-				ldisc = tty_ldisc_ref(tty);
-				if (ldisc) {
-					ldisc->ops->write_wakeup(tty);
-					tty_ldisc_deref(ldisc);
-				}
-				tty_kref_put(tty);
-			}
+			tty_port_tty_wakeup(&ifx_dev->tty_port);
 		}
 	}
 }
@@ -962,7 +916,7 @@ static irqreturn_t ifx_spi_reset_interrupt(int irq, void *dev)
 		set_bit(MR_INPROGRESS, &ifx_dev->mdm_reset_state);
 		if (!solreset) {
 			/* unsolicited reset  */
-			ifx_spi_ttyhangup(ifx_dev);
+			tty_port_tty_hangup(&ifx_dev->tty_port, false);
 		}
 	} else {
 		/* exited reset */
@@ -1325,30 +1279,6 @@ static void ifx_spi_spi_shutdown(struct spi_device *spi)
  */
 
 /**
- *	ifx_spi_spi_suspend	-	suspend SPI on system suspend
- *	@dev: device being suspended
- *
- *	Suspend the SPI side. No action needed on Intel MID platforms, may
- *	need extending for other systems.
- */
-static int ifx_spi_spi_suspend(struct spi_device *spi, pm_message_t msg)
-{
-	return 0;
-}
-
-/**
- *	ifx_spi_spi_resume	-	resume SPI side on system resume
- *	@dev: device being suspended
- *
- *	Suspend the SPI side. No action needed on Intel MID platforms, may
- *	need extending for other systems.
- */
-static int ifx_spi_spi_resume(struct spi_device *spi)
-{
-	return 0;
-}
-
-/**
  *	ifx_spi_pm_suspend	-	suspend modem on system suspend
  *	@dev: device being suspended
  *
@@ -1437,8 +1367,6 @@ static struct spi_driver ifx_spi_driver = {
 	.probe = ifx_spi_spi_probe,
 	.shutdown = ifx_spi_spi_shutdown,
 	.remove = ifx_spi_spi_remove,
-	.suspend = ifx_spi_spi_suspend,
-	.resume = ifx_spi_spi_resume,
 	.id_table = ifx_id_table
 };
 
diff --git a/drivers/tty/serial/jsm/jsm_tty.c b/drivers/tty/serial/jsm/jsm_tty.c
index 00f250a..27bb750 100644
--- a/drivers/tty/serial/jsm/jsm_tty.c
+++ b/drivers/tty/serial/jsm/jsm_tty.c
@@ -596,12 +596,6 @@ void jsm_input(struct jsm_channel *ch)
 
 	jsm_dbg(READ, &ch->ch_bd->pci_dev, "start 2\n");
 
-	if (data_len <= 0) {
-		spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
-		jsm_dbg(READ, &ch->ch_bd->pci_dev, "jsm_input 1\n");
-		return;
-	}
-
 	len = tty_buffer_request_room(port, data_len);
 	n = len;
 
diff --git a/drivers/tty/serial/max3100.c b/drivers/tty/serial/max3100.c
index 32517d4..57da9bb 100644
--- a/drivers/tty/serial/max3100.c
+++ b/drivers/tty/serial/max3100.c
@@ -849,11 +849,11 @@ static int max3100_remove(struct spi_device *spi)
 	return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 
-static int max3100_suspend(struct spi_device *spi, pm_message_t state)
+static int max3100_suspend(struct device *dev)
 {
-	struct max3100_port *s = dev_get_drvdata(&spi->dev);
+	struct max3100_port *s = dev_get_drvdata(dev);
 
 	dev_dbg(&s->spi->dev, "%s\n", __func__);
 
@@ -874,9 +874,9 @@ static int max3100_suspend(struct spi_device *spi, pm_message_t state)
 	return 0;
 }
 
-static int max3100_resume(struct spi_device *spi)
+static int max3100_resume(struct device *dev)
 {
-	struct max3100_port *s = dev_get_drvdata(&spi->dev);
+	struct max3100_port *s = dev_get_drvdata(dev);
 
 	dev_dbg(&s->spi->dev, "%s\n", __func__);
 
@@ -894,21 +894,21 @@ static int max3100_resume(struct spi_device *spi)
 	return 0;
 }
 
+static SIMPLE_DEV_PM_OPS(max3100_pm_ops, max3100_suspend, max3100_resume);
+#define MAX3100_PM_OPS (&max3100_pm_ops)
+
 #else
-#define max3100_suspend NULL
-#define max3100_resume  NULL
+#define MAX3100_PM_OPS NULL
 #endif
 
 static struct spi_driver max3100_driver = {
 	.driver = {
 		.name		= "max3100",
 		.owner		= THIS_MODULE,
+		.pm		= MAX3100_PM_OPS,
 	},
-
 	.probe		= max3100_probe,
 	.remove		= max3100_remove,
-	.suspend	= max3100_suspend,
-	.resume		= max3100_resume,
 };
 
 module_spi_driver(max3100_driver);
diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c
index 0c2422c..8941e64 100644
--- a/drivers/tty/serial/max310x.c
+++ b/drivers/tty/serial/max310x.c
@@ -881,12 +881,14 @@ static struct uart_ops max310x_ops = {
 	.verify_port	= max310x_verify_port,
 };
 
-static int max310x_suspend(struct spi_device *spi, pm_message_t state)
+#ifdef CONFIG_PM_SLEEP
+
+static int max310x_suspend(struct device *dev)
 {
 	int ret;
-	struct max310x_port *s = dev_get_drvdata(&spi->dev);
+	struct max310x_port *s = dev_get_drvdata(dev);
 
-	dev_dbg(&spi->dev, "Suspend\n");
+	dev_dbg(dev, "Suspend\n");
 
 	ret = uart_suspend_port(&s->uart, &s->port);
 
@@ -905,11 +907,11 @@ static int max310x_suspend(struct spi_device *spi, pm_message_t state)
 	return ret;
 }
 
-static int max310x_resume(struct spi_device *spi)
+static int max310x_resume(struct device *dev)
 {
-	struct max310x_port *s = dev_get_drvdata(&spi->dev);
+	struct max310x_port *s = dev_get_drvdata(dev);
 
-	dev_dbg(&spi->dev, "Resume\n");
+	dev_dbg(dev, "Resume\n");
 
 	if (s->pdata->suspend)
 		s->pdata->suspend(0);
@@ -928,6 +930,13 @@ static int max310x_resume(struct spi_device *spi)
 	return uart_resume_port(&s->uart, &s->port);
 }
 
+static SIMPLE_DEV_PM_OPS(max310x_pm_ops, max310x_suspend, max310x_resume);
+#define MAX310X_PM_OPS (&max310x_pm_ops)
+
+#else
+#define MAX310X_PM_OPS NULL
+#endif
+
 #ifdef CONFIG_GPIOLIB
 static int max310x_gpio_get(struct gpio_chip *chip, unsigned offset)
 {
@@ -1242,11 +1251,10 @@ static struct spi_driver max310x_driver = {
 	.driver = {
 		.name	= "max310x",
 		.owner	= THIS_MODULE,
+		.pm	= MAX310X_PM_OPS,
 	},
 	.probe		= max310x_probe,
 	.remove		= max310x_remove,
-	.suspend	= max310x_suspend,
-	.resume		= max310x_resume,
 	.id_table	= max310x_id_table,
 };
 module_spi_driver(max310x_driver);
diff --git a/drivers/tty/serial/mrst_max3110.c b/drivers/tty/serial/mrst_max3110.c
index f641c23..9b6ef20 100644
--- a/drivers/tty/serial/mrst_max3110.c
+++ b/drivers/tty/serial/mrst_max3110.c
@@ -743,9 +743,10 @@ static struct uart_driver serial_m3110_reg = {
 	.cons		= &serial_m3110_console,
 };
 
-#ifdef CONFIG_PM
-static int serial_m3110_suspend(struct spi_device *spi, pm_message_t state)
+#ifdef CONFIG_PM_SLEEP
+static int serial_m3110_suspend(struct device *dev)
 {
+	struct spi_device *spi = to_spi_device(dev);
 	struct uart_max3110 *max = spi_get_drvdata(spi);
 
 	disable_irq(max->irq);
@@ -754,8 +755,9 @@ static int serial_m3110_suspend(struct spi_device *spi, pm_message_t state)
 	return 0;
 }
 
-static int serial_m3110_resume(struct spi_device *spi)
+static int serial_m3110_resume(struct device *dev)
 {
+	struct spi_device *spi = to_spi_device(dev);
 	struct uart_max3110 *max = spi_get_drvdata(spi);
 
 	max3110_out(max, max->cur_conf);
@@ -763,9 +765,13 @@ static int serial_m3110_resume(struct spi_device *spi)
 	enable_irq(max->irq);
 	return 0;
 }
+
+static SIMPLE_DEV_PM_OPS(serial_m3110_pm_ops, serial_m3110_suspend,
+			serial_m3110_resume);
+#define SERIAL_M3110_PM_OPS (&serial_m3110_pm_ops)
+
 #else
-#define serial_m3110_suspend	NULL
-#define serial_m3110_resume	NULL
+#define SERIAL_M3110_PM_OPS NULL
 #endif
 
 static int serial_m3110_probe(struct spi_device *spi)
@@ -872,11 +878,10 @@ static struct spi_driver uart_max3110_driver = {
 	.driver = {
 			.name	= "spi_max3111",
 			.owner	= THIS_MODULE,
+			.pm	= SERIAL_M3110_PM_OPS,
 	},
 	.probe		= serial_m3110_probe,
 	.remove		= serial_m3110_remove,
-	.suspend	= serial_m3110_suspend,
-	.resume		= serial_m3110_resume,
 };
 
 static int __init serial_m3110_init(void)
diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c
index 4a942c7..4ca2f64 100644
--- a/drivers/tty/serial/msm_serial_hs.c
+++ b/drivers/tty/serial/msm_serial_hs.c
@@ -907,7 +907,6 @@ static void msm_hs_dmov_rx_callback(struct msm_dmov_cmd *cmd_ptr,
 	unsigned int error_f = 0;
 	unsigned long flags;
 	unsigned int flush;
-	struct tty_struct *tty;
 	struct tty_port *port;
 	struct uart_port *uport;
 	struct msm_hs_port *msm_uport;
@@ -919,7 +918,6 @@ static void msm_hs_dmov_rx_callback(struct msm_dmov_cmd *cmd_ptr,
 	clk_enable(msm_uport->clk);
 
 	port = &uport->state->port;
-	tty = port->tty;
 
 	msm_hs_write(uport, UARTDM_CR_ADDR, STALE_EVENT_DISABLE);
 
diff --git a/drivers/tty/serial/msm_smd_tty.c b/drivers/tty/serial/msm_smd_tty.c
index e722ff1..1238ac3 100644
--- a/drivers/tty/serial/msm_smd_tty.c
+++ b/drivers/tty/serial/msm_smd_tty.c
@@ -90,13 +90,13 @@ static void smd_tty_notify(void *priv, unsigned event)
 
 static int smd_tty_port_activate(struct tty_port *tport, struct tty_struct *tty)
 {
+	struct smd_tty_info *info = container_of(tport, struct smd_tty_info,
+			port);
 	int i, res = 0;
-	int n = tty->index;
 	const char *name = NULL;
-	struct smd_tty_info *info = smd_tty + n;
 
 	for (i = 0; i < smd_tty_channels_len; i++) {
-		if (smd_tty_channels[i].id == n) {
+		if (smd_tty_channels[i].id == tty->index) {
 			name = smd_tty_channels[i].name;
 			break;
 		}
@@ -117,17 +117,13 @@ static int smd_tty_port_activate(struct tty_port *tport, struct tty_struct *tty)
 
 static void smd_tty_port_shutdown(struct tty_port *tport)
 {
-	struct smd_tty_info *info;
-	struct tty_struct *tty = tty_port_tty_get(tport);
+	struct smd_tty_info *info = container_of(tport, struct smd_tty_info,
+			port);
 
-	info = tty->driver_data;
 	if (info->ch) {
 		smd_close(info->ch);
 		info->ch = 0;
 	}
-
-	tty->driver_data = 0;
-	tty_kref_put(tty);
 }
 
 static int smd_tty_open(struct tty_struct *tty, struct file *f)
diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c
index d549fe1..269a27c 100644
--- a/drivers/tty/serial/mxs-auart.c
+++ b/drivers/tty/serial/mxs-auart.c
@@ -35,7 +35,7 @@
 #include <linux/pinctrl/consumer.h>
 #include <linux/of_device.h>
 #include <linux/dma-mapping.h>
-#include <linux/fsl/mxs-dma.h>
+#include <linux/dmaengine.h>
 
 #include <asm/cacheflush.h>
 
@@ -148,11 +148,6 @@ struct mxs_auart_port {
 	struct device *dev;
 
 	/* for DMA */
-	struct mxs_dma_data dma_data;
-	int dma_channel_rx, dma_channel_tx;
-	int dma_irq_rx, dma_irq_tx;
-	int dma_channel;
-
 	struct scatterlist tx_sgl;
 	struct dma_chan	*tx_dma_chan;
 	void *tx_dma_buf;
@@ -440,20 +435,6 @@ static u32 mxs_auart_get_mctrl(struct uart_port *u)
 	return mctrl;
 }
 
-static bool mxs_auart_dma_filter(struct dma_chan *chan, void *param)
-{
-	struct mxs_auart_port *s = param;
-
-	if (!mxs_dma_is_apbx(chan))
-		return false;
-
-	if (s->dma_channel == chan->chan_id) {
-		chan->private = &s->dma_data;
-		return true;
-	}
-	return false;
-}
-
 static int mxs_auart_dma_prep_rx(struct mxs_auart_port *s);
 static void dma_rx_callback(void *arg)
 {
@@ -545,21 +526,11 @@ static void mxs_auart_dma_exit(struct mxs_auart_port *s)
 
 static int mxs_auart_dma_init(struct mxs_auart_port *s)
 {
-	dma_cap_mask_t mask;
-
 	if (auart_dma_enabled(s))
 		return 0;
 
-	/* We do not get the right DMA channels. */
-	if (s->dma_channel_rx == -1 || s->dma_channel_tx == -1)
-		return -EINVAL;
-
 	/* init for RX */
-	dma_cap_zero(mask);
-	dma_cap_set(DMA_SLAVE, mask);
-	s->dma_channel = s->dma_channel_rx;
-	s->dma_data.chan_irq = s->dma_irq_rx;
-	s->rx_dma_chan = dma_request_channel(mask, mxs_auart_dma_filter, s);
+	s->rx_dma_chan = dma_request_slave_channel(s->dev, "rx");
 	if (!s->rx_dma_chan)
 		goto err_out;
 	s->rx_dma_buf = kzalloc(UART_XMIT_SIZE, GFP_KERNEL | GFP_DMA);
@@ -567,9 +538,7 @@ static int mxs_auart_dma_init(struct mxs_auart_port *s)
 		goto err_out;
 
 	/* init for TX */
-	s->dma_channel = s->dma_channel_tx;
-	s->dma_data.chan_irq = s->dma_irq_tx;
-	s->tx_dma_chan = dma_request_channel(mask, mxs_auart_dma_filter, s);
+	s->tx_dma_chan = dma_request_slave_channel(s->dev, "tx");
 	if (!s->tx_dma_chan)
 		goto err_out;
 	s->tx_dma_buf = kzalloc(UART_XMIT_SIZE, GFP_KERNEL | GFP_DMA);
@@ -1020,7 +989,6 @@ static int serial_mxs_probe_dt(struct mxs_auart_port *s,
 		struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
-	u32 dma_channel[2];
 	int ret;
 
 	if (!np)
@@ -1034,20 +1002,8 @@ static int serial_mxs_probe_dt(struct mxs_auart_port *s,
 	}
 	s->port.line = ret;
 
-	s->dma_irq_rx = platform_get_irq(pdev, 1);
-	s->dma_irq_tx = platform_get_irq(pdev, 2);
+	s->flags |= MXS_AUART_DMA_CONFIG;
 
-	ret = of_property_read_u32_array(np, "fsl,auart-dma-channel",
-					dma_channel, 2);
-	if (ret == 0) {
-		s->dma_channel_rx = dma_channel[0];
-		s->dma_channel_tx = dma_channel[1];
-
-		s->flags |= MXS_AUART_DMA_CONFIG;
-	} else {
-		s->dma_channel_rx = -1;
-		s->dma_channel_tx = -1;
-	}
 	return 0;
 }
 
diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c
index b025d54..39c7ea4 100644
--- a/drivers/tty/serial/of_serial.c
+++ b/drivers/tty/serial/of_serial.c
@@ -14,7 +14,6 @@
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/serial_core.h>
-#include <linux/serial_8250.h>
 #include <linux/serial_reg.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
@@ -22,6 +21,8 @@
 #include <linux/nwpserial.h>
 #include <linux/clk.h>
 
+#include "8250/8250.h"
+
 struct of_serial_info {
 	struct clk *clk;
 	int type;
@@ -97,6 +98,10 @@ static int of_platform_serial_setup(struct platform_device *ofdev,
 	if (of_property_read_u32(np, "reg-shift", &prop) == 0)
 		port->regshift = prop;
 
+	/* Check for fifo size */
+	if (of_property_read_u32(np, "fifo-size", &prop) == 0)
+		port->fifosize = 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) {
@@ -167,11 +172,17 @@ static int of_platform_serial_probe(struct platform_device *ofdev)
 #ifdef CONFIG_SERIAL_8250
 	case PORT_8250 ... PORT_MAX_8250:
 	{
-		/* For now the of bindings don't support the extra
-		   8250 specific bits */
 		struct uart_8250_port port8250;
 		memset(&port8250, 0, sizeof(port8250));
 		port8250.port = port;
+
+		if (port.fifosize)
+			port8250.capabilities = UART_CAP_FIFO;
+
+		if (of_property_read_bool(ofdev->dev.of_node,
+					  "auto-flow-control"))
+			port8250.capabilities |= UART_CAP_AFE;
+
 		ret = serial8250_register_8250_port(&port8250);
 		break;
 	}
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index 4dc4140..30d4f7a 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -886,6 +886,17 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
 	serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR);
 	/* FIFO ENABLE, DMA MODE */
 
+	up->scr |= OMAP_UART_SCR_RX_TRIG_GRANU1_MASK;
+	/*
+	 * NOTE: Setting OMAP_UART_SCR_RX_TRIG_GRANU1_MASK
+	 * sets Enables the granularity of 1 for TRIGGER RX
+	 * level. Along with setting RX FIFO trigger level
+	 * to 1 (as noted below, 16 characters) and TLR[3:0]
+	 * to zero this will result RX FIFO threshold level
+	 * to 1 character, instead of 16 as noted in comment
+	 * below.
+	 */
+
 	/* Set receive FIFO threshold to 16 characters and
 	 * transmit FIFO threshold to 16 spaces
 	 */
diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c
index 7a6c989..21a7e17 100644
--- a/drivers/tty/serial/pch_uart.c
+++ b/drivers/tty/serial/pch_uart.c
@@ -1493,29 +1493,6 @@ static int pch_uart_verify_port(struct uart_port *port,
 	return 0;
 }
 
-static struct uart_ops pch_uart_ops = {
-	.tx_empty = pch_uart_tx_empty,
-	.set_mctrl = pch_uart_set_mctrl,
-	.get_mctrl = pch_uart_get_mctrl,
-	.stop_tx = pch_uart_stop_tx,
-	.start_tx = pch_uart_start_tx,
-	.stop_rx = pch_uart_stop_rx,
-	.enable_ms = pch_uart_enable_ms,
-	.break_ctl = pch_uart_break_ctl,
-	.startup = pch_uart_startup,
-	.shutdown = pch_uart_shutdown,
-	.set_termios = pch_uart_set_termios,
-/*	.pm		= pch_uart_pm,		Not supported yet */
-/*	.set_wake	= pch_uart_set_wake,	Not supported yet */
-	.type = pch_uart_type,
-	.release_port = pch_uart_release_port,
-	.request_port = pch_uart_request_port,
-	.config_port = pch_uart_config_port,
-	.verify_port = pch_uart_verify_port
-};
-
-#ifdef CONFIG_SERIAL_PCH_UART_CONSOLE
-
 /*
  *	Wait for transmitter & holding register to empty
  */
@@ -1547,6 +1524,84 @@ static void wait_for_xmitr(struct eg20t_port *up, int bits)
 	}
 }
 
+#ifdef CONFIG_CONSOLE_POLL
+/*
+ * Console polling routines for communicate via uart while
+ * in an interrupt or debug context.
+ */
+static int pch_uart_get_poll_char(struct uart_port *port)
+{
+	struct eg20t_port *priv =
+		container_of(port, struct eg20t_port, port);
+	u8 lsr = ioread8(priv->membase + UART_LSR);
+
+	if (!(lsr & UART_LSR_DR))
+		return NO_POLL_CHAR;
+
+	return ioread8(priv->membase + PCH_UART_RBR);
+}
+
+
+static void pch_uart_put_poll_char(struct uart_port *port,
+			 unsigned char c)
+{
+	unsigned int ier;
+	struct eg20t_port *priv =
+		container_of(port, struct eg20t_port, port);
+
+	/*
+	 * First save the IER then disable the interrupts
+	 */
+	ier = ioread8(priv->membase + UART_IER);
+	pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_ALL_INT);
+
+	wait_for_xmitr(priv, UART_LSR_THRE);
+	/*
+	 * Send the character out.
+	 * If a LF, also do CR...
+	 */
+	iowrite8(c, priv->membase + PCH_UART_THR);
+	if (c == 10) {
+		wait_for_xmitr(priv, UART_LSR_THRE);
+		iowrite8(13, priv->membase + PCH_UART_THR);
+	}
+
+	/*
+	 * Finally, wait for transmitter to become empty
+	 * and restore the IER
+	 */
+	wait_for_xmitr(priv, BOTH_EMPTY);
+	iowrite8(ier, priv->membase + UART_IER);
+}
+#endif /* CONFIG_CONSOLE_POLL */
+
+static struct uart_ops pch_uart_ops = {
+	.tx_empty = pch_uart_tx_empty,
+	.set_mctrl = pch_uart_set_mctrl,
+	.get_mctrl = pch_uart_get_mctrl,
+	.stop_tx = pch_uart_stop_tx,
+	.start_tx = pch_uart_start_tx,
+	.stop_rx = pch_uart_stop_rx,
+	.enable_ms = pch_uart_enable_ms,
+	.break_ctl = pch_uart_break_ctl,
+	.startup = pch_uart_startup,
+	.shutdown = pch_uart_shutdown,
+	.set_termios = pch_uart_set_termios,
+/*	.pm		= pch_uart_pm,		Not supported yet */
+/*	.set_wake	= pch_uart_set_wake,	Not supported yet */
+	.type = pch_uart_type,
+	.release_port = pch_uart_release_port,
+	.request_port = pch_uart_request_port,
+	.config_port = pch_uart_config_port,
+	.verify_port = pch_uart_verify_port,
+#ifdef CONFIG_CONSOLE_POLL
+	.poll_get_char = pch_uart_get_poll_char,
+	.poll_put_char = pch_uart_put_poll_char,
+#endif
+};
+
+#ifdef CONFIG_SERIAL_PCH_UART_CONSOLE
+
 static void pch_console_putchar(struct uart_port *port, int ch)
 {
 	struct eg20t_port *priv =
@@ -1655,7 +1710,7 @@ static struct console pch_console = {
 #define PCH_CONSOLE	(&pch_console)
 #else
 #define PCH_CONSOLE	NULL
-#endif
+#endif	/* CONFIG_SERIAL_PCH_UART_CONSOLE */
 
 static struct uart_driver pch_uart_driver = {
 	.owner = THIS_MODULE,
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c
index 2769a38..7883f11 100644
--- a/drivers/tty/serial/samsung.c
+++ b/drivers/tty/serial/samsung.c
@@ -446,6 +446,8 @@ static void s3c24xx_serial_shutdown(struct uart_port *port)
 
 	/* Clear pending interrupts and mask all interrupts */
 	if (s3c24xx_serial_has_interrupt_mask(port)) {
+		free_irq(port->irq, ourport);
+
 		wr_regl(port, S3C64XX_UINTP, 0xf);
 		wr_regl(port, S3C64XX_UINTM, 0xf);
 	}
@@ -505,6 +507,8 @@ static int s3c64xx_serial_startup(struct uart_port *port)
 	dbg("s3c64xx_serial_startup: port=%p (%08lx,%p)\n",
 	    port->mapbase, port->membase);
 
+	wr_regl(port, S3C64XX_UINTM, 0xf);
+
 	ret = request_irq(port->irq, s3c64xx_serial_handle_irq, IRQF_SHARED,
 			  s3c24xx_serial_portname(port), ourport);
 	if (ret) {
@@ -1307,9 +1311,29 @@ static int s3c24xx_serial_resume(struct device *dev)
 	return 0;
 }
 
+static int s3c24xx_serial_resume_noirq(struct device *dev)
+{
+	struct uart_port *port = s3c24xx_dev_to_port(dev);
+
+	if (port) {
+		/* restore IRQ mask */
+		if (s3c24xx_serial_has_interrupt_mask(port)) {
+			unsigned int uintm = 0xf;
+			if (tx_enabled(port))
+				uintm &= ~S3C64XX_UINTM_TXD_MSK;
+			if (rx_enabled(port))
+				uintm &= ~S3C64XX_UINTM_RXD_MSK;
+			wr_regl(port, S3C64XX_UINTM, uintm);
+		}
+	}
+
+	return 0;
+}
+
 static const struct dev_pm_ops s3c24xx_serial_pm_ops = {
 	.suspend = s3c24xx_serial_suspend,
 	.resume = s3c24xx_serial_resume,
+	.resume_noirq = s3c24xx_serial_resume_noirq,
 };
 #define SERIAL_SAMSUNG_PM_OPS	(&s3c24xx_serial_pm_ops)
 
@@ -1343,6 +1367,13 @@ s3c24xx_serial_console_txrdy(struct uart_port *port, unsigned int ufcon)
 	return (utrstat & S3C2410_UTRSTAT_TXE) ? 1 : 0;
 }
 
+static bool
+s3c24xx_port_configured(unsigned int ucon)
+{
+	/* consider the serial port configured if the tx/rx mode set */
+	return (ucon & 0xf) != 0;
+}
+
 #ifdef CONFIG_CONSOLE_POLL
 /*
  * Console polling routines for writing and reading from the uart while
@@ -1365,6 +1396,11 @@ static void s3c24xx_serial_put_poll_char(struct uart_port *port,
 		unsigned char c)
 {
 	unsigned int ufcon = rd_regl(cons_uart, S3C2410_UFCON);
+	unsigned int ucon = rd_regl(cons_uart, S3C2410_UCON);
+
+	/* not possible to xmit on unconfigured port */
+	if (!s3c24xx_port_configured(ucon))
+		return;
 
 	while (!s3c24xx_serial_console_txrdy(port, ufcon))
 		cpu_relax();
@@ -1377,6 +1413,12 @@ static void
 s3c24xx_serial_console_putchar(struct uart_port *port, int ch)
 {
 	unsigned int ufcon = rd_regl(cons_uart, S3C2410_UFCON);
+	unsigned int ucon = rd_regl(cons_uart, S3C2410_UCON);
+
+	/* not possible to xmit on unconfigured port */
+	if (!s3c24xx_port_configured(ucon))
+		return;
+
 	while (!s3c24xx_serial_console_txrdy(port, ufcon))
 		barrier();
 	wr_regb(cons_uart, S3C2410_UTXH, ch);
@@ -1409,9 +1451,7 @@ s3c24xx_serial_get_options(struct uart_port *port, int *baud,
 	    "registers: ulcon=%08x, ucon=%08x, ubdriv=%08x\n",
 	    port, ulcon, ucon, ubrdiv);
 
-	if ((ucon & 0xf) != 0) {
-		/* consider the serial port configured if the tx/rx mode set */
-
+	if (s3c24xx_port_configured(ucon)) {
 		switch (ulcon & S3C2410_LCON_CSMASK) {
 		case S3C2410_LCON_CS5:
 			*bits = 5;
diff --git a/drivers/tty/serial/serial-tegra.c b/drivers/tty/serial/serial-tegra.c
index 372de8a..9799d04 100644
--- a/drivers/tty/serial/serial-tegra.c
+++ b/drivers/tty/serial/serial-tegra.c
@@ -26,6 +26,7 @@
 #include <linux/dmaengine.h>
 #include <linux/dma-mapping.h>
 #include <linux/dmapool.h>
+#include <linux/err.h>
 #include <linux/io.h>
 #include <linux/irq.h>
 #include <linux/module.h>
@@ -1301,11 +1302,9 @@ static int tegra_uart_probe(struct platform_device *pdev)
 	}
 
 	u->mapbase = resource->start;
-	u->membase = devm_request_and_ioremap(&pdev->dev, resource);
-	if (!u->membase) {
-		dev_err(&pdev->dev, "memregion/iomap address req failed\n");
-		return -EADDRNOTAVAIL;
-	}
+	u->membase = devm_ioremap_resource(&pdev->dev, resource);
+	if (IS_ERR(u->membase))
+		return PTR_ERR(u->membase);
 
 	tup->uart_clk = devm_clk_get(&pdev->dev, NULL);
 	if (IS_ERR(tup->uart_clk)) {
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index a400002..19cc749 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -1711,7 +1711,7 @@ static int uart_proc_show(struct seq_file *m, void *v)
 
 static int uart_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, uart_proc_show, PDE(inode)->data);
+	return single_open(file, uart_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations uart_proc_fops = {
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index 1564186..e3847cc 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -52,6 +52,7 @@
 #include <linux/scatterlist.h>
 #include <linux/slab.h>
 #include <linux/gpio.h>
+#include <linux/of.h>
 
 #ifdef CONFIG_SUPERH
 #include <asm/sh_bios.h>
@@ -2351,6 +2352,112 @@ static int sci_remove(struct platform_device *dev)
 	return 0;
 }
 
+#ifdef CONFIG_OF
+static const struct of_device_id of_sci_match[] = {
+	{ .compatible = "renesas,sci-SCI-uart",
+		.data = (void *)PORT_SCI },
+	{ .compatible = "renesas,sci-SCIF-uart",
+		.data = (void *)PORT_SCIF },
+	{ .compatible = "renesas,sci-IRDA-uart",
+		.data = (void *)PORT_IRDA },
+	{ .compatible = "renesas,sci-SCIFA-uart",
+		.data = (void *)PORT_SCIFA },
+	{ .compatible = "renesas,sci-SCIFB-uart",
+		.data = (void *)PORT_SCIFB },
+	{},
+};
+MODULE_DEVICE_TABLE(of, of_sci_match);
+
+static struct plat_sci_port *sci_parse_dt(struct platform_device *pdev,
+								int *dev_id)
+{
+	struct plat_sci_port *p;
+	struct device_node *np = pdev->dev.of_node;
+	const struct of_device_id *match;
+	struct resource *res;
+	const __be32 *prop;
+	int i, irq, val;
+
+	match = of_match_node(of_sci_match, pdev->dev.of_node);
+	if (!match || !match->data) {
+		dev_err(&pdev->dev, "OF match error\n");
+		return NULL;
+	}
+
+	p = devm_kzalloc(&pdev->dev, sizeof(struct plat_sci_port), GFP_KERNEL);
+	if (!p) {
+		dev_err(&pdev->dev, "failed to allocate DT config data\n");
+		return NULL;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "failed to get I/O memory\n");
+		return NULL;
+	}
+	p->mapbase = res->start;
+
+	for (i = 0; i < SCIx_NR_IRQS; i++) {
+		irq = platform_get_irq(pdev, i);
+		if (irq < 0) {
+			dev_err(&pdev->dev, "failed to get irq data %d\n", i);
+			return NULL;
+		}
+		p->irqs[i] = irq;
+	}
+
+	prop = of_get_property(np, "cell-index", NULL);
+	if (!prop) {
+		dev_err(&pdev->dev, "required DT prop cell-index missing\n");
+		return NULL;
+	}
+	*dev_id = be32_to_cpup(prop);
+
+	prop = of_get_property(np, "renesas,scscr", NULL);
+	if (!prop) {
+		dev_err(&pdev->dev, "required DT prop scscr missing\n");
+		return NULL;
+	}
+	p->scscr = be32_to_cpup(prop);
+
+	prop = of_get_property(np, "renesas,scbrr-algo-id", NULL);
+	if (!prop) {
+		dev_err(&pdev->dev, "required DT prop scbrr-algo-id missing\n");
+		return NULL;
+	}
+	val = be32_to_cpup(prop);
+	if (val <= SCBRR_ALGO_INVALID || val >= SCBRR_NR_ALGOS) {
+		dev_err(&pdev->dev, "DT prop scbrr-algo-id out of range\n");
+		return NULL;
+	}
+	p->scbrr_algo_id = val;
+
+	p->flags = UPF_IOREMAP;
+	if (of_get_property(np, "renesas,autoconf", NULL))
+		p->flags |= UPF_BOOT_AUTOCONF;
+
+	prop = of_get_property(np, "renesas,regtype", NULL);
+	if (prop) {
+		val = be32_to_cpup(prop);
+		if (val < SCIx_PROBE_REGTYPE || val >= SCIx_NR_REGTYPES) {
+			dev_err(&pdev->dev, "DT prop regtype out of range\n");
+			return NULL;
+		}
+		p->regtype = val;
+	}
+
+	p->type = (unsigned int)match->data;
+
+	return p;
+}
+#else
+static struct plat_sci_port *sci_parse_dt(struct platform_device *pdev,
+								int *dev_id)
+{
+	return NULL;
+}
+#endif /* CONFIG_OF */
+
 static int sci_probe_single(struct platform_device *dev,
 				      unsigned int index,
 				      struct plat_sci_port *p,
@@ -2383,9 +2490,9 @@ static int sci_probe_single(struct platform_device *dev,
 
 static int sci_probe(struct platform_device *dev)
 {
-	struct plat_sci_port *p = dev->dev.platform_data;
-	struct sci_port *sp = &sci_ports[dev->id];
-	int ret;
+	struct plat_sci_port *p;
+	struct sci_port *sp;
+	int ret, dev_id = dev->id;
 
 	/*
 	 * If we've come here via earlyprintk initialization, head off to
@@ -2395,9 +2502,20 @@ static int sci_probe(struct platform_device *dev)
 	if (is_early_platform_device(dev))
 		return sci_probe_earlyprintk(dev);
 
+	if (dev->dev.of_node)
+		p = sci_parse_dt(dev, &dev_id);
+	else
+		p = dev->dev.platform_data;
+
+	if (!p) {
+		dev_err(&dev->dev, "no setup data supplied\n");
+		return -EINVAL;
+	}
+
+	sp = &sci_ports[dev_id];
 	platform_set_drvdata(dev, sp);
 
-	ret = sci_probe_single(dev, dev->id, p, sp);
+	ret = sci_probe_single(dev, dev_id, p, sp);
 	if (ret)
 		return ret;
 
@@ -2449,6 +2567,7 @@ static struct platform_driver sci_driver = {
 		.name	= "sh-sci",
 		.owner	= THIS_MODULE,
 		.pm	= &sci_dev_pm_ops,
+		.of_match_table = of_match_ptr(of_sci_match),
 	},
 };
 
diff --git a/drivers/tty/serial/sh-sci.h b/drivers/tty/serial/sh-sci.h
index 4c22a15..5aca736 100644
--- a/drivers/tty/serial/sh-sci.h
+++ b/drivers/tty/serial/sh-sci.h
@@ -15,8 +15,6 @@
     defined(CONFIG_CPU_SUBTYPE_SH7720) || \
     defined(CONFIG_CPU_SUBTYPE_SH7721) || \
     defined(CONFIG_ARCH_SH73A0) || \
-    defined(CONFIG_ARCH_SH7367) || \
-    defined(CONFIG_ARCH_SH7377) || \
     defined(CONFIG_ARCH_SH7372) || \
     defined(CONFIG_ARCH_R8A7740)
 
diff --git a/drivers/tty/serial/sunsab.c b/drivers/tty/serial/sunsab.c
index 8de2213..a422c8b 100644
--- a/drivers/tty/serial/sunsab.c
+++ b/drivers/tty/serial/sunsab.c
@@ -203,7 +203,7 @@ receive_chars(struct uart_sunsab_port *up,
 				flag = TTY_FRAME;
 		}
 
-		if (uart_handle_sysrq_char(&up->port, ch))
+		if (uart_handle_sysrq_char(&up->port, ch) || !port)
 			continue;
 
 		if ((stat->sreg.isr0 & (up->port.ignore_status_mask & 0xff)) == 0 &&
diff --git a/drivers/tty/serial/sunzilog.c b/drivers/tty/serial/sunzilog.c
index 27669ff..813ef8e 100644
--- a/drivers/tty/serial/sunzilog.c
+++ b/drivers/tty/serial/sunzilog.c
@@ -388,7 +388,7 @@ sunzilog_receive_chars(struct uart_sunzilog_port *up,
 			else if (r1 & CRC_ERR)
 				flag = TTY_FRAME;
 		}
-		if (uart_handle_sysrq_char(&up->port, ch))
+		if (uart_handle_sysrq_char(&up->port, ch) || !port)
 			continue;
 
 		if (up->port.ignore_status_mask == 0xff ||
diff --git a/drivers/tty/serial/vt8500_serial.c b/drivers/tty/serial/vt8500_serial.c
index 705240e..1a8bc22 100644
--- a/drivers/tty/serial/vt8500_serial.c
+++ b/drivers/tty/serial/vt8500_serial.c
@@ -35,6 +35,7 @@
 #include <linux/clk.h>
 #include <linux/platform_device.h>
 #include <linux/of.h>
+#include <linux/err.h>
 
 /*
  * UART Register offsets
@@ -585,9 +586,9 @@ static int vt8500_serial_probe(struct platform_device *pdev)
 	if (!vt8500_port)
 		return -ENOMEM;
 
-	vt8500_port->uart.membase = devm_request_and_ioremap(&pdev->dev, mmres);
-	if (!vt8500_port->uart.membase)
-		return -EADDRNOTAVAIL;
+	vt8500_port->uart.membase = devm_ioremap_resource(&pdev->dev, mmres);
+	if (IS_ERR(vt8500_port->uart.membase))
+		return PTR_ERR(vt8500_port->uart.membase);
 
 	vt8500_port->clk = of_clk_get(pdev->dev.of_node, 0);
 	if (IS_ERR(vt8500_port->clk)) {
diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c
index f36bbba..4e5c778 100644
--- a/drivers/tty/serial/xilinx_uartps.c
+++ b/drivers/tty/serial/xilinx_uartps.c
@@ -585,9 +585,6 @@ static int xuartps_startup(struct uart_port *port)
 	xuartps_writel(XUARTPS_IXR_TXEMPTY | XUARTPS_IXR_PARITY |
 		XUARTPS_IXR_FRAMING | XUARTPS_IXR_OVERRUN |
 		XUARTPS_IXR_RXTRIG | XUARTPS_IXR_TOUT, XUARTPS_IER_OFFSET);
-	xuartps_writel(~(XUARTPS_IXR_TXEMPTY | XUARTPS_IXR_PARITY |
-		XUARTPS_IXR_FRAMING | XUARTPS_IXR_OVERRUN |
-		XUARTPS_IXR_RXTRIG | XUARTPS_IXR_TOUT), XUARTPS_IDR_OFFSET);
 
 	return retval;
 }
diff --git a/drivers/tty/synclink.c b/drivers/tty/synclink.c
index 8983276..72d6071 100644
--- a/drivers/tty/synclink.c
+++ b/drivers/tty/synclink.c
@@ -1058,9 +1058,6 @@ static void mgsl_bh_handler(struct work_struct *work)
 		container_of(work, struct mgsl_struct, task);
 	int action;
 
-	if (!info)
-		return;
-		
 	if ( debug_level >= DEBUG_LEVEL_BH )
 		printk( "%s(%d):mgsl_bh_handler(%s) entry\n",
 			__FILE__,__LINE__,info->device_name);
diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c
index 3687f0c..b51c154 100644
--- a/drivers/tty/sysrq.c
+++ b/drivers/tty/sysrq.c
@@ -43,6 +43,7 @@
 #include <linux/input.h>
 #include <linux/uaccess.h>
 #include <linux/moduleparam.h>
+#include <linux/jiffies.h>
 
 #include <asm/ptrace.h>
 #include <asm/irq_regs.h>
@@ -51,6 +52,9 @@
 static int __read_mostly sysrq_enabled = SYSRQ_DEFAULT_ENABLE;
 static bool __read_mostly sysrq_always_enabled;
 
+unsigned short platform_sysrq_reset_seq[] __weak = { KEY_RESERVED };
+int sysrq_reset_downtime_ms __weak;
+
 static bool sysrq_on(void)
 {
 	return sysrq_enabled || sysrq_always_enabled;
@@ -101,7 +105,7 @@ static void sysrq_handle_SAK(int key)
 }
 static struct sysrq_key_op sysrq_SAK_op = {
 	.handler	= sysrq_handle_SAK,
-	.help_msg	= "saK",
+	.help_msg	= "sak(k)",
 	.action_msg	= "SAK",
 	.enable_mask	= SYSRQ_ENABLE_KEYBOARD,
 };
@@ -117,7 +121,7 @@ static void sysrq_handle_unraw(int key)
 
 static struct sysrq_key_op sysrq_unraw_op = {
 	.handler	= sysrq_handle_unraw,
-	.help_msg	= "unRaw",
+	.help_msg	= "unraw(r)",
 	.action_msg	= "Keyboard mode set to system default",
 	.enable_mask	= SYSRQ_ENABLE_KEYBOARD,
 };
@@ -135,7 +139,7 @@ static void sysrq_handle_crash(int key)
 }
 static struct sysrq_key_op sysrq_crash_op = {
 	.handler	= sysrq_handle_crash,
-	.help_msg	= "Crash",
+	.help_msg	= "crash(c)",
 	.action_msg	= "Trigger a crash",
 	.enable_mask	= SYSRQ_ENABLE_DUMP,
 };
@@ -148,7 +152,7 @@ static void sysrq_handle_reboot(int key)
 }
 static struct sysrq_key_op sysrq_reboot_op = {
 	.handler	= sysrq_handle_reboot,
-	.help_msg	= "reBoot",
+	.help_msg	= "reboot(b)",
 	.action_msg	= "Resetting",
 	.enable_mask	= SYSRQ_ENABLE_BOOT,
 };
@@ -159,7 +163,7 @@ static void sysrq_handle_sync(int key)
 }
 static struct sysrq_key_op sysrq_sync_op = {
 	.handler	= sysrq_handle_sync,
-	.help_msg	= "Sync",
+	.help_msg	= "sync(s)",
 	.action_msg	= "Emergency Sync",
 	.enable_mask	= SYSRQ_ENABLE_SYNC,
 };
@@ -171,7 +175,7 @@ static void sysrq_handle_show_timers(int key)
 
 static struct sysrq_key_op sysrq_show_timers_op = {
 	.handler	= sysrq_handle_show_timers,
-	.help_msg	= "show-all-timers(Q)",
+	.help_msg	= "show-all-timers(q)",
 	.action_msg	= "Show clockevent devices & pending hrtimers (no others)",
 };
 
@@ -181,7 +185,7 @@ static void sysrq_handle_mountro(int key)
 }
 static struct sysrq_key_op sysrq_mountro_op = {
 	.handler	= sysrq_handle_mountro,
-	.help_msg	= "Unmount",
+	.help_msg	= "unmount(u)",
 	.action_msg	= "Emergency Remount R/O",
 	.enable_mask	= SYSRQ_ENABLE_REMOUNT,
 };
@@ -194,7 +198,7 @@ static void sysrq_handle_showlocks(int key)
 
 static struct sysrq_key_op sysrq_showlocks_op = {
 	.handler	= sysrq_handle_showlocks,
-	.help_msg	= "show-all-locks(D)",
+	.help_msg	= "show-all-locks(d)",
 	.action_msg	= "Show Locks Held",
 };
 #else
@@ -245,7 +249,7 @@ static void sysrq_handle_showallcpus(int key)
 
 static struct sysrq_key_op sysrq_showallcpus_op = {
 	.handler	= sysrq_handle_showallcpus,
-	.help_msg	= "show-backtrace-all-active-cpus(L)",
+	.help_msg	= "show-backtrace-all-active-cpus(l)",
 	.action_msg	= "Show backtrace of all active CPUs",
 	.enable_mask	= SYSRQ_ENABLE_DUMP,
 };
@@ -260,7 +264,7 @@ static void sysrq_handle_showregs(int key)
 }
 static struct sysrq_key_op sysrq_showregs_op = {
 	.handler	= sysrq_handle_showregs,
-	.help_msg	= "show-registers(P)",
+	.help_msg	= "show-registers(p)",
 	.action_msg	= "Show Regs",
 	.enable_mask	= SYSRQ_ENABLE_DUMP,
 };
@@ -271,7 +275,7 @@ static void sysrq_handle_showstate(int key)
 }
 static struct sysrq_key_op sysrq_showstate_op = {
 	.handler	= sysrq_handle_showstate,
-	.help_msg	= "show-task-states(T)",
+	.help_msg	= "show-task-states(t)",
 	.action_msg	= "Show State",
 	.enable_mask	= SYSRQ_ENABLE_DUMP,
 };
@@ -282,7 +286,7 @@ static void sysrq_handle_showstate_blocked(int key)
 }
 static struct sysrq_key_op sysrq_showstate_blocked_op = {
 	.handler	= sysrq_handle_showstate_blocked,
-	.help_msg	= "show-blocked-tasks(W)",
+	.help_msg	= "show-blocked-tasks(w)",
 	.action_msg	= "Show Blocked State",
 	.enable_mask	= SYSRQ_ENABLE_DUMP,
 };
@@ -296,7 +300,7 @@ static void sysrq_ftrace_dump(int key)
 }
 static struct sysrq_key_op sysrq_ftrace_dump_op = {
 	.handler	= sysrq_ftrace_dump,
-	.help_msg	= "dump-ftrace-buffer(Z)",
+	.help_msg	= "dump-ftrace-buffer(z)",
 	.action_msg	= "Dump ftrace buffer",
 	.enable_mask	= SYSRQ_ENABLE_DUMP,
 };
@@ -310,7 +314,7 @@ static void sysrq_handle_showmem(int key)
 }
 static struct sysrq_key_op sysrq_showmem_op = {
 	.handler	= sysrq_handle_showmem,
-	.help_msg	= "show-memory-usage(M)",
+	.help_msg	= "show-memory-usage(m)",
 	.action_msg	= "Show Memory",
 	.enable_mask	= SYSRQ_ENABLE_DUMP,
 };
@@ -341,7 +345,7 @@ static void sysrq_handle_term(int key)
 }
 static struct sysrq_key_op sysrq_term_op = {
 	.handler	= sysrq_handle_term,
-	.help_msg	= "terminate-all-tasks(E)",
+	.help_msg	= "terminate-all-tasks(e)",
 	.action_msg	= "Terminate All Tasks",
 	.enable_mask	= SYSRQ_ENABLE_SIGNAL,
 };
@@ -360,7 +364,7 @@ static void sysrq_handle_moom(int key)
 }
 static struct sysrq_key_op sysrq_moom_op = {
 	.handler	= sysrq_handle_moom,
-	.help_msg	= "memory-full-oom-kill(F)",
+	.help_msg	= "memory-full-oom-kill(f)",
 	.action_msg	= "Manual OOM execution",
 	.enable_mask	= SYSRQ_ENABLE_SIGNAL,
 };
@@ -372,7 +376,7 @@ static void sysrq_handle_thaw(int key)
 }
 static struct sysrq_key_op sysrq_thaw_op = {
 	.handler	= sysrq_handle_thaw,
-	.help_msg	= "thaw-filesystems(J)",
+	.help_msg	= "thaw-filesystems(j)",
 	.action_msg	= "Emergency Thaw of all frozen filesystems",
 	.enable_mask	= SYSRQ_ENABLE_SIGNAL,
 };
@@ -385,7 +389,7 @@ static void sysrq_handle_kill(int key)
 }
 static struct sysrq_key_op sysrq_kill_op = {
 	.handler	= sysrq_handle_kill,
-	.help_msg	= "kill-all-tasks(I)",
+	.help_msg	= "kill-all-tasks(i)",
 	.action_msg	= "Kill All Tasks",
 	.enable_mask	= SYSRQ_ENABLE_SIGNAL,
 };
@@ -396,7 +400,7 @@ static void sysrq_handle_unrt(int key)
 }
 static struct sysrq_key_op sysrq_unrt_op = {
 	.handler	= sysrq_handle_unrt,
-	.help_msg	= "nice-all-RT-tasks(N)",
+	.help_msg	= "nice-all-RT-tasks(n)",
 	.action_msg	= "Nice All RT Tasks",
 	.enable_mask	= SYSRQ_ENABLE_RTNICE,
 };
@@ -586,6 +590,7 @@ struct sysrq_state {
 	int reset_seq_len;
 	int reset_seq_cnt;
 	int reset_seq_version;
+	struct timer_list keyreset_timer;
 };
 
 #define SYSRQ_KEY_RESET_MAX	20 /* Should be plenty */
@@ -619,29 +624,51 @@ static void sysrq_parse_reset_sequence(struct sysrq_state *state)
 	state->reset_seq_version = sysrq_reset_seq_version;
 }
 
-static bool sysrq_detect_reset_sequence(struct sysrq_state *state,
+static void sysrq_do_reset(unsigned long dummy)
+{
+	__handle_sysrq(sysrq_xlate[KEY_B], false);
+}
+
+static void sysrq_handle_reset_request(struct sysrq_state *state)
+{
+	if (sysrq_reset_downtime_ms)
+		mod_timer(&state->keyreset_timer,
+			jiffies + msecs_to_jiffies(sysrq_reset_downtime_ms));
+	else
+		sysrq_do_reset(0);
+}
+
+static void sysrq_detect_reset_sequence(struct sysrq_state *state,
 					unsigned int code, int value)
 {
 	if (!test_bit(code, state->reset_keybit)) {
 		/*
 		 * Pressing any key _not_ in reset sequence cancels
-		 * the reset sequence.
+		 * the reset sequence.  Also cancelling the timer in
+		 * case additional keys were pressed after a reset
+		 * has been requested.
 		 */
-		if (value && state->reset_seq_cnt)
+		if (value && state->reset_seq_cnt) {
 			state->reset_canceled = true;
+			del_timer(&state->keyreset_timer);
+		}
 	} else if (value == 0) {
-		/* key release */
+		/*
+		 * Key release - all keys in the reset sequence need
+		 * to be pressed and held for the reset timeout
+		 * to hold.
+		 */
+		del_timer(&state->keyreset_timer);
+
 		if (--state->reset_seq_cnt == 0)
 			state->reset_canceled = false;
 	} else if (value == 1) {
 		/* key press, not autorepeat */
 		if (++state->reset_seq_cnt == state->reset_seq_len &&
 		    !state->reset_canceled) {
-			return true;
+			sysrq_handle_reset_request(state);
 		}
 	}
-
-	return false;
 }
 
 static void sysrq_reinject_alt_sysrq(struct work_struct *work)
@@ -748,10 +775,8 @@ static bool sysrq_handle_keypress(struct sysrq_state *sysrq,
 		if (was_active)
 			schedule_work(&sysrq->reinject_work);
 
-		if (sysrq_detect_reset_sequence(sysrq, code, value)) {
-			/* Force emergency reboot */
-			__handle_sysrq(sysrq_xlate[KEY_B], false);
-		}
+		/* Check for reset sequence */
+		sysrq_detect_reset_sequence(sysrq, code, value);
 
 	} else if (value == 0 && test_and_clear_bit(code, sysrq->key_down)) {
 		/*
@@ -812,6 +837,7 @@ static int sysrq_connect(struct input_handler *handler,
 	sysrq->handle.handler = handler;
 	sysrq->handle.name = "sysrq";
 	sysrq->handle.private = sysrq;
+	setup_timer(&sysrq->keyreset_timer, sysrq_do_reset, 0);
 
 	error = input_register_handle(&sysrq->handle);
 	if (error) {
@@ -841,6 +867,7 @@ static void sysrq_disconnect(struct input_handle *handle)
 
 	input_close_device(handle);
 	cancel_work_sync(&sysrq->reinject_work);
+	del_timer_sync(&sysrq->keyreset_timer);
 	input_unregister_handle(handle);
 	kfree(sysrq);
 }
@@ -870,8 +897,6 @@ static struct input_handler sysrq_handler = {
 
 static bool sysrq_handler_registered;
 
-unsigned short platform_sysrq_reset_seq[] __weak = { KEY_RESERVED };
-
 static inline void sysrq_register_handler(void)
 {
 	unsigned short key;
@@ -931,6 +956,8 @@ static struct kernel_param_ops param_ops_sysrq_reset_seq = {
 module_param_array_named(reset_seq, sysrq_reset_seq, sysrq_reset_seq,
 			 &sysrq_reset_seq_len, 0644);
 
+module_param_named(sysrq_downtime_ms, sysrq_reset_downtime_ms, int, 0644);
+
 #else
 
 static inline void sysrq_register_handler(void)
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index 05400ac..cbf5a50 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -533,6 +533,60 @@ void tty_wakeup(struct tty_struct *tty)
 EXPORT_SYMBOL_GPL(tty_wakeup);
 
 /**
+ *	tty_signal_session_leader	- sends SIGHUP to session leader
+ *	@tty		controlling tty
+ *	@exit_session	if non-zero, signal all foreground group processes
+ *
+ *	Send SIGHUP and SIGCONT to the session leader and its process group.
+ *	Optionally, signal all processes in the foreground process group.
+ *
+ *	Returns the number of processes in the session with this tty
+ *	as their controlling terminal. This value is used to drop
+ *	tty references for those processes.
+ */
+static int tty_signal_session_leader(struct tty_struct *tty, int exit_session)
+{
+	struct task_struct *p;
+	int refs = 0;
+	struct pid *tty_pgrp = NULL;
+
+	read_lock(&tasklist_lock);
+	if (tty->session) {
+		do_each_pid_task(tty->session, PIDTYPE_SID, p) {
+			spin_lock_irq(&p->sighand->siglock);
+			if (p->signal->tty == tty) {
+				p->signal->tty = NULL;
+				/* We defer the dereferences outside fo
+				   the tasklist lock */
+				refs++;
+			}
+			if (!p->signal->leader) {
+				spin_unlock_irq(&p->sighand->siglock);
+				continue;
+			}
+			__group_send_sig_info(SIGHUP, SEND_SIG_PRIV, p);
+			__group_send_sig_info(SIGCONT, SEND_SIG_PRIV, p);
+			put_pid(p->signal->tty_old_pgrp);  /* A noop */
+			spin_lock(&tty->ctrl_lock);
+			tty_pgrp = get_pid(tty->pgrp);
+			if (tty->pgrp)
+				p->signal->tty_old_pgrp = get_pid(tty->pgrp);
+			spin_unlock(&tty->ctrl_lock);
+			spin_unlock_irq(&p->sighand->siglock);
+		} while_each_pid_task(tty->session, PIDTYPE_SID, p);
+	}
+	read_unlock(&tasklist_lock);
+
+	if (tty_pgrp) {
+		if (exit_session)
+			kill_pgrp(tty_pgrp, SIGHUP, exit_session);
+		put_pid(tty_pgrp);
+	}
+
+	return refs;
+}
+
+/**
  *	__tty_hangup		-	actual handler for hangup events
  *	@work: tty device
  *
@@ -554,15 +608,13 @@ EXPORT_SYMBOL_GPL(tty_wakeup);
  *		  tasklist_lock to walk task list for hangup event
  *		    ->siglock to protect ->signal/->sighand
  */
-static void __tty_hangup(struct tty_struct *tty)
+static void __tty_hangup(struct tty_struct *tty, int exit_session)
 {
 	struct file *cons_filp = NULL;
 	struct file *filp, *f = NULL;
-	struct task_struct *p;
 	struct tty_file_private *priv;
 	int    closecount = 0, n;
-	unsigned long flags;
-	int refs = 0;
+	int refs;
 
 	if (!tty)
 		return;
@@ -599,39 +651,18 @@ static void __tty_hangup(struct tty_struct *tty)
 	}
 	spin_unlock(&tty_files_lock);
 
+	refs = tty_signal_session_leader(tty, exit_session);
+	/* Account for the p->signal references we killed */
+	while (refs--)
+		tty_kref_put(tty);
+
 	/*
 	 * it drops BTM and thus races with reopen
 	 * we protect the race by TTY_HUPPING
 	 */
 	tty_ldisc_hangup(tty);
 
-	read_lock(&tasklist_lock);
-	if (tty->session) {
-		do_each_pid_task(tty->session, PIDTYPE_SID, p) {
-			spin_lock_irq(&p->sighand->siglock);
-			if (p->signal->tty == tty) {
-				p->signal->tty = NULL;
-				/* We defer the dereferences outside fo
-				   the tasklist lock */
-				refs++;
-			}
-			if (!p->signal->leader) {
-				spin_unlock_irq(&p->sighand->siglock);
-				continue;
-			}
-			__group_send_sig_info(SIGHUP, SEND_SIG_PRIV, p);
-			__group_send_sig_info(SIGCONT, SEND_SIG_PRIV, p);
-			put_pid(p->signal->tty_old_pgrp);  /* A noop */
-			spin_lock_irqsave(&tty->ctrl_lock, flags);
-			if (tty->pgrp)
-				p->signal->tty_old_pgrp = get_pid(tty->pgrp);
-			spin_unlock_irqrestore(&tty->ctrl_lock, flags);
-			spin_unlock_irq(&p->sighand->siglock);
-		} while_each_pid_task(tty->session, PIDTYPE_SID, p);
-	}
-	read_unlock(&tasklist_lock);
-
-	spin_lock_irqsave(&tty->ctrl_lock, flags);
+	spin_lock_irq(&tty->ctrl_lock);
 	clear_bit(TTY_THROTTLED, &tty->flags);
 	clear_bit(TTY_PUSH, &tty->flags);
 	clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
@@ -640,11 +671,7 @@ static void __tty_hangup(struct tty_struct *tty)
 	tty->session = NULL;
 	tty->pgrp = NULL;
 	tty->ctrl_status = 0;
-	spin_unlock_irqrestore(&tty->ctrl_lock, flags);
-
-	/* Account for the p->signal references we killed */
-	while (refs--)
-		tty_kref_put(tty);
+	spin_unlock_irq(&tty->ctrl_lock);
 
 	/*
 	 * If one of the devices matches a console pointer, we
@@ -666,7 +693,6 @@ static void __tty_hangup(struct tty_struct *tty)
 	 */
 	set_bit(TTY_HUPPED, &tty->flags);
 	clear_bit(TTY_HUPPING, &tty->flags);
-	tty_ldisc_enable(tty);
 
 	tty_unlock(tty);
 
@@ -679,7 +705,7 @@ static void do_tty_hangup(struct work_struct *work)
 	struct tty_struct *tty =
 		container_of(work, struct tty_struct, hangup_work);
 
-	__tty_hangup(tty);
+	__tty_hangup(tty, 0);
 }
 
 /**
@@ -717,7 +743,7 @@ void tty_vhangup(struct tty_struct *tty)
 
 	printk(KERN_DEBUG "%s vhangup...\n", tty_name(tty, buf));
 #endif
-	__tty_hangup(tty);
+	__tty_hangup(tty, 0);
 }
 
 EXPORT_SYMBOL(tty_vhangup);
@@ -741,6 +767,27 @@ void tty_vhangup_self(void)
 }
 
 /**
+ *	tty_vhangup_session		-	hangup session leader exit
+ *	@tty: tty to hangup
+ *
+ *	The session leader is exiting and hanging up its controlling terminal.
+ *	Every process in the foreground process group is signalled SIGHUP.
+ *
+ *	We do this synchronously so that when the syscall returns the process
+ *	is complete. That guarantee is necessary for security reasons.
+ */
+
+static void tty_vhangup_session(struct tty_struct *tty)
+{
+#ifdef TTY_DEBUG_HANGUP
+	char	buf[64];
+
+	printk(KERN_DEBUG "%s vhangup session...\n", tty_name(tty, buf));
+#endif
+	__tty_hangup(tty, 1);
+}
+
+/**
  *	tty_hung_up_p		-	was tty hung up
  *	@filp: file pointer of tty
  *
@@ -797,18 +844,18 @@ void disassociate_ctty(int on_exit)
 
 	tty = get_current_tty();
 	if (tty) {
-		struct pid *tty_pgrp = get_pid(tty->pgrp);
-		if (on_exit) {
-			if (tty->driver->type != TTY_DRIVER_TYPE_PTY)
-				tty_vhangup(tty);
-		}
-		tty_kref_put(tty);
-		if (tty_pgrp) {
-			kill_pgrp(tty_pgrp, SIGHUP, on_exit);
-			if (!on_exit)
+		if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY) {
+			tty_vhangup_session(tty);
+		} else {
+			struct pid *tty_pgrp = tty_get_pgrp(tty);
+			if (tty_pgrp) {
+				kill_pgrp(tty_pgrp, SIGHUP, on_exit);
 				kill_pgrp(tty_pgrp, SIGCONT, on_exit);
-			put_pid(tty_pgrp);
+				put_pid(tty_pgrp);
+			}
 		}
+		tty_kref_put(tty);
+
 	} else if (on_exit) {
 		struct pid *old_pgrp;
 		spin_lock_irq(&current->sighand->siglock);
@@ -1344,9 +1391,7 @@ static int tty_reopen(struct tty_struct *tty)
 	}
 	tty->count++;
 
-	mutex_lock(&tty->ldisc_mutex);
 	WARN_ON(!test_bit(TTY_LDISC, &tty->flags));
-	mutex_unlock(&tty->ldisc_mutex);
 
 	return 0;
 }
@@ -1463,6 +1508,17 @@ void tty_free_termios(struct tty_struct *tty)
 }
 EXPORT_SYMBOL(tty_free_termios);
 
+/**
+ *	tty_flush_works		-	flush all works of a tty
+ *	@tty: tty device to flush works for
+ *
+ *	Sync flush all works belonging to @tty.
+ */
+static void tty_flush_works(struct tty_struct *tty)
+{
+	flush_work(&tty->SAK_work);
+	flush_work(&tty->hangup_work);
+}
 
 /**
  *	release_one_tty		-	release tty structure memory
@@ -1548,6 +1604,7 @@ static void release_tty(struct tty_struct *tty, int idx)
 	tty_free_termios(tty);
 	tty_driver_remove_tty(tty->driver, tty);
 	tty->port->itty = NULL;
+	cancel_work_sync(&tty->port->buf.work);
 
 	if (tty->link)
 		tty_kref_put(tty->link);
@@ -1777,12 +1834,21 @@ int tty_release(struct inode *inode, struct file *filp)
 		return 0;
 
 #ifdef TTY_DEBUG_HANGUP
-	printk(KERN_DEBUG "%s: freeing tty structure...\n", __func__);
+	printk(KERN_DEBUG "%s: %s: final close\n", __func__, tty_name(tty, buf));
 #endif
 	/*
 	 * Ask the line discipline code to release its structures
 	 */
 	tty_ldisc_release(tty, o_tty);
+
+	/* Wait for pending work before tty destruction commmences */
+	tty_flush_works(tty);
+	if (o_tty)
+		tty_flush_works(o_tty);
+
+#ifdef TTY_DEBUG_HANGUP
+	printk(KERN_DEBUG "%s: %s: freeing structure...\n", __func__, tty_name(tty, buf));
+#endif
 	/*
 	 * The release_tty function takes care of the details of clearing
 	 * the slots and preserving the termios structure. The tty_unlock_pair
diff --git a/drivers/tty/tty_ioctl.c b/drivers/tty/tty_ioctl.c
index d58b92c..d119034 100644
--- a/drivers/tty/tty_ioctl.c
+++ b/drivers/tty/tty_ioctl.c
@@ -106,6 +106,7 @@ void tty_throttle(struct tty_struct *tty)
 	if (!test_and_set_bit(TTY_THROTTLED, &tty->flags) &&
 	    tty->ops->throttle)
 		tty->ops->throttle(tty);
+	tty->flow_change = 0;
 	mutex_unlock(&tty->termios_mutex);
 }
 EXPORT_SYMBOL(tty_throttle);
@@ -129,11 +130,74 @@ void tty_unthrottle(struct tty_struct *tty)
 	if (test_and_clear_bit(TTY_THROTTLED, &tty->flags) &&
 	    tty->ops->unthrottle)
 		tty->ops->unthrottle(tty);
+	tty->flow_change = 0;
 	mutex_unlock(&tty->termios_mutex);
 }
 EXPORT_SYMBOL(tty_unthrottle);
 
 /**
+ *	tty_throttle_safe	-	flow control
+ *	@tty: terminal
+ *
+ *	Similar to tty_throttle() but will only attempt throttle
+ *	if tty->flow_change is TTY_THROTTLE_SAFE. Prevents an accidental
+ *	throttle due to race conditions when throttling is conditional
+ *	on factors evaluated prior to throttling.
+ *
+ *	Returns 0 if tty is throttled (or was already throttled)
+ */
+
+int tty_throttle_safe(struct tty_struct *tty)
+{
+	int ret = 0;
+
+	mutex_lock(&tty->termios_mutex);
+	if (!test_bit(TTY_THROTTLED, &tty->flags)) {
+		if (tty->flow_change != TTY_THROTTLE_SAFE)
+			ret = 1;
+		else {
+			__set_bit(TTY_THROTTLED, &tty->flags);
+			if (tty->ops->throttle)
+				tty->ops->throttle(tty);
+		}
+	}
+	mutex_unlock(&tty->termios_mutex);
+
+	return ret;
+}
+
+/**
+ *	tty_unthrottle_safe	-	flow control
+ *	@tty: terminal
+ *
+ *	Similar to tty_unthrottle() but will only attempt unthrottle
+ *	if tty->flow_change is TTY_UNTHROTTLE_SAFE. Prevents an accidental
+ *	unthrottle due to race conditions when unthrottling is conditional
+ *	on factors evaluated prior to unthrottling.
+ *
+ *	Returns 0 if tty is unthrottled (or was already unthrottled)
+ */
+
+int tty_unthrottle_safe(struct tty_struct *tty)
+{
+	int ret = 0;
+
+	mutex_lock(&tty->termios_mutex);
+	if (test_bit(TTY_THROTTLED, &tty->flags)) {
+		if (tty->flow_change != TTY_UNTHROTTLE_SAFE)
+			ret = 1;
+		else {
+			__clear_bit(TTY_THROTTLED, &tty->flags);
+			if (tty->ops->unthrottle)
+				tty->ops->unthrottle(tty);
+		}
+	}
+	mutex_unlock(&tty->termios_mutex);
+
+	return ret;
+}
+
+/**
  *	tty_wait_until_sent	-	wait for I/O to finish
  *	@tty: tty we are waiting for
  *	@timeout: how long we will wait
@@ -415,34 +479,6 @@ void tty_encode_baud_rate(struct tty_struct *tty, speed_t ibaud, speed_t obaud)
 EXPORT_SYMBOL_GPL(tty_encode_baud_rate);
 
 /**
- *	tty_get_baud_rate	-	get tty bit rates
- *	@tty: tty to query
- *
- *	Returns the baud rate as an integer for this terminal. The
- *	termios lock must be held by the caller and the terminal bit
- *	flags may be updated.
- *
- *	Locking: none
- */
-
-speed_t tty_get_baud_rate(struct tty_struct *tty)
-{
-	speed_t baud = tty_termios_baud_rate(&tty->termios);
-
-	if (baud == 38400 && tty->alt_speed) {
-		if (!tty->warned) {
-			printk(KERN_WARNING "Use of setserial/setrocket to "
-					    "set SPD_* flags is deprecated\n");
-			tty->warned = 1;
-		}
-		baud = tty->alt_speed;
-	}
-
-	return baud;
-}
-EXPORT_SYMBOL(tty_get_baud_rate);
-
-/**
  *	tty_termios_copy_hw	-	copy hardware settings
  *	@new: New termios
  *	@old: Old termios
@@ -1086,14 +1122,12 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
 }
 EXPORT_SYMBOL_GPL(tty_mode_ioctl);
 
-int tty_perform_flush(struct tty_struct *tty, unsigned long arg)
+
+/* Caller guarantees ldisc reference is held */
+static int __tty_perform_flush(struct tty_struct *tty, unsigned long arg)
 {
-	struct tty_ldisc *ld;
-	int retval = tty_check_change(tty);
-	if (retval)
-		return retval;
+	struct tty_ldisc *ld = tty->ldisc;
 
-	ld = tty_ldisc_ref_wait(tty);
 	switch (arg) {
 	case TCIFLUSH:
 		if (ld && ld->ops->flush_buffer) {
@@ -1111,12 +1145,24 @@ int tty_perform_flush(struct tty_struct *tty, unsigned long arg)
 		tty_driver_flush_buffer(tty);
 		break;
 	default:
-		tty_ldisc_deref(ld);
 		return -EINVAL;
 	}
-	tty_ldisc_deref(ld);
 	return 0;
 }
+
+int tty_perform_flush(struct tty_struct *tty, unsigned long arg)
+{
+	struct tty_ldisc *ld;
+	int retval = tty_check_change(tty);
+	if (retval)
+		return retval;
+
+	ld = tty_ldisc_ref_wait(tty);
+	retval = __tty_perform_flush(tty, arg);
+	if (ld)
+		tty_ldisc_deref(ld);
+	return retval;
+}
 EXPORT_SYMBOL_GPL(tty_perform_flush);
 
 int n_tty_ioctl_helper(struct tty_struct *tty, struct file *file,
@@ -1155,7 +1201,7 @@ int n_tty_ioctl_helper(struct tty_struct *tty, struct file *file,
 		}
 		return 0;
 	case TCFLSH:
-		return tty_perform_flush(tty, arg);
+		return __tty_perform_flush(tty, arg);
 	default:
 		/* Try the mode commands */
 		return tty_mode_ioctl(tty, file, cmd, arg);
diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c
index d794087..1afe192 100644
--- a/drivers/tty/tty_ldisc.c
+++ b/drivers/tty/tty_ldisc.c
@@ -20,6 +20,17 @@
 #include <linux/uaccess.h>
 #include <linux/ratelimit.h>
 
+#undef LDISC_DEBUG_HANGUP
+
+#ifdef LDISC_DEBUG_HANGUP
+#define tty_ldisc_debug(tty, f, args...) ({				       \
+	char __b[64];							       \
+	printk(KERN_DEBUG "%s: %s: " f, __func__, tty_name(tty, __b), ##args); \
+})
+#else
+#define tty_ldisc_debug(tty, f, args...)
+#endif
+
 /*
  *	This guards the refcounted line discipline lists. The lock
  *	must be taken with irqs off because there are hangup path
@@ -31,44 +42,6 @@ static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait);
 /* Line disc dispatch table */
 static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS];
 
-static inline struct tty_ldisc *get_ldisc(struct tty_ldisc *ld)
-{
-	if (ld)
-		atomic_inc(&ld->users);
-	return ld;
-}
-
-static void put_ldisc(struct tty_ldisc *ld)
-{
-	unsigned long flags;
-
-	if (WARN_ON_ONCE(!ld))
-		return;
-
-	/*
-	 * If this is the last user, free the ldisc, and
-	 * release the ldisc ops.
-	 *
-	 * We really want an "atomic_dec_and_raw_lock_irqsave()",
-	 * but we don't have it, so this does it by hand.
-	 */
-	raw_spin_lock_irqsave(&tty_ldisc_lock, flags);
-	if (atomic_dec_and_test(&ld->users)) {
-		struct tty_ldisc_ops *ldo = ld->ops;
-
-		ldo->refcount--;
-		module_put(ldo->owner);
-		raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags);
-
-		kfree(ld);
-		return;
-	}
-	raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags);
-
-	if (waitqueue_active(&ld->wq_idle))
-		wake_up(&ld->wq_idle);
-}
-
 /**
  *	tty_register_ldisc	-	install a line discipline
  *	@disc: ldisc number
@@ -206,6 +179,29 @@ static struct tty_ldisc *tty_ldisc_get(int disc)
 	return ld;
 }
 
+/**
+ *	tty_ldisc_put		-	release the ldisc
+ *
+ *	Complement of tty_ldisc_get().
+ */
+static inline void tty_ldisc_put(struct tty_ldisc *ld)
+{
+	unsigned long flags;
+
+	if (WARN_ON_ONCE(!ld))
+		return;
+
+	raw_spin_lock_irqsave(&tty_ldisc_lock, flags);
+
+	/* unreleased reader reference(s) will cause this WARN */
+	WARN_ON(!atomic_dec_and_test(&ld->users));
+
+	ld->ops->refcount--;
+	module_put(ld->ops->owner);
+	kfree(ld);
+	raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+}
+
 static void *tty_ldiscs_seq_start(struct seq_file *m, loff_t *pos)
 {
 	return (*pos < NR_LDISCS) ? pos : NULL;
@@ -255,24 +251,6 @@ const struct file_operations tty_ldiscs_proc_fops = {
 };
 
 /**
- *	tty_ldisc_assign	-	set ldisc on a tty
- *	@tty: tty to assign
- *	@ld: line discipline
- *
- *	Install an instance of a line discipline into a tty structure. The
- *	ldisc must have a reference count above zero to ensure it remains.
- *	The tty instance refcount starts at zero.
- *
- *	Locking:
- *		Caller must hold references
- */
-
-static void tty_ldisc_assign(struct tty_struct *tty, struct tty_ldisc *ld)
-{
-	tty->ldisc = ld;
-}
-
-/**
  *	tty_ldisc_try		-	internal helper
  *	@tty: the tty
  *
@@ -289,10 +267,13 @@ static struct tty_ldisc *tty_ldisc_try(struct tty_struct *tty)
 	unsigned long flags;
 	struct tty_ldisc *ld;
 
+	/* FIXME: this allows reference acquire after TTY_LDISC is cleared */
 	raw_spin_lock_irqsave(&tty_ldisc_lock, flags);
 	ld = NULL;
-	if (test_bit(TTY_LDISC, &tty->flags))
-		ld = get_ldisc(tty->ldisc);
+	if (test_bit(TTY_LDISC, &tty->flags) && tty->ldisc) {
+		ld = tty->ldisc;
+		atomic_inc(&ld->users);
+	}
 	raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags);
 	return ld;
 }
@@ -352,14 +333,23 @@ EXPORT_SYMBOL_GPL(tty_ldisc_ref);
 
 void tty_ldisc_deref(struct tty_ldisc *ld)
 {
-	put_ldisc(ld);
-}
-EXPORT_SYMBOL_GPL(tty_ldisc_deref);
+	unsigned long flags;
 
-static inline void tty_ldisc_put(struct tty_ldisc *ld)
-{
-	put_ldisc(ld);
+	if (WARN_ON_ONCE(!ld))
+		return;
+
+	raw_spin_lock_irqsave(&tty_ldisc_lock, flags);
+	/*
+	 * WARNs if one-too-many reader references were released
+	 * - the last reference must be released with tty_ldisc_put
+	 */
+	WARN_ON(atomic_dec_and_test(&ld->users));
+	raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+
+	if (waitqueue_active(&ld->wq_idle))
+		wake_up(&ld->wq_idle);
 }
+EXPORT_SYMBOL_GPL(tty_ldisc_deref);
 
 /**
  *	tty_ldisc_enable	-	allow ldisc use
@@ -373,8 +363,9 @@ static inline void tty_ldisc_put(struct tty_ldisc *ld)
  *	Clearing directly is allowed.
  */
 
-void tty_ldisc_enable(struct tty_struct *tty)
+static void tty_ldisc_enable(struct tty_struct *tty)
 {
+	clear_bit(TTY_LDISC_HALTED, &tty->flags);
 	set_bit(TTY_LDISC, &tty->flags);
 	clear_bit(TTY_LDISC_CHANGING, &tty->flags);
 	wake_up(&tty_ldisc_wait);
@@ -479,7 +470,7 @@ static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old)
 	/* There is an outstanding reference here so this is safe */
 	old = tty_ldisc_get(old->ops->num);
 	WARN_ON(IS_ERR(old));
-	tty_ldisc_assign(tty, old);
+	tty->ldisc = old;
 	tty_set_termios_ldisc(tty, old->ops->num);
 	if (tty_ldisc_open(tty, old) < 0) {
 		tty_ldisc_put(old);
@@ -487,7 +478,7 @@ static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old)
 		new_ldisc = tty_ldisc_get(N_TTY);
 		if (IS_ERR(new_ldisc))
 			panic("n_tty: get");
-		tty_ldisc_assign(tty, new_ldisc);
+		tty->ldisc = new_ldisc;
 		tty_set_termios_ldisc(tty, N_TTY);
 		r = tty_ldisc_open(tty, new_ldisc);
 		if (r < 0)
@@ -498,52 +489,98 @@ static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old)
 }
 
 /**
+ *	tty_ldisc_wait_idle	-	wait for the ldisc to become idle
+ *	@tty: tty to wait for
+ *	@timeout: for how long to wait at most
+ *
+ *	Wait for the line discipline to become idle. The discipline must
+ *	have been halted for this to guarantee it remains idle.
+ */
+static int tty_ldisc_wait_idle(struct tty_struct *tty, long timeout)
+{
+	long ret;
+	ret = wait_event_timeout(tty->ldisc->wq_idle,
+			atomic_read(&tty->ldisc->users) == 1, timeout);
+	return ret > 0 ? 0 : -EBUSY;
+}
+
+/**
  *	tty_ldisc_halt		-	shut down the line discipline
  *	@tty: tty device
+ *	@o_tty: paired pty device (can be NULL)
+ *	@timeout: # of jiffies to wait for ldisc refs to be released
  *
- *	Shut down the line discipline and work queue for this tty device.
- *	The TTY_LDISC flag being cleared ensures no further references can
- *	be obtained while the delayed work queue halt ensures that no more
- *	data is fed to the ldisc.
+ *	Shut down the line discipline and work queue for this tty device and
+ *	its paired pty (if exists). Clearing the TTY_LDISC flag ensures
+ *	no further references can be obtained, while waiting for existing
+ *	references to be released ensures no more data is fed to the ldisc.
  *
  *	You need to do a 'flush_scheduled_work()' (outside the ldisc_mutex)
  *	in order to make sure any currently executing ldisc work is also
  *	flushed.
  */
 
-static int tty_ldisc_halt(struct tty_struct *tty)
+static int tty_ldisc_halt(struct tty_struct *tty, struct tty_struct *o_tty,
+			  long timeout)
 {
+	int retval;
+
 	clear_bit(TTY_LDISC, &tty->flags);
-	return cancel_work_sync(&tty->port->buf.work);
-}
+	if (o_tty)
+		clear_bit(TTY_LDISC, &o_tty->flags);
 
-/**
- *	tty_ldisc_flush_works	-	flush all works of a tty
- *	@tty: tty device to flush works for
- *
- *	Sync flush all works belonging to @tty.
- */
-static void tty_ldisc_flush_works(struct tty_struct *tty)
-{
-	flush_work(&tty->hangup_work);
-	flush_work(&tty->SAK_work);
-	flush_work(&tty->port->buf.work);
+	retval = tty_ldisc_wait_idle(tty, timeout);
+	if (!retval && o_tty)
+		retval = tty_ldisc_wait_idle(o_tty, timeout);
+	if (retval)
+		return retval;
+
+	set_bit(TTY_LDISC_HALTED, &tty->flags);
+	if (o_tty)
+		set_bit(TTY_LDISC_HALTED, &o_tty->flags);
+
+	return 0;
 }
 
 /**
- *	tty_ldisc_wait_idle	-	wait for the ldisc to become idle
- *	@tty: tty to wait for
- *	@timeout: for how long to wait at most
+ *	tty_ldisc_hangup_halt - halt the line discipline for hangup
+ *	@tty: tty being hung up
  *
- *	Wait for the line discipline to become idle. The discipline must
- *	have been halted for this to guarantee it remains idle.
+ *	Shut down the line discipline and work queue for the tty device
+ *	being hungup. Clear the TTY_LDISC flag to ensure no further
+ *	references can be obtained and wait for remaining references to be
+ *	released to ensure no more data is fed to this ldisc.
+ *	Caller must hold legacy and ->ldisc_mutex.
+ *
+ *	NB: tty_set_ldisc() is prevented from changing the ldisc concurrently
+ *	with this function by checking the TTY_HUPPING flag.
  */
-static int tty_ldisc_wait_idle(struct tty_struct *tty, long timeout)
+static bool tty_ldisc_hangup_halt(struct tty_struct *tty)
 {
-	long ret;
-	ret = wait_event_timeout(tty->ldisc->wq_idle,
-			atomic_read(&tty->ldisc->users) == 1, timeout);
-	return ret > 0 ? 0 : -EBUSY;
+	char cur_n[TASK_COMM_LEN], tty_n[64];
+	long timeout = 3 * HZ;
+
+	clear_bit(TTY_LDISC, &tty->flags);
+
+	if (tty->ldisc) {	/* Not yet closed */
+		tty_unlock(tty);
+
+		while (tty_ldisc_wait_idle(tty, timeout) == -EBUSY) {
+			timeout = MAX_SCHEDULE_TIMEOUT;
+			printk_ratelimited(KERN_WARNING
+				"%s: waiting (%s) for %s took too long, but we keep waiting...\n",
+				__func__, get_task_comm(cur_n, current),
+				tty_name(tty, tty_n));
+		}
+
+		set_bit(TTY_LDISC_HALTED, &tty->flags);
+
+		/* must reacquire both locks and preserve lock order */
+		mutex_unlock(&tty->ldisc_mutex);
+		tty_lock(tty);
+		mutex_lock(&tty->ldisc_mutex);
+	}
+	return !!tty->ldisc;
 }
 
 /**
@@ -563,7 +600,6 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
 {
 	int retval;
 	struct tty_ldisc *o_ldisc, *new_ldisc;
-	int work, o_work = 0;
 	struct tty_struct *o_tty;
 
 	new_ldisc = tty_ldisc_get(ldisc);
@@ -589,15 +625,6 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
 		return 0;
 	}
 
-	tty_unlock(tty);
-	/*
-	 *	Problem: What do we do if this blocks ?
-	 *	We could deadlock here
-	 */
-
-	tty_wait_until_sent(tty, 0);
-
-	tty_lock(tty);
 	mutex_lock(&tty->ldisc_mutex);
 
 	/*
@@ -637,20 +664,16 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
 	 *	parallel to the change and re-referencing the tty.
 	 */
 
-	work = tty_ldisc_halt(tty);
-	if (o_tty)
-		o_work = tty_ldisc_halt(o_tty);
+	retval = tty_ldisc_halt(tty, o_tty, 5 * HZ);
 
 	/*
-	 * Wait for ->hangup_work and ->buf.work handlers to terminate.
+	 * Wait for hangup to complete, if pending.
 	 * We must drop the mutex here in case a hangup is also in process.
 	 */
 
 	mutex_unlock(&tty->ldisc_mutex);
 
-	tty_ldisc_flush_works(tty);
-
-	retval = tty_ldisc_wait_idle(tty, 5 * HZ);
+	flush_work(&tty->hangup_work);
 
 	tty_lock(tty);
 	mutex_lock(&tty->ldisc_mutex);
@@ -675,7 +698,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
 	tty_ldisc_close(tty, o_ldisc);
 
 	/* Now set up the new line discipline. */
-	tty_ldisc_assign(tty, new_ldisc);
+	tty->ldisc = new_ldisc;
 	tty_set_termios_ldisc(tty, ldisc);
 
 	retval = tty_ldisc_open(tty, new_ldisc);
@@ -705,10 +728,10 @@ enable:
 
 	/* Restart the work queue in case no characters kick it off. Safe if
 	   already running */
-	if (work)
-		schedule_work(&tty->port->buf.work);
-	if (o_work)
+	schedule_work(&tty->port->buf.work);
+	if (o_tty)
 		schedule_work(&o_tty->port->buf.work);
+
 	mutex_unlock(&tty->ldisc_mutex);
 	tty_unlock(tty);
 	return retval;
@@ -749,11 +772,10 @@ static int tty_ldisc_reinit(struct tty_struct *tty, int ldisc)
 
 	tty_ldisc_close(tty, tty->ldisc);
 	tty_ldisc_put(tty->ldisc);
-	tty->ldisc = NULL;
 	/*
 	 *	Switch the line discipline back
 	 */
-	tty_ldisc_assign(tty, ld);
+	tty->ldisc = ld;
 	tty_set_termios_ldisc(tty, ldisc);
 
 	return 0;
@@ -780,6 +802,8 @@ void tty_ldisc_hangup(struct tty_struct *tty)
 	int reset = tty->driver->flags & TTY_DRIVER_RESET_TERMIOS;
 	int err = 0;
 
+	tty_ldisc_debug(tty, "closing ldisc: %p\n", tty->ldisc);
+
 	/*
 	 * FIXME! What are the locking issues here? This may me overdoing
 	 * things... This question is especially important now that we've
@@ -812,40 +836,12 @@ void tty_ldisc_hangup(struct tty_struct *tty)
 	 */
 	mutex_lock(&tty->ldisc_mutex);
 
-	/*
-	 * this is like tty_ldisc_halt, but we need to give up
-	 * the BTM before calling cancel_work_sync, which may
-	 * need to wait for another function taking the BTM
-	 */
-	clear_bit(TTY_LDISC, &tty->flags);
-	tty_unlock(tty);
-	cancel_work_sync(&tty->port->buf.work);
-	mutex_unlock(&tty->ldisc_mutex);
-retry:
-	tty_lock(tty);
-	mutex_lock(&tty->ldisc_mutex);
-
-	/* At this point we have a closed ldisc and we want to
-	   reopen it. We could defer this to the next open but
-	   it means auditing a lot of other paths so this is
-	   a FIXME */
-	if (tty->ldisc) {	/* Not yet closed */
-		if (atomic_read(&tty->ldisc->users) != 1) {
-			char cur_n[TASK_COMM_LEN], tty_n[64];
-			long timeout = 3 * HZ;
-			tty_unlock(tty);
-
-			while (tty_ldisc_wait_idle(tty, timeout) == -EBUSY) {
-				timeout = MAX_SCHEDULE_TIMEOUT;
-				printk_ratelimited(KERN_WARNING
-					"%s: waiting (%s) for %s took too long, but we keep waiting...\n",
-					__func__, get_task_comm(cur_n, current),
-					tty_name(tty, tty_n));
-			}
-			mutex_unlock(&tty->ldisc_mutex);
-			goto retry;
-		}
+	if (tty_ldisc_hangup_halt(tty)) {
 
+		/* At this point we have a halted ldisc; we want to close it and
+		   reopen a new ldisc. We could defer the reopen to the next
+		   open but it means auditing a lot of other paths so this is
+		   a FIXME */
 		if (reset == 0) {
 
 			if (!tty_ldisc_reinit(tty, tty->termios.c_line))
@@ -864,6 +860,8 @@ retry:
 	mutex_unlock(&tty->ldisc_mutex);
 	if (reset)
 		tty_reset_termios(tty);
+
+	tty_ldisc_debug(tty, "re-opened ldisc: %p\n", tty->ldisc);
 }
 
 /**
@@ -899,11 +897,6 @@ int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty)
 
 static void tty_ldisc_kill(struct tty_struct *tty)
 {
-	/* There cannot be users from userspace now. But there still might be
-	 * drivers holding a reference via tty_ldisc_ref. Do not steal them the
-	 * ldisc until they are done. */
-	tty_ldisc_wait_idle(tty, MAX_SCHEDULE_TIMEOUT);
-
 	mutex_lock(&tty->ldisc_mutex);
 	/*
 	 * Now kill off the ldisc
@@ -931,18 +924,13 @@ static void tty_ldisc_kill(struct tty_struct *tty)
 void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty)
 {
 	/*
-	 * Prevent flush_to_ldisc() from rescheduling the work for later.  Then
-	 * kill any delayed work. As this is the final close it does not
-	 * race with the set_ldisc code path.
+	 * Shutdown this line discipline. As this is the final close,
+	 * it does not race with the set_ldisc code path.
 	 */
 
-	tty_ldisc_halt(tty);
-	if (o_tty)
-		tty_ldisc_halt(o_tty);
+	tty_ldisc_debug(tty, "closing ldisc: %p\n", tty->ldisc);
 
-	tty_ldisc_flush_works(tty);
-	if (o_tty)
-		tty_ldisc_flush_works(o_tty);
+	tty_ldisc_halt(tty, o_tty, MAX_SCHEDULE_TIMEOUT);
 
 	tty_lock_pair(tty, o_tty);
 	/* This will need doing differently if we need to lock */
@@ -953,6 +941,8 @@ void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty)
 	tty_unlock_pair(tty, o_tty);
 	/* And the memory resources remaining (buffers, termios) will be
 	   disposed of when the kref hits zero */
+
+	tty_ldisc_debug(tty, "ldisc closed\n");
 }
 
 /**
@@ -968,7 +958,7 @@ void tty_ldisc_init(struct tty_struct *tty)
 	struct tty_ldisc *ld = tty_ldisc_get(N_TTY);
 	if (IS_ERR(ld))
 		panic("n_tty: init_tty");
-	tty_ldisc_assign(tty, ld);
+	tty->ldisc = ld;
 }
 
 /**
@@ -980,8 +970,8 @@ void tty_ldisc_init(struct tty_struct *tty)
  */
 void tty_ldisc_deinit(struct tty_struct *tty)
 {
-	put_ldisc(tty->ldisc);
-	tty_ldisc_assign(tty, NULL);
+	tty_ldisc_put(tty->ldisc);
+	tty->ldisc = NULL;
 }
 
 void tty_ldisc_begin(void)
diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c
index b7ff59d..121aeb9 100644
--- a/drivers/tty/tty_port.c
+++ b/drivers/tty/tty_port.c
@@ -132,6 +132,7 @@ EXPORT_SYMBOL(tty_port_free_xmit_buf);
  */
 void tty_port_destroy(struct tty_port *port)
 {
+	cancel_work_sync(&port->buf.work);
 	tty_buffer_free_all(port);
 }
 EXPORT_SYMBOL(tty_port_destroy);
@@ -196,12 +197,24 @@ void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty)
 }
 EXPORT_SYMBOL(tty_port_tty_set);
 
-static void tty_port_shutdown(struct tty_port *port)
+static void tty_port_shutdown(struct tty_port *port, struct tty_struct *tty)
 {
 	mutex_lock(&port->mutex);
-	if (port->ops->shutdown && !port->console &&
-		test_and_clear_bit(ASYNCB_INITIALIZED, &port->flags))
+	if (port->console)
+		goto out;
+
+	if (test_and_clear_bit(ASYNCB_INITIALIZED, &port->flags)) {
+		/*
+		 * Drop DTR/RTS if HUPCL is set. This causes any attached
+		 * modem to hang up the line.
+		 */
+		if (tty && C_HUPCL(tty))
+			tty_port_lower_dtr_rts(port);
+
+		if (port->ops->shutdown)
 			port->ops->shutdown(port);
+	}
+out:
 	mutex_unlock(&port->mutex);
 }
 
@@ -215,24 +228,58 @@ static void tty_port_shutdown(struct tty_port *port)
 
 void tty_port_hangup(struct tty_port *port)
 {
+	struct tty_struct *tty;
 	unsigned long flags;
 
 	spin_lock_irqsave(&port->lock, flags);
 	port->count = 0;
 	port->flags &= ~ASYNC_NORMAL_ACTIVE;
-	if (port->tty) {
-		set_bit(TTY_IO_ERROR, &port->tty->flags);
-		tty_kref_put(port->tty);
-	}
+	tty = port->tty;
+	if (tty)
+		set_bit(TTY_IO_ERROR, &tty->flags);
 	port->tty = NULL;
 	spin_unlock_irqrestore(&port->lock, flags);
+	tty_port_shutdown(port, tty);
+	tty_kref_put(tty);
 	wake_up_interruptible(&port->open_wait);
 	wake_up_interruptible(&port->delta_msr_wait);
-	tty_port_shutdown(port);
 }
 EXPORT_SYMBOL(tty_port_hangup);
 
 /**
+ * tty_port_tty_hangup - helper to hang up a tty
+ *
+ * @port: tty port
+ * @check_clocal: hang only ttys with CLOCAL unset?
+ */
+void tty_port_tty_hangup(struct tty_port *port, bool check_clocal)
+{
+	struct tty_struct *tty = tty_port_tty_get(port);
+
+	if (tty && (!check_clocal || !C_CLOCAL(tty))) {
+		tty_hangup(tty);
+		tty_kref_put(tty);
+	}
+}
+EXPORT_SYMBOL_GPL(tty_port_tty_hangup);
+
+/**
+ * tty_port_tty_wakeup - helper to wake up a tty
+ *
+ * @port: tty port
+ */
+void tty_port_tty_wakeup(struct tty_port *port)
+{
+	struct tty_struct *tty = tty_port_tty_get(port);
+
+	if (tty) {
+		tty_wakeup(tty);
+		tty_kref_put(tty);
+	}
+}
+EXPORT_SYMBOL_GPL(tty_port_tty_wakeup);
+
+/**
  *	tty_port_carrier_raised	-	carrier raised check
  *	@port: tty port
  *
@@ -350,7 +397,7 @@ int tty_port_block_til_ready(struct tty_port *port,
 
 	while (1) {
 		/* Indicate we are open */
-		if (tty->termios.c_cflag & CBAUD)
+		if (C_BAUD(tty) && test_bit(ASYNCB_INITIALIZED, &port->flags))
 			tty_port_raise_dtr_rts(port);
 
 		prepare_to_wait(&port->open_wait, &wait, TASK_INTERRUPTIBLE);
@@ -395,6 +442,20 @@ int tty_port_block_til_ready(struct tty_port *port,
 }
 EXPORT_SYMBOL(tty_port_block_til_ready);
 
+static void tty_port_drain_delay(struct tty_port *port, struct tty_struct *tty)
+{
+	unsigned int bps = tty_get_baud_rate(tty);
+	long timeout;
+
+	if (bps > 1200) {
+		timeout = (HZ * 10 * port->drain_delay) / bps;
+		timeout = max_t(long, timeout, HZ / 10);
+	} else {
+		timeout = 2 * HZ;
+	}
+	schedule_timeout_interruptible(timeout);
+}
+
 int tty_port_close_start(struct tty_port *port,
 				struct tty_struct *tty, struct file *filp)
 {
@@ -427,31 +488,19 @@ int tty_port_close_start(struct tty_port *port,
 	set_bit(ASYNCB_CLOSING, &port->flags);
 	tty->closing = 1;
 	spin_unlock_irqrestore(&port->lock, flags);
-	/* Don't block on a stalled port, just pull the chain */
-	if (tty->flow_stopped)
-		tty_driver_flush_buffer(tty);
-	if (test_bit(ASYNCB_INITIALIZED, &port->flags) &&
-			port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
-		tty_wait_until_sent_from_close(tty, port->closing_wait);
-	if (port->drain_delay) {
-		unsigned int bps = tty_get_baud_rate(tty);
-		long timeout;
-
-		if (bps > 1200)
-			timeout = max_t(long,
-				(HZ * 10 * port->drain_delay) / bps, HZ / 10);
-		else
-			timeout = 2 * HZ;
-		schedule_timeout_interruptible(timeout);
+
+	if (test_bit(ASYNCB_INITIALIZED, &port->flags)) {
+		/* Don't block on a stalled port, just pull the chain */
+		if (tty->flow_stopped)
+			tty_driver_flush_buffer(tty);
+		if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
+			tty_wait_until_sent_from_close(tty, port->closing_wait);
+		if (port->drain_delay)
+			tty_port_drain_delay(port, tty);
 	}
 	/* Flush the ldisc buffering */
 	tty_ldisc_flush(tty);
 
-	/* Drop DTR/RTS if HUPCL is set. This causes any attached modem to
-	   hang up the line */
-	if (tty->termios.c_cflag & HUPCL)
-		tty_port_lower_dtr_rts(port);
-
 	/* Don't call port->drop for the last reference. Callers will want
 	   to drop the last active reference in ->shutdown() or the tty
 	   shutdown path */
@@ -486,7 +535,7 @@ void tty_port_close(struct tty_port *port, struct tty_struct *tty,
 {
 	if (tty_port_close_start(port, tty, filp) == 0)
 		return;
-	tty_port_shutdown(port);
+	tty_port_shutdown(port, tty);
 	set_bit(TTY_IO_ERROR, &tty->flags);
 	tty_port_close_end(port, tty);
 	tty_port_tty_set(port, NULL);
diff --git a/drivers/tty/vt/consolemap.c b/drivers/tty/vt/consolemap.c
index 248381b..2978ca5 100644
--- a/drivers/tty/vt/consolemap.c
+++ b/drivers/tty/vt/consolemap.c
@@ -194,8 +194,7 @@ static void set_inverse_transl(struct vc_data *conp, struct uni_pagedir *p, int
 	q = p->inverse_translations[i];
 
 	if (!q) {
-		q = p->inverse_translations[i] = (unsigned char *) 
-			kmalloc(MAX_GLYPH, GFP_KERNEL);
+		q = p->inverse_translations[i] = kmalloc(MAX_GLYPH, GFP_KERNEL);
 		if (!q) return;
 	}
 	memset(q, 0, MAX_GLYPH);
diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c
index c8b9262..b645c47 100644
--- a/drivers/uio/uio.c
+++ b/drivers/uio/uio.c
@@ -374,6 +374,7 @@ static int uio_get_minor(struct uio_device *idev)
 	retval = idr_alloc(&uio_idr, idev, 0, UIO_MAX_DEVICES, GFP_KERNEL);
 	if (retval >= 0) {
 		idev->minor = retval;
+		retval = 0;
 	} else if (retval == -ENOSPC) {
 		dev_err(idev->dev, "too many uio devices\n");
 		retval = -EINVAL;
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index 640ae6c..2c481b8 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -186,6 +186,4 @@ source "drivers/usb/atm/Kconfig"
 
 source "drivers/usb/gadget/Kconfig"
 
-source "drivers/usb/otg/Kconfig"
-
 endif # USB_SUPPORT
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
index 8f5ebce..c41feba 100644
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -6,8 +6,6 @@
 
 obj-$(CONFIG_USB)		+= core/
 
-obj-$(CONFIG_USB_OTG_UTILS)	+= otg/
-
 obj-$(CONFIG_USB_DWC3)		+= dwc3/
 
 obj-$(CONFIG_USB_MON)		+= mon/
@@ -46,7 +44,7 @@ obj-$(CONFIG_USB_MICROTEK)	+= image/
 obj-$(CONFIG_USB_SERIAL)	+= serial/
 
 obj-$(CONFIG_USB)		+= misc/
-obj-$(CONFIG_USB_OTG_UTILS)	+= phy/
+obj-$(CONFIG_USB_PHY)		+= phy/
 obj-$(CONFIG_EARLY_PRINTK_DBGP)	+= early/
 
 obj-$(CONFIG_USB_ATM)		+= atm/
diff --git a/drivers/usb/chipidea/Makefile b/drivers/usb/chipidea/Makefile
index d92ca32..4ab83e9 100644
--- a/drivers/usb/chipidea/Makefile
+++ b/drivers/usb/chipidea/Makefile
@@ -17,5 +17,5 @@ ifneq ($(CONFIG_PCI),)
 endif
 
 ifneq ($(CONFIG_OF_DEVICE),)
-	obj-$(CONFIG_USB_CHIPIDEA)	+= ci13xxx_imx.o usbmisc_imx6q.o
+	obj-$(CONFIG_USB_CHIPIDEA)	+= ci13xxx_imx.o usbmisc_imx.o
 endif
diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h
index e25d126..b0a6bce 100644
--- a/drivers/usb/chipidea/ci.h
+++ b/drivers/usb/chipidea/ci.h
@@ -21,6 +21,7 @@
 /******************************************************************************
  * DEFINE
  *****************************************************************************/
+#define TD_PAGE_COUNT      5
 #define CI13XXX_PAGE_SIZE  4096ul /* page size for TD's */
 #define ENDPT_MAX          32
 
@@ -129,6 +130,7 @@ struct hw_bank {
  * @vbus_active: is VBUS active
  * @transceiver: pointer to USB PHY, if any
  * @hcd: pointer to usb_hcd for ehci host driver
+ * @debugfs: root dentry for this controller in debugfs
  */
 struct ci13xxx {
 	struct device			*dev;
@@ -139,7 +141,6 @@ struct ci13xxx {
 	enum ci_role			role;
 	bool				is_otg;
 	struct work_struct		work;
-	struct work_struct		vbus_work;
 	struct workqueue_struct		*wq;
 
 	struct dma_pool			*qh_pool;
@@ -165,6 +166,7 @@ struct ci13xxx {
 	bool				global_phy;
 	struct usb_phy			*transceiver;
 	struct usb_hcd			*hcd;
+	struct dentry			*debugfs;
 };
 
 static inline struct ci_role_driver *ci_role(struct ci13xxx *ci)
@@ -234,19 +236,6 @@ enum ci13xxx_regs {
 };
 
 /**
- * ffs_nr: find first (least significant) bit set
- * @x: the word to search
- *
- * This function returns bit number (instead of position)
- */
-static inline int ffs_nr(u32 x)
-{
-	int n = ffs(x);
-
-	return n ? n-1 : 32;
-}
-
-/**
  * hw_read: reads from a hw register
  * @reg:  register index
  * @mask: bitfield mask
@@ -304,7 +293,7 @@ static inline u32 hw_test_and_write(struct ci13xxx *ci, enum ci13xxx_regs reg,
 	u32 val = hw_read(ci, reg, ~0);
 
 	hw_write(ci, reg, mask, data);
-	return (val & mask) >> ffs_nr(mask);
+	return (val & mask) >> __ffs(mask);
 }
 
 int hw_device_reset(struct ci13xxx *ci, u32 mode);
diff --git a/drivers/usb/chipidea/ci13xxx_imx.c b/drivers/usb/chipidea/ci13xxx_imx.c
index 8c29122..8faec9d 100644
--- a/drivers/usb/chipidea/ci13xxx_imx.c
+++ b/drivers/usb/chipidea/ci13xxx_imx.c
@@ -79,6 +79,9 @@ int usbmisc_get_init_data(struct device *dev, struct usbmisc_usb_device *usbdev)
 	if (of_find_property(np, "disable-over-current", NULL))
 		usbdev->disable_oc = 1;
 
+	if (of_find_property(np, "external-vbus-divider", NULL))
+		usbdev->evdo = 1;
+
 	return 0;
 }
 EXPORT_SYMBOL_GPL(usbmisc_get_init_data);
@@ -202,6 +205,15 @@ static int ci13xxx_imx_probe(struct platform_device *pdev)
 		goto err;
 	}
 
+	if (usbmisc_ops && usbmisc_ops->post) {
+		ret = usbmisc_ops->post(&pdev->dev);
+		if (ret) {
+			dev_err(&pdev->dev,
+				"usbmisc post failed, ret=%d\n", ret);
+			goto put_np;
+		}
+	}
+
 	data->ci_pdev = plat_ci;
 	platform_set_drvdata(pdev, data);
 
diff --git a/drivers/usb/chipidea/ci13xxx_imx.h b/drivers/usb/chipidea/ci13xxx_imx.h
index 9cd2e91..550bfa4 100644
--- a/drivers/usb/chipidea/ci13xxx_imx.h
+++ b/drivers/usb/chipidea/ci13xxx_imx.h
@@ -13,6 +13,8 @@
 struct usbmisc_ops {
 	/* It's called once when probe a usb device */
 	int (*init)(struct device *dev);
+	/* It's called once after adding a usb device */
+	int (*post)(struct device *dev);
 };
 
 struct usbmisc_usb_device {
@@ -20,6 +22,7 @@ struct usbmisc_usb_device {
 	int index;
 
 	unsigned int disable_oc:1; /* over current detect disabled */
+	unsigned int evdo:1; /* set external vbus divider option */
 };
 
 int usbmisc_set_ops(const struct usbmisc_ops *ops);
diff --git a/drivers/usb/chipidea/ci13xxx_pci.c b/drivers/usb/chipidea/ci13xxx_pci.c
index 9b227e3..4e1fc61 100644
--- a/drivers/usb/chipidea/ci13xxx_pci.c
+++ b/drivers/usb/chipidea/ci13xxx_pci.c
@@ -23,17 +23,17 @@
 /******************************************************************************
  * PCI block
  *****************************************************************************/
-struct ci13xxx_platform_data pci_platdata = {
+static struct ci13xxx_platform_data pci_platdata = {
 	.name		= UDC_DRIVER_NAME,
 	.capoffset	= DEF_CAPOFFSET,
 };
 
-struct ci13xxx_platform_data langwell_pci_platdata = {
+static struct ci13xxx_platform_data langwell_pci_platdata = {
 	.name		= UDC_DRIVER_NAME,
 	.capoffset	= 0,
 };
 
-struct ci13xxx_platform_data penwell_pci_platdata = {
+static struct ci13xxx_platform_data penwell_pci_platdata = {
 	.name		= UDC_DRIVER_NAME,
 	.capoffset	= 0,
 	.power_budget	= 200,
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
index 57cae1f..450107e 100644
--- a/drivers/usb/chipidea/core.c
+++ b/drivers/usb/chipidea/core.c
@@ -51,15 +51,12 @@
  */
 #include <linux/delay.h>
 #include <linux/device.h>
-#include <linux/dmapool.h>
 #include <linux/dma-mapping.h>
-#include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/module.h>
 #include <linux/idr.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
-#include <linux/irq.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/pm_runtime.h>
@@ -158,7 +155,7 @@ int hw_port_test_set(struct ci13xxx *ci, u8 mode)
 	if (mode > TEST_MODE_MAX)
 		return -EINVAL;
 
-	hw_write(ci, OP_PORTSC, PORTSC_PTC, mode << ffs_nr(PORTSC_PTC));
+	hw_write(ci, OP_PORTSC, PORTSC_PTC, mode << __ffs(PORTSC_PTC));
 	return 0;
 }
 
@@ -169,7 +166,7 @@ int hw_port_test_set(struct ci13xxx *ci, u8 mode)
  */
 u8 hw_port_test_get(struct ci13xxx *ci)
 {
-	return hw_read(ci, OP_PORTSC, PORTSC_PTC) >> ffs_nr(PORTSC_PTC);
+	return hw_read(ci, OP_PORTSC, PORTSC_PTC) >> __ffs(PORTSC_PTC);
 }
 
 static int hw_device_init(struct ci13xxx *ci, void __iomem *base)
@@ -181,11 +178,11 @@ static int hw_device_init(struct ci13xxx *ci, void __iomem *base)
 
 	ci->hw_bank.cap = ci->hw_bank.abs;
 	ci->hw_bank.cap += ci->platdata->capoffset;
-	ci->hw_bank.op = ci->hw_bank.cap + ioread8(ci->hw_bank.cap);
+	ci->hw_bank.op = ci->hw_bank.cap + (ioread32(ci->hw_bank.cap) & 0xff);
 
 	hw_alloc_regmap(ci, false);
 	reg = hw_read(ci, CAP_HCCPARAMS, HCCPARAMS_LEN) >>
-		ffs_nr(HCCPARAMS_LEN);
+		__ffs(HCCPARAMS_LEN);
 	ci->hw_bank.lpm  = reg;
 	hw_alloc_regmap(ci, !!reg);
 	ci->hw_bank.size = ci->hw_bank.op - ci->hw_bank.abs;
@@ -193,7 +190,7 @@ static int hw_device_init(struct ci13xxx *ci, void __iomem *base)
 	ci->hw_bank.size /= sizeof(u32);
 
 	reg = hw_read(ci, CAP_DCCPARAMS, DCCPARAMS_DEN) >>
-		ffs_nr(DCCPARAMS_DEN);
+		__ffs(DCCPARAMS_DEN);
 	ci->hw_ep_max = reg * 2;   /* cache hw ENDPT_MAX */
 
 	if (ci->hw_ep_max > ENDPT_MAX)
@@ -283,38 +280,6 @@ static void ci_role_work(struct work_struct *work)
 	}
 }
 
-static ssize_t show_role(struct device *dev, struct device_attribute *attr,
-			 char *buf)
-{
-	struct ci13xxx *ci = dev_get_drvdata(dev);
-
-	return sprintf(buf, "%s\n", ci_role(ci)->name);
-}
-
-static ssize_t store_role(struct device *dev, struct device_attribute *attr,
-			  const char *buf, size_t count)
-{
-	struct ci13xxx *ci = dev_get_drvdata(dev);
-	enum ci_role role;
-	int ret;
-
-	for (role = CI_ROLE_HOST; role < CI_ROLE_END; role++)
-		if (ci->roles[role] && !strcmp(buf, ci->roles[role]->name))
-			break;
-
-	if (role == CI_ROLE_END || role == ci->role)
-		return -EINVAL;
-
-	ci_role_stop(ci);
-	ret = ci_role_start(ci, role);
-	if (ret)
-		return ret;
-
-	return count;
-}
-
-static DEVICE_ATTR(role, S_IRUSR | S_IWUSR, show_role, store_role);
-
 static irqreturn_t ci_irq(int irq, void *data)
 {
 	struct ci13xxx *ci = data;
@@ -410,11 +375,9 @@ static int ci_hdrc_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
-	base = devm_request_and_ioremap(dev, res);
-	if (!base) {
-		dev_err(dev, "can't request and ioremap resource\n");
-		return -ENOMEM;
-	}
+	base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
 
 	ci = devm_kzalloc(dev, sizeof(*ci), GFP_KERNEL);
 	if (!ci) {
@@ -489,17 +452,14 @@ static int ci_hdrc_probe(struct platform_device *pdev)
 	if (ret)
 		goto stop;
 
-	ret = device_create_file(dev, &dev_attr_role);
-	if (ret)
-		goto rm_attr;
-
 	if (ci->is_otg)
 		hw_write(ci, OP_OTGSC, OTGSC_IDIE, OTGSC_IDIE);
 
-	return ret;
+	ret = dbg_create_files(ci);
+	if (!ret)
+		return 0;
 
-rm_attr:
-	device_remove_file(dev, &dev_attr_role);
+	free_irq(ci->irq, ci);
 stop:
 	ci_role_stop(ci);
 rm_wq:
@@ -513,9 +473,9 @@ static int ci_hdrc_remove(struct platform_device *pdev)
 {
 	struct ci13xxx *ci = platform_get_drvdata(pdev);
 
+	dbg_remove_files(ci);
 	flush_workqueue(ci->wq);
 	destroy_workqueue(ci->wq);
-	device_remove_file(ci->dev, &dev_attr_role);
 	free_irq(ci->irq, ci);
 	ci_role_stop(ci);
 
diff --git a/drivers/usb/chipidea/debug.c b/drivers/usb/chipidea/debug.c
index a62c4a4..36a7063 100644
--- a/drivers/usb/chipidea/debug.c
+++ b/drivers/usb/chipidea/debug.c
@@ -1,590 +1,126 @@
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/dmapool.h>
-#include <linux/dma-mapping.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/irq.h>
 #include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/pm_runtime.h>
+#include <linux/device.h>
+#include <linux/types.h>
+#include <linux/spinlock.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/uaccess.h>
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
-#include <linux/usb/otg.h>
-#include <linux/usb/chipidea.h>
 
 #include "ci.h"
 #include "udc.h"
 #include "bits.h"
 #include "debug.h"
 
-/* Interrupt statistics */
-#define ISR_MASK   0x1F
-static struct isr_statistics {
-	u32 test;
-	u32 ui;
-	u32 uei;
-	u32 pci;
-	u32 uri;
-	u32 sli;
-	u32 none;
-	struct {
-		u32 cnt;
-		u32 buf[ISR_MASK+1];
-		u32 idx;
-	} hndl;
-} isr_statistics;
-
-void dbg_interrupt(u32 intmask)
-{
-	if (!intmask) {
-		isr_statistics.none++;
-		return;
-	}
-
-	isr_statistics.hndl.buf[isr_statistics.hndl.idx++] = intmask;
-	isr_statistics.hndl.idx &= ISR_MASK;
-	isr_statistics.hndl.cnt++;
-
-	if (USBi_URI & intmask)
-		isr_statistics.uri++;
-	if (USBi_PCI & intmask)
-		isr_statistics.pci++;
-	if (USBi_UEI & intmask)
-		isr_statistics.uei++;
-	if (USBi_UI  & intmask)
-		isr_statistics.ui++;
-	if (USBi_SLI & intmask)
-		isr_statistics.sli++;
-}
-
 /**
- * hw_register_read: reads all device registers (execute without interruption)
- * @buf:  destination buffer
- * @size: buffer size
- *
- * This function returns number of registers read
+ * ci_device_show: prints information about device capabilities and status
  */
-static size_t hw_register_read(struct ci13xxx *ci, u32 *buf, size_t size)
+static int ci_device_show(struct seq_file *s, void *data)
 {
-	unsigned i;
-
-	if (size > ci->hw_bank.size)
-		size = ci->hw_bank.size;
-
-	for (i = 0; i < size; i++)
-		buf[i] = hw_read(ci, i * sizeof(u32), ~0);
-
-	return size;
-}
-
-/**
- * hw_register_write: writes to register
- * @addr: register address
- * @data: register value
- *
- * This function returns an error code
- */
-static int hw_register_write(struct ci13xxx *ci, u16 addr, u32 data)
-{
-	/* align */
-	addr /= sizeof(u32);
-
-	if (addr >= ci->hw_bank.size)
-		return -EINVAL;
-
-	/* align */
-	addr *= sizeof(u32);
-
-	hw_write(ci, addr, ~0, data);
-	return 0;
-}
-
-/**
- * hw_intr_clear: disables interrupt & clears interrupt status (execute without
- *                interruption)
- * @n: interrupt bit
- *
- * This function returns an error code
- */
-static int hw_intr_clear(struct ci13xxx *ci, int n)
-{
-	if (n >= REG_BITS)
-		return -EINVAL;
-
-	hw_write(ci, OP_USBINTR, BIT(n), 0);
-	hw_write(ci, OP_USBSTS,  BIT(n), BIT(n));
-	return 0;
-}
-
-/**
- * hw_intr_force: enables interrupt & forces interrupt status (execute without
- *                interruption)
- * @n: interrupt bit
- *
- * This function returns an error code
- */
-static int hw_intr_force(struct ci13xxx *ci, int n)
-{
-	if (n >= REG_BITS)
-		return -EINVAL;
-
-	hw_write(ci, CAP_TESTMODE, TESTMODE_FORCE, TESTMODE_FORCE);
-	hw_write(ci, OP_USBINTR,  BIT(n), BIT(n));
-	hw_write(ci, OP_USBSTS,   BIT(n), BIT(n));
-	hw_write(ci, CAP_TESTMODE, TESTMODE_FORCE, 0);
-	return 0;
-}
-
-/**
- * show_device: prints information about device capabilities and status
- *
- * Check "device.h" for details
- */
-static ssize_t show_device(struct device *dev, struct device_attribute *attr,
-			   char *buf)
-{
-	struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
+	struct ci13xxx *ci = s->private;
 	struct usb_gadget *gadget = &ci->gadget;
-	int n = 0;
 
-	if (attr == NULL || buf == NULL) {
-		dev_err(ci->dev, "[%s] EINVAL\n", __func__);
+	seq_printf(s, "speed             = %d\n", gadget->speed);
+	seq_printf(s, "max_speed         = %d\n", gadget->max_speed);
+	seq_printf(s, "is_otg            = %d\n", gadget->is_otg);
+	seq_printf(s, "is_a_peripheral   = %d\n", gadget->is_a_peripheral);
+	seq_printf(s, "b_hnp_enable      = %d\n", gadget->b_hnp_enable);
+	seq_printf(s, "a_hnp_support     = %d\n", gadget->a_hnp_support);
+	seq_printf(s, "a_alt_hnp_support = %d\n", gadget->a_alt_hnp_support);
+	seq_printf(s, "name              = %s\n",
+		   (gadget->name ? gadget->name : ""));
+
+	if (!ci->driver)
 		return 0;
-	}
-
-	n += scnprintf(buf + n, PAGE_SIZE - n, "speed             = %d\n",
-		       gadget->speed);
-	n += scnprintf(buf + n, PAGE_SIZE - n, "max_speed         = %d\n",
-		       gadget->max_speed);
-	n += scnprintf(buf + n, PAGE_SIZE - n, "is_otg            = %d\n",
-		       gadget->is_otg);
-	n += scnprintf(buf + n, PAGE_SIZE - n, "is_a_peripheral   = %d\n",
-		       gadget->is_a_peripheral);
-	n += scnprintf(buf + n, PAGE_SIZE - n, "b_hnp_enable      = %d\n",
-		       gadget->b_hnp_enable);
-	n += scnprintf(buf + n, PAGE_SIZE - n, "a_hnp_support     = %d\n",
-		       gadget->a_hnp_support);
-	n += scnprintf(buf + n, PAGE_SIZE - n, "a_alt_hnp_support = %d\n",
-		       gadget->a_alt_hnp_support);
-	n += scnprintf(buf + n, PAGE_SIZE - n, "name              = %s\n",
-		       (gadget->name ? gadget->name : ""));
-
-	return n;
-}
-static DEVICE_ATTR(device, S_IRUSR, show_device, NULL);
-
-/**
- * show_driver: prints information about attached gadget (if any)
- *
- * Check "device.h" for details
- */
-static ssize_t show_driver(struct device *dev, struct device_attribute *attr,
-			   char *buf)
-{
-	struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
-	struct usb_gadget_driver *driver = ci->driver;
-	int n = 0;
-
-	if (attr == NULL || buf == NULL) {
-		dev_err(dev, "[%s] EINVAL\n", __func__);
-		return 0;
-	}
-
-	if (driver == NULL)
-		return scnprintf(buf, PAGE_SIZE,
-				 "There is no gadget attached!\n");
 
-	n += scnprintf(buf + n, PAGE_SIZE - n, "function  = %s\n",
-		       (driver->function ? driver->function : ""));
-	n += scnprintf(buf + n, PAGE_SIZE - n, "max speed = %d\n",
-		       driver->max_speed);
+	seq_printf(s, "gadget function   = %s\n",
+		       (ci->driver->function ? ci->driver->function : ""));
+	seq_printf(s, "gadget max speed  = %d\n", ci->driver->max_speed);
 
-	return n;
-}
-static DEVICE_ATTR(driver, S_IRUSR, show_driver, NULL);
-
-/* Maximum event message length */
-#define DBG_DATA_MSG   64UL
-
-/* Maximum event messages */
-#define DBG_DATA_MAX   128UL
-
-/* Event buffer descriptor */
-static struct {
-	char     (buf[DBG_DATA_MAX])[DBG_DATA_MSG];   /* buffer */
-	unsigned idx;   /* index */
-	unsigned tty;   /* print to console? */
-	rwlock_t lck;   /* lock */
-} dbg_data = {
-	.idx = 0,
-	.tty = 0,
-	.lck = __RW_LOCK_UNLOCKED(dbg_data.lck)
-};
-
-/**
- * dbg_dec: decrements debug event index
- * @idx: buffer index
- */
-static void dbg_dec(unsigned *idx)
-{
-	*idx = (*idx - 1) & (DBG_DATA_MAX-1);
-}
-
-/**
- * dbg_inc: increments debug event index
- * @idx: buffer index
- */
-static void dbg_inc(unsigned *idx)
-{
-	*idx = (*idx + 1) & (DBG_DATA_MAX-1);
-}
-
-/**
- * dbg_print:  prints the common part of the event
- * @addr:   endpoint address
- * @name:   event name
- * @status: status
- * @extra:  extra information
- */
-static void dbg_print(u8 addr, const char *name, int status, const char *extra)
-{
-	struct timeval tval;
-	unsigned int stamp;
-	unsigned long flags;
-
-	write_lock_irqsave(&dbg_data.lck, flags);
-
-	do_gettimeofday(&tval);
-	stamp = tval.tv_sec & 0xFFFF;	/* 2^32 = 4294967296. Limit to 4096s */
-	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",
-		  stamp, addr, name, status, extra);
-
-	dbg_inc(&dbg_data.idx);
-
-	write_unlock_irqrestore(&dbg_data.lck, flags);
-
-	if (dbg_data.tty != 0)
-		pr_notice("%04X\t? %02X %-7.7s %4i ?\t%s\n",
-			  stamp, addr, name, status, extra);
-}
-
-/**
- * dbg_done: prints a DONE event
- * @addr:   endpoint address
- * @td:     transfer descriptor
- * @status: status
- */
-void dbg_done(u8 addr, const u32 token, int status)
-{
-	char msg[DBG_DATA_MSG];
-
-	scnprintf(msg, sizeof(msg), "%d %02X",
-		  (int)(token & TD_TOTAL_BYTES) >> ffs_nr(TD_TOTAL_BYTES),
-		  (int)(token & TD_STATUS)      >> ffs_nr(TD_STATUS));
-	dbg_print(addr, "DONE", status, msg);
-}
-
-/**
- * dbg_event: prints a generic event
- * @addr:   endpoint address
- * @name:   event name
- * @status: status
- */
-void dbg_event(u8 addr, const char *name, int status)
-{
-	if (name != NULL)
-		dbg_print(addr, name, status, "");
-}
-
-/*
- * dbg_queue: prints a QUEUE event
- * @addr:   endpoint address
- * @req:    USB request
- * @status: status
- */
-void dbg_queue(u8 addr, const struct usb_request *req, int status)
-{
-	char msg[DBG_DATA_MSG];
-
-	if (req != NULL) {
-		scnprintf(msg, sizeof(msg),
-			  "%d %d", !req->no_interrupt, req->length);
-		dbg_print(addr, "QUEUE", status, msg);
-	}
-}
-
-/**
- * dbg_setup: prints a SETUP event
- * @addr: endpoint address
- * @req:  setup request
- */
-void dbg_setup(u8 addr, const struct usb_ctrlrequest *req)
-{
-	char msg[DBG_DATA_MSG];
-
-	if (req != NULL) {
-		scnprintf(msg, sizeof(msg),
-			  "%02X %02X %04X %04X %d", req->bRequestType,
-			  req->bRequest, le16_to_cpu(req->wValue),
-			  le16_to_cpu(req->wIndex), le16_to_cpu(req->wLength));
-		dbg_print(addr, "SETUP", 0, msg);
-	}
+	return 0;
 }
 
-/**
- * show_events: displays the event buffer
- *
- * Check "device.h" for details
- */
-static ssize_t show_events(struct device *dev, struct device_attribute *attr,
-			   char *buf)
+static int ci_device_open(struct inode *inode, struct file *file)
 {
-	unsigned long flags;
-	unsigned i, j, n = 0;
-
-	if (attr == NULL || buf == NULL) {
-		dev_err(dev->parent, "[%s] EINVAL\n", __func__);
-		return 0;
-	}
-
-	read_lock_irqsave(&dbg_data.lck, flags);
-
-	i = dbg_data.idx;
-	for (dbg_dec(&i); i != dbg_data.idx; dbg_dec(&i)) {
-		n += strlen(dbg_data.buf[i]);
-		if (n >= PAGE_SIZE) {
-			n -= strlen(dbg_data.buf[i]);
-			break;
-		}
-	}
-	for (j = 0, dbg_inc(&i); j < n; dbg_inc(&i))
-		j += scnprintf(buf + j, PAGE_SIZE - j,
-			       "%s", dbg_data.buf[i]);
-
-	read_unlock_irqrestore(&dbg_data.lck, flags);
-
-	return n;
+	return single_open(file, ci_device_show, inode->i_private);
 }
 
-/**
- * store_events: configure if events are going to be also printed to console
- *
- * Check "device.h" for details
- */
-static ssize_t store_events(struct device *dev, struct device_attribute *attr,
-			    const char *buf, size_t count)
-{
-	unsigned tty;
-
-	if (attr == NULL || buf == NULL) {
-		dev_err(dev, "[%s] EINVAL\n", __func__);
-		goto done;
-	}
-
-	if (sscanf(buf, "%u", &tty) != 1 || tty > 1) {
-		dev_err(dev, "<1|0>: enable|disable console log\n");
-		goto done;
-	}
-
-	dbg_data.tty = tty;
-	dev_info(dev, "tty = %u", dbg_data.tty);
-
- done:
-	return count;
-}
-static DEVICE_ATTR(events, S_IRUSR | S_IWUSR, show_events, store_events);
+static const struct file_operations ci_device_fops = {
+	.open		= ci_device_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
 
 /**
- * show_inters: interrupt status, enable status and historic
- *
- * Check "device.h" for details
+ * ci_port_test_show: reads port test mode
  */
-static ssize_t show_inters(struct device *dev, struct device_attribute *attr,
-			   char *buf)
+static int ci_port_test_show(struct seq_file *s, void *data)
 {
-	struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
+	struct ci13xxx *ci = s->private;
 	unsigned long flags;
-	u32 intr;
-	unsigned i, j, n = 0;
-
-	if (attr == NULL || buf == NULL) {
-		dev_err(ci->dev, "[%s] EINVAL\n", __func__);
-		return 0;
-	}
+	unsigned mode;
 
 	spin_lock_irqsave(&ci->lock, flags);
-
-	/*n += scnprintf(buf + n, PAGE_SIZE - n,
-		       "status = %08x\n", hw_read_intr_status(ci));
-	n += scnprintf(buf + n, PAGE_SIZE - n,
-	"enable = %08x\n", hw_read_intr_enable(ci));*/
-
-	n += scnprintf(buf + n, PAGE_SIZE - n, "*test = %d\n",
-		       isr_statistics.test);
-	n += scnprintf(buf + n, PAGE_SIZE - n, "? ui  = %d\n",
-		       isr_statistics.ui);
-	n += scnprintf(buf + n, PAGE_SIZE - n, "? uei = %d\n",
-		       isr_statistics.uei);
-	n += scnprintf(buf + n, PAGE_SIZE - n, "? pci = %d\n",
-		       isr_statistics.pci);
-	n += scnprintf(buf + n, PAGE_SIZE - n, "? uri = %d\n",
-		       isr_statistics.uri);
-	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);
-	n += scnprintf(buf + n, PAGE_SIZE - n, "*hndl = %d\n",
-		       isr_statistics.hndl.cnt);
-
-	for (i = isr_statistics.hndl.idx, j = 0; j <= ISR_MASK; j++, i++) {
-		i   &= ISR_MASK;
-		intr = isr_statistics.hndl.buf[i];
-
-		if (USBi_UI  & intr)
-			n += scnprintf(buf + n, PAGE_SIZE - n, "ui  ");
-		intr &= ~USBi_UI;
-		if (USBi_UEI & intr)
-			n += scnprintf(buf + n, PAGE_SIZE - n, "uei ");
-		intr &= ~USBi_UEI;
-		if (USBi_PCI & intr)
-			n += scnprintf(buf + n, PAGE_SIZE - n, "pci ");
-		intr &= ~USBi_PCI;
-		if (USBi_URI & intr)
-			n += scnprintf(buf + n, PAGE_SIZE - n, "uri ");
-		intr &= ~USBi_URI;
-		if (USBi_SLI & intr)
-			n += scnprintf(buf + n, PAGE_SIZE - n, "sli ");
-		intr &= ~USBi_SLI;
-		if (intr)
-			n += scnprintf(buf + n, PAGE_SIZE - n, "??? ");
-		if (isr_statistics.hndl.buf[i])
-			n += scnprintf(buf + n, PAGE_SIZE - n, "\n");
-	}
-
+	mode = hw_port_test_get(ci);
 	spin_unlock_irqrestore(&ci->lock, flags);
 
-	return n;
-}
-
-/**
- * store_inters: enable & force or disable an individual interrutps
- *                   (to be used for test purposes only)
- *
- * Check "device.h" for details
- */
-static ssize_t store_inters(struct device *dev, struct device_attribute *attr,
-			    const char *buf, size_t count)
-{
-	struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
-	unsigned long flags;
-	unsigned en, bit;
-
-	if (attr == NULL || buf == NULL) {
-		dev_err(ci->dev, "EINVAL\n");
-		goto done;
-	}
+	seq_printf(s, "mode = %u\n", mode);
 
-	if (sscanf(buf, "%u %u", &en, &bit) != 2 || en > 1) {
-		dev_err(ci->dev, "<1|0> <bit>: enable|disable interrupt\n");
-		goto done;
-	}
-
-	spin_lock_irqsave(&ci->lock, flags);
-	if (en) {
-		if (hw_intr_force(ci, bit))
-			dev_err(dev, "invalid bit number\n");
-		else
-			isr_statistics.test++;
-	} else {
-		if (hw_intr_clear(ci, bit))
-			dev_err(dev, "invalid bit number\n");
-	}
-	spin_unlock_irqrestore(&ci->lock, flags);
-
- done:
-	return count;
+	return 0;
 }
-static DEVICE_ATTR(inters, S_IRUSR | S_IWUSR, show_inters, store_inters);
 
 /**
- * show_port_test: reads port test mode
- *
- * Check "device.h" for details
+ * ci_port_test_write: writes port test mode
  */
-static ssize_t show_port_test(struct device *dev,
-			      struct device_attribute *attr, char *buf)
+static ssize_t ci_port_test_write(struct file *file, const char __user *ubuf,
+				  size_t count, loff_t *ppos)
 {
-	struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
+	struct seq_file *s = file->private_data;
+	struct ci13xxx *ci = s->private;
 	unsigned long flags;
 	unsigned mode;
+	char buf[32];
+	int ret;
 
-	if (attr == NULL || buf == NULL) {
-		dev_err(ci->dev, "EINVAL\n");
-		return 0;
-	}
+	if (copy_from_user(buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
+		return -EFAULT;
+
+	if (sscanf(buf, "%u", &mode) != 1)
+		return -EINVAL;
 
 	spin_lock_irqsave(&ci->lock, flags);
-	mode = hw_port_test_get(ci);
+	ret = hw_port_test_set(ci, mode);
 	spin_unlock_irqrestore(&ci->lock, flags);
 
-	return scnprintf(buf, PAGE_SIZE, "mode = %u\n", mode);
+	return ret ? ret : count;
 }
 
-/**
- * store_port_test: writes port test mode
- *
- * Check "device.h" for details
- */
-static ssize_t store_port_test(struct device *dev,
-			       struct device_attribute *attr,
-			       const char *buf, size_t count)
+static int ci_port_test_open(struct inode *inode, struct file *file)
 {
-	struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
-	unsigned long flags;
-	unsigned mode;
-
-	if (attr == NULL || buf == NULL) {
-		dev_err(ci->dev, "[%s] EINVAL\n", __func__);
-		goto done;
-	}
-
-	if (sscanf(buf, "%u", &mode) != 1) {
-		dev_err(ci->dev, "<mode>: set port test mode");
-		goto done;
-	}
-
-	spin_lock_irqsave(&ci->lock, flags);
-	if (hw_port_test_set(ci, mode))
-		dev_err(ci->dev, "invalid mode\n");
-	spin_unlock_irqrestore(&ci->lock, flags);
-
- done:
-	return count;
+	return single_open(file, ci_port_test_show, inode->i_private);
 }
-static DEVICE_ATTR(port_test, S_IRUSR | S_IWUSR,
-		   show_port_test, store_port_test);
+
+static const struct file_operations ci_port_test_fops = {
+	.open		= ci_port_test_open,
+	.write		= ci_port_test_write,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
 
 /**
- * show_qheads: DMA contents of all queue heads
- *
- * Check "device.h" for details
+ * ci_qheads_show: DMA contents of all queue heads
  */
-static ssize_t show_qheads(struct device *dev, struct device_attribute *attr,
-			   char *buf)
+static int ci_qheads_show(struct seq_file *s, void *data)
 {
-	struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
+	struct ci13xxx *ci = s->private;
 	unsigned long flags;
-	unsigned i, j, n = 0;
+	unsigned i, j;
 
-	if (attr == NULL || buf == NULL) {
-		dev_err(ci->dev, "[%s] EINVAL\n", __func__);
+	if (ci->role != CI_ROLE_GADGET) {
+		seq_printf(s, "not in gadget mode\n");
 		return 0;
 	}
 
@@ -593,209 +129,173 @@ static ssize_t show_qheads(struct device *dev, struct device_attribute *attr,
 		struct ci13xxx_ep *mEpRx = &ci->ci13xxx_ep[i];
 		struct ci13xxx_ep *mEpTx =
 			&ci->ci13xxx_ep[i + ci->hw_ep_max/2];
-		n += scnprintf(buf + n, PAGE_SIZE - n,
-			       "EP=%02i: RX=%08X TX=%08X\n",
-			       i, (u32)mEpRx->qh.dma, (u32)mEpTx->qh.dma);
-		for (j = 0; j < (sizeof(struct ci13xxx_qh)/sizeof(u32)); j++) {
-			n += scnprintf(buf + n, PAGE_SIZE - n,
-				       " %04X:    %08X    %08X\n", j,
-				       *((u32 *)mEpRx->qh.ptr + j),
-				       *((u32 *)mEpTx->qh.ptr + j));
-		}
+		seq_printf(s, "EP=%02i: RX=%08X TX=%08X\n",
+			   i, (u32)mEpRx->qh.dma, (u32)mEpTx->qh.dma);
+		for (j = 0; j < (sizeof(struct ci13xxx_qh)/sizeof(u32)); j++)
+			seq_printf(s, " %04X:    %08X    %08X\n", j,
+				   *((u32 *)mEpRx->qh.ptr + j),
+				   *((u32 *)mEpTx->qh.ptr + j));
 	}
 	spin_unlock_irqrestore(&ci->lock, flags);
 
-	return n;
+	return 0;
+}
+
+static int ci_qheads_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, ci_qheads_show, inode->i_private);
 }
-static DEVICE_ATTR(qheads, S_IRUSR, show_qheads, NULL);
+
+static const struct file_operations ci_qheads_fops = {
+	.open		= ci_qheads_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
 
 /**
- * show_registers: dumps all registers
- *
- * Check "device.h" for details
+ * ci_requests_show: DMA contents of all requests currently queued (all endpts)
  */
-#define DUMP_ENTRIES	512
-static ssize_t show_registers(struct device *dev,
-			      struct device_attribute *attr, char *buf)
+static int ci_requests_show(struct seq_file *s, void *data)
 {
-	struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
+	struct ci13xxx *ci = s->private;
 	unsigned long flags;
-	u32 *dump;
-	unsigned i, k, n = 0;
-
-	if (attr == NULL || buf == NULL) {
-		dev_err(ci->dev, "[%s] EINVAL\n", __func__);
-		return 0;
-	}
+	struct list_head   *ptr = NULL;
+	struct ci13xxx_req *req = NULL;
+	unsigned i, j, qsize = sizeof(struct ci13xxx_td)/sizeof(u32);
 
-	dump = kmalloc(sizeof(u32) * DUMP_ENTRIES, GFP_KERNEL);
-	if (!dump) {
-		dev_err(ci->dev, "%s: out of memory\n", __func__);
+	if (ci->role != CI_ROLE_GADGET) {
+		seq_printf(s, "not in gadget mode\n");
 		return 0;
 	}
 
 	spin_lock_irqsave(&ci->lock, flags);
-	k = hw_register_read(ci, dump, DUMP_ENTRIES);
-	spin_unlock_irqrestore(&ci->lock, flags);
+	for (i = 0; i < ci->hw_ep_max; i++)
+		list_for_each(ptr, &ci->ci13xxx_ep[i].qh.queue) {
+			req = list_entry(ptr, struct ci13xxx_req, queue);
 
-	for (i = 0; i < k; i++) {
-		n += scnprintf(buf + n, PAGE_SIZE - n,
-			       "reg[0x%04X] = 0x%08X\n",
-			       i * (unsigned)sizeof(u32), dump[i]);
-	}
-	kfree(dump);
+			seq_printf(s, "EP=%02i: TD=%08X %s\n",
+				   i % (ci->hw_ep_max / 2), (u32)req->dma,
+				   ((i < ci->hw_ep_max/2) ? "RX" : "TX"));
+
+			for (j = 0; j < qsize; j++)
+				seq_printf(s, " %04X:    %08X\n", j,
+					   *((u32 *)req->ptr + j));
+		}
+	spin_unlock_irqrestore(&ci->lock, flags);
 
-	return n;
+	return 0;
 }
 
-/**
- * store_registers: writes value to register address
- *
- * Check "device.h" for details
- */
-static ssize_t store_registers(struct device *dev,
-			       struct device_attribute *attr,
-			       const char *buf, size_t count)
+static int ci_requests_open(struct inode *inode, struct file *file)
 {
-	struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
-	unsigned long addr, data, flags;
+	return single_open(file, ci_requests_show, inode->i_private);
+}
 
-	if (attr == NULL || buf == NULL) {
-		dev_err(ci->dev, "[%s] EINVAL\n", __func__);
-		goto done;
-	}
+static const struct file_operations ci_requests_fops = {
+	.open		= ci_requests_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
 
-	if (sscanf(buf, "%li %li", &addr, &data) != 2) {
-		dev_err(ci->dev,
-			"<addr> <data>: write data to register address\n");
-		goto done;
-	}
+static int ci_role_show(struct seq_file *s, void *data)
+{
+	struct ci13xxx *ci = s->private;
 
-	spin_lock_irqsave(&ci->lock, flags);
-	if (hw_register_write(ci, addr, data))
-		dev_err(ci->dev, "invalid address range\n");
-	spin_unlock_irqrestore(&ci->lock, flags);
+	seq_printf(s, "%s\n", ci_role(ci)->name);
 
- done:
-	return count;
+	return 0;
 }
-static DEVICE_ATTR(registers, S_IRUSR | S_IWUSR,
-		   show_registers, store_registers);
 
-/**
- * show_requests: DMA contents of all requests currently queued (all endpts)
- *
- * Check "device.h" for details
- */
-static ssize_t show_requests(struct device *dev, struct device_attribute *attr,
-			     char *buf)
+static ssize_t ci_role_write(struct file *file, const char __user *ubuf,
+			     size_t count, loff_t *ppos)
 {
-	struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
-	unsigned long flags;
-	struct list_head   *ptr = NULL;
-	struct ci13xxx_req *req = NULL;
-	unsigned i, j, n = 0, qSize = sizeof(struct ci13xxx_td)/sizeof(u32);
-
-	if (attr == NULL || buf == NULL) {
-		dev_err(ci->dev, "[%s] EINVAL\n", __func__);
-		return 0;
-	}
+	struct seq_file *s = file->private_data;
+	struct ci13xxx *ci = s->private;
+	enum ci_role role;
+	char buf[8];
+	int ret;
+
+	if (copy_from_user(buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
+		return -EFAULT;
+
+	for (role = CI_ROLE_HOST; role < CI_ROLE_END; role++)
+		if (ci->roles[role] &&
+		    !strncmp(buf, ci->roles[role]->name,
+			     strlen(ci->roles[role]->name)))
+			break;
 
-	spin_lock_irqsave(&ci->lock, flags);
-	for (i = 0; i < ci->hw_ep_max; i++)
-		list_for_each(ptr, &ci->ci13xxx_ep[i].qh.queue)
-		{
-			req = list_entry(ptr, struct ci13xxx_req, queue);
+	if (role == CI_ROLE_END || role == ci->role)
+		return -EINVAL;
 
-			n += scnprintf(buf + n, PAGE_SIZE - n,
-					"EP=%02i: TD=%08X %s\n",
-					i % ci->hw_ep_max/2, (u32)req->dma,
-					((i < ci->hw_ep_max/2) ? "RX" : "TX"));
+	ci_role_stop(ci);
+	ret = ci_role_start(ci, role);
 
-			for (j = 0; j < qSize; j++)
-				n += scnprintf(buf + n, PAGE_SIZE - n,
-						" %04X:    %08X\n", j,
-						*((u32 *)req->ptr + j));
-		}
-	spin_unlock_irqrestore(&ci->lock, flags);
+	return ret ? ret : count;
+}
 
-	return n;
+static int ci_role_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, ci_role_show, inode->i_private);
 }
-static DEVICE_ATTR(requests, S_IRUSR, show_requests, NULL);
+
+static const struct file_operations ci_role_fops = {
+	.open		= ci_role_open,
+	.write		= ci_role_write,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
 
 /**
  * dbg_create_files: initializes the attribute interface
- * @dev: device
+ * @ci: device
  *
  * This function returns an error code
  */
-int dbg_create_files(struct device *dev)
+int dbg_create_files(struct ci13xxx *ci)
 {
-	int retval = 0;
-
-	if (dev == NULL)
-		return -EINVAL;
-	retval = device_create_file(dev, &dev_attr_device);
-	if (retval)
-		goto done;
-	retval = device_create_file(dev, &dev_attr_driver);
-	if (retval)
-		goto rm_device;
-	retval = device_create_file(dev, &dev_attr_events);
-	if (retval)
-		goto rm_driver;
-	retval = device_create_file(dev, &dev_attr_inters);
-	if (retval)
-		goto rm_events;
-	retval = device_create_file(dev, &dev_attr_port_test);
-	if (retval)
-		goto rm_inters;
-	retval = device_create_file(dev, &dev_attr_qheads);
-	if (retval)
-		goto rm_port_test;
-	retval = device_create_file(dev, &dev_attr_registers);
-	if (retval)
-		goto rm_qheads;
-	retval = device_create_file(dev, &dev_attr_requests);
-	if (retval)
-		goto rm_registers;
-	return 0;
-
- rm_registers:
-	device_remove_file(dev, &dev_attr_registers);
- rm_qheads:
-	device_remove_file(dev, &dev_attr_qheads);
- rm_port_test:
-	device_remove_file(dev, &dev_attr_port_test);
- rm_inters:
-	device_remove_file(dev, &dev_attr_inters);
- rm_events:
-	device_remove_file(dev, &dev_attr_events);
- rm_driver:
-	device_remove_file(dev, &dev_attr_driver);
- rm_device:
-	device_remove_file(dev, &dev_attr_device);
- done:
-	return retval;
+	struct dentry *dent;
+
+	ci->debugfs = debugfs_create_dir(dev_name(ci->dev), NULL);
+	if (!ci->debugfs)
+		return -ENOMEM;
+
+	dent = debugfs_create_file("device", S_IRUGO, ci->debugfs, ci,
+				   &ci_device_fops);
+	if (!dent)
+		goto err;
+
+	dent = debugfs_create_file("port_test", S_IRUGO | S_IWUSR, ci->debugfs,
+				   ci, &ci_port_test_fops);
+	if (!dent)
+		goto err;
+
+	dent = debugfs_create_file("qheads", S_IRUGO, ci->debugfs, ci,
+				   &ci_qheads_fops);
+	if (!dent)
+		goto err;
+
+	dent = debugfs_create_file("requests", S_IRUGO, ci->debugfs, ci,
+				   &ci_requests_fops);
+	if (!dent)
+		goto err;
+
+	dent = debugfs_create_file("role", S_IRUGO | S_IWUSR, ci->debugfs, ci,
+				   &ci_role_fops);
+	if (dent)
+		return 0;
+err:
+	debugfs_remove_recursive(ci->debugfs);
+	return -ENOMEM;
 }
 
 /**
  * dbg_remove_files: destroys the attribute interface
- * @dev: device
- *
- * This function returns an error code
+ * @ci: device
  */
-int dbg_remove_files(struct device *dev)
+void dbg_remove_files(struct ci13xxx *ci)
 {
-	if (dev == NULL)
-		return -EINVAL;
-	device_remove_file(dev, &dev_attr_requests);
-	device_remove_file(dev, &dev_attr_registers);
-	device_remove_file(dev, &dev_attr_qheads);
-	device_remove_file(dev, &dev_attr_port_test);
-	device_remove_file(dev, &dev_attr_inters);
-	device_remove_file(dev, &dev_attr_events);
-	device_remove_file(dev, &dev_attr_driver);
-	device_remove_file(dev, &dev_attr_device);
-	return 0;
+	debugfs_remove_recursive(ci->debugfs);
 }
diff --git a/drivers/usb/chipidea/debug.h b/drivers/usb/chipidea/debug.h
index 80d9686..7ca6ca0 100644
--- a/drivers/usb/chipidea/debug.h
+++ b/drivers/usb/chipidea/debug.h
@@ -14,42 +14,16 @@
 #define __DRIVERS_USB_CHIPIDEA_DEBUG_H
 
 #ifdef CONFIG_USB_CHIPIDEA_DEBUG
-void dbg_interrupt(u32 intmask);
-void dbg_done(u8 addr, const u32 token, int status);
-void dbg_event(u8 addr, const char *name, int status);
-void dbg_queue(u8 addr, const struct usb_request *req, int status);
-void dbg_setup(u8 addr, const struct usb_ctrlrequest *req);
-int dbg_create_files(struct device *dev);
-int dbg_remove_files(struct device *dev);
+int dbg_create_files(struct ci13xxx *ci);
+void dbg_remove_files(struct ci13xxx *ci);
 #else
-static inline void dbg_interrupt(u32 intmask)
-{
-}
-
-static inline void dbg_done(u8 addr, const u32 token, int status)
-{
-}
-
-static inline void dbg_event(u8 addr, const char *name, int status)
-{
-}
-
-static inline void dbg_queue(u8 addr, const struct usb_request *req, int status)
-{
-}
-
-static inline void dbg_setup(u8 addr, const struct usb_ctrlrequest *req)
-{
-}
-
-static inline int dbg_create_files(struct device *dev)
+static inline int dbg_create_files(struct ci13xxx *ci)
 {
 	return 0;
 }
 
-static inline int dbg_remove_files(struct device *dev)
+static inline void dbg_remove_files(struct ci13xxx *ci)
 {
-	return 0;
 }
 #endif
 
diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c
index f64fbea..68bc9ba 100644
--- a/drivers/usb/chipidea/udc.c
+++ b/drivers/usb/chipidea/udc.c
@@ -13,14 +13,8 @@
 #include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/dmapool.h>
-#include <linux/dma-mapping.h>
 #include <linux/err.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/irq.h>
+#include <linux/irqreturn.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/pm_runtime.h>
@@ -146,7 +140,7 @@ static int hw_ep_enable(struct ci13xxx *ci, int num, int dir, int type)
 
 	if (dir) {
 		mask  = ENDPTCTRL_TXT;  /* type    */
-		data  = type << ffs_nr(mask);
+		data  = type << __ffs(mask);
 
 		mask |= ENDPTCTRL_TXS;  /* unstall */
 		mask |= ENDPTCTRL_TXR;  /* reset data toggle */
@@ -155,7 +149,7 @@ static int hw_ep_enable(struct ci13xxx *ci, int num, int dir, int type)
 		data |= ENDPTCTRL_TXE;
 	} else {
 		mask  = ENDPTCTRL_RXT;  /* type    */
-		data  = type << ffs_nr(mask);
+		data  = type << __ffs(mask);
 
 		mask |= ENDPTCTRL_RXS;  /* unstall */
 		mask |= ENDPTCTRL_RXR;  /* reset data toggle */
@@ -305,18 +299,6 @@ static u32 hw_test_and_clear_intr_active(struct ci13xxx *ci)
 	return reg;
 }
 
-static void hw_enable_vbus_intr(struct ci13xxx *ci)
-{
-	hw_write(ci, OP_OTGSC, OTGSC_AVVIS, OTGSC_AVVIS);
-	hw_write(ci, OP_OTGSC, OTGSC_AVVIE, OTGSC_AVVIE);
-	queue_work(ci->wq, &ci->vbus_work);
-}
-
-static void hw_disable_vbus_intr(struct ci13xxx *ci)
-{
-	hw_write(ci, OP_OTGSC, OTGSC_AVVIE, 0);
-}
-
 /**
  * hw_test_and_clear_setup_guard: test & clear setup guard (execute without
  *                                interruption)
@@ -349,7 +331,7 @@ static int hw_test_and_set_setup_guard(struct ci13xxx *ci)
 static void hw_usb_set_address(struct ci13xxx *ci, u8 value)
 {
 	hw_write(ci, OP_DEVICEADDR, DEVICEADDR_USBADR,
-		 value << ffs_nr(DEVICEADDR_USBADR));
+		 value << __ffs(DEVICEADDR_USBADR));
 }
 
 /**
@@ -383,16 +365,6 @@ static int hw_usb_reset(struct ci13xxx *ci)
 	return 0;
 }
 
-static void vbus_work(struct work_struct *work)
-{
-	struct ci13xxx *ci = container_of(work, struct ci13xxx, vbus_work);
-
-	if (hw_read(ci, OP_OTGSC, OTGSC_AVV))
-		usb_gadget_vbus_connect(&ci->gadget);
-	else
-		usb_gadget_vbus_disconnect(&ci->gadget);
-}
-
 /******************************************************************************
  * UTIL block
  *****************************************************************************/
@@ -432,10 +404,10 @@ static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
 			return -ENOMEM;
 
 		memset(mReq->zptr, 0, sizeof(*mReq->zptr));
-		mReq->zptr->next    = TD_TERMINATE;
-		mReq->zptr->token   = TD_STATUS_ACTIVE;
+		mReq->zptr->next    = cpu_to_le32(TD_TERMINATE);
+		mReq->zptr->token   = cpu_to_le32(TD_STATUS_ACTIVE);
 		if (!mReq->req.no_interrupt)
-			mReq->zptr->token   |= TD_IOC;
+			mReq->zptr->token   |= cpu_to_le32(TD_IOC);
 	}
 	ret = usb_gadget_map_request(&ci->gadget, &mReq->req, mEp->dir);
 	if (ret)
@@ -446,32 +418,35 @@ static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
 	 * TODO - handle requests which spawns into several TDs
 	 */
 	memset(mReq->ptr, 0, sizeof(*mReq->ptr));
-	mReq->ptr->token    = length << ffs_nr(TD_TOTAL_BYTES);
-	mReq->ptr->token   &= TD_TOTAL_BYTES;
-	mReq->ptr->token   |= TD_STATUS_ACTIVE;
+	mReq->ptr->token    = cpu_to_le32(length << __ffs(TD_TOTAL_BYTES));
+	mReq->ptr->token   &= cpu_to_le32(TD_TOTAL_BYTES);
+	mReq->ptr->token   |= cpu_to_le32(TD_STATUS_ACTIVE);
 	if (mReq->zptr) {
-		mReq->ptr->next    = mReq->zdma;
+		mReq->ptr->next    = cpu_to_le32(mReq->zdma);
 	} else {
-		mReq->ptr->next    = TD_TERMINATE;
+		mReq->ptr->next    = cpu_to_le32(TD_TERMINATE);
 		if (!mReq->req.no_interrupt)
-			mReq->ptr->token  |= TD_IOC;
+			mReq->ptr->token  |= cpu_to_le32(TD_IOC);
+	}
+	mReq->ptr->page[0]  = cpu_to_le32(mReq->req.dma);
+	for (i = 1; i < TD_PAGE_COUNT; i++) {
+		u32 page = mReq->req.dma + i * CI13XXX_PAGE_SIZE;
+		page &= ~TD_RESERVED_MASK;
+		mReq->ptr->page[i] = cpu_to_le32(page);
 	}
-	mReq->ptr->page[0]  = mReq->req.dma;
-	for (i = 1; i < 5; i++)
-		mReq->ptr->page[i] =
-			(mReq->req.dma + i * CI13XXX_PAGE_SIZE) & ~TD_RESERVED_MASK;
 
 	if (!list_empty(&mEp->qh.queue)) {
 		struct ci13xxx_req *mReqPrev;
 		int n = hw_ep_bit(mEp->num, mEp->dir);
 		int tmp_stat;
+		u32 next = mReq->dma & TD_ADDR_MASK;
 
 		mReqPrev = list_entry(mEp->qh.queue.prev,
 				struct ci13xxx_req, queue);
 		if (mReqPrev->zptr)
-			mReqPrev->zptr->next = mReq->dma & TD_ADDR_MASK;
+			mReqPrev->zptr->next = cpu_to_le32(next);
 		else
-			mReqPrev->ptr->next = mReq->dma & TD_ADDR_MASK;
+			mReqPrev->ptr->next = cpu_to_le32(next);
 		wmb();
 		if (hw_read(ci, OP_ENDPTPRIME, BIT(n)))
 			goto done;
@@ -485,9 +460,9 @@ static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
 	}
 
 	/*  QH configuration */
-	mEp->qh.ptr->td.next   = mReq->dma;    /* TERMINATE = 0 */
-	mEp->qh.ptr->td.token &= ~TD_STATUS;   /* clear status */
-	mEp->qh.ptr->cap |=  QH_ZLT;
+	mEp->qh.ptr->td.next   = cpu_to_le32(mReq->dma);    /* TERMINATE = 0 */
+	mEp->qh.ptr->td.token &=
+		cpu_to_le32(~(TD_STATUS_HALTED|TD_STATUS_ACTIVE));
 
 	wmb();   /* synchronize before ep prime */
 
@@ -506,14 +481,16 @@ done:
  */
 static int _hardware_dequeue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
 {
+	u32 tmptoken = le32_to_cpu(mReq->ptr->token);
+
 	if (mReq->req.status != -EALREADY)
 		return -EINVAL;
 
-	if ((TD_STATUS_ACTIVE & mReq->ptr->token) != 0)
+	if ((TD_STATUS_ACTIVE & tmptoken) != 0)
 		return -EBUSY;
 
 	if (mReq->zptr) {
-		if ((TD_STATUS_ACTIVE & mReq->zptr->token) != 0)
+		if ((cpu_to_le32(TD_STATUS_ACTIVE) & mReq->zptr->token) != 0)
 			return -EBUSY;
 		dma_pool_free(mEp->td_pool, mReq->zptr, mReq->zdma);
 		mReq->zptr = NULL;
@@ -523,7 +500,7 @@ static int _hardware_dequeue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
 
 	usb_gadget_unmap_request(&mEp->ci->gadget, &mReq->req, mEp->dir);
 
-	mReq->req.status = mReq->ptr->token & TD_STATUS;
+	mReq->req.status = tmptoken & TD_STATUS;
 	if ((TD_STATUS_HALTED & mReq->req.status) != 0)
 		mReq->req.status = -1;
 	else if ((TD_STATUS_DT_ERR & mReq->req.status) != 0)
@@ -531,8 +508,8 @@ static int _hardware_dequeue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
 	else if ((TD_STATUS_TR_ERR & mReq->req.status) != 0)
 		mReq->req.status = -1;
 
-	mReq->req.actual   = mReq->ptr->token & TD_TOTAL_BYTES;
-	mReq->req.actual >>= ffs_nr(TD_TOTAL_BYTES);
+	mReq->req.actual   = tmptoken & TD_TOTAL_BYTES;
+	mReq->req.actual >>= __ffs(TD_TOTAL_BYTES);
 	mReq->req.actual   = mReq->req.length - mReq->req.actual;
 	mReq->req.actual   = mReq->req.status ? 0 : mReq->req.actual;
 
@@ -629,8 +606,6 @@ __acquires(ci->lock)
 {
 	int retval;
 
-	dbg_event(0xFF, "BUS RST", 0);
-
 	spin_unlock(&ci->lock);
 	retval = _gadget_stop_activity(&ci->gadget);
 	if (retval)
@@ -668,6 +643,59 @@ static void isr_get_status_complete(struct usb_ep *ep, struct usb_request *req)
 }
 
 /**
+ * _ep_queue: queues (submits) an I/O request to an endpoint
+ *
+ * Caller must hold lock
+ */
+static int _ep_queue(struct usb_ep *ep, struct usb_request *req,
+		    gfp_t __maybe_unused gfp_flags)
+{
+	struct ci13xxx_ep  *mEp  = container_of(ep,  struct ci13xxx_ep, ep);
+	struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req);
+	struct ci13xxx *ci = mEp->ci;
+	int retval = 0;
+
+	if (ep == NULL || req == NULL || mEp->ep.desc == NULL)
+		return -EINVAL;
+
+	if (mEp->type == USB_ENDPOINT_XFER_CONTROL) {
+		if (req->length)
+			mEp = (ci->ep0_dir == RX) ?
+			       ci->ep0out : ci->ep0in;
+		if (!list_empty(&mEp->qh.queue)) {
+			_ep_nuke(mEp);
+			retval = -EOVERFLOW;
+			dev_warn(mEp->ci->dev, "endpoint ctrl %X nuked\n",
+				 _usb_addr(mEp));
+		}
+	}
+
+	/* first nuke then test link, e.g. previous status has not sent */
+	if (!list_empty(&mReq->queue)) {
+		dev_err(mEp->ci->dev, "request already in queue\n");
+		return -EBUSY;
+	}
+
+	if (req->length > (TD_PAGE_COUNT - 1) * CI13XXX_PAGE_SIZE) {
+		dev_err(mEp->ci->dev, "request bigger than one td\n");
+		return -EMSGSIZE;
+	}
+
+	/* push request */
+	mReq->req.status = -EINPROGRESS;
+	mReq->req.actual = 0;
+
+	retval = _hardware_enqueue(mEp, mReq);
+
+	if (retval == -EALREADY)
+		retval = 0;
+	if (!retval)
+		list_add_tail(&mReq->queue, &mEp->qh.queue);
+
+	return retval;
+}
+
+/**
  * isr_get_status_response: get_status request response
  * @ci: ci struct
  * @setup: setup request packet
@@ -714,9 +742,7 @@ __acquires(mEp->lock)
 	}
 	/* else do nothing; reserved for future use */
 
-	spin_unlock(mEp->lock);
-	retval = usb_ep_queue(&mEp->ep, req, gfp_flags);
-	spin_lock(mEp->lock);
+	retval = _ep_queue(&mEp->ep, req, gfp_flags);
 	if (retval)
 		goto err_free_buf;
 
@@ -763,8 +789,6 @@ isr_setup_status_complete(struct usb_ep *ep, struct usb_request *req)
  * This function returns an error code
  */
 static int isr_setup_status_phase(struct ci13xxx *ci)
-__releases(mEp->lock)
-__acquires(mEp->lock)
 {
 	int retval;
 	struct ci13xxx_ep *mEp;
@@ -773,9 +797,7 @@ __acquires(mEp->lock)
 	ci->status->context = ci;
 	ci->status->complete = isr_setup_status_complete;
 
-	spin_unlock(mEp->lock);
-	retval = usb_ep_queue(&mEp->ep, ci->status, GFP_ATOMIC);
-	spin_lock(mEp->lock);
+	retval = _ep_queue(&mEp->ep, ci->status, GFP_ATOMIC);
 
 	return retval;
 }
@@ -801,7 +823,6 @@ __acquires(mEp->lock)
 		if (retval < 0)
 			break;
 		list_del_init(&mReq->queue);
-		dbg_done(_usb_addr(mEp), mReq->ptr->token, retval);
 		if (mReq->req.complete != NULL) {
 			spin_unlock(mEp->lock);
 			if ((mEp->type == USB_ENDPOINT_XFER_CONTROL) &&
@@ -814,8 +835,6 @@ __acquires(mEp->lock)
 
 	if (retval == -EBUSY)
 		retval = 0;
-	if (retval < 0)
-		dbg_event(_usb_addr(mEp), "DONE", retval);
 
 	return retval;
 }
@@ -847,8 +866,6 @@ __acquires(ci->lock)
 				if (err > 0)   /* needs status phase */
 					err = isr_setup_status_phase(ci);
 				if (err < 0) {
-					dbg_event(_usb_addr(mEp),
-						  "ERROR", err);
 					spin_unlock(&ci->lock);
 					if (usb_ep_set_halt(&mEp->ep))
 						dev_err(ci->dev,
@@ -884,8 +901,6 @@ __acquires(ci->lock)
 
 		ci->ep0_dir = (type & USB_DIR_IN) ? TX : RX;
 
-		dbg_setup(_usb_addr(mEp), &req);
-
 		switch (req.bRequest) {
 		case USB_REQ_CLEAR_FEATURE:
 			if (type == (USB_DIR_OUT|USB_RECIP_ENDPOINT) &&
@@ -997,8 +1012,6 @@ delegate:
 		}
 
 		if (err < 0) {
-			dbg_event(_usb_addr(mEp), "ERROR", err);
-
 			spin_unlock(&ci->lock);
 			if (usb_ep_set_halt(&mEp->ep))
 				dev_err(ci->dev, "error: ep_set_halt\n");
@@ -1021,6 +1034,7 @@ static int ep_enable(struct usb_ep *ep,
 	struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
 	int retval = 0;
 	unsigned long flags;
+	u32 cap = 0;
 
 	if (ep == NULL || desc == NULL)
 		return -EINVAL;
@@ -1040,20 +1054,15 @@ static int ep_enable(struct usb_ep *ep,
 
 	mEp->ep.maxpacket = usb_endpoint_maxp(desc);
 
-	dbg_event(_usb_addr(mEp), "ENABLE", 0);
-
-	mEp->qh.ptr->cap = 0;
-
 	if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
-		mEp->qh.ptr->cap |=  QH_IOS;
-	else if (mEp->type == USB_ENDPOINT_XFER_ISOC)
-		mEp->qh.ptr->cap &= ~QH_MULT;
-	else
-		mEp->qh.ptr->cap &= ~QH_ZLT;
+		cap |= QH_IOS;
+	if (mEp->num)
+		cap |= QH_ZLT;
+	cap |= (mEp->ep.maxpacket << __ffs(QH_MAX_PKT)) & QH_MAX_PKT;
+
+	mEp->qh.ptr->cap = cpu_to_le32(cap);
 
-	mEp->qh.ptr->cap |=
-		(mEp->ep.maxpacket << ffs_nr(QH_MAX_PKT)) & QH_MAX_PKT;
-	mEp->qh.ptr->td.next |= TD_TERMINATE;   /* needed? */
+	mEp->qh.ptr->td.next |= cpu_to_le32(TD_TERMINATE);   /* needed? */
 
 	/*
 	 * Enable endpoints in the HW other than ep0 as ep0
@@ -1088,8 +1097,6 @@ static int ep_disable(struct usb_ep *ep)
 
 	direction = mEp->dir;
 	do {
-		dbg_event(_usb_addr(mEp), "DISABLE", 0);
-
 		retval |= _ep_nuke(mEp);
 		retval |= hw_ep_disable(mEp->ci, mEp->num, mEp->dir);
 
@@ -1129,8 +1136,6 @@ static struct usb_request *ep_alloc_request(struct usb_ep *ep, gfp_t gfp_flags)
 		}
 	}
 
-	dbg_event(_usb_addr(mEp), "ALLOC", mReq == NULL);
-
 	return (mReq == NULL) ? NULL : &mReq->req;
 }
 
@@ -1158,8 +1163,6 @@ static void ep_free_request(struct usb_ep *ep, struct usb_request *req)
 		dma_pool_free(mEp->td_pool, mReq->ptr, mReq->dma);
 	kfree(mReq);
 
-	dbg_event(_usb_addr(mEp), "FREE", 0);
-
 	spin_unlock_irqrestore(mEp->lock, flags);
 }
 
@@ -1172,8 +1175,6 @@ static int ep_queue(struct usb_ep *ep, struct usb_request *req,
 		    gfp_t __maybe_unused gfp_flags)
 {
 	struct ci13xxx_ep  *mEp  = container_of(ep,  struct ci13xxx_ep, ep);
-	struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req);
-	struct ci13xxx *ci = mEp->ci;
 	int retval = 0;
 	unsigned long flags;
 
@@ -1181,48 +1182,7 @@ static int ep_queue(struct usb_ep *ep, struct usb_request *req,
 		return -EINVAL;
 
 	spin_lock_irqsave(mEp->lock, flags);
-
-	if (mEp->type == USB_ENDPOINT_XFER_CONTROL) {
-		if (req->length)
-			mEp = (ci->ep0_dir == RX) ?
-			       ci->ep0out : ci->ep0in;
-		if (!list_empty(&mEp->qh.queue)) {
-			_ep_nuke(mEp);
-			retval = -EOVERFLOW;
-			dev_warn(mEp->ci->dev, "endpoint ctrl %X nuked\n",
-				 _usb_addr(mEp));
-		}
-	}
-
-	/* first nuke then test link, e.g. previous status has not sent */
-	if (!list_empty(&mReq->queue)) {
-		retval = -EBUSY;
-		dev_err(mEp->ci->dev, "request already in queue\n");
-		goto done;
-	}
-
-	if (req->length > 4 * CI13XXX_PAGE_SIZE) {
-		req->length = 4 * CI13XXX_PAGE_SIZE;
-		retval = -EMSGSIZE;
-		dev_warn(mEp->ci->dev, "request length truncated\n");
-	}
-
-	dbg_queue(_usb_addr(mEp), req, retval);
-
-	/* push request */
-	mReq->req.status = -EINPROGRESS;
-	mReq->req.actual = 0;
-
-	retval = _hardware_enqueue(mEp, mReq);
-
-	if (retval == -EALREADY) {
-		dbg_event(_usb_addr(mEp), "QUEUE", retval);
-		retval = 0;
-	}
-	if (!retval)
-		list_add_tail(&mReq->queue, &mEp->qh.queue);
-
- done:
+	retval = _ep_queue(ep, req, gfp_flags);
 	spin_unlock_irqrestore(mEp->lock, flags);
 	return retval;
 }
@@ -1245,8 +1205,6 @@ static int ep_dequeue(struct usb_ep *ep, struct usb_request *req)
 
 	spin_lock_irqsave(mEp->lock, flags);
 
-	dbg_event(_usb_addr(mEp), "DEQUEUE", 0);
-
 	hw_ep_flush(mEp->ci, mEp->num, mEp->dir);
 
 	/* pop request */
@@ -1293,7 +1251,6 @@ static int ep_set_halt(struct usb_ep *ep, int value)
 
 	direction = mEp->dir;
 	do {
-		dbg_event(_usb_addr(mEp), "HALT", value);
 		retval |= hw_ep_set_halt(mEp->ci, mEp->num, mEp->dir, value);
 
 		if (!value)
@@ -1322,10 +1279,7 @@ static int ep_set_wedge(struct usb_ep *ep)
 		return -EINVAL;
 
 	spin_lock_irqsave(mEp->lock, flags);
-
-	dbg_event(_usb_addr(mEp), "WEDGE", 0);
 	mEp->wedge = 1;
-
 	spin_unlock_irqrestore(mEp->lock, flags);
 
 	return usb_ep_set_halt(ep);
@@ -1348,7 +1302,6 @@ static void ep_fifo_flush(struct usb_ep *ep)
 
 	spin_lock_irqsave(mEp->lock, flags);
 
-	dbg_event(_usb_addr(mEp), "FFLUSH", 0);
 	hw_ep_flush(mEp->ci, mEp->num, mEp->dir);
 
 	spin_unlock_irqrestore(mEp->lock, flags);
@@ -1392,7 +1345,6 @@ static int ci13xxx_vbus_session(struct usb_gadget *_gadget, int is_active)
 		if (is_active) {
 			pm_runtime_get_sync(&_gadget->dev);
 			hw_device_reset(ci, USBMODE_CM_DC);
-			hw_enable_vbus_intr(ci);
 			hw_device_state(ci, ci->ep0out->qh.dma);
 		} else {
 			hw_device_state(ci, 0);
@@ -1567,10 +1519,8 @@ static int ci13xxx_start(struct usb_gadget *gadget,
 	pm_runtime_get_sync(&ci->gadget.dev);
 	if (ci->platdata->flags & CI13XXX_PULLUP_ON_VBUS) {
 		if (ci->vbus_active) {
-			if (ci->platdata->flags & CI13XXX_REGS_SHARED) {
+			if (ci->platdata->flags & CI13XXX_REGS_SHARED)
 				hw_device_reset(ci, USBMODE_CM_DC);
-				hw_enable_vbus_intr(ci);
-			}
 		} else {
 			pm_runtime_put_sync(&ci->gadget.dev);
 			goto done;
@@ -1642,7 +1592,6 @@ static irqreturn_t udc_irq(struct ci13xxx *ci)
 		}
 	}
 	intr = hw_test_and_clear_intr_active(ci);
-	dbg_interrupt(intr);
 
 	if (intr) {
 		/* order defines priority - do NOT change it */
@@ -1676,29 +1625,12 @@ static irqreturn_t udc_irq(struct ci13xxx *ci)
 	} else {
 		retval = IRQ_NONE;
 	}
-
-	intr = hw_read(ci, OP_OTGSC, ~0);
-	hw_write(ci, OP_OTGSC, ~0, intr);
-
-	if (intr & (OTGSC_AVVIE & OTGSC_AVVIS))
-		queue_work(ci->wq, &ci->vbus_work);
-
 	spin_unlock(&ci->lock);
 
 	return retval;
 }
 
 /**
- * udc_release: driver release function
- * @dev: device
- *
- * Currently does nothing
- */
-static void udc_release(struct device *dev)
-{
-}
-
-/**
  * udc_start: initialize gadget role
  * @ci: chipidea controller
  */
@@ -1717,12 +1649,6 @@ static int udc_start(struct ci13xxx *ci)
 
 	INIT_LIST_HEAD(&ci->gadget.ep_list);
 
-	dev_set_name(&ci->gadget.dev, "gadget");
-	ci->gadget.dev.dma_mask = dev->dma_mask;
-	ci->gadget.dev.coherent_dma_mask = dev->coherent_dma_mask;
-	ci->gadget.dev.parent   = dev;
-	ci->gadget.dev.release  = udc_release;
-
 	/* alloc resources */
 	ci->qh_pool = dma_pool_create("ci13xxx_qh", dev,
 				       sizeof(struct ci13xxx_qh),
@@ -1758,24 +1684,13 @@ static int udc_start(struct ci13xxx *ci)
 		retval = hw_device_reset(ci, USBMODE_CM_DC);
 		if (retval)
 			goto put_transceiver;
-		hw_enable_vbus_intr(ci);
-	}
-
-	retval = device_register(&ci->gadget.dev);
-	if (retval) {
-		put_device(&ci->gadget.dev);
-		goto put_transceiver;
 	}
 
-	retval = dbg_create_files(ci->dev);
-	if (retval)
-		goto unreg_device;
-
 	if (!IS_ERR_OR_NULL(ci->transceiver)) {
 		retval = otg_set_peripheral(ci->transceiver->otg,
 						&ci->gadget);
 		if (retval)
-			goto remove_dbg;
+			goto put_transceiver;
 	}
 
 	retval = usb_add_gadget_udc(dev, &ci->gadget);
@@ -1795,10 +1710,6 @@ remove_trans:
 	}
 
 	dev_err(dev, "error = %i\n", retval);
-remove_dbg:
-	dbg_remove_files(ci->dev);
-unreg_device:
-	device_unregister(&ci->gadget.dev);
 put_transceiver:
 	if (!IS_ERR_OR_NULL(ci->transceiver) && ci->global_phy)
 		usb_put_phy(ci->transceiver);
@@ -1821,9 +1732,6 @@ static void udc_stop(struct ci13xxx *ci)
 	if (ci == NULL)
 		return;
 
-	hw_disable_vbus_intr(ci);
-	cancel_work_sync(&ci->vbus_work);
-
 	usb_del_gadget_udc(&ci->gadget);
 
 	destroy_eps(ci);
@@ -1836,8 +1744,6 @@ static void udc_stop(struct ci13xxx *ci)
 		if (ci->global_phy)
 			usb_put_phy(ci->transceiver);
 	}
-	dbg_remove_files(ci->dev);
-	device_unregister(&ci->gadget.dev);
 	/* my kobject is dynamic, I swear! */
 	memset(&ci->gadget, 0, sizeof(ci->gadget));
 }
@@ -1864,7 +1770,6 @@ int ci_hdrc_gadget_init(struct ci13xxx *ci)
 	rdrv->irq	= udc_irq;
 	rdrv->name	= "gadget";
 	ci->roles[CI_ROLE_GADGET] = rdrv;
-	INIT_WORK(&ci->vbus_work, vbus_work);
 
 	return 0;
 }
diff --git a/drivers/usb/chipidea/usbmisc_imx.c b/drivers/usb/chipidea/usbmisc_imx.c
new file mode 100644
index 0000000..714a6bd
--- /dev/null
+++ b/drivers/usb/chipidea/usbmisc_imx.c
@@ -0,0 +1,261 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ *
+ * 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/of_platform.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+
+#include "ci13xxx_imx.h"
+
+#define USB_DEV_MAX 4
+
+#define MX25_USB_PHY_CTRL_OFFSET	0x08
+#define MX25_BM_EXTERNAL_VBUS_DIVIDER	BIT(23)
+
+#define MX53_USB_OTG_PHY_CTRL_0_OFFSET	0x08
+#define MX53_USB_UH2_CTRL_OFFSET	0x14
+#define MX53_USB_UH3_CTRL_OFFSET	0x18
+#define MX53_BM_OVER_CUR_DIS_H1		BIT(5)
+#define MX53_BM_OVER_CUR_DIS_OTG	BIT(8)
+#define MX53_BM_OVER_CUR_DIS_UHx	BIT(30)
+
+#define MX6_BM_OVER_CUR_DIS		BIT(7)
+
+struct imx_usbmisc {
+	void __iomem *base;
+	spinlock_t lock;
+	struct clk *clk;
+	struct usbmisc_usb_device usbdev[USB_DEV_MAX];
+	const struct usbmisc_ops *ops;
+};
+
+static struct imx_usbmisc *usbmisc;
+
+static struct usbmisc_usb_device *get_usbdev(struct device *dev)
+{
+	int i, ret;
+
+	for (i = 0; i < USB_DEV_MAX; i++) {
+		if (usbmisc->usbdev[i].dev == dev)
+			return &usbmisc->usbdev[i];
+		else if (!usbmisc->usbdev[i].dev)
+			break;
+	}
+
+	if (i >= USB_DEV_MAX)
+		return ERR_PTR(-EBUSY);
+
+	ret = usbmisc_get_init_data(dev, &usbmisc->usbdev[i]);
+	if (ret)
+		return ERR_PTR(ret);
+
+	return &usbmisc->usbdev[i];
+}
+
+static int usbmisc_imx25_post(struct device *dev)
+{
+	struct usbmisc_usb_device *usbdev;
+	void __iomem *reg;
+	unsigned long flags;
+	u32 val;
+
+	usbdev = get_usbdev(dev);
+	if (IS_ERR(usbdev))
+		return PTR_ERR(usbdev);
+
+	reg = usbmisc->base + MX25_USB_PHY_CTRL_OFFSET;
+
+	if (usbdev->evdo) {
+		spin_lock_irqsave(&usbmisc->lock, flags);
+		val = readl(reg);
+		writel(val | MX25_BM_EXTERNAL_VBUS_DIVIDER, reg);
+		spin_unlock_irqrestore(&usbmisc->lock, flags);
+		usleep_range(5000, 10000); /* needed to stabilize voltage */
+	}
+
+	return 0;
+}
+
+static int usbmisc_imx53_init(struct device *dev)
+{
+	struct usbmisc_usb_device *usbdev;
+	void __iomem *reg = NULL;
+	unsigned long flags;
+	u32 val = 0;
+
+	usbdev = get_usbdev(dev);
+	if (IS_ERR(usbdev))
+		return PTR_ERR(usbdev);
+
+	if (usbdev->disable_oc) {
+		spin_lock_irqsave(&usbmisc->lock, flags);
+		switch (usbdev->index) {
+		case 0:
+			reg = usbmisc->base + MX53_USB_OTG_PHY_CTRL_0_OFFSET;
+			val = readl(reg) | MX53_BM_OVER_CUR_DIS_OTG;
+			break;
+		case 1:
+			reg = usbmisc->base + MX53_USB_OTG_PHY_CTRL_0_OFFSET;
+			val = readl(reg) | MX53_BM_OVER_CUR_DIS_H1;
+			break;
+		case 2:
+			reg = usbmisc->base + MX53_USB_UH2_CTRL_OFFSET;
+			val = readl(reg) | MX53_BM_OVER_CUR_DIS_UHx;
+			break;
+		case 3:
+			reg = usbmisc->base + MX53_USB_UH3_CTRL_OFFSET;
+			val = readl(reg) | MX53_BM_OVER_CUR_DIS_UHx;
+			break;
+		}
+		if (reg && val)
+			writel(val, reg);
+		spin_unlock_irqrestore(&usbmisc->lock, flags);
+	}
+
+	return 0;
+}
+
+static int usbmisc_imx6q_init(struct device *dev)
+{
+
+	struct usbmisc_usb_device *usbdev;
+	unsigned long flags;
+	u32 reg;
+
+	usbdev = get_usbdev(dev);
+	if (IS_ERR(usbdev))
+		return PTR_ERR(usbdev);
+
+	if (usbdev->disable_oc) {
+		spin_lock_irqsave(&usbmisc->lock, flags);
+		reg = readl(usbmisc->base + usbdev->index * 4);
+		writel(reg | MX6_BM_OVER_CUR_DIS,
+			usbmisc->base + usbdev->index * 4);
+		spin_unlock_irqrestore(&usbmisc->lock, flags);
+	}
+
+	return 0;
+}
+
+static const struct usbmisc_ops imx25_usbmisc_ops = {
+	.post = usbmisc_imx25_post,
+};
+
+static const struct usbmisc_ops imx53_usbmisc_ops = {
+	.init = usbmisc_imx53_init,
+};
+
+static const struct usbmisc_ops imx6q_usbmisc_ops = {
+	.init = usbmisc_imx6q_init,
+};
+
+static const struct of_device_id usbmisc_imx_dt_ids[] = {
+	{
+		.compatible = "fsl,imx25-usbmisc",
+		.data = &imx25_usbmisc_ops,
+	},
+	{
+		.compatible = "fsl,imx53-usbmisc",
+		.data = &imx53_usbmisc_ops,
+	},
+	{
+		.compatible = "fsl,imx6q-usbmisc",
+		.data = &imx6q_usbmisc_ops,
+	},
+	{ /* sentinel */ }
+};
+
+static int usbmisc_imx_probe(struct platform_device *pdev)
+{
+	struct resource	*res;
+	struct imx_usbmisc *data;
+	int ret;
+	struct of_device_id *tmp_dev;
+
+	if (usbmisc)
+		return -EBUSY;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	spin_lock_init(&data->lock);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	data->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(data->base))
+		return PTR_ERR(data->base);
+
+	data->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(data->clk)) {
+		dev_err(&pdev->dev,
+			"failed to get clock, err=%ld\n", PTR_ERR(data->clk));
+		return PTR_ERR(data->clk);
+	}
+
+	ret = clk_prepare_enable(data->clk);
+	if (ret) {
+		dev_err(&pdev->dev,
+			"clk_prepare_enable failed, err=%d\n", ret);
+		return ret;
+	}
+
+	tmp_dev = (struct of_device_id *)
+		of_match_device(usbmisc_imx_dt_ids, &pdev->dev);
+	data->ops = (const struct usbmisc_ops *)tmp_dev->data;
+	usbmisc = data;
+	ret = usbmisc_set_ops(data->ops);
+	if (ret) {
+		usbmisc = NULL;
+		clk_disable_unprepare(data->clk);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int usbmisc_imx_remove(struct platform_device *pdev)
+{
+	usbmisc_unset_ops(usbmisc->ops);
+	clk_disable_unprepare(usbmisc->clk);
+	usbmisc = NULL;
+	return 0;
+}
+
+static struct platform_driver usbmisc_imx_driver = {
+	.probe = usbmisc_imx_probe,
+	.remove = usbmisc_imx_remove,
+	.driver = {
+		.name = "usbmisc_imx",
+		.owner = THIS_MODULE,
+		.of_match_table = usbmisc_imx_dt_ids,
+	 },
+};
+
+int usbmisc_imx_drv_init(void)
+{
+	return platform_driver_register(&usbmisc_imx_driver);
+}
+subsys_initcall(usbmisc_imx_drv_init);
+
+void usbmisc_imx_drv_exit(void)
+{
+	platform_driver_unregister(&usbmisc_imx_driver);
+}
+module_exit(usbmisc_imx_drv_exit);
+
+MODULE_ALIAS("platform:usbmisc-imx");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("driver for imx usb non-core registers");
+MODULE_AUTHOR("Richard Zhao <richard.zhao@freescale.com>");
diff --git a/drivers/usb/chipidea/usbmisc_imx6q.c b/drivers/usb/chipidea/usbmisc_imx6q.c
deleted file mode 100644
index a1bce39..0000000
--- a/drivers/usb/chipidea/usbmisc_imx6q.c
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright 2012 Freescale Semiconductor, Inc.
- *
- * 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/of_platform.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/io.h>
-
-#include "ci13xxx_imx.h"
-
-#define USB_DEV_MAX 4
-
-#define BM_OVER_CUR_DIS		BIT(7)
-
-struct imx6q_usbmisc {
-	void __iomem *base;
-	spinlock_t lock;
-	struct clk *clk;
-	struct usbmisc_usb_device usbdev[USB_DEV_MAX];
-};
-
-static struct imx6q_usbmisc *usbmisc;
-
-static struct usbmisc_usb_device *get_usbdev(struct device *dev)
-{
-	int i, ret;
-
-	for (i = 0; i < USB_DEV_MAX; i++) {
-		if (usbmisc->usbdev[i].dev == dev)
-			return &usbmisc->usbdev[i];
-		else if (!usbmisc->usbdev[i].dev)
-			break;
-	}
-
-	if (i >= USB_DEV_MAX)
-		return ERR_PTR(-EBUSY);
-
-	ret = usbmisc_get_init_data(dev, &usbmisc->usbdev[i]);
-	if (ret)
-		return ERR_PTR(ret);
-
-	return &usbmisc->usbdev[i];
-}
-
-static int usbmisc_imx6q_init(struct device *dev)
-{
-
-	struct usbmisc_usb_device *usbdev;
-	unsigned long flags;
-	u32 reg;
-
-	usbdev = get_usbdev(dev);
-	if (IS_ERR(usbdev))
-		return PTR_ERR(usbdev);
-
-	if (usbdev->disable_oc) {
-		spin_lock_irqsave(&usbmisc->lock, flags);
-		reg = readl(usbmisc->base + usbdev->index * 4);
-		writel(reg | BM_OVER_CUR_DIS,
-			usbmisc->base + usbdev->index * 4);
-		spin_unlock_irqrestore(&usbmisc->lock, flags);
-	}
-
-	return 0;
-}
-
-static const struct usbmisc_ops imx6q_usbmisc_ops = {
-	.init = usbmisc_imx6q_init,
-};
-
-static const struct of_device_id usbmisc_imx6q_dt_ids[] = {
-	{ .compatible = "fsl,imx6q-usbmisc"},
-	{ /* sentinel */ }
-};
-
-static int usbmisc_imx6q_probe(struct platform_device *pdev)
-{
-	struct resource	*res;
-	struct imx6q_usbmisc *data;
-	int ret;
-
-	if (usbmisc)
-		return -EBUSY;
-
-	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
-	if (!data)
-		return -ENOMEM;
-
-	spin_lock_init(&data->lock);
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	data->base = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(data->base))
-		return PTR_ERR(data->base);
-
-	data->clk = devm_clk_get(&pdev->dev, NULL);
-	if (IS_ERR(data->clk)) {
-		dev_err(&pdev->dev,
-			"failed to get clock, err=%ld\n", PTR_ERR(data->clk));
-		return PTR_ERR(data->clk);
-	}
-
-	ret = clk_prepare_enable(data->clk);
-	if (ret) {
-		dev_err(&pdev->dev,
-			"clk_prepare_enable failed, err=%d\n", ret);
-		return ret;
-	}
-
-	ret = usbmisc_set_ops(&imx6q_usbmisc_ops);
-	if (ret) {
-		clk_disable_unprepare(data->clk);
-		return ret;
-	}
-
-	usbmisc = data;
-
-	return 0;
-}
-
-static int usbmisc_imx6q_remove(struct platform_device *pdev)
-{
-	usbmisc_unset_ops(&imx6q_usbmisc_ops);
-	clk_disable_unprepare(usbmisc->clk);
-	return 0;
-}
-
-static struct platform_driver usbmisc_imx6q_driver = {
-	.probe = usbmisc_imx6q_probe,
-	.remove = usbmisc_imx6q_remove,
-	.driver = {
-		.name = "usbmisc_imx6q",
-		.owner = THIS_MODULE,
-		.of_match_table = usbmisc_imx6q_dt_ids,
-	 },
-};
-
-int __init usbmisc_imx6q_drv_init(void)
-{
-	return platform_driver_register(&usbmisc_imx6q_driver);
-}
-subsys_initcall(usbmisc_imx6q_drv_init);
-
-void __exit usbmisc_imx6q_drv_exit(void)
-{
-	platform_driver_unregister(&usbmisc_imx6q_driver);
-}
-module_exit(usbmisc_imx6q_drv_exit);
-
-MODULE_ALIAS("platform:usbmisc-imx6q");
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("driver for imx6q usb non-core registers");
-MODULE_AUTHOR("Richard Zhao <richard.zhao@freescale.com>");
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 387dc6c..9b1cbcf 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -292,7 +292,6 @@ static void acm_ctrl_irq(struct urb *urb)
 {
 	struct acm *acm = urb->context;
 	struct usb_cdc_notification *dr = urb->transfer_buffer;
-	struct tty_struct *tty;
 	unsigned char *data;
 	int newctrl;
 	int retval;
@@ -327,17 +326,12 @@ static void acm_ctrl_irq(struct urb *urb)
 		break;
 
 	case USB_CDC_NOTIFY_SERIAL_STATE:
-		tty = tty_port_tty_get(&acm->port);
 		newctrl = get_unaligned_le16(data);
 
-		if (tty) {
-			if (!acm->clocal &&
-				(acm->ctrlin & ~newctrl & ACM_CTRL_DCD)) {
-				dev_dbg(&acm->control->dev,
-					"%s - calling hangup\n", __func__);
-				tty_hangup(tty);
-			}
-			tty_kref_put(tty);
+		if (!acm->clocal && (acm->ctrlin & ~newctrl & ACM_CTRL_DCD)) {
+			dev_dbg(&acm->control->dev, "%s - calling hangup\n",
+					__func__);
+			tty_port_tty_hangup(&acm->port, false);
 		}
 
 		acm->ctrlin = newctrl;
@@ -475,15 +469,10 @@ static void acm_write_bulk(struct urb *urb)
 static void acm_softint(struct work_struct *work)
 {
 	struct acm *acm = container_of(work, struct acm, work);
-	struct tty_struct *tty;
 
 	dev_vdbg(&acm->data->dev, "%s\n", __func__);
 
-	tty = tty_port_tty_get(&acm->port);
-	if (!tty)
-		return;
-	tty_wakeup(tty);
-	tty_kref_put(tty);
+	tty_port_tty_wakeup(&acm->port);
 }
 
 /*
@@ -839,14 +828,6 @@ static int acm_tty_ioctl(struct tty_struct *tty,
 	return rv;
 }
 
-static const __u32 acm_tty_speed[] = {
-	0, 50, 75, 110, 134, 150, 200, 300, 600,
-	1200, 1800, 2400, 4800, 9600, 19200, 38400,
-	57600, 115200, 230400, 460800, 500000, 576000,
-	921600, 1000000, 1152000, 1500000, 2000000,
-	2500000, 3000000, 3500000, 4000000
-};
-
 static void acm_tty_set_termios(struct tty_struct *tty,
 						struct ktermios *termios_old)
 {
@@ -981,6 +962,10 @@ static int acm_probe(struct usb_interface *intf,
 
 	/* normal quirks */
 	quirks = (unsigned long)id->driver_info;
+
+	if (quirks == IGNORE_DEVICE)
+		return -ENODEV;
+
 	num_rx_buf = (quirks == SINGLE_RX_URB) ? 1 : ACM_NR;
 
 	/* handle quirks deadly to normal probing*/
@@ -1519,15 +1504,9 @@ err_out:
 static int acm_reset_resume(struct usb_interface *intf)
 {
 	struct acm *acm = usb_get_intfdata(intf);
-	struct tty_struct *tty;
 
-	if (test_bit(ASYNCB_INITIALIZED, &acm->port.flags)) {
-		tty = tty_port_tty_get(&acm->port);
-		if (tty) {
-			tty_hangup(tty);
-			tty_kref_put(tty);
-		}
-	}
+	if (test_bit(ASYNCB_INITIALIZED, &acm->port.flags))
+		tty_port_tty_hangup(&acm->port, false);
 
 	return acm_resume(intf);
 }
@@ -1700,6 +1679,15 @@ static const struct usb_device_id acm_ids[] = {
 	.driver_info = NO_DATA_INTERFACE,
 	},
 
+#if IS_ENABLED(CONFIG_INPUT_IMS_PCU)
+	{ USB_DEVICE(0x04d8, 0x0082),	/* Application mode */
+	.driver_info = IGNORE_DEVICE,
+	},
+	{ USB_DEVICE(0x04d8, 0x0083),	/* Bootloader mode */
+	.driver_info = IGNORE_DEVICE,
+	},
+#endif
+
 	/* control interfaces without any protocol set */
 	{ USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
 		USB_CDC_PROTO_NONE) },
diff --git a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h
index 35ef887..0f76e4a 100644
--- a/drivers/usb/class/cdc-acm.h
+++ b/drivers/usb/class/cdc-acm.h
@@ -128,3 +128,4 @@ struct acm {
 #define NO_CAP_LINE			4
 #define NOT_A_MODEM			8
 #define NO_DATA_INTERFACE		16
+#define IGNORE_DEVICE			32
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c
index 122d056..8a230f0 100644
--- a/drivers/usb/class/cdc-wdm.c
+++ b/drivers/usb/class/cdc-wdm.c
@@ -13,6 +13,7 @@
  */
 #include <linux/kernel.h>
 #include <linux/errno.h>
+#include <linux/ioctl.h>
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
@@ -644,6 +645,22 @@ static int wdm_release(struct inode *inode, struct file *file)
 	return 0;
 }
 
+static long wdm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct wdm_device *desc = file->private_data;
+	int rv = 0;
+
+	switch (cmd) {
+	case IOCTL_WDM_MAX_COMMAND:
+		if (copy_to_user((void __user *)arg, &desc->wMaxCommand, sizeof(desc->wMaxCommand)))
+			rv = -EFAULT;
+		break;
+	default:
+		rv = -ENOTTY;
+	}
+	return rv;
+}
+
 static const struct file_operations wdm_fops = {
 	.owner =	THIS_MODULE,
 	.read =		wdm_read,
@@ -652,6 +669,8 @@ static const struct file_operations wdm_fops = {
 	.flush =	wdm_flush,
 	.release =	wdm_release,
 	.poll =		wdm_poll,
+	.unlocked_ioctl = wdm_ioctl,
+	.compat_ioctl = wdm_ioctl,
 	.llseek =	noop_llseek,
 };
 
diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig
index f70c1a1..7b7305e 100644
--- a/drivers/usb/core/Kconfig
+++ b/drivers/usb/core/Kconfig
@@ -27,6 +27,22 @@ config USB_ANNOUNCE_NEW_DEVICES
 comment "Miscellaneous USB options"
 	depends on USB
 
+config USB_DEFAULT_PERSIST
+	bool "Enable USB persist by default"
+	depends on USB
+	default y
+	help
+	  Say N here if you don't want USB power session persistance
+	  enabled by default.  If you say N it will make suspended USB
+	  devices that lose power get reenumerated as if they had been
+	  unplugged, causing any mounted filesystems to be lost.  The
+	  persist feature can still be enabled for individual devices
+	  through the power/persist sysfs node. See
+	  Documentation/usb/persist.txt for more info.
+
+	  If you have any questions about this, say Y here, only say N
+	  if you know exactly what you are doing.
+
 config USB_DYNAMIC_MINORS
 	bool "Dynamic USB minor allocation"
 	depends on USB
@@ -38,22 +54,6 @@ config USB_DYNAMIC_MINORS
 
 	  If you are unsure about this, say N here.
 
-config USB_SUSPEND
-	bool "USB runtime power management (autosuspend) and wakeup"
-	depends on USB && PM_RUNTIME
-	help
-	  If you say Y here, you can use driver calls or the sysfs
-	  "power/control" file to enable or disable autosuspend for
-	  individual USB peripherals (see
-	  Documentation/usb/power-management.txt for more details).
-
-	  Also, USB "remote wakeup" signaling is supported, whereby some
-	  USB devices (like keyboards and network adapters) can wake up
-	  their parent hub.  That wakeup cascades up the USB tree, and
-	  could wake the system from states like suspend-to-RAM.
-
-	  If you are unsure about this, say N here.
-
 config USB_OTG
 	bool "OTG support"
 	depends on USB
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index d938b2b..6eab440 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -1196,9 +1196,14 @@ done:
  *
  * This is the central routine for suspending USB devices.  It calls the
  * suspend methods for all the interface drivers in @udev and then calls
- * the suspend method for @udev itself.  If an error occurs at any stage,
- * all the interfaces which were suspended are resumed so that they remain
- * in the same state as the device.
+ * the suspend method for @udev itself.  When the routine is called in
+ * autosuspend, if an error occurs at any stage, all the interfaces
+ * which were suspended are resumed so that they remain in the same
+ * state as the device, but when called from system sleep, all error
+ * from suspend methods of interfaces and the non-root-hub device itself
+ * are simply ignored, so all suspended interfaces are only resumed
+ * to the device's state when @udev is root-hub and its suspend method
+ * returns failure.
  *
  * Autosuspend requests originating from a child device or an interface
  * driver may be made without the protection of @udev's device lock, but
@@ -1248,10 +1253,12 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
 
 	/* If the suspend failed, resume interfaces that did get suspended */
 	if (status != 0) {
-		msg.event ^= (PM_EVENT_SUSPEND | PM_EVENT_RESUME);
-		while (++i < n) {
-			intf = udev->actconfig->interface[i];
-			usb_resume_interface(udev, intf, msg, 0);
+		if (udev->actconfig) {
+			msg.event ^= (PM_EVENT_SUSPEND | PM_EVENT_RESUME);
+			while (++i < n) {
+				intf = udev->actconfig->interface[i];
+				usb_resume_interface(udev, intf, msg, 0);
+			}
 		}
 
 	/* If the suspend succeeded then prevent any more URB submissions
@@ -1407,7 +1414,7 @@ int usb_resume(struct device *dev, pm_message_t msg)
 
 #endif /* CONFIG_PM */
 
-#ifdef CONFIG_USB_SUSPEND
+#ifdef CONFIG_PM_RUNTIME
 
 /**
  * usb_enable_autosuspend - allow a USB device to be autosuspended
@@ -1775,7 +1782,7 @@ int usb_set_usb2_hardware_lpm(struct usb_device *udev, int enable)
 	return ret;
 }
 
-#endif /* CONFIG_USB_SUSPEND */
+#endif /* CONFIG_PM_RUNTIME */
 
 struct bus_type usb_bus_type = {
 	.name =		"usb",
diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c
index 271e761..acbfeb0 100644
--- a/drivers/usb/core/generic.c
+++ b/drivers/usb/core/generic.c
@@ -169,7 +169,7 @@ static int generic_probe(struct usb_device *udev)
 		c = usb_choose_configuration(udev);
 		if (c >= 0) {
 			err = usb_set_configuration(udev, c);
-			if (err) {
+			if (err && err != -ENODEV) {
 				dev_err(&udev->dev, "can't set config #%d, error %d\n",
 					c, err);
 				/* This need not be fatal.  The user can try to
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index 2b487d4..caeb8d6 100644
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -37,119 +37,123 @@
 
 /* PCI-based HCs are common, but plenty of non-PCI HCs are used too */
 
-#ifdef CONFIG_PM_SLEEP
-
-/* Coordinate handoffs between EHCI and companion controllers
- * during system resume
+/*
+ * Coordinate handoffs between EHCI and companion controllers
+ * during EHCI probing and system resume.
  */
 
-static DEFINE_MUTEX(companions_mutex);
+static DECLARE_RWSEM(companions_rwsem);
 
 #define CL_UHCI		PCI_CLASS_SERIAL_USB_UHCI
 #define CL_OHCI		PCI_CLASS_SERIAL_USB_OHCI
 #define CL_EHCI		PCI_CLASS_SERIAL_USB_EHCI
 
-enum companion_action {
-	SET_HS_COMPANION, CLEAR_HS_COMPANION, WAIT_FOR_COMPANIONS
-};
+static inline int is_ohci_or_uhci(struct pci_dev *pdev)
+{
+	return pdev->class == CL_OHCI || pdev->class == CL_UHCI;
+}
+
+typedef void (*companion_fn)(struct pci_dev *pdev, struct usb_hcd *hcd,
+		struct pci_dev *companion, struct usb_hcd *companion_hcd);
 
-static void companion_common(struct pci_dev *pdev, struct usb_hcd *hcd,
-		enum companion_action action)
+/* Iterate over PCI devices in the same slot as pdev and call fn for each */
+static void for_each_companion(struct pci_dev *pdev, struct usb_hcd *hcd,
+		companion_fn fn)
 {
 	struct pci_dev		*companion;
 	struct usb_hcd		*companion_hcd;
 	unsigned int		slot = PCI_SLOT(pdev->devfn);
 
-	/* Iterate through other PCI functions in the same slot.
-	 * If pdev is OHCI or UHCI then we are looking for EHCI, and
-	 * vice versa.
+	/*
+	 * Iterate through other PCI functions in the same slot.
+	 * If the function's drvdata isn't set then it isn't bound to
+	 * a USB host controller driver, so skip it.
 	 */
 	companion = NULL;
 	for_each_pci_dev(companion) {
 		if (companion->bus != pdev->bus ||
 				PCI_SLOT(companion->devfn) != slot)
 			continue;
-
 		companion_hcd = pci_get_drvdata(companion);
 		if (!companion_hcd)
 			continue;
-
-		/* For SET_HS_COMPANION, store a pointer to the EHCI bus in
-		 * the OHCI/UHCI companion bus structure.
-		 * For CLEAR_HS_COMPANION, clear the pointer to the EHCI bus
-		 * in the OHCI/UHCI companion bus structure.
-		 * For WAIT_FOR_COMPANIONS, wait until the OHCI/UHCI
-		 * companion controllers have fully resumed.
-		 */
-
-		if ((pdev->class == CL_OHCI || pdev->class == CL_UHCI) &&
-				companion->class == CL_EHCI) {
-			/* action must be SET_HS_COMPANION */
-			dev_dbg(&companion->dev, "HS companion for %s\n",
-					dev_name(&pdev->dev));
-			hcd->self.hs_companion = &companion_hcd->self;
-
-		} else if (pdev->class == CL_EHCI &&
-				(companion->class == CL_OHCI ||
-				companion->class == CL_UHCI)) {
-			switch (action) {
-			case SET_HS_COMPANION:
-				dev_dbg(&pdev->dev, "HS companion for %s\n",
-						dev_name(&companion->dev));
-				companion_hcd->self.hs_companion = &hcd->self;
-				break;
-			case CLEAR_HS_COMPANION:
-				companion_hcd->self.hs_companion = NULL;
-				break;
-			case WAIT_FOR_COMPANIONS:
-				device_pm_wait_for_dev(&pdev->dev,
-						&companion->dev);
-				break;
-			}
-		}
+		fn(pdev, hcd, companion, companion_hcd);
 	}
 }
 
-static void set_hs_companion(struct pci_dev *pdev, struct usb_hcd *hcd)
+/*
+ * We're about to add an EHCI controller, which will unceremoniously grab
+ * all the port connections away from its companions.  To prevent annoying
+ * error messages, lock the companion's root hub and gracefully unconfigure
+ * it beforehand.  Leave it locked until the EHCI controller is all set.
+ */
+static void ehci_pre_add(struct pci_dev *pdev, struct usb_hcd *hcd,
+		struct pci_dev *companion, struct usb_hcd *companion_hcd)
 {
-	mutex_lock(&companions_mutex);
-	dev_set_drvdata(&pdev->dev, hcd);
-	companion_common(pdev, hcd, SET_HS_COMPANION);
-	mutex_unlock(&companions_mutex);
+	struct usb_device *udev;
+
+	if (is_ohci_or_uhci(companion)) {
+		udev = companion_hcd->self.root_hub;
+		usb_lock_device(udev);
+		usb_set_configuration(udev, 0);
+	}
 }
 
-static void clear_hs_companion(struct pci_dev *pdev, struct usb_hcd *hcd)
+/*
+ * Adding the EHCI controller has either succeeded or failed.  Set the
+ * companion pointer accordingly, and in either case, reconfigure and
+ * unlock the root hub.
+ */
+static void ehci_post_add(struct pci_dev *pdev, struct usb_hcd *hcd,
+		struct pci_dev *companion, struct usb_hcd *companion_hcd)
 {
-	mutex_lock(&companions_mutex);
-	dev_set_drvdata(&pdev->dev, NULL);
+	struct usb_device *udev;
 
-	/* If pdev is OHCI or UHCI, just clear its hs_companion pointer */
-	if (pdev->class == CL_OHCI || pdev->class == CL_UHCI)
-		hcd->self.hs_companion = NULL;
+	if (is_ohci_or_uhci(companion)) {
+		if (dev_get_drvdata(&pdev->dev)) {	/* Succeeded */
+			dev_dbg(&pdev->dev, "HS companion for %s\n",
+					dev_name(&companion->dev));
+			companion_hcd->self.hs_companion = &hcd->self;
+		}
+		udev = companion_hcd->self.root_hub;
+		usb_set_configuration(udev, 1);
+		usb_unlock_device(udev);
+	}
+}
 
-	/* Otherwise search for companion buses and clear their pointers */
-	else
-		companion_common(pdev, hcd, CLEAR_HS_COMPANION);
-	mutex_unlock(&companions_mutex);
+/*
+ * We just added a non-EHCI controller.  Find the EHCI controller to
+ * which it is a companion, and store a pointer to the bus structure.
+ */
+static void non_ehci_add(struct pci_dev *pdev, struct usb_hcd *hcd,
+		struct pci_dev *companion, struct usb_hcd *companion_hcd)
+{
+	if (is_ohci_or_uhci(pdev) && companion->class == CL_EHCI) {
+		dev_dbg(&pdev->dev, "FS/LS companion for %s\n",
+				dev_name(&companion->dev));
+		hcd->self.hs_companion = &companion_hcd->self;
+	}
 }
 
-static void wait_for_companions(struct pci_dev *pdev, struct usb_hcd *hcd)
+/* We are removing an EHCI controller.  Clear the companions' pointers. */
+static void ehci_remove(struct pci_dev *pdev, struct usb_hcd *hcd,
+		struct pci_dev *companion, struct usb_hcd *companion_hcd)
 {
-	/* Only EHCI controllers need to wait.
-	 * No locking is needed because a controller cannot be resumed
-	 * while one of its companions is getting unbound.
-	 */
-	if (pdev->class == CL_EHCI)
-		companion_common(pdev, hcd, WAIT_FOR_COMPANIONS);
+	if (is_ohci_or_uhci(companion))
+		companion_hcd->self.hs_companion = NULL;
 }
 
-#else /* !CONFIG_PM_SLEEP */
+#ifdef	CONFIG_PM
 
-static inline void set_hs_companion(struct pci_dev *d, struct usb_hcd *h) {}
-static inline void clear_hs_companion(struct pci_dev *d, struct usb_hcd *h) {}
-static inline void wait_for_companions(struct pci_dev *d, struct usb_hcd *h) {}
+/* An EHCI controller must wait for its companions before resuming. */
+static void ehci_wait_for_companions(struct pci_dev *pdev, struct usb_hcd *hcd,
+		struct pci_dev *companion, struct usb_hcd *companion_hcd)
+{
+	if (is_ohci_or_uhci(companion))
+		device_pm_wait_for_dev(&pdev->dev, &companion->dev);
+}
 
-#endif /* !CONFIG_PM_SLEEP */
+#endif	/* CONFIG_PM */
 
 /*-------------------------------------------------------------------------*/
 
@@ -217,7 +221,7 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 				driver->description)) {
 			dev_dbg(&dev->dev, "controller already in use\n");
 			retval = -EBUSY;
-			goto clear_companion;
+			goto put_hcd;
 		}
 		hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
 		if (hcd->regs == NULL) {
@@ -244,16 +248,35 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 		if (region == PCI_ROM_RESOURCE) {
 			dev_dbg(&dev->dev, "no i/o regions available\n");
 			retval = -EBUSY;
-			goto clear_companion;
+			goto put_hcd;
 		}
 	}
 
 	pci_set_master(dev);
 
-	retval = usb_add_hcd(hcd, hcd_irq, IRQF_SHARED);
+	/* Note: dev_set_drvdata must be called while holding the rwsem */
+	if (dev->class == CL_EHCI) {
+		down_write(&companions_rwsem);
+		dev_set_drvdata(&dev->dev, hcd);
+		for_each_companion(dev, hcd, ehci_pre_add);
+		retval = usb_add_hcd(hcd, hcd_irq, IRQF_SHARED);
+		if (retval != 0)
+			dev_set_drvdata(&dev->dev, NULL);
+		for_each_companion(dev, hcd, ehci_post_add);
+		up_write(&companions_rwsem);
+	} else {
+		down_read(&companions_rwsem);
+		dev_set_drvdata(&dev->dev, hcd);
+		retval = usb_add_hcd(hcd, hcd_irq, IRQF_SHARED);
+		if (retval != 0)
+			dev_set_drvdata(&dev->dev, NULL);
+		else
+			for_each_companion(dev, hcd, non_ehci_add);
+		up_read(&companions_rwsem);
+	}
+
 	if (retval != 0)
 		goto unmap_registers;
-	set_hs_companion(dev, hcd);
 
 	if (pci_dev_run_wake(dev))
 		pm_runtime_put_noidle(&dev->dev);
@@ -266,8 +289,7 @@ release_mem_region:
 		release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 	} else
 		release_region(hcd->rsrc_start, hcd->rsrc_len);
-clear_companion:
-	clear_hs_companion(dev, hcd);
+put_hcd:
 	usb_put_hcd(hcd);
 disable_pci:
 	pci_disable_device(dev);
@@ -310,14 +332,29 @@ void usb_hcd_pci_remove(struct pci_dev *dev)
 	usb_hcd_irq(0, hcd);
 	local_irq_enable();
 
-	usb_remove_hcd(hcd);
+	/* Note: dev_set_drvdata must be called while holding the rwsem */
+	if (dev->class == CL_EHCI) {
+		down_write(&companions_rwsem);
+		for_each_companion(dev, hcd, ehci_remove);
+		usb_remove_hcd(hcd);
+		dev_set_drvdata(&dev->dev, NULL);
+		up_write(&companions_rwsem);
+	} else {
+		/* Not EHCI; just clear the companion pointer */
+		down_read(&companions_rwsem);
+		hcd->self.hs_companion = NULL;
+		usb_remove_hcd(hcd);
+		dev_set_drvdata(&dev->dev, NULL);
+		up_read(&companions_rwsem);
+	}
+
 	if (hcd->driver->flags & HCD_MEMORY) {
 		iounmap(hcd->regs);
 		release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 	} else {
 		release_region(hcd->rsrc_start, hcd->rsrc_len);
 	}
-	clear_hs_companion(dev, hcd);
+
 	usb_put_hcd(hcd);
 	pci_disable_device(dev);
 }
@@ -463,8 +500,15 @@ static int resume_common(struct device *dev, int event)
 	pci_set_master(pci_dev);
 
 	if (hcd->driver->pci_resume && !HCD_DEAD(hcd)) {
-		if (event != PM_EVENT_AUTO_RESUME)
-			wait_for_companions(pci_dev, hcd);
+
+		/*
+		 * Only EHCI controllers have to wait for their companions.
+		 * No locking is needed because PCI controller drivers do not
+		 * get unbound during system resume.
+		 */
+		if (pci_dev->class == CL_EHCI && event != PM_EVENT_AUTO_RESUME)
+			for_each_companion(pci_dev, hcd,
+					ehci_wait_for_companions);
 
 		retval = hcd->driver->pci_resume(hcd,
 				event == PM_EVENT_RESTORE);
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index f9ec44c..d53547d 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -2125,7 +2125,7 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg)
 
 #endif	/* CONFIG_PM */
 
-#ifdef	CONFIG_USB_SUSPEND
+#ifdef	CONFIG_PM_RUNTIME
 
 /* Workqueue routine for root-hub remote wakeup */
 static void hcd_resume_work(struct work_struct *work)
@@ -2160,7 +2160,7 @@ void usb_hcd_resume_root_hub (struct usb_hcd *hcd)
 }
 EXPORT_SYMBOL_GPL(usb_hcd_resume_root_hub);
 
-#endif	/* CONFIG_USB_SUSPEND */
+#endif	/* CONFIG_PM_RUNTIME */
 
 /*-------------------------------------------------------------------------*/
 
@@ -2336,7 +2336,7 @@ struct usb_hcd *usb_create_shared_hcd(const struct hc_driver *driver,
 	init_timer(&hcd->rh_timer);
 	hcd->rh_timer.function = rh_timer_func;
 	hcd->rh_timer.data = (unsigned long) hcd;
-#ifdef CONFIG_USB_SUSPEND
+#ifdef CONFIG_PM_RUNTIME
 	INIT_WORK(&hcd->wakeup_work, hcd_resume_work);
 #endif
 
@@ -2590,7 +2590,7 @@ error_create_attr_group:
 	hcd->rh_registered = 0;
 	spin_unlock_irq(&hcd_root_hub_lock);
 
-#ifdef CONFIG_USB_SUSPEND
+#ifdef CONFIG_PM_RUNTIME
 	cancel_work_sync(&hcd->wakeup_work);
 #endif
 	mutex_lock(&usb_bus_list_lock);
@@ -2645,7 +2645,7 @@ void usb_remove_hcd(struct usb_hcd *hcd)
 	hcd->rh_registered = 0;
 	spin_unlock_irq (&hcd_root_hub_lock);
 
-#ifdef CONFIG_USB_SUSPEND
+#ifdef CONFIG_PM_RUNTIME
 	cancel_work_sync(&hcd->wakeup_work);
 #endif
 
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 5480352..feef935 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -555,8 +555,9 @@ static int hub_port_status(struct usb_hub *hub, int port1,
 	mutex_lock(&hub->status_mutex);
 	ret = get_port_status(hub->hdev, port1, &hub->status->port);
 	if (ret < 4) {
-		dev_err(hub->intfdev,
-			"%s failed (err = %d)\n", __func__, ret);
+		if (ret != -ENODEV)
+			dev_err(hub->intfdev,
+				"%s failed (err = %d)\n", __func__, ret);
 		if (ret >= 0)
 			ret = -EIO;
 	} else {
@@ -699,7 +700,7 @@ static void hub_tt_work(struct work_struct *work)
 		/* drop lock so HCD can concurrently report other TT errors */
 		spin_unlock_irqrestore (&hub->tt.lock, flags);
 		status = hub_clear_tt_buffer (hdev, clear->devinfo, clear->tt);
-		if (status)
+		if (status && status != -ENODEV)
 			dev_err (&hdev->dev,
 				"clear tt %d (%04x) error %d\n",
 				clear->tt, clear->devinfo, status);
@@ -837,10 +838,11 @@ static int hub_hub_status(struct usb_hub *hub,
 
 	mutex_lock(&hub->status_mutex);
 	ret = get_hub_status(hub->hdev, &hub->status->hub);
-	if (ret < 0)
-		dev_err (hub->intfdev,
-			"%s failed (err = %d)\n", __func__, ret);
-	else {
+	if (ret < 0) {
+		if (ret != -ENODEV)
+			dev_err(hub->intfdev,
+				"%s failed (err = %d)\n", __func__, ret);
+	} else {
 		*status = le16_to_cpu(hub->status->hub.wHubStatus);
 		*change = le16_to_cpu(hub->status->hub.wHubChange); 
 		ret = 0;
@@ -877,11 +879,8 @@ static int hub_usb3_port_disable(struct usb_hub *hub, int port1)
 		return -EINVAL;
 
 	ret = hub_set_port_link_state(hub, port1, USB_SS_PORT_LS_SS_DISABLED);
-	if (ret) {
-		dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n",
-				port1, ret);
+	if (ret)
 		return ret;
-	}
 
 	/* Wait for the link to enter the disabled state. */
 	for (total_time = 0; ; total_time += HUB_DEBOUNCE_STEP) {
@@ -918,7 +917,7 @@ static int hub_port_disable(struct usb_hub *hub, int port1, int set_state)
 			ret = usb_clear_port_feature(hdev, port1,
 					USB_PORT_FEAT_ENABLE);
 	}
-	if (ret)
+	if (ret && ret != -ENODEV)
 		dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n",
 				port1, ret);
 	return ret;
@@ -1317,6 +1316,10 @@ static int hub_configure(struct usb_hub *hub,
 		message = "hub has too many ports!";
 		ret = -ENODEV;
 		goto fail;
+	} else if (hub->descriptor->bNbrPorts == 0) {
+		message = "hub doesn't have any ports!";
+		ret = -ENODEV;
+		goto fail;
 	}
 
 	hdev->maxchild = hub->descriptor->bNbrPorts;
@@ -2192,8 +2195,9 @@ static int usb_enumerate_device(struct usb_device *udev)
 	if (udev->config == NULL) {
 		err = usb_get_configuration(udev);
 		if (err < 0) {
-			dev_err(&udev->dev, "can't read configurations, error %d\n",
-				err);
+			if (err != -ENODEV)
+				dev_err(&udev->dev, "can't read configurations, error %d\n",
+						err);
 			return err;
 		}
 	}
@@ -2640,14 +2644,16 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
 		status = set_port_feature(hub->hdev, port1, (warm ?
 					USB_PORT_FEAT_BH_PORT_RESET :
 					USB_PORT_FEAT_RESET));
-		if (status) {
+		if (status == -ENODEV) {
+			;	/* The hub is gone */
+		} else if (status) {
 			dev_err(hub->intfdev,
 					"cannot %sreset port %d (err = %d)\n",
 					warm ? "warm " : "", port1, status);
 		} else {
 			status = hub_port_wait_reset(hub, port1, udev, delay,
 								warm);
-			if (status && status != -ENOTCONN)
+			if (status && status != -ENOTCONN && status != -ENODEV)
 				dev_dbg(hub->intfdev,
 						"port_wait_reset: err = %d\n",
 						status);
@@ -2821,7 +2827,7 @@ void usb_enable_ltm(struct usb_device *udev)
 }
 EXPORT_SYMBOL_GPL(usb_enable_ltm);
 
-#ifdef	CONFIG_USB_SUSPEND
+#ifdef	CONFIG_PM
 /*
  * usb_disable_function_remotewakeup - disable usb3.0
  * device's function remote wakeup
@@ -2880,9 +2886,11 @@ static int usb_disable_function_remotewakeup(struct usb_device *udev)
  * Linux (2.6) currently has NO mechanisms to initiate that:  no khubd
  * timer, no SRP, no requests through sysfs.
  *
- * If CONFIG_USB_SUSPEND isn't enabled, devices only really suspend when
- * the root hub for their bus goes into global suspend ... so we don't
- * (falsely) update the device power state to say it suspended.
+ * If Runtime PM isn't enabled or used, non-SuperSpeed devices really get
+ * suspended only when their bus goes into global suspend (i.e., the root
+ * hub is suspended).  Nevertheless, we change @udev->state to
+ * USB_STATE_SUSPENDED as this is the device's "logical" state.  The actual
+ * upstream port setting is stored in @udev->port_is_suspended.
  *
  * Returns 0 on success, else negative errno.
  */
@@ -2893,6 +2901,7 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
 	enum pm_qos_flags_status pm_qos_stat;
 	int		port1 = udev->portnum;
 	int		status;
+	bool		really_suspend = true;
 
 	/* enable remote wakeup when appropriate; this lets the device
 	 * wake up the upstream hub (including maybe the root hub).
@@ -2949,9 +2958,19 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
 	/* see 7.1.7.6 */
 	if (hub_is_superspeed(hub->hdev))
 		status = hub_set_port_link_state(hub, port1, USB_SS_PORT_LS_U3);
-	else
+	else if (PMSG_IS_AUTO(msg))
 		status = set_port_feature(hub->hdev, port1,
 						USB_PORT_FEAT_SUSPEND);
+	/*
+	 * For system suspend, we do not need to enable the suspend feature
+	 * on individual USB-2 ports.  The devices will automatically go
+	 * into suspend a few ms after the root hub stops sending packets.
+	 * The USB 2.0 spec calls this "global suspend".
+	 */
+	else {
+		really_suspend = false;
+		status = 0;
+	}
 	if (status) {
 		dev_dbg(hub->intfdev, "can't suspend port %d, status %d\n",
 				port1, status);
@@ -2987,8 +3006,10 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
 				(PMSG_IS_AUTO(msg) ? "auto-" : ""),
 				udev->do_remote_wakeup);
 		usb_set_device_state(udev, USB_STATE_SUSPENDED);
-		udev->port_is_suspended = 1;
-		msleep(10);
+		if (really_suspend) {
+			udev->port_is_suspended = 1;
+			msleep(10);
+		}
 	}
 
 	/*
@@ -3226,6 +3247,10 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)
 	return status;
 }
 
+#endif	/* CONFIG_PM */
+
+#ifdef	CONFIG_PM_RUNTIME
+
 /* caller has locked udev */
 int usb_remote_wakeup(struct usb_device *udev)
 {
@@ -3242,38 +3267,6 @@ int usb_remote_wakeup(struct usb_device *udev)
 	return status;
 }
 
-#else	/* CONFIG_USB_SUSPEND */
-
-/* When CONFIG_USB_SUSPEND isn't set, we never suspend or resume any ports. */
-
-int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
-{
-	return 0;
-}
-
-/* However we may need to do a reset-resume */
-
-int usb_port_resume(struct usb_device *udev, pm_message_t msg)
-{
-	struct usb_hub	*hub = usb_hub_to_struct_hub(udev->parent);
-	int		port1 = udev->portnum;
-	int		status;
-	u16		portchange, portstatus;
-
-	status = hub_port_status(hub, port1, &portstatus, &portchange);
-	status = check_port_resume_type(udev,
-			hub, port1, status, portchange, portstatus);
-
-	if (status) {
-		dev_dbg(&udev->dev, "can't resume, status %d\n", status);
-		hub_port_logical_disconnect(hub, port1);
-	} else if (udev->reset_resume) {
-		dev_dbg(&udev->dev, "reset-resume\n");
-		status = usb_reset_and_verify_device(udev);
-	}
-	return status;
-}
-
 #endif
 
 static int check_ports_changed(struct usb_hub *hub)
@@ -4090,9 +4083,9 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
 				goto fail;
 			}
 			if (r) {
-				dev_err(&udev->dev,
-					"device descriptor read/64, error %d\n",
-					r);
+				if (r != -ENODEV)
+					dev_err(&udev->dev, "device descriptor read/64, error %d\n",
+							r);
 				retval = -EMSGSIZE;
 				continue;
 			}
@@ -4112,9 +4105,9 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
 				msleep(200);
 			}
 			if (retval < 0) {
-				dev_err(&udev->dev,
-					"device not accepting address %d, error %d\n",
-					devnum, retval);
+				if (retval != -ENODEV)
+					dev_err(&udev->dev, "device not accepting address %d, error %d\n",
+							devnum, retval);
 				goto fail;
 			}
 			if (udev->speed == USB_SPEED_SUPER) {
@@ -4136,7 +4129,8 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
 
 		retval = usb_get_device_descriptor(udev, 8);
 		if (retval < 8) {
-			dev_err(&udev->dev,
+			if (retval != -ENODEV)
+				dev_err(&udev->dev,
 					"device descriptor read/8, error %d\n",
 					retval);
 			if (retval >= 0)
@@ -4190,8 +4184,9 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
   
 	retval = usb_get_device_descriptor(udev, USB_DT_DEVICE_SIZE);
 	if (retval < (signed)sizeof(udev->descriptor)) {
-		dev_err(&udev->dev, "device descriptor read/all, error %d\n",
-			retval);
+		if (retval != -ENODEV)
+			dev_err(&udev->dev, "device descriptor read/all, error %d\n",
+					retval);
 		if (retval >= 0)
 			retval = -ENOMSG;
 		goto fail;
@@ -4333,7 +4328,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
 		if (portstatus & USB_PORT_STAT_ENABLE) {
 			status = 0;		/* Nothing to do */
 
-#ifdef CONFIG_USB_SUSPEND
+#ifdef CONFIG_PM_RUNTIME
 		} else if (udev->state == USB_STATE_SUSPENDED &&
 				udev->persist_enabled) {
 			/* For a suspended device, treat this as a
@@ -4373,7 +4368,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
 				USB_PORT_STAT_C_ENABLE)) {
 		status = hub_port_debounce_be_stable(hub, port1);
 		if (status < 0) {
-			if (printk_ratelimit())
+			if (status != -ENODEV && printk_ratelimit())
 				dev_err(hub_dev, "connect-debounce failed, "
 						"port %d disabled\n", port1);
 			portstatus &= ~USB_PORT_STAT_CONNECTION;
@@ -4402,6 +4397,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
 	else
 		unit_load = 100;
 
+	status = 0;
 	for (i = 0; i < SET_CONFIG_TRIES; i++) {
 
 		/* reallocate for each attempt, since references
@@ -4526,9 +4522,11 @@ loop:
 	}
 	if (hub->hdev->parent ||
 			!hcd->driver->port_handed_over ||
-			!(hcd->driver->port_handed_over)(hcd, port1))
-		dev_err(hub_dev, "unable to enumerate USB device on port %d\n",
-				port1);
+			!(hcd->driver->port_handed_over)(hcd, port1)) {
+		if (status != -ENOTCONN && status != -ENODEV)
+			dev_err(hub_dev, "unable to enumerate USB device on port %d\n",
+					port1);
+	}
  
 done:
 	hub_port_disable(hub, port1, 1);
diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c
index 797f9d5..b8bad29 100644
--- a/drivers/usb/core/port.c
+++ b/drivers/usb/core/port.c
@@ -67,11 +67,10 @@ static void usb_port_device_release(struct device *dev)
 {
 	struct usb_port *port_dev = to_usb_port(dev);
 
-	dev_pm_qos_hide_flags(dev);
 	kfree(port_dev);
 }
 
-#ifdef CONFIG_USB_SUSPEND
+#ifdef CONFIG_PM_RUNTIME
 static int usb_port_runtime_resume(struct device *dev)
 {
 	struct usb_port *port_dev = to_usb_port(dev);
@@ -139,7 +138,7 @@ static int usb_port_runtime_suspend(struct device *dev)
 #endif
 
 static const struct dev_pm_ops usb_port_pm_ops = {
-#ifdef CONFIG_USB_SUSPEND
+#ifdef CONFIG_PM_RUNTIME
 	.runtime_suspend =	usb_port_runtime_suspend,
 	.runtime_resume =	usb_port_runtime_resume,
 	.runtime_idle =		pm_generic_runtime_idle,
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
index 3113c1d..ab5638d 100644
--- a/drivers/usb/core/quirks.c
+++ b/drivers/usb/core/quirks.c
@@ -201,20 +201,14 @@ void usb_detect_quirks(struct usb_device *udev)
 		dev_dbg(&udev->dev, "USB quirks for this device: %x\n",
 			udev->quirks);
 
-	/* For the present, all devices default to USB-PERSIST enabled */
-#if 0		/* was: #ifdef CONFIG_PM */
-	/* Hubs are automatically enabled for USB-PERSIST */
-	if (udev->descriptor.bDeviceClass == USB_CLASS_HUB)
+#ifdef CONFIG_USB_DEFAULT_PERSIST
+	if (!(udev->quirks & USB_QUIRK_RESET))
 		udev->persist_enabled = 1;
-
 #else
-	/* In the absence of PM, we can safely enable USB-PERSIST
-	 * for all devices.  It will affect things like hub resets
-	 * and EMF-related port disables.
-	 */
-	if (!(udev->quirks & USB_QUIRK_RESET))
+	/* Hubs are automatically enabled for USB-PERSIST */
+	if (udev->descriptor.bDeviceClass == USB_CLASS_HUB)
 		udev->persist_enabled = 1;
-#endif	/* CONFIG_PM */
+#endif	/* CONFIG_USB_DEFAULT_PERSIST */
 }
 
 void usb_detect_interface_quirks(struct usb_device *udev)
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
index 3f81a3d..aa38db4 100644
--- a/drivers/usb/core/sysfs.c
+++ b/drivers/usb/core/sysfs.c
@@ -338,7 +338,7 @@ static void remove_persist_attributes(struct device *dev)
 
 #endif	/* CONFIG_PM */
 
-#ifdef	CONFIG_USB_SUSPEND
+#ifdef	CONFIG_PM_RUNTIME
 
 static ssize_t
 show_connected_duration(struct device *dev, struct device_attribute *attr,
@@ -544,7 +544,7 @@ static void remove_power_attributes(struct device *dev)
 #define add_power_attributes(dev)	0
 #define remove_power_attributes(dev)	do {} while (0)
 
-#endif	/* CONFIG_USB_SUSPEND */
+#endif	/* CONFIG_PM_RUNTIME */
 
 
 /* Descriptor fields */
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index e0d9d94..16927fa 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -683,10 +683,13 @@ EXPORT_SYMBOL_GPL(usb_kill_urb);
 void usb_poison_urb(struct urb *urb)
 {
 	might_sleep();
-	if (!(urb && urb->dev && urb->ep))
+	if (!urb)
 		return;
 	atomic_inc(&urb->reject);
 
+	if (!urb->dev || !urb->ep)
+		return;
+
 	usb_hcd_unlink_urb(urb, -ENOENT);
 	wait_event(usb_kill_urb_queue, atomic_read(&urb->use_count) == 0);
 }
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index f81b925..03eb7ae 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -49,7 +49,7 @@ const char *usbcore_name = "usbcore";
 
 static bool nousb;	/* Disable USB when built into kernel image */
 
-#ifdef	CONFIG_USB_SUSPEND
+#ifdef	CONFIG_PM_RUNTIME
 static int usb_autosuspend_delay = 2;		/* Default delay value,
 						 * in seconds */
 module_param_named(autosuspend, usb_autosuspend_delay, int, 0644);
@@ -307,7 +307,7 @@ static const struct dev_pm_ops usb_device_pm_ops = {
 	.thaw =		usb_dev_thaw,
 	.poweroff =	usb_dev_poweroff,
 	.restore =	usb_dev_restore,
-#ifdef CONFIG_USB_SUSPEND
+#ifdef CONFIG_PM_RUNTIME
 	.runtime_suspend =	usb_runtime_suspend,
 	.runtime_resume =	usb_runtime_resume,
 	.runtime_idle =		usb_runtime_idle,
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index a7f20bd..8238577 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -93,7 +93,7 @@ static inline int usb_port_resume(struct usb_device *udev, pm_message_t msg)
 
 #endif
 
-#ifdef CONFIG_USB_SUSPEND
+#ifdef CONFIG_PM_RUNTIME
 
 extern void usb_autosuspend_device(struct usb_device *udev);
 extern int usb_autoresume_device(struct usb_device *udev);
diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
index 68e9a2c..ea5ee9c 100644
--- a/drivers/usb/dwc3/Kconfig
+++ b/drivers/usb/dwc3/Kconfig
@@ -1,7 +1,6 @@
 config USB_DWC3
 	tristate "DesignWare USB3 DRD Core Support"
 	depends on (USB || USB_GADGET) && GENERIC_HARDIRQS
-	select USB_OTG_UTILS
 	select USB_XHCI_PLATFORM if USB_SUPPORT && USB_XHCI_HCD
 	help
 	  Say Y or M here if your system has a Dual Role SuperSpeed
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index ffa6b00..c35d49d 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -140,7 +140,8 @@ static void dwc3_free_one_event_buffer(struct dwc3 *dwc,
  * Returns a pointer to the allocated event buffer structure on success
  * otherwise ERR_PTR(errno).
  */
-static struct dwc3_event_buffer *dwc3_alloc_one_event_buffer(struct dwc3 *dwc, unsigned length)
+static struct dwc3_event_buffer *dwc3_alloc_one_event_buffer(struct dwc3 *dwc,
+		unsigned length)
 {
 	struct dwc3_event_buffer	*evt;
 
@@ -259,6 +260,17 @@ static void dwc3_event_buffers_cleanup(struct dwc3 *dwc)
 	}
 }
 
+static void dwc3_core_num_eps(struct dwc3 *dwc)
+{
+	struct dwc3_hwparams	*parms = &dwc->hwparams;
+
+	dwc->num_in_eps = DWC3_NUM_IN_EPS(parms);
+	dwc->num_out_eps = DWC3_NUM_EPS(parms) - dwc->num_in_eps;
+
+	dev_vdbg(dwc->dev, "found %d IN and %d OUT endpoints\n",
+			dwc->num_in_eps, dwc->num_out_eps);
+}
+
 static void dwc3_cache_hwparams(struct dwc3 *dwc)
 {
 	struct dwc3_hwparams	*parms = &dwc->hwparams;
@@ -335,13 +347,9 @@ static int dwc3_core_init(struct dwc3 *dwc)
 	if (dwc->revision < DWC3_REVISION_190A)
 		reg |= DWC3_GCTL_U2RSTECN;
 
-	dwc3_writel(dwc->regs, DWC3_GCTL, reg);
+	dwc3_core_num_eps(dwc);
 
-	ret = dwc3_event_buffers_setup(dwc);
-	if (ret) {
-		dev_err(dwc->dev, "failed to setup event buffers\n");
-		goto err0;
-	}
+	dwc3_writel(dwc->regs, DWC3_GCTL, reg);
 
 	return 0;
 
@@ -351,8 +359,6 @@ err0:
 
 static void dwc3_core_exit(struct dwc3 *dwc)
 {
-	dwc3_event_buffers_cleanup(dwc);
-
 	usb_phy_shutdown(dwc->usb2_phy);
 	usb_phy_shutdown(dwc->usb3_phy);
 }
@@ -428,12 +434,32 @@ static int dwc3_probe(struct platform_device *pdev)
 		dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
 	}
 
-	if (IS_ERR_OR_NULL(dwc->usb2_phy)) {
+	if (IS_ERR(dwc->usb2_phy)) {
+		ret = PTR_ERR(dwc->usb2_phy);
+
+		/*
+		 * if -ENXIO is returned, it means PHY layer wasn't
+		 * enabled, so it makes no sense to return -EPROBE_DEFER
+		 * in that case, since no PHY driver will ever probe.
+		 */
+		if (ret == -ENXIO)
+			return ret;
+
 		dev_err(dev, "no usb2 phy configured\n");
 		return -EPROBE_DEFER;
 	}
 
-	if (IS_ERR_OR_NULL(dwc->usb3_phy)) {
+	if (IS_ERR(dwc->usb3_phy)) {
+		ret = PTR_ERR(dwc->usb2_phy);
+
+		/*
+		 * if -ENXIO is returned, it means PHY layer wasn't
+		 * enabled, so it makes no sense to return -EPROBE_DEFER
+		 * in that case, since no PHY driver will ever probe.
+		 */
+		if (ret == -ENXIO)
+			return ret;
+
 		dev_err(dev, "no usb3 phy configured\n");
 		return -EPROBE_DEFER;
 	}
@@ -448,6 +474,10 @@ static int dwc3_probe(struct platform_device *pdev)
 	dwc->regs_size	= resource_size(res);
 	dwc->dev	= dev;
 
+	dev->dma_mask	= dev->parent->dma_mask;
+	dev->dma_parms	= dev->parent->dma_parms;
+	dma_set_coherent_mask(dev, dev->parent->coherent_dma_mask);
+
 	if (!strncmp("super", maximum_speed, 5))
 		dwc->maximum_speed = DWC3_DCFG_SUPERSPEED;
 	else if (!strncmp("high", maximum_speed, 4))
@@ -480,7 +510,18 @@ static int dwc3_probe(struct platform_device *pdev)
 		goto err0;
 	}
 
-	mode = DWC3_MODE(dwc->hwparams.hwparams0);
+	ret = dwc3_event_buffers_setup(dwc);
+	if (ret) {
+		dev_err(dwc->dev, "failed to setup event buffers\n");
+		goto err1;
+	}
+
+	if (IS_ENABLED(CONFIG_USB_DWC3_HOST))
+		mode = DWC3_MODE_HOST;
+	else if (IS_ENABLED(CONFIG_USB_DWC3_GADGET))
+		mode = DWC3_MODE_DEVICE;
+	else
+		mode = DWC3_MODE_DRD;
 
 	switch (mode) {
 	case DWC3_MODE_DEVICE:
@@ -488,7 +529,7 @@ static int dwc3_probe(struct platform_device *pdev)
 		ret = dwc3_gadget_init(dwc);
 		if (ret) {
 			dev_err(dev, "failed to initialize gadget\n");
-			goto err1;
+			goto err2;
 		}
 		break;
 	case DWC3_MODE_HOST:
@@ -496,7 +537,7 @@ static int dwc3_probe(struct platform_device *pdev)
 		ret = dwc3_host_init(dwc);
 		if (ret) {
 			dev_err(dev, "failed to initialize host\n");
-			goto err1;
+			goto err2;
 		}
 		break;
 	case DWC3_MODE_DRD:
@@ -504,32 +545,32 @@ static int dwc3_probe(struct platform_device *pdev)
 		ret = dwc3_host_init(dwc);
 		if (ret) {
 			dev_err(dev, "failed to initialize host\n");
-			goto err1;
+			goto err2;
 		}
 
 		ret = dwc3_gadget_init(dwc);
 		if (ret) {
 			dev_err(dev, "failed to initialize gadget\n");
-			goto err1;
+			goto err2;
 		}
 		break;
 	default:
 		dev_err(dev, "Unsupported mode of operation %d\n", mode);
-		goto err1;
+		goto err2;
 	}
 	dwc->mode = mode;
 
 	ret = dwc3_debugfs_init(dwc);
 	if (ret) {
 		dev_err(dev, "failed to initialize debugfs\n");
-		goto err2;
+		goto err3;
 	}
 
 	pm_runtime_allow(dev);
 
 	return 0;
 
-err2:
+err3:
 	switch (mode) {
 	case DWC3_MODE_DEVICE:
 		dwc3_gadget_exit(dwc);
@@ -546,6 +587,9 @@ err2:
 		break;
 	}
 
+err2:
+	dwc3_event_buffers_cleanup(dwc);
+
 err1:
 	dwc3_core_exit(dwc);
 
@@ -583,12 +627,130 @@ static int dwc3_remove(struct platform_device *pdev)
 		break;
 	}
 
+	dwc3_event_buffers_cleanup(dwc);
 	dwc3_free_event_buffers(dwc);
 	dwc3_core_exit(dwc);
 
 	return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int dwc3_prepare(struct device *dev)
+{
+	struct dwc3	*dwc = dev_get_drvdata(dev);
+	unsigned long	flags;
+
+	spin_lock_irqsave(&dwc->lock, flags);
+
+	switch (dwc->mode) {
+	case DWC3_MODE_DEVICE:
+	case DWC3_MODE_DRD:
+		dwc3_gadget_prepare(dwc);
+		/* FALLTHROUGH */
+	case DWC3_MODE_HOST:
+	default:
+		dwc3_event_buffers_cleanup(dwc);
+		break;
+	}
+
+	spin_unlock_irqrestore(&dwc->lock, flags);
+
+	return 0;
+}
+
+static void dwc3_complete(struct device *dev)
+{
+	struct dwc3	*dwc = dev_get_drvdata(dev);
+	unsigned long	flags;
+
+	spin_lock_irqsave(&dwc->lock, flags);
+
+	switch (dwc->mode) {
+	case DWC3_MODE_DEVICE:
+	case DWC3_MODE_DRD:
+		dwc3_gadget_complete(dwc);
+		/* FALLTHROUGH */
+	case DWC3_MODE_HOST:
+	default:
+		dwc3_event_buffers_setup(dwc);
+		break;
+	}
+
+	spin_unlock_irqrestore(&dwc->lock, flags);
+}
+
+static int dwc3_suspend(struct device *dev)
+{
+	struct dwc3	*dwc = dev_get_drvdata(dev);
+	unsigned long	flags;
+
+	spin_lock_irqsave(&dwc->lock, flags);
+
+	switch (dwc->mode) {
+	case DWC3_MODE_DEVICE:
+	case DWC3_MODE_DRD:
+		dwc3_gadget_suspend(dwc);
+		/* FALLTHROUGH */
+	case DWC3_MODE_HOST:
+	default:
+		/* do nothing */
+		break;
+	}
+
+	dwc->gctl = dwc3_readl(dwc->regs, DWC3_GCTL);
+	spin_unlock_irqrestore(&dwc->lock, flags);
+
+	usb_phy_shutdown(dwc->usb3_phy);
+	usb_phy_shutdown(dwc->usb2_phy);
+
+	return 0;
+}
+
+static int dwc3_resume(struct device *dev)
+{
+	struct dwc3	*dwc = dev_get_drvdata(dev);
+	unsigned long	flags;
+
+	usb_phy_init(dwc->usb3_phy);
+	usb_phy_init(dwc->usb2_phy);
+	msleep(100);
+
+	spin_lock_irqsave(&dwc->lock, flags);
+
+	dwc3_writel(dwc->regs, DWC3_GCTL, dwc->gctl);
+
+	switch (dwc->mode) {
+	case DWC3_MODE_DEVICE:
+	case DWC3_MODE_DRD:
+		dwc3_gadget_resume(dwc);
+		/* FALLTHROUGH */
+	case DWC3_MODE_HOST:
+	default:
+		/* do nothing */
+		break;
+	}
+
+	spin_unlock_irqrestore(&dwc->lock, flags);
+
+	pm_runtime_disable(dev);
+	pm_runtime_set_active(dev);
+	pm_runtime_enable(dev);
+
+	return 0;
+}
+
+static const struct dev_pm_ops dwc3_dev_pm_ops = {
+	.prepare	= dwc3_prepare,
+	.complete	= dwc3_complete,
+
+	SET_SYSTEM_SLEEP_PM_OPS(dwc3_suspend, dwc3_resume)
+};
+
+#define DWC3_PM_OPS	&(dwc3_dev_pm_ops)
+#else
+#define DWC3_PM_OPS	NULL
+#endif
+
 #ifdef CONFIG_OF
 static const struct of_device_id of_dwc3_match[] = {
 	{
@@ -605,6 +767,7 @@ static struct platform_driver dwc3_driver = {
 	.driver		= {
 		.name	= "dwc3",
 		.of_match_table	= of_match_ptr(of_dwc3_match),
+		.pm	= DWC3_PM_OPS,
 	},
 };
 
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index b417506..b69d322 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -154,8 +154,9 @@
 /* OTG Registers */
 #define DWC3_OCFG		0xcc00
 #define DWC3_OCTL		0xcc04
-#define DWC3_OEVTEN		0xcc08
-#define DWC3_OSTS		0xcc0C
+#define DWC3_OEVT		0xcc08
+#define DWC3_OEVTEN		0xcc0C
+#define DWC3_OSTS		0xcc10
 
 /* Bit fields */
 
@@ -369,6 +370,9 @@ struct dwc3_trb;
  * @list: a list of event buffers
  * @buf: _THE_ buffer
  * @length: size of this buffer
+ * @lpos: event offset
+ * @count: cache of last read event count register
+ * @flags: flags related to this event buffer
  * @dma: dma_addr_t
  * @dwc: pointer to DWC controller
  */
@@ -376,6 +380,10 @@ struct dwc3_event_buffer {
 	void			*buf;
 	unsigned		length;
 	unsigned int		lpos;
+	unsigned int		count;
+	unsigned int		flags;
+
+#define DWC3_EVENT_PENDING	BIT(0)
 
 	dma_addr_t		dma;
 
@@ -487,12 +495,6 @@ enum dwc3_link_state {
 	DWC3_LINK_STATE_MASK		= 0x0f,
 };
 
-enum dwc3_device_state {
-	DWC3_DEFAULT_STATE,
-	DWC3_ADDRESS_STATE,
-	DWC3_CONFIGURED_STATE,
-};
-
 /* TRB Length, PCM and Status */
 #define DWC3_TRB_SIZE_MASK	(0x00ffffff)
 #define DWC3_TRB_SIZE_LENGTH(n)	((n) & DWC3_TRB_SIZE_MASK)
@@ -574,6 +576,14 @@ struct dwc3_hwparams {
 /* HWPARAMS1 */
 #define DWC3_NUM_INT(n)		(((n) & (0x3f << 15)) >> 15)
 
+/* HWPARAMS3 */
+#define DWC3_NUM_IN_EPS_MASK	(0x1f << 18)
+#define DWC3_NUM_EPS_MASK	(0x3f << 12)
+#define DWC3_NUM_EPS(p)		(((p)->hwparams3 &		\
+			(DWC3_NUM_EPS_MASK)) >> 12)
+#define DWC3_NUM_IN_EPS(p)	(((p)->hwparams3 &		\
+			(DWC3_NUM_IN_EPS_MASK)) >> 18)
+
 /* HWPARAMS7 */
 #define DWC3_RAM1_DEPTH(n)	((n) & 0xffff)
 
@@ -618,7 +628,6 @@ struct dwc3_scratchpad_array {
  * @gadget_driver: pointer to the gadget driver
  * @regs: base address for our registers
  * @regs_size: address space size
- * @irq: IRQ number
  * @num_event_buffers: calculated number of event buffers
  * @u1u2: only used on revisions <1.83a for workaround
  * @maximum_speed: maximum speed requested (mainly for testing purposes)
@@ -626,6 +635,8 @@ struct dwc3_scratchpad_array {
  * @mode: mode of operation
  * @usb2_phy: pointer to USB2 PHY
  * @usb3_phy: pointer to USB3 PHY
+ * @dcfg: saved contents of DCFG register
+ * @gctl: saved contents of GCTL register
  * @is_selfpowered: true when we are selfpowered
  * @three_stage_setup: set if we perform a three phase setup
  * @ep0_bounced: true when we used bounce buffer
@@ -639,6 +650,8 @@ struct dwc3_scratchpad_array {
  * @u2pel: parameter from Set SEL request.
  * @u1sel: parameter from Set SEL request.
  * @u1pel: parameter from Set SEL request.
+ * @num_out_eps: number of out endpoints
+ * @num_in_eps: number of in endpoints
  * @ep0_next_event: hold the next expected event
  * @ep0state: state of endpoint zero
  * @link_state: link state
@@ -656,8 +669,10 @@ struct dwc3 {
 	dma_addr_t		ep0_trb_addr;
 	dma_addr_t		ep0_bounce_addr;
 	struct dwc3_request	ep0_usb_req;
+
 	/* device lock */
 	spinlock_t		lock;
+
 	struct device		*dev;
 
 	struct platform_device	*xhci;
@@ -675,6 +690,10 @@ struct dwc3 {
 	void __iomem		*regs;
 	size_t			regs_size;
 
+	/* used for suspend/resume */
+	u32			dcfg;
+	u32			gctl;
+
 	u32			num_event_buffers;
 	u32			u1u2;
 	u32			maximum_speed;
@@ -694,6 +713,9 @@ struct dwc3 {
 #define DWC3_REVISION_202A	0x5533202a
 #define DWC3_REVISION_210A	0x5533210a
 #define DWC3_REVISION_220A	0x5533220a
+#define DWC3_REVISION_230A	0x5533230a
+#define DWC3_REVISION_240A	0x5533240a
+#define DWC3_REVISION_250A	0x5533250a
 
 	unsigned		is_selfpowered:1;
 	unsigned		three_stage_setup:1;
@@ -704,11 +726,11 @@ struct dwc3 {
 	unsigned		delayed_status:1;
 	unsigned		needs_fifo_resize:1;
 	unsigned		resize_fifos:1;
+	unsigned		pullups_connected:1;
 
 	enum dwc3_ep0_next	ep0_next_event;
 	enum dwc3_ep0_state	ep0state;
 	enum dwc3_link_state	link_state;
-	enum dwc3_device_state	dev_state;
 
 	u16			isoch_delay;
 	u16			u2sel;
@@ -718,6 +740,9 @@ struct dwc3 {
 
 	u8			speed;
 
+	u8			num_out_eps;
+	u8			num_in_eps;
+
 	void			*mem;
 
 	struct dwc3_hwparams	hwparams;
@@ -884,4 +909,31 @@ static inline void dwc3_gadget_exit(struct dwc3 *dwc)
 { }
 #endif
 
+/* power management interface */
+#if !IS_ENABLED(CONFIG_USB_DWC3_HOST)
+int dwc3_gadget_prepare(struct dwc3 *dwc);
+void dwc3_gadget_complete(struct dwc3 *dwc);
+int dwc3_gadget_suspend(struct dwc3 *dwc);
+int dwc3_gadget_resume(struct dwc3 *dwc);
+#else
+static inline int dwc3_gadget_prepare(struct dwc3 *dwc)
+{
+	return 0;
+}
+
+static inline void dwc3_gadget_complete(struct dwc3 *dwc)
+{
+}
+
+static inline int dwc3_gadget_suspend(struct dwc3 *dwc)
+{
+	return 0;
+}
+
+static inline int dwc3_gadget_resume(struct dwc3 *dwc)
+{
+	return 0;
+}
+#endif /* !IS_ENABLED(CONFIG_USB_DWC3_HOST) */
+
 #endif /* __DRIVERS_USB_DWC3_CORE_H */
diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c
index 4a752e7..9e9f122 100644
--- a/drivers/usb/dwc3/debugfs.c
+++ b/drivers/usb/dwc3/debugfs.c
@@ -59,7 +59,7 @@
 	.offset	= DWC3_ ##nm - DWC3_GLOBALS_REGS_START,	\
 }
 
-static struct debugfs_reg32 dwc3_regs[] = {
+static const struct debugfs_reg32 dwc3_regs[] = {
 	dump_register(GSBUSCFG0),
 	dump_register(GSBUSCFG1),
 	dump_register(GTXTHRCFG),
@@ -372,6 +372,7 @@ static struct debugfs_reg32 dwc3_regs[] = {
 
 	dump_register(OCFG),
 	dump_register(OCTL),
+	dump_register(OEVT),
 	dump_register(OEVTEN),
 	dump_register(OSTS),
 };
@@ -577,8 +578,14 @@ static int dwc3_link_state_show(struct seq_file *s, void *unused)
 	case DWC3_LINK_STATE_LPBK:
 		seq_printf(s, "Loopback\n");
 		break;
+	case DWC3_LINK_STATE_RESET:
+		seq_printf(s, "Reset\n");
+		break;
+	case DWC3_LINK_STATE_RESUME:
+		seq_printf(s, "Resume\n");
+		break;
 	default:
-		seq_printf(s, "UNKNOWN %d\n", reg);
+		seq_printf(s, "UNKNOWN %d\n", state);
 	}
 
 	return 0;
@@ -661,28 +668,31 @@ int dwc3_debugfs_init(struct dwc3 *dwc)
 		goto err1;
 	}
 
-#if IS_ENABLED(CONFIG_USB_DWC3_GADGET)
-	file = debugfs_create_file("mode", S_IRUGO | S_IWUSR, root,
-			dwc, &dwc3_mode_fops);
-	if (!file) {
-		ret = -ENOMEM;
-		goto err1;
-	}
-
-	file = debugfs_create_file("testmode", S_IRUGO | S_IWUSR, root,
-			dwc, &dwc3_testmode_fops);
-	if (!file) {
-		ret = -ENOMEM;
-		goto err1;
+	if (IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)) {
+		file = debugfs_create_file("mode", S_IRUGO | S_IWUSR, root,
+				dwc, &dwc3_mode_fops);
+		if (!file) {
+			ret = -ENOMEM;
+			goto err1;
+		}
 	}
 
-	file = debugfs_create_file("link_state", S_IRUGO | S_IWUSR, root,
-			dwc, &dwc3_link_state_fops);
-	if (!file) {
-		ret = -ENOMEM;
-		goto err1;
+	if (IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE) ||
+			IS_ENABLED(CONFIG_USB_DWC3_GADGET)) {
+		file = debugfs_create_file("testmode", S_IRUGO | S_IWUSR, root,
+				dwc, &dwc3_testmode_fops);
+		if (!file) {
+			ret = -ENOMEM;
+			goto err1;
+		}
+
+		file = debugfs_create_file("link_state", S_IRUGO | S_IWUSR, root,
+				dwc, &dwc3_link_state_fops);
+		if (!file) {
+			ret = -ENOMEM;
+			goto err1;
+		}
 	}
-#endif
 
 	return 0;
 
diff --git a/drivers/usb/dwc3/dwc3-exynos.c b/drivers/usb/dwc3/dwc3-exynos.c
index b082bec..a8afe6e 100644
--- a/drivers/usb/dwc3/dwc3-exynos.c
+++ b/drivers/usb/dwc3/dwc3-exynos.c
@@ -22,9 +22,9 @@
 #include <linux/usb/otg.h>
 #include <linux/usb/nop-usb-xceiv.h>
 #include <linux/of.h>
+#include <linux/of_platform.h>
 
 struct dwc3_exynos {
-	struct platform_device	*dwc3;
 	struct platform_device	*usb2_phy;
 	struct platform_device	*usb3_phy;
 	struct device		*dev;
@@ -86,21 +86,30 @@ err1:
 	return ret;
 }
 
+static int dwc3_exynos_remove_child(struct device *dev, void *unused)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+
+	platform_device_unregister(pdev);
+
+	return 0;
+}
+
 static u64 dwc3_exynos_dma_mask = DMA_BIT_MASK(32);
 
 static int dwc3_exynos_probe(struct platform_device *pdev)
 {
-	struct platform_device	*dwc3;
 	struct dwc3_exynos	*exynos;
 	struct clk		*clk;
 	struct device		*dev = &pdev->dev;
+	struct device_node	*node = dev->of_node;
 
 	int			ret = -ENOMEM;
 
 	exynos = devm_kzalloc(dev, sizeof(*exynos), GFP_KERNEL);
 	if (!exynos) {
 		dev_err(dev, "not enough memory\n");
-		return -ENOMEM;
+		goto err1;
 	}
 
 	/*
@@ -108,21 +117,15 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
 	 * Since shared usb code relies on it, set it here for now.
 	 * Once we move to full device tree support this will vanish off.
 	 */
-	if (!pdev->dev.dma_mask)
-		pdev->dev.dma_mask = &dwc3_exynos_dma_mask;
+	if (!dev->dma_mask)
+		dev->dma_mask = &dwc3_exynos_dma_mask;
 
 	platform_set_drvdata(pdev, exynos);
 
 	ret = dwc3_exynos_register_phys(exynos);
 	if (ret) {
 		dev_err(dev, "couldn't register PHYs\n");
-		return ret;
-	}
-
-	dwc3 = platform_device_alloc("dwc3", PLATFORM_DEVID_AUTO);
-	if (!dwc3) {
-		dev_err(dev, "couldn't allocate dwc3 device\n");
-		return -ENOMEM;
+		goto err1;
 	}
 
 	clk = devm_clk_get(dev, "usbdrd30");
@@ -132,37 +135,28 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
 		goto err1;
 	}
 
-	dma_set_coherent_mask(&dwc3->dev, dev->coherent_dma_mask);
-
-	dwc3->dev.parent = dev;
-	dwc3->dev.dma_mask = dev->dma_mask;
-	dwc3->dev.dma_parms = dev->dma_parms;
-	exynos->dwc3	= dwc3;
 	exynos->dev	= dev;
 	exynos->clk	= clk;
 
-	clk_enable(exynos->clk);
-
-	ret = platform_device_add_resources(dwc3, pdev->resource,
-			pdev->num_resources);
-	if (ret) {
-		dev_err(dev, "couldn't add resources to dwc3 device\n");
-		goto err2;
-	}
-
-	ret = platform_device_add(dwc3);
-	if (ret) {
-		dev_err(dev, "failed to register dwc3 device\n");
+	clk_prepare_enable(exynos->clk);
+
+	if (node) {
+		ret = of_platform_populate(node, NULL, NULL, dev);
+		if (ret) {
+			dev_err(dev, "failed to add dwc3 core\n");
+			goto err2;
+		}
+	} else {
+		dev_err(dev, "no device node, failed to add dwc3 core\n");
+		ret = -ENODEV;
 		goto err2;
 	}
 
 	return 0;
 
 err2:
-	clk_disable(clk);
+	clk_disable_unprepare(clk);
 err1:
-	platform_device_put(dwc3);
-
 	return ret;
 }
 
@@ -170,11 +164,11 @@ static int dwc3_exynos_remove(struct platform_device *pdev)
 {
 	struct dwc3_exynos	*exynos = platform_get_drvdata(pdev);
 
-	platform_device_unregister(exynos->dwc3);
 	platform_device_unregister(exynos->usb2_phy);
 	platform_device_unregister(exynos->usb3_phy);
+	device_for_each_child(&pdev->dev, NULL, dwc3_exynos_remove_child);
 
-	clk_disable(exynos->clk);
+	clk_disable_unprepare(exynos->clk);
 
 	return 0;
 }
@@ -187,12 +181,46 @@ static const struct of_device_id exynos_dwc3_match[] = {
 MODULE_DEVICE_TABLE(of, exynos_dwc3_match);
 #endif
 
+#ifdef CONFIG_PM_SLEEP
+static int dwc3_exynos_suspend(struct device *dev)
+{
+	struct dwc3_exynos *exynos = dev_get_drvdata(dev);
+
+	clk_disable(exynos->clk);
+
+	return 0;
+}
+
+static int dwc3_exynos_resume(struct device *dev)
+{
+	struct dwc3_exynos *exynos = dev_get_drvdata(dev);
+
+	clk_enable(exynos->clk);
+
+	/* runtime set active to reflect active state. */
+	pm_runtime_disable(dev);
+	pm_runtime_set_active(dev);
+	pm_runtime_enable(dev);
+
+	return 0;
+}
+
+static const struct dev_pm_ops dwc3_exynos_dev_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(dwc3_exynos_suspend, dwc3_exynos_resume)
+};
+
+#define DEV_PM_OPS	(&dwc3_exynos_dev_pm_ops)
+#else
+#define DEV_PM_OPS	NULL
+#endif /* CONFIG_PM_SLEEP */
+
 static struct platform_driver dwc3_exynos_driver = {
 	.probe		= dwc3_exynos_probe,
 	.remove		= dwc3_exynos_remove,
 	.driver		= {
 		.name	= "exynos-dwc3",
 		.of_match_table = of_match_ptr(exynos_dwc3_match),
+		.pm	= DEV_PM_OPS,
 	},
 };
 
diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c
index afa05e3..34638b9 100644
--- a/drivers/usb/dwc3/dwc3-omap.c
+++ b/drivers/usb/dwc3/dwc3-omap.c
@@ -52,7 +52,6 @@
 #include <linux/of_platform.h>
 
 #include <linux/usb/otg.h>
-#include <linux/usb/nop-usb-xceiv.h>
 
 /*
  * All these registers belong to OMAP's Wrapper around the
@@ -117,20 +116,17 @@ struct dwc3_omap {
 	/* device lock */
 	spinlock_t		lock;
 
-	struct platform_device	*usb2_phy;
-	struct platform_device	*usb3_phy;
 	struct device		*dev;
 
 	int			irq;
 	void __iomem		*base;
 
-	void			*context;
-	u32			resource_size;
+	u32			utmi_otg_status;
 
 	u32			dma_status:1;
 };
 
-struct dwc3_omap		*_omap;
+static struct dwc3_omap		*_omap;
 
 static inline u32 dwc3_omap_readl(void __iomem *base, u32 offset)
 {
@@ -142,11 +138,14 @@ static inline void dwc3_omap_writel(void __iomem *base, u32 offset, u32 value)
 	writel(value, base + offset);
 }
 
-void dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status)
+int dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status)
 {
 	u32			val;
 	struct dwc3_omap	*omap = _omap;
 
+	if (!omap)
+		return -EPROBE_DEFER;
+
 	switch (status) {
 	case OMAP_DWC3_ID_GROUND:
 		dev_dbg(omap->dev, "ID GND\n");
@@ -189,63 +188,9 @@ void dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status)
 		dev_dbg(omap->dev, "ID float\n");
 	}
 
-	return;
-}
-EXPORT_SYMBOL_GPL(dwc3_omap_mailbox);
-
-static int dwc3_omap_register_phys(struct dwc3_omap *omap)
-{
-	struct nop_usb_xceiv_platform_data pdata;
-	struct platform_device	*pdev;
-	int			ret;
-
-	memset(&pdata, 0x00, sizeof(pdata));
-
-	pdev = platform_device_alloc("nop_usb_xceiv", PLATFORM_DEVID_AUTO);
-	if (!pdev)
-		return -ENOMEM;
-
-	omap->usb2_phy = pdev;
-	pdata.type = USB_PHY_TYPE_USB2;
-
-	ret = platform_device_add_data(omap->usb2_phy, &pdata, sizeof(pdata));
-	if (ret)
-		goto err1;
-
-	pdev = platform_device_alloc("nop_usb_xceiv", PLATFORM_DEVID_AUTO);
-	if (!pdev) {
-		ret = -ENOMEM;
-		goto err1;
-	}
-
-	omap->usb3_phy = pdev;
-	pdata.type = USB_PHY_TYPE_USB3;
-
-	ret = platform_device_add_data(omap->usb3_phy, &pdata, sizeof(pdata));
-	if (ret)
-		goto err2;
-
-	ret = platform_device_add(omap->usb2_phy);
-	if (ret)
-		goto err2;
-
-	ret = platform_device_add(omap->usb3_phy);
-	if (ret)
-		goto err3;
-
 	return 0;
-
-err3:
-	platform_device_del(omap->usb2_phy);
-
-err2:
-	platform_device_put(omap->usb3_phy);
-
-err1:
-	platform_device_put(omap->usb2_phy);
-
-	return ret;
 }
+EXPORT_SYMBOL_GPL(dwc3_omap_mailbox);
 
 static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap)
 {
@@ -307,24 +252,57 @@ static int dwc3_omap_remove_core(struct device *dev, void *c)
 	return 0;
 }
 
+static void dwc3_omap_enable_irqs(struct dwc3_omap *omap)
+{
+	u32			reg;
+
+	/* enable all IRQs */
+	reg = USBOTGSS_IRQO_COREIRQ_ST;
+	dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_0, reg);
+
+	reg = (USBOTGSS_IRQ1_OEVT |
+			USBOTGSS_IRQ1_DRVVBUS_RISE |
+			USBOTGSS_IRQ1_CHRGVBUS_RISE |
+			USBOTGSS_IRQ1_DISCHRGVBUS_RISE |
+			USBOTGSS_IRQ1_IDPULLUP_RISE |
+			USBOTGSS_IRQ1_DRVVBUS_FALL |
+			USBOTGSS_IRQ1_CHRGVBUS_FALL |
+			USBOTGSS_IRQ1_DISCHRGVBUS_FALL |
+			USBOTGSS_IRQ1_IDPULLUP_FALL);
+
+	dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_1, reg);
+}
+
+static void dwc3_omap_disable_irqs(struct dwc3_omap *omap)
+{
+	/* disable all IRQs */
+	dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_1, 0x00);
+	dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_0, 0x00);
+}
+
+static u64 dwc3_omap_dma_mask = DMA_BIT_MASK(32);
+
 static int dwc3_omap_probe(struct platform_device *pdev)
 {
-	struct dwc3_omap_data	*pdata = pdev->dev.platform_data;
 	struct device_node	*node = pdev->dev.of_node;
 
 	struct dwc3_omap	*omap;
 	struct resource		*res;
 	struct device		*dev = &pdev->dev;
 
-	int			size;
 	int			ret = -ENOMEM;
 	int			irq;
 
-	const u32		*utmi_mode;
+	int			utmi_mode = 0;
+
 	u32			reg;
 
 	void __iomem		*base;
-	void			*context;
+
+	if (!node) {
+		dev_err(dev, "device node not found\n");
+		return -EINVAL;
+	}
 
 	omap = devm_kzalloc(dev, sizeof(*omap), GFP_KERNEL);
 	if (!omap) {
@@ -334,13 +312,13 @@ static int dwc3_omap_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, omap);
 
-	irq = platform_get_irq(pdev, 1);
+	irq = platform_get_irq(pdev, 0);
 	if (irq < 0) {
 		dev_err(dev, "missing IRQ resource\n");
 		return -EINVAL;
 	}
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res) {
 		dev_err(dev, "missing memory base resource\n");
 		return -EINVAL;
@@ -352,25 +330,12 @@ static int dwc3_omap_probe(struct platform_device *pdev)
 		return -ENOMEM;
 	}
 
-	ret = dwc3_omap_register_phys(omap);
-	if (ret) {
-		dev_err(dev, "couldn't register PHYs\n");
-		return ret;
-	}
-
-	context = devm_kzalloc(dev, resource_size(res), GFP_KERNEL);
-	if (!context) {
-		dev_err(dev, "couldn't allocate dwc3 context memory\n");
-		return -ENOMEM;
-	}
-
 	spin_lock_init(&omap->lock);
 
-	omap->resource_size = resource_size(res);
-	omap->context	= context;
 	omap->dev	= dev;
 	omap->irq	= irq;
 	omap->base	= base;
+	dev->dma_mask	= &dwc3_omap_dma_mask;
 
 	/*
 	 * REVISIT if we ever have two instances of the wrapper, we will be
@@ -387,25 +352,17 @@ static int dwc3_omap_probe(struct platform_device *pdev)
 
 	reg = dwc3_omap_readl(omap->base, USBOTGSS_UTMI_OTG_STATUS);
 
-	utmi_mode = of_get_property(node, "utmi-mode", &size);
-	if (utmi_mode && size == sizeof(*utmi_mode)) {
-		reg |= *utmi_mode;
-	} else {
-		if (!pdata) {
-			dev_dbg(dev, "missing platform data\n");
-		} else {
-			switch (pdata->utmi_mode) {
-			case DWC3_OMAP_UTMI_MODE_SW:
-				reg |= USBOTGSS_UTMI_OTG_STATUS_SW_MODE;
-				break;
-			case DWC3_OMAP_UTMI_MODE_HW:
-				reg &= ~USBOTGSS_UTMI_OTG_STATUS_SW_MODE;
-				break;
-			default:
-				dev_dbg(dev, "UNKNOWN utmi mode %d\n",
-						pdata->utmi_mode);
-			}
-		}
+	of_property_read_u32(node, "utmi-mode", &utmi_mode);
+
+	switch (utmi_mode) {
+	case DWC3_OMAP_UTMI_MODE_SW:
+		reg |= USBOTGSS_UTMI_OTG_STATUS_SW_MODE;
+		break;
+	case DWC3_OMAP_UTMI_MODE_HW:
+		reg &= ~USBOTGSS_UTMI_OTG_STATUS_SW_MODE;
+		break;
+	default:
+		dev_dbg(dev, "UNKNOWN utmi mode %d\n", utmi_mode);
 	}
 
 	dwc3_omap_writel(omap->base, USBOTGSS_UTMI_OTG_STATUS, reg);
@@ -422,29 +379,12 @@ static int dwc3_omap_probe(struct platform_device *pdev)
 		return ret;
 	}
 
-	/* enable all IRQs */
-	reg = USBOTGSS_IRQO_COREIRQ_ST;
-	dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_0, reg);
+	dwc3_omap_enable_irqs(omap);
 
-	reg = (USBOTGSS_IRQ1_OEVT |
-			USBOTGSS_IRQ1_DRVVBUS_RISE |
-			USBOTGSS_IRQ1_CHRGVBUS_RISE |
-			USBOTGSS_IRQ1_DISCHRGVBUS_RISE |
-			USBOTGSS_IRQ1_IDPULLUP_RISE |
-			USBOTGSS_IRQ1_DRVVBUS_FALL |
-			USBOTGSS_IRQ1_CHRGVBUS_FALL |
-			USBOTGSS_IRQ1_DISCHRGVBUS_FALL |
-			USBOTGSS_IRQ1_IDPULLUP_FALL);
-
-	dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_1, reg);
-
-	if (node) {
-		ret = of_platform_populate(node, NULL, NULL, dev);
-		if (ret) {
-			dev_err(&pdev->dev,
-				"failed to add create dwc3 core\n");
-			return ret;
-		}
+	ret = of_platform_populate(node, NULL, NULL, dev);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to create dwc3 core\n");
+		return ret;
 	}
 
 	return 0;
@@ -454,8 +394,7 @@ static int dwc3_omap_remove(struct platform_device *pdev)
 {
 	struct dwc3_omap	*omap = platform_get_drvdata(pdev);
 
-	platform_device_unregister(omap->usb2_phy);
-	platform_device_unregister(omap->usb3_phy);
+	dwc3_omap_disable_irqs(omap);
 	pm_runtime_put_sync(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
 	device_for_each_child(&pdev->dev, NULL, dwc3_omap_remove_core);
@@ -465,18 +404,72 @@ static int dwc3_omap_remove(struct platform_device *pdev)
 
 static const struct of_device_id of_dwc3_match[] = {
 	{
-		"ti,dwc3",
+		.compatible =	"ti,dwc3"
 	},
 	{ },
 };
 MODULE_DEVICE_TABLE(of, of_dwc3_match);
 
+#ifdef CONFIG_PM_SLEEP
+static int dwc3_omap_prepare(struct device *dev)
+{
+	struct dwc3_omap	*omap = dev_get_drvdata(dev);
+
+	dwc3_omap_disable_irqs(omap);
+
+	return 0;
+}
+
+static void dwc3_omap_complete(struct device *dev)
+{
+	struct dwc3_omap	*omap = dev_get_drvdata(dev);
+
+	dwc3_omap_enable_irqs(omap);
+}
+
+static int dwc3_omap_suspend(struct device *dev)
+{
+	struct dwc3_omap	*omap = dev_get_drvdata(dev);
+
+	omap->utmi_otg_status = dwc3_omap_readl(omap->base,
+			USBOTGSS_UTMI_OTG_STATUS);
+
+	return 0;
+}
+
+static int dwc3_omap_resume(struct device *dev)
+{
+	struct dwc3_omap	*omap = dev_get_drvdata(dev);
+
+	dwc3_omap_writel(omap->base, USBOTGSS_UTMI_OTG_STATUS,
+			omap->utmi_otg_status);
+
+	pm_runtime_disable(dev);
+	pm_runtime_set_active(dev);
+	pm_runtime_enable(dev);
+
+	return 0;
+}
+
+static const struct dev_pm_ops dwc3_omap_dev_pm_ops = {
+	.prepare	= dwc3_omap_prepare,
+	.complete	= dwc3_omap_complete,
+
+	SET_SYSTEM_SLEEP_PM_OPS(dwc3_omap_suspend, dwc3_omap_resume)
+};
+
+#define DEV_PM_OPS	(&dwc3_omap_dev_pm_ops)
+#else
+#define DEV_PM_OPS	NULL
+#endif /* CONFIG_PM_SLEEP */
+
 static struct platform_driver dwc3_omap_driver = {
 	.probe		= dwc3_omap_probe,
 	.remove		= dwc3_omap_remove,
 	.driver		= {
 		.name	= "omap-dwc3",
 		.of_match_table	= of_dwc3_match,
+		.pm	= DEV_PM_OPS,
 	},
 };
 
diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c
index e8d7768..227d4a7 100644
--- a/drivers/usb/dwc3/dwc3-pci.c
+++ b/drivers/usb/dwc3/dwc3-pci.c
@@ -212,11 +212,49 @@ static DEFINE_PCI_DEVICE_TABLE(dwc3_pci_id_table) = {
 };
 MODULE_DEVICE_TABLE(pci, dwc3_pci_id_table);
 
+#ifdef CONFIG_PM
+static int dwc3_pci_suspend(struct device *dev)
+{
+	struct pci_dev	*pci = to_pci_dev(dev);
+
+	pci_disable_device(pci);
+
+	return 0;
+}
+
+static int dwc3_pci_resume(struct device *dev)
+{
+	struct pci_dev	*pci = to_pci_dev(dev);
+	int		ret;
+
+	ret = pci_enable_device(pci);
+	if (ret) {
+		dev_err(dev, "can't re-enable device --> %d\n", ret);
+		return ret;
+	}
+
+	pci_set_master(pci);
+
+	return 0;
+}
+
+static const struct dev_pm_ops dwc3_pci_dev_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(dwc3_pci_suspend, dwc3_pci_resume)
+};
+
+#define DEV_PM_OPS	(&dwc3_pci_dev_pm_ops)
+#else
+#define DEV_PM_OPS	NULL
+#endif /* CONFIG_PM */
+
 static struct pci_driver dwc3_pci_driver = {
 	.name		= "dwc3-pci",
 	.id_table	= dwc3_pci_id_table,
 	.probe		= dwc3_pci_probe,
 	.remove		= dwc3_pci_remove,
+	.driver		= {
+		.pm	= DEV_PM_OPS,
+	},
 };
 
 MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index 1d139ca..5acbb94 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -394,10 +394,13 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
 	u32			wIndex;
 	u32			reg;
 	int			ret;
+	enum usb_device_state	state;
 
 	wValue = le16_to_cpu(ctrl->wValue);
 	wIndex = le16_to_cpu(ctrl->wIndex);
 	recip = ctrl->bRequestType & USB_RECIP_MASK;
+	state = dwc->gadget.state;
+
 	switch (recip) {
 	case USB_RECIP_DEVICE:
 
@@ -409,7 +412,7 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
 		 * default control pipe
 		 */
 		case USB_DEVICE_U1_ENABLE:
-			if (dwc->dev_state != DWC3_CONFIGURED_STATE)
+			if (state != USB_STATE_CONFIGURED)
 				return -EINVAL;
 			if (dwc->speed != DWC3_DSTS_SUPERSPEED)
 				return -EINVAL;
@@ -423,7 +426,7 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
 			break;
 
 		case USB_DEVICE_U2_ENABLE:
-			if (dwc->dev_state != DWC3_CONFIGURED_STATE)
+			if (state != USB_STATE_CONFIGURED)
 				return -EINVAL;
 			if (dwc->speed != DWC3_DSTS_SUPERSPEED)
 				return -EINVAL;
@@ -493,6 +496,7 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
 
 static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
 {
+	enum usb_device_state state = dwc->gadget.state;
 	u32 addr;
 	u32 reg;
 
@@ -502,7 +506,7 @@ static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
 		return -EINVAL;
 	}
 
-	if (dwc->dev_state == DWC3_CONFIGURED_STATE) {
+	if (state == USB_STATE_CONFIGURED) {
 		dev_dbg(dwc->dev, "trying to set address when configured\n");
 		return -EINVAL;
 	}
@@ -513,9 +517,9 @@ static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
 	dwc3_writel(dwc->regs, DWC3_DCFG, reg);
 
 	if (addr)
-		dwc->dev_state = DWC3_ADDRESS_STATE;
+		usb_gadget_set_state(&dwc->gadget, USB_STATE_ADDRESS);
 	else
-		dwc->dev_state = DWC3_DEFAULT_STATE;
+		usb_gadget_set_state(&dwc->gadget, USB_STATE_DEFAULT);
 
 	return 0;
 }
@@ -532,6 +536,7 @@ static int dwc3_ep0_delegate_req(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
 
 static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
 {
+	enum usb_device_state state = dwc->gadget.state;
 	u32 cfg;
 	int ret;
 	u32 reg;
@@ -539,16 +544,18 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
 	dwc->start_config_issued = false;
 	cfg = le16_to_cpu(ctrl->wValue);
 
-	switch (dwc->dev_state) {
-	case DWC3_DEFAULT_STATE:
+	switch (state) {
+	case USB_STATE_DEFAULT:
 		return -EINVAL;
 		break;
 
-	case DWC3_ADDRESS_STATE:
+	case USB_STATE_ADDRESS:
 		ret = dwc3_ep0_delegate_req(dwc, ctrl);
 		/* if the cfg matches and the cfg is non zero */
 		if (cfg && (!ret || (ret == USB_GADGET_DELAYED_STATUS))) {
-			dwc->dev_state = DWC3_CONFIGURED_STATE;
+			usb_gadget_set_state(&dwc->gadget,
+					USB_STATE_CONFIGURED);
+
 			/*
 			 * Enable transition to U1/U2 state when
 			 * nothing is pending from application.
@@ -562,10 +569,11 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
 		}
 		break;
 
-	case DWC3_CONFIGURED_STATE:
+	case USB_STATE_CONFIGURED:
 		ret = dwc3_ep0_delegate_req(dwc, ctrl);
 		if (!cfg)
-			dwc->dev_state = DWC3_ADDRESS_STATE;
+			usb_gadget_set_state(&dwc->gadget,
+					USB_STATE_ADDRESS);
 		break;
 	default:
 		ret = -EINVAL;
@@ -620,10 +628,11 @@ static void dwc3_ep0_set_sel_cmpl(struct usb_ep *ep, struct usb_request *req)
 static int dwc3_ep0_set_sel(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
 {
 	struct dwc3_ep	*dep;
+	enum usb_device_state state = dwc->gadget.state;
 	u16		wLength;
 	u16		wValue;
 
-	if (dwc->dev_state == DWC3_DEFAULT_STATE)
+	if (state == USB_STATE_DEFAULT)
 		return -EINVAL;
 
 	wValue = le16_to_cpu(ctrl->wValue);
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 82e160e..2b6e7e0 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1425,8 +1425,10 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on)
 		if (dwc->revision >= DWC3_REVISION_194A)
 			reg &= ~DWC3_DCTL_KEEP_CONNECT;
 		reg |= DWC3_DCTL_RUN_STOP;
+		dwc->pullups_connected = true;
 	} else {
 		reg &= ~DWC3_DCTL_RUN_STOP;
+		dwc->pullups_connected = false;
 	}
 
 	dwc3_writel(dwc->regs, DWC3_DCTL, reg);
@@ -1469,6 +1471,33 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
 	return ret;
 }
 
+static void dwc3_gadget_enable_irq(struct dwc3 *dwc)
+{
+	u32			reg;
+
+	/* Enable all but Start and End of Frame IRQs */
+	reg = (DWC3_DEVTEN_VNDRDEVTSTRCVEDEN |
+			DWC3_DEVTEN_EVNTOVERFLOWEN |
+			DWC3_DEVTEN_CMDCMPLTEN |
+			DWC3_DEVTEN_ERRTICERREN |
+			DWC3_DEVTEN_WKUPEVTEN |
+			DWC3_DEVTEN_ULSTCNGEN |
+			DWC3_DEVTEN_CONNECTDONEEN |
+			DWC3_DEVTEN_USBRSTEN |
+			DWC3_DEVTEN_DISCONNEVTEN);
+
+	dwc3_writel(dwc->regs, DWC3_DEVTEN, reg);
+}
+
+static void dwc3_gadget_disable_irq(struct dwc3 *dwc)
+{
+	/* mask all interrupts */
+	dwc3_writel(dwc->regs, DWC3_DEVTEN, 0x00);
+}
+
+static irqreturn_t dwc3_interrupt(int irq, void *_dwc);
+static irqreturn_t dwc3_thread_interrupt(int irq, void *_dwc);
+
 static int dwc3_gadget_start(struct usb_gadget *g,
 		struct usb_gadget_driver *driver)
 {
@@ -1476,6 +1505,7 @@ static int dwc3_gadget_start(struct usb_gadget *g,
 	struct dwc3_ep		*dep;
 	unsigned long		flags;
 	int			ret = 0;
+	int			irq;
 	u32			reg;
 
 	spin_lock_irqsave(&dwc->lock, flags);
@@ -1489,7 +1519,6 @@ static int dwc3_gadget_start(struct usb_gadget *g,
 	}
 
 	dwc->gadget_driver	= driver;
-	dwc->gadget.dev.driver	= &driver->driver;
 
 	reg = dwc3_readl(dwc->regs, DWC3_DCFG);
 	reg &= ~(DWC3_DCFG_SPEED_MASK);
@@ -1536,6 +1565,17 @@ static int dwc3_gadget_start(struct usb_gadget *g,
 	dwc->ep0state = EP0_SETUP_PHASE;
 	dwc3_ep0_out_start(dwc);
 
+	irq = platform_get_irq(to_platform_device(dwc->dev), 0);
+	ret = request_threaded_irq(irq, dwc3_interrupt, dwc3_thread_interrupt,
+			IRQF_SHARED | IRQF_ONESHOT, "dwc3", dwc);
+	if (ret) {
+		dev_err(dwc->dev, "failed to request irq #%d --> %d\n",
+				irq, ret);
+		goto err1;
+	}
+
+	dwc3_gadget_enable_irq(dwc);
+
 	spin_unlock_irqrestore(&dwc->lock, flags);
 
 	return 0;
@@ -1554,14 +1594,18 @@ static int dwc3_gadget_stop(struct usb_gadget *g,
 {
 	struct dwc3		*dwc = gadget_to_dwc(g);
 	unsigned long		flags;
+	int			irq;
 
 	spin_lock_irqsave(&dwc->lock, flags);
 
+	dwc3_gadget_disable_irq(dwc);
+	irq = platform_get_irq(to_platform_device(dwc->dev), 0);
+	free_irq(irq, dwc);
+
 	__dwc3_gadget_ep_disable(dwc->eps[0]);
 	__dwc3_gadget_ep_disable(dwc->eps[1]);
 
 	dwc->gadget_driver	= NULL;
-	dwc->gadget.dev.driver	= NULL;
 
 	spin_unlock_irqrestore(&dwc->lock, flags);
 
@@ -1579,14 +1623,15 @@ static const struct usb_gadget_ops dwc3_gadget_ops = {
 
 /* -------------------------------------------------------------------------- */
 
-static int dwc3_gadget_init_endpoints(struct dwc3 *dwc)
+static int dwc3_gadget_init_hw_endpoints(struct dwc3 *dwc,
+		u8 num, u32 direction)
 {
 	struct dwc3_ep			*dep;
-	u8				epnum;
+	u8				i;
 
-	INIT_LIST_HEAD(&dwc->gadget.ep_list);
+	for (i = 0; i < num; i++) {
+		u8 epnum = (i << 1) | (!!direction);
 
-	for (epnum = 0; epnum < DWC3_ENDPOINTS_NUM; epnum++) {
 		dep = kzalloc(sizeof(*dep), GFP_KERNEL);
 		if (!dep) {
 			dev_err(dwc->dev, "can't allocate endpoint %d\n",
@@ -1600,6 +1645,7 @@ static int dwc3_gadget_init_endpoints(struct dwc3 *dwc)
 
 		snprintf(dep->name, sizeof(dep->name), "ep%d%s", epnum >> 1,
 				(epnum & 1) ? "in" : "out");
+
 		dep->endpoint.name = dep->name;
 		dep->direction = (epnum & 1);
 
@@ -1630,6 +1676,27 @@ static int dwc3_gadget_init_endpoints(struct dwc3 *dwc)
 	return 0;
 }
 
+static int dwc3_gadget_init_endpoints(struct dwc3 *dwc)
+{
+	int				ret;
+
+	INIT_LIST_HEAD(&dwc->gadget.ep_list);
+
+	ret = dwc3_gadget_init_hw_endpoints(dwc, dwc->num_out_eps, 0);
+	if (ret < 0) {
+		dev_vdbg(dwc->dev, "failed to allocate OUT endpoints\n");
+		return ret;
+	}
+
+	ret = dwc3_gadget_init_hw_endpoints(dwc, dwc->num_in_eps, 1);
+	if (ret < 0) {
+		dev_vdbg(dwc->dev, "failed to allocate IN endpoints\n");
+		return ret;
+	}
+
+	return 0;
+}
+
 static void dwc3_gadget_free_endpoints(struct dwc3 *dwc)
 {
 	struct dwc3_ep			*dep;
@@ -1637,6 +1704,9 @@ static void dwc3_gadget_free_endpoints(struct dwc3 *dwc)
 
 	for (epnum = 0; epnum < DWC3_ENDPOINTS_NUM; epnum++) {
 		dep = dwc->eps[epnum];
+		if (!dep)
+			continue;
+
 		dwc3_free_trb_pool(dep);
 
 		if (epnum != 0 && epnum != 1)
@@ -1646,12 +1716,8 @@ static void dwc3_gadget_free_endpoints(struct dwc3 *dwc)
 	}
 }
 
-static void dwc3_gadget_release(struct device *dev)
-{
-	dev_dbg(dev, "%s\n", __func__);
-}
-
 /* -------------------------------------------------------------------------- */
+
 static int __dwc3_cleanup_done_trbs(struct dwc3 *dwc, struct dwc3_ep *dep,
 		struct dwc3_request *req, struct dwc3_trb *trb,
 		const struct dwc3_event_depevt *event, int status)
@@ -1975,6 +2041,9 @@ static void dwc3_stop_active_transfers(struct dwc3 *dwc)
 		struct dwc3_ep *dep;
 
 		dep = dwc->eps[epnum];
+		if (!dep)
+			continue;
+
 		if (!(dep->flags & DWC3_EP_ENABLED))
 			continue;
 
@@ -1992,6 +2061,8 @@ static void dwc3_clear_stall_all_ep(struct dwc3 *dwc)
 		int ret;
 
 		dep = dwc->eps[epnum];
+		if (!dep)
+			continue;
 
 		if (!(dep->flags & DWC3_EP_STALL))
 			continue;
@@ -2091,7 +2162,7 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
 	}
 
 	/* after reset -> Default State */
-	dwc->dev_state = DWC3_DEFAULT_STATE;
+	usb_gadget_set_state(&dwc->gadget, USB_STATE_DEFAULT);
 
 	/* Recent versions support automatic phy suspend and don't need this */
 	if (dwc->revision < DWC3_REVISION_194A) {
@@ -2277,6 +2348,34 @@ static void dwc3_gadget_linksts_change_interrupt(struct dwc3 *dwc,
 		unsigned int evtinfo)
 {
 	enum dwc3_link_state	next = evtinfo & DWC3_LINK_STATE_MASK;
+	unsigned int		pwropt;
+
+	/*
+	 * WORKAROUND: DWC3 < 2.50a have an issue when configured without
+	 * Hibernation mode enabled which would show up when device detects
+	 * host-initiated U3 exit.
+	 *
+	 * In that case, device will generate a Link State Change Interrupt
+	 * from U3 to RESUME which is only necessary if Hibernation is
+	 * configured in.
+	 *
+	 * There are no functional changes due to such spurious event and we
+	 * just need to ignore it.
+	 *
+	 * Refers to:
+	 *
+	 * STAR#9000570034 RTL: SS Resume event generated in non-Hibernation
+	 * operational mode
+	 */
+	pwropt = DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1);
+	if ((dwc->revision < DWC3_REVISION_250A) &&
+			(pwropt != DWC3_GHWPARAMS1_EN_PWROPT_HIB)) {
+		if ((dwc->link_state == DWC3_LINK_STATE_U3) &&
+				(next == DWC3_LINK_STATE_RESUME)) {
+			dev_vdbg(dwc->dev, "ignoring transition U3 -> Resume\n");
+			return;
+		}
+	}
 
 	/*
 	 * WORKAROUND: DWC3 Revisions <1.83a have an issue which, depending
@@ -2387,40 +2486,73 @@ static void dwc3_process_event_entry(struct dwc3 *dwc,
 	}
 }
 
+static irqreturn_t dwc3_thread_interrupt(int irq, void *_dwc)
+{
+	struct dwc3 *dwc = _dwc;
+	unsigned long flags;
+	irqreturn_t ret = IRQ_NONE;
+	int i;
+
+	spin_lock_irqsave(&dwc->lock, flags);
+
+	for (i = 0; i < dwc->num_event_buffers; i++) {
+		struct dwc3_event_buffer *evt;
+		int			left;
+
+		evt = dwc->ev_buffs[i];
+		left = evt->count;
+
+		if (!(evt->flags & DWC3_EVENT_PENDING))
+			continue;
+
+		while (left > 0) {
+			union dwc3_event event;
+
+			event.raw = *(u32 *) (evt->buf + evt->lpos);
+
+			dwc3_process_event_entry(dwc, &event);
+
+			/*
+			 * FIXME we wrap around correctly to the next entry as
+			 * almost all entries are 4 bytes in size. There is one
+			 * entry which has 12 bytes which is a regular entry
+			 * followed by 8 bytes data. ATM I don't know how
+			 * things are organized if we get next to the a
+			 * boundary so I worry about that once we try to handle
+			 * that.
+			 */
+			evt->lpos = (evt->lpos + 4) % DWC3_EVENT_BUFFERS_SIZE;
+			left -= 4;
+
+			dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(i), 4);
+		}
+
+		evt->count = 0;
+		evt->flags &= ~DWC3_EVENT_PENDING;
+		ret = IRQ_HANDLED;
+	}
+
+	spin_unlock_irqrestore(&dwc->lock, flags);
+
+	return ret;
+}
+
 static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc, u32 buf)
 {
 	struct dwc3_event_buffer *evt;
-	int left;
 	u32 count;
 
+	evt = dwc->ev_buffs[buf];
+
 	count = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(buf));
 	count &= DWC3_GEVNTCOUNT_MASK;
 	if (!count)
 		return IRQ_NONE;
 
-	evt = dwc->ev_buffs[buf];
-	left = count;
-
-	while (left > 0) {
-		union dwc3_event event;
-
-		event.raw = *(u32 *) (evt->buf + evt->lpos);
+	evt->count = count;
+	evt->flags |= DWC3_EVENT_PENDING;
 
-		dwc3_process_event_entry(dwc, &event);
-		/*
-		 * XXX we wrap around correctly to the next entry as almost all
-		 * entries are 4 bytes in size. There is one entry which has 12
-		 * bytes which is a regular entry followed by 8 bytes data. ATM
-		 * I don't know how things are organized if were get next to the
-		 * a boundary so I worry about that once we try to handle that.
-		 */
-		evt->lpos = (evt->lpos + 4) % DWC3_EVENT_BUFFERS_SIZE;
-		left -= 4;
-
-		dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(buf), 4);
-	}
-
-	return IRQ_HANDLED;
+	return IRQ_WAKE_THREAD;
 }
 
 static irqreturn_t dwc3_interrupt(int irq, void *_dwc)
@@ -2435,7 +2567,7 @@ static irqreturn_t dwc3_interrupt(int irq, void *_dwc)
 		irqreturn_t status;
 
 		status = dwc3_process_event_buf(dwc, i);
-		if (status == IRQ_HANDLED)
+		if (status == IRQ_WAKE_THREAD)
 			ret = status;
 	}
 
@@ -2454,7 +2586,6 @@ int dwc3_gadget_init(struct dwc3 *dwc)
 {
 	u32					reg;
 	int					ret;
-	int					irq;
 
 	dwc->ctrl_req = dma_alloc_coherent(dwc->dev, sizeof(*dwc->ctrl_req),
 			&dwc->ctrl_req_addr, GFP_KERNEL);
@@ -2488,19 +2619,10 @@ int dwc3_gadget_init(struct dwc3 *dwc)
 		goto err3;
 	}
 
-	dev_set_name(&dwc->gadget.dev, "gadget");
-
 	dwc->gadget.ops			= &dwc3_gadget_ops;
 	dwc->gadget.max_speed		= USB_SPEED_SUPER;
 	dwc->gadget.speed		= USB_SPEED_UNKNOWN;
-	dwc->gadget.dev.parent		= dwc->dev;
 	dwc->gadget.sg_supported	= true;
-
-	dma_set_coherent_mask(&dwc->gadget.dev, dwc->dev->coherent_dma_mask);
-
-	dwc->gadget.dev.dma_parms	= dwc->dev->dma_parms;
-	dwc->gadget.dev.dma_mask	= dwc->dev->dma_mask;
-	dwc->gadget.dev.release		= dwc3_gadget_release;
 	dwc->gadget.name		= "dwc3-gadget";
 
 	/*
@@ -2512,60 +2634,24 @@ int dwc3_gadget_init(struct dwc3 *dwc)
 	if (ret)
 		goto err4;
 
-	irq = platform_get_irq(to_platform_device(dwc->dev), 0);
-
-	ret = request_irq(irq, dwc3_interrupt, IRQF_SHARED,
-			"dwc3", dwc);
-	if (ret) {
-		dev_err(dwc->dev, "failed to request irq #%d --> %d\n",
-				irq, ret);
-		goto err5;
-	}
-
 	reg = dwc3_readl(dwc->regs, DWC3_DCFG);
 	reg |= DWC3_DCFG_LPM_CAP;
 	dwc3_writel(dwc->regs, DWC3_DCFG, reg);
 
-	/* Enable all but Start and End of Frame IRQs */
-	reg = (DWC3_DEVTEN_VNDRDEVTSTRCVEDEN |
-			DWC3_DEVTEN_EVNTOVERFLOWEN |
-			DWC3_DEVTEN_CMDCMPLTEN |
-			DWC3_DEVTEN_ERRTICERREN |
-			DWC3_DEVTEN_WKUPEVTEN |
-			DWC3_DEVTEN_ULSTCNGEN |
-			DWC3_DEVTEN_CONNECTDONEEN |
-			DWC3_DEVTEN_USBRSTEN |
-			DWC3_DEVTEN_DISCONNEVTEN);
-	dwc3_writel(dwc->regs, DWC3_DEVTEN, reg);
-
-	/* automatic phy suspend only on recent versions */
+	/* Enable USB2 LPM and automatic phy suspend only on recent versions */
 	if (dwc->revision >= DWC3_REVISION_194A) {
 		dwc3_gadget_usb2_phy_suspend(dwc, false);
 		dwc3_gadget_usb3_phy_suspend(dwc, false);
 	}
 
-	ret = device_register(&dwc->gadget.dev);
-	if (ret) {
-		dev_err(dwc->dev, "failed to register gadget device\n");
-		put_device(&dwc->gadget.dev);
-		goto err6;
-	}
-
 	ret = usb_add_gadget_udc(dwc->dev, &dwc->gadget);
 	if (ret) {
 		dev_err(dwc->dev, "failed to register udc\n");
-		goto err7;
+		goto err5;
 	}
 
 	return 0;
 
-err7:
-	device_unregister(&dwc->gadget.dev);
-
-err6:
-	dwc3_writel(dwc->regs, DWC3_DEVTEN, 0x00);
-	free_irq(irq, dwc);
-
 err5:
 	dwc3_gadget_free_endpoints(dwc);
 
@@ -2588,15 +2674,11 @@ err0:
 	return ret;
 }
 
+/* -------------------------------------------------------------------------- */
+
 void dwc3_gadget_exit(struct dwc3 *dwc)
 {
-	int			irq;
-
 	usb_del_gadget_udc(&dwc->gadget);
-	irq = platform_get_irq(to_platform_device(dwc->dev), 0);
-
-	dwc3_writel(dwc->regs, DWC3_DEVTEN, 0x00);
-	free_irq(irq, dwc);
 
 	dwc3_gadget_free_endpoints(dwc);
 
@@ -2610,6 +2692,63 @@ void dwc3_gadget_exit(struct dwc3 *dwc)
 
 	dma_free_coherent(dwc->dev, sizeof(*dwc->ctrl_req),
 			dwc->ctrl_req, dwc->ctrl_req_addr);
+}
 
-	device_unregister(&dwc->gadget.dev);
+int dwc3_gadget_prepare(struct dwc3 *dwc)
+{
+	if (dwc->pullups_connected)
+		dwc3_gadget_disable_irq(dwc);
+
+	return 0;
+}
+
+void dwc3_gadget_complete(struct dwc3 *dwc)
+{
+	if (dwc->pullups_connected) {
+		dwc3_gadget_enable_irq(dwc);
+		dwc3_gadget_run_stop(dwc, true);
+	}
+}
+
+int dwc3_gadget_suspend(struct dwc3 *dwc)
+{
+	__dwc3_gadget_ep_disable(dwc->eps[0]);
+	__dwc3_gadget_ep_disable(dwc->eps[1]);
+
+	dwc->dcfg = dwc3_readl(dwc->regs, DWC3_DCFG);
+
+	return 0;
+}
+
+int dwc3_gadget_resume(struct dwc3 *dwc)
+{
+	struct dwc3_ep		*dep;
+	int			ret;
+
+	/* Start with SuperSpeed Default */
+	dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512);
+
+	dep = dwc->eps[0];
+	ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, false);
+	if (ret)
+		goto err0;
+
+	dep = dwc->eps[1];
+	ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, false);
+	if (ret)
+		goto err1;
+
+	/* begin to receive SETUP packets */
+	dwc->ep0state = EP0_SETUP_PHASE;
+	dwc3_ep0_out_start(dwc);
+
+	dwc3_writel(dwc->regs, DWC3_DCFG, dwc->dcfg);
+
+	return 0;
+
+err1:
+	__dwc3_gadget_ep_disable(dwc->eps[0]);
+
+err0:
+	return ret;
 }
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index c7525b1..a61d981 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -196,7 +196,6 @@ config USB_OMAP
 	tristate "OMAP USB Device Controller"
 	depends on ARCH_OMAP1
 	select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_H4_OTG
-	select USB_OTG_UTILS if ARCH_OMAP
 	help
 	   Many Texas Instruments OMAP processors have flexible full
 	   speed USB device controllers, with support for up to 30
@@ -211,7 +210,6 @@ config USB_OMAP
 config USB_PXA25X
 	tristate "PXA 25x or IXP 4xx"
 	depends on (ARCH_PXA && PXA25x) || ARCH_IXP4XX
-	select USB_OTG_UTILS
 	help
 	   Intel's PXA 25x series XScale ARM-5TE processors include
 	   an integrated full speed USB 1.1 device controller.  The
@@ -259,8 +257,6 @@ config USB_RENESAS_USBHS_UDC
 
 config USB_PXA27X
 	tristate "PXA 27x"
-	depends on ARCH_PXA && (PXA27x || PXA3xx)
-	select USB_OTG_UTILS
 	help
 	   Intel's PXA 27x series XScale ARM v5TE processors include
 	   an integrated full speed USB 1.1 device controller.
@@ -329,9 +325,6 @@ config USB_MV_UDC
 
 config USB_MV_U3D
 	tristate "MARVELL PXA2128 USB 3.0 controller"
-	depends on CPU_MMP3
-	select USB_GADGET_DUALSPEED
-	select USB_GADGET_SUPERSPEED
 	help
 	  MARVELL PXA2128 Processor series include a super speed USB3.0 device
 	  controller, which support super speed USB peripheral.
@@ -501,6 +494,7 @@ endmenu
 # composite based drivers
 config USB_LIBCOMPOSITE
 	tristate
+	select CONFIGFS_FS
 	depends on USB_GADGET
 
 config USB_F_ACM
@@ -512,6 +506,12 @@ config USB_F_SS_LB
 config USB_U_SERIAL
 	tristate
 
+config USB_F_SERIAL
+	tristate
+
+config USB_F_OBEX
+	tristate
+
 choice
 	tristate "USB Gadget Drivers"
 	default USB_ETH
@@ -766,6 +766,8 @@ config USB_G_SERIAL
 	depends on TTY
 	select USB_U_SERIAL
 	select USB_F_ACM
+	select USB_F_SERIAL
+	select USB_F_OBEX
 	select USB_LIBCOMPOSITE
 	help
 	  The Serial Gadget talks to the Linux-USB generic serial driver.
@@ -839,6 +841,7 @@ config USB_G_NOKIA
 	depends on PHONET
 	select USB_LIBCOMPOSITE
 	select USB_U_SERIAL
+	select USB_F_ACM
 	help
 	  The Nokia composite gadget provides support for acm, obex
 	  and phonet in only one composite gadget driver.
@@ -957,6 +960,7 @@ config USB_G_WEBCAM
 	tristate "USB Webcam Gadget"
 	depends on VIDEO_DEV
 	select USB_LIBCOMPOSITE
+	select VIDEOBUF2_VMALLOC
 	help
 	  The Webcam Gadget acts as a composite USB Audio and Video Class
 	  device. It provides a userspace API to process UVC control requests
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 82fb225..6afd166 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -6,7 +6,7 @@ ccflags-$(CONFIG_USB_GADGET_DEBUG) := -DDEBUG
 obj-$(CONFIG_USB_GADGET)	+= udc-core.o
 obj-$(CONFIG_USB_LIBCOMPOSITE)	+= libcomposite.o
 libcomposite-y			:= usbstring.o config.o epautoconf.o
-libcomposite-y			+= composite.o functions.o
+libcomposite-y			+= composite.o functions.o configfs.o
 obj-$(CONFIG_USB_DUMMY_HCD)	+= dummy_hcd.o
 obj-$(CONFIG_USB_NET2272)	+= net2272.o
 obj-$(CONFIG_USB_NET2280)	+= net2280.o
@@ -36,10 +36,15 @@ obj-$(CONFIG_USB_FUSB300)	+= fusb300_udc.o
 obj-$(CONFIG_USB_MV_U3D)	+= mv_u3d_core.o
 
 # USB Functions
-obj-$(CONFIG_USB_F_ACM)		+= f_acm.o
-f_ss_lb-y			:= f_loopback.o f_sourcesink.o
-obj-$(CONFIG_USB_F_SS_LB)	+= f_ss_lb.o
+usb_f_acm-y			:= f_acm.o
+obj-$(CONFIG_USB_F_ACM)		+= usb_f_acm.o
+usb_f_ss_lb-y			:= f_loopback.o f_sourcesink.o
+obj-$(CONFIG_USB_F_SS_LB)	+= usb_f_ss_lb.o
 obj-$(CONFIG_USB_U_SERIAL)	+= u_serial.o
+usb_f_serial-y			:= f_serial.o
+obj-$(CONFIG_USB_F_SERIAL)	+= usb_f_serial.o
+usb_f_obex-y			:= f_obex.o
+obj-$(CONFIG_USB_F_OBEX)	+= usb_f_obex.o
 
 #
 # USB gadget drivers
diff --git a/drivers/usb/gadget/acm_ms.c b/drivers/usb/gadget/acm_ms.c
index 8f2b0e3..4b947bb 100644
--- a/drivers/usb/gadget/acm_ms.c
+++ b/drivers/usb/gadget/acm_ms.c
@@ -109,7 +109,6 @@ FSG_MODULE_PARAMETERS(/* no prefix */, fsg_mod_data);
 static struct fsg_common fsg_common;
 
 /*-------------------------------------------------------------------------*/
-static unsigned char tty_line;
 static struct usb_function *f_acm;
 static struct usb_function_instance *f_acm_inst;
 /*
@@ -117,7 +116,6 @@ static struct usb_function_instance *f_acm_inst;
  */
 static int __init acm_ms_do_config(struct usb_configuration *c)
 {
-	struct f_serial_opts *opts;
 	int	status;
 
 	if (gadget_is_otg(c->cdev->gadget)) {
@@ -129,9 +127,6 @@ static int __init acm_ms_do_config(struct usb_configuration *c)
 	if (IS_ERR(f_acm_inst))
 		return PTR_ERR(f_acm_inst);
 
-	opts = container_of(f_acm_inst, struct f_serial_opts, func_inst);
-	opts->port_num = tty_line;
-
 	f_acm = usb_get_function(f_acm_inst);
 	if (IS_ERR(f_acm)) {
 		status = PTR_ERR(f_acm);
@@ -171,16 +166,11 @@ static int __init acm_ms_bind(struct usb_composite_dev *cdev)
 	int			status;
 	void			*retp;
 
-	/* set up serial link layer */
-	status = gserial_alloc_line(&tty_line);
-	if (status < 0)
-		return status;
-
 	/* set up mass storage function */
 	retp = fsg_common_from_params(&fsg_common, cdev, &fsg_mod_data);
 	if (IS_ERR(retp)) {
 		status = PTR_ERR(retp);
-		goto fail0;
+		return PTR_ERR(retp);
 	}
 
 	/*
@@ -207,8 +197,6 @@ static int __init acm_ms_bind(struct usb_composite_dev *cdev)
 	/* error recovery */
 fail1:
 	fsg_common_put(&fsg_common);
-fail0:
-	gserial_free_line(tty_line);
 	return status;
 }
 
@@ -216,7 +204,6 @@ static int __exit acm_ms_unbind(struct usb_composite_dev *cdev)
 {
 	usb_put_function(f_acm);
 	usb_put_function_instance(f_acm_inst);
-	gserial_free_line(tty_line);
 	return 0;
 }
 
diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c
index 75973f3..24bd363 100644
--- a/drivers/usb/gadget/amd5536udc.c
+++ b/drivers/usb/gadget/amd5536udc.c
@@ -1922,7 +1922,6 @@ static int amd5536_udc_start(struct usb_gadget *g,
 
 	driver->driver.bus = NULL;
 	dev->driver = driver;
-	dev->gadget.dev.driver = &driver->driver;
 
 	/* Some gadget drivers use both ep0 directions.
 	 * NOTE: to gadget driver, ep0 is just one endpoint...
@@ -1973,7 +1972,6 @@ static int amd5536_udc_stop(struct usb_gadget *g,
 	shutdown(dev, driver);
 	spin_unlock_irqrestore(&dev->lock, flags);
 
-	dev->gadget.dev.driver = NULL;
 	dev->driver = NULL;
 
 	/* set SD */
@@ -3080,7 +3078,6 @@ static void udc_pci_remove(struct pci_dev *pdev)
 	if (dev->active)
 		pci_disable_device(pdev);
 
-	device_unregister(&dev->gadget.dev);
 	pci_set_drvdata(pdev, NULL);
 
 	udc_remove(dev);
@@ -3102,7 +3099,7 @@ static int init_dma_pools(struct udc *dev)
 	}
 
 	/* DMA setup */
-	dev->data_requests = dma_pool_create("data_requests", NULL,
+	dev->data_requests = dma_pool_create("data_requests", &dev->pdev->dev,
 		sizeof(struct udc_data_dma), 0, 0);
 	if (!dev->data_requests) {
 		DBG(dev, "can't get request data pool\n");
@@ -3114,7 +3111,7 @@ static int init_dma_pools(struct udc *dev)
 	dev->ep[UDC_EP0IN_IX].dma = &dev->regs->ctl;
 
 	/* dma desc for setup data */
-	dev->stp_requests = dma_pool_create("setup requests", NULL,
+	dev->stp_requests = dma_pool_create("setup requests", &dev->pdev->dev,
 		sizeof(struct udc_stp_dma), 0, 0);
 	if (!dev->stp_requests) {
 		DBG(dev, "can't get stp request pool\n");
@@ -3245,8 +3242,6 @@ static int udc_pci_probe(
 	dev->phys_addr = resource;
 	dev->irq = pdev->irq;
 	dev->pdev = pdev;
-	dev->gadget.dev.parent = &pdev->dev;
-	dev->gadget.dev.dma_mask = pdev->dev.dma_mask;
 
 	/* general probing */
 	if (udc_probe(dev) == 0)
@@ -3273,7 +3268,6 @@ static int udc_probe(struct udc *dev)
 	dev->gadget.ops = &udc_ops;
 
 	dev_set_name(&dev->gadget.dev, "gadget");
-	dev->gadget.dev.release = gadget_release;
 	dev->gadget.name = name;
 	dev->gadget.max_speed = USB_SPEED_HIGH;
 
@@ -3297,17 +3291,11 @@ 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);
+	retval = usb_add_gadget_udc_release(&udc->pdev->dev, &dev->gadget,
+			gadget_release);
 	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;
-	}
-
 	/* timer init */
 	init_timer(&udc_timer);
 	udc_timer.function = udc_timer_function;
diff --git a/drivers/usb/gadget/amd5536udc.h b/drivers/usb/gadget/amd5536udc.h
index f1bf32e..6744d3b 100644
--- a/drivers/usb/gadget/amd5536udc.h
+++ b/drivers/usb/gadget/amd5536udc.h
@@ -472,7 +472,6 @@ struct udc_request {
 
 	/* flags */
 	unsigned			dma_going : 1,
-					dma_mapping : 1,
 					dma_done : 1;
 	/* phys. address */
 	dma_addr_t			td_phys;
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
index 45dd292..073b938 100644
--- a/drivers/usb/gadget/at91_udc.c
+++ b/drivers/usb/gadget/at91_udc.c
@@ -221,7 +221,7 @@ static int proc_udc_show(struct seq_file *s, void *unused)
 
 static int proc_udc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, proc_udc_show, PDE(inode)->data);
+	return single_open(file, proc_udc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations proc_ops = {
@@ -1631,7 +1631,6 @@ static int at91_start(struct usb_gadget *gadget,
 
 	udc = container_of(gadget, struct at91_udc, gadget);
 	udc->driver = driver;
-	udc->gadget.dev.driver = &driver->driver;
 	udc->gadget.dev.of_node = udc->pdev->dev.of_node;
 	udc->enabled = 1;
 	udc->selfpowered = 1;
@@ -1652,7 +1651,6 @@ static int at91_stop(struct usb_gadget *gadget,
 	at91_udp_write(udc, AT91_UDP_IDR, ~0);
 	spin_unlock_irqrestore(&udc->lock, flags);
 
-	udc->gadget.dev.driver = NULL;
 	udc->driver = NULL;
 
 	DBG("unbound from %s\n", driver->driver.name);
@@ -1780,13 +1778,7 @@ static int at91udc_probe(struct platform_device *pdev)
 		DBG("clocks missing\n");
 		retval = -ENODEV;
 		/* NOTE: we "know" here that refcounts on these are NOPs */
-		goto fail0b;
-	}
-
-	retval = device_register(&udc->gadget.dev);
-	if (retval < 0) {
-		put_device(&udc->gadget.dev);
-		goto fail0b;
+		goto fail1;
 	}
 
 	/* don't do anything until we have both gadget driver and VBUS */
@@ -1857,8 +1849,6 @@ fail3:
 fail2:
 	free_irq(udc->udp_irq, udc);
 fail1:
-	device_unregister(&udc->gadget.dev);
-fail0b:
 	iounmap(udc->udp_baseaddr);
 fail0a:
 	if (cpu_is_at91rm9200())
@@ -1892,8 +1882,6 @@ static int __exit at91udc_remove(struct platform_device *pdev)
 		gpio_free(udc->board.vbus_pin);
 	}
 	free_irq(udc->udp_irq, udc);
-	device_unregister(&udc->gadget.dev);
-
 	iounmap(udc->udp_baseaddr);
 
 	if (cpu_is_at91rm9200())
diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c
index b66130c..f2a970f 100644
--- a/drivers/usb/gadget/atmel_usba_udc.c
+++ b/drivers/usb/gadget/atmel_usba_udc.c
@@ -489,13 +489,8 @@ request_complete(struct usba_ep *ep, struct usba_request *req, int status)
 	if (req->req.status == -EINPROGRESS)
 		req->req.status = status;
 
-	if (req->mapped) {
-		dma_unmap_single(
-			&udc->pdev->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 (req->using_dma)
+		usb_gadget_unmap_request(&udc->gadget, &req->req, ep->is_in);
 
 	DBG(DBG_GADGET | DBG_REQ,
 		"%s: req %p complete: status %d, actual %u\n",
@@ -684,7 +679,6 @@ usba_ep_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
 		return NULL;
 
 	INIT_LIST_HEAD(&req->queue);
-	req->req.dma = DMA_ADDR_INVALID;
 
 	return &req->req;
 }
@@ -717,20 +711,11 @@ static int queue_dma(struct usba_udc *udc, struct usba_ep *ep,
 		return -EINVAL;
 	}
 
-	req->using_dma = 1;
-
-	if (req->req.dma == DMA_ADDR_INVALID) {
-		req->req.dma = dma_map_single(
-			&udc->pdev->dev, req->req.buf, req->req.length,
-			ep->is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
-		req->mapped = 1;
-	} else {
-		dma_sync_single_for_device(
-			&udc->pdev->dev, req->req.dma, req->req.length,
-			ep->is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
-		req->mapped = 0;
-	}
+	ret = usb_gadget_map_request(&udc->gadget, &req->req, ep->is_in);
+	if (ret)
+		return ret;
 
+	req->using_dma = 1;
 	req->ctrl = USBA_BF(DMA_BUF_LEN, req->req.length)
 			| USBA_DMA_CH_EN | USBA_DMA_END_BUF_IE
 			| USBA_DMA_END_TR_EN | USBA_DMA_END_TR_IE;
@@ -1799,7 +1784,6 @@ static int atmel_usba_start(struct usb_gadget *gadget,
 
 	udc->devstatus = 1 << USB_DEVICE_SELF_POWERED;
 	udc->driver = driver;
-	udc->gadget.dev.driver = &driver->driver;
 	spin_unlock_irqrestore(&udc->lock, flags);
 
 	clk_enable(udc->pclk);
@@ -1841,7 +1825,6 @@ static int atmel_usba_stop(struct usb_gadget *gadget,
 	toggle_bias(0);
 	usba_writel(udc, CTRL, USBA_DISABLE_MASK);
 
-	udc->gadget.dev.driver = NULL;
 	udc->driver = NULL;
 
 	clk_disable(udc->hclk);
@@ -1900,10 +1883,6 @@ static int __init usba_udc_probe(struct platform_device *pdev)
 	dev_info(&pdev->dev, "FIFO at 0x%08lx mapped at %p\n",
 		 (unsigned long)fifo->start, udc->fifo);
 
-	device_initialize(&udc->gadget.dev);
-	udc->gadget.dev.parent = &pdev->dev;
-	udc->gadget.dev.dma_mask = pdev->dev.dma_mask;
-
 	platform_set_drvdata(pdev, udc);
 
 	/* Make sure we start from a clean slate */
@@ -1962,12 +1941,6 @@ static int __init usba_udc_probe(struct platform_device *pdev)
 	}
 	udc->irq = irq;
 
-	ret = device_add(&udc->gadget.dev);
-	if (ret) {
-		dev_dbg(&pdev->dev, "Could not add gadget: %d\n", ret);
-		goto err_device_add;
-	}
-
 	if (gpio_is_valid(pdata->vbus_pin)) {
 		if (!gpio_request(pdata->vbus_pin, "atmel_usba_udc")) {
 			udc->vbus_pin = pdata->vbus_pin;
@@ -2007,9 +1980,6 @@ err_add_udc:
 		gpio_free(udc->vbus_pin);
 	}
 
-	device_unregister(&udc->gadget.dev);
-
-err_device_add:
 	free_irq(irq, udc);
 err_request_irq:
 	kfree(usba_ep);
@@ -2053,8 +2023,6 @@ static int __exit usba_udc_remove(struct platform_device *pdev)
 	clk_put(udc->hclk);
 	clk_put(udc->pclk);
 
-	device_unregister(&udc->gadget.dev);
-
 	return 0;
 }
 
diff --git a/drivers/usb/gadget/atmel_usba_udc.h b/drivers/usb/gadget/atmel_usba_udc.h
index 9791259..d65a618 100644
--- a/drivers/usb/gadget/atmel_usba_udc.h
+++ b/drivers/usb/gadget/atmel_usba_udc.h
@@ -216,12 +216,6 @@
 #define EP0_EPT_SIZE		USBA_EPT_SIZE_64
 #define EP0_NR_BANKS		1
 
-/*
- * REVISIT: Try to eliminate this value. Can we rely on req->mapped to
- * provide this information?
- */
-#define DMA_ADDR_INVALID (~(dma_addr_t)0)
-
 #define FIFO_IOMEM_ID	0
 #define CTRL_IOMEM_ID	1
 
diff --git a/drivers/usb/gadget/bcm63xx_udc.c b/drivers/usb/gadget/bcm63xx_udc.c
index 8cc8253..6e65182 100644
--- a/drivers/usb/gadget/bcm63xx_udc.c
+++ b/drivers/usb/gadget/bcm63xx_udc.c
@@ -1819,7 +1819,6 @@ static int bcm63xx_udc_start(struct usb_gadget *gadget,
 
 	udc->driver = driver;
 	driver->driver.bus = NULL;
-	udc->gadget.dev.driver = &driver->driver;
 	udc->gadget.dev.of_node = udc->dev->of_node;
 
 	spin_unlock_irqrestore(&udc->lock, flags);
@@ -1841,7 +1840,6 @@ static int bcm63xx_udc_stop(struct usb_gadget *gadget,
 	spin_lock_irqsave(&udc->lock, flags);
 
 	udc->driver = NULL;
-	udc->gadget.dev.driver = NULL;
 
 	/*
 	 * If we switch the PHY too abruptly after dropping D+, the host
@@ -2306,17 +2304,6 @@ static void bcm63xx_udc_cleanup_debugfs(struct bcm63xx_udc *udc)
  ***********************************************************************/
 
 /**
- * bcm63xx_udc_gadget_release - Called from device_release().
- * @dev: Unused.
- *
- * We get a warning if this function doesn't exist, but it's empty because
- * we don't have to free any of the memory allocated with the devm_* APIs.
- */
-static void bcm63xx_udc_gadget_release(struct device *dev)
-{
-}
-
-/**
  * bcm63xx_udc_probe - Initialize a new instance of the UDC.
  * @pdev: Platform device struct from the bcm63xx BSP code.
  *
@@ -2368,13 +2355,9 @@ static int bcm63xx_udc_probe(struct platform_device *pdev)
 
 	spin_lock_init(&udc->lock);
 	INIT_WORK(&udc->ep0_wq, bcm63xx_ep0_process);
-	dev_set_name(&udc->gadget.dev, "gadget");
 
 	udc->gadget.ops = &bcm63xx_udc_ops;
 	udc->gadget.name = dev_name(dev);
-	udc->gadget.dev.parent = dev;
-	udc->gadget.dev.release = bcm63xx_udc_gadget_release;
-	udc->gadget.dev.dma_mask = dev->dma_mask;
 
 	if (!pd->use_fullspeed && !use_fullspeed)
 		udc->gadget.max_speed = USB_SPEED_HIGH;
@@ -2414,17 +2397,12 @@ static int bcm63xx_udc_probe(struct platform_device *pdev)
 		}
 	}
 
-	rc = device_register(&udc->gadget.dev);
-	if (rc)
-		goto out_uninit;
-
 	bcm63xx_udc_init_debugfs(udc);
 	rc = usb_add_gadget_udc(dev, &udc->gadget);
 	if (!rc)
 		return 0;
 
 	bcm63xx_udc_cleanup_debugfs(udc);
-	device_unregister(&udc->gadget.dev);
 out_uninit:
 	bcm63xx_uninit_udc_hw(udc);
 	return rc;
@@ -2440,7 +2418,6 @@ static int bcm63xx_udc_remove(struct platform_device *pdev)
 
 	bcm63xx_udc_cleanup_debugfs(udc);
 	usb_del_gadget_udc(&udc->gadget);
-	device_unregister(&udc->gadget.dev);
 	BUG_ON(udc->driver);
 
 	platform_set_drvdata(pdev, NULL);
diff --git a/drivers/usb/gadget/cdc2.c b/drivers/usb/gadget/cdc2.c
index a7d6f70..c6ee6f1 100644
--- a/drivers/usb/gadget/cdc2.c
+++ b/drivers/usb/gadget/cdc2.c
@@ -103,18 +103,16 @@ static struct usb_gadget_strings *dev_strings[] = {
 };
 
 static u8 hostaddr[ETH_ALEN];
-
+static struct eth_dev *the_dev;
 /*-------------------------------------------------------------------------*/
 static struct usb_function *f_acm;
 static struct usb_function_instance *fi_serial;
 
-static unsigned char tty_line;
 /*
  * We _always_ have both CDC ECM and CDC ACM functions.
  */
 static int __init cdc_do_config(struct usb_configuration *c)
 {
-	struct f_serial_opts *opts;
 	int	status;
 
 	if (gadget_is_otg(c->cdev->gadget)) {
@@ -122,7 +120,7 @@ static int __init cdc_do_config(struct usb_configuration *c)
 		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 	}
 
-	status = ecm_bind_config(c, hostaddr);
+	status = ecm_bind_config(c, hostaddr, the_dev);
 	if (status < 0)
 		return status;
 
@@ -130,9 +128,6 @@ static int __init cdc_do_config(struct usb_configuration *c)
 	if (IS_ERR(fi_serial))
 		return PTR_ERR(fi_serial);
 
-	opts = container_of(fi_serial, struct f_serial_opts, func_inst);
-	opts->port_num = tty_line;
-
 	f_acm = usb_get_function(fi_serial);
 	if (IS_ERR(f_acm))
 		goto err_func_acm;
@@ -169,14 +164,9 @@ static int __init cdc_bind(struct usb_composite_dev *cdev)
 	}
 
 	/* set up network link layer */
-	status = gether_setup(cdev->gadget, hostaddr);
-	if (status < 0)
-		return status;
-
-	/* set up serial link layer */
-	status = gserial_alloc_line(&tty_line);
-	if (status < 0)
-		goto fail0;
+	the_dev = gether_setup(cdev->gadget, hostaddr);
+	if (IS_ERR(the_dev))
+		return PTR_ERR(the_dev);
 
 	/* Allocate string descriptor numbers ... note that string
 	 * contents can be overridden by the composite_dev glue.
@@ -200,9 +190,7 @@ static int __init cdc_bind(struct usb_composite_dev *cdev)
 	return 0;
 
 fail1:
-	gserial_free_line(tty_line);
-fail0:
-	gether_cleanup();
+	gether_cleanup(the_dev);
 	return status;
 }
 
@@ -210,8 +198,7 @@ static int __exit cdc_unbind(struct usb_composite_dev *cdev)
 {
 	usb_put_function(f_acm);
 	usb_put_function_instance(fi_serial);
-	gserial_free_line(tty_line);
-	gether_cleanup();
+	gether_cleanup(the_dev);
 	return 0;
 }
 
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index c0d62b2..55f4df6 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -1637,6 +1637,7 @@ void composite_dev_cleanup(struct usb_composite_dev *cdev)
 		kfree(cdev->req->buf);
 		usb_ep_free_request(cdev->gadget->ep0, cdev->req);
 	}
+	cdev->next_string_id = 0;
 	device_remove_file(&cdev->gadget->dev, &dev_attr_suspended);
 }
 
diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c
new file mode 100644
index 0000000..a34633a
--- /dev/null
+++ b/drivers/usb/gadget/configfs.c
@@ -0,0 +1,1003 @@
+#include <linux/configfs.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/usb/composite.h>
+#include <linux/usb/gadget_configfs.h>
+
+int check_user_usb_string(const char *name,
+		struct usb_gadget_strings *stringtab_dev)
+{
+	unsigned primary_lang;
+	unsigned sub_lang;
+	u16 num;
+	int ret;
+
+	ret = kstrtou16(name, 0, &num);
+	if (ret)
+		return ret;
+
+	primary_lang = num & 0x3ff;
+	sub_lang = num >> 10;
+
+	/* simple sanity check for valid langid */
+	switch (primary_lang) {
+	case 0:
+	case 0x62 ... 0xfe:
+	case 0x100 ... 0x3ff:
+		return -EINVAL;
+	}
+	if (!sub_lang)
+		return -EINVAL;
+
+	stringtab_dev->language = num;
+	return 0;
+}
+
+#define MAX_NAME_LEN	40
+#define MAX_USB_STRING_LANGS 2
+
+struct gadget_info {
+	struct config_group group;
+	struct config_group functions_group;
+	struct config_group configs_group;
+	struct config_group strings_group;
+	struct config_group *default_groups[4];
+
+	struct mutex lock;
+	struct usb_gadget_strings *gstrings[MAX_USB_STRING_LANGS + 1];
+	struct list_head string_list;
+	struct list_head available_func;
+
+	const char *udc_name;
+#ifdef CONFIG_USB_OTG
+	struct usb_otg_descriptor otg;
+#endif
+	struct usb_composite_driver composite;
+	struct usb_composite_dev cdev;
+};
+
+struct config_usb_cfg {
+	struct config_group group;
+	struct config_group strings_group;
+	struct config_group *default_groups[2];
+	struct list_head string_list;
+	struct usb_configuration c;
+	struct list_head func_list;
+	struct usb_gadget_strings *gstrings[MAX_USB_STRING_LANGS + 1];
+};
+
+struct gadget_strings {
+	struct usb_gadget_strings stringtab_dev;
+	struct usb_string strings[USB_GADGET_FIRST_AVAIL_IDX];
+	char *manufacturer;
+	char *product;
+	char *serialnumber;
+
+	struct config_group group;
+	struct list_head list;
+};
+
+struct gadget_config_name {
+	struct usb_gadget_strings stringtab_dev;
+	struct usb_string strings;
+	char *configuration;
+
+	struct config_group group;
+	struct list_head list;
+};
+
+static int usb_string_copy(const char *s, char **s_copy)
+{
+	int ret;
+	char *str;
+	char *copy = *s_copy;
+	ret = strlen(s);
+	if (ret > 126)
+		return -EOVERFLOW;
+
+	str = kstrdup(s, GFP_KERNEL);
+	if (!str)
+		return -ENOMEM;
+	if (str[ret - 1] == '\n')
+		str[ret - 1] = '\0';
+	kfree(copy);
+	*s_copy = str;
+	return 0;
+}
+
+CONFIGFS_ATTR_STRUCT(gadget_info);
+CONFIGFS_ATTR_STRUCT(config_usb_cfg);
+
+#define GI_DEVICE_DESC_ITEM_ATTR(name)	\
+	static struct gadget_info_attribute gadget_cdev_desc_##name = \
+		__CONFIGFS_ATTR(name,  S_IRUGO | S_IWUSR,		\
+				gadget_dev_desc_##name##_show,		\
+				gadget_dev_desc_##name##_store)
+
+#define GI_DEVICE_DESC_SIMPLE_R_u8(__name)	\
+	static ssize_t gadget_dev_desc_##__name##_show(struct gadget_info *gi, \
+			char *page)	\
+{	\
+	return sprintf(page, "0x%02x\n", gi->cdev.desc.__name);	\
+}
+
+#define GI_DEVICE_DESC_SIMPLE_R_u16(__name)	\
+	static ssize_t gadget_dev_desc_##__name##_show(struct gadget_info *gi, \
+			char *page)	\
+{	\
+	return sprintf(page, "0x%04x\n", le16_to_cpup(&gi->cdev.desc.__name)); \
+}
+
+
+#define GI_DEVICE_DESC_SIMPLE_W_u8(_name)		\
+	static ssize_t gadget_dev_desc_##_name##_store(struct gadget_info *gi, \
+		const char *page, size_t len)		\
+{							\
+	u8 val;						\
+	int ret;					\
+	ret = kstrtou8(page, 0, &val);			\
+	if (ret)					\
+		return ret;				\
+	gi->cdev.desc._name = val;			\
+	return len;					\
+}
+
+#define GI_DEVICE_DESC_SIMPLE_W_u16(_name)	\
+	static ssize_t gadget_dev_desc_##_name##_store(struct gadget_info *gi, \
+		const char *page, size_t len)		\
+{							\
+	u16 val;					\
+	int ret;					\
+	ret = kstrtou16(page, 0, &val);			\
+	if (ret)					\
+		return ret;				\
+	gi->cdev.desc._name = cpu_to_le16p(&val);	\
+	return len;					\
+}
+
+#define GI_DEVICE_DESC_SIMPLE_RW(_name, _type)	\
+	GI_DEVICE_DESC_SIMPLE_R_##_type(_name)	\
+	GI_DEVICE_DESC_SIMPLE_W_##_type(_name)
+
+GI_DEVICE_DESC_SIMPLE_R_u16(bcdUSB);
+GI_DEVICE_DESC_SIMPLE_RW(bDeviceClass, u8);
+GI_DEVICE_DESC_SIMPLE_RW(bDeviceSubClass, u8);
+GI_DEVICE_DESC_SIMPLE_RW(bDeviceProtocol, u8);
+GI_DEVICE_DESC_SIMPLE_RW(bMaxPacketSize0, u8);
+GI_DEVICE_DESC_SIMPLE_RW(idVendor, u16);
+GI_DEVICE_DESC_SIMPLE_RW(idProduct, u16);
+GI_DEVICE_DESC_SIMPLE_R_u16(bcdDevice);
+
+static ssize_t is_valid_bcd(u16 bcd_val)
+{
+	if ((bcd_val & 0xf) > 9)
+		return -EINVAL;
+	if (((bcd_val >> 4) & 0xf) > 9)
+		return -EINVAL;
+	if (((bcd_val >> 8) & 0xf) > 9)
+		return -EINVAL;
+	if (((bcd_val >> 12) & 0xf) > 9)
+		return -EINVAL;
+	return 0;
+}
+
+static ssize_t gadget_dev_desc_bcdDevice_store(struct gadget_info *gi,
+		const char *page, size_t len)
+{
+	u16 bcdDevice;
+	int ret;
+
+	ret = kstrtou16(page, 0, &bcdDevice);
+	if (ret)
+		return ret;
+	ret = is_valid_bcd(bcdDevice);
+	if (ret)
+		return ret;
+
+	gi->cdev.desc.bcdDevice = cpu_to_le16(bcdDevice);
+	return len;
+}
+
+static ssize_t gadget_dev_desc_bcdUSB_store(struct gadget_info *gi,
+		const char *page, size_t len)
+{
+	u16 bcdUSB;
+	int ret;
+
+	ret = kstrtou16(page, 0, &bcdUSB);
+	if (ret)
+		return ret;
+	ret = is_valid_bcd(bcdUSB);
+	if (ret)
+		return ret;
+
+	gi->cdev.desc.bcdUSB = cpu_to_le16(bcdUSB);
+	return len;
+}
+
+static ssize_t gadget_dev_desc_UDC_show(struct gadget_info *gi, char *page)
+{
+	return sprintf(page, "%s\n", gi->udc_name ?: "");
+}
+
+static int unregister_gadget(struct gadget_info *gi)
+{
+	int ret;
+
+	if (!gi->udc_name)
+		return -ENODEV;
+
+	ret = usb_gadget_unregister_driver(&gi->composite.gadget_driver);
+	if (ret)
+		return ret;
+	kfree(gi->udc_name);
+	gi->udc_name = NULL;
+	return 0;
+}
+
+static ssize_t gadget_dev_desc_UDC_store(struct gadget_info *gi,
+		const char *page, size_t len)
+{
+	char *name;
+	int ret;
+
+	name = kstrdup(page, GFP_KERNEL);
+	if (!name)
+		return -ENOMEM;
+	if (name[len - 1] == '\n')
+		name[len - 1] = '\0';
+
+	mutex_lock(&gi->lock);
+
+	if (!strlen(name)) {
+		ret = unregister_gadget(gi);
+		if (ret)
+			goto err;
+	} else {
+		if (gi->udc_name) {
+			ret = -EBUSY;
+			goto err;
+		}
+		ret = udc_attach_driver(name, &gi->composite.gadget_driver);
+		if (ret)
+			goto err;
+		gi->udc_name = name;
+	}
+	mutex_unlock(&gi->lock);
+	return len;
+err:
+	kfree(name);
+	mutex_unlock(&gi->lock);
+	return ret;
+}
+
+GI_DEVICE_DESC_ITEM_ATTR(bDeviceClass);
+GI_DEVICE_DESC_ITEM_ATTR(bDeviceSubClass);
+GI_DEVICE_DESC_ITEM_ATTR(bDeviceProtocol);
+GI_DEVICE_DESC_ITEM_ATTR(bMaxPacketSize0);
+GI_DEVICE_DESC_ITEM_ATTR(idVendor);
+GI_DEVICE_DESC_ITEM_ATTR(idProduct);
+GI_DEVICE_DESC_ITEM_ATTR(bcdDevice);
+GI_DEVICE_DESC_ITEM_ATTR(bcdUSB);
+GI_DEVICE_DESC_ITEM_ATTR(UDC);
+
+static struct configfs_attribute *gadget_root_attrs[] = {
+	&gadget_cdev_desc_bDeviceClass.attr,
+	&gadget_cdev_desc_bDeviceSubClass.attr,
+	&gadget_cdev_desc_bDeviceProtocol.attr,
+	&gadget_cdev_desc_bMaxPacketSize0.attr,
+	&gadget_cdev_desc_idVendor.attr,
+	&gadget_cdev_desc_idProduct.attr,
+	&gadget_cdev_desc_bcdDevice.attr,
+	&gadget_cdev_desc_bcdUSB.attr,
+	&gadget_cdev_desc_UDC.attr,
+	NULL,
+};
+
+static inline struct gadget_info *to_gadget_info(struct config_item *item)
+{
+	 return container_of(to_config_group(item), struct gadget_info, group);
+}
+
+static inline struct gadget_strings *to_gadget_strings(struct config_item *item)
+{
+	 return container_of(to_config_group(item), struct gadget_strings,
+			 group);
+}
+
+static inline struct gadget_config_name *to_gadget_config_name(
+		struct config_item *item)
+{
+	 return container_of(to_config_group(item), struct gadget_config_name,
+			 group);
+}
+
+static inline struct config_usb_cfg *to_config_usb_cfg(struct config_item *item)
+{
+	return container_of(to_config_group(item), struct config_usb_cfg,
+			group);
+}
+
+static inline struct usb_function_instance *to_usb_function_instance(
+		struct config_item *item)
+{
+	 return container_of(to_config_group(item),
+			 struct usb_function_instance, group);
+}
+
+static void gadget_info_attr_release(struct config_item *item)
+{
+	struct gadget_info *gi = to_gadget_info(item);
+
+	WARN_ON(!list_empty(&gi->cdev.configs));
+	WARN_ON(!list_empty(&gi->string_list));
+	WARN_ON(!list_empty(&gi->available_func));
+	kfree(gi->composite.gadget_driver.function);
+	kfree(gi);
+}
+
+CONFIGFS_ATTR_OPS(gadget_info);
+
+static struct configfs_item_operations gadget_root_item_ops = {
+	.release                = gadget_info_attr_release,
+	.show_attribute         = gadget_info_attr_show,
+	.store_attribute        = gadget_info_attr_store,
+};
+
+static void gadget_config_attr_release(struct config_item *item)
+{
+	struct config_usb_cfg *cfg = to_config_usb_cfg(item);
+
+	WARN_ON(!list_empty(&cfg->c.functions));
+	list_del(&cfg->c.list);
+	kfree(cfg->c.label);
+	kfree(cfg);
+}
+
+static int config_usb_cfg_link(
+	struct config_item *usb_cfg_ci,
+	struct config_item *usb_func_ci)
+{
+	struct config_usb_cfg *cfg = to_config_usb_cfg(usb_cfg_ci);
+	struct usb_composite_dev *cdev = cfg->c.cdev;
+	struct gadget_info *gi = container_of(cdev, struct gadget_info, cdev);
+
+	struct config_group *group = to_config_group(usb_func_ci);
+	struct usb_function_instance *fi = container_of(group,
+			struct usb_function_instance, group);
+	struct usb_function_instance *a_fi;
+	struct usb_function *f;
+	int ret;
+
+	mutex_lock(&gi->lock);
+	/*
+	 * Make sure this function is from within our _this_ gadget and not
+	 * from another gadget or a random directory.
+	 * Also a function instance can only be linked once.
+	 */
+	list_for_each_entry(a_fi, &gi->available_func, cfs_list) {
+		if (a_fi == fi)
+			break;
+	}
+	if (a_fi != fi) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	list_for_each_entry(f, &cfg->func_list, list) {
+		if (f->fi == fi) {
+			ret = -EEXIST;
+			goto out;
+		}
+	}
+
+	f = usb_get_function(fi);
+	if (IS_ERR(f)) {
+		ret = PTR_ERR(f);
+		goto out;
+	}
+
+	/* stash the function until we bind it to the gadget */
+	list_add_tail(&f->list, &cfg->func_list);
+	ret = 0;
+out:
+	mutex_unlock(&gi->lock);
+	return ret;
+}
+
+static int config_usb_cfg_unlink(
+	struct config_item *usb_cfg_ci,
+	struct config_item *usb_func_ci)
+{
+	struct config_usb_cfg *cfg = to_config_usb_cfg(usb_cfg_ci);
+	struct usb_composite_dev *cdev = cfg->c.cdev;
+	struct gadget_info *gi = container_of(cdev, struct gadget_info, cdev);
+
+	struct config_group *group = to_config_group(usb_func_ci);
+	struct usb_function_instance *fi = container_of(group,
+			struct usb_function_instance, group);
+	struct usb_function *f;
+
+	/*
+	 * ideally I would like to forbid to unlink functions while a gadget is
+	 * bound to an UDC. Since this isn't possible at the moment, we simply
+	 * force an unbind, the function is available here and then we can
+	 * remove the function.
+	 */
+	mutex_lock(&gi->lock);
+	if (gi->udc_name)
+		unregister_gadget(gi);
+	WARN_ON(gi->udc_name);
+
+	list_for_each_entry(f, &cfg->func_list, list) {
+		if (f->fi == fi) {
+			list_del(&f->list);
+			usb_put_function(f);
+			mutex_unlock(&gi->lock);
+			return 0;
+		}
+	}
+	mutex_unlock(&gi->lock);
+	__WARN_printf("Unable to locate function to unbind\n");
+	return 0;
+}
+
+CONFIGFS_ATTR_OPS(config_usb_cfg);
+
+static struct configfs_item_operations gadget_config_item_ops = {
+	.release                = gadget_config_attr_release,
+	.show_attribute         = config_usb_cfg_attr_show,
+	.store_attribute        = config_usb_cfg_attr_store,
+	.allow_link             = config_usb_cfg_link,
+	.drop_link              = config_usb_cfg_unlink,
+};
+
+
+static ssize_t gadget_config_desc_MaxPower_show(struct config_usb_cfg *cfg,
+		char *page)
+{
+	return sprintf(page, "%u\n", cfg->c.MaxPower);
+}
+
+static ssize_t gadget_config_desc_MaxPower_store(struct config_usb_cfg *cfg,
+		const char *page, size_t len)
+{
+	u16 val;
+	int ret;
+	ret = kstrtou16(page, 0, &val);
+	if (ret)
+		return ret;
+	if (DIV_ROUND_UP(val, 8) > 0xff)
+		return -ERANGE;
+	cfg->c.MaxPower = val;
+	return len;
+}
+
+static ssize_t gadget_config_desc_bmAttributes_show(struct config_usb_cfg *cfg,
+		char *page)
+{
+	return sprintf(page, "0x%02x\n", cfg->c.bmAttributes);
+}
+
+static ssize_t gadget_config_desc_bmAttributes_store(struct config_usb_cfg *cfg,
+		const char *page, size_t len)
+{
+	u8 val;
+	int ret;
+	ret = kstrtou8(page, 0, &val);
+	if (ret)
+		return ret;
+	if (!(val & USB_CONFIG_ATT_ONE))
+		return -EINVAL;
+	if (val & ~(USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER |
+				USB_CONFIG_ATT_WAKEUP))
+		return -EINVAL;
+	cfg->c.bmAttributes = val;
+	return len;
+}
+
+#define CFG_CONFIG_DESC_ITEM_ATTR(name)	\
+	static struct config_usb_cfg_attribute gadget_usb_cfg_##name = \
+		__CONFIGFS_ATTR(name,  S_IRUGO | S_IWUSR,		\
+				gadget_config_desc_##name##_show,	\
+				gadget_config_desc_##name##_store)
+
+CFG_CONFIG_DESC_ITEM_ATTR(MaxPower);
+CFG_CONFIG_DESC_ITEM_ATTR(bmAttributes);
+
+static struct configfs_attribute *gadget_config_attrs[] = {
+	&gadget_usb_cfg_MaxPower.attr,
+	&gadget_usb_cfg_bmAttributes.attr,
+	NULL,
+};
+
+static struct config_item_type gadget_config_type = {
+	.ct_item_ops	= &gadget_config_item_ops,
+	.ct_attrs	= gadget_config_attrs,
+	.ct_owner	= THIS_MODULE,
+};
+
+static struct config_item_type gadget_root_type = {
+	.ct_item_ops	= &gadget_root_item_ops,
+	.ct_attrs	= gadget_root_attrs,
+	.ct_owner	= THIS_MODULE,
+};
+
+static void composite_init_dev(struct usb_composite_dev *cdev)
+{
+	spin_lock_init(&cdev->lock);
+	INIT_LIST_HEAD(&cdev->configs);
+	INIT_LIST_HEAD(&cdev->gstrings);
+}
+
+static struct config_group *function_make(
+		struct config_group *group,
+		const char *name)
+{
+	struct gadget_info *gi;
+	struct usb_function_instance *fi;
+	char buf[MAX_NAME_LEN];
+	char *func_name;
+	char *instance_name;
+	int ret;
+
+	ret = snprintf(buf, MAX_NAME_LEN, "%s", name);
+	if (ret >= MAX_NAME_LEN)
+		return ERR_PTR(-ENAMETOOLONG);
+
+	func_name = buf;
+	instance_name = strchr(func_name, '.');
+	if (!instance_name) {
+		pr_err("Unable to locate . in FUNC.INSTANCE\n");
+		return ERR_PTR(-EINVAL);
+	}
+	*instance_name = '\0';
+	instance_name++;
+
+	fi = usb_get_function_instance(func_name);
+	if (IS_ERR(fi))
+		return ERR_PTR(PTR_ERR(fi));
+
+	ret = config_item_set_name(&fi->group.cg_item, name);
+	if (ret) {
+		usb_put_function_instance(fi);
+		return ERR_PTR(ret);
+	}
+
+	gi = container_of(group, struct gadget_info, functions_group);
+
+	mutex_lock(&gi->lock);
+	list_add_tail(&fi->cfs_list, &gi->available_func);
+	mutex_unlock(&gi->lock);
+	return &fi->group;
+}
+
+static void function_drop(
+		struct config_group *group,
+		struct config_item *item)
+{
+	struct usb_function_instance *fi = to_usb_function_instance(item);
+	struct gadget_info *gi;
+
+	gi = container_of(group, struct gadget_info, functions_group);
+
+	mutex_lock(&gi->lock);
+	list_del(&fi->cfs_list);
+	mutex_unlock(&gi->lock);
+	config_item_put(item);
+}
+
+static struct configfs_group_operations functions_ops = {
+	.make_group     = &function_make,
+	.drop_item      = &function_drop,
+};
+
+static struct config_item_type functions_type = {
+	.ct_group_ops   = &functions_ops,
+	.ct_owner       = THIS_MODULE,
+};
+
+CONFIGFS_ATTR_STRUCT(gadget_config_name);
+GS_STRINGS_RW(gadget_config_name, configuration);
+
+static struct configfs_attribute *gadget_config_name_langid_attrs[] = {
+	&gadget_config_name_configuration.attr,
+	NULL,
+};
+
+static void gadget_config_name_attr_release(struct config_item *item)
+{
+	struct gadget_config_name *cn = to_gadget_config_name(item);
+
+	kfree(cn->configuration);
+
+	list_del(&cn->list);
+	kfree(cn);
+}
+
+USB_CONFIG_STRING_RW_OPS(gadget_config_name);
+USB_CONFIG_STRINGS_LANG(gadget_config_name, config_usb_cfg);
+
+static struct config_group *config_desc_make(
+		struct config_group *group,
+		const char *name)
+{
+	struct gadget_info *gi;
+	struct config_usb_cfg *cfg;
+	char buf[MAX_NAME_LEN];
+	char *num_str;
+	u8 num;
+	int ret;
+
+	gi = container_of(group, struct gadget_info, configs_group);
+	ret = snprintf(buf, MAX_NAME_LEN, "%s", name);
+	if (ret >= MAX_NAME_LEN)
+		return ERR_PTR(-ENAMETOOLONG);
+
+	num_str = strchr(buf, '.');
+	if (!num_str) {
+		pr_err("Unable to locate . in name.bConfigurationValue\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	*num_str = '\0';
+	num_str++;
+
+	if (!strlen(buf))
+		return ERR_PTR(-EINVAL);
+
+	ret = kstrtou8(num_str, 0, &num);
+	if (ret)
+		return ERR_PTR(ret);
+
+	cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
+	if (!cfg)
+		return ERR_PTR(-ENOMEM);
+	cfg->c.label = kstrdup(buf, GFP_KERNEL);
+	if (!cfg->c.label) {
+		ret = -ENOMEM;
+		goto err;
+	}
+	cfg->c.bConfigurationValue = num;
+	cfg->c.MaxPower = CONFIG_USB_GADGET_VBUS_DRAW;
+	cfg->c.bmAttributes = USB_CONFIG_ATT_ONE;
+	INIT_LIST_HEAD(&cfg->string_list);
+	INIT_LIST_HEAD(&cfg->func_list);
+
+	cfg->group.default_groups = cfg->default_groups;
+	cfg->default_groups[0] = &cfg->strings_group;
+
+	config_group_init_type_name(&cfg->group, name,
+				&gadget_config_type);
+	config_group_init_type_name(&cfg->strings_group, "strings",
+			&gadget_config_name_strings_type);
+
+	ret = usb_add_config_only(&gi->cdev, &cfg->c);
+	if (ret)
+		goto err;
+
+	return &cfg->group;
+err:
+	kfree(cfg->c.label);
+	kfree(cfg);
+	return ERR_PTR(ret);
+}
+
+static void config_desc_drop(
+		struct config_group *group,
+		struct config_item *item)
+{
+	config_item_put(item);
+}
+
+static struct configfs_group_operations config_desc_ops = {
+	.make_group     = &config_desc_make,
+	.drop_item      = &config_desc_drop,
+};
+
+static struct config_item_type config_desc_type = {
+	.ct_group_ops   = &config_desc_ops,
+	.ct_owner       = THIS_MODULE,
+};
+
+CONFIGFS_ATTR_STRUCT(gadget_strings);
+GS_STRINGS_RW(gadget_strings, manufacturer);
+GS_STRINGS_RW(gadget_strings, product);
+GS_STRINGS_RW(gadget_strings, serialnumber);
+
+static struct configfs_attribute *gadget_strings_langid_attrs[] = {
+	&gadget_strings_manufacturer.attr,
+	&gadget_strings_product.attr,
+	&gadget_strings_serialnumber.attr,
+	NULL,
+};
+
+static void gadget_strings_attr_release(struct config_item *item)
+{
+	struct gadget_strings *gs = to_gadget_strings(item);
+
+	kfree(gs->manufacturer);
+	kfree(gs->product);
+	kfree(gs->serialnumber);
+
+	list_del(&gs->list);
+	kfree(gs);
+}
+
+USB_CONFIG_STRING_RW_OPS(gadget_strings);
+USB_CONFIG_STRINGS_LANG(gadget_strings, gadget_info);
+
+static int configfs_do_nothing(struct usb_composite_dev *cdev)
+{
+	__WARN();
+	return -EINVAL;
+}
+
+int composite_dev_prepare(struct usb_composite_driver *composite,
+		struct usb_composite_dev *dev);
+
+static void purge_configs_funcs(struct gadget_info *gi)
+{
+	struct usb_configuration	*c;
+
+	list_for_each_entry(c, &gi->cdev.configs, list) {
+		struct usb_function *f, *tmp;
+		struct config_usb_cfg *cfg;
+
+		cfg = container_of(c, struct config_usb_cfg, c);
+
+		list_for_each_entry_safe(f, tmp, &c->functions, list) {
+
+			list_move_tail(&f->list, &cfg->func_list);
+			if (f->unbind) {
+				dev_err(&gi->cdev.gadget->dev, "unbind function"
+						" '%s'/%p\n", f->name, f);
+				f->unbind(c, f);
+			}
+		}
+		c->next_interface_id = 0;
+		c->superspeed = 0;
+		c->highspeed = 0;
+		c->fullspeed = 0;
+	}
+}
+
+static int configfs_composite_bind(struct usb_gadget *gadget,
+		struct usb_gadget_driver *gdriver)
+{
+	struct usb_composite_driver     *composite = to_cdriver(gdriver);
+	struct gadget_info		*gi = container_of(composite,
+						struct gadget_info, composite);
+	struct usb_composite_dev	*cdev = &gi->cdev;
+	struct usb_configuration	*c;
+	struct usb_string		*s;
+	unsigned			i;
+	int				ret;
+
+	/* the gi->lock is hold by the caller */
+	cdev->gadget = gadget;
+	set_gadget_data(gadget, cdev);
+	ret = composite_dev_prepare(composite, cdev);
+	if (ret)
+		return ret;
+	/* and now the gadget bind */
+	ret = -EINVAL;
+
+	if (list_empty(&gi->cdev.configs)) {
+		pr_err("Need atleast one configuration in %s.\n",
+				gi->composite.name);
+		goto err_comp_cleanup;
+	}
+
+
+	list_for_each_entry(c, &gi->cdev.configs, list) {
+		struct config_usb_cfg *cfg;
+
+		cfg = container_of(c, struct config_usb_cfg, c);
+		if (list_empty(&cfg->func_list)) {
+			pr_err("Config %s/%d of %s needs atleast one function.\n",
+			      c->label, c->bConfigurationValue,
+			      gi->composite.name);
+			goto err_comp_cleanup;
+		}
+	}
+
+	/* init all strings */
+	if (!list_empty(&gi->string_list)) {
+		struct gadget_strings *gs;
+
+		i = 0;
+		list_for_each_entry(gs, &gi->string_list, list) {
+
+			gi->gstrings[i] = &gs->stringtab_dev;
+			gs->stringtab_dev.strings = gs->strings;
+			gs->strings[USB_GADGET_MANUFACTURER_IDX].s =
+				gs->manufacturer;
+			gs->strings[USB_GADGET_PRODUCT_IDX].s = gs->product;
+			gs->strings[USB_GADGET_SERIAL_IDX].s = gs->serialnumber;
+			i++;
+		}
+		gi->gstrings[i] = NULL;
+		s = usb_gstrings_attach(&gi->cdev, gi->gstrings,
+				USB_GADGET_FIRST_AVAIL_IDX);
+		if (IS_ERR(s))
+			goto err_comp_cleanup;
+
+		gi->cdev.desc.iManufacturer = s[USB_GADGET_MANUFACTURER_IDX].id;
+		gi->cdev.desc.iProduct = s[USB_GADGET_PRODUCT_IDX].id;
+		gi->cdev.desc.iSerialNumber = s[USB_GADGET_SERIAL_IDX].id;
+	}
+
+	/* Go through all configs, attach all functions */
+	list_for_each_entry(c, &gi->cdev.configs, list) {
+		struct config_usb_cfg *cfg;
+		struct usb_function *f;
+		struct usb_function *tmp;
+		struct gadget_config_name *cn;
+
+		cfg = container_of(c, struct config_usb_cfg, c);
+		if (!list_empty(&cfg->string_list)) {
+			i = 0;
+			list_for_each_entry(cn, &cfg->string_list, list) {
+				cfg->gstrings[i] = &cn->stringtab_dev;
+				cn->stringtab_dev.strings = &cn->strings;
+				cn->strings.s = cn->configuration;
+				i++;
+			}
+			cfg->gstrings[i] = NULL;
+			s = usb_gstrings_attach(&gi->cdev, cfg->gstrings, 1);
+			if (IS_ERR(s))
+				goto err_comp_cleanup;
+			c->iConfiguration = s[0].id;
+		}
+
+		list_for_each_entry_safe(f, tmp, &cfg->func_list, list) {
+			list_del(&f->list);
+			ret = usb_add_function(c, f);
+			if (ret)
+				goto err_purge_funcs;
+		}
+		usb_ep_autoconfig_reset(cdev->gadget);
+	}
+	usb_ep_autoconfig_reset(cdev->gadget);
+	return 0;
+
+err_purge_funcs:
+	purge_configs_funcs(gi);
+err_comp_cleanup:
+	composite_dev_cleanup(cdev);
+	return ret;
+}
+
+static void configfs_composite_unbind(struct usb_gadget *gadget)
+{
+	struct usb_composite_dev	*cdev;
+	struct gadget_info		*gi;
+
+	/* the gi->lock is hold by the caller */
+
+	cdev = get_gadget_data(gadget);
+	gi = container_of(cdev, struct gadget_info, cdev);
+
+	purge_configs_funcs(gi);
+	composite_dev_cleanup(cdev);
+	usb_ep_autoconfig_reset(cdev->gadget);
+	cdev->gadget = NULL;
+	set_gadget_data(gadget, NULL);
+}
+
+static const struct usb_gadget_driver configfs_driver_template = {
+	.bind           = configfs_composite_bind,
+	.unbind         = configfs_composite_unbind,
+
+	.setup          = composite_setup,
+	.disconnect     = composite_disconnect,
+
+	.max_speed	= USB_SPEED_SUPER,
+	.driver = {
+		.owner          = THIS_MODULE,
+		.name		= "configfs-gadget",
+	},
+};
+
+static struct config_group *gadgets_make(
+		struct config_group *group,
+		const char *name)
+{
+	struct gadget_info *gi;
+
+	gi = kzalloc(sizeof(*gi), GFP_KERNEL);
+	if (!gi)
+		return ERR_PTR(-ENOMEM);
+
+	gi->group.default_groups = gi->default_groups;
+	gi->group.default_groups[0] = &gi->functions_group;
+	gi->group.default_groups[1] = &gi->configs_group;
+	gi->group.default_groups[2] = &gi->strings_group;
+
+	config_group_init_type_name(&gi->functions_group, "functions",
+			&functions_type);
+	config_group_init_type_name(&gi->configs_group, "configs",
+			&config_desc_type);
+	config_group_init_type_name(&gi->strings_group, "strings",
+			&gadget_strings_strings_type);
+
+	gi->composite.bind = configfs_do_nothing;
+	gi->composite.unbind = configfs_do_nothing;
+	gi->composite.suspend = NULL;
+	gi->composite.resume = NULL;
+	gi->composite.max_speed = USB_SPEED_SUPER;
+
+	mutex_init(&gi->lock);
+	INIT_LIST_HEAD(&gi->string_list);
+	INIT_LIST_HEAD(&gi->available_func);
+
+	composite_init_dev(&gi->cdev);
+	gi->cdev.desc.bLength = USB_DT_DEVICE_SIZE;
+	gi->cdev.desc.bDescriptorType = USB_DT_DEVICE;
+	gi->cdev.desc.bcdDevice = cpu_to_le16(get_default_bcdDevice());
+
+	gi->composite.gadget_driver = configfs_driver_template;
+
+	gi->composite.gadget_driver.function = kstrdup(name, GFP_KERNEL);
+	gi->composite.name = gi->composite.gadget_driver.function;
+
+	if (!gi->composite.gadget_driver.function)
+		goto err;
+
+#ifdef CONFIG_USB_OTG
+	gi->otg.bLength = sizeof(struct usb_otg_descriptor);
+	gi->otg.bDescriptorType = USB_DT_OTG;
+	gi->otg.bmAttributes = USB_OTG_SRP | USB_OTG_HNP;
+#endif
+
+	config_group_init_type_name(&gi->group, name,
+				&gadget_root_type);
+	return &gi->group;
+err:
+	kfree(gi);
+	return ERR_PTR(-ENOMEM);
+}
+
+static void gadgets_drop(struct config_group *group, struct config_item *item)
+{
+	config_item_put(item);
+}
+
+static struct configfs_group_operations gadgets_ops = {
+	.make_group     = &gadgets_make,
+	.drop_item      = &gadgets_drop,
+};
+
+static struct config_item_type gadgets_type = {
+	.ct_group_ops   = &gadgets_ops,
+	.ct_owner       = THIS_MODULE,
+};
+
+static struct configfs_subsystem gadget_subsys = {
+	.su_group = {
+		.cg_item = {
+			.ci_namebuf = "usb_gadget",
+			.ci_type = &gadgets_type,
+		},
+	},
+	.su_mutex = __MUTEX_INITIALIZER(gadget_subsys.su_mutex),
+};
+
+static int __init gadget_cfs_init(void)
+{
+	int ret;
+
+	config_group_init(&gadget_subsys.su_group);
+
+	ret = configfs_register_subsystem(&gadget_subsys);
+	return ret;
+}
+module_init(gadget_cfs_init);
+
+static void __exit gadget_cfs_exit(void)
+{
+	configfs_unregister_subsystem(&gadget_subsys);
+}
+module_exit(gadget_cfs_exit);
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index 8cf0c0f..a792e32 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -912,7 +912,6 @@ static int dummy_udc_start(struct usb_gadget *g,
 	dum->devstatus = 0;
 
 	dum->driver = driver;
-	dum->gadget.dev.driver = &driver->driver;
 	dev_dbg(udc_dev(dum), "binding gadget driver '%s'\n",
 			driver->driver.name);
 	return 0;
@@ -927,7 +926,6 @@ static int dummy_udc_stop(struct usb_gadget *g,
 	dev_dbg(udc_dev(dum), "unregister gadget driver '%s'\n",
 			driver->driver.name);
 
-	dum->gadget.dev.driver = NULL;
 	dum->driver = NULL;
 
 	return 0;
@@ -937,11 +935,6 @@ static int dummy_udc_stop(struct usb_gadget *g,
 
 /* The gadget structure is stored inside the hcd structure and will be
  * released along with it. */
-static void dummy_gadget_release(struct device *dev)
-{
-	return;
-}
-
 static void init_dummy_udc_hw(struct dummy *dum)
 {
 	int i;
@@ -984,15 +977,7 @@ static int dummy_udc_probe(struct platform_device *pdev)
 	dum->gadget.ops = &dummy_ops;
 	dum->gadget.max_speed = USB_SPEED_SUPER;
 
-	dev_set_name(&dum->gadget.dev, "gadget");
 	dum->gadget.dev.parent = &pdev->dev;
-	dum->gadget.dev.release = dummy_gadget_release;
-	rc = device_register(&dum->gadget.dev);
-	if (rc < 0) {
-		put_device(&dum->gadget.dev);
-		return rc;
-	}
-
 	init_dummy_udc_hw(dum);
 
 	rc = usb_add_gadget_udc(&pdev->dev, &dum->gadget);
@@ -1008,7 +993,6 @@ static int dummy_udc_probe(struct platform_device *pdev)
 err_dev:
 	usb_del_gadget_udc(&dum->gadget);
 err_udc:
-	device_unregister(&dum->gadget.dev);
 	return rc;
 }
 
@@ -1019,7 +1003,6 @@ static int dummy_udc_remove(struct platform_device *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;
 }
 
@@ -1923,7 +1906,7 @@ done:
 }
 
 /* usb 3.0 root hub device descriptor */
-struct {
+static struct {
 	struct usb_bos_descriptor bos;
 	struct usb_ss_cap_descriptor ss_cap;
 } __packed usb3_bos_desc = {
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index 18c3f42..56c8eca 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -207,7 +207,7 @@ static struct usb_gadget_strings *dev_strings[] = {
 };
 
 static u8 hostaddr[ETH_ALEN];
-
+static struct eth_dev *the_dev;
 /*-------------------------------------------------------------------------*/
 
 /*
@@ -224,7 +224,7 @@ static int __init rndis_do_config(struct usb_configuration *c)
 		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 	}
 
-	return rndis_bind_config(c, hostaddr);
+	return rndis_bind_config(c, hostaddr, the_dev);
 }
 
 static struct usb_configuration rndis_config_driver = {
@@ -257,11 +257,11 @@ static int __init eth_do_config(struct usb_configuration *c)
 	}
 
 	if (use_eem)
-		return eem_bind_config(c);
+		return eem_bind_config(c, the_dev);
 	else if (can_support_ecm(c->cdev->gadget))
-		return ecm_bind_config(c, hostaddr);
+		return ecm_bind_config(c, hostaddr, the_dev);
 	else
-		return geth_bind_config(c, hostaddr);
+		return geth_bind_config(c, hostaddr, the_dev);
 }
 
 static struct usb_configuration eth_config_driver = {
@@ -279,9 +279,9 @@ static int __init eth_bind(struct usb_composite_dev *cdev)
 	int			status;
 
 	/* set up network link layer */
-	status = gether_setup(cdev->gadget, hostaddr);
-	if (status < 0)
-		return status;
+	the_dev = gether_setup(cdev->gadget, hostaddr);
+	if (IS_ERR(the_dev))
+		return PTR_ERR(the_dev);
 
 	/* set up main config label and device descriptor */
 	if (use_eem) {
@@ -338,13 +338,13 @@ static int __init eth_bind(struct usb_composite_dev *cdev)
 	return 0;
 
 fail:
-	gether_cleanup();
+	gether_cleanup(the_dev);
 	return status;
 }
 
 static int __exit eth_unbind(struct usb_composite_dev *cdev)
 {
-	gether_cleanup();
+	gether_cleanup(the_dev);
 	return 0;
 }
 
diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c
index 1ae180b..4b7e33e 100644
--- a/drivers/usb/gadget/f_acm.c
+++ b/drivers/usb/gadget/f_acm.c
@@ -715,13 +715,31 @@ fail:
 	return status;
 }
 
-static struct f_acm *acm_alloc_basic_func(void)
+static void acm_unbind(struct usb_configuration *c, struct usb_function *f)
+{
+	struct f_acm		*acm = func_to_acm(f);
+
+	acm_string_defs[0].id = 0;
+	usb_free_all_descriptors(f);
+	if (acm->notify_req)
+		gs_free_req(acm->notify, acm->notify_req);
+}
+
+static void acm_free_func(struct usb_function *f)
+{
+	struct f_acm		*acm = func_to_acm(f);
+
+	kfree(acm);
+}
+
+static struct usb_function *acm_alloc_func(struct usb_function_instance *fi)
 {
-	struct f_acm	*acm;
+	struct f_serial_opts *opts;
+	struct f_acm *acm;
 
 	acm = kzalloc(sizeof(*acm), GFP_KERNEL);
 	if (!acm)
-		return NULL;
+		return ERR_PTR(-ENOMEM);
 
 	spin_lock_init(&acm->lock);
 
@@ -730,109 +748,100 @@ static struct f_acm *acm_alloc_basic_func(void)
 	acm->port.send_break = acm_send_break;
 
 	acm->port.func.name = "acm";
+	acm->port.func.strings = acm_strings;
 	/* descriptors are per-instance copies */
 	acm->port.func.bind = acm_bind;
 	acm->port.func.set_alt = acm_set_alt;
 	acm->port.func.setup = acm_setup;
 	acm->port.func.disable = acm_disable;
 
-	return acm;
+	opts = container_of(fi, struct f_serial_opts, func_inst);
+	acm->port_num = opts->port_num;
+	acm->port.func.unbind = acm_unbind;
+	acm->port.func.free_func = acm_free_func;
+
+	return &acm->port.func;
 }
 
-#ifdef USB_FACM_INCLUDED
-static void
-acm_old_unbind(struct usb_configuration *c, struct usb_function *f)
+static inline struct f_serial_opts *to_f_serial_opts(struct config_item *item)
 {
-	struct f_acm		*acm = func_to_acm(f);
-
-	usb_free_all_descriptors(f);
-	if (acm->notify_req)
-		gs_free_req(acm->notify, acm->notify_req);
-	kfree(acm);
+	return container_of(to_config_group(item), struct f_serial_opts,
+			func_inst.group);
 }
 
-/**
- * acm_bind_config - add a CDC ACM function to a configuration
- * @c: the configuration to support the CDC ACM instance
- * @port_num: /dev/ttyGS* port this interface will use
- * Context: single threaded during gadget setup
- *
- * Returns zero on success, else negative errno.
- *
- */
-int acm_bind_config(struct usb_configuration *c, u8 port_num)
+CONFIGFS_ATTR_STRUCT(f_serial_opts);
+static ssize_t f_acm_attr_show(struct config_item *item,
+				 struct configfs_attribute *attr,
+				 char *page)
 {
-	struct f_acm	*acm;
-	int		status;
-
-	/* allocate and initialize one new instance */
-	acm = acm_alloc_basic_func();
-	if (!acm)
-		return -ENOMEM;
-
-	acm->port_num = port_num;
-	acm->port.func.unbind = acm_old_unbind;
-
-	status = usb_add_function(c, &acm->port.func);
-	if (status)
-		kfree(acm);
-	return status;
+	struct f_serial_opts *opts = to_f_serial_opts(item);
+	struct f_serial_opts_attribute *f_serial_opts_attr =
+		container_of(attr, struct f_serial_opts_attribute, attr);
+	ssize_t ret = 0;
+
+	if (f_serial_opts_attr->show)
+		ret = f_serial_opts_attr->show(opts, page);
+	return ret;
 }
 
-#else
-
-static void acm_unbind(struct usb_configuration *c, struct usb_function *f)
+static void acm_attr_release(struct config_item *item)
 {
-	struct f_acm		*acm = func_to_acm(f);
+	struct f_serial_opts *opts = to_f_serial_opts(item);
 
-	acm_string_defs[0].id = 0;
-	usb_free_all_descriptors(f);
-	if (acm->notify_req)
-		gs_free_req(acm->notify, acm->notify_req);
+	usb_put_function_instance(&opts->func_inst);
 }
 
-static void acm_free_func(struct usb_function *f)
-{
-	struct f_acm		*acm = func_to_acm(f);
+static struct configfs_item_operations acm_item_ops = {
+	.release                = acm_attr_release,
+	.show_attribute		= f_acm_attr_show,
+};
 
-	kfree(acm);
+static ssize_t f_acm_port_num_show(struct f_serial_opts *opts, char *page)
+{
+	return sprintf(page, "%u\n", opts->port_num);
 }
 
-static struct usb_function *acm_alloc_func(struct usb_function_instance *fi)
-{
-	struct f_serial_opts *opts;
-	struct f_acm *acm;
+static struct f_serial_opts_attribute f_acm_port_num =
+	__CONFIGFS_ATTR_RO(port_num, f_acm_port_num_show);
 
-	acm = acm_alloc_basic_func();
-	if (!acm)
-		return ERR_PTR(-ENOMEM);
 
-	opts = container_of(fi, struct f_serial_opts, func_inst);
-	acm->port_num = opts->port_num;
-	acm->port.func.unbind = acm_unbind;
-	acm->port.func.free_func = acm_free_func;
+static struct configfs_attribute *acm_attrs[] = {
+	&f_acm_port_num.attr,
+	NULL,
+};
 
-	return &acm->port.func;
-}
+static struct config_item_type acm_func_type = {
+	.ct_item_ops    = &acm_item_ops,
+	.ct_attrs	= acm_attrs,
+	.ct_owner       = THIS_MODULE,
+};
 
 static void acm_free_instance(struct usb_function_instance *fi)
 {
 	struct f_serial_opts *opts;
 
 	opts = container_of(fi, struct f_serial_opts, func_inst);
+	gserial_free_line(opts->port_num);
 	kfree(opts);
 }
 
 static struct usb_function_instance *acm_alloc_instance(void)
 {
 	struct f_serial_opts *opts;
+	int ret;
 
 	opts = kzalloc(sizeof(*opts), GFP_KERNEL);
 	if (!opts)
 		return ERR_PTR(-ENOMEM);
 	opts->func_inst.free_func_inst = acm_free_instance;
+	ret = gserial_alloc_line(&opts->port_num);
+	if (ret) {
+		kfree(opts);
+		return ERR_PTR(ret);
+	}
+	config_group_init_type_name(&opts->func_inst.group, "",
+			&acm_func_type);
 	return &opts->func_inst;
 }
 DECLARE_USB_FUNCTION_INIT(acm, acm_alloc_instance, acm_alloc_func);
 MODULE_LICENSE("GPL");
-#endif
diff --git a/drivers/usb/gadget/f_ecm.c b/drivers/usb/gadget/f_ecm.c
index 83420a3..d893d69 100644
--- a/drivers/usb/gadget/f_ecm.c
+++ b/drivers/usb/gadget/f_ecm.c
@@ -824,7 +824,8 @@ ecm_unbind(struct usb_configuration *c, struct usb_function *f)
  * for calling @gether_cleanup() before module unload.
  */
 int
-ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
+ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
+		struct eth_dev *dev)
 {
 	struct f_ecm	*ecm;
 	int		status;
@@ -852,6 +853,7 @@ ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
 	snprintf(ecm->ethaddr, sizeof ecm->ethaddr, "%pm", ethaddr);
 	ecm_string_defs[1].s = ecm->ethaddr;
 
+	ecm->port.ioport = dev;
 	ecm->port.cdc_filter = DEFAULT_FILTER;
 
 	ecm->port.func.name = "cdc_ethernet";
diff --git a/drivers/usb/gadget/f_eem.c b/drivers/usb/gadget/f_eem.c
index cf0ebee..f4e0bbe 100644
--- a/drivers/usb/gadget/f_eem.c
+++ b/drivers/usb/gadget/f_eem.c
@@ -528,7 +528,7 @@ error:
  * Caller must have called @gether_setup().  Caller is also responsible
  * for calling @gether_cleanup() before module unload.
  */
-int __init eem_bind_config(struct usb_configuration *c)
+int __init eem_bind_config(struct usb_configuration *c, struct eth_dev *dev)
 {
 	struct f_eem	*eem;
 	int		status;
@@ -549,6 +549,7 @@ int __init eem_bind_config(struct usb_configuration *c)
 	if (!eem)
 		return -ENOMEM;
 
+	eem->port.ioport = dev;
 	eem->port.cdc_filter = DEFAULT_FILTER;
 
 	eem->port.func.name = "cdc_eem";
diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c
index c377ff8..f394f29 100644
--- a/drivers/usb/gadget/f_fs.c
+++ b/drivers/usb/gadget/f_fs.c
@@ -727,7 +727,6 @@ static long ffs_ep0_ioctl(struct file *file, unsigned code, unsigned long value)
 }
 
 static const struct file_operations ffs_ep0_operations = {
-	.owner =	THIS_MODULE,
 	.llseek =	no_llseek,
 
 	.open =		ffs_ep0_open,
@@ -947,7 +946,6 @@ static long ffs_epfile_ioctl(struct file *file, unsigned code,
 }
 
 static const struct file_operations ffs_epfile_operations = {
-	.owner =	THIS_MODULE,
 	.llseek =	no_llseek,
 
 	.open =		ffs_epfile_open,
diff --git a/drivers/usb/gadget/f_ncm.c b/drivers/usb/gadget/f_ncm.c
index 5e7557e..ee19bc8 100644
--- a/drivers/usb/gadget/f_ncm.c
+++ b/drivers/usb/gadget/f_ncm.c
@@ -1287,7 +1287,8 @@ ncm_unbind(struct usb_configuration *c, struct usb_function *f)
  * Caller must have called @gether_setup().  Caller is also responsible
  * for calling @gether_cleanup() before module unload.
  */
-int __init ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
+int __init ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
+		struct eth_dev *dev)
 {
 	struct f_ncm	*ncm;
 	int		status;
@@ -1321,6 +1322,7 @@ int __init ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
 
 	spin_lock_init(&ncm->lock);
 	ncm_reset_values(ncm);
+	ncm->port.ioport = dev;
 	ncm->port.is_fixed = true;
 
 	ncm->port.func.name = "cdc_network";
diff --git a/drivers/usb/gadget/f_obex.c b/drivers/usb/gadget/f_obex.c
index 36a0045..29a348a 100644
--- a/drivers/usb/gadget/f_obex.c
+++ b/drivers/usb/gadget/f_obex.c
@@ -72,7 +72,7 @@ static struct usb_gadget_strings *obex_strings[] = {
 
 /*-------------------------------------------------------------------------*/
 
-static struct usb_interface_descriptor obex_control_intf __initdata = {
+static struct usb_interface_descriptor obex_control_intf = {
 	.bLength		= sizeof(obex_control_intf),
 	.bDescriptorType	= USB_DT_INTERFACE,
 	.bInterfaceNumber	= 0,
@@ -83,7 +83,7 @@ static struct usb_interface_descriptor obex_control_intf __initdata = {
 	.bInterfaceSubClass	= USB_CDC_SUBCLASS_OBEX,
 };
 
-static struct usb_interface_descriptor obex_data_nop_intf __initdata = {
+static struct usb_interface_descriptor obex_data_nop_intf = {
 	.bLength		= sizeof(obex_data_nop_intf),
 	.bDescriptorType	= USB_DT_INTERFACE,
 	.bInterfaceNumber	= 1,
@@ -93,7 +93,7 @@ static struct usb_interface_descriptor obex_data_nop_intf __initdata = {
 	.bInterfaceClass	= USB_CLASS_CDC_DATA,
 };
 
-static struct usb_interface_descriptor obex_data_intf __initdata = {
+static struct usb_interface_descriptor obex_data_intf = {
 	.bLength		= sizeof(obex_data_intf),
 	.bDescriptorType	= USB_DT_INTERFACE,
 	.bInterfaceNumber	= 2,
@@ -103,14 +103,14 @@ static struct usb_interface_descriptor obex_data_intf __initdata = {
 	.bInterfaceClass	= USB_CLASS_CDC_DATA,
 };
 
-static struct usb_cdc_header_desc obex_cdc_header_desc __initdata = {
+static struct usb_cdc_header_desc obex_cdc_header_desc = {
 	.bLength		= sizeof(obex_cdc_header_desc),
 	.bDescriptorType	= USB_DT_CS_INTERFACE,
 	.bDescriptorSubType	= USB_CDC_HEADER_TYPE,
 	.bcdCDC			= cpu_to_le16(0x0120),
 };
 
-static struct usb_cdc_union_desc obex_cdc_union_desc __initdata = {
+static struct usb_cdc_union_desc obex_cdc_union_desc = {
 	.bLength		= sizeof(obex_cdc_union_desc),
 	.bDescriptorType	= USB_DT_CS_INTERFACE,
 	.bDescriptorSubType	= USB_CDC_UNION_TYPE,
@@ -118,7 +118,7 @@ static struct usb_cdc_union_desc obex_cdc_union_desc __initdata = {
 	.bSlaveInterface0	= 2,
 };
 
-static struct usb_cdc_obex_desc obex_desc __initdata = {
+static struct usb_cdc_obex_desc obex_desc = {
 	.bLength		= sizeof(obex_desc),
 	.bDescriptorType	= USB_DT_CS_INTERFACE,
 	.bDescriptorSubType	= USB_CDC_OBEX_TYPE,
@@ -127,7 +127,7 @@ static struct usb_cdc_obex_desc obex_desc __initdata = {
 
 /* High-Speed Support */
 
-static struct usb_endpoint_descriptor obex_hs_ep_out_desc __initdata = {
+static struct usb_endpoint_descriptor obex_hs_ep_out_desc = {
 	.bLength		= USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType	= USB_DT_ENDPOINT,
 
@@ -136,7 +136,7 @@ static struct usb_endpoint_descriptor obex_hs_ep_out_desc __initdata = {
 	.wMaxPacketSize		= cpu_to_le16(512),
 };
 
-static struct usb_endpoint_descriptor obex_hs_ep_in_desc __initdata = {
+static struct usb_endpoint_descriptor obex_hs_ep_in_desc = {
 	.bLength		= USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType	= USB_DT_ENDPOINT,
 
@@ -145,7 +145,7 @@ static struct usb_endpoint_descriptor obex_hs_ep_in_desc __initdata = {
 	.wMaxPacketSize		= cpu_to_le16(512),
 };
 
-static struct usb_descriptor_header *hs_function[] __initdata = {
+static struct usb_descriptor_header *hs_function[] = {
 	(struct usb_descriptor_header *) &obex_control_intf,
 	(struct usb_descriptor_header *) &obex_cdc_header_desc,
 	(struct usb_descriptor_header *) &obex_desc,
@@ -160,7 +160,7 @@ static struct usb_descriptor_header *hs_function[] __initdata = {
 
 /* Full-Speed Support */
 
-static struct usb_endpoint_descriptor obex_fs_ep_in_desc __initdata = {
+static struct usb_endpoint_descriptor obex_fs_ep_in_desc = {
 	.bLength		= USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType	= USB_DT_ENDPOINT,
 
@@ -168,7 +168,7 @@ static struct usb_endpoint_descriptor obex_fs_ep_in_desc __initdata = {
 	.bmAttributes		= USB_ENDPOINT_XFER_BULK,
 };
 
-static struct usb_endpoint_descriptor obex_fs_ep_out_desc __initdata = {
+static struct usb_endpoint_descriptor obex_fs_ep_out_desc = {
 	.bLength		= USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType	= USB_DT_ENDPOINT,
 
@@ -176,7 +176,7 @@ static struct usb_endpoint_descriptor obex_fs_ep_out_desc __initdata = {
 	.bmAttributes		= USB_ENDPOINT_XFER_BULK,
 };
 
-static struct usb_descriptor_header *fs_function[] __initdata = {
+static struct usb_descriptor_header *fs_function[] = {
 	(struct usb_descriptor_header *) &obex_control_intf,
 	(struct usb_descriptor_header *) &obex_cdc_header_desc,
 	(struct usb_descriptor_header *) &obex_desc,
@@ -290,14 +290,43 @@ static void obex_disconnect(struct gserial *g)
 
 /*-------------------------------------------------------------------------*/
 
-static int __init
-obex_bind(struct usb_configuration *c, struct usb_function *f)
+/* Some controllers can't support CDC OBEX ... */
+static inline bool can_support_obex(struct usb_configuration *c)
+{
+	/* Since the first interface is a NOP, we can ignore the
+	 * issue of multi-interface support on most controllers.
+	 *
+	 * Altsettings are mandatory, however...
+	 */
+	if (!gadget_supports_altsettings(c->cdev->gadget))
+		return false;
+
+	/* everything else is *probably* fine ... */
+	return true;
+}
+
+static int obex_bind(struct usb_configuration *c, struct usb_function *f)
 {
 	struct usb_composite_dev *cdev = c->cdev;
 	struct f_obex		*obex = func_to_obex(f);
 	int			status;
 	struct usb_ep		*ep;
 
+	if (!can_support_obex(c))
+		return -EINVAL;
+
+	if (obex_string_defs[OBEX_CTRL_IDX].id == 0) {
+		status = usb_string_ids_tab(c->cdev, obex_string_defs);
+		if (status < 0)
+			return status;
+		obex_control_intf.iInterface =
+			obex_string_defs[OBEX_CTRL_IDX].id;
+
+		status = obex_string_defs[OBEX_DATA_IDX].id;
+		obex_data_nop_intf.iInterface = status;
+		obex_data_intf.iInterface = status;
+	}
+
 	/* allocate instance-specific interface IDs, and patch descriptors */
 
 	status = usb_interface_id(c, f);
@@ -376,29 +405,16 @@ fail:
 	return status;
 }
 
+#ifdef USBF_OBEX_INCLUDED
+
 static void
-obex_unbind(struct usb_configuration *c, struct usb_function *f)
+obex_old_unbind(struct usb_configuration *c, struct usb_function *f)
 {
 	obex_string_defs[OBEX_CTRL_IDX].id = 0;
 	usb_free_all_descriptors(f);
 	kfree(func_to_obex(f));
 }
 
-/* Some controllers can't support CDC OBEX ... */
-static inline bool can_support_obex(struct usb_configuration *c)
-{
-	/* Since the first interface is a NOP, we can ignore the
-	 * issue of multi-interface support on most controllers.
-	 *
-	 * Altsettings are mandatory, however...
-	 */
-	if (!gadget_supports_altsettings(c->cdev->gadget))
-		return false;
-
-	/* everything else is *probably* fine ... */
-	return true;
-}
-
 /**
  * obex_bind_config - add a CDC OBEX function to a configuration
  * @c: the configuration to support the CDC OBEX instance
@@ -412,21 +428,6 @@ int __init obex_bind_config(struct usb_configuration *c, u8 port_num)
 	struct f_obex	*obex;
 	int		status;
 
-	if (!can_support_obex(c))
-		return -EINVAL;
-
-	if (obex_string_defs[OBEX_CTRL_IDX].id == 0) {
-		status = usb_string_ids_tab(c->cdev, obex_string_defs);
-		if (status < 0)
-			return status;
-		obex_control_intf.iInterface =
-			obex_string_defs[OBEX_CTRL_IDX].id;
-
-		status = obex_string_defs[OBEX_DATA_IDX].id;
-		obex_data_nop_intf.iInterface = status;
-		obex_data_intf.iInterface = status;
-	}
-
 	/* allocate and initialize one new instance */
 	obex = kzalloc(sizeof *obex, GFP_KERNEL);
 	if (!obex)
@@ -441,7 +442,7 @@ int __init obex_bind_config(struct usb_configuration *c, u8 port_num)
 	obex->port.func.strings = obex_strings;
 	/* descriptors are per-instance copies */
 	obex->port.func.bind = obex_bind;
-	obex->port.func.unbind = obex_unbind;
+	obex->port.func.unbind = obex_old_unbind;
 	obex->port.func.set_alt = obex_set_alt;
 	obex->port.func.get_alt = obex_get_alt;
 	obex->port.func.disable = obex_disable;
@@ -453,5 +454,138 @@ int __init obex_bind_config(struct usb_configuration *c, u8 port_num)
 	return status;
 }
 
+#else
+
+static inline struct f_serial_opts *to_f_serial_opts(struct config_item *item)
+{
+	return container_of(to_config_group(item), struct f_serial_opts,
+			    func_inst.group);
+}
+
+CONFIGFS_ATTR_STRUCT(f_serial_opts);
+static ssize_t f_obex_attr_show(struct config_item *item,
+				struct configfs_attribute *attr,
+				char *page)
+{
+	struct f_serial_opts *opts = to_f_serial_opts(item);
+	struct f_serial_opts_attribute *f_serial_opts_attr =
+		container_of(attr, struct f_serial_opts_attribute, attr);
+	ssize_t ret = 0;
+
+	if (f_serial_opts_attr->show)
+		ret = f_serial_opts_attr->show(opts, page);
+
+	return ret;
+}
+
+static void obex_attr_release(struct config_item *item)
+{
+	struct f_serial_opts *opts = to_f_serial_opts(item);
+
+	usb_put_function_instance(&opts->func_inst);
+}
+
+static struct configfs_item_operations obex_item_ops = {
+	.release	= obex_attr_release,
+	.show_attribute = f_obex_attr_show,
+};
+
+static ssize_t f_obex_port_num_show(struct f_serial_opts *opts, char *page)
+{
+	return sprintf(page, "%u\n", opts->port_num);
+}
+
+static struct f_serial_opts_attribute f_obex_port_num =
+	__CONFIGFS_ATTR_RO(port_num, f_obex_port_num_show);
+
+static struct configfs_attribute *acm_attrs[] = {
+	&f_obex_port_num.attr,
+	NULL,
+};
+
+static struct config_item_type obex_func_type = {
+	.ct_item_ops	= &obex_item_ops,
+	.ct_attrs	= acm_attrs,
+	.ct_owner	= THIS_MODULE,
+};
+
+static void obex_free_inst(struct usb_function_instance *f)
+{
+	struct f_serial_opts *opts;
+
+	opts = container_of(f, struct f_serial_opts, func_inst);
+	gserial_free_line(opts->port_num);
+	kfree(opts);
+}
+
+static struct usb_function_instance *obex_alloc_inst(void)
+{
+	struct f_serial_opts *opts;
+	int ret;
+
+	opts = kzalloc(sizeof(*opts), GFP_KERNEL);
+	if (!opts)
+		return ERR_PTR(-ENOMEM);
+
+	opts->func_inst.free_func_inst = obex_free_inst;
+	ret = gserial_alloc_line(&opts->port_num);
+	if (ret) {
+		kfree(opts);
+		return ERR_PTR(ret);
+	}
+	config_group_init_type_name(&opts->func_inst.group, "",
+				    &obex_func_type);
+
+	return &opts->func_inst;
+}
+
+static void obex_free(struct usb_function *f)
+{
+	struct f_obex *obex;
+
+	obex = func_to_obex(f);
+	kfree(obex);
+}
+
+static void obex_unbind(struct usb_configuration *c, struct usb_function *f)
+{
+	obex_string_defs[OBEX_CTRL_IDX].id = 0;
+	usb_free_all_descriptors(f);
+}
+
+struct usb_function *obex_alloc(struct usb_function_instance *fi)
+{
+	struct f_obex	*obex;
+	struct f_serial_opts *opts;
+
+	/* allocate and initialize one new instance */
+	obex = kzalloc(sizeof(*obex), GFP_KERNEL);
+	if (!obex)
+		return ERR_PTR(-ENOMEM);
+
+	opts = container_of(fi, struct f_serial_opts, func_inst);
+
+	obex->port_num = opts->port_num;
+
+	obex->port.connect = obex_connect;
+	obex->port.disconnect = obex_disconnect;
+
+	obex->port.func.name = "obex";
+	obex->port.func.strings = obex_strings;
+	/* descriptors are per-instance copies */
+	obex->port.func.bind = obex_bind;
+	obex->port.func.unbind = obex_unbind;
+	obex->port.func.set_alt = obex_set_alt;
+	obex->port.func.get_alt = obex_get_alt;
+	obex->port.func.disable = obex_disable;
+	obex->port.func.free_func = obex_free;
+
+	return &obex->port.func;
+}
+
+DECLARE_USB_FUNCTION_INIT(obex, obex_alloc_inst, obex_alloc);
+
+#endif
+
 MODULE_AUTHOR("Felipe Balbi");
 MODULE_LICENSE("GPL");
diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c
index cc9c49c..36e8c44 100644
--- a/drivers/usb/gadget/f_rndis.c
+++ b/drivers/usb/gadget/f_rndis.c
@@ -813,7 +813,7 @@ static inline bool can_support_rndis(struct usb_configuration *c)
 
 int
 rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
-				u32 vendorID, const char *manufacturer)
+		u32 vendorID, const char *manufacturer, struct eth_dev *dev)
 {
 	struct f_rndis	*rndis;
 	int		status;
@@ -846,6 +846,7 @@ rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
 	rndis->vendorID = vendorID;
 	rndis->manufacturer = manufacturer;
 
+	rndis->port.ioport = dev;
 	/* RNDIS activates when the host changes this filter */
 	rndis->port.cdc_filter = 0;
 
diff --git a/drivers/usb/gadget/f_serial.c b/drivers/usb/gadget/f_serial.c
index da33cfb..981113c 100644
--- a/drivers/usb/gadget/f_serial.c
+++ b/drivers/usb/gadget/f_serial.c
@@ -12,6 +12,7 @@
 
 #include <linux/slab.h>
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/device.h>
 
 #include "u_serial.h"
@@ -42,7 +43,7 @@ static inline struct f_gser *func_to_gser(struct usb_function *f)
 
 /* interface descriptor: */
 
-static struct usb_interface_descriptor gser_interface_desc __initdata = {
+static struct usb_interface_descriptor gser_interface_desc = {
 	.bLength =		USB_DT_INTERFACE_SIZE,
 	.bDescriptorType =	USB_DT_INTERFACE,
 	/* .bInterfaceNumber = DYNAMIC */
@@ -55,21 +56,21 @@ static struct usb_interface_descriptor gser_interface_desc __initdata = {
 
 /* full speed support: */
 
-static struct usb_endpoint_descriptor gser_fs_in_desc __initdata = {
+static struct usb_endpoint_descriptor gser_fs_in_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 	.bEndpointAddress =	USB_DIR_IN,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 };
 
-static struct usb_endpoint_descriptor gser_fs_out_desc __initdata = {
+static struct usb_endpoint_descriptor gser_fs_out_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 	.bEndpointAddress =	USB_DIR_OUT,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 };
 
-static struct usb_descriptor_header *gser_fs_function[] __initdata = {
+static struct usb_descriptor_header *gser_fs_function[] = {
 	(struct usb_descriptor_header *) &gser_interface_desc,
 	(struct usb_descriptor_header *) &gser_fs_in_desc,
 	(struct usb_descriptor_header *) &gser_fs_out_desc,
@@ -78,47 +79,47 @@ static struct usb_descriptor_header *gser_fs_function[] __initdata = {
 
 /* high speed support: */
 
-static struct usb_endpoint_descriptor gser_hs_in_desc __initdata = {
+static struct usb_endpoint_descriptor gser_hs_in_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 	.wMaxPacketSize =	cpu_to_le16(512),
 };
 
-static struct usb_endpoint_descriptor gser_hs_out_desc __initdata = {
+static struct usb_endpoint_descriptor gser_hs_out_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 	.wMaxPacketSize =	cpu_to_le16(512),
 };
 
-static struct usb_descriptor_header *gser_hs_function[] __initdata = {
+static struct usb_descriptor_header *gser_hs_function[] = {
 	(struct usb_descriptor_header *) &gser_interface_desc,
 	(struct usb_descriptor_header *) &gser_hs_in_desc,
 	(struct usb_descriptor_header *) &gser_hs_out_desc,
 	NULL,
 };
 
-static struct usb_endpoint_descriptor gser_ss_in_desc __initdata = {
+static struct usb_endpoint_descriptor gser_ss_in_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 	.wMaxPacketSize =	cpu_to_le16(1024),
 };
 
-static struct usb_endpoint_descriptor gser_ss_out_desc __initdata = {
+static struct usb_endpoint_descriptor gser_ss_out_desc = {
 	.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 gser_ss_bulk_comp_desc __initdata = {
+static struct usb_ss_ep_comp_descriptor gser_ss_bulk_comp_desc = {
 	.bLength =              sizeof gser_ss_bulk_comp_desc,
 	.bDescriptorType =      USB_DT_SS_ENDPOINT_COMP,
 };
 
-static struct usb_descriptor_header *gser_ss_function[] __initdata = {
+static struct usb_descriptor_header *gser_ss_function[] = {
 	(struct usb_descriptor_header *) &gser_interface_desc,
 	(struct usb_descriptor_header *) &gser_ss_in_desc,
 	(struct usb_descriptor_header *) &gser_ss_bulk_comp_desc,
@@ -183,14 +184,25 @@ static void gser_disable(struct usb_function *f)
 
 /* serial function driver setup/binding */
 
-static int __init
-gser_bind(struct usb_configuration *c, struct usb_function *f)
+static int gser_bind(struct usb_configuration *c, struct usb_function *f)
 {
 	struct usb_composite_dev *cdev = c->cdev;
 	struct f_gser		*gser = func_to_gser(f);
 	int			status;
 	struct usb_ep		*ep;
 
+	/* REVISIT might want instance-specific strings to help
+	 * distinguish instances ...
+	 */
+
+	/* maybe allocate device-global string ID */
+	if (gser_string_defs[0].id == 0) {
+		status = usb_string_id(c->cdev);
+		if (status < 0)
+			return status;
+		gser_string_defs[0].id = status;
+	}
+
 	/* allocate instance-specific interface IDs */
 	status = usb_interface_id(c, f);
 	if (status < 0)
@@ -246,44 +258,115 @@ fail:
 	return status;
 }
 
-static void
-gser_unbind(struct usb_configuration *c, struct usb_function *f)
+static inline struct f_serial_opts *to_f_serial_opts(struct config_item *item)
 {
-	usb_free_all_descriptors(f);
-	kfree(func_to_gser(f));
+	return container_of(to_config_group(item), struct f_serial_opts,
+			    func_inst.group);
 }
 
-/**
- * gser_bind_config - add a generic serial function to a configuration
- * @c: the configuration to support the serial instance
- * @port_num: /dev/ttyGS* port this interface will use
- * Context: single threaded during gadget setup
- *
- * Returns zero on success, else negative errno.
- */
-int __init gser_bind_config(struct usb_configuration *c, u8 port_num)
+CONFIGFS_ATTR_STRUCT(f_serial_opts);
+static ssize_t f_serial_attr_show(struct config_item *item,
+				  struct configfs_attribute *attr,
+				  char *page)
 {
-	struct f_gser	*gser;
-	int		status;
+	struct f_serial_opts *opts = to_f_serial_opts(item);
+	struct f_serial_opts_attribute *f_serial_opts_attr =
+		container_of(attr, struct f_serial_opts_attribute, attr);
+	ssize_t ret = 0;
 
-	/* REVISIT might want instance-specific strings to help
-	 * distinguish instances ...
-	 */
+	if (f_serial_opts_attr->show)
+		ret = f_serial_opts_attr->show(opts, page);
 
-	/* maybe allocate device-global string ID */
-	if (gser_string_defs[0].id == 0) {
-		status = usb_string_id(c->cdev);
-		if (status < 0)
-			return status;
-		gser_string_defs[0].id = status;
+	return ret;
+}
+
+static void serial_attr_release(struct config_item *item)
+{
+	struct f_serial_opts *opts = to_f_serial_opts(item);
+
+	usb_put_function_instance(&opts->func_inst);
+}
+
+static struct configfs_item_operations serial_item_ops = {
+	.release	= serial_attr_release,
+	.show_attribute = f_serial_attr_show,
+};
+
+static ssize_t f_serial_port_num_show(struct f_serial_opts *opts, char *page)
+{
+	return sprintf(page, "%u\n", opts->port_num);
+}
+
+static struct f_serial_opts_attribute f_serial_port_num =
+	__CONFIGFS_ATTR_RO(port_num, f_serial_port_num_show);
+
+static struct configfs_attribute *acm_attrs[] = {
+	&f_serial_port_num.attr,
+	NULL,
+};
+
+static struct config_item_type serial_func_type = {
+	.ct_item_ops	= &serial_item_ops,
+	.ct_attrs	= acm_attrs,
+	.ct_owner	= THIS_MODULE,
+};
+
+static void gser_free_inst(struct usb_function_instance *f)
+{
+	struct f_serial_opts *opts;
+
+	opts = container_of(f, struct f_serial_opts, func_inst);
+	gserial_free_line(opts->port_num);
+	kfree(opts);
+}
+
+static struct usb_function_instance *gser_alloc_inst(void)
+{
+	struct f_serial_opts *opts;
+	int ret;
+
+	opts = kzalloc(sizeof(*opts), GFP_KERNEL);
+	if (!opts)
+		return ERR_PTR(-ENOMEM);
+
+	opts->func_inst.free_func_inst = gser_free_inst;
+	ret = gserial_alloc_line(&opts->port_num);
+	if (ret) {
+		kfree(opts);
+		return ERR_PTR(ret);
 	}
+	config_group_init_type_name(&opts->func_inst.group, "",
+				    &serial_func_type);
+
+	return &opts->func_inst;
+}
+
+static void gser_free(struct usb_function *f)
+{
+	struct f_gser *serial;
+
+	serial = func_to_gser(f);
+	kfree(serial);
+}
+
+static void gser_unbind(struct usb_configuration *c, struct usb_function *f)
+{
+	usb_free_all_descriptors(f);
+}
+
+struct usb_function *gser_alloc(struct usb_function_instance *fi)
+{
+	struct f_gser	*gser;
+	struct f_serial_opts *opts;
 
 	/* allocate and initialize one new instance */
-	gser = kzalloc(sizeof *gser, GFP_KERNEL);
+	gser = kzalloc(sizeof(*gser), GFP_KERNEL);
 	if (!gser)
-		return -ENOMEM;
+		return ERR_PTR(-ENOMEM);
 
-	gser->port_num = port_num;
+	opts = container_of(fi, struct f_serial_opts, func_inst);
+
+	gser->port_num = opts->port_num;
 
 	gser->port.func.name = "gser";
 	gser->port.func.strings = gser_strings;
@@ -291,9 +374,12 @@ int __init gser_bind_config(struct usb_configuration *c, u8 port_num)
 	gser->port.func.unbind = gser_unbind;
 	gser->port.func.set_alt = gser_set_alt;
 	gser->port.func.disable = gser_disable;
+	gser->port.func.free_func = gser_free;
 
-	status = usb_add_function(c, &gser->port.func);
-	if (status)
-		kfree(gser);
-	return status;
+	return &gser->port.func;
 }
+
+DECLARE_USB_FUNCTION_INIT(gser, gser_alloc_inst, gser_alloc);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Al Borchers");
+MODULE_AUTHOR("David Brownell");
diff --git a/drivers/usb/gadget/f_subset.c b/drivers/usb/gadget/f_subset.c
index f172bd1..185d6f5 100644
--- a/drivers/usb/gadget/f_subset.c
+++ b/drivers/usb/gadget/f_subset.c
@@ -380,7 +380,8 @@ geth_unbind(struct usb_configuration *c, struct usb_function *f)
  * Caller must have called @gether_setup().  Caller is also responsible
  * for calling @gether_cleanup() before module unload.
  */
-int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
+int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
+		struct eth_dev *dev)
 {
 	struct f_gether	*geth;
 	int		status;
@@ -406,6 +407,7 @@ int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
 	snprintf(geth->ethaddr, sizeof geth->ethaddr, "%pm", ethaddr);
 	geth_string_defs[1].s = geth->ethaddr;
 
+	geth->port.ioport = dev;
 	geth->port.cdc_filter = DEFAULT_FILTER;
 
 	geth->port.func.name = "cdc_subset";
diff --git a/drivers/usb/gadget/f_uvc.c b/drivers/usb/gadget/f_uvc.c
index 92efd6e..38dcedd 100644
--- a/drivers/usb/gadget/f_uvc.c
+++ b/drivers/usb/gadget/f_uvc.c
@@ -33,19 +33,15 @@ unsigned int uvc_gadget_trace_param;
 /*-------------------------------------------------------------------------*/
 
 /* module parameters specific to the Video streaming endpoint */
-static unsigned streaming_interval = 1;
+static unsigned int streaming_interval = 1;
 module_param(streaming_interval, uint, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(streaming_interval, "1 - 16");
 
-static unsigned streaming_maxpacket = 1024;
+static unsigned int streaming_maxpacket = 1024;
 module_param(streaming_maxpacket, uint, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(streaming_maxpacket, "0 - 1023 (fs), 0 - 1024 (hs/ss)");
+MODULE_PARM_DESC(streaming_maxpacket, "1 - 1023 (FS), 1 - 3072 (hs/ss)");
 
-static unsigned streaming_mult;
-module_param(streaming_mult, uint, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(streaming_mult, "0 - 2 (hs/ss only)");
-
-static unsigned streaming_maxburst;
+static unsigned int streaming_maxburst;
 module_param(streaming_maxburst, uint, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(streaming_maxburst, "0 - 15 (ss only)");
 
@@ -55,13 +51,11 @@ MODULE_PARM_DESC(streaming_maxburst, "0 - 15 (ss only)");
 
 /* string IDs are assigned dynamically */
 
-#define UVC_STRING_ASSOCIATION_IDX		0
-#define UVC_STRING_CONTROL_IDX			1
-#define UVC_STRING_STREAMING_IDX		2
+#define UVC_STRING_CONTROL_IDX			0
+#define UVC_STRING_STREAMING_IDX		1
 
 static struct usb_string uvc_en_us_strings[] = {
-	[UVC_STRING_ASSOCIATION_IDX].s = "UVC Camera",
-	[UVC_STRING_CONTROL_IDX].s = "Video Control",
+	[UVC_STRING_CONTROL_IDX].s = "UVC Camera",
 	[UVC_STRING_STREAMING_IDX].s = "Video Streaming",
 	{  }
 };
@@ -79,7 +73,7 @@ static struct usb_gadget_strings *uvc_function_strings[] = {
 #define UVC_INTF_VIDEO_CONTROL			0
 #define UVC_INTF_VIDEO_STREAMING		1
 
-#define STATUS_BYTECOUNT			16	/* 16 bytes status */
+#define UVC_STATUS_MAX_PACKET_SIZE		16	/* 16 bytes status */
 
 static struct usb_interface_assoc_descriptor uvc_iad __initdata = {
 	.bLength		= sizeof(uvc_iad),
@@ -104,20 +98,29 @@ static struct usb_interface_descriptor uvc_control_intf __initdata = {
 	.iInterface		= 0,
 };
 
-static struct usb_endpoint_descriptor uvc_fs_control_ep __initdata = {
+static struct usb_endpoint_descriptor uvc_control_ep __initdata = {
 	.bLength		= USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType	= USB_DT_ENDPOINT,
 	.bEndpointAddress	= USB_DIR_IN,
 	.bmAttributes		= USB_ENDPOINT_XFER_INT,
-	.wMaxPacketSize		= cpu_to_le16(STATUS_BYTECOUNT),
+	.wMaxPacketSize		= cpu_to_le16(UVC_STATUS_MAX_PACKET_SIZE),
 	.bInterval		= 8,
 };
 
+static struct usb_ss_ep_comp_descriptor uvc_ss_control_comp __initdata = {
+	.bLength		= sizeof(uvc_ss_control_comp),
+	.bDescriptorType	= USB_DT_SS_ENDPOINT_COMP,
+	/* The following 3 values can be tweaked if necessary. */
+	.bMaxBurst		= 0,
+	.bmAttributes		= 0,
+	.wBytesPerInterval	= cpu_to_le16(UVC_STATUS_MAX_PACKET_SIZE),
+};
+
 static struct uvc_control_endpoint_descriptor uvc_control_cs_ep __initdata = {
 	.bLength		= UVC_DT_CONTROL_ENDPOINT_SIZE,
 	.bDescriptorType	= USB_DT_CS_ENDPOINT,
 	.bDescriptorSubType	= UVC_EP_INTERRUPT,
-	.wMaxTransferSize	= cpu_to_le16(STATUS_BYTECOUNT),
+	.wMaxTransferSize	= cpu_to_le16(UVC_STATUS_MAX_PACKET_SIZE),
 };
 
 static struct usb_interface_descriptor uvc_streaming_intf_alt0 __initdata = {
@@ -144,63 +147,53 @@ static struct usb_interface_descriptor uvc_streaming_intf_alt1 __initdata = {
 	.iInterface		= 0,
 };
 
-static struct usb_endpoint_descriptor uvc_fs_streaming_ep = {
+static struct usb_endpoint_descriptor uvc_fs_streaming_ep __initdata = {
 	.bLength		= USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType	= USB_DT_ENDPOINT,
 	.bEndpointAddress	= USB_DIR_IN,
-	.bmAttributes		= USB_ENDPOINT_XFER_ISOC,
-	.wMaxPacketSize		= cpu_to_le16(512),
-	.bInterval		= 1,
+	.bmAttributes		= USB_ENDPOINT_SYNC_ASYNC
+				| USB_ENDPOINT_XFER_ISOC,
+	/* The wMaxPacketSize and bInterval values will be initialized from
+	 * module parameters.
+	 */
+	.wMaxPacketSize		= 0,
+	.bInterval		= 0,
 };
 
-static struct usb_endpoint_descriptor uvc_hs_streaming_ep = {
+static struct usb_endpoint_descriptor uvc_hs_streaming_ep __initdata = {
 	.bLength		= USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType	= USB_DT_ENDPOINT,
 	.bEndpointAddress	= USB_DIR_IN,
-	.bmAttributes		= USB_ENDPOINT_XFER_ISOC,
-	.wMaxPacketSize		= cpu_to_le16(1024),
-	.bInterval		= 1,
-};
-
-/* super speed support */
-static struct usb_endpoint_descriptor uvc_ss_control_ep __initdata = {
-	.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 =		8,
-};
-
-static struct usb_ss_ep_comp_descriptor uvc_ss_control_comp __initdata = {
-	.bLength =		sizeof uvc_ss_control_comp,
-	.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),
+	.bmAttributes		= USB_ENDPOINT_SYNC_ASYNC
+				| USB_ENDPOINT_XFER_ISOC,
+	/* The wMaxPacketSize and bInterval values will be initialized from
+	 * module parameters.
+	 */
+	.wMaxPacketSize		= 0,
+	.bInterval		= 0,
 };
 
 static struct usb_endpoint_descriptor uvc_ss_streaming_ep __initdata = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
+	.bLength		= USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType	= USB_DT_ENDPOINT,
 
-	.bEndpointAddress =	USB_DIR_IN,
-	.bmAttributes =		USB_ENDPOINT_XFER_ISOC,
-	.wMaxPacketSize =	cpu_to_le16(1024),
-	.bInterval =		4,
+	.bEndpointAddress	= USB_DIR_IN,
+	.bmAttributes		= USB_ENDPOINT_SYNC_ASYNC
+				| USB_ENDPOINT_XFER_ISOC,
+	/* The wMaxPacketSize and bInterval values will be initialized from
+	 * module parameters.
+	 */
+	.wMaxPacketSize		= 0,
+	.bInterval		= 0,
 };
 
-static struct usb_ss_ep_comp_descriptor uvc_ss_streaming_comp = {
-	.bLength =		sizeof uvc_ss_streaming_comp,
-	.bDescriptorType =	USB_DT_SS_ENDPOINT_COMP,
-
-	/* the following 3 values can be tweaked if necessary */
-	.bMaxBurst =		0,
-	.bmAttributes =	0,
-	.wBytesPerInterval =	cpu_to_le16(1024),
+static struct usb_ss_ep_comp_descriptor uvc_ss_streaming_comp __initdata = {
+	.bLength		= sizeof(uvc_ss_streaming_comp),
+	.bDescriptorType	= USB_DT_SS_ENDPOINT_COMP,
+	/* The following 3 values can be tweaked if necessary. */
+	.bMaxBurst		= 0,
+	.bmAttributes		= 0,
+	.wBytesPerInterval	= cpu_to_le16(1024),
 };
 
 static const struct usb_descriptor_header * const uvc_fs_streaming[] = {
@@ -273,6 +266,13 @@ uvc_function_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
 	return 0;
 }
 
+void uvc_function_setup_continue(struct uvc_device *uvc)
+{
+	struct usb_composite_dev *cdev = uvc->func.config->cdev;
+
+	usb_composite_setup_continue(cdev);
+}
+
 static int
 uvc_function_get_alt(struct usb_function *f, unsigned interface)
 {
@@ -335,7 +335,7 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt)
 		v4l2_event_queue(uvc->vdev, &v4l2_event);
 
 		uvc->state = UVC_STATE_CONNECTED;
-		break;
+		return 0;
 
 	case 1:
 		if (uvc->state != UVC_STATE_CONNECTED)
@@ -352,15 +352,11 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt)
 		memset(&v4l2_event, 0, sizeof(v4l2_event));
 		v4l2_event.type = UVC_EVENT_STREAMON;
 		v4l2_event_queue(uvc->vdev, &v4l2_event);
-
-		uvc->state = UVC_STATE_STREAMING;
-		break;
+		return USB_GADGET_DELAYED_STATUS;
 
 	default:
 		return -EINVAL;
 	}
-
-	return 0;
 }
 
 static void
@@ -454,7 +450,6 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
 	const struct uvc_descriptor_header * const *uvc_streaming_cls;
 	const struct usb_descriptor_header * const *uvc_streaming_std;
 	const struct usb_descriptor_header * const *src;
-	static struct usb_endpoint_descriptor *uvc_control_ep;
 	struct usb_descriptor_header **dst;
 	struct usb_descriptor_header **hdr;
 	unsigned int control_size;
@@ -468,14 +463,12 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
 		uvc_control_desc = uvc->desc.ss_control;
 		uvc_streaming_cls = uvc->desc.ss_streaming;
 		uvc_streaming_std = uvc_ss_streaming;
-		uvc_control_ep = &uvc_ss_control_ep;
 		break;
 
 	case USB_SPEED_HIGH:
 		uvc_control_desc = uvc->desc.fs_control;
 		uvc_streaming_cls = uvc->desc.hs_streaming;
 		uvc_streaming_std = uvc_hs_streaming;
-		uvc_control_ep = &uvc_fs_control_ep;
 		break;
 
 	case USB_SPEED_FULL:
@@ -483,7 +476,6 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
 		uvc_control_desc = uvc->desc.fs_control;
 		uvc_streaming_cls = uvc->desc.fs_streaming;
 		uvc_streaming_std = uvc_fs_streaming;
-		uvc_control_ep = &uvc_fs_control_ep;
 		break;
 	}
 
@@ -494,6 +486,7 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
 	 * Class-specific UVC control descriptors
 	 * uvc_control_ep
 	 * uvc_control_cs_ep
+	 * uvc_ss_control_comp (for SS only)
 	 * uvc_streaming_intf_alt0
 	 * Class-specific UVC streaming descriptors
 	 * uvc_{fs|hs}_streaming
@@ -503,7 +496,7 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
 	control_size = 0;
 	streaming_size = 0;
 	bytes = uvc_iad.bLength + uvc_control_intf.bLength
-	      + uvc_control_ep->bLength + uvc_control_cs_ep.bLength
+	      + uvc_control_ep.bLength + uvc_control_cs_ep.bLength
 	      + uvc_streaming_intf_alt0.bLength;
 
 	if (speed == USB_SPEED_SUPER) {
@@ -514,13 +507,13 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
 	}
 
 	for (src = (const struct usb_descriptor_header **)uvc_control_desc;
-			*src; ++src) {
+	     *src; ++src) {
 		control_size += (*src)->bLength;
 		bytes += (*src)->bLength;
 		n_desc++;
 	}
 	for (src = (const struct usb_descriptor_header **)uvc_streaming_cls;
-			*src; ++src) {
+	     *src; ++src) {
 		streaming_size += (*src)->bLength;
 		bytes += (*src)->bLength;
 		n_desc++;
@@ -549,7 +542,7 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
 	uvc_control_header->bInCollection = 1;
 	uvc_control_header->baInterfaceNr[0] = uvc->streaming_intf;
 
-	UVC_COPY_DESCRIPTOR(mem, dst, uvc_control_ep);
+	UVC_COPY_DESCRIPTOR(mem, dst, &uvc_control_ep);
 	if (speed == USB_SPEED_SUPER)
 		UVC_COPY_DESCRIPTOR(mem, dst, &uvc_ss_control_comp);
 
@@ -560,8 +553,7 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
 	UVC_COPY_DESCRIPTORS(mem, dst,
 		(const struct usb_descriptor_header**)uvc_streaming_cls);
 	uvc_streaming_header->wTotalLength = cpu_to_le16(streaming_size);
-	uvc_streaming_header->bEndpointAddress =
-		uvc_fs_streaming_ep.bEndpointAddress;
+	uvc_streaming_header->bEndpointAddress = uvc->video.ep->address;
 
 	UVC_COPY_DESCRIPTORS(mem, dst, uvc_streaming_std);
 
@@ -581,7 +573,7 @@ uvc_function_unbind(struct usb_configuration *c, struct usb_function *f)
 	uvc->control_ep->driver_data = NULL;
 	uvc->video.ep->driver_data = NULL;
 
-	uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id = 0;
+	uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id = 0;
 	usb_ep_free_request(cdev->gadget->ep0, uvc->control_req);
 	kfree(uvc->control_buf);
 
@@ -595,31 +587,52 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
 {
 	struct usb_composite_dev *cdev = c->cdev;
 	struct uvc_device *uvc = to_uvc(f);
+	unsigned int max_packet_mult;
+	unsigned int max_packet_size;
 	struct usb_ep *ep;
 	int ret = -EINVAL;
 
 	INFO(cdev, "uvc_function_bind\n");
 
-	/* sanity check the streaming endpoint module parameters */
-	if (streaming_interval < 1)
-		streaming_interval = 1;
-	if (streaming_interval > 16)
-		streaming_interval = 16;
-	if (streaming_mult > 2)
-		streaming_mult = 2;
-	if (streaming_maxburst > 15)
-		streaming_maxburst = 15;
-
-	/*
-	 * fill in the FS video streaming specific descriptors from the
-	 * module parameters
+	/* Sanity check the streaming endpoint module parameters.
 	 */
-	uvc_fs_streaming_ep.wMaxPacketSize = streaming_maxpacket > 1023 ?
-						1023 : streaming_maxpacket;
+	streaming_interval = clamp(streaming_interval, 1U, 16U);
+	streaming_maxpacket = clamp(streaming_maxpacket, 1U, 3072U);
+	streaming_maxburst = min(streaming_maxburst, 15U);
+
+	/* Fill in the FS/HS/SS Video Streaming specific descriptors from the
+	 * module parameters.
+	 *
+	 * NOTE: We assume that the user knows what they are doing and won't
+	 * give parameters that their UDC doesn't support.
+	 */
+	if (streaming_maxpacket <= 1024) {
+		max_packet_mult = 1;
+		max_packet_size = streaming_maxpacket;
+	} else if (streaming_maxpacket <= 2048) {
+		max_packet_mult = 2;
+		max_packet_size = streaming_maxpacket / 2;
+	} else {
+		max_packet_mult = 3;
+		max_packet_size = streaming_maxpacket / 3;
+	}
+
+	uvc_fs_streaming_ep.wMaxPacketSize = min(streaming_maxpacket, 1023U);
 	uvc_fs_streaming_ep.bInterval = streaming_interval;
 
+	uvc_hs_streaming_ep.wMaxPacketSize = max_packet_size;
+	uvc_hs_streaming_ep.wMaxPacketSize |= ((max_packet_mult - 1) << 11);
+	uvc_hs_streaming_ep.bInterval = streaming_interval;
+
+	uvc_ss_streaming_ep.wMaxPacketSize = max_packet_size;
+	uvc_ss_streaming_ep.bInterval = streaming_interval;
+	uvc_ss_streaming_comp.bmAttributes = max_packet_mult - 1;
+	uvc_ss_streaming_comp.bMaxBurst = streaming_maxburst;
+	uvc_ss_streaming_comp.wBytesPerInterval =
+		max_packet_size * max_packet_mult * streaming_maxburst;
+
 	/* Allocate endpoints. */
-	ep = usb_ep_autoconfig(cdev->gadget, &uvc_fs_control_ep);
+	ep = usb_ep_autoconfig(cdev->gadget, &uvc_control_ep);
 	if (!ep) {
 		INFO(cdev, "Unable to allocate control EP\n");
 		goto error;
@@ -627,7 +640,14 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
 	uvc->control_ep = ep;
 	ep->driver_data = uvc;
 
-	ep = usb_ep_autoconfig(cdev->gadget, &uvc_fs_streaming_ep);
+	if (gadget_is_superspeed(c->cdev->gadget))
+		ep = usb_ep_autoconfig_ss(cdev->gadget, &uvc_ss_streaming_ep,
+					  &uvc_ss_streaming_comp);
+	else if (gadget_is_dualspeed(cdev->gadget))
+		ep = usb_ep_autoconfig(cdev->gadget, &uvc_hs_streaming_ep);
+	else
+		ep = usb_ep_autoconfig(cdev->gadget, &uvc_fs_streaming_ep);
+
 	if (!ep) {
 		INFO(cdev, "Unable to allocate streaming EP\n");
 		goto error;
@@ -635,6 +655,10 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
 	uvc->video.ep = ep;
 	ep->driver_data = uvc;
 
+	uvc_fs_streaming_ep.bEndpointAddress = uvc->video.ep->address;
+	uvc_hs_streaming_ep.bEndpointAddress = uvc->video.ep->address;
+	uvc_ss_streaming_ep.bEndpointAddress = uvc->video.ep->address;
+
 	/* Allocate interface IDs. */
 	if ((ret = usb_interface_id(c, f)) < 0)
 		goto error;
@@ -648,37 +672,6 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
 	uvc_streaming_intf_alt1.bInterfaceNumber = ret;
 	uvc->streaming_intf = ret;
 
-	/* sanity check the streaming endpoint module parameters */
-	if (streaming_maxpacket > 1024)
-		streaming_maxpacket = 1024;
-	/*
-	 * Fill in the HS descriptors from the module parameters for the Video
-	 * Streaming endpoint.
-	 * NOTE: We assume that the user knows what they are doing and won't
-	 * give parameters that their UDC doesn't support.
-	 */
-	uvc_hs_streaming_ep.wMaxPacketSize = streaming_maxpacket;
-	uvc_hs_streaming_ep.wMaxPacketSize |= streaming_mult << 11;
-	uvc_hs_streaming_ep.bInterval = streaming_interval;
-	uvc_hs_streaming_ep.bEndpointAddress =
-		uvc_fs_streaming_ep.bEndpointAddress;
-
-	/*
-	 * Fill in the SS descriptors from the module parameters for the Video
-	 * Streaming endpoint.
-	 * NOTE: We assume that the user knows what they are doing and won't
-	 * give parameters that their UDC doesn't support.
-	 */
-	uvc_ss_streaming_ep.wMaxPacketSize = streaming_maxpacket;
-	uvc_ss_streaming_ep.bInterval = streaming_interval;
-	uvc_ss_streaming_comp.bmAttributes = streaming_mult;
-	uvc_ss_streaming_comp.bMaxBurst = streaming_maxburst;
-	uvc_ss_streaming_comp.wBytesPerInterval =
-		streaming_maxpacket * (streaming_mult + 1) *
-		(streaming_maxburst + 1);
-	uvc_ss_streaming_ep.bEndpointAddress =
-		uvc_fs_streaming_ep.bEndpointAddress;
-
 	/* Copy descriptors */
 	f->fs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_FULL);
 	if (gadget_is_dualspeed(cdev->gadget))
@@ -775,23 +768,23 @@ uvc_bind_config(struct usb_configuration *c,
 
 	/* Validate the descriptors. */
 	if (fs_control == NULL || fs_control[0] == NULL ||
-		fs_control[0]->bDescriptorSubType != UVC_VC_HEADER)
+	    fs_control[0]->bDescriptorSubType != UVC_VC_HEADER)
 		goto error;
 
 	if (ss_control == NULL || ss_control[0] == NULL ||
-		ss_control[0]->bDescriptorSubType != UVC_VC_HEADER)
+	    ss_control[0]->bDescriptorSubType != UVC_VC_HEADER)
 		goto error;
 
 	if (fs_streaming == NULL || fs_streaming[0] == NULL ||
-		fs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)
+	    fs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)
 		goto error;
 
 	if (hs_streaming == NULL || hs_streaming[0] == NULL ||
-		hs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)
+	    hs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)
 		goto error;
 
 	if (ss_streaming == NULL || ss_streaming[0] == NULL ||
-		ss_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)
+	    ss_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)
 		goto error;
 
 	uvc->desc.fs_control = fs_control;
@@ -800,13 +793,16 @@ uvc_bind_config(struct usb_configuration *c,
 	uvc->desc.hs_streaming = hs_streaming;
 	uvc->desc.ss_streaming = ss_streaming;
 
-	/* Allocate string descriptor numbers. */
-	if (uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id == 0) {
+	/* String descriptors are global, we only need to allocate string IDs
+	 * for the first UVC function. UVC functions beyond the first (if any)
+	 * will reuse the same IDs.
+	 */
+	if (uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id == 0) {
 		ret = usb_string_ids_tab(c->cdev, uvc_en_us_strings);
 		if (ret)
 			goto error;
 		uvc_iad.iFunction =
-			uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id;
+			uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id;
 		uvc_control_intf.iInterface =
 			uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id;
 		ret = uvc_en_us_strings[UVC_STRING_STREAMING_IDX].id;
diff --git a/drivers/usb/gadget/f_uvc.h b/drivers/usb/gadget/f_uvc.h
index c3d258d..ec52752 100644
--- a/drivers/usb/gadget/f_uvc.h
+++ b/drivers/usb/gadget/f_uvc.h
@@ -16,12 +16,12 @@
 #include <linux/usb/composite.h>
 #include <linux/usb/video.h>
 
-extern int uvc_bind_config(struct usb_configuration *c,
-		   const struct uvc_descriptor_header * const *fs_control,
-		   const struct uvc_descriptor_header * const *hs_control,
-		   const struct uvc_descriptor_header * const *fs_streaming,
-		   const struct uvc_descriptor_header * const *hs_streaming,
-		   const struct uvc_descriptor_header * const *ss_streaming);
+int uvc_bind_config(struct usb_configuration *c,
+		    const struct uvc_descriptor_header * const *fs_control,
+		    const struct uvc_descriptor_header * const *hs_control,
+		    const struct uvc_descriptor_header * const *fs_streaming,
+		    const struct uvc_descriptor_header * const *hs_streaming,
+		    const struct uvc_descriptor_header * const *ss_streaming);
 
 #endif /* _F_UVC_H_ */
 
diff --git a/drivers/usb/gadget/fsl_qe_udc.c b/drivers/usb/gadget/fsl_qe_udc.c
index 034477c..9a7ee33 100644
--- a/drivers/usb/gadget/fsl_qe_udc.c
+++ b/drivers/usb/gadget/fsl_qe_udc.c
@@ -2296,7 +2296,6 @@ static int fsl_qe_start(struct usb_gadget *gadget,
 	driver->driver.bus = NULL;
 	/* hook up the driver */
 	udc->driver = driver;
-	udc->gadget.dev.driver = &driver->driver;
 	udc->gadget.speed = driver->max_speed;
 
 	/* Enable IRQ reg and Set usbcmd reg EN bit */
@@ -2338,7 +2337,6 @@ static int fsl_qe_stop(struct usb_gadget *gadget,
 		nuke(loop_ep, -ESHUTDOWN);
 	spin_unlock_irqrestore(&udc->lock, flags);
 
-	udc->gadget.dev.driver = NULL;
 	udc->driver = NULL;
 
 	dev_info(udc->dev, "unregistered gadget driver '%s'\r\n",
@@ -2523,12 +2521,6 @@ static int qe_udc_probe(struct platform_device *ofdev)
 
 	/* name: Identifies the controller hardware type. */
 	udc->gadget.name = driver_name;
-
-	device_initialize(&udc->gadget.dev);
-
-	dev_set_name(&udc->gadget.dev, "gadget");
-
-	udc->gadget.dev.release = qe_udc_release;
 	udc->gadget.dev.parent = &ofdev->dev;
 
 	/* initialize qe_ep struct */
@@ -2592,22 +2584,17 @@ static int qe_udc_probe(struct platform_device *ofdev)
 		goto err5;
 	}
 
-	ret = device_add(&udc->gadget.dev);
+	ret = usb_add_gadget_udc_release(&ofdev->dev, &udc->gadget,
+			qe_udc_release);
 	if (ret)
 		goto err6;
 
-	ret = usb_add_gadget_udc(&ofdev->dev, &udc->gadget);
-	if (ret)
-		goto err7;
-
 	dev_set_drvdata(&ofdev->dev, udc);
 	dev_info(udc->dev,
 			"%s USB controller initialized as device\n",
 			(udc->soc_type == PORT_QE) ? "QE" : "CPM");
 	return 0;
 
-err7:
-	device_unregister(&udc->gadget.dev);
 err6:
 	free_irq(udc->usb_irq, udc);
 err5:
@@ -2702,7 +2689,6 @@ static int qe_udc_remove(struct platform_device *ofdev)
 
 	iounmap(udc->usb_regs);
 
-	device_unregister(&udc->gadget.dev);
 	/* wait for release() of gadget.dev to free udc */
 	wait_for_completion(&done);
 
diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c
index 04d5fef..7c2a101 100644
--- a/drivers/usb/gadget/fsl_udc_core.c
+++ b/drivers/usb/gadget/fsl_udc_core.c
@@ -185,20 +185,7 @@ static void done(struct fsl_ep *ep, struct fsl_req *req, int status)
 		dma_pool_free(udc->td_pool, curr_td, curr_td->td_dma);
 	}
 
-	if (req->mapped) {
-		dma_unmap_single(ep->udc->gadget.dev.parent,
-			req->req.dma, req->req.length,
-			ep_is_in(ep)
-				? DMA_TO_DEVICE
-				: DMA_FROM_DEVICE);
-		req->req.dma = DMA_ADDR_INVALID;
-		req->mapped = 0;
-	} else
-		dma_sync_single_for_cpu(ep->udc->gadget.dev.parent,
-			req->req.dma, req->req.length,
-			ep_is_in(ep)
-				? DMA_TO_DEVICE
-				: DMA_FROM_DEVICE);
+	usb_gadget_unmap_request(&ep->udc->gadget, &req->req, ep_is_in(ep));
 
 	if (status && (status != -ESHUTDOWN))
 		VDBG("complete %s req %p stat %d len %u/%u",
@@ -888,6 +875,7 @@ fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 	struct fsl_req *req = container_of(_req, struct fsl_req, req);
 	struct fsl_udc *udc;
 	unsigned long flags;
+	int ret;
 
 	/* catch various bogus parameters */
 	if (!_req || !req->req.complete || !req->req.buf
@@ -910,22 +898,9 @@ fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 
 	req->ep = ep;
 
-	/* map virtual address to hardware */
-	if (req->req.dma == DMA_ADDR_INVALID) {
-		req->req.dma = dma_map_single(ep->udc->gadget.dev.parent,
-					req->req.buf,
-					req->req.length, ep_is_in(ep)
-						? DMA_TO_DEVICE
-						: DMA_FROM_DEVICE);
-		req->mapped = 1;
-	} else {
-		dma_sync_single_for_device(ep->udc->gadget.dev.parent,
-					req->req.dma, req->req.length,
-					ep_is_in(ep)
-						? DMA_TO_DEVICE
-						: DMA_FROM_DEVICE);
-		req->mapped = 0;
-	}
+	ret = usb_gadget_map_request(&ep->udc->gadget, &req->req, ep_is_in(ep));
+	if (ret)
+		return ret;
 
 	req->req.status = -EINPROGRESS;
 	req->req.actual = 0;
@@ -1290,6 +1265,7 @@ static int ep0_prime_status(struct fsl_udc *udc, int direction)
 {
 	struct fsl_req *req = udc->status_req;
 	struct fsl_ep *ep;
+	int ret;
 
 	if (direction == EP_DIR_IN)
 		udc->ep0_dir = USB_DIR_IN;
@@ -1307,10 +1283,9 @@ static int ep0_prime_status(struct fsl_udc *udc, int direction)
 	req->req.complete = NULL;
 	req->dtd_count = 0;
 
-	req->req.dma = dma_map_single(ep->udc->gadget.dev.parent,
-			req->req.buf, req->req.length,
-			ep_is_in(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
-	req->mapped = 1;
+	ret = usb_gadget_map_request(&ep->udc->gadget, &req->req, ep_is_in(ep));
+	if (ret)
+		return ret;
 
 	if (fsl_req_to_dtd(req, GFP_ATOMIC) == 0)
 		fsl_queue_td(ep, req);
@@ -1353,6 +1328,7 @@ static void ch9getstatus(struct fsl_udc *udc, u8 request_type, u16 value,
 	u16 tmp = 0;		/* Status, cpu endian */
 	struct fsl_req *req;
 	struct fsl_ep *ep;
+	int ret;
 
 	ep = &udc->eps[0];
 
@@ -1390,10 +1366,9 @@ static void ch9getstatus(struct fsl_udc *udc, u8 request_type, u16 value,
 	req->req.complete = NULL;
 	req->dtd_count = 0;
 
-	req->req.dma = dma_map_single(ep->udc->gadget.dev.parent,
-				req->req.buf, req->req.length,
-				ep_is_in(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
-	req->mapped = 1;
+	ret = usb_gadget_map_request(&ep->udc->gadget, &req->req, ep_is_in(ep));
+	if (ret)
+		goto stall;
 
 	/* prime the data phase */
 	if ((fsl_req_to_dtd(req, GFP_ATOMIC) == 0))
@@ -1964,7 +1939,6 @@ static int fsl_udc_start(struct usb_gadget *g,
 	driver->driver.bus = NULL;
 	/* hook up the driver */
 	udc_controller->driver = driver;
-	udc_controller->gadget.dev.driver = &driver->driver;
 	spin_unlock_irqrestore(&udc_controller->lock, flags);
 
 	if (!IS_ERR_OR_NULL(udc_controller->transceiver)) {
@@ -1980,7 +1954,6 @@ static int fsl_udc_start(struct usb_gadget *g,
 			if (retval < 0) {
 				ERR("can't bind to transceiver\n");
 				driver->unbind(&udc_controller->gadget);
-				udc_controller->gadget.dev.driver = 0;
 				udc_controller->driver = 0;
 				return retval;
 			}
@@ -2023,7 +1996,6 @@ static int fsl_udc_stop(struct usb_gadget *g,
 		nuke(loop_ep, -ESHUTDOWN);
 	spin_unlock_irqrestore(&udc_controller->lock, flags);
 
-	udc_controller->gadget.dev.driver = NULL;
 	udc_controller->driver = NULL;
 
 	return 0;
@@ -2521,12 +2493,7 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
 
 	/* Setup gadget.dev and register with kernel */
 	dev_set_name(&udc_controller->gadget.dev, "gadget");
-	udc_controller->gadget.dev.release = fsl_udc_release;
-	udc_controller->gadget.dev.parent = &pdev->dev;
 	udc_controller->gadget.dev.of_node = pdev->dev.of_node;
-	ret = device_register(&udc_controller->gadget.dev);
-	if (ret < 0)
-		goto err_free_irq;
 
 	if (!IS_ERR_OR_NULL(udc_controller->transceiver))
 		udc_controller->gadget.is_otg = 1;
@@ -2559,10 +2526,11 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
 			DTD_ALIGNMENT, UDC_DMA_BOUNDARY);
 	if (udc_controller->td_pool == NULL) {
 		ret = -ENOMEM;
-		goto err_unregister;
+		goto err_free_irq;
 	}
 
-	ret = usb_add_gadget_udc(&pdev->dev, &udc_controller->gadget);
+	ret = usb_add_gadget_udc_release(&pdev->dev, &udc_controller->gadget,
+			fsl_udc_release);
 	if (ret)
 		goto err_del_udc;
 
@@ -2571,8 +2539,6 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
 
 err_del_udc:
 	dma_pool_destroy(udc_controller->td_pool);
-err_unregister:
-	device_unregister(&udc_controller->gadget.dev);
 err_free_irq:
 	free_irq(udc_controller->irq, udc_controller);
 err_iounmap:
@@ -2622,7 +2588,6 @@ static int __exit fsl_udc_remove(struct platform_device *pdev)
 	if (pdata->operating_mode == FSL_USB2_DR_DEVICE)
 		release_mem_region(res->start, resource_size(res));
 
-	device_unregister(&udc_controller->gadget.dev);
 	/* free udc --wait for the release() finished */
 	wait_for_completion(&done);
 
@@ -2747,21 +2712,7 @@ static struct platform_driver udc_driver = {
 	},
 };
 
-static int __init udc_init(void)
-{
-	printk(KERN_INFO "%s (%s)\n", driver_desc, DRIVER_VERSION);
-	return platform_driver_probe(&udc_driver, fsl_udc_probe);
-}
-
-module_init(udc_init);
-
-static void __exit udc_exit(void)
-{
-	platform_driver_unregister(&udc_driver);
-	printk(KERN_WARNING "%s unregistered\n", driver_desc);
-}
-
-module_exit(udc_exit);
+module_platform_driver_probe(udc_driver, fsl_udc_probe);
 
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_AUTHOR(DRIVER_AUTHOR);
diff --git a/drivers/usb/gadget/fusb300_udc.c b/drivers/usb/gadget/fusb300_udc.c
index 066cb89..cec8871 100644
--- a/drivers/usb/gadget/fusb300_udc.c
+++ b/drivers/usb/gadget/fusb300_udc.c
@@ -394,7 +394,7 @@ static void fusb300_clear_epnstall(struct fusb300 *fusb300, u8 ep)
 
 	if (reg & FUSB300_EPSET0_STL) {
 		printk(KERN_DEBUG "EP%d stall... Clear!!\n", ep);
-		reg &= ~FUSB300_EPSET0_STL;
+		reg |= FUSB300_EPSET0_STL_CLR;
 		iowrite32(reg, fusb300->reg + FUSB300_OFFSET_EPSET0(ep));
 	}
 }
@@ -930,33 +930,33 @@ static void fusb300_wait_idma_finished(struct fusb300_ep *ep)
 
 	fusb300_clear_int(ep->fusb300, FUSB300_OFFSET_IGR0,
 		FUSB300_IGR0_EPn_PRD_INT(ep->epnum));
+	return;
+
 IDMA_RESET:
-	fusb300_clear_int(ep->fusb300, FUSB300_OFFSET_IGER0,
-		FUSB300_IGER0_EEPn_PRD_INT(ep->epnum));
+	reg = ioread32(ep->fusb300->reg + FUSB300_OFFSET_IGER0);
+	reg &= ~FUSB300_IGER0_EEPn_PRD_INT(ep->epnum);
+	iowrite32(reg, ep->fusb300->reg + FUSB300_OFFSET_IGER0);
 }
 
-static void  fusb300_set_idma(struct fusb300_ep *ep,
+static void fusb300_set_idma(struct fusb300_ep *ep,
 			struct fusb300_request *req)
 {
-	dma_addr_t d;
-
-	d = dma_map_single(NULL, req->req.buf, req->req.length, DMA_TO_DEVICE);
+	int ret;
 
-	if (dma_mapping_error(NULL, d)) {
-		printk(KERN_DEBUG "dma_mapping_error\n");
+	ret = usb_gadget_map_request(&ep->fusb300->gadget,
+			&req->req, DMA_TO_DEVICE);
+	if (ret)
 		return;
-	}
-
-	dma_sync_single_for_device(NULL, d, req->req.length, DMA_TO_DEVICE);
 
 	fusb300_enable_bit(ep->fusb300, FUSB300_OFFSET_IGER0,
 		FUSB300_IGER0_EEPn_PRD_INT(ep->epnum));
 
-	fusb300_fill_idma_prdtbl(ep, d, req->req.length);
+	fusb300_fill_idma_prdtbl(ep, req->req.dma, req->req.length);
 	/* check idma is done */
 	fusb300_wait_idma_finished(ep);
 
-	dma_unmap_single(NULL, d, req->req.length, DMA_TO_DEVICE);
+	usb_gadget_unmap_request(&ep->fusb300->gadget,
+			&req->req, DMA_TO_DEVICE);
 }
 
 static void in_ep_fifo_handler(struct fusb300_ep *ep)
@@ -1316,7 +1316,6 @@ static int fusb300_udc_start(struct usb_gadget *g,
 	/* hook up the driver */
 	driver->driver.bus = NULL;
 	fusb300->driver = driver;
-	fusb300->gadget.dev.driver = &driver->driver;
 
 	return 0;
 }
@@ -1327,7 +1326,6 @@ static int fusb300_udc_stop(struct usb_gadget *g,
 	struct fusb300 *fusb300 = to_fusb300(g);
 
 	driver->unbind(&fusb300->gadget);
-	fusb300->gadget.dev.driver = NULL;
 
 	init_controller(fusb300);
 	fusb300->driver = NULL;
@@ -1422,14 +1420,7 @@ static int __init fusb300_probe(struct platform_device *pdev)
 
 	fusb300->gadget.ops = &fusb300_gadget_ops;
 
-	device_initialize(&fusb300->gadget.dev);
-
-	dev_set_name(&fusb300->gadget.dev, "gadget");
-
 	fusb300->gadget.max_speed = USB_SPEED_HIGH;
-	fusb300->gadget.dev.parent = &pdev->dev;
-	fusb300->gadget.dev.dma_mask = pdev->dev.dma_mask;
-	fusb300->gadget.dev.release = pdev->dev.release;
 	fusb300->gadget.name = udc_name;
 	fusb300->reg = reg;
 
@@ -1478,19 +1469,10 @@ static int __init fusb300_probe(struct platform_device *pdev)
 	if (ret)
 		goto err_add_udc;
 
-	ret = device_add(&fusb300->gadget.dev);
-	if (ret) {
-		pr_err("device_add error (%d)\n", ret);
-		goto err_add_device;
-	}
-
 	dev_info(&pdev->dev, "version %s\n", DRIVER_VERSION);
 
 	return 0;
 
-err_add_device:
-	usb_del_gadget_udc(&fusb300->gadget);
-
 err_add_udc:
 	fusb300_free_request(&fusb300->ep[0]->ep, fusb300->ep0_req);
 
diff --git a/drivers/usb/gadget/fusb300_udc.h b/drivers/usb/gadget/fusb300_udc.h
index 6ba444a..ae811d8 100644
--- a/drivers/usb/gadget/fusb300_udc.h
+++ b/drivers/usb/gadget/fusb300_udc.h
@@ -111,8 +111,8 @@
 /*
  * * EPn Setting 0 (EPn_SET0, offset = 020H+(n-1)*30H, n=1~15 )
  * */
+#define FUSB300_EPSET0_STL_CLR		(1 << 3)
 #define FUSB300_EPSET0_CLRSEQNUM	(1 << 2)
-#define FUSB300_EPSET0_EPn_TX0BYTE	(1 << 1)
 #define FUSB300_EPSET0_STL		(1 << 0)
 
 /*
diff --git a/drivers/usb/gadget/g_ffs.c b/drivers/usb/gadget/g_ffs.c
index 3b343b2..787a78e 100644
--- a/drivers/usb/gadget/g_ffs.c
+++ b/drivers/usb/gadget/g_ffs.c
@@ -13,7 +13,6 @@
 #define pr_fmt(fmt) "g_ffs: " fmt
 
 #include <linux/module.h>
-
 /*
  * kbuild is not very cooperative with respect to linking separately
  * compiled library objects into one module.  So for now we won't use
@@ -38,13 +37,16 @@
 #  include "u_ether.c"
 
 static u8 gfs_hostaddr[ETH_ALEN];
+static struct eth_dev *the_dev;
 #  ifdef CONFIG_USB_FUNCTIONFS_ETH
-static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]);
+static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
+		struct eth_dev *dev);
 #  endif
 #else
-#  define gether_cleanup() do { } while (0)
-#  define gether_setup(gadget, hostaddr)   ((int)0)
+#  define the_dev	NULL
+#  define gether_cleanup(dev) do { } while (0)
 #  define gfs_hostaddr NULL
+struct eth_dev;
 #endif
 
 #include "f_fs.c"
@@ -137,7 +139,8 @@ static struct usb_gadget_strings *gfs_dev_strings[] = {
 
 struct gfs_configuration {
 	struct usb_configuration c;
-	int (*eth)(struct usb_configuration *c, u8 *ethaddr);
+	int (*eth)(struct usb_configuration *c, u8 *ethaddr,
+			struct eth_dev *dev);
 } gfs_configurations[] = {
 #ifdef CONFIG_USB_FUNCTIONFS_RNDIS
 	{
@@ -346,10 +349,13 @@ static int gfs_bind(struct usb_composite_dev *cdev)
 
 	if (missing_funcs)
 		return -ENODEV;
-
-	ret = gether_setup(cdev->gadget, gfs_hostaddr);
-	if (unlikely(ret < 0))
+#if defined CONFIG_USB_FUNCTIONFS_ETH || defined CONFIG_USB_FUNCTIONFS_RNDIS
+	the_dev = gether_setup(cdev->gadget, gfs_hostaddr);
+#endif
+	if (IS_ERR(the_dev)) {
+		ret = PTR_ERR(the_dev);
 		goto error_quick;
+	}
 	gfs_ether_setup = true;
 
 	ret = usb_string_ids_tab(cdev, gfs_strings);
@@ -386,7 +392,7 @@ error_unbind:
 	for (i = 0; i < func_num; i++)
 		functionfs_unbind(ffs_tab[i].ffs_data);
 error:
-	gether_cleanup();
+	gether_cleanup(the_dev);
 error_quick:
 	gfs_ether_setup = false;
 	return ret;
@@ -410,7 +416,7 @@ static int gfs_unbind(struct usb_composite_dev *cdev)
 	 * do...?
 	 */
 	if (gfs_ether_setup)
-		gether_cleanup();
+		gether_cleanup(the_dev);
 	gfs_ether_setup = false;
 
 	for (i = func_num; i--; )
@@ -440,7 +446,7 @@ static int gfs_do_config(struct usb_configuration *c)
 	}
 
 	if (gc->eth) {
-		ret = gc->eth(c, gfs_hostaddr);
+		ret = gc->eth(c, gfs_hostaddr, the_dev);
 		if (unlikely(ret < 0))
 			return ret;
 	}
@@ -469,11 +475,12 @@ static int gfs_do_config(struct usb_configuration *c)
 
 #ifdef CONFIG_USB_FUNCTIONFS_ETH
 
-static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
+static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
+		struct eth_dev *dev)
 {
 	return can_support_ecm(c->cdev->gadget)
-		? ecm_bind_config(c, ethaddr)
-		: geth_bind_config(c, ethaddr);
+		? ecm_bind_config(c, ethaddr, dev)
+		: geth_bind_config(c, ethaddr, dev);
 }
 
 #endif
diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c
index 85742d4..991aba3 100644
--- a/drivers/usb/gadget/goku_udc.c
+++ b/drivers/usb/gadget/goku_udc.c
@@ -51,8 +51,6 @@
 #define	DRIVER_DESC		"TC86C001 USB Device Controller"
 #define	DRIVER_VERSION		"30-Oct 2003"
 
-#define	DMA_ADDR_INVALID	(~(dma_addr_t)0)
-
 static const char driver_name [] = "goku_udc";
 static const char driver_desc [] = DRIVER_DESC;
 
@@ -275,7 +273,6 @@ goku_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
 	if (!req)
 		return NULL;
 
-	req->req.dma = DMA_ADDR_INVALID;
 	INIT_LIST_HEAD(&req->queue);
 	return &req->req;
 }
@@ -1354,7 +1351,6 @@ static int goku_udc_start(struct usb_gadget *g,
 	/* hook up the driver */
 	driver->driver.bus = NULL;
 	dev->driver = driver;
-	dev->gadget.dev.driver = &driver->driver;
 
 	/*
 	 * then enable host detection and ep0; and we're ready
@@ -1394,7 +1390,6 @@ static int goku_udc_stop(struct usb_gadget *g,
 	dev->driver = NULL;
 	stop_activity(dev, driver);
 	spin_unlock_irqrestore(&dev->lock, flags);
-	dev->gadget.dev.driver = NULL;
 
 	return 0;
 }
@@ -1716,8 +1711,6 @@ static void goku_remove(struct pci_dev *pdev)
 				pci_resource_len (pdev, 0));
 	if (dev->enabled)
 		pci_disable_device(pdev);
-	if (dev->registered)
-		device_unregister(&dev->gadget.dev);
 
 	pci_set_drvdata(pdev, NULL);
 	dev->regs = NULL;
@@ -1756,10 +1749,6 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	dev->gadget.max_speed = USB_SPEED_FULL;
 
 	/* the "gadget" abstracts/virtualizes the controller */
-	dev_set_name(&dev->gadget.dev, "gadget");
-	dev->gadget.dev.parent = &pdev->dev;
-	dev->gadget.dev.dma_mask = pdev->dev.dma_mask;
-	dev->gadget.dev.release = gadget_release;
 	dev->gadget.name = driver_name;
 
 	/* now all the pci goodies ... */
@@ -1810,13 +1799,8 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	create_proc_read_entry(proc_node_name, 0, NULL, udc_proc_read, dev);
 #endif
 
-	retval = device_register(&dev->gadget.dev);
-	if (retval) {
-		put_device(&dev->gadget.dev);
-		goto err;
-	}
-	dev->registered = 1;
-	retval = usb_add_gadget_udc(&pdev->dev, &dev->gadget);
+	retval = usb_add_gadget_udc_release(&pdev->dev, &dev->gadget,
+			gadget_release);
 	if (retval)
 		goto err;
 
diff --git a/drivers/usb/gadget/goku_udc.h b/drivers/usb/gadget/goku_udc.h
index b4470d2..86d2ada 100644
--- a/drivers/usb/gadget/goku_udc.h
+++ b/drivers/usb/gadget/goku_udc.h
@@ -250,8 +250,7 @@ struct goku_udc {
 					got_region:1,
 					req_config:1,
 					configured:1,
-					enabled:1,
-					registered:1;
+					enabled:1;
 
 	/* pci state used to access those endpoints */
 	struct pci_dev			*pdev;
diff --git a/drivers/usb/gadget/imx_udc.c b/drivers/usb/gadget/imx_udc.c
index 5bd930d..b5cebd6 100644
--- a/drivers/usb/gadget/imx_udc.c
+++ b/drivers/usb/gadget/imx_udc.c
@@ -1338,7 +1338,6 @@ static int imx_udc_start(struct usb_gadget *gadget,
 	imx_usb = container_of(gadget, struct imx_udc_struct, gadget);
 	/* first hook up the driver ... */
 	imx_usb->driver = driver;
-	imx_usb->gadget.dev.driver = &driver->driver;
 
 	D_INI(imx_usb->dev, "<%s> registered gadget driver '%s'\n",
 		__func__, driver->driver.name);
@@ -1358,7 +1357,6 @@ static int imx_udc_stop(struct usb_gadget *gadget,
 	imx_udc_disable(imx_usb);
 	del_timer(&imx_usb->timer);
 
-	imx_usb->gadget.dev.driver = NULL;
 	imx_usb->driver = NULL;
 
 	D_INI(imx_usb->dev, "<%s> unregistered gadget driver '%s'\n",
@@ -1461,15 +1459,6 @@ static int __init imx_udc_probe(struct platform_device *pdev)
 	imx_usb->clk = clk;
 	imx_usb->dev = &pdev->dev;
 
-	device_initialize(&imx_usb->gadget.dev);
-
-	imx_usb->gadget.dev.parent = &pdev->dev;
-	imx_usb->gadget.dev.dma_mask = pdev->dev.dma_mask;
-
-	ret = device_add(&imx_usb->gadget.dev);
-	if (retval)
-		goto fail4;
-
 	platform_set_drvdata(pdev, imx_usb);
 
 	usb_init_data(imx_usb);
@@ -1481,11 +1470,9 @@ static int __init imx_udc_probe(struct platform_device *pdev)
 
 	ret = usb_add_gadget_udc(&pdev->dev, &imx_usb->gadget);
 	if (ret)
-		goto fail5;
+		goto fail4;
 
 	return 0;
-fail5:
-	device_unregister(&imx_usb->gadget.dev);
 fail4:
 	for (i = 0; i < IMX_USB_NB_EP + 1; i++)
 		free_irq(imx_usb->usbd_int[i], imx_usb);
@@ -1509,7 +1496,6 @@ static int __exit imx_udc_remove(struct platform_device *pdev)
 	int i;
 
 	usb_del_gadget_udc(&imx_usb->gadget);
-	device_unregister(&imx_usb->gadget.dev);
 	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 e2b2e9c..570c005 100644
--- a/drivers/usb/gadget/inode.c
+++ b/drivers/usb/gadget/inode.c
@@ -24,6 +24,8 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/poll.h>
+#include <linux/mmu_context.h>
+#include <linux/aio.h>
 
 #include <linux/device.h>
 #include <linux/moduleparam.h>
@@ -513,6 +515,9 @@ static long ep_ioctl(struct file *fd, unsigned code, unsigned long value)
 struct kiocb_priv {
 	struct usb_request	*req;
 	struct ep_data		*epdata;
+	struct kiocb		*iocb;
+	struct mm_struct	*mm;
+	struct work_struct	work;
 	void			*buf;
 	const struct iovec	*iv;
 	unsigned long		nr_segs;
@@ -528,7 +533,6 @@ static int ep_aio_cancel(struct kiocb *iocb, struct io_event *e)
 	local_irq_disable();
 	epdata = priv->epdata;
 	// spin_lock(&epdata->dev->lock);
-	kiocbSetCancelled(iocb);
 	if (likely(epdata && epdata->ep && priv->req))
 		value = usb_ep_dequeue (epdata->ep, priv->req);
 	else
@@ -540,15 +544,12 @@ static int ep_aio_cancel(struct kiocb *iocb, struct io_event *e)
 	return value;
 }
 
-static ssize_t ep_aio_read_retry(struct kiocb *iocb)
+static ssize_t ep_copy_to_user(struct kiocb_priv *priv)
 {
-	struct kiocb_priv	*priv = iocb->private;
 	ssize_t			len, total;
 	void			*to_copy;
 	int			i;
 
-	/* we "retry" to get the right mm context for this: */
-
 	/* copy stuff into user buffers */
 	total = priv->actual;
 	len = 0;
@@ -568,9 +569,26 @@ static ssize_t ep_aio_read_retry(struct kiocb *iocb)
 		if (total == 0)
 			break;
 	}
+
+	return len;
+}
+
+static void ep_user_copy_worker(struct work_struct *work)
+{
+	struct kiocb_priv *priv = container_of(work, struct kiocb_priv, work);
+	struct mm_struct *mm = priv->mm;
+	struct kiocb *iocb = priv->iocb;
+	size_t ret;
+
+	use_mm(mm);
+	ret = ep_copy_to_user(priv);
+	unuse_mm(mm);
+
+	/* completing the iocb can drop the ctx and mm, don't touch mm after */
+	aio_complete(iocb, ret, ret);
+
 	kfree(priv->buf);
 	kfree(priv);
-	return len;
 }
 
 static void ep_aio_complete(struct usb_ep *ep, struct usb_request *req)
@@ -596,14 +614,14 @@ static void ep_aio_complete(struct usb_ep *ep, struct usb_request *req)
 		aio_complete(iocb, req->actual ? req->actual : req->status,
 				req->status);
 	} else {
-		/* retry() won't report both; so we hide some faults */
+		/* ep_copy_to_user() won't report both; we hide some faults */
 		if (unlikely(0 != req->status))
 			DBG(epdata->dev, "%s fault %d len %d\n",
 				ep->name, req->status, req->actual);
 
 		priv->buf = req->buf;
 		priv->actual = req->actual;
-		kick_iocb(iocb);
+		schedule_work(&priv->work);
 	}
 	spin_unlock(&epdata->dev->lock);
 
@@ -633,8 +651,10 @@ fail:
 		return value;
 	}
 	iocb->private = priv;
+	priv->iocb = iocb;
 	priv->iv = iv;
 	priv->nr_segs = nr_segs;
+	INIT_WORK(&priv->work, ep_user_copy_worker);
 
 	value = get_ready_ep(iocb->ki_filp->f_flags, epdata);
 	if (unlikely(value < 0)) {
@@ -642,10 +662,11 @@ fail:
 		goto fail;
 	}
 
-	iocb->ki_cancel = ep_aio_cancel;
+	kiocb_set_cancel_fn(iocb, ep_aio_cancel);
 	get_ep(epdata);
 	priv->epdata = epdata;
 	priv->actual = 0;
+	priv->mm = current->mm; /* mm teardown waits for iocbs in exit_aio() */
 
 	/* each kiocb is coupled to one usb_request, but we can't
 	 * allocate or submit those if the host disconnected.
@@ -674,7 +695,7 @@ fail:
 		kfree(priv);
 		put_ep(epdata);
 	} else
-		value = (iv ? -EIOCBRETRY : -EIOCBQUEUED);
+		value = -EIOCBQUEUED;
 	return value;
 }
 
@@ -692,7 +713,6 @@ ep_aio_read(struct kiocb *iocb, const struct iovec *iov,
 	if (unlikely(!buf))
 		return -ENOMEM;
 
-	iocb->ki_retry = ep_aio_read_retry;
 	return ep_aio_rwtail(iocb, buf, iocb->ki_left, epdata, iov, nr_segs);
 }
 
@@ -887,7 +907,6 @@ ep_open (struct inode *inode, struct file *fd)
 
 /* used before endpoint configuration */
 static const struct file_operations ep_config_operations = {
-	.owner =	THIS_MODULE,
 	.llseek =	no_llseek,
 
 	.open =		ep_open,
@@ -1940,7 +1959,6 @@ dev_open (struct inode *inode, struct file *fd)
 }
 
 static const struct file_operations dev_init_operations = {
-	.owner =	THIS_MODULE,
 	.llseek =	no_llseek,
 
 	.open =		dev_open,
diff --git a/drivers/usb/gadget/lpc32xx_udc.c b/drivers/usb/gadget/lpc32xx_udc.c
index aa04089..67128be 100644
--- a/drivers/usb/gadget/lpc32xx_udc.c
+++ b/drivers/usb/gadget/lpc32xx_udc.c
@@ -565,7 +565,7 @@ static int proc_udc_show(struct seq_file *s, void *unused)
 
 static int proc_udc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, proc_udc_show, PDE(inode)->data);
+	return single_open(file, proc_udc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations proc_ops = {
@@ -1469,23 +1469,7 @@ static void done(struct lpc32xx_ep *ep, struct lpc32xx_request *req, int status)
 		status = req->req.status;
 
 	if (ep->lep) {
-		enum dma_data_direction direction;
-
-		if (ep->is_in)
-			direction = DMA_TO_DEVICE;
-		else
-			direction = DMA_FROM_DEVICE;
-
-		if (req->mapped) {
-			dma_unmap_single(ep->udc->gadget.dev.parent,
-					req->req.dma, req->req.length,
-					direction);
-			req->req.dma = 0;
-			req->mapped = 0;
-		} else
-			dma_sync_single_for_cpu(ep->udc->gadget.dev.parent,
-						req->req.dma, req->req.length,
-						direction);
+		usb_gadget_unmap_request(&udc->gadget, &req->req, ep->is_in);
 
 		/* Free DDs */
 		udc_dd_free(udc, req->dd_desc_ptr);
@@ -1841,26 +1825,11 @@ static int lpc32xx_ep_queue(struct usb_ep *_ep,
 	}
 
 	if (ep->lep) {
-		enum dma_data_direction direction;
 		struct lpc32xx_usbd_dd_gad *dd;
 
-		/* Map DMA pointer */
-		if (ep->is_in)
-			direction = DMA_TO_DEVICE;
-		else
-			direction = DMA_FROM_DEVICE;
-
-		if (req->req.dma == 0) {
-			req->req.dma = dma_map_single(
-				ep->udc->gadget.dev.parent,
-				req->req.buf, req->req.length, direction);
-			req->mapped = 1;
-		} else {
-			dma_sync_single_for_device(
-				ep->udc->gadget.dev.parent, req->req.dma,
-				req->req.length, direction);
-			req->mapped = 0;
-		}
+		status = usb_gadget_map_request(&udc->gadget, _req, ep->is_in);
+		if (status)
+			return status;
 
 		/* For the request, build a list of DDs */
 		dd = udc_dd_alloc(udc);
@@ -2977,7 +2946,6 @@ static int lpc32xx_start(struct usb_gadget *gadget,
 	}
 
 	udc->driver = driver;
-	udc->gadget.dev.driver = &driver->driver;
 	udc->gadget.dev.of_node = udc->dev->of_node;
 	udc->enabled = 1;
 	udc->selfpowered = 1;
@@ -3026,7 +2994,6 @@ static int lpc32xx_stop(struct usb_gadget *gadget,
 	}
 
 	udc->enabled = 0;
-	udc->gadget.dev.driver = NULL;
 	udc->driver = NULL;
 
 	return 0;
@@ -3248,12 +3215,6 @@ static int __init lpc32xx_udc_probe(struct platform_device *pdev)
 	udc_disable(udc);
 	udc_reinit(udc);
 
-	retval = device_register(&udc->gadget.dev);
-	if (retval < 0) {
-		dev_err(udc->dev, "Device registration failure\n");
-		goto dev_register_fail;
-	}
-
 	/* Request IRQs - low and high priority USB device IRQs are routed to
 	 * the same handler, while the DMA interrupt is routed elsewhere */
 	retval = request_irq(udc->udp_irq[IRQ_USB_LP], lpc32xx_usb_lp_irq,
@@ -3320,8 +3281,6 @@ irq_dev_fail:
 irq_hp_fail:
 	free_irq(udc->udp_irq[IRQ_USB_LP], udc);
 irq_lp_fail:
-	device_unregister(&udc->gadget.dev);
-dev_register_fail:
 	dma_pool_destroy(udc->dd_cache);
 dma_alloc_fail:
 	dma_free_coherent(&pdev->dev, UDCA_BUFF_SIZE,
@@ -3376,8 +3335,6 @@ static int lpc32xx_udc_remove(struct platform_device *pdev)
 	free_irq(udc->udp_irq[IRQ_USB_HP], udc);
 	free_irq(udc->udp_irq[IRQ_USB_LP], udc);
 
-	device_unregister(&udc->gadget.dev);
-
 	clk_disable(udc->usb_otg_clk);
 	clk_put(udc->usb_otg_clk);
 	clk_disable(udc->usb_slv_clk);
diff --git a/drivers/usb/gadget/m66592-udc.c b/drivers/usb/gadget/m66592-udc.c
index c1b8c2d..866ef09 100644
--- a/drivers/usb/gadget/m66592-udc.c
+++ b/drivers/usb/gadget/m66592-udc.c
@@ -1471,7 +1471,6 @@ static int m66592_udc_start(struct usb_gadget *g,
 	/* hook up the driver */
 	driver->driver.bus = NULL;
 	m66592->driver = driver;
-	m66592->gadget.dev.driver = &driver->driver;
 
 	m66592_bset(m66592, M66592_VBSE | M66592_URST, M66592_INTENB0);
 	if (m66592_read(m66592, M66592_INTSTS0) & M66592_VBSTS) {
@@ -1494,7 +1493,6 @@ static int m66592_udc_stop(struct usb_gadget *g,
 	m66592_bclr(m66592, M66592_VBSE | M66592_URST, M66592_INTENB0);
 
 	driver->unbind(&m66592->gadget);
-	m66592->gadget.dev.driver = NULL;
 
 	init_controller(m66592);
 	disable_controller(m66592);
@@ -1538,7 +1536,6 @@ static int __exit m66592_remove(struct platform_device *pdev)
 	struct m66592		*m66592 = dev_get_drvdata(&pdev->dev);
 
 	usb_del_gadget_udc(&m66592->gadget);
-	device_del(&m66592->gadget.dev);
 
 	del_timer_sync(&m66592->timer);
 	iounmap(m66592->reg);
@@ -1608,12 +1605,7 @@ static int __init m66592_probe(struct platform_device *pdev)
 	dev_set_drvdata(&pdev->dev, m66592);
 
 	m66592->gadget.ops = &m66592_gadget_ops;
-	device_initialize(&m66592->gadget.dev);
-	dev_set_name(&m66592->gadget.dev, "gadget");
 	m66592->gadget.max_speed = USB_SPEED_HIGH;
-	m66592->gadget.dev.parent = &pdev->dev;
-	m66592->gadget.dev.dma_mask = pdev->dev.dma_mask;
-	m66592->gadget.dev.release = pdev->dev.release;
 	m66592->gadget.name = udc_name;
 
 	init_timer(&m66592->timer);
@@ -1674,12 +1666,6 @@ static int __init m66592_probe(struct platform_device *pdev)
 
 	init_controller(m66592);
 
-	ret = device_add(&m66592->gadget.dev);
-	if (ret) {
-		pr_err("device_add error (%d)\n", ret);
-		goto err_device_add;
-	}
-
 	ret = usb_add_gadget_udc(&pdev->dev, &m66592->gadget);
 	if (ret)
 		goto err_add_udc;
@@ -1688,9 +1674,6 @@ static int __init m66592_probe(struct platform_device *pdev)
 	return 0;
 
 err_add_udc:
-	device_del(&m66592->gadget.dev);
-
-err_device_add:
 	m66592_free_request(&m66592->ep[0].ep, m66592->ep0_req);
 
 clean_up3:
diff --git a/drivers/usb/gadget/multi.c b/drivers/usb/gadget/multi.c
index 20bbbf9..a74ebef 100644
--- a/drivers/usb/gadget/multi.c
+++ b/drivers/usb/gadget/multi.c
@@ -135,8 +135,8 @@ static struct fsg_common fsg_common;
 
 static u8 hostaddr[ETH_ALEN];
 
-static unsigned char tty_line;
 static struct usb_function_instance *fi_acm;
+static struct eth_dev *the_dev;
 
 /********** RNDIS **********/
 
@@ -152,7 +152,7 @@ static __init int rndis_do_config(struct usb_configuration *c)
 		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 	}
 
-	ret = rndis_bind_config(c, hostaddr);
+	ret = rndis_bind_config(c, hostaddr, the_dev);
 	if (ret < 0)
 		return ret;
 
@@ -214,7 +214,7 @@ static __init int cdc_do_config(struct usb_configuration *c)
 		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 	}
 
-	ret = ecm_bind_config(c, hostaddr);
+	ret = ecm_bind_config(c, hostaddr, the_dev);
 	if (ret < 0)
 		return ret;
 
@@ -269,7 +269,6 @@ static int cdc_config_register(struct usb_composite_dev *cdev)
 static int __ref multi_bind(struct usb_composite_dev *cdev)
 {
 	struct usb_gadget *gadget = cdev->gadget;
-	struct f_serial_opts *opts;
 	int status;
 
 	if (!can_support_ecm(cdev->gadget)) {
@@ -279,24 +278,17 @@ static int __ref multi_bind(struct usb_composite_dev *cdev)
 	}
 
 	/* set up network link layer */
-	status = gether_setup(cdev->gadget, hostaddr);
-	if (status < 0)
-		return status;
+	the_dev = gether_setup(cdev->gadget, hostaddr);
+	if (IS_ERR(the_dev))
+		return PTR_ERR(the_dev);
 
 	/* set up serial link layer */
-	status = gserial_alloc_line(&tty_line);
-	if (status < 0)
-		goto fail0;
-
 	fi_acm = usb_get_function_instance("acm");
 	if (IS_ERR(fi_acm)) {
 		status = PTR_ERR(fi_acm);
-		goto fail0dot5;
+		goto fail0;
 	}
 
-	opts = container_of(fi_acm, struct f_serial_opts, func_inst);
-	opts->port_num = tty_line;
-
 	/* set up mass storage function */
 	{
 		void *retp;
@@ -334,10 +326,8 @@ fail2:
 	fsg_common_put(&fsg_common);
 fail1:
 	usb_put_function_instance(fi_acm);
-fail0dot5:
-	gserial_free_line(tty_line);
 fail0:
-	gether_cleanup();
+	gether_cleanup(the_dev);
 	return status;
 }
 
@@ -350,8 +340,7 @@ static int __exit multi_unbind(struct usb_composite_dev *cdev)
 	usb_put_function(f_acm_rndis);
 #endif
 	usb_put_function_instance(fi_acm);
-	gserial_free_line(tty_line);
-	gether_cleanup();
+	gether_cleanup(the_dev);
 	return 0;
 }
 
diff --git a/drivers/usb/gadget/mv_u3d_core.c b/drivers/usb/gadget/mv_u3d_core.c
index b5cea27..58288e9 100644
--- a/drivers/usb/gadget/mv_u3d_core.c
+++ b/drivers/usb/gadget/mv_u3d_core.c
@@ -30,9 +30,6 @@
 #include <linux/platform_device.h>
 #include <linux/platform_data/mv_usb.h>
 #include <linux/clk.h>
-#include <asm/system.h>
-#include <asm/unaligned.h>
-#include <asm/byteorder.h>
 
 #include "mv_u3d.h"
 
@@ -125,7 +122,7 @@ static int mv_u3d_process_ep_req(struct mv_u3d *u3d, int index,
 	struct mv_u3d_trb	*curr_trb;
 	dma_addr_t cur_deq_lo;
 	struct mv_u3d_ep_context	*curr_ep_context;
-	int trb_complete, actual, remaining_length;
+	int trb_complete, actual, remaining_length = 0;
 	int direction, ep_num;
 	int retval = 0;
 	u32 tmp, status, length;
@@ -189,6 +186,8 @@ static int mv_u3d_process_ep_req(struct mv_u3d *u3d, int index,
  */
 static
 void mv_u3d_done(struct mv_u3d_ep *ep, struct mv_u3d_req *req, int status)
+	__releases(&ep->udc->lock)
+	__acquires(&ep->udc->lock)
 {
 	struct mv_u3d *u3d = (struct mv_u3d *)ep->u3d;
 
@@ -812,19 +811,19 @@ mv_u3d_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 		return 0;
 	}
 
-	dev_dbg(u3d->dev, "%s: %s, req: 0x%x\n",
-			__func__, _ep->name, (u32)req);
+	dev_dbg(u3d->dev, "%s: %s, req: 0x%p\n",
+			__func__, _ep->name, req);
 
 	/* catch various bogus parameters */
 	if (!req->req.complete || !req->req.buf
 			|| !list_empty(&req->queue)) {
 		dev_err(u3d->dev,
-			"%s, bad params, _req: 0x%x,"
-			"req->req.complete: 0x%x, req->req.buf: 0x%x,"
+			"%s, bad params, _req: 0x%p,"
+			"req->req.complete: 0x%p, req->req.buf: 0x%p,"
 			"list_empty: 0x%x\n",
-			__func__, (u32)_req,
-			(u32)req->req.complete, (u32)req->req.buf,
-			(u32)list_empty(&req->queue));
+			__func__, _req,
+			req->req.complete, req->req.buf,
+			list_empty(&req->queue));
 		return -EINVAL;
 	}
 	if (unlikely(!ep->ep.desc)) {
@@ -905,7 +904,7 @@ static int mv_u3d_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
 					struct mv_u3d_req, queue);
 
 			/* Point first TRB of next request to the EP context. */
-			iowrite32((u32) next_req->trb_head,
+			iowrite32((unsigned long) next_req->trb_head,
 					&ep_context->trb_addr_lo);
 		} else {
 			struct mv_u3d_ep_context *ep_context;
@@ -1264,7 +1263,6 @@ static int mv_u3d_start(struct usb_gadget *g,
 	/* hook up the driver ... */
 	driver->driver.bus = NULL;
 	u3d->driver = driver;
-	u3d->gadget.dev.driver = &driver->driver;
 
 	u3d->ep0_dir = USB_DIR_OUT;
 
@@ -1302,7 +1300,6 @@ static int mv_u3d_stop(struct usb_gadget *g,
 
 	spin_unlock_irqrestore(&u3d->lock, flags);
 
-	u3d->gadget.dev.driver = NULL;
 	u3d->driver = NULL;
 
 	return 0;
@@ -1525,6 +1522,8 @@ static int mv_u3d_is_set_configuration(struct usb_ctrlrequest *setup)
 
 static void mv_u3d_handle_setup_packet(struct mv_u3d *u3d, u8 ep_num,
 	struct usb_ctrlrequest *setup)
+	__releases(&u3c->lock)
+	__acquires(&u3c->lock)
 {
 	bool delegate = false;
 
@@ -1758,11 +1757,6 @@ static irqreturn_t mv_u3d_irq(int irq, void *dev)
 	return IRQ_HANDLED;
 }
 
-static void mv_u3d_gadget_release(struct device *dev)
-{
-	dev_dbg(dev, "%s\n", __func__);
-}
-
 static int mv_u3d_remove(struct platform_device *dev)
 {
 	struct mv_u3d *u3d = platform_get_drvdata(dev);
@@ -1792,8 +1786,6 @@ static int mv_u3d_remove(struct platform_device *dev)
 
 	clk_put(u3d->clk);
 
-	device_unregister(&u3d->gadget.dev);
-
 	platform_set_drvdata(dev, NULL);
 
 	kfree(u3d);
@@ -1829,7 +1821,7 @@ static int mv_u3d_probe(struct platform_device *dev)
 	u3d->dev = &dev->dev;
 	u3d->vbus = pdata->vbus;
 
-	u3d->clk = clk_get(&dev->dev, pdata->clkname[0]);
+	u3d->clk = clk_get(&dev->dev, NULL);
 	if (IS_ERR(u3d->clk)) {
 		retval = PTR_ERR(u3d->clk);
 		goto err_get_clk;
@@ -1849,8 +1841,9 @@ static int mv_u3d_probe(struct platform_device *dev)
 		retval = -EBUSY;
 		goto err_map_cap_regs;
 	} else {
-		dev_dbg(&dev->dev, "cap_regs address: 0x%x/0x%x\n",
-			(unsigned int)r->start, (unsigned int)u3d->cap_regs);
+		dev_dbg(&dev->dev, "cap_regs address: 0x%lx/0x%lx\n",
+			(unsigned long) r->start,
+			(unsigned long) u3d->cap_regs);
 	}
 
 	/* we will access controller register, so enable the u3d controller */
@@ -1864,10 +1857,10 @@ static int mv_u3d_probe(struct platform_device *dev)
 		}
 	}
 
-	u3d->op_regs = (struct mv_u3d_op_regs __iomem *)((u32)u3d->cap_regs
+	u3d->op_regs = (struct mv_u3d_op_regs __iomem *)(u3d->cap_regs
 		+ MV_U3D_USB3_OP_REGS_OFFSET);
 
-	u3d->vuc_regs = (struct mv_u3d_vuc_regs __iomem *)((u32)u3d->cap_regs
+	u3d->vuc_regs = (struct mv_u3d_vuc_regs __iomem *)(u3d->cap_regs
 		+ ioread32(&u3d->cap_regs->vuoff));
 
 	u3d->max_eps = 16;
@@ -1957,16 +1950,8 @@ static int mv_u3d_probe(struct platform_device *dev)
 	u3d->gadget.speed = USB_SPEED_UNKNOWN;	/* speed */
 
 	/* the "gadget" abstracts/virtualizes the controller */
-	dev_set_name(&u3d->gadget.dev, "gadget");
-	u3d->gadget.dev.parent = &dev->dev;
-	u3d->gadget.dev.dma_mask = dev->dev.dma_mask;
-	u3d->gadget.dev.release = mv_u3d_gadget_release;
 	u3d->gadget.name = driver_name;		/* gadget name */
 
-	retval = device_register(&u3d->gadget.dev);
-	if (retval)
-		goto err_register_gadget_device;
-
 	mv_u3d_eps_init(u3d);
 
 	/* external vbus detection */
@@ -1991,8 +1976,6 @@ static int mv_u3d_probe(struct platform_device *dev)
 	return 0;
 
 err_unregister:
-	device_unregister(&u3d->gadget.dev);
-err_register_gadget_device:
 	free_irq(u3d->irq, &dev->dev);
 err_request_irq:
 err_get_irq:
@@ -2021,7 +2004,7 @@ err_pdata:
 	return retval;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int mv_u3d_suspend(struct device *dev)
 {
 	struct mv_u3d *u3d = dev_get_drvdata(dev);
@@ -2064,10 +2047,10 @@ static int mv_u3d_resume(struct device *dev)
 
 	return 0;
 }
-
-SIMPLE_DEV_PM_OPS(mv_u3d_pm_ops, mv_u3d_suspend, mv_u3d_resume);
 #endif
 
+static SIMPLE_DEV_PM_OPS(mv_u3d_pm_ops, mv_u3d_suspend, mv_u3d_resume);
+
 static void mv_u3d_shutdown(struct platform_device *dev)
 {
 	struct mv_u3d *u3d = dev_get_drvdata(&dev->dev);
@@ -2080,14 +2063,12 @@ static void mv_u3d_shutdown(struct platform_device *dev)
 
 static struct platform_driver mv_u3d_driver = {
 	.probe		= mv_u3d_probe,
-	.remove		= __exit_p(mv_u3d_remove),
+	.remove		= mv_u3d_remove,
 	.shutdown	= mv_u3d_shutdown,
 	.driver		= {
 		.owner	= THIS_MODULE,
 		.name	= "mv-u3d",
-#ifdef CONFIG_PM
 		.pm	= &mv_u3d_pm_ops,
-#endif
 	},
 };
 
diff --git a/drivers/usb/gadget/mv_udc.h b/drivers/usb/gadget/mv_udc.h
index 9073436..be77f20 100644
--- a/drivers/usb/gadget/mv_udc.h
+++ b/drivers/usb/gadget/mv_udc.h
@@ -222,8 +222,7 @@ struct mv_udc {
 	struct mv_usb_platform_data     *pdata;
 
 	/* some SOC has mutiple clock sources for USB*/
-	unsigned int    clknum;
-	struct clk      *clk[0];
+	struct clk      *clk;
 };
 
 /* endpoint data structure */
diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c
index c8cf959..c2a5702 100644
--- a/drivers/usb/gadget/mv_udc_core.c
+++ b/drivers/usb/gadget/mv_udc_core.c
@@ -212,6 +212,8 @@ static int process_ep_req(struct mv_udc *udc, int index,
  * request is still in progress.
  */
 static void done(struct mv_ep *ep, struct mv_req *req, int status)
+	__releases(&ep->udc->lock)
+	__acquires(&ep->udc->lock)
 {
 	struct mv_udc *udc = NULL;
 	unsigned char stopped = ep->stopped;
@@ -237,18 +239,7 @@ static void done(struct mv_ep *ep, struct mv_req *req, int status)
 		dma_pool_free(udc->dtd_pool, curr_td, curr_td->td_dma);
 	}
 
-	if (req->mapped) {
-		dma_unmap_single(ep->udc->gadget.dev.parent,
-			req->req.dma, req->req.length,
-			((ep_dir(ep) == EP_DIR_IN) ?
-				DMA_TO_DEVICE : DMA_FROM_DEVICE));
-		req->req.dma = DMA_ADDR_INVALID;
-		req->mapped = 0;
-	} else
-		dma_sync_single_for_cpu(ep->udc->gadget.dev.parent,
-			req->req.dma, req->req.length,
-			((ep_dir(ep) == EP_DIR_IN) ?
-				DMA_TO_DEVICE : DMA_FROM_DEVICE));
+	usb_gadget_unmap_request(&udc->gadget, &req->req, ep_dir(ep));
 
 	if (status && (status != -ESHUTDOWN))
 		dev_info(&udc->dev->dev, "complete %s req %p stat %d len %u/%u",
@@ -732,21 +723,9 @@ mv_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 	req->ep = ep;
 
 	/* map virtual address to hardware */
-	if (req->req.dma == DMA_ADDR_INVALID) {
-		req->req.dma = dma_map_single(ep->udc->gadget.dev.parent,
-					req->req.buf,
-					req->req.length, ep_dir(ep)
-						? DMA_TO_DEVICE
-						: DMA_FROM_DEVICE);
-		req->mapped = 1;
-	} else {
-		dma_sync_single_for_device(ep->udc->gadget.dev.parent,
-					req->req.dma, req->req.length,
-					ep_dir(ep)
-						? DMA_TO_DEVICE
-						: DMA_FROM_DEVICE);
-		req->mapped = 0;
-	}
+	retval = usb_gadget_map_request(&udc->gadget, _req, ep_dir(ep));
+	if (retval)
+		return retval;
 
 	req->req.status = -EINPROGRESS;
 	req->req.actual = 0;
@@ -780,18 +759,7 @@ mv_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 	return 0;
 
 err_unmap_dma:
-	if (req->mapped) {
-		dma_unmap_single(ep->udc->gadget.dev.parent,
-				req->req.dma, req->req.length,
-				((ep_dir(ep) == EP_DIR_IN) ?
-				DMA_TO_DEVICE : DMA_FROM_DEVICE));
-		req->req.dma = DMA_ADDR_INVALID;
-		req->mapped = 0;
-	} else
-		dma_sync_single_for_cpu(ep->udc->gadget.dev.parent,
-				req->req.dma, req->req.length,
-				((ep_dir(ep) == EP_DIR_IN) ?
-				DMA_TO_DEVICE : DMA_FROM_DEVICE));
+	usb_gadget_unmap_request(&udc->gadget, _req, ep_dir(ep));
 
 	return retval;
 }
@@ -1006,18 +974,12 @@ static struct usb_ep_ops mv_ep_ops = {
 
 static void udc_clock_enable(struct mv_udc *udc)
 {
-	unsigned int i;
-
-	for (i = 0; i < udc->clknum; i++)
-		clk_prepare_enable(udc->clk[i]);
+	clk_prepare_enable(udc->clk);
 }
 
 static void udc_clock_disable(struct mv_udc *udc)
 {
-	unsigned int i;
-
-	for (i = 0; i < udc->clknum; i++)
-		clk_disable_unprepare(udc->clk[i]);
+	clk_disable_unprepare(udc->clk);
 }
 
 static void udc_stop(struct mv_udc *udc)
@@ -1386,7 +1348,6 @@ static int mv_udc_start(struct usb_gadget *gadget,
 	/* hook up the driver ... */
 	driver->driver.bus = NULL;
 	udc->driver = driver;
-	udc->gadget.dev.driver = &driver->driver;
 
 	udc->usb_state = USB_STATE_ATTACHED;
 	udc->ep0_state = WAIT_FOR_SETUP;
@@ -1401,7 +1362,6 @@ static int mv_udc_start(struct usb_gadget *gadget,
 			dev_err(&udc->dev->dev,
 				"unable to register peripheral to otg\n");
 			udc->driver = NULL;
-			udc->gadget.dev.driver = NULL;
 			return retval;
 		}
 	}
@@ -1437,7 +1397,6 @@ static int mv_udc_stop(struct usb_gadget *gadget,
 	spin_unlock_irqrestore(&udc->lock, flags);
 
 	/* unbind gadget driver */
-	udc->gadget.dev.driver = NULL;
 	udc->driver = NULL;
 
 	return 0;
@@ -1528,14 +1487,7 @@ udc_prime_status(struct mv_udc *udc, u8 direction, u16 status, bool empty)
 
 	return 0;
 out:
-	if (req->mapped) {
-		dma_unmap_single(ep->udc->gadget.dev.parent,
-				req->req.dma, req->req.length,
-				((ep_dir(ep) == EP_DIR_IN) ?
-				DMA_TO_DEVICE : DMA_FROM_DEVICE));
-		req->req.dma = DMA_ADDR_INVALID;
-		req->mapped = 0;
-	}
+	usb_gadget_unmap_request(&udc->gadget, &req->req, ep_dir(ep));
 
 	return retval;
 }
@@ -1695,6 +1647,8 @@ out:
 
 static void handle_setup_packet(struct mv_udc *udc, u8 ep_num,
 	struct usb_ctrlrequest *setup)
+	__releases(&ep->udc->lock)
+	__acquires(&ep->udc->lock)
 {
 	bool delegate = false;
 
@@ -1891,7 +1845,7 @@ static void irq_process_tr_complete(struct mv_udc *udc)
 	}
 }
 
-void irq_process_reset(struct mv_udc *udc)
+static void irq_process_reset(struct mv_udc *udc)
 {
 	u32 tmp;
 	unsigned int loops;
@@ -2138,8 +2092,6 @@ static int mv_udc_remove(struct platform_device *pdev)
 
 	mv_udc_disable(udc);
 
-	device_unregister(&udc->gadget.dev);
-
 	/* free dev, wait for the release() finished */
 	wait_for_completion(udc->done);
 
@@ -2151,7 +2103,6 @@ static int mv_udc_probe(struct platform_device *pdev)
 	struct mv_usb_platform_data *pdata = pdev->dev.platform_data;
 	struct mv_udc *udc;
 	int retval = 0;
-	int clk_i = 0;
 	struct resource *r;
 	size_t size;
 
@@ -2160,8 +2111,7 @@ static int mv_udc_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
-	size = sizeof(*udc) + sizeof(struct clk *) * pdata->clknum;
-	udc = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
+	udc = devm_kzalloc(&pdev->dev, sizeof(*udc), GFP_KERNEL);
 	if (udc == NULL) {
 		dev_err(&pdev->dev, "failed to allocate memory for udc\n");
 		return -ENOMEM;
@@ -2173,26 +2123,24 @@ static int mv_udc_probe(struct platform_device *pdev)
 
 	udc->dev = pdev;
 
-#ifdef CONFIG_USB_OTG_UTILS
 	if (pdata->mode == MV_USB_MODE_OTG) {
 		udc->transceiver = devm_usb_get_phy(&pdev->dev,
 					USB_PHY_TYPE_USB2);
-		if (IS_ERR_OR_NULL(udc->transceiver)) {
+		if (IS_ERR(udc->transceiver)) {
+			retval = PTR_ERR(udc->transceiver);
+
+			if (retval == -ENXIO)
+				return retval;
+
 			udc->transceiver = NULL;
-			return -ENODEV;
+			return -EPROBE_DEFER;
 		}
 	}
-#endif
 
-	udc->clknum = pdata->clknum;
-	for (clk_i = 0; clk_i < udc->clknum; clk_i++) {
-		udc->clk[clk_i] = devm_clk_get(&pdev->dev,
-					pdata->clkname[clk_i]);
-		if (IS_ERR(udc->clk[clk_i])) {
-			retval = PTR_ERR(udc->clk[clk_i]);
-			return retval;
-		}
-	}
+	/* udc only have one sysclk. */
+	udc->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(udc->clk))
+		return PTR_ERR(udc->clk);
 
 	r = platform_get_resource_byname(udc->dev, IORESOURCE_MEM, "capregs");
 	if (r == NULL) {
@@ -2311,16 +2259,8 @@ static int mv_udc_probe(struct platform_device *pdev)
 	udc->gadget.max_speed = USB_SPEED_HIGH;	/* support dual speed */
 
 	/* the "gadget" abstracts/virtualizes the controller */
-	dev_set_name(&udc->gadget.dev, "gadget");
-	udc->gadget.dev.parent = &pdev->dev;
-	udc->gadget.dev.dma_mask = pdev->dev.dma_mask;
-	udc->gadget.dev.release = gadget_release;
 	udc->gadget.name = driver_name;		/* gadget name */
 
-	retval = device_register(&udc->gadget.dev);
-	if (retval)
-		goto err_destroy_dma;
-
 	eps_init(udc);
 
 	/* VBUS detect: we can disable/enable clock on demand.*/
@@ -2342,7 +2282,7 @@ static int mv_udc_probe(struct platform_device *pdev)
 		if (!udc->qwork) {
 			dev_err(&pdev->dev, "cannot create workqueue\n");
 			retval = -ENOMEM;
-			goto err_unregister;
+			goto err_destroy_dma;
 		}
 
 		INIT_WORK(&udc->vbus_work, mv_udc_vbus_work);
@@ -2358,7 +2298,8 @@ static int mv_udc_probe(struct platform_device *pdev)
 	else
 		udc->vbus_active = 1;
 
-	retval = usb_add_gadget_udc(&pdev->dev, &udc->gadget);
+	retval = usb_add_gadget_udc_release(&pdev->dev, &udc->gadget,
+			gadget_release);
 	if (retval)
 		goto err_create_workqueue;
 
@@ -2370,8 +2311,6 @@ static int mv_udc_probe(struct platform_device *pdev)
 
 err_create_workqueue:
 	destroy_workqueue(udc->qwork);
-err_unregister:
-	device_unregister(&udc->gadget.dev);
 err_destroy_dma:
 	dma_pool_destroy(udc->dtd_pool);
 err_free_dma:
diff --git a/drivers/usb/gadget/ncm.c b/drivers/usb/gadget/ncm.c
index a22ad9a..3b02fd4 100644
--- a/drivers/usb/gadget/ncm.c
+++ b/drivers/usb/gadget/ncm.c
@@ -111,6 +111,7 @@ static struct usb_gadget_strings *dev_strings[] = {
 	NULL,
 };
 
+struct eth_dev *the_dev;
 static u8 hostaddr[ETH_ALEN];
 
 /*-------------------------------------------------------------------------*/
@@ -124,7 +125,7 @@ static int __init ncm_do_config(struct usb_configuration *c)
 		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 	}
 
-	return ncm_bind_config(c, hostaddr);
+	return ncm_bind_config(c, hostaddr, the_dev);
 }
 
 static struct usb_configuration ncm_config_driver = {
@@ -143,9 +144,9 @@ static int __init gncm_bind(struct usb_composite_dev *cdev)
 	int			status;
 
 	/* set up network link layer */
-	status = gether_setup(cdev->gadget, hostaddr);
-	if (status < 0)
-		return status;
+	the_dev = gether_setup(cdev->gadget, hostaddr);
+	if (IS_ERR(the_dev))
+		return PTR_ERR(the_dev);
 
 	/* Allocate string descriptor numbers ... note that string
 	 * contents can be overridden by the composite_dev glue.
@@ -168,13 +169,13 @@ static int __init gncm_bind(struct usb_composite_dev *cdev)
 	return 0;
 
 fail:
-	gether_cleanup();
+	gether_cleanup(the_dev);
 	return status;
 }
 
 static int __exit gncm_unbind(struct usb_composite_dev *cdev)
 {
-	gether_cleanup();
+	gether_cleanup(the_dev);
 	return 0;
 }
 
diff --git a/drivers/usb/gadget/net2272.c b/drivers/usb/gadget/net2272.c
index 32524b63..f1e50a3 100644
--- a/drivers/usb/gadget/net2272.c
+++ b/drivers/usb/gadget/net2272.c
@@ -58,7 +58,6 @@ static const char * const ep_name[] = {
 	"ep-a", "ep-b", "ep-c",
 };
 
-#define DMA_ADDR_INVALID	(~(dma_addr_t)0)
 #ifdef CONFIG_USB_NET2272_DMA
 /*
  * use_dma: the NET2272 can use an external DMA controller.
@@ -341,7 +340,6 @@ net2272_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
 	if (!req)
 		return NULL;
 
-	req->req.dma = DMA_ADDR_INVALID;
 	INIT_LIST_HEAD(&req->queue);
 
 	return &req->req;
@@ -913,7 +911,7 @@ net2272_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 			}
 		}
 	}
-	if (likely(req != 0))
+	if (likely(req))
 		list_add_tail(&req->queue, &ep->queue);
 
 	if (likely(!list_empty(&ep->queue)))
@@ -1467,7 +1465,6 @@ static int net2272_start(struct usb_gadget *_gadget,
 	dev->softconnect = 1;
 	driver->driver.bus = NULL;
 	dev->driver = driver;
-	dev->gadget.dev.driver = &driver->driver;
 
 	/* ... then enable host detection and ep0; and we're ready
 	 * for set_configuration as well as eventual disconnect.
@@ -1517,7 +1514,6 @@ static int net2272_stop(struct usb_gadget *_gadget,
 	stop_activity(dev, driver);
 	spin_unlock_irqrestore(&dev->lock, flags);
 
-	dev->gadget.dev.driver = NULL;
 	dev->driver = NULL;
 
 	dev_dbg(dev->dev, "unregistered driver '%s'\n", driver->driver.name);
@@ -1549,7 +1545,7 @@ net2272_handle_dma(struct net2272_ep *ep)
 	      | (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->dma << DMA_ENDPOINT_SELECT));
 
 	ep->dev->dma_busy = 0;
 
@@ -1622,7 +1618,7 @@ net2272_handle_ep(struct net2272_ep *ep)
 	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);
+		ep->ep.name, stat0, stat1, req ? &req->req : NULL);
 
 	net2272_ep_write(ep, EP_STAT0, stat0 &
 		~((1 << NAK_OUT_PACKETS)
@@ -2216,7 +2212,6 @@ net2272_remove(struct net2272 *dev)
 	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");
@@ -2243,10 +2238,6 @@ static struct net2272 *net2272_probe_init(struct device *dev, unsigned int irq)
 	ret->gadget.max_speed = USB_SPEED_HIGH;
 
 	/* 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;
@@ -2282,14 +2273,12 @@ net2272_probe_fin(struct net2272 *dev, unsigned int irqflags)
 		dma_mode_string());
 	dev_info(dev->dev, "version: %s\n", driver_vers);
 
-	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;
+		goto err_irq;
 
-	ret = usb_add_gadget_udc(dev->dev, &dev->gadget);
+	ret = usb_add_gadget_udc_release(dev->dev, &dev->gadget,
+			net2272_gadget_release);
 	if (ret)
 		goto err_add_udc;
 
@@ -2297,8 +2286,6 @@ net2272_probe_fin(struct net2272 *dev, unsigned int irqflags)
 
 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:
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
index 3bd0f99..fbd006a 100644
--- a/drivers/usb/gadget/net2280.c
+++ b/drivers/usb/gadget/net2280.c
@@ -65,7 +65,6 @@
 #define	DRIVER_DESC		"PLX NET228x USB Peripheral Controller"
 #define	DRIVER_VERSION		"2005 Sept 27"
 
-#define	DMA_ADDR_INVALID	(~(dma_addr_t)0)
 #define	EP_DONTUSE		13	/* nonzero */
 
 #define USE_RDK_LEDS		/* GPIO pins control three LEDs */
@@ -406,7 +405,6 @@ net2280_alloc_request (struct usb_ep *_ep, gfp_t gfp_flags)
 	if (!req)
 		return NULL;
 
-	req->req.dma = DMA_ADDR_INVALID;
 	INIT_LIST_HEAD (&req->queue);
 
 	/* this dma descriptor may be swapped with the previous dummy */
@@ -420,7 +418,6 @@ net2280_alloc_request (struct usb_ep *_ep, gfp_t gfp_flags)
 			return NULL;
 		}
 		td->dmacount = 0;	/* not VALID */
-		td->dmaaddr = cpu_to_le32 (DMA_ADDR_INVALID);
 		td->dmadesc = td->dmaaddr;
 		req->td = td;
 	}
@@ -1896,7 +1893,6 @@ static int net2280_start(struct usb_gadget *_gadget,
 	dev->softconnect = 1;
 	driver->driver.bus = NULL;
 	dev->driver = driver;
-	dev->gadget.dev.driver = &driver->driver;
 
 	retval = device_create_file (&dev->pdev->dev, &dev_attr_function);
 	if (retval) goto err_unbind;
@@ -1924,7 +1920,6 @@ static int net2280_start(struct usb_gadget *_gadget,
 err_func:
 	device_remove_file (&dev->pdev->dev, &dev_attr_function);
 err_unbind:
-	dev->gadget.dev.driver = NULL;
 	dev->driver = NULL;
 	return retval;
 }
@@ -1967,7 +1962,6 @@ static int net2280_stop(struct usb_gadget *_gadget,
 	stop_activity (dev, driver);
 	spin_unlock_irqrestore (&dev->lock, flags);
 
-	dev->gadget.dev.driver = NULL;
 	dev->driver = NULL;
 
 	net2280_led_active (dev, 0);
@@ -2072,7 +2066,7 @@ static void handle_ep_small (struct net2280_ep *ep)
 		return;
 
 	/* manual DMA queue advance after short OUT */
-	if (likely (ep->dma != 0)) {
+	if (likely (ep->dma)) {
 		if (t & (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT)) {
 			u32	count;
 			int	stopped = ep->stopped;
@@ -2330,7 +2324,7 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
 			/* hw handles device and interface status */
 			if (u.r.bRequestType != (USB_DIR_IN|USB_RECIP_ENDPOINT))
 				goto delegate;
-			if ((e = get_ep_by_addr (dev, w_index)) == 0
+			if ((e = get_ep_by_addr (dev, w_index)) == NULL
 					|| w_length > 2)
 				goto do_stall;
 
@@ -2358,7 +2352,7 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
 			if (w_value != USB_ENDPOINT_HALT
 					|| w_length != 0)
 				goto do_stall;
-			if ((e = get_ep_by_addr (dev, w_index)) == 0)
+			if ((e = get_ep_by_addr (dev, w_index)) == NULL)
 				goto do_stall;
 			if (e->wedged) {
 				VDEBUG(dev, "%s wedged, halt not cleared\n",
@@ -2380,7 +2374,7 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
 			if (w_value != USB_ENDPOINT_HALT
 					|| w_length != 0)
 				goto do_stall;
-			if ((e = get_ep_by_addr (dev, w_index)) == 0)
+			if ((e = get_ep_by_addr (dev, w_index)) == NULL)
 				goto do_stall;
 			if (e->ep.name == ep0name)
 				goto do_stall;
@@ -2685,7 +2679,6 @@ static void net2280_remove (struct pci_dev *pdev)
 				pci_resource_len (pdev, 0));
 	if (dev->enabled)
 		pci_disable_device (pdev);
-	device_unregister (&dev->gadget.dev);
 	device_remove_file (&pdev->dev, &dev_attr_registers);
 	pci_set_drvdata (pdev, NULL);
 
@@ -2717,10 +2710,6 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
 	dev->gadget.max_speed = USB_SPEED_HIGH;
 
 	/* the "gadget" abstracts/virtualizes the controller */
-	dev_set_name(&dev->gadget.dev, "gadget");
-	dev->gadget.dev.parent = &pdev->dev;
-	dev->gadget.dev.dma_mask = pdev->dev.dma_mask;
-	dev->gadget.dev.release = gadget_release;
 	dev->gadget.name = driver_name;
 
 	/* now all the pci goodies ... */
@@ -2802,7 +2791,6 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
 			goto done;
 		}
 		td->dmacount = 0;	/* not VALID */
-		td->dmaaddr = cpu_to_le32 (DMA_ADDR_INVALID);
 		td->dmadesc = td->dmaaddr;
 		dev->ep [i].dummy = td;
 	}
@@ -2829,12 +2817,11 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
 			use_dma
 				? (use_dma_chaining ? "chaining" : "enabled")
 				: "disabled");
-	retval = device_register (&dev->gadget.dev);
-	if (retval) goto done;
 	retval = device_create_file (&pdev->dev, &dev_attr_registers);
 	if (retval) goto done;
 
-	retval = usb_add_gadget_udc(&pdev->dev, &dev->gadget);
+	retval = usb_add_gadget_udc_release(&pdev->dev, &dev->gadget,
+			gadget_release);
 	if (retval)
 		goto done;
 	return 0;
diff --git a/drivers/usb/gadget/nokia.c b/drivers/usb/gadget/nokia.c
index def3740..3b344b4 100644
--- a/drivers/usb/gadget/nokia.c
+++ b/drivers/usb/gadget/nokia.c
@@ -37,11 +37,9 @@
  * the runtime footprint, and giving us at least some parts of what
  * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
  */
-#define USB_FACM_INCLUDED
-#include "f_acm.c"
+#define USBF_OBEX_INCLUDED
 #include "f_ecm.c"
 #include "f_obex.c"
-#include "f_serial.c"
 #include "f_phonet.c"
 #include "u_ether.c"
 
@@ -98,20 +96,40 @@ MODULE_AUTHOR("Felipe Balbi");
 MODULE_LICENSE("GPL");
 
 /*-------------------------------------------------------------------------*/
-
+static struct usb_function *f_acm_cfg1;
+static struct usb_function *f_acm_cfg2;
 static u8 hostaddr[ETH_ALEN];
+static struct eth_dev *the_dev;
 
 enum {
 	TTY_PORT_OBEX0,
 	TTY_PORT_OBEX1,
-	TTY_PORT_ACM,
 	TTY_PORTS_MAX,
 };
 
 static unsigned char tty_lines[TTY_PORTS_MAX];
 
+static struct usb_configuration nokia_config_500ma_driver = {
+	.label		= "Bus Powered",
+	.bConfigurationValue = 1,
+	/* .iConfiguration = DYNAMIC */
+	.bmAttributes	= USB_CONFIG_ATT_ONE,
+	.MaxPower	= 500,
+};
+
+static struct usb_configuration nokia_config_100ma_driver = {
+	.label		= "Self Powered",
+	.bConfigurationValue = 2,
+	/* .iConfiguration = DYNAMIC */
+	.bmAttributes	= USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
+	.MaxPower	= 100,
+};
+
+static struct usb_function_instance *fi_acm;
+
 static int __init nokia_bind_config(struct usb_configuration *c)
 {
+	struct usb_function *f_acm;
 	int status = 0;
 
 	status = phonet_bind_config(c);
@@ -126,33 +144,32 @@ static int __init nokia_bind_config(struct usb_configuration *c)
 	if (status)
 		printk(KERN_DEBUG "could not bind obex config %d\n", 0);
 
-	status = acm_bind_config(c, tty_lines[TTY_PORT_ACM]);
-	if (status)
-		printk(KERN_DEBUG "could not bind acm config\n");
+	f_acm = usb_get_function(fi_acm);
+	if (IS_ERR(f_acm))
+		return PTR_ERR(f_acm);
 
-	status = ecm_bind_config(c, hostaddr);
+	status = usb_add_function(c, f_acm);
 	if (status)
-		printk(KERN_DEBUG "could not bind ecm config\n");
+		goto err_conf;
+
+	status = ecm_bind_config(c, hostaddr, the_dev);
+	if (status) {
+		pr_debug("could not bind ecm config %d\n", status);
+		goto err_ecm;
+	}
+	if (c == &nokia_config_500ma_driver)
+		f_acm_cfg1 = f_acm;
+	else
+		f_acm_cfg2 = f_acm;
 
 	return status;
+err_ecm:
+	usb_remove_function(c, f_acm);
+err_conf:
+	usb_put_function(f_acm);
+	return status;
 }
 
-static struct usb_configuration nokia_config_500ma_driver = {
-	.label		= "Bus Powered",
-	.bConfigurationValue = 1,
-	/* .iConfiguration = DYNAMIC */
-	.bmAttributes	= USB_CONFIG_ATT_ONE,
-	.MaxPower	= 500,
-};
-
-static struct usb_configuration nokia_config_100ma_driver = {
-	.label		= "Self Powered",
-	.bConfigurationValue = 2,
-	/* .iConfiguration = DYNAMIC */
-	.bmAttributes	= USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
-	.MaxPower	= 100,
-};
-
 static int __init nokia_bind(struct usb_composite_dev *cdev)
 {
 	struct usb_gadget	*gadget = cdev->gadget;
@@ -169,9 +186,11 @@ static int __init nokia_bind(struct usb_composite_dev *cdev)
 			goto err_ether;
 	}
 
-	status = gether_setup(cdev->gadget, hostaddr);
-	if (status < 0)
+	the_dev = gether_setup(cdev->gadget, hostaddr);
+	if (IS_ERR(the_dev)) {
+		status = PTR_ERR(the_dev);
 		goto err_ether;
+	}
 
 	status = usb_string_ids_tab(cdev, strings_dev);
 	if (status < 0)
@@ -185,24 +204,32 @@ static int __init nokia_bind(struct usb_composite_dev *cdev)
 	if (!gadget_supports_altsettings(gadget))
 		goto err_usb;
 
+	fi_acm = usb_get_function_instance("acm");
+	if (IS_ERR(fi_acm))
+		goto err_usb;
+
 	/* finally register the configuration */
 	status = usb_add_config(cdev, &nokia_config_500ma_driver,
 			nokia_bind_config);
 	if (status < 0)
-		goto err_usb;
+		goto err_acm_inst;
 
 	status = usb_add_config(cdev, &nokia_config_100ma_driver,
 			nokia_bind_config);
 	if (status < 0)
-		goto err_usb;
+		goto err_put_cfg1;
 
 	usb_composite_overwrite_options(cdev, &coverwrite);
 	dev_info(&gadget->dev, "%s\n", NOKIA_LONG_NAME);
 
 	return 0;
 
+err_put_cfg1:
+	usb_put_function(f_acm_cfg1);
+err_acm_inst:
+	usb_put_function_instance(fi_acm);
 err_usb:
-	gether_cleanup();
+	gether_cleanup(the_dev);
 err_ether:
 	cur_line--;
 	while (cur_line >= 0)
@@ -217,12 +244,15 @@ static int __exit nokia_unbind(struct usb_composite_dev *cdev)
 {
 	int i;
 
+	usb_put_function(f_acm_cfg1);
+	usb_put_function(f_acm_cfg2);
+	usb_put_function_instance(fi_acm);
 	gphonet_cleanup();
 
 	for (i = 0; i < TTY_PORTS_MAX; i++)
 		gserial_free_line(tty_lines[i]);
 
-	gether_cleanup();
+	gether_cleanup(the_dev);
 
 	return 0;
 }
@@ -247,4 +277,3 @@ static void __exit nokia_cleanup(void)
 	usb_composite_unregister(&nokia_driver);
 }
 module_exit(nokia_cleanup);
-
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
index f844565..b8ed74a 100644
--- a/drivers/usb/gadget/omap_udc.c
+++ b/drivers/usb/gadget/omap_udc.c
@@ -2067,7 +2067,6 @@ static int omap_udc_start(struct usb_gadget *g,
 	/* hook up the driver */
 	driver->driver.bus = NULL;
 	udc->driver = driver;
-	udc->gadget.dev.driver = &driver->driver;
 	spin_unlock_irqrestore(&udc->lock, flags);
 
 	if (udc->dc_clk != NULL)
@@ -2083,7 +2082,6 @@ static int omap_udc_start(struct usb_gadget *g,
 			ERR("can't bind to transceiver\n");
 			if (driver->unbind) {
 				driver->unbind(&udc->gadget);
-				udc->gadget.dev.driver = NULL;
 				udc->driver = NULL;
 			}
 			goto done;
@@ -2129,7 +2127,6 @@ static int omap_udc_stop(struct usb_gadget *g,
 	udc_quiesce(udc);
 	spin_unlock_irqrestore(&udc->lock, flags);
 
-	udc->gadget.dev.driver = NULL;
 	udc->driver = NULL;
 
 	if (udc->dc_clk != NULL)
@@ -2631,14 +2628,6 @@ omap_udc_setup(struct platform_device *odev, struct usb_phy *xceiv)
 	udc->gadget.speed = USB_SPEED_UNKNOWN;
 	udc->gadget.max_speed = USB_SPEED_FULL;
 	udc->gadget.name = driver_name;
-
-	device_initialize(&udc->gadget.dev);
-	dev_set_name(&udc->gadget.dev, "gadget");
-	udc->gadget.dev.release = omap_udc_release;
-	udc->gadget.dev.parent = &odev->dev;
-	if (use_dma)
-		udc->gadget.dev.dma_mask = odev->dev.dma_mask;
-
 	udc->transceiver = xceiv;
 
 	/* ep0 is special; put it right after the SETUP buffer */
@@ -2912,14 +2901,13 @@ bad_on_1710:
 	}
 
 	create_proc_file();
-	status = device_add(&udc->gadget.dev);
+	status = usb_add_gadget_udc_release(&pdev->dev, &udc->gadget,
+			omap_udc_release);
 	if (status)
 		goto cleanup4;
 
-	status = usb_add_gadget_udc(&pdev->dev, &udc->gadget);
-	if (!status)
-		return status;
-	/* If fail, fall through */
+	return 0;
+
 cleanup4:
 	remove_proc_file();
 
@@ -2990,7 +2978,6 @@ static int omap_udc_remove(struct platform_device *pdev)
 	release_mem_region(pdev->resource[0].start,
 			pdev->resource[0].end - pdev->resource[0].start + 1);
 
-	device_unregister(&udc->gadget.dev);
 	wait_for_completion(&done);
 
 	return 0;
diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/pch_udc.c
index a787a8e..24174e1 100644
--- a/drivers/usb/gadget/pch_udc.c
+++ b/drivers/usb/gadget/pch_udc.c
@@ -358,7 +358,6 @@ struct pch_udc_dev {
 			prot_stall:1,
 			irq_registered:1,
 			mem_region:1,
-			registered:1,
 			suspended:1,
 			connected:1,
 			vbus_session:1,
@@ -1441,6 +1440,8 @@ static void pch_vbus_gpio_free(struct pch_udc_dev *dev)
  */
 static void complete_req(struct pch_udc_ep *ep, struct pch_udc_request *req,
 								 int status)
+	__releases(&dev->lock)
+	__acquires(&dev->lock)
 {
 	struct pch_udc_dev	*dev;
 	unsigned halted = ep->halted;
@@ -2382,6 +2383,8 @@ static void pch_udc_svc_control_in(struct pch_udc_dev *dev)
  * @dev:	Reference to the device structure
  */
 static void pch_udc_svc_control_out(struct pch_udc_dev *dev)
+	__releases(&dev->lock)
+	__acquires(&dev->lock)
 {
 	u32	stat;
 	int setup_supported;
@@ -2989,7 +2992,6 @@ static int pch_udc_start(struct usb_gadget *g,
 
 	driver->driver.bus = NULL;
 	dev->driver = driver;
-	dev->gadget.dev.driver = &driver->driver;
 
 	/* get ready for ep0 traffic */
 	pch_udc_setup_ep0(dev);
@@ -3010,7 +3012,6 @@ static int pch_udc_stop(struct usb_gadget *g,
 	pch_udc_disable_interrupts(dev, UDC_DEVINT_MSK);
 
 	/* Assures that there are no pending requests with this driver */
-	dev->gadget.dev.driver = NULL;
 	dev->driver = NULL;
 	dev->connected = 0;
 
@@ -3078,8 +3079,6 @@ static void pch_udc_remove(struct pci_dev *pdev)
 				   pci_resource_len(pdev, PCH_UDC_PCI_BAR));
 	if (dev->active)
 		pci_disable_device(pdev);
-	if (dev->registered)
-		device_unregister(&dev->gadget.dev);
 	kfree(dev);
 	pci_set_drvdata(pdev, NULL);
 }
@@ -3196,21 +3195,13 @@ static int pch_udc_probe(struct pci_dev *pdev,
 	if (retval)
 		goto finished;
 
-	dev_set_name(&dev->gadget.dev, "gadget");
-	dev->gadget.dev.parent = &pdev->dev;
-	dev->gadget.dev.dma_mask = pdev->dev.dma_mask;
-	dev->gadget.dev.release = gadget_release;
 	dev->gadget.name = KBUILD_MODNAME;
 	dev->gadget.max_speed = USB_SPEED_HIGH;
 
-	retval = device_register(&dev->gadget.dev);
-	if (retval)
-		goto finished;
-	dev->registered = 1;
-
 	/* 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);
+	retval = usb_add_gadget_udc_release(&pdev->dev, &dev->gadget,
+			gadget_release);
 	if (retval)
 		goto finished;
 	return 0;
diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c
index d0f3748..ef47495 100644
--- a/drivers/usb/gadget/pxa25x_udc.c
+++ b/drivers/usb/gadget/pxa25x_udc.c
@@ -1263,7 +1263,6 @@ static int pxa25x_udc_start(struct usb_gadget *g,
 
 	/* first hook up the driver ... */
 	dev->driver = driver;
-	dev->gadget.dev.driver = &driver->driver;
 	dev->pullup = 1;
 
 	/* ... then enable host detection and ep0; and we're ready
@@ -1325,7 +1324,6 @@ static int pxa25x_udc_stop(struct usb_gadget*g,
 	if (!IS_ERR_OR_NULL(dev->transceiver))
 		(void) otg_set_peripheral(dev->transceiver->otg, NULL);
 
-	dev->gadget.dev.driver = NULL;
 	dev->driver = NULL;
 
 	dump_state(dev);
@@ -2138,17 +2136,6 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev)
 	dev->timer.function = udc_watchdog;
 	dev->timer.data = (unsigned long) dev;
 
-	device_initialize(&dev->gadget.dev);
-	dev->gadget.dev.parent = &pdev->dev;
-	dev->gadget.dev.dma_mask = pdev->dev.dma_mask;
-
-	retval = device_add(&dev->gadget.dev);
-	if (retval) {
-		dev->driver = NULL;
-		dev->gadget.dev.driver = NULL;
-		goto err_device_add;
-	}
-
 	the_controller = dev;
 	platform_set_drvdata(pdev, dev);
 
@@ -2199,8 +2186,6 @@ lubbock_fail0:
 	free_irq(irq, dev);
 #endif
  err_irq1:
-	device_unregister(&dev->gadget.dev);
- err_device_add:
 	if (gpio_is_valid(dev->mach->gpio_pullup))
 		gpio_free(dev->mach->gpio_pullup);
  err_gpio_pullup:
@@ -2226,7 +2211,6 @@ static int __exit pxa25x_udc_remove(struct platform_device *pdev)
 		return -EBUSY;
 
 	usb_del_gadget_udc(&dev->gadget);
-	device_unregister(&dev->gadget.dev);
 	dev->pullup = 0;
 	pullup(dev);
 
diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c
index 2fc8676..6b4c7d9 100644
--- a/drivers/usb/gadget/pxa27x_udc.c
+++ b/drivers/usb/gadget/pxa27x_udc.c
@@ -24,14 +24,12 @@
 #include <linux/gpio.h>
 #include <linux/slab.h>
 #include <linux/prefetch.h>
-
-#include <asm/byteorder.h>
-#include <mach/hardware.h>
+#include <linux/byteorder/generic.h>
+#include <linux/platform_data/pxa2xx_udc.h>
 
 #include <linux/usb.h>
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
-#include <mach/udc.h>
 
 #include "pxa27x_udc.h"
 
@@ -611,7 +609,7 @@ static void inc_ep_stats_bytes(struct pxa_ep *ep, int count, int is_in)
  *
  * Find the physical pxa27x ep, and setup its UDCCR
  */
-static __init void pxa_ep_setup(struct pxa_ep *ep)
+static void pxa_ep_setup(struct pxa_ep *ep)
 {
 	u32 new_udccr;
 
@@ -633,7 +631,7 @@ static __init void pxa_ep_setup(struct pxa_ep *ep)
  *
  * Setup all pxa physical endpoints, except ep0
  */
-static __init void pxa_eps_setup(struct pxa_udc *dev)
+static void pxa_eps_setup(struct pxa_udc *dev)
 {
 	unsigned int i;
 
@@ -1718,7 +1716,7 @@ static void udc_disable(struct pxa_udc *udc)
  * Initializes gadget endpoint list, endpoints locks. No action is taken
  * on the hardware.
  */
-static __init void udc_init_data(struct pxa_udc *dev)
+static void udc_init_data(struct pxa_udc *dev)
 {
 	int i;
 	struct pxa_ep *ep;
@@ -1811,7 +1809,6 @@ static int pxa27x_udc_start(struct usb_gadget *g,
 
 	/* first hook up the driver ... */
 	udc->driver = driver;
-	udc->gadget.dev.driver = &driver->driver;
 	dplus_pullup(udc, 1);
 
 	if (!IS_ERR_OR_NULL(udc->transceiver)) {
@@ -1829,7 +1826,6 @@ static int pxa27x_udc_start(struct usb_gadget *g,
 
 fail:
 	udc->driver = NULL;
-	udc->gadget.dev.driver = NULL;
 	return retval;
 }
 
@@ -1871,7 +1867,6 @@ static int pxa27x_udc_stop(struct usb_gadget *g,
 
 	udc->driver = NULL;
 
-
 	if (!IS_ERR_OR_NULL(udc->transceiver))
 		return otg_set_peripheral(udc->transceiver->otg, NULL);
 	return 0;
@@ -2413,7 +2408,7 @@ static struct pxa_udc memory = {
  * Perform basic init : allocates udc clock, creates sysfs files, requests
  * irq.
  */
-static int __init pxa_udc_probe(struct platform_device *pdev)
+static int pxa_udc_probe(struct platform_device *pdev)
 {
 	struct resource *regs;
 	struct pxa_udc *udc = &memory;
@@ -2456,9 +2451,6 @@ static int __init pxa_udc_probe(struct platform_device *pdev)
 		goto err_map;
 	}
 
-	device_initialize(&udc->gadget.dev);
-	udc->gadget.dev.parent = &pdev->dev;
-	udc->gadget.dev.dma_mask = NULL;
 	udc->vbus_sensed = 0;
 
 	the_controller = udc;
@@ -2475,12 +2467,6 @@ static int __init pxa_udc_probe(struct platform_device *pdev)
 		goto err_irq;
 	}
 
-	retval = device_add(&udc->gadget.dev);
-	if (retval) {
-		dev_err(udc->dev, "device_add error %d\n", retval);
-		goto err_dev_add;
-	}
-
 	retval = usb_add_gadget_udc(&pdev->dev, &udc->gadget);
 	if (retval)
 		goto err_add_udc;
@@ -2490,8 +2476,6 @@ static int __init pxa_udc_probe(struct platform_device *pdev)
 	return 0;
 
 err_add_udc:
-	device_unregister(&udc->gadget.dev);
-err_dev_add:
 	free_irq(udc->irq, udc);
 err_irq:
 	iounmap(udc->regs);
@@ -2506,13 +2490,12 @@ err_clk:
  * pxa_udc_remove - removes the udc device driver
  * @_dev: platform device
  */
-static int __exit pxa_udc_remove(struct platform_device *_dev)
+static int 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);
-	device_del(&udc->gadget.dev);
 	usb_gadget_unregister_driver(udc->driver);
 	free_irq(udc->irq, udc);
 	pxa_cleanup_debugfs(udc);
@@ -2625,7 +2608,8 @@ static struct platform_driver udc_driver = {
 		.name	= "pxa27x-udc",
 		.owner	= THIS_MODULE,
 	},
-	.remove		= __exit_p(pxa_udc_remove),
+	.probe		= pxa_udc_probe,
+	.remove		= pxa_udc_remove,
 	.shutdown	= pxa_udc_shutdown,
 #ifdef CONFIG_PM
 	.suspend	= pxa_udc_suspend,
@@ -2633,22 +2617,7 @@ static struct platform_driver udc_driver = {
 #endif
 };
 
-static int __init udc_init(void)
-{
-	if (!cpu_is_pxa27x() && !cpu_is_pxa3xx())
-		return -ENODEV;
-
-	printk(KERN_INFO "%s: version %s\n", driver_name, DRIVER_VERSION);
-	return platform_driver_probe(&udc_driver, pxa_udc_probe);
-}
-module_init(udc_init);
-
-
-static void __exit udc_exit(void)
-{
-	platform_driver_unregister(&udc_driver);
-}
-module_exit(udc_exit);
+module_platform_driver(udc_driver);
 
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_AUTHOR("Robert Jarzmik");
diff --git a/drivers/usb/gadget/r8a66597-udc.c b/drivers/usb/gadget/r8a66597-udc.c
index f46a1b7..0b742d1 100644
--- a/drivers/usb/gadget/r8a66597-udc.c
+++ b/drivers/usb/gadget/r8a66597-udc.c
@@ -1837,7 +1837,6 @@ static int __exit r8a66597_remove(struct platform_device *pdev)
 		clk_put(r8a66597->clk);
 	}
 
-	device_unregister(&r8a66597->gadget.dev);
 	kfree(r8a66597);
 	return 0;
 }
@@ -1915,17 +1914,8 @@ static int __init r8a66597_probe(struct platform_device *pdev)
 	r8a66597->irq_sense_low = irq_trigger == IRQF_TRIGGER_LOW;
 
 	r8a66597->gadget.ops = &r8a66597_gadget_ops;
-	dev_set_name(&r8a66597->gadget.dev, "gadget");
 	r8a66597->gadget.max_speed = USB_SPEED_HIGH;
-	r8a66597->gadget.dev.parent = &pdev->dev;
-	r8a66597->gadget.dev.dma_mask = pdev->dev.dma_mask;
-	r8a66597->gadget.dev.release = pdev->dev.release;
 	r8a66597->gadget.name = udc_name;
-	ret = device_register(&r8a66597->gadget.dev);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "device_register failed\n");
-		goto clean_up;
-	}
 
 	init_timer(&r8a66597->timer);
 	r8a66597->timer.function = r8a66597_timer;
@@ -1939,7 +1929,7 @@ static int __init r8a66597_probe(struct platform_device *pdev)
 			dev_err(&pdev->dev, "cannot get clock \"%s\"\n",
 				clk_name);
 			ret = PTR_ERR(r8a66597->clk);
-			goto clean_up_dev;
+			goto clean_up;
 		}
 		clk_enable(r8a66597->clk);
 	}
@@ -2007,8 +1997,6 @@ clean_up2:
 		clk_disable(r8a66597->clk);
 		clk_put(r8a66597->clk);
 	}
-clean_up_dev:
-	device_unregister(&r8a66597->gadget.dev);
 clean_up:
 	if (r8a66597) {
 		if (r8a66597->sudmac_reg)
diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c
index d9297ee..1e4cfb0 100644
--- a/drivers/usb/gadget/rndis.c
+++ b/drivers/usb/gadget/rndis.c
@@ -1065,7 +1065,7 @@ static int rndis_proc_show(struct seq_file *m, void *v)
 static ssize_t rndis_proc_write(struct file *file, const char __user *buffer,
 				size_t count, loff_t *ppos)
 {
-	rndis_params *p = PDE(file_inode(file))->data;
+	rndis_params *p = PDE_DATA(file_inode(file));
 	u32 speed = 0;
 	int i, fl_speed = 0;
 
@@ -1109,7 +1109,7 @@ static ssize_t rndis_proc_write(struct file *file, const char __user *buffer,
 
 static int rndis_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, rndis_proc_show, PDE(inode)->data);
+	return single_open(file, rndis_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations rndis_proc_fops = {
diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c
index c26564f..a3cdc32 100644
--- a/drivers/usb/gadget/s3c-hsotg.c
+++ b/drivers/usb/gadget/s3c-hsotg.c
@@ -39,8 +39,6 @@
 
 #include "s3c-hsotg.h"
 
-#define DMA_ADDR_INVALID (~((dma_addr_t)0))
-
 static const char * const s3c_hsotg_supply_names[] = {
 	"vusb_d",		/* digital USB supply, 1.2V */
 	"vusb_a",		/* analog USB supply, 1.1V */
@@ -405,7 +403,6 @@ static struct usb_request *s3c_hsotg_ep_alloc_request(struct usb_ep *ep,
 
 	INIT_LIST_HEAD(&req->queue);
 
-	req->req.dma = DMA_ADDR_INVALID;
 	return &req->req;
 }
 
@@ -435,24 +432,12 @@ static void s3c_hsotg_unmap_dma(struct s3c_hsotg *hsotg,
 				struct s3c_hsotg_req *hs_req)
 {
 	struct usb_request *req = &hs_req->req;
-	enum dma_data_direction dir;
-
-	dir = hs_ep->dir_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
 
 	/* ignore this if we're not moving any data */
 	if (hs_req->req.length == 0)
 		return;
 
-	if (hs_req->mapped) {
-		/* we mapped this, so unmap and remove the dma */
-
-		dma_unmap_single(hsotg->dev, req->dma, req->length, dir);
-
-		req->dma = DMA_ADDR_INVALID;
-		hs_req->mapped = 0;
-	} else {
-		dma_sync_single_for_cpu(hsotg->dev, req->dma, req->length, dir);
-	}
+	usb_gadget_unmap_request(&hsotg->gadget, hs_req, hs_ep->dir_in);
 }
 
 /**
@@ -852,37 +837,16 @@ static int s3c_hsotg_map_dma(struct s3c_hsotg *hsotg,
 			     struct s3c_hsotg_ep *hs_ep,
 			     struct usb_request *req)
 {
-	enum dma_data_direction dir;
 	struct s3c_hsotg_req *hs_req = our_req(req);
-
-	dir = hs_ep->dir_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+	int ret;
 
 	/* if the length is zero, ignore the DMA data */
 	if (hs_req->req.length == 0)
 		return 0;
 
-	if (req->dma == DMA_ADDR_INVALID) {
-		dma_addr_t dma;
-
-		dma = dma_map_single(hsotg->dev, req->buf, req->length, dir);
-
-		if (unlikely(dma_mapping_error(hsotg->dev, dma)))
-			goto dma_error;
-
-		if (dma & 3) {
-			dev_err(hsotg->dev, "%s: unaligned dma buffer\n",
-				__func__);
-
-			dma_unmap_single(hsotg->dev, dma, req->length, dir);
-			return -EINVAL;
-		}
-
-		hs_req->mapped = 1;
-		req->dma = dma;
-	} else {
-		dma_sync_single_for_cpu(hsotg->dev, req->dma, req->length, dir);
-		hs_req->mapped = 0;
-	}
+	ret = usb_gadget_map_request(&hsotg->gadget, req, hs_ep->dir_in);
+	if (ret)
+		goto dma_error;
 
 	return 0;
 
@@ -2961,9 +2925,7 @@ static int s3c_hsotg_udc_start(struct usb_gadget *gadget,
 
 	driver->driver.bus = NULL;
 	hsotg->driver = driver;
-	hsotg->gadget.dev.driver = &driver->driver;
 	hsotg->gadget.dev.of_node = hsotg->dev->of_node;
-	hsotg->gadget.dev.dma_mask = hsotg->dev->dma_mask;
 	hsotg->gadget.speed = USB_SPEED_UNKNOWN;
 
 	ret = regulator_bulk_enable(ARRAY_SIZE(hsotg->supplies),
@@ -2979,7 +2941,6 @@ static int s3c_hsotg_udc_start(struct usb_gadget *gadget,
 
 err:
 	hsotg->driver = NULL;
-	hsotg->gadget.dev.driver = NULL;
 	return ret;
 }
 
@@ -3014,7 +2975,6 @@ static int s3c_hsotg_udc_stop(struct usb_gadget *gadget,
 
 	hsotg->driver = NULL;
 	hsotg->gadget.speed = USB_SPEED_UNKNOWN;
-	hsotg->gadget.dev.driver = NULL;
 
 	spin_unlock_irqrestore(&hsotg->lock, flags);
 
@@ -3484,16 +3444,6 @@ static void s3c_hsotg_delete_debug(struct s3c_hsotg *hsotg)
 }
 
 /**
- * s3c_hsotg_release - release callback for hsotg device
- * @dev: Device to for which release is called
- *
- * Nothing to do as the resource is allocated using devm_ API.
- */
-static void s3c_hsotg_release(struct device *dev)
-{
-}
-
-/**
  * s3c_hsotg_probe - probe function for hsotg driver
  * @pdev: The platform information for the driver
  */
@@ -3517,7 +3467,7 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
 	}
 
 	phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
-	if (IS_ERR_OR_NULL(phy)) {
+	if (IS_ERR(phy)) {
 		/* Fallback for pdata */
 		plat = pdev->dev.platform_data;
 		if (!plat) {
@@ -3567,18 +3517,10 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
 
 	dev_info(dev, "regs %p, irq %d\n", hsotg->regs, hsotg->irq);
 
-	device_initialize(&hsotg->gadget.dev);
-
-	dev_set_name(&hsotg->gadget.dev, "gadget");
-
 	hsotg->gadget.max_speed = USB_SPEED_HIGH;
 	hsotg->gadget.ops = &s3c_hsotg_gadget_ops;
 	hsotg->gadget.name = dev_name(dev);
 
-	hsotg->gadget.dev.parent = dev;
-	hsotg->gadget.dev.dma_mask = dev->dma_mask;
-	hsotg->gadget.dev.release = s3c_hsotg_release;
-
 	/* reset the system */
 
 	clk_prepare_enable(hsotg->clk);
@@ -3658,12 +3600,6 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
 
 	s3c_hsotg_phy_disable(hsotg);
 
-	ret = device_add(&hsotg->gadget.dev);
-	if (ret) {
-		put_device(&hsotg->gadget.dev);
-		goto err_ep_mem;
-	}
-
 	ret = usb_add_gadget_udc(&pdev->dev, &hsotg->gadget);
 	if (ret)
 		goto err_ep_mem;
@@ -3702,10 +3638,8 @@ static int s3c_hsotg_remove(struct platform_device *pdev)
 	}
 
 	s3c_hsotg_phy_disable(hsotg);
-
 	clk_disable_unprepare(hsotg->clk);
 
-	device_unregister(&hsotg->gadget.dev);
 	return 0;
 }
 
diff --git a/drivers/usb/gadget/s3c-hsudc.c b/drivers/usb/gadget/s3c-hsudc.c
index 458965a..b1f0771 100644
--- a/drivers/usb/gadget/s3c-hsudc.c
+++ b/drivers/usb/gadget/s3c-hsudc.c
@@ -283,7 +283,6 @@ static void s3c_hsudc_nuke_ep(struct s3c_hsudc_ep *hsep, int status)
 /**
  * s3c_hsudc_stop_activity - Stop activity on all endpoints.
  * @hsudc: Device controller for which EP activity is to be stopped.
- * @driver: Reference to the gadget driver which is currently active.
  *
  * All the endpoints are stopped and any pending transfer requests if any on
  * the endpoint are terminated.
@@ -1154,7 +1153,6 @@ static int s3c_hsudc_start(struct usb_gadget *gadget,
 		return -EBUSY;
 
 	hsudc->driver = driver;
-	hsudc->gadget.dev.driver = &driver->driver;
 
 	ret = regulator_bulk_enable(ARRAY_SIZE(hsudc->supplies),
 				    hsudc->supplies);
@@ -1190,7 +1188,6 @@ err_otg:
 	regulator_bulk_disable(ARRAY_SIZE(hsudc->supplies), hsudc->supplies);
 err_supplies:
 	hsudc->driver = NULL;
-	hsudc->gadget.dev.driver = NULL;
 	return ret;
 }
 
@@ -1208,7 +1205,6 @@ static int s3c_hsudc_stop(struct usb_gadget *gadget,
 
 	spin_lock_irqsave(&hsudc->lock, flags);
 	hsudc->driver = NULL;
-	hsudc->gadget.dev.driver = NULL;
 	hsudc->gadget.speed = USB_SPEED_UNKNOWN;
 	s3c_hsudc_uninit_phy();
 
@@ -1303,15 +1299,10 @@ static int s3c_hsudc_probe(struct platform_device *pdev)
 
 	spin_lock_init(&hsudc->lock);
 
-	dev_set_name(&hsudc->gadget.dev, "gadget");
-
 	hsudc->gadget.max_speed = USB_SPEED_HIGH;
 	hsudc->gadget.ops = &s3c_hsudc_gadget_ops;
 	hsudc->gadget.name = dev_name(dev);
-	hsudc->gadget.dev.parent = dev;
-	hsudc->gadget.dev.dma_mask = dev->dma_mask;
 	hsudc->gadget.ep0 = &hsudc->ep[0].ep;
-
 	hsudc->gadget.is_otg = 0;
 	hsudc->gadget.is_a_peripheral = 0;
 	hsudc->gadget.speed = USB_SPEED_UNKNOWN;
@@ -1345,12 +1336,6 @@ static int s3c_hsudc_probe(struct platform_device *pdev)
 	disable_irq(hsudc->irq);
 	local_irq_enable();
 
-	ret = device_register(&hsudc->gadget.dev);
-	if (ret) {
-		put_device(&hsudc->gadget.dev);
-		goto err_add_device;
-	}
-
 	ret = usb_add_gadget_udc(&pdev->dev, &hsudc->gadget);
 	if (ret)
 		goto err_add_udc;
@@ -1359,7 +1344,6 @@ static int s3c_hsudc_probe(struct platform_device *pdev)
 
 	return 0;
 err_add_udc:
-	device_unregister(&hsudc->gadget.dev);
 err_add_device:
 	clk_disable(hsudc->uclk);
 err_res:
diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c
index 08f8965..d0e75e1 100644
--- a/drivers/usb/gadget/s3c2410_udc.c
+++ b/drivers/usb/gadget/s3c2410_udc.c
@@ -1674,7 +1674,6 @@ static int s3c2410_udc_start(struct usb_gadget *g,
 
 	/* Hook the driver */
 	udc->driver = driver;
-	udc->gadget.dev.driver = &driver->driver;
 
 	/* Enable udc */
 	s3c2410_udc_enable(udc);
@@ -1824,17 +1823,6 @@ static int s3c2410_udc_probe(struct platform_device *pdev)
 		goto err_mem;
 	}
 
-	device_initialize(&udc->gadget.dev);
-	udc->gadget.dev.parent = &pdev->dev;
-	udc->gadget.dev.dma_mask = pdev->dev.dma_mask;
-
-	/* Bind the driver */
-	retval = device_add(&udc->gadget.dev);
-	if (retval) {
-		dev_err(&udc->gadget.dev, "Error in device_add() : %d\n", retval);
-		goto err_device_add;
-	}
-
 	the_controller = udc;
 	platform_set_drvdata(pdev, udc);
 
@@ -1923,8 +1911,6 @@ err_gpio_claim:
 err_int:
 	free_irq(IRQ_USBD, udc);
 err_map:
-	device_unregister(&udc->gadget.dev);
-err_device_add:
 	iounmap(base_addr);
 err_mem:
 	release_mem_region(rsrc_start, rsrc_len);
@@ -1946,7 +1932,6 @@ static int s3c2410_udc_remove(struct platform_device *pdev)
 		return -EBUSY;
 
 	usb_del_gadget_udc(&udc->gadget);
-	device_unregister(&udc->gadget.dev);
 	debugfs_remove(udc->regs_info);
 
 	if (udc_info && !udc_info->udc_command &&
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c
index 68d7bb0..1f5f978 100644
--- a/drivers/usb/gadget/serial.c
+++ b/drivers/usb/gadget/serial.c
@@ -12,6 +12,7 @@
 
 #include <linux/kernel.h>
 #include <linux/device.h>
+#include <linux/module.h>
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
 
@@ -28,18 +29,6 @@
 #define GS_VERSION_NAME			GS_LONG_NAME " " GS_VERSION_STR
 
 /*-------------------------------------------------------------------------*/
-
-/*
- * Kbuild is not very cooperative with respect to linking separately
- * compiled library objects into one module.  So for now we won't use
- * separate compilation ... ensuring init/exit sections work to shrink
- * the runtime footprint, and giving us at least some parts of what
- * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
- */
-#include "f_obex.c"
-#include "f_serial.c"
-
-/*-------------------------------------------------------------------------*/
 USB_GADGET_COMPOSITE_OPTIONS();
 
 /* Thanks to NetChip Technologies for donating this product ID.
@@ -126,27 +115,6 @@ module_param(n_ports, uint, 0);
 MODULE_PARM_DESC(n_ports, "number of ports to create, default=1");
 
 /*-------------------------------------------------------------------------*/
-static unsigned char tty_lines[MAX_U_SERIAL_PORTS];
-
-static int __init serial_bind_obex_config(struct usb_configuration *c)
-{
-	unsigned i;
-	int status = 0;
-
-	for (i = 0; i < n_ports && status == 0; i++)
-		status = obex_bind_config(c, tty_lines[i]);
-	return status;
-}
-
-static int __init serial_bind_gser_config(struct usb_configuration *c)
-{
-	unsigned i;
-	int status = 0;
-
-	for (i = 0; i < n_ports && status == 0; i++)
-		status = gser_bind_config(c, tty_lines[i]);
-	return status;
-}
 
 static struct usb_configuration serial_config_driver = {
 	/* .label = f(use_acm) */
@@ -169,15 +137,12 @@ static int serial_register_ports(struct usb_composite_dev *cdev,
 		goto out;
 
 	for (i = 0; i < n_ports; i++) {
-		struct f_serial_opts *opts;
 
 		fi_serial[i] = usb_get_function_instance(f_name);
 		if (IS_ERR(fi_serial[i])) {
 			ret = PTR_ERR(fi_serial[i]);
 			goto fail;
 		}
-		opts = container_of(fi_serial[i], struct f_serial_opts, func_inst);
-		opts->port_num = tty_lines[i];
 
 		f_serial[i] = usb_get_function(fi_serial[i]);
 		if (IS_ERR(f_serial[i])) {
@@ -212,13 +177,6 @@ out:
 static int __init gs_bind(struct usb_composite_dev *cdev)
 {
 	int			status;
-	int			cur_line;
-
-	for (cur_line = 0; cur_line < n_ports; cur_line++) {
-		status = gserial_alloc_line(&tty_lines[cur_line]);
-		if (status)
-			goto fail;
-	}
 
 	/* Allocate string descriptor numbers ... note that string
 	 * contents can be overridden by the composite_dev glue.
@@ -243,11 +201,12 @@ static int __init gs_bind(struct usb_composite_dev *cdev)
 				"acm");
 		usb_ep_autoconfig_reset(cdev->gadget);
 	} else if (use_obex)
-		status = usb_add_config(cdev, &serial_config_driver,
-				serial_bind_obex_config);
-	else
-		status = usb_add_config(cdev, &serial_config_driver,
-				serial_bind_gser_config);
+		status = serial_register_ports(cdev, &serial_config_driver,
+				"obex");
+	else {
+		status = serial_register_ports(cdev, &serial_config_driver,
+				"gser");
+	}
 	if (status < 0)
 		goto fail;
 
@@ -257,9 +216,6 @@ static int __init gs_bind(struct usb_composite_dev *cdev)
 	return 0;
 
 fail:
-	cur_line--;
-	while (cur_line >= 0)
-		gserial_free_line(tty_lines[cur_line--]);
 	return status;
 }
 
@@ -270,7 +226,6 @@ static int gs_unbind(struct usb_composite_dev *cdev)
 	for (i = 0; i < n_ports; i++) {
 		usb_put_function(f_serial[i]);
 		usb_put_function_instance(fi_serial[i]);
-		gserial_free_line(tty_lines[i]);
 	}
 	return 0;
 }
diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c
index a0aa721..4b76124 100644
--- a/drivers/usb/gadget/u_ether.c
+++ b/drivers/usb/gadget/u_ether.c
@@ -50,7 +50,6 @@
 
 struct eth_dev {
 	/* lock is held while accessing port_usb
-	 * or updating its backlink port_usb->ioport
 	 */
 	spinlock_t		lock;
 	struct gether		*port_usb;
@@ -729,8 +728,6 @@ static int get_ether_addr(const char *str, u8 *dev_addr)
 	return 1;
 }
 
-static struct eth_dev *the_dev;
-
 static const struct net_device_ops eth_netdev_ops = {
 	.ndo_open		= eth_open,
 	.ndo_stop		= eth_stop,
@@ -758,19 +755,16 @@ static struct device_type gadget_type = {
  *
  * Returns negative errno, or zero on success
  */
-int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
+struct eth_dev *gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
 		const char *netname)
 {
 	struct eth_dev		*dev;
 	struct net_device	*net;
 	int			status;
 
-	if (the_dev)
-		return -EBUSY;
-
 	net = alloc_etherdev(sizeof *dev);
 	if (!net)
-		return -ENOMEM;
+		return ERR_PTR(-ENOMEM);
 
 	dev = netdev_priv(net);
 	spin_lock_init(&dev->lock);
@@ -807,12 +801,11 @@ int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
 	if (status < 0) {
 		dev_dbg(&g->dev, "register_netdev failed, %d\n", status);
 		free_netdev(net);
+		dev = ERR_PTR(status);
 	} else {
 		INFO(dev, "MAC %pM\n", net->dev_addr);
 		INFO(dev, "HOST MAC %pM\n", dev->host_mac);
 
-		the_dev = dev;
-
 		/* two kinds of host-initiated state changes:
 		 *  - iff DATA transfer is active, carrier is "on"
 		 *  - tx queueing enabled if open *and* carrier is "on"
@@ -820,7 +813,7 @@ int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
 		netif_carrier_off(net);
 	}
 
-	return status;
+	return dev;
 }
 
 /**
@@ -829,19 +822,16 @@ int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
  *
  * This is called to free all resources allocated by @gether_setup().
  */
-void gether_cleanup(void)
+void gether_cleanup(struct eth_dev *dev)
 {
-	if (!the_dev)
+	if (!dev)
 		return;
 
-	unregister_netdev(the_dev->net);
-	flush_work(&the_dev->work);
-	free_netdev(the_dev->net);
-
-	the_dev = NULL;
+	unregister_netdev(dev->net);
+	flush_work(&dev->work);
+	free_netdev(dev->net);
 }
 
-
 /**
  * gether_connect - notify network layer that USB link is active
  * @link: the USB link, set up with endpoints, descriptors matching
@@ -860,7 +850,7 @@ void gether_cleanup(void)
  */
 struct net_device *gether_connect(struct gether *link)
 {
-	struct eth_dev		*dev = the_dev;
+	struct eth_dev		*dev = link->ioport;
 	int			result = 0;
 
 	if (!dev)
@@ -895,7 +885,6 @@ struct net_device *gether_connect(struct gether *link)
 
 		spin_lock(&dev->lock);
 		dev->port_usb = link;
-		link->ioport = dev;
 		if (netif_running(dev->net)) {
 			if (link->open)
 				link->open(link);
@@ -989,6 +978,5 @@ void gether_disconnect(struct gether *link)
 
 	spin_lock(&dev->lock);
 	dev->port_usb = NULL;
-	link->ioport = NULL;
 	spin_unlock(&dev->lock);
 }
diff --git a/drivers/usb/gadget/u_ether.h b/drivers/usb/gadget/u_ether.h
index 6f4a162..0252233 100644
--- a/drivers/usb/gadget/u_ether.h
+++ b/drivers/usb/gadget/u_ether.h
@@ -21,6 +21,7 @@
 
 #include "gadget_chips.h"
 
+struct eth_dev;
 
 /*
  * This represents the USB side of an "ethernet" link, managed by a USB
@@ -70,7 +71,7 @@ struct gether {
 			|USB_CDC_PACKET_TYPE_DIRECTED)
 
 /* variant of gether_setup that allows customizing network device name */
-int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
+struct eth_dev *gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
 		const char *netname);
 
 /* netdev setup/teardown as directed by the gadget driver */
@@ -86,12 +87,13 @@ int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
  *
  * Returns negative errno, or zero on success
  */
-static inline int gether_setup(struct usb_gadget *g, u8 ethaddr[ETH_ALEN])
+static inline struct eth_dev *gether_setup(struct usb_gadget *g,
+		u8 ethaddr[ETH_ALEN])
 {
 	return gether_setup_name(g, ethaddr, "usb");
 }
 
-void gether_cleanup(void);
+void gether_cleanup(struct eth_dev *dev);
 
 /* connect/disconnect is handled by individual functions */
 struct net_device *gether_connect(struct gether *);
@@ -111,21 +113,24 @@ static inline bool can_support_ecm(struct usb_gadget *gadget)
 }
 
 /* each configuration may bind one instance of an ethernet link */
-int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]);
-int ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]);
-int ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]);
-int eem_bind_config(struct usb_configuration *c);
+int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
+		struct eth_dev *dev);
+int ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
+		struct eth_dev *dev);
+int ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
+		struct eth_dev *dev);
+int eem_bind_config(struct usb_configuration *c, struct eth_dev *dev);
 
 #ifdef USB_ETH_RNDIS
 
 int rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
-				u32 vendorID, const char *manufacturer);
+		u32 vendorID, const char *manufacturer, struct eth_dev *dev);
 
 #else
 
 static inline int
 rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
-				u32 vendorID, const char *manufacturer)
+		u32 vendorID, const char *manufacturer, struct eth_dev *dev)
 {
 	return 0;
 }
@@ -145,9 +150,9 @@ rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
  * for calling @gether_cleanup() before module unload.
  */
 static inline int rndis_bind_config(struct usb_configuration *c,
-				    u8 ethaddr[ETH_ALEN])
+		u8 ethaddr[ETH_ALEN], struct eth_dev *dev)
 {
-	return rndis_bind_config_vendor(c, ethaddr, 0, NULL);
+	return rndis_bind_config_vendor(c, ethaddr, 0, NULL, dev);
 }
 
 
diff --git a/drivers/usb/gadget/u_serial.h b/drivers/usb/gadget/u_serial.h
index 66ce73a..c20210c 100644
--- a/drivers/usb/gadget/u_serial.h
+++ b/drivers/usb/gadget/u_serial.h
@@ -65,7 +65,6 @@ int gserial_connect(struct gserial *, u8 port_num);
 void gserial_disconnect(struct gserial *);
 
 /* functions are bound to configurations by a config or gadget driver */
-int acm_bind_config(struct usb_configuration *c, u8 port_num);
 int gser_bind_config(struct usb_configuration *c, u8 port_num);
 int obex_bind_config(struct usb_configuration *c, u8 port_num);
 
diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c
index f8f62c3..ffd8fa5 100644
--- a/drivers/usb/gadget/udc-core.c
+++ b/drivers/usb/gadget/udc-core.c
@@ -101,6 +101,16 @@ EXPORT_SYMBOL_GPL(usb_gadget_unmap_request);
 
 /* ------------------------------------------------------------------------- */
 
+void usb_gadget_set_state(struct usb_gadget *gadget,
+		enum usb_device_state state)
+{
+	gadget->state = state;
+	sysfs_notify(&gadget->dev.kobj, NULL, "status");
+}
+EXPORT_SYMBOL_GPL(usb_gadget_set_state);
+
+/* ------------------------------------------------------------------------- */
+
 /**
  * usb_gadget_udc_start - tells usb device controller to start up
  * @gadget: The gadget we want to get started
@@ -156,15 +166,23 @@ static void usb_udc_release(struct device *dev)
 }
 
 static const struct attribute_group *usb_udc_attr_groups[];
+
+static void usb_udc_nop_release(struct device *dev)
+{
+	dev_vdbg(dev, "%s\n", __func__);
+}
+
 /**
- * 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
+ * usb_add_gadget_udc_release - 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.
+ * @release: a gadget release function.
  *
  * Returns zero on success, negative errno otherwise.
  */
-int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget)
+int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget,
+		void (*release)(struct device *dev))
 {
 	struct usb_udc		*udc;
 	int			ret = -ENOMEM;
@@ -173,6 +191,22 @@ int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget)
 	if (!udc)
 		goto err1;
 
+	dev_set_name(&gadget->dev, "gadget");
+	gadget->dev.parent = parent;
+
+	dma_set_coherent_mask(&gadget->dev, parent->coherent_dma_mask);
+	gadget->dev.dma_parms = parent->dma_parms;
+	gadget->dev.dma_mask = parent->dma_mask;
+
+	if (release)
+		gadget->dev.release = release;
+	else
+		gadget->dev.release = usb_udc_nop_release;
+
+	ret = device_register(&gadget->dev);
+	if (ret)
+		goto err2;
+
 	device_initialize(&udc->dev);
 	udc->dev.release = usb_udc_release;
 	udc->dev.class = udc_class;
@@ -180,7 +214,7 @@ int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget)
 	udc->dev.parent = parent;
 	ret = dev_set_name(&udc->dev, "%s", kobject_name(&parent->kobj));
 	if (ret)
-		goto err2;
+		goto err3;
 
 	udc->gadget = gadget;
 
@@ -189,21 +223,42 @@ int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget)
 
 	ret = device_add(&udc->dev);
 	if (ret)
-		goto err3;
+		goto err4;
+
+	usb_gadget_set_state(gadget, USB_STATE_NOTATTACHED);
 
 	mutex_unlock(&udc_lock);
 
 	return 0;
-err3:
+
+err4:
 	list_del(&udc->list);
 	mutex_unlock(&udc_lock);
 
-err2:
+err3:
 	put_device(&udc->dev);
 
+err2:
+	put_device(&gadget->dev);
+	kfree(udc);
+
 err1:
 	return ret;
 }
+EXPORT_SYMBOL_GPL(usb_add_gadget_udc_release);
+
+/**
+ * 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)
+{
+	return usb_add_gadget_udc_release(parent, gadget, NULL);
+}
 EXPORT_SYMBOL_GPL(usb_add_gadget_udc);
 
 static void usb_gadget_remove_driver(struct usb_udc *udc)
@@ -220,6 +275,7 @@ static void usb_gadget_remove_driver(struct usb_udc *udc)
 
 	udc->driver = NULL;
 	udc->dev.driver = NULL;
+	udc->gadget->dev.driver = NULL;
 }
 
 /**
@@ -254,6 +310,7 @@ found:
 
 	kobject_uevent(&udc->dev.kobj, KOBJ_REMOVE);
 	device_unregister(&udc->dev);
+	device_unregister(&gadget->dev);
 }
 EXPORT_SYMBOL_GPL(usb_del_gadget_udc);
 
@@ -268,6 +325,7 @@ static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *dri
 
 	udc->driver = driver;
 	udc->dev.driver = &driver->driver;
+	udc->gadget->dev.driver = &driver->driver;
 
 	ret = driver->bind(udc->gadget, driver);
 	if (ret)
@@ -286,6 +344,7 @@ err1:
 			udc->driver->function, ret);
 	udc->driver = NULL;
 	udc->dev.driver = NULL;
+	udc->gadget->dev.driver = NULL;
 	return ret;
 }
 
@@ -395,6 +454,16 @@ static ssize_t usb_udc_softconn_store(struct device *dev,
 }
 static DEVICE_ATTR(soft_connect, S_IWUSR, NULL, usb_udc_softconn_store);
 
+static ssize_t usb_gadget_state_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 sprintf(buf, "%s\n", usb_state_string(gadget->state));
+}
+static DEVICE_ATTR(state, S_IRUGO, usb_gadget_state_show, NULL);
+
 #define USB_UDC_SPEED_ATTR(name, param)					\
 ssize_t usb_udc_##param##_show(struct device *dev,			\
 		struct device_attribute *attr, char *buf)		\
@@ -403,7 +472,7 @@ ssize_t usb_udc_##param##_show(struct device *dev,			\
 	return snprintf(buf, PAGE_SIZE, "%s\n",				\
 			usb_speed_string(udc->gadget->param));		\
 }									\
-static DEVICE_ATTR(name, S_IRUSR, usb_udc_##param##_show, NULL)
+static DEVICE_ATTR(name, S_IRUGO, usb_udc_##param##_show, NULL)
 
 static USB_UDC_SPEED_ATTR(current_speed, speed);
 static USB_UDC_SPEED_ATTR(maximum_speed, max_speed);
@@ -428,6 +497,7 @@ 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_state.attr,
 	&dev_attr_current_speed.attr,
 	&dev_attr_maximum_speed.attr,
 
diff --git a/drivers/usb/gadget/uvc.h b/drivers/usb/gadget/uvc.h
index 93b0c11..817e9e1 100644
--- a/drivers/usb/gadget/uvc.h
+++ b/drivers/usb/gadget/uvc.h
@@ -98,8 +98,6 @@ extern unsigned int uvc_gadget_trace_param;
 #define DRIVER_VERSION				"0.1.0"
 #define DRIVER_VERSION_NUMBER			KERNEL_VERSION(0, 1, 0)
 
-#define DMA_ADDR_INVALID			(~(dma_addr_t)0)
-
 #define UVC_NUM_REQUESTS			4
 #define UVC_MAX_REQUEST_SIZE			64
 #define UVC_MAX_EVENTS				4
@@ -190,6 +188,7 @@ struct uvc_file_handle
  * Functions
  */
 
+extern void uvc_function_setup_continue(struct uvc_device *uvc);
 extern void uvc_endpoint_stream(struct uvc_device *dev);
 
 extern void uvc_function_connect(struct uvc_device *uvc);
diff --git a/drivers/usb/gadget/uvc_queue.c b/drivers/usb/gadget/uvc_queue.c
index 104ae9c..7ce27e3 100644
--- a/drivers/usb/gadget/uvc_queue.c
+++ b/drivers/usb/gadget/uvc_queue.c
@@ -10,6 +10,7 @@
  *	(at your option) any later version.
  */
 
+#include <linux/atomic.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/list.h>
@@ -18,7 +19,8 @@
 #include <linux/videodev2.h>
 #include <linux/vmalloc.h>
 #include <linux/wait.h>
-#include <linux/atomic.h>
+
+#include <media/videobuf2-vmalloc.h>
 
 #include "uvc.h"
 
@@ -28,330 +30,175 @@
  * Video queues is initialized by uvc_queue_init(). The function performs
  * basic initialization of the uvc_video_queue struct and never fails.
  *
- * Video buffer allocation and freeing are performed by uvc_alloc_buffers and
- * uvc_free_buffers respectively. The former acquires the video queue lock,
- * while the later must be called with the lock held (so that allocation can
- * free previously allocated buffers). Trying to free buffers that are mapped
- * to user space will return -EBUSY.
- *
- * Video buffers are managed using two queues. However, unlike most USB video
- * drivers that use an in queue and an out queue, we use a main queue to hold
- * all queued buffers (both 'empty' and 'done' buffers), and an irq queue to
- * hold empty buffers. This design (copied from video-buf) minimizes locking
- * in interrupt, as only one queue is shared between interrupt and user
- * contexts.
- *
- * Use cases
- * ---------
- *
- * Unless stated otherwise, all operations that modify the irq buffers queue
- * are protected by the irq spinlock.
- *
- * 1. The user queues the buffers, starts streaming and dequeues a buffer.
- *
- *    The buffers are added to the main and irq queues. Both operations are
- *    protected by the queue lock, and the later is protected by the irq
- *    spinlock as well.
- *
- *    The completion handler fetches a buffer from the irq queue and fills it
- *    with video data. If no buffer is available (irq queue empty), the handler
- *    returns immediately.
- *
- *    When the buffer is full, the completion handler removes it from the irq
- *    queue, marks it as ready (UVC_BUF_STATE_DONE) and wakes its wait queue.
- *    At that point, any process waiting on the buffer will be woken up. If a
- *    process tries to dequeue a buffer after it has been marked ready, the
- *    dequeing will succeed immediately.
- *
- * 2. Buffers are queued, user is waiting on a buffer and the device gets
- *    disconnected.
- *
- *    When the device is disconnected, the kernel calls the completion handler
- *    with an appropriate status code. The handler marks all buffers in the
- *    irq queue as being erroneous (UVC_BUF_STATE_ERROR) and wakes them up so
- *    that any process waiting on a buffer gets woken up.
- *
- *    Waking up up the first buffer on the irq list is not enough, as the
- *    process waiting on the buffer might restart the dequeue operation
- *    immediately.
- *
+ * Video buffers are managed by videobuf2. The driver uses a mutex to protect
+ * the videobuf2 queue operations by serializing calls to videobuf2 and a
+ * spinlock to protect the IRQ queue that holds the buffers to be processed by
+ * the driver.
  */
 
-static void
-uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type)
-{
-	mutex_init(&queue->mutex);
-	spin_lock_init(&queue->irqlock);
-	INIT_LIST_HEAD(&queue->mainqueue);
-	INIT_LIST_HEAD(&queue->irqqueue);
-	queue->type = type;
-}
-
-/*
- * Free the video buffers.
- *
- * This function must be called with the queue lock held.
+/* -----------------------------------------------------------------------------
+ * videobuf2 queue operations
  */
-static int uvc_free_buffers(struct uvc_video_queue *queue)
+
+static int uvc_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+			   unsigned int *nbuffers, unsigned int *nplanes,
+			   unsigned int sizes[], void *alloc_ctxs[])
 {
-	unsigned int i;
+	struct uvc_video_queue *queue = vb2_get_drv_priv(vq);
+	struct uvc_video *video = container_of(queue, struct uvc_video, queue);
 
-	for (i = 0; i < queue->count; ++i) {
-		if (queue->buffer[i].vma_use_count != 0)
-			return -EBUSY;
-	}
+	if (*nbuffers > UVC_MAX_VIDEO_BUFFERS)
+		*nbuffers = UVC_MAX_VIDEO_BUFFERS;
 
-	if (queue->count) {
-		vfree(queue->mem);
-		queue->count = 0;
-	}
+	*nplanes = 1;
+
+	sizes[0] = video->imagesize;
 
 	return 0;
 }
 
-/*
- * Allocate the video buffers.
- *
- * Pages are reserved to make sure they will not be swapped, as they will be
- * filled in the URB completion handler.
- *
- * Buffers will be individually mapped, so they must all be page aligned.
- */
-static int
-uvc_alloc_buffers(struct uvc_video_queue *queue, unsigned int nbuffers,
-		  unsigned int buflength)
+static int uvc_buffer_prepare(struct vb2_buffer *vb)
 {
-	unsigned int bufsize = PAGE_ALIGN(buflength);
-	unsigned int i;
-	void *mem = NULL;
-	int ret;
+	struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue);
+	struct uvc_buffer *buf = container_of(vb, struct uvc_buffer, buf);
 
-	if (nbuffers > UVC_MAX_VIDEO_BUFFERS)
-		nbuffers = UVC_MAX_VIDEO_BUFFERS;
+	if (vb->v4l2_buf.type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+	    vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) {
+		uvc_trace(UVC_TRACE_CAPTURE, "[E] Bytes used out of bounds.\n");
+		return -EINVAL;
+	}
 
-	mutex_lock(&queue->mutex);
+	if (unlikely(queue->flags & UVC_QUEUE_DISCONNECTED))
+		return -ENODEV;
 
-	if ((ret = uvc_free_buffers(queue)) < 0)
-		goto done;
+	buf->state = UVC_BUF_STATE_QUEUED;
+	buf->mem = vb2_plane_vaddr(vb, 0);
+	buf->length = vb2_plane_size(vb, 0);
+	if (vb->v4l2_buf.type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		buf->bytesused = 0;
+	else
+		buf->bytesused = vb2_get_plane_payload(vb, 0);
 
-	/* Bail out if no buffers should be allocated. */
-	if (nbuffers == 0)
-		goto done;
+	return 0;
+}
 
-	/* Decrement the number of buffers until allocation succeeds. */
-	for (; nbuffers > 0; --nbuffers) {
-		mem = vmalloc_32(nbuffers * bufsize);
-		if (mem != NULL)
-			break;
-	}
+static void uvc_buffer_queue(struct vb2_buffer *vb)
+{
+	struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue);
+	struct uvc_buffer *buf = container_of(vb, struct uvc_buffer, buf);
+	unsigned long flags;
 
-	if (mem == NULL) {
-		ret = -ENOMEM;
-		goto done;
-	}
+	spin_lock_irqsave(&queue->irqlock, flags);
 
-	for (i = 0; i < nbuffers; ++i) {
-		memset(&queue->buffer[i], 0, sizeof queue->buffer[i]);
-		queue->buffer[i].buf.index = i;
-		queue->buffer[i].buf.m.offset = i * bufsize;
-		queue->buffer[i].buf.length = buflength;
-		queue->buffer[i].buf.type = queue->type;
-		queue->buffer[i].buf.sequence = 0;
-		queue->buffer[i].buf.field = V4L2_FIELD_NONE;
-		queue->buffer[i].buf.memory = V4L2_MEMORY_MMAP;
-		queue->buffer[i].buf.flags = 0;
-		init_waitqueue_head(&queue->buffer[i].wait);
+	if (likely(!(queue->flags & UVC_QUEUE_DISCONNECTED))) {
+		list_add_tail(&buf->queue, &queue->irqqueue);
+	} else {
+		/* If the device is disconnected return the buffer to userspace
+		 * directly. The next QBUF call will fail with -ENODEV.
+		 */
+		buf->state = UVC_BUF_STATE_ERROR;
+		vb2_buffer_done(&buf->buf, VB2_BUF_STATE_ERROR);
 	}
 
-	queue->mem = mem;
-	queue->count = nbuffers;
-	queue->buf_size = bufsize;
-	ret = nbuffers;
-
-done:
-	mutex_unlock(&queue->mutex);
-	return ret;
+	spin_unlock_irqrestore(&queue->irqlock, flags);
 }
 
-static void __uvc_query_buffer(struct uvc_buffer *buf,
-		struct v4l2_buffer *v4l2_buf)
-{
-	memcpy(v4l2_buf, &buf->buf, sizeof *v4l2_buf);
-
-	if (buf->vma_use_count)
-		v4l2_buf->flags |= V4L2_BUF_FLAG_MAPPED;
-
-	switch (buf->state) {
-	case UVC_BUF_STATE_ERROR:
-	case UVC_BUF_STATE_DONE:
-		v4l2_buf->flags |= V4L2_BUF_FLAG_DONE;
-		break;
-	case UVC_BUF_STATE_QUEUED:
-	case UVC_BUF_STATE_ACTIVE:
-		v4l2_buf->flags |= V4L2_BUF_FLAG_QUEUED;
-		break;
-	case UVC_BUF_STATE_IDLE:
-	default:
-		break;
-	}
-}
+static struct vb2_ops uvc_queue_qops = {
+	.queue_setup = uvc_queue_setup,
+	.buf_prepare = uvc_buffer_prepare,
+	.buf_queue = uvc_buffer_queue,
+};
 
-static int
-uvc_query_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *v4l2_buf)
+static int uvc_queue_init(struct uvc_video_queue *queue,
+			  enum v4l2_buf_type type)
 {
-	int ret = 0;
+	int ret;
 
-	mutex_lock(&queue->mutex);
-	if (v4l2_buf->index >= queue->count) {
-		ret = -EINVAL;
-		goto done;
-	}
+	queue->queue.type = type;
+	queue->queue.io_modes = VB2_MMAP | VB2_USERPTR;
+	queue->queue.drv_priv = queue;
+	queue->queue.buf_struct_size = sizeof(struct uvc_buffer);
+	queue->queue.ops = &uvc_queue_qops;
+	queue->queue.mem_ops = &vb2_vmalloc_memops;
+	ret = vb2_queue_init(&queue->queue);
+	if (ret)
+		return ret;
+
+	mutex_init(&queue->mutex);
+	spin_lock_init(&queue->irqlock);
+	INIT_LIST_HEAD(&queue->irqqueue);
+	queue->flags = 0;
 
-	__uvc_query_buffer(&queue->buffer[v4l2_buf->index], v4l2_buf);
+	return 0;
+}
 
-done:
+/*
+ * Free the video buffers.
+ */
+static void uvc_free_buffers(struct uvc_video_queue *queue)
+{
+	mutex_lock(&queue->mutex);
+	vb2_queue_release(&queue->queue);
 	mutex_unlock(&queue->mutex);
-	return ret;
 }
 
 /*
- * Queue a video buffer. Attempting to queue a buffer that has already been
- * queued will return -EINVAL.
+ * Allocate the video buffers.
  */
-static int
-uvc_queue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *v4l2_buf)
+static int uvc_alloc_buffers(struct uvc_video_queue *queue,
+			     struct v4l2_requestbuffers *rb)
 {
-	struct uvc_buffer *buf;
-	unsigned long flags;
-	int ret = 0;
+	int ret;
 
-	uvc_trace(UVC_TRACE_CAPTURE, "Queuing buffer %u.\n", v4l2_buf->index);
+	mutex_lock(&queue->mutex);
+	ret = vb2_reqbufs(&queue->queue, rb);
+	mutex_unlock(&queue->mutex);
 
-	if (v4l2_buf->type != queue->type ||
-	    v4l2_buf->memory != V4L2_MEMORY_MMAP) {
-		uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer type (%u) "
-			"and/or memory (%u).\n", v4l2_buf->type,
-			v4l2_buf->memory);
-		return -EINVAL;
-	}
+	return ret ? ret : rb->count;
+}
 
-	mutex_lock(&queue->mutex);
-	if (v4l2_buf->index >= queue->count) {
-		uvc_trace(UVC_TRACE_CAPTURE, "[E] Out of range index.\n");
-		ret = -EINVAL;
-		goto done;
-	}
+static int uvc_query_buffer(struct uvc_video_queue *queue,
+			    struct v4l2_buffer *buf)
+{
+	int ret;
 
-	buf = &queue->buffer[v4l2_buf->index];
-	if (buf->state != UVC_BUF_STATE_IDLE) {
-		uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer state "
-			"(%u).\n", buf->state);
-		ret = -EINVAL;
-		goto done;
-	}
+	mutex_lock(&queue->mutex);
+	ret = vb2_querybuf(&queue->queue, buf);
+	mutex_unlock(&queue->mutex);
 
-	if (v4l2_buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
-	    v4l2_buf->bytesused > buf->buf.length) {
-		uvc_trace(UVC_TRACE_CAPTURE, "[E] Bytes used out of bounds.\n");
-		ret = -EINVAL;
-		goto done;
-	}
+	return ret;
+}
 
-	if (v4l2_buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		buf->buf.bytesused = 0;
-	else
-		buf->buf.bytesused = v4l2_buf->bytesused;
+static int uvc_queue_buffer(struct uvc_video_queue *queue,
+			    struct v4l2_buffer *buf)
+{
+	unsigned long flags;
+	int ret;
 
+	mutex_lock(&queue->mutex);
+	ret = vb2_qbuf(&queue->queue, buf);
 	spin_lock_irqsave(&queue->irqlock, flags);
-	if (queue->flags & UVC_QUEUE_DISCONNECTED) {
-		spin_unlock_irqrestore(&queue->irqlock, flags);
-		ret = -ENODEV;
-		goto done;
-	}
-	buf->state = UVC_BUF_STATE_QUEUED;
-
 	ret = (queue->flags & UVC_QUEUE_PAUSED) != 0;
 	queue->flags &= ~UVC_QUEUE_PAUSED;
-
-	list_add_tail(&buf->stream, &queue->mainqueue);
-	list_add_tail(&buf->queue, &queue->irqqueue);
 	spin_unlock_irqrestore(&queue->irqlock, flags);
-
-done:
 	mutex_unlock(&queue->mutex);
-	return ret;
-}
 
-static int uvc_queue_waiton(struct uvc_buffer *buf, int nonblocking)
-{
-	if (nonblocking) {
-		return (buf->state != UVC_BUF_STATE_QUEUED &&
-			buf->state != UVC_BUF_STATE_ACTIVE)
-			? 0 : -EAGAIN;
-	}
-
-	return wait_event_interruptible(buf->wait,
-		buf->state != UVC_BUF_STATE_QUEUED &&
-		buf->state != UVC_BUF_STATE_ACTIVE);
+	return ret;
 }
 
 /*
  * Dequeue a video buffer. If nonblocking is false, block until a buffer is
  * available.
  */
-static int
-uvc_dequeue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *v4l2_buf,
-		   int nonblocking)
+static int uvc_dequeue_buffer(struct uvc_video_queue *queue,
+			      struct v4l2_buffer *buf, int nonblocking)
 {
-	struct uvc_buffer *buf;
-	int ret = 0;
-
-	if (v4l2_buf->type != queue->type ||
-	    v4l2_buf->memory != V4L2_MEMORY_MMAP) {
-		uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer type (%u) "
-			"and/or memory (%u).\n", v4l2_buf->type,
-			v4l2_buf->memory);
-		return -EINVAL;
-	}
+	int ret;
 
 	mutex_lock(&queue->mutex);
-	if (list_empty(&queue->mainqueue)) {
-		uvc_trace(UVC_TRACE_CAPTURE, "[E] Empty buffer queue.\n");
-		ret = -EINVAL;
-		goto done;
-	}
-
-	buf = list_first_entry(&queue->mainqueue, struct uvc_buffer, stream);
-	if ((ret = uvc_queue_waiton(buf, nonblocking)) < 0)
-		goto done;
-
-	uvc_trace(UVC_TRACE_CAPTURE, "Dequeuing buffer %u (%u, %u bytes).\n",
-		buf->buf.index, buf->state, buf->buf.bytesused);
-
-	switch (buf->state) {
-	case UVC_BUF_STATE_ERROR:
-		uvc_trace(UVC_TRACE_CAPTURE, "[W] Corrupted data "
-			"(transmission error).\n");
-		ret = -EIO;
-	case UVC_BUF_STATE_DONE:
-		buf->state = UVC_BUF_STATE_IDLE;
-		break;
-
-	case UVC_BUF_STATE_IDLE:
-	case UVC_BUF_STATE_QUEUED:
-	case UVC_BUF_STATE_ACTIVE:
-	default:
-		uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer state %u "
-			"(driver bug?).\n", buf->state);
-		ret = -EINVAL;
-		goto done;
-	}
-
-	list_del(&buf->stream);
-	__uvc_query_buffer(buf, v4l2_buf);
-
-done:
+	ret = vb2_dqbuf(&queue->queue, buf, nonblocking);
 	mutex_unlock(&queue->mutex);
+
 	return ret;
 }
 
@@ -361,105 +208,47 @@ done:
  * This function implements video queue polling and is intended to be used by
  * the device poll handler.
  */
-static unsigned int
-uvc_queue_poll(struct uvc_video_queue *queue, struct file *file,
-	       poll_table *wait)
+static unsigned int uvc_queue_poll(struct uvc_video_queue *queue,
+				   struct file *file, poll_table *wait)
 {
-	struct uvc_buffer *buf;
-	unsigned int mask = 0;
+	unsigned int ret;
 
 	mutex_lock(&queue->mutex);
-	if (list_empty(&queue->mainqueue))
-		goto done;
-
-	buf = list_first_entry(&queue->mainqueue, struct uvc_buffer, stream);
-
-	poll_wait(file, &buf->wait, wait);
-	if (buf->state == UVC_BUF_STATE_DONE ||
-	    buf->state == UVC_BUF_STATE_ERROR)
-		mask |= POLLOUT | POLLWRNORM;
-
-done:
+	ret = vb2_poll(&queue->queue, file, wait);
 	mutex_unlock(&queue->mutex);
-	return mask;
-}
 
-/*
- * VMA operations.
- */
-static void uvc_vm_open(struct vm_area_struct *vma)
-{
-	struct uvc_buffer *buffer = vma->vm_private_data;
-	buffer->vma_use_count++;
+	return ret;
 }
 
-static void uvc_vm_close(struct vm_area_struct *vma)
+static int uvc_queue_mmap(struct uvc_video_queue *queue,
+			  struct vm_area_struct *vma)
 {
-	struct uvc_buffer *buffer = vma->vm_private_data;
-	buffer->vma_use_count--;
-}
+	int ret;
 
-static struct vm_operations_struct uvc_vm_ops = {
-	.open		= uvc_vm_open,
-	.close		= uvc_vm_close,
-};
+	mutex_lock(&queue->mutex);
+	ret = vb2_mmap(&queue->queue, vma);
+	mutex_unlock(&queue->mutex);
+
+	return ret;
+}
 
+#ifndef CONFIG_MMU
 /*
- * Memory-map a buffer.
+ * Get unmapped area.
  *
- * This function implements video buffer memory mapping and is intended to be
- * used by the device mmap handler.
+ * NO-MMU arch need this function to make mmap() work correctly.
  */
-static int
-uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma)
+static unsigned long uvc_queue_get_unmapped_area(struct uvc_video_queue *queue,
+		unsigned long pgoff)
 {
-	struct uvc_buffer *uninitialized_var(buffer);
-	struct page *page;
-	unsigned long addr, start, size;
-	unsigned int i;
-	int ret = 0;
-
-	start = vma->vm_start;
-	size = vma->vm_end - vma->vm_start;
+	unsigned long ret;
 
 	mutex_lock(&queue->mutex);
-
-	for (i = 0; i < queue->count; ++i) {
-		buffer = &queue->buffer[i];
-		if ((buffer->buf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff)
-			break;
-	}
-
-	if (i == queue->count || size != queue->buf_size) {
-		ret = -EINVAL;
-		goto done;
-	}
-
-	/*
-	 * VM_IO marks the area as being an mmaped region for I/O to a
-	 * device. It also prevents the region from being core dumped.
-	 */
-	vma->vm_flags |= VM_IO;
-
-	addr = (unsigned long)queue->mem + buffer->buf.m.offset;
-	while (size > 0) {
-		page = vmalloc_to_page((void *)addr);
-		if ((ret = vm_insert_page(vma, start, page)) < 0)
-			goto done;
-
-		start += PAGE_SIZE;
-		addr += PAGE_SIZE;
-		size -= PAGE_SIZE;
-	}
-
-	vma->vm_ops = &uvc_vm_ops;
-	vma->vm_private_data = buffer;
-	uvc_vm_open(vma);
-
-done:
+	ret = vb2_get_unmapped_area(&queue->queue, 0, 0, pgoff, 0);
 	mutex_unlock(&queue->mutex);
 	return ret;
 }
+#endif
 
 /*
  * Cancel the video buffers queue.
@@ -484,7 +273,7 @@ static void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect)
 				       queue);
 		list_del(&buf->queue);
 		buf->state = UVC_BUF_STATE_ERROR;
-		wake_up(&buf->wait);
+		vb2_buffer_done(&buf->buf, VB2_BUF_STATE_ERROR);
 	}
 	/* This must be protected by the irqlock spinlock to avoid race
 	 * conditions between uvc_queue_buffer and the disconnection event that
@@ -516,26 +305,33 @@ static void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect)
  */
 static int uvc_queue_enable(struct uvc_video_queue *queue, int enable)
 {
-	unsigned int i;
+	unsigned long flags;
 	int ret = 0;
 
 	mutex_lock(&queue->mutex);
 	if (enable) {
-		if (uvc_queue_streaming(queue)) {
-			ret = -EBUSY;
+		ret = vb2_streamon(&queue->queue, queue->queue.type);
+		if (ret < 0)
 			goto done;
-		}
+
 		queue->sequence = 0;
-		queue->flags |= UVC_QUEUE_STREAMING;
 		queue->buf_used = 0;
 	} else {
-		uvc_queue_cancel(queue, 0);
-		INIT_LIST_HEAD(&queue->mainqueue);
+		ret = vb2_streamoff(&queue->queue, queue->queue.type);
+		if (ret < 0)
+			goto done;
 
-		for (i = 0; i < queue->count; ++i)
-			queue->buffer[i].state = UVC_BUF_STATE_IDLE;
+		spin_lock_irqsave(&queue->irqlock, flags);
+		INIT_LIST_HEAD(&queue->irqqueue);
 
-		queue->flags &= ~UVC_QUEUE_STREAMING;
+		/*
+		 * FIXME: We need to clear the DISCONNECTED flag to ensure that
+		 * applications will be able to queue buffers for the next
+		 * streaming run. However, clearing it here doesn't guarantee
+		 * that the device will be reconnected in the meantime.
+		 */
+		queue->flags &= ~UVC_QUEUE_DISCONNECTED;
+		spin_unlock_irqrestore(&queue->irqlock, flags);
 	}
 
 done:
@@ -544,15 +340,15 @@ done:
 }
 
 /* called with &queue_irqlock held.. */
-static struct uvc_buffer *
-uvc_queue_next_buffer(struct uvc_video_queue *queue, struct uvc_buffer *buf)
+static struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue,
+						struct uvc_buffer *buf)
 {
 	struct uvc_buffer *nextbuf;
 
 	if ((queue->flags & UVC_QUEUE_DROP_INCOMPLETE) &&
-	    buf->buf.length != buf->buf.bytesused) {
+	     buf->length != buf->bytesused) {
 		buf->state = UVC_BUF_STATE_QUEUED;
-		buf->buf.bytesused = 0;
+		vb2_set_plane_payload(&buf->buf, 0, 0);
 		return buf;
 	}
 
@@ -563,10 +359,18 @@ uvc_queue_next_buffer(struct uvc_video_queue *queue, struct uvc_buffer *buf)
 	else
 		nextbuf = NULL;
 
-	buf->buf.sequence = queue->sequence++;
-	do_gettimeofday(&buf->buf.timestamp);
+	/*
+	 * FIXME: with videobuf2, the sequence number or timestamp fields
+	 * are valid only for video capture devices and the UVC gadget usually
+	 * is a video output device. Keeping these until the specs are clear on
+	 * this aspect.
+	 */
+	buf->buf.v4l2_buf.sequence = queue->sequence++;
+	do_gettimeofday(&buf->buf.v4l2_buf.timestamp);
+
+	vb2_set_plane_payload(&buf->buf, 0, buf->bytesused);
+	vb2_buffer_done(&buf->buf, VB2_BUF_STATE_DONE);
 
-	wake_up(&buf->wait);
 	return nextbuf;
 }
 
diff --git a/drivers/usb/gadget/uvc_queue.h b/drivers/usb/gadget/uvc_queue.h
index 1812a8e..8e76ce9 100644
--- a/drivers/usb/gadget/uvc_queue.h
+++ b/drivers/usb/gadget/uvc_queue.h
@@ -6,6 +6,7 @@
 #include <linux/kernel.h>
 #include <linux/poll.h>
 #include <linux/videodev2.h>
+#include <media/videobuf2-core.h>
 
 /* Maximum frame size in bytes, for sanity checking. */
 #define UVC_MAX_FRAME_SIZE	(16*1024*1024)
@@ -25,42 +26,35 @@ enum uvc_buffer_state {
 };
 
 struct uvc_buffer {
-	unsigned long vma_use_count;
-	struct list_head stream;
-
-	/* Touched by interrupt handler. */
-	struct v4l2_buffer buf;
+	struct vb2_buffer buf;
 	struct list_head queue;
-	wait_queue_head_t wait;
+
 	enum uvc_buffer_state state;
+	void *mem;
+	unsigned int length;
+	unsigned int bytesused;
 };
 
-#define UVC_QUEUE_STREAMING		(1 << 0)
-#define UVC_QUEUE_DISCONNECTED		(1 << 1)
-#define UVC_QUEUE_DROP_INCOMPLETE	(1 << 2)
-#define UVC_QUEUE_PAUSED		(1 << 3)
+#define UVC_QUEUE_DISCONNECTED		(1 << 0)
+#define UVC_QUEUE_DROP_INCOMPLETE	(1 << 1)
+#define UVC_QUEUE_PAUSED		(1 << 2)
 
 struct uvc_video_queue {
-	enum v4l2_buf_type type;
+	struct vb2_queue queue;
+	struct mutex mutex;	/* Protects queue */
 
-	void *mem;
 	unsigned int flags;
 	__u32 sequence;
 
-	unsigned int count;
-	unsigned int buf_size;
 	unsigned int buf_used;
-	struct uvc_buffer buffer[UVC_MAX_VIDEO_BUFFERS];
-	struct mutex mutex;	/* protects buffers and mainqueue */
-	spinlock_t irqlock;	/* protects irqqueue */
 
-	struct list_head mainqueue;
+	spinlock_t irqlock;	/* Protects flags and irqqueue */
 	struct list_head irqqueue;
 };
 
 static inline int uvc_queue_streaming(struct uvc_video_queue *queue)
 {
-	return queue->flags & UVC_QUEUE_STREAMING;
+	return vb2_is_streaming(&queue->queue);
 }
 
 #endif /* __KERNEL__ */
diff --git a/drivers/usb/gadget/uvc_v4l2.c b/drivers/usb/gadget/uvc_v4l2.c
index 2ca9386..ad48e81 100644
--- a/drivers/usb/gadget/uvc_v4l2.c
+++ b/drivers/usb/gadget/uvc_v4l2.c
@@ -41,9 +41,8 @@ uvc_send_response(struct uvc_device *uvc, struct uvc_request_data *data)
 
 	req->length = min_t(unsigned int, uvc->event_length, data->length);
 	req->zero = data->length < uvc->event_length;
-	req->dma = DMA_ADDR_INVALID;
 
-	memcpy(req->buf, data->data, data->length);
+	memcpy(req->buf, data->data, req->length);
 
 	return usb_ep_queue(cdev->gadget->ep0, req, GFP_KERNEL);
 }
@@ -148,16 +147,13 @@ uvc_v4l2_release(struct file *file)
 	uvc_function_disconnect(uvc);
 
 	uvc_video_enable(video, 0);
-	mutex_lock(&video->queue.mutex);
-	if (uvc_free_buffers(&video->queue) < 0)
-		printk(KERN_ERR "uvc_v4l2_release: Unable to free "
-				"buffers.\n");
-	mutex_unlock(&video->queue.mutex);
+	uvc_free_buffers(&video->queue);
 
 	file->private_data = NULL;
 	v4l2_fh_del(&handle->vfh);
 	v4l2_fh_exit(&handle->vfh);
 	kfree(handle);
+
 	return 0;
 }
 
@@ -178,9 +174,9 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 		struct v4l2_capability *cap = arg;
 
 		memset(cap, 0, sizeof *cap);
-		strncpy(cap->driver, "g_uvc", sizeof(cap->driver));
-		strncpy(cap->card, cdev->gadget->name, sizeof(cap->card));
-		strncpy(cap->bus_info, dev_name(&cdev->gadget->dev),
+		strlcpy(cap->driver, "g_uvc", sizeof(cap->driver));
+		strlcpy(cap->card, cdev->gadget->name, sizeof(cap->card));
+		strlcpy(cap->bus_info, dev_name(&cdev->gadget->dev),
 			sizeof cap->bus_info);
 		cap->version = DRIVER_VERSION_NUMBER;
 		cap->capabilities = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
@@ -192,7 +188,7 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 	{
 		struct v4l2_format *fmt = arg;
 
-		if (fmt->type != video->queue.type)
+		if (fmt->type != video->queue.queue.type)
 			return -EINVAL;
 
 		return uvc_v4l2_get_format(video, fmt);
@@ -202,7 +198,7 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 	{
 		struct v4l2_format *fmt = arg;
 
-		if (fmt->type != video->queue.type)
+		if (fmt->type != video->queue.queue.type)
 			return -EINVAL;
 
 		return uvc_v4l2_set_format(video, fmt);
@@ -213,16 +209,13 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 	{
 		struct v4l2_requestbuffers *rb = arg;
 
-		if (rb->type != video->queue.type ||
-		    rb->memory != V4L2_MEMORY_MMAP)
+		if (rb->type != video->queue.queue.type)
 			return -EINVAL;
 
-		ret = uvc_alloc_buffers(&video->queue, rb->count,
-					video->imagesize);
+		ret = uvc_alloc_buffers(&video->queue, rb);
 		if (ret < 0)
 			return ret;
 
-		rb->count = ret;
 		ret = 0;
 		break;
 	}
@@ -231,9 +224,6 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 	{
 		struct v4l2_buffer *buf = arg;
 
-		if (buf->type != video->queue.type)
-			return -EINVAL;
-
 		return uvc_query_buffer(&video->queue, buf);
 	}
 
@@ -251,24 +241,36 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 	{
 		int *type = arg;
 
-		if (*type != video->queue.type)
+		if (*type != video->queue.queue.type)
 			return -EINVAL;
 
-		return uvc_video_enable(video, 1);
+		/* Enable UVC video. */
+		ret = uvc_video_enable(video, 1);
+		if (ret < 0)
+			return ret;
+
+		/*
+		 * Complete the alternate setting selection setup phase now that
+		 * userspace is ready to provide video frames.
+		 */
+		uvc_function_setup_continue(uvc);
+		uvc->state = UVC_STATE_STREAMING;
+
+		return 0;
 	}
 
 	case VIDIOC_STREAMOFF:
 	{
 		int *type = arg;
 
-		if (*type != video->queue.type)
+		if (*type != video->queue.queue.type)
 			return -EINVAL;
 
 		return uvc_video_enable(video, 0);
 	}
 
 	/* Events */
-        case VIDIOC_DQEVENT:
+	case VIDIOC_DQEVENT:
 	{
 		struct v4l2_event *event = arg;
 
@@ -333,17 +335,21 @@ uvc_v4l2_poll(struct file *file, poll_table *wait)
 {
 	struct video_device *vdev = video_devdata(file);
 	struct uvc_device *uvc = video_get_drvdata(vdev);
-	struct uvc_file_handle *handle = to_uvc_file_handle(file->private_data);
-	unsigned int mask = 0;
 
-	poll_wait(file, &handle->vfh.wait, wait);
-	if (v4l2_event_pending(&handle->vfh))
-		mask |= POLLPRI;
+	return uvc_queue_poll(&uvc->video.queue, file, wait);
+}
 
-	mask |= uvc_queue_poll(&uvc->video.queue, file, wait);
+#ifndef CONFIG_MMU
+static unsigned long uvc_v4l2_get_unmapped_area(struct file *file,
+		unsigned long addr, unsigned long len, unsigned long pgoff,
+		unsigned long flags)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct uvc_device *uvc = video_get_drvdata(vdev);
 
-	return mask;
+	return uvc_queue_get_unmapped_area(&uvc->video.queue, pgoff);
 }
+#endif
 
 static struct v4l2_file_operations uvc_v4l2_fops = {
 	.owner		= THIS_MODULE,
@@ -352,5 +358,8 @@ static struct v4l2_file_operations uvc_v4l2_fops = {
 	.ioctl		= uvc_v4l2_ioctl,
 	.mmap		= uvc_v4l2_mmap,
 	.poll		= uvc_v4l2_poll,
+#ifndef CONFIG_MMU
+	.get_unmapped_area = uvc_v4l2_get_unmapped_area,
+#endif
 };
 
diff --git a/drivers/usb/gadget/uvc_video.c b/drivers/usb/gadget/uvc_video.c
index b0e53a8..71e896d 100644
--- a/drivers/usb/gadget/uvc_video.c
+++ b/drivers/usb/gadget/uvc_video.c
@@ -32,7 +32,7 @@ uvc_video_encode_header(struct uvc_video *video, struct uvc_buffer *buf,
 	data[0] = 2;
 	data[1] = UVC_STREAM_EOH | video->fid;
 
-	if (buf->buf.bytesused - video->queue.buf_used <= len - 2)
+	if (buf->bytesused - video->queue.buf_used <= len - 2)
 		data[1] |= UVC_STREAM_EOF;
 
 	return 2;
@@ -47,8 +47,8 @@ uvc_video_encode_data(struct uvc_video *video, struct uvc_buffer *buf,
 	void *mem;
 
 	/* Copy video data to the USB buffer. */
-	mem = queue->mem + buf->buf.m.offset + queue->buf_used;
-	nbytes = min((unsigned int)len, buf->buf.bytesused - queue->buf_used);
+	mem = buf->mem + queue->buf_used;
+	nbytes = min((unsigned int)len, buf->bytesused - queue->buf_used);
 
 	memcpy(data, mem, nbytes);
 	queue->buf_used += nbytes;
@@ -82,7 +82,7 @@ uvc_video_encode_bulk(struct usb_request *req, struct uvc_video *video,
 	req->length = video->req_size - len;
 	req->zero = video->payload_size == video->max_payload_size;
 
-	if (buf->buf.bytesused == video->queue.buf_used) {
+	if (buf->bytesused == video->queue.buf_used) {
 		video->queue.buf_used = 0;
 		buf->state = UVC_BUF_STATE_DONE;
 		uvc_queue_next_buffer(&video->queue, buf);
@@ -92,7 +92,7 @@ uvc_video_encode_bulk(struct usb_request *req, struct uvc_video *video,
 	}
 
 	if (video->payload_size == video->max_payload_size ||
-	    buf->buf.bytesused == video->queue.buf_used)
+	    buf->bytesused == video->queue.buf_used)
 		video->payload_size = 0;
 }
 
@@ -115,7 +115,7 @@ uvc_video_encode_isoc(struct usb_request *req, struct uvc_video *video,
 
 	req->length = video->req_size - len;
 
-	if (buf->buf.bytesused == video->queue.buf_used) {
+	if (buf->bytesused == video->queue.buf_used) {
 		video->queue.buf_used = 0;
 		buf->state = UVC_BUF_STATE_DONE;
 		uvc_queue_next_buffer(&video->queue, buf);
@@ -161,6 +161,7 @@ static void
 uvc_video_complete(struct usb_ep *ep, struct usb_request *req)
 {
 	struct uvc_video *video = req->context;
+	struct uvc_video_queue *queue = &video->queue;
 	struct uvc_buffer *buf;
 	unsigned long flags;
 	int ret;
@@ -169,13 +170,15 @@ uvc_video_complete(struct usb_ep *ep, struct usb_request *req)
 	case 0:
 		break;
 
-	case -ESHUTDOWN:
+	case -ESHUTDOWN:	/* disconnect from host. */
 		printk(KERN_INFO "VS request cancelled.\n");
+		uvc_queue_cancel(queue, 1);
 		goto requeue;
 
 	default:
 		printk(KERN_INFO "VS request completed with status %d.\n",
 			req->status);
+		uvc_queue_cancel(queue, 0);
 		goto requeue;
 	}
 
@@ -229,13 +232,18 @@ uvc_video_free_requests(struct uvc_video *video)
 static int
 uvc_video_alloc_requests(struct uvc_video *video)
 {
+	unsigned int req_size;
 	unsigned int i;
 	int ret = -ENOMEM;
 
 	BUG_ON(video->req_size);
 
+	req_size = video->ep->maxpacket
+		 * max_t(unsigned int, video->ep->maxburst, 1)
+		 * (video->ep->mult + 1);
+
 	for (i = 0; i < UVC_NUM_REQUESTS; ++i) {
-		video->req_buffer[i] = kmalloc(video->ep->maxpacket, GFP_KERNEL);
+		video->req_buffer[i] = kmalloc(req_size, GFP_KERNEL);
 		if (video->req_buffer[i] == NULL)
 			goto error;
 
@@ -245,14 +253,14 @@ uvc_video_alloc_requests(struct uvc_video *video)
 
 		video->req[i]->buf = video->req_buffer[i];
 		video->req[i]->length = 0;
-		video->req[i]->dma = DMA_ADDR_INVALID;
 		video->req[i]->complete = uvc_video_complete;
 		video->req[i]->context = video;
 
 		list_add_tail(&video->req[i]->list, &video->req_free);
 	}
 
-	video->req_size = video->ep->maxpacket;
+	video->req_size = req_size;
+
 	return 0;
 
 error:
@@ -309,7 +317,8 @@ uvc_video_pump(struct uvc_video *video)
 		video->encode(req, video, buf);
 
 		/* Queue the USB request */
-		if ((ret = usb_ep_queue(video->ep, req, GFP_KERNEL)) < 0) {
+		ret = usb_ep_queue(video->ep, req, GFP_ATOMIC);
+		if (ret < 0) {
 			printk(KERN_INFO "Failed to queue request (%d)\n", ret);
 			usb_ep_set_halt(video->ep);
 			spin_unlock_irqrestore(&video->queue.irqlock, flags);
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index c59a112..f7af098 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -155,8 +155,9 @@ config USB_EHCI_MXC
 	  Variation of ARC USB block used in some Freescale chips.
 
 config USB_EHCI_HCD_OMAP
-	bool "EHCI support for OMAP3 and later chips"
+	tristate "EHCI support for OMAP3 and later chips"
 	depends on USB_EHCI_HCD && ARCH_OMAP
+	select NOP_USB_XCEIV
 	default y
 	---help---
 	  Enables support for the on-chip EHCI controller on
@@ -179,6 +180,7 @@ config USB_EHCI_TEGRA
        boolean "NVIDIA Tegra HCD support"
        depends on USB_EHCI_HCD && ARCH_TEGRA
        select USB_EHCI_ROOT_HUB_TT
+       select USB_PHY
        help
          This driver enables support for the internal USB Host Controllers
          found in NVIDIA Tegra SoCs. The controllers are EHCI compliant.
@@ -300,7 +302,6 @@ config USB_OHCI_HCD
 	tristate "OHCI HCD support"
 	depends on USB && USB_ARCH_HAS_OHCI
 	select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3
-	select USB_OTG_UTILS if ARCH_OMAP
 	depends on USB_ISP1301 || !ARCH_LPC32XX
 	---help---
 	  The Open Host Controller Interface (OHCI) is a standard for accessing
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 001fbff..56de410 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -27,6 +27,7 @@ obj-$(CONFIG_USB_EHCI_HCD)	+= ehci-hcd.o
 obj-$(CONFIG_USB_EHCI_PCI)	+= ehci-pci.o
 obj-$(CONFIG_USB_EHCI_HCD_PLATFORM)	+= ehci-platform.o
 obj-$(CONFIG_USB_EHCI_MXC)	+= ehci-mxc.o
+obj-$(CONFIG_USB_EHCI_HCD_OMAP)	+= ehci-omap.o
 
 obj-$(CONFIG_USB_OXU210HP_HCD)	+= oxu210hp-hcd.o
 obj-$(CONFIG_USB_ISP116X_HCD)	+= isp116x-hcd.o
diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
index 70b496d..5429d26 100644
--- a/drivers/usb/host/ehci-dbg.c
+++ b/drivers/usb/host/ehci-dbg.c
@@ -510,14 +510,16 @@ static ssize_t fill_async_buffer(struct debug_buffer *buf)
 	spin_lock_irqsave (&ehci->lock, flags);
 	for (qh = ehci->async->qh_next.qh; size > 0 && qh; qh = qh->qh_next.qh)
 		qh_lines (ehci, qh, &next, &size);
-	if (ehci->async_unlink && size > 0) {
+	if (!list_empty(&ehci->async_unlink) && size > 0) {
 		temp = scnprintf(next, size, "\nunlink =\n");
 		size -= temp;
 		next += temp;
 
-		for (qh = ehci->async_unlink; size > 0 && qh;
-				qh = qh->unlink_next)
-			qh_lines (ehci, qh, &next, &size);
+		list_for_each_entry(qh, &ehci->async_unlink, unlink_node) {
+			if (size <= 0)
+				break;
+			qh_lines(ehci, qh, &next, &size);
+		}
 	}
 	spin_unlock_irqrestore (&ehci->lock, flags);
 
@@ -814,9 +816,10 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf)
 		}
 	}
 
-	if (ehci->async_unlink) {
+	if (!list_empty(&ehci->async_unlink)) {
 		temp = scnprintf(next, size, "async unlink qh %p\n",
-				ehci->async_unlink);
+				list_first_entry(&ehci->async_unlink,
+						struct ehci_qh, unlink_node));
 		size -= temp;
 		next += temp;
 	}
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index d81d2fc..3be3df2 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -370,6 +370,15 @@ static int ehci_fsl_setup(struct usb_hcd *hcd)
 	/* EHCI registers start at offset 0x100 */
 	ehci->caps = hcd->regs + 0x100;
 
+#ifdef CONFIG_PPC_83xx
+	/*
+	 * Deal with MPC834X that need port power to be cycled after the power
+	 * fault condition is removed. Otherwise the state machine does not
+	 * reflect PORTSC[CSC] correctly.
+	 */
+	ehci->need_oc_pp_cycle = 1;
+#endif
+
 	hcd->has_tt = 1;
 
 	retval = ehci_setup(hcd);
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 416a6dc..b12b97d 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -482,6 +482,9 @@ static int ehci_init(struct usb_hcd *hcd)
 	 * periodic_size can shrink by USBCMD update if hcc_params allows.
 	 */
 	ehci->periodic_size = DEFAULT_I_TDPS;
+	INIT_LIST_HEAD(&ehci->async_unlink);
+	INIT_LIST_HEAD(&ehci->async_idle);
+	INIT_LIST_HEAD(&ehci->intr_unlink);
 	INIT_LIST_HEAD(&ehci->intr_qh_list);
 	INIT_LIST_HEAD(&ehci->cached_itd_list);
 	INIT_LIST_HEAD(&ehci->cached_sitd_list);
@@ -749,7 +752,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
 		/* guard against (alleged) silicon errata */
 		if (cmd & CMD_IAAD)
 			ehci_dbg(ehci, "IAA with IAAD still set?\n");
-		if (ehci->async_iaa)
+		if (ehci->iaa_in_progress)
 			COUNT(ehci->stats.iaa);
 		end_unlink_async(ehci);
 	}
@@ -757,7 +760,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
 	/* remote wakeup [4.3.1] */
 	if (status & STS_PCD) {
 		unsigned	i = HCS_N_PORTS (ehci->hcs_params);
-		u32		ppcd = 0;
+		u32		ppcd = ~0;
 
 		/* kick root hub later */
 		pcd_status = status;
@@ -774,7 +777,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
 			int pstatus;
 
 			/* leverage per-port change bits feature */
-			if (ehci->has_ppcd && !(ppcd & (1 << i)))
+			if (!(ppcd & (1 << i)))
 				continue;
 			pstatus = ehci_readl(ehci,
 					 &ehci->regs->port_status[i]);
@@ -896,17 +899,24 @@ static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
 	if (rc)
 		goto done;
 
-	switch (usb_pipetype (urb->pipe)) {
-	// case PIPE_CONTROL:
-	// case PIPE_BULK:
-	default:
+	if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
+		/*
+		 * We don't expedite dequeue for isochronous URBs.
+		 * Just wait until they complete normally or their
+		 * time slot expires.
+		 */
+	} else {
 		qh = (struct ehci_qh *) urb->hcpriv;
-		if (!qh)
-			break;
+		qh->exception = 1;
 		switch (qh->qh_state) {
 		case QH_STATE_LINKED:
+			if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT)
+				start_unlink_intr(ehci, qh);
+			else
+				start_unlink_async(ehci, qh);
+			break;
 		case QH_STATE_COMPLETING:
-			start_unlink_async(ehci, qh);
+			qh->dequeue_during_giveback = 1;
 			break;
 		case QH_STATE_UNLINK:
 		case QH_STATE_UNLINK_WAIT:
@@ -917,33 +927,6 @@ static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
 			qh_completions(ehci, qh);
 			break;
 		}
-		break;
-
-	case PIPE_INTERRUPT:
-		qh = (struct ehci_qh *) urb->hcpriv;
-		if (!qh)
-			break;
-		switch (qh->qh_state) {
-		case QH_STATE_LINKED:
-		case QH_STATE_COMPLETING:
-			start_unlink_intr(ehci, qh);
-			break;
-		case QH_STATE_IDLE:
-			qh_completions (ehci, qh);
-			break;
-		default:
-			ehci_dbg (ehci, "bogus qh %p state %d\n",
-					qh, qh->qh_state);
-			goto done;
-		}
-		break;
-
-	case PIPE_ISOCHRONOUS:
-		// itd or sitd ...
-
-		// wait till next completion, do it then.
-		// completion irqs can wait up to 1024 msec,
-		break;
 	}
 done:
 	spin_unlock_irqrestore (&ehci->lock, flags);
@@ -984,6 +967,7 @@ rescan:
 		goto done;
 	}
 
+	qh->exception = 1;
 	if (ehci->rh_state < EHCI_RH_RUNNING)
 		qh->qh_state = QH_STATE_IDLE;
 	switch (qh->qh_state) {
@@ -1052,13 +1036,12 @@ ehci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
 		usb_settoggle(qh->dev, epnum, is_out, 0);
 		if (!list_empty(&qh->qtd_list)) {
 			WARN_ONCE(1, "clear_halt for a busy endpoint\n");
-		} else if (qh->qh_state == QH_STATE_LINKED ||
-				qh->qh_state == QH_STATE_COMPLETING) {
-
+		} else {
 			/* The toggle value in the QH can't be updated
 			 * while the QH is active.  Unlink it now;
 			 * re-linking will call qh_refresh().
 			 */
+			qh->exception = 1;
 			if (eptype == USB_ENDPOINT_XFER_BULK)
 				start_unlink_async(ehci, qh);
 			else
@@ -1251,11 +1234,6 @@ MODULE_LICENSE ("GPL");
 #define PLATFORM_DRIVER		ehci_hcd_sh_driver
 #endif
 
-#ifdef CONFIG_USB_EHCI_HCD_OMAP
-#include "ehci-omap.c"
-#define        PLATFORM_DRIVER         ehci_hcd_omap_driver
-#endif
-
 #ifdef CONFIG_PPC_PS3
 #include "ehci-ps3.c"
 #define	PS3_SYSTEM_BUS_DRIVER	ps3_ehci_driver
@@ -1291,11 +1269,6 @@ MODULE_LICENSE ("GPL");
 #define PLATFORM_DRIVER		ehci_octeon_driver
 #endif
 
-#ifdef CONFIG_ARCH_VT8500
-#include "ehci-vt8500.c"
-#define	PLATFORM_DRIVER		vt8500_ehci_driver
-#endif
-
 #ifdef CONFIG_PLAT_SPEAR
 #include "ehci-spear.c"
 #define PLATFORM_DRIVER		spear_ehci_hcd_driver
@@ -1345,6 +1318,7 @@ MODULE_LICENSE ("GPL");
 	!IS_ENABLED(CONFIG_USB_EHCI_HCD_PLATFORM) && \
 	!IS_ENABLED(CONFIG_USB_CHIPIDEA_HOST) && \
 	!IS_ENABLED(CONFIG_USB_EHCI_MXC) && \
+	!IS_ENABLED(CONFIG_USB_EHCI_HCD_OMAP) && \
 	!defined(PLATFORM_DRIVER) && \
 	!defined(PS3_SYSTEM_BUS_DRIVER) && \
 	!defined(OF_PLATFORM_DRIVER) && \
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 7d06e77..9ab4a4d 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -464,7 +464,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
 	while (i--) {
 		temp = ehci_readl(ehci, &ehci->regs->port_status [i]);
 		if (test_bit(i, &resume_needed)) {
-			temp &= ~(PORT_RWC_BITS | PORT_RESUME);
+			temp &= ~(PORT_RWC_BITS | PORT_SUSPEND | PORT_RESUME);
 			ehci_writel(ehci, temp, &ehci->regs->port_status [i]);
 			ehci_vdbg (ehci, "resumed port %d\n", i + 1);
 		}
@@ -590,7 +590,7 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
 	u32		mask;
 	int		ports, i, retval = 1;
 	unsigned long	flags;
-	u32		ppcd = 0;
+	u32		ppcd = ~0;
 
 	/* init status to no-changes */
 	buf [0] = 0;
@@ -628,9 +628,10 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
 
 	for (i = 0; i < ports; i++) {
 		/* leverage per-port change bits feature */
-		if (ehci->has_ppcd && !(ppcd & (1 << i)))
-			continue;
-		temp = ehci_readl(ehci, &ehci->regs->port_status [i]);
+		if (ppcd & (1 << i))
+			temp = ehci_readl(ehci, &ehci->regs->port_status[i]);
+		else
+			temp = 0;
 
 		/*
 		 * Return status information even for ports with OWNER set.
@@ -839,7 +840,8 @@ static int ehci_hub_control (
 			 * power switching; they're allowed to just limit the
 			 * current.  khubd will turn the power back on.
 			 */
-			if ((temp & PORT_OC) && HCS_PPC(ehci->hcs_params)) {
+			if (((temp & PORT_OC) || (ehci->need_oc_pp_cycle))
+					&& HCS_PPC(ehci->hcs_params)) {
 				ehci_writel(ehci,
 					temp & ~(PORT_RWC_BITS | PORT_POWER),
 					status_reg);
@@ -870,10 +872,9 @@ static int ehci_hub_control (
 				usb_hcd_end_port_resume(&hcd->self, wIndex);
 
 				/* stop resume signaling */
-				temp = ehci_readl(ehci, status_reg);
-				ehci_writel(ehci,
-					temp & ~(PORT_RWC_BITS | PORT_RESUME),
-					status_reg);
+				temp &= ~(PORT_RWC_BITS |
+						PORT_SUSPEND | PORT_RESUME);
+				ehci_writel(ehci, temp, status_reg);
 				clear_bit(wIndex, &ehci->resuming_ports);
 				retval = handshake(ehci, status_reg,
 					   PORT_RESUME, 0, 2000 /* 2msec */);
@@ -883,7 +884,7 @@ static int ehci_hub_control (
 						wIndex + 1, retval);
 					goto error;
 				}
-				temp &= ~(PORT_SUSPEND|PORT_RESUME|(3<<10));
+				temp = ehci_readl(ehci, status_reg);
 			}
 		}
 
diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c
index 88a49c8..ebf4103 100644
--- a/drivers/usb/host/ehci-msm.c
+++ b/drivers/usb/host/ehci-msm.c
@@ -145,7 +145,7 @@ static int ehci_msm_probe(struct platform_device *pdev)
 	 * management.
 	 */
 	phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
-	if (IS_ERR_OR_NULL(phy)) {
+	if (IS_ERR(phy)) {
 		dev_err(&pdev->dev, "unable to find transceiver\n");
 		ret = -ENODEV;
 		goto put_hcd;
diff --git a/drivers/usb/host/ehci-mv.c b/drivers/usb/host/ehci-mv.c
index 3065809..4020629 100644
--- a/drivers/usb/host/ehci-mv.c
+++ b/drivers/usb/host/ehci-mv.c
@@ -33,25 +33,17 @@ struct ehci_hcd_mv {
 
 	struct mv_usb_platform_data *pdata;
 
-	/* clock source and total clock number */
-	unsigned int clknum;
-	struct clk *clk[0];
+	struct clk *clk;
 };
 
 static void ehci_clock_enable(struct ehci_hcd_mv *ehci_mv)
 {
-	unsigned int i;
-
-	for (i = 0; i < ehci_mv->clknum; i++)
-		clk_prepare_enable(ehci_mv->clk[i]);
+	clk_prepare_enable(ehci_mv->clk);
 }
 
 static void ehci_clock_disable(struct ehci_hcd_mv *ehci_mv)
 {
-	unsigned int i;
-
-	for (i = 0; i < ehci_mv->clknum; i++)
-		clk_disable_unprepare(ehci_mv->clk[i]);
+	clk_disable_unprepare(ehci_mv->clk);
 }
 
 static int mv_ehci_enable(struct ehci_hcd_mv *ehci_mv)
@@ -144,9 +136,8 @@ static int mv_ehci_probe(struct platform_device *pdev)
 	struct ehci_hcd *ehci;
 	struct ehci_hcd_mv *ehci_mv;
 	struct resource *r;
-	int clk_i, retval = -ENODEV;
+	int retval = -ENODEV;
 	u32 offset;
-	size_t size;
 
 	if (!pdata) {
 		dev_err(&pdev->dev, "missing platform_data\n");
@@ -160,8 +151,7 @@ static int mv_ehci_probe(struct platform_device *pdev)
 	if (!hcd)
 		return -ENOMEM;
 
-	size = sizeof(*ehci_mv) + sizeof(struct clk *) * pdata->clknum;
-	ehci_mv = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
+	ehci_mv = devm_kzalloc(&pdev->dev, sizeof(*ehci_mv), GFP_KERNEL);
 	if (ehci_mv == NULL) {
 		dev_err(&pdev->dev, "cannot allocate ehci_hcd_mv\n");
 		retval = -ENOMEM;
@@ -172,16 +162,11 @@ static int mv_ehci_probe(struct platform_device *pdev)
 	ehci_mv->pdata = pdata;
 	ehci_mv->hcd = hcd;
 
-	ehci_mv->clknum = pdata->clknum;
-	for (clk_i = 0; clk_i < ehci_mv->clknum; clk_i++) {
-		ehci_mv->clk[clk_i] =
-		    devm_clk_get(&pdev->dev, pdata->clkname[clk_i]);
-		if (IS_ERR(ehci_mv->clk[clk_i])) {
-			dev_err(&pdev->dev, "error get clck \"%s\"\n",
-				pdata->clkname[clk_i]);
-			retval = PTR_ERR(ehci_mv->clk[clk_i]);
-			goto err_clear_drvdata;
-		}
+	ehci_mv->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(ehci_mv->clk)) {
+		dev_err(&pdev->dev, "error getting clock\n");
+		retval = PTR_ERR(ehci_mv->clk);
+		goto err_clear_drvdata;
 	}
 
 	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phyregs");
@@ -225,7 +210,7 @@ static int mv_ehci_probe(struct platform_device *pdev)
 		(void __iomem *) ((unsigned long) ehci_mv->cap_regs + offset);
 
 	hcd->rsrc_start = r->start;
-	hcd->rsrc_len = r->end - r->start + 1;
+	hcd->rsrc_len = resource_size(r);
 	hcd->regs = ehci_mv->op_regs;
 
 	hcd->irq = platform_get_irq(pdev, 0);
@@ -240,12 +225,16 @@ static int mv_ehci_probe(struct platform_device *pdev)
 
 	ehci_mv->mode = pdata->mode;
 	if (ehci_mv->mode == MV_USB_MODE_OTG) {
-#ifdef CONFIG_USB_OTG_UTILS
 		ehci_mv->otg = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
-		if (IS_ERR_OR_NULL(ehci_mv->otg)) {
-			dev_err(&pdev->dev,
-				"unable to find transceiver\n");
-			retval = -ENODEV;
+		if (IS_ERR(ehci_mv->otg)) {
+			retval = PTR_ERR(ehci_mv->otg);
+
+			if (retval == -ENXIO)
+				dev_info(&pdev->dev, "MV_USB_MODE_OTG "
+						"must have CONFIG_USB_PHY enabled\n");
+			else
+				dev_err(&pdev->dev,
+						"unable to find transceiver\n");
 			goto err_disable_clk;
 		}
 
@@ -258,11 +247,6 @@ static int mv_ehci_probe(struct platform_device *pdev)
 		}
 		/* otg will enable clock before use as host */
 		mv_ehci_disable(ehci_mv);
-#else
-		dev_info(&pdev->dev, "MV_USB_MODE_OTG "
-			 "must have CONFIG_USB_OTG_UTILS enabled\n");
-		goto err_disable_clk;
-#endif
 	} else {
 		if (pdata->set_vbus)
 			pdata->set_vbus(1);
diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c
index e9301fb..a38c8c8 100644
--- a/drivers/usb/host/ehci-mxc.c
+++ b/drivers/usb/host/ehci-mxc.c
@@ -28,11 +28,7 @@
 #include <linux/slab.h>
 #include <linux/usb.h>
 #include <linux/usb/hcd.h>
-
 #include <linux/platform_data/usb-ehci-mxc.h>
-
-#include <asm/mach-types.h>
-
 #include "ehci.h"
 
 #define DRIVER_DESC "Freescale On-Chip EHCI Host driver"
@@ -61,8 +57,6 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev)
 	struct device *dev = &pdev->dev;
 	struct ehci_hcd *ehci;
 
-	dev_info(&pdev->dev, "initializing i.MX USB Controller\n");
-
 	if (!pdata) {
 		dev_err(dev, "No platform data given, bailing out.\n");
 		return -EINVAL;
@@ -178,7 +172,7 @@ err_alloc:
 	return ret;
 }
 
-static int __exit ehci_mxc_drv_remove(struct platform_device *pdev)
+static int ehci_mxc_drv_remove(struct platform_device *pdev)
 {
 	struct mxc_usbh_platform_data *pdata = pdev->dev.platform_data;
 	struct usb_hcd *hcd = platform_get_drvdata(pdev);
diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
index 0555ee4..5de3e43 100644
--- a/drivers/usb/host/ehci-omap.c
+++ b/drivers/usb/host/ehci-omap.c
@@ -4,10 +4,11 @@
  * Bus Glue for the EHCI controllers in OMAP3/4
  * Tested on several OMAP3 boards, and OMAP4 Pandaboard
  *
- * Copyright (C) 2007-2011 Texas Instruments, Inc.
+ * Copyright (C) 2007-2013 Texas Instruments, Inc.
  *	Author: Vikram Pandita <vikram.pandita@ti.com>
  *	Author: Anand Gadiyar <gadiyar@ti.com>
  *	Author: Keshava Munegowda <keshava_mgowda@ti.com>
+ *	Author: Roger Quadros <rogerq@ti.com>
  *
  * Copyright (C) 2009 Nokia Corporation
  *	Contact: Felipe Balbi <felipe.balbi@nokia.com>
@@ -28,21 +29,23 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  *
- * TODO (last updated Feb 27, 2010):
- *	- add kernel-doc
- *	- enable AUTOIDLE
- *	- add suspend/resume
- *	- add HSIC and TLL support
- *	- convert to use hwmod and runtime PM
  */
 
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/io.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/usb/ulpi.h>
-#include <linux/regulator/consumer.h>
 #include <linux/pm_runtime.h>
 #include <linux/gpio.h>
 #include <linux/clk.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+#include <linux/of.h>
+#include <linux/dma-mapping.h>
+
+#include "ehci.h"
 
 #include <linux/platform_data/usb-omap.h>
 
@@ -57,10 +60,16 @@
 #define	EHCI_INSNREG05_ULPI_EXTREGADD_SHIFT		8
 #define	EHCI_INSNREG05_ULPI_WRDATA_SHIFT		0
 
-/*-------------------------------------------------------------------------*/
+#define DRIVER_DESC "OMAP-EHCI Host Controller driver"
+
+static const char hcd_name[] = "ehci-omap";
 
-static const struct hc_driver ehci_omap_hc_driver;
+/*-------------------------------------------------------------------------*/
 
+struct omap_hcd {
+	struct usb_phy *phy[OMAP3_HS_USB_PORTS]; /* one PHY for each port */
+	int nports;
+};
 
 static inline void ehci_write(void __iomem *base, u32 reg, u32 val)
 {
@@ -72,99 +81,16 @@ static inline u32 ehci_read(void __iomem *base, u32 reg)
 	return __raw_readl(base + reg);
 }
 
+/* configure so an HC device and id are always provided */
+/* always called with process context; sleeping is OK */
 
-static void omap_ehci_soft_phy_reset(struct usb_hcd *hcd, u8 port)
-{
-	unsigned long timeout = jiffies + msecs_to_jiffies(1000);
-	unsigned reg = 0;
-
-	reg = ULPI_FUNC_CTRL_RESET
-		/* FUNCTION_CTRL_SET register */
-		| (ULPI_SET(ULPI_FUNC_CTRL) << EHCI_INSNREG05_ULPI_REGADD_SHIFT)
-		/* Write */
-		| (2 << EHCI_INSNREG05_ULPI_OPSEL_SHIFT)
-		/* PORTn */
-		| ((port + 1) << EHCI_INSNREG05_ULPI_PORTSEL_SHIFT)
-		/* start ULPI access*/
-		| (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT);
-
-	ehci_write(hcd->regs, EHCI_INSNREG05_ULPI, reg);
-
-	/* Wait for ULPI access completion */
-	while ((ehci_read(hcd->regs, EHCI_INSNREG05_ULPI)
-			& (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT))) {
-		cpu_relax();
-
-		if (time_after(jiffies, timeout)) {
-			dev_dbg(hcd->self.controller,
-					"phy reset operation timed out\n");
-			break;
-		}
-	}
-}
-
-static int omap_ehci_init(struct usb_hcd *hcd)
-{
-	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
-	int			rc;
-	struct usbhs_omap_platform_data	*pdata;
-
-	pdata = hcd->self.controller->platform_data;
-
-	/* Hold PHYs in reset while initializing EHCI controller */
-	if (pdata->phy_reset) {
-		if (gpio_is_valid(pdata->reset_gpio_port[0]))
-			gpio_set_value_cansleep(pdata->reset_gpio_port[0], 0);
-
-		if (gpio_is_valid(pdata->reset_gpio_port[1]))
-			gpio_set_value_cansleep(pdata->reset_gpio_port[1], 0);
-
-		/* Hold the PHY in RESET for enough time till DIR is high */
-		udelay(10);
-	}
-
-	/* Soft reset the PHY using PHY reset command over ULPI */
-	if (pdata->port_mode[0] == OMAP_EHCI_PORT_MODE_PHY)
-		omap_ehci_soft_phy_reset(hcd, 0);
-	if (pdata->port_mode[1] == OMAP_EHCI_PORT_MODE_PHY)
-		omap_ehci_soft_phy_reset(hcd, 1);
-
-	/* we know this is the memory we want, no need to ioremap again */
-	ehci->caps = hcd->regs;
-
-	rc = ehci_setup(hcd);
-
-	if (pdata->phy_reset) {
-		/* Hold the PHY in RESET for enough time till
-		 * PHY is settled and ready
-		 */
-		udelay(10);
-
-		if (gpio_is_valid(pdata->reset_gpio_port[0]))
-			gpio_set_value_cansleep(pdata->reset_gpio_port[0], 1);
-
-		if (gpio_is_valid(pdata->reset_gpio_port[1]))
-			gpio_set_value_cansleep(pdata->reset_gpio_port[1], 1);
-	}
-
-	return rc;
-}
+static struct hc_driver __read_mostly ehci_omap_hc_driver;
 
-static void disable_put_regulator(
-		struct usbhs_omap_platform_data *pdata)
-{
-	int i;
-
-	for (i = 0 ; i < OMAP3_HS_USB_PORTS ; i++) {
-		if (pdata->regulator[i]) {
-			regulator_disable(pdata->regulator[i]);
-			regulator_put(pdata->regulator[i]);
-		}
-	}
-}
+static const struct ehci_driver_overrides ehci_omap_overrides __initdata = {
+	.extra_priv_size = sizeof(struct omap_hcd),
+};
 
-/* configure so an HC device and id are always provided */
-/* always called with process context; sleeping is OK */
+static u64 omap_ehci_dma_mask = DMA_BIT_MASK(32);
 
 /**
  * ehci_hcd_omap_probe - initialize TI-based HCDs
@@ -175,15 +101,15 @@ static void disable_put_regulator(
  */
 static int ehci_hcd_omap_probe(struct platform_device *pdev)
 {
-	struct device				*dev = &pdev->dev;
-	struct usbhs_omap_platform_data		*pdata = dev->platform_data;
-	struct resource				*res;
-	struct usb_hcd				*hcd;
-	void __iomem				*regs;
-	int					ret = -ENODEV;
-	int					irq;
-	int					i;
-	char					supply[7];
+	struct device *dev = &pdev->dev;
+	struct usbhs_omap_platform_data *pdata = dev->platform_data;
+	struct resource	*res;
+	struct usb_hcd	*hcd;
+	void __iomem *regs;
+	int ret = -ENODEV;
+	int irq;
+	int i;
+	struct omap_hcd	*omap;
 
 	if (usb_disabled())
 		return -ENODEV;
@@ -193,52 +119,74 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
-	irq = platform_get_irq_byname(pdev, "ehci-irq");
-	if (irq < 0) {
-		dev_err(dev, "EHCI irq failed\n");
-		return -ENODEV;
+	/* For DT boot, get platform data from parent. i.e. usbhshost */
+	if (dev->of_node) {
+		pdata = dev->parent->platform_data;
+		dev->platform_data = pdata;
 	}
 
-	res =  platform_get_resource_byname(pdev,
-				IORESOURCE_MEM, "ehci");
-	if (!res) {
-		dev_err(dev, "UHH EHCI get resource failed\n");
+	if (!pdata) {
+		dev_err(dev, "Missing platform data\n");
 		return -ENODEV;
 	}
 
-	regs = ioremap(res->start, resource_size(res));
-	if (!regs) {
-		dev_err(dev, "UHH EHCI ioremap failed\n");
-		return -ENOMEM;
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(dev, "EHCI irq failed\n");
+		return -ENODEV;
 	}
 
+	res =  platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	regs = devm_ioremap_resource(dev, res);
+	if (IS_ERR(regs))
+		return PTR_ERR(regs);
+
+	/*
+	 * Right now device-tree probed devices don't get dma_mask set.
+	 * Since shared usb code relies on it, set it here for now.
+	 * Once we have dma capability bindings this can go away.
+	 */
+	if (!pdev->dev.dma_mask)
+		pdev->dev.dma_mask = &omap_ehci_dma_mask;
+
 	hcd = usb_create_hcd(&ehci_omap_hc_driver, dev,
 			dev_name(dev));
 	if (!hcd) {
-		dev_err(dev, "failed to create hcd with err %d\n", ret);
-		ret = -ENOMEM;
-		goto err_io;
+		dev_err(dev, "Failed to create HCD\n");
+		return -ENOMEM;
 	}
 
 	hcd->rsrc_start = res->start;
 	hcd->rsrc_len = resource_size(res);
 	hcd->regs = regs;
-
-	/* get ehci regulator and enable */
-	for (i = 0 ; i < OMAP3_HS_USB_PORTS ; i++) {
-		if (pdata->port_mode[i] != OMAP_EHCI_PORT_MODE_PHY) {
-			pdata->regulator[i] = NULL;
-			continue;
-		}
-		snprintf(supply, sizeof(supply), "hsusb%d", i);
-		pdata->regulator[i] = regulator_get(dev, supply);
-		if (IS_ERR(pdata->regulator[i])) {
-			pdata->regulator[i] = NULL;
-			dev_dbg(dev,
-			"failed to get ehci port%d regulator\n", i);
-		} else {
-			regulator_enable(pdata->regulator[i]);
+	hcd_to_ehci(hcd)->caps = regs;
+
+	omap = (struct omap_hcd *)hcd_to_ehci(hcd)->priv;
+	omap->nports = pdata->nports;
+
+	platform_set_drvdata(pdev, hcd);
+
+	/* get the PHY devices if needed */
+	for (i = 0 ; i < omap->nports ; i++) {
+		struct usb_phy *phy;
+
+		/* get the PHY device */
+		if (dev->of_node)
+			phy = devm_usb_get_phy_by_phandle(dev, "phys", i);
+		else
+			phy = devm_usb_get_phy_dev(dev, i);
+		if (IS_ERR(phy) || !phy) {
+			/* Don't bail out if PHY is not absolutely necessary */
+			if (pdata->port_mode[i] != OMAP_EHCI_PORT_MODE_PHY)
+				continue;
+
+			ret = IS_ERR(phy) ? PTR_ERR(phy) : -ENODEV;
+			dev_err(dev, "Can't get PHY device for port %d: %d\n",
+					i, ret);
+			goto err_phy;
 		}
+
+		omap->phy[i] = phy;
 	}
 
 	pm_runtime_enable(dev);
@@ -262,16 +210,34 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
 		goto err_pm_runtime;
 	}
 
+	/*
+	 * Bring PHYs out of reset.
+	 * Even though HSIC mode is a PHY-less mode, the reset
+	 * line exists between the chips and can be modelled
+	 * as a PHY device for reset control.
+	 */
+	for (i = 0; i < omap->nports; i++) {
+		if (!omap->phy[i])
+			continue;
+
+		usb_phy_init(omap->phy[i]);
+		/* bring PHY out of suspend */
+		usb_phy_set_suspend(omap->phy[i], 0);
+	}
 
 	return 0;
 
 err_pm_runtime:
-	disable_put_regulator(pdata);
 	pm_runtime_put_sync(dev);
+
+err_phy:
+	for (i = 0; i < omap->nports; i++) {
+		if (omap->phy[i])
+			usb_phy_shutdown(omap->phy[i]);
+	}
+
 	usb_put_hcd(hcd);
 
-err_io:
-	iounmap(regs);
 	return ret;
 }
 
@@ -286,14 +252,19 @@ err_io:
  */
 static int ehci_hcd_omap_remove(struct platform_device *pdev)
 {
-	struct device *dev				= &pdev->dev;
-	struct usb_hcd *hcd				= dev_get_drvdata(dev);
+	struct device *dev = &pdev->dev;
+	struct usb_hcd *hcd = dev_get_drvdata(dev);
+	struct omap_hcd *omap = (struct omap_hcd *)hcd_to_ehci(hcd)->priv;
+	int i;
 
 	usb_remove_hcd(hcd);
-	disable_put_regulator(dev->platform_data);
-	iounmap(hcd->regs);
-	usb_put_hcd(hcd);
 
+	for (i = 0; i < omap->nports; i++) {
+		if (omap->phy[i])
+			usb_phy_shutdown(omap->phy[i]);
+	}
+
+	usb_put_hcd(hcd);
 	pm_runtime_put_sync(dev);
 	pm_runtime_disable(dev);
 
@@ -308,6 +279,13 @@ static void ehci_hcd_omap_shutdown(struct platform_device *pdev)
 		hcd->driver->shutdown(hcd);
 }
 
+static const struct of_device_id omap_ehci_dt_ids[] = {
+	{ .compatible = "ti,ehci-omap" },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(of, omap_ehci_dt_ids);
+
 static struct platform_driver ehci_hcd_omap_driver = {
 	.probe			= ehci_hcd_omap_probe,
 	.remove			= ehci_hcd_omap_remove,
@@ -315,56 +293,35 @@ static struct platform_driver ehci_hcd_omap_driver = {
 	/*.suspend		= ehci_hcd_omap_suspend, */
 	/*.resume		= ehci_hcd_omap_resume, */
 	.driver = {
-		.name		= "ehci-omap",
+		.name		= hcd_name,
+		.of_match_table = of_match_ptr(omap_ehci_dt_ids),
 	}
 };
 
 /*-------------------------------------------------------------------------*/
 
-static const struct hc_driver ehci_omap_hc_driver = {
-	.description		= hcd_name,
-	.product_desc		= "OMAP-EHCI Host Controller",
-	.hcd_priv_size		= sizeof(struct ehci_hcd),
-
-	/*
-	 * generic hardware linkage
-	 */
-	.irq			= ehci_irq,
-	.flags			= HCD_MEMORY | HCD_USB2,
-
-	/*
-	 * basic lifecycle operations
-	 */
-	.reset			= omap_ehci_init,
-	.start			= ehci_run,
-	.stop			= ehci_stop,
-	.shutdown		= ehci_shutdown,
-
-	/*
-	 * managing i/o requests and associated device resources
-	 */
-	.urb_enqueue		= ehci_urb_enqueue,
-	.urb_dequeue		= ehci_urb_dequeue,
-	.endpoint_disable	= ehci_endpoint_disable,
-	.endpoint_reset		= ehci_endpoint_reset,
+static int __init ehci_omap_init(void)
+{
+	if (usb_disabled())
+		return -ENODEV;
 
-	/*
-	 * scheduling support
-	 */
-	.get_frame_number	= ehci_get_frame,
+	pr_info("%s: " DRIVER_DESC "\n", hcd_name);
 
-	/*
-	 * root hub support
-	 */
-	.hub_status_data	= ehci_hub_status_data,
-	.hub_control		= ehci_hub_control,
-	.bus_suspend		= ehci_bus_suspend,
-	.bus_resume		= ehci_bus_resume,
+	ehci_init_driver(&ehci_omap_hc_driver, &ehci_omap_overrides);
+	return platform_driver_register(&ehci_hcd_omap_driver);
+}
+module_init(ehci_omap_init);
 
-	.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
-};
+static void __exit ehci_omap_cleanup(void)
+{
+	platform_driver_unregister(&ehci_hcd_omap_driver);
+}
+module_exit(ehci_omap_cleanup);
 
 MODULE_ALIAS("platform:ehci-omap");
 MODULE_AUTHOR("Texas Instruments, Inc.");
 MODULE_AUTHOR("Felipe Balbi <felipe.balbi@nokia.com>");
+MODULE_AUTHOR("Roger Quadros <rogerq@ti.com>");
 
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c
index 914a3ec..38c45fb 100644
--- a/drivers/usb/host/ehci-orion.c
+++ b/drivers/usb/host/ehci-orion.c
@@ -305,7 +305,7 @@ err1:
 	return err;
 }
 
-static int __exit ehci_orion_drv_remove(struct platform_device *pdev)
+static int ehci_orion_drv_remove(struct platform_device *pdev)
 {
 	struct usb_hcd *hcd = platform_get_drvdata(pdev);
 	struct clk *clk;
@@ -333,7 +333,7 @@ MODULE_DEVICE_TABLE(of, ehci_orion_dt_ids);
 
 static struct platform_driver ehci_orion_driver = {
 	.probe		= ehci_orion_drv_probe,
-	.remove		= __exit_p(ehci_orion_drv_remove),
+	.remove		= ehci_orion_drv_remove,
 	.shutdown	= usb_hcd_platform_shutdown,
 	.driver = {
 		.name	= "orion-ehci",
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index 170b939..a573d5f 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -292,17 +292,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
 		}
 	}
 
-#ifdef	CONFIG_USB_SUSPEND
-	/* REVISIT: the controller works fine for wakeup iff the root hub
-	 * itself is "globally" suspended, but usbcore currently doesn't
-	 * understand such things.
-	 *
-	 * System suspend currently expects to be able to suspend the entire
-	 * device tree, device-at-a-time.  If we failed selective suspend
-	 * reports, system suspend would fail; so the root hub code must claim
-	 * success.  That's lying to usbcore, and it matters for runtime
-	 * PM scenarios with selective suspend and remote wakeup...
-	 */
+#ifdef	CONFIG_PM_RUNTIME
 	if (ehci->no_selective_suspend && device_can_wakeup(&pdev->dev))
 		ehci_warn(ehci, "selective suspend/wakeup unavailable\n");
 #endif
diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c
index ca75063..cda0fa9 100644
--- a/drivers/usb/host/ehci-platform.c
+++ b/drivers/usb/host/ehci-platform.c
@@ -18,11 +18,13 @@
  *
  * Licensed under the GNU/GPL. See COPYING for details.
  */
+#include <linux/dma-mapping.h>
 #include <linux/err.h>
 #include <linux/kernel.h>
 #include <linux/hrtimer.h>
 #include <linux/io.h>
 #include <linux/module.h>
+#include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/usb.h>
 #include <linux/usb/hcd.h>
@@ -62,22 +64,32 @@ static const struct ehci_driver_overrides platform_overrides __initdata = {
 	.reset =	ehci_platform_reset,
 };
 
+static struct usb_ehci_pdata ehci_platform_defaults;
+
 static int ehci_platform_probe(struct platform_device *dev)
 {
 	struct usb_hcd *hcd;
 	struct resource *res_mem;
-	struct usb_ehci_pdata *pdata = dev->dev.platform_data;
+	struct usb_ehci_pdata *pdata;
 	int irq;
 	int err = -ENOMEM;
 
-	if (!pdata) {
-		WARN_ON(1);
-		return -ENODEV;
-	}
-
 	if (usb_disabled())
 		return -ENODEV;
 
+	/*
+	 * use reasonable defaults so platforms don't have to provide these.
+	 * with DT probing on ARM, none of these are set.
+	 */
+	if (!dev->dev.platform_data)
+		dev->dev.platform_data = &ehci_platform_defaults;
+	if (!dev->dev.dma_mask)
+		dev->dev.dma_mask = &dev->dev.coherent_dma_mask;
+	if (!dev->dev.coherent_dma_mask)
+		dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+
+	pdata = dev->dev.platform_data;
+
 	irq = platform_get_irq(dev, 0);
 	if (irq < 0) {
 		dev_err(&dev->dev, "no irq provided");
@@ -139,6 +151,9 @@ static int ehci_platform_remove(struct platform_device *dev)
 	if (pdata->power_off)
 		pdata->power_off(dev);
 
+	if (pdata == &ehci_platform_defaults)
+		dev->dev.platform_data = NULL;
+
 	return 0;
 }
 
@@ -183,6 +198,12 @@ static int ehci_platform_resume(struct device *dev)
 #define ehci_platform_resume	NULL
 #endif /* CONFIG_PM */
 
+static const struct of_device_id vt8500_ehci_ids[] = {
+	{ .compatible = "via,vt8500-ehci", },
+	{ .compatible = "wm,prizm-ehci", },
+	{}
+};
+
 static const struct platform_device_id ehci_platform_table[] = {
 	{ "ehci-platform", 0 },
 	{ }
@@ -203,6 +224,7 @@ static struct platform_driver ehci_platform_driver = {
 		.owner	= THIS_MODULE,
 		.name	= "ehci-platform",
 		.pm	= &ehci_platform_pm_ops,
+		.of_match_table = of_match_ptr(vt8500_ehci_ids),
 	}
 };
 
diff --git a/drivers/usb/host/ehci-ps3.c b/drivers/usb/host/ehci-ps3.c
index df5925a..fd98377 100644
--- a/drivers/usb/host/ehci-ps3.c
+++ b/drivers/usb/host/ehci-ps3.c
@@ -221,7 +221,6 @@ static int ps3_ehci_remove(struct ps3_system_bus_device *dev)
 
 	tmp = hcd->irq;
 
-	ehci_shutdown(hcd);
 	usb_remove_hcd(hcd);
 
 	ps3_system_bus_set_drvdata(dev, NULL);
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index 23d1369..d34b399 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -90,7 +90,7 @@ qh_update (struct ehci_hcd *ehci, struct ehci_qh *qh, struct ehci_qtd *qtd)
 	struct ehci_qh_hw *hw = qh->hw;
 
 	/* writes to an active overlay are unsafe */
-	BUG_ON(qh->qh_state != QH_STATE_IDLE);
+	WARN_ON(qh->qh_state != QH_STATE_IDLE);
 
 	hw->hw_qtd_next = QTD_NEXT(ehci, qtd->qtd_dma);
 	hw->hw_alt_next = EHCI_LIST_END(ehci);
@@ -123,26 +123,19 @@ qh_refresh (struct ehci_hcd *ehci, struct ehci_qh *qh)
 {
 	struct ehci_qtd *qtd;
 
-	if (list_empty (&qh->qtd_list))
-		qtd = qh->dummy;
-	else {
-		qtd = list_entry (qh->qtd_list.next,
-				struct ehci_qtd, qtd_list);
-		/*
-		 * first qtd may already be partially processed.
-		 * If we come here during unlink, the QH overlay region
-		 * might have reference to the just unlinked qtd. The
-		 * qtd is updated in qh_completions(). Update the QH
-		 * overlay here.
-		 */
-		if (qh->hw->hw_token & ACTIVE_BIT(ehci)) {
-			qh->hw->hw_qtd_next = qtd->hw_next;
-			qtd = NULL;
-		}
-	}
+	qtd = list_entry(qh->qtd_list.next, struct ehci_qtd, qtd_list);
 
-	if (qtd)
-		qh_update (ehci, qh, qtd);
+	/*
+	 * first qtd may already be partially processed.
+	 * If we come here during unlink, the QH overlay region
+	 * might have reference to the just unlinked qtd. The
+	 * qtd is updated in qh_completions(). Update the QH
+	 * overlay here.
+	 */
+	if (qh->hw->hw_token & ACTIVE_BIT(ehci))
+		qh->hw->hw_qtd_next = qtd->hw_next;
+	else
+		qh_update(ehci, qh, qtd);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -299,8 +292,8 @@ static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh);
 
 /*
  * Process and free completed qtds for a qh, returning URBs to drivers.
- * Chases up to qh->hw_current.  Returns number of completions called,
- * indicating how much "real" work we did.
+ * Chases up to qh->hw_current.  Returns nonzero if the caller should
+ * unlink qh.
  */
 static unsigned
 qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
@@ -309,13 +302,9 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
 	struct list_head	*entry, *tmp;
 	int			last_status;
 	int			stopped;
-	unsigned		count = 0;
 	u8			state;
 	struct ehci_qh_hw	*hw = qh->hw;
 
-	if (unlikely (list_empty (&qh->qtd_list)))
-		return count;
-
 	/* completions (or tasks on other cpus) must never clobber HALT
 	 * till we've gone through and cleaned everything up, even when
 	 * they add urbs to this qh's queue or mark them for unlinking.
@@ -333,7 +322,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
  rescan:
 	last = NULL;
 	last_status = -EINPROGRESS;
-	qh->needs_rescan = 0;
+	qh->dequeue_during_giveback = 0;
 
 	/* remove de-activated QTDs from front of queue.
 	 * after faults (including short reads), cleanup this urb
@@ -352,7 +341,6 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
 		if (last) {
 			if (likely (last->urb != urb)) {
 				ehci_urb_done(ehci, last->urb, last_status);
-				count++;
 				last_status = -EINPROGRESS;
 			}
 			ehci_qtd_free (ehci, last);
@@ -526,23 +514,16 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
 	/* last urb's completion might still need calling */
 	if (likely (last != NULL)) {
 		ehci_urb_done(ehci, last->urb, last_status);
-		count++;
 		ehci_qtd_free (ehci, last);
 	}
 
 	/* Do we need to rescan for URBs dequeued during a giveback? */
-	if (unlikely(qh->needs_rescan)) {
+	if (unlikely(qh->dequeue_during_giveback)) {
 		/* If the QH is already unlinked, do the rescan now. */
 		if (state == QH_STATE_IDLE)
 			goto rescan;
 
-		/* Otherwise we have to wait until the QH is fully unlinked.
-		 * Our caller will start an unlink if qh->needs_rescan is
-		 * set.  But if an unlink has already started, nothing needs
-		 * to be done.
-		 */
-		if (state != QH_STATE_LINKED)
-			qh->needs_rescan = 0;
+		/* Otherwise the caller must unlink the QH. */
 	}
 
 	/* restore original state; caller must unlink or relink */
@@ -551,33 +532,23 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
 	/* be sure the hardware's done with the qh before refreshing
 	 * it after fault cleanup, or recovering from silicon wrongly
 	 * overlaying the dummy qtd (which reduces DMA chatter).
+	 *
+	 * We won't refresh a QH that's linked (after the HC
+	 * stopped the queue).  That avoids a race:
+	 *  - HC reads first part of QH;
+	 *  - CPU updates that first part and the token;
+	 *  - HC reads rest of that QH, including token
+	 * Result:  HC gets an inconsistent image, and then
+	 * DMAs to/from the wrong memory (corrupting it).
+	 *
+	 * That should be rare for interrupt transfers,
+	 * except maybe high bandwidth ...
 	 */
-	if (stopped != 0 || hw->hw_qtd_next == EHCI_LIST_END(ehci)) {
-		switch (state) {
-		case QH_STATE_IDLE:
-			qh_refresh(ehci, qh);
-			break;
-		case QH_STATE_LINKED:
-			/* We won't refresh a QH that's linked (after the HC
-			 * stopped the queue).  That avoids a race:
-			 *  - HC reads first part of QH;
-			 *  - CPU updates that first part and the token;
-			 *  - HC reads rest of that QH, including token
-			 * Result:  HC gets an inconsistent image, and then
-			 * DMAs to/from the wrong memory (corrupting it).
-			 *
-			 * That should be rare for interrupt transfers,
-			 * except maybe high bandwidth ...
-			 */
+	if (stopped != 0 || hw->hw_qtd_next == EHCI_LIST_END(ehci))
+		qh->exception = 1;
 
-			/* Tell the caller to start an unlink */
-			qh->needs_rescan = 1;
-			break;
-		/* otherwise, unlink already started */
-		}
-	}
-
-	return count;
+	/* Let the caller know if the QH needs to be unlinked. */
+	return qh->exception;
 }
 
 /*-------------------------------------------------------------------------*/
@@ -957,14 +928,13 @@ done:
 
 	/* NOTE:  if (PIPE_INTERRUPT) { scheduler sets s-mask } */
 
-	/* init as live, toggle clear, advance to dummy */
+	/* init as live, toggle clear */
 	qh->qh_state = QH_STATE_IDLE;
 	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;
 }
 
@@ -988,8 +958,9 @@ static void disable_async(struct ehci_hcd *ehci)
 	if (--ehci->async_count)
 		return;
 
-	/* The async schedule and async_unlink list are supposed to be empty */
-	WARN_ON(ehci->async->qh_next.qh || ehci->async_unlink);
+	/* The async schedule and unlink lists are supposed to be empty */
+	WARN_ON(ehci->async->qh_next.qh || !list_empty(&ehci->async_unlink) ||
+			!list_empty(&ehci->async_idle));
 
 	/* Don't turn off the schedule until ASS is 1 */
 	ehci_poll_ASS(ehci);
@@ -1020,8 +991,9 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
 	head->qh_next.qh = qh;
 	head->hw->hw_next = dma;
 
-	qh->xacterrs = 0;
 	qh->qh_state = QH_STATE_LINKED;
+	qh->xacterrs = 0;
+	qh->exception = 0;
 	/* qtd completions reported later by interrupt */
 
 	enable_async(ehci);
@@ -1179,11 +1151,7 @@ static void single_unlink_async(struct ehci_hcd *ehci, struct ehci_qh *qh)
 
 	/* Add to the end of the list of QHs waiting for the next IAAD */
 	qh->qh_state = QH_STATE_UNLINK_WAIT;
-	if (ehci->async_unlink)
-		ehci->async_unlink_last->unlink_next = qh;
-	else
-		ehci->async_unlink = qh;
-	ehci->async_unlink_last = qh;
+	list_add_tail(&qh->unlink_node, &ehci->async_unlink);
 
 	/* Unlink it from the schedule */
 	prev = ehci->async;
@@ -1196,44 +1164,19 @@ static void single_unlink_async(struct ehci_hcd *ehci, struct ehci_qh *qh)
 		ehci->qh_scan_next = qh->qh_next.qh;
 }
 
-static void start_iaa_cycle(struct ehci_hcd *ehci, bool nested)
+static void start_iaa_cycle(struct ehci_hcd *ehci)
 {
-	/*
-	 * Do nothing if an IAA cycle is already running or
-	 * if one will be started shortly.
-	 */
-	if (ehci->async_iaa || ehci->async_unlinking)
+	/* Do nothing if an IAA cycle is already running */
+	if (ehci->iaa_in_progress)
 		return;
+	ehci->iaa_in_progress = true;
 
 	/* If the controller isn't running, we don't have to wait for it */
 	if (unlikely(ehci->rh_state < EHCI_RH_RUNNING)) {
-
-		/* Do all the waiting QHs */
-		ehci->async_iaa = ehci->async_unlink;
-		ehci->async_unlink = NULL;
-
-		if (!nested)		/* Avoid recursion */
-			end_unlink_async(ehci);
+		end_unlink_async(ehci);
 
 	/* Otherwise start a new IAA cycle */
 	} else if (likely(ehci->rh_state == EHCI_RH_RUNNING)) {
-		struct ehci_qh		*qh;
-
-		/* Do only the first waiting QH (nVidia bug?) */
-		qh = ehci->async_unlink;
-
-		/*
-		 * Intel (?) bug: The HC can write back the overlay region
-		 * even after the IAA interrupt occurs.  In self-defense,
-		 * always go through two IAA cycles for each QH.
-		 */
-		if (qh->qh_state == QH_STATE_UNLINK_WAIT) {
-			qh->qh_state = QH_STATE_UNLINK;
-		} else {
-			ehci->async_iaa = qh;
-			ehci->async_unlink = qh->unlink_next;
-			qh->unlink_next = NULL;
-		}
 
 		/* Make sure the unlinks are all visible to the hardware */
 		wmb();
@@ -1250,36 +1193,73 @@ static void start_iaa_cycle(struct ehci_hcd *ehci, bool nested)
 static void end_unlink_async(struct ehci_hcd *ehci)
 {
 	struct ehci_qh		*qh;
+	bool			early_exit;
 
 	if (ehci->has_synopsys_hc_bug)
 		ehci_writel(ehci, (u32) ehci->async->qh_dma,
 			    &ehci->regs->async_next);
 
+	/* The current IAA cycle has ended */
+	ehci->iaa_in_progress = false;
+
+	if (list_empty(&ehci->async_unlink))
+		return;
+	qh = list_first_entry(&ehci->async_unlink, struct ehci_qh,
+			unlink_node);	/* QH whose IAA cycle just ended */
+
+	/*
+	 * If async_unlinking is set then this routine is already running,
+	 * either on the stack or on another CPU.
+	 */
+	early_exit = ehci->async_unlinking;
+
+	/* If the controller isn't running, process all the waiting QHs */
+	if (ehci->rh_state < EHCI_RH_RUNNING)
+		list_splice_tail_init(&ehci->async_unlink, &ehci->async_idle);
+
+	/*
+	 * Intel (?) bug: The HC can write back the overlay region even
+	 * after the IAA interrupt occurs.  In self-defense, always go
+	 * through two IAA cycles for each QH.
+	 */
+	else if (qh->qh_state == QH_STATE_UNLINK_WAIT) {
+		qh->qh_state = QH_STATE_UNLINK;
+		early_exit = true;
+	}
+
+	/* Otherwise process only the first waiting QH (NVIDIA bug?) */
+	else
+		list_move_tail(&qh->unlink_node, &ehci->async_idle);
+
+	/* Start a new IAA cycle if any QHs are waiting for it */
+	if (!list_empty(&ehci->async_unlink))
+		start_iaa_cycle(ehci);
+
+	/*
+	 * Don't allow nesting or concurrent calls,
+	 * or wait for the second IAA cycle for the next QH.
+	 */
+	if (early_exit)
+		return;
+
 	/* Process the idle QHs */
- restart:
 	ehci->async_unlinking = true;
-	while (ehci->async_iaa) {
-		qh = ehci->async_iaa;
-		ehci->async_iaa = qh->unlink_next;
-		qh->unlink_next = NULL;
+	while (!list_empty(&ehci->async_idle)) {
+		qh = list_first_entry(&ehci->async_idle, struct ehci_qh,
+				unlink_node);
+		list_del(&qh->unlink_node);
 
 		qh->qh_state = QH_STATE_IDLE;
 		qh->qh_next.qh = NULL;
 
-		qh_completions(ehci, qh);
+		if (!list_empty(&qh->qtd_list))
+			qh_completions(ehci, qh);
 		if (!list_empty(&qh->qtd_list) &&
 				ehci->rh_state == EHCI_RH_RUNNING)
 			qh_link_async(ehci, qh);
 		disable_async(ehci);
 	}
 	ehci->async_unlinking = false;
-
-	/* Start a new IAA cycle if any QHs are waiting for it */
-	if (ehci->async_unlink) {
-		start_iaa_cycle(ehci, true);
-		if (unlikely(ehci->rh_state < EHCI_RH_RUNNING))
-			goto restart;
-	}
 }
 
 static void start_unlink_async(struct ehci_hcd *ehci, struct ehci_qh *qh);
@@ -1288,7 +1268,6 @@ static void unlink_empty_async(struct ehci_hcd *ehci)
 {
 	struct ehci_qh		*qh;
 	struct ehci_qh		*qh_to_unlink = NULL;
-	bool			check_unlinks_later = false;
 	int			count = 0;
 
 	/* Find the last async QH which has been empty for a timer cycle */
@@ -1296,15 +1275,13 @@ static void unlink_empty_async(struct ehci_hcd *ehci)
 		if (list_empty(&qh->qtd_list) &&
 				qh->qh_state == QH_STATE_LINKED) {
 			++count;
-			if (qh->unlink_cycle == ehci->async_unlink_cycle)
-				check_unlinks_later = true;
-			else
+			if (qh->unlink_cycle != ehci->async_unlink_cycle)
 				qh_to_unlink = qh;
 		}
 	}
 
 	/* If nothing else is being unlinked, unlink the last empty QH */
-	if (!ehci->async_iaa && !ehci->async_unlink && qh_to_unlink) {
+	if (list_empty(&ehci->async_unlink) && qh_to_unlink) {
 		start_unlink_async(ehci, qh_to_unlink);
 		--count;
 	}
@@ -1317,7 +1294,7 @@ static void unlink_empty_async(struct ehci_hcd *ehci)
 }
 
 /* The root hub is suspended; unlink all the async QHs */
-static void unlink_empty_async_suspended(struct ehci_hcd *ehci)
+static void __maybe_unused unlink_empty_async_suspended(struct ehci_hcd *ehci)
 {
 	struct ehci_qh		*qh;
 
@@ -1326,7 +1303,7 @@ static void unlink_empty_async_suspended(struct ehci_hcd *ehci)
 		WARN_ON(!list_empty(&qh->qtd_list));
 		single_unlink_async(ehci, qh);
 	}
-	start_iaa_cycle(ehci, false);
+	start_iaa_cycle(ehci);
 }
 
 /* makes sure the async qh will become idle */
@@ -1334,19 +1311,12 @@ static void unlink_empty_async_suspended(struct ehci_hcd *ehci)
 
 static void start_unlink_async(struct ehci_hcd *ehci, struct ehci_qh *qh)
 {
-	/*
-	 * If the QH isn't linked then there's nothing we can do
-	 * unless we were called during a giveback, in which case
-	 * qh_completions() has to deal with it.
-	 */
-	if (qh->qh_state != QH_STATE_LINKED) {
-		if (qh->qh_state == QH_STATE_COMPLETING)
-			qh->needs_rescan = 1;
+	/* If the QH isn't linked then there's nothing we can do. */
+	if (qh->qh_state != QH_STATE_LINKED)
 		return;
-	}
 
 	single_unlink_async(ehci, qh);
-	start_iaa_cycle(ehci, false);
+	start_iaa_cycle(ehci);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -1360,7 +1330,7 @@ static void scan_async (struct ehci_hcd *ehci)
 	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;
@@ -1373,14 +1343,13 @@ static void scan_async (struct ehci_hcd *ehci)
 			 * in single_unlink_async().
 			 */
 			temp = qh_completions(ehci, qh);
-			if (qh->needs_rescan) {
+			if (unlikely(temp)) {
 				start_unlink_async(ehci, qh);
 			} else if (list_empty(&qh->qtd_list)
 					&& qh->qh_state == QH_STATE_LINKED) {
 				qh->unlink_cycle = ehci->async_unlink_cycle;
 				check_unlinks_later = true;
-			} else if (temp != 0)
-				goto rescan;
+			}
 		}
 	}
 
diff --git a/drivers/usb/host/ehci-s5p.c b/drivers/usb/host/ehci-s5p.c
index 20ebf6a..43a2a16 100644
--- a/drivers/usb/host/ehci-s5p.c
+++ b/drivers/usb/host/ehci-s5p.c
@@ -92,20 +92,21 @@ static void s5p_ehci_phy_disable(struct s5p_ehci_hcd *s5p_ehci)
 
 static void s5p_setup_vbus_gpio(struct platform_device *pdev)
 {
+	struct device *dev = &pdev->dev;
 	int err;
 	int gpio;
 
-	if (!pdev->dev.of_node)
+	if (!dev->of_node)
 		return;
 
-	gpio = of_get_named_gpio(pdev->dev.of_node,
-			"samsung,vbus-gpio", 0);
+	gpio = of_get_named_gpio(dev->of_node, "samsung,vbus-gpio", 0);
 	if (!gpio_is_valid(gpio))
 		return;
 
-	err = gpio_request_one(gpio, GPIOF_OUT_INIT_HIGH, "ehci_vbus_gpio");
+	err = devm_gpio_request_one(dev, gpio, GPIOF_OUT_INIT_HIGH,
+				    "ehci_vbus_gpio");
 	if (err)
-		dev_err(&pdev->dev, "can't request ehci vbus gpio %d", gpio);
+		dev_err(dev, "can't request ehci vbus gpio %d", gpio);
 }
 
 static u64 ehci_s5p_dma_mask = DMA_BIT_MASK(32);
@@ -139,7 +140,7 @@ static int s5p_ehci_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
-	if (IS_ERR_OR_NULL(phy)) {
+	if (IS_ERR(phy)) {
 		/* Fallback to pdata */
 		if (!pdata) {
 			dev_warn(&pdev->dev, "no platform data or transceiver defined\n");
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index 010f686..acff5b8 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -539,6 +539,7 @@ static void qh_link_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh)
 	}
 	qh->qh_state = QH_STATE_LINKED;
 	qh->xacterrs = 0;
+	qh->exception = 0;
 
 	/* update per-qh bandwidth for usbfs */
 	ehci_to_hcd(ehci)->self.bandwidth_allocated += qh->period
@@ -602,15 +603,9 @@ static void qh_unlink_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh)
 
 static void start_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh)
 {
-	/* If the QH isn't linked then there's nothing we can do
-	 * unless we were called during a giveback, in which case
-	 * qh_completions() has to deal with it.
-	 */
-	if (qh->qh_state != QH_STATE_LINKED) {
-		if (qh->qh_state == QH_STATE_COMPLETING)
-			qh->needs_rescan = 1;
+	/* If the QH isn't linked then there's nothing we can do. */
+	if (qh->qh_state != QH_STATE_LINKED)
 		return;
-	}
 
 	qh_unlink_periodic (ehci, qh);
 
@@ -625,17 +620,13 @@ static void start_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh)
 	qh->unlink_cycle = ehci->intr_unlink_cycle;
 
 	/* New entries go at the end of the intr_unlink list */
-	if (ehci->intr_unlink)
-		ehci->intr_unlink_last->unlink_next = qh;
-	else
-		ehci->intr_unlink = qh;
-	ehci->intr_unlink_last = qh;
+	list_add_tail(&qh->unlink_node, &ehci->intr_unlink);
 
 	if (ehci->intr_unlinking)
 		;	/* Avoid recursive calls */
 	else if (ehci->rh_state < EHCI_RH_RUNNING)
 		ehci_handle_intr_unlinks(ehci);
-	else if (ehci->intr_unlink == qh) {
+	else if (ehci->intr_unlink.next == &qh->unlink_node) {
 		ehci_enable_event(ehci, EHCI_HRTIMER_UNLINK_INTR, true);
 		++ehci->intr_unlink_cycle;
 	}
@@ -649,7 +640,8 @@ static void end_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh)
 	qh->qh_state = QH_STATE_IDLE;
 	hw->hw_next = EHCI_LIST_END(ehci);
 
-	qh_completions(ehci, qh);
+	if (!list_empty(&qh->qtd_list))
+		qh_completions(ehci, qh);
 
 	/* reschedule QH iff another request is queued */
 	if (!list_empty(&qh->qtd_list) && ehci->rh_state == EHCI_RH_RUNNING) {
@@ -792,7 +784,6 @@ static int qh_schedule(struct ehci_hcd *ehci, struct ehci_qh *qh)
 	unsigned	frame;		/* 0..(qh->period - 1), or NO_FRAME */
 	struct ehci_qh_hw	*hw = qh->hw;
 
-	qh_refresh(ehci, qh);
 	hw->hw_next = EHCI_LIST_END(ehci);
 	frame = qh->start;
 
@@ -844,8 +835,6 @@ static int qh_schedule(struct ehci_hcd *ehci, struct ehci_qh *qh)
 	} else
 		ehci_dbg (ehci, "reused qh %p schedule\n", qh);
 
-	/* stuff into the periodic schedule */
-	qh_link_periodic(ehci, qh);
 done:
 	return status;
 }
@@ -891,6 +880,12 @@ static int intr_submit (
 	qh = qh_append_tds(ehci, urb, qtd_list, epnum, &urb->ep->hcpriv);
 	BUG_ON (qh == NULL);
 
+	/* stuff into the periodic schedule */
+	if (qh->qh_state == QH_STATE_IDLE) {
+		qh_refresh(ehci, qh);
+		qh_link_periodic(ehci, qh);
+	}
+
 	/* ... update usbfs periodic stats */
 	ehci_to_hcd(ehci)->self.bandwidth_int_reqs++;
 
@@ -911,7 +906,7 @@ static void scan_intr(struct ehci_hcd *ehci)
 
 	list_for_each_entry_safe(qh, ehci->qh_scan_next, &ehci->intr_qh_list,
 			intr_node) {
- rescan:
+
 		/* clean any finished work for this qh */
 		if (!list_empty(&qh->qtd_list)) {
 			int temp;
@@ -924,12 +919,9 @@ static void scan_intr(struct ehci_hcd *ehci)
 			 * in qh_unlink_periodic().
 			 */
 			temp = qh_completions(ehci, qh);
-			if (unlikely(qh->needs_rescan ||
-					(list_empty(&qh->qtd_list) &&
-						qh->qh_state == QH_STATE_LINKED)))
+			if (unlikely(temp || (list_empty(&qh->qtd_list) &&
+					qh->qh_state == QH_STATE_LINKED)))
 				start_unlink_intr(ehci, qh);
-			else if (temp != 0)
-				goto rescan;
 		}
 	}
 }
diff --git a/drivers/usb/host/ehci-sh.c b/drivers/usb/host/ehci-sh.c
index 3565a30..b44d716 100644
--- a/drivers/usb/host/ehci-sh.c
+++ b/drivers/usb/host/ehci-sh.c
@@ -77,7 +77,6 @@ static const struct hc_driver ehci_sh_hc_driver = {
 
 static int ehci_hcd_sh_probe(struct platform_device *pdev)
 {
-	const struct hc_driver *driver = &ehci_sh_hc_driver;
 	struct resource *res;
 	struct ehci_sh_priv *priv;
 	struct ehci_sh_platdata *pdata;
@@ -170,7 +169,7 @@ fail_create_hcd:
 	return ret;
 }
 
-static int __exit ehci_hcd_sh_remove(struct platform_device *pdev)
+static int ehci_hcd_sh_remove(struct platform_device *pdev)
 {
 	struct ehci_sh_priv *priv = platform_get_drvdata(pdev);
 	struct usb_hcd *hcd = priv->hcd;
@@ -196,7 +195,7 @@ static void ehci_hcd_sh_shutdown(struct platform_device *pdev)
 
 static struct platform_driver ehci_hcd_sh_driver = {
 	.probe		= ehci_hcd_sh_probe,
-	.remove		= __exit_p(ehci_hcd_sh_remove),
+	.remove		= ehci_hcd_sh_remove,
 	.shutdown	= ehci_hcd_sh_shutdown,
 	.driver		= {
 		.name	= "sh_ehci",
diff --git a/drivers/usb/host/ehci-spear.c b/drivers/usb/host/ehci-spear.c
index 466c1bb..210bb67 100644
--- a/drivers/usb/host/ehci-spear.c
+++ b/drivers/usb/host/ehci-spear.c
@@ -78,7 +78,7 @@ static const struct hc_driver ehci_spear_hc_driver = {
 	.clear_tt_buffer_complete	= ehci_clear_tt_buffer_complete,
 };
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int ehci_spear_drv_suspend(struct device *dev)
 {
 	struct usb_hcd *hcd = dev_get_drvdata(dev);
@@ -94,7 +94,7 @@ static int ehci_spear_drv_resume(struct device *dev)
 	ehci_resume(hcd, false);
 	return 0;
 }
-#endif /* CONFIG_PM */
+#endif /* CONFIG_PM_SLEEP */
 
 static SIMPLE_DEV_PM_OPS(ehci_spear_pm_ops, ehci_spear_drv_suspend,
 		ehci_spear_drv_resume);
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index 568aecc..ed201ae 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -28,6 +28,7 @@
 #include <linux/pm_runtime.h>
 #include <linux/usb/ehci_def.h>
 #include <linux/usb/tegra_usb_phy.h>
+#include <linux/clk/tegra.h>
 
 #define TEGRA_USB_BASE			0xC5000000
 #define TEGRA_USB2_BASE			0xC5004000
@@ -691,6 +692,10 @@ static int tegra_ehci_probe(struct platform_device *pdev)
 	if (err)
 		goto fail_clk;
 
+	tegra_periph_reset_assert(tegra->clk);
+	udelay(1);
+	tegra_periph_reset_deassert(tegra->clk);
+
 	tegra->needs_double_reset = of_property_read_bool(pdev->dev.of_node,
 		"nvidia,needs-double-reset");
 
@@ -755,7 +760,7 @@ static int tegra_ehci_probe(struct platform_device *pdev)
 	err = usb_phy_set_suspend(hcd->phy, 0);
 	if (err) {
 		dev_err(&pdev->dev, "Failed to power on the phy\n");
-		goto fail;
+		goto fail_phy;
 	}
 
 	tegra->host_resumed = 1;
@@ -765,17 +770,17 @@ static int tegra_ehci_probe(struct platform_device *pdev)
 	if (!irq) {
 		dev_err(&pdev->dev, "Failed to get IRQ\n");
 		err = -ENODEV;
-		goto fail;
+		goto fail_phy;
 	}
 
-#ifdef CONFIG_USB_OTG_UTILS
 	if (pdata->operating_mode == TEGRA_USB_OTG) {
 		tegra->transceiver =
 			devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
-		if (!IS_ERR_OR_NULL(tegra->transceiver))
+		if (!IS_ERR(tegra->transceiver))
 			otg_set_host(tegra->transceiver->otg, &hcd->self);
+	} else {
+		tegra->transceiver = ERR_PTR(-ENODEV);
 	}
-#endif
 
 	err = usb_add_hcd(hcd, irq, IRQF_SHARED);
 	if (err) {
@@ -794,10 +799,9 @@ static int tegra_ehci_probe(struct platform_device *pdev)
 	return err;
 
 fail:
-#ifdef CONFIG_USB_OTG_UTILS
-	if (!IS_ERR_OR_NULL(tegra->transceiver))
+	if (!IS_ERR(tegra->transceiver))
 		otg_set_host(tegra->transceiver->otg, NULL);
-#endif
+fail_phy:
 	usb_phy_shutdown(hcd->phy);
 fail_io:
 	clk_disable_unprepare(tegra->clk);
@@ -815,10 +819,8 @@ static int tegra_ehci_remove(struct platform_device *pdev)
 	pm_runtime_disable(&pdev->dev);
 	pm_runtime_put_noidle(&pdev->dev);
 
-#ifdef CONFIG_USB_OTG_UTILS
-	if (!IS_ERR_OR_NULL(tegra->transceiver))
+	if (!IS_ERR(tegra->transceiver))
 		otg_set_host(tegra->transceiver->otg, NULL);
-#endif
 
 	usb_phy_shutdown(hcd->phy);
 	usb_remove_hcd(hcd);
diff --git a/drivers/usb/host/ehci-timer.c b/drivers/usb/host/ehci-timer.c
index c3fa130..11e5b32 100644
--- a/drivers/usb/host/ehci-timer.c
+++ b/drivers/usb/host/ehci-timer.c
@@ -113,8 +113,8 @@ static void ehci_poll_ASS(struct ehci_hcd *ehci)
 
 	if (want != actual) {
 
-		/* Poll again later, but give up after about 20 ms */
-		if (ehci->ASS_poll_count++ < 20) {
+		/* Poll again later, but give up after about 2-4 ms */
+		if (ehci->ASS_poll_count++ < 2) {
 			ehci_enable_event(ehci, EHCI_HRTIMER_POLL_ASS, true);
 			return;
 		}
@@ -159,8 +159,8 @@ static void ehci_poll_PSS(struct ehci_hcd *ehci)
 
 	if (want != actual) {
 
-		/* Poll again later, but give up after about 20 ms */
-		if (ehci->PSS_poll_count++ < 20) {
+		/* Poll again later, but give up after about 2-4 ms */
+		if (ehci->PSS_poll_count++ < 2) {
 			ehci_enable_event(ehci, EHCI_HRTIMER_POLL_PSS, true);
 			return;
 		}
@@ -229,18 +229,19 @@ static void ehci_handle_intr_unlinks(struct ehci_hcd *ehci)
 	 * process all the QHs on the list.
 	 */
 	ehci->intr_unlinking = true;
-	while (ehci->intr_unlink) {
-		struct ehci_qh	*qh = ehci->intr_unlink;
+	while (!list_empty(&ehci->intr_unlink)) {
+		struct ehci_qh	*qh;
 
+		qh = list_first_entry(&ehci->intr_unlink, struct ehci_qh,
+				unlink_node);
 		if (!stopped && qh->unlink_cycle == ehci->intr_unlink_cycle)
 			break;
-		ehci->intr_unlink = qh->unlink_next;
-		qh->unlink_next = NULL;
+		list_del(&qh->unlink_node);
 		end_unlink_intr(ehci, qh);
 	}
 
 	/* Handle remaining entries later */
-	if (ehci->intr_unlink) {
+	if (!list_empty(&ehci->intr_unlink)) {
 		ehci_enable_event(ehci, EHCI_HRTIMER_UNLINK_INTR, true);
 		++ehci->intr_unlink_cycle;
 	}
@@ -295,8 +296,7 @@ static void end_free_itds(struct ehci_hcd *ehci)
 /* Handle lost (or very late) IAA interrupts */
 static void ehci_iaa_watchdog(struct ehci_hcd *ehci)
 {
-	if (ehci->rh_state != EHCI_RH_RUNNING)
-		return;
+	u32 cmd, status;
 
 	/*
 	 * Lost IAA irqs wedge things badly; seen first with a vt8235.
@@ -304,34 +304,32 @@ static void ehci_iaa_watchdog(struct ehci_hcd *ehci)
 	 * (a) SMP races against real IAA firing and retriggering, and
 	 * (b) clean HC shutdown, when IAA watchdog was pending.
 	 */
-	if (1) {
-		u32 cmd, status;
-
-		/* If we get here, IAA is *REALLY* late.  It's barely
-		 * conceivable that the system is so busy that CMD_IAAD
-		 * is still legitimately set, so let's be sure it's
-		 * clear before we read STS_IAA.  (The HC should clear
-		 * CMD_IAAD when it sets STS_IAA.)
-		 */
-		cmd = ehci_readl(ehci, &ehci->regs->command);
-
-		/*
-		 * If IAA is set here it either legitimately triggered
-		 * after the watchdog timer expired (_way_ late, so we'll
-		 * still count it as lost) ... or a silicon erratum:
-		 * - VIA seems to set IAA without triggering the IRQ;
-		 * - IAAD potentially cleared without setting IAA.
-		 */
-		status = ehci_readl(ehci, &ehci->regs->status);
-		if ((status & STS_IAA) || !(cmd & CMD_IAAD)) {
-			COUNT(ehci->stats.lost_iaa);
-			ehci_writel(ehci, STS_IAA, &ehci->regs->status);
-		}
+	if (!ehci->iaa_in_progress || ehci->rh_state != EHCI_RH_RUNNING)
+		return;
+
+	/* If we get here, IAA is *REALLY* late.  It's barely
+	 * conceivable that the system is so busy that CMD_IAAD
+	 * is still legitimately set, so let's be sure it's
+	 * clear before we read STS_IAA.  (The HC should clear
+	 * CMD_IAAD when it sets STS_IAA.)
+	 */
+	cmd = ehci_readl(ehci, &ehci->regs->command);
 
-		ehci_vdbg(ehci, "IAA watchdog: status %x cmd %x\n",
-				status, cmd);
-		end_unlink_async(ehci);
+	/*
+	 * If IAA is set here it either legitimately triggered
+	 * after the watchdog timer expired (_way_ late, so we'll
+	 * still count it as lost) ... or a silicon erratum:
+	 * - VIA seems to set IAA without triggering the IRQ;
+	 * - IAAD potentially cleared without setting IAA.
+	 */
+	status = ehci_readl(ehci, &ehci->regs->status);
+	if ((status & STS_IAA) || !(cmd & CMD_IAAD)) {
+		COUNT(ehci->stats.lost_iaa);
+		ehci_writel(ehci, STS_IAA, &ehci->regs->status);
 	}
+
+	ehci_dbg(ehci, "IAA watchdog: status %x cmd %x\n", status, cmd);
+	end_unlink_async(ehci);
 }
 
 
diff --git a/drivers/usb/host/ehci-vt8500.c b/drivers/usb/host/ehci-vt8500.c
deleted file mode 100644
index 7ecf709..0000000
--- a/drivers/usb/host/ehci-vt8500.c
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * drivers/usb/host/ehci-vt8500.c
- *
- * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
- *
- * Based on ehci-au1xxx.c
- *
- * 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/of.h>
-#include <linux/platform_device.h>
-
-static const struct hc_driver vt8500_ehci_hc_driver = {
-	.description		= hcd_name,
-	.product_desc		= "VT8500 EHCI",
-	.hcd_priv_size		= sizeof(struct ehci_hcd),
-
-	/*
-	 * generic hardware linkage
-	 */
-	.irq			= ehci_irq,
-	.flags			= HCD_MEMORY | HCD_USB2,
-
-	/*
-	 * basic lifecycle operations
-	 */
-	.reset			= ehci_setup,
-	.start			= ehci_run,
-	.stop			= ehci_stop,
-	.shutdown		= ehci_shutdown,
-
-	/*
-	 * managing i/o requests and associated device resources
-	 */
-	.urb_enqueue		= ehci_urb_enqueue,
-	.urb_dequeue		= ehci_urb_dequeue,
-	.endpoint_disable	= ehci_endpoint_disable,
-	.endpoint_reset		= ehci_endpoint_reset,
-
-	/*
-	 * scheduling support
-	 */
-	.get_frame_number	= ehci_get_frame,
-
-	/*
-	 * root hub support
-	 */
-	.hub_status_data	= ehci_hub_status_data,
-	.hub_control		= ehci_hub_control,
-	.bus_suspend		= ehci_bus_suspend,
-	.bus_resume		= ehci_bus_resume,
-	.relinquish_port	= ehci_relinquish_port,
-	.port_handed_over	= ehci_port_handed_over,
-
-	.clear_tt_buffer_complete	= ehci_clear_tt_buffer_complete,
-};
-
-static u64 vt8500_ehci_dma_mask = DMA_BIT_MASK(32);
-
-static int vt8500_ehci_drv_probe(struct platform_device *pdev)
-{
-	struct usb_hcd *hcd;
-	struct ehci_hcd *ehci;
-	struct resource *res;
-	int ret;
-
-	if (usb_disabled())
-		return -ENODEV;
-
-	/*
-	 * Right now device-tree probed devices don't get dma_mask set.
-	 * Since shared usb code relies on it, set it here for now.
-	 * Once we have dma capability bindings this can go away.
-	 */
-	if (!pdev->dev.dma_mask)
-		pdev->dev.dma_mask = &vt8500_ehci_dma_mask;
-
-	if (pdev->resource[1].flags != IORESOURCE_IRQ) {
-		pr_debug("resource[1] is not IORESOURCE_IRQ");
-		return -ENOMEM;
-	}
-	hcd = usb_create_hcd(&vt8500_ehci_hc_driver, &pdev->dev, "VT8500");
-	if (!hcd)
-		return -ENOMEM;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	hcd->rsrc_start = res->start;
-	hcd->rsrc_len = resource_size(res);
-
-	hcd->regs = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(hcd->regs)) {
-		ret = PTR_ERR(hcd->regs);
-		goto err1;
-	}
-
-	ehci = hcd_to_ehci(hcd);
-	ehci->caps = hcd->regs;
-
-	ret = usb_add_hcd(hcd, pdev->resource[1].start,
-			  IRQF_SHARED);
-	if (ret == 0) {
-		platform_set_drvdata(pdev, hcd);
-		return ret;
-	}
-
-err1:
-	usb_put_hcd(hcd);
-	return ret;
-}
-
-static int vt8500_ehci_drv_remove(struct platform_device *pdev)
-{
-	struct usb_hcd *hcd = platform_get_drvdata(pdev);
-
-	usb_remove_hcd(hcd);
-	usb_put_hcd(hcd);
-	platform_set_drvdata(pdev, NULL);
-
-	return 0;
-}
-
-static const struct of_device_id vt8500_ehci_ids[] = {
-	{ .compatible = "via,vt8500-ehci", },
-	{ .compatible = "wm,prizm-ehci", },
-	{}
-};
-
-static struct platform_driver vt8500_ehci_driver = {
-	.probe		= vt8500_ehci_drv_probe,
-	.remove		= vt8500_ehci_drv_remove,
-	.shutdown	= usb_hcd_platform_shutdown,
-	.driver = {
-		.name	= "vt8500-ehci",
-		.owner	= THIS_MODULE,
-		.of_match_table = of_match_ptr(vt8500_ehci_ids),
-	}
-};
-
-MODULE_ALIAS("platform:vt8500-ehci");
-MODULE_DEVICE_TABLE(of, vt8500_ehci_ids);
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 36c3a82..7c978b2 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -121,6 +121,7 @@ struct ehci_hcd {			/* one per controller */
 	bool			scanning:1;
 	bool			need_rescan:1;
 	bool			intr_unlinking:1;
+	bool			iaa_in_progress:1;
 	bool			async_unlinking:1;
 	bool			shutdown:1;
 	struct ehci_qh		*qh_scan_next;
@@ -128,9 +129,8 @@ struct ehci_hcd {			/* one per controller */
 	/* async schedule support */
 	struct ehci_qh		*async;
 	struct ehci_qh		*dummy;		/* For AMD quirk use */
-	struct ehci_qh		*async_unlink;
-	struct ehci_qh		*async_unlink_last;
-	struct ehci_qh		*async_iaa;
+	struct list_head	async_unlink;
+	struct list_head	async_idle;
 	unsigned		async_unlink_cycle;
 	unsigned		async_count;	/* async activity count */
 
@@ -143,8 +143,7 @@ struct ehci_hcd {			/* one per controller */
 	unsigned		i_thresh;	/* uframes HC might cache */
 
 	union ehci_shadow	*pshadow;	/* mirror hw periodic table */
-	struct ehci_qh		*intr_unlink;
-	struct ehci_qh		*intr_unlink_last;
+	struct list_head	intr_unlink;
 	unsigned		intr_unlink_cycle;
 	unsigned		now_frame;	/* frame from HC hardware */
 	unsigned		last_iso_frame;	/* last frame scanned for iso */
@@ -200,6 +199,7 @@ struct ehci_hcd {			/* one per controller */
 	unsigned		use_dummy_qh:1;	/* AMD Frame List table quirk*/
 	unsigned		has_synopsys_hc_bug:1; /* Synopsys HC */
 	unsigned		frame_index_bug:1; /* MosChip (AKA NetMos) */
+	unsigned		need_oc_pp_cycle:1; /* MPC834X port power */
 
 	/* required for usb32 quirk */
 	#define OHCI_CTRL_HCFS          (3 << 6)
@@ -380,11 +380,10 @@ struct ehci_qh {
 	struct list_head	qtd_list;	/* sw qtd list */
 	struct list_head	intr_node;	/* list of intr QHs */
 	struct ehci_qtd		*dummy;
-	struct ehci_qh		*unlink_next;	/* next on unlink list */
+	struct list_head	unlink_node;
 
 	unsigned		unlink_cycle;
 
-	u8			needs_rescan;	/* Dequeue during giveback */
 	u8			qh_state;
 #define	QH_STATE_LINKED		1		/* HC sees this */
 #define	QH_STATE_UNLINK		2		/* HC may still see this */
@@ -407,6 +406,9 @@ struct ehci_qh {
 	struct usb_device	*dev;		/* access to TT */
 	unsigned		is_out:1;	/* bulk or intr OUT */
 	unsigned		clearing_tt:1;	/* Clear-TT-Buf in progress */
+	unsigned		dequeue_during_giveback:1;
+	unsigned		exception:1;	/* got a fault, or an unlink
+						   was requested */
 };
 
 /*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c
index 974480c..b04e8ec 100644
--- a/drivers/usb/host/isp1362-hcd.c
+++ b/drivers/usb/host/isp1362-hcd.c
@@ -2175,7 +2175,7 @@ static int proc_isp1362_show(struct seq_file *s, void *unused)
 
 static int proc_isp1362_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, proc_isp1362_show, PDE(inode)->data);
+	return single_open(file, proc_isp1362_show, PDE_DATA(inode));
 }
 
 static const struct file_operations proc_ops = {
@@ -2192,14 +2192,11 @@ static void create_debug_file(struct isp1362_hcd *isp1362_hcd)
 {
 	struct proc_dir_entry *pde;
 
-	pde = create_proc_entry(proc_filename, 0, NULL);
+	pde = proc_create_data(proc_filename, 0, NULL, &proc_ops, isp1362_hcd);
 	if (pde == NULL) {
 		pr_warning("%s: Failed to create debug file '%s'\n", __func__, proc_filename);
 		return;
 	}
-
-	pde->proc_fops = &proc_ops;
-	pde->data = isp1362_hcd;
 	isp1362_hcd->pde = pde;
 }
 
diff --git a/drivers/usb/host/ohci-exynos.c b/drivers/usb/host/ohci-exynos.c
index e3b7e85..4b469e0 100644
--- a/drivers/usb/host/ohci-exynos.c
+++ b/drivers/usb/host/ohci-exynos.c
@@ -128,7 +128,7 @@ static int exynos_ohci_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
-	if (IS_ERR_OR_NULL(phy)) {
+	if (IS_ERR(phy)) {
 		/* Fallback to pdata */
 		if (!pdata) {
 			dev_warn(&pdev->dev, "no platform data or transceiver defined\n");
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
index db09dae..60ff422 100644
--- a/drivers/usb/host/ohci-hub.c
+++ b/drivers/usb/host/ohci-hub.c
@@ -580,14 +580,8 @@ static int ohci_start_port_reset (struct usb_hcd *hcd, unsigned port)
 
 /* See usb 7.1.7.5:  root hubs must issue at least 50 msec reset signaling,
  * not necessarily continuous ... to guard against resume signaling.
- * The short timeout is safe for non-root hubs, and is backward-compatible
- * with earlier Linux hosts.
  */
-#ifdef	CONFIG_USB_SUSPEND
 #define	PORT_RESET_MSEC		50
-#else
-#define	PORT_RESET_MSEC		10
-#endif
 
 /* this timer value might be vendor-specific ... */
 #define	PORT_RESET_HW_MSEC	10
diff --git a/drivers/usb/host/ohci-omap3.c b/drivers/usb/host/ohci-omap3.c
index eb35d96..ddfc314 100644
--- a/drivers/usb/host/ohci-omap3.c
+++ b/drivers/usb/host/ohci-omap3.c
@@ -31,6 +31,8 @@
 
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
+#include <linux/of.h>
+#include <linux/dma-mapping.h>
 
 /*-------------------------------------------------------------------------*/
 
@@ -112,6 +114,8 @@ static const struct hc_driver ohci_omap3_hc_driver = {
 
 /*-------------------------------------------------------------------------*/
 
+static u64 omap_ohci_dma_mask = DMA_BIT_MASK(32);
+
 /*
  * configure so an HC device and id are always provided
  * always called with process context; sleeping is OK
@@ -141,14 +145,13 @@ static int ohci_hcd_omap3_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
-	irq = platform_get_irq_byname(pdev, "ohci-irq");
+	irq = platform_get_irq(pdev, 0);
 	if (irq < 0) {
 		dev_err(dev, "OHCI irq failed\n");
 		return -ENODEV;
 	}
 
-	res = platform_get_resource_byname(pdev,
-				IORESOURCE_MEM, "ohci");
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res) {
 		dev_err(dev, "UHH OHCI get resource failed\n");
 		return -ENOMEM;
@@ -160,6 +163,13 @@ static int ohci_hcd_omap3_probe(struct platform_device *pdev)
 		return -ENOMEM;
 	}
 
+	/*
+	 * Right now device-tree probed devices don't get dma_mask set.
+	 * Since shared usb code relies on it, set it here for now.
+	 * Once we have dma capability bindings this can go away.
+	 */
+	if (!pdev->dev.dma_mask)
+		pdev->dev.dma_mask = &omap_ohci_dma_mask;
 
 	hcd = usb_create_hcd(&ohci_omap3_hc_driver, dev,
 			dev_name(dev));
@@ -229,12 +239,20 @@ static void ohci_hcd_omap3_shutdown(struct platform_device *pdev)
 		hcd->driver->shutdown(hcd);
 }
 
+static const struct of_device_id omap_ohci_dt_ids[] = {
+	{ .compatible = "ti,ohci-omap3" },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(of, omap_ohci_dt_ids);
+
 static struct platform_driver ohci_hcd_omap3_driver = {
 	.probe		= ohci_hcd_omap3_probe,
 	.remove		= ohci_hcd_omap3_remove,
 	.shutdown	= ohci_hcd_omap3_shutdown,
 	.driver		= {
 		.name	= "ohci-omap3",
+		.of_match_table = of_match_ptr(omap_ohci_dt_ids),
 	},
 };
 
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
index d62f040..ad4483e 100644
--- a/drivers/usb/host/sl811-hcd.c
+++ b/drivers/usb/host/sl811-hcd.c
@@ -1494,7 +1494,7 @@ static int proc_sl811h_show(struct seq_file *s, void *unused)
 
 static int proc_sl811h_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, proc_sl811h_show, PDE(inode)->data);
+	return single_open(file, proc_sl811h_show, PDE_DATA(inode));
 }
 
 static const struct file_operations proc_ops = {
@@ -1755,7 +1755,7 @@ sl811h_probe(struct platform_device *dev)
 
 /* for this device there's no useful distinction between the controller
  * and its root hub, except that the root hub only gets direct PM calls
- * when CONFIG_USB_SUSPEND is enabled.
+ * when CONFIG_PM_RUNTIME is enabled.
  */
 
 static int
diff --git a/drivers/usb/host/sl811_cs.c b/drivers/usb/host/sl811_cs.c
index 3b6f50e..469564e 100644
--- a/drivers/usb/host/sl811_cs.c
+++ b/drivers/usb/host/sl811_cs.c
@@ -200,17 +200,4 @@ static struct pcmcia_driver sl811_cs_driver = {
 	.remove		= sl811_cs_detach,
 	.id_table	= sl811_ids,
 };
-
-/*====================================================================*/
-
-static int __init init_sl811_cs(void)
-{
-	return pcmcia_register_driver(&sl811_cs_driver);
-}
-module_init(init_sl811_cs);
-
-static void __exit exit_sl811_cs(void)
-{
-	pcmcia_unregister_driver(&sl811_cs_driver);
-}
-module_exit(exit_sl811_cs);
+module_pcmcia_driver(sl811_cs_driver);
diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c
index 5efdffe..5c124bf 100644
--- a/drivers/usb/host/u132-hcd.c
+++ b/drivers/usb/host/u132-hcd.c
@@ -3141,10 +3141,11 @@ static int u132_probe(struct platform_device *pdev)
 
 
 #ifdef CONFIG_PM
-/* for this device there's no useful distinction between the controller
-* and its root hub, except that the root hub only gets direct PM calls
-* when CONFIG_USB_SUSPEND is enabled.
-*/
+/*
+ * for this device there's no useful distinction between the controller
+ * and its root hub, except that the root hub only gets direct PM calls
+ * when CONFIG_PM_RUNTIME is enabled.
+ */
 static int u132_suspend(struct platform_device *pdev, pm_message_t state)
 {
 	struct usb_hcd *hcd = platform_get_drvdata(pdev);
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 6891442..187a3ec 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -1075,7 +1075,7 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
 			set_bit(port_index, &bus_state->bus_suspended);
 		}
 		/* USB core sets remote wake mask for USB 3.0 hubs,
-		 * including the USB 3.0 roothub, but only if CONFIG_USB_SUSPEND
+		 * including the USB 3.0 roothub, but only if CONFIG_PM_RUNTIME
 		 * is enabled, so also enable remote wake here.
 		 */
 		if (hcd->self.root_hub->do_remote_wakeup) {
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 53b8f89..5156b72 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -3801,7 +3801,7 @@ int xhci_find_raw_port_number(struct usb_hcd *hcd, int port1)
 	return raw_port;
 }
 
-#ifdef CONFIG_USB_SUSPEND
+#ifdef CONFIG_PM_RUNTIME
 
 /* BESL to HIRD Encoding array for USB2 LPM */
 static int xhci_besl_encoding[16] = {125, 150, 200, 300, 400, 500, 1000, 2000,
@@ -4051,7 +4051,7 @@ int xhci_update_device(struct usb_hcd *hcd, struct usb_device *udev)
 	return 0;
 }
 
-#endif /* CONFIG_USB_SUSPEND */
+#endif /* CONFIG_PM_RUNTIME */
 
 /*---------------------- USB 3.0 Link PM functions ------------------------*/
 
diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c
index 0fc6e5f..ba6a5d6 100644
--- a/drivers/usb/misc/appledisplay.c
+++ b/drivers/usb/misc/appledisplay.c
@@ -63,6 +63,7 @@ static const struct usb_device_id appledisplay_table[] = {
 	{ APPLEDISPLAY_DEVICE(0x9219) },
 	{ APPLEDISPLAY_DEVICE(0x921c) },
 	{ APPLEDISPLAY_DEVICE(0x921d) },
+	{ APPLEDISPLAY_DEVICE(0x9236) },
 
 	/* Terminating entry */
 	{ }
diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c
index dd573ab..c21386e 100644
--- a/drivers/usb/misc/sisusbvga/sisusb.c
+++ b/drivers/usb/misc/sisusbvga/sisusb.c
@@ -3084,7 +3084,7 @@ static int sisusb_probe(struct usb_interface *intf,
 
 	/* Allocate memory for our private */
 	if (!(sisusb = kzalloc(sizeof(*sisusb), GFP_KERNEL))) {
-		dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate memory for private data\n");
+		dev_err(&dev->dev, "Failed to allocate memory for private data\n");
 		return -ENOMEM;
 	}
 	kref_init(&sisusb->kref);
diff --git a/drivers/usb/misc/usb3503.c b/drivers/usb/misc/usb3503.c
index f713f6a..d3a1cce 100644
--- a/drivers/usb/misc/usb3503.c
+++ b/drivers/usb/misc/usb3503.c
@@ -307,18 +307,7 @@ static struct i2c_driver usb3503_driver = {
 	.id_table	= usb3503_id,
 };
 
-static int __init usb3503_init(void)
-{
-	return i2c_add_driver(&usb3503_driver);
-}
-
-static void __exit usb3503_exit(void)
-{
-	i2c_del_driver(&usb3503_driver);
-}
-
-module_init(usb3503_init);
-module_exit(usb3503_exit);
+module_i2c_driver(usb3503_driver);
 
 MODULE_AUTHOR("Dongjin Kim <tobetter@gmail.com>");
 MODULE_DESCRIPTION("USB3503 USB HUB driver");
diff --git a/drivers/usb/misc/uss720.c b/drivers/usb/misc/uss720.c
index 29cad9e..e129cf6 100644
--- a/drivers/usb/misc/uss720.c
+++ b/drivers/usb/misc/uss720.c
@@ -705,7 +705,7 @@ static int uss720_probe(struct usb_interface *intf,
 		return -ENODEV;
 	}
 	i = usb_set_interface(usbdev, intf->altsetting->desc.bInterfaceNumber, 2);
-	dev_dbg(&intf->dev, "set inteface result %d\n", i);
+	dev_dbg(&intf->dev, "set interface result %d\n", i);
 
 	interface = intf->cur_altsetting;
 
diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig
index 05e5143..47442d3 100644
--- a/drivers/usb/musb/Kconfig
+++ b/drivers/usb/musb/Kconfig
@@ -7,7 +7,6 @@
 config USB_MUSB_HDRC
 	tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)'
 	depends on USB && USB_GADGET
-	select USB_OTG_UTILS
 	help
 	  Say Y here if your system has a dual role high speed USB
 	  controller based on the Mentor Graphics silicon IP.  Then
@@ -34,10 +33,12 @@ choice
 config USB_MUSB_DAVINCI
 	tristate "DaVinci"
 	depends on ARCH_DAVINCI_DMx
+	depends on BROKEN
 
 config USB_MUSB_DA8XX
 	tristate "DA8xx/OMAP-L1x"
 	depends on ARCH_DAVINCI_DA8XX
+	depends on BROKEN
 
 config USB_MUSB_TUSB6010
 	tristate "TUSB6010"
@@ -53,7 +54,6 @@ config USB_MUSB_AM35X
 
 config USB_MUSB_DSPS
 	tristate "TI DSPS platforms"
-	depends on SOC_TI81XX || SOC_AM33XX
 
 config USB_MUSB_BLACKFIN
 	tristate "Blackfin"
@@ -61,12 +61,12 @@ config USB_MUSB_BLACKFIN
 
 config USB_MUSB_UX500
 	tristate "U8500 and U5500"
-	depends on (ARCH_U8500 && AB8500_USB)
 
 endchoice
 
 choice
 	prompt 'MUSB DMA mode'
+	default MUSB_PIO_ONLY if ARCH_MULTIPLATFORM
 	default USB_UX500_DMA if USB_MUSB_UX500
 	default USB_INVENTRA_DMA if USB_MUSB_OMAP2PLUS || USB_MUSB_BLACKFIN
 	default USB_TI_CPPI_DMA if USB_MUSB_DAVINCI
diff --git a/drivers/usb/musb/am35x.c b/drivers/usb/musb/am35x.c
index 59eea21..2231850 100644
--- a/drivers/usb/musb/am35x.c
+++ b/drivers/usb/musb/am35x.c
@@ -149,7 +149,7 @@ static void otg_timer(unsigned long _musb)
 	 */
 	devctl = musb_readb(mregs, MUSB_DEVCTL);
 	dev_dbg(musb->controller, "Poll devctl %02x (%s)\n", devctl,
-		otg_state_string(musb->xceiv->state));
+		usb_otg_state_string(musb->xceiv->state));
 
 	spin_lock_irqsave(&musb->lock, flags);
 	switch (musb->xceiv->state) {
@@ -195,7 +195,7 @@ static void am35x_musb_try_idle(struct musb *musb, unsigned long timeout)
 	if (musb->is_active || (musb->a_wait_bcon == 0 &&
 				musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) {
 		dev_dbg(musb->controller, "%s active, deleting timer\n",
-			otg_state_string(musb->xceiv->state));
+			usb_otg_state_string(musb->xceiv->state));
 		del_timer(&otg_workaround);
 		last_timer = jiffies;
 		return;
@@ -208,7 +208,7 @@ static void am35x_musb_try_idle(struct musb *musb, unsigned long timeout)
 	last_timer = timeout;
 
 	dev_dbg(musb->controller, "%s inactive, starting idle timer for %u ms\n",
-		otg_state_string(musb->xceiv->state),
+		usb_otg_state_string(musb->xceiv->state),
 		jiffies_to_msecs(timeout - jiffies));
 	mod_timer(&otg_workaround, timeout);
 }
@@ -298,7 +298,7 @@ static irqreturn_t am35x_musb_interrupt(int irq, void *hci)
 		/* NOTE: this must complete power-on within 100 ms. */
 		dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n",
 				drvvbus ? "on" : "off",
-				otg_state_string(musb->xceiv->state),
+				usb_otg_state_string(musb->xceiv->state),
 				err ? " ERROR" : "",
 				devctl);
 		ret = IRQ_HANDLED;
diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c
index dbb31b3..5e63b16 100644
--- a/drivers/usb/musb/blackfin.c
+++ b/drivers/usb/musb/blackfin.c
@@ -280,13 +280,13 @@ static void musb_conn_timer_handler(unsigned long _musb)
 		break;
 	default:
 		dev_dbg(musb->controller, "%s state not handled\n",
-			otg_state_string(musb->xceiv->state));
+			usb_otg_state_string(musb->xceiv->state));
 		break;
 	}
 	spin_unlock_irqrestore(&musb->lock, flags);
 
 	dev_dbg(musb->controller, "state is %s\n",
-		otg_state_string(musb->xceiv->state));
+		usb_otg_state_string(musb->xceiv->state));
 }
 
 static void bfin_musb_enable(struct musb *musb)
@@ -307,7 +307,7 @@ static void bfin_musb_set_vbus(struct musb *musb, int is_on)
 
 	dev_dbg(musb->controller, "VBUS %s, devctl %02x "
 		/* otg %3x conf %08x prcm %08x */ "\n",
-		otg_state_string(musb->xceiv->state),
+		usb_otg_state_string(musb->xceiv->state),
 		musb_readb(musb->mregs, MUSB_DEVCTL));
 }
 
diff --git a/drivers/usb/musb/cppi_dma.c b/drivers/usb/musb/cppi_dma.c
index f522000..9db211e 100644
--- a/drivers/usb/musb/cppi_dma.c
+++ b/drivers/usb/musb/cppi_dma.c
@@ -435,7 +435,6 @@ cppi_rndis_update(struct cppi_channel *c, int is_rx,
 	}
 }
 
-#ifdef CONFIG_USB_MUSB_DEBUG
 static void cppi_dump_rxbd(const char *tag, struct cppi_descriptor *bd)
 {
 	pr_debug("RXBD/%s %08x: "
@@ -444,21 +443,16 @@ static void cppi_dump_rxbd(const char *tag, struct cppi_descriptor *bd)
 			bd->hw_next, bd->hw_bufp, bd->hw_off_len,
 			bd->hw_options);
 }
-#endif
 
 static void cppi_dump_rxq(int level, const char *tag, struct cppi_channel *rx)
 {
-#ifdef CONFIG_USB_MUSB_DEBUG
 	struct cppi_descriptor	*bd;
 
-	if (!_dbg_level(level))
-		return;
 	cppi_dump_rx(level, rx, tag);
 	if (rx->last_processed)
 		cppi_dump_rxbd("last", rx->last_processed);
 	for (bd = rx->head; bd; bd = bd->next)
 		cppi_dump_rxbd("active", bd);
-#endif
 }
 
 
@@ -784,6 +778,7 @@ cppi_next_rx_segment(struct musb *musb, struct cppi_channel *rx, int onepacket)
 	void __iomem		*tibase = musb->ctrl_base;
 	int			is_rndis = 0;
 	struct cppi_rx_stateram	__iomem *rx_ram = rx->state_ram;
+	struct cppi_descriptor	*d;
 
 	if (onepacket) {
 		/* almost every USB driver, host or peripheral side */
@@ -897,14 +892,8 @@ cppi_next_rx_segment(struct musb *musb, struct cppi_channel *rx, int onepacket)
 	bd->hw_options |= CPPI_SOP_SET;
 	tail->hw_options |= CPPI_EOP_SET;
 
-#ifdef CONFIG_USB_MUSB_DEBUG
-	if (_dbg_level(5)) {
-		struct cppi_descriptor	*d;
-
-		for (d = rx->head; d; d = d->next)
-			cppi_dump_rxbd("S", d);
-	}
-#endif
+	for (d = rx->head; d; d = d->next)
+		cppi_dump_rxbd("S", d);
 
 	/* in case the preceding transfer left some state... */
 	tail = rx->last_processed;
diff --git a/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c
index 41613a2..b903b74 100644
--- a/drivers/usb/musb/da8xx.c
+++ b/drivers/usb/musb/da8xx.c
@@ -198,7 +198,7 @@ static void otg_timer(unsigned long _musb)
 	 */
 	devctl = musb_readb(mregs, MUSB_DEVCTL);
 	dev_dbg(musb->controller, "Poll devctl %02x (%s)\n", devctl,
-		otg_state_string(musb->xceiv->state));
+		usb_otg_state_string(musb->xceiv->state));
 
 	spin_lock_irqsave(&musb->lock, flags);
 	switch (musb->xceiv->state) {
@@ -267,7 +267,7 @@ static void da8xx_musb_try_idle(struct musb *musb, unsigned long timeout)
 	if (musb->is_active || (musb->a_wait_bcon == 0 &&
 				musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) {
 		dev_dbg(musb->controller, "%s active, deleting timer\n",
-			otg_state_string(musb->xceiv->state));
+			usb_otg_state_string(musb->xceiv->state));
 		del_timer(&otg_workaround);
 		last_timer = jiffies;
 		return;
@@ -280,7 +280,7 @@ static void da8xx_musb_try_idle(struct musb *musb, unsigned long timeout)
 	last_timer = timeout;
 
 	dev_dbg(musb->controller, "%s inactive, starting idle timer for %u ms\n",
-		otg_state_string(musb->xceiv->state),
+		usb_otg_state_string(musb->xceiv->state),
 		jiffies_to_msecs(timeout - jiffies));
 	mod_timer(&otg_workaround, timeout);
 }
@@ -360,7 +360,7 @@ static irqreturn_t da8xx_musb_interrupt(int irq, void *hci)
 
 		dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n",
 				drvvbus ? "on" : "off",
-				otg_state_string(musb->xceiv->state),
+				usb_otg_state_string(musb->xceiv->state),
 				err ? " ERROR" : "",
 				devctl);
 		ret = IRQ_HANDLED;
diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c
index e040d91..bea6cc3 100644
--- a/drivers/usb/musb/davinci.c
+++ b/drivers/usb/musb/davinci.c
@@ -215,7 +215,7 @@ static void otg_timer(unsigned long _musb)
 	 */
 	devctl = musb_readb(mregs, MUSB_DEVCTL);
 	dev_dbg(musb->controller, "poll devctl %02x (%s)\n", devctl,
-		otg_state_string(musb->xceiv->state));
+		usb_otg_state_string(musb->xceiv->state));
 
 	spin_lock_irqsave(&musb->lock, flags);
 	switch (musb->xceiv->state) {
@@ -349,7 +349,7 @@ static irqreturn_t davinci_musb_interrupt(int irq, void *__hci)
 		davinci_musb_source_power(musb, drvvbus, 0);
 		dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n",
 				drvvbus ? "on" : "off",
-				otg_state_string(musb->xceiv->state),
+				usb_otg_state_string(musb->xceiv->state),
 				err ? " ERROR" : "",
 				devctl);
 		retval = IRQ_HANDLED;
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index daec6e0..37a261a 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -372,13 +372,13 @@ static void musb_otg_timer_func(unsigned long data)
 	case OTG_STATE_A_SUSPEND:
 	case OTG_STATE_A_WAIT_BCON:
 		dev_dbg(musb->controller, "HNP: %s timeout\n",
-			otg_state_string(musb->xceiv->state));
+			usb_otg_state_string(musb->xceiv->state));
 		musb_platform_set_vbus(musb, 0);
 		musb->xceiv->state = OTG_STATE_A_WAIT_VFALL;
 		break;
 	default:
 		dev_dbg(musb->controller, "HNP: Unhandled mode %s\n",
-			otg_state_string(musb->xceiv->state));
+			usb_otg_state_string(musb->xceiv->state));
 	}
 	musb->ignore_disconnect = 0;
 	spin_unlock_irqrestore(&musb->lock, flags);
@@ -393,13 +393,14 @@ void musb_hnp_stop(struct musb *musb)
 	void __iomem	*mbase = musb->mregs;
 	u8	reg;
 
-	dev_dbg(musb->controller, "HNP: stop from %s\n", otg_state_string(musb->xceiv->state));
+	dev_dbg(musb->controller, "HNP: stop from %s\n",
+			usb_otg_state_string(musb->xceiv->state));
 
 	switch (musb->xceiv->state) {
 	case OTG_STATE_A_PERIPHERAL:
 		musb_g_disconnect(musb);
 		dev_dbg(musb->controller, "HNP: back to %s\n",
-			otg_state_string(musb->xceiv->state));
+			usb_otg_state_string(musb->xceiv->state));
 		break;
 	case OTG_STATE_B_HOST:
 		dev_dbg(musb->controller, "HNP: Disabling HR\n");
@@ -413,7 +414,7 @@ void musb_hnp_stop(struct musb *musb)
 		break;
 	default:
 		dev_dbg(musb->controller, "HNP: Stopping in unknown state %s\n",
-			otg_state_string(musb->xceiv->state));
+			usb_otg_state_string(musb->xceiv->state));
 	}
 
 	/*
@@ -451,7 +452,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
 	 */
 	if (int_usb & MUSB_INTR_RESUME) {
 		handled = IRQ_HANDLED;
-		dev_dbg(musb->controller, "RESUME (%s)\n", otg_state_string(musb->xceiv->state));
+		dev_dbg(musb->controller, "RESUME (%s)\n", usb_otg_state_string(musb->xceiv->state));
 
 		if (devctl & MUSB_DEVCTL_HM) {
 			void __iomem *mbase = musb->mregs;
@@ -493,7 +494,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
 			default:
 				WARNING("bogus %s RESUME (%s)\n",
 					"host",
-					otg_state_string(musb->xceiv->state));
+					usb_otg_state_string(musb->xceiv->state));
 			}
 		} else {
 			switch (musb->xceiv->state) {
@@ -522,7 +523,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
 			default:
 				WARNING("bogus %s RESUME (%s)\n",
 					"peripheral",
-					otg_state_string(musb->xceiv->state));
+					usb_otg_state_string(musb->xceiv->state));
 			}
 		}
 	}
@@ -538,7 +539,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
 		}
 
 		dev_dbg(musb->controller, "SESSION_REQUEST (%s)\n",
-			otg_state_string(musb->xceiv->state));
+			usb_otg_state_string(musb->xceiv->state));
 
 		/* IRQ arrives from ID pin sense or (later, if VBUS power
 		 * is removed) SRP.  responses are time critical:
@@ -602,8 +603,9 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
 			break;
 		}
 
-		dev_dbg(musb->controller, "VBUS_ERROR in %s (%02x, %s), retry #%d, port1 %08x\n",
-				otg_state_string(musb->xceiv->state),
+		dev_printk(ignore ? KERN_DEBUG : KERN_ERR, musb->controller,
+				"VBUS_ERROR in %s (%02x, %s), retry #%d, port1 %08x\n",
+				usb_otg_state_string(musb->xceiv->state),
 				devctl,
 				({ char *s;
 				switch (devctl & MUSB_DEVCTL_VBUS) {
@@ -628,7 +630,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
 
 	if (int_usb & MUSB_INTR_SUSPEND) {
 		dev_dbg(musb->controller, "SUSPEND (%s) devctl %02x\n",
-			otg_state_string(musb->xceiv->state), devctl);
+			usb_otg_state_string(musb->xceiv->state), devctl);
 		handled = IRQ_HANDLED;
 
 		switch (musb->xceiv->state) {
@@ -745,12 +747,12 @@ b_host:
 			usb_hcd_resume_root_hub(hcd);
 
 		dev_dbg(musb->controller, "CONNECT (%s) devctl %02x\n",
-				otg_state_string(musb->xceiv->state), devctl);
+				usb_otg_state_string(musb->xceiv->state), devctl);
 	}
 
 	if ((int_usb & MUSB_INTR_DISCONNECT) && !musb->ignore_disconnect) {
 		dev_dbg(musb->controller, "DISCONNECT (%s) as %s, devctl %02x\n",
-				otg_state_string(musb->xceiv->state),
+				usb_otg_state_string(musb->xceiv->state),
 				MUSB_MODE(musb), devctl);
 		handled = IRQ_HANDLED;
 
@@ -787,7 +789,7 @@ b_host:
 			break;
 		default:
 			WARNING("unhandled DISCONNECT transition (%s)\n",
-				otg_state_string(musb->xceiv->state));
+				usb_otg_state_string(musb->xceiv->state));
 			break;
 		}
 	}
@@ -813,7 +815,7 @@ b_host:
 			}
 		} else {
 			dev_dbg(musb->controller, "BUS RESET as %s\n",
-				otg_state_string(musb->xceiv->state));
+				usb_otg_state_string(musb->xceiv->state));
 			switch (musb->xceiv->state) {
 			case OTG_STATE_A_SUSPEND:
 				/* We need to ignore disconnect on suspend
@@ -826,7 +828,7 @@ b_host:
 			case OTG_STATE_A_WAIT_BCON:	/* OPT TD.4.7-900ms */
 				/* never use invalid T(a_wait_bcon) */
 				dev_dbg(musb->controller, "HNP: in %s, %d msec timeout\n",
-					otg_state_string(musb->xceiv->state),
+					usb_otg_state_string(musb->xceiv->state),
 					TA_WAIT_BCON(musb));
 				mod_timer(&musb->otg_timer, jiffies
 					+ msecs_to_jiffies(TA_WAIT_BCON(musb)));
@@ -838,7 +840,7 @@ b_host:
 				break;
 			case OTG_STATE_B_WAIT_ACON:
 				dev_dbg(musb->controller, "HNP: RESET (%s), to b_peripheral\n",
-					otg_state_string(musb->xceiv->state));
+					usb_otg_state_string(musb->xceiv->state));
 				musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
 				musb_g_reset(musb);
 				break;
@@ -850,7 +852,7 @@ b_host:
 				break;
 			default:
 				dev_dbg(musb->controller, "Unhandled BUS RESET as %s\n",
-					otg_state_string(musb->xceiv->state));
+					usb_otg_state_string(musb->xceiv->state));
 			}
 		}
 	}
@@ -1632,7 +1634,7 @@ musb_mode_show(struct device *dev, struct device_attribute *attr, char *buf)
 	int ret = -EINVAL;
 
 	spin_lock_irqsave(&musb->lock, flags);
-	ret = sprintf(buf, "%s\n", otg_state_string(musb->xceiv->state));
+	ret = sprintf(buf, "%s\n", usb_otg_state_string(musb->xceiv->state));
 	spin_unlock_irqrestore(&musb->lock, flags);
 
 	return ret;
@@ -1951,9 +1953,13 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
 		musb_write_ulpi_buscontrol(musb->mregs, busctl);
 	}
 
-	MUSB_DEV_MODE(musb);
-	musb->xceiv->otg->default_a = 0;
-	musb->xceiv->state = OTG_STATE_B_IDLE;
+	if (musb->xceiv->otg->default_a) {
+		MUSB_HST_MODE(musb);
+		musb->xceiv->state = OTG_STATE_A_IDLE;
+	} else {
+		MUSB_DEV_MODE(musb);
+		musb->xceiv->state = OTG_STATE_B_IDLE;
+	}
 
 	status = musb_gadget_setup(musb);
 
@@ -2008,7 +2014,6 @@ static int musb_probe(struct platform_device *pdev)
 {
 	struct device	*dev = &pdev->dev;
 	int		irq = platform_get_irq_byname(pdev, "mc");
-	int		status;
 	struct resource	*iomem;
 	void __iomem	*base;
 
@@ -2016,24 +2021,17 @@ static int musb_probe(struct platform_device *pdev)
 	if (!iomem || irq <= 0)
 		return -ENODEV;
 
-	base = ioremap(iomem->start, resource_size(iomem));
-	if (!base) {
-		dev_err(dev, "ioremap failed\n");
-		return -ENOMEM;
-	}
+	base = devm_ioremap_resource(dev, iomem);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
 
-	status = musb_init_controller(dev, irq, base);
-	if (status < 0)
-		iounmap(base);
-
-	return status;
+	return musb_init_controller(dev, irq, base);
 }
 
 static int musb_remove(struct platform_device *pdev)
 {
 	struct device	*dev = &pdev->dev;
 	struct musb	*musb = dev_to_musb(dev);
-	void __iomem	*ctrl_base = musb->ctrl_base;
 
 	/* this gets called on rmmod.
 	 *  - Host mode: host may still be active
@@ -2044,7 +2042,6 @@ static int musb_remove(struct platform_device *pdev)
 	musb_shutdown(pdev);
 
 	musb_free(musb);
-	iounmap(ctrl_base);
 	device_init_wakeup(dev, 0);
 #ifndef CONFIG_MUSB_PIO_ONLY
 	dma_set_mask(dev, *dev->parent->dma_mask);
@@ -2293,8 +2290,6 @@ static int __init musb_init(void)
 	if (usb_disabled())
 		return 0;
 
-	pr_info("%s: version " MUSB_VERSION ", ?dma?, otg (peripheral+host)\n",
-		musb_driver_name);
 	return platform_driver_register(&musb_driver);
 }
 module_init(musb_init);
diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c
index 6bb8971..3a18e44 100644
--- a/drivers/usb/musb/musb_dsps.c
+++ b/drivers/usb/musb/musb_dsps.c
@@ -38,6 +38,7 @@
 #include <linux/module.h>
 #include <linux/usb/nop-usb-xceiv.h>
 #include <linux/platform_data/usb-omap.h>
+#include <linux/sizes.h>
 
 #include <linux/of.h>
 #include <linux/of_device.h>
@@ -224,7 +225,7 @@ static void otg_timer(unsigned long _musb)
 	 */
 	devctl = dsps_readb(mregs, MUSB_DEVCTL);
 	dev_dbg(musb->controller, "Poll devctl %02x (%s)\n", devctl,
-				otg_state_string(musb->xceiv->state));
+				usb_otg_state_string(musb->xceiv->state));
 
 	spin_lock_irqsave(&musb->lock, flags);
 	switch (musb->xceiv->state) {
@@ -273,7 +274,7 @@ static void dsps_musb_try_idle(struct musb *musb, unsigned long timeout)
 	if (musb->is_active || (musb->a_wait_bcon == 0 &&
 				musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) {
 		dev_dbg(musb->controller, "%s active, deleting timer\n",
-				otg_state_string(musb->xceiv->state));
+				usb_otg_state_string(musb->xceiv->state));
 		del_timer(&glue->timer[pdev->id]);
 		glue->last_timer[pdev->id] = jiffies;
 		return;
@@ -288,7 +289,7 @@ static void dsps_musb_try_idle(struct musb *musb, unsigned long timeout)
 	glue->last_timer[pdev->id] = timeout;
 
 	dev_dbg(musb->controller, "%s inactive, starting idle timer for %u ms\n",
-		otg_state_string(musb->xceiv->state),
+		usb_otg_state_string(musb->xceiv->state),
 			jiffies_to_msecs(timeout - jiffies));
 	mod_timer(&glue->timer[pdev->id], timeout);
 }
@@ -334,7 +335,7 @@ static irqreturn_t dsps_interrupt(int irq, void *hci)
 	 * value but DEVCTL.BDEVICE is invalid without DEVCTL.SESSION set.
 	 * Also, DRVVBUS pulses for SRP (but not at 5V) ...
 	 */
-	if (usbintr & MUSB_INTR_BABBLE)
+	if (is_host_active(musb) && usbintr & MUSB_INTR_BABBLE)
 		pr_info("CAUTION: musb: Babble Interrupt Occurred\n");
 
 	if (usbintr & ((1 << wrp->drvvbus) << wrp->usb_shift)) {
@@ -377,7 +378,7 @@ static irqreturn_t dsps_interrupt(int irq, void *hci)
 		/* NOTE: this must complete power-on within 100 ms. */
 		dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n",
 				drvvbus ? "on" : "off",
-				otg_state_string(musb->xceiv->state),
+				usb_otg_state_string(musb->xceiv->state),
 				err ? " ERROR" : "",
 				devctl);
 		ret = IRQ_HANDLED;
@@ -596,14 +597,13 @@ err0:
 
 static int dsps_probe(struct platform_device *pdev)
 {
-	struct device_node *np = pdev->dev.of_node;
 	const struct of_device_id *match;
 	const struct dsps_musb_wrapper *wrp;
 	struct dsps_glue *glue;
 	struct resource *iomem;
 	int ret, i;
 
-	match = of_match_node(musb_dsps_of_match, np);
+	match = of_match_node(musb_dsps_of_match, pdev->dev.of_node);
 	if (!match) {
 		dev_err(&pdev->dev, "fail to get matching of_match struct\n");
 		ret = -EINVAL;
diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
index 83edded..ba70923 100644
--- a/drivers/usb/musb/musb_gadget.c
+++ b/drivers/usb/musb/musb_gadget.c
@@ -46,48 +46,6 @@
 #include "musb_core.h"
 
 
-/* MUSB PERIPHERAL status 3-mar-2006:
- *
- * - EP0 seems solid.  It passes both USBCV and usbtest control cases.
- *   Minor glitches:
- *
- *     + remote wakeup to Linux hosts work, but saw USBCV failures;
- *       in one test run (operator error?)
- *     + endpoint halt tests -- in both usbtest and usbcv -- seem
- *       to break when dma is enabled ... is something wrongly
- *       clearing SENDSTALL?
- *
- * - Mass storage behaved ok when last tested.  Network traffic patterns
- *   (with lots of short transfers etc) need retesting; they turn up the
- *   worst cases of the DMA, since short packets are typical but are not
- *   required.
- *
- * - TX/IN
- *     + both pio and dma behave in with network and g_zero tests
- *     + no cppi throughput issues other than no-hw-queueing
- *     + failed with FLAT_REG (DaVinci)
- *     + seems to behave with double buffering, PIO -and- CPPI
- *     + with gadgetfs + AIO, requests got lost?
- *
- * - RX/OUT
- *     + both pio and dma behave in with network and g_zero tests
- *     + dma is slow in typical case (short_not_ok is clear)
- *     + double buffering ok with PIO
- *     + double buffering *FAILS* with CPPI, wrong data bytes sometimes
- *     + request lossage observed with gadgetfs
- *
- * - ISO not tested ... might work, but only weakly isochronous
- *
- * - Gadget driver disabling of softconnect during bind() is ignored; so
- *   drivers can't hold off host requests until userspace is ready.
- *   (Workaround:  they can turn it off later.)
- *
- * - PORTABILITY (assumes PIO works):
- *     + DaVinci, basically works with cppi dma
- *     + OMAP 2430, ditto with mentor dma
- *     + TUSB 6010, platform-specific dma in the works
- */
-
 /* ----------------------------------------------------------------------- */
 
 #define is_buffer_mapped(req) (is_dma_capable() && \
@@ -280,41 +238,6 @@ static inline int max_ep_writesize(struct musb *musb, struct musb_ep *ep)
 		return ep->packet_sz;
 }
 
-
-#ifdef CONFIG_USB_INVENTRA_DMA
-
-/* Peripheral tx (IN) using Mentor DMA works as follows:
-	Only mode 0 is used for transfers <= wPktSize,
-	mode 1 is used for larger transfers,
-
-	One of the following happens:
-	- Host sends IN token which causes an endpoint interrupt
-		-> TxAvail
-			-> if DMA is currently busy, exit.
-			-> if queue is non-empty, txstate().
-
-	- Request is queued by the gadget driver.
-		-> if queue was previously empty, txstate()
-
-	txstate()
-		-> start
-		  /\	-> setup DMA
-		  |     (data is transferred to the FIFO, then sent out when
-		  |	IN token(s) are recd from Host.
-		  |		-> DMA interrupt on completion
-		  |		   calls TxAvail.
-		  |		      -> stop DMA, ~DMAENAB,
-		  |		      -> set TxPktRdy for last short pkt or zlp
-		  |		      -> Complete Request
-		  |		      -> Continue next request (call txstate)
-		  |___________________________________|
-
- * Non-Mentor DMA engines can of course work differently, such as by
- * upleveling from irq-per-packet to irq-per-buffer.
- */
-
-#endif
-
 /*
  * An endpoint is transmitting data. This can be called either from
  * the IRQ routine or from ep.queue() to kickstart a request on an
@@ -621,37 +544,6 @@ void musb_g_tx(struct musb *musb, u8 epnum)
 
 /* ------------------------------------------------------------ */
 
-#ifdef CONFIG_USB_INVENTRA_DMA
-
-/* Peripheral rx (OUT) using Mentor DMA works as follows:
-	- Only mode 0 is used.
-
-	- Request is queued by the gadget class driver.
-		-> if queue was previously empty, rxstate()
-
-	- Host sends OUT token which causes an endpoint interrupt
-	  /\      -> RxReady
-	  |	      -> if request queued, call rxstate
-	  |		/\	-> setup DMA
-	  |		|	     -> DMA interrupt on completion
-	  |		|		-> RxReady
-	  |		|		      -> stop DMA
-	  |		|		      -> ack the read
-	  |		|		      -> if data recd = max expected
-	  |		|				by the request, or host
-	  |		|				sent a short packet,
-	  |		|				complete the request,
-	  |		|				and start the next one.
-	  |		|_____________________________________|
-	  |					 else just wait for the host
-	  |					    to send the next OUT token.
-	  |__________________________________________________|
-
- * Non-Mentor DMA engines can of course work differently.
- */
-
-#endif
-
 /*
  * Context: controller locked, IRQs blocked, endpoint selected
  */
@@ -740,7 +632,7 @@ static void rxstate(struct musb *musb, struct musb_request *req)
 				struct dma_controller	*c;
 				struct dma_channel	*channel;
 				int			use_dma = 0;
-				int transfer_size;
+				unsigned int transfer_size;
 
 				c = musb->dma_controller;
 				channel = musb_ep->dma;
@@ -782,10 +674,11 @@ static void rxstate(struct musb *musb, struct musb_request *req)
 						csr | MUSB_RXCSR_DMAMODE);
 					musb_writew(epio, MUSB_RXCSR, csr);
 
-					transfer_size = min(request->length - request->actual,
+					transfer_size = min_t(unsigned int,
+							request->length -
+							request->actual,
 							channel->max_len);
 					musb_ep->dma->desired_mode = 1;
-
 				} else {
 					if (!musb_ep->hb_mult &&
 						musb_ep->hw_ep->rx_double_buffered)
@@ -815,7 +708,7 @@ static void rxstate(struct musb *musb, struct musb_request *req)
 
 				struct dma_controller *c;
 				struct dma_channel *channel;
-				int transfer_size = 0;
+				unsigned int transfer_size = 0;
 
 				c = musb->dma_controller;
 				channel = musb_ep->dma;
@@ -824,11 +717,13 @@ static void rxstate(struct musb *musb, struct musb_request *req)
 				if (fifo_count < musb_ep->packet_sz)
 					transfer_size = fifo_count;
 				else if (request->short_not_ok)
-					transfer_size =	min(request->length -
+					transfer_size =	min_t(unsigned int,
+							request->length -
 							request->actual,
 							channel->max_len);
 				else
-					transfer_size = min(request->length -
+					transfer_size = min_t(unsigned int,
+							request->length -
 							request->actual,
 							(unsigned)fifo_count);
 
@@ -1681,7 +1576,7 @@ static int musb_gadget_wakeup(struct usb_gadget *gadget)
 		goto done;
 	default:
 		dev_dbg(musb->controller, "Unhandled wake: %s\n",
-			otg_state_string(musb->xceiv->state));
+			usb_otg_state_string(musb->xceiv->state));
 		goto done;
 	}
 
@@ -1801,13 +1696,6 @@ static const struct usb_gadget_ops musb_gadget_operations = {
  * all peripheral ports are external...
  */
 
-static void musb_gadget_release(struct device *dev)
-{
-	/* kref_put(WHAT) */
-	dev_dbg(dev, "%s\n", __func__);
-}
-
-
 static void
 init_peripheral_ep(struct musb *musb, struct musb_ep *ep, u8 epnum, int is_in)
 {
@@ -1892,12 +1780,7 @@ int musb_gadget_setup(struct musb *musb)
 	musb->g.speed = USB_SPEED_UNKNOWN;
 
 	/* this "gadget" abstracts/virtualizes the controller */
-	dev_set_name(&musb->g.dev, "gadget");
-	musb->g.dev.parent = musb->controller;
-	musb->g.dev.dma_mask = musb->controller->dma_mask;
-	musb->g.dev.release = musb_gadget_release;
 	musb->g.name = musb_driver_name;
-
 	musb->g.is_otg = 1;
 
 	musb_g_init_endpoints(musb);
@@ -1905,11 +1788,6 @@ int musb_gadget_setup(struct musb *musb)
 	musb->is_active = 0;
 	musb_platform_try_idle(musb, 0);
 
-	status = device_register(&musb->g.dev);
-	if (status != 0) {
-		put_device(&musb->g.dev);
-		return status;
-	}
 	status = usb_add_gadget_udc(musb->controller, &musb->g);
 	if (status)
 		goto err;
@@ -1924,8 +1802,6 @@ err:
 void musb_gadget_cleanup(struct musb *musb)
 {
 	usb_del_gadget_udc(&musb->g);
-	if (musb->g.dev.parent)
-		device_unregister(&musb->g.dev);
 }
 
 /*
@@ -1977,9 +1853,8 @@ static int musb_gadget_start(struct usb_gadget *g,
 		goto err;
 	}
 
-	if ((musb->xceiv->last_event == USB_EVENT_ID)
-				&& otg->set_vbus)
-		otg_set_vbus(otg, 1);
+	if (musb->xceiv->last_event == USB_EVENT_ID)
+		musb_platform_set_vbus(musb, 1);
 
 	hcd->self.uses_pio_for_control = 1;
 
@@ -2063,6 +1938,7 @@ static int musb_gadget_stop(struct usb_gadget *g,
 	dev_dbg(musb->controller, "unregistering driver %s\n", driver->function);
 
 	musb->is_active = 0;
+	musb->gadget_driver = NULL;
 	musb_platform_try_idle(musb, 0);
 	spin_unlock_irqrestore(&musb->lock, flags);
 
@@ -2099,7 +1975,7 @@ void musb_g_resume(struct musb *musb)
 		break;
 	default:
 		WARNING("unhandled RESUME transition (%s)\n",
-				otg_state_string(musb->xceiv->state));
+				usb_otg_state_string(musb->xceiv->state));
 	}
 }
 
@@ -2129,7 +2005,7 @@ void musb_g_suspend(struct musb *musb)
 		 * A_PERIPHERAL may need care too
 		 */
 		WARNING("unhandled SUSPEND transition (%s)\n",
-				otg_state_string(musb->xceiv->state));
+				usb_otg_state_string(musb->xceiv->state));
 	}
 }
 
@@ -2163,7 +2039,7 @@ void musb_g_disconnect(struct musb *musb)
 	switch (musb->xceiv->state) {
 	default:
 		dev_dbg(musb->controller, "Unhandled disconnect %s, setting a_idle\n",
-			otg_state_string(musb->xceiv->state));
+			usb_otg_state_string(musb->xceiv->state));
 		musb->xceiv->state = OTG_STATE_A_IDLE;
 		MUSB_HST_MODE(musb);
 		break;
diff --git a/drivers/usb/musb/musb_gadget_ep0.c b/drivers/usb/musb/musb_gadget_ep0.c
index c9c1ac4..2af45a0 100644
--- a/drivers/usb/musb/musb_gadget_ep0.c
+++ b/drivers/usb/musb/musb_gadget_ep0.c
@@ -505,8 +505,10 @@ static void ep0_rxstate(struct musb *musb)
 			req->status = -EOVERFLOW;
 			count = len;
 		}
-		musb_read_fifo(&musb->endpoints[0], count, buf);
-		req->actual += count;
+		if (count > 0) {
+			musb_read_fifo(&musb->endpoints[0], count, buf);
+			req->actual += count;
+		}
 		csr = MUSB_CSR0_P_SVDRXPKTRDY;
 		if (count < 64 || req->actual == req->length) {
 			musb->ep0_state = MUSB_EP0_STAGE_STATUSIN;
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index 1ce1fcf..8914dec 100644
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -2453,7 +2453,7 @@ static int musb_bus_suspend(struct usb_hcd *hcd)
 
 	if (musb->is_active) {
 		WARNING("trying to suspend as %s while active\n",
-				otg_state_string(musb->xceiv->state));
+				usb_otg_state_string(musb->xceiv->state));
 		return -EBUSY;
 	} else
 		return 0;
@@ -2465,6 +2465,118 @@ static int musb_bus_resume(struct usb_hcd *hcd)
 	return 0;
 }
 
+
+#ifndef CONFIG_MUSB_PIO_ONLY
+
+#define MUSB_USB_DMA_ALIGN 4
+
+struct musb_temp_buffer {
+	void *kmalloc_ptr;
+	void *old_xfer_buffer;
+	u8 data[0];
+};
+
+static void musb_free_temp_buffer(struct urb *urb)
+{
+	enum dma_data_direction dir;
+	struct musb_temp_buffer *temp;
+
+	if (!(urb->transfer_flags & URB_ALIGNED_TEMP_BUFFER))
+		return;
+
+	dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+
+	temp = container_of(urb->transfer_buffer, struct musb_temp_buffer,
+			    data);
+
+	if (dir == DMA_FROM_DEVICE) {
+		memcpy(temp->old_xfer_buffer, temp->data,
+		       urb->transfer_buffer_length);
+	}
+	urb->transfer_buffer = temp->old_xfer_buffer;
+	kfree(temp->kmalloc_ptr);
+
+	urb->transfer_flags &= ~URB_ALIGNED_TEMP_BUFFER;
+}
+
+static int musb_alloc_temp_buffer(struct urb *urb, gfp_t mem_flags)
+{
+	enum dma_data_direction dir;
+	struct musb_temp_buffer *temp;
+	void *kmalloc_ptr;
+	size_t kmalloc_size;
+
+	if (urb->num_sgs || urb->sg ||
+	    urb->transfer_buffer_length == 0 ||
+	    !((uintptr_t)urb->transfer_buffer & (MUSB_USB_DMA_ALIGN - 1)))
+		return 0;
+
+	dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+
+	/* Allocate a buffer with enough padding for alignment */
+	kmalloc_size = urb->transfer_buffer_length +
+		sizeof(struct musb_temp_buffer) + MUSB_USB_DMA_ALIGN - 1;
+
+	kmalloc_ptr = kmalloc(kmalloc_size, mem_flags);
+	if (!kmalloc_ptr)
+		return -ENOMEM;
+
+	/* Position our struct temp_buffer such that data is aligned */
+	temp = PTR_ALIGN(kmalloc_ptr, MUSB_USB_DMA_ALIGN);
+
+
+	temp->kmalloc_ptr = kmalloc_ptr;
+	temp->old_xfer_buffer = urb->transfer_buffer;
+	if (dir == DMA_TO_DEVICE)
+		memcpy(temp->data, urb->transfer_buffer,
+		       urb->transfer_buffer_length);
+	urb->transfer_buffer = temp->data;
+
+	urb->transfer_flags |= URB_ALIGNED_TEMP_BUFFER;
+
+	return 0;
+}
+
+static int musb_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
+				      gfp_t mem_flags)
+{
+	struct musb	*musb = hcd_to_musb(hcd);
+	int ret;
+
+	/*
+	 * The DMA engine in RTL1.8 and above cannot handle
+	 * DMA addresses that are not aligned to a 4 byte boundary.
+	 * For such engine implemented (un)map_urb_for_dma hooks.
+	 * Do not use these hooks for RTL<1.8
+	 */
+	if (musb->hwvers < MUSB_HWVERS_1800)
+		return usb_hcd_map_urb_for_dma(hcd, urb, mem_flags);
+
+	ret = musb_alloc_temp_buffer(urb, mem_flags);
+	if (ret)
+		return ret;
+
+	ret = usb_hcd_map_urb_for_dma(hcd, urb, mem_flags);
+	if (ret)
+		musb_free_temp_buffer(urb);
+
+	return ret;
+}
+
+static void musb_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
+{
+	struct musb	*musb = hcd_to_musb(hcd);
+
+	usb_hcd_unmap_urb_for_dma(hcd, urb);
+
+	/* Do not use this hook for RTL<1.8 (see description above) */
+	if (musb->hwvers < MUSB_HWVERS_1800)
+		return;
+
+	musb_free_temp_buffer(urb);
+}
+#endif /* !CONFIG_MUSB_PIO_ONLY */
+
 const struct hc_driver musb_hc_driver = {
 	.description		= "musb-hcd",
 	.product_desc		= "MUSB HDRC host driver",
@@ -2484,6 +2596,11 @@ const struct hc_driver musb_hc_driver = {
 	.urb_dequeue		= musb_urb_dequeue,
 	.endpoint_disable	= musb_h_disable,
 
+#ifndef CONFIG_MUSB_PIO_ONLY
+	.map_urb_for_dma	= musb_map_urb_for_dma,
+	.unmap_urb_for_dma	= musb_unmap_urb_for_dma,
+#endif
+
 	.hub_status_data	= musb_hub_status_data,
 	.hub_control		= musb_hub_control,
 	.bus_suspend		= musb_bus_suspend,
diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c
index f705791..ef7d110 100644
--- a/drivers/usb/musb/musb_virthub.c
+++ b/drivers/usb/musb/musb_virthub.c
@@ -95,7 +95,7 @@ static void musb_port_suspend(struct musb *musb, bool do_suspend)
 			break;
 		default:
 			dev_dbg(musb->controller, "bogus rh suspend? %s\n",
-				otg_state_string(musb->xceiv->state));
+				usb_otg_state_string(musb->xceiv->state));
 		}
 	} else if (power & MUSB_POWER_SUSPENDM) {
 		power &= ~MUSB_POWER_SUSPENDM;
@@ -203,7 +203,7 @@ void musb_root_disconnect(struct musb *musb)
 		break;
 	default:
 		dev_dbg(musb->controller, "host disconnect (%s)\n",
-			otg_state_string(musb->xceiv->state));
+			usb_otg_state_string(musb->xceiv->state));
 	}
 }
 
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
index 1a42a45..3551f1a 100644
--- a/drivers/usb/musb/omap2430.c
+++ b/drivers/usb/musb/omap2430.c
@@ -117,7 +117,7 @@ static void omap2430_musb_try_idle(struct musb *musb, unsigned long timeout)
 	if (musb->is_active || ((musb->a_wait_bcon == 0)
 			&& (musb->xceiv->state == OTG_STATE_A_WAIT_BCON))) {
 		dev_dbg(musb->controller, "%s active, deleting timer\n",
-			otg_state_string(musb->xceiv->state));
+			usb_otg_state_string(musb->xceiv->state));
 		del_timer(&musb_idle_timer);
 		last_timer = jiffies;
 		return;
@@ -134,7 +134,7 @@ static void omap2430_musb_try_idle(struct musb *musb, unsigned long timeout)
 	last_timer = timeout;
 
 	dev_dbg(musb->controller, "%s inactive, for idle timer for %lu ms\n",
-		otg_state_string(musb->xceiv->state),
+		usb_otg_state_string(musb->xceiv->state),
 		(unsigned long)jiffies_to_msecs(timeout - jiffies));
 	mod_timer(&musb_idle_timer, timeout);
 }
@@ -174,8 +174,7 @@ static void omap2430_musb_set_vbus(struct musb *musb, int is_on)
 				}
 			}
 
-			if (otg->set_vbus)
-				otg_set_vbus(otg, 1);
+			otg_set_vbus(otg, 1);
 		} else {
 			musb->is_active = 1;
 			otg->default_a = 1;
@@ -200,7 +199,7 @@ static void omap2430_musb_set_vbus(struct musb *musb, int is_on)
 
 	dev_dbg(musb->controller, "VBUS %s, devctl %02x "
 		/* otg %3x conf %08x prcm %08x */ "\n",
-		otg_state_string(musb->xceiv->state),
+		usb_otg_state_string(musb->xceiv->state),
 		musb_readb(musb->mregs, MUSB_DEVCTL));
 }
 
@@ -292,14 +291,14 @@ static void omap_musb_set_mailbox(struct omap2430_glue *glue)
 
 		musb->xceiv->last_event = USB_EVENT_NONE;
 		if (musb->gadget_driver) {
+			omap2430_musb_set_vbus(musb, 0);
 			pm_runtime_mark_last_busy(dev);
 			pm_runtime_put_autosuspend(dev);
 		}
 
-		if (data->interface_type == MUSB_INTERFACE_UTMI) {
-			if (musb->xceiv->otg->set_vbus)
-				otg_set_vbus(musb->xceiv->otg, 0);
-		}
+		if (data->interface_type == MUSB_INTERFACE_UTMI)
+			otg_set_vbus(musb->xceiv->otg, 0);
+
 		omap_control_usb_set_mode(glue->control_otghs,
 			USB_MODE_DISCONNECT);
 		break;
@@ -355,7 +354,12 @@ static int omap2430_musb_init(struct musb *musb)
 	else
 		musb->xceiv = devm_usb_get_phy_dev(dev, 0);
 
-	if (IS_ERR_OR_NULL(musb->xceiv)) {
+	if (IS_ERR(musb->xceiv)) {
+		status = PTR_ERR(musb->xceiv);
+
+		if (status == -ENXIO)
+			return status;
+
 		pr_err("HS USB OTG: no transceiver configured\n");
 		return -EPROBE_DEFER;
 	}
@@ -393,6 +397,8 @@ static int omap2430_musb_init(struct musb *musb)
 	if (glue->status != OMAP_MUSB_UNKNOWN)
 		omap_musb_set_mailbox(glue);
 
+	usb_phy_init(musb->xceiv);
+
 	pm_runtime_put_noidle(musb->controller);
 	return 0;
 
@@ -526,10 +532,10 @@ static int omap2430_probe(struct platform_device *pdev)
 		}
 
 		of_property_read_u32(np, "mode", (u32 *)&pdata->mode);
-		of_property_read_u32(np, "interface_type",
+		of_property_read_u32(np, "interface-type",
 						(u32 *)&data->interface_type);
-		of_property_read_u32(np, "num_eps", (u32 *)&config->num_eps);
-		of_property_read_u32(np, "ram_bits", (u32 *)&config->ram_bits);
+		of_property_read_u32(np, "num-eps", (u32 *)&config->num_eps);
+		of_property_read_u32(np, "ram-bits", (u32 *)&config->ram_bits);
 		of_property_read_u32(np, "power", (u32 *)&pdata->power);
 		config->multipoint = of_property_read_bool(np, "multipoint");
 		pdata->has_mailbox = of_property_read_bool(np,
diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c
index 464bd23..7369ba3 100644
--- a/drivers/usb/musb/tusb6010.c
+++ b/drivers/usb/musb/tusb6010.c
@@ -423,7 +423,7 @@ static void musb_do_idle(unsigned long _musb)
 			&& (musb->idle_timeout == 0
 				|| time_after(jiffies, musb->idle_timeout))) {
 			dev_dbg(musb->controller, "Nothing connected %s, turning off VBUS\n",
-					otg_state_string(musb->xceiv->state));
+					usb_otg_state_string(musb->xceiv->state));
 		}
 		/* FALLTHROUGH */
 	case OTG_STATE_A_IDLE:
@@ -478,7 +478,7 @@ static void tusb_musb_try_idle(struct musb *musb, unsigned long timeout)
 	if (musb->is_active || ((musb->a_wait_bcon == 0)
 			&& (musb->xceiv->state == OTG_STATE_A_WAIT_BCON))) {
 		dev_dbg(musb->controller, "%s active, deleting timer\n",
-			otg_state_string(musb->xceiv->state));
+			usb_otg_state_string(musb->xceiv->state));
 		del_timer(&musb_idle_timer);
 		last_timer = jiffies;
 		return;
@@ -495,7 +495,7 @@ static void tusb_musb_try_idle(struct musb *musb, unsigned long timeout)
 	last_timer = timeout;
 
 	dev_dbg(musb->controller, "%s inactive, for idle timer for %lu ms\n",
-		otg_state_string(musb->xceiv->state),
+		usb_otg_state_string(musb->xceiv->state),
 		(unsigned long)jiffies_to_msecs(timeout - jiffies));
 	mod_timer(&musb_idle_timer, timeout);
 }
@@ -571,7 +571,7 @@ static void tusb_musb_set_vbus(struct musb *musb, int is_on)
 	musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
 
 	dev_dbg(musb->controller, "VBUS %s, devctl %02x otg %3x conf %08x prcm %08x\n",
-		otg_state_string(musb->xceiv->state),
+		usb_otg_state_string(musb->xceiv->state),
 		musb_readb(musb->mregs, MUSB_DEVCTL),
 		musb_readl(tbase, TUSB_DEV_OTG_STAT),
 		conf, prcm);
@@ -678,13 +678,13 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase)
 				musb->is_active = 0;
 			}
 			dev_dbg(musb->controller, "vbus change, %s, otg %03x\n",
-				otg_state_string(musb->xceiv->state), otg_stat);
+				usb_otg_state_string(musb->xceiv->state), otg_stat);
 			idle_timeout = jiffies + (1 * HZ);
 			schedule_work(&musb->irq_work);
 
 		} else /* A-dev state machine */ {
 			dev_dbg(musb->controller, "vbus change, %s, otg %03x\n",
-				otg_state_string(musb->xceiv->state), otg_stat);
+				usb_otg_state_string(musb->xceiv->state), otg_stat);
 
 			switch (musb->xceiv->state) {
 			case OTG_STATE_A_IDLE:
@@ -733,7 +733,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase)
 		u8	devctl;
 
 		dev_dbg(musb->controller, "%s timer, %03x\n",
-			otg_state_string(musb->xceiv->state), otg_stat);
+			usb_otg_state_string(musb->xceiv->state), otg_stat);
 
 		switch (musb->xceiv->state) {
 		case OTG_STATE_A_WAIT_VRISE:
diff --git a/drivers/usb/musb/ux500.c b/drivers/usb/musb/ux500.c
index 13a3929..2c80004 100644
--- a/drivers/usb/musb/ux500.c
+++ b/drivers/usb/musb/ux500.c
@@ -26,6 +26,7 @@
 #include <linux/err.h>
 #include <linux/io.h>
 #include <linux/platform_device.h>
+#include <linux/usb/musb-ux500.h>
 
 #include "musb_core.h"
 
@@ -36,6 +37,98 @@ struct ux500_glue {
 };
 #define glue_to_musb(g)	platform_get_drvdata(g->musb)
 
+static void ux500_musb_set_vbus(struct musb *musb, int is_on)
+{
+	u8            devctl;
+	unsigned long timeout = jiffies + msecs_to_jiffies(1000);
+	/* HDRC controls CPEN, but beware current surges during device
+	 * connect.  They can trigger transient overcurrent conditions
+	 * that must be ignored.
+	 */
+
+	devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
+
+	if (is_on) {
+		if (musb->xceiv->state == OTG_STATE_A_IDLE) {
+			/* start the session */
+			devctl |= MUSB_DEVCTL_SESSION;
+			musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
+			/*
+			 * Wait for the musb to set as A device to enable the
+			 * VBUS
+			 */
+			while (musb_readb(musb->mregs, MUSB_DEVCTL) & 0x80) {
+
+				if (time_after(jiffies, timeout)) {
+					dev_err(musb->controller,
+					"configured as A device timeout");
+					break;
+				}
+			}
+
+		} else {
+			musb->is_active = 1;
+			musb->xceiv->otg->default_a = 1;
+			musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
+			devctl |= MUSB_DEVCTL_SESSION;
+			MUSB_HST_MODE(musb);
+		}
+	} else {
+		musb->is_active = 0;
+
+		/* NOTE: we're skipping A_WAIT_VFALL -> A_IDLE and jumping
+		 * right to B_IDLE...
+		 */
+		musb->xceiv->otg->default_a = 0;
+		devctl &= ~MUSB_DEVCTL_SESSION;
+		MUSB_DEV_MODE(musb);
+	}
+	musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
+
+	/*
+	 * Devctl values will be updated after vbus goes below
+	 * session_valid. The time taken depends on the capacitance
+	 * on VBUS line. The max discharge time can be upto 1 sec
+	 * as per the spec. Typically on our platform, it is 200ms
+	 */
+	if (!is_on)
+		mdelay(200);
+
+	dev_dbg(musb->controller, "VBUS %s, devctl %02x\n",
+		usb_otg_state_string(musb->xceiv->state),
+		musb_readb(musb->mregs, MUSB_DEVCTL));
+}
+
+static int musb_otg_notifications(struct notifier_block *nb,
+		unsigned long event, void *unused)
+{
+	struct musb *musb = container_of(nb, struct musb, nb);
+
+	dev_dbg(musb->controller, "musb_otg_notifications %ld %s\n",
+			event, usb_otg_state_string(musb->xceiv->state));
+
+	switch (event) {
+	case UX500_MUSB_ID:
+		dev_dbg(musb->controller, "ID GND\n");
+		ux500_musb_set_vbus(musb, 1);
+		break;
+	case UX500_MUSB_VBUS:
+		dev_dbg(musb->controller, "VBUS Connect\n");
+		break;
+	case UX500_MUSB_NONE:
+		dev_dbg(musb->controller, "VBUS Disconnect\n");
+		if (is_host_active(musb))
+			ux500_musb_set_vbus(musb, 0);
+		else
+			musb->xceiv->state = OTG_STATE_B_IDLE;
+		break;
+	default:
+		dev_dbg(musb->controller, "ID float\n");
+		return NOTIFY_DONE;
+	}
+	return NOTIFY_OK;
+}
+
 static irqreturn_t ux500_musb_interrupt(int irq, void *__hci)
 {
 	unsigned long   flags;
@@ -58,12 +151,21 @@ static irqreturn_t ux500_musb_interrupt(int irq, void *__hci)
 
 static int ux500_musb_init(struct musb *musb)
 {
+	int status;
+
 	musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
 	if (IS_ERR_OR_NULL(musb->xceiv)) {
 		pr_err("HS USB OTG: no transceiver configured\n");
 		return -EPROBE_DEFER;
 	}
 
+	musb->nb.notifier_call = musb_otg_notifications;
+	status = usb_register_notifier(musb->xceiv, &musb->nb);
+	if (status < 0) {
+		dev_dbg(musb->controller, "notification register failed\n");
+		return status;
+	}
+
 	musb->isr = ux500_musb_interrupt;
 
 	return 0;
@@ -71,6 +173,8 @@ static int ux500_musb_init(struct musb *musb)
 
 static int ux500_musb_exit(struct musb *musb)
 {
+	usb_unregister_notifier(musb->xceiv, &musb->nb);
+
 	usb_put_phy(musb->xceiv);
 
 	return 0;
@@ -79,6 +183,8 @@ static int ux500_musb_exit(struct musb *musb)
 static const struct musb_platform_ops ux500_ops = {
 	.init		= ux500_musb_init,
 	.exit		= ux500_musb_exit,
+
+	.set_vbus	= ux500_musb_set_vbus,
 };
 
 static int ux500_probe(struct platform_device *pdev)
diff --git a/drivers/usb/musb/ux500_dma.c b/drivers/usb/musb/ux500_dma.c
index 039e567..3381206 100644
--- a/drivers/usb/musb/ux500_dma.c
+++ b/drivers/usb/musb/ux500_dma.c
@@ -1,7 +1,7 @@
 /*
  * drivers/usb/musb/ux500_dma.c
  *
- * U8500 and U5500 DMA support code
+ * U8500 DMA support code
  *
  * Copyright (C) 2009 STMicroelectronics
  * Copyright (C) 2011 ST-Ericsson SA
@@ -30,6 +30,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/dmaengine.h>
 #include <linux/pfn.h>
+#include <linux/sizes.h>
 #include <linux/platform_data/usb-musb-ux500.h>
 #include "musb_core.h"
 
@@ -56,7 +57,7 @@ struct ux500_dma_controller {
 };
 
 /* Work function invoked from DMA callback to handle rx transfers. */
-void ux500_dma_callback(void *private_data)
+static void ux500_dma_callback(void *private_data)
 {
 	struct dma_channel *channel = private_data;
 	struct ux500_dma_channel *ux500_channel = channel->private_data;
@@ -93,8 +94,9 @@ static bool ux500_configure_channel(struct dma_channel *channel,
 	struct musb *musb = ux500_channel->controller->private_data;
 
 	dev_dbg(musb->controller,
-		"packet_sz=%d, mode=%d, dma_addr=0x%x, len=%d is_tx=%d\n",
-		packet_sz, mode, dma_addr, len, ux500_channel->is_tx);
+		"packet_sz=%d, mode=%d, dma_addr=0x%llu, len=%d is_tx=%d\n",
+		packet_sz, mode, (unsigned long long) dma_addr,
+		len, ux500_channel->is_tx);
 
 	ux500_channel->cur_len = len;
 
@@ -191,7 +193,7 @@ static int ux500_dma_is_compatible(struct dma_channel *channel,
 		u16 maxpacket, void *buf, u32 length)
 {
 	if ((maxpacket & 0x3)		||
-		((int)buf & 0x3)	||
+		((unsigned long int) buf & 0x3)	||
 		(length < 512)		||
 		(length & 0x3))
 		return false;
@@ -372,12 +374,17 @@ struct dma_controller *dma_controller_create(struct musb *musb, void __iomem *ba
 
 	controller = kzalloc(sizeof(*controller), GFP_KERNEL);
 	if (!controller)
-		return NULL;
+		goto kzalloc_fail;
 
 	controller->private_data = musb;
 
 	/* Save physical address for DMA controller. */
 	iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!iomem) {
+		dev_err(musb->controller, "no memory resource defined\n");
+		goto plat_get_fail;
+	}
+
 	controller->phy_base = (dma_addr_t) iomem->start;
 
 	controller->controller.start = ux500_dma_controller_start;
@@ -389,4 +396,9 @@ struct dma_controller *dma_controller_create(struct musb *musb, void __iomem *ba
 	controller->controller.is_compatible = ux500_dma_is_compatible;
 
 	return &controller->controller;
+
+plat_get_fail:
+	kfree(controller);
+kzalloc_fail:
+	return NULL;
 }
diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig
deleted file mode 100644
index 37962c9..0000000
--- a/drivers/usb/otg/Kconfig
+++ /dev/null
@@ -1,141 +0,0 @@
-#
-# USB OTG infrastructure may be needed for peripheral-only, host-only,
-# or OTG-capable configurations when OTG transceivers or controllers
-# are used.
-#
-
-comment "OTG and related infrastructure"
-
-config USB_OTG_UTILS
-	bool
-	help
-	  Select this to make sure the build includes objects from
-	  the OTG infrastructure directory.
-
-if USB || USB_GADGET
-
-#
-# USB Transceiver Drivers
-#
-config USB_GPIO_VBUS
-	tristate "GPIO based peripheral-only VBUS sensing 'transceiver'"
-	depends on GENERIC_GPIO
-	select USB_OTG_UTILS
-	help
-	  Provides simple GPIO VBUS sensing for controllers with an
-	  internal transceiver via the usb_phy interface, and
-	  optionally control of a D+ pullup GPIO as well as a VBUS
-	  current limit regulator.
-
-config ISP1301_OMAP
-	tristate "Philips ISP1301 with OMAP OTG"
-	depends on I2C && ARCH_OMAP_OTG
-	select USB_OTG_UTILS
-	help
-	  If you say yes here you get support for the Philips ISP1301
-	  USB-On-The-Go transceiver working with the OMAP OTG controller.
-	  The ISP1301 is a full speed USB  transceiver which is used in
-	  products including H2, H3, and H4 development boards for Texas
-	  Instruments OMAP processors.
-
-	  This driver can also be built as a module.  If so, the module
-	  will be called isp1301_omap.
-
-config USB_ULPI
-	bool "Generic ULPI Transceiver Driver"
-	depends on ARM
-	select USB_OTG_UTILS
-	help
-	  Enable this to support ULPI connected USB OTG transceivers which
-	  are likely found on embedded boards.
-
-config USB_ULPI_VIEWPORT
-	bool
-	depends on USB_ULPI
-	help
-	  Provides read/write operations to the ULPI phy register set for
-	  controllers with a viewport register (e.g. Chipidea/ARC controllers).
-
-config TWL4030_USB
-	tristate "TWL4030 USB Transceiver Driver"
-	depends on TWL4030_CORE && REGULATOR_TWL4030 && USB_MUSB_OMAP2PLUS
-	select USB_OTG_UTILS
-	help
-	  Enable this to support the USB OTG transceiver on TWL4030
-	  family chips (including the TWL5030 and TPS659x0 devices).
-	  This transceiver supports high and full speed devices plus,
-	  in host mode, low speed.
-
-config TWL6030_USB
-	tristate "TWL6030 USB Transceiver Driver"
-	depends on TWL4030_CORE && OMAP_USB2 && USB_MUSB_OMAP2PLUS
-	select USB_OTG_UTILS
-	help
-	  Enable this to support the USB OTG transceiver on TWL6030
-	  family chips. This TWL6030 transceiver has the VBUS and ID GND
-	  and OTG SRP events capabilities. For all other transceiver functionality
-	  UTMI PHY is embedded in OMAP4430. The internal PHY configurations APIs
-	  are hooked to this driver through platform_data structure.
-	  The definition of internal PHY APIs are in the mach-omap2 layer.
-
-config NOP_USB_XCEIV
-	tristate "NOP USB Transceiver Driver"
-	select USB_OTG_UTILS
-	help
-	  This driver is to be used by all the usb transceiver which are either
-	  built-in with usb ip or which are autonomous and doesn't require any
-	  phy programming such as ISP1x04 etc.
-
-config USB_MSM_OTG
-	tristate "OTG support for Qualcomm on-chip USB controller"
-	depends on (USB || USB_GADGET) && ARCH_MSM
-	select USB_OTG_UTILS
-	help
-	  Enable this to support the USB OTG transceiver on MSM chips. It
-	  handles PHY initialization, clock management, and workarounds
-	  required after resetting the hardware and power management.
-	  This driver is required even for peripheral only or host only
-	  mode configurations.
-	  This driver is not supported on boards like trout which
-	  has an external PHY.
-
-config AB8500_USB
-	tristate "AB8500 USB Transceiver Driver"
-	depends on AB8500_CORE
-	select USB_OTG_UTILS
-	help
-	  Enable this to support the USB OTG transceiver in AB8500 chip.
-	  This transceiver supports high and full speed devices plus,
-	  in host mode, low speed.
-
-config FSL_USB2_OTG
-	bool "Freescale USB OTG Transceiver Driver"
-	depends on USB_EHCI_FSL && USB_FSL_USB2 && USB_SUSPEND
-	select USB_OTG
-	select USB_OTG_UTILS
-	help
-	  Enable this to support Freescale USB OTG transceiver.
-
-config USB_MXS_PHY
-	tristate "Freescale MXS USB PHY support"
-	depends on ARCH_MXC || ARCH_MXS
-	select STMP_DEVICE
-	select USB_OTG_UTILS
-	help
-	  Enable this to support the Freescale MXS USB PHY.
-
-	  MXS Phy is used by some of the i.MX SoCs, for example imx23/28/6x.
-
-config USB_MV_OTG
-	tristate "Marvell USB OTG support"
-	depends on USB_EHCI_MV && USB_MV_UDC && USB_SUSPEND
-	select USB_OTG
-	select USB_OTG_UTILS
-	help
-	  Say Y here if you want to build Marvell USB OTG transciever
-	  driver in kernel (including PXA and MMP series). This driver
-	  implements role switch between EHCI host driver and gadget driver.
-
-	  To compile this driver as a module, choose M here.
-
-endif # USB || OTG
diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile
deleted file mode 100644
index a844b8d..0000000
--- a/drivers/usb/otg/Makefile
+++ /dev/null
@@ -1,24 +0,0 @@
-#
-# OTG infrastructure and transceiver drivers
-#
-
-ccflags-$(CONFIG_USB_DEBUG)		:= -DDEBUG
-ccflags-$(CONFIG_USB_GADGET_DEBUG)	+= -DDEBUG
-
-# infrastructure
-obj-$(CONFIG_USB_OTG_UTILS)	+= otg.o
-
-# transceiver drivers
-obj-$(CONFIG_USB_GPIO_VBUS)	+= gpio_vbus.o
-obj-$(CONFIG_ISP1301_OMAP)	+= isp1301_omap.o
-obj-$(CONFIG_TWL4030_USB)	+= twl4030-usb.o
-obj-$(CONFIG_TWL6030_USB)	+= twl6030-usb.o
-obj-$(CONFIG_NOP_USB_XCEIV)	+= nop-usb-xceiv.o
-obj-$(CONFIG_USB_ULPI)		+= ulpi.o
-obj-$(CONFIG_USB_ULPI_VIEWPORT)	+= ulpi_viewport.o
-obj-$(CONFIG_USB_MSM_OTG)	+= msm_otg.o
-obj-$(CONFIG_AB8500_USB)	+= ab8500-usb.o
-fsl_usb2_otg-objs		:= fsl_otg.o otg_fsm.o
-obj-$(CONFIG_FSL_USB2_OTG)	+= fsl_usb2_otg.o
-obj-$(CONFIG_USB_MXS_PHY)	+= mxs-phy.o
-obj-$(CONFIG_USB_MV_OTG)	+= mv_otg.o
diff --git a/drivers/usb/otg/ab8500-usb.c b/drivers/usb/otg/ab8500-usb.c
deleted file mode 100644
index 2d86f26..0000000
--- a/drivers/usb/otg/ab8500-usb.c
+++ /dev/null
@@ -1,596 +0,0 @@
-/*
- * drivers/usb/otg/ab8500_usb.c
- *
- * USB transceiver driver for AB8500 chip
- *
- * Copyright (C) 2010 ST-Ericsson AB
- * Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.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/module.h>
-#include <linux/platform_device.h>
-#include <linux/usb/otg.h>
-#include <linux/slab.h>
-#include <linux/notifier.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/mfd/abx500.h>
-#include <linux/mfd/abx500/ab8500.h>
-
-#define AB8500_MAIN_WD_CTRL_REG 0x01
-#define AB8500_USB_LINE_STAT_REG 0x80
-#define AB8500_USB_PHY_CTRL_REG 0x8A
-
-#define AB8500_BIT_OTG_STAT_ID (1 << 0)
-#define AB8500_BIT_PHY_CTRL_HOST_EN (1 << 0)
-#define AB8500_BIT_PHY_CTRL_DEVICE_EN (1 << 1)
-#define AB8500_BIT_WD_CTRL_ENABLE (1 << 0)
-#define AB8500_BIT_WD_CTRL_KICK (1 << 1)
-
-#define AB8500_V1x_LINK_STAT_WAIT (HZ/10)
-#define AB8500_WD_KICK_DELAY_US 100 /* usec */
-#define AB8500_WD_V11_DISABLE_DELAY_US 100 /* usec */
-#define AB8500_WD_V10_DISABLE_DELAY_MS 100 /* ms */
-
-/* Usb line status register */
-enum ab8500_usb_link_status {
-	USB_LINK_NOT_CONFIGURED = 0,
-	USB_LINK_STD_HOST_NC,
-	USB_LINK_STD_HOST_C_NS,
-	USB_LINK_STD_HOST_C_S,
-	USB_LINK_HOST_CHG_NM,
-	USB_LINK_HOST_CHG_HS,
-	USB_LINK_HOST_CHG_HS_CHIRP,
-	USB_LINK_DEDICATED_CHG,
-	USB_LINK_ACA_RID_A,
-	USB_LINK_ACA_RID_B,
-	USB_LINK_ACA_RID_C_NM,
-	USB_LINK_ACA_RID_C_HS,
-	USB_LINK_ACA_RID_C_HS_CHIRP,
-	USB_LINK_HM_IDGND,
-	USB_LINK_RESERVED,
-	USB_LINK_NOT_VALID_LINK
-};
-
-struct ab8500_usb {
-	struct usb_phy phy;
-	struct device *dev;
-	int irq_num_id_rise;
-	int irq_num_id_fall;
-	int irq_num_vbus_rise;
-	int irq_num_vbus_fall;
-	int irq_num_link_status;
-	unsigned vbus_draw;
-	struct delayed_work dwork;
-	struct work_struct phy_dis_work;
-	unsigned long link_status_wait;
-	int rev;
-};
-
-static inline struct ab8500_usb *phy_to_ab(struct usb_phy *x)
-{
-	return container_of(x, struct ab8500_usb, phy);
-}
-
-static void ab8500_usb_wd_workaround(struct ab8500_usb *ab)
-{
-	abx500_set_register_interruptible(ab->dev,
-		AB8500_SYS_CTRL2_BLOCK,
-		AB8500_MAIN_WD_CTRL_REG,
-		AB8500_BIT_WD_CTRL_ENABLE);
-
-	udelay(AB8500_WD_KICK_DELAY_US);
-
-	abx500_set_register_interruptible(ab->dev,
-		AB8500_SYS_CTRL2_BLOCK,
-		AB8500_MAIN_WD_CTRL_REG,
-		(AB8500_BIT_WD_CTRL_ENABLE
-		| AB8500_BIT_WD_CTRL_KICK));
-
-	if (ab->rev > 0x10) /* v1.1 v2.0 */
-		udelay(AB8500_WD_V11_DISABLE_DELAY_US);
-	else /* v1.0 */
-		msleep(AB8500_WD_V10_DISABLE_DELAY_MS);
-
-	abx500_set_register_interruptible(ab->dev,
-		AB8500_SYS_CTRL2_BLOCK,
-		AB8500_MAIN_WD_CTRL_REG,
-		0);
-}
-
-static void ab8500_usb_phy_ctrl(struct ab8500_usb *ab, bool sel_host,
-					bool enable)
-{
-	u8 ctrl_reg;
-	abx500_get_register_interruptible(ab->dev,
-				AB8500_USB,
-				AB8500_USB_PHY_CTRL_REG,
-				&ctrl_reg);
-	if (sel_host) {
-		if (enable)
-			ctrl_reg |= AB8500_BIT_PHY_CTRL_HOST_EN;
-		else
-			ctrl_reg &= ~AB8500_BIT_PHY_CTRL_HOST_EN;
-	} else {
-		if (enable)
-			ctrl_reg |= AB8500_BIT_PHY_CTRL_DEVICE_EN;
-		else
-			ctrl_reg &= ~AB8500_BIT_PHY_CTRL_DEVICE_EN;
-	}
-
-	abx500_set_register_interruptible(ab->dev,
-				AB8500_USB,
-				AB8500_USB_PHY_CTRL_REG,
-				ctrl_reg);
-
-	/* Needed to enable the phy.*/
-	if (enable)
-		ab8500_usb_wd_workaround(ab);
-}
-
-#define ab8500_usb_host_phy_en(ab)	ab8500_usb_phy_ctrl(ab, true, true)
-#define ab8500_usb_host_phy_dis(ab)	ab8500_usb_phy_ctrl(ab, true, false)
-#define ab8500_usb_peri_phy_en(ab)	ab8500_usb_phy_ctrl(ab, false, true)
-#define ab8500_usb_peri_phy_dis(ab)	ab8500_usb_phy_ctrl(ab, false, false)
-
-static int ab8500_usb_link_status_update(struct ab8500_usb *ab)
-{
-	u8 reg;
-	enum ab8500_usb_link_status lsts;
-	void *v = NULL;
-	enum usb_phy_events event;
-
-	abx500_get_register_interruptible(ab->dev,
-			AB8500_USB,
-			AB8500_USB_LINE_STAT_REG,
-			&reg);
-
-	lsts = (reg >> 3) & 0x0F;
-
-	switch (lsts) {
-	case USB_LINK_NOT_CONFIGURED:
-	case USB_LINK_RESERVED:
-	case USB_LINK_NOT_VALID_LINK:
-		/* TODO: Disable regulators. */
-		ab8500_usb_host_phy_dis(ab);
-		ab8500_usb_peri_phy_dis(ab);
-		ab->phy.state = OTG_STATE_B_IDLE;
-		ab->phy.otg->default_a = false;
-		ab->vbus_draw = 0;
-		event = USB_EVENT_NONE;
-		break;
-
-	case USB_LINK_STD_HOST_NC:
-	case USB_LINK_STD_HOST_C_NS:
-	case USB_LINK_STD_HOST_C_S:
-	case USB_LINK_HOST_CHG_NM:
-	case USB_LINK_HOST_CHG_HS:
-	case USB_LINK_HOST_CHG_HS_CHIRP:
-		if (ab->phy.otg->gadget) {
-			/* TODO: Enable regulators. */
-			ab8500_usb_peri_phy_en(ab);
-			v = ab->phy.otg->gadget;
-		}
-		event = USB_EVENT_VBUS;
-		break;
-
-	case USB_LINK_HM_IDGND:
-		if (ab->phy.otg->host) {
-			/* TODO: Enable regulators. */
-			ab8500_usb_host_phy_en(ab);
-			v = ab->phy.otg->host;
-		}
-		ab->phy.state = OTG_STATE_A_IDLE;
-		ab->phy.otg->default_a = true;
-		event = USB_EVENT_ID;
-		break;
-
-	case USB_LINK_ACA_RID_A:
-	case USB_LINK_ACA_RID_B:
-		/* TODO */
-	case USB_LINK_ACA_RID_C_NM:
-	case USB_LINK_ACA_RID_C_HS:
-	case USB_LINK_ACA_RID_C_HS_CHIRP:
-	case USB_LINK_DEDICATED_CHG:
-		/* TODO: vbus_draw */
-		event = USB_EVENT_CHARGER;
-		break;
-	}
-
-	atomic_notifier_call_chain(&ab->phy.notifier, event, v);
-
-	return 0;
-}
-
-static void ab8500_usb_delayed_work(struct work_struct *work)
-{
-	struct ab8500_usb *ab = container_of(work, struct ab8500_usb,
-						dwork.work);
-
-	ab8500_usb_link_status_update(ab);
-}
-
-static irqreturn_t ab8500_usb_v1x_common_irq(int irq, void *data)
-{
-	struct ab8500_usb *ab = (struct ab8500_usb *) data;
-
-	/* Wait for link status to become stable. */
-	schedule_delayed_work(&ab->dwork, ab->link_status_wait);
-
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t ab8500_usb_v1x_vbus_fall_irq(int irq, void *data)
-{
-	struct ab8500_usb *ab = (struct ab8500_usb *) data;
-
-	/* Link status will not be updated till phy is disabled. */
-	ab8500_usb_peri_phy_dis(ab);
-
-	/* Wait for link status to become stable. */
-	schedule_delayed_work(&ab->dwork, ab->link_status_wait);
-
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t ab8500_usb_v20_irq(int irq, void *data)
-{
-	struct ab8500_usb *ab = (struct ab8500_usb *) data;
-
-	ab8500_usb_link_status_update(ab);
-
-	return IRQ_HANDLED;
-}
-
-static void ab8500_usb_phy_disable_work(struct work_struct *work)
-{
-	struct ab8500_usb *ab = container_of(work, struct ab8500_usb,
-						phy_dis_work);
-
-	if (!ab->phy.otg->host)
-		ab8500_usb_host_phy_dis(ab);
-
-	if (!ab->phy.otg->gadget)
-		ab8500_usb_peri_phy_dis(ab);
-}
-
-static int ab8500_usb_set_power(struct usb_phy *phy, unsigned mA)
-{
-	struct ab8500_usb *ab;
-
-	if (!phy)
-		return -ENODEV;
-
-	ab = phy_to_ab(phy);
-
-	ab->vbus_draw = mA;
-
-	if (mA)
-		atomic_notifier_call_chain(&ab->phy.notifier,
-				USB_EVENT_ENUMERATED, ab->phy.otg->gadget);
-	return 0;
-}
-
-/* TODO: Implement some way for charging or other drivers to read
- * ab->vbus_draw.
- */
-
-static int ab8500_usb_set_suspend(struct usb_phy *x, int suspend)
-{
-	/* TODO */
-	return 0;
-}
-
-static int ab8500_usb_set_peripheral(struct usb_otg *otg,
-					struct usb_gadget *gadget)
-{
-	struct ab8500_usb *ab;
-
-	if (!otg)
-		return -ENODEV;
-
-	ab = phy_to_ab(otg->phy);
-
-	/* Some drivers call this function in atomic context.
-	 * Do not update ab8500 registers directly till this
-	 * is fixed.
-	 */
-
-	if (!gadget) {
-		/* TODO: Disable regulators. */
-		otg->gadget = NULL;
-		schedule_work(&ab->phy_dis_work);
-	} else {
-		otg->gadget = gadget;
-		otg->phy->state = OTG_STATE_B_IDLE;
-
-		/* Phy will not be enabled if cable is already
-		 * plugged-in. Schedule to enable phy.
-		 * Use same delay to avoid any race condition.
-		 */
-		schedule_delayed_work(&ab->dwork, ab->link_status_wait);
-	}
-
-	return 0;
-}
-
-static int ab8500_usb_set_host(struct usb_otg *otg, struct usb_bus *host)
-{
-	struct ab8500_usb *ab;
-
-	if (!otg)
-		return -ENODEV;
-
-	ab = phy_to_ab(otg->phy);
-
-	/* Some drivers call this function in atomic context.
-	 * Do not update ab8500 registers directly till this
-	 * is fixed.
-	 */
-
-	if (!host) {
-		/* TODO: Disable regulators. */
-		otg->host = NULL;
-		schedule_work(&ab->phy_dis_work);
-	} else {
-		otg->host = host;
-		/* Phy will not be enabled if cable is already
-		 * plugged-in. Schedule to enable phy.
-		 * Use same delay to avoid any race condition.
-		 */
-		schedule_delayed_work(&ab->dwork, ab->link_status_wait);
-	}
-
-	return 0;
-}
-
-static void ab8500_usb_irq_free(struct ab8500_usb *ab)
-{
-	if (ab->rev < 0x20) {
-		free_irq(ab->irq_num_id_rise, ab);
-		free_irq(ab->irq_num_id_fall, ab);
-		free_irq(ab->irq_num_vbus_rise, ab);
-		free_irq(ab->irq_num_vbus_fall, ab);
-	} else {
-		free_irq(ab->irq_num_link_status, ab);
-	}
-}
-
-static int ab8500_usb_v1x_res_setup(struct platform_device *pdev,
-				struct ab8500_usb *ab)
-{
-	int err;
-
-	ab->irq_num_id_rise = platform_get_irq_byname(pdev, "ID_WAKEUP_R");
-	if (ab->irq_num_id_rise < 0) {
-		dev_err(&pdev->dev, "ID rise irq not found\n");
-		return ab->irq_num_id_rise;
-	}
-	err = request_threaded_irq(ab->irq_num_id_rise, NULL,
-		ab8500_usb_v1x_common_irq,
-		IRQF_NO_SUSPEND | IRQF_SHARED,
-		"usb-id-rise", ab);
-	if (err < 0) {
-		dev_err(ab->dev, "request_irq failed for ID rise irq\n");
-		goto fail0;
-	}
-
-	ab->irq_num_id_fall = platform_get_irq_byname(pdev, "ID_WAKEUP_F");
-	if (ab->irq_num_id_fall < 0) {
-		dev_err(&pdev->dev, "ID fall irq not found\n");
-		return ab->irq_num_id_fall;
-	}
-	err = request_threaded_irq(ab->irq_num_id_fall, NULL,
-		ab8500_usb_v1x_common_irq,
-		IRQF_NO_SUSPEND | IRQF_SHARED,
-		"usb-id-fall", ab);
-	if (err < 0) {
-		dev_err(ab->dev, "request_irq failed for ID fall irq\n");
-		goto fail1;
-	}
-
-	ab->irq_num_vbus_rise = platform_get_irq_byname(pdev, "VBUS_DET_R");
-	if (ab->irq_num_vbus_rise < 0) {
-		dev_err(&pdev->dev, "VBUS rise irq not found\n");
-		return ab->irq_num_vbus_rise;
-	}
-	err = request_threaded_irq(ab->irq_num_vbus_rise, NULL,
-		ab8500_usb_v1x_common_irq,
-		IRQF_NO_SUSPEND | IRQF_SHARED,
-		"usb-vbus-rise", ab);
-	if (err < 0) {
-		dev_err(ab->dev, "request_irq failed for Vbus rise irq\n");
-		goto fail2;
-	}
-
-	ab->irq_num_vbus_fall = platform_get_irq_byname(pdev, "VBUS_DET_F");
-	if (ab->irq_num_vbus_fall < 0) {
-		dev_err(&pdev->dev, "VBUS fall irq not found\n");
-		return ab->irq_num_vbus_fall;
-	}
-	err = request_threaded_irq(ab->irq_num_vbus_fall, NULL,
-		ab8500_usb_v1x_vbus_fall_irq,
-		IRQF_NO_SUSPEND | IRQF_SHARED,
-		"usb-vbus-fall", ab);
-	if (err < 0) {
-		dev_err(ab->dev, "request_irq failed for Vbus fall irq\n");
-		goto fail3;
-	}
-
-	return 0;
-fail3:
-	free_irq(ab->irq_num_vbus_rise, ab);
-fail2:
-	free_irq(ab->irq_num_id_fall, ab);
-fail1:
-	free_irq(ab->irq_num_id_rise, ab);
-fail0:
-	return err;
-}
-
-static int ab8500_usb_v2_res_setup(struct platform_device *pdev,
-				struct ab8500_usb *ab)
-{
-	int err;
-
-	ab->irq_num_link_status = platform_get_irq_byname(pdev,
-						"USB_LINK_STATUS");
-	if (ab->irq_num_link_status < 0) {
-		dev_err(&pdev->dev, "Link status irq not found\n");
-		return ab->irq_num_link_status;
-	}
-
-	err = request_threaded_irq(ab->irq_num_link_status, NULL,
-		ab8500_usb_v20_irq,
-		IRQF_NO_SUSPEND | IRQF_SHARED,
-		"usb-link-status", ab);
-	if (err < 0) {
-		dev_err(ab->dev,
-			"request_irq failed for link status irq\n");
-		return err;
-	}
-
-	return 0;
-}
-
-static int ab8500_usb_probe(struct platform_device *pdev)
-{
-	struct ab8500_usb	*ab;
-	struct usb_otg		*otg;
-	int err;
-	int rev;
-
-	rev = abx500_get_chip_id(&pdev->dev);
-	if (rev < 0) {
-		dev_err(&pdev->dev, "Chip id read failed\n");
-		return rev;
-	} else if (rev < 0x10) {
-		dev_err(&pdev->dev, "Unsupported AB8500 chip\n");
-		return -ENODEV;
-	}
-
-	ab = kzalloc(sizeof *ab, GFP_KERNEL);
-	if (!ab)
-		return -ENOMEM;
-
-	otg = kzalloc(sizeof *otg, GFP_KERNEL);
-	if (!otg) {
-		kfree(ab);
-		return -ENOMEM;
-	}
-
-	ab->dev			= &pdev->dev;
-	ab->rev			= rev;
-	ab->phy.dev		= ab->dev;
-	ab->phy.otg		= otg;
-	ab->phy.label		= "ab8500";
-	ab->phy.set_suspend	= ab8500_usb_set_suspend;
-	ab->phy.set_power	= ab8500_usb_set_power;
-	ab->phy.state		= OTG_STATE_UNDEFINED;
-
-	otg->phy		= &ab->phy;
-	otg->set_host		= ab8500_usb_set_host;
-	otg->set_peripheral	= ab8500_usb_set_peripheral;
-
-	platform_set_drvdata(pdev, ab);
-
-	ATOMIC_INIT_NOTIFIER_HEAD(&ab->phy.notifier);
-
-	/* v1: Wait for link status to become stable.
-	 * all: Updates form set_host and set_peripheral as they are atomic.
-	 */
-	INIT_DELAYED_WORK(&ab->dwork, ab8500_usb_delayed_work);
-
-	/* all: Disable phy when called from set_host and set_peripheral */
-	INIT_WORK(&ab->phy_dis_work, ab8500_usb_phy_disable_work);
-
-	if (ab->rev < 0x20) {
-		err = ab8500_usb_v1x_res_setup(pdev, ab);
-		ab->link_status_wait = AB8500_V1x_LINK_STAT_WAIT;
-	} else {
-		err = ab8500_usb_v2_res_setup(pdev, ab);
-	}
-
-	if (err < 0)
-		goto fail0;
-
-	err = usb_add_phy(&ab->phy, USB_PHY_TYPE_USB2);
-	if (err) {
-		dev_err(&pdev->dev, "Can't register transceiver\n");
-		goto fail1;
-	}
-
-	dev_info(&pdev->dev, "AB8500 usb driver initialized\n");
-
-	return 0;
-fail1:
-	ab8500_usb_irq_free(ab);
-fail0:
-	kfree(otg);
-	kfree(ab);
-	return err;
-}
-
-static int ab8500_usb_remove(struct platform_device *pdev)
-{
-	struct ab8500_usb *ab = platform_get_drvdata(pdev);
-
-	ab8500_usb_irq_free(ab);
-
-	cancel_delayed_work_sync(&ab->dwork);
-
-	cancel_work_sync(&ab->phy_dis_work);
-
-	usb_remove_phy(&ab->phy);
-
-	ab8500_usb_host_phy_dis(ab);
-	ab8500_usb_peri_phy_dis(ab);
-
-	platform_set_drvdata(pdev, NULL);
-
-	kfree(ab->phy.otg);
-	kfree(ab);
-
-	return 0;
-}
-
-static struct platform_driver ab8500_usb_driver = {
-	.probe		= ab8500_usb_probe,
-	.remove		= ab8500_usb_remove,
-	.driver		= {
-		.name	= "ab8500-usb",
-		.owner	= THIS_MODULE,
-	},
-};
-
-static int __init ab8500_usb_init(void)
-{
-	return platform_driver_register(&ab8500_usb_driver);
-}
-subsys_initcall(ab8500_usb_init);
-
-static void __exit ab8500_usb_exit(void)
-{
-	platform_driver_unregister(&ab8500_usb_driver);
-}
-module_exit(ab8500_usb_exit);
-
-MODULE_ALIAS("platform:ab8500_usb");
-MODULE_AUTHOR("ST-Ericsson AB");
-MODULE_DESCRIPTION("AB8500 usb transceiver driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/usb/otg/fsl_otg.c b/drivers/usb/otg/fsl_otg.c
deleted file mode 100644
index d16adb4..0000000
--- a/drivers/usb/otg/fsl_otg.c
+++ /dev/null
@@ -1,1183 +0,0 @@
-/*
- * Copyright (C) 2007,2008 Freescale semiconductor, Inc.
- *
- * Author: Li Yang <LeoLi@freescale.com>
- *         Jerry Huang <Chang-Ming.Huang@freescale.com>
- *
- * Initialization based on code from Shlomi Gridish.
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You 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/delay.h>
-#include <linux/slab.h>
-#include <linux/proc_fs.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/timer.h>
-#include <linux/usb.h>
-#include <linux/device.h>
-#include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
-#include <linux/workqueue.h>
-#include <linux/time.h>
-#include <linux/fsl_devices.h>
-#include <linux/platform_device.h>
-#include <linux/uaccess.h>
-
-#include <asm/unaligned.h>
-
-#include "fsl_otg.h"
-
-#define DRIVER_VERSION "Rev. 1.55"
-#define DRIVER_AUTHOR "Jerry Huang/Li Yang"
-#define DRIVER_DESC "Freescale USB OTG Transceiver Driver"
-#define DRIVER_INFO DRIVER_DESC " " DRIVER_VERSION
-
-static const char driver_name[] = "fsl-usb2-otg";
-
-const pm_message_t otg_suspend_state = {
-	.event = 1,
-};
-
-#define HA_DATA_PULSE
-
-static struct usb_dr_mmap *usb_dr_regs;
-static struct fsl_otg *fsl_otg_dev;
-static int srp_wait_done;
-
-/* FSM timers */
-struct fsl_otg_timer *a_wait_vrise_tmr, *a_wait_bcon_tmr, *a_aidl_bdis_tmr,
-	*b_ase0_brst_tmr, *b_se0_srp_tmr;
-
-/* Driver specific timers */
-struct fsl_otg_timer *b_data_pulse_tmr, *b_vbus_pulse_tmr, *b_srp_fail_tmr,
-	*b_srp_wait_tmr, *a_wait_enum_tmr;
-
-static struct list_head active_timers;
-
-static struct fsl_otg_config fsl_otg_initdata = {
-	.otg_port = 1,
-};
-
-#ifdef CONFIG_PPC32
-static u32 _fsl_readl_be(const unsigned __iomem *p)
-{
-	return in_be32(p);
-}
-
-static u32 _fsl_readl_le(const unsigned __iomem *p)
-{
-	return in_le32(p);
-}
-
-static void _fsl_writel_be(u32 v, unsigned __iomem *p)
-{
-	out_be32(p, v);
-}
-
-static void _fsl_writel_le(u32 v, unsigned __iomem *p)
-{
-	out_le32(p, v);
-}
-
-static u32 (*_fsl_readl)(const unsigned __iomem *p);
-static void (*_fsl_writel)(u32 v, unsigned __iomem *p);
-
-#define fsl_readl(p)		(*_fsl_readl)((p))
-#define fsl_writel(v, p)	(*_fsl_writel)((v), (p))
-
-#else
-#define fsl_readl(addr)		readl(addr)
-#define fsl_writel(val, addr)	writel(val, addr)
-#endif /* CONFIG_PPC32 */
-
-/* Routines to access transceiver ULPI registers */
-u8 view_ulpi(u8 addr)
-{
-	u32 temp;
-
-	temp = 0x40000000 | (addr << 16);
-	fsl_writel(temp, &usb_dr_regs->ulpiview);
-	udelay(1000);
-	while (temp & 0x40)
-		temp = fsl_readl(&usb_dr_regs->ulpiview);
-	return (le32_to_cpu(temp) & 0x0000ff00) >> 8;
-}
-
-int write_ulpi(u8 addr, u8 data)
-{
-	u32 temp;
-
-	temp = 0x60000000 | (addr << 16) | data;
-	fsl_writel(temp, &usb_dr_regs->ulpiview);
-	return 0;
-}
-
-/* -------------------------------------------------------------*/
-/* Operations that will be called from OTG Finite State Machine */
-
-/* Charge vbus for vbus pulsing in SRP */
-void fsl_otg_chrg_vbus(int on)
-{
-	u32 tmp;
-
-	tmp = fsl_readl(&usb_dr_regs->otgsc) & ~OTGSC_INTSTS_MASK;
-
-	if (on)
-		/* stop discharging, start charging */
-		tmp = (tmp & ~OTGSC_CTRL_VBUS_DISCHARGE) |
-			OTGSC_CTRL_VBUS_CHARGE;
-	else
-		/* stop charging */
-		tmp &= ~OTGSC_CTRL_VBUS_CHARGE;
-
-	fsl_writel(tmp, &usb_dr_regs->otgsc);
-}
-
-/* Discharge vbus through a resistor to ground */
-void fsl_otg_dischrg_vbus(int on)
-{
-	u32 tmp;
-
-	tmp = fsl_readl(&usb_dr_regs->otgsc) & ~OTGSC_INTSTS_MASK;
-
-	if (on)
-		/* stop charging, start discharging */
-		tmp = (tmp & ~OTGSC_CTRL_VBUS_CHARGE) |
-			OTGSC_CTRL_VBUS_DISCHARGE;
-	else
-		/* stop discharging */
-		tmp &= ~OTGSC_CTRL_VBUS_DISCHARGE;
-
-	fsl_writel(tmp, &usb_dr_regs->otgsc);
-}
-
-/* A-device driver vbus, controlled through PP bit in PORTSC */
-void fsl_otg_drv_vbus(int on)
-{
-	u32 tmp;
-
-	if (on) {
-		tmp = fsl_readl(&usb_dr_regs->portsc) & ~PORTSC_W1C_BITS;
-		fsl_writel(tmp | PORTSC_PORT_POWER, &usb_dr_regs->portsc);
-	} else {
-		tmp = fsl_readl(&usb_dr_regs->portsc) &
-		      ~PORTSC_W1C_BITS & ~PORTSC_PORT_POWER;
-		fsl_writel(tmp, &usb_dr_regs->portsc);
-	}
-}
-
-/*
- * Pull-up D+, signalling connect by periperal. Also used in
- * data-line pulsing in SRP
- */
-void fsl_otg_loc_conn(int on)
-{
-	u32 tmp;
-
-	tmp = fsl_readl(&usb_dr_regs->otgsc) & ~OTGSC_INTSTS_MASK;
-
-	if (on)
-		tmp |= OTGSC_CTRL_DATA_PULSING;
-	else
-		tmp &= ~OTGSC_CTRL_DATA_PULSING;
-
-	fsl_writel(tmp, &usb_dr_regs->otgsc);
-}
-
-/*
- * Generate SOF by host.  This is controlled through suspend/resume the
- * port.  In host mode, controller will automatically send SOF.
- * Suspend will block the data on the port.
- */
-void fsl_otg_loc_sof(int on)
-{
-	u32 tmp;
-
-	tmp = fsl_readl(&fsl_otg_dev->dr_mem_map->portsc) & ~PORTSC_W1C_BITS;
-	if (on)
-		tmp |= PORTSC_PORT_FORCE_RESUME;
-	else
-		tmp |= PORTSC_PORT_SUSPEND;
-
-	fsl_writel(tmp, &fsl_otg_dev->dr_mem_map->portsc);
-
-}
-
-/* Start SRP pulsing by data-line pulsing, followed with v-bus pulsing. */
-void fsl_otg_start_pulse(void)
-{
-	u32 tmp;
-
-	srp_wait_done = 0;
-#ifdef HA_DATA_PULSE
-	tmp = fsl_readl(&usb_dr_regs->otgsc) & ~OTGSC_INTSTS_MASK;
-	tmp |= OTGSC_HA_DATA_PULSE;
-	fsl_writel(tmp, &usb_dr_regs->otgsc);
-#else
-	fsl_otg_loc_conn(1);
-#endif
-
-	fsl_otg_add_timer(b_data_pulse_tmr);
-}
-
-void b_data_pulse_end(unsigned long foo)
-{
-#ifdef HA_DATA_PULSE
-#else
-	fsl_otg_loc_conn(0);
-#endif
-
-	/* Do VBUS pulse after data pulse */
-	fsl_otg_pulse_vbus();
-}
-
-void fsl_otg_pulse_vbus(void)
-{
-	srp_wait_done = 0;
-	fsl_otg_chrg_vbus(1);
-	/* start the timer to end vbus charge */
-	fsl_otg_add_timer(b_vbus_pulse_tmr);
-}
-
-void b_vbus_pulse_end(unsigned long foo)
-{
-	fsl_otg_chrg_vbus(0);
-
-	/*
-	 * As USB3300 using the same a_sess_vld and b_sess_vld voltage
-	 * we need to discharge the bus for a while to distinguish
-	 * residual voltage of vbus pulsing and A device pull up
-	 */
-	fsl_otg_dischrg_vbus(1);
-	fsl_otg_add_timer(b_srp_wait_tmr);
-}
-
-void b_srp_end(unsigned long foo)
-{
-	fsl_otg_dischrg_vbus(0);
-	srp_wait_done = 1;
-
-	if ((fsl_otg_dev->phy.state == OTG_STATE_B_SRP_INIT) &&
-	    fsl_otg_dev->fsm.b_sess_vld)
-		fsl_otg_dev->fsm.b_srp_done = 1;
-}
-
-/*
- * Workaround for a_host suspending too fast.  When a_bus_req=0,
- * a_host will start by SRP.  It needs to set b_hnp_enable before
- * actually suspending to start HNP
- */
-void a_wait_enum(unsigned long foo)
-{
-	VDBG("a_wait_enum timeout\n");
-	if (!fsl_otg_dev->phy.otg->host->b_hnp_enable)
-		fsl_otg_add_timer(a_wait_enum_tmr);
-	else
-		otg_statemachine(&fsl_otg_dev->fsm);
-}
-
-/* The timeout callback function to set time out bit */
-void set_tmout(unsigned long indicator)
-{
-	*(int *)indicator = 1;
-}
-
-/* Initialize timers */
-int fsl_otg_init_timers(struct otg_fsm *fsm)
-{
-	/* FSM used timers */
-	a_wait_vrise_tmr = otg_timer_initializer(&set_tmout, TA_WAIT_VRISE,
-				(unsigned long)&fsm->a_wait_vrise_tmout);
-	if (!a_wait_vrise_tmr)
-		return -ENOMEM;
-
-	a_wait_bcon_tmr = otg_timer_initializer(&set_tmout, TA_WAIT_BCON,
-				(unsigned long)&fsm->a_wait_bcon_tmout);
-	if (!a_wait_bcon_tmr)
-		return -ENOMEM;
-
-	a_aidl_bdis_tmr = otg_timer_initializer(&set_tmout, TA_AIDL_BDIS,
-				(unsigned long)&fsm->a_aidl_bdis_tmout);
-	if (!a_aidl_bdis_tmr)
-		return -ENOMEM;
-
-	b_ase0_brst_tmr = otg_timer_initializer(&set_tmout, TB_ASE0_BRST,
-				(unsigned long)&fsm->b_ase0_brst_tmout);
-	if (!b_ase0_brst_tmr)
-		return -ENOMEM;
-
-	b_se0_srp_tmr = otg_timer_initializer(&set_tmout, TB_SE0_SRP,
-				(unsigned long)&fsm->b_se0_srp);
-	if (!b_se0_srp_tmr)
-		return -ENOMEM;
-
-	b_srp_fail_tmr = otg_timer_initializer(&set_tmout, TB_SRP_FAIL,
-				(unsigned long)&fsm->b_srp_done);
-	if (!b_srp_fail_tmr)
-		return -ENOMEM;
-
-	a_wait_enum_tmr = otg_timer_initializer(&a_wait_enum, 10,
-				(unsigned long)&fsm);
-	if (!a_wait_enum_tmr)
-		return -ENOMEM;
-
-	/* device driver used timers */
-	b_srp_wait_tmr = otg_timer_initializer(&b_srp_end, TB_SRP_WAIT, 0);
-	if (!b_srp_wait_tmr)
-		return -ENOMEM;
-
-	b_data_pulse_tmr = otg_timer_initializer(&b_data_pulse_end,
-				TB_DATA_PLS, 0);
-	if (!b_data_pulse_tmr)
-		return -ENOMEM;
-
-	b_vbus_pulse_tmr = otg_timer_initializer(&b_vbus_pulse_end,
-				TB_VBUS_PLS, 0);
-	if (!b_vbus_pulse_tmr)
-		return -ENOMEM;
-
-	return 0;
-}
-
-/* Uninitialize timers */
-void fsl_otg_uninit_timers(void)
-{
-	/* FSM used timers */
-	if (a_wait_vrise_tmr != NULL)
-		kfree(a_wait_vrise_tmr);
-	if (a_wait_bcon_tmr != NULL)
-		kfree(a_wait_bcon_tmr);
-	if (a_aidl_bdis_tmr != NULL)
-		kfree(a_aidl_bdis_tmr);
-	if (b_ase0_brst_tmr != NULL)
-		kfree(b_ase0_brst_tmr);
-	if (b_se0_srp_tmr != NULL)
-		kfree(b_se0_srp_tmr);
-	if (b_srp_fail_tmr != NULL)
-		kfree(b_srp_fail_tmr);
-	if (a_wait_enum_tmr != NULL)
-		kfree(a_wait_enum_tmr);
-
-	/* device driver used timers */
-	if (b_srp_wait_tmr != NULL)
-		kfree(b_srp_wait_tmr);
-	if (b_data_pulse_tmr != NULL)
-		kfree(b_data_pulse_tmr);
-	if (b_vbus_pulse_tmr != NULL)
-		kfree(b_vbus_pulse_tmr);
-}
-
-/* Add timer to timer list */
-void fsl_otg_add_timer(void *gtimer)
-{
-	struct fsl_otg_timer *timer = gtimer;
-	struct fsl_otg_timer *tmp_timer;
-
-	/*
-	 * Check if the timer is already in the active list,
-	 * if so update timer count
-	 */
-	list_for_each_entry(tmp_timer, &active_timers, list)
-	    if (tmp_timer == timer) {
-		timer->count = timer->expires;
-		return;
-	}
-	timer->count = timer->expires;
-	list_add_tail(&timer->list, &active_timers);
-}
-
-/* Remove timer from the timer list; clear timeout status */
-void fsl_otg_del_timer(void *gtimer)
-{
-	struct fsl_otg_timer *timer = gtimer;
-	struct fsl_otg_timer *tmp_timer, *del_tmp;
-
-	list_for_each_entry_safe(tmp_timer, del_tmp, &active_timers, list)
-		if (tmp_timer == timer)
-			list_del(&timer->list);
-}
-
-/*
- * Reduce timer count by 1, and find timeout conditions.
- * Called by fsl_otg 1ms timer interrupt
- */
-int fsl_otg_tick_timer(void)
-{
-	struct fsl_otg_timer *tmp_timer, *del_tmp;
-	int expired = 0;
-
-	list_for_each_entry_safe(tmp_timer, del_tmp, &active_timers, list) {
-		tmp_timer->count--;
-		/* check if timer expires */
-		if (!tmp_timer->count) {
-			list_del(&tmp_timer->list);
-			tmp_timer->function(tmp_timer->data);
-			expired = 1;
-		}
-	}
-
-	return expired;
-}
-
-/* Reset controller, not reset the bus */
-void otg_reset_controller(void)
-{
-	u32 command;
-
-	command = fsl_readl(&usb_dr_regs->usbcmd);
-	command |= (1 << 1);
-	fsl_writel(command, &usb_dr_regs->usbcmd);
-	while (fsl_readl(&usb_dr_regs->usbcmd) & (1 << 1))
-		;
-}
-
-/* Call suspend/resume routines in host driver */
-int fsl_otg_start_host(struct otg_fsm *fsm, int on)
-{
-	struct usb_otg *otg = fsm->otg;
-	struct device *dev;
-	struct fsl_otg *otg_dev = container_of(otg->phy, struct fsl_otg, phy);
-	u32 retval = 0;
-
-	if (!otg->host)
-		return -ENODEV;
-	dev = otg->host->controller;
-
-	/*
-	 * Update a_vbus_vld state as a_vbus_vld int is disabled
-	 * in device mode
-	 */
-	fsm->a_vbus_vld =
-		!!(fsl_readl(&usb_dr_regs->otgsc) & OTGSC_STS_A_VBUS_VALID);
-	if (on) {
-		/* start fsl usb host controller */
-		if (otg_dev->host_working)
-			goto end;
-		else {
-			otg_reset_controller();
-			VDBG("host on......\n");
-			if (dev->driver->pm && dev->driver->pm->resume) {
-				retval = dev->driver->pm->resume(dev);
-				if (fsm->id) {
-					/* default-b */
-					fsl_otg_drv_vbus(1);
-					/*
-					 * Workaround: b_host can't driver
-					 * vbus, but PP in PORTSC needs to
-					 * be 1 for host to work.
-					 * So we set drv_vbus bit in
-					 * transceiver to 0 thru ULPI.
-					 */
-					write_ulpi(0x0c, 0x20);
-				}
-			}
-
-			otg_dev->host_working = 1;
-		}
-	} else {
-		/* stop fsl usb host controller */
-		if (!otg_dev->host_working)
-			goto end;
-		else {
-			VDBG("host off......\n");
-			if (dev && dev->driver) {
-				if (dev->driver->pm && dev->driver->pm->suspend)
-					retval = dev->driver->pm->suspend(dev);
-				if (fsm->id)
-					/* default-b */
-					fsl_otg_drv_vbus(0);
-			}
-			otg_dev->host_working = 0;
-		}
-	}
-end:
-	return retval;
-}
-
-/*
- * Call suspend and resume function in udc driver
- * to stop and start udc driver.
- */
-int fsl_otg_start_gadget(struct otg_fsm *fsm, int on)
-{
-	struct usb_otg *otg = fsm->otg;
-	struct device *dev;
-
-	if (!otg->gadget || !otg->gadget->dev.parent)
-		return -ENODEV;
-
-	VDBG("gadget %s\n", on ? "on" : "off");
-	dev = otg->gadget->dev.parent;
-
-	if (on) {
-		if (dev->driver->resume)
-			dev->driver->resume(dev);
-	} else {
-		if (dev->driver->suspend)
-			dev->driver->suspend(dev, otg_suspend_state);
-	}
-
-	return 0;
-}
-
-/*
- * Called by initialization code of host driver.  Register host controller
- * to the OTG.  Suspend host for OTG role detection.
- */
-static int fsl_otg_set_host(struct usb_otg *otg, struct usb_bus *host)
-{
-	struct fsl_otg *otg_dev;
-
-	if (!otg)
-		return -ENODEV;
-
-	otg_dev = container_of(otg->phy, struct fsl_otg, phy);
-	if (otg_dev != fsl_otg_dev)
-		return -ENODEV;
-
-	otg->host = host;
-
-	otg_dev->fsm.a_bus_drop = 0;
-	otg_dev->fsm.a_bus_req = 1;
-
-	if (host) {
-		VDBG("host off......\n");
-
-		otg->host->otg_port = fsl_otg_initdata.otg_port;
-		otg->host->is_b_host = otg_dev->fsm.id;
-		/*
-		 * must leave time for khubd to finish its thing
-		 * before yanking the host driver out from under it,
-		 * so suspend the host after a short delay.
-		 */
-		otg_dev->host_working = 1;
-		schedule_delayed_work(&otg_dev->otg_event, 100);
-		return 0;
-	} else {
-		/* host driver going away */
-		if (!(fsl_readl(&otg_dev->dr_mem_map->otgsc) &
-		      OTGSC_STS_USB_ID)) {
-			/* Mini-A cable connected */
-			struct otg_fsm *fsm = &otg_dev->fsm;
-
-			otg->phy->state = OTG_STATE_UNDEFINED;
-			fsm->protocol = PROTO_UNDEF;
-		}
-	}
-
-	otg_dev->host_working = 0;
-
-	otg_statemachine(&otg_dev->fsm);
-
-	return 0;
-}
-
-/* Called by initialization code of udc.  Register udc to OTG. */
-static int fsl_otg_set_peripheral(struct usb_otg *otg,
-					struct usb_gadget *gadget)
-{
-	struct fsl_otg *otg_dev;
-
-	if (!otg)
-		return -ENODEV;
-
-	otg_dev = container_of(otg->phy, struct fsl_otg, phy);
-	VDBG("otg_dev 0x%x\n", (int)otg_dev);
-	VDBG("fsl_otg_dev 0x%x\n", (int)fsl_otg_dev);
-	if (otg_dev != fsl_otg_dev)
-		return -ENODEV;
-
-	if (!gadget) {
-		if (!otg->default_a)
-			otg->gadget->ops->vbus_draw(otg->gadget, 0);
-		usb_gadget_vbus_disconnect(otg->gadget);
-		otg->gadget = 0;
-		otg_dev->fsm.b_bus_req = 0;
-		otg_statemachine(&otg_dev->fsm);
-		return 0;
-	}
-
-	otg->gadget = gadget;
-	otg->gadget->is_a_peripheral = !otg_dev->fsm.id;
-
-	otg_dev->fsm.b_bus_req = 1;
-
-	/* start the gadget right away if the ID pin says Mini-B */
-	DBG("ID pin=%d\n", otg_dev->fsm.id);
-	if (otg_dev->fsm.id == 1) {
-		fsl_otg_start_host(&otg_dev->fsm, 0);
-		otg_drv_vbus(&otg_dev->fsm, 0);
-		fsl_otg_start_gadget(&otg_dev->fsm, 1);
-	}
-
-	return 0;
-}
-
-/* Set OTG port power, only for B-device */
-static int fsl_otg_set_power(struct usb_phy *phy, unsigned mA)
-{
-	if (!fsl_otg_dev)
-		return -ENODEV;
-	if (phy->state == OTG_STATE_B_PERIPHERAL)
-		pr_info("FSL OTG: Draw %d mA\n", mA);
-
-	return 0;
-}
-
-/*
- * Delayed pin detect interrupt processing.
- *
- * When the Mini-A cable is disconnected from the board,
- * the pin-detect interrupt happens before the disconnect
- * interrupts for the connected device(s).  In order to
- * process the disconnect interrupt(s) prior to switching
- * roles, the pin-detect interrupts are delayed, and handled
- * by this routine.
- */
-static void fsl_otg_event(struct work_struct *work)
-{
-	struct fsl_otg *og = container_of(work, struct fsl_otg, otg_event.work);
-	struct otg_fsm *fsm = &og->fsm;
-
-	if (fsm->id) {		/* switch to gadget */
-		fsl_otg_start_host(fsm, 0);
-		otg_drv_vbus(fsm, 0);
-		fsl_otg_start_gadget(fsm, 1);
-	}
-}
-
-/* B-device start SRP */
-static int fsl_otg_start_srp(struct usb_otg *otg)
-{
-	struct fsl_otg *otg_dev;
-
-	if (!otg || otg->phy->state != OTG_STATE_B_IDLE)
-		return -ENODEV;
-
-	otg_dev = container_of(otg->phy, struct fsl_otg, phy);
-	if (otg_dev != fsl_otg_dev)
-		return -ENODEV;
-
-	otg_dev->fsm.b_bus_req = 1;
-	otg_statemachine(&otg_dev->fsm);
-
-	return 0;
-}
-
-/* A_host suspend will call this function to start hnp */
-static int fsl_otg_start_hnp(struct usb_otg *otg)
-{
-	struct fsl_otg *otg_dev;
-
-	if (!otg)
-		return -ENODEV;
-
-	otg_dev = container_of(otg->phy, struct fsl_otg, phy);
-	if (otg_dev != fsl_otg_dev)
-		return -ENODEV;
-
-	DBG("start_hnp...n");
-
-	/* clear a_bus_req to enter a_suspend state */
-	otg_dev->fsm.a_bus_req = 0;
-	otg_statemachine(&otg_dev->fsm);
-
-	return 0;
-}
-
-/*
- * Interrupt handler.  OTG/host/peripheral share the same int line.
- * OTG driver clears OTGSC interrupts and leaves USB interrupts
- * intact.  It needs to have knowledge of some USB interrupts
- * such as port change.
- */
-irqreturn_t fsl_otg_isr(int irq, void *dev_id)
-{
-	struct otg_fsm *fsm = &((struct fsl_otg *)dev_id)->fsm;
-	struct usb_otg *otg = ((struct fsl_otg *)dev_id)->phy.otg;
-	u32 otg_int_src, otg_sc;
-
-	otg_sc = fsl_readl(&usb_dr_regs->otgsc);
-	otg_int_src = otg_sc & OTGSC_INTSTS_MASK & (otg_sc >> 8);
-
-	/* Only clear otg interrupts */
-	fsl_writel(otg_sc, &usb_dr_regs->otgsc);
-
-	/*FIXME: ID change not generate when init to 0 */
-	fsm->id = (otg_sc & OTGSC_STS_USB_ID) ? 1 : 0;
-	otg->default_a = (fsm->id == 0);
-
-	/* process OTG interrupts */
-	if (otg_int_src) {
-		if (otg_int_src & OTGSC_INTSTS_USB_ID) {
-			fsm->id = (otg_sc & OTGSC_STS_USB_ID) ? 1 : 0;
-			otg->default_a = (fsm->id == 0);
-			/* clear conn information */
-			if (fsm->id)
-				fsm->b_conn = 0;
-			else
-				fsm->a_conn = 0;
-
-			if (otg->host)
-				otg->host->is_b_host = fsm->id;
-			if (otg->gadget)
-				otg->gadget->is_a_peripheral = !fsm->id;
-			VDBG("ID int (ID is %d)\n", fsm->id);
-
-			if (fsm->id) {	/* switch to gadget */
-				schedule_delayed_work(
-					&((struct fsl_otg *)dev_id)->otg_event,
-					100);
-			} else {	/* switch to host */
-				cancel_delayed_work(&
-						    ((struct fsl_otg *)dev_id)->
-						    otg_event);
-				fsl_otg_start_gadget(fsm, 0);
-				otg_drv_vbus(fsm, 1);
-				fsl_otg_start_host(fsm, 1);
-			}
-			return IRQ_HANDLED;
-		}
-	}
-	return IRQ_NONE;
-}
-
-static struct otg_fsm_ops fsl_otg_ops = {
-	.chrg_vbus = fsl_otg_chrg_vbus,
-	.drv_vbus = fsl_otg_drv_vbus,
-	.loc_conn = fsl_otg_loc_conn,
-	.loc_sof = fsl_otg_loc_sof,
-	.start_pulse = fsl_otg_start_pulse,
-
-	.add_timer = fsl_otg_add_timer,
-	.del_timer = fsl_otg_del_timer,
-
-	.start_host = fsl_otg_start_host,
-	.start_gadget = fsl_otg_start_gadget,
-};
-
-/* Initialize the global variable fsl_otg_dev and request IRQ for OTG */
-static int fsl_otg_conf(struct platform_device *pdev)
-{
-	struct fsl_otg *fsl_otg_tc;
-	int status;
-
-	if (fsl_otg_dev)
-		return 0;
-
-	/* allocate space to fsl otg device */
-	fsl_otg_tc = kzalloc(sizeof(struct fsl_otg), GFP_KERNEL);
-	if (!fsl_otg_tc)
-		return -ENOMEM;
-
-	fsl_otg_tc->phy.otg = kzalloc(sizeof(struct usb_otg), GFP_KERNEL);
-	if (!fsl_otg_tc->phy.otg) {
-		kfree(fsl_otg_tc);
-		return -ENOMEM;
-	}
-
-	INIT_DELAYED_WORK(&fsl_otg_tc->otg_event, fsl_otg_event);
-
-	INIT_LIST_HEAD(&active_timers);
-	status = fsl_otg_init_timers(&fsl_otg_tc->fsm);
-	if (status) {
-		pr_info("Couldn't init OTG timers\n");
-		goto err;
-	}
-	spin_lock_init(&fsl_otg_tc->fsm.lock);
-
-	/* Set OTG state machine operations */
-	fsl_otg_tc->fsm.ops = &fsl_otg_ops;
-
-	/* initialize the otg structure */
-	fsl_otg_tc->phy.label = DRIVER_DESC;
-	fsl_otg_tc->phy.set_power = fsl_otg_set_power;
-
-	fsl_otg_tc->phy.otg->phy = &fsl_otg_tc->phy;
-	fsl_otg_tc->phy.otg->set_host = fsl_otg_set_host;
-	fsl_otg_tc->phy.otg->set_peripheral = fsl_otg_set_peripheral;
-	fsl_otg_tc->phy.otg->start_hnp = fsl_otg_start_hnp;
-	fsl_otg_tc->phy.otg->start_srp = fsl_otg_start_srp;
-
-	fsl_otg_dev = fsl_otg_tc;
-
-	/* Store the otg transceiver */
-	status = usb_add_phy(&fsl_otg_tc->phy, USB_PHY_TYPE_USB2);
-	if (status) {
-		pr_warn(FSL_OTG_NAME ": unable to register OTG transceiver.\n");
-		goto err;
-	}
-
-	return 0;
-err:
-	fsl_otg_uninit_timers();
-	kfree(fsl_otg_tc->phy.otg);
-	kfree(fsl_otg_tc);
-	return status;
-}
-
-/* OTG Initialization */
-int usb_otg_start(struct platform_device *pdev)
-{
-	struct fsl_otg *p_otg;
-	struct usb_phy *otg_trans = usb_get_phy(USB_PHY_TYPE_USB2);
-	struct otg_fsm *fsm;
-	int status;
-	struct resource *res;
-	u32 temp;
-	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
-
-	p_otg = container_of(otg_trans, struct fsl_otg, phy);
-	fsm = &p_otg->fsm;
-
-	/* Initialize the state machine structure with default values */
-	SET_OTG_STATE(otg_trans, OTG_STATE_UNDEFINED);
-	fsm->otg = p_otg->phy.otg;
-
-	/* We don't require predefined MEM/IRQ resource index */
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res)
-		return -ENXIO;
-
-	/* We don't request_mem_region here to enable resource sharing
-	 * with host/device */
-
-	usb_dr_regs = ioremap(res->start, sizeof(struct usb_dr_mmap));
-	p_otg->dr_mem_map = (struct usb_dr_mmap *)usb_dr_regs;
-	pdata->regs = (void *)usb_dr_regs;
-
-	if (pdata->init && pdata->init(pdev) != 0)
-		return -EINVAL;
-
-	if (pdata->big_endian_mmio) {
-		_fsl_readl = _fsl_readl_be;
-		_fsl_writel = _fsl_writel_be;
-	} else {
-		_fsl_readl = _fsl_readl_le;
-		_fsl_writel = _fsl_writel_le;
-	}
-
-	/* request irq */
-	p_otg->irq = platform_get_irq(pdev, 0);
-	status = request_irq(p_otg->irq, fsl_otg_isr,
-				IRQF_SHARED, driver_name, p_otg);
-	if (status) {
-		dev_dbg(p_otg->phy.dev, "can't get IRQ %d, error %d\n",
-			p_otg->irq, status);
-		iounmap(p_otg->dr_mem_map);
-		kfree(p_otg->phy.otg);
-		kfree(p_otg);
-		return status;
-	}
-
-	/* stop the controller */
-	temp = fsl_readl(&p_otg->dr_mem_map->usbcmd);
-	temp &= ~USB_CMD_RUN_STOP;
-	fsl_writel(temp, &p_otg->dr_mem_map->usbcmd);
-
-	/* reset the controller */
-	temp = fsl_readl(&p_otg->dr_mem_map->usbcmd);
-	temp |= USB_CMD_CTRL_RESET;
-	fsl_writel(temp, &p_otg->dr_mem_map->usbcmd);
-
-	/* wait reset completed */
-	while (fsl_readl(&p_otg->dr_mem_map->usbcmd) & USB_CMD_CTRL_RESET)
-		;
-
-	/* configure the VBUSHS as IDLE(both host and device) */
-	temp = USB_MODE_STREAM_DISABLE | (pdata->es ? USB_MODE_ES : 0);
-	fsl_writel(temp, &p_otg->dr_mem_map->usbmode);
-
-	/* configure PHY interface */
-	temp = fsl_readl(&p_otg->dr_mem_map->portsc);
-	temp &= ~(PORTSC_PHY_TYPE_SEL | PORTSC_PTW);
-	switch (pdata->phy_mode) {
-	case FSL_USB2_PHY_ULPI:
-		temp |= PORTSC_PTS_ULPI;
-		break;
-	case FSL_USB2_PHY_UTMI_WIDE:
-		temp |= PORTSC_PTW_16BIT;
-		/* fall through */
-	case FSL_USB2_PHY_UTMI:
-		temp |= PORTSC_PTS_UTMI;
-		/* fall through */
-	default:
-		break;
-	}
-	fsl_writel(temp, &p_otg->dr_mem_map->portsc);
-
-	if (pdata->have_sysif_regs) {
-		/* configure control enable IO output, big endian register */
-		temp = __raw_readl(&p_otg->dr_mem_map->control);
-		temp |= USB_CTRL_IOENB;
-		__raw_writel(temp, &p_otg->dr_mem_map->control);
-	}
-
-	/* disable all interrupt and clear all OTGSC status */
-	temp = fsl_readl(&p_otg->dr_mem_map->otgsc);
-	temp &= ~OTGSC_INTERRUPT_ENABLE_BITS_MASK;
-	temp |= OTGSC_INTERRUPT_STATUS_BITS_MASK | OTGSC_CTRL_VBUS_DISCHARGE;
-	fsl_writel(temp, &p_otg->dr_mem_map->otgsc);
-
-	/*
-	 * The identification (id) input is FALSE when a Mini-A plug is inserted
-	 * in the devices Mini-AB receptacle. Otherwise, this input is TRUE.
-	 * Also: record initial state of ID pin
-	 */
-	if (fsl_readl(&p_otg->dr_mem_map->otgsc) & OTGSC_STS_USB_ID) {
-		p_otg->phy.state = OTG_STATE_UNDEFINED;
-		p_otg->fsm.id = 1;
-	} else {
-		p_otg->phy.state = OTG_STATE_A_IDLE;
-		p_otg->fsm.id = 0;
-	}
-
-	DBG("initial ID pin=%d\n", p_otg->fsm.id);
-
-	/* enable OTG ID pin interrupt */
-	temp = fsl_readl(&p_otg->dr_mem_map->otgsc);
-	temp |= OTGSC_INTR_USB_ID_EN;
-	temp &= ~(OTGSC_CTRL_VBUS_DISCHARGE | OTGSC_INTR_1MS_TIMER_EN);
-	fsl_writel(temp, &p_otg->dr_mem_map->otgsc);
-
-	return 0;
-}
-
-/*
- * state file in sysfs
- */
-static int show_fsl_usb2_otg_state(struct device *dev,
-				   struct device_attribute *attr, char *buf)
-{
-	struct otg_fsm *fsm = &fsl_otg_dev->fsm;
-	char *next = buf;
-	unsigned size = PAGE_SIZE;
-	unsigned long flags;
-	int t;
-
-	spin_lock_irqsave(&fsm->lock, flags);
-
-	/* basic driver infomation */
-	t = scnprintf(next, size,
-			DRIVER_DESC "\n" "fsl_usb2_otg version: %s\n\n",
-			DRIVER_VERSION);
-	size -= t;
-	next += t;
-
-	/* Registers */
-	t = scnprintf(next, size,
-			"OTGSC:   0x%08x\n"
-			"PORTSC:  0x%08x\n"
-			"USBMODE: 0x%08x\n"
-			"USBCMD:  0x%08x\n"
-			"USBSTS:  0x%08x\n"
-			"USBINTR: 0x%08x\n",
-			fsl_readl(&usb_dr_regs->otgsc),
-			fsl_readl(&usb_dr_regs->portsc),
-			fsl_readl(&usb_dr_regs->usbmode),
-			fsl_readl(&usb_dr_regs->usbcmd),
-			fsl_readl(&usb_dr_regs->usbsts),
-			fsl_readl(&usb_dr_regs->usbintr));
-	size -= t;
-	next += t;
-
-	/* State */
-	t = scnprintf(next, size,
-		      "OTG state: %s\n\n",
-		      otg_state_string(fsl_otg_dev->phy.state));
-	size -= t;
-	next += t;
-
-	/* State Machine Variables */
-	t = scnprintf(next, size,
-			"a_bus_req: %d\n"
-			"b_bus_req: %d\n"
-			"a_bus_resume: %d\n"
-			"a_bus_suspend: %d\n"
-			"a_conn: %d\n"
-			"a_sess_vld: %d\n"
-			"a_srp_det: %d\n"
-			"a_vbus_vld: %d\n"
-			"b_bus_resume: %d\n"
-			"b_bus_suspend: %d\n"
-			"b_conn: %d\n"
-			"b_se0_srp: %d\n"
-			"b_sess_end: %d\n"
-			"b_sess_vld: %d\n"
-			"id: %d\n",
-			fsm->a_bus_req,
-			fsm->b_bus_req,
-			fsm->a_bus_resume,
-			fsm->a_bus_suspend,
-			fsm->a_conn,
-			fsm->a_sess_vld,
-			fsm->a_srp_det,
-			fsm->a_vbus_vld,
-			fsm->b_bus_resume,
-			fsm->b_bus_suspend,
-			fsm->b_conn,
-			fsm->b_se0_srp,
-			fsm->b_sess_end,
-			fsm->b_sess_vld,
-			fsm->id);
-	size -= t;
-	next += t;
-
-	spin_unlock_irqrestore(&fsm->lock, flags);
-
-	return PAGE_SIZE - size;
-}
-
-static DEVICE_ATTR(fsl_usb2_otg_state, S_IRUGO, show_fsl_usb2_otg_state, NULL);
-
-
-/* Char driver interface to control some OTG input */
-
-/*
- * Handle some ioctl command, such as get otg
- * status and set host suspend
- */
-static long fsl_otg_ioctl(struct file *file, unsigned int cmd,
-			  unsigned long arg)
-{
-	u32 retval = 0;
-
-	switch (cmd) {
-	case GET_OTG_STATUS:
-		retval = fsl_otg_dev->host_working;
-		break;
-
-	case SET_A_SUSPEND_REQ:
-		fsl_otg_dev->fsm.a_suspend_req = arg;
-		break;
-
-	case SET_A_BUS_DROP:
-		fsl_otg_dev->fsm.a_bus_drop = arg;
-		break;
-
-	case SET_A_BUS_REQ:
-		fsl_otg_dev->fsm.a_bus_req = arg;
-		break;
-
-	case SET_B_BUS_REQ:
-		fsl_otg_dev->fsm.b_bus_req = arg;
-		break;
-
-	default:
-		break;
-	}
-
-	otg_statemachine(&fsl_otg_dev->fsm);
-
-	return retval;
-}
-
-static int fsl_otg_open(struct inode *inode, struct file *file)
-{
-	return 0;
-}
-
-static int fsl_otg_release(struct inode *inode, struct file *file)
-{
-	return 0;
-}
-
-static const struct file_operations otg_fops = {
-	.owner = THIS_MODULE,
-	.llseek = NULL,
-	.read = NULL,
-	.write = NULL,
-	.unlocked_ioctl = fsl_otg_ioctl,
-	.open = fsl_otg_open,
-	.release = fsl_otg_release,
-};
-
-static int fsl_otg_probe(struct platform_device *pdev)
-{
-	int ret;
-
-	if (!pdev->dev.platform_data)
-		return -ENODEV;
-
-	/* configure the OTG */
-	ret = fsl_otg_conf(pdev);
-	if (ret) {
-		dev_err(&pdev->dev, "Couldn't configure OTG module\n");
-		return ret;
-	}
-
-	/* start OTG */
-	ret = usb_otg_start(pdev);
-	if (ret) {
-		dev_err(&pdev->dev, "Can't init FSL OTG device\n");
-		return ret;
-	}
-
-	ret = register_chrdev(FSL_OTG_MAJOR, FSL_OTG_NAME, &otg_fops);
-	if (ret) {
-		dev_err(&pdev->dev, "unable to register FSL OTG device\n");
-		return ret;
-	}
-
-	ret = device_create_file(&pdev->dev, &dev_attr_fsl_usb2_otg_state);
-	if (ret)
-		dev_warn(&pdev->dev, "Can't register sysfs attribute\n");
-
-	return ret;
-}
-
-static int fsl_otg_remove(struct platform_device *pdev)
-{
-	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
-
-	usb_remove_phy(&fsl_otg_dev->phy);
-	free_irq(fsl_otg_dev->irq, fsl_otg_dev);
-
-	iounmap((void *)usb_dr_regs);
-
-	fsl_otg_uninit_timers();
-	kfree(fsl_otg_dev->phy.otg);
-	kfree(fsl_otg_dev);
-
-	device_remove_file(&pdev->dev, &dev_attr_fsl_usb2_otg_state);
-
-	unregister_chrdev(FSL_OTG_MAJOR, FSL_OTG_NAME);
-
-	if (pdata->exit)
-		pdata->exit(pdev);
-
-	return 0;
-}
-
-struct platform_driver fsl_otg_driver = {
-	.probe = fsl_otg_probe,
-	.remove = fsl_otg_remove,
-	.driver = {
-		.name = driver_name,
-		.owner = THIS_MODULE,
-	},
-};
-
-module_platform_driver(fsl_otg_driver);
-
-MODULE_DESCRIPTION(DRIVER_INFO);
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_LICENSE("GPL");
diff --git a/drivers/usb/otg/fsl_otg.h b/drivers/usb/otg/fsl_otg.h
deleted file mode 100644
index ca26628..0000000
--- a/drivers/usb/otg/fsl_otg.h
+++ /dev/null
@@ -1,406 +0,0 @@
-/* Copyright (C) 2007,2008 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.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You 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 "otg_fsm.h"
-#include <linux/usb/otg.h>
-#include <linux/ioctl.h>
-
-/* USB Command Register Bit Masks */
-#define USB_CMD_RUN_STOP		(0x1<<0)
-#define USB_CMD_CTRL_RESET		(0x1<<1)
-#define USB_CMD_PERIODIC_SCHEDULE_EN	(0x1<<4)
-#define USB_CMD_ASYNC_SCHEDULE_EN	(0x1<<5)
-#define USB_CMD_INT_AA_DOORBELL		(0x1<<6)
-#define USB_CMD_ASP			(0x3<<8)
-#define USB_CMD_ASYNC_SCH_PARK_EN	(0x1<<11)
-#define USB_CMD_SUTW			(0x1<<13)
-#define USB_CMD_ATDTW			(0x1<<14)
-#define USB_CMD_ITC			(0xFF<<16)
-
-/* bit 15,3,2 are frame list size */
-#define USB_CMD_FRAME_SIZE_1024		(0x0<<15 | 0x0<<2)
-#define USB_CMD_FRAME_SIZE_512		(0x0<<15 | 0x1<<2)
-#define USB_CMD_FRAME_SIZE_256		(0x0<<15 | 0x2<<2)
-#define USB_CMD_FRAME_SIZE_128		(0x0<<15 | 0x3<<2)
-#define USB_CMD_FRAME_SIZE_64		(0x1<<15 | 0x0<<2)
-#define USB_CMD_FRAME_SIZE_32		(0x1<<15 | 0x1<<2)
-#define USB_CMD_FRAME_SIZE_16		(0x1<<15 | 0x2<<2)
-#define USB_CMD_FRAME_SIZE_8		(0x1<<15 | 0x3<<2)
-
-/* bit 9-8 are async schedule park mode count */
-#define USB_CMD_ASP_00			(0x0<<8)
-#define USB_CMD_ASP_01			(0x1<<8)
-#define USB_CMD_ASP_10			(0x2<<8)
-#define USB_CMD_ASP_11			(0x3<<8)
-#define USB_CMD_ASP_BIT_POS		(8)
-
-/* bit 23-16 are interrupt threshold control */
-#define USB_CMD_ITC_NO_THRESHOLD	(0x00<<16)
-#define USB_CMD_ITC_1_MICRO_FRM		(0x01<<16)
-#define USB_CMD_ITC_2_MICRO_FRM		(0x02<<16)
-#define USB_CMD_ITC_4_MICRO_FRM		(0x04<<16)
-#define USB_CMD_ITC_8_MICRO_FRM		(0x08<<16)
-#define USB_CMD_ITC_16_MICRO_FRM	(0x10<<16)
-#define USB_CMD_ITC_32_MICRO_FRM	(0x20<<16)
-#define USB_CMD_ITC_64_MICRO_FRM	(0x40<<16)
-#define USB_CMD_ITC_BIT_POS		(16)
-
-/* USB Status Register Bit Masks */
-#define USB_STS_INT			(0x1<<0)
-#define USB_STS_ERR			(0x1<<1)
-#define USB_STS_PORT_CHANGE		(0x1<<2)
-#define USB_STS_FRM_LST_ROLL		(0x1<<3)
-#define USB_STS_SYS_ERR			(0x1<<4)
-#define USB_STS_IAA			(0x1<<5)
-#define USB_STS_RESET_RECEIVED		(0x1<<6)
-#define USB_STS_SOF			(0x1<<7)
-#define USB_STS_DCSUSPEND		(0x1<<8)
-#define USB_STS_HC_HALTED		(0x1<<12)
-#define USB_STS_RCL			(0x1<<13)
-#define USB_STS_PERIODIC_SCHEDULE	(0x1<<14)
-#define USB_STS_ASYNC_SCHEDULE		(0x1<<15)
-
-/* USB Interrupt Enable Register Bit Masks */
-#define USB_INTR_INT_EN			(0x1<<0)
-#define USB_INTR_ERR_INT_EN		(0x1<<1)
-#define USB_INTR_PC_DETECT_EN		(0x1<<2)
-#define USB_INTR_FRM_LST_ROLL_EN	(0x1<<3)
-#define USB_INTR_SYS_ERR_EN		(0x1<<4)
-#define USB_INTR_ASYN_ADV_EN		(0x1<<5)
-#define USB_INTR_RESET_EN		(0x1<<6)
-#define USB_INTR_SOF_EN			(0x1<<7)
-#define USB_INTR_DEVICE_SUSPEND		(0x1<<8)
-
-/* Device Address bit masks */
-#define USB_DEVICE_ADDRESS_MASK		(0x7F<<25)
-#define USB_DEVICE_ADDRESS_BIT_POS	(25)
-/* PORTSC  Register Bit Masks,Only one PORT in OTG mode*/
-#define PORTSC_CURRENT_CONNECT_STATUS	(0x1<<0)
-#define PORTSC_CONNECT_STATUS_CHANGE	(0x1<<1)
-#define PORTSC_PORT_ENABLE		(0x1<<2)
-#define PORTSC_PORT_EN_DIS_CHANGE	(0x1<<3)
-#define PORTSC_OVER_CURRENT_ACT		(0x1<<4)
-#define PORTSC_OVER_CUURENT_CHG		(0x1<<5)
-#define PORTSC_PORT_FORCE_RESUME	(0x1<<6)
-#define PORTSC_PORT_SUSPEND		(0x1<<7)
-#define PORTSC_PORT_RESET		(0x1<<8)
-#define PORTSC_LINE_STATUS_BITS		(0x3<<10)
-#define PORTSC_PORT_POWER		(0x1<<12)
-#define PORTSC_PORT_INDICTOR_CTRL	(0x3<<14)
-#define PORTSC_PORT_TEST_CTRL		(0xF<<16)
-#define PORTSC_WAKE_ON_CONNECT_EN	(0x1<<20)
-#define PORTSC_WAKE_ON_CONNECT_DIS	(0x1<<21)
-#define PORTSC_WAKE_ON_OVER_CURRENT	(0x1<<22)
-#define PORTSC_PHY_LOW_POWER_SPD	(0x1<<23)
-#define PORTSC_PORT_FORCE_FULL_SPEED	(0x1<<24)
-#define PORTSC_PORT_SPEED_MASK		(0x3<<26)
-#define PORTSC_TRANSCEIVER_WIDTH	(0x1<<28)
-#define PORTSC_PHY_TYPE_SEL		(0x3<<30)
-/* bit 11-10 are line status */
-#define PORTSC_LINE_STATUS_SE0		(0x0<<10)
-#define PORTSC_LINE_STATUS_JSTATE	(0x1<<10)
-#define PORTSC_LINE_STATUS_KSTATE	(0x2<<10)
-#define PORTSC_LINE_STATUS_UNDEF	(0x3<<10)
-#define PORTSC_LINE_STATUS_BIT_POS	(10)
-
-/* bit 15-14 are port indicator control */
-#define PORTSC_PIC_OFF			(0x0<<14)
-#define PORTSC_PIC_AMBER		(0x1<<14)
-#define PORTSC_PIC_GREEN		(0x2<<14)
-#define PORTSC_PIC_UNDEF		(0x3<<14)
-#define PORTSC_PIC_BIT_POS		(14)
-
-/* bit 19-16 are port test control */
-#define PORTSC_PTC_DISABLE		(0x0<<16)
-#define PORTSC_PTC_JSTATE		(0x1<<16)
-#define PORTSC_PTC_KSTATE		(0x2<<16)
-#define PORTSC_PTC_SEQNAK		(0x3<<16)
-#define PORTSC_PTC_PACKET		(0x4<<16)
-#define PORTSC_PTC_FORCE_EN		(0x5<<16)
-#define PORTSC_PTC_BIT_POS		(16)
-
-/* bit 27-26 are port speed */
-#define PORTSC_PORT_SPEED_FULL		(0x0<<26)
-#define PORTSC_PORT_SPEED_LOW		(0x1<<26)
-#define PORTSC_PORT_SPEED_HIGH		(0x2<<26)
-#define PORTSC_PORT_SPEED_UNDEF		(0x3<<26)
-#define PORTSC_SPEED_BIT_POS		(26)
-
-/* bit 28 is parallel transceiver width for UTMI interface */
-#define PORTSC_PTW			(0x1<<28)
-#define PORTSC_PTW_8BIT			(0x0<<28)
-#define PORTSC_PTW_16BIT		(0x1<<28)
-
-/* bit 31-30 are port transceiver select */
-#define PORTSC_PTS_UTMI			(0x0<<30)
-#define PORTSC_PTS_ULPI			(0x2<<30)
-#define PORTSC_PTS_FSLS_SERIAL		(0x3<<30)
-#define PORTSC_PTS_BIT_POS		(30)
-
-#define PORTSC_W1C_BITS			\
-	(PORTSC_CONNECT_STATUS_CHANGE |	\
-	 PORTSC_PORT_EN_DIS_CHANGE    |	\
-	 PORTSC_OVER_CUURENT_CHG)
-
-/* OTG Status Control Register Bit Masks */
-#define OTGSC_CTRL_VBUS_DISCHARGE	(0x1<<0)
-#define OTGSC_CTRL_VBUS_CHARGE		(0x1<<1)
-#define OTGSC_CTRL_OTG_TERMINATION	(0x1<<3)
-#define OTGSC_CTRL_DATA_PULSING		(0x1<<4)
-#define OTGSC_CTRL_ID_PULL_EN		(0x1<<5)
-#define OTGSC_HA_DATA_PULSE		(0x1<<6)
-#define OTGSC_HA_BA			(0x1<<7)
-#define OTGSC_STS_USB_ID		(0x1<<8)
-#define OTGSC_STS_A_VBUS_VALID		(0x1<<9)
-#define OTGSC_STS_A_SESSION_VALID	(0x1<<10)
-#define OTGSC_STS_B_SESSION_VALID	(0x1<<11)
-#define OTGSC_STS_B_SESSION_END		(0x1<<12)
-#define OTGSC_STS_1MS_TOGGLE		(0x1<<13)
-#define OTGSC_STS_DATA_PULSING		(0x1<<14)
-#define OTGSC_INTSTS_USB_ID		(0x1<<16)
-#define OTGSC_INTSTS_A_VBUS_VALID	(0x1<<17)
-#define OTGSC_INTSTS_A_SESSION_VALID	(0x1<<18)
-#define OTGSC_INTSTS_B_SESSION_VALID	(0x1<<19)
-#define OTGSC_INTSTS_B_SESSION_END	(0x1<<20)
-#define OTGSC_INTSTS_1MS		(0x1<<21)
-#define OTGSC_INTSTS_DATA_PULSING	(0x1<<22)
-#define OTGSC_INTR_USB_ID_EN		(0x1<<24)
-#define OTGSC_INTR_A_VBUS_VALID_EN	(0x1<<25)
-#define OTGSC_INTR_A_SESSION_VALID_EN	(0x1<<26)
-#define OTGSC_INTR_B_SESSION_VALID_EN	(0x1<<27)
-#define OTGSC_INTR_B_SESSION_END_EN	(0x1<<28)
-#define OTGSC_INTR_1MS_TIMER_EN		(0x1<<29)
-#define OTGSC_INTR_DATA_PULSING_EN	(0x1<<30)
-#define OTGSC_INTSTS_MASK		(0x00ff0000)
-
-/* USB MODE Register Bit Masks */
-#define  USB_MODE_CTRL_MODE_IDLE	(0x0<<0)
-#define  USB_MODE_CTRL_MODE_DEVICE	(0x2<<0)
-#define  USB_MODE_CTRL_MODE_HOST	(0x3<<0)
-#define  USB_MODE_CTRL_MODE_RSV		(0x1<<0)
-#define  USB_MODE_SETUP_LOCK_OFF	(0x1<<3)
-#define  USB_MODE_STREAM_DISABLE	(0x1<<4)
-#define  USB_MODE_ES			(0x1<<2) /* Endian Select */
-
-/* control Register Bit Masks */
-#define  USB_CTRL_IOENB			(0x1<<2)
-#define  USB_CTRL_ULPI_INT0EN		(0x1<<0)
-
-/* BCSR5 */
-#define BCSR5_INT_USB			(0x02)
-
-/* USB module clk cfg */
-#define SCCR_OFFS			(0xA08)
-#define SCCR_USB_CLK_DISABLE		(0x00000000)	/* USB clk disable */
-#define SCCR_USB_MPHCM_11		(0x00c00000)
-#define SCCR_USB_MPHCM_01		(0x00400000)
-#define SCCR_USB_MPHCM_10		(0x00800000)
-#define SCCR_USB_DRCM_11		(0x00300000)
-#define SCCR_USB_DRCM_01		(0x00100000)
-#define SCCR_USB_DRCM_10		(0x00200000)
-
-#define SICRL_OFFS			(0x114)
-#define SICRL_USB0			(0x40000000)
-#define SICRL_USB1			(0x20000000)
-
-#define SICRH_OFFS			(0x118)
-#define SICRH_USB_UTMI			(0x00020000)
-
-/* OTG interrupt enable bit masks */
-#define  OTGSC_INTERRUPT_ENABLE_BITS_MASK  \
-	(OTGSC_INTR_USB_ID_EN            | \
-	OTGSC_INTR_1MS_TIMER_EN		 | \
-	OTGSC_INTR_A_VBUS_VALID_EN       | \
-	OTGSC_INTR_A_SESSION_VALID_EN    | \
-	OTGSC_INTR_B_SESSION_VALID_EN    | \
-	OTGSC_INTR_B_SESSION_END_EN      | \
-	OTGSC_INTR_DATA_PULSING_EN)
-
-/* OTG interrupt status bit masks */
-#define  OTGSC_INTERRUPT_STATUS_BITS_MASK  \
-	(OTGSC_INTSTS_USB_ID          |    \
-	OTGSC_INTR_1MS_TIMER_EN       |    \
-	OTGSC_INTSTS_A_VBUS_VALID     |    \
-	OTGSC_INTSTS_A_SESSION_VALID  |    \
-	OTGSC_INTSTS_B_SESSION_VALID  |    \
-	OTGSC_INTSTS_B_SESSION_END    |    \
-	OTGSC_INTSTS_DATA_PULSING)
-
-/*
- *  A-DEVICE timing  constants
- */
-
-/* Wait for VBUS Rise  */
-#define TA_WAIT_VRISE	(100)	/* a_wait_vrise 100 ms, section: 6.6.5.1 */
-
-/* Wait for B-Connect */
-#define TA_WAIT_BCON	(10000)  /* a_wait_bcon > 1 sec, section: 6.6.5.2
-				  * This is only used to get out of
-				  * OTG_STATE_A_WAIT_BCON state if there was
-				  * no connection for these many milliseconds
-				  */
-
-/* A-Idle to B-Disconnect */
-/* It is necessary for this timer to be more than 750 ms because of a bug in OPT
- * test 5.4 in which B OPT disconnects after 750 ms instead of 75ms as stated
- * in the test description
- */
-#define TA_AIDL_BDIS	(5000)	/* a_suspend minimum 200 ms, section: 6.6.5.3 */
-
-/* B-Idle to A-Disconnect */
-#define TA_BIDL_ADIS	(12)	/* 3 to 200 ms */
-
-/* B-device timing constants */
-
-
-/* Data-Line Pulse Time*/
-#define TB_DATA_PLS	(10)	/* b_srp_init,continue 5~10ms, section:5.3.3 */
-#define TB_DATA_PLS_MIN	(5)	/* minimum 5 ms */
-#define TB_DATA_PLS_MAX	(10)	/* maximum 10 ms */
-
-/* SRP Initiate Time  */
-#define TB_SRP_INIT	(100)	/* b_srp_init,maximum 100 ms, section:5.3.8 */
-
-/* SRP Fail Time  */
-#define TB_SRP_FAIL	(7000)	/* b_srp_init,Fail time 5~30s, section:6.8.2.2*/
-
-/* SRP result wait time */
-#define TB_SRP_WAIT	(60)
-
-/* VBus time */
-#define TB_VBUS_PLS	(30)	/* time to keep vbus pulsing asserted */
-
-/* Discharge time */
-/* This time should be less than 10ms. It varies from system to system. */
-#define TB_VBUS_DSCHRG	(8)
-
-/* A-SE0 to B-Reset  */
-#define TB_ASE0_BRST	(20)	/* b_wait_acon, mini 3.125 ms,section:6.8.2.4 */
-
-/* A bus suspend timer before we can switch to b_wait_aconn */
-#define TB_A_SUSPEND	(7)
-#define TB_BUS_RESUME	(12)
-
-/* SE0 Time Before SRP */
-#define TB_SE0_SRP	(2)	/* b_idle,minimum 2 ms, section:5.3.2 */
-
-#define SET_OTG_STATE(otg_ptr, newstate)	((otg_ptr)->state = newstate)
-
-struct usb_dr_mmap {
-	/* Capability register */
-	u8 res1[256];
-	u16 caplength;		/* Capability Register Length */
-	u16 hciversion;		/* Host Controller Interface Version */
-	u32 hcsparams;		/* Host Controller Structual Parameters */
-	u32 hccparams;		/* Host Controller Capability Parameters */
-	u8 res2[20];
-	u32 dciversion;		/* Device Controller Interface Version */
-	u32 dccparams;		/* Device Controller Capability Parameters */
-	u8 res3[24];
-	/* Operation register */
-	u32 usbcmd;		/* USB Command Register */
-	u32 usbsts;		/* USB Status Register */
-	u32 usbintr;		/* USB Interrupt Enable Register */
-	u32 frindex;		/* Frame Index Register */
-	u8 res4[4];
-	u32 deviceaddr;		/* Device Address */
-	u32 endpointlistaddr;	/* Endpoint List Address Register */
-	u8 res5[4];
-	u32 burstsize;		/* Master Interface Data Burst Size Register */
-	u32 txttfilltuning;	/* Transmit FIFO Tuning Controls Register */
-	u8 res6[8];
-	u32 ulpiview;		/* ULPI register access */
-	u8 res7[12];
-	u32 configflag;		/* Configure Flag Register */
-	u32 portsc;		/* Port 1 Status and Control Register */
-	u8 res8[28];
-	u32 otgsc;		/* On-The-Go Status and Control */
-	u32 usbmode;		/* USB Mode Register */
-	u32 endptsetupstat;	/* Endpoint Setup Status Register */
-	u32 endpointprime;	/* Endpoint Initialization Register */
-	u32 endptflush;		/* Endpoint Flush Register */
-	u32 endptstatus;	/* Endpoint Status Register */
-	u32 endptcomplete;	/* Endpoint Complete Register */
-	u32 endptctrl[6];	/* Endpoint Control Registers */
-	u8 res9[552];
-	u32 snoop1;
-	u32 snoop2;
-	u32 age_cnt_thresh;	/* Age Count Threshold Register */
-	u32 pri_ctrl;		/* Priority Control Register */
-	u32 si_ctrl;		/* System Interface Control Register */
-	u8 res10[236];
-	u32 control;		/* General Purpose Control Register */
-};
-
-struct fsl_otg_timer {
-	unsigned long expires;	/* Number of count increase to timeout */
-	unsigned long count;	/* Tick counter */
-	void (*function)(unsigned long);	/* Timeout function */
-	unsigned long data;	/* Data passed to function */
-	struct list_head list;
-};
-
-inline struct fsl_otg_timer *otg_timer_initializer
-(void (*function)(unsigned long), unsigned long expires, unsigned long data)
-{
-	struct fsl_otg_timer *timer;
-
-	timer = kmalloc(sizeof(struct fsl_otg_timer), GFP_KERNEL);
-	if (!timer)
-		return NULL;
-	timer->function = function;
-	timer->expires = expires;
-	timer->data = data;
-	return timer;
-}
-
-struct fsl_otg {
-	struct usb_phy phy;
-	struct otg_fsm fsm;
-	struct usb_dr_mmap *dr_mem_map;
-	struct delayed_work otg_event;
-
-	/* used for usb host */
-	struct work_struct work_wq;
-	u8	host_working;
-
-	int irq;
-};
-
-struct fsl_otg_config {
-	u8 otg_port;
-};
-
-/* For SRP and HNP handle */
-#define FSL_OTG_MAJOR		240
-#define FSL_OTG_NAME		"fsl-usb2-otg"
-/* Command to OTG driver ioctl */
-#define OTG_IOCTL_MAGIC		FSL_OTG_MAJOR
-/* if otg work as host, it should return 1, otherwise return 0 */
-#define GET_OTG_STATUS		_IOR(OTG_IOCTL_MAGIC, 1, int)
-#define SET_A_SUSPEND_REQ	_IOW(OTG_IOCTL_MAGIC, 2, int)
-#define SET_A_BUS_DROP		_IOW(OTG_IOCTL_MAGIC, 3, int)
-#define SET_A_BUS_REQ		_IOW(OTG_IOCTL_MAGIC, 4, int)
-#define SET_B_BUS_REQ		_IOW(OTG_IOCTL_MAGIC, 5, int)
-#define GET_A_SUSPEND_REQ	_IOR(OTG_IOCTL_MAGIC, 6, int)
-#define GET_A_BUS_DROP		_IOR(OTG_IOCTL_MAGIC, 7, int)
-#define GET_A_BUS_REQ		_IOR(OTG_IOCTL_MAGIC, 8, int)
-#define GET_B_BUS_REQ		_IOR(OTG_IOCTL_MAGIC, 9, int)
-
-void fsl_otg_add_timer(void *timer);
-void fsl_otg_del_timer(void *timer);
-void fsl_otg_pulse_vbus(void);
diff --git a/drivers/usb/otg/gpio_vbus.c b/drivers/usb/otg/gpio_vbus.c
deleted file mode 100644
index a7d4ac5..0000000
--- a/drivers/usb/otg/gpio_vbus.c
+++ /dev/null
@@ -1,416 +0,0 @@
-/*
- * gpio-vbus.c - simple GPIO VBUS sensing driver for B peripheral devices
- *
- * Copyright (c) 2008 Philipp Zabel <philipp.zabel@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/usb.h>
-#include <linux/workqueue.h>
-
-#include <linux/regulator/consumer.h>
-
-#include <linux/usb/gadget.h>
-#include <linux/usb/gpio_vbus.h>
-#include <linux/usb/otg.h>
-
-
-/*
- * A simple GPIO VBUS sensing driver for B peripheral only devices
- * with internal transceivers. It can control a D+ pullup GPIO and
- * a regulator to limit the current drawn from VBUS.
- *
- * Needs to be loaded before the UDC driver that will use it.
- */
-struct gpio_vbus_data {
-	struct usb_phy		phy;
-	struct device          *dev;
-	struct regulator       *vbus_draw;
-	int			vbus_draw_enabled;
-	unsigned		mA;
-	struct delayed_work	work;
-	int			vbus;
-	int			irq;
-};
-
-
-/*
- * This driver relies on "both edges" triggering.  VBUS has 100 msec to
- * stabilize, so the peripheral controller driver may need to cope with
- * some bouncing due to current surges (e.g. charging local capacitance)
- * and contact chatter.
- *
- * REVISIT in desperate straits, toggling between rising and falling
- * edges might be workable.
- */
-#define VBUS_IRQ_FLAGS \
-	(IRQF_SHARED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)
-
-
-/* interface to regulator framework */
-static void set_vbus_draw(struct gpio_vbus_data *gpio_vbus, unsigned mA)
-{
-	struct regulator *vbus_draw = gpio_vbus->vbus_draw;
-	int enabled;
-
-	if (!vbus_draw)
-		return;
-
-	enabled = gpio_vbus->vbus_draw_enabled;
-	if (mA) {
-		regulator_set_current_limit(vbus_draw, 0, 1000 * mA);
-		if (!enabled) {
-			regulator_enable(vbus_draw);
-			gpio_vbus->vbus_draw_enabled = 1;
-		}
-	} else {
-		if (enabled) {
-			regulator_disable(vbus_draw);
-			gpio_vbus->vbus_draw_enabled = 0;
-		}
-	}
-	gpio_vbus->mA = mA;
-}
-
-static int is_vbus_powered(struct gpio_vbus_mach_info *pdata)
-{
-	int vbus;
-
-	vbus = gpio_get_value(pdata->gpio_vbus);
-	if (pdata->gpio_vbus_inverted)
-		vbus = !vbus;
-
-	return vbus;
-}
-
-static void gpio_vbus_work(struct work_struct *work)
-{
-	struct gpio_vbus_data *gpio_vbus =
-		container_of(work, struct gpio_vbus_data, work.work);
-	struct gpio_vbus_mach_info *pdata = gpio_vbus->dev->platform_data;
-	int gpio, status, vbus;
-
-	if (!gpio_vbus->phy.otg->gadget)
-		return;
-
-	vbus = is_vbus_powered(pdata);
-	if ((vbus ^ gpio_vbus->vbus) == 0)
-		return;
-	gpio_vbus->vbus = vbus;
-
-	/* Peripheral controllers which manage the pullup themselves won't have
-	 * gpio_pullup configured here.  If it's configured here, we'll do what
-	 * isp1301_omap::b_peripheral() does and enable the pullup here... although
-	 * that may complicate usb_gadget_{,dis}connect() support.
-	 */
-	gpio = pdata->gpio_pullup;
-
-	if (vbus) {
-		status = USB_EVENT_VBUS;
-		gpio_vbus->phy.state = OTG_STATE_B_PERIPHERAL;
-		gpio_vbus->phy.last_event = status;
-		usb_gadget_vbus_connect(gpio_vbus->phy.otg->gadget);
-
-		/* drawing a "unit load" is *always* OK, except for OTG */
-		set_vbus_draw(gpio_vbus, 100);
-
-		/* optionally enable D+ pullup */
-		if (gpio_is_valid(gpio))
-			gpio_set_value(gpio, !pdata->gpio_pullup_inverted);
-
-		atomic_notifier_call_chain(&gpio_vbus->phy.notifier,
-					   status, gpio_vbus->phy.otg->gadget);
-	} else {
-		/* optionally disable D+ pullup */
-		if (gpio_is_valid(gpio))
-			gpio_set_value(gpio, pdata->gpio_pullup_inverted);
-
-		set_vbus_draw(gpio_vbus, 0);
-
-		usb_gadget_vbus_disconnect(gpio_vbus->phy.otg->gadget);
-		status = USB_EVENT_NONE;
-		gpio_vbus->phy.state = OTG_STATE_B_IDLE;
-		gpio_vbus->phy.last_event = status;
-
-		atomic_notifier_call_chain(&gpio_vbus->phy.notifier,
-					   status, gpio_vbus->phy.otg->gadget);
-	}
-}
-
-/* VBUS change IRQ handler */
-static irqreturn_t gpio_vbus_irq(int irq, void *data)
-{
-	struct platform_device *pdev = data;
-	struct gpio_vbus_mach_info *pdata = pdev->dev.platform_data;
-	struct gpio_vbus_data *gpio_vbus = platform_get_drvdata(pdev);
-	struct usb_otg *otg = gpio_vbus->phy.otg;
-
-	dev_dbg(&pdev->dev, "VBUS %s (gadget: %s)\n",
-		is_vbus_powered(pdata) ? "supplied" : "inactive",
-		otg->gadget ? otg->gadget->name : "none");
-
-	if (otg->gadget)
-		schedule_delayed_work(&gpio_vbus->work, msecs_to_jiffies(100));
-
-	return IRQ_HANDLED;
-}
-
-/* OTG transceiver interface */
-
-/* bind/unbind the peripheral controller */
-static int gpio_vbus_set_peripheral(struct usb_otg *otg,
-					struct usb_gadget *gadget)
-{
-	struct gpio_vbus_data *gpio_vbus;
-	struct gpio_vbus_mach_info *pdata;
-	struct platform_device *pdev;
-	int gpio;
-
-	gpio_vbus = container_of(otg->phy, struct gpio_vbus_data, phy);
-	pdev = to_platform_device(gpio_vbus->dev);
-	pdata = gpio_vbus->dev->platform_data;
-	gpio = pdata->gpio_pullup;
-
-	if (!gadget) {
-		dev_dbg(&pdev->dev, "unregistering gadget '%s'\n",
-			otg->gadget->name);
-
-		/* optionally disable D+ pullup */
-		if (gpio_is_valid(gpio))
-			gpio_set_value(gpio, pdata->gpio_pullup_inverted);
-
-		set_vbus_draw(gpio_vbus, 0);
-
-		usb_gadget_vbus_disconnect(otg->gadget);
-		otg->phy->state = OTG_STATE_UNDEFINED;
-
-		otg->gadget = NULL;
-		return 0;
-	}
-
-	otg->gadget = gadget;
-	dev_dbg(&pdev->dev, "registered gadget '%s'\n", gadget->name);
-
-	/* initialize connection state */
-	gpio_vbus->vbus = 0; /* start with disconnected */
-	gpio_vbus_irq(gpio_vbus->irq, pdev);
-	return 0;
-}
-
-/* effective for B devices, ignored for A-peripheral */
-static int gpio_vbus_set_power(struct usb_phy *phy, unsigned mA)
-{
-	struct gpio_vbus_data *gpio_vbus;
-
-	gpio_vbus = container_of(phy, struct gpio_vbus_data, phy);
-
-	if (phy->state == OTG_STATE_B_PERIPHERAL)
-		set_vbus_draw(gpio_vbus, mA);
-	return 0;
-}
-
-/* for non-OTG B devices: set/clear transceiver suspend mode */
-static int gpio_vbus_set_suspend(struct usb_phy *phy, int suspend)
-{
-	struct gpio_vbus_data *gpio_vbus;
-
-	gpio_vbus = container_of(phy, struct gpio_vbus_data, phy);
-
-	/* draw max 0 mA from vbus in suspend mode; or the previously
-	 * recorded amount of current if not suspended
-	 *
-	 * NOTE: high powered configs (mA > 100) may draw up to 2.5 mA
-	 * if they're wake-enabled ... we don't handle that yet.
-	 */
-	return gpio_vbus_set_power(phy, suspend ? 0 : gpio_vbus->mA);
-}
-
-/* platform driver interface */
-
-static int __init gpio_vbus_probe(struct platform_device *pdev)
-{
-	struct gpio_vbus_mach_info *pdata = pdev->dev.platform_data;
-	struct gpio_vbus_data *gpio_vbus;
-	struct resource *res;
-	int err, gpio, irq;
-	unsigned long irqflags;
-
-	if (!pdata || !gpio_is_valid(pdata->gpio_vbus))
-		return -EINVAL;
-	gpio = pdata->gpio_vbus;
-
-	gpio_vbus = kzalloc(sizeof(struct gpio_vbus_data), GFP_KERNEL);
-	if (!gpio_vbus)
-		return -ENOMEM;
-
-	gpio_vbus->phy.otg = kzalloc(sizeof(struct usb_otg), GFP_KERNEL);
-	if (!gpio_vbus->phy.otg) {
-		kfree(gpio_vbus);
-		return -ENOMEM;
-	}
-
-	platform_set_drvdata(pdev, gpio_vbus);
-	gpio_vbus->dev = &pdev->dev;
-	gpio_vbus->phy.label = "gpio-vbus";
-	gpio_vbus->phy.set_power = gpio_vbus_set_power;
-	gpio_vbus->phy.set_suspend = gpio_vbus_set_suspend;
-	gpio_vbus->phy.state = OTG_STATE_UNDEFINED;
-
-	gpio_vbus->phy.otg->phy = &gpio_vbus->phy;
-	gpio_vbus->phy.otg->set_peripheral = gpio_vbus_set_peripheral;
-
-	err = gpio_request(gpio, "vbus_detect");
-	if (err) {
-		dev_err(&pdev->dev, "can't request vbus gpio %d, err: %d\n",
-			gpio, err);
-		goto err_gpio;
-	}
-	gpio_direction_input(gpio);
-
-	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	if (res) {
-		irq = res->start;
-		irqflags = (res->flags & IRQF_TRIGGER_MASK) | IRQF_SHARED;
-	} else {
-		irq = gpio_to_irq(gpio);
-		irqflags = VBUS_IRQ_FLAGS;
-	}
-
-	gpio_vbus->irq = irq;
-
-	/* if data line pullup is in use, initialize it to "not pulling up" */
-	gpio = pdata->gpio_pullup;
-	if (gpio_is_valid(gpio)) {
-		err = gpio_request(gpio, "udc_pullup");
-		if (err) {
-			dev_err(&pdev->dev,
-				"can't request pullup gpio %d, err: %d\n",
-				gpio, err);
-			gpio_free(pdata->gpio_vbus);
-			goto err_gpio;
-		}
-		gpio_direction_output(gpio, pdata->gpio_pullup_inverted);
-	}
-
-	err = request_irq(irq, gpio_vbus_irq, irqflags, "vbus_detect", pdev);
-	if (err) {
-		dev_err(&pdev->dev, "can't request irq %i, err: %d\n",
-			irq, err);
-		goto err_irq;
-	}
-
-	ATOMIC_INIT_NOTIFIER_HEAD(&gpio_vbus->phy.notifier);
-
-	INIT_DELAYED_WORK(&gpio_vbus->work, gpio_vbus_work);
-
-	gpio_vbus->vbus_draw = regulator_get(&pdev->dev, "vbus_draw");
-	if (IS_ERR(gpio_vbus->vbus_draw)) {
-		dev_dbg(&pdev->dev, "can't get vbus_draw regulator, err: %ld\n",
-			PTR_ERR(gpio_vbus->vbus_draw));
-		gpio_vbus->vbus_draw = NULL;
-	}
-
-	/* only active when a gadget is registered */
-	err = usb_add_phy(&gpio_vbus->phy, USB_PHY_TYPE_USB2);
-	if (err) {
-		dev_err(&pdev->dev, "can't register transceiver, err: %d\n",
-			err);
-		goto err_otg;
-	}
-
-	device_init_wakeup(&pdev->dev, pdata->wakeup);
-
-	return 0;
-err_otg:
-	regulator_put(gpio_vbus->vbus_draw);
-	free_irq(irq, pdev);
-err_irq:
-	if (gpio_is_valid(pdata->gpio_pullup))
-		gpio_free(pdata->gpio_pullup);
-	gpio_free(pdata->gpio_vbus);
-err_gpio:
-	platform_set_drvdata(pdev, NULL);
-	kfree(gpio_vbus->phy.otg);
-	kfree(gpio_vbus);
-	return err;
-}
-
-static int __exit gpio_vbus_remove(struct platform_device *pdev)
-{
-	struct gpio_vbus_data *gpio_vbus = platform_get_drvdata(pdev);
-	struct gpio_vbus_mach_info *pdata = pdev->dev.platform_data;
-	int gpio = pdata->gpio_vbus;
-
-	device_init_wakeup(&pdev->dev, 0);
-	cancel_delayed_work_sync(&gpio_vbus->work);
-	regulator_put(gpio_vbus->vbus_draw);
-
-	usb_remove_phy(&gpio_vbus->phy);
-
-	free_irq(gpio_vbus->irq, pdev);
-	if (gpio_is_valid(pdata->gpio_pullup))
-		gpio_free(pdata->gpio_pullup);
-	gpio_free(gpio);
-	platform_set_drvdata(pdev, NULL);
-	kfree(gpio_vbus->phy.otg);
-	kfree(gpio_vbus);
-
-	return 0;
-}
-
-#ifdef CONFIG_PM
-static int gpio_vbus_pm_suspend(struct device *dev)
-{
-	struct gpio_vbus_data *gpio_vbus = dev_get_drvdata(dev);
-
-	if (device_may_wakeup(dev))
-		enable_irq_wake(gpio_vbus->irq);
-
-	return 0;
-}
-
-static int gpio_vbus_pm_resume(struct device *dev)
-{
-	struct gpio_vbus_data *gpio_vbus = dev_get_drvdata(dev);
-
-	if (device_may_wakeup(dev))
-		disable_irq_wake(gpio_vbus->irq);
-
-	return 0;
-}
-
-static const struct dev_pm_ops gpio_vbus_dev_pm_ops = {
-	.suspend	= gpio_vbus_pm_suspend,
-	.resume		= gpio_vbus_pm_resume,
-};
-#endif
-
-/* NOTE:  the gpio-vbus device may *NOT* be hotplugged */
-
-MODULE_ALIAS("platform:gpio-vbus");
-
-static struct platform_driver gpio_vbus_driver = {
-	.driver = {
-		.name  = "gpio-vbus",
-		.owner = THIS_MODULE,
-#ifdef CONFIG_PM
-		.pm = &gpio_vbus_dev_pm_ops,
-#endif
-	},
-	.remove  = __exit_p(gpio_vbus_remove),
-};
-
-module_platform_driver_probe(gpio_vbus_driver, gpio_vbus_probe);
-
-MODULE_DESCRIPTION("simple GPIO controlled OTG transceiver driver");
-MODULE_AUTHOR("Philipp Zabel");
-MODULE_LICENSE("GPL");
diff --git a/drivers/usb/otg/isp1301_omap.c b/drivers/usb/otg/isp1301_omap.c
deleted file mode 100644
index af9cb11..0000000
--- a/drivers/usb/otg/isp1301_omap.c
+++ /dev/null
@@ -1,1656 +0,0 @@
-/*
- * isp1301_omap - ISP 1301 USB transceiver, talking to OMAP OTG controller
- *
- * Copyright (C) 2004 Texas Instruments
- * Copyright (C) 2004 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/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-#include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
-#include <linux/usb.h>
-#include <linux/usb/otg.h>
-#include <linux/i2c.h>
-#include <linux/workqueue.h>
-
-#include <asm/irq.h>
-#include <asm/mach-types.h>
-
-#include <mach/mux.h>
-
-#include <mach/usb.h>
-
-#ifndef	DEBUG
-#undef	VERBOSE
-#endif
-
-
-#define	DRIVER_VERSION	"24 August 2004"
-#define	DRIVER_NAME	(isp1301_driver.driver.name)
-
-MODULE_DESCRIPTION("ISP1301 USB OTG Transceiver Driver");
-MODULE_LICENSE("GPL");
-
-struct isp1301 {
-	struct usb_phy		phy;
-	struct i2c_client	*client;
-	void			(*i2c_release)(struct device *dev);
-
-	int			irq_type;
-
-	u32			last_otg_ctrl;
-	unsigned		working:1;
-
-	struct timer_list	timer;
-
-	/* use keventd context to change the state for us */
-	struct work_struct	work;
-
-	unsigned long		todo;
-#		define WORK_UPDATE_ISP	0	/* update ISP from OTG */
-#		define WORK_UPDATE_OTG	1	/* update OTG from ISP */
-#		define WORK_HOST_RESUME	4	/* resume host */
-#		define WORK_TIMER	6	/* timer fired */
-#		define WORK_STOP	7	/* don't resubmit */
-};
-
-
-/* bits in OTG_CTRL */
-
-#define	OTG_XCEIV_OUTPUTS \
-	(OTG_ASESSVLD|OTG_BSESSEND|OTG_BSESSVLD|OTG_VBUSVLD|OTG_ID)
-#define	OTG_XCEIV_INPUTS \
-	(OTG_PULLDOWN|OTG_PULLUP|OTG_DRV_VBUS|OTG_PD_VBUS|OTG_PU_VBUS|OTG_PU_ID)
-#define	OTG_CTRL_BITS \
-	(OTG_A_BUSREQ|OTG_A_SETB_HNPEN|OTG_B_BUSREQ|OTG_B_HNPEN|OTG_BUSDROP)
-	/* and OTG_PULLUP is sometimes written */
-
-#define	OTG_CTRL_MASK	(OTG_DRIVER_SEL| \
-	OTG_XCEIV_OUTPUTS|OTG_XCEIV_INPUTS| \
-	OTG_CTRL_BITS)
-
-
-/*-------------------------------------------------------------------------*/
-
-/* board-specific PM hooks */
-
-#if defined(CONFIG_MACH_OMAP_H2) || defined(CONFIG_MACH_OMAP_H3)
-
-#if	defined(CONFIG_TPS65010) || defined(CONFIG_TPS65010_MODULE)
-
-#include <linux/i2c/tps65010.h>
-
-#else
-
-static inline int tps65010_set_vbus_draw(unsigned mA)
-{
-	pr_debug("tps65010: draw %d mA (STUB)\n", mA);
-	return 0;
-}
-
-#endif
-
-static void enable_vbus_draw(struct isp1301 *isp, unsigned mA)
-{
-	int status = tps65010_set_vbus_draw(mA);
-	if (status < 0)
-		pr_debug("  VBUS %d mA error %d\n", mA, status);
-}
-
-#else
-
-static void enable_vbus_draw(struct isp1301 *isp, unsigned mA)
-{
-	/* H4 controls this by DIP switch S2.4; no soft control.
-	 * ON means the charger is always enabled.  Leave it OFF
-	 * unless the OTG port is used only in B-peripheral mode.
-	 */
-}
-
-#endif
-
-static void enable_vbus_source(struct isp1301 *isp)
-{
-	/* this board won't supply more than 8mA vbus power.
-	 * some boards can switch a 100ma "unit load" (or more).
-	 */
-}
-
-
-/* products will deliver OTG messages with LEDs, GUI, etc */
-static inline void notresponding(struct isp1301 *isp)
-{
-	printk(KERN_NOTICE "OTG device not responding.\n");
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static struct i2c_driver isp1301_driver;
-
-/* smbus apis are used for portability */
-
-static inline u8
-isp1301_get_u8(struct isp1301 *isp, u8 reg)
-{
-	return i2c_smbus_read_byte_data(isp->client, reg + 0);
-}
-
-static inline int
-isp1301_get_u16(struct isp1301 *isp, u8 reg)
-{
-	return i2c_smbus_read_word_data(isp->client, reg);
-}
-
-static inline int
-isp1301_set_bits(struct isp1301 *isp, u8 reg, u8 bits)
-{
-	return i2c_smbus_write_byte_data(isp->client, reg + 0, bits);
-}
-
-static inline int
-isp1301_clear_bits(struct isp1301 *isp, u8 reg, u8 bits)
-{
-	return i2c_smbus_write_byte_data(isp->client, reg + 1, bits);
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* identification */
-#define	ISP1301_VENDOR_ID		0x00	/* u16 read */
-#define	ISP1301_PRODUCT_ID		0x02	/* u16 read */
-#define	ISP1301_BCD_DEVICE		0x14	/* u16 read */
-
-#define	I2C_VENDOR_ID_PHILIPS		0x04cc
-#define	I2C_PRODUCT_ID_PHILIPS_1301	0x1301
-
-/* operational registers */
-#define	ISP1301_MODE_CONTROL_1		0x04	/* u8 read, set, +1 clear */
-#	define	MC1_SPEED		(1 << 0)
-#	define	MC1_SUSPEND		(1 << 1)
-#	define	MC1_DAT_SE0		(1 << 2)
-#	define	MC1_TRANSPARENT		(1 << 3)
-#	define	MC1_BDIS_ACON_EN	(1 << 4)
-#	define	MC1_OE_INT_EN		(1 << 5)
-#	define	MC1_UART_EN		(1 << 6)
-#	define	MC1_MASK		0x7f
-#define	ISP1301_MODE_CONTROL_2		0x12	/* u8 read, set, +1 clear */
-#	define	MC2_GLOBAL_PWR_DN	(1 << 0)
-#	define	MC2_SPD_SUSP_CTRL	(1 << 1)
-#	define	MC2_BI_DI		(1 << 2)
-#	define	MC2_TRANSP_BDIR0	(1 << 3)
-#	define	MC2_TRANSP_BDIR1	(1 << 4)
-#	define	MC2_AUDIO_EN		(1 << 5)
-#	define	MC2_PSW_EN		(1 << 6)
-#	define	MC2_EN2V7		(1 << 7)
-#define	ISP1301_OTG_CONTROL_1		0x06	/* u8 read, set, +1 clear */
-#	define	OTG1_DP_PULLUP		(1 << 0)
-#	define	OTG1_DM_PULLUP		(1 << 1)
-#	define	OTG1_DP_PULLDOWN	(1 << 2)
-#	define	OTG1_DM_PULLDOWN	(1 << 3)
-#	define	OTG1_ID_PULLDOWN	(1 << 4)
-#	define	OTG1_VBUS_DRV		(1 << 5)
-#	define	OTG1_VBUS_DISCHRG	(1 << 6)
-#	define	OTG1_VBUS_CHRG		(1 << 7)
-#define	ISP1301_OTG_STATUS		0x10	/* u8 readonly */
-#	define	OTG_B_SESS_END		(1 << 6)
-#	define	OTG_B_SESS_VLD		(1 << 7)
-
-#define	ISP1301_INTERRUPT_SOURCE	0x08	/* u8 read */
-#define	ISP1301_INTERRUPT_LATCH		0x0A	/* u8 read, set, +1 clear */
-
-#define	ISP1301_INTERRUPT_FALLING	0x0C	/* u8 read, set, +1 clear */
-#define	ISP1301_INTERRUPT_RISING	0x0E	/* u8 read, set, +1 clear */
-
-/* same bitfields in all interrupt registers */
-#	define	INTR_VBUS_VLD		(1 << 0)
-#	define	INTR_SESS_VLD		(1 << 1)
-#	define	INTR_DP_HI		(1 << 2)
-#	define	INTR_ID_GND		(1 << 3)
-#	define	INTR_DM_HI		(1 << 4)
-#	define	INTR_ID_FLOAT		(1 << 5)
-#	define	INTR_BDIS_ACON		(1 << 6)
-#	define	INTR_CR_INT		(1 << 7)
-
-/*-------------------------------------------------------------------------*/
-
-static inline const char *state_name(struct isp1301 *isp)
-{
-	return otg_state_string(isp->phy.state);
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* NOTE:  some of this ISP1301 setup is specific to H2 boards;
- * not everything is guarded by board-specific checks, or even using
- * omap_usb_config data to deduce MC1_DAT_SE0 and MC2_BI_DI.
- *
- * ALSO:  this currently doesn't use ISP1301 low-power modes
- * while OTG is running.
- */
-
-static void power_down(struct isp1301 *isp)
-{
-	isp->phy.state = OTG_STATE_UNDEFINED;
-
-	// isp1301_set_bits(isp, ISP1301_MODE_CONTROL_2, MC2_GLOBAL_PWR_DN);
-	isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1, MC1_SUSPEND);
-
-	isp1301_clear_bits(isp, ISP1301_OTG_CONTROL_1, OTG1_ID_PULLDOWN);
-	isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_1, MC1_DAT_SE0);
-}
-
-static void power_up(struct isp1301 *isp)
-{
-	// isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_2, MC2_GLOBAL_PWR_DN);
-	isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_1, MC1_SUSPEND);
-
-	/* do this only when cpu is driving transceiver,
-	 * so host won't see a low speed device...
-	 */
-	isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1, MC1_DAT_SE0);
-}
-
-#define	NO_HOST_SUSPEND
-
-static int host_suspend(struct isp1301 *isp)
-{
-#ifdef	NO_HOST_SUSPEND
-	return 0;
-#else
-	struct device	*dev;
-
-	if (!isp->phy.otg->host)
-		return -ENODEV;
-
-	/* Currently ASSUMES only the OTG port matters;
-	 * other ports could be active...
-	 */
-	dev = isp->phy.otg->host->controller;
-	return dev->driver->suspend(dev, 3, 0);
-#endif
-}
-
-static int host_resume(struct isp1301 *isp)
-{
-#ifdef	NO_HOST_SUSPEND
-	return 0;
-#else
-	struct device	*dev;
-
-	if (!isp->phy.otg->host)
-		return -ENODEV;
-
-	dev = isp->phy.otg->host->controller;
-	return dev->driver->resume(dev, 0);
-#endif
-}
-
-static int gadget_suspend(struct isp1301 *isp)
-{
-	isp->phy.otg->gadget->b_hnp_enable = 0;
-	isp->phy.otg->gadget->a_hnp_support = 0;
-	isp->phy.otg->gadget->a_alt_hnp_support = 0;
-	return usb_gadget_vbus_disconnect(isp->phy.otg->gadget);
-}
-
-/*-------------------------------------------------------------------------*/
-
-#define	TIMER_MINUTES	10
-#define	TIMER_JIFFIES	(TIMER_MINUTES * 60 * HZ)
-
-/* Almost all our I2C messaging comes from a work queue's task context.
- * NOTE: guaranteeing certain response times might mean we shouldn't
- * share keventd's work queue; a realtime task might be safest.
- */
-static void isp1301_defer_work(struct isp1301 *isp, int work)
-{
-	int status;
-
-	if (isp && !test_and_set_bit(work, &isp->todo)) {
-		(void) get_device(&isp->client->dev);
-		status = schedule_work(&isp->work);
-		if (!status && !isp->working)
-			dev_vdbg(&isp->client->dev,
-				"work item %d may be lost\n", work);
-	}
-}
-
-/* called from irq handlers */
-static void a_idle(struct isp1301 *isp, const char *tag)
-{
-	u32 l;
-
-	if (isp->phy.state == OTG_STATE_A_IDLE)
-		return;
-
-	isp->phy.otg->default_a = 1;
-	if (isp->phy.otg->host) {
-		isp->phy.otg->host->is_b_host = 0;
-		host_suspend(isp);
-	}
-	if (isp->phy.otg->gadget) {
-		isp->phy.otg->gadget->is_a_peripheral = 1;
-		gadget_suspend(isp);
-	}
-	isp->phy.state = OTG_STATE_A_IDLE;
-	l = omap_readl(OTG_CTRL) & OTG_XCEIV_OUTPUTS;
-	omap_writel(l, OTG_CTRL);
-	isp->last_otg_ctrl = l;
-	pr_debug("  --> %s/%s\n", state_name(isp), tag);
-}
-
-/* called from irq handlers */
-static void b_idle(struct isp1301 *isp, const char *tag)
-{
-	u32 l;
-
-	if (isp->phy.state == OTG_STATE_B_IDLE)
-		return;
-
-	isp->phy.otg->default_a = 0;
-	if (isp->phy.otg->host) {
-		isp->phy.otg->host->is_b_host = 1;
-		host_suspend(isp);
-	}
-	if (isp->phy.otg->gadget) {
-		isp->phy.otg->gadget->is_a_peripheral = 0;
-		gadget_suspend(isp);
-	}
-	isp->phy.state = OTG_STATE_B_IDLE;
-	l = omap_readl(OTG_CTRL) & OTG_XCEIV_OUTPUTS;
-	omap_writel(l, OTG_CTRL);
-	isp->last_otg_ctrl = l;
-	pr_debug("  --> %s/%s\n", state_name(isp), tag);
-}
-
-static void
-dump_regs(struct isp1301 *isp, const char *label)
-{
-#ifdef	DEBUG
-	u8	ctrl = isp1301_get_u8(isp, ISP1301_OTG_CONTROL_1);
-	u8	status = isp1301_get_u8(isp, ISP1301_OTG_STATUS);
-	u8	src = isp1301_get_u8(isp, ISP1301_INTERRUPT_SOURCE);
-
-	pr_debug("otg: %06x, %s %s, otg/%02x stat/%02x.%02x\n",
-		omap_readl(OTG_CTRL), label, state_name(isp),
-		ctrl, status, src);
-	/* mode control and irq enables don't change much */
-#endif
-}
-
-/*-------------------------------------------------------------------------*/
-
-#ifdef	CONFIG_USB_OTG
-
-/*
- * The OMAP OTG controller handles most of the OTG state transitions.
- *
- * We translate isp1301 outputs (mostly voltage comparator status) into
- * OTG inputs; OTG outputs (mostly pullup/pulldown controls) and HNP state
- * flags into isp1301 inputs ... and infer state transitions.
- */
-
-#ifdef	VERBOSE
-
-static void check_state(struct isp1301 *isp, const char *tag)
-{
-	enum usb_otg_state	state = OTG_STATE_UNDEFINED;
-	u8			fsm = omap_readw(OTG_TEST) & 0x0ff;
-	unsigned		extra = 0;
-
-	switch (fsm) {
-
-	/* default-b */
-	case 0x0:
-		state = OTG_STATE_B_IDLE;
-		break;
-	case 0x3:
-	case 0x7:
-		extra = 1;
-	case 0x1:
-		state = OTG_STATE_B_PERIPHERAL;
-		break;
-	case 0x11:
-		state = OTG_STATE_B_SRP_INIT;
-		break;
-
-	/* extra dual-role default-b states */
-	case 0x12:
-	case 0x13:
-	case 0x16:
-		extra = 1;
-	case 0x17:
-		state = OTG_STATE_B_WAIT_ACON;
-		break;
-	case 0x34:
-		state = OTG_STATE_B_HOST;
-		break;
-
-	/* default-a */
-	case 0x36:
-		state = OTG_STATE_A_IDLE;
-		break;
-	case 0x3c:
-		state = OTG_STATE_A_WAIT_VFALL;
-		break;
-	case 0x7d:
-		state = OTG_STATE_A_VBUS_ERR;
-		break;
-	case 0x9e:
-	case 0x9f:
-		extra = 1;
-	case 0x89:
-		state = OTG_STATE_A_PERIPHERAL;
-		break;
-	case 0xb7:
-		state = OTG_STATE_A_WAIT_VRISE;
-		break;
-	case 0xb8:
-		state = OTG_STATE_A_WAIT_BCON;
-		break;
-	case 0xb9:
-		state = OTG_STATE_A_HOST;
-		break;
-	case 0xba:
-		state = OTG_STATE_A_SUSPEND;
-		break;
-	default:
-		break;
-	}
-	if (isp->phy.state == state && !extra)
-		return;
-	pr_debug("otg: %s FSM %s/%02x, %s, %06x\n", tag,
-		otg_state_string(state), fsm, state_name(isp),
-		omap_readl(OTG_CTRL));
-}
-
-#else
-
-static inline void check_state(struct isp1301 *isp, const char *tag) { }
-
-#endif
-
-/* outputs from ISP1301_INTERRUPT_SOURCE */
-static void update_otg1(struct isp1301 *isp, u8 int_src)
-{
-	u32	otg_ctrl;
-
-	otg_ctrl = omap_readl(OTG_CTRL) & OTG_CTRL_MASK;
-	otg_ctrl &= ~OTG_XCEIV_INPUTS;
-	otg_ctrl &= ~(OTG_ID|OTG_ASESSVLD|OTG_VBUSVLD);
-
-	if (int_src & INTR_SESS_VLD)
-		otg_ctrl |= OTG_ASESSVLD;
-	else if (isp->phy.state == OTG_STATE_A_WAIT_VFALL) {
-		a_idle(isp, "vfall");
-		otg_ctrl &= ~OTG_CTRL_BITS;
-	}
-	if (int_src & INTR_VBUS_VLD)
-		otg_ctrl |= OTG_VBUSVLD;
-	if (int_src & INTR_ID_GND) {		/* default-A */
-		if (isp->phy.state == OTG_STATE_B_IDLE
-				|| isp->phy.state
-					== OTG_STATE_UNDEFINED) {
-			a_idle(isp, "init");
-			return;
-		}
-	} else {				/* default-B */
-		otg_ctrl |= OTG_ID;
-		if (isp->phy.state == OTG_STATE_A_IDLE
-			|| isp->phy.state == OTG_STATE_UNDEFINED) {
-			b_idle(isp, "init");
-			return;
-		}
-	}
-	omap_writel(otg_ctrl, OTG_CTRL);
-}
-
-/* outputs from ISP1301_OTG_STATUS */
-static void update_otg2(struct isp1301 *isp, u8 otg_status)
-{
-	u32	otg_ctrl;
-
-	otg_ctrl = omap_readl(OTG_CTRL) & OTG_CTRL_MASK;
-	otg_ctrl &= ~OTG_XCEIV_INPUTS;
-	otg_ctrl &= ~(OTG_BSESSVLD | OTG_BSESSEND);
-	if (otg_status & OTG_B_SESS_VLD)
-		otg_ctrl |= OTG_BSESSVLD;
-	else if (otg_status & OTG_B_SESS_END)
-		otg_ctrl |= OTG_BSESSEND;
-	omap_writel(otg_ctrl, OTG_CTRL);
-}
-
-/* inputs going to ISP1301 */
-static void otg_update_isp(struct isp1301 *isp)
-{
-	u32	otg_ctrl, otg_change;
-	u8	set = OTG1_DM_PULLDOWN, clr = OTG1_DM_PULLUP;
-
-	otg_ctrl = omap_readl(OTG_CTRL);
-	otg_change = otg_ctrl ^ isp->last_otg_ctrl;
-	isp->last_otg_ctrl = otg_ctrl;
-	otg_ctrl = otg_ctrl & OTG_XCEIV_INPUTS;
-
-	switch (isp->phy.state) {
-	case OTG_STATE_B_IDLE:
-	case OTG_STATE_B_PERIPHERAL:
-	case OTG_STATE_B_SRP_INIT:
-		if (!(otg_ctrl & OTG_PULLUP)) {
-			// if (otg_ctrl & OTG_B_HNPEN) {
-			if (isp->phy.otg->gadget->b_hnp_enable) {
-				isp->phy.state = OTG_STATE_B_WAIT_ACON;
-				pr_debug("  --> b_wait_acon\n");
-			}
-			goto pulldown;
-		}
-pullup:
-		set |= OTG1_DP_PULLUP;
-		clr |= OTG1_DP_PULLDOWN;
-		break;
-	case OTG_STATE_A_SUSPEND:
-	case OTG_STATE_A_PERIPHERAL:
-		if (otg_ctrl & OTG_PULLUP)
-			goto pullup;
-		/* FALLTHROUGH */
-	// case OTG_STATE_B_WAIT_ACON:
-	default:
-pulldown:
-		set |= OTG1_DP_PULLDOWN;
-		clr |= OTG1_DP_PULLUP;
-		break;
-	}
-
-#	define toggle(OTG,ISP) do { \
-		if (otg_ctrl & OTG) set |= ISP; \
-		else clr |= ISP; \
-		} while (0)
-
-	if (!(isp->phy.otg->host))
-		otg_ctrl &= ~OTG_DRV_VBUS;
-
-	switch (isp->phy.state) {
-	case OTG_STATE_A_SUSPEND:
-		if (otg_ctrl & OTG_DRV_VBUS) {
-			set |= OTG1_VBUS_DRV;
-			break;
-		}
-		/* HNP failed for some reason (A_AIDL_BDIS timeout) */
-		notresponding(isp);
-
-		/* FALLTHROUGH */
-	case OTG_STATE_A_VBUS_ERR:
-		isp->phy.state = OTG_STATE_A_WAIT_VFALL;
-		pr_debug("  --> a_wait_vfall\n");
-		/* FALLTHROUGH */
-	case OTG_STATE_A_WAIT_VFALL:
-		/* FIXME usbcore thinks port power is still on ... */
-		clr |= OTG1_VBUS_DRV;
-		break;
-	case OTG_STATE_A_IDLE:
-		if (otg_ctrl & OTG_DRV_VBUS) {
-			isp->phy.state = OTG_STATE_A_WAIT_VRISE;
-			pr_debug("  --> a_wait_vrise\n");
-		}
-		/* FALLTHROUGH */
-	default:
-		toggle(OTG_DRV_VBUS, OTG1_VBUS_DRV);
-	}
-
-	toggle(OTG_PU_VBUS, OTG1_VBUS_CHRG);
-	toggle(OTG_PD_VBUS, OTG1_VBUS_DISCHRG);
-
-#	undef toggle
-
-	isp1301_set_bits(isp, ISP1301_OTG_CONTROL_1, set);
-	isp1301_clear_bits(isp, ISP1301_OTG_CONTROL_1, clr);
-
-	/* HNP switch to host or peripheral; and SRP */
-	if (otg_change & OTG_PULLUP) {
-		u32 l;
-
-		switch (isp->phy.state) {
-		case OTG_STATE_B_IDLE:
-			if (clr & OTG1_DP_PULLUP)
-				break;
-			isp->phy.state = OTG_STATE_B_PERIPHERAL;
-			pr_debug("  --> b_peripheral\n");
-			break;
-		case OTG_STATE_A_SUSPEND:
-			if (clr & OTG1_DP_PULLUP)
-				break;
-			isp->phy.state = OTG_STATE_A_PERIPHERAL;
-			pr_debug("  --> a_peripheral\n");
-			break;
-		default:
-			break;
-		}
-		l = omap_readl(OTG_CTRL);
-		l |= OTG_PULLUP;
-		omap_writel(l, OTG_CTRL);
-	}
-
-	check_state(isp, __func__);
-	dump_regs(isp, "otg->isp1301");
-}
-
-static irqreturn_t omap_otg_irq(int irq, void *_isp)
-{
-	u16		otg_irq = omap_readw(OTG_IRQ_SRC);
-	u32		otg_ctrl;
-	int		ret = IRQ_NONE;
-	struct isp1301	*isp = _isp;
-	struct usb_otg	*otg = isp->phy.otg;
-
-	/* 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);
-		ret = IRQ_HANDLED;
-
-	/* SRP to become b_peripheral failed */
-	} else if (otg_irq & B_SRP_TMROUT) {
-		pr_debug("otg: B_SRP_TIMEOUT, %06x\n", omap_readl(OTG_CTRL));
-		notresponding(isp);
-
-		/* gadget drivers that care should monitor all kinds of
-		 * remote wakeup (SRP, normal) using their own timer
-		 * to give "check cable and A-device" messages.
-		 */
-		if (isp->phy.state == OTG_STATE_B_SRP_INIT)
-			b_idle(isp, "srp_timeout");
-
-		omap_writew(B_SRP_TMROUT, OTG_IRQ_SRC);
-		ret = IRQ_HANDLED;
-
-	/* HNP to become b_host failed */
-	} else if (otg_irq & B_HNP_FAIL) {
-		pr_debug("otg: %s B_HNP_FAIL, %06x\n",
-				state_name(isp), omap_readl(OTG_CTRL));
-		notresponding(isp);
-
-		otg_ctrl = omap_readl(OTG_CTRL);
-		otg_ctrl |= OTG_BUSDROP;
-		otg_ctrl &= OTG_CTRL_MASK & ~OTG_XCEIV_INPUTS;
-		omap_writel(otg_ctrl, OTG_CTRL);
-
-		/* subset of b_peripheral()... */
-		isp->phy.state = OTG_STATE_B_PERIPHERAL;
-		pr_debug("  --> b_peripheral\n");
-
-		omap_writew(B_HNP_FAIL, OTG_IRQ_SRC);
-		ret = IRQ_HANDLED;
-
-	/* detect SRP from B-device ... */
-	} else if (otg_irq & A_SRP_DETECT) {
-		pr_debug("otg: %s SRP_DETECT, %06x\n",
-				state_name(isp), omap_readl(OTG_CTRL));
-
-		isp1301_defer_work(isp, WORK_UPDATE_OTG);
-		switch (isp->phy.state) {
-		case OTG_STATE_A_IDLE:
-			if (!otg->host)
-				break;
-			isp1301_defer_work(isp, WORK_HOST_RESUME);
-			otg_ctrl = omap_readl(OTG_CTRL);
-			otg_ctrl |= OTG_A_BUSREQ;
-			otg_ctrl &= ~(OTG_BUSDROP|OTG_B_BUSREQ)
-					& ~OTG_XCEIV_INPUTS
-					& OTG_CTRL_MASK;
-			omap_writel(otg_ctrl, OTG_CTRL);
-			break;
-		default:
-			break;
-		}
-
-		omap_writew(A_SRP_DETECT, OTG_IRQ_SRC);
-		ret = IRQ_HANDLED;
-
-	/* timer expired:  T(a_wait_bcon) and maybe T(a_wait_vrise)
-	 * we don't track them separately
-	 */
-	} else if (otg_irq & A_REQ_TMROUT) {
-		otg_ctrl = omap_readl(OTG_CTRL);
-		pr_info("otg: BCON_TMOUT from %s, %06x\n",
-				state_name(isp), otg_ctrl);
-		notresponding(isp);
-
-		otg_ctrl |= OTG_BUSDROP;
-		otg_ctrl &= ~OTG_A_BUSREQ & OTG_CTRL_MASK & ~OTG_XCEIV_INPUTS;
-		omap_writel(otg_ctrl, OTG_CTRL);
-		isp->phy.state = OTG_STATE_A_WAIT_VFALL;
-
-		omap_writew(A_REQ_TMROUT, OTG_IRQ_SRC);
-		ret = IRQ_HANDLED;
-
-	/* A-supplied voltage fell too low; overcurrent */
-	} else if (otg_irq & A_VBUS_ERR) {
-		otg_ctrl = omap_readl(OTG_CTRL);
-		printk(KERN_ERR "otg: %s, VBUS_ERR %04x ctrl %06x\n",
-			state_name(isp), otg_irq, otg_ctrl);
-
-		otg_ctrl |= OTG_BUSDROP;
-		otg_ctrl &= ~OTG_A_BUSREQ & OTG_CTRL_MASK & ~OTG_XCEIV_INPUTS;
-		omap_writel(otg_ctrl, OTG_CTRL);
-		isp->phy.state = OTG_STATE_A_VBUS_ERR;
-
-		omap_writew(A_VBUS_ERR, OTG_IRQ_SRC);
-		ret = IRQ_HANDLED;
-
-	/* switch driver; the transceiver code activates it,
-	 * ungating the udc clock or resuming OHCI.
-	 */
-	} else if (otg_irq & DRIVER_SWITCH) {
-		int	kick = 0;
-
-		otg_ctrl = omap_readl(OTG_CTRL);
-		printk(KERN_NOTICE "otg: %s, SWITCH to %s, ctrl %06x\n",
-				state_name(isp),
-				(otg_ctrl & OTG_DRIVER_SEL)
-					? "gadget" : "host",
-				otg_ctrl);
-		isp1301_defer_work(isp, WORK_UPDATE_ISP);
-
-		/* role is peripheral */
-		if (otg_ctrl & OTG_DRIVER_SEL) {
-			switch (isp->phy.state) {
-			case OTG_STATE_A_IDLE:
-				b_idle(isp, __func__);
-				break;
-			default:
-				break;
-			}
-			isp1301_defer_work(isp, WORK_UPDATE_ISP);
-
-		/* role is host */
-		} else {
-			if (!(otg_ctrl & OTG_ID)) {
-				otg_ctrl &= OTG_CTRL_MASK & ~OTG_XCEIV_INPUTS;
-				omap_writel(otg_ctrl | OTG_A_BUSREQ, OTG_CTRL);
-			}
-
-			if (otg->host) {
-				switch (isp->phy.state) {
-				case OTG_STATE_B_WAIT_ACON:
-					isp->phy.state = OTG_STATE_B_HOST;
-					pr_debug("  --> b_host\n");
-					kick = 1;
-					break;
-				case OTG_STATE_A_WAIT_BCON:
-					isp->phy.state = OTG_STATE_A_HOST;
-					pr_debug("  --> a_host\n");
-					break;
-				case OTG_STATE_A_PERIPHERAL:
-					isp->phy.state = OTG_STATE_A_WAIT_BCON;
-					pr_debug("  --> a_wait_bcon\n");
-					break;
-				default:
-					break;
-				}
-				isp1301_defer_work(isp, WORK_HOST_RESUME);
-			}
-		}
-
-		omap_writew(DRIVER_SWITCH, OTG_IRQ_SRC);
-		ret = IRQ_HANDLED;
-
-		if (kick)
-			usb_bus_start_enum(otg->host, otg->host->otg_port);
-	}
-
-	check_state(isp, __func__);
-	return ret;
-}
-
-static struct platform_device *otg_dev;
-
-static int isp1301_otg_init(struct isp1301 *isp)
-{
-	u32 l;
-
-	if (!otg_dev)
-		return -ENODEV;
-
-	dump_regs(isp, __func__);
-	/* some of these values are board-specific... */
-	l = omap_readl(OTG_SYSCON_2);
-	l |= OTG_EN
-		/* for B-device: */
-		| SRP_GPDATA		/* 9msec Bdev D+ pulse */
-		| SRP_GPDVBUS		/* discharge after VBUS pulse */
-		// | (3 << 24)		/* 2msec VBUS pulse */
-		/* for A-device: */
-		| (0 << 20)		/* 200ms nominal A_WAIT_VRISE timer */
-		| SRP_DPW		/* detect 167+ns SRP pulses */
-		| SRP_DATA | SRP_VBUS	/* accept both kinds of SRP pulse */
-		;
-	omap_writel(l, OTG_SYSCON_2);
-
-	update_otg1(isp, isp1301_get_u8(isp, ISP1301_INTERRUPT_SOURCE));
-	update_otg2(isp, isp1301_get_u8(isp, ISP1301_OTG_STATUS));
-
-	check_state(isp, __func__);
-	pr_debug("otg: %s, %s %06x\n",
-			state_name(isp), __func__, omap_readl(OTG_CTRL));
-
-	omap_writew(DRIVER_SWITCH | OPRT_CHG
-			| B_SRP_TMROUT | B_HNP_FAIL
-			| A_VBUS_ERR | A_SRP_DETECT | A_REQ_TMROUT, OTG_IRQ_EN);
-
-	l = omap_readl(OTG_SYSCON_2);
-	l |= OTG_EN;
-	omap_writel(l, OTG_SYSCON_2);
-
-	return 0;
-}
-
-static int otg_probe(struct platform_device *dev)
-{
-	// struct omap_usb_config *config = dev->platform_data;
-
-	otg_dev = dev;
-	return 0;
-}
-
-static int otg_remove(struct platform_device *dev)
-{
-	otg_dev = NULL;
-	return 0;
-}
-
-static struct platform_driver omap_otg_driver = {
-	.probe		= otg_probe,
-	.remove		= otg_remove,
-	.driver		= {
-		.owner	= THIS_MODULE,
-		.name	= "omap_otg",
-	},
-};
-
-static int otg_bind(struct isp1301 *isp)
-{
-	int	status;
-
-	if (otg_dev)
-		return -EBUSY;
-
-	status = platform_driver_register(&omap_otg_driver);
-	if (status < 0)
-		return status;
-
-	if (otg_dev)
-		status = request_irq(otg_dev->resource[1].start, omap_otg_irq,
-				0, DRIVER_NAME, isp);
-	else
-		status = -ENODEV;
-
-	if (status < 0)
-		platform_driver_unregister(&omap_otg_driver);
-	return status;
-}
-
-static void otg_unbind(struct isp1301 *isp)
-{
-	if (!otg_dev)
-		return;
-	free_irq(otg_dev->resource[1].start, isp);
-}
-
-#else
-
-/* OTG controller isn't clocked */
-
-#endif	/* CONFIG_USB_OTG */
-
-/*-------------------------------------------------------------------------*/
-
-static void b_peripheral(struct isp1301 *isp)
-{
-	u32 l;
-
-	l = omap_readl(OTG_CTRL) & OTG_XCEIV_OUTPUTS;
-	omap_writel(l, OTG_CTRL);
-
-	usb_gadget_vbus_connect(isp->phy.otg->gadget);
-
-#ifdef	CONFIG_USB_OTG
-	enable_vbus_draw(isp, 8);
-	otg_update_isp(isp);
-#else
-	enable_vbus_draw(isp, 100);
-	/* UDC driver just set OTG_BSESSVLD */
-	isp1301_set_bits(isp, ISP1301_OTG_CONTROL_1, OTG1_DP_PULLUP);
-	isp1301_clear_bits(isp, ISP1301_OTG_CONTROL_1, OTG1_DP_PULLDOWN);
-	isp->phy.state = OTG_STATE_B_PERIPHERAL;
-	pr_debug("  --> b_peripheral\n");
-	dump_regs(isp, "2periph");
-#endif
-}
-
-static void isp_update_otg(struct isp1301 *isp, u8 stat)
-{
-	struct usb_otg		*otg = isp->phy.otg;
-	u8			isp_stat, isp_bstat;
-	enum usb_otg_state	state = isp->phy.state;
-
-	if (stat & INTR_BDIS_ACON)
-		pr_debug("OTG:  BDIS_ACON, %s\n", state_name(isp));
-
-	/* start certain state transitions right away */
-	isp_stat = isp1301_get_u8(isp, ISP1301_INTERRUPT_SOURCE);
-	if (isp_stat & INTR_ID_GND) {
-		if (otg->default_a) {
-			switch (state) {
-			case OTG_STATE_B_IDLE:
-				a_idle(isp, "idle");
-				/* FALLTHROUGH */
-			case OTG_STATE_A_IDLE:
-				enable_vbus_source(isp);
-				/* FALLTHROUGH */
-			case OTG_STATE_A_WAIT_VRISE:
-				/* we skip over OTG_STATE_A_WAIT_BCON, since
-				 * the HC will transition to A_HOST (or
-				 * A_SUSPEND!) without our noticing except
-				 * when HNP is used.
-				 */
-				if (isp_stat & INTR_VBUS_VLD)
-					isp->phy.state = OTG_STATE_A_HOST;
-				break;
-			case OTG_STATE_A_WAIT_VFALL:
-				if (!(isp_stat & INTR_SESS_VLD))
-					a_idle(isp, "vfell");
-				break;
-			default:
-				if (!(isp_stat & INTR_VBUS_VLD))
-					isp->phy.state = OTG_STATE_A_VBUS_ERR;
-				break;
-			}
-			isp_bstat = isp1301_get_u8(isp, ISP1301_OTG_STATUS);
-		} else {
-			switch (state) {
-			case OTG_STATE_B_PERIPHERAL:
-			case OTG_STATE_B_HOST:
-			case OTG_STATE_B_WAIT_ACON:
-				usb_gadget_vbus_disconnect(otg->gadget);
-				break;
-			default:
-				break;
-			}
-			if (state != OTG_STATE_A_IDLE)
-				a_idle(isp, "id");
-			if (otg->host && state == OTG_STATE_A_IDLE)
-				isp1301_defer_work(isp, WORK_HOST_RESUME);
-			isp_bstat = 0;
-		}
-	} else {
-		u32 l;
-
-		/* if user unplugged mini-A end of cable,
-		 * don't bypass A_WAIT_VFALL.
-		 */
-		if (otg->default_a) {
-			switch (state) {
-			default:
-				isp->phy.state = OTG_STATE_A_WAIT_VFALL;
-				break;
-			case OTG_STATE_A_WAIT_VFALL:
-				state = OTG_STATE_A_IDLE;
-				/* khubd may take a while to notice and
-				 * handle this disconnect, so don't go
-				 * to B_IDLE quite yet.
-				 */
-				break;
-			case OTG_STATE_A_IDLE:
-				host_suspend(isp);
-				isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_1,
-						MC1_BDIS_ACON_EN);
-				isp->phy.state = OTG_STATE_B_IDLE;
-				l = omap_readl(OTG_CTRL) & OTG_CTRL_MASK;
-				l &= ~OTG_CTRL_BITS;
-				omap_writel(l, OTG_CTRL);
-				break;
-			case OTG_STATE_B_IDLE:
-				break;
-			}
-		}
-		isp_bstat = isp1301_get_u8(isp, ISP1301_OTG_STATUS);
-
-		switch (isp->phy.state) {
-		case OTG_STATE_B_PERIPHERAL:
-		case OTG_STATE_B_WAIT_ACON:
-		case OTG_STATE_B_HOST:
-			if (likely(isp_bstat & OTG_B_SESS_VLD))
-				break;
-			enable_vbus_draw(isp, 0);
-#ifndef	CONFIG_USB_OTG
-			/* UDC driver will clear OTG_BSESSVLD */
-			isp1301_set_bits(isp, ISP1301_OTG_CONTROL_1,
-						OTG1_DP_PULLDOWN);
-			isp1301_clear_bits(isp, ISP1301_OTG_CONTROL_1,
-						OTG1_DP_PULLUP);
-			dump_regs(isp, __func__);
-#endif
-			/* FALLTHROUGH */
-		case OTG_STATE_B_SRP_INIT:
-			b_idle(isp, __func__);
-			l = omap_readl(OTG_CTRL) & OTG_XCEIV_OUTPUTS;
-			omap_writel(l, OTG_CTRL);
-			/* FALLTHROUGH */
-		case OTG_STATE_B_IDLE:
-			if (otg->gadget && (isp_bstat & OTG_B_SESS_VLD)) {
-#ifdef	CONFIG_USB_OTG
-				update_otg1(isp, isp_stat);
-				update_otg2(isp, isp_bstat);
-#endif
-				b_peripheral(isp);
-			} else if (!(isp_stat & (INTR_VBUS_VLD|INTR_SESS_VLD)))
-				isp_bstat |= OTG_B_SESS_END;
-			break;
-		case OTG_STATE_A_WAIT_VFALL:
-			break;
-		default:
-			pr_debug("otg: unsupported b-device %s\n",
-				state_name(isp));
-			break;
-		}
-	}
-
-	if (state != isp->phy.state)
-		pr_debug("  isp, %s -> %s\n",
-				otg_state_string(state), state_name(isp));
-
-#ifdef	CONFIG_USB_OTG
-	/* update the OTG controller state to match the isp1301; may
-	 * trigger OPRT_CHG irqs for changes going to the isp1301.
-	 */
-	update_otg1(isp, isp_stat);
-	update_otg2(isp, isp_bstat);
-	check_state(isp, __func__);
-#endif
-
-	dump_regs(isp, "isp1301->otg");
-}
-
-/*-------------------------------------------------------------------------*/
-
-static u8 isp1301_clear_latch(struct isp1301 *isp)
-{
-	u8 latch = isp1301_get_u8(isp, ISP1301_INTERRUPT_LATCH);
-	isp1301_clear_bits(isp, ISP1301_INTERRUPT_LATCH, latch);
-	return latch;
-}
-
-static void
-isp1301_work(struct work_struct *work)
-{
-	struct isp1301	*isp = container_of(work, struct isp1301, work);
-	int		stop;
-
-	/* implicit lock:  we're the only task using this device */
-	isp->working = 1;
-	do {
-		stop = test_bit(WORK_STOP, &isp->todo);
-
-#ifdef	CONFIG_USB_OTG
-		/* transfer state from otg engine to isp1301 */
-		if (test_and_clear_bit(WORK_UPDATE_ISP, &isp->todo)) {
-			otg_update_isp(isp);
-			put_device(&isp->client->dev);
-		}
-#endif
-		/* transfer state from isp1301 to otg engine */
-		if (test_and_clear_bit(WORK_UPDATE_OTG, &isp->todo)) {
-			u8		stat = isp1301_clear_latch(isp);
-
-			isp_update_otg(isp, stat);
-			put_device(&isp->client->dev);
-		}
-
-		if (test_and_clear_bit(WORK_HOST_RESUME, &isp->todo)) {
-			u32	otg_ctrl;
-
-			/*
-			 * skip A_WAIT_VRISE; hc transitions invisibly
-			 * skip A_WAIT_BCON; same.
-			 */
-			switch (isp->phy.state) {
-			case OTG_STATE_A_WAIT_BCON:
-			case OTG_STATE_A_WAIT_VRISE:
-				isp->phy.state = OTG_STATE_A_HOST;
-				pr_debug("  --> a_host\n");
-				otg_ctrl = omap_readl(OTG_CTRL);
-				otg_ctrl |= OTG_A_BUSREQ;
-				otg_ctrl &= ~(OTG_BUSDROP|OTG_B_BUSREQ)
-						& OTG_CTRL_MASK;
-				omap_writel(otg_ctrl, OTG_CTRL);
-				break;
-			case OTG_STATE_B_WAIT_ACON:
-				isp->phy.state = OTG_STATE_B_HOST;
-				pr_debug("  --> b_host (acon)\n");
-				break;
-			case OTG_STATE_B_HOST:
-			case OTG_STATE_B_IDLE:
-			case OTG_STATE_A_IDLE:
-				break;
-			default:
-				pr_debug("  host resume in %s\n",
-						state_name(isp));
-			}
-			host_resume(isp);
-			// mdelay(10);
-			put_device(&isp->client->dev);
-		}
-
-		if (test_and_clear_bit(WORK_TIMER, &isp->todo)) {
-#ifdef	VERBOSE
-			dump_regs(isp, "timer");
-			if (!stop)
-				mod_timer(&isp->timer, jiffies + TIMER_JIFFIES);
-#endif
-			put_device(&isp->client->dev);
-		}
-
-		if (isp->todo)
-			dev_vdbg(&isp->client->dev,
-				"work done, todo = 0x%lx\n",
-				isp->todo);
-		if (stop) {
-			dev_dbg(&isp->client->dev, "stop\n");
-			break;
-		}
-	} while (isp->todo);
-	isp->working = 0;
-}
-
-static irqreturn_t isp1301_irq(int irq, void *isp)
-{
-	isp1301_defer_work(isp, WORK_UPDATE_OTG);
-	return IRQ_HANDLED;
-}
-
-static void isp1301_timer(unsigned long _isp)
-{
-	isp1301_defer_work((void *)_isp, WORK_TIMER);
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void isp1301_release(struct device *dev)
-{
-	struct isp1301	*isp;
-
-	isp = dev_get_drvdata(dev);
-
-	/* FIXME -- not with a "new style" driver, it doesn't!! */
-
-	/* ugly -- i2c hijacks our memory hook to wait_for_completion() */
-	if (isp->i2c_release)
-		isp->i2c_release(dev);
-	kfree(isp->phy.otg);
-	kfree (isp);
-}
-
-static struct isp1301 *the_transceiver;
-
-static int __exit isp1301_remove(struct i2c_client *i2c)
-{
-	struct isp1301	*isp;
-
-	isp = i2c_get_clientdata(i2c);
-
-	isp1301_clear_bits(isp, ISP1301_INTERRUPT_FALLING, ~0);
-	isp1301_clear_bits(isp, ISP1301_INTERRUPT_RISING, ~0);
-	free_irq(i2c->irq, isp);
-#ifdef	CONFIG_USB_OTG
-	otg_unbind(isp);
-#endif
-	if (machine_is_omap_h2())
-		gpio_free(2);
-
-	isp->timer.data = 0;
-	set_bit(WORK_STOP, &isp->todo);
-	del_timer_sync(&isp->timer);
-	flush_work(&isp->work);
-
-	put_device(&i2c->dev);
-	the_transceiver = NULL;
-
-	return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* NOTE:  three modes are possible here, only one of which
- * will be standards-conformant on any given system:
- *
- *  - OTG mode (dual-role), required if there's a Mini-AB connector
- *  - HOST mode, for when there's one or more A (host) connectors
- *  - DEVICE mode, for when there's a B/Mini-B (device) connector
- *
- * As a rule, you won't have an isp1301 chip unless it's there to
- * support the OTG mode.  Other modes help testing USB controllers
- * in isolation from (full) OTG support, or maybe so later board
- * revisions can help to support those feature.
- */
-
-#ifdef	CONFIG_USB_OTG
-
-static int isp1301_otg_enable(struct isp1301 *isp)
-{
-	power_up(isp);
-	isp1301_otg_init(isp);
-
-	/* NOTE:  since we don't change this, this provides
-	 * a few more interrupts than are strictly needed.
-	 */
-	isp1301_set_bits(isp, ISP1301_INTERRUPT_RISING,
-		INTR_VBUS_VLD | INTR_SESS_VLD | INTR_ID_GND);
-	isp1301_set_bits(isp, ISP1301_INTERRUPT_FALLING,
-		INTR_VBUS_VLD | INTR_SESS_VLD | INTR_ID_GND);
-
-	dev_info(&isp->client->dev, "ready for dual-role USB ...\n");
-
-	return 0;
-}
-
-#endif
-
-/* add or disable the host device+driver */
-static int
-isp1301_set_host(struct usb_otg *otg, struct usb_bus *host)
-{
-	struct isp1301	*isp = container_of(otg->phy, struct isp1301, phy);
-
-	if (!otg || isp != the_transceiver)
-		return -ENODEV;
-
-	if (!host) {
-		omap_writew(0, OTG_IRQ_EN);
-		power_down(isp);
-		otg->host = NULL;
-		return 0;
-	}
-
-#ifdef	CONFIG_USB_OTG
-	otg->host = host;
-	dev_dbg(&isp->client->dev, "registered host\n");
-	host_suspend(isp);
-	if (otg->gadget)
-		return isp1301_otg_enable(isp);
-	return 0;
-
-#elif	!defined(CONFIG_USB_GADGET_OMAP)
-	// FIXME update its refcount
-	otg->host = host;
-
-	power_up(isp);
-
-	if (machine_is_omap_h2())
-		isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1, MC1_DAT_SE0);
-
-	dev_info(&isp->client->dev, "A-Host sessions ok\n");
-	isp1301_set_bits(isp, ISP1301_INTERRUPT_RISING,
-		INTR_ID_GND);
-	isp1301_set_bits(isp, ISP1301_INTERRUPT_FALLING,
-		INTR_ID_GND);
-
-	/* If this has a Mini-AB connector, this mode is highly
-	 * nonstandard ... but can be handy for testing, especially with
-	 * the Mini-A end of an OTG cable.  (Or something nonstandard
-	 * like MiniB-to-StandardB, maybe built with a gender mender.)
-	 */
-	isp1301_set_bits(isp, ISP1301_OTG_CONTROL_1, OTG1_VBUS_DRV);
-
-	dump_regs(isp, __func__);
-
-	return 0;
-
-#else
-	dev_dbg(&isp->client->dev, "host sessions not allowed\n");
-	return -EINVAL;
-#endif
-
-}
-
-static int
-isp1301_set_peripheral(struct usb_otg *otg, struct usb_gadget *gadget)
-{
-	struct isp1301	*isp = container_of(otg->phy, struct isp1301, phy);
-
-	if (!otg || isp != the_transceiver)
-		return -ENODEV;
-
-	if (!gadget) {
-		omap_writew(0, OTG_IRQ_EN);
-		if (!otg->default_a)
-			enable_vbus_draw(isp, 0);
-		usb_gadget_vbus_disconnect(otg->gadget);
-		otg->gadget = NULL;
-		power_down(isp);
-		return 0;
-	}
-
-#ifdef	CONFIG_USB_OTG
-	otg->gadget = gadget;
-	dev_dbg(&isp->client->dev, "registered gadget\n");
-	/* gadget driver may be suspended until vbus_connect () */
-	if (otg->host)
-		return isp1301_otg_enable(isp);
-	return 0;
-
-#elif	!defined(CONFIG_USB_OHCI_HCD) && !defined(CONFIG_USB_OHCI_HCD_MODULE)
-	otg->gadget = gadget;
-	// FIXME update its refcount
-
-	{
-		u32 l;
-
-		l = omap_readl(OTG_CTRL) & OTG_CTRL_MASK;
-		l &= ~(OTG_XCEIV_OUTPUTS|OTG_CTRL_BITS);
-		l |= OTG_ID;
-		omap_writel(l, OTG_CTRL);
-	}
-
-	power_up(isp);
-	isp->phy.state = OTG_STATE_B_IDLE;
-
-	if (machine_is_omap_h2() || machine_is_omap_h3())
-		isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1, MC1_DAT_SE0);
-
-	isp1301_set_bits(isp, ISP1301_INTERRUPT_RISING,
-		INTR_SESS_VLD);
-	isp1301_set_bits(isp, ISP1301_INTERRUPT_FALLING,
-		INTR_VBUS_VLD);
-	dev_info(&isp->client->dev, "B-Peripheral sessions ok\n");
-	dump_regs(isp, __func__);
-
-	/* If this has a Mini-AB connector, this mode is highly
-	 * nonstandard ... but can be handy for testing, so long
-	 * as you don't plug a Mini-A cable into the jack.
-	 */
-	if (isp1301_get_u8(isp, ISP1301_INTERRUPT_SOURCE) & INTR_VBUS_VLD)
-		b_peripheral(isp);
-
-	return 0;
-
-#else
-	dev_dbg(&isp->client->dev, "peripheral sessions not allowed\n");
-	return -EINVAL;
-#endif
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static int
-isp1301_set_power(struct usb_phy *dev, unsigned mA)
-{
-	if (!the_transceiver)
-		return -ENODEV;
-	if (dev->state == OTG_STATE_B_PERIPHERAL)
-		enable_vbus_draw(the_transceiver, mA);
-	return 0;
-}
-
-static int
-isp1301_start_srp(struct usb_otg *otg)
-{
-	struct isp1301	*isp = container_of(otg->phy, struct isp1301, phy);
-	u32		otg_ctrl;
-
-	if (!otg || isp != the_transceiver
-			|| isp->phy.state != OTG_STATE_B_IDLE)
-		return -ENODEV;
-
-	otg_ctrl = omap_readl(OTG_CTRL);
-	if (!(otg_ctrl & OTG_BSESSEND))
-		return -EINVAL;
-
-	otg_ctrl |= OTG_B_BUSREQ;
-	otg_ctrl &= ~OTG_A_BUSREQ & OTG_CTRL_MASK;
-	omap_writel(otg_ctrl, OTG_CTRL);
-	isp->phy.state = OTG_STATE_B_SRP_INIT;
-
-	pr_debug("otg: SRP, %s ... %06x\n", state_name(isp),
-			omap_readl(OTG_CTRL));
-#ifdef	CONFIG_USB_OTG
-	check_state(isp, __func__);
-#endif
-	return 0;
-}
-
-static int
-isp1301_start_hnp(struct usb_otg *otg)
-{
-#ifdef	CONFIG_USB_OTG
-	struct isp1301	*isp = container_of(otg->phy, struct isp1301, phy);
-	u32 l;
-
-	if (!otg || isp != the_transceiver)
-		return -ENODEV;
-	if (otg->default_a && (otg->host == NULL || !otg->host->b_hnp_enable))
-		return -ENOTCONN;
-	if (!otg->default_a && (otg->gadget == NULL
-			|| !otg->gadget->b_hnp_enable))
-		return -ENOTCONN;
-
-	/* We want hardware to manage most HNP protocol timings.
-	 * So do this part as early as possible...
-	 */
-	switch (isp->phy.state) {
-	case OTG_STATE_B_HOST:
-		isp->phy.state = OTG_STATE_B_PERIPHERAL;
-		/* caller will suspend next */
-		break;
-	case OTG_STATE_A_HOST:
-#if 0
-		/* autoconnect mode avoids irq latency bugs */
-		isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1,
-				MC1_BDIS_ACON_EN);
-#endif
-		/* caller must suspend then clear A_BUSREQ */
-		usb_gadget_vbus_connect(otg->gadget);
-		l = omap_readl(OTG_CTRL);
-		l |= OTG_A_SETB_HNPEN;
-		omap_writel(l, OTG_CTRL);
-
-		break;
-	case OTG_STATE_A_PERIPHERAL:
-		/* initiated by B-Host suspend */
-		break;
-	default:
-		return -EILSEQ;
-	}
-	pr_debug("otg: HNP %s, %06x ...\n",
-		state_name(isp), omap_readl(OTG_CTRL));
-	check_state(isp, __func__);
-	return 0;
-#else
-	/* srp-only */
-	return -EINVAL;
-#endif
-}
-
-/*-------------------------------------------------------------------------*/
-
-static int
-isp1301_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
-{
-	int			status;
-	struct isp1301		*isp;
-
-	if (the_transceiver)
-		return 0;
-
-	isp = kzalloc(sizeof *isp, GFP_KERNEL);
-	if (!isp)
-		return 0;
-
-	isp->phy.otg = kzalloc(sizeof *isp->phy.otg, GFP_KERNEL);
-	if (!isp->phy.otg) {
-		kfree(isp);
-		return 0;
-	}
-
-	INIT_WORK(&isp->work, isp1301_work);
-	init_timer(&isp->timer);
-	isp->timer.function = isp1301_timer;
-	isp->timer.data = (unsigned long) isp;
-
-	i2c_set_clientdata(i2c, isp);
-	isp->client = i2c;
-
-	/* verify the chip (shouldn't be necessary) */
-	status = isp1301_get_u16(isp, ISP1301_VENDOR_ID);
-	if (status != I2C_VENDOR_ID_PHILIPS) {
-		dev_dbg(&i2c->dev, "not philips id: %d\n", status);
-		goto fail;
-	}
-	status = isp1301_get_u16(isp, ISP1301_PRODUCT_ID);
-	if (status != I2C_PRODUCT_ID_PHILIPS_1301) {
-		dev_dbg(&i2c->dev, "not isp1301, %d\n", status);
-		goto fail;
-	}
-	isp->i2c_release = i2c->dev.release;
-	i2c->dev.release = isp1301_release;
-
-	/* initial development used chiprev 2.00 */
-	status = i2c_smbus_read_word_data(i2c, ISP1301_BCD_DEVICE);
-	dev_info(&i2c->dev, "chiprev %x.%02x, driver " DRIVER_VERSION "\n",
-		status >> 8, status & 0xff);
-
-	/* make like power-on reset */
-	isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_1, MC1_MASK);
-
-	isp1301_set_bits(isp, ISP1301_MODE_CONTROL_2, MC2_BI_DI);
-	isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_2, ~MC2_BI_DI);
-
-	isp1301_set_bits(isp, ISP1301_OTG_CONTROL_1,
-				OTG1_DM_PULLDOWN | OTG1_DP_PULLDOWN);
-	isp1301_clear_bits(isp, ISP1301_OTG_CONTROL_1,
-				~(OTG1_DM_PULLDOWN | OTG1_DP_PULLDOWN));
-
-	isp1301_clear_bits(isp, ISP1301_INTERRUPT_LATCH, ~0);
-	isp1301_clear_bits(isp, ISP1301_INTERRUPT_FALLING, ~0);
-	isp1301_clear_bits(isp, ISP1301_INTERRUPT_RISING, ~0);
-
-#ifdef	CONFIG_USB_OTG
-	status = otg_bind(isp);
-	if (status < 0) {
-		dev_dbg(&i2c->dev, "can't bind OTG\n");
-		goto fail;
-	}
-#endif
-
-	if (machine_is_omap_h2()) {
-		/* full speed signaling by default */
-		isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1,
-			MC1_SPEED);
-		isp1301_set_bits(isp, ISP1301_MODE_CONTROL_2,
-			MC2_SPD_SUSP_CTRL);
-
-		/* IRQ wired at M14 */
-		omap_cfg_reg(M14_1510_GPIO2);
-		if (gpio_request(2, "isp1301") == 0)
-			gpio_direction_input(2);
-		isp->irq_type = IRQF_TRIGGER_FALLING;
-	}
-
-	status = request_irq(i2c->irq, isp1301_irq,
-			isp->irq_type, DRIVER_NAME, isp);
-	if (status < 0) {
-		dev_dbg(&i2c->dev, "can't get IRQ %d, err %d\n",
-				i2c->irq, status);
-		goto fail;
-	}
-
-	isp->phy.dev = &i2c->dev;
-	isp->phy.label = DRIVER_NAME;
-	isp->phy.set_power = isp1301_set_power,
-
-	isp->phy.otg->phy = &isp->phy;
-	isp->phy.otg->set_host = isp1301_set_host,
-	isp->phy.otg->set_peripheral = isp1301_set_peripheral,
-	isp->phy.otg->start_srp = isp1301_start_srp,
-	isp->phy.otg->start_hnp = isp1301_start_hnp,
-
-	enable_vbus_draw(isp, 0);
-	power_down(isp);
-	the_transceiver = isp;
-
-#ifdef	CONFIG_USB_OTG
-	update_otg1(isp, isp1301_get_u8(isp, ISP1301_INTERRUPT_SOURCE));
-	update_otg2(isp, isp1301_get_u8(isp, ISP1301_OTG_STATUS));
-#endif
-
-	dump_regs(isp, __func__);
-
-#ifdef	VERBOSE
-	mod_timer(&isp->timer, jiffies + TIMER_JIFFIES);
-	dev_dbg(&i2c->dev, "scheduled timer, %d min\n", TIMER_MINUTES);
-#endif
-
-	status = usb_add_phy(&isp->phy, USB_PHY_TYPE_USB2);
-	if (status < 0)
-		dev_err(&i2c->dev, "can't register transceiver, %d\n",
-			status);
-
-	return 0;
-
-fail:
-	kfree(isp->phy.otg);
-	kfree(isp);
-	return -ENODEV;
-}
-
-static const struct i2c_device_id isp1301_id[] = {
-	{ "isp1301_omap", 0 },
-	{ }
-};
-MODULE_DEVICE_TABLE(i2c, isp1301_id);
-
-static struct i2c_driver isp1301_driver = {
-	.driver = {
-		.name	= "isp1301_omap",
-	},
-	.probe		= isp1301_probe,
-	.remove		= __exit_p(isp1301_remove),
-	.id_table	= isp1301_id,
-};
-
-/*-------------------------------------------------------------------------*/
-
-static int __init isp_init(void)
-{
-	return i2c_add_driver(&isp1301_driver);
-}
-subsys_initcall(isp_init);
-
-static void __exit isp_exit(void)
-{
-	if (the_transceiver)
-		usb_remove_phy(&the_transceiver->phy);
-	i2c_del_driver(&isp1301_driver);
-}
-module_exit(isp_exit);
-
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
deleted file mode 100644
index 749fbf4..0000000
--- a/drivers/usb/otg/msm_otg.c
+++ /dev/null
@@ -1,1762 +0,0 @@
-/* Copyright (c) 2009-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.
- *
- */
-
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/err.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/ioport.h>
-#include <linux/uaccess.h>
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-#include <linux/pm_runtime.h>
-
-#include <linux/usb.h>
-#include <linux/usb/otg.h>
-#include <linux/usb/ulpi.h>
-#include <linux/usb/gadget.h>
-#include <linux/usb/hcd.h>
-#include <linux/usb/msm_hsusb.h>
-#include <linux/usb/msm_hsusb_hw.h>
-#include <linux/regulator/consumer.h>
-
-#include <mach/clk.h>
-
-#define MSM_USB_BASE	(motg->regs)
-#define DRIVER_NAME	"msm_otg"
-
-#define ULPI_IO_TIMEOUT_USEC	(10 * 1000)
-
-#define USB_PHY_3P3_VOL_MIN	3050000 /* uV */
-#define USB_PHY_3P3_VOL_MAX	3300000 /* uV */
-#define USB_PHY_3P3_HPM_LOAD	50000	/* uA */
-#define USB_PHY_3P3_LPM_LOAD	4000	/* uA */
-
-#define USB_PHY_1P8_VOL_MIN	1800000 /* uV */
-#define USB_PHY_1P8_VOL_MAX	1800000 /* uV */
-#define USB_PHY_1P8_HPM_LOAD	50000	/* uA */
-#define USB_PHY_1P8_LPM_LOAD	4000	/* uA */
-
-#define USB_PHY_VDD_DIG_VOL_MIN	1000000 /* uV */
-#define USB_PHY_VDD_DIG_VOL_MAX	1320000 /* uV */
-
-static struct regulator *hsusb_3p3;
-static struct regulator *hsusb_1p8;
-static struct regulator *hsusb_vddcx;
-
-static int msm_hsusb_init_vddcx(struct msm_otg *motg, int init)
-{
-	int ret = 0;
-
-	if (init) {
-		hsusb_vddcx = regulator_get(motg->phy.dev, "HSUSB_VDDCX");
-		if (IS_ERR(hsusb_vddcx)) {
-			dev_err(motg->phy.dev, "unable to get hsusb vddcx\n");
-			return PTR_ERR(hsusb_vddcx);
-		}
-
-		ret = regulator_set_voltage(hsusb_vddcx,
-				USB_PHY_VDD_DIG_VOL_MIN,
-				USB_PHY_VDD_DIG_VOL_MAX);
-		if (ret) {
-			dev_err(motg->phy.dev, "unable to set the voltage "
-					"for hsusb vddcx\n");
-			regulator_put(hsusb_vddcx);
-			return ret;
-		}
-
-		ret = regulator_enable(hsusb_vddcx);
-		if (ret) {
-			dev_err(motg->phy.dev, "unable to enable hsusb vddcx\n");
-			regulator_put(hsusb_vddcx);
-		}
-	} else {
-		ret = regulator_set_voltage(hsusb_vddcx, 0,
-			USB_PHY_VDD_DIG_VOL_MAX);
-		if (ret)
-			dev_err(motg->phy.dev, "unable to set the voltage "
-					"for hsusb vddcx\n");
-		ret = regulator_disable(hsusb_vddcx);
-		if (ret)
-			dev_err(motg->phy.dev, "unable to disable hsusb vddcx\n");
-
-		regulator_put(hsusb_vddcx);
-	}
-
-	return ret;
-}
-
-static int msm_hsusb_ldo_init(struct msm_otg *motg, int init)
-{
-	int rc = 0;
-
-	if (init) {
-		hsusb_3p3 = regulator_get(motg->phy.dev, "HSUSB_3p3");
-		if (IS_ERR(hsusb_3p3)) {
-			dev_err(motg->phy.dev, "unable to get hsusb 3p3\n");
-			return PTR_ERR(hsusb_3p3);
-		}
-
-		rc = regulator_set_voltage(hsusb_3p3, USB_PHY_3P3_VOL_MIN,
-				USB_PHY_3P3_VOL_MAX);
-		if (rc) {
-			dev_err(motg->phy.dev, "unable to set voltage level "
-					"for hsusb 3p3\n");
-			goto put_3p3;
-		}
-		rc = regulator_enable(hsusb_3p3);
-		if (rc) {
-			dev_err(motg->phy.dev, "unable to enable the hsusb 3p3\n");
-			goto put_3p3;
-		}
-		hsusb_1p8 = regulator_get(motg->phy.dev, "HSUSB_1p8");
-		if (IS_ERR(hsusb_1p8)) {
-			dev_err(motg->phy.dev, "unable to get hsusb 1p8\n");
-			rc = PTR_ERR(hsusb_1p8);
-			goto disable_3p3;
-		}
-		rc = regulator_set_voltage(hsusb_1p8, USB_PHY_1P8_VOL_MIN,
-				USB_PHY_1P8_VOL_MAX);
-		if (rc) {
-			dev_err(motg->phy.dev, "unable to set voltage level "
-					"for hsusb 1p8\n");
-			goto put_1p8;
-		}
-		rc = regulator_enable(hsusb_1p8);
-		if (rc) {
-			dev_err(motg->phy.dev, "unable to enable the hsusb 1p8\n");
-			goto put_1p8;
-		}
-
-		return 0;
-	}
-
-	regulator_disable(hsusb_1p8);
-put_1p8:
-	regulator_put(hsusb_1p8);
-disable_3p3:
-	regulator_disable(hsusb_3p3);
-put_3p3:
-	regulator_put(hsusb_3p3);
-	return rc;
-}
-
-#ifdef CONFIG_PM_SLEEP
-#define USB_PHY_SUSP_DIG_VOL  500000
-static int msm_hsusb_config_vddcx(int high)
-{
-	int max_vol = USB_PHY_VDD_DIG_VOL_MAX;
-	int min_vol;
-	int ret;
-
-	if (high)
-		min_vol = USB_PHY_VDD_DIG_VOL_MIN;
-	else
-		min_vol = USB_PHY_SUSP_DIG_VOL;
-
-	ret = regulator_set_voltage(hsusb_vddcx, min_vol, max_vol);
-	if (ret) {
-		pr_err("%s: unable to set the voltage for regulator "
-			"HSUSB_VDDCX\n", __func__);
-		return ret;
-	}
-
-	pr_debug("%s: min_vol:%d max_vol:%d\n", __func__, min_vol, max_vol);
-
-	return ret;
-}
-#endif
-
-static int msm_hsusb_ldo_set_mode(int on)
-{
-	int ret = 0;
-
-	if (!hsusb_1p8 || IS_ERR(hsusb_1p8)) {
-		pr_err("%s: HSUSB_1p8 is not initialized\n", __func__);
-		return -ENODEV;
-	}
-
-	if (!hsusb_3p3 || IS_ERR(hsusb_3p3)) {
-		pr_err("%s: HSUSB_3p3 is not initialized\n", __func__);
-		return -ENODEV;
-	}
-
-	if (on) {
-		ret = regulator_set_optimum_mode(hsusb_1p8,
-				USB_PHY_1P8_HPM_LOAD);
-		if (ret < 0) {
-			pr_err("%s: Unable to set HPM of the regulator "
-				"HSUSB_1p8\n", __func__);
-			return ret;
-		}
-		ret = regulator_set_optimum_mode(hsusb_3p3,
-				USB_PHY_3P3_HPM_LOAD);
-		if (ret < 0) {
-			pr_err("%s: Unable to set HPM of the regulator "
-				"HSUSB_3p3\n", __func__);
-			regulator_set_optimum_mode(hsusb_1p8,
-				USB_PHY_1P8_LPM_LOAD);
-			return ret;
-		}
-	} else {
-		ret = regulator_set_optimum_mode(hsusb_1p8,
-				USB_PHY_1P8_LPM_LOAD);
-		if (ret < 0)
-			pr_err("%s: Unable to set LPM of the regulator "
-				"HSUSB_1p8\n", __func__);
-		ret = regulator_set_optimum_mode(hsusb_3p3,
-				USB_PHY_3P3_LPM_LOAD);
-		if (ret < 0)
-			pr_err("%s: Unable to set LPM of the regulator "
-				"HSUSB_3p3\n", __func__);
-	}
-
-	pr_debug("reg (%s)\n", on ? "HPM" : "LPM");
-	return ret < 0 ? ret : 0;
-}
-
-static int ulpi_read(struct usb_phy *phy, u32 reg)
-{
-	struct msm_otg *motg = container_of(phy, struct msm_otg, phy);
-	int cnt = 0;
-
-	/* initiate read operation */
-	writel(ULPI_RUN | ULPI_READ | ULPI_ADDR(reg),
-	       USB_ULPI_VIEWPORT);
-
-	/* wait for completion */
-	while (cnt < ULPI_IO_TIMEOUT_USEC) {
-		if (!(readl(USB_ULPI_VIEWPORT) & ULPI_RUN))
-			break;
-		udelay(1);
-		cnt++;
-	}
-
-	if (cnt >= ULPI_IO_TIMEOUT_USEC) {
-		dev_err(phy->dev, "ulpi_read: timeout %08x\n",
-			readl(USB_ULPI_VIEWPORT));
-		return -ETIMEDOUT;
-	}
-	return ULPI_DATA_READ(readl(USB_ULPI_VIEWPORT));
-}
-
-static int ulpi_write(struct usb_phy *phy, u32 val, u32 reg)
-{
-	struct msm_otg *motg = container_of(phy, struct msm_otg, phy);
-	int cnt = 0;
-
-	/* initiate write operation */
-	writel(ULPI_RUN | ULPI_WRITE |
-	       ULPI_ADDR(reg) | ULPI_DATA(val),
-	       USB_ULPI_VIEWPORT);
-
-	/* wait for completion */
-	while (cnt < ULPI_IO_TIMEOUT_USEC) {
-		if (!(readl(USB_ULPI_VIEWPORT) & ULPI_RUN))
-			break;
-		udelay(1);
-		cnt++;
-	}
-
-	if (cnt >= ULPI_IO_TIMEOUT_USEC) {
-		dev_err(phy->dev, "ulpi_write: timeout\n");
-		return -ETIMEDOUT;
-	}
-	return 0;
-}
-
-static struct usb_phy_io_ops msm_otg_io_ops = {
-	.read = ulpi_read,
-	.write = ulpi_write,
-};
-
-static void ulpi_init(struct msm_otg *motg)
-{
-	struct msm_otg_platform_data *pdata = motg->pdata;
-	int *seq = pdata->phy_init_seq;
-
-	if (!seq)
-		return;
-
-	while (seq[0] >= 0) {
-		dev_vdbg(motg->phy.dev, "ulpi: write 0x%02x to 0x%02x\n",
-				seq[0], seq[1]);
-		ulpi_write(&motg->phy, seq[0], seq[1]);
-		seq += 2;
-	}
-}
-
-static int msm_otg_link_clk_reset(struct msm_otg *motg, bool assert)
-{
-	int ret;
-
-	if (assert) {
-		ret = clk_reset(motg->clk, CLK_RESET_ASSERT);
-		if (ret)
-			dev_err(motg->phy.dev, "usb hs_clk assert failed\n");
-	} else {
-		ret = clk_reset(motg->clk, CLK_RESET_DEASSERT);
-		if (ret)
-			dev_err(motg->phy.dev, "usb hs_clk deassert failed\n");
-	}
-	return ret;
-}
-
-static int msm_otg_phy_clk_reset(struct msm_otg *motg)
-{
-	int ret;
-
-	ret = clk_reset(motg->phy_reset_clk, CLK_RESET_ASSERT);
-	if (ret) {
-		dev_err(motg->phy.dev, "usb phy clk assert failed\n");
-		return ret;
-	}
-	usleep_range(10000, 12000);
-	ret = clk_reset(motg->phy_reset_clk, CLK_RESET_DEASSERT);
-	if (ret)
-		dev_err(motg->phy.dev, "usb phy clk deassert failed\n");
-	return ret;
-}
-
-static int msm_otg_phy_reset(struct msm_otg *motg)
-{
-	u32 val;
-	int ret;
-	int retries;
-
-	ret = msm_otg_link_clk_reset(motg, 1);
-	if (ret)
-		return ret;
-	ret = msm_otg_phy_clk_reset(motg);
-	if (ret)
-		return ret;
-	ret = msm_otg_link_clk_reset(motg, 0);
-	if (ret)
-		return ret;
-
-	val = readl(USB_PORTSC) & ~PORTSC_PTS_MASK;
-	writel(val | PORTSC_PTS_ULPI, USB_PORTSC);
-
-	for (retries = 3; retries > 0; retries--) {
-		ret = ulpi_write(&motg->phy, ULPI_FUNC_CTRL_SUSPENDM,
-				ULPI_CLR(ULPI_FUNC_CTRL));
-		if (!ret)
-			break;
-		ret = msm_otg_phy_clk_reset(motg);
-		if (ret)
-			return ret;
-	}
-	if (!retries)
-		return -ETIMEDOUT;
-
-	/* This reset calibrates the phy, if the above write succeeded */
-	ret = msm_otg_phy_clk_reset(motg);
-	if (ret)
-		return ret;
-
-	for (retries = 3; retries > 0; retries--) {
-		ret = ulpi_read(&motg->phy, ULPI_DEBUG);
-		if (ret != -ETIMEDOUT)
-			break;
-		ret = msm_otg_phy_clk_reset(motg);
-		if (ret)
-			return ret;
-	}
-	if (!retries)
-		return -ETIMEDOUT;
-
-	dev_info(motg->phy.dev, "phy_reset: success\n");
-	return 0;
-}
-
-#define LINK_RESET_TIMEOUT_USEC		(250 * 1000)
-static int msm_otg_reset(struct usb_phy *phy)
-{
-	struct msm_otg *motg = container_of(phy, struct msm_otg, phy);
-	struct msm_otg_platform_data *pdata = motg->pdata;
-	int cnt = 0;
-	int ret;
-	u32 val = 0;
-	u32 ulpi_val = 0;
-
-	ret = msm_otg_phy_reset(motg);
-	if (ret) {
-		dev_err(phy->dev, "phy_reset failed\n");
-		return ret;
-	}
-
-	ulpi_init(motg);
-
-	writel(USBCMD_RESET, USB_USBCMD);
-	while (cnt < LINK_RESET_TIMEOUT_USEC) {
-		if (!(readl(USB_USBCMD) & USBCMD_RESET))
-			break;
-		udelay(1);
-		cnt++;
-	}
-	if (cnt >= LINK_RESET_TIMEOUT_USEC)
-		return -ETIMEDOUT;
-
-	/* select ULPI phy */
-	writel(0x80000000, USB_PORTSC);
-
-	msleep(100);
-
-	writel(0x0, USB_AHBBURST);
-	writel(0x00, USB_AHBMODE);
-
-	if (pdata->otg_control == OTG_PHY_CONTROL) {
-		val = readl(USB_OTGSC);
-		if (pdata->mode == USB_OTG) {
-			ulpi_val = ULPI_INT_IDGRD | ULPI_INT_SESS_VALID;
-			val |= OTGSC_IDIE | OTGSC_BSVIE;
-		} else if (pdata->mode == USB_PERIPHERAL) {
-			ulpi_val = ULPI_INT_SESS_VALID;
-			val |= OTGSC_BSVIE;
-		}
-		writel(val, USB_OTGSC);
-		ulpi_write(phy, ulpi_val, ULPI_USB_INT_EN_RISE);
-		ulpi_write(phy, ulpi_val, ULPI_USB_INT_EN_FALL);
-	}
-
-	return 0;
-}
-
-#define PHY_SUSPEND_TIMEOUT_USEC	(500 * 1000)
-#define PHY_RESUME_TIMEOUT_USEC	(100 * 1000)
-
-#ifdef CONFIG_PM_SLEEP
-static int msm_otg_suspend(struct msm_otg *motg)
-{
-	struct usb_phy *phy = &motg->phy;
-	struct usb_bus *bus = phy->otg->host;
-	struct msm_otg_platform_data *pdata = motg->pdata;
-	int cnt = 0;
-
-	if (atomic_read(&motg->in_lpm))
-		return 0;
-
-	disable_irq(motg->irq);
-	/*
-	 * Chipidea 45-nm PHY suspend sequence:
-	 *
-	 * Interrupt Latch Register auto-clear feature is not present
-	 * in all PHY versions. Latch register is clear on read type.
-	 * Clear latch register to avoid spurious wakeup from
-	 * low power mode (LPM).
-	 *
-	 * PHY comparators are disabled when PHY enters into low power
-	 * mode (LPM). Keep PHY comparators ON in LPM only when we expect
-	 * VBUS/Id notifications from USB PHY. Otherwise turn off USB
-	 * PHY comparators. This save significant amount of power.
-	 *
-	 * PLL is not turned off when PHY enters into low power mode (LPM).
-	 * Disable PLL for maximum power savings.
-	 */
-
-	if (motg->pdata->phy_type == CI_45NM_INTEGRATED_PHY) {
-		ulpi_read(phy, 0x14);
-		if (pdata->otg_control == OTG_PHY_CONTROL)
-			ulpi_write(phy, 0x01, 0x30);
-		ulpi_write(phy, 0x08, 0x09);
-	}
-
-	/*
-	 * PHY may take some time or even fail to enter into low power
-	 * mode (LPM). Hence poll for 500 msec and reset the PHY and link
-	 * in failure case.
-	 */
-	writel(readl(USB_PORTSC) | PORTSC_PHCD, USB_PORTSC);
-	while (cnt < PHY_SUSPEND_TIMEOUT_USEC) {
-		if (readl(USB_PORTSC) & PORTSC_PHCD)
-			break;
-		udelay(1);
-		cnt++;
-	}
-
-	if (cnt >= PHY_SUSPEND_TIMEOUT_USEC) {
-		dev_err(phy->dev, "Unable to suspend PHY\n");
-		msm_otg_reset(phy);
-		enable_irq(motg->irq);
-		return -ETIMEDOUT;
-	}
-
-	/*
-	 * PHY has capability to generate interrupt asynchronously in low
-	 * power mode (LPM). This interrupt is level triggered. So USB IRQ
-	 * line must be disabled till async interrupt enable bit is cleared
-	 * in USBCMD register. Assert STP (ULPI interface STOP signal) to
-	 * block data communication from PHY.
-	 */
-	writel(readl(USB_USBCMD) | ASYNC_INTR_CTRL | ULPI_STP_CTRL, USB_USBCMD);
-
-	if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY &&
-			motg->pdata->otg_control == OTG_PMIC_CONTROL)
-		writel(readl(USB_PHY_CTRL) | PHY_RETEN, USB_PHY_CTRL);
-
-	clk_disable(motg->pclk);
-	clk_disable(motg->clk);
-	if (motg->core_clk)
-		clk_disable(motg->core_clk);
-
-	if (!IS_ERR(motg->pclk_src))
-		clk_disable(motg->pclk_src);
-
-	if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY &&
-			motg->pdata->otg_control == OTG_PMIC_CONTROL) {
-		msm_hsusb_ldo_set_mode(0);
-		msm_hsusb_config_vddcx(0);
-	}
-
-	if (device_may_wakeup(phy->dev))
-		enable_irq_wake(motg->irq);
-	if (bus)
-		clear_bit(HCD_FLAG_HW_ACCESSIBLE, &(bus_to_hcd(bus))->flags);
-
-	atomic_set(&motg->in_lpm, 1);
-	enable_irq(motg->irq);
-
-	dev_info(phy->dev, "USB in low power mode\n");
-
-	return 0;
-}
-
-static int msm_otg_resume(struct msm_otg *motg)
-{
-	struct usb_phy *phy = &motg->phy;
-	struct usb_bus *bus = phy->otg->host;
-	int cnt = 0;
-	unsigned temp;
-
-	if (!atomic_read(&motg->in_lpm))
-		return 0;
-
-	if (!IS_ERR(motg->pclk_src))
-		clk_enable(motg->pclk_src);
-
-	clk_enable(motg->pclk);
-	clk_enable(motg->clk);
-	if (motg->core_clk)
-		clk_enable(motg->core_clk);
-
-	if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY &&
-			motg->pdata->otg_control == OTG_PMIC_CONTROL) {
-		msm_hsusb_ldo_set_mode(1);
-		msm_hsusb_config_vddcx(1);
-		writel(readl(USB_PHY_CTRL) & ~PHY_RETEN, USB_PHY_CTRL);
-	}
-
-	temp = readl(USB_USBCMD);
-	temp &= ~ASYNC_INTR_CTRL;
-	temp &= ~ULPI_STP_CTRL;
-	writel(temp, USB_USBCMD);
-
-	/*
-	 * PHY comes out of low power mode (LPM) in case of wakeup
-	 * from asynchronous interrupt.
-	 */
-	if (!(readl(USB_PORTSC) & PORTSC_PHCD))
-		goto skip_phy_resume;
-
-	writel(readl(USB_PORTSC) & ~PORTSC_PHCD, USB_PORTSC);
-	while (cnt < PHY_RESUME_TIMEOUT_USEC) {
-		if (!(readl(USB_PORTSC) & PORTSC_PHCD))
-			break;
-		udelay(1);
-		cnt++;
-	}
-
-	if (cnt >= PHY_RESUME_TIMEOUT_USEC) {
-		/*
-		 * This is a fatal error. Reset the link and
-		 * PHY. USB state can not be restored. Re-insertion
-		 * of USB cable is the only way to get USB working.
-		 */
-		dev_err(phy->dev, "Unable to resume USB."
-				"Re-plugin the cable\n");
-		msm_otg_reset(phy);
-	}
-
-skip_phy_resume:
-	if (device_may_wakeup(phy->dev))
-		disable_irq_wake(motg->irq);
-	if (bus)
-		set_bit(HCD_FLAG_HW_ACCESSIBLE, &(bus_to_hcd(bus))->flags);
-
-	atomic_set(&motg->in_lpm, 0);
-
-	if (motg->async_int) {
-		motg->async_int = 0;
-		pm_runtime_put(phy->dev);
-		enable_irq(motg->irq);
-	}
-
-	dev_info(phy->dev, "USB exited from low power mode\n");
-
-	return 0;
-}
-#endif
-
-static void msm_otg_notify_charger(struct msm_otg *motg, unsigned mA)
-{
-	if (motg->cur_power == mA)
-		return;
-
-	/* TODO: Notify PMIC about available current */
-	dev_info(motg->phy.dev, "Avail curr from USB = %u\n", mA);
-	motg->cur_power = mA;
-}
-
-static int msm_otg_set_power(struct usb_phy *phy, unsigned mA)
-{
-	struct msm_otg *motg = container_of(phy, struct msm_otg, phy);
-
-	/*
-	 * Gadget driver uses set_power method to notify about the
-	 * available current based on suspend/configured states.
-	 *
-	 * IDEV_CHG can be drawn irrespective of suspend/un-configured
-	 * states when CDP/ACA is connected.
-	 */
-	if (motg->chg_type == USB_SDP_CHARGER)
-		msm_otg_notify_charger(motg, mA);
-
-	return 0;
-}
-
-static void msm_otg_start_host(struct usb_phy *phy, int on)
-{
-	struct msm_otg *motg = container_of(phy, struct msm_otg, phy);
-	struct msm_otg_platform_data *pdata = motg->pdata;
-	struct usb_hcd *hcd;
-
-	if (!phy->otg->host)
-		return;
-
-	hcd = bus_to_hcd(phy->otg->host);
-
-	if (on) {
-		dev_dbg(phy->dev, "host on\n");
-
-		if (pdata->vbus_power)
-			pdata->vbus_power(1);
-		/*
-		 * Some boards have a switch cotrolled by gpio
-		 * to enable/disable internal HUB. Enable internal
-		 * HUB before kicking the host.
-		 */
-		if (pdata->setup_gpio)
-			pdata->setup_gpio(OTG_STATE_A_HOST);
-#ifdef CONFIG_USB
-		usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
-#endif
-	} else {
-		dev_dbg(phy->dev, "host off\n");
-
-#ifdef CONFIG_USB
-		usb_remove_hcd(hcd);
-#endif
-		if (pdata->setup_gpio)
-			pdata->setup_gpio(OTG_STATE_UNDEFINED);
-		if (pdata->vbus_power)
-			pdata->vbus_power(0);
-	}
-}
-
-static int msm_otg_set_host(struct usb_otg *otg, struct usb_bus *host)
-{
-	struct msm_otg *motg = container_of(otg->phy, struct msm_otg, phy);
-	struct usb_hcd *hcd;
-
-	/*
-	 * Fail host registration if this board can support
-	 * only peripheral configuration.
-	 */
-	if (motg->pdata->mode == USB_PERIPHERAL) {
-		dev_info(otg->phy->dev, "Host mode is not supported\n");
-		return -ENODEV;
-	}
-
-	if (!host) {
-		if (otg->phy->state == OTG_STATE_A_HOST) {
-			pm_runtime_get_sync(otg->phy->dev);
-			msm_otg_start_host(otg->phy, 0);
-			otg->host = NULL;
-			otg->phy->state = OTG_STATE_UNDEFINED;
-			schedule_work(&motg->sm_work);
-		} else {
-			otg->host = NULL;
-		}
-
-		return 0;
-	}
-
-	hcd = bus_to_hcd(host);
-	hcd->power_budget = motg->pdata->power_budget;
-
-	otg->host = host;
-	dev_dbg(otg->phy->dev, "host driver registered w/ tranceiver\n");
-
-	/*
-	 * Kick the state machine work, if peripheral is not supported
-	 * or peripheral is already registered with us.
-	 */
-	if (motg->pdata->mode == USB_HOST || otg->gadget) {
-		pm_runtime_get_sync(otg->phy->dev);
-		schedule_work(&motg->sm_work);
-	}
-
-	return 0;
-}
-
-static void msm_otg_start_peripheral(struct usb_phy *phy, int on)
-{
-	struct msm_otg *motg = container_of(phy, struct msm_otg, phy);
-	struct msm_otg_platform_data *pdata = motg->pdata;
-
-	if (!phy->otg->gadget)
-		return;
-
-	if (on) {
-		dev_dbg(phy->dev, "gadget on\n");
-		/*
-		 * Some boards have a switch cotrolled by gpio
-		 * to enable/disable internal HUB. Disable internal
-		 * HUB before kicking the gadget.
-		 */
-		if (pdata->setup_gpio)
-			pdata->setup_gpio(OTG_STATE_B_PERIPHERAL);
-		usb_gadget_vbus_connect(phy->otg->gadget);
-	} else {
-		dev_dbg(phy->dev, "gadget off\n");
-		usb_gadget_vbus_disconnect(phy->otg->gadget);
-		if (pdata->setup_gpio)
-			pdata->setup_gpio(OTG_STATE_UNDEFINED);
-	}
-
-}
-
-static int msm_otg_set_peripheral(struct usb_otg *otg,
-					struct usb_gadget *gadget)
-{
-	struct msm_otg *motg = container_of(otg->phy, struct msm_otg, phy);
-
-	/*
-	 * Fail peripheral registration if this board can support
-	 * only host configuration.
-	 */
-	if (motg->pdata->mode == USB_HOST) {
-		dev_info(otg->phy->dev, "Peripheral mode is not supported\n");
-		return -ENODEV;
-	}
-
-	if (!gadget) {
-		if (otg->phy->state == OTG_STATE_B_PERIPHERAL) {
-			pm_runtime_get_sync(otg->phy->dev);
-			msm_otg_start_peripheral(otg->phy, 0);
-			otg->gadget = NULL;
-			otg->phy->state = OTG_STATE_UNDEFINED;
-			schedule_work(&motg->sm_work);
-		} else {
-			otg->gadget = NULL;
-		}
-
-		return 0;
-	}
-	otg->gadget = gadget;
-	dev_dbg(otg->phy->dev, "peripheral driver registered w/ tranceiver\n");
-
-	/*
-	 * Kick the state machine work, if host is not supported
-	 * or host is already registered with us.
-	 */
-	if (motg->pdata->mode == USB_PERIPHERAL || otg->host) {
-		pm_runtime_get_sync(otg->phy->dev);
-		schedule_work(&motg->sm_work);
-	}
-
-	return 0;
-}
-
-static bool msm_chg_check_secondary_det(struct msm_otg *motg)
-{
-	struct usb_phy *phy = &motg->phy;
-	u32 chg_det;
-	bool ret = false;
-
-	switch (motg->pdata->phy_type) {
-	case CI_45NM_INTEGRATED_PHY:
-		chg_det = ulpi_read(phy, 0x34);
-		ret = chg_det & (1 << 4);
-		break;
-	case SNPS_28NM_INTEGRATED_PHY:
-		chg_det = ulpi_read(phy, 0x87);
-		ret = chg_det & 1;
-		break;
-	default:
-		break;
-	}
-	return ret;
-}
-
-static void msm_chg_enable_secondary_det(struct msm_otg *motg)
-{
-	struct usb_phy *phy = &motg->phy;
-	u32 chg_det;
-
-	switch (motg->pdata->phy_type) {
-	case CI_45NM_INTEGRATED_PHY:
-		chg_det = ulpi_read(phy, 0x34);
-		/* Turn off charger block */
-		chg_det |= ~(1 << 1);
-		ulpi_write(phy, chg_det, 0x34);
-		udelay(20);
-		/* control chg block via ULPI */
-		chg_det &= ~(1 << 3);
-		ulpi_write(phy, chg_det, 0x34);
-		/* put it in host mode for enabling D- source */
-		chg_det &= ~(1 << 2);
-		ulpi_write(phy, chg_det, 0x34);
-		/* Turn on chg detect block */
-		chg_det &= ~(1 << 1);
-		ulpi_write(phy, chg_det, 0x34);
-		udelay(20);
-		/* enable chg detection */
-		chg_det &= ~(1 << 0);
-		ulpi_write(phy, chg_det, 0x34);
-		break;
-	case SNPS_28NM_INTEGRATED_PHY:
-		/*
-		 * Configure DM as current source, DP as current sink
-		 * and enable battery charging comparators.
-		 */
-		ulpi_write(phy, 0x8, 0x85);
-		ulpi_write(phy, 0x2, 0x85);
-		ulpi_write(phy, 0x1, 0x85);
-		break;
-	default:
-		break;
-	}
-}
-
-static bool msm_chg_check_primary_det(struct msm_otg *motg)
-{
-	struct usb_phy *phy = &motg->phy;
-	u32 chg_det;
-	bool ret = false;
-
-	switch (motg->pdata->phy_type) {
-	case CI_45NM_INTEGRATED_PHY:
-		chg_det = ulpi_read(phy, 0x34);
-		ret = chg_det & (1 << 4);
-		break;
-	case SNPS_28NM_INTEGRATED_PHY:
-		chg_det = ulpi_read(phy, 0x87);
-		ret = chg_det & 1;
-		break;
-	default:
-		break;
-	}
-	return ret;
-}
-
-static void msm_chg_enable_primary_det(struct msm_otg *motg)
-{
-	struct usb_phy *phy = &motg->phy;
-	u32 chg_det;
-
-	switch (motg->pdata->phy_type) {
-	case CI_45NM_INTEGRATED_PHY:
-		chg_det = ulpi_read(phy, 0x34);
-		/* enable chg detection */
-		chg_det &= ~(1 << 0);
-		ulpi_write(phy, chg_det, 0x34);
-		break;
-	case SNPS_28NM_INTEGRATED_PHY:
-		/*
-		 * Configure DP as current source, DM as current sink
-		 * and enable battery charging comparators.
-		 */
-		ulpi_write(phy, 0x2, 0x85);
-		ulpi_write(phy, 0x1, 0x85);
-		break;
-	default:
-		break;
-	}
-}
-
-static bool msm_chg_check_dcd(struct msm_otg *motg)
-{
-	struct usb_phy *phy = &motg->phy;
-	u32 line_state;
-	bool ret = false;
-
-	switch (motg->pdata->phy_type) {
-	case CI_45NM_INTEGRATED_PHY:
-		line_state = ulpi_read(phy, 0x15);
-		ret = !(line_state & 1);
-		break;
-	case SNPS_28NM_INTEGRATED_PHY:
-		line_state = ulpi_read(phy, 0x87);
-		ret = line_state & 2;
-		break;
-	default:
-		break;
-	}
-	return ret;
-}
-
-static void msm_chg_disable_dcd(struct msm_otg *motg)
-{
-	struct usb_phy *phy = &motg->phy;
-	u32 chg_det;
-
-	switch (motg->pdata->phy_type) {
-	case CI_45NM_INTEGRATED_PHY:
-		chg_det = ulpi_read(phy, 0x34);
-		chg_det &= ~(1 << 5);
-		ulpi_write(phy, chg_det, 0x34);
-		break;
-	case SNPS_28NM_INTEGRATED_PHY:
-		ulpi_write(phy, 0x10, 0x86);
-		break;
-	default:
-		break;
-	}
-}
-
-static void msm_chg_enable_dcd(struct msm_otg *motg)
-{
-	struct usb_phy *phy = &motg->phy;
-	u32 chg_det;
-
-	switch (motg->pdata->phy_type) {
-	case CI_45NM_INTEGRATED_PHY:
-		chg_det = ulpi_read(phy, 0x34);
-		/* Turn on D+ current source */
-		chg_det |= (1 << 5);
-		ulpi_write(phy, chg_det, 0x34);
-		break;
-	case SNPS_28NM_INTEGRATED_PHY:
-		/* Data contact detection enable */
-		ulpi_write(phy, 0x10, 0x85);
-		break;
-	default:
-		break;
-	}
-}
-
-static void msm_chg_block_on(struct msm_otg *motg)
-{
-	struct usb_phy *phy = &motg->phy;
-	u32 func_ctrl, chg_det;
-
-	/* put the controller in non-driving mode */
-	func_ctrl = ulpi_read(phy, ULPI_FUNC_CTRL);
-	func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
-	func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING;
-	ulpi_write(phy, func_ctrl, ULPI_FUNC_CTRL);
-
-	switch (motg->pdata->phy_type) {
-	case CI_45NM_INTEGRATED_PHY:
-		chg_det = ulpi_read(phy, 0x34);
-		/* control chg block via ULPI */
-		chg_det &= ~(1 << 3);
-		ulpi_write(phy, chg_det, 0x34);
-		/* Turn on chg detect block */
-		chg_det &= ~(1 << 1);
-		ulpi_write(phy, chg_det, 0x34);
-		udelay(20);
-		break;
-	case SNPS_28NM_INTEGRATED_PHY:
-		/* Clear charger detecting control bits */
-		ulpi_write(phy, 0x3F, 0x86);
-		/* Clear alt interrupt latch and enable bits */
-		ulpi_write(phy, 0x1F, 0x92);
-		ulpi_write(phy, 0x1F, 0x95);
-		udelay(100);
-		break;
-	default:
-		break;
-	}
-}
-
-static void msm_chg_block_off(struct msm_otg *motg)
-{
-	struct usb_phy *phy = &motg->phy;
-	u32 func_ctrl, chg_det;
-
-	switch (motg->pdata->phy_type) {
-	case CI_45NM_INTEGRATED_PHY:
-		chg_det = ulpi_read(phy, 0x34);
-		/* Turn off charger block */
-		chg_det |= ~(1 << 1);
-		ulpi_write(phy, chg_det, 0x34);
-		break;
-	case SNPS_28NM_INTEGRATED_PHY:
-		/* Clear charger detecting control bits */
-		ulpi_write(phy, 0x3F, 0x86);
-		/* Clear alt interrupt latch and enable bits */
-		ulpi_write(phy, 0x1F, 0x92);
-		ulpi_write(phy, 0x1F, 0x95);
-		break;
-	default:
-		break;
-	}
-
-	/* put the controller in normal mode */
-	func_ctrl = ulpi_read(phy, ULPI_FUNC_CTRL);
-	func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
-	func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NORMAL;
-	ulpi_write(phy, func_ctrl, ULPI_FUNC_CTRL);
-}
-
-#define MSM_CHG_DCD_POLL_TIME		(100 * HZ/1000) /* 100 msec */
-#define MSM_CHG_DCD_MAX_RETRIES		6 /* Tdcd_tmout = 6 * 100 msec */
-#define MSM_CHG_PRIMARY_DET_TIME	(40 * HZ/1000) /* TVDPSRC_ON */
-#define MSM_CHG_SECONDARY_DET_TIME	(40 * HZ/1000) /* TVDMSRC_ON */
-static void msm_chg_detect_work(struct work_struct *w)
-{
-	struct msm_otg *motg = container_of(w, struct msm_otg, chg_work.work);
-	struct usb_phy *phy = &motg->phy;
-	bool is_dcd, tmout, vout;
-	unsigned long delay;
-
-	dev_dbg(phy->dev, "chg detection work\n");
-	switch (motg->chg_state) {
-	case USB_CHG_STATE_UNDEFINED:
-		pm_runtime_get_sync(phy->dev);
-		msm_chg_block_on(motg);
-		msm_chg_enable_dcd(motg);
-		motg->chg_state = USB_CHG_STATE_WAIT_FOR_DCD;
-		motg->dcd_retries = 0;
-		delay = MSM_CHG_DCD_POLL_TIME;
-		break;
-	case USB_CHG_STATE_WAIT_FOR_DCD:
-		is_dcd = msm_chg_check_dcd(motg);
-		tmout = ++motg->dcd_retries == MSM_CHG_DCD_MAX_RETRIES;
-		if (is_dcd || tmout) {
-			msm_chg_disable_dcd(motg);
-			msm_chg_enable_primary_det(motg);
-			delay = MSM_CHG_PRIMARY_DET_TIME;
-			motg->chg_state = USB_CHG_STATE_DCD_DONE;
-		} else {
-			delay = MSM_CHG_DCD_POLL_TIME;
-		}
-		break;
-	case USB_CHG_STATE_DCD_DONE:
-		vout = msm_chg_check_primary_det(motg);
-		if (vout) {
-			msm_chg_enable_secondary_det(motg);
-			delay = MSM_CHG_SECONDARY_DET_TIME;
-			motg->chg_state = USB_CHG_STATE_PRIMARY_DONE;
-		} else {
-			motg->chg_type = USB_SDP_CHARGER;
-			motg->chg_state = USB_CHG_STATE_DETECTED;
-			delay = 0;
-		}
-		break;
-	case USB_CHG_STATE_PRIMARY_DONE:
-		vout = msm_chg_check_secondary_det(motg);
-		if (vout)
-			motg->chg_type = USB_DCP_CHARGER;
-		else
-			motg->chg_type = USB_CDP_CHARGER;
-		motg->chg_state = USB_CHG_STATE_SECONDARY_DONE;
-		/* fall through */
-	case USB_CHG_STATE_SECONDARY_DONE:
-		motg->chg_state = USB_CHG_STATE_DETECTED;
-	case USB_CHG_STATE_DETECTED:
-		msm_chg_block_off(motg);
-		dev_dbg(phy->dev, "charger = %d\n", motg->chg_type);
-		schedule_work(&motg->sm_work);
-		return;
-	default:
-		return;
-	}
-
-	schedule_delayed_work(&motg->chg_work, delay);
-}
-
-/*
- * We support OTG, Peripheral only and Host only configurations. In case
- * of OTG, mode switch (host-->peripheral/peripheral-->host) can happen
- * via Id pin status or user request (debugfs). Id/BSV interrupts are not
- * enabled when switch is controlled by user and default mode is supplied
- * by board file, which can be changed by userspace later.
- */
-static void msm_otg_init_sm(struct msm_otg *motg)
-{
-	struct msm_otg_platform_data *pdata = motg->pdata;
-	u32 otgsc = readl(USB_OTGSC);
-
-	switch (pdata->mode) {
-	case USB_OTG:
-		if (pdata->otg_control == OTG_PHY_CONTROL) {
-			if (otgsc & OTGSC_ID)
-				set_bit(ID, &motg->inputs);
-			else
-				clear_bit(ID, &motg->inputs);
-
-			if (otgsc & OTGSC_BSV)
-				set_bit(B_SESS_VLD, &motg->inputs);
-			else
-				clear_bit(B_SESS_VLD, &motg->inputs);
-		} else if (pdata->otg_control == OTG_USER_CONTROL) {
-			if (pdata->default_mode == USB_HOST) {
-				clear_bit(ID, &motg->inputs);
-			} else if (pdata->default_mode == USB_PERIPHERAL) {
-				set_bit(ID, &motg->inputs);
-				set_bit(B_SESS_VLD, &motg->inputs);
-			} else {
-				set_bit(ID, &motg->inputs);
-				clear_bit(B_SESS_VLD, &motg->inputs);
-			}
-		}
-		break;
-	case USB_HOST:
-		clear_bit(ID, &motg->inputs);
-		break;
-	case USB_PERIPHERAL:
-		set_bit(ID, &motg->inputs);
-		if (otgsc & OTGSC_BSV)
-			set_bit(B_SESS_VLD, &motg->inputs);
-		else
-			clear_bit(B_SESS_VLD, &motg->inputs);
-		break;
-	default:
-		break;
-	}
-}
-
-static void msm_otg_sm_work(struct work_struct *w)
-{
-	struct msm_otg *motg = container_of(w, struct msm_otg, sm_work);
-	struct usb_otg *otg = motg->phy.otg;
-
-	switch (otg->phy->state) {
-	case OTG_STATE_UNDEFINED:
-		dev_dbg(otg->phy->dev, "OTG_STATE_UNDEFINED state\n");
-		msm_otg_reset(otg->phy);
-		msm_otg_init_sm(motg);
-		otg->phy->state = OTG_STATE_B_IDLE;
-		/* FALL THROUGH */
-	case OTG_STATE_B_IDLE:
-		dev_dbg(otg->phy->dev, "OTG_STATE_B_IDLE state\n");
-		if (!test_bit(ID, &motg->inputs) && otg->host) {
-			/* disable BSV bit */
-			writel(readl(USB_OTGSC) & ~OTGSC_BSVIE, USB_OTGSC);
-			msm_otg_start_host(otg->phy, 1);
-			otg->phy->state = OTG_STATE_A_HOST;
-		} else if (test_bit(B_SESS_VLD, &motg->inputs)) {
-			switch (motg->chg_state) {
-			case USB_CHG_STATE_UNDEFINED:
-				msm_chg_detect_work(&motg->chg_work.work);
-				break;
-			case USB_CHG_STATE_DETECTED:
-				switch (motg->chg_type) {
-				case USB_DCP_CHARGER:
-					msm_otg_notify_charger(motg,
-							IDEV_CHG_MAX);
-					break;
-				case USB_CDP_CHARGER:
-					msm_otg_notify_charger(motg,
-							IDEV_CHG_MAX);
-					msm_otg_start_peripheral(otg->phy, 1);
-					otg->phy->state
-						= OTG_STATE_B_PERIPHERAL;
-					break;
-				case USB_SDP_CHARGER:
-					msm_otg_notify_charger(motg, IUNIT);
-					msm_otg_start_peripheral(otg->phy, 1);
-					otg->phy->state
-						= OTG_STATE_B_PERIPHERAL;
-					break;
-				default:
-					break;
-				}
-				break;
-			default:
-				break;
-			}
-		} else {
-			/*
-			 * If charger detection work is pending, decrement
-			 * the pm usage counter to balance with the one that
-			 * is incremented in charger detection work.
-			 */
-			if (cancel_delayed_work_sync(&motg->chg_work)) {
-				pm_runtime_put_sync(otg->phy->dev);
-				msm_otg_reset(otg->phy);
-			}
-			msm_otg_notify_charger(motg, 0);
-			motg->chg_state = USB_CHG_STATE_UNDEFINED;
-			motg->chg_type = USB_INVALID_CHARGER;
-		}
-		pm_runtime_put_sync(otg->phy->dev);
-		break;
-	case OTG_STATE_B_PERIPHERAL:
-		dev_dbg(otg->phy->dev, "OTG_STATE_B_PERIPHERAL state\n");
-		if (!test_bit(B_SESS_VLD, &motg->inputs) ||
-				!test_bit(ID, &motg->inputs)) {
-			msm_otg_notify_charger(motg, 0);
-			msm_otg_start_peripheral(otg->phy, 0);
-			motg->chg_state = USB_CHG_STATE_UNDEFINED;
-			motg->chg_type = USB_INVALID_CHARGER;
-			otg->phy->state = OTG_STATE_B_IDLE;
-			msm_otg_reset(otg->phy);
-			schedule_work(w);
-		}
-		break;
-	case OTG_STATE_A_HOST:
-		dev_dbg(otg->phy->dev, "OTG_STATE_A_HOST state\n");
-		if (test_bit(ID, &motg->inputs)) {
-			msm_otg_start_host(otg->phy, 0);
-			otg->phy->state = OTG_STATE_B_IDLE;
-			msm_otg_reset(otg->phy);
-			schedule_work(w);
-		}
-		break;
-	default:
-		break;
-	}
-}
-
-static irqreturn_t msm_otg_irq(int irq, void *data)
-{
-	struct msm_otg *motg = data;
-	struct usb_phy *phy = &motg->phy;
-	u32 otgsc = 0;
-
-	if (atomic_read(&motg->in_lpm)) {
-		disable_irq_nosync(irq);
-		motg->async_int = 1;
-		pm_runtime_get(phy->dev);
-		return IRQ_HANDLED;
-	}
-
-	otgsc = readl(USB_OTGSC);
-	if (!(otgsc & (OTGSC_IDIS | OTGSC_BSVIS)))
-		return IRQ_NONE;
-
-	if ((otgsc & OTGSC_IDIS) && (otgsc & OTGSC_IDIE)) {
-		if (otgsc & OTGSC_ID)
-			set_bit(ID, &motg->inputs);
-		else
-			clear_bit(ID, &motg->inputs);
-		dev_dbg(phy->dev, "ID set/clear\n");
-		pm_runtime_get_noresume(phy->dev);
-	} else if ((otgsc & OTGSC_BSVIS) && (otgsc & OTGSC_BSVIE)) {
-		if (otgsc & OTGSC_BSV)
-			set_bit(B_SESS_VLD, &motg->inputs);
-		else
-			clear_bit(B_SESS_VLD, &motg->inputs);
-		dev_dbg(phy->dev, "BSV set/clear\n");
-		pm_runtime_get_noresume(phy->dev);
-	}
-
-	writel(otgsc, USB_OTGSC);
-	schedule_work(&motg->sm_work);
-	return IRQ_HANDLED;
-}
-
-static int msm_otg_mode_show(struct seq_file *s, void *unused)
-{
-	struct msm_otg *motg = s->private;
-	struct usb_otg *otg = motg->phy.otg;
-
-	switch (otg->phy->state) {
-	case OTG_STATE_A_HOST:
-		seq_printf(s, "host\n");
-		break;
-	case OTG_STATE_B_PERIPHERAL:
-		seq_printf(s, "peripheral\n");
-		break;
-	default:
-		seq_printf(s, "none\n");
-		break;
-	}
-
-	return 0;
-}
-
-static int msm_otg_mode_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, msm_otg_mode_show, inode->i_private);
-}
-
-static ssize_t msm_otg_mode_write(struct file *file, const char __user *ubuf,
-				size_t count, loff_t *ppos)
-{
-	struct seq_file *s = file->private_data;
-	struct msm_otg *motg = s->private;
-	char buf[16];
-	struct usb_otg *otg = motg->phy.otg;
-	int status = count;
-	enum usb_mode_type req_mode;
-
-	memset(buf, 0x00, sizeof(buf));
-
-	if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) {
-		status = -EFAULT;
-		goto out;
-	}
-
-	if (!strncmp(buf, "host", 4)) {
-		req_mode = USB_HOST;
-	} else if (!strncmp(buf, "peripheral", 10)) {
-		req_mode = USB_PERIPHERAL;
-	} else if (!strncmp(buf, "none", 4)) {
-		req_mode = USB_NONE;
-	} else {
-		status = -EINVAL;
-		goto out;
-	}
-
-	switch (req_mode) {
-	case USB_NONE:
-		switch (otg->phy->state) {
-		case OTG_STATE_A_HOST:
-		case OTG_STATE_B_PERIPHERAL:
-			set_bit(ID, &motg->inputs);
-			clear_bit(B_SESS_VLD, &motg->inputs);
-			break;
-		default:
-			goto out;
-		}
-		break;
-	case USB_PERIPHERAL:
-		switch (otg->phy->state) {
-		case OTG_STATE_B_IDLE:
-		case OTG_STATE_A_HOST:
-			set_bit(ID, &motg->inputs);
-			set_bit(B_SESS_VLD, &motg->inputs);
-			break;
-		default:
-			goto out;
-		}
-		break;
-	case USB_HOST:
-		switch (otg->phy->state) {
-		case OTG_STATE_B_IDLE:
-		case OTG_STATE_B_PERIPHERAL:
-			clear_bit(ID, &motg->inputs);
-			break;
-		default:
-			goto out;
-		}
-		break;
-	default:
-		goto out;
-	}
-
-	pm_runtime_get_sync(otg->phy->dev);
-	schedule_work(&motg->sm_work);
-out:
-	return status;
-}
-
-const struct file_operations msm_otg_mode_fops = {
-	.open = msm_otg_mode_open,
-	.read = seq_read,
-	.write = msm_otg_mode_write,
-	.llseek = seq_lseek,
-	.release = single_release,
-};
-
-static struct dentry *msm_otg_dbg_root;
-static struct dentry *msm_otg_dbg_mode;
-
-static int msm_otg_debugfs_init(struct msm_otg *motg)
-{
-	msm_otg_dbg_root = debugfs_create_dir("msm_otg", NULL);
-
-	if (!msm_otg_dbg_root || IS_ERR(msm_otg_dbg_root))
-		return -ENODEV;
-
-	msm_otg_dbg_mode = debugfs_create_file("mode", S_IRUGO | S_IWUSR,
-				msm_otg_dbg_root, motg, &msm_otg_mode_fops);
-	if (!msm_otg_dbg_mode) {
-		debugfs_remove(msm_otg_dbg_root);
-		msm_otg_dbg_root = NULL;
-		return -ENODEV;
-	}
-
-	return 0;
-}
-
-static void msm_otg_debugfs_cleanup(void)
-{
-	debugfs_remove(msm_otg_dbg_mode);
-	debugfs_remove(msm_otg_dbg_root);
-}
-
-static int __init msm_otg_probe(struct platform_device *pdev)
-{
-	int ret = 0;
-	struct resource *res;
-	struct msm_otg *motg;
-	struct usb_phy *phy;
-
-	dev_info(&pdev->dev, "msm_otg probe\n");
-	if (!pdev->dev.platform_data) {
-		dev_err(&pdev->dev, "No platform data given. Bailing out\n");
-		return -ENODEV;
-	}
-
-	motg = kzalloc(sizeof(struct msm_otg), GFP_KERNEL);
-	if (!motg) {
-		dev_err(&pdev->dev, "unable to allocate msm_otg\n");
-		return -ENOMEM;
-	}
-
-	motg->phy.otg = kzalloc(sizeof(struct usb_otg), GFP_KERNEL);
-	if (!motg->phy.otg) {
-		dev_err(&pdev->dev, "unable to allocate msm_otg\n");
-		return -ENOMEM;
-	}
-
-	motg->pdata = pdev->dev.platform_data;
-	phy = &motg->phy;
-	phy->dev = &pdev->dev;
-
-	motg->phy_reset_clk = clk_get(&pdev->dev, "usb_phy_clk");
-	if (IS_ERR(motg->phy_reset_clk)) {
-		dev_err(&pdev->dev, "failed to get usb_phy_clk\n");
-		ret = PTR_ERR(motg->phy_reset_clk);
-		goto free_motg;
-	}
-
-	motg->clk = clk_get(&pdev->dev, "usb_hs_clk");
-	if (IS_ERR(motg->clk)) {
-		dev_err(&pdev->dev, "failed to get usb_hs_clk\n");
-		ret = PTR_ERR(motg->clk);
-		goto put_phy_reset_clk;
-	}
-	clk_set_rate(motg->clk, 60000000);
-
-	/*
-	 * If USB Core is running its protocol engine based on CORE CLK,
-	 * CORE CLK  must be running at >55Mhz for correct HSUSB
-	 * operation and USB core cannot tolerate frequency changes on
-	 * CORE CLK. For such USB cores, vote for maximum clk frequency
-	 * on pclk source
-	 */
-	 if (motg->pdata->pclk_src_name) {
-		motg->pclk_src = clk_get(&pdev->dev,
-			motg->pdata->pclk_src_name);
-		if (IS_ERR(motg->pclk_src))
-			goto put_clk;
-		clk_set_rate(motg->pclk_src, INT_MAX);
-		clk_enable(motg->pclk_src);
-	} else
-		motg->pclk_src = ERR_PTR(-ENOENT);
-
-
-	motg->pclk = clk_get(&pdev->dev, "usb_hs_pclk");
-	if (IS_ERR(motg->pclk)) {
-		dev_err(&pdev->dev, "failed to get usb_hs_pclk\n");
-		ret = PTR_ERR(motg->pclk);
-		goto put_pclk_src;
-	}
-
-	/*
-	 * USB core clock is not present on all MSM chips. This
-	 * clock is introduced to remove the dependency on AXI
-	 * bus frequency.
-	 */
-	motg->core_clk = clk_get(&pdev->dev, "usb_hs_core_clk");
-	if (IS_ERR(motg->core_clk))
-		motg->core_clk = NULL;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(&pdev->dev, "failed to get platform resource mem\n");
-		ret = -ENODEV;
-		goto put_core_clk;
-	}
-
-	motg->regs = ioremap(res->start, resource_size(res));
-	if (!motg->regs) {
-		dev_err(&pdev->dev, "ioremap failed\n");
-		ret = -ENOMEM;
-		goto put_core_clk;
-	}
-	dev_info(&pdev->dev, "OTG regs = %p\n", motg->regs);
-
-	motg->irq = platform_get_irq(pdev, 0);
-	if (!motg->irq) {
-		dev_err(&pdev->dev, "platform_get_irq failed\n");
-		ret = -ENODEV;
-		goto free_regs;
-	}
-
-	clk_enable(motg->clk);
-	clk_enable(motg->pclk);
-
-	ret = msm_hsusb_init_vddcx(motg, 1);
-	if (ret) {
-		dev_err(&pdev->dev, "hsusb vddcx configuration failed\n");
-		goto free_regs;
-	}
-
-	ret = msm_hsusb_ldo_init(motg, 1);
-	if (ret) {
-		dev_err(&pdev->dev, "hsusb vreg configuration failed\n");
-		goto vddcx_exit;
-	}
-	ret = msm_hsusb_ldo_set_mode(1);
-	if (ret) {
-		dev_err(&pdev->dev, "hsusb vreg enable failed\n");
-		goto ldo_exit;
-	}
-
-	if (motg->core_clk)
-		clk_enable(motg->core_clk);
-
-	writel(0, USB_USBINTR);
-	writel(0, USB_OTGSC);
-
-	INIT_WORK(&motg->sm_work, msm_otg_sm_work);
-	INIT_DELAYED_WORK(&motg->chg_work, msm_chg_detect_work);
-	ret = request_irq(motg->irq, msm_otg_irq, IRQF_SHARED,
-					"msm_otg", motg);
-	if (ret) {
-		dev_err(&pdev->dev, "request irq failed\n");
-		goto disable_clks;
-	}
-
-	phy->init = msm_otg_reset;
-	phy->set_power = msm_otg_set_power;
-
-	phy->io_ops = &msm_otg_io_ops;
-
-	phy->otg->phy = &motg->phy;
-	phy->otg->set_host = msm_otg_set_host;
-	phy->otg->set_peripheral = msm_otg_set_peripheral;
-
-	ret = usb_add_phy(&motg->phy, USB_PHY_TYPE_USB2);
-	if (ret) {
-		dev_err(&pdev->dev, "usb_add_phy failed\n");
-		goto free_irq;
-	}
-
-	platform_set_drvdata(pdev, motg);
-	device_init_wakeup(&pdev->dev, 1);
-
-	if (motg->pdata->mode == USB_OTG &&
-			motg->pdata->otg_control == OTG_USER_CONTROL) {
-		ret = msm_otg_debugfs_init(motg);
-		if (ret)
-			dev_dbg(&pdev->dev, "mode debugfs file is"
-					"not available\n");
-	}
-
-	pm_runtime_set_active(&pdev->dev);
-	pm_runtime_enable(&pdev->dev);
-
-	return 0;
-free_irq:
-	free_irq(motg->irq, motg);
-disable_clks:
-	clk_disable(motg->pclk);
-	clk_disable(motg->clk);
-ldo_exit:
-	msm_hsusb_ldo_init(motg, 0);
-vddcx_exit:
-	msm_hsusb_init_vddcx(motg, 0);
-free_regs:
-	iounmap(motg->regs);
-put_core_clk:
-	if (motg->core_clk)
-		clk_put(motg->core_clk);
-	clk_put(motg->pclk);
-put_pclk_src:
-	if (!IS_ERR(motg->pclk_src)) {
-		clk_disable(motg->pclk_src);
-		clk_put(motg->pclk_src);
-	}
-put_clk:
-	clk_put(motg->clk);
-put_phy_reset_clk:
-	clk_put(motg->phy_reset_clk);
-free_motg:
-	kfree(motg->phy.otg);
-	kfree(motg);
-	return ret;
-}
-
-static int msm_otg_remove(struct platform_device *pdev)
-{
-	struct msm_otg *motg = platform_get_drvdata(pdev);
-	struct usb_phy *phy = &motg->phy;
-	int cnt = 0;
-
-	if (phy->otg->host || phy->otg->gadget)
-		return -EBUSY;
-
-	msm_otg_debugfs_cleanup();
-	cancel_delayed_work_sync(&motg->chg_work);
-	cancel_work_sync(&motg->sm_work);
-
-	pm_runtime_resume(&pdev->dev);
-
-	device_init_wakeup(&pdev->dev, 0);
-	pm_runtime_disable(&pdev->dev);
-
-	usb_remove_phy(phy);
-	free_irq(motg->irq, motg);
-
-	/*
-	 * Put PHY in low power mode.
-	 */
-	ulpi_read(phy, 0x14);
-	ulpi_write(phy, 0x08, 0x09);
-
-	writel(readl(USB_PORTSC) | PORTSC_PHCD, USB_PORTSC);
-	while (cnt < PHY_SUSPEND_TIMEOUT_USEC) {
-		if (readl(USB_PORTSC) & PORTSC_PHCD)
-			break;
-		udelay(1);
-		cnt++;
-	}
-	if (cnt >= PHY_SUSPEND_TIMEOUT_USEC)
-		dev_err(phy->dev, "Unable to suspend PHY\n");
-
-	clk_disable(motg->pclk);
-	clk_disable(motg->clk);
-	if (motg->core_clk)
-		clk_disable(motg->core_clk);
-	if (!IS_ERR(motg->pclk_src)) {
-		clk_disable(motg->pclk_src);
-		clk_put(motg->pclk_src);
-	}
-	msm_hsusb_ldo_init(motg, 0);
-
-	iounmap(motg->regs);
-	pm_runtime_set_suspended(&pdev->dev);
-
-	clk_put(motg->phy_reset_clk);
-	clk_put(motg->pclk);
-	clk_put(motg->clk);
-	if (motg->core_clk)
-		clk_put(motg->core_clk);
-
-	kfree(motg->phy.otg);
-	kfree(motg);
-
-	return 0;
-}
-
-#ifdef CONFIG_PM_RUNTIME
-static int msm_otg_runtime_idle(struct device *dev)
-{
-	struct msm_otg *motg = dev_get_drvdata(dev);
-	struct usb_otg *otg = motg->phy.otg;
-
-	dev_dbg(dev, "OTG runtime idle\n");
-
-	/*
-	 * It is observed some times that a spurious interrupt
-	 * comes when PHY is put into LPM immediately after PHY reset.
-	 * This 1 sec delay also prevents entering into LPM immediately
-	 * after asynchronous interrupt.
-	 */
-	if (otg->phy->state != OTG_STATE_UNDEFINED)
-		pm_schedule_suspend(dev, 1000);
-
-	return -EAGAIN;
-}
-
-static int msm_otg_runtime_suspend(struct device *dev)
-{
-	struct msm_otg *motg = dev_get_drvdata(dev);
-
-	dev_dbg(dev, "OTG runtime suspend\n");
-	return msm_otg_suspend(motg);
-}
-
-static int msm_otg_runtime_resume(struct device *dev)
-{
-	struct msm_otg *motg = dev_get_drvdata(dev);
-
-	dev_dbg(dev, "OTG runtime resume\n");
-	return msm_otg_resume(motg);
-}
-#endif
-
-#ifdef CONFIG_PM_SLEEP
-static int msm_otg_pm_suspend(struct device *dev)
-{
-	struct msm_otg *motg = dev_get_drvdata(dev);
-
-	dev_dbg(dev, "OTG PM suspend\n");
-	return msm_otg_suspend(motg);
-}
-
-static int msm_otg_pm_resume(struct device *dev)
-{
-	struct msm_otg *motg = dev_get_drvdata(dev);
-	int ret;
-
-	dev_dbg(dev, "OTG PM resume\n");
-
-	ret = msm_otg_resume(motg);
-	if (ret)
-		return ret;
-
-	/*
-	 * Runtime PM Documentation recommends bringing the
-	 * device to full powered state upon resume.
-	 */
-	pm_runtime_disable(dev);
-	pm_runtime_set_active(dev);
-	pm_runtime_enable(dev);
-
-	return 0;
-}
-#endif
-
-#ifdef CONFIG_PM
-static const struct dev_pm_ops msm_otg_dev_pm_ops = {
-	SET_SYSTEM_SLEEP_PM_OPS(msm_otg_pm_suspend, msm_otg_pm_resume)
-	SET_RUNTIME_PM_OPS(msm_otg_runtime_suspend, msm_otg_runtime_resume,
-				msm_otg_runtime_idle)
-};
-#endif
-
-static struct platform_driver msm_otg_driver = {
-	.remove = msm_otg_remove,
-	.driver = {
-		.name = DRIVER_NAME,
-		.owner = THIS_MODULE,
-#ifdef CONFIG_PM
-		.pm = &msm_otg_dev_pm_ops,
-#endif
-	},
-};
-
-module_platform_driver_probe(msm_otg_driver, msm_otg_probe);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("MSM USB transceiver driver");
diff --git a/drivers/usb/otg/mv_otg.c b/drivers/usb/otg/mv_otg.c
deleted file mode 100644
index b6a9be3..0000000
--- a/drivers/usb/otg/mv_otg.c
+++ /dev/null
@@ -1,923 +0,0 @@
-/*
- * Copyright (C) 2011 Marvell International Ltd. All rights reserved.
- * Author: Chao Xie <chao.xie@marvell.com>
- *	   Neil Zhang <zhangwm@marvell.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/kernel.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/uaccess.h>
-#include <linux/device.h>
-#include <linux/proc_fs.h>
-#include <linux/clk.h>
-#include <linux/workqueue.h>
-#include <linux/platform_device.h>
-
-#include <linux/usb.h>
-#include <linux/usb/ch9.h>
-#include <linux/usb/otg.h>
-#include <linux/usb/gadget.h>
-#include <linux/usb/hcd.h>
-#include <linux/platform_data/mv_usb.h>
-
-#include "mv_otg.h"
-
-#define	DRIVER_DESC	"Marvell USB OTG transceiver driver"
-#define	DRIVER_VERSION	"Jan 20, 2010"
-
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_VERSION(DRIVER_VERSION);
-MODULE_LICENSE("GPL");
-
-static const char driver_name[] = "mv-otg";
-
-static char *state_string[] = {
-	"undefined",
-	"b_idle",
-	"b_srp_init",
-	"b_peripheral",
-	"b_wait_acon",
-	"b_host",
-	"a_idle",
-	"a_wait_vrise",
-	"a_wait_bcon",
-	"a_host",
-	"a_suspend",
-	"a_peripheral",
-	"a_wait_vfall",
-	"a_vbus_err"
-};
-
-static int mv_otg_set_vbus(struct usb_otg *otg, bool on)
-{
-	struct mv_otg *mvotg = container_of(otg->phy, struct mv_otg, phy);
-	if (mvotg->pdata->set_vbus == NULL)
-		return -ENODEV;
-
-	return mvotg->pdata->set_vbus(on);
-}
-
-static int mv_otg_set_host(struct usb_otg *otg,
-			   struct usb_bus *host)
-{
-	otg->host = host;
-
-	return 0;
-}
-
-static int mv_otg_set_peripheral(struct usb_otg *otg,
-				 struct usb_gadget *gadget)
-{
-	otg->gadget = gadget;
-
-	return 0;
-}
-
-static void mv_otg_run_state_machine(struct mv_otg *mvotg,
-				     unsigned long delay)
-{
-	dev_dbg(&mvotg->pdev->dev, "transceiver is updated\n");
-	if (!mvotg->qwork)
-		return;
-
-	queue_delayed_work(mvotg->qwork, &mvotg->work, delay);
-}
-
-static void mv_otg_timer_await_bcon(unsigned long data)
-{
-	struct mv_otg *mvotg = (struct mv_otg *) data;
-
-	mvotg->otg_ctrl.a_wait_bcon_timeout = 1;
-
-	dev_info(&mvotg->pdev->dev, "B Device No Response!\n");
-
-	if (spin_trylock(&mvotg->wq_lock)) {
-		mv_otg_run_state_machine(mvotg, 0);
-		spin_unlock(&mvotg->wq_lock);
-	}
-}
-
-static int mv_otg_cancel_timer(struct mv_otg *mvotg, unsigned int id)
-{
-	struct timer_list *timer;
-
-	if (id >= OTG_TIMER_NUM)
-		return -EINVAL;
-
-	timer = &mvotg->otg_ctrl.timer[id];
-
-	if (timer_pending(timer))
-		del_timer(timer);
-
-	return 0;
-}
-
-static int mv_otg_set_timer(struct mv_otg *mvotg, unsigned int id,
-			    unsigned long interval,
-			    void (*callback) (unsigned long))
-{
-	struct timer_list *timer;
-
-	if (id >= OTG_TIMER_NUM)
-		return -EINVAL;
-
-	timer = &mvotg->otg_ctrl.timer[id];
-	if (timer_pending(timer)) {
-		dev_err(&mvotg->pdev->dev, "Timer%d is already running\n", id);
-		return -EBUSY;
-	}
-
-	init_timer(timer);
-	timer->data = (unsigned long) mvotg;
-	timer->function = callback;
-	timer->expires = jiffies + interval;
-	add_timer(timer);
-
-	return 0;
-}
-
-static int mv_otg_reset(struct mv_otg *mvotg)
-{
-	unsigned int loops;
-	u32 tmp;
-
-	/* Stop the controller */
-	tmp = readl(&mvotg->op_regs->usbcmd);
-	tmp &= ~USBCMD_RUN_STOP;
-	writel(tmp, &mvotg->op_regs->usbcmd);
-
-	/* Reset the controller to get default values */
-	writel(USBCMD_CTRL_RESET, &mvotg->op_regs->usbcmd);
-
-	loops = 500;
-	while (readl(&mvotg->op_regs->usbcmd) & USBCMD_CTRL_RESET) {
-		if (loops == 0) {
-			dev_err(&mvotg->pdev->dev,
-				"Wait for RESET completed TIMEOUT\n");
-			return -ETIMEDOUT;
-		}
-		loops--;
-		udelay(20);
-	}
-
-	writel(0x0, &mvotg->op_regs->usbintr);
-	tmp = readl(&mvotg->op_regs->usbsts);
-	writel(tmp, &mvotg->op_regs->usbsts);
-
-	return 0;
-}
-
-static void mv_otg_init_irq(struct mv_otg *mvotg)
-{
-	u32 otgsc;
-
-	mvotg->irq_en = OTGSC_INTR_A_SESSION_VALID
-	    | OTGSC_INTR_A_VBUS_VALID;
-	mvotg->irq_status = OTGSC_INTSTS_A_SESSION_VALID
-	    | OTGSC_INTSTS_A_VBUS_VALID;
-
-	if (mvotg->pdata->vbus == NULL) {
-		mvotg->irq_en |= OTGSC_INTR_B_SESSION_VALID
-		    | OTGSC_INTR_B_SESSION_END;
-		mvotg->irq_status |= OTGSC_INTSTS_B_SESSION_VALID
-		    | OTGSC_INTSTS_B_SESSION_END;
-	}
-
-	if (mvotg->pdata->id == NULL) {
-		mvotg->irq_en |= OTGSC_INTR_USB_ID;
-		mvotg->irq_status |= OTGSC_INTSTS_USB_ID;
-	}
-
-	otgsc = readl(&mvotg->op_regs->otgsc);
-	otgsc |= mvotg->irq_en;
-	writel(otgsc, &mvotg->op_regs->otgsc);
-}
-
-static void mv_otg_start_host(struct mv_otg *mvotg, int on)
-{
-#ifdef CONFIG_USB
-	struct usb_otg *otg = mvotg->phy.otg;
-	struct usb_hcd *hcd;
-
-	if (!otg->host)
-		return;
-
-	dev_info(&mvotg->pdev->dev, "%s host\n", on ? "start" : "stop");
-
-	hcd = bus_to_hcd(otg->host);
-
-	if (on)
-		usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
-	else
-		usb_remove_hcd(hcd);
-#endif /* CONFIG_USB */
-}
-
-static void mv_otg_start_periphrals(struct mv_otg *mvotg, int on)
-{
-	struct usb_otg *otg = mvotg->phy.otg;
-
-	if (!otg->gadget)
-		return;
-
-	dev_info(mvotg->phy.dev, "gadget %s\n", on ? "on" : "off");
-
-	if (on)
-		usb_gadget_vbus_connect(otg->gadget);
-	else
-		usb_gadget_vbus_disconnect(otg->gadget);
-}
-
-static void otg_clock_enable(struct mv_otg *mvotg)
-{
-	unsigned int i;
-
-	for (i = 0; i < mvotg->clknum; i++)
-		clk_prepare_enable(mvotg->clk[i]);
-}
-
-static void otg_clock_disable(struct mv_otg *mvotg)
-{
-	unsigned int i;
-
-	for (i = 0; i < mvotg->clknum; i++)
-		clk_disable_unprepare(mvotg->clk[i]);
-}
-
-static int mv_otg_enable_internal(struct mv_otg *mvotg)
-{
-	int retval = 0;
-
-	if (mvotg->active)
-		return 0;
-
-	dev_dbg(&mvotg->pdev->dev, "otg enabled\n");
-
-	otg_clock_enable(mvotg);
-	if (mvotg->pdata->phy_init) {
-		retval = mvotg->pdata->phy_init(mvotg->phy_regs);
-		if (retval) {
-			dev_err(&mvotg->pdev->dev,
-				"init phy error %d\n", retval);
-			otg_clock_disable(mvotg);
-			return retval;
-		}
-	}
-	mvotg->active = 1;
-
-	return 0;
-
-}
-
-static int mv_otg_enable(struct mv_otg *mvotg)
-{
-	if (mvotg->clock_gating)
-		return mv_otg_enable_internal(mvotg);
-
-	return 0;
-}
-
-static void mv_otg_disable_internal(struct mv_otg *mvotg)
-{
-	if (mvotg->active) {
-		dev_dbg(&mvotg->pdev->dev, "otg disabled\n");
-		if (mvotg->pdata->phy_deinit)
-			mvotg->pdata->phy_deinit(mvotg->phy_regs);
-		otg_clock_disable(mvotg);
-		mvotg->active = 0;
-	}
-}
-
-static void mv_otg_disable(struct mv_otg *mvotg)
-{
-	if (mvotg->clock_gating)
-		mv_otg_disable_internal(mvotg);
-}
-
-static void mv_otg_update_inputs(struct mv_otg *mvotg)
-{
-	struct mv_otg_ctrl *otg_ctrl = &mvotg->otg_ctrl;
-	u32 otgsc;
-
-	otgsc = readl(&mvotg->op_regs->otgsc);
-
-	if (mvotg->pdata->vbus) {
-		if (mvotg->pdata->vbus->poll() == VBUS_HIGH) {
-			otg_ctrl->b_sess_vld = 1;
-			otg_ctrl->b_sess_end = 0;
-		} else {
-			otg_ctrl->b_sess_vld = 0;
-			otg_ctrl->b_sess_end = 1;
-		}
-	} else {
-		otg_ctrl->b_sess_vld = !!(otgsc & OTGSC_STS_B_SESSION_VALID);
-		otg_ctrl->b_sess_end = !!(otgsc & OTGSC_STS_B_SESSION_END);
-	}
-
-	if (mvotg->pdata->id)
-		otg_ctrl->id = !!mvotg->pdata->id->poll();
-	else
-		otg_ctrl->id = !!(otgsc & OTGSC_STS_USB_ID);
-
-	if (mvotg->pdata->otg_force_a_bus_req && !otg_ctrl->id)
-		otg_ctrl->a_bus_req = 1;
-
-	otg_ctrl->a_sess_vld = !!(otgsc & OTGSC_STS_A_SESSION_VALID);
-	otg_ctrl->a_vbus_vld = !!(otgsc & OTGSC_STS_A_VBUS_VALID);
-
-	dev_dbg(&mvotg->pdev->dev, "%s: ", __func__);
-	dev_dbg(&mvotg->pdev->dev, "id %d\n", otg_ctrl->id);
-	dev_dbg(&mvotg->pdev->dev, "b_sess_vld %d\n", otg_ctrl->b_sess_vld);
-	dev_dbg(&mvotg->pdev->dev, "b_sess_end %d\n", otg_ctrl->b_sess_end);
-	dev_dbg(&mvotg->pdev->dev, "a_vbus_vld %d\n", otg_ctrl->a_vbus_vld);
-	dev_dbg(&mvotg->pdev->dev, "a_sess_vld %d\n", otg_ctrl->a_sess_vld);
-}
-
-static void mv_otg_update_state(struct mv_otg *mvotg)
-{
-	struct mv_otg_ctrl *otg_ctrl = &mvotg->otg_ctrl;
-	struct usb_phy *phy = &mvotg->phy;
-	int old_state = phy->state;
-
-	switch (old_state) {
-	case OTG_STATE_UNDEFINED:
-		phy->state = OTG_STATE_B_IDLE;
-		/* FALL THROUGH */
-	case OTG_STATE_B_IDLE:
-		if (otg_ctrl->id == 0)
-			phy->state = OTG_STATE_A_IDLE;
-		else if (otg_ctrl->b_sess_vld)
-			phy->state = OTG_STATE_B_PERIPHERAL;
-		break;
-	case OTG_STATE_B_PERIPHERAL:
-		if (!otg_ctrl->b_sess_vld || otg_ctrl->id == 0)
-			phy->state = OTG_STATE_B_IDLE;
-		break;
-	case OTG_STATE_A_IDLE:
-		if (otg_ctrl->id)
-			phy->state = OTG_STATE_B_IDLE;
-		else if (!(otg_ctrl->a_bus_drop) &&
-			 (otg_ctrl->a_bus_req || otg_ctrl->a_srp_det))
-			phy->state = OTG_STATE_A_WAIT_VRISE;
-		break;
-	case OTG_STATE_A_WAIT_VRISE:
-		if (otg_ctrl->a_vbus_vld)
-			phy->state = OTG_STATE_A_WAIT_BCON;
-		break;
-	case OTG_STATE_A_WAIT_BCON:
-		if (otg_ctrl->id || otg_ctrl->a_bus_drop
-		    || otg_ctrl->a_wait_bcon_timeout) {
-			mv_otg_cancel_timer(mvotg, A_WAIT_BCON_TIMER);
-			mvotg->otg_ctrl.a_wait_bcon_timeout = 0;
-			phy->state = OTG_STATE_A_WAIT_VFALL;
-			otg_ctrl->a_bus_req = 0;
-		} else if (!otg_ctrl->a_vbus_vld) {
-			mv_otg_cancel_timer(mvotg, A_WAIT_BCON_TIMER);
-			mvotg->otg_ctrl.a_wait_bcon_timeout = 0;
-			phy->state = OTG_STATE_A_VBUS_ERR;
-		} else if (otg_ctrl->b_conn) {
-			mv_otg_cancel_timer(mvotg, A_WAIT_BCON_TIMER);
-			mvotg->otg_ctrl.a_wait_bcon_timeout = 0;
-			phy->state = OTG_STATE_A_HOST;
-		}
-		break;
-	case OTG_STATE_A_HOST:
-		if (otg_ctrl->id || !otg_ctrl->b_conn
-		    || otg_ctrl->a_bus_drop)
-			phy->state = OTG_STATE_A_WAIT_BCON;
-		else if (!otg_ctrl->a_vbus_vld)
-			phy->state = OTG_STATE_A_VBUS_ERR;
-		break;
-	case OTG_STATE_A_WAIT_VFALL:
-		if (otg_ctrl->id
-		    || (!otg_ctrl->b_conn && otg_ctrl->a_sess_vld)
-		    || otg_ctrl->a_bus_req)
-			phy->state = OTG_STATE_A_IDLE;
-		break;
-	case OTG_STATE_A_VBUS_ERR:
-		if (otg_ctrl->id || otg_ctrl->a_clr_err
-		    || otg_ctrl->a_bus_drop) {
-			otg_ctrl->a_clr_err = 0;
-			phy->state = OTG_STATE_A_WAIT_VFALL;
-		}
-		break;
-	default:
-		break;
-	}
-}
-
-static void mv_otg_work(struct work_struct *work)
-{
-	struct mv_otg *mvotg;
-	struct usb_phy *phy;
-	struct usb_otg *otg;
-	int old_state;
-
-	mvotg = container_of(to_delayed_work(work), struct mv_otg, work);
-
-run:
-	/* work queue is single thread, or we need spin_lock to protect */
-	phy = &mvotg->phy;
-	otg = phy->otg;
-	old_state = phy->state;
-
-	if (!mvotg->active)
-		return;
-
-	mv_otg_update_inputs(mvotg);
-	mv_otg_update_state(mvotg);
-
-	if (old_state != phy->state) {
-		dev_info(&mvotg->pdev->dev, "change from state %s to %s\n",
-			 state_string[old_state],
-			 state_string[phy->state]);
-
-		switch (phy->state) {
-		case OTG_STATE_B_IDLE:
-			otg->default_a = 0;
-			if (old_state == OTG_STATE_B_PERIPHERAL)
-				mv_otg_start_periphrals(mvotg, 0);
-			mv_otg_reset(mvotg);
-			mv_otg_disable(mvotg);
-			break;
-		case OTG_STATE_B_PERIPHERAL:
-			mv_otg_enable(mvotg);
-			mv_otg_start_periphrals(mvotg, 1);
-			break;
-		case OTG_STATE_A_IDLE:
-			otg->default_a = 1;
-			mv_otg_enable(mvotg);
-			if (old_state == OTG_STATE_A_WAIT_VFALL)
-				mv_otg_start_host(mvotg, 0);
-			mv_otg_reset(mvotg);
-			break;
-		case OTG_STATE_A_WAIT_VRISE:
-			mv_otg_set_vbus(otg, 1);
-			break;
-		case OTG_STATE_A_WAIT_BCON:
-			if (old_state != OTG_STATE_A_HOST)
-				mv_otg_start_host(mvotg, 1);
-			mv_otg_set_timer(mvotg, A_WAIT_BCON_TIMER,
-					 T_A_WAIT_BCON,
-					 mv_otg_timer_await_bcon);
-			/*
-			 * Now, we directly enter A_HOST. So set b_conn = 1
-			 * here. In fact, it need host driver to notify us.
-			 */
-			mvotg->otg_ctrl.b_conn = 1;
-			break;
-		case OTG_STATE_A_HOST:
-			break;
-		case OTG_STATE_A_WAIT_VFALL:
-			/*
-			 * Now, we has exited A_HOST. So set b_conn = 0
-			 * here. In fact, it need host driver to notify us.
-			 */
-			mvotg->otg_ctrl.b_conn = 0;
-			mv_otg_set_vbus(otg, 0);
-			break;
-		case OTG_STATE_A_VBUS_ERR:
-			break;
-		default:
-			break;
-		}
-		goto run;
-	}
-}
-
-static irqreturn_t mv_otg_irq(int irq, void *dev)
-{
-	struct mv_otg *mvotg = dev;
-	u32 otgsc;
-
-	otgsc = readl(&mvotg->op_regs->otgsc);
-	writel(otgsc, &mvotg->op_regs->otgsc);
-
-	/*
-	 * if we have vbus, then the vbus detection for B-device
-	 * will be done by mv_otg_inputs_irq().
-	 */
-	if (mvotg->pdata->vbus)
-		if ((otgsc & OTGSC_STS_USB_ID) &&
-		    !(otgsc & OTGSC_INTSTS_USB_ID))
-			return IRQ_NONE;
-
-	if ((otgsc & mvotg->irq_status) == 0)
-		return IRQ_NONE;
-
-	mv_otg_run_state_machine(mvotg, 0);
-
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t mv_otg_inputs_irq(int irq, void *dev)
-{
-	struct mv_otg *mvotg = dev;
-
-	/* The clock may disabled at this time */
-	if (!mvotg->active) {
-		mv_otg_enable(mvotg);
-		mv_otg_init_irq(mvotg);
-	}
-
-	mv_otg_run_state_machine(mvotg, 0);
-
-	return IRQ_HANDLED;
-}
-
-static ssize_t
-get_a_bus_req(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct mv_otg *mvotg = dev_get_drvdata(dev);
-	return scnprintf(buf, PAGE_SIZE, "%d\n",
-			 mvotg->otg_ctrl.a_bus_req);
-}
-
-static ssize_t
-set_a_bus_req(struct device *dev, struct device_attribute *attr,
-	      const char *buf, size_t count)
-{
-	struct mv_otg *mvotg = dev_get_drvdata(dev);
-
-	if (count > 2)
-		return -1;
-
-	/* We will use this interface to change to A device */
-	if (mvotg->phy.state != OTG_STATE_B_IDLE
-	    && mvotg->phy.state != OTG_STATE_A_IDLE)
-		return -1;
-
-	/* The clock may disabled and we need to set irq for ID detected */
-	mv_otg_enable(mvotg);
-	mv_otg_init_irq(mvotg);
-
-	if (buf[0] == '1') {
-		mvotg->otg_ctrl.a_bus_req = 1;
-		mvotg->otg_ctrl.a_bus_drop = 0;
-		dev_dbg(&mvotg->pdev->dev,
-			"User request: a_bus_req = 1\n");
-
-		if (spin_trylock(&mvotg->wq_lock)) {
-			mv_otg_run_state_machine(mvotg, 0);
-			spin_unlock(&mvotg->wq_lock);
-		}
-	}
-
-	return count;
-}
-
-static DEVICE_ATTR(a_bus_req, S_IRUGO | S_IWUSR, get_a_bus_req,
-		   set_a_bus_req);
-
-static ssize_t
-set_a_clr_err(struct device *dev, struct device_attribute *attr,
-	      const char *buf, size_t count)
-{
-	struct mv_otg *mvotg = dev_get_drvdata(dev);
-	if (!mvotg->phy.otg->default_a)
-		return -1;
-
-	if (count > 2)
-		return -1;
-
-	if (buf[0] == '1') {
-		mvotg->otg_ctrl.a_clr_err = 1;
-		dev_dbg(&mvotg->pdev->dev,
-			"User request: a_clr_err = 1\n");
-	}
-
-	if (spin_trylock(&mvotg->wq_lock)) {
-		mv_otg_run_state_machine(mvotg, 0);
-		spin_unlock(&mvotg->wq_lock);
-	}
-
-	return count;
-}
-
-static DEVICE_ATTR(a_clr_err, S_IWUSR, NULL, set_a_clr_err);
-
-static ssize_t
-get_a_bus_drop(struct device *dev, struct device_attribute *attr,
-	       char *buf)
-{
-	struct mv_otg *mvotg = dev_get_drvdata(dev);
-	return scnprintf(buf, PAGE_SIZE, "%d\n",
-			 mvotg->otg_ctrl.a_bus_drop);
-}
-
-static ssize_t
-set_a_bus_drop(struct device *dev, struct device_attribute *attr,
-	       const char *buf, size_t count)
-{
-	struct mv_otg *mvotg = dev_get_drvdata(dev);
-	if (!mvotg->phy.otg->default_a)
-		return -1;
-
-	if (count > 2)
-		return -1;
-
-	if (buf[0] == '0') {
-		mvotg->otg_ctrl.a_bus_drop = 0;
-		dev_dbg(&mvotg->pdev->dev,
-			"User request: a_bus_drop = 0\n");
-	} else if (buf[0] == '1') {
-		mvotg->otg_ctrl.a_bus_drop = 1;
-		mvotg->otg_ctrl.a_bus_req = 0;
-		dev_dbg(&mvotg->pdev->dev,
-			"User request: a_bus_drop = 1\n");
-		dev_dbg(&mvotg->pdev->dev,
-			"User request: and a_bus_req = 0\n");
-	}
-
-	if (spin_trylock(&mvotg->wq_lock)) {
-		mv_otg_run_state_machine(mvotg, 0);
-		spin_unlock(&mvotg->wq_lock);
-	}
-
-	return count;
-}
-
-static DEVICE_ATTR(a_bus_drop, S_IRUGO | S_IWUSR,
-		   get_a_bus_drop, set_a_bus_drop);
-
-static struct attribute *inputs_attrs[] = {
-	&dev_attr_a_bus_req.attr,
-	&dev_attr_a_clr_err.attr,
-	&dev_attr_a_bus_drop.attr,
-	NULL,
-};
-
-static struct attribute_group inputs_attr_group = {
-	.name = "inputs",
-	.attrs = inputs_attrs,
-};
-
-int mv_otg_remove(struct platform_device *pdev)
-{
-	struct mv_otg *mvotg = platform_get_drvdata(pdev);
-
-	sysfs_remove_group(&mvotg->pdev->dev.kobj, &inputs_attr_group);
-
-	if (mvotg->qwork) {
-		flush_workqueue(mvotg->qwork);
-		destroy_workqueue(mvotg->qwork);
-	}
-
-	mv_otg_disable(mvotg);
-
-	usb_remove_phy(&mvotg->phy);
-	platform_set_drvdata(pdev, NULL);
-
-	return 0;
-}
-
-static int mv_otg_probe(struct platform_device *pdev)
-{
-	struct mv_usb_platform_data *pdata = pdev->dev.platform_data;
-	struct mv_otg *mvotg;
-	struct usb_otg *otg;
-	struct resource *r;
-	int retval = 0, clk_i, i;
-	size_t size;
-
-	if (pdata == NULL) {
-		dev_err(&pdev->dev, "failed to get platform data\n");
-		return -ENODEV;
-	}
-
-	size = sizeof(*mvotg) + sizeof(struct clk *) * pdata->clknum;
-	mvotg = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
-	if (!mvotg) {
-		dev_err(&pdev->dev, "failed to allocate memory!\n");
-		return -ENOMEM;
-	}
-
-	otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL);
-	if (!otg)
-		return -ENOMEM;
-
-	platform_set_drvdata(pdev, mvotg);
-
-	mvotg->pdev = pdev;
-	mvotg->pdata = pdata;
-
-	mvotg->clknum = pdata->clknum;
-	for (clk_i = 0; clk_i < mvotg->clknum; clk_i++) {
-		mvotg->clk[clk_i] = devm_clk_get(&pdev->dev,
-						pdata->clkname[clk_i]);
-		if (IS_ERR(mvotg->clk[clk_i])) {
-			retval = PTR_ERR(mvotg->clk[clk_i]);
-			return retval;
-		}
-	}
-
-	mvotg->qwork = create_singlethread_workqueue("mv_otg_queue");
-	if (!mvotg->qwork) {
-		dev_dbg(&pdev->dev, "cannot create workqueue for OTG\n");
-		return -ENOMEM;
-	}
-
-	INIT_DELAYED_WORK(&mvotg->work, mv_otg_work);
-
-	/* OTG common part */
-	mvotg->pdev = pdev;
-	mvotg->phy.dev = &pdev->dev;
-	mvotg->phy.otg = otg;
-	mvotg->phy.label = driver_name;
-	mvotg->phy.state = OTG_STATE_UNDEFINED;
-
-	otg->phy = &mvotg->phy;
-	otg->set_host = mv_otg_set_host;
-	otg->set_peripheral = mv_otg_set_peripheral;
-	otg->set_vbus = mv_otg_set_vbus;
-
-	for (i = 0; i < OTG_TIMER_NUM; i++)
-		init_timer(&mvotg->otg_ctrl.timer[i]);
-
-	r = platform_get_resource_byname(mvotg->pdev,
-					 IORESOURCE_MEM, "phyregs");
-	if (r == NULL) {
-		dev_err(&pdev->dev, "no phy I/O memory resource defined\n");
-		retval = -ENODEV;
-		goto err_destroy_workqueue;
-	}
-
-	mvotg->phy_regs = devm_ioremap(&pdev->dev, r->start, resource_size(r));
-	if (mvotg->phy_regs == NULL) {
-		dev_err(&pdev->dev, "failed to map phy I/O memory\n");
-		retval = -EFAULT;
-		goto err_destroy_workqueue;
-	}
-
-	r = platform_get_resource_byname(mvotg->pdev,
-					 IORESOURCE_MEM, "capregs");
-	if (r == NULL) {
-		dev_err(&pdev->dev, "no I/O memory resource defined\n");
-		retval = -ENODEV;
-		goto err_destroy_workqueue;
-	}
-
-	mvotg->cap_regs = devm_ioremap(&pdev->dev, r->start, resource_size(r));
-	if (mvotg->cap_regs == NULL) {
-		dev_err(&pdev->dev, "failed to map I/O memory\n");
-		retval = -EFAULT;
-		goto err_destroy_workqueue;
-	}
-
-	/* we will acces controller register, so enable the udc controller */
-	retval = mv_otg_enable_internal(mvotg);
-	if (retval) {
-		dev_err(&pdev->dev, "mv otg enable error %d\n", retval);
-		goto err_destroy_workqueue;
-	}
-
-	mvotg->op_regs =
-		(struct mv_otg_regs __iomem *) ((unsigned long) mvotg->cap_regs
-			+ (readl(mvotg->cap_regs) & CAPLENGTH_MASK));
-
-	if (pdata->id) {
-		retval = devm_request_threaded_irq(&pdev->dev, pdata->id->irq,
-						NULL, mv_otg_inputs_irq,
-						IRQF_ONESHOT, "id", mvotg);
-		if (retval) {
-			dev_info(&pdev->dev,
-				 "Failed to request irq for ID\n");
-			pdata->id = NULL;
-		}
-	}
-
-	if (pdata->vbus) {
-		mvotg->clock_gating = 1;
-		retval = devm_request_threaded_irq(&pdev->dev, pdata->vbus->irq,
-						NULL, mv_otg_inputs_irq,
-						IRQF_ONESHOT, "vbus", mvotg);
-		if (retval) {
-			dev_info(&pdev->dev,
-				 "Failed to request irq for VBUS, "
-				 "disable clock gating\n");
-			mvotg->clock_gating = 0;
-			pdata->vbus = NULL;
-		}
-	}
-
-	if (pdata->disable_otg_clock_gating)
-		mvotg->clock_gating = 0;
-
-	mv_otg_reset(mvotg);
-	mv_otg_init_irq(mvotg);
-
-	r = platform_get_resource(mvotg->pdev, IORESOURCE_IRQ, 0);
-	if (r == NULL) {
-		dev_err(&pdev->dev, "no IRQ resource defined\n");
-		retval = -ENODEV;
-		goto err_disable_clk;
-	}
-
-	mvotg->irq = r->start;
-	if (devm_request_irq(&pdev->dev, mvotg->irq, mv_otg_irq, IRQF_SHARED,
-			driver_name, mvotg)) {
-		dev_err(&pdev->dev, "Request irq %d for OTG failed\n",
-			mvotg->irq);
-		mvotg->irq = 0;
-		retval = -ENODEV;
-		goto err_disable_clk;
-	}
-
-	retval = usb_add_phy(&mvotg->phy, USB_PHY_TYPE_USB2);
-	if (retval < 0) {
-		dev_err(&pdev->dev, "can't register transceiver, %d\n",
-			retval);
-		goto err_disable_clk;
-	}
-
-	retval = sysfs_create_group(&pdev->dev.kobj, &inputs_attr_group);
-	if (retval < 0) {
-		dev_dbg(&pdev->dev,
-			"Can't register sysfs attr group: %d\n", retval);
-		goto err_remove_phy;
-	}
-
-	spin_lock_init(&mvotg->wq_lock);
-	if (spin_trylock(&mvotg->wq_lock)) {
-		mv_otg_run_state_machine(mvotg, 2 * HZ);
-		spin_unlock(&mvotg->wq_lock);
-	}
-
-	dev_info(&pdev->dev,
-		 "successful probe OTG device %s clock gating.\n",
-		 mvotg->clock_gating ? "with" : "without");
-
-	return 0;
-
-err_remove_phy:
-	usb_remove_phy(&mvotg->phy);
-err_disable_clk:
-	mv_otg_disable_internal(mvotg);
-err_destroy_workqueue:
-	flush_workqueue(mvotg->qwork);
-	destroy_workqueue(mvotg->qwork);
-
-	platform_set_drvdata(pdev, NULL);
-
-	return retval;
-}
-
-#ifdef CONFIG_PM
-static int mv_otg_suspend(struct platform_device *pdev, pm_message_t state)
-{
-	struct mv_otg *mvotg = platform_get_drvdata(pdev);
-
-	if (mvotg->phy.state != OTG_STATE_B_IDLE) {
-		dev_info(&pdev->dev,
-			 "OTG state is not B_IDLE, it is %d!\n",
-			 mvotg->phy.state);
-		return -EAGAIN;
-	}
-
-	if (!mvotg->clock_gating)
-		mv_otg_disable_internal(mvotg);
-
-	return 0;
-}
-
-static int mv_otg_resume(struct platform_device *pdev)
-{
-	struct mv_otg *mvotg = platform_get_drvdata(pdev);
-	u32 otgsc;
-
-	if (!mvotg->clock_gating) {
-		mv_otg_enable_internal(mvotg);
-
-		otgsc = readl(&mvotg->op_regs->otgsc);
-		otgsc |= mvotg->irq_en;
-		writel(otgsc, &mvotg->op_regs->otgsc);
-
-		if (spin_trylock(&mvotg->wq_lock)) {
-			mv_otg_run_state_machine(mvotg, 0);
-			spin_unlock(&mvotg->wq_lock);
-		}
-	}
-	return 0;
-}
-#endif
-
-static struct platform_driver mv_otg_driver = {
-	.probe = mv_otg_probe,
-	.remove = __exit_p(mv_otg_remove),
-	.driver = {
-		   .owner = THIS_MODULE,
-		   .name = driver_name,
-		   },
-#ifdef CONFIG_PM
-	.suspend = mv_otg_suspend,
-	.resume = mv_otg_resume,
-#endif
-};
-module_platform_driver(mv_otg_driver);
diff --git a/drivers/usb/otg/mv_otg.h b/drivers/usb/otg/mv_otg.h
deleted file mode 100644
index 8a9e351..0000000
--- a/drivers/usb/otg/mv_otg.h
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright (C) 2011 Marvell International 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 as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-
-#ifndef	__MV_USB_OTG_CONTROLLER__
-#define	__MV_USB_OTG_CONTROLLER__
-
-#include <linux/types.h>
-
-/* Command Register Bit Masks */
-#define USBCMD_RUN_STOP			(0x00000001)
-#define USBCMD_CTRL_RESET		(0x00000002)
-
-/* otgsc Register Bit Masks */
-#define OTGSC_CTRL_VUSB_DISCHARGE		0x00000001
-#define OTGSC_CTRL_VUSB_CHARGE			0x00000002
-#define OTGSC_CTRL_OTG_TERM			0x00000008
-#define OTGSC_CTRL_DATA_PULSING			0x00000010
-#define OTGSC_STS_USB_ID			0x00000100
-#define OTGSC_STS_A_VBUS_VALID			0x00000200
-#define OTGSC_STS_A_SESSION_VALID		0x00000400
-#define OTGSC_STS_B_SESSION_VALID		0x00000800
-#define OTGSC_STS_B_SESSION_END			0x00001000
-#define OTGSC_STS_1MS_TOGGLE			0x00002000
-#define OTGSC_STS_DATA_PULSING			0x00004000
-#define OTGSC_INTSTS_USB_ID			0x00010000
-#define OTGSC_INTSTS_A_VBUS_VALID		0x00020000
-#define OTGSC_INTSTS_A_SESSION_VALID		0x00040000
-#define OTGSC_INTSTS_B_SESSION_VALID		0x00080000
-#define OTGSC_INTSTS_B_SESSION_END		0x00100000
-#define OTGSC_INTSTS_1MS			0x00200000
-#define OTGSC_INTSTS_DATA_PULSING		0x00400000
-#define OTGSC_INTR_USB_ID			0x01000000
-#define OTGSC_INTR_A_VBUS_VALID			0x02000000
-#define OTGSC_INTR_A_SESSION_VALID		0x04000000
-#define OTGSC_INTR_B_SESSION_VALID		0x08000000
-#define OTGSC_INTR_B_SESSION_END		0x10000000
-#define OTGSC_INTR_1MS_TIMER			0x20000000
-#define OTGSC_INTR_DATA_PULSING			0x40000000
-
-#define CAPLENGTH_MASK		(0xff)
-
-/* Timer's interval, unit 10ms */
-#define T_A_WAIT_VRISE		100
-#define T_A_WAIT_BCON		2000
-#define T_A_AIDL_BDIS		100
-#define T_A_BIDL_ADIS		20
-#define T_B_ASE0_BRST		400
-#define T_B_SE0_SRP		300
-#define T_B_SRP_FAIL		2000
-#define T_B_DATA_PLS		10
-#define T_B_SRP_INIT		100
-#define T_A_SRP_RSPNS		10
-#define T_A_DRV_RSM		5
-
-enum otg_function {
-	OTG_B_DEVICE = 0,
-	OTG_A_DEVICE
-};
-
-enum mv_otg_timer {
-	A_WAIT_BCON_TIMER = 0,
-	OTG_TIMER_NUM
-};
-
-/* PXA OTG state machine */
-struct mv_otg_ctrl {
-	/* internal variables */
-	u8 a_set_b_hnp_en;	/* A-Device set b_hnp_en */
-	u8 b_srp_done;
-	u8 b_hnp_en;
-
-	/* OTG inputs */
-	u8 a_bus_drop;
-	u8 a_bus_req;
-	u8 a_clr_err;
-	u8 a_bus_resume;
-	u8 a_bus_suspend;
-	u8 a_conn;
-	u8 a_sess_vld;
-	u8 a_srp_det;
-	u8 a_vbus_vld;
-	u8 b_bus_req;		/* B-Device Require Bus */
-	u8 b_bus_resume;
-	u8 b_bus_suspend;
-	u8 b_conn;
-	u8 b_se0_srp;
-	u8 b_sess_end;
-	u8 b_sess_vld;
-	u8 id;
-	u8 a_suspend_req;
-
-	/*Timer event */
-	u8 a_aidl_bdis_timeout;
-	u8 b_ase0_brst_timeout;
-	u8 a_bidl_adis_timeout;
-	u8 a_wait_bcon_timeout;
-
-	struct timer_list timer[OTG_TIMER_NUM];
-};
-
-#define VUSBHS_MAX_PORTS	8
-
-struct mv_otg_regs {
-	u32 usbcmd;		/* Command register */
-	u32 usbsts;		/* Status register */
-	u32 usbintr;		/* Interrupt enable */
-	u32 frindex;		/* Frame index */
-	u32 reserved1[1];
-	u32 deviceaddr;		/* Device Address */
-	u32 eplistaddr;		/* Endpoint List Address */
-	u32 ttctrl;		/* HOST TT status and control */
-	u32 burstsize;		/* Programmable Burst Size */
-	u32 txfilltuning;	/* Host Transmit Pre-Buffer Packet Tuning */
-	u32 reserved[4];
-	u32 epnak;		/* Endpoint NAK */
-	u32 epnaken;		/* Endpoint NAK Enable */
-	u32 configflag;		/* Configured Flag register */
-	u32 portsc[VUSBHS_MAX_PORTS];	/* Port Status/Control x, x = 1..8 */
-	u32 otgsc;
-	u32 usbmode;		/* USB Host/Device mode */
-	u32 epsetupstat;	/* Endpoint Setup Status */
-	u32 epprime;		/* Endpoint Initialize */
-	u32 epflush;		/* Endpoint De-initialize */
-	u32 epstatus;		/* Endpoint Status */
-	u32 epcomplete;		/* Endpoint Interrupt On Complete */
-	u32 epctrlx[16];	/* Endpoint Control, where x = 0.. 15 */
-	u32 mcr;		/* Mux Control */
-	u32 isr;		/* Interrupt Status */
-	u32 ier;		/* Interrupt Enable */
-};
-
-struct mv_otg {
-	struct usb_phy phy;
-	struct mv_otg_ctrl otg_ctrl;
-
-	/* base address */
-	void __iomem *phy_regs;
-	void __iomem *cap_regs;
-	struct mv_otg_regs __iomem *op_regs;
-
-	struct platform_device *pdev;
-	int irq;
-	u32 irq_status;
-	u32 irq_en;
-
-	struct delayed_work work;
-	struct workqueue_struct *qwork;
-
-	spinlock_t wq_lock;
-
-	struct mv_usb_platform_data *pdata;
-
-	unsigned int active;
-	unsigned int clock_gating;
-	unsigned int clknum;
-	struct clk *clk[0];
-};
-
-#endif
diff --git a/drivers/usb/otg/mxs-phy.c b/drivers/usb/otg/mxs-phy.c
deleted file mode 100644
index b0d9f11..0000000
--- a/drivers/usb/otg/mxs-phy.c
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * Copyright 2012 Freescale Semiconductor, Inc.
- * Copyright (C) 2012 Marek Vasut <marex@denx.de>
- * on behalf of DENX Software Engineering GmbH
- *
- * 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/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/usb/otg.h>
-#include <linux/stmp_device.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/io.h>
-
-#define DRIVER_NAME "mxs_phy"
-
-#define HW_USBPHY_PWD				0x00
-#define HW_USBPHY_CTRL				0x30
-#define HW_USBPHY_CTRL_SET			0x34
-#define HW_USBPHY_CTRL_CLR			0x38
-
-#define BM_USBPHY_CTRL_SFTRST			BIT(31)
-#define BM_USBPHY_CTRL_CLKGATE			BIT(30)
-#define BM_USBPHY_CTRL_ENUTMILEVEL3		BIT(15)
-#define BM_USBPHY_CTRL_ENUTMILEVEL2		BIT(14)
-#define BM_USBPHY_CTRL_ENHOSTDISCONDETECT	BIT(1)
-
-struct mxs_phy {
-	struct usb_phy phy;
-	struct clk *clk;
-};
-
-#define to_mxs_phy(p) container_of((p), struct mxs_phy, phy)
-
-static void mxs_phy_hw_init(struct mxs_phy *mxs_phy)
-{
-	void __iomem *base = mxs_phy->phy.io_priv;
-
-	stmp_reset_block(base + HW_USBPHY_CTRL);
-
-	/* Power up the PHY */
-	writel_relaxed(0, base + HW_USBPHY_PWD);
-
-	/* enable FS/LS device */
-	writel_relaxed(BM_USBPHY_CTRL_ENUTMILEVEL2 |
-			BM_USBPHY_CTRL_ENUTMILEVEL3,
-			base + HW_USBPHY_CTRL_SET);
-}
-
-static int mxs_phy_init(struct usb_phy *phy)
-{
-	struct mxs_phy *mxs_phy = to_mxs_phy(phy);
-
-	clk_prepare_enable(mxs_phy->clk);
-	mxs_phy_hw_init(mxs_phy);
-
-	return 0;
-}
-
-static void mxs_phy_shutdown(struct usb_phy *phy)
-{
-	struct mxs_phy *mxs_phy = to_mxs_phy(phy);
-
-	writel_relaxed(BM_USBPHY_CTRL_CLKGATE,
-			phy->io_priv + HW_USBPHY_CTRL_SET);
-
-	clk_disable_unprepare(mxs_phy->clk);
-}
-
-static int mxs_phy_suspend(struct usb_phy *x, int suspend)
-{
-	struct mxs_phy *mxs_phy = to_mxs_phy(x);
-
-	if (suspend) {
-		writel_relaxed(0xffffffff, x->io_priv + HW_USBPHY_PWD);
-		writel_relaxed(BM_USBPHY_CTRL_CLKGATE,
-			x->io_priv + HW_USBPHY_CTRL_SET);
-		clk_disable_unprepare(mxs_phy->clk);
-	} else {
-		clk_prepare_enable(mxs_phy->clk);
-		writel_relaxed(BM_USBPHY_CTRL_CLKGATE,
-			x->io_priv + HW_USBPHY_CTRL_CLR);
-		writel_relaxed(0, x->io_priv + HW_USBPHY_PWD);
-	}
-
-	return 0;
-}
-
-static int mxs_phy_on_connect(struct usb_phy *phy,
-		enum usb_device_speed speed)
-{
-	dev_dbg(phy->dev, "%s speed device has connected\n",
-		(speed == USB_SPEED_HIGH) ? "high" : "non-high");
-
-	if (speed == USB_SPEED_HIGH)
-		writel_relaxed(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
-				phy->io_priv + HW_USBPHY_CTRL_SET);
-
-	return 0;
-}
-
-static int mxs_phy_on_disconnect(struct usb_phy *phy,
-		enum usb_device_speed speed)
-{
-	dev_dbg(phy->dev, "%s speed device has disconnected\n",
-		(speed == USB_SPEED_HIGH) ? "high" : "non-high");
-
-	if (speed == USB_SPEED_HIGH)
-		writel_relaxed(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
-				phy->io_priv + HW_USBPHY_CTRL_CLR);
-
-	return 0;
-}
-
-static int mxs_phy_probe(struct platform_device *pdev)
-{
-	struct resource *res;
-	void __iomem *base;
-	struct clk *clk;
-	struct mxs_phy *mxs_phy;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(&pdev->dev, "can't get device resources\n");
-		return -ENOENT;
-	}
-
-	base = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(base))
-		return PTR_ERR(base);
-
-	clk = devm_clk_get(&pdev->dev, NULL);
-	if (IS_ERR(clk)) {
-		dev_err(&pdev->dev,
-			"can't get the clock, err=%ld", PTR_ERR(clk));
-		return PTR_ERR(clk);
-	}
-
-	mxs_phy = devm_kzalloc(&pdev->dev, sizeof(*mxs_phy), GFP_KERNEL);
-	if (!mxs_phy) {
-		dev_err(&pdev->dev, "Failed to allocate USB PHY structure!\n");
-		return -ENOMEM;
-	}
-
-	mxs_phy->phy.io_priv		= base;
-	mxs_phy->phy.dev		= &pdev->dev;
-	mxs_phy->phy.label		= DRIVER_NAME;
-	mxs_phy->phy.init		= mxs_phy_init;
-	mxs_phy->phy.shutdown		= mxs_phy_shutdown;
-	mxs_phy->phy.set_suspend	= mxs_phy_suspend;
-	mxs_phy->phy.notify_connect	= mxs_phy_on_connect;
-	mxs_phy->phy.notify_disconnect	= mxs_phy_on_disconnect;
-
-	ATOMIC_INIT_NOTIFIER_HEAD(&mxs_phy->phy.notifier);
-
-	mxs_phy->clk = clk;
-
-	platform_set_drvdata(pdev, &mxs_phy->phy);
-
-	return 0;
-}
-
-static int mxs_phy_remove(struct platform_device *pdev)
-{
-	platform_set_drvdata(pdev, NULL);
-
-	return 0;
-}
-
-static const struct of_device_id mxs_phy_dt_ids[] = {
-	{ .compatible = "fsl,imx23-usbphy", },
-	{ /* sentinel */ }
-};
-MODULE_DEVICE_TABLE(of, mxs_phy_dt_ids);
-
-static struct platform_driver mxs_phy_driver = {
-	.probe = mxs_phy_probe,
-	.remove = mxs_phy_remove,
-	.driver = {
-		.name = DRIVER_NAME,
-		.owner	= THIS_MODULE,
-		.of_match_table = mxs_phy_dt_ids,
-	 },
-};
-
-static int __init mxs_phy_module_init(void)
-{
-	return platform_driver_register(&mxs_phy_driver);
-}
-postcore_initcall(mxs_phy_module_init);
-
-static void __exit mxs_phy_module_exit(void)
-{
-	platform_driver_unregister(&mxs_phy_driver);
-}
-module_exit(mxs_phy_module_exit);
-
-MODULE_ALIAS("platform:mxs-usb-phy");
-MODULE_AUTHOR("Marek Vasut <marex@denx.de>");
-MODULE_AUTHOR("Richard Zhao <richard.zhao@freescale.com>");
-MODULE_DESCRIPTION("Freescale MXS USB PHY driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/usb/otg/nop-usb-xceiv.c b/drivers/usb/otg/nop-usb-xceiv.c
deleted file mode 100644
index a3ce24b..0000000
--- a/drivers/usb/otg/nop-usb-xceiv.c
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * drivers/usb/otg/nop-usb-xceiv.c
- *
- * NOP USB transceiver for all USB transceiver which are either built-in
- * into USB IP or which are mostly autonomous.
- *
- * Copyright (C) 2009 Texas Instruments Inc
- * Author: Ajay Kumar Gupta <ajay.gupta@ti.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.
- *
- * Current status:
- *	This provides a "nop" transceiver for PHYs which are
- *	autonomous such as isp1504, isp1707, etc.
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
-#include <linux/usb/otg.h>
-#include <linux/usb/nop-usb-xceiv.h>
-#include <linux/slab.h>
-
-struct nop_usb_xceiv {
-	struct usb_phy		phy;
-	struct device		*dev;
-};
-
-static struct platform_device *pd;
-
-void usb_nop_xceiv_register(void)
-{
-	if (pd)
-		return;
-	pd = platform_device_register_simple("nop_usb_xceiv", -1, NULL, 0);
-	if (!pd) {
-		printk(KERN_ERR "Unable to register usb nop transceiver\n");
-		return;
-	}
-}
-EXPORT_SYMBOL(usb_nop_xceiv_register);
-
-void usb_nop_xceiv_unregister(void)
-{
-	platform_device_unregister(pd);
-	pd = NULL;
-}
-EXPORT_SYMBOL(usb_nop_xceiv_unregister);
-
-static int nop_set_suspend(struct usb_phy *x, int suspend)
-{
-	return 0;
-}
-
-static int nop_set_peripheral(struct usb_otg *otg, struct usb_gadget *gadget)
-{
-	if (!otg)
-		return -ENODEV;
-
-	if (!gadget) {
-		otg->gadget = NULL;
-		return -ENODEV;
-	}
-
-	otg->gadget = gadget;
-	otg->phy->state = OTG_STATE_B_IDLE;
-	return 0;
-}
-
-static int nop_set_host(struct usb_otg *otg, struct usb_bus *host)
-{
-	if (!otg)
-		return -ENODEV;
-
-	if (!host) {
-		otg->host = NULL;
-		return -ENODEV;
-	}
-
-	otg->host = host;
-	return 0;
-}
-
-static int nop_usb_xceiv_probe(struct platform_device *pdev)
-{
-	struct nop_usb_xceiv_platform_data *pdata = pdev->dev.platform_data;
-	struct nop_usb_xceiv	*nop;
-	enum usb_phy_type	type = USB_PHY_TYPE_USB2;
-	int err;
-
-	nop = kzalloc(sizeof *nop, GFP_KERNEL);
-	if (!nop)
-		return -ENOMEM;
-
-	nop->phy.otg = kzalloc(sizeof *nop->phy.otg, GFP_KERNEL);
-	if (!nop->phy.otg) {
-		kfree(nop);
-		return -ENOMEM;
-	}
-
-	if (pdata)
-		type = pdata->type;
-
-	nop->dev		= &pdev->dev;
-	nop->phy.dev		= nop->dev;
-	nop->phy.label		= "nop-xceiv";
-	nop->phy.set_suspend	= nop_set_suspend;
-	nop->phy.state		= OTG_STATE_UNDEFINED;
-
-	nop->phy.otg->phy		= &nop->phy;
-	nop->phy.otg->set_host		= nop_set_host;
-	nop->phy.otg->set_peripheral	= nop_set_peripheral;
-
-	err = usb_add_phy(&nop->phy, type);
-	if (err) {
-		dev_err(&pdev->dev, "can't register transceiver, err: %d\n",
-			err);
-		goto exit;
-	}
-
-	platform_set_drvdata(pdev, nop);
-
-	ATOMIC_INIT_NOTIFIER_HEAD(&nop->phy.notifier);
-
-	return 0;
-exit:
-	kfree(nop->phy.otg);
-	kfree(nop);
-	return err;
-}
-
-static int nop_usb_xceiv_remove(struct platform_device *pdev)
-{
-	struct nop_usb_xceiv *nop = platform_get_drvdata(pdev);
-
-	usb_remove_phy(&nop->phy);
-
-	platform_set_drvdata(pdev, NULL);
-	kfree(nop->phy.otg);
-	kfree(nop);
-
-	return 0;
-}
-
-static struct platform_driver nop_usb_xceiv_driver = {
-	.probe		= nop_usb_xceiv_probe,
-	.remove		= nop_usb_xceiv_remove,
-	.driver		= {
-		.name	= "nop_usb_xceiv",
-		.owner	= THIS_MODULE,
-	},
-};
-
-static int __init nop_usb_xceiv_init(void)
-{
-	return platform_driver_register(&nop_usb_xceiv_driver);
-}
-subsys_initcall(nop_usb_xceiv_init);
-
-static void __exit nop_usb_xceiv_exit(void)
-{
-	platform_driver_unregister(&nop_usb_xceiv_driver);
-}
-module_exit(nop_usb_xceiv_exit);
-
-MODULE_ALIAS("platform:nop_usb_xceiv");
-MODULE_AUTHOR("Texas Instruments Inc");
-MODULE_DESCRIPTION("NOP USB Transceiver driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/usb/otg/otg.c b/drivers/usb/otg/otg.c
deleted file mode 100644
index 2bd03d2..0000000
--- a/drivers/usb/otg/otg.c
+++ /dev/null
@@ -1,474 +0,0 @@
-/*
- * otg.c -- USB OTG utility code
- *
- * Copyright (C) 2004 Texas Instruments
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/kernel.h>
-#include <linux/export.h>
-#include <linux/err.h>
-#include <linux/device.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/of.h>
-
-#include <linux/usb/otg.h>
-
-static LIST_HEAD(phy_list);
-static LIST_HEAD(phy_bind_list);
-static DEFINE_SPINLOCK(phy_lock);
-
-static struct usb_phy *__usb_find_phy(struct list_head *list,
-	enum usb_phy_type type)
-{
-	struct usb_phy  *phy = NULL;
-
-	list_for_each_entry(phy, list, head) {
-		if (phy->type != type)
-			continue;
-
-		return phy;
-	}
-
-	return ERR_PTR(-ENODEV);
-}
-
-static struct usb_phy *__usb_find_phy_dev(struct device *dev,
-	struct list_head *list, u8 index)
-{
-	struct usb_phy_bind *phy_bind = NULL;
-
-	list_for_each_entry(phy_bind, list, list) {
-		if (!(strcmp(phy_bind->dev_name, dev_name(dev))) &&
-				phy_bind->index == index) {
-			if (phy_bind->phy)
-				return phy_bind->phy;
-			else
-				return ERR_PTR(-EPROBE_DEFER);
-		}
-	}
-
-	return ERR_PTR(-ENODEV);
-}
-
-static struct usb_phy *__of_usb_find_phy(struct device_node *node)
-{
-	struct usb_phy  *phy;
-
-	list_for_each_entry(phy, &phy_list, head) {
-		if (node != phy->dev->of_node)
-			continue;
-
-		return phy;
-	}
-
-	return ERR_PTR(-ENODEV);
-}
-
-static void devm_usb_phy_release(struct device *dev, void *res)
-{
-	struct usb_phy *phy = *(struct usb_phy **)res;
-
-	usb_put_phy(phy);
-}
-
-static int devm_usb_phy_match(struct device *dev, void *res, void *match_data)
-{
-	return res == match_data;
-}
-
-/**
- * devm_usb_get_phy - find the USB PHY
- * @dev - device that requests this phy
- * @type - the type of the phy the controller requires
- *
- * Gets the phy using usb_get_phy(), and associates a device with it using
- * devres. On driver detach, release function is invoked on the devres data,
- * then, devres data is freed.
- *
- * For use by USB host and peripheral drivers.
- */
-struct usb_phy *devm_usb_get_phy(struct device *dev, enum usb_phy_type type)
-{
-	struct usb_phy **ptr, *phy;
-
-	ptr = devres_alloc(devm_usb_phy_release, sizeof(*ptr), GFP_KERNEL);
-	if (!ptr)
-		return NULL;
-
-	phy = usb_get_phy(type);
-	if (!IS_ERR(phy)) {
-		*ptr = phy;
-		devres_add(dev, ptr);
-	} else
-		devres_free(ptr);
-
-	return phy;
-}
-EXPORT_SYMBOL(devm_usb_get_phy);
-
-/**
- * usb_get_phy - find the USB PHY
- * @type - the type of the phy the controller requires
- *
- * Returns the phy driver, after getting a refcount to it; or
- * -ENODEV if there is no such phy.  The caller is responsible for
- * calling usb_put_phy() to release that count.
- *
- * For use by USB host and peripheral drivers.
- */
-struct usb_phy *usb_get_phy(enum usb_phy_type type)
-{
-	struct usb_phy	*phy = NULL;
-	unsigned long	flags;
-
-	spin_lock_irqsave(&phy_lock, flags);
-
-	phy = __usb_find_phy(&phy_list, type);
-	if (IS_ERR(phy) || !try_module_get(phy->dev->driver->owner)) {
-		pr_err("unable to find transceiver of type %s\n",
-			usb_phy_type_string(type));
-		goto err0;
-	}
-
-	get_device(phy->dev);
-
-err0:
-	spin_unlock_irqrestore(&phy_lock, flags);
-
-	return phy;
-}
-EXPORT_SYMBOL(usb_get_phy);
-
- /**
- * devm_usb_get_phy_by_phandle - find the USB PHY by phandle
- * @dev - device that requests this phy
- * @phandle - name of the property holding the phy phandle value
- * @index - the index of the phy
- *
- * Returns the phy driver associated with the given phandle value,
- * after getting a refcount to it, -ENODEV if there is no such phy or
- * -EPROBE_DEFER if there is a phandle to the phy, but the device is
- * not yet loaded. While at that, it also associates the device with
- * the phy using devres. On driver detach, release function is invoked
- * on the devres data, then, devres data is freed.
- *
- * For use by USB host and peripheral drivers.
- */
-struct usb_phy *devm_usb_get_phy_by_phandle(struct device *dev,
-	const char *phandle, u8 index)
-{
-	struct usb_phy	*phy = ERR_PTR(-ENOMEM), **ptr;
-	unsigned long	flags;
-	struct device_node *node;
-
-	if (!dev->of_node) {
-		dev_dbg(dev, "device does not have a device node entry\n");
-		return ERR_PTR(-EINVAL);
-	}
-
-	node = of_parse_phandle(dev->of_node, phandle, index);
-	if (!node) {
-		dev_dbg(dev, "failed to get %s phandle in %s node\n", phandle,
-			dev->of_node->full_name);
-		return ERR_PTR(-ENODEV);
-	}
-
-	ptr = devres_alloc(devm_usb_phy_release, sizeof(*ptr), GFP_KERNEL);
-	if (!ptr) {
-		dev_dbg(dev, "failed to allocate memory for devres\n");
-		goto err0;
-	}
-
-	spin_lock_irqsave(&phy_lock, flags);
-
-	phy = __of_usb_find_phy(node);
-	if (IS_ERR(phy) || !try_module_get(phy->dev->driver->owner)) {
-		phy = ERR_PTR(-EPROBE_DEFER);
-		devres_free(ptr);
-		goto err1;
-	}
-
-	*ptr = phy;
-	devres_add(dev, ptr);
-
-	get_device(phy->dev);
-
-err1:
-	spin_unlock_irqrestore(&phy_lock, flags);
-
-err0:
-	of_node_put(node);
-
-	return phy;
-}
-EXPORT_SYMBOL(devm_usb_get_phy_by_phandle);
-
-/**
- * usb_get_phy_dev - find the USB PHY
- * @dev - device that requests this phy
- * @index - the index of the phy
- *
- * Returns the phy driver, after getting a refcount to it; or
- * -ENODEV if there is no such phy.  The caller is responsible for
- * calling usb_put_phy() to release that count.
- *
- * For use by USB host and peripheral drivers.
- */
-struct usb_phy *usb_get_phy_dev(struct device *dev, u8 index)
-{
-	struct usb_phy	*phy = NULL;
-	unsigned long	flags;
-
-	spin_lock_irqsave(&phy_lock, flags);
-
-	phy = __usb_find_phy_dev(dev, &phy_bind_list, index);
-	if (IS_ERR(phy) || !try_module_get(phy->dev->driver->owner)) {
-		pr_err("unable to find transceiver\n");
-		goto err0;
-	}
-
-	get_device(phy->dev);
-
-err0:
-	spin_unlock_irqrestore(&phy_lock, flags);
-
-	return phy;
-}
-EXPORT_SYMBOL(usb_get_phy_dev);
-
-/**
- * devm_usb_get_phy_dev - find the USB PHY using device ptr and index
- * @dev - device that requests this phy
- * @index - the index of the phy
- *
- * Gets the phy using usb_get_phy_dev(), and associates a device with it using
- * devres. On driver detach, release function is invoked on the devres data,
- * then, devres data is freed.
- *
- * For use by USB host and peripheral drivers.
- */
-struct usb_phy *devm_usb_get_phy_dev(struct device *dev, u8 index)
-{
-	struct usb_phy **ptr, *phy;
-
-	ptr = devres_alloc(devm_usb_phy_release, sizeof(*ptr), GFP_KERNEL);
-	if (!ptr)
-		return NULL;
-
-	phy = usb_get_phy_dev(dev, index);
-	if (!IS_ERR(phy)) {
-		*ptr = phy;
-		devres_add(dev, ptr);
-	} else
-		devres_free(ptr);
-
-	return phy;
-}
-EXPORT_SYMBOL(devm_usb_get_phy_dev);
-
-/**
- * devm_usb_put_phy - release the USB PHY
- * @dev - device that wants to release this phy
- * @phy - the phy returned by devm_usb_get_phy()
- *
- * destroys the devres associated with this phy and invokes usb_put_phy
- * to release the phy.
- *
- * For use by USB host and peripheral drivers.
- */
-void devm_usb_put_phy(struct device *dev, struct usb_phy *phy)
-{
-	int r;
-
-	r = devres_destroy(dev, devm_usb_phy_release, devm_usb_phy_match, phy);
-	dev_WARN_ONCE(dev, r, "couldn't find PHY resource\n");
-}
-EXPORT_SYMBOL(devm_usb_put_phy);
-
-/**
- * usb_put_phy - release the USB PHY
- * @x: the phy returned by usb_get_phy()
- *
- * Releases a refcount the caller received from usb_get_phy().
- *
- * For use by USB host and peripheral drivers.
- */
-void usb_put_phy(struct usb_phy *x)
-{
-	if (x) {
-		struct module *owner = x->dev->driver->owner;
-
-		put_device(x->dev);
-		module_put(owner);
-	}
-}
-EXPORT_SYMBOL(usb_put_phy);
-
-/**
- * usb_add_phy - declare the USB PHY
- * @x: the USB phy to be used; or NULL
- * @type - the type of this PHY
- *
- * This call is exclusively for use by phy drivers, which
- * coordinate the activities of drivers for host and peripheral
- * controllers, and in some cases for VBUS current regulation.
- */
-int usb_add_phy(struct usb_phy *x, enum usb_phy_type type)
-{
-	int		ret = 0;
-	unsigned long	flags;
-	struct usb_phy	*phy;
-
-	if (x->type != USB_PHY_TYPE_UNDEFINED) {
-		dev_err(x->dev, "not accepting initialized PHY %s\n", x->label);
-		return -EINVAL;
-	}
-
-	spin_lock_irqsave(&phy_lock, flags);
-
-	list_for_each_entry(phy, &phy_list, head) {
-		if (phy->type == type) {
-			ret = -EBUSY;
-			dev_err(x->dev, "transceiver type %s already exists\n",
-						usb_phy_type_string(type));
-			goto out;
-		}
-	}
-
-	x->type = type;
-	list_add_tail(&x->head, &phy_list);
-
-out:
-	spin_unlock_irqrestore(&phy_lock, flags);
-	return ret;
-}
-EXPORT_SYMBOL(usb_add_phy);
-
-/**
- * usb_add_phy_dev - declare the USB PHY
- * @x: the USB phy to be used; or NULL
- *
- * This call is exclusively for use by phy drivers, which
- * coordinate the activities of drivers for host and peripheral
- * controllers, and in some cases for VBUS current regulation.
- */
-int usb_add_phy_dev(struct usb_phy *x)
-{
-	struct usb_phy_bind *phy_bind;
-	unsigned long flags;
-
-	if (!x->dev) {
-		dev_err(x->dev, "no device provided for PHY\n");
-		return -EINVAL;
-	}
-
-	spin_lock_irqsave(&phy_lock, flags);
-	list_for_each_entry(phy_bind, &phy_bind_list, list)
-		if (!(strcmp(phy_bind->phy_dev_name, dev_name(x->dev))))
-			phy_bind->phy = x;
-
-	list_add_tail(&x->head, &phy_list);
-
-	spin_unlock_irqrestore(&phy_lock, flags);
-	return 0;
-}
-EXPORT_SYMBOL(usb_add_phy_dev);
-
-/**
- * usb_remove_phy - remove the OTG PHY
- * @x: the USB OTG PHY to be removed;
- *
- * This reverts the effects of usb_add_phy
- */
-void usb_remove_phy(struct usb_phy *x)
-{
-	unsigned long	flags;
-	struct usb_phy_bind *phy_bind;
-
-	spin_lock_irqsave(&phy_lock, flags);
-	if (x) {
-		list_for_each_entry(phy_bind, &phy_bind_list, list)
-			if (phy_bind->phy == x)
-				phy_bind->phy = NULL;
-		list_del(&x->head);
-	}
-	spin_unlock_irqrestore(&phy_lock, flags);
-}
-EXPORT_SYMBOL(usb_remove_phy);
-
-/**
- * usb_bind_phy - bind the phy and the controller that uses the phy
- * @dev_name: the device name of the device that will bind to the phy
- * @index: index to specify the port number
- * @phy_dev_name: the device name of the phy
- *
- * Fills the phy_bind structure with the dev_name and phy_dev_name. This will
- * be used when the phy driver registers the phy and when the controller
- * requests this phy.
- *
- * To be used by platform specific initialization code.
- */
-int __init usb_bind_phy(const char *dev_name, u8 index,
-				const char *phy_dev_name)
-{
-	struct usb_phy_bind *phy_bind;
-	unsigned long flags;
-
-	phy_bind = kzalloc(sizeof(*phy_bind), GFP_KERNEL);
-	if (!phy_bind) {
-		pr_err("phy_bind(): No memory for phy_bind");
-		return -ENOMEM;
-	}
-
-	phy_bind->dev_name = dev_name;
-	phy_bind->phy_dev_name = phy_dev_name;
-	phy_bind->index = index;
-
-	spin_lock_irqsave(&phy_lock, flags);
-	list_add_tail(&phy_bind->list, &phy_bind_list);
-	spin_unlock_irqrestore(&phy_lock, flags);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(usb_bind_phy);
-
-const char *otg_state_string(enum usb_otg_state state)
-{
-	switch (state) {
-	case OTG_STATE_A_IDLE:
-		return "a_idle";
-	case OTG_STATE_A_WAIT_VRISE:
-		return "a_wait_vrise";
-	case OTG_STATE_A_WAIT_BCON:
-		return "a_wait_bcon";
-	case OTG_STATE_A_HOST:
-		return "a_host";
-	case OTG_STATE_A_SUSPEND:
-		return "a_suspend";
-	case OTG_STATE_A_PERIPHERAL:
-		return "a_peripheral";
-	case OTG_STATE_A_WAIT_VFALL:
-		return "a_wait_vfall";
-	case OTG_STATE_A_VBUS_ERR:
-		return "a_vbus_err";
-	case OTG_STATE_B_IDLE:
-		return "b_idle";
-	case OTG_STATE_B_SRP_INIT:
-		return "b_srp_init";
-	case OTG_STATE_B_PERIPHERAL:
-		return "b_peripheral";
-	case OTG_STATE_B_WAIT_ACON:
-		return "b_wait_acon";
-	case OTG_STATE_B_HOST:
-		return "b_host";
-	default:
-		return "UNDEFINED";
-	}
-}
-EXPORT_SYMBOL(otg_state_string);
diff --git a/drivers/usb/otg/otg_fsm.c b/drivers/usb/otg/otg_fsm.c
deleted file mode 100644
index ade131a..0000000
--- a/drivers/usb/otg/otg_fsm.c
+++ /dev/null
@@ -1,348 +0,0 @@
-/*
- * OTG Finite State Machine from OTG spec
- *
- * Copyright (C) 2007,2008 Freescale Semiconductor, Inc.
- *
- * Author:	Li Yang <LeoLi@freescale.com>
- *		Jerry Huang <Chang-Ming.Huang@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.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You 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/types.h>
-#include <linux/spinlock.h>
-#include <linux/delay.h>
-#include <linux/usb.h>
-#include <linux/usb/gadget.h>
-#include <linux/usb/otg.h>
-
-#include "otg_fsm.h"
-
-/* Change USB protocol when there is a protocol change */
-static int otg_set_protocol(struct otg_fsm *fsm, int protocol)
-{
-	int ret = 0;
-
-	if (fsm->protocol != protocol) {
-		VDBG("Changing role fsm->protocol= %d; new protocol= %d\n",
-			fsm->protocol, protocol);
-		/* stop old protocol */
-		if (fsm->protocol == PROTO_HOST)
-			ret = fsm->ops->start_host(fsm, 0);
-		else if (fsm->protocol == PROTO_GADGET)
-			ret = fsm->ops->start_gadget(fsm, 0);
-		if (ret)
-			return ret;
-
-		/* start new protocol */
-		if (protocol == PROTO_HOST)
-			ret = fsm->ops->start_host(fsm, 1);
-		else if (protocol == PROTO_GADGET)
-			ret = fsm->ops->start_gadget(fsm, 1);
-		if (ret)
-			return ret;
-
-		fsm->protocol = protocol;
-		return 0;
-	}
-
-	return 0;
-}
-
-static int state_changed;
-
-/* Called when leaving a state.  Do state clean up jobs here */
-void otg_leave_state(struct otg_fsm *fsm, enum usb_otg_state old_state)
-{
-	switch (old_state) {
-	case OTG_STATE_B_IDLE:
-		otg_del_timer(fsm, b_se0_srp_tmr);
-		fsm->b_se0_srp = 0;
-		break;
-	case OTG_STATE_B_SRP_INIT:
-		fsm->b_srp_done = 0;
-		break;
-	case OTG_STATE_B_PERIPHERAL:
-		break;
-	case OTG_STATE_B_WAIT_ACON:
-		otg_del_timer(fsm, b_ase0_brst_tmr);
-		fsm->b_ase0_brst_tmout = 0;
-		break;
-	case OTG_STATE_B_HOST:
-		break;
-	case OTG_STATE_A_IDLE:
-		break;
-	case OTG_STATE_A_WAIT_VRISE:
-		otg_del_timer(fsm, a_wait_vrise_tmr);
-		fsm->a_wait_vrise_tmout = 0;
-		break;
-	case OTG_STATE_A_WAIT_BCON:
-		otg_del_timer(fsm, a_wait_bcon_tmr);
-		fsm->a_wait_bcon_tmout = 0;
-		break;
-	case OTG_STATE_A_HOST:
-		otg_del_timer(fsm, a_wait_enum_tmr);
-		break;
-	case OTG_STATE_A_SUSPEND:
-		otg_del_timer(fsm, a_aidl_bdis_tmr);
-		fsm->a_aidl_bdis_tmout = 0;
-		fsm->a_suspend_req = 0;
-		break;
-	case OTG_STATE_A_PERIPHERAL:
-		break;
-	case OTG_STATE_A_WAIT_VFALL:
-		otg_del_timer(fsm, a_wait_vrise_tmr);
-		break;
-	case OTG_STATE_A_VBUS_ERR:
-		break;
-	default:
-		break;
-	}
-}
-
-/* Called when entering a state */
-int otg_set_state(struct otg_fsm *fsm, enum usb_otg_state new_state)
-{
-	state_changed = 1;
-	if (fsm->otg->phy->state == new_state)
-		return 0;
-	VDBG("Set state: %s\n", otg_state_string(new_state));
-	otg_leave_state(fsm, fsm->otg->phy->state);
-	switch (new_state) {
-	case OTG_STATE_B_IDLE:
-		otg_drv_vbus(fsm, 0);
-		otg_chrg_vbus(fsm, 0);
-		otg_loc_conn(fsm, 0);
-		otg_loc_sof(fsm, 0);
-		otg_set_protocol(fsm, PROTO_UNDEF);
-		otg_add_timer(fsm, b_se0_srp_tmr);
-		break;
-	case OTG_STATE_B_SRP_INIT:
-		otg_start_pulse(fsm);
-		otg_loc_sof(fsm, 0);
-		otg_set_protocol(fsm, PROTO_UNDEF);
-		otg_add_timer(fsm, b_srp_fail_tmr);
-		break;
-	case OTG_STATE_B_PERIPHERAL:
-		otg_chrg_vbus(fsm, 0);
-		otg_loc_conn(fsm, 1);
-		otg_loc_sof(fsm, 0);
-		otg_set_protocol(fsm, PROTO_GADGET);
-		break;
-	case OTG_STATE_B_WAIT_ACON:
-		otg_chrg_vbus(fsm, 0);
-		otg_loc_conn(fsm, 0);
-		otg_loc_sof(fsm, 0);
-		otg_set_protocol(fsm, PROTO_HOST);
-		otg_add_timer(fsm, b_ase0_brst_tmr);
-		fsm->a_bus_suspend = 0;
-		break;
-	case OTG_STATE_B_HOST:
-		otg_chrg_vbus(fsm, 0);
-		otg_loc_conn(fsm, 0);
-		otg_loc_sof(fsm, 1);
-		otg_set_protocol(fsm, PROTO_HOST);
-		usb_bus_start_enum(fsm->otg->host,
-				fsm->otg->host->otg_port);
-		break;
-	case OTG_STATE_A_IDLE:
-		otg_drv_vbus(fsm, 0);
-		otg_chrg_vbus(fsm, 0);
-		otg_loc_conn(fsm, 0);
-		otg_loc_sof(fsm, 0);
-		otg_set_protocol(fsm, PROTO_HOST);
-		break;
-	case OTG_STATE_A_WAIT_VRISE:
-		otg_drv_vbus(fsm, 1);
-		otg_loc_conn(fsm, 0);
-		otg_loc_sof(fsm, 0);
-		otg_set_protocol(fsm, PROTO_HOST);
-		otg_add_timer(fsm, a_wait_vrise_tmr);
-		break;
-	case OTG_STATE_A_WAIT_BCON:
-		otg_drv_vbus(fsm, 1);
-		otg_loc_conn(fsm, 0);
-		otg_loc_sof(fsm, 0);
-		otg_set_protocol(fsm, PROTO_HOST);
-		otg_add_timer(fsm, a_wait_bcon_tmr);
-		break;
-	case OTG_STATE_A_HOST:
-		otg_drv_vbus(fsm, 1);
-		otg_loc_conn(fsm, 0);
-		otg_loc_sof(fsm, 1);
-		otg_set_protocol(fsm, PROTO_HOST);
-		/*
-		 * When HNP is triggered while a_bus_req = 0, a_host will
-		 * suspend too fast to complete a_set_b_hnp_en
-		 */
-		if (!fsm->a_bus_req || fsm->a_suspend_req)
-			otg_add_timer(fsm, a_wait_enum_tmr);
-		break;
-	case OTG_STATE_A_SUSPEND:
-		otg_drv_vbus(fsm, 1);
-		otg_loc_conn(fsm, 0);
-		otg_loc_sof(fsm, 0);
-		otg_set_protocol(fsm, PROTO_HOST);
-		otg_add_timer(fsm, a_aidl_bdis_tmr);
-
-		break;
-	case OTG_STATE_A_PERIPHERAL:
-		otg_loc_conn(fsm, 1);
-		otg_loc_sof(fsm, 0);
-		otg_set_protocol(fsm, PROTO_GADGET);
-		otg_drv_vbus(fsm, 1);
-		break;
-	case OTG_STATE_A_WAIT_VFALL:
-		otg_drv_vbus(fsm, 0);
-		otg_loc_conn(fsm, 0);
-		otg_loc_sof(fsm, 0);
-		otg_set_protocol(fsm, PROTO_HOST);
-		break;
-	case OTG_STATE_A_VBUS_ERR:
-		otg_drv_vbus(fsm, 0);
-		otg_loc_conn(fsm, 0);
-		otg_loc_sof(fsm, 0);
-		otg_set_protocol(fsm, PROTO_UNDEF);
-		break;
-	default:
-		break;
-	}
-
-	fsm->otg->phy->state = new_state;
-	return 0;
-}
-
-/* State change judgement */
-int otg_statemachine(struct otg_fsm *fsm)
-{
-	enum usb_otg_state state;
-	unsigned long flags;
-
-	spin_lock_irqsave(&fsm->lock, flags);
-
-	state = fsm->otg->phy->state;
-	state_changed = 0;
-	/* State machine state change judgement */
-
-	switch (state) {
-	case OTG_STATE_UNDEFINED:
-		VDBG("fsm->id = %d\n", fsm->id);
-		if (fsm->id)
-			otg_set_state(fsm, OTG_STATE_B_IDLE);
-		else
-			otg_set_state(fsm, OTG_STATE_A_IDLE);
-		break;
-	case OTG_STATE_B_IDLE:
-		if (!fsm->id)
-			otg_set_state(fsm, OTG_STATE_A_IDLE);
-		else if (fsm->b_sess_vld && fsm->otg->gadget)
-			otg_set_state(fsm, OTG_STATE_B_PERIPHERAL);
-		else if (fsm->b_bus_req && fsm->b_sess_end && fsm->b_se0_srp)
-			otg_set_state(fsm, OTG_STATE_B_SRP_INIT);
-		break;
-	case OTG_STATE_B_SRP_INIT:
-		if (!fsm->id || fsm->b_srp_done)
-			otg_set_state(fsm, OTG_STATE_B_IDLE);
-		break;
-	case OTG_STATE_B_PERIPHERAL:
-		if (!fsm->id || !fsm->b_sess_vld)
-			otg_set_state(fsm, OTG_STATE_B_IDLE);
-		else if (fsm->b_bus_req && fsm->otg->
-				gadget->b_hnp_enable && fsm->a_bus_suspend)
-			otg_set_state(fsm, OTG_STATE_B_WAIT_ACON);
-		break;
-	case OTG_STATE_B_WAIT_ACON:
-		if (fsm->a_conn)
-			otg_set_state(fsm, OTG_STATE_B_HOST);
-		else if (!fsm->id || !fsm->b_sess_vld)
-			otg_set_state(fsm, OTG_STATE_B_IDLE);
-		else if (fsm->a_bus_resume || fsm->b_ase0_brst_tmout) {
-			fsm->b_ase0_brst_tmout = 0;
-			otg_set_state(fsm, OTG_STATE_B_PERIPHERAL);
-		}
-		break;
-	case OTG_STATE_B_HOST:
-		if (!fsm->id || !fsm->b_sess_vld)
-			otg_set_state(fsm, OTG_STATE_B_IDLE);
-		else if (!fsm->b_bus_req || !fsm->a_conn)
-			otg_set_state(fsm, OTG_STATE_B_PERIPHERAL);
-		break;
-	case OTG_STATE_A_IDLE:
-		if (fsm->id)
-			otg_set_state(fsm, OTG_STATE_B_IDLE);
-		else if (!fsm->a_bus_drop && (fsm->a_bus_req || fsm->a_srp_det))
-			otg_set_state(fsm, OTG_STATE_A_WAIT_VRISE);
-		break;
-	case OTG_STATE_A_WAIT_VRISE:
-		if (fsm->id || fsm->a_bus_drop || fsm->a_vbus_vld ||
-				fsm->a_wait_vrise_tmout) {
-			otg_set_state(fsm, OTG_STATE_A_WAIT_BCON);
-		}
-		break;
-	case OTG_STATE_A_WAIT_BCON:
-		if (!fsm->a_vbus_vld)
-			otg_set_state(fsm, OTG_STATE_A_VBUS_ERR);
-		else if (fsm->b_conn)
-			otg_set_state(fsm, OTG_STATE_A_HOST);
-		else if (fsm->id | fsm->a_bus_drop | fsm->a_wait_bcon_tmout)
-			otg_set_state(fsm, OTG_STATE_A_WAIT_VFALL);
-		break;
-	case OTG_STATE_A_HOST:
-		if ((!fsm->a_bus_req || fsm->a_suspend_req) &&
-				fsm->otg->host->b_hnp_enable)
-			otg_set_state(fsm, OTG_STATE_A_SUSPEND);
-		else if (fsm->id || !fsm->b_conn || fsm->a_bus_drop)
-			otg_set_state(fsm, OTG_STATE_A_WAIT_BCON);
-		else if (!fsm->a_vbus_vld)
-			otg_set_state(fsm, OTG_STATE_A_VBUS_ERR);
-		break;
-	case OTG_STATE_A_SUSPEND:
-		if (!fsm->b_conn && fsm->otg->host->b_hnp_enable)
-			otg_set_state(fsm, OTG_STATE_A_PERIPHERAL);
-		else if (!fsm->b_conn && !fsm->otg->host->b_hnp_enable)
-			otg_set_state(fsm, OTG_STATE_A_WAIT_BCON);
-		else if (fsm->a_bus_req || fsm->b_bus_resume)
-			otg_set_state(fsm, OTG_STATE_A_HOST);
-		else if (fsm->id || fsm->a_bus_drop || fsm->a_aidl_bdis_tmout)
-			otg_set_state(fsm, OTG_STATE_A_WAIT_VFALL);
-		else if (!fsm->a_vbus_vld)
-			otg_set_state(fsm, OTG_STATE_A_VBUS_ERR);
-		break;
-	case OTG_STATE_A_PERIPHERAL:
-		if (fsm->id || fsm->a_bus_drop)
-			otg_set_state(fsm, OTG_STATE_A_WAIT_VFALL);
-		else if (fsm->b_bus_suspend)
-			otg_set_state(fsm, OTG_STATE_A_WAIT_BCON);
-		else if (!fsm->a_vbus_vld)
-			otg_set_state(fsm, OTG_STATE_A_VBUS_ERR);
-		break;
-	case OTG_STATE_A_WAIT_VFALL:
-		if (fsm->id || fsm->a_bus_req || (!fsm->a_sess_vld &&
-					!fsm->b_conn))
-			otg_set_state(fsm, OTG_STATE_A_IDLE);
-		break;
-	case OTG_STATE_A_VBUS_ERR:
-		if (fsm->id || fsm->a_bus_drop || fsm->a_clr_err)
-			otg_set_state(fsm, OTG_STATE_A_WAIT_VFALL);
-		break;
-	default:
-		break;
-	}
-	spin_unlock_irqrestore(&fsm->lock, flags);
-
-	VDBG("quit statemachine, changed = %d\n", state_changed);
-	return state_changed;
-}
diff --git a/drivers/usb/otg/otg_fsm.h b/drivers/usb/otg/otg_fsm.h
deleted file mode 100644
index c30a2e1..0000000
--- a/drivers/usb/otg/otg_fsm.h
+++ /dev/null
@@ -1,154 +0,0 @@
-/* Copyright (C) 2007,2008 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.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You 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.
- */
-
-#undef DEBUG
-#undef VERBOSE
-
-#ifdef DEBUG
-#define DBG(fmt, args...) printk(KERN_DEBUG "[%s]  " fmt , \
-				 __func__, ## args)
-#else
-#define DBG(fmt, args...)	do {} while (0)
-#endif
-
-#ifdef VERBOSE
-#define VDBG		DBG
-#else
-#define VDBG(stuff...)	do {} while (0)
-#endif
-
-#ifdef VERBOSE
-#define MPC_LOC printk("Current Location [%s]:[%d]\n", __FILE__, __LINE__)
-#else
-#define MPC_LOC do {} while (0)
-#endif
-
-#define PROTO_UNDEF	(0)
-#define PROTO_HOST	(1)
-#define PROTO_GADGET	(2)
-
-/* OTG state machine according to the OTG spec */
-struct otg_fsm {
-	/* Input */
-	int a_bus_resume;
-	int a_bus_suspend;
-	int a_conn;
-	int a_sess_vld;
-	int a_srp_det;
-	int a_vbus_vld;
-	int b_bus_resume;
-	int b_bus_suspend;
-	int b_conn;
-	int b_se0_srp;
-	int b_sess_end;
-	int b_sess_vld;
-	int id;
-
-	/* Internal variables */
-	int a_set_b_hnp_en;
-	int b_srp_done;
-	int b_hnp_enable;
-
-	/* Timeout indicator for timers */
-	int a_wait_vrise_tmout;
-	int a_wait_bcon_tmout;
-	int a_aidl_bdis_tmout;
-	int b_ase0_brst_tmout;
-
-	/* Informative variables */
-	int a_bus_drop;
-	int a_bus_req;
-	int a_clr_err;
-	int a_suspend_req;
-	int b_bus_req;
-
-	/* Output */
-	int drv_vbus;
-	int loc_conn;
-	int loc_sof;
-
-	struct otg_fsm_ops *ops;
-	struct usb_otg *otg;
-
-	/* Current usb protocol used: 0:undefine; 1:host; 2:client */
-	int protocol;
-	spinlock_t lock;
-};
-
-struct otg_fsm_ops {
-	void	(*chrg_vbus)(int on);
-	void	(*drv_vbus)(int on);
-	void	(*loc_conn)(int on);
-	void	(*loc_sof)(int on);
-	void	(*start_pulse)(void);
-	void	(*add_timer)(void *timer);
-	void	(*del_timer)(void *timer);
-	int	(*start_host)(struct otg_fsm *fsm, int on);
-	int	(*start_gadget)(struct otg_fsm *fsm, int on);
-};
-
-
-static inline void otg_chrg_vbus(struct otg_fsm *fsm, int on)
-{
-	fsm->ops->chrg_vbus(on);
-}
-
-static inline void otg_drv_vbus(struct otg_fsm *fsm, int on)
-{
-	if (fsm->drv_vbus != on) {
-		fsm->drv_vbus = on;
-		fsm->ops->drv_vbus(on);
-	}
-}
-
-static inline void otg_loc_conn(struct otg_fsm *fsm, int on)
-{
-	if (fsm->loc_conn != on) {
-		fsm->loc_conn = on;
-		fsm->ops->loc_conn(on);
-	}
-}
-
-static inline void otg_loc_sof(struct otg_fsm *fsm, int on)
-{
-	if (fsm->loc_sof != on) {
-		fsm->loc_sof = on;
-		fsm->ops->loc_sof(on);
-	}
-}
-
-static inline void otg_start_pulse(struct otg_fsm *fsm)
-{
-	fsm->ops->start_pulse();
-}
-
-static inline void otg_add_timer(struct otg_fsm *fsm, void *timer)
-{
-	fsm->ops->add_timer(timer);
-}
-
-static inline void otg_del_timer(struct otg_fsm *fsm, void *timer)
-{
-	fsm->ops->del_timer(timer);
-}
-
-int otg_statemachine(struct otg_fsm *fsm);
-
-/* Defined by device specific driver, for different timer implementation */
-extern struct fsl_otg_timer *a_wait_vrise_tmr, *a_wait_bcon_tmr,
-	*a_aidl_bdis_tmr, *b_ase0_brst_tmr, *b_se0_srp_tmr, *b_srp_fail_tmr,
-	*a_wait_enum_tmr;
diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c
deleted file mode 100644
index a994715..0000000
--- a/drivers/usb/otg/twl4030-usb.c
+++ /dev/null
@@ -1,728 +0,0 @@
-/*
- * twl4030_usb - TWL4030 USB transceiver, talking to OMAP OTG controller
- *
- * Copyright (C) 2004-2007 Texas Instruments
- * Copyright (C) 2008 Nokia Corporation
- * Contact: Felipe Balbi <felipe.balbi@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., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Current status:
- *	- HS USB ULPI mode works.
- *	- 3-pin mode support may be added in future.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/spinlock.h>
-#include <linux/workqueue.h>
-#include <linux/io.h>
-#include <linux/delay.h>
-#include <linux/usb/otg.h>
-#include <linux/usb/musb-omap.h>
-#include <linux/usb/ulpi.h>
-#include <linux/i2c/twl.h>
-#include <linux/regulator/consumer.h>
-#include <linux/err.h>
-#include <linux/slab.h>
-
-/* Register defines */
-
-#define MCPC_CTRL			0x30
-#define MCPC_CTRL_RTSOL			(1 << 7)
-#define MCPC_CTRL_EXTSWR		(1 << 6)
-#define MCPC_CTRL_EXTSWC		(1 << 5)
-#define MCPC_CTRL_VOICESW		(1 << 4)
-#define MCPC_CTRL_OUT64K		(1 << 3)
-#define MCPC_CTRL_RTSCTSSW		(1 << 2)
-#define MCPC_CTRL_HS_UART		(1 << 0)
-
-#define MCPC_IO_CTRL			0x33
-#define MCPC_IO_CTRL_MICBIASEN		(1 << 5)
-#define MCPC_IO_CTRL_CTS_NPU		(1 << 4)
-#define MCPC_IO_CTRL_RXD_PU		(1 << 3)
-#define MCPC_IO_CTRL_TXDTYP		(1 << 2)
-#define MCPC_IO_CTRL_CTSTYP		(1 << 1)
-#define MCPC_IO_CTRL_RTSTYP		(1 << 0)
-
-#define MCPC_CTRL2			0x36
-#define MCPC_CTRL2_MCPC_CK_EN		(1 << 0)
-
-#define OTHER_FUNC_CTRL			0x80
-#define OTHER_FUNC_CTRL_BDIS_ACON_EN	(1 << 4)
-#define OTHER_FUNC_CTRL_FIVEWIRE_MODE	(1 << 2)
-
-#define OTHER_IFC_CTRL			0x83
-#define OTHER_IFC_CTRL_OE_INT_EN	(1 << 6)
-#define OTHER_IFC_CTRL_CEA2011_MODE	(1 << 5)
-#define OTHER_IFC_CTRL_FSLSSERIALMODE_4PIN	(1 << 4)
-#define OTHER_IFC_CTRL_HIZ_ULPI_60MHZ_OUT	(1 << 3)
-#define OTHER_IFC_CTRL_HIZ_ULPI		(1 << 2)
-#define OTHER_IFC_CTRL_ALT_INT_REROUTE	(1 << 0)
-
-#define OTHER_INT_EN_RISE		0x86
-#define OTHER_INT_EN_FALL		0x89
-#define OTHER_INT_STS			0x8C
-#define OTHER_INT_LATCH			0x8D
-#define OTHER_INT_VB_SESS_VLD		(1 << 7)
-#define OTHER_INT_DM_HI			(1 << 6) /* not valid for "latch" reg */
-#define OTHER_INT_DP_HI			(1 << 5) /* not valid for "latch" reg */
-#define OTHER_INT_BDIS_ACON		(1 << 3) /* not valid for "fall" regs */
-#define OTHER_INT_MANU			(1 << 1)
-#define OTHER_INT_ABNORMAL_STRESS	(1 << 0)
-
-#define ID_STATUS			0x96
-#define ID_RES_FLOAT			(1 << 4)
-#define ID_RES_440K			(1 << 3)
-#define ID_RES_200K			(1 << 2)
-#define ID_RES_102K			(1 << 1)
-#define ID_RES_GND			(1 << 0)
-
-#define POWER_CTRL			0xAC
-#define POWER_CTRL_OTG_ENAB		(1 << 5)
-
-#define OTHER_IFC_CTRL2			0xAF
-#define OTHER_IFC_CTRL2_ULPI_STP_LOW	(1 << 4)
-#define OTHER_IFC_CTRL2_ULPI_TXEN_POL	(1 << 3)
-#define OTHER_IFC_CTRL2_ULPI_4PIN_2430	(1 << 2)
-#define OTHER_IFC_CTRL2_USB_INT_OUTSEL_MASK	(3 << 0) /* bits 0 and 1 */
-#define OTHER_IFC_CTRL2_USB_INT_OUTSEL_INT1N	(0 << 0)
-#define OTHER_IFC_CTRL2_USB_INT_OUTSEL_INT2N	(1 << 0)
-
-#define REG_CTRL_EN			0xB2
-#define REG_CTRL_ERROR			0xB5
-#define ULPI_I2C_CONFLICT_INTEN		(1 << 0)
-
-#define OTHER_FUNC_CTRL2		0xB8
-#define OTHER_FUNC_CTRL2_VBAT_TIMER_EN	(1 << 0)
-
-/* following registers do not have separate _clr and _set registers */
-#define VBUS_DEBOUNCE			0xC0
-#define ID_DEBOUNCE			0xC1
-#define VBAT_TIMER			0xD3
-#define PHY_PWR_CTRL			0xFD
-#define PHY_PWR_PHYPWD			(1 << 0)
-#define PHY_CLK_CTRL			0xFE
-#define PHY_CLK_CTRL_CLOCKGATING_EN	(1 << 2)
-#define PHY_CLK_CTRL_CLK32K_EN		(1 << 1)
-#define REQ_PHY_DPLL_CLK		(1 << 0)
-#define PHY_CLK_CTRL_STS		0xFF
-#define PHY_DPLL_CLK			(1 << 0)
-
-/* In module TWL_MODULE_PM_MASTER */
-#define STS_HW_CONDITIONS		0x0F
-
-/* In module TWL_MODULE_PM_RECEIVER */
-#define VUSB_DEDICATED1			0x7D
-#define VUSB_DEDICATED2			0x7E
-#define VUSB1V5_DEV_GRP			0x71
-#define VUSB1V5_TYPE			0x72
-#define VUSB1V5_REMAP			0x73
-#define VUSB1V8_DEV_GRP			0x74
-#define VUSB1V8_TYPE			0x75
-#define VUSB1V8_REMAP			0x76
-#define VUSB3V1_DEV_GRP			0x77
-#define VUSB3V1_TYPE			0x78
-#define VUSB3V1_REMAP			0x79
-
-/* In module TWL4030_MODULE_INTBR */
-#define PMBR1				0x0D
-#define GPIO_USB_4PIN_ULPI_2430C	(3 << 0)
-
-struct twl4030_usb {
-	struct usb_phy		phy;
-	struct device		*dev;
-
-	/* TWL4030 internal USB regulator supplies */
-	struct regulator	*usb1v5;
-	struct regulator	*usb1v8;
-	struct regulator	*usb3v1;
-
-	/* for vbus reporting with irqs disabled */
-	spinlock_t		lock;
-
-	/* pin configuration */
-	enum twl4030_usb_mode	usb_mode;
-
-	int			irq;
-	enum omap_musb_vbus_id_status linkstat;
-	bool			vbus_supplied;
-	u8			asleep;
-	bool			irq_enabled;
-};
-
-/* internal define on top of container_of */
-#define phy_to_twl(x)		container_of((x), struct twl4030_usb, phy)
-
-/*-------------------------------------------------------------------------*/
-
-static int twl4030_i2c_write_u8_verify(struct twl4030_usb *twl,
-		u8 module, u8 data, u8 address)
-{
-	u8 check;
-
-	if ((twl_i2c_write_u8(module, data, address) >= 0) &&
-	    (twl_i2c_read_u8(module, &check, address) >= 0) &&
-						(check == data))
-		return 0;
-	dev_dbg(twl->dev, "Write%d[%d,0x%x] wrote %02x but read %02x\n",
-			1, module, address, check, data);
-
-	/* Failed once: Try again */
-	if ((twl_i2c_write_u8(module, data, address) >= 0) &&
-	    (twl_i2c_read_u8(module, &check, address) >= 0) &&
-						(check == data))
-		return 0;
-	dev_dbg(twl->dev, "Write%d[%d,0x%x] wrote %02x but read %02x\n",
-			2, module, address, check, data);
-
-	/* Failed again: Return error */
-	return -EBUSY;
-}
-
-#define twl4030_usb_write_verify(twl, address, data)	\
-	twl4030_i2c_write_u8_verify(twl, TWL_MODULE_USB, (data), (address))
-
-static inline int twl4030_usb_write(struct twl4030_usb *twl,
-		u8 address, u8 data)
-{
-	int ret = 0;
-
-	ret = twl_i2c_write_u8(TWL_MODULE_USB, data, address);
-	if (ret < 0)
-		dev_dbg(twl->dev,
-			"TWL4030:USB:Write[0x%x] Error %d\n", address, ret);
-	return ret;
-}
-
-static inline int twl4030_readb(struct twl4030_usb *twl, u8 module, u8 address)
-{
-	u8 data;
-	int ret = 0;
-
-	ret = twl_i2c_read_u8(module, &data, address);
-	if (ret >= 0)
-		ret = data;
-	else
-		dev_dbg(twl->dev,
-			"TWL4030:readb[0x%x,0x%x] Error %d\n",
-					module, address, ret);
-
-	return ret;
-}
-
-static inline int twl4030_usb_read(struct twl4030_usb *twl, u8 address)
-{
-	return twl4030_readb(twl, TWL_MODULE_USB, address);
-}
-
-/*-------------------------------------------------------------------------*/
-
-static inline int
-twl4030_usb_set_bits(struct twl4030_usb *twl, u8 reg, u8 bits)
-{
-	return twl4030_usb_write(twl, ULPI_SET(reg), bits);
-}
-
-static inline int
-twl4030_usb_clear_bits(struct twl4030_usb *twl, u8 reg, u8 bits)
-{
-	return twl4030_usb_write(twl, ULPI_CLR(reg), bits);
-}
-
-/*-------------------------------------------------------------------------*/
-
-static enum omap_musb_vbus_id_status
-	twl4030_usb_linkstat(struct twl4030_usb *twl)
-{
-	int	status;
-	enum omap_musb_vbus_id_status linkstat = OMAP_MUSB_UNKNOWN;
-
-	twl->vbus_supplied = false;
-
-	/*
-	 * For ID/VBUS sensing, see manual section 15.4.8 ...
-	 * except when using only battery backup power, two
-	 * comparators produce VBUS_PRES and ID_PRES signals,
-	 * which don't match docs elsewhere.  But ... BIT(7)
-	 * and BIT(2) of STS_HW_CONDITIONS, respectively, do
-	 * seem to match up.  If either is true the USB_PRES
-	 * signal is active, the OTG module is activated, and
-	 * its interrupt may be raised (may wake the system).
-	 */
-	status = twl4030_readb(twl, TWL_MODULE_PM_MASTER, STS_HW_CONDITIONS);
-	if (status < 0)
-		dev_err(twl->dev, "USB link status err %d\n", status);
-	else if (status & (BIT(7) | BIT(2))) {
-		if (status & (BIT(7)))
-                        twl->vbus_supplied = true;
-
-		if (status & BIT(2))
-			linkstat = OMAP_MUSB_ID_GROUND;
-		else
-			linkstat = OMAP_MUSB_VBUS_VALID;
-	} else {
-		if (twl->linkstat != OMAP_MUSB_UNKNOWN)
-			linkstat = OMAP_MUSB_VBUS_OFF;
-	}
-
-	dev_dbg(twl->dev, "HW_CONDITIONS 0x%02x/%d; link %d\n",
-			status, status, linkstat);
-
-	/* REVISIT this assumes host and peripheral controllers
-	 * are registered, and that both are active...
-	 */
-
-	spin_lock_irq(&twl->lock);
-	twl->linkstat = linkstat;
-	spin_unlock_irq(&twl->lock);
-
-	return linkstat;
-}
-
-static void twl4030_usb_set_mode(struct twl4030_usb *twl, int mode)
-{
-	twl->usb_mode = mode;
-
-	switch (mode) {
-	case T2_USB_MODE_ULPI:
-		twl4030_usb_clear_bits(twl, ULPI_IFC_CTRL,
-					ULPI_IFC_CTRL_CARKITMODE);
-		twl4030_usb_set_bits(twl, POWER_CTRL, POWER_CTRL_OTG_ENAB);
-		twl4030_usb_clear_bits(twl, ULPI_FUNC_CTRL,
-					ULPI_FUNC_CTRL_XCVRSEL_MASK |
-					ULPI_FUNC_CTRL_OPMODE_MASK);
-		break;
-	case -1:
-		/* FIXME: power on defaults */
-		break;
-	default:
-		dev_err(twl->dev, "unsupported T2 transceiver mode %d\n",
-				mode);
-		break;
-	};
-}
-
-static void twl4030_i2c_access(struct twl4030_usb *twl, int on)
-{
-	unsigned long timeout;
-	int val = twl4030_usb_read(twl, PHY_CLK_CTRL);
-
-	if (val >= 0) {
-		if (on) {
-			/* enable DPLL to access PHY registers over I2C */
-			val |= REQ_PHY_DPLL_CLK;
-			WARN_ON(twl4030_usb_write_verify(twl, PHY_CLK_CTRL,
-						(u8)val) < 0);
-
-			timeout = jiffies + HZ;
-			while (!(twl4030_usb_read(twl, PHY_CLK_CTRL_STS) &
-							PHY_DPLL_CLK)
-				&& time_before(jiffies, timeout))
-					udelay(10);
-			if (!(twl4030_usb_read(twl, PHY_CLK_CTRL_STS) &
-							PHY_DPLL_CLK))
-				dev_err(twl->dev, "Timeout setting T2 HSUSB "
-						"PHY DPLL clock\n");
-		} else {
-			/* let ULPI control the DPLL clock */
-			val &= ~REQ_PHY_DPLL_CLK;
-			WARN_ON(twl4030_usb_write_verify(twl, PHY_CLK_CTRL,
-						(u8)val) < 0);
-		}
-	}
-}
-
-static void __twl4030_phy_power(struct twl4030_usb *twl, int on)
-{
-	u8 pwr = twl4030_usb_read(twl, PHY_PWR_CTRL);
-
-	if (on)
-		pwr &= ~PHY_PWR_PHYPWD;
-	else
-		pwr |= PHY_PWR_PHYPWD;
-
-	WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) < 0);
-}
-
-static void twl4030_phy_power(struct twl4030_usb *twl, int on)
-{
-	if (on) {
-		regulator_enable(twl->usb3v1);
-		regulator_enable(twl->usb1v8);
-		/*
-		 * Disabling usb3v1 regulator (= writing 0 to VUSB3V1_DEV_GRP
-		 * in twl4030) resets the VUSB_DEDICATED2 register. This reset
-		 * enables VUSB3V1_SLEEP bit that remaps usb3v1 ACTIVE state to
-		 * SLEEP. We work around this by clearing the bit after usv3v1
-		 * is re-activated. This ensures that VUSB3V1 is really active.
-		 */
-		twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2);
-		regulator_enable(twl->usb1v5);
-		__twl4030_phy_power(twl, 1);
-		twl4030_usb_write(twl, PHY_CLK_CTRL,
-				  twl4030_usb_read(twl, PHY_CLK_CTRL) |
-					(PHY_CLK_CTRL_CLOCKGATING_EN |
-						PHY_CLK_CTRL_CLK32K_EN));
-	} else {
-		__twl4030_phy_power(twl, 0);
-		regulator_disable(twl->usb1v5);
-		regulator_disable(twl->usb1v8);
-		regulator_disable(twl->usb3v1);
-	}
-}
-
-static void twl4030_phy_suspend(struct twl4030_usb *twl, int controller_off)
-{
-	if (twl->asleep)
-		return;
-
-	twl4030_phy_power(twl, 0);
-	twl->asleep = 1;
-	dev_dbg(twl->dev, "%s\n", __func__);
-}
-
-static void __twl4030_phy_resume(struct twl4030_usb *twl)
-{
-	twl4030_phy_power(twl, 1);
-	twl4030_i2c_access(twl, 1);
-	twl4030_usb_set_mode(twl, twl->usb_mode);
-	if (twl->usb_mode == T2_USB_MODE_ULPI)
-		twl4030_i2c_access(twl, 0);
-}
-
-static void twl4030_phy_resume(struct twl4030_usb *twl)
-{
-	if (!twl->asleep)
-		return;
-	__twl4030_phy_resume(twl);
-	twl->asleep = 0;
-	dev_dbg(twl->dev, "%s\n", __func__);
-}
-
-static int twl4030_usb_ldo_init(struct twl4030_usb *twl)
-{
-	/* Enable writing to power configuration registers */
-	twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG1,
-			 TWL4030_PM_MASTER_PROTECT_KEY);
-
-	twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG2,
-			 TWL4030_PM_MASTER_PROTECT_KEY);
-
-	/* Keep VUSB3V1 LDO in sleep state until VBUS/ID change detected*/
-	/*twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2);*/
-
-	/* input to VUSB3V1 LDO is from VBAT, not VBUS */
-	twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0x14, VUSB_DEDICATED1);
-
-	/* Initialize 3.1V regulator */
-	twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB3V1_DEV_GRP);
-
-	twl->usb3v1 = regulator_get(twl->dev, "usb3v1");
-	if (IS_ERR(twl->usb3v1))
-		return -ENODEV;
-
-	twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB3V1_TYPE);
-
-	/* Initialize 1.5V regulator */
-	twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB1V5_DEV_GRP);
-
-	twl->usb1v5 = regulator_get(twl->dev, "usb1v5");
-	if (IS_ERR(twl->usb1v5))
-		goto fail1;
-
-	twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB1V5_TYPE);
-
-	/* Initialize 1.8V regulator */
-	twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB1V8_DEV_GRP);
-
-	twl->usb1v8 = regulator_get(twl->dev, "usb1v8");
-	if (IS_ERR(twl->usb1v8))
-		goto fail2;
-
-	twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB1V8_TYPE);
-
-	/* disable access to power configuration registers */
-	twl_i2c_write_u8(TWL_MODULE_PM_MASTER, 0,
-			 TWL4030_PM_MASTER_PROTECT_KEY);
-
-	return 0;
-
-fail2:
-	regulator_put(twl->usb1v5);
-	twl->usb1v5 = NULL;
-fail1:
-	regulator_put(twl->usb3v1);
-	twl->usb3v1 = NULL;
-	return -ENODEV;
-}
-
-static ssize_t twl4030_usb_vbus_show(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct twl4030_usb *twl = dev_get_drvdata(dev);
-	unsigned long flags;
-	int ret = -EINVAL;
-
-	spin_lock_irqsave(&twl->lock, flags);
-	ret = sprintf(buf, "%s\n",
-			twl->vbus_supplied ? "on" : "off");
-	spin_unlock_irqrestore(&twl->lock, flags);
-
-	return ret;
-}
-static DEVICE_ATTR(vbus, 0444, twl4030_usb_vbus_show, NULL);
-
-static irqreturn_t twl4030_usb_irq(int irq, void *_twl)
-{
-	struct twl4030_usb *twl = _twl;
-	enum omap_musb_vbus_id_status status;
-
-	status = twl4030_usb_linkstat(twl);
-	if (status > 0) {
-		/* FIXME add a set_power() method so that B-devices can
-		 * configure the charger appropriately.  It's not always
-		 * correct to consume VBUS power, and how much current to
-		 * consume is a function of the USB configuration chosen
-		 * by the host.
-		 *
-		 * REVISIT usb_gadget_vbus_connect(...) as needed, ditto
-		 * its disconnect() sibling, when changing to/from the
-		 * USB_LINK_VBUS state.  musb_hdrc won't care until it
-		 * starts to handle softconnect right.
-		 */
-		if (status == OMAP_MUSB_VBUS_OFF ||
-				status == OMAP_MUSB_ID_FLOAT)
-			twl4030_phy_suspend(twl, 0);
-		else
-			twl4030_phy_resume(twl);
-
-		omap_musb_mailbox(twl->linkstat);
-	}
-	sysfs_notify(&twl->dev->kobj, NULL, "vbus");
-
-	return IRQ_HANDLED;
-}
-
-static void twl4030_usb_phy_init(struct twl4030_usb *twl)
-{
-	enum omap_musb_vbus_id_status status;
-
-	status = twl4030_usb_linkstat(twl);
-	if (status > 0) {
-		if (status == OMAP_MUSB_VBUS_OFF ||
-				status == OMAP_MUSB_ID_FLOAT) {
-			__twl4030_phy_power(twl, 0);
-			twl->asleep = 1;
-		} else {
-			__twl4030_phy_resume(twl);
-			twl->asleep = 0;
-		}
-
-		omap_musb_mailbox(twl->linkstat);
-	}
-	sysfs_notify(&twl->dev->kobj, NULL, "vbus");
-}
-
-static int twl4030_set_suspend(struct usb_phy *x, int suspend)
-{
-	struct twl4030_usb *twl = phy_to_twl(x);
-
-	if (suspend)
-		twl4030_phy_suspend(twl, 1);
-	else
-		twl4030_phy_resume(twl);
-
-	return 0;
-}
-
-static int twl4030_set_peripheral(struct usb_otg *otg,
-					struct usb_gadget *gadget)
-{
-	if (!otg)
-		return -ENODEV;
-
-	otg->gadget = gadget;
-	if (!gadget)
-		otg->phy->state = OTG_STATE_UNDEFINED;
-
-	return 0;
-}
-
-static int twl4030_set_host(struct usb_otg *otg, struct usb_bus *host)
-{
-	if (!otg)
-		return -ENODEV;
-
-	otg->host = host;
-	if (!host)
-		otg->phy->state = OTG_STATE_UNDEFINED;
-
-	return 0;
-}
-
-static int twl4030_usb_probe(struct platform_device *pdev)
-{
-	struct twl4030_usb_data *pdata = pdev->dev.platform_data;
-	struct twl4030_usb	*twl;
-	int			status, err;
-	struct usb_otg		*otg;
-	struct device_node	*np = pdev->dev.of_node;
-
-	twl = devm_kzalloc(&pdev->dev, sizeof *twl, GFP_KERNEL);
-	if (!twl)
-		return -ENOMEM;
-
-	if (np)
-		of_property_read_u32(np, "usb_mode",
-				(enum twl4030_usb_mode *)&twl->usb_mode);
-	else if (pdata)
-		twl->usb_mode = pdata->usb_mode;
-	else {
-		dev_err(&pdev->dev, "twl4030 initialized without pdata\n");
-		return -EINVAL;
-	}
-
-	otg = devm_kzalloc(&pdev->dev, sizeof *otg, GFP_KERNEL);
-	if (!otg)
-		return -ENOMEM;
-
-	twl->dev		= &pdev->dev;
-	twl->irq		= platform_get_irq(pdev, 0);
-	twl->vbus_supplied	= false;
-	twl->asleep		= 1;
-	twl->linkstat		= OMAP_MUSB_UNKNOWN;
-
-	twl->phy.dev		= twl->dev;
-	twl->phy.label		= "twl4030";
-	twl->phy.otg		= otg;
-	twl->phy.type		= USB_PHY_TYPE_USB2;
-	twl->phy.set_suspend	= twl4030_set_suspend;
-
-	otg->phy		= &twl->phy;
-	otg->set_host		= twl4030_set_host;
-	otg->set_peripheral	= twl4030_set_peripheral;
-
-	/* init spinlock for workqueue */
-	spin_lock_init(&twl->lock);
-
-	err = twl4030_usb_ldo_init(twl);
-	if (err) {
-		dev_err(&pdev->dev, "ldo init failed\n");
-		return err;
-	}
-	usb_add_phy_dev(&twl->phy);
-
-	platform_set_drvdata(pdev, twl);
-	if (device_create_file(&pdev->dev, &dev_attr_vbus))
-		dev_warn(&pdev->dev, "could not create sysfs file\n");
-
-	/* Our job is to use irqs and status from the power module
-	 * to keep the transceiver disabled when nothing's connected.
-	 *
-	 * FIXME we actually shouldn't start enabling it until the
-	 * USB controller drivers have said they're ready, by calling
-	 * set_host() and/or set_peripheral() ... OTG_capable boards
-	 * need both handles, otherwise just one suffices.
-	 */
-	twl->irq_enabled = true;
-	status = request_threaded_irq(twl->irq, NULL, twl4030_usb_irq,
-			IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING |
-			IRQF_ONESHOT, "twl4030_usb", twl);
-	if (status < 0) {
-		dev_dbg(&pdev->dev, "can't get IRQ %d, err %d\n",
-			twl->irq, status);
-		return status;
-	}
-
-	/* Power down phy or make it work according to
-	 * current link state.
-	 */
-	twl4030_usb_phy_init(twl);
-
-	dev_info(&pdev->dev, "Initialized TWL4030 USB module\n");
-	return 0;
-}
-
-static int __exit twl4030_usb_remove(struct platform_device *pdev)
-{
-	struct twl4030_usb *twl = platform_get_drvdata(pdev);
-	int val;
-
-	free_irq(twl->irq, twl);
-	device_remove_file(twl->dev, &dev_attr_vbus);
-
-	/* set transceiver mode to power on defaults */
-	twl4030_usb_set_mode(twl, -1);
-
-	/* autogate 60MHz ULPI clock,
-	 * clear dpll clock request for i2c access,
-	 * disable 32KHz
-	 */
-	val = twl4030_usb_read(twl, PHY_CLK_CTRL);
-	if (val >= 0) {
-		val |= PHY_CLK_CTRL_CLOCKGATING_EN;
-		val &= ~(PHY_CLK_CTRL_CLK32K_EN | REQ_PHY_DPLL_CLK);
-		twl4030_usb_write(twl, PHY_CLK_CTRL, (u8)val);
-	}
-
-	/* disable complete OTG block */
-	twl4030_usb_clear_bits(twl, POWER_CTRL, POWER_CTRL_OTG_ENAB);
-
-	if (!twl->asleep)
-		twl4030_phy_power(twl, 0);
-	regulator_put(twl->usb1v5);
-	regulator_put(twl->usb1v8);
-	regulator_put(twl->usb3v1);
-
-	return 0;
-}
-
-#ifdef CONFIG_OF
-static const struct of_device_id twl4030_usb_id_table[] = {
-	{ .compatible = "ti,twl4030-usb" },
-	{}
-};
-MODULE_DEVICE_TABLE(of, twl4030_usb_id_table);
-#endif
-
-static struct platform_driver twl4030_usb_driver = {
-	.probe		= twl4030_usb_probe,
-	.remove		= __exit_p(twl4030_usb_remove),
-	.driver		= {
-		.name	= "twl4030_usb",
-		.owner	= THIS_MODULE,
-		.of_match_table = of_match_ptr(twl4030_usb_id_table),
-	},
-};
-
-static int __init twl4030_usb_init(void)
-{
-	return platform_driver_register(&twl4030_usb_driver);
-}
-subsys_initcall(twl4030_usb_init);
-
-static void __exit twl4030_usb_exit(void)
-{
-	platform_driver_unregister(&twl4030_usb_driver);
-}
-module_exit(twl4030_usb_exit);
-
-MODULE_ALIAS("platform:twl4030_usb");
-MODULE_AUTHOR("Texas Instruments, Inc, Nokia Corporation");
-MODULE_DESCRIPTION("TWL4030 USB transceiver driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/usb/otg/twl6030-usb.c b/drivers/usb/otg/twl6030-usb.c
deleted file mode 100644
index 8cd6cf4..0000000
--- a/drivers/usb/otg/twl6030-usb.c
+++ /dev/null
@@ -1,446 +0,0 @@
-/*
- * twl6030_usb - TWL6030 USB transceiver, talking to OMAP OTG driver.
- *
- * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.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.
- *
- * Author: Hema HK <hemahk@ti.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., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/usb/musb-omap.h>
-#include <linux/usb/phy_companion.h>
-#include <linux/usb/omap_usb.h>
-#include <linux/i2c/twl.h>
-#include <linux/regulator/consumer.h>
-#include <linux/err.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-
-/* usb register definitions */
-#define USB_VENDOR_ID_LSB		0x00
-#define USB_VENDOR_ID_MSB		0x01
-#define USB_PRODUCT_ID_LSB		0x02
-#define USB_PRODUCT_ID_MSB		0x03
-#define USB_VBUS_CTRL_SET		0x04
-#define USB_VBUS_CTRL_CLR		0x05
-#define USB_ID_CTRL_SET			0x06
-#define USB_ID_CTRL_CLR			0x07
-#define USB_VBUS_INT_SRC		0x08
-#define USB_VBUS_INT_LATCH_SET		0x09
-#define USB_VBUS_INT_LATCH_CLR		0x0A
-#define USB_VBUS_INT_EN_LO_SET		0x0B
-#define USB_VBUS_INT_EN_LO_CLR		0x0C
-#define USB_VBUS_INT_EN_HI_SET		0x0D
-#define USB_VBUS_INT_EN_HI_CLR		0x0E
-#define USB_ID_INT_SRC			0x0F
-#define USB_ID_INT_LATCH_SET		0x10
-#define USB_ID_INT_LATCH_CLR		0x11
-
-#define USB_ID_INT_EN_LO_SET		0x12
-#define USB_ID_INT_EN_LO_CLR		0x13
-#define USB_ID_INT_EN_HI_SET		0x14
-#define USB_ID_INT_EN_HI_CLR		0x15
-#define USB_OTG_ADP_CTRL		0x16
-#define USB_OTG_ADP_HIGH		0x17
-#define USB_OTG_ADP_LOW			0x18
-#define USB_OTG_ADP_RISE		0x19
-#define USB_OTG_REVISION		0x1A
-
-/* to be moved to LDO */
-#define TWL6030_MISC2			0xE5
-#define TWL6030_CFG_LDO_PD2		0xF5
-#define TWL6030_BACKUP_REG		0xFA
-
-#define STS_HW_CONDITIONS		0x21
-
-/* In module TWL6030_MODULE_PM_MASTER */
-#define STS_HW_CONDITIONS		0x21
-#define STS_USB_ID			BIT(2)
-
-/* In module TWL6030_MODULE_PM_RECEIVER */
-#define VUSB_CFG_TRANS			0x71
-#define VUSB_CFG_STATE			0x72
-#define VUSB_CFG_VOLTAGE		0x73
-
-/* in module TWL6030_MODULE_MAIN_CHARGE */
-
-#define CHARGERUSB_CTRL1		0x8
-
-#define CONTROLLER_STAT1		0x03
-#define	VBUS_DET			BIT(2)
-
-struct twl6030_usb {
-	struct phy_companion	comparator;
-	struct device		*dev;
-
-	/* for vbus reporting with irqs disabled */
-	spinlock_t		lock;
-
-	struct regulator		*usb3v3;
-
-	/* used to set vbus, in atomic path */
-	struct work_struct	set_vbus_work;
-
-	int			irq1;
-	int			irq2;
-	enum omap_musb_vbus_id_status linkstat;
-	u8			asleep;
-	bool			irq_enabled;
-	bool			vbus_enable;
-	const char		*regulator;
-};
-
-#define	comparator_to_twl(x) container_of((x), struct twl6030_usb, comparator)
-
-/*-------------------------------------------------------------------------*/
-
-static inline int twl6030_writeb(struct twl6030_usb *twl, u8 module,
-						u8 data, u8 address)
-{
-	int ret = 0;
-
-	ret = twl_i2c_write_u8(module, data, address);
-	if (ret < 0)
-		dev_err(twl->dev,
-			"Write[0x%x] Error %d\n", address, ret);
-	return ret;
-}
-
-static inline u8 twl6030_readb(struct twl6030_usb *twl, u8 module, u8 address)
-{
-	u8 data, ret = 0;
-
-	ret = twl_i2c_read_u8(module, &data, address);
-	if (ret >= 0)
-		ret = data;
-	else
-		dev_err(twl->dev,
-			"readb[0x%x,0x%x] Error %d\n",
-					module, address, ret);
-	return ret;
-}
-
-static int twl6030_start_srp(struct phy_companion *comparator)
-{
-	struct twl6030_usb *twl = comparator_to_twl(comparator);
-
-	twl6030_writeb(twl, TWL_MODULE_USB, 0x24, USB_VBUS_CTRL_SET);
-	twl6030_writeb(twl, TWL_MODULE_USB, 0x84, USB_VBUS_CTRL_SET);
-
-	mdelay(100);
-	twl6030_writeb(twl, TWL_MODULE_USB, 0xa0, USB_VBUS_CTRL_CLR);
-
-	return 0;
-}
-
-static int twl6030_usb_ldo_init(struct twl6030_usb *twl)
-{
-	/* Set to OTG_REV 1.3 and turn on the ID_WAKEUP_COMP */
-	twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x1, TWL6030_BACKUP_REG);
-
-	/* Program CFG_LDO_PD2 register and set VUSB bit */
-	twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x1, TWL6030_CFG_LDO_PD2);
-
-	/* Program MISC2 register and set bit VUSB_IN_VBAT */
-	twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x10, TWL6030_MISC2);
-
-	twl->usb3v3 = regulator_get(twl->dev, twl->regulator);
-	if (IS_ERR(twl->usb3v3))
-		return -ENODEV;
-
-	/* Program the USB_VBUS_CTRL_SET and set VBUS_ACT_COMP bit */
-	twl6030_writeb(twl, TWL_MODULE_USB, 0x4, USB_VBUS_CTRL_SET);
-
-	/*
-	 * Program the USB_ID_CTRL_SET register to enable GND drive
-	 * and the ID comparators
-	 */
-	twl6030_writeb(twl, TWL_MODULE_USB, 0x14, USB_ID_CTRL_SET);
-
-	return 0;
-}
-
-static ssize_t twl6030_usb_vbus_show(struct device *dev,
-			struct device_attribute *attr, char *buf)
-{
-	struct twl6030_usb *twl = dev_get_drvdata(dev);
-	unsigned long flags;
-	int ret = -EINVAL;
-
-	spin_lock_irqsave(&twl->lock, flags);
-
-	switch (twl->linkstat) {
-	case OMAP_MUSB_VBUS_VALID:
-	       ret = snprintf(buf, PAGE_SIZE, "vbus\n");
-	       break;
-	case OMAP_MUSB_ID_GROUND:
-	       ret = snprintf(buf, PAGE_SIZE, "id\n");
-	       break;
-	case OMAP_MUSB_VBUS_OFF:
-	       ret = snprintf(buf, PAGE_SIZE, "none\n");
-	       break;
-	default:
-	       ret = snprintf(buf, PAGE_SIZE, "UNKNOWN\n");
-	}
-	spin_unlock_irqrestore(&twl->lock, flags);
-
-	return ret;
-}
-static DEVICE_ATTR(vbus, 0444, twl6030_usb_vbus_show, NULL);
-
-static irqreturn_t twl6030_usb_irq(int irq, void *_twl)
-{
-	struct twl6030_usb *twl = _twl;
-	enum omap_musb_vbus_id_status status = OMAP_MUSB_UNKNOWN;
-	u8 vbus_state, hw_state;
-
-	hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS);
-
-	vbus_state = twl6030_readb(twl, TWL_MODULE_MAIN_CHARGE,
-						CONTROLLER_STAT1);
-	if (!(hw_state & STS_USB_ID)) {
-		if (vbus_state & VBUS_DET) {
-			regulator_enable(twl->usb3v3);
-			twl->asleep = 1;
-			status = OMAP_MUSB_VBUS_VALID;
-			twl->linkstat = status;
-			omap_musb_mailbox(status);
-		} else {
-			if (twl->linkstat != OMAP_MUSB_UNKNOWN) {
-				status = OMAP_MUSB_VBUS_OFF;
-				twl->linkstat = status;
-				omap_musb_mailbox(status);
-				if (twl->asleep) {
-					regulator_disable(twl->usb3v3);
-					twl->asleep = 0;
-				}
-			}
-		}
-	}
-	sysfs_notify(&twl->dev->kobj, NULL, "vbus");
-
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl)
-{
-	struct twl6030_usb *twl = _twl;
-	enum omap_musb_vbus_id_status status = OMAP_MUSB_UNKNOWN;
-	u8 hw_state;
-
-	hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS);
-
-	if (hw_state & STS_USB_ID) {
-
-		regulator_enable(twl->usb3v3);
-		twl->asleep = 1;
-		twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_CLR);
-		twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_SET);
-		status = OMAP_MUSB_ID_GROUND;
-		twl->linkstat = status;
-		omap_musb_mailbox(status);
-	} else  {
-		twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_CLR);
-		twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_SET);
-	}
-	twl6030_writeb(twl, TWL_MODULE_USB, status, USB_ID_INT_LATCH_CLR);
-
-	return IRQ_HANDLED;
-}
-
-static int twl6030_enable_irq(struct twl6030_usb *twl)
-{
-	twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_SET);
-	twl6030_interrupt_unmask(0x05, REG_INT_MSK_LINE_C);
-	twl6030_interrupt_unmask(0x05, REG_INT_MSK_STS_C);
-
-	twl6030_interrupt_unmask(TWL6030_CHARGER_CTRL_INT_MASK,
-				REG_INT_MSK_LINE_C);
-	twl6030_interrupt_unmask(TWL6030_CHARGER_CTRL_INT_MASK,
-				REG_INT_MSK_STS_C);
-	twl6030_usb_irq(twl->irq2, twl);
-	twl6030_usbotg_irq(twl->irq1, twl);
-
-	return 0;
-}
-
-static void otg_set_vbus_work(struct work_struct *data)
-{
-	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 (twl->vbus_enable)
-		twl6030_writeb(twl, TWL_MODULE_MAIN_CHARGE , 0x40,
-							CHARGERUSB_CTRL1);
-	else
-		twl6030_writeb(twl, TWL_MODULE_MAIN_CHARGE , 0x00,
-							CHARGERUSB_CTRL1);
-}
-
-static int twl6030_set_vbus(struct phy_companion *comparator, bool enabled)
-{
-	struct twl6030_usb *twl = comparator_to_twl(comparator);
-
-	twl->vbus_enable = enabled;
-	schedule_work(&twl->set_vbus_work);
-
-	return 0;
-}
-
-static int twl6030_usb_probe(struct platform_device *pdev)
-{
-	u32 ret;
-	struct twl6030_usb	*twl;
-	int			status, err;
-	struct device_node	*np = pdev->dev.of_node;
-	struct device		*dev = &pdev->dev;
-	struct twl4030_usb_data	*pdata = dev->platform_data;
-
-	twl = devm_kzalloc(dev, sizeof *twl, GFP_KERNEL);
-	if (!twl)
-		return -ENOMEM;
-
-	twl->dev		= &pdev->dev;
-	twl->irq1		= platform_get_irq(pdev, 0);
-	twl->irq2		= platform_get_irq(pdev, 1);
-	twl->linkstat		= OMAP_MUSB_UNKNOWN;
-
-	twl->comparator.set_vbus	= twl6030_set_vbus;
-	twl->comparator.start_srp	= twl6030_start_srp;
-
-	ret = omap_usb2_set_comparator(&twl->comparator);
-	if (ret == -ENODEV) {
-		dev_info(&pdev->dev, "phy not ready, deferring probe");
-		return -EPROBE_DEFER;
-	}
-
-	if (np) {
-		twl->regulator = "usb";
-	} else if (pdata) {
-		if (pdata->features & TWL6025_SUBCLASS)
-			twl->regulator = "ldousb";
-		else
-			twl->regulator = "vusb";
-	} else {
-		dev_err(&pdev->dev, "twl6030 initialized without pdata\n");
-		return -EINVAL;
-	}
-
-	/* init spinlock for workqueue */
-	spin_lock_init(&twl->lock);
-
-	err = twl6030_usb_ldo_init(twl);
-	if (err) {
-		dev_err(&pdev->dev, "ldo init failed\n");
-		return err;
-	}
-
-	platform_set_drvdata(pdev, twl);
-	if (device_create_file(&pdev->dev, &dev_attr_vbus))
-		dev_warn(&pdev->dev, "could not create sysfs file\n");
-
-	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 | IRQF_ONESHOT,
-			"twl6030_usb", twl);
-	if (status < 0) {
-		dev_err(&pdev->dev, "can't get IRQ %d, err %d\n",
-			twl->irq1, status);
-		device_remove_file(twl->dev, &dev_attr_vbus);
-		return status;
-	}
-
-	status = request_threaded_irq(twl->irq2, NULL, twl6030_usb_irq,
-			IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | IRQF_ONESHOT,
-			"twl6030_usb", twl);
-	if (status < 0) {
-		dev_err(&pdev->dev, "can't get IRQ %d, err %d\n",
-			twl->irq2, status);
-		free_irq(twl->irq1, twl);
-		device_remove_file(twl->dev, &dev_attr_vbus);
-		return status;
-	}
-
-	twl->asleep = 0;
-	twl6030_enable_irq(twl);
-	dev_info(&pdev->dev, "Initialized TWL6030 USB module\n");
-
-	return 0;
-}
-
-static int __exit twl6030_usb_remove(struct platform_device *pdev)
-{
-	struct twl6030_usb *twl = platform_get_drvdata(pdev);
-
-	twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK,
-		REG_INT_MSK_LINE_C);
-	twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK,
-			REG_INT_MSK_STS_C);
-	free_irq(twl->irq1, twl);
-	free_irq(twl->irq2, twl);
-	regulator_put(twl->usb3v3);
-	device_remove_file(twl->dev, &dev_attr_vbus);
-	cancel_work_sync(&twl->set_vbus_work);
-
-	return 0;
-}
-
-#ifdef CONFIG_OF
-static const struct of_device_id twl6030_usb_id_table[] = {
-	{ .compatible = "ti,twl6030-usb" },
-	{}
-};
-MODULE_DEVICE_TABLE(of, twl6030_usb_id_table);
-#endif
-
-static struct platform_driver twl6030_usb_driver = {
-	.probe		= twl6030_usb_probe,
-	.remove		= __exit_p(twl6030_usb_remove),
-	.driver		= {
-		.name	= "twl6030_usb",
-		.owner	= THIS_MODULE,
-		.of_match_table = of_match_ptr(twl6030_usb_id_table),
-	},
-};
-
-static int __init twl6030_usb_init(void)
-{
-	return platform_driver_register(&twl6030_usb_driver);
-}
-subsys_initcall(twl6030_usb_init);
-
-static void __exit twl6030_usb_exit(void)
-{
-	platform_driver_unregister(&twl6030_usb_driver);
-}
-module_exit(twl6030_usb_exit);
-
-MODULE_ALIAS("platform:twl6030_usb");
-MODULE_AUTHOR("Hema HK <hemahk@ti.com>");
-MODULE_DESCRIPTION("TWL6030 USB transceiver driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/usb/otg/ulpi.c b/drivers/usb/otg/ulpi.c
deleted file mode 100644
index 217339d..0000000
--- a/drivers/usb/otg/ulpi.c
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
- * Generic ULPI USB transceiver support
- *
- * Copyright (C) 2009 Daniel Mack <daniel@caiaq.de>
- *
- * Based on sources from
- *
- *   Sascha Hauer <s.hauer@pengutronix.de>
- *   Freescale 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.
- *
- * You 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/export.h>
-#include <linux/usb.h>
-#include <linux/usb/otg.h>
-#include <linux/usb/ulpi.h>
-
-
-struct ulpi_info {
-	unsigned int	id;
-	char		*name;
-};
-
-#define ULPI_ID(vendor, product) (((vendor) << 16) | (product))
-#define ULPI_INFO(_id, _name)		\
-	{				\
-		.id	= (_id),	\
-		.name	= (_name),	\
-	}
-
-/* ULPI hardcoded IDs, used for probing */
-static struct ulpi_info ulpi_ids[] = {
-	ULPI_INFO(ULPI_ID(0x04cc, 0x1504), "NXP ISP1504"),
-	ULPI_INFO(ULPI_ID(0x0424, 0x0006), "SMSC USB331x"),
-};
-
-static int ulpi_set_otg_flags(struct usb_phy *phy)
-{
-	unsigned int flags = ULPI_OTG_CTRL_DP_PULLDOWN |
-			     ULPI_OTG_CTRL_DM_PULLDOWN;
-
-	if (phy->flags & ULPI_OTG_ID_PULLUP)
-		flags |= ULPI_OTG_CTRL_ID_PULLUP;
-
-	/*
-	 * ULPI Specification rev.1.1 default
-	 * for Dp/DmPulldown is enabled.
-	 */
-	if (phy->flags & ULPI_OTG_DP_PULLDOWN_DIS)
-		flags &= ~ULPI_OTG_CTRL_DP_PULLDOWN;
-
-	if (phy->flags & ULPI_OTG_DM_PULLDOWN_DIS)
-		flags &= ~ULPI_OTG_CTRL_DM_PULLDOWN;
-
-	if (phy->flags & ULPI_OTG_EXTVBUSIND)
-		flags |= ULPI_OTG_CTRL_EXTVBUSIND;
-
-	return usb_phy_io_write(phy, flags, ULPI_OTG_CTRL);
-}
-
-static int ulpi_set_fc_flags(struct usb_phy *phy)
-{
-	unsigned int flags = 0;
-
-	/*
-	 * ULPI Specification rev.1.1 default
-	 * for XcvrSelect is Full Speed.
-	 */
-	if (phy->flags & ULPI_FC_HS)
-		flags |= ULPI_FUNC_CTRL_HIGH_SPEED;
-	else if (phy->flags & ULPI_FC_LS)
-		flags |= ULPI_FUNC_CTRL_LOW_SPEED;
-	else if (phy->flags & ULPI_FC_FS4LS)
-		flags |= ULPI_FUNC_CTRL_FS4LS;
-	else
-		flags |= ULPI_FUNC_CTRL_FULL_SPEED;
-
-	if (phy->flags & ULPI_FC_TERMSEL)
-		flags |= ULPI_FUNC_CTRL_TERMSELECT;
-
-	/*
-	 * ULPI Specification rev.1.1 default
-	 * for OpMode is Normal Operation.
-	 */
-	if (phy->flags & ULPI_FC_OP_NODRV)
-		flags |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING;
-	else if (phy->flags & ULPI_FC_OP_DIS_NRZI)
-		flags |= ULPI_FUNC_CTRL_OPMODE_DISABLE_NRZI;
-	else if (phy->flags & ULPI_FC_OP_NSYNC_NEOP)
-		flags |= ULPI_FUNC_CTRL_OPMODE_NOSYNC_NOEOP;
-	else
-		flags |= ULPI_FUNC_CTRL_OPMODE_NORMAL;
-
-	/*
-	 * ULPI Specification rev.1.1 default
-	 * for SuspendM is Powered.
-	 */
-	flags |= ULPI_FUNC_CTRL_SUSPENDM;
-
-	return usb_phy_io_write(phy, flags, ULPI_FUNC_CTRL);
-}
-
-static int ulpi_set_ic_flags(struct usb_phy *phy)
-{
-	unsigned int flags = 0;
-
-	if (phy->flags & ULPI_IC_AUTORESUME)
-		flags |= ULPI_IFC_CTRL_AUTORESUME;
-
-	if (phy->flags & ULPI_IC_EXTVBUS_INDINV)
-		flags |= ULPI_IFC_CTRL_EXTERNAL_VBUS;
-
-	if (phy->flags & ULPI_IC_IND_PASSTHRU)
-		flags |= ULPI_IFC_CTRL_PASSTHRU;
-
-	if (phy->flags & ULPI_IC_PROTECT_DIS)
-		flags |= ULPI_IFC_CTRL_PROTECT_IFC_DISABLE;
-
-	return usb_phy_io_write(phy, flags, ULPI_IFC_CTRL);
-}
-
-static int ulpi_set_flags(struct usb_phy *phy)
-{
-	int ret;
-
-	ret = ulpi_set_otg_flags(phy);
-	if (ret)
-		return ret;
-
-	ret = ulpi_set_ic_flags(phy);
-	if (ret)
-		return ret;
-
-	return ulpi_set_fc_flags(phy);
-}
-
-static int ulpi_check_integrity(struct usb_phy *phy)
-{
-	int ret, i;
-	unsigned int val = 0x55;
-
-	for (i = 0; i < 2; i++) {
-		ret = usb_phy_io_write(phy, val, ULPI_SCRATCH);
-		if (ret < 0)
-			return ret;
-
-		ret = usb_phy_io_read(phy, ULPI_SCRATCH);
-		if (ret < 0)
-			return ret;
-
-		if (ret != val) {
-			pr_err("ULPI integrity check: failed!");
-			return -ENODEV;
-		}
-		val = val << 1;
-	}
-
-	pr_info("ULPI integrity check: passed.\n");
-
-	return 0;
-}
-
-static int ulpi_init(struct usb_phy *phy)
-{
-	int i, vid, pid, ret;
-	u32 ulpi_id = 0;
-
-	for (i = 0; i < 4; i++) {
-		ret = usb_phy_io_read(phy, ULPI_PRODUCT_ID_HIGH - i);
-		if (ret < 0)
-			return ret;
-		ulpi_id = (ulpi_id << 8) | ret;
-	}
-	vid = ulpi_id & 0xffff;
-	pid = ulpi_id >> 16;
-
-	pr_info("ULPI transceiver vendor/product ID 0x%04x/0x%04x\n", vid, pid);
-
-	for (i = 0; i < ARRAY_SIZE(ulpi_ids); i++) {
-		if (ulpi_ids[i].id == ULPI_ID(vid, pid)) {
-			pr_info("Found %s ULPI transceiver.\n",
-				ulpi_ids[i].name);
-			break;
-		}
-	}
-
-	ret = ulpi_check_integrity(phy);
-	if (ret)
-		return ret;
-
-	return ulpi_set_flags(phy);
-}
-
-static int ulpi_set_host(struct usb_otg *otg, struct usb_bus *host)
-{
-	struct usb_phy *phy = otg->phy;
-	unsigned int flags = usb_phy_io_read(phy, ULPI_IFC_CTRL);
-
-	if (!host) {
-		otg->host = NULL;
-		return 0;
-	}
-
-	otg->host = host;
-
-	flags &= ~(ULPI_IFC_CTRL_6_PIN_SERIAL_MODE |
-		   ULPI_IFC_CTRL_3_PIN_SERIAL_MODE |
-		   ULPI_IFC_CTRL_CARKITMODE);
-
-	if (phy->flags & ULPI_IC_6PIN_SERIAL)
-		flags |= ULPI_IFC_CTRL_6_PIN_SERIAL_MODE;
-	else if (phy->flags & ULPI_IC_3PIN_SERIAL)
-		flags |= ULPI_IFC_CTRL_3_PIN_SERIAL_MODE;
-	else if (phy->flags & ULPI_IC_CARKIT)
-		flags |= ULPI_IFC_CTRL_CARKITMODE;
-
-	return usb_phy_io_write(phy, flags, ULPI_IFC_CTRL);
-}
-
-static int ulpi_set_vbus(struct usb_otg *otg, bool on)
-{
-	struct usb_phy *phy = otg->phy;
-	unsigned int flags = usb_phy_io_read(phy, ULPI_OTG_CTRL);
-
-	flags &= ~(ULPI_OTG_CTRL_DRVVBUS | ULPI_OTG_CTRL_DRVVBUS_EXT);
-
-	if (on) {
-		if (phy->flags & ULPI_OTG_DRVVBUS)
-			flags |= ULPI_OTG_CTRL_DRVVBUS;
-
-		if (phy->flags & ULPI_OTG_DRVVBUS_EXT)
-			flags |= ULPI_OTG_CTRL_DRVVBUS_EXT;
-	}
-
-	return usb_phy_io_write(phy, flags, ULPI_OTG_CTRL);
-}
-
-struct usb_phy *
-otg_ulpi_create(struct usb_phy_io_ops *ops,
-		unsigned int flags)
-{
-	struct usb_phy *phy;
-	struct usb_otg *otg;
-
-	phy = kzalloc(sizeof(*phy), GFP_KERNEL);
-	if (!phy)
-		return NULL;
-
-	otg = kzalloc(sizeof(*otg), GFP_KERNEL);
-	if (!otg) {
-		kfree(phy);
-		return NULL;
-	}
-
-	phy->label	= "ULPI";
-	phy->flags	= flags;
-	phy->io_ops	= ops;
-	phy->otg	= otg;
-	phy->init	= ulpi_init;
-
-	otg->phy	= phy;
-	otg->set_host	= ulpi_set_host;
-	otg->set_vbus	= ulpi_set_vbus;
-
-	return phy;
-}
-EXPORT_SYMBOL_GPL(otg_ulpi_create);
-
diff --git a/drivers/usb/otg/ulpi_viewport.c b/drivers/usb/otg/ulpi_viewport.c
deleted file mode 100644
index c5ba7e5..0000000
--- a/drivers/usb/otg/ulpi_viewport.c
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2011 Google, 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.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/usb.h>
-#include <linux/io.h>
-#include <linux/usb/otg.h>
-#include <linux/usb/ulpi.h>
-
-#define ULPI_VIEW_WAKEUP	(1 << 31)
-#define ULPI_VIEW_RUN		(1 << 30)
-#define ULPI_VIEW_WRITE		(1 << 29)
-#define ULPI_VIEW_READ		(0 << 29)
-#define ULPI_VIEW_ADDR(x)	(((x) & 0xff) << 16)
-#define ULPI_VIEW_DATA_READ(x)	(((x) >> 8) & 0xff)
-#define ULPI_VIEW_DATA_WRITE(x)	((x) & 0xff)
-
-static int ulpi_viewport_wait(void __iomem *view, u32 mask)
-{
-	unsigned long usec = 2000;
-
-	while (usec--) {
-		if (!(readl(view) & mask))
-			return 0;
-
-		udelay(1);
-	};
-
-	return -ETIMEDOUT;
-}
-
-static int ulpi_viewport_read(struct usb_phy *otg, u32 reg)
-{
-	int ret;
-	void __iomem *view = otg->io_priv;
-
-	writel(ULPI_VIEW_WAKEUP | ULPI_VIEW_WRITE, view);
-	ret = ulpi_viewport_wait(view, ULPI_VIEW_WAKEUP);
-	if (ret)
-		return ret;
-
-	writel(ULPI_VIEW_RUN | ULPI_VIEW_READ | ULPI_VIEW_ADDR(reg), view);
-	ret = ulpi_viewport_wait(view, ULPI_VIEW_RUN);
-	if (ret)
-		return ret;
-
-	return ULPI_VIEW_DATA_READ(readl(view));
-}
-
-static int ulpi_viewport_write(struct usb_phy *otg, u32 val, u32 reg)
-{
-	int ret;
-	void __iomem *view = otg->io_priv;
-
-	writel(ULPI_VIEW_WAKEUP | ULPI_VIEW_WRITE, view);
-	ret = ulpi_viewport_wait(view, ULPI_VIEW_WAKEUP);
-	if (ret)
-		return ret;
-
-	writel(ULPI_VIEW_RUN | ULPI_VIEW_WRITE | ULPI_VIEW_DATA_WRITE(val) |
-						 ULPI_VIEW_ADDR(reg), view);
-
-	return ulpi_viewport_wait(view, ULPI_VIEW_RUN);
-}
-
-struct usb_phy_io_ops ulpi_viewport_access_ops = {
-	.read	= ulpi_viewport_read,
-	.write	= ulpi_viewport_write,
-};
diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig
index 9054938..3a7fec9 100644
--- a/drivers/usb/phy/Kconfig
+++ b/drivers/usb/phy/Kconfig
@@ -1,13 +1,74 @@
 #
 # Physical Layer USB driver configuration
 #
-comment "USB Physical Layer drivers"
-	depends on USB || USB_GADGET
+menuconfig USB_PHY
+	tristate "USB Physical Layer drivers"
+	help
+	  USB controllers (those which are host, device or DRD) need a
+	  device to handle the physical layer signalling, commonly called
+	  a PHY.
+
+	  The following drivers add support for such PHY devices.
+
+if USB_PHY
+
+#
+# USB Transceiver Drivers
+#
+config AB8500_USB
+	tristate "AB8500 USB Transceiver Driver"
+	depends on AB8500_CORE
+	help
+	  Enable this to support the USB OTG transceiver in AB8500 chip.
+	  This transceiver supports high and full speed devices plus,
+	  in host mode, low speed.
+
+config FSL_USB2_OTG
+	bool "Freescale USB OTG Transceiver Driver"
+	depends on USB_EHCI_FSL && USB_FSL_USB2 && USB_SUSPEND
+	select USB_OTG
+	help
+	  Enable this to support Freescale USB OTG transceiver.
+
+config ISP1301_OMAP
+	tristate "Philips ISP1301 with OMAP OTG"
+	depends on I2C && ARCH_OMAP_OTG
+	help
+	  If you say yes here you get support for the Philips ISP1301
+	  USB-On-The-Go transceiver working with the OMAP OTG controller.
+	  The ISP1301 is a full speed USB  transceiver which is used in
+	  products including H2, H3, and H4 development boards for Texas
+	  Instruments OMAP processors.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called isp1301_omap.
+
+config MV_U3D_PHY
+	bool "Marvell USB 3.0 PHY controller Driver"
+	depends on CPU_MMP3
+	help
+	  Enable this to support Marvell USB 3.0 phy controller for Marvell
+	  SoC.
+
+config NOP_USB_XCEIV
+	tristate "NOP USB Transceiver Driver"
+	help
+	  This driver is to be used by all the usb transceiver which are either
+	  built-in with usb ip or which are autonomous and doesn't require any
+	  phy programming such as ISP1x04 etc.
+
+config OMAP_CONTROL_USB
+	tristate "OMAP CONTROL USB Driver"
+	help
+	  Enable this to add support for the USB part present in the control
+	  module. This driver has API to power on the USB2 PHY and to write to
+	  the mailbox. The mailbox is present only in omap4 and the register to
+	  power on the USB2 PHY is present in OMAP4 and OMAP5. OMAP5 has an
+	  additional register to power on USB3 PHY.
 
 config OMAP_USB2
 	tristate "OMAP USB2 PHY Driver"
 	depends on ARCH_OMAP2PLUS
-	select USB_OTG_UTILS
 	select OMAP_CONTROL_USB
 	help
 	  Enable this to support the transceiver that is part of SOC. This
@@ -17,7 +78,6 @@ config OMAP_USB2
 
 config OMAP_USB3
 	tristate "OMAP USB3 PHY Driver"
-	select USB_OTG_UTILS
 	select OMAP_CONTROL_USB
 	help
 	  Enable this to support the USB3 PHY that is part of SOC. This
@@ -25,14 +85,55 @@ config OMAP_USB3
 	  This driver interacts with the "OMAP Control USB Driver" to power
 	  on/off the PHY.
 
-config OMAP_CONTROL_USB
-	tristate "OMAP CONTROL USB Driver"
+config SAMSUNG_USBPHY
+	tristate "Samsung USB PHY Driver"
 	help
-	  Enable this to add support for the USB part present in the control
-	  module. This driver has API to power on the USB2 PHY and to write to
-	  the mailbox. The mailbox is present only in omap4 and the register to
-	  power on the USB2 PHY is present in OMAP4 and OMAP5. OMAP5 has an
-	  additional register to power on USB3 PHY.
+	  Enable this to support Samsung USB phy helper driver for Samsung SoCs.
+	  This driver provides common interface to interact, for Samsung USB 2.0 PHY
+	  driver and later for Samsung USB 3.0 PHY driver.
+
+config SAMSUNG_USB2PHY
+	tristate "Samsung USB 2.0 PHY controller Driver"
+	select SAMSUNG_USBPHY
+	help
+	  Enable this to support Samsung USB 2.0 (High Speed) PHY controller
+	  driver for Samsung SoCs.
+
+config SAMSUNG_USB3PHY
+	tristate "Samsung USB 3.0 PHY controller Driver"
+	select SAMSUNG_USBPHY
+	help
+	  Enable this to support Samsung USB 3.0 (Super Speed) phy controller
+	  for samsung SoCs.
+
+config TWL4030_USB
+	tristate "TWL4030 USB Transceiver Driver"
+	depends on TWL4030_CORE && REGULATOR_TWL4030 && USB_MUSB_OMAP2PLUS
+	help
+	  Enable this to support the USB OTG transceiver on TWL4030
+	  family chips (including the TWL5030 and TPS659x0 devices).
+	  This transceiver supports high and full speed devices plus,
+	  in host mode, low speed.
+
+config TWL6030_USB
+	tristate "TWL6030 USB Transceiver Driver"
+	depends on TWL4030_CORE && OMAP_USB2 && USB_MUSB_OMAP2PLUS
+	help
+	  Enable this to support the USB OTG transceiver on TWL6030
+	  family chips. This TWL6030 transceiver has the VBUS and ID GND
+	  and OTG SRP events capabilities. For all other transceiver functionality
+	  UTMI PHY is embedded in OMAP4430. The internal PHY configurations APIs
+	  are hooked to this driver through platform_data structure.
+	  The definition of internal PHY APIs are in the mach-omap2 layer.
+
+config USB_GPIO_VBUS
+	tristate "GPIO based peripheral-only VBUS sensing 'transceiver'"
+	depends on GENERIC_GPIO
+	help
+	  Provides simple GPIO VBUS sensing for controllers with an
+	  internal transceiver via the usb_phy interface, and
+	  optionally control of a D+ pullup GPIO as well as a VBUS
+	  current limit regulator.
 
 config USB_ISP1301
 	tristate "NXP ISP1301 USB transceiver support"
@@ -47,18 +148,41 @@ config USB_ISP1301
 	  To compile this driver as a module, choose M here: the
 	  module will be called isp1301.
 
-config MV_U3D_PHY
-	bool "Marvell USB 3.0 PHY controller Driver"
-	depends on USB_MV_U3D
-	select USB_OTG_UTILS
+config USB_MSM_OTG
+	tristate "OTG support for Qualcomm on-chip USB controller"
+	depends on (USB || USB_GADGET) && ARCH_MSM
 	help
-	  Enable this to support Marvell USB 3.0 phy controller for Marvell
-	  SoC.
+	  Enable this to support the USB OTG transceiver on MSM chips. It
+	  handles PHY initialization, clock management, and workarounds
+	  required after resetting the hardware and power management.
+	  This driver is required even for peripheral only or host only
+	  mode configurations.
+	  This driver is not supported on boards like trout which
+	  has an external PHY.
+
+config USB_MV_OTG
+	tristate "Marvell USB OTG support"
+	depends on USB_EHCI_MV && USB_MV_UDC && USB_SUSPEND
+	select USB_OTG
+	help
+	  Say Y here if you want to build Marvell USB OTG transciever
+	  driver in kernel (including PXA and MMP series). This driver
+	  implements role switch between EHCI host driver and gadget driver.
+
+	  To compile this driver as a module, choose M here.
+
+config USB_MXS_PHY
+	tristate "Freescale MXS USB PHY support"
+	depends on ARCH_MXC || ARCH_MXS
+	select STMP_DEVICE
+	help
+	  Enable this to support the Freescale MXS USB PHY.
+
+	  MXS Phy is used by some of the i.MX SoCs, for example imx23/28/6x.
 
 config USB_RCAR_PHY
 	tristate "Renesas R-Car USB phy support"
 	depends on USB || USB_GADGET
-	select USB_OTG_UTILS
 	help
 	  Say Y here to add support for the Renesas R-Car USB phy driver.
 	  This chip is typically used as USB phy for USB host, gadget.
@@ -67,10 +191,18 @@ config USB_RCAR_PHY
 	  To compile this driver as a module, choose M here: the
 	  module will be called rcar-phy.
 
-config SAMSUNG_USBPHY
-	bool "Samsung USB PHY controller Driver"
-	depends on USB_S3C_HSOTG || USB_EHCI_S5P || USB_OHCI_EXYNOS
-	select USB_OTG_UTILS
+config USB_ULPI
+	bool "Generic ULPI Transceiver Driver"
+	depends on ARM
+	help
+	  Enable this to support ULPI connected USB OTG transceivers which
+	  are likely found on embedded boards.
+
+config USB_ULPI_VIEWPORT
+	bool
+	depends on USB_ULPI
 	help
-	  Enable this to support Samsung USB phy controller for samsung
-	  SoCs.
+	  Provides read/write operations to the ULPI phy register set for
+	  controllers with a viewport register (e.g. Chipidea/ARC controllers).
+
+endif # USB_PHY
diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile
index b13faa1..33863c0 100644
--- a/drivers/usb/phy/Makefile
+++ b/drivers/usb/phy/Makefile
@@ -4,11 +4,30 @@
 
 ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG
 
-obj-$(CONFIG_OMAP_USB2)			+= omap-usb2.o
-obj-$(CONFIG_OMAP_USB3)			+= omap-usb3.o
-obj-$(CONFIG_OMAP_CONTROL_USB)		+= omap-control-usb.o
-obj-$(CONFIG_USB_ISP1301)		+= isp1301.o
-obj-$(CONFIG_MV_U3D_PHY)		+= mv_u3d_phy.o
-obj-$(CONFIG_USB_EHCI_TEGRA)	+= tegra_usb_phy.o
-obj-$(CONFIG_USB_RCAR_PHY)		+= rcar-phy.o
-obj-$(CONFIG_SAMSUNG_USBPHY)		+= samsung-usbphy.o
+obj-$(CONFIG_USB_PHY)			+= phy.o
+
+# transceiver drivers, keep the list sorted
+
+obj-$(CONFIG_AB8500_USB)		+= phy-ab8500-usb.o
+phy-fsl-usb2-objs			:= phy-fsl-usb.o phy-fsm-usb.o
+obj-$(CONFIG_FSL_USB2_OTG)		+= phy-fsl-usb2.o
+obj-$(CONFIG_ISP1301_OMAP)		+= phy-isp1301.omap.o
+obj-$(CONFIG_MV_U3D_PHY)		+= phy-mv-u3d-usb.o
+obj-$(CONFIG_NOP_USB_XCEIV)		+= phy-nop.o
+obj-$(CONFIG_OMAP_CONTROL_USB)		+= phy-omap-control.o
+obj-$(CONFIG_OMAP_USB2)			+= phy-omap-usb2.o
+obj-$(CONFIG_OMAP_USB3)			+= phy-omap-usb3.o
+obj-$(CONFIG_SAMSUNG_USBPHY)		+= phy-samsung-usb.o
+obj-$(CONFIG_SAMSUNG_USB2PHY)		+= phy-samsung-usb2.o
+obj-$(CONFIG_SAMSUNG_USB3PHY)		+= phy-samsung-usb3.o
+obj-$(CONFIG_TWL4030_USB)		+= phy-twl4030-usb.o
+obj-$(CONFIG_TWL6030_USB)		+= phy-twl6030-usb.o
+obj-$(CONFIG_USB_EHCI_TEGRA)		+= phy-tegra-usb.o
+obj-$(CONFIG_USB_GPIO_VBUS)		+= phy-gpio-vbus-usb.o
+obj-$(CONFIG_USB_ISP1301)		+= phy-isp1301.o
+obj-$(CONFIG_USB_MSM_OTG)		+= phy-msm-usb.o
+obj-$(CONFIG_USB_MV_OTG)		+= phy-mv-usb.o
+obj-$(CONFIG_USB_MXS_PHY)		+= phy-mxs-usb.o
+obj-$(CONFIG_USB_RCAR_PHY)		+= phy-rcar-usb.o
+obj-$(CONFIG_USB_ULPI)			+= phy-ulpi.o
+obj-$(CONFIG_USB_ULPI_VIEWPORT)		+= phy-ulpi-viewport.o
diff --git a/drivers/usb/phy/isp1301.c b/drivers/usb/phy/isp1301.c
deleted file mode 100644
index 18dbf7e..0000000
--- a/drivers/usb/phy/isp1301.c
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * NXP ISP1301 USB transceiver driver
- *
- * Copyright (C) 2012 Roland Stigge
- *
- * Author: Roland Stigge <stigge@antcom.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/module.h>
-#include <linux/i2c.h>
-
-#define DRV_NAME		"isp1301"
-
-static const struct i2c_device_id isp1301_id[] = {
-	{ "isp1301", 0 },
-	{ }
-};
-
-static struct i2c_client *isp1301_i2c_client;
-
-static int isp1301_probe(struct i2c_client *client,
-			 const struct i2c_device_id *i2c_id)
-{
-	isp1301_i2c_client = client;
-	return 0;
-}
-
-static int isp1301_remove(struct i2c_client *client)
-{
-	return 0;
-}
-
-static struct i2c_driver isp1301_driver = {
-	.driver = {
-		.name = DRV_NAME,
-	},
-	.probe = isp1301_probe,
-	.remove = isp1301_remove,
-	.id_table = isp1301_id,
-};
-
-module_i2c_driver(isp1301_driver);
-
-static int match(struct device *dev, void *data)
-{
-	struct device_node *node = (struct device_node *)data;
-	return (dev->of_node == node) &&
-		(dev->driver == &isp1301_driver.driver);
-}
-
-struct i2c_client *isp1301_get_client(struct device_node *node)
-{
-	if (node) { /* reference of ISP1301 I2C node via DT */
-		struct device *dev = bus_find_device(&i2c_bus_type, NULL,
-						     node, match);
-		if (!dev)
-			return NULL;
-		return to_i2c_client(dev);
-	} else { /* non-DT: only one ISP1301 chip supported */
-		return isp1301_i2c_client;
-	}
-}
-EXPORT_SYMBOL_GPL(isp1301_get_client);
-
-MODULE_AUTHOR("Roland Stigge <stigge@antcom.de>");
-MODULE_DESCRIPTION("NXP ISP1301 USB transceiver driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/usb/phy/mv_u3d_phy.c b/drivers/usb/phy/mv_u3d_phy.c
deleted file mode 100644
index 9d85991..0000000
--- a/drivers/usb/phy/mv_u3d_phy.c
+++ /dev/null
@@ -1,343 +0,0 @@
-/*
- * Copyright (C) 2011 Marvell International Ltd. 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.
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/usb/otg.h>
-#include <linux/platform_data/mv_usb.h>
-
-#include "mv_u3d_phy.h"
-
-/*
- * struct mv_u3d_phy - transceiver driver state
- * @phy: transceiver structure
- * @dev: The parent device supplied to the probe function
- * @clk: usb phy clock
- * @base: usb phy register memory base
- */
-struct mv_u3d_phy {
-	struct usb_phy	phy;
-	struct mv_usb_platform_data *plat;
-	struct device	*dev;
-	struct clk	*clk;
-	void __iomem	*base;
-};
-
-static u32 mv_u3d_phy_read(void __iomem *base, u32 reg)
-{
-	void __iomem *addr, *data;
-
-	addr = base;
-	data = base + 0x4;
-
-	writel_relaxed(reg, addr);
-	return readl_relaxed(data);
-}
-
-static void mv_u3d_phy_set(void __iomem *base, u32 reg, u32 value)
-{
-	void __iomem *addr, *data;
-	u32 tmp;
-
-	addr = base;
-	data = base + 0x4;
-
-	writel_relaxed(reg, addr);
-	tmp = readl_relaxed(data);
-	tmp |= value;
-	writel_relaxed(tmp, data);
-}
-
-static void mv_u3d_phy_clear(void __iomem *base, u32 reg, u32 value)
-{
-	void __iomem *addr, *data;
-	u32 tmp;
-
-	addr = base;
-	data = base + 0x4;
-
-	writel_relaxed(reg, addr);
-	tmp = readl_relaxed(data);
-	tmp &= ~value;
-	writel_relaxed(tmp, data);
-}
-
-static void mv_u3d_phy_write(void __iomem *base, u32 reg, u32 value)
-{
-	void __iomem *addr, *data;
-
-	addr = base;
-	data = base + 0x4;
-
-	writel_relaxed(reg, addr);
-	writel_relaxed(value, data);
-}
-
-void mv_u3d_phy_shutdown(struct usb_phy *phy)
-{
-	struct mv_u3d_phy *mv_u3d_phy;
-	void __iomem *base;
-	u32 val;
-
-	mv_u3d_phy = container_of(phy, struct mv_u3d_phy, phy);
-	base = mv_u3d_phy->base;
-
-	/* Power down Reference Analog current, bit 15
-	 * Power down PLL, bit 14
-	 * Power down Receiver, bit 13
-	 * Power down Transmitter, bit 12
-	 * of USB3_POWER_PLL_CONTROL register
-	 */
-	val = mv_u3d_phy_read(base, USB3_POWER_PLL_CONTROL);
-	val &= ~(USB3_POWER_PLL_CONTROL_PU);
-	mv_u3d_phy_write(base, USB3_POWER_PLL_CONTROL, val);
-
-	if (mv_u3d_phy->clk)
-		clk_disable(mv_u3d_phy->clk);
-}
-
-static int mv_u3d_phy_init(struct usb_phy *phy)
-{
-	struct mv_u3d_phy *mv_u3d_phy;
-	void __iomem *base;
-	u32 val, count;
-
-	/* enable usb3 phy */
-	mv_u3d_phy = container_of(phy, struct mv_u3d_phy, phy);
-
-	if (mv_u3d_phy->clk)
-		clk_enable(mv_u3d_phy->clk);
-
-	base = mv_u3d_phy->base;
-
-	val = mv_u3d_phy_read(base, USB3_POWER_PLL_CONTROL);
-	val &= ~(USB3_POWER_PLL_CONTROL_PU_MASK);
-	val |= 0xF << USB3_POWER_PLL_CONTROL_PU_SHIFT;
-	mv_u3d_phy_write(base, USB3_POWER_PLL_CONTROL, val);
-	udelay(100);
-
-	mv_u3d_phy_write(base, USB3_RESET_CONTROL,
-			USB3_RESET_CONTROL_RESET_PIPE);
-	udelay(100);
-
-	mv_u3d_phy_write(base, USB3_RESET_CONTROL,
-			USB3_RESET_CONTROL_RESET_PIPE
-			| USB3_RESET_CONTROL_RESET_PHY);
-	udelay(100);
-
-	val = mv_u3d_phy_read(base, USB3_POWER_PLL_CONTROL);
-	val &= ~(USB3_POWER_PLL_CONTROL_REF_FREF_SEL_MASK
-		| USB3_POWER_PLL_CONTROL_PHY_MODE_MASK);
-	val |=  (USB3_PLL_25MHZ << USB3_POWER_PLL_CONTROL_REF_FREF_SEL_SHIFT)
-		| (0x5 << USB3_POWER_PLL_CONTROL_PHY_MODE_SHIFT);
-	mv_u3d_phy_write(base, USB3_POWER_PLL_CONTROL, val);
-	udelay(100);
-
-	mv_u3d_phy_clear(base, USB3_KVCO_CALI_CONTROL,
-		USB3_KVCO_CALI_CONTROL_USE_MAX_PLL_RATE_MASK);
-	udelay(100);
-
-	val = mv_u3d_phy_read(base, USB3_SQUELCH_FFE);
-	val &= ~(USB3_SQUELCH_FFE_FFE_CAP_SEL_MASK
-		| USB3_SQUELCH_FFE_FFE_RES_SEL_MASK
-		| USB3_SQUELCH_FFE_SQ_THRESH_IN_MASK);
-	val |= ((0xD << USB3_SQUELCH_FFE_FFE_CAP_SEL_SHIFT)
-		| (0x7 << USB3_SQUELCH_FFE_FFE_RES_SEL_SHIFT)
-		| (0x8 << USB3_SQUELCH_FFE_SQ_THRESH_IN_SHIFT));
-	mv_u3d_phy_write(base, USB3_SQUELCH_FFE, val);
-	udelay(100);
-
-	val = mv_u3d_phy_read(base, USB3_GEN1_SET0);
-	val &= ~USB3_GEN1_SET0_G1_TX_SLEW_CTRL_EN_MASK;
-	val |= 1 << USB3_GEN1_SET0_G1_TX_EMPH_EN_SHIFT;
-	mv_u3d_phy_write(base, USB3_GEN1_SET0, val);
-	udelay(100);
-
-	val = mv_u3d_phy_read(base, USB3_GEN2_SET0);
-	val &= ~(USB3_GEN2_SET0_G2_TX_AMP_MASK
-		| USB3_GEN2_SET0_G2_TX_EMPH_AMP_MASK
-		| USB3_GEN2_SET0_G2_TX_SLEW_CTRL_EN_MASK);
-	val |= ((0x14 << USB3_GEN2_SET0_G2_TX_AMP_SHIFT)
-		| (1 << USB3_GEN2_SET0_G2_TX_AMP_ADJ_SHIFT)
-		| (0xA << USB3_GEN2_SET0_G2_TX_EMPH_AMP_SHIFT)
-		| (1 << USB3_GEN2_SET0_G2_TX_EMPH_EN_SHIFT));
-	mv_u3d_phy_write(base, USB3_GEN2_SET0, val);
-	udelay(100);
-
-	mv_u3d_phy_read(base, USB3_TX_EMPPH);
-	val &= ~(USB3_TX_EMPPH_AMP_MASK
-		| USB3_TX_EMPPH_EN_MASK
-		| USB3_TX_EMPPH_AMP_FORCE_MASK
-		| USB3_TX_EMPPH_PAR1_MASK
-		| USB3_TX_EMPPH_PAR2_MASK);
-	val |= ((0xB << USB3_TX_EMPPH_AMP_SHIFT)
-		| (1 << USB3_TX_EMPPH_EN_SHIFT)
-		| (1 << USB3_TX_EMPPH_AMP_FORCE_SHIFT)
-		| (0x1C << USB3_TX_EMPPH_PAR1_SHIFT)
-		| (1 << USB3_TX_EMPPH_PAR2_SHIFT));
-
-	mv_u3d_phy_write(base, USB3_TX_EMPPH, val);
-	udelay(100);
-
-	val = mv_u3d_phy_read(base, USB3_GEN2_SET1);
-	val &= ~(USB3_GEN2_SET1_G2_RX_SELMUPI_MASK
-		| USB3_GEN2_SET1_G2_RX_SELMUPF_MASK
-		| USB3_GEN2_SET1_G2_RX_SELMUFI_MASK
-		| USB3_GEN2_SET1_G2_RX_SELMUFF_MASK);
-	val |= ((1 << USB3_GEN2_SET1_G2_RX_SELMUPI_SHIFT)
-		| (1 << USB3_GEN2_SET1_G2_RX_SELMUPF_SHIFT)
-		| (1 << USB3_GEN2_SET1_G2_RX_SELMUFI_SHIFT)
-		| (1 << USB3_GEN2_SET1_G2_RX_SELMUFF_SHIFT));
-	mv_u3d_phy_write(base, USB3_GEN2_SET1, val);
-	udelay(100);
-
-	val = mv_u3d_phy_read(base, USB3_DIGITAL_LOOPBACK_EN);
-	val &= ~USB3_DIGITAL_LOOPBACK_EN_SEL_BITS_MASK;
-	val |= 1 << USB3_DIGITAL_LOOPBACK_EN_SEL_BITS_SHIFT;
-	mv_u3d_phy_write(base, USB3_DIGITAL_LOOPBACK_EN, val);
-	udelay(100);
-
-	val = mv_u3d_phy_read(base, USB3_IMPEDANCE_TX_SSC);
-	val &= ~USB3_IMPEDANCE_TX_SSC_SSC_AMP_MASK;
-	val |= 0xC << USB3_IMPEDANCE_TX_SSC_SSC_AMP_SHIFT;
-	mv_u3d_phy_write(base, USB3_IMPEDANCE_TX_SSC, val);
-	udelay(100);
-
-	val = mv_u3d_phy_read(base, USB3_IMPEDANCE_CALI_CTRL);
-	val &= ~USB3_IMPEDANCE_CALI_CTRL_IMP_CAL_THR_MASK;
-	val |= 0x4 << USB3_IMPEDANCE_CALI_CTRL_IMP_CAL_THR_SHIFT;
-	mv_u3d_phy_write(base, USB3_IMPEDANCE_CALI_CTRL, val);
-	udelay(100);
-
-	val = mv_u3d_phy_read(base, USB3_PHY_ISOLATION_MODE);
-	val &= ~(USB3_PHY_ISOLATION_MODE_PHY_GEN_RX_MASK
-		| USB3_PHY_ISOLATION_MODE_PHY_GEN_TX_MASK
-		| USB3_PHY_ISOLATION_MODE_TX_DRV_IDLE_MASK);
-	val |= ((1 << USB3_PHY_ISOLATION_MODE_PHY_GEN_RX_SHIFT)
-		| (1 << USB3_PHY_ISOLATION_MODE_PHY_GEN_TX_SHIFT));
-	mv_u3d_phy_write(base, USB3_PHY_ISOLATION_MODE, val);
-	udelay(100);
-
-	val = mv_u3d_phy_read(base, USB3_TXDETRX);
-	val &= ~(USB3_TXDETRX_VTHSEL_MASK);
-	val |= 0x1 << USB3_TXDETRX_VTHSEL_SHIFT;
-	mv_u3d_phy_write(base, USB3_TXDETRX, val);
-	udelay(100);
-
-	dev_dbg(mv_u3d_phy->dev, "start calibration\n");
-
-calstart:
-	/* Perform Manual Calibration */
-	mv_u3d_phy_set(base, USB3_KVCO_CALI_CONTROL,
-		1 << USB3_KVCO_CALI_CONTROL_CAL_START_SHIFT);
-
-	mdelay(1);
-
-	count = 0;
-	while (1) {
-		val = mv_u3d_phy_read(base, USB3_KVCO_CALI_CONTROL);
-		if (val & (1 << USB3_KVCO_CALI_CONTROL_CAL_DONE_SHIFT))
-			break;
-		else if (count > 50) {
-			dev_dbg(mv_u3d_phy->dev, "calibration failure, retry...\n");
-			goto calstart;
-		}
-		count++;
-		mdelay(1);
-	}
-
-	/* active PIPE interface */
-	mv_u3d_phy_write(base, USB3_PIPE_SM_CTRL,
-		1 << USB3_PIPE_SM_CTRL_PHY_INIT_DONE);
-
-	return 0;
-}
-
-static int mv_u3d_phy_probe(struct platform_device *pdev)
-{
-	struct mv_u3d_phy *mv_u3d_phy;
-	struct mv_usb_platform_data *pdata;
-	struct device *dev = &pdev->dev;
-	struct resource *res;
-	void __iomem	*phy_base;
-	int	ret;
-
-	pdata = pdev->dev.platform_data;
-	if (!pdata) {
-		dev_err(&pdev->dev, "%s: no platform data defined\n", __func__);
-		return -EINVAL;
-	}
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(dev, "missing mem resource\n");
-		return -ENODEV;
-	}
-
-	phy_base = devm_ioremap_resource(dev, res);
-	if (IS_ERR(phy_base))
-		return PTR_ERR(phy_base);
-
-	mv_u3d_phy = devm_kzalloc(dev, sizeof(*mv_u3d_phy), GFP_KERNEL);
-	if (!mv_u3d_phy)
-		return -ENOMEM;
-
-	mv_u3d_phy->dev			= &pdev->dev;
-	mv_u3d_phy->plat		= pdata;
-	mv_u3d_phy->base		= phy_base;
-	mv_u3d_phy->phy.dev		= mv_u3d_phy->dev;
-	mv_u3d_phy->phy.label		= "mv-u3d-phy";
-	mv_u3d_phy->phy.init		= mv_u3d_phy_init;
-	mv_u3d_phy->phy.shutdown	= mv_u3d_phy_shutdown;
-
-	ret = usb_add_phy(&mv_u3d_phy->phy, USB_PHY_TYPE_USB3);
-	if (ret)
-		goto err;
-
-	if (!mv_u3d_phy->clk)
-		mv_u3d_phy->clk = clk_get(mv_u3d_phy->dev, "u3dphy");
-
-	platform_set_drvdata(pdev, mv_u3d_phy);
-
-	dev_info(&pdev->dev, "Initialized Marvell USB 3.0 PHY\n");
-err:
-	return ret;
-}
-
-static int __exit mv_u3d_phy_remove(struct platform_device *pdev)
-{
-	struct mv_u3d_phy *mv_u3d_phy = platform_get_drvdata(pdev);
-
-	usb_remove_phy(&mv_u3d_phy->phy);
-
-	if (mv_u3d_phy->clk) {
-		clk_put(mv_u3d_phy->clk);
-		mv_u3d_phy->clk = NULL;
-	}
-
-	return 0;
-}
-
-static struct platform_driver mv_u3d_phy_driver = {
-	.probe		= mv_u3d_phy_probe,
-	.remove		= mv_u3d_phy_remove,
-	.driver		= {
-		.name	= "mv-u3d-phy",
-		.owner	= THIS_MODULE,
-	},
-};
-
-module_platform_driver(mv_u3d_phy_driver);
-MODULE_DESCRIPTION("Marvell USB 3.0 PHY controller");
-MODULE_AUTHOR("Yu Xu <yuxu@marvell.com>");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:mv-u3d-phy");
diff --git a/drivers/usb/phy/mv_u3d_phy.h b/drivers/usb/phy/mv_u3d_phy.h
deleted file mode 100644
index 2a658cb..0000000
--- a/drivers/usb/phy/mv_u3d_phy.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (C) 2011 Marvell International Ltd. 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.
- */
-
-#ifndef __MV_U3D_PHY_H
-#define __MV_U3D_PHY_H
-
-#define USB3_POWER_PLL_CONTROL		0x1
-#define USB3_KVCO_CALI_CONTROL		0x2
-#define USB3_IMPEDANCE_CALI_CTRL	0x3
-#define USB3_IMPEDANCE_TX_SSC		0x4
-#define USB3_SQUELCH_FFE		0x6
-#define USB3_GEN1_SET0			0xD
-#define USB3_GEN2_SET0			0xF
-#define USB3_GEN2_SET1			0x10
-#define USB3_DIGITAL_LOOPBACK_EN	0x23
-#define USB3_PHY_ISOLATION_MODE		0x26
-#define USB3_TXDETRX			0x48
-#define USB3_TX_EMPPH			0x5E
-#define USB3_RESET_CONTROL		0x90
-#define USB3_PIPE_SM_CTRL		0x91
-
-#define USB3_RESET_CONTROL_RESET_PIPE			0x1
-#define USB3_RESET_CONTROL_RESET_PHY			0x2
-
-#define USB3_POWER_PLL_CONTROL_REF_FREF_SEL_MASK	(0x1F << 0)
-#define USB3_POWER_PLL_CONTROL_REF_FREF_SEL_SHIFT	0
-#define USB3_PLL_25MHZ					0x2
-#define USB3_PLL_26MHZ					0x5
-#define USB3_POWER_PLL_CONTROL_PHY_MODE_MASK		(0x7 << 5)
-#define USB3_POWER_PLL_CONTROL_PHY_MODE_SHIFT		5
-#define USB3_POWER_PLL_CONTROL_PU_MASK			(0xF << 12)
-#define USB3_POWER_PLL_CONTROL_PU_SHIFT			12
-#define USB3_POWER_PLL_CONTROL_PU			(0xF << 12)
-
-#define USB3_KVCO_CALI_CONTROL_USE_MAX_PLL_RATE_MASK	(0x1 << 12)
-#define USB3_KVCO_CALI_CONTROL_USE_MAX_PLL_RATE_SHIFT	12
-#define USB3_KVCO_CALI_CONTROL_CAL_DONE_SHIFT		14
-#define USB3_KVCO_CALI_CONTROL_CAL_START_SHIFT		15
-
-#define USB3_SQUELCH_FFE_FFE_CAP_SEL_MASK		0xF
-#define USB3_SQUELCH_FFE_FFE_CAP_SEL_SHIFT		0
-#define USB3_SQUELCH_FFE_FFE_RES_SEL_MASK		(0x7 << 4)
-#define USB3_SQUELCH_FFE_FFE_RES_SEL_SHIFT		4
-#define USB3_SQUELCH_FFE_SQ_THRESH_IN_MASK		(0x1F << 8)
-#define USB3_SQUELCH_FFE_SQ_THRESH_IN_SHIFT		8
-
-#define USB3_GEN1_SET0_G1_TX_SLEW_CTRL_EN_MASK		(0x1 << 15)
-#define USB3_GEN1_SET0_G1_TX_EMPH_EN_SHIFT		11
-
-#define USB3_GEN2_SET0_G2_TX_AMP_MASK			(0x1F << 1)
-#define USB3_GEN2_SET0_G2_TX_AMP_SHIFT			1
-#define USB3_GEN2_SET0_G2_TX_AMP_ADJ_SHIFT		6
-#define USB3_GEN2_SET0_G2_TX_EMPH_AMP_MASK		(0xF << 7)
-#define USB3_GEN2_SET0_G2_TX_EMPH_AMP_SHIFT		7
-#define USB3_GEN2_SET0_G2_TX_EMPH_EN_MASK		(0x1 << 11)
-#define USB3_GEN2_SET0_G2_TX_EMPH_EN_SHIFT		11
-#define USB3_GEN2_SET0_G2_TX_SLEW_CTRL_EN_MASK		(0x1 << 15)
-#define USB3_GEN2_SET0_G2_TX_SLEW_CTRL_EN_SHIFT		15
-
-#define USB3_GEN2_SET1_G2_RX_SELMUPI_MASK		(0x7 << 0)
-#define USB3_GEN2_SET1_G2_RX_SELMUPI_SHIFT		0
-#define USB3_GEN2_SET1_G2_RX_SELMUPF_MASK		(0x7 << 3)
-#define USB3_GEN2_SET1_G2_RX_SELMUPF_SHIFT		3
-#define USB3_GEN2_SET1_G2_RX_SELMUFI_MASK		(0x3 << 6)
-#define USB3_GEN2_SET1_G2_RX_SELMUFI_SHIFT		6
-#define USB3_GEN2_SET1_G2_RX_SELMUFF_MASK		(0x3 << 8)
-#define USB3_GEN2_SET1_G2_RX_SELMUFF_SHIFT		8
-
-#define USB3_DIGITAL_LOOPBACK_EN_SEL_BITS_MASK		(0x3 << 10)
-#define USB3_DIGITAL_LOOPBACK_EN_SEL_BITS_SHIFT		10
-
-#define USB3_IMPEDANCE_CALI_CTRL_IMP_CAL_THR_MASK	(0x7 << 12)
-#define USB3_IMPEDANCE_CALI_CTRL_IMP_CAL_THR_SHIFT	12
-
-#define USB3_IMPEDANCE_TX_SSC_SSC_AMP_MASK		(0x3F << 0)
-#define USB3_IMPEDANCE_TX_SSC_SSC_AMP_SHIFT		0
-
-#define USB3_PHY_ISOLATION_MODE_PHY_GEN_RX_MASK		0xF
-#define USB3_PHY_ISOLATION_MODE_PHY_GEN_RX_SHIFT	0
-#define USB3_PHY_ISOLATION_MODE_PHY_GEN_TX_MASK		(0xF << 4)
-#define USB3_PHY_ISOLATION_MODE_PHY_GEN_TX_SHIFT	4
-#define USB3_PHY_ISOLATION_MODE_TX_DRV_IDLE_MASK	(0x1 << 8)
-
-#define USB3_TXDETRX_VTHSEL_MASK			(0x3 << 4)
-#define USB3_TXDETRX_VTHSEL_SHIFT			4
-
-#define USB3_TX_EMPPH_AMP_MASK				(0xF << 0)
-#define USB3_TX_EMPPH_AMP_SHIFT				0
-#define USB3_TX_EMPPH_EN_MASK				(0x1 << 6)
-#define USB3_TX_EMPPH_EN_SHIFT				6
-#define USB3_TX_EMPPH_AMP_FORCE_MASK			(0x1 << 7)
-#define USB3_TX_EMPPH_AMP_FORCE_SHIFT			7
-#define USB3_TX_EMPPH_PAR1_MASK				(0x1F << 8)
-#define USB3_TX_EMPPH_PAR1_SHIFT			8
-#define USB3_TX_EMPPH_PAR2_MASK				(0x1 << 13)
-#define USB3_TX_EMPPH_PAR2_SHIFT			13
-
-#define USB3_PIPE_SM_CTRL_PHY_INIT_DONE			15
-
-#endif /* __MV_U3D_PHY_H */
diff --git a/drivers/usb/phy/omap-control-usb.c b/drivers/usb/phy/omap-control-usb.c
deleted file mode 100644
index 1419ced..0000000
--- a/drivers/usb/phy/omap-control-usb.c
+++ /dev/null
@@ -1,289 +0,0 @@
-/*
- * omap-control-usb.c - The USB part of control module.
- *
- * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.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.
- *
- * Author: Kishon Vijay Abraham I <kishon@ti.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.
- *
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/of.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/clk.h>
-#include <linux/usb/omap_control_usb.h>
-
-static struct omap_control_usb *control_usb;
-
-/**
- * omap_get_control_dev - returns the device pointer for this control device
- *
- * This API should be called to get the device pointer for this control
- * module device. This device pointer should be used for called other
- * exported API's in this driver.
- *
- * To be used by PHY driver and glue driver.
- */
-struct device *omap_get_control_dev(void)
-{
-	if (!control_usb)
-		return ERR_PTR(-ENODEV);
-
-	return control_usb->dev;
-}
-EXPORT_SYMBOL_GPL(omap_get_control_dev);
-
-/**
- * omap_control_usb3_phy_power - power on/off the serializer using control
- *	module
- * @dev: the control module device
- * @on: 0 to off and 1 to on based on powering on or off the PHY
- *
- * usb3 PHY driver should call this API to power on or off the PHY.
- */
-void omap_control_usb3_phy_power(struct device *dev, bool on)
-{
-	u32 val;
-	unsigned long rate;
-	struct omap_control_usb	*control_usb = dev_get_drvdata(dev);
-
-	if (control_usb->type != OMAP_CTRL_DEV_TYPE2)
-		return;
-
-	rate = clk_get_rate(control_usb->sys_clk);
-	rate = rate/1000000;
-
-	val = readl(control_usb->phy_power);
-
-	if (on) {
-		val &= ~(OMAP_CTRL_USB_PWRCTL_CLK_CMD_MASK |
-			OMAP_CTRL_USB_PWRCTL_CLK_FREQ_MASK);
-		val |= OMAP_CTRL_USB3_PHY_TX_RX_POWERON <<
-			OMAP_CTRL_USB_PWRCTL_CLK_CMD_SHIFT;
-		val |= rate << OMAP_CTRL_USB_PWRCTL_CLK_FREQ_SHIFT;
-	} else {
-		val &= ~OMAP_CTRL_USB_PWRCTL_CLK_CMD_MASK;
-		val |= OMAP_CTRL_USB3_PHY_TX_RX_POWEROFF <<
-			OMAP_CTRL_USB_PWRCTL_CLK_CMD_SHIFT;
-	}
-
-	writel(val, control_usb->phy_power);
-}
-EXPORT_SYMBOL_GPL(omap_control_usb3_phy_power);
-
-/**
- * omap_control_usb_phy_power - power on/off the phy using control module reg
- * @dev: the control module device
- * @on: 0 or 1, based on powering on or off the PHY
- */
-void omap_control_usb_phy_power(struct device *dev, int on)
-{
-	u32 val;
-	struct omap_control_usb	*control_usb = dev_get_drvdata(dev);
-
-	val = readl(control_usb->dev_conf);
-
-	if (on)
-		val &= ~OMAP_CTRL_DEV_PHY_PD;
-	else
-		val |= OMAP_CTRL_DEV_PHY_PD;
-
-	writel(val, control_usb->dev_conf);
-}
-EXPORT_SYMBOL_GPL(omap_control_usb_phy_power);
-
-/**
- * omap_control_usb_host_mode - set AVALID, VBUSVALID and ID pin in grounded
- * @ctrl_usb: struct omap_control_usb *
- *
- * Writes to the mailbox register to notify the usb core that a usb
- * device has been connected.
- */
-static void omap_control_usb_host_mode(struct omap_control_usb *ctrl_usb)
-{
-	u32 val;
-
-	val = readl(ctrl_usb->otghs_control);
-	val &= ~(OMAP_CTRL_DEV_IDDIG | OMAP_CTRL_DEV_SESSEND);
-	val |= OMAP_CTRL_DEV_AVALID | OMAP_CTRL_DEV_VBUSVALID;
-	writel(val, ctrl_usb->otghs_control);
-}
-
-/**
- * omap_control_usb_device_mode - set AVALID, VBUSVALID and ID pin in high
- * impedance
- * @ctrl_usb: struct omap_control_usb *
- *
- * Writes to the mailbox register to notify the usb core that it has been
- * connected to a usb host.
- */
-static void omap_control_usb_device_mode(struct omap_control_usb *ctrl_usb)
-{
-	u32 val;
-
-	val = readl(ctrl_usb->otghs_control);
-	val &= ~OMAP_CTRL_DEV_SESSEND;
-	val |= OMAP_CTRL_DEV_IDDIG | OMAP_CTRL_DEV_AVALID |
-		OMAP_CTRL_DEV_VBUSVALID;
-	writel(val, ctrl_usb->otghs_control);
-}
-
-/**
- * omap_control_usb_set_sessionend - Enable SESSIONEND and IDIG to high
- * impedance
- * @ctrl_usb: struct omap_control_usb *
- *
- * Writes to the mailbox register to notify the usb core it's now in
- * disconnected state.
- */
-static void omap_control_usb_set_sessionend(struct omap_control_usb *ctrl_usb)
-{
-	u32 val;
-
-	val = readl(ctrl_usb->otghs_control);
-	val &= ~(OMAP_CTRL_DEV_AVALID | OMAP_CTRL_DEV_VBUSVALID);
-	val |= OMAP_CTRL_DEV_IDDIG | OMAP_CTRL_DEV_SESSEND;
-	writel(val, ctrl_usb->otghs_control);
-}
-
-/**
- * omap_control_usb_set_mode - Calls to functions to set USB in one of host mode
- * or device mode or to denote disconnected state
- * @dev: the control module device
- * @mode: The mode to which usb should be configured
- *
- * This is an API to write to the mailbox register to notify the usb core that
- * a usb device has been connected.
- */
-void omap_control_usb_set_mode(struct device *dev,
-	enum omap_control_usb_mode mode)
-{
-	struct omap_control_usb	*ctrl_usb;
-
-	if (IS_ERR(dev) || control_usb->type != OMAP_CTRL_DEV_TYPE1)
-		return;
-
-	ctrl_usb = dev_get_drvdata(dev);
-
-	switch (mode) {
-	case USB_MODE_HOST:
-		omap_control_usb_host_mode(ctrl_usb);
-		break;
-	case USB_MODE_DEVICE:
-		omap_control_usb_device_mode(ctrl_usb);
-		break;
-	case USB_MODE_DISCONNECT:
-		omap_control_usb_set_sessionend(ctrl_usb);
-		break;
-	default:
-		dev_vdbg(dev, "invalid omap control usb mode\n");
-	}
-}
-EXPORT_SYMBOL_GPL(omap_control_usb_set_mode);
-
-static int omap_control_usb_probe(struct platform_device *pdev)
-{
-	struct resource	*res;
-	struct device_node *np = pdev->dev.of_node;
-	struct omap_control_usb_platform_data *pdata = pdev->dev.platform_data;
-
-	control_usb = devm_kzalloc(&pdev->dev, sizeof(*control_usb),
-		GFP_KERNEL);
-	if (!control_usb) {
-		dev_err(&pdev->dev, "unable to alloc memory for control usb\n");
-		return -ENOMEM;
-	}
-
-	if (np) {
-		of_property_read_u32(np, "ti,type", &control_usb->type);
-	} else if (pdata) {
-		control_usb->type = pdata->type;
-	} else {
-		dev_err(&pdev->dev, "no pdata present\n");
-		return -EINVAL;
-	}
-
-	control_usb->dev	= &pdev->dev;
-
-	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
-		"control_dev_conf");
-	control_usb->dev_conf = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(control_usb->dev_conf))
-		return PTR_ERR(control_usb->dev_conf);
-
-	if (control_usb->type == OMAP_CTRL_DEV_TYPE1) {
-		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
-			"otghs_control");
-		control_usb->otghs_control = devm_ioremap_resource(
-			&pdev->dev, res);
-		if (IS_ERR(control_usb->otghs_control))
-			return PTR_ERR(control_usb->otghs_control);
-	}
-
-	if (control_usb->type == OMAP_CTRL_DEV_TYPE2) {
-		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
-			"phy_power_usb");
-		control_usb->phy_power = devm_ioremap_resource(
-			&pdev->dev, res);
-		if (IS_ERR(control_usb->phy_power))
-			return PTR_ERR(control_usb->phy_power);
-
-		control_usb->sys_clk = devm_clk_get(control_usb->dev,
-			"sys_clkin");
-		if (IS_ERR(control_usb->sys_clk)) {
-			pr_err("%s: unable to get sys_clkin\n", __func__);
-			return -EINVAL;
-		}
-	}
-
-
-	dev_set_drvdata(control_usb->dev, control_usb);
-
-	return 0;
-}
-
-#ifdef CONFIG_OF
-static const struct of_device_id omap_control_usb_id_table[] = {
-	{ .compatible = "ti,omap-control-usb" },
-	{}
-};
-MODULE_DEVICE_TABLE(of, omap_control_usb_id_table);
-#endif
-
-static struct platform_driver omap_control_usb_driver = {
-	.probe		= omap_control_usb_probe,
-	.driver		= {
-		.name	= "omap-control-usb",
-		.owner	= THIS_MODULE,
-		.of_match_table = of_match_ptr(omap_control_usb_id_table),
-	},
-};
-
-static int __init omap_control_usb_init(void)
-{
-	return platform_driver_register(&omap_control_usb_driver);
-}
-subsys_initcall(omap_control_usb_init);
-
-static void __exit omap_control_usb_exit(void)
-{
-	platform_driver_unregister(&omap_control_usb_driver);
-}
-module_exit(omap_control_usb_exit);
-
-MODULE_ALIAS("platform: omap_control_usb");
-MODULE_AUTHOR("Texas Instruments Inc.");
-MODULE_DESCRIPTION("OMAP Control Module USB Driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/phy/omap-usb2.c b/drivers/usb/phy/omap-usb2.c
deleted file mode 100644
index 844ab68..0000000
--- a/drivers/usb/phy/omap-usb2.c
+++ /dev/null
@@ -1,273 +0,0 @@
-/*
- * omap-usb2.c - USB PHY, talking to musb controller in OMAP.
- *
- * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.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.
- *
- * Author: Kishon Vijay Abraham I <kishon@ti.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.
- *
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/of.h>
-#include <linux/io.h>
-#include <linux/usb/omap_usb.h>
-#include <linux/usb/phy_companion.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/pm_runtime.h>
-#include <linux/delay.h>
-#include <linux/usb/omap_control_usb.h>
-
-/**
- * omap_usb2_set_comparator - links the comparator present in the sytem with
- *	this phy
- * @comparator - the companion phy(comparator) for this phy
- *
- * The phy companion driver should call this API passing the phy_companion
- * filled with set_vbus and start_srp to be used by usb phy.
- *
- * For use by phy companion driver
- */
-int omap_usb2_set_comparator(struct phy_companion *comparator)
-{
-	struct omap_usb	*phy;
-	struct usb_phy	*x = usb_get_phy(USB_PHY_TYPE_USB2);
-
-	if (IS_ERR(x))
-		return -ENODEV;
-
-	phy = phy_to_omapusb(x);
-	phy->comparator = comparator;
-	return 0;
-}
-EXPORT_SYMBOL_GPL(omap_usb2_set_comparator);
-
-static int omap_usb_set_vbus(struct usb_otg *otg, bool enabled)
-{
-	struct omap_usb *phy = phy_to_omapusb(otg->phy);
-
-	if (!phy->comparator)
-		return -ENODEV;
-
-	return phy->comparator->set_vbus(phy->comparator, enabled);
-}
-
-static int omap_usb_start_srp(struct usb_otg *otg)
-{
-	struct omap_usb *phy = phy_to_omapusb(otg->phy);
-
-	if (!phy->comparator)
-		return -ENODEV;
-
-	return phy->comparator->start_srp(phy->comparator);
-}
-
-static int omap_usb_set_host(struct usb_otg *otg, struct usb_bus *host)
-{
-	struct usb_phy	*phy = otg->phy;
-
-	otg->host = host;
-	if (!host)
-		phy->state = OTG_STATE_UNDEFINED;
-
-	return 0;
-}
-
-static int omap_usb_set_peripheral(struct usb_otg *otg,
-		struct usb_gadget *gadget)
-{
-	struct usb_phy	*phy = otg->phy;
-
-	otg->gadget = gadget;
-	if (!gadget)
-		phy->state = OTG_STATE_UNDEFINED;
-
-	return 0;
-}
-
-static int omap_usb2_suspend(struct usb_phy *x, int suspend)
-{
-	u32 ret;
-	struct omap_usb *phy = phy_to_omapusb(x);
-
-	if (suspend && !phy->is_suspended) {
-		omap_control_usb_phy_power(phy->control_dev, 0);
-		pm_runtime_put_sync(phy->dev);
-		phy->is_suspended = 1;
-	} else if (!suspend && phy->is_suspended) {
-		ret = pm_runtime_get_sync(phy->dev);
-		if (ret < 0) {
-			dev_err(phy->dev, "get_sync failed with err %d\n",
-									ret);
-			return ret;
-		}
-		omap_control_usb_phy_power(phy->control_dev, 1);
-		phy->is_suspended = 0;
-	}
-
-	return 0;
-}
-
-static int omap_usb2_probe(struct platform_device *pdev)
-{
-	struct omap_usb			*phy;
-	struct usb_otg			*otg;
-
-	phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
-	if (!phy) {
-		dev_err(&pdev->dev, "unable to allocate memory for USB2 PHY\n");
-		return -ENOMEM;
-	}
-
-	otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL);
-	if (!otg) {
-		dev_err(&pdev->dev, "unable to allocate memory for USB OTG\n");
-		return -ENOMEM;
-	}
-
-	phy->dev		= &pdev->dev;
-
-	phy->phy.dev		= phy->dev;
-	phy->phy.label		= "omap-usb2";
-	phy->phy.set_suspend	= omap_usb2_suspend;
-	phy->phy.otg		= otg;
-	phy->phy.type		= USB_PHY_TYPE_USB2;
-
-	phy->control_dev = omap_get_control_dev();
-	if (IS_ERR(phy->control_dev)) {
-		dev_dbg(&pdev->dev, "Failed to get control device\n");
-		return -ENODEV;
-	}
-
-	phy->is_suspended	= 1;
-	omap_control_usb_phy_power(phy->control_dev, 0);
-
-	otg->set_host		= omap_usb_set_host;
-	otg->set_peripheral	= omap_usb_set_peripheral;
-	otg->set_vbus		= omap_usb_set_vbus;
-	otg->start_srp		= omap_usb_start_srp;
-	otg->phy		= &phy->phy;
-
-	phy->wkupclk = devm_clk_get(phy->dev, "usb_phy_cm_clk32k");
-	if (IS_ERR(phy->wkupclk)) {
-		dev_err(&pdev->dev, "unable to get usb_phy_cm_clk32k\n");
-		return PTR_ERR(phy->wkupclk);
-	}
-	clk_prepare(phy->wkupclk);
-
-	phy->optclk = devm_clk_get(phy->dev, "usb_otg_ss_refclk960m");
-	if (IS_ERR(phy->optclk))
-		dev_vdbg(&pdev->dev, "unable to get refclk960m\n");
-	else
-		clk_prepare(phy->optclk);
-
-	usb_add_phy_dev(&phy->phy);
-
-	platform_set_drvdata(pdev, phy);
-
-	pm_runtime_enable(phy->dev);
-
-	return 0;
-}
-
-static int omap_usb2_remove(struct platform_device *pdev)
-{
-	struct omap_usb	*phy = platform_get_drvdata(pdev);
-
-	clk_unprepare(phy->wkupclk);
-	if (!IS_ERR(phy->optclk))
-		clk_unprepare(phy->optclk);
-	usb_remove_phy(&phy->phy);
-
-	return 0;
-}
-
-#ifdef CONFIG_PM_RUNTIME
-
-static int omap_usb2_runtime_suspend(struct device *dev)
-{
-	struct platform_device	*pdev = to_platform_device(dev);
-	struct omap_usb	*phy = platform_get_drvdata(pdev);
-
-	clk_disable(phy->wkupclk);
-	if (!IS_ERR(phy->optclk))
-		clk_disable(phy->optclk);
-
-	return 0;
-}
-
-static int omap_usb2_runtime_resume(struct device *dev)
-{
-	u32 ret = 0;
-	struct platform_device	*pdev = to_platform_device(dev);
-	struct omap_usb	*phy = platform_get_drvdata(pdev);
-
-	ret = clk_enable(phy->wkupclk);
-	if (ret < 0) {
-		dev_err(phy->dev, "Failed to enable wkupclk %d\n", ret);
-		goto err0;
-	}
-
-	if (!IS_ERR(phy->optclk)) {
-		ret = clk_enable(phy->optclk);
-		if (ret < 0) {
-			dev_err(phy->dev, "Failed to enable optclk %d\n", ret);
-			goto err1;
-		}
-	}
-
-	return 0;
-
-err1:
-	clk_disable(phy->wkupclk);
-
-err0:
-	return ret;
-}
-
-static const struct dev_pm_ops omap_usb2_pm_ops = {
-	SET_RUNTIME_PM_OPS(omap_usb2_runtime_suspend, omap_usb2_runtime_resume,
-		NULL)
-};
-
-#define DEV_PM_OPS     (&omap_usb2_pm_ops)
-#else
-#define DEV_PM_OPS     NULL
-#endif
-
-#ifdef CONFIG_OF
-static const struct of_device_id omap_usb2_id_table[] = {
-	{ .compatible = "ti,omap-usb2" },
-	{}
-};
-MODULE_DEVICE_TABLE(of, omap_usb2_id_table);
-#endif
-
-static struct platform_driver omap_usb2_driver = {
-	.probe		= omap_usb2_probe,
-	.remove		= omap_usb2_remove,
-	.driver		= {
-		.name	= "omap-usb2",
-		.owner	= THIS_MODULE,
-		.pm	= DEV_PM_OPS,
-		.of_match_table = of_match_ptr(omap_usb2_id_table),
-	},
-};
-
-module_platform_driver(omap_usb2_driver);
-
-MODULE_ALIAS("platform: omap_usb2");
-MODULE_AUTHOR("Texas Instruments Inc.");
-MODULE_DESCRIPTION("OMAP USB2 phy driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/phy/omap-usb3.c b/drivers/usb/phy/omap-usb3.c
deleted file mode 100644
index a6e60b1..0000000
--- a/drivers/usb/phy/omap-usb3.c
+++ /dev/null
@@ -1,353 +0,0 @@
-/*
- * omap-usb3 - USB PHY, talking to dwc3 controller in OMAP.
- *
- * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.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.
- *
- * Author: Kishon Vijay Abraham I <kishon@ti.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.
- *
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/usb/omap_usb.h>
-#include <linux/of.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/pm_runtime.h>
-#include <linux/delay.h>
-#include <linux/usb/omap_control_usb.h>
-
-#define	NUM_SYS_CLKS		5
-#define	PLL_STATUS		0x00000004
-#define	PLL_GO			0x00000008
-#define	PLL_CONFIGURATION1	0x0000000C
-#define	PLL_CONFIGURATION2	0x00000010
-#define	PLL_CONFIGURATION3	0x00000014
-#define	PLL_CONFIGURATION4	0x00000020
-
-#define	PLL_REGM_MASK		0x001FFE00
-#define	PLL_REGM_SHIFT		0x9
-#define	PLL_REGM_F_MASK		0x0003FFFF
-#define	PLL_REGM_F_SHIFT	0x0
-#define	PLL_REGN_MASK		0x000001FE
-#define	PLL_REGN_SHIFT		0x1
-#define	PLL_SELFREQDCO_MASK	0x0000000E
-#define	PLL_SELFREQDCO_SHIFT	0x1
-#define	PLL_SD_MASK		0x0003FC00
-#define	PLL_SD_SHIFT		0x9
-#define	SET_PLL_GO		0x1
-#define	PLL_TICOPWDN		0x10000
-#define	PLL_LOCK		0x2
-#define	PLL_IDLE		0x1
-
-/*
- * This is an Empirical value that works, need to confirm the actual
- * value required for the USB3PHY_PLL_CONFIGURATION2.PLL_IDLE status
- * to be correctly reflected in the USB3PHY_PLL_STATUS register.
- */
-# define PLL_IDLE_TIME  100;
-
-enum sys_clk_rate {
-	CLK_RATE_UNDEFINED = -1,
-	CLK_RATE_12MHZ,
-	CLK_RATE_16MHZ,
-	CLK_RATE_19MHZ,
-	CLK_RATE_26MHZ,
-	CLK_RATE_38MHZ
-};
-
-static struct usb_dpll_params omap_usb3_dpll_params[NUM_SYS_CLKS] = {
-	{1250, 5, 4, 20, 0},		/* 12 MHz */
-	{3125, 20, 4, 20, 0},		/* 16.8 MHz */
-	{1172, 8, 4, 20, 65537},	/* 19.2 MHz */
-	{1250, 12, 4, 20, 0},		/* 26 MHz */
-	{3125, 47, 4, 20, 92843},	/* 38.4 MHz */
-};
-
-static int omap_usb3_suspend(struct usb_phy *x, int suspend)
-{
-	struct omap_usb *phy = phy_to_omapusb(x);
-	int	val;
-	int timeout = PLL_IDLE_TIME;
-
-	if (suspend && !phy->is_suspended) {
-		val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
-		val |= PLL_IDLE;
-		omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
-
-		do {
-			val = omap_usb_readl(phy->pll_ctrl_base, PLL_STATUS);
-			if (val & PLL_TICOPWDN)
-				break;
-			udelay(1);
-		} while (--timeout);
-
-		omap_control_usb3_phy_power(phy->control_dev, 0);
-
-		phy->is_suspended	= 1;
-	} else if (!suspend && phy->is_suspended) {
-		phy->is_suspended	= 0;
-
-		val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
-		val &= ~PLL_IDLE;
-		omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
-
-		do {
-			val = omap_usb_readl(phy->pll_ctrl_base, PLL_STATUS);
-			if (!(val & PLL_TICOPWDN))
-				break;
-			udelay(1);
-		} while (--timeout);
-	}
-
-	return 0;
-}
-
-static inline enum sys_clk_rate __get_sys_clk_index(unsigned long rate)
-{
-	switch (rate) {
-	case 12000000:
-		return CLK_RATE_12MHZ;
-	case 16800000:
-		return CLK_RATE_16MHZ;
-	case 19200000:
-		return CLK_RATE_19MHZ;
-	case 26000000:
-		return CLK_RATE_26MHZ;
-	case 38400000:
-		return CLK_RATE_38MHZ;
-	default:
-		return CLK_RATE_UNDEFINED;
-	}
-}
-
-static void omap_usb_dpll_relock(struct omap_usb *phy)
-{
-	u32		val;
-	unsigned long	timeout;
-
-	omap_usb_writel(phy->pll_ctrl_base, PLL_GO, SET_PLL_GO);
-
-	timeout = jiffies + msecs_to_jiffies(20);
-	do {
-		val = omap_usb_readl(phy->pll_ctrl_base, PLL_STATUS);
-		if (val & PLL_LOCK)
-			break;
-	} while (!WARN_ON(time_after(jiffies, timeout)));
-}
-
-static int omap_usb_dpll_lock(struct omap_usb *phy)
-{
-	u32			val;
-	unsigned long		rate;
-	enum sys_clk_rate	clk_index;
-
-	rate		= clk_get_rate(phy->sys_clk);
-	clk_index	= __get_sys_clk_index(rate);
-
-	if (clk_index == CLK_RATE_UNDEFINED) {
-		pr_err("dpll cannot be locked for sys clk freq:%luHz\n", rate);
-		return -EINVAL;
-	}
-
-	val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1);
-	val &= ~PLL_REGN_MASK;
-	val |= omap_usb3_dpll_params[clk_index].n << PLL_REGN_SHIFT;
-	omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val);
-
-	val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
-	val &= ~PLL_SELFREQDCO_MASK;
-	val |= omap_usb3_dpll_params[clk_index].freq << PLL_SELFREQDCO_SHIFT;
-	omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
-
-	val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1);
-	val &= ~PLL_REGM_MASK;
-	val |= omap_usb3_dpll_params[clk_index].m << PLL_REGM_SHIFT;
-	omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val);
-
-	val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION4);
-	val &= ~PLL_REGM_F_MASK;
-	val |= omap_usb3_dpll_params[clk_index].mf << PLL_REGM_F_SHIFT;
-	omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION4, val);
-
-	val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION3);
-	val &= ~PLL_SD_MASK;
-	val |= omap_usb3_dpll_params[clk_index].sd << PLL_SD_SHIFT;
-	omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION3, val);
-
-	omap_usb_dpll_relock(phy);
-
-	return 0;
-}
-
-static int omap_usb3_init(struct usb_phy *x)
-{
-	struct omap_usb	*phy = phy_to_omapusb(x);
-
-	omap_usb_dpll_lock(phy);
-	omap_control_usb3_phy_power(phy->control_dev, 1);
-
-	return 0;
-}
-
-static int omap_usb3_probe(struct platform_device *pdev)
-{
-	struct omap_usb			*phy;
-	struct resource			*res;
-
-	phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
-	if (!phy) {
-		dev_err(&pdev->dev, "unable to alloc mem for OMAP USB3 PHY\n");
-		return -ENOMEM;
-	}
-
-	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pll_ctrl");
-	phy->pll_ctrl_base = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(phy->pll_ctrl_base))
-		return PTR_ERR(phy->pll_ctrl_base);
-
-	phy->dev		= &pdev->dev;
-
-	phy->phy.dev		= phy->dev;
-	phy->phy.label		= "omap-usb3";
-	phy->phy.init		= omap_usb3_init;
-	phy->phy.set_suspend	= omap_usb3_suspend;
-	phy->phy.type		= USB_PHY_TYPE_USB3;
-
-	phy->is_suspended	= 1;
-	phy->wkupclk = devm_clk_get(phy->dev, "usb_phy_cm_clk32k");
-	if (IS_ERR(phy->wkupclk)) {
-		dev_err(&pdev->dev, "unable to get usb_phy_cm_clk32k\n");
-		return PTR_ERR(phy->wkupclk);
-	}
-	clk_prepare(phy->wkupclk);
-
-	phy->optclk = devm_clk_get(phy->dev, "usb_otg_ss_refclk960m");
-	if (IS_ERR(phy->optclk)) {
-		dev_err(&pdev->dev, "unable to get usb_otg_ss_refclk960m\n");
-		return PTR_ERR(phy->optclk);
-	}
-	clk_prepare(phy->optclk);
-
-	phy->sys_clk = devm_clk_get(phy->dev, "sys_clkin");
-	if (IS_ERR(phy->sys_clk)) {
-		pr_err("%s: unable to get sys_clkin\n", __func__);
-		return -EINVAL;
-	}
-
-	phy->control_dev = omap_get_control_dev();
-	if (IS_ERR(phy->control_dev)) {
-		dev_dbg(&pdev->dev, "Failed to get control device\n");
-		return -ENODEV;
-	}
-
-	omap_control_usb3_phy_power(phy->control_dev, 0);
-	usb_add_phy_dev(&phy->phy);
-
-	platform_set_drvdata(pdev, phy);
-
-	pm_runtime_enable(phy->dev);
-	pm_runtime_get(&pdev->dev);
-
-	return 0;
-}
-
-static int omap_usb3_remove(struct platform_device *pdev)
-{
-	struct omap_usb *phy = platform_get_drvdata(pdev);
-
-	clk_unprepare(phy->wkupclk);
-	clk_unprepare(phy->optclk);
-	usb_remove_phy(&phy->phy);
-	if (!pm_runtime_suspended(&pdev->dev))
-		pm_runtime_put(&pdev->dev);
-	pm_runtime_disable(&pdev->dev);
-
-	return 0;
-}
-
-#ifdef CONFIG_PM_RUNTIME
-
-static int omap_usb3_runtime_suspend(struct device *dev)
-{
-	struct platform_device	*pdev = to_platform_device(dev);
-	struct omap_usb	*phy = platform_get_drvdata(pdev);
-
-	clk_disable(phy->wkupclk);
-	clk_disable(phy->optclk);
-
-	return 0;
-}
-
-static int omap_usb3_runtime_resume(struct device *dev)
-{
-	u32 ret = 0;
-	struct platform_device	*pdev = to_platform_device(dev);
-	struct omap_usb	*phy = platform_get_drvdata(pdev);
-
-	ret = clk_enable(phy->optclk);
-	if (ret) {
-		dev_err(phy->dev, "Failed to enable optclk %d\n", ret);
-		goto err1;
-	}
-
-	ret = clk_enable(phy->wkupclk);
-	if (ret) {
-		dev_err(phy->dev, "Failed to enable wkupclk %d\n", ret);
-		goto err2;
-	}
-
-	return 0;
-
-err2:
-	clk_disable(phy->optclk);
-
-err1:
-	return ret;
-}
-
-static const struct dev_pm_ops omap_usb3_pm_ops = {
-	SET_RUNTIME_PM_OPS(omap_usb3_runtime_suspend, omap_usb3_runtime_resume,
-		NULL)
-};
-
-#define DEV_PM_OPS     (&omap_usb3_pm_ops)
-#else
-#define DEV_PM_OPS     NULL
-#endif
-
-#ifdef CONFIG_OF
-static const struct of_device_id omap_usb3_id_table[] = {
-	{ .compatible = "ti,omap-usb3" },
-	{}
-};
-MODULE_DEVICE_TABLE(of, omap_usb3_id_table);
-#endif
-
-static struct platform_driver omap_usb3_driver = {
-	.probe		= omap_usb3_probe,
-	.remove		= omap_usb3_remove,
-	.driver		= {
-		.name	= "omap-usb3",
-		.owner	= THIS_MODULE,
-		.pm	= DEV_PM_OPS,
-		.of_match_table = of_match_ptr(omap_usb3_id_table),
-	},
-};
-
-module_platform_driver(omap_usb3_driver);
-
-MODULE_ALIAS("platform: omap_usb3");
-MODULE_AUTHOR("Texas Instruments Inc.");
-MODULE_DESCRIPTION("OMAP USB3 phy driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/phy/phy-ab8500-usb.c b/drivers/usb/phy/phy-ab8500-usb.c
new file mode 100644
index 0000000..4acef26
--- /dev/null
+++ b/drivers/usb/phy/phy-ab8500-usb.c
@@ -0,0 +1,924 @@
+/*
+ * drivers/usb/otg/ab8500_usb.c
+ *
+ * USB transceiver driver for AB8500 chip
+ *
+ * Copyright (C) 2010 ST-Ericsson AB
+ * Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.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/module.h>
+#include <linux/platform_device.h>
+#include <linux/usb/otg.h>
+#include <linux/slab.h>
+#include <linux/notifier.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/mfd/abx500.h>
+#include <linux/mfd/abx500/ab8500.h>
+#include <linux/usb/musb-ux500.h>
+#include <linux/regulator/consumer.h>
+#include <linux/pinctrl/consumer.h>
+
+/* Bank AB8500_SYS_CTRL2_BLOCK */
+#define AB8500_MAIN_WD_CTRL_REG 0x01
+
+/* Bank AB8500_USB */
+#define AB8500_USB_LINE_STAT_REG 0x80
+#define AB8505_USB_LINE_STAT_REG 0x94
+#define AB8500_USB_PHY_CTRL_REG 0x8A
+
+/* Bank AB8500_DEVELOPMENT */
+#define AB8500_BANK12_ACCESS 0x00
+
+/* Bank AB8500_DEBUG */
+#define AB8500_USB_PHY_TUNE1 0x05
+#define AB8500_USB_PHY_TUNE2 0x06
+#define AB8500_USB_PHY_TUNE3 0x07
+
+#define AB8500_BIT_OTG_STAT_ID (1 << 0)
+#define AB8500_BIT_PHY_CTRL_HOST_EN (1 << 0)
+#define AB8500_BIT_PHY_CTRL_DEVICE_EN (1 << 1)
+#define AB8500_BIT_WD_CTRL_ENABLE (1 << 0)
+#define AB8500_BIT_WD_CTRL_KICK (1 << 1)
+
+#define AB8500_WD_KICK_DELAY_US 100 /* usec */
+#define AB8500_WD_V11_DISABLE_DELAY_US 100 /* usec */
+#define AB8500_V20_31952_DISABLE_DELAY_US 100 /* usec */
+
+/* Usb line status register */
+enum ab8500_usb_link_status {
+	USB_LINK_NOT_CONFIGURED_8500 = 0,
+	USB_LINK_STD_HOST_NC_8500,
+	USB_LINK_STD_HOST_C_NS_8500,
+	USB_LINK_STD_HOST_C_S_8500,
+	USB_LINK_HOST_CHG_NM_8500,
+	USB_LINK_HOST_CHG_HS_8500,
+	USB_LINK_HOST_CHG_HS_CHIRP_8500,
+	USB_LINK_DEDICATED_CHG_8500,
+	USB_LINK_ACA_RID_A_8500,
+	USB_LINK_ACA_RID_B_8500,
+	USB_LINK_ACA_RID_C_NM_8500,
+	USB_LINK_ACA_RID_C_HS_8500,
+	USB_LINK_ACA_RID_C_HS_CHIRP_8500,
+	USB_LINK_HM_IDGND_8500,
+	USB_LINK_RESERVED_8500,
+	USB_LINK_NOT_VALID_LINK_8500,
+};
+
+enum ab8505_usb_link_status {
+	USB_LINK_NOT_CONFIGURED_8505 = 0,
+	USB_LINK_STD_HOST_NC_8505,
+	USB_LINK_STD_HOST_C_NS_8505,
+	USB_LINK_STD_HOST_C_S_8505,
+	USB_LINK_CDP_8505,
+	USB_LINK_RESERVED0_8505,
+	USB_LINK_RESERVED1_8505,
+	USB_LINK_DEDICATED_CHG_8505,
+	USB_LINK_ACA_RID_A_8505,
+	USB_LINK_ACA_RID_B_8505,
+	USB_LINK_ACA_RID_C_NM_8505,
+	USB_LINK_RESERVED2_8505,
+	USB_LINK_RESERVED3_8505,
+	USB_LINK_HM_IDGND_8505,
+	USB_LINK_CHARGERPORT_NOT_OK_8505,
+	USB_LINK_CHARGER_DM_HIGH_8505,
+	USB_LINK_PHYEN_NO_VBUS_NO_IDGND_8505,
+	USB_LINK_STD_UPSTREAM_NO_IDGNG_NO_VBUS_8505,
+	USB_LINK_STD_UPSTREAM_8505,
+	USB_LINK_CHARGER_SE1_8505,
+	USB_LINK_CARKIT_CHGR_1_8505,
+	USB_LINK_CARKIT_CHGR_2_8505,
+	USB_LINK_ACA_DOCK_CHGR_8505,
+	USB_LINK_SAMSUNG_BOOT_CBL_PHY_EN_8505,
+	USB_LINK_SAMSUNG_BOOT_CBL_PHY_DISB_8505,
+	USB_LINK_SAMSUNG_UART_CBL_PHY_EN_8505,
+	USB_LINK_SAMSUNG_UART_CBL_PHY_DISB_8505,
+	USB_LINK_MOTOROLA_FACTORY_CBL_PHY_EN_8505,
+};
+
+enum ab8500_usb_mode {
+	USB_IDLE = 0,
+	USB_PERIPHERAL,
+	USB_HOST,
+	USB_DEDICATED_CHG
+};
+
+struct ab8500_usb {
+	struct usb_phy phy;
+	struct device *dev;
+	struct ab8500 *ab8500;
+	unsigned vbus_draw;
+	struct work_struct phy_dis_work;
+	enum ab8500_usb_mode mode;
+	struct regulator *v_ape;
+	struct regulator *v_musb;
+	struct regulator *v_ulpi;
+	int saved_v_ulpi;
+	int previous_link_status_state;
+	struct pinctrl *pinctrl;
+	struct pinctrl_state *pins_sleep;
+};
+
+static inline struct ab8500_usb *phy_to_ab(struct usb_phy *x)
+{
+	return container_of(x, struct ab8500_usb, phy);
+}
+
+static void ab8500_usb_wd_workaround(struct ab8500_usb *ab)
+{
+	abx500_set_register_interruptible(ab->dev,
+		AB8500_SYS_CTRL2_BLOCK,
+		AB8500_MAIN_WD_CTRL_REG,
+		AB8500_BIT_WD_CTRL_ENABLE);
+
+	udelay(AB8500_WD_KICK_DELAY_US);
+
+	abx500_set_register_interruptible(ab->dev,
+		AB8500_SYS_CTRL2_BLOCK,
+		AB8500_MAIN_WD_CTRL_REG,
+		(AB8500_BIT_WD_CTRL_ENABLE
+		| AB8500_BIT_WD_CTRL_KICK));
+
+	udelay(AB8500_WD_V11_DISABLE_DELAY_US);
+
+	abx500_set_register_interruptible(ab->dev,
+		AB8500_SYS_CTRL2_BLOCK,
+		AB8500_MAIN_WD_CTRL_REG,
+		0);
+}
+
+static void ab8500_usb_regulator_enable(struct ab8500_usb *ab)
+{
+	int ret, volt;
+
+	ret = regulator_enable(ab->v_ape);
+	if (ret)
+		dev_err(ab->dev, "Failed to enable v-ape\n");
+
+	if (!is_ab8500_2p0_or_earlier(ab->ab8500)) {
+		ab->saved_v_ulpi = regulator_get_voltage(ab->v_ulpi);
+		if (ab->saved_v_ulpi < 0)
+			dev_err(ab->dev, "Failed to get v_ulpi voltage\n");
+
+		ret = regulator_set_voltage(ab->v_ulpi, 1300000, 1350000);
+		if (ret < 0)
+			dev_err(ab->dev, "Failed to set the Vintcore to 1.3V, ret=%d\n",
+					ret);
+
+		ret = regulator_set_optimum_mode(ab->v_ulpi, 28000);
+		if (ret < 0)
+			dev_err(ab->dev, "Failed to set optimum mode (ret=%d)\n",
+					ret);
+	}
+
+	ret = regulator_enable(ab->v_ulpi);
+	if (ret)
+		dev_err(ab->dev, "Failed to enable vddulpivio18\n");
+
+	if (!is_ab8500_2p0_or_earlier(ab->ab8500)) {
+		volt = regulator_get_voltage(ab->v_ulpi);
+		if ((volt != 1300000) && (volt != 1350000))
+			dev_err(ab->dev, "Vintcore is not set to 1.3V volt=%d\n",
+					volt);
+	}
+
+	ret = regulator_enable(ab->v_musb);
+	if (ret)
+		dev_err(ab->dev, "Failed to enable musb_1v8\n");
+}
+
+static void ab8500_usb_regulator_disable(struct ab8500_usb *ab)
+{
+	int ret;
+
+	regulator_disable(ab->v_musb);
+
+	regulator_disable(ab->v_ulpi);
+
+	/* USB is not the only consumer of Vintcore, restore old settings */
+	if (!is_ab8500_2p0_or_earlier(ab->ab8500)) {
+		if (ab->saved_v_ulpi > 0) {
+			ret = regulator_set_voltage(ab->v_ulpi,
+					ab->saved_v_ulpi, ab->saved_v_ulpi);
+			if (ret < 0)
+				dev_err(ab->dev, "Failed to set the Vintcore to %duV, ret=%d\n",
+						ab->saved_v_ulpi, ret);
+		}
+
+		ret = regulator_set_optimum_mode(ab->v_ulpi, 0);
+		if (ret < 0)
+			dev_err(ab->dev, "Failed to set optimum mode (ret=%d)\n",
+					ret);
+	}
+
+	regulator_disable(ab->v_ape);
+}
+
+static void ab8500_usb_wd_linkstatus(struct ab8500_usb *ab, u8 bit)
+{
+	/* Workaround for v2.0 bug # 31952 */
+	if (is_ab8500_2p0(ab->ab8500)) {
+		abx500_mask_and_set_register_interruptible(ab->dev,
+				AB8500_USB, AB8500_USB_PHY_CTRL_REG,
+				bit, bit);
+		udelay(AB8500_V20_31952_DISABLE_DELAY_US);
+	}
+}
+
+static void ab8500_usb_phy_enable(struct ab8500_usb *ab, bool sel_host)
+{
+	u8 bit;
+	bit = sel_host ? AB8500_BIT_PHY_CTRL_HOST_EN :
+		AB8500_BIT_PHY_CTRL_DEVICE_EN;
+
+	/* mux and configure USB pins to DEFAULT state */
+	ab->pinctrl = pinctrl_get_select(ab->dev, PINCTRL_STATE_DEFAULT);
+	if (IS_ERR(ab->pinctrl))
+		dev_err(ab->dev, "could not get/set default pinstate\n");
+
+	ab8500_usb_regulator_enable(ab);
+
+	abx500_mask_and_set_register_interruptible(ab->dev,
+			AB8500_USB, AB8500_USB_PHY_CTRL_REG,
+			bit, bit);
+}
+
+static void ab8500_usb_phy_disable(struct ab8500_usb *ab, bool sel_host)
+{
+	u8 bit;
+	bit = sel_host ? AB8500_BIT_PHY_CTRL_HOST_EN :
+		AB8500_BIT_PHY_CTRL_DEVICE_EN;
+
+	ab8500_usb_wd_linkstatus(ab, bit);
+
+	abx500_mask_and_set_register_interruptible(ab->dev,
+			AB8500_USB, AB8500_USB_PHY_CTRL_REG,
+			bit, 0);
+
+	/* Needed to disable the phy.*/
+	ab8500_usb_wd_workaround(ab);
+
+	ab8500_usb_regulator_disable(ab);
+
+	if (!IS_ERR(ab->pinctrl)) {
+		/* configure USB pins to SLEEP state */
+		ab->pins_sleep = pinctrl_lookup_state(ab->pinctrl,
+				PINCTRL_STATE_SLEEP);
+
+		if (IS_ERR(ab->pins_sleep))
+			dev_dbg(ab->dev, "could not get sleep pinstate\n");
+		else if (pinctrl_select_state(ab->pinctrl, ab->pins_sleep))
+			dev_err(ab->dev, "could not set pins to sleep state\n");
+
+		/* as USB pins are shared with idddet, release them to allow
+		 * iddet to request them
+		 */
+		pinctrl_put(ab->pinctrl);
+	}
+}
+
+#define ab8500_usb_host_phy_en(ab)	ab8500_usb_phy_enable(ab, true)
+#define ab8500_usb_host_phy_dis(ab)	ab8500_usb_phy_disable(ab, true)
+#define ab8500_usb_peri_phy_en(ab)	ab8500_usb_phy_enable(ab, false)
+#define ab8500_usb_peri_phy_dis(ab)	ab8500_usb_phy_disable(ab, false)
+
+static int ab8505_usb_link_status_update(struct ab8500_usb *ab,
+		enum ab8505_usb_link_status lsts)
+{
+	enum ux500_musb_vbus_id_status event = 0;
+
+	dev_dbg(ab->dev, "ab8505_usb_link_status_update %d\n", lsts);
+
+	/*
+	 * Spurious link_status interrupts are seen at the time of
+	 * disconnection of a device in RIDA state
+	 */
+	if (ab->previous_link_status_state == USB_LINK_ACA_RID_A_8505 &&
+			(lsts == USB_LINK_STD_HOST_NC_8505))
+		return 0;
+
+	ab->previous_link_status_state = lsts;
+
+	switch (lsts) {
+	case USB_LINK_ACA_RID_B_8505:
+		event = UX500_MUSB_RIDB;
+	case USB_LINK_NOT_CONFIGURED_8505:
+	case USB_LINK_RESERVED0_8505:
+	case USB_LINK_RESERVED1_8505:
+	case USB_LINK_RESERVED2_8505:
+	case USB_LINK_RESERVED3_8505:
+		ab->mode = USB_IDLE;
+		ab->phy.otg->default_a = false;
+		ab->vbus_draw = 0;
+		if (event != UX500_MUSB_RIDB)
+			event = UX500_MUSB_NONE;
+		/*
+		 * Fallback to default B_IDLE as nothing
+		 * is connected
+		 */
+		ab->phy.state = OTG_STATE_B_IDLE;
+		break;
+
+	case USB_LINK_ACA_RID_C_NM_8505:
+		event = UX500_MUSB_RIDC;
+	case USB_LINK_STD_HOST_NC_8505:
+	case USB_LINK_STD_HOST_C_NS_8505:
+	case USB_LINK_STD_HOST_C_S_8505:
+	case USB_LINK_CDP_8505:
+		if (ab->mode == USB_IDLE) {
+			ab->mode = USB_PERIPHERAL;
+			ab8500_usb_peri_phy_en(ab);
+			atomic_notifier_call_chain(&ab->phy.notifier,
+					UX500_MUSB_PREPARE, &ab->vbus_draw);
+		}
+		if (event != UX500_MUSB_RIDC)
+			event = UX500_MUSB_VBUS;
+		break;
+
+	case USB_LINK_ACA_RID_A_8505:
+	case USB_LINK_ACA_DOCK_CHGR_8505:
+		event = UX500_MUSB_RIDA;
+	case USB_LINK_HM_IDGND_8505:
+		if (ab->mode == USB_IDLE) {
+			ab->mode = USB_HOST;
+			ab8500_usb_host_phy_en(ab);
+			atomic_notifier_call_chain(&ab->phy.notifier,
+					UX500_MUSB_PREPARE, &ab->vbus_draw);
+		}
+		ab->phy.otg->default_a = true;
+		if (event != UX500_MUSB_RIDA)
+			event = UX500_MUSB_ID;
+		atomic_notifier_call_chain(&ab->phy.notifier,
+				event, &ab->vbus_draw);
+		break;
+
+	case USB_LINK_DEDICATED_CHG_8505:
+		ab->mode = USB_DEDICATED_CHG;
+		event = UX500_MUSB_CHARGER;
+		atomic_notifier_call_chain(&ab->phy.notifier,
+				event, &ab->vbus_draw);
+		break;
+
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int ab8500_usb_link_status_update(struct ab8500_usb *ab,
+		enum ab8500_usb_link_status lsts)
+{
+	enum ux500_musb_vbus_id_status event = 0;
+
+	dev_dbg(ab->dev, "ab8500_usb_link_status_update %d\n", lsts);
+
+	/*
+	 * Spurious link_status interrupts are seen in case of a
+	 * disconnection of a device in IDGND and RIDA stage
+	 */
+	if (ab->previous_link_status_state == USB_LINK_HM_IDGND_8500 &&
+			(lsts == USB_LINK_STD_HOST_C_NS_8500 ||
+			 lsts == USB_LINK_STD_HOST_NC_8500))
+		return 0;
+
+	if (ab->previous_link_status_state == USB_LINK_ACA_RID_A_8500 &&
+			lsts == USB_LINK_STD_HOST_NC_8500)
+		return 0;
+
+	ab->previous_link_status_state = lsts;
+
+	switch (lsts) {
+	case USB_LINK_ACA_RID_B_8500:
+		event = UX500_MUSB_RIDB;
+	case USB_LINK_NOT_CONFIGURED_8500:
+	case USB_LINK_NOT_VALID_LINK_8500:
+		ab->mode = USB_IDLE;
+		ab->phy.otg->default_a = false;
+		ab->vbus_draw = 0;
+		if (event != UX500_MUSB_RIDB)
+			event = UX500_MUSB_NONE;
+		/* Fallback to default B_IDLE as nothing is connected */
+		ab->phy.state = OTG_STATE_B_IDLE;
+		break;
+
+	case USB_LINK_ACA_RID_C_NM_8500:
+	case USB_LINK_ACA_RID_C_HS_8500:
+	case USB_LINK_ACA_RID_C_HS_CHIRP_8500:
+		event = UX500_MUSB_RIDC;
+	case USB_LINK_STD_HOST_NC_8500:
+	case USB_LINK_STD_HOST_C_NS_8500:
+	case USB_LINK_STD_HOST_C_S_8500:
+	case USB_LINK_HOST_CHG_NM_8500:
+	case USB_LINK_HOST_CHG_HS_8500:
+	case USB_LINK_HOST_CHG_HS_CHIRP_8500:
+		if (ab->mode == USB_IDLE) {
+			ab->mode = USB_PERIPHERAL;
+			ab8500_usb_peri_phy_en(ab);
+			atomic_notifier_call_chain(&ab->phy.notifier,
+					UX500_MUSB_PREPARE, &ab->vbus_draw);
+		}
+		if (event != UX500_MUSB_RIDC)
+			event = UX500_MUSB_VBUS;
+		break;
+
+	case USB_LINK_ACA_RID_A_8500:
+		event = UX500_MUSB_RIDA;
+	case USB_LINK_HM_IDGND_8500:
+		if (ab->mode == USB_IDLE) {
+			ab->mode = USB_HOST;
+			ab8500_usb_host_phy_en(ab);
+			atomic_notifier_call_chain(&ab->phy.notifier,
+					UX500_MUSB_PREPARE, &ab->vbus_draw);
+		}
+		ab->phy.otg->default_a = true;
+		if (event != UX500_MUSB_RIDA)
+			event = UX500_MUSB_ID;
+		atomic_notifier_call_chain(&ab->phy.notifier,
+				event, &ab->vbus_draw);
+		break;
+
+	case USB_LINK_DEDICATED_CHG_8500:
+		ab->mode = USB_DEDICATED_CHG;
+		event = UX500_MUSB_CHARGER;
+		atomic_notifier_call_chain(&ab->phy.notifier,
+				event, &ab->vbus_draw);
+		break;
+
+	case USB_LINK_RESERVED_8500:
+		break;
+	}
+
+	return 0;
+}
+
+/*
+ * Connection Sequence:
+ *   1. Link Status Interrupt
+ *   2. Enable AB clock
+ *   3. Enable AB regulators
+ *   4. Enable USB phy
+ *   5. Reset the musb controller
+ *   6. Switch the ULPI GPIO pins to fucntion mode
+ *   7. Enable the musb Peripheral5 clock
+ *   8. Restore MUSB context
+ */
+static int abx500_usb_link_status_update(struct ab8500_usb *ab)
+{
+	u8 reg;
+	int ret = 0;
+
+	if (is_ab8500(ab->ab8500)) {
+		enum ab8500_usb_link_status lsts;
+
+		abx500_get_register_interruptible(ab->dev,
+				AB8500_USB, AB8500_USB_LINE_STAT_REG, &reg);
+		lsts = (reg >> 3) & 0x0F;
+		ret = ab8500_usb_link_status_update(ab, lsts);
+	} else if (is_ab8505(ab->ab8500)) {
+		enum ab8505_usb_link_status lsts;
+
+		abx500_get_register_interruptible(ab->dev,
+				AB8500_USB, AB8505_USB_LINE_STAT_REG, &reg);
+		lsts = (reg >> 3) & 0x1F;
+		ret = ab8505_usb_link_status_update(ab, lsts);
+	}
+
+	return ret;
+}
+
+/*
+ * Disconnection Sequence:
+ *   1. Disconect Interrupt
+ *   2. Disable regulators
+ *   3. Disable AB clock
+ *   4. Disable the Phy
+ *   5. Link Status Interrupt
+ *   6. Disable Musb Clock
+ */
+static irqreturn_t ab8500_usb_disconnect_irq(int irq, void *data)
+{
+	struct ab8500_usb *ab = (struct ab8500_usb *) data;
+	enum usb_phy_events event = UX500_MUSB_NONE;
+
+	/* Link status will not be updated till phy is disabled. */
+	if (ab->mode == USB_HOST) {
+		ab->phy.otg->default_a = false;
+		ab->vbus_draw = 0;
+		atomic_notifier_call_chain(&ab->phy.notifier,
+				event, &ab->vbus_draw);
+		ab8500_usb_host_phy_dis(ab);
+		ab->mode = USB_IDLE;
+	}
+
+	if (ab->mode == USB_PERIPHERAL) {
+		atomic_notifier_call_chain(&ab->phy.notifier,
+				event, &ab->vbus_draw);
+		ab8500_usb_peri_phy_dis(ab);
+		atomic_notifier_call_chain(&ab->phy.notifier,
+				UX500_MUSB_CLEAN, &ab->vbus_draw);
+		ab->mode = USB_IDLE;
+		ab->phy.otg->default_a = false;
+		ab->vbus_draw = 0;
+	}
+
+	if (is_ab8500_2p0(ab->ab8500)) {
+		if (ab->mode == USB_DEDICATED_CHG) {
+			ab8500_usb_wd_linkstatus(ab,
+					AB8500_BIT_PHY_CTRL_DEVICE_EN);
+			abx500_mask_and_set_register_interruptible(ab->dev,
+					AB8500_USB, AB8500_USB_PHY_CTRL_REG,
+					AB8500_BIT_PHY_CTRL_DEVICE_EN, 0);
+		}
+	}
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t ab8500_usb_link_status_irq(int irq, void *data)
+{
+	struct ab8500_usb *ab = (struct ab8500_usb *) data;
+
+	abx500_usb_link_status_update(ab);
+
+	return IRQ_HANDLED;
+}
+
+static void ab8500_usb_phy_disable_work(struct work_struct *work)
+{
+	struct ab8500_usb *ab = container_of(work, struct ab8500_usb,
+						phy_dis_work);
+
+	if (!ab->phy.otg->host)
+		ab8500_usb_host_phy_dis(ab);
+
+	if (!ab->phy.otg->gadget)
+		ab8500_usb_peri_phy_dis(ab);
+}
+
+static unsigned ab8500_eyediagram_workaroud(struct ab8500_usb *ab, unsigned mA)
+{
+	/*
+	 * AB8500 V2 has eye diagram issues when drawing more than 100mA from
+	 * VBUS.  Set charging current to 100mA in case of standard host
+	 */
+	if (is_ab8500_2p0_or_earlier(ab->ab8500))
+		if (mA > 100)
+			mA = 100;
+
+	return mA;
+}
+
+static int ab8500_usb_set_power(struct usb_phy *phy, unsigned mA)
+{
+	struct ab8500_usb *ab;
+
+	if (!phy)
+		return -ENODEV;
+
+	ab = phy_to_ab(phy);
+
+	mA = ab8500_eyediagram_workaroud(ab, mA);
+
+	ab->vbus_draw = mA;
+
+	atomic_notifier_call_chain(&ab->phy.notifier,
+			UX500_MUSB_VBUS, &ab->vbus_draw);
+
+	return 0;
+}
+
+static int ab8500_usb_set_suspend(struct usb_phy *x, int suspend)
+{
+	/* TODO */
+	return 0;
+}
+
+static int ab8500_usb_set_peripheral(struct usb_otg *otg,
+					struct usb_gadget *gadget)
+{
+	struct ab8500_usb *ab;
+
+	if (!otg)
+		return -ENODEV;
+
+	ab = phy_to_ab(otg->phy);
+
+	ab->phy.otg->gadget = gadget;
+
+	/* Some drivers call this function in atomic context.
+	 * Do not update ab8500 registers directly till this
+	 * is fixed.
+	 */
+
+	if ((ab->mode != USB_IDLE) && (!gadget)) {
+		ab->mode = USB_IDLE;
+		schedule_work(&ab->phy_dis_work);
+	}
+
+	return 0;
+}
+
+static int ab8500_usb_set_host(struct usb_otg *otg, struct usb_bus *host)
+{
+	struct ab8500_usb *ab;
+
+	if (!otg)
+		return -ENODEV;
+
+	ab = phy_to_ab(otg->phy);
+
+	ab->phy.otg->host = host;
+
+	/* Some drivers call this function in atomic context.
+	 * Do not update ab8500 registers directly till this
+	 * is fixed.
+	 */
+
+	if ((ab->mode != USB_IDLE) && (!host)) {
+		ab->mode = USB_IDLE;
+		schedule_work(&ab->phy_dis_work);
+	}
+
+	return 0;
+}
+
+static int ab8500_usb_regulator_get(struct ab8500_usb *ab)
+{
+	int err;
+
+	ab->v_ape = devm_regulator_get(ab->dev, "v-ape");
+	if (IS_ERR(ab->v_ape)) {
+		dev_err(ab->dev, "Could not get v-ape supply\n");
+		err = PTR_ERR(ab->v_ape);
+		return err;
+	}
+
+	ab->v_ulpi = devm_regulator_get(ab->dev, "vddulpivio18");
+	if (IS_ERR(ab->v_ulpi)) {
+		dev_err(ab->dev, "Could not get vddulpivio18 supply\n");
+		err = PTR_ERR(ab->v_ulpi);
+		return err;
+	}
+
+	ab->v_musb = devm_regulator_get(ab->dev, "musb_1v8");
+	if (IS_ERR(ab->v_musb)) {
+		dev_err(ab->dev, "Could not get musb_1v8 supply\n");
+		err = PTR_ERR(ab->v_musb);
+		return err;
+	}
+
+	return 0;
+}
+
+static int ab8500_usb_irq_setup(struct platform_device *pdev,
+		struct ab8500_usb *ab)
+{
+	int err;
+	int irq;
+
+	irq = platform_get_irq_byname(pdev, "USB_LINK_STATUS");
+	if (irq < 0) {
+		dev_err(&pdev->dev, "Link status irq not found\n");
+		return irq;
+	}
+	err = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+			ab8500_usb_link_status_irq,
+			IRQF_NO_SUSPEND | IRQF_SHARED, "usb-link-status", ab);
+	if (err < 0) {
+		dev_err(ab->dev, "request_irq failed for link status irq\n");
+		return err;
+	}
+
+	irq = platform_get_irq_byname(pdev, "ID_WAKEUP_F");
+	if (irq < 0) {
+		dev_err(&pdev->dev, "ID fall irq not found\n");
+		return irq;
+	}
+	err = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+			ab8500_usb_disconnect_irq,
+			IRQF_NO_SUSPEND | IRQF_SHARED, "usb-id-fall", ab);
+	if (err < 0) {
+		dev_err(ab->dev, "request_irq failed for ID fall irq\n");
+		return err;
+	}
+
+	irq = platform_get_irq_byname(pdev, "VBUS_DET_F");
+	if (irq < 0) {
+		dev_err(&pdev->dev, "VBUS fall irq not found\n");
+		return irq;
+	}
+	err = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+			ab8500_usb_disconnect_irq,
+			IRQF_NO_SUSPEND | IRQF_SHARED, "usb-vbus-fall", ab);
+	if (err < 0) {
+		dev_err(ab->dev, "request_irq failed for Vbus fall irq\n");
+		return err;
+	}
+
+	return 0;
+}
+
+static int ab8500_usb_probe(struct platform_device *pdev)
+{
+	struct ab8500_usb	*ab;
+	struct ab8500		*ab8500;
+	struct usb_otg		*otg;
+	int err;
+	int rev;
+
+	ab8500 = dev_get_drvdata(pdev->dev.parent);
+	rev = abx500_get_chip_id(&pdev->dev);
+
+	if (is_ab8500_1p1_or_earlier(ab8500)) {
+		dev_err(&pdev->dev, "Unsupported AB8500 chip rev=%d\n", rev);
+		return -ENODEV;
+	}
+
+	ab = devm_kzalloc(&pdev->dev, sizeof(*ab), GFP_KERNEL);
+	if (!ab)
+		return -ENOMEM;
+
+	otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL);
+	if (!otg)
+		return -ENOMEM;
+
+	ab->dev			= &pdev->dev;
+	ab->ab8500		= ab8500;
+	ab->phy.dev		= ab->dev;
+	ab->phy.otg		= otg;
+	ab->phy.label		= "ab8500";
+	ab->phy.set_suspend	= ab8500_usb_set_suspend;
+	ab->phy.set_power	= ab8500_usb_set_power;
+	ab->phy.state		= OTG_STATE_UNDEFINED;
+
+	otg->phy		= &ab->phy;
+	otg->set_host		= ab8500_usb_set_host;
+	otg->set_peripheral	= ab8500_usb_set_peripheral;
+
+	platform_set_drvdata(pdev, ab);
+
+	ATOMIC_INIT_NOTIFIER_HEAD(&ab->phy.notifier);
+
+	/* all: Disable phy when called from set_host and set_peripheral */
+	INIT_WORK(&ab->phy_dis_work, ab8500_usb_phy_disable_work);
+
+	err = ab8500_usb_regulator_get(ab);
+	if (err)
+		return err;
+
+	err = ab8500_usb_irq_setup(pdev, ab);
+	if (err < 0)
+		return err;
+
+	err = usb_add_phy(&ab->phy, USB_PHY_TYPE_USB2);
+	if (err) {
+		dev_err(&pdev->dev, "Can't register transceiver\n");
+		return err;
+	}
+
+	/* Phy tuning values for AB8500 */
+	if (!is_ab8500_2p0_or_earlier(ab->ab8500)) {
+		/* Enable the PBT/Bank 0x12 access */
+		err = abx500_set_register_interruptible(ab->dev,
+				AB8500_DEVELOPMENT, AB8500_BANK12_ACCESS, 0x01);
+		if (err < 0)
+			dev_err(ab->dev, "Failed to enable bank12 access err=%d\n",
+					err);
+
+		err = abx500_set_register_interruptible(ab->dev,
+				AB8500_DEBUG, AB8500_USB_PHY_TUNE1, 0xC8);
+		if (err < 0)
+			dev_err(ab->dev, "Failed to set PHY_TUNE1 register err=%d\n",
+					err);
+
+		err = abx500_set_register_interruptible(ab->dev,
+				AB8500_DEBUG, AB8500_USB_PHY_TUNE2, 0x00);
+		if (err < 0)
+			dev_err(ab->dev, "Failed to set PHY_TUNE2 register err=%d\n",
+					err);
+
+		err = abx500_set_register_interruptible(ab->dev,
+				AB8500_DEBUG, AB8500_USB_PHY_TUNE3, 0x78);
+		if (err < 0)
+			dev_err(ab->dev, "Failed to set PHY_TUNE3 regester err=%d\n",
+					err);
+
+		/* Switch to normal mode/disable Bank 0x12 access */
+		err = abx500_set_register_interruptible(ab->dev,
+				AB8500_DEVELOPMENT, AB8500_BANK12_ACCESS, 0x00);
+		if (err < 0)
+			dev_err(ab->dev, "Failed to switch bank12 access err=%d\n",
+					err);
+	}
+
+	/* Phy tuning values for AB8505 */
+	if (is_ab8505(ab->ab8500)) {
+		/* Enable the PBT/Bank 0x12 access */
+		err = abx500_mask_and_set_register_interruptible(ab->dev,
+				AB8500_DEVELOPMENT, AB8500_BANK12_ACCESS,
+				0x01, 0x01);
+		if (err < 0)
+			dev_err(ab->dev, "Failed to enable bank12 access err=%d\n",
+					err);
+
+		err = abx500_mask_and_set_register_interruptible(ab->dev,
+				AB8500_DEBUG, AB8500_USB_PHY_TUNE1,
+				0xC8, 0xC8);
+		if (err < 0)
+			dev_err(ab->dev, "Failed to set PHY_TUNE1 register err=%d\n",
+					err);
+
+		err = abx500_mask_and_set_register_interruptible(ab->dev,
+				AB8500_DEBUG, AB8500_USB_PHY_TUNE2,
+				0x60, 0x60);
+		if (err < 0)
+			dev_err(ab->dev, "Failed to set PHY_TUNE2 register err=%d\n",
+					err);
+
+		err = abx500_mask_and_set_register_interruptible(ab->dev,
+				AB8500_DEBUG, AB8500_USB_PHY_TUNE3,
+				0xFC, 0x80);
+
+		if (err < 0)
+			dev_err(ab->dev, "Failed to set PHY_TUNE3 regester err=%d\n",
+					err);
+
+		/* Switch to normal mode/disable Bank 0x12 access */
+		err = abx500_mask_and_set_register_interruptible(ab->dev,
+				AB8500_DEVELOPMENT, AB8500_BANK12_ACCESS,
+				0x00, 0x00);
+		if (err < 0)
+			dev_err(ab->dev, "Failed to switch bank12 access err=%d\n",
+					err);
+	}
+
+	/* Needed to enable ID detection. */
+	ab8500_usb_wd_workaround(ab);
+
+	abx500_usb_link_status_update(ab);
+
+	dev_info(&pdev->dev, "revision 0x%2x driver initialized\n", rev);
+
+	return 0;
+}
+
+static int ab8500_usb_remove(struct platform_device *pdev)
+{
+	struct ab8500_usb *ab = platform_get_drvdata(pdev);
+
+	cancel_work_sync(&ab->phy_dis_work);
+
+	usb_remove_phy(&ab->phy);
+
+	if (ab->mode == USB_HOST)
+		ab8500_usb_host_phy_dis(ab);
+	else if (ab->mode == USB_PERIPHERAL)
+		ab8500_usb_peri_phy_dis(ab);
+
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+static struct platform_driver ab8500_usb_driver = {
+	.probe		= ab8500_usb_probe,
+	.remove		= ab8500_usb_remove,
+	.driver		= {
+		.name	= "ab8500-usb",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init ab8500_usb_init(void)
+{
+	return platform_driver_register(&ab8500_usb_driver);
+}
+subsys_initcall(ab8500_usb_init);
+
+static void __exit ab8500_usb_exit(void)
+{
+	platform_driver_unregister(&ab8500_usb_driver);
+}
+module_exit(ab8500_usb_exit);
+
+MODULE_ALIAS("platform:ab8500_usb");
+MODULE_AUTHOR("ST-Ericsson AB");
+MODULE_DESCRIPTION("AB8500 usb transceiver driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/phy/phy-fsl-usb.c b/drivers/usb/phy/phy-fsl-usb.c
new file mode 100644
index 0000000..97b9308
--- /dev/null
+++ b/drivers/usb/phy/phy-fsl-usb.c
@@ -0,0 +1,1173 @@
+/*
+ * Copyright (C) 2007,2008 Freescale semiconductor, Inc.
+ *
+ * Author: Li Yang <LeoLi@freescale.com>
+ *         Jerry Huang <Chang-Ming.Huang@freescale.com>
+ *
+ * Initialization based on code from Shlomi Gridish.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You 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/delay.h>
+#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/timer.h>
+#include <linux/usb.h>
+#include <linux/device.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <linux/workqueue.h>
+#include <linux/time.h>
+#include <linux/fsl_devices.h>
+#include <linux/platform_device.h>
+#include <linux/uaccess.h>
+
+#include <asm/unaligned.h>
+
+#include "phy-fsl-usb.h"
+
+#define DRIVER_VERSION "Rev. 1.55"
+#define DRIVER_AUTHOR "Jerry Huang/Li Yang"
+#define DRIVER_DESC "Freescale USB OTG Transceiver Driver"
+#define DRIVER_INFO DRIVER_DESC " " DRIVER_VERSION
+
+static const char driver_name[] = "fsl-usb2-otg";
+
+const pm_message_t otg_suspend_state = {
+	.event = 1,
+};
+
+#define HA_DATA_PULSE
+
+static struct usb_dr_mmap *usb_dr_regs;
+static struct fsl_otg *fsl_otg_dev;
+static int srp_wait_done;
+
+/* FSM timers */
+struct fsl_otg_timer *a_wait_vrise_tmr, *a_wait_bcon_tmr, *a_aidl_bdis_tmr,
+	*b_ase0_brst_tmr, *b_se0_srp_tmr;
+
+/* Driver specific timers */
+struct fsl_otg_timer *b_data_pulse_tmr, *b_vbus_pulse_tmr, *b_srp_fail_tmr,
+	*b_srp_wait_tmr, *a_wait_enum_tmr;
+
+static struct list_head active_timers;
+
+static struct fsl_otg_config fsl_otg_initdata = {
+	.otg_port = 1,
+};
+
+#ifdef CONFIG_PPC32
+static u32 _fsl_readl_be(const unsigned __iomem *p)
+{
+	return in_be32(p);
+}
+
+static u32 _fsl_readl_le(const unsigned __iomem *p)
+{
+	return in_le32(p);
+}
+
+static void _fsl_writel_be(u32 v, unsigned __iomem *p)
+{
+	out_be32(p, v);
+}
+
+static void _fsl_writel_le(u32 v, unsigned __iomem *p)
+{
+	out_le32(p, v);
+}
+
+static u32 (*_fsl_readl)(const unsigned __iomem *p);
+static void (*_fsl_writel)(u32 v, unsigned __iomem *p);
+
+#define fsl_readl(p)		(*_fsl_readl)((p))
+#define fsl_writel(v, p)	(*_fsl_writel)((v), (p))
+
+#else
+#define fsl_readl(addr)		readl(addr)
+#define fsl_writel(val, addr)	writel(val, addr)
+#endif /* CONFIG_PPC32 */
+
+/* Routines to access transceiver ULPI registers */
+u8 view_ulpi(u8 addr)
+{
+	u32 temp;
+
+	temp = 0x40000000 | (addr << 16);
+	fsl_writel(temp, &usb_dr_regs->ulpiview);
+	udelay(1000);
+	while (temp & 0x40)
+		temp = fsl_readl(&usb_dr_regs->ulpiview);
+	return (le32_to_cpu(temp) & 0x0000ff00) >> 8;
+}
+
+int write_ulpi(u8 addr, u8 data)
+{
+	u32 temp;
+
+	temp = 0x60000000 | (addr << 16) | data;
+	fsl_writel(temp, &usb_dr_regs->ulpiview);
+	return 0;
+}
+
+/* -------------------------------------------------------------*/
+/* Operations that will be called from OTG Finite State Machine */
+
+/* Charge vbus for vbus pulsing in SRP */
+void fsl_otg_chrg_vbus(int on)
+{
+	u32 tmp;
+
+	tmp = fsl_readl(&usb_dr_regs->otgsc) & ~OTGSC_INTSTS_MASK;
+
+	if (on)
+		/* stop discharging, start charging */
+		tmp = (tmp & ~OTGSC_CTRL_VBUS_DISCHARGE) |
+			OTGSC_CTRL_VBUS_CHARGE;
+	else
+		/* stop charging */
+		tmp &= ~OTGSC_CTRL_VBUS_CHARGE;
+
+	fsl_writel(tmp, &usb_dr_regs->otgsc);
+}
+
+/* Discharge vbus through a resistor to ground */
+void fsl_otg_dischrg_vbus(int on)
+{
+	u32 tmp;
+
+	tmp = fsl_readl(&usb_dr_regs->otgsc) & ~OTGSC_INTSTS_MASK;
+
+	if (on)
+		/* stop charging, start discharging */
+		tmp = (tmp & ~OTGSC_CTRL_VBUS_CHARGE) |
+			OTGSC_CTRL_VBUS_DISCHARGE;
+	else
+		/* stop discharging */
+		tmp &= ~OTGSC_CTRL_VBUS_DISCHARGE;
+
+	fsl_writel(tmp, &usb_dr_regs->otgsc);
+}
+
+/* A-device driver vbus, controlled through PP bit in PORTSC */
+void fsl_otg_drv_vbus(int on)
+{
+	u32 tmp;
+
+	if (on) {
+		tmp = fsl_readl(&usb_dr_regs->portsc) & ~PORTSC_W1C_BITS;
+		fsl_writel(tmp | PORTSC_PORT_POWER, &usb_dr_regs->portsc);
+	} else {
+		tmp = fsl_readl(&usb_dr_regs->portsc) &
+		      ~PORTSC_W1C_BITS & ~PORTSC_PORT_POWER;
+		fsl_writel(tmp, &usb_dr_regs->portsc);
+	}
+}
+
+/*
+ * Pull-up D+, signalling connect by periperal. Also used in
+ * data-line pulsing in SRP
+ */
+void fsl_otg_loc_conn(int on)
+{
+	u32 tmp;
+
+	tmp = fsl_readl(&usb_dr_regs->otgsc) & ~OTGSC_INTSTS_MASK;
+
+	if (on)
+		tmp |= OTGSC_CTRL_DATA_PULSING;
+	else
+		tmp &= ~OTGSC_CTRL_DATA_PULSING;
+
+	fsl_writel(tmp, &usb_dr_regs->otgsc);
+}
+
+/*
+ * Generate SOF by host.  This is controlled through suspend/resume the
+ * port.  In host mode, controller will automatically send SOF.
+ * Suspend will block the data on the port.
+ */
+void fsl_otg_loc_sof(int on)
+{
+	u32 tmp;
+
+	tmp = fsl_readl(&fsl_otg_dev->dr_mem_map->portsc) & ~PORTSC_W1C_BITS;
+	if (on)
+		tmp |= PORTSC_PORT_FORCE_RESUME;
+	else
+		tmp |= PORTSC_PORT_SUSPEND;
+
+	fsl_writel(tmp, &fsl_otg_dev->dr_mem_map->portsc);
+
+}
+
+/* Start SRP pulsing by data-line pulsing, followed with v-bus pulsing. */
+void fsl_otg_start_pulse(void)
+{
+	u32 tmp;
+
+	srp_wait_done = 0;
+#ifdef HA_DATA_PULSE
+	tmp = fsl_readl(&usb_dr_regs->otgsc) & ~OTGSC_INTSTS_MASK;
+	tmp |= OTGSC_HA_DATA_PULSE;
+	fsl_writel(tmp, &usb_dr_regs->otgsc);
+#else
+	fsl_otg_loc_conn(1);
+#endif
+
+	fsl_otg_add_timer(b_data_pulse_tmr);
+}
+
+void b_data_pulse_end(unsigned long foo)
+{
+#ifdef HA_DATA_PULSE
+#else
+	fsl_otg_loc_conn(0);
+#endif
+
+	/* Do VBUS pulse after data pulse */
+	fsl_otg_pulse_vbus();
+}
+
+void fsl_otg_pulse_vbus(void)
+{
+	srp_wait_done = 0;
+	fsl_otg_chrg_vbus(1);
+	/* start the timer to end vbus charge */
+	fsl_otg_add_timer(b_vbus_pulse_tmr);
+}
+
+void b_vbus_pulse_end(unsigned long foo)
+{
+	fsl_otg_chrg_vbus(0);
+
+	/*
+	 * As USB3300 using the same a_sess_vld and b_sess_vld voltage
+	 * we need to discharge the bus for a while to distinguish
+	 * residual voltage of vbus pulsing and A device pull up
+	 */
+	fsl_otg_dischrg_vbus(1);
+	fsl_otg_add_timer(b_srp_wait_tmr);
+}
+
+void b_srp_end(unsigned long foo)
+{
+	fsl_otg_dischrg_vbus(0);
+	srp_wait_done = 1;
+
+	if ((fsl_otg_dev->phy.state == OTG_STATE_B_SRP_INIT) &&
+	    fsl_otg_dev->fsm.b_sess_vld)
+		fsl_otg_dev->fsm.b_srp_done = 1;
+}
+
+/*
+ * Workaround for a_host suspending too fast.  When a_bus_req=0,
+ * a_host will start by SRP.  It needs to set b_hnp_enable before
+ * actually suspending to start HNP
+ */
+void a_wait_enum(unsigned long foo)
+{
+	VDBG("a_wait_enum timeout\n");
+	if (!fsl_otg_dev->phy.otg->host->b_hnp_enable)
+		fsl_otg_add_timer(a_wait_enum_tmr);
+	else
+		otg_statemachine(&fsl_otg_dev->fsm);
+}
+
+/* The timeout callback function to set time out bit */
+void set_tmout(unsigned long indicator)
+{
+	*(int *)indicator = 1;
+}
+
+/* Initialize timers */
+int fsl_otg_init_timers(struct otg_fsm *fsm)
+{
+	/* FSM used timers */
+	a_wait_vrise_tmr = otg_timer_initializer(&set_tmout, TA_WAIT_VRISE,
+				(unsigned long)&fsm->a_wait_vrise_tmout);
+	if (!a_wait_vrise_tmr)
+		return -ENOMEM;
+
+	a_wait_bcon_tmr = otg_timer_initializer(&set_tmout, TA_WAIT_BCON,
+				(unsigned long)&fsm->a_wait_bcon_tmout);
+	if (!a_wait_bcon_tmr)
+		return -ENOMEM;
+
+	a_aidl_bdis_tmr = otg_timer_initializer(&set_tmout, TA_AIDL_BDIS,
+				(unsigned long)&fsm->a_aidl_bdis_tmout);
+	if (!a_aidl_bdis_tmr)
+		return -ENOMEM;
+
+	b_ase0_brst_tmr = otg_timer_initializer(&set_tmout, TB_ASE0_BRST,
+				(unsigned long)&fsm->b_ase0_brst_tmout);
+	if (!b_ase0_brst_tmr)
+		return -ENOMEM;
+
+	b_se0_srp_tmr = otg_timer_initializer(&set_tmout, TB_SE0_SRP,
+				(unsigned long)&fsm->b_se0_srp);
+	if (!b_se0_srp_tmr)
+		return -ENOMEM;
+
+	b_srp_fail_tmr = otg_timer_initializer(&set_tmout, TB_SRP_FAIL,
+				(unsigned long)&fsm->b_srp_done);
+	if (!b_srp_fail_tmr)
+		return -ENOMEM;
+
+	a_wait_enum_tmr = otg_timer_initializer(&a_wait_enum, 10,
+				(unsigned long)&fsm);
+	if (!a_wait_enum_tmr)
+		return -ENOMEM;
+
+	/* device driver used timers */
+	b_srp_wait_tmr = otg_timer_initializer(&b_srp_end, TB_SRP_WAIT, 0);
+	if (!b_srp_wait_tmr)
+		return -ENOMEM;
+
+	b_data_pulse_tmr = otg_timer_initializer(&b_data_pulse_end,
+				TB_DATA_PLS, 0);
+	if (!b_data_pulse_tmr)
+		return -ENOMEM;
+
+	b_vbus_pulse_tmr = otg_timer_initializer(&b_vbus_pulse_end,
+				TB_VBUS_PLS, 0);
+	if (!b_vbus_pulse_tmr)
+		return -ENOMEM;
+
+	return 0;
+}
+
+/* Uninitialize timers */
+void fsl_otg_uninit_timers(void)
+{
+	/* FSM used timers */
+	kfree(a_wait_vrise_tmr);
+	kfree(a_wait_bcon_tmr);
+	kfree(a_aidl_bdis_tmr);
+	kfree(b_ase0_brst_tmr);
+	kfree(b_se0_srp_tmr);
+	kfree(b_srp_fail_tmr);
+	kfree(a_wait_enum_tmr);
+
+	/* device driver used timers */
+	kfree(b_srp_wait_tmr);
+	kfree(b_data_pulse_tmr);
+	kfree(b_vbus_pulse_tmr);
+}
+
+/* Add timer to timer list */
+void fsl_otg_add_timer(void *gtimer)
+{
+	struct fsl_otg_timer *timer = gtimer;
+	struct fsl_otg_timer *tmp_timer;
+
+	/*
+	 * Check if the timer is already in the active list,
+	 * if so update timer count
+	 */
+	list_for_each_entry(tmp_timer, &active_timers, list)
+	    if (tmp_timer == timer) {
+		timer->count = timer->expires;
+		return;
+	}
+	timer->count = timer->expires;
+	list_add_tail(&timer->list, &active_timers);
+}
+
+/* Remove timer from the timer list; clear timeout status */
+void fsl_otg_del_timer(void *gtimer)
+{
+	struct fsl_otg_timer *timer = gtimer;
+	struct fsl_otg_timer *tmp_timer, *del_tmp;
+
+	list_for_each_entry_safe(tmp_timer, del_tmp, &active_timers, list)
+		if (tmp_timer == timer)
+			list_del(&timer->list);
+}
+
+/*
+ * Reduce timer count by 1, and find timeout conditions.
+ * Called by fsl_otg 1ms timer interrupt
+ */
+int fsl_otg_tick_timer(void)
+{
+	struct fsl_otg_timer *tmp_timer, *del_tmp;
+	int expired = 0;
+
+	list_for_each_entry_safe(tmp_timer, del_tmp, &active_timers, list) {
+		tmp_timer->count--;
+		/* check if timer expires */
+		if (!tmp_timer->count) {
+			list_del(&tmp_timer->list);
+			tmp_timer->function(tmp_timer->data);
+			expired = 1;
+		}
+	}
+
+	return expired;
+}
+
+/* Reset controller, not reset the bus */
+void otg_reset_controller(void)
+{
+	u32 command;
+
+	command = fsl_readl(&usb_dr_regs->usbcmd);
+	command |= (1 << 1);
+	fsl_writel(command, &usb_dr_regs->usbcmd);
+	while (fsl_readl(&usb_dr_regs->usbcmd) & (1 << 1))
+		;
+}
+
+/* Call suspend/resume routines in host driver */
+int fsl_otg_start_host(struct otg_fsm *fsm, int on)
+{
+	struct usb_otg *otg = fsm->otg;
+	struct device *dev;
+	struct fsl_otg *otg_dev = container_of(otg->phy, struct fsl_otg, phy);
+	u32 retval = 0;
+
+	if (!otg->host)
+		return -ENODEV;
+	dev = otg->host->controller;
+
+	/*
+	 * Update a_vbus_vld state as a_vbus_vld int is disabled
+	 * in device mode
+	 */
+	fsm->a_vbus_vld =
+		!!(fsl_readl(&usb_dr_regs->otgsc) & OTGSC_STS_A_VBUS_VALID);
+	if (on) {
+		/* start fsl usb host controller */
+		if (otg_dev->host_working)
+			goto end;
+		else {
+			otg_reset_controller();
+			VDBG("host on......\n");
+			if (dev->driver->pm && dev->driver->pm->resume) {
+				retval = dev->driver->pm->resume(dev);
+				if (fsm->id) {
+					/* default-b */
+					fsl_otg_drv_vbus(1);
+					/*
+					 * Workaround: b_host can't driver
+					 * vbus, but PP in PORTSC needs to
+					 * be 1 for host to work.
+					 * So we set drv_vbus bit in
+					 * transceiver to 0 thru ULPI.
+					 */
+					write_ulpi(0x0c, 0x20);
+				}
+			}
+
+			otg_dev->host_working = 1;
+		}
+	} else {
+		/* stop fsl usb host controller */
+		if (!otg_dev->host_working)
+			goto end;
+		else {
+			VDBG("host off......\n");
+			if (dev && dev->driver) {
+				if (dev->driver->pm && dev->driver->pm->suspend)
+					retval = dev->driver->pm->suspend(dev);
+				if (fsm->id)
+					/* default-b */
+					fsl_otg_drv_vbus(0);
+			}
+			otg_dev->host_working = 0;
+		}
+	}
+end:
+	return retval;
+}
+
+/*
+ * Call suspend and resume function in udc driver
+ * to stop and start udc driver.
+ */
+int fsl_otg_start_gadget(struct otg_fsm *fsm, int on)
+{
+	struct usb_otg *otg = fsm->otg;
+	struct device *dev;
+
+	if (!otg->gadget || !otg->gadget->dev.parent)
+		return -ENODEV;
+
+	VDBG("gadget %s\n", on ? "on" : "off");
+	dev = otg->gadget->dev.parent;
+
+	if (on) {
+		if (dev->driver->resume)
+			dev->driver->resume(dev);
+	} else {
+		if (dev->driver->suspend)
+			dev->driver->suspend(dev, otg_suspend_state);
+	}
+
+	return 0;
+}
+
+/*
+ * Called by initialization code of host driver.  Register host controller
+ * to the OTG.  Suspend host for OTG role detection.
+ */
+static int fsl_otg_set_host(struct usb_otg *otg, struct usb_bus *host)
+{
+	struct fsl_otg *otg_dev;
+
+	if (!otg)
+		return -ENODEV;
+
+	otg_dev = container_of(otg->phy, struct fsl_otg, phy);
+	if (otg_dev != fsl_otg_dev)
+		return -ENODEV;
+
+	otg->host = host;
+
+	otg_dev->fsm.a_bus_drop = 0;
+	otg_dev->fsm.a_bus_req = 1;
+
+	if (host) {
+		VDBG("host off......\n");
+
+		otg->host->otg_port = fsl_otg_initdata.otg_port;
+		otg->host->is_b_host = otg_dev->fsm.id;
+		/*
+		 * must leave time for khubd to finish its thing
+		 * before yanking the host driver out from under it,
+		 * so suspend the host after a short delay.
+		 */
+		otg_dev->host_working = 1;
+		schedule_delayed_work(&otg_dev->otg_event, 100);
+		return 0;
+	} else {
+		/* host driver going away */
+		if (!(fsl_readl(&otg_dev->dr_mem_map->otgsc) &
+		      OTGSC_STS_USB_ID)) {
+			/* Mini-A cable connected */
+			struct otg_fsm *fsm = &otg_dev->fsm;
+
+			otg->phy->state = OTG_STATE_UNDEFINED;
+			fsm->protocol = PROTO_UNDEF;
+		}
+	}
+
+	otg_dev->host_working = 0;
+
+	otg_statemachine(&otg_dev->fsm);
+
+	return 0;
+}
+
+/* Called by initialization code of udc.  Register udc to OTG. */
+static int fsl_otg_set_peripheral(struct usb_otg *otg,
+					struct usb_gadget *gadget)
+{
+	struct fsl_otg *otg_dev;
+
+	if (!otg)
+		return -ENODEV;
+
+	otg_dev = container_of(otg->phy, struct fsl_otg, phy);
+	VDBG("otg_dev 0x%x\n", (int)otg_dev);
+	VDBG("fsl_otg_dev 0x%x\n", (int)fsl_otg_dev);
+	if (otg_dev != fsl_otg_dev)
+		return -ENODEV;
+
+	if (!gadget) {
+		if (!otg->default_a)
+			otg->gadget->ops->vbus_draw(otg->gadget, 0);
+		usb_gadget_vbus_disconnect(otg->gadget);
+		otg->gadget = 0;
+		otg_dev->fsm.b_bus_req = 0;
+		otg_statemachine(&otg_dev->fsm);
+		return 0;
+	}
+
+	otg->gadget = gadget;
+	otg->gadget->is_a_peripheral = !otg_dev->fsm.id;
+
+	otg_dev->fsm.b_bus_req = 1;
+
+	/* start the gadget right away if the ID pin says Mini-B */
+	DBG("ID pin=%d\n", otg_dev->fsm.id);
+	if (otg_dev->fsm.id == 1) {
+		fsl_otg_start_host(&otg_dev->fsm, 0);
+		otg_drv_vbus(&otg_dev->fsm, 0);
+		fsl_otg_start_gadget(&otg_dev->fsm, 1);
+	}
+
+	return 0;
+}
+
+/* Set OTG port power, only for B-device */
+static int fsl_otg_set_power(struct usb_phy *phy, unsigned mA)
+{
+	if (!fsl_otg_dev)
+		return -ENODEV;
+	if (phy->state == OTG_STATE_B_PERIPHERAL)
+		pr_info("FSL OTG: Draw %d mA\n", mA);
+
+	return 0;
+}
+
+/*
+ * Delayed pin detect interrupt processing.
+ *
+ * When the Mini-A cable is disconnected from the board,
+ * the pin-detect interrupt happens before the disconnect
+ * interrupts for the connected device(s).  In order to
+ * process the disconnect interrupt(s) prior to switching
+ * roles, the pin-detect interrupts are delayed, and handled
+ * by this routine.
+ */
+static void fsl_otg_event(struct work_struct *work)
+{
+	struct fsl_otg *og = container_of(work, struct fsl_otg, otg_event.work);
+	struct otg_fsm *fsm = &og->fsm;
+
+	if (fsm->id) {		/* switch to gadget */
+		fsl_otg_start_host(fsm, 0);
+		otg_drv_vbus(fsm, 0);
+		fsl_otg_start_gadget(fsm, 1);
+	}
+}
+
+/* B-device start SRP */
+static int fsl_otg_start_srp(struct usb_otg *otg)
+{
+	struct fsl_otg *otg_dev;
+
+	if (!otg || otg->phy->state != OTG_STATE_B_IDLE)
+		return -ENODEV;
+
+	otg_dev = container_of(otg->phy, struct fsl_otg, phy);
+	if (otg_dev != fsl_otg_dev)
+		return -ENODEV;
+
+	otg_dev->fsm.b_bus_req = 1;
+	otg_statemachine(&otg_dev->fsm);
+
+	return 0;
+}
+
+/* A_host suspend will call this function to start hnp */
+static int fsl_otg_start_hnp(struct usb_otg *otg)
+{
+	struct fsl_otg *otg_dev;
+
+	if (!otg)
+		return -ENODEV;
+
+	otg_dev = container_of(otg->phy, struct fsl_otg, phy);
+	if (otg_dev != fsl_otg_dev)
+		return -ENODEV;
+
+	DBG("start_hnp...n");
+
+	/* clear a_bus_req to enter a_suspend state */
+	otg_dev->fsm.a_bus_req = 0;
+	otg_statemachine(&otg_dev->fsm);
+
+	return 0;
+}
+
+/*
+ * Interrupt handler.  OTG/host/peripheral share the same int line.
+ * OTG driver clears OTGSC interrupts and leaves USB interrupts
+ * intact.  It needs to have knowledge of some USB interrupts
+ * such as port change.
+ */
+irqreturn_t fsl_otg_isr(int irq, void *dev_id)
+{
+	struct otg_fsm *fsm = &((struct fsl_otg *)dev_id)->fsm;
+	struct usb_otg *otg = ((struct fsl_otg *)dev_id)->phy.otg;
+	u32 otg_int_src, otg_sc;
+
+	otg_sc = fsl_readl(&usb_dr_regs->otgsc);
+	otg_int_src = otg_sc & OTGSC_INTSTS_MASK & (otg_sc >> 8);
+
+	/* Only clear otg interrupts */
+	fsl_writel(otg_sc, &usb_dr_regs->otgsc);
+
+	/*FIXME: ID change not generate when init to 0 */
+	fsm->id = (otg_sc & OTGSC_STS_USB_ID) ? 1 : 0;
+	otg->default_a = (fsm->id == 0);
+
+	/* process OTG interrupts */
+	if (otg_int_src) {
+		if (otg_int_src & OTGSC_INTSTS_USB_ID) {
+			fsm->id = (otg_sc & OTGSC_STS_USB_ID) ? 1 : 0;
+			otg->default_a = (fsm->id == 0);
+			/* clear conn information */
+			if (fsm->id)
+				fsm->b_conn = 0;
+			else
+				fsm->a_conn = 0;
+
+			if (otg->host)
+				otg->host->is_b_host = fsm->id;
+			if (otg->gadget)
+				otg->gadget->is_a_peripheral = !fsm->id;
+			VDBG("ID int (ID is %d)\n", fsm->id);
+
+			if (fsm->id) {	/* switch to gadget */
+				schedule_delayed_work(
+					&((struct fsl_otg *)dev_id)->otg_event,
+					100);
+			} else {	/* switch to host */
+				cancel_delayed_work(&
+						    ((struct fsl_otg *)dev_id)->
+						    otg_event);
+				fsl_otg_start_gadget(fsm, 0);
+				otg_drv_vbus(fsm, 1);
+				fsl_otg_start_host(fsm, 1);
+			}
+			return IRQ_HANDLED;
+		}
+	}
+	return IRQ_NONE;
+}
+
+static struct otg_fsm_ops fsl_otg_ops = {
+	.chrg_vbus = fsl_otg_chrg_vbus,
+	.drv_vbus = fsl_otg_drv_vbus,
+	.loc_conn = fsl_otg_loc_conn,
+	.loc_sof = fsl_otg_loc_sof,
+	.start_pulse = fsl_otg_start_pulse,
+
+	.add_timer = fsl_otg_add_timer,
+	.del_timer = fsl_otg_del_timer,
+
+	.start_host = fsl_otg_start_host,
+	.start_gadget = fsl_otg_start_gadget,
+};
+
+/* Initialize the global variable fsl_otg_dev and request IRQ for OTG */
+static int fsl_otg_conf(struct platform_device *pdev)
+{
+	struct fsl_otg *fsl_otg_tc;
+	int status;
+
+	if (fsl_otg_dev)
+		return 0;
+
+	/* allocate space to fsl otg device */
+	fsl_otg_tc = kzalloc(sizeof(struct fsl_otg), GFP_KERNEL);
+	if (!fsl_otg_tc)
+		return -ENOMEM;
+
+	fsl_otg_tc->phy.otg = kzalloc(sizeof(struct usb_otg), GFP_KERNEL);
+	if (!fsl_otg_tc->phy.otg) {
+		kfree(fsl_otg_tc);
+		return -ENOMEM;
+	}
+
+	INIT_DELAYED_WORK(&fsl_otg_tc->otg_event, fsl_otg_event);
+
+	INIT_LIST_HEAD(&active_timers);
+	status = fsl_otg_init_timers(&fsl_otg_tc->fsm);
+	if (status) {
+		pr_info("Couldn't init OTG timers\n");
+		goto err;
+	}
+	spin_lock_init(&fsl_otg_tc->fsm.lock);
+
+	/* Set OTG state machine operations */
+	fsl_otg_tc->fsm.ops = &fsl_otg_ops;
+
+	/* initialize the otg structure */
+	fsl_otg_tc->phy.label = DRIVER_DESC;
+	fsl_otg_tc->phy.set_power = fsl_otg_set_power;
+
+	fsl_otg_tc->phy.otg->phy = &fsl_otg_tc->phy;
+	fsl_otg_tc->phy.otg->set_host = fsl_otg_set_host;
+	fsl_otg_tc->phy.otg->set_peripheral = fsl_otg_set_peripheral;
+	fsl_otg_tc->phy.otg->start_hnp = fsl_otg_start_hnp;
+	fsl_otg_tc->phy.otg->start_srp = fsl_otg_start_srp;
+
+	fsl_otg_dev = fsl_otg_tc;
+
+	/* Store the otg transceiver */
+	status = usb_add_phy(&fsl_otg_tc->phy, USB_PHY_TYPE_USB2);
+	if (status) {
+		pr_warn(FSL_OTG_NAME ": unable to register OTG transceiver.\n");
+		goto err;
+	}
+
+	return 0;
+err:
+	fsl_otg_uninit_timers();
+	kfree(fsl_otg_tc->phy.otg);
+	kfree(fsl_otg_tc);
+	return status;
+}
+
+/* OTG Initialization */
+int usb_otg_start(struct platform_device *pdev)
+{
+	struct fsl_otg *p_otg;
+	struct usb_phy *otg_trans = usb_get_phy(USB_PHY_TYPE_USB2);
+	struct otg_fsm *fsm;
+	int status;
+	struct resource *res;
+	u32 temp;
+	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
+
+	p_otg = container_of(otg_trans, struct fsl_otg, phy);
+	fsm = &p_otg->fsm;
+
+	/* Initialize the state machine structure with default values */
+	SET_OTG_STATE(otg_trans, OTG_STATE_UNDEFINED);
+	fsm->otg = p_otg->phy.otg;
+
+	/* We don't require predefined MEM/IRQ resource index */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENXIO;
+
+	/* We don't request_mem_region here to enable resource sharing
+	 * with host/device */
+
+	usb_dr_regs = ioremap(res->start, sizeof(struct usb_dr_mmap));
+	p_otg->dr_mem_map = (struct usb_dr_mmap *)usb_dr_regs;
+	pdata->regs = (void *)usb_dr_regs;
+
+	if (pdata->init && pdata->init(pdev) != 0)
+		return -EINVAL;
+
+	if (pdata->big_endian_mmio) {
+		_fsl_readl = _fsl_readl_be;
+		_fsl_writel = _fsl_writel_be;
+	} else {
+		_fsl_readl = _fsl_readl_le;
+		_fsl_writel = _fsl_writel_le;
+	}
+
+	/* request irq */
+	p_otg->irq = platform_get_irq(pdev, 0);
+	status = request_irq(p_otg->irq, fsl_otg_isr,
+				IRQF_SHARED, driver_name, p_otg);
+	if (status) {
+		dev_dbg(p_otg->phy.dev, "can't get IRQ %d, error %d\n",
+			p_otg->irq, status);
+		iounmap(p_otg->dr_mem_map);
+		kfree(p_otg->phy.otg);
+		kfree(p_otg);
+		return status;
+	}
+
+	/* stop the controller */
+	temp = fsl_readl(&p_otg->dr_mem_map->usbcmd);
+	temp &= ~USB_CMD_RUN_STOP;
+	fsl_writel(temp, &p_otg->dr_mem_map->usbcmd);
+
+	/* reset the controller */
+	temp = fsl_readl(&p_otg->dr_mem_map->usbcmd);
+	temp |= USB_CMD_CTRL_RESET;
+	fsl_writel(temp, &p_otg->dr_mem_map->usbcmd);
+
+	/* wait reset completed */
+	while (fsl_readl(&p_otg->dr_mem_map->usbcmd) & USB_CMD_CTRL_RESET)
+		;
+
+	/* configure the VBUSHS as IDLE(both host and device) */
+	temp = USB_MODE_STREAM_DISABLE | (pdata->es ? USB_MODE_ES : 0);
+	fsl_writel(temp, &p_otg->dr_mem_map->usbmode);
+
+	/* configure PHY interface */
+	temp = fsl_readl(&p_otg->dr_mem_map->portsc);
+	temp &= ~(PORTSC_PHY_TYPE_SEL | PORTSC_PTW);
+	switch (pdata->phy_mode) {
+	case FSL_USB2_PHY_ULPI:
+		temp |= PORTSC_PTS_ULPI;
+		break;
+	case FSL_USB2_PHY_UTMI_WIDE:
+		temp |= PORTSC_PTW_16BIT;
+		/* fall through */
+	case FSL_USB2_PHY_UTMI:
+		temp |= PORTSC_PTS_UTMI;
+		/* fall through */
+	default:
+		break;
+	}
+	fsl_writel(temp, &p_otg->dr_mem_map->portsc);
+
+	if (pdata->have_sysif_regs) {
+		/* configure control enable IO output, big endian register */
+		temp = __raw_readl(&p_otg->dr_mem_map->control);
+		temp |= USB_CTRL_IOENB;
+		__raw_writel(temp, &p_otg->dr_mem_map->control);
+	}
+
+	/* disable all interrupt and clear all OTGSC status */
+	temp = fsl_readl(&p_otg->dr_mem_map->otgsc);
+	temp &= ~OTGSC_INTERRUPT_ENABLE_BITS_MASK;
+	temp |= OTGSC_INTERRUPT_STATUS_BITS_MASK | OTGSC_CTRL_VBUS_DISCHARGE;
+	fsl_writel(temp, &p_otg->dr_mem_map->otgsc);
+
+	/*
+	 * The identification (id) input is FALSE when a Mini-A plug is inserted
+	 * in the devices Mini-AB receptacle. Otherwise, this input is TRUE.
+	 * Also: record initial state of ID pin
+	 */
+	if (fsl_readl(&p_otg->dr_mem_map->otgsc) & OTGSC_STS_USB_ID) {
+		p_otg->phy.state = OTG_STATE_UNDEFINED;
+		p_otg->fsm.id = 1;
+	} else {
+		p_otg->phy.state = OTG_STATE_A_IDLE;
+		p_otg->fsm.id = 0;
+	}
+
+	DBG("initial ID pin=%d\n", p_otg->fsm.id);
+
+	/* enable OTG ID pin interrupt */
+	temp = fsl_readl(&p_otg->dr_mem_map->otgsc);
+	temp |= OTGSC_INTR_USB_ID_EN;
+	temp &= ~(OTGSC_CTRL_VBUS_DISCHARGE | OTGSC_INTR_1MS_TIMER_EN);
+	fsl_writel(temp, &p_otg->dr_mem_map->otgsc);
+
+	return 0;
+}
+
+/*
+ * state file in sysfs
+ */
+static int show_fsl_usb2_otg_state(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	struct otg_fsm *fsm = &fsl_otg_dev->fsm;
+	char *next = buf;
+	unsigned size = PAGE_SIZE;
+	unsigned long flags;
+	int t;
+
+	spin_lock_irqsave(&fsm->lock, flags);
+
+	/* basic driver infomation */
+	t = scnprintf(next, size,
+			DRIVER_DESC "\n" "fsl_usb2_otg version: %s\n\n",
+			DRIVER_VERSION);
+	size -= t;
+	next += t;
+
+	/* Registers */
+	t = scnprintf(next, size,
+			"OTGSC:   0x%08x\n"
+			"PORTSC:  0x%08x\n"
+			"USBMODE: 0x%08x\n"
+			"USBCMD:  0x%08x\n"
+			"USBSTS:  0x%08x\n"
+			"USBINTR: 0x%08x\n",
+			fsl_readl(&usb_dr_regs->otgsc),
+			fsl_readl(&usb_dr_regs->portsc),
+			fsl_readl(&usb_dr_regs->usbmode),
+			fsl_readl(&usb_dr_regs->usbcmd),
+			fsl_readl(&usb_dr_regs->usbsts),
+			fsl_readl(&usb_dr_regs->usbintr));
+	size -= t;
+	next += t;
+
+	/* State */
+	t = scnprintf(next, size,
+		      "OTG state: %s\n\n",
+		      usb_otg_state_string(fsl_otg_dev->phy.state));
+	size -= t;
+	next += t;
+
+	/* State Machine Variables */
+	t = scnprintf(next, size,
+			"a_bus_req: %d\n"
+			"b_bus_req: %d\n"
+			"a_bus_resume: %d\n"
+			"a_bus_suspend: %d\n"
+			"a_conn: %d\n"
+			"a_sess_vld: %d\n"
+			"a_srp_det: %d\n"
+			"a_vbus_vld: %d\n"
+			"b_bus_resume: %d\n"
+			"b_bus_suspend: %d\n"
+			"b_conn: %d\n"
+			"b_se0_srp: %d\n"
+			"b_sess_end: %d\n"
+			"b_sess_vld: %d\n"
+			"id: %d\n",
+			fsm->a_bus_req,
+			fsm->b_bus_req,
+			fsm->a_bus_resume,
+			fsm->a_bus_suspend,
+			fsm->a_conn,
+			fsm->a_sess_vld,
+			fsm->a_srp_det,
+			fsm->a_vbus_vld,
+			fsm->b_bus_resume,
+			fsm->b_bus_suspend,
+			fsm->b_conn,
+			fsm->b_se0_srp,
+			fsm->b_sess_end,
+			fsm->b_sess_vld,
+			fsm->id);
+	size -= t;
+	next += t;
+
+	spin_unlock_irqrestore(&fsm->lock, flags);
+
+	return PAGE_SIZE - size;
+}
+
+static DEVICE_ATTR(fsl_usb2_otg_state, S_IRUGO, show_fsl_usb2_otg_state, NULL);
+
+
+/* Char driver interface to control some OTG input */
+
+/*
+ * Handle some ioctl command, such as get otg
+ * status and set host suspend
+ */
+static long fsl_otg_ioctl(struct file *file, unsigned int cmd,
+			  unsigned long arg)
+{
+	u32 retval = 0;
+
+	switch (cmd) {
+	case GET_OTG_STATUS:
+		retval = fsl_otg_dev->host_working;
+		break;
+
+	case SET_A_SUSPEND_REQ:
+		fsl_otg_dev->fsm.a_suspend_req = arg;
+		break;
+
+	case SET_A_BUS_DROP:
+		fsl_otg_dev->fsm.a_bus_drop = arg;
+		break;
+
+	case SET_A_BUS_REQ:
+		fsl_otg_dev->fsm.a_bus_req = arg;
+		break;
+
+	case SET_B_BUS_REQ:
+		fsl_otg_dev->fsm.b_bus_req = arg;
+		break;
+
+	default:
+		break;
+	}
+
+	otg_statemachine(&fsl_otg_dev->fsm);
+
+	return retval;
+}
+
+static int fsl_otg_open(struct inode *inode, struct file *file)
+{
+	return 0;
+}
+
+static int fsl_otg_release(struct inode *inode, struct file *file)
+{
+	return 0;
+}
+
+static const struct file_operations otg_fops = {
+	.owner = THIS_MODULE,
+	.llseek = NULL,
+	.read = NULL,
+	.write = NULL,
+	.unlocked_ioctl = fsl_otg_ioctl,
+	.open = fsl_otg_open,
+	.release = fsl_otg_release,
+};
+
+static int fsl_otg_probe(struct platform_device *pdev)
+{
+	int ret;
+
+	if (!pdev->dev.platform_data)
+		return -ENODEV;
+
+	/* configure the OTG */
+	ret = fsl_otg_conf(pdev);
+	if (ret) {
+		dev_err(&pdev->dev, "Couldn't configure OTG module\n");
+		return ret;
+	}
+
+	/* start OTG */
+	ret = usb_otg_start(pdev);
+	if (ret) {
+		dev_err(&pdev->dev, "Can't init FSL OTG device\n");
+		return ret;
+	}
+
+	ret = register_chrdev(FSL_OTG_MAJOR, FSL_OTG_NAME, &otg_fops);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to register FSL OTG device\n");
+		return ret;
+	}
+
+	ret = device_create_file(&pdev->dev, &dev_attr_fsl_usb2_otg_state);
+	if (ret)
+		dev_warn(&pdev->dev, "Can't register sysfs attribute\n");
+
+	return ret;
+}
+
+static int fsl_otg_remove(struct platform_device *pdev)
+{
+	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
+
+	usb_remove_phy(&fsl_otg_dev->phy);
+	free_irq(fsl_otg_dev->irq, fsl_otg_dev);
+
+	iounmap((void *)usb_dr_regs);
+
+	fsl_otg_uninit_timers();
+	kfree(fsl_otg_dev->phy.otg);
+	kfree(fsl_otg_dev);
+
+	device_remove_file(&pdev->dev, &dev_attr_fsl_usb2_otg_state);
+
+	unregister_chrdev(FSL_OTG_MAJOR, FSL_OTG_NAME);
+
+	if (pdata->exit)
+		pdata->exit(pdev);
+
+	return 0;
+}
+
+struct platform_driver fsl_otg_driver = {
+	.probe = fsl_otg_probe,
+	.remove = fsl_otg_remove,
+	.driver = {
+		.name = driver_name,
+		.owner = THIS_MODULE,
+	},
+};
+
+module_platform_driver(fsl_otg_driver);
+
+MODULE_DESCRIPTION(DRIVER_INFO);
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/phy/phy-fsl-usb.h b/drivers/usb/phy/phy-fsl-usb.h
new file mode 100644
index 0000000..ca26628
--- /dev/null
+++ b/drivers/usb/phy/phy-fsl-usb.h
@@ -0,0 +1,406 @@
+/* Copyright (C) 2007,2008 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.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You 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 "otg_fsm.h"
+#include <linux/usb/otg.h>
+#include <linux/ioctl.h>
+
+/* USB Command Register Bit Masks */
+#define USB_CMD_RUN_STOP		(0x1<<0)
+#define USB_CMD_CTRL_RESET		(0x1<<1)
+#define USB_CMD_PERIODIC_SCHEDULE_EN	(0x1<<4)
+#define USB_CMD_ASYNC_SCHEDULE_EN	(0x1<<5)
+#define USB_CMD_INT_AA_DOORBELL		(0x1<<6)
+#define USB_CMD_ASP			(0x3<<8)
+#define USB_CMD_ASYNC_SCH_PARK_EN	(0x1<<11)
+#define USB_CMD_SUTW			(0x1<<13)
+#define USB_CMD_ATDTW			(0x1<<14)
+#define USB_CMD_ITC			(0xFF<<16)
+
+/* bit 15,3,2 are frame list size */
+#define USB_CMD_FRAME_SIZE_1024		(0x0<<15 | 0x0<<2)
+#define USB_CMD_FRAME_SIZE_512		(0x0<<15 | 0x1<<2)
+#define USB_CMD_FRAME_SIZE_256		(0x0<<15 | 0x2<<2)
+#define USB_CMD_FRAME_SIZE_128		(0x0<<15 | 0x3<<2)
+#define USB_CMD_FRAME_SIZE_64		(0x1<<15 | 0x0<<2)
+#define USB_CMD_FRAME_SIZE_32		(0x1<<15 | 0x1<<2)
+#define USB_CMD_FRAME_SIZE_16		(0x1<<15 | 0x2<<2)
+#define USB_CMD_FRAME_SIZE_8		(0x1<<15 | 0x3<<2)
+
+/* bit 9-8 are async schedule park mode count */
+#define USB_CMD_ASP_00			(0x0<<8)
+#define USB_CMD_ASP_01			(0x1<<8)
+#define USB_CMD_ASP_10			(0x2<<8)
+#define USB_CMD_ASP_11			(0x3<<8)
+#define USB_CMD_ASP_BIT_POS		(8)
+
+/* bit 23-16 are interrupt threshold control */
+#define USB_CMD_ITC_NO_THRESHOLD	(0x00<<16)
+#define USB_CMD_ITC_1_MICRO_FRM		(0x01<<16)
+#define USB_CMD_ITC_2_MICRO_FRM		(0x02<<16)
+#define USB_CMD_ITC_4_MICRO_FRM		(0x04<<16)
+#define USB_CMD_ITC_8_MICRO_FRM		(0x08<<16)
+#define USB_CMD_ITC_16_MICRO_FRM	(0x10<<16)
+#define USB_CMD_ITC_32_MICRO_FRM	(0x20<<16)
+#define USB_CMD_ITC_64_MICRO_FRM	(0x40<<16)
+#define USB_CMD_ITC_BIT_POS		(16)
+
+/* USB Status Register Bit Masks */
+#define USB_STS_INT			(0x1<<0)
+#define USB_STS_ERR			(0x1<<1)
+#define USB_STS_PORT_CHANGE		(0x1<<2)
+#define USB_STS_FRM_LST_ROLL		(0x1<<3)
+#define USB_STS_SYS_ERR			(0x1<<4)
+#define USB_STS_IAA			(0x1<<5)
+#define USB_STS_RESET_RECEIVED		(0x1<<6)
+#define USB_STS_SOF			(0x1<<7)
+#define USB_STS_DCSUSPEND		(0x1<<8)
+#define USB_STS_HC_HALTED		(0x1<<12)
+#define USB_STS_RCL			(0x1<<13)
+#define USB_STS_PERIODIC_SCHEDULE	(0x1<<14)
+#define USB_STS_ASYNC_SCHEDULE		(0x1<<15)
+
+/* USB Interrupt Enable Register Bit Masks */
+#define USB_INTR_INT_EN			(0x1<<0)
+#define USB_INTR_ERR_INT_EN		(0x1<<1)
+#define USB_INTR_PC_DETECT_EN		(0x1<<2)
+#define USB_INTR_FRM_LST_ROLL_EN	(0x1<<3)
+#define USB_INTR_SYS_ERR_EN		(0x1<<4)
+#define USB_INTR_ASYN_ADV_EN		(0x1<<5)
+#define USB_INTR_RESET_EN		(0x1<<6)
+#define USB_INTR_SOF_EN			(0x1<<7)
+#define USB_INTR_DEVICE_SUSPEND		(0x1<<8)
+
+/* Device Address bit masks */
+#define USB_DEVICE_ADDRESS_MASK		(0x7F<<25)
+#define USB_DEVICE_ADDRESS_BIT_POS	(25)
+/* PORTSC  Register Bit Masks,Only one PORT in OTG mode*/
+#define PORTSC_CURRENT_CONNECT_STATUS	(0x1<<0)
+#define PORTSC_CONNECT_STATUS_CHANGE	(0x1<<1)
+#define PORTSC_PORT_ENABLE		(0x1<<2)
+#define PORTSC_PORT_EN_DIS_CHANGE	(0x1<<3)
+#define PORTSC_OVER_CURRENT_ACT		(0x1<<4)
+#define PORTSC_OVER_CUURENT_CHG		(0x1<<5)
+#define PORTSC_PORT_FORCE_RESUME	(0x1<<6)
+#define PORTSC_PORT_SUSPEND		(0x1<<7)
+#define PORTSC_PORT_RESET		(0x1<<8)
+#define PORTSC_LINE_STATUS_BITS		(0x3<<10)
+#define PORTSC_PORT_POWER		(0x1<<12)
+#define PORTSC_PORT_INDICTOR_CTRL	(0x3<<14)
+#define PORTSC_PORT_TEST_CTRL		(0xF<<16)
+#define PORTSC_WAKE_ON_CONNECT_EN	(0x1<<20)
+#define PORTSC_WAKE_ON_CONNECT_DIS	(0x1<<21)
+#define PORTSC_WAKE_ON_OVER_CURRENT	(0x1<<22)
+#define PORTSC_PHY_LOW_POWER_SPD	(0x1<<23)
+#define PORTSC_PORT_FORCE_FULL_SPEED	(0x1<<24)
+#define PORTSC_PORT_SPEED_MASK		(0x3<<26)
+#define PORTSC_TRANSCEIVER_WIDTH	(0x1<<28)
+#define PORTSC_PHY_TYPE_SEL		(0x3<<30)
+/* bit 11-10 are line status */
+#define PORTSC_LINE_STATUS_SE0		(0x0<<10)
+#define PORTSC_LINE_STATUS_JSTATE	(0x1<<10)
+#define PORTSC_LINE_STATUS_KSTATE	(0x2<<10)
+#define PORTSC_LINE_STATUS_UNDEF	(0x3<<10)
+#define PORTSC_LINE_STATUS_BIT_POS	(10)
+
+/* bit 15-14 are port indicator control */
+#define PORTSC_PIC_OFF			(0x0<<14)
+#define PORTSC_PIC_AMBER		(0x1<<14)
+#define PORTSC_PIC_GREEN		(0x2<<14)
+#define PORTSC_PIC_UNDEF		(0x3<<14)
+#define PORTSC_PIC_BIT_POS		(14)
+
+/* bit 19-16 are port test control */
+#define PORTSC_PTC_DISABLE		(0x0<<16)
+#define PORTSC_PTC_JSTATE		(0x1<<16)
+#define PORTSC_PTC_KSTATE		(0x2<<16)
+#define PORTSC_PTC_SEQNAK		(0x3<<16)
+#define PORTSC_PTC_PACKET		(0x4<<16)
+#define PORTSC_PTC_FORCE_EN		(0x5<<16)
+#define PORTSC_PTC_BIT_POS		(16)
+
+/* bit 27-26 are port speed */
+#define PORTSC_PORT_SPEED_FULL		(0x0<<26)
+#define PORTSC_PORT_SPEED_LOW		(0x1<<26)
+#define PORTSC_PORT_SPEED_HIGH		(0x2<<26)
+#define PORTSC_PORT_SPEED_UNDEF		(0x3<<26)
+#define PORTSC_SPEED_BIT_POS		(26)
+
+/* bit 28 is parallel transceiver width for UTMI interface */
+#define PORTSC_PTW			(0x1<<28)
+#define PORTSC_PTW_8BIT			(0x0<<28)
+#define PORTSC_PTW_16BIT		(0x1<<28)
+
+/* bit 31-30 are port transceiver select */
+#define PORTSC_PTS_UTMI			(0x0<<30)
+#define PORTSC_PTS_ULPI			(0x2<<30)
+#define PORTSC_PTS_FSLS_SERIAL		(0x3<<30)
+#define PORTSC_PTS_BIT_POS		(30)
+
+#define PORTSC_W1C_BITS			\
+	(PORTSC_CONNECT_STATUS_CHANGE |	\
+	 PORTSC_PORT_EN_DIS_CHANGE    |	\
+	 PORTSC_OVER_CUURENT_CHG)
+
+/* OTG Status Control Register Bit Masks */
+#define OTGSC_CTRL_VBUS_DISCHARGE	(0x1<<0)
+#define OTGSC_CTRL_VBUS_CHARGE		(0x1<<1)
+#define OTGSC_CTRL_OTG_TERMINATION	(0x1<<3)
+#define OTGSC_CTRL_DATA_PULSING		(0x1<<4)
+#define OTGSC_CTRL_ID_PULL_EN		(0x1<<5)
+#define OTGSC_HA_DATA_PULSE		(0x1<<6)
+#define OTGSC_HA_BA			(0x1<<7)
+#define OTGSC_STS_USB_ID		(0x1<<8)
+#define OTGSC_STS_A_VBUS_VALID		(0x1<<9)
+#define OTGSC_STS_A_SESSION_VALID	(0x1<<10)
+#define OTGSC_STS_B_SESSION_VALID	(0x1<<11)
+#define OTGSC_STS_B_SESSION_END		(0x1<<12)
+#define OTGSC_STS_1MS_TOGGLE		(0x1<<13)
+#define OTGSC_STS_DATA_PULSING		(0x1<<14)
+#define OTGSC_INTSTS_USB_ID		(0x1<<16)
+#define OTGSC_INTSTS_A_VBUS_VALID	(0x1<<17)
+#define OTGSC_INTSTS_A_SESSION_VALID	(0x1<<18)
+#define OTGSC_INTSTS_B_SESSION_VALID	(0x1<<19)
+#define OTGSC_INTSTS_B_SESSION_END	(0x1<<20)
+#define OTGSC_INTSTS_1MS		(0x1<<21)
+#define OTGSC_INTSTS_DATA_PULSING	(0x1<<22)
+#define OTGSC_INTR_USB_ID_EN		(0x1<<24)
+#define OTGSC_INTR_A_VBUS_VALID_EN	(0x1<<25)
+#define OTGSC_INTR_A_SESSION_VALID_EN	(0x1<<26)
+#define OTGSC_INTR_B_SESSION_VALID_EN	(0x1<<27)
+#define OTGSC_INTR_B_SESSION_END_EN	(0x1<<28)
+#define OTGSC_INTR_1MS_TIMER_EN		(0x1<<29)
+#define OTGSC_INTR_DATA_PULSING_EN	(0x1<<30)
+#define OTGSC_INTSTS_MASK		(0x00ff0000)
+
+/* USB MODE Register Bit Masks */
+#define  USB_MODE_CTRL_MODE_IDLE	(0x0<<0)
+#define  USB_MODE_CTRL_MODE_DEVICE	(0x2<<0)
+#define  USB_MODE_CTRL_MODE_HOST	(0x3<<0)
+#define  USB_MODE_CTRL_MODE_RSV		(0x1<<0)
+#define  USB_MODE_SETUP_LOCK_OFF	(0x1<<3)
+#define  USB_MODE_STREAM_DISABLE	(0x1<<4)
+#define  USB_MODE_ES			(0x1<<2) /* Endian Select */
+
+/* control Register Bit Masks */
+#define  USB_CTRL_IOENB			(0x1<<2)
+#define  USB_CTRL_ULPI_INT0EN		(0x1<<0)
+
+/* BCSR5 */
+#define BCSR5_INT_USB			(0x02)
+
+/* USB module clk cfg */
+#define SCCR_OFFS			(0xA08)
+#define SCCR_USB_CLK_DISABLE		(0x00000000)	/* USB clk disable */
+#define SCCR_USB_MPHCM_11		(0x00c00000)
+#define SCCR_USB_MPHCM_01		(0x00400000)
+#define SCCR_USB_MPHCM_10		(0x00800000)
+#define SCCR_USB_DRCM_11		(0x00300000)
+#define SCCR_USB_DRCM_01		(0x00100000)
+#define SCCR_USB_DRCM_10		(0x00200000)
+
+#define SICRL_OFFS			(0x114)
+#define SICRL_USB0			(0x40000000)
+#define SICRL_USB1			(0x20000000)
+
+#define SICRH_OFFS			(0x118)
+#define SICRH_USB_UTMI			(0x00020000)
+
+/* OTG interrupt enable bit masks */
+#define  OTGSC_INTERRUPT_ENABLE_BITS_MASK  \
+	(OTGSC_INTR_USB_ID_EN            | \
+	OTGSC_INTR_1MS_TIMER_EN		 | \
+	OTGSC_INTR_A_VBUS_VALID_EN       | \
+	OTGSC_INTR_A_SESSION_VALID_EN    | \
+	OTGSC_INTR_B_SESSION_VALID_EN    | \
+	OTGSC_INTR_B_SESSION_END_EN      | \
+	OTGSC_INTR_DATA_PULSING_EN)
+
+/* OTG interrupt status bit masks */
+#define  OTGSC_INTERRUPT_STATUS_BITS_MASK  \
+	(OTGSC_INTSTS_USB_ID          |    \
+	OTGSC_INTR_1MS_TIMER_EN       |    \
+	OTGSC_INTSTS_A_VBUS_VALID     |    \
+	OTGSC_INTSTS_A_SESSION_VALID  |    \
+	OTGSC_INTSTS_B_SESSION_VALID  |    \
+	OTGSC_INTSTS_B_SESSION_END    |    \
+	OTGSC_INTSTS_DATA_PULSING)
+
+/*
+ *  A-DEVICE timing  constants
+ */
+
+/* Wait for VBUS Rise  */
+#define TA_WAIT_VRISE	(100)	/* a_wait_vrise 100 ms, section: 6.6.5.1 */
+
+/* Wait for B-Connect */
+#define TA_WAIT_BCON	(10000)  /* a_wait_bcon > 1 sec, section: 6.6.5.2
+				  * This is only used to get out of
+				  * OTG_STATE_A_WAIT_BCON state if there was
+				  * no connection for these many milliseconds
+				  */
+
+/* A-Idle to B-Disconnect */
+/* It is necessary for this timer to be more than 750 ms because of a bug in OPT
+ * test 5.4 in which B OPT disconnects after 750 ms instead of 75ms as stated
+ * in the test description
+ */
+#define TA_AIDL_BDIS	(5000)	/* a_suspend minimum 200 ms, section: 6.6.5.3 */
+
+/* B-Idle to A-Disconnect */
+#define TA_BIDL_ADIS	(12)	/* 3 to 200 ms */
+
+/* B-device timing constants */
+
+
+/* Data-Line Pulse Time*/
+#define TB_DATA_PLS	(10)	/* b_srp_init,continue 5~10ms, section:5.3.3 */
+#define TB_DATA_PLS_MIN	(5)	/* minimum 5 ms */
+#define TB_DATA_PLS_MAX	(10)	/* maximum 10 ms */
+
+/* SRP Initiate Time  */
+#define TB_SRP_INIT	(100)	/* b_srp_init,maximum 100 ms, section:5.3.8 */
+
+/* SRP Fail Time  */
+#define TB_SRP_FAIL	(7000)	/* b_srp_init,Fail time 5~30s, section:6.8.2.2*/
+
+/* SRP result wait time */
+#define TB_SRP_WAIT	(60)
+
+/* VBus time */
+#define TB_VBUS_PLS	(30)	/* time to keep vbus pulsing asserted */
+
+/* Discharge time */
+/* This time should be less than 10ms. It varies from system to system. */
+#define TB_VBUS_DSCHRG	(8)
+
+/* A-SE0 to B-Reset  */
+#define TB_ASE0_BRST	(20)	/* b_wait_acon, mini 3.125 ms,section:6.8.2.4 */
+
+/* A bus suspend timer before we can switch to b_wait_aconn */
+#define TB_A_SUSPEND	(7)
+#define TB_BUS_RESUME	(12)
+
+/* SE0 Time Before SRP */
+#define TB_SE0_SRP	(2)	/* b_idle,minimum 2 ms, section:5.3.2 */
+
+#define SET_OTG_STATE(otg_ptr, newstate)	((otg_ptr)->state = newstate)
+
+struct usb_dr_mmap {
+	/* Capability register */
+	u8 res1[256];
+	u16 caplength;		/* Capability Register Length */
+	u16 hciversion;		/* Host Controller Interface Version */
+	u32 hcsparams;		/* Host Controller Structual Parameters */
+	u32 hccparams;		/* Host Controller Capability Parameters */
+	u8 res2[20];
+	u32 dciversion;		/* Device Controller Interface Version */
+	u32 dccparams;		/* Device Controller Capability Parameters */
+	u8 res3[24];
+	/* Operation register */
+	u32 usbcmd;		/* USB Command Register */
+	u32 usbsts;		/* USB Status Register */
+	u32 usbintr;		/* USB Interrupt Enable Register */
+	u32 frindex;		/* Frame Index Register */
+	u8 res4[4];
+	u32 deviceaddr;		/* Device Address */
+	u32 endpointlistaddr;	/* Endpoint List Address Register */
+	u8 res5[4];
+	u32 burstsize;		/* Master Interface Data Burst Size Register */
+	u32 txttfilltuning;	/* Transmit FIFO Tuning Controls Register */
+	u8 res6[8];
+	u32 ulpiview;		/* ULPI register access */
+	u8 res7[12];
+	u32 configflag;		/* Configure Flag Register */
+	u32 portsc;		/* Port 1 Status and Control Register */
+	u8 res8[28];
+	u32 otgsc;		/* On-The-Go Status and Control */
+	u32 usbmode;		/* USB Mode Register */
+	u32 endptsetupstat;	/* Endpoint Setup Status Register */
+	u32 endpointprime;	/* Endpoint Initialization Register */
+	u32 endptflush;		/* Endpoint Flush Register */
+	u32 endptstatus;	/* Endpoint Status Register */
+	u32 endptcomplete;	/* Endpoint Complete Register */
+	u32 endptctrl[6];	/* Endpoint Control Registers */
+	u8 res9[552];
+	u32 snoop1;
+	u32 snoop2;
+	u32 age_cnt_thresh;	/* Age Count Threshold Register */
+	u32 pri_ctrl;		/* Priority Control Register */
+	u32 si_ctrl;		/* System Interface Control Register */
+	u8 res10[236];
+	u32 control;		/* General Purpose Control Register */
+};
+
+struct fsl_otg_timer {
+	unsigned long expires;	/* Number of count increase to timeout */
+	unsigned long count;	/* Tick counter */
+	void (*function)(unsigned long);	/* Timeout function */
+	unsigned long data;	/* Data passed to function */
+	struct list_head list;
+};
+
+inline struct fsl_otg_timer *otg_timer_initializer
+(void (*function)(unsigned long), unsigned long expires, unsigned long data)
+{
+	struct fsl_otg_timer *timer;
+
+	timer = kmalloc(sizeof(struct fsl_otg_timer), GFP_KERNEL);
+	if (!timer)
+		return NULL;
+	timer->function = function;
+	timer->expires = expires;
+	timer->data = data;
+	return timer;
+}
+
+struct fsl_otg {
+	struct usb_phy phy;
+	struct otg_fsm fsm;
+	struct usb_dr_mmap *dr_mem_map;
+	struct delayed_work otg_event;
+
+	/* used for usb host */
+	struct work_struct work_wq;
+	u8	host_working;
+
+	int irq;
+};
+
+struct fsl_otg_config {
+	u8 otg_port;
+};
+
+/* For SRP and HNP handle */
+#define FSL_OTG_MAJOR		240
+#define FSL_OTG_NAME		"fsl-usb2-otg"
+/* Command to OTG driver ioctl */
+#define OTG_IOCTL_MAGIC		FSL_OTG_MAJOR
+/* if otg work as host, it should return 1, otherwise return 0 */
+#define GET_OTG_STATUS		_IOR(OTG_IOCTL_MAGIC, 1, int)
+#define SET_A_SUSPEND_REQ	_IOW(OTG_IOCTL_MAGIC, 2, int)
+#define SET_A_BUS_DROP		_IOW(OTG_IOCTL_MAGIC, 3, int)
+#define SET_A_BUS_REQ		_IOW(OTG_IOCTL_MAGIC, 4, int)
+#define SET_B_BUS_REQ		_IOW(OTG_IOCTL_MAGIC, 5, int)
+#define GET_A_SUSPEND_REQ	_IOR(OTG_IOCTL_MAGIC, 6, int)
+#define GET_A_BUS_DROP		_IOR(OTG_IOCTL_MAGIC, 7, int)
+#define GET_A_BUS_REQ		_IOR(OTG_IOCTL_MAGIC, 8, int)
+#define GET_B_BUS_REQ		_IOR(OTG_IOCTL_MAGIC, 9, int)
+
+void fsl_otg_add_timer(void *timer);
+void fsl_otg_del_timer(void *timer);
+void fsl_otg_pulse_vbus(void);
diff --git a/drivers/usb/phy/phy-fsm-usb.c b/drivers/usb/phy/phy-fsm-usb.c
new file mode 100644
index 0000000..c520b35
--- /dev/null
+++ b/drivers/usb/phy/phy-fsm-usb.c
@@ -0,0 +1,348 @@
+/*
+ * OTG Finite State Machine from OTG spec
+ *
+ * Copyright (C) 2007,2008 Freescale Semiconductor, Inc.
+ *
+ * Author:	Li Yang <LeoLi@freescale.com>
+ *		Jerry Huang <Chang-Ming.Huang@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.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You 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/types.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/usb.h>
+#include <linux/usb/gadget.h>
+#include <linux/usb/otg.h>
+
+#include "phy-otg-fsm.h"
+
+/* Change USB protocol when there is a protocol change */
+static int otg_set_protocol(struct otg_fsm *fsm, int protocol)
+{
+	int ret = 0;
+
+	if (fsm->protocol != protocol) {
+		VDBG("Changing role fsm->protocol= %d; new protocol= %d\n",
+			fsm->protocol, protocol);
+		/* stop old protocol */
+		if (fsm->protocol == PROTO_HOST)
+			ret = fsm->ops->start_host(fsm, 0);
+		else if (fsm->protocol == PROTO_GADGET)
+			ret = fsm->ops->start_gadget(fsm, 0);
+		if (ret)
+			return ret;
+
+		/* start new protocol */
+		if (protocol == PROTO_HOST)
+			ret = fsm->ops->start_host(fsm, 1);
+		else if (protocol == PROTO_GADGET)
+			ret = fsm->ops->start_gadget(fsm, 1);
+		if (ret)
+			return ret;
+
+		fsm->protocol = protocol;
+		return 0;
+	}
+
+	return 0;
+}
+
+static int state_changed;
+
+/* Called when leaving a state.  Do state clean up jobs here */
+void otg_leave_state(struct otg_fsm *fsm, enum usb_otg_state old_state)
+{
+	switch (old_state) {
+	case OTG_STATE_B_IDLE:
+		otg_del_timer(fsm, b_se0_srp_tmr);
+		fsm->b_se0_srp = 0;
+		break;
+	case OTG_STATE_B_SRP_INIT:
+		fsm->b_srp_done = 0;
+		break;
+	case OTG_STATE_B_PERIPHERAL:
+		break;
+	case OTG_STATE_B_WAIT_ACON:
+		otg_del_timer(fsm, b_ase0_brst_tmr);
+		fsm->b_ase0_brst_tmout = 0;
+		break;
+	case OTG_STATE_B_HOST:
+		break;
+	case OTG_STATE_A_IDLE:
+		break;
+	case OTG_STATE_A_WAIT_VRISE:
+		otg_del_timer(fsm, a_wait_vrise_tmr);
+		fsm->a_wait_vrise_tmout = 0;
+		break;
+	case OTG_STATE_A_WAIT_BCON:
+		otg_del_timer(fsm, a_wait_bcon_tmr);
+		fsm->a_wait_bcon_tmout = 0;
+		break;
+	case OTG_STATE_A_HOST:
+		otg_del_timer(fsm, a_wait_enum_tmr);
+		break;
+	case OTG_STATE_A_SUSPEND:
+		otg_del_timer(fsm, a_aidl_bdis_tmr);
+		fsm->a_aidl_bdis_tmout = 0;
+		fsm->a_suspend_req = 0;
+		break;
+	case OTG_STATE_A_PERIPHERAL:
+		break;
+	case OTG_STATE_A_WAIT_VFALL:
+		otg_del_timer(fsm, a_wait_vrise_tmr);
+		break;
+	case OTG_STATE_A_VBUS_ERR:
+		break;
+	default:
+		break;
+	}
+}
+
+/* Called when entering a state */
+int otg_set_state(struct otg_fsm *fsm, enum usb_otg_state new_state)
+{
+	state_changed = 1;
+	if (fsm->otg->phy->state == new_state)
+		return 0;
+	VDBG("Set state: %s\n", usb_otg_state_string(new_state));
+	otg_leave_state(fsm, fsm->otg->phy->state);
+	switch (new_state) {
+	case OTG_STATE_B_IDLE:
+		otg_drv_vbus(fsm, 0);
+		otg_chrg_vbus(fsm, 0);
+		otg_loc_conn(fsm, 0);
+		otg_loc_sof(fsm, 0);
+		otg_set_protocol(fsm, PROTO_UNDEF);
+		otg_add_timer(fsm, b_se0_srp_tmr);
+		break;
+	case OTG_STATE_B_SRP_INIT:
+		otg_start_pulse(fsm);
+		otg_loc_sof(fsm, 0);
+		otg_set_protocol(fsm, PROTO_UNDEF);
+		otg_add_timer(fsm, b_srp_fail_tmr);
+		break;
+	case OTG_STATE_B_PERIPHERAL:
+		otg_chrg_vbus(fsm, 0);
+		otg_loc_conn(fsm, 1);
+		otg_loc_sof(fsm, 0);
+		otg_set_protocol(fsm, PROTO_GADGET);
+		break;
+	case OTG_STATE_B_WAIT_ACON:
+		otg_chrg_vbus(fsm, 0);
+		otg_loc_conn(fsm, 0);
+		otg_loc_sof(fsm, 0);
+		otg_set_protocol(fsm, PROTO_HOST);
+		otg_add_timer(fsm, b_ase0_brst_tmr);
+		fsm->a_bus_suspend = 0;
+		break;
+	case OTG_STATE_B_HOST:
+		otg_chrg_vbus(fsm, 0);
+		otg_loc_conn(fsm, 0);
+		otg_loc_sof(fsm, 1);
+		otg_set_protocol(fsm, PROTO_HOST);
+		usb_bus_start_enum(fsm->otg->host,
+				fsm->otg->host->otg_port);
+		break;
+	case OTG_STATE_A_IDLE:
+		otg_drv_vbus(fsm, 0);
+		otg_chrg_vbus(fsm, 0);
+		otg_loc_conn(fsm, 0);
+		otg_loc_sof(fsm, 0);
+		otg_set_protocol(fsm, PROTO_HOST);
+		break;
+	case OTG_STATE_A_WAIT_VRISE:
+		otg_drv_vbus(fsm, 1);
+		otg_loc_conn(fsm, 0);
+		otg_loc_sof(fsm, 0);
+		otg_set_protocol(fsm, PROTO_HOST);
+		otg_add_timer(fsm, a_wait_vrise_tmr);
+		break;
+	case OTG_STATE_A_WAIT_BCON:
+		otg_drv_vbus(fsm, 1);
+		otg_loc_conn(fsm, 0);
+		otg_loc_sof(fsm, 0);
+		otg_set_protocol(fsm, PROTO_HOST);
+		otg_add_timer(fsm, a_wait_bcon_tmr);
+		break;
+	case OTG_STATE_A_HOST:
+		otg_drv_vbus(fsm, 1);
+		otg_loc_conn(fsm, 0);
+		otg_loc_sof(fsm, 1);
+		otg_set_protocol(fsm, PROTO_HOST);
+		/*
+		 * When HNP is triggered while a_bus_req = 0, a_host will
+		 * suspend too fast to complete a_set_b_hnp_en
+		 */
+		if (!fsm->a_bus_req || fsm->a_suspend_req)
+			otg_add_timer(fsm, a_wait_enum_tmr);
+		break;
+	case OTG_STATE_A_SUSPEND:
+		otg_drv_vbus(fsm, 1);
+		otg_loc_conn(fsm, 0);
+		otg_loc_sof(fsm, 0);
+		otg_set_protocol(fsm, PROTO_HOST);
+		otg_add_timer(fsm, a_aidl_bdis_tmr);
+
+		break;
+	case OTG_STATE_A_PERIPHERAL:
+		otg_loc_conn(fsm, 1);
+		otg_loc_sof(fsm, 0);
+		otg_set_protocol(fsm, PROTO_GADGET);
+		otg_drv_vbus(fsm, 1);
+		break;
+	case OTG_STATE_A_WAIT_VFALL:
+		otg_drv_vbus(fsm, 0);
+		otg_loc_conn(fsm, 0);
+		otg_loc_sof(fsm, 0);
+		otg_set_protocol(fsm, PROTO_HOST);
+		break;
+	case OTG_STATE_A_VBUS_ERR:
+		otg_drv_vbus(fsm, 0);
+		otg_loc_conn(fsm, 0);
+		otg_loc_sof(fsm, 0);
+		otg_set_protocol(fsm, PROTO_UNDEF);
+		break;
+	default:
+		break;
+	}
+
+	fsm->otg->phy->state = new_state;
+	return 0;
+}
+
+/* State change judgement */
+int otg_statemachine(struct otg_fsm *fsm)
+{
+	enum usb_otg_state state;
+	unsigned long flags;
+
+	spin_lock_irqsave(&fsm->lock, flags);
+
+	state = fsm->otg->phy->state;
+	state_changed = 0;
+	/* State machine state change judgement */
+
+	switch (state) {
+	case OTG_STATE_UNDEFINED:
+		VDBG("fsm->id = %d\n", fsm->id);
+		if (fsm->id)
+			otg_set_state(fsm, OTG_STATE_B_IDLE);
+		else
+			otg_set_state(fsm, OTG_STATE_A_IDLE);
+		break;
+	case OTG_STATE_B_IDLE:
+		if (!fsm->id)
+			otg_set_state(fsm, OTG_STATE_A_IDLE);
+		else if (fsm->b_sess_vld && fsm->otg->gadget)
+			otg_set_state(fsm, OTG_STATE_B_PERIPHERAL);
+		else if (fsm->b_bus_req && fsm->b_sess_end && fsm->b_se0_srp)
+			otg_set_state(fsm, OTG_STATE_B_SRP_INIT);
+		break;
+	case OTG_STATE_B_SRP_INIT:
+		if (!fsm->id || fsm->b_srp_done)
+			otg_set_state(fsm, OTG_STATE_B_IDLE);
+		break;
+	case OTG_STATE_B_PERIPHERAL:
+		if (!fsm->id || !fsm->b_sess_vld)
+			otg_set_state(fsm, OTG_STATE_B_IDLE);
+		else if (fsm->b_bus_req && fsm->otg->
+				gadget->b_hnp_enable && fsm->a_bus_suspend)
+			otg_set_state(fsm, OTG_STATE_B_WAIT_ACON);
+		break;
+	case OTG_STATE_B_WAIT_ACON:
+		if (fsm->a_conn)
+			otg_set_state(fsm, OTG_STATE_B_HOST);
+		else if (!fsm->id || !fsm->b_sess_vld)
+			otg_set_state(fsm, OTG_STATE_B_IDLE);
+		else if (fsm->a_bus_resume || fsm->b_ase0_brst_tmout) {
+			fsm->b_ase0_brst_tmout = 0;
+			otg_set_state(fsm, OTG_STATE_B_PERIPHERAL);
+		}
+		break;
+	case OTG_STATE_B_HOST:
+		if (!fsm->id || !fsm->b_sess_vld)
+			otg_set_state(fsm, OTG_STATE_B_IDLE);
+		else if (!fsm->b_bus_req || !fsm->a_conn)
+			otg_set_state(fsm, OTG_STATE_B_PERIPHERAL);
+		break;
+	case OTG_STATE_A_IDLE:
+		if (fsm->id)
+			otg_set_state(fsm, OTG_STATE_B_IDLE);
+		else if (!fsm->a_bus_drop && (fsm->a_bus_req || fsm->a_srp_det))
+			otg_set_state(fsm, OTG_STATE_A_WAIT_VRISE);
+		break;
+	case OTG_STATE_A_WAIT_VRISE:
+		if (fsm->id || fsm->a_bus_drop || fsm->a_vbus_vld ||
+				fsm->a_wait_vrise_tmout) {
+			otg_set_state(fsm, OTG_STATE_A_WAIT_BCON);
+		}
+		break;
+	case OTG_STATE_A_WAIT_BCON:
+		if (!fsm->a_vbus_vld)
+			otg_set_state(fsm, OTG_STATE_A_VBUS_ERR);
+		else if (fsm->b_conn)
+			otg_set_state(fsm, OTG_STATE_A_HOST);
+		else if (fsm->id | fsm->a_bus_drop | fsm->a_wait_bcon_tmout)
+			otg_set_state(fsm, OTG_STATE_A_WAIT_VFALL);
+		break;
+	case OTG_STATE_A_HOST:
+		if ((!fsm->a_bus_req || fsm->a_suspend_req) &&
+				fsm->otg->host->b_hnp_enable)
+			otg_set_state(fsm, OTG_STATE_A_SUSPEND);
+		else if (fsm->id || !fsm->b_conn || fsm->a_bus_drop)
+			otg_set_state(fsm, OTG_STATE_A_WAIT_BCON);
+		else if (!fsm->a_vbus_vld)
+			otg_set_state(fsm, OTG_STATE_A_VBUS_ERR);
+		break;
+	case OTG_STATE_A_SUSPEND:
+		if (!fsm->b_conn && fsm->otg->host->b_hnp_enable)
+			otg_set_state(fsm, OTG_STATE_A_PERIPHERAL);
+		else if (!fsm->b_conn && !fsm->otg->host->b_hnp_enable)
+			otg_set_state(fsm, OTG_STATE_A_WAIT_BCON);
+		else if (fsm->a_bus_req || fsm->b_bus_resume)
+			otg_set_state(fsm, OTG_STATE_A_HOST);
+		else if (fsm->id || fsm->a_bus_drop || fsm->a_aidl_bdis_tmout)
+			otg_set_state(fsm, OTG_STATE_A_WAIT_VFALL);
+		else if (!fsm->a_vbus_vld)
+			otg_set_state(fsm, OTG_STATE_A_VBUS_ERR);
+		break;
+	case OTG_STATE_A_PERIPHERAL:
+		if (fsm->id || fsm->a_bus_drop)
+			otg_set_state(fsm, OTG_STATE_A_WAIT_VFALL);
+		else if (fsm->b_bus_suspend)
+			otg_set_state(fsm, OTG_STATE_A_WAIT_BCON);
+		else if (!fsm->a_vbus_vld)
+			otg_set_state(fsm, OTG_STATE_A_VBUS_ERR);
+		break;
+	case OTG_STATE_A_WAIT_VFALL:
+		if (fsm->id || fsm->a_bus_req || (!fsm->a_sess_vld &&
+					!fsm->b_conn))
+			otg_set_state(fsm, OTG_STATE_A_IDLE);
+		break;
+	case OTG_STATE_A_VBUS_ERR:
+		if (fsm->id || fsm->a_bus_drop || fsm->a_clr_err)
+			otg_set_state(fsm, OTG_STATE_A_WAIT_VFALL);
+		break;
+	default:
+		break;
+	}
+	spin_unlock_irqrestore(&fsm->lock, flags);
+
+	VDBG("quit statemachine, changed = %d\n", state_changed);
+	return state_changed;
+}
diff --git a/drivers/usb/phy/phy-fsm-usb.h b/drivers/usb/phy/phy-fsm-usb.h
new file mode 100644
index 0000000..c30a2e1
--- /dev/null
+++ b/drivers/usb/phy/phy-fsm-usb.h
@@ -0,0 +1,154 @@
+/* Copyright (C) 2007,2008 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.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You 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.
+ */
+
+#undef DEBUG
+#undef VERBOSE
+
+#ifdef DEBUG
+#define DBG(fmt, args...) printk(KERN_DEBUG "[%s]  " fmt , \
+				 __func__, ## args)
+#else
+#define DBG(fmt, args...)	do {} while (0)
+#endif
+
+#ifdef VERBOSE
+#define VDBG		DBG
+#else
+#define VDBG(stuff...)	do {} while (0)
+#endif
+
+#ifdef VERBOSE
+#define MPC_LOC printk("Current Location [%s]:[%d]\n", __FILE__, __LINE__)
+#else
+#define MPC_LOC do {} while (0)
+#endif
+
+#define PROTO_UNDEF	(0)
+#define PROTO_HOST	(1)
+#define PROTO_GADGET	(2)
+
+/* OTG state machine according to the OTG spec */
+struct otg_fsm {
+	/* Input */
+	int a_bus_resume;
+	int a_bus_suspend;
+	int a_conn;
+	int a_sess_vld;
+	int a_srp_det;
+	int a_vbus_vld;
+	int b_bus_resume;
+	int b_bus_suspend;
+	int b_conn;
+	int b_se0_srp;
+	int b_sess_end;
+	int b_sess_vld;
+	int id;
+
+	/* Internal variables */
+	int a_set_b_hnp_en;
+	int b_srp_done;
+	int b_hnp_enable;
+
+	/* Timeout indicator for timers */
+	int a_wait_vrise_tmout;
+	int a_wait_bcon_tmout;
+	int a_aidl_bdis_tmout;
+	int b_ase0_brst_tmout;
+
+	/* Informative variables */
+	int a_bus_drop;
+	int a_bus_req;
+	int a_clr_err;
+	int a_suspend_req;
+	int b_bus_req;
+
+	/* Output */
+	int drv_vbus;
+	int loc_conn;
+	int loc_sof;
+
+	struct otg_fsm_ops *ops;
+	struct usb_otg *otg;
+
+	/* Current usb protocol used: 0:undefine; 1:host; 2:client */
+	int protocol;
+	spinlock_t lock;
+};
+
+struct otg_fsm_ops {
+	void	(*chrg_vbus)(int on);
+	void	(*drv_vbus)(int on);
+	void	(*loc_conn)(int on);
+	void	(*loc_sof)(int on);
+	void	(*start_pulse)(void);
+	void	(*add_timer)(void *timer);
+	void	(*del_timer)(void *timer);
+	int	(*start_host)(struct otg_fsm *fsm, int on);
+	int	(*start_gadget)(struct otg_fsm *fsm, int on);
+};
+
+
+static inline void otg_chrg_vbus(struct otg_fsm *fsm, int on)
+{
+	fsm->ops->chrg_vbus(on);
+}
+
+static inline void otg_drv_vbus(struct otg_fsm *fsm, int on)
+{
+	if (fsm->drv_vbus != on) {
+		fsm->drv_vbus = on;
+		fsm->ops->drv_vbus(on);
+	}
+}
+
+static inline void otg_loc_conn(struct otg_fsm *fsm, int on)
+{
+	if (fsm->loc_conn != on) {
+		fsm->loc_conn = on;
+		fsm->ops->loc_conn(on);
+	}
+}
+
+static inline void otg_loc_sof(struct otg_fsm *fsm, int on)
+{
+	if (fsm->loc_sof != on) {
+		fsm->loc_sof = on;
+		fsm->ops->loc_sof(on);
+	}
+}
+
+static inline void otg_start_pulse(struct otg_fsm *fsm)
+{
+	fsm->ops->start_pulse();
+}
+
+static inline void otg_add_timer(struct otg_fsm *fsm, void *timer)
+{
+	fsm->ops->add_timer(timer);
+}
+
+static inline void otg_del_timer(struct otg_fsm *fsm, void *timer)
+{
+	fsm->ops->del_timer(timer);
+}
+
+int otg_statemachine(struct otg_fsm *fsm);
+
+/* Defined by device specific driver, for different timer implementation */
+extern struct fsl_otg_timer *a_wait_vrise_tmr, *a_wait_bcon_tmr,
+	*a_aidl_bdis_tmr, *b_ase0_brst_tmr, *b_se0_srp_tmr, *b_srp_fail_tmr,
+	*a_wait_enum_tmr;
diff --git a/drivers/usb/phy/phy-gpio-vbus-usb.c b/drivers/usb/phy/phy-gpio-vbus-usb.c
new file mode 100644
index 0000000..4c76074
--- /dev/null
+++ b/drivers/usb/phy/phy-gpio-vbus-usb.c
@@ -0,0 +1,421 @@
+/*
+ * gpio-vbus.c - simple GPIO VBUS sensing driver for B peripheral devices
+ *
+ * Copyright (c) 2008 Philipp Zabel <philipp.zabel@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/usb.h>
+#include <linux/workqueue.h>
+
+#include <linux/regulator/consumer.h>
+
+#include <linux/usb/gadget.h>
+#include <linux/usb/gpio_vbus.h>
+#include <linux/usb/otg.h>
+
+
+/*
+ * A simple GPIO VBUS sensing driver for B peripheral only devices
+ * with internal transceivers. It can control a D+ pullup GPIO and
+ * a regulator to limit the current drawn from VBUS.
+ *
+ * Needs to be loaded before the UDC driver that will use it.
+ */
+struct gpio_vbus_data {
+	struct usb_phy		phy;
+	struct device          *dev;
+	struct regulator       *vbus_draw;
+	int			vbus_draw_enabled;
+	unsigned		mA;
+	struct delayed_work	work;
+	int			vbus;
+	int			irq;
+};
+
+
+/*
+ * This driver relies on "both edges" triggering.  VBUS has 100 msec to
+ * stabilize, so the peripheral controller driver may need to cope with
+ * some bouncing due to current surges (e.g. charging local capacitance)
+ * and contact chatter.
+ *
+ * REVISIT in desperate straits, toggling between rising and falling
+ * edges might be workable.
+ */
+#define VBUS_IRQ_FLAGS \
+	(IRQF_SHARED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)
+
+
+/* interface to regulator framework */
+static void set_vbus_draw(struct gpio_vbus_data *gpio_vbus, unsigned mA)
+{
+	struct regulator *vbus_draw = gpio_vbus->vbus_draw;
+	int enabled;
+	int ret;
+
+	if (!vbus_draw)
+		return;
+
+	enabled = gpio_vbus->vbus_draw_enabled;
+	if (mA) {
+		regulator_set_current_limit(vbus_draw, 0, 1000 * mA);
+		if (!enabled) {
+			ret = regulator_enable(vbus_draw);
+			if (ret < 0)
+				return;
+			gpio_vbus->vbus_draw_enabled = 1;
+		}
+	} else {
+		if (enabled) {
+			ret = regulator_disable(vbus_draw);
+			if (ret < 0)
+				return;
+			gpio_vbus->vbus_draw_enabled = 0;
+		}
+	}
+	gpio_vbus->mA = mA;
+}
+
+static int is_vbus_powered(struct gpio_vbus_mach_info *pdata)
+{
+	int vbus;
+
+	vbus = gpio_get_value(pdata->gpio_vbus);
+	if (pdata->gpio_vbus_inverted)
+		vbus = !vbus;
+
+	return vbus;
+}
+
+static void gpio_vbus_work(struct work_struct *work)
+{
+	struct gpio_vbus_data *gpio_vbus =
+		container_of(work, struct gpio_vbus_data, work.work);
+	struct gpio_vbus_mach_info *pdata = gpio_vbus->dev->platform_data;
+	int gpio, status, vbus;
+
+	if (!gpio_vbus->phy.otg->gadget)
+		return;
+
+	vbus = is_vbus_powered(pdata);
+	if ((vbus ^ gpio_vbus->vbus) == 0)
+		return;
+	gpio_vbus->vbus = vbus;
+
+	/* Peripheral controllers which manage the pullup themselves won't have
+	 * gpio_pullup configured here.  If it's configured here, we'll do what
+	 * isp1301_omap::b_peripheral() does and enable the pullup here... although
+	 * that may complicate usb_gadget_{,dis}connect() support.
+	 */
+	gpio = pdata->gpio_pullup;
+
+	if (vbus) {
+		status = USB_EVENT_VBUS;
+		gpio_vbus->phy.state = OTG_STATE_B_PERIPHERAL;
+		gpio_vbus->phy.last_event = status;
+		usb_gadget_vbus_connect(gpio_vbus->phy.otg->gadget);
+
+		/* drawing a "unit load" is *always* OK, except for OTG */
+		set_vbus_draw(gpio_vbus, 100);
+
+		/* optionally enable D+ pullup */
+		if (gpio_is_valid(gpio))
+			gpio_set_value(gpio, !pdata->gpio_pullup_inverted);
+
+		atomic_notifier_call_chain(&gpio_vbus->phy.notifier,
+					   status, gpio_vbus->phy.otg->gadget);
+	} else {
+		/* optionally disable D+ pullup */
+		if (gpio_is_valid(gpio))
+			gpio_set_value(gpio, pdata->gpio_pullup_inverted);
+
+		set_vbus_draw(gpio_vbus, 0);
+
+		usb_gadget_vbus_disconnect(gpio_vbus->phy.otg->gadget);
+		status = USB_EVENT_NONE;
+		gpio_vbus->phy.state = OTG_STATE_B_IDLE;
+		gpio_vbus->phy.last_event = status;
+
+		atomic_notifier_call_chain(&gpio_vbus->phy.notifier,
+					   status, gpio_vbus->phy.otg->gadget);
+	}
+}
+
+/* VBUS change IRQ handler */
+static irqreturn_t gpio_vbus_irq(int irq, void *data)
+{
+	struct platform_device *pdev = data;
+	struct gpio_vbus_mach_info *pdata = pdev->dev.platform_data;
+	struct gpio_vbus_data *gpio_vbus = platform_get_drvdata(pdev);
+	struct usb_otg *otg = gpio_vbus->phy.otg;
+
+	dev_dbg(&pdev->dev, "VBUS %s (gadget: %s)\n",
+		is_vbus_powered(pdata) ? "supplied" : "inactive",
+		otg->gadget ? otg->gadget->name : "none");
+
+	if (otg->gadget)
+		schedule_delayed_work(&gpio_vbus->work, msecs_to_jiffies(100));
+
+	return IRQ_HANDLED;
+}
+
+/* OTG transceiver interface */
+
+/* bind/unbind the peripheral controller */
+static int gpio_vbus_set_peripheral(struct usb_otg *otg,
+					struct usb_gadget *gadget)
+{
+	struct gpio_vbus_data *gpio_vbus;
+	struct gpio_vbus_mach_info *pdata;
+	struct platform_device *pdev;
+	int gpio;
+
+	gpio_vbus = container_of(otg->phy, struct gpio_vbus_data, phy);
+	pdev = to_platform_device(gpio_vbus->dev);
+	pdata = gpio_vbus->dev->platform_data;
+	gpio = pdata->gpio_pullup;
+
+	if (!gadget) {
+		dev_dbg(&pdev->dev, "unregistering gadget '%s'\n",
+			otg->gadget->name);
+
+		/* optionally disable D+ pullup */
+		if (gpio_is_valid(gpio))
+			gpio_set_value(gpio, pdata->gpio_pullup_inverted);
+
+		set_vbus_draw(gpio_vbus, 0);
+
+		usb_gadget_vbus_disconnect(otg->gadget);
+		otg->phy->state = OTG_STATE_UNDEFINED;
+
+		otg->gadget = NULL;
+		return 0;
+	}
+
+	otg->gadget = gadget;
+	dev_dbg(&pdev->dev, "registered gadget '%s'\n", gadget->name);
+
+	/* initialize connection state */
+	gpio_vbus->vbus = 0; /* start with disconnected */
+	gpio_vbus_irq(gpio_vbus->irq, pdev);
+	return 0;
+}
+
+/* effective for B devices, ignored for A-peripheral */
+static int gpio_vbus_set_power(struct usb_phy *phy, unsigned mA)
+{
+	struct gpio_vbus_data *gpio_vbus;
+
+	gpio_vbus = container_of(phy, struct gpio_vbus_data, phy);
+
+	if (phy->state == OTG_STATE_B_PERIPHERAL)
+		set_vbus_draw(gpio_vbus, mA);
+	return 0;
+}
+
+/* for non-OTG B devices: set/clear transceiver suspend mode */
+static int gpio_vbus_set_suspend(struct usb_phy *phy, int suspend)
+{
+	struct gpio_vbus_data *gpio_vbus;
+
+	gpio_vbus = container_of(phy, struct gpio_vbus_data, phy);
+
+	/* draw max 0 mA from vbus in suspend mode; or the previously
+	 * recorded amount of current if not suspended
+	 *
+	 * NOTE: high powered configs (mA > 100) may draw up to 2.5 mA
+	 * if they're wake-enabled ... we don't handle that yet.
+	 */
+	return gpio_vbus_set_power(phy, suspend ? 0 : gpio_vbus->mA);
+}
+
+/* platform driver interface */
+
+static int __init gpio_vbus_probe(struct platform_device *pdev)
+{
+	struct gpio_vbus_mach_info *pdata = pdev->dev.platform_data;
+	struct gpio_vbus_data *gpio_vbus;
+	struct resource *res;
+	int err, gpio, irq;
+	unsigned long irqflags;
+
+	if (!pdata || !gpio_is_valid(pdata->gpio_vbus))
+		return -EINVAL;
+	gpio = pdata->gpio_vbus;
+
+	gpio_vbus = kzalloc(sizeof(struct gpio_vbus_data), GFP_KERNEL);
+	if (!gpio_vbus)
+		return -ENOMEM;
+
+	gpio_vbus->phy.otg = kzalloc(sizeof(struct usb_otg), GFP_KERNEL);
+	if (!gpio_vbus->phy.otg) {
+		kfree(gpio_vbus);
+		return -ENOMEM;
+	}
+
+	platform_set_drvdata(pdev, gpio_vbus);
+	gpio_vbus->dev = &pdev->dev;
+	gpio_vbus->phy.label = "gpio-vbus";
+	gpio_vbus->phy.set_power = gpio_vbus_set_power;
+	gpio_vbus->phy.set_suspend = gpio_vbus_set_suspend;
+	gpio_vbus->phy.state = OTG_STATE_UNDEFINED;
+
+	gpio_vbus->phy.otg->phy = &gpio_vbus->phy;
+	gpio_vbus->phy.otg->set_peripheral = gpio_vbus_set_peripheral;
+
+	err = gpio_request(gpio, "vbus_detect");
+	if (err) {
+		dev_err(&pdev->dev, "can't request vbus gpio %d, err: %d\n",
+			gpio, err);
+		goto err_gpio;
+	}
+	gpio_direction_input(gpio);
+
+	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (res) {
+		irq = res->start;
+		irqflags = (res->flags & IRQF_TRIGGER_MASK) | IRQF_SHARED;
+	} else {
+		irq = gpio_to_irq(gpio);
+		irqflags = VBUS_IRQ_FLAGS;
+	}
+
+	gpio_vbus->irq = irq;
+
+	/* if data line pullup is in use, initialize it to "not pulling up" */
+	gpio = pdata->gpio_pullup;
+	if (gpio_is_valid(gpio)) {
+		err = gpio_request(gpio, "udc_pullup");
+		if (err) {
+			dev_err(&pdev->dev,
+				"can't request pullup gpio %d, err: %d\n",
+				gpio, err);
+			gpio_free(pdata->gpio_vbus);
+			goto err_gpio;
+		}
+		gpio_direction_output(gpio, pdata->gpio_pullup_inverted);
+	}
+
+	err = request_irq(irq, gpio_vbus_irq, irqflags, "vbus_detect", pdev);
+	if (err) {
+		dev_err(&pdev->dev, "can't request irq %i, err: %d\n",
+			irq, err);
+		goto err_irq;
+	}
+
+	ATOMIC_INIT_NOTIFIER_HEAD(&gpio_vbus->phy.notifier);
+
+	INIT_DELAYED_WORK(&gpio_vbus->work, gpio_vbus_work);
+
+	gpio_vbus->vbus_draw = regulator_get(&pdev->dev, "vbus_draw");
+	if (IS_ERR(gpio_vbus->vbus_draw)) {
+		dev_dbg(&pdev->dev, "can't get vbus_draw regulator, err: %ld\n",
+			PTR_ERR(gpio_vbus->vbus_draw));
+		gpio_vbus->vbus_draw = NULL;
+	}
+
+	/* only active when a gadget is registered */
+	err = usb_add_phy(&gpio_vbus->phy, USB_PHY_TYPE_USB2);
+	if (err) {
+		dev_err(&pdev->dev, "can't register transceiver, err: %d\n",
+			err);
+		goto err_otg;
+	}
+
+	device_init_wakeup(&pdev->dev, pdata->wakeup);
+
+	return 0;
+err_otg:
+	regulator_put(gpio_vbus->vbus_draw);
+	free_irq(irq, pdev);
+err_irq:
+	if (gpio_is_valid(pdata->gpio_pullup))
+		gpio_free(pdata->gpio_pullup);
+	gpio_free(pdata->gpio_vbus);
+err_gpio:
+	platform_set_drvdata(pdev, NULL);
+	kfree(gpio_vbus->phy.otg);
+	kfree(gpio_vbus);
+	return err;
+}
+
+static int __exit gpio_vbus_remove(struct platform_device *pdev)
+{
+	struct gpio_vbus_data *gpio_vbus = platform_get_drvdata(pdev);
+	struct gpio_vbus_mach_info *pdata = pdev->dev.platform_data;
+	int gpio = pdata->gpio_vbus;
+
+	device_init_wakeup(&pdev->dev, 0);
+	cancel_delayed_work_sync(&gpio_vbus->work);
+	regulator_put(gpio_vbus->vbus_draw);
+
+	usb_remove_phy(&gpio_vbus->phy);
+
+	free_irq(gpio_vbus->irq, pdev);
+	if (gpio_is_valid(pdata->gpio_pullup))
+		gpio_free(pdata->gpio_pullup);
+	gpio_free(gpio);
+	platform_set_drvdata(pdev, NULL);
+	kfree(gpio_vbus->phy.otg);
+	kfree(gpio_vbus);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int gpio_vbus_pm_suspend(struct device *dev)
+{
+	struct gpio_vbus_data *gpio_vbus = dev_get_drvdata(dev);
+
+	if (device_may_wakeup(dev))
+		enable_irq_wake(gpio_vbus->irq);
+
+	return 0;
+}
+
+static int gpio_vbus_pm_resume(struct device *dev)
+{
+	struct gpio_vbus_data *gpio_vbus = dev_get_drvdata(dev);
+
+	if (device_may_wakeup(dev))
+		disable_irq_wake(gpio_vbus->irq);
+
+	return 0;
+}
+
+static const struct dev_pm_ops gpio_vbus_dev_pm_ops = {
+	.suspend	= gpio_vbus_pm_suspend,
+	.resume		= gpio_vbus_pm_resume,
+};
+#endif
+
+/* NOTE:  the gpio-vbus device may *NOT* be hotplugged */
+
+MODULE_ALIAS("platform:gpio-vbus");
+
+static struct platform_driver gpio_vbus_driver = {
+	.driver = {
+		.name  = "gpio-vbus",
+		.owner = THIS_MODULE,
+#ifdef CONFIG_PM
+		.pm = &gpio_vbus_dev_pm_ops,
+#endif
+	},
+	.remove  = __exit_p(gpio_vbus_remove),
+};
+
+module_platform_driver_probe(gpio_vbus_driver, gpio_vbus_probe);
+
+MODULE_DESCRIPTION("simple GPIO controlled OTG transceiver driver");
+MODULE_AUTHOR("Philipp Zabel");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/phy/phy-isp1301-omap.c b/drivers/usb/phy/phy-isp1301-omap.c
new file mode 100644
index 0000000..ae481af
--- /dev/null
+++ b/drivers/usb/phy/phy-isp1301-omap.c
@@ -0,0 +1,1656 @@
+/*
+ * isp1301_omap - ISP 1301 USB transceiver, talking to OMAP OTG controller
+ *
+ * Copyright (C) 2004 Texas Instruments
+ * Copyright (C) 2004 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/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <linux/usb.h>
+#include <linux/usb/otg.h>
+#include <linux/i2c.h>
+#include <linux/workqueue.h>
+
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+
+#include <mach/mux.h>
+
+#include <mach/usb.h>
+
+#ifndef	DEBUG
+#undef	VERBOSE
+#endif
+
+
+#define	DRIVER_VERSION	"24 August 2004"
+#define	DRIVER_NAME	(isp1301_driver.driver.name)
+
+MODULE_DESCRIPTION("ISP1301 USB OTG Transceiver Driver");
+MODULE_LICENSE("GPL");
+
+struct isp1301 {
+	struct usb_phy		phy;
+	struct i2c_client	*client;
+	void			(*i2c_release)(struct device *dev);
+
+	int			irq_type;
+
+	u32			last_otg_ctrl;
+	unsigned		working:1;
+
+	struct timer_list	timer;
+
+	/* use keventd context to change the state for us */
+	struct work_struct	work;
+
+	unsigned long		todo;
+#		define WORK_UPDATE_ISP	0	/* update ISP from OTG */
+#		define WORK_UPDATE_OTG	1	/* update OTG from ISP */
+#		define WORK_HOST_RESUME	4	/* resume host */
+#		define WORK_TIMER	6	/* timer fired */
+#		define WORK_STOP	7	/* don't resubmit */
+};
+
+
+/* bits in OTG_CTRL */
+
+#define	OTG_XCEIV_OUTPUTS \
+	(OTG_ASESSVLD|OTG_BSESSEND|OTG_BSESSVLD|OTG_VBUSVLD|OTG_ID)
+#define	OTG_XCEIV_INPUTS \
+	(OTG_PULLDOWN|OTG_PULLUP|OTG_DRV_VBUS|OTG_PD_VBUS|OTG_PU_VBUS|OTG_PU_ID)
+#define	OTG_CTRL_BITS \
+	(OTG_A_BUSREQ|OTG_A_SETB_HNPEN|OTG_B_BUSREQ|OTG_B_HNPEN|OTG_BUSDROP)
+	/* and OTG_PULLUP is sometimes written */
+
+#define	OTG_CTRL_MASK	(OTG_DRIVER_SEL| \
+	OTG_XCEIV_OUTPUTS|OTG_XCEIV_INPUTS| \
+	OTG_CTRL_BITS)
+
+
+/*-------------------------------------------------------------------------*/
+
+/* board-specific PM hooks */
+
+#if defined(CONFIG_MACH_OMAP_H2) || defined(CONFIG_MACH_OMAP_H3)
+
+#if	defined(CONFIG_TPS65010) || defined(CONFIG_TPS65010_MODULE)
+
+#include <linux/i2c/tps65010.h>
+
+#else
+
+static inline int tps65010_set_vbus_draw(unsigned mA)
+{
+	pr_debug("tps65010: draw %d mA (STUB)\n", mA);
+	return 0;
+}
+
+#endif
+
+static void enable_vbus_draw(struct isp1301 *isp, unsigned mA)
+{
+	int status = tps65010_set_vbus_draw(mA);
+	if (status < 0)
+		pr_debug("  VBUS %d mA error %d\n", mA, status);
+}
+
+#else
+
+static void enable_vbus_draw(struct isp1301 *isp, unsigned mA)
+{
+	/* H4 controls this by DIP switch S2.4; no soft control.
+	 * ON means the charger is always enabled.  Leave it OFF
+	 * unless the OTG port is used only in B-peripheral mode.
+	 */
+}
+
+#endif
+
+static void enable_vbus_source(struct isp1301 *isp)
+{
+	/* this board won't supply more than 8mA vbus power.
+	 * some boards can switch a 100ma "unit load" (or more).
+	 */
+}
+
+
+/* products will deliver OTG messages with LEDs, GUI, etc */
+static inline void notresponding(struct isp1301 *isp)
+{
+	printk(KERN_NOTICE "OTG device not responding.\n");
+}
+
+
+/*-------------------------------------------------------------------------*/
+
+static struct i2c_driver isp1301_driver;
+
+/* smbus apis are used for portability */
+
+static inline u8
+isp1301_get_u8(struct isp1301 *isp, u8 reg)
+{
+	return i2c_smbus_read_byte_data(isp->client, reg + 0);
+}
+
+static inline int
+isp1301_get_u16(struct isp1301 *isp, u8 reg)
+{
+	return i2c_smbus_read_word_data(isp->client, reg);
+}
+
+static inline int
+isp1301_set_bits(struct isp1301 *isp, u8 reg, u8 bits)
+{
+	return i2c_smbus_write_byte_data(isp->client, reg + 0, bits);
+}
+
+static inline int
+isp1301_clear_bits(struct isp1301 *isp, u8 reg, u8 bits)
+{
+	return i2c_smbus_write_byte_data(isp->client, reg + 1, bits);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* identification */
+#define	ISP1301_VENDOR_ID		0x00	/* u16 read */
+#define	ISP1301_PRODUCT_ID		0x02	/* u16 read */
+#define	ISP1301_BCD_DEVICE		0x14	/* u16 read */
+
+#define	I2C_VENDOR_ID_PHILIPS		0x04cc
+#define	I2C_PRODUCT_ID_PHILIPS_1301	0x1301
+
+/* operational registers */
+#define	ISP1301_MODE_CONTROL_1		0x04	/* u8 read, set, +1 clear */
+#	define	MC1_SPEED		(1 << 0)
+#	define	MC1_SUSPEND		(1 << 1)
+#	define	MC1_DAT_SE0		(1 << 2)
+#	define	MC1_TRANSPARENT		(1 << 3)
+#	define	MC1_BDIS_ACON_EN	(1 << 4)
+#	define	MC1_OE_INT_EN		(1 << 5)
+#	define	MC1_UART_EN		(1 << 6)
+#	define	MC1_MASK		0x7f
+#define	ISP1301_MODE_CONTROL_2		0x12	/* u8 read, set, +1 clear */
+#	define	MC2_GLOBAL_PWR_DN	(1 << 0)
+#	define	MC2_SPD_SUSP_CTRL	(1 << 1)
+#	define	MC2_BI_DI		(1 << 2)
+#	define	MC2_TRANSP_BDIR0	(1 << 3)
+#	define	MC2_TRANSP_BDIR1	(1 << 4)
+#	define	MC2_AUDIO_EN		(1 << 5)
+#	define	MC2_PSW_EN		(1 << 6)
+#	define	MC2_EN2V7		(1 << 7)
+#define	ISP1301_OTG_CONTROL_1		0x06	/* u8 read, set, +1 clear */
+#	define	OTG1_DP_PULLUP		(1 << 0)
+#	define	OTG1_DM_PULLUP		(1 << 1)
+#	define	OTG1_DP_PULLDOWN	(1 << 2)
+#	define	OTG1_DM_PULLDOWN	(1 << 3)
+#	define	OTG1_ID_PULLDOWN	(1 << 4)
+#	define	OTG1_VBUS_DRV		(1 << 5)
+#	define	OTG1_VBUS_DISCHRG	(1 << 6)
+#	define	OTG1_VBUS_CHRG		(1 << 7)
+#define	ISP1301_OTG_STATUS		0x10	/* u8 readonly */
+#	define	OTG_B_SESS_END		(1 << 6)
+#	define	OTG_B_SESS_VLD		(1 << 7)
+
+#define	ISP1301_INTERRUPT_SOURCE	0x08	/* u8 read */
+#define	ISP1301_INTERRUPT_LATCH		0x0A	/* u8 read, set, +1 clear */
+
+#define	ISP1301_INTERRUPT_FALLING	0x0C	/* u8 read, set, +1 clear */
+#define	ISP1301_INTERRUPT_RISING	0x0E	/* u8 read, set, +1 clear */
+
+/* same bitfields in all interrupt registers */
+#	define	INTR_VBUS_VLD		(1 << 0)
+#	define	INTR_SESS_VLD		(1 << 1)
+#	define	INTR_DP_HI		(1 << 2)
+#	define	INTR_ID_GND		(1 << 3)
+#	define	INTR_DM_HI		(1 << 4)
+#	define	INTR_ID_FLOAT		(1 << 5)
+#	define	INTR_BDIS_ACON		(1 << 6)
+#	define	INTR_CR_INT		(1 << 7)
+
+/*-------------------------------------------------------------------------*/
+
+static inline const char *state_name(struct isp1301 *isp)
+{
+	return usb_otg_state_string(isp->phy.state);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* NOTE:  some of this ISP1301 setup is specific to H2 boards;
+ * not everything is guarded by board-specific checks, or even using
+ * omap_usb_config data to deduce MC1_DAT_SE0 and MC2_BI_DI.
+ *
+ * ALSO:  this currently doesn't use ISP1301 low-power modes
+ * while OTG is running.
+ */
+
+static void power_down(struct isp1301 *isp)
+{
+	isp->phy.state = OTG_STATE_UNDEFINED;
+
+	// isp1301_set_bits(isp, ISP1301_MODE_CONTROL_2, MC2_GLOBAL_PWR_DN);
+	isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1, MC1_SUSPEND);
+
+	isp1301_clear_bits(isp, ISP1301_OTG_CONTROL_1, OTG1_ID_PULLDOWN);
+	isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_1, MC1_DAT_SE0);
+}
+
+static void power_up(struct isp1301 *isp)
+{
+	// isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_2, MC2_GLOBAL_PWR_DN);
+	isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_1, MC1_SUSPEND);
+
+	/* do this only when cpu is driving transceiver,
+	 * so host won't see a low speed device...
+	 */
+	isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1, MC1_DAT_SE0);
+}
+
+#define	NO_HOST_SUSPEND
+
+static int host_suspend(struct isp1301 *isp)
+{
+#ifdef	NO_HOST_SUSPEND
+	return 0;
+#else
+	struct device	*dev;
+
+	if (!isp->phy.otg->host)
+		return -ENODEV;
+
+	/* Currently ASSUMES only the OTG port matters;
+	 * other ports could be active...
+	 */
+	dev = isp->phy.otg->host->controller;
+	return dev->driver->suspend(dev, 3, 0);
+#endif
+}
+
+static int host_resume(struct isp1301 *isp)
+{
+#ifdef	NO_HOST_SUSPEND
+	return 0;
+#else
+	struct device	*dev;
+
+	if (!isp->phy.otg->host)
+		return -ENODEV;
+
+	dev = isp->phy.otg->host->controller;
+	return dev->driver->resume(dev, 0);
+#endif
+}
+
+static int gadget_suspend(struct isp1301 *isp)
+{
+	isp->phy.otg->gadget->b_hnp_enable = 0;
+	isp->phy.otg->gadget->a_hnp_support = 0;
+	isp->phy.otg->gadget->a_alt_hnp_support = 0;
+	return usb_gadget_vbus_disconnect(isp->phy.otg->gadget);
+}
+
+/*-------------------------------------------------------------------------*/
+
+#define	TIMER_MINUTES	10
+#define	TIMER_JIFFIES	(TIMER_MINUTES * 60 * HZ)
+
+/* Almost all our I2C messaging comes from a work queue's task context.
+ * NOTE: guaranteeing certain response times might mean we shouldn't
+ * share keventd's work queue; a realtime task might be safest.
+ */
+static void isp1301_defer_work(struct isp1301 *isp, int work)
+{
+	int status;
+
+	if (isp && !test_and_set_bit(work, &isp->todo)) {
+		(void) get_device(&isp->client->dev);
+		status = schedule_work(&isp->work);
+		if (!status && !isp->working)
+			dev_vdbg(&isp->client->dev,
+				"work item %d may be lost\n", work);
+	}
+}
+
+/* called from irq handlers */
+static void a_idle(struct isp1301 *isp, const char *tag)
+{
+	u32 l;
+
+	if (isp->phy.state == OTG_STATE_A_IDLE)
+		return;
+
+	isp->phy.otg->default_a = 1;
+	if (isp->phy.otg->host) {
+		isp->phy.otg->host->is_b_host = 0;
+		host_suspend(isp);
+	}
+	if (isp->phy.otg->gadget) {
+		isp->phy.otg->gadget->is_a_peripheral = 1;
+		gadget_suspend(isp);
+	}
+	isp->phy.state = OTG_STATE_A_IDLE;
+	l = omap_readl(OTG_CTRL) & OTG_XCEIV_OUTPUTS;
+	omap_writel(l, OTG_CTRL);
+	isp->last_otg_ctrl = l;
+	pr_debug("  --> %s/%s\n", state_name(isp), tag);
+}
+
+/* called from irq handlers */
+static void b_idle(struct isp1301 *isp, const char *tag)
+{
+	u32 l;
+
+	if (isp->phy.state == OTG_STATE_B_IDLE)
+		return;
+
+	isp->phy.otg->default_a = 0;
+	if (isp->phy.otg->host) {
+		isp->phy.otg->host->is_b_host = 1;
+		host_suspend(isp);
+	}
+	if (isp->phy.otg->gadget) {
+		isp->phy.otg->gadget->is_a_peripheral = 0;
+		gadget_suspend(isp);
+	}
+	isp->phy.state = OTG_STATE_B_IDLE;
+	l = omap_readl(OTG_CTRL) & OTG_XCEIV_OUTPUTS;
+	omap_writel(l, OTG_CTRL);
+	isp->last_otg_ctrl = l;
+	pr_debug("  --> %s/%s\n", state_name(isp), tag);
+}
+
+static void
+dump_regs(struct isp1301 *isp, const char *label)
+{
+#ifdef	DEBUG
+	u8	ctrl = isp1301_get_u8(isp, ISP1301_OTG_CONTROL_1);
+	u8	status = isp1301_get_u8(isp, ISP1301_OTG_STATUS);
+	u8	src = isp1301_get_u8(isp, ISP1301_INTERRUPT_SOURCE);
+
+	pr_debug("otg: %06x, %s %s, otg/%02x stat/%02x.%02x\n",
+		omap_readl(OTG_CTRL), label, state_name(isp),
+		ctrl, status, src);
+	/* mode control and irq enables don't change much */
+#endif
+}
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef	CONFIG_USB_OTG
+
+/*
+ * The OMAP OTG controller handles most of the OTG state transitions.
+ *
+ * We translate isp1301 outputs (mostly voltage comparator status) into
+ * OTG inputs; OTG outputs (mostly pullup/pulldown controls) and HNP state
+ * flags into isp1301 inputs ... and infer state transitions.
+ */
+
+#ifdef	VERBOSE
+
+static void check_state(struct isp1301 *isp, const char *tag)
+{
+	enum usb_otg_state	state = OTG_STATE_UNDEFINED;
+	u8			fsm = omap_readw(OTG_TEST) & 0x0ff;
+	unsigned		extra = 0;
+
+	switch (fsm) {
+
+	/* default-b */
+	case 0x0:
+		state = OTG_STATE_B_IDLE;
+		break;
+	case 0x3:
+	case 0x7:
+		extra = 1;
+	case 0x1:
+		state = OTG_STATE_B_PERIPHERAL;
+		break;
+	case 0x11:
+		state = OTG_STATE_B_SRP_INIT;
+		break;
+
+	/* extra dual-role default-b states */
+	case 0x12:
+	case 0x13:
+	case 0x16:
+		extra = 1;
+	case 0x17:
+		state = OTG_STATE_B_WAIT_ACON;
+		break;
+	case 0x34:
+		state = OTG_STATE_B_HOST;
+		break;
+
+	/* default-a */
+	case 0x36:
+		state = OTG_STATE_A_IDLE;
+		break;
+	case 0x3c:
+		state = OTG_STATE_A_WAIT_VFALL;
+		break;
+	case 0x7d:
+		state = OTG_STATE_A_VBUS_ERR;
+		break;
+	case 0x9e:
+	case 0x9f:
+		extra = 1;
+	case 0x89:
+		state = OTG_STATE_A_PERIPHERAL;
+		break;
+	case 0xb7:
+		state = OTG_STATE_A_WAIT_VRISE;
+		break;
+	case 0xb8:
+		state = OTG_STATE_A_WAIT_BCON;
+		break;
+	case 0xb9:
+		state = OTG_STATE_A_HOST;
+		break;
+	case 0xba:
+		state = OTG_STATE_A_SUSPEND;
+		break;
+	default:
+		break;
+	}
+	if (isp->phy.state == state && !extra)
+		return;
+	pr_debug("otg: %s FSM %s/%02x, %s, %06x\n", tag,
+		usb_otg_state_string(state), fsm, state_name(isp),
+		omap_readl(OTG_CTRL));
+}
+
+#else
+
+static inline void check_state(struct isp1301 *isp, const char *tag) { }
+
+#endif
+
+/* outputs from ISP1301_INTERRUPT_SOURCE */
+static void update_otg1(struct isp1301 *isp, u8 int_src)
+{
+	u32	otg_ctrl;
+
+	otg_ctrl = omap_readl(OTG_CTRL) & OTG_CTRL_MASK;
+	otg_ctrl &= ~OTG_XCEIV_INPUTS;
+	otg_ctrl &= ~(OTG_ID|OTG_ASESSVLD|OTG_VBUSVLD);
+
+	if (int_src & INTR_SESS_VLD)
+		otg_ctrl |= OTG_ASESSVLD;
+	else if (isp->phy.state == OTG_STATE_A_WAIT_VFALL) {
+		a_idle(isp, "vfall");
+		otg_ctrl &= ~OTG_CTRL_BITS;
+	}
+	if (int_src & INTR_VBUS_VLD)
+		otg_ctrl |= OTG_VBUSVLD;
+	if (int_src & INTR_ID_GND) {		/* default-A */
+		if (isp->phy.state == OTG_STATE_B_IDLE
+				|| isp->phy.state
+					== OTG_STATE_UNDEFINED) {
+			a_idle(isp, "init");
+			return;
+		}
+	} else {				/* default-B */
+		otg_ctrl |= OTG_ID;
+		if (isp->phy.state == OTG_STATE_A_IDLE
+			|| isp->phy.state == OTG_STATE_UNDEFINED) {
+			b_idle(isp, "init");
+			return;
+		}
+	}
+	omap_writel(otg_ctrl, OTG_CTRL);
+}
+
+/* outputs from ISP1301_OTG_STATUS */
+static void update_otg2(struct isp1301 *isp, u8 otg_status)
+{
+	u32	otg_ctrl;
+
+	otg_ctrl = omap_readl(OTG_CTRL) & OTG_CTRL_MASK;
+	otg_ctrl &= ~OTG_XCEIV_INPUTS;
+	otg_ctrl &= ~(OTG_BSESSVLD | OTG_BSESSEND);
+	if (otg_status & OTG_B_SESS_VLD)
+		otg_ctrl |= OTG_BSESSVLD;
+	else if (otg_status & OTG_B_SESS_END)
+		otg_ctrl |= OTG_BSESSEND;
+	omap_writel(otg_ctrl, OTG_CTRL);
+}
+
+/* inputs going to ISP1301 */
+static void otg_update_isp(struct isp1301 *isp)
+{
+	u32	otg_ctrl, otg_change;
+	u8	set = OTG1_DM_PULLDOWN, clr = OTG1_DM_PULLUP;
+
+	otg_ctrl = omap_readl(OTG_CTRL);
+	otg_change = otg_ctrl ^ isp->last_otg_ctrl;
+	isp->last_otg_ctrl = otg_ctrl;
+	otg_ctrl = otg_ctrl & OTG_XCEIV_INPUTS;
+
+	switch (isp->phy.state) {
+	case OTG_STATE_B_IDLE:
+	case OTG_STATE_B_PERIPHERAL:
+	case OTG_STATE_B_SRP_INIT:
+		if (!(otg_ctrl & OTG_PULLUP)) {
+			// if (otg_ctrl & OTG_B_HNPEN) {
+			if (isp->phy.otg->gadget->b_hnp_enable) {
+				isp->phy.state = OTG_STATE_B_WAIT_ACON;
+				pr_debug("  --> b_wait_acon\n");
+			}
+			goto pulldown;
+		}
+pullup:
+		set |= OTG1_DP_PULLUP;
+		clr |= OTG1_DP_PULLDOWN;
+		break;
+	case OTG_STATE_A_SUSPEND:
+	case OTG_STATE_A_PERIPHERAL:
+		if (otg_ctrl & OTG_PULLUP)
+			goto pullup;
+		/* FALLTHROUGH */
+	// case OTG_STATE_B_WAIT_ACON:
+	default:
+pulldown:
+		set |= OTG1_DP_PULLDOWN;
+		clr |= OTG1_DP_PULLUP;
+		break;
+	}
+
+#	define toggle(OTG,ISP) do { \
+		if (otg_ctrl & OTG) set |= ISP; \
+		else clr |= ISP; \
+		} while (0)
+
+	if (!(isp->phy.otg->host))
+		otg_ctrl &= ~OTG_DRV_VBUS;
+
+	switch (isp->phy.state) {
+	case OTG_STATE_A_SUSPEND:
+		if (otg_ctrl & OTG_DRV_VBUS) {
+			set |= OTG1_VBUS_DRV;
+			break;
+		}
+		/* HNP failed for some reason (A_AIDL_BDIS timeout) */
+		notresponding(isp);
+
+		/* FALLTHROUGH */
+	case OTG_STATE_A_VBUS_ERR:
+		isp->phy.state = OTG_STATE_A_WAIT_VFALL;
+		pr_debug("  --> a_wait_vfall\n");
+		/* FALLTHROUGH */
+	case OTG_STATE_A_WAIT_VFALL:
+		/* FIXME usbcore thinks port power is still on ... */
+		clr |= OTG1_VBUS_DRV;
+		break;
+	case OTG_STATE_A_IDLE:
+		if (otg_ctrl & OTG_DRV_VBUS) {
+			isp->phy.state = OTG_STATE_A_WAIT_VRISE;
+			pr_debug("  --> a_wait_vrise\n");
+		}
+		/* FALLTHROUGH */
+	default:
+		toggle(OTG_DRV_VBUS, OTG1_VBUS_DRV);
+	}
+
+	toggle(OTG_PU_VBUS, OTG1_VBUS_CHRG);
+	toggle(OTG_PD_VBUS, OTG1_VBUS_DISCHRG);
+
+#	undef toggle
+
+	isp1301_set_bits(isp, ISP1301_OTG_CONTROL_1, set);
+	isp1301_clear_bits(isp, ISP1301_OTG_CONTROL_1, clr);
+
+	/* HNP switch to host or peripheral; and SRP */
+	if (otg_change & OTG_PULLUP) {
+		u32 l;
+
+		switch (isp->phy.state) {
+		case OTG_STATE_B_IDLE:
+			if (clr & OTG1_DP_PULLUP)
+				break;
+			isp->phy.state = OTG_STATE_B_PERIPHERAL;
+			pr_debug("  --> b_peripheral\n");
+			break;
+		case OTG_STATE_A_SUSPEND:
+			if (clr & OTG1_DP_PULLUP)
+				break;
+			isp->phy.state = OTG_STATE_A_PERIPHERAL;
+			pr_debug("  --> a_peripheral\n");
+			break;
+		default:
+			break;
+		}
+		l = omap_readl(OTG_CTRL);
+		l |= OTG_PULLUP;
+		omap_writel(l, OTG_CTRL);
+	}
+
+	check_state(isp, __func__);
+	dump_regs(isp, "otg->isp1301");
+}
+
+static irqreturn_t omap_otg_irq(int irq, void *_isp)
+{
+	u16		otg_irq = omap_readw(OTG_IRQ_SRC);
+	u32		otg_ctrl;
+	int		ret = IRQ_NONE;
+	struct isp1301	*isp = _isp;
+	struct usb_otg	*otg = isp->phy.otg;
+
+	/* 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);
+		ret = IRQ_HANDLED;
+
+	/* SRP to become b_peripheral failed */
+	} else if (otg_irq & B_SRP_TMROUT) {
+		pr_debug("otg: B_SRP_TIMEOUT, %06x\n", omap_readl(OTG_CTRL));
+		notresponding(isp);
+
+		/* gadget drivers that care should monitor all kinds of
+		 * remote wakeup (SRP, normal) using their own timer
+		 * to give "check cable and A-device" messages.
+		 */
+		if (isp->phy.state == OTG_STATE_B_SRP_INIT)
+			b_idle(isp, "srp_timeout");
+
+		omap_writew(B_SRP_TMROUT, OTG_IRQ_SRC);
+		ret = IRQ_HANDLED;
+
+	/* HNP to become b_host failed */
+	} else if (otg_irq & B_HNP_FAIL) {
+		pr_debug("otg: %s B_HNP_FAIL, %06x\n",
+				state_name(isp), omap_readl(OTG_CTRL));
+		notresponding(isp);
+
+		otg_ctrl = omap_readl(OTG_CTRL);
+		otg_ctrl |= OTG_BUSDROP;
+		otg_ctrl &= OTG_CTRL_MASK & ~OTG_XCEIV_INPUTS;
+		omap_writel(otg_ctrl, OTG_CTRL);
+
+		/* subset of b_peripheral()... */
+		isp->phy.state = OTG_STATE_B_PERIPHERAL;
+		pr_debug("  --> b_peripheral\n");
+
+		omap_writew(B_HNP_FAIL, OTG_IRQ_SRC);
+		ret = IRQ_HANDLED;
+
+	/* detect SRP from B-device ... */
+	} else if (otg_irq & A_SRP_DETECT) {
+		pr_debug("otg: %s SRP_DETECT, %06x\n",
+				state_name(isp), omap_readl(OTG_CTRL));
+
+		isp1301_defer_work(isp, WORK_UPDATE_OTG);
+		switch (isp->phy.state) {
+		case OTG_STATE_A_IDLE:
+			if (!otg->host)
+				break;
+			isp1301_defer_work(isp, WORK_HOST_RESUME);
+			otg_ctrl = omap_readl(OTG_CTRL);
+			otg_ctrl |= OTG_A_BUSREQ;
+			otg_ctrl &= ~(OTG_BUSDROP|OTG_B_BUSREQ)
+					& ~OTG_XCEIV_INPUTS
+					& OTG_CTRL_MASK;
+			omap_writel(otg_ctrl, OTG_CTRL);
+			break;
+		default:
+			break;
+		}
+
+		omap_writew(A_SRP_DETECT, OTG_IRQ_SRC);
+		ret = IRQ_HANDLED;
+
+	/* timer expired:  T(a_wait_bcon) and maybe T(a_wait_vrise)
+	 * we don't track them separately
+	 */
+	} else if (otg_irq & A_REQ_TMROUT) {
+		otg_ctrl = omap_readl(OTG_CTRL);
+		pr_info("otg: BCON_TMOUT from %s, %06x\n",
+				state_name(isp), otg_ctrl);
+		notresponding(isp);
+
+		otg_ctrl |= OTG_BUSDROP;
+		otg_ctrl &= ~OTG_A_BUSREQ & OTG_CTRL_MASK & ~OTG_XCEIV_INPUTS;
+		omap_writel(otg_ctrl, OTG_CTRL);
+		isp->phy.state = OTG_STATE_A_WAIT_VFALL;
+
+		omap_writew(A_REQ_TMROUT, OTG_IRQ_SRC);
+		ret = IRQ_HANDLED;
+
+	/* A-supplied voltage fell too low; overcurrent */
+	} else if (otg_irq & A_VBUS_ERR) {
+		otg_ctrl = omap_readl(OTG_CTRL);
+		printk(KERN_ERR "otg: %s, VBUS_ERR %04x ctrl %06x\n",
+			state_name(isp), otg_irq, otg_ctrl);
+
+		otg_ctrl |= OTG_BUSDROP;
+		otg_ctrl &= ~OTG_A_BUSREQ & OTG_CTRL_MASK & ~OTG_XCEIV_INPUTS;
+		omap_writel(otg_ctrl, OTG_CTRL);
+		isp->phy.state = OTG_STATE_A_VBUS_ERR;
+
+		omap_writew(A_VBUS_ERR, OTG_IRQ_SRC);
+		ret = IRQ_HANDLED;
+
+	/* switch driver; the transceiver code activates it,
+	 * ungating the udc clock or resuming OHCI.
+	 */
+	} else if (otg_irq & DRIVER_SWITCH) {
+		int	kick = 0;
+
+		otg_ctrl = omap_readl(OTG_CTRL);
+		printk(KERN_NOTICE "otg: %s, SWITCH to %s, ctrl %06x\n",
+				state_name(isp),
+				(otg_ctrl & OTG_DRIVER_SEL)
+					? "gadget" : "host",
+				otg_ctrl);
+		isp1301_defer_work(isp, WORK_UPDATE_ISP);
+
+		/* role is peripheral */
+		if (otg_ctrl & OTG_DRIVER_SEL) {
+			switch (isp->phy.state) {
+			case OTG_STATE_A_IDLE:
+				b_idle(isp, __func__);
+				break;
+			default:
+				break;
+			}
+			isp1301_defer_work(isp, WORK_UPDATE_ISP);
+
+		/* role is host */
+		} else {
+			if (!(otg_ctrl & OTG_ID)) {
+				otg_ctrl &= OTG_CTRL_MASK & ~OTG_XCEIV_INPUTS;
+				omap_writel(otg_ctrl | OTG_A_BUSREQ, OTG_CTRL);
+			}
+
+			if (otg->host) {
+				switch (isp->phy.state) {
+				case OTG_STATE_B_WAIT_ACON:
+					isp->phy.state = OTG_STATE_B_HOST;
+					pr_debug("  --> b_host\n");
+					kick = 1;
+					break;
+				case OTG_STATE_A_WAIT_BCON:
+					isp->phy.state = OTG_STATE_A_HOST;
+					pr_debug("  --> a_host\n");
+					break;
+				case OTG_STATE_A_PERIPHERAL:
+					isp->phy.state = OTG_STATE_A_WAIT_BCON;
+					pr_debug("  --> a_wait_bcon\n");
+					break;
+				default:
+					break;
+				}
+				isp1301_defer_work(isp, WORK_HOST_RESUME);
+			}
+		}
+
+		omap_writew(DRIVER_SWITCH, OTG_IRQ_SRC);
+		ret = IRQ_HANDLED;
+
+		if (kick)
+			usb_bus_start_enum(otg->host, otg->host->otg_port);
+	}
+
+	check_state(isp, __func__);
+	return ret;
+}
+
+static struct platform_device *otg_dev;
+
+static int isp1301_otg_init(struct isp1301 *isp)
+{
+	u32 l;
+
+	if (!otg_dev)
+		return -ENODEV;
+
+	dump_regs(isp, __func__);
+	/* some of these values are board-specific... */
+	l = omap_readl(OTG_SYSCON_2);
+	l |= OTG_EN
+		/* for B-device: */
+		| SRP_GPDATA		/* 9msec Bdev D+ pulse */
+		| SRP_GPDVBUS		/* discharge after VBUS pulse */
+		// | (3 << 24)		/* 2msec VBUS pulse */
+		/* for A-device: */
+		| (0 << 20)		/* 200ms nominal A_WAIT_VRISE timer */
+		| SRP_DPW		/* detect 167+ns SRP pulses */
+		| SRP_DATA | SRP_VBUS	/* accept both kinds of SRP pulse */
+		;
+	omap_writel(l, OTG_SYSCON_2);
+
+	update_otg1(isp, isp1301_get_u8(isp, ISP1301_INTERRUPT_SOURCE));
+	update_otg2(isp, isp1301_get_u8(isp, ISP1301_OTG_STATUS));
+
+	check_state(isp, __func__);
+	pr_debug("otg: %s, %s %06x\n",
+			state_name(isp), __func__, omap_readl(OTG_CTRL));
+
+	omap_writew(DRIVER_SWITCH | OPRT_CHG
+			| B_SRP_TMROUT | B_HNP_FAIL
+			| A_VBUS_ERR | A_SRP_DETECT | A_REQ_TMROUT, OTG_IRQ_EN);
+
+	l = omap_readl(OTG_SYSCON_2);
+	l |= OTG_EN;
+	omap_writel(l, OTG_SYSCON_2);
+
+	return 0;
+}
+
+static int otg_probe(struct platform_device *dev)
+{
+	// struct omap_usb_config *config = dev->platform_data;
+
+	otg_dev = dev;
+	return 0;
+}
+
+static int otg_remove(struct platform_device *dev)
+{
+	otg_dev = NULL;
+	return 0;
+}
+
+static struct platform_driver omap_otg_driver = {
+	.probe		= otg_probe,
+	.remove		= otg_remove,
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= "omap_otg",
+	},
+};
+
+static int otg_bind(struct isp1301 *isp)
+{
+	int	status;
+
+	if (otg_dev)
+		return -EBUSY;
+
+	status = platform_driver_register(&omap_otg_driver);
+	if (status < 0)
+		return status;
+
+	if (otg_dev)
+		status = request_irq(otg_dev->resource[1].start, omap_otg_irq,
+				0, DRIVER_NAME, isp);
+	else
+		status = -ENODEV;
+
+	if (status < 0)
+		platform_driver_unregister(&omap_otg_driver);
+	return status;
+}
+
+static void otg_unbind(struct isp1301 *isp)
+{
+	if (!otg_dev)
+		return;
+	free_irq(otg_dev->resource[1].start, isp);
+}
+
+#else
+
+/* OTG controller isn't clocked */
+
+#endif	/* CONFIG_USB_OTG */
+
+/*-------------------------------------------------------------------------*/
+
+static void b_peripheral(struct isp1301 *isp)
+{
+	u32 l;
+
+	l = omap_readl(OTG_CTRL) & OTG_XCEIV_OUTPUTS;
+	omap_writel(l, OTG_CTRL);
+
+	usb_gadget_vbus_connect(isp->phy.otg->gadget);
+
+#ifdef	CONFIG_USB_OTG
+	enable_vbus_draw(isp, 8);
+	otg_update_isp(isp);
+#else
+	enable_vbus_draw(isp, 100);
+	/* UDC driver just set OTG_BSESSVLD */
+	isp1301_set_bits(isp, ISP1301_OTG_CONTROL_1, OTG1_DP_PULLUP);
+	isp1301_clear_bits(isp, ISP1301_OTG_CONTROL_1, OTG1_DP_PULLDOWN);
+	isp->phy.state = OTG_STATE_B_PERIPHERAL;
+	pr_debug("  --> b_peripheral\n");
+	dump_regs(isp, "2periph");
+#endif
+}
+
+static void isp_update_otg(struct isp1301 *isp, u8 stat)
+{
+	struct usb_otg		*otg = isp->phy.otg;
+	u8			isp_stat, isp_bstat;
+	enum usb_otg_state	state = isp->phy.state;
+
+	if (stat & INTR_BDIS_ACON)
+		pr_debug("OTG:  BDIS_ACON, %s\n", state_name(isp));
+
+	/* start certain state transitions right away */
+	isp_stat = isp1301_get_u8(isp, ISP1301_INTERRUPT_SOURCE);
+	if (isp_stat & INTR_ID_GND) {
+		if (otg->default_a) {
+			switch (state) {
+			case OTG_STATE_B_IDLE:
+				a_idle(isp, "idle");
+				/* FALLTHROUGH */
+			case OTG_STATE_A_IDLE:
+				enable_vbus_source(isp);
+				/* FALLTHROUGH */
+			case OTG_STATE_A_WAIT_VRISE:
+				/* we skip over OTG_STATE_A_WAIT_BCON, since
+				 * the HC will transition to A_HOST (or
+				 * A_SUSPEND!) without our noticing except
+				 * when HNP is used.
+				 */
+				if (isp_stat & INTR_VBUS_VLD)
+					isp->phy.state = OTG_STATE_A_HOST;
+				break;
+			case OTG_STATE_A_WAIT_VFALL:
+				if (!(isp_stat & INTR_SESS_VLD))
+					a_idle(isp, "vfell");
+				break;
+			default:
+				if (!(isp_stat & INTR_VBUS_VLD))
+					isp->phy.state = OTG_STATE_A_VBUS_ERR;
+				break;
+			}
+			isp_bstat = isp1301_get_u8(isp, ISP1301_OTG_STATUS);
+		} else {
+			switch (state) {
+			case OTG_STATE_B_PERIPHERAL:
+			case OTG_STATE_B_HOST:
+			case OTG_STATE_B_WAIT_ACON:
+				usb_gadget_vbus_disconnect(otg->gadget);
+				break;
+			default:
+				break;
+			}
+			if (state != OTG_STATE_A_IDLE)
+				a_idle(isp, "id");
+			if (otg->host && state == OTG_STATE_A_IDLE)
+				isp1301_defer_work(isp, WORK_HOST_RESUME);
+			isp_bstat = 0;
+		}
+	} else {
+		u32 l;
+
+		/* if user unplugged mini-A end of cable,
+		 * don't bypass A_WAIT_VFALL.
+		 */
+		if (otg->default_a) {
+			switch (state) {
+			default:
+				isp->phy.state = OTG_STATE_A_WAIT_VFALL;
+				break;
+			case OTG_STATE_A_WAIT_VFALL:
+				state = OTG_STATE_A_IDLE;
+				/* khubd may take a while to notice and
+				 * handle this disconnect, so don't go
+				 * to B_IDLE quite yet.
+				 */
+				break;
+			case OTG_STATE_A_IDLE:
+				host_suspend(isp);
+				isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_1,
+						MC1_BDIS_ACON_EN);
+				isp->phy.state = OTG_STATE_B_IDLE;
+				l = omap_readl(OTG_CTRL) & OTG_CTRL_MASK;
+				l &= ~OTG_CTRL_BITS;
+				omap_writel(l, OTG_CTRL);
+				break;
+			case OTG_STATE_B_IDLE:
+				break;
+			}
+		}
+		isp_bstat = isp1301_get_u8(isp, ISP1301_OTG_STATUS);
+
+		switch (isp->phy.state) {
+		case OTG_STATE_B_PERIPHERAL:
+		case OTG_STATE_B_WAIT_ACON:
+		case OTG_STATE_B_HOST:
+			if (likely(isp_bstat & OTG_B_SESS_VLD))
+				break;
+			enable_vbus_draw(isp, 0);
+#ifndef	CONFIG_USB_OTG
+			/* UDC driver will clear OTG_BSESSVLD */
+			isp1301_set_bits(isp, ISP1301_OTG_CONTROL_1,
+						OTG1_DP_PULLDOWN);
+			isp1301_clear_bits(isp, ISP1301_OTG_CONTROL_1,
+						OTG1_DP_PULLUP);
+			dump_regs(isp, __func__);
+#endif
+			/* FALLTHROUGH */
+		case OTG_STATE_B_SRP_INIT:
+			b_idle(isp, __func__);
+			l = omap_readl(OTG_CTRL) & OTG_XCEIV_OUTPUTS;
+			omap_writel(l, OTG_CTRL);
+			/* FALLTHROUGH */
+		case OTG_STATE_B_IDLE:
+			if (otg->gadget && (isp_bstat & OTG_B_SESS_VLD)) {
+#ifdef	CONFIG_USB_OTG
+				update_otg1(isp, isp_stat);
+				update_otg2(isp, isp_bstat);
+#endif
+				b_peripheral(isp);
+			} else if (!(isp_stat & (INTR_VBUS_VLD|INTR_SESS_VLD)))
+				isp_bstat |= OTG_B_SESS_END;
+			break;
+		case OTG_STATE_A_WAIT_VFALL:
+			break;
+		default:
+			pr_debug("otg: unsupported b-device %s\n",
+				state_name(isp));
+			break;
+		}
+	}
+
+	if (state != isp->phy.state)
+		pr_debug("  isp, %s -> %s\n",
+				usb_otg_state_string(state), state_name(isp));
+
+#ifdef	CONFIG_USB_OTG
+	/* update the OTG controller state to match the isp1301; may
+	 * trigger OPRT_CHG irqs for changes going to the isp1301.
+	 */
+	update_otg1(isp, isp_stat);
+	update_otg2(isp, isp_bstat);
+	check_state(isp, __func__);
+#endif
+
+	dump_regs(isp, "isp1301->otg");
+}
+
+/*-------------------------------------------------------------------------*/
+
+static u8 isp1301_clear_latch(struct isp1301 *isp)
+{
+	u8 latch = isp1301_get_u8(isp, ISP1301_INTERRUPT_LATCH);
+	isp1301_clear_bits(isp, ISP1301_INTERRUPT_LATCH, latch);
+	return latch;
+}
+
+static void
+isp1301_work(struct work_struct *work)
+{
+	struct isp1301	*isp = container_of(work, struct isp1301, work);
+	int		stop;
+
+	/* implicit lock:  we're the only task using this device */
+	isp->working = 1;
+	do {
+		stop = test_bit(WORK_STOP, &isp->todo);
+
+#ifdef	CONFIG_USB_OTG
+		/* transfer state from otg engine to isp1301 */
+		if (test_and_clear_bit(WORK_UPDATE_ISP, &isp->todo)) {
+			otg_update_isp(isp);
+			put_device(&isp->client->dev);
+		}
+#endif
+		/* transfer state from isp1301 to otg engine */
+		if (test_and_clear_bit(WORK_UPDATE_OTG, &isp->todo)) {
+			u8		stat = isp1301_clear_latch(isp);
+
+			isp_update_otg(isp, stat);
+			put_device(&isp->client->dev);
+		}
+
+		if (test_and_clear_bit(WORK_HOST_RESUME, &isp->todo)) {
+			u32	otg_ctrl;
+
+			/*
+			 * skip A_WAIT_VRISE; hc transitions invisibly
+			 * skip A_WAIT_BCON; same.
+			 */
+			switch (isp->phy.state) {
+			case OTG_STATE_A_WAIT_BCON:
+			case OTG_STATE_A_WAIT_VRISE:
+				isp->phy.state = OTG_STATE_A_HOST;
+				pr_debug("  --> a_host\n");
+				otg_ctrl = omap_readl(OTG_CTRL);
+				otg_ctrl |= OTG_A_BUSREQ;
+				otg_ctrl &= ~(OTG_BUSDROP|OTG_B_BUSREQ)
+						& OTG_CTRL_MASK;
+				omap_writel(otg_ctrl, OTG_CTRL);
+				break;
+			case OTG_STATE_B_WAIT_ACON:
+				isp->phy.state = OTG_STATE_B_HOST;
+				pr_debug("  --> b_host (acon)\n");
+				break;
+			case OTG_STATE_B_HOST:
+			case OTG_STATE_B_IDLE:
+			case OTG_STATE_A_IDLE:
+				break;
+			default:
+				pr_debug("  host resume in %s\n",
+						state_name(isp));
+			}
+			host_resume(isp);
+			// mdelay(10);
+			put_device(&isp->client->dev);
+		}
+
+		if (test_and_clear_bit(WORK_TIMER, &isp->todo)) {
+#ifdef	VERBOSE
+			dump_regs(isp, "timer");
+			if (!stop)
+				mod_timer(&isp->timer, jiffies + TIMER_JIFFIES);
+#endif
+			put_device(&isp->client->dev);
+		}
+
+		if (isp->todo)
+			dev_vdbg(&isp->client->dev,
+				"work done, todo = 0x%lx\n",
+				isp->todo);
+		if (stop) {
+			dev_dbg(&isp->client->dev, "stop\n");
+			break;
+		}
+	} while (isp->todo);
+	isp->working = 0;
+}
+
+static irqreturn_t isp1301_irq(int irq, void *isp)
+{
+	isp1301_defer_work(isp, WORK_UPDATE_OTG);
+	return IRQ_HANDLED;
+}
+
+static void isp1301_timer(unsigned long _isp)
+{
+	isp1301_defer_work((void *)_isp, WORK_TIMER);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void isp1301_release(struct device *dev)
+{
+	struct isp1301	*isp;
+
+	isp = dev_get_drvdata(dev);
+
+	/* FIXME -- not with a "new style" driver, it doesn't!! */
+
+	/* ugly -- i2c hijacks our memory hook to wait_for_completion() */
+	if (isp->i2c_release)
+		isp->i2c_release(dev);
+	kfree(isp->phy.otg);
+	kfree (isp);
+}
+
+static struct isp1301 *the_transceiver;
+
+static int isp1301_remove(struct i2c_client *i2c)
+{
+	struct isp1301	*isp;
+
+	isp = i2c_get_clientdata(i2c);
+
+	isp1301_clear_bits(isp, ISP1301_INTERRUPT_FALLING, ~0);
+	isp1301_clear_bits(isp, ISP1301_INTERRUPT_RISING, ~0);
+	free_irq(i2c->irq, isp);
+#ifdef	CONFIG_USB_OTG
+	otg_unbind(isp);
+#endif
+	if (machine_is_omap_h2())
+		gpio_free(2);
+
+	isp->timer.data = 0;
+	set_bit(WORK_STOP, &isp->todo);
+	del_timer_sync(&isp->timer);
+	flush_work(&isp->work);
+
+	put_device(&i2c->dev);
+	the_transceiver = NULL;
+
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* NOTE:  three modes are possible here, only one of which
+ * will be standards-conformant on any given system:
+ *
+ *  - OTG mode (dual-role), required if there's a Mini-AB connector
+ *  - HOST mode, for when there's one or more A (host) connectors
+ *  - DEVICE mode, for when there's a B/Mini-B (device) connector
+ *
+ * As a rule, you won't have an isp1301 chip unless it's there to
+ * support the OTG mode.  Other modes help testing USB controllers
+ * in isolation from (full) OTG support, or maybe so later board
+ * revisions can help to support those feature.
+ */
+
+#ifdef	CONFIG_USB_OTG
+
+static int isp1301_otg_enable(struct isp1301 *isp)
+{
+	power_up(isp);
+	isp1301_otg_init(isp);
+
+	/* NOTE:  since we don't change this, this provides
+	 * a few more interrupts than are strictly needed.
+	 */
+	isp1301_set_bits(isp, ISP1301_INTERRUPT_RISING,
+		INTR_VBUS_VLD | INTR_SESS_VLD | INTR_ID_GND);
+	isp1301_set_bits(isp, ISP1301_INTERRUPT_FALLING,
+		INTR_VBUS_VLD | INTR_SESS_VLD | INTR_ID_GND);
+
+	dev_info(&isp->client->dev, "ready for dual-role USB ...\n");
+
+	return 0;
+}
+
+#endif
+
+/* add or disable the host device+driver */
+static int
+isp1301_set_host(struct usb_otg *otg, struct usb_bus *host)
+{
+	struct isp1301	*isp = container_of(otg->phy, struct isp1301, phy);
+
+	if (!otg || isp != the_transceiver)
+		return -ENODEV;
+
+	if (!host) {
+		omap_writew(0, OTG_IRQ_EN);
+		power_down(isp);
+		otg->host = NULL;
+		return 0;
+	}
+
+#ifdef	CONFIG_USB_OTG
+	otg->host = host;
+	dev_dbg(&isp->client->dev, "registered host\n");
+	host_suspend(isp);
+	if (otg->gadget)
+		return isp1301_otg_enable(isp);
+	return 0;
+
+#elif	!defined(CONFIG_USB_GADGET_OMAP)
+	// FIXME update its refcount
+	otg->host = host;
+
+	power_up(isp);
+
+	if (machine_is_omap_h2())
+		isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1, MC1_DAT_SE0);
+
+	dev_info(&isp->client->dev, "A-Host sessions ok\n");
+	isp1301_set_bits(isp, ISP1301_INTERRUPT_RISING,
+		INTR_ID_GND);
+	isp1301_set_bits(isp, ISP1301_INTERRUPT_FALLING,
+		INTR_ID_GND);
+
+	/* If this has a Mini-AB connector, this mode is highly
+	 * nonstandard ... but can be handy for testing, especially with
+	 * the Mini-A end of an OTG cable.  (Or something nonstandard
+	 * like MiniB-to-StandardB, maybe built with a gender mender.)
+	 */
+	isp1301_set_bits(isp, ISP1301_OTG_CONTROL_1, OTG1_VBUS_DRV);
+
+	dump_regs(isp, __func__);
+
+	return 0;
+
+#else
+	dev_dbg(&isp->client->dev, "host sessions not allowed\n");
+	return -EINVAL;
+#endif
+
+}
+
+static int
+isp1301_set_peripheral(struct usb_otg *otg, struct usb_gadget *gadget)
+{
+	struct isp1301	*isp = container_of(otg->phy, struct isp1301, phy);
+
+	if (!otg || isp != the_transceiver)
+		return -ENODEV;
+
+	if (!gadget) {
+		omap_writew(0, OTG_IRQ_EN);
+		if (!otg->default_a)
+			enable_vbus_draw(isp, 0);
+		usb_gadget_vbus_disconnect(otg->gadget);
+		otg->gadget = NULL;
+		power_down(isp);
+		return 0;
+	}
+
+#ifdef	CONFIG_USB_OTG
+	otg->gadget = gadget;
+	dev_dbg(&isp->client->dev, "registered gadget\n");
+	/* gadget driver may be suspended until vbus_connect () */
+	if (otg->host)
+		return isp1301_otg_enable(isp);
+	return 0;
+
+#elif	!defined(CONFIG_USB_OHCI_HCD) && !defined(CONFIG_USB_OHCI_HCD_MODULE)
+	otg->gadget = gadget;
+	// FIXME update its refcount
+
+	{
+		u32 l;
+
+		l = omap_readl(OTG_CTRL) & OTG_CTRL_MASK;
+		l &= ~(OTG_XCEIV_OUTPUTS|OTG_CTRL_BITS);
+		l |= OTG_ID;
+		omap_writel(l, OTG_CTRL);
+	}
+
+	power_up(isp);
+	isp->phy.state = OTG_STATE_B_IDLE;
+
+	if (machine_is_omap_h2() || machine_is_omap_h3())
+		isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1, MC1_DAT_SE0);
+
+	isp1301_set_bits(isp, ISP1301_INTERRUPT_RISING,
+		INTR_SESS_VLD);
+	isp1301_set_bits(isp, ISP1301_INTERRUPT_FALLING,
+		INTR_VBUS_VLD);
+	dev_info(&isp->client->dev, "B-Peripheral sessions ok\n");
+	dump_regs(isp, __func__);
+
+	/* If this has a Mini-AB connector, this mode is highly
+	 * nonstandard ... but can be handy for testing, so long
+	 * as you don't plug a Mini-A cable into the jack.
+	 */
+	if (isp1301_get_u8(isp, ISP1301_INTERRUPT_SOURCE) & INTR_VBUS_VLD)
+		b_peripheral(isp);
+
+	return 0;
+
+#else
+	dev_dbg(&isp->client->dev, "peripheral sessions not allowed\n");
+	return -EINVAL;
+#endif
+}
+
+
+/*-------------------------------------------------------------------------*/
+
+static int
+isp1301_set_power(struct usb_phy *dev, unsigned mA)
+{
+	if (!the_transceiver)
+		return -ENODEV;
+	if (dev->state == OTG_STATE_B_PERIPHERAL)
+		enable_vbus_draw(the_transceiver, mA);
+	return 0;
+}
+
+static int
+isp1301_start_srp(struct usb_otg *otg)
+{
+	struct isp1301	*isp = container_of(otg->phy, struct isp1301, phy);
+	u32		otg_ctrl;
+
+	if (!otg || isp != the_transceiver
+			|| isp->phy.state != OTG_STATE_B_IDLE)
+		return -ENODEV;
+
+	otg_ctrl = omap_readl(OTG_CTRL);
+	if (!(otg_ctrl & OTG_BSESSEND))
+		return -EINVAL;
+
+	otg_ctrl |= OTG_B_BUSREQ;
+	otg_ctrl &= ~OTG_A_BUSREQ & OTG_CTRL_MASK;
+	omap_writel(otg_ctrl, OTG_CTRL);
+	isp->phy.state = OTG_STATE_B_SRP_INIT;
+
+	pr_debug("otg: SRP, %s ... %06x\n", state_name(isp),
+			omap_readl(OTG_CTRL));
+#ifdef	CONFIG_USB_OTG
+	check_state(isp, __func__);
+#endif
+	return 0;
+}
+
+static int
+isp1301_start_hnp(struct usb_otg *otg)
+{
+#ifdef	CONFIG_USB_OTG
+	struct isp1301	*isp = container_of(otg->phy, struct isp1301, phy);
+	u32 l;
+
+	if (!otg || isp != the_transceiver)
+		return -ENODEV;
+	if (otg->default_a && (otg->host == NULL || !otg->host->b_hnp_enable))
+		return -ENOTCONN;
+	if (!otg->default_a && (otg->gadget == NULL
+			|| !otg->gadget->b_hnp_enable))
+		return -ENOTCONN;
+
+	/* We want hardware to manage most HNP protocol timings.
+	 * So do this part as early as possible...
+	 */
+	switch (isp->phy.state) {
+	case OTG_STATE_B_HOST:
+		isp->phy.state = OTG_STATE_B_PERIPHERAL;
+		/* caller will suspend next */
+		break;
+	case OTG_STATE_A_HOST:
+#if 0
+		/* autoconnect mode avoids irq latency bugs */
+		isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1,
+				MC1_BDIS_ACON_EN);
+#endif
+		/* caller must suspend then clear A_BUSREQ */
+		usb_gadget_vbus_connect(otg->gadget);
+		l = omap_readl(OTG_CTRL);
+		l |= OTG_A_SETB_HNPEN;
+		omap_writel(l, OTG_CTRL);
+
+		break;
+	case OTG_STATE_A_PERIPHERAL:
+		/* initiated by B-Host suspend */
+		break;
+	default:
+		return -EILSEQ;
+	}
+	pr_debug("otg: HNP %s, %06x ...\n",
+		state_name(isp), omap_readl(OTG_CTRL));
+	check_state(isp, __func__);
+	return 0;
+#else
+	/* srp-only */
+	return -EINVAL;
+#endif
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int
+isp1301_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
+{
+	int			status;
+	struct isp1301		*isp;
+
+	if (the_transceiver)
+		return 0;
+
+	isp = kzalloc(sizeof *isp, GFP_KERNEL);
+	if (!isp)
+		return 0;
+
+	isp->phy.otg = kzalloc(sizeof *isp->phy.otg, GFP_KERNEL);
+	if (!isp->phy.otg) {
+		kfree(isp);
+		return 0;
+	}
+
+	INIT_WORK(&isp->work, isp1301_work);
+	init_timer(&isp->timer);
+	isp->timer.function = isp1301_timer;
+	isp->timer.data = (unsigned long) isp;
+
+	i2c_set_clientdata(i2c, isp);
+	isp->client = i2c;
+
+	/* verify the chip (shouldn't be necessary) */
+	status = isp1301_get_u16(isp, ISP1301_VENDOR_ID);
+	if (status != I2C_VENDOR_ID_PHILIPS) {
+		dev_dbg(&i2c->dev, "not philips id: %d\n", status);
+		goto fail;
+	}
+	status = isp1301_get_u16(isp, ISP1301_PRODUCT_ID);
+	if (status != I2C_PRODUCT_ID_PHILIPS_1301) {
+		dev_dbg(&i2c->dev, "not isp1301, %d\n", status);
+		goto fail;
+	}
+	isp->i2c_release = i2c->dev.release;
+	i2c->dev.release = isp1301_release;
+
+	/* initial development used chiprev 2.00 */
+	status = i2c_smbus_read_word_data(i2c, ISP1301_BCD_DEVICE);
+	dev_info(&i2c->dev, "chiprev %x.%02x, driver " DRIVER_VERSION "\n",
+		status >> 8, status & 0xff);
+
+	/* make like power-on reset */
+	isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_1, MC1_MASK);
+
+	isp1301_set_bits(isp, ISP1301_MODE_CONTROL_2, MC2_BI_DI);
+	isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_2, ~MC2_BI_DI);
+
+	isp1301_set_bits(isp, ISP1301_OTG_CONTROL_1,
+				OTG1_DM_PULLDOWN | OTG1_DP_PULLDOWN);
+	isp1301_clear_bits(isp, ISP1301_OTG_CONTROL_1,
+				~(OTG1_DM_PULLDOWN | OTG1_DP_PULLDOWN));
+
+	isp1301_clear_bits(isp, ISP1301_INTERRUPT_LATCH, ~0);
+	isp1301_clear_bits(isp, ISP1301_INTERRUPT_FALLING, ~0);
+	isp1301_clear_bits(isp, ISP1301_INTERRUPT_RISING, ~0);
+
+#ifdef	CONFIG_USB_OTG
+	status = otg_bind(isp);
+	if (status < 0) {
+		dev_dbg(&i2c->dev, "can't bind OTG\n");
+		goto fail;
+	}
+#endif
+
+	if (machine_is_omap_h2()) {
+		/* full speed signaling by default */
+		isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1,
+			MC1_SPEED);
+		isp1301_set_bits(isp, ISP1301_MODE_CONTROL_2,
+			MC2_SPD_SUSP_CTRL);
+
+		/* IRQ wired at M14 */
+		omap_cfg_reg(M14_1510_GPIO2);
+		if (gpio_request(2, "isp1301") == 0)
+			gpio_direction_input(2);
+		isp->irq_type = IRQF_TRIGGER_FALLING;
+	}
+
+	status = request_irq(i2c->irq, isp1301_irq,
+			isp->irq_type, DRIVER_NAME, isp);
+	if (status < 0) {
+		dev_dbg(&i2c->dev, "can't get IRQ %d, err %d\n",
+				i2c->irq, status);
+		goto fail;
+	}
+
+	isp->phy.dev = &i2c->dev;
+	isp->phy.label = DRIVER_NAME;
+	isp->phy.set_power = isp1301_set_power,
+
+	isp->phy.otg->phy = &isp->phy;
+	isp->phy.otg->set_host = isp1301_set_host,
+	isp->phy.otg->set_peripheral = isp1301_set_peripheral,
+	isp->phy.otg->start_srp = isp1301_start_srp,
+	isp->phy.otg->start_hnp = isp1301_start_hnp,
+
+	enable_vbus_draw(isp, 0);
+	power_down(isp);
+	the_transceiver = isp;
+
+#ifdef	CONFIG_USB_OTG
+	update_otg1(isp, isp1301_get_u8(isp, ISP1301_INTERRUPT_SOURCE));
+	update_otg2(isp, isp1301_get_u8(isp, ISP1301_OTG_STATUS));
+#endif
+
+	dump_regs(isp, __func__);
+
+#ifdef	VERBOSE
+	mod_timer(&isp->timer, jiffies + TIMER_JIFFIES);
+	dev_dbg(&i2c->dev, "scheduled timer, %d min\n", TIMER_MINUTES);
+#endif
+
+	status = usb_add_phy(&isp->phy, USB_PHY_TYPE_USB2);
+	if (status < 0)
+		dev_err(&i2c->dev, "can't register transceiver, %d\n",
+			status);
+
+	return 0;
+
+fail:
+	kfree(isp->phy.otg);
+	kfree(isp);
+	return -ENODEV;
+}
+
+static const struct i2c_device_id isp1301_id[] = {
+	{ "isp1301_omap", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, isp1301_id);
+
+static struct i2c_driver isp1301_driver = {
+	.driver = {
+		.name	= "isp1301_omap",
+	},
+	.probe		= isp1301_probe,
+	.remove		= isp1301_remove,
+	.id_table	= isp1301_id,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static int __init isp_init(void)
+{
+	return i2c_add_driver(&isp1301_driver);
+}
+subsys_initcall(isp_init);
+
+static void __exit isp_exit(void)
+{
+	if (the_transceiver)
+		usb_remove_phy(&the_transceiver->phy);
+	i2c_del_driver(&isp1301_driver);
+}
+module_exit(isp_exit);
+
diff --git a/drivers/usb/phy/phy-isp1301.c b/drivers/usb/phy/phy-isp1301.c
new file mode 100644
index 0000000..225ae6c
--- /dev/null
+++ b/drivers/usb/phy/phy-isp1301.c
@@ -0,0 +1,162 @@
+/*
+ * NXP ISP1301 USB transceiver driver
+ *
+ * Copyright (C) 2012 Roland Stigge
+ *
+ * Author: Roland Stigge <stigge@antcom.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/module.h>
+#include <linux/mutex.h>
+#include <linux/i2c.h>
+#include <linux/usb/phy.h>
+#include <linux/usb/isp1301.h>
+
+#define DRV_NAME		"isp1301"
+
+struct isp1301 {
+	struct usb_phy		phy;
+	struct mutex		mutex;
+
+	struct i2c_client	*client;
+};
+
+#define phy_to_isp(p)		(container_of((p), struct isp1301, phy))
+
+static const struct i2c_device_id isp1301_id[] = {
+	{ "isp1301", 0 },
+	{ }
+};
+
+static struct i2c_client *isp1301_i2c_client;
+
+static int __isp1301_write(struct isp1301 *isp, u8 reg, u8 value, u8 clear)
+{
+	return i2c_smbus_write_byte_data(isp->client, reg | clear, value);
+}
+
+static int isp1301_write(struct isp1301 *isp, u8 reg, u8 value)
+{
+	return __isp1301_write(isp, reg, value, 0);
+}
+
+static int isp1301_clear(struct isp1301 *isp, u8 reg, u8 value)
+{
+	return __isp1301_write(isp, reg, value, ISP1301_I2C_REG_CLEAR_ADDR);
+}
+
+static int isp1301_phy_init(struct usb_phy *phy)
+{
+	struct isp1301 *isp = phy_to_isp(phy);
+
+	/* Disable transparent UART mode first */
+	isp1301_clear(isp, ISP1301_I2C_MODE_CONTROL_1, MC1_UART_EN);
+	isp1301_clear(isp, ISP1301_I2C_MODE_CONTROL_1, ~MC1_SPEED_REG);
+	isp1301_write(isp, ISP1301_I2C_MODE_CONTROL_1, MC1_SPEED_REG);
+	isp1301_clear(isp, ISP1301_I2C_MODE_CONTROL_2, ~0);
+	isp1301_write(isp, ISP1301_I2C_MODE_CONTROL_2, (MC2_BI_DI | MC2_PSW_EN
+				| MC2_SPD_SUSP_CTRL));
+
+	isp1301_clear(isp, ISP1301_I2C_OTG_CONTROL_1, ~0);
+	isp1301_write(isp, ISP1301_I2C_MODE_CONTROL_1, MC1_DAT_SE0);
+	isp1301_write(isp, ISP1301_I2C_OTG_CONTROL_1, (OTG1_DM_PULLDOWN
+				| OTG1_DP_PULLDOWN));
+	isp1301_clear(isp, ISP1301_I2C_OTG_CONTROL_1, (OTG1_DM_PULLUP
+				| OTG1_DP_PULLUP));
+
+	/* mask all interrupts */
+	isp1301_clear(isp, ISP1301_I2C_INTERRUPT_LATCH, ~0);
+	isp1301_clear(isp, ISP1301_I2C_INTERRUPT_FALLING, ~0);
+	isp1301_clear(isp, ISP1301_I2C_INTERRUPT_RISING, ~0);
+
+	return 0;
+}
+
+static int isp1301_phy_set_vbus(struct usb_phy *phy, int on)
+{
+	struct isp1301 *isp = phy_to_isp(phy);
+
+	if (on)
+		isp1301_write(isp, ISP1301_I2C_OTG_CONTROL_1, OTG1_VBUS_DRV);
+	else
+		isp1301_clear(isp, ISP1301_I2C_OTG_CONTROL_1, OTG1_VBUS_DRV);
+
+	return 0;
+}
+
+static int isp1301_probe(struct i2c_client *client,
+			 const struct i2c_device_id *i2c_id)
+{
+	struct isp1301 *isp;
+	struct usb_phy *phy;
+
+	isp = devm_kzalloc(&client->dev, sizeof(*isp), GFP_KERNEL);
+	if (!isp)
+		return -ENOMEM;
+
+	isp->client = client;
+	mutex_init(&isp->mutex);
+
+	phy = &isp->phy;
+	phy->label = DRV_NAME;
+	phy->init = isp1301_phy_init;
+	phy->set_vbus = isp1301_phy_set_vbus;
+	phy->type = USB_PHY_TYPE_USB2;
+
+	i2c_set_clientdata(client, isp);
+	usb_add_phy_dev(phy);
+
+	isp1301_i2c_client = client;
+
+	return 0;
+}
+
+static int isp1301_remove(struct i2c_client *client)
+{
+	struct isp1301 *isp = i2c_get_clientdata(client);
+
+	usb_remove_phy(&isp->phy);
+	isp1301_i2c_client = NULL;
+
+	return 0;
+}
+
+static struct i2c_driver isp1301_driver = {
+	.driver = {
+		.name = DRV_NAME,
+	},
+	.probe = isp1301_probe,
+	.remove = isp1301_remove,
+	.id_table = isp1301_id,
+};
+
+module_i2c_driver(isp1301_driver);
+
+static int match(struct device *dev, void *data)
+{
+	struct device_node *node = (struct device_node *)data;
+	return (dev->of_node == node) &&
+		(dev->driver == &isp1301_driver.driver);
+}
+
+struct i2c_client *isp1301_get_client(struct device_node *node)
+{
+	if (node) { /* reference of ISP1301 I2C node via DT */
+		struct device *dev = bus_find_device(&i2c_bus_type, NULL,
+						     node, match);
+		if (!dev)
+			return NULL;
+		return to_i2c_client(dev);
+	} else { /* non-DT: only one ISP1301 chip supported */
+		return isp1301_i2c_client;
+	}
+}
+EXPORT_SYMBOL_GPL(isp1301_get_client);
+
+MODULE_AUTHOR("Roland Stigge <stigge@antcom.de>");
+MODULE_DESCRIPTION("NXP ISP1301 USB transceiver driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c
new file mode 100644
index 0000000..749fbf4
--- /dev/null
+++ b/drivers/usb/phy/phy-msm-usb.c
@@ -0,0 +1,1762 @@
+/* Copyright (c) 2009-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.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/uaccess.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/pm_runtime.h>
+
+#include <linux/usb.h>
+#include <linux/usb/otg.h>
+#include <linux/usb/ulpi.h>
+#include <linux/usb/gadget.h>
+#include <linux/usb/hcd.h>
+#include <linux/usb/msm_hsusb.h>
+#include <linux/usb/msm_hsusb_hw.h>
+#include <linux/regulator/consumer.h>
+
+#include <mach/clk.h>
+
+#define MSM_USB_BASE	(motg->regs)
+#define DRIVER_NAME	"msm_otg"
+
+#define ULPI_IO_TIMEOUT_USEC	(10 * 1000)
+
+#define USB_PHY_3P3_VOL_MIN	3050000 /* uV */
+#define USB_PHY_3P3_VOL_MAX	3300000 /* uV */
+#define USB_PHY_3P3_HPM_LOAD	50000	/* uA */
+#define USB_PHY_3P3_LPM_LOAD	4000	/* uA */
+
+#define USB_PHY_1P8_VOL_MIN	1800000 /* uV */
+#define USB_PHY_1P8_VOL_MAX	1800000 /* uV */
+#define USB_PHY_1P8_HPM_LOAD	50000	/* uA */
+#define USB_PHY_1P8_LPM_LOAD	4000	/* uA */
+
+#define USB_PHY_VDD_DIG_VOL_MIN	1000000 /* uV */
+#define USB_PHY_VDD_DIG_VOL_MAX	1320000 /* uV */
+
+static struct regulator *hsusb_3p3;
+static struct regulator *hsusb_1p8;
+static struct regulator *hsusb_vddcx;
+
+static int msm_hsusb_init_vddcx(struct msm_otg *motg, int init)
+{
+	int ret = 0;
+
+	if (init) {
+		hsusb_vddcx = regulator_get(motg->phy.dev, "HSUSB_VDDCX");
+		if (IS_ERR(hsusb_vddcx)) {
+			dev_err(motg->phy.dev, "unable to get hsusb vddcx\n");
+			return PTR_ERR(hsusb_vddcx);
+		}
+
+		ret = regulator_set_voltage(hsusb_vddcx,
+				USB_PHY_VDD_DIG_VOL_MIN,
+				USB_PHY_VDD_DIG_VOL_MAX);
+		if (ret) {
+			dev_err(motg->phy.dev, "unable to set the voltage "
+					"for hsusb vddcx\n");
+			regulator_put(hsusb_vddcx);
+			return ret;
+		}
+
+		ret = regulator_enable(hsusb_vddcx);
+		if (ret) {
+			dev_err(motg->phy.dev, "unable to enable hsusb vddcx\n");
+			regulator_put(hsusb_vddcx);
+		}
+	} else {
+		ret = regulator_set_voltage(hsusb_vddcx, 0,
+			USB_PHY_VDD_DIG_VOL_MAX);
+		if (ret)
+			dev_err(motg->phy.dev, "unable to set the voltage "
+					"for hsusb vddcx\n");
+		ret = regulator_disable(hsusb_vddcx);
+		if (ret)
+			dev_err(motg->phy.dev, "unable to disable hsusb vddcx\n");
+
+		regulator_put(hsusb_vddcx);
+	}
+
+	return ret;
+}
+
+static int msm_hsusb_ldo_init(struct msm_otg *motg, int init)
+{
+	int rc = 0;
+
+	if (init) {
+		hsusb_3p3 = regulator_get(motg->phy.dev, "HSUSB_3p3");
+		if (IS_ERR(hsusb_3p3)) {
+			dev_err(motg->phy.dev, "unable to get hsusb 3p3\n");
+			return PTR_ERR(hsusb_3p3);
+		}
+
+		rc = regulator_set_voltage(hsusb_3p3, USB_PHY_3P3_VOL_MIN,
+				USB_PHY_3P3_VOL_MAX);
+		if (rc) {
+			dev_err(motg->phy.dev, "unable to set voltage level "
+					"for hsusb 3p3\n");
+			goto put_3p3;
+		}
+		rc = regulator_enable(hsusb_3p3);
+		if (rc) {
+			dev_err(motg->phy.dev, "unable to enable the hsusb 3p3\n");
+			goto put_3p3;
+		}
+		hsusb_1p8 = regulator_get(motg->phy.dev, "HSUSB_1p8");
+		if (IS_ERR(hsusb_1p8)) {
+			dev_err(motg->phy.dev, "unable to get hsusb 1p8\n");
+			rc = PTR_ERR(hsusb_1p8);
+			goto disable_3p3;
+		}
+		rc = regulator_set_voltage(hsusb_1p8, USB_PHY_1P8_VOL_MIN,
+				USB_PHY_1P8_VOL_MAX);
+		if (rc) {
+			dev_err(motg->phy.dev, "unable to set voltage level "
+					"for hsusb 1p8\n");
+			goto put_1p8;
+		}
+		rc = regulator_enable(hsusb_1p8);
+		if (rc) {
+			dev_err(motg->phy.dev, "unable to enable the hsusb 1p8\n");
+			goto put_1p8;
+		}
+
+		return 0;
+	}
+
+	regulator_disable(hsusb_1p8);
+put_1p8:
+	regulator_put(hsusb_1p8);
+disable_3p3:
+	regulator_disable(hsusb_3p3);
+put_3p3:
+	regulator_put(hsusb_3p3);
+	return rc;
+}
+
+#ifdef CONFIG_PM_SLEEP
+#define USB_PHY_SUSP_DIG_VOL  500000
+static int msm_hsusb_config_vddcx(int high)
+{
+	int max_vol = USB_PHY_VDD_DIG_VOL_MAX;
+	int min_vol;
+	int ret;
+
+	if (high)
+		min_vol = USB_PHY_VDD_DIG_VOL_MIN;
+	else
+		min_vol = USB_PHY_SUSP_DIG_VOL;
+
+	ret = regulator_set_voltage(hsusb_vddcx, min_vol, max_vol);
+	if (ret) {
+		pr_err("%s: unable to set the voltage for regulator "
+			"HSUSB_VDDCX\n", __func__);
+		return ret;
+	}
+
+	pr_debug("%s: min_vol:%d max_vol:%d\n", __func__, min_vol, max_vol);
+
+	return ret;
+}
+#endif
+
+static int msm_hsusb_ldo_set_mode(int on)
+{
+	int ret = 0;
+
+	if (!hsusb_1p8 || IS_ERR(hsusb_1p8)) {
+		pr_err("%s: HSUSB_1p8 is not initialized\n", __func__);
+		return -ENODEV;
+	}
+
+	if (!hsusb_3p3 || IS_ERR(hsusb_3p3)) {
+		pr_err("%s: HSUSB_3p3 is not initialized\n", __func__);
+		return -ENODEV;
+	}
+
+	if (on) {
+		ret = regulator_set_optimum_mode(hsusb_1p8,
+				USB_PHY_1P8_HPM_LOAD);
+		if (ret < 0) {
+			pr_err("%s: Unable to set HPM of the regulator "
+				"HSUSB_1p8\n", __func__);
+			return ret;
+		}
+		ret = regulator_set_optimum_mode(hsusb_3p3,
+				USB_PHY_3P3_HPM_LOAD);
+		if (ret < 0) {
+			pr_err("%s: Unable to set HPM of the regulator "
+				"HSUSB_3p3\n", __func__);
+			regulator_set_optimum_mode(hsusb_1p8,
+				USB_PHY_1P8_LPM_LOAD);
+			return ret;
+		}
+	} else {
+		ret = regulator_set_optimum_mode(hsusb_1p8,
+				USB_PHY_1P8_LPM_LOAD);
+		if (ret < 0)
+			pr_err("%s: Unable to set LPM of the regulator "
+				"HSUSB_1p8\n", __func__);
+		ret = regulator_set_optimum_mode(hsusb_3p3,
+				USB_PHY_3P3_LPM_LOAD);
+		if (ret < 0)
+			pr_err("%s: Unable to set LPM of the regulator "
+				"HSUSB_3p3\n", __func__);
+	}
+
+	pr_debug("reg (%s)\n", on ? "HPM" : "LPM");
+	return ret < 0 ? ret : 0;
+}
+
+static int ulpi_read(struct usb_phy *phy, u32 reg)
+{
+	struct msm_otg *motg = container_of(phy, struct msm_otg, phy);
+	int cnt = 0;
+
+	/* initiate read operation */
+	writel(ULPI_RUN | ULPI_READ | ULPI_ADDR(reg),
+	       USB_ULPI_VIEWPORT);
+
+	/* wait for completion */
+	while (cnt < ULPI_IO_TIMEOUT_USEC) {
+		if (!(readl(USB_ULPI_VIEWPORT) & ULPI_RUN))
+			break;
+		udelay(1);
+		cnt++;
+	}
+
+	if (cnt >= ULPI_IO_TIMEOUT_USEC) {
+		dev_err(phy->dev, "ulpi_read: timeout %08x\n",
+			readl(USB_ULPI_VIEWPORT));
+		return -ETIMEDOUT;
+	}
+	return ULPI_DATA_READ(readl(USB_ULPI_VIEWPORT));
+}
+
+static int ulpi_write(struct usb_phy *phy, u32 val, u32 reg)
+{
+	struct msm_otg *motg = container_of(phy, struct msm_otg, phy);
+	int cnt = 0;
+
+	/* initiate write operation */
+	writel(ULPI_RUN | ULPI_WRITE |
+	       ULPI_ADDR(reg) | ULPI_DATA(val),
+	       USB_ULPI_VIEWPORT);
+
+	/* wait for completion */
+	while (cnt < ULPI_IO_TIMEOUT_USEC) {
+		if (!(readl(USB_ULPI_VIEWPORT) & ULPI_RUN))
+			break;
+		udelay(1);
+		cnt++;
+	}
+
+	if (cnt >= ULPI_IO_TIMEOUT_USEC) {
+		dev_err(phy->dev, "ulpi_write: timeout\n");
+		return -ETIMEDOUT;
+	}
+	return 0;
+}
+
+static struct usb_phy_io_ops msm_otg_io_ops = {
+	.read = ulpi_read,
+	.write = ulpi_write,
+};
+
+static void ulpi_init(struct msm_otg *motg)
+{
+	struct msm_otg_platform_data *pdata = motg->pdata;
+	int *seq = pdata->phy_init_seq;
+
+	if (!seq)
+		return;
+
+	while (seq[0] >= 0) {
+		dev_vdbg(motg->phy.dev, "ulpi: write 0x%02x to 0x%02x\n",
+				seq[0], seq[1]);
+		ulpi_write(&motg->phy, seq[0], seq[1]);
+		seq += 2;
+	}
+}
+
+static int msm_otg_link_clk_reset(struct msm_otg *motg, bool assert)
+{
+	int ret;
+
+	if (assert) {
+		ret = clk_reset(motg->clk, CLK_RESET_ASSERT);
+		if (ret)
+			dev_err(motg->phy.dev, "usb hs_clk assert failed\n");
+	} else {
+		ret = clk_reset(motg->clk, CLK_RESET_DEASSERT);
+		if (ret)
+			dev_err(motg->phy.dev, "usb hs_clk deassert failed\n");
+	}
+	return ret;
+}
+
+static int msm_otg_phy_clk_reset(struct msm_otg *motg)
+{
+	int ret;
+
+	ret = clk_reset(motg->phy_reset_clk, CLK_RESET_ASSERT);
+	if (ret) {
+		dev_err(motg->phy.dev, "usb phy clk assert failed\n");
+		return ret;
+	}
+	usleep_range(10000, 12000);
+	ret = clk_reset(motg->phy_reset_clk, CLK_RESET_DEASSERT);
+	if (ret)
+		dev_err(motg->phy.dev, "usb phy clk deassert failed\n");
+	return ret;
+}
+
+static int msm_otg_phy_reset(struct msm_otg *motg)
+{
+	u32 val;
+	int ret;
+	int retries;
+
+	ret = msm_otg_link_clk_reset(motg, 1);
+	if (ret)
+		return ret;
+	ret = msm_otg_phy_clk_reset(motg);
+	if (ret)
+		return ret;
+	ret = msm_otg_link_clk_reset(motg, 0);
+	if (ret)
+		return ret;
+
+	val = readl(USB_PORTSC) & ~PORTSC_PTS_MASK;
+	writel(val | PORTSC_PTS_ULPI, USB_PORTSC);
+
+	for (retries = 3; retries > 0; retries--) {
+		ret = ulpi_write(&motg->phy, ULPI_FUNC_CTRL_SUSPENDM,
+				ULPI_CLR(ULPI_FUNC_CTRL));
+		if (!ret)
+			break;
+		ret = msm_otg_phy_clk_reset(motg);
+		if (ret)
+			return ret;
+	}
+	if (!retries)
+		return -ETIMEDOUT;
+
+	/* This reset calibrates the phy, if the above write succeeded */
+	ret = msm_otg_phy_clk_reset(motg);
+	if (ret)
+		return ret;
+
+	for (retries = 3; retries > 0; retries--) {
+		ret = ulpi_read(&motg->phy, ULPI_DEBUG);
+		if (ret != -ETIMEDOUT)
+			break;
+		ret = msm_otg_phy_clk_reset(motg);
+		if (ret)
+			return ret;
+	}
+	if (!retries)
+		return -ETIMEDOUT;
+
+	dev_info(motg->phy.dev, "phy_reset: success\n");
+	return 0;
+}
+
+#define LINK_RESET_TIMEOUT_USEC		(250 * 1000)
+static int msm_otg_reset(struct usb_phy *phy)
+{
+	struct msm_otg *motg = container_of(phy, struct msm_otg, phy);
+	struct msm_otg_platform_data *pdata = motg->pdata;
+	int cnt = 0;
+	int ret;
+	u32 val = 0;
+	u32 ulpi_val = 0;
+
+	ret = msm_otg_phy_reset(motg);
+	if (ret) {
+		dev_err(phy->dev, "phy_reset failed\n");
+		return ret;
+	}
+
+	ulpi_init(motg);
+
+	writel(USBCMD_RESET, USB_USBCMD);
+	while (cnt < LINK_RESET_TIMEOUT_USEC) {
+		if (!(readl(USB_USBCMD) & USBCMD_RESET))
+			break;
+		udelay(1);
+		cnt++;
+	}
+	if (cnt >= LINK_RESET_TIMEOUT_USEC)
+		return -ETIMEDOUT;
+
+	/* select ULPI phy */
+	writel(0x80000000, USB_PORTSC);
+
+	msleep(100);
+
+	writel(0x0, USB_AHBBURST);
+	writel(0x00, USB_AHBMODE);
+
+	if (pdata->otg_control == OTG_PHY_CONTROL) {
+		val = readl(USB_OTGSC);
+		if (pdata->mode == USB_OTG) {
+			ulpi_val = ULPI_INT_IDGRD | ULPI_INT_SESS_VALID;
+			val |= OTGSC_IDIE | OTGSC_BSVIE;
+		} else if (pdata->mode == USB_PERIPHERAL) {
+			ulpi_val = ULPI_INT_SESS_VALID;
+			val |= OTGSC_BSVIE;
+		}
+		writel(val, USB_OTGSC);
+		ulpi_write(phy, ulpi_val, ULPI_USB_INT_EN_RISE);
+		ulpi_write(phy, ulpi_val, ULPI_USB_INT_EN_FALL);
+	}
+
+	return 0;
+}
+
+#define PHY_SUSPEND_TIMEOUT_USEC	(500 * 1000)
+#define PHY_RESUME_TIMEOUT_USEC	(100 * 1000)
+
+#ifdef CONFIG_PM_SLEEP
+static int msm_otg_suspend(struct msm_otg *motg)
+{
+	struct usb_phy *phy = &motg->phy;
+	struct usb_bus *bus = phy->otg->host;
+	struct msm_otg_platform_data *pdata = motg->pdata;
+	int cnt = 0;
+
+	if (atomic_read(&motg->in_lpm))
+		return 0;
+
+	disable_irq(motg->irq);
+	/*
+	 * Chipidea 45-nm PHY suspend sequence:
+	 *
+	 * Interrupt Latch Register auto-clear feature is not present
+	 * in all PHY versions. Latch register is clear on read type.
+	 * Clear latch register to avoid spurious wakeup from
+	 * low power mode (LPM).
+	 *
+	 * PHY comparators are disabled when PHY enters into low power
+	 * mode (LPM). Keep PHY comparators ON in LPM only when we expect
+	 * VBUS/Id notifications from USB PHY. Otherwise turn off USB
+	 * PHY comparators. This save significant amount of power.
+	 *
+	 * PLL is not turned off when PHY enters into low power mode (LPM).
+	 * Disable PLL for maximum power savings.
+	 */
+
+	if (motg->pdata->phy_type == CI_45NM_INTEGRATED_PHY) {
+		ulpi_read(phy, 0x14);
+		if (pdata->otg_control == OTG_PHY_CONTROL)
+			ulpi_write(phy, 0x01, 0x30);
+		ulpi_write(phy, 0x08, 0x09);
+	}
+
+	/*
+	 * PHY may take some time or even fail to enter into low power
+	 * mode (LPM). Hence poll for 500 msec and reset the PHY and link
+	 * in failure case.
+	 */
+	writel(readl(USB_PORTSC) | PORTSC_PHCD, USB_PORTSC);
+	while (cnt < PHY_SUSPEND_TIMEOUT_USEC) {
+		if (readl(USB_PORTSC) & PORTSC_PHCD)
+			break;
+		udelay(1);
+		cnt++;
+	}
+
+	if (cnt >= PHY_SUSPEND_TIMEOUT_USEC) {
+		dev_err(phy->dev, "Unable to suspend PHY\n");
+		msm_otg_reset(phy);
+		enable_irq(motg->irq);
+		return -ETIMEDOUT;
+	}
+
+	/*
+	 * PHY has capability to generate interrupt asynchronously in low
+	 * power mode (LPM). This interrupt is level triggered. So USB IRQ
+	 * line must be disabled till async interrupt enable bit is cleared
+	 * in USBCMD register. Assert STP (ULPI interface STOP signal) to
+	 * block data communication from PHY.
+	 */
+	writel(readl(USB_USBCMD) | ASYNC_INTR_CTRL | ULPI_STP_CTRL, USB_USBCMD);
+
+	if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY &&
+			motg->pdata->otg_control == OTG_PMIC_CONTROL)
+		writel(readl(USB_PHY_CTRL) | PHY_RETEN, USB_PHY_CTRL);
+
+	clk_disable(motg->pclk);
+	clk_disable(motg->clk);
+	if (motg->core_clk)
+		clk_disable(motg->core_clk);
+
+	if (!IS_ERR(motg->pclk_src))
+		clk_disable(motg->pclk_src);
+
+	if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY &&
+			motg->pdata->otg_control == OTG_PMIC_CONTROL) {
+		msm_hsusb_ldo_set_mode(0);
+		msm_hsusb_config_vddcx(0);
+	}
+
+	if (device_may_wakeup(phy->dev))
+		enable_irq_wake(motg->irq);
+	if (bus)
+		clear_bit(HCD_FLAG_HW_ACCESSIBLE, &(bus_to_hcd(bus))->flags);
+
+	atomic_set(&motg->in_lpm, 1);
+	enable_irq(motg->irq);
+
+	dev_info(phy->dev, "USB in low power mode\n");
+
+	return 0;
+}
+
+static int msm_otg_resume(struct msm_otg *motg)
+{
+	struct usb_phy *phy = &motg->phy;
+	struct usb_bus *bus = phy->otg->host;
+	int cnt = 0;
+	unsigned temp;
+
+	if (!atomic_read(&motg->in_lpm))
+		return 0;
+
+	if (!IS_ERR(motg->pclk_src))
+		clk_enable(motg->pclk_src);
+
+	clk_enable(motg->pclk);
+	clk_enable(motg->clk);
+	if (motg->core_clk)
+		clk_enable(motg->core_clk);
+
+	if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY &&
+			motg->pdata->otg_control == OTG_PMIC_CONTROL) {
+		msm_hsusb_ldo_set_mode(1);
+		msm_hsusb_config_vddcx(1);
+		writel(readl(USB_PHY_CTRL) & ~PHY_RETEN, USB_PHY_CTRL);
+	}
+
+	temp = readl(USB_USBCMD);
+	temp &= ~ASYNC_INTR_CTRL;
+	temp &= ~ULPI_STP_CTRL;
+	writel(temp, USB_USBCMD);
+
+	/*
+	 * PHY comes out of low power mode (LPM) in case of wakeup
+	 * from asynchronous interrupt.
+	 */
+	if (!(readl(USB_PORTSC) & PORTSC_PHCD))
+		goto skip_phy_resume;
+
+	writel(readl(USB_PORTSC) & ~PORTSC_PHCD, USB_PORTSC);
+	while (cnt < PHY_RESUME_TIMEOUT_USEC) {
+		if (!(readl(USB_PORTSC) & PORTSC_PHCD))
+			break;
+		udelay(1);
+		cnt++;
+	}
+
+	if (cnt >= PHY_RESUME_TIMEOUT_USEC) {
+		/*
+		 * This is a fatal error. Reset the link and
+		 * PHY. USB state can not be restored. Re-insertion
+		 * of USB cable is the only way to get USB working.
+		 */
+		dev_err(phy->dev, "Unable to resume USB."
+				"Re-plugin the cable\n");
+		msm_otg_reset(phy);
+	}
+
+skip_phy_resume:
+	if (device_may_wakeup(phy->dev))
+		disable_irq_wake(motg->irq);
+	if (bus)
+		set_bit(HCD_FLAG_HW_ACCESSIBLE, &(bus_to_hcd(bus))->flags);
+
+	atomic_set(&motg->in_lpm, 0);
+
+	if (motg->async_int) {
+		motg->async_int = 0;
+		pm_runtime_put(phy->dev);
+		enable_irq(motg->irq);
+	}
+
+	dev_info(phy->dev, "USB exited from low power mode\n");
+
+	return 0;
+}
+#endif
+
+static void msm_otg_notify_charger(struct msm_otg *motg, unsigned mA)
+{
+	if (motg->cur_power == mA)
+		return;
+
+	/* TODO: Notify PMIC about available current */
+	dev_info(motg->phy.dev, "Avail curr from USB = %u\n", mA);
+	motg->cur_power = mA;
+}
+
+static int msm_otg_set_power(struct usb_phy *phy, unsigned mA)
+{
+	struct msm_otg *motg = container_of(phy, struct msm_otg, phy);
+
+	/*
+	 * Gadget driver uses set_power method to notify about the
+	 * available current based on suspend/configured states.
+	 *
+	 * IDEV_CHG can be drawn irrespective of suspend/un-configured
+	 * states when CDP/ACA is connected.
+	 */
+	if (motg->chg_type == USB_SDP_CHARGER)
+		msm_otg_notify_charger(motg, mA);
+
+	return 0;
+}
+
+static void msm_otg_start_host(struct usb_phy *phy, int on)
+{
+	struct msm_otg *motg = container_of(phy, struct msm_otg, phy);
+	struct msm_otg_platform_data *pdata = motg->pdata;
+	struct usb_hcd *hcd;
+
+	if (!phy->otg->host)
+		return;
+
+	hcd = bus_to_hcd(phy->otg->host);
+
+	if (on) {
+		dev_dbg(phy->dev, "host on\n");
+
+		if (pdata->vbus_power)
+			pdata->vbus_power(1);
+		/*
+		 * Some boards have a switch cotrolled by gpio
+		 * to enable/disable internal HUB. Enable internal
+		 * HUB before kicking the host.
+		 */
+		if (pdata->setup_gpio)
+			pdata->setup_gpio(OTG_STATE_A_HOST);
+#ifdef CONFIG_USB
+		usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
+#endif
+	} else {
+		dev_dbg(phy->dev, "host off\n");
+
+#ifdef CONFIG_USB
+		usb_remove_hcd(hcd);
+#endif
+		if (pdata->setup_gpio)
+			pdata->setup_gpio(OTG_STATE_UNDEFINED);
+		if (pdata->vbus_power)
+			pdata->vbus_power(0);
+	}
+}
+
+static int msm_otg_set_host(struct usb_otg *otg, struct usb_bus *host)
+{
+	struct msm_otg *motg = container_of(otg->phy, struct msm_otg, phy);
+	struct usb_hcd *hcd;
+
+	/*
+	 * Fail host registration if this board can support
+	 * only peripheral configuration.
+	 */
+	if (motg->pdata->mode == USB_PERIPHERAL) {
+		dev_info(otg->phy->dev, "Host mode is not supported\n");
+		return -ENODEV;
+	}
+
+	if (!host) {
+		if (otg->phy->state == OTG_STATE_A_HOST) {
+			pm_runtime_get_sync(otg->phy->dev);
+			msm_otg_start_host(otg->phy, 0);
+			otg->host = NULL;
+			otg->phy->state = OTG_STATE_UNDEFINED;
+			schedule_work(&motg->sm_work);
+		} else {
+			otg->host = NULL;
+		}
+
+		return 0;
+	}
+
+	hcd = bus_to_hcd(host);
+	hcd->power_budget = motg->pdata->power_budget;
+
+	otg->host = host;
+	dev_dbg(otg->phy->dev, "host driver registered w/ tranceiver\n");
+
+	/*
+	 * Kick the state machine work, if peripheral is not supported
+	 * or peripheral is already registered with us.
+	 */
+	if (motg->pdata->mode == USB_HOST || otg->gadget) {
+		pm_runtime_get_sync(otg->phy->dev);
+		schedule_work(&motg->sm_work);
+	}
+
+	return 0;
+}
+
+static void msm_otg_start_peripheral(struct usb_phy *phy, int on)
+{
+	struct msm_otg *motg = container_of(phy, struct msm_otg, phy);
+	struct msm_otg_platform_data *pdata = motg->pdata;
+
+	if (!phy->otg->gadget)
+		return;
+
+	if (on) {
+		dev_dbg(phy->dev, "gadget on\n");
+		/*
+		 * Some boards have a switch cotrolled by gpio
+		 * to enable/disable internal HUB. Disable internal
+		 * HUB before kicking the gadget.
+		 */
+		if (pdata->setup_gpio)
+			pdata->setup_gpio(OTG_STATE_B_PERIPHERAL);
+		usb_gadget_vbus_connect(phy->otg->gadget);
+	} else {
+		dev_dbg(phy->dev, "gadget off\n");
+		usb_gadget_vbus_disconnect(phy->otg->gadget);
+		if (pdata->setup_gpio)
+			pdata->setup_gpio(OTG_STATE_UNDEFINED);
+	}
+
+}
+
+static int msm_otg_set_peripheral(struct usb_otg *otg,
+					struct usb_gadget *gadget)
+{
+	struct msm_otg *motg = container_of(otg->phy, struct msm_otg, phy);
+
+	/*
+	 * Fail peripheral registration if this board can support
+	 * only host configuration.
+	 */
+	if (motg->pdata->mode == USB_HOST) {
+		dev_info(otg->phy->dev, "Peripheral mode is not supported\n");
+		return -ENODEV;
+	}
+
+	if (!gadget) {
+		if (otg->phy->state == OTG_STATE_B_PERIPHERAL) {
+			pm_runtime_get_sync(otg->phy->dev);
+			msm_otg_start_peripheral(otg->phy, 0);
+			otg->gadget = NULL;
+			otg->phy->state = OTG_STATE_UNDEFINED;
+			schedule_work(&motg->sm_work);
+		} else {
+			otg->gadget = NULL;
+		}
+
+		return 0;
+	}
+	otg->gadget = gadget;
+	dev_dbg(otg->phy->dev, "peripheral driver registered w/ tranceiver\n");
+
+	/*
+	 * Kick the state machine work, if host is not supported
+	 * or host is already registered with us.
+	 */
+	if (motg->pdata->mode == USB_PERIPHERAL || otg->host) {
+		pm_runtime_get_sync(otg->phy->dev);
+		schedule_work(&motg->sm_work);
+	}
+
+	return 0;
+}
+
+static bool msm_chg_check_secondary_det(struct msm_otg *motg)
+{
+	struct usb_phy *phy = &motg->phy;
+	u32 chg_det;
+	bool ret = false;
+
+	switch (motg->pdata->phy_type) {
+	case CI_45NM_INTEGRATED_PHY:
+		chg_det = ulpi_read(phy, 0x34);
+		ret = chg_det & (1 << 4);
+		break;
+	case SNPS_28NM_INTEGRATED_PHY:
+		chg_det = ulpi_read(phy, 0x87);
+		ret = chg_det & 1;
+		break;
+	default:
+		break;
+	}
+	return ret;
+}
+
+static void msm_chg_enable_secondary_det(struct msm_otg *motg)
+{
+	struct usb_phy *phy = &motg->phy;
+	u32 chg_det;
+
+	switch (motg->pdata->phy_type) {
+	case CI_45NM_INTEGRATED_PHY:
+		chg_det = ulpi_read(phy, 0x34);
+		/* Turn off charger block */
+		chg_det |= ~(1 << 1);
+		ulpi_write(phy, chg_det, 0x34);
+		udelay(20);
+		/* control chg block via ULPI */
+		chg_det &= ~(1 << 3);
+		ulpi_write(phy, chg_det, 0x34);
+		/* put it in host mode for enabling D- source */
+		chg_det &= ~(1 << 2);
+		ulpi_write(phy, chg_det, 0x34);
+		/* Turn on chg detect block */
+		chg_det &= ~(1 << 1);
+		ulpi_write(phy, chg_det, 0x34);
+		udelay(20);
+		/* enable chg detection */
+		chg_det &= ~(1 << 0);
+		ulpi_write(phy, chg_det, 0x34);
+		break;
+	case SNPS_28NM_INTEGRATED_PHY:
+		/*
+		 * Configure DM as current source, DP as current sink
+		 * and enable battery charging comparators.
+		 */
+		ulpi_write(phy, 0x8, 0x85);
+		ulpi_write(phy, 0x2, 0x85);
+		ulpi_write(phy, 0x1, 0x85);
+		break;
+	default:
+		break;
+	}
+}
+
+static bool msm_chg_check_primary_det(struct msm_otg *motg)
+{
+	struct usb_phy *phy = &motg->phy;
+	u32 chg_det;
+	bool ret = false;
+
+	switch (motg->pdata->phy_type) {
+	case CI_45NM_INTEGRATED_PHY:
+		chg_det = ulpi_read(phy, 0x34);
+		ret = chg_det & (1 << 4);
+		break;
+	case SNPS_28NM_INTEGRATED_PHY:
+		chg_det = ulpi_read(phy, 0x87);
+		ret = chg_det & 1;
+		break;
+	default:
+		break;
+	}
+	return ret;
+}
+
+static void msm_chg_enable_primary_det(struct msm_otg *motg)
+{
+	struct usb_phy *phy = &motg->phy;
+	u32 chg_det;
+
+	switch (motg->pdata->phy_type) {
+	case CI_45NM_INTEGRATED_PHY:
+		chg_det = ulpi_read(phy, 0x34);
+		/* enable chg detection */
+		chg_det &= ~(1 << 0);
+		ulpi_write(phy, chg_det, 0x34);
+		break;
+	case SNPS_28NM_INTEGRATED_PHY:
+		/*
+		 * Configure DP as current source, DM as current sink
+		 * and enable battery charging comparators.
+		 */
+		ulpi_write(phy, 0x2, 0x85);
+		ulpi_write(phy, 0x1, 0x85);
+		break;
+	default:
+		break;
+	}
+}
+
+static bool msm_chg_check_dcd(struct msm_otg *motg)
+{
+	struct usb_phy *phy = &motg->phy;
+	u32 line_state;
+	bool ret = false;
+
+	switch (motg->pdata->phy_type) {
+	case CI_45NM_INTEGRATED_PHY:
+		line_state = ulpi_read(phy, 0x15);
+		ret = !(line_state & 1);
+		break;
+	case SNPS_28NM_INTEGRATED_PHY:
+		line_state = ulpi_read(phy, 0x87);
+		ret = line_state & 2;
+		break;
+	default:
+		break;
+	}
+	return ret;
+}
+
+static void msm_chg_disable_dcd(struct msm_otg *motg)
+{
+	struct usb_phy *phy = &motg->phy;
+	u32 chg_det;
+
+	switch (motg->pdata->phy_type) {
+	case CI_45NM_INTEGRATED_PHY:
+		chg_det = ulpi_read(phy, 0x34);
+		chg_det &= ~(1 << 5);
+		ulpi_write(phy, chg_det, 0x34);
+		break;
+	case SNPS_28NM_INTEGRATED_PHY:
+		ulpi_write(phy, 0x10, 0x86);
+		break;
+	default:
+		break;
+	}
+}
+
+static void msm_chg_enable_dcd(struct msm_otg *motg)
+{
+	struct usb_phy *phy = &motg->phy;
+	u32 chg_det;
+
+	switch (motg->pdata->phy_type) {
+	case CI_45NM_INTEGRATED_PHY:
+		chg_det = ulpi_read(phy, 0x34);
+		/* Turn on D+ current source */
+		chg_det |= (1 << 5);
+		ulpi_write(phy, chg_det, 0x34);
+		break;
+	case SNPS_28NM_INTEGRATED_PHY:
+		/* Data contact detection enable */
+		ulpi_write(phy, 0x10, 0x85);
+		break;
+	default:
+		break;
+	}
+}
+
+static void msm_chg_block_on(struct msm_otg *motg)
+{
+	struct usb_phy *phy = &motg->phy;
+	u32 func_ctrl, chg_det;
+
+	/* put the controller in non-driving mode */
+	func_ctrl = ulpi_read(phy, ULPI_FUNC_CTRL);
+	func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
+	func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING;
+	ulpi_write(phy, func_ctrl, ULPI_FUNC_CTRL);
+
+	switch (motg->pdata->phy_type) {
+	case CI_45NM_INTEGRATED_PHY:
+		chg_det = ulpi_read(phy, 0x34);
+		/* control chg block via ULPI */
+		chg_det &= ~(1 << 3);
+		ulpi_write(phy, chg_det, 0x34);
+		/* Turn on chg detect block */
+		chg_det &= ~(1 << 1);
+		ulpi_write(phy, chg_det, 0x34);
+		udelay(20);
+		break;
+	case SNPS_28NM_INTEGRATED_PHY:
+		/* Clear charger detecting control bits */
+		ulpi_write(phy, 0x3F, 0x86);
+		/* Clear alt interrupt latch and enable bits */
+		ulpi_write(phy, 0x1F, 0x92);
+		ulpi_write(phy, 0x1F, 0x95);
+		udelay(100);
+		break;
+	default:
+		break;
+	}
+}
+
+static void msm_chg_block_off(struct msm_otg *motg)
+{
+	struct usb_phy *phy = &motg->phy;
+	u32 func_ctrl, chg_det;
+
+	switch (motg->pdata->phy_type) {
+	case CI_45NM_INTEGRATED_PHY:
+		chg_det = ulpi_read(phy, 0x34);
+		/* Turn off charger block */
+		chg_det |= ~(1 << 1);
+		ulpi_write(phy, chg_det, 0x34);
+		break;
+	case SNPS_28NM_INTEGRATED_PHY:
+		/* Clear charger detecting control bits */
+		ulpi_write(phy, 0x3F, 0x86);
+		/* Clear alt interrupt latch and enable bits */
+		ulpi_write(phy, 0x1F, 0x92);
+		ulpi_write(phy, 0x1F, 0x95);
+		break;
+	default:
+		break;
+	}
+
+	/* put the controller in normal mode */
+	func_ctrl = ulpi_read(phy, ULPI_FUNC_CTRL);
+	func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
+	func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NORMAL;
+	ulpi_write(phy, func_ctrl, ULPI_FUNC_CTRL);
+}
+
+#define MSM_CHG_DCD_POLL_TIME		(100 * HZ/1000) /* 100 msec */
+#define MSM_CHG_DCD_MAX_RETRIES		6 /* Tdcd_tmout = 6 * 100 msec */
+#define MSM_CHG_PRIMARY_DET_TIME	(40 * HZ/1000) /* TVDPSRC_ON */
+#define MSM_CHG_SECONDARY_DET_TIME	(40 * HZ/1000) /* TVDMSRC_ON */
+static void msm_chg_detect_work(struct work_struct *w)
+{
+	struct msm_otg *motg = container_of(w, struct msm_otg, chg_work.work);
+	struct usb_phy *phy = &motg->phy;
+	bool is_dcd, tmout, vout;
+	unsigned long delay;
+
+	dev_dbg(phy->dev, "chg detection work\n");
+	switch (motg->chg_state) {
+	case USB_CHG_STATE_UNDEFINED:
+		pm_runtime_get_sync(phy->dev);
+		msm_chg_block_on(motg);
+		msm_chg_enable_dcd(motg);
+		motg->chg_state = USB_CHG_STATE_WAIT_FOR_DCD;
+		motg->dcd_retries = 0;
+		delay = MSM_CHG_DCD_POLL_TIME;
+		break;
+	case USB_CHG_STATE_WAIT_FOR_DCD:
+		is_dcd = msm_chg_check_dcd(motg);
+		tmout = ++motg->dcd_retries == MSM_CHG_DCD_MAX_RETRIES;
+		if (is_dcd || tmout) {
+			msm_chg_disable_dcd(motg);
+			msm_chg_enable_primary_det(motg);
+			delay = MSM_CHG_PRIMARY_DET_TIME;
+			motg->chg_state = USB_CHG_STATE_DCD_DONE;
+		} else {
+			delay = MSM_CHG_DCD_POLL_TIME;
+		}
+		break;
+	case USB_CHG_STATE_DCD_DONE:
+		vout = msm_chg_check_primary_det(motg);
+		if (vout) {
+			msm_chg_enable_secondary_det(motg);
+			delay = MSM_CHG_SECONDARY_DET_TIME;
+			motg->chg_state = USB_CHG_STATE_PRIMARY_DONE;
+		} else {
+			motg->chg_type = USB_SDP_CHARGER;
+			motg->chg_state = USB_CHG_STATE_DETECTED;
+			delay = 0;
+		}
+		break;
+	case USB_CHG_STATE_PRIMARY_DONE:
+		vout = msm_chg_check_secondary_det(motg);
+		if (vout)
+			motg->chg_type = USB_DCP_CHARGER;
+		else
+			motg->chg_type = USB_CDP_CHARGER;
+		motg->chg_state = USB_CHG_STATE_SECONDARY_DONE;
+		/* fall through */
+	case USB_CHG_STATE_SECONDARY_DONE:
+		motg->chg_state = USB_CHG_STATE_DETECTED;
+	case USB_CHG_STATE_DETECTED:
+		msm_chg_block_off(motg);
+		dev_dbg(phy->dev, "charger = %d\n", motg->chg_type);
+		schedule_work(&motg->sm_work);
+		return;
+	default:
+		return;
+	}
+
+	schedule_delayed_work(&motg->chg_work, delay);
+}
+
+/*
+ * We support OTG, Peripheral only and Host only configurations. In case
+ * of OTG, mode switch (host-->peripheral/peripheral-->host) can happen
+ * via Id pin status or user request (debugfs). Id/BSV interrupts are not
+ * enabled when switch is controlled by user and default mode is supplied
+ * by board file, which can be changed by userspace later.
+ */
+static void msm_otg_init_sm(struct msm_otg *motg)
+{
+	struct msm_otg_platform_data *pdata = motg->pdata;
+	u32 otgsc = readl(USB_OTGSC);
+
+	switch (pdata->mode) {
+	case USB_OTG:
+		if (pdata->otg_control == OTG_PHY_CONTROL) {
+			if (otgsc & OTGSC_ID)
+				set_bit(ID, &motg->inputs);
+			else
+				clear_bit(ID, &motg->inputs);
+
+			if (otgsc & OTGSC_BSV)
+				set_bit(B_SESS_VLD, &motg->inputs);
+			else
+				clear_bit(B_SESS_VLD, &motg->inputs);
+		} else if (pdata->otg_control == OTG_USER_CONTROL) {
+			if (pdata->default_mode == USB_HOST) {
+				clear_bit(ID, &motg->inputs);
+			} else if (pdata->default_mode == USB_PERIPHERAL) {
+				set_bit(ID, &motg->inputs);
+				set_bit(B_SESS_VLD, &motg->inputs);
+			} else {
+				set_bit(ID, &motg->inputs);
+				clear_bit(B_SESS_VLD, &motg->inputs);
+			}
+		}
+		break;
+	case USB_HOST:
+		clear_bit(ID, &motg->inputs);
+		break;
+	case USB_PERIPHERAL:
+		set_bit(ID, &motg->inputs);
+		if (otgsc & OTGSC_BSV)
+			set_bit(B_SESS_VLD, &motg->inputs);
+		else
+			clear_bit(B_SESS_VLD, &motg->inputs);
+		break;
+	default:
+		break;
+	}
+}
+
+static void msm_otg_sm_work(struct work_struct *w)
+{
+	struct msm_otg *motg = container_of(w, struct msm_otg, sm_work);
+	struct usb_otg *otg = motg->phy.otg;
+
+	switch (otg->phy->state) {
+	case OTG_STATE_UNDEFINED:
+		dev_dbg(otg->phy->dev, "OTG_STATE_UNDEFINED state\n");
+		msm_otg_reset(otg->phy);
+		msm_otg_init_sm(motg);
+		otg->phy->state = OTG_STATE_B_IDLE;
+		/* FALL THROUGH */
+	case OTG_STATE_B_IDLE:
+		dev_dbg(otg->phy->dev, "OTG_STATE_B_IDLE state\n");
+		if (!test_bit(ID, &motg->inputs) && otg->host) {
+			/* disable BSV bit */
+			writel(readl(USB_OTGSC) & ~OTGSC_BSVIE, USB_OTGSC);
+			msm_otg_start_host(otg->phy, 1);
+			otg->phy->state = OTG_STATE_A_HOST;
+		} else if (test_bit(B_SESS_VLD, &motg->inputs)) {
+			switch (motg->chg_state) {
+			case USB_CHG_STATE_UNDEFINED:
+				msm_chg_detect_work(&motg->chg_work.work);
+				break;
+			case USB_CHG_STATE_DETECTED:
+				switch (motg->chg_type) {
+				case USB_DCP_CHARGER:
+					msm_otg_notify_charger(motg,
+							IDEV_CHG_MAX);
+					break;
+				case USB_CDP_CHARGER:
+					msm_otg_notify_charger(motg,
+							IDEV_CHG_MAX);
+					msm_otg_start_peripheral(otg->phy, 1);
+					otg->phy->state
+						= OTG_STATE_B_PERIPHERAL;
+					break;
+				case USB_SDP_CHARGER:
+					msm_otg_notify_charger(motg, IUNIT);
+					msm_otg_start_peripheral(otg->phy, 1);
+					otg->phy->state
+						= OTG_STATE_B_PERIPHERAL;
+					break;
+				default:
+					break;
+				}
+				break;
+			default:
+				break;
+			}
+		} else {
+			/*
+			 * If charger detection work is pending, decrement
+			 * the pm usage counter to balance with the one that
+			 * is incremented in charger detection work.
+			 */
+			if (cancel_delayed_work_sync(&motg->chg_work)) {
+				pm_runtime_put_sync(otg->phy->dev);
+				msm_otg_reset(otg->phy);
+			}
+			msm_otg_notify_charger(motg, 0);
+			motg->chg_state = USB_CHG_STATE_UNDEFINED;
+			motg->chg_type = USB_INVALID_CHARGER;
+		}
+		pm_runtime_put_sync(otg->phy->dev);
+		break;
+	case OTG_STATE_B_PERIPHERAL:
+		dev_dbg(otg->phy->dev, "OTG_STATE_B_PERIPHERAL state\n");
+		if (!test_bit(B_SESS_VLD, &motg->inputs) ||
+				!test_bit(ID, &motg->inputs)) {
+			msm_otg_notify_charger(motg, 0);
+			msm_otg_start_peripheral(otg->phy, 0);
+			motg->chg_state = USB_CHG_STATE_UNDEFINED;
+			motg->chg_type = USB_INVALID_CHARGER;
+			otg->phy->state = OTG_STATE_B_IDLE;
+			msm_otg_reset(otg->phy);
+			schedule_work(w);
+		}
+		break;
+	case OTG_STATE_A_HOST:
+		dev_dbg(otg->phy->dev, "OTG_STATE_A_HOST state\n");
+		if (test_bit(ID, &motg->inputs)) {
+			msm_otg_start_host(otg->phy, 0);
+			otg->phy->state = OTG_STATE_B_IDLE;
+			msm_otg_reset(otg->phy);
+			schedule_work(w);
+		}
+		break;
+	default:
+		break;
+	}
+}
+
+static irqreturn_t msm_otg_irq(int irq, void *data)
+{
+	struct msm_otg *motg = data;
+	struct usb_phy *phy = &motg->phy;
+	u32 otgsc = 0;
+
+	if (atomic_read(&motg->in_lpm)) {
+		disable_irq_nosync(irq);
+		motg->async_int = 1;
+		pm_runtime_get(phy->dev);
+		return IRQ_HANDLED;
+	}
+
+	otgsc = readl(USB_OTGSC);
+	if (!(otgsc & (OTGSC_IDIS | OTGSC_BSVIS)))
+		return IRQ_NONE;
+
+	if ((otgsc & OTGSC_IDIS) && (otgsc & OTGSC_IDIE)) {
+		if (otgsc & OTGSC_ID)
+			set_bit(ID, &motg->inputs);
+		else
+			clear_bit(ID, &motg->inputs);
+		dev_dbg(phy->dev, "ID set/clear\n");
+		pm_runtime_get_noresume(phy->dev);
+	} else if ((otgsc & OTGSC_BSVIS) && (otgsc & OTGSC_BSVIE)) {
+		if (otgsc & OTGSC_BSV)
+			set_bit(B_SESS_VLD, &motg->inputs);
+		else
+			clear_bit(B_SESS_VLD, &motg->inputs);
+		dev_dbg(phy->dev, "BSV set/clear\n");
+		pm_runtime_get_noresume(phy->dev);
+	}
+
+	writel(otgsc, USB_OTGSC);
+	schedule_work(&motg->sm_work);
+	return IRQ_HANDLED;
+}
+
+static int msm_otg_mode_show(struct seq_file *s, void *unused)
+{
+	struct msm_otg *motg = s->private;
+	struct usb_otg *otg = motg->phy.otg;
+
+	switch (otg->phy->state) {
+	case OTG_STATE_A_HOST:
+		seq_printf(s, "host\n");
+		break;
+	case OTG_STATE_B_PERIPHERAL:
+		seq_printf(s, "peripheral\n");
+		break;
+	default:
+		seq_printf(s, "none\n");
+		break;
+	}
+
+	return 0;
+}
+
+static int msm_otg_mode_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, msm_otg_mode_show, inode->i_private);
+}
+
+static ssize_t msm_otg_mode_write(struct file *file, const char __user *ubuf,
+				size_t count, loff_t *ppos)
+{
+	struct seq_file *s = file->private_data;
+	struct msm_otg *motg = s->private;
+	char buf[16];
+	struct usb_otg *otg = motg->phy.otg;
+	int status = count;
+	enum usb_mode_type req_mode;
+
+	memset(buf, 0x00, sizeof(buf));
+
+	if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) {
+		status = -EFAULT;
+		goto out;
+	}
+
+	if (!strncmp(buf, "host", 4)) {
+		req_mode = USB_HOST;
+	} else if (!strncmp(buf, "peripheral", 10)) {
+		req_mode = USB_PERIPHERAL;
+	} else if (!strncmp(buf, "none", 4)) {
+		req_mode = USB_NONE;
+	} else {
+		status = -EINVAL;
+		goto out;
+	}
+
+	switch (req_mode) {
+	case USB_NONE:
+		switch (otg->phy->state) {
+		case OTG_STATE_A_HOST:
+		case OTG_STATE_B_PERIPHERAL:
+			set_bit(ID, &motg->inputs);
+			clear_bit(B_SESS_VLD, &motg->inputs);
+			break;
+		default:
+			goto out;
+		}
+		break;
+	case USB_PERIPHERAL:
+		switch (otg->phy->state) {
+		case OTG_STATE_B_IDLE:
+		case OTG_STATE_A_HOST:
+			set_bit(ID, &motg->inputs);
+			set_bit(B_SESS_VLD, &motg->inputs);
+			break;
+		default:
+			goto out;
+		}
+		break;
+	case USB_HOST:
+		switch (otg->phy->state) {
+		case OTG_STATE_B_IDLE:
+		case OTG_STATE_B_PERIPHERAL:
+			clear_bit(ID, &motg->inputs);
+			break;
+		default:
+			goto out;
+		}
+		break;
+	default:
+		goto out;
+	}
+
+	pm_runtime_get_sync(otg->phy->dev);
+	schedule_work(&motg->sm_work);
+out:
+	return status;
+}
+
+const struct file_operations msm_otg_mode_fops = {
+	.open = msm_otg_mode_open,
+	.read = seq_read,
+	.write = msm_otg_mode_write,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
+static struct dentry *msm_otg_dbg_root;
+static struct dentry *msm_otg_dbg_mode;
+
+static int msm_otg_debugfs_init(struct msm_otg *motg)
+{
+	msm_otg_dbg_root = debugfs_create_dir("msm_otg", NULL);
+
+	if (!msm_otg_dbg_root || IS_ERR(msm_otg_dbg_root))
+		return -ENODEV;
+
+	msm_otg_dbg_mode = debugfs_create_file("mode", S_IRUGO | S_IWUSR,
+				msm_otg_dbg_root, motg, &msm_otg_mode_fops);
+	if (!msm_otg_dbg_mode) {
+		debugfs_remove(msm_otg_dbg_root);
+		msm_otg_dbg_root = NULL;
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static void msm_otg_debugfs_cleanup(void)
+{
+	debugfs_remove(msm_otg_dbg_mode);
+	debugfs_remove(msm_otg_dbg_root);
+}
+
+static int __init msm_otg_probe(struct platform_device *pdev)
+{
+	int ret = 0;
+	struct resource *res;
+	struct msm_otg *motg;
+	struct usb_phy *phy;
+
+	dev_info(&pdev->dev, "msm_otg probe\n");
+	if (!pdev->dev.platform_data) {
+		dev_err(&pdev->dev, "No platform data given. Bailing out\n");
+		return -ENODEV;
+	}
+
+	motg = kzalloc(sizeof(struct msm_otg), GFP_KERNEL);
+	if (!motg) {
+		dev_err(&pdev->dev, "unable to allocate msm_otg\n");
+		return -ENOMEM;
+	}
+
+	motg->phy.otg = kzalloc(sizeof(struct usb_otg), GFP_KERNEL);
+	if (!motg->phy.otg) {
+		dev_err(&pdev->dev, "unable to allocate msm_otg\n");
+		return -ENOMEM;
+	}
+
+	motg->pdata = pdev->dev.platform_data;
+	phy = &motg->phy;
+	phy->dev = &pdev->dev;
+
+	motg->phy_reset_clk = clk_get(&pdev->dev, "usb_phy_clk");
+	if (IS_ERR(motg->phy_reset_clk)) {
+		dev_err(&pdev->dev, "failed to get usb_phy_clk\n");
+		ret = PTR_ERR(motg->phy_reset_clk);
+		goto free_motg;
+	}
+
+	motg->clk = clk_get(&pdev->dev, "usb_hs_clk");
+	if (IS_ERR(motg->clk)) {
+		dev_err(&pdev->dev, "failed to get usb_hs_clk\n");
+		ret = PTR_ERR(motg->clk);
+		goto put_phy_reset_clk;
+	}
+	clk_set_rate(motg->clk, 60000000);
+
+	/*
+	 * If USB Core is running its protocol engine based on CORE CLK,
+	 * CORE CLK  must be running at >55Mhz for correct HSUSB
+	 * operation and USB core cannot tolerate frequency changes on
+	 * CORE CLK. For such USB cores, vote for maximum clk frequency
+	 * on pclk source
+	 */
+	 if (motg->pdata->pclk_src_name) {
+		motg->pclk_src = clk_get(&pdev->dev,
+			motg->pdata->pclk_src_name);
+		if (IS_ERR(motg->pclk_src))
+			goto put_clk;
+		clk_set_rate(motg->pclk_src, INT_MAX);
+		clk_enable(motg->pclk_src);
+	} else
+		motg->pclk_src = ERR_PTR(-ENOENT);
+
+
+	motg->pclk = clk_get(&pdev->dev, "usb_hs_pclk");
+	if (IS_ERR(motg->pclk)) {
+		dev_err(&pdev->dev, "failed to get usb_hs_pclk\n");
+		ret = PTR_ERR(motg->pclk);
+		goto put_pclk_src;
+	}
+
+	/*
+	 * USB core clock is not present on all MSM chips. This
+	 * clock is introduced to remove the dependency on AXI
+	 * bus frequency.
+	 */
+	motg->core_clk = clk_get(&pdev->dev, "usb_hs_core_clk");
+	if (IS_ERR(motg->core_clk))
+		motg->core_clk = NULL;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "failed to get platform resource mem\n");
+		ret = -ENODEV;
+		goto put_core_clk;
+	}
+
+	motg->regs = ioremap(res->start, resource_size(res));
+	if (!motg->regs) {
+		dev_err(&pdev->dev, "ioremap failed\n");
+		ret = -ENOMEM;
+		goto put_core_clk;
+	}
+	dev_info(&pdev->dev, "OTG regs = %p\n", motg->regs);
+
+	motg->irq = platform_get_irq(pdev, 0);
+	if (!motg->irq) {
+		dev_err(&pdev->dev, "platform_get_irq failed\n");
+		ret = -ENODEV;
+		goto free_regs;
+	}
+
+	clk_enable(motg->clk);
+	clk_enable(motg->pclk);
+
+	ret = msm_hsusb_init_vddcx(motg, 1);
+	if (ret) {
+		dev_err(&pdev->dev, "hsusb vddcx configuration failed\n");
+		goto free_regs;
+	}
+
+	ret = msm_hsusb_ldo_init(motg, 1);
+	if (ret) {
+		dev_err(&pdev->dev, "hsusb vreg configuration failed\n");
+		goto vddcx_exit;
+	}
+	ret = msm_hsusb_ldo_set_mode(1);
+	if (ret) {
+		dev_err(&pdev->dev, "hsusb vreg enable failed\n");
+		goto ldo_exit;
+	}
+
+	if (motg->core_clk)
+		clk_enable(motg->core_clk);
+
+	writel(0, USB_USBINTR);
+	writel(0, USB_OTGSC);
+
+	INIT_WORK(&motg->sm_work, msm_otg_sm_work);
+	INIT_DELAYED_WORK(&motg->chg_work, msm_chg_detect_work);
+	ret = request_irq(motg->irq, msm_otg_irq, IRQF_SHARED,
+					"msm_otg", motg);
+	if (ret) {
+		dev_err(&pdev->dev, "request irq failed\n");
+		goto disable_clks;
+	}
+
+	phy->init = msm_otg_reset;
+	phy->set_power = msm_otg_set_power;
+
+	phy->io_ops = &msm_otg_io_ops;
+
+	phy->otg->phy = &motg->phy;
+	phy->otg->set_host = msm_otg_set_host;
+	phy->otg->set_peripheral = msm_otg_set_peripheral;
+
+	ret = usb_add_phy(&motg->phy, USB_PHY_TYPE_USB2);
+	if (ret) {
+		dev_err(&pdev->dev, "usb_add_phy failed\n");
+		goto free_irq;
+	}
+
+	platform_set_drvdata(pdev, motg);
+	device_init_wakeup(&pdev->dev, 1);
+
+	if (motg->pdata->mode == USB_OTG &&
+			motg->pdata->otg_control == OTG_USER_CONTROL) {
+		ret = msm_otg_debugfs_init(motg);
+		if (ret)
+			dev_dbg(&pdev->dev, "mode debugfs file is"
+					"not available\n");
+	}
+
+	pm_runtime_set_active(&pdev->dev);
+	pm_runtime_enable(&pdev->dev);
+
+	return 0;
+free_irq:
+	free_irq(motg->irq, motg);
+disable_clks:
+	clk_disable(motg->pclk);
+	clk_disable(motg->clk);
+ldo_exit:
+	msm_hsusb_ldo_init(motg, 0);
+vddcx_exit:
+	msm_hsusb_init_vddcx(motg, 0);
+free_regs:
+	iounmap(motg->regs);
+put_core_clk:
+	if (motg->core_clk)
+		clk_put(motg->core_clk);
+	clk_put(motg->pclk);
+put_pclk_src:
+	if (!IS_ERR(motg->pclk_src)) {
+		clk_disable(motg->pclk_src);
+		clk_put(motg->pclk_src);
+	}
+put_clk:
+	clk_put(motg->clk);
+put_phy_reset_clk:
+	clk_put(motg->phy_reset_clk);
+free_motg:
+	kfree(motg->phy.otg);
+	kfree(motg);
+	return ret;
+}
+
+static int msm_otg_remove(struct platform_device *pdev)
+{
+	struct msm_otg *motg = platform_get_drvdata(pdev);
+	struct usb_phy *phy = &motg->phy;
+	int cnt = 0;
+
+	if (phy->otg->host || phy->otg->gadget)
+		return -EBUSY;
+
+	msm_otg_debugfs_cleanup();
+	cancel_delayed_work_sync(&motg->chg_work);
+	cancel_work_sync(&motg->sm_work);
+
+	pm_runtime_resume(&pdev->dev);
+
+	device_init_wakeup(&pdev->dev, 0);
+	pm_runtime_disable(&pdev->dev);
+
+	usb_remove_phy(phy);
+	free_irq(motg->irq, motg);
+
+	/*
+	 * Put PHY in low power mode.
+	 */
+	ulpi_read(phy, 0x14);
+	ulpi_write(phy, 0x08, 0x09);
+
+	writel(readl(USB_PORTSC) | PORTSC_PHCD, USB_PORTSC);
+	while (cnt < PHY_SUSPEND_TIMEOUT_USEC) {
+		if (readl(USB_PORTSC) & PORTSC_PHCD)
+			break;
+		udelay(1);
+		cnt++;
+	}
+	if (cnt >= PHY_SUSPEND_TIMEOUT_USEC)
+		dev_err(phy->dev, "Unable to suspend PHY\n");
+
+	clk_disable(motg->pclk);
+	clk_disable(motg->clk);
+	if (motg->core_clk)
+		clk_disable(motg->core_clk);
+	if (!IS_ERR(motg->pclk_src)) {
+		clk_disable(motg->pclk_src);
+		clk_put(motg->pclk_src);
+	}
+	msm_hsusb_ldo_init(motg, 0);
+
+	iounmap(motg->regs);
+	pm_runtime_set_suspended(&pdev->dev);
+
+	clk_put(motg->phy_reset_clk);
+	clk_put(motg->pclk);
+	clk_put(motg->clk);
+	if (motg->core_clk)
+		clk_put(motg->core_clk);
+
+	kfree(motg->phy.otg);
+	kfree(motg);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_RUNTIME
+static int msm_otg_runtime_idle(struct device *dev)
+{
+	struct msm_otg *motg = dev_get_drvdata(dev);
+	struct usb_otg *otg = motg->phy.otg;
+
+	dev_dbg(dev, "OTG runtime idle\n");
+
+	/*
+	 * It is observed some times that a spurious interrupt
+	 * comes when PHY is put into LPM immediately after PHY reset.
+	 * This 1 sec delay also prevents entering into LPM immediately
+	 * after asynchronous interrupt.
+	 */
+	if (otg->phy->state != OTG_STATE_UNDEFINED)
+		pm_schedule_suspend(dev, 1000);
+
+	return -EAGAIN;
+}
+
+static int msm_otg_runtime_suspend(struct device *dev)
+{
+	struct msm_otg *motg = dev_get_drvdata(dev);
+
+	dev_dbg(dev, "OTG runtime suspend\n");
+	return msm_otg_suspend(motg);
+}
+
+static int msm_otg_runtime_resume(struct device *dev)
+{
+	struct msm_otg *motg = dev_get_drvdata(dev);
+
+	dev_dbg(dev, "OTG runtime resume\n");
+	return msm_otg_resume(motg);
+}
+#endif
+
+#ifdef CONFIG_PM_SLEEP
+static int msm_otg_pm_suspend(struct device *dev)
+{
+	struct msm_otg *motg = dev_get_drvdata(dev);
+
+	dev_dbg(dev, "OTG PM suspend\n");
+	return msm_otg_suspend(motg);
+}
+
+static int msm_otg_pm_resume(struct device *dev)
+{
+	struct msm_otg *motg = dev_get_drvdata(dev);
+	int ret;
+
+	dev_dbg(dev, "OTG PM resume\n");
+
+	ret = msm_otg_resume(motg);
+	if (ret)
+		return ret;
+
+	/*
+	 * Runtime PM Documentation recommends bringing the
+	 * device to full powered state upon resume.
+	 */
+	pm_runtime_disable(dev);
+	pm_runtime_set_active(dev);
+	pm_runtime_enable(dev);
+
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_PM
+static const struct dev_pm_ops msm_otg_dev_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(msm_otg_pm_suspend, msm_otg_pm_resume)
+	SET_RUNTIME_PM_OPS(msm_otg_runtime_suspend, msm_otg_runtime_resume,
+				msm_otg_runtime_idle)
+};
+#endif
+
+static struct platform_driver msm_otg_driver = {
+	.remove = msm_otg_remove,
+	.driver = {
+		.name = DRIVER_NAME,
+		.owner = THIS_MODULE,
+#ifdef CONFIG_PM
+		.pm = &msm_otg_dev_pm_ops,
+#endif
+	},
+};
+
+module_platform_driver_probe(msm_otg_driver, msm_otg_probe);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("MSM USB transceiver driver");
diff --git a/drivers/usb/phy/phy-mv-u3d-usb.c b/drivers/usb/phy/phy-mv-u3d-usb.c
new file mode 100644
index 0000000..f7838a4
--- /dev/null
+++ b/drivers/usb/phy/phy-mv-u3d-usb.c
@@ -0,0 +1,343 @@
+/*
+ * Copyright (C) 2011 Marvell International Ltd. 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.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/usb/otg.h>
+#include <linux/platform_data/mv_usb.h>
+
+#include "phy-mv-u3d-usb.h"
+
+/*
+ * struct mv_u3d_phy - transceiver driver state
+ * @phy: transceiver structure
+ * @dev: The parent device supplied to the probe function
+ * @clk: usb phy clock
+ * @base: usb phy register memory base
+ */
+struct mv_u3d_phy {
+	struct usb_phy	phy;
+	struct mv_usb_platform_data *plat;
+	struct device	*dev;
+	struct clk	*clk;
+	void __iomem	*base;
+};
+
+static u32 mv_u3d_phy_read(void __iomem *base, u32 reg)
+{
+	void __iomem *addr, *data;
+
+	addr = base;
+	data = base + 0x4;
+
+	writel_relaxed(reg, addr);
+	return readl_relaxed(data);
+}
+
+static void mv_u3d_phy_set(void __iomem *base, u32 reg, u32 value)
+{
+	void __iomem *addr, *data;
+	u32 tmp;
+
+	addr = base;
+	data = base + 0x4;
+
+	writel_relaxed(reg, addr);
+	tmp = readl_relaxed(data);
+	tmp |= value;
+	writel_relaxed(tmp, data);
+}
+
+static void mv_u3d_phy_clear(void __iomem *base, u32 reg, u32 value)
+{
+	void __iomem *addr, *data;
+	u32 tmp;
+
+	addr = base;
+	data = base + 0x4;
+
+	writel_relaxed(reg, addr);
+	tmp = readl_relaxed(data);
+	tmp &= ~value;
+	writel_relaxed(tmp, data);
+}
+
+static void mv_u3d_phy_write(void __iomem *base, u32 reg, u32 value)
+{
+	void __iomem *addr, *data;
+
+	addr = base;
+	data = base + 0x4;
+
+	writel_relaxed(reg, addr);
+	writel_relaxed(value, data);
+}
+
+void mv_u3d_phy_shutdown(struct usb_phy *phy)
+{
+	struct mv_u3d_phy *mv_u3d_phy;
+	void __iomem *base;
+	u32 val;
+
+	mv_u3d_phy = container_of(phy, struct mv_u3d_phy, phy);
+	base = mv_u3d_phy->base;
+
+	/* Power down Reference Analog current, bit 15
+	 * Power down PLL, bit 14
+	 * Power down Receiver, bit 13
+	 * Power down Transmitter, bit 12
+	 * of USB3_POWER_PLL_CONTROL register
+	 */
+	val = mv_u3d_phy_read(base, USB3_POWER_PLL_CONTROL);
+	val &= ~(USB3_POWER_PLL_CONTROL_PU);
+	mv_u3d_phy_write(base, USB3_POWER_PLL_CONTROL, val);
+
+	if (mv_u3d_phy->clk)
+		clk_disable(mv_u3d_phy->clk);
+}
+
+static int mv_u3d_phy_init(struct usb_phy *phy)
+{
+	struct mv_u3d_phy *mv_u3d_phy;
+	void __iomem *base;
+	u32 val, count;
+
+	/* enable usb3 phy */
+	mv_u3d_phy = container_of(phy, struct mv_u3d_phy, phy);
+
+	if (mv_u3d_phy->clk)
+		clk_enable(mv_u3d_phy->clk);
+
+	base = mv_u3d_phy->base;
+
+	val = mv_u3d_phy_read(base, USB3_POWER_PLL_CONTROL);
+	val &= ~(USB3_POWER_PLL_CONTROL_PU_MASK);
+	val |= 0xF << USB3_POWER_PLL_CONTROL_PU_SHIFT;
+	mv_u3d_phy_write(base, USB3_POWER_PLL_CONTROL, val);
+	udelay(100);
+
+	mv_u3d_phy_write(base, USB3_RESET_CONTROL,
+			USB3_RESET_CONTROL_RESET_PIPE);
+	udelay(100);
+
+	mv_u3d_phy_write(base, USB3_RESET_CONTROL,
+			USB3_RESET_CONTROL_RESET_PIPE
+			| USB3_RESET_CONTROL_RESET_PHY);
+	udelay(100);
+
+	val = mv_u3d_phy_read(base, USB3_POWER_PLL_CONTROL);
+	val &= ~(USB3_POWER_PLL_CONTROL_REF_FREF_SEL_MASK
+		| USB3_POWER_PLL_CONTROL_PHY_MODE_MASK);
+	val |=  (USB3_PLL_25MHZ << USB3_POWER_PLL_CONTROL_REF_FREF_SEL_SHIFT)
+		| (0x5 << USB3_POWER_PLL_CONTROL_PHY_MODE_SHIFT);
+	mv_u3d_phy_write(base, USB3_POWER_PLL_CONTROL, val);
+	udelay(100);
+
+	mv_u3d_phy_clear(base, USB3_KVCO_CALI_CONTROL,
+		USB3_KVCO_CALI_CONTROL_USE_MAX_PLL_RATE_MASK);
+	udelay(100);
+
+	val = mv_u3d_phy_read(base, USB3_SQUELCH_FFE);
+	val &= ~(USB3_SQUELCH_FFE_FFE_CAP_SEL_MASK
+		| USB3_SQUELCH_FFE_FFE_RES_SEL_MASK
+		| USB3_SQUELCH_FFE_SQ_THRESH_IN_MASK);
+	val |= ((0xD << USB3_SQUELCH_FFE_FFE_CAP_SEL_SHIFT)
+		| (0x7 << USB3_SQUELCH_FFE_FFE_RES_SEL_SHIFT)
+		| (0x8 << USB3_SQUELCH_FFE_SQ_THRESH_IN_SHIFT));
+	mv_u3d_phy_write(base, USB3_SQUELCH_FFE, val);
+	udelay(100);
+
+	val = mv_u3d_phy_read(base, USB3_GEN1_SET0);
+	val &= ~USB3_GEN1_SET0_G1_TX_SLEW_CTRL_EN_MASK;
+	val |= 1 << USB3_GEN1_SET0_G1_TX_EMPH_EN_SHIFT;
+	mv_u3d_phy_write(base, USB3_GEN1_SET0, val);
+	udelay(100);
+
+	val = mv_u3d_phy_read(base, USB3_GEN2_SET0);
+	val &= ~(USB3_GEN2_SET0_G2_TX_AMP_MASK
+		| USB3_GEN2_SET0_G2_TX_EMPH_AMP_MASK
+		| USB3_GEN2_SET0_G2_TX_SLEW_CTRL_EN_MASK);
+	val |= ((0x14 << USB3_GEN2_SET0_G2_TX_AMP_SHIFT)
+		| (1 << USB3_GEN2_SET0_G2_TX_AMP_ADJ_SHIFT)
+		| (0xA << USB3_GEN2_SET0_G2_TX_EMPH_AMP_SHIFT)
+		| (1 << USB3_GEN2_SET0_G2_TX_EMPH_EN_SHIFT));
+	mv_u3d_phy_write(base, USB3_GEN2_SET0, val);
+	udelay(100);
+
+	mv_u3d_phy_read(base, USB3_TX_EMPPH);
+	val &= ~(USB3_TX_EMPPH_AMP_MASK
+		| USB3_TX_EMPPH_EN_MASK
+		| USB3_TX_EMPPH_AMP_FORCE_MASK
+		| USB3_TX_EMPPH_PAR1_MASK
+		| USB3_TX_EMPPH_PAR2_MASK);
+	val |= ((0xB << USB3_TX_EMPPH_AMP_SHIFT)
+		| (1 << USB3_TX_EMPPH_EN_SHIFT)
+		| (1 << USB3_TX_EMPPH_AMP_FORCE_SHIFT)
+		| (0x1C << USB3_TX_EMPPH_PAR1_SHIFT)
+		| (1 << USB3_TX_EMPPH_PAR2_SHIFT));
+
+	mv_u3d_phy_write(base, USB3_TX_EMPPH, val);
+	udelay(100);
+
+	val = mv_u3d_phy_read(base, USB3_GEN2_SET1);
+	val &= ~(USB3_GEN2_SET1_G2_RX_SELMUPI_MASK
+		| USB3_GEN2_SET1_G2_RX_SELMUPF_MASK
+		| USB3_GEN2_SET1_G2_RX_SELMUFI_MASK
+		| USB3_GEN2_SET1_G2_RX_SELMUFF_MASK);
+	val |= ((1 << USB3_GEN2_SET1_G2_RX_SELMUPI_SHIFT)
+		| (1 << USB3_GEN2_SET1_G2_RX_SELMUPF_SHIFT)
+		| (1 << USB3_GEN2_SET1_G2_RX_SELMUFI_SHIFT)
+		| (1 << USB3_GEN2_SET1_G2_RX_SELMUFF_SHIFT));
+	mv_u3d_phy_write(base, USB3_GEN2_SET1, val);
+	udelay(100);
+
+	val = mv_u3d_phy_read(base, USB3_DIGITAL_LOOPBACK_EN);
+	val &= ~USB3_DIGITAL_LOOPBACK_EN_SEL_BITS_MASK;
+	val |= 1 << USB3_DIGITAL_LOOPBACK_EN_SEL_BITS_SHIFT;
+	mv_u3d_phy_write(base, USB3_DIGITAL_LOOPBACK_EN, val);
+	udelay(100);
+
+	val = mv_u3d_phy_read(base, USB3_IMPEDANCE_TX_SSC);
+	val &= ~USB3_IMPEDANCE_TX_SSC_SSC_AMP_MASK;
+	val |= 0xC << USB3_IMPEDANCE_TX_SSC_SSC_AMP_SHIFT;
+	mv_u3d_phy_write(base, USB3_IMPEDANCE_TX_SSC, val);
+	udelay(100);
+
+	val = mv_u3d_phy_read(base, USB3_IMPEDANCE_CALI_CTRL);
+	val &= ~USB3_IMPEDANCE_CALI_CTRL_IMP_CAL_THR_MASK;
+	val |= 0x4 << USB3_IMPEDANCE_CALI_CTRL_IMP_CAL_THR_SHIFT;
+	mv_u3d_phy_write(base, USB3_IMPEDANCE_CALI_CTRL, val);
+	udelay(100);
+
+	val = mv_u3d_phy_read(base, USB3_PHY_ISOLATION_MODE);
+	val &= ~(USB3_PHY_ISOLATION_MODE_PHY_GEN_RX_MASK
+		| USB3_PHY_ISOLATION_MODE_PHY_GEN_TX_MASK
+		| USB3_PHY_ISOLATION_MODE_TX_DRV_IDLE_MASK);
+	val |= ((1 << USB3_PHY_ISOLATION_MODE_PHY_GEN_RX_SHIFT)
+		| (1 << USB3_PHY_ISOLATION_MODE_PHY_GEN_TX_SHIFT));
+	mv_u3d_phy_write(base, USB3_PHY_ISOLATION_MODE, val);
+	udelay(100);
+
+	val = mv_u3d_phy_read(base, USB3_TXDETRX);
+	val &= ~(USB3_TXDETRX_VTHSEL_MASK);
+	val |= 0x1 << USB3_TXDETRX_VTHSEL_SHIFT;
+	mv_u3d_phy_write(base, USB3_TXDETRX, val);
+	udelay(100);
+
+	dev_dbg(mv_u3d_phy->dev, "start calibration\n");
+
+calstart:
+	/* Perform Manual Calibration */
+	mv_u3d_phy_set(base, USB3_KVCO_CALI_CONTROL,
+		1 << USB3_KVCO_CALI_CONTROL_CAL_START_SHIFT);
+
+	mdelay(1);
+
+	count = 0;
+	while (1) {
+		val = mv_u3d_phy_read(base, USB3_KVCO_CALI_CONTROL);
+		if (val & (1 << USB3_KVCO_CALI_CONTROL_CAL_DONE_SHIFT))
+			break;
+		else if (count > 50) {
+			dev_dbg(mv_u3d_phy->dev, "calibration failure, retry...\n");
+			goto calstart;
+		}
+		count++;
+		mdelay(1);
+	}
+
+	/* active PIPE interface */
+	mv_u3d_phy_write(base, USB3_PIPE_SM_CTRL,
+		1 << USB3_PIPE_SM_CTRL_PHY_INIT_DONE);
+
+	return 0;
+}
+
+static int mv_u3d_phy_probe(struct platform_device *pdev)
+{
+	struct mv_u3d_phy *mv_u3d_phy;
+	struct mv_usb_platform_data *pdata;
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	void __iomem	*phy_base;
+	int	ret;
+
+	pdata = pdev->dev.platform_data;
+	if (!pdata) {
+		dev_err(&pdev->dev, "%s: no platform data defined\n", __func__);
+		return -EINVAL;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(dev, "missing mem resource\n");
+		return -ENODEV;
+	}
+
+	phy_base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(phy_base))
+		return PTR_ERR(phy_base);
+
+	mv_u3d_phy = devm_kzalloc(dev, sizeof(*mv_u3d_phy), GFP_KERNEL);
+	if (!mv_u3d_phy)
+		return -ENOMEM;
+
+	mv_u3d_phy->dev			= &pdev->dev;
+	mv_u3d_phy->plat		= pdata;
+	mv_u3d_phy->base		= phy_base;
+	mv_u3d_phy->phy.dev		= mv_u3d_phy->dev;
+	mv_u3d_phy->phy.label		= "mv-u3d-phy";
+	mv_u3d_phy->phy.init		= mv_u3d_phy_init;
+	mv_u3d_phy->phy.shutdown	= mv_u3d_phy_shutdown;
+
+	ret = usb_add_phy(&mv_u3d_phy->phy, USB_PHY_TYPE_USB3);
+	if (ret)
+		goto err;
+
+	if (!mv_u3d_phy->clk)
+		mv_u3d_phy->clk = clk_get(mv_u3d_phy->dev, "u3dphy");
+
+	platform_set_drvdata(pdev, mv_u3d_phy);
+
+	dev_info(&pdev->dev, "Initialized Marvell USB 3.0 PHY\n");
+err:
+	return ret;
+}
+
+static int mv_u3d_phy_remove(struct platform_device *pdev)
+{
+	struct mv_u3d_phy *mv_u3d_phy = platform_get_drvdata(pdev);
+
+	usb_remove_phy(&mv_u3d_phy->phy);
+
+	if (mv_u3d_phy->clk) {
+		clk_put(mv_u3d_phy->clk);
+		mv_u3d_phy->clk = NULL;
+	}
+
+	return 0;
+}
+
+static struct platform_driver mv_u3d_phy_driver = {
+	.probe		= mv_u3d_phy_probe,
+	.remove		= mv_u3d_phy_remove,
+	.driver		= {
+		.name	= "mv-u3d-phy",
+		.owner	= THIS_MODULE,
+	},
+};
+
+module_platform_driver(mv_u3d_phy_driver);
+MODULE_DESCRIPTION("Marvell USB 3.0 PHY controller");
+MODULE_AUTHOR("Yu Xu <yuxu@marvell.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:mv-u3d-phy");
diff --git a/drivers/usb/phy/phy-mv-u3d-usb.h b/drivers/usb/phy/phy-mv-u3d-usb.h
new file mode 100644
index 0000000..2a658cb
--- /dev/null
+++ b/drivers/usb/phy/phy-mv-u3d-usb.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2011 Marvell International Ltd. 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.
+ */
+
+#ifndef __MV_U3D_PHY_H
+#define __MV_U3D_PHY_H
+
+#define USB3_POWER_PLL_CONTROL		0x1
+#define USB3_KVCO_CALI_CONTROL		0x2
+#define USB3_IMPEDANCE_CALI_CTRL	0x3
+#define USB3_IMPEDANCE_TX_SSC		0x4
+#define USB3_SQUELCH_FFE		0x6
+#define USB3_GEN1_SET0			0xD
+#define USB3_GEN2_SET0			0xF
+#define USB3_GEN2_SET1			0x10
+#define USB3_DIGITAL_LOOPBACK_EN	0x23
+#define USB3_PHY_ISOLATION_MODE		0x26
+#define USB3_TXDETRX			0x48
+#define USB3_TX_EMPPH			0x5E
+#define USB3_RESET_CONTROL		0x90
+#define USB3_PIPE_SM_CTRL		0x91
+
+#define USB3_RESET_CONTROL_RESET_PIPE			0x1
+#define USB3_RESET_CONTROL_RESET_PHY			0x2
+
+#define USB3_POWER_PLL_CONTROL_REF_FREF_SEL_MASK	(0x1F << 0)
+#define USB3_POWER_PLL_CONTROL_REF_FREF_SEL_SHIFT	0
+#define USB3_PLL_25MHZ					0x2
+#define USB3_PLL_26MHZ					0x5
+#define USB3_POWER_PLL_CONTROL_PHY_MODE_MASK		(0x7 << 5)
+#define USB3_POWER_PLL_CONTROL_PHY_MODE_SHIFT		5
+#define USB3_POWER_PLL_CONTROL_PU_MASK			(0xF << 12)
+#define USB3_POWER_PLL_CONTROL_PU_SHIFT			12
+#define USB3_POWER_PLL_CONTROL_PU			(0xF << 12)
+
+#define USB3_KVCO_CALI_CONTROL_USE_MAX_PLL_RATE_MASK	(0x1 << 12)
+#define USB3_KVCO_CALI_CONTROL_USE_MAX_PLL_RATE_SHIFT	12
+#define USB3_KVCO_CALI_CONTROL_CAL_DONE_SHIFT		14
+#define USB3_KVCO_CALI_CONTROL_CAL_START_SHIFT		15
+
+#define USB3_SQUELCH_FFE_FFE_CAP_SEL_MASK		0xF
+#define USB3_SQUELCH_FFE_FFE_CAP_SEL_SHIFT		0
+#define USB3_SQUELCH_FFE_FFE_RES_SEL_MASK		(0x7 << 4)
+#define USB3_SQUELCH_FFE_FFE_RES_SEL_SHIFT		4
+#define USB3_SQUELCH_FFE_SQ_THRESH_IN_MASK		(0x1F << 8)
+#define USB3_SQUELCH_FFE_SQ_THRESH_IN_SHIFT		8
+
+#define USB3_GEN1_SET0_G1_TX_SLEW_CTRL_EN_MASK		(0x1 << 15)
+#define USB3_GEN1_SET0_G1_TX_EMPH_EN_SHIFT		11
+
+#define USB3_GEN2_SET0_G2_TX_AMP_MASK			(0x1F << 1)
+#define USB3_GEN2_SET0_G2_TX_AMP_SHIFT			1
+#define USB3_GEN2_SET0_G2_TX_AMP_ADJ_SHIFT		6
+#define USB3_GEN2_SET0_G2_TX_EMPH_AMP_MASK		(0xF << 7)
+#define USB3_GEN2_SET0_G2_TX_EMPH_AMP_SHIFT		7
+#define USB3_GEN2_SET0_G2_TX_EMPH_EN_MASK		(0x1 << 11)
+#define USB3_GEN2_SET0_G2_TX_EMPH_EN_SHIFT		11
+#define USB3_GEN2_SET0_G2_TX_SLEW_CTRL_EN_MASK		(0x1 << 15)
+#define USB3_GEN2_SET0_G2_TX_SLEW_CTRL_EN_SHIFT		15
+
+#define USB3_GEN2_SET1_G2_RX_SELMUPI_MASK		(0x7 << 0)
+#define USB3_GEN2_SET1_G2_RX_SELMUPI_SHIFT		0
+#define USB3_GEN2_SET1_G2_RX_SELMUPF_MASK		(0x7 << 3)
+#define USB3_GEN2_SET1_G2_RX_SELMUPF_SHIFT		3
+#define USB3_GEN2_SET1_G2_RX_SELMUFI_MASK		(0x3 << 6)
+#define USB3_GEN2_SET1_G2_RX_SELMUFI_SHIFT		6
+#define USB3_GEN2_SET1_G2_RX_SELMUFF_MASK		(0x3 << 8)
+#define USB3_GEN2_SET1_G2_RX_SELMUFF_SHIFT		8
+
+#define USB3_DIGITAL_LOOPBACK_EN_SEL_BITS_MASK		(0x3 << 10)
+#define USB3_DIGITAL_LOOPBACK_EN_SEL_BITS_SHIFT		10
+
+#define USB3_IMPEDANCE_CALI_CTRL_IMP_CAL_THR_MASK	(0x7 << 12)
+#define USB3_IMPEDANCE_CALI_CTRL_IMP_CAL_THR_SHIFT	12
+
+#define USB3_IMPEDANCE_TX_SSC_SSC_AMP_MASK		(0x3F << 0)
+#define USB3_IMPEDANCE_TX_SSC_SSC_AMP_SHIFT		0
+
+#define USB3_PHY_ISOLATION_MODE_PHY_GEN_RX_MASK		0xF
+#define USB3_PHY_ISOLATION_MODE_PHY_GEN_RX_SHIFT	0
+#define USB3_PHY_ISOLATION_MODE_PHY_GEN_TX_MASK		(0xF << 4)
+#define USB3_PHY_ISOLATION_MODE_PHY_GEN_TX_SHIFT	4
+#define USB3_PHY_ISOLATION_MODE_TX_DRV_IDLE_MASK	(0x1 << 8)
+
+#define USB3_TXDETRX_VTHSEL_MASK			(0x3 << 4)
+#define USB3_TXDETRX_VTHSEL_SHIFT			4
+
+#define USB3_TX_EMPPH_AMP_MASK				(0xF << 0)
+#define USB3_TX_EMPPH_AMP_SHIFT				0
+#define USB3_TX_EMPPH_EN_MASK				(0x1 << 6)
+#define USB3_TX_EMPPH_EN_SHIFT				6
+#define USB3_TX_EMPPH_AMP_FORCE_MASK			(0x1 << 7)
+#define USB3_TX_EMPPH_AMP_FORCE_SHIFT			7
+#define USB3_TX_EMPPH_PAR1_MASK				(0x1F << 8)
+#define USB3_TX_EMPPH_PAR1_SHIFT			8
+#define USB3_TX_EMPPH_PAR2_MASK				(0x1 << 13)
+#define USB3_TX_EMPPH_PAR2_SHIFT			13
+
+#define USB3_PIPE_SM_CTRL_PHY_INIT_DONE			15
+
+#endif /* __MV_U3D_PHY_H */
diff --git a/drivers/usb/phy/phy-mv-usb.c b/drivers/usb/phy/phy-mv-usb.c
new file mode 100644
index 0000000..c987bbe
--- /dev/null
+++ b/drivers/usb/phy/phy-mv-usb.c
@@ -0,0 +1,909 @@
+/*
+ * Copyright (C) 2011 Marvell International Ltd. All rights reserved.
+ * Author: Chao Xie <chao.xie@marvell.com>
+ *	   Neil Zhang <zhangwm@marvell.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/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
+#include <linux/device.h>
+#include <linux/proc_fs.h>
+#include <linux/clk.h>
+#include <linux/workqueue.h>
+#include <linux/platform_device.h>
+
+#include <linux/usb.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/otg.h>
+#include <linux/usb/gadget.h>
+#include <linux/usb/hcd.h>
+#include <linux/platform_data/mv_usb.h>
+
+#include "phy-mv-usb.h"
+
+#define	DRIVER_DESC	"Marvell USB OTG transceiver driver"
+#define	DRIVER_VERSION	"Jan 20, 2010"
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_LICENSE("GPL");
+
+static const char driver_name[] = "mv-otg";
+
+static char *state_string[] = {
+	"undefined",
+	"b_idle",
+	"b_srp_init",
+	"b_peripheral",
+	"b_wait_acon",
+	"b_host",
+	"a_idle",
+	"a_wait_vrise",
+	"a_wait_bcon",
+	"a_host",
+	"a_suspend",
+	"a_peripheral",
+	"a_wait_vfall",
+	"a_vbus_err"
+};
+
+static int mv_otg_set_vbus(struct usb_otg *otg, bool on)
+{
+	struct mv_otg *mvotg = container_of(otg->phy, struct mv_otg, phy);
+	if (mvotg->pdata->set_vbus == NULL)
+		return -ENODEV;
+
+	return mvotg->pdata->set_vbus(on);
+}
+
+static int mv_otg_set_host(struct usb_otg *otg,
+			   struct usb_bus *host)
+{
+	otg->host = host;
+
+	return 0;
+}
+
+static int mv_otg_set_peripheral(struct usb_otg *otg,
+				 struct usb_gadget *gadget)
+{
+	otg->gadget = gadget;
+
+	return 0;
+}
+
+static void mv_otg_run_state_machine(struct mv_otg *mvotg,
+				     unsigned long delay)
+{
+	dev_dbg(&mvotg->pdev->dev, "transceiver is updated\n");
+	if (!mvotg->qwork)
+		return;
+
+	queue_delayed_work(mvotg->qwork, &mvotg->work, delay);
+}
+
+static void mv_otg_timer_await_bcon(unsigned long data)
+{
+	struct mv_otg *mvotg = (struct mv_otg *) data;
+
+	mvotg->otg_ctrl.a_wait_bcon_timeout = 1;
+
+	dev_info(&mvotg->pdev->dev, "B Device No Response!\n");
+
+	if (spin_trylock(&mvotg->wq_lock)) {
+		mv_otg_run_state_machine(mvotg, 0);
+		spin_unlock(&mvotg->wq_lock);
+	}
+}
+
+static int mv_otg_cancel_timer(struct mv_otg *mvotg, unsigned int id)
+{
+	struct timer_list *timer;
+
+	if (id >= OTG_TIMER_NUM)
+		return -EINVAL;
+
+	timer = &mvotg->otg_ctrl.timer[id];
+
+	if (timer_pending(timer))
+		del_timer(timer);
+
+	return 0;
+}
+
+static int mv_otg_set_timer(struct mv_otg *mvotg, unsigned int id,
+			    unsigned long interval,
+			    void (*callback) (unsigned long))
+{
+	struct timer_list *timer;
+
+	if (id >= OTG_TIMER_NUM)
+		return -EINVAL;
+
+	timer = &mvotg->otg_ctrl.timer[id];
+	if (timer_pending(timer)) {
+		dev_err(&mvotg->pdev->dev, "Timer%d is already running\n", id);
+		return -EBUSY;
+	}
+
+	init_timer(timer);
+	timer->data = (unsigned long) mvotg;
+	timer->function = callback;
+	timer->expires = jiffies + interval;
+	add_timer(timer);
+
+	return 0;
+}
+
+static int mv_otg_reset(struct mv_otg *mvotg)
+{
+	unsigned int loops;
+	u32 tmp;
+
+	/* Stop the controller */
+	tmp = readl(&mvotg->op_regs->usbcmd);
+	tmp &= ~USBCMD_RUN_STOP;
+	writel(tmp, &mvotg->op_regs->usbcmd);
+
+	/* Reset the controller to get default values */
+	writel(USBCMD_CTRL_RESET, &mvotg->op_regs->usbcmd);
+
+	loops = 500;
+	while (readl(&mvotg->op_regs->usbcmd) & USBCMD_CTRL_RESET) {
+		if (loops == 0) {
+			dev_err(&mvotg->pdev->dev,
+				"Wait for RESET completed TIMEOUT\n");
+			return -ETIMEDOUT;
+		}
+		loops--;
+		udelay(20);
+	}
+
+	writel(0x0, &mvotg->op_regs->usbintr);
+	tmp = readl(&mvotg->op_regs->usbsts);
+	writel(tmp, &mvotg->op_regs->usbsts);
+
+	return 0;
+}
+
+static void mv_otg_init_irq(struct mv_otg *mvotg)
+{
+	u32 otgsc;
+
+	mvotg->irq_en = OTGSC_INTR_A_SESSION_VALID
+	    | OTGSC_INTR_A_VBUS_VALID;
+	mvotg->irq_status = OTGSC_INTSTS_A_SESSION_VALID
+	    | OTGSC_INTSTS_A_VBUS_VALID;
+
+	if (mvotg->pdata->vbus == NULL) {
+		mvotg->irq_en |= OTGSC_INTR_B_SESSION_VALID
+		    | OTGSC_INTR_B_SESSION_END;
+		mvotg->irq_status |= OTGSC_INTSTS_B_SESSION_VALID
+		    | OTGSC_INTSTS_B_SESSION_END;
+	}
+
+	if (mvotg->pdata->id == NULL) {
+		mvotg->irq_en |= OTGSC_INTR_USB_ID;
+		mvotg->irq_status |= OTGSC_INTSTS_USB_ID;
+	}
+
+	otgsc = readl(&mvotg->op_regs->otgsc);
+	otgsc |= mvotg->irq_en;
+	writel(otgsc, &mvotg->op_regs->otgsc);
+}
+
+static void mv_otg_start_host(struct mv_otg *mvotg, int on)
+{
+#ifdef CONFIG_USB
+	struct usb_otg *otg = mvotg->phy.otg;
+	struct usb_hcd *hcd;
+
+	if (!otg->host)
+		return;
+
+	dev_info(&mvotg->pdev->dev, "%s host\n", on ? "start" : "stop");
+
+	hcd = bus_to_hcd(otg->host);
+
+	if (on)
+		usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
+	else
+		usb_remove_hcd(hcd);
+#endif /* CONFIG_USB */
+}
+
+static void mv_otg_start_periphrals(struct mv_otg *mvotg, int on)
+{
+	struct usb_otg *otg = mvotg->phy.otg;
+
+	if (!otg->gadget)
+		return;
+
+	dev_info(mvotg->phy.dev, "gadget %s\n", on ? "on" : "off");
+
+	if (on)
+		usb_gadget_vbus_connect(otg->gadget);
+	else
+		usb_gadget_vbus_disconnect(otg->gadget);
+}
+
+static void otg_clock_enable(struct mv_otg *mvotg)
+{
+	clk_prepare_enable(mvotg->clk);
+}
+
+static void otg_clock_disable(struct mv_otg *mvotg)
+{
+	clk_disable_unprepare(mvotg->clk);
+}
+
+static int mv_otg_enable_internal(struct mv_otg *mvotg)
+{
+	int retval = 0;
+
+	if (mvotg->active)
+		return 0;
+
+	dev_dbg(&mvotg->pdev->dev, "otg enabled\n");
+
+	otg_clock_enable(mvotg);
+	if (mvotg->pdata->phy_init) {
+		retval = mvotg->pdata->phy_init(mvotg->phy_regs);
+		if (retval) {
+			dev_err(&mvotg->pdev->dev,
+				"init phy error %d\n", retval);
+			otg_clock_disable(mvotg);
+			return retval;
+		}
+	}
+	mvotg->active = 1;
+
+	return 0;
+
+}
+
+static int mv_otg_enable(struct mv_otg *mvotg)
+{
+	if (mvotg->clock_gating)
+		return mv_otg_enable_internal(mvotg);
+
+	return 0;
+}
+
+static void mv_otg_disable_internal(struct mv_otg *mvotg)
+{
+	if (mvotg->active) {
+		dev_dbg(&mvotg->pdev->dev, "otg disabled\n");
+		if (mvotg->pdata->phy_deinit)
+			mvotg->pdata->phy_deinit(mvotg->phy_regs);
+		otg_clock_disable(mvotg);
+		mvotg->active = 0;
+	}
+}
+
+static void mv_otg_disable(struct mv_otg *mvotg)
+{
+	if (mvotg->clock_gating)
+		mv_otg_disable_internal(mvotg);
+}
+
+static void mv_otg_update_inputs(struct mv_otg *mvotg)
+{
+	struct mv_otg_ctrl *otg_ctrl = &mvotg->otg_ctrl;
+	u32 otgsc;
+
+	otgsc = readl(&mvotg->op_regs->otgsc);
+
+	if (mvotg->pdata->vbus) {
+		if (mvotg->pdata->vbus->poll() == VBUS_HIGH) {
+			otg_ctrl->b_sess_vld = 1;
+			otg_ctrl->b_sess_end = 0;
+		} else {
+			otg_ctrl->b_sess_vld = 0;
+			otg_ctrl->b_sess_end = 1;
+		}
+	} else {
+		otg_ctrl->b_sess_vld = !!(otgsc & OTGSC_STS_B_SESSION_VALID);
+		otg_ctrl->b_sess_end = !!(otgsc & OTGSC_STS_B_SESSION_END);
+	}
+
+	if (mvotg->pdata->id)
+		otg_ctrl->id = !!mvotg->pdata->id->poll();
+	else
+		otg_ctrl->id = !!(otgsc & OTGSC_STS_USB_ID);
+
+	if (mvotg->pdata->otg_force_a_bus_req && !otg_ctrl->id)
+		otg_ctrl->a_bus_req = 1;
+
+	otg_ctrl->a_sess_vld = !!(otgsc & OTGSC_STS_A_SESSION_VALID);
+	otg_ctrl->a_vbus_vld = !!(otgsc & OTGSC_STS_A_VBUS_VALID);
+
+	dev_dbg(&mvotg->pdev->dev, "%s: ", __func__);
+	dev_dbg(&mvotg->pdev->dev, "id %d\n", otg_ctrl->id);
+	dev_dbg(&mvotg->pdev->dev, "b_sess_vld %d\n", otg_ctrl->b_sess_vld);
+	dev_dbg(&mvotg->pdev->dev, "b_sess_end %d\n", otg_ctrl->b_sess_end);
+	dev_dbg(&mvotg->pdev->dev, "a_vbus_vld %d\n", otg_ctrl->a_vbus_vld);
+	dev_dbg(&mvotg->pdev->dev, "a_sess_vld %d\n", otg_ctrl->a_sess_vld);
+}
+
+static void mv_otg_update_state(struct mv_otg *mvotg)
+{
+	struct mv_otg_ctrl *otg_ctrl = &mvotg->otg_ctrl;
+	struct usb_phy *phy = &mvotg->phy;
+	int old_state = phy->state;
+
+	switch (old_state) {
+	case OTG_STATE_UNDEFINED:
+		phy->state = OTG_STATE_B_IDLE;
+		/* FALL THROUGH */
+	case OTG_STATE_B_IDLE:
+		if (otg_ctrl->id == 0)
+			phy->state = OTG_STATE_A_IDLE;
+		else if (otg_ctrl->b_sess_vld)
+			phy->state = OTG_STATE_B_PERIPHERAL;
+		break;
+	case OTG_STATE_B_PERIPHERAL:
+		if (!otg_ctrl->b_sess_vld || otg_ctrl->id == 0)
+			phy->state = OTG_STATE_B_IDLE;
+		break;
+	case OTG_STATE_A_IDLE:
+		if (otg_ctrl->id)
+			phy->state = OTG_STATE_B_IDLE;
+		else if (!(otg_ctrl->a_bus_drop) &&
+			 (otg_ctrl->a_bus_req || otg_ctrl->a_srp_det))
+			phy->state = OTG_STATE_A_WAIT_VRISE;
+		break;
+	case OTG_STATE_A_WAIT_VRISE:
+		if (otg_ctrl->a_vbus_vld)
+			phy->state = OTG_STATE_A_WAIT_BCON;
+		break;
+	case OTG_STATE_A_WAIT_BCON:
+		if (otg_ctrl->id || otg_ctrl->a_bus_drop
+		    || otg_ctrl->a_wait_bcon_timeout) {
+			mv_otg_cancel_timer(mvotg, A_WAIT_BCON_TIMER);
+			mvotg->otg_ctrl.a_wait_bcon_timeout = 0;
+			phy->state = OTG_STATE_A_WAIT_VFALL;
+			otg_ctrl->a_bus_req = 0;
+		} else if (!otg_ctrl->a_vbus_vld) {
+			mv_otg_cancel_timer(mvotg, A_WAIT_BCON_TIMER);
+			mvotg->otg_ctrl.a_wait_bcon_timeout = 0;
+			phy->state = OTG_STATE_A_VBUS_ERR;
+		} else if (otg_ctrl->b_conn) {
+			mv_otg_cancel_timer(mvotg, A_WAIT_BCON_TIMER);
+			mvotg->otg_ctrl.a_wait_bcon_timeout = 0;
+			phy->state = OTG_STATE_A_HOST;
+		}
+		break;
+	case OTG_STATE_A_HOST:
+		if (otg_ctrl->id || !otg_ctrl->b_conn
+		    || otg_ctrl->a_bus_drop)
+			phy->state = OTG_STATE_A_WAIT_BCON;
+		else if (!otg_ctrl->a_vbus_vld)
+			phy->state = OTG_STATE_A_VBUS_ERR;
+		break;
+	case OTG_STATE_A_WAIT_VFALL:
+		if (otg_ctrl->id
+		    || (!otg_ctrl->b_conn && otg_ctrl->a_sess_vld)
+		    || otg_ctrl->a_bus_req)
+			phy->state = OTG_STATE_A_IDLE;
+		break;
+	case OTG_STATE_A_VBUS_ERR:
+		if (otg_ctrl->id || otg_ctrl->a_clr_err
+		    || otg_ctrl->a_bus_drop) {
+			otg_ctrl->a_clr_err = 0;
+			phy->state = OTG_STATE_A_WAIT_VFALL;
+		}
+		break;
+	default:
+		break;
+	}
+}
+
+static void mv_otg_work(struct work_struct *work)
+{
+	struct mv_otg *mvotg;
+	struct usb_phy *phy;
+	struct usb_otg *otg;
+	int old_state;
+
+	mvotg = container_of(to_delayed_work(work), struct mv_otg, work);
+
+run:
+	/* work queue is single thread, or we need spin_lock to protect */
+	phy = &mvotg->phy;
+	otg = phy->otg;
+	old_state = phy->state;
+
+	if (!mvotg->active)
+		return;
+
+	mv_otg_update_inputs(mvotg);
+	mv_otg_update_state(mvotg);
+
+	if (old_state != phy->state) {
+		dev_info(&mvotg->pdev->dev, "change from state %s to %s\n",
+			 state_string[old_state],
+			 state_string[phy->state]);
+
+		switch (phy->state) {
+		case OTG_STATE_B_IDLE:
+			otg->default_a = 0;
+			if (old_state == OTG_STATE_B_PERIPHERAL)
+				mv_otg_start_periphrals(mvotg, 0);
+			mv_otg_reset(mvotg);
+			mv_otg_disable(mvotg);
+			break;
+		case OTG_STATE_B_PERIPHERAL:
+			mv_otg_enable(mvotg);
+			mv_otg_start_periphrals(mvotg, 1);
+			break;
+		case OTG_STATE_A_IDLE:
+			otg->default_a = 1;
+			mv_otg_enable(mvotg);
+			if (old_state == OTG_STATE_A_WAIT_VFALL)
+				mv_otg_start_host(mvotg, 0);
+			mv_otg_reset(mvotg);
+			break;
+		case OTG_STATE_A_WAIT_VRISE:
+			mv_otg_set_vbus(otg, 1);
+			break;
+		case OTG_STATE_A_WAIT_BCON:
+			if (old_state != OTG_STATE_A_HOST)
+				mv_otg_start_host(mvotg, 1);
+			mv_otg_set_timer(mvotg, A_WAIT_BCON_TIMER,
+					 T_A_WAIT_BCON,
+					 mv_otg_timer_await_bcon);
+			/*
+			 * Now, we directly enter A_HOST. So set b_conn = 1
+			 * here. In fact, it need host driver to notify us.
+			 */
+			mvotg->otg_ctrl.b_conn = 1;
+			break;
+		case OTG_STATE_A_HOST:
+			break;
+		case OTG_STATE_A_WAIT_VFALL:
+			/*
+			 * Now, we has exited A_HOST. So set b_conn = 0
+			 * here. In fact, it need host driver to notify us.
+			 */
+			mvotg->otg_ctrl.b_conn = 0;
+			mv_otg_set_vbus(otg, 0);
+			break;
+		case OTG_STATE_A_VBUS_ERR:
+			break;
+		default:
+			break;
+		}
+		goto run;
+	}
+}
+
+static irqreturn_t mv_otg_irq(int irq, void *dev)
+{
+	struct mv_otg *mvotg = dev;
+	u32 otgsc;
+
+	otgsc = readl(&mvotg->op_regs->otgsc);
+	writel(otgsc, &mvotg->op_regs->otgsc);
+
+	/*
+	 * if we have vbus, then the vbus detection for B-device
+	 * will be done by mv_otg_inputs_irq().
+	 */
+	if (mvotg->pdata->vbus)
+		if ((otgsc & OTGSC_STS_USB_ID) &&
+		    !(otgsc & OTGSC_INTSTS_USB_ID))
+			return IRQ_NONE;
+
+	if ((otgsc & mvotg->irq_status) == 0)
+		return IRQ_NONE;
+
+	mv_otg_run_state_machine(mvotg, 0);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t mv_otg_inputs_irq(int irq, void *dev)
+{
+	struct mv_otg *mvotg = dev;
+
+	/* The clock may disabled at this time */
+	if (!mvotg->active) {
+		mv_otg_enable(mvotg);
+		mv_otg_init_irq(mvotg);
+	}
+
+	mv_otg_run_state_machine(mvotg, 0);
+
+	return IRQ_HANDLED;
+}
+
+static ssize_t
+get_a_bus_req(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct mv_otg *mvotg = dev_get_drvdata(dev);
+	return scnprintf(buf, PAGE_SIZE, "%d\n",
+			 mvotg->otg_ctrl.a_bus_req);
+}
+
+static ssize_t
+set_a_bus_req(struct device *dev, struct device_attribute *attr,
+	      const char *buf, size_t count)
+{
+	struct mv_otg *mvotg = dev_get_drvdata(dev);
+
+	if (count > 2)
+		return -1;
+
+	/* We will use this interface to change to A device */
+	if (mvotg->phy.state != OTG_STATE_B_IDLE
+	    && mvotg->phy.state != OTG_STATE_A_IDLE)
+		return -1;
+
+	/* The clock may disabled and we need to set irq for ID detected */
+	mv_otg_enable(mvotg);
+	mv_otg_init_irq(mvotg);
+
+	if (buf[0] == '1') {
+		mvotg->otg_ctrl.a_bus_req = 1;
+		mvotg->otg_ctrl.a_bus_drop = 0;
+		dev_dbg(&mvotg->pdev->dev,
+			"User request: a_bus_req = 1\n");
+
+		if (spin_trylock(&mvotg->wq_lock)) {
+			mv_otg_run_state_machine(mvotg, 0);
+			spin_unlock(&mvotg->wq_lock);
+		}
+	}
+
+	return count;
+}
+
+static DEVICE_ATTR(a_bus_req, S_IRUGO | S_IWUSR, get_a_bus_req,
+		   set_a_bus_req);
+
+static ssize_t
+set_a_clr_err(struct device *dev, struct device_attribute *attr,
+	      const char *buf, size_t count)
+{
+	struct mv_otg *mvotg = dev_get_drvdata(dev);
+	if (!mvotg->phy.otg->default_a)
+		return -1;
+
+	if (count > 2)
+		return -1;
+
+	if (buf[0] == '1') {
+		mvotg->otg_ctrl.a_clr_err = 1;
+		dev_dbg(&mvotg->pdev->dev,
+			"User request: a_clr_err = 1\n");
+	}
+
+	if (spin_trylock(&mvotg->wq_lock)) {
+		mv_otg_run_state_machine(mvotg, 0);
+		spin_unlock(&mvotg->wq_lock);
+	}
+
+	return count;
+}
+
+static DEVICE_ATTR(a_clr_err, S_IWUSR, NULL, set_a_clr_err);
+
+static ssize_t
+get_a_bus_drop(struct device *dev, struct device_attribute *attr,
+	       char *buf)
+{
+	struct mv_otg *mvotg = dev_get_drvdata(dev);
+	return scnprintf(buf, PAGE_SIZE, "%d\n",
+			 mvotg->otg_ctrl.a_bus_drop);
+}
+
+static ssize_t
+set_a_bus_drop(struct device *dev, struct device_attribute *attr,
+	       const char *buf, size_t count)
+{
+	struct mv_otg *mvotg = dev_get_drvdata(dev);
+	if (!mvotg->phy.otg->default_a)
+		return -1;
+
+	if (count > 2)
+		return -1;
+
+	if (buf[0] == '0') {
+		mvotg->otg_ctrl.a_bus_drop = 0;
+		dev_dbg(&mvotg->pdev->dev,
+			"User request: a_bus_drop = 0\n");
+	} else if (buf[0] == '1') {
+		mvotg->otg_ctrl.a_bus_drop = 1;
+		mvotg->otg_ctrl.a_bus_req = 0;
+		dev_dbg(&mvotg->pdev->dev,
+			"User request: a_bus_drop = 1\n");
+		dev_dbg(&mvotg->pdev->dev,
+			"User request: and a_bus_req = 0\n");
+	}
+
+	if (spin_trylock(&mvotg->wq_lock)) {
+		mv_otg_run_state_machine(mvotg, 0);
+		spin_unlock(&mvotg->wq_lock);
+	}
+
+	return count;
+}
+
+static DEVICE_ATTR(a_bus_drop, S_IRUGO | S_IWUSR,
+		   get_a_bus_drop, set_a_bus_drop);
+
+static struct attribute *inputs_attrs[] = {
+	&dev_attr_a_bus_req.attr,
+	&dev_attr_a_clr_err.attr,
+	&dev_attr_a_bus_drop.attr,
+	NULL,
+};
+
+static struct attribute_group inputs_attr_group = {
+	.name = "inputs",
+	.attrs = inputs_attrs,
+};
+
+int mv_otg_remove(struct platform_device *pdev)
+{
+	struct mv_otg *mvotg = platform_get_drvdata(pdev);
+
+	sysfs_remove_group(&mvotg->pdev->dev.kobj, &inputs_attr_group);
+
+	if (mvotg->qwork) {
+		flush_workqueue(mvotg->qwork);
+		destroy_workqueue(mvotg->qwork);
+	}
+
+	mv_otg_disable(mvotg);
+
+	usb_remove_phy(&mvotg->phy);
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+static int mv_otg_probe(struct platform_device *pdev)
+{
+	struct mv_usb_platform_data *pdata = pdev->dev.platform_data;
+	struct mv_otg *mvotg;
+	struct usb_otg *otg;
+	struct resource *r;
+	int retval = 0, i;
+
+	if (pdata == NULL) {
+		dev_err(&pdev->dev, "failed to get platform data\n");
+		return -ENODEV;
+	}
+
+	mvotg = devm_kzalloc(&pdev->dev, sizeof(*mvotg), GFP_KERNEL);
+	if (!mvotg) {
+		dev_err(&pdev->dev, "failed to allocate memory!\n");
+		return -ENOMEM;
+	}
+
+	otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL);
+	if (!otg)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, mvotg);
+
+	mvotg->pdev = pdev;
+	mvotg->pdata = pdata;
+
+	mvotg->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(mvotg->clk))
+		return PTR_ERR(mvotg->clk);
+
+	mvotg->qwork = create_singlethread_workqueue("mv_otg_queue");
+	if (!mvotg->qwork) {
+		dev_dbg(&pdev->dev, "cannot create workqueue for OTG\n");
+		return -ENOMEM;
+	}
+
+	INIT_DELAYED_WORK(&mvotg->work, mv_otg_work);
+
+	/* OTG common part */
+	mvotg->pdev = pdev;
+	mvotg->phy.dev = &pdev->dev;
+	mvotg->phy.otg = otg;
+	mvotg->phy.label = driver_name;
+	mvotg->phy.state = OTG_STATE_UNDEFINED;
+
+	otg->phy = &mvotg->phy;
+	otg->set_host = mv_otg_set_host;
+	otg->set_peripheral = mv_otg_set_peripheral;
+	otg->set_vbus = mv_otg_set_vbus;
+
+	for (i = 0; i < OTG_TIMER_NUM; i++)
+		init_timer(&mvotg->otg_ctrl.timer[i]);
+
+	r = platform_get_resource_byname(mvotg->pdev,
+					 IORESOURCE_MEM, "phyregs");
+	if (r == NULL) {
+		dev_err(&pdev->dev, "no phy I/O memory resource defined\n");
+		retval = -ENODEV;
+		goto err_destroy_workqueue;
+	}
+
+	mvotg->phy_regs = devm_ioremap(&pdev->dev, r->start, resource_size(r));
+	if (mvotg->phy_regs == NULL) {
+		dev_err(&pdev->dev, "failed to map phy I/O memory\n");
+		retval = -EFAULT;
+		goto err_destroy_workqueue;
+	}
+
+	r = platform_get_resource_byname(mvotg->pdev,
+					 IORESOURCE_MEM, "capregs");
+	if (r == NULL) {
+		dev_err(&pdev->dev, "no I/O memory resource defined\n");
+		retval = -ENODEV;
+		goto err_destroy_workqueue;
+	}
+
+	mvotg->cap_regs = devm_ioremap(&pdev->dev, r->start, resource_size(r));
+	if (mvotg->cap_regs == NULL) {
+		dev_err(&pdev->dev, "failed to map I/O memory\n");
+		retval = -EFAULT;
+		goto err_destroy_workqueue;
+	}
+
+	/* we will acces controller register, so enable the udc controller */
+	retval = mv_otg_enable_internal(mvotg);
+	if (retval) {
+		dev_err(&pdev->dev, "mv otg enable error %d\n", retval);
+		goto err_destroy_workqueue;
+	}
+
+	mvotg->op_regs =
+		(struct mv_otg_regs __iomem *) ((unsigned long) mvotg->cap_regs
+			+ (readl(mvotg->cap_regs) & CAPLENGTH_MASK));
+
+	if (pdata->id) {
+		retval = devm_request_threaded_irq(&pdev->dev, pdata->id->irq,
+						NULL, mv_otg_inputs_irq,
+						IRQF_ONESHOT, "id", mvotg);
+		if (retval) {
+			dev_info(&pdev->dev,
+				 "Failed to request irq for ID\n");
+			pdata->id = NULL;
+		}
+	}
+
+	if (pdata->vbus) {
+		mvotg->clock_gating = 1;
+		retval = devm_request_threaded_irq(&pdev->dev, pdata->vbus->irq,
+						NULL, mv_otg_inputs_irq,
+						IRQF_ONESHOT, "vbus", mvotg);
+		if (retval) {
+			dev_info(&pdev->dev,
+				 "Failed to request irq for VBUS, "
+				 "disable clock gating\n");
+			mvotg->clock_gating = 0;
+			pdata->vbus = NULL;
+		}
+	}
+
+	if (pdata->disable_otg_clock_gating)
+		mvotg->clock_gating = 0;
+
+	mv_otg_reset(mvotg);
+	mv_otg_init_irq(mvotg);
+
+	r = platform_get_resource(mvotg->pdev, IORESOURCE_IRQ, 0);
+	if (r == NULL) {
+		dev_err(&pdev->dev, "no IRQ resource defined\n");
+		retval = -ENODEV;
+		goto err_disable_clk;
+	}
+
+	mvotg->irq = r->start;
+	if (devm_request_irq(&pdev->dev, mvotg->irq, mv_otg_irq, IRQF_SHARED,
+			driver_name, mvotg)) {
+		dev_err(&pdev->dev, "Request irq %d for OTG failed\n",
+			mvotg->irq);
+		mvotg->irq = 0;
+		retval = -ENODEV;
+		goto err_disable_clk;
+	}
+
+	retval = usb_add_phy(&mvotg->phy, USB_PHY_TYPE_USB2);
+	if (retval < 0) {
+		dev_err(&pdev->dev, "can't register transceiver, %d\n",
+			retval);
+		goto err_disable_clk;
+	}
+
+	retval = sysfs_create_group(&pdev->dev.kobj, &inputs_attr_group);
+	if (retval < 0) {
+		dev_dbg(&pdev->dev,
+			"Can't register sysfs attr group: %d\n", retval);
+		goto err_remove_phy;
+	}
+
+	spin_lock_init(&mvotg->wq_lock);
+	if (spin_trylock(&mvotg->wq_lock)) {
+		mv_otg_run_state_machine(mvotg, 2 * HZ);
+		spin_unlock(&mvotg->wq_lock);
+	}
+
+	dev_info(&pdev->dev,
+		 "successful probe OTG device %s clock gating.\n",
+		 mvotg->clock_gating ? "with" : "without");
+
+	return 0;
+
+err_remove_phy:
+	usb_remove_phy(&mvotg->phy);
+err_disable_clk:
+	mv_otg_disable_internal(mvotg);
+err_destroy_workqueue:
+	flush_workqueue(mvotg->qwork);
+	destroy_workqueue(mvotg->qwork);
+
+	platform_set_drvdata(pdev, NULL);
+
+	return retval;
+}
+
+#ifdef CONFIG_PM
+static int mv_otg_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct mv_otg *mvotg = platform_get_drvdata(pdev);
+
+	if (mvotg->phy.state != OTG_STATE_B_IDLE) {
+		dev_info(&pdev->dev,
+			 "OTG state is not B_IDLE, it is %d!\n",
+			 mvotg->phy.state);
+		return -EAGAIN;
+	}
+
+	if (!mvotg->clock_gating)
+		mv_otg_disable_internal(mvotg);
+
+	return 0;
+}
+
+static int mv_otg_resume(struct platform_device *pdev)
+{
+	struct mv_otg *mvotg = platform_get_drvdata(pdev);
+	u32 otgsc;
+
+	if (!mvotg->clock_gating) {
+		mv_otg_enable_internal(mvotg);
+
+		otgsc = readl(&mvotg->op_regs->otgsc);
+		otgsc |= mvotg->irq_en;
+		writel(otgsc, &mvotg->op_regs->otgsc);
+
+		if (spin_trylock(&mvotg->wq_lock)) {
+			mv_otg_run_state_machine(mvotg, 0);
+			spin_unlock(&mvotg->wq_lock);
+		}
+	}
+	return 0;
+}
+#endif
+
+static struct platform_driver mv_otg_driver = {
+	.probe = mv_otg_probe,
+	.remove = __exit_p(mv_otg_remove),
+	.driver = {
+		   .owner = THIS_MODULE,
+		   .name = driver_name,
+		   },
+#ifdef CONFIG_PM
+	.suspend = mv_otg_suspend,
+	.resume = mv_otg_resume,
+#endif
+};
+module_platform_driver(mv_otg_driver);
diff --git a/drivers/usb/phy/phy-mv-usb.h b/drivers/usb/phy/phy-mv-usb.h
new file mode 100644
index 0000000..551da6e
--- /dev/null
+++ b/drivers/usb/phy/phy-mv-usb.h
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2011 Marvell International 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 as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#ifndef	__MV_USB_OTG_CONTROLLER__
+#define	__MV_USB_OTG_CONTROLLER__
+
+#include <linux/types.h>
+
+/* Command Register Bit Masks */
+#define USBCMD_RUN_STOP			(0x00000001)
+#define USBCMD_CTRL_RESET		(0x00000002)
+
+/* otgsc Register Bit Masks */
+#define OTGSC_CTRL_VUSB_DISCHARGE		0x00000001
+#define OTGSC_CTRL_VUSB_CHARGE			0x00000002
+#define OTGSC_CTRL_OTG_TERM			0x00000008
+#define OTGSC_CTRL_DATA_PULSING			0x00000010
+#define OTGSC_STS_USB_ID			0x00000100
+#define OTGSC_STS_A_VBUS_VALID			0x00000200
+#define OTGSC_STS_A_SESSION_VALID		0x00000400
+#define OTGSC_STS_B_SESSION_VALID		0x00000800
+#define OTGSC_STS_B_SESSION_END			0x00001000
+#define OTGSC_STS_1MS_TOGGLE			0x00002000
+#define OTGSC_STS_DATA_PULSING			0x00004000
+#define OTGSC_INTSTS_USB_ID			0x00010000
+#define OTGSC_INTSTS_A_VBUS_VALID		0x00020000
+#define OTGSC_INTSTS_A_SESSION_VALID		0x00040000
+#define OTGSC_INTSTS_B_SESSION_VALID		0x00080000
+#define OTGSC_INTSTS_B_SESSION_END		0x00100000
+#define OTGSC_INTSTS_1MS			0x00200000
+#define OTGSC_INTSTS_DATA_PULSING		0x00400000
+#define OTGSC_INTR_USB_ID			0x01000000
+#define OTGSC_INTR_A_VBUS_VALID			0x02000000
+#define OTGSC_INTR_A_SESSION_VALID		0x04000000
+#define OTGSC_INTR_B_SESSION_VALID		0x08000000
+#define OTGSC_INTR_B_SESSION_END		0x10000000
+#define OTGSC_INTR_1MS_TIMER			0x20000000
+#define OTGSC_INTR_DATA_PULSING			0x40000000
+
+#define CAPLENGTH_MASK		(0xff)
+
+/* Timer's interval, unit 10ms */
+#define T_A_WAIT_VRISE		100
+#define T_A_WAIT_BCON		2000
+#define T_A_AIDL_BDIS		100
+#define T_A_BIDL_ADIS		20
+#define T_B_ASE0_BRST		400
+#define T_B_SE0_SRP		300
+#define T_B_SRP_FAIL		2000
+#define T_B_DATA_PLS		10
+#define T_B_SRP_INIT		100
+#define T_A_SRP_RSPNS		10
+#define T_A_DRV_RSM		5
+
+enum otg_function {
+	OTG_B_DEVICE = 0,
+	OTG_A_DEVICE
+};
+
+enum mv_otg_timer {
+	A_WAIT_BCON_TIMER = 0,
+	OTG_TIMER_NUM
+};
+
+/* PXA OTG state machine */
+struct mv_otg_ctrl {
+	/* internal variables */
+	u8 a_set_b_hnp_en;	/* A-Device set b_hnp_en */
+	u8 b_srp_done;
+	u8 b_hnp_en;
+
+	/* OTG inputs */
+	u8 a_bus_drop;
+	u8 a_bus_req;
+	u8 a_clr_err;
+	u8 a_bus_resume;
+	u8 a_bus_suspend;
+	u8 a_conn;
+	u8 a_sess_vld;
+	u8 a_srp_det;
+	u8 a_vbus_vld;
+	u8 b_bus_req;		/* B-Device Require Bus */
+	u8 b_bus_resume;
+	u8 b_bus_suspend;
+	u8 b_conn;
+	u8 b_se0_srp;
+	u8 b_sess_end;
+	u8 b_sess_vld;
+	u8 id;
+	u8 a_suspend_req;
+
+	/*Timer event */
+	u8 a_aidl_bdis_timeout;
+	u8 b_ase0_brst_timeout;
+	u8 a_bidl_adis_timeout;
+	u8 a_wait_bcon_timeout;
+
+	struct timer_list timer[OTG_TIMER_NUM];
+};
+
+#define VUSBHS_MAX_PORTS	8
+
+struct mv_otg_regs {
+	u32 usbcmd;		/* Command register */
+	u32 usbsts;		/* Status register */
+	u32 usbintr;		/* Interrupt enable */
+	u32 frindex;		/* Frame index */
+	u32 reserved1[1];
+	u32 deviceaddr;		/* Device Address */
+	u32 eplistaddr;		/* Endpoint List Address */
+	u32 ttctrl;		/* HOST TT status and control */
+	u32 burstsize;		/* Programmable Burst Size */
+	u32 txfilltuning;	/* Host Transmit Pre-Buffer Packet Tuning */
+	u32 reserved[4];
+	u32 epnak;		/* Endpoint NAK */
+	u32 epnaken;		/* Endpoint NAK Enable */
+	u32 configflag;		/* Configured Flag register */
+	u32 portsc[VUSBHS_MAX_PORTS];	/* Port Status/Control x, x = 1..8 */
+	u32 otgsc;
+	u32 usbmode;		/* USB Host/Device mode */
+	u32 epsetupstat;	/* Endpoint Setup Status */
+	u32 epprime;		/* Endpoint Initialize */
+	u32 epflush;		/* Endpoint De-initialize */
+	u32 epstatus;		/* Endpoint Status */
+	u32 epcomplete;		/* Endpoint Interrupt On Complete */
+	u32 epctrlx[16];	/* Endpoint Control, where x = 0.. 15 */
+	u32 mcr;		/* Mux Control */
+	u32 isr;		/* Interrupt Status */
+	u32 ier;		/* Interrupt Enable */
+};
+
+struct mv_otg {
+	struct usb_phy phy;
+	struct mv_otg_ctrl otg_ctrl;
+
+	/* base address */
+	void __iomem *phy_regs;
+	void __iomem *cap_regs;
+	struct mv_otg_regs __iomem *op_regs;
+
+	struct platform_device *pdev;
+	int irq;
+	u32 irq_status;
+	u32 irq_en;
+
+	struct delayed_work work;
+	struct workqueue_struct *qwork;
+
+	spinlock_t wq_lock;
+
+	struct mv_usb_platform_data *pdata;
+
+	unsigned int active;
+	unsigned int clock_gating;
+	struct clk *clk;
+};
+
+#endif
diff --git a/drivers/usb/phy/phy-mxs-usb.c b/drivers/usb/phy/phy-mxs-usb.c
new file mode 100644
index 0000000..9d4381e
--- /dev/null
+++ b/drivers/usb/phy/phy-mxs-usb.c
@@ -0,0 +1,220 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ * Copyright (C) 2012 Marek Vasut <marex@denx.de>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * 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/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/usb/otg.h>
+#include <linux/stmp_device.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+
+#define DRIVER_NAME "mxs_phy"
+
+#define HW_USBPHY_PWD				0x00
+#define HW_USBPHY_CTRL				0x30
+#define HW_USBPHY_CTRL_SET			0x34
+#define HW_USBPHY_CTRL_CLR			0x38
+
+#define BM_USBPHY_CTRL_SFTRST			BIT(31)
+#define BM_USBPHY_CTRL_CLKGATE			BIT(30)
+#define BM_USBPHY_CTRL_ENUTMILEVEL3		BIT(15)
+#define BM_USBPHY_CTRL_ENUTMILEVEL2		BIT(14)
+#define BM_USBPHY_CTRL_ENHOSTDISCONDETECT	BIT(1)
+
+struct mxs_phy {
+	struct usb_phy phy;
+	struct clk *clk;
+};
+
+#define to_mxs_phy(p) container_of((p), struct mxs_phy, phy)
+
+static void mxs_phy_hw_init(struct mxs_phy *mxs_phy)
+{
+	void __iomem *base = mxs_phy->phy.io_priv;
+
+	stmp_reset_block(base + HW_USBPHY_CTRL);
+
+	/* Power up the PHY */
+	writel(0, base + HW_USBPHY_PWD);
+
+	/* enable FS/LS device */
+	writel(BM_USBPHY_CTRL_ENUTMILEVEL2 |
+	       BM_USBPHY_CTRL_ENUTMILEVEL3,
+	       base + HW_USBPHY_CTRL_SET);
+}
+
+static int mxs_phy_init(struct usb_phy *phy)
+{
+	struct mxs_phy *mxs_phy = to_mxs_phy(phy);
+
+	clk_prepare_enable(mxs_phy->clk);
+	mxs_phy_hw_init(mxs_phy);
+
+	return 0;
+}
+
+static void mxs_phy_shutdown(struct usb_phy *phy)
+{
+	struct mxs_phy *mxs_phy = to_mxs_phy(phy);
+
+	writel(BM_USBPHY_CTRL_CLKGATE,
+	       phy->io_priv + HW_USBPHY_CTRL_SET);
+
+	clk_disable_unprepare(mxs_phy->clk);
+}
+
+static int mxs_phy_suspend(struct usb_phy *x, int suspend)
+{
+	struct mxs_phy *mxs_phy = to_mxs_phy(x);
+
+	if (suspend) {
+		writel(0xffffffff, x->io_priv + HW_USBPHY_PWD);
+		writel(BM_USBPHY_CTRL_CLKGATE,
+		       x->io_priv + HW_USBPHY_CTRL_SET);
+		clk_disable_unprepare(mxs_phy->clk);
+	} else {
+		clk_prepare_enable(mxs_phy->clk);
+		writel(BM_USBPHY_CTRL_CLKGATE,
+		       x->io_priv + HW_USBPHY_CTRL_CLR);
+		writel(0, x->io_priv + HW_USBPHY_PWD);
+	}
+
+	return 0;
+}
+
+static int mxs_phy_on_connect(struct usb_phy *phy,
+		enum usb_device_speed speed)
+{
+	dev_dbg(phy->dev, "%s speed device has connected\n",
+		(speed == USB_SPEED_HIGH) ? "high" : "non-high");
+
+	if (speed == USB_SPEED_HIGH)
+		writel(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
+		       phy->io_priv + HW_USBPHY_CTRL_SET);
+
+	return 0;
+}
+
+static int mxs_phy_on_disconnect(struct usb_phy *phy,
+		enum usb_device_speed speed)
+{
+	dev_dbg(phy->dev, "%s speed device has disconnected\n",
+		(speed == USB_SPEED_HIGH) ? "high" : "non-high");
+
+	if (speed == USB_SPEED_HIGH)
+		writel(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
+		       phy->io_priv + HW_USBPHY_CTRL_CLR);
+
+	return 0;
+}
+
+static int mxs_phy_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	void __iomem *base;
+	struct clk *clk;
+	struct mxs_phy *mxs_phy;
+	int ret;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "can't get device resources\n");
+		return -ENOENT;
+	}
+
+	base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(clk)) {
+		dev_err(&pdev->dev,
+			"can't get the clock, err=%ld", PTR_ERR(clk));
+		return PTR_ERR(clk);
+	}
+
+	mxs_phy = devm_kzalloc(&pdev->dev, sizeof(*mxs_phy), GFP_KERNEL);
+	if (!mxs_phy) {
+		dev_err(&pdev->dev, "Failed to allocate USB PHY structure!\n");
+		return -ENOMEM;
+	}
+
+	mxs_phy->phy.io_priv		= base;
+	mxs_phy->phy.dev		= &pdev->dev;
+	mxs_phy->phy.label		= DRIVER_NAME;
+	mxs_phy->phy.init		= mxs_phy_init;
+	mxs_phy->phy.shutdown		= mxs_phy_shutdown;
+	mxs_phy->phy.set_suspend	= mxs_phy_suspend;
+	mxs_phy->phy.notify_connect	= mxs_phy_on_connect;
+	mxs_phy->phy.notify_disconnect	= mxs_phy_on_disconnect;
+
+	ATOMIC_INIT_NOTIFIER_HEAD(&mxs_phy->phy.notifier);
+
+	mxs_phy->clk = clk;
+
+	platform_set_drvdata(pdev, &mxs_phy->phy);
+
+	ret = usb_add_phy_dev(&mxs_phy->phy);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int mxs_phy_remove(struct platform_device *pdev)
+{
+	struct mxs_phy *mxs_phy = platform_get_drvdata(pdev);
+
+	usb_remove_phy(&mxs_phy->phy);
+
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+static const struct of_device_id mxs_phy_dt_ids[] = {
+	{ .compatible = "fsl,imx23-usbphy", },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, mxs_phy_dt_ids);
+
+static struct platform_driver mxs_phy_driver = {
+	.probe = mxs_phy_probe,
+	.remove = mxs_phy_remove,
+	.driver = {
+		.name = DRIVER_NAME,
+		.owner	= THIS_MODULE,
+		.of_match_table = mxs_phy_dt_ids,
+	 },
+};
+
+static int __init mxs_phy_module_init(void)
+{
+	return platform_driver_register(&mxs_phy_driver);
+}
+postcore_initcall(mxs_phy_module_init);
+
+static void __exit mxs_phy_module_exit(void)
+{
+	platform_driver_unregister(&mxs_phy_driver);
+}
+module_exit(mxs_phy_module_exit);
+
+MODULE_ALIAS("platform:mxs-usb-phy");
+MODULE_AUTHOR("Marek Vasut <marex@denx.de>");
+MODULE_AUTHOR("Richard Zhao <richard.zhao@freescale.com>");
+MODULE_DESCRIPTION("Freescale MXS USB PHY driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/phy/phy-nop.c b/drivers/usb/phy/phy-nop.c
new file mode 100644
index 0000000..2b10cc9
--- /dev/null
+++ b/drivers/usb/phy/phy-nop.c
@@ -0,0 +1,294 @@
+/*
+ * drivers/usb/otg/nop-usb-xceiv.c
+ *
+ * NOP USB transceiver for all USB transceiver which are either built-in
+ * into USB IP or which are mostly autonomous.
+ *
+ * Copyright (C) 2009 Texas Instruments Inc
+ * Author: Ajay Kumar Gupta <ajay.gupta@ti.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.
+ *
+ * Current status:
+ *	This provides a "nop" transceiver for PHYs which are
+ *	autonomous such as isp1504, isp1707, etc.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/usb/otg.h>
+#include <linux/usb/nop-usb-xceiv.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/regulator/consumer.h>
+#include <linux/of.h>
+
+struct nop_usb_xceiv {
+	struct usb_phy phy;
+	struct device *dev;
+	struct clk *clk;
+	struct regulator *vcc;
+	struct regulator *reset;
+};
+
+static struct platform_device *pd;
+
+void usb_nop_xceiv_register(void)
+{
+	if (pd)
+		return;
+	pd = platform_device_register_simple("nop_usb_xceiv", -1, NULL, 0);
+	if (!pd) {
+		printk(KERN_ERR "Unable to register usb nop transceiver\n");
+		return;
+	}
+}
+EXPORT_SYMBOL(usb_nop_xceiv_register);
+
+void usb_nop_xceiv_unregister(void)
+{
+	platform_device_unregister(pd);
+	pd = NULL;
+}
+EXPORT_SYMBOL(usb_nop_xceiv_unregister);
+
+static int nop_set_suspend(struct usb_phy *x, int suspend)
+{
+	return 0;
+}
+
+static int nop_init(struct usb_phy *phy)
+{
+	struct nop_usb_xceiv *nop = dev_get_drvdata(phy->dev);
+
+	if (!IS_ERR(nop->vcc)) {
+		if (regulator_enable(nop->vcc))
+			dev_err(phy->dev, "Failed to enable power\n");
+	}
+
+	if (!IS_ERR(nop->clk))
+		clk_enable(nop->clk);
+
+	if (!IS_ERR(nop->reset)) {
+		/* De-assert RESET */
+		if (regulator_enable(nop->reset))
+			dev_err(phy->dev, "Failed to de-assert reset\n");
+	}
+
+	return 0;
+}
+
+static void nop_shutdown(struct usb_phy *phy)
+{
+	struct nop_usb_xceiv *nop = dev_get_drvdata(phy->dev);
+
+	if (!IS_ERR(nop->reset)) {
+		/* Assert RESET */
+		if (regulator_disable(nop->reset))
+			dev_err(phy->dev, "Failed to assert reset\n");
+	}
+
+	if (!IS_ERR(nop->clk))
+		clk_disable(nop->clk);
+
+	if (!IS_ERR(nop->vcc)) {
+		if (regulator_disable(nop->vcc))
+			dev_err(phy->dev, "Failed to disable power\n");
+	}
+}
+
+static int nop_set_peripheral(struct usb_otg *otg, struct usb_gadget *gadget)
+{
+	if (!otg)
+		return -ENODEV;
+
+	if (!gadget) {
+		otg->gadget = NULL;
+		return -ENODEV;
+	}
+
+	otg->gadget = gadget;
+	otg->phy->state = OTG_STATE_B_IDLE;
+	return 0;
+}
+
+static int nop_set_host(struct usb_otg *otg, struct usb_bus *host)
+{
+	if (!otg)
+		return -ENODEV;
+
+	if (!host) {
+		otg->host = NULL;
+		return -ENODEV;
+	}
+
+	otg->host = host;
+	return 0;
+}
+
+static int nop_usb_xceiv_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct nop_usb_xceiv_platform_data *pdata = pdev->dev.platform_data;
+	struct nop_usb_xceiv	*nop;
+	enum usb_phy_type	type = USB_PHY_TYPE_USB2;
+	int err;
+	u32 clk_rate = 0;
+	bool needs_vcc = false;
+	bool needs_reset = false;
+
+	nop = devm_kzalloc(&pdev->dev, sizeof(*nop), GFP_KERNEL);
+	if (!nop)
+		return -ENOMEM;
+
+	nop->phy.otg = devm_kzalloc(&pdev->dev, sizeof(*nop->phy.otg),
+							GFP_KERNEL);
+	if (!nop->phy.otg)
+		return -ENOMEM;
+
+	if (dev->of_node) {
+		struct device_node *node = dev->of_node;
+
+		if (of_property_read_u32(node, "clock-frequency", &clk_rate))
+			clk_rate = 0;
+
+		needs_vcc = of_property_read_bool(node, "vcc-supply");
+		needs_reset = of_property_read_bool(node, "reset-supply");
+
+	} else if (pdata) {
+		type = pdata->type;
+		clk_rate = pdata->clk_rate;
+		needs_vcc = pdata->needs_vcc;
+		needs_reset = pdata->needs_reset;
+	}
+
+	nop->clk = devm_clk_get(&pdev->dev, "main_clk");
+	if (IS_ERR(nop->clk)) {
+		dev_dbg(&pdev->dev, "Can't get phy clock: %ld\n",
+					PTR_ERR(nop->clk));
+	}
+
+	if (!IS_ERR(nop->clk) && clk_rate) {
+		err = clk_set_rate(nop->clk, clk_rate);
+		if (err) {
+			dev_err(&pdev->dev, "Error setting clock rate\n");
+			return err;
+		}
+	}
+
+	if (!IS_ERR(nop->clk)) {
+		err = clk_prepare(nop->clk);
+		if (err) {
+			dev_err(&pdev->dev, "Error preparing clock\n");
+			return err;
+		}
+	}
+
+	nop->vcc = devm_regulator_get(&pdev->dev, "vcc");
+	if (IS_ERR(nop->vcc)) {
+		dev_dbg(&pdev->dev, "Error getting vcc regulator: %ld\n",
+					PTR_ERR(nop->vcc));
+		if (needs_vcc)
+			return -EPROBE_DEFER;
+	}
+
+	nop->reset = devm_regulator_get(&pdev->dev, "reset");
+	if (IS_ERR(nop->reset)) {
+		dev_dbg(&pdev->dev, "Error getting reset regulator: %ld\n",
+					PTR_ERR(nop->reset));
+		if (needs_reset)
+			return -EPROBE_DEFER;
+	}
+
+	nop->dev		= &pdev->dev;
+	nop->phy.dev		= nop->dev;
+	nop->phy.label		= "nop-xceiv";
+	nop->phy.set_suspend	= nop_set_suspend;
+	nop->phy.init		= nop_init;
+	nop->phy.shutdown	= nop_shutdown;
+	nop->phy.state		= OTG_STATE_UNDEFINED;
+	nop->phy.type		= type;
+
+	nop->phy.otg->phy		= &nop->phy;
+	nop->phy.otg->set_host		= nop_set_host;
+	nop->phy.otg->set_peripheral	= nop_set_peripheral;
+
+	err = usb_add_phy_dev(&nop->phy);
+	if (err) {
+		dev_err(&pdev->dev, "can't register transceiver, err: %d\n",
+			err);
+		goto err_add;
+	}
+
+	platform_set_drvdata(pdev, nop);
+
+	ATOMIC_INIT_NOTIFIER_HEAD(&nop->phy.notifier);
+
+	return 0;
+
+err_add:
+	if (!IS_ERR(nop->clk))
+		clk_unprepare(nop->clk);
+	return err;
+}
+
+static int nop_usb_xceiv_remove(struct platform_device *pdev)
+{
+	struct nop_usb_xceiv *nop = platform_get_drvdata(pdev);
+
+	if (!IS_ERR(nop->clk))
+		clk_unprepare(nop->clk);
+
+	usb_remove_phy(&nop->phy);
+
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+static const struct of_device_id nop_xceiv_dt_ids[] = {
+	{ .compatible = "usb-nop-xceiv" },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(of, nop_xceiv_dt_ids);
+
+static struct platform_driver nop_usb_xceiv_driver = {
+	.probe		= nop_usb_xceiv_probe,
+	.remove		= nop_usb_xceiv_remove,
+	.driver		= {
+		.name	= "nop_usb_xceiv",
+		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(nop_xceiv_dt_ids),
+	},
+};
+
+static int __init nop_usb_xceiv_init(void)
+{
+	return platform_driver_register(&nop_usb_xceiv_driver);
+}
+subsys_initcall(nop_usb_xceiv_init);
+
+static void __exit nop_usb_xceiv_exit(void)
+{
+	platform_driver_unregister(&nop_usb_xceiv_driver);
+}
+module_exit(nop_usb_xceiv_exit);
+
+MODULE_ALIAS("platform:nop_usb_xceiv");
+MODULE_AUTHOR("Texas Instruments Inc");
+MODULE_DESCRIPTION("NOP USB Transceiver driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/phy/phy-omap-control.c b/drivers/usb/phy/phy-omap-control.c
new file mode 100644
index 0000000..1419ced
--- /dev/null
+++ b/drivers/usb/phy/phy-omap-control.c
@@ -0,0 +1,289 @@
+/*
+ * omap-control-usb.c - The USB part of control module.
+ *
+ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.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.
+ *
+ * Author: Kishon Vijay Abraham I <kishon@ti.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.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/usb/omap_control_usb.h>
+
+static struct omap_control_usb *control_usb;
+
+/**
+ * omap_get_control_dev - returns the device pointer for this control device
+ *
+ * This API should be called to get the device pointer for this control
+ * module device. This device pointer should be used for called other
+ * exported API's in this driver.
+ *
+ * To be used by PHY driver and glue driver.
+ */
+struct device *omap_get_control_dev(void)
+{
+	if (!control_usb)
+		return ERR_PTR(-ENODEV);
+
+	return control_usb->dev;
+}
+EXPORT_SYMBOL_GPL(omap_get_control_dev);
+
+/**
+ * omap_control_usb3_phy_power - power on/off the serializer using control
+ *	module
+ * @dev: the control module device
+ * @on: 0 to off and 1 to on based on powering on or off the PHY
+ *
+ * usb3 PHY driver should call this API to power on or off the PHY.
+ */
+void omap_control_usb3_phy_power(struct device *dev, bool on)
+{
+	u32 val;
+	unsigned long rate;
+	struct omap_control_usb	*control_usb = dev_get_drvdata(dev);
+
+	if (control_usb->type != OMAP_CTRL_DEV_TYPE2)
+		return;
+
+	rate = clk_get_rate(control_usb->sys_clk);
+	rate = rate/1000000;
+
+	val = readl(control_usb->phy_power);
+
+	if (on) {
+		val &= ~(OMAP_CTRL_USB_PWRCTL_CLK_CMD_MASK |
+			OMAP_CTRL_USB_PWRCTL_CLK_FREQ_MASK);
+		val |= OMAP_CTRL_USB3_PHY_TX_RX_POWERON <<
+			OMAP_CTRL_USB_PWRCTL_CLK_CMD_SHIFT;
+		val |= rate << OMAP_CTRL_USB_PWRCTL_CLK_FREQ_SHIFT;
+	} else {
+		val &= ~OMAP_CTRL_USB_PWRCTL_CLK_CMD_MASK;
+		val |= OMAP_CTRL_USB3_PHY_TX_RX_POWEROFF <<
+			OMAP_CTRL_USB_PWRCTL_CLK_CMD_SHIFT;
+	}
+
+	writel(val, control_usb->phy_power);
+}
+EXPORT_SYMBOL_GPL(omap_control_usb3_phy_power);
+
+/**
+ * omap_control_usb_phy_power - power on/off the phy using control module reg
+ * @dev: the control module device
+ * @on: 0 or 1, based on powering on or off the PHY
+ */
+void omap_control_usb_phy_power(struct device *dev, int on)
+{
+	u32 val;
+	struct omap_control_usb	*control_usb = dev_get_drvdata(dev);
+
+	val = readl(control_usb->dev_conf);
+
+	if (on)
+		val &= ~OMAP_CTRL_DEV_PHY_PD;
+	else
+		val |= OMAP_CTRL_DEV_PHY_PD;
+
+	writel(val, control_usb->dev_conf);
+}
+EXPORT_SYMBOL_GPL(omap_control_usb_phy_power);
+
+/**
+ * omap_control_usb_host_mode - set AVALID, VBUSVALID and ID pin in grounded
+ * @ctrl_usb: struct omap_control_usb *
+ *
+ * Writes to the mailbox register to notify the usb core that a usb
+ * device has been connected.
+ */
+static void omap_control_usb_host_mode(struct omap_control_usb *ctrl_usb)
+{
+	u32 val;
+
+	val = readl(ctrl_usb->otghs_control);
+	val &= ~(OMAP_CTRL_DEV_IDDIG | OMAP_CTRL_DEV_SESSEND);
+	val |= OMAP_CTRL_DEV_AVALID | OMAP_CTRL_DEV_VBUSVALID;
+	writel(val, ctrl_usb->otghs_control);
+}
+
+/**
+ * omap_control_usb_device_mode - set AVALID, VBUSVALID and ID pin in high
+ * impedance
+ * @ctrl_usb: struct omap_control_usb *
+ *
+ * Writes to the mailbox register to notify the usb core that it has been
+ * connected to a usb host.
+ */
+static void omap_control_usb_device_mode(struct omap_control_usb *ctrl_usb)
+{
+	u32 val;
+
+	val = readl(ctrl_usb->otghs_control);
+	val &= ~OMAP_CTRL_DEV_SESSEND;
+	val |= OMAP_CTRL_DEV_IDDIG | OMAP_CTRL_DEV_AVALID |
+		OMAP_CTRL_DEV_VBUSVALID;
+	writel(val, ctrl_usb->otghs_control);
+}
+
+/**
+ * omap_control_usb_set_sessionend - Enable SESSIONEND and IDIG to high
+ * impedance
+ * @ctrl_usb: struct omap_control_usb *
+ *
+ * Writes to the mailbox register to notify the usb core it's now in
+ * disconnected state.
+ */
+static void omap_control_usb_set_sessionend(struct omap_control_usb *ctrl_usb)
+{
+	u32 val;
+
+	val = readl(ctrl_usb->otghs_control);
+	val &= ~(OMAP_CTRL_DEV_AVALID | OMAP_CTRL_DEV_VBUSVALID);
+	val |= OMAP_CTRL_DEV_IDDIG | OMAP_CTRL_DEV_SESSEND;
+	writel(val, ctrl_usb->otghs_control);
+}
+
+/**
+ * omap_control_usb_set_mode - Calls to functions to set USB in one of host mode
+ * or device mode or to denote disconnected state
+ * @dev: the control module device
+ * @mode: The mode to which usb should be configured
+ *
+ * This is an API to write to the mailbox register to notify the usb core that
+ * a usb device has been connected.
+ */
+void omap_control_usb_set_mode(struct device *dev,
+	enum omap_control_usb_mode mode)
+{
+	struct omap_control_usb	*ctrl_usb;
+
+	if (IS_ERR(dev) || control_usb->type != OMAP_CTRL_DEV_TYPE1)
+		return;
+
+	ctrl_usb = dev_get_drvdata(dev);
+
+	switch (mode) {
+	case USB_MODE_HOST:
+		omap_control_usb_host_mode(ctrl_usb);
+		break;
+	case USB_MODE_DEVICE:
+		omap_control_usb_device_mode(ctrl_usb);
+		break;
+	case USB_MODE_DISCONNECT:
+		omap_control_usb_set_sessionend(ctrl_usb);
+		break;
+	default:
+		dev_vdbg(dev, "invalid omap control usb mode\n");
+	}
+}
+EXPORT_SYMBOL_GPL(omap_control_usb_set_mode);
+
+static int omap_control_usb_probe(struct platform_device *pdev)
+{
+	struct resource	*res;
+	struct device_node *np = pdev->dev.of_node;
+	struct omap_control_usb_platform_data *pdata = pdev->dev.platform_data;
+
+	control_usb = devm_kzalloc(&pdev->dev, sizeof(*control_usb),
+		GFP_KERNEL);
+	if (!control_usb) {
+		dev_err(&pdev->dev, "unable to alloc memory for control usb\n");
+		return -ENOMEM;
+	}
+
+	if (np) {
+		of_property_read_u32(np, "ti,type", &control_usb->type);
+	} else if (pdata) {
+		control_usb->type = pdata->type;
+	} else {
+		dev_err(&pdev->dev, "no pdata present\n");
+		return -EINVAL;
+	}
+
+	control_usb->dev	= &pdev->dev;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+		"control_dev_conf");
+	control_usb->dev_conf = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(control_usb->dev_conf))
+		return PTR_ERR(control_usb->dev_conf);
+
+	if (control_usb->type == OMAP_CTRL_DEV_TYPE1) {
+		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+			"otghs_control");
+		control_usb->otghs_control = devm_ioremap_resource(
+			&pdev->dev, res);
+		if (IS_ERR(control_usb->otghs_control))
+			return PTR_ERR(control_usb->otghs_control);
+	}
+
+	if (control_usb->type == OMAP_CTRL_DEV_TYPE2) {
+		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+			"phy_power_usb");
+		control_usb->phy_power = devm_ioremap_resource(
+			&pdev->dev, res);
+		if (IS_ERR(control_usb->phy_power))
+			return PTR_ERR(control_usb->phy_power);
+
+		control_usb->sys_clk = devm_clk_get(control_usb->dev,
+			"sys_clkin");
+		if (IS_ERR(control_usb->sys_clk)) {
+			pr_err("%s: unable to get sys_clkin\n", __func__);
+			return -EINVAL;
+		}
+	}
+
+
+	dev_set_drvdata(control_usb->dev, control_usb);
+
+	return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id omap_control_usb_id_table[] = {
+	{ .compatible = "ti,omap-control-usb" },
+	{}
+};
+MODULE_DEVICE_TABLE(of, omap_control_usb_id_table);
+#endif
+
+static struct platform_driver omap_control_usb_driver = {
+	.probe		= omap_control_usb_probe,
+	.driver		= {
+		.name	= "omap-control-usb",
+		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(omap_control_usb_id_table),
+	},
+};
+
+static int __init omap_control_usb_init(void)
+{
+	return platform_driver_register(&omap_control_usb_driver);
+}
+subsys_initcall(omap_control_usb_init);
+
+static void __exit omap_control_usb_exit(void)
+{
+	platform_driver_unregister(&omap_control_usb_driver);
+}
+module_exit(omap_control_usb_exit);
+
+MODULE_ALIAS("platform: omap_control_usb");
+MODULE_AUTHOR("Texas Instruments Inc.");
+MODULE_DESCRIPTION("OMAP Control Module USB Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/phy/phy-omap-usb2.c b/drivers/usb/phy/phy-omap-usb2.c
new file mode 100644
index 0000000..844ab68
--- /dev/null
+++ b/drivers/usb/phy/phy-omap-usb2.c
@@ -0,0 +1,273 @@
+/*
+ * omap-usb2.c - USB PHY, talking to musb controller in OMAP.
+ *
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.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.
+ *
+ * Author: Kishon Vijay Abraham I <kishon@ti.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.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/io.h>
+#include <linux/usb/omap_usb.h>
+#include <linux/usb/phy_companion.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/pm_runtime.h>
+#include <linux/delay.h>
+#include <linux/usb/omap_control_usb.h>
+
+/**
+ * omap_usb2_set_comparator - links the comparator present in the sytem with
+ *	this phy
+ * @comparator - the companion phy(comparator) for this phy
+ *
+ * The phy companion driver should call this API passing the phy_companion
+ * filled with set_vbus and start_srp to be used by usb phy.
+ *
+ * For use by phy companion driver
+ */
+int omap_usb2_set_comparator(struct phy_companion *comparator)
+{
+	struct omap_usb	*phy;
+	struct usb_phy	*x = usb_get_phy(USB_PHY_TYPE_USB2);
+
+	if (IS_ERR(x))
+		return -ENODEV;
+
+	phy = phy_to_omapusb(x);
+	phy->comparator = comparator;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(omap_usb2_set_comparator);
+
+static int omap_usb_set_vbus(struct usb_otg *otg, bool enabled)
+{
+	struct omap_usb *phy = phy_to_omapusb(otg->phy);
+
+	if (!phy->comparator)
+		return -ENODEV;
+
+	return phy->comparator->set_vbus(phy->comparator, enabled);
+}
+
+static int omap_usb_start_srp(struct usb_otg *otg)
+{
+	struct omap_usb *phy = phy_to_omapusb(otg->phy);
+
+	if (!phy->comparator)
+		return -ENODEV;
+
+	return phy->comparator->start_srp(phy->comparator);
+}
+
+static int omap_usb_set_host(struct usb_otg *otg, struct usb_bus *host)
+{
+	struct usb_phy	*phy = otg->phy;
+
+	otg->host = host;
+	if (!host)
+		phy->state = OTG_STATE_UNDEFINED;
+
+	return 0;
+}
+
+static int omap_usb_set_peripheral(struct usb_otg *otg,
+		struct usb_gadget *gadget)
+{
+	struct usb_phy	*phy = otg->phy;
+
+	otg->gadget = gadget;
+	if (!gadget)
+		phy->state = OTG_STATE_UNDEFINED;
+
+	return 0;
+}
+
+static int omap_usb2_suspend(struct usb_phy *x, int suspend)
+{
+	u32 ret;
+	struct omap_usb *phy = phy_to_omapusb(x);
+
+	if (suspend && !phy->is_suspended) {
+		omap_control_usb_phy_power(phy->control_dev, 0);
+		pm_runtime_put_sync(phy->dev);
+		phy->is_suspended = 1;
+	} else if (!suspend && phy->is_suspended) {
+		ret = pm_runtime_get_sync(phy->dev);
+		if (ret < 0) {
+			dev_err(phy->dev, "get_sync failed with err %d\n",
+									ret);
+			return ret;
+		}
+		omap_control_usb_phy_power(phy->control_dev, 1);
+		phy->is_suspended = 0;
+	}
+
+	return 0;
+}
+
+static int omap_usb2_probe(struct platform_device *pdev)
+{
+	struct omap_usb			*phy;
+	struct usb_otg			*otg;
+
+	phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
+	if (!phy) {
+		dev_err(&pdev->dev, "unable to allocate memory for USB2 PHY\n");
+		return -ENOMEM;
+	}
+
+	otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL);
+	if (!otg) {
+		dev_err(&pdev->dev, "unable to allocate memory for USB OTG\n");
+		return -ENOMEM;
+	}
+
+	phy->dev		= &pdev->dev;
+
+	phy->phy.dev		= phy->dev;
+	phy->phy.label		= "omap-usb2";
+	phy->phy.set_suspend	= omap_usb2_suspend;
+	phy->phy.otg		= otg;
+	phy->phy.type		= USB_PHY_TYPE_USB2;
+
+	phy->control_dev = omap_get_control_dev();
+	if (IS_ERR(phy->control_dev)) {
+		dev_dbg(&pdev->dev, "Failed to get control device\n");
+		return -ENODEV;
+	}
+
+	phy->is_suspended	= 1;
+	omap_control_usb_phy_power(phy->control_dev, 0);
+
+	otg->set_host		= omap_usb_set_host;
+	otg->set_peripheral	= omap_usb_set_peripheral;
+	otg->set_vbus		= omap_usb_set_vbus;
+	otg->start_srp		= omap_usb_start_srp;
+	otg->phy		= &phy->phy;
+
+	phy->wkupclk = devm_clk_get(phy->dev, "usb_phy_cm_clk32k");
+	if (IS_ERR(phy->wkupclk)) {
+		dev_err(&pdev->dev, "unable to get usb_phy_cm_clk32k\n");
+		return PTR_ERR(phy->wkupclk);
+	}
+	clk_prepare(phy->wkupclk);
+
+	phy->optclk = devm_clk_get(phy->dev, "usb_otg_ss_refclk960m");
+	if (IS_ERR(phy->optclk))
+		dev_vdbg(&pdev->dev, "unable to get refclk960m\n");
+	else
+		clk_prepare(phy->optclk);
+
+	usb_add_phy_dev(&phy->phy);
+
+	platform_set_drvdata(pdev, phy);
+
+	pm_runtime_enable(phy->dev);
+
+	return 0;
+}
+
+static int omap_usb2_remove(struct platform_device *pdev)
+{
+	struct omap_usb	*phy = platform_get_drvdata(pdev);
+
+	clk_unprepare(phy->wkupclk);
+	if (!IS_ERR(phy->optclk))
+		clk_unprepare(phy->optclk);
+	usb_remove_phy(&phy->phy);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_RUNTIME
+
+static int omap_usb2_runtime_suspend(struct device *dev)
+{
+	struct platform_device	*pdev = to_platform_device(dev);
+	struct omap_usb	*phy = platform_get_drvdata(pdev);
+
+	clk_disable(phy->wkupclk);
+	if (!IS_ERR(phy->optclk))
+		clk_disable(phy->optclk);
+
+	return 0;
+}
+
+static int omap_usb2_runtime_resume(struct device *dev)
+{
+	u32 ret = 0;
+	struct platform_device	*pdev = to_platform_device(dev);
+	struct omap_usb	*phy = platform_get_drvdata(pdev);
+
+	ret = clk_enable(phy->wkupclk);
+	if (ret < 0) {
+		dev_err(phy->dev, "Failed to enable wkupclk %d\n", ret);
+		goto err0;
+	}
+
+	if (!IS_ERR(phy->optclk)) {
+		ret = clk_enable(phy->optclk);
+		if (ret < 0) {
+			dev_err(phy->dev, "Failed to enable optclk %d\n", ret);
+			goto err1;
+		}
+	}
+
+	return 0;
+
+err1:
+	clk_disable(phy->wkupclk);
+
+err0:
+	return ret;
+}
+
+static const struct dev_pm_ops omap_usb2_pm_ops = {
+	SET_RUNTIME_PM_OPS(omap_usb2_runtime_suspend, omap_usb2_runtime_resume,
+		NULL)
+};
+
+#define DEV_PM_OPS     (&omap_usb2_pm_ops)
+#else
+#define DEV_PM_OPS     NULL
+#endif
+
+#ifdef CONFIG_OF
+static const struct of_device_id omap_usb2_id_table[] = {
+	{ .compatible = "ti,omap-usb2" },
+	{}
+};
+MODULE_DEVICE_TABLE(of, omap_usb2_id_table);
+#endif
+
+static struct platform_driver omap_usb2_driver = {
+	.probe		= omap_usb2_probe,
+	.remove		= omap_usb2_remove,
+	.driver		= {
+		.name	= "omap-usb2",
+		.owner	= THIS_MODULE,
+		.pm	= DEV_PM_OPS,
+		.of_match_table = of_match_ptr(omap_usb2_id_table),
+	},
+};
+
+module_platform_driver(omap_usb2_driver);
+
+MODULE_ALIAS("platform: omap_usb2");
+MODULE_AUTHOR("Texas Instruments Inc.");
+MODULE_DESCRIPTION("OMAP USB2 phy driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/phy/phy-omap-usb3.c b/drivers/usb/phy/phy-omap-usb3.c
new file mode 100644
index 0000000..a6e60b1
--- /dev/null
+++ b/drivers/usb/phy/phy-omap-usb3.c
@@ -0,0 +1,353 @@
+/*
+ * omap-usb3 - USB PHY, talking to dwc3 controller in OMAP.
+ *
+ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.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.
+ *
+ * Author: Kishon Vijay Abraham I <kishon@ti.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.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/usb/omap_usb.h>
+#include <linux/of.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/pm_runtime.h>
+#include <linux/delay.h>
+#include <linux/usb/omap_control_usb.h>
+
+#define	NUM_SYS_CLKS		5
+#define	PLL_STATUS		0x00000004
+#define	PLL_GO			0x00000008
+#define	PLL_CONFIGURATION1	0x0000000C
+#define	PLL_CONFIGURATION2	0x00000010
+#define	PLL_CONFIGURATION3	0x00000014
+#define	PLL_CONFIGURATION4	0x00000020
+
+#define	PLL_REGM_MASK		0x001FFE00
+#define	PLL_REGM_SHIFT		0x9
+#define	PLL_REGM_F_MASK		0x0003FFFF
+#define	PLL_REGM_F_SHIFT	0x0
+#define	PLL_REGN_MASK		0x000001FE
+#define	PLL_REGN_SHIFT		0x1
+#define	PLL_SELFREQDCO_MASK	0x0000000E
+#define	PLL_SELFREQDCO_SHIFT	0x1
+#define	PLL_SD_MASK		0x0003FC00
+#define	PLL_SD_SHIFT		0x9
+#define	SET_PLL_GO		0x1
+#define	PLL_TICOPWDN		0x10000
+#define	PLL_LOCK		0x2
+#define	PLL_IDLE		0x1
+
+/*
+ * This is an Empirical value that works, need to confirm the actual
+ * value required for the USB3PHY_PLL_CONFIGURATION2.PLL_IDLE status
+ * to be correctly reflected in the USB3PHY_PLL_STATUS register.
+ */
+# define PLL_IDLE_TIME  100;
+
+enum sys_clk_rate {
+	CLK_RATE_UNDEFINED = -1,
+	CLK_RATE_12MHZ,
+	CLK_RATE_16MHZ,
+	CLK_RATE_19MHZ,
+	CLK_RATE_26MHZ,
+	CLK_RATE_38MHZ
+};
+
+static struct usb_dpll_params omap_usb3_dpll_params[NUM_SYS_CLKS] = {
+	{1250, 5, 4, 20, 0},		/* 12 MHz */
+	{3125, 20, 4, 20, 0},		/* 16.8 MHz */
+	{1172, 8, 4, 20, 65537},	/* 19.2 MHz */
+	{1250, 12, 4, 20, 0},		/* 26 MHz */
+	{3125, 47, 4, 20, 92843},	/* 38.4 MHz */
+};
+
+static int omap_usb3_suspend(struct usb_phy *x, int suspend)
+{
+	struct omap_usb *phy = phy_to_omapusb(x);
+	int	val;
+	int timeout = PLL_IDLE_TIME;
+
+	if (suspend && !phy->is_suspended) {
+		val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
+		val |= PLL_IDLE;
+		omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
+
+		do {
+			val = omap_usb_readl(phy->pll_ctrl_base, PLL_STATUS);
+			if (val & PLL_TICOPWDN)
+				break;
+			udelay(1);
+		} while (--timeout);
+
+		omap_control_usb3_phy_power(phy->control_dev, 0);
+
+		phy->is_suspended	= 1;
+	} else if (!suspend && phy->is_suspended) {
+		phy->is_suspended	= 0;
+
+		val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
+		val &= ~PLL_IDLE;
+		omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
+
+		do {
+			val = omap_usb_readl(phy->pll_ctrl_base, PLL_STATUS);
+			if (!(val & PLL_TICOPWDN))
+				break;
+			udelay(1);
+		} while (--timeout);
+	}
+
+	return 0;
+}
+
+static inline enum sys_clk_rate __get_sys_clk_index(unsigned long rate)
+{
+	switch (rate) {
+	case 12000000:
+		return CLK_RATE_12MHZ;
+	case 16800000:
+		return CLK_RATE_16MHZ;
+	case 19200000:
+		return CLK_RATE_19MHZ;
+	case 26000000:
+		return CLK_RATE_26MHZ;
+	case 38400000:
+		return CLK_RATE_38MHZ;
+	default:
+		return CLK_RATE_UNDEFINED;
+	}
+}
+
+static void omap_usb_dpll_relock(struct omap_usb *phy)
+{
+	u32		val;
+	unsigned long	timeout;
+
+	omap_usb_writel(phy->pll_ctrl_base, PLL_GO, SET_PLL_GO);
+
+	timeout = jiffies + msecs_to_jiffies(20);
+	do {
+		val = omap_usb_readl(phy->pll_ctrl_base, PLL_STATUS);
+		if (val & PLL_LOCK)
+			break;
+	} while (!WARN_ON(time_after(jiffies, timeout)));
+}
+
+static int omap_usb_dpll_lock(struct omap_usb *phy)
+{
+	u32			val;
+	unsigned long		rate;
+	enum sys_clk_rate	clk_index;
+
+	rate		= clk_get_rate(phy->sys_clk);
+	clk_index	= __get_sys_clk_index(rate);
+
+	if (clk_index == CLK_RATE_UNDEFINED) {
+		pr_err("dpll cannot be locked for sys clk freq:%luHz\n", rate);
+		return -EINVAL;
+	}
+
+	val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1);
+	val &= ~PLL_REGN_MASK;
+	val |= omap_usb3_dpll_params[clk_index].n << PLL_REGN_SHIFT;
+	omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val);
+
+	val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
+	val &= ~PLL_SELFREQDCO_MASK;
+	val |= omap_usb3_dpll_params[clk_index].freq << PLL_SELFREQDCO_SHIFT;
+	omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
+
+	val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1);
+	val &= ~PLL_REGM_MASK;
+	val |= omap_usb3_dpll_params[clk_index].m << PLL_REGM_SHIFT;
+	omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val);
+
+	val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION4);
+	val &= ~PLL_REGM_F_MASK;
+	val |= omap_usb3_dpll_params[clk_index].mf << PLL_REGM_F_SHIFT;
+	omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION4, val);
+
+	val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION3);
+	val &= ~PLL_SD_MASK;
+	val |= omap_usb3_dpll_params[clk_index].sd << PLL_SD_SHIFT;
+	omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION3, val);
+
+	omap_usb_dpll_relock(phy);
+
+	return 0;
+}
+
+static int omap_usb3_init(struct usb_phy *x)
+{
+	struct omap_usb	*phy = phy_to_omapusb(x);
+
+	omap_usb_dpll_lock(phy);
+	omap_control_usb3_phy_power(phy->control_dev, 1);
+
+	return 0;
+}
+
+static int omap_usb3_probe(struct platform_device *pdev)
+{
+	struct omap_usb			*phy;
+	struct resource			*res;
+
+	phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
+	if (!phy) {
+		dev_err(&pdev->dev, "unable to alloc mem for OMAP USB3 PHY\n");
+		return -ENOMEM;
+	}
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pll_ctrl");
+	phy->pll_ctrl_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(phy->pll_ctrl_base))
+		return PTR_ERR(phy->pll_ctrl_base);
+
+	phy->dev		= &pdev->dev;
+
+	phy->phy.dev		= phy->dev;
+	phy->phy.label		= "omap-usb3";
+	phy->phy.init		= omap_usb3_init;
+	phy->phy.set_suspend	= omap_usb3_suspend;
+	phy->phy.type		= USB_PHY_TYPE_USB3;
+
+	phy->is_suspended	= 1;
+	phy->wkupclk = devm_clk_get(phy->dev, "usb_phy_cm_clk32k");
+	if (IS_ERR(phy->wkupclk)) {
+		dev_err(&pdev->dev, "unable to get usb_phy_cm_clk32k\n");
+		return PTR_ERR(phy->wkupclk);
+	}
+	clk_prepare(phy->wkupclk);
+
+	phy->optclk = devm_clk_get(phy->dev, "usb_otg_ss_refclk960m");
+	if (IS_ERR(phy->optclk)) {
+		dev_err(&pdev->dev, "unable to get usb_otg_ss_refclk960m\n");
+		return PTR_ERR(phy->optclk);
+	}
+	clk_prepare(phy->optclk);
+
+	phy->sys_clk = devm_clk_get(phy->dev, "sys_clkin");
+	if (IS_ERR(phy->sys_clk)) {
+		pr_err("%s: unable to get sys_clkin\n", __func__);
+		return -EINVAL;
+	}
+
+	phy->control_dev = omap_get_control_dev();
+	if (IS_ERR(phy->control_dev)) {
+		dev_dbg(&pdev->dev, "Failed to get control device\n");
+		return -ENODEV;
+	}
+
+	omap_control_usb3_phy_power(phy->control_dev, 0);
+	usb_add_phy_dev(&phy->phy);
+
+	platform_set_drvdata(pdev, phy);
+
+	pm_runtime_enable(phy->dev);
+	pm_runtime_get(&pdev->dev);
+
+	return 0;
+}
+
+static int omap_usb3_remove(struct platform_device *pdev)
+{
+	struct omap_usb *phy = platform_get_drvdata(pdev);
+
+	clk_unprepare(phy->wkupclk);
+	clk_unprepare(phy->optclk);
+	usb_remove_phy(&phy->phy);
+	if (!pm_runtime_suspended(&pdev->dev))
+		pm_runtime_put(&pdev->dev);
+	pm_runtime_disable(&pdev->dev);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_RUNTIME
+
+static int omap_usb3_runtime_suspend(struct device *dev)
+{
+	struct platform_device	*pdev = to_platform_device(dev);
+	struct omap_usb	*phy = platform_get_drvdata(pdev);
+
+	clk_disable(phy->wkupclk);
+	clk_disable(phy->optclk);
+
+	return 0;
+}
+
+static int omap_usb3_runtime_resume(struct device *dev)
+{
+	u32 ret = 0;
+	struct platform_device	*pdev = to_platform_device(dev);
+	struct omap_usb	*phy = platform_get_drvdata(pdev);
+
+	ret = clk_enable(phy->optclk);
+	if (ret) {
+		dev_err(phy->dev, "Failed to enable optclk %d\n", ret);
+		goto err1;
+	}
+
+	ret = clk_enable(phy->wkupclk);
+	if (ret) {
+		dev_err(phy->dev, "Failed to enable wkupclk %d\n", ret);
+		goto err2;
+	}
+
+	return 0;
+
+err2:
+	clk_disable(phy->optclk);
+
+err1:
+	return ret;
+}
+
+static const struct dev_pm_ops omap_usb3_pm_ops = {
+	SET_RUNTIME_PM_OPS(omap_usb3_runtime_suspend, omap_usb3_runtime_resume,
+		NULL)
+};
+
+#define DEV_PM_OPS     (&omap_usb3_pm_ops)
+#else
+#define DEV_PM_OPS     NULL
+#endif
+
+#ifdef CONFIG_OF
+static const struct of_device_id omap_usb3_id_table[] = {
+	{ .compatible = "ti,omap-usb3" },
+	{}
+};
+MODULE_DEVICE_TABLE(of, omap_usb3_id_table);
+#endif
+
+static struct platform_driver omap_usb3_driver = {
+	.probe		= omap_usb3_probe,
+	.remove		= omap_usb3_remove,
+	.driver		= {
+		.name	= "omap-usb3",
+		.owner	= THIS_MODULE,
+		.pm	= DEV_PM_OPS,
+		.of_match_table = of_match_ptr(omap_usb3_id_table),
+	},
+};
+
+module_platform_driver(omap_usb3_driver);
+
+MODULE_ALIAS("platform: omap_usb3");
+MODULE_AUTHOR("Texas Instruments Inc.");
+MODULE_DESCRIPTION("OMAP USB3 phy driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/phy/phy-rcar-usb.c b/drivers/usb/phy/phy-rcar-usb.c
new file mode 100644
index 0000000..a35681b
--- /dev/null
+++ b/drivers/usb/phy/phy-rcar-usb.c
@@ -0,0 +1,220 @@
+/*
+ * Renesas R-Car USB phy driver
+ *
+ * Copyright (C) 2012 Renesas Solutions Corp.
+ * Kuninori Morimoto <kuninori.morimoto.gx@renesas.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/delay.h>
+#include <linux/io.h>
+#include <linux/usb/otg.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/module.h>
+
+/* USBH common register */
+#define USBPCTRL0	0x0800
+#define USBPCTRL1	0x0804
+#define USBST		0x0808
+#define USBEH0		0x080C
+#define USBOH0		0x081C
+#define USBCTL0		0x0858
+#define EIIBC1		0x0094
+#define EIIBC2		0x009C
+
+/* USBPCTRL1 */
+#define PHY_RST		(1 << 2)
+#define PLL_ENB		(1 << 1)
+#define PHY_ENB		(1 << 0)
+
+/* USBST */
+#define ST_ACT		(1 << 31)
+#define ST_PLL		(1 << 30)
+
+struct rcar_usb_phy_priv {
+	struct usb_phy phy;
+	spinlock_t lock;
+
+	void __iomem *reg0;
+	void __iomem *reg1;
+	int counter;
+};
+
+#define usb_phy_to_priv(p) container_of(p, struct rcar_usb_phy_priv, phy)
+
+
+/*
+ * USB initial/install operation.
+ *
+ * This function setup USB phy.
+ * The used value and setting order came from
+ * [USB :: Initial setting] on datasheet.
+ */
+static int rcar_usb_phy_init(struct usb_phy *phy)
+{
+	struct rcar_usb_phy_priv *priv = usb_phy_to_priv(phy);
+	struct device *dev = phy->dev;
+	void __iomem *reg0 = priv->reg0;
+	void __iomem *reg1 = priv->reg1;
+	int i;
+	u32 val;
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->lock, flags);
+	if (priv->counter++ == 0) {
+
+		/*
+		 * USB phy start-up
+		 */
+
+		/* (1) USB-PHY standby release */
+		iowrite32(PHY_ENB, (reg0 + USBPCTRL1));
+
+		/* (2) start USB-PHY internal PLL */
+		iowrite32(PHY_ENB | PLL_ENB, (reg0 + USBPCTRL1));
+
+		/* (3) USB module status check */
+		for (i = 0; i < 1024; i++) {
+			udelay(10);
+			val = ioread32(reg0 + USBST);
+			if (val == (ST_ACT | ST_PLL))
+				break;
+		}
+
+		if (val != (ST_ACT | ST_PLL)) {
+			dev_err(dev, "USB phy not ready\n");
+			goto phy_init_end;
+		}
+
+		/* (4) USB-PHY reset clear */
+		iowrite32(PHY_ENB | PLL_ENB | PHY_RST, (reg0 + USBPCTRL1));
+
+		/* set platform specific port settings */
+		iowrite32(0x00000000, (reg0 + USBPCTRL0));
+
+		/*
+		 * EHCI IP internal buffer setting
+		 * EHCI IP internal buffer enable
+		 *
+		 * These are recommended value of a datasheet
+		 * see [USB :: EHCI internal buffer setting]
+		 */
+		iowrite32(0x00ff0040, (reg0 + EIIBC1));
+		iowrite32(0x00ff0040, (reg1 + EIIBC1));
+
+		iowrite32(0x00000001, (reg0 + EIIBC2));
+		iowrite32(0x00000001, (reg1 + EIIBC2));
+
+		/*
+		 * Bus alignment settings
+		 */
+
+		/* (1) EHCI bus alignment (little endian) */
+		iowrite32(0x00000000, (reg0 + USBEH0));
+
+		/* (1) OHCI bus alignment (little endian) */
+		iowrite32(0x00000000, (reg0 + USBOH0));
+	}
+
+phy_init_end:
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	return 0;
+}
+
+static void rcar_usb_phy_shutdown(struct usb_phy *phy)
+{
+	struct rcar_usb_phy_priv *priv = usb_phy_to_priv(phy);
+	void __iomem *reg0 = priv->reg0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	if (priv->counter-- == 1) { /* last user */
+		iowrite32(0x00000000, (reg0 + USBPCTRL0));
+		iowrite32(0x00000000, (reg0 + USBPCTRL1));
+	}
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+static int rcar_usb_phy_probe(struct platform_device *pdev)
+{
+	struct rcar_usb_phy_priv *priv;
+	struct resource *res0, *res1;
+	struct device *dev = &pdev->dev;
+	void __iomem *reg0, *reg1;
+	int ret;
+
+	res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	res1 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!res0 || !res1) {
+		dev_err(dev, "Not enough platform resources\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * CAUTION
+	 *
+	 * Because this phy address is also mapped under OHCI/EHCI address area,
+	 * this driver can't use devm_request_and_ioremap(dev, res) here
+	 */
+	reg0 = devm_ioremap_nocache(dev, res0->start, resource_size(res0));
+	reg1 = devm_ioremap_nocache(dev, res1->start, resource_size(res1));
+	if (!reg0 || !reg1) {
+		dev_err(dev, "ioremap error\n");
+		return -ENOMEM;
+	}
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		dev_err(dev, "priv data allocation error\n");
+		return -ENOMEM;
+	}
+
+	priv->reg0		= reg0;
+	priv->reg1		= reg1;
+	priv->counter		= 0;
+	priv->phy.dev		= dev;
+	priv->phy.label		= dev_name(dev);
+	priv->phy.init		= rcar_usb_phy_init;
+	priv->phy.shutdown	= rcar_usb_phy_shutdown;
+	spin_lock_init(&priv->lock);
+
+	ret = usb_add_phy(&priv->phy, USB_PHY_TYPE_USB2);
+	if (ret < 0) {
+		dev_err(dev, "usb phy addition error\n");
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, priv);
+
+	return ret;
+}
+
+static int rcar_usb_phy_remove(struct platform_device *pdev)
+{
+	struct rcar_usb_phy_priv *priv = platform_get_drvdata(pdev);
+
+	usb_remove_phy(&priv->phy);
+
+	return 0;
+}
+
+static struct platform_driver rcar_usb_phy_driver = {
+	.driver		= {
+		.name	= "rcar_usb_phy",
+	},
+	.probe		= rcar_usb_phy_probe,
+	.remove		= rcar_usb_phy_remove,
+};
+
+module_platform_driver(rcar_usb_phy_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Renesas R-Car USB phy");
+MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
diff --git a/drivers/usb/phy/phy-samsung-usb.c b/drivers/usb/phy/phy-samsung-usb.c
new file mode 100644
index 0000000..7b118ee5
--- /dev/null
+++ b/drivers/usb/phy/phy-samsung-usb.c
@@ -0,0 +1,236 @@
+/* linux/drivers/usb/phy/phy-samsung-usb.c
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *              http://www.samsung.com
+ *
+ * Author: Praveen Paneri <p.paneri@samsung.com>
+ *
+ * Samsung USB-PHY helper driver with common function calls;
+ * interacts with Samsung USB 2.0 PHY controller driver and later
+ * with Samsung USB 3.0 PHY 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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/platform_device.h>
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/usb/samsung_usb_phy.h>
+
+#include "phy-samsung-usb.h"
+
+int samsung_usbphy_parse_dt(struct samsung_usbphy *sphy)
+{
+	struct device_node *usbphy_sys;
+
+	/* Getting node for system controller interface for usb-phy */
+	usbphy_sys = of_get_child_by_name(sphy->dev->of_node, "usbphy-sys");
+	if (!usbphy_sys) {
+		dev_err(sphy->dev, "No sys-controller interface for usb-phy\n");
+		return -ENODEV;
+	}
+
+	sphy->pmuregs = of_iomap(usbphy_sys, 0);
+
+	if (sphy->pmuregs == NULL) {
+		dev_err(sphy->dev, "Can't get usb-phy pmu control register\n");
+		goto err0;
+	}
+
+	sphy->sysreg = of_iomap(usbphy_sys, 1);
+
+	/*
+	 * Not returning error code here, since this situation is not fatal.
+	 * Few SoCs may not have this switch available
+	 */
+	if (sphy->sysreg == NULL)
+		dev_warn(sphy->dev, "Can't get usb-phy sysreg cfg register\n");
+
+	of_node_put(usbphy_sys);
+
+	return 0;
+
+err0:
+	of_node_put(usbphy_sys);
+	return -ENXIO;
+}
+EXPORT_SYMBOL_GPL(samsung_usbphy_parse_dt);
+
+/*
+ * Set isolation here for phy.
+ * Here 'on = true' would mean USB PHY block is isolated, hence
+ * de-activated and vice-versa.
+ */
+void samsung_usbphy_set_isolation(struct samsung_usbphy *sphy, bool on)
+{
+	void __iomem *reg = NULL;
+	u32 reg_val;
+	u32 en_mask = 0;
+
+	if (!sphy->pmuregs) {
+		dev_warn(sphy->dev, "Can't set pmu isolation\n");
+		return;
+	}
+
+	switch (sphy->drv_data->cpu_type) {
+	case TYPE_S3C64XX:
+		/*
+		 * Do nothing: We will add here once S3C64xx goes for DT support
+		 */
+		break;
+	case TYPE_EXYNOS4210:
+		/*
+		 * Fall through since exynos4210 and exynos5250 have similar
+		 * register architecture: two separate registers for host and
+		 * device phy control with enable bit at position 0.
+		 */
+	case TYPE_EXYNOS5250:
+		if (sphy->phy_type == USB_PHY_TYPE_DEVICE) {
+			reg = sphy->pmuregs +
+				sphy->drv_data->devphy_reg_offset;
+			en_mask = sphy->drv_data->devphy_en_mask;
+		} else if (sphy->phy_type == USB_PHY_TYPE_HOST) {
+			reg = sphy->pmuregs +
+				sphy->drv_data->hostphy_reg_offset;
+			en_mask = sphy->drv_data->hostphy_en_mask;
+		}
+		break;
+	default:
+		dev_err(sphy->dev, "Invalid SoC type\n");
+		return;
+	}
+
+	reg_val = readl(reg);
+
+	if (on)
+		reg_val &= ~en_mask;
+	else
+		reg_val |= en_mask;
+
+	writel(reg_val, reg);
+}
+EXPORT_SYMBOL_GPL(samsung_usbphy_set_isolation);
+
+/*
+ * Configure the mode of working of usb-phy here: HOST/DEVICE.
+ */
+void samsung_usbphy_cfg_sel(struct samsung_usbphy *sphy)
+{
+	u32 reg;
+
+	if (!sphy->sysreg) {
+		dev_warn(sphy->dev, "Can't configure specified phy mode\n");
+		return;
+	}
+
+	reg = readl(sphy->sysreg);
+
+	if (sphy->phy_type == USB_PHY_TYPE_DEVICE)
+		reg &= ~EXYNOS_USB20PHY_CFG_HOST_LINK;
+	else if (sphy->phy_type == USB_PHY_TYPE_HOST)
+		reg |= EXYNOS_USB20PHY_CFG_HOST_LINK;
+
+	writel(reg, sphy->sysreg);
+}
+EXPORT_SYMBOL_GPL(samsung_usbphy_cfg_sel);
+
+/*
+ * PHYs are different for USB Device and USB Host.
+ * This make sure that correct PHY type is selected before
+ * any operation on PHY.
+ */
+int samsung_usbphy_set_type(struct usb_phy *phy,
+				enum samsung_usb_phy_type phy_type)
+{
+	struct samsung_usbphy *sphy = phy_to_sphy(phy);
+
+	sphy->phy_type = phy_type;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(samsung_usbphy_set_type);
+
+/*
+ * Returns reference clock frequency selection value
+ */
+int samsung_usbphy_get_refclk_freq(struct samsung_usbphy *sphy)
+{
+	struct clk *ref_clk;
+	int refclk_freq = 0;
+
+	/*
+	 * In exynos5250 USB host and device PHY use
+	 * external crystal clock XXTI
+	 */
+	if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250)
+		ref_clk = devm_clk_get(sphy->dev, "ext_xtal");
+	else
+		ref_clk = devm_clk_get(sphy->dev, "xusbxti");
+	if (IS_ERR(ref_clk)) {
+		dev_err(sphy->dev, "Failed to get reference clock\n");
+		return PTR_ERR(ref_clk);
+	}
+
+	if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250) {
+		/* set clock frequency for PLL */
+		switch (clk_get_rate(ref_clk)) {
+		case 9600 * KHZ:
+			refclk_freq = FSEL_CLKSEL_9600K;
+			break;
+		case 10 * MHZ:
+			refclk_freq = FSEL_CLKSEL_10M;
+			break;
+		case 12 * MHZ:
+			refclk_freq = FSEL_CLKSEL_12M;
+			break;
+		case 19200 * KHZ:
+			refclk_freq = FSEL_CLKSEL_19200K;
+			break;
+		case 20 * MHZ:
+			refclk_freq = FSEL_CLKSEL_20M;
+			break;
+		case 50 * MHZ:
+			refclk_freq = FSEL_CLKSEL_50M;
+			break;
+		case 24 * MHZ:
+		default:
+			/* default reference clock */
+			refclk_freq = FSEL_CLKSEL_24M;
+			break;
+		}
+	} else {
+		switch (clk_get_rate(ref_clk)) {
+		case 12 * MHZ:
+			refclk_freq = PHYCLK_CLKSEL_12M;
+			break;
+		case 24 * MHZ:
+			refclk_freq = PHYCLK_CLKSEL_24M;
+			break;
+		case 48 * MHZ:
+			refclk_freq = PHYCLK_CLKSEL_48M;
+			break;
+		default:
+			if (sphy->drv_data->cpu_type == TYPE_S3C64XX)
+				refclk_freq = PHYCLK_CLKSEL_48M;
+			else
+				refclk_freq = PHYCLK_CLKSEL_24M;
+			break;
+		}
+	}
+	clk_put(ref_clk);
+
+	return refclk_freq;
+}
+EXPORT_SYMBOL_GPL(samsung_usbphy_get_refclk_freq);
diff --git a/drivers/usb/phy/phy-samsung-usb.h b/drivers/usb/phy/phy-samsung-usb.h
new file mode 100644
index 0000000..70a9cae
--- /dev/null
+++ b/drivers/usb/phy/phy-samsung-usb.h
@@ -0,0 +1,327 @@
+/* linux/drivers/usb/phy/phy-samsung-usb.h
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *              http://www.samsung.com
+ *
+ * Samsung USB-PHY transceiver; talks to S3C HS OTG controller, EHCI-S5P and
+ * OHCI-EXYNOS controllers.
+ *
+ * This program is free software; you can 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.
+ */
+
+#include <linux/usb/phy.h>
+
+/* Register definitions */
+
+#define SAMSUNG_PHYPWR				(0x00)
+
+#define PHYPWR_NORMAL_MASK			(0x19 << 0)
+#define PHYPWR_OTG_DISABLE			(0x1 << 4)
+#define PHYPWR_ANALOG_POWERDOWN			(0x1 << 3)
+#define PHYPWR_FORCE_SUSPEND			(0x1 << 1)
+/* For Exynos4 */
+#define PHYPWR_NORMAL_MASK_PHY0			(0x39 << 0)
+#define PHYPWR_SLEEP_PHY0			(0x1 << 5)
+
+#define SAMSUNG_PHYCLK				(0x04)
+
+#define PHYCLK_MODE_USB11			(0x1 << 6)
+#define PHYCLK_EXT_OSC				(0x1 << 5)
+#define PHYCLK_COMMON_ON_N			(0x1 << 4)
+#define PHYCLK_ID_PULL				(0x1 << 2)
+#define PHYCLK_CLKSEL_MASK			(0x3 << 0)
+#define PHYCLK_CLKSEL_48M			(0x0 << 0)
+#define PHYCLK_CLKSEL_12M			(0x2 << 0)
+#define PHYCLK_CLKSEL_24M			(0x3 << 0)
+
+#define SAMSUNG_RSTCON				(0x08)
+
+#define RSTCON_PHYLINK_SWRST			(0x1 << 2)
+#define RSTCON_HLINK_SWRST			(0x1 << 1)
+#define RSTCON_SWRST				(0x1 << 0)
+
+/* EXYNOS5 */
+#define EXYNOS5_PHY_HOST_CTRL0			(0x00)
+
+#define HOST_CTRL0_PHYSWRSTALL			(0x1 << 31)
+
+#define HOST_CTRL0_REFCLKSEL_MASK		(0x3 << 19)
+#define HOST_CTRL0_REFCLKSEL_XTAL		(0x0 << 19)
+#define HOST_CTRL0_REFCLKSEL_EXTL		(0x1 << 19)
+#define HOST_CTRL0_REFCLKSEL_CLKCORE		(0x2 << 19)
+
+#define HOST_CTRL0_FSEL_MASK			(0x7 << 16)
+#define HOST_CTRL0_FSEL(_x)			((_x) << 16)
+
+#define FSEL_CLKSEL_50M				(0x7)
+#define FSEL_CLKSEL_24M				(0x5)
+#define FSEL_CLKSEL_20M				(0x4)
+#define FSEL_CLKSEL_19200K			(0x3)
+#define FSEL_CLKSEL_12M				(0x2)
+#define FSEL_CLKSEL_10M				(0x1)
+#define FSEL_CLKSEL_9600K			(0x0)
+
+#define HOST_CTRL0_TESTBURNIN			(0x1 << 11)
+#define HOST_CTRL0_RETENABLE			(0x1 << 10)
+#define HOST_CTRL0_COMMONON_N			(0x1 << 9)
+#define HOST_CTRL0_SIDDQ			(0x1 << 6)
+#define HOST_CTRL0_FORCESLEEP			(0x1 << 5)
+#define HOST_CTRL0_FORCESUSPEND			(0x1 << 4)
+#define HOST_CTRL0_WORDINTERFACE		(0x1 << 3)
+#define HOST_CTRL0_UTMISWRST			(0x1 << 2)
+#define HOST_CTRL0_LINKSWRST			(0x1 << 1)
+#define HOST_CTRL0_PHYSWRST			(0x1 << 0)
+
+#define EXYNOS5_PHY_HOST_TUNE0			(0x04)
+
+#define EXYNOS5_PHY_HSIC_CTRL1			(0x10)
+
+#define EXYNOS5_PHY_HSIC_TUNE1			(0x14)
+
+#define EXYNOS5_PHY_HSIC_CTRL2			(0x20)
+
+#define EXYNOS5_PHY_HSIC_TUNE2			(0x24)
+
+#define HSIC_CTRL_REFCLKSEL_MASK		(0x3 << 23)
+#define HSIC_CTRL_REFCLKSEL			(0x2 << 23)
+
+#define HSIC_CTRL_REFCLKDIV_MASK		(0x7f << 16)
+#define HSIC_CTRL_REFCLKDIV(_x)			((_x) << 16)
+#define HSIC_CTRL_REFCLKDIV_12			(0x24 << 16)
+#define HSIC_CTRL_REFCLKDIV_15			(0x1c << 16)
+#define HSIC_CTRL_REFCLKDIV_16			(0x1a << 16)
+#define HSIC_CTRL_REFCLKDIV_19_2		(0x15 << 16)
+#define HSIC_CTRL_REFCLKDIV_20			(0x14 << 16)
+
+#define HSIC_CTRL_SIDDQ				(0x1 << 6)
+#define HSIC_CTRL_FORCESLEEP			(0x1 << 5)
+#define HSIC_CTRL_FORCESUSPEND			(0x1 << 4)
+#define HSIC_CTRL_WORDINTERFACE			(0x1 << 3)
+#define HSIC_CTRL_UTMISWRST			(0x1 << 2)
+#define HSIC_CTRL_PHYSWRST			(0x1 << 0)
+
+#define EXYNOS5_PHY_HOST_EHCICTRL		(0x30)
+
+#define HOST_EHCICTRL_ENAINCRXALIGN		(0x1 << 29)
+#define HOST_EHCICTRL_ENAINCR4			(0x1 << 28)
+#define HOST_EHCICTRL_ENAINCR8			(0x1 << 27)
+#define HOST_EHCICTRL_ENAINCR16			(0x1 << 26)
+
+#define EXYNOS5_PHY_HOST_OHCICTRL		(0x34)
+
+#define HOST_OHCICTRL_SUSPLGCY			(0x1 << 3)
+#define HOST_OHCICTRL_APPSTARTCLK		(0x1 << 2)
+#define HOST_OHCICTRL_CNTSEL			(0x1 << 1)
+#define HOST_OHCICTRL_CLKCKTRST			(0x1 << 0)
+
+#define EXYNOS5_PHY_OTG_SYS			(0x38)
+
+#define OTG_SYS_PHYLINK_SWRESET			(0x1 << 14)
+#define OTG_SYS_LINKSWRST_UOTG			(0x1 << 13)
+#define OTG_SYS_PHY0_SWRST			(0x1 << 12)
+
+#define OTG_SYS_REFCLKSEL_MASK			(0x3 << 9)
+#define OTG_SYS_REFCLKSEL_XTAL			(0x0 << 9)
+#define OTG_SYS_REFCLKSEL_EXTL			(0x1 << 9)
+#define OTG_SYS_REFCLKSEL_CLKCORE		(0x2 << 9)
+
+#define OTG_SYS_IDPULLUP_UOTG			(0x1 << 8)
+#define OTG_SYS_COMMON_ON			(0x1 << 7)
+
+#define OTG_SYS_FSEL_MASK			(0x7 << 4)
+#define OTG_SYS_FSEL(_x)			((_x) << 4)
+
+#define OTG_SYS_FORCESLEEP			(0x1 << 3)
+#define OTG_SYS_OTGDISABLE			(0x1 << 2)
+#define OTG_SYS_SIDDQ_UOTG			(0x1 << 1)
+#define OTG_SYS_FORCESUSPEND			(0x1 << 0)
+
+#define EXYNOS5_PHY_OTG_TUNE			(0x40)
+
+/* EXYNOS5: USB 3.0 DRD */
+#define EXYNOS5_DRD_LINKSYSTEM			(0x04)
+
+#define LINKSYSTEM_FLADJ_MASK			(0x3f << 1)
+#define LINKSYSTEM_FLADJ(_x)			((_x) << 1)
+#define LINKSYSTEM_XHCI_VERSION_CONTROL		(0x1 << 27)
+
+#define EXYNOS5_DRD_PHYUTMI			(0x08)
+
+#define PHYUTMI_OTGDISABLE			(0x1 << 6)
+#define PHYUTMI_FORCESUSPEND			(0x1 << 1)
+#define PHYUTMI_FORCESLEEP			(0x1 << 0)
+
+#define EXYNOS5_DRD_PHYPIPE			(0x0c)
+
+#define EXYNOS5_DRD_PHYCLKRST			(0x10)
+
+#define PHYCLKRST_SSC_REFCLKSEL_MASK		(0xff << 23)
+#define PHYCLKRST_SSC_REFCLKSEL(_x)		((_x) << 23)
+
+#define PHYCLKRST_SSC_RANGE_MASK		(0x03 << 21)
+#define PHYCLKRST_SSC_RANGE(_x)			((_x) << 21)
+
+#define PHYCLKRST_SSC_EN			(0x1 << 20)
+#define PHYCLKRST_REF_SSP_EN			(0x1 << 19)
+#define PHYCLKRST_REF_CLKDIV2			(0x1 << 18)
+
+#define PHYCLKRST_MPLL_MULTIPLIER_MASK		(0x7f << 11)
+#define PHYCLKRST_MPLL_MULTIPLIER_100MHZ_REF	(0x19 << 11)
+#define PHYCLKRST_MPLL_MULTIPLIER_50M_REF	(0x02 << 11)
+#define PHYCLKRST_MPLL_MULTIPLIER_24MHZ_REF	(0x68 << 11)
+#define PHYCLKRST_MPLL_MULTIPLIER_20MHZ_REF	(0x7d << 11)
+#define PHYCLKRST_MPLL_MULTIPLIER_19200KHZ_REF	(0x02 << 11)
+
+#define PHYCLKRST_FSEL_MASK			(0x3f << 5)
+#define PHYCLKRST_FSEL(_x)			((_x) << 5)
+#define PHYCLKRST_FSEL_PAD_100MHZ		(0x27 << 5)
+#define PHYCLKRST_FSEL_PAD_24MHZ		(0x2a << 5)
+#define PHYCLKRST_FSEL_PAD_20MHZ		(0x31 << 5)
+#define PHYCLKRST_FSEL_PAD_19_2MHZ		(0x38 << 5)
+
+#define PHYCLKRST_RETENABLEN			(0x1 << 4)
+
+#define PHYCLKRST_REFCLKSEL_MASK		(0x03 << 2)
+#define PHYCLKRST_REFCLKSEL_PAD_REFCLK		(0x2 << 2)
+#define PHYCLKRST_REFCLKSEL_EXT_REFCLK		(0x3 << 2)
+
+#define PHYCLKRST_PORTRESET			(0x1 << 1)
+#define PHYCLKRST_COMMONONN			(0x1 << 0)
+
+#define EXYNOS5_DRD_PHYREG0			(0x14)
+#define EXYNOS5_DRD_PHYREG1			(0x18)
+
+#define EXYNOS5_DRD_PHYPARAM0			(0x1c)
+
+#define PHYPARAM0_REF_USE_PAD			(0x1 << 31)
+#define PHYPARAM0_REF_LOSLEVEL_MASK		(0x1f << 26)
+#define PHYPARAM0_REF_LOSLEVEL			(0x9 << 26)
+
+#define EXYNOS5_DRD_PHYPARAM1			(0x20)
+
+#define PHYPARAM1_PCS_TXDEEMPH_MASK		(0x1f << 0)
+#define PHYPARAM1_PCS_TXDEEMPH			(0x1c)
+
+#define EXYNOS5_DRD_PHYTERM			(0x24)
+
+#define EXYNOS5_DRD_PHYTEST			(0x28)
+
+#define PHYTEST_POWERDOWN_SSP			(0x1 << 3)
+#define PHYTEST_POWERDOWN_HSP			(0x1 << 2)
+
+#define EXYNOS5_DRD_PHYADP			(0x2c)
+
+#define EXYNOS5_DRD_PHYBATCHG			(0x30)
+
+#define PHYBATCHG_UTMI_CLKSEL			(0x1 << 2)
+
+#define EXYNOS5_DRD_PHYRESUME			(0x34)
+#define EXYNOS5_DRD_LINKPORT			(0x44)
+
+#ifndef MHZ
+#define MHZ (1000*1000)
+#endif
+
+#ifndef KHZ
+#define KHZ (1000)
+#endif
+
+#define EXYNOS_USBHOST_PHY_CTRL_OFFSET		(0x4)
+#define S3C64XX_USBPHY_ENABLE			(0x1 << 16)
+#define EXYNOS_USBPHY_ENABLE			(0x1 << 0)
+#define EXYNOS_USB20PHY_CFG_HOST_LINK		(0x1 << 0)
+
+enum samsung_cpu_type {
+	TYPE_S3C64XX,
+	TYPE_EXYNOS4210,
+	TYPE_EXYNOS5250,
+};
+
+/*
+ * struct samsung_usbphy_drvdata - driver data for various SoC variants
+ * @cpu_type: machine identifier
+ * @devphy_en_mask: device phy enable mask for PHY CONTROL register
+ * @hostphy_en_mask: host phy enable mask for PHY CONTROL register
+ * @devphy_reg_offset: offset to DEVICE PHY CONTROL register from
+ *		       mapped address of system controller.
+ * @hostphy_reg_offset: offset to HOST PHY CONTROL register from
+ *		       mapped address of system controller.
+ *
+ *	Here we have a separate mask for device type phy.
+ *	Having different masks for host and device type phy helps
+ *	in setting independent masks in case of SoCs like S5PV210,
+ *	in which PHY0 and PHY1 enable bits belong to same register
+ *	placed at position 0 and 1 respectively.
+ *	Although for newer SoCs like exynos these bits belong to
+ *	different registers altogether placed at position 0.
+ */
+struct samsung_usbphy_drvdata {
+	int cpu_type;
+	int devphy_en_mask;
+	int hostphy_en_mask;
+	u32 devphy_reg_offset;
+	u32 hostphy_reg_offset;
+};
+
+/*
+ * struct samsung_usbphy - transceiver driver state
+ * @phy: transceiver structure
+ * @plat: platform data
+ * @dev: The parent device supplied to the probe function
+ * @clk: usb phy clock
+ * @regs: usb phy controller registers memory base
+ * @pmuregs: USB device PHY_CONTROL register memory base
+ * @sysreg: USB2.0 PHY_CFG register memory base
+ * @ref_clk_freq: reference clock frequency selection
+ * @drv_data: driver data available for different SoCs
+ * @phy_type: Samsung SoCs specific phy types:	#HOST
+ *						#DEVICE
+ * @phy_usage: usage count for phy
+ * @lock: lock for phy operations
+ */
+struct samsung_usbphy {
+	struct usb_phy	phy;
+	struct samsung_usbphy_data *plat;
+	struct device	*dev;
+	struct clk	*clk;
+	void __iomem	*regs;
+	void __iomem	*pmuregs;
+	void __iomem	*sysreg;
+	int		ref_clk_freq;
+	const struct samsung_usbphy_drvdata *drv_data;
+	enum samsung_usb_phy_type phy_type;
+	atomic_t	phy_usage;
+	spinlock_t	lock;
+};
+
+#define phy_to_sphy(x)		container_of((x), struct samsung_usbphy, phy)
+
+static const struct of_device_id samsung_usbphy_dt_match[];
+
+static inline const struct samsung_usbphy_drvdata
+*samsung_usbphy_get_driver_data(struct platform_device *pdev)
+{
+	if (pdev->dev.of_node) {
+		const struct of_device_id *match;
+		match = of_match_node(samsung_usbphy_dt_match,
+							pdev->dev.of_node);
+		return match->data;
+	}
+
+	return (struct samsung_usbphy_drvdata *)
+				platform_get_device_id(pdev)->driver_data;
+}
+
+extern int samsung_usbphy_parse_dt(struct samsung_usbphy *sphy);
+extern void samsung_usbphy_set_isolation(struct samsung_usbphy *sphy, bool on);
+extern void samsung_usbphy_cfg_sel(struct samsung_usbphy *sphy);
+extern int samsung_usbphy_set_type(struct usb_phy *phy,
+					enum samsung_usb_phy_type phy_type);
+extern int samsung_usbphy_get_refclk_freq(struct samsung_usbphy *sphy);
diff --git a/drivers/usb/phy/phy-samsung-usb2.c b/drivers/usb/phy/phy-samsung-usb2.c
new file mode 100644
index 0000000..45ffe03
--- /dev/null
+++ b/drivers/usb/phy/phy-samsung-usb2.c
@@ -0,0 +1,509 @@
+/* linux/drivers/usb/phy/phy-samsung-usb2.c
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *              http://www.samsung.com
+ *
+ * Author: Praveen Paneri <p.paneri@samsung.com>
+ *
+ * Samsung USB2.0 PHY transceiver; talks to S3C HS OTG controller, EHCI-S5P and
+ * OHCI-EXYNOS controllers.
+ *
+ * This program is free software; you can 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.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/usb/otg.h>
+#include <linux/usb/samsung_usb_phy.h>
+#include <linux/platform_data/samsung-usbphy.h>
+
+#include "phy-samsung-usb.h"
+
+static int samsung_usbphy_set_host(struct usb_otg *otg, struct usb_bus *host)
+{
+	if (!otg)
+		return -ENODEV;
+
+	if (!otg->host)
+		otg->host = host;
+
+	return 0;
+}
+
+static bool exynos5_phyhost_is_on(void __iomem *regs)
+{
+	u32 reg;
+
+	reg = readl(regs + EXYNOS5_PHY_HOST_CTRL0);
+
+	return !(reg & HOST_CTRL0_SIDDQ);
+}
+
+static void samsung_exynos5_usb2phy_enable(struct samsung_usbphy *sphy)
+{
+	void __iomem *regs = sphy->regs;
+	u32 phyclk = sphy->ref_clk_freq;
+	u32 phyhost;
+	u32 phyotg;
+	u32 phyhsic;
+	u32 ehcictrl;
+	u32 ohcictrl;
+
+	/*
+	 * phy_usage helps in keeping usage count for phy
+	 * so that the first consumer enabling the phy is also
+	 * the last consumer to disable it.
+	 */
+
+	atomic_inc(&sphy->phy_usage);
+
+	if (exynos5_phyhost_is_on(regs)) {
+		dev_info(sphy->dev, "Already power on PHY\n");
+		return;
+	}
+
+	/* Host configuration */
+	phyhost = readl(regs + EXYNOS5_PHY_HOST_CTRL0);
+
+	/* phy reference clock configuration */
+	phyhost &= ~HOST_CTRL0_FSEL_MASK;
+	phyhost |= HOST_CTRL0_FSEL(phyclk);
+
+	/* host phy reset */
+	phyhost &= ~(HOST_CTRL0_PHYSWRST |
+			HOST_CTRL0_PHYSWRSTALL |
+			HOST_CTRL0_SIDDQ |
+			/* Enable normal mode of operation */
+			HOST_CTRL0_FORCESUSPEND |
+			HOST_CTRL0_FORCESLEEP);
+
+	/* Link reset */
+	phyhost |= (HOST_CTRL0_LINKSWRST |
+			HOST_CTRL0_UTMISWRST |
+			/* COMMON Block configuration during suspend */
+			HOST_CTRL0_COMMONON_N);
+	writel(phyhost, regs + EXYNOS5_PHY_HOST_CTRL0);
+	udelay(10);
+	phyhost &= ~(HOST_CTRL0_LINKSWRST |
+			HOST_CTRL0_UTMISWRST);
+	writel(phyhost, regs + EXYNOS5_PHY_HOST_CTRL0);
+
+	/* OTG configuration */
+	phyotg = readl(regs + EXYNOS5_PHY_OTG_SYS);
+
+	/* phy reference clock configuration */
+	phyotg &= ~OTG_SYS_FSEL_MASK;
+	phyotg |= OTG_SYS_FSEL(phyclk);
+
+	/* Enable normal mode of operation */
+	phyotg &= ~(OTG_SYS_FORCESUSPEND |
+			OTG_SYS_SIDDQ_UOTG |
+			OTG_SYS_FORCESLEEP |
+			OTG_SYS_REFCLKSEL_MASK |
+			/* COMMON Block configuration during suspend */
+			OTG_SYS_COMMON_ON);
+
+	/* OTG phy & link reset */
+	phyotg |= (OTG_SYS_PHY0_SWRST |
+			OTG_SYS_LINKSWRST_UOTG |
+			OTG_SYS_PHYLINK_SWRESET |
+			OTG_SYS_OTGDISABLE |
+			/* Set phy refclk */
+			OTG_SYS_REFCLKSEL_CLKCORE);
+
+	writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS);
+	udelay(10);
+	phyotg &= ~(OTG_SYS_PHY0_SWRST |
+			OTG_SYS_LINKSWRST_UOTG |
+			OTG_SYS_PHYLINK_SWRESET);
+	writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS);
+
+	/* HSIC phy configuration */
+	phyhsic = (HSIC_CTRL_REFCLKDIV_12 |
+			HSIC_CTRL_REFCLKSEL |
+			HSIC_CTRL_PHYSWRST);
+	writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL1);
+	writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL2);
+	udelay(10);
+	phyhsic &= ~HSIC_CTRL_PHYSWRST;
+	writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL1);
+	writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL2);
+
+	udelay(80);
+
+	/* enable EHCI DMA burst */
+	ehcictrl = readl(regs + EXYNOS5_PHY_HOST_EHCICTRL);
+	ehcictrl |= (HOST_EHCICTRL_ENAINCRXALIGN |
+				HOST_EHCICTRL_ENAINCR4 |
+				HOST_EHCICTRL_ENAINCR8 |
+				HOST_EHCICTRL_ENAINCR16);
+	writel(ehcictrl, regs + EXYNOS5_PHY_HOST_EHCICTRL);
+
+	/* set ohci_suspend_on_n */
+	ohcictrl = readl(regs + EXYNOS5_PHY_HOST_OHCICTRL);
+	ohcictrl |= HOST_OHCICTRL_SUSPLGCY;
+	writel(ohcictrl, regs + EXYNOS5_PHY_HOST_OHCICTRL);
+}
+
+static void samsung_usb2phy_enable(struct samsung_usbphy *sphy)
+{
+	void __iomem *regs = sphy->regs;
+	u32 phypwr;
+	u32 phyclk;
+	u32 rstcon;
+
+	/* set clock frequency for PLL */
+	phyclk = sphy->ref_clk_freq;
+	phypwr = readl(regs + SAMSUNG_PHYPWR);
+	rstcon = readl(regs + SAMSUNG_RSTCON);
+
+	switch (sphy->drv_data->cpu_type) {
+	case TYPE_S3C64XX:
+		phyclk &= ~PHYCLK_COMMON_ON_N;
+		phypwr &= ~PHYPWR_NORMAL_MASK;
+		rstcon |= RSTCON_SWRST;
+		break;
+	case TYPE_EXYNOS4210:
+		phypwr &= ~PHYPWR_NORMAL_MASK_PHY0;
+		rstcon |= RSTCON_SWRST;
+	default:
+		break;
+	}
+
+	writel(phyclk, regs + SAMSUNG_PHYCLK);
+	/* Configure PHY0 for normal operation*/
+	writel(phypwr, regs + SAMSUNG_PHYPWR);
+	/* reset all ports of PHY and Link */
+	writel(rstcon, regs + SAMSUNG_RSTCON);
+	udelay(10);
+	rstcon &= ~RSTCON_SWRST;
+	writel(rstcon, regs + SAMSUNG_RSTCON);
+}
+
+static void samsung_exynos5_usb2phy_disable(struct samsung_usbphy *sphy)
+{
+	void __iomem *regs = sphy->regs;
+	u32 phyhost;
+	u32 phyotg;
+	u32 phyhsic;
+
+	if (atomic_dec_return(&sphy->phy_usage) > 0) {
+		dev_info(sphy->dev, "still being used\n");
+		return;
+	}
+
+	phyhsic = (HSIC_CTRL_REFCLKDIV_12 |
+			HSIC_CTRL_REFCLKSEL |
+			HSIC_CTRL_SIDDQ |
+			HSIC_CTRL_FORCESLEEP |
+			HSIC_CTRL_FORCESUSPEND);
+	writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL1);
+	writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL2);
+
+	phyhost = readl(regs + EXYNOS5_PHY_HOST_CTRL0);
+	phyhost |= (HOST_CTRL0_SIDDQ |
+			HOST_CTRL0_FORCESUSPEND |
+			HOST_CTRL0_FORCESLEEP |
+			HOST_CTRL0_PHYSWRST |
+			HOST_CTRL0_PHYSWRSTALL);
+	writel(phyhost, regs + EXYNOS5_PHY_HOST_CTRL0);
+
+	phyotg = readl(regs + EXYNOS5_PHY_OTG_SYS);
+	phyotg |= (OTG_SYS_FORCESUSPEND |
+			OTG_SYS_SIDDQ_UOTG |
+			OTG_SYS_FORCESLEEP);
+	writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS);
+}
+
+static void samsung_usb2phy_disable(struct samsung_usbphy *sphy)
+{
+	void __iomem *regs = sphy->regs;
+	u32 phypwr;
+
+	phypwr = readl(regs + SAMSUNG_PHYPWR);
+
+	switch (sphy->drv_data->cpu_type) {
+	case TYPE_S3C64XX:
+		phypwr |= PHYPWR_NORMAL_MASK;
+		break;
+	case TYPE_EXYNOS4210:
+		phypwr |= PHYPWR_NORMAL_MASK_PHY0;
+	default:
+		break;
+	}
+
+	/* Disable analog and otg block power */
+	writel(phypwr, regs + SAMSUNG_PHYPWR);
+}
+
+/*
+ * The function passed to the usb driver for phy initialization
+ */
+static int samsung_usb2phy_init(struct usb_phy *phy)
+{
+	struct samsung_usbphy *sphy;
+	struct usb_bus *host = NULL;
+	unsigned long flags;
+	int ret = 0;
+
+	sphy = phy_to_sphy(phy);
+
+	host = phy->otg->host;
+
+	/* Enable the phy clock */
+	ret = clk_prepare_enable(sphy->clk);
+	if (ret) {
+		dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__);
+		return ret;
+	}
+
+	spin_lock_irqsave(&sphy->lock, flags);
+
+	if (host) {
+		/* setting default phy-type for USB 2.0 */
+		if (!strstr(dev_name(host->controller), "ehci") ||
+				!strstr(dev_name(host->controller), "ohci"))
+			samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_HOST);
+	} else {
+		samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE);
+	}
+
+	/* Disable phy isolation */
+	if (sphy->plat && sphy->plat->pmu_isolation)
+		sphy->plat->pmu_isolation(false);
+	else
+		samsung_usbphy_set_isolation(sphy, false);
+
+	/* Selecting Host/OTG mode; After reset USB2.0PHY_CFG: HOST */
+	samsung_usbphy_cfg_sel(sphy);
+
+	/* Initialize usb phy registers */
+	if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250)
+		samsung_exynos5_usb2phy_enable(sphy);
+	else
+		samsung_usb2phy_enable(sphy);
+
+	spin_unlock_irqrestore(&sphy->lock, flags);
+
+	/* Disable the phy clock */
+	clk_disable_unprepare(sphy->clk);
+
+	return ret;
+}
+
+/*
+ * The function passed to the usb driver for phy shutdown
+ */
+static void samsung_usb2phy_shutdown(struct usb_phy *phy)
+{
+	struct samsung_usbphy *sphy;
+	struct usb_bus *host = NULL;
+	unsigned long flags;
+
+	sphy = phy_to_sphy(phy);
+
+	host = phy->otg->host;
+
+	if (clk_prepare_enable(sphy->clk)) {
+		dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__);
+		return;
+	}
+
+	spin_lock_irqsave(&sphy->lock, flags);
+
+	if (host) {
+		/* setting default phy-type for USB 2.0 */
+		if (!strstr(dev_name(host->controller), "ehci") ||
+				!strstr(dev_name(host->controller), "ohci"))
+			samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_HOST);
+	} else {
+		samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE);
+	}
+
+	/* De-initialize usb phy registers */
+	if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250)
+		samsung_exynos5_usb2phy_disable(sphy);
+	else
+		samsung_usb2phy_disable(sphy);
+
+	/* Enable phy isolation */
+	if (sphy->plat && sphy->plat->pmu_isolation)
+		sphy->plat->pmu_isolation(true);
+	else
+		samsung_usbphy_set_isolation(sphy, true);
+
+	spin_unlock_irqrestore(&sphy->lock, flags);
+
+	clk_disable_unprepare(sphy->clk);
+}
+
+static int samsung_usb2phy_probe(struct platform_device *pdev)
+{
+	struct samsung_usbphy *sphy;
+	struct usb_otg *otg;
+	struct samsung_usbphy_data *pdata = pdev->dev.platform_data;
+	const struct samsung_usbphy_drvdata *drv_data;
+	struct device *dev = &pdev->dev;
+	struct resource *phy_mem;
+	void __iomem	*phy_base;
+	struct clk *clk;
+	int ret;
+
+	phy_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!phy_mem) {
+		dev_err(dev, "%s: missing mem resource\n", __func__);
+		return -ENODEV;
+	}
+
+	phy_base = devm_ioremap_resource(dev, phy_mem);
+	if (IS_ERR(phy_base))
+		return PTR_ERR(phy_base);
+
+	sphy = devm_kzalloc(dev, sizeof(*sphy), GFP_KERNEL);
+	if (!sphy)
+		return -ENOMEM;
+
+	otg = devm_kzalloc(dev, sizeof(*otg), GFP_KERNEL);
+	if (!otg)
+		return -ENOMEM;
+
+	drv_data = samsung_usbphy_get_driver_data(pdev);
+
+	if (drv_data->cpu_type == TYPE_EXYNOS5250)
+		clk = devm_clk_get(dev, "usbhost");
+	else
+		clk = devm_clk_get(dev, "otg");
+
+	if (IS_ERR(clk)) {
+		dev_err(dev, "Failed to get otg clock\n");
+		return PTR_ERR(clk);
+	}
+
+	sphy->dev = dev;
+
+	if (dev->of_node) {
+		ret = samsung_usbphy_parse_dt(sphy);
+		if (ret < 0)
+			return ret;
+	} else {
+		if (!pdata) {
+			dev_err(dev, "no platform data specified\n");
+			return -EINVAL;
+		}
+	}
+
+	sphy->plat		= pdata;
+	sphy->regs		= phy_base;
+	sphy->clk		= clk;
+	sphy->drv_data		= drv_data;
+	sphy->phy.dev		= sphy->dev;
+	sphy->phy.label		= "samsung-usb2phy";
+	sphy->phy.init		= samsung_usb2phy_init;
+	sphy->phy.shutdown	= samsung_usb2phy_shutdown;
+	sphy->ref_clk_freq	= samsung_usbphy_get_refclk_freq(sphy);
+
+	sphy->phy.otg		= otg;
+	sphy->phy.otg->phy	= &sphy->phy;
+	sphy->phy.otg->set_host = samsung_usbphy_set_host;
+
+	spin_lock_init(&sphy->lock);
+
+	platform_set_drvdata(pdev, sphy);
+
+	return usb_add_phy(&sphy->phy, USB_PHY_TYPE_USB2);
+}
+
+static int samsung_usb2phy_remove(struct platform_device *pdev)
+{
+	struct samsung_usbphy *sphy = platform_get_drvdata(pdev);
+
+	usb_remove_phy(&sphy->phy);
+
+	if (sphy->pmuregs)
+		iounmap(sphy->pmuregs);
+	if (sphy->sysreg)
+		iounmap(sphy->sysreg);
+
+	return 0;
+}
+
+static const struct samsung_usbphy_drvdata usb2phy_s3c64xx = {
+	.cpu_type		= TYPE_S3C64XX,
+	.devphy_en_mask		= S3C64XX_USBPHY_ENABLE,
+};
+
+static const struct samsung_usbphy_drvdata usb2phy_exynos4 = {
+	.cpu_type		= TYPE_EXYNOS4210,
+	.devphy_en_mask		= EXYNOS_USBPHY_ENABLE,
+	.hostphy_en_mask	= EXYNOS_USBPHY_ENABLE,
+};
+
+static struct samsung_usbphy_drvdata usb2phy_exynos5 = {
+	.cpu_type		= TYPE_EXYNOS5250,
+	.hostphy_en_mask	= EXYNOS_USBPHY_ENABLE,
+	.hostphy_reg_offset	= EXYNOS_USBHOST_PHY_CTRL_OFFSET,
+};
+
+#ifdef CONFIG_OF
+static const struct of_device_id samsung_usbphy_dt_match[] = {
+	{
+		.compatible = "samsung,s3c64xx-usb2phy",
+		.data = &usb2phy_s3c64xx,
+	}, {
+		.compatible = "samsung,exynos4210-usb2phy",
+		.data = &usb2phy_exynos4,
+	}, {
+		.compatible = "samsung,exynos5250-usb2phy",
+		.data = &usb2phy_exynos5
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, samsung_usbphy_dt_match);
+#endif
+
+static struct platform_device_id samsung_usbphy_driver_ids[] = {
+	{
+		.name		= "s3c64xx-usb2phy",
+		.driver_data	= (unsigned long)&usb2phy_s3c64xx,
+	}, {
+		.name		= "exynos4210-usb2phy",
+		.driver_data	= (unsigned long)&usb2phy_exynos4,
+	}, {
+		.name		= "exynos5250-usb2phy",
+		.driver_data	= (unsigned long)&usb2phy_exynos5,
+	},
+	{},
+};
+
+MODULE_DEVICE_TABLE(platform, samsung_usbphy_driver_ids);
+
+static struct platform_driver samsung_usb2phy_driver = {
+	.probe		= samsung_usb2phy_probe,
+	.remove		= samsung_usb2phy_remove,
+	.id_table	= samsung_usbphy_driver_ids,
+	.driver		= {
+		.name	= "samsung-usb2phy",
+		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(samsung_usbphy_dt_match),
+	},
+};
+
+module_platform_driver(samsung_usb2phy_driver);
+
+MODULE_DESCRIPTION("Samsung USB 2.0 phy controller");
+MODULE_AUTHOR("Praveen Paneri <p.paneri@samsung.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:samsung-usb2phy");
diff --git a/drivers/usb/phy/phy-samsung-usb3.c b/drivers/usb/phy/phy-samsung-usb3.c
new file mode 100644
index 0000000..133f3d0
--- /dev/null
+++ b/drivers/usb/phy/phy-samsung-usb3.c
@@ -0,0 +1,347 @@
+/* linux/drivers/usb/phy/phy-samsung-usb3.c
+ *
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ *              http://www.samsung.com
+ *
+ * Author: Vivek Gautam <gautam.vivek@samsung.com>
+ *
+ * Samsung USB 3.0 PHY transceiver; talks to DWC3 controller.
+ *
+ * This program is free software; you can 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.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/usb/samsung_usb_phy.h>
+#include <linux/platform_data/samsung-usbphy.h>
+
+#include "phy-samsung-usb.h"
+
+/*
+ * Sets the phy clk as EXTREFCLK (XXTI) which is internal clock from clock core.
+ */
+static u32 samsung_usb3phy_set_refclk(struct samsung_usbphy *sphy)
+{
+	u32 reg;
+	u32 refclk;
+
+	refclk = sphy->ref_clk_freq;
+
+	reg = PHYCLKRST_REFCLKSEL_EXT_REFCLK |
+		PHYCLKRST_FSEL(refclk);
+
+	switch (refclk) {
+	case FSEL_CLKSEL_50M:
+		reg |= (PHYCLKRST_MPLL_MULTIPLIER_50M_REF |
+			PHYCLKRST_SSC_REFCLKSEL(0x00));
+		break;
+	case FSEL_CLKSEL_20M:
+		reg |= (PHYCLKRST_MPLL_MULTIPLIER_20MHZ_REF |
+			PHYCLKRST_SSC_REFCLKSEL(0x00));
+		break;
+	case FSEL_CLKSEL_19200K:
+		reg |= (PHYCLKRST_MPLL_MULTIPLIER_19200KHZ_REF |
+			PHYCLKRST_SSC_REFCLKSEL(0x88));
+		break;
+	case FSEL_CLKSEL_24M:
+	default:
+		reg |= (PHYCLKRST_MPLL_MULTIPLIER_24MHZ_REF |
+			PHYCLKRST_SSC_REFCLKSEL(0x88));
+		break;
+	}
+
+	return reg;
+}
+
+static int samsung_exynos5_usb3phy_enable(struct samsung_usbphy *sphy)
+{
+	void __iomem *regs = sphy->regs;
+	u32 phyparam0;
+	u32 phyparam1;
+	u32 linksystem;
+	u32 phybatchg;
+	u32 phytest;
+	u32 phyclkrst;
+
+	/* Reset USB 3.0 PHY */
+	writel(0x0, regs + EXYNOS5_DRD_PHYREG0);
+
+	phyparam0 = readl(regs + EXYNOS5_DRD_PHYPARAM0);
+	/* Select PHY CLK source */
+	phyparam0 &= ~PHYPARAM0_REF_USE_PAD;
+	/* Set Loss-of-Signal Detector sensitivity */
+	phyparam0 &= ~PHYPARAM0_REF_LOSLEVEL_MASK;
+	phyparam0 |= PHYPARAM0_REF_LOSLEVEL;
+	writel(phyparam0, regs + EXYNOS5_DRD_PHYPARAM0);
+
+	writel(0x0, regs + EXYNOS5_DRD_PHYRESUME);
+
+	/*
+	 * Setting the Frame length Adj value[6:1] to default 0x20
+	 * See xHCI 1.0 spec, 5.2.4
+	 */
+	linksystem = LINKSYSTEM_XHCI_VERSION_CONTROL |
+			LINKSYSTEM_FLADJ(0x20);
+	writel(linksystem, regs + EXYNOS5_DRD_LINKSYSTEM);
+
+	phyparam1 = readl(regs + EXYNOS5_DRD_PHYPARAM1);
+	/* Set Tx De-Emphasis level */
+	phyparam1 &= ~PHYPARAM1_PCS_TXDEEMPH_MASK;
+	phyparam1 |= PHYPARAM1_PCS_TXDEEMPH;
+	writel(phyparam1, regs + EXYNOS5_DRD_PHYPARAM1);
+
+	phybatchg = readl(regs + EXYNOS5_DRD_PHYBATCHG);
+	phybatchg |= PHYBATCHG_UTMI_CLKSEL;
+	writel(phybatchg, regs + EXYNOS5_DRD_PHYBATCHG);
+
+	/* PHYTEST POWERDOWN Control */
+	phytest = readl(regs + EXYNOS5_DRD_PHYTEST);
+	phytest &= ~(PHYTEST_POWERDOWN_SSP |
+			PHYTEST_POWERDOWN_HSP);
+	writel(phytest, regs + EXYNOS5_DRD_PHYTEST);
+
+	/* UTMI Power Control */
+	writel(PHYUTMI_OTGDISABLE, regs + EXYNOS5_DRD_PHYUTMI);
+
+	phyclkrst = samsung_usb3phy_set_refclk(sphy);
+
+	phyclkrst |= PHYCLKRST_PORTRESET |
+			/* Digital power supply in normal operating mode */
+			PHYCLKRST_RETENABLEN |
+			/* Enable ref clock for SS function */
+			PHYCLKRST_REF_SSP_EN |
+			/* Enable spread spectrum */
+			PHYCLKRST_SSC_EN |
+			/* Power down HS Bias and PLL blocks in suspend mode */
+			PHYCLKRST_COMMONONN;
+
+	writel(phyclkrst, regs + EXYNOS5_DRD_PHYCLKRST);
+
+	udelay(10);
+
+	phyclkrst &= ~(PHYCLKRST_PORTRESET);
+	writel(phyclkrst, regs + EXYNOS5_DRD_PHYCLKRST);
+
+	return 0;
+}
+
+static void samsung_exynos5_usb3phy_disable(struct samsung_usbphy *sphy)
+{
+	u32 phyutmi;
+	u32 phyclkrst;
+	u32 phytest;
+	void __iomem *regs = sphy->regs;
+
+	phyutmi = PHYUTMI_OTGDISABLE |
+			PHYUTMI_FORCESUSPEND |
+			PHYUTMI_FORCESLEEP;
+	writel(phyutmi, regs + EXYNOS5_DRD_PHYUTMI);
+
+	/* Resetting the PHYCLKRST enable bits to reduce leakage current */
+	phyclkrst = readl(regs + EXYNOS5_DRD_PHYCLKRST);
+	phyclkrst &= ~(PHYCLKRST_REF_SSP_EN |
+			PHYCLKRST_SSC_EN |
+			PHYCLKRST_COMMONONN);
+	writel(phyclkrst, regs + EXYNOS5_DRD_PHYCLKRST);
+
+	/* Control PHYTEST to remove leakage current */
+	phytest = readl(regs + EXYNOS5_DRD_PHYTEST);
+	phytest |= (PHYTEST_POWERDOWN_SSP |
+			PHYTEST_POWERDOWN_HSP);
+	writel(phytest, regs + EXYNOS5_DRD_PHYTEST);
+}
+
+static int samsung_usb3phy_init(struct usb_phy *phy)
+{
+	struct samsung_usbphy *sphy;
+	unsigned long flags;
+	int ret = 0;
+
+	sphy = phy_to_sphy(phy);
+
+	/* Enable the phy clock */
+	ret = clk_prepare_enable(sphy->clk);
+	if (ret) {
+		dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__);
+		return ret;
+	}
+
+	spin_lock_irqsave(&sphy->lock, flags);
+
+	/* setting default phy-type for USB 3.0 */
+	samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE);
+
+	/* Disable phy isolation */
+	samsung_usbphy_set_isolation(sphy, false);
+
+	/* Initialize usb phy registers */
+	samsung_exynos5_usb3phy_enable(sphy);
+
+	spin_unlock_irqrestore(&sphy->lock, flags);
+
+	/* Disable the phy clock */
+	clk_disable_unprepare(sphy->clk);
+
+	return ret;
+}
+
+/*
+ * The function passed to the usb driver for phy shutdown
+ */
+static void samsung_usb3phy_shutdown(struct usb_phy *phy)
+{
+	struct samsung_usbphy *sphy;
+	unsigned long flags;
+
+	sphy = phy_to_sphy(phy);
+
+	if (clk_prepare_enable(sphy->clk)) {
+		dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__);
+		return;
+	}
+
+	spin_lock_irqsave(&sphy->lock, flags);
+
+	/* setting default phy-type for USB 3.0 */
+	samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE);
+
+	/* De-initialize usb phy registers */
+	samsung_exynos5_usb3phy_disable(sphy);
+
+	/* Enable phy isolation */
+	samsung_usbphy_set_isolation(sphy, true);
+
+	spin_unlock_irqrestore(&sphy->lock, flags);
+
+	clk_disable_unprepare(sphy->clk);
+}
+
+static int samsung_usb3phy_probe(struct platform_device *pdev)
+{
+	struct samsung_usbphy *sphy;
+	struct samsung_usbphy_data *pdata = pdev->dev.platform_data;
+	struct device *dev = &pdev->dev;
+	struct resource *phy_mem;
+	void __iomem	*phy_base;
+	struct clk *clk;
+	int ret;
+
+	phy_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!phy_mem) {
+		dev_err(dev, "%s: missing mem resource\n", __func__);
+		return -ENODEV;
+	}
+
+	phy_base = devm_ioremap_resource(dev, phy_mem);
+	if (IS_ERR(phy_base))
+		return PTR_ERR(phy_base);
+
+	sphy = devm_kzalloc(dev, sizeof(*sphy), GFP_KERNEL);
+	if (!sphy)
+		return -ENOMEM;
+
+	clk = devm_clk_get(dev, "usbdrd30");
+	if (IS_ERR(clk)) {
+		dev_err(dev, "Failed to get device clock\n");
+		return PTR_ERR(clk);
+	}
+
+	sphy->dev = dev;
+
+	if (dev->of_node) {
+		ret = samsung_usbphy_parse_dt(sphy);
+		if (ret < 0)
+			return ret;
+	} else {
+		if (!pdata) {
+			dev_err(dev, "no platform data specified\n");
+			return -EINVAL;
+		}
+	}
+
+	sphy->plat		= pdata;
+	sphy->regs		= phy_base;
+	sphy->clk		= clk;
+	sphy->phy.dev		= sphy->dev;
+	sphy->phy.label		= "samsung-usb3phy";
+	sphy->phy.init		= samsung_usb3phy_init;
+	sphy->phy.shutdown	= samsung_usb3phy_shutdown;
+	sphy->drv_data		= samsung_usbphy_get_driver_data(pdev);
+	sphy->ref_clk_freq	= samsung_usbphy_get_refclk_freq(sphy);
+
+	spin_lock_init(&sphy->lock);
+
+	platform_set_drvdata(pdev, sphy);
+
+	return usb_add_phy(&sphy->phy, USB_PHY_TYPE_USB3);
+}
+
+static int samsung_usb3phy_remove(struct platform_device *pdev)
+{
+	struct samsung_usbphy *sphy = platform_get_drvdata(pdev);
+
+	usb_remove_phy(&sphy->phy);
+
+	if (sphy->pmuregs)
+		iounmap(sphy->pmuregs);
+	if (sphy->sysreg)
+		iounmap(sphy->sysreg);
+
+	return 0;
+}
+
+static struct samsung_usbphy_drvdata usb3phy_exynos5 = {
+	.cpu_type		= TYPE_EXYNOS5250,
+	.devphy_en_mask		= EXYNOS_USBPHY_ENABLE,
+};
+
+#ifdef CONFIG_OF
+static const struct of_device_id samsung_usbphy_dt_match[] = {
+	{
+		.compatible = "samsung,exynos5250-usb3phy",
+		.data = &usb3phy_exynos5
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, samsung_usbphy_dt_match);
+#endif
+
+static struct platform_device_id samsung_usbphy_driver_ids[] = {
+	{
+		.name		= "exynos5250-usb3phy",
+		.driver_data	= (unsigned long)&usb3phy_exynos5,
+	},
+	{},
+};
+
+MODULE_DEVICE_TABLE(platform, samsung_usbphy_driver_ids);
+
+static struct platform_driver samsung_usb3phy_driver = {
+	.probe		= samsung_usb3phy_probe,
+	.remove		= samsung_usb3phy_remove,
+	.id_table	= samsung_usbphy_driver_ids,
+	.driver		= {
+		.name	= "samsung-usb3phy",
+		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(samsung_usbphy_dt_match),
+	},
+};
+
+module_platform_driver(samsung_usb3phy_driver);
+
+MODULE_DESCRIPTION("Samsung USB 3.0 phy controller");
+MODULE_AUTHOR("Vivek Gautam <gautam.vivek@samsung.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:samsung-usb3phy");
diff --git a/drivers/usb/phy/phy-tegra-usb.c b/drivers/usb/phy/phy-tegra-usb.c
new file mode 100644
index 0000000..5487d38
--- /dev/null
+++ b/drivers/usb/phy/phy-tegra-usb.c
@@ -0,0 +1,798 @@
+/*
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *	Erik Gilling <konkers@google.com>
+ *	Benoit Goby <benoit@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/resource.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/usb/otg.h>
+#include <linux/usb/ulpi.h>
+#include <asm/mach-types.h>
+#include <linux/usb/tegra_usb_phy.h>
+
+#define TEGRA_USB_BASE		0xC5000000
+#define TEGRA_USB_SIZE		SZ_16K
+
+#define ULPI_VIEWPORT		0x170
+
+#define USB_SUSP_CTRL		0x400
+#define   USB_WAKE_ON_CNNT_EN_DEV	(1 << 3)
+#define   USB_WAKE_ON_DISCON_EN_DEV	(1 << 4)
+#define   USB_SUSP_CLR		(1 << 5)
+#define   USB_PHY_CLK_VALID	(1 << 7)
+#define   UTMIP_RESET			(1 << 11)
+#define   UHSIC_RESET			(1 << 11)
+#define   UTMIP_PHY_ENABLE		(1 << 12)
+#define   ULPI_PHY_ENABLE	(1 << 13)
+#define   USB_SUSP_SET		(1 << 14)
+#define   USB_WAKEUP_DEBOUNCE_COUNT(x)	(((x) & 0x7) << 16)
+
+#define USB1_LEGACY_CTRL	0x410
+#define   USB1_NO_LEGACY_MODE			(1 << 0)
+#define   USB1_VBUS_SENSE_CTL_MASK		(3 << 1)
+#define   USB1_VBUS_SENSE_CTL_VBUS_WAKEUP	(0 << 1)
+#define   USB1_VBUS_SENSE_CTL_AB_SESS_VLD_OR_VBUS_WAKEUP \
+						(1 << 1)
+#define   USB1_VBUS_SENSE_CTL_AB_SESS_VLD	(2 << 1)
+#define   USB1_VBUS_SENSE_CTL_A_SESS_VLD	(3 << 1)
+
+#define ULPI_TIMING_CTRL_0	0x424
+#define   ULPI_OUTPUT_PINMUX_BYP	(1 << 10)
+#define   ULPI_CLKOUT_PINMUX_BYP	(1 << 11)
+
+#define ULPI_TIMING_CTRL_1	0x428
+#define   ULPI_DATA_TRIMMER_LOAD	(1 << 0)
+#define   ULPI_DATA_TRIMMER_SEL(x)	(((x) & 0x7) << 1)
+#define   ULPI_STPDIRNXT_TRIMMER_LOAD	(1 << 16)
+#define   ULPI_STPDIRNXT_TRIMMER_SEL(x)	(((x) & 0x7) << 17)
+#define   ULPI_DIR_TRIMMER_LOAD		(1 << 24)
+#define   ULPI_DIR_TRIMMER_SEL(x)	(((x) & 0x7) << 25)
+
+#define UTMIP_PLL_CFG1		0x804
+#define   UTMIP_XTAL_FREQ_COUNT(x)		(((x) & 0xfff) << 0)
+#define   UTMIP_PLLU_ENABLE_DLY_COUNT(x)	(((x) & 0x1f) << 27)
+
+#define UTMIP_XCVR_CFG0		0x808
+#define   UTMIP_XCVR_SETUP(x)			(((x) & 0xf) << 0)
+#define   UTMIP_XCVR_LSRSLEW(x)			(((x) & 0x3) << 8)
+#define   UTMIP_XCVR_LSFSLEW(x)			(((x) & 0x3) << 10)
+#define   UTMIP_FORCE_PD_POWERDOWN		(1 << 14)
+#define   UTMIP_FORCE_PD2_POWERDOWN		(1 << 16)
+#define   UTMIP_FORCE_PDZI_POWERDOWN		(1 << 18)
+#define   UTMIP_XCVR_HSSLEW_MSB(x)		(((x) & 0x7f) << 25)
+
+#define UTMIP_BIAS_CFG0		0x80c
+#define   UTMIP_OTGPD			(1 << 11)
+#define   UTMIP_BIASPD			(1 << 10)
+
+#define UTMIP_HSRX_CFG0		0x810
+#define   UTMIP_ELASTIC_LIMIT(x)	(((x) & 0x1f) << 10)
+#define   UTMIP_IDLE_WAIT(x)		(((x) & 0x1f) << 15)
+
+#define UTMIP_HSRX_CFG1		0x814
+#define   UTMIP_HS_SYNC_START_DLY(x)	(((x) & 0x1f) << 1)
+
+#define UTMIP_TX_CFG0		0x820
+#define   UTMIP_FS_PREABMLE_J		(1 << 19)
+#define   UTMIP_HS_DISCON_DISABLE	(1 << 8)
+
+#define UTMIP_MISC_CFG0		0x824
+#define   UTMIP_DPDM_OBSERVE		(1 << 26)
+#define   UTMIP_DPDM_OBSERVE_SEL(x)	(((x) & 0xf) << 27)
+#define   UTMIP_DPDM_OBSERVE_SEL_FS_J	UTMIP_DPDM_OBSERVE_SEL(0xf)
+#define   UTMIP_DPDM_OBSERVE_SEL_FS_K	UTMIP_DPDM_OBSERVE_SEL(0xe)
+#define   UTMIP_DPDM_OBSERVE_SEL_FS_SE1 UTMIP_DPDM_OBSERVE_SEL(0xd)
+#define   UTMIP_DPDM_OBSERVE_SEL_FS_SE0 UTMIP_DPDM_OBSERVE_SEL(0xc)
+#define   UTMIP_SUSPEND_EXIT_ON_EDGE	(1 << 22)
+
+#define UTMIP_MISC_CFG1		0x828
+#define   UTMIP_PLL_ACTIVE_DLY_COUNT(x)	(((x) & 0x1f) << 18)
+#define   UTMIP_PLLU_STABLE_COUNT(x)	(((x) & 0xfff) << 6)
+
+#define UTMIP_DEBOUNCE_CFG0	0x82c
+#define   UTMIP_BIAS_DEBOUNCE_A(x)	(((x) & 0xffff) << 0)
+
+#define UTMIP_BAT_CHRG_CFG0	0x830
+#define   UTMIP_PD_CHRG			(1 << 0)
+
+#define UTMIP_SPARE_CFG0	0x834
+#define   FUSE_SETUP_SEL		(1 << 3)
+
+#define UTMIP_XCVR_CFG1		0x838
+#define   UTMIP_FORCE_PDDISC_POWERDOWN	(1 << 0)
+#define   UTMIP_FORCE_PDCHRP_POWERDOWN	(1 << 2)
+#define   UTMIP_FORCE_PDDR_POWERDOWN	(1 << 4)
+#define   UTMIP_XCVR_TERM_RANGE_ADJ(x)	(((x) & 0xf) << 18)
+
+#define UTMIP_BIAS_CFG1		0x83c
+#define   UTMIP_BIAS_PDTRK_COUNT(x)	(((x) & 0x1f) << 3)
+
+static DEFINE_SPINLOCK(utmip_pad_lock);
+static int utmip_pad_count;
+
+struct tegra_xtal_freq {
+	int freq;
+	u8 enable_delay;
+	u8 stable_count;
+	u8 active_delay;
+	u8 xtal_freq_count;
+	u16 debounce;
+};
+
+static const struct tegra_xtal_freq tegra_freq_table[] = {
+	{
+		.freq = 12000000,
+		.enable_delay = 0x02,
+		.stable_count = 0x2F,
+		.active_delay = 0x04,
+		.xtal_freq_count = 0x76,
+		.debounce = 0x7530,
+	},
+	{
+		.freq = 13000000,
+		.enable_delay = 0x02,
+		.stable_count = 0x33,
+		.active_delay = 0x05,
+		.xtal_freq_count = 0x7F,
+		.debounce = 0x7EF4,
+	},
+	{
+		.freq = 19200000,
+		.enable_delay = 0x03,
+		.stable_count = 0x4B,
+		.active_delay = 0x06,
+		.xtal_freq_count = 0xBB,
+		.debounce = 0xBB80,
+	},
+	{
+		.freq = 26000000,
+		.enable_delay = 0x04,
+		.stable_count = 0x66,
+		.active_delay = 0x09,
+		.xtal_freq_count = 0xFE,
+		.debounce = 0xFDE8,
+	},
+};
+
+static struct tegra_utmip_config utmip_default[] = {
+	[0] = {
+		.hssync_start_delay = 9,
+		.idle_wait_delay = 17,
+		.elastic_limit = 16,
+		.term_range_adj = 6,
+		.xcvr_setup = 9,
+		.xcvr_lsfslew = 1,
+		.xcvr_lsrslew = 1,
+	},
+	[2] = {
+		.hssync_start_delay = 9,
+		.idle_wait_delay = 17,
+		.elastic_limit = 16,
+		.term_range_adj = 6,
+		.xcvr_setup = 9,
+		.xcvr_lsfslew = 2,
+		.xcvr_lsrslew = 2,
+	},
+};
+
+static int utmip_pad_open(struct tegra_usb_phy *phy)
+{
+	phy->pad_clk = clk_get_sys("utmip-pad", NULL);
+	if (IS_ERR(phy->pad_clk)) {
+		pr_err("%s: can't get utmip pad clock\n", __func__);
+		return PTR_ERR(phy->pad_clk);
+	}
+
+	if (phy->is_legacy_phy) {
+		phy->pad_regs = phy->regs;
+	} else {
+		phy->pad_regs = ioremap(TEGRA_USB_BASE, TEGRA_USB_SIZE);
+		if (!phy->pad_regs) {
+			pr_err("%s: can't remap usb registers\n", __func__);
+			clk_put(phy->pad_clk);
+			return -ENOMEM;
+		}
+	}
+	return 0;
+}
+
+static void utmip_pad_close(struct tegra_usb_phy *phy)
+{
+	if (!phy->is_legacy_phy)
+		iounmap(phy->pad_regs);
+	clk_put(phy->pad_clk);
+}
+
+static void utmip_pad_power_on(struct tegra_usb_phy *phy)
+{
+	unsigned long val, flags;
+	void __iomem *base = phy->pad_regs;
+
+	clk_prepare_enable(phy->pad_clk);
+
+	spin_lock_irqsave(&utmip_pad_lock, flags);
+
+	if (utmip_pad_count++ == 0) {
+		val = readl(base + UTMIP_BIAS_CFG0);
+		val &= ~(UTMIP_OTGPD | UTMIP_BIASPD);
+		writel(val, base + UTMIP_BIAS_CFG0);
+	}
+
+	spin_unlock_irqrestore(&utmip_pad_lock, flags);
+
+	clk_disable_unprepare(phy->pad_clk);
+}
+
+static int utmip_pad_power_off(struct tegra_usb_phy *phy)
+{
+	unsigned long val, flags;
+	void __iomem *base = phy->pad_regs;
+
+	if (!utmip_pad_count) {
+		pr_err("%s: utmip pad already powered off\n", __func__);
+		return -EINVAL;
+	}
+
+	clk_prepare_enable(phy->pad_clk);
+
+	spin_lock_irqsave(&utmip_pad_lock, flags);
+
+	if (--utmip_pad_count == 0) {
+		val = readl(base + UTMIP_BIAS_CFG0);
+		val |= UTMIP_OTGPD | UTMIP_BIASPD;
+		writel(val, base + UTMIP_BIAS_CFG0);
+	}
+
+	spin_unlock_irqrestore(&utmip_pad_lock, flags);
+
+	clk_disable_unprepare(phy->pad_clk);
+
+	return 0;
+}
+
+static int utmi_wait_register(void __iomem *reg, u32 mask, u32 result)
+{
+	unsigned long timeout = 2000;
+	do {
+		if ((readl(reg) & mask) == result)
+			return 0;
+		udelay(1);
+		timeout--;
+	} while (timeout);
+	return -1;
+}
+
+static void utmi_phy_clk_disable(struct tegra_usb_phy *phy)
+{
+	unsigned long val;
+	void __iomem *base = phy->regs;
+
+	if (phy->is_legacy_phy) {
+		val = readl(base + USB_SUSP_CTRL);
+		val |= USB_SUSP_SET;
+		writel(val, base + USB_SUSP_CTRL);
+
+		udelay(10);
+
+		val = readl(base + USB_SUSP_CTRL);
+		val &= ~USB_SUSP_SET;
+		writel(val, base + USB_SUSP_CTRL);
+	} else
+		tegra_ehci_set_phcd(&phy->u_phy, true);
+
+	if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, 0) < 0)
+		pr_err("%s: timeout waiting for phy to stabilize\n", __func__);
+}
+
+static void utmi_phy_clk_enable(struct tegra_usb_phy *phy)
+{
+	unsigned long val;
+	void __iomem *base = phy->regs;
+
+	if (phy->is_legacy_phy) {
+		val = readl(base + USB_SUSP_CTRL);
+		val |= USB_SUSP_CLR;
+		writel(val, base + USB_SUSP_CTRL);
+
+		udelay(10);
+
+		val = readl(base + USB_SUSP_CTRL);
+		val &= ~USB_SUSP_CLR;
+		writel(val, base + USB_SUSP_CTRL);
+	} else
+		tegra_ehci_set_phcd(&phy->u_phy, false);
+
+	if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID,
+						     USB_PHY_CLK_VALID))
+		pr_err("%s: timeout waiting for phy to stabilize\n", __func__);
+}
+
+static int utmi_phy_power_on(struct tegra_usb_phy *phy)
+{
+	unsigned long val;
+	void __iomem *base = phy->regs;
+	struct tegra_utmip_config *config = phy->config;
+
+	val = readl(base + USB_SUSP_CTRL);
+	val |= UTMIP_RESET;
+	writel(val, base + USB_SUSP_CTRL);
+
+	if (phy->is_legacy_phy) {
+		val = readl(base + USB1_LEGACY_CTRL);
+		val |= USB1_NO_LEGACY_MODE;
+		writel(val, base + USB1_LEGACY_CTRL);
+	}
+
+	val = readl(base + UTMIP_TX_CFG0);
+	val &= ~UTMIP_FS_PREABMLE_J;
+	writel(val, base + UTMIP_TX_CFG0);
+
+	val = readl(base + UTMIP_HSRX_CFG0);
+	val &= ~(UTMIP_IDLE_WAIT(~0) | UTMIP_ELASTIC_LIMIT(~0));
+	val |= UTMIP_IDLE_WAIT(config->idle_wait_delay);
+	val |= UTMIP_ELASTIC_LIMIT(config->elastic_limit);
+	writel(val, base + UTMIP_HSRX_CFG0);
+
+	val = readl(base + UTMIP_HSRX_CFG1);
+	val &= ~UTMIP_HS_SYNC_START_DLY(~0);
+	val |= UTMIP_HS_SYNC_START_DLY(config->hssync_start_delay);
+	writel(val, base + UTMIP_HSRX_CFG1);
+
+	val = readl(base + UTMIP_DEBOUNCE_CFG0);
+	val &= ~UTMIP_BIAS_DEBOUNCE_A(~0);
+	val |= UTMIP_BIAS_DEBOUNCE_A(phy->freq->debounce);
+	writel(val, base + UTMIP_DEBOUNCE_CFG0);
+
+	val = readl(base + UTMIP_MISC_CFG0);
+	val &= ~UTMIP_SUSPEND_EXIT_ON_EDGE;
+	writel(val, base + UTMIP_MISC_CFG0);
+
+	val = readl(base + UTMIP_MISC_CFG1);
+	val &= ~(UTMIP_PLL_ACTIVE_DLY_COUNT(~0) | UTMIP_PLLU_STABLE_COUNT(~0));
+	val |= UTMIP_PLL_ACTIVE_DLY_COUNT(phy->freq->active_delay) |
+		UTMIP_PLLU_STABLE_COUNT(phy->freq->stable_count);
+	writel(val, base + UTMIP_MISC_CFG1);
+
+	val = readl(base + UTMIP_PLL_CFG1);
+	val &= ~(UTMIP_XTAL_FREQ_COUNT(~0) | UTMIP_PLLU_ENABLE_DLY_COUNT(~0));
+	val |= UTMIP_XTAL_FREQ_COUNT(phy->freq->xtal_freq_count) |
+		UTMIP_PLLU_ENABLE_DLY_COUNT(phy->freq->enable_delay);
+	writel(val, base + UTMIP_PLL_CFG1);
+
+	if (phy->mode == TEGRA_USB_PHY_MODE_DEVICE) {
+		val = readl(base + USB_SUSP_CTRL);
+		val &= ~(USB_WAKE_ON_CNNT_EN_DEV | USB_WAKE_ON_DISCON_EN_DEV);
+		writel(val, base + USB_SUSP_CTRL);
+	}
+
+	utmip_pad_power_on(phy);
+
+	val = readl(base + UTMIP_XCVR_CFG0);
+	val &= ~(UTMIP_FORCE_PD_POWERDOWN | UTMIP_FORCE_PD2_POWERDOWN |
+		 UTMIP_FORCE_PDZI_POWERDOWN | UTMIP_XCVR_SETUP(~0) |
+		 UTMIP_XCVR_LSFSLEW(~0) | UTMIP_XCVR_LSRSLEW(~0) |
+		 UTMIP_XCVR_HSSLEW_MSB(~0));
+	val |= UTMIP_XCVR_SETUP(config->xcvr_setup);
+	val |= UTMIP_XCVR_LSFSLEW(config->xcvr_lsfslew);
+	val |= UTMIP_XCVR_LSRSLEW(config->xcvr_lsrslew);
+	writel(val, base + UTMIP_XCVR_CFG0);
+
+	val = readl(base + UTMIP_XCVR_CFG1);
+	val &= ~(UTMIP_FORCE_PDDISC_POWERDOWN | UTMIP_FORCE_PDCHRP_POWERDOWN |
+		 UTMIP_FORCE_PDDR_POWERDOWN | UTMIP_XCVR_TERM_RANGE_ADJ(~0));
+	val |= UTMIP_XCVR_TERM_RANGE_ADJ(config->term_range_adj);
+	writel(val, base + UTMIP_XCVR_CFG1);
+
+	val = readl(base + UTMIP_BAT_CHRG_CFG0);
+	val &= ~UTMIP_PD_CHRG;
+	writel(val, base + UTMIP_BAT_CHRG_CFG0);
+
+	val = readl(base + UTMIP_BIAS_CFG1);
+	val &= ~UTMIP_BIAS_PDTRK_COUNT(~0);
+	val |= UTMIP_BIAS_PDTRK_COUNT(0x5);
+	writel(val, base + UTMIP_BIAS_CFG1);
+
+	if (phy->is_legacy_phy) {
+		val = readl(base + UTMIP_SPARE_CFG0);
+		if (phy->mode == TEGRA_USB_PHY_MODE_DEVICE)
+			val &= ~FUSE_SETUP_SEL;
+		else
+			val |= FUSE_SETUP_SEL;
+		writel(val, base + UTMIP_SPARE_CFG0);
+	} else {
+		val = readl(base + USB_SUSP_CTRL);
+		val |= UTMIP_PHY_ENABLE;
+		writel(val, base + USB_SUSP_CTRL);
+	}
+
+	val = readl(base + USB_SUSP_CTRL);
+	val &= ~UTMIP_RESET;
+	writel(val, base + USB_SUSP_CTRL);
+
+	if (phy->is_legacy_phy) {
+		val = readl(base + USB1_LEGACY_CTRL);
+		val &= ~USB1_VBUS_SENSE_CTL_MASK;
+		val |= USB1_VBUS_SENSE_CTL_A_SESS_VLD;
+		writel(val, base + USB1_LEGACY_CTRL);
+
+		val = readl(base + USB_SUSP_CTRL);
+		val &= ~USB_SUSP_SET;
+		writel(val, base + USB_SUSP_CTRL);
+	}
+
+	utmi_phy_clk_enable(phy);
+
+	if (!phy->is_legacy_phy)
+		tegra_ehci_set_pts(&phy->u_phy, 0);
+
+	return 0;
+}
+
+static int utmi_phy_power_off(struct tegra_usb_phy *phy)
+{
+	unsigned long val;
+	void __iomem *base = phy->regs;
+
+	utmi_phy_clk_disable(phy);
+
+	if (phy->mode == TEGRA_USB_PHY_MODE_DEVICE) {
+		val = readl(base + USB_SUSP_CTRL);
+		val &= ~USB_WAKEUP_DEBOUNCE_COUNT(~0);
+		val |= USB_WAKE_ON_CNNT_EN_DEV | USB_WAKEUP_DEBOUNCE_COUNT(5);
+		writel(val, base + USB_SUSP_CTRL);
+	}
+
+	val = readl(base + USB_SUSP_CTRL);
+	val |= UTMIP_RESET;
+	writel(val, base + USB_SUSP_CTRL);
+
+	val = readl(base + UTMIP_BAT_CHRG_CFG0);
+	val |= UTMIP_PD_CHRG;
+	writel(val, base + UTMIP_BAT_CHRG_CFG0);
+
+	val = readl(base + UTMIP_XCVR_CFG0);
+	val |= UTMIP_FORCE_PD_POWERDOWN | UTMIP_FORCE_PD2_POWERDOWN |
+	       UTMIP_FORCE_PDZI_POWERDOWN;
+	writel(val, base + UTMIP_XCVR_CFG0);
+
+	val = readl(base + UTMIP_XCVR_CFG1);
+	val |= UTMIP_FORCE_PDDISC_POWERDOWN | UTMIP_FORCE_PDCHRP_POWERDOWN |
+	       UTMIP_FORCE_PDDR_POWERDOWN;
+	writel(val, base + UTMIP_XCVR_CFG1);
+
+	return utmip_pad_power_off(phy);
+}
+
+static void utmi_phy_preresume(struct tegra_usb_phy *phy)
+{
+	unsigned long val;
+	void __iomem *base = phy->regs;
+
+	val = readl(base + UTMIP_TX_CFG0);
+	val |= UTMIP_HS_DISCON_DISABLE;
+	writel(val, base + UTMIP_TX_CFG0);
+}
+
+static void utmi_phy_postresume(struct tegra_usb_phy *phy)
+{
+	unsigned long val;
+	void __iomem *base = phy->regs;
+
+	val = readl(base + UTMIP_TX_CFG0);
+	val &= ~UTMIP_HS_DISCON_DISABLE;
+	writel(val, base + UTMIP_TX_CFG0);
+}
+
+static void utmi_phy_restore_start(struct tegra_usb_phy *phy,
+				   enum tegra_usb_phy_port_speed port_speed)
+{
+	unsigned long val;
+	void __iomem *base = phy->regs;
+
+	val = readl(base + UTMIP_MISC_CFG0);
+	val &= ~UTMIP_DPDM_OBSERVE_SEL(~0);
+	if (port_speed == TEGRA_USB_PHY_PORT_SPEED_LOW)
+		val |= UTMIP_DPDM_OBSERVE_SEL_FS_K;
+	else
+		val |= UTMIP_DPDM_OBSERVE_SEL_FS_J;
+	writel(val, base + UTMIP_MISC_CFG0);
+	udelay(1);
+
+	val = readl(base + UTMIP_MISC_CFG0);
+	val |= UTMIP_DPDM_OBSERVE;
+	writel(val, base + UTMIP_MISC_CFG0);
+	udelay(10);
+}
+
+static void utmi_phy_restore_end(struct tegra_usb_phy *phy)
+{
+	unsigned long val;
+	void __iomem *base = phy->regs;
+
+	val = readl(base + UTMIP_MISC_CFG0);
+	val &= ~UTMIP_DPDM_OBSERVE;
+	writel(val, base + UTMIP_MISC_CFG0);
+	udelay(10);
+}
+
+static int ulpi_phy_power_on(struct tegra_usb_phy *phy)
+{
+	int ret;
+	unsigned long val;
+	void __iomem *base = phy->regs;
+	struct tegra_ulpi_config *config = phy->config;
+
+	gpio_direction_output(config->reset_gpio, 0);
+	msleep(5);
+	gpio_direction_output(config->reset_gpio, 1);
+
+	clk_prepare_enable(phy->clk);
+	msleep(1);
+
+	val = readl(base + USB_SUSP_CTRL);
+	val |= UHSIC_RESET;
+	writel(val, base + USB_SUSP_CTRL);
+
+	val = readl(base + ULPI_TIMING_CTRL_0);
+	val |= ULPI_OUTPUT_PINMUX_BYP | ULPI_CLKOUT_PINMUX_BYP;
+	writel(val, base + ULPI_TIMING_CTRL_0);
+
+	val = readl(base + USB_SUSP_CTRL);
+	val |= ULPI_PHY_ENABLE;
+	writel(val, base + USB_SUSP_CTRL);
+
+	val = 0;
+	writel(val, base + ULPI_TIMING_CTRL_1);
+
+	val |= ULPI_DATA_TRIMMER_SEL(4);
+	val |= ULPI_STPDIRNXT_TRIMMER_SEL(4);
+	val |= ULPI_DIR_TRIMMER_SEL(4);
+	writel(val, base + ULPI_TIMING_CTRL_1);
+	udelay(10);
+
+	val |= ULPI_DATA_TRIMMER_LOAD;
+	val |= ULPI_STPDIRNXT_TRIMMER_LOAD;
+	val |= ULPI_DIR_TRIMMER_LOAD;
+	writel(val, base + ULPI_TIMING_CTRL_1);
+
+	/* Fix VbusInvalid due to floating VBUS */
+	ret = usb_phy_io_write(phy->ulpi, 0x40, 0x08);
+	if (ret) {
+		pr_err("%s: ulpi write failed\n", __func__);
+		return ret;
+	}
+
+	ret = usb_phy_io_write(phy->ulpi, 0x80, 0x0B);
+	if (ret) {
+		pr_err("%s: ulpi write failed\n", __func__);
+		return ret;
+	}
+
+	val = readl(base + USB_SUSP_CTRL);
+	val |= USB_SUSP_CLR;
+	writel(val, base + USB_SUSP_CTRL);
+	udelay(100);
+
+	val = readl(base + USB_SUSP_CTRL);
+	val &= ~USB_SUSP_CLR;
+	writel(val, base + USB_SUSP_CTRL);
+
+	return 0;
+}
+
+static int ulpi_phy_power_off(struct tegra_usb_phy *phy)
+{
+	struct tegra_ulpi_config *config = phy->config;
+
+	clk_disable(phy->clk);
+	return gpio_direction_output(config->reset_gpio, 0);
+}
+
+static int	tegra_phy_init(struct usb_phy *x)
+{
+	struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy);
+	struct tegra_ulpi_config *ulpi_config;
+	int err;
+
+	if (phy->is_ulpi_phy) {
+		ulpi_config = phy->config;
+		phy->clk = clk_get_sys(NULL, ulpi_config->clk);
+		if (IS_ERR(phy->clk)) {
+			pr_err("%s: can't get ulpi clock\n", __func__);
+			err = -ENXIO;
+			goto err1;
+		}
+		if (!gpio_is_valid(ulpi_config->reset_gpio))
+			ulpi_config->reset_gpio =
+				of_get_named_gpio(phy->dev->of_node,
+						  "nvidia,phy-reset-gpio", 0);
+		if (!gpio_is_valid(ulpi_config->reset_gpio)) {
+			pr_err("%s: invalid reset gpio: %d\n", __func__,
+			       ulpi_config->reset_gpio);
+			err = -EINVAL;
+			goto err1;
+		}
+		gpio_request(ulpi_config->reset_gpio, "ulpi_phy_reset_b");
+		gpio_direction_output(ulpi_config->reset_gpio, 0);
+		phy->ulpi = otg_ulpi_create(&ulpi_viewport_access_ops, 0);
+		phy->ulpi->io_priv = phy->regs + ULPI_VIEWPORT;
+	} else {
+		err = utmip_pad_open(phy);
+		if (err < 0)
+			goto err1;
+	}
+	return 0;
+err1:
+	clk_disable_unprepare(phy->pll_u);
+	clk_put(phy->pll_u);
+	return err;
+}
+
+static void tegra_usb_phy_close(struct usb_phy *x)
+{
+	struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy);
+
+	if (phy->is_ulpi_phy)
+		clk_put(phy->clk);
+	else
+		utmip_pad_close(phy);
+	clk_disable_unprepare(phy->pll_u);
+	clk_put(phy->pll_u);
+	kfree(phy);
+}
+
+static int tegra_usb_phy_power_on(struct tegra_usb_phy *phy)
+{
+	if (phy->is_ulpi_phy)
+		return ulpi_phy_power_on(phy);
+	else
+		return utmi_phy_power_on(phy);
+}
+
+static int tegra_usb_phy_power_off(struct tegra_usb_phy *phy)
+{
+	if (phy->is_ulpi_phy)
+		return ulpi_phy_power_off(phy);
+	else
+		return utmi_phy_power_off(phy);
+}
+
+static int	tegra_usb_phy_suspend(struct usb_phy *x, int suspend)
+{
+	struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy);
+	if (suspend)
+		return tegra_usb_phy_power_off(phy);
+	else
+		return tegra_usb_phy_power_on(phy);
+}
+
+struct tegra_usb_phy *tegra_usb_phy_open(struct device *dev, int instance,
+	void __iomem *regs, void *config, enum tegra_usb_phy_mode phy_mode)
+{
+	struct tegra_usb_phy *phy;
+	unsigned long parent_rate;
+	int i;
+	int err;
+	struct device_node *np = dev->of_node;
+
+	phy = kzalloc(sizeof(struct tegra_usb_phy), GFP_KERNEL);
+	if (!phy)
+		return ERR_PTR(-ENOMEM);
+
+	phy->instance = instance;
+	phy->regs = regs;
+	phy->config = config;
+	phy->mode = phy_mode;
+	phy->dev = dev;
+	phy->is_legacy_phy =
+		of_property_read_bool(np, "nvidia,has-legacy-mode");
+	err = of_property_match_string(np, "phy_type", "ulpi");
+	if (err < 0)
+		phy->is_ulpi_phy = false;
+	else
+		phy->is_ulpi_phy = true;
+
+	if (!phy->config) {
+		if (phy->is_ulpi_phy) {
+			pr_err("%s: ulpi phy configuration missing", __func__);
+			err = -EINVAL;
+			goto err0;
+		} else {
+			phy->config = &utmip_default[instance];
+		}
+	}
+
+	phy->pll_u = clk_get_sys(NULL, "pll_u");
+	if (IS_ERR(phy->pll_u)) {
+		pr_err("Can't get pll_u clock\n");
+		err = PTR_ERR(phy->pll_u);
+		goto err0;
+	}
+	clk_prepare_enable(phy->pll_u);
+
+	parent_rate = clk_get_rate(clk_get_parent(phy->pll_u));
+	for (i = 0; i < ARRAY_SIZE(tegra_freq_table); i++) {
+		if (tegra_freq_table[i].freq == parent_rate) {
+			phy->freq = &tegra_freq_table[i];
+			break;
+		}
+	}
+	if (!phy->freq) {
+		pr_err("invalid pll_u parent rate %ld\n", parent_rate);
+		err = -EINVAL;
+		goto err1;
+	}
+
+	phy->u_phy.init = tegra_phy_init;
+	phy->u_phy.shutdown = tegra_usb_phy_close;
+	phy->u_phy.set_suspend = tegra_usb_phy_suspend;
+
+	return phy;
+
+err1:
+	clk_disable_unprepare(phy->pll_u);
+	clk_put(phy->pll_u);
+err0:
+	kfree(phy);
+	return ERR_PTR(err);
+}
+EXPORT_SYMBOL_GPL(tegra_usb_phy_open);
+
+void tegra_usb_phy_preresume(struct usb_phy *x)
+{
+	struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy);
+
+	if (!phy->is_ulpi_phy)
+		utmi_phy_preresume(phy);
+}
+EXPORT_SYMBOL_GPL(tegra_usb_phy_preresume);
+
+void tegra_usb_phy_postresume(struct usb_phy *x)
+{
+	struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy);
+
+	if (!phy->is_ulpi_phy)
+		utmi_phy_postresume(phy);
+}
+EXPORT_SYMBOL_GPL(tegra_usb_phy_postresume);
+
+void tegra_ehci_phy_restore_start(struct usb_phy *x,
+				 enum tegra_usb_phy_port_speed port_speed)
+{
+	struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy);
+
+	if (!phy->is_ulpi_phy)
+		utmi_phy_restore_start(phy, port_speed);
+}
+EXPORT_SYMBOL_GPL(tegra_ehci_phy_restore_start);
+
+void tegra_ehci_phy_restore_end(struct usb_phy *x)
+{
+	struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy);
+
+	if (!phy->is_ulpi_phy)
+		utmi_phy_restore_end(phy);
+}
+EXPORT_SYMBOL_GPL(tegra_ehci_phy_restore_end);
+
diff --git a/drivers/usb/phy/phy-twl4030-usb.c b/drivers/usb/phy/phy-twl4030-usb.c
new file mode 100644
index 0000000..8f78d2d
--- /dev/null
+++ b/drivers/usb/phy/phy-twl4030-usb.c
@@ -0,0 +1,794 @@
+/*
+ * twl4030_usb - TWL4030 USB transceiver, talking to OMAP OTG controller
+ *
+ * Copyright (C) 2004-2007 Texas Instruments
+ * Copyright (C) 2008 Nokia Corporation
+ * Contact: Felipe Balbi <felipe.balbi@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Current status:
+ *	- HS USB ULPI mode works.
+ *	- 3-pin mode support may be added in future.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/usb/otg.h>
+#include <linux/usb/musb-omap.h>
+#include <linux/usb/ulpi.h>
+#include <linux/i2c/twl.h>
+#include <linux/regulator/consumer.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+
+/* Register defines */
+
+#define MCPC_CTRL			0x30
+#define MCPC_CTRL_RTSOL			(1 << 7)
+#define MCPC_CTRL_EXTSWR		(1 << 6)
+#define MCPC_CTRL_EXTSWC		(1 << 5)
+#define MCPC_CTRL_VOICESW		(1 << 4)
+#define MCPC_CTRL_OUT64K		(1 << 3)
+#define MCPC_CTRL_RTSCTSSW		(1 << 2)
+#define MCPC_CTRL_HS_UART		(1 << 0)
+
+#define MCPC_IO_CTRL			0x33
+#define MCPC_IO_CTRL_MICBIASEN		(1 << 5)
+#define MCPC_IO_CTRL_CTS_NPU		(1 << 4)
+#define MCPC_IO_CTRL_RXD_PU		(1 << 3)
+#define MCPC_IO_CTRL_TXDTYP		(1 << 2)
+#define MCPC_IO_CTRL_CTSTYP		(1 << 1)
+#define MCPC_IO_CTRL_RTSTYP		(1 << 0)
+
+#define MCPC_CTRL2			0x36
+#define MCPC_CTRL2_MCPC_CK_EN		(1 << 0)
+
+#define OTHER_FUNC_CTRL			0x80
+#define OTHER_FUNC_CTRL_BDIS_ACON_EN	(1 << 4)
+#define OTHER_FUNC_CTRL_FIVEWIRE_MODE	(1 << 2)
+
+#define OTHER_IFC_CTRL			0x83
+#define OTHER_IFC_CTRL_OE_INT_EN	(1 << 6)
+#define OTHER_IFC_CTRL_CEA2011_MODE	(1 << 5)
+#define OTHER_IFC_CTRL_FSLSSERIALMODE_4PIN	(1 << 4)
+#define OTHER_IFC_CTRL_HIZ_ULPI_60MHZ_OUT	(1 << 3)
+#define OTHER_IFC_CTRL_HIZ_ULPI		(1 << 2)
+#define OTHER_IFC_CTRL_ALT_INT_REROUTE	(1 << 0)
+
+#define OTHER_INT_EN_RISE		0x86
+#define OTHER_INT_EN_FALL		0x89
+#define OTHER_INT_STS			0x8C
+#define OTHER_INT_LATCH			0x8D
+#define OTHER_INT_VB_SESS_VLD		(1 << 7)
+#define OTHER_INT_DM_HI			(1 << 6) /* not valid for "latch" reg */
+#define OTHER_INT_DP_HI			(1 << 5) /* not valid for "latch" reg */
+#define OTHER_INT_BDIS_ACON		(1 << 3) /* not valid for "fall" regs */
+#define OTHER_INT_MANU			(1 << 1)
+#define OTHER_INT_ABNORMAL_STRESS	(1 << 0)
+
+#define ID_STATUS			0x96
+#define ID_RES_FLOAT			(1 << 4)
+#define ID_RES_440K			(1 << 3)
+#define ID_RES_200K			(1 << 2)
+#define ID_RES_102K			(1 << 1)
+#define ID_RES_GND			(1 << 0)
+
+#define POWER_CTRL			0xAC
+#define POWER_CTRL_OTG_ENAB		(1 << 5)
+
+#define OTHER_IFC_CTRL2			0xAF
+#define OTHER_IFC_CTRL2_ULPI_STP_LOW	(1 << 4)
+#define OTHER_IFC_CTRL2_ULPI_TXEN_POL	(1 << 3)
+#define OTHER_IFC_CTRL2_ULPI_4PIN_2430	(1 << 2)
+#define OTHER_IFC_CTRL2_USB_INT_OUTSEL_MASK	(3 << 0) /* bits 0 and 1 */
+#define OTHER_IFC_CTRL2_USB_INT_OUTSEL_INT1N	(0 << 0)
+#define OTHER_IFC_CTRL2_USB_INT_OUTSEL_INT2N	(1 << 0)
+
+#define REG_CTRL_EN			0xB2
+#define REG_CTRL_ERROR			0xB5
+#define ULPI_I2C_CONFLICT_INTEN		(1 << 0)
+
+#define OTHER_FUNC_CTRL2		0xB8
+#define OTHER_FUNC_CTRL2_VBAT_TIMER_EN	(1 << 0)
+
+/* following registers do not have separate _clr and _set registers */
+#define VBUS_DEBOUNCE			0xC0
+#define ID_DEBOUNCE			0xC1
+#define VBAT_TIMER			0xD3
+#define PHY_PWR_CTRL			0xFD
+#define PHY_PWR_PHYPWD			(1 << 0)
+#define PHY_CLK_CTRL			0xFE
+#define PHY_CLK_CTRL_CLOCKGATING_EN	(1 << 2)
+#define PHY_CLK_CTRL_CLK32K_EN		(1 << 1)
+#define REQ_PHY_DPLL_CLK		(1 << 0)
+#define PHY_CLK_CTRL_STS		0xFF
+#define PHY_DPLL_CLK			(1 << 0)
+
+/* In module TWL_MODULE_PM_MASTER */
+#define STS_HW_CONDITIONS		0x0F
+
+/* In module TWL_MODULE_PM_RECEIVER */
+#define VUSB_DEDICATED1			0x7D
+#define VUSB_DEDICATED2			0x7E
+#define VUSB1V5_DEV_GRP			0x71
+#define VUSB1V5_TYPE			0x72
+#define VUSB1V5_REMAP			0x73
+#define VUSB1V8_DEV_GRP			0x74
+#define VUSB1V8_TYPE			0x75
+#define VUSB1V8_REMAP			0x76
+#define VUSB3V1_DEV_GRP			0x77
+#define VUSB3V1_TYPE			0x78
+#define VUSB3V1_REMAP			0x79
+
+/* In module TWL4030_MODULE_INTBR */
+#define PMBR1				0x0D
+#define GPIO_USB_4PIN_ULPI_2430C	(3 << 0)
+
+struct twl4030_usb {
+	struct usb_phy		phy;
+	struct device		*dev;
+
+	/* TWL4030 internal USB regulator supplies */
+	struct regulator	*usb1v5;
+	struct regulator	*usb1v8;
+	struct regulator	*usb3v1;
+
+	/* for vbus reporting with irqs disabled */
+	spinlock_t		lock;
+
+	/* pin configuration */
+	enum twl4030_usb_mode	usb_mode;
+
+	int			irq;
+	enum omap_musb_vbus_id_status linkstat;
+	bool			vbus_supplied;
+	u8			asleep;
+	bool			irq_enabled;
+
+	struct delayed_work	id_workaround_work;
+};
+
+/* internal define on top of container_of */
+#define phy_to_twl(x)		container_of((x), struct twl4030_usb, phy)
+
+/*-------------------------------------------------------------------------*/
+
+static int twl4030_i2c_write_u8_verify(struct twl4030_usb *twl,
+		u8 module, u8 data, u8 address)
+{
+	u8 check;
+
+	if ((twl_i2c_write_u8(module, data, address) >= 0) &&
+	    (twl_i2c_read_u8(module, &check, address) >= 0) &&
+						(check == data))
+		return 0;
+	dev_dbg(twl->dev, "Write%d[%d,0x%x] wrote %02x but read %02x\n",
+			1, module, address, check, data);
+
+	/* Failed once: Try again */
+	if ((twl_i2c_write_u8(module, data, address) >= 0) &&
+	    (twl_i2c_read_u8(module, &check, address) >= 0) &&
+						(check == data))
+		return 0;
+	dev_dbg(twl->dev, "Write%d[%d,0x%x] wrote %02x but read %02x\n",
+			2, module, address, check, data);
+
+	/* Failed again: Return error */
+	return -EBUSY;
+}
+
+#define twl4030_usb_write_verify(twl, address, data)	\
+	twl4030_i2c_write_u8_verify(twl, TWL_MODULE_USB, (data), (address))
+
+static inline int twl4030_usb_write(struct twl4030_usb *twl,
+		u8 address, u8 data)
+{
+	int ret = 0;
+
+	ret = twl_i2c_write_u8(TWL_MODULE_USB, data, address);
+	if (ret < 0)
+		dev_dbg(twl->dev,
+			"TWL4030:USB:Write[0x%x] Error %d\n", address, ret);
+	return ret;
+}
+
+static inline int twl4030_readb(struct twl4030_usb *twl, u8 module, u8 address)
+{
+	u8 data;
+	int ret = 0;
+
+	ret = twl_i2c_read_u8(module, &data, address);
+	if (ret >= 0)
+		ret = data;
+	else
+		dev_dbg(twl->dev,
+			"TWL4030:readb[0x%x,0x%x] Error %d\n",
+					module, address, ret);
+
+	return ret;
+}
+
+static inline int twl4030_usb_read(struct twl4030_usb *twl, u8 address)
+{
+	return twl4030_readb(twl, TWL_MODULE_USB, address);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static inline int
+twl4030_usb_set_bits(struct twl4030_usb *twl, u8 reg, u8 bits)
+{
+	return twl4030_usb_write(twl, ULPI_SET(reg), bits);
+}
+
+static inline int
+twl4030_usb_clear_bits(struct twl4030_usb *twl, u8 reg, u8 bits)
+{
+	return twl4030_usb_write(twl, ULPI_CLR(reg), bits);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static bool twl4030_is_driving_vbus(struct twl4030_usb *twl)
+{
+	int ret;
+
+	ret = twl4030_usb_read(twl, PHY_CLK_CTRL_STS);
+	if (ret < 0 || !(ret & PHY_DPLL_CLK))
+		/*
+		 * if clocks are off, registers are not updated,
+		 * but we can assume we don't drive VBUS in this case
+		 */
+		return false;
+
+	ret = twl4030_usb_read(twl, ULPI_OTG_CTRL);
+	if (ret < 0)
+		return false;
+
+	return (ret & (ULPI_OTG_DRVVBUS | ULPI_OTG_CHRGVBUS)) ? true : false;
+}
+
+static enum omap_musb_vbus_id_status
+	twl4030_usb_linkstat(struct twl4030_usb *twl)
+{
+	int	status;
+	enum omap_musb_vbus_id_status linkstat = OMAP_MUSB_UNKNOWN;
+
+	twl->vbus_supplied = false;
+
+	/*
+	 * For ID/VBUS sensing, see manual section 15.4.8 ...
+	 * except when using only battery backup power, two
+	 * comparators produce VBUS_PRES and ID_PRES signals,
+	 * which don't match docs elsewhere.  But ... BIT(7)
+	 * and BIT(2) of STS_HW_CONDITIONS, respectively, do
+	 * seem to match up.  If either is true the USB_PRES
+	 * signal is active, the OTG module is activated, and
+	 * its interrupt may be raised (may wake the system).
+	 */
+	status = twl4030_readb(twl, TWL_MODULE_PM_MASTER, STS_HW_CONDITIONS);
+	if (status < 0)
+		dev_err(twl->dev, "USB link status err %d\n", status);
+	else if (status & (BIT(7) | BIT(2))) {
+		if (status & BIT(7)) {
+			if (twl4030_is_driving_vbus(twl))
+				status &= ~BIT(7);
+			else
+				twl->vbus_supplied = true;
+		}
+
+		if (status & BIT(2))
+			linkstat = OMAP_MUSB_ID_GROUND;
+		else if (status & BIT(7))
+			linkstat = OMAP_MUSB_VBUS_VALID;
+		else
+			linkstat = OMAP_MUSB_VBUS_OFF;
+	} else {
+		if (twl->linkstat != OMAP_MUSB_UNKNOWN)
+			linkstat = OMAP_MUSB_VBUS_OFF;
+	}
+
+	dev_dbg(twl->dev, "HW_CONDITIONS 0x%02x/%d; link %d\n",
+			status, status, linkstat);
+
+	/* REVISIT this assumes host and peripheral controllers
+	 * are registered, and that both are active...
+	 */
+
+	return linkstat;
+}
+
+static void twl4030_usb_set_mode(struct twl4030_usb *twl, int mode)
+{
+	twl->usb_mode = mode;
+
+	switch (mode) {
+	case T2_USB_MODE_ULPI:
+		twl4030_usb_clear_bits(twl, ULPI_IFC_CTRL,
+					ULPI_IFC_CTRL_CARKITMODE);
+		twl4030_usb_set_bits(twl, POWER_CTRL, POWER_CTRL_OTG_ENAB);
+		twl4030_usb_clear_bits(twl, ULPI_FUNC_CTRL,
+					ULPI_FUNC_CTRL_XCVRSEL_MASK |
+					ULPI_FUNC_CTRL_OPMODE_MASK);
+		break;
+	case -1:
+		/* FIXME: power on defaults */
+		break;
+	default:
+		dev_err(twl->dev, "unsupported T2 transceiver mode %d\n",
+				mode);
+		break;
+	};
+}
+
+static void twl4030_i2c_access(struct twl4030_usb *twl, int on)
+{
+	unsigned long timeout;
+	int val = twl4030_usb_read(twl, PHY_CLK_CTRL);
+
+	if (val >= 0) {
+		if (on) {
+			/* enable DPLL to access PHY registers over I2C */
+			val |= REQ_PHY_DPLL_CLK;
+			WARN_ON(twl4030_usb_write_verify(twl, PHY_CLK_CTRL,
+						(u8)val) < 0);
+
+			timeout = jiffies + HZ;
+			while (!(twl4030_usb_read(twl, PHY_CLK_CTRL_STS) &
+							PHY_DPLL_CLK)
+				&& time_before(jiffies, timeout))
+					udelay(10);
+			if (!(twl4030_usb_read(twl, PHY_CLK_CTRL_STS) &
+							PHY_DPLL_CLK))
+				dev_err(twl->dev, "Timeout setting T2 HSUSB "
+						"PHY DPLL clock\n");
+		} else {
+			/* let ULPI control the DPLL clock */
+			val &= ~REQ_PHY_DPLL_CLK;
+			WARN_ON(twl4030_usb_write_verify(twl, PHY_CLK_CTRL,
+						(u8)val) < 0);
+		}
+	}
+}
+
+static void __twl4030_phy_power(struct twl4030_usb *twl, int on)
+{
+	u8 pwr = twl4030_usb_read(twl, PHY_PWR_CTRL);
+
+	if (on)
+		pwr &= ~PHY_PWR_PHYPWD;
+	else
+		pwr |= PHY_PWR_PHYPWD;
+
+	WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) < 0);
+}
+
+static void twl4030_phy_power(struct twl4030_usb *twl, int on)
+{
+	int ret;
+
+	if (on) {
+		ret = regulator_enable(twl->usb3v1);
+		if (ret)
+			dev_err(twl->dev, "Failed to enable usb3v1\n");
+
+		ret = regulator_enable(twl->usb1v8);
+		if (ret)
+			dev_err(twl->dev, "Failed to enable usb1v8\n");
+
+		/*
+		 * Disabling usb3v1 regulator (= writing 0 to VUSB3V1_DEV_GRP
+		 * in twl4030) resets the VUSB_DEDICATED2 register. This reset
+		 * enables VUSB3V1_SLEEP bit that remaps usb3v1 ACTIVE state to
+		 * SLEEP. We work around this by clearing the bit after usv3v1
+		 * is re-activated. This ensures that VUSB3V1 is really active.
+		 */
+		twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2);
+
+		ret = regulator_enable(twl->usb1v5);
+		if (ret)
+			dev_err(twl->dev, "Failed to enable usb1v5\n");
+
+		__twl4030_phy_power(twl, 1);
+		twl4030_usb_write(twl, PHY_CLK_CTRL,
+				  twl4030_usb_read(twl, PHY_CLK_CTRL) |
+					(PHY_CLK_CTRL_CLOCKGATING_EN |
+						PHY_CLK_CTRL_CLK32K_EN));
+	} else {
+		__twl4030_phy_power(twl, 0);
+		regulator_disable(twl->usb1v5);
+		regulator_disable(twl->usb1v8);
+		regulator_disable(twl->usb3v1);
+	}
+}
+
+static void twl4030_phy_suspend(struct twl4030_usb *twl, int controller_off)
+{
+	if (twl->asleep)
+		return;
+
+	twl4030_phy_power(twl, 0);
+	twl->asleep = 1;
+	dev_dbg(twl->dev, "%s\n", __func__);
+}
+
+static void __twl4030_phy_resume(struct twl4030_usb *twl)
+{
+	twl4030_phy_power(twl, 1);
+	twl4030_i2c_access(twl, 1);
+	twl4030_usb_set_mode(twl, twl->usb_mode);
+	if (twl->usb_mode == T2_USB_MODE_ULPI)
+		twl4030_i2c_access(twl, 0);
+}
+
+static void twl4030_phy_resume(struct twl4030_usb *twl)
+{
+	if (!twl->asleep)
+		return;
+	__twl4030_phy_resume(twl);
+	twl->asleep = 0;
+	dev_dbg(twl->dev, "%s\n", __func__);
+
+	/*
+	 * XXX When VBUS gets driven after musb goes to A mode,
+	 * ID_PRES related interrupts no longer arrive, why?
+	 * Register itself is updated fine though, so we must poll.
+	 */
+	if (twl->linkstat == OMAP_MUSB_ID_GROUND) {
+		cancel_delayed_work(&twl->id_workaround_work);
+		schedule_delayed_work(&twl->id_workaround_work, HZ);
+	}
+}
+
+static int twl4030_usb_ldo_init(struct twl4030_usb *twl)
+{
+	/* Enable writing to power configuration registers */
+	twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG1,
+			 TWL4030_PM_MASTER_PROTECT_KEY);
+
+	twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG2,
+			 TWL4030_PM_MASTER_PROTECT_KEY);
+
+	/* Keep VUSB3V1 LDO in sleep state until VBUS/ID change detected*/
+	/*twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2);*/
+
+	/* input to VUSB3V1 LDO is from VBAT, not VBUS */
+	twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0x14, VUSB_DEDICATED1);
+
+	/* Initialize 3.1V regulator */
+	twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB3V1_DEV_GRP);
+
+	twl->usb3v1 = devm_regulator_get(twl->dev, "usb3v1");
+	if (IS_ERR(twl->usb3v1))
+		return -ENODEV;
+
+	twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB3V1_TYPE);
+
+	/* Initialize 1.5V regulator */
+	twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB1V5_DEV_GRP);
+
+	twl->usb1v5 = devm_regulator_get(twl->dev, "usb1v5");
+	if (IS_ERR(twl->usb1v5))
+		return -ENODEV;
+
+	twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB1V5_TYPE);
+
+	/* Initialize 1.8V regulator */
+	twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB1V8_DEV_GRP);
+
+	twl->usb1v8 = devm_regulator_get(twl->dev, "usb1v8");
+	if (IS_ERR(twl->usb1v8))
+		return -ENODEV;
+
+	twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB1V8_TYPE);
+
+	/* disable access to power configuration registers */
+	twl_i2c_write_u8(TWL_MODULE_PM_MASTER, 0,
+			 TWL4030_PM_MASTER_PROTECT_KEY);
+
+	return 0;
+}
+
+static ssize_t twl4030_usb_vbus_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct twl4030_usb *twl = dev_get_drvdata(dev);
+	unsigned long flags;
+	int ret = -EINVAL;
+
+	spin_lock_irqsave(&twl->lock, flags);
+	ret = sprintf(buf, "%s\n",
+			twl->vbus_supplied ? "on" : "off");
+	spin_unlock_irqrestore(&twl->lock, flags);
+
+	return ret;
+}
+static DEVICE_ATTR(vbus, 0444, twl4030_usb_vbus_show, NULL);
+
+static irqreturn_t twl4030_usb_irq(int irq, void *_twl)
+{
+	struct twl4030_usb *twl = _twl;
+	enum omap_musb_vbus_id_status status;
+	bool status_changed = false;
+
+	status = twl4030_usb_linkstat(twl);
+
+	spin_lock_irq(&twl->lock);
+	if (status >= 0 && status != twl->linkstat) {
+		twl->linkstat = status;
+		status_changed = true;
+	}
+	spin_unlock_irq(&twl->lock);
+
+	if (status_changed) {
+		/* FIXME add a set_power() method so that B-devices can
+		 * configure the charger appropriately.  It's not always
+		 * correct to consume VBUS power, and how much current to
+		 * consume is a function of the USB configuration chosen
+		 * by the host.
+		 *
+		 * REVISIT usb_gadget_vbus_connect(...) as needed, ditto
+		 * its disconnect() sibling, when changing to/from the
+		 * USB_LINK_VBUS state.  musb_hdrc won't care until it
+		 * starts to handle softconnect right.
+		 */
+		omap_musb_mailbox(status);
+	}
+	sysfs_notify(&twl->dev->kobj, NULL, "vbus");
+
+	return IRQ_HANDLED;
+}
+
+static void twl4030_id_workaround_work(struct work_struct *work)
+{
+	struct twl4030_usb *twl = container_of(work, struct twl4030_usb,
+		id_workaround_work.work);
+	enum omap_musb_vbus_id_status status;
+	bool status_changed = false;
+
+	status = twl4030_usb_linkstat(twl);
+
+	spin_lock_irq(&twl->lock);
+	if (status >= 0 && status != twl->linkstat) {
+		twl->linkstat = status;
+		status_changed = true;
+	}
+	spin_unlock_irq(&twl->lock);
+
+	if (status_changed) {
+		dev_dbg(twl->dev, "handle missing status change to %d\n",
+				status);
+		omap_musb_mailbox(status);
+	}
+
+	/* don't schedule during sleep - irq works right then */
+	if (status == OMAP_MUSB_ID_GROUND && !twl->asleep) {
+		cancel_delayed_work(&twl->id_workaround_work);
+		schedule_delayed_work(&twl->id_workaround_work, HZ);
+	}
+}
+
+static int twl4030_usb_phy_init(struct usb_phy *phy)
+{
+	struct twl4030_usb *twl = phy_to_twl(phy);
+	enum omap_musb_vbus_id_status status;
+
+	/*
+	 * Start in sleep state, we'll get called through set_suspend()
+	 * callback when musb is runtime resumed and it's time to start.
+	 */
+	__twl4030_phy_power(twl, 0);
+	twl->asleep = 1;
+
+	status = twl4030_usb_linkstat(twl);
+	twl->linkstat = status;
+
+	if (status == OMAP_MUSB_ID_GROUND || status == OMAP_MUSB_VBUS_VALID)
+		omap_musb_mailbox(twl->linkstat);
+
+	sysfs_notify(&twl->dev->kobj, NULL, "vbus");
+	return 0;
+}
+
+static int twl4030_set_suspend(struct usb_phy *x, int suspend)
+{
+	struct twl4030_usb *twl = phy_to_twl(x);
+
+	if (suspend)
+		twl4030_phy_suspend(twl, 1);
+	else
+		twl4030_phy_resume(twl);
+
+	return 0;
+}
+
+static int twl4030_set_peripheral(struct usb_otg *otg,
+					struct usb_gadget *gadget)
+{
+	if (!otg)
+		return -ENODEV;
+
+	otg->gadget = gadget;
+	if (!gadget)
+		otg->phy->state = OTG_STATE_UNDEFINED;
+
+	return 0;
+}
+
+static int twl4030_set_host(struct usb_otg *otg, struct usb_bus *host)
+{
+	if (!otg)
+		return -ENODEV;
+
+	otg->host = host;
+	if (!host)
+		otg->phy->state = OTG_STATE_UNDEFINED;
+
+	return 0;
+}
+
+static int twl4030_usb_probe(struct platform_device *pdev)
+{
+	struct twl4030_usb_data *pdata = pdev->dev.platform_data;
+	struct twl4030_usb	*twl;
+	int			status, err;
+	struct usb_otg		*otg;
+	struct device_node	*np = pdev->dev.of_node;
+
+	twl = devm_kzalloc(&pdev->dev, sizeof *twl, GFP_KERNEL);
+	if (!twl)
+		return -ENOMEM;
+
+	if (np)
+		of_property_read_u32(np, "usb_mode",
+				(enum twl4030_usb_mode *)&twl->usb_mode);
+	else if (pdata)
+		twl->usb_mode = pdata->usb_mode;
+	else {
+		dev_err(&pdev->dev, "twl4030 initialized without pdata\n");
+		return -EINVAL;
+	}
+
+	otg = devm_kzalloc(&pdev->dev, sizeof *otg, GFP_KERNEL);
+	if (!otg)
+		return -ENOMEM;
+
+	twl->dev		= &pdev->dev;
+	twl->irq		= platform_get_irq(pdev, 0);
+	twl->vbus_supplied	= false;
+	twl->asleep		= 1;
+	twl->linkstat		= OMAP_MUSB_UNKNOWN;
+
+	twl->phy.dev		= twl->dev;
+	twl->phy.label		= "twl4030";
+	twl->phy.otg		= otg;
+	twl->phy.type		= USB_PHY_TYPE_USB2;
+	twl->phy.set_suspend	= twl4030_set_suspend;
+	twl->phy.init		= twl4030_usb_phy_init;
+
+	otg->phy		= &twl->phy;
+	otg->set_host		= twl4030_set_host;
+	otg->set_peripheral	= twl4030_set_peripheral;
+
+	/* init spinlock for workqueue */
+	spin_lock_init(&twl->lock);
+
+	INIT_DELAYED_WORK(&twl->id_workaround_work, twl4030_id_workaround_work);
+
+	err = twl4030_usb_ldo_init(twl);
+	if (err) {
+		dev_err(&pdev->dev, "ldo init failed\n");
+		return err;
+	}
+	usb_add_phy_dev(&twl->phy);
+
+	platform_set_drvdata(pdev, twl);
+	if (device_create_file(&pdev->dev, &dev_attr_vbus))
+		dev_warn(&pdev->dev, "could not create sysfs file\n");
+
+	/* Our job is to use irqs and status from the power module
+	 * to keep the transceiver disabled when nothing's connected.
+	 *
+	 * FIXME we actually shouldn't start enabling it until the
+	 * USB controller drivers have said they're ready, by calling
+	 * set_host() and/or set_peripheral() ... OTG_capable boards
+	 * need both handles, otherwise just one suffices.
+	 */
+	twl->irq_enabled = true;
+	status = devm_request_threaded_irq(twl->dev, twl->irq, NULL,
+			twl4030_usb_irq, IRQF_TRIGGER_FALLING |
+			IRQF_TRIGGER_RISING | IRQF_ONESHOT, "twl4030_usb", twl);
+	if (status < 0) {
+		dev_dbg(&pdev->dev, "can't get IRQ %d, err %d\n",
+			twl->irq, status);
+		return status;
+	}
+
+	dev_info(&pdev->dev, "Initialized TWL4030 USB module\n");
+	return 0;
+}
+
+static int twl4030_usb_remove(struct platform_device *pdev)
+{
+	struct twl4030_usb *twl = platform_get_drvdata(pdev);
+	int val;
+
+	cancel_delayed_work(&twl->id_workaround_work);
+	device_remove_file(twl->dev, &dev_attr_vbus);
+
+	/* set transceiver mode to power on defaults */
+	twl4030_usb_set_mode(twl, -1);
+
+	/* autogate 60MHz ULPI clock,
+	 * clear dpll clock request for i2c access,
+	 * disable 32KHz
+	 */
+	val = twl4030_usb_read(twl, PHY_CLK_CTRL);
+	if (val >= 0) {
+		val |= PHY_CLK_CTRL_CLOCKGATING_EN;
+		val &= ~(PHY_CLK_CTRL_CLK32K_EN | REQ_PHY_DPLL_CLK);
+		twl4030_usb_write(twl, PHY_CLK_CTRL, (u8)val);
+	}
+
+	/* disable complete OTG block */
+	twl4030_usb_clear_bits(twl, POWER_CTRL, POWER_CTRL_OTG_ENAB);
+
+	if (!twl->asleep)
+		twl4030_phy_power(twl, 0);
+
+	return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id twl4030_usb_id_table[] = {
+	{ .compatible = "ti,twl4030-usb" },
+	{}
+};
+MODULE_DEVICE_TABLE(of, twl4030_usb_id_table);
+#endif
+
+static struct platform_driver twl4030_usb_driver = {
+	.probe		= twl4030_usb_probe,
+	.remove		= twl4030_usb_remove,
+	.driver		= {
+		.name	= "twl4030_usb",
+		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(twl4030_usb_id_table),
+	},
+};
+
+static int __init twl4030_usb_init(void)
+{
+	return platform_driver_register(&twl4030_usb_driver);
+}
+subsys_initcall(twl4030_usb_init);
+
+static void __exit twl4030_usb_exit(void)
+{
+	platform_driver_unregister(&twl4030_usb_driver);
+}
+module_exit(twl4030_usb_exit);
+
+MODULE_ALIAS("platform:twl4030_usb");
+MODULE_AUTHOR("Texas Instruments, Inc, Nokia Corporation");
+MODULE_DESCRIPTION("TWL4030 USB transceiver driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/phy/phy-twl6030-usb.c b/drivers/usb/phy/phy-twl6030-usb.c
new file mode 100644
index 0000000..9de7ada
--- /dev/null
+++ b/drivers/usb/phy/phy-twl6030-usb.c
@@ -0,0 +1,453 @@
+/*
+ * twl6030_usb - TWL6030 USB transceiver, talking to OMAP OTG driver.
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.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.
+ *
+ * Author: Hema HK <hemahk@ti.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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/usb/musb-omap.h>
+#include <linux/usb/phy_companion.h>
+#include <linux/usb/omap_usb.h>
+#include <linux/i2c/twl.h>
+#include <linux/regulator/consumer.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+
+/* usb register definitions */
+#define USB_VENDOR_ID_LSB		0x00
+#define USB_VENDOR_ID_MSB		0x01
+#define USB_PRODUCT_ID_LSB		0x02
+#define USB_PRODUCT_ID_MSB		0x03
+#define USB_VBUS_CTRL_SET		0x04
+#define USB_VBUS_CTRL_CLR		0x05
+#define USB_ID_CTRL_SET			0x06
+#define USB_ID_CTRL_CLR			0x07
+#define USB_VBUS_INT_SRC		0x08
+#define USB_VBUS_INT_LATCH_SET		0x09
+#define USB_VBUS_INT_LATCH_CLR		0x0A
+#define USB_VBUS_INT_EN_LO_SET		0x0B
+#define USB_VBUS_INT_EN_LO_CLR		0x0C
+#define USB_VBUS_INT_EN_HI_SET		0x0D
+#define USB_VBUS_INT_EN_HI_CLR		0x0E
+#define USB_ID_INT_SRC			0x0F
+#define USB_ID_INT_LATCH_SET		0x10
+#define USB_ID_INT_LATCH_CLR		0x11
+
+#define USB_ID_INT_EN_LO_SET		0x12
+#define USB_ID_INT_EN_LO_CLR		0x13
+#define USB_ID_INT_EN_HI_SET		0x14
+#define USB_ID_INT_EN_HI_CLR		0x15
+#define USB_OTG_ADP_CTRL		0x16
+#define USB_OTG_ADP_HIGH		0x17
+#define USB_OTG_ADP_LOW			0x18
+#define USB_OTG_ADP_RISE		0x19
+#define USB_OTG_REVISION		0x1A
+
+/* to be moved to LDO */
+#define TWL6030_MISC2			0xE5
+#define TWL6030_CFG_LDO_PD2		0xF5
+#define TWL6030_BACKUP_REG		0xFA
+
+#define STS_HW_CONDITIONS		0x21
+
+/* In module TWL6030_MODULE_PM_MASTER */
+#define STS_HW_CONDITIONS		0x21
+#define STS_USB_ID			BIT(2)
+
+/* In module TWL6030_MODULE_PM_RECEIVER */
+#define VUSB_CFG_TRANS			0x71
+#define VUSB_CFG_STATE			0x72
+#define VUSB_CFG_VOLTAGE		0x73
+
+/* in module TWL6030_MODULE_MAIN_CHARGE */
+
+#define CHARGERUSB_CTRL1		0x8
+
+#define CONTROLLER_STAT1		0x03
+#define	VBUS_DET			BIT(2)
+
+struct twl6030_usb {
+	struct phy_companion	comparator;
+	struct device		*dev;
+
+	/* for vbus reporting with irqs disabled */
+	spinlock_t		lock;
+
+	struct regulator		*usb3v3;
+
+	/* used to set vbus, in atomic path */
+	struct work_struct	set_vbus_work;
+
+	int			irq1;
+	int			irq2;
+	enum omap_musb_vbus_id_status linkstat;
+	u8			asleep;
+	bool			irq_enabled;
+	bool			vbus_enable;
+	const char		*regulator;
+};
+
+#define	comparator_to_twl(x) container_of((x), struct twl6030_usb, comparator)
+
+/*-------------------------------------------------------------------------*/
+
+static inline int twl6030_writeb(struct twl6030_usb *twl, u8 module,
+						u8 data, u8 address)
+{
+	int ret = 0;
+
+	ret = twl_i2c_write_u8(module, data, address);
+	if (ret < 0)
+		dev_err(twl->dev,
+			"Write[0x%x] Error %d\n", address, ret);
+	return ret;
+}
+
+static inline u8 twl6030_readb(struct twl6030_usb *twl, u8 module, u8 address)
+{
+	u8 data, ret = 0;
+
+	ret = twl_i2c_read_u8(module, &data, address);
+	if (ret >= 0)
+		ret = data;
+	else
+		dev_err(twl->dev,
+			"readb[0x%x,0x%x] Error %d\n",
+					module, address, ret);
+	return ret;
+}
+
+static int twl6030_start_srp(struct phy_companion *comparator)
+{
+	struct twl6030_usb *twl = comparator_to_twl(comparator);
+
+	twl6030_writeb(twl, TWL_MODULE_USB, 0x24, USB_VBUS_CTRL_SET);
+	twl6030_writeb(twl, TWL_MODULE_USB, 0x84, USB_VBUS_CTRL_SET);
+
+	mdelay(100);
+	twl6030_writeb(twl, TWL_MODULE_USB, 0xa0, USB_VBUS_CTRL_CLR);
+
+	return 0;
+}
+
+static int twl6030_usb_ldo_init(struct twl6030_usb *twl)
+{
+	/* Set to OTG_REV 1.3 and turn on the ID_WAKEUP_COMP */
+	twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x1, TWL6030_BACKUP_REG);
+
+	/* Program CFG_LDO_PD2 register and set VUSB bit */
+	twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x1, TWL6030_CFG_LDO_PD2);
+
+	/* Program MISC2 register and set bit VUSB_IN_VBAT */
+	twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x10, TWL6030_MISC2);
+
+	twl->usb3v3 = regulator_get(twl->dev, twl->regulator);
+	if (IS_ERR(twl->usb3v3))
+		return -ENODEV;
+
+	/* Program the USB_VBUS_CTRL_SET and set VBUS_ACT_COMP bit */
+	twl6030_writeb(twl, TWL_MODULE_USB, 0x4, USB_VBUS_CTRL_SET);
+
+	/*
+	 * Program the USB_ID_CTRL_SET register to enable GND drive
+	 * and the ID comparators
+	 */
+	twl6030_writeb(twl, TWL_MODULE_USB, 0x14, USB_ID_CTRL_SET);
+
+	return 0;
+}
+
+static ssize_t twl6030_usb_vbus_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	struct twl6030_usb *twl = dev_get_drvdata(dev);
+	unsigned long flags;
+	int ret = -EINVAL;
+
+	spin_lock_irqsave(&twl->lock, flags);
+
+	switch (twl->linkstat) {
+	case OMAP_MUSB_VBUS_VALID:
+	       ret = snprintf(buf, PAGE_SIZE, "vbus\n");
+	       break;
+	case OMAP_MUSB_ID_GROUND:
+	       ret = snprintf(buf, PAGE_SIZE, "id\n");
+	       break;
+	case OMAP_MUSB_VBUS_OFF:
+	       ret = snprintf(buf, PAGE_SIZE, "none\n");
+	       break;
+	default:
+	       ret = snprintf(buf, PAGE_SIZE, "UNKNOWN\n");
+	}
+	spin_unlock_irqrestore(&twl->lock, flags);
+
+	return ret;
+}
+static DEVICE_ATTR(vbus, 0444, twl6030_usb_vbus_show, NULL);
+
+static irqreturn_t twl6030_usb_irq(int irq, void *_twl)
+{
+	struct twl6030_usb *twl = _twl;
+	enum omap_musb_vbus_id_status status = OMAP_MUSB_UNKNOWN;
+	u8 vbus_state, hw_state;
+	int ret;
+
+	hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS);
+
+	vbus_state = twl6030_readb(twl, TWL_MODULE_MAIN_CHARGE,
+						CONTROLLER_STAT1);
+	if (!(hw_state & STS_USB_ID)) {
+		if (vbus_state & VBUS_DET) {
+			ret = regulator_enable(twl->usb3v3);
+			if (ret)
+				dev_err(twl->dev, "Failed to enable usb3v3\n");
+
+			twl->asleep = 1;
+			status = OMAP_MUSB_VBUS_VALID;
+			twl->linkstat = status;
+			omap_musb_mailbox(status);
+		} else {
+			if (twl->linkstat != OMAP_MUSB_UNKNOWN) {
+				status = OMAP_MUSB_VBUS_OFF;
+				twl->linkstat = status;
+				omap_musb_mailbox(status);
+				if (twl->asleep) {
+					regulator_disable(twl->usb3v3);
+					twl->asleep = 0;
+				}
+			}
+		}
+	}
+	sysfs_notify(&twl->dev->kobj, NULL, "vbus");
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl)
+{
+	struct twl6030_usb *twl = _twl;
+	enum omap_musb_vbus_id_status status = OMAP_MUSB_UNKNOWN;
+	u8 hw_state;
+	int ret;
+
+	hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS);
+
+	if (hw_state & STS_USB_ID) {
+		ret = regulator_enable(twl->usb3v3);
+		if (ret)
+			dev_err(twl->dev, "Failed to enable usb3v3\n");
+
+		twl->asleep = 1;
+		twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_CLR);
+		twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_SET);
+		status = OMAP_MUSB_ID_GROUND;
+		twl->linkstat = status;
+		omap_musb_mailbox(status);
+	} else  {
+		twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_CLR);
+		twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_SET);
+	}
+	twl6030_writeb(twl, TWL_MODULE_USB, status, USB_ID_INT_LATCH_CLR);
+
+	return IRQ_HANDLED;
+}
+
+static int twl6030_enable_irq(struct twl6030_usb *twl)
+{
+	twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_SET);
+	twl6030_interrupt_unmask(0x05, REG_INT_MSK_LINE_C);
+	twl6030_interrupt_unmask(0x05, REG_INT_MSK_STS_C);
+
+	twl6030_interrupt_unmask(TWL6030_CHARGER_CTRL_INT_MASK,
+				REG_INT_MSK_LINE_C);
+	twl6030_interrupt_unmask(TWL6030_CHARGER_CTRL_INT_MASK,
+				REG_INT_MSK_STS_C);
+	twl6030_usb_irq(twl->irq2, twl);
+	twl6030_usbotg_irq(twl->irq1, twl);
+
+	return 0;
+}
+
+static void otg_set_vbus_work(struct work_struct *data)
+{
+	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 (twl->vbus_enable)
+		twl6030_writeb(twl, TWL_MODULE_MAIN_CHARGE , 0x40,
+							CHARGERUSB_CTRL1);
+	else
+		twl6030_writeb(twl, TWL_MODULE_MAIN_CHARGE , 0x00,
+							CHARGERUSB_CTRL1);
+}
+
+static int twl6030_set_vbus(struct phy_companion *comparator, bool enabled)
+{
+	struct twl6030_usb *twl = comparator_to_twl(comparator);
+
+	twl->vbus_enable = enabled;
+	schedule_work(&twl->set_vbus_work);
+
+	return 0;
+}
+
+static int twl6030_usb_probe(struct platform_device *pdev)
+{
+	u32 ret;
+	struct twl6030_usb	*twl;
+	int			status, err;
+	struct device_node	*np = pdev->dev.of_node;
+	struct device		*dev = &pdev->dev;
+	struct twl4030_usb_data	*pdata = dev->platform_data;
+
+	twl = devm_kzalloc(dev, sizeof *twl, GFP_KERNEL);
+	if (!twl)
+		return -ENOMEM;
+
+	twl->dev		= &pdev->dev;
+	twl->irq1		= platform_get_irq(pdev, 0);
+	twl->irq2		= platform_get_irq(pdev, 1);
+	twl->linkstat		= OMAP_MUSB_UNKNOWN;
+
+	twl->comparator.set_vbus	= twl6030_set_vbus;
+	twl->comparator.start_srp	= twl6030_start_srp;
+
+	ret = omap_usb2_set_comparator(&twl->comparator);
+	if (ret == -ENODEV) {
+		dev_info(&pdev->dev, "phy not ready, deferring probe");
+		return -EPROBE_DEFER;
+	}
+
+	if (np) {
+		twl->regulator = "usb";
+	} else if (pdata) {
+		if (pdata->features & TWL6025_SUBCLASS)
+			twl->regulator = "ldousb";
+		else
+			twl->regulator = "vusb";
+	} else {
+		dev_err(&pdev->dev, "twl6030 initialized without pdata\n");
+		return -EINVAL;
+	}
+
+	/* init spinlock for workqueue */
+	spin_lock_init(&twl->lock);
+
+	err = twl6030_usb_ldo_init(twl);
+	if (err) {
+		dev_err(&pdev->dev, "ldo init failed\n");
+		return err;
+	}
+
+	platform_set_drvdata(pdev, twl);
+	if (device_create_file(&pdev->dev, &dev_attr_vbus))
+		dev_warn(&pdev->dev, "could not create sysfs file\n");
+
+	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 | IRQF_ONESHOT,
+			"twl6030_usb", twl);
+	if (status < 0) {
+		dev_err(&pdev->dev, "can't get IRQ %d, err %d\n",
+			twl->irq1, status);
+		device_remove_file(twl->dev, &dev_attr_vbus);
+		return status;
+	}
+
+	status = request_threaded_irq(twl->irq2, NULL, twl6030_usb_irq,
+			IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+			"twl6030_usb", twl);
+	if (status < 0) {
+		dev_err(&pdev->dev, "can't get IRQ %d, err %d\n",
+			twl->irq2, status);
+		free_irq(twl->irq1, twl);
+		device_remove_file(twl->dev, &dev_attr_vbus);
+		return status;
+	}
+
+	twl->asleep = 0;
+	twl6030_enable_irq(twl);
+	dev_info(&pdev->dev, "Initialized TWL6030 USB module\n");
+
+	return 0;
+}
+
+static int twl6030_usb_remove(struct platform_device *pdev)
+{
+	struct twl6030_usb *twl = platform_get_drvdata(pdev);
+
+	twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK,
+		REG_INT_MSK_LINE_C);
+	twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK,
+			REG_INT_MSK_STS_C);
+	free_irq(twl->irq1, twl);
+	free_irq(twl->irq2, twl);
+	regulator_put(twl->usb3v3);
+	device_remove_file(twl->dev, &dev_attr_vbus);
+	cancel_work_sync(&twl->set_vbus_work);
+
+	return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id twl6030_usb_id_table[] = {
+	{ .compatible = "ti,twl6030-usb" },
+	{}
+};
+MODULE_DEVICE_TABLE(of, twl6030_usb_id_table);
+#endif
+
+static struct platform_driver twl6030_usb_driver = {
+	.probe		= twl6030_usb_probe,
+	.remove		= twl6030_usb_remove,
+	.driver		= {
+		.name	= "twl6030_usb",
+		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(twl6030_usb_id_table),
+	},
+};
+
+static int __init twl6030_usb_init(void)
+{
+	return platform_driver_register(&twl6030_usb_driver);
+}
+subsys_initcall(twl6030_usb_init);
+
+static void __exit twl6030_usb_exit(void)
+{
+	platform_driver_unregister(&twl6030_usb_driver);
+}
+module_exit(twl6030_usb_exit);
+
+MODULE_ALIAS("platform:twl6030_usb");
+MODULE_AUTHOR("Hema HK <hemahk@ti.com>");
+MODULE_DESCRIPTION("TWL6030 USB transceiver driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/phy/phy-ulpi-viewport.c b/drivers/usb/phy/phy-ulpi-viewport.c
new file mode 100644
index 0000000..c5ba7e5
--- /dev/null
+++ b/drivers/usb/phy/phy-ulpi-viewport.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2011 Google, 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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/usb.h>
+#include <linux/io.h>
+#include <linux/usb/otg.h>
+#include <linux/usb/ulpi.h>
+
+#define ULPI_VIEW_WAKEUP	(1 << 31)
+#define ULPI_VIEW_RUN		(1 << 30)
+#define ULPI_VIEW_WRITE		(1 << 29)
+#define ULPI_VIEW_READ		(0 << 29)
+#define ULPI_VIEW_ADDR(x)	(((x) & 0xff) << 16)
+#define ULPI_VIEW_DATA_READ(x)	(((x) >> 8) & 0xff)
+#define ULPI_VIEW_DATA_WRITE(x)	((x) & 0xff)
+
+static int ulpi_viewport_wait(void __iomem *view, u32 mask)
+{
+	unsigned long usec = 2000;
+
+	while (usec--) {
+		if (!(readl(view) & mask))
+			return 0;
+
+		udelay(1);
+	};
+
+	return -ETIMEDOUT;
+}
+
+static int ulpi_viewport_read(struct usb_phy *otg, u32 reg)
+{
+	int ret;
+	void __iomem *view = otg->io_priv;
+
+	writel(ULPI_VIEW_WAKEUP | ULPI_VIEW_WRITE, view);
+	ret = ulpi_viewport_wait(view, ULPI_VIEW_WAKEUP);
+	if (ret)
+		return ret;
+
+	writel(ULPI_VIEW_RUN | ULPI_VIEW_READ | ULPI_VIEW_ADDR(reg), view);
+	ret = ulpi_viewport_wait(view, ULPI_VIEW_RUN);
+	if (ret)
+		return ret;
+
+	return ULPI_VIEW_DATA_READ(readl(view));
+}
+
+static int ulpi_viewport_write(struct usb_phy *otg, u32 val, u32 reg)
+{
+	int ret;
+	void __iomem *view = otg->io_priv;
+
+	writel(ULPI_VIEW_WAKEUP | ULPI_VIEW_WRITE, view);
+	ret = ulpi_viewport_wait(view, ULPI_VIEW_WAKEUP);
+	if (ret)
+		return ret;
+
+	writel(ULPI_VIEW_RUN | ULPI_VIEW_WRITE | ULPI_VIEW_DATA_WRITE(val) |
+						 ULPI_VIEW_ADDR(reg), view);
+
+	return ulpi_viewport_wait(view, ULPI_VIEW_RUN);
+}
+
+struct usb_phy_io_ops ulpi_viewport_access_ops = {
+	.read	= ulpi_viewport_read,
+	.write	= ulpi_viewport_write,
+};
diff --git a/drivers/usb/phy/phy-ulpi.c b/drivers/usb/phy/phy-ulpi.c
new file mode 100644
index 0000000..217339d
--- /dev/null
+++ b/drivers/usb/phy/phy-ulpi.c
@@ -0,0 +1,283 @@
+/*
+ * Generic ULPI USB transceiver support
+ *
+ * Copyright (C) 2009 Daniel Mack <daniel@caiaq.de>
+ *
+ * Based on sources from
+ *
+ *   Sascha Hauer <s.hauer@pengutronix.de>
+ *   Freescale 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.
+ *
+ * You 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/export.h>
+#include <linux/usb.h>
+#include <linux/usb/otg.h>
+#include <linux/usb/ulpi.h>
+
+
+struct ulpi_info {
+	unsigned int	id;
+	char		*name;
+};
+
+#define ULPI_ID(vendor, product) (((vendor) << 16) | (product))
+#define ULPI_INFO(_id, _name)		\
+	{				\
+		.id	= (_id),	\
+		.name	= (_name),	\
+	}
+
+/* ULPI hardcoded IDs, used for probing */
+static struct ulpi_info ulpi_ids[] = {
+	ULPI_INFO(ULPI_ID(0x04cc, 0x1504), "NXP ISP1504"),
+	ULPI_INFO(ULPI_ID(0x0424, 0x0006), "SMSC USB331x"),
+};
+
+static int ulpi_set_otg_flags(struct usb_phy *phy)
+{
+	unsigned int flags = ULPI_OTG_CTRL_DP_PULLDOWN |
+			     ULPI_OTG_CTRL_DM_PULLDOWN;
+
+	if (phy->flags & ULPI_OTG_ID_PULLUP)
+		flags |= ULPI_OTG_CTRL_ID_PULLUP;
+
+	/*
+	 * ULPI Specification rev.1.1 default
+	 * for Dp/DmPulldown is enabled.
+	 */
+	if (phy->flags & ULPI_OTG_DP_PULLDOWN_DIS)
+		flags &= ~ULPI_OTG_CTRL_DP_PULLDOWN;
+
+	if (phy->flags & ULPI_OTG_DM_PULLDOWN_DIS)
+		flags &= ~ULPI_OTG_CTRL_DM_PULLDOWN;
+
+	if (phy->flags & ULPI_OTG_EXTVBUSIND)
+		flags |= ULPI_OTG_CTRL_EXTVBUSIND;
+
+	return usb_phy_io_write(phy, flags, ULPI_OTG_CTRL);
+}
+
+static int ulpi_set_fc_flags(struct usb_phy *phy)
+{
+	unsigned int flags = 0;
+
+	/*
+	 * ULPI Specification rev.1.1 default
+	 * for XcvrSelect is Full Speed.
+	 */
+	if (phy->flags & ULPI_FC_HS)
+		flags |= ULPI_FUNC_CTRL_HIGH_SPEED;
+	else if (phy->flags & ULPI_FC_LS)
+		flags |= ULPI_FUNC_CTRL_LOW_SPEED;
+	else if (phy->flags & ULPI_FC_FS4LS)
+		flags |= ULPI_FUNC_CTRL_FS4LS;
+	else
+		flags |= ULPI_FUNC_CTRL_FULL_SPEED;
+
+	if (phy->flags & ULPI_FC_TERMSEL)
+		flags |= ULPI_FUNC_CTRL_TERMSELECT;
+
+	/*
+	 * ULPI Specification rev.1.1 default
+	 * for OpMode is Normal Operation.
+	 */
+	if (phy->flags & ULPI_FC_OP_NODRV)
+		flags |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING;
+	else if (phy->flags & ULPI_FC_OP_DIS_NRZI)
+		flags |= ULPI_FUNC_CTRL_OPMODE_DISABLE_NRZI;
+	else if (phy->flags & ULPI_FC_OP_NSYNC_NEOP)
+		flags |= ULPI_FUNC_CTRL_OPMODE_NOSYNC_NOEOP;
+	else
+		flags |= ULPI_FUNC_CTRL_OPMODE_NORMAL;
+
+	/*
+	 * ULPI Specification rev.1.1 default
+	 * for SuspendM is Powered.
+	 */
+	flags |= ULPI_FUNC_CTRL_SUSPENDM;
+
+	return usb_phy_io_write(phy, flags, ULPI_FUNC_CTRL);
+}
+
+static int ulpi_set_ic_flags(struct usb_phy *phy)
+{
+	unsigned int flags = 0;
+
+	if (phy->flags & ULPI_IC_AUTORESUME)
+		flags |= ULPI_IFC_CTRL_AUTORESUME;
+
+	if (phy->flags & ULPI_IC_EXTVBUS_INDINV)
+		flags |= ULPI_IFC_CTRL_EXTERNAL_VBUS;
+
+	if (phy->flags & ULPI_IC_IND_PASSTHRU)
+		flags |= ULPI_IFC_CTRL_PASSTHRU;
+
+	if (phy->flags & ULPI_IC_PROTECT_DIS)
+		flags |= ULPI_IFC_CTRL_PROTECT_IFC_DISABLE;
+
+	return usb_phy_io_write(phy, flags, ULPI_IFC_CTRL);
+}
+
+static int ulpi_set_flags(struct usb_phy *phy)
+{
+	int ret;
+
+	ret = ulpi_set_otg_flags(phy);
+	if (ret)
+		return ret;
+
+	ret = ulpi_set_ic_flags(phy);
+	if (ret)
+		return ret;
+
+	return ulpi_set_fc_flags(phy);
+}
+
+static int ulpi_check_integrity(struct usb_phy *phy)
+{
+	int ret, i;
+	unsigned int val = 0x55;
+
+	for (i = 0; i < 2; i++) {
+		ret = usb_phy_io_write(phy, val, ULPI_SCRATCH);
+		if (ret < 0)
+			return ret;
+
+		ret = usb_phy_io_read(phy, ULPI_SCRATCH);
+		if (ret < 0)
+			return ret;
+
+		if (ret != val) {
+			pr_err("ULPI integrity check: failed!");
+			return -ENODEV;
+		}
+		val = val << 1;
+	}
+
+	pr_info("ULPI integrity check: passed.\n");
+
+	return 0;
+}
+
+static int ulpi_init(struct usb_phy *phy)
+{
+	int i, vid, pid, ret;
+	u32 ulpi_id = 0;
+
+	for (i = 0; i < 4; i++) {
+		ret = usb_phy_io_read(phy, ULPI_PRODUCT_ID_HIGH - i);
+		if (ret < 0)
+			return ret;
+		ulpi_id = (ulpi_id << 8) | ret;
+	}
+	vid = ulpi_id & 0xffff;
+	pid = ulpi_id >> 16;
+
+	pr_info("ULPI transceiver vendor/product ID 0x%04x/0x%04x\n", vid, pid);
+
+	for (i = 0; i < ARRAY_SIZE(ulpi_ids); i++) {
+		if (ulpi_ids[i].id == ULPI_ID(vid, pid)) {
+			pr_info("Found %s ULPI transceiver.\n",
+				ulpi_ids[i].name);
+			break;
+		}
+	}
+
+	ret = ulpi_check_integrity(phy);
+	if (ret)
+		return ret;
+
+	return ulpi_set_flags(phy);
+}
+
+static int ulpi_set_host(struct usb_otg *otg, struct usb_bus *host)
+{
+	struct usb_phy *phy = otg->phy;
+	unsigned int flags = usb_phy_io_read(phy, ULPI_IFC_CTRL);
+
+	if (!host) {
+		otg->host = NULL;
+		return 0;
+	}
+
+	otg->host = host;
+
+	flags &= ~(ULPI_IFC_CTRL_6_PIN_SERIAL_MODE |
+		   ULPI_IFC_CTRL_3_PIN_SERIAL_MODE |
+		   ULPI_IFC_CTRL_CARKITMODE);
+
+	if (phy->flags & ULPI_IC_6PIN_SERIAL)
+		flags |= ULPI_IFC_CTRL_6_PIN_SERIAL_MODE;
+	else if (phy->flags & ULPI_IC_3PIN_SERIAL)
+		flags |= ULPI_IFC_CTRL_3_PIN_SERIAL_MODE;
+	else if (phy->flags & ULPI_IC_CARKIT)
+		flags |= ULPI_IFC_CTRL_CARKITMODE;
+
+	return usb_phy_io_write(phy, flags, ULPI_IFC_CTRL);
+}
+
+static int ulpi_set_vbus(struct usb_otg *otg, bool on)
+{
+	struct usb_phy *phy = otg->phy;
+	unsigned int flags = usb_phy_io_read(phy, ULPI_OTG_CTRL);
+
+	flags &= ~(ULPI_OTG_CTRL_DRVVBUS | ULPI_OTG_CTRL_DRVVBUS_EXT);
+
+	if (on) {
+		if (phy->flags & ULPI_OTG_DRVVBUS)
+			flags |= ULPI_OTG_CTRL_DRVVBUS;
+
+		if (phy->flags & ULPI_OTG_DRVVBUS_EXT)
+			flags |= ULPI_OTG_CTRL_DRVVBUS_EXT;
+	}
+
+	return usb_phy_io_write(phy, flags, ULPI_OTG_CTRL);
+}
+
+struct usb_phy *
+otg_ulpi_create(struct usb_phy_io_ops *ops,
+		unsigned int flags)
+{
+	struct usb_phy *phy;
+	struct usb_otg *otg;
+
+	phy = kzalloc(sizeof(*phy), GFP_KERNEL);
+	if (!phy)
+		return NULL;
+
+	otg = kzalloc(sizeof(*otg), GFP_KERNEL);
+	if (!otg) {
+		kfree(phy);
+		return NULL;
+	}
+
+	phy->label	= "ULPI";
+	phy->flags	= flags;
+	phy->io_ops	= ops;
+	phy->otg	= otg;
+	phy->init	= ulpi_init;
+
+	otg->phy	= phy;
+	otg->set_host	= ulpi_set_host;
+	otg->set_vbus	= ulpi_set_vbus;
+
+	return phy;
+}
+EXPORT_SYMBOL_GPL(otg_ulpi_create);
+
diff --git a/drivers/usb/phy/phy.c b/drivers/usb/phy/phy.c
new file mode 100644
index 0000000..f52c006
--- /dev/null
+++ b/drivers/usb/phy/phy.c
@@ -0,0 +1,438 @@
+/*
+ * phy.c -- USB phy handling
+ *
+ * Copyright (C) 2004-2013 Texas Instruments
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#include <linux/kernel.h>
+#include <linux/export.h>
+#include <linux/err.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+
+#include <linux/usb/phy.h>
+
+static LIST_HEAD(phy_list);
+static LIST_HEAD(phy_bind_list);
+static DEFINE_SPINLOCK(phy_lock);
+
+static struct usb_phy *__usb_find_phy(struct list_head *list,
+	enum usb_phy_type type)
+{
+	struct usb_phy  *phy = NULL;
+
+	list_for_each_entry(phy, list, head) {
+		if (phy->type != type)
+			continue;
+
+		return phy;
+	}
+
+	return ERR_PTR(-ENODEV);
+}
+
+static struct usb_phy *__usb_find_phy_dev(struct device *dev,
+	struct list_head *list, u8 index)
+{
+	struct usb_phy_bind *phy_bind = NULL;
+
+	list_for_each_entry(phy_bind, list, list) {
+		if (!(strcmp(phy_bind->dev_name, dev_name(dev))) &&
+				phy_bind->index == index) {
+			if (phy_bind->phy)
+				return phy_bind->phy;
+			else
+				return ERR_PTR(-EPROBE_DEFER);
+		}
+	}
+
+	return ERR_PTR(-ENODEV);
+}
+
+static struct usb_phy *__of_usb_find_phy(struct device_node *node)
+{
+	struct usb_phy  *phy;
+
+	list_for_each_entry(phy, &phy_list, head) {
+		if (node != phy->dev->of_node)
+			continue;
+
+		return phy;
+	}
+
+	return ERR_PTR(-ENODEV);
+}
+
+static void devm_usb_phy_release(struct device *dev, void *res)
+{
+	struct usb_phy *phy = *(struct usb_phy **)res;
+
+	usb_put_phy(phy);
+}
+
+static int devm_usb_phy_match(struct device *dev, void *res, void *match_data)
+{
+	return res == match_data;
+}
+
+/**
+ * devm_usb_get_phy - find the USB PHY
+ * @dev - device that requests this phy
+ * @type - the type of the phy the controller requires
+ *
+ * Gets the phy using usb_get_phy(), and associates a device with it using
+ * devres. On driver detach, release function is invoked on the devres data,
+ * then, devres data is freed.
+ *
+ * For use by USB host and peripheral drivers.
+ */
+struct usb_phy *devm_usb_get_phy(struct device *dev, enum usb_phy_type type)
+{
+	struct usb_phy **ptr, *phy;
+
+	ptr = devres_alloc(devm_usb_phy_release, sizeof(*ptr), GFP_KERNEL);
+	if (!ptr)
+		return NULL;
+
+	phy = usb_get_phy(type);
+	if (!IS_ERR(phy)) {
+		*ptr = phy;
+		devres_add(dev, ptr);
+	} else
+		devres_free(ptr);
+
+	return phy;
+}
+EXPORT_SYMBOL_GPL(devm_usb_get_phy);
+
+/**
+ * usb_get_phy - find the USB PHY
+ * @type - the type of the phy the controller requires
+ *
+ * Returns the phy driver, after getting a refcount to it; or
+ * -ENODEV if there is no such phy.  The caller is responsible for
+ * calling usb_put_phy() to release that count.
+ *
+ * For use by USB host and peripheral drivers.
+ */
+struct usb_phy *usb_get_phy(enum usb_phy_type type)
+{
+	struct usb_phy	*phy = NULL;
+	unsigned long	flags;
+
+	spin_lock_irqsave(&phy_lock, flags);
+
+	phy = __usb_find_phy(&phy_list, type);
+	if (IS_ERR(phy) || !try_module_get(phy->dev->driver->owner)) {
+		pr_err("unable to find transceiver of type %s\n",
+			usb_phy_type_string(type));
+		goto err0;
+	}
+
+	get_device(phy->dev);
+
+err0:
+	spin_unlock_irqrestore(&phy_lock, flags);
+
+	return phy;
+}
+EXPORT_SYMBOL_GPL(usb_get_phy);
+
+ /**
+ * devm_usb_get_phy_by_phandle - find the USB PHY by phandle
+ * @dev - device that requests this phy
+ * @phandle - name of the property holding the phy phandle value
+ * @index - the index of the phy
+ *
+ * Returns the phy driver associated with the given phandle value,
+ * after getting a refcount to it, -ENODEV if there is no such phy or
+ * -EPROBE_DEFER if there is a phandle to the phy, but the device is
+ * not yet loaded. While at that, it also associates the device with
+ * the phy using devres. On driver detach, release function is invoked
+ * on the devres data, then, devres data is freed.
+ *
+ * For use by USB host and peripheral drivers.
+ */
+struct usb_phy *devm_usb_get_phy_by_phandle(struct device *dev,
+	const char *phandle, u8 index)
+{
+	struct usb_phy	*phy = ERR_PTR(-ENOMEM), **ptr;
+	unsigned long	flags;
+	struct device_node *node;
+
+	if (!dev->of_node) {
+		dev_dbg(dev, "device does not have a device node entry\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	node = of_parse_phandle(dev->of_node, phandle, index);
+	if (!node) {
+		dev_dbg(dev, "failed to get %s phandle in %s node\n", phandle,
+			dev->of_node->full_name);
+		return ERR_PTR(-ENODEV);
+	}
+
+	ptr = devres_alloc(devm_usb_phy_release, sizeof(*ptr), GFP_KERNEL);
+	if (!ptr) {
+		dev_dbg(dev, "failed to allocate memory for devres\n");
+		goto err0;
+	}
+
+	spin_lock_irqsave(&phy_lock, flags);
+
+	phy = __of_usb_find_phy(node);
+	if (IS_ERR(phy) || !try_module_get(phy->dev->driver->owner)) {
+		phy = ERR_PTR(-EPROBE_DEFER);
+		devres_free(ptr);
+		goto err1;
+	}
+
+	*ptr = phy;
+	devres_add(dev, ptr);
+
+	get_device(phy->dev);
+
+err1:
+	spin_unlock_irqrestore(&phy_lock, flags);
+
+err0:
+	of_node_put(node);
+
+	return phy;
+}
+EXPORT_SYMBOL_GPL(devm_usb_get_phy_by_phandle);
+
+/**
+ * usb_get_phy_dev - find the USB PHY
+ * @dev - device that requests this phy
+ * @index - the index of the phy
+ *
+ * Returns the phy driver, after getting a refcount to it; or
+ * -ENODEV if there is no such phy.  The caller is responsible for
+ * calling usb_put_phy() to release that count.
+ *
+ * For use by USB host and peripheral drivers.
+ */
+struct usb_phy *usb_get_phy_dev(struct device *dev, u8 index)
+{
+	struct usb_phy	*phy = NULL;
+	unsigned long	flags;
+
+	spin_lock_irqsave(&phy_lock, flags);
+
+	phy = __usb_find_phy_dev(dev, &phy_bind_list, index);
+	if (IS_ERR(phy) || !try_module_get(phy->dev->driver->owner)) {
+		pr_err("unable to find transceiver\n");
+		goto err0;
+	}
+
+	get_device(phy->dev);
+
+err0:
+	spin_unlock_irqrestore(&phy_lock, flags);
+
+	return phy;
+}
+EXPORT_SYMBOL_GPL(usb_get_phy_dev);
+
+/**
+ * devm_usb_get_phy_dev - find the USB PHY using device ptr and index
+ * @dev - device that requests this phy
+ * @index - the index of the phy
+ *
+ * Gets the phy using usb_get_phy_dev(), and associates a device with it using
+ * devres. On driver detach, release function is invoked on the devres data,
+ * then, devres data is freed.
+ *
+ * For use by USB host and peripheral drivers.
+ */
+struct usb_phy *devm_usb_get_phy_dev(struct device *dev, u8 index)
+{
+	struct usb_phy **ptr, *phy;
+
+	ptr = devres_alloc(devm_usb_phy_release, sizeof(*ptr), GFP_KERNEL);
+	if (!ptr)
+		return NULL;
+
+	phy = usb_get_phy_dev(dev, index);
+	if (!IS_ERR(phy)) {
+		*ptr = phy;
+		devres_add(dev, ptr);
+	} else
+		devres_free(ptr);
+
+	return phy;
+}
+EXPORT_SYMBOL_GPL(devm_usb_get_phy_dev);
+
+/**
+ * devm_usb_put_phy - release the USB PHY
+ * @dev - device that wants to release this phy
+ * @phy - the phy returned by devm_usb_get_phy()
+ *
+ * destroys the devres associated with this phy and invokes usb_put_phy
+ * to release the phy.
+ *
+ * For use by USB host and peripheral drivers.
+ */
+void devm_usb_put_phy(struct device *dev, struct usb_phy *phy)
+{
+	int r;
+
+	r = devres_destroy(dev, devm_usb_phy_release, devm_usb_phy_match, phy);
+	dev_WARN_ONCE(dev, r, "couldn't find PHY resource\n");
+}
+EXPORT_SYMBOL_GPL(devm_usb_put_phy);
+
+/**
+ * usb_put_phy - release the USB PHY
+ * @x: the phy returned by usb_get_phy()
+ *
+ * Releases a refcount the caller received from usb_get_phy().
+ *
+ * For use by USB host and peripheral drivers.
+ */
+void usb_put_phy(struct usb_phy *x)
+{
+	if (x) {
+		struct module *owner = x->dev->driver->owner;
+
+		put_device(x->dev);
+		module_put(owner);
+	}
+}
+EXPORT_SYMBOL_GPL(usb_put_phy);
+
+/**
+ * usb_add_phy - declare the USB PHY
+ * @x: the USB phy to be used; or NULL
+ * @type - the type of this PHY
+ *
+ * This call is exclusively for use by phy drivers, which
+ * coordinate the activities of drivers for host and peripheral
+ * controllers, and in some cases for VBUS current regulation.
+ */
+int usb_add_phy(struct usb_phy *x, enum usb_phy_type type)
+{
+	int		ret = 0;
+	unsigned long	flags;
+	struct usb_phy	*phy;
+
+	if (x->type != USB_PHY_TYPE_UNDEFINED) {
+		dev_err(x->dev, "not accepting initialized PHY %s\n", x->label);
+		return -EINVAL;
+	}
+
+	spin_lock_irqsave(&phy_lock, flags);
+
+	list_for_each_entry(phy, &phy_list, head) {
+		if (phy->type == type) {
+			ret = -EBUSY;
+			dev_err(x->dev, "transceiver type %s already exists\n",
+						usb_phy_type_string(type));
+			goto out;
+		}
+	}
+
+	x->type = type;
+	list_add_tail(&x->head, &phy_list);
+
+out:
+	spin_unlock_irqrestore(&phy_lock, flags);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(usb_add_phy);
+
+/**
+ * usb_add_phy_dev - declare the USB PHY
+ * @x: the USB phy to be used; or NULL
+ *
+ * This call is exclusively for use by phy drivers, which
+ * coordinate the activities of drivers for host and peripheral
+ * controllers, and in some cases for VBUS current regulation.
+ */
+int usb_add_phy_dev(struct usb_phy *x)
+{
+	struct usb_phy_bind *phy_bind;
+	unsigned long flags;
+
+	if (!x->dev) {
+		dev_err(x->dev, "no device provided for PHY\n");
+		return -EINVAL;
+	}
+
+	spin_lock_irqsave(&phy_lock, flags);
+	list_for_each_entry(phy_bind, &phy_bind_list, list)
+		if (!(strcmp(phy_bind->phy_dev_name, dev_name(x->dev))))
+			phy_bind->phy = x;
+
+	list_add_tail(&x->head, &phy_list);
+
+	spin_unlock_irqrestore(&phy_lock, flags);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(usb_add_phy_dev);
+
+/**
+ * usb_remove_phy - remove the OTG PHY
+ * @x: the USB OTG PHY to be removed;
+ *
+ * This reverts the effects of usb_add_phy
+ */
+void usb_remove_phy(struct usb_phy *x)
+{
+	unsigned long	flags;
+	struct usb_phy_bind *phy_bind;
+
+	spin_lock_irqsave(&phy_lock, flags);
+	if (x) {
+		list_for_each_entry(phy_bind, &phy_bind_list, list)
+			if (phy_bind->phy == x)
+				phy_bind->phy = NULL;
+		list_del(&x->head);
+	}
+	spin_unlock_irqrestore(&phy_lock, flags);
+}
+EXPORT_SYMBOL_GPL(usb_remove_phy);
+
+/**
+ * usb_bind_phy - bind the phy and the controller that uses the phy
+ * @dev_name: the device name of the device that will bind to the phy
+ * @index: index to specify the port number
+ * @phy_dev_name: the device name of the phy
+ *
+ * Fills the phy_bind structure with the dev_name and phy_dev_name. This will
+ * be used when the phy driver registers the phy and when the controller
+ * requests this phy.
+ *
+ * To be used by platform specific initialization code.
+ */
+int __init usb_bind_phy(const char *dev_name, u8 index,
+				const char *phy_dev_name)
+{
+	struct usb_phy_bind *phy_bind;
+	unsigned long flags;
+
+	phy_bind = kzalloc(sizeof(*phy_bind), GFP_KERNEL);
+	if (!phy_bind) {
+		pr_err("phy_bind(): No memory for phy_bind");
+		return -ENOMEM;
+	}
+
+	phy_bind->dev_name = dev_name;
+	phy_bind->phy_dev_name = phy_dev_name;
+	phy_bind->index = index;
+
+	spin_lock_irqsave(&phy_lock, flags);
+	list_add_tail(&phy_bind->list, &phy_bind_list);
+	spin_unlock_irqrestore(&phy_lock, flags);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(usb_bind_phy);
diff --git a/drivers/usb/phy/rcar-phy.c b/drivers/usb/phy/rcar-phy.c
deleted file mode 100644
index a35681b..0000000
--- a/drivers/usb/phy/rcar-phy.c
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * Renesas R-Car USB phy driver
- *
- * Copyright (C) 2012 Renesas Solutions Corp.
- * Kuninori Morimoto <kuninori.morimoto.gx@renesas.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/delay.h>
-#include <linux/io.h>
-#include <linux/usb/otg.h>
-#include <linux/platform_device.h>
-#include <linux/spinlock.h>
-#include <linux/module.h>
-
-/* USBH common register */
-#define USBPCTRL0	0x0800
-#define USBPCTRL1	0x0804
-#define USBST		0x0808
-#define USBEH0		0x080C
-#define USBOH0		0x081C
-#define USBCTL0		0x0858
-#define EIIBC1		0x0094
-#define EIIBC2		0x009C
-
-/* USBPCTRL1 */
-#define PHY_RST		(1 << 2)
-#define PLL_ENB		(1 << 1)
-#define PHY_ENB		(1 << 0)
-
-/* USBST */
-#define ST_ACT		(1 << 31)
-#define ST_PLL		(1 << 30)
-
-struct rcar_usb_phy_priv {
-	struct usb_phy phy;
-	spinlock_t lock;
-
-	void __iomem *reg0;
-	void __iomem *reg1;
-	int counter;
-};
-
-#define usb_phy_to_priv(p) container_of(p, struct rcar_usb_phy_priv, phy)
-
-
-/*
- * USB initial/install operation.
- *
- * This function setup USB phy.
- * The used value and setting order came from
- * [USB :: Initial setting] on datasheet.
- */
-static int rcar_usb_phy_init(struct usb_phy *phy)
-{
-	struct rcar_usb_phy_priv *priv = usb_phy_to_priv(phy);
-	struct device *dev = phy->dev;
-	void __iomem *reg0 = priv->reg0;
-	void __iomem *reg1 = priv->reg1;
-	int i;
-	u32 val;
-	unsigned long flags;
-
-	spin_lock_irqsave(&priv->lock, flags);
-	if (priv->counter++ == 0) {
-
-		/*
-		 * USB phy start-up
-		 */
-
-		/* (1) USB-PHY standby release */
-		iowrite32(PHY_ENB, (reg0 + USBPCTRL1));
-
-		/* (2) start USB-PHY internal PLL */
-		iowrite32(PHY_ENB | PLL_ENB, (reg0 + USBPCTRL1));
-
-		/* (3) USB module status check */
-		for (i = 0; i < 1024; i++) {
-			udelay(10);
-			val = ioread32(reg0 + USBST);
-			if (val == (ST_ACT | ST_PLL))
-				break;
-		}
-
-		if (val != (ST_ACT | ST_PLL)) {
-			dev_err(dev, "USB phy not ready\n");
-			goto phy_init_end;
-		}
-
-		/* (4) USB-PHY reset clear */
-		iowrite32(PHY_ENB | PLL_ENB | PHY_RST, (reg0 + USBPCTRL1));
-
-		/* set platform specific port settings */
-		iowrite32(0x00000000, (reg0 + USBPCTRL0));
-
-		/*
-		 * EHCI IP internal buffer setting
-		 * EHCI IP internal buffer enable
-		 *
-		 * These are recommended value of a datasheet
-		 * see [USB :: EHCI internal buffer setting]
-		 */
-		iowrite32(0x00ff0040, (reg0 + EIIBC1));
-		iowrite32(0x00ff0040, (reg1 + EIIBC1));
-
-		iowrite32(0x00000001, (reg0 + EIIBC2));
-		iowrite32(0x00000001, (reg1 + EIIBC2));
-
-		/*
-		 * Bus alignment settings
-		 */
-
-		/* (1) EHCI bus alignment (little endian) */
-		iowrite32(0x00000000, (reg0 + USBEH0));
-
-		/* (1) OHCI bus alignment (little endian) */
-		iowrite32(0x00000000, (reg0 + USBOH0));
-	}
-
-phy_init_end:
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	return 0;
-}
-
-static void rcar_usb_phy_shutdown(struct usb_phy *phy)
-{
-	struct rcar_usb_phy_priv *priv = usb_phy_to_priv(phy);
-	void __iomem *reg0 = priv->reg0;
-	unsigned long flags;
-
-	spin_lock_irqsave(&priv->lock, flags);
-
-	if (priv->counter-- == 1) { /* last user */
-		iowrite32(0x00000000, (reg0 + USBPCTRL0));
-		iowrite32(0x00000000, (reg0 + USBPCTRL1));
-	}
-
-	spin_unlock_irqrestore(&priv->lock, flags);
-}
-
-static int rcar_usb_phy_probe(struct platform_device *pdev)
-{
-	struct rcar_usb_phy_priv *priv;
-	struct resource *res0, *res1;
-	struct device *dev = &pdev->dev;
-	void __iomem *reg0, *reg1;
-	int ret;
-
-	res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	res1 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-	if (!res0 || !res1) {
-		dev_err(dev, "Not enough platform resources\n");
-		return -EINVAL;
-	}
-
-	/*
-	 * CAUTION
-	 *
-	 * Because this phy address is also mapped under OHCI/EHCI address area,
-	 * this driver can't use devm_request_and_ioremap(dev, res) here
-	 */
-	reg0 = devm_ioremap_nocache(dev, res0->start, resource_size(res0));
-	reg1 = devm_ioremap_nocache(dev, res1->start, resource_size(res1));
-	if (!reg0 || !reg1) {
-		dev_err(dev, "ioremap error\n");
-		return -ENOMEM;
-	}
-
-	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
-	if (!priv) {
-		dev_err(dev, "priv data allocation error\n");
-		return -ENOMEM;
-	}
-
-	priv->reg0		= reg0;
-	priv->reg1		= reg1;
-	priv->counter		= 0;
-	priv->phy.dev		= dev;
-	priv->phy.label		= dev_name(dev);
-	priv->phy.init		= rcar_usb_phy_init;
-	priv->phy.shutdown	= rcar_usb_phy_shutdown;
-	spin_lock_init(&priv->lock);
-
-	ret = usb_add_phy(&priv->phy, USB_PHY_TYPE_USB2);
-	if (ret < 0) {
-		dev_err(dev, "usb phy addition error\n");
-		return ret;
-	}
-
-	platform_set_drvdata(pdev, priv);
-
-	return ret;
-}
-
-static int rcar_usb_phy_remove(struct platform_device *pdev)
-{
-	struct rcar_usb_phy_priv *priv = platform_get_drvdata(pdev);
-
-	usb_remove_phy(&priv->phy);
-
-	return 0;
-}
-
-static struct platform_driver rcar_usb_phy_driver = {
-	.driver		= {
-		.name	= "rcar_usb_phy",
-	},
-	.probe		= rcar_usb_phy_probe,
-	.remove		= rcar_usb_phy_remove,
-};
-
-module_platform_driver(rcar_usb_phy_driver);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("Renesas R-Car USB phy");
-MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
diff --git a/drivers/usb/phy/samsung-usbphy.c b/drivers/usb/phy/samsung-usbphy.c
deleted file mode 100644
index 967101e..0000000
--- a/drivers/usb/phy/samsung-usbphy.c
+++ /dev/null
@@ -1,928 +0,0 @@
-/* linux/drivers/usb/phy/samsung-usbphy.c
- *
- * Copyright (c) 2012 Samsung Electronics Co., Ltd.
- *              http://www.samsung.com
- *
- * Author: Praveen Paneri <p.paneri@samsung.com>
- *
- * Samsung USB2.0 PHY transceiver; talks to S3C HS OTG controller, EHCI-S5P and
- * OHCI-EXYNOS controllers.
- *
- * This program is free software; you can 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.
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/usb/otg.h>
-#include <linux/usb/samsung_usb_phy.h>
-#include <linux/platform_data/samsung-usbphy.h>
-
-/* Register definitions */
-
-#define SAMSUNG_PHYPWR				(0x00)
-
-#define PHYPWR_NORMAL_MASK			(0x19 << 0)
-#define PHYPWR_OTG_DISABLE			(0x1 << 4)
-#define PHYPWR_ANALOG_POWERDOWN			(0x1 << 3)
-#define PHYPWR_FORCE_SUSPEND			(0x1 << 1)
-/* For Exynos4 */
-#define PHYPWR_NORMAL_MASK_PHY0			(0x39 << 0)
-#define PHYPWR_SLEEP_PHY0			(0x1 << 5)
-
-#define SAMSUNG_PHYCLK				(0x04)
-
-#define PHYCLK_MODE_USB11			(0x1 << 6)
-#define PHYCLK_EXT_OSC				(0x1 << 5)
-#define PHYCLK_COMMON_ON_N			(0x1 << 4)
-#define PHYCLK_ID_PULL				(0x1 << 2)
-#define PHYCLK_CLKSEL_MASK			(0x3 << 0)
-#define PHYCLK_CLKSEL_48M			(0x0 << 0)
-#define PHYCLK_CLKSEL_12M			(0x2 << 0)
-#define PHYCLK_CLKSEL_24M			(0x3 << 0)
-
-#define SAMSUNG_RSTCON				(0x08)
-
-#define RSTCON_PHYLINK_SWRST			(0x1 << 2)
-#define RSTCON_HLINK_SWRST			(0x1 << 1)
-#define RSTCON_SWRST				(0x1 << 0)
-
-/* EXYNOS5 */
-#define EXYNOS5_PHY_HOST_CTRL0			(0x00)
-
-#define HOST_CTRL0_PHYSWRSTALL			(0x1 << 31)
-
-#define HOST_CTRL0_REFCLKSEL_MASK		(0x3 << 19)
-#define HOST_CTRL0_REFCLKSEL_XTAL		(0x0 << 19)
-#define HOST_CTRL0_REFCLKSEL_EXTL		(0x1 << 19)
-#define HOST_CTRL0_REFCLKSEL_CLKCORE		(0x2 << 19)
-
-#define HOST_CTRL0_FSEL_MASK			(0x7 << 16)
-#define HOST_CTRL0_FSEL(_x)			((_x) << 16)
-
-#define FSEL_CLKSEL_50M				(0x7)
-#define FSEL_CLKSEL_24M				(0x5)
-#define FSEL_CLKSEL_20M				(0x4)
-#define FSEL_CLKSEL_19200K			(0x3)
-#define FSEL_CLKSEL_12M				(0x2)
-#define FSEL_CLKSEL_10M				(0x1)
-#define FSEL_CLKSEL_9600K			(0x0)
-
-#define HOST_CTRL0_TESTBURNIN			(0x1 << 11)
-#define HOST_CTRL0_RETENABLE			(0x1 << 10)
-#define HOST_CTRL0_COMMONON_N			(0x1 << 9)
-#define HOST_CTRL0_SIDDQ			(0x1 << 6)
-#define HOST_CTRL0_FORCESLEEP			(0x1 << 5)
-#define HOST_CTRL0_FORCESUSPEND			(0x1 << 4)
-#define HOST_CTRL0_WORDINTERFACE		(0x1 << 3)
-#define HOST_CTRL0_UTMISWRST			(0x1 << 2)
-#define HOST_CTRL0_LINKSWRST			(0x1 << 1)
-#define HOST_CTRL0_PHYSWRST			(0x1 << 0)
-
-#define EXYNOS5_PHY_HOST_TUNE0			(0x04)
-
-#define EXYNOS5_PHY_HSIC_CTRL1			(0x10)
-
-#define EXYNOS5_PHY_HSIC_TUNE1			(0x14)
-
-#define EXYNOS5_PHY_HSIC_CTRL2			(0x20)
-
-#define EXYNOS5_PHY_HSIC_TUNE2			(0x24)
-
-#define HSIC_CTRL_REFCLKSEL_MASK		(0x3 << 23)
-#define HSIC_CTRL_REFCLKSEL			(0x2 << 23)
-
-#define HSIC_CTRL_REFCLKDIV_MASK		(0x7f << 16)
-#define HSIC_CTRL_REFCLKDIV(_x)			((_x) << 16)
-#define HSIC_CTRL_REFCLKDIV_12			(0x24 << 16)
-#define HSIC_CTRL_REFCLKDIV_15			(0x1c << 16)
-#define HSIC_CTRL_REFCLKDIV_16			(0x1a << 16)
-#define HSIC_CTRL_REFCLKDIV_19_2		(0x15 << 16)
-#define HSIC_CTRL_REFCLKDIV_20			(0x14 << 16)
-
-#define HSIC_CTRL_SIDDQ				(0x1 << 6)
-#define HSIC_CTRL_FORCESLEEP			(0x1 << 5)
-#define HSIC_CTRL_FORCESUSPEND			(0x1 << 4)
-#define HSIC_CTRL_WORDINTERFACE			(0x1 << 3)
-#define HSIC_CTRL_UTMISWRST			(0x1 << 2)
-#define HSIC_CTRL_PHYSWRST			(0x1 << 0)
-
-#define EXYNOS5_PHY_HOST_EHCICTRL		(0x30)
-
-#define HOST_EHCICTRL_ENAINCRXALIGN		(0x1 << 29)
-#define HOST_EHCICTRL_ENAINCR4			(0x1 << 28)
-#define HOST_EHCICTRL_ENAINCR8			(0x1 << 27)
-#define HOST_EHCICTRL_ENAINCR16			(0x1 << 26)
-
-#define EXYNOS5_PHY_HOST_OHCICTRL		(0x34)
-
-#define HOST_OHCICTRL_SUSPLGCY			(0x1 << 3)
-#define HOST_OHCICTRL_APPSTARTCLK		(0x1 << 2)
-#define HOST_OHCICTRL_CNTSEL			(0x1 << 1)
-#define HOST_OHCICTRL_CLKCKTRST			(0x1 << 0)
-
-#define EXYNOS5_PHY_OTG_SYS			(0x38)
-
-#define OTG_SYS_PHYLINK_SWRESET			(0x1 << 14)
-#define OTG_SYS_LINKSWRST_UOTG			(0x1 << 13)
-#define OTG_SYS_PHY0_SWRST			(0x1 << 12)
-
-#define OTG_SYS_REFCLKSEL_MASK			(0x3 << 9)
-#define OTG_SYS_REFCLKSEL_XTAL			(0x0 << 9)
-#define OTG_SYS_REFCLKSEL_EXTL			(0x1 << 9)
-#define OTG_SYS_REFCLKSEL_CLKCORE		(0x2 << 9)
-
-#define OTG_SYS_IDPULLUP_UOTG			(0x1 << 8)
-#define OTG_SYS_COMMON_ON			(0x1 << 7)
-
-#define OTG_SYS_FSEL_MASK			(0x7 << 4)
-#define OTG_SYS_FSEL(_x)			((_x) << 4)
-
-#define OTG_SYS_FORCESLEEP			(0x1 << 3)
-#define OTG_SYS_OTGDISABLE			(0x1 << 2)
-#define OTG_SYS_SIDDQ_UOTG			(0x1 << 1)
-#define OTG_SYS_FORCESUSPEND			(0x1 << 0)
-
-#define EXYNOS5_PHY_OTG_TUNE			(0x40)
-
-#ifndef MHZ
-#define MHZ (1000*1000)
-#endif
-
-#ifndef KHZ
-#define KHZ (1000)
-#endif
-
-#define EXYNOS_USBHOST_PHY_CTRL_OFFSET		(0x4)
-#define S3C64XX_USBPHY_ENABLE			(0x1 << 16)
-#define EXYNOS_USBPHY_ENABLE			(0x1 << 0)
-#define EXYNOS_USB20PHY_CFG_HOST_LINK		(0x1 << 0)
-
-enum samsung_cpu_type {
-	TYPE_S3C64XX,
-	TYPE_EXYNOS4210,
-	TYPE_EXYNOS5250,
-};
-
-/*
- * struct samsung_usbphy_drvdata - driver data for various SoC variants
- * @cpu_type: machine identifier
- * @devphy_en_mask: device phy enable mask for PHY CONTROL register
- * @hostphy_en_mask: host phy enable mask for PHY CONTROL register
- * @devphy_reg_offset: offset to DEVICE PHY CONTROL register from
- *		       mapped address of system controller.
- * @hostphy_reg_offset: offset to HOST PHY CONTROL register from
- *		       mapped address of system controller.
- *
- *	Here we have a separate mask for device type phy.
- *	Having different masks for host and device type phy helps
- *	in setting independent masks in case of SoCs like S5PV210,
- *	in which PHY0 and PHY1 enable bits belong to same register
- *	placed at position 0 and 1 respectively.
- *	Although for newer SoCs like exynos these bits belong to
- *	different registers altogether placed at position 0.
- */
-struct samsung_usbphy_drvdata {
-	int cpu_type;
-	int devphy_en_mask;
-	int hostphy_en_mask;
-	u32 devphy_reg_offset;
-	u32 hostphy_reg_offset;
-};
-
-/*
- * struct samsung_usbphy - transceiver driver state
- * @phy: transceiver structure
- * @plat: platform data
- * @dev: The parent device supplied to the probe function
- * @clk: usb phy clock
- * @regs: usb phy controller registers memory base
- * @pmuregs: USB device PHY_CONTROL register memory base
- * @sysreg: USB2.0 PHY_CFG register memory base
- * @ref_clk_freq: reference clock frequency selection
- * @drv_data: driver data available for different SoCs
- * @phy_type: Samsung SoCs specific phy types:	#HOST
- *						#DEVICE
- * @phy_usage: usage count for phy
- * @lock: lock for phy operations
- */
-struct samsung_usbphy {
-	struct usb_phy	phy;
-	struct samsung_usbphy_data *plat;
-	struct device	*dev;
-	struct clk	*clk;
-	void __iomem	*regs;
-	void __iomem	*pmuregs;
-	void __iomem	*sysreg;
-	int		ref_clk_freq;
-	const struct samsung_usbphy_drvdata *drv_data;
-	enum samsung_usb_phy_type phy_type;
-	atomic_t	phy_usage;
-	spinlock_t	lock;
-};
-
-#define phy_to_sphy(x)		container_of((x), struct samsung_usbphy, phy)
-
-int samsung_usbphy_set_host(struct usb_otg *otg, struct usb_bus *host)
-{
-	if (!otg)
-		return -ENODEV;
-
-	if (!otg->host)
-		otg->host = host;
-
-	return 0;
-}
-
-static int samsung_usbphy_parse_dt(struct samsung_usbphy *sphy)
-{
-	struct device_node *usbphy_sys;
-
-	/* Getting node for system controller interface for usb-phy */
-	usbphy_sys = of_get_child_by_name(sphy->dev->of_node, "usbphy-sys");
-	if (!usbphy_sys) {
-		dev_err(sphy->dev, "No sys-controller interface for usb-phy\n");
-		return -ENODEV;
-	}
-
-	sphy->pmuregs = of_iomap(usbphy_sys, 0);
-
-	if (sphy->pmuregs == NULL) {
-		dev_err(sphy->dev, "Can't get usb-phy pmu control register\n");
-		goto err0;
-	}
-
-	sphy->sysreg = of_iomap(usbphy_sys, 1);
-
-	/*
-	 * Not returning error code here, since this situation is not fatal.
-	 * Few SoCs may not have this switch available
-	 */
-	if (sphy->sysreg == NULL)
-		dev_warn(sphy->dev, "Can't get usb-phy sysreg cfg register\n");
-
-	of_node_put(usbphy_sys);
-
-	return 0;
-
-err0:
-	of_node_put(usbphy_sys);
-	return -ENXIO;
-}
-
-/*
- * Set isolation here for phy.
- * Here 'on = true' would mean USB PHY block is isolated, hence
- * de-activated and vice-versa.
- */
-static void samsung_usbphy_set_isolation(struct samsung_usbphy *sphy, bool on)
-{
-	void __iomem *reg = NULL;
-	u32 reg_val;
-	u32 en_mask = 0;
-
-	if (!sphy->pmuregs) {
-		dev_warn(sphy->dev, "Can't set pmu isolation\n");
-		return;
-	}
-
-	switch (sphy->drv_data->cpu_type) {
-	case TYPE_S3C64XX:
-		/*
-		 * Do nothing: We will add here once S3C64xx goes for DT support
-		 */
-		break;
-	case TYPE_EXYNOS4210:
-		/*
-		 * Fall through since exynos4210 and exynos5250 have similar
-		 * register architecture: two separate registers for host and
-		 * device phy control with enable bit at position 0.
-		 */
-	case TYPE_EXYNOS5250:
-		if (sphy->phy_type == USB_PHY_TYPE_DEVICE) {
-			reg = sphy->pmuregs +
-				sphy->drv_data->devphy_reg_offset;
-			en_mask = sphy->drv_data->devphy_en_mask;
-		} else if (sphy->phy_type == USB_PHY_TYPE_HOST) {
-			reg = sphy->pmuregs +
-				sphy->drv_data->hostphy_reg_offset;
-			en_mask = sphy->drv_data->hostphy_en_mask;
-		}
-		break;
-	default:
-		dev_err(sphy->dev, "Invalid SoC type\n");
-		return;
-	}
-
-	reg_val = readl(reg);
-
-	if (on)
-		reg_val &= ~en_mask;
-	else
-		reg_val |= en_mask;
-
-	writel(reg_val, reg);
-}
-
-/*
- * Configure the mode of working of usb-phy here: HOST/DEVICE.
- */
-static void samsung_usbphy_cfg_sel(struct samsung_usbphy *sphy)
-{
-	u32 reg;
-
-	if (!sphy->sysreg) {
-		dev_warn(sphy->dev, "Can't configure specified phy mode\n");
-		return;
-	}
-
-	reg = readl(sphy->sysreg);
-
-	if (sphy->phy_type == USB_PHY_TYPE_DEVICE)
-		reg &= ~EXYNOS_USB20PHY_CFG_HOST_LINK;
-	else if (sphy->phy_type == USB_PHY_TYPE_HOST)
-		reg |= EXYNOS_USB20PHY_CFG_HOST_LINK;
-
-	writel(reg, sphy->sysreg);
-}
-
-/*
- * PHYs are different for USB Device and USB Host.
- * This make sure that correct PHY type is selected before
- * any operation on PHY.
- */
-static int samsung_usbphy_set_type(struct usb_phy *phy,
-				enum samsung_usb_phy_type phy_type)
-{
-	struct samsung_usbphy *sphy = phy_to_sphy(phy);
-
-	sphy->phy_type = phy_type;
-
-	return 0;
-}
-
-/*
- * Returns reference clock frequency selection value
- */
-static int samsung_usbphy_get_refclk_freq(struct samsung_usbphy *sphy)
-{
-	struct clk *ref_clk;
-	int refclk_freq = 0;
-
-	/*
-	 * In exynos5250 USB host and device PHY use
-	 * external crystal clock XXTI
-	 */
-	if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250)
-		ref_clk = clk_get(sphy->dev, "ext_xtal");
-	else
-		ref_clk = clk_get(sphy->dev, "xusbxti");
-	if (IS_ERR(ref_clk)) {
-		dev_err(sphy->dev, "Failed to get reference clock\n");
-		return PTR_ERR(ref_clk);
-	}
-
-	if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250) {
-		/* set clock frequency for PLL */
-		switch (clk_get_rate(ref_clk)) {
-		case 9600 * KHZ:
-			refclk_freq = FSEL_CLKSEL_9600K;
-			break;
-		case 10 * MHZ:
-			refclk_freq = FSEL_CLKSEL_10M;
-			break;
-		case 12 * MHZ:
-			refclk_freq = FSEL_CLKSEL_12M;
-			break;
-		case 19200 * KHZ:
-			refclk_freq = FSEL_CLKSEL_19200K;
-			break;
-		case 20 * MHZ:
-			refclk_freq = FSEL_CLKSEL_20M;
-			break;
-		case 50 * MHZ:
-			refclk_freq = FSEL_CLKSEL_50M;
-			break;
-		case 24 * MHZ:
-		default:
-			/* default reference clock */
-			refclk_freq = FSEL_CLKSEL_24M;
-			break;
-		}
-	} else {
-		switch (clk_get_rate(ref_clk)) {
-		case 12 * MHZ:
-			refclk_freq = PHYCLK_CLKSEL_12M;
-			break;
-		case 24 * MHZ:
-			refclk_freq = PHYCLK_CLKSEL_24M;
-			break;
-		case 48 * MHZ:
-			refclk_freq = PHYCLK_CLKSEL_48M;
-			break;
-		default:
-			if (sphy->drv_data->cpu_type == TYPE_S3C64XX)
-				refclk_freq = PHYCLK_CLKSEL_48M;
-			else
-				refclk_freq = PHYCLK_CLKSEL_24M;
-			break;
-		}
-	}
-	clk_put(ref_clk);
-
-	return refclk_freq;
-}
-
-static bool exynos5_phyhost_is_on(void *regs)
-{
-	u32 reg;
-
-	reg = readl(regs + EXYNOS5_PHY_HOST_CTRL0);
-
-	return !(reg & HOST_CTRL0_SIDDQ);
-}
-
-static void samsung_exynos5_usbphy_enable(struct samsung_usbphy *sphy)
-{
-	void __iomem *regs = sphy->regs;
-	u32 phyclk = sphy->ref_clk_freq;
-	u32 phyhost;
-	u32 phyotg;
-	u32 phyhsic;
-	u32 ehcictrl;
-	u32 ohcictrl;
-
-	/*
-	 * phy_usage helps in keeping usage count for phy
-	 * so that the first consumer enabling the phy is also
-	 * the last consumer to disable it.
-	 */
-
-	atomic_inc(&sphy->phy_usage);
-
-	if (exynos5_phyhost_is_on(regs)) {
-		dev_info(sphy->dev, "Already power on PHY\n");
-		return;
-	}
-
-	/* Host configuration */
-	phyhost = readl(regs + EXYNOS5_PHY_HOST_CTRL0);
-
-	/* phy reference clock configuration */
-	phyhost &= ~HOST_CTRL0_FSEL_MASK;
-	phyhost |= HOST_CTRL0_FSEL(phyclk);
-
-	/* host phy reset */
-	phyhost &= ~(HOST_CTRL0_PHYSWRST |
-			HOST_CTRL0_PHYSWRSTALL |
-			HOST_CTRL0_SIDDQ |
-			/* Enable normal mode of operation */
-			HOST_CTRL0_FORCESUSPEND |
-			HOST_CTRL0_FORCESLEEP);
-
-	/* Link reset */
-	phyhost |= (HOST_CTRL0_LINKSWRST |
-			HOST_CTRL0_UTMISWRST |
-			/* COMMON Block configuration during suspend */
-			HOST_CTRL0_COMMONON_N);
-	writel(phyhost, regs + EXYNOS5_PHY_HOST_CTRL0);
-	udelay(10);
-	phyhost &= ~(HOST_CTRL0_LINKSWRST |
-			HOST_CTRL0_UTMISWRST);
-	writel(phyhost, regs + EXYNOS5_PHY_HOST_CTRL0);
-
-	/* OTG configuration */
-	phyotg = readl(regs + EXYNOS5_PHY_OTG_SYS);
-
-	/* phy reference clock configuration */
-	phyotg &= ~OTG_SYS_FSEL_MASK;
-	phyotg |= OTG_SYS_FSEL(phyclk);
-
-	/* Enable normal mode of operation */
-	phyotg &= ~(OTG_SYS_FORCESUSPEND |
-			OTG_SYS_SIDDQ_UOTG |
-			OTG_SYS_FORCESLEEP |
-			OTG_SYS_REFCLKSEL_MASK |
-			/* COMMON Block configuration during suspend */
-			OTG_SYS_COMMON_ON);
-
-	/* OTG phy & link reset */
-	phyotg |= (OTG_SYS_PHY0_SWRST |
-			OTG_SYS_LINKSWRST_UOTG |
-			OTG_SYS_PHYLINK_SWRESET |
-			OTG_SYS_OTGDISABLE |
-			/* Set phy refclk */
-			OTG_SYS_REFCLKSEL_CLKCORE);
-
-	writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS);
-	udelay(10);
-	phyotg &= ~(OTG_SYS_PHY0_SWRST |
-			OTG_SYS_LINKSWRST_UOTG |
-			OTG_SYS_PHYLINK_SWRESET);
-	writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS);
-
-	/* HSIC phy configuration */
-	phyhsic = (HSIC_CTRL_REFCLKDIV_12 |
-			HSIC_CTRL_REFCLKSEL |
-			HSIC_CTRL_PHYSWRST);
-	writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL1);
-	writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL2);
-	udelay(10);
-	phyhsic &= ~HSIC_CTRL_PHYSWRST;
-	writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL1);
-	writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL2);
-
-	udelay(80);
-
-	/* enable EHCI DMA burst */
-	ehcictrl = readl(regs + EXYNOS5_PHY_HOST_EHCICTRL);
-	ehcictrl |= (HOST_EHCICTRL_ENAINCRXALIGN |
-				HOST_EHCICTRL_ENAINCR4 |
-				HOST_EHCICTRL_ENAINCR8 |
-				HOST_EHCICTRL_ENAINCR16);
-	writel(ehcictrl, regs + EXYNOS5_PHY_HOST_EHCICTRL);
-
-	/* set ohci_suspend_on_n */
-	ohcictrl = readl(regs + EXYNOS5_PHY_HOST_OHCICTRL);
-	ohcictrl |= HOST_OHCICTRL_SUSPLGCY;
-	writel(ohcictrl, regs + EXYNOS5_PHY_HOST_OHCICTRL);
-}
-
-static void samsung_usbphy_enable(struct samsung_usbphy *sphy)
-{
-	void __iomem *regs = sphy->regs;
-	u32 phypwr;
-	u32 phyclk;
-	u32 rstcon;
-
-	/* set clock frequency for PLL */
-	phyclk = sphy->ref_clk_freq;
-	phypwr = readl(regs + SAMSUNG_PHYPWR);
-	rstcon = readl(regs + SAMSUNG_RSTCON);
-
-	switch (sphy->drv_data->cpu_type) {
-	case TYPE_S3C64XX:
-		phyclk &= ~PHYCLK_COMMON_ON_N;
-		phypwr &= ~PHYPWR_NORMAL_MASK;
-		rstcon |= RSTCON_SWRST;
-		break;
-	case TYPE_EXYNOS4210:
-		phypwr &= ~PHYPWR_NORMAL_MASK_PHY0;
-		rstcon |= RSTCON_SWRST;
-	default:
-		break;
-	}
-
-	writel(phyclk, regs + SAMSUNG_PHYCLK);
-	/* Configure PHY0 for normal operation*/
-	writel(phypwr, regs + SAMSUNG_PHYPWR);
-	/* reset all ports of PHY and Link */
-	writel(rstcon, regs + SAMSUNG_RSTCON);
-	udelay(10);
-	rstcon &= ~RSTCON_SWRST;
-	writel(rstcon, regs + SAMSUNG_RSTCON);
-}
-
-static void samsung_exynos5_usbphy_disable(struct samsung_usbphy *sphy)
-{
-	void __iomem *regs = sphy->regs;
-	u32 phyhost;
-	u32 phyotg;
-	u32 phyhsic;
-
-	if (atomic_dec_return(&sphy->phy_usage) > 0) {
-		dev_info(sphy->dev, "still being used\n");
-		return;
-	}
-
-	phyhsic = (HSIC_CTRL_REFCLKDIV_12 |
-			HSIC_CTRL_REFCLKSEL |
-			HSIC_CTRL_SIDDQ |
-			HSIC_CTRL_FORCESLEEP |
-			HSIC_CTRL_FORCESUSPEND);
-	writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL1);
-	writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL2);
-
-	phyhost = readl(regs + EXYNOS5_PHY_HOST_CTRL0);
-	phyhost |= (HOST_CTRL0_SIDDQ |
-			HOST_CTRL0_FORCESUSPEND |
-			HOST_CTRL0_FORCESLEEP |
-			HOST_CTRL0_PHYSWRST |
-			HOST_CTRL0_PHYSWRSTALL);
-	writel(phyhost, regs + EXYNOS5_PHY_HOST_CTRL0);
-
-	phyotg = readl(regs + EXYNOS5_PHY_OTG_SYS);
-	phyotg |= (OTG_SYS_FORCESUSPEND |
-			OTG_SYS_SIDDQ_UOTG |
-			OTG_SYS_FORCESLEEP);
-	writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS);
-}
-
-static void samsung_usbphy_disable(struct samsung_usbphy *sphy)
-{
-	void __iomem *regs = sphy->regs;
-	u32 phypwr;
-
-	phypwr = readl(regs + SAMSUNG_PHYPWR);
-
-	switch (sphy->drv_data->cpu_type) {
-	case TYPE_S3C64XX:
-		phypwr |= PHYPWR_NORMAL_MASK;
-		break;
-	case TYPE_EXYNOS4210:
-		phypwr |= PHYPWR_NORMAL_MASK_PHY0;
-	default:
-		break;
-	}
-
-	/* Disable analog and otg block power */
-	writel(phypwr, regs + SAMSUNG_PHYPWR);
-}
-
-/*
- * The function passed to the usb driver for phy initialization
- */
-static int samsung_usbphy_init(struct usb_phy *phy)
-{
-	struct samsung_usbphy *sphy;
-	struct usb_bus *host = NULL;
-	unsigned long flags;
-	int ret = 0;
-
-	sphy = phy_to_sphy(phy);
-
-	host = phy->otg->host;
-
-	/* Enable the phy clock */
-	ret = clk_prepare_enable(sphy->clk);
-	if (ret) {
-		dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__);
-		return ret;
-	}
-
-	spin_lock_irqsave(&sphy->lock, flags);
-
-	if (host) {
-		/* setting default phy-type for USB 2.0 */
-		if (!strstr(dev_name(host->controller), "ehci") ||
-				!strstr(dev_name(host->controller), "ohci"))
-			samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_HOST);
-	} else {
-		samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE);
-	}
-
-	/* Disable phy isolation */
-	if (sphy->plat && sphy->plat->pmu_isolation)
-		sphy->plat->pmu_isolation(false);
-	else
-		samsung_usbphy_set_isolation(sphy, false);
-
-	/* Selecting Host/OTG mode; After reset USB2.0PHY_CFG: HOST */
-	samsung_usbphy_cfg_sel(sphy);
-
-	/* Initialize usb phy registers */
-	if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250)
-		samsung_exynos5_usbphy_enable(sphy);
-	else
-		samsung_usbphy_enable(sphy);
-
-	spin_unlock_irqrestore(&sphy->lock, flags);
-
-	/* Disable the phy clock */
-	clk_disable_unprepare(sphy->clk);
-
-	return ret;
-}
-
-/*
- * The function passed to the usb driver for phy shutdown
- */
-static void samsung_usbphy_shutdown(struct usb_phy *phy)
-{
-	struct samsung_usbphy *sphy;
-	struct usb_bus *host = NULL;
-	unsigned long flags;
-
-	sphy = phy_to_sphy(phy);
-
-	host = phy->otg->host;
-
-	if (clk_prepare_enable(sphy->clk)) {
-		dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__);
-		return;
-	}
-
-	spin_lock_irqsave(&sphy->lock, flags);
-
-	if (host) {
-		/* setting default phy-type for USB 2.0 */
-		if (!strstr(dev_name(host->controller), "ehci") ||
-				!strstr(dev_name(host->controller), "ohci"))
-			samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_HOST);
-	} else {
-		samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE);
-	}
-
-	/* De-initialize usb phy registers */
-	if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250)
-		samsung_exynos5_usbphy_disable(sphy);
-	else
-		samsung_usbphy_disable(sphy);
-
-	/* Enable phy isolation */
-	if (sphy->plat && sphy->plat->pmu_isolation)
-		sphy->plat->pmu_isolation(true);
-	else
-		samsung_usbphy_set_isolation(sphy, true);
-
-	spin_unlock_irqrestore(&sphy->lock, flags);
-
-	clk_disable_unprepare(sphy->clk);
-}
-
-static const struct of_device_id samsung_usbphy_dt_match[];
-
-static inline const struct samsung_usbphy_drvdata
-*samsung_usbphy_get_driver_data(struct platform_device *pdev)
-{
-	if (pdev->dev.of_node) {
-		const struct of_device_id *match;
-		match = of_match_node(samsung_usbphy_dt_match,
-							pdev->dev.of_node);
-		return match->data;
-	}
-
-	return (struct samsung_usbphy_drvdata *)
-				platform_get_device_id(pdev)->driver_data;
-}
-
-static int samsung_usbphy_probe(struct platform_device *pdev)
-{
-	struct samsung_usbphy *sphy;
-	struct usb_otg *otg;
-	struct samsung_usbphy_data *pdata = pdev->dev.platform_data;
-	const struct samsung_usbphy_drvdata *drv_data;
-	struct device *dev = &pdev->dev;
-	struct resource *phy_mem;
-	void __iomem	*phy_base;
-	struct clk *clk;
-	int ret;
-
-	phy_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!phy_mem) {
-		dev_err(dev, "%s: missing mem resource\n", __func__);
-		return -ENODEV;
-	}
-
-	phy_base = devm_ioremap_resource(dev, phy_mem);
-	if (IS_ERR(phy_base))
-		return PTR_ERR(phy_base);
-
-	sphy = devm_kzalloc(dev, sizeof(*sphy), GFP_KERNEL);
-	if (!sphy)
-		return -ENOMEM;
-
-	otg = devm_kzalloc(dev, sizeof(*otg), GFP_KERNEL);
-	if (!otg)
-		return -ENOMEM;
-
-	drv_data = samsung_usbphy_get_driver_data(pdev);
-
-	if (drv_data->cpu_type == TYPE_EXYNOS5250)
-		clk = devm_clk_get(dev, "usbhost");
-	else
-		clk = devm_clk_get(dev, "otg");
-
-	if (IS_ERR(clk)) {
-		dev_err(dev, "Failed to get otg clock\n");
-		return PTR_ERR(clk);
-	}
-
-	sphy->dev = dev;
-
-	if (dev->of_node) {
-		ret = samsung_usbphy_parse_dt(sphy);
-		if (ret < 0)
-			return ret;
-	} else {
-		if (!pdata) {
-			dev_err(dev, "no platform data specified\n");
-			return -EINVAL;
-		}
-	}
-
-	sphy->plat		= pdata;
-	sphy->regs		= phy_base;
-	sphy->clk		= clk;
-	sphy->drv_data		= drv_data;
-	sphy->phy.dev		= sphy->dev;
-	sphy->phy.label		= "samsung-usbphy";
-	sphy->phy.init		= samsung_usbphy_init;
-	sphy->phy.shutdown	= samsung_usbphy_shutdown;
-	sphy->ref_clk_freq	= samsung_usbphy_get_refclk_freq(sphy);
-
-	sphy->phy.otg		= otg;
-	sphy->phy.otg->phy	= &sphy->phy;
-	sphy->phy.otg->set_host = samsung_usbphy_set_host;
-
-	spin_lock_init(&sphy->lock);
-
-	platform_set_drvdata(pdev, sphy);
-
-	return usb_add_phy(&sphy->phy, USB_PHY_TYPE_USB2);
-}
-
-static int samsung_usbphy_remove(struct platform_device *pdev)
-{
-	struct samsung_usbphy *sphy = platform_get_drvdata(pdev);
-
-	usb_remove_phy(&sphy->phy);
-
-	if (sphy->pmuregs)
-		iounmap(sphy->pmuregs);
-	if (sphy->sysreg)
-		iounmap(sphy->sysreg);
-
-	return 0;
-}
-
-static const struct samsung_usbphy_drvdata usbphy_s3c64xx = {
-	.cpu_type		= TYPE_S3C64XX,
-	.devphy_en_mask		= S3C64XX_USBPHY_ENABLE,
-};
-
-static const struct samsung_usbphy_drvdata usbphy_exynos4 = {
-	.cpu_type		= TYPE_EXYNOS4210,
-	.devphy_en_mask		= EXYNOS_USBPHY_ENABLE,
-	.hostphy_en_mask	= EXYNOS_USBPHY_ENABLE,
-};
-
-static struct samsung_usbphy_drvdata usbphy_exynos5 = {
-	.cpu_type		= TYPE_EXYNOS5250,
-	.hostphy_en_mask	= EXYNOS_USBPHY_ENABLE,
-	.hostphy_reg_offset	= EXYNOS_USBHOST_PHY_CTRL_OFFSET,
-};
-
-#ifdef CONFIG_OF
-static const struct of_device_id samsung_usbphy_dt_match[] = {
-	{
-		.compatible = "samsung,s3c64xx-usbphy",
-		.data = &usbphy_s3c64xx,
-	}, {
-		.compatible = "samsung,exynos4210-usbphy",
-		.data = &usbphy_exynos4,
-	}, {
-		.compatible = "samsung,exynos5250-usbphy",
-		.data = &usbphy_exynos5
-	},
-	{},
-};
-MODULE_DEVICE_TABLE(of, samsung_usbphy_dt_match);
-#endif
-
-static struct platform_device_id samsung_usbphy_driver_ids[] = {
-	{
-		.name		= "s3c64xx-usbphy",
-		.driver_data	= (unsigned long)&usbphy_s3c64xx,
-	}, {
-		.name		= "exynos4210-usbphy",
-		.driver_data	= (unsigned long)&usbphy_exynos4,
-	}, {
-		.name		= "exynos5250-usbphy",
-		.driver_data	= (unsigned long)&usbphy_exynos5,
-	},
-	{},
-};
-
-MODULE_DEVICE_TABLE(platform, samsung_usbphy_driver_ids);
-
-static struct platform_driver samsung_usbphy_driver = {
-	.probe		= samsung_usbphy_probe,
-	.remove		= samsung_usbphy_remove,
-	.id_table	= samsung_usbphy_driver_ids,
-	.driver		= {
-		.name	= "samsung-usbphy",
-		.owner	= THIS_MODULE,
-		.of_match_table = of_match_ptr(samsung_usbphy_dt_match),
-	},
-};
-
-module_platform_driver(samsung_usbphy_driver);
-
-MODULE_DESCRIPTION("Samsung USB phy controller");
-MODULE_AUTHOR("Praveen Paneri <p.paneri@samsung.com>");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:samsung-usbphy");
diff --git a/drivers/usb/phy/tegra_usb_phy.c b/drivers/usb/phy/tegra_usb_phy.c
deleted file mode 100644
index 5487d38..0000000
--- a/drivers/usb/phy/tegra_usb_phy.c
+++ /dev/null
@@ -1,798 +0,0 @@
-/*
- * Copyright (C) 2010 Google, Inc.
- *
- * Author:
- *	Erik Gilling <konkers@google.com>
- *	Benoit Goby <benoit@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/resource.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/err.h>
-#include <linux/export.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-#include <linux/of.h>
-#include <linux/of_gpio.h>
-#include <linux/usb/otg.h>
-#include <linux/usb/ulpi.h>
-#include <asm/mach-types.h>
-#include <linux/usb/tegra_usb_phy.h>
-
-#define TEGRA_USB_BASE		0xC5000000
-#define TEGRA_USB_SIZE		SZ_16K
-
-#define ULPI_VIEWPORT		0x170
-
-#define USB_SUSP_CTRL		0x400
-#define   USB_WAKE_ON_CNNT_EN_DEV	(1 << 3)
-#define   USB_WAKE_ON_DISCON_EN_DEV	(1 << 4)
-#define   USB_SUSP_CLR		(1 << 5)
-#define   USB_PHY_CLK_VALID	(1 << 7)
-#define   UTMIP_RESET			(1 << 11)
-#define   UHSIC_RESET			(1 << 11)
-#define   UTMIP_PHY_ENABLE		(1 << 12)
-#define   ULPI_PHY_ENABLE	(1 << 13)
-#define   USB_SUSP_SET		(1 << 14)
-#define   USB_WAKEUP_DEBOUNCE_COUNT(x)	(((x) & 0x7) << 16)
-
-#define USB1_LEGACY_CTRL	0x410
-#define   USB1_NO_LEGACY_MODE			(1 << 0)
-#define   USB1_VBUS_SENSE_CTL_MASK		(3 << 1)
-#define   USB1_VBUS_SENSE_CTL_VBUS_WAKEUP	(0 << 1)
-#define   USB1_VBUS_SENSE_CTL_AB_SESS_VLD_OR_VBUS_WAKEUP \
-						(1 << 1)
-#define   USB1_VBUS_SENSE_CTL_AB_SESS_VLD	(2 << 1)
-#define   USB1_VBUS_SENSE_CTL_A_SESS_VLD	(3 << 1)
-
-#define ULPI_TIMING_CTRL_0	0x424
-#define   ULPI_OUTPUT_PINMUX_BYP	(1 << 10)
-#define   ULPI_CLKOUT_PINMUX_BYP	(1 << 11)
-
-#define ULPI_TIMING_CTRL_1	0x428
-#define   ULPI_DATA_TRIMMER_LOAD	(1 << 0)
-#define   ULPI_DATA_TRIMMER_SEL(x)	(((x) & 0x7) << 1)
-#define   ULPI_STPDIRNXT_TRIMMER_LOAD	(1 << 16)
-#define   ULPI_STPDIRNXT_TRIMMER_SEL(x)	(((x) & 0x7) << 17)
-#define   ULPI_DIR_TRIMMER_LOAD		(1 << 24)
-#define   ULPI_DIR_TRIMMER_SEL(x)	(((x) & 0x7) << 25)
-
-#define UTMIP_PLL_CFG1		0x804
-#define   UTMIP_XTAL_FREQ_COUNT(x)		(((x) & 0xfff) << 0)
-#define   UTMIP_PLLU_ENABLE_DLY_COUNT(x)	(((x) & 0x1f) << 27)
-
-#define UTMIP_XCVR_CFG0		0x808
-#define   UTMIP_XCVR_SETUP(x)			(((x) & 0xf) << 0)
-#define   UTMIP_XCVR_LSRSLEW(x)			(((x) & 0x3) << 8)
-#define   UTMIP_XCVR_LSFSLEW(x)			(((x) & 0x3) << 10)
-#define   UTMIP_FORCE_PD_POWERDOWN		(1 << 14)
-#define   UTMIP_FORCE_PD2_POWERDOWN		(1 << 16)
-#define   UTMIP_FORCE_PDZI_POWERDOWN		(1 << 18)
-#define   UTMIP_XCVR_HSSLEW_MSB(x)		(((x) & 0x7f) << 25)
-
-#define UTMIP_BIAS_CFG0		0x80c
-#define   UTMIP_OTGPD			(1 << 11)
-#define   UTMIP_BIASPD			(1 << 10)
-
-#define UTMIP_HSRX_CFG0		0x810
-#define   UTMIP_ELASTIC_LIMIT(x)	(((x) & 0x1f) << 10)
-#define   UTMIP_IDLE_WAIT(x)		(((x) & 0x1f) << 15)
-
-#define UTMIP_HSRX_CFG1		0x814
-#define   UTMIP_HS_SYNC_START_DLY(x)	(((x) & 0x1f) << 1)
-
-#define UTMIP_TX_CFG0		0x820
-#define   UTMIP_FS_PREABMLE_J		(1 << 19)
-#define   UTMIP_HS_DISCON_DISABLE	(1 << 8)
-
-#define UTMIP_MISC_CFG0		0x824
-#define   UTMIP_DPDM_OBSERVE		(1 << 26)
-#define   UTMIP_DPDM_OBSERVE_SEL(x)	(((x) & 0xf) << 27)
-#define   UTMIP_DPDM_OBSERVE_SEL_FS_J	UTMIP_DPDM_OBSERVE_SEL(0xf)
-#define   UTMIP_DPDM_OBSERVE_SEL_FS_K	UTMIP_DPDM_OBSERVE_SEL(0xe)
-#define   UTMIP_DPDM_OBSERVE_SEL_FS_SE1 UTMIP_DPDM_OBSERVE_SEL(0xd)
-#define   UTMIP_DPDM_OBSERVE_SEL_FS_SE0 UTMIP_DPDM_OBSERVE_SEL(0xc)
-#define   UTMIP_SUSPEND_EXIT_ON_EDGE	(1 << 22)
-
-#define UTMIP_MISC_CFG1		0x828
-#define   UTMIP_PLL_ACTIVE_DLY_COUNT(x)	(((x) & 0x1f) << 18)
-#define   UTMIP_PLLU_STABLE_COUNT(x)	(((x) & 0xfff) << 6)
-
-#define UTMIP_DEBOUNCE_CFG0	0x82c
-#define   UTMIP_BIAS_DEBOUNCE_A(x)	(((x) & 0xffff) << 0)
-
-#define UTMIP_BAT_CHRG_CFG0	0x830
-#define   UTMIP_PD_CHRG			(1 << 0)
-
-#define UTMIP_SPARE_CFG0	0x834
-#define   FUSE_SETUP_SEL		(1 << 3)
-
-#define UTMIP_XCVR_CFG1		0x838
-#define   UTMIP_FORCE_PDDISC_POWERDOWN	(1 << 0)
-#define   UTMIP_FORCE_PDCHRP_POWERDOWN	(1 << 2)
-#define   UTMIP_FORCE_PDDR_POWERDOWN	(1 << 4)
-#define   UTMIP_XCVR_TERM_RANGE_ADJ(x)	(((x) & 0xf) << 18)
-
-#define UTMIP_BIAS_CFG1		0x83c
-#define   UTMIP_BIAS_PDTRK_COUNT(x)	(((x) & 0x1f) << 3)
-
-static DEFINE_SPINLOCK(utmip_pad_lock);
-static int utmip_pad_count;
-
-struct tegra_xtal_freq {
-	int freq;
-	u8 enable_delay;
-	u8 stable_count;
-	u8 active_delay;
-	u8 xtal_freq_count;
-	u16 debounce;
-};
-
-static const struct tegra_xtal_freq tegra_freq_table[] = {
-	{
-		.freq = 12000000,
-		.enable_delay = 0x02,
-		.stable_count = 0x2F,
-		.active_delay = 0x04,
-		.xtal_freq_count = 0x76,
-		.debounce = 0x7530,
-	},
-	{
-		.freq = 13000000,
-		.enable_delay = 0x02,
-		.stable_count = 0x33,
-		.active_delay = 0x05,
-		.xtal_freq_count = 0x7F,
-		.debounce = 0x7EF4,
-	},
-	{
-		.freq = 19200000,
-		.enable_delay = 0x03,
-		.stable_count = 0x4B,
-		.active_delay = 0x06,
-		.xtal_freq_count = 0xBB,
-		.debounce = 0xBB80,
-	},
-	{
-		.freq = 26000000,
-		.enable_delay = 0x04,
-		.stable_count = 0x66,
-		.active_delay = 0x09,
-		.xtal_freq_count = 0xFE,
-		.debounce = 0xFDE8,
-	},
-};
-
-static struct tegra_utmip_config utmip_default[] = {
-	[0] = {
-		.hssync_start_delay = 9,
-		.idle_wait_delay = 17,
-		.elastic_limit = 16,
-		.term_range_adj = 6,
-		.xcvr_setup = 9,
-		.xcvr_lsfslew = 1,
-		.xcvr_lsrslew = 1,
-	},
-	[2] = {
-		.hssync_start_delay = 9,
-		.idle_wait_delay = 17,
-		.elastic_limit = 16,
-		.term_range_adj = 6,
-		.xcvr_setup = 9,
-		.xcvr_lsfslew = 2,
-		.xcvr_lsrslew = 2,
-	},
-};
-
-static int utmip_pad_open(struct tegra_usb_phy *phy)
-{
-	phy->pad_clk = clk_get_sys("utmip-pad", NULL);
-	if (IS_ERR(phy->pad_clk)) {
-		pr_err("%s: can't get utmip pad clock\n", __func__);
-		return PTR_ERR(phy->pad_clk);
-	}
-
-	if (phy->is_legacy_phy) {
-		phy->pad_regs = phy->regs;
-	} else {
-		phy->pad_regs = ioremap(TEGRA_USB_BASE, TEGRA_USB_SIZE);
-		if (!phy->pad_regs) {
-			pr_err("%s: can't remap usb registers\n", __func__);
-			clk_put(phy->pad_clk);
-			return -ENOMEM;
-		}
-	}
-	return 0;
-}
-
-static void utmip_pad_close(struct tegra_usb_phy *phy)
-{
-	if (!phy->is_legacy_phy)
-		iounmap(phy->pad_regs);
-	clk_put(phy->pad_clk);
-}
-
-static void utmip_pad_power_on(struct tegra_usb_phy *phy)
-{
-	unsigned long val, flags;
-	void __iomem *base = phy->pad_regs;
-
-	clk_prepare_enable(phy->pad_clk);
-
-	spin_lock_irqsave(&utmip_pad_lock, flags);
-
-	if (utmip_pad_count++ == 0) {
-		val = readl(base + UTMIP_BIAS_CFG0);
-		val &= ~(UTMIP_OTGPD | UTMIP_BIASPD);
-		writel(val, base + UTMIP_BIAS_CFG0);
-	}
-
-	spin_unlock_irqrestore(&utmip_pad_lock, flags);
-
-	clk_disable_unprepare(phy->pad_clk);
-}
-
-static int utmip_pad_power_off(struct tegra_usb_phy *phy)
-{
-	unsigned long val, flags;
-	void __iomem *base = phy->pad_regs;
-
-	if (!utmip_pad_count) {
-		pr_err("%s: utmip pad already powered off\n", __func__);
-		return -EINVAL;
-	}
-
-	clk_prepare_enable(phy->pad_clk);
-
-	spin_lock_irqsave(&utmip_pad_lock, flags);
-
-	if (--utmip_pad_count == 0) {
-		val = readl(base + UTMIP_BIAS_CFG0);
-		val |= UTMIP_OTGPD | UTMIP_BIASPD;
-		writel(val, base + UTMIP_BIAS_CFG0);
-	}
-
-	spin_unlock_irqrestore(&utmip_pad_lock, flags);
-
-	clk_disable_unprepare(phy->pad_clk);
-
-	return 0;
-}
-
-static int utmi_wait_register(void __iomem *reg, u32 mask, u32 result)
-{
-	unsigned long timeout = 2000;
-	do {
-		if ((readl(reg) & mask) == result)
-			return 0;
-		udelay(1);
-		timeout--;
-	} while (timeout);
-	return -1;
-}
-
-static void utmi_phy_clk_disable(struct tegra_usb_phy *phy)
-{
-	unsigned long val;
-	void __iomem *base = phy->regs;
-
-	if (phy->is_legacy_phy) {
-		val = readl(base + USB_SUSP_CTRL);
-		val |= USB_SUSP_SET;
-		writel(val, base + USB_SUSP_CTRL);
-
-		udelay(10);
-
-		val = readl(base + USB_SUSP_CTRL);
-		val &= ~USB_SUSP_SET;
-		writel(val, base + USB_SUSP_CTRL);
-	} else
-		tegra_ehci_set_phcd(&phy->u_phy, true);
-
-	if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, 0) < 0)
-		pr_err("%s: timeout waiting for phy to stabilize\n", __func__);
-}
-
-static void utmi_phy_clk_enable(struct tegra_usb_phy *phy)
-{
-	unsigned long val;
-	void __iomem *base = phy->regs;
-
-	if (phy->is_legacy_phy) {
-		val = readl(base + USB_SUSP_CTRL);
-		val |= USB_SUSP_CLR;
-		writel(val, base + USB_SUSP_CTRL);
-
-		udelay(10);
-
-		val = readl(base + USB_SUSP_CTRL);
-		val &= ~USB_SUSP_CLR;
-		writel(val, base + USB_SUSP_CTRL);
-	} else
-		tegra_ehci_set_phcd(&phy->u_phy, false);
-
-	if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID,
-						     USB_PHY_CLK_VALID))
-		pr_err("%s: timeout waiting for phy to stabilize\n", __func__);
-}
-
-static int utmi_phy_power_on(struct tegra_usb_phy *phy)
-{
-	unsigned long val;
-	void __iomem *base = phy->regs;
-	struct tegra_utmip_config *config = phy->config;
-
-	val = readl(base + USB_SUSP_CTRL);
-	val |= UTMIP_RESET;
-	writel(val, base + USB_SUSP_CTRL);
-
-	if (phy->is_legacy_phy) {
-		val = readl(base + USB1_LEGACY_CTRL);
-		val |= USB1_NO_LEGACY_MODE;
-		writel(val, base + USB1_LEGACY_CTRL);
-	}
-
-	val = readl(base + UTMIP_TX_CFG0);
-	val &= ~UTMIP_FS_PREABMLE_J;
-	writel(val, base + UTMIP_TX_CFG0);
-
-	val = readl(base + UTMIP_HSRX_CFG0);
-	val &= ~(UTMIP_IDLE_WAIT(~0) | UTMIP_ELASTIC_LIMIT(~0));
-	val |= UTMIP_IDLE_WAIT(config->idle_wait_delay);
-	val |= UTMIP_ELASTIC_LIMIT(config->elastic_limit);
-	writel(val, base + UTMIP_HSRX_CFG0);
-
-	val = readl(base + UTMIP_HSRX_CFG1);
-	val &= ~UTMIP_HS_SYNC_START_DLY(~0);
-	val |= UTMIP_HS_SYNC_START_DLY(config->hssync_start_delay);
-	writel(val, base + UTMIP_HSRX_CFG1);
-
-	val = readl(base + UTMIP_DEBOUNCE_CFG0);
-	val &= ~UTMIP_BIAS_DEBOUNCE_A(~0);
-	val |= UTMIP_BIAS_DEBOUNCE_A(phy->freq->debounce);
-	writel(val, base + UTMIP_DEBOUNCE_CFG0);
-
-	val = readl(base + UTMIP_MISC_CFG0);
-	val &= ~UTMIP_SUSPEND_EXIT_ON_EDGE;
-	writel(val, base + UTMIP_MISC_CFG0);
-
-	val = readl(base + UTMIP_MISC_CFG1);
-	val &= ~(UTMIP_PLL_ACTIVE_DLY_COUNT(~0) | UTMIP_PLLU_STABLE_COUNT(~0));
-	val |= UTMIP_PLL_ACTIVE_DLY_COUNT(phy->freq->active_delay) |
-		UTMIP_PLLU_STABLE_COUNT(phy->freq->stable_count);
-	writel(val, base + UTMIP_MISC_CFG1);
-
-	val = readl(base + UTMIP_PLL_CFG1);
-	val &= ~(UTMIP_XTAL_FREQ_COUNT(~0) | UTMIP_PLLU_ENABLE_DLY_COUNT(~0));
-	val |= UTMIP_XTAL_FREQ_COUNT(phy->freq->xtal_freq_count) |
-		UTMIP_PLLU_ENABLE_DLY_COUNT(phy->freq->enable_delay);
-	writel(val, base + UTMIP_PLL_CFG1);
-
-	if (phy->mode == TEGRA_USB_PHY_MODE_DEVICE) {
-		val = readl(base + USB_SUSP_CTRL);
-		val &= ~(USB_WAKE_ON_CNNT_EN_DEV | USB_WAKE_ON_DISCON_EN_DEV);
-		writel(val, base + USB_SUSP_CTRL);
-	}
-
-	utmip_pad_power_on(phy);
-
-	val = readl(base + UTMIP_XCVR_CFG0);
-	val &= ~(UTMIP_FORCE_PD_POWERDOWN | UTMIP_FORCE_PD2_POWERDOWN |
-		 UTMIP_FORCE_PDZI_POWERDOWN | UTMIP_XCVR_SETUP(~0) |
-		 UTMIP_XCVR_LSFSLEW(~0) | UTMIP_XCVR_LSRSLEW(~0) |
-		 UTMIP_XCVR_HSSLEW_MSB(~0));
-	val |= UTMIP_XCVR_SETUP(config->xcvr_setup);
-	val |= UTMIP_XCVR_LSFSLEW(config->xcvr_lsfslew);
-	val |= UTMIP_XCVR_LSRSLEW(config->xcvr_lsrslew);
-	writel(val, base + UTMIP_XCVR_CFG0);
-
-	val = readl(base + UTMIP_XCVR_CFG1);
-	val &= ~(UTMIP_FORCE_PDDISC_POWERDOWN | UTMIP_FORCE_PDCHRP_POWERDOWN |
-		 UTMIP_FORCE_PDDR_POWERDOWN | UTMIP_XCVR_TERM_RANGE_ADJ(~0));
-	val |= UTMIP_XCVR_TERM_RANGE_ADJ(config->term_range_adj);
-	writel(val, base + UTMIP_XCVR_CFG1);
-
-	val = readl(base + UTMIP_BAT_CHRG_CFG0);
-	val &= ~UTMIP_PD_CHRG;
-	writel(val, base + UTMIP_BAT_CHRG_CFG0);
-
-	val = readl(base + UTMIP_BIAS_CFG1);
-	val &= ~UTMIP_BIAS_PDTRK_COUNT(~0);
-	val |= UTMIP_BIAS_PDTRK_COUNT(0x5);
-	writel(val, base + UTMIP_BIAS_CFG1);
-
-	if (phy->is_legacy_phy) {
-		val = readl(base + UTMIP_SPARE_CFG0);
-		if (phy->mode == TEGRA_USB_PHY_MODE_DEVICE)
-			val &= ~FUSE_SETUP_SEL;
-		else
-			val |= FUSE_SETUP_SEL;
-		writel(val, base + UTMIP_SPARE_CFG0);
-	} else {
-		val = readl(base + USB_SUSP_CTRL);
-		val |= UTMIP_PHY_ENABLE;
-		writel(val, base + USB_SUSP_CTRL);
-	}
-
-	val = readl(base + USB_SUSP_CTRL);
-	val &= ~UTMIP_RESET;
-	writel(val, base + USB_SUSP_CTRL);
-
-	if (phy->is_legacy_phy) {
-		val = readl(base + USB1_LEGACY_CTRL);
-		val &= ~USB1_VBUS_SENSE_CTL_MASK;
-		val |= USB1_VBUS_SENSE_CTL_A_SESS_VLD;
-		writel(val, base + USB1_LEGACY_CTRL);
-
-		val = readl(base + USB_SUSP_CTRL);
-		val &= ~USB_SUSP_SET;
-		writel(val, base + USB_SUSP_CTRL);
-	}
-
-	utmi_phy_clk_enable(phy);
-
-	if (!phy->is_legacy_phy)
-		tegra_ehci_set_pts(&phy->u_phy, 0);
-
-	return 0;
-}
-
-static int utmi_phy_power_off(struct tegra_usb_phy *phy)
-{
-	unsigned long val;
-	void __iomem *base = phy->regs;
-
-	utmi_phy_clk_disable(phy);
-
-	if (phy->mode == TEGRA_USB_PHY_MODE_DEVICE) {
-		val = readl(base + USB_SUSP_CTRL);
-		val &= ~USB_WAKEUP_DEBOUNCE_COUNT(~0);
-		val |= USB_WAKE_ON_CNNT_EN_DEV | USB_WAKEUP_DEBOUNCE_COUNT(5);
-		writel(val, base + USB_SUSP_CTRL);
-	}
-
-	val = readl(base + USB_SUSP_CTRL);
-	val |= UTMIP_RESET;
-	writel(val, base + USB_SUSP_CTRL);
-
-	val = readl(base + UTMIP_BAT_CHRG_CFG0);
-	val |= UTMIP_PD_CHRG;
-	writel(val, base + UTMIP_BAT_CHRG_CFG0);
-
-	val = readl(base + UTMIP_XCVR_CFG0);
-	val |= UTMIP_FORCE_PD_POWERDOWN | UTMIP_FORCE_PD2_POWERDOWN |
-	       UTMIP_FORCE_PDZI_POWERDOWN;
-	writel(val, base + UTMIP_XCVR_CFG0);
-
-	val = readl(base + UTMIP_XCVR_CFG1);
-	val |= UTMIP_FORCE_PDDISC_POWERDOWN | UTMIP_FORCE_PDCHRP_POWERDOWN |
-	       UTMIP_FORCE_PDDR_POWERDOWN;
-	writel(val, base + UTMIP_XCVR_CFG1);
-
-	return utmip_pad_power_off(phy);
-}
-
-static void utmi_phy_preresume(struct tegra_usb_phy *phy)
-{
-	unsigned long val;
-	void __iomem *base = phy->regs;
-
-	val = readl(base + UTMIP_TX_CFG0);
-	val |= UTMIP_HS_DISCON_DISABLE;
-	writel(val, base + UTMIP_TX_CFG0);
-}
-
-static void utmi_phy_postresume(struct tegra_usb_phy *phy)
-{
-	unsigned long val;
-	void __iomem *base = phy->regs;
-
-	val = readl(base + UTMIP_TX_CFG0);
-	val &= ~UTMIP_HS_DISCON_DISABLE;
-	writel(val, base + UTMIP_TX_CFG0);
-}
-
-static void utmi_phy_restore_start(struct tegra_usb_phy *phy,
-				   enum tegra_usb_phy_port_speed port_speed)
-{
-	unsigned long val;
-	void __iomem *base = phy->regs;
-
-	val = readl(base + UTMIP_MISC_CFG0);
-	val &= ~UTMIP_DPDM_OBSERVE_SEL(~0);
-	if (port_speed == TEGRA_USB_PHY_PORT_SPEED_LOW)
-		val |= UTMIP_DPDM_OBSERVE_SEL_FS_K;
-	else
-		val |= UTMIP_DPDM_OBSERVE_SEL_FS_J;
-	writel(val, base + UTMIP_MISC_CFG0);
-	udelay(1);
-
-	val = readl(base + UTMIP_MISC_CFG0);
-	val |= UTMIP_DPDM_OBSERVE;
-	writel(val, base + UTMIP_MISC_CFG0);
-	udelay(10);
-}
-
-static void utmi_phy_restore_end(struct tegra_usb_phy *phy)
-{
-	unsigned long val;
-	void __iomem *base = phy->regs;
-
-	val = readl(base + UTMIP_MISC_CFG0);
-	val &= ~UTMIP_DPDM_OBSERVE;
-	writel(val, base + UTMIP_MISC_CFG0);
-	udelay(10);
-}
-
-static int ulpi_phy_power_on(struct tegra_usb_phy *phy)
-{
-	int ret;
-	unsigned long val;
-	void __iomem *base = phy->regs;
-	struct tegra_ulpi_config *config = phy->config;
-
-	gpio_direction_output(config->reset_gpio, 0);
-	msleep(5);
-	gpio_direction_output(config->reset_gpio, 1);
-
-	clk_prepare_enable(phy->clk);
-	msleep(1);
-
-	val = readl(base + USB_SUSP_CTRL);
-	val |= UHSIC_RESET;
-	writel(val, base + USB_SUSP_CTRL);
-
-	val = readl(base + ULPI_TIMING_CTRL_0);
-	val |= ULPI_OUTPUT_PINMUX_BYP | ULPI_CLKOUT_PINMUX_BYP;
-	writel(val, base + ULPI_TIMING_CTRL_0);
-
-	val = readl(base + USB_SUSP_CTRL);
-	val |= ULPI_PHY_ENABLE;
-	writel(val, base + USB_SUSP_CTRL);
-
-	val = 0;
-	writel(val, base + ULPI_TIMING_CTRL_1);
-
-	val |= ULPI_DATA_TRIMMER_SEL(4);
-	val |= ULPI_STPDIRNXT_TRIMMER_SEL(4);
-	val |= ULPI_DIR_TRIMMER_SEL(4);
-	writel(val, base + ULPI_TIMING_CTRL_1);
-	udelay(10);
-
-	val |= ULPI_DATA_TRIMMER_LOAD;
-	val |= ULPI_STPDIRNXT_TRIMMER_LOAD;
-	val |= ULPI_DIR_TRIMMER_LOAD;
-	writel(val, base + ULPI_TIMING_CTRL_1);
-
-	/* Fix VbusInvalid due to floating VBUS */
-	ret = usb_phy_io_write(phy->ulpi, 0x40, 0x08);
-	if (ret) {
-		pr_err("%s: ulpi write failed\n", __func__);
-		return ret;
-	}
-
-	ret = usb_phy_io_write(phy->ulpi, 0x80, 0x0B);
-	if (ret) {
-		pr_err("%s: ulpi write failed\n", __func__);
-		return ret;
-	}
-
-	val = readl(base + USB_SUSP_CTRL);
-	val |= USB_SUSP_CLR;
-	writel(val, base + USB_SUSP_CTRL);
-	udelay(100);
-
-	val = readl(base + USB_SUSP_CTRL);
-	val &= ~USB_SUSP_CLR;
-	writel(val, base + USB_SUSP_CTRL);
-
-	return 0;
-}
-
-static int ulpi_phy_power_off(struct tegra_usb_phy *phy)
-{
-	struct tegra_ulpi_config *config = phy->config;
-
-	clk_disable(phy->clk);
-	return gpio_direction_output(config->reset_gpio, 0);
-}
-
-static int	tegra_phy_init(struct usb_phy *x)
-{
-	struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy);
-	struct tegra_ulpi_config *ulpi_config;
-	int err;
-
-	if (phy->is_ulpi_phy) {
-		ulpi_config = phy->config;
-		phy->clk = clk_get_sys(NULL, ulpi_config->clk);
-		if (IS_ERR(phy->clk)) {
-			pr_err("%s: can't get ulpi clock\n", __func__);
-			err = -ENXIO;
-			goto err1;
-		}
-		if (!gpio_is_valid(ulpi_config->reset_gpio))
-			ulpi_config->reset_gpio =
-				of_get_named_gpio(phy->dev->of_node,
-						  "nvidia,phy-reset-gpio", 0);
-		if (!gpio_is_valid(ulpi_config->reset_gpio)) {
-			pr_err("%s: invalid reset gpio: %d\n", __func__,
-			       ulpi_config->reset_gpio);
-			err = -EINVAL;
-			goto err1;
-		}
-		gpio_request(ulpi_config->reset_gpio, "ulpi_phy_reset_b");
-		gpio_direction_output(ulpi_config->reset_gpio, 0);
-		phy->ulpi = otg_ulpi_create(&ulpi_viewport_access_ops, 0);
-		phy->ulpi->io_priv = phy->regs + ULPI_VIEWPORT;
-	} else {
-		err = utmip_pad_open(phy);
-		if (err < 0)
-			goto err1;
-	}
-	return 0;
-err1:
-	clk_disable_unprepare(phy->pll_u);
-	clk_put(phy->pll_u);
-	return err;
-}
-
-static void tegra_usb_phy_close(struct usb_phy *x)
-{
-	struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy);
-
-	if (phy->is_ulpi_phy)
-		clk_put(phy->clk);
-	else
-		utmip_pad_close(phy);
-	clk_disable_unprepare(phy->pll_u);
-	clk_put(phy->pll_u);
-	kfree(phy);
-}
-
-static int tegra_usb_phy_power_on(struct tegra_usb_phy *phy)
-{
-	if (phy->is_ulpi_phy)
-		return ulpi_phy_power_on(phy);
-	else
-		return utmi_phy_power_on(phy);
-}
-
-static int tegra_usb_phy_power_off(struct tegra_usb_phy *phy)
-{
-	if (phy->is_ulpi_phy)
-		return ulpi_phy_power_off(phy);
-	else
-		return utmi_phy_power_off(phy);
-}
-
-static int	tegra_usb_phy_suspend(struct usb_phy *x, int suspend)
-{
-	struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy);
-	if (suspend)
-		return tegra_usb_phy_power_off(phy);
-	else
-		return tegra_usb_phy_power_on(phy);
-}
-
-struct tegra_usb_phy *tegra_usb_phy_open(struct device *dev, int instance,
-	void __iomem *regs, void *config, enum tegra_usb_phy_mode phy_mode)
-{
-	struct tegra_usb_phy *phy;
-	unsigned long parent_rate;
-	int i;
-	int err;
-	struct device_node *np = dev->of_node;
-
-	phy = kzalloc(sizeof(struct tegra_usb_phy), GFP_KERNEL);
-	if (!phy)
-		return ERR_PTR(-ENOMEM);
-
-	phy->instance = instance;
-	phy->regs = regs;
-	phy->config = config;
-	phy->mode = phy_mode;
-	phy->dev = dev;
-	phy->is_legacy_phy =
-		of_property_read_bool(np, "nvidia,has-legacy-mode");
-	err = of_property_match_string(np, "phy_type", "ulpi");
-	if (err < 0)
-		phy->is_ulpi_phy = false;
-	else
-		phy->is_ulpi_phy = true;
-
-	if (!phy->config) {
-		if (phy->is_ulpi_phy) {
-			pr_err("%s: ulpi phy configuration missing", __func__);
-			err = -EINVAL;
-			goto err0;
-		} else {
-			phy->config = &utmip_default[instance];
-		}
-	}
-
-	phy->pll_u = clk_get_sys(NULL, "pll_u");
-	if (IS_ERR(phy->pll_u)) {
-		pr_err("Can't get pll_u clock\n");
-		err = PTR_ERR(phy->pll_u);
-		goto err0;
-	}
-	clk_prepare_enable(phy->pll_u);
-
-	parent_rate = clk_get_rate(clk_get_parent(phy->pll_u));
-	for (i = 0; i < ARRAY_SIZE(tegra_freq_table); i++) {
-		if (tegra_freq_table[i].freq == parent_rate) {
-			phy->freq = &tegra_freq_table[i];
-			break;
-		}
-	}
-	if (!phy->freq) {
-		pr_err("invalid pll_u parent rate %ld\n", parent_rate);
-		err = -EINVAL;
-		goto err1;
-	}
-
-	phy->u_phy.init = tegra_phy_init;
-	phy->u_phy.shutdown = tegra_usb_phy_close;
-	phy->u_phy.set_suspend = tegra_usb_phy_suspend;
-
-	return phy;
-
-err1:
-	clk_disable_unprepare(phy->pll_u);
-	clk_put(phy->pll_u);
-err0:
-	kfree(phy);
-	return ERR_PTR(err);
-}
-EXPORT_SYMBOL_GPL(tegra_usb_phy_open);
-
-void tegra_usb_phy_preresume(struct usb_phy *x)
-{
-	struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy);
-
-	if (!phy->is_ulpi_phy)
-		utmi_phy_preresume(phy);
-}
-EXPORT_SYMBOL_GPL(tegra_usb_phy_preresume);
-
-void tegra_usb_phy_postresume(struct usb_phy *x)
-{
-	struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy);
-
-	if (!phy->is_ulpi_phy)
-		utmi_phy_postresume(phy);
-}
-EXPORT_SYMBOL_GPL(tegra_usb_phy_postresume);
-
-void tegra_ehci_phy_restore_start(struct usb_phy *x,
-				 enum tegra_usb_phy_port_speed port_speed)
-{
-	struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy);
-
-	if (!phy->is_ulpi_phy)
-		utmi_phy_restore_start(phy, port_speed);
-}
-EXPORT_SYMBOL_GPL(tegra_ehci_phy_restore_start);
-
-void tegra_ehci_phy_restore_end(struct usb_phy *x)
-{
-	struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy);
-
-	if (!phy->is_ulpi_phy)
-		utmi_phy_restore_end(phy);
-}
-EXPORT_SYMBOL_GPL(tegra_ehci_phy_restore_end);
-
diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c
index 9538f0f..45b9401 100644
--- a/drivers/usb/renesas_usbhs/fifo.c
+++ b/drivers/usb/renesas_usbhs/fifo.c
@@ -32,7 +32,6 @@
  */
 void usbhs_pkt_init(struct usbhs_pkt *pkt)
 {
-	pkt->dma = DMA_ADDR_INVALID;
 	INIT_LIST_HEAD(&pkt->node);
 }
 
diff --git a/drivers/usb/renesas_usbhs/fifo.h b/drivers/usb/renesas_usbhs/fifo.h
index c31731a..a168a17 100644
--- a/drivers/usb/renesas_usbhs/fifo.h
+++ b/drivers/usb/renesas_usbhs/fifo.h
@@ -23,8 +23,6 @@
 #include <asm/dma.h>
 #include "pipe.h"
 
-#define	DMA_ADDR_INVALID	(~(dma_addr_t)0)
-
 struct usbhs_fifo {
 	char *name;
 	u32 port;	/* xFIFO */
diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c
index 78fca97..ed4949f 100644
--- a/drivers/usb/renesas_usbhs/mod_gadget.c
+++ b/drivers/usb/renesas_usbhs/mod_gadget.c
@@ -230,7 +230,7 @@ static int usbhsg_recip_handler_std_clear_endpoint(struct usbhs_priv *priv,
 	return 0;
 }
 
-struct usbhsg_recip_handle req_clear_feature = {
+static struct usbhsg_recip_handle req_clear_feature = {
 	.name		= "clear feature",
 	.device		= usbhsg_recip_handler_std_control_done,
 	.interface	= usbhsg_recip_handler_std_control_done,
@@ -271,7 +271,7 @@ static int usbhsg_recip_handler_std_set_endpoint(struct usbhs_priv *priv,
 	return 0;
 }
 
-struct usbhsg_recip_handle req_set_feature = {
+static struct usbhsg_recip_handle req_set_feature = {
 	.name		= "set feature",
 	.device		= usbhsg_recip_handler_std_set_device,
 	.interface	= usbhsg_recip_handler_std_control_done,
@@ -372,7 +372,7 @@ static int usbhsg_recip_handler_std_get_endpoint(struct usbhs_priv *priv,
 	return 0;
 }
 
-struct usbhsg_recip_handle req_get_status = {
+static struct usbhsg_recip_handle req_get_status = {
 	.name		= "get status",
 	.device		= usbhsg_recip_handler_std_get_device,
 	.interface	= usbhsg_recip_handler_std_get_interface,
@@ -845,7 +845,6 @@ static int usbhsg_gadget_start(struct usb_gadget *gadget,
 
 	/* first hook up the driver ... */
 	gpriv->driver = driver;
-	gpriv->gadget.dev.driver = &driver->driver;
 
 	return usbhsg_try_start(priv, USBHSG_STATUS_REGISTERD);
 }
@@ -861,7 +860,6 @@ static int usbhsg_gadget_stop(struct usb_gadget *gadget,
 		return -EINVAL;
 
 	usbhsg_try_stop(priv, USBHSG_STATUS_REGISTERD);
-	gpriv->gadget.dev.driver = NULL;
 	gpriv->driver = NULL;
 
 	return 0;
@@ -925,11 +923,6 @@ static int usbhsg_stop(struct usbhs_priv *priv)
 	return usbhsg_try_stop(priv, USBHSG_STATUS_STARTED);
 }
 
-static void usbhs_mod_gadget_release(struct device *pdev)
-{
-	/* do nothing */
-}
-
 int usbhs_mod_gadget_probe(struct usbhs_priv *priv)
 {
 	struct usbhsg_gpriv *gpriv;
@@ -976,15 +969,10 @@ int usbhs_mod_gadget_probe(struct usbhs_priv *priv)
 	/*
 	 * init gadget
 	 */
-	dev_set_name(&gpriv->gadget.dev, "gadget");
 	gpriv->gadget.dev.parent	= dev;
-	gpriv->gadget.dev.release	= usbhs_mod_gadget_release;
 	gpriv->gadget.name		= "renesas_usbhs_udc";
 	gpriv->gadget.ops		= &usbhsg_gadget_ops;
 	gpriv->gadget.max_speed		= USB_SPEED_HIGH;
-	ret = device_register(&gpriv->gadget.dev);
-	if (ret < 0)
-		goto err_add_udc;
 
 	INIT_LIST_HEAD(&gpriv->gadget.ep_list);
 
@@ -1014,15 +1002,13 @@ int usbhs_mod_gadget_probe(struct usbhs_priv *priv)
 
 	ret = usb_add_gadget_udc(dev, &gpriv->gadget);
 	if (ret)
-		goto err_register;
+		goto err_add_udc;
 
 
 	dev_info(dev, "gadget probed\n");
 
 	return 0;
 
-err_register:
-	device_unregister(&gpriv->gadget.dev);
 err_add_udc:
 	kfree(gpriv->uep);
 
@@ -1038,8 +1024,6 @@ void usbhs_mod_gadget_remove(struct usbhs_priv *priv)
 
 	usb_del_gadget_udc(&gpriv->gadget);
 
-	device_unregister(&gpriv->gadget.dev);
-
 	kfree(gpriv->uep);
 	kfree(gpriv);
 }
diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c
index 4775f82..3b16118 100644
--- a/drivers/usb/serial/ark3116.c
+++ b/drivers/usb/serial/ark3116.c
@@ -62,7 +62,6 @@ static int is_irda(struct usb_serial *serial)
 }
 
 struct ark3116_private {
-	struct async_icount	icount;
 	int			irda;	/* 1 for irda device */
 
 	/* protects hw register updates */
@@ -341,18 +340,15 @@ static void ark3116_close(struct usb_serial_port *port)
 {
 	struct usb_serial *serial = port->serial;
 
-	if (serial->dev) {
-		/* disable DMA */
-		ark3116_write_reg(serial, UART_FCR, 0);
-
-		/* deactivate interrupts */
-		ark3116_write_reg(serial, UART_IER, 0);
+	/* disable DMA */
+	ark3116_write_reg(serial, UART_FCR, 0);
 
-		usb_serial_generic_close(port);
-		if (serial->num_interrupt_in)
-			usb_kill_urb(port->interrupt_in_urb);
-	}
+	/* deactivate interrupts */
+	ark3116_write_reg(serial, UART_IER, 0);
 
+	usb_serial_generic_close(port);
+	if (serial->num_interrupt_in)
+		usb_kill_urb(port->interrupt_in_urb);
 }
 
 static int ark3116_open(struct tty_struct *tty, struct usb_serial_port *port)
@@ -405,31 +401,10 @@ err_out:
 	return result;
 }
 
-static int ark3116_get_icount(struct tty_struct *tty,
-					struct serial_icounter_struct *icount)
-{
-	struct usb_serial_port *port = tty->driver_data;
-	struct ark3116_private *priv = usb_get_serial_port_data(port);
-	struct async_icount cnow = priv->icount;
-	icount->cts = cnow.cts;
-	icount->dsr = cnow.dsr;
-	icount->rng = cnow.rng;
-	icount->dcd = cnow.dcd;
-	icount->rx = cnow.rx;
-	icount->tx = cnow.tx;
-	icount->frame = cnow.frame;
-	icount->overrun = cnow.overrun;
-	icount->parity = cnow.parity;
-	icount->brk = cnow.brk;
-	icount->buf_overrun = cnow.buf_overrun;
-	return 0;
-}
-
 static int ark3116_ioctl(struct tty_struct *tty,
 			 unsigned int cmd, unsigned long arg)
 {
 	struct usb_serial_port *port = tty->driver_data;
-	struct ark3116_private *priv = usb_get_serial_port_data(port);
 	struct serial_struct serstruct;
 	void __user *user_arg = (void __user *)arg;
 
@@ -451,33 +426,6 @@ static int ark3116_ioctl(struct tty_struct *tty,
 		if (copy_from_user(&serstruct, user_arg, sizeof(serstruct)))
 			return -EFAULT;
 		return 0;
-	case TIOCMIWAIT:
-		for (;;) {
-			struct async_icount prev = priv->icount;
-			interruptible_sleep_on(&port->delta_msr_wait);
-			/* see if a signal did it */
-			if (signal_pending(current))
-				return -ERESTARTSYS;
-
-			if (port->serial->disconnected)
-				return -EIO;
-
-			if ((prev.rng == priv->icount.rng) &&
-			    (prev.dsr == priv->icount.dsr) &&
-			    (prev.dcd == priv->icount.dcd) &&
-			    (prev.cts == priv->icount.cts))
-				return -EIO;
-			if ((arg & TIOCM_RNG &&
-			     (prev.rng != priv->icount.rng)) ||
-			    (arg & TIOCM_DSR &&
-			     (prev.dsr != priv->icount.dsr)) ||
-			    (arg & TIOCM_CD  &&
-			     (prev.dcd != priv->icount.dcd)) ||
-			    (arg & TIOCM_CTS &&
-			     (prev.cts != priv->icount.cts)))
-				return 0;
-		}
-		break;
 	}
 
 	return -ENOIOCTLCMD;
@@ -575,14 +523,14 @@ static void ark3116_update_msr(struct usb_serial_port *port, __u8 msr)
 	if (msr & UART_MSR_ANY_DELTA) {
 		/* update input line counters */
 		if (msr & UART_MSR_DCTS)
-			priv->icount.cts++;
+			port->icount.cts++;
 		if (msr & UART_MSR_DDSR)
-			priv->icount.dsr++;
+			port->icount.dsr++;
 		if (msr & UART_MSR_DDCD)
-			priv->icount.dcd++;
+			port->icount.dcd++;
 		if (msr & UART_MSR_TERI)
-			priv->icount.rng++;
-		wake_up_interruptible(&port->delta_msr_wait);
+			port->icount.rng++;
+		wake_up_interruptible(&port->port.delta_msr_wait);
 	}
 }
 
@@ -598,13 +546,13 @@ static void ark3116_update_lsr(struct usb_serial_port *port, __u8 lsr)
 
 	if (lsr&UART_LSR_BRK_ERROR_BITS) {
 		if (lsr & UART_LSR_BI)
-			priv->icount.brk++;
+			port->icount.brk++;
 		if (lsr & UART_LSR_FE)
-			priv->icount.frame++;
+			port->icount.frame++;
 		if (lsr & UART_LSR_PE)
-			priv->icount.parity++;
+			port->icount.parity++;
 		if (lsr & UART_LSR_OE)
-			priv->icount.overrun++;
+			port->icount.overrun++;
 	}
 }
 
@@ -722,7 +670,8 @@ static struct usb_serial_driver ark3116_device = {
 	.ioctl =		ark3116_ioctl,
 	.tiocmget =		ark3116_tiocmget,
 	.tiocmset =		ark3116_tiocmset,
-	.get_icount =		ark3116_get_icount,
+	.tiocmiwait =		usb_serial_generic_tiocmiwait,
+	.get_icount =		usb_serial_generic_get_icount,
 	.open =			ark3116_open,
 	.close =		ark3116_close,
 	.break_ctl = 		ark3116_break_ctl,
diff --git a/drivers/usb/serial/bus.c b/drivers/usb/serial/bus.c
index 37decb1..3c4db6d 100644
--- a/drivers/usb/serial/bus.c
+++ b/drivers/usb/serial/bus.c
@@ -106,14 +106,15 @@ static int usb_serial_device_remove(struct device *dev)
 	/* make sure suspend/resume doesn't race against port_remove */
 	usb_autopm_get_interface(port->serial->interface);
 
+	minor = port->number;
+	tty_unregister_device(usb_serial_tty_driver, minor);
+
 	device_remove_file(&port->dev, &dev_attr_port_number);
 
 	driver = port->serial->type;
 	if (driver->port_remove)
 		retval = driver->port_remove(port);
 
-	minor = port->number;
-	tty_unregister_device(usb_serial_tty_driver, minor);
 	dev_info(dev, "%s converter now disconnected from ttyUSB%d\n",
 		 driver->description, minor);
 
diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c
index 07d4650..c2a4171 100644
--- a/drivers/usb/serial/ch341.c
+++ b/drivers/usb/serial/ch341.c
@@ -296,7 +296,6 @@ static void ch341_dtr_rts(struct usb_serial_port *port, int on)
 		priv->line_control &= ~(CH341_BIT_RTS | CH341_BIT_DTR);
 	spin_unlock_irqrestore(&priv->lock, flags);
 	ch341_set_handshake(port->serial->dev, priv->line_control);
-	wake_up_interruptible(&port->delta_msr_wait);
 }
 
 static void ch341_close(struct usb_serial_port *port)
@@ -489,7 +488,7 @@ static void ch341_read_int_callback(struct urb *urb)
 			tty_kref_put(tty);
 		}
 
-		wake_up_interruptible(&port->delta_msr_wait);
+		wake_up_interruptible(&port->port.delta_msr_wait);
 	}
 
 exit:
@@ -500,8 +499,9 @@ exit:
 			__func__, status);
 }
 
-static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
+static int ch341_tiocmiwait(struct tty_struct *tty, unsigned long arg)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct ch341_private *priv = usb_get_serial_port_data(port);
 	unsigned long flags;
 	u8 prevstatus;
@@ -515,7 +515,7 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	while (!multi_change) {
-		interruptible_sleep_on(&port->delta_msr_wait);
+		interruptible_sleep_on(&port->port.delta_msr_wait);
 		/* see if a signal did it */
 		if (signal_pending(current))
 			return -ERESTARTSYS;
@@ -542,26 +542,6 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
 	return 0;
 }
 
-static int ch341_ioctl(struct tty_struct *tty,
-			unsigned int cmd, unsigned long arg)
-{
-	struct usb_serial_port *port = tty->driver_data;
-
-	dev_dbg(&port->dev, "%s (%d) cmd = 0x%04x\n", __func__, port->number, cmd);
-
-	switch (cmd) {
-	case TIOCMIWAIT:
-		dev_dbg(&port->dev, "%s (%d) TIOCMIWAIT\n", __func__,  port->number);
-		return wait_modem_info(port, arg);
-
-	default:
-		dev_dbg(&port->dev, "%s not supported = 0x%04x\n", __func__, cmd);
-		break;
-	}
-
-	return -ENOIOCTLCMD;
-}
-
 static int ch341_tiocmget(struct tty_struct *tty)
 {
 	struct usb_serial_port *port = tty->driver_data;
@@ -611,11 +591,11 @@ static struct usb_serial_driver ch341_device = {
 	.dtr_rts	   = ch341_dtr_rts,
 	.carrier_raised	   = ch341_carrier_raised,
 	.close             = ch341_close,
-	.ioctl             = ch341_ioctl,
 	.set_termios       = ch341_set_termios,
 	.break_ctl         = ch341_break_ctl,
 	.tiocmget          = ch341_tiocmget,
 	.tiocmset          = ch341_tiocmset,
+	.tiocmiwait        = ch341_tiocmiwait,
 	.read_int_callback = ch341_read_int_callback,
 	.port_probe        = ch341_port_probe,
 	.port_remove       = ch341_port_remove,
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
index 4747d1c..2c65955 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -462,11 +462,7 @@ static int cp210x_open(struct tty_struct *tty, struct usb_serial_port *port)
 static void cp210x_close(struct usb_serial_port *port)
 {
 	usb_serial_generic_close(port);
-
-	mutex_lock(&port->serial->disc_mutex);
-	if (!port->serial->disconnected)
-		cp210x_set_config_single(port, CP210X_IFC_ENABLE, UART_DISABLE);
-	mutex_unlock(&port->serial->disc_mutex);
+	cp210x_set_config_single(port, CP210X_IFC_ENABLE, UART_DISABLE);
 }
 
 /*
diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c
index 629bd28..7814262 100644
--- a/drivers/usb/serial/cyberjack.c
+++ b/drivers/usb/serial/cyberjack.c
@@ -51,7 +51,6 @@
 #define CYBERJACK_PRODUCT_ID	0x0100
 
 /* Function prototypes */
-static void cyberjack_disconnect(struct usb_serial *serial);
 static int cyberjack_port_probe(struct usb_serial_port *port);
 static int cyberjack_port_remove(struct usb_serial_port *port);
 static int  cyberjack_open(struct tty_struct *tty,
@@ -79,7 +78,6 @@ static struct usb_serial_driver cyberjack_device = {
 	.description =		"Reiner SCT Cyberjack USB card reader",
 	.id_table =		id_table,
 	.num_ports =		1,
-	.disconnect =		cyberjack_disconnect,
 	.port_probe =		cyberjack_port_probe,
 	.port_remove =		cyberjack_port_remove,
 	.open =			cyberjack_open,
@@ -130,20 +128,14 @@ static int cyberjack_port_remove(struct usb_serial_port *port)
 {
 	struct cyberjack_private *priv;
 
+	usb_kill_urb(port->interrupt_in_urb);
+
 	priv = usb_get_serial_port_data(port);
 	kfree(priv);
 
 	return 0;
 }
 
-static void cyberjack_disconnect(struct usb_serial *serial)
-{
-	int i;
-
-	for (i = 0; i < serial->num_ports; ++i)
-		usb_kill_urb(serial->port[i]->interrupt_in_urb);
-}
-
 static int  cyberjack_open(struct tty_struct *tty,
 					struct usb_serial_port *port)
 {
@@ -166,11 +158,8 @@ static int  cyberjack_open(struct tty_struct *tty,
 
 static void cyberjack_close(struct usb_serial_port *port)
 {
-	if (port->serial->dev) {
-		/* shutdown any bulk reads that might be going on */
-		usb_kill_urb(port->write_urb);
-		usb_kill_urb(port->read_urb);
-	}
+	usb_kill_urb(port->write_urb);
+	usb_kill_urb(port->read_urb);
 }
 
 static int cyberjack_write(struct tty_struct *tty,
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index ba7352e..d341555 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -129,13 +129,12 @@ static int  cypress_write(struct tty_struct *tty, struct usb_serial_port *port,
 			const unsigned char *buf, int count);
 static void cypress_send(struct usb_serial_port *port);
 static int  cypress_write_room(struct tty_struct *tty);
-static int  cypress_ioctl(struct tty_struct *tty,
-			unsigned int cmd, unsigned long arg);
 static void cypress_set_termios(struct tty_struct *tty,
 			struct usb_serial_port *port, struct ktermios *old);
 static int  cypress_tiocmget(struct tty_struct *tty);
 static int  cypress_tiocmset(struct tty_struct *tty,
 			unsigned int set, unsigned int clear);
+static int  cypress_tiocmiwait(struct tty_struct *tty, unsigned long arg);
 static int  cypress_chars_in_buffer(struct tty_struct *tty);
 static void cypress_throttle(struct tty_struct *tty);
 static void cypress_unthrottle(struct tty_struct *tty);
@@ -158,10 +157,10 @@ static struct usb_serial_driver cypress_earthmate_device = {
 	.dtr_rts =			cypress_dtr_rts,
 	.write =			cypress_write,
 	.write_room =			cypress_write_room,
-	.ioctl =			cypress_ioctl,
 	.set_termios =			cypress_set_termios,
 	.tiocmget =			cypress_tiocmget,
 	.tiocmset =			cypress_tiocmset,
+	.tiocmiwait =			cypress_tiocmiwait,
 	.chars_in_buffer =		cypress_chars_in_buffer,
 	.throttle =		 	cypress_throttle,
 	.unthrottle =			cypress_unthrottle,
@@ -184,10 +183,10 @@ static struct usb_serial_driver cypress_hidcom_device = {
 	.dtr_rts =			cypress_dtr_rts,
 	.write =			cypress_write,
 	.write_room =			cypress_write_room,
-	.ioctl =			cypress_ioctl,
 	.set_termios =			cypress_set_termios,
 	.tiocmget =			cypress_tiocmget,
 	.tiocmset =			cypress_tiocmset,
+	.tiocmiwait =			cypress_tiocmiwait,
 	.chars_in_buffer =		cypress_chars_in_buffer,
 	.throttle =			cypress_throttle,
 	.unthrottle =			cypress_unthrottle,
@@ -210,10 +209,10 @@ static struct usb_serial_driver cypress_ca42v2_device = {
 	.dtr_rts =			cypress_dtr_rts,
 	.write =			cypress_write,
 	.write_room =			cypress_write_room,
-	.ioctl =			cypress_ioctl,
 	.set_termios =			cypress_set_termios,
 	.tiocmget =			cypress_tiocmget,
 	.tiocmset =			cypress_tiocmset,
+	.tiocmiwait =			cypress_tiocmiwait,
 	.chars_in_buffer =		cypress_chars_in_buffer,
 	.throttle =			cypress_throttle,
 	.unthrottle =			cypress_unthrottle,
@@ -633,12 +632,6 @@ static void cypress_close(struct usb_serial_port *port)
 	struct cypress_private *priv = usb_get_serial_port_data(port);
 	unsigned long flags;
 
-	/* writing is potentially harmful, lock must be taken */
-	mutex_lock(&port->serial->disc_mutex);
-	if (port->serial->disconnected) {
-		mutex_unlock(&port->serial->disc_mutex);
-		return;
-	}
 	spin_lock_irqsave(&priv->lock, flags);
 	kfifo_reset_out(&priv->write_fifo);
 	spin_unlock_irqrestore(&priv->lock, flags);
@@ -650,7 +643,6 @@ static void cypress_close(struct usb_serial_port *port)
 	if (stats)
 		dev_info(&port->dev, "Statistics: %d Bytes In | %d Bytes Out | %d Commands Issued\n",
 			priv->bytes_in, priv->bytes_out, priv->cmd_count);
-	mutex_unlock(&port->serial->disc_mutex);
 } /* cypress_close */
 
 
@@ -855,55 +847,43 @@ static int cypress_tiocmset(struct tty_struct *tty,
 }
 
 
-static int cypress_ioctl(struct tty_struct *tty,
-					unsigned int cmd, unsigned long arg)
+static int cypress_tiocmiwait(struct tty_struct *tty, unsigned long arg)
 {
 	struct usb_serial_port *port = tty->driver_data;
 	struct cypress_private *priv = usb_get_serial_port_data(port);
-
-	dev_dbg(&port->dev, "%s - port %d, cmd 0x%.4x\n", __func__, port->number, cmd);
-
-	switch (cmd) {
-	/* This code comes from drivers/char/serial.c and ftdi_sio.c */
-	case TIOCMIWAIT:
-		for (;;) {
-			interruptible_sleep_on(&port->delta_msr_wait);
-			/* see if a signal did it */
-			if (signal_pending(current))
-				return -ERESTARTSYS;
-
-			if (port->serial->disconnected)
-				return -EIO;
-
-			{
-				char diff = priv->diff_status;
-				if (diff == 0)
-					return -EIO; /* no change => error */
-
-				/* consume all events */
-				priv->diff_status = 0;
-
-				/* return 0 if caller wanted to know about
-				   these bits */
-				if (((arg & TIOCM_RNG) && (diff & UART_RI)) ||
-				    ((arg & TIOCM_DSR) && (diff & UART_DSR)) ||
-				    ((arg & TIOCM_CD) && (diff & UART_CD)) ||
-				    ((arg & TIOCM_CTS) && (diff & UART_CTS)))
-					return 0;
-				/* otherwise caller can't care less about what
-				 * happened, and so we continue to wait for
-				 * more events.
-				 */
-			}
-		}
-		return 0;
-	default:
-		break;
+	char diff;
+
+	for (;;) {
+		interruptible_sleep_on(&port->port.delta_msr_wait);
+		/* see if a signal did it */
+		if (signal_pending(current))
+			return -ERESTARTSYS;
+
+		if (port->serial->disconnected)
+			return -EIO;
+
+		diff = priv->diff_status;
+		if (diff == 0)
+			return -EIO; /* no change => error */
+
+		/* consume all events */
+		priv->diff_status = 0;
+
+		/* return 0 if caller wanted to know about
+		   these bits */
+		if (((arg & TIOCM_RNG) && (diff & UART_RI))  ||
+			((arg & TIOCM_DSR) && (diff & UART_DSR)) ||
+			((arg & TIOCM_CD)  && (diff & UART_CD))  ||
+			((arg & TIOCM_CTS) && (diff & UART_CTS)))
+			return 0;
+		/* otherwise caller can't care less about what
+		 * happened, and so we continue to wait for
+		 * more events.
+		 */
 	}
-	dev_dbg(&port->dev, "%s - arg not supported - it was 0x%04x - check include/asm/ioctls.h\n", __func__, cmd);
-	return -ENOIOCTLCMD;
-} /* cypress_ioctl */
 
+	return 0;
+}
 
 static void cypress_set_termios(struct tty_struct *tty,
 	struct usb_serial_port *port, struct ktermios *old_termios)
@@ -1189,7 +1169,7 @@ static void cypress_read_int_callback(struct urb *urb)
 	if (priv->current_status != priv->prev_status) {
 		priv->diff_status |= priv->current_status ^
 			priv->prev_status;
-		wake_up_interruptible(&port->delta_msr_wait);
+		wake_up_interruptible(&port->port.delta_msr_wait);
 		priv->prev_status = priv->current_status;
 	}
 	spin_unlock_irqrestore(&priv->lock, flags);
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index ebe45fa..7b807d3 100644
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/drivers/usb/serial/digi_acceleport.c
@@ -196,7 +196,6 @@ struct digi_port {
 	unsigned char dp_out_buf[DIGI_OUT_BUF_SIZE];
 	int dp_write_urb_in_use;
 	unsigned int dp_modem_signals;
-	wait_queue_head_t dp_modem_change_wait;
 	int dp_transmit_idle;
 	wait_queue_head_t dp_transmit_idle_wait;
 	int dp_throttled;
@@ -210,7 +209,6 @@ struct digi_port {
 
 /* Local Function Declarations */
 
-static void digi_wakeup_write(struct usb_serial_port *port);
 static void digi_wakeup_write_lock(struct work_struct *work);
 static int digi_write_oob_command(struct usb_serial_port *port,
 	unsigned char *buf, int count, int interruptible);
@@ -374,20 +372,10 @@ static void digi_wakeup_write_lock(struct work_struct *work)
 	unsigned long flags;
 
 	spin_lock_irqsave(&priv->dp_port_lock, flags);
-	digi_wakeup_write(port);
+	tty_port_tty_wakeup(&port->port);
 	spin_unlock_irqrestore(&priv->dp_port_lock, flags);
 }
 
-static void digi_wakeup_write(struct usb_serial_port *port)
-{
-	struct tty_struct *tty = tty_port_tty_get(&port->port);
-	if (tty) {
-		tty_wakeup(tty);
-		tty_kref_put(tty);
-	}
-}
-
-
 /*
  *  Digi Write OOB Command
  *
@@ -1044,7 +1032,7 @@ static void digi_write_bulk_callback(struct urb *urb)
 		}
 	}
 	/* wake up processes sleeping on writes immediately */
-	digi_wakeup_write(port);
+	tty_port_tty_wakeup(&port->port);
 	/* also queue up a wakeup at scheduler time, in case we */
 	/* lost the race in write_chan(). */
 	schedule_work(&priv->dp_wakeup_work);
@@ -1149,53 +1137,51 @@ static void digi_close(struct usb_serial_port *port)
 	if (port->serial->disconnected)
 		goto exit;
 
-	if (port->serial->dev) {
-		/* FIXME: Transmit idle belongs in the wait_unti_sent path */
-		digi_transmit_idle(port, DIGI_CLOSE_TIMEOUT);
-
-		/* disable input flow control */
-		buf[0] = DIGI_CMD_SET_INPUT_FLOW_CONTROL;
-		buf[1] = priv->dp_port_num;
-		buf[2] = DIGI_DISABLE;
-		buf[3] = 0;
-
-		/* disable output flow control */
-		buf[4] = DIGI_CMD_SET_OUTPUT_FLOW_CONTROL;
-		buf[5] = priv->dp_port_num;
-		buf[6] = DIGI_DISABLE;
-		buf[7] = 0;
-
-		/* disable reading modem signals automatically */
-		buf[8] = DIGI_CMD_READ_INPUT_SIGNALS;
-		buf[9] = priv->dp_port_num;
-		buf[10] = DIGI_DISABLE;
-		buf[11] = 0;
-
-		/* disable receive */
-		buf[12] = DIGI_CMD_RECEIVE_ENABLE;
-		buf[13] = priv->dp_port_num;
-		buf[14] = DIGI_DISABLE;
-		buf[15] = 0;
-
-		/* flush fifos */
-		buf[16] = DIGI_CMD_IFLUSH_FIFO;
-		buf[17] = priv->dp_port_num;
-		buf[18] = DIGI_FLUSH_TX | DIGI_FLUSH_RX;
-		buf[19] = 0;
-
-		ret = digi_write_oob_command(port, buf, 20, 0);
-		if (ret != 0)
-			dev_dbg(&port->dev, "digi_close: write oob failed, ret=%d\n", ret);
-
-		/* wait for final commands on oob port to complete */
-		prepare_to_wait(&priv->dp_flush_wait, &wait,
-							TASK_INTERRUPTIBLE);
-		schedule_timeout(DIGI_CLOSE_TIMEOUT);
-		finish_wait(&priv->dp_flush_wait, &wait);
-
-		/* shutdown any outstanding bulk writes */
-		usb_kill_urb(port->write_urb);
-	}
+	/* FIXME: Transmit idle belongs in the wait_unti_sent path */
+	digi_transmit_idle(port, DIGI_CLOSE_TIMEOUT);
+
+	/* disable input flow control */
+	buf[0] = DIGI_CMD_SET_INPUT_FLOW_CONTROL;
+	buf[1] = priv->dp_port_num;
+	buf[2] = DIGI_DISABLE;
+	buf[3] = 0;
+
+	/* disable output flow control */
+	buf[4] = DIGI_CMD_SET_OUTPUT_FLOW_CONTROL;
+	buf[5] = priv->dp_port_num;
+	buf[6] = DIGI_DISABLE;
+	buf[7] = 0;
+
+	/* disable reading modem signals automatically */
+	buf[8] = DIGI_CMD_READ_INPUT_SIGNALS;
+	buf[9] = priv->dp_port_num;
+	buf[10] = DIGI_DISABLE;
+	buf[11] = 0;
+
+	/* disable receive */
+	buf[12] = DIGI_CMD_RECEIVE_ENABLE;
+	buf[13] = priv->dp_port_num;
+	buf[14] = DIGI_DISABLE;
+	buf[15] = 0;
+
+	/* flush fifos */
+	buf[16] = DIGI_CMD_IFLUSH_FIFO;
+	buf[17] = priv->dp_port_num;
+	buf[18] = DIGI_FLUSH_TX | DIGI_FLUSH_RX;
+	buf[19] = 0;
+
+	ret = digi_write_oob_command(port, buf, 20, 0);
+	if (ret != 0)
+		dev_dbg(&port->dev, "digi_close: write oob failed, ret=%d\n",
+									ret);
+	/* wait for final commands on oob port to complete */
+	prepare_to_wait(&priv->dp_flush_wait, &wait,
+			TASK_INTERRUPTIBLE);
+	schedule_timeout(DIGI_CLOSE_TIMEOUT);
+	finish_wait(&priv->dp_flush_wait, &wait);
+
+	/* shutdown any outstanding bulk writes */
+	usb_kill_urb(port->write_urb);
 exit:
 	spin_lock_irq(&priv->dp_port_lock);
 	priv->dp_write_urb_in_use = 0;
@@ -1252,7 +1238,6 @@ static int digi_port_init(struct usb_serial_port *port, unsigned port_num)
 
 	spin_lock_init(&priv->dp_port_lock);
 	priv->dp_port_num = port_num;
-	init_waitqueue_head(&priv->dp_modem_change_wait);
 	init_waitqueue_head(&priv->dp_transmit_idle_wait);
 	init_waitqueue_head(&priv->dp_flush_wait);
 	init_waitqueue_head(&priv->dp_close_wait);
@@ -1522,7 +1507,7 @@ static int digi_read_oob_callback(struct urb *urb)
 				/* port must be open to use tty struct */
 				if (rts) {
 					tty->hw_stopped = 0;
-					digi_wakeup_write(port);
+					tty_port_tty_wakeup(&port->port);
 				}
 			} else {
 				priv->dp_modem_signals &= ~TIOCM_CTS;
@@ -1543,7 +1528,6 @@ static int digi_read_oob_callback(struct urb *urb)
 			else
 				priv->dp_modem_signals &= ~TIOCM_CD;
 
-			wake_up_interruptible(&priv->dp_modem_change_wait);
 			spin_unlock(&priv->dp_port_lock);
 		} else if (opcode == DIGI_CMD_TRANSMIT_IDLE) {
 			spin_lock(&priv->dp_port_lock);
diff --git a/drivers/usb/serial/f81232.c b/drivers/usb/serial/f81232.c
index a172ad5..090b411 100644
--- a/drivers/usb/serial/f81232.c
+++ b/drivers/usb/serial/f81232.c
@@ -110,7 +110,7 @@ static void f81232_process_read_urb(struct urb *urb)
 	line_status = priv->line_status;
 	priv->line_status &= ~UART_STATE_TRANSIENT_MASK;
 	spin_unlock_irqrestore(&priv->lock, flags);
-	wake_up_interruptible(&port->delta_msr_wait);
+	wake_up_interruptible(&port->port.delta_msr_wait);
 
 	if (!urb->actual_length)
 		return;
@@ -242,8 +242,9 @@ static int f81232_carrier_raised(struct usb_serial_port *port)
 	return 0;
 }
 
-static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
+static int f81232_tiocmiwait(struct tty_struct *tty, unsigned long arg)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct f81232_private *priv = usb_get_serial_port_data(port);
 	unsigned long flags;
 	unsigned int prevstatus;
@@ -255,7 +256,7 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	while (1) {
-		interruptible_sleep_on(&port->delta_msr_wait);
+		interruptible_sleep_on(&port->port.delta_msr_wait);
 		/* see if a signal did it */
 		if (signal_pending(current))
 			return -ERESTARTSYS;
@@ -302,11 +303,6 @@ static int f81232_ioctl(struct tty_struct *tty,
 			return -EFAULT;
 
 		return 0;
-
-	case TIOCMIWAIT:
-		dev_dbg(&port->dev, "%s (%d) TIOCMIWAIT\n", __func__,
-			port->number);
-		return wait_modem_info(port, arg);
 	default:
 		dev_dbg(&port->dev, "%s not supported = 0x%04x\n",
 			__func__, cmd);
@@ -358,6 +354,7 @@ static struct usb_serial_driver f81232_device = {
 	.set_termios =		f81232_set_termios,
 	.tiocmget =		f81232_tiocmget,
 	.tiocmset =		f81232_tiocmset,
+	.tiocmiwait =		f81232_tiocmiwait,
 	.process_read_urb =	f81232_process_read_urb,
 	.read_int_callback =	f81232_read_int_callback,
 	.port_probe =		f81232_port_probe,
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 9886180..778c54d 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -1,7 +1,7 @@
 /*
  * USB FTDI SIO driver
  *
- *	Copyright (C) 2009 - 2010
+ *	Copyright (C) 2009 - 2013
  *	    Johan Hovold (jhovold@gmail.com)
  *	Copyright (C) 1999 - 2001
  *	    Greg Kroah-Hartman (greg@kroah.com)
@@ -55,7 +55,6 @@ static __u16 vendor = FTDI_VID;
 static __u16 product;
 
 struct ftdi_private {
-	struct kref kref;
 	enum ftdi_chip_type chip_type;
 				/* type of device, either SIO or FT8U232AM */
 	int baud_base;		/* baud base clock for divisor setting */
@@ -68,7 +67,6 @@ struct ftdi_private {
 				 */
 	int flags;		/* some ASYNC_xxxx flags are supported */
 	unsigned long last_dtr_rts;	/* saved modem control outputs */
-	struct async_icount	icount;
 	char prev_status;        /* Used for TIOCMIWAIT */
 	char transmit_empty;	/* If transmitter is empty or not */
 	__u16 interface;	/* FT2232C, FT2232H or FT4232H port interface
@@ -911,7 +909,6 @@ static int  ftdi_sio_probe(struct usb_serial *serial,
 static int  ftdi_sio_port_probe(struct usb_serial_port *port);
 static int  ftdi_sio_port_remove(struct usb_serial_port *port);
 static int  ftdi_open(struct tty_struct *tty, struct usb_serial_port *port);
-static void ftdi_close(struct usb_serial_port *port);
 static void ftdi_dtr_rts(struct usb_serial_port *port, int on);
 static void ftdi_process_read_urb(struct urb *urb);
 static int ftdi_prepare_write_buffer(struct usb_serial_port *port,
@@ -921,8 +918,6 @@ static void ftdi_set_termios(struct tty_struct *tty,
 static int  ftdi_tiocmget(struct tty_struct *tty);
 static int  ftdi_tiocmset(struct tty_struct *tty,
 			unsigned int set, unsigned int clear);
-static int ftdi_get_icount(struct tty_struct *tty,
-			   struct serial_icounter_struct *icount);
 static int  ftdi_ioctl(struct tty_struct *tty,
 			unsigned int cmd, unsigned long arg);
 static void ftdi_break_ctl(struct tty_struct *tty, int break_state);
@@ -951,7 +946,6 @@ static struct usb_serial_driver ftdi_sio_device = {
 	.port_probe =		ftdi_sio_port_probe,
 	.port_remove =		ftdi_sio_port_remove,
 	.open =			ftdi_open,
-	.close =		ftdi_close,
 	.dtr_rts =		ftdi_dtr_rts,
 	.throttle =		usb_serial_generic_throttle,
 	.unthrottle =		usb_serial_generic_unthrottle,
@@ -959,7 +953,8 @@ static struct usb_serial_driver ftdi_sio_device = {
 	.prepare_write_buffer =	ftdi_prepare_write_buffer,
 	.tiocmget =		ftdi_tiocmget,
 	.tiocmset =		ftdi_tiocmset,
-	.get_icount =           ftdi_get_icount,
+	.tiocmiwait =		usb_serial_generic_tiocmiwait,
+	.get_icount =           usb_serial_generic_get_icount,
 	.ioctl =		ftdi_ioctl,
 	.set_termios =		ftdi_set_termios,
 	.break_ctl =		ftdi_break_ctl,
@@ -1688,7 +1683,6 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
 		return -ENOMEM;
 	}
 
-	kref_init(&priv->kref);
 	mutex_init(&priv->cfg_lock);
 
 	priv->flags = ASYNC_LOW_LATENCY;
@@ -1826,22 +1820,13 @@ static int ftdi_mtxorb_hack_setup(struct usb_serial *serial)
 	return 0;
 }
 
-static void ftdi_sio_priv_release(struct kref *k)
-{
-	struct ftdi_private *priv = container_of(k, struct ftdi_private, kref);
-
-	kfree(priv);
-}
-
 static int ftdi_sio_port_remove(struct usb_serial_port *port)
 {
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
 
-	wake_up_interruptible(&port->delta_msr_wait);
-
 	remove_sysfs_attrs(port);
 
-	kref_put(&priv->kref, ftdi_sio_priv_release);
+	kfree(priv);
 
 	return 0;
 }
@@ -1851,7 +1836,6 @@ static int ftdi_open(struct tty_struct *tty, struct usb_serial_port *port)
 	struct ktermios dummy;
 	struct usb_device *dev = port->serial->dev;
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
-	int result;
 
 	/* No error checking for this (will get errors later anyway) */
 	/* See ftdi_sio.h for description of what is reset */
@@ -1870,12 +1854,7 @@ static int ftdi_open(struct tty_struct *tty, struct usb_serial_port *port)
 		ftdi_set_termios(tty, port, &dummy);
 	}
 
-	/* Start reading from the device */
-	result = usb_serial_generic_open(tty, port);
-	if (!result)
-		kref_get(&priv->kref);
-
-	return result;
+	return usb_serial_generic_open(tty, port);
 }
 
 static void ftdi_dtr_rts(struct usb_serial_port *port, int on)
@@ -1900,19 +1879,6 @@ static void ftdi_dtr_rts(struct usb_serial_port *port, int on)
 		clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
 }
 
-/*
- * usbserial:__serial_close  only calls ftdi_close if the point is open
- *
- *   This only gets called when it is the last close
- */
-static void ftdi_close(struct usb_serial_port *port)
-{
-	struct ftdi_private *priv = usb_get_serial_port_data(port);
-
-	usb_serial_generic_close(port);
-	kref_put(&priv->kref, ftdi_sio_priv_release);
-}
-
 /* The SIO requires the first byte to have:
  *  B0 1
  *  B1 0
@@ -1940,7 +1906,7 @@ static int ftdi_prepare_write_buffer(struct usb_serial_port *port,
 			c = kfifo_out(&port->write_fifo, &buffer[i + 1], len);
 			if (!c)
 				break;
-			priv->icount.tx += c;
+			port->icount.tx += c;
 			buffer[i] = (c << 2) + 1;
 			count += c + 1;
 		}
@@ -1948,7 +1914,7 @@ static int ftdi_prepare_write_buffer(struct usb_serial_port *port,
 	} else {
 		count = kfifo_out_locked(&port->write_fifo, dest, size,
 								&port->lock);
-		priv->icount.tx += count;
+		port->icount.tx += count;
 	}
 
 	return count;
@@ -1977,15 +1943,15 @@ static int ftdi_process_packet(struct usb_serial_port *port,
 		char diff_status = status ^ priv->prev_status;
 
 		if (diff_status & FTDI_RS0_CTS)
-			priv->icount.cts++;
+			port->icount.cts++;
 		if (diff_status & FTDI_RS0_DSR)
-			priv->icount.dsr++;
+			port->icount.dsr++;
 		if (diff_status & FTDI_RS0_RI)
-			priv->icount.rng++;
+			port->icount.rng++;
 		if (diff_status & FTDI_RS0_RLSD)
-			priv->icount.dcd++;
+			port->icount.dcd++;
 
-		wake_up_interruptible(&port->delta_msr_wait);
+		wake_up_interruptible(&port->port.delta_msr_wait);
 		priv->prev_status = status;
 	}
 
@@ -1995,18 +1961,18 @@ static int ftdi_process_packet(struct usb_serial_port *port,
 		 * over framing errors */
 		if (packet[1] & FTDI_RS_BI) {
 			flag = TTY_BREAK;
-			priv->icount.brk++;
+			port->icount.brk++;
 			usb_serial_handle_break(port);
 		} else if (packet[1] & FTDI_RS_PE) {
 			flag = TTY_PARITY;
-			priv->icount.parity++;
+			port->icount.parity++;
 		} else if (packet[1] & FTDI_RS_FE) {
 			flag = TTY_FRAME;
-			priv->icount.frame++;
+			port->icount.frame++;
 		}
 		/* Overrun is special, not associated with a char */
 		if (packet[1] & FTDI_RS_OE) {
-			priv->icount.overrun++;
+			port->icount.overrun++;
 			tty_insert_flip_char(&port->port, 0, TTY_OVERRUN);
 		}
 	}
@@ -2020,7 +1986,7 @@ static int ftdi_process_packet(struct usb_serial_port *port,
 	len -= 2;
 	if (!len)
 		return 0;	/* status only */
-	priv->icount.rx += len;
+	port->icount.rx += len;
 	ch = packet + 2;
 
 	if (port->port.console && port->sysrq) {
@@ -2384,34 +2350,10 @@ static int ftdi_tiocmset(struct tty_struct *tty,
 	return update_mctrl(port, set, clear);
 }
 
-static int ftdi_get_icount(struct tty_struct *tty,
-				struct serial_icounter_struct *icount)
-{
-	struct usb_serial_port *port = tty->driver_data;
-	struct ftdi_private *priv = usb_get_serial_port_data(port);
-	struct async_icount *ic = &priv->icount;
-
-	icount->cts = ic->cts;
-	icount->dsr = ic->dsr;
-	icount->rng = ic->rng;
-	icount->dcd = ic->dcd;
-	icount->tx = ic->tx;
-	icount->rx = ic->rx;
-	icount->frame = ic->frame;
-	icount->parity = ic->parity;
-	icount->overrun = ic->overrun;
-	icount->brk = ic->brk;
-	icount->buf_overrun = ic->buf_overrun;
-	return 0;
-}
-
 static int ftdi_ioctl(struct tty_struct *tty,
 					unsigned int cmd, unsigned long arg)
 {
 	struct usb_serial_port *port = tty->driver_data;
-	struct ftdi_private *priv = usb_get_serial_port_data(port);
-	struct async_icount cnow;
-	struct async_icount cprev;
 
 	dev_dbg(&port->dev, "%s cmd 0x%04x\n", __func__, cmd);
 
@@ -2425,35 +2367,6 @@ static int ftdi_ioctl(struct tty_struct *tty,
 	case TIOCSSERIAL: /* sets serial port data */
 		return set_serial_info(tty, port,
 					(struct serial_struct __user *) arg);
-
-	/*
-	 * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
-	 * - 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.
-	 *
-	 * This code is borrowed from linux/drivers/char/serial.c
-	 */
-	case TIOCMIWAIT:
-		cprev = priv->icount;
-		for (;;) {
-			interruptible_sleep_on(&port->delta_msr_wait);
-			/* see if a signal did it */
-			if (signal_pending(current))
-				return -ERESTARTSYS;
-
-			if (port->serial->disconnected)
-				return -EIO;
-
-			cnow = priv->icount;
-			if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
-			    ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
-			    ((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) ||
-			    ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) {
-				return 0;
-			}
-			cprev = cnow;
-		}
 	case TIOCSERGETLSR:
 		return get_lsr_info(port, (struct serial_struct __user *)arg);
 		break;
diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c
index 81caf56..b110c57 100644
--- a/drivers/usb/serial/garmin_gps.c
+++ b/drivers/usb/serial/garmin_gps.c
@@ -946,16 +946,12 @@ static int garmin_open(struct tty_struct *tty, struct usb_serial_port *port)
 
 static void garmin_close(struct usb_serial_port *port)
 {
-	struct usb_serial *serial = port->serial;
 	struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
 
 	dev_dbg(&port->dev, "%s - port %d - mode=%d state=%d flags=0x%X\n",
 		__func__, port->number, garmin_data_p->mode,
 		garmin_data_p->state, garmin_data_p->flags);
 
-	if (!serial)
-		return;
-
 	garmin_clear(garmin_data_p);
 
 	/* shutdown our urbs */
@@ -1185,17 +1181,11 @@ static void garmin_read_bulk_callback(struct urb *urb)
 {
 	unsigned long flags;
 	struct usb_serial_port *port = urb->context;
-	struct usb_serial *serial =  port->serial;
 	struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
 	unsigned char *data = urb->transfer_buffer;
 	int status = urb->status;
 	int retval;
 
-	if (!serial) {
-		dev_dbg(&urb->dev->dev, "%s - bad serial pointer, exiting\n", __func__);
-		return;
-	}
-
 	if (status) {
 		dev_dbg(&urb->dev->dev, "%s - nonzero read bulk status received: %d\n",
 			__func__, status);
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index 4c5c23f..297665f 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -1,7 +1,7 @@
 /*
  * USB Serial Converter Generic functions
  *
- * Copyright (C) 2010 - 2011 Johan Hovold (jhovold@gmail.com)
+ * Copyright (C) 2010 - 2013 Johan Hovold (jhovold@gmail.com)
  * Copyright (C) 1999 - 2002 Greg Kroah-Hartman (greg@kroah.com)
  *
  *	This program is free software; you can redistribute it and/or
@@ -45,8 +45,6 @@ struct usb_serial_driver usb_serial_generic_device = {
 	},
 	.id_table =		generic_device_ids,
 	.num_ports =		1,
-	.disconnect =		usb_serial_generic_disconnect,
-	.release =		usb_serial_generic_release,
 	.throttle =		usb_serial_generic_throttle,
 	.unthrottle =		usb_serial_generic_unthrottle,
 	.resume =		usb_serial_generic_resume,
@@ -102,32 +100,23 @@ int usb_serial_generic_open(struct tty_struct *tty, struct usb_serial_port *port
 }
 EXPORT_SYMBOL_GPL(usb_serial_generic_open);
 
-static void generic_cleanup(struct usb_serial_port *port)
+void usb_serial_generic_close(struct usb_serial_port *port)
 {
-	struct usb_serial *serial = port->serial;
 	unsigned long flags;
 	int i;
 
-	if (serial->dev) {
-		/* shutdown any bulk transfers that might be going on */
-		if (port->bulk_out_size) {
-			for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i)
-				usb_kill_urb(port->write_urbs[i]);
+	if (port->bulk_out_size) {
+		for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i)
+			usb_kill_urb(port->write_urbs[i]);
 
-			spin_lock_irqsave(&port->lock, flags);
-			kfifo_reset_out(&port->write_fifo);
-			spin_unlock_irqrestore(&port->lock, flags);
-		}
-		if (port->bulk_in_size) {
-			for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i)
-				usb_kill_urb(port->read_urbs[i]);
-		}
+		spin_lock_irqsave(&port->lock, flags);
+		kfifo_reset_out(&port->write_fifo);
+		spin_unlock_irqrestore(&port->lock, flags);
+	}
+	if (port->bulk_in_size) {
+		for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i)
+			usb_kill_urb(port->read_urbs[i]);
 	}
-}
-
-void usb_serial_generic_close(struct usb_serial_port *port)
-{
-	generic_cleanup(port);
 }
 EXPORT_SYMBOL_GPL(usb_serial_generic_close);
 
@@ -272,8 +261,7 @@ static int usb_serial_generic_submit_read_urb(struct usb_serial_port *port,
 	if (!test_and_clear_bit(index, &port->read_urbs_free))
 		return 0;
 
-	dev_dbg(&port->dev, "%s - port %d, urb %d\n", __func__,
-		port->number, index);
+	dev_dbg(&port->dev, "%s - urb %d\n", __func__, index);
 
 	res = usb_submit_urb(port->read_urbs[index], mem_flags);
 	if (res) {
@@ -347,8 +335,8 @@ void usb_serial_generic_read_bulk_callback(struct urb *urb)
 	}
 	set_bit(i, &port->read_urbs_free);
 
-	dev_dbg(&port->dev, "%s - port %d, urb %d, len %d\n",
-		__func__, port->number, i, urb->actual_length);
+	dev_dbg(&port->dev, "%s - urb %d, len %d\n", __func__, i,
+							urb->actual_length);
 
 	if (urb->status) {
 		dev_dbg(&port->dev, "%s - non-zero urb status: %d\n",
@@ -430,6 +418,91 @@ void usb_serial_generic_unthrottle(struct tty_struct *tty)
 }
 EXPORT_SYMBOL_GPL(usb_serial_generic_unthrottle);
 
+static bool usb_serial_generic_msr_changed(struct tty_struct *tty,
+				unsigned long arg, struct async_icount *cprev)
+{
+	struct usb_serial_port *port = tty->driver_data;
+	struct async_icount cnow;
+	unsigned long flags;
+	bool ret;
+
+	/*
+	 * Use tty-port initialised flag to detect all hangups including the
+	 * one generated at USB-device disconnect.
+	 *
+	 * FIXME: Remove hupping check once tty_port_hangup calls shutdown
+	 *        (which clears the initialised flag) before wake up.
+	 */
+	if (test_bit(TTY_HUPPING, &tty->flags))
+		return true;
+	if (!test_bit(ASYNCB_INITIALIZED, &port->port.flags))
+		return true;
+
+	spin_lock_irqsave(&port->lock, flags);
+	cnow = port->icount;				/* atomic copy*/
+	spin_unlock_irqrestore(&port->lock, flags);
+
+	ret =	((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));
+
+	*cprev = cnow;
+
+	return ret;
+}
+
+int usb_serial_generic_tiocmiwait(struct tty_struct *tty, unsigned long arg)
+{
+	struct usb_serial_port *port = tty->driver_data;
+	struct async_icount cnow;
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&port->lock, flags);
+	cnow = port->icount;				/* atomic copy */
+	spin_unlock_irqrestore(&port->lock, flags);
+
+	ret = wait_event_interruptible(port->port.delta_msr_wait,
+			usb_serial_generic_msr_changed(tty, arg, &cnow));
+	if (!ret) {
+		if (test_bit(TTY_HUPPING, &tty->flags))
+			ret = -EIO;
+		if (!test_bit(ASYNCB_INITIALIZED, &port->port.flags))
+			ret = -EIO;
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(usb_serial_generic_tiocmiwait);
+
+int usb_serial_generic_get_icount(struct tty_struct *tty,
+					struct serial_icounter_struct *icount)
+{
+	struct usb_serial_port *port = tty->driver_data;
+	struct async_icount cnow;
+	unsigned long flags;
+
+	spin_lock_irqsave(&port->lock, flags);
+	cnow = port->icount;				/* atomic copy */
+	spin_unlock_irqrestore(&port->lock, flags);
+
+	icount->cts = cnow.cts;
+	icount->dsr = cnow.dsr;
+	icount->rng = cnow.rng;
+	icount->dcd = cnow.dcd;
+	icount->tx = cnow.tx;
+	icount->rx = cnow.rx;
+	icount->frame = cnow.frame;
+	icount->parity = cnow.parity;
+	icount->overrun = cnow.overrun;
+	icount->brk = cnow.brk;
+	icount->buf_overrun = cnow.buf_overrun;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(usb_serial_generic_get_icount);
+
 #ifdef CONFIG_MAGIC_SYSRQ
 int usb_serial_handle_sysrq_char(struct usb_serial_port *port, unsigned int ch)
 {
@@ -473,8 +546,7 @@ void usb_serial_handle_dcd_change(struct usb_serial_port *usb_port,
 {
 	struct tty_port *port = &usb_port->port;
 
-	dev_dbg(&usb_port->dev, "%s - port %d, status %d\n", __func__,
-		usb_port->number, status);
+	dev_dbg(&usb_port->dev, "%s - status %d\n", __func__, status);
 
 	if (status)
 		wake_up_interruptible(&port->open_wait);
@@ -510,17 +582,3 @@ int usb_serial_generic_resume(struct usb_serial *serial)
 	return c ? -EIO : 0;
 }
 EXPORT_SYMBOL_GPL(usb_serial_generic_resume);
-
-void usb_serial_generic_disconnect(struct usb_serial *serial)
-{
-	int i;
-
-	/* stop reads and writes on all ports */
-	for (i = 0; i < serial->num_ports; ++i)
-		generic_cleanup(serial->port[i]);
-}
-EXPORT_SYMBOL_GPL(usb_serial_generic_disconnect);
-
-void usb_serial_generic_release(struct usb_serial *serial)
-{
-}
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index efd8b97..1477e85 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -111,7 +111,6 @@ struct edgeport_port {
 	wait_queue_head_t	wait_open;		/* for handling sleeping while waiting for open to finish */
 	wait_queue_head_t	wait_command;		/* for handling sleeping while waiting for command to finish */
 
-	struct async_icount	icount;
 	struct usb_serial_port	*port;			/* loop back to the owner of this object */
 };
 
@@ -215,8 +214,6 @@ static void edge_break(struct tty_struct *tty, int break_state);
 static int  edge_tiocmget(struct tty_struct *tty);
 static int  edge_tiocmset(struct tty_struct *tty,
 					unsigned int set, unsigned int clear);
-static int  edge_get_icount(struct tty_struct *tty,
-				struct serial_icounter_struct *icount);
 static int  edge_startup(struct usb_serial *serial);
 static void edge_disconnect(struct usb_serial *serial);
 static void edge_release(struct usb_serial *serial);
@@ -564,7 +561,6 @@ static void edge_interrupt_callback(struct urb *urb)
 	struct device *dev;
 	struct edgeport_port *edge_port;
 	struct usb_serial_port *port;
-	struct tty_struct *tty;
 	unsigned char *data = urb->transfer_buffer;
 	int length = urb->actual_length;
 	int bytes_avail;
@@ -643,12 +639,7 @@ static void edge_interrupt_callback(struct urb *urb)
 
 					/* tell the tty driver that something
 					   has changed */
-					tty = tty_port_tty_get(
-						&edge_port->port->port);
-					if (tty) {
-						tty_wakeup(tty);
-						tty_kref_put(tty);
-					}
+					tty_port_tty_wakeup(&edge_port->port->port);
 					/* Since we have more credit, check
 					   if more data can be sent */
 					send_more_port_data(edge_serial,
@@ -737,7 +728,6 @@ static void edge_bulk_in_callback(struct urb *urb)
 static void edge_bulk_out_data_callback(struct urb *urb)
 {
 	struct edgeport_port *edge_port = urb->context;
-	struct tty_struct *tty;
 	int status = urb->status;
 
 	if (status) {
@@ -746,14 +736,8 @@ static void edge_bulk_out_data_callback(struct urb *urb)
 			__func__, status);
 	}
 
-	tty = tty_port_tty_get(&edge_port->port->port);
-
-	if (tty && edge_port->open) {
-		/* let the tty driver wakeup if it has a special
-		   write_wakeup function */
-		tty_wakeup(tty);
-	}
-	tty_kref_put(tty);
+	if (edge_port->open)
+		tty_port_tty_wakeup(&edge_port->port->port);
 
 	/* Release the Write URB */
 	edge_port->write_in_progress = false;
@@ -772,7 +756,6 @@ static void edge_bulk_out_data_callback(struct urb *urb)
 static void edge_bulk_out_cmd_callback(struct urb *urb)
 {
 	struct edgeport_port *edge_port = urb->context;
-	struct tty_struct *tty;
 	int status = urb->status;
 
 	atomic_dec(&CmdUrbs);
@@ -793,13 +776,9 @@ static void edge_bulk_out_cmd_callback(struct urb *urb)
 		return;
 	}
 
-	/* Get pointer to tty */
-	tty = tty_port_tty_get(&edge_port->port->port);
-
 	/* tell the tty driver that something has changed */
-	if (tty && edge_port->open)
-		tty_wakeup(tty);
-	tty_kref_put(tty);
+	if (edge_port->open)
+		tty_port_tty_wakeup(&edge_port->port->port);
 
 	/* we have completed the command */
 	edge_port->commandPending = false;
@@ -885,9 +864,6 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port)
 	init_waitqueue_head(&edge_port->wait_chase);
 	init_waitqueue_head(&edge_port->wait_command);
 
-	/* initialize our icount structure */
-	memset(&(edge_port->icount), 0x00, sizeof(edge_port->icount));
-
 	/* initialize our port settings */
 	edge_port->txCredits = 0;	/* Can't send any data yet */
 	/* Must always set this bit to enable ints! */
@@ -1314,7 +1290,7 @@ static void send_more_port_data(struct edgeport_serial *edge_serial,
 
 	/* decrement the number of credits we have by the number we just sent */
 	edge_port->txCredits -= count;
-	edge_port->icount.tx += count;
+	edge_port->port->icount.tx += count;
 
 	status = usb_submit_urb(urb, GFP_ATOMIC);
 	if (status) {
@@ -1326,7 +1302,7 @@ static void send_more_port_data(struct edgeport_serial *edge_serial,
 
 		/* revert the credits as something bad happened. */
 		edge_port->txCredits += count;
-		edge_port->icount.tx -= count;
+		edge_port->port->icount.tx -= count;
 	}
 	dev_dbg(dev, "%s wrote %d byte(s) TxCredit %d, Fifo %d\n",
 		__func__, count, edge_port->txCredits, fifo->count);
@@ -1588,31 +1564,6 @@ static int edge_tiocmget(struct tty_struct *tty)
 	return result;
 }
 
-static int edge_get_icount(struct tty_struct *tty,
-				struct serial_icounter_struct *icount)
-{
-	struct usb_serial_port *port = tty->driver_data;
-	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
-	struct async_icount cnow;
-	cnow = edge_port->icount;
-
-	icount->cts = cnow.cts;
-	icount->dsr = cnow.dsr;
-	icount->rng = cnow.rng;
-	icount->dcd = cnow.dcd;
-	icount->rx = cnow.rx;
-	icount->tx = cnow.tx;
-	icount->frame = cnow.frame;
-	icount->overrun = cnow.overrun;
-	icount->parity = cnow.parity;
-	icount->brk = cnow.brk;
-	icount->buf_overrun = cnow.buf_overrun;
-
-	dev_dbg(&port->dev, "%s (%d) TIOCGICOUNT RX=%d, TX=%d\n", __func__,
-		port->number, icount->rx, icount->tx);
-	return 0;
-}
-
 static int get_serial_info(struct edgeport_port *edge_port,
 				struct serial_struct __user *retinfo)
 {
@@ -1649,8 +1600,6 @@ static int edge_ioctl(struct tty_struct *tty,
 	struct usb_serial_port *port = tty->driver_data;
 	DEFINE_WAIT(wait);
 	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
-	struct async_icount cnow;
-	struct async_icount cprev;
 
 	dev_dbg(&port->dev, "%s - port %d, cmd = 0x%x\n", __func__, port->number, cmd);
 
@@ -1662,37 +1611,6 @@ static int edge_ioctl(struct tty_struct *tty,
 	case TIOCGSERIAL:
 		dev_dbg(&port->dev, "%s (%d) TIOCGSERIAL\n", __func__,  port->number);
 		return get_serial_info(edge_port, (struct serial_struct __user *) arg);
-
-	case TIOCMIWAIT:
-		dev_dbg(&port->dev, "%s (%d) TIOCMIWAIT\n", __func__,  port->number);
-		cprev = edge_port->icount;
-		while (1) {
-			prepare_to_wait(&port->delta_msr_wait,
-						&wait, TASK_INTERRUPTIBLE);
-			schedule();
-			finish_wait(&port->delta_msr_wait, &wait);
-			/* see if a signal did it */
-			if (signal_pending(current))
-				return -ERESTARTSYS;
-
-			if (port->serial->disconnected)
-				return -EIO;
-
-			cnow = edge_port->icount;
-			if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
-			    cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
-				return -EIO; /* no change => error */
-			if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
-			    ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
-			    ((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) ||
-			    ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) {
-				return 0;
-			}
-			cprev = cnow;
-		}
-		/* NOTREACHED */
-		break;
-
 	}
 	return -ENOIOCTLCMD;
 }
@@ -1866,7 +1784,7 @@ static void process_rcvd_data(struct edgeport_serial *edge_serial,
 						edge_serial->rxPort);
 					edge_tty_recv(edge_port->port, buffer,
 							rxLen);
-					edge_port->icount.rx += rxLen;
+					edge_port->port->icount.rx += rxLen;
 				}
 				buffer += rxLen;
 			}
@@ -2042,7 +1960,7 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 newMsr)
 
 	if (newMsr & (EDGEPORT_MSR_DELTA_CTS | EDGEPORT_MSR_DELTA_DSR |
 			EDGEPORT_MSR_DELTA_RI | EDGEPORT_MSR_DELTA_CD)) {
-		icount = &edge_port->icount;
+		icount = &edge_port->port->icount;
 
 		/* update input line counters */
 		if (newMsr & EDGEPORT_MSR_DELTA_CTS)
@@ -2053,7 +1971,7 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 newMsr)
 			icount->dcd++;
 		if (newMsr & EDGEPORT_MSR_DELTA_RI)
 			icount->rng++;
-		wake_up_interruptible(&edge_port->port->delta_msr_wait);
+		wake_up_interruptible(&edge_port->port->port.delta_msr_wait);
 	}
 
 	/* Save the new modem status */
@@ -2088,7 +2006,7 @@ static void handle_new_lsr(struct edgeport_port *edge_port, __u8 lsrData,
 		edge_tty_recv(edge_port->port, &data, 1);
 
 	/* update input line counters */
-	icount = &edge_port->icount;
+	icount = &edge_port->port->icount;
 	if (newLsr & LSR_BREAK)
 		icount->brk++;
 	if (newLsr & LSR_OVER_ERR)
diff --git a/drivers/usb/serial/io_tables.h b/drivers/usb/serial/io_tables.h
index 1511dd0..ae5fac5 100644
--- a/drivers/usb/serial/io_tables.h
+++ b/drivers/usb/serial/io_tables.h
@@ -116,7 +116,8 @@ static struct usb_serial_driver edgeport_2port_device = {
 	.set_termios		= edge_set_termios,
 	.tiocmget		= edge_tiocmget,
 	.tiocmset		= edge_tiocmset,
-	.get_icount		= edge_get_icount,
+	.tiocmiwait		= usb_serial_generic_tiocmiwait,
+	.get_icount		= usb_serial_generic_get_icount,
 	.write			= edge_write,
 	.write_room		= edge_write_room,
 	.chars_in_buffer	= edge_chars_in_buffer,
@@ -147,7 +148,8 @@ static struct usb_serial_driver edgeport_4port_device = {
 	.set_termios		= edge_set_termios,
 	.tiocmget		= edge_tiocmget,
 	.tiocmset		= edge_tiocmset,
-	.get_icount		= edge_get_icount,
+	.tiocmiwait		= usb_serial_generic_tiocmiwait,
+	.get_icount		= usb_serial_generic_get_icount,
 	.write			= edge_write,
 	.write_room		= edge_write_room,
 	.chars_in_buffer	= edge_chars_in_buffer,
@@ -178,7 +180,8 @@ static struct usb_serial_driver edgeport_8port_device = {
 	.set_termios		= edge_set_termios,
 	.tiocmget		= edge_tiocmget,
 	.tiocmset		= edge_tiocmset,
-	.get_icount		= edge_get_icount,
+	.tiocmiwait		= usb_serial_generic_tiocmiwait,
+	.get_icount		= usb_serial_generic_get_icount,
 	.write			= edge_write,
 	.write_room		= edge_write_room,
 	.chars_in_buffer	= edge_chars_in_buffer,
@@ -209,7 +212,8 @@ static struct usb_serial_driver epic_device = {
 	.set_termios		= edge_set_termios,
 	.tiocmget		= edge_tiocmget,
 	.tiocmset		= edge_tiocmset,
-	.get_icount		= edge_get_icount,
+	.tiocmiwait		= usb_serial_generic_tiocmiwait,
+	.get_icount		= usb_serial_generic_get_icount,
 	.write			= edge_write,
 	.write_room		= edge_write_room,
 	.chars_in_buffer	= edge_chars_in_buffer,
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index 7777172..0ccc422 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -86,7 +86,7 @@ struct edgeport_port {
 	int baud_rate;
 	int close_pending;
 	int lsr_event;
-	struct async_icount	icount;
+
 	struct edgeport_serial	*edge_serial;
 	struct usb_serial_port	*port;
 	__u8 bUartMode;		/* Port type, 0: RS232, etc. */
@@ -1445,7 +1445,7 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 msr)
 
 	if (msr & (EDGEPORT_MSR_DELTA_CTS | EDGEPORT_MSR_DELTA_DSR |
 			EDGEPORT_MSR_DELTA_RI | EDGEPORT_MSR_DELTA_CD)) {
-		icount = &edge_port->icount;
+		icount = &edge_port->port->icount;
 
 		/* update input line counters */
 		if (msr & EDGEPORT_MSR_DELTA_CTS)
@@ -1456,7 +1456,7 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 msr)
 			icount->dcd++;
 		if (msr & EDGEPORT_MSR_DELTA_RI)
 			icount->rng++;
-		wake_up_interruptible(&edge_port->port->delta_msr_wait);
+		wake_up_interruptible(&edge_port->port->port.delta_msr_wait);
 	}
 
 	/* Save the new modem status */
@@ -1498,7 +1498,7 @@ static void handle_new_lsr(struct edgeport_port *edge_port, int lsr_data,
 		edge_tty_recv(edge_port->port, &data, 1);
 
 	/* update input line counters */
-	icount = &edge_port->icount;
+	icount = &edge_port->port->icount;
 	if (new_lsr & LSR_BREAK)
 		icount->brk++;
 	if (new_lsr & LSR_OVER_ERR)
@@ -1657,7 +1657,7 @@ static void edge_bulk_in_callback(struct urb *urb)
 		else
 			edge_tty_recv(edge_port->port, data,
 					urb->actual_length);
-		edge_port->icount.rx += urb->actual_length;
+		edge_port->port->icount.rx += urb->actual_length;
 	}
 
 exit:
@@ -1750,8 +1750,6 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port)
 
 	dev = port->serial->dev;
 
-	memset(&(edge_port->icount), 0x00, sizeof(edge_port->icount));
-
 	/* turn off loopback */
 	status = ti_do_config(edge_port, UMPC_SET_CLR_LOOPBACK, 0);
 	if (status) {
@@ -1909,21 +1907,10 @@ static void edge_close(struct usb_serial_port *port)
 	kfifo_reset_out(&edge_port->write_fifo);
 	spin_unlock_irqrestore(&edge_port->ep_lock, flags);
 
-	/* assuming we can still talk to the device,
-	 * send a close port command to it */
 	dev_dbg(&port->dev, "%s - send umpc_close_port\n", __func__);
 	port_number = port->number - port->serial->minor;
-
-	mutex_lock(&serial->disc_mutex);
-	if (!serial->disconnected) {
-		send_cmd(serial->dev,
-				     UMPC_CLOSE_PORT,
-				     (__u8)(UMPM_UART1_PORT + port_number),
-				     0,
-				     NULL,
-				     0);
-	}
-	mutex_unlock(&serial->disc_mutex);
+	send_cmd(serial->dev, UMPC_CLOSE_PORT,
+		     (__u8)(UMPM_UART1_PORT + port_number), 0, NULL, 0);
 
 	mutex_lock(&edge_serial->es_lock);
 	--edge_port->edge_serial->num_ports_open;
@@ -1999,7 +1986,7 @@ static void edge_send(struct tty_struct *tty)
 		edge_port->ep_write_urb_in_use = 0;
 		/* TODO: reschedule edge_send */
 	} else
-		edge_port->icount.tx += count;
+		edge_port->port->icount.tx += count;
 
 	/* wakeup any process waiting for writes to complete */
 	/* there is now more room in the buffer for new writes */
@@ -2360,27 +2347,6 @@ static int edge_tiocmget(struct tty_struct *tty)
 	return result;
 }
 
-static int edge_get_icount(struct tty_struct *tty,
-				struct serial_icounter_struct *icount)
-{
-	struct usb_serial_port *port = tty->driver_data;
-	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
-	struct async_icount *ic = &edge_port->icount;
-
-	icount->cts = ic->cts;
-	icount->dsr = ic->dsr;
-	icount->rng = ic->rng;
-	icount->dcd = ic->dcd;
-	icount->tx = ic->tx;
-        icount->rx = ic->rx;
-        icount->frame = ic->frame;
-        icount->parity = ic->parity;
-        icount->overrun = ic->overrun;
-        icount->brk = ic->brk;
-        icount->buf_overrun = ic->buf_overrun;
-	return 0;
-}
-
 static int get_serial_info(struct edgeport_port *edge_port,
 				struct serial_struct __user *retinfo)
 {
@@ -2416,8 +2382,6 @@ static int edge_ioctl(struct tty_struct *tty,
 {
 	struct usb_serial_port *port = tty->driver_data;
 	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
-	struct async_icount cnow;
-	struct async_icount cprev;
 
 	dev_dbg(&port->dev, "%s - port %d, cmd = 0x%x\n", __func__, port->number, cmd);
 
@@ -2426,32 +2390,6 @@ static int edge_ioctl(struct tty_struct *tty,
 		dev_dbg(&port->dev, "%s - TIOCGSERIAL\n", __func__);
 		return get_serial_info(edge_port,
 				(struct serial_struct __user *) arg);
-	case TIOCMIWAIT:
-		dev_dbg(&port->dev, "%s - TIOCMIWAIT\n", __func__);
-		cprev = edge_port->icount;
-		while (1) {
-			interruptible_sleep_on(&port->delta_msr_wait);
-			/* see if a signal did it */
-			if (signal_pending(current))
-				return -ERESTARTSYS;
-
-			if (port->serial->disconnected)
-				return -EIO;
-
-			cnow = edge_port->icount;
-			if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
-			    cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
-				return -EIO; /* no change => error */
-			if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
-			    ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
-			    ((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) ||
-			    ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) {
-				return 0;
-			}
-			cprev = cnow;
-		}
-		/* not reached */
-		break;
 	}
 	return -ENOIOCTLCMD;
 }
@@ -2546,7 +2484,6 @@ static int edge_port_remove(struct usb_serial_port *port)
 	struct edgeport_port *edge_port;
 
 	edge_port = usb_get_serial_port_data(port);
-
 	edge_remove_sysfs_attrs(port);
 	kfifo_free(&edge_port->write_fifo);
 	kfree(edge_port);
@@ -2618,7 +2555,8 @@ static struct usb_serial_driver edgeport_1port_device = {
 	.set_termios		= edge_set_termios,
 	.tiocmget		= edge_tiocmget,
 	.tiocmset		= edge_tiocmset,
-	.get_icount		= edge_get_icount,
+	.tiocmiwait		= usb_serial_generic_tiocmiwait,
+	.get_icount		= usb_serial_generic_get_icount,
 	.write			= edge_write,
 	.write_room		= edge_write_room,
 	.chars_in_buffer	= edge_chars_in_buffer,
@@ -2649,7 +2587,8 @@ static struct usb_serial_driver edgeport_2port_device = {
 	.set_termios		= edge_set_termios,
 	.tiocmget		= edge_tiocmget,
 	.tiocmset		= edge_tiocmset,
-	.get_icount		= edge_get_icount,
+	.tiocmiwait		= usb_serial_generic_tiocmiwait,
+	.get_icount		= usb_serial_generic_get_icount,
 	.write			= edge_write,
 	.write_room		= edge_write_room,
 	.chars_in_buffer	= edge_chars_in_buffer,
diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c
index ff77027..9d74c27 100644
--- a/drivers/usb/serial/iuu_phoenix.c
+++ b/drivers/usb/serial/iuu_phoenix.c
@@ -55,7 +55,6 @@ static void read_rxcmd_callback(struct urb *urb);
 
 struct iuu_private {
 	spinlock_t lock;	/* store irq state */
-	wait_queue_head_t delta_msr_wait;
 	u8 line_status;
 	int tiostatus;		/* store IUART SIGNAL for tiocmget call */
 	u8 reset;		/* if 1 reset is needed */
@@ -94,7 +93,6 @@ static int iuu_port_probe(struct usb_serial_port *port)
 
 	priv->vcc = vcc_default;
 	spin_lock_init(&priv->lock);
-	init_waitqueue_head(&priv->delta_msr_wait);
 
 	usb_set_serial_port_data(port, priv);
 
@@ -944,22 +942,13 @@ static void iuu_set_termios(struct tty_struct *tty,
 static void iuu_close(struct usb_serial_port *port)
 {
 	/* iuu_led (port,255,0,0,0); */
-	struct usb_serial *serial;
-
-	serial = port->serial;
-	if (!serial)
-		return;
 
 	iuu_uart_off(port);
-	if (serial->dev) {
-		/* free writebuf */
-		/* shutdown our urbs */
-		dev_dbg(&port->dev, "%s - shutting down urbs\n", __func__);
-		usb_kill_urb(port->write_urb);
-		usb_kill_urb(port->read_urb);
-		usb_kill_urb(port->interrupt_in_urb);
-		iuu_led(port, 0, 0, 0xF000, 0xFF);
-	}
+
+	usb_kill_urb(port->write_urb);
+	usb_kill_urb(port->read_urb);
+
+	iuu_led(port, 0, 0, 0xF000, 0xFF);
 }
 
 static void iuu_init_termios(struct tty_struct *tty)
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
index 1fd1935..5b912fc 100644
--- a/drivers/usb/serial/keyspan.c
+++ b/drivers/usb/serial/keyspan.c
@@ -378,7 +378,6 @@ static void	usa26_instat_callback(struct urb *urb)
 	struct usb_serial			*serial;
 	struct usb_serial_port			*port;
 	struct keyspan_port_private	 	*p_priv;
-	struct tty_struct			*tty;
 	int old_dcd_state, err;
 	int status = urb->status;
 
@@ -421,12 +420,8 @@ static void	usa26_instat_callback(struct urb *urb)
 	p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);
 	p_priv->ri_state = ((msg->ri) ? 1 : 0);
 
-	if (old_dcd_state != p_priv->dcd_state) {
-		tty = tty_port_tty_get(&port->port);
-		if (tty && !C_CLOCAL(tty))
-			tty_hangup(tty);
-		tty_kref_put(tty);
-	}
+	if (old_dcd_state != p_priv->dcd_state)
+		tty_port_tty_hangup(&port->port, true);
 
 	/* Resubmit urb so we continue receiving */
 	err = usb_submit_urb(urb, GFP_ATOMIC);
@@ -510,7 +505,6 @@ static void	usa28_instat_callback(struct urb *urb)
 	struct usb_serial			*serial;
 	struct usb_serial_port			*port;
 	struct keyspan_port_private	 	*p_priv;
-	struct tty_struct			*tty;
 	int old_dcd_state;
 	int status = urb->status;
 
@@ -551,12 +545,8 @@ static void	usa28_instat_callback(struct urb *urb)
 	p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
 	p_priv->ri_state = ((msg->ri) ? 1 : 0);
 
-	if (old_dcd_state != p_priv->dcd_state && old_dcd_state) {
-		tty = tty_port_tty_get(&port->port);
-		if (tty && !C_CLOCAL(tty))
-			tty_hangup(tty);
-		tty_kref_put(tty);
-	}
+	if (old_dcd_state != p_priv->dcd_state && old_dcd_state)
+		tty_port_tty_hangup(&port->port, true);
 
 		/* Resubmit urb so we continue receiving */
 	err = usb_submit_urb(urb, GFP_ATOMIC);
@@ -642,12 +632,8 @@ static void	usa49_instat_callback(struct urb *urb)
 	p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
 	p_priv->ri_state = ((msg->ri) ? 1 : 0);
 
-	if (old_dcd_state != p_priv->dcd_state && old_dcd_state) {
-		struct tty_struct *tty = tty_port_tty_get(&port->port);
-		if (tty && !C_CLOCAL(tty))
-			tty_hangup(tty);
-		tty_kref_put(tty);
-	}
+	if (old_dcd_state != p_priv->dcd_state && old_dcd_state)
+		tty_port_tty_hangup(&port->port, true);
 
 	/* Resubmit urb so we continue receiving */
 	err = usb_submit_urb(urb, GFP_ATOMIC);
@@ -851,7 +837,6 @@ static void	usa90_instat_callback(struct urb *urb)
 	struct usb_serial			*serial;
 	struct usb_serial_port			*port;
 	struct keyspan_port_private	 	*p_priv;
-	struct tty_struct			*tty;
 	int old_dcd_state, err;
 	int status = urb->status;
 
@@ -880,12 +865,8 @@ static void	usa90_instat_callback(struct urb *urb)
 	p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
 	p_priv->ri_state = ((msg->ri) ? 1 : 0);
 
-	if (old_dcd_state != p_priv->dcd_state && old_dcd_state) {
-		tty = tty_port_tty_get(&port->port);
-		if (tty && !C_CLOCAL(tty))
-			tty_hangup(tty);
-		tty_kref_put(tty);
-	}
+	if (old_dcd_state != p_priv->dcd_state && old_dcd_state)
+		tty_port_tty_hangup(&port->port, true);
 
 	/* Resubmit urb so we continue receiving */
 	err = usb_submit_urb(urb, GFP_ATOMIC);
@@ -953,12 +934,8 @@ static void	usa67_instat_callback(struct urb *urb)
 	p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0);
 	p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);
 
-	if (old_dcd_state != p_priv->dcd_state && old_dcd_state) {
-		struct tty_struct *tty = tty_port_tty_get(&port->port);
-		if (tty && !C_CLOCAL(tty))
-			tty_hangup(tty);
-		tty_kref_put(tty);
-	}
+	if (old_dcd_state != p_priv->dcd_state && old_dcd_state)
+		tty_port_tty_hangup(&port->port, true);
 
 	/* Resubmit urb so we continue receiving */
 	err = usb_submit_urb(urb, GFP_ATOMIC);
@@ -1115,7 +1092,6 @@ static void keyspan_dtr_rts(struct usb_serial_port *port, int on)
 static void keyspan_close(struct usb_serial_port *port)
 {
 	int			i;
-	struct usb_serial	*serial = port->serial;
 	struct keyspan_port_private 	*p_priv;
 
 	p_priv = usb_get_serial_port_data(port);
@@ -1123,28 +1099,17 @@ static void keyspan_close(struct usb_serial_port *port)
 	p_priv->rts_state = 0;
 	p_priv->dtr_state = 0;
 
-	if (serial->dev) {
-		keyspan_send_setup(port, 2);
-		/* pilot-xfer seems to work best with this delay */
-		mdelay(100);
-		/* keyspan_set_termios(port, NULL); */
-	}
-
-	/*while (p_priv->outcont_urb->status == -EINPROGRESS) {
-		dev_dbg(&port->dev, "%s - urb in progress\n", __func__);
-	}*/
+	keyspan_send_setup(port, 2);
+	/* pilot-xfer seems to work best with this delay */
+	mdelay(100);
 
 	p_priv->out_flip = 0;
 	p_priv->in_flip = 0;
 
-	if (serial->dev) {
-		/* Stop reading/writing urbs */
-		stop_urb(p_priv->inack_urb);
-		/* stop_urb(p_priv->outcont_urb); */
-		for (i = 0; i < 2; i++) {
-			stop_urb(p_priv->in_urbs[i]);
-			stop_urb(p_priv->out_urbs[i]);
-		}
+	stop_urb(p_priv->inack_urb);
+	for (i = 0; i < 2; i++) {
+		stop_urb(p_priv->in_urbs[i]);
+		stop_urb(p_priv->out_urbs[i]);
 	}
 }
 
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c
index 3b17d5d..5f1d382 100644
--- a/drivers/usb/serial/keyspan_pda.c
+++ b/drivers/usb/serial/keyspan_pda.c
@@ -104,10 +104,8 @@ static void keyspan_pda_wakeup_write(struct work_struct *work)
 	struct keyspan_pda_private *priv =
 		container_of(work, struct keyspan_pda_private, wakeup_work);
 	struct usb_serial_port *port = priv->port;
-	struct tty_struct *tty = tty_port_tty_get(&port->port);
-	if (tty)
-		tty_wakeup(tty);
-	tty_kref_put(tty);
+
+	tty_port_tty_wakeup(&port->port);
 }
 
 static void keyspan_pda_request_unthrottle(struct work_struct *work)
@@ -595,12 +593,10 @@ static void keyspan_pda_dtr_rts(struct usb_serial_port *port, int on)
 {
 	struct usb_serial *serial = port->serial;
 
-	if (serial->dev) {
-		if (on)
-			keyspan_pda_set_modem_info(serial, (1<<7) | (1<< 2));
-		else
-			keyspan_pda_set_modem_info(serial, 0);
-	}
+	if (on)
+		keyspan_pda_set_modem_info(serial, (1 << 7) | (1 << 2));
+	else
+		keyspan_pda_set_modem_info(serial, 0);
 }
 
 
@@ -651,13 +647,8 @@ error:
 }
 static void keyspan_pda_close(struct usb_serial_port *port)
 {
-	struct usb_serial *serial = port->serial;
-
-	if (serial->dev) {
-		/* shutdown our bulk reads and writes */
-		usb_kill_urb(port->write_urb);
-		usb_kill_urb(port->interrupt_in_urb);
-	}
+	usb_kill_urb(port->write_urb);
+	usb_kill_urb(port->interrupt_in_urb);
 }
 
 
diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
index 769d910..1b4054f 100644
--- a/drivers/usb/serial/kl5kusb105.c
+++ b/drivers/usb/serial/kl5kusb105.c
@@ -341,28 +341,20 @@ static void klsi_105_close(struct usb_serial_port *port)
 {
 	int rc;
 
-	mutex_lock(&port->serial->disc_mutex);
-	if (!port->serial->disconnected) {
-		/* send READ_OFF */
-		rc = usb_control_msg(port->serial->dev,
-				     usb_sndctrlpipe(port->serial->dev, 0),
-				     KL5KUSB105A_SIO_CONFIGURE,
-				     USB_TYPE_VENDOR | USB_DIR_OUT,
-				     KL5KUSB105A_SIO_CONFIGURE_READ_OFF,
-				     0, /* index */
-				     NULL, 0,
-				     KLSI_TIMEOUT);
-		if (rc < 0)
-			dev_err(&port->dev,
-				"Disabling read failed (error = %d)\n", rc);
-	}
-	mutex_unlock(&port->serial->disc_mutex);
+	/* send READ_OFF */
+	rc = usb_control_msg(port->serial->dev,
+			     usb_sndctrlpipe(port->serial->dev, 0),
+			     KL5KUSB105A_SIO_CONFIGURE,
+			     USB_TYPE_VENDOR | USB_DIR_OUT,
+			     KL5KUSB105A_SIO_CONFIGURE_READ_OFF,
+			     0, /* index */
+			     NULL, 0,
+			     KLSI_TIMEOUT);
+	if (rc < 0)
+		dev_err(&port->dev, "failed to disable read: %d\n", rc);
 
 	/* shutdown our bulk reads and writes */
 	usb_serial_generic_close(port);
-
-	/* wgg - do I need this? I think so. */
-	usb_kill_urb(port->interrupt_in_urb);
 }
 
 /* We need to write a complete 64-byte data block and encode the
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
index 06d5a60..3353c9e 100644
--- a/drivers/usb/serial/mct_u232.c
+++ b/drivers/usb/serial/mct_u232.c
@@ -35,7 +35,6 @@
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
 #include <linux/serial.h>
-#include <linux/ioctl.h>
 #include "mct_u232.h"
 
 #define DRIVER_AUTHOR "Wolfgang Grandegger <wolfgang@ces.ch>"
@@ -57,10 +56,6 @@ static void mct_u232_break_ctl(struct tty_struct *tty, int break_state);
 static int  mct_u232_tiocmget(struct tty_struct *tty);
 static int  mct_u232_tiocmset(struct tty_struct *tty,
 			unsigned int set, unsigned int clear);
-static int  mct_u232_ioctl(struct tty_struct *tty,
-			unsigned int cmd, unsigned long arg);
-static int  mct_u232_get_icount(struct tty_struct *tty,
-			struct serial_icounter_struct *icount);
 static void mct_u232_throttle(struct tty_struct *tty);
 static void mct_u232_unthrottle(struct tty_struct *tty);
 
@@ -95,11 +90,11 @@ static struct usb_serial_driver mct_u232_device = {
 	.break_ctl =	     mct_u232_break_ctl,
 	.tiocmget =	     mct_u232_tiocmget,
 	.tiocmset =	     mct_u232_tiocmset,
+	.tiocmiwait =        usb_serial_generic_tiocmiwait,
 	.attach =	     mct_u232_startup,
 	.port_probe =        mct_u232_port_probe,
 	.port_remove =       mct_u232_port_remove,
-	.ioctl =             mct_u232_ioctl,
-	.get_icount =        mct_u232_get_icount,
+	.get_icount =        usb_serial_generic_get_icount,
 };
 
 static struct usb_serial_driver * const serial_drivers[] = {
@@ -113,7 +108,6 @@ struct mct_u232_private {
 	unsigned char	     last_lsr;      /* Line Status Register */
 	unsigned char	     last_msr;      /* Modem Status Register */
 	unsigned int	     rx_flags;      /* Throttling flags */
-	struct async_icount  icount;
 };
 
 #define THROTTLED		0x01
@@ -570,7 +564,7 @@ static void mct_u232_read_int_callback(struct urb *urb)
 	/* Record Control Line states */
 	mct_u232_msr_to_state(port, &priv->control_state, priv->last_msr);
 
-	mct_u232_msr_to_icount(&priv->icount, priv->last_msr);
+	mct_u232_msr_to_icount(&port->icount, priv->last_msr);
 
 #if 0
 	/* Not yet handled. See belkin_sa.c for further information */
@@ -598,7 +592,7 @@ static void mct_u232_read_int_callback(struct urb *urb)
 		tty_kref_put(tty);
 	}
 #endif
-	wake_up_interruptible(&port->delta_msr_wait);
+	wake_up_interruptible(&port->port.delta_msr_wait);
 	spin_unlock_irqrestore(&priv->lock, flags);
 exit:
 	retval = usb_submit_urb(urb, GFP_ATOMIC);
@@ -786,86 +780,6 @@ static void mct_u232_unthrottle(struct tty_struct *tty)
 	}
 }
 
-static int  mct_u232_ioctl(struct tty_struct *tty,
-			unsigned int cmd, unsigned long arg)
-{
-	DEFINE_WAIT(wait);
-	struct usb_serial_port *port = tty->driver_data;
-	struct mct_u232_private *mct_u232_port = usb_get_serial_port_data(port);
-	struct async_icount cnow, cprev;
-	unsigned long flags;
-
-	dev_dbg(&port->dev, "%s - cmd = 0x%x\n", __func__, cmd);
-
-	switch (cmd) {
-
-	case TIOCMIWAIT:
-
-		dev_dbg(&port->dev, "%s TIOCMIWAIT", __func__);
-
-		spin_lock_irqsave(&mct_u232_port->lock, flags);
-		cprev = mct_u232_port->icount;
-		spin_unlock_irqrestore(&mct_u232_port->lock, flags);
-		for ( ; ; ) {
-			prepare_to_wait(&port->delta_msr_wait,
-					&wait, TASK_INTERRUPTIBLE);
-			schedule();
-			finish_wait(&port->delta_msr_wait, &wait);
-			/* see if a signal did it */
-			if (signal_pending(current))
-				return -ERESTARTSYS;
-
-			if (port->serial->disconnected)
-				return -EIO;
-
-			spin_lock_irqsave(&mct_u232_port->lock, flags);
-			cnow = mct_u232_port->icount;
-			spin_unlock_irqrestore(&mct_u232_port->lock, flags);
-			if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
-			    cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
-				return -EIO; /* no change => error */
-			if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
-			    ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
-			    ((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) ||
-			    ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) {
-				return 0;
-			}
-			cprev = cnow;
-		}
-
-	}
-	return -ENOIOCTLCMD;
-}
-
-static int  mct_u232_get_icount(struct tty_struct *tty,
-			struct serial_icounter_struct *icount)
-{
-	struct usb_serial_port *port = tty->driver_data;
-	struct mct_u232_private *mct_u232_port = usb_get_serial_port_data(port);
-	struct async_icount *ic = &mct_u232_port->icount;
-	unsigned long flags;
-
-	spin_lock_irqsave(&mct_u232_port->lock, flags);
-
-	icount->cts = ic->cts;
-	icount->dsr = ic->dsr;
-	icount->rng = ic->rng;
-	icount->dcd = ic->dcd;
-	icount->rx = ic->rx;
-	icount->tx = ic->tx;
-	icount->frame = ic->frame;
-	icount->overrun = ic->overrun;
-	icount->parity = ic->parity;
-	icount->brk = ic->brk;
-	icount->buf_overrun = ic->buf_overrun;
-
-	spin_unlock_irqrestore(&mct_u232_port->lock, flags);
-
-	dev_dbg(&port->dev, "%s TIOCGICOUNT RX=%d, TX=%d\n",
-		__func__,  icount->rx, icount->tx);
-	return 0;
-}
-
 module_usb_serial_driver(serial_drivers, id_table);
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
diff --git a/drivers/usb/serial/metro-usb.c b/drivers/usb/serial/metro-usb.c
index bf3c7a2..47e2477 100644
--- a/drivers/usb/serial/metro-usb.c
+++ b/drivers/usb/serial/metro-usb.c
@@ -177,10 +177,7 @@ static void metrousb_cleanup(struct usb_serial_port *port)
 	usb_unlink_urb(port->interrupt_in_urb);
 	usb_kill_urb(port->interrupt_in_urb);
 
-	mutex_lock(&port->serial->disc_mutex);
-	if (!port->serial->disconnected)
-		metrousb_send_unidirectional_cmd(UNI_CMD_CLOSE, port);
-	mutex_unlock(&port->serial->disc_mutex);
+	metrousb_send_unidirectional_cmd(UNI_CMD_CLOSE, port);
 }
 
 static int metrousb_open(struct tty_struct *tty, struct usb_serial_port *port)
diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c
index e0ebec3..cc0e543 100644
--- a/drivers/usb/serial/mos7720.c
+++ b/drivers/usb/serial/mos7720.c
@@ -62,7 +62,6 @@ struct moschip_port {
 	__u8	shadowMCR;		/* last MCR value received */
 	__u8	shadowMSR;		/* last MSR value received */
 	char			open;
-	struct async_icount	icount;
 	struct usb_serial_port	*port;	/* loop back to the owner */
 	struct urb		*write_urb_pool[NUM_URBS];
 };
@@ -932,7 +931,6 @@ static void mos7720_bulk_in_callback(struct urb *urb)
 static void mos7720_bulk_out_data_callback(struct urb *urb)
 {
 	struct moschip_port *mos7720_port;
-	struct tty_struct *tty;
 	int status = urb->status;
 
 	if (status) {
@@ -946,11 +944,8 @@ static void mos7720_bulk_out_data_callback(struct urb *urb)
 		return ;
 	}
 
-	tty = tty_port_tty_get(&mos7720_port->port->port);
-
-	if (tty && mos7720_port->open)
-		tty_wakeup(tty);
-	tty_kref_put(tty);
+	if (mos7720_port->open)
+		tty_port_tty_wakeup(&mos7720_port->port->port);
 }
 
 /*
@@ -1075,9 +1070,6 @@ static int mos7720_open(struct tty_struct *tty, struct usb_serial_port *port)
 		dev_err(&port->dev, "%s - Error %d submitting read urb\n",
 							__func__, response);
 
-	/* initialize our icount structure */
-	memset(&(mos7720_port->icount), 0x00, sizeof(mos7720_port->icount));
-
 	/* initialize our port settings */
 	mos7720_port->shadowMCR = UART_MCR_OUT2; /* Must set to enable ints! */
 
@@ -1144,16 +1136,9 @@ static void mos7720_close(struct usb_serial_port *port)
 	usb_kill_urb(port->write_urb);
 	usb_kill_urb(port->read_urb);
 
-	mutex_lock(&serial->disc_mutex);
-	/* these commands must not be issued if the device has
-	 * been disconnected */
-	if (!serial->disconnected) {
-		write_mos_reg(serial, port->number - port->serial->minor,
-			      MCR, 0x00);
-		write_mos_reg(serial, port->number - port->serial->minor,
-			      IER, 0x00);
-	}
-	mutex_unlock(&serial->disc_mutex);
+	write_mos_reg(serial, port->number - port->serial->minor, MCR, 0x00);
+	write_mos_reg(serial, port->number - port->serial->minor, IER, 0x00);
+
 	mos7720_port->open = 0;
 }
 
@@ -1803,33 +1788,6 @@ static int mos7720_tiocmset(struct tty_struct *tty,
 	return 0;
 }
 
-static int mos7720_get_icount(struct tty_struct *tty,
-				struct serial_icounter_struct *icount)
-{
-	struct usb_serial_port *port = tty->driver_data;
-	struct moschip_port *mos7720_port;
-	struct async_icount cnow;
-
-	mos7720_port = usb_get_serial_port_data(port);
-	cnow = mos7720_port->icount;
-
-	icount->cts = cnow.cts;
-	icount->dsr = cnow.dsr;
-	icount->rng = cnow.rng;
-	icount->dcd = cnow.dcd;
-	icount->rx = cnow.rx;
-	icount->tx = cnow.tx;
-	icount->frame = cnow.frame;
-	icount->overrun = cnow.overrun;
-	icount->parity = cnow.parity;
-	icount->brk = cnow.brk;
-	icount->buf_overrun = cnow.buf_overrun;
-
-	dev_dbg(&port->dev, "%s TIOCGICOUNT RX=%d, TX=%d\n", __func__,
-		icount->rx, icount->tx);
-	return 0;
-}
-
 static int set_modem_info(struct moschip_port *mos7720_port, unsigned int cmd,
 			  unsigned int __user *value)
 {
@@ -1905,8 +1863,6 @@ static int mos7720_ioctl(struct tty_struct *tty,
 {
 	struct usb_serial_port *port = tty->driver_data;
 	struct moschip_port *mos7720_port;
-	struct async_icount cnow;
-	struct async_icount cprev;
 
 	mos7720_port = usb_get_serial_port_data(port);
 	if (mos7720_port == NULL)
@@ -1931,27 +1887,6 @@ static int mos7720_ioctl(struct tty_struct *tty,
 		dev_dbg(&port->dev, "%s TIOCGSERIAL\n", __func__);
 		return get_serial_info(mos7720_port,
 				       (struct serial_struct __user *)arg);
-
-	case TIOCMIWAIT:
-		dev_dbg(&port->dev, "%s TIOCMIWAIT\n", __func__);
-		cprev = mos7720_port->icount;
-		while (1) {
-			if (signal_pending(current))
-				return -ERESTARTSYS;
-			cnow = mos7720_port->icount;
-			if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
-			    cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
-				return -EIO; /* no change => error */
-			if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
-			    ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
-			    ((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) ||
-			    ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) {
-				return 0;
-			}
-			cprev = cnow;
-		}
-		/* NOTREACHED */
-		break;
 	}
 
 	return -ENOIOCTLCMD;
@@ -2107,7 +2042,6 @@ static struct usb_serial_driver moschip7720_2port_driver = {
 	.ioctl			= mos7720_ioctl,
 	.tiocmget		= mos7720_tiocmget,
 	.tiocmset		= mos7720_tiocmset,
-	.get_icount		= mos7720_get_icount,
 	.set_termios		= mos7720_set_termios,
 	.write			= mos7720_write,
 	.write_room		= mos7720_write_room,
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
index b8051fa..a0d5ea5 100644
--- a/drivers/usb/serial/mos7840.c
+++ b/drivers/usb/serial/mos7840.c
@@ -219,8 +219,6 @@ struct moschip_port {
 	char open;
 	char open_ports;
 	wait_queue_head_t wait_chase;	/* for handling sleeping while waiting for chase to finish */
-	int delta_msr_cond;
-	struct async_icount icount;
 	struct usb_serial_port *port;	/* loop back to the owner of this object */
 
 	/* Offsets */
@@ -399,32 +397,22 @@ static void mos7840_handle_new_msr(struct moschip_port *port, __u8 new_msr)
 	struct moschip_port *mos7840_port;
 	struct async_icount *icount;
 	mos7840_port = port;
-	icount = &mos7840_port->icount;
 	if (new_msr &
 	    (MOS_MSR_DELTA_CTS | MOS_MSR_DELTA_DSR | MOS_MSR_DELTA_RI |
 	     MOS_MSR_DELTA_CD)) {
-		icount = &mos7840_port->icount;
+		icount = &mos7840_port->port->icount;
 
 		/* update input line counters */
-		if (new_msr & MOS_MSR_DELTA_CTS) {
+		if (new_msr & MOS_MSR_DELTA_CTS)
 			icount->cts++;
-			smp_wmb();
-		}
-		if (new_msr & MOS_MSR_DELTA_DSR) {
+		if (new_msr & MOS_MSR_DELTA_DSR)
 			icount->dsr++;
-			smp_wmb();
-		}
-		if (new_msr & MOS_MSR_DELTA_CD) {
+		if (new_msr & MOS_MSR_DELTA_CD)
 			icount->dcd++;
-			smp_wmb();
-		}
-		if (new_msr & MOS_MSR_DELTA_RI) {
+		if (new_msr & MOS_MSR_DELTA_RI)
 			icount->rng++;
-			smp_wmb();
-		}
 
-		mos7840_port->delta_msr_cond = 1;
-		wake_up_interruptible(&port->port->delta_msr_wait);
+		wake_up_interruptible(&port->port->port.delta_msr_wait);
 	}
 }
 
@@ -442,23 +430,15 @@ static void mos7840_handle_new_lsr(struct moschip_port *port, __u8 new_lsr)
 	}
 
 	/* update input line counters */
-	icount = &port->icount;
-	if (new_lsr & SERIAL_LSR_BI) {
+	icount = &port->port->icount;
+	if (new_lsr & SERIAL_LSR_BI)
 		icount->brk++;
-		smp_wmb();
-	}
-	if (new_lsr & SERIAL_LSR_OE) {
+	if (new_lsr & SERIAL_LSR_OE)
 		icount->overrun++;
-		smp_wmb();
-	}
-	if (new_lsr & SERIAL_LSR_PE) {
+	if (new_lsr & SERIAL_LSR_PE)
 		icount->parity++;
-		smp_wmb();
-	}
-	if (new_lsr & SERIAL_LSR_FE) {
+	if (new_lsr & SERIAL_LSR_FE)
 		icount->frame++;
-		smp_wmb();
-	}
 }
 
 /************************************************************************/
@@ -777,9 +757,8 @@ static void mos7840_bulk_in_callback(struct urb *urb)
 		struct tty_port *tport = &mos7840_port->port->port;
 		tty_insert_flip_string(tport, data, urb->actual_length);
 		tty_flip_buffer_push(tport);
-		mos7840_port->icount.rx += urb->actual_length;
-		smp_wmb();
-		dev_dbg(&port->dev, "mos7840_port->icount.rx is %d:\n", mos7840_port->icount.rx);
+		port->icount.rx += urb->actual_length;
+		dev_dbg(&port->dev, "icount.rx is %d:\n", port->icount.rx);
 	}
 
 	if (!mos7840_port->read_urb) {
@@ -816,7 +795,6 @@ static void mos7840_bulk_out_data_callback(struct urb *urb)
 {
 	struct moschip_port *mos7840_port;
 	struct usb_serial_port *port;
-	struct tty_struct *tty;
 	int status = urb->status;
 	int i;
 
@@ -839,10 +817,8 @@ static void mos7840_bulk_out_data_callback(struct urb *urb)
 	if (mos7840_port_paranoia_check(port, __func__))
 		return;
 
-	tty = tty_port_tty_get(&port->port);
-	if (tty && mos7840_port->open)
-		tty_wakeup(tty);
-	tty_kref_put(tty);
+	if (mos7840_port->open)
+		tty_port_tty_wakeup(&port->port);
 
 }
 
@@ -1130,17 +1106,12 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port)
 	/* initialize our wait queues */
 	init_waitqueue_head(&mos7840_port->wait_chase);
 
-	/* initialize our icount structure */
-	memset(&(mos7840_port->icount), 0x00, sizeof(mos7840_port->icount));
-
 	/* initialize our port settings */
 	/* Must set to enable ints! */
 	mos7840_port->shadowMCR = MCR_MASTER_IE;
 	/* send a open port command */
 	mos7840_port->open = 1;
 	/* mos7840_change_port_settings(mos7840_port,old_termios); */
-	mos7840_port->icount.tx = 0;
-	mos7840_port->icount.rx = 0;
 
 	return 0;
 }
@@ -1223,25 +1194,10 @@ static void mos7840_close(struct usb_serial_port *port)
 		}
 	}
 
-	/* While closing port, shutdown all bulk read, write  *
-	 * and interrupt read if they exists                  */
-	if (serial->dev) {
-		if (mos7840_port->write_urb) {
-			dev_dbg(&port->dev, "%s", "Shutdown bulk write\n");
-			usb_kill_urb(mos7840_port->write_urb);
-		}
-		if (mos7840_port->read_urb) {
-			dev_dbg(&port->dev, "%s", "Shutdown bulk read\n");
-			usb_kill_urb(mos7840_port->read_urb);
-			mos7840_port->read_urb_busy = false;
-		}
-		if ((&mos7840_port->control_urb)) {
-			dev_dbg(&port->dev, "%s", "Shutdown control read\n");
-			/*/      usb_kill_urb (mos7840_port->control_urb); */
-		}
-	}
-/*      if(mos7840_port->ctrl_buf != NULL) */
-/*              kfree(mos7840_port->ctrl_buf); */
+	usb_kill_urb(mos7840_port->write_urb);
+	usb_kill_urb(mos7840_port->read_urb);
+	mos7840_port->read_urb_busy = false;
+
 	port0->open_ports--;
 	dev_dbg(&port->dev, "%s in close%d:in port%d\n", __func__, port0->open_ports, port->number);
 	if (port0->open_ports == 0) {
@@ -1253,8 +1209,7 @@ static void mos7840_close(struct usb_serial_port *port)
 
 	if (mos7840_port->write_urb) {
 		/* if this urb had a transfer buffer already (old tx) free it */
-		if (mos7840_port->write_urb->transfer_buffer != NULL)
-			kfree(mos7840_port->write_urb->transfer_buffer);
+		kfree(mos7840_port->write_urb->transfer_buffer);
 		usb_free_urb(mos7840_port->write_urb);
 	}
 
@@ -1331,9 +1286,8 @@ static void mos7840_break(struct tty_struct *tty, int break_state)
 	if (mos7840_port == NULL)
 		return;
 
-	if (serial->dev)
-		/* flush and block until tx is empty */
-		mos7840_block_until_chase_response(tty, mos7840_port);
+	/* flush and block until tx is empty */
+	mos7840_block_until_chase_response(tty, mos7840_port);
 
 	if (break_state == -1)
 		data = mos7840_port->shadowLCR | LCR_SET_BREAK;
@@ -1523,9 +1477,8 @@ static int mos7840_write(struct tty_struct *tty, struct usb_serial_port *port,
 		goto exit;
 	}
 	bytes_sent = transfer_size;
-	mos7840_port->icount.tx += transfer_size;
-	smp_wmb();
-	dev_dbg(&port->dev, "mos7840_port->icount.tx is %d:\n", mos7840_port->icount.tx);
+	port->icount.tx += transfer_size;
+	dev_dbg(&port->dev, "icount.tx is %d:\n", port->icount.tx);
 exit:
 	return bytes_sent;
 
@@ -2144,34 +2097,6 @@ static int mos7840_get_serial_info(struct moschip_port *mos7840_port,
 	return 0;
 }
 
-static int mos7840_get_icount(struct tty_struct *tty,
-			struct serial_icounter_struct *icount)
-{
-	struct usb_serial_port *port = tty->driver_data;
-	struct moschip_port *mos7840_port;
-	struct async_icount cnow;
-
-	mos7840_port = mos7840_get_port_private(port);
-	cnow = mos7840_port->icount;
-
-	smp_rmb();
-	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;
-
-	dev_dbg(&port->dev, "%s TIOCGICOUNT RX=%d, TX=%d\n", __func__,
-		icount->rx, icount->tx);
-	return 0;
-}
-
 /*****************************************************************************
  * SerialIoctl
  *	this function handles any ioctl calls to the driver
@@ -2184,9 +2109,6 @@ static int mos7840_ioctl(struct tty_struct *tty,
 	void __user *argp = (void __user *)arg;
 	struct moschip_port *mos7840_port;
 
-	struct async_icount cnow;
-	struct async_icount cprev;
-
 	if (mos7840_port_paranoia_check(port, __func__))
 		return -1;
 
@@ -2211,41 +2133,6 @@ static int mos7840_ioctl(struct tty_struct *tty,
 	case TIOCSSERIAL:
 		dev_dbg(&port->dev, "%s TIOCSSERIAL\n", __func__);
 		break;
-
-	case TIOCMIWAIT:
-		dev_dbg(&port->dev, "%s  TIOCMIWAIT\n", __func__);
-		cprev = mos7840_port->icount;
-		while (1) {
-			/* interruptible_sleep_on(&mos7840_port->delta_msr_wait); */
-			mos7840_port->delta_msr_cond = 0;
-			wait_event_interruptible(port->delta_msr_wait,
-						 (port->serial->disconnected ||
-						  mos7840_port->
-						  delta_msr_cond == 1));
-
-			/* see if a signal did it */
-			if (signal_pending(current))
-				return -ERESTARTSYS;
-
-			if (port->serial->disconnected)
-				return -EIO;
-
-			cnow = mos7840_port->icount;
-			smp_rmb();
-			if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
-			    cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
-				return -EIO;	/* no change => error */
-			if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
-			    ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
-			    ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
-			    ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) {
-				return 0;
-			}
-			cprev = cnow;
-		}
-		/* NOTREACHED */
-		break;
-
 	default:
 		break;
 	}
@@ -2592,7 +2479,8 @@ static struct usb_serial_driver moschip7840_4port_device = {
 	.break_ctl = mos7840_break,
 	.tiocmget = mos7840_tiocmget,
 	.tiocmset = mos7840_tiocmset,
-	.get_icount = mos7840_get_icount,
+	.tiocmiwait = usb_serial_generic_tiocmiwait,
+	.get_icount = usb_serial_generic_get_icount,
 	.port_probe = mos7840_port_probe,
 	.port_remove = mos7840_port_remove,
 	.read_bulk_callback = mos7840_bulk_in_callback,
diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c
index e13e1a4..5f4b0cd 100644
--- a/drivers/usb/serial/opticon.c
+++ b/drivers/usb/serial/opticon.c
@@ -120,7 +120,10 @@ static int send_control_msg(struct usb_serial_port *port, u8 requesttype,
 				0, 0, buffer, 1, 0);
 	kfree(buffer);
 
-	return retval;
+	if (retval < 0)
+		return retval;
+
+	return 0;
 }
 
 static int opticon_open(struct tty_struct *tty, struct usb_serial_port *port)
@@ -306,7 +309,6 @@ static int opticon_tiocmset(struct tty_struct *tty,
 			   unsigned int set, unsigned int clear)
 {
 	struct usb_serial_port *port = tty->driver_data;
-	struct usb_serial *serial = port->serial;
 	struct opticon_private *priv = usb_get_serial_port_data(port);
 	unsigned long flags;
 	bool rts;
@@ -327,15 +329,11 @@ static int opticon_tiocmset(struct tty_struct *tty,
 	if (!changed)
 		return 0;
 
-	/* Send the new RTS state to the connected device */
-	mutex_lock(&serial->disc_mutex);
-	if (!serial->disconnected)
-		ret = send_control_msg(port, CONTROL_RTS, !rts);
-	else
-		ret = -ENODEV;
-	mutex_unlock(&serial->disc_mutex);
+	ret = send_control_msg(port, CONTROL_RTS, !rts);
+	if (ret)
+		return usb_translate_errors(ret);
 
-	return ret;
+	return 0;
 }
 
 static int get_serial_info(struct usb_serial_port *port,
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index 558adfc..09cd396 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -1537,13 +1537,8 @@ static void option_instat_callback(struct urb *urb)
 			portdata->dsr_state = ((signals & 0x02) ? 1 : 0);
 			portdata->ri_state = ((signals & 0x08) ? 1 : 0);
 
-			if (old_dcd_state && !portdata->dcd_state) {
-				struct tty_struct *tty =
-						tty_port_tty_get(&port->port);
-				if (tty && !C_CLOCAL(tty))
-					tty_hangup(tty);
-				tty_kref_put(tty);
-			}
+			if (old_dcd_state && !portdata->dcd_state)
+				tty_port_tty_hangup(&port->port, true);
 		} else {
 			dev_dbg(dev, "%s: type %x req %x\n", __func__,
 				req_pkt->bRequestType, req_pkt->bRequest);
diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c
index 87c71cc..7e3e078 100644
--- a/drivers/usb/serial/oti6858.c
+++ b/drivers/usb/serial/oti6858.c
@@ -124,8 +124,6 @@ static void oti6858_close(struct usb_serial_port *port);
 static void oti6858_set_termios(struct tty_struct *tty,
 			struct usb_serial_port *port, struct ktermios *old);
 static void oti6858_init_termios(struct tty_struct *tty);
-static int oti6858_ioctl(struct tty_struct *tty,
-			unsigned int cmd, unsigned long arg);
 static void oti6858_read_int_callback(struct urb *urb);
 static void oti6858_read_bulk_callback(struct urb *urb);
 static void oti6858_write_bulk_callback(struct urb *urb);
@@ -136,6 +134,7 @@ static int oti6858_chars_in_buffer(struct tty_struct *tty);
 static int oti6858_tiocmget(struct tty_struct *tty);
 static int oti6858_tiocmset(struct tty_struct *tty,
 				unsigned int set, unsigned int clear);
+static int oti6858_tiocmiwait(struct tty_struct *tty, unsigned long arg);
 static int oti6858_port_probe(struct usb_serial_port *port);
 static int oti6858_port_remove(struct usb_serial_port *port);
 
@@ -150,11 +149,11 @@ static struct usb_serial_driver oti6858_device = {
 	.open =			oti6858_open,
 	.close =		oti6858_close,
 	.write =		oti6858_write,
-	.ioctl =		oti6858_ioctl,
 	.set_termios =		oti6858_set_termios,
 	.init_termios = 	oti6858_init_termios,
 	.tiocmget =		oti6858_tiocmget,
 	.tiocmset =		oti6858_tiocmset,
+	.tiocmiwait =		oti6858_tiocmiwait,
 	.read_bulk_callback =	oti6858_read_bulk_callback,
 	.read_int_callback =	oti6858_read_int_callback,
 	.write_bulk_callback =	oti6858_write_bulk_callback,
@@ -650,8 +649,9 @@ static int oti6858_tiocmget(struct tty_struct *tty)
 	return result;
 }
 
-static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
+static int oti6858_tiocmiwait(struct tty_struct *tty, unsigned long arg)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct oti6858_private *priv = usb_get_serial_port_data(port);
 	unsigned long flags;
 	unsigned int prev, status;
@@ -662,7 +662,7 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	while (1) {
-		wait_event_interruptible(port->delta_msr_wait,
+		wait_event_interruptible(port->port.delta_msr_wait,
 					port->serial->disconnected ||
 					priv->status.pin_state != prev);
 		if (signal_pending(current))
@@ -689,24 +689,6 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
 	return 0;
 }
 
-static int oti6858_ioctl(struct tty_struct *tty,
-			unsigned int cmd, unsigned long arg)
-{
-	struct usb_serial_port *port = tty->driver_data;
-
-	dev_dbg(&port->dev, "%s(cmd = 0x%04x, arg = 0x%08lx)\n", __func__, cmd, arg);
-
-	switch (cmd) {
-	case TIOCMIWAIT:
-		dev_dbg(&port->dev, "%s(): TIOCMIWAIT\n", __func__);
-		return wait_modem_info(port, arg);
-	default:
-		dev_dbg(&port->dev, "%s(): 0x%04x not supported\n", __func__, cmd);
-		break;
-	}
-	return -ENOIOCTLCMD;
-}
-
 static void oti6858_read_int_callback(struct urb *urb)
 {
 	struct usb_serial_port *port =  urb->context;
@@ -765,7 +747,7 @@ static void oti6858_read_int_callback(struct urb *urb)
 
 		if (!priv->transient) {
 			if (xs->pin_state != priv->status.pin_state)
-				wake_up_interruptible(&port->delta_msr_wait);
+				wake_up_interruptible(&port->port.delta_msr_wait);
 			memcpy(&priv->status, xs, OTI6858_CTRL_PKT_SIZE);
 		}
 
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 3b10018..7151659 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -149,7 +149,7 @@ static int pl2303_vendor_read(__u16 value, __u16 index,
 	int res = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
 			VENDOR_READ_REQUEST, VENDOR_READ_REQUEST_TYPE,
 			value, index, buf, 1, 100);
-	dev_dbg(&serial->dev->dev, "0x%x:0x%x:0x%x:0x%x  %d - %x\n",
+	dev_dbg(&serial->interface->dev, "0x%x:0x%x:0x%x:0x%x  %d - %x\n",
 		VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, value, index,
 		res, buf[0]);
 	return res;
@@ -161,7 +161,7 @@ static int pl2303_vendor_write(__u16 value, __u16 index,
 	int res = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
 			VENDOR_WRITE_REQUEST, VENDOR_WRITE_REQUEST_TYPE,
 			value, index, NULL, 0, 100);
-	dev_dbg(&serial->dev->dev, "0x%x:0x%x:0x%x:0x%x  %d\n",
+	dev_dbg(&serial->interface->dev, "0x%x:0x%x:0x%x:0x%x  %d\n",
 		VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, value, index,
 		res);
 	return res;
@@ -248,14 +248,15 @@ static int pl2303_port_remove(struct usb_serial_port *port)
 	return 0;
 }
 
-static int set_control_lines(struct usb_device *dev, u8 value)
+static int pl2303_set_control_lines(struct usb_serial_port *port, u8 value)
 {
+	struct usb_device *dev = port->serial->dev;
 	int retval;
 
 	retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
 				 SET_CONTROL_REQUEST, SET_CONTROL_REQUEST_TYPE,
 				 value, 0, NULL, 0, 100);
-	dev_dbg(&dev->dev, "%s - value = %d, retval = %d\n", __func__,
+	dev_dbg(&port->dev, "%s - value = %d, retval = %d\n", __func__,
 		value, retval);
 	return retval;
 }
@@ -437,7 +438,7 @@ static void pl2303_set_termios(struct tty_struct *tty,
 	if (control != priv->line_control) {
 		control = priv->line_control;
 		spin_unlock_irqrestore(&priv->lock, flags);
-		set_control_lines(serial->dev, control);
+		pl2303_set_control_lines(port, control);
 	} else {
 		spin_unlock_irqrestore(&priv->lock, flags);
 	}
@@ -480,7 +481,7 @@ static void pl2303_dtr_rts(struct usb_serial_port *port, int on)
 		priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS);
 	control = priv->line_control;
 	spin_unlock_irqrestore(&priv->lock, flags);
-	set_control_lines(port->serial->dev, control);
+	pl2303_set_control_lines(port, control);
 }
 
 static void pl2303_close(struct usb_serial_port *port)
@@ -530,7 +531,6 @@ static int pl2303_tiocmset(struct tty_struct *tty,
 			   unsigned int set, unsigned int clear)
 {
 	struct usb_serial_port *port = tty->driver_data;
-	struct usb_serial *serial = port->serial;
 	struct pl2303_private *priv = usb_get_serial_port_data(port);
 	unsigned long flags;
 	u8 control;
@@ -548,14 +548,11 @@ static int pl2303_tiocmset(struct tty_struct *tty,
 	control = priv->line_control;
 	spin_unlock_irqrestore(&priv->lock, flags);
 
-	mutex_lock(&serial->disc_mutex);
-	if (!serial->disconnected)
-		ret = set_control_lines(serial->dev, control);
-	else
-		ret = -ENODEV;
-	mutex_unlock(&serial->disc_mutex);
+	ret = pl2303_set_control_lines(port, control);
+	if (ret)
+		return usb_translate_errors(ret);
 
-	return ret;
+	return 0;
 }
 
 static int pl2303_tiocmget(struct tty_struct *tty)
@@ -592,8 +589,9 @@ static int pl2303_carrier_raised(struct usb_serial_port *port)
 	return 0;
 }
 
-static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
+static int pl2303_tiocmiwait(struct tty_struct *tty, unsigned long arg)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct pl2303_private *priv = usb_get_serial_port_data(port);
 	unsigned long flags;
 	unsigned int prevstatus;
@@ -605,7 +603,7 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	while (1) {
-		interruptible_sleep_on(&port->delta_msr_wait);
+		interruptible_sleep_on(&port->port.delta_msr_wait);
 		/* see if a signal did it */
 		if (signal_pending(current))
 			return -ERESTARTSYS;
@@ -651,10 +649,6 @@ static int pl2303_ioctl(struct tty_struct *tty,
 			return -EFAULT;
 
 		return 0;
-
-	case TIOCMIWAIT:
-		dev_dbg(&port->dev, "%s TIOCMIWAIT\n", __func__);
-		return wait_modem_info(port, arg);
 	default:
 		dev_dbg(&port->dev, "%s not supported = 0x%04x\n", __func__, cmd);
 		break;
@@ -720,7 +714,7 @@ static void pl2303_update_line_status(struct usb_serial_port *port,
 	spin_unlock_irqrestore(&priv->lock, flags);
 	if (priv->line_status & UART_BREAK_ERROR)
 		usb_serial_handle_break(port);
-	wake_up_interruptible(&port->delta_msr_wait);
+	wake_up_interruptible(&port->port.delta_msr_wait);
 
 	tty = tty_port_tty_get(&port->port);
 	if (!tty)
@@ -784,7 +778,7 @@ static void pl2303_process_read_urb(struct urb *urb)
 	line_status = priv->line_status;
 	priv->line_status &= ~UART_STATE_TRANSIENT_MASK;
 	spin_unlock_irqrestore(&priv->lock, flags);
-	wake_up_interruptible(&port->delta_msr_wait);
+	wake_up_interruptible(&port->port.delta_msr_wait);
 
 	if (!urb->actual_length)
 		return;
@@ -835,6 +829,7 @@ static struct usb_serial_driver pl2303_device = {
 	.set_termios =		pl2303_set_termios,
 	.tiocmget =		pl2303_tiocmget,
 	.tiocmset =		pl2303_tiocmset,
+	.tiocmiwait =		pl2303_tiocmiwait,
 	.process_read_urb =	pl2303_process_read_urb,
 	.read_int_callback =	pl2303_read_int_callback,
 	.attach =		pl2303_startup,
diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c
index 75f125d..02b0803 100644
--- a/drivers/usb/serial/quatech2.c
+++ b/drivers/usb/serial/quatech2.c
@@ -116,7 +116,6 @@ struct qt2_serial_private {
 };
 
 struct qt2_port_private {
-	bool is_open;
 	u8   device_port;
 
 	spinlock_t urb_lock;
@@ -128,8 +127,6 @@ struct qt2_port_private {
 	u8          shadowLSR;
 	u8          shadowMSR;
 
-	struct async_icount icount;
-
 	struct usb_serial_port *port;
 };
 
@@ -397,7 +394,6 @@ static int qt2_open(struct tty_struct *tty, struct usb_serial_port *port)
 		return status;
 	}
 
-	port_priv->is_open = true;
 	port_priv->device_port = (u8) device_port;
 
 	if (tty)
@@ -417,19 +413,11 @@ static void qt2_close(struct usb_serial_port *port)
 	serial = port->serial;
 	port_priv = usb_get_serial_port_data(port);
 
-	port_priv->is_open = false;
-
 	spin_lock_irqsave(&port_priv->urb_lock, flags);
 	usb_kill_urb(port_priv->write_urb);
 	port_priv->urb_in_use = false;
 	spin_unlock_irqrestore(&port_priv->urb_lock, flags);
 
-	mutex_lock(&port->serial->disc_mutex);
-	if (port->serial->disconnected) {
-		mutex_unlock(&port->serial->disc_mutex);
-		return;
-	}
-
 	/* flush the port transmit buffer */
 	i = usb_control_msg(serial->dev,
 			    usb_rcvctrlpipe(serial->dev, 0),
@@ -460,8 +448,6 @@ static void qt2_close(struct usb_serial_port *port)
 	if (i < 0)
 		dev_err(&port->dev, "%s - close port failed %i\n",
 			__func__, i);
-
-	mutex_unlock(&port->serial->disc_mutex);
 }
 
 static void qt2_disconnect(struct usb_serial *serial)
@@ -494,71 +480,6 @@ static int get_serial_info(struct usb_serial_port *port,
 	return 0;
 }
 
-static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
-{
-	struct qt2_port_private *priv = usb_get_serial_port_data(port);
-	struct async_icount prev, cur;
-	unsigned long flags;
-
-	spin_lock_irqsave(&priv->lock, flags);
-	prev = priv->icount;
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	while (1) {
-		wait_event_interruptible(port->delta_msr_wait,
-					 (port->serial->disconnected ||
-					  (priv->icount.rng != prev.rng) ||
-					  (priv->icount.dsr != prev.dsr) ||
-					  (priv->icount.dcd != prev.dcd) ||
-					  (priv->icount.cts != prev.cts)));
-
-		if (signal_pending(current))
-			return -ERESTARTSYS;
-
-		if (port->serial->disconnected)
-			return -EIO;
-
-		spin_lock_irqsave(&priv->lock, flags);
-		cur = priv->icount;
-		spin_unlock_irqrestore(&priv->lock, flags);
-
-		if ((prev.rng == cur.rng) &&
-		    (prev.dsr == cur.dsr) &&
-		    (prev.dcd == cur.dcd) &&
-		    (prev.cts == cur.cts))
-			return -EIO;
-
-		if ((arg & TIOCM_RNG && (prev.rng != cur.rng)) ||
-		    (arg & TIOCM_DSR && (prev.dsr != cur.dsr)) ||
-		    (arg & TIOCM_CD && (prev.dcd != cur.dcd)) ||
-		    (arg & TIOCM_CTS && (prev.cts != cur.cts)))
-			return 0;
-	}
-	return 0;
-}
-
-static int qt2_get_icount(struct tty_struct *tty,
-			  struct serial_icounter_struct *icount)
-{
-	struct usb_serial_port *port = tty->driver_data;
-	struct qt2_port_private *priv = usb_get_serial_port_data(port);
-	struct async_icount cnow = priv->icount;
-
-	icount->cts = cnow.cts;
-	icount->dsr = cnow.dsr;
-	icount->rng = cnow.rng;
-	icount->dcd = cnow.dcd;
-	icount->rx = cnow.rx;
-	icount->tx = cnow.tx;
-	icount->frame = cnow.frame;
-	icount->overrun = cnow.overrun;
-	icount->parity = cnow.parity;
-	icount->brk = cnow.brk;
-	icount->buf_overrun = cnow.buf_overrun;
-
-	return 0;
-}
-
 static int qt2_ioctl(struct tty_struct *tty,
 		     unsigned int cmd, unsigned long arg)
 {
@@ -568,10 +489,6 @@ static int qt2_ioctl(struct tty_struct *tty,
 	case TIOCGSERIAL:
 		return get_serial_info(port,
 				       (struct serial_struct __user *)arg);
-
-	case TIOCMIWAIT:
-		return wait_modem_info(port, arg);
-
 	default:
 		break;
 	}
@@ -664,9 +581,7 @@ void qt2_process_read_urb(struct urb *urb)
 						 __func__);
 					break;
 				}
-
-				if (port_priv->is_open)
-					tty_flip_buffer_push(&port->port);
+				tty_flip_buffer_push(&port->port);
 
 				newport = *(ch + 3);
 
@@ -709,8 +624,7 @@ void qt2_process_read_urb(struct urb *urb)
 		tty_insert_flip_string(&port->port, ch, 1);
 	}
 
-	if (port_priv->is_open)
-		tty_flip_buffer_push(&port->port);
+	tty_flip_buffer_push(&port->port);
 }
 
 static void qt2_write_bulk_callback(struct urb *urb)
@@ -910,12 +824,6 @@ static void qt2_break_ctl(struct tty_struct *tty, int break_state)
 
 	port_priv = usb_get_serial_port_data(port);
 
-	if (!port_priv->is_open) {
-		dev_err(&port->dev,
-			"%s - port is not open\n", __func__);
-		return;
-	}
-
 	val = (break_state == -1) ? 1 : 0;
 
 	status = qt2_control_msg(port->serial->dev, QT2_BREAK_CONTROL,
@@ -961,18 +869,15 @@ static void qt2_update_msr(struct usb_serial_port *port, unsigned char *ch)
 	if (newMSR & UART_MSR_ANY_DELTA) {
 		/* update input line counters */
 		if (newMSR & UART_MSR_DCTS)
-			port_priv->icount.cts++;
-
+			port->icount.cts++;
 		if (newMSR & UART_MSR_DDSR)
-			port_priv->icount.dsr++;
-
+			port->icount.dsr++;
 		if (newMSR & UART_MSR_DDCD)
-			port_priv->icount.dcd++;
-
+			port->icount.dcd++;
 		if (newMSR & UART_MSR_TERI)
-			port_priv->icount.rng++;
+			port->icount.rng++;
 
-		wake_up_interruptible(&port->delta_msr_wait);
+		wake_up_interruptible(&port->port.delta_msr_wait);
 	}
 }
 
@@ -992,7 +897,7 @@ static void qt2_update_lsr(struct usb_serial_port *port, unsigned char *ch)
 	port_priv->shadowLSR = newLSR;
 	spin_unlock_irqrestore(&port_priv->lock, flags);
 
-	icount = &port_priv->icount;
+	icount = &port->icount;
 
 	if (newLSR & UART_LSR_BRK_ERROR_BITS) {
 
@@ -1102,7 +1007,8 @@ static struct usb_serial_driver qt2_device = {
 	.break_ctl           = qt2_break_ctl,
 	.tiocmget            = qt2_tiocmget,
 	.tiocmset            = qt2_tiocmset,
-	.get_icount	     = qt2_get_icount,
+	.tiocmiwait          = usb_serial_generic_tiocmiwait,
+	.get_icount	     = usb_serial_generic_get_icount,
 	.ioctl               = qt2_ioctl,
 	.set_termios         = qt2_set_termios,
 };
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c
index c13f6e7..8894665 100644
--- a/drivers/usb/serial/sierra.c
+++ b/drivers/usb/serial/sierra.c
@@ -628,7 +628,6 @@ static void sierra_instat_callback(struct urb *urb)
 			unsigned char signals = *((unsigned char *)
 					urb->transfer_buffer +
 					sizeof(struct usb_ctrlrequest));
-			struct tty_struct *tty;
 
 			dev_dbg(&port->dev, "%s: signal x%x\n", __func__,
 				signals);
@@ -639,11 +638,8 @@ static void sierra_instat_callback(struct urb *urb)
 			portdata->dsr_state = ((signals & 0x02) ? 1 : 0);
 			portdata->ri_state = ((signals & 0x08) ? 1 : 0);
 
-			tty = tty_port_tty_get(&port->port);
-			if (tty && !C_CLOCAL(tty) &&
-					old_dcd_state && !portdata->dcd_state)
-				tty_hangup(tty);
-			tty_kref_put(tty);
+			if (old_dcd_state && !portdata->dcd_state)
+				tty_port_tty_hangup(&port->port, true);
 		} else {
 			dev_dbg(&port->dev, "%s: type %x req %x\n",
 				__func__, req_pkt->bRequestType,
@@ -778,30 +774,25 @@ static void sierra_close(struct usb_serial_port *port)
 	portdata->rts_state = 0;
 	portdata->dtr_state = 0;
 
-	if (serial->dev) {
-		mutex_lock(&serial->disc_mutex);
-		if (!serial->disconnected) {
-			serial->interface->needs_remote_wakeup = 0;
-			/* odd error handling due to pm counters */
-			if (!usb_autopm_get_interface(serial->interface))
-				sierra_send_setup(port);
-			else
-				usb_autopm_get_interface_no_resume(serial->interface);
-				
-		}
-		mutex_unlock(&serial->disc_mutex);
-		spin_lock_irq(&intfdata->susp_lock);
-		portdata->opened = 0;
-		spin_unlock_irq(&intfdata->susp_lock);
+	mutex_lock(&serial->disc_mutex);
+	if (!serial->disconnected) {
+		serial->interface->needs_remote_wakeup = 0;
+		/* odd error handling due to pm counters */
+		if (!usb_autopm_get_interface(serial->interface))
+			sierra_send_setup(port);
+		else
+			usb_autopm_get_interface_no_resume(serial->interface);
 
+	}
+	mutex_unlock(&serial->disc_mutex);
+	spin_lock_irq(&intfdata->susp_lock);
+	portdata->opened = 0;
+	spin_unlock_irq(&intfdata->susp_lock);
 
-		/* Stop reading urbs */
-		sierra_stop_rx_urbs(port);
-		/* .. and release them */
-		for (i = 0; i < portdata->num_in_urbs; i++) {
-			sierra_release_urb(portdata->in_urbs[i]);
-			portdata->in_urbs[i] = NULL;
-		}
+	sierra_stop_rx_urbs(port);
+	for (i = 0; i < portdata->num_in_urbs; i++) {
+		sierra_release_urb(portdata->in_urbs[i]);
+		portdata->in_urbs[i] = NULL;
 	}
 }
 
diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c
index 549ef68..cf3df79 100644
--- a/drivers/usb/serial/spcp8x5.c
+++ b/drivers/usb/serial/spcp8x5.c
@@ -1,7 +1,7 @@
 /*
  * spcp8x5 USB to serial adaptor driver
  *
- * Copyright (C) 2010 Johan Hovold (jhovold@gmail.com)
+ * Copyright (C) 2010-2013 Johan Hovold (jhovold@gmail.com)
  * Copyright (C) 2006 Linxb (xubin.lin@worldplus.com.cn)
  * Copyright (C) 2006 S1 Corp.
  *
@@ -13,8 +13,6 @@
  *	it under the terms of the GNU General Public License as published by
  *	the Free Software Foundation; either version 2 of the License, or
  *	(at your option) any later version.
- *
- *
  */
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -28,7 +26,10 @@
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
 
-#define DRIVER_DESC 	"SPCP8x5 USB to serial adaptor driver"
+#define DRIVER_DESC	"SPCP8x5 USB to serial adaptor driver"
+
+#define SPCP825_QUIRK_NO_UART_STATUS	0x01
+#define SPCP825_QUIRK_NO_WORK_MODE	0x02
 
 #define SPCP8x5_007_VID		0x04FC
 #define SPCP8x5_007_PID		0x0201
@@ -46,13 +47,15 @@ static const struct usb_device_id id_table[] = {
 	{ USB_DEVICE(SPCP8x5_INTERMATIC_VID, SPCP8x5_INTERMATIC_PID)},
 	{ USB_DEVICE(SPCP8x5_835_VID, SPCP8x5_835_PID)},
 	{ USB_DEVICE(SPCP8x5_008_VID, SPCP8x5_008_PID)},
-	{ USB_DEVICE(SPCP8x5_007_VID, SPCP8x5_007_PID)},
+	{ USB_DEVICE(SPCP8x5_007_VID, SPCP8x5_007_PID),
+	  .driver_info = SPCP825_QUIRK_NO_UART_STATUS |
+				SPCP825_QUIRK_NO_WORK_MODE },
 	{ }					/* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, id_table);
 
 struct spcp8x5_usb_ctrl_arg {
-	u8 	type;
+	u8	type;
 	u8	cmd;
 	u8	cmd_type;
 	u16	value;
@@ -138,49 +141,33 @@ struct spcp8x5_usb_ctrl_arg {
 #define UART_OVERRUN_ERROR		0x40
 #define UART_CTS			0x80
 
-enum spcp8x5_type {
-	SPCP825_007_TYPE,
-	SPCP825_008_TYPE,
-	SPCP825_PHILIP_TYPE,
-	SPCP825_INTERMATIC_TYPE,
-	SPCP835_TYPE,
-};
-
 struct spcp8x5_private {
-	spinlock_t 	lock;
-	enum spcp8x5_type	type;
-	u8 			line_control;
-	u8 			line_status;
+	unsigned		quirks;
+	spinlock_t		lock;
+	u8			line_control;
 };
 
+static int spcp8x5_probe(struct usb_serial *serial,
+						const struct usb_device_id *id)
+{
+	usb_set_serial_data(serial, (void *)id);
+
+	return 0;
+}
+
 static int spcp8x5_port_probe(struct usb_serial_port *port)
 {
-	struct usb_serial *serial = port->serial;
+	const struct usb_device_id *id = usb_get_serial_data(port->serial);
 	struct spcp8x5_private *priv;
-	enum spcp8x5_type type = SPCP825_007_TYPE;
-	u16 product = le16_to_cpu(serial->dev->descriptor.idProduct);
-
-	if (product == 0x0201)
-		type = SPCP825_007_TYPE;
-	else if (product == 0x0231)
-		type = SPCP835_TYPE;
-	else if (product == 0x0235)
-		type = SPCP825_008_TYPE;
-	else if (product == 0x0204)
-		type = SPCP825_INTERMATIC_TYPE;
-	else if (product == 0x0471 &&
-		 serial->dev->descriptor.idVendor == cpu_to_le16(0x081e))
-		type = SPCP825_PHILIP_TYPE;
-	dev_dbg(&serial->dev->dev, "device type = %d\n", (int)type);
 
 	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 	if (!priv)
 		return -ENOMEM;
 
 	spin_lock_init(&priv->lock);
-	priv->type = type;
+	priv->quirks = id->driver_info;
 
-	usb_set_serial_port_data(port , priv);
+	usb_set_serial_port_data(port, priv);
 
 	return 0;
 }
@@ -195,86 +182,79 @@ static int spcp8x5_port_remove(struct usb_serial_port *port)
 	return 0;
 }
 
-/* set the modem control line of the device.
- * NOTE spcp825-007 not supported this */
-static int spcp8x5_set_ctrlLine(struct usb_device *dev, u8 value,
-				enum spcp8x5_type type)
+static int spcp8x5_set_ctrl_line(struct usb_serial_port *port, u8 mcr)
 {
+	struct spcp8x5_private *priv = usb_get_serial_port_data(port);
+	struct usb_device *dev = port->serial->dev;
 	int retval;
-	u8 mcr = 0 ;
 
-	if (type == SPCP825_007_TYPE)
+	if (priv->quirks & SPCP825_QUIRK_NO_UART_STATUS)
 		return -EPERM;
 
-	mcr = (unsigned short)value;
 	retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
 				 SET_UART_STATUS_TYPE, SET_UART_STATUS,
 				 mcr, 0x04, NULL, 0, 100);
-	if (retval != 0)
-		dev_dbg(&dev->dev, "usb_control_msg return %#x\n", retval);
+	if (retval != 0) {
+		dev_err(&port->dev, "failed to set control lines: %d\n",
+								retval);
+	}
 	return retval;
 }
 
-/* get the modem status register of the device
- * NOTE spcp825-007 not supported this */
-static int spcp8x5_get_msr(struct usb_device *dev, u8 *status,
-			   enum spcp8x5_type type)
+static int spcp8x5_get_msr(struct usb_serial_port *port, u8 *status)
 {
-	u8 *status_buffer;
+	struct spcp8x5_private *priv = usb_get_serial_port_data(port);
+	struct usb_device *dev = port->serial->dev;
+	u8 *buf;
 	int ret;
 
-	/* I return Permited not support here but seem inval device
-	 * is more fix */
-	if (type == SPCP825_007_TYPE)
+	if (priv->quirks & SPCP825_QUIRK_NO_UART_STATUS)
 		return -EPERM;
-	if (status == NULL)
-		return -EINVAL;
 
-	status_buffer = kmalloc(1, GFP_KERNEL);
-	if (!status_buffer)
+	buf = kzalloc(1, GFP_KERNEL);
+	if (!buf)
 		return -ENOMEM;
-	status_buffer[0] = status[0];
 
 	ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
 			      GET_UART_STATUS, GET_UART_STATUS_TYPE,
-			      0, GET_UART_STATUS_MSR, status_buffer, 1, 100);
+			      0, GET_UART_STATUS_MSR, buf, 1, 100);
 	if (ret < 0)
-		dev_dbg(&dev->dev, "Get MSR = 0x%p failed (error = %d)",
-			status_buffer, ret);
+		dev_err(&port->dev, "failed to get modem status: %d", ret);
 
-	dev_dbg(&dev->dev, "0xc0:0x22:0:6  %d - 0x%p ", ret, status_buffer);
-	status[0] = status_buffer[0];
-	kfree(status_buffer);
+	dev_dbg(&port->dev, "0xc0:0x22:0:6  %d - 0x02%x", ret, *buf);
+	*status = *buf;
+	kfree(buf);
 
 	return ret;
 }
 
-/* select the work mode.
- * NOTE this function not supported by spcp825-007 */
-static void spcp8x5_set_workMode(struct usb_device *dev, u16 value,
-				 u16 index, enum spcp8x5_type type)
+static void spcp8x5_set_work_mode(struct usb_serial_port *port, u16 value,
+								 u16 index)
 {
+	struct spcp8x5_private *priv = usb_get_serial_port_data(port);
+	struct usb_device *dev = port->serial->dev;
 	int ret;
 
-	/* I return Permited not support here but seem inval device
-	 * is more fix */
-	if (type == SPCP825_007_TYPE)
+	if (priv->quirks & SPCP825_QUIRK_NO_WORK_MODE)
 		return;
 
 	ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
 			      SET_WORKING_MODE_TYPE, SET_WORKING_MODE,
 			      value, index, NULL, 0, 100);
-	dev_dbg(&dev->dev, "value = %#x , index = %#x\n", value, index);
+	dev_dbg(&port->dev, "value = %#x , index = %#x\n", value, index);
 	if (ret < 0)
-		dev_dbg(&dev->dev,
-			"RTSCTS usb_control_msg(enable flowctrl) = %d\n", ret);
+		dev_err(&port->dev, "failed to set work mode: %d\n", ret);
 }
 
 static int spcp8x5_carrier_raised(struct usb_serial_port *port)
 {
-	struct spcp8x5_private *priv = usb_get_serial_port_data(port);
-	if (priv->line_status & MSR_STATUS_LINE_DCD)
+	u8 msr;
+	int ret;
+
+	ret = spcp8x5_get_msr(port, &msr);
+	if (ret || msr & MSR_STATUS_LINE_DCD)
 		return 1;
+
 	return 0;
 }
 
@@ -293,20 +273,17 @@ static void spcp8x5_dtr_rts(struct usb_serial_port *port, int on)
 						| MCR_CONTROL_LINE_RTS);
 	control = priv->line_control;
 	spin_unlock_irqrestore(&priv->lock, flags);
-	spcp8x5_set_ctrlLine(port->serial->dev, control , priv->type);
+	spcp8x5_set_ctrl_line(port, control);
 }
 
 static void spcp8x5_init_termios(struct tty_struct *tty)
 {
-	/* for the 1st time call this function */
 	tty->termios = tty_std_termios;
 	tty->termios.c_cflag = B115200 | CS8 | CREAD | HUPCL | CLOCAL;
 	tty->termios.c_ispeed = 115200;
 	tty->termios.c_ospeed = 115200;
 }
 
-/* set the serial param for transfer. we should check if we really need to
- * transfer. if we set flow control we should do this too. */
 static void spcp8x5_set_termios(struct tty_struct *tty,
 		struct usb_serial_port *port, struct ktermios *old_termios)
 {
@@ -321,7 +298,6 @@ static void spcp8x5_set_termios(struct tty_struct *tty,
 	int i;
 	u8 control;
 
-
 	/* check that they really want us to change something */
 	if (!tty_termios_hw_change(&tty->termios, old_termios))
 		return;
@@ -337,7 +313,7 @@ static void spcp8x5_set_termios(struct tty_struct *tty,
 	if (control != priv->line_control) {
 		control = priv->line_control;
 		spin_unlock_irqrestore(&priv->lock, flags);
-		spcp8x5_set_ctrlLine(serial->dev, control , priv->type);
+		spcp8x5_set_ctrl_line(port, control);
 	} else {
 		spin_unlock_irqrestore(&priv->lock, flags);
 	}
@@ -397,9 +373,9 @@ static void spcp8x5_set_termios(struct tty_struct *tty,
 	if (cflag & PARENB) {
 		buf[1] |= (cflag & PARODD) ?
 		SET_UART_FORMAT_PAR_ODD : SET_UART_FORMAT_PAR_EVEN ;
-	} else
+	} else {
 		buf[1] |= SET_UART_FORMAT_PAR_NONE;
-
+	}
 	uartdata = buf[0] | buf[1]<<8;
 
 	i = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
@@ -412,22 +388,16 @@ static void spcp8x5_set_termios(struct tty_struct *tty,
 
 	if (cflag & CRTSCTS) {
 		/* enable hardware flow control */
-		spcp8x5_set_workMode(serial->dev, 0x000a,
-				     SET_WORKING_MODE_U2C, priv->type);
+		spcp8x5_set_work_mode(port, 0x000a, SET_WORKING_MODE_U2C);
 	}
 }
 
-/* open the serial port. do some usb system call. set termios and get the line
- * status of the device. */
 static int spcp8x5_open(struct tty_struct *tty, struct usb_serial_port *port)
 {
 	struct ktermios tmp_termios;
 	struct usb_serial *serial = port->serial;
 	struct spcp8x5_private *priv = usb_get_serial_port_data(port);
 	int ret;
-	unsigned long flags;
-	u8 status = 0x30;
-	/* status 0x30 means DSR and CTS = 1 other CDC RI and delta = 0 */
 
 	usb_clear_halt(serial->dev, port->write_urb->pipe);
 	usb_clear_halt(serial->dev, port->read_urb->pipe);
@@ -438,142 +408,16 @@ static int spcp8x5_open(struct tty_struct *tty, struct usb_serial_port *port)
 	if (ret)
 		return ret;
 
-	spcp8x5_set_ctrlLine(serial->dev, priv->line_control , priv->type);
+	spcp8x5_set_ctrl_line(port, priv->line_control);
 
-	/* Setup termios */
 	if (tty)
 		spcp8x5_set_termios(tty, port, &tmp_termios);
 
-	spcp8x5_get_msr(serial->dev, &status, priv->type);
-
-	/* may be we should update uart status here but now we did not do */
-	spin_lock_irqsave(&priv->lock, flags);
-	priv->line_status = status & 0xf0 ;
-	spin_unlock_irqrestore(&priv->lock, flags);
-
 	port->port.drain_delay = 256;
 
 	return usb_serial_generic_open(tty, port);
 }
 
-static void spcp8x5_process_read_urb(struct urb *urb)
-{
-	struct usb_serial_port *port = urb->context;
-	struct spcp8x5_private *priv = usb_get_serial_port_data(port);
-	unsigned char *data = urb->transfer_buffer;
-	unsigned long flags;
-	u8 status;
-	char tty_flag;
-
-	/* get tty_flag from status */
-	tty_flag = TTY_NORMAL;
-
-	spin_lock_irqsave(&priv->lock, flags);
-	status = priv->line_status;
-	priv->line_status &= ~UART_STATE_TRANSIENT_MASK;
-	spin_unlock_irqrestore(&priv->lock, flags);
-	/* wake up the wait for termios */
-	wake_up_interruptible(&port->delta_msr_wait);
-
-	if (!urb->actual_length)
-		return;
-
-
-	if (status & UART_STATE_TRANSIENT_MASK) {
-		/* break takes precedence over parity, which takes precedence
-		 * over framing errors */
-		if (status & UART_BREAK_ERROR)
-			tty_flag = TTY_BREAK;
-		else if (status & UART_PARITY_ERROR)
-			tty_flag = TTY_PARITY;
-		else if (status & UART_FRAME_ERROR)
-			tty_flag = TTY_FRAME;
-		dev_dbg(&port->dev, "tty_flag = %d\n", tty_flag);
-
-		/* overrun is special, not associated with a char */
-		if (status & UART_OVERRUN_ERROR)
-			tty_insert_flip_char(&port->port, 0, TTY_OVERRUN);
-
-		if (status & UART_DCD) {
-			struct tty_struct *tty = tty_port_tty_get(&port->port);
-			if (tty) {
-				usb_serial_handle_dcd_change(port, tty,
-				       priv->line_status & MSR_STATUS_LINE_DCD);
-				tty_kref_put(tty);
-			}
-		}
-	}
-
-	tty_insert_flip_string_fixed_flag(&port->port, data, tty_flag,
-							urb->actual_length);
-	tty_flip_buffer_push(&port->port);
-}
-
-static int spcp8x5_wait_modem_info(struct usb_serial_port *port,
-				   unsigned int arg)
-{
-	struct spcp8x5_private *priv = usb_get_serial_port_data(port);
-	unsigned long flags;
-	unsigned int prevstatus;
-	unsigned int status;
-	unsigned int changed;
-
-	spin_lock_irqsave(&priv->lock, flags);
-	prevstatus = priv->line_status;
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	while (1) {
-		/* wake up in bulk read */
-		interruptible_sleep_on(&port->delta_msr_wait);
-
-		/* see if a signal did it */
-		if (signal_pending(current))
-			return -ERESTARTSYS;
-
-		if (port->serial->disconnected)
-			return -EIO;
-
-		spin_lock_irqsave(&priv->lock, flags);
-		status = priv->line_status;
-		spin_unlock_irqrestore(&priv->lock, flags);
-
-		changed = prevstatus^status;
-
-		if (((arg & TIOCM_RNG) && (changed & MSR_STATUS_LINE_RI)) ||
-		    ((arg & TIOCM_DSR) && (changed & MSR_STATUS_LINE_DSR)) ||
-		    ((arg & TIOCM_CD)  && (changed & MSR_STATUS_LINE_DCD)) ||
-		    ((arg & TIOCM_CTS) && (changed & MSR_STATUS_LINE_CTS)))
-			return 0;
-
-		prevstatus = status;
-	}
-	/* NOTREACHED */
-	return 0;
-}
-
-static int spcp8x5_ioctl(struct tty_struct *tty,
-			 unsigned int cmd, unsigned long arg)
-{
-	struct usb_serial_port *port = tty->driver_data;
-
-	dev_dbg(&port->dev, "%s (%d) cmd = 0x%04x\n", __func__,
-		port->number, cmd);
-
-	switch (cmd) {
-	case TIOCMIWAIT:
-		dev_dbg(&port->dev, "%s (%d) TIOCMIWAIT\n", __func__,
-			port->number);
-		return spcp8x5_wait_modem_info(port, arg);
-
-	default:
-		dev_dbg(&port->dev, "%s not supported = 0x%04x", __func__,
-			cmd);
-		break;
-	}
-
-	return -ENOIOCTLCMD;
-}
-
 static int spcp8x5_tiocmset(struct tty_struct *tty,
 			    unsigned int set, unsigned int clear)
 {
@@ -594,7 +438,7 @@ static int spcp8x5_tiocmset(struct tty_struct *tty,
 	control = priv->line_control;
 	spin_unlock_irqrestore(&priv->lock, flags);
 
-	return spcp8x5_set_ctrlLine(port->serial->dev, control , priv->type);
+	return spcp8x5_set_ctrl_line(port, control);
 }
 
 static int spcp8x5_tiocmget(struct tty_struct *tty)
@@ -603,12 +447,15 @@ static int spcp8x5_tiocmget(struct tty_struct *tty)
 	struct spcp8x5_private *priv = usb_get_serial_port_data(port);
 	unsigned long flags;
 	unsigned int mcr;
-	unsigned int status;
+	u8 status;
 	unsigned int result;
 
+	result = spcp8x5_get_msr(port, &status);
+	if (result)
+		return result;
+
 	spin_lock_irqsave(&priv->lock, flags);
 	mcr = priv->line_control;
-	status = priv->line_status;
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	result = ((mcr & MCR_DTR)			? TIOCM_DTR : 0)
@@ -621,7 +468,6 @@ static int spcp8x5_tiocmget(struct tty_struct *tty)
 	return result;
 }
 
-/* All of the device info needed for the spcp8x5 SIO serial converter */
 static struct usb_serial_driver spcp8x5_device = {
 	.driver = {
 		.owner =	THIS_MODULE,
@@ -629,17 +475,16 @@ static struct usb_serial_driver spcp8x5_device = {
 	},
 	.id_table		= id_table,
 	.num_ports		= 1,
-	.open 			= spcp8x5_open,
+	.open			= spcp8x5_open,
 	.dtr_rts		= spcp8x5_dtr_rts,
 	.carrier_raised		= spcp8x5_carrier_raised,
-	.set_termios 		= spcp8x5_set_termios,
+	.set_termios		= spcp8x5_set_termios,
 	.init_termios		= spcp8x5_init_termios,
-	.ioctl 			= spcp8x5_ioctl,
-	.tiocmget 		= spcp8x5_tiocmget,
-	.tiocmset 		= spcp8x5_tiocmset,
+	.tiocmget		= spcp8x5_tiocmget,
+	.tiocmset		= spcp8x5_tiocmset,
+	.probe			= spcp8x5_probe,
 	.port_probe		= spcp8x5_port_probe,
 	.port_remove		= spcp8x5_port_remove,
-	.process_read_urb	= spcp8x5_process_read_urb,
 };
 
 static struct usb_serial_driver * const serial_drivers[] = {
diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c
index 4b2a197..5b62dbb 100644
--- a/drivers/usb/serial/ssu100.c
+++ b/drivers/usb/serial/ssu100.c
@@ -61,7 +61,6 @@ struct ssu100_port_private {
 	spinlock_t status_lock;
 	u8 shadowLSR;
 	u8 shadowMSR;
-	struct async_icount icount;
 };
 
 static inline int ssu100_control_msg(struct usb_device *dev,
@@ -315,11 +314,6 @@ static int ssu100_open(struct tty_struct *tty, struct usb_serial_port *port)
 	return usb_serial_generic_open(tty, port);
 }
 
-static void ssu100_close(struct usb_serial_port *port)
-{
-	usb_serial_generic_close(port);
-}
-
 static int get_serial_info(struct usb_serial_port *port,
 			   struct serial_struct __user *retinfo)
 {
@@ -343,73 +337,6 @@ static int get_serial_info(struct usb_serial_port *port,
 	return 0;
 }
 
-static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
-{
-	struct ssu100_port_private *priv = usb_get_serial_port_data(port);
-	struct async_icount prev, cur;
-	unsigned long flags;
-
-	spin_lock_irqsave(&priv->status_lock, flags);
-	prev = priv->icount;
-	spin_unlock_irqrestore(&priv->status_lock, flags);
-
-	while (1) {
-		wait_event_interruptible(port->delta_msr_wait,
-					 (port->serial->disconnected ||
-					  (priv->icount.rng != prev.rng) ||
-					  (priv->icount.dsr != prev.dsr) ||
-					  (priv->icount.dcd != prev.dcd) ||
-					  (priv->icount.cts != prev.cts)));
-
-		if (signal_pending(current))
-			return -ERESTARTSYS;
-
-		if (port->serial->disconnected)
-			return -EIO;
-
-		spin_lock_irqsave(&priv->status_lock, flags);
-		cur = priv->icount;
-		spin_unlock_irqrestore(&priv->status_lock, flags);
-
-		if ((prev.rng == cur.rng) &&
-		    (prev.dsr == cur.dsr) &&
-		    (prev.dcd == cur.dcd) &&
-		    (prev.cts == cur.cts))
-			return -EIO;
-
-		if ((arg & TIOCM_RNG && (prev.rng != cur.rng)) ||
-		    (arg & TIOCM_DSR && (prev.dsr != cur.dsr)) ||
-		    (arg & TIOCM_CD  && (prev.dcd != cur.dcd)) ||
-		    (arg & TIOCM_CTS && (prev.cts != cur.cts)))
-			return 0;
-	}
-	return 0;
-}
-
-static int ssu100_get_icount(struct tty_struct *tty,
-			struct serial_icounter_struct *icount)
-{
-	struct usb_serial_port *port = tty->driver_data;
-	struct ssu100_port_private *priv = usb_get_serial_port_data(port);
-	struct async_icount cnow = priv->icount;
-
-	icount->cts = cnow.cts;
-	icount->dsr = cnow.dsr;
-	icount->rng = cnow.rng;
-	icount->dcd = cnow.dcd;
-	icount->rx = cnow.rx;
-	icount->tx = cnow.tx;
-	icount->frame = cnow.frame;
-	icount->overrun = cnow.overrun;
-	icount->parity = cnow.parity;
-	icount->brk = cnow.brk;
-	icount->buf_overrun = cnow.buf_overrun;
-
-	return 0;
-}
-
-
-
 static int ssu100_ioctl(struct tty_struct *tty,
 		    unsigned int cmd, unsigned long arg)
 {
@@ -421,10 +348,6 @@ static int ssu100_ioctl(struct tty_struct *tty,
 	case TIOCGSERIAL:
 		return get_serial_info(port,
 				       (struct serial_struct __user *) arg);
-
-	case TIOCMIWAIT:
-		return wait_modem_info(port, arg);
-
 	default:
 		break;
 	}
@@ -532,14 +455,14 @@ static void ssu100_update_msr(struct usb_serial_port *port, u8 msr)
 	if (msr & UART_MSR_ANY_DELTA) {
 		/* update input line counters */
 		if (msr & UART_MSR_DCTS)
-			priv->icount.cts++;
+			port->icount.cts++;
 		if (msr & UART_MSR_DDSR)
-			priv->icount.dsr++;
+			port->icount.dsr++;
 		if (msr & UART_MSR_DDCD)
-			priv->icount.dcd++;
+			port->icount.dcd++;
 		if (msr & UART_MSR_TERI)
-			priv->icount.rng++;
-		wake_up_interruptible(&port->delta_msr_wait);
+			port->icount.rng++;
+		wake_up_interruptible(&port->port.delta_msr_wait);
 	}
 }
 
@@ -558,22 +481,22 @@ static void ssu100_update_lsr(struct usb_serial_port *port, u8 lsr,
 		/* we always want to update icount, but we only want to
 		 * update tty_flag for one case */
 		if (lsr & UART_LSR_BI) {
-			priv->icount.brk++;
+			port->icount.brk++;
 			*tty_flag = TTY_BREAK;
 			usb_serial_handle_break(port);
 		}
 		if (lsr & UART_LSR_PE) {
-			priv->icount.parity++;
+			port->icount.parity++;
 			if (*tty_flag == TTY_NORMAL)
 				*tty_flag = TTY_PARITY;
 		}
 		if (lsr & UART_LSR_FE) {
-			priv->icount.frame++;
+			port->icount.frame++;
 			if (*tty_flag == TTY_NORMAL)
 				*tty_flag = TTY_FRAME;
 		}
 		if (lsr & UART_LSR_OE){
-			priv->icount.overrun++;
+			port->icount.overrun++;
 			if (*tty_flag == TTY_NORMAL)
 				*tty_flag = TTY_OVERRUN;
 		}
@@ -630,7 +553,6 @@ static struct usb_serial_driver ssu100_device = {
 	.id_table	     = id_table,
 	.num_ports	     = 1,
 	.open		     = ssu100_open,
-	.close		     = ssu100_close,
 	.attach              = ssu100_attach,
 	.port_probe          = ssu100_port_probe,
 	.port_remove         = ssu100_port_remove,
@@ -638,10 +560,10 @@ static struct usb_serial_driver ssu100_device = {
 	.process_read_urb    = ssu100_process_read_urb,
 	.tiocmget            = ssu100_tiocmget,
 	.tiocmset            = ssu100_tiocmset,
-	.get_icount	     = ssu100_get_icount,
+	.tiocmiwait          = usb_serial_generic_tiocmiwait,
+	.get_icount	     = usb_serial_generic_get_icount,
 	.ioctl               = ssu100_ioctl,
 	.set_termios         = ssu100_set_termios,
-	.disconnect          = usb_serial_generic_disconnect,
 };
 
 static struct usb_serial_driver * const serial_drivers[] = {
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
index 73deb02..2a74973 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.c
+++ b/drivers/usb/serial/ti_usb_3410_5052.c
@@ -73,7 +73,6 @@ struct ti_port {
 	unsigned int		tp_uart_base_addr;
 	int			tp_flags;
 	int			tp_closing_wait;/* in .01 secs */
-	struct async_icount	tp_icount;
 	wait_queue_head_t	tp_write_wait;
 	struct ti_device	*tp_tdev;
 	struct usb_serial_port	*tp_port;
@@ -108,8 +107,6 @@ static void ti_throttle(struct tty_struct *tty);
 static void ti_unthrottle(struct tty_struct *tty);
 static int ti_ioctl(struct tty_struct *tty,
 		unsigned int cmd, unsigned long arg);
-static int ti_get_icount(struct tty_struct *tty,
-		struct serial_icounter_struct *icount);
 static void ti_set_termios(struct tty_struct *tty,
 		struct usb_serial_port *port, struct ktermios *old_termios);
 static int ti_tiocmget(struct tty_struct *tty);
@@ -235,7 +232,8 @@ static struct usb_serial_driver ti_1port_device = {
 	.set_termios		= ti_set_termios,
 	.tiocmget		= ti_tiocmget,
 	.tiocmset		= ti_tiocmset,
-	.get_icount		= ti_get_icount,
+	.tiocmiwait		= usb_serial_generic_tiocmiwait,
+	.get_icount		= usb_serial_generic_get_icount,
 	.break_ctl		= ti_break,
 	.read_int_callback	= ti_interrupt_callback,
 	.read_bulk_callback	= ti_bulk_in_callback,
@@ -265,7 +263,8 @@ static struct usb_serial_driver ti_2port_device = {
 	.set_termios		= ti_set_termios,
 	.tiocmget		= ti_tiocmget,
 	.tiocmset		= ti_tiocmset,
-	.get_icount		= ti_get_icount,
+	.tiocmiwait		= usb_serial_generic_tiocmiwait,
+	.get_icount		= usb_serial_generic_get_icount,
 	.break_ctl		= ti_break,
 	.read_int_callback	= ti_interrupt_callback,
 	.read_bulk_callback	= ti_bulk_in_callback,
@@ -480,8 +479,6 @@ static int ti_open(struct tty_struct *tty, struct usb_serial_port *port)
 
 	port_number = port->number - port->serial->minor;
 
-	memset(&(tport->tp_icount), 0x00, sizeof(tport->tp_icount));
-
 	tport->tp_msr = 0;
 	tport->tp_shadow_mcr |= (TI_MCR_RTS | TI_MCR_DTR);
 
@@ -731,38 +728,11 @@ static void ti_unthrottle(struct tty_struct *tty)
 	}
 }
 
-static int ti_get_icount(struct tty_struct *tty,
-		struct serial_icounter_struct *icount)
-{
-	struct usb_serial_port *port = tty->driver_data;
-	struct ti_port *tport = usb_get_serial_port_data(port);
-	struct async_icount cnow = tport->tp_icount;
-
-	dev_dbg(&port->dev, "%s - TIOCGICOUNT RX=%d, TX=%d\n", __func__,
-		cnow.rx, cnow.tx);
-
-	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;
-}
-
 static int ti_ioctl(struct tty_struct *tty,
 	unsigned int cmd, unsigned long arg)
 {
 	struct usb_serial_port *port = tty->driver_data;
 	struct ti_port *tport = usb_get_serial_port_data(port);
-	struct async_icount cnow;
-	struct async_icount cprev;
 
 	dev_dbg(&port->dev, "%s - cmd = 0x%04X\n", __func__, cmd);
 
@@ -778,29 +748,6 @@ static int ti_ioctl(struct tty_struct *tty,
 		dev_dbg(&port->dev, "%s - TIOCSSERIAL\n", __func__);
 		return ti_set_serial_info(tty, tport,
 				(struct serial_struct __user *)arg);
-	case TIOCMIWAIT:
-		dev_dbg(&port->dev, "%s - TIOCMIWAIT\n", __func__);
-		cprev = tport->tp_icount;
-		while (1) {
-			interruptible_sleep_on(&port->delta_msr_wait);
-			if (signal_pending(current))
-				return -ERESTARTSYS;
-
-			if (port->serial->disconnected)
-				return -EIO;
-
-			cnow = tport->tp_icount;
-			if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
-			    cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
-				return -EIO; /* no change => error */
-			if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
-			    ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
-			    ((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) ||
-			    ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)))
-				return 0;
-			cprev = cnow;
-		}
-		break;
 	}
 	return -ENOIOCTLCMD;
 }
@@ -1156,7 +1103,7 @@ static void ti_bulk_in_callback(struct urb *urb)
 		else
 			ti_recv(port, urb->transfer_buffer, urb->actual_length);
 		spin_lock(&tport->tp_lock);
-		tport->tp_icount.rx += urb->actual_length;
+		port->icount.rx += urb->actual_length;
 		spin_unlock(&tport->tp_lock);
 	}
 
@@ -1229,7 +1176,6 @@ static void ti_send(struct ti_port *tport)
 {
 	int count, result;
 	struct usb_serial_port *port = tport->tp_port;
-	struct tty_struct *tty = tty_port_tty_get(&port->port);	/* FIXME */
 	unsigned long flags;
 
 	spin_lock_irqsave(&tport->tp_lock, flags);
@@ -1265,19 +1211,17 @@ static void ti_send(struct ti_port *tport)
 		/* TODO: reschedule ti_send */
 	} else {
 		spin_lock_irqsave(&tport->tp_lock, flags);
-		tport->tp_icount.tx += count;
+		port->icount.tx += count;
 		spin_unlock_irqrestore(&tport->tp_lock, flags);
 	}
 
 	/* more room in the buffer for new writes, wakeup */
-	if (tty)
-		tty_wakeup(tty);
-	tty_kref_put(tty);
+	tty_port_tty_wakeup(&port->port);
+
 	wake_up_interruptible(&tport->tp_write_wait);
 	return;
 unlock:
 	spin_unlock_irqrestore(&tport->tp_lock, flags);
-	tty_kref_put(tty);
 	return;
 }
 
@@ -1385,7 +1329,7 @@ static void ti_handle_new_msr(struct ti_port *tport, __u8 msr)
 
 	if (msr & TI_MSR_DELTA_MASK) {
 		spin_lock_irqsave(&tport->tp_lock, flags);
-		icount = &tport->tp_icount;
+		icount = &tport->tp_port->icount;
 		if (msr & TI_MSR_DELTA_CTS)
 			icount->cts++;
 		if (msr & TI_MSR_DELTA_DSR)
@@ -1394,7 +1338,7 @@ static void ti_handle_new_msr(struct ti_port *tport, __u8 msr)
 			icount->dcd++;
 		if (msr & TI_MSR_DELTA_RI)
 			icount->rng++;
-		wake_up_interruptible(&tport->tp_port->delta_msr_wait);
+		wake_up_interruptible(&tport->tp_port->port.delta_msr_wait);
 		spin_unlock_irqrestore(&tport->tp_lock, flags);
 	}
 
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 5d9b178..cf75beb 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -1,6 +1,7 @@
 /*
  * USB Serial Converter driver
  *
+ * Copyright (C) 2009 - 2013 Johan Hovold (jhovold@gmail.com)
  * Copyright (C) 1999 - 2012 Greg Kroah-Hartman (greg@kroah.com)
  * Copyright (C) 2000 Peter Berger (pberger@brimson.com)
  * Copyright (C) 2000 Al Borchers (borchers@steinerpoint.com)
@@ -14,7 +15,6 @@
  *
  * See Documentation/usb/usb-serial.txt for more information on using this
  * driver
- *
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -49,7 +49,6 @@
    drivers depend on it.
 */
 
-/* initially all NULL */
 static struct usb_serial *serial_table[SERIAL_TTY_MINORS];
 static DEFINE_MUTEX(table_lock);
 static LIST_HEAD(usb_serial_driver_list);
@@ -139,7 +138,7 @@ static void destroy_serial(struct kref *kref)
 	if (serial->minor != SERIAL_TTY_NO_MINOR)
 		return_serial(serial);
 
-	if (serial->attached)
+	if (serial->attached && serial->type->release)
 		serial->type->release(serial);
 
 	/* Now that nothing is using the ports, they can be freed */
@@ -225,7 +224,7 @@ static int serial_install(struct tty_driver *driver, struct tty_struct *tty)
 	return retval;
 }
 
-static int serial_activate(struct tty_port *tport, struct tty_struct *tty)
+static int serial_port_activate(struct tty_port *tport, struct tty_struct *tty)
 {
 	struct usb_serial_port *port =
 		container_of(tport, struct usb_serial_port, port);
@@ -249,30 +248,27 @@ static int serial_open(struct tty_struct *tty, struct file *filp)
 {
 	struct usb_serial_port *port = tty->driver_data;
 
-	dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number);
+	dev_dbg(tty->dev, "%s\n", __func__);
+
 	return tty_port_open(&port->port, tty, filp);
 }
 
 /**
- * serial_down - shut down hardware
+ * serial_port_shutdown - shut down hardware
  * @tport: tty port to shut down
  *
- * Shut down a USB serial port unless it is the console.  We never
- * shut down the console hardware as it will always be in use. Serialized
- * against activate by the tport mutex and kept to matching open/close pairs
+ * Shut down a USB serial port. Serialized against activate by the
+ * tport mutex and kept to matching open/close pairs
  * of calls by the ASYNCB_INITIALIZED flag.
+ *
+ * Not called if tty is console.
  */
-static void serial_down(struct tty_port *tport)
+static void serial_port_shutdown(struct tty_port *tport)
 {
 	struct usb_serial_port *port =
 		container_of(tport, struct usb_serial_port, port);
 	struct usb_serial_driver *drv = port->serial->type;
-	/*
-	 * The console is magical.  Do not hang up the console hardware
-	 * or there will be tears.
-	 */
-	if (port->port.console)
-		return;
+
 	if (drv->close)
 		drv->close(port);
 }
@@ -281,7 +277,8 @@ static void serial_hangup(struct tty_struct *tty)
 {
 	struct usb_serial_port *port = tty->driver_data;
 
-	dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number);
+	dev_dbg(tty->dev, "%s\n", __func__);
+
 	tty_port_hangup(&port->port);
 }
 
@@ -289,7 +286,8 @@ static void serial_close(struct tty_struct *tty, struct file *filp)
 {
 	struct usb_serial_port *port = tty->driver_data;
 
-	dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number);
+	dev_dbg(tty->dev, "%s\n", __func__);
+
 	tty_port_close(&port->port, tty, filp);
 }
 
@@ -308,14 +306,14 @@ static void serial_cleanup(struct tty_struct *tty)
 	struct usb_serial *serial;
 	struct module *owner;
 
+	dev_dbg(tty->dev, "%s\n", __func__);
+
 	/* The console is magical.  Do not hang up the console hardware
 	 * or there will be tears.
 	 */
 	if (port->port.console)
 		return;
 
-	dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number);
-
 	tty->driver_data = NULL;
 
 	serial = port->serial;
@@ -339,10 +337,8 @@ static int serial_write(struct tty_struct *tty, const unsigned char *buf,
 	if (port->serial->dev->state == USB_STATE_NOTATTACHED)
 		goto exit;
 
-	dev_dbg(tty->dev, "%s - port %d, %d byte(s)\n", __func__,
-		port->number, count);
+	dev_dbg(tty->dev, "%s - %d byte(s)\n", __func__, count);
 
-	/* pass on to the driver specific version of this function */
 	retval = port->serial->type->write(tty, port, buf, count);
 	if (retval < 0)
 		retval = usb_translate_errors(retval);
@@ -354,8 +350,8 @@ static int serial_write_room(struct tty_struct *tty)
 {
 	struct usb_serial_port *port = tty->driver_data;
 
-	dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number);
-	/* pass on to the driver specific version of this function */
+	dev_dbg(tty->dev, "%s\n", __func__);
+
 	return port->serial->type->write_room(tty);
 }
 
@@ -365,7 +361,7 @@ static int serial_chars_in_buffer(struct tty_struct *tty)
 	struct usb_serial *serial = port->serial;
 	int count = 0;
 
-	dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number);
+	dev_dbg(tty->dev, "%s\n", __func__);
 
 	mutex_lock(&serial->disc_mutex);
 	/* if the device was unplugged then any remaining characters
@@ -383,9 +379,8 @@ static void serial_throttle(struct tty_struct *tty)
 {
 	struct usb_serial_port *port = tty->driver_data;
 
-	dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number);
+	dev_dbg(tty->dev, "%s\n", __func__);
 
-	/* pass on to the driver specific version of this function */
 	if (port->serial->type->throttle)
 		port->serial->type->throttle(tty);
 }
@@ -394,9 +389,8 @@ static void serial_unthrottle(struct tty_struct *tty)
 {
 	struct usb_serial_port *port = tty->driver_data;
 
-	dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number);
+	dev_dbg(tty->dev, "%s\n", __func__);
 
-	/* pass on to the driver specific version of this function */
 	if (port->serial->type->unthrottle)
 		port->serial->type->unthrottle(tty);
 }
@@ -407,15 +401,20 @@ static int serial_ioctl(struct tty_struct *tty,
 	struct usb_serial_port *port = tty->driver_data;
 	int retval = -ENODEV;
 
-	dev_dbg(tty->dev, "%s - port %d, cmd 0x%.4x\n", __func__,
-		port->number, cmd);
+	dev_dbg(tty->dev, "%s - cmd 0x%.4x\n", __func__, cmd);
+
+	switch (cmd) {
+	case TIOCMIWAIT:
+		if (port->serial->type->tiocmiwait)
+			retval = port->serial->type->tiocmiwait(tty, arg);
+		break;
+	default:
+		if (port->serial->type->ioctl)
+			retval = port->serial->type->ioctl(tty, cmd, arg);
+		else
+			retval = -ENOIOCTLCMD;
+	}
 
-	/* pass on to the driver specific version of this function
-	   if it is available */
-	if (port->serial->type->ioctl) {
-		retval = port->serial->type->ioctl(tty, cmd, arg);
-	} else
-		retval = -ENOIOCTLCMD;
 	return retval;
 }
 
@@ -423,10 +422,8 @@ static void serial_set_termios(struct tty_struct *tty, struct ktermios *old)
 {
 	struct usb_serial_port *port = tty->driver_data;
 
-	dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number);
+	dev_dbg(tty->dev, "%s\n", __func__);
 
-	/* pass on to the driver specific version of this function
-	   if it is available */
 	if (port->serial->type->set_termios)
 		port->serial->type->set_termios(tty, port, old);
 	else
@@ -437,12 +434,11 @@ static int serial_break(struct tty_struct *tty, int break_state)
 {
 	struct usb_serial_port *port = tty->driver_data;
 
-	dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number);
+	dev_dbg(tty->dev, "%s\n", __func__);
 
-	/* pass on to the driver specific version of this function
-	   if it is available */
 	if (port->serial->type->break_ctl)
 		port->serial->type->break_ctl(tty, break_state);
+
 	return 0;
 }
 
@@ -496,7 +492,7 @@ static int serial_tiocmget(struct tty_struct *tty)
 {
 	struct usb_serial_port *port = tty->driver_data;
 
-	dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number);
+	dev_dbg(tty->dev, "%s\n", __func__);
 
 	if (port->serial->type->tiocmget)
 		return port->serial->type->tiocmget(tty);
@@ -508,7 +504,7 @@ static int serial_tiocmset(struct tty_struct *tty,
 {
 	struct usb_serial_port *port = tty->driver_data;
 
-	dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number);
+	dev_dbg(tty->dev, "%s\n", __func__);
 
 	if (port->serial->type->tiocmset)
 		return port->serial->type->tiocmset(tty, set, clear);
@@ -520,7 +516,7 @@ static int serial_get_icount(struct tty_struct *tty,
 {
 	struct usb_serial_port *port = tty->driver_data;
 
-	dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number);
+	dev_dbg(tty->dev, "%s\n", __func__);
 
 	if (port->serial->type->get_icount)
 		return port->serial->type->get_icount(tty, icount);
@@ -542,55 +538,43 @@ static void usb_serial_port_work(struct work_struct *work)
 {
 	struct usb_serial_port *port =
 		container_of(work, struct usb_serial_port, work);
-	struct tty_struct *tty;
 
-	tty = tty_port_tty_get(&port->port);
-	if (!tty)
-		return;
+	tty_port_tty_wakeup(&port->port);
+}
+
+static void usb_serial_port_poison_urbs(struct usb_serial_port *port)
+{
+	int i;
 
-	dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number);
+	for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i)
+		usb_poison_urb(port->read_urbs[i]);
+	for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i)
+		usb_poison_urb(port->write_urbs[i]);
 
-	tty_wakeup(tty);
-	tty_kref_put(tty);
+	usb_poison_urb(port->interrupt_in_urb);
+	usb_poison_urb(port->interrupt_out_urb);
 }
 
-static void kill_traffic(struct usb_serial_port *port)
+static void usb_serial_port_unpoison_urbs(struct usb_serial_port *port)
 {
 	int i;
 
 	for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i)
-		usb_kill_urb(port->read_urbs[i]);
+		usb_unpoison_urb(port->read_urbs[i]);
 	for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i)
-		usb_kill_urb(port->write_urbs[i]);
-	/*
-	 * This is tricky.
-	 * Some drivers submit the read_urb in the
-	 * handler for the write_urb or vice versa
-	 * this order determines the order in which
-	 * usb_kill_urb() must be used to reliably
-	 * kill the URBs. As it is unknown here,
-	 * both orders must be used in turn.
-	 * The call below is not redundant.
-	 */
-	usb_kill_urb(port->read_urb);
-	usb_kill_urb(port->interrupt_in_urb);
-	usb_kill_urb(port->interrupt_out_urb);
+		usb_unpoison_urb(port->write_urbs[i]);
+
+	usb_unpoison_urb(port->interrupt_in_urb);
+	usb_unpoison_urb(port->interrupt_out_urb);
 }
 
-static void port_release(struct device *dev)
+static void usb_serial_port_release(struct device *dev)
 {
 	struct usb_serial_port *port = to_usb_serial_port(dev);
 	int i;
 
 	dev_dbg(dev, "%s\n", __func__);
 
-	/*
-	 * Stop all the traffic before cancelling the work, so that
-	 * nobody will restart it by calling usb_serial_port_softint.
-	 */
-	kill_traffic(port);
-	cancel_work_sync(&port->work);
-
 	usb_free_urb(port->interrupt_in_urb);
 	usb_free_urb(port->interrupt_out_urb);
 	for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i) {
@@ -615,10 +599,8 @@ static struct usb_serial *create_serial(struct usb_device *dev,
 	struct usb_serial *serial;
 
 	serial = kzalloc(sizeof(*serial), GFP_KERNEL);
-	if (!serial) {
-		dev_err(&dev->dev, "%s - out of memory\n", __func__);
+	if (!serial)
 		return NULL;
-	}
 	serial->dev = usb_get_dev(dev);
 	serial->type = driver;
 	serial->interface = usb_get_intf(interface);
@@ -681,7 +663,7 @@ static struct usb_serial_driver *search_serial_device(
 	return NULL;
 }
 
-static int serial_carrier_raised(struct tty_port *port)
+static int serial_port_carrier_raised(struct tty_port *port)
 {
 	struct usb_serial_port *p = container_of(port, struct usb_serial_port, port);
 	struct usb_serial_driver *drv = p->serial->type;
@@ -692,7 +674,7 @@ static int serial_carrier_raised(struct tty_port *port)
 	return 1;
 }
 
-static void serial_dtr_rts(struct tty_port *port, int on)
+static void serial_port_dtr_rts(struct tty_port *port, int on)
 {
 	struct usb_serial_port *p = container_of(port, struct usb_serial_port, port);
 	struct usb_serial *serial = p->serial;
@@ -712,10 +694,10 @@ static void serial_dtr_rts(struct tty_port *port, int on)
 }
 
 static const struct tty_port_operations serial_port_ops = {
-	.carrier_raised = serial_carrier_raised,
-	.dtr_rts = serial_dtr_rts,
-	.activate = serial_activate,
-	.shutdown = serial_down,
+	.carrier_raised		= serial_port_carrier_raised,
+	.dtr_rts		= serial_port_dtr_rts,
+	.activate		= serial_port_activate,
+	.shutdown		= serial_port_shutdown,
 };
 
 static int usb_serial_probe(struct usb_interface *interface,
@@ -762,7 +744,6 @@ static int usb_serial_probe(struct usb_interface *interface,
 	serial = create_serial(dev, interface, type);
 	if (!serial) {
 		module_put(type->driver.owner);
-		dev_err(ddev, "%s - out of memory\n", __func__);
 		return -ENOMEM;
 	}
 
@@ -903,7 +884,6 @@ static int usb_serial_probe(struct usb_interface *interface,
 		port->port.ops = &serial_port_ops;
 		port->serial = serial;
 		spin_lock_init(&port->lock);
-		init_waitqueue_head(&port->delta_msr_wait);
 		/* Keep this for private driver use for the moment but
 		   should probably go away */
 		INIT_WORK(&port->work, usb_serial_port_work);
@@ -911,7 +891,7 @@ static int usb_serial_probe(struct usb_interface *interface,
 		port->dev.parent = &interface->dev;
 		port->dev.driver = NULL;
 		port->dev.bus = &usb_serial_bus_type;
-		port->dev.release = &port_release;
+		port->dev.release = &usb_serial_port_release;
 		device_initialize(&port->dev);
 	}
 
@@ -927,16 +907,12 @@ static int usb_serial_probe(struct usb_interface *interface,
 		for (j = 0; j < ARRAY_SIZE(port->read_urbs); ++j) {
 			set_bit(j, &port->read_urbs_free);
 			port->read_urbs[j] = usb_alloc_urb(0, GFP_KERNEL);
-			if (!port->read_urbs[j]) {
-				dev_err(ddev, "No free urbs available\n");
+			if (!port->read_urbs[j])
 				goto probe_error;
-			}
 			port->bulk_in_buffers[j] = kmalloc(buffer_size,
 								GFP_KERNEL);
-			if (!port->bulk_in_buffers[j]) {
-				dev_err(ddev, "Couldn't allocate bulk_in_buffer\n");
+			if (!port->bulk_in_buffers[j])
 				goto probe_error;
-			}
 			usb_fill_bulk_urb(port->read_urbs[j], dev,
 					usb_rcvbulkpipe(dev,
 						endpoint->bEndpointAddress),
@@ -963,16 +939,12 @@ static int usb_serial_probe(struct usb_interface *interface,
 		for (j = 0; j < ARRAY_SIZE(port->write_urbs); ++j) {
 			set_bit(j, &port->write_urbs_free);
 			port->write_urbs[j] = usb_alloc_urb(0, GFP_KERNEL);
-			if (!port->write_urbs[j]) {
-				dev_err(ddev, "No free urbs available\n");
+			if (!port->write_urbs[j])
 				goto probe_error;
-			}
 			port->bulk_out_buffers[j] = kmalloc(buffer_size,
 								GFP_KERNEL);
-			if (!port->bulk_out_buffers[j]) {
-				dev_err(ddev, "Couldn't allocate bulk_out_buffer\n");
+			if (!port->bulk_out_buffers[j])
 				goto probe_error;
-			}
 			usb_fill_bulk_urb(port->write_urbs[j], dev,
 					usb_sndbulkpipe(dev,
 						endpoint->bEndpointAddress),
@@ -990,19 +962,15 @@ static int usb_serial_probe(struct usb_interface *interface,
 			endpoint = interrupt_in_endpoint[i];
 			port = serial->port[i];
 			port->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
-			if (!port->interrupt_in_urb) {
-				dev_err(ddev, "No free urbs available\n");
+			if (!port->interrupt_in_urb)
 				goto probe_error;
-			}
 			buffer_size = usb_endpoint_maxp(endpoint);
 			port->interrupt_in_endpointAddress =
 						endpoint->bEndpointAddress;
 			port->interrupt_in_buffer = kmalloc(buffer_size,
 								GFP_KERNEL);
-			if (!port->interrupt_in_buffer) {
-				dev_err(ddev, "Couldn't allocate interrupt_in_buffer\n");
+			if (!port->interrupt_in_buffer)
 				goto probe_error;
-			}
 			usb_fill_int_urb(port->interrupt_in_urb, dev,
 				usb_rcvintpipe(dev,
 						endpoint->bEndpointAddress),
@@ -1019,20 +987,16 @@ static int usb_serial_probe(struct usb_interface *interface,
 			endpoint = interrupt_out_endpoint[i];
 			port = serial->port[i];
 			port->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
-			if (!port->interrupt_out_urb) {
-				dev_err(ddev, "No free urbs available\n");
+			if (!port->interrupt_out_urb)
 				goto probe_error;
-			}
 			buffer_size = usb_endpoint_maxp(endpoint);
 			port->interrupt_out_size = buffer_size;
 			port->interrupt_out_endpointAddress =
 						endpoint->bEndpointAddress;
 			port->interrupt_out_buffer = kmalloc(buffer_size,
 								GFP_KERNEL);
-			if (!port->interrupt_out_buffer) {
-				dev_err(ddev, "Couldn't allocate interrupt_out_buffer\n");
+			if (!port->interrupt_out_buffer)
 				goto probe_error;
-			}
 			usb_fill_int_urb(port->interrupt_out_urb, dev,
 				usb_sndintpipe(dev,
 						  endpoint->bEndpointAddress),
@@ -1121,13 +1085,15 @@ static void usb_serial_disconnect(struct usb_interface *interface)
 				tty_vhangup(tty);
 				tty_kref_put(tty);
 			}
-			kill_traffic(port);
+			usb_serial_port_poison_urbs(port);
+			wake_up_interruptible(&port->port.delta_msr_wait);
 			cancel_work_sync(&port->work);
 			if (device_is_registered(&port->dev))
 				device_del(&port->dev);
 		}
 	}
-	serial->type->disconnect(serial);
+	if (serial->type->disconnect)
+		serial->type->disconnect(serial);
 
 	/* let the last holder of this object cause it to be cleaned up */
 	usb_serial_put(serial);
@@ -1142,6 +1108,11 @@ int usb_serial_suspend(struct usb_interface *intf, pm_message_t message)
 
 	serial->suspending = 1;
 
+	/*
+	 * serial->type->suspend() MUST return 0 in system sleep context,
+	 * otherwise, the resume callback has to recover device from
+	 * previous suspend failure.
+	 */
 	if (serial->type->suspend) {
 		r = serial->type->suspend(serial, message);
 		if (r < 0) {
@@ -1153,7 +1124,7 @@ int usb_serial_suspend(struct usb_interface *intf, pm_message_t message)
 	for (i = 0; i < serial->num_ports; ++i) {
 		port = serial->port[i];
 		if (port)
-			kill_traffic(port);
+			usb_serial_port_poison_urbs(port);
 	}
 
 err_out:
@@ -1161,11 +1132,25 @@ err_out:
 }
 EXPORT_SYMBOL(usb_serial_suspend);
 
+static void usb_serial_unpoison_port_urbs(struct usb_serial *serial)
+{
+	struct usb_serial_port *port;
+	int i;
+
+	for (i = 0; i < serial->num_ports; ++i) {
+		port = serial->port[i];
+		if (port)
+			usb_serial_port_unpoison_urbs(port);
+	}
+}
+
 int usb_serial_resume(struct usb_interface *intf)
 {
 	struct usb_serial *serial = usb_get_intfdata(intf);
 	int rv;
 
+	usb_serial_unpoison_port_urbs(serial);
+
 	serial->suspending = 0;
 	if (serial->type->resume)
 		rv = serial->type->resume(serial);
@@ -1181,6 +1166,8 @@ static int usb_serial_reset_resume(struct usb_interface *intf)
 	struct usb_serial *serial = usb_get_intfdata(intf);
 	int rv;
 
+	usb_serial_unpoison_port_urbs(serial);
+
 	serial->suspending = 0;
 	if (serial->type->reset_resume)
 		rv = serial->type->reset_resume(serial);
@@ -1317,12 +1304,12 @@ module_exit(usb_serial_exit);
 	do {								\
 		if (!type->function) {					\
 			type->function = usb_serial_generic_##function;	\
-			pr_debug("Had to override the " #function	\
-				" usb serial operation with the generic one.");\
-			}						\
+			pr_debug("%s: using generic " #function	"\n",	\
+						type->driver.name);	\
+		}							\
 	} while (0)
 
-static void fixup_generic(struct usb_serial_driver *device)
+static void usb_serial_operations_init(struct usb_serial_driver *device)
 {
 	set_to_generic_if_null(device, open);
 	set_to_generic_if_null(device, write);
@@ -1331,8 +1318,6 @@ static void fixup_generic(struct usb_serial_driver *device)
 	set_to_generic_if_null(device, chars_in_buffer);
 	set_to_generic_if_null(device, read_bulk_callback);
 	set_to_generic_if_null(device, write_bulk_callback);
-	set_to_generic_if_null(device, disconnect);
-	set_to_generic_if_null(device, release);
 	set_to_generic_if_null(device, process_read_urb);
 	set_to_generic_if_null(device, prepare_write_buffer);
 }
@@ -1344,8 +1329,6 @@ static int usb_serial_register(struct usb_serial_driver *driver)
 	if (usb_disabled())
 		return -ENODEV;
 
-	fixup_generic(driver);
-
 	if (!driver->description)
 		driver->description = driver->driver.name;
 	if (!driver->usb_driver) {
@@ -1354,6 +1337,8 @@ static int usb_serial_register(struct usb_serial_driver *driver)
 		return -EINVAL;
 	}
 
+	usb_serial_operations_init(driver);
+
 	/* Add this device to our list of devices */
 	mutex_lock(&table_lock);
 	list_add(&driver->driver_list, &usb_serial_driver_list);
@@ -1471,7 +1456,6 @@ void usb_serial_deregister_drivers(struct usb_serial_driver *const serial_driver
 }
 EXPORT_SYMBOL_GPL(usb_serial_deregister_drivers);
 
-/* Module information */
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c
index 571965a..ece326e 100644
--- a/drivers/usb/serial/usb_wwan.c
+++ b/drivers/usb/serial/usb_wwan.c
@@ -421,20 +421,19 @@ void usb_wwan_close(struct usb_serial_port *port)
 
 	portdata = usb_get_serial_port_data(port);
 
-	if (serial->dev) {
-		/* Stop reading/writing urbs */
-		spin_lock_irq(&intfdata->susp_lock);
-		portdata->opened = 0;
-		spin_unlock_irq(&intfdata->susp_lock);
+	/* Stop reading/writing urbs */
+	spin_lock_irq(&intfdata->susp_lock);
+	portdata->opened = 0;
+	spin_unlock_irq(&intfdata->susp_lock);
 
-		for (i = 0; i < N_IN_URB; i++)
-			usb_kill_urb(portdata->in_urbs[i]);
-		for (i = 0; i < N_OUT_URB; i++)
-			usb_kill_urb(portdata->out_urbs[i]);
-		/* balancing - important as an error cannot be handled*/
-		usb_autopm_get_interface_no_resume(serial->interface);
-		serial->interface->needs_remote_wakeup = 0;
-	}
+	for (i = 0; i < N_IN_URB; i++)
+		usb_kill_urb(portdata->in_urbs[i]);
+	for (i = 0; i < N_OUT_URB; i++)
+		usb_kill_urb(portdata->out_urbs[i]);
+
+	/* balancing - important as an error cannot be handled*/
+	usb_autopm_get_interface_no_resume(serial->interface);
+	serial->interface->needs_remote_wakeup = 0;
 }
 EXPORT_SYMBOL(usb_wwan_close);
 
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
index 1129aa7..7573ec8 100644
--- a/drivers/usb/serial/visor.c
+++ b/drivers/usb/serial/visor.c
@@ -257,24 +257,18 @@ static void visor_close(struct usb_serial_port *port)
 {
 	unsigned char *transfer_buffer;
 
-	/* shutdown our urbs */
 	usb_serial_generic_close(port);
 	usb_kill_urb(port->interrupt_in_urb);
 
-	mutex_lock(&port->serial->disc_mutex);
-	if (!port->serial->disconnected) {
-		/* Try to send shutdown message, unless the device is gone */
-		transfer_buffer =  kmalloc(0x12, GFP_KERNEL);
-		if (transfer_buffer) {
-			usb_control_msg(port->serial->dev,
+	transfer_buffer = kmalloc(0x12, GFP_KERNEL);
+	if (!transfer_buffer)
+		return;
+	usb_control_msg(port->serial->dev,
 					 usb_rcvctrlpipe(port->serial->dev, 0),
 					 VISOR_CLOSE_NOTIFICATION, 0xc2,
 					 0x0000, 0x0000,
 					 transfer_buffer, 0x12, 300);
-			kfree(transfer_buffer);
-		}
-	}
-	mutex_unlock(&port->serial->disc_mutex);
+	kfree(transfer_buffer);
 }
 
 static void visor_read_int_callback(struct urb *urb)
diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c
index ecea478..06a3d22 100644
--- a/drivers/usb/storage/isd200.c
+++ b/drivers/usb/storage/isd200.c
@@ -1457,8 +1457,7 @@ static int isd200_init_info(struct us_data *us)
 		retStatus = ISD200_ERROR;
 	else {
 		info->id = kzalloc(ATA_ID_WORDS * 2, GFP_KERNEL);
-		info->RegsBuf = (unsigned char *)
-				kmalloc(sizeof(info->ATARegs), GFP_KERNEL);
+		info->RegsBuf = kmalloc(sizeof(info->ATARegs), GFP_KERNEL);
 		info->srb.sense_buffer =
 				kmalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL);
 		if (!info->id || !info->RegsBuf || !info->srb.sense_buffer) {
diff --git a/drivers/usb/storage/onetouch.c b/drivers/usb/storage/onetouch.c
index cb79de6..2696489 100644
--- a/drivers/usb/storage/onetouch.c
+++ b/drivers/usb/storage/onetouch.c
@@ -195,6 +195,7 @@ static int onetouch_connect_input(struct us_data *ss)
 
 	pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress);
 	maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
+	maxp = min(maxp, ONETOUCH_PKT_LEN);
 
 	onetouch = kzalloc(sizeof(struct usb_onetouch), GFP_KERNEL);
 	input_dev = input_allocate_device();
@@ -245,8 +246,7 @@ static int onetouch_connect_input(struct us_data *ss)
 	input_dev->open = usb_onetouch_open;
 	input_dev->close = usb_onetouch_close;
 
-	usb_fill_int_urb(onetouch->irq, udev, pipe, onetouch->data,
-			 (maxp > 8 ? 8 : maxp),
+	usb_fill_int_urb(onetouch->irq, udev, pipe, onetouch->data, maxp,
 			 usb_onetouch_irq, onetouch, endpoint->bInterval);
 	onetouch->irq->transfer_dma = onetouch->data_dma;
 	onetouch->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index 92f35ab..615c66e 100644
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -438,22 +438,21 @@ void usb_stor_report_bus_reset(struct us_data *us)
  * /proc/scsi/ functions
  ***********************************************************************/
 
+static int write_info(struct Scsi_Host *host, char *buffer, int length)
+{
+	/* if someone is sending us data, just throw it away */
+	return length;
+}
+
 /* we use this macro to help us write into the buffer */
 #undef SPRINTF
-#define SPRINTF(args...) \
-	do { if (pos < buffer+length) pos += sprintf(pos, ## args); } while (0)
+#define SPRINTF(args...) seq_printf(m, ## args)
 
-static int proc_info (struct Scsi_Host *host, char *buffer,
-		char **start, off_t offset, int length, int inout)
+static int show_info (struct seq_file *m, struct Scsi_Host *host)
 {
 	struct us_data *us = host_to_us(host);
-	char *pos = buffer;
 	const char *string;
 
-	/* if someone is sending us data, just throw it away */
-	if (inout)
-		return length;
-
 	/* print the controller name */
 	SPRINTF("   Host scsi%d: usb-storage\n", host->host_no);
 
@@ -483,28 +482,14 @@ static int proc_info (struct Scsi_Host *host, char *buffer,
 	SPRINTF("    Transport: %s\n", us->transport_name);
 
 	/* show the device flags */
-	if (pos < buffer + length) {
-		pos += sprintf(pos, "       Quirks:");
+	SPRINTF("       Quirks:");
 
 #define US_FLAG(name, value) \
-	if (us->fflags & value) pos += sprintf(pos, " " #name);
+	if (us->fflags & value) seq_printf(m, " " #name);
 US_DO_ALL_FLAGS
 #undef US_FLAG
-
-		*(pos++) = '\n';
-	}
-
-	/*
-	 * Calculate start of next buffer, and return value.
-	 */
-	*start = buffer + offset;
-
-	if ((pos - buffer) < offset)
-		return (0);
-	else if ((pos - buffer - offset) < length)
-		return (pos - buffer - offset);
-	else
-		return (length);
+	seq_putc(m, '\n');
+	return 0;
 }
 
 /***********************************************************************
@@ -549,7 +534,8 @@ struct scsi_host_template usb_stor_host_template = {
 	/* basic userland interface stuff */
 	.name =				"usb-storage",
 	.proc_name =			"usb-storage",
-	.proc_info =			proc_info,
+	.show_info =			show_info,
+	.write_info =			write_info,
 	.info =				host_info,
 
 	/* command interface -- queued only */
diff --git a/drivers/usb/usb-common.c b/drivers/usb/usb-common.c
index d29503e..0db0a91 100644
--- a/drivers/usb/usb-common.c
+++ b/drivers/usb/usb-common.c
@@ -14,6 +14,32 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/usb/ch9.h>
+#include <linux/usb/otg.h>
+
+const char *usb_otg_state_string(enum usb_otg_state state)
+{
+	static const char *const names[] = {
+		[OTG_STATE_A_IDLE] = "a_idle",
+		[OTG_STATE_A_WAIT_VRISE] = "a_wait_vrise",
+		[OTG_STATE_A_WAIT_BCON] = "a_wait_bcon",
+		[OTG_STATE_A_HOST] = "a_host",
+		[OTG_STATE_A_SUSPEND] = "a_suspend",
+		[OTG_STATE_A_PERIPHERAL] = "a_peripheral",
+		[OTG_STATE_A_WAIT_VFALL] = "a_wait_vfall",
+		[OTG_STATE_A_VBUS_ERR] = "a_vbus_err",
+		[OTG_STATE_B_IDLE] = "b_idle",
+		[OTG_STATE_B_SRP_INIT] = "b_srp_init",
+		[OTG_STATE_B_PERIPHERAL] = "b_peripheral",
+		[OTG_STATE_B_WAIT_ACON] = "b_wait_acon",
+		[OTG_STATE_B_HOST] = "b_host",
+	};
+
+	if (state < 0 || state >= ARRAY_SIZE(names))
+		return "UNDEFINED";
+
+	return names[state];
+}
+EXPORT_SYMBOL_GPL(usb_otg_state_string);
 
 const char *usb_speed_string(enum usb_device_speed speed)
 {
@@ -32,4 +58,25 @@ const char *usb_speed_string(enum usb_device_speed speed)
 }
 EXPORT_SYMBOL_GPL(usb_speed_string);
 
+const char *usb_state_string(enum usb_device_state state)
+{
+	static const char *const names[] = {
+		[USB_STATE_NOTATTACHED] = "not attached",
+		[USB_STATE_ATTACHED] = "attached",
+		[USB_STATE_POWERED] = "powered",
+		[USB_STATE_RECONNECTING] = "reconnecting",
+		[USB_STATE_UNAUTHENTICATED] = "unauthenticated",
+		[USB_STATE_DEFAULT] = "default",
+		[USB_STATE_ADDRESS] = "addresssed",
+		[USB_STATE_CONFIGURED] = "configured",
+		[USB_STATE_SUSPENDED] = "suspended",
+	};
+
+	if (state < 0 || state >= ARRAY_SIZE(names))
+		return "UNKNOWN";
+
+	return names[state];
+}
+EXPORT_SYMBOL_GPL(usb_state_string);
+
 MODULE_LICENSE("GPL");
diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c
index ce31017..7ed3b03 100644
--- a/drivers/usb/usb-skeleton.c
+++ b/drivers/usb/usb-skeleton.c
@@ -61,11 +61,10 @@ struct usb_skel {
 	__u8			bulk_out_endpointAddr;	/* the address of the bulk out endpoint */
 	int			errors;			/* the last request tanked */
 	bool			ongoing_read;		/* a read is going on */
-	bool			processed_urb;		/* indicates we haven't processed the urb */
 	spinlock_t		err_lock;		/* lock for errors */
 	struct kref		kref;
 	struct mutex		io_mutex;		/* synchronize I/O with disconnect */
-	struct completion	bulk_in_completion;	/* to wait for an ongoing read */
+	wait_queue_head_t	bulk_in_wait;		/* to wait for an ongoing read */
 };
 #define to_skel_dev(d) container_of(d, struct usb_skel, kref)
 
@@ -185,7 +184,7 @@ static void skel_read_bulk_callback(struct urb *urb)
 	dev->ongoing_read = 0;
 	spin_unlock(&dev->err_lock);
 
-	complete(&dev->bulk_in_completion);
+	wake_up_interruptible(&dev->bulk_in_wait);
 }
 
 static int skel_do_read_io(struct usb_skel *dev, size_t count)
@@ -206,13 +205,16 @@ static int skel_do_read_io(struct usb_skel *dev, size_t count)
 	dev->ongoing_read = 1;
 	spin_unlock_irq(&dev->err_lock);
 
+	/* submit bulk in urb, which means no data to deliver */
+	dev->bulk_in_filled = 0;
+	dev->bulk_in_copied = 0;
+
 	/* do it */
 	rv = usb_submit_urb(dev->bulk_in_urb, GFP_KERNEL);
 	if (rv < 0) {
 		dev_err(&dev->interface->dev,
 			"%s - failed submitting read urb, error %d\n",
 			__func__, rv);
-		dev->bulk_in_filled = 0;
 		rv = (rv == -ENOMEM) ? rv : -EIO;
 		spin_lock_irq(&dev->err_lock);
 		dev->ongoing_read = 0;
@@ -261,25 +263,9 @@ retry:
 		 * IO may take forever
 		 * hence wait in an interruptible state
 		 */
-		rv = wait_for_completion_interruptible(&dev->bulk_in_completion);
+		rv = wait_event_interruptible(dev->bulk_in_wait, (!dev->ongoing_read));
 		if (rv < 0)
 			goto exit;
-		/*
-		 * by waiting we also semiprocessed the urb
-		 * we must finish now
-		 */
-		dev->bulk_in_copied = 0;
-		dev->processed_urb = 1;
-	}
-
-	if (!dev->processed_urb) {
-		/*
-		 * the URB hasn't been processed
-		 * do it now
-		 */
-		wait_for_completion(&dev->bulk_in_completion);
-		dev->bulk_in_copied = 0;
-		dev->processed_urb = 1;
 	}
 
 	/* errors must be reported */
@@ -289,8 +275,6 @@ retry:
 		dev->errors = 0;
 		/* to preserve notifications about reset */
 		rv = (rv == -EPIPE) ? rv : -EIO;
-		/* no data to deliver */
-		dev->bulk_in_filled = 0;
 		/* report it */
 		goto exit;
 	}
@@ -526,7 +510,7 @@ static int skel_probe(struct usb_interface *interface,
 	mutex_init(&dev->io_mutex);
 	spin_lock_init(&dev->err_lock);
 	init_usb_anchor(&dev->submitted);
-	init_completion(&dev->bulk_in_completion);
+	init_waitqueue_head(&dev->bulk_in_wait);
 
 	dev->udev = usb_get_dev(interface_to_usbdev(interface));
 	dev->interface = interface;
diff --git a/drivers/uwb/rsv.c b/drivers/uwb/rsv.c
index 0b0d8bc..f4ae05f 100644
--- a/drivers/uwb/rsv.c
+++ b/drivers/uwb/rsv.c
@@ -231,7 +231,7 @@ void uwb_rsv_backoff_win_increment(struct uwb_rc *rc)
 		return;
 
 	bow->window <<= 1;
-	bow->n = random32() & (bow->window - 1);
+	bow->n = prandom_u32() & (bow->window - 1);
 	dev_dbg(dev, "new_window=%d, n=%d\n: ", bow->window, bow->n);
 
 	/* reset the timer associated variables */
@@ -557,7 +557,7 @@ int uwb_rsv_establish(struct uwb_rsv *rsv)
 	if (ret)
 		goto out;
 
-	rsv->tiebreaker = random32() & 1;
+	rsv->tiebreaker = prandom_u32() & 1;
 	/* get available mas bitmap */
 	uwb_drp_available(rc, &available);
 
diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c
index 8189cb6..866bde1 100644
--- a/drivers/vfio/pci/vfio_pci.c
+++ b/drivers/vfio/pci/vfio_pci.c
@@ -201,7 +201,9 @@ static int vfio_pci_get_irq_count(struct vfio_pci_device *vdev, int irq_type)
 
 			return (flags & PCI_MSIX_FLAGS_QSIZE) + 1;
 		}
-	}
+	} else if (irq_type == VFIO_PCI_ERR_IRQ_INDEX)
+		if (pci_is_pcie(vdev->pdev))
+			return 1;
 
 	return 0;
 }
@@ -317,6 +319,17 @@ static long vfio_pci_ioctl(void *device_data,
 		if (info.argsz < minsz || info.index >= VFIO_PCI_NUM_IRQS)
 			return -EINVAL;
 
+		switch (info.index) {
+		case VFIO_PCI_INTX_IRQ_INDEX ... VFIO_PCI_MSIX_IRQ_INDEX:
+			break;
+		case VFIO_PCI_ERR_IRQ_INDEX:
+			if (pci_is_pcie(vdev->pdev))
+				break;
+		/* pass thru to return error */
+		default:
+			return -EINVAL;
+		}
+
 		info.flags = VFIO_IRQ_INFO_EVENTFD;
 
 		info.count = vfio_pci_get_irq_count(vdev, info.index);
@@ -346,6 +359,7 @@ static long vfio_pci_ioctl(void *device_data,
 
 		if (!(hdr.flags & VFIO_IRQ_SET_DATA_NONE)) {
 			size_t size;
+			int max = vfio_pci_get_irq_count(vdev, hdr.index);
 
 			if (hdr.flags & VFIO_IRQ_SET_DATA_BOOL)
 				size = sizeof(uint8_t);
@@ -355,7 +369,7 @@ static long vfio_pci_ioctl(void *device_data,
 				return -EINVAL;
 
 			if (hdr.argsz - minsz < hdr.count * size ||
-			    hdr.count > vfio_pci_get_irq_count(vdev, hdr.index))
+			    hdr.start >= max || hdr.start + hdr.count > max)
 				return -EINVAL;
 
 			data = memdup_user((void __user *)(arg + minsz),
@@ -551,11 +565,40 @@ static void vfio_pci_remove(struct pci_dev *pdev)
 	kfree(vdev);
 }
 
+static pci_ers_result_t vfio_pci_aer_err_detected(struct pci_dev *pdev,
+						  pci_channel_state_t state)
+{
+	struct vfio_pci_device *vdev;
+	struct vfio_device *device;
+
+	device = vfio_device_get_from_dev(&pdev->dev);
+	if (device == NULL)
+		return PCI_ERS_RESULT_DISCONNECT;
+
+	vdev = vfio_device_data(device);
+	if (vdev == NULL) {
+		vfio_device_put(device);
+		return PCI_ERS_RESULT_DISCONNECT;
+	}
+
+	if (vdev->err_trigger)
+		eventfd_signal(vdev->err_trigger, 1);
+
+	vfio_device_put(device);
+
+	return PCI_ERS_RESULT_CAN_RECOVER;
+}
+
+static struct pci_error_handlers vfio_err_handlers = {
+	.error_detected = vfio_pci_aer_err_detected,
+};
+
 static struct pci_driver vfio_pci_driver = {
 	.name		= "vfio-pci",
 	.id_table	= NULL, /* only dynamic ids */
 	.probe		= vfio_pci_probe,
 	.remove		= vfio_pci_remove,
+	.err_handler	= &vfio_err_handlers,
 };
 
 static void __exit vfio_pci_cleanup(void)
diff --git a/drivers/vfio/pci/vfio_pci_config.c b/drivers/vfio/pci/vfio_pci_config.c
index aeb00fc..58b41a5 100644
--- a/drivers/vfio/pci/vfio_pci_config.c
+++ b/drivers/vfio/pci/vfio_pci_config.c
@@ -274,9 +274,10 @@ static int vfio_direct_config_read(struct vfio_pci_device *vdev, int pos,
 	return count;
 }
 
-static int vfio_direct_config_write(struct vfio_pci_device *vdev, int pos,
-				    int count, struct perm_bits *perm,
-				    int offset, __le32 val)
+/* Raw access skips any kind of virtualization */
+static int vfio_raw_config_write(struct vfio_pci_device *vdev, int pos,
+				 int count, struct perm_bits *perm,
+				 int offset, __le32 val)
 {
 	int ret;
 
@@ -287,13 +288,36 @@ static int vfio_direct_config_write(struct vfio_pci_device *vdev, int pos,
 	return count;
 }
 
-/* Default all regions to read-only, no-virtualization */
+static int vfio_raw_config_read(struct vfio_pci_device *vdev, int pos,
+				int count, struct perm_bits *perm,
+				int offset, __le32 *val)
+{
+	int ret;
+
+	ret = vfio_user_config_read(vdev->pdev, pos, val, count);
+	if (ret)
+		return pcibios_err_to_errno(ret);
+
+	return count;
+}
+
+/* Default capability regions to read-only, no-virtualization */
 static struct perm_bits cap_perms[PCI_CAP_ID_MAX + 1] = {
 	[0 ... PCI_CAP_ID_MAX] = { .readfn = vfio_direct_config_read }
 };
 static struct perm_bits ecap_perms[PCI_EXT_CAP_ID_MAX + 1] = {
 	[0 ... PCI_EXT_CAP_ID_MAX] = { .readfn = vfio_direct_config_read }
 };
+/*
+ * Default unassigned regions to raw read-write access.  Some devices
+ * require this to function as they hide registers between the gaps in
+ * config space (be2net).  Like MMIO and I/O port registers, we have
+ * to trust the hardware isolation.
+ */
+static struct perm_bits unassigned_perms = {
+	.readfn = vfio_raw_config_read,
+	.writefn = vfio_raw_config_write
+};
 
 static void free_perm_bits(struct perm_bits *perm)
 {
@@ -779,16 +803,16 @@ int __init vfio_pci_init_perm_bits(void)
 
 	/* Capabilities */
 	ret |= init_pci_cap_pm_perm(&cap_perms[PCI_CAP_ID_PM]);
-	cap_perms[PCI_CAP_ID_VPD].writefn = vfio_direct_config_write;
+	cap_perms[PCI_CAP_ID_VPD].writefn = vfio_raw_config_write;
 	ret |= init_pci_cap_pcix_perm(&cap_perms[PCI_CAP_ID_PCIX]);
-	cap_perms[PCI_CAP_ID_VNDR].writefn = vfio_direct_config_write;
+	cap_perms[PCI_CAP_ID_VNDR].writefn = vfio_raw_config_write;
 	ret |= init_pci_cap_exp_perm(&cap_perms[PCI_CAP_ID_EXP]);
 	ret |= init_pci_cap_af_perm(&cap_perms[PCI_CAP_ID_AF]);
 
 	/* Extended capabilities */
 	ret |= init_pci_ext_cap_err_perm(&ecap_perms[PCI_EXT_CAP_ID_ERR]);
 	ret |= init_pci_ext_cap_pwr_perm(&ecap_perms[PCI_EXT_CAP_ID_PWR]);
-	ecap_perms[PCI_EXT_CAP_ID_VNDR].writefn = vfio_direct_config_write;
+	ecap_perms[PCI_EXT_CAP_ID_VNDR].writefn = vfio_raw_config_write;
 
 	if (ret)
 		vfio_pci_uninit_perm_bits();
@@ -801,9 +825,6 @@ static int vfio_find_cap_start(struct vfio_pci_device *vdev, int pos)
 	u8 cap;
 	int base = (pos >= PCI_CFG_SPACE_SIZE) ? PCI_CFG_SPACE_SIZE :
 						 PCI_STD_HEADER_SIZEOF;
-	base /= 4;
-	pos /= 4;
-
 	cap = vdev->pci_config_map[pos];
 
 	if (cap == PCI_CAP_ID_BASIC)
@@ -813,7 +834,7 @@ static int vfio_find_cap_start(struct vfio_pci_device *vdev, int pos)
 	while (pos - 1 >= base && vdev->pci_config_map[pos - 1] == cap)
 		pos--;
 
-	return pos * 4;
+	return pos;
 }
 
 static int vfio_msi_config_read(struct vfio_pci_device *vdev, int pos,
@@ -1230,8 +1251,8 @@ static int vfio_cap_init(struct vfio_pci_device *vdev)
 		}
 
 		/* Sanity check, do we overlap other capabilities? */
-		for (i = 0; i < len; i += 4) {
-			if (likely(map[(pos + i) / 4] == PCI_CAP_ID_INVALID))
+		for (i = 0; i < len; i++) {
+			if (likely(map[pos + i] == PCI_CAP_ID_INVALID))
 				continue;
 
 			pr_warn("%s: %s pci config conflict @0x%x, was cap 0x%x now cap 0x%x\n",
@@ -1239,7 +1260,7 @@ static int vfio_cap_init(struct vfio_pci_device *vdev)
 				pos + i, map[pos + i], cap);
 		}
 
-		memset(map + (pos / 4), cap, len / 4);
+		memset(map + pos, cap, len);
 		ret = vfio_fill_vconfig_bytes(vdev, pos, len);
 		if (ret)
 			return ret;
@@ -1314,8 +1335,8 @@ static int vfio_ecap_init(struct vfio_pci_device *vdev)
 			hidden = true;
 		}
 
-		for (i = 0; i < len; i += 4) {
-			if (likely(map[(epos + i) / 4] == PCI_CAP_ID_INVALID))
+		for (i = 0; i < len; i++) {
+			if (likely(map[epos + i] == PCI_CAP_ID_INVALID))
 				continue;
 
 			pr_warn("%s: %s pci config conflict @0x%x, was ecap 0x%x now ecap 0x%x\n",
@@ -1330,7 +1351,7 @@ static int vfio_ecap_init(struct vfio_pci_device *vdev)
 		 */
 		BUILD_BUG_ON(PCI_EXT_CAP_ID_MAX >= PCI_CAP_ID_INVALID);
 
-		memset(map + (epos / 4), ecap, len / 4);
+		memset(map + epos, ecap, len);
 		ret = vfio_fill_vconfig_bytes(vdev, epos, len);
 		if (ret)
 			return ret;
@@ -1377,10 +1398,12 @@ int vfio_config_init(struct vfio_pci_device *vdev)
 	int ret;
 
 	/*
-	 * Config space, caps and ecaps are all dword aligned, so we can
-	 * use one byte per dword to record the type.
+	 * Config space, caps and ecaps are all dword aligned, so we could
+	 * use one byte per dword to record the type.  However, there are
+	 * no requiremenst on the length of a capability, so the gap between
+	 * capabilities needs byte granularity.
 	 */
-	map = kmalloc(pdev->cfg_size / 4, GFP_KERNEL);
+	map = kmalloc(pdev->cfg_size, GFP_KERNEL);
 	if (!map)
 		return -ENOMEM;
 
@@ -1393,9 +1416,9 @@ int vfio_config_init(struct vfio_pci_device *vdev)
 	vdev->pci_config_map = map;
 	vdev->vconfig = vconfig;
 
-	memset(map, PCI_CAP_ID_BASIC, PCI_STD_HEADER_SIZEOF / 4);
-	memset(map + (PCI_STD_HEADER_SIZEOF / 4), PCI_CAP_ID_INVALID,
-	       (pdev->cfg_size - PCI_STD_HEADER_SIZEOF) / 4);
+	memset(map, PCI_CAP_ID_BASIC, PCI_STD_HEADER_SIZEOF);
+	memset(map + PCI_STD_HEADER_SIZEOF, PCI_CAP_ID_INVALID,
+	       pdev->cfg_size - PCI_STD_HEADER_SIZEOF);
 
 	ret = vfio_fill_vconfig_bytes(vdev, 0, PCI_STD_HEADER_SIZEOF);
 	if (ret)
@@ -1450,6 +1473,22 @@ void vfio_config_free(struct vfio_pci_device *vdev)
 	vdev->msi_perm = NULL;
 }
 
+/*
+ * Find the remaining number of bytes in a dword that match the given
+ * position.  Stop at either the end of the capability or the dword boundary.
+ */
+static size_t vfio_pci_cap_remaining_dword(struct vfio_pci_device *vdev,
+					   loff_t pos)
+{
+	u8 cap = vdev->pci_config_map[pos];
+	size_t i;
+
+	for (i = 1; (pos + i) % 4 && vdev->pci_config_map[pos + i] == cap; i++)
+		/* nop */;
+
+	return i;
+}
+
 static ssize_t vfio_config_do_rw(struct vfio_pci_device *vdev, char __user *buf,
 				 size_t count, loff_t *ppos, bool iswrite)
 {
@@ -1458,55 +1497,48 @@ static ssize_t vfio_config_do_rw(struct vfio_pci_device *vdev, char __user *buf,
 	__le32 val = 0;
 	int cap_start = 0, offset;
 	u8 cap_id;
-	ssize_t ret = count;
+	ssize_t ret;
 
-	if (*ppos < 0 || *ppos + count > pdev->cfg_size)
+	if (*ppos < 0 || *ppos >= pdev->cfg_size ||
+	    *ppos + count > pdev->cfg_size)
 		return -EFAULT;
 
 	/*
-	 * gcc can't seem to figure out we're a static function, only called
-	 * with count of 1/2/4 and hits copy_from_user_overflow without this.
+	 * Chop accesses into aligned chunks containing no more than a
+	 * single capability.  Caller increments to the next chunk.
 	 */
-	if (count > sizeof(val))
-		return -EINVAL;
+	count = min(count, vfio_pci_cap_remaining_dword(vdev, *ppos));
+	if (count >= 4 && !(*ppos % 4))
+		count = 4;
+	else if (count >= 2 && !(*ppos % 2))
+		count = 2;
+	else
+		count = 1;
 
-	cap_id = vdev->pci_config_map[*ppos / 4];
+	ret = count;
 
-	if (cap_id == PCI_CAP_ID_INVALID) {
-		if (iswrite)
-			return ret; /* drop */
-
-		/*
-		 * Per PCI spec 3.0, section 6.1, reads from reserved and
-		 * unimplemented registers return 0
-		 */
-		if (copy_to_user(buf, &val, count))
-			return -EFAULT;
-
-		return ret;
-	}
-
-	/*
-	 * All capabilities are minimum 4 bytes and aligned on dword
-	 * boundaries.  Since we don't support unaligned accesses, we're
-	 * only ever accessing a single capability.
-	 */
-	if (*ppos >= PCI_CFG_SPACE_SIZE) {
-		WARN_ON(cap_id > PCI_EXT_CAP_ID_MAX);
-
-		perm = &ecap_perms[cap_id];
-		cap_start = vfio_find_cap_start(vdev, *ppos);
+	cap_id = vdev->pci_config_map[*ppos];
 
+	if (cap_id == PCI_CAP_ID_INVALID) {
+		perm = &unassigned_perms;
+		cap_start = *ppos;
 	} else {
-		WARN_ON(cap_id > PCI_CAP_ID_MAX);
+		if (*ppos >= PCI_CFG_SPACE_SIZE) {
+			WARN_ON(cap_id > PCI_EXT_CAP_ID_MAX);
 
-		perm = &cap_perms[cap_id];
+			perm = &ecap_perms[cap_id];
+			cap_start = vfio_find_cap_start(vdev, *ppos);
+		} else {
+			WARN_ON(cap_id > PCI_CAP_ID_MAX);
 
-		if (cap_id == PCI_CAP_ID_MSI)
-			perm = vdev->msi_perm;
+			perm = &cap_perms[cap_id];
 
-		if (cap_id > PCI_CAP_ID_BASIC)
-			cap_start = vfio_find_cap_start(vdev, *ppos);
+			if (cap_id == PCI_CAP_ID_MSI)
+				perm = vdev->msi_perm;
+
+			if (cap_id > PCI_CAP_ID_BASIC)
+				cap_start = vfio_find_cap_start(vdev, *ppos);
+		}
 	}
 
 	WARN_ON(!cap_start && cap_id != PCI_CAP_ID_BASIC);
@@ -1546,20 +1578,8 @@ ssize_t vfio_pci_config_rw(struct vfio_pci_device *vdev, char __user *buf,
 
 	pos &= VFIO_PCI_OFFSET_MASK;
 
-	/*
-	 * We want to both keep the access size the caller users as well as
-	 * support reading large chunks of config space in a single call.
-	 * PCI doesn't support unaligned accesses, so we can safely break
-	 * those apart.
-	 */
 	while (count) {
-		if (count >= 4 && !(pos % 4))
-			ret = vfio_config_do_rw(vdev, buf, 4, &pos, iswrite);
-		else if (count >= 2 && !(pos % 2))
-			ret = vfio_config_do_rw(vdev, buf, 2, &pos, iswrite);
-		else
-			ret = vfio_config_do_rw(vdev, buf, 1, &pos, iswrite);
-
+		ret = vfio_config_do_rw(vdev, buf, count, &pos, iswrite);
 		if (ret < 0)
 			return ret;
 
diff --git a/drivers/vfio/pci/vfio_pci_intrs.c b/drivers/vfio/pci/vfio_pci_intrs.c
index a965091..4bc704e 100644
--- a/drivers/vfio/pci/vfio_pci_intrs.c
+++ b/drivers/vfio/pci/vfio_pci_intrs.c
@@ -287,7 +287,8 @@ void vfio_pci_intx_mask(struct vfio_pci_device *vdev)
  * a signal is necessary, which can then be handled via a work queue
  * or directly depending on the caller.
  */
-int vfio_pci_intx_unmask_handler(struct vfio_pci_device *vdev, void *unused)
+static int vfio_pci_intx_unmask_handler(struct vfio_pci_device *vdev,
+					void *unused)
 {
 	struct pci_dev *pdev = vdev->pdev;
 	unsigned long flags;
@@ -746,6 +747,63 @@ static int vfio_pci_set_msi_trigger(struct vfio_pci_device *vdev,
 	return 0;
 }
 
+static int vfio_pci_set_err_trigger(struct vfio_pci_device *vdev,
+				    unsigned index, unsigned start,
+				    unsigned count, uint32_t flags, void *data)
+{
+	int32_t fd = *(int32_t *)data;
+	struct pci_dev *pdev = vdev->pdev;
+
+	if ((index != VFIO_PCI_ERR_IRQ_INDEX) ||
+	    !(flags & VFIO_IRQ_SET_DATA_TYPE_MASK))
+		return -EINVAL;
+
+	/*
+	 * device_lock synchronizes setting and checking of
+	 * err_trigger. The vfio_pci_aer_err_detected() is also
+	 * called with device_lock held.
+	 */
+
+	/* DATA_NONE/DATA_BOOL enables loopback testing */
+
+	if (flags & VFIO_IRQ_SET_DATA_NONE) {
+		device_lock(&pdev->dev);
+		if (vdev->err_trigger)
+			eventfd_signal(vdev->err_trigger, 1);
+		device_unlock(&pdev->dev);
+		return 0;
+	} else if (flags & VFIO_IRQ_SET_DATA_BOOL) {
+		uint8_t trigger = *(uint8_t *)data;
+		device_lock(&pdev->dev);
+		if (trigger && vdev->err_trigger)
+			eventfd_signal(vdev->err_trigger, 1);
+		device_unlock(&pdev->dev);
+		return 0;
+	}
+
+	/* Handle SET_DATA_EVENTFD */
+
+	if (fd == -1) {
+		device_lock(&pdev->dev);
+		if (vdev->err_trigger)
+			eventfd_ctx_put(vdev->err_trigger);
+		vdev->err_trigger = NULL;
+		device_unlock(&pdev->dev);
+		return 0;
+	} else if (fd >= 0) {
+		struct eventfd_ctx *efdctx;
+		efdctx = eventfd_ctx_fdget(fd);
+		if (IS_ERR(efdctx))
+			return PTR_ERR(efdctx);
+		device_lock(&pdev->dev);
+		if (vdev->err_trigger)
+			eventfd_ctx_put(vdev->err_trigger);
+		vdev->err_trigger = efdctx;
+		device_unlock(&pdev->dev);
+		return 0;
+	} else
+		return -EINVAL;
+}
 int vfio_pci_set_irqs_ioctl(struct vfio_pci_device *vdev, uint32_t flags,
 			    unsigned index, unsigned start, unsigned count,
 			    void *data)
@@ -780,6 +838,13 @@ int vfio_pci_set_irqs_ioctl(struct vfio_pci_device *vdev, uint32_t flags,
 			break;
 		}
 		break;
+	case VFIO_PCI_ERR_IRQ_INDEX:
+		switch (flags & VFIO_IRQ_SET_ACTION_TYPE_MASK) {
+		case VFIO_IRQ_SET_ACTION_TRIGGER:
+			if (pci_is_pcie(vdev->pdev))
+				func = vfio_pci_set_err_trigger;
+			break;
+		}
 	}
 
 	if (!func)
diff --git a/drivers/vfio/pci/vfio_pci_private.h b/drivers/vfio/pci/vfio_pci_private.h
index d7e55d0..9c6d5d0 100644
--- a/drivers/vfio/pci/vfio_pci_private.h
+++ b/drivers/vfio/pci/vfio_pci_private.h
@@ -56,6 +56,7 @@ struct vfio_pci_device {
 	bool			has_vga;
 	struct pci_saved_state	*pci_saved_state;
 	atomic_t		refcnt;
+	struct eventfd_ctx	*err_trigger;
 };
 
 #define is_intx(vdev) (vdev->irq_type == VFIO_PCI_INTX_IRQ_INDEX)
diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c
index fcc12f3..21eddd9 100644
--- a/drivers/vfio/vfio.c
+++ b/drivers/vfio/vfio.c
@@ -392,12 +392,13 @@ static void vfio_device_release(struct kref *kref)
 }
 
 /* Device reference always implies a group reference */
-static void vfio_device_put(struct vfio_device *device)
+void vfio_device_put(struct vfio_device *device)
 {
 	struct vfio_group *group = device->group;
 	kref_put_mutex(&device->kref, vfio_device_release, &group->device_lock);
 	vfio_group_put(group);
 }
+EXPORT_SYMBOL_GPL(vfio_device_put);
 
 static void vfio_device_get(struct vfio_device *device)
 {
@@ -627,6 +628,33 @@ int vfio_add_group_dev(struct device *dev,
 }
 EXPORT_SYMBOL_GPL(vfio_add_group_dev);
 
+/**
+ * Get a reference to the vfio_device for a device that is known to
+ * be bound to a vfio driver.  The driver implicitly holds a
+ * vfio_device reference between vfio_add_group_dev and
+ * vfio_del_group_dev.  We can therefore use drvdata to increment
+ * that reference from the struct device.  This additional
+ * reference must be released by calling vfio_device_put.
+ */
+struct vfio_device *vfio_device_get_from_dev(struct device *dev)
+{
+	struct vfio_device *device = dev_get_drvdata(dev);
+
+	vfio_device_get(device);
+
+	return device;
+}
+EXPORT_SYMBOL_GPL(vfio_device_get_from_dev);
+
+/*
+ * Caller must hold a reference to the vfio_device
+ */
+void *vfio_device_data(struct vfio_device *device)
+{
+	return device->device_data;
+}
+EXPORT_SYMBOL_GPL(vfio_device_data);
+
 /* Given a referenced group, check if it contains the device */
 static bool vfio_dev_present(struct vfio_group *group, struct device *dev)
 {
diff --git a/drivers/vhost/Kconfig b/drivers/vhost/Kconfig
index bf24317..85b773a 100644
--- a/drivers/vhost/Kconfig
+++ b/drivers/vhost/Kconfig
@@ -1,6 +1,7 @@
 config VHOST_NET
 	tristate "Host kernel accelerator for virtio net"
 	depends on NET && EVENTFD && (TUN || !TUN) && (MACVTAP || !MACVTAP)
+	select VHOST_RING
 	---help---
 	  This kernel module can be loaded in host kernel to accelerate
 	  guest networking with virtio_net. Not to be confused with virtio_net
@@ -12,3 +13,10 @@ config VHOST_NET
 if STAGING
 source "drivers/vhost/Kconfig.tcm"
 endif
+
+config VHOST_RING
+	tristate
+	---help---
+	  This option is selected by any driver which needs to access
+	  the host side of a virtio ring.
+
diff --git a/drivers/vhost/Kconfig.tcm b/drivers/vhost/Kconfig.tcm
index 7e3aa28..c3a8cfa 100644
--- a/drivers/vhost/Kconfig.tcm
+++ b/drivers/vhost/Kconfig.tcm
@@ -1,6 +1,7 @@
 config TCM_VHOST
 	tristate "TCM_VHOST fabric module"
 	depends on TARGET_CORE && EVENTFD && m
+	select VHOST_RING
 	default n
 	---help---
 	Say M here to enable the TCM_VHOST fabric module for use with virtio-scsi guests
diff --git a/drivers/vhost/Makefile b/drivers/vhost/Makefile
index a27b053..1d37f5e 100644
--- a/drivers/vhost/Makefile
+++ b/drivers/vhost/Makefile
@@ -2,3 +2,5 @@ obj-$(CONFIG_VHOST_NET) += vhost_net.o
 vhost_net-y := vhost.o net.o
 
 obj-$(CONFIG_TCM_VHOST) += tcm_vhost.o
+
+obj-$(CONFIG_VHOST_RING) += vringh.o
diff --git a/drivers/vhost/tcm_vhost.c b/drivers/vhost/tcm_vhost.c
index 2968b49..4a68c1f 100644
--- a/drivers/vhost/tcm_vhost.c
+++ b/drivers/vhost/tcm_vhost.c
@@ -76,7 +76,6 @@ struct vhost_scsi {
 	/* Protected by vhost_scsi->dev.mutex */
 	struct tcm_vhost_tpg *vs_tpg[VHOST_SCSI_MAX_TARGET];
 	char vs_vhost_wwpn[TRANSPORT_IQN_LEN];
-	bool vs_endpoint;
 
 	struct vhost_dev dev;
 	struct vhost_virtqueue vqs[VHOST_SCSI_MAX_VQ];
@@ -100,6 +99,24 @@ static int iov_num_pages(struct iovec *iov)
 	       ((unsigned long)iov->iov_base & PAGE_MASK)) >> PAGE_SHIFT;
 }
 
+static bool tcm_vhost_check_endpoint(struct vhost_virtqueue *vq)
+{
+	bool ret = false;
+
+	/*
+	 * We can handle the vq only after the endpoint is setup by calling the
+	 * VHOST_SCSI_SET_ENDPOINT ioctl.
+	 *
+	 * TODO: Check that we are running from vhost_worker which acts
+	 * as read-side critical section for vhost kind of RCU.
+	 * See the comments in struct vhost_virtqueue in drivers/vhost/vhost.h
+	 */
+	if (rcu_dereference_check(vq->private_data, 1))
+		ret = true;
+
+	return ret;
+}
+
 static int tcm_vhost_check_true(struct se_portal_group *se_tpg)
 {
 	return 1;
@@ -590,8 +607,7 @@ static void vhost_scsi_handle_vq(struct vhost_scsi *vs,
 	int head, ret;
 	u8 target;
 
-	/* Must use ioctl VHOST_SCSI_SET_ENDPOINT */
-	if (unlikely(!vs->vs_endpoint))
+	if (!tcm_vhost_check_endpoint(vq))
 		return;
 
 	mutex_lock(&vq->mutex);
@@ -790,8 +806,9 @@ static int vhost_scsi_set_endpoint(
 {
 	struct tcm_vhost_tport *tv_tport;
 	struct tcm_vhost_tpg *tv_tpg;
+	struct vhost_virtqueue *vq;
 	bool match = false;
-	int index, ret;
+	int index, ret, i;
 
 	mutex_lock(&vs->dev.mutex);
 	/* Verify that ring has been setup correctly. */
@@ -835,7 +852,14 @@ static int vhost_scsi_set_endpoint(
 	if (match) {
 		memcpy(vs->vs_vhost_wwpn, t->vhost_wwpn,
 		       sizeof(vs->vs_vhost_wwpn));
-		vs->vs_endpoint = true;
+		for (i = 0; i < VHOST_SCSI_MAX_VQ; i++) {
+			vq = &vs->vqs[i];
+			/* Flushing the vhost_work acts as synchronize_rcu */
+			mutex_lock(&vq->mutex);
+			rcu_assign_pointer(vq->private_data, vs);
+			vhost_init_used(vq);
+			mutex_unlock(&vq->mutex);
+		}
 		ret = 0;
 	} else {
 		ret = -EEXIST;
@@ -851,6 +875,8 @@ static int vhost_scsi_clear_endpoint(
 {
 	struct tcm_vhost_tport *tv_tport;
 	struct tcm_vhost_tpg *tv_tpg;
+	struct vhost_virtqueue *vq;
+	bool match = false;
 	int index, ret, i;
 	u8 target;
 
@@ -886,9 +912,18 @@ static int vhost_scsi_clear_endpoint(
 		}
 		tv_tpg->tv_tpg_vhost_count--;
 		vs->vs_tpg[target] = NULL;
-		vs->vs_endpoint = false;
+		match = true;
 		mutex_unlock(&tv_tpg->tv_tpg_mutex);
 	}
+	if (match) {
+		for (i = 0; i < VHOST_SCSI_MAX_VQ; i++) {
+			vq = &vs->vqs[i];
+			/* Flushing the vhost_work acts as synchronize_rcu */
+			mutex_lock(&vq->mutex);
+			rcu_assign_pointer(vq->private_data, NULL);
+			mutex_unlock(&vq->mutex);
+		}
+	}
 	mutex_unlock(&vs->dev.mutex);
 	return 0;
 
diff --git a/drivers/vhost/test.c b/drivers/vhost/test.c
index 91d6f06..329d302 100644
--- a/drivers/vhost/test.c
+++ b/drivers/vhost/test.c
@@ -275,7 +275,9 @@ static long vhost_test_ioctl(struct file *f, unsigned int ioctl,
 		return vhost_test_reset_owner(n);
 	default:
 		mutex_lock(&n->dev.mutex);
-		r = vhost_dev_ioctl(&n->dev, ioctl, arg);
+		r = vhost_dev_ioctl(&n->dev, ioctl, argp);
+                if (r == -ENOIOCTLCMD)
+                        r = vhost_vring_ioctl(&n->dev, ioctl, argp);
 		vhost_test_flush(n);
 		mutex_unlock(&n->dev.mutex);
 		return r;
diff --git a/drivers/vhost/vringh.c b/drivers/vhost/vringh.c
new file mode 100644
index 0000000..bff0775
--- /dev/null
+++ b/drivers/vhost/vringh.c
@@ -0,0 +1,1007 @@
+/*
+ * Helpers for the host side of a virtio ring.
+ *
+ * Since these may be in userspace, we use (inline) accessors.
+ */
+#include <linux/vringh.h>
+#include <linux/virtio_ring.h>
+#include <linux/kernel.h>
+#include <linux/ratelimit.h>
+#include <linux/uaccess.h>
+#include <linux/slab.h>
+#include <linux/export.h>
+
+static __printf(1,2) __cold void vringh_bad(const char *fmt, ...)
+{
+	static DEFINE_RATELIMIT_STATE(vringh_rs,
+				      DEFAULT_RATELIMIT_INTERVAL,
+				      DEFAULT_RATELIMIT_BURST);
+	if (__ratelimit(&vringh_rs)) {
+		va_list ap;
+		va_start(ap, fmt);
+		printk(KERN_NOTICE "vringh:");
+		vprintk(fmt, ap);
+		va_end(ap);
+	}
+}
+
+/* Returns vring->num if empty, -ve on error. */
+static inline int __vringh_get_head(const struct vringh *vrh,
+				    int (*getu16)(u16 *val, const u16 *p),
+				    u16 *last_avail_idx)
+{
+	u16 avail_idx, i, head;
+	int err;
+
+	err = getu16(&avail_idx, &vrh->vring.avail->idx);
+	if (err) {
+		vringh_bad("Failed to access avail idx at %p",
+			   &vrh->vring.avail->idx);
+		return err;
+	}
+
+	if (*last_avail_idx == avail_idx)
+		return vrh->vring.num;
+
+	/* Only get avail ring entries after they have been exposed by guest. */
+	virtio_rmb(vrh->weak_barriers);
+
+	i = *last_avail_idx & (vrh->vring.num - 1);
+
+	err = getu16(&head, &vrh->vring.avail->ring[i]);
+	if (err) {
+		vringh_bad("Failed to read head: idx %d address %p",
+			   *last_avail_idx, &vrh->vring.avail->ring[i]);
+		return err;
+	}
+
+	if (head >= vrh->vring.num) {
+		vringh_bad("Guest says index %u > %u is available",
+			   head, vrh->vring.num);
+		return -EINVAL;
+	}
+
+	(*last_avail_idx)++;
+	return head;
+}
+
+/* Copy some bytes to/from the iovec.  Returns num copied. */
+static inline ssize_t vringh_iov_xfer(struct vringh_kiov *iov,
+				      void *ptr, size_t len,
+				      int (*xfer)(void *addr, void *ptr,
+						  size_t len))
+{
+	int err, done = 0;
+
+	while (len && iov->i < iov->used) {
+		size_t partlen;
+
+		partlen = min(iov->iov[iov->i].iov_len, len);
+		err = xfer(iov->iov[iov->i].iov_base, ptr, partlen);
+		if (err)
+			return err;
+		done += partlen;
+		len -= partlen;
+		ptr += partlen;
+		iov->consumed += partlen;
+		iov->iov[iov->i].iov_len -= partlen;
+		iov->iov[iov->i].iov_base += partlen;
+
+		if (!iov->iov[iov->i].iov_len) {
+			/* Fix up old iov element then increment. */
+			iov->iov[iov->i].iov_len = iov->consumed;
+			iov->iov[iov->i].iov_base -= iov->consumed;
+			
+			iov->consumed = 0;
+			iov->i++;
+		}
+	}
+	return done;
+}
+
+/* May reduce *len if range is shorter. */
+static inline bool range_check(struct vringh *vrh, u64 addr, size_t *len,
+			       struct vringh_range *range,
+			       bool (*getrange)(struct vringh *,
+						u64, struct vringh_range *))
+{
+	if (addr < range->start || addr > range->end_incl) {
+		if (!getrange(vrh, addr, range))
+			return false;
+	}
+	BUG_ON(addr < range->start || addr > range->end_incl);
+
+	/* To end of memory? */
+	if (unlikely(addr + *len == 0)) {
+		if (range->end_incl == -1ULL)
+			return true;
+		goto truncate;
+	}
+
+	/* Otherwise, don't wrap. */
+	if (addr + *len < addr) {
+		vringh_bad("Wrapping descriptor %zu@0x%llx",
+			   *len, (unsigned long long)addr);
+		return false;
+	}
+
+	if (unlikely(addr + *len - 1 > range->end_incl))
+		goto truncate;
+	return true;
+
+truncate:
+	*len = range->end_incl + 1 - addr;
+	return true;
+}
+
+static inline bool no_range_check(struct vringh *vrh, u64 addr, size_t *len,
+				  struct vringh_range *range,
+				  bool (*getrange)(struct vringh *,
+						   u64, struct vringh_range *))
+{
+	return true;
+}
+
+/* No reason for this code to be inline. */
+static int move_to_indirect(int *up_next, u16 *i, void *addr,
+			    const struct vring_desc *desc,
+			    struct vring_desc **descs, int *desc_max)
+{
+	/* Indirect tables can't have indirect. */
+	if (*up_next != -1) {
+		vringh_bad("Multilevel indirect %u->%u", *up_next, *i);
+		return -EINVAL;
+	}
+
+	if (unlikely(desc->len % sizeof(struct vring_desc))) {
+		vringh_bad("Strange indirect len %u", desc->len);
+		return -EINVAL;
+	}
+
+	/* We will check this when we follow it! */
+	if (desc->flags & VRING_DESC_F_NEXT)
+		*up_next = desc->next;
+	else
+		*up_next = -2;
+	*descs = addr;
+	*desc_max = desc->len / sizeof(struct vring_desc);
+
+	/* Now, start at the first indirect. */
+	*i = 0;
+	return 0;
+}
+
+static int resize_iovec(struct vringh_kiov *iov, gfp_t gfp)
+{
+	struct kvec *new;
+	unsigned int flag, new_num = (iov->max_num & ~VRINGH_IOV_ALLOCATED) * 2;
+
+	if (new_num < 8)
+		new_num = 8;
+
+	flag = (iov->max_num & VRINGH_IOV_ALLOCATED);
+	if (flag)
+		new = krealloc(iov->iov, new_num * sizeof(struct iovec), gfp);
+	else {
+		new = kmalloc(new_num * sizeof(struct iovec), gfp);
+		if (new) {
+			memcpy(new, iov->iov,
+			       iov->max_num * sizeof(struct iovec));
+			flag = VRINGH_IOV_ALLOCATED;
+		}
+	}
+	if (!new)
+		return -ENOMEM;
+	iov->iov = new;
+	iov->max_num = (new_num | flag);
+	return 0;
+}
+
+static u16 __cold return_from_indirect(const struct vringh *vrh, int *up_next,
+				       struct vring_desc **descs, int *desc_max)
+{
+	u16 i = *up_next;
+
+	*up_next = -1;
+	*descs = vrh->vring.desc;
+	*desc_max = vrh->vring.num;
+	return i;
+}
+
+static int slow_copy(struct vringh *vrh, void *dst, const void *src,
+		     bool (*rcheck)(struct vringh *vrh, u64 addr, size_t *len,
+				    struct vringh_range *range,
+				    bool (*getrange)(struct vringh *vrh,
+						     u64,
+						     struct vringh_range *)),
+		     bool (*getrange)(struct vringh *vrh,
+				      u64 addr,
+				      struct vringh_range *r),
+		     struct vringh_range *range,
+		     int (*copy)(void *dst, const void *src, size_t len))
+{
+	size_t part, len = sizeof(struct vring_desc);
+
+	do {
+		u64 addr;
+		int err;
+
+		part = len;
+		addr = (u64)(unsigned long)src - range->offset;
+
+		if (!rcheck(vrh, addr, &part, range, getrange))
+			return -EINVAL;
+
+		err = copy(dst, src, part);
+		if (err)
+			return err;
+
+		dst += part;
+		src += part;
+		len -= part;
+	} while (len);
+	return 0;
+}
+
+static inline int
+__vringh_iov(struct vringh *vrh, u16 i,
+	     struct vringh_kiov *riov,
+	     struct vringh_kiov *wiov,
+	     bool (*rcheck)(struct vringh *vrh, u64 addr, size_t *len,
+			    struct vringh_range *range,
+			    bool (*getrange)(struct vringh *, u64,
+					     struct vringh_range *)),
+	     bool (*getrange)(struct vringh *, u64, struct vringh_range *),
+	     gfp_t gfp,
+	     int (*copy)(void *dst, const void *src, size_t len))
+{
+	int err, count = 0, up_next, desc_max;
+	struct vring_desc desc, *descs;
+	struct vringh_range range = { -1ULL, 0 }, slowrange;
+	bool slow = false;
+
+	/* We start traversing vring's descriptor table. */
+	descs = vrh->vring.desc;
+	desc_max = vrh->vring.num;
+	up_next = -1;
+
+	if (riov)
+		riov->i = riov->used = 0;
+	else if (wiov)
+		wiov->i = wiov->used = 0;
+	else
+		/* You must want something! */
+		BUG();
+
+	for (;;) {
+		void *addr;
+		struct vringh_kiov *iov;
+		size_t len;
+
+		if (unlikely(slow))
+			err = slow_copy(vrh, &desc, &descs[i], rcheck, getrange,
+					&slowrange, copy);
+		else
+			err = copy(&desc, &descs[i], sizeof(desc));
+		if (unlikely(err))
+			goto fail;
+
+		if (unlikely(desc.flags & VRING_DESC_F_INDIRECT)) {
+			/* Make sure it's OK, and get offset. */
+			len = desc.len;
+			if (!rcheck(vrh, desc.addr, &len, &range, getrange)) {
+				err = -EINVAL;
+				goto fail;
+			}
+
+			if (unlikely(len != desc.len)) {
+				slow = true;
+				/* We need to save this range to use offset */
+				slowrange = range;
+			}
+
+			addr = (void *)(long)(desc.addr + range.offset);
+			err = move_to_indirect(&up_next, &i, addr, &desc,
+					       &descs, &desc_max);
+			if (err)
+				goto fail;
+			continue;
+		}
+
+		if (count++ == vrh->vring.num) {
+			vringh_bad("Descriptor loop in %p", descs);
+			err = -ELOOP;
+			goto fail;
+		}
+
+		if (desc.flags & VRING_DESC_F_WRITE)
+			iov = wiov;
+		else {
+			iov = riov;
+			if (unlikely(wiov && wiov->i)) {
+				vringh_bad("Readable desc %p after writable",
+					   &descs[i]);
+				err = -EINVAL;
+				goto fail;
+			}
+		}
+
+		if (!iov) {
+			vringh_bad("Unexpected %s desc",
+				   !wiov ? "writable" : "readable");
+			err = -EPROTO;
+			goto fail;
+		}
+
+	again:
+		/* Make sure it's OK, and get offset. */
+		len = desc.len;
+		if (!rcheck(vrh, desc.addr, &len, &range, getrange)) {
+			err = -EINVAL;
+			goto fail;
+		}
+		addr = (void *)(unsigned long)(desc.addr + range.offset);
+
+		if (unlikely(iov->used == (iov->max_num & ~VRINGH_IOV_ALLOCATED))) {
+			err = resize_iovec(iov, gfp);
+			if (err)
+				goto fail;
+		}
+
+		iov->iov[iov->used].iov_base = addr;
+		iov->iov[iov->used].iov_len = len;
+		iov->used++;
+
+		if (unlikely(len != desc.len)) {
+			desc.len -= len;
+			desc.addr += len;
+			goto again;
+		}
+
+		if (desc.flags & VRING_DESC_F_NEXT) {
+			i = desc.next;
+		} else {
+			/* Just in case we need to finish traversing above. */
+			if (unlikely(up_next > 0)) {
+				i = return_from_indirect(vrh, &up_next,
+							 &descs, &desc_max);
+				slow = false;
+			} else
+				break;
+		}
+
+		if (i >= desc_max) {
+			vringh_bad("Chained index %u > %u", i, desc_max);
+			err = -EINVAL;
+			goto fail;
+		}
+	}
+
+	return 0;
+
+fail:
+	return err;
+}
+
+static inline int __vringh_complete(struct vringh *vrh,
+				    const struct vring_used_elem *used,
+				    unsigned int num_used,
+				    int (*putu16)(u16 *p, u16 val),
+				    int (*putused)(struct vring_used_elem *dst,
+						   const struct vring_used_elem
+						   *src, unsigned num))
+{
+	struct vring_used *used_ring;
+	int err;
+	u16 used_idx, off;
+
+	used_ring = vrh->vring.used;
+	used_idx = vrh->last_used_idx + vrh->completed;
+
+	off = used_idx % vrh->vring.num;
+
+	/* Compiler knows num_used == 1 sometimes, hence extra check */
+	if (num_used > 1 && unlikely(off + num_used >= vrh->vring.num)) {
+		u16 part = vrh->vring.num - off;
+		err = putused(&used_ring->ring[off], used, part);
+		if (!err)
+			err = putused(&used_ring->ring[0], used + part,
+				      num_used - part);
+	} else
+		err = putused(&used_ring->ring[off], used, num_used);
+
+	if (err) {
+		vringh_bad("Failed to write %u used entries %u at %p",
+			   num_used, off, &used_ring->ring[off]);
+		return err;
+	}
+
+	/* Make sure buffer is written before we update index. */
+	virtio_wmb(vrh->weak_barriers);
+
+	err = putu16(&vrh->vring.used->idx, used_idx + num_used);
+	if (err) {
+		vringh_bad("Failed to update used index at %p",
+			   &vrh->vring.used->idx);
+		return err;
+	}
+
+	vrh->completed += num_used;
+	return 0;
+}
+
+
+static inline int __vringh_need_notify(struct vringh *vrh,
+				       int (*getu16)(u16 *val, const u16 *p))
+{
+	bool notify;
+	u16 used_event;
+	int err;
+
+	/* Flush out used index update. This is paired with the
+	 * barrier that the Guest executes when enabling
+	 * interrupts. */
+	virtio_mb(vrh->weak_barriers);
+
+	/* Old-style, without event indices. */
+	if (!vrh->event_indices) {
+		u16 flags;
+		err = getu16(&flags, &vrh->vring.avail->flags);
+		if (err) {
+			vringh_bad("Failed to get flags at %p",
+				   &vrh->vring.avail->flags);
+			return err;
+		}
+		return (!(flags & VRING_AVAIL_F_NO_INTERRUPT));
+	}
+
+	/* Modern: we know when other side wants to know. */
+	err = getu16(&used_event, &vring_used_event(&vrh->vring));
+	if (err) {
+		vringh_bad("Failed to get used event idx at %p",
+			   &vring_used_event(&vrh->vring));
+		return err;
+	}
+
+	/* Just in case we added so many that we wrap. */
+	if (unlikely(vrh->completed > 0xffff))
+		notify = true;
+	else
+		notify = vring_need_event(used_event,
+					  vrh->last_used_idx + vrh->completed,
+					  vrh->last_used_idx);
+
+	vrh->last_used_idx += vrh->completed;
+	vrh->completed = 0;
+	return notify;
+}
+
+static inline bool __vringh_notify_enable(struct vringh *vrh,
+					  int (*getu16)(u16 *val, const u16 *p),
+					  int (*putu16)(u16 *p, u16 val))
+{
+	u16 avail;
+
+	if (!vrh->event_indices) {
+		/* Old-school; update flags. */
+		if (putu16(&vrh->vring.used->flags, 0) != 0) {
+			vringh_bad("Clearing used flags %p",
+				   &vrh->vring.used->flags);
+			return true;
+		}
+	} else {
+		if (putu16(&vring_avail_event(&vrh->vring),
+			   vrh->last_avail_idx) != 0) {
+			vringh_bad("Updating avail event index %p",
+				   &vring_avail_event(&vrh->vring));
+			return true;
+		}
+	}
+
+	/* They could have slipped one in as we were doing that: make
+	 * sure it's written, then check again. */
+	virtio_mb(vrh->weak_barriers);
+
+	if (getu16(&avail, &vrh->vring.avail->idx) != 0) {
+		vringh_bad("Failed to check avail idx at %p",
+			   &vrh->vring.avail->idx);
+		return true;
+	}
+
+	/* This is unlikely, so we just leave notifications enabled
+	 * (if we're using event_indices, we'll only get one
+	 * notification anyway). */
+	return avail == vrh->last_avail_idx;
+}
+
+static inline void __vringh_notify_disable(struct vringh *vrh,
+					   int (*putu16)(u16 *p, u16 val))
+{
+	if (!vrh->event_indices) {
+		/* Old-school; update flags. */
+		if (putu16(&vrh->vring.used->flags, VRING_USED_F_NO_NOTIFY)) {
+			vringh_bad("Setting used flags %p",
+				   &vrh->vring.used->flags);
+		}
+	}
+}
+
+/* Userspace access helpers: in this case, addresses are really userspace. */
+static inline int getu16_user(u16 *val, const u16 *p)
+{
+	return get_user(*val, (__force u16 __user *)p);
+}
+
+static inline int putu16_user(u16 *p, u16 val)
+{
+	return put_user(val, (__force u16 __user *)p);
+}
+
+static inline int copydesc_user(void *dst, const void *src, size_t len)
+{
+	return copy_from_user(dst, (__force void __user *)src, len) ?
+		-EFAULT : 0;
+}
+
+static inline int putused_user(struct vring_used_elem *dst,
+			       const struct vring_used_elem *src,
+			       unsigned int num)
+{
+	return copy_to_user((__force void __user *)dst, src,
+			    sizeof(*dst) * num) ? -EFAULT : 0;
+}
+
+static inline int xfer_from_user(void *src, void *dst, size_t len)
+{
+	return copy_from_user(dst, (__force void __user *)src, len) ?
+		-EFAULT : 0;
+}
+
+static inline int xfer_to_user(void *dst, void *src, size_t len)
+{
+	return copy_to_user((__force void __user *)dst, src, len) ?
+		-EFAULT : 0;
+}
+
+/**
+ * vringh_init_user - initialize a vringh for a userspace vring.
+ * @vrh: the vringh to initialize.
+ * @features: the feature bits for this ring.
+ * @num: the number of elements.
+ * @weak_barriers: true if we only need memory barriers, not I/O.
+ * @desc: the userpace descriptor pointer.
+ * @avail: the userpace avail pointer.
+ * @used: the userpace used pointer.
+ *
+ * Returns an error if num is invalid: you should check pointers
+ * yourself!
+ */
+int vringh_init_user(struct vringh *vrh, u32 features,
+		     unsigned int num, bool weak_barriers,
+		     struct vring_desc __user *desc,
+		     struct vring_avail __user *avail,
+		     struct vring_used __user *used)
+{
+	/* Sane power of 2 please! */
+	if (!num || num > 0xffff || (num & (num - 1))) {
+		vringh_bad("Bad ring size %u", num);
+		return -EINVAL;
+	}
+
+	vrh->event_indices = (features & (1 << VIRTIO_RING_F_EVENT_IDX));
+	vrh->weak_barriers = weak_barriers;
+	vrh->completed = 0;
+	vrh->last_avail_idx = 0;
+	vrh->last_used_idx = 0;
+	vrh->vring.num = num;
+	/* vring expects kernel addresses, but only used via accessors. */
+	vrh->vring.desc = (__force struct vring_desc *)desc;
+	vrh->vring.avail = (__force struct vring_avail *)avail;
+	vrh->vring.used = (__force struct vring_used *)used;
+	return 0;
+}
+EXPORT_SYMBOL(vringh_init_user);
+
+/**
+ * vringh_getdesc_user - get next available descriptor from userspace ring.
+ * @vrh: the userspace vring.
+ * @riov: where to put the readable descriptors (or NULL)
+ * @wiov: where to put the writable descriptors (or NULL)
+ * @getrange: function to call to check ranges.
+ * @head: head index we received, for passing to vringh_complete_user().
+ *
+ * Returns 0 if there was no descriptor, 1 if there was, or -errno.
+ *
+ * Note that on error return, you can tell the difference between an
+ * invalid ring and a single invalid descriptor: in the former case,
+ * *head will be vrh->vring.num.  You may be able to ignore an invalid
+ * descriptor, but there's not much you can do with an invalid ring.
+ *
+ * Note that you may need to clean up riov and wiov, even on error!
+ */
+int vringh_getdesc_user(struct vringh *vrh,
+			struct vringh_iov *riov,
+			struct vringh_iov *wiov,
+			bool (*getrange)(struct vringh *vrh,
+					 u64 addr, struct vringh_range *r),
+			u16 *head)
+{
+	int err;
+
+	*head = vrh->vring.num;
+	err = __vringh_get_head(vrh, getu16_user, &vrh->last_avail_idx);
+	if (err < 0)
+		return err;
+
+	/* Empty... */
+	if (err == vrh->vring.num)
+		return 0;
+
+	/* We need the layouts to be the identical for this to work */
+	BUILD_BUG_ON(sizeof(struct vringh_kiov) != sizeof(struct vringh_iov));
+	BUILD_BUG_ON(offsetof(struct vringh_kiov, iov) !=
+		     offsetof(struct vringh_iov, iov));
+	BUILD_BUG_ON(offsetof(struct vringh_kiov, i) !=
+		     offsetof(struct vringh_iov, i));
+	BUILD_BUG_ON(offsetof(struct vringh_kiov, used) !=
+		     offsetof(struct vringh_iov, used));
+	BUILD_BUG_ON(offsetof(struct vringh_kiov, max_num) !=
+		     offsetof(struct vringh_iov, max_num));
+	BUILD_BUG_ON(sizeof(struct iovec) != sizeof(struct kvec));
+	BUILD_BUG_ON(offsetof(struct iovec, iov_base) !=
+		     offsetof(struct kvec, iov_base));
+	BUILD_BUG_ON(offsetof(struct iovec, iov_len) !=
+		     offsetof(struct kvec, iov_len));
+	BUILD_BUG_ON(sizeof(((struct iovec *)NULL)->iov_base)
+		     != sizeof(((struct kvec *)NULL)->iov_base));
+	BUILD_BUG_ON(sizeof(((struct iovec *)NULL)->iov_len)
+		     != sizeof(((struct kvec *)NULL)->iov_len));
+
+	*head = err;
+	err = __vringh_iov(vrh, *head, (struct vringh_kiov *)riov,
+			   (struct vringh_kiov *)wiov,
+			   range_check, getrange, GFP_KERNEL, copydesc_user);
+	if (err)
+		return err;
+
+	return 1;
+}
+EXPORT_SYMBOL(vringh_getdesc_user);
+
+/**
+ * vringh_iov_pull_user - copy bytes from vring_iov.
+ * @riov: the riov as passed to vringh_getdesc_user() (updated as we consume)
+ * @dst: the place to copy.
+ * @len: the maximum length to copy.
+ *
+ * Returns the bytes copied <= len or a negative errno.
+ */
+ssize_t vringh_iov_pull_user(struct vringh_iov *riov, void *dst, size_t len)
+{
+	return vringh_iov_xfer((struct vringh_kiov *)riov,
+			       dst, len, xfer_from_user);
+}
+EXPORT_SYMBOL(vringh_iov_pull_user);
+
+/**
+ * vringh_iov_push_user - copy bytes into vring_iov.
+ * @wiov: the wiov as passed to vringh_getdesc_user() (updated as we consume)
+ * @dst: the place to copy.
+ * @len: the maximum length to copy.
+ *
+ * Returns the bytes copied <= len or a negative errno.
+ */
+ssize_t vringh_iov_push_user(struct vringh_iov *wiov,
+			     const void *src, size_t len)
+{
+	return vringh_iov_xfer((struct vringh_kiov *)wiov,
+			       (void *)src, len, xfer_to_user);
+}
+EXPORT_SYMBOL(vringh_iov_push_user);
+
+/**
+ * vringh_abandon_user - we've decided not to handle the descriptor(s).
+ * @vrh: the vring.
+ * @num: the number of descriptors to put back (ie. num
+ *	 vringh_get_user() to undo).
+ *
+ * The next vringh_get_user() will return the old descriptor(s) again.
+ */
+void vringh_abandon_user(struct vringh *vrh, unsigned int num)
+{
+	/* We only update vring_avail_event(vr) when we want to be notified,
+	 * so we haven't changed that yet. */
+	vrh->last_avail_idx -= num;
+}
+EXPORT_SYMBOL(vringh_abandon_user);
+
+/**
+ * vringh_complete_user - we've finished with descriptor, publish it.
+ * @vrh: the vring.
+ * @head: the head as filled in by vringh_getdesc_user.
+ * @len: the length of data we have written.
+ *
+ * You should check vringh_need_notify_user() after one or more calls
+ * to this function.
+ */
+int vringh_complete_user(struct vringh *vrh, u16 head, u32 len)
+{
+	struct vring_used_elem used;
+
+	used.id = head;
+	used.len = len;
+	return __vringh_complete(vrh, &used, 1, putu16_user, putused_user);
+}
+EXPORT_SYMBOL(vringh_complete_user);
+
+/**
+ * vringh_complete_multi_user - we've finished with many descriptors.
+ * @vrh: the vring.
+ * @used: the head, length pairs.
+ * @num_used: the number of used elements.
+ *
+ * You should check vringh_need_notify_user() after one or more calls
+ * to this function.
+ */
+int vringh_complete_multi_user(struct vringh *vrh,
+			       const struct vring_used_elem used[],
+			       unsigned num_used)
+{
+	return __vringh_complete(vrh, used, num_used,
+				 putu16_user, putused_user);
+}
+EXPORT_SYMBOL(vringh_complete_multi_user);
+
+/**
+ * vringh_notify_enable_user - we want to know if something changes.
+ * @vrh: the vring.
+ *
+ * This always enables notifications, but returns false if there are
+ * now more buffers available in the vring.
+ */
+bool vringh_notify_enable_user(struct vringh *vrh)
+{
+	return __vringh_notify_enable(vrh, getu16_user, putu16_user);
+}
+EXPORT_SYMBOL(vringh_notify_enable_user);
+
+/**
+ * vringh_notify_disable_user - don't tell us if something changes.
+ * @vrh: the vring.
+ *
+ * This is our normal running state: we disable and then only enable when
+ * we're going to sleep.
+ */
+void vringh_notify_disable_user(struct vringh *vrh)
+{
+	__vringh_notify_disable(vrh, putu16_user);
+}
+EXPORT_SYMBOL(vringh_notify_disable_user);
+
+/**
+ * vringh_need_notify_user - must we tell the other side about used buffers?
+ * @vrh: the vring we've called vringh_complete_user() on.
+ *
+ * Returns -errno or 0 if we don't need to tell the other side, 1 if we do.
+ */
+int vringh_need_notify_user(struct vringh *vrh)
+{
+	return __vringh_need_notify(vrh, getu16_user);
+}
+EXPORT_SYMBOL(vringh_need_notify_user);
+
+/* Kernelspace access helpers. */
+static inline int getu16_kern(u16 *val, const u16 *p)
+{
+	*val = ACCESS_ONCE(*p);
+	return 0;
+}
+
+static inline int putu16_kern(u16 *p, u16 val)
+{
+	ACCESS_ONCE(*p) = val;
+	return 0;
+}
+
+static inline int copydesc_kern(void *dst, const void *src, size_t len)
+{
+	memcpy(dst, src, len);
+	return 0;
+}
+
+static inline int putused_kern(struct vring_used_elem *dst,
+			       const struct vring_used_elem *src,
+			       unsigned int num)
+{
+	memcpy(dst, src, num * sizeof(*dst));
+	return 0;
+}
+
+static inline int xfer_kern(void *src, void *dst, size_t len)
+{
+	memcpy(dst, src, len);
+	return 0;
+}
+
+/**
+ * vringh_init_kern - initialize a vringh for a kernelspace vring.
+ * @vrh: the vringh to initialize.
+ * @features: the feature bits for this ring.
+ * @num: the number of elements.
+ * @weak_barriers: true if we only need memory barriers, not I/O.
+ * @desc: the userpace descriptor pointer.
+ * @avail: the userpace avail pointer.
+ * @used: the userpace used pointer.
+ *
+ * Returns an error if num is invalid.
+ */
+int vringh_init_kern(struct vringh *vrh, u32 features,
+		     unsigned int num, bool weak_barriers,
+		     struct vring_desc *desc,
+		     struct vring_avail *avail,
+		     struct vring_used *used)
+{
+	/* Sane power of 2 please! */
+	if (!num || num > 0xffff || (num & (num - 1))) {
+		vringh_bad("Bad ring size %u", num);
+		return -EINVAL;
+	}
+
+	vrh->event_indices = (features & (1 << VIRTIO_RING_F_EVENT_IDX));
+	vrh->weak_barriers = weak_barriers;
+	vrh->completed = 0;
+	vrh->last_avail_idx = 0;
+	vrh->last_used_idx = 0;
+	vrh->vring.num = num;
+	vrh->vring.desc = desc;
+	vrh->vring.avail = avail;
+	vrh->vring.used = used;
+	return 0;
+}
+EXPORT_SYMBOL(vringh_init_kern);
+
+/**
+ * vringh_getdesc_kern - get next available descriptor from kernelspace ring.
+ * @vrh: the kernelspace vring.
+ * @riov: where to put the readable descriptors (or NULL)
+ * @wiov: where to put the writable descriptors (or NULL)
+ * @head: head index we received, for passing to vringh_complete_kern().
+ * @gfp: flags for allocating larger riov/wiov.
+ *
+ * Returns 0 if there was no descriptor, 1 if there was, or -errno.
+ *
+ * Note that on error return, you can tell the difference between an
+ * invalid ring and a single invalid descriptor: in the former case,
+ * *head will be vrh->vring.num.  You may be able to ignore an invalid
+ * descriptor, but there's not much you can do with an invalid ring.
+ *
+ * Note that you may need to clean up riov and wiov, even on error!
+ */
+int vringh_getdesc_kern(struct vringh *vrh,
+			struct vringh_kiov *riov,
+			struct vringh_kiov *wiov,
+			u16 *head,
+			gfp_t gfp)
+{
+	int err;
+
+	err = __vringh_get_head(vrh, getu16_kern, &vrh->last_avail_idx);
+	if (err < 0)
+		return err;
+
+	/* Empty... */
+	if (err == vrh->vring.num)
+		return 0;
+
+	*head = err;
+	err = __vringh_iov(vrh, *head, riov, wiov, no_range_check, NULL,
+			   gfp, copydesc_kern);
+	if (err)
+		return err;
+
+	return 1;
+}
+EXPORT_SYMBOL(vringh_getdesc_kern);
+
+/**
+ * vringh_iov_pull_kern - copy bytes from vring_iov.
+ * @riov: the riov as passed to vringh_getdesc_kern() (updated as we consume)
+ * @dst: the place to copy.
+ * @len: the maximum length to copy.
+ *
+ * Returns the bytes copied <= len or a negative errno.
+ */
+ssize_t vringh_iov_pull_kern(struct vringh_kiov *riov, void *dst, size_t len)
+{
+	return vringh_iov_xfer(riov, dst, len, xfer_kern);
+}
+EXPORT_SYMBOL(vringh_iov_pull_kern);
+
+/**
+ * vringh_iov_push_kern - copy bytes into vring_iov.
+ * @wiov: the wiov as passed to vringh_getdesc_kern() (updated as we consume)
+ * @dst: the place to copy.
+ * @len: the maximum length to copy.
+ *
+ * Returns the bytes copied <= len or a negative errno.
+ */
+ssize_t vringh_iov_push_kern(struct vringh_kiov *wiov,
+			     const void *src, size_t len)
+{
+	return vringh_iov_xfer(wiov, (void *)src, len, xfer_kern);
+}
+EXPORT_SYMBOL(vringh_iov_push_kern);
+
+/**
+ * vringh_abandon_kern - we've decided not to handle the descriptor(s).
+ * @vrh: the vring.
+ * @num: the number of descriptors to put back (ie. num
+ *	 vringh_get_kern() to undo).
+ *
+ * The next vringh_get_kern() will return the old descriptor(s) again.
+ */
+void vringh_abandon_kern(struct vringh *vrh, unsigned int num)
+{
+	/* We only update vring_avail_event(vr) when we want to be notified,
+	 * so we haven't changed that yet. */
+	vrh->last_avail_idx -= num;
+}
+EXPORT_SYMBOL(vringh_abandon_kern);
+
+/**
+ * vringh_complete_kern - we've finished with descriptor, publish it.
+ * @vrh: the vring.
+ * @head: the head as filled in by vringh_getdesc_kern.
+ * @len: the length of data we have written.
+ *
+ * You should check vringh_need_notify_kern() after one or more calls
+ * to this function.
+ */
+int vringh_complete_kern(struct vringh *vrh, u16 head, u32 len)
+{
+	struct vring_used_elem used;
+
+	used.id = head;
+	used.len = len;
+
+	return __vringh_complete(vrh, &used, 1, putu16_kern, putused_kern);
+}
+EXPORT_SYMBOL(vringh_complete_kern);
+
+/**
+ * vringh_notify_enable_kern - we want to know if something changes.
+ * @vrh: the vring.
+ *
+ * This always enables notifications, but returns false if there are
+ * now more buffers available in the vring.
+ */
+bool vringh_notify_enable_kern(struct vringh *vrh)
+{
+	return __vringh_notify_enable(vrh, getu16_kern, putu16_kern);
+}
+EXPORT_SYMBOL(vringh_notify_enable_kern);
+
+/**
+ * vringh_notify_disable_kern - don't tell us if something changes.
+ * @vrh: the vring.
+ *
+ * This is our normal running state: we disable and then only enable when
+ * we're going to sleep.
+ */
+void vringh_notify_disable_kern(struct vringh *vrh)
+{
+	__vringh_notify_disable(vrh, putu16_kern);
+}
+EXPORT_SYMBOL(vringh_notify_disable_kern);
+
+/**
+ * vringh_need_notify_kern - must we tell the other side about used buffers?
+ * @vrh: the vring we've called vringh_complete_kern() on.
+ *
+ * Returns -errno or 0 if we don't need to tell the other side, 1 if we do.
+ */
+int vringh_need_notify_kern(struct vringh *vrh)
+{
+	return __vringh_need_notify(vrh, getu16_kern);
+}
+EXPORT_SYMBOL(vringh_need_notify_kern);
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 4c1546f..898390c 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -212,14 +212,6 @@ config FB_SYS_FOPS
        depends on FB
        default n
 
-config FB_WMT_GE_ROPS
-	tristate
-	depends on FB
-	default n
-	---help---
-	  Include functions for accelerated rectangle filling and area
-	  copying using WonderMedia Graphics Engine operations.
-
 config FB_DEFERRED_IO
 	bool
 	depends on FB
@@ -1797,22 +1789,39 @@ config FB_AU1200
 	  option au1200fb:panel=<name>.
 
 config FB_VT8500
-	bool "VT8500 LCD Driver"
+	bool "VIA VT8500 framebuffer support"
 	depends on (FB = y) && ARM && ARCH_VT8500
-	select FB_WMT_GE_ROPS
+	select FB_SYS_FILLRECT if (!FB_WMT_GE_ROPS)
+	select FB_SYS_COPYAREA if (!FB_WMT_GE_ROPS)
 	select FB_SYS_IMAGEBLIT
+	select FB_MODE_HELPERS
+	select OF_DISPLAY_TIMING
+	select OF_VIDEOMODE
 	help
 	  This is the framebuffer driver for VIA VT8500 integrated LCD
 	  controller.
 
 config FB_WM8505
-	bool "WM8505 frame buffer support"
+	bool "Wondermedia WM8xxx-series frame buffer support"
 	depends on (FB = y) && ARM && ARCH_VT8500
-	select FB_WMT_GE_ROPS
+	select FB_SYS_FILLRECT if (!FB_WMT_GE_ROPS)
+	select FB_SYS_COPYAREA if (!FB_WMT_GE_ROPS)
 	select FB_SYS_IMAGEBLIT
+	select FB_MODE_HELPERS
+	select OF_DISPLAY_TIMING
+	select OF_VIDEOMODE
 	help
-	  This is the framebuffer driver for WonderMedia WM8505/WM8650
-	  integrated LCD controller.
+	  This is the framebuffer driver for WonderMedia WM8xxx-series
+	  integrated LCD controller. This driver covers the WM8505, WM8650
+	  and WM8850 SoCs.
+
+config FB_WMT_GE_ROPS
+	bool "VT8500/WM8xxx accelerated raster ops support"
+	depends on (FB = y) && (FB_VT8500 || FB_WM8505)
+	default n
+	help
+	  This adds support for accelerated raster operations on the
+	  VIA VT8500 and Wondermedia 85xx series SoCs.
 
 source "drivers/video/geode/Kconfig"
 
@@ -2437,6 +2446,8 @@ config FB_MXS
 	select FB_CFB_FILLRECT
 	select FB_CFB_COPYAREA
 	select FB_CFB_IMAGEBLIT
+	select FB_MODE_HELPERS
+	select OF_VIDEOMODE
 	help
 	  Framebuffer support for the MXS SoC.
 
@@ -2451,6 +2462,15 @@ config FB_PUV3_UNIGFX
 	  Choose this option if you want to use the Unigfx device as a
 	  framebuffer device. Without the support of PCI & AGP.
 
+config FB_HYPERV
+	tristate "Microsoft Hyper-V Synthetic Video support"
+	depends on FB && HYPERV
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	help
+	  This framebuffer driver supports Microsoft Hyper-V Synthetic Video.
+
 source "drivers/video/omap/Kconfig"
 source "drivers/video/omap2/Kconfig"
 source "drivers/video/exynos/Kconfig"
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 9df3873..97f7b6d 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -149,6 +149,7 @@ obj-$(CONFIG_FB_MSM)              += msm/
 obj-$(CONFIG_FB_NUC900)           += nuc900fb.o
 obj-$(CONFIG_FB_JZ4740)		  += jz4740_fb.o
 obj-$(CONFIG_FB_PUV3_UNIGFX)      += fb-puv3.o
+obj-$(CONFIG_FB_HYPERV)		  += hyperv_fb.o
 
 # Platform or fallback drivers go here
 obj-$(CONFIG_FB_UVESA)            += uvesafb.o
diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c
index 7fa1bf8..77cb4ff 100644
--- a/drivers/video/amifb.c
+++ b/drivers/video/amifb.c
@@ -3788,19 +3788,7 @@ static struct platform_driver amifb_driver = {
 	},
 };
 
-static int __init amifb_init(void)
-{
-	return platform_driver_probe(&amifb_driver, amifb_probe);
-}
-
-module_init(amifb_init);
-
-static void __exit amifb_exit(void)
-{
-	platform_driver_unregister(&amifb_driver);
-}
-
-module_exit(amifb_exit);
+module_platform_driver_probe(amifb_driver, amifb_probe);
 
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:amiga-video");
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c
index 025428e..540909d 100644
--- a/drivers/video/atmel_lcdfb.c
+++ b/drivers/video/atmel_lcdfb.c
@@ -34,6 +34,77 @@
 #define ATMEL_LCDC_DMA_BURST_LEN	8	/* words */
 #define ATMEL_LCDC_FIFO_SIZE		512	/* words */
 
+struct atmel_lcdfb_config {
+	bool have_alt_pixclock;
+	bool have_hozval;
+	bool have_intensity_bit;
+};
+
+static struct atmel_lcdfb_config at91sam9261_config = {
+	.have_hozval		= true,
+	.have_intensity_bit	= true,
+};
+
+static struct atmel_lcdfb_config at91sam9263_config = {
+	.have_intensity_bit	= true,
+};
+
+static struct atmel_lcdfb_config at91sam9g10_config = {
+	.have_hozval		= true,
+};
+
+static struct atmel_lcdfb_config at91sam9g45_config = {
+	.have_alt_pixclock	= true,
+};
+
+static struct atmel_lcdfb_config at91sam9g45es_config = {
+};
+
+static struct atmel_lcdfb_config at91sam9rl_config = {
+	.have_intensity_bit	= true,
+};
+
+static struct atmel_lcdfb_config at32ap_config = {
+	.have_hozval		= true,
+};
+
+static const struct platform_device_id atmel_lcdfb_devtypes[] = {
+	{
+		.name = "at91sam9261-lcdfb",
+		.driver_data = (unsigned long)&at91sam9261_config,
+	}, {
+		.name = "at91sam9263-lcdfb",
+		.driver_data = (unsigned long)&at91sam9263_config,
+	}, {
+		.name = "at91sam9g10-lcdfb",
+		.driver_data = (unsigned long)&at91sam9g10_config,
+	}, {
+		.name = "at91sam9g45-lcdfb",
+		.driver_data = (unsigned long)&at91sam9g45_config,
+	}, {
+		.name = "at91sam9g45es-lcdfb",
+		.driver_data = (unsigned long)&at91sam9g45es_config,
+	}, {
+		.name = "at91sam9rl-lcdfb",
+		.driver_data = (unsigned long)&at91sam9rl_config,
+	}, {
+		.name = "at32ap-lcdfb",
+		.driver_data = (unsigned long)&at32ap_config,
+	}, {
+		/* terminator */
+	}
+};
+
+static struct atmel_lcdfb_config *
+atmel_lcdfb_get_config(struct platform_device *pdev)
+{
+	unsigned long data;
+
+	data = platform_get_device_id(pdev)->driver_data;
+
+	return (struct atmel_lcdfb_config *)data;
+}
+
 #if defined(CONFIG_ARCH_AT91)
 #define	ATMEL_LCDFB_FBINFO_DEFAULT	(FBINFO_DEFAULT \
 					 | FBINFO_PARTIAL_PAN_OK \
@@ -193,14 +264,16 @@ static struct fb_fix_screeninfo atmel_lcdfb_fix __initdata = {
 	.accel		= FB_ACCEL_NONE,
 };
 
-static unsigned long compute_hozval(unsigned long xres, unsigned long lcdcon2)
+static unsigned long compute_hozval(struct atmel_lcdfb_info *sinfo,
+							unsigned long xres)
 {
+	unsigned long lcdcon2;
 	unsigned long value;
 
-	if (!(cpu_is_at91sam9261() || cpu_is_at91sam9g10()
-		|| cpu_is_at32ap7000()))
+	if (!sinfo->config->have_hozval)
 		return xres;
 
+	lcdcon2 = lcdc_readl(sinfo, ATMEL_LCDC_LCDCON2);
 	value = xres;
 	if ((lcdcon2 & ATMEL_LCDC_DISTYPE) != ATMEL_LCDC_DISTYPE_TFT) {
 		/* STN display */
@@ -423,7 +496,7 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var,
 		break;
 	case 16:
 		/* Older SOCs use IBGR:555 rather than BGR:565. */
-		if (sinfo->have_intensity_bit)
+		if (sinfo->config->have_intensity_bit)
 			var->green.length = 5;
 		else
 			var->green.length = 6;
@@ -531,7 +604,7 @@ static int atmel_lcdfb_set_par(struct fb_info *info)
 	/* Now, the LCDC core... */
 
 	/* Set pixel clock */
-	if (cpu_is_at91sam9g45() && !cpu_is_at91sam9g45es())
+	if (sinfo->config->have_alt_pixclock)
 		pix_factor = 1;
 
 	clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000;
@@ -591,8 +664,7 @@ static int atmel_lcdfb_set_par(struct fb_info *info)
 	lcdc_writel(sinfo, ATMEL_LCDC_TIM2, value);
 
 	/* Horizontal value (aka line size) */
-	hozval_linesz = compute_hozval(info->var.xres,
-					lcdc_readl(sinfo, ATMEL_LCDC_LCDCON2));
+	hozval_linesz = compute_hozval(sinfo, info->var.xres);
 
 	/* Display size */
 	value = (hozval_linesz - 1) << ATMEL_LCDC_HOZVAL_OFFSET;
@@ -684,7 +756,7 @@ static int atmel_lcdfb_setcolreg(unsigned int regno, unsigned int red,
 
 	case FB_VISUAL_PSEUDOCOLOR:
 		if (regno < 256) {
-			if (sinfo->have_intensity_bit) {
+			if (sinfo->config->have_intensity_bit) {
 				/* old style I+BGR:555 */
 				val  = ((red   >> 11) & 0x001f);
 				val |= ((green >>  6) & 0x03e0);
@@ -821,15 +893,13 @@ static int __init atmel_lcdfb_init_fbinfo(struct atmel_lcdfb_info *sinfo)
 
 static void atmel_lcdfb_start_clock(struct atmel_lcdfb_info *sinfo)
 {
-	if (sinfo->bus_clk)
-		clk_enable(sinfo->bus_clk);
+	clk_enable(sinfo->bus_clk);
 	clk_enable(sinfo->lcdc_clk);
 }
 
 static void atmel_lcdfb_stop_clock(struct atmel_lcdfb_info *sinfo)
 {
-	if (sinfo->bus_clk)
-		clk_disable(sinfo->bus_clk);
+	clk_disable(sinfo->bus_clk);
 	clk_disable(sinfo->lcdc_clk);
 }
 
@@ -874,10 +944,9 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
 	}
 	sinfo->info = info;
 	sinfo->pdev = pdev;
-	if (cpu_is_at91sam9261() || cpu_is_at91sam9263() ||
-							cpu_is_at91sam9rl()) {
-		sinfo->have_intensity_bit = true;
-	}
+	sinfo->config = atmel_lcdfb_get_config(pdev);
+	if (!sinfo->config)
+		goto free_info;
 
 	strcpy(info->fix.id, sinfo->pdev->name);
 	info->flags = ATMEL_LCDFB_FBINFO_DEFAULT;
@@ -888,13 +957,10 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
 	info->fix = atmel_lcdfb_fix;
 
 	/* Enable LCDC Clocks */
-	if (cpu_is_at91sam9261() || cpu_is_at91sam9g10()
-	 || cpu_is_at32ap7000()) {
-		sinfo->bus_clk = clk_get(dev, "hck1");
-		if (IS_ERR(sinfo->bus_clk)) {
-			ret = PTR_ERR(sinfo->bus_clk);
-			goto free_info;
-		}
+	sinfo->bus_clk = clk_get(dev, "hclk");
+	if (IS_ERR(sinfo->bus_clk)) {
+		ret = PTR_ERR(sinfo->bus_clk);
+		goto free_info;
 	}
 	sinfo->lcdc_clk = clk_get(dev, "lcdc_clk");
 	if (IS_ERR(sinfo->lcdc_clk)) {
@@ -1055,8 +1121,7 @@ stop_clk:
 	atmel_lcdfb_stop_clock(sinfo);
 	clk_put(sinfo->lcdc_clk);
 put_bus_clk:
-	if (sinfo->bus_clk)
-		clk_put(sinfo->bus_clk);
+	clk_put(sinfo->bus_clk);
 free_info:
 	framebuffer_release(info);
 out:
@@ -1081,8 +1146,7 @@ static int __exit atmel_lcdfb_remove(struct platform_device *pdev)
 	unregister_framebuffer(info);
 	atmel_lcdfb_stop_clock(sinfo);
 	clk_put(sinfo->lcdc_clk);
-	if (sinfo->bus_clk)
-		clk_put(sinfo->bus_clk);
+	clk_put(sinfo->bus_clk);
 	fb_dealloc_cmap(&info->cmap);
 	free_irq(sinfo->irq_base, info);
 	iounmap(sinfo->mmio);
@@ -1151,25 +1215,14 @@ static struct platform_driver atmel_lcdfb_driver = {
 	.remove		= __exit_p(atmel_lcdfb_remove),
 	.suspend	= atmel_lcdfb_suspend,
 	.resume		= atmel_lcdfb_resume,
-
+	.id_table	= atmel_lcdfb_devtypes,
 	.driver		= {
 		.name	= "atmel_lcdfb",
 		.owner	= THIS_MODULE,
 	},
 };
 
-static int __init atmel_lcdfb_init(void)
-{
-	return platform_driver_probe(&atmel_lcdfb_driver, atmel_lcdfb_probe);
-}
-
-static void __exit atmel_lcdfb_exit(void)
-{
-	platform_driver_unregister(&atmel_lcdfb_driver);
-}
-
-module_init(atmel_lcdfb_init);
-module_exit(atmel_lcdfb_exit);
+module_platform_driver_probe(atmel_lcdfb_driver, atmel_lcdfb_probe);
 
 MODULE_DESCRIPTION("AT91/AT32 LCD Controller framebuffer driver");
 MODULE_AUTHOR("Nicolas Ferre <nicolas.ferre@atmel.com>");
diff --git a/drivers/video/auo_k1900fb.c b/drivers/video/auo_k1900fb.c
index 1a9ac6e..f5b668e 100644
--- a/drivers/video/auo_k1900fb.c
+++ b/drivers/video/auo_k1900fb.c
@@ -60,9 +60,12 @@
 
 static void auok1900_init(struct auok190xfb_par *par)
 {
+	struct device *dev = par->info->device;
 	struct auok190x_board *board = par->board;
 	u16 init_param = 0;
 
+	pm_runtime_get_sync(dev);
+
 	init_param |= AUOK1900_INIT_TEMP_AVERAGE;
 	init_param |= AUOK1900_INIT_ROTATE(par->rotation);
 	init_param |= AUOK190X_INIT_INVERSE_WHITE;
@@ -74,6 +77,9 @@ static void auok1900_init(struct auok190xfb_par *par)
 
 	/* let the controller finish */
 	board->wait_for_rdy(par);
+
+	pm_runtime_mark_last_busy(dev);
+	pm_runtime_put_autosuspend(dev);
 }
 
 static void auok1900_update_region(struct auok190xfb_par *par, int mode,
@@ -82,6 +88,7 @@ static void auok1900_update_region(struct auok190xfb_par *par, int mode,
 	struct device *dev = par->info->device;
 	unsigned char *buf = (unsigned char *)par->info->screen_base;
 	int xres = par->info->var.xres;
+	int line_length = par->info->fix.line_length;
 	u16 args[4];
 
 	pm_runtime_get_sync(dev);
@@ -100,9 +107,9 @@ static void auok1900_update_region(struct auok190xfb_par *par, int mode,
 	args[1] = y1 + 1;
 	args[2] = xres;
 	args[3] = y2 - y1;
-	buf += y1 * xres;
+	buf += y1 * line_length;
 	auok190x_send_cmdargs_pixels(par, AUOK1900_CMD_PARTIALDISP, 4, args,
-				     ((y2 - y1) * xres)/2, (u16 *) buf);
+				     ((y2 - y1) * line_length)/2, (u16 *) buf);
 	auok190x_send_command(par, AUOK190X_CMD_DATA_STOP);
 
 	par->update_cnt++;
diff --git a/drivers/video/auo_k1901fb.c b/drivers/video/auo_k1901fb.c
index d1db165..12b9adc 100644
--- a/drivers/video/auo_k1901fb.c
+++ b/drivers/video/auo_k1901fb.c
@@ -101,9 +101,12 @@
 
 static void auok1901_init(struct auok190xfb_par *par)
 {
+	struct device *dev = par->info->device;
 	struct auok190x_board *board = par->board;
 	u16 init_param = 0;
 
+	pm_runtime_get_sync(dev);
+
 	init_param |= AUOK190X_INIT_INVERSE_WHITE;
 	init_param |= AUOK190X_INIT_FORMAT0;
 	init_param |= AUOK1901_INIT_RESOLUTION(par->resolution);
@@ -113,6 +116,9 @@ static void auok1901_init(struct auok190xfb_par *par)
 
 	/* let the controller finish */
 	board->wait_for_rdy(par);
+
+	pm_runtime_mark_last_busy(dev);
+	pm_runtime_put_autosuspend(dev);
 }
 
 static void auok1901_update_region(struct auok190xfb_par *par, int mode,
@@ -121,6 +127,7 @@ static void auok1901_update_region(struct auok190xfb_par *par, int mode,
 	struct device *dev = par->info->device;
 	unsigned char *buf = (unsigned char *)par->info->screen_base;
 	int xres = par->info->var.xres;
+	int line_length = par->info->fix.line_length;
 	u16 args[5];
 
 	pm_runtime_get_sync(dev);
@@ -139,9 +146,9 @@ static void auok1901_update_region(struct auok190xfb_par *par, int mode,
 	args[1] = y1 + 1;
 	args[2] = xres;
 	args[3] = y2 - y1;
-	buf += y1 * xres;
+	buf += y1 * line_length;
 	auok190x_send_cmdargs_pixels_nowait(par, AUOK1901_CMD_DMA_START, 4,
-					    args, ((y2 - y1) * xres)/2,
+					    args, ((y2 - y1) * line_length)/2,
 					    (u16 *) buf);
 	auok190x_send_command_nowait(par, AUOK190X_CMD_DATA_STOP);
 
diff --git a/drivers/video/auo_k190x.c b/drivers/video/auo_k190x.c
index 53846cb..b1f19b2 100644
--- a/drivers/video/auo_k190x.c
+++ b/drivers/video/auo_k190x.c
@@ -40,6 +40,14 @@ static struct panel_info panel_table[] = {
 		.w = 1024,
 		.h = 768,
 	},
+	[AUOK190X_RESOLUTION_600_800] = {
+		.w = 600,
+		.h = 800,
+	},
+	[AUOK190X_RESOLUTION_768_1024] = {
+		.w = 768,
+		.h = 1024,
+	},
 };
 
 /*
@@ -60,8 +68,48 @@ static void auok190x_issue_cmd(struct auok190xfb_par *par, u16 data)
 	par->board->set_ctl(par, AUOK190X_I80_DC, 1);
 }
 
-static int auok190x_issue_pixels(struct auok190xfb_par *par, int size,
-				 u16 *data)
+/**
+ * Conversion of 16bit color to 4bit grayscale
+ * does roughly (0.3 * R + 0.6 G + 0.1 B) / 2
+ */
+static inline int rgb565_to_gray4(u16 data, struct fb_var_screeninfo *var)
+{
+	return ((((data & 0xF800) >> var->red.offset) * 77 +
+		 ((data & 0x07E0) >> (var->green.offset + 1)) * 151 +
+		 ((data & 0x1F) >> var->blue.offset) * 28) >> 8 >> 1);
+}
+
+static int auok190x_issue_pixels_rgb565(struct auok190xfb_par *par, int size,
+					u16 *data)
+{
+	struct fb_var_screeninfo *var = &par->info->var;
+	struct device *dev = par->info->device;
+	int i;
+	u16 tmp;
+
+	if (size & 7) {
+		dev_err(dev, "issue_pixels: size %d must be a multiple of 8\n",
+			size);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < (size >> 2); i++) {
+		par->board->set_ctl(par, AUOK190X_I80_WR, 0);
+
+		tmp  = (rgb565_to_gray4(data[4*i], var) & 0x000F);
+		tmp |= (rgb565_to_gray4(data[4*i+1], var) << 4) & 0x00F0;
+		tmp |= (rgb565_to_gray4(data[4*i+2], var) << 8) & 0x0F00;
+		tmp |= (rgb565_to_gray4(data[4*i+3], var) << 12) & 0xF000;
+
+		par->board->set_hdb(par, tmp);
+		par->board->set_ctl(par, AUOK190X_I80_WR, 1);
+	}
+
+	return 0;
+}
+
+static int auok190x_issue_pixels_gray8(struct auok190xfb_par *par, int size,
+				       u16 *data)
 {
 	struct device *dev = par->info->device;
 	int i;
@@ -91,6 +139,23 @@ static int auok190x_issue_pixels(struct auok190xfb_par *par, int size,
 	return 0;
 }
 
+static int auok190x_issue_pixels(struct auok190xfb_par *par, int size,
+				 u16 *data)
+{
+	struct fb_info *info = par->info;
+	struct device *dev = par->info->device;
+
+	if (info->var.bits_per_pixel == 8 && info->var.grayscale)
+		auok190x_issue_pixels_gray8(par, size, data);
+	else if (info->var.bits_per_pixel == 16)
+		auok190x_issue_pixels_rgb565(par, size, data);
+	else
+		dev_err(dev, "unsupported color mode (bits: %d, gray: %d)\n",
+			info->var.bits_per_pixel, info->var.grayscale);
+
+	return 0;
+}
+
 static u16 auok190x_read_data(struct auok190xfb_par *par)
 {
 	u16 data;
@@ -224,8 +289,8 @@ static void auok190xfb_dpy_deferred_io(struct fb_info *info,
 {
 	struct fb_deferred_io *fbdefio = info->fbdefio;
 	struct auok190xfb_par *par = info->par;
+	u16 line_length = info->fix.line_length;
 	u16 yres = info->var.yres;
-	u16 xres = info->var.xres;
 	u16 y1 = 0, h = 0;
 	int prev_index = -1;
 	struct page *cur;
@@ -254,7 +319,7 @@ static void auok190xfb_dpy_deferred_io(struct fb_info *info,
 	}
 
 	/* height increment is fixed per page */
-	h_inc = DIV_ROUND_UP(PAGE_SIZE , xres);
+	h_inc = DIV_ROUND_UP(PAGE_SIZE , line_length);
 
 	/* calculate number of pages from pixel height */
 	threshold = par->consecutive_threshold / h_inc;
@@ -265,7 +330,7 @@ static void auok190xfb_dpy_deferred_io(struct fb_info *info,
 	list_for_each_entry(cur, &fbdefio->pagelist, lru) {
 		if (prev_index < 0) {
 			/* just starting so assign first page */
-			y1 = (cur->index << PAGE_SHIFT) / xres;
+			y1 = (cur->index << PAGE_SHIFT) / line_length;
 			h = h_inc;
 		} else if ((cur->index - prev_index) <= threshold) {
 			/* page is within our threshold for single updates */
@@ -275,7 +340,7 @@ static void auok190xfb_dpy_deferred_io(struct fb_info *info,
 			par->update_partial(par, y1, y1 + h);
 
 			/* start over with our non consecutive page */
-			y1 = (cur->index << PAGE_SHIFT) / xres;
+			y1 = (cur->index << PAGE_SHIFT) / line_length;
 			h = h_inc;
 		}
 		prev_index = cur->index;
@@ -376,27 +441,127 @@ static void auok190xfb_imageblit(struct fb_info *info,
 static int auok190xfb_check_var(struct fb_var_screeninfo *var,
 				   struct fb_info *info)
 {
-	if (info->var.xres != var->xres || info->var.yres != var->yres ||
-	    info->var.xres_virtual != var->xres_virtual ||
-	    info->var.yres_virtual != var->yres_virtual) {
-		pr_info("%s: Resolution not supported: X%u x Y%u\n",
-			 __func__, var->xres, var->yres);
+	struct device *dev = info->device;
+	struct auok190xfb_par *par = info->par;
+	struct panel_info *panel = &panel_table[par->resolution];
+	int size;
+
+	/*
+	 * Color depth
+	 */
+
+	if (var->bits_per_pixel == 8 && var->grayscale == 1) {
+		/*
+		 * For 8-bit grayscale, R, G, and B offset are equal.
+		 */
+		var->red.length = 8;
+		var->red.offset = 0;
+		var->red.msb_right = 0;
+
+		var->green.length = 8;
+		var->green.offset = 0;
+		var->green.msb_right = 0;
+
+		var->blue.length = 8;
+		var->blue.offset = 0;
+		var->blue.msb_right = 0;
+
+		var->transp.length = 0;
+		var->transp.offset = 0;
+		var->transp.msb_right = 0;
+	} else if (var->bits_per_pixel == 16) {
+		var->red.length = 5;
+		var->red.offset = 11;
+		var->red.msb_right = 0;
+
+		var->green.length = 6;
+		var->green.offset = 5;
+		var->green.msb_right = 0;
+
+		var->blue.length = 5;
+		var->blue.offset = 0;
+		var->blue.msb_right = 0;
+
+		var->transp.length = 0;
+		var->transp.offset = 0;
+		var->transp.msb_right = 0;
+	} else {
+		dev_warn(dev, "unsupported color mode (bits: %d, grayscale: %d)\n",
+			info->var.bits_per_pixel, info->var.grayscale);
 		return -EINVAL;
 	}
 
 	/*
+	 * Dimensions
+	 */
+
+	switch (var->rotate) {
+	case FB_ROTATE_UR:
+	case FB_ROTATE_UD:
+		var->xres = panel->w;
+		var->yres = panel->h;
+		break;
+	case FB_ROTATE_CW:
+	case FB_ROTATE_CCW:
+		var->xres = panel->h;
+		var->yres = panel->w;
+		break;
+	default:
+		dev_dbg(dev, "Invalid rotation request\n");
+		return -EINVAL;
+	}
+
+	var->xres_virtual = var->xres;
+	var->yres_virtual = var->yres;
+
+	/*
 	 *  Memory limit
 	 */
 
-	if ((info->fix.line_length * var->yres_virtual) > info->fix.smem_len) {
-		pr_info("%s: Memory Limit requested yres_virtual = %u\n",
-			 __func__, var->yres_virtual);
+	size = var->xres_virtual * var->yres_virtual * var->bits_per_pixel / 8;
+	if (size > info->fix.smem_len) {
+		dev_err(dev, "Memory limit exceeded, requested %dK\n",
+			size >> 10);
 		return -ENOMEM;
 	}
 
 	return 0;
 }
 
+static int auok190xfb_set_fix(struct fb_info *info)
+{
+	struct fb_fix_screeninfo *fix = &info->fix;
+	struct fb_var_screeninfo *var = &info->var;
+
+	fix->line_length = var->xres_virtual * var->bits_per_pixel / 8;
+
+	fix->type = FB_TYPE_PACKED_PIXELS;
+	fix->accel = FB_ACCEL_NONE;
+	fix->visual = (var->grayscale) ? FB_VISUAL_STATIC_PSEUDOCOLOR
+				       : FB_VISUAL_TRUECOLOR;
+	fix->xpanstep = 0;
+	fix->ypanstep = 0;
+	fix->ywrapstep = 0;
+
+	return 0;
+}
+
+static int auok190xfb_set_par(struct fb_info *info)
+{
+	struct auok190xfb_par *par = info->par;
+
+	par->rotation = info->var.rotate;
+	auok190xfb_set_fix(info);
+
+	/* reinit the controller to honor the rotation */
+	par->init(par);
+
+	/* wait for init to complete */
+	par->board->wait_for_rdy(par);
+
+	return 0;
+}
+
 static struct fb_ops auok190xfb_ops = {
 	.owner		= THIS_MODULE,
 	.fb_read	= fb_sys_read,
@@ -405,6 +570,7 @@ static struct fb_ops auok190xfb_ops = {
 	.fb_copyarea	= auok190xfb_copyarea,
 	.fb_imageblit	= auok190xfb_imageblit,
 	.fb_check_var	= auok190xfb_check_var,
+	.fb_set_par     = auok190xfb_set_par,
 };
 
 /*
@@ -588,10 +754,16 @@ static int auok190x_power(struct auok190xfb_par *par, bool on)
 
 static void auok190x_recover(struct auok190xfb_par *par)
 {
+	struct device *dev = par->info->device;
+
 	auok190x_power(par, 0);
 	msleep(100);
 	auok190x_power(par, 1);
 
+	/* after powercycling the device, it's always active */
+	pm_runtime_set_active(dev);
+	par->standby = 0;
+
 	par->init(par);
 
 	/* wait for init to complete */
@@ -875,42 +1047,17 @@ int auok190x_common_probe(struct platform_device *pdev,
 	/* initialise fix, var, resolution and rotation */
 
 	strlcpy(info->fix.id, init->id, 16);
-	info->fix.type = FB_TYPE_PACKED_PIXELS;
-	info->fix.visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
-	info->fix.xpanstep = 0;
-	info->fix.ypanstep = 0;
-	info->fix.ywrapstep = 0;
-	info->fix.accel = FB_ACCEL_NONE;
-
 	info->var.bits_per_pixel = 8;
 	info->var.grayscale = 1;
-	info->var.red.length = 8;
-	info->var.green.length = 8;
-	info->var.blue.length = 8;
 
 	panel = &panel_table[board->resolution];
 
-	/* if 90 degree rotation, switch width and height */
-	if (board->rotation & 1) {
-		info->var.xres = panel->h;
-		info->var.yres = panel->w;
-		info->var.xres_virtual = panel->h;
-		info->var.yres_virtual = panel->w;
-		info->fix.line_length = panel->h;
-	} else {
-		info->var.xres = panel->w;
-		info->var.yres = panel->h;
-		info->var.xres_virtual = panel->w;
-		info->var.yres_virtual = panel->h;
-		info->fix.line_length = panel->w;
-	}
-
 	par->resolution = board->resolution;
-	par->rotation = board->rotation;
+	par->rotation = 0;
 
 	/* videomemory handling */
 
-	videomemorysize = roundup((panel->w * panel->h), PAGE_SIZE);
+	videomemorysize = roundup((panel->w * panel->h) * 2, PAGE_SIZE);
 	videomemory = vmalloc(videomemorysize);
 	if (!videomemory) {
 		ret = -ENOMEM;
@@ -924,6 +1071,12 @@ int auok190x_common_probe(struct platform_device *pdev,
 	info->flags = FBINFO_FLAG_DEFAULT | FBINFO_VIRTFB;
 	info->fbops = &auok190xfb_ops;
 
+	ret = auok190xfb_check_var(&info->var, info);
+	if (ret)
+		goto err_defio;
+
+	auok190xfb_set_fix(info);
+
 	/* deferred io init */
 
 	info->fbdefio = devm_kzalloc(info->device,
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
index db10d01..2e166c3 100644
--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -59,6 +59,13 @@ config LCD_LTV350QV
 
 	  The LTV350QV panel is present on all ATSTK1000 boards.
 
+config LCD_ILI922X
+	tristate "ILI Technology ILI9221/ILI9222 support"
+	depends on SPI
+	help
+	  If you have a panel based on the ILI9221/9222 controller
+	  chip then say y to include a driver for it.
+
 config LCD_ILI9320
 	tristate "ILI Technology ILI9320 controller support"
 	depends on SPI
@@ -161,7 +168,7 @@ if BACKLIGHT_CLASS_DEVICE
 config BACKLIGHT_ATMEL_LCDC
 	bool "Atmel LCDC Contrast-as-Backlight control"
 	depends on FB_ATMEL
-	default y if MACH_SAM9261EK || MACH_SAM9G10EK || MACH_SAM9263EK
+	default y if MACH_AT91SAM9261EK || MACH_AT91SAM9G10EK || MACH_AT91SAM9263EK
 	help
 	  This provides a backlight control internal to the Atmel LCDC
 	  driver.  If the LCD "contrast control" on your board is wired
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
index 96c4d62..92711fe 100644
--- a/drivers/video/backlight/Makefile
+++ b/drivers/video/backlight/Makefile
@@ -5,6 +5,7 @@ obj-$(CONFIG_LCD_CLASS_DEVICE)		+= lcd.o
 obj-$(CONFIG_LCD_CORGI)			+= corgi_lcd.o
 obj-$(CONFIG_LCD_HP700)			+= jornada720_lcd.o
 obj-$(CONFIG_LCD_HX8357)		+= hx8357.o
+obj-$(CONFIG_LCD_ILI922X)		+= ili922x.o
 obj-$(CONFIG_LCD_ILI9320)		+= ili9320.o
 obj-$(CONFIG_LCD_L4F00242T03)		+= l4f00242t03.o
 obj-$(CONFIG_LCD_LD9040)		+= ld9040.o
diff --git a/drivers/video/backlight/adp5520_bl.c b/drivers/video/backlight/adp5520_bl.c
index a1e41d4..c84701b 100644
--- a/drivers/video/backlight/adp5520_bl.c
+++ b/drivers/video/backlight/adp5520_bl.c
@@ -143,13 +143,16 @@ static int adp5520_bl_setup(struct backlight_device *bl)
 static ssize_t adp5520_show(struct device *dev, char *buf, int reg)
 {
 	struct adp5520_bl *data = dev_get_drvdata(dev);
-	int error;
+	int ret;
 	uint8_t reg_val;
 
 	mutex_lock(&data->lock);
-	error = adp5520_read(data->master, reg, &reg_val);
+	ret = adp5520_read(data->master, reg, &reg_val);
 	mutex_unlock(&data->lock);
 
+	if (ret < 0)
+		return ret;
+
 	return sprintf(buf, "%u\n", reg_val);
 }
 
@@ -349,35 +352,34 @@ static int adp5520_bl_remove(struct platform_device *pdev)
 	return 0;
 }
 
-#ifdef CONFIG_PM
-static int adp5520_bl_suspend(struct platform_device *pdev,
-				 pm_message_t state)
+#ifdef CONFIG_PM_SLEEP
+static int adp5520_bl_suspend(struct device *dev)
 {
-	struct backlight_device *bl = platform_get_drvdata(pdev);
+	struct backlight_device *bl = dev_get_drvdata(dev);
+
 	return adp5520_bl_set(bl, 0);
 }
 
-static int adp5520_bl_resume(struct platform_device *pdev)
+static int adp5520_bl_resume(struct device *dev)
 {
-	struct backlight_device *bl = platform_get_drvdata(pdev);
+	struct backlight_device *bl = dev_get_drvdata(dev);
 
 	backlight_update_status(bl);
 	return 0;
 }
-#else
-#define adp5520_bl_suspend	NULL
-#define adp5520_bl_resume	NULL
 #endif
 
+static SIMPLE_DEV_PM_OPS(adp5520_bl_pm_ops, adp5520_bl_suspend,
+			adp5520_bl_resume);
+
 static struct platform_driver adp5520_bl_driver = {
 	.driver		= {
 		.name	= "adp5520-backlight",
 		.owner	= THIS_MODULE,
+		.pm	= &adp5520_bl_pm_ops,
 	},
 	.probe		= adp5520_bl_probe,
 	.remove		= adp5520_bl_remove,
-	.suspend	= adp5520_bl_suspend,
-	.resume		= adp5520_bl_resume,
 };
 
 module_platform_driver(adp5520_bl_driver);
diff --git a/drivers/video/backlight/adp8860_bl.c b/drivers/video/backlight/adp8860_bl.c
index a77c9ca..75b10f8 100644
--- a/drivers/video/backlight/adp8860_bl.c
+++ b/drivers/video/backlight/adp8860_bl.c
@@ -249,12 +249,14 @@ static int adp8860_led_probe(struct i2c_client *client)
 		if (led_dat->id > 7 || led_dat->id < 1) {
 			dev_err(&client->dev, "Invalid LED ID %d\n",
 				led_dat->id);
+			ret = -EINVAL;
 			goto err;
 		}
 
 		if (pdata->bl_led_assign & (1 << (led_dat->id - 1))) {
 			dev_err(&client->dev, "LED %d used by Backlight\n",
 				led_dat->id);
+			ret = -EBUSY;
 			goto err;
 		}
 
@@ -773,25 +775,29 @@ static int adp8860_remove(struct i2c_client *client)
 	return 0;
 }
 
-#ifdef CONFIG_PM
-static int adp8860_i2c_suspend(struct i2c_client *client, pm_message_t message)
+#ifdef CONFIG_PM_SLEEP
+static int adp8860_i2c_suspend(struct device *dev)
 {
+	struct i2c_client *client = to_i2c_client(dev);
+
 	adp8860_clr_bits(client, ADP8860_MDCR, NSTBY);
 
 	return 0;
 }
 
-static int adp8860_i2c_resume(struct i2c_client *client)
+static int adp8860_i2c_resume(struct device *dev)
 {
+	struct i2c_client *client = to_i2c_client(dev);
+
 	adp8860_set_bits(client, ADP8860_MDCR, NSTBY | BLEN);
 
 	return 0;
 }
-#else
-#define adp8860_i2c_suspend NULL
-#define adp8860_i2c_resume NULL
 #endif
 
+static SIMPLE_DEV_PM_OPS(adp8860_i2c_pm_ops, adp8860_i2c_suspend,
+			adp8860_i2c_resume);
+
 static const struct i2c_device_id adp8860_id[] = {
 	{ "adp8860", adp8860 },
 	{ "adp8861", adp8861 },
@@ -802,12 +808,11 @@ MODULE_DEVICE_TABLE(i2c, adp8860_id);
 
 static struct i2c_driver adp8860_driver = {
 	.driver = {
-		.name = KBUILD_MODNAME,
+		.name	= KBUILD_MODNAME,
+		.pm	= &adp8860_i2c_pm_ops,
 	},
 	.probe    = adp8860_probe,
 	.remove   = adp8860_remove,
-	.suspend = adp8860_i2c_suspend,
-	.resume  = adp8860_i2c_resume,
 	.id_table = adp8860_id,
 };
 
diff --git a/drivers/video/backlight/adp8870_bl.c b/drivers/video/backlight/adp8870_bl.c
index 712c25a..90049d7 100644
--- a/drivers/video/backlight/adp8870_bl.c
+++ b/drivers/video/backlight/adp8870_bl.c
@@ -274,12 +274,14 @@ static int adp8870_led_probe(struct i2c_client *client)
 		if (led_dat->id > 7 || led_dat->id < 1) {
 			dev_err(&client->dev, "Invalid LED ID %d\n",
 				led_dat->id);
+			ret = -EINVAL;
 			goto err;
 		}
 
 		if (pdata->bl_led_assign & (1 << (led_dat->id - 1))) {
 			dev_err(&client->dev, "LED %d used by Backlight\n",
 				led_dat->id);
+			ret = -EBUSY;
 			goto err;
 		}
 
@@ -895,13 +897,13 @@ static int adp8870_probe(struct i2c_client *client,
 
 	data->bl = bl;
 
-	if (pdata->en_ambl_sens)
+	if (pdata->en_ambl_sens) {
 		ret = sysfs_create_group(&bl->dev.kobj,
 			&adp8870_bl_attr_group);
-
-	if (ret) {
-		dev_err(&client->dev, "failed to register sysfs\n");
-		goto out1;
+		if (ret) {
+			dev_err(&client->dev, "failed to register sysfs\n");
+			goto out1;
+		}
 	}
 
 	ret = adp8870_bl_setup(bl);
@@ -947,25 +949,29 @@ static int adp8870_remove(struct i2c_client *client)
 	return 0;
 }
 
-#ifdef CONFIG_PM
-static int adp8870_i2c_suspend(struct i2c_client *client, pm_message_t message)
+#ifdef CONFIG_PM_SLEEP
+static int adp8870_i2c_suspend(struct device *dev)
 {
+	struct i2c_client *client = to_i2c_client(dev);
+
 	adp8870_clr_bits(client, ADP8870_MDCR, NSTBY);
 
 	return 0;
 }
 
-static int adp8870_i2c_resume(struct i2c_client *client)
+static int adp8870_i2c_resume(struct device *dev)
 {
+	struct i2c_client *client = to_i2c_client(dev);
+
 	adp8870_set_bits(client, ADP8870_MDCR, NSTBY | BLEN);
 
 	return 0;
 }
-#else
-#define adp8870_i2c_suspend NULL
-#define adp8870_i2c_resume NULL
 #endif
 
+static SIMPLE_DEV_PM_OPS(adp8870_i2c_pm_ops, adp8870_i2c_suspend,
+			adp8870_i2c_resume);
+
 static const struct i2c_device_id adp8870_id[] = {
 	{ "adp8870", 0 },
 	{ }
@@ -974,12 +980,11 @@ MODULE_DEVICE_TABLE(i2c, adp8870_id);
 
 static struct i2c_driver adp8870_driver = {
 	.driver = {
-		.name = KBUILD_MODNAME,
+		.name	= KBUILD_MODNAME,
+		.pm	= &adp8870_i2c_pm_ops,
 	},
 	.probe    = adp8870_probe,
 	.remove   = adp8870_remove,
-	.suspend = adp8870_i2c_suspend,
-	.resume  = adp8870_i2c_resume,
 	.id_table = adp8870_id,
 };
 
diff --git a/drivers/video/backlight/ams369fg06.c b/drivers/video/backlight/ams369fg06.c
index c02aa2c..319fef6 100644
--- a/drivers/video/backlight/ams369fg06.c
+++ b/drivers/video/backlight/ams369fg06.c
@@ -533,12 +533,12 @@ static int ams369fg06_remove(struct spi_device *spi)
 	return 0;
 }
 
-#if defined(CONFIG_PM)
-static int ams369fg06_suspend(struct spi_device *spi, pm_message_t mesg)
+#ifdef CONFIG_PM_SLEEP
+static int ams369fg06_suspend(struct device *dev)
 {
-	struct ams369fg06 *lcd = spi_get_drvdata(spi);
+	struct ams369fg06 *lcd = dev_get_drvdata(dev);
 
-	dev_dbg(&spi->dev, "lcd->power = %d\n", lcd->power);
+	dev_dbg(dev, "lcd->power = %d\n", lcd->power);
 
 	/*
 	 * when lcd panel is suspend, lcd panel becomes off
@@ -547,19 +547,19 @@ static int ams369fg06_suspend(struct spi_device *spi, pm_message_t mesg)
 	return ams369fg06_power(lcd, FB_BLANK_POWERDOWN);
 }
 
-static int ams369fg06_resume(struct spi_device *spi)
+static int ams369fg06_resume(struct device *dev)
 {
-	struct ams369fg06 *lcd = spi_get_drvdata(spi);
+	struct ams369fg06 *lcd = dev_get_drvdata(dev);
 
 	lcd->power = FB_BLANK_POWERDOWN;
 
 	return ams369fg06_power(lcd, FB_BLANK_UNBLANK);
 }
-#else
-#define ams369fg06_suspend	NULL
-#define ams369fg06_resume	NULL
 #endif
 
+static SIMPLE_DEV_PM_OPS(ams369fg06_pm_ops, ams369fg06_suspend,
+			ams369fg06_resume);
+
 static void ams369fg06_shutdown(struct spi_device *spi)
 {
 	struct ams369fg06 *lcd = spi_get_drvdata(spi);
@@ -571,12 +571,11 @@ static struct spi_driver ams369fg06_driver = {
 	.driver = {
 		.name	= "ams369fg06",
 		.owner	= THIS_MODULE,
+		.pm	= &ams369fg06_pm_ops,
 	},
 	.probe		= ams369fg06_probe,
 	.remove		= ams369fg06_remove,
 	.shutdown	= ams369fg06_shutdown,
-	.suspend	= ams369fg06_suspend,
-	.resume		= ams369fg06_resume,
 };
 
 module_spi_driver(ams369fg06_driver);
diff --git a/drivers/video/backlight/as3711_bl.c b/drivers/video/backlight/as3711_bl.c
index 41d52fe..123887c 100644
--- a/drivers/video/backlight/as3711_bl.c
+++ b/drivers/video/backlight/as3711_bl.c
@@ -258,6 +258,109 @@ static int as3711_bl_register(struct platform_device *pdev,
 	return 0;
 }
 
+static int as3711_backlight_parse_dt(struct device *dev)
+{
+	struct as3711_bl_pdata *pdata = dev_get_platdata(dev);
+	struct device_node *bl =
+		of_find_node_by_name(dev->parent->of_node, "backlight"), *fb;
+	int ret;
+
+	if (!bl) {
+		dev_dbg(dev, "backlight node not found\n");
+		return -ENODEV;
+	}
+
+	fb = of_parse_phandle(bl, "su1-dev", 0);
+	if (fb) {
+		pdata->su1_fb = fb->full_name;
+
+		ret = of_property_read_u32(bl, "su1-max-uA", &pdata->su1_max_uA);
+		if (pdata->su1_max_uA <= 0)
+			ret = -EINVAL;
+		if (ret < 0)
+			return ret;
+	}
+
+	fb = of_parse_phandle(bl, "su2-dev", 0);
+	if (fb) {
+		int count = 0;
+
+		pdata->su2_fb = fb->full_name;
+
+		ret = of_property_read_u32(bl, "su2-max-uA", &pdata->su2_max_uA);
+		if (pdata->su2_max_uA <= 0)
+			ret = -EINVAL;
+		if (ret < 0)
+			return ret;
+
+		if (of_find_property(bl, "su2-feedback-voltage", NULL)) {
+			pdata->su2_feedback = AS3711_SU2_VOLTAGE;
+			count++;
+		}
+		if (of_find_property(bl, "su2-feedback-curr1", NULL)) {
+			pdata->su2_feedback = AS3711_SU2_CURR1;
+			count++;
+		}
+		if (of_find_property(bl, "su2-feedback-curr2", NULL)) {
+			pdata->su2_feedback = AS3711_SU2_CURR2;
+			count++;
+		}
+		if (of_find_property(bl, "su2-feedback-curr3", NULL)) {
+			pdata->su2_feedback = AS3711_SU2_CURR3;
+			count++;
+		}
+		if (of_find_property(bl, "su2-feedback-curr-auto", NULL)) {
+			pdata->su2_feedback = AS3711_SU2_CURR_AUTO;
+			count++;
+		}
+		if (count != 1)
+			return -EINVAL;
+
+		count = 0;
+		if (of_find_property(bl, "su2-fbprot-lx-sd4", NULL)) {
+			pdata->su2_fbprot = AS3711_SU2_LX_SD4;
+			count++;
+		}
+		if (of_find_property(bl, "su2-fbprot-gpio2", NULL)) {
+			pdata->su2_fbprot = AS3711_SU2_GPIO2;
+			count++;
+		}
+		if (of_find_property(bl, "su2-fbprot-gpio3", NULL)) {
+			pdata->su2_fbprot = AS3711_SU2_GPIO3;
+			count++;
+		}
+		if (of_find_property(bl, "su2-fbprot-gpio4", NULL)) {
+			pdata->su2_fbprot = AS3711_SU2_GPIO4;
+			count++;
+		}
+		if (count != 1)
+			return -EINVAL;
+
+		count = 0;
+		if (of_find_property(bl, "su2-auto-curr1", NULL)) {
+			pdata->su2_auto_curr1 = true;
+			count++;
+		}
+		if (of_find_property(bl, "su2-auto-curr2", NULL)) {
+			pdata->su2_auto_curr2 = true;
+			count++;
+		}
+		if (of_find_property(bl, "su2-auto-curr3", NULL)) {
+			pdata->su2_auto_curr3 = true;
+			count++;
+		}
+
+		/*
+		 * At least one su2-auto-curr* must be specified iff
+		 * AS3711_SU2_CURR_AUTO is used
+		 */
+		if (!count ^ (pdata->su2_feedback != AS3711_SU2_CURR_AUTO))
+			return -EINVAL;
+	}
+
+	return 0;
+}
+
 static int as3711_backlight_probe(struct platform_device *pdev)
 {
 	struct as3711_bl_pdata *pdata = dev_get_platdata(&pdev->dev);
@@ -267,11 +370,24 @@ static int as3711_backlight_probe(struct platform_device *pdev)
 	unsigned int max_brightness;
 	int ret;
 
-	if (!pdata || (!pdata->su1_fb && !pdata->su2_fb)) {
+	if (!pdata) {
 		dev_err(&pdev->dev, "No platform data, exiting...\n");
 		return -ENODEV;
 	}
 
+	if (pdev->dev.parent->of_node) {
+		ret = as3711_backlight_parse_dt(&pdev->dev);
+		if (ret < 0) {
+			dev_err(&pdev->dev, "DT parsing failed: %d\n", ret);
+			return ret;
+		}
+	}
+
+	if (!pdata->su1_fb && !pdata->su2_fb) {
+		dev_err(&pdev->dev, "No framebuffer specified\n");
+		return -EINVAL;
+	}
+
 	/*
 	 * Due to possible hardware damage I chose to block all modes,
 	 * unsupported on my hardware. Anyone, wishing to use any of those modes
diff --git a/drivers/video/backlight/atmel-pwm-bl.c b/drivers/video/backlight/atmel-pwm-bl.c
index de5e5e7..a60d6af 100644
--- a/drivers/video/backlight/atmel-pwm-bl.c
+++ b/drivers/video/backlight/atmel-pwm-bl.c
@@ -118,7 +118,7 @@ static const struct backlight_ops atmel_pwm_bl_ops = {
 	.update_status  = atmel_pwm_bl_set_intensity,
 };
 
-static int atmel_pwm_bl_probe(struct platform_device *pdev)
+static int __init atmel_pwm_bl_probe(struct platform_device *pdev)
 {
 	struct backlight_properties props;
 	const struct atmel_pwm_bl_platform_data *pdata;
@@ -225,17 +225,7 @@ static struct platform_driver atmel_pwm_bl_driver = {
 	.remove = __exit_p(atmel_pwm_bl_remove),
 };
 
-static int __init atmel_pwm_bl_init(void)
-{
-	return platform_driver_probe(&atmel_pwm_bl_driver, atmel_pwm_bl_probe);
-}
-module_init(atmel_pwm_bl_init);
-
-static void __exit atmel_pwm_bl_exit(void)
-{
-	platform_driver_unregister(&atmel_pwm_bl_driver);
-}
-module_exit(atmel_pwm_bl_exit);
+module_platform_driver_probe(atmel_pwm_bl_driver, atmel_pwm_bl_probe);
 
 MODULE_AUTHOR("Hans-Christian egtvedt <hans-christian.egtvedt@atmel.com>");
 MODULE_DESCRIPTION("Atmel PWM backlight driver");
diff --git a/drivers/video/backlight/corgi_lcd.c b/drivers/video/backlight/corgi_lcd.c
index aa782f3..c97867a 100644
--- a/drivers/video/backlight/corgi_lcd.c
+++ b/drivers/video/backlight/corgi_lcd.c
@@ -457,10 +457,10 @@ static const struct backlight_ops corgi_bl_ops = {
 	.update_status  = corgi_bl_update_status,
 };
 
-#ifdef CONFIG_PM
-static int corgi_lcd_suspend(struct spi_device *spi, pm_message_t state)
+#ifdef CONFIG_PM_SLEEP
+static int corgi_lcd_suspend(struct device *dev)
 {
-	struct corgi_lcd *lcd = spi_get_drvdata(spi);
+	struct corgi_lcd *lcd = dev_get_drvdata(dev);
 
 	corgibl_flags |= CORGIBL_SUSPENDED;
 	corgi_bl_set_intensity(lcd, 0);
@@ -468,20 +468,19 @@ static int corgi_lcd_suspend(struct spi_device *spi, pm_message_t state)
 	return 0;
 }
 
-static int corgi_lcd_resume(struct spi_device *spi)
+static int corgi_lcd_resume(struct device *dev)
 {
-	struct corgi_lcd *lcd = spi_get_drvdata(spi);
+	struct corgi_lcd *lcd = dev_get_drvdata(dev);
 
 	corgibl_flags &= ~CORGIBL_SUSPENDED;
 	corgi_lcd_set_power(lcd->lcd_dev, FB_BLANK_UNBLANK);
 	backlight_update_status(lcd->bl_dev);
 	return 0;
 }
-#else
-#define corgi_lcd_suspend	NULL
-#define corgi_lcd_resume	NULL
 #endif
 
+static SIMPLE_DEV_PM_OPS(corgi_lcd_pm_ops, corgi_lcd_suspend, corgi_lcd_resume);
+
 static int setup_gpio_backlight(struct corgi_lcd *lcd,
 				struct corgi_lcd_platform_data *pdata)
 {
@@ -611,11 +610,10 @@ static struct spi_driver corgi_lcd_driver = {
 	.driver		= {
 		.name	= "corgi-lcd",
 		.owner	= THIS_MODULE,
+		.pm	= &corgi_lcd_pm_ops,
 	},
 	.probe		= corgi_lcd_probe,
 	.remove		= corgi_lcd_remove,
-	.suspend	= corgi_lcd_suspend,
-	.resume		= corgi_lcd_resume,
 };
 
 module_spi_driver(corgi_lcd_driver);
diff --git a/drivers/video/backlight/da903x_bl.c b/drivers/video/backlight/da903x_bl.c
index 8179cef..67cadd3 100644
--- a/drivers/video/backlight/da903x_bl.c
+++ b/drivers/video/backlight/da903x_bl.c
@@ -88,16 +88,21 @@ static int da903x_backlight_update_status(struct backlight_device *bl)
 	if (bl->props.fb_blank != FB_BLANK_UNBLANK)
 		brightness = 0;
 
+	if (bl->props.state & BL_CORE_SUSPENDED)
+		brightness = 0;
+
 	return da903x_backlight_set(bl, brightness);
 }
 
 static int da903x_backlight_get_brightness(struct backlight_device *bl)
 {
 	struct da903x_backlight_data *data = bl_get_data(bl);
+
 	return data->current_brightness;
 }
 
 static const struct backlight_ops da903x_backlight_ops = {
+	.options	= BL_CORE_SUSPENDRESUME,
 	.update_status	= da903x_backlight_update_status,
 	.get_brightness	= da903x_backlight_get_brightness,
 };
@@ -161,35 +166,10 @@ static int da903x_backlight_remove(struct platform_device *pdev)
 	return 0;
 }
 
-#ifdef CONFIG_PM
-static int da903x_backlight_suspend(struct device *dev)
-{
-	struct backlight_device *bl = dev_get_drvdata(dev);
-
-	return da903x_backlight_set(bl, 0);
-}
-
-static int da903x_backlight_resume(struct device *dev)
-{
-	struct backlight_device *bl = dev_get_drvdata(dev);
-
-	backlight_update_status(bl);
-	return 0;
-}
-
-static const struct dev_pm_ops da903x_backlight_pm_ops = {
-	.suspend	= da903x_backlight_suspend,
-	.resume		= da903x_backlight_resume,
-};
-#endif
-
 static struct platform_driver da903x_backlight_driver = {
 	.driver		= {
 		.name	= "da903x-backlight",
 		.owner	= THIS_MODULE,
-#ifdef CONFIG_PM
-		.pm	= &da903x_backlight_pm_ops,
-#endif
 	},
 	.probe		= da903x_backlight_probe,
 	.remove		= da903x_backlight_remove,
diff --git a/drivers/video/backlight/ep93xx_bl.c b/drivers/video/backlight/ep93xx_bl.c
index ef3e21e..3345582 100644
--- a/drivers/video/backlight/ep93xx_bl.c
+++ b/drivers/video/backlight/ep93xx_bl.c
@@ -60,7 +60,7 @@ static const struct backlight_ops ep93xxbl_ops = {
 	.get_brightness	= ep93xxbl_get_brightness,
 };
 
-static int __init ep93xxbl_probe(struct platform_device *dev)
+static int ep93xxbl_probe(struct platform_device *dev)
 {
 	struct ep93xxbl *ep93xxbl;
 	struct backlight_device *bl;
@@ -115,35 +115,33 @@ static int ep93xxbl_remove(struct platform_device *dev)
 	return 0;
 }
 
-#ifdef CONFIG_PM
-static int ep93xxbl_suspend(struct platform_device *dev, pm_message_t state)
+#ifdef CONFIG_PM_SLEEP
+static int ep93xxbl_suspend(struct device *dev)
 {
-	struct backlight_device *bl = platform_get_drvdata(dev);
+	struct backlight_device *bl = dev_get_drvdata(dev);
 
 	return ep93xxbl_set(bl, 0);
 }
 
-static int ep93xxbl_resume(struct platform_device *dev)
+static int ep93xxbl_resume(struct device *dev)
 {
-	struct backlight_device *bl = platform_get_drvdata(dev);
+	struct backlight_device *bl = dev_get_drvdata(dev);
 
 	backlight_update_status(bl);
 	return 0;
 }
-#else
-#define ep93xxbl_suspend	NULL
-#define ep93xxbl_resume		NULL
 #endif
 
+static SIMPLE_DEV_PM_OPS(ep93xxbl_pm_ops, ep93xxbl_suspend, ep93xxbl_resume);
+
 static struct platform_driver ep93xxbl_driver = {
 	.driver		= {
 		.name	= "ep93xx-bl",
 		.owner	= THIS_MODULE,
+		.pm	= &ep93xxbl_pm_ops,
 	},
 	.probe		= ep93xxbl_probe,
 	.remove		= ep93xxbl_remove,
-	.suspend	= ep93xxbl_suspend,
-	.resume		= ep93xxbl_resume,
 };
 
 module_platform_driver(ep93xxbl_driver);
diff --git a/drivers/video/backlight/generic_bl.c b/drivers/video/backlight/generic_bl.c
index 0ae155b..19e393b 100644
--- a/drivers/video/backlight/generic_bl.c
+++ b/drivers/video/backlight/generic_bl.c
@@ -9,8 +9,6 @@
  *
  */
 
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -108,7 +106,7 @@ static int genericbl_probe(struct platform_device *pdev)
 
 	generic_backlight_device = bd;
 
-	pr_info("Generic Backlight Driver Initialized.\n");
+	dev_info(&pdev->dev, "Generic Backlight Driver Initialized.\n");
 	return 0;
 }
 
@@ -122,7 +120,7 @@ static int genericbl_remove(struct platform_device *pdev)
 
 	backlight_device_unregister(bd);
 
-	pr_info("Generic Backlight Driver Unloaded\n");
+	dev_info(&pdev->dev, "Generic Backlight Driver Unloaded\n");
 	return 0;
 }
 
diff --git a/drivers/video/backlight/hp680_bl.c b/drivers/video/backlight/hp680_bl.c
index 5cefd73..00076ec 100644
--- a/drivers/video/backlight/hp680_bl.c
+++ b/drivers/video/backlight/hp680_bl.c
@@ -64,29 +64,28 @@ static void hp680bl_send_intensity(struct backlight_device *bd)
 }
 
 
-#ifdef CONFIG_PM
-static int hp680bl_suspend(struct platform_device *pdev, pm_message_t state)
+#ifdef CONFIG_PM_SLEEP
+static int hp680bl_suspend(struct device *dev)
 {
-	struct backlight_device *bd = platform_get_drvdata(pdev);
+	struct backlight_device *bd = dev_get_drvdata(dev);
 
 	hp680bl_suspended = 1;
 	hp680bl_send_intensity(bd);
 	return 0;
 }
 
-static int hp680bl_resume(struct platform_device *pdev)
+static int hp680bl_resume(struct device *dev)
 {
-	struct backlight_device *bd = platform_get_drvdata(pdev);
+	struct backlight_device *bd = dev_get_drvdata(dev);
 
 	hp680bl_suspended = 0;
 	hp680bl_send_intensity(bd);
 	return 0;
 }
-#else
-#define hp680bl_suspend	NULL
-#define hp680bl_resume	NULL
 #endif
 
+static SIMPLE_DEV_PM_OPS(hp680bl_pm_ops, hp680bl_suspend, hp680bl_resume);
+
 static int hp680bl_set_intensity(struct backlight_device *bd)
 {
 	hp680bl_send_intensity(bd);
@@ -140,10 +139,9 @@ static int hp680bl_remove(struct platform_device *pdev)
 static struct platform_driver hp680bl_driver = {
 	.probe		= hp680bl_probe,
 	.remove		= hp680bl_remove,
-	.suspend	= hp680bl_suspend,
-	.resume		= hp680bl_resume,
 	.driver		= {
 		.name	= "hp680-bl",
+		.pm	= &hp680bl_pm_ops,
 	},
 };
 
diff --git a/drivers/video/backlight/ili922x.c b/drivers/video/backlight/ili922x.c
new file mode 100644
index 0000000..8b8465e
--- /dev/null
+++ b/drivers/video/backlight/ili922x.c
@@ -0,0 +1,555 @@
+/*
+ * (C) Copyright 2008
+ * Stefano Babic, DENX Software Engineering, sbabic@denx.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 driver implements a lcd device for the ILITEK 922x display
+ * controller. The interface to the display is SPI and the display's
+ * memory is cyclically updated over the RGB interface.
+ */
+
+#include <linux/fb.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/lcd.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+#include <linux/spi/spi.h>
+#include <linux/string.h>
+
+/* Register offset, see manual section 8.2 */
+#define REG_START_OSCILLATION			0x00
+#define REG_DRIVER_CODE_READ			0x00
+#define REG_DRIVER_OUTPUT_CONTROL		0x01
+#define REG_LCD_AC_DRIVEING_CONTROL		0x02
+#define REG_ENTRY_MODE				0x03
+#define REG_COMPARE_1				0x04
+#define REG_COMPARE_2				0x05
+#define REG_DISPLAY_CONTROL_1			0x07
+#define REG_DISPLAY_CONTROL_2			0x08
+#define REG_DISPLAY_CONTROL_3			0x09
+#define REG_FRAME_CYCLE_CONTROL			0x0B
+#define REG_EXT_INTF_CONTROL			0x0C
+#define REG_POWER_CONTROL_1			0x10
+#define REG_POWER_CONTROL_2			0x11
+#define REG_POWER_CONTROL_3			0x12
+#define REG_POWER_CONTROL_4			0x13
+#define REG_RAM_ADDRESS_SET			0x21
+#define REG_WRITE_DATA_TO_GRAM			0x22
+#define REG_RAM_WRITE_MASK1			0x23
+#define REG_RAM_WRITE_MASK2			0x24
+#define REG_GAMMA_CONTROL_1			0x30
+#define REG_GAMMA_CONTROL_2			0x31
+#define REG_GAMMA_CONTROL_3			0x32
+#define REG_GAMMA_CONTROL_4			0x33
+#define REG_GAMMA_CONTROL_5			0x34
+#define REG_GAMMA_CONTROL_6			0x35
+#define REG_GAMMA_CONTROL_7			0x36
+#define REG_GAMMA_CONTROL_8			0x37
+#define REG_GAMMA_CONTROL_9			0x38
+#define REG_GAMMA_CONTROL_10			0x39
+#define REG_GATE_SCAN_CONTROL			0x40
+#define REG_VERT_SCROLL_CONTROL			0x41
+#define REG_FIRST_SCREEN_DRIVE_POS		0x42
+#define REG_SECOND_SCREEN_DRIVE_POS		0x43
+#define REG_RAM_ADDR_POS_H			0x44
+#define REG_RAM_ADDR_POS_V			0x45
+#define REG_OSCILLATOR_CONTROL			0x4F
+#define REG_GPIO				0x60
+#define REG_OTP_VCM_PROGRAMMING			0x61
+#define REG_OTP_VCM_STATUS_ENABLE		0x62
+#define REG_OTP_PROGRAMMING_ID_KEY		0x65
+
+/*
+ * maximum frequency for register access
+ * (not for the GRAM access)
+ */
+#define ILITEK_MAX_FREQ_REG	4000000
+
+/*
+ * Device ID as found in the datasheet (supports 9221 and 9222)
+ */
+#define ILITEK_DEVICE_ID	0x9220
+#define ILITEK_DEVICE_ID_MASK	0xFFF0
+
+/* Last two bits in the START BYTE */
+#define START_RS_INDEX		0
+#define START_RS_REG		1
+#define START_RW_WRITE		0
+#define START_RW_READ		1
+
+/**
+ * START_BYTE(id, rs, rw)
+ *
+ * Set the start byte according to the required operation.
+ * The start byte is defined as:
+ *   ----------------------------------
+ *  | 0 | 1 | 1 | 1 | 0 | ID | RS | RW |
+ *   ----------------------------------
+ * @id: display's id as set by the manufacturer
+ * @rs: operation type bit, one of:
+ *	  - START_RS_INDEX	set the index register
+ *	  - START_RS_REG	write/read registers/GRAM
+ * @rw: read/write operation
+ *	 - START_RW_WRITE	write
+ *	 - START_RW_READ	read
+ */
+#define START_BYTE(id, rs, rw)	\
+	(0x70 | (((id) & 0x01) << 2) | (((rs) & 0x01) << 1) | ((rw) & 0x01))
+
+/**
+ * CHECK_FREQ_REG(spi_device s, spi_transfer x) - Check the frequency
+ *	for the SPI transfer. According to the datasheet, the controller
+ *	accept higher frequency for the GRAM transfer, but it requires
+ *	lower frequency when the registers are read/written.
+ *	The macro sets the frequency in the spi_transfer structure if
+ *	the frequency exceeds the maximum value.
+ */
+#define CHECK_FREQ_REG(s, x)	\
+	do {			\
+		if (s->max_speed_hz > ILITEK_MAX_FREQ_REG)	\
+			((struct spi_transfer *)x)->speed_hz =	\
+					ILITEK_MAX_FREQ_REG;	\
+	} while (0)
+
+#define CMD_BUFSIZE		16
+
+#define POWER_IS_ON(pwr)	((pwr) <= FB_BLANK_NORMAL)
+
+#define set_tx_byte(b)		(tx_invert ? ~(b) : b)
+
+/**
+ * ili922x_id - id as set by manufacturer
+ */
+static int ili922x_id = 1;
+module_param(ili922x_id, int, 0);
+
+static int tx_invert;
+module_param(tx_invert, int, 0);
+
+/**
+ * driver's private structure
+ */
+struct ili922x {
+	struct spi_device *spi;
+	struct lcd_device *ld;
+	int power;
+};
+
+/**
+ * ili922x_read_status - read status register from display
+ * @spi: spi device
+ * @rs:  output value
+ */
+static int ili922x_read_status(struct spi_device *spi, u16 *rs)
+{
+	struct spi_message msg;
+	struct spi_transfer xfer;
+	unsigned char tbuf[CMD_BUFSIZE];
+	unsigned char rbuf[CMD_BUFSIZE];
+	int ret, i;
+
+	memset(&xfer, 0, sizeof(struct spi_transfer));
+	spi_message_init(&msg);
+	xfer.tx_buf = tbuf;
+	xfer.rx_buf = rbuf;
+	xfer.cs_change = 1;
+	CHECK_FREQ_REG(spi, &xfer);
+
+	tbuf[0] = set_tx_byte(START_BYTE(ili922x_id, START_RS_INDEX,
+					 START_RW_READ));
+	/*
+	 * we need 4-byte xfer here due to invalid dummy byte
+	 * received after start byte
+	 */
+	for (i = 1; i < 4; i++)
+		tbuf[i] = set_tx_byte(0);	/* dummy */
+
+	xfer.bits_per_word = 8;
+	xfer.len = 4;
+	spi_message_add_tail(&xfer, &msg);
+	ret = spi_sync(spi, &msg);
+	if (ret < 0) {
+		dev_dbg(&spi->dev, "Error sending SPI message 0x%x", ret);
+		return ret;
+	}
+
+	*rs = (rbuf[2] << 8) + rbuf[3];
+	return 0;
+}
+
+/**
+ * ili922x_read - read register from display
+ * @spi: spi device
+ * @reg: offset of the register to be read
+ * @rx:  output value
+ */
+static int ili922x_read(struct spi_device *spi, u8 reg, u16 *rx)
+{
+	struct spi_message msg;
+	struct spi_transfer xfer_regindex, xfer_regvalue;
+	unsigned char tbuf[CMD_BUFSIZE];
+	unsigned char rbuf[CMD_BUFSIZE];
+	int ret, len = 0, send_bytes;
+
+	memset(&xfer_regindex, 0, sizeof(struct spi_transfer));
+	memset(&xfer_regvalue, 0, sizeof(struct spi_transfer));
+	spi_message_init(&msg);
+	xfer_regindex.tx_buf = tbuf;
+	xfer_regindex.rx_buf = rbuf;
+	xfer_regindex.cs_change = 1;
+	CHECK_FREQ_REG(spi, &xfer_regindex);
+
+	tbuf[0] = set_tx_byte(START_BYTE(ili922x_id, START_RS_INDEX,
+					 START_RW_WRITE));
+	tbuf[1] = set_tx_byte(0);
+	tbuf[2] = set_tx_byte(reg);
+	xfer_regindex.bits_per_word = 8;
+	len = xfer_regindex.len = 3;
+	spi_message_add_tail(&xfer_regindex, &msg);
+
+	send_bytes = len;
+
+	tbuf[len++] = set_tx_byte(START_BYTE(ili922x_id, START_RS_REG,
+					     START_RW_READ));
+	tbuf[len++] = set_tx_byte(0);
+	tbuf[len] = set_tx_byte(0);
+
+	xfer_regvalue.cs_change = 1;
+	xfer_regvalue.len = 3;
+	xfer_regvalue.tx_buf = &tbuf[send_bytes];
+	xfer_regvalue.rx_buf = &rbuf[send_bytes];
+	CHECK_FREQ_REG(spi, &xfer_regvalue);
+
+	spi_message_add_tail(&xfer_regvalue, &msg);
+	ret = spi_sync(spi, &msg);
+	if (ret < 0) {
+		dev_dbg(&spi->dev, "Error sending SPI message 0x%x", ret);
+		return ret;
+	}
+
+	*rx = (rbuf[1 + send_bytes] << 8) + rbuf[2 + send_bytes];
+	return 0;
+}
+
+/**
+ * ili922x_write - write a controller register
+ * @spi: struct spi_device *
+ * @reg: offset of the register to be written
+ * @value: value to be written
+ */
+static int ili922x_write(struct spi_device *spi, u8 reg, u16 value)
+{
+	struct spi_message msg;
+	struct spi_transfer xfer_regindex, xfer_regvalue;
+	unsigned char tbuf[CMD_BUFSIZE];
+	unsigned char rbuf[CMD_BUFSIZE];
+	int ret, len = 0;
+
+	memset(&xfer_regindex, 0, sizeof(struct spi_transfer));
+	memset(&xfer_regvalue, 0, sizeof(struct spi_transfer));
+
+	spi_message_init(&msg);
+	xfer_regindex.tx_buf = tbuf;
+	xfer_regindex.rx_buf = rbuf;
+	xfer_regindex.cs_change = 1;
+	CHECK_FREQ_REG(spi, &xfer_regindex);
+
+	tbuf[0] = set_tx_byte(START_BYTE(ili922x_id, START_RS_INDEX,
+					 START_RW_WRITE));
+	tbuf[1] = set_tx_byte(0);
+	tbuf[2] = set_tx_byte(reg);
+	xfer_regindex.bits_per_word = 8;
+	xfer_regindex.len = 3;
+	spi_message_add_tail(&xfer_regindex, &msg);
+
+	ret = spi_sync(spi, &msg);
+
+	spi_message_init(&msg);
+	len = 0;
+	tbuf[0] = set_tx_byte(START_BYTE(ili922x_id, START_RS_REG,
+					 START_RW_WRITE));
+	tbuf[1] = set_tx_byte((value & 0xFF00) >> 8);
+	tbuf[2] = set_tx_byte(value & 0x00FF);
+
+	xfer_regvalue.cs_change = 1;
+	xfer_regvalue.len = 3;
+	xfer_regvalue.tx_buf = tbuf;
+	xfer_regvalue.rx_buf = rbuf;
+	CHECK_FREQ_REG(spi, &xfer_regvalue);
+
+	spi_message_add_tail(&xfer_regvalue, &msg);
+
+	ret = spi_sync(spi, &msg);
+	if (ret < 0) {
+		dev_err(&spi->dev, "Error sending SPI message 0x%x", ret);
+		return ret;
+	}
+	return 0;
+}
+
+#ifdef DEBUG
+/**
+ * ili922x_reg_dump - dump all registers
+ */
+static void ili922x_reg_dump(struct spi_device *spi)
+{
+	u8 reg;
+	u16 rx;
+
+	dev_dbg(&spi->dev, "ILI922x configuration registers:\n");
+	for (reg = REG_START_OSCILLATION;
+	     reg <= REG_OTP_PROGRAMMING_ID_KEY; reg++) {
+		ili922x_read(spi, reg, &rx);
+		dev_dbg(&spi->dev, "reg @ 0x%02X: 0x%04X\n", reg, rx);
+	}
+}
+#else
+static inline void ili922x_reg_dump(struct spi_device *spi) {}
+#endif
+
+/**
+ * set_write_to_gram_reg - initialize the display to write the GRAM
+ * @spi: spi device
+ */
+static void set_write_to_gram_reg(struct spi_device *spi)
+{
+	struct spi_message msg;
+	struct spi_transfer xfer;
+	unsigned char tbuf[CMD_BUFSIZE];
+
+	memset(&xfer, 0, sizeof(struct spi_transfer));
+
+	spi_message_init(&msg);
+	xfer.tx_buf = tbuf;
+	xfer.rx_buf = NULL;
+	xfer.cs_change = 1;
+
+	tbuf[0] = START_BYTE(ili922x_id, START_RS_INDEX, START_RW_WRITE);
+	tbuf[1] = 0;
+	tbuf[2] = REG_WRITE_DATA_TO_GRAM;
+
+	xfer.bits_per_word = 8;
+	xfer.len = 3;
+	spi_message_add_tail(&xfer, &msg);
+	spi_sync(spi, &msg);
+}
+
+/**
+ * ili922x_poweron - turn the display on
+ * @spi: spi device
+ *
+ * The sequence to turn on the display is taken from
+ * the datasheet and/or the example code provided by the
+ * manufacturer.
+ */
+static int ili922x_poweron(struct spi_device *spi)
+{
+	int ret;
+
+	/* Power on */
+	ret = ili922x_write(spi, REG_POWER_CONTROL_1, 0x0000);
+	usleep_range(10000, 10500);
+	ret += ili922x_write(spi, REG_POWER_CONTROL_2, 0x0000);
+	ret += ili922x_write(spi, REG_POWER_CONTROL_3, 0x0000);
+	msleep(40);
+	ret += ili922x_write(spi, REG_POWER_CONTROL_4, 0x0000);
+	msleep(40);
+	/* register 0x56 is not documented in the datasheet */
+	ret += ili922x_write(spi, 0x56, 0x080F);
+	ret += ili922x_write(spi, REG_POWER_CONTROL_1, 0x4240);
+	usleep_range(10000, 10500);
+	ret += ili922x_write(spi, REG_POWER_CONTROL_2, 0x0000);
+	ret += ili922x_write(spi, REG_POWER_CONTROL_3, 0x0014);
+	msleep(40);
+	ret += ili922x_write(spi, REG_POWER_CONTROL_4, 0x1319);
+	msleep(40);
+
+	return ret;
+}
+
+/**
+ * ili922x_poweroff - turn the display off
+ * @spi: spi device
+ */
+static int ili922x_poweroff(struct spi_device *spi)
+{
+	int ret;
+
+	/* Power off */
+	ret = ili922x_write(spi, REG_POWER_CONTROL_1, 0x0000);
+	usleep_range(10000, 10500);
+	ret += ili922x_write(spi, REG_POWER_CONTROL_2, 0x0000);
+	ret += ili922x_write(spi, REG_POWER_CONTROL_3, 0x0000);
+	msleep(40);
+	ret += ili922x_write(spi, REG_POWER_CONTROL_4, 0x0000);
+	msleep(40);
+
+	return ret;
+}
+
+/**
+ * ili922x_display_init - initialize the display by setting
+ *			  the configuration registers
+ * @spi: spi device
+ */
+static void ili922x_display_init(struct spi_device *spi)
+{
+	ili922x_write(spi, REG_START_OSCILLATION, 1);
+	usleep_range(10000, 10500);
+	ili922x_write(spi, REG_DRIVER_OUTPUT_CONTROL, 0x691B);
+	ili922x_write(spi, REG_LCD_AC_DRIVEING_CONTROL, 0x0700);
+	ili922x_write(spi, REG_ENTRY_MODE, 0x1030);
+	ili922x_write(spi, REG_COMPARE_1, 0x0000);
+	ili922x_write(spi, REG_COMPARE_2, 0x0000);
+	ili922x_write(spi, REG_DISPLAY_CONTROL_1, 0x0037);
+	ili922x_write(spi, REG_DISPLAY_CONTROL_2, 0x0202);
+	ili922x_write(spi, REG_DISPLAY_CONTROL_3, 0x0000);
+	ili922x_write(spi, REG_FRAME_CYCLE_CONTROL, 0x0000);
+
+	/* Set RGB interface */
+	ili922x_write(spi, REG_EXT_INTF_CONTROL, 0x0110);
+
+	ili922x_poweron(spi);
+
+	ili922x_write(spi, REG_GAMMA_CONTROL_1, 0x0302);
+	ili922x_write(spi, REG_GAMMA_CONTROL_2, 0x0407);
+	ili922x_write(spi, REG_GAMMA_CONTROL_3, 0x0304);
+	ili922x_write(spi, REG_GAMMA_CONTROL_4, 0x0203);
+	ili922x_write(spi, REG_GAMMA_CONTROL_5, 0x0706);
+	ili922x_write(spi, REG_GAMMA_CONTROL_6, 0x0407);
+	ili922x_write(spi, REG_GAMMA_CONTROL_7, 0x0706);
+	ili922x_write(spi, REG_GAMMA_CONTROL_8, 0x0000);
+	ili922x_write(spi, REG_GAMMA_CONTROL_9, 0x0C06);
+	ili922x_write(spi, REG_GAMMA_CONTROL_10, 0x0F00);
+	ili922x_write(spi, REG_RAM_ADDRESS_SET, 0x0000);
+	ili922x_write(spi, REG_GATE_SCAN_CONTROL, 0x0000);
+	ili922x_write(spi, REG_VERT_SCROLL_CONTROL, 0x0000);
+	ili922x_write(spi, REG_FIRST_SCREEN_DRIVE_POS, 0xDB00);
+	ili922x_write(spi, REG_SECOND_SCREEN_DRIVE_POS, 0xDB00);
+	ili922x_write(spi, REG_RAM_ADDR_POS_H, 0xAF00);
+	ili922x_write(spi, REG_RAM_ADDR_POS_V, 0xDB00);
+	ili922x_reg_dump(spi);
+	set_write_to_gram_reg(spi);
+}
+
+static int ili922x_lcd_power(struct ili922x *lcd, int power)
+{
+	int ret = 0;
+
+	if (POWER_IS_ON(power) && !POWER_IS_ON(lcd->power))
+		ret = ili922x_poweron(lcd->spi);
+	else if (!POWER_IS_ON(power) && POWER_IS_ON(lcd->power))
+		ret = ili922x_poweroff(lcd->spi);
+
+	if (!ret)
+		lcd->power = power;
+
+	return ret;
+}
+
+static int ili922x_set_power(struct lcd_device *ld, int power)
+{
+	struct ili922x *ili = lcd_get_data(ld);
+
+	return ili922x_lcd_power(ili, power);
+}
+
+static int ili922x_get_power(struct lcd_device *ld)
+{
+	struct ili922x *ili = lcd_get_data(ld);
+
+	return ili->power;
+}
+
+static struct lcd_ops ili922x_ops = {
+	.get_power = ili922x_get_power,
+	.set_power = ili922x_set_power,
+};
+
+static int ili922x_probe(struct spi_device *spi)
+{
+	struct ili922x *ili;
+	struct lcd_device *lcd;
+	int ret;
+	u16 reg = 0;
+
+	ili = devm_kzalloc(&spi->dev, sizeof(*ili), GFP_KERNEL);
+	if (!ili) {
+		dev_err(&spi->dev, "cannot alloc priv data\n");
+		return -ENOMEM;
+	}
+
+	ili->spi = spi;
+	dev_set_drvdata(&spi->dev, ili);
+
+	/* check if the device is connected */
+	ret = ili922x_read(spi, REG_DRIVER_CODE_READ, &reg);
+	if (ret || ((reg & ILITEK_DEVICE_ID_MASK) != ILITEK_DEVICE_ID)) {
+		dev_err(&spi->dev,
+			"no LCD found: Chip ID 0x%x, ret %d\n",
+			reg, ret);
+		return -ENODEV;
+	} else {
+		dev_info(&spi->dev, "ILI%x found, SPI freq %d, mode %d\n",
+			 reg, spi->max_speed_hz, spi->mode);
+	}
+
+	ret = ili922x_read_status(spi, &reg);
+	if (ret) {
+		dev_err(&spi->dev, "reading RS failed...\n");
+		return ret;
+	} else
+		dev_dbg(&spi->dev, "status: 0x%x\n", reg);
+
+	ili922x_display_init(spi);
+
+	ili->power = FB_BLANK_POWERDOWN;
+
+	lcd = lcd_device_register("ili922xlcd", &spi->dev, ili,
+				  &ili922x_ops);
+	if (IS_ERR(lcd)) {
+		dev_err(&spi->dev, "cannot register LCD\n");
+		return PTR_ERR(lcd);
+	}
+
+	ili->ld = lcd;
+	spi_set_drvdata(spi, ili);
+
+	ili922x_lcd_power(ili, FB_BLANK_UNBLANK);
+
+	return 0;
+}
+
+static int ili922x_remove(struct spi_device *spi)
+{
+	struct ili922x *ili = spi_get_drvdata(spi);
+
+	ili922x_poweroff(spi);
+	lcd_device_unregister(ili->ld);
+	return 0;
+}
+
+static struct spi_driver ili922x_driver = {
+	.driver = {
+		.name = "ili922x",
+		.owner = THIS_MODULE,
+	},
+	.probe = ili922x_probe,
+	.remove = ili922x_remove,
+};
+
+module_spi_driver(ili922x_driver);
+
+MODULE_AUTHOR("Stefano Babic <sbabic@denx.de>");
+MODULE_DESCRIPTION("ILI9221/9222 LCD driver");
+MODULE_LICENSE("GPL");
+MODULE_PARM_DESC(ili922x_id, "set controller identifier (default=1)");
+MODULE_PARM_DESC(tx_invert, "invert bytes before sending");
diff --git a/drivers/video/backlight/jornada720_bl.c b/drivers/video/backlight/jornada720_bl.c
index fef6ce4..3ccb893 100644
--- a/drivers/video/backlight/jornada720_bl.c
+++ b/drivers/video/backlight/jornada720_bl.c
@@ -9,8 +9,6 @@
  *
  */
 
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
 #include <linux/backlight.h>
 #include <linux/device.h>
 #include <linux/fb.h>
@@ -40,11 +38,13 @@ static int jornada_bl_get_brightness(struct backlight_device *bd)
 	ret = jornada_ssp_byte(GETBRIGHTNESS);
 
 	if (jornada_ssp_byte(GETBRIGHTNESS) != TXDUMMY) {
-		pr_err("get brightness timeout\n");
+		dev_err(&bd->dev, "get brightness timeout\n");
 		jornada_ssp_end();
 		return -ETIMEDOUT;
-	} else /* exchange txdummy for value */
+	} else {
+		/* exchange txdummy for value */
 		ret = jornada_ssp_byte(TXDUMMY);
+	}
 
 	jornada_ssp_end();
 
@@ -61,7 +61,7 @@ static int jornada_bl_update_status(struct backlight_device *bd)
 	if ((bd->props.power != FB_BLANK_UNBLANK) || (bd->props.fb_blank != FB_BLANK_UNBLANK)) {
 		ret = jornada_ssp_byte(BRIGHTNESSOFF);
 		if (ret != TXDUMMY) {
-			pr_info("brightness off timeout\n");
+			dev_info(&bd->dev, "brightness off timeout\n");
 			/* turn off backlight */
 			PPSR &= ~PPC_LDD1;
 			PPDR |= PPC_LDD1;
@@ -72,7 +72,7 @@ static int jornada_bl_update_status(struct backlight_device *bd)
 
 		/* send command to our mcu */
 		if (jornada_ssp_byte(SETBRIGHTNESS) != TXDUMMY) {
-			pr_info("failed to set brightness\n");
+			dev_info(&bd->dev, "failed to set brightness\n");
 			ret = -ETIMEDOUT;
 			goto out;
 		}
@@ -86,7 +86,7 @@ static int jornada_bl_update_status(struct backlight_device *bd)
 		 */
 		if (jornada_ssp_byte(BL_MAX_BRIGHT - bd->props.brightness)
 			!= TXDUMMY) {
-			pr_err("set brightness failed\n");
+			dev_err(&bd->dev, "set brightness failed\n");
 			ret = -ETIMEDOUT;
 		}
 
@@ -120,7 +120,7 @@ static int jornada_bl_probe(struct platform_device *pdev)
 
 	if (IS_ERR(bd)) {
 		ret = PTR_ERR(bd);
-		pr_err("failed to register device, err=%x\n", ret);
+		dev_err(&pdev->dev, "failed to register device, err=%x\n", ret);
 		return ret;
 	}
 
@@ -134,7 +134,7 @@ static int jornada_bl_probe(struct platform_device *pdev)
 	jornada_bl_update_status(bd);
 
 	platform_set_drvdata(pdev, bd);
-	pr_info("HP Jornada 700 series backlight driver\n");
+	dev_info(&pdev->dev, "HP Jornada 700 series backlight driver\n");
 
 	return 0;
 }
diff --git a/drivers/video/backlight/jornada720_lcd.c b/drivers/video/backlight/jornada720_lcd.c
index 635b305..b061413 100644
--- a/drivers/video/backlight/jornada720_lcd.c
+++ b/drivers/video/backlight/jornada720_lcd.c
@@ -9,8 +9,6 @@
  *
  */
 
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
 #include <linux/device.h>
 #include <linux/fb.h>
 #include <linux/kernel.h>
@@ -27,7 +25,7 @@
 #define LCD_MAX_CONTRAST	0xff
 #define LCD_DEF_CONTRAST	0x80
 
-static int jornada_lcd_get_power(struct lcd_device *dev)
+static int jornada_lcd_get_power(struct lcd_device *ld)
 {
 	/* LDD2 in PPC = LCD POWER */
 	if (PPSR & PPC_LDD2)
@@ -36,17 +34,17 @@ static int jornada_lcd_get_power(struct lcd_device *dev)
 		return FB_BLANK_POWERDOWN;	/* PW OFF */
 }
 
-static int jornada_lcd_get_contrast(struct lcd_device *dev)
+static int jornada_lcd_get_contrast(struct lcd_device *ld)
 {
 	int ret;
 
-	if (jornada_lcd_get_power(dev) != FB_BLANK_UNBLANK)
+	if (jornada_lcd_get_power(ld) != FB_BLANK_UNBLANK)
 		return 0;
 
 	jornada_ssp_start();
 
 	if (jornada_ssp_byte(GETCONTRAST) != TXDUMMY) {
-		pr_err("get contrast failed\n");
+		dev_err(&ld->dev, "get contrast failed\n");
 		jornada_ssp_end();
 		return -ETIMEDOUT;
 	} else {
@@ -56,7 +54,7 @@ static int jornada_lcd_get_contrast(struct lcd_device *dev)
 	}
 }
 
-static int jornada_lcd_set_contrast(struct lcd_device *dev, int value)
+static int jornada_lcd_set_contrast(struct lcd_device *ld, int value)
 {
 	int ret;
 
@@ -67,7 +65,7 @@ static int jornada_lcd_set_contrast(struct lcd_device *dev, int value)
 
 	/* push the new value */
 	if (jornada_ssp_byte(value) != TXDUMMY) {
-		pr_err("set contrast failed\n");
+		dev_err(&ld->dev, "set contrast failed\n");
 		jornada_ssp_end();
 		return -ETIMEDOUT;
 	}
@@ -78,13 +76,14 @@ static int jornada_lcd_set_contrast(struct lcd_device *dev, int value)
 	return 0;
 }
 
-static int jornada_lcd_set_power(struct lcd_device *dev, int power)
+static int jornada_lcd_set_power(struct lcd_device *ld, int power)
 {
 	if (power != FB_BLANK_UNBLANK) {
 		PPSR &= ~PPC_LDD2;
 		PPDR |= PPC_LDD2;
-	} else
+	} else {
 		PPSR |= PPC_LDD2;
+	}
 
 	return 0;
 }
@@ -105,7 +104,7 @@ static int jornada_lcd_probe(struct platform_device *pdev)
 
 	if (IS_ERR(lcd_device)) {
 		ret = PTR_ERR(lcd_device);
-		pr_err("failed to register device\n");
+		dev_err(&pdev->dev, "failed to register device\n");
 		return ret;
 	}
 
diff --git a/drivers/video/backlight/kb3886_bl.c b/drivers/video/backlight/kb3886_bl.c
index 6c5ed6b..bca6ccc 100644
--- a/drivers/video/backlight/kb3886_bl.c
+++ b/drivers/video/backlight/kb3886_bl.c
@@ -106,29 +106,28 @@ static int kb3886bl_send_intensity(struct backlight_device *bd)
 	return 0;
 }
 
-#ifdef CONFIG_PM
-static int kb3886bl_suspend(struct platform_device *pdev, pm_message_t state)
+#ifdef CONFIG_PM_SLEEP
+static int kb3886bl_suspend(struct device *dev)
 {
-	struct backlight_device *bd = platform_get_drvdata(pdev);
+	struct backlight_device *bd = dev_get_drvdata(dev);
 
 	kb3886bl_flags |= KB3886BL_SUSPENDED;
 	backlight_update_status(bd);
 	return 0;
 }
 
-static int kb3886bl_resume(struct platform_device *pdev)
+static int kb3886bl_resume(struct device *dev)
 {
-	struct backlight_device *bd = platform_get_drvdata(pdev);
+	struct backlight_device *bd = dev_get_drvdata(dev);
 
 	kb3886bl_flags &= ~KB3886BL_SUSPENDED;
 	backlight_update_status(bd);
 	return 0;
 }
-#else
-#define kb3886bl_suspend	NULL
-#define kb3886bl_resume		NULL
 #endif
 
+static SIMPLE_DEV_PM_OPS(kb3886bl_pm_ops, kb3886bl_suspend, kb3886bl_resume);
+
 static int kb3886bl_get_intensity(struct backlight_device *bd)
 {
 	return kb3886bl_intensity;
@@ -179,10 +178,9 @@ static int kb3886bl_remove(struct platform_device *pdev)
 static struct platform_driver kb3886bl_driver = {
 	.probe		= kb3886bl_probe,
 	.remove		= kb3886bl_remove,
-	.suspend	= kb3886bl_suspend,
-	.resume		= kb3886bl_resume,
 	.driver		= {
 		.name	= "kb3886-bl",
+		.pm	= &kb3886bl_pm_ops,
 	},
 };
 
diff --git a/drivers/video/backlight/l4f00242t03.c b/drivers/video/backlight/l4f00242t03.c
index fb61557..a35a38c 100644
--- a/drivers/video/backlight/l4f00242t03.c
+++ b/drivers/video/backlight/l4f00242t03.c
@@ -51,14 +51,33 @@ static void l4f00242t03_lcd_init(struct spi_device *spi)
 	struct l4f00242t03_pdata *pdata = spi->dev.platform_data;
 	struct l4f00242t03_priv *priv = spi_get_drvdata(spi);
 	const u16 cmd[] = { 0x36, param(0), 0x3A, param(0x60) };
+	int ret;
 
 	dev_dbg(&spi->dev, "initializing LCD\n");
 
-	regulator_set_voltage(priv->io_reg, 1800000, 1800000);
-	regulator_enable(priv->io_reg);
+	ret = regulator_set_voltage(priv->io_reg, 1800000, 1800000);
+	if (ret) {
+		dev_err(&spi->dev, "failed to set the IO regulator voltage.\n");
+		return;
+	}
+	ret = regulator_enable(priv->io_reg);
+	if (ret) {
+		dev_err(&spi->dev, "failed to enable the IO regulator.\n");
+		return;
+	}
 
-	regulator_set_voltage(priv->core_reg, 2800000, 2800000);
-	regulator_enable(priv->core_reg);
+	ret = regulator_set_voltage(priv->core_reg, 2800000, 2800000);
+	if (ret) {
+		dev_err(&spi->dev, "failed to set the core regulator voltage.\n");
+		regulator_disable(priv->io_reg);
+		return;
+	}
+	ret = regulator_enable(priv->core_reg);
+	if (ret) {
+		dev_err(&spi->dev, "failed to enable the core regulator.\n");
+		regulator_disable(priv->io_reg);
+		return;
+	}
 
 	l4f00242t03_reset(pdata->reset_gpio);
 
diff --git a/drivers/video/backlight/ld9040.c b/drivers/video/backlight/ld9040.c
index 1b642f5..1e0a309 100644
--- a/drivers/video/backlight/ld9040.c
+++ b/drivers/video/backlight/ld9040.c
@@ -775,12 +775,12 @@ static int ld9040_remove(struct spi_device *spi)
 	return 0;
 }
 
-#if defined(CONFIG_PM)
-static int ld9040_suspend(struct spi_device *spi, pm_message_t mesg)
+#ifdef CONFIG_PM_SLEEP
+static int ld9040_suspend(struct device *dev)
 {
-	struct ld9040 *lcd = spi_get_drvdata(spi);
+	struct ld9040 *lcd = dev_get_drvdata(dev);
 
-	dev_dbg(&spi->dev, "lcd->power = %d\n", lcd->power);
+	dev_dbg(dev, "lcd->power = %d\n", lcd->power);
 
 	/*
 	 * when lcd panel is suspend, lcd panel becomes off
@@ -789,19 +789,18 @@ static int ld9040_suspend(struct spi_device *spi, pm_message_t mesg)
 	return ld9040_power(lcd, FB_BLANK_POWERDOWN);
 }
 
-static int ld9040_resume(struct spi_device *spi)
+static int ld9040_resume(struct device *dev)
 {
-	struct ld9040 *lcd = spi_get_drvdata(spi);
+	struct ld9040 *lcd = dev_get_drvdata(dev);
 
 	lcd->power = FB_BLANK_POWERDOWN;
 
 	return ld9040_power(lcd, FB_BLANK_UNBLANK);
 }
-#else
-#define ld9040_suspend		NULL
-#define ld9040_resume		NULL
 #endif
 
+static SIMPLE_DEV_PM_OPS(ld9040_pm_ops, ld9040_suspend, ld9040_resume);
+
 /* Power down all displays on reboot, poweroff or halt. */
 static void ld9040_shutdown(struct spi_device *spi)
 {
@@ -814,12 +813,11 @@ static struct spi_driver ld9040_driver = {
 	.driver = {
 		.name	= "ld9040",
 		.owner	= THIS_MODULE,
+		.pm	= &ld9040_pm_ops,
 	},
 	.probe		= ld9040_probe,
 	.remove		= ld9040_remove,
 	.shutdown	= ld9040_shutdown,
-	.suspend	= ld9040_suspend,
-	.resume		= ld9040_resume,
 };
 
 module_spi_driver(ld9040_driver);
diff --git a/drivers/video/backlight/lm3533_bl.c b/drivers/video/backlight/lm3533_bl.c
index 5d18d4d..1d1dbfb 100644
--- a/drivers/video/backlight/lm3533_bl.c
+++ b/drivers/video/backlight/lm3533_bl.c
@@ -368,29 +368,28 @@ static int lm3533_bl_remove(struct platform_device *pdev)
 	return 0;
 }
 
-#ifdef CONFIG_PM
-static int lm3533_bl_suspend(struct platform_device *pdev, pm_message_t state)
+#ifdef CONFIG_PM_SLEEP
+static int lm3533_bl_suspend(struct device *dev)
 {
-	struct lm3533_bl *bl = platform_get_drvdata(pdev);
+	struct lm3533_bl *bl = dev_get_drvdata(dev);
 
-	dev_dbg(&pdev->dev, "%s\n", __func__);
+	dev_dbg(dev, "%s\n", __func__);
 
 	return lm3533_ctrlbank_disable(&bl->cb);
 }
 
-static int lm3533_bl_resume(struct platform_device *pdev)
+static int lm3533_bl_resume(struct device *dev)
 {
-	struct lm3533_bl *bl = platform_get_drvdata(pdev);
+	struct lm3533_bl *bl = dev_get_drvdata(dev);
 
-	dev_dbg(&pdev->dev, "%s\n", __func__);
+	dev_dbg(dev, "%s\n", __func__);
 
 	return lm3533_ctrlbank_enable(&bl->cb);
 }
-#else
-#define lm3533_bl_suspend	NULL
-#define lm3533_bl_resume	NULL
 #endif
 
+static SIMPLE_DEV_PM_OPS(lm3533_bl_pm_ops, lm3533_bl_suspend, lm3533_bl_resume);
+
 static void lm3533_bl_shutdown(struct platform_device *pdev)
 {
 	struct lm3533_bl *bl = platform_get_drvdata(pdev);
@@ -404,12 +403,11 @@ static struct platform_driver lm3533_bl_driver = {
 	.driver = {
 		.name	= "lm3533-backlight",
 		.owner	= THIS_MODULE,
+		.pm	= &lm3533_bl_pm_ops,
 	},
 	.probe		= lm3533_bl_probe,
 	.remove		= lm3533_bl_remove,
 	.shutdown	= lm3533_bl_shutdown,
-	.suspend	= lm3533_bl_suspend,
-	.resume		= lm3533_bl_resume,
 };
 module_platform_driver(lm3533_bl_driver);
 
diff --git a/drivers/video/backlight/lms501kf03.c b/drivers/video/backlight/lms501kf03.c
index b43882a..cf01b9a 100644
--- a/drivers/video/backlight/lms501kf03.c
+++ b/drivers/video/backlight/lms501kf03.c
@@ -387,13 +387,12 @@ static int lms501kf03_remove(struct spi_device *spi)
 	return 0;
 }
 
-#if defined(CONFIG_PM)
-
-static int lms501kf03_suspend(struct spi_device *spi, pm_message_t mesg)
+#ifdef CONFIG_PM_SLEEP
+static int lms501kf03_suspend(struct device *dev)
 {
-	struct lms501kf03 *lcd = spi_get_drvdata(spi);
+	struct lms501kf03 *lcd = dev_get_drvdata(dev);
 
-	dev_dbg(&spi->dev, "lcd->power = %d\n", lcd->power);
+	dev_dbg(dev, "lcd->power = %d\n", lcd->power);
 
 	/*
 	 * when lcd panel is suspend, lcd panel becomes off
@@ -402,19 +401,19 @@ static int lms501kf03_suspend(struct spi_device *spi, pm_message_t mesg)
 	return lms501kf03_power(lcd, FB_BLANK_POWERDOWN);
 }
 
-static int lms501kf03_resume(struct spi_device *spi)
+static int lms501kf03_resume(struct device *dev)
 {
-	struct lms501kf03 *lcd = spi_get_drvdata(spi);
+	struct lms501kf03 *lcd = dev_get_drvdata(dev);
 
 	lcd->power = FB_BLANK_POWERDOWN;
 
 	return lms501kf03_power(lcd, FB_BLANK_UNBLANK);
 }
-#else
-#define lms501kf03_suspend	NULL
-#define lms501kf03_resume	NULL
 #endif
 
+static SIMPLE_DEV_PM_OPS(lms501kf03_pm_ops, lms501kf03_suspend,
+			lms501kf03_resume);
+
 static void lms501kf03_shutdown(struct spi_device *spi)
 {
 	struct lms501kf03 *lcd = spi_get_drvdata(spi);
@@ -426,12 +425,11 @@ static struct spi_driver lms501kf03_driver = {
 	.driver = {
 		.name	= "lms501kf03",
 		.owner	= THIS_MODULE,
+		.pm	= &lms501kf03_pm_ops,
 	},
 	.probe		= lms501kf03_probe,
 	.remove		= lms501kf03_remove,
 	.shutdown	= lms501kf03_shutdown,
-	.suspend	= lms501kf03_suspend,
-	.resume		= lms501kf03_resume,
 };
 
 module_spi_driver(lms501kf03_driver);
diff --git a/drivers/video/backlight/locomolcd.c b/drivers/video/backlight/locomolcd.c
index 146fea8..6c3ec42 100644
--- a/drivers/video/backlight/locomolcd.c
+++ b/drivers/video/backlight/locomolcd.c
@@ -157,25 +157,24 @@ static const struct backlight_ops locomobl_data = {
 	.update_status  = locomolcd_set_intensity,
 };
 
-#ifdef CONFIG_PM
-static int locomolcd_suspend(struct locomo_dev *dev, pm_message_t state)
+#ifdef CONFIG_PM_SLEEP
+static int locomolcd_suspend(struct device *dev)
 {
 	locomolcd_flags |= LOCOMOLCD_SUSPENDED;
 	locomolcd_set_intensity(locomolcd_bl_device);
 	return 0;
 }
 
-static int locomolcd_resume(struct locomo_dev *dev)
+static int locomolcd_resume(struct device *dev)
 {
 	locomolcd_flags &= ~LOCOMOLCD_SUSPENDED;
 	locomolcd_set_intensity(locomolcd_bl_device);
 	return 0;
 }
-#else
-#define locomolcd_suspend	NULL
-#define locomolcd_resume	NULL
 #endif
 
+static SIMPLE_DEV_PM_OPS(locomolcd_pm_ops, locomolcd_suspend, locomolcd_resume);
+
 static int locomolcd_probe(struct locomo_dev *ldev)
 {
 	struct backlight_properties props;
@@ -230,13 +229,12 @@ static int locomolcd_remove(struct locomo_dev *dev)
 
 static struct locomo_driver poodle_lcd_driver = {
 	.drv = {
-		.name = "locomo-backlight",
+		.name	= "locomo-backlight",
+		.pm	= &locomolcd_pm_ops,
 	},
 	.devid	= LOCOMO_DEVID_BACKLIGHT,
 	.probe	= locomolcd_probe,
 	.remove	= locomolcd_remove,
-	.suspend = locomolcd_suspend,
-	.resume = locomolcd_resume,
 };
 
 static int __init locomolcd_init(void)
diff --git a/drivers/video/backlight/lp855x_bl.c b/drivers/video/backlight/lp855x_bl.c
index 7ae9ae6..c98bdbf 100644
--- a/drivers/video/backlight/lp855x_bl.c
+++ b/drivers/video/backlight/lp855x_bl.c
@@ -35,7 +35,6 @@
 #define LP8557_EPROM_START		0x10
 #define LP8557_EPROM_END		0x1E
 
-#define BUF_SIZE		20
 #define DEFAULT_BL_NAME		"lcd-backlight"
 #define MAX_BRIGHTNESS		255
 
@@ -304,7 +303,7 @@ static ssize_t lp855x_get_chip_id(struct device *dev,
 				struct device_attribute *attr, char *buf)
 {
 	struct lp855x *lp = dev_get_drvdata(dev);
-	return scnprintf(buf, BUF_SIZE, "%s\n", lp->chipname);
+	return scnprintf(buf, PAGE_SIZE, "%s\n", lp->chipname);
 }
 
 static ssize_t lp855x_get_bl_ctl_mode(struct device *dev,
@@ -319,7 +318,7 @@ static ssize_t lp855x_get_bl_ctl_mode(struct device *dev,
 	else if (mode == REGISTER_BASED)
 		strmode = "register based";
 
-	return scnprintf(buf, BUF_SIZE, "%s\n", strmode);
+	return scnprintf(buf, PAGE_SIZE, "%s\n", strmode);
 }
 
 static DEVICE_ATTR(chip_id, S_IRUGO, lp855x_get_chip_id, NULL);
@@ -339,7 +338,6 @@ static int lp855x_probe(struct i2c_client *cl, const struct i2c_device_id *id)
 {
 	struct lp855x *lp;
 	struct lp855x_platform_data *pdata = cl->dev.platform_data;
-	enum lp855x_brightness_ctrl_mode mode;
 	int ret;
 
 	if (!pdata) {
@@ -354,7 +352,6 @@ static int lp855x_probe(struct i2c_client *cl, const struct i2c_device_id *id)
 	if (!lp)
 		return -ENOMEM;
 
-	mode = pdata->mode;
 	lp->client = cl;
 	lp->dev = &cl->dev;
 	lp->pdata = pdata;
diff --git a/drivers/video/backlight/ltv350qv.c b/drivers/video/backlight/ltv350qv.c
index c0b4b8f..ed1b392 100644
--- a/drivers/video/backlight/ltv350qv.c
+++ b/drivers/video/backlight/ltv350qv.c
@@ -271,25 +271,24 @@ static int ltv350qv_remove(struct spi_device *spi)
 	return 0;
 }
 
-#ifdef CONFIG_PM
-static int ltv350qv_suspend(struct spi_device *spi, pm_message_t state)
+#ifdef CONFIG_PM_SLEEP
+static int ltv350qv_suspend(struct device *dev)
 {
-	struct ltv350qv *lcd = spi_get_drvdata(spi);
+	struct ltv350qv *lcd = dev_get_drvdata(dev);
 
 	return ltv350qv_power(lcd, FB_BLANK_POWERDOWN);
 }
 
-static int ltv350qv_resume(struct spi_device *spi)
+static int ltv350qv_resume(struct device *dev)
 {
-	struct ltv350qv *lcd = spi_get_drvdata(spi);
+	struct ltv350qv *lcd = dev_get_drvdata(dev);
 
 	return ltv350qv_power(lcd, FB_BLANK_UNBLANK);
 }
-#else
-#define ltv350qv_suspend	NULL
-#define ltv350qv_resume		NULL
 #endif
 
+static SIMPLE_DEV_PM_OPS(ltv350qv_pm_ops, ltv350qv_suspend, ltv350qv_resume);
+
 /* Power down all displays on reboot, poweroff or halt */
 static void ltv350qv_shutdown(struct spi_device *spi)
 {
@@ -302,13 +301,12 @@ static struct spi_driver ltv350qv_driver = {
 	.driver = {
 		.name		= "ltv350qv",
 		.owner		= THIS_MODULE,
+		.pm		= &ltv350qv_pm_ops,
 	},
 
 	.probe		= ltv350qv_probe,
 	.remove		= ltv350qv_remove,
 	.shutdown	= ltv350qv_shutdown,
-	.suspend	= ltv350qv_suspend,
-	.resume		= ltv350qv_resume,
 };
 
 module_spi_driver(ltv350qv_driver);
diff --git a/drivers/video/backlight/omap1_bl.c b/drivers/video/backlight/omap1_bl.c
index 6271101..0aed176 100644
--- a/drivers/video/backlight/omap1_bl.c
+++ b/drivers/video/backlight/omap1_bl.c
@@ -18,8 +18,6 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -170,7 +168,7 @@ static int omapbl_probe(struct platform_device *pdev)
 	dev->props.brightness = pdata->default_intensity;
 	omapbl_update_status(dev);
 
-	pr_info("OMAP LCD backlight initialised\n");
+	dev_info(&pdev->dev, "OMAP LCD backlight initialised\n");
 
 	return 0;
 }
diff --git a/drivers/video/backlight/platform_lcd.c b/drivers/video/backlight/platform_lcd.c
index 17a6b83..54d94de 100644
--- a/drivers/video/backlight/platform_lcd.c
+++ b/drivers/video/backlight/platform_lcd.c
@@ -121,7 +121,7 @@ static int platform_lcd_remove(struct platform_device *pdev)
 	return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int platform_lcd_suspend(struct device *dev)
 {
 	struct platform_lcd *plcd = dev_get_drvdata(dev);
@@ -141,10 +141,10 @@ static int platform_lcd_resume(struct device *dev)
 
 	return 0;
 }
+#endif
 
 static SIMPLE_DEV_PM_OPS(platform_lcd_pm_ops, platform_lcd_suspend,
 			platform_lcd_resume);
-#endif
 
 #ifdef CONFIG_OF
 static const struct of_device_id platform_lcd_of_match[] = {
@@ -158,9 +158,7 @@ static struct platform_driver platform_lcd_driver = {
 	.driver		= {
 		.name	= "platform-lcd",
 		.owner	= THIS_MODULE,
-#ifdef CONFIG_PM
 		.pm	= &platform_lcd_pm_ops,
-#endif
 		.of_match_table = of_match_ptr(platform_lcd_of_match),
 	},
 	.probe		= platform_lcd_probe,
diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c
index fa00304..1fea627 100644
--- a/drivers/video/backlight/pwm_bl.c
+++ b/drivers/video/backlight/pwm_bl.c
@@ -274,7 +274,7 @@ static int pwm_backlight_remove(struct platform_device *pdev)
 	return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int pwm_backlight_suspend(struct device *dev)
 {
 	struct backlight_device *bl = dev_get_drvdata(dev);
@@ -296,19 +296,16 @@ static int pwm_backlight_resume(struct device *dev)
 	backlight_update_status(bl);
 	return 0;
 }
+#endif
 
 static SIMPLE_DEV_PM_OPS(pwm_backlight_pm_ops, pwm_backlight_suspend,
 			 pwm_backlight_resume);
 
-#endif
-
 static struct platform_driver pwm_backlight_driver = {
 	.driver		= {
 		.name		= "pwm-backlight",
 		.owner		= THIS_MODULE,
-#ifdef CONFIG_PM
 		.pm		= &pwm_backlight_pm_ops,
-#endif
 		.of_match_table	= of_match_ptr(pwm_backlight_of_match),
 	},
 	.probe		= pwm_backlight_probe,
diff --git a/drivers/video/backlight/s6e63m0.c b/drivers/video/backlight/s6e63m0.c
index 9c2677f..b37bb18 100644
--- a/drivers/video/backlight/s6e63m0.c
+++ b/drivers/video/backlight/s6e63m0.c
@@ -817,12 +817,12 @@ static int s6e63m0_remove(struct spi_device *spi)
 	return 0;
 }
 
-#if defined(CONFIG_PM)
-static int s6e63m0_suspend(struct spi_device *spi, pm_message_t mesg)
+#ifdef CONFIG_PM_SLEEP
+static int s6e63m0_suspend(struct device *dev)
 {
-	struct s6e63m0 *lcd = spi_get_drvdata(spi);
+	struct s6e63m0 *lcd = dev_get_drvdata(dev);
 
-	dev_dbg(&spi->dev, "lcd->power = %d\n", lcd->power);
+	dev_dbg(dev, "lcd->power = %d\n", lcd->power);
 
 	/*
 	 * when lcd panel is suspend, lcd panel becomes off
@@ -831,19 +831,18 @@ static int s6e63m0_suspend(struct spi_device *spi, pm_message_t mesg)
 	return s6e63m0_power(lcd, FB_BLANK_POWERDOWN);
 }
 
-static int s6e63m0_resume(struct spi_device *spi)
+static int s6e63m0_resume(struct device *dev)
 {
-	struct s6e63m0 *lcd = spi_get_drvdata(spi);
+	struct s6e63m0 *lcd = dev_get_drvdata(dev);
 
 	lcd->power = FB_BLANK_POWERDOWN;
 
 	return s6e63m0_power(lcd, FB_BLANK_UNBLANK);
 }
-#else
-#define s6e63m0_suspend		NULL
-#define s6e63m0_resume		NULL
 #endif
 
+static SIMPLE_DEV_PM_OPS(s6e63m0_pm_ops, s6e63m0_suspend, s6e63m0_resume);
+
 /* Power down all displays on reboot, poweroff or halt. */
 static void s6e63m0_shutdown(struct spi_device *spi)
 {
@@ -856,12 +855,11 @@ static struct spi_driver s6e63m0_driver = {
 	.driver = {
 		.name	= "s6e63m0",
 		.owner	= THIS_MODULE,
+		.pm	= &s6e63m0_pm_ops,
 	},
 	.probe		= s6e63m0_probe,
 	.remove		= s6e63m0_remove,
 	.shutdown	= s6e63m0_shutdown,
-	.suspend	= s6e63m0_suspend,
-	.resume		= s6e63m0_resume,
 };
 
 module_spi_driver(s6e63m0_driver);
diff --git a/drivers/video/backlight/tdo24m.c b/drivers/video/backlight/tdo24m.c
index 0016208..18cdf46 100644
--- a/drivers/video/backlight/tdo24m.c
+++ b/drivers/video/backlight/tdo24m.c
@@ -412,25 +412,24 @@ static int tdo24m_remove(struct spi_device *spi)
 	return 0;
 }
 
-#ifdef CONFIG_PM
-static int tdo24m_suspend(struct spi_device *spi, pm_message_t state)
+#ifdef CONFIG_PM_SLEEP
+static int tdo24m_suspend(struct device *dev)
 {
-	struct tdo24m *lcd = spi_get_drvdata(spi);
+	struct tdo24m *lcd = dev_get_drvdata(dev);
 
 	return tdo24m_power(lcd, FB_BLANK_POWERDOWN);
 }
 
-static int tdo24m_resume(struct spi_device *spi)
+static int tdo24m_resume(struct device *dev)
 {
-	struct tdo24m *lcd = spi_get_drvdata(spi);
+	struct tdo24m *lcd = dev_get_drvdata(dev);
 
 	return tdo24m_power(lcd, FB_BLANK_UNBLANK);
 }
-#else
-#define tdo24m_suspend	NULL
-#define tdo24m_resume	NULL
 #endif
 
+static SIMPLE_DEV_PM_OPS(tdo24m_pm_ops, tdo24m_suspend, tdo24m_resume);
+
 /* Power down all displays on reboot, poweroff or halt */
 static void tdo24m_shutdown(struct spi_device *spi)
 {
@@ -443,12 +442,11 @@ static struct spi_driver tdo24m_driver = {
 	.driver = {
 		.name		= "tdo24m",
 		.owner		= THIS_MODULE,
+		.pm		= &tdo24m_pm_ops,
 	},
 	.probe		= tdo24m_probe,
 	.remove		= tdo24m_remove,
 	.shutdown	= tdo24m_shutdown,
-	.suspend	= tdo24m_suspend,
-	.resume		= tdo24m_resume,
 };
 
 module_spi_driver(tdo24m_driver);
diff --git a/drivers/video/bfin_adv7393fb.c b/drivers/video/bfin_adv7393fb.c
index 8d411a3..a54f7f7 100644
--- a/drivers/video/bfin_adv7393fb.c
+++ b/drivers/video/bfin_adv7393fb.c
@@ -333,29 +333,23 @@ static int proc_output(char *buf)
 	return p - buf;
 }
 
-static int
-adv7393_read_proc(char *page, char **start, off_t off,
-		  int count, int *eof, void *data)
+static ssize_t
+adv7393_read_proc(struct file *file, char __user *buf,
+		  size_t size, loff_t *ppos)
 {
-	int len;
-
-	len = proc_output(page);
-	if (len <= off + count)
-		*eof = 1;
-	*start = page + off;
-	len -= off;
-	if (len > count)
-		len = count;
-	if (len < 0)
-		len = 0;
-	return len;
+	static const char message[] = "Usage:\n"
+		"echo 0x[REG][Value] > adv7393\n"
+		"example: echo 0x1234 >adv7393\n"
+		"writes 0x34 into Register 0x12\n";
+	return simple_read_from_buffer(buf, size, ppos, message,
+					sizeof(message));
 }
 
-static int
+static ssize_t
 adv7393_write_proc(struct file *file, const char __user * buffer,
-		   size_t count, void *data)
+		   size_t count, loff_t *ppos)
 {
-	struct adv7393fb_device *fbdev = data;
+	struct adv7393fb_device *fbdev = PDE_DATA(file_inode(file));
 	unsigned int val;
 	int ret;
 
@@ -368,6 +362,12 @@ adv7393_write_proc(struct file *file, const char __user * buffer,
 	return count;
 }
 
+static const struct file_operations fops = {
+	.read = adv7393_read_proc,
+	.write = adv7393_write_proc,
+	.llseek = default_llseek,
+};
+
 static int bfin_adv7393_fb_probe(struct i2c_client *client,
 				 const struct i2c_device_id *id)
 {
@@ -506,17 +506,12 @@ static int bfin_adv7393_fb_probe(struct i2c_client *client,
 	       fbdev->info.node, fbdev->info.fix.id);
 	dev_info(&client->dev, "fb memory address : 0x%p\n", fbdev->fb_mem);
 
-	entry = create_proc_entry("driver/adv7393", 0, NULL);
+	entry = proc_create_data("driver/adv7393", 0, NULL, &fops, fbdev);
 	if (!entry) {
 		dev_err(&client->dev, "unable to create /proc entry\n");
 		ret = -EFAULT;
 		goto free_fb;
 	}
-
-	entry->read_proc = adv7393_read_proc;
-	entry->write_proc = adv7393_write_proc;
-	entry->data = fbdev;
-
 	return 0;
 
 free_fb:
diff --git a/drivers/video/console/fbcon_cw.c b/drivers/video/console/fbcon_cw.c
index 6a73782..a93670e 100644
--- a/drivers/video/console/fbcon_cw.c
+++ b/drivers/video/console/fbcon_cw.c
@@ -27,7 +27,7 @@ static void cw_update_attr(u8 *dst, u8 *src, int attribute,
 {
 	int i, j, offset = (vc->vc_font.height < 10) ? 1 : 2;
 	int width = (vc->vc_font.height + 7) >> 3;
-	u8 c, t = 0, msk = ~(0xff >> offset);
+	u8 c, msk = ~(0xff >> offset);
 
 	for (i = 0; i < vc->vc_font.width; i++) {
 		for (j = 0; j < width; j++) {
@@ -40,7 +40,6 @@ static void cw_update_attr(u8 *dst, u8 *src, int attribute,
 				c = ~c;
 			src++;
 			*dst++ = c;
-			t = c;
 		}
 	}
 }
diff --git a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c
index 5788678..e78d9f2 100644
--- a/drivers/video/cyber2000fb.c
+++ b/drivers/video/cyber2000fb.c
@@ -518,6 +518,9 @@ static void cyber2000fb_set_timing(struct cfb_info *cfb, struct par_info *hw)
 	cyber2000_grphw(0xb9, 0x00, cfb);
 	spin_unlock(&cfb->reg_b0_lock);
 
+	/* wait (for the PLL?) to avoid palette corruption at higher clocks */
+	msleep(1000);
+
 	cfb->ramdac_ctrl = hw->ramdac;
 	cyber2000fb_write_ramdac_ctrl(cfb);
 
diff --git a/drivers/video/ep93xx-fb.c b/drivers/video/ep93xx-fb.c
index e06cd5d..ee1ee54 100644
--- a/drivers/video/ep93xx-fb.c
+++ b/drivers/video/ep93xx-fb.c
@@ -419,7 +419,7 @@ static struct fb_ops ep93xxfb_ops = {
 	.fb_mmap	= ep93xxfb_mmap,
 };
 
-static int __init ep93xxfb_calc_fbsize(struct ep93xxfb_mach_info *mach_info)
+static int ep93xxfb_calc_fbsize(struct ep93xxfb_mach_info *mach_info)
 {
 	int i, fb_size = 0;
 
@@ -441,7 +441,7 @@ static int __init ep93xxfb_calc_fbsize(struct ep93xxfb_mach_info *mach_info)
 	return fb_size;
 }
 
-static int __init ep93xxfb_alloc_videomem(struct fb_info *info)
+static int ep93xxfb_alloc_videomem(struct fb_info *info)
 {
 	struct ep93xx_fbi *fbi = info->par;
 	char __iomem *virt_addr;
@@ -627,19 +627,7 @@ static struct platform_driver ep93xxfb_driver = {
 		.owner	= THIS_MODULE,
 	},
 };
-
-static int ep93xxfb_init(void)
-{
-	return platform_driver_register(&ep93xxfb_driver);
-}
-
-static void __exit ep93xxfb_exit(void)
-{
-	platform_driver_unregister(&ep93xxfb_driver);
-}
-
-module_init(ep93xxfb_init);
-module_exit(ep93xxfb_exit);
+module_platform_driver(ep93xxfb_driver);
 
 MODULE_DESCRIPTION("EP93XX Framebuffer Driver");
 MODULE_ALIAS("platform:ep93xx-fb");
diff --git a/drivers/video/exynos/exynos_dp_core.c b/drivers/video/exynos/exynos_dp_core.c
index de9d4da..12bbede 100644
--- a/drivers/video/exynos/exynos_dp_core.c
+++ b/drivers/video/exynos/exynos_dp_core.c
@@ -976,14 +976,14 @@ static int exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp)
 	}
 
 	if (of_property_read_u32(dp_phy_node, "reg", &phy_base)) {
-		dev_err(dp->dev, "faild to get reg for dptx-phy\n");
+		dev_err(dp->dev, "failed to get reg for dptx-phy\n");
 		ret = -EINVAL;
 		goto err;
 	}
 
 	if (of_property_read_u32(dp_phy_node, "samsung,enable-mask",
 				&dp->enable_mask)) {
-		dev_err(dp->dev, "faild to get enable-mask for dptx-phy\n");
+		dev_err(dp->dev, "failed to get enable-mask for dptx-phy\n");
 		ret = -EINVAL;
 		goto err;
 	}
diff --git a/drivers/video/exynos/exynos_mipi_dsi.c b/drivers/video/exynos/exynos_mipi_dsi.c
index fac7df6..87cd13b 100644
--- a/drivers/video/exynos/exynos_mipi_dsi.c
+++ b/drivers/video/exynos/exynos_mipi_dsi.c
@@ -32,6 +32,7 @@
 #include <linux/notifier.h>
 #include <linux/regulator/consumer.h>
 #include <linux/pm_runtime.h>
+#include <linux/err.h>
 
 #include <video/exynos_mipi_dsim.h>
 
@@ -384,10 +385,9 @@ static int exynos_mipi_dsi_probe(struct platform_device *pdev)
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
-	dsim->reg_base = devm_request_and_ioremap(&pdev->dev, res);
-	if (!dsim->reg_base) {
-		dev_err(&pdev->dev, "failed to remap io region\n");
-		ret = -ENOMEM;
+	dsim->reg_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(dsim->reg_base)) {
+		ret = PTR_ERR(dsim->reg_base);
 		goto error;
 	}
 
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 7c25408..ccd44b0 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -1645,6 +1645,11 @@ static int do_register_framebuffer(struct fb_info *fb_info)
 	if (!fb_info->modelist.prev || !fb_info->modelist.next)
 		INIT_LIST_HEAD(&fb_info->modelist);
 
+	if (fb_info->skip_vt_switch)
+		pm_vt_switch_required(fb_info->dev, false);
+	else
+		pm_vt_switch_required(fb_info->dev, true);
+
 	fb_var_to_videomode(&mode, &fb_info->var);
 	fb_add_videomode(&mode, &fb_info->modelist);
 	registered_fb[i] = fb_info;
@@ -1679,6 +1684,8 @@ static int do_unregister_framebuffer(struct fb_info *fb_info)
 	if (ret)
 		return -EINVAL;
 
+	pm_vt_switch_unregister(fb_info->dev);
+
 	unlink_framebuffer(fb_info);
 	if (fb_info->pixmap.addr &&
 	    (fb_info->pixmap.flags & FB_PIXMAP_DEFAULT))
diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c
index 41fbd94..6c27805 100644
--- a/drivers/video/fsl-diu-fb.c
+++ b/drivers/video/fsl-diu-fb.c
@@ -375,7 +375,10 @@ struct fsl_diu_data {
 	struct diu_ad dummy_ad __aligned(8);
 	struct diu_ad ad[NUM_AOIS] __aligned(8);
 	u8 gamma[256 * 3] __aligned(32);
-	u8 cursor[MAX_CURS * MAX_CURS * 2] __aligned(32);
+	/* It's easier to parse the cursor data as little-endian */
+	__le16 cursor[MAX_CURS * MAX_CURS] __aligned(32);
+	/* Blank cursor data -- used to hide the cursor */
+	__le16 blank_cursor[MAX_CURS * MAX_CURS] __aligned(32);
 	uint8_t edid_data[EDID_LENGTH];
 	bool has_edid;
 } __aligned(32);
@@ -824,7 +827,6 @@ static void update_lcdc(struct fb_info *info)
 	/* Program DIU registers */
 
 	out_be32(&hw->gamma, DMA_ADDR(data, gamma));
-	out_be32(&hw->cursor, DMA_ADDR(data, cursor));
 
 	out_be32(&hw->bgnd, 0x007F7F7F); /* Set background to grey */
 	out_be32(&hw->disp_size, (var->yres << 16) | var->xres);
@@ -968,6 +970,156 @@ static u32 fsl_diu_get_pixel_format(unsigned int bits_per_pixel)
 }
 
 /*
+ * Copies a cursor image from user space to the proper place in driver
+ * memory so that the hardware can display the cursor image.
+ *
+ * Cursor data is represented as a sequence of 'width' bits packed into bytes.
+ * That is, the first 8 bits are in the first byte, the second 8 bits in the
+ * second byte, and so on.  Therefore, the each row of the cursor is (width +
+ * 7) / 8 bytes of 'data'
+ *
+ * The DIU only supports cursors up to 32x32 (MAX_CURS).  We reject cursors
+ * larger than this, so we already know that 'width' <= 32.  Therefore, we can
+ * simplify our code by using a 32-bit big-endian integer ("line") to read in
+ * a single line of pixels, and only look at the top 'width' bits of that
+ * integer.
+ *
+ * This could result in an unaligned 32-bit read.  For example, if the cursor
+ * is 24x24, then the first three bytes of 'image' contain the pixel data for
+ * the top line of the cursor.  We do a 32-bit read of 'image', but we look
+ * only at the top 24 bits.  Then we increment 'image' by 3 bytes.  The next
+ * read is unaligned.  The only problem is that we might read past the end of
+ * 'image' by 1-3 bytes, but that should not cause any problems.
+ */
+static void fsl_diu_load_cursor_image(struct fb_info *info,
+	const void *image, uint16_t bg, uint16_t fg,
+	unsigned int width, unsigned int height)
+{
+	struct mfb_info *mfbi = info->par;
+	struct fsl_diu_data *data = mfbi->parent;
+	__le16 *cursor = data->cursor;
+	__le16 _fg = cpu_to_le16(fg);
+	__le16 _bg = cpu_to_le16(bg);
+	unsigned int h, w;
+
+	for (h = 0; h < height; h++) {
+		uint32_t mask = 1 << 31;
+		uint32_t line = be32_to_cpup(image);
+
+		for (w = 0; w < width; w++) {
+			cursor[w] = (line & mask) ? _fg : _bg;
+			mask >>= 1;
+		}
+
+		cursor += MAX_CURS;
+		image += DIV_ROUND_UP(width, 8);
+	}
+}
+
+/*
+ * Set a hardware cursor.  The image data for the cursor is passed via the
+ * fb_cursor object.
+ */
+static int fsl_diu_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+	struct mfb_info *mfbi = info->par;
+	struct fsl_diu_data *data = mfbi->parent;
+	struct diu __iomem *hw = data->diu_reg;
+
+	if (cursor->image.width > MAX_CURS || cursor->image.height > MAX_CURS)
+		return -EINVAL;
+
+	/* The cursor size has changed */
+	if (cursor->set & FB_CUR_SETSIZE) {
+		/*
+		 * The DIU cursor is a fixed size, so when we get this
+		 * message, instead of resizing the cursor, we just clear
+		 * all the image data, in expectation of new data.  However,
+		 * in tests this control does not appear to be normally
+		 * called.
+		 */
+		memset(data->cursor, 0, sizeof(data->cursor));
+	}
+
+	/* The cursor position has changed (cursor->image.dx|dy) */
+	if (cursor->set & FB_CUR_SETPOS) {
+		uint32_t xx, yy;
+
+		yy = (cursor->image.dy - info->var.yoffset) & 0x7ff;
+		xx = (cursor->image.dx - info->var.xoffset) & 0x7ff;
+
+		out_be32(&hw->curs_pos, yy << 16 | xx);
+	}
+
+	/*
+	 * FB_CUR_SETIMAGE - the cursor image has changed
+	 * FB_CUR_SETCMAP  - the cursor colors has changed
+	 * FB_CUR_SETSHAPE - the cursor bitmask has changed
+	 */
+	if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETCMAP | FB_CUR_SETIMAGE)) {
+		unsigned int image_size =
+			DIV_ROUND_UP(cursor->image.width, 8) * cursor->image.height;
+		unsigned int image_words =
+			DIV_ROUND_UP(image_size, sizeof(uint32_t));
+		unsigned int bg_idx = cursor->image.bg_color;
+		unsigned int fg_idx = cursor->image.fg_color;
+		uint8_t buffer[image_size];
+		uint32_t *image, *source, *mask;
+		uint16_t fg, bg;
+		unsigned int i;
+
+		if (info->state != FBINFO_STATE_RUNNING)
+			return 0;
+
+		/*
+		 * Determine the size of the cursor image data.  Normally,
+		 * it's 8x16.
+		 */
+		image_size = DIV_ROUND_UP(cursor->image.width, 8) *
+			cursor->image.height;
+
+		bg = ((info->cmap.red[bg_idx] & 0xf8) << 7) |
+		     ((info->cmap.green[bg_idx] & 0xf8) << 2) |
+		     ((info->cmap.blue[bg_idx] & 0xf8) >> 3) |
+		     1 << 15;
+
+		fg = ((info->cmap.red[fg_idx] & 0xf8) << 7) |
+		     ((info->cmap.green[fg_idx] & 0xf8) << 2) |
+		     ((info->cmap.blue[fg_idx] & 0xf8) >> 3) |
+		     1 << 15;
+
+		/* Use 32-bit operations on the data to improve performance */
+		image = (uint32_t *)buffer;
+		source = (uint32_t *)cursor->image.data;
+		mask = (uint32_t *)cursor->mask;
+
+		if (cursor->rop == ROP_XOR)
+			for (i = 0; i < image_words; i++)
+				image[i] = source[i] ^ mask[i];
+		else
+			for (i = 0; i < image_words; i++)
+				image[i] = source[i] & mask[i];
+
+		fsl_diu_load_cursor_image(info, image, bg, fg,
+			cursor->image.width, cursor->image.height);
+	};
+
+	/*
+	 * Show or hide the cursor.  The cursor data is always stored in the
+	 * 'cursor' memory block, and the actual cursor position is always in
+	 * the DIU's CURS_POS register.  To hide the cursor, we redirect the
+	 * CURSOR register to a blank cursor.  The show the cursor, we
+	 * redirect the CURSOR register to the real cursor data.
+	 */
+	if (cursor->enable)
+		out_be32(&hw->cursor, DMA_ADDR(data, cursor));
+	else
+		out_be32(&hw->cursor, DMA_ADDR(data, blank_cursor));
+
+	return 0;
+}
+
+/*
  * Using the fb_var_screeninfo in fb_info we set the resolution of this
  * particular framebuffer. This function alters the fb_fix_screeninfo stored
  * in fb_info. It does not alter var in fb_info since we are using that
@@ -1312,6 +1464,7 @@ static struct fb_ops fsl_diu_ops = {
 	.fb_ioctl = fsl_diu_ioctl,
 	.fb_open = fsl_diu_open,
 	.fb_release = fsl_diu_release,
+	.fb_cursor = fsl_diu_cursor,
 };
 
 static int install_fb(struct fb_info *info)
diff --git a/drivers/video/goldfishfb.c b/drivers/video/goldfishfb.c
index 489abb3..7f6c9e6 100644
--- a/drivers/video/goldfishfb.c
+++ b/drivers/video/goldfishfb.c
@@ -148,7 +148,7 @@ static int goldfish_fb_pan_display(struct fb_var_screeninfo *var,
 	wait_event_timeout(fb->wait,
 			fb->base_update_count != base_update_count, HZ / 15);
 	if (fb->base_update_count == base_update_count)
-		pr_err("goldfish_fb_pan_display: timeout wating for base update\n");
+		pr_err("goldfish_fb_pan_display: timeout waiting for base update\n");
 	return 0;
 }
 
diff --git a/drivers/video/hyperv_fb.c b/drivers/video/hyperv_fb.c
new file mode 100644
index 0000000..d4d2c5f
--- /dev/null
+++ b/drivers/video/hyperv_fb.c
@@ -0,0 +1,829 @@
+/*
+ * Copyright (c) 2012, Microsoft Corporation.
+ *
+ * Author:
+ *   Haiyang Zhang <haiyangz@microsoft.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, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/*
+ * Hyper-V Synthetic Video Frame Buffer Driver
+ *
+ * This is the driver for the Hyper-V Synthetic Video, which supports
+ * screen resolution up to Full HD 1920x1080 with 32 bit color on Windows
+ * Server 2012, and 1600x1200 with 16 bit color on Windows Server 2008 R2
+ * or earlier.
+ *
+ * It also solves the double mouse cursor issue of the emulated video mode.
+ *
+ * The default screen resolution is 1152x864, which may be changed by a
+ * kernel parameter:
+ *     video=hyperv_fb:<width>x<height>
+ *     For example: video=hyperv_fb:1280x1024
+ *
+ * Portrait orientation is also supported:
+ *     For example: video=hyperv_fb:864x1152
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/completion.h>
+#include <linux/fb.h>
+#include <linux/pci.h>
+
+#include <linux/hyperv.h>
+
+
+/* Hyper-V Synthetic Video Protocol definitions and structures */
+#define MAX_VMBUS_PKT_SIZE 0x4000
+
+#define SYNTHVID_VERSION(major, minor) ((minor) << 16 | (major))
+#define SYNTHVID_VERSION_WIN7 SYNTHVID_VERSION(3, 0)
+#define SYNTHVID_VERSION_WIN8 SYNTHVID_VERSION(3, 2)
+
+#define SYNTHVID_DEPTH_WIN7 16
+#define SYNTHVID_DEPTH_WIN8 32
+
+#define SYNTHVID_FB_SIZE_WIN7 (4 * 1024 * 1024)
+#define SYNTHVID_WIDTH_MAX_WIN7 1600
+#define SYNTHVID_HEIGHT_MAX_WIN7 1200
+
+#define SYNTHVID_FB_SIZE_WIN8 (8 * 1024 * 1024)
+
+#define PCI_VENDOR_ID_MICROSOFT 0x1414
+#define PCI_DEVICE_ID_HYPERV_VIDEO 0x5353
+
+
+enum pipe_msg_type {
+	PIPE_MSG_INVALID,
+	PIPE_MSG_DATA,
+	PIPE_MSG_MAX
+};
+
+struct pipe_msg_hdr {
+	u32 type;
+	u32 size; /* size of message after this field */
+} __packed;
+
+
+enum synthvid_msg_type {
+	SYNTHVID_ERROR			= 0,
+	SYNTHVID_VERSION_REQUEST	= 1,
+	SYNTHVID_VERSION_RESPONSE	= 2,
+	SYNTHVID_VRAM_LOCATION		= 3,
+	SYNTHVID_VRAM_LOCATION_ACK	= 4,
+	SYNTHVID_SITUATION_UPDATE	= 5,
+	SYNTHVID_SITUATION_UPDATE_ACK	= 6,
+	SYNTHVID_POINTER_POSITION	= 7,
+	SYNTHVID_POINTER_SHAPE		= 8,
+	SYNTHVID_FEATURE_CHANGE		= 9,
+	SYNTHVID_DIRT			= 10,
+
+	SYNTHVID_MAX			= 11
+};
+
+struct synthvid_msg_hdr {
+	u32 type;
+	u32 size;  /* size of this header + payload after this field*/
+} __packed;
+
+
+struct synthvid_version_req {
+	u32 version;
+} __packed;
+
+struct synthvid_version_resp {
+	u32 version;
+	u8 is_accepted;
+	u8 max_video_outputs;
+} __packed;
+
+struct synthvid_vram_location {
+	u64 user_ctx;
+	u8 is_vram_gpa_specified;
+	u64 vram_gpa;
+} __packed;
+
+struct synthvid_vram_location_ack {
+	u64 user_ctx;
+} __packed;
+
+struct video_output_situation {
+	u8 active;
+	u32 vram_offset;
+	u8 depth_bits;
+	u32 width_pixels;
+	u32 height_pixels;
+	u32 pitch_bytes;
+} __packed;
+
+struct synthvid_situation_update {
+	u64 user_ctx;
+	u8 video_output_count;
+	struct video_output_situation video_output[1];
+} __packed;
+
+struct synthvid_situation_update_ack {
+	u64 user_ctx;
+} __packed;
+
+struct synthvid_pointer_position {
+	u8 is_visible;
+	u8 video_output;
+	s32 image_x;
+	s32 image_y;
+} __packed;
+
+
+#define CURSOR_MAX_X 96
+#define CURSOR_MAX_Y 96
+#define CURSOR_ARGB_PIXEL_SIZE 4
+#define CURSOR_MAX_SIZE (CURSOR_MAX_X * CURSOR_MAX_Y * CURSOR_ARGB_PIXEL_SIZE)
+#define CURSOR_COMPLETE (-1)
+
+struct synthvid_pointer_shape {
+	u8 part_idx;
+	u8 is_argb;
+	u32 width; /* CURSOR_MAX_X at most */
+	u32 height; /* CURSOR_MAX_Y at most */
+	u32 hot_x; /* hotspot relative to upper-left of pointer image */
+	u32 hot_y;
+	u8 data[4];
+} __packed;
+
+struct synthvid_feature_change {
+	u8 is_dirt_needed;
+	u8 is_ptr_pos_needed;
+	u8 is_ptr_shape_needed;
+	u8 is_situ_needed;
+} __packed;
+
+struct rect {
+	s32 x1, y1; /* top left corner */
+	s32 x2, y2; /* bottom right corner, exclusive */
+} __packed;
+
+struct synthvid_dirt {
+	u8 video_output;
+	u8 dirt_count;
+	struct rect rect[1];
+} __packed;
+
+struct synthvid_msg {
+	struct pipe_msg_hdr pipe_hdr;
+	struct synthvid_msg_hdr vid_hdr;
+	union {
+		struct synthvid_version_req ver_req;
+		struct synthvid_version_resp ver_resp;
+		struct synthvid_vram_location vram;
+		struct synthvid_vram_location_ack vram_ack;
+		struct synthvid_situation_update situ;
+		struct synthvid_situation_update_ack situ_ack;
+		struct synthvid_pointer_position ptr_pos;
+		struct synthvid_pointer_shape ptr_shape;
+		struct synthvid_feature_change feature_chg;
+		struct synthvid_dirt dirt;
+	};
+} __packed;
+
+
+
+/* FB driver definitions and structures */
+#define HVFB_WIDTH 1152 /* default screen width */
+#define HVFB_HEIGHT 864 /* default screen height */
+#define HVFB_WIDTH_MIN 640
+#define HVFB_HEIGHT_MIN 480
+
+#define RING_BUFSIZE (256 * 1024)
+#define VSP_TIMEOUT (10 * HZ)
+#define HVFB_UPDATE_DELAY (HZ / 20)
+
+struct hvfb_par {
+	struct fb_info *info;
+	bool fb_ready; /* fb device is ready */
+	struct completion wait;
+	u32 synthvid_version;
+
+	struct delayed_work dwork;
+	bool update;
+
+	u32 pseudo_palette[16];
+	u8 init_buf[MAX_VMBUS_PKT_SIZE];
+	u8 recv_buf[MAX_VMBUS_PKT_SIZE];
+};
+
+static uint screen_width = HVFB_WIDTH;
+static uint screen_height = HVFB_HEIGHT;
+static uint screen_depth;
+static uint screen_fb_size;
+
+/* Send message to Hyper-V host */
+static inline int synthvid_send(struct hv_device *hdev,
+				struct synthvid_msg *msg)
+{
+	static atomic64_t request_id = ATOMIC64_INIT(0);
+	int ret;
+
+	msg->pipe_hdr.type = PIPE_MSG_DATA;
+	msg->pipe_hdr.size = msg->vid_hdr.size;
+
+	ret = vmbus_sendpacket(hdev->channel, msg,
+			       msg->vid_hdr.size + sizeof(struct pipe_msg_hdr),
+			       atomic64_inc_return(&request_id),
+			       VM_PKT_DATA_INBAND, 0);
+
+	if (ret)
+		pr_err("Unable to send packet via vmbus\n");
+
+	return ret;
+}
+
+
+/* Send screen resolution info to host */
+static int synthvid_send_situ(struct hv_device *hdev)
+{
+	struct fb_info *info = hv_get_drvdata(hdev);
+	struct synthvid_msg msg;
+
+	if (!info)
+		return -ENODEV;
+
+	memset(&msg, 0, sizeof(struct synthvid_msg));
+
+	msg.vid_hdr.type = SYNTHVID_SITUATION_UPDATE;
+	msg.vid_hdr.size = sizeof(struct synthvid_msg_hdr) +
+		sizeof(struct synthvid_situation_update);
+	msg.situ.user_ctx = 0;
+	msg.situ.video_output_count = 1;
+	msg.situ.video_output[0].active = 1;
+	msg.situ.video_output[0].vram_offset = 0;
+	msg.situ.video_output[0].depth_bits = info->var.bits_per_pixel;
+	msg.situ.video_output[0].width_pixels = info->var.xres;
+	msg.situ.video_output[0].height_pixels = info->var.yres;
+	msg.situ.video_output[0].pitch_bytes = info->fix.line_length;
+
+	synthvid_send(hdev, &msg);
+
+	return 0;
+}
+
+/* Send mouse pointer info to host */
+static int synthvid_send_ptr(struct hv_device *hdev)
+{
+	struct synthvid_msg msg;
+
+	memset(&msg, 0, sizeof(struct synthvid_msg));
+	msg.vid_hdr.type = SYNTHVID_POINTER_POSITION;
+	msg.vid_hdr.size = sizeof(struct synthvid_msg_hdr) +
+		sizeof(struct synthvid_pointer_position);
+	msg.ptr_pos.is_visible = 1;
+	msg.ptr_pos.video_output = 0;
+	msg.ptr_pos.image_x = 0;
+	msg.ptr_pos.image_y = 0;
+	synthvid_send(hdev, &msg);
+
+	memset(&msg, 0, sizeof(struct synthvid_msg));
+	msg.vid_hdr.type = SYNTHVID_POINTER_SHAPE;
+	msg.vid_hdr.size = sizeof(struct synthvid_msg_hdr) +
+		sizeof(struct synthvid_pointer_shape);
+	msg.ptr_shape.part_idx = CURSOR_COMPLETE;
+	msg.ptr_shape.is_argb = 1;
+	msg.ptr_shape.width = 1;
+	msg.ptr_shape.height = 1;
+	msg.ptr_shape.hot_x = 0;
+	msg.ptr_shape.hot_y = 0;
+	msg.ptr_shape.data[0] = 0;
+	msg.ptr_shape.data[1] = 1;
+	msg.ptr_shape.data[2] = 1;
+	msg.ptr_shape.data[3] = 1;
+	synthvid_send(hdev, &msg);
+
+	return 0;
+}
+
+/* Send updated screen area (dirty rectangle) location to host */
+static int synthvid_update(struct fb_info *info)
+{
+	struct hv_device *hdev = device_to_hv_device(info->device);
+	struct synthvid_msg msg;
+
+	memset(&msg, 0, sizeof(struct synthvid_msg));
+
+	msg.vid_hdr.type = SYNTHVID_DIRT;
+	msg.vid_hdr.size = sizeof(struct synthvid_msg_hdr) +
+		sizeof(struct synthvid_dirt);
+	msg.dirt.video_output = 0;
+	msg.dirt.dirt_count = 1;
+	msg.dirt.rect[0].x1 = 0;
+	msg.dirt.rect[0].y1 = 0;
+	msg.dirt.rect[0].x2 = info->var.xres;
+	msg.dirt.rect[0].y2 = info->var.yres;
+
+	synthvid_send(hdev, &msg);
+
+	return 0;
+}
+
+
+/*
+ * Actions on received messages from host:
+ * Complete the wait event.
+ * Or, reply with screen and cursor info.
+ */
+static void synthvid_recv_sub(struct hv_device *hdev)
+{
+	struct fb_info *info = hv_get_drvdata(hdev);
+	struct hvfb_par *par;
+	struct synthvid_msg *msg;
+
+	if (!info)
+		return;
+
+	par = info->par;
+	msg = (struct synthvid_msg *)par->recv_buf;
+
+	/* Complete the wait event */
+	if (msg->vid_hdr.type == SYNTHVID_VERSION_RESPONSE ||
+	    msg->vid_hdr.type == SYNTHVID_VRAM_LOCATION_ACK) {
+		memcpy(par->init_buf, msg, MAX_VMBUS_PKT_SIZE);
+		complete(&par->wait);
+		return;
+	}
+
+	/* Reply with screen and cursor info */
+	if (msg->vid_hdr.type == SYNTHVID_FEATURE_CHANGE) {
+		if (par->fb_ready) {
+			synthvid_send_ptr(hdev);
+			synthvid_send_situ(hdev);
+		}
+
+		par->update = msg->feature_chg.is_dirt_needed;
+		if (par->update)
+			schedule_delayed_work(&par->dwork, HVFB_UPDATE_DELAY);
+	}
+}
+
+/* Receive callback for messages from the host */
+static void synthvid_receive(void *ctx)
+{
+	struct hv_device *hdev = ctx;
+	struct fb_info *info = hv_get_drvdata(hdev);
+	struct hvfb_par *par;
+	struct synthvid_msg *recv_buf;
+	u32 bytes_recvd;
+	u64 req_id;
+	int ret;
+
+	if (!info)
+		return;
+
+	par = info->par;
+	recv_buf = (struct synthvid_msg *)par->recv_buf;
+
+	do {
+		ret = vmbus_recvpacket(hdev->channel, recv_buf,
+				       MAX_VMBUS_PKT_SIZE,
+				       &bytes_recvd, &req_id);
+		if (bytes_recvd > 0 &&
+		    recv_buf->pipe_hdr.type == PIPE_MSG_DATA)
+			synthvid_recv_sub(hdev);
+	} while (bytes_recvd > 0 && ret == 0);
+}
+
+/* Check synthetic video protocol version with the host */
+static int synthvid_negotiate_ver(struct hv_device *hdev, u32 ver)
+{
+	struct fb_info *info = hv_get_drvdata(hdev);
+	struct hvfb_par *par = info->par;
+	struct synthvid_msg *msg = (struct synthvid_msg *)par->init_buf;
+	int t, ret = 0;
+
+	memset(msg, 0, sizeof(struct synthvid_msg));
+	msg->vid_hdr.type = SYNTHVID_VERSION_REQUEST;
+	msg->vid_hdr.size = sizeof(struct synthvid_msg_hdr) +
+		sizeof(struct synthvid_version_req);
+	msg->ver_req.version = ver;
+	synthvid_send(hdev, msg);
+
+	t = wait_for_completion_timeout(&par->wait, VSP_TIMEOUT);
+	if (!t) {
+		pr_err("Time out on waiting version response\n");
+		ret = -ETIMEDOUT;
+		goto out;
+	}
+	if (!msg->ver_resp.is_accepted) {
+		ret = -ENODEV;
+		goto out;
+	}
+
+	par->synthvid_version = ver;
+
+out:
+	return ret;
+}
+
+/* Connect to VSP (Virtual Service Provider) on host */
+static int synthvid_connect_vsp(struct hv_device *hdev)
+{
+	struct fb_info *info = hv_get_drvdata(hdev);
+	struct hvfb_par *par = info->par;
+	int ret;
+
+	ret = vmbus_open(hdev->channel, RING_BUFSIZE, RING_BUFSIZE,
+			 NULL, 0, synthvid_receive, hdev);
+	if (ret) {
+		pr_err("Unable to open vmbus channel\n");
+		return ret;
+	}
+
+	/* Negotiate the protocol version with host */
+	if (vmbus_proto_version == VERSION_WS2008 ||
+	    vmbus_proto_version == VERSION_WIN7)
+		ret = synthvid_negotiate_ver(hdev, SYNTHVID_VERSION_WIN7);
+	else
+		ret = synthvid_negotiate_ver(hdev, SYNTHVID_VERSION_WIN8);
+
+	if (ret) {
+		pr_err("Synthetic video device version not accepted\n");
+		goto error;
+	}
+
+	if (par->synthvid_version == SYNTHVID_VERSION_WIN7) {
+		screen_depth = SYNTHVID_DEPTH_WIN7;
+		screen_fb_size = SYNTHVID_FB_SIZE_WIN7;
+	} else {
+		screen_depth = SYNTHVID_DEPTH_WIN8;
+		screen_fb_size = SYNTHVID_FB_SIZE_WIN8;
+	}
+
+	return 0;
+
+error:
+	vmbus_close(hdev->channel);
+	return ret;
+}
+
+/* Send VRAM and Situation messages to the host */
+static int synthvid_send_config(struct hv_device *hdev)
+{
+	struct fb_info *info = hv_get_drvdata(hdev);
+	struct hvfb_par *par = info->par;
+	struct synthvid_msg *msg = (struct synthvid_msg *)par->init_buf;
+	int t, ret = 0;
+
+	/* Send VRAM location */
+	memset(msg, 0, sizeof(struct synthvid_msg));
+	msg->vid_hdr.type = SYNTHVID_VRAM_LOCATION;
+	msg->vid_hdr.size = sizeof(struct synthvid_msg_hdr) +
+		sizeof(struct synthvid_vram_location);
+	msg->vram.user_ctx = msg->vram.vram_gpa = info->fix.smem_start;
+	msg->vram.is_vram_gpa_specified = 1;
+	synthvid_send(hdev, msg);
+
+	t = wait_for_completion_timeout(&par->wait, VSP_TIMEOUT);
+	if (!t) {
+		pr_err("Time out on waiting vram location ack\n");
+		ret = -ETIMEDOUT;
+		goto out;
+	}
+	if (msg->vram_ack.user_ctx != info->fix.smem_start) {
+		pr_err("Unable to set VRAM location\n");
+		ret = -ENODEV;
+		goto out;
+	}
+
+	/* Send pointer and situation update */
+	synthvid_send_ptr(hdev);
+	synthvid_send_situ(hdev);
+
+out:
+	return ret;
+}
+
+
+/*
+ * Delayed work callback:
+ * It is called at HVFB_UPDATE_DELAY or longer time interval to process
+ * screen updates. It is re-scheduled if further update is necessary.
+ */
+static void hvfb_update_work(struct work_struct *w)
+{
+	struct hvfb_par *par = container_of(w, struct hvfb_par, dwork.work);
+	struct fb_info *info = par->info;
+
+	if (par->fb_ready)
+		synthvid_update(info);
+
+	if (par->update)
+		schedule_delayed_work(&par->dwork, HVFB_UPDATE_DELAY);
+}
+
+
+/* Framebuffer operation handlers */
+
+static int hvfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	if (var->xres < HVFB_WIDTH_MIN || var->yres < HVFB_HEIGHT_MIN ||
+	    var->xres > screen_width || var->yres >  screen_height ||
+	    var->bits_per_pixel != screen_depth)
+		return -EINVAL;
+
+	var->xres_virtual = var->xres;
+	var->yres_virtual = var->yres;
+
+	return 0;
+}
+
+static int hvfb_set_par(struct fb_info *info)
+{
+	struct hv_device *hdev = device_to_hv_device(info->device);
+
+	return synthvid_send_situ(hdev);
+}
+
+
+static inline u32 chan_to_field(u32 chan, struct fb_bitfield *bf)
+{
+	return ((chan & 0xffff) >> (16 - bf->length)) << bf->offset;
+}
+
+static int hvfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+			  unsigned blue, unsigned transp, struct fb_info *info)
+{
+	u32 *pal = info->pseudo_palette;
+
+	if (regno > 15)
+		return -EINVAL;
+
+	pal[regno] = chan_to_field(red, &info->var.red)
+		| chan_to_field(green, &info->var.green)
+		| chan_to_field(blue, &info->var.blue)
+		| chan_to_field(transp, &info->var.transp);
+
+	return 0;
+}
+
+
+static struct fb_ops hvfb_ops = {
+	.owner = THIS_MODULE,
+	.fb_check_var = hvfb_check_var,
+	.fb_set_par = hvfb_set_par,
+	.fb_setcolreg = hvfb_setcolreg,
+	.fb_fillrect = cfb_fillrect,
+	.fb_copyarea = cfb_copyarea,
+	.fb_imageblit = cfb_imageblit,
+};
+
+
+/* Get options from kernel paramenter "video=" */
+static void hvfb_get_option(struct fb_info *info)
+{
+	struct hvfb_par *par = info->par;
+	char *opt = NULL, *p;
+	uint x = 0, y = 0;
+
+	if (fb_get_options(KBUILD_MODNAME, &opt) || !opt || !*opt)
+		return;
+
+	p = strsep(&opt, "x");
+	if (!*p || kstrtouint(p, 0, &x) ||
+	    !opt || !*opt || kstrtouint(opt, 0, &y)) {
+		pr_err("Screen option is invalid: skipped\n");
+		return;
+	}
+
+	if (x < HVFB_WIDTH_MIN || y < HVFB_HEIGHT_MIN ||
+	    (par->synthvid_version == SYNTHVID_VERSION_WIN8 &&
+	     x * y * screen_depth / 8 > SYNTHVID_FB_SIZE_WIN8) ||
+	    (par->synthvid_version == SYNTHVID_VERSION_WIN7 &&
+	     (x > SYNTHVID_WIDTH_MAX_WIN7 || y > SYNTHVID_HEIGHT_MAX_WIN7))) {
+		pr_err("Screen resolution option is out of range: skipped\n");
+		return;
+	}
+
+	screen_width = x;
+	screen_height = y;
+	return;
+}
+
+
+/* Get framebuffer memory from Hyper-V video pci space */
+static int hvfb_getmem(struct fb_info *info)
+{
+	struct pci_dev *pdev;
+	ulong fb_phys;
+	void __iomem *fb_virt;
+
+	pdev = pci_get_device(PCI_VENDOR_ID_MICROSOFT,
+			      PCI_DEVICE_ID_HYPERV_VIDEO, NULL);
+	if (!pdev) {
+		pr_err("Unable to find PCI Hyper-V video\n");
+		return -ENODEV;
+	}
+
+	if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM) ||
+	    pci_resource_len(pdev, 0) < screen_fb_size)
+		goto err1;
+
+	fb_phys = pci_resource_end(pdev, 0) - screen_fb_size + 1;
+	if (!request_mem_region(fb_phys, screen_fb_size, KBUILD_MODNAME))
+		goto err1;
+
+	fb_virt = ioremap(fb_phys, screen_fb_size);
+	if (!fb_virt)
+		goto err2;
+
+	info->apertures = alloc_apertures(1);
+	if (!info->apertures)
+		goto err3;
+
+	info->apertures->ranges[0].base = pci_resource_start(pdev, 0);
+	info->apertures->ranges[0].size = pci_resource_len(pdev, 0);
+	info->fix.smem_start = fb_phys;
+	info->fix.smem_len = screen_fb_size;
+	info->screen_base = fb_virt;
+	info->screen_size = screen_fb_size;
+
+	pci_dev_put(pdev);
+	return 0;
+
+err3:
+	iounmap(fb_virt);
+err2:
+	release_mem_region(fb_phys, screen_fb_size);
+err1:
+	pci_dev_put(pdev);
+	return -ENOMEM;
+}
+
+/* Release the framebuffer */
+static void hvfb_putmem(struct fb_info *info)
+{
+	iounmap(info->screen_base);
+	release_mem_region(info->fix.smem_start, screen_fb_size);
+}
+
+
+static int hvfb_probe(struct hv_device *hdev,
+		      const struct hv_vmbus_device_id *dev_id)
+{
+	struct fb_info *info;
+	struct hvfb_par *par;
+	int ret;
+
+	info = framebuffer_alloc(sizeof(struct hvfb_par), &hdev->device);
+	if (!info) {
+		pr_err("No memory for framebuffer info\n");
+		return -ENOMEM;
+	}
+
+	par = info->par;
+	par->info = info;
+	par->fb_ready = false;
+	init_completion(&par->wait);
+	INIT_DELAYED_WORK(&par->dwork, hvfb_update_work);
+
+	/* Connect to VSP */
+	hv_set_drvdata(hdev, info);
+	ret = synthvid_connect_vsp(hdev);
+	if (ret) {
+		pr_err("Unable to connect to VSP\n");
+		goto error1;
+	}
+
+	ret = hvfb_getmem(info);
+	if (ret) {
+		pr_err("No memory for framebuffer\n");
+		goto error2;
+	}
+
+	hvfb_get_option(info);
+	pr_info("Screen resolution: %dx%d, Color depth: %d\n",
+		screen_width, screen_height, screen_depth);
+
+
+	/* Set up fb_info */
+	info->flags = FBINFO_DEFAULT;
+
+	info->var.xres_virtual = info->var.xres = screen_width;
+	info->var.yres_virtual = info->var.yres = screen_height;
+	info->var.bits_per_pixel = screen_depth;
+
+	if (info->var.bits_per_pixel == 16) {
+		info->var.red = (struct fb_bitfield){11, 5, 0};
+		info->var.green = (struct fb_bitfield){5, 6, 0};
+		info->var.blue = (struct fb_bitfield){0, 5, 0};
+		info->var.transp = (struct fb_bitfield){0, 0, 0};
+	} else {
+		info->var.red = (struct fb_bitfield){16, 8, 0};
+		info->var.green = (struct fb_bitfield){8, 8, 0};
+		info->var.blue = (struct fb_bitfield){0, 8, 0};
+		info->var.transp = (struct fb_bitfield){24, 8, 0};
+	}
+
+	info->var.activate = FB_ACTIVATE_NOW;
+	info->var.height = -1;
+	info->var.width = -1;
+	info->var.vmode = FB_VMODE_NONINTERLACED;
+
+	strcpy(info->fix.id, KBUILD_MODNAME);
+	info->fix.type = FB_TYPE_PACKED_PIXELS;
+	info->fix.visual = FB_VISUAL_TRUECOLOR;
+	info->fix.line_length = screen_width * screen_depth / 8;
+	info->fix.accel = FB_ACCEL_NONE;
+
+	info->fbops = &hvfb_ops;
+	info->pseudo_palette = par->pseudo_palette;
+
+	/* Send config to host */
+	ret = synthvid_send_config(hdev);
+	if (ret)
+		goto error;
+
+	ret = register_framebuffer(info);
+	if (ret) {
+		pr_err("Unable to register framebuffer\n");
+		goto error;
+	}
+
+	par->fb_ready = true;
+
+	return 0;
+
+error:
+	hvfb_putmem(info);
+error2:
+	vmbus_close(hdev->channel);
+error1:
+	cancel_delayed_work_sync(&par->dwork);
+	hv_set_drvdata(hdev, NULL);
+	framebuffer_release(info);
+	return ret;
+}
+
+
+static int hvfb_remove(struct hv_device *hdev)
+{
+	struct fb_info *info = hv_get_drvdata(hdev);
+	struct hvfb_par *par = info->par;
+
+	par->update = false;
+	par->fb_ready = false;
+
+	unregister_framebuffer(info);
+	cancel_delayed_work_sync(&par->dwork);
+
+	vmbus_close(hdev->channel);
+	hv_set_drvdata(hdev, NULL);
+
+	hvfb_putmem(info);
+	framebuffer_release(info);
+
+	return 0;
+}
+
+
+static const struct hv_vmbus_device_id id_table[] = {
+	/* Synthetic Video Device GUID */
+	{HV_SYNTHVID_GUID},
+	{}
+};
+
+MODULE_DEVICE_TABLE(vmbus, id_table);
+
+static struct hv_driver hvfb_drv = {
+	.name = KBUILD_MODNAME,
+	.id_table = id_table,
+	.probe = hvfb_probe,
+	.remove = hvfb_remove,
+};
+
+
+static int __init hvfb_drv_init(void)
+{
+	return vmbus_driver_register(&hvfb_drv);
+}
+
+static void __exit hvfb_drv_exit(void)
+{
+	vmbus_driver_unregister(&hvfb_drv);
+}
+
+module_init(hvfb_drv_init);
+module_exit(hvfb_drv_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_VERSION(HV_DRV_VERSION);
+MODULE_DESCRIPTION("Microsoft Hyper-V Synthetic Video Frame Buffer Driver");
diff --git a/drivers/video/matrox/matroxfb_maven.c b/drivers/video/matrox/matroxfb_maven.c
index 217678e..fd28974 100644
--- a/drivers/video/matrox/matroxfb_maven.c
+++ b/drivers/video/matrox/matroxfb_maven.c
@@ -137,8 +137,20 @@ static int* get_ctrl_ptr(struct maven_data* md, int idx) {
 
 static int maven_get_reg(struct i2c_client* c, char reg) {
 	char dst;
-	struct i2c_msg msgs[] = {{ c->addr, I2C_M_REV_DIR_ADDR, sizeof(reg), &reg },
-				 { c->addr, I2C_M_RD | I2C_M_NOSTART, sizeof(dst), &dst }};
+	struct i2c_msg msgs[] = {
+		{
+			.addr = c->addr,
+			.flags = I2C_M_REV_DIR_ADDR,
+			.len = sizeof(reg),
+			.buf = &reg
+		},
+		{
+			.addr = c->addr,
+			.flags = I2C_M_RD | I2C_M_NOSTART,
+			.len = sizeof(dst),
+			.buf = &dst
+		}
+	};
 	s32 err;
 
 	err = i2c_transfer(c->adapter, msgs, 2);
diff --git a/drivers/video/mmp/hw/mmp_ctrl.h b/drivers/video/mmp/hw/mmp_ctrl.h
index 6408d8e..edd2002 100644
--- a/drivers/video/mmp/hw/mmp_ctrl.h
+++ b/drivers/video/mmp/hw/mmp_ctrl.h
@@ -961,56 +961,7 @@ struct lcd_regs {
 	LCD_TVG_CUTVLN : PN2_LCD_GRA_CUTVLN) : LCD_GRA_CUTVLN)
 
 /*
- * defined Video Memory Color format for DMA control 0 register
- * DMA0 bit[23:20]
- */
-#define VMODE_RGB565		0x0
-#define VMODE_RGB1555		0x1
-#define VMODE_RGB888PACKED	0x2
-#define VMODE_RGB888UNPACKED	0x3
-#define VMODE_RGBA888		0x4
-#define VMODE_YUV422PACKED	0x5
-#define VMODE_YUV422PLANAR	0x6
-#define VMODE_YUV420PLANAR	0x7
-#define VMODE_SMPNCMD		0x8
-#define VMODE_PALETTE4BIT	0x9
-#define VMODE_PALETTE8BIT	0xa
-#define VMODE_RESERVED		0xb
-
-/*
- * defined Graphic Memory Color format for DMA control 0 register
- * DMA0 bit[19:16]
- */
-#define GMODE_RGB565		0x0
-#define GMODE_RGB1555		0x1
-#define GMODE_RGB888PACKED	0x2
-#define GMODE_RGB888UNPACKED	0x3
-#define GMODE_RGBA888		0x4
-#define GMODE_YUV422PACKED	0x5
-#define GMODE_YUV422PLANAR	0x6
-#define GMODE_YUV420PLANAR	0x7
-#define GMODE_SMPNCMD		0x8
-#define GMODE_PALETTE4BIT	0x9
-#define GMODE_PALETTE8BIT	0xa
-#define GMODE_RESERVED		0xb
-
-/*
- * define for DMA control 1 register
- */
-#define DMA1_FRAME_TRIG		31 /* bit location */
-#define DMA1_VSYNC_MODE		28
-#define DMA1_VSYNC_INV		27
-#define DMA1_CKEY		24
-#define DMA1_CARRY		23
-#define DMA1_LNBUF_ENA		22
-#define DMA1_GATED_ENA		21
-#define DMA1_PWRDN_ENA		20
-#define DMA1_DSCALE		18
-#define DMA1_ALPHA_MODE		16
-#define DMA1_ALPHA		08
-#define DMA1_PXLCMD		00
-
-/*
+ * defined for Configure Dumb Mode
  * defined for Configure Dumb Mode
  * DUMB LCD Panel bit[31:28]
  */
@@ -1050,18 +1001,6 @@ struct lcd_regs {
 #define	 CFG_CYC_BURST_LEN16			(1<<4)
 #define	 CFG_CYC_BURST_LEN8			(0<<4)
 
-/*
- * defined Dumb Panel Clock Divider register
- * SCLK_Source bit[31]
- */
- /* 0: PLL clock select*/
-#define AXI_BUS_SEL			0x80000000
-#define CCD_CLK_SEL			0x40000000
-#define DCON_CLK_SEL			0x20000000
-#define ENA_CLK_INT_DIV			CONFIG_FB_DOVE_CLCD_SCLK_DIV
-#define IDLE_CLK_INT_DIV		0x1	  /* idle Integer Divider */
-#define DIS_CLK_INT_DIV			0x0	  /* Disable Integer Divider */
-
 /* SRAM ID */
 #define SRAMID_GAMMA_YR			0x0
 #define SRAMID_GAMMA_UG			0x1
@@ -1471,422 +1410,6 @@ struct dsi_regs {
 #define LVDS_FREQ_OFFSET_MODE_CK_DIV4_OUT	(0x1 << 1)
 #define LVDS_FREQ_OFFSET_MODE_EN		(0x1 << 0)
 
-/* VDMA */
-struct vdma_ch_regs {
-#define VDMA_DC_SADDR_1		0x320
-#define VDMA_DC_SADDR_2		0x3A0
-#define VDMA_DC_SZ_1		0x324
-#define VDMA_DC_SZ_2		0x3A4
-#define VDMA_CTRL_1		0x328
-#define VDMA_CTRL_2		0x3A8
-#define VDMA_SRC_SZ_1		0x32C
-#define VDMA_SRC_SZ_2		0x3AC
-#define VDMA_SA_1		0x330
-#define VDMA_SA_2		0x3B0
-#define VDMA_DA_1		0x334
-#define VDMA_DA_2		0x3B4
-#define VDMA_SZ_1		0x338
-#define VDMA_SZ_2		0x3B8
-	u32	dc_saddr;
-	u32	dc_size;
-	u32	ctrl;
-	u32	src_size;
-	u32	src_addr;
-	u32	dst_addr;
-	u32	dst_size;
-#define VDMA_PITCH_1		0x33C
-#define VDMA_PITCH_2		0x3BC
-#define VDMA_ROT_CTRL_1		0x340
-#define VDMA_ROT_CTRL_2		0x3C0
-#define VDMA_RAM_CTRL0_1	0x344
-#define VDMA_RAM_CTRL0_2	0x3C4
-#define VDMA_RAM_CTRL1_1	0x348
-#define VDMA_RAM_CTRL1_2	0x3C8
-	u32	pitch;
-	u32	rot_ctrl;
-	u32	ram_ctrl0;
-	u32	ram_ctrl1;
-
-};
-struct vdma_regs {
-#define VDMA_ARBR_CTRL		0x300
-#define VDMA_IRQR		0x304
-#define VDMA_IRQM		0x308
-#define VDMA_IRQS		0x30C
-#define VDMA_MDMA_ARBR_CTRL	0x310
-	u32	arbr_ctr;
-	u32	irq_raw;
-	u32	irq_mask;
-	u32	irq_status;
-	u32	mdma_arbr_ctrl;
-	u32	reserved[3];
-
-	struct vdma_ch_regs	ch1;
-	u32	reserved2[21];
-	struct vdma_ch_regs	ch2;
-};
-
-/* CMU */
-#define CMU_PIP_DE_H_CFG	0x0008
-#define CMU_PRI1_H_CFG		0x000C
-#define CMU_PRI2_H_CFG		0x0010
-#define CMU_ACE_MAIN_DE1_H_CFG	0x0014
-#define CMU_ACE_MAIN_DE2_H_CFG	0x0018
-#define CMU_ACE_PIP_DE1_H_CFG	0x001C
-#define CMU_ACE_PIP_DE2_H_CFG	0x0020
-#define CMU_PIP_DE_V_CFG	0x0024
-#define CMU_PRI_V_CFG		0x0028
-#define CMU_ACE_MAIN_DE_V_CFG	0x002C
-#define CMU_ACE_PIP_DE_V_CFG	0x0030
-#define CMU_BAR_0_CFG		0x0034
-#define CMU_BAR_1_CFG		0x0038
-#define CMU_BAR_2_CFG		0x003C
-#define CMU_BAR_3_CFG		0x0040
-#define CMU_BAR_4_CFG		0x0044
-#define CMU_BAR_5_CFG		0x0048
-#define CMU_BAR_6_CFG		0x004C
-#define CMU_BAR_7_CFG		0x0050
-#define CMU_BAR_8_CFG		0x0054
-#define CMU_BAR_9_CFG		0x0058
-#define CMU_BAR_10_CFG		0x005C
-#define CMU_BAR_11_CFG		0x0060
-#define CMU_BAR_12_CFG		0x0064
-#define CMU_BAR_13_CFG		0x0068
-#define CMU_BAR_14_CFG		0x006C
-#define CMU_BAR_15_CFG		0x0070
-#define CMU_BAR_CTRL		0x0074
-#define PATTERN_TOTAL		0x0078
-#define PATTERN_ACTIVE		0x007C
-#define PATTERN_FRONT_PORCH	0x0080
-#define PATTERN_BACK_PORCH	0x0084
-#define CMU_CLK_CTRL		0x0088
-
-#define CMU_ICSC_M_C0_L		0x0900
-#define CMU_ICSC_M_C0_H		0x0901
-#define CMU_ICSC_M_C1_L		0x0902
-#define CMU_ICSC_M_C1_H		0x0903
-#define CMU_ICSC_M_C2_L		0x0904
-#define CMU_ICSC_M_C2_H		0x0905
-#define CMU_ICSC_M_C3_L		0x0906
-#define CMU_ICSC_M_C3_H		0x0907
-#define CMU_ICSC_M_C4_L		0x0908
-#define CMU_ICSC_M_C4_H		0x0909
-#define CMU_ICSC_M_C5_L		0x090A
-#define CMU_ICSC_M_C5_H		0x090B
-#define CMU_ICSC_M_C6_L		0x090C
-#define CMU_ICSC_M_C6_H		0x090D
-#define CMU_ICSC_M_C7_L		0x090E
-#define CMU_ICSC_M_C7_H		0x090F
-#define CMU_ICSC_M_C8_L		0x0910
-#define CMU_ICSC_M_C8_H		0x0911
-#define CMU_ICSC_M_O1_0		0x0914
-#define CMU_ICSC_M_O1_1		0x0915
-#define CMU_ICSC_M_O1_2		0x0916
-#define CMU_ICSC_M_O2_0		0x0918
-#define CMU_ICSC_M_O2_1		0x0919
-#define CMU_ICSC_M_O2_2		0x091A
-#define CMU_ICSC_M_O3_0		0x091C
-#define CMU_ICSC_M_O3_1		0x091D
-#define CMU_ICSC_M_O3_2		0x091E
-#define CMU_ICSC_P_C0_L		0x0920
-#define CMU_ICSC_P_C0_H		0x0921
-#define CMU_ICSC_P_C1_L		0x0922
-#define CMU_ICSC_P_C1_H		0x0923
-#define CMU_ICSC_P_C2_L		0x0924
-#define CMU_ICSC_P_C2_H		0x0925
-#define CMU_ICSC_P_C3_L		0x0926
-#define CMU_ICSC_P_C3_H		0x0927
-#define CMU_ICSC_P_C4_L		0x0928
-#define CMU_ICSC_P_C4_H		0x0929
-#define CMU_ICSC_P_C5_L		0x092A
-#define CMU_ICSC_P_C5_H		0x092B
-#define CMU_ICSC_P_C6_L		0x092C
-#define CMU_ICSC_P_C6_H		0x092D
-#define CMU_ICSC_P_C7_L		0x092E
-#define CMU_ICSC_P_C7_H		0x092F
-#define CMU_ICSC_P_C8_L		0x0930
-#define CMU_ICSC_P_C8_H		0x0931
-#define CMU_ICSC_P_O1_0		0x0934
-#define CMU_ICSC_P_O1_1		0x0935
-#define CMU_ICSC_P_O1_2		0x0936
-#define CMU_ICSC_P_O2_0		0x0938
-#define CMU_ICSC_P_O2_1		0x0939
-#define CMU_ICSC_P_O2_2		0x093A
-#define CMU_ICSC_P_O3_0		0x093C
-#define CMU_ICSC_P_O3_1		0x093D
-#define CMU_ICSC_P_O3_2		0x093E
-#define CMU_BR_M_EN		0x0940
-#define CMU_BR_M_TH1_L		0x0942
-#define CMU_BR_M_TH1_H		0x0943
-#define CMU_BR_M_TH2_L		0x0944
-#define CMU_BR_M_TH2_H		0x0945
-#define CMU_ACE_M_EN		0x0950
-#define CMU_ACE_M_WFG1		0x0951
-#define CMU_ACE_M_WFG2		0x0952
-#define CMU_ACE_M_WFG3		0x0953
-#define CMU_ACE_M_TH0		0x0954
-#define CMU_ACE_M_TH1		0x0955
-#define CMU_ACE_M_TH2		0x0956
-#define CMU_ACE_M_TH3		0x0957
-#define CMU_ACE_M_TH4		0x0958
-#define CMU_ACE_M_TH5		0x0959
-#define CMU_ACE_M_OP0_L		0x095A
-#define CMU_ACE_M_OP0_H		0x095B
-#define CMU_ACE_M_OP5_L		0x095C
-#define CMU_ACE_M_OP5_H		0x095D
-#define CMU_ACE_M_GB2		0x095E
-#define CMU_ACE_M_GB3		0x095F
-#define CMU_ACE_M_MS1		0x0960
-#define CMU_ACE_M_MS2		0x0961
-#define CMU_ACE_M_MS3		0x0962
-#define CMU_BR_P_EN		0x0970
-#define CMU_BR_P_TH1_L		0x0972
-#define CMU_BR_P_TH1_H		0x0973
-#define CMU_BR_P_TH2_L		0x0974
-#define CMU_BR_P_TH2_H		0x0975
-#define CMU_ACE_P_EN		0x0980
-#define CMU_ACE_P_WFG1		0x0981
-#define CMU_ACE_P_WFG2		0x0982
-#define CMU_ACE_P_WFG3		0x0983
-#define CMU_ACE_P_TH0		0x0984
-#define CMU_ACE_P_TH1		0x0985
-#define CMU_ACE_P_TH2		0x0986
-#define CMU_ACE_P_TH3		0x0987
-#define CMU_ACE_P_TH4		0x0988
-#define CMU_ACE_P_TH5		0x0989
-#define CMU_ACE_P_OP0_L		0x098A
-#define CMU_ACE_P_OP0_H		0x098B
-#define CMU_ACE_P_OP5_L		0x098C
-#define CMU_ACE_P_OP5_H		0x098D
-#define CMU_ACE_P_GB2		0x098E
-#define CMU_ACE_P_GB3		0x098F
-#define CMU_ACE_P_MS1		0x0990
-#define CMU_ACE_P_MS2		0x0991
-#define CMU_ACE_P_MS3		0x0992
-#define CMU_FTDC_M_EN		0x09A0
-#define CMU_FTDC_P_EN		0x09A1
-#define CMU_FTDC_INLOW_L	0x09A2
-#define CMU_FTDC_INLOW_H	0x09A3
-#define CMU_FTDC_INHIGH_L	0x09A4
-#define CMU_FTDC_INHIGH_H	0x09A5
-#define CMU_FTDC_OUTLOW_L	0x09A6
-#define CMU_FTDC_OUTLOW_H	0x09A7
-#define CMU_FTDC_OUTHIGH_L	0x09A8
-#define CMU_FTDC_OUTHIGH_H	0x09A9
-#define CMU_FTDC_YLOW		0x09AA
-#define CMU_FTDC_YHIGH		0x09AB
-#define CMU_FTDC_CH1		0x09AC
-#define CMU_FTDC_CH2_L		0x09AE
-#define CMU_FTDC_CH2_H		0x09AF
-#define CMU_FTDC_CH3_L		0x09B0
-#define CMU_FTDC_CH3_H		0x09B1
-#define CMU_FTDC_1_C00_6	0x09B2
-#define CMU_FTDC_1_C01_6	0x09B8
-#define CMU_FTDC_1_C11_6	0x09BE
-#define CMU_FTDC_1_C10_6	0x09C4
-#define CMU_FTDC_1_OFF00_6	0x09CA
-#define CMU_FTDC_1_OFF10_6	0x09D0
-#define CMU_HS_M_EN		0x0A00
-#define CMU_HS_M_AX1_L		0x0A02
-#define CMU_HS_M_AX1_H		0x0A03
-#define CMU_HS_M_AX2_L		0x0A04
-#define CMU_HS_M_AX2_H		0x0A05
-#define CMU_HS_M_AX3_L		0x0A06
-#define CMU_HS_M_AX3_H		0x0A07
-#define CMU_HS_M_AX4_L		0x0A08
-#define CMU_HS_M_AX4_H		0x0A09
-#define CMU_HS_M_AX5_L		0x0A0A
-#define CMU_HS_M_AX5_H		0x0A0B
-#define CMU_HS_M_AX6_L		0x0A0C
-#define CMU_HS_M_AX6_H		0x0A0D
-#define CMU_HS_M_AX7_L		0x0A0E
-#define CMU_HS_M_AX7_H		0x0A0F
-#define CMU_HS_M_AX8_L		0x0A10
-#define CMU_HS_M_AX8_H		0x0A11
-#define CMU_HS_M_AX9_L		0x0A12
-#define CMU_HS_M_AX9_H		0x0A13
-#define CMU_HS_M_AX10_L		0x0A14
-#define CMU_HS_M_AX10_H		0x0A15
-#define CMU_HS_M_AX11_L		0x0A16
-#define CMU_HS_M_AX11_H		0x0A17
-#define CMU_HS_M_AX12_L		0x0A18
-#define CMU_HS_M_AX12_H		0x0A19
-#define CMU_HS_M_AX13_L		0x0A1A
-#define CMU_HS_M_AX13_H		0x0A1B
-#define CMU_HS_M_AX14_L		0x0A1C
-#define CMU_HS_M_AX14_H		0x0A1D
-#define CMU_HS_M_H1_H14		0x0A1E
-#define CMU_HS_M_S1_S14		0x0A2C
-#define CMU_HS_M_GL		0x0A3A
-#define CMU_HS_M_MAXSAT_RGB_Y_L	0x0A3C
-#define CMU_HS_M_MAXSAT_RGB_Y_H	0x0A3D
-#define CMU_HS_M_MAXSAT_RCR_L	0x0A3E
-#define CMU_HS_M_MAXSAT_RCR_H	0x0A3F
-#define CMU_HS_M_MAXSAT_RCB_L	0x0A40
-#define CMU_HS_M_MAXSAT_RCB_H	0x0A41
-#define CMU_HS_M_MAXSAT_GCR_L	0x0A42
-#define CMU_HS_M_MAXSAT_GCR_H	0x0A43
-#define CMU_HS_M_MAXSAT_GCB_L	0x0A44
-#define CMU_HS_M_MAXSAT_GCB_H	0x0A45
-#define CMU_HS_M_MAXSAT_BCR_L	0x0A46
-#define CMU_HS_M_MAXSAT_BCR_H	0x0A47
-#define CMU_HS_M_MAXSAT_BCB_L	0x0A48
-#define CMU_HS_M_MAXSAT_BCB_H	0x0A49
-#define CMU_HS_M_ROFF_L		0x0A4A
-#define CMU_HS_M_ROFF_H		0x0A4B
-#define CMU_HS_M_GOFF_L		0x0A4C
-#define CMU_HS_M_GOFF_H		0x0A4D
-#define CMU_HS_M_BOFF_L		0x0A4E
-#define CMU_HS_M_BOFF_H		0x0A4F
-#define CMU_HS_P_EN		0x0A50
-#define CMU_HS_P_AX1_L		0x0A52
-#define CMU_HS_P_AX1_H		0x0A53
-#define CMU_HS_P_AX2_L		0x0A54
-#define CMU_HS_P_AX2_H		0x0A55
-#define CMU_HS_P_AX3_L		0x0A56
-#define CMU_HS_P_AX3_H		0x0A57
-#define CMU_HS_P_AX4_L		0x0A58
-#define CMU_HS_P_AX4_H		0x0A59
-#define CMU_HS_P_AX5_L		0x0A5A
-#define CMU_HS_P_AX5_H		0x0A5B
-#define CMU_HS_P_AX6_L		0x0A5C
-#define CMU_HS_P_AX6_H		0x0A5D
-#define CMU_HS_P_AX7_L		0x0A5E
-#define CMU_HS_P_AX7_H		0x0A5F
-#define CMU_HS_P_AX8_L		0x0A60
-#define CMU_HS_P_AX8_H		0x0A61
-#define CMU_HS_P_AX9_L		0x0A62
-#define CMU_HS_P_AX9_H		0x0A63
-#define CMU_HS_P_AX10_L		0x0A64
-#define CMU_HS_P_AX10_H		0x0A65
-#define CMU_HS_P_AX11_L		0x0A66
-#define CMU_HS_P_AX11_H		0x0A67
-#define CMU_HS_P_AX12_L		0x0A68
-#define CMU_HS_P_AX12_H		0x0A69
-#define CMU_HS_P_AX13_L		0x0A6A
-#define CMU_HS_P_AX13_H		0x0A6B
-#define CMU_HS_P_AX14_L		0x0A6C
-#define CMU_HS_P_AX14_H		0x0A6D
-#define CMU_HS_P_H1_H14		0x0A6E
-#define CMU_HS_P_S1_S14		0x0A7C
-#define CMU_HS_P_GL		0x0A8A
-#define CMU_HS_P_MAXSAT_RGB_Y_L	0x0A8C
-#define CMU_HS_P_MAXSAT_RGB_Y_H	0x0A8D
-#define CMU_HS_P_MAXSAT_RCR_L	0x0A8E
-#define CMU_HS_P_MAXSAT_RCR_H	0x0A8F
-#define CMU_HS_P_MAXSAT_RCB_L	0x0A90
-#define CMU_HS_P_MAXSAT_RCB_H	0x0A91
-#define CMU_HS_P_MAXSAT_GCR_L	0x0A92
-#define CMU_HS_P_MAXSAT_GCR_H	0x0A93
-#define CMU_HS_P_MAXSAT_GCB_L	0x0A94
-#define CMU_HS_P_MAXSAT_GCB_H	0x0A95
-#define CMU_HS_P_MAXSAT_BCR_L	0x0A96
-#define CMU_HS_P_MAXSAT_BCR_H	0x0A97
-#define CMU_HS_P_MAXSAT_BCB_L	0x0A98
-#define CMU_HS_P_MAXSAT_BCB_H	0x0A99
-#define CMU_HS_P_ROFF_L		0x0A9A
-#define CMU_HS_P_ROFF_H		0x0A9B
-#define CMU_HS_P_GOFF_L		0x0A9C
-#define CMU_HS_P_GOFF_H		0x0A9D
-#define CMU_HS_P_BOFF_L		0x0A9E
-#define CMU_HS_P_BOFF_H		0x0A9F
-#define CMU_GLCSC_M_C0_L	0x0AA0
-#define CMU_GLCSC_M_C0_H	0x0AA1
-#define CMU_GLCSC_M_C1_L	0x0AA2
-#define CMU_GLCSC_M_C1_H	0x0AA3
-#define CMU_GLCSC_M_C2_L	0x0AA4
-#define CMU_GLCSC_M_C2_H	0x0AA5
-#define CMU_GLCSC_M_C3_L	0x0AA6
-#define CMU_GLCSC_M_C3_H	0x0AA7
-#define CMU_GLCSC_M_C4_L	0x0AA8
-#define CMU_GLCSC_M_C4_H	0x0AA9
-#define CMU_GLCSC_M_C5_L	0x0AAA
-#define CMU_GLCSC_M_C5_H	0x0AAB
-#define CMU_GLCSC_M_C6_L	0x0AAC
-#define CMU_GLCSC_M_C6_H	0x0AAD
-#define CMU_GLCSC_M_C7_L	0x0AAE
-#define CMU_GLCSC_M_C7_H	0x0AAF
-#define CMU_GLCSC_M_C8_L	0x0AB0
-#define CMU_GLCSC_M_C8_H	0x0AB1
-#define CMU_GLCSC_M_O1_1	0x0AB4
-#define CMU_GLCSC_M_O1_2	0x0AB5
-#define CMU_GLCSC_M_O1_3	0x0AB6
-#define CMU_GLCSC_M_O2_1	0x0AB8
-#define CMU_GLCSC_M_O2_2	0x0AB9
-#define CMU_GLCSC_M_O2_3	0x0ABA
-#define CMU_GLCSC_M_O3_1	0x0ABC
-#define CMU_GLCSC_M_O3_2	0x0ABD
-#define CMU_GLCSC_M_O3_3	0x0ABE
-#define CMU_GLCSC_P_C0_L	0x0AC0
-#define CMU_GLCSC_P_C0_H	0x0AC1
-#define CMU_GLCSC_P_C1_L	0x0AC2
-#define CMU_GLCSC_P_C1_H	0x0AC3
-#define CMU_GLCSC_P_C2_L	0x0AC4
-#define CMU_GLCSC_P_C2_H	0x0AC5
-#define CMU_GLCSC_P_C3_L	0x0AC6
-#define CMU_GLCSC_P_C3_H	0x0AC7
-#define CMU_GLCSC_P_C4_L	0x0AC8
-#define CMU_GLCSC_P_C4_H	0x0AC9
-#define CMU_GLCSC_P_C5_L	0x0ACA
-#define CMU_GLCSC_P_C5_H	0x0ACB
-#define CMU_GLCSC_P_C6_L	0x0ACC
-#define CMU_GLCSC_P_C6_H	0x0ACD
-#define CMU_GLCSC_P_C7_L	0x0ACE
-#define CMU_GLCSC_P_C7_H	0x0ACF
-#define CMU_GLCSC_P_C8_L	0x0AD0
-#define CMU_GLCSC_P_C8_H	0x0AD1
-#define CMU_GLCSC_P_O1_1	0x0AD4
-#define CMU_GLCSC_P_O1_2	0x0AD5
-#define CMU_GLCSC_P_O1_3	0x0AD6
-#define CMU_GLCSC_P_O2_1	0x0AD8
-#define CMU_GLCSC_P_O2_2	0x0AD9
-#define CMU_GLCSC_P_O2_3	0x0ADA
-#define CMU_GLCSC_P_O3_1	0x0ADC
-#define CMU_GLCSC_P_O3_2	0x0ADD
-#define CMU_GLCSC_P_O3_3	0x0ADE
-#define CMU_PIXVAL_M_EN		0x0AE0
-#define CMU_PIXVAL_P_EN		0x0AE1
-
-#define CMU_CLK_CTRL_TCLK	0x0
-#define CMU_CLK_CTRL_SCLK	0x2
-#define CMU_CLK_CTRL_MSK	0x2
-#define CMU_CLK_CTRL_ENABLE	0x1
-
-#define LCD_TOP_CTRL_TV		0x2
-#define LCD_TOP_CTRL_PN		0x0
-#define LCD_TOP_CTRL_SEL_MSK	0x2
-#define LCD_IO_CMU_IN_SEL_MSK	(0x3 << 20)
-#define LCD_IO_CMU_IN_SEL_TV	0
-#define LCD_IO_CMU_IN_SEL_PN	1
-#define LCD_IO_CMU_IN_SEL_PN2	2
-#define LCD_IO_TV_OUT_SEL_MSK	(0x3 << 26)
-#define LCD_IO_PN_OUT_SEL_MSK	(0x3 << 24)
-#define LCD_IO_PN2_OUT_SEL_MSK	(0x3 << 28)
-#define LCD_IO_TV_OUT_SEL_NON	3
-#define LCD_IO_PN_OUT_SEL_NON	3
-#define LCD_IO_PN2_OUT_SEL_NON	3
-#define LCD_TOP_CTRL_CMU_ENABLE 0x1
-#define LCD_IO_OVERL_MSK	0xC00000
-#define LCD_IO_OVERL_TV		0x0
-#define LCD_IO_OVERL_LCD1	0x400000
-#define LCD_IO_OVERL_LCD2	0xC00000
-#define HINVERT_MSK		0x4
-#define VINVERT_MSK		0x8
-#define HINVERT_LEN		0x2
-#define VINVERT_LEN		0x3
-
-#define CMU_CTRL		0x88
-#define CMU_CTRL_A0_MSK		0x6
-#define CMU_CTRL_A0_TV		0x0
-#define CMU_CTRL_A0_LCD1	0x1
-#define CMU_CTRL_A0_LCD2	0x2
-#define CMU_CTRL_A0_HDMI	0x3
-
-#define ICR_DRV_ROUTE_OFF	0x0
-#define ICR_DRV_ROUTE_TV	0x1
-#define ICR_DRV_ROUTE_LCD1	0x2
-#define ICR_DRV_ROUTE_LCD2	0x3
-
 enum {
 	PATH_PN = 0,
 	PATH_TV,
diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c
index 45169cb..eac7c1a 100644
--- a/drivers/video/mxsfb.c
+++ b/drivers/video/mxsfb.c
@@ -43,12 +43,14 @@
 #include <linux/kernel.h>
 #include <linux/of_device.h>
 #include <linux/of_gpio.h>
+#include <video/of_display_timing.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
 #include <linux/dma-mapping.h>
 #include <linux/io.h>
 #include <linux/pinctrl/consumer.h>
-#include <linux/mxsfb.h>
+#include <linux/fb.h>
+#include <video/videomode.h>
 
 #define REG_SET	4
 #define REG_CLR	8
@@ -107,7 +109,7 @@
 #define VDCTRL0_ENABLE_PRESENT		(1 << 28)
 #define VDCTRL0_VSYNC_ACT_HIGH		(1 << 27)
 #define VDCTRL0_HSYNC_ACT_HIGH		(1 << 26)
-#define VDCTRL0_DOTCLK_ACT_FAILING	(1 << 25)
+#define VDCTRL0_DOTCLK_ACT_FALLING	(1 << 25)
 #define VDCTRL0_ENABLE_ACT_HIGH		(1 << 24)
 #define VDCTRL0_VSYNC_PERIOD_UNIT	(1 << 21)
 #define VDCTRL0_VSYNC_PULSE_WIDTH_UNIT	(1 << 20)
@@ -142,6 +144,14 @@
 #define BLUE 2
 #define TRANSP 3
 
+#define STMLCDIF_8BIT  1 /** pixel data bus to the display is of 8 bit width */
+#define STMLCDIF_16BIT 0 /** pixel data bus to the display is of 16 bit width */
+#define STMLCDIF_18BIT 2 /** pixel data bus to the display is of 18 bit width */
+#define STMLCDIF_24BIT 3 /** pixel data bus to the display is of 24 bit width */
+
+#define MXSFB_SYNC_DATA_ENABLE_HIGH_ACT	(1 << 6)
+#define MXSFB_SYNC_DOTCLK_FALLING_ACT	(1 << 7) /* negtive edge sampling */
+
 enum mxsfb_devtype {
 	MXSFB_V3,
 	MXSFB_V4,
@@ -168,7 +178,6 @@ struct mxsfb_info {
 	unsigned ld_intf_width;
 	unsigned dotclk_delay;
 	const struct mxsfb_devdata *devdata;
-	int mapped;
 	u32 sync;
 };
 
@@ -459,8 +468,8 @@ static int mxsfb_set_par(struct fb_info *fb_info)
 		vdctrl0 |= VDCTRL0_VSYNC_ACT_HIGH;
 	if (host->sync & MXSFB_SYNC_DATA_ENABLE_HIGH_ACT)
 		vdctrl0 |= VDCTRL0_ENABLE_ACT_HIGH;
-	if (host->sync & MXSFB_SYNC_DOTCLK_FAILING_ACT)
-		vdctrl0 |= VDCTRL0_DOTCLK_ACT_FAILING;
+	if (host->sync & MXSFB_SYNC_DOTCLK_FALLING_ACT)
+		vdctrl0 |= VDCTRL0_DOTCLK_ACT_FALLING;
 
 	writel(vdctrl0, host->base + LCDC_VDCTRL0);
 
@@ -679,14 +688,105 @@ static int mxsfb_restore_mode(struct mxsfb_info *host)
 	return 0;
 }
 
+static int mxsfb_init_fbinfo_dt(struct mxsfb_info *host)
+{
+	struct fb_info *fb_info = &host->fb_info;
+	struct fb_var_screeninfo *var = &fb_info->var;
+	struct device *dev = &host->pdev->dev;
+	struct device_node *np = host->pdev->dev.of_node;
+	struct device_node *display_np;
+	struct device_node *timings_np;
+	struct display_timings *timings;
+	u32 width;
+	int i;
+	int ret = 0;
+
+	display_np = of_parse_phandle(np, "display", 0);
+	if (!display_np) {
+		dev_err(dev, "failed to find display phandle\n");
+		return -ENOENT;
+	}
+
+	ret = of_property_read_u32(display_np, "bus-width", &width);
+	if (ret < 0) {
+		dev_err(dev, "failed to get property bus-width\n");
+		goto put_display_node;
+	}
+
+	switch (width) {
+	case 8:
+		host->ld_intf_width = STMLCDIF_8BIT;
+		break;
+	case 16:
+		host->ld_intf_width = STMLCDIF_16BIT;
+		break;
+	case 18:
+		host->ld_intf_width = STMLCDIF_18BIT;
+		break;
+	case 24:
+		host->ld_intf_width = STMLCDIF_24BIT;
+		break;
+	default:
+		dev_err(dev, "invalid bus-width value\n");
+		ret = -EINVAL;
+		goto put_display_node;
+	}
+
+	ret = of_property_read_u32(display_np, "bits-per-pixel",
+				   &var->bits_per_pixel);
+	if (ret < 0) {
+		dev_err(dev, "failed to get property bits-per-pixel\n");
+		goto put_display_node;
+	}
+
+	timings = of_get_display_timings(display_np);
+	if (!timings) {
+		dev_err(dev, "failed to get display timings\n");
+		ret = -ENOENT;
+		goto put_display_node;
+	}
+
+	timings_np = of_find_node_by_name(display_np,
+					  "display-timings");
+	if (!timings_np) {
+		dev_err(dev, "failed to find display-timings node\n");
+		ret = -ENOENT;
+		goto put_display_node;
+	}
+
+	for (i = 0; i < of_get_child_count(timings_np); i++) {
+		struct videomode vm;
+		struct fb_videomode fb_vm;
+
+		ret = videomode_from_timing(timings, &vm, i);
+		if (ret < 0)
+			goto put_timings_node;
+		ret = fb_videomode_from_videomode(&vm, &fb_vm);
+		if (ret < 0)
+			goto put_timings_node;
+
+		if (vm.data_flags & DISPLAY_FLAGS_DE_HIGH)
+			host->sync |= MXSFB_SYNC_DATA_ENABLE_HIGH_ACT;
+		if (vm.data_flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE)
+			host->sync |= MXSFB_SYNC_DOTCLK_FALLING_ACT;
+		fb_add_videomode(&fb_vm, &fb_info->modelist);
+	}
+
+put_timings_node:
+	of_node_put(timings_np);
+put_display_node:
+	of_node_put(display_np);
+	return ret;
+}
+
 static int mxsfb_init_fbinfo(struct mxsfb_info *host)
 {
 	struct fb_info *fb_info = &host->fb_info;
 	struct fb_var_screeninfo *var = &fb_info->var;
-	struct mxsfb_platform_data *pdata = host->pdev->dev.platform_data;
 	dma_addr_t fb_phys;
 	void *fb_virt;
-	unsigned fb_size = pdata->fb_size;
+	unsigned fb_size;
+	int ret;
 
 	fb_info->fbops = &mxsfb_ops;
 	fb_info->flags = FBINFO_FLAG_DEFAULT | FBINFO_READS_FAST;
@@ -696,40 +796,22 @@ static int mxsfb_init_fbinfo(struct mxsfb_info *host)
 	fb_info->fix.visual = FB_VISUAL_TRUECOLOR,
 	fb_info->fix.accel = FB_ACCEL_NONE;
 
-	var->bits_per_pixel = pdata->default_bpp ? pdata->default_bpp : 16;
+	ret = mxsfb_init_fbinfo_dt(host);
+	if (ret)
+		return ret;
+
 	var->nonstd = 0;
 	var->activate = FB_ACTIVATE_NOW;
 	var->accel_flags = 0;
 	var->vmode = FB_VMODE_NONINTERLACED;
 
-	host->dotclk_delay = pdata->dotclk_delay;
-	host->ld_intf_width = pdata->ld_intf_width;
-
 	/* Memory allocation for framebuffer */
-	if (pdata->fb_phys) {
-		if (!fb_size)
-			return -EINVAL;
-
-		fb_phys = pdata->fb_phys;
+	fb_size = SZ_2M;
+	fb_virt = alloc_pages_exact(fb_size, GFP_DMA);
+	if (!fb_virt)
+		return -ENOMEM;
 
-		if (!request_mem_region(fb_phys, fb_size, host->pdev->name))
-			return -ENOMEM;
-
-		fb_virt = ioremap(fb_phys, fb_size);
-		if (!fb_virt) {
-			release_mem_region(fb_phys, fb_size);
-			return -ENOMEM;
-		}
-		host->mapped = 1;
-	} else {
-		if (!fb_size)
-			fb_size = SZ_2M; /* default */
-		fb_virt = alloc_pages_exact(fb_size, GFP_DMA);
-		if (!fb_virt)
-			return -ENOMEM;
-
-		fb_phys = virt_to_phys(fb_virt);
-	}
+	fb_phys = virt_to_phys(fb_virt);
 
 	fb_info->fix.smem_start = fb_phys;
 	fb_info->screen_base = fb_virt;
@@ -745,13 +827,7 @@ static void mxsfb_free_videomem(struct mxsfb_info *host)
 {
 	struct fb_info *fb_info = &host->fb_info;
 
-	if (host->mapped) {
-		iounmap(fb_info->screen_base);
-		release_mem_region(fb_info->fix.smem_start,
-				fb_info->screen_size);
-	} else {
-		free_pages_exact(fb_info->screen_base, fb_info->fix.smem_len);
-	}
+	free_pages_exact(fb_info->screen_base, fb_info->fix.smem_len);
 }
 
 static struct platform_device_id mxsfb_devtype[] = {
@@ -778,7 +854,6 @@ static int mxsfb_probe(struct platform_device *pdev)
 {
 	const struct of_device_id *of_id =
 			of_match_device(mxsfb_dt_ids, &pdev->dev);
-	struct mxsfb_platform_data *pdata = pdev->dev.platform_data;
 	struct resource *res;
 	struct mxsfb_info *host;
 	struct fb_info *fb_info;
@@ -786,39 +861,30 @@ static int mxsfb_probe(struct platform_device *pdev)
 	struct pinctrl *pinctrl;
 	int panel_enable;
 	enum of_gpio_flags flags;
-	int i, ret;
+	int ret;
 
 	if (of_id)
 		pdev->id_entry = of_id->data;
 
-	if (!pdata) {
-		dev_err(&pdev->dev, "No platformdata. Giving up\n");
-		return -ENODEV;
-	}
-
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res) {
 		dev_err(&pdev->dev, "Cannot get memory IO resource\n");
 		return -ENODEV;
 	}
 
-	if (!request_mem_region(res->start, resource_size(res), pdev->name))
-		return -EBUSY;
-
 	fb_info = framebuffer_alloc(sizeof(struct mxsfb_info), &pdev->dev);
 	if (!fb_info) {
 		dev_err(&pdev->dev, "Failed to allocate fbdev\n");
-		ret = -ENOMEM;
-		goto error_alloc_info;
+		return -ENOMEM;
 	}
 
 	host = to_imxfb_host(fb_info);
 
-	host->base = ioremap(res->start, resource_size(res));
-	if (!host->base) {
+	host->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(host->base)) {
 		dev_err(&pdev->dev, "ioremap failed\n");
-		ret = -ENOMEM;
-		goto error_ioremap;
+		ret = PTR_ERR(host->base);
+		goto fb_release;
 	}
 
 	host->pdev = pdev;
@@ -829,13 +895,13 @@ static int mxsfb_probe(struct platform_device *pdev)
 	pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
 	if (IS_ERR(pinctrl)) {
 		ret = PTR_ERR(pinctrl);
-		goto error_getpin;
+		goto fb_release;
 	}
 
-	host->clk = clk_get(&host->pdev->dev, NULL);
+	host->clk = devm_clk_get(&host->pdev->dev, NULL);
 	if (IS_ERR(host->clk)) {
 		ret = PTR_ERR(host->clk);
-		goto error_getclock;
+		goto fb_release;
 	}
 
 	panel_enable = of_get_named_gpio_flags(pdev->dev.of_node,
@@ -850,26 +916,22 @@ static int mxsfb_probe(struct platform_device *pdev)
 			dev_err(&pdev->dev,
 				"failed to request gpio %d: %d\n",
 				panel_enable, ret);
-			goto error_panel_enable;
+			goto fb_release;
 		}
 	}
 
-	fb_info->pseudo_palette = kmalloc(sizeof(u32) * 16, GFP_KERNEL);
+	fb_info->pseudo_palette = devm_kzalloc(&pdev->dev, sizeof(u32) * 16,
+					       GFP_KERNEL);
 	if (!fb_info->pseudo_palette) {
 		ret = -ENOMEM;
-		goto error_pseudo_pallette;
+		goto fb_release;
 	}
 
 	INIT_LIST_HEAD(&fb_info->modelist);
 
-	host->sync = pdata->sync;
-
 	ret = mxsfb_init_fbinfo(host);
 	if (ret != 0)
-		goto error_init_fb;
-
-	for (i = 0; i < pdata->mode_count; i++)
-		fb_add_videomode(&pdata->mode_list[i], &fb_info->modelist);
+		goto fb_release;
 
 	modelist = list_first_entry(&fb_info->modelist,
 			struct fb_modelist, list);
@@ -883,7 +945,7 @@ static int mxsfb_probe(struct platform_device *pdev)
 	ret = register_framebuffer(fb_info);
 	if (ret != 0) {
 		dev_err(&pdev->dev,"Failed to register framebuffer\n");
-		goto error_register;
+		goto fb_destroy;
 	}
 
 	if (!host->enabled) {
@@ -896,22 +958,12 @@ static int mxsfb_probe(struct platform_device *pdev)
 
 	return 0;
 
-error_register:
+fb_destroy:
 	if (host->enabled)
 		clk_disable_unprepare(host->clk);
 	fb_destroy_modelist(&fb_info->modelist);
-error_init_fb:
-	kfree(fb_info->pseudo_palette);
-error_pseudo_pallette:
-error_panel_enable:
-	clk_put(host->clk);
-error_getclock:
-error_getpin:
-	iounmap(host->base);
-error_ioremap:
+fb_release:
 	framebuffer_release(fb_info);
-error_alloc_info:
-	release_mem_region(res->start, resource_size(res));
 
 	return ret;
 }
@@ -920,19 +972,14 @@ static int mxsfb_remove(struct platform_device *pdev)
 {
 	struct fb_info *fb_info = platform_get_drvdata(pdev);
 	struct mxsfb_info *host = to_imxfb_host(fb_info);
-	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
 	if (host->enabled)
 		mxsfb_disable_controller(fb_info);
 
 	unregister_framebuffer(fb_info);
-	kfree(fb_info->pseudo_palette);
 	mxsfb_free_videomem(host);
-	iounmap(host->base);
-	clk_put(host->clk);
 
 	framebuffer_release(fb_info);
-	release_mem_region(res->start, resource_size(res));
 
 	platform_set_drvdata(pdev, NULL);
 
diff --git a/drivers/video/omap/Kconfig b/drivers/video/omap/Kconfig
index e512581..0bc3a93 100644
--- a/drivers/video/omap/Kconfig
+++ b/drivers/video/omap/Kconfig
@@ -39,17 +39,6 @@ config FB_OMAP_LCD_MIPID
 	  the Mobile Industry Processor Interface DBI-C/DCS
 	  specification. (Supported LCDs: Philips LPH8923, Sharp LS041Y3)
 
-config FB_OMAP_CONSISTENT_DMA_SIZE
-	int "Consistent DMA memory size (MB)"
-	depends on FB_OMAP
-	range 1 14
-	default 2
-	help
-	  Increase the DMA consistent memory size according to your video
-	  memory needs, for example if you want to use multiple planes.
-	  The size must be 2MB aligned.
-	  If unsure say 1.
-
 config FB_OMAP_DMA_TUNE
         bool "Set DMA SDRAM access priority high"
         depends on FB_OMAP
diff --git a/drivers/video/omap2/displays/panel-acx565akm.c b/drivers/video/omap2/displays/panel-acx565akm.c
index 72699f8..d7f69c0 100644
--- a/drivers/video/omap2/displays/panel-acx565akm.c
+++ b/drivers/video/omap2/displays/panel-acx565akm.c
@@ -29,8 +29,10 @@
 #include <linux/sched.h>
 #include <linux/backlight.h>
 #include <linux/fb.h>
+#include <linux/gpio.h>
 
 #include <video/omapdss.h>
+#include <video/omap-panel-data.h>
 
 #define MIPID_CMD_READ_DISP_ID		0x04
 #define MIPID_CMD_READ_RED		0x06
@@ -336,8 +338,6 @@ static int acx565akm_bl_update_status(struct backlight_device *dev)
 	r = 0;
 	if (md->has_bc)
 		acx565akm_set_brightness(md, level);
-	else if (md->dssdev->set_backlight)
-		r = md->dssdev->set_backlight(md->dssdev, level);
 	else
 		r = -ENODEV;
 
@@ -352,7 +352,7 @@ static int acx565akm_bl_get_intensity(struct backlight_device *dev)
 
 	dev_dbg(&dev->dev, "%s\n", __func__);
 
-	if (!md->has_bc && md->dssdev->set_backlight == NULL)
+	if (!md->has_bc)
 		return -ENODEV;
 
 	if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
@@ -496,21 +496,38 @@ static struct omap_video_timings acx_panel_timings = {
 	.sync_pclk_edge	= OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
 };
 
+static struct panel_acx565akm_data *get_panel_data(struct omap_dss_device *dssdev)
+{
+	return (struct panel_acx565akm_data *) dssdev->data;
+}
+
 static int acx_panel_probe(struct omap_dss_device *dssdev)
 {
 	int r;
 	struct acx565akm_device *md = &acx_dev;
+	struct panel_acx565akm_data *panel_data = get_panel_data(dssdev);
 	struct backlight_device *bldev;
 	int max_brightness, brightness;
 	struct backlight_properties props;
 
 	dev_dbg(&dssdev->dev, "%s\n", __func__);
 
+	if (!panel_data)
+		return -EINVAL;
+
 	/* FIXME AC bias ? */
 	dssdev->panel.timings = acx_panel_timings;
 
-	if (dssdev->platform_enable)
-		dssdev->platform_enable(dssdev);
+	if (gpio_is_valid(panel_data->reset_gpio)) {
+		r = devm_gpio_request_one(&dssdev->dev, panel_data->reset_gpio,
+				GPIOF_OUT_INIT_LOW, "lcd reset");
+		if (r)
+			return r;
+	}
+
+	if (gpio_is_valid(panel_data->reset_gpio))
+		gpio_set_value(panel_data->reset_gpio, 1);
+
 	/*
 	 * After reset we have to wait 5 msec before the first
 	 * command can be sent.
@@ -522,8 +539,9 @@ static int acx_panel_probe(struct omap_dss_device *dssdev)
 	r = panel_detect(md);
 	if (r) {
 		dev_err(&dssdev->dev, "%s panel detect error\n", __func__);
-		if (!md->enabled && dssdev->platform_disable)
-			dssdev->platform_disable(dssdev);
+		if (!md->enabled && gpio_is_valid(panel_data->reset_gpio))
+			gpio_set_value(panel_data->reset_gpio, 0);
+
 		return r;
 	}
 
@@ -532,8 +550,8 @@ static int acx_panel_probe(struct omap_dss_device *dssdev)
 	mutex_unlock(&acx_dev.mutex);
 
 	if (!md->enabled) {
-		if (dssdev->platform_disable)
-			dssdev->platform_disable(dssdev);
+		if (gpio_is_valid(panel_data->reset_gpio))
+			gpio_set_value(panel_data->reset_gpio, 0);
 	}
 
 	/*------- Backlight control --------*/
@@ -557,15 +575,10 @@ static int acx_panel_probe(struct omap_dss_device *dssdev)
 		md->cabc_mode = get_hw_cabc_mode(md);
 	}
 
-	if (md->has_bc)
-		max_brightness = 255;
-	else
-		max_brightness = dssdev->max_backlight_level;
+	max_brightness = 255;
 
 	if (md->has_bc)
 		brightness = acx565akm_get_actual_brightness(md);
-	else if (dssdev->get_backlight)
-		brightness = dssdev->get_backlight(dssdev);
 	else
 		brightness = 0;
 
@@ -591,6 +604,7 @@ static void acx_panel_remove(struct omap_dss_device *dssdev)
 static int acx_panel_power_on(struct omap_dss_device *dssdev)
 {
 	struct acx565akm_device *md = &acx_dev;
+	struct panel_acx565akm_data *panel_data = get_panel_data(dssdev);
 	int r;
 
 	dev_dbg(&dssdev->dev, "%s\n", __func__);
@@ -612,11 +626,8 @@ static int acx_panel_power_on(struct omap_dss_device *dssdev)
 	/*FIXME tweak me */
 	msleep(50);
 
-	if (dssdev->platform_enable) {
-		r = dssdev->platform_enable(dssdev);
-		if (r)
-			goto fail;
-	}
+	if (gpio_is_valid(panel_data->reset_gpio))
+		gpio_set_value(panel_data->reset_gpio, 1);
 
 	if (md->enabled) {
 		dev_dbg(&md->spi->dev, "panel already enabled\n");
@@ -645,8 +656,7 @@ static int acx_panel_power_on(struct omap_dss_device *dssdev)
 	mutex_unlock(&md->mutex);
 
 	return acx565akm_bl_update_status(md->bl_dev);
-fail:
-	omapdss_sdi_display_disable(dssdev);
+
 fail_unlock:
 	mutex_unlock(&md->mutex);
 	return r;
@@ -655,6 +665,7 @@ fail_unlock:
 static void acx_panel_power_off(struct omap_dss_device *dssdev)
 {
 	struct acx565akm_device *md = &acx_dev;
+	struct panel_acx565akm_data *panel_data = get_panel_data(dssdev);
 
 	dev_dbg(&dssdev->dev, "%s\n", __func__);
 
@@ -678,8 +689,8 @@ static void acx_panel_power_off(struct omap_dss_device *dssdev)
 	 */
 	msleep(50);
 
-	if (dssdev->platform_disable)
-		dssdev->platform_disable(dssdev);
+	if (gpio_is_valid(panel_data->reset_gpio))
+		gpio_set_value(panel_data->reset_gpio, 0);
 
 	/* FIXME need to tweak this delay */
 	msleep(100);
diff --git a/drivers/video/omap2/displays/panel-generic-dpi.c b/drivers/video/omap2/displays/panel-generic-dpi.c
index c904f42..97363f7 100644
--- a/drivers/video/omap2/displays/panel-generic-dpi.c
+++ b/drivers/video/omap2/displays/panel-generic-dpi.c
@@ -33,9 +33,10 @@
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
+#include <linux/gpio.h>
 #include <video/omapdss.h>
 
-#include <video/omap-panel-generic-dpi.h>
+#include <video/omap-panel-data.h>
 
 struct panel_config {
 	struct omap_video_timings timings;
@@ -533,7 +534,7 @@ static inline struct panel_generic_dpi_data
 
 static int generic_dpi_panel_power_on(struct omap_dss_device *dssdev)
 {
-	int r;
+	int r, i;
 	struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev);
 	struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
 	struct panel_config *panel_config = drv_data->panel_config;
@@ -552,15 +553,13 @@ static int generic_dpi_panel_power_on(struct omap_dss_device *dssdev)
 	if (panel_config->power_on_delay)
 		msleep(panel_config->power_on_delay);
 
-	if (panel_data->platform_enable) {
-		r = panel_data->platform_enable(dssdev);
-		if (r)
-			goto err1;
+	for (i = 0; i < panel_data->num_gpios; ++i) {
+		gpio_set_value_cansleep(panel_data->gpios[i],
+				panel_data->gpio_invert[i] ? 0 : 1);
 	}
 
 	return 0;
-err1:
-	omapdss_dpi_display_disable(dssdev);
+
 err0:
 	return r;
 }
@@ -570,12 +569,15 @@ static void generic_dpi_panel_power_off(struct omap_dss_device *dssdev)
 	struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev);
 	struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
 	struct panel_config *panel_config = drv_data->panel_config;
+	int i;
 
 	if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
 		return;
 
-	if (panel_data->platform_disable)
-		panel_data->platform_disable(dssdev);
+	for (i = panel_data->num_gpios - 1; i >= 0; --i) {
+		gpio_set_value_cansleep(panel_data->gpios[i],
+				panel_data->gpio_invert[i] ? 1 : 0);
+	}
 
 	/* wait couple of vsyncs after disabling the LCD */
 	if (panel_config->power_off_delay)
@@ -589,7 +591,7 @@ static int generic_dpi_panel_probe(struct omap_dss_device *dssdev)
 	struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev);
 	struct panel_config *panel_config = NULL;
 	struct panel_drv_data *drv_data = NULL;
-	int i;
+	int i, r;
 
 	dev_dbg(&dssdev->dev, "probe\n");
 
@@ -606,9 +608,18 @@ static int generic_dpi_panel_probe(struct omap_dss_device *dssdev)
 	if (!panel_config)
 		return -EINVAL;
 
+	for (i = 0; i < panel_data->num_gpios; ++i) {
+		r = devm_gpio_request_one(&dssdev->dev, panel_data->gpios[i],
+				panel_data->gpio_invert[i] ?
+				GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW,
+				"panel gpio");
+		if (r)
+			return r;
+	}
+
 	dssdev->panel.timings = panel_config->timings;
 
-	drv_data = kzalloc(sizeof(*drv_data), GFP_KERNEL);
+	drv_data = devm_kzalloc(&dssdev->dev, sizeof(*drv_data), GFP_KERNEL);
 	if (!drv_data)
 		return -ENOMEM;
 
@@ -624,12 +635,8 @@ static int generic_dpi_panel_probe(struct omap_dss_device *dssdev)
 
 static void __exit generic_dpi_panel_remove(struct omap_dss_device *dssdev)
 {
-	struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
-
 	dev_dbg(&dssdev->dev, "remove\n");
 
-	kfree(drv_data);
-
 	dev_set_drvdata(&dssdev->dev, NULL);
 }
 
diff --git a/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c b/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c
index 6e5abe8..4ea6548 100644
--- a/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c
+++ b/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c
@@ -20,8 +20,10 @@
 #include <linux/delay.h>
 #include <linux/spi/spi.h>
 #include <linux/mutex.h>
+#include <linux/gpio.h>
 
 #include <video/omapdss.h>
+#include <video/omap-panel-data.h>
 
 struct lb035q02_data {
 	struct mutex lock;
@@ -48,9 +50,16 @@ static struct omap_video_timings lb035q02_timings = {
 	.sync_pclk_edge	= OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
 };
 
+static inline struct panel_generic_dpi_data
+*get_panel_data(const struct omap_dss_device *dssdev)
+{
+	return (struct panel_generic_dpi_data *) dssdev->data;
+}
+
 static int lb035q02_panel_power_on(struct omap_dss_device *dssdev)
 {
-	int r;
+	struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev);
+	int r, i;
 
 	if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
 		return 0;
@@ -62,54 +71,65 @@ static int lb035q02_panel_power_on(struct omap_dss_device *dssdev)
 	if (r)
 		goto err0;
 
-	if (dssdev->platform_enable) {
-		r = dssdev->platform_enable(dssdev);
-		if (r)
-			goto err1;
+	for (i = 0; i < panel_data->num_gpios; ++i) {
+		gpio_set_value_cansleep(panel_data->gpios[i],
+				panel_data->gpio_invert[i] ? 0 : 1);
 	}
 
 	return 0;
-err1:
-	omapdss_dpi_display_disable(dssdev);
+
 err0:
 	return r;
 }
 
 static void lb035q02_panel_power_off(struct omap_dss_device *dssdev)
 {
+	struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev);
+	int i;
+
 	if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
 		return;
 
-	if (dssdev->platform_disable)
-		dssdev->platform_disable(dssdev);
+	for (i = panel_data->num_gpios - 1; i >= 0; --i) {
+		gpio_set_value_cansleep(panel_data->gpios[i],
+				panel_data->gpio_invert[i] ? 1 : 0);
+	}
 
 	omapdss_dpi_display_disable(dssdev);
 }
 
 static int lb035q02_panel_probe(struct omap_dss_device *dssdev)
 {
+	struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev);
 	struct lb035q02_data *ld;
-	int r;
+	int r, i;
+
+	if (!panel_data)
+		return -EINVAL;
 
 	dssdev->panel.timings = lb035q02_timings;
 
-	ld = kzalloc(sizeof(*ld), GFP_KERNEL);
-	if (!ld) {
-		r = -ENOMEM;
-		goto err;
+	ld = devm_kzalloc(&dssdev->dev, sizeof(*ld), GFP_KERNEL);
+	if (!ld)
+		return -ENOMEM;
+
+	for (i = 0; i < panel_data->num_gpios; ++i) {
+		r = devm_gpio_request_one(&dssdev->dev, panel_data->gpios[i],
+				panel_data->gpio_invert[i] ?
+				GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW,
+				"panel gpio");
+		if (r)
+			return r;
 	}
+
 	mutex_init(&ld->lock);
 	dev_set_drvdata(&dssdev->dev, ld);
+
 	return 0;
-err:
-	return r;
 }
 
 static void lb035q02_panel_remove(struct omap_dss_device *dssdev)
 {
-	struct lb035q02_data *ld = dev_get_drvdata(&dssdev->dev);
-
-	kfree(ld);
 }
 
 static int lb035q02_panel_enable(struct omap_dss_device *dssdev)
diff --git a/drivers/video/omap2/displays/panel-n8x0.c b/drivers/video/omap2/displays/panel-n8x0.c
index dd12947..f94ead6 100644
--- a/drivers/video/omap2/displays/panel-n8x0.c
+++ b/drivers/video/omap2/displays/panel-n8x0.c
@@ -5,11 +5,10 @@
 #include <linux/slab.h>
 #include <linux/gpio.h>
 #include <linux/spi/spi.h>
-#include <linux/backlight.h>
 #include <linux/fb.h>
 
 #include <video/omapdss.h>
-#include <video/omap-panel-n8x0.h>
+#include <video/omap-panel-data.h>
 
 #define BLIZZARD_REV_CODE                      0x00
 #define BLIZZARD_CONFIG                        0x02
@@ -69,7 +68,6 @@ static struct panel_drv_data {
 
 	struct omap_dss_device *dssdev;
 	struct spi_device *spidev;
-	struct backlight_device *bldev;
 
 	int blizzard_ver;
 } s_drv_data;
@@ -297,12 +295,6 @@ static int n8x0_panel_power_on(struct omap_dss_device *dssdev)
 
 	gpio_direction_output(bdata->ctrl_pwrdown, 1);
 
-	if (bdata->platform_enable) {
-		r = bdata->platform_enable(dssdev);
-		if (r)
-			goto err_plat_en;
-	}
-
 	omapdss_rfbi_set_size(dssdev, dssdev->panel.timings.x_res,
 		dssdev->panel.timings.y_res);
 	omapdss_rfbi_set_pixel_size(dssdev, dssdev->ctrl.pixel_size);
@@ -375,9 +367,6 @@ err_inv_panel:
 err_inv_chip:
 	omapdss_rfbi_display_disable(dssdev);
 err_rfbi_en:
-	if (bdata->platform_disable)
-		bdata->platform_disable(dssdev);
-err_plat_en:
 	gpio_direction_output(bdata->ctrl_pwrdown, 0);
 	return r;
 }
@@ -394,9 +383,6 @@ static void n8x0_panel_power_off(struct omap_dss_device *dssdev)
 	send_display_off(spi);
 	send_sleep_in(spi);
 
-	if (bdata->platform_disable)
-		bdata->platform_disable(dssdev);
-
 	/*
 	 * HACK: we should turn off the panel here, but there is some problem
 	 * with the initialization sequence, and we fail to init the panel if we
@@ -424,54 +410,10 @@ static const struct rfbi_timings n8x0_panel_timings = {
 	.cs_pulse_width = 0,
 };
 
-static int n8x0_bl_update_status(struct backlight_device *dev)
-{
-	struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev);
-	struct panel_n8x0_data *bdata = get_board_data(dssdev);
-	struct panel_drv_data *ddata = get_drv_data(dssdev);
-	int r;
-	int level;
-
-	mutex_lock(&ddata->lock);
-
-	if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
-			dev->props.power == FB_BLANK_UNBLANK)
-		level = dev->props.brightness;
-	else
-		level = 0;
-
-	dev_dbg(&dssdev->dev, "update brightness to %d\n", level);
-
-	if (!bdata->set_backlight)
-		r = -EINVAL;
-	else
-		r = bdata->set_backlight(dssdev, level);
-
-	mutex_unlock(&ddata->lock);
-
-	return r;
-}
-
-static int n8x0_bl_get_intensity(struct backlight_device *dev)
-{
-	if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
-			dev->props.power == FB_BLANK_UNBLANK)
-		return dev->props.brightness;
-
-	return 0;
-}
-
-static const struct backlight_ops n8x0_bl_ops = {
-	.get_brightness = n8x0_bl_get_intensity,
-	.update_status  = n8x0_bl_update_status,
-};
-
 static int n8x0_panel_probe(struct omap_dss_device *dssdev)
 {
 	struct panel_n8x0_data *bdata = get_board_data(dssdev);
 	struct panel_drv_data *ddata;
-	struct backlight_device *bldev;
-	struct backlight_properties props;
 	int r;
 
 	dev_dbg(&dssdev->dev, "probe\n");
@@ -491,40 +433,27 @@ static int n8x0_panel_probe(struct omap_dss_device *dssdev)
 	dssdev->ctrl.rfbi_timings = n8x0_panel_timings;
 	dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
 
-	memset(&props, 0, sizeof(props));
-	props.max_brightness = 127;
-	props.type = BACKLIGHT_PLATFORM;
-	bldev = backlight_device_register(dev_name(&dssdev->dev), &dssdev->dev,
-			dssdev, &n8x0_bl_ops, &props);
-	if (IS_ERR(bldev)) {
-		r = PTR_ERR(bldev);
-		dev_err(&dssdev->dev, "register backlight failed\n");
-		return r;
+	if (gpio_is_valid(bdata->panel_reset)) {
+		r = devm_gpio_request_one(&dssdev->dev, bdata->panel_reset,
+				GPIOF_OUT_INIT_LOW, "PANEL RESET");
+		if (r)
+			return r;
 	}
 
-	ddata->bldev = bldev;
-
-	bldev->props.fb_blank = FB_BLANK_UNBLANK;
-	bldev->props.power = FB_BLANK_UNBLANK;
-	bldev->props.brightness = 127;
-
-	n8x0_bl_update_status(bldev);
+	if (gpio_is_valid(bdata->ctrl_pwrdown)) {
+		r = devm_gpio_request_one(&dssdev->dev, bdata->ctrl_pwrdown,
+				GPIOF_OUT_INIT_LOW, "PANEL PWRDOWN");
+		if (r)
+			return r;
+	}
 
 	return 0;
 }
 
 static void n8x0_panel_remove(struct omap_dss_device *dssdev)
 {
-	struct panel_drv_data *ddata = get_drv_data(dssdev);
-	struct backlight_device *bldev;
-
 	dev_dbg(&dssdev->dev, "remove\n");
 
-	bldev = ddata->bldev;
-	bldev->props.power = FB_BLANK_POWERDOWN;
-	n8x0_bl_update_status(bldev);
-	backlight_device_unregister(bldev);
-
 	dev_set_drvdata(&dssdev->dev, NULL);
 }
 
diff --git a/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c b/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
index c4e9c2b..1e0097d 100644
--- a/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
+++ b/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
@@ -19,10 +19,11 @@
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/spi/spi.h>
-#include <linux/backlight.h>
 #include <linux/fb.h>
+#include <linux/gpio.h>
 
 #include <video/omapdss.h>
+#include <video/omap-panel-data.h>
 
 #define LCD_XRES		800
 #define LCD_YRES		480
@@ -32,10 +33,6 @@
  */
 #define LCD_PIXEL_CLOCK		23800
 
-struct nec_8048_data {
-	struct backlight_device *bl;
-};
-
 static const struct {
 	unsigned char addr;
 	unsigned char dat;
@@ -84,93 +81,47 @@ static struct omap_video_timings nec_8048_panel_timings = {
 	.sync_pclk_edge	= OMAPDSS_DRIVE_SIG_RISING_EDGE,
 };
 
-static int nec_8048_bl_update_status(struct backlight_device *bl)
-{
-	struct omap_dss_device *dssdev = dev_get_drvdata(&bl->dev);
-	int level;
-
-	if (!dssdev->set_backlight)
-		return -EINVAL;
-
-	if (bl->props.fb_blank == FB_BLANK_UNBLANK &&
-			bl->props.power == FB_BLANK_UNBLANK)
-		level = bl->props.brightness;
-	else
-		level = 0;
-
-	return dssdev->set_backlight(dssdev, level);
-}
-
-static int nec_8048_bl_get_brightness(struct backlight_device *bl)
+static inline struct panel_nec_nl8048_data
+*get_panel_data(const struct omap_dss_device *dssdev)
 {
-	if (bl->props.fb_blank == FB_BLANK_UNBLANK &&
-			bl->props.power == FB_BLANK_UNBLANK)
-		return bl->props.brightness;
-
-	return 0;
+	return (struct panel_nec_nl8048_data *) dssdev->data;
 }
 
-static const struct backlight_ops nec_8048_bl_ops = {
-	.get_brightness	= nec_8048_bl_get_brightness,
-	.update_status	= nec_8048_bl_update_status,
-};
-
 static int nec_8048_panel_probe(struct omap_dss_device *dssdev)
 {
-	struct backlight_device *bl;
-	struct nec_8048_data *necd;
-	struct backlight_properties props;
+	struct panel_nec_nl8048_data *pd = get_panel_data(dssdev);
 	int r;
 
-	dssdev->panel.timings = nec_8048_panel_timings;
-
-	necd = kzalloc(sizeof(*necd), GFP_KERNEL);
-	if (!necd)
-		return -ENOMEM;
-
-	dev_set_drvdata(&dssdev->dev, necd);
+	if (!pd)
+		return -EINVAL;
 
-	memset(&props, 0, sizeof(struct backlight_properties));
-	props.max_brightness = 255;
+	dssdev->panel.timings = nec_8048_panel_timings;
 
-	bl = backlight_device_register("nec-8048", &dssdev->dev, dssdev,
-			&nec_8048_bl_ops, &props);
-	if (IS_ERR(bl)) {
-		r = PTR_ERR(bl);
-		kfree(necd);
-		return r;
+	if (gpio_is_valid(pd->qvga_gpio)) {
+		r = devm_gpio_request_one(&dssdev->dev, pd->qvga_gpio,
+				GPIOF_OUT_INIT_HIGH, "lcd QVGA");
+		if (r)
+			return r;
 	}
-	necd->bl = bl;
 
-	bl->props.fb_blank = FB_BLANK_UNBLANK;
-	bl->props.power = FB_BLANK_UNBLANK;
-	bl->props.max_brightness = dssdev->max_backlight_level;
-	bl->props.brightness = dssdev->max_backlight_level;
-
-	r = nec_8048_bl_update_status(bl);
-	if (r < 0)
-		dev_err(&dssdev->dev, "failed to set lcd brightness\n");
+	if (gpio_is_valid(pd->res_gpio)) {
+		r = devm_gpio_request_one(&dssdev->dev, pd->res_gpio,
+				GPIOF_OUT_INIT_LOW, "lcd RES");
+		if (r)
+			return r;
+	}
 
 	return 0;
 }
 
 static void nec_8048_panel_remove(struct omap_dss_device *dssdev)
 {
-	struct nec_8048_data *necd = dev_get_drvdata(&dssdev->dev);
-	struct backlight_device *bl = necd->bl;
-
-	bl->props.power = FB_BLANK_POWERDOWN;
-	nec_8048_bl_update_status(bl);
-	backlight_device_unregister(bl);
-
-	kfree(necd);
 }
 
 static int nec_8048_panel_power_on(struct omap_dss_device *dssdev)
 {
+	struct panel_nec_nl8048_data *pd = get_panel_data(dssdev);
 	int r;
-	struct nec_8048_data *necd = dev_get_drvdata(&dssdev->dev);
-	struct backlight_device *bl = necd->bl;
 
 	if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
 		return 0;
@@ -182,36 +133,24 @@ static int nec_8048_panel_power_on(struct omap_dss_device *dssdev)
 	if (r)
 		goto err0;
 
-	if (dssdev->platform_enable) {
-		r = dssdev->platform_enable(dssdev);
-		if (r)
-			goto err1;
-	}
-
-	r = nec_8048_bl_update_status(bl);
-	if (r < 0)
-		dev_err(&dssdev->dev, "failed to set lcd brightness\n");
+	if (gpio_is_valid(pd->res_gpio))
+		gpio_set_value_cansleep(pd->res_gpio, 1);
 
 	return 0;
-err1:
-	omapdss_dpi_display_disable(dssdev);
+
 err0:
 	return r;
 }
 
 static void nec_8048_panel_power_off(struct omap_dss_device *dssdev)
 {
-	struct nec_8048_data *necd = dev_get_drvdata(&dssdev->dev);
-	struct backlight_device *bl = necd->bl;
+	struct panel_nec_nl8048_data *pd = get_panel_data(dssdev);
 
 	if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
 		return;
 
-	bl->props.brightness = 0;
-	nec_8048_bl_update_status(bl);
-
-	if (dssdev->platform_disable)
-		dssdev->platform_disable(dssdev);
+	if (gpio_is_valid(pd->res_gpio))
+		gpio_set_value_cansleep(pd->res_gpio, 0);
 
 	omapdss_dpi_display_disable(dssdev);
 }
diff --git a/drivers/video/omap2/displays/panel-picodlp.c b/drivers/video/omap2/displays/panel-picodlp.c
index 1b94018..62f2db0 100644
--- a/drivers/video/omap2/displays/panel-picodlp.c
+++ b/drivers/video/omap2/displays/panel-picodlp.c
@@ -31,7 +31,7 @@
 #include <linux/gpio.h>
 
 #include <video/omapdss.h>
-#include <video/omap-panel-picodlp.h>
+#include <video/omap-panel-data.h>
 
 #include "panel-picodlp.h"
 
@@ -354,12 +354,6 @@ static int picodlp_panel_power_on(struct omap_dss_device *dssdev)
 	struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev);
 	struct picodlp_panel_data *picodlp_pdata = get_panel_data(dssdev);
 
-	if (dssdev->platform_enable) {
-		r = dssdev->platform_enable(dssdev);
-		if (r)
-			return r;
-	}
-
 	gpio_set_value(picodlp_pdata->pwrgood_gpio, 0);
 	msleep(1);
 	gpio_set_value(picodlp_pdata->pwrgood_gpio, 1);
@@ -398,9 +392,6 @@ static int picodlp_panel_power_on(struct omap_dss_device *dssdev)
 err:
 	omapdss_dpi_display_disable(dssdev);
 err1:
-	if (dssdev->platform_disable)
-		dssdev->platform_disable(dssdev);
-
 	return r;
 }
 
@@ -412,9 +403,6 @@ static void picodlp_panel_power_off(struct omap_dss_device *dssdev)
 
 	gpio_set_value(picodlp_pdata->emu_done_gpio, 0);
 	gpio_set_value(picodlp_pdata->pwrgood_gpio, 0);
-
-	if (dssdev->platform_disable)
-		dssdev->platform_disable(dssdev);
 }
 
 static int picodlp_panel_probe(struct omap_dss_device *dssdev)
@@ -423,11 +411,14 @@ static int picodlp_panel_probe(struct omap_dss_device *dssdev)
 	struct picodlp_panel_data *picodlp_pdata = get_panel_data(dssdev);
 	struct i2c_adapter *adapter;
 	struct i2c_client *picodlp_i2c_client;
-	int r = 0, picodlp_adapter_id;
+	int r, picodlp_adapter_id;
 
 	dssdev->panel.timings = pico_ls_timings;
 
-	picod =  kzalloc(sizeof(struct picodlp_data), GFP_KERNEL);
+	if (!picodlp_pdata)
+		return -EINVAL;
+
+	picod = devm_kzalloc(&dssdev->dev, sizeof(*picod), GFP_KERNEL);
 	if (!picod)
 		return -ENOMEM;
 
@@ -438,25 +429,37 @@ static int picodlp_panel_probe(struct omap_dss_device *dssdev)
 	adapter = i2c_get_adapter(picodlp_adapter_id);
 	if (!adapter) {
 		dev_err(&dssdev->dev, "can't get i2c adapter\n");
-		r = -ENODEV;
-		goto err;
+		return -ENODEV;
 	}
 
 	picodlp_i2c_client = i2c_new_device(adapter, &picodlp_i2c_board_info);
 	if (!picodlp_i2c_client) {
 		dev_err(&dssdev->dev, "can't add i2c device::"
 					 " picodlp_i2c_client is NULL\n");
-		r = -ENODEV;
-		goto err;
+		return -ENODEV;
 	}
 
 	picod->picodlp_i2c_client = picodlp_i2c_client;
 
 	dev_set_drvdata(&dssdev->dev, picod);
-	return r;
-err:
-	kfree(picod);
-	return r;
+
+	if (gpio_is_valid(picodlp_pdata->emu_done_gpio)) {
+		r = devm_gpio_request_one(&dssdev->dev,
+				picodlp_pdata->emu_done_gpio,
+				GPIOF_IN, "DLP EMU DONE");
+		if (r)
+			return r;
+	}
+
+	if (gpio_is_valid(picodlp_pdata->pwrgood_gpio)) {
+		r = devm_gpio_request_one(&dssdev->dev,
+				picodlp_pdata->pwrgood_gpio,
+				GPIOF_OUT_INIT_LOW, "DLP PWRGOOD");
+		if (r)
+			return r;
+	}
+
+	return 0;
 }
 
 static void picodlp_panel_remove(struct omap_dss_device *dssdev)
diff --git a/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
index cada8c6..74cb0eb 100644
--- a/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
+++ b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
@@ -20,16 +20,13 @@
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/device.h>
-#include <linux/backlight.h>
 #include <linux/fb.h>
 #include <linux/err.h>
 #include <linux/slab.h>
+#include <linux/gpio.h>
 
 #include <video/omapdss.h>
-
-struct sharp_data {
-	struct backlight_device *bl;
-};
+#include <video/omap-panel-data.h>
 
 static struct omap_video_timings sharp_ls_timings = {
 	.x_res = 480,
@@ -52,91 +49,67 @@ static struct omap_video_timings sharp_ls_timings = {
 	.sync_pclk_edge	= OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
 };
 
-static int sharp_ls_bl_update_status(struct backlight_device *bl)
+static inline struct panel_sharp_ls037v7dw01_data
+*get_panel_data(const struct omap_dss_device *dssdev)
 {
-	struct omap_dss_device *dssdev = dev_get_drvdata(&bl->dev);
-	int level;
-
-	if (!dssdev->set_backlight)
-		return -EINVAL;
-
-	if (bl->props.fb_blank == FB_BLANK_UNBLANK &&
-			bl->props.power == FB_BLANK_UNBLANK)
-		level = bl->props.brightness;
-	else
-		level = 0;
-
-	return dssdev->set_backlight(dssdev, level);
+	return (struct panel_sharp_ls037v7dw01_data *) dssdev->data;
 }
 
-static int sharp_ls_bl_get_brightness(struct backlight_device *bl)
-{
-	if (bl->props.fb_blank == FB_BLANK_UNBLANK &&
-			bl->props.power == FB_BLANK_UNBLANK)
-		return bl->props.brightness;
-
-	return 0;
-}
-
-static const struct backlight_ops sharp_ls_bl_ops = {
-	.get_brightness = sharp_ls_bl_get_brightness,
-	.update_status  = sharp_ls_bl_update_status,
-};
-
-
-
 static int sharp_ls_panel_probe(struct omap_dss_device *dssdev)
 {
-	struct backlight_properties props;
-	struct backlight_device *bl;
-	struct sharp_data *sd;
+	struct panel_sharp_ls037v7dw01_data *pd = get_panel_data(dssdev);
 	int r;
 
+	if (!pd)
+		return -EINVAL;
+
 	dssdev->panel.timings = sharp_ls_timings;
 
-	sd = kzalloc(sizeof(*sd), GFP_KERNEL);
-	if (!sd)
-		return -ENOMEM;
+	if (gpio_is_valid(pd->mo_gpio)) {
+		r = devm_gpio_request_one(&dssdev->dev, pd->mo_gpio,
+				GPIOF_OUT_INIT_LOW, "lcd MO");
+		if (r)
+			return r;
+	}
 
-	dev_set_drvdata(&dssdev->dev, sd);
+	if (gpio_is_valid(pd->lr_gpio)) {
+		r = devm_gpio_request_one(&dssdev->dev, pd->lr_gpio,
+				GPIOF_OUT_INIT_HIGH, "lcd LR");
+		if (r)
+			return r;
+	}
 
-	memset(&props, 0, sizeof(struct backlight_properties));
-	props.max_brightness = dssdev->max_backlight_level;
-	props.type = BACKLIGHT_RAW;
+	if (gpio_is_valid(pd->ud_gpio)) {
+		r = devm_gpio_request_one(&dssdev->dev, pd->ud_gpio,
+				GPIOF_OUT_INIT_HIGH, "lcd UD");
+		if (r)
+			return r;
+	}
 
-	bl = backlight_device_register("sharp-ls", &dssdev->dev, dssdev,
-			&sharp_ls_bl_ops, &props);
-	if (IS_ERR(bl)) {
-		r = PTR_ERR(bl);
-		kfree(sd);
-		return r;
+	if (gpio_is_valid(pd->resb_gpio)) {
+		r = devm_gpio_request_one(&dssdev->dev, pd->resb_gpio,
+				GPIOF_OUT_INIT_LOW, "lcd RESB");
+		if (r)
+			return r;
 	}
-	sd->bl = bl;
 
-	bl->props.fb_blank = FB_BLANK_UNBLANK;
-	bl->props.power = FB_BLANK_UNBLANK;
-	bl->props.brightness = dssdev->max_backlight_level;
-	r = sharp_ls_bl_update_status(bl);
-	if (r < 0)
-		dev_err(&dssdev->dev, "failed to set lcd brightness\n");
+	if (gpio_is_valid(pd->ini_gpio)) {
+		r = devm_gpio_request_one(&dssdev->dev, pd->ini_gpio,
+				GPIOF_OUT_INIT_LOW, "lcd INI");
+		if (r)
+			return r;
+	}
 
 	return 0;
 }
 
 static void __exit sharp_ls_panel_remove(struct omap_dss_device *dssdev)
 {
-	struct sharp_data *sd = dev_get_drvdata(&dssdev->dev);
-	struct backlight_device *bl = sd->bl;
-
-	bl->props.power = FB_BLANK_POWERDOWN;
-	sharp_ls_bl_update_status(bl);
-	backlight_device_unregister(bl);
-
-	kfree(sd);
 }
 
 static int sharp_ls_power_on(struct omap_dss_device *dssdev)
 {
+	struct panel_sharp_ls037v7dw01_data *pd = get_panel_data(dssdev);
 	int r = 0;
 
 	if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
@@ -152,26 +125,29 @@ static int sharp_ls_power_on(struct omap_dss_device *dssdev)
 	/* wait couple of vsyncs until enabling the LCD */
 	msleep(50);
 
-	if (dssdev->platform_enable) {
-		r = dssdev->platform_enable(dssdev);
-		if (r)
-			goto err1;
-	}
+	if (gpio_is_valid(pd->resb_gpio))
+		gpio_set_value_cansleep(pd->resb_gpio, 1);
+
+	if (gpio_is_valid(pd->ini_gpio))
+		gpio_set_value_cansleep(pd->ini_gpio, 1);
 
 	return 0;
-err1:
-	omapdss_dpi_display_disable(dssdev);
 err0:
 	return r;
 }
 
 static void sharp_ls_power_off(struct omap_dss_device *dssdev)
 {
+	struct panel_sharp_ls037v7dw01_data *pd = get_panel_data(dssdev);
+
 	if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
 		return;
 
-	if (dssdev->platform_disable)
-		dssdev->platform_disable(dssdev);
+	if (gpio_is_valid(pd->ini_gpio))
+		gpio_set_value_cansleep(pd->ini_gpio, 0);
+
+	if (gpio_is_valid(pd->resb_gpio))
+		gpio_set_value_cansleep(pd->resb_gpio, 0);
 
 	/* wait at least 5 vsyncs after disabling the LCD */
 
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
index a32407a..c4f78bd 100644
--- a/drivers/video/omap2/displays/panel-taal.c
+++ b/drivers/video/omap2/displays/panel-taal.c
@@ -33,7 +33,7 @@
 #include <linux/mutex.h>
 
 #include <video/omapdss.h>
-#include <video/omap-panel-nokia-dsi.h>
+#include <video/omap-panel-data.h>
 #include <video/mipi_display.h>
 
 /* DSI Virtual channel. Hardcoded for now. */
@@ -54,61 +54,6 @@ static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable);
 
 static int taal_panel_reset(struct omap_dss_device *dssdev);
 
-/**
- * struct panel_config - panel configuration
- * @name: panel name
- * @type: panel type
- * @timings: panel resolution
- * @sleep: various panel specific delays, passed to msleep() if non-zero
- * @reset_sequence: reset sequence timings, passed to udelay() if non-zero
- * @regulators: array of panel regulators
- * @num_regulators: number of regulators in the array
- */
-struct panel_config {
-	const char *name;
-	int type;
-
-	struct omap_video_timings timings;
-
-	struct {
-		unsigned int sleep_in;
-		unsigned int sleep_out;
-		unsigned int hw_reset;
-		unsigned int enable_te;
-	} sleep;
-
-	struct {
-		unsigned int high;
-		unsigned int low;
-	} reset_sequence;
-
-};
-
-enum {
-	PANEL_TAAL,
-};
-
-static struct panel_config panel_configs[] = {
-	{
-		.name		= "taal",
-		.type		= PANEL_TAAL,
-		.timings	= {
-			.x_res		= 864,
-			.y_res		= 480,
-		},
-		.sleep		= {
-			.sleep_in	= 5,
-			.sleep_out	= 5,
-			.hw_reset	= 5,
-			.enable_te	= 100, /* possible panel bug */
-		},
-		.reset_sequence	= {
-			.high		= 10,
-			.low		= 10,
-		},
-	},
-};
-
 struct taal_data {
 	struct mutex lock;
 
@@ -121,9 +66,6 @@ struct taal_data {
 
 	struct omap_dss_device *dssdev;
 
-	/* panel specific HW info */
-	struct panel_config *panel_config;
-
 	/* panel HW configuration from DT or platform data */
 	int reset_gpio;
 	int ext_te_gpio;
@@ -134,8 +76,6 @@ struct taal_data {
 
 	/* runtime variables */
 	bool enabled;
-	u8 rotate;
-	bool mirror;
 
 	bool te_enabled;
 
@@ -221,8 +161,7 @@ static int taal_sleep_in(struct taal_data *td)
 
 	hw_guard_start(td, 120);
 
-	if (td->panel_config->sleep.sleep_in)
-		msleep(td->panel_config->sleep.sleep_in);
+	msleep(5);
 
 	return 0;
 }
@@ -239,8 +178,7 @@ static int taal_sleep_out(struct taal_data *td)
 
 	hw_guard_start(td, 120);
 
-	if (td->panel_config->sleep.sleep_out)
-		msleep(td->panel_config->sleep.sleep_out);
+	msleep(5);
 
 	return 0;
 }
@@ -262,49 +200,6 @@ static int taal_get_id(struct taal_data *td, u8 *id1, u8 *id2, u8 *id3)
 	return 0;
 }
 
-static int taal_set_addr_mode(struct taal_data *td, u8 rotate, bool mirror)
-{
-	int r;
-	u8 mode;
-	int b5, b6, b7;
-
-	r = taal_dcs_read_1(td, MIPI_DCS_GET_ADDRESS_MODE, &mode);
-	if (r)
-		return r;
-
-	switch (rotate) {
-	default:
-	case 0:
-		b7 = 0;
-		b6 = 0;
-		b5 = 0;
-		break;
-	case 1:
-		b7 = 0;
-		b6 = 1;
-		b5 = 1;
-		break;
-	case 2:
-		b7 = 1;
-		b6 = 1;
-		b5 = 0;
-		break;
-	case 3:
-		b7 = 1;
-		b6 = 0;
-		b5 = 1;
-		break;
-	}
-
-	if (mirror)
-		b6 = !b6;
-
-	mode &= ~((1<<7) | (1<<6) | (1<<5));
-	mode |= (b7 << 7) | (b6 << 6) | (b5 << 5);
-
-	return taal_dcs_write_1(td, MIPI_DCS_SET_ADDRESS_MODE, mode);
-}
-
 static int taal_set_update_window(struct taal_data *td,
 		u16 x, u16 y, u16 w, u16 h)
 {
@@ -515,15 +410,8 @@ static const struct backlight_ops taal_bl_ops = {
 static void taal_get_resolution(struct omap_dss_device *dssdev,
 		u16 *xres, u16 *yres)
 {
-	struct taal_data *td = dev_get_drvdata(&dssdev->dev);
-
-	if (td->rotate == 0 || td->rotate == 2) {
-		*xres = dssdev->panel.timings.x_res;
-		*yres = dssdev->panel.timings.y_res;
-	} else {
-		*yres = dssdev->panel.timings.x_res;
-		*xres = dssdev->panel.timings.y_res;
-	}
+	*xres = dssdev->panel.timings.x_res;
+	*yres = dssdev->panel.timings.y_res;
 }
 
 static ssize_t taal_num_errors_show(struct device *dev,
@@ -845,17 +733,14 @@ static void taal_hw_reset(struct omap_dss_device *dssdev)
 		return;
 
 	gpio_set_value(td->reset_gpio, 1);
-	if (td->panel_config->reset_sequence.high)
-		udelay(td->panel_config->reset_sequence.high);
+	udelay(10);
 	/* reset the panel */
 	gpio_set_value(td->reset_gpio, 0);
 	/* assert reset */
-	if (td->panel_config->reset_sequence.low)
-		udelay(td->panel_config->reset_sequence.low);
+	udelay(10);
 	gpio_set_value(td->reset_gpio, 1);
 	/* wait after releasing reset */
-	if (td->panel_config->sleep.hw_reset)
-		msleep(td->panel_config->sleep.hw_reset);
+	msleep(5);
 }
 
 static void taal_probe_pdata(struct taal_data *td,
@@ -881,8 +766,7 @@ static int taal_probe(struct omap_dss_device *dssdev)
 	struct backlight_properties props;
 	struct taal_data *td;
 	struct backlight_device *bldev = NULL;
-	int r, i;
-	const char *panel_name;
+	int r;
 
 	dev_dbg(&dssdev->dev, "probe\n");
 
@@ -897,26 +781,13 @@ static int taal_probe(struct omap_dss_device *dssdev)
 		const struct nokia_dsi_panel_data *pdata = dssdev->data;
 
 		taal_probe_pdata(td, pdata);
-
-		panel_name = pdata->name;
 	} else {
 		return -ENODEV;
 	}
 
-	if (panel_name == NULL)
-		return -EINVAL;
-
-	for (i = 0; i < ARRAY_SIZE(panel_configs); i++) {
-		if (strcmp(panel_name, panel_configs[i].name) == 0) {
-			td->panel_config = &panel_configs[i];
-			break;
-		}
-	}
-
-	if (!td->panel_config)
-		return -EINVAL;
-
-	dssdev->panel.timings = td->panel_config->timings;
+	dssdev->panel.timings.x_res = 864;
+	dssdev->panel.timings.y_res = 480;
+	dssdev->panel.timings.pixel_clock = DIV_ROUND_UP(864 * 480 * 60, 1000);
 	dssdev->panel.dsi_pix_fmt = OMAP_DSS_DSI_FMT_RGB888;
 	dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE |
 		OMAP_DSS_DISPLAY_CAP_TEAR_ELIM;
@@ -1049,6 +920,15 @@ static int taal_power_on(struct omap_dss_device *dssdev)
 	struct taal_data *td = dev_get_drvdata(&dssdev->dev);
 	u8 id1, id2, id3;
 	int r;
+	struct omap_dss_dsi_config dsi_config = {
+		.mode = OMAP_DSS_DSI_CMD_MODE,
+		.pixel_format = OMAP_DSS_DSI_FMT_RGB888,
+		.timings = &dssdev->panel.timings,
+		.hs_clk_min = 150000000,
+		.hs_clk_max = 300000000,
+		.lp_clk_min = 7000000,
+		.lp_clk_max = 10000000,
+	};
 
 	r = omapdss_dsi_configure_pins(dssdev, &td->pin_config);
 	if (r) {
@@ -1056,14 +936,9 @@ static int taal_power_on(struct omap_dss_device *dssdev)
 		goto err0;
 	};
 
-	omapdss_dsi_set_size(dssdev, dssdev->panel.timings.x_res,
-		dssdev->panel.timings.y_res);
-	omapdss_dsi_set_pixel_format(dssdev, OMAP_DSS_DSI_FMT_RGB888);
-	omapdss_dsi_set_operation_mode(dssdev, OMAP_DSS_DSI_CMD_MODE);
-
-	r = omapdss_dsi_set_clocks(dssdev, 216000000, 10000000);
+	r = omapdss_dsi_set_config(dssdev, &dsi_config);
 	if (r) {
-		dev_err(&dssdev->dev, "failed to set HS and LP clocks\n");
+		dev_err(&dssdev->dev, "failed to configure DSI\n");
 		goto err0;
 	}
 
@@ -1086,8 +961,7 @@ static int taal_power_on(struct omap_dss_device *dssdev)
 		goto err;
 
 	/* on early Taal revisions CABC is broken */
-	if (td->panel_config->type == PANEL_TAAL &&
-		(id2 == 0x00 || id2 == 0xff || id2 == 0x81))
+	if (id2 == 0x00 || id2 == 0xff || id2 == 0x81)
 		td->cabc_broken = true;
 
 	r = taal_dcs_write_1(td, DCS_BRIGHTNESS, 0xff);
@@ -1104,10 +978,6 @@ static int taal_power_on(struct omap_dss_device *dssdev)
 	if (r)
 		goto err;
 
-	r = taal_set_addr_mode(td, td->rotate, td->mirror);
-	if (r)
-		goto err;
-
 	if (!td->cabc_broken) {
 		r = taal_dcs_write_1(td, DCS_WRITE_CABC, td->cabc_mode);
 		if (r)
@@ -1129,8 +999,8 @@ static int taal_power_on(struct omap_dss_device *dssdev)
 	td->enabled = 1;
 
 	if (!td->intro_printed) {
-		dev_info(&dssdev->dev, "%s panel revision %02x.%02x.%02x\n",
-			td->panel_config->name, id1, id2, id3);
+		dev_info(&dssdev->dev, "panel revision %02x.%02x.%02x\n",
+			id1, id2, id3);
 		if (td->cabc_broken)
 			dev_info(&dssdev->dev,
 					"old Taal version, CABC disabled\n");
@@ -1311,8 +1181,8 @@ static int taal_update(struct omap_dss_device *dssdev,
 
 	/* XXX no need to send this every frame, but dsi break if not done */
 	r = taal_set_update_window(td, 0, 0,
-			td->panel_config->timings.x_res,
-			td->panel_config->timings.y_res);
+			dssdev->panel.timings.x_res,
+			dssdev->panel.timings.y_res);
 	if (r)
 		goto err;
 
@@ -1365,8 +1235,8 @@ static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable)
 	if (!gpio_is_valid(td->ext_te_gpio))
 		omapdss_dsi_enable_te(dssdev, enable);
 
-	if (td->panel_config->sleep.enable_te)
-		msleep(td->panel_config->sleep.enable_te);
+	/* possible panel bug */
+	msleep(100);
 
 	return r;
 }
@@ -1419,112 +1289,6 @@ static int taal_get_te(struct omap_dss_device *dssdev)
 	return r;
 }
 
-static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate)
-{
-	struct taal_data *td = dev_get_drvdata(&dssdev->dev);
-	u16 dw, dh;
-	int r;
-
-	dev_dbg(&dssdev->dev, "rotate %d\n", rotate);
-
-	mutex_lock(&td->lock);
-
-	if (td->rotate == rotate)
-		goto end;
-
-	dsi_bus_lock(dssdev);
-
-	if (td->enabled) {
-		r = taal_wake_up(dssdev);
-		if (r)
-			goto err;
-
-		r = taal_set_addr_mode(td, rotate, td->mirror);
-		if (r)
-			goto err;
-	}
-
-	if (rotate == 0 || rotate == 2) {
-		dw = dssdev->panel.timings.x_res;
-		dh = dssdev->panel.timings.y_res;
-	} else {
-		dw = dssdev->panel.timings.y_res;
-		dh = dssdev->panel.timings.x_res;
-	}
-
-	omapdss_dsi_set_size(dssdev, dw, dh);
-
-	td->rotate = rotate;
-
-	dsi_bus_unlock(dssdev);
-end:
-	mutex_unlock(&td->lock);
-	return 0;
-err:
-	dsi_bus_unlock(dssdev);
-	mutex_unlock(&td->lock);
-	return r;
-}
-
-static u8 taal_get_rotate(struct omap_dss_device *dssdev)
-{
-	struct taal_data *td = dev_get_drvdata(&dssdev->dev);
-	int r;
-
-	mutex_lock(&td->lock);
-	r = td->rotate;
-	mutex_unlock(&td->lock);
-
-	return r;
-}
-
-static int taal_mirror(struct omap_dss_device *dssdev, bool enable)
-{
-	struct taal_data *td = dev_get_drvdata(&dssdev->dev);
-	int r;
-
-	dev_dbg(&dssdev->dev, "mirror %d\n", enable);
-
-	mutex_lock(&td->lock);
-
-	if (td->mirror == enable)
-		goto end;
-
-	dsi_bus_lock(dssdev);
-	if (td->enabled) {
-		r = taal_wake_up(dssdev);
-		if (r)
-			goto err;
-
-		r = taal_set_addr_mode(td, td->rotate, enable);
-		if (r)
-			goto err;
-	}
-
-	td->mirror = enable;
-
-	dsi_bus_unlock(dssdev);
-end:
-	mutex_unlock(&td->lock);
-	return 0;
-err:
-	dsi_bus_unlock(dssdev);
-	mutex_unlock(&td->lock);
-	return r;
-}
-
-static bool taal_get_mirror(struct omap_dss_device *dssdev)
-{
-	struct taal_data *td = dev_get_drvdata(&dssdev->dev);
-	int r;
-
-	mutex_lock(&td->lock);
-	r = td->mirror;
-	mutex_unlock(&td->lock);
-
-	return r;
-}
-
 static int taal_run_test(struct omap_dss_device *dssdev, int test_num)
 {
 	struct taal_data *td = dev_get_drvdata(&dssdev->dev);
@@ -1758,10 +1522,6 @@ static struct omap_dss_driver taal_driver = {
 	.enable_te	= taal_enable_te,
 	.get_te		= taal_get_te,
 
-	.set_rotate	= taal_rotate,
-	.get_rotate	= taal_get_rotate,
-	.set_mirror	= taal_mirror,
-	.get_mirror	= taal_get_mirror,
 	.run_test	= taal_run_test,
 	.memory_read	= taal_memory_read,
 
diff --git a/drivers/video/omap2/displays/panel-tfp410.c b/drivers/video/omap2/displays/panel-tfp410.c
index 8281baa..a1dba868 100644
--- a/drivers/video/omap2/displays/panel-tfp410.c
+++ b/drivers/video/omap2/displays/panel-tfp410.c
@@ -24,7 +24,7 @@
 #include <linux/gpio.h>
 #include <drm/drm_edid.h>
 
-#include <video/omap-panel-tfp410.h>
+#include <video/omap-panel-data.h>
 
 static const struct omap_video_timings tfp410_default_timings = {
 	.x_res		= 640,
diff --git a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
index 048c983..abf2bc4 100644
--- a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
+++ b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
@@ -18,6 +18,7 @@
 #include <linux/slab.h>
 
 #include <video/omapdss.h>
+#include <video/omap-panel-data.h>
 
 #define TPO_R02_MODE(x)		((x) & 7)
 #define TPO_R02_MODE_800x480	7
@@ -278,9 +279,14 @@ static const struct omap_video_timings tpo_td043_timings = {
 	.sync_pclk_edge	= OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
 };
 
+static inline struct panel_tpo_td043_data
+*get_panel_data(const struct omap_dss_device *dssdev)
+{
+	return (struct panel_tpo_td043_data *) dssdev->data;
+}
+
 static int tpo_td043_power_on(struct tpo_td043_device *tpo_td043)
 {
-	int nreset_gpio = tpo_td043->nreset_gpio;
 	int r;
 
 	if (tpo_td043->powered_on)
@@ -293,8 +299,8 @@ static int tpo_td043_power_on(struct tpo_td043_device *tpo_td043)
 	/* wait for panel to stabilize */
 	msleep(160);
 
-	if (gpio_is_valid(nreset_gpio))
-		gpio_set_value(nreset_gpio, 1);
+	if (gpio_is_valid(tpo_td043->nreset_gpio))
+		gpio_set_value(tpo_td043->nreset_gpio, 1);
 
 	tpo_td043_write(tpo_td043->spi, 2,
 			TPO_R02_MODE(tpo_td043->mode) | TPO_R02_NCLK_RISING);
@@ -311,16 +317,14 @@ static int tpo_td043_power_on(struct tpo_td043_device *tpo_td043)
 
 static void tpo_td043_power_off(struct tpo_td043_device *tpo_td043)
 {
-	int nreset_gpio = tpo_td043->nreset_gpio;
-
 	if (!tpo_td043->powered_on)
 		return;
 
 	tpo_td043_write(tpo_td043->spi, 3,
 			TPO_R03_VAL_STANDBY | TPO_R03_EN_PWM);
 
-	if (gpio_is_valid(nreset_gpio))
-		gpio_set_value(nreset_gpio, 0);
+	if (gpio_is_valid(tpo_td043->nreset_gpio))
+		gpio_set_value(tpo_td043->nreset_gpio, 0);
 
 	/* wait for at least 2 vsyncs before cutting off power */
 	msleep(50);
@@ -347,12 +351,6 @@ static int tpo_td043_enable_dss(struct omap_dss_device *dssdev)
 	if (r)
 		goto err0;
 
-	if (dssdev->platform_enable) {
-		r = dssdev->platform_enable(dssdev);
-		if (r)
-			goto err1;
-	}
-
 	/*
 	 * If we are resuming from system suspend, SPI clocks might not be
 	 * enabled yet, so we'll program the LCD from SPI PM resume callback.
@@ -379,9 +377,6 @@ static void tpo_td043_disable_dss(struct omap_dss_device *dssdev)
 	if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
 		return;
 
-	if (dssdev->platform_disable)
-		dssdev->platform_disable(dssdev);
-
 	omapdss_dpi_display_disable(dssdev);
 
 	if (!tpo_td043->spi_suspended)
@@ -407,7 +402,7 @@ static void tpo_td043_disable(struct omap_dss_device *dssdev)
 static int tpo_td043_probe(struct omap_dss_device *dssdev)
 {
 	struct tpo_td043_device *tpo_td043 = g_tpo_td043;
-	int nreset_gpio = dssdev->reset_gpio;
+	struct panel_tpo_td043_data *pdata = get_panel_data(dssdev);
 	int ret = 0;
 
 	dev_dbg(&dssdev->dev, "probe\n");
@@ -417,6 +412,11 @@ static int tpo_td043_probe(struct omap_dss_device *dssdev)
 		return -ENODEV;
 	}
 
+	if (!pdata)
+		return -EINVAL;
+
+	tpo_td043->nreset_gpio = pdata->nreset_gpio;
+
 	dssdev->panel.timings = tpo_td043_timings;
 	dssdev->ctrl.pixel_size = 24;
 
@@ -430,9 +430,10 @@ static int tpo_td043_probe(struct omap_dss_device *dssdev)
 		goto fail_regulator;
 	}
 
-	if (gpio_is_valid(nreset_gpio)) {
-		ret = gpio_request_one(nreset_gpio, GPIOF_OUT_INIT_LOW,
-					"lcd reset");
+	if (gpio_is_valid(tpo_td043->nreset_gpio)) {
+		ret = devm_gpio_request_one(&dssdev->dev,
+				tpo_td043->nreset_gpio, GPIOF_OUT_INIT_LOW,
+				"lcd reset");
 		if (ret < 0) {
 			dev_err(&dssdev->dev, "couldn't request reset GPIO\n");
 			goto fail_gpio_req;
@@ -457,14 +458,11 @@ fail_regulator:
 static void tpo_td043_remove(struct omap_dss_device *dssdev)
 {
 	struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev);
-	int nreset_gpio = dssdev->reset_gpio;
 
 	dev_dbg(&dssdev->dev, "remove\n");
 
 	sysfs_remove_group(&dssdev->dev.kobj, &tpo_td043_attr_group);
 	regulator_put(tpo_td043->vcc_reg);
-	if (gpio_is_valid(nreset_gpio))
-		gpio_free(nreset_gpio);
 }
 
 static void tpo_td043_set_timings(struct omap_dss_device *dssdev,
@@ -527,7 +525,6 @@ static int tpo_td043_spi_probe(struct spi_device *spi)
 		return -ENOMEM;
 
 	tpo_td043->spi = spi;
-	tpo_td043->nreset_gpio = dssdev->reset_gpio;
 	dev_set_drvdata(&spi->dev, tpo_td043);
 	g_tpo_td043 = tpo_td043;
 
diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c
index d446bdf..a4b356a 100644
--- a/drivers/video/omap2/dss/apply.c
+++ b/drivers/video/omap2/dss/apply.c
@@ -435,20 +435,27 @@ static inline struct omap_dss_device *dss_mgr_get_device(struct omap_overlay_man
 static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr)
 {
 	unsigned long timeout = msecs_to_jiffies(500);
-	struct omap_dss_device *dssdev = mgr->get_device(mgr);
 	u32 irq;
 	int r;
 
+	if (mgr->output == NULL)
+		return -ENODEV;
+
 	r = dispc_runtime_get();
 	if (r)
 		return r;
 
-	if (dssdev->type == OMAP_DISPLAY_TYPE_VENC)
+	switch (mgr->output->id) {
+	case OMAP_DSS_OUTPUT_VENC:
 		irq = DISPC_IRQ_EVSYNC_ODD;
-	else if (dssdev->type == OMAP_DISPLAY_TYPE_HDMI)
+		break;
+	case OMAP_DSS_OUTPUT_HDMI:
 		irq = DISPC_IRQ_EVSYNC_EVEN;
-	else
+		break;
+	default:
 		irq = dispc_mgr_get_vsync_irq(mgr->id);
+		break;
+	}
 
 	r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
 
diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
index f8779d4..60cc6fe 100644
--- a/drivers/video/omap2/dss/core.c
+++ b/drivers/video/omap2/dss/core.c
@@ -181,10 +181,7 @@ int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *))
 	d = debugfs_create_file(name, S_IRUGO, dss_debugfs_dir,
 			write, &dss_debug_fops);
 
-	if (IS_ERR(d))
-		return PTR_ERR(d);
-
-	return 0;
+	return PTR_RET(d);
 }
 #else /* CONFIG_OMAP2_DSS_DEBUGFS */
 static inline int dss_initialize_debugfs(void)
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index 05ff2b9..8cfa27b 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -97,6 +97,8 @@ static struct {
 
 	int irq;
 
+	unsigned long core_clk_rate;
+
 	u32 fifo_size[DISPC_MAX_NR_FIFOS];
 	/* maps which plane is using a fifo. fifo-id -> plane-id */
 	int fifo_assignment[DISPC_MAX_NR_FIFOS];
@@ -2951,6 +2953,10 @@ static void dispc_mgr_set_lcd_divisor(enum omap_channel channel, u16 lck_div,
 
 	dispc_write_reg(DISPC_DIVISORo(channel),
 			FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0));
+
+	if (dss_has_feature(FEAT_CORE_CLK_DIV) == false &&
+			channel == OMAP_DSS_CHANNEL_LCD)
+		dispc.core_clk_rate = dispc_fclk_rate() / lck_div;
 }
 
 static void dispc_mgr_get_lcd_divisor(enum omap_channel channel, int *lck_div,
@@ -3056,15 +3062,7 @@ unsigned long dispc_mgr_pclk_rate(enum omap_channel channel)
 
 unsigned long dispc_core_clk_rate(void)
 {
-	int lcd;
-	unsigned long fclk = dispc_fclk_rate();
-
-	if (dss_has_feature(FEAT_CORE_CLK_DIV))
-		lcd = REG_GET(DISPC_DIVISOR, 23, 16);
-	else
-		lcd = REG_GET(DISPC_DIVISORo(OMAP_DSS_CHANNEL_LCD), 23, 16);
-
-	return fclk / lcd;
+	return dispc.core_clk_rate;
 }
 
 static unsigned long dispc_plane_pclk_rate(enum omap_plane plane)
@@ -3313,67 +3311,79 @@ static void dispc_dump_regs(struct seq_file *s)
 #undef DUMPREG
 }
 
-/* with fck as input clock rate, find dispc dividers that produce req_pck */
-void dispc_find_clk_divs(unsigned long req_pck, unsigned long fck,
+/* calculate clock rates using dividers in cinfo */
+int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
 		struct dispc_clock_info *cinfo)
 {
-	u16 pcd_min, pcd_max;
-	unsigned long best_pck;
-	u16 best_ld, cur_ld;
-	u16 best_pd, cur_pd;
+	if (cinfo->lck_div > 255 || cinfo->lck_div == 0)
+		return -EINVAL;
+	if (cinfo->pck_div < 1 || cinfo->pck_div > 255)
+		return -EINVAL;
 
-	pcd_min = dss_feat_get_param_min(FEAT_PARAM_DSS_PCD);
-	pcd_max = dss_feat_get_param_max(FEAT_PARAM_DSS_PCD);
+	cinfo->lck = dispc_fclk_rate / cinfo->lck_div;
+	cinfo->pck = cinfo->lck / cinfo->pck_div;
 
-	best_pck = 0;
-	best_ld = 0;
-	best_pd = 0;
+	return 0;
+}
 
-	for (cur_ld = 1; cur_ld <= 255; ++cur_ld) {
-		unsigned long lck = fck / cur_ld;
+bool dispc_div_calc(unsigned long dispc,
+		unsigned long pck_min, unsigned long pck_max,
+		dispc_div_calc_func func, void *data)
+{
+	int lckd, lckd_start, lckd_stop;
+	int pckd, pckd_start, pckd_stop;
+	unsigned long pck, lck;
+	unsigned long lck_max;
+	unsigned long pckd_hw_min, pckd_hw_max;
+	unsigned min_fck_per_pck;
+	unsigned long fck;
 
-		for (cur_pd = pcd_min; cur_pd <= pcd_max; ++cur_pd) {
-			unsigned long pck = lck / cur_pd;
-			long old_delta = abs(best_pck - req_pck);
-			long new_delta = abs(pck - req_pck);
+#ifdef CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK
+	min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
+#else
+	min_fck_per_pck = 0;
+#endif
 
-			if (best_pck == 0 || new_delta < old_delta) {
-				best_pck = pck;
-				best_ld = cur_ld;
-				best_pd = cur_pd;
+	pckd_hw_min = dss_feat_get_param_min(FEAT_PARAM_DSS_PCD);
+	pckd_hw_max = dss_feat_get_param_max(FEAT_PARAM_DSS_PCD);
 
-				if (pck == req_pck)
-					goto found;
-			}
+	lck_max = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
 
-			if (pck < req_pck)
-				break;
-		}
+	pck_min = pck_min ? pck_min : 1;
+	pck_max = pck_max ? pck_max : ULONG_MAX;
 
-		if (lck / pcd_min < req_pck)
-			break;
-	}
+	lckd_start = max(DIV_ROUND_UP(dispc, lck_max), 1ul);
+	lckd_stop = min(dispc / pck_min, 255ul);
 
-found:
-	cinfo->lck_div = best_ld;
-	cinfo->pck_div = best_pd;
-	cinfo->lck = fck / cinfo->lck_div;
-	cinfo->pck = cinfo->lck / cinfo->pck_div;
-}
+	for (lckd = lckd_start; lckd <= lckd_stop; ++lckd) {
+		lck = dispc / lckd;
 
-/* calculate clock rates using dividers in cinfo */
-int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
-		struct dispc_clock_info *cinfo)
-{
-	if (cinfo->lck_div > 255 || cinfo->lck_div == 0)
-		return -EINVAL;
-	if (cinfo->pck_div < 1 || cinfo->pck_div > 255)
-		return -EINVAL;
+		pckd_start = max(DIV_ROUND_UP(lck, pck_max), pckd_hw_min);
+		pckd_stop = min(lck / pck_min, pckd_hw_max);
 
-	cinfo->lck = dispc_fclk_rate / cinfo->lck_div;
-	cinfo->pck = cinfo->lck / cinfo->pck_div;
+		for (pckd = pckd_start; pckd <= pckd_stop; ++pckd) {
+			pck = lck / pckd;
 
-	return 0;
+			/*
+			 * For OMAP2/3 the DISPC fclk is the same as LCD's logic
+			 * clock, which means we're configuring DISPC fclk here
+			 * also. Thus we need to use the calculated lck. For
+			 * OMAP4+ the DISPC fclk is a separate clock.
+			 */
+			if (dss_has_feature(FEAT_CORE_CLK_DIV))
+				fck = dispc_core_clk_rate();
+			else
+				fck = lck;
+
+			if (fck < pck * min_fck_per_pck)
+				continue;
+
+			if (func(lckd, pckd, lck, pck, data))
+				return true;
+		}
+	}
+
+	return false;
 }
 
 void dispc_mgr_set_clock_div(enum omap_channel channel,
@@ -3451,6 +3461,8 @@ static void _omap_dispc_initial_config(void)
 		l = FLD_MOD(l, 1, 0, 0);
 		l = FLD_MOD(l, 1, 23, 16);
 		dispc_write_reg(DISPC_DIVISOR, l);
+
+		dispc.core_clk_rate = dispc_fclk_rate();
 	}
 
 	/* FUNCGATED */
diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c
index 4af136a..abe1a4e2 100644
--- a/drivers/video/omap2/dss/dpi.c
+++ b/drivers/video/omap2/dss/dpi.c
@@ -63,15 +63,29 @@ static struct platform_device *dpi_get_dsidev(enum omap_channel channel)
 	case OMAPDSS_VER_OMAP3630:
 	case OMAPDSS_VER_AM35xx:
 		return NULL;
-	default:
-		break;
-	}
 
-	switch (channel) {
-	case OMAP_DSS_CHANNEL_LCD:
-		return dsi_get_dsidev_from_id(0);
-	case OMAP_DSS_CHANNEL_LCD2:
-		return dsi_get_dsidev_from_id(1);
+	case OMAPDSS_VER_OMAP4430_ES1:
+	case OMAPDSS_VER_OMAP4430_ES2:
+	case OMAPDSS_VER_OMAP4:
+		switch (channel) {
+		case OMAP_DSS_CHANNEL_LCD:
+			return dsi_get_dsidev_from_id(0);
+		case OMAP_DSS_CHANNEL_LCD2:
+			return dsi_get_dsidev_from_id(1);
+		default:
+			return NULL;
+		}
+
+	case OMAPDSS_VER_OMAP5:
+		switch (channel) {
+		case OMAP_DSS_CHANNEL_LCD:
+			return dsi_get_dsidev_from_id(0);
+		case OMAP_DSS_CHANNEL_LCD3:
+			return dsi_get_dsidev_from_id(1);
+		default:
+			return NULL;
+		}
+
 	default:
 		return NULL;
 	}
@@ -91,75 +105,211 @@ static enum omap_dss_clk_source dpi_get_alt_clk_src(enum omap_channel channel)
 	}
 }
 
-static int dpi_set_dsi_clk(struct omap_dss_device *dssdev,
+struct dpi_clk_calc_ctx {
+	struct platform_device *dsidev;
+
+	/* inputs */
+
+	unsigned long pck_min, pck_max;
+
+	/* outputs */
+
+	struct dsi_clock_info dsi_cinfo;
+	struct dss_clock_info dss_cinfo;
+	struct dispc_clock_info dispc_cinfo;
+};
+
+static bool dpi_calc_dispc_cb(int lckd, int pckd, unsigned long lck,
+		unsigned long pck, void *data)
+{
+	struct dpi_clk_calc_ctx *ctx = data;
+
+	/*
+	 * Odd dividers give us uneven duty cycle, causing problem when level
+	 * shifted. So skip all odd dividers when the pixel clock is on the
+	 * higher side.
+	 */
+	if (ctx->pck_min >= 1000000) {
+		if (lckd > 1 && lckd % 2 != 0)
+			return false;
+
+		if (pckd > 1 && pckd % 2 != 0)
+			return false;
+	}
+
+	ctx->dispc_cinfo.lck_div = lckd;
+	ctx->dispc_cinfo.pck_div = pckd;
+	ctx->dispc_cinfo.lck = lck;
+	ctx->dispc_cinfo.pck = pck;
+
+	return true;
+}
+
+
+static bool dpi_calc_hsdiv_cb(int regm_dispc, unsigned long dispc,
+		void *data)
+{
+	struct dpi_clk_calc_ctx *ctx = data;
+
+	/*
+	 * Odd dividers give us uneven duty cycle, causing problem when level
+	 * shifted. So skip all odd dividers when the pixel clock is on the
+	 * higher side.
+	 */
+	if (regm_dispc > 1 && regm_dispc % 2 != 0 && ctx->pck_min >= 1000000)
+		return false;
+
+	ctx->dsi_cinfo.regm_dispc = regm_dispc;
+	ctx->dsi_cinfo.dsi_pll_hsdiv_dispc_clk = dispc;
+
+	return dispc_div_calc(dispc, ctx->pck_min, ctx->pck_max,
+			dpi_calc_dispc_cb, ctx);
+}
+
+
+static bool dpi_calc_pll_cb(int regn, int regm, unsigned long fint,
+		unsigned long pll,
+		void *data)
+{
+	struct dpi_clk_calc_ctx *ctx = data;
+
+	ctx->dsi_cinfo.regn = regn;
+	ctx->dsi_cinfo.regm = regm;
+	ctx->dsi_cinfo.fint = fint;
+	ctx->dsi_cinfo.clkin4ddr = pll;
+
+	return dsi_hsdiv_calc(ctx->dsidev, pll, ctx->pck_min,
+			dpi_calc_hsdiv_cb, ctx);
+}
+
+static bool dpi_calc_dss_cb(int fckd, unsigned long fck, void *data)
+{
+	struct dpi_clk_calc_ctx *ctx = data;
+
+	ctx->dss_cinfo.fck = fck;
+	ctx->dss_cinfo.fck_div = fckd;
+
+	return dispc_div_calc(fck, ctx->pck_min, ctx->pck_max,
+			dpi_calc_dispc_cb, ctx);
+}
+
+static bool dpi_dsi_clk_calc(unsigned long pck, struct dpi_clk_calc_ctx *ctx)
+{
+	unsigned long clkin;
+	unsigned long pll_min, pll_max;
+
+	clkin = dsi_get_pll_clkin(dpi.dsidev);
+
+	memset(ctx, 0, sizeof(*ctx));
+	ctx->dsidev = dpi.dsidev;
+	ctx->pck_min = pck - 1000;
+	ctx->pck_max = pck + 1000;
+	ctx->dsi_cinfo.clkin = clkin;
+
+	pll_min = 0;
+	pll_max = 0;
+
+	return dsi_pll_calc(dpi.dsidev, clkin,
+			pll_min, pll_max,
+			dpi_calc_pll_cb, ctx);
+}
+
+static bool dpi_dss_clk_calc(unsigned long pck, struct dpi_clk_calc_ctx *ctx)
+{
+	int i;
+
+	/*
+	 * DSS fck gives us very few possibilities, so finding a good pixel
+	 * clock may not be possible. We try multiple times to find the clock,
+	 * each time widening the pixel clock range we look for, up to
+	 * +/- 1MHz.
+	 */
+
+	for (i = 0; i < 10; ++i) {
+		bool ok;
+
+		memset(ctx, 0, sizeof(*ctx));
+		if (pck > 1000 * i * i * i)
+			ctx->pck_min = max(pck - 1000 * i * i * i, 0lu);
+		else
+			ctx->pck_min = 0;
+		ctx->pck_max = pck + 1000 * i * i * i;
+
+		ok = dss_div_calc(ctx->pck_min, dpi_calc_dss_cb, ctx);
+		if (ok)
+			return ok;
+	}
+
+	return false;
+}
+
+
+
+static int dpi_set_dsi_clk(enum omap_channel channel,
 		unsigned long pck_req, unsigned long *fck, int *lck_div,
 		int *pck_div)
 {
-	struct omap_overlay_manager *mgr = dssdev->output->manager;
-	struct dsi_clock_info dsi_cinfo;
-	struct dispc_clock_info dispc_cinfo;
+	struct dpi_clk_calc_ctx ctx;
 	int r;
+	bool ok;
 
-	r = dsi_pll_calc_clock_div_pck(dpi.dsidev, pck_req, &dsi_cinfo,
-			&dispc_cinfo);
-	if (r)
-		return r;
+	ok = dpi_dsi_clk_calc(pck_req, &ctx);
+	if (!ok)
+		return -EINVAL;
 
-	r = dsi_pll_set_clock_div(dpi.dsidev, &dsi_cinfo);
+	r = dsi_pll_set_clock_div(dpi.dsidev, &ctx.dsi_cinfo);
 	if (r)
 		return r;
 
-	dss_select_lcd_clk_source(mgr->id,
-			dpi_get_alt_clk_src(mgr->id));
+	dss_select_lcd_clk_source(channel,
+			dpi_get_alt_clk_src(channel));
 
-	dpi.mgr_config.clock_info = dispc_cinfo;
+	dpi.mgr_config.clock_info = ctx.dispc_cinfo;
 
-	*fck = dsi_cinfo.dsi_pll_hsdiv_dispc_clk;
-	*lck_div = dispc_cinfo.lck_div;
-	*pck_div = dispc_cinfo.pck_div;
+	*fck = ctx.dsi_cinfo.dsi_pll_hsdiv_dispc_clk;
+	*lck_div = ctx.dispc_cinfo.lck_div;
+	*pck_div = ctx.dispc_cinfo.pck_div;
 
 	return 0;
 }
 
-static int dpi_set_dispc_clk(struct omap_dss_device *dssdev,
-		unsigned long pck_req, unsigned long *fck, int *lck_div,
-		int *pck_div)
+static int dpi_set_dispc_clk(unsigned long pck_req, unsigned long *fck,
+		int *lck_div, int *pck_div)
 {
-	struct dss_clock_info dss_cinfo;
-	struct dispc_clock_info dispc_cinfo;
+	struct dpi_clk_calc_ctx ctx;
 	int r;
+	bool ok;
 
-	r = dss_calc_clock_div(pck_req, &dss_cinfo, &dispc_cinfo);
-	if (r)
-		return r;
+	ok = dpi_dss_clk_calc(pck_req, &ctx);
+	if (!ok)
+		return -EINVAL;
 
-	r = dss_set_clock_div(&dss_cinfo);
+	r = dss_set_clock_div(&ctx.dss_cinfo);
 	if (r)
 		return r;
 
-	dpi.mgr_config.clock_info = dispc_cinfo;
+	dpi.mgr_config.clock_info = ctx.dispc_cinfo;
 
-	*fck = dss_cinfo.fck;
-	*lck_div = dispc_cinfo.lck_div;
-	*pck_div = dispc_cinfo.pck_div;
+	*fck = ctx.dss_cinfo.fck;
+	*lck_div = ctx.dispc_cinfo.lck_div;
+	*pck_div = ctx.dispc_cinfo.pck_div;
 
 	return 0;
 }
 
-static int dpi_set_mode(struct omap_dss_device *dssdev)
+static int dpi_set_mode(struct omap_overlay_manager *mgr)
 {
 	struct omap_video_timings *t = &dpi.timings;
-	struct omap_overlay_manager *mgr = dssdev->output->manager;
 	int lck_div = 0, pck_div = 0;
 	unsigned long fck = 0;
 	unsigned long pck;
 	int r = 0;
 
 	if (dpi.dsidev)
-		r = dpi_set_dsi_clk(dssdev, t->pixel_clock * 1000, &fck,
+		r = dpi_set_dsi_clk(mgr->id, t->pixel_clock * 1000, &fck,
 				&lck_div, &pck_div);
 	else
-		r = dpi_set_dispc_clk(dssdev, t->pixel_clock * 1000, &fck,
+		r = dpi_set_dispc_clk(t->pixel_clock * 1000, &fck,
 				&lck_div, &pck_div);
 	if (r)
 		return r;
@@ -179,10 +329,8 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)
 	return 0;
 }
 
-static void dpi_config_lcd_manager(struct omap_dss_device *dssdev)
+static void dpi_config_lcd_manager(struct omap_overlay_manager *mgr)
 {
-	struct omap_overlay_manager *mgr = dssdev->output->manager;
-
 	dpi.mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS;
 
 	dpi.mgr_config.stallmode = false;
@@ -197,7 +345,7 @@ static void dpi_config_lcd_manager(struct omap_dss_device *dssdev)
 
 int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
 {
-	struct omap_dss_output *out = dssdev->output;
+	struct omap_dss_output *out = &dpi.output;
 	int r;
 
 	mutex_lock(&dpi.lock);
@@ -230,7 +378,7 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
 	if (r)
 		goto err_get_dispc;
 
-	r = dss_dpi_select_source(dssdev->channel);
+	r = dss_dpi_select_source(out->manager->id);
 	if (r)
 		goto err_src_sel;
 
@@ -244,11 +392,11 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
 			goto err_dsi_pll_init;
 	}
 
-	r = dpi_set_mode(dssdev);
+	r = dpi_set_mode(out->manager);
 	if (r)
 		goto err_set_mode;
 
-	dpi_config_lcd_manager(dssdev);
+	dpi_config_lcd_manager(out->manager);
 
 	mdelay(2);
 
@@ -285,7 +433,7 @@ EXPORT_SYMBOL(omapdss_dpi_display_enable);
 
 void omapdss_dpi_display_disable(struct omap_dss_device *dssdev)
 {
-	struct omap_overlay_manager *mgr = dssdev->output->manager;
+	struct omap_overlay_manager *mgr = dpi.output.manager;
 
 	mutex_lock(&dpi.lock);
 
@@ -324,12 +472,12 @@ EXPORT_SYMBOL(omapdss_dpi_set_timings);
 int dpi_check_timings(struct omap_dss_device *dssdev,
 			struct omap_video_timings *timings)
 {
-	int r;
-	struct omap_overlay_manager *mgr = dssdev->output->manager;
+	struct omap_overlay_manager *mgr = dpi.output.manager;
 	int lck_div, pck_div;
 	unsigned long fck;
 	unsigned long pck;
-	struct dispc_clock_info dispc_cinfo;
+	struct dpi_clk_calc_ctx ctx;
+	bool ok;
 
 	if (mgr && !dispc_mgr_timings_ok(mgr->id, timings))
 		return -EINVAL;
@@ -338,28 +486,21 @@ int dpi_check_timings(struct omap_dss_device *dssdev,
 		return -EINVAL;
 
 	if (dpi.dsidev) {
-		struct dsi_clock_info dsi_cinfo;
-		r = dsi_pll_calc_clock_div_pck(dpi.dsidev,
-				timings->pixel_clock * 1000,
-				&dsi_cinfo, &dispc_cinfo);
-
-		if (r)
-			return r;
+		ok = dpi_dsi_clk_calc(timings->pixel_clock * 1000, &ctx);
+		if (!ok)
+			return -EINVAL;
 
-		fck = dsi_cinfo.dsi_pll_hsdiv_dispc_clk;
+		fck = ctx.dsi_cinfo.dsi_pll_hsdiv_dispc_clk;
 	} else {
-		struct dss_clock_info dss_cinfo;
-		r = dss_calc_clock_div(timings->pixel_clock * 1000,
-				&dss_cinfo, &dispc_cinfo);
+		ok = dpi_dss_clk_calc(timings->pixel_clock * 1000, &ctx);
+		if (!ok)
+			return -EINVAL;
 
-		if (r)
-			return r;
-
-		fck = dss_cinfo.fck;
+		fck = ctx.dss_cinfo.fck;
 	}
 
-	lck_div = dispc_cinfo.lck_div;
-	pck_div = dispc_cinfo.pck_div;
+	lck_div = ctx.dispc_cinfo.lck_div;
+	pck_div = ctx.dispc_cinfo.pck_div;
 
 	pck = fck / lck_div / pck_div / 1000;
 
@@ -401,6 +542,36 @@ static int __init dpi_verify_dsi_pll(struct platform_device *dsidev)
 	return 0;
 }
 
+/*
+ * Return a hardcoded channel for the DPI output. This should work for
+ * current use cases, but this can be later expanded to either resolve
+ * the channel in some more dynamic manner, or get the channel as a user
+ * parameter.
+ */
+static enum omap_channel dpi_get_channel(void)
+{
+	switch (omapdss_get_version()) {
+	case OMAPDSS_VER_OMAP24xx:
+	case OMAPDSS_VER_OMAP34xx_ES1:
+	case OMAPDSS_VER_OMAP34xx_ES3:
+	case OMAPDSS_VER_OMAP3630:
+	case OMAPDSS_VER_AM35xx:
+		return OMAP_DSS_CHANNEL_LCD;
+
+	case OMAPDSS_VER_OMAP4430_ES1:
+	case OMAPDSS_VER_OMAP4430_ES2:
+	case OMAPDSS_VER_OMAP4:
+		return OMAP_DSS_CHANNEL_LCD2;
+
+	case OMAPDSS_VER_OMAP5:
+		return OMAP_DSS_CHANNEL_LCD3;
+
+	default:
+		DSSWARN("unsupported DSS version\n");
+		return OMAP_DSS_CHANNEL_LCD;
+	}
+}
+
 static int __init dpi_init_display(struct omap_dss_device *dssdev)
 {
 	struct platform_device *dsidev;
@@ -421,12 +592,7 @@ static int __init dpi_init_display(struct omap_dss_device *dssdev)
 		dpi.vdds_dsi_reg = vdds_dsi;
 	}
 
-	/*
-	 * XXX We shouldn't need dssdev->channel for this. The dsi pll clock
-	 * source for DPI is SoC integration detail, not something that should
-	 * be configured in the dssdev
-	 */
-	dsidev = dpi_get_dsidev(dssdev->channel);
+	dsidev = dpi_get_dsidev(dpi.output.dispc_channel);
 
 	if (dsidev && dpi_verify_dsi_pll(dsidev)) {
 		dsidev = NULL;
@@ -517,6 +683,8 @@ static void __init dpi_init_output(struct platform_device *pdev)
 	out->pdev = pdev;
 	out->id = OMAP_DSS_OUTPUT_DPI;
 	out->type = OMAP_DISPLAY_TYPE_DPI;
+	out->name = "dpi.0";
+	out->dispc_channel = dpi_get_channel();
 
 	dss_register_output(out);
 }
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 28d41d1..9b1c5ec 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -200,6 +200,11 @@ struct dsi_reg { u16 idx; };
 
 typedef void (*omap_dsi_isr_t) (void *arg, u32 mask);
 
+static int dsi_display_init_dispc(struct platform_device *dsidev,
+	struct omap_overlay_manager *mgr);
+static void dsi_display_uninit_dispc(struct platform_device *dsidev,
+	struct omap_overlay_manager *mgr);
+
 #define DSI_MAX_NR_ISRS                2
 #define DSI_MAX_NR_LANES	5
 
@@ -250,6 +255,24 @@ struct dsi_isr_tables {
 	struct dsi_isr_data isr_table_cio[DSI_MAX_NR_ISRS];
 };
 
+struct dsi_clk_calc_ctx {
+	struct platform_device *dsidev;
+
+	/* inputs */
+
+	const struct omap_dss_dsi_config *config;
+
+	unsigned long req_pck_min, req_pck_nom, req_pck_max;
+
+	/* outputs */
+
+	struct dsi_clock_info dsi_cinfo;
+	struct dispc_clock_info dispc_cinfo;
+
+	struct omap_video_timings dispc_vm;
+	struct omap_dss_dsi_videomode_timings dsi_vm;
+};
+
 struct dsi_data {
 	struct platform_device *pdev;
 	void __iomem	*base;
@@ -261,6 +284,9 @@ struct dsi_data {
 	struct clk *dss_clk;
 	struct clk *sys_clk;
 
+	struct dispc_clock_info user_dispc_cinfo;
+	struct dsi_clock_info user_dsi_cinfo;
+
 	struct dsi_clock_info current_cinfo;
 
 	bool vdds_dsi_enabled;
@@ -324,6 +350,7 @@ struct dsi_data {
 	unsigned long lpdiv_max;
 
 	unsigned num_lanes_supported;
+	unsigned line_buffer_size;
 
 	struct dsi_lane_config lanes[DSI_MAX_NR_LANES];
 	unsigned num_lanes_used;
@@ -1192,15 +1219,33 @@ static unsigned long dsi_fclk_rate(struct platform_device *dsidev)
 	return r;
 }
 
-static int dsi_set_lp_clk_divisor(struct omap_dss_device *dssdev)
+static int dsi_lp_clock_calc(struct dsi_clock_info *cinfo,
+		unsigned long lp_clk_min, unsigned long lp_clk_max)
+{
+	unsigned long dsi_fclk = cinfo->dsi_pll_hsdiv_dsi_clk;
+	unsigned lp_clk_div;
+	unsigned long lp_clk;
+
+	lp_clk_div = DIV_ROUND_UP(dsi_fclk, lp_clk_max * 2);
+	lp_clk = dsi_fclk / 2 / lp_clk_div;
+
+	if (lp_clk < lp_clk_min || lp_clk > lp_clk_max)
+		return -EINVAL;
+
+	cinfo->lp_clk_div = lp_clk_div;
+	cinfo->lp_clk = lp_clk;
+
+	return 0;
+}
+
+static int dsi_set_lp_clk_divisor(struct platform_device *dsidev)
 {
-	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
 	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
 	unsigned long dsi_fclk;
 	unsigned lp_clk_div;
 	unsigned long lp_clk;
 
-	lp_clk_div = dssdev->clocks.dsi.lp_clk_div;
+	lp_clk_div = dsi->user_dsi_cinfo.lp_clk_div;
 
 	if (lp_clk_div == 0 || lp_clk_div > dsi->lpdiv_max)
 		return -EINVAL;
@@ -1272,6 +1317,75 @@ static int dsi_pll_power(struct platform_device *dsidev,
 	return 0;
 }
 
+unsigned long dsi_get_pll_clkin(struct platform_device *dsidev)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	return clk_get_rate(dsi->sys_clk);
+}
+
+bool dsi_hsdiv_calc(struct platform_device *dsidev, unsigned long pll,
+		unsigned long out_min, dsi_hsdiv_calc_func func, void *data)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	int regm, regm_start, regm_stop;
+	unsigned long out_max;
+	unsigned long out;
+
+	out_min = out_min ? out_min : 1;
+	out_max = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
+
+	regm_start = max(DIV_ROUND_UP(pll, out_max), 1ul);
+	regm_stop = min(pll / out_min, dsi->regm_dispc_max);
+
+	for (regm = regm_start; regm <= regm_stop; ++regm) {
+		out = pll / regm;
+
+		if (func(regm, out, data))
+			return true;
+	}
+
+	return false;
+}
+
+bool dsi_pll_calc(struct platform_device *dsidev, unsigned long clkin,
+		unsigned long pll_min, unsigned long pll_max,
+		dsi_pll_calc_func func, void *data)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	int regn, regn_start, regn_stop;
+	int regm, regm_start, regm_stop;
+	unsigned long fint, pll;
+	const unsigned long pll_hw_max = 1800000000;
+	unsigned long fint_hw_min, fint_hw_max;
+
+	fint_hw_min = dsi->fint_min;
+	fint_hw_max = dsi->fint_max;
+
+	regn_start = max(DIV_ROUND_UP(clkin, fint_hw_max), 1ul);
+	regn_stop = min(clkin / fint_hw_min, dsi->regn_max);
+
+	pll_max = pll_max ? pll_max : ULONG_MAX;
+
+	for (regn = regn_start; regn <= regn_stop; ++regn) {
+		fint = clkin / regn;
+
+		regm_start = max(DIV_ROUND_UP(DIV_ROUND_UP(pll_min, fint), 2),
+				1ul);
+		regm_stop = min3(pll_max / fint / 2,
+				pll_hw_max / fint / 2,
+				dsi->regm_max);
+
+		for (regm = regm_start; regm <= regm_stop; ++regm) {
+			pll = 2 * regm * fint;
+
+			if (func(regn, regm, fint, pll, data))
+				return true;
+		}
+	}
+
+	return false;
+}
+
 /* calculate clock rates using dividers in cinfo */
 static int dsi_calc_clock_rates(struct platform_device *dsidev,
 		struct dsi_clock_info *cinfo)
@@ -1316,192 +1430,7 @@ static int dsi_calc_clock_rates(struct platform_device *dsidev,
 	return 0;
 }
 
-int dsi_pll_calc_clock_div_pck(struct platform_device *dsidev,
-		unsigned long req_pck, struct dsi_clock_info *dsi_cinfo,
-		struct dispc_clock_info *dispc_cinfo)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	struct dsi_clock_info cur, best;
-	struct dispc_clock_info best_dispc;
-	int min_fck_per_pck;
-	int match = 0;
-	unsigned long dss_sys_clk, max_dss_fck;
-
-	dss_sys_clk = clk_get_rate(dsi->sys_clk);
-
-	max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
-
-	if (req_pck == dsi->cache_req_pck &&
-			dsi->cache_cinfo.clkin == dss_sys_clk) {
-		DSSDBG("DSI clock info found from cache\n");
-		*dsi_cinfo = dsi->cache_cinfo;
-		dispc_find_clk_divs(req_pck, dsi_cinfo->dsi_pll_hsdiv_dispc_clk,
-			dispc_cinfo);
-		return 0;
-	}
-
-	min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
-
-	if (min_fck_per_pck &&
-		req_pck * min_fck_per_pck > max_dss_fck) {
-		DSSERR("Requested pixel clock not possible with the current "
-				"OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning "
-				"the constraint off.\n");
-		min_fck_per_pck = 0;
-	}
-
-	DSSDBG("dsi_pll_calc\n");
-
-retry:
-	memset(&best, 0, sizeof(best));
-	memset(&best_dispc, 0, sizeof(best_dispc));
-
-	memset(&cur, 0, sizeof(cur));
-	cur.clkin = dss_sys_clk;
-
-	/* 0.75MHz < Fint = clkin / regn < 2.1MHz */
-	/* To reduce PLL lock time, keep Fint high (around 2 MHz) */
-	for (cur.regn = 1; cur.regn < dsi->regn_max; ++cur.regn) {
-		cur.fint = cur.clkin / cur.regn;
-
-		if (cur.fint > dsi->fint_max || cur.fint < dsi->fint_min)
-			continue;
-
-		/* DSIPHY(MHz) = (2 * regm / regn) * clkin */
-		for (cur.regm = 1; cur.regm < dsi->regm_max; ++cur.regm) {
-			unsigned long a, b;
-
-			a = 2 * cur.regm * (cur.clkin/1000);
-			b = cur.regn;
-			cur.clkin4ddr = a / b * 1000;
-
-			if (cur.clkin4ddr > 1800 * 1000 * 1000)
-				break;
-
-			/* dsi_pll_hsdiv_dispc_clk(MHz) =
-			 * DSIPHY(MHz) / regm_dispc  < 173MHz/186Mhz */
-			for (cur.regm_dispc = 1; cur.regm_dispc <
-					dsi->regm_dispc_max; ++cur.regm_dispc) {
-				struct dispc_clock_info cur_dispc;
-				cur.dsi_pll_hsdiv_dispc_clk =
-					cur.clkin4ddr / cur.regm_dispc;
-
-				if (cur.regm_dispc > 1 &&
-						cur.regm_dispc % 2 != 0 &&
-						req_pck >= 1000000)
-					continue;
-
-				/* this will narrow down the search a bit,
-				 * but still give pixclocks below what was
-				 * requested */
-				if (cur.dsi_pll_hsdiv_dispc_clk  < req_pck)
-					break;
-
-				if (cur.dsi_pll_hsdiv_dispc_clk > max_dss_fck)
-					continue;
-
-				if (min_fck_per_pck &&
-					cur.dsi_pll_hsdiv_dispc_clk <
-						req_pck * min_fck_per_pck)
-					continue;
-
-				match = 1;
-
-				dispc_find_clk_divs(req_pck,
-						cur.dsi_pll_hsdiv_dispc_clk,
-						&cur_dispc);
-
-				if (abs(cur_dispc.pck - req_pck) <
-						abs(best_dispc.pck - req_pck)) {
-					best = cur;
-					best_dispc = cur_dispc;
-
-					if (cur_dispc.pck == req_pck)
-						goto found;
-				}
-			}
-		}
-	}
-found:
-	if (!match) {
-		if (min_fck_per_pck) {
-			DSSERR("Could not find suitable clock settings.\n"
-					"Turning FCK/PCK constraint off and"
-					"trying again.\n");
-			min_fck_per_pck = 0;
-			goto retry;
-		}
-
-		DSSERR("Could not find suitable clock settings.\n");
-
-		return -EINVAL;
-	}
-
-	/* dsi_pll_hsdiv_dsi_clk (regm_dsi) is not used */
-	best.regm_dsi = 0;
-	best.dsi_pll_hsdiv_dsi_clk = 0;
-
-	if (dsi_cinfo)
-		*dsi_cinfo = best;
-	if (dispc_cinfo)
-		*dispc_cinfo = best_dispc;
-
-	dsi->cache_req_pck = req_pck;
-	dsi->cache_clk_freq = 0;
-	dsi->cache_cinfo = best;
-
-	return 0;
-}
-
-static int dsi_pll_calc_ddrfreq(struct platform_device *dsidev,
-		unsigned long req_clkin4ddr, struct dsi_clock_info *cinfo)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	struct dsi_clock_info cur, best;
-
-	DSSDBG("dsi_pll_calc_ddrfreq\n");
-
-	memset(&best, 0, sizeof(best));
-	memset(&cur, 0, sizeof(cur));
-
-	cur.clkin = clk_get_rate(dsi->sys_clk);
-
-	for (cur.regn = 1; cur.regn < dsi->regn_max; ++cur.regn) {
-		cur.fint = cur.clkin / cur.regn;
-
-		if (cur.fint > dsi->fint_max || cur.fint < dsi->fint_min)
-			continue;
-
-		/* DSIPHY(MHz) = (2 * regm / regn) * clkin */
-		for (cur.regm = 1; cur.regm < dsi->regm_max; ++cur.regm) {
-			unsigned long a, b;
-
-			a = 2 * cur.regm * (cur.clkin/1000);
-			b = cur.regn;
-			cur.clkin4ddr = a / b * 1000;
-
-			if (cur.clkin4ddr > 1800 * 1000 * 1000)
-				break;
-
-			if (abs(cur.clkin4ddr - req_clkin4ddr) <
-					abs(best.clkin4ddr - req_clkin4ddr)) {
-				best = cur;
-				DSSDBG("best %ld\n", best.clkin4ddr);
-			}
-
-			if (cur.clkin4ddr == req_clkin4ddr)
-				goto found;
-		}
-	}
-found:
-	if (cinfo)
-		*cinfo = best;
-
-	return 0;
-}
-
-static void dsi_pll_calc_dsi_fck(struct platform_device *dsidev,
-		struct dsi_clock_info *cinfo)
+static void dsi_pll_calc_dsi_fck(struct dsi_clock_info *cinfo)
 {
 	unsigned long max_dsi_fck;
 
@@ -1511,90 +1440,6 @@ static void dsi_pll_calc_dsi_fck(struct platform_device *dsidev,
 	cinfo->dsi_pll_hsdiv_dsi_clk = cinfo->clkin4ddr / cinfo->regm_dsi;
 }
 
-static int dsi_pll_calc_dispc_fck(struct platform_device *dsidev,
-		unsigned long req_pck, struct dsi_clock_info *cinfo,
-		struct dispc_clock_info *dispc_cinfo)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	unsigned regm_dispc, best_regm_dispc;
-	unsigned long dispc_clk, best_dispc_clk;
-	int min_fck_per_pck;
-	unsigned long max_dss_fck;
-	struct dispc_clock_info best_dispc;
-	bool match;
-
-	max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
-
-	min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
-
-	if (min_fck_per_pck &&
-			req_pck * min_fck_per_pck > max_dss_fck) {
-		DSSERR("Requested pixel clock not possible with the current "
-				"OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning "
-				"the constraint off.\n");
-		min_fck_per_pck = 0;
-	}
-
-retry:
-	best_regm_dispc = 0;
-	best_dispc_clk = 0;
-	memset(&best_dispc, 0, sizeof(best_dispc));
-	match = false;
-
-	for (regm_dispc = 1; regm_dispc < dsi->regm_dispc_max; ++regm_dispc) {
-		struct dispc_clock_info cur_dispc;
-
-		dispc_clk = cinfo->clkin4ddr / regm_dispc;
-
-		/* this will narrow down the search a bit,
-		 * but still give pixclocks below what was
-		 * requested */
-		if (dispc_clk  < req_pck)
-			break;
-
-		if (dispc_clk > max_dss_fck)
-			continue;
-
-		if (min_fck_per_pck && dispc_clk < req_pck * min_fck_per_pck)
-			continue;
-
-		match = true;
-
-		dispc_find_clk_divs(req_pck, dispc_clk, &cur_dispc);
-
-		if (abs(cur_dispc.pck - req_pck) <
-				abs(best_dispc.pck - req_pck)) {
-			best_regm_dispc = regm_dispc;
-			best_dispc_clk = dispc_clk;
-			best_dispc = cur_dispc;
-
-			if (cur_dispc.pck == req_pck)
-				goto found;
-		}
-	}
-
-	if (!match) {
-		if (min_fck_per_pck) {
-			DSSERR("Could not find suitable clock settings.\n"
-					"Turning FCK/PCK constraint off and"
-					"trying again.\n");
-			min_fck_per_pck = 0;
-			goto retry;
-		}
-
-		DSSERR("Could not find suitable clock settings.\n");
-
-		return -EINVAL;
-	}
-found:
-	cinfo->regm_dispc = best_regm_dispc;
-	cinfo->dsi_pll_hsdiv_dispc_clk = best_dispc_clk;
-
-	*dispc_cinfo = best_dispc;
-
-	return 0;
-}
-
 int dsi_pll_set_clock_div(struct platform_device *dsidev,
 		struct dsi_clock_info *cinfo)
 {
@@ -2783,6 +2628,7 @@ static int dsi_vc_enable(struct platform_device *dsidev, int channel,
 
 static void dsi_vc_initial_config(struct platform_device *dsidev, int channel)
 {
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
 	u32 r;
 
 	DSSDBG("Initial config of virtual channel %d", channel);
@@ -2807,6 +2653,8 @@ static void dsi_vc_initial_config(struct platform_device *dsidev, int channel)
 	r = FLD_MOD(r, 4, 23, 21); /* DMA_TX_REQ_NB = no dma */
 
 	dsi_write_reg(dsidev, DSI_VC_CTRL(channel), r);
+
+	dsi->vc[channel].source = DSI_VC_SOURCE_L4;
 }
 
 static int dsi_vc_config_source(struct platform_device *dsidev, int channel,
@@ -3777,13 +3625,12 @@ static void dsi_config_vp_num_line_buffers(struct platform_device *dsidev)
 
 	if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
 		int bpp = dsi_get_pixel_size(dsi->pix_fmt);
-		unsigned line_buf_size = dsi_get_line_buf_size(dsidev);
 		struct omap_video_timings *timings = &dsi->timings;
 		/*
 		 * Don't use line buffers if width is greater than the video
 		 * port's line buffer size
 		 */
-		if (line_buf_size <= timings->x_res * bpp / 8)
+		if (dsi->line_buffer_size <= timings->x_res * bpp / 8)
 			num_line_buffers = 0;
 		else
 			num_line_buffers = 2;
@@ -3799,18 +3646,22 @@ static void dsi_config_vp_num_line_buffers(struct platform_device *dsidev)
 static void dsi_config_vp_sync_events(struct platform_device *dsidev)
 {
 	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	bool vsync_end = dsi->vm_timings.vp_vsync_end;
-	bool hsync_end = dsi->vm_timings.vp_hsync_end;
+	bool sync_end;
 	u32 r;
 
+	if (dsi->vm_timings.trans_mode == OMAP_DSS_DSI_PULSE_MODE)
+		sync_end = true;
+	else
+		sync_end = false;
+
 	r = dsi_read_reg(dsidev, DSI_CTRL);
 	r = FLD_MOD(r, 1, 9, 9);		/* VP_DE_POL */
 	r = FLD_MOD(r, 1, 10, 10);		/* VP_HSYNC_POL */
 	r = FLD_MOD(r, 1, 11, 11);		/* VP_VSYNC_POL */
 	r = FLD_MOD(r, 1, 15, 15);		/* VP_VSYNC_START */
-	r = FLD_MOD(r, vsync_end, 16, 16);	/* VP_VSYNC_END */
+	r = FLD_MOD(r, sync_end, 16, 16);	/* VP_VSYNC_END */
 	r = FLD_MOD(r, 1, 17, 17);		/* VP_HSYNC_START */
-	r = FLD_MOD(r, hsync_end, 18, 18);	/* VP_HSYNC_END */
+	r = FLD_MOD(r, sync_end, 18, 18);	/* VP_HSYNC_END */
 	dsi_write_reg(dsidev, DSI_CTRL, r);
 }
 
@@ -3897,9 +3748,8 @@ static int dsi_compute_interleave_lp(int blank, int enter_hs, int exit_hs,
 	return max(lp_inter, 0);
 }
 
-static void dsi_config_cmd_mode_interleaving(struct omap_dss_device *dssdev)
+static void dsi_config_cmd_mode_interleaving(struct platform_device *dsidev)
 {
-	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
 	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
 	int blanking_mode;
 	int hfp_blanking_mode, hbp_blanking_mode, hsa_blanking_mode;
@@ -3910,7 +3760,7 @@ static void dsi_config_cmd_mode_interleaving(struct omap_dss_device *dssdev)
 	struct omap_video_timings *timings = &dsi->timings;
 	int bpp = dsi_get_pixel_size(dsi->pix_fmt);
 	int ndl = dsi->num_lanes_used - 1;
-	int dsi_fclk_hsdiv = dssdev->clocks.dsi.regm_dsi + 1;
+	int dsi_fclk_hsdiv = dsi->user_dsi_cinfo.regm_dsi + 1;
 	int hsa_interleave_hs = 0, hsa_interleave_lp = 0;
 	int hfp_interleave_hs = 0, hfp_interleave_lp = 0;
 	int hbp_interleave_hs = 0, hbp_interleave_lp = 0;
@@ -4015,9 +3865,8 @@ static void dsi_config_cmd_mode_interleaving(struct omap_dss_device *dssdev)
 	dsi_write_reg(dsidev, DSI_VM_TIMING6, r);
 }
 
-static int dsi_proto_config(struct omap_dss_device *dssdev)
+static int dsi_proto_config(struct platform_device *dsidev)
 {
-	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
 	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
 	u32 r;
 	int buswidth = 0;
@@ -4075,7 +3924,7 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)
 	if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
 		dsi_config_vp_sync_events(dsidev);
 		dsi_config_blanking_modes(dsidev);
-		dsi_config_cmd_mode_interleaving(dssdev);
+		dsi_config_cmd_mode_interleaving(dsidev);
 	}
 
 	dsi_vc_initial_config(dsidev, 0);
@@ -4159,11 +4008,12 @@ static void dsi_proto_timings(struct platform_device *dsidev)
 		int vfp = dsi->vm_timings.vfp;
 		int vbp = dsi->vm_timings.vbp;
 		int window_sync = dsi->vm_timings.window_sync;
-		bool hsync_end = dsi->vm_timings.vp_hsync_end;
+		bool hsync_end;
 		struct omap_video_timings *timings = &dsi->timings;
 		int bpp = dsi_get_pixel_size(dsi->pix_fmt);
 		int tl, t_he, width_bytes;
 
+		hsync_end = dsi->vm_timings.trans_mode == OMAP_DSS_DSI_PULSE_MODE;
 		t_he = hsync_end ?
 			((hsa == 0 && ndl == 3) ? 1 : DIV_ROUND_UP(4, ndl)) : 0;
 
@@ -4266,82 +4116,26 @@ int omapdss_dsi_configure_pins(struct omap_dss_device *dssdev,
 }
 EXPORT_SYMBOL(omapdss_dsi_configure_pins);
 
-int omapdss_dsi_set_clocks(struct omap_dss_device *dssdev,
-		unsigned long ddr_clk, unsigned long lp_clk)
-{
-	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	struct dsi_clock_info cinfo;
-	struct dispc_clock_info dispc_cinfo;
-	unsigned lp_clk_div;
-	unsigned long dsi_fclk;
-	int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt);
-	unsigned long pck;
-	int r;
-
-	DSSDBG("Setting DSI clocks: ddr_clk %lu, lp_clk %lu", ddr_clk, lp_clk);
-
-	mutex_lock(&dsi->lock);
-
-	/* Calculate PLL output clock */
-	r = dsi_pll_calc_ddrfreq(dsidev, ddr_clk * 4, &cinfo);
-	if (r)
-		goto err;
-
-	/* Calculate PLL's DSI clock */
-	dsi_pll_calc_dsi_fck(dsidev, &cinfo);
-
-	/* Calculate PLL's DISPC clock and pck & lck divs */
-	pck = cinfo.clkin4ddr / 16 * (dsi->num_lanes_used - 1) * 8 / bpp;
-	DSSDBG("finding dispc dividers for pck %lu\n", pck);
-	r = dsi_pll_calc_dispc_fck(dsidev, pck, &cinfo, &dispc_cinfo);
-	if (r)
-		goto err;
-
-	/* Calculate LP clock */
-	dsi_fclk = cinfo.dsi_pll_hsdiv_dsi_clk;
-	lp_clk_div = DIV_ROUND_UP(dsi_fclk, lp_clk * 2);
-
-	dssdev->clocks.dsi.regn = cinfo.regn;
-	dssdev->clocks.dsi.regm = cinfo.regm;
-	dssdev->clocks.dsi.regm_dispc = cinfo.regm_dispc;
-	dssdev->clocks.dsi.regm_dsi = cinfo.regm_dsi;
-
-	dssdev->clocks.dsi.lp_clk_div = lp_clk_div;
-
-	dssdev->clocks.dispc.channel.lck_div = dispc_cinfo.lck_div;
-	dssdev->clocks.dispc.channel.pck_div = dispc_cinfo.pck_div;
-
-	dssdev->clocks.dispc.dispc_fclk_src = OMAP_DSS_CLK_SRC_FCK;
-
-	dssdev->clocks.dispc.channel.lcd_clk_src =
-		dsi->module_id == 0 ?
-		OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC :
-		OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC;
-
-	dssdev->clocks.dsi.dsi_fclk_src =
-		dsi->module_id == 0 ?
-		OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI :
-		OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI;
-
-	mutex_unlock(&dsi->lock);
-	return 0;
-err:
-	mutex_unlock(&dsi->lock);
-	return r;
-}
-EXPORT_SYMBOL(omapdss_dsi_set_clocks);
-
 int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
 {
 	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
 	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	struct omap_overlay_manager *mgr = dssdev->output->manager;
+	struct omap_overlay_manager *mgr = dsi->output.manager;
 	int bpp = dsi_get_pixel_size(dsi->pix_fmt);
+	struct omap_dss_output *out = &dsi->output;
 	u8 data_type;
 	u16 word_count;
 	int r;
 
+	if (out == NULL || out->manager == NULL) {
+		DSSERR("failed to enable display: no output/manager\n");
+		return -ENODEV;
+	}
+
+	r = dsi_display_init_dispc(dsidev, mgr);
+	if (r)
+		goto err_init_dispc;
+
 	if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
 		switch (dsi->pix_fmt) {
 		case OMAP_DSS_DSI_FMT_RGB888:
@@ -4357,8 +4151,8 @@ int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
 			data_type = MIPI_DSI_PACKED_PIXEL_STREAM_16;
 			break;
 		default:
-			BUG();
-			return -EINVAL;
+			r = -EINVAL;
+			goto err_pix_fmt;
 		};
 
 		dsi_if_enable(dsidev, false);
@@ -4377,16 +4171,20 @@ int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
 	}
 
 	r = dss_mgr_enable(mgr);
-	if (r) {
-		if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
-			dsi_if_enable(dsidev, false);
-			dsi_vc_enable(dsidev, channel, false);
-		}
-
-		return r;
-	}
+	if (r)
+		goto err_mgr_enable;
 
 	return 0;
+
+err_mgr_enable:
+	if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
+		dsi_if_enable(dsidev, false);
+		dsi_vc_enable(dsidev, channel, false);
+	}
+err_pix_fmt:
+	dsi_display_uninit_dispc(dsidev, mgr);
+err_init_dispc:
+	return r;
 }
 EXPORT_SYMBOL(dsi_enable_video_output);
 
@@ -4394,7 +4192,7 @@ void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel)
 {
 	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
 	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	struct omap_overlay_manager *mgr = dssdev->output->manager;
+	struct omap_overlay_manager *mgr = dsi->output.manager;
 
 	if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
 		dsi_if_enable(dsidev, false);
@@ -4408,14 +4206,15 @@ void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel)
 	}
 
 	dss_mgr_disable(mgr);
+
+	dsi_display_uninit_dispc(dsidev, mgr);
 }
 EXPORT_SYMBOL(dsi_disable_video_output);
 
-static void dsi_update_screen_dispc(struct omap_dss_device *dssdev)
+static void dsi_update_screen_dispc(struct platform_device *dsidev)
 {
-	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
 	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	struct omap_overlay_manager *mgr = dssdev->output->manager;
+	struct omap_overlay_manager *mgr = dsi->output.manager;
 	unsigned bytespp;
 	unsigned bytespl;
 	unsigned bytespf;
@@ -4425,7 +4224,7 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev)
 	u32 l;
 	int r;
 	const unsigned channel = dsi->update_channel;
-	const unsigned line_buf_size = dsi_get_line_buf_size(dsidev);
+	const unsigned line_buf_size = dsi->line_buffer_size;
 	u16 w = dsi->timings.x_res;
 	u16 h = dsi->timings.y_res;
 
@@ -4571,7 +4370,7 @@ int omap_dsi_update(struct omap_dss_device *dssdev, int channel,
 	dsi->update_bytes = dw * dh *
 		dsi_get_pixel_size(dsi->pix_fmt) / 8;
 #endif
-	dsi_update_screen_dispc(dssdev);
+	dsi_update_screen_dispc(dsidev);
 
 	return 0;
 }
@@ -4579,18 +4378,17 @@ EXPORT_SYMBOL(omap_dsi_update);
 
 /* Display funcs */
 
-static int dsi_configure_dispc_clocks(struct omap_dss_device *dssdev)
+static int dsi_configure_dispc_clocks(struct platform_device *dsidev)
 {
-	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
 	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
 	struct dispc_clock_info dispc_cinfo;
 	int r;
-	unsigned long long fck;
+	unsigned long fck;
 
 	fck = dsi_get_pll_hsdiv_dispc_rate(dsidev);
 
-	dispc_cinfo.lck_div = dssdev->clocks.dispc.channel.lck_div;
-	dispc_cinfo.pck_div = dssdev->clocks.dispc.channel.pck_div;
+	dispc_cinfo.lck_div = dsi->user_dispc_cinfo.lck_div;
+	dispc_cinfo.pck_div = dsi->user_dispc_cinfo.pck_div;
 
 	r = dispc_calc_clock_rates(fck, &dispc_cinfo);
 	if (r) {
@@ -4603,21 +4401,17 @@ static int dsi_configure_dispc_clocks(struct omap_dss_device *dssdev)
 	return 0;
 }
 
-static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
+static int dsi_display_init_dispc(struct platform_device *dsidev,
+		struct omap_overlay_manager *mgr)
 {
-	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
 	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	struct omap_overlay_manager *mgr = dssdev->output->manager;
 	int r;
 
-	if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) {
-		dsi->timings.hsw = 1;
-		dsi->timings.hfp = 1;
-		dsi->timings.hbp = 1;
-		dsi->timings.vsw = 1;
-		dsi->timings.vfp = 0;
-		dsi->timings.vbp = 0;
+	dss_select_lcd_clk_source(mgr->id, dsi->module_id == 0 ?
+			OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC :
+			OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC);
 
+	if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) {
 		r = dss_mgr_register_framedone_handler(mgr,
 				dsi_framedone_irq_callback, dsidev);
 		if (r) {
@@ -4645,7 +4439,7 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
 
 	dss_mgr_set_timings(mgr, &dsi->timings);
 
-	r = dsi_configure_dispc_clocks(dssdev);
+	r = dsi_configure_dispc_clocks(dsidev);
 	if (r)
 		goto err1;
 
@@ -4662,30 +4456,30 @@ err1:
 		dss_mgr_unregister_framedone_handler(mgr,
 				dsi_framedone_irq_callback, dsidev);
 err:
+	dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK);
 	return r;
 }
 
-static void dsi_display_uninit_dispc(struct omap_dss_device *dssdev)
+static void dsi_display_uninit_dispc(struct platform_device *dsidev,
+		struct omap_overlay_manager *mgr)
 {
-	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
 	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	struct omap_overlay_manager *mgr = dssdev->output->manager;
 
 	if (dsi->mode == OMAP_DSS_DSI_CMD_MODE)
 		dss_mgr_unregister_framedone_handler(mgr,
 				dsi_framedone_irq_callback, dsidev);
+
+	dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK);
 }
 
-static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev)
+static int dsi_configure_dsi_clocks(struct platform_device *dsidev)
 {
-	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
 	struct dsi_clock_info cinfo;
 	int r;
 
-	cinfo.regn  = dssdev->clocks.dsi.regn;
-	cinfo.regm  = dssdev->clocks.dsi.regm;
-	cinfo.regm_dispc = dssdev->clocks.dsi.regm_dispc;
-	cinfo.regm_dsi = dssdev->clocks.dsi.regm_dsi;
+	cinfo = dsi->user_dsi_cinfo;
+
 	r = dsi_calc_clock_rates(dsidev, &cinfo);
 	if (r) {
 		DSSERR("Failed to calc dsi clocks\n");
@@ -4701,24 +4495,22 @@ static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev)
 	return 0;
 }
 
-static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
+static int dsi_display_init_dsi(struct platform_device *dsidev)
 {
-	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
 	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	struct omap_overlay_manager *mgr = dssdev->output->manager;
 	int r;
 
 	r = dsi_pll_init(dsidev, true, true);
 	if (r)
 		goto err0;
 
-	r = dsi_configure_dsi_clocks(dssdev);
+	r = dsi_configure_dsi_clocks(dsidev);
 	if (r)
 		goto err1;
 
-	dss_select_dsi_clk_source(dsi->module_id, dssdev->clocks.dsi.dsi_fclk_src);
-	dss_select_lcd_clk_source(mgr->id,
-			dssdev->clocks.dispc.channel.lcd_clk_src);
+	dss_select_dsi_clk_source(dsi->module_id, dsi->module_id == 0 ?
+			OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI :
+			OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI);
 
 	DSSDBG("PLL OK\n");
 
@@ -4729,12 +4521,12 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
 	_dsi_print_reset_status(dsidev);
 
 	dsi_proto_timings(dsidev);
-	dsi_set_lp_clk_divisor(dssdev);
+	dsi_set_lp_clk_divisor(dsidev);
 
 	if (1)
 		_dsi_print_reset_status(dsidev);
 
-	r = dsi_proto_config(dssdev);
+	r = dsi_proto_config(dsidev);
 	if (r)
 		goto err3;
 
@@ -4751,20 +4543,16 @@ err3:
 	dsi_cio_uninit(dsidev);
 err2:
 	dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK);
-	dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK);
-
 err1:
 	dsi_pll_uninit(dsidev, true);
 err0:
 	return r;
 }
 
-static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev,
+static void dsi_display_uninit_dsi(struct platform_device *dsidev,
 		bool disconnect_lanes, bool enter_ulps)
 {
-	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
 	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	struct omap_overlay_manager *mgr = dssdev->output->manager;
 
 	if (enter_ulps && !dsi->ulps_enabled)
 		dsi_enter_ulps(dsidev);
@@ -4777,7 +4565,6 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev,
 	dsi_vc_enable(dsidev, 3, 0);
 
 	dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK);
-	dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK);
 	dsi_cio_uninit(dsidev);
 	dsi_pll_uninit(dsidev, disconnect_lanes);
 }
@@ -4786,7 +4573,6 @@ int omapdss_dsi_display_enable(struct omap_dss_device *dssdev)
 {
 	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
 	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	struct omap_dss_output *out = dssdev->output;
 	int r = 0;
 
 	DSSDBG("dsi_display_enable\n");
@@ -4795,12 +4581,6 @@ int omapdss_dsi_display_enable(struct omap_dss_device *dssdev)
 
 	mutex_lock(&dsi->lock);
 
-	if (out == NULL || out->manager == NULL) {
-		DSSERR("failed to enable display: no output/manager\n");
-		r = -ENODEV;
-		goto err_start_dev;
-	}
-
 	r = omap_dss_start_device(dssdev);
 	if (r) {
 		DSSERR("failed to start device\n");
@@ -4815,11 +4595,7 @@ int omapdss_dsi_display_enable(struct omap_dss_device *dssdev)
 
 	_dsi_initialize_irq(dsidev);
 
-	r = dsi_display_init_dispc(dssdev);
-	if (r)
-		goto err_init_dispc;
-
-	r = dsi_display_init_dsi(dssdev);
+	r = dsi_display_init_dsi(dsidev);
 	if (r)
 		goto err_init_dsi;
 
@@ -4828,8 +4604,6 @@ int omapdss_dsi_display_enable(struct omap_dss_device *dssdev)
 	return 0;
 
 err_init_dsi:
-	dsi_display_uninit_dispc(dssdev);
-err_init_dispc:
 	dsi_enable_pll_clock(dsidev, 0);
 	dsi_runtime_put(dsidev);
 err_get_dsi:
@@ -4858,9 +4632,7 @@ void omapdss_dsi_display_disable(struct omap_dss_device *dssdev,
 	dsi_sync_vc(dsidev, 2);
 	dsi_sync_vc(dsidev, 3);
 
-	dsi_display_uninit_dispc(dssdev);
-
-	dsi_display_uninit_dsi(dssdev, disconnect_lanes, enter_ulps);
+	dsi_display_uninit_dsi(dsidev, disconnect_lanes, enter_ulps);
 
 	dsi_runtime_put(dsidev);
 	dsi_enable_pll_clock(dsidev, 0);
@@ -4881,75 +4653,577 @@ int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable)
 }
 EXPORT_SYMBOL(omapdss_dsi_enable_te);
 
-void omapdss_dsi_set_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
+#ifdef PRINT_VERBOSE_VM_TIMINGS
+static void print_dsi_vm(const char *str,
+		const struct omap_dss_dsi_videomode_timings *t)
+{
+	unsigned long byteclk = t->hsclk / 4;
+	int bl, wc, pps, tot;
+
+	wc = DIV_ROUND_UP(t->hact * t->bitspp, 8);
+	pps = DIV_ROUND_UP(wc + 6, t->ndl); /* pixel packet size */
+	bl = t->hss + t->hsa + t->hse + t->hbp + t->hfp;
+	tot = bl + pps;
+
+#define TO_DSI_T(x) ((u32)div64_u64((u64)x * 1000000000llu, byteclk))
+
+	pr_debug("%s bck %lu, %u/%u/%u/%u/%u/%u = %u+%u = %u, "
+			"%u/%u/%u/%u/%u/%u = %u + %u = %u\n",
+			str,
+			byteclk,
+			t->hss, t->hsa, t->hse, t->hbp, pps, t->hfp,
+			bl, pps, tot,
+			TO_DSI_T(t->hss),
+			TO_DSI_T(t->hsa),
+			TO_DSI_T(t->hse),
+			TO_DSI_T(t->hbp),
+			TO_DSI_T(pps),
+			TO_DSI_T(t->hfp),
+
+			TO_DSI_T(bl),
+			TO_DSI_T(pps),
+
+			TO_DSI_T(tot));
+#undef TO_DSI_T
+}
+
+static void print_dispc_vm(const char *str, const struct omap_video_timings *t)
+{
+	unsigned long pck = t->pixel_clock * 1000;
+	int hact, bl, tot;
+
+	hact = t->x_res;
+	bl = t->hsw + t->hbp + t->hfp;
+	tot = hact + bl;
+
+#define TO_DISPC_T(x) ((u32)div64_u64((u64)x * 1000000000llu, pck))
+
+	pr_debug("%s pck %lu, %u/%u/%u/%u = %u+%u = %u, "
+			"%u/%u/%u/%u = %u + %u = %u\n",
+			str,
+			pck,
+			t->hsw, t->hbp, hact, t->hfp,
+			bl, hact, tot,
+			TO_DISPC_T(t->hsw),
+			TO_DISPC_T(t->hbp),
+			TO_DISPC_T(hact),
+			TO_DISPC_T(t->hfp),
+			TO_DISPC_T(bl),
+			TO_DISPC_T(hact),
+			TO_DISPC_T(tot));
+#undef TO_DISPC_T
+}
+
+/* note: this is not quite accurate */
+static void print_dsi_dispc_vm(const char *str,
+		const struct omap_dss_dsi_videomode_timings *t)
+{
+	struct omap_video_timings vm = { 0 };
+	unsigned long byteclk = t->hsclk / 4;
+	unsigned long pck;
+	u64 dsi_tput;
+	int dsi_hact, dsi_htot;
+
+	dsi_tput = (u64)byteclk * t->ndl * 8;
+	pck = (u32)div64_u64(dsi_tput, t->bitspp);
+	dsi_hact = DIV_ROUND_UP(DIV_ROUND_UP(t->hact * t->bitspp, 8) + 6, t->ndl);
+	dsi_htot = t->hss + t->hsa + t->hse + t->hbp + dsi_hact + t->hfp;
+
+	vm.pixel_clock = pck / 1000;
+	vm.hsw = div64_u64((u64)(t->hsa + t->hse) * pck, byteclk);
+	vm.hbp = div64_u64((u64)t->hbp * pck, byteclk);
+	vm.hfp = div64_u64((u64)t->hfp * pck, byteclk);
+	vm.x_res = t->hact;
+
+	print_dispc_vm(str, &vm);
+}
+#endif /* PRINT_VERBOSE_VM_TIMINGS */
+
+static bool dsi_cm_calc_dispc_cb(int lckd, int pckd, unsigned long lck,
+		unsigned long pck, void *data)
 {
-	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	struct dsi_clk_calc_ctx *ctx = data;
+	struct omap_video_timings *t = &ctx->dispc_vm;
 
-	mutex_lock(&dsi->lock);
+	ctx->dispc_cinfo.lck_div = lckd;
+	ctx->dispc_cinfo.pck_div = pckd;
+	ctx->dispc_cinfo.lck = lck;
+	ctx->dispc_cinfo.pck = pck;
 
-	dsi->timings = *timings;
+	*t = *ctx->config->timings;
+	t->pixel_clock = pck / 1000;
+	t->x_res = ctx->config->timings->x_res;
+	t->y_res = ctx->config->timings->y_res;
+	t->hsw = t->hfp = t->hbp = t->vsw = 1;
+	t->vfp = t->vbp = 0;
 
-	mutex_unlock(&dsi->lock);
+	return true;
 }
-EXPORT_SYMBOL(omapdss_dsi_set_timings);
 
-void omapdss_dsi_set_size(struct omap_dss_device *dssdev, u16 w, u16 h)
+static bool dsi_cm_calc_hsdiv_cb(int regm_dispc, unsigned long dispc,
+		void *data)
 {
-	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	struct dsi_clk_calc_ctx *ctx = data;
 
-	mutex_lock(&dsi->lock);
+	ctx->dsi_cinfo.regm_dispc = regm_dispc;
+	ctx->dsi_cinfo.dsi_pll_hsdiv_dispc_clk = dispc;
 
-	dsi->timings.x_res = w;
-	dsi->timings.y_res = h;
+	return dispc_div_calc(dispc, ctx->req_pck_min, ctx->req_pck_max,
+			dsi_cm_calc_dispc_cb, ctx);
+}
 
-	mutex_unlock(&dsi->lock);
+static bool dsi_cm_calc_pll_cb(int regn, int regm, unsigned long fint,
+		unsigned long pll, void *data)
+{
+	struct dsi_clk_calc_ctx *ctx = data;
+
+	ctx->dsi_cinfo.regn = regn;
+	ctx->dsi_cinfo.regm = regm;
+	ctx->dsi_cinfo.fint = fint;
+	ctx->dsi_cinfo.clkin4ddr = pll;
+
+	return dsi_hsdiv_calc(ctx->dsidev, pll, ctx->req_pck_min,
+			dsi_cm_calc_hsdiv_cb, ctx);
 }
-EXPORT_SYMBOL(omapdss_dsi_set_size);
 
-void omapdss_dsi_set_pixel_format(struct omap_dss_device *dssdev,
-		enum omap_dss_dsi_pixel_format fmt)
+static bool dsi_cm_calc(struct dsi_data *dsi,
+		const struct omap_dss_dsi_config *cfg,
+		struct dsi_clk_calc_ctx *ctx)
 {
-	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	unsigned long clkin;
+	int bitspp, ndl;
+	unsigned long pll_min, pll_max;
+	unsigned long pck, txbyteclk;
 
-	mutex_lock(&dsi->lock);
+	clkin = clk_get_rate(dsi->sys_clk);
+	bitspp = dsi_get_pixel_size(cfg->pixel_format);
+	ndl = dsi->num_lanes_used - 1;
+
+	/*
+	 * Here we should calculate minimum txbyteclk to be able to send the
+	 * frame in time, and also to handle TE. That's not very simple, though,
+	 * especially as we go to LP between each pixel packet due to HW
+	 * "feature". So let's just estimate very roughly and multiply by 1.5.
+	 */
+	pck = cfg->timings->pixel_clock * 1000;
+	pck = pck * 3 / 2;
+	txbyteclk = pck * bitspp / 8 / ndl;
 
-	dsi->pix_fmt = fmt;
+	memset(ctx, 0, sizeof(*ctx));
+	ctx->dsidev = dsi->pdev;
+	ctx->config = cfg;
+	ctx->req_pck_min = pck;
+	ctx->req_pck_nom = pck;
+	ctx->req_pck_max = pck * 3 / 2;
+	ctx->dsi_cinfo.clkin = clkin;
 
-	mutex_unlock(&dsi->lock);
+	pll_min = max(cfg->hs_clk_min * 4, txbyteclk * 4 * 4);
+	pll_max = cfg->hs_clk_max * 4;
+
+	return dsi_pll_calc(dsi->pdev, clkin,
+			pll_min, pll_max,
+			dsi_cm_calc_pll_cb, ctx);
 }
-EXPORT_SYMBOL(omapdss_dsi_set_pixel_format);
 
-void omapdss_dsi_set_operation_mode(struct omap_dss_device *dssdev,
-		enum omap_dss_dsi_mode mode)
+static bool dsi_vm_calc_blanking(struct dsi_clk_calc_ctx *ctx)
 {
-	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	struct dsi_data *dsi = dsi_get_dsidrv_data(ctx->dsidev);
+	const struct omap_dss_dsi_config *cfg = ctx->config;
+	int bitspp = dsi_get_pixel_size(cfg->pixel_format);
+	int ndl = dsi->num_lanes_used - 1;
+	unsigned long hsclk = ctx->dsi_cinfo.clkin4ddr / 4;
+	unsigned long byteclk = hsclk / 4;
 
-	mutex_lock(&dsi->lock);
+	unsigned long dispc_pck, req_pck_min, req_pck_nom, req_pck_max;
+	int xres;
+	int panel_htot, panel_hbl; /* pixels */
+	int dispc_htot, dispc_hbl; /* pixels */
+	int dsi_htot, dsi_hact, dsi_hbl, hss, hse; /* byteclks */
+	int hfp, hsa, hbp;
+	const struct omap_video_timings *req_vm;
+	struct omap_video_timings *dispc_vm;
+	struct omap_dss_dsi_videomode_timings *dsi_vm;
+	u64 dsi_tput, dispc_tput;
 
-	dsi->mode = mode;
+	dsi_tput = (u64)byteclk * ndl * 8;
 
-	mutex_unlock(&dsi->lock);
+	req_vm = cfg->timings;
+	req_pck_min = ctx->req_pck_min;
+	req_pck_max = ctx->req_pck_max;
+	req_pck_nom = ctx->req_pck_nom;
+
+	dispc_pck = ctx->dispc_cinfo.pck;
+	dispc_tput = (u64)dispc_pck * bitspp;
+
+	xres = req_vm->x_res;
+
+	panel_hbl = req_vm->hfp + req_vm->hbp + req_vm->hsw;
+	panel_htot = xres + panel_hbl;
+
+	dsi_hact = DIV_ROUND_UP(DIV_ROUND_UP(xres * bitspp, 8) + 6, ndl);
+
+	/*
+	 * When there are no line buffers, DISPC and DSI must have the
+	 * same tput. Otherwise DISPC tput needs to be higher than DSI's.
+	 */
+	if (dsi->line_buffer_size < xres * bitspp / 8) {
+		if (dispc_tput != dsi_tput)
+			return false;
+	} else {
+		if (dispc_tput < dsi_tput)
+			return false;
+	}
+
+	/* DSI tput must be over the min requirement */
+	if (dsi_tput < (u64)bitspp * req_pck_min)
+		return false;
+
+	/* When non-burst mode, DSI tput must be below max requirement. */
+	if (cfg->trans_mode != OMAP_DSS_DSI_BURST_MODE) {
+		if (dsi_tput > (u64)bitspp * req_pck_max)
+			return false;
+	}
+
+	hss = DIV_ROUND_UP(4, ndl);
+
+	if (cfg->trans_mode == OMAP_DSS_DSI_PULSE_MODE) {
+		if (ndl == 3 && req_vm->hsw == 0)
+			hse = 1;
+		else
+			hse = DIV_ROUND_UP(4, ndl);
+	} else {
+		hse = 0;
+	}
+
+	/* DSI htot to match the panel's nominal pck */
+	dsi_htot = div64_u64((u64)panel_htot * byteclk, req_pck_nom);
+
+	/* fail if there would be no time for blanking */
+	if (dsi_htot < hss + hse + dsi_hact)
+		return false;
+
+	/* total DSI blanking needed to achieve panel's TL */
+	dsi_hbl = dsi_htot - dsi_hact;
+
+	/* DISPC htot to match the DSI TL */
+	dispc_htot = div64_u64((u64)dsi_htot * dispc_pck, byteclk);
+
+	/* verify that the DSI and DISPC TLs are the same */
+	if ((u64)dsi_htot * dispc_pck != (u64)dispc_htot * byteclk)
+		return false;
+
+	dispc_hbl = dispc_htot - xres;
+
+	/* setup DSI videomode */
+
+	dsi_vm = &ctx->dsi_vm;
+	memset(dsi_vm, 0, sizeof(*dsi_vm));
+
+	dsi_vm->hsclk = hsclk;
+
+	dsi_vm->ndl = ndl;
+	dsi_vm->bitspp = bitspp;
+
+	if (cfg->trans_mode != OMAP_DSS_DSI_PULSE_MODE) {
+		hsa = 0;
+	} else if (ndl == 3 && req_vm->hsw == 0) {
+		hsa = 0;
+	} else {
+		hsa = div64_u64((u64)req_vm->hsw * byteclk, req_pck_nom);
+		hsa = max(hsa - hse, 1);
+	}
+
+	hbp = div64_u64((u64)req_vm->hbp * byteclk, req_pck_nom);
+	hbp = max(hbp, 1);
+
+	hfp = dsi_hbl - (hss + hsa + hse + hbp);
+	if (hfp < 1) {
+		int t;
+		/* we need to take cycles from hbp */
+
+		t = 1 - hfp;
+		hbp = max(hbp - t, 1);
+		hfp = dsi_hbl - (hss + hsa + hse + hbp);
+
+		if (hfp < 1 && hsa > 0) {
+			/* we need to take cycles from hsa */
+			t = 1 - hfp;
+			hsa = max(hsa - t, 1);
+			hfp = dsi_hbl - (hss + hsa + hse + hbp);
+		}
+	}
+
+	if (hfp < 1)
+		return false;
+
+	dsi_vm->hss = hss;
+	dsi_vm->hsa = hsa;
+	dsi_vm->hse = hse;
+	dsi_vm->hbp = hbp;
+	dsi_vm->hact = xres;
+	dsi_vm->hfp = hfp;
+
+	dsi_vm->vsa = req_vm->vsw;
+	dsi_vm->vbp = req_vm->vbp;
+	dsi_vm->vact = req_vm->y_res;
+	dsi_vm->vfp = req_vm->vfp;
+
+	dsi_vm->trans_mode = cfg->trans_mode;
+
+	dsi_vm->blanking_mode = 0;
+	dsi_vm->hsa_blanking_mode = 1;
+	dsi_vm->hfp_blanking_mode = 1;
+	dsi_vm->hbp_blanking_mode = 1;
+
+	dsi_vm->ddr_clk_always_on = cfg->ddr_clk_always_on;
+	dsi_vm->window_sync = 4;
+
+	/* setup DISPC videomode */
+
+	dispc_vm = &ctx->dispc_vm;
+	*dispc_vm = *req_vm;
+	dispc_vm->pixel_clock = dispc_pck / 1000;
+
+	if (cfg->trans_mode == OMAP_DSS_DSI_PULSE_MODE) {
+		hsa = div64_u64((u64)req_vm->hsw * dispc_pck,
+				req_pck_nom);
+		hsa = max(hsa, 1);
+	} else {
+		hsa = 1;
+	}
+
+	hbp = div64_u64((u64)req_vm->hbp * dispc_pck, req_pck_nom);
+	hbp = max(hbp, 1);
+
+	hfp = dispc_hbl - hsa - hbp;
+	if (hfp < 1) {
+		int t;
+		/* we need to take cycles from hbp */
+
+		t = 1 - hfp;
+		hbp = max(hbp - t, 1);
+		hfp = dispc_hbl - hsa - hbp;
+
+		if (hfp < 1) {
+			/* we need to take cycles from hsa */
+			t = 1 - hfp;
+			hsa = max(hsa - t, 1);
+			hfp = dispc_hbl - hsa - hbp;
+		}
+	}
+
+	if (hfp < 1)
+		return false;
+
+	dispc_vm->hfp = hfp;
+	dispc_vm->hsw = hsa;
+	dispc_vm->hbp = hbp;
+
+	return true;
+}
+
+
+static bool dsi_vm_calc_dispc_cb(int lckd, int pckd, unsigned long lck,
+		unsigned long pck, void *data)
+{
+	struct dsi_clk_calc_ctx *ctx = data;
+
+	ctx->dispc_cinfo.lck_div = lckd;
+	ctx->dispc_cinfo.pck_div = pckd;
+	ctx->dispc_cinfo.lck = lck;
+	ctx->dispc_cinfo.pck = pck;
+
+	if (dsi_vm_calc_blanking(ctx) == false)
+		return false;
+
+#ifdef PRINT_VERBOSE_VM_TIMINGS
+	print_dispc_vm("dispc", &ctx->dispc_vm);
+	print_dsi_vm("dsi  ", &ctx->dsi_vm);
+	print_dispc_vm("req  ", ctx->config->timings);
+	print_dsi_dispc_vm("act  ", &ctx->dsi_vm);
+#endif
+
+	return true;
+}
+
+static bool dsi_vm_calc_hsdiv_cb(int regm_dispc, unsigned long dispc,
+		void *data)
+{
+	struct dsi_clk_calc_ctx *ctx = data;
+	unsigned long pck_max;
+
+	ctx->dsi_cinfo.regm_dispc = regm_dispc;
+	ctx->dsi_cinfo.dsi_pll_hsdiv_dispc_clk = dispc;
+
+	/*
+	 * In burst mode we can let the dispc pck be arbitrarily high, but it
+	 * limits our scaling abilities. So for now, don't aim too high.
+	 */
+
+	if (ctx->config->trans_mode == OMAP_DSS_DSI_BURST_MODE)
+		pck_max = ctx->req_pck_max + 10000000;
+	else
+		pck_max = ctx->req_pck_max;
+
+	return dispc_div_calc(dispc, ctx->req_pck_min, pck_max,
+			dsi_vm_calc_dispc_cb, ctx);
+}
+
+static bool dsi_vm_calc_pll_cb(int regn, int regm, unsigned long fint,
+		unsigned long pll, void *data)
+{
+	struct dsi_clk_calc_ctx *ctx = data;
+
+	ctx->dsi_cinfo.regn = regn;
+	ctx->dsi_cinfo.regm = regm;
+	ctx->dsi_cinfo.fint = fint;
+	ctx->dsi_cinfo.clkin4ddr = pll;
+
+	return dsi_hsdiv_calc(ctx->dsidev, pll, ctx->req_pck_min,
+			dsi_vm_calc_hsdiv_cb, ctx);
+}
+
+static bool dsi_vm_calc(struct dsi_data *dsi,
+		const struct omap_dss_dsi_config *cfg,
+		struct dsi_clk_calc_ctx *ctx)
+{
+	const struct omap_video_timings *t = cfg->timings;
+	unsigned long clkin;
+	unsigned long pll_min;
+	unsigned long pll_max;
+	int ndl = dsi->num_lanes_used - 1;
+	int bitspp = dsi_get_pixel_size(cfg->pixel_format);
+	unsigned long byteclk_min;
+
+	clkin = clk_get_rate(dsi->sys_clk);
+
+	memset(ctx, 0, sizeof(*ctx));
+	ctx->dsidev = dsi->pdev;
+	ctx->config = cfg;
+
+	ctx->dsi_cinfo.clkin = clkin;
+
+	/* these limits should come from the panel driver */
+	ctx->req_pck_min = t->pixel_clock * 1000 - 1000;
+	ctx->req_pck_nom = t->pixel_clock * 1000;
+	ctx->req_pck_max = t->pixel_clock * 1000 + 1000;
+
+	byteclk_min = div64_u64((u64)ctx->req_pck_min * bitspp, ndl * 8);
+	pll_min = max(cfg->hs_clk_min * 4, byteclk_min * 4 * 4);
+
+	if (cfg->trans_mode == OMAP_DSS_DSI_BURST_MODE) {
+		pll_max = cfg->hs_clk_max * 4;
+	} else {
+		unsigned long byteclk_max;
+		byteclk_max = div64_u64((u64)ctx->req_pck_max * bitspp,
+				ndl * 8);
+
+		pll_max = byteclk_max * 4 * 4;
+	}
+
+	return dsi_pll_calc(dsi->pdev, clkin,
+			pll_min, pll_max,
+			dsi_vm_calc_pll_cb, ctx);
 }
-EXPORT_SYMBOL(omapdss_dsi_set_operation_mode);
 
-void omapdss_dsi_set_videomode_timings(struct omap_dss_device *dssdev,
-		struct omap_dss_dsi_videomode_timings *timings)
+int omapdss_dsi_set_config(struct omap_dss_device *dssdev,
+		const struct omap_dss_dsi_config *config)
 {
 	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
 	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	struct dsi_clk_calc_ctx ctx;
+	bool ok;
+	int r;
 
 	mutex_lock(&dsi->lock);
 
-	dsi->vm_timings = *timings;
+	dsi->pix_fmt = config->pixel_format;
+	dsi->mode = config->mode;
+
+	if (config->mode == OMAP_DSS_DSI_VIDEO_MODE)
+		ok = dsi_vm_calc(dsi, config, &ctx);
+	else
+		ok = dsi_cm_calc(dsi, config, &ctx);
+
+	if (!ok) {
+		DSSERR("failed to find suitable DSI clock settings\n");
+		r = -EINVAL;
+		goto err;
+	}
+
+	dsi_pll_calc_dsi_fck(&ctx.dsi_cinfo);
+
+	r = dsi_lp_clock_calc(&ctx.dsi_cinfo, config->lp_clk_min,
+			config->lp_clk_max);
+	if (r) {
+		DSSERR("failed to find suitable DSI LP clock settings\n");
+		goto err;
+	}
+
+	dsi->user_dsi_cinfo = ctx.dsi_cinfo;
+	dsi->user_dispc_cinfo = ctx.dispc_cinfo;
+
+	dsi->timings = ctx.dispc_vm;
+	dsi->vm_timings = ctx.dsi_vm;
 
 	mutex_unlock(&dsi->lock);
+
+	return 0;
+err:
+	mutex_unlock(&dsi->lock);
+
+	return r;
+}
+EXPORT_SYMBOL(omapdss_dsi_set_config);
+
+/*
+ * Return a hardcoded channel for the DSI output. This should work for
+ * current use cases, but this can be later expanded to either resolve
+ * the channel in some more dynamic manner, or get the channel as a user
+ * parameter.
+ */
+static enum omap_channel dsi_get_channel(int module_id)
+{
+	switch (omapdss_get_version()) {
+	case OMAPDSS_VER_OMAP24xx:
+		DSSWARN("DSI not supported\n");
+		return OMAP_DSS_CHANNEL_LCD;
+
+	case OMAPDSS_VER_OMAP34xx_ES1:
+	case OMAPDSS_VER_OMAP34xx_ES3:
+	case OMAPDSS_VER_OMAP3630:
+	case OMAPDSS_VER_AM35xx:
+		return OMAP_DSS_CHANNEL_LCD;
+
+	case OMAPDSS_VER_OMAP4430_ES1:
+	case OMAPDSS_VER_OMAP4430_ES2:
+	case OMAPDSS_VER_OMAP4:
+		switch (module_id) {
+		case 0:
+			return OMAP_DSS_CHANNEL_LCD;
+		case 1:
+			return OMAP_DSS_CHANNEL_LCD2;
+		default:
+			DSSWARN("unsupported module id\n");
+			return OMAP_DSS_CHANNEL_LCD;
+		}
+
+	case OMAPDSS_VER_OMAP5:
+		switch (module_id) {
+		case 0:
+			return OMAP_DSS_CHANNEL_LCD;
+		case 1:
+			return OMAP_DSS_CHANNEL_LCD3;
+		default:
+			DSSWARN("unsupported module id\n");
+			return OMAP_DSS_CHANNEL_LCD;
+		}
+
+	default:
+		DSSWARN("unsupported DSS version\n");
+		return OMAP_DSS_CHANNEL_LCD;
+	}
 }
-EXPORT_SYMBOL(omapdss_dsi_set_videomode_timings);
 
 static int __init dsi_init_display(struct omap_dss_device *dssdev)
 {
@@ -5073,7 +5347,7 @@ static int dsi_get_clocks(struct platform_device *dsidev)
 	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
 	struct clk *clk;
 
-	clk = clk_get(&dsidev->dev, "fck");
+	clk = devm_clk_get(&dsidev->dev, "fck");
 	if (IS_ERR(clk)) {
 		DSSERR("can't get fck\n");
 		return PTR_ERR(clk);
@@ -5081,11 +5355,9 @@ static int dsi_get_clocks(struct platform_device *dsidev)
 
 	dsi->dss_clk = clk;
 
-	clk = clk_get(&dsidev->dev, "sys_clk");
+	clk = devm_clk_get(&dsidev->dev, "sys_clk");
 	if (IS_ERR(clk)) {
 		DSSERR("can't get sys_clk\n");
-		clk_put(dsi->dss_clk);
-		dsi->dss_clk = NULL;
 		return PTR_ERR(clk);
 	}
 
@@ -5094,16 +5366,6 @@ static int dsi_get_clocks(struct platform_device *dsidev)
 	return 0;
 }
 
-static void dsi_put_clocks(struct platform_device *dsidev)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-
-	if (dsi->dss_clk)
-		clk_put(dsi->dss_clk);
-	if (dsi->sys_clk)
-		clk_put(dsi->sys_clk);
-}
-
 static struct omap_dss_device * __init dsi_find_dssdev(struct platform_device *pdev)
 {
 	struct omap_dss_board_info *pdata = pdev->dev.platform_data;
@@ -5188,6 +5450,8 @@ static void __init dsi_init_output(struct platform_device *dsidev)
 			OMAP_DSS_OUTPUT_DSI1 : OMAP_DSS_OUTPUT_DSI2;
 
 	out->type = OMAP_DISPLAY_TYPE_DSI;
+	out->name = dsi->module_id == 0 ? "dsi.0" : "dsi.1";
+	out->dispc_channel = dsi_get_channel(dsi->module_id);
 
 	dss_register_output(out);
 }
@@ -5293,6 +5557,8 @@ static int __init omap_dsihw_probe(struct platform_device *dsidev)
 	else
 		dsi->num_lanes_supported = 3;
 
+	dsi->line_buffer_size = dsi_get_line_buf_size(dsidev);
+
 	dsi_init_output(dsidev);
 
 	dsi_probe_pdata(dsidev);
@@ -5314,7 +5580,6 @@ static int __init omap_dsihw_probe(struct platform_device *dsidev)
 
 err_runtime_get:
 	pm_runtime_disable(&dsidev->dev);
-	dsi_put_clocks(dsidev);
 	return r;
 }
 
@@ -5330,8 +5595,6 @@ static int __exit omap_dsihw_remove(struct platform_device *dsidev)
 
 	pm_runtime_disable(&dsidev->dev);
 
-	dsi_put_clocks(dsidev);
-
 	if (dsi->vdds_dsi_reg != NULL) {
 		if (dsi->vdds_dsi_enabled) {
 			regulator_disable(dsi->vdds_dsi_reg);
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index 054c2a2..fdd32e8 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -473,6 +473,45 @@ int dss_calc_clock_rates(struct dss_clock_info *cinfo)
 	return 0;
 }
 
+bool dss_div_calc(unsigned long fck_min, dss_div_calc_func func, void *data)
+{
+	int fckd, fckd_start, fckd_stop;
+	unsigned long fck;
+	unsigned long fck_hw_max;
+	unsigned long fckd_hw_max;
+	unsigned long prate;
+
+	if (dss.dpll4_m4_ck == NULL) {
+		/*
+		 * TODO: dss1_fclk can be changed on OMAP2, but the available
+		 * dividers are not continuous. We just use the pre-set rate for
+		 * now.
+		 */
+		fck = clk_get_rate(dss.dss_clk);
+		fckd = 1;
+		return func(fckd, fck, data);
+	}
+
+	fck_hw_max = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
+	fckd_hw_max = dss.feat->fck_div_max;
+
+	prate = dss_get_dpll4_rate() * dss.feat->dss_fck_multiplier;
+
+	fck_min = fck_min ? fck_min : 1;
+
+	fckd_start = min(prate / fck_min, fckd_hw_max);
+	fckd_stop = max(DIV_ROUND_UP(prate, fck_hw_max), 1ul);
+
+	for (fckd = fckd_start; fckd >= fckd_stop; --fckd) {
+		fck = prate / fckd;
+
+		if (func(fckd, fck, data))
+			return true;
+	}
+
+	return false;
+}
+
 int dss_set_clock_div(struct dss_clock_info *cinfo)
 {
 	if (dss.dpll4_m4_ck) {
@@ -542,121 +581,6 @@ static int dss_setup_default_clock(void)
 	return 0;
 }
 
-int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo,
-		struct dispc_clock_info *dispc_cinfo)
-{
-	unsigned long prate;
-	struct dss_clock_info best_dss;
-	struct dispc_clock_info best_dispc;
-
-	unsigned long fck, max_dss_fck;
-
-	u16 fck_div;
-
-	int match = 0;
-	int min_fck_per_pck;
-
-	prate = dss_get_dpll4_rate();
-
-	max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
-
-	fck = clk_get_rate(dss.dss_clk);
-	if (req_pck == dss.cache_req_pck && prate == dss.cache_prate &&
-		dss.cache_dss_cinfo.fck == fck) {
-		DSSDBG("dispc clock info found from cache.\n");
-		*dss_cinfo = dss.cache_dss_cinfo;
-		*dispc_cinfo = dss.cache_dispc_cinfo;
-		return 0;
-	}
-
-	min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
-
-	if (min_fck_per_pck &&
-		req_pck * min_fck_per_pck > max_dss_fck) {
-		DSSERR("Requested pixel clock not possible with the current "
-				"OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning "
-				"the constraint off.\n");
-		min_fck_per_pck = 0;
-	}
-
-retry:
-	memset(&best_dss, 0, sizeof(best_dss));
-	memset(&best_dispc, 0, sizeof(best_dispc));
-
-	if (dss.dpll4_m4_ck == NULL) {
-		struct dispc_clock_info cur_dispc;
-		/* XXX can we change the clock on omap2? */
-		fck = clk_get_rate(dss.dss_clk);
-		fck_div = 1;
-
-		dispc_find_clk_divs(req_pck, fck, &cur_dispc);
-		match = 1;
-
-		best_dss.fck = fck;
-		best_dss.fck_div = fck_div;
-
-		best_dispc = cur_dispc;
-
-		goto found;
-	} else {
-		for (fck_div = dss.feat->fck_div_max; fck_div > 0; --fck_div) {
-			struct dispc_clock_info cur_dispc;
-
-			fck = prate / fck_div * dss.feat->dss_fck_multiplier;
-
-			if (fck > max_dss_fck)
-				continue;
-
-			if (min_fck_per_pck &&
-					fck < req_pck * min_fck_per_pck)
-				continue;
-
-			match = 1;
-
-			dispc_find_clk_divs(req_pck, fck, &cur_dispc);
-
-			if (abs(cur_dispc.pck - req_pck) <
-					abs(best_dispc.pck - req_pck)) {
-
-				best_dss.fck = fck;
-				best_dss.fck_div = fck_div;
-
-				best_dispc = cur_dispc;
-
-				if (cur_dispc.pck == req_pck)
-					goto found;
-			}
-		}
-	}
-
-found:
-	if (!match) {
-		if (min_fck_per_pck) {
-			DSSERR("Could not find suitable clock settings.\n"
-					"Turning FCK/PCK constraint off and"
-					"trying again.\n");
-			min_fck_per_pck = 0;
-			goto retry;
-		}
-
-		DSSERR("Could not find suitable clock settings.\n");
-
-		return -EINVAL;
-	}
-
-	if (dss_cinfo)
-		*dss_cinfo = best_dss;
-	if (dispc_cinfo)
-		*dispc_cinfo = best_dispc;
-
-	dss.cache_req_pck = req_pck;
-	dss.cache_prate = prate;
-	dss.cache_dss_cinfo = best_dss;
-	dss.cache_dispc_cinfo = best_dispc;
-
-	return 0;
-}
-
 void dss_set_venc_output(enum omap_dss_venc_type type)
 {
 	int l = 0;
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index 610c8e5..faaf358 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -268,8 +268,9 @@ void dss_set_dac_pwrdn_bgz(bool enable);
 unsigned long dss_get_dpll4_rate(void);
 int dss_calc_clock_rates(struct dss_clock_info *cinfo);
 int dss_set_clock_div(struct dss_clock_info *cinfo);
-int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo,
-		struct dispc_clock_info *dispc_cinfo);
+
+typedef bool (*dss_div_calc_func)(int fckd, unsigned long fck, void *data);
+bool dss_div_calc(unsigned long fck_min, dss_div_calc_func func, void *data);
 
 /* SDI */
 int sdi_init_platform_driver(void) __init;
@@ -292,12 +293,21 @@ void dsi_dump_clocks(struct seq_file *s);
 void dsi_irq_handler(void);
 u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt);
 
+unsigned long dsi_get_pll_clkin(struct platform_device *dsidev);
+
+typedef bool (*dsi_pll_calc_func)(int regn, int regm, unsigned long fint,
+		unsigned long pll, void *data);
+typedef bool (*dsi_hsdiv_calc_func)(int regm_dispc, unsigned long dispc,
+		void *data);
+bool dsi_hsdiv_calc(struct platform_device *dsidev, unsigned long pll,
+		unsigned long out_min, dsi_hsdiv_calc_func func, void *data);
+bool dsi_pll_calc(struct platform_device *dsidev, unsigned long clkin,
+		unsigned long pll_min, unsigned long pll_max,
+		dsi_pll_calc_func func, void *data);
+
 unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev);
 int dsi_pll_set_clock_div(struct platform_device *dsidev,
 		struct dsi_clock_info *cinfo);
-int dsi_pll_calc_clock_div_pck(struct platform_device *dsidev,
-		unsigned long req_pck, struct dsi_clock_info *cinfo,
-		struct dispc_clock_info *dispc_cinfo);
 int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk,
 		bool enable_hsdiv);
 void dsi_pll_uninit(struct platform_device *dsidev, bool disconnect_lanes);
@@ -328,14 +338,6 @@ static inline int dsi_pll_set_clock_div(struct platform_device *dsidev,
 	WARN("%s: DSI not compiled in\n", __func__);
 	return -ENODEV;
 }
-static inline int dsi_pll_calc_clock_div_pck(struct platform_device *dsidev,
-		unsigned long req_pck,
-		struct dsi_clock_info *dsi_cinfo,
-		struct dispc_clock_info *dispc_cinfo)
-{
-	WARN("%s: DSI not compiled in\n", __func__);
-	return -ENODEV;
-}
 static inline int dsi_pll_init(struct platform_device *dsidev,
 		bool enable_hsclk, bool enable_hsdiv)
 {
@@ -376,11 +378,15 @@ void dispc_enable_fifomerge(bool enable);
 void dispc_enable_gamma_table(bool enable);
 void dispc_set_loadmode(enum omap_dss_load_mode mode);
 
+typedef bool (*dispc_div_calc_func)(int lckd, int pckd, unsigned long lck,
+		unsigned long pck, void *data);
+bool dispc_div_calc(unsigned long dispc,
+		unsigned long pck_min, unsigned long pck_max,
+		dispc_div_calc_func func, void *data);
+
 bool dispc_mgr_timings_ok(enum omap_channel channel,
 		const struct omap_video_timings *timings);
 unsigned long dispc_fclk_rate(void);
-void dispc_find_clk_divs(unsigned long req_pck, unsigned long fck,
-		struct dispc_clock_info *cinfo);
 int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
 		struct dispc_clock_info *cinfo);
 
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index 7292364..a6f9538 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -472,17 +472,12 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
 	 * Input clock is predivided by N + 1
 	 * out put of which is reference clk
 	 */
-	if (dssdev->clocks.hdmi.regn == 0)
-		pi->regn = HDMI_DEFAULT_REGN;
-	else
-		pi->regn = dssdev->clocks.hdmi.regn;
+
+	pi->regn = HDMI_DEFAULT_REGN;
 
 	refclk = clkin / pi->regn;
 
-	if (dssdev->clocks.hdmi.regm2 == 0)
-		pi->regm2 = HDMI_DEFAULT_REGM2;
-	else
-		pi->regm2 = dssdev->clocks.hdmi.regm2;
+	pi->regm2 = HDMI_DEFAULT_REGM2;
 
 	/*
 	 * multiplier is pixel_clk/ref_clk
@@ -1017,8 +1012,6 @@ static void __init hdmi_probe_pdata(struct platform_device *pdev)
 	hdmi.ls_oe_gpio = priv->ls_oe_gpio;
 	hdmi.hpd_gpio = priv->hpd_gpio;
 
-	dssdev->channel = OMAP_DSS_CHANNEL_DIGIT;
-
 	r = hdmi_init_display(dssdev);
 	if (r) {
 		DSSERR("device %s init failed: %d\n", dssdev->name, r);
@@ -1051,6 +1044,8 @@ static void __init hdmi_init_output(struct platform_device *pdev)
 	out->pdev = pdev;
 	out->id = OMAP_DSS_OUTPUT_HDMI;
 	out->type = OMAP_DISPLAY_TYPE_HDMI;
+	out->name = "hdmi.0";
+	out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT;
 
 	dss_register_output(out);
 }
@@ -1097,6 +1092,8 @@ static int __init omapdss_hdmihw_probe(struct platform_device *pdev)
 	hdmi.ip_data.pll_offset = HDMI_PLLCTRL;
 	hdmi.ip_data.phy_offset = HDMI_PHY;
 
+	hdmi_init_output(pdev);
+
 	r = hdmi_panel_init();
 	if (r) {
 		DSSERR("can't init panel\n");
@@ -1105,8 +1102,6 @@ static int __init omapdss_hdmihw_probe(struct platform_device *pdev)
 
 	dss_debugfs_create_file("hdmi", hdmi_dump_regs);
 
-	hdmi_init_output(pdev);
-
 	hdmi_probe_pdata(pdev);
 
 	return 0;
diff --git a/drivers/video/omap2/dss/output.c b/drivers/video/omap2/dss/output.c
index 79dea1a..5214df6 100644
--- a/drivers/video/omap2/dss/output.c
+++ b/drivers/video/omap2/dss/output.c
@@ -113,6 +113,7 @@ struct omap_dss_output *omap_dss_get_output(enum omap_dss_output_id id)
 
 	return NULL;
 }
+EXPORT_SYMBOL(omap_dss_get_output);
 
 static const struct dss_mgr_ops *dss_mgr_ops;
 
diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c
index e903dd3..1a691bb 100644
--- a/drivers/video/omap2/dss/rfbi.c
+++ b/drivers/video/omap2/dss/rfbi.c
@@ -1025,6 +1025,8 @@ static void __init rfbi_init_output(struct platform_device *pdev)
 	out->pdev = pdev;
 	out->id = OMAP_DSS_OUTPUT_DBI;
 	out->type = OMAP_DISPLAY_TYPE_DBI;
+	out->name = "rfbi.0";
+	out->dispc_channel = OMAP_DSS_CHANNEL_LCD;
 
 	dss_register_output(out);
 }
diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c
index 62b5374..e6baee2 100644
--- a/drivers/video/omap2/dss/sdi.c
+++ b/drivers/video/omap2/dss/sdi.c
@@ -41,6 +41,72 @@ static struct {
 	struct omap_dss_output output;
 } sdi;
 
+struct sdi_clk_calc_ctx {
+	unsigned long pck_min, pck_max;
+
+	struct dss_clock_info dss_cinfo;
+	struct dispc_clock_info dispc_cinfo;
+};
+
+static bool dpi_calc_dispc_cb(int lckd, int pckd, unsigned long lck,
+		unsigned long pck, void *data)
+{
+	struct sdi_clk_calc_ctx *ctx = data;
+
+	ctx->dispc_cinfo.lck_div = lckd;
+	ctx->dispc_cinfo.pck_div = pckd;
+	ctx->dispc_cinfo.lck = lck;
+	ctx->dispc_cinfo.pck = pck;
+
+	return true;
+}
+
+static bool dpi_calc_dss_cb(int fckd, unsigned long fck, void *data)
+{
+	struct sdi_clk_calc_ctx *ctx = data;
+
+	ctx->dss_cinfo.fck = fck;
+	ctx->dss_cinfo.fck_div = fckd;
+
+	return dispc_div_calc(fck, ctx->pck_min, ctx->pck_max,
+			dpi_calc_dispc_cb, ctx);
+}
+
+static int sdi_calc_clock_div(unsigned long pclk,
+		struct dss_clock_info *dss_cinfo,
+		struct dispc_clock_info *dispc_cinfo)
+{
+	int i;
+	struct sdi_clk_calc_ctx ctx;
+
+	/*
+	 * DSS fclk gives us very few possibilities, so finding a good pixel
+	 * clock may not be possible. We try multiple times to find the clock,
+	 * each time widening the pixel clock range we look for, up to
+	 * +/- 1MHz.
+	 */
+
+	for (i = 0; i < 10; ++i) {
+		bool ok;
+
+		memset(&ctx, 0, sizeof(ctx));
+		if (pclk > 1000 * i * i * i)
+			ctx.pck_min = max(pclk - 1000 * i * i * i, 0lu);
+		else
+			ctx.pck_min = 0;
+		ctx.pck_max = pclk + 1000 * i * i * i;
+
+		ok = dss_div_calc(ctx.pck_min, dpi_calc_dss_cb, &ctx);
+		if (ok) {
+			*dss_cinfo = ctx.dss_cinfo;
+			*dispc_cinfo = ctx.dispc_cinfo;
+			return 0;
+		}
+	}
+
+	return -EINVAL;
+}
+
 static void sdi_config_lcd_manager(struct omap_dss_device *dssdev)
 {
 	struct omap_overlay_manager *mgr = dssdev->output->manager;
@@ -88,7 +154,7 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
 	t->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
 	t->sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
 
-	r = dss_calc_clock_div(t->pixel_clock * 1000, &dss_cinfo, &dispc_cinfo);
+	r = sdi_calc_clock_div(t->pixel_clock * 1000, &dss_cinfo, &dispc_cinfo);
 	if (r)
 		goto err_calc_clock_div;
 
@@ -278,6 +344,8 @@ static void __init sdi_init_output(struct platform_device *pdev)
 	out->pdev = pdev;
 	out->id = OMAP_DSS_OUTPUT_SDI;
 	out->type = OMAP_DISPLAY_TYPE_SDI;
+	out->name = "sdi.0";
+	out->dispc_channel = OMAP_DSS_CHANNEL_LCD;
 
 	dss_register_output(out);
 }
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
index 006caf3..23d7db3 100644
--- a/drivers/video/omap2/dss/venc.c
+++ b/drivers/video/omap2/dss/venc.c
@@ -519,10 +519,6 @@ int omapdss_venc_display_enable(struct omap_dss_device *dssdev)
 		goto err0;
 	}
 
-	if (dssdev->platform_enable)
-		dssdev->platform_enable(dssdev);
-
-
 	r = venc_power_on(dssdev);
 	if (r)
 		goto err1;
@@ -533,8 +529,6 @@ int omapdss_venc_display_enable(struct omap_dss_device *dssdev)
 
 	return 0;
 err1:
-	if (dssdev->platform_disable)
-		dssdev->platform_disable(dssdev);
 	omap_dss_stop_device(dssdev);
 err0:
 	mutex_unlock(&venc.venc_lock);
@@ -551,9 +545,6 @@ void omapdss_venc_display_disable(struct omap_dss_device *dssdev)
 
 	omap_dss_stop_device(dssdev);
 
-	if (dssdev->platform_disable)
-		dssdev->platform_disable(dssdev);
-
 	mutex_unlock(&venc.venc_lock);
 }
 
@@ -786,8 +777,6 @@ static void __init venc_probe_pdata(struct platform_device *vencdev)
 
 	dss_copy_device_pdata(dssdev, plat_dssdev);
 
-	dssdev->channel = OMAP_DSS_CHANNEL_DIGIT;
-
 	r = venc_init_display(dssdev);
 	if (r) {
 		DSSERR("device %s init failed: %d\n", dssdev->name, r);
@@ -819,6 +808,8 @@ static void __init venc_init_output(struct platform_device *pdev)
 	out->pdev = pdev;
 	out->id = OMAP_DSS_OUTPUT_VENC;
 	out->type = OMAP_DISPLAY_TYPE_VENC;
+	out->name = "venc.0";
+	out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT;
 
 	dss_register_output(out);
 }
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
index ca585ef..f38348e 100644
--- a/drivers/video/omap2/omapfb/omapfb-main.c
+++ b/drivers/video/omap2/omapfb/omapfb-main.c
@@ -2388,7 +2388,7 @@ static int omapfb_init_connections(struct omapfb2_device *fbdev,
 		struct omap_dss_device *dssdev = fbdev->displays[i].dssdev;
 		struct omap_dss_output *out = dssdev->output;
 
-		mgr = omap_dss_get_overlay_manager(dssdev->channel);
+		mgr = omap_dss_get_overlay_manager(out->dispc_channel);
 
 		if (!mgr || !out)
 			continue;
diff --git a/drivers/video/omap2/vrfb.c b/drivers/video/omap2/vrfb.c
index 10560ef..5261229 100644
--- a/drivers/video/omap2/vrfb.c
+++ b/drivers/video/omap2/vrfb.c
@@ -397,18 +397,7 @@ static struct platform_driver vrfb_driver = {
 	.remove		= __exit_p(vrfb_remove),
 };
 
-static int __init vrfb_init(void)
-{
-	return platform_driver_probe(&vrfb_driver, &vrfb_probe);
-}
-
-static void __exit vrfb_exit(void)
-{
-	platform_driver_unregister(&vrfb_driver);
-}
-
-module_init(vrfb_init);
-module_exit(vrfb_exit);
+module_platform_driver_probe(vrfb_driver, vrfb_probe);
 
 MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
 MODULE_DESCRIPTION("OMAP VRFB");
diff --git a/drivers/video/sh_mipi_dsi.c b/drivers/video/sh_mipi_dsi.c
index 701b461..6cad530 100644
--- a/drivers/video/sh_mipi_dsi.c
+++ b/drivers/video/sh_mipi_dsi.c
@@ -581,17 +581,7 @@ static struct platform_driver sh_mipi_driver = {
 	},
 };
 
-static int __init sh_mipi_init(void)
-{
-	return platform_driver_probe(&sh_mipi_driver, sh_mipi_probe);
-}
-module_init(sh_mipi_init);
-
-static void __exit sh_mipi_exit(void)
-{
-	platform_driver_unregister(&sh_mipi_driver);
-}
-module_exit(sh_mipi_exit);
+module_platform_driver_probe(sh_mipi_driver, sh_mipi_probe);
 
 MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
 MODULE_DESCRIPTION("SuperH / ARM-shmobile MIPI DSI driver");
diff --git a/drivers/video/sh_mobile_hdmi.c b/drivers/video/sh_mobile_hdmi.c
index 930e550..bfe4728 100644
--- a/drivers/video/sh_mobile_hdmi.c
+++ b/drivers/video/sh_mobile_hdmi.c
@@ -1445,17 +1445,7 @@ static struct platform_driver sh_hdmi_driver = {
 	},
 };
 
-static int __init sh_hdmi_init(void)
-{
-	return platform_driver_probe(&sh_hdmi_driver, sh_hdmi_probe);
-}
-module_init(sh_hdmi_init);
-
-static void __exit sh_hdmi_exit(void)
-{
-	platform_driver_unregister(&sh_hdmi_driver);
-}
-module_exit(sh_hdmi_exit);
+module_platform_driver_probe(sh_hdmi_driver, sh_hdmi_probe);
 
 MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
 MODULE_DESCRIPTION("SuperH / ARM-shmobile HDMI driver");
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index 63203ac..0264704 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -858,6 +858,7 @@ static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch)
 	tmp = ((mode->xres & 7) << 24) | ((display_h_total & 7) << 16)
 	    | ((mode->hsync_len & 7) << 8) | (hsync_pos & 7);
 	lcdc_write_chan(ch, LDHAJR, tmp);
+	lcdc_write_chan_mirror(ch, LDHAJR, tmp);
 }
 
 static void sh_mobile_lcdc_overlay_setup(struct sh_mobile_lcdc_overlay *ovl)
diff --git a/drivers/video/uvesafb.c b/drivers/video/uvesafb.c
index b75db01..0d0a43c 100644
--- a/drivers/video/uvesafb.c
+++ b/drivers/video/uvesafb.c
@@ -166,7 +166,7 @@ static int uvesafb_exec(struct uvesafb_ktask *task)
 	memcpy(&m->id, &uvesafb_cn_id, sizeof(m->id));
 	m->seq = seq;
 	m->len = len;
-	m->ack = random32();
+	m->ack = prandom_u32();
 
 	/* uvesafb_task structure */
 	memcpy(m + 1, &task->t, sizeof(task->t));
diff --git a/drivers/video/vt8500lcdfb.c b/drivers/video/vt8500lcdfb.c
index aa2579c..9547e18 100644
--- a/drivers/video/vt8500lcdfb.c
+++ b/drivers/video/vt8500lcdfb.c
@@ -15,22 +15,21 @@
  * GNU General Public License for more details.
  */
 
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
 #include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/errno.h>
 #include <linux/fb.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
-#include <linux/dma-mapping.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/module.h>
 #include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/string.h>
 #include <linux/wait.h>
-
-#include <linux/platform_data/video-vt8500lcdfb.h>
+#include <video/of_display_timing.h>
 
 #include "vt8500lcdfb.h"
 #include "wmt_ge_rops.h"
@@ -277,11 +276,11 @@ static int vt8500lcd_probe(struct platform_device *pdev)
 {
 	struct vt8500lcd_info *fbi;
 	struct resource *res;
+	struct display_timings *disp_timing;
 	void *addr;
 	int irq, ret;
 
 	struct fb_videomode	of_mode;
-	struct device_node	*np;
 	u32			bpp;
 	dma_addr_t fb_mem_phys;
 	unsigned long fb_mem_len;
@@ -346,32 +345,18 @@ static int vt8500lcd_probe(struct platform_device *pdev)
 		goto failed_free_res;
 	}
 
-	np = of_parse_phandle(pdev->dev.of_node, "default-mode", 0);
-	if (!np) {
-		pr_err("%s: No display description in Device Tree\n", __func__);
-		ret = -EINVAL;
-		goto failed_free_res;
-	}
+	disp_timing = of_get_display_timings(pdev->dev.of_node);
+	if (!disp_timing)
+		return -EINVAL;
 
-	/*
-	 * This code is copied from Sascha Hauer's of_videomode helper
-	 * and can be replaced with a call to the helper once mainlined
-	 */
-	ret = 0;
-	ret |= of_property_read_u32(np, "hactive", &of_mode.xres);
-	ret |= of_property_read_u32(np, "vactive", &of_mode.yres);
-	ret |= of_property_read_u32(np, "hback-porch", &of_mode.left_margin);
-	ret |= of_property_read_u32(np, "hfront-porch", &of_mode.right_margin);
-	ret |= of_property_read_u32(np, "hsync-len", &of_mode.hsync_len);
-	ret |= of_property_read_u32(np, "vback-porch", &of_mode.upper_margin);
-	ret |= of_property_read_u32(np, "vfront-porch", &of_mode.lower_margin);
-	ret |= of_property_read_u32(np, "vsync-len", &of_mode.vsync_len);
-	ret |= of_property_read_u32(np, "bpp", &bpp);
-	if (ret) {
-		pr_err("%s: Unable to read display properties\n", __func__);
-		goto failed_free_res;
-	}
-	of_mode.vmode = FB_VMODE_NONINTERLACED;
+	ret = of_get_fb_videomode(pdev->dev.of_node, &of_mode,
+							OF_USE_NATIVE_MODE);
+	if (ret)
+		return ret;
+
+	ret = of_property_read_u32(pdev->dev.of_node, "bits-per-pixel", &bpp);
+	if (ret)
+		return ret;
 
 	/* try allocating the framebuffer */
 	fb_mem_len = of_mode.xres * of_mode.yres * 2 * (bpp / 8);
diff --git a/drivers/video/wm8505fb.c b/drivers/video/wm8505fb.c
index 4dd0580..19e2e7f 100644
--- a/drivers/video/wm8505fb.c
+++ b/drivers/video/wm8505fb.c
@@ -14,25 +14,24 @@
  * GNU General Public License for more details.
  */
 
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
 #include <linux/delay.h>
+#include <linux/dma-mapping.h>
 #include <linux/fb.h>
+#include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
-#include <linux/dma-mapping.h>
-#include <linux/platform_device.h>
-#include <linux/wait.h>
+#include <linux/kernel.h>
+#include <linux/memblock.h>
+#include <linux/mm.h>
+#include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_fdt.h>
-#include <linux/memblock.h>
-
-#include <linux/platform_data/video-vt8500lcdfb.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/wait.h>
+#include <video/of_display_timing.h>
 
 #include "wm8505fb_regs.h"
 #include "wmt_ge_rops.h"
@@ -263,26 +262,22 @@ static struct fb_ops wm8505fb_ops = {
 static int wm8505fb_probe(struct platform_device *pdev)
 {
 	struct wm8505fb_info	*fbi;
-	struct resource		*res;
+	struct resource	*res;
+	struct display_timings *disp_timing;
 	void			*addr;
 	int ret;
 
-	struct fb_videomode	of_mode;
-	struct device_node	*np;
+	struct fb_videomode	mode;
 	u32			bpp;
 	dma_addr_t fb_mem_phys;
 	unsigned long fb_mem_len;
 	void *fb_mem_virt;
 
-	ret = -ENOMEM;
-	fbi = NULL;
-
 	fbi = devm_kzalloc(&pdev->dev, sizeof(struct wm8505fb_info) +
 			sizeof(u32) * 16, GFP_KERNEL);
 	if (!fbi) {
 		dev_err(&pdev->dev, "Failed to initialize framebuffer device\n");
-		ret = -ENOMEM;
-		goto failed;
+		return -ENOMEM;
 	}
 
 	strcpy(fbi->fb.fix.id, DRIVER_NAME);
@@ -308,54 +303,23 @@ static int wm8505fb_probe(struct platform_device *pdev)
 	fbi->fb.pseudo_palette	= addr;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (res == NULL) {
-		dev_err(&pdev->dev, "no I/O memory resource defined\n");
-		ret = -ENODEV;
-		goto failed_fbi;
-	}
+	fbi->regbase = devm_request_and_ioremap(&pdev->dev, res);
+	if (fbi->regbase == NULL)
+		return -EBUSY;
 
-	res = request_mem_region(res->start, resource_size(res), DRIVER_NAME);
-	if (res == NULL) {
-		dev_err(&pdev->dev, "failed to request I/O memory\n");
-		ret = -EBUSY;
-		goto failed_fbi;
-	}
-
-	fbi->regbase = ioremap(res->start, resource_size(res));
-	if (fbi->regbase == NULL) {
-		dev_err(&pdev->dev, "failed to map I/O memory\n");
-		ret = -EBUSY;
-		goto failed_free_res;
-	}
+	disp_timing = of_get_display_timings(pdev->dev.of_node);
+	if (!disp_timing)
+		return -EINVAL;
 
-	np = of_parse_phandle(pdev->dev.of_node, "default-mode", 0);
-	if (!np) {
-		pr_err("%s: No display description in Device Tree\n", __func__);
-		ret = -EINVAL;
-		goto failed_free_res;
-	}
+	ret = of_get_fb_videomode(pdev->dev.of_node, &mode, OF_USE_NATIVE_MODE);
+	if (ret)
+		return ret;
 
-	/*
-	 * This code is copied from Sascha Hauer's of_videomode helper
-	 * and can be replaced with a call to the helper once mainlined
-	 */
-	ret = 0;
-	ret |= of_property_read_u32(np, "hactive", &of_mode.xres);
-	ret |= of_property_read_u32(np, "vactive", &of_mode.yres);
-	ret |= of_property_read_u32(np, "hback-porch", &of_mode.left_margin);
-	ret |= of_property_read_u32(np, "hfront-porch", &of_mode.right_margin);
-	ret |= of_property_read_u32(np, "hsync-len", &of_mode.hsync_len);
-	ret |= of_property_read_u32(np, "vback-porch", &of_mode.upper_margin);
-	ret |= of_property_read_u32(np, "vfront-porch", &of_mode.lower_margin);
-	ret |= of_property_read_u32(np, "vsync-len", &of_mode.vsync_len);
-	ret |= of_property_read_u32(np, "bpp", &bpp);
-	if (ret) {
-		pr_err("%s: Unable to read display properties\n", __func__);
-		goto failed_free_res;
-	}
+	ret = of_property_read_u32(pdev->dev.of_node, "bits-per-pixel", &bpp);
+	if (ret)
+		return ret;
 
-	of_mode.vmode = FB_VMODE_NONINTERLACED;
-	fb_videomode_to_var(&fbi->fb.var, &of_mode);
+	fb_videomode_to_var(&fbi->fb.var, &mode);
 
 	fbi->fb.var.nonstd		= 0;
 	fbi->fb.var.activate		= FB_ACTIVATE_NOW;
@@ -364,16 +328,16 @@ static int wm8505fb_probe(struct platform_device *pdev)
 	fbi->fb.var.width		= -1;
 
 	/* try allocating the framebuffer */
-	fb_mem_len = of_mode.xres * of_mode.yres * 2 * (bpp / 8);
-	fb_mem_virt = dma_alloc_coherent(&pdev->dev, fb_mem_len, &fb_mem_phys,
+	fb_mem_len = mode.xres * mode.yres * 2 * (bpp / 8);
+	fb_mem_virt = dmam_alloc_coherent(&pdev->dev, fb_mem_len, &fb_mem_phys,
 				GFP_KERNEL);
 	if (!fb_mem_virt) {
 		pr_err("%s: Failed to allocate framebuffer\n", __func__);
 		return -ENOMEM;
-	};
+	}
 
-	fbi->fb.var.xres_virtual	= of_mode.xres;
-	fbi->fb.var.yres_virtual	= of_mode.yres * 2;
+	fbi->fb.var.xres_virtual	= mode.xres;
+	fbi->fb.var.yres_virtual	= mode.yres * 2;
 	fbi->fb.var.bits_per_pixel	= bpp;
 
 	fbi->fb.fix.smem_start		= fb_mem_phys;
@@ -381,28 +345,29 @@ static int wm8505fb_probe(struct platform_device *pdev)
 	fbi->fb.screen_base		= fb_mem_virt;
 	fbi->fb.screen_size		= fb_mem_len;
 
+	fbi->contrast = 0x10;
+	ret = wm8505fb_set_par(&fbi->fb);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to set parameters\n");
+		return ret;
+	}
+
 	if (fb_alloc_cmap(&fbi->fb.cmap, 256, 0) < 0) {
 		dev_err(&pdev->dev, "Failed to allocate color map\n");
-		ret = -ENOMEM;
-		goto failed_free_io;
+		return -ENOMEM;
 	}
 
 	wm8505fb_init_hw(&fbi->fb);
 
-	fbi->contrast = 0x80;
-	ret = wm8505fb_set_par(&fbi->fb);
-	if (ret) {
-		dev_err(&pdev->dev, "Failed to set parameters\n");
-		goto failed_free_cmap;
-	}
-
 	platform_set_drvdata(pdev, fbi);
 
 	ret = register_framebuffer(&fbi->fb);
 	if (ret < 0) {
 		dev_err(&pdev->dev,
 			"Failed to register framebuffer device: %d\n", ret);
-		goto failed_free_cmap;
+		if (fbi->fb.cmap.len)
+			fb_dealloc_cmap(&fbi->fb.cmap);
+		return ret;
 	}
 
 	ret = device_create_file(&pdev->dev, &dev_attr_contrast);
@@ -416,25 +381,11 @@ static int wm8505fb_probe(struct platform_device *pdev)
 	       fbi->fb.fix.smem_start + fbi->fb.fix.smem_len - 1);
 
 	return 0;
-
-failed_free_cmap:
-	if (fbi->fb.cmap.len)
-		fb_dealloc_cmap(&fbi->fb.cmap);
-failed_free_io:
-	iounmap(fbi->regbase);
-failed_free_res:
-	release_mem_region(res->start, resource_size(res));
-failed_fbi:
-	platform_set_drvdata(pdev, NULL);
-	kfree(fbi);
-failed:
-	return ret;
 }
 
 static int wm8505fb_remove(struct platform_device *pdev)
 {
 	struct wm8505fb_info *fbi = platform_get_drvdata(pdev);
-	struct resource *res;
 
 	device_remove_file(&pdev->dev, &dev_attr_contrast);
 
@@ -445,13 +396,6 @@ static int wm8505fb_remove(struct platform_device *pdev)
 	if (fbi->fb.cmap.len)
 		fb_dealloc_cmap(&fbi->fb.cmap);
 
-	iounmap(fbi->regbase);
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	release_mem_region(res->start, resource_size(res));
-
-	kfree(fbi);
-
 	return 0;
 }
 
diff --git a/drivers/video/wmt_ge_rops.h b/drivers/video/wmt_ge_rops.h
index 8738075..f73ec63 100644
--- a/drivers/video/wmt_ge_rops.h
+++ b/drivers/video/wmt_ge_rops.h
@@ -1,5 +1,28 @@
+#ifdef CONFIG_FB_WMT_GE_ROPS
+
 extern void wmt_ge_fillrect(struct fb_info *info,
 			    const struct fb_fillrect *rect);
 extern void wmt_ge_copyarea(struct fb_info *info,
 			    const struct fb_copyarea *area);
 extern int wmt_ge_sync(struct fb_info *info);
+
+#else
+
+static inline int wmt_ge_sync(struct fb_info *p)
+{
+	return 0;
+}
+
+static inline void wmt_ge_fillrect(struct fb_info *p,
+				    const struct fb_fillrect *rect)
+{
+	sys_fillrect(p, rect);
+}
+
+static inline void wmt_ge_copyarea(struct fb_info *p,
+				     const struct fb_copyarea *area)
+{
+	sys_copyarea(p, area);
+}
+
+#endif
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
index 8dab163..bd3ae32 100644
--- a/drivers/virtio/virtio_balloon.c
+++ b/drivers/virtio/virtio_balloon.c
@@ -108,7 +108,7 @@ static void tell_host(struct virtio_balloon *vb, struct virtqueue *vq)
 	sg_init_one(&sg, vb->pfns, sizeof(vb->pfns[0]) * vb->num_pfns);
 
 	/* We should always be able to add one buffer to an empty queue. */
-	if (virtqueue_add_buf(vq, &sg, 1, 0, vb, GFP_KERNEL) < 0)
+	if (virtqueue_add_outbuf(vq, &sg, 1, vb, GFP_KERNEL) < 0)
 		BUG();
 	virtqueue_kick(vq);
 
@@ -256,7 +256,7 @@ static void stats_handle_request(struct virtio_balloon *vb)
 	if (!virtqueue_get_buf(vq, &len))
 		return;
 	sg_init_one(&sg, vb->stats, sizeof(vb->stats));
-	if (virtqueue_add_buf(vq, &sg, 1, 0, vb, GFP_KERNEL) < 0)
+	if (virtqueue_add_outbuf(vq, &sg, 1, vb, GFP_KERNEL) < 0)
 		BUG();
 	virtqueue_kick(vq);
 }
@@ -341,7 +341,7 @@ static int init_vqs(struct virtio_balloon *vb)
 		 * use it to signal us later.
 		 */
 		sg_init_one(&sg, vb->stats, sizeof vb->stats);
-		if (virtqueue_add_buf(vb->stats_vq, &sg, 1, 0, vb, GFP_KERNEL)
+		if (virtqueue_add_outbuf(vb->stats_vq, &sg, 1, vb, GFP_KERNEL)
 		    < 0)
 			BUG();
 		virtqueue_kick(vb->stats_vq);
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index ffd7e7d..5217baf 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -24,27 +24,6 @@
 #include <linux/module.h>
 #include <linux/hrtimer.h>
 
-/* virtio guest is communicating with a virtual "device" that actually runs on
- * a host processor.  Memory barriers are used to control SMP effects. */
-#ifdef CONFIG_SMP
-/* Where possible, use SMP barriers which are more lightweight than mandatory
- * barriers, because mandatory barriers control MMIO effects on accesses
- * through relaxed memory I/O windows (which virtio-pci does not use). */
-#define virtio_mb(vq) \
-	do { if ((vq)->weak_barriers) smp_mb(); else mb(); } while(0)
-#define virtio_rmb(vq) \
-	do { if ((vq)->weak_barriers) smp_rmb(); else rmb(); } while(0)
-#define virtio_wmb(vq) \
-	do { if ((vq)->weak_barriers) smp_wmb(); else wmb(); } while(0)
-#else
-/* We must force memory ordering even if guest is UP since host could be
- * running on another CPU, but SMP barriers are defined to barrier() in that
- * configuration. So fall back to mandatory barriers instead. */
-#define virtio_mb(vq) mb()
-#define virtio_rmb(vq) rmb()
-#define virtio_wmb(vq) wmb()
-#endif
-
 #ifdef DEBUG
 /* For development, we want to crash whenever the ring is screwed. */
 #define BAD_RING(_vq, fmt, args...)				\
@@ -119,16 +98,36 @@ struct vring_virtqueue
 
 #define to_vvq(_vq) container_of(_vq, struct vring_virtqueue, vq)
 
+static inline struct scatterlist *sg_next_chained(struct scatterlist *sg,
+						  unsigned int *count)
+{
+	return sg_next(sg);
+}
+
+static inline struct scatterlist *sg_next_arr(struct scatterlist *sg,
+					      unsigned int *count)
+{
+	if (--(*count) == 0)
+		return NULL;
+	return sg + 1;
+}
+
 /* Set up an indirect table of descriptors and add it to the queue. */
-static int vring_add_indirect(struct vring_virtqueue *vq,
-			      struct scatterlist sg[],
-			      unsigned int out,
-			      unsigned int in,
-			      gfp_t gfp)
+static inline int vring_add_indirect(struct vring_virtqueue *vq,
+				     struct scatterlist *sgs[],
+				     struct scatterlist *(*next)
+				       (struct scatterlist *, unsigned int *),
+				     unsigned int total_sg,
+				     unsigned int total_out,
+				     unsigned int total_in,
+				     unsigned int out_sgs,
+				     unsigned int in_sgs,
+				     gfp_t gfp)
 {
 	struct vring_desc *desc;
 	unsigned head;
-	int i;
+	struct scatterlist *sg;
+	int i, n;
 
 	/*
 	 * We require lowmem mappings for the descriptors because
@@ -137,25 +136,31 @@ static int vring_add_indirect(struct vring_virtqueue *vq,
 	 */
 	gfp &= ~(__GFP_HIGHMEM | __GFP_HIGH);
 
-	desc = kmalloc((out + in) * sizeof(struct vring_desc), gfp);
+	desc = kmalloc(total_sg * sizeof(struct vring_desc), gfp);
 	if (!desc)
 		return -ENOMEM;
 
-	/* Transfer entries from the sg list into the indirect page */
-	for (i = 0; i < out; i++) {
-		desc[i].flags = VRING_DESC_F_NEXT;
-		desc[i].addr = sg_phys(sg);
-		desc[i].len = sg->length;
-		desc[i].next = i+1;
-		sg++;
+	/* Transfer entries from the sg lists into the indirect page */
+	i = 0;
+	for (n = 0; n < out_sgs; n++) {
+		for (sg = sgs[n]; sg; sg = next(sg, &total_out)) {
+			desc[i].flags = VRING_DESC_F_NEXT;
+			desc[i].addr = sg_phys(sg);
+			desc[i].len = sg->length;
+			desc[i].next = i+1;
+			i++;
+		}
 	}
-	for (; i < (out + in); i++) {
-		desc[i].flags = VRING_DESC_F_NEXT|VRING_DESC_F_WRITE;
-		desc[i].addr = sg_phys(sg);
-		desc[i].len = sg->length;
-		desc[i].next = i+1;
-		sg++;
+	for (; n < (out_sgs + in_sgs); n++) {
+		for (sg = sgs[n]; sg; sg = next(sg, &total_in)) {
+			desc[i].flags = VRING_DESC_F_NEXT|VRING_DESC_F_WRITE;
+			desc[i].addr = sg_phys(sg);
+			desc[i].len = sg->length;
+			desc[i].next = i+1;
+			i++;
+		}
 	}
+	BUG_ON(i != total_sg);
 
 	/* Last one doesn't continue. */
 	desc[i-1].flags &= ~VRING_DESC_F_NEXT;
@@ -176,29 +181,20 @@ static int vring_add_indirect(struct vring_virtqueue *vq,
 	return head;
 }
 
-/**
- * virtqueue_add_buf - expose buffer to other end
- * @vq: the struct virtqueue we're talking about.
- * @sg: the description of the buffer(s).
- * @out_num: the number of sg readable by other side
- * @in_num: the number of sg which are writable (after readable ones)
- * @data: the token identifying the buffer.
- * @gfp: how to do memory allocations (if necessary).
- *
- * Caller must ensure we don't call this with other virtqueue operations
- * at the same time (except where noted).
- *
- * Returns zero or a negative error (ie. ENOSPC, ENOMEM).
- */
-int virtqueue_add_buf(struct virtqueue *_vq,
-		      struct scatterlist sg[],
-		      unsigned int out,
-		      unsigned int in,
-		      void *data,
-		      gfp_t gfp)
+static inline int virtqueue_add(struct virtqueue *_vq,
+				struct scatterlist *sgs[],
+				struct scatterlist *(*next)
+				  (struct scatterlist *, unsigned int *),
+				unsigned int total_out,
+				unsigned int total_in,
+				unsigned int out_sgs,
+				unsigned int in_sgs,
+				void *data,
+				gfp_t gfp)
 {
 	struct vring_virtqueue *vq = to_vvq(_vq);
-	unsigned int i, avail, uninitialized_var(prev);
+	struct scatterlist *sg;
+	unsigned int i, n, avail, uninitialized_var(prev), total_sg;
 	int head;
 
 	START_USE(vq);
@@ -218,46 +214,54 @@ int virtqueue_add_buf(struct virtqueue *_vq,
 	}
 #endif
 
+	total_sg = total_in + total_out;
+
 	/* If the host supports indirect descriptor tables, and we have multiple
 	 * buffers, then go indirect. FIXME: tune this threshold */
-	if (vq->indirect && (out + in) > 1 && vq->vq.num_free) {
-		head = vring_add_indirect(vq, sg, out, in, gfp);
+	if (vq->indirect && total_sg > 1 && vq->vq.num_free) {
+		head = vring_add_indirect(vq, sgs, next, total_sg, total_out,
+					  total_in,
+					  out_sgs, in_sgs, gfp);
 		if (likely(head >= 0))
 			goto add_head;
 	}
 
-	BUG_ON(out + in > vq->vring.num);
-	BUG_ON(out + in == 0);
+	BUG_ON(total_sg > vq->vring.num);
+	BUG_ON(total_sg == 0);
 
-	if (vq->vq.num_free < out + in) {
+	if (vq->vq.num_free < total_sg) {
 		pr_debug("Can't add buf len %i - avail = %i\n",
-			 out + in, vq->vq.num_free);
+			 total_sg, vq->vq.num_free);
 		/* FIXME: for historical reasons, we force a notify here if
 		 * there are outgoing parts to the buffer.  Presumably the
 		 * host should service the ring ASAP. */
-		if (out)
+		if (out_sgs)
 			vq->notify(&vq->vq);
 		END_USE(vq);
 		return -ENOSPC;
 	}
 
 	/* We're about to use some buffers from the free list. */
-	vq->vq.num_free -= out + in;
-
-	head = vq->free_head;
-	for (i = vq->free_head; out; i = vq->vring.desc[i].next, out--) {
-		vq->vring.desc[i].flags = VRING_DESC_F_NEXT;
-		vq->vring.desc[i].addr = sg_phys(sg);
-		vq->vring.desc[i].len = sg->length;
-		prev = i;
-		sg++;
+	vq->vq.num_free -= total_sg;
+
+	head = i = vq->free_head;
+	for (n = 0; n < out_sgs; n++) {
+		for (sg = sgs[n]; sg; sg = next(sg, &total_out)) {
+			vq->vring.desc[i].flags = VRING_DESC_F_NEXT;
+			vq->vring.desc[i].addr = sg_phys(sg);
+			vq->vring.desc[i].len = sg->length;
+			prev = i;
+			i = vq->vring.desc[i].next;
+		}
 	}
-	for (; in; i = vq->vring.desc[i].next, in--) {
-		vq->vring.desc[i].flags = VRING_DESC_F_NEXT|VRING_DESC_F_WRITE;
-		vq->vring.desc[i].addr = sg_phys(sg);
-		vq->vring.desc[i].len = sg->length;
-		prev = i;
-		sg++;
+	for (; n < (out_sgs + in_sgs); n++) {
+		for (sg = sgs[n]; sg; sg = next(sg, &total_in)) {
+			vq->vring.desc[i].flags = VRING_DESC_F_NEXT|VRING_DESC_F_WRITE;
+			vq->vring.desc[i].addr = sg_phys(sg);
+			vq->vring.desc[i].len = sg->length;
+			prev = i;
+			i = vq->vring.desc[i].next;
+		}
 	}
 	/* Last one doesn't continue. */
 	vq->vring.desc[prev].flags &= ~VRING_DESC_F_NEXT;
@@ -276,7 +280,7 @@ add_head:
 
 	/* Descriptors and available array need to be set before we expose the
 	 * new available array entries. */
-	virtio_wmb(vq);
+	virtio_wmb(vq->weak_barriers);
 	vq->vring.avail->idx++;
 	vq->num_added++;
 
@@ -290,9 +294,122 @@ add_head:
 
 	return 0;
 }
+
+/**
+ * virtqueue_add_buf - expose buffer to other end
+ * @vq: the struct virtqueue we're talking about.
+ * @sg: the description of the buffer(s).
+ * @out_num: the number of sg readable by other side
+ * @in_num: the number of sg which are writable (after readable ones)
+ * @data: the token identifying the buffer.
+ * @gfp: how to do memory allocations (if necessary).
+ *
+ * Caller must ensure we don't call this with other virtqueue operations
+ * at the same time (except where noted).
+ *
+ * Returns zero or a negative error (ie. ENOSPC, ENOMEM).
+ */
+int virtqueue_add_buf(struct virtqueue *_vq,
+		      struct scatterlist sg[],
+		      unsigned int out,
+		      unsigned int in,
+		      void *data,
+		      gfp_t gfp)
+{
+	struct scatterlist *sgs[2];
+
+	sgs[0] = sg;
+	sgs[1] = sg + out;
+
+	return virtqueue_add(_vq, sgs, sg_next_arr,
+			     out, in, out ? 1 : 0, in ? 1 : 0, data, gfp);
+}
 EXPORT_SYMBOL_GPL(virtqueue_add_buf);
 
 /**
+ * virtqueue_add_sgs - expose buffers to other end
+ * @vq: the struct virtqueue we're talking about.
+ * @sgs: array of terminated scatterlists.
+ * @out_num: the number of scatterlists readable by other side
+ * @in_num: the number of scatterlists which are writable (after readable ones)
+ * @data: the token identifying the buffer.
+ * @gfp: how to do memory allocations (if necessary).
+ *
+ * Caller must ensure we don't call this with other virtqueue operations
+ * at the same time (except where noted).
+ *
+ * Returns zero or a negative error (ie. ENOSPC, ENOMEM).
+ */
+int virtqueue_add_sgs(struct virtqueue *_vq,
+		      struct scatterlist *sgs[],
+		      unsigned int out_sgs,
+		      unsigned int in_sgs,
+		      void *data,
+		      gfp_t gfp)
+{
+	unsigned int i, total_out, total_in;
+
+	/* Count them first. */
+	for (i = total_out = total_in = 0; i < out_sgs; i++) {
+		struct scatterlist *sg;
+		for (sg = sgs[i]; sg; sg = sg_next(sg))
+			total_out++;
+	}
+	for (; i < out_sgs + in_sgs; i++) {
+		struct scatterlist *sg;
+		for (sg = sgs[i]; sg; sg = sg_next(sg))
+			total_in++;
+	}
+	return virtqueue_add(_vq, sgs, sg_next_chained,
+			     total_out, total_in, out_sgs, in_sgs, data, gfp);
+}
+EXPORT_SYMBOL_GPL(virtqueue_add_sgs);
+
+/**
+ * virtqueue_add_outbuf - expose output buffers to other end
+ * @vq: the struct virtqueue we're talking about.
+ * @sgs: array of scatterlists (need not be terminated!)
+ * @num: the number of scatterlists readable by other side
+ * @data: the token identifying the buffer.
+ * @gfp: how to do memory allocations (if necessary).
+ *
+ * Caller must ensure we don't call this with other virtqueue operations
+ * at the same time (except where noted).
+ *
+ * Returns zero or a negative error (ie. ENOSPC, ENOMEM).
+ */
+int virtqueue_add_outbuf(struct virtqueue *vq,
+			 struct scatterlist sg[], unsigned int num,
+			 void *data,
+			 gfp_t gfp)
+{
+	return virtqueue_add(vq, &sg, sg_next_arr, num, 0, 1, 0, data, gfp);
+}
+EXPORT_SYMBOL_GPL(virtqueue_add_outbuf);
+
+/**
+ * virtqueue_add_inbuf - expose input buffers to other end
+ * @vq: the struct virtqueue we're talking about.
+ * @sgs: array of scatterlists (need not be terminated!)
+ * @num: the number of scatterlists writable by other side
+ * @data: the token identifying the buffer.
+ * @gfp: how to do memory allocations (if necessary).
+ *
+ * Caller must ensure we don't call this with other virtqueue operations
+ * at the same time (except where noted).
+ *
+ * Returns zero or a negative error (ie. ENOSPC, ENOMEM).
+ */
+int virtqueue_add_inbuf(struct virtqueue *vq,
+			struct scatterlist sg[], unsigned int num,
+			void *data,
+			gfp_t gfp)
+{
+	return virtqueue_add(vq, &sg, sg_next_arr, 0, num, 0, 1, data, gfp);
+}
+EXPORT_SYMBOL_GPL(virtqueue_add_inbuf);
+
+/**
  * virtqueue_kick_prepare - first half of split virtqueue_kick call.
  * @vq: the struct virtqueue
  *
@@ -312,7 +429,7 @@ bool virtqueue_kick_prepare(struct virtqueue *_vq)
 	START_USE(vq);
 	/* We need to expose available array entries before checking avail
 	 * event. */
-	virtio_mb(vq);
+	virtio_mb(vq->weak_barriers);
 
 	old = vq->vring.avail->idx - vq->num_added;
 	new = vq->vring.avail->idx;
@@ -436,7 +553,7 @@ void *virtqueue_get_buf(struct virtqueue *_vq, unsigned int *len)
 	}
 
 	/* Only get used array entries after they have been exposed by host. */
-	virtio_rmb(vq);
+	virtio_rmb(vq->weak_barriers);
 
 	last_used = (vq->last_used_idx & (vq->vring.num - 1));
 	i = vq->vring.used->ring[last_used].id;
@@ -460,7 +577,7 @@ void *virtqueue_get_buf(struct virtqueue *_vq, unsigned int *len)
 	 * the read in the next get_buf call. */
 	if (!(vq->vring.avail->flags & VRING_AVAIL_F_NO_INTERRUPT)) {
 		vring_used_event(&vq->vring) = vq->last_used_idx;
-		virtio_mb(vq);
+		virtio_mb(vq->weak_barriers);
 	}
 
 #ifdef DEBUG
@@ -513,7 +630,7 @@ bool virtqueue_enable_cb(struct virtqueue *_vq)
 	 * entry. Always do both to keep code simple. */
 	vq->vring.avail->flags &= ~VRING_AVAIL_F_NO_INTERRUPT;
 	vring_used_event(&vq->vring) = vq->last_used_idx;
-	virtio_mb(vq);
+	virtio_mb(vq->weak_barriers);
 	if (unlikely(more_used(vq))) {
 		END_USE(vq);
 		return false;
@@ -553,7 +670,7 @@ bool virtqueue_enable_cb_delayed(struct virtqueue *_vq)
 	/* TODO: tune this threshold */
 	bufs = (u16)(vq->vring.avail->idx - vq->last_used_idx) * 3 / 4;
 	vring_used_event(&vq->vring) = vq->last_used_idx + bufs;
-	virtio_mb(vq);
+	virtio_mb(vq->weak_barriers);
 	if (unlikely((u16)(vq->vring.used->idx - vq->last_used_idx) > bufs)) {
 		END_USE(vq);
 		return false;
diff --git a/drivers/w1/masters/mxc_w1.c b/drivers/w1/masters/mxc_w1.c
index 950d354..47e12cf 100644
--- a/drivers/w1/masters/mxc_w1.c
+++ b/drivers/w1/masters/mxc_w1.c
@@ -121,9 +121,9 @@ static int mxc_w1_probe(struct platform_device *pdev)
 	mdev->clkdiv = (clk_get_rate(mdev->clk) / 1000000) - 1;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	mdev->regs = devm_request_and_ioremap(&pdev->dev, res);
-	if (!mdev->regs)
-		return -EBUSY;
+	mdev->regs = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(mdev->regs))
+		return PTR_ERR(mdev->regs);
 
 	clk_prepare_enable(mdev->clk);
 	__raw_writeb(mdev->clkdiv, mdev->regs + MXC_W1_TIME_DIVIDER);
diff --git a/drivers/w1/slaves/Kconfig b/drivers/w1/slaves/Kconfig
index 762561f..5e6a3c9 100644
--- a/drivers/w1/slaves/Kconfig
+++ b/drivers/w1/slaves/Kconfig
@@ -22,6 +22,16 @@ config W1_SLAVE_DS2408
 	  Say Y here if you want to use a 1-wire
 	  DS2408 8-Channel Addressable Switch device support
 
+config W1_SLAVE_DS2408_READBACK
+	bool "Read-back values written to DS2408's output register"
+	depends on W1_SLAVE_DS2408
+	default y
+	help
+	  Enabling this will cause the driver to read back the values written
+	  to the chip's output register in order to detect errors.
+
+	  This is slower but useful when debugging chips and/or busses.
+
 config W1_SLAVE_DS2413
 	tristate "Dual Channel Addressable Switch 0x3a family support (DS2413)"
 	help
diff --git a/drivers/w1/slaves/w1_ds2408.c b/drivers/w1/slaves/w1_ds2408.c
index 441ad3a..e45eca1 100644
--- a/drivers/w1/slaves/w1_ds2408.c
+++ b/drivers/w1/slaves/w1_ds2408.c
@@ -178,6 +178,15 @@ static ssize_t w1_f29_write_output(
 		w1_write_block(sl->master, w1_buf, 3);
 
 		readBack = w1_read_8(sl->master);
+
+		if (readBack != W1_F29_SUCCESS_CONFIRM_BYTE) {
+			if (w1_reset_resume_command(sl->master))
+				goto error;
+			/* try again, the slave is ready for a command */
+			continue;
+		}
+
+#ifdef CONFIG_W1_SLAVE_DS2408_READBACK
 		/* here the master could read another byte which
 		   would be the PIO reg (the actual pin logic state)
 		   since in this driver we don't know which pins are
@@ -186,11 +195,6 @@ static ssize_t w1_f29_write_output(
 		if (w1_reset_resume_command(sl->master))
 			goto error;
 
-		if (readBack != 0xAA) {
-			/* try again, the slave is ready for a command */
-			continue;
-		}
-
 		/* go read back the output latches */
 		/* (the direct effect of the write above) */
 		w1_buf[0] = W1_F29_FUNC_READ_PIO_REGS;
@@ -198,7 +202,9 @@ static ssize_t w1_f29_write_output(
 		w1_buf[2] = 0;
 		w1_write_block(sl->master, w1_buf, 3);
 		/* read the result of the READ_PIO_REGS command */
-		if (w1_read_8(sl->master) == *buf) {
+		if (w1_read_8(sl->master) == *buf)
+#endif
+		{
 			/* success! */
 			mutex_unlock(&sl->master->bus_mutex);
 			dev_dbg(&sl->dev,
@@ -297,8 +303,7 @@ error:
 
 
 
-#define NB_SYSFS_BIN_FILES 6
-static struct bin_attribute w1_f29_sysfs_bin_files[NB_SYSFS_BIN_FILES] = {
+static struct bin_attribute w1_f29_sysfs_bin_files[] = {
 	{
 		.attr =	{
 			.name = "state",
@@ -357,7 +362,7 @@ static int w1_f29_add_slave(struct w1_slave *sl)
 	int err = 0;
 	int i;
 
-	for (i = 0; i < NB_SYSFS_BIN_FILES && !err; ++i)
+	for (i = 0; i < ARRAY_SIZE(w1_f29_sysfs_bin_files) && !err; ++i)
 		err = sysfs_create_bin_file(
 			&sl->dev.kobj,
 			&(w1_f29_sysfs_bin_files[i]));
@@ -371,7 +376,7 @@ static int w1_f29_add_slave(struct w1_slave *sl)
 static void w1_f29_remove_slave(struct w1_slave *sl)
 {
 	int i;
-	for (i = NB_SYSFS_BIN_FILES - 1; i >= 0; --i)
+	for (i = ARRAY_SIZE(w1_f29_sysfs_bin_files) - 1; i >= 0; --i)
 		sysfs_remove_bin_file(&sl->dev.kobj,
 			&(w1_f29_sysfs_bin_files[i]));
 }
diff --git a/drivers/watchdog/ath79_wdt.c b/drivers/watchdog/ath79_wdt.c
index 8987990..d184c48 100644
--- a/drivers/watchdog/ath79_wdt.c
+++ b/drivers/watchdog/ath79_wdt.c
@@ -253,11 +253,9 @@ static int ath79_wdt_probe(struct platform_device *pdev)
 		return -EINVAL;
 	}
 
-	wdt_base = devm_request_and_ioremap(&pdev->dev, res);
-	if (!wdt_base) {
-		dev_err(&pdev->dev, "unable to remap memory region\n");
-		return -ENOMEM;
-	}
+	wdt_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(wdt_base))
+		return PTR_ERR(wdt_base);
 
 	wdt_clk = devm_clk_get(&pdev->dev, "wdt");
 	if (IS_ERR(wdt_clk))
diff --git a/drivers/watchdog/davinci_wdt.c b/drivers/watchdog/davinci_wdt.c
index 7df1fdc..100d4fb 100644
--- a/drivers/watchdog/davinci_wdt.c
+++ b/drivers/watchdog/davinci_wdt.c
@@ -27,6 +27,7 @@
 #include <linux/device.h>
 #include <linux/clk.h>
 #include <linux/slab.h>
+#include <linux/err.h>
 
 #define MODULE_NAME "DAVINCI-WDT: "
 
@@ -221,11 +222,9 @@ static int davinci_wdt_probe(struct platform_device *pdev)
 		return -ENOENT;
 	}
 
-	wdt_base = devm_request_and_ioremap(dev, wdt_mem);
-	if (!wdt_base) {
-		dev_err(dev, "ioremap failed\n");
-		return -EADDRNOTAVAIL;
-	}
+	wdt_base = devm_ioremap_resource(dev, wdt_mem);
+	if (IS_ERR(wdt_base))
+		return PTR_ERR(wdt_base);
 
 	ret = misc_register(&davinci_wdt_miscdev);
 	if (ret < 0) {
diff --git a/drivers/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c
index c1a221c..ee03135 100644
--- a/drivers/watchdog/s3c2410_wdt.c
+++ b/drivers/watchdog/s3c2410_wdt.c
@@ -330,10 +330,9 @@ static int s3c2410wdt_probe(struct platform_device *pdev)
 	}
 
 	/* get the memory region for the watchdog timer */
-	wdt_base = devm_request_and_ioremap(dev, wdt_mem);
-	if (wdt_base == NULL) {
-		dev_err(dev, "failed to devm_request_and_ioremap() region\n");
-		ret = -ENOMEM;
+	wdt_base = devm_ioremap_resource(dev, wdt_mem);
+	if (IS_ERR(wdt_base)) {
+		ret = PTR_ERR(wdt_base);
 		goto err;
 	}
 
diff --git a/drivers/watchdog/shwdt.c b/drivers/watchdog/shwdt.c
index 6a89e40..6185af2 100644
--- a/drivers/watchdog/shwdt.c
+++ b/drivers/watchdog/shwdt.c
@@ -34,6 +34,7 @@
 #include <linux/slab.h>
 #include <linux/io.h>
 #include <linux/clk.h>
+#include <linux/err.h>
 #include <asm/watchdog.h>
 
 #define DRV_NAME "sh-wdt"
@@ -249,9 +250,9 @@ static int sh_wdt_probe(struct platform_device *pdev)
 		wdt->clk = NULL;
 	}
 
-	wdt->base = devm_request_and_ioremap(wdt->dev, res);
-	if (unlikely(!wdt->base)) {
-		rc = -EADDRNOTAVAIL;
+	wdt->base = devm_ioremap_resource(wdt->dev, res);
+	if (IS_ERR(wdt->base)) {
+		rc = PTR_ERR(wdt->base);
 		goto err;
 	}
 
diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig
index 67af155..dd4d9cb 100644
--- a/drivers/xen/Kconfig
+++ b/drivers/xen/Kconfig
@@ -145,9 +145,9 @@ config SWIOTLB_XEN
 	select SWIOTLB
 
 config XEN_TMEM
-	bool
+	tristate
 	depends on !ARM
-	default y if (CLEANCACHE || FRONTSWAP)
+	default m if (CLEANCACHE || FRONTSWAP)
 	help
 	  Shim to interface in-kernel Transcendent Memory hooks
 	  (e.g. cleancache and frontswap) to Xen tmem hypercalls.
diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c
index a56776d..d42da3b 100644
--- a/drivers/xen/balloon.c
+++ b/drivers/xen/balloon.c
@@ -361,7 +361,9 @@ static enum bp_state increase_reservation(unsigned long nr_pages)
 
 #ifdef CONFIG_XEN_HAVE_PVMMU
 		/* Link back into the page tables if not highmem. */
-		if (xen_pv_domain() && !PageHighMem(page)) {
+		if (xen_pv_domain() && !PageHighMem(page) &&
+		    !xen_feature(XENFEAT_auto_translated_physmap)) {
+
 			int ret;
 			ret = HYPERVISOR_update_va_mapping(
 				(unsigned long)__va(pfn << PAGE_SHIFT),
@@ -420,10 +422,12 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp)
 
 #ifdef CONFIG_XEN_HAVE_PVMMU
 		if (xen_pv_domain() && !PageHighMem(page)) {
-			ret = HYPERVISOR_update_va_mapping(
-				(unsigned long)__va(pfn << PAGE_SHIFT),
-				__pte_ma(0), 0);
-			BUG_ON(ret);
+			if (!xen_feature(XENFEAT_auto_translated_physmap)) {
+				ret = HYPERVISOR_update_va_mapping(
+					(unsigned long)__va(pfn << PAGE_SHIFT),
+					__pte_ma(0), 0);
+				BUG_ON(ret);
+			}
 		}
 #endif
 	}
diff --git a/drivers/xen/cpu_hotplug.c b/drivers/xen/cpu_hotplug.c
index 084041d..b0b87dd 100644
--- a/drivers/xen/cpu_hotplug.c
+++ b/drivers/xen/cpu_hotplug.c
@@ -2,6 +2,7 @@
 
 #include <xen/xen.h>
 #include <xen/xenbus.h>
+#include <xen/features.h>
 
 #include <asm/xen/hypervisor.h>
 #include <asm/cpu.h>
@@ -100,7 +101,8 @@ static int __init setup_vcpu_hotplug_event(void)
 	static struct notifier_block xsn_cpu = {
 		.notifier_call = setup_cpu_watcher };
 
-	if (!xen_pv_domain())
+	/* PVH TBD/FIXME: future work */
+	if (!xen_pv_domain() || xen_feature(XENFEAT_auto_translated_physmap))
 		return -ENODEV;
 
 	register_xenstore_notifier(&xsn_cpu);
diff --git a/drivers/xen/events.c b/drivers/xen/events.c
index aa85881..27599dc 100644
--- a/drivers/xen/events.c
+++ b/drivers/xen/events.c
@@ -1316,7 +1316,7 @@ static void __xen_evtchn_do_upcall(void)
 {
 	int start_word_idx, start_bit_idx;
 	int word_idx, bit_idx;
-	int i;
+	int i, irq;
 	int cpu = get_cpu();
 	struct shared_info *s = HYPERVISOR_shared_info;
 	struct vcpu_info *vcpu_info = __this_cpu_read(xen_vcpu);
@@ -1324,6 +1324,8 @@ static void __xen_evtchn_do_upcall(void)
 
 	do {
 		xen_ulong_t pending_words;
+		xen_ulong_t pending_bits;
+		struct irq_desc *desc;
 
 		vcpu_info->evtchn_upcall_pending = 0;
 
@@ -1335,6 +1337,17 @@ static void __xen_evtchn_do_upcall(void)
 		 * selector flag. xchg_xen_ulong must contain an
 		 * appropriate barrier.
 		 */
+		if ((irq = per_cpu(virq_to_irq, cpu)[VIRQ_TIMER]) != -1) {
+			int evtchn = evtchn_from_irq(irq);
+			word_idx = evtchn / BITS_PER_LONG;
+			pending_bits = evtchn % BITS_PER_LONG;
+			if (active_evtchns(cpu, s, word_idx) & (1ULL << pending_bits)) {
+				desc = irq_to_desc(irq);
+				if (desc)
+					generic_handle_irq_desc(irq, desc);
+			}
+		}
+
 		pending_words = xchg_xen_ulong(&vcpu_info->evtchn_pending_sel, 0);
 
 		start_word_idx = __this_cpu_read(current_word_idx);
@@ -1343,7 +1356,6 @@ static void __xen_evtchn_do_upcall(void)
 		word_idx = start_word_idx;
 
 		for (i = 0; pending_words != 0; i++) {
-			xen_ulong_t pending_bits;
 			xen_ulong_t words;
 
 			words = MASK_LSBS(pending_words, word_idx);
@@ -1372,8 +1384,7 @@ static void __xen_evtchn_do_upcall(void)
 
 			do {
 				xen_ulong_t bits;
-				int port, irq;
-				struct irq_desc *desc;
+				int port;
 
 				bits = MASK_LSBS(pending_bits, bit_idx);
 
@@ -1807,7 +1818,7 @@ int xen_set_callback_via(uint64_t via)
 }
 EXPORT_SYMBOL_GPL(xen_set_callback_via);
 
-#ifdef CONFIG_XEN_PVHVM
+#ifdef CONFIG_X86
 /* Vector callbacks are better than PCI interrupts to receive event
  * channel notifications because we can receive vector callbacks on any
  * vcpu and we don't need PCI support or APIC interactions. */
@@ -1869,6 +1880,13 @@ void __init xen_init_IRQ(void)
 		if (xen_initial_domain())
 			pci_xen_initial_domain();
 
+		if (xen_feature(XENFEAT_hvm_callback_vector)) {
+			xen_callback_vector();
+			return;
+		}
+
+		/* PVH: TBD/FIXME: debug and fix eio map to work with pvh */
+
 		pirq_eoi_map = (void *)__get_free_page(GFP_KERNEL|__GFP_ZERO);
 		eoi_gmfn.gmfn = virt_to_mfn(pirq_eoi_map);
 		rc = HYPERVISOR_physdev_op(PHYSDEVOP_pirq_eoi_gmfn_v2, &eoi_gmfn);
diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c
index 3c8803f..1112a267 100644
--- a/drivers/xen/gntdev.c
+++ b/drivers/xen/gntdev.c
@@ -851,7 +851,8 @@ static int __init gntdev_init(void)
 	if (!xen_domain())
 		return -ENODEV;
 
-	use_ptemod = xen_pv_domain();
+	use_ptemod = xen_pv_domain() &&
+		     !xen_feature(XENFEAT_auto_translated_physmap);
 
 	err = misc_register(&gntdev_miscdev);
 	if (err != 0) {
diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c
index 04c1b2d..f4e067b 100644
--- a/drivers/xen/grant-table.c
+++ b/drivers/xen/grant-table.c
@@ -47,6 +47,7 @@
 #include <xen/grant_table.h>
 #include <xen/interface/memory.h>
 #include <xen/hvc-console.h>
+#include <xen/balloon.h>
 #include <asm/xen/hypercall.h>
 #include <asm/xen/interface.h>
 
@@ -1026,17 +1027,33 @@ static void gnttab_unmap_frames_v2(void)
 	arch_gnttab_unmap(grstatus, nr_status_frames(nr_grant_frames));
 }
 
+static xen_pfn_t pvh_get_grant_pfn(int grant_idx)
+{
+	unsigned long vaddr;
+	unsigned int level;
+	pte_t *pte;
+
+	vaddr = (unsigned long)(gnttab_shared.addr) + grant_idx * PAGE_SIZE;
+	pte = lookup_address(vaddr, &level);
+	BUG_ON(pte == NULL);
+	return pte_mfn(*pte);
+}
+
 static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
 {
 	struct gnttab_setup_table setup;
+	unsigned long start_gpfn = 0;
 	xen_pfn_t *frames;
 	unsigned int nr_gframes = end_idx + 1;
 	int rc;
 
-	if (xen_hvm_domain()) {
+	if (xen_hvm_domain() || xen_feature(XENFEAT_auto_translated_physmap)) {
 		struct xen_add_to_physmap xatp;
 		unsigned int i = end_idx;
 		rc = 0;
+
+		if (xen_hvm_domain())
+			start_gpfn = xen_hvm_resume_frames >> PAGE_SHIFT;
 		/*
 		 * Loop backwards, so that the first hypercall has the largest
 		 * index, ensuring that the table will grow only once.
@@ -1045,7 +1062,11 @@ static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
 			xatp.domid = DOMID_SELF;
 			xatp.idx = i;
 			xatp.space = XENMAPSPACE_grant_table;
-			xatp.gpfn = (xen_hvm_resume_frames >> PAGE_SHIFT) + i;
+			if (xen_hvm_domain())
+				xatp.gpfn = start_gpfn + i;
+			else
+				xatp.gpfn = pvh_get_grant_pfn(i);
+
 			rc = HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp);
 			if (rc != 0) {
 				printk(KERN_WARNING
@@ -1108,7 +1129,7 @@ static void gnttab_request_version(void)
 	int rc;
 	struct gnttab_set_version gsv;
 
-	if (xen_hvm_domain())
+	if (xen_hvm_domain() || xen_feature(XENFEAT_auto_translated_physmap))
 		gsv.version = 1;
 	else
 		gsv.version = 2;
@@ -1135,14 +1156,51 @@ static void gnttab_request_version(void)
 		grant_table_version);
 }
 
+/*
+ * PVH: we need three things: virtual address, pfns, and mfns. The pfns
+ * are allocated via ballooning, then we call arch_gnttab_map_shared to
+ * allocate the VA and put pfn's in the pte's for the VA. The mfn's are
+ * finally allocated in gnttab_map() by xen which also populates the P2M.
+ */
+static int xlated_setup_gnttab_pages(unsigned long numpages, void **addr)
+{
+	int i, rc;
+	unsigned long pfns[numpages];
+	struct page *pages[numpages];
+
+	rc = alloc_xenballooned_pages(numpages, pages, 0);
+	if (rc != 0) {
+		pr_warn("%s Couldn't balloon alloc %ld pfns rc:%d\n", __func__,
+			numpages, rc);
+		return rc;
+	}
+	for (i = 0; i < numpages; i++)
+		pfns[i] = page_to_pfn(pages[i]);
+
+	rc = arch_gnttab_map_shared(pfns, numpages, numpages, addr);
+	if (rc != 0)
+		free_xenballooned_pages(numpages, pages);
+
+	return rc;
+}
+
 static int gnttab_setup(void)
 {
+	int rc;
 	unsigned int max_nr_gframes;
 
 	max_nr_gframes = gnttab_max_grant_frames();
 	if (max_nr_gframes < nr_grant_frames)
 		return -ENOSYS;
 
+	if (xen_pv_domain() && xen_feature(XENFEAT_auto_translated_physmap) &&
+	    !gnttab_shared.addr) {
+
+		rc = xlated_setup_gnttab_pages((unsigned long)max_nr_gframes,
+					       &gnttab_shared.addr);
+		if (rc != 0)
+			return rc;
+	}
 	if (xen_pv_domain())
 		return gnttab_map(0, nr_grant_frames - 1);
 
diff --git a/drivers/xen/privcmd.c b/drivers/xen/privcmd.c
index ca2b00e..2cfc24d 100644
--- a/drivers/xen/privcmd.c
+++ b/drivers/xen/privcmd.c
@@ -504,7 +504,7 @@ static void privcmd_close(struct vm_area_struct *vma)
 	struct page **pages = vma->vm_private_data;
 	int numpgs = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
 
-	if (!xen_feature(XENFEAT_auto_translated_physmap || !numpgs || !pages))
+	if (!xen_feature(XENFEAT_auto_translated_physmap) || !numpgs || !pages)
 		return;
 
 	xen_unmap_domain_mfn_range(vma, numpgs, pages);
diff --git a/drivers/xen/tmem.c b/drivers/xen/tmem.c
index 3ee836d..e3600be 100644
--- a/drivers/xen/tmem.c
+++ b/drivers/xen/tmem.c
@@ -5,6 +5,7 @@
  * Author: Dan Magenheimer
  */
 
+#include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/init.h>
@@ -128,6 +129,7 @@ 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);
 }
 
+#ifndef CONFIG_XEN_TMEM_MODULE
 bool __read_mostly tmem_enabled = false;
 
 static int __init enable_tmem(char *s)
@@ -136,6 +138,7 @@ static int __init enable_tmem(char *s)
 	return 1;
 }
 __setup("tmem", enable_tmem);
+#endif
 
 #ifdef CONFIG_CLEANCACHE
 static int xen_tmem_destroy_pool(u32 pool_id)
@@ -227,16 +230,21 @@ static int tmem_cleancache_init_shared_fs(char *uuid, size_t pagesize)
 	return xen_tmem_new_pool(shared_uuid, TMEM_POOL_SHARED, pagesize);
 }
 
-static bool __initdata use_cleancache = true;
-
+static bool disable_cleancache __read_mostly;
+static bool disable_selfballooning __read_mostly;
+#ifdef CONFIG_XEN_TMEM_MODULE
+module_param(disable_cleancache, bool, S_IRUGO);
+module_param(disable_selfballooning, bool, S_IRUGO);
+#else
 static int __init no_cleancache(char *s)
 {
-	use_cleancache = false;
+	disable_cleancache = true;
 	return 1;
 }
 __setup("nocleancache", no_cleancache);
+#endif
 
-static struct cleancache_ops __initdata tmem_cleancache_ops = {
+static struct cleancache_ops tmem_cleancache_ops = {
 	.put_page = tmem_cleancache_put_page,
 	.get_page = tmem_cleancache_get_page,
 	.invalidate_page = tmem_cleancache_flush_page,
@@ -353,54 +361,71 @@ static void tmem_frontswap_init(unsigned ignored)
 		    xen_tmem_new_pool(private, TMEM_POOL_PERSIST, PAGE_SIZE);
 }
 
-static bool __initdata use_frontswap = true;
-
+static bool disable_frontswap __read_mostly;
+static bool disable_frontswap_selfshrinking __read_mostly;
+#ifdef CONFIG_XEN_TMEM_MODULE
+module_param(disable_frontswap, bool, S_IRUGO);
+module_param(disable_frontswap_selfshrinking, bool, S_IRUGO);
+#else
 static int __init no_frontswap(char *s)
 {
-	use_frontswap = false;
+	disable_frontswap = true;
 	return 1;
 }
 __setup("nofrontswap", no_frontswap);
+#endif
 
-static struct frontswap_ops __initdata tmem_frontswap_ops = {
+static struct frontswap_ops tmem_frontswap_ops = {
 	.store = tmem_frontswap_store,
 	.load = tmem_frontswap_load,
 	.invalidate_page = tmem_frontswap_flush_page,
 	.invalidate_area = tmem_frontswap_flush_area,
 	.init = tmem_frontswap_init
 };
+#else	/* CONFIG_FRONTSWAP */
+#define disable_frontswap_selfshrinking 1
 #endif
 
-static int __init xen_tmem_init(void)
+static int xen_tmem_init(void)
 {
 	if (!xen_domain())
 		return 0;
 #ifdef CONFIG_FRONTSWAP
-	if (tmem_enabled && use_frontswap) {
+	if (tmem_enabled && !disable_frontswap) {
 		char *s = "";
-		struct frontswap_ops old_ops =
+		struct frontswap_ops *old_ops =
 			frontswap_register_ops(&tmem_frontswap_ops);
 
 		tmem_frontswap_poolid = -1;
-		if (old_ops.init != NULL)
+		if (IS_ERR(old_ops) || old_ops) {
+			if (IS_ERR(old_ops))
+				return PTR_ERR(old_ops);
 			s = " (WARNING: frontswap_ops overridden)";
+		}
 		printk(KERN_INFO "frontswap enabled, RAM provided by "
 				 "Xen Transcendent Memory%s\n", s);
 	}
 #endif
 #ifdef CONFIG_CLEANCACHE
 	BUG_ON(sizeof(struct cleancache_filekey) != sizeof(struct tmem_oid));
-	if (tmem_enabled && use_cleancache) {
+	if (tmem_enabled && !disable_cleancache) {
 		char *s = "";
-		struct cleancache_ops old_ops =
+		struct cleancache_ops *old_ops =
 			cleancache_register_ops(&tmem_cleancache_ops);
-		if (old_ops.init_fs != NULL)
+		if (old_ops)
 			s = " (WARNING: cleancache_ops overridden)";
 		printk(KERN_INFO "cleancache enabled, RAM provided by "
 				 "Xen Transcendent Memory%s\n", s);
 	}
 #endif
+#ifdef CONFIG_XEN_SELFBALLOONING
+	xen_selfballoon_init(!disable_selfballooning,
+				!disable_frontswap_selfshrinking);
+#endif
 	return 0;
 }
 
 module_init(xen_tmem_init)
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Dan Magenheimer <dan.magenheimer@oracle.com>");
+MODULE_DESCRIPTION("Shim to Xen transcendent memory");
diff --git a/drivers/xen/xen-selfballoon.c b/drivers/xen/xen-selfballoon.c
index 2552d3e..f2ef569 100644
--- a/drivers/xen/xen-selfballoon.c
+++ b/drivers/xen/xen-selfballoon.c
@@ -121,7 +121,7 @@ static DECLARE_DELAYED_WORK(selfballoon_worker, selfballoon_process);
 static bool frontswap_selfshrinking __read_mostly;
 
 /* Enable/disable with kernel boot option. */
-static bool use_frontswap_selfshrink __initdata = true;
+static bool use_frontswap_selfshrink = true;
 
 /*
  * The default values for the following parameters were deemed reasonable
@@ -185,7 +185,7 @@ static int __init xen_nofrontswap_selfshrink_setup(char *s)
 __setup("noselfshrink", xen_nofrontswap_selfshrink_setup);
 
 /* Disable with kernel boot option. */
-static bool use_selfballooning __initdata = true;
+static bool use_selfballooning = true;
 
 static int __init xen_noselfballooning_setup(char *s)
 {
@@ -196,7 +196,7 @@ static int __init xen_noselfballooning_setup(char *s)
 __setup("noselfballooning", xen_noselfballooning_setup);
 #else /* !CONFIG_FRONTSWAP */
 /* Enable with kernel boot option. */
-static bool use_selfballooning __initdata = false;
+static bool use_selfballooning;
 
 static int __init xen_selfballooning_setup(char *s)
 {
@@ -537,7 +537,7 @@ int register_xen_selfballooning(struct device *dev)
 }
 EXPORT_SYMBOL(register_xen_selfballooning);
 
-static int __init xen_selfballoon_init(void)
+int xen_selfballoon_init(bool use_selfballooning, bool use_frontswap_selfshrink)
 {
 	bool enable = false;
 
@@ -571,7 +571,4 @@ static int __init xen_selfballoon_init(void)
 
 	return 0;
 }
-
-subsys_initcall(xen_selfballoon_init);
-
-MODULE_LICENSE("GPL");
+EXPORT_SYMBOL(xen_selfballoon_init);
diff --git a/drivers/xen/xenbus/xenbus_client.c b/drivers/xen/xenbus/xenbus_client.c
index 61786be..4d9bb0a 100644
--- a/drivers/xen/xenbus/xenbus_client.c
+++ b/drivers/xen/xenbus/xenbus_client.c
@@ -45,6 +45,7 @@
 #include <xen/grant_table.h>
 #include <xen/xenbus.h>
 #include <xen/xen.h>
+#include <xen/features.h>
 
 #include "xenbus_probe.h"
 
@@ -742,7 +743,7 @@ static const struct xenbus_ring_ops ring_ops_hvm = {
 
 void __init xenbus_ring_ops_init(void)
 {
-	if (xen_pv_domain())
+	if (xen_pv_domain() && !xen_feature(XENFEAT_auto_translated_physmap))
 		ring_ops = &ring_ops_pv;
 	else
 		ring_ops = &ring_ops_hvm;
diff --git a/drivers/zorro/proc.c b/drivers/zorro/proc.c
index 73b3383..6d3a602 100644
--- a/drivers/zorro/proc.c
+++ b/drivers/zorro/proc.c
@@ -47,9 +47,7 @@ proc_bus_zorro_lseek(struct file *file, loff_t off, int whence)
 static ssize_t
 proc_bus_zorro_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
 {
-	struct inode *ino = file_inode(file);
-	struct proc_dir_entry *dp = PDE(ino);
-	struct zorro_dev *z = dp->data;
+	struct zorro_dev *z = PDE_DATA(file_inode(file));
 	struct ConfigDev cd;
 	loff_t pos = *ppos;
 
diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c
index 0ad61c6..055562c 100644
--- a/fs/9p/vfs_addr.c
+++ b/fs/9p/vfs_addr.c
@@ -33,6 +33,7 @@
 #include <linux/pagemap.h>
 #include <linux/idr.h>
 #include <linux/sched.h>
+#include <linux/aio.h>
 #include <net/9p/9p.h>
 #include <net/9p/client.h>
 
diff --git a/fs/Kconfig.binfmt b/fs/Kconfig.binfmt
index 0efd152..370b24c 100644
--- a/fs/Kconfig.binfmt
+++ b/fs/Kconfig.binfmt
@@ -65,6 +65,20 @@ config CORE_DUMP_DEFAULT_ELF_HEADERS
 	  This config option changes the default setting of coredump_filter
 	  seen at boot time.  If unsure, say Y.
 
+config BINFMT_SCRIPT
+	tristate "Kernel support for scripts starting with #!"
+	default y
+	help
+	  Say Y here if you want to execute interpreted scripts starting with
+	  #! followed by the path to an interpreter.
+
+	  You can build this support as a module; however, until that module
+	  gets loaded, you cannot run scripts.  Thus, if you want to load this
+	  module from an initramfs, the portion of the initramfs before loading
+	  this module must consist of compiled binaries only.
+
+	  Most systems will not boot if you say M or N here.  If unsure, say Y.
+
 config BINFMT_FLAT
 	bool "Kernel support for flat binaries"
 	depends on !MMU && (!FRV || BROKEN)
diff --git a/fs/Makefile b/fs/Makefile
index 9d53192..9759aca 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -7,10 +7,10 @@
 
 obj-y :=	open.o read_write.o file_table.o super.o \
 		char_dev.o stat.o exec.o pipe.o namei.o fcntl.o \
-		ioctl.o readdir.o select.o fifo.o dcache.o inode.o \
+		ioctl.o readdir.o select.o dcache.o inode.o \
 		attr.o bad_inode.o file.o filesystems.o namespace.o \
 		seq_file.o xattr.o libfs.o fs-writeback.o \
-		pnode.o drop_caches.o splice.o sync.o utimes.o \
+		pnode.o splice.o sync.o utimes.o \
 		stack.o fs_struct.o statfs.o
 
 ifeq ($(CONFIG_BLOCK),y)
@@ -34,10 +34,7 @@ obj-$(CONFIG_COMPAT)		+= compat.o compat_ioctl.o
 obj-$(CONFIG_BINFMT_AOUT)	+= binfmt_aout.o
 obj-$(CONFIG_BINFMT_EM86)	+= binfmt_em86.o
 obj-$(CONFIG_BINFMT_MISC)	+= binfmt_misc.o
-
-# binfmt_script is always there
-obj-y				+= binfmt_script.o
-
+obj-$(CONFIG_BINFMT_SCRIPT)	+= binfmt_script.o
 obj-$(CONFIG_BINFMT_ELF)	+= binfmt_elf.o
 obj-$(CONFIG_COMPAT_BINFMT_ELF)	+= compat_binfmt_elf.o
 obj-$(CONFIG_BINFMT_ELF_FDPIC)	+= binfmt_elf_fdpic.o
@@ -49,6 +46,7 @@ obj-$(CONFIG_FS_POSIX_ACL)	+= posix_acl.o xattr_acl.o
 obj-$(CONFIG_NFS_COMMON)	+= nfs_common/
 obj-$(CONFIG_GENERIC_ACL)	+= generic_acl.o
 obj-$(CONFIG_COREDUMP)		+= coredump.o
+obj-$(CONFIG_SYSCTL)		+= drop_caches.o
 
 obj-$(CONFIG_FHANDLE)		+= fhandle.o
 
diff --git a/fs/afs/proc.c b/fs/afs/proc.c
index 096b23f..526e4bb 100644
--- a/fs/afs/proc.c
+++ b/fs/afs/proc.c
@@ -190,7 +190,7 @@ static int afs_proc_cells_open(struct inode *inode, struct file *file)
 		return ret;
 
 	m = file->private_data;
-	m->private = PDE(inode)->data;
+	m->private = PDE_DATA(inode);
 
 	return 0;
 }
@@ -448,7 +448,7 @@ static int afs_proc_cell_volumes_open(struct inode *inode, struct file *file)
 	struct seq_file *m;
 	int ret;
 
-	cell = PDE(inode)->data;
+	cell = PDE_DATA(inode);
 	if (!cell)
 		return -ENOENT;
 
@@ -554,7 +554,7 @@ static int afs_proc_cell_vlservers_open(struct inode *inode, struct file *file)
 	struct seq_file *m;
 	int ret;
 
-	cell = PDE(inode)->data;
+	cell = PDE_DATA(inode);
 	if (!cell)
 		return -ENOENT;
 
@@ -659,7 +659,7 @@ static int afs_proc_cell_servers_open(struct inode *inode, struct file *file)
 	struct seq_file *m;
 	int ret;
 
-	cell = PDE(inode)->data;
+	cell = PDE_DATA(inode);
 	if (!cell)
 		return -ENOENT;
 
diff --git a/fs/afs/write.c b/fs/afs/write.c
index 7e03ead..a890db4 100644
--- a/fs/afs/write.c
+++ b/fs/afs/write.c
@@ -14,6 +14,7 @@
 #include <linux/pagemap.h>
 #include <linux/writeback.h>
 #include <linux/pagevec.h>
+#include <linux/aio.h>
 #include "internal.h"
 
 static int afs_write_back_from_locked_page(struct afs_writeback *wb,
diff --git a/fs/aio.c b/fs/aio.c
index 3f941f2..5b7ed78 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -8,6 +8,8 @@
  *
  *	See ../COPYING for licensing terms.
  */
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/errno.h>
@@ -18,14 +20,14 @@
 #include <linux/backing-dev.h>
 #include <linux/uio.h>
 
-#define DEBUG 0
-
 #include <linux/sched.h>
 #include <linux/fs.h>
 #include <linux/file.h>
 #include <linux/mm.h>
 #include <linux/mman.h>
+#include <linux/bio.h>
 #include <linux/mmu_context.h>
+#include <linux/percpu.h>
 #include <linux/slab.h>
 #include <linux/timer.h>
 #include <linux/aio.h>
@@ -35,15 +37,111 @@
 #include <linux/eventfd.h>
 #include <linux/blkdev.h>
 #include <linux/compat.h>
+#include <linux/percpu-refcount.h>
 
 #include <asm/kmap_types.h>
 #include <asm/uaccess.h>
 
-#if DEBUG > 1
-#define dprintk		printk
-#else
-#define dprintk(x...)	do { ; } while (0)
-#endif
+#define AIO_RING_MAGIC			0xa10a10a1
+#define AIO_RING_COMPAT_FEATURES	1
+#define AIO_RING_INCOMPAT_FEATURES	0
+struct aio_ring {
+	unsigned	id;	/* kernel internal index number */
+	unsigned	nr;	/* number of io_events */
+	unsigned	head;
+	unsigned	tail;
+
+	unsigned	magic;
+	unsigned	compat_features;
+	unsigned	incompat_features;
+	unsigned	header_length;	/* size of aio_ring */
+
+
+	struct io_event		io_events[0];
+}; /* 128 bytes + ring size */
+
+#define AIO_RING_PAGES	8
+
+struct kioctx_cpu {
+	unsigned		reqs_available;
+};
+
+struct kioctx {
+	struct percpu_ref	users;
+
+	/* This needs improving */
+	unsigned long		user_id;
+	struct hlist_node	list;
+
+	struct __percpu kioctx_cpu *cpu;
+
+	/*
+	 * For percpu reqs_available, number of slots we move to/from global
+	 * counter at a time:
+	 */
+	unsigned		req_batch;
+	/*
+	 * This is what userspace passed to io_setup(), it's not used for
+	 * anything but counting against the global max_reqs quota.
+	 *
+	 * The real limit is nr_events - 1, which will be larger (see
+	 * aio_setup_ring())
+	 */
+	unsigned		max_reqs;
+
+	/* Size of ringbuffer, in units of struct io_event */
+	unsigned		nr_events;
+
+	unsigned long		mmap_base;
+	unsigned long		mmap_size;
+
+	struct page		**ring_pages;
+	long			nr_pages;
+
+	struct rcu_head		rcu_head;
+	struct work_struct	rcu_work;
+
+	struct {
+		/*
+		 * This counts the number of available slots in the ringbuffer,
+		 * so we avoid overflowing it: it's decremented (if positive)
+		 * when allocating a kiocb and incremented when the resulting
+		 * io_event is pulled off the ringbuffer.
+		 *
+		 * We batch accesses to it with a percpu version.
+		 */
+		atomic_t	reqs_available;
+	} ____cacheline_aligned_in_smp;
+
+	struct {
+		spinlock_t	ctx_lock;
+		struct list_head active_reqs;	/* used for cancellation */
+	} ____cacheline_aligned_in_smp;
+
+	struct {
+		struct mutex	ring_lock;
+		wait_queue_head_t wait;
+
+		/*
+		 * Copy of the real tail - to reduce cacheline bouncing. Updated
+		 * by aio_complete() whenever it updates the real tail.
+		 */
+		unsigned	shadow_tail;
+	} ____cacheline_aligned_in_smp;
+
+	struct {
+		/*
+		 * This is the canonical copy of the tail pointer, updated by
+		 * aio_complete(). But aio_complete() also uses it as a lock, so
+		 * other code can't use it; aio_complete() keeps shadow_tail in
+		 * sync with the real value of the tail pointer for other code
+		 * to use.
+		 */
+		unsigned	tail;
+	} ____cacheline_aligned_in_smp;
+
+	struct page		*internal_pages[AIO_RING_PAGES];
+};
 
 /*------ sysctl variables----*/
 static DEFINE_SPINLOCK(aio_nr_lock);
@@ -54,11 +152,6 @@ unsigned long aio_max_nr = 0x10000; /* system wide maximum number of aio request
 static struct kmem_cache	*kiocb_cachep;
 static struct kmem_cache	*kioctx_cachep;
 
-static struct workqueue_struct *aio_wq;
-
-static void aio_kick_handler(struct work_struct *);
-static void aio_queue_work(struct kioctx *);
-
 /* aio_setup
  *	Creates the slab caches used by the aio routines, panic on
  *	failure as this is done early during the boot sequence.
@@ -68,10 +161,7 @@ static int __init aio_setup(void)
 	kiocb_cachep = KMEM_CACHE(kiocb, SLAB_HWCACHE_ALIGN|SLAB_PANIC);
 	kioctx_cachep = KMEM_CACHE(kioctx,SLAB_HWCACHE_ALIGN|SLAB_PANIC);
 
-	aio_wq = alloc_workqueue("aio", 0, 1);	/* used to limit concurrency */
-	BUG_ON(!aio_wq);
-
-	pr_debug("aio_setup: sizeof(struct page) = %d\n", (int)sizeof(struct page));
+	pr_debug("sizeof(struct page) = %zu\n", sizeof(struct page));
 
 	return 0;
 }
@@ -79,28 +169,23 @@ __initcall(aio_setup);
 
 static void aio_free_ring(struct kioctx *ctx)
 {
-	struct aio_ring_info *info = &ctx->ring_info;
 	long i;
 
-	for (i=0; i<info->nr_pages; i++)
-		put_page(info->ring_pages[i]);
+	for (i = 0; i < ctx->nr_pages; i++)
+		put_page(ctx->ring_pages[i]);
 
-	if (info->mmap_size) {
-		BUG_ON(ctx->mm != current->mm);
-		vm_munmap(info->mmap_base, info->mmap_size);
-	}
+	if (ctx->mmap_size)
+		vm_munmap(ctx->mmap_base, ctx->mmap_size);
 
-	if (info->ring_pages && info->ring_pages != info->internal_pages)
-		kfree(info->ring_pages);
-	info->ring_pages = NULL;
-	info->nr = 0;
+	if (ctx->ring_pages && ctx->ring_pages != ctx->internal_pages)
+		kfree(ctx->ring_pages);
 }
 
 static int aio_setup_ring(struct kioctx *ctx)
 {
 	struct aio_ring *ring;
-	struct aio_ring_info *info = &ctx->ring_info;
 	unsigned nr_events = ctx->max_reqs;
+	struct mm_struct *mm = current->mm;
 	unsigned long size, populate;
 	int nr_pages;
 
@@ -116,46 +201,44 @@ static int aio_setup_ring(struct kioctx *ctx)
 
 	nr_events = (PAGE_SIZE * nr_pages - sizeof(struct aio_ring)) / sizeof(struct io_event);
 
-	info->nr = 0;
-	info->ring_pages = info->internal_pages;
+	ctx->nr_events = 0;
+	ctx->ring_pages = ctx->internal_pages;
 	if (nr_pages > AIO_RING_PAGES) {
-		info->ring_pages = kcalloc(nr_pages, sizeof(struct page *), GFP_KERNEL);
-		if (!info->ring_pages)
+		ctx->ring_pages = kcalloc(nr_pages, sizeof(struct page *),
+					  GFP_KERNEL);
+		if (!ctx->ring_pages)
 			return -ENOMEM;
 	}
 
-	info->mmap_size = nr_pages * PAGE_SIZE;
-	dprintk("attempting mmap of %lu bytes\n", info->mmap_size);
-	down_write(&ctx->mm->mmap_sem);
-	info->mmap_base = do_mmap_pgoff(NULL, 0, info->mmap_size, 
-					PROT_READ|PROT_WRITE,
-					MAP_ANONYMOUS|MAP_PRIVATE, 0,
-					&populate);
-	if (IS_ERR((void *)info->mmap_base)) {
-		up_write(&ctx->mm->mmap_sem);
-		info->mmap_size = 0;
+	ctx->mmap_size = nr_pages * PAGE_SIZE;
+	pr_debug("attempting mmap of %lu bytes\n", ctx->mmap_size);
+	down_write(&mm->mmap_sem);
+	ctx->mmap_base = do_mmap_pgoff(NULL, 0, ctx->mmap_size,
+				       PROT_READ|PROT_WRITE,
+				       MAP_ANONYMOUS|MAP_PRIVATE, 0, &populate);
+	if (IS_ERR((void *)ctx->mmap_base)) {
+		up_write(&mm->mmap_sem);
+		ctx->mmap_size = 0;
 		aio_free_ring(ctx);
 		return -EAGAIN;
 	}
 
-	dprintk("mmap address: 0x%08lx\n", info->mmap_base);
-	info->nr_pages = get_user_pages(current, ctx->mm,
-					info->mmap_base, nr_pages, 
-					1, 0, info->ring_pages, NULL);
-	up_write(&ctx->mm->mmap_sem);
+	pr_debug("mmap address: 0x%08lx\n", ctx->mmap_base);
+	ctx->nr_pages = get_user_pages(current, mm, ctx->mmap_base, nr_pages,
+				       1, 0, ctx->ring_pages, NULL);
+	up_write(&mm->mmap_sem);
 
-	if (unlikely(info->nr_pages != nr_pages)) {
+	if (unlikely(ctx->nr_pages != nr_pages)) {
 		aio_free_ring(ctx);
 		return -EAGAIN;
 	}
 	if (populate)
-		mm_populate(info->mmap_base, populate);
-
-	ctx->user_id = info->mmap_base;
+		mm_populate(ctx->mmap_base, populate);
 
-	info->nr = nr_events;		/* trusted copy */
+	ctx->user_id = ctx->mmap_base;
+	ctx->nr_events = nr_events; /* trusted copy */
 
-	ring = kmap_atomic(info->ring_pages[0]);
+	ring = kmap_atomic(ctx->ring_pages[0]);
 	ring->nr = nr_events;	/* user copy */
 	ring->id = ctx->user_id;
 	ring->head = ring->tail = 0;
@@ -164,72 +247,145 @@ static int aio_setup_ring(struct kioctx *ctx)
 	ring->incompat_features = AIO_RING_INCOMPAT_FEATURES;
 	ring->header_length = sizeof(struct aio_ring);
 	kunmap_atomic(ring);
+	flush_dcache_page(ctx->ring_pages[0]);
 
 	return 0;
 }
 
-
-/* aio_ring_event: returns a pointer to the event at the given index from
- * kmap_atomic().  Release the pointer with put_aio_ring_event();
- */
 #define AIO_EVENTS_PER_PAGE	(PAGE_SIZE / sizeof(struct io_event))
 #define AIO_EVENTS_FIRST_PAGE	((PAGE_SIZE - sizeof(struct aio_ring)) / sizeof(struct io_event))
 #define AIO_EVENTS_OFFSET	(AIO_EVENTS_PER_PAGE - AIO_EVENTS_FIRST_PAGE)
 
-#define aio_ring_event(info, nr) ({					\
-	unsigned pos = (nr) + AIO_EVENTS_OFFSET;			\
-	struct io_event *__event;					\
-	__event = kmap_atomic(						\
-			(info)->ring_pages[pos / AIO_EVENTS_PER_PAGE]); \
-	__event += pos % AIO_EVENTS_PER_PAGE;				\
-	__event;							\
-})
-
-#define put_aio_ring_event(event) do {		\
-	struct io_event *__event = (event);	\
-	(void)__event;				\
-	kunmap_atomic((void *)((unsigned long)__event & PAGE_MASK)); \
-} while(0)
-
-static void ctx_rcu_free(struct rcu_head *head)
+void kiocb_set_cancel_fn(struct kiocb *req, kiocb_cancel_fn *cancel)
+{
+	struct kioctx *ctx = req->ki_ctx;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ctx->ctx_lock, flags);
+
+	if (!req->ki_list.next)
+		list_add(&req->ki_list, &ctx->active_reqs);
+
+	req->ki_cancel = cancel;
+
+	spin_unlock_irqrestore(&ctx->ctx_lock, flags);
+}
+EXPORT_SYMBOL(kiocb_set_cancel_fn);
+
+static int kiocb_cancel(struct kioctx *ctx, struct kiocb *kiocb,
+			struct io_event *res)
+{
+	kiocb_cancel_fn *old, *cancel;
+	int ret = -EINVAL;
+
+	/*
+	 * Don't want to set kiocb->ki_cancel = KIOCB_CANCELLED unless it
+	 * actually has a cancel function, hence the cmpxchg()
+	 */
+
+	cancel = ACCESS_ONCE(kiocb->ki_cancel);
+	do {
+		if (!cancel || cancel == KIOCB_CANCELLED)
+			return ret;
+
+		old = cancel;
+		cancel = cmpxchg(&kiocb->ki_cancel, old, KIOCB_CANCELLED);
+	} while (cancel != old);
+
+	atomic_inc(&kiocb->ki_users);
+	spin_unlock_irq(&ctx->ctx_lock);
+
+	memset(res, 0, sizeof(*res));
+	res->obj = (u64)(unsigned long)kiocb->ki_obj.user;
+	res->data = kiocb->ki_user_data;
+	ret = cancel(kiocb, res);
+
+	spin_lock_irq(&ctx->ctx_lock);
+
+	return ret;
+}
+
+static void free_ioctx_rcu(struct rcu_head *head)
 {
 	struct kioctx *ctx = container_of(head, struct kioctx, rcu_head);
+
+	free_percpu(ctx->cpu);
 	kmem_cache_free(kioctx_cachep, ctx);
 }
 
-/* __put_ioctx
- *	Called when the last user of an aio context has gone away,
- *	and the struct needs to be freed.
+/*
+ * When this function runs, the kioctx has been removed from the "hash table"
+ * and ctx->users has dropped to 0, so we know no more kiocbs can be submitted -
+ * now it's safe to cancel any that need to be.
  */
-static void __put_ioctx(struct kioctx *ctx)
+static void free_ioctx(struct kioctx *ctx)
 {
-	unsigned nr_events = ctx->max_reqs;
-	BUG_ON(ctx->reqs_active);
+	struct aio_ring *ring;
+	struct io_event res;
+	struct kiocb *req;
+	unsigned cpu, head, avail;
 
-	cancel_delayed_work_sync(&ctx->wq);
-	aio_free_ring(ctx);
-	mmdrop(ctx->mm);
-	ctx->mm = NULL;
-	if (nr_events) {
-		spin_lock(&aio_nr_lock);
-		BUG_ON(aio_nr - nr_events > aio_nr);
-		aio_nr -= nr_events;
-		spin_unlock(&aio_nr_lock);
+	spin_lock_irq(&ctx->ctx_lock);
+
+	while (!list_empty(&ctx->active_reqs)) {
+		req = list_first_entry(&ctx->active_reqs,
+				       struct kiocb, ki_list);
+
+		list_del_init(&req->ki_list);
+		kiocb_cancel(ctx, req, &res);
 	}
-	pr_debug("__put_ioctx: freeing %p\n", ctx);
-	call_rcu(&ctx->rcu_head, ctx_rcu_free);
-}
 
-static inline int try_get_ioctx(struct kioctx *kioctx)
-{
-	return atomic_inc_not_zero(&kioctx->users);
+	spin_unlock_irq(&ctx->ctx_lock);
+
+	for_each_possible_cpu(cpu) {
+		struct kioctx_cpu *kcpu = per_cpu_ptr(ctx->cpu, cpu);
+
+		atomic_add(kcpu->reqs_available, &ctx->reqs_available);
+		kcpu->reqs_available = 0;
+	}
+
+	ring = kmap_atomic(ctx->ring_pages[0]);
+	head = ring->head;
+	kunmap_atomic(ring);
+
+	while (atomic_read(&ctx->reqs_available) < ctx->nr_events - 1) {
+		wait_event(ctx->wait,
+			   (head != ctx->shadow_tail) ||
+			   (atomic_read(&ctx->reqs_available) >= ctx->nr_events - 1));
+
+		avail = (head <= ctx->shadow_tail
+			 ? ctx->shadow_tail : ctx->nr_events) - head;
+
+		atomic_add(avail, &ctx->reqs_available);
+		head += avail;
+		head %= ctx->nr_events;
+	}
+
+	WARN_ON(atomic_read(&ctx->reqs_available) > ctx->nr_events - 1);
+
+	aio_free_ring(ctx);
+
+	spin_lock(&aio_nr_lock);
+	BUG_ON(aio_nr - ctx->max_reqs > aio_nr);
+	aio_nr -= ctx->max_reqs;
+	spin_unlock(&aio_nr_lock);
+
+	pr_debug("freeing %p\n", ctx);
+
+	/*
+	 * Here the call_rcu() is between the wait_event() for reqs_active to
+	 * hit 0, and freeing the ioctx.
+	 *
+	 * aio_complete() decrements reqs_active, but it has to touch the ioctx
+	 * after to issue a wakeup so we use rcu.
+	 */
+	call_rcu(&ctx->rcu_head, free_ioctx_rcu);
 }
 
-static inline void put_ioctx(struct kioctx *kioctx)
+static void put_ioctx(struct kioctx *ctx)
 {
-	BUG_ON(atomic_read(&kioctx->users) <= 0);
-	if (unlikely(atomic_dec_and_test(&kioctx->users)))
-		__put_ioctx(kioctx);
+	if (percpu_ref_put(&ctx->users))
+		free_ioctx(ctx);
 }
 
 /* ioctx_alloc
@@ -237,10 +393,22 @@ static inline void put_ioctx(struct kioctx *kioctx)
  */
 static struct kioctx *ioctx_alloc(unsigned nr_events)
 {
-	struct mm_struct *mm;
+	struct mm_struct *mm = current->mm;
 	struct kioctx *ctx;
 	int err = -ENOMEM;
 
+	/*
+	 * We keep track of the number of available ringbuffer slots, to prevent
+	 * overflow (reqs_available), and we also use percpu counters for this.
+	 *
+	 * So since up to half the slots might be on other cpu's percpu counters
+	 * and unavailable, double nr_events so userspace sees what they
+	 * expected: additionally, we move req_batch slots to/from percpu
+	 * counters at a time, so make sure that isn't 0:
+	 */
+	nr_events = max(nr_events, num_possible_cpus() * 4);
+	nr_events *= 2;
+
 	/* Prevent overflows */
 	if ((nr_events > (0x10000000U / sizeof(struct io_event))) ||
 	    (nr_events > (0x10000000U / sizeof(struct kiocb)))) {
@@ -256,21 +424,29 @@ static struct kioctx *ioctx_alloc(unsigned nr_events)
 		return ERR_PTR(-ENOMEM);
 
 	ctx->max_reqs = nr_events;
-	mm = ctx->mm = current->mm;
-	atomic_inc(&mm->mm_count);
 
-	atomic_set(&ctx->users, 2);
+	percpu_ref_init(&ctx->users);
+	rcu_read_lock();
+	percpu_ref_get(&ctx->users);
+	rcu_read_unlock();
+
 	spin_lock_init(&ctx->ctx_lock);
-	spin_lock_init(&ctx->ring_info.ring_lock);
+	mutex_init(&ctx->ring_lock);
 	init_waitqueue_head(&ctx->wait);
 
 	INIT_LIST_HEAD(&ctx->active_reqs);
-	INIT_LIST_HEAD(&ctx->run_list);
-	INIT_DELAYED_WORK(&ctx->wq, aio_kick_handler);
 
-	if (aio_setup_ring(ctx) < 0)
+	ctx->cpu = alloc_percpu(struct kioctx_cpu);
+	if (!ctx->cpu)
 		goto out_freectx;
 
+	if (aio_setup_ring(ctx) < 0)
+		goto out_freepcpu;
+
+	atomic_set(&ctx->reqs_available, ctx->nr_events - 1);
+	ctx->req_batch = (ctx->nr_events - 1) / (num_possible_cpus() * 4);
+	BUG_ON(!ctx->req_batch);
+
 	/* limit the number of system wide aios */
 	spin_lock(&aio_nr_lock);
 	if (aio_nr + nr_events > aio_max_nr ||
@@ -286,64 +462,58 @@ static struct kioctx *ioctx_alloc(unsigned nr_events)
 	hlist_add_head_rcu(&ctx->list, &mm->ioctx_list);
 	spin_unlock(&mm->ioctx_lock);
 
-	dprintk("aio: allocated ioctx %p[%ld]: mm=%p mask=0x%x\n",
-		ctx, ctx->user_id, current->mm, ctx->ring_info.nr);
+	pr_debug("allocated ioctx %p[%ld]: mm=%p mask=0x%x\n",
+		 ctx, ctx->user_id, mm, ctx->nr_events);
 	return ctx;
 
 out_cleanup:
 	err = -EAGAIN;
 	aio_free_ring(ctx);
+out_freepcpu:
+	free_percpu(ctx->cpu);
 out_freectx:
-	mmdrop(mm);
 	kmem_cache_free(kioctx_cachep, ctx);
-	dprintk("aio: error allocating ioctx %d\n", err);
+	pr_debug("error allocating ioctx %d\n", err);
 	return ERR_PTR(err);
 }
 
-/* kill_ctx
- *	Cancels all outstanding aio requests on an aio context.  Used 
- *	when the processes owning a context have all exited to encourage 
- *	the rapid destruction of the kioctx.
- */
-static void kill_ctx(struct kioctx *ctx)
+static void kill_ioctx_work(struct work_struct *work)
 {
-	int (*cancel)(struct kiocb *, struct io_event *);
-	struct task_struct *tsk = current;
-	DECLARE_WAITQUEUE(wait, tsk);
-	struct io_event res;
+	struct kioctx *ctx = container_of(work, struct kioctx, rcu_work);
 
-	spin_lock_irq(&ctx->ctx_lock);
-	ctx->dead = 1;
-	while (!list_empty(&ctx->active_reqs)) {
-		struct list_head *pos = ctx->active_reqs.next;
-		struct kiocb *iocb = list_kiocb(pos);
-		list_del_init(&iocb->ki_list);
-		cancel = iocb->ki_cancel;
-		kiocbSetCancelled(iocb);
-		if (cancel) {
-			iocb->ki_users++;
-			spin_unlock_irq(&ctx->ctx_lock);
-			cancel(iocb, &res);
-			spin_lock_irq(&ctx->ctx_lock);
-		}
-	}
+	wake_up_all(&ctx->wait);
+	put_ioctx(ctx);
+}
 
-	if (!ctx->reqs_active)
-		goto out;
+static void kill_ioctx_rcu(struct rcu_head *head)
+{
+	struct kioctx *ctx = container_of(head, struct kioctx, rcu_head);
 
-	add_wait_queue(&ctx->wait, &wait);
-	set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-	while (ctx->reqs_active) {
-		spin_unlock_irq(&ctx->ctx_lock);
-		io_schedule();
-		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-		spin_lock_irq(&ctx->ctx_lock);
-	}
-	__set_task_state(tsk, TASK_RUNNING);
-	remove_wait_queue(&ctx->wait, &wait);
+	INIT_WORK(&ctx->rcu_work, kill_ioctx_work);
+	schedule_work(&ctx->rcu_work);
+}
 
-out:
-	spin_unlock_irq(&ctx->ctx_lock);
+/* kill_ioctx
+ *	Cancels all outstanding aio requests on an aio context.  Used
+ *	when the processes owning a context have all exited to encourage
+ *	the rapid destruction of the kioctx.
+ */
+static void kill_ioctx(struct kioctx *ctx)
+{
+	if (percpu_ref_kill(&ctx->users)) {
+		hlist_del_rcu(&ctx->list);
+		/* Between hlist_del_rcu() and dropping the initial ref */
+		synchronize_rcu();
+
+		/*
+		 * We can't punt to workqueue here because put_ioctx() ->
+		 * free_ioctx() will unmap the ringbuffer, and that has to be
+		 * done in the original process's context. kill_ioctx_rcu/work()
+		 * exist for exit_aio(), as in that path free_ioctx() won't do
+		 * the unmap.
+		 */
+		kill_ioctx_work(&ctx->rcu_work);
+	}
 }
 
 /* wait_on_sync_kiocb:
@@ -351,9 +521,9 @@ out:
  */
 ssize_t wait_on_sync_kiocb(struct kiocb *iocb)
 {
-	while (iocb->ki_users) {
+	while (atomic_read(&iocb->ki_users)) {
 		set_current_state(TASK_UNINTERRUPTIBLE);
-		if (!iocb->ki_users)
+		if (!atomic_read(&iocb->ki_users))
 			break;
 		io_schedule();
 	}
@@ -362,28 +532,20 @@ ssize_t wait_on_sync_kiocb(struct kiocb *iocb)
 }
 EXPORT_SYMBOL(wait_on_sync_kiocb);
 
-/* exit_aio: called when the last user of mm goes away.  At this point, 
- * there is no way for any new requests to be submited or any of the 
- * io_* syscalls to be called on the context.  However, there may be 
- * outstanding requests which hold references to the context; as they 
- * go away, they will call put_ioctx and release any pinned memory
- * associated with the request (held via struct page * references).
+/*
+ * exit_aio: called when the last user of mm goes away.  At this point, there is
+ * no way for any new requests to be submited or any of the io_* syscalls to be
+ * called on the context.
+ *
+ * There may be outstanding kiocbs, but free_ioctx() will explicitly wait on
+ * them.
  */
 void exit_aio(struct mm_struct *mm)
 {
 	struct kioctx *ctx;
+	struct hlist_node *n;
 
-	while (!hlist_empty(&mm->ioctx_list)) {
-		ctx = hlist_entry(mm->ioctx_list.first, struct kioctx, list);
-		hlist_del_rcu(&ctx->list);
-
-		kill_ctx(ctx);
-
-		if (1 != atomic_read(&ctx->users))
-			printk(KERN_DEBUG
-				"exit_aio:ioctx still alive: %d %d %d\n",
-				atomic_read(&ctx->users), ctx->dead,
-				ctx->reqs_active);
+	hlist_for_each_entry_safe(ctx, n, &mm->ioctx_list, list) {
 		/*
 		 * We don't need to bother with munmap() here -
 		 * exit_mmap(mm) is coming and it'll unmap everything.
@@ -391,150 +553,95 @@ void exit_aio(struct mm_struct *mm)
 		 * as indicator that it needs to unmap the area,
 		 * just set it to 0; aio_free_ring() is the only
 		 * place that uses ->mmap_size, so it's safe.
-		 * That way we get all munmap done to current->mm -
-		 * all other callers have ctx->mm == current->mm.
 		 */
-		ctx->ring_info.mmap_size = 0;
-		put_ioctx(ctx);
+		ctx->mmap_size = 0;
+
+		if (percpu_ref_kill(&ctx->users)) {
+			hlist_del_rcu(&ctx->list);
+			call_rcu(&ctx->rcu_head, kill_ioctx_rcu);
+		}
 	}
 }
 
-/* aio_get_req
- *	Allocate a slot for an aio request.  Increments the users count
- * of the kioctx so that the kioctx stays around until all requests are
- * complete.  Returns NULL if no requests are free.
- *
- * Returns with kiocb->users set to 2.  The io submit code path holds
- * an extra reference while submitting the i/o.
- * This prevents races between the aio code path referencing the
- * req (after submitting it) and aio_complete() freeing the req.
- */
-static struct kiocb *__aio_get_req(struct kioctx *ctx)
+static void put_reqs_available(struct kioctx *ctx, unsigned nr)
 {
-	struct kiocb *req = NULL;
+	struct kioctx_cpu *kcpu;
 
-	req = kmem_cache_alloc(kiocb_cachep, GFP_KERNEL);
-	if (unlikely(!req))
-		return NULL;
+	preempt_disable();
+	kcpu = this_cpu_ptr(ctx->cpu);
 
-	req->ki_flags = 0;
-	req->ki_users = 2;
-	req->ki_key = 0;
-	req->ki_ctx = ctx;
-	req->ki_cancel = NULL;
-	req->ki_retry = NULL;
-	req->ki_dtor = NULL;
-	req->private = NULL;
-	req->ki_iovec = NULL;
-	INIT_LIST_HEAD(&req->ki_run_list);
-	req->ki_eventfd = NULL;
+	kcpu->reqs_available += nr;
+	while (kcpu->reqs_available >= ctx->req_batch * 2) {
+		kcpu->reqs_available -= ctx->req_batch;
+		atomic_add(ctx->req_batch, &ctx->reqs_available);
+	}
 
-	return req;
+	preempt_enable();
 }
 
-/*
- * struct kiocb's are allocated in batches to reduce the number of
- * times the ctx lock is acquired and released.
- */
-#define KIOCB_BATCH_SIZE	32L
-struct kiocb_batch {
-	struct list_head head;
-	long count; /* number of requests left to allocate */
-};
-
-static void kiocb_batch_init(struct kiocb_batch *batch, long total)
+static bool get_reqs_available(struct kioctx *ctx)
 {
-	INIT_LIST_HEAD(&batch->head);
-	batch->count = total;
-}
+	struct kioctx_cpu *kcpu;
+	bool ret = false;
 
-static void kiocb_batch_free(struct kioctx *ctx, struct kiocb_batch *batch)
-{
-	struct kiocb *req, *n;
+	preempt_disable();
+	kcpu = this_cpu_ptr(ctx->cpu);
 
-	if (list_empty(&batch->head))
-		return;
+	if (!kcpu->reqs_available) {
+		int old, avail = atomic_read(&ctx->reqs_available);
 
-	spin_lock_irq(&ctx->ctx_lock);
-	list_for_each_entry_safe(req, n, &batch->head, ki_batch) {
-		list_del(&req->ki_batch);
-		list_del(&req->ki_list);
-		kmem_cache_free(kiocb_cachep, req);
-		ctx->reqs_active--;
-	}
-	if (unlikely(!ctx->reqs_active && ctx->dead))
-		wake_up_all(&ctx->wait);
-	spin_unlock_irq(&ctx->ctx_lock);
-}
-
-/*
- * Allocate a batch of kiocbs.  This avoids taking and dropping the
- * context lock a lot during setup.
- */
-static int kiocb_batch_refill(struct kioctx *ctx, struct kiocb_batch *batch)
-{
-	unsigned short allocated, to_alloc;
-	long avail;
-	struct kiocb *req, *n;
-	struct aio_ring *ring;
-
-	to_alloc = min(batch->count, KIOCB_BATCH_SIZE);
-	for (allocated = 0; allocated < to_alloc; allocated++) {
-		req = __aio_get_req(ctx);
-		if (!req)
-			/* allocation failed, go with what we've got */
-			break;
-		list_add(&req->ki_batch, &batch->head);
-	}
-
-	if (allocated == 0)
-		goto out;
+		do {
+			if (avail < ctx->req_batch)
+				goto out;
 
-	spin_lock_irq(&ctx->ctx_lock);
-	ring = kmap_atomic(ctx->ring_info.ring_pages[0]);
-
-	avail = aio_ring_avail(&ctx->ring_info, ring) - ctx->reqs_active;
-	BUG_ON(avail < 0);
-	if (avail < allocated) {
-		/* Trim back the number of requests. */
-		list_for_each_entry_safe(req, n, &batch->head, ki_batch) {
-			list_del(&req->ki_batch);
-			kmem_cache_free(kiocb_cachep, req);
-			if (--allocated <= avail)
-				break;
-		}
-	}
+			old = avail;
+			avail = atomic_cmpxchg(&ctx->reqs_available,
+					       avail, avail - ctx->req_batch);
+		} while (avail != old);
 
-	batch->count -= allocated;
-	list_for_each_entry(req, &batch->head, ki_batch) {
-		list_add(&req->ki_list, &ctx->active_reqs);
-		ctx->reqs_active++;
+		kcpu->reqs_available += ctx->req_batch;
 	}
 
-	kunmap_atomic(ring);
-	spin_unlock_irq(&ctx->ctx_lock);
-
+	ret = true;
+	kcpu->reqs_available--;
 out:
-	return allocated;
+	preempt_enable();
+	return ret;
 }
 
-static inline struct kiocb *aio_get_req(struct kioctx *ctx,
-					struct kiocb_batch *batch)
+/* aio_get_req
+ *	Allocate a slot for an aio request.  Increments the ki_users count
+ * of the kioctx so that the kioctx stays around until all requests are
+ * complete.  Returns NULL if no requests are free.
+ *
+ * Returns with kiocb->ki_users set to 2.  The io submit code path holds
+ * an extra reference while submitting the i/o.
+ * This prevents races between the aio code path referencing the
+ * req (after submitting it) and aio_complete() freeing the req.
+ */
+static inline struct kiocb *aio_get_req(struct kioctx *ctx)
 {
 	struct kiocb *req;
 
-	if (list_empty(&batch->head))
-		if (kiocb_batch_refill(ctx, batch) == 0)
-			return NULL;
-	req = list_first_entry(&batch->head, struct kiocb, ki_batch);
-	list_del(&req->ki_batch);
+	if (!get_reqs_available(ctx))
+		return NULL;
+
+	req = kmem_cache_alloc(kiocb_cachep, GFP_KERNEL|__GFP_ZERO);
+	if (unlikely(!req))
+		goto out_put;
+
+	atomic_set(&req->ki_users, 2);
+	req->ki_ctx = ctx;
 	return req;
+out_put:
+	put_reqs_available(ctx, 1);
+	return NULL;
 }
 
-static inline void really_put_req(struct kioctx *ctx, struct kiocb *req)
+static void kiocb_free(struct kiocb *req)
 {
-	assert_spin_locked(&ctx->ctx_lock);
-
+	if (req->ki_filp)
+		fput(req->ki_filp);
 	if (req->ki_eventfd != NULL)
 		eventfd_ctx_put(req->ki_eventfd);
 	if (req->ki_dtor)
@@ -542,48 +649,12 @@ static inline void really_put_req(struct kioctx *ctx, struct kiocb *req)
 	if (req->ki_iovec != &req->ki_inline_vec)
 		kfree(req->ki_iovec);
 	kmem_cache_free(kiocb_cachep, req);
-	ctx->reqs_active--;
-
-	if (unlikely(!ctx->reqs_active && ctx->dead))
-		wake_up_all(&ctx->wait);
 }
 
-/* __aio_put_req
- *	Returns true if this put was the last user of the request.
- */
-static int __aio_put_req(struct kioctx *ctx, struct kiocb *req)
+void aio_put_req(struct kiocb *req)
 {
-	dprintk(KERN_DEBUG "aio_put(%p): f_count=%ld\n",
-		req, atomic_long_read(&req->ki_filp->f_count));
-
-	assert_spin_locked(&ctx->ctx_lock);
-
-	req->ki_users--;
-	BUG_ON(req->ki_users < 0);
-	if (likely(req->ki_users))
-		return 0;
-	list_del(&req->ki_list);		/* remove from active_reqs */
-	req->ki_cancel = NULL;
-	req->ki_retry = NULL;
-
-	fput(req->ki_filp);
-	req->ki_filp = NULL;
-	really_put_req(ctx, req);
-	return 1;
-}
-
-/* aio_put_req
- *	Returns true if this put was the last user of the kiocb,
- *	false if the request is still in use.
- */
-int aio_put_req(struct kiocb *req)
-{
-	struct kioctx *ctx = req->ki_ctx;
-	int ret;
-	spin_lock_irq(&ctx->ctx_lock);
-	ret = __aio_put_req(ctx, req);
-	spin_unlock_irq(&ctx->ctx_lock);
-	return ret;
+	if (atomic_dec_and_test(&req->ki_users))
+		kiocb_free(req);
 }
 EXPORT_SYMBOL(aio_put_req);
 
@@ -595,13 +666,8 @@ static struct kioctx *lookup_ioctx(unsigned long ctx_id)
 	rcu_read_lock();
 
 	hlist_for_each_entry_rcu(ctx, &mm->ioctx_list, list) {
-		/*
-		 * RCU protects us against accessing freed memory but
-		 * we have to be careful not to get a reference when the
-		 * reference count already dropped to 0 (ctx->dead test
-		 * is unreliable because of races).
-		 */
-		if (ctx->user_id == ctx_id && !ctx->dead && try_get_ioctx(ctx)){
+		if (ctx->user_id == ctx_id) {
+			percpu_ref_get(&ctx->users);
 			ret = ctx;
 			break;
 		}
@@ -611,610 +677,332 @@ static struct kioctx *lookup_ioctx(unsigned long ctx_id)
 	return ret;
 }
 
-/*
- * Queue up a kiocb to be retried. Assumes that the kiocb
- * has already been marked as kicked, and places it on
- * the retry run list for the corresponding ioctx, if it
- * isn't already queued. Returns 1 if it actually queued
- * the kiocb (to tell the caller to activate the work
- * queue to process it), or 0, if it found that it was
- * already queued.
- */
-static inline int __queue_kicked_iocb(struct kiocb *iocb)
+static inline unsigned kioctx_ring_put(struct kioctx *ctx, struct kiocb *req,
+				       unsigned tail)
 {
-	struct kioctx *ctx = iocb->ki_ctx;
+	struct io_event	*ev_page, *event;
+	unsigned pos = tail + AIO_EVENTS_OFFSET;
 
-	assert_spin_locked(&ctx->ctx_lock);
-
-	if (list_empty(&iocb->ki_run_list)) {
-		list_add_tail(&iocb->ki_run_list,
-			&ctx->run_list);
-		return 1;
-	}
-	return 0;
-}
-
-/* aio_run_iocb
- *	This is the core aio execution routine. It is
- *	invoked both for initial i/o submission and
- *	subsequent retries via the aio_kick_handler.
- *	Expects to be invoked with iocb->ki_ctx->lock
- *	already held. The lock is released and reacquired
- *	as needed during processing.
- *
- * Calls the iocb retry method (already setup for the
- * iocb on initial submission) for operation specific
- * handling, but takes care of most of common retry
- * execution details for a given iocb. The retry method
- * needs to be non-blocking as far as possible, to avoid
- * holding up other iocbs waiting to be serviced by the
- * retry kernel thread.
- *
- * The trickier parts in this code have to do with
- * ensuring that only one retry instance is in progress
- * for a given iocb at any time. Providing that guarantee
- * simplifies the coding of individual aio operations as
- * it avoids various potential races.
- */
-static ssize_t aio_run_iocb(struct kiocb *iocb)
-{
-	struct kioctx	*ctx = iocb->ki_ctx;
-	ssize_t (*retry)(struct kiocb *);
-	ssize_t ret;
-
-	if (!(retry = iocb->ki_retry)) {
-		printk("aio_run_iocb: iocb->ki_retry = NULL\n");
-		return 0;
-	}
-
-	/*
-	 * We don't want the next retry iteration for this
-	 * operation to start until this one has returned and
-	 * updated the iocb state. However, wait_queue functions
-	 * can trigger a kick_iocb from interrupt context in the
-	 * meantime, indicating that data is available for the next
-	 * iteration. We want to remember that and enable the
-	 * next retry iteration _after_ we are through with
-	 * this one.
-	 *
-	 * So, in order to be able to register a "kick", but
-	 * prevent it from being queued now, we clear the kick
-	 * flag, but make the kick code *think* that the iocb is
-	 * still on the run list until we are actually done.
-	 * When we are done with this iteration, we check if
-	 * the iocb was kicked in the meantime and if so, queue
-	 * it up afresh.
-	 */
-
-	kiocbClearKicked(iocb);
-
-	/*
-	 * This is so that aio_complete knows it doesn't need to
-	 * pull the iocb off the run list (We can't just call
-	 * INIT_LIST_HEAD because we don't want a kick_iocb to
-	 * queue this on the run list yet)
-	 */
-	iocb->ki_run_list.next = iocb->ki_run_list.prev = NULL;
-	spin_unlock_irq(&ctx->ctx_lock);
-
-	/* Quit retrying if the i/o has been cancelled */
-	if (kiocbIsCancelled(iocb)) {
-		ret = -EINTR;
-		aio_complete(iocb, ret, 0);
-		/* must not access the iocb after this */
-		goto out;
-	}
-
-	/*
-	 * Now we are all set to call the retry method in async
-	 * context.
-	 */
-	ret = retry(iocb);
-
-	if (ret != -EIOCBRETRY && ret != -EIOCBQUEUED) {
-		/*
-		 * There's no easy way to restart the syscall since other AIO's
-		 * may be already running. Just fail this IO with EINTR.
-		 */
-		if (unlikely(ret == -ERESTARTSYS || ret == -ERESTARTNOINTR ||
-			     ret == -ERESTARTNOHAND || ret == -ERESTART_RESTARTBLOCK))
-			ret = -EINTR;
-		aio_complete(iocb, ret, 0);
-	}
-out:
-	spin_lock_irq(&ctx->ctx_lock);
-
-	if (-EIOCBRETRY == ret) {
-		/*
-		 * OK, now that we are done with this iteration
-		 * and know that there is more left to go,
-		 * this is where we let go so that a subsequent
-		 * "kick" can start the next iteration
-		 */
-
-		/* will make __queue_kicked_iocb succeed from here on */
-		INIT_LIST_HEAD(&iocb->ki_run_list);
-		/* we must queue the next iteration ourselves, if it
-		 * has already been kicked */
-		if (kiocbIsKicked(iocb)) {
-			__queue_kicked_iocb(iocb);
-
-			/*
-			 * __queue_kicked_iocb will always return 1 here, because
-			 * iocb->ki_run_list is empty at this point so it should
-			 * be safe to unconditionally queue the context into the
-			 * work queue.
-			 */
-			aio_queue_work(ctx);
-		}
-	}
-	return ret;
-}
-
-/*
- * __aio_run_iocbs:
- * 	Process all pending retries queued on the ioctx
- * 	run list.
- * Assumes it is operating within the aio issuer's mm
- * context.
- */
-static int __aio_run_iocbs(struct kioctx *ctx)
-{
-	struct kiocb *iocb;
-	struct list_head run_list;
-
-	assert_spin_locked(&ctx->ctx_lock);
-
-	list_replace_init(&ctx->run_list, &run_list);
-	while (!list_empty(&run_list)) {
-		iocb = list_entry(run_list.next, struct kiocb,
-			ki_run_list);
-		list_del(&iocb->ki_run_list);
-		/*
-		 * Hold an extra reference while retrying i/o.
-		 */
-		iocb->ki_users++;       /* grab extra reference */
-		aio_run_iocb(iocb);
-		__aio_put_req(ctx, iocb);
- 	}
-	if (!list_empty(&ctx->run_list))
-		return 1;
-	return 0;
-}
+	if (++tail >= ctx->nr_events)
+		tail = 0;
 
-static void aio_queue_work(struct kioctx * ctx)
-{
-	unsigned long timeout;
-	/*
-	 * if someone is waiting, get the work started right
-	 * away, otherwise, use a longer delay
-	 */
-	smp_mb();
-	if (waitqueue_active(&ctx->wait))
-		timeout = 1;
-	else
-		timeout = HZ/10;
-	queue_delayed_work(aio_wq, &ctx->wq, timeout);
-}
+	ev_page = kmap_atomic(ctx->ring_pages[pos / AIO_EVENTS_PER_PAGE]);
+	event = ev_page + pos % AIO_EVENTS_PER_PAGE;
 
-/*
- * aio_run_all_iocbs:
- *	Process all pending retries queued on the ioctx
- *	run list, and keep running them until the list
- *	stays empty.
- * Assumes it is operating within the aio issuer's mm context.
- */
-static inline void aio_run_all_iocbs(struct kioctx *ctx)
-{
-	spin_lock_irq(&ctx->ctx_lock);
-	while (__aio_run_iocbs(ctx))
-		;
-	spin_unlock_irq(&ctx->ctx_lock);
-}
+	event->obj	= (u64)(unsigned long)req->ki_obj.user;
+	event->data	= req->ki_user_data;
+	event->res	= req->ki_res;
+	event->res2	= req->ki_res2;
 
-/*
- * aio_kick_handler:
- * 	Work queue handler triggered to process pending
- * 	retries on an ioctx. Takes on the aio issuer's
- *	mm context before running the iocbs, so that
- *	copy_xxx_user operates on the issuer's address
- *      space.
- * Run on aiod's context.
- */
-static void aio_kick_handler(struct work_struct *work)
-{
-	struct kioctx *ctx = container_of(work, struct kioctx, wq.work);
-	mm_segment_t oldfs = get_fs();
-	struct mm_struct *mm;
-	int requeue;
+	kunmap_atomic(ev_page);
+	flush_dcache_page(ctx->ring_pages[pos / AIO_EVENTS_PER_PAGE]);
 
-	set_fs(USER_DS);
-	use_mm(ctx->mm);
-	spin_lock_irq(&ctx->ctx_lock);
-	requeue =__aio_run_iocbs(ctx);
-	mm = ctx->mm;
-	spin_unlock_irq(&ctx->ctx_lock);
- 	unuse_mm(mm);
-	set_fs(oldfs);
-	/*
-	 * we're in a worker thread already; no point using non-zero delay
-	 */
-	if (requeue)
-		queue_delayed_work(aio_wq, &ctx->wq, 0);
-}
+	pr_debug("%p[%u]: %p: %p %Lx %lx %lx\n",
+		 ctx, tail, req, req->ki_obj.user, req->ki_user_data,
+		 req->ki_res, req->ki_res2);
 
+	return tail;
+}
 
-/*
- * Called by kick_iocb to queue the kiocb for retry
- * and if required activate the aio work queue to process
- * it
- */
-static void try_queue_kicked_iocb(struct kiocb *iocb)
+static inline unsigned kioctx_ring_lock(struct kioctx *ctx)
 {
- 	struct kioctx	*ctx = iocb->ki_ctx;
-	unsigned long flags;
-	int run = 0;
+	unsigned tail;
 
-	spin_lock_irqsave(&ctx->ctx_lock, flags);
-	/* set this inside the lock so that we can't race with aio_run_iocb()
-	 * testing it and putting the iocb on the run list under the lock */
-	if (!kiocbTryKick(iocb))
-		run = __queue_kicked_iocb(iocb);
-	spin_unlock_irqrestore(&ctx->ctx_lock, flags);
-	if (run)
-		aio_queue_work(ctx);
+	/*
+	 * ctx->tail is both our lock and the canonical version of the tail
+	 * pointer.
+	 */
+	while ((tail = xchg(&ctx->tail, UINT_MAX)) == UINT_MAX)
+		cpu_relax();
+
+	return tail;
 }
 
-/*
- * kick_iocb:
- *      Called typically from a wait queue callback context
- *      to trigger a retry of the iocb.
- *      The retry is usually executed by aio workqueue
- *      threads (See aio_kick_handler).
- */
-void kick_iocb(struct kiocb *iocb)
+static inline void kioctx_ring_unlock(struct kioctx *ctx, unsigned tail)
 {
-	/* sync iocbs are easy: they can only ever be executing from a 
-	 * single context. */
-	if (is_sync_kiocb(iocb)) {
-		kiocbSetKicked(iocb);
-	        wake_up_process(iocb->ki_obj.tsk);
+	struct aio_ring *ring;
+
+	if (!ctx)
 		return;
-	}
 
-	try_queue_kicked_iocb(iocb);
-}
-EXPORT_SYMBOL(kick_iocb);
+	smp_wmb();
+	/* make event visible before updating tail */
 
-/* aio_complete
- *	Called when the io request on the given iocb is complete.
- *	Returns true if this is the last user of the request.  The 
- *	only other user of the request can be the cancellation code.
- */
-int aio_complete(struct kiocb *iocb, long res, long res2)
-{
-	struct kioctx	*ctx = iocb->ki_ctx;
-	struct aio_ring_info	*info;
-	struct aio_ring	*ring;
-	struct io_event	*event;
-	unsigned long	flags;
-	unsigned long	tail;
-	int		ret;
+	ctx->shadow_tail = tail;
 
-	/*
-	 * Special case handling for sync iocbs:
-	 *  - events go directly into the iocb for fast handling
-	 *  - the sync task with the iocb in its stack holds the single iocb
-	 *    ref, no other paths have a way to get another ref
-	 *  - the sync task helpfully left a reference to itself in the iocb
-	 */
-	if (is_sync_kiocb(iocb)) {
-		BUG_ON(iocb->ki_users != 1);
-		iocb->ki_user_data = res;
-		iocb->ki_users = 0;
-		wake_up_process(iocb->ki_obj.tsk);
-		return 1;
-	}
+	ring = kmap_atomic(ctx->ring_pages[0]);
+	ring->tail = tail;
+	kunmap_atomic(ring);
+	flush_dcache_page(ctx->ring_pages[0]);
 
-	info = &ctx->ring_info;
+	/* unlock, make new tail visible before checking waitlist */
+	smp_mb();
 
-	/* add a completion event to the ring buffer.
-	 * must be done holding ctx->ctx_lock to prevent
-	 * other code from messing with the tail
-	 * pointer since we might be called from irq
-	 * context.
-	 */
-	spin_lock_irqsave(&ctx->ctx_lock, flags);
+	ctx->tail = tail;
+
+	if (waitqueue_active(&ctx->wait))
+		wake_up(&ctx->wait);
+}
+
+void batch_complete_aio(struct batch_complete *batch)
+{
+	struct kioctx *ctx = NULL;
+	struct eventfd_ctx *eventfd = NULL;
+	struct rb_node *n;
+	unsigned long flags;
+	unsigned tail = 0;
 
-	if (iocb->ki_run_list.prev && !list_empty(&iocb->ki_run_list))
-		list_del_init(&iocb->ki_run_list);
+	if (RB_EMPTY_ROOT(&batch->kiocb))
+		return;
 
 	/*
-	 * cancelled requests don't get events, userland was given one
-	 * when the event got cancelled.
+	 * Take rcu_read_lock() in case the kioctx is being destroyed, as we
+	 * need to issue a wakeup after incrementing reqs_available.
 	 */
-	if (kiocbIsCancelled(iocb))
-		goto put_rq;
+	rcu_read_lock();
+	local_irq_save(flags);
 
-	ring = kmap_atomic(info->ring_pages[0]);
+	n = rb_first(&batch->kiocb);
+	while (n) {
+		struct kiocb *req = container_of(n, struct kiocb, ki_node);
 
-	tail = info->tail;
-	event = aio_ring_event(info, tail);
-	if (++tail >= info->nr)
-		tail = 0;
+		if (n->rb_right) {
+			n->rb_right->__rb_parent_color = n->__rb_parent_color;
+			n = n->rb_right;
 
-	event->obj = (u64)(unsigned long)iocb->ki_obj.user;
-	event->data = iocb->ki_user_data;
-	event->res = res;
-	event->res2 = res2;
+			while (n->rb_left)
+				n = n->rb_left;
+		} else {
+			n = rb_parent(n);
+		}
 
-	dprintk("aio_complete: %p[%lu]: %p: %p %Lx %lx %lx\n",
-		ctx, tail, iocb, iocb->ki_obj.user, iocb->ki_user_data,
-		res, res2);
+		if (unlikely(req->ki_eventfd != eventfd)) {
+			if (eventfd) {
+				/* Make event visible */
+				kioctx_ring_unlock(ctx, tail);
+				ctx = NULL;
 
-	/* after flagging the request as done, we
-	 * must never even look at it again
-	 */
-	smp_wmb();	/* make event visible before updating tail */
+				eventfd_signal(eventfd, 1);
+				eventfd_ctx_put(eventfd);
+			}
 
-	info->tail = tail;
-	ring->tail = tail;
+			eventfd = req->ki_eventfd;
+			req->ki_eventfd = NULL;
+		}
 
-	put_aio_ring_event(event);
-	kunmap_atomic(ring);
+		if (unlikely(req->ki_ctx != ctx)) {
+			kioctx_ring_unlock(ctx, tail);
 
-	pr_debug("added to ring %p at [%lu]\n", iocb, tail);
+			ctx = req->ki_ctx;
+			tail = kioctx_ring_lock(ctx);
+		}
+
+		tail = kioctx_ring_put(ctx, req, tail);
+		aio_put_req(req);
+	}
+
+	kioctx_ring_unlock(ctx, tail);
+	local_irq_restore(flags);
+	rcu_read_unlock();
 
 	/*
 	 * Check if the user asked us to deliver the result through an
 	 * eventfd. The eventfd_signal() function is safe to be called
 	 * from IRQ context.
 	 */
-	if (iocb->ki_eventfd != NULL)
-		eventfd_signal(iocb->ki_eventfd, 1);
+	if (eventfd) {
+		eventfd_signal(eventfd, 1);
+		eventfd_ctx_put(eventfd);
+	}
+}
+EXPORT_SYMBOL(batch_complete_aio);
+
+/* aio_complete_batch
+ *	Called when the io request on the given iocb is complete; @batch may be
+ *	NULL.
+ */
+void aio_complete_batch(struct kiocb *req, long res, long res2,
+			struct batch_complete *batch)
+{
+	req->ki_res = res;
+	req->ki_res2 = res2;
 
-put_rq:
-	/* everything turned out well, dispose of the aiocb. */
-	ret = __aio_put_req(ctx, iocb);
+	if (req->ki_list.next) {
+		struct kioctx *ctx = req->ki_ctx;
+		unsigned long flags;
+
+		spin_lock_irqsave(&ctx->ctx_lock, flags);
+		list_del(&req->ki_list);
+		spin_unlock_irqrestore(&ctx->ctx_lock, flags);
+	}
 
 	/*
-	 * We have to order our ring_info tail store above and test
-	 * of the wait list below outside the wait lock.  This is
-	 * like in wake_up_bit() where clearing a bit has to be
-	 * ordered with the unlocked test.
+	 * Special case handling for sync iocbs:
+	 *  - events go directly into the iocb for fast handling
+	 *  - the sync task with the iocb in its stack holds the single iocb
+	 *    ref, no other paths have a way to get another ref
+	 *  - the sync task helpfully left a reference to itself in the iocb
 	 */
-	smp_mb();
+	if (is_sync_kiocb(req)) {
+		BUG_ON(atomic_read(&req->ki_users) != 1);
+		req->ki_user_data = req->ki_res;
+		atomic_set(&req->ki_users, 0);
+		wake_up_process(req->ki_obj.tsk);
+	} else if (batch) {
+		int res;
+		struct kiocb *t;
+		struct rb_node **n = &batch->kiocb.rb_node, *parent = NULL;
+
+		while (*n) {
+			parent = *n;
+			t = container_of(*n, struct kiocb, ki_node);
+
+			res = req->ki_ctx != t->ki_ctx
+				? req->ki_ctx < t->ki_ctx
+				: req->ki_eventfd != t->ki_eventfd
+				? req->ki_eventfd < t->ki_eventfd
+				: req < t;
+
+			n = res ? &(*n)->rb_left : &(*n)->rb_right;
+		}
 
-	if (waitqueue_active(&ctx->wait))
-		wake_up(&ctx->wait);
+		rb_link_node(&req->ki_node, parent, n);
+		rb_insert_color(&req->ki_node, &batch->kiocb);
+	} else {
+		struct batch_complete batch_stack;
 
-	spin_unlock_irqrestore(&ctx->ctx_lock, flags);
-	return ret;
+		memset(&req->ki_node, 0, sizeof(req->ki_node));
+		batch_stack.kiocb.rb_node = &req->ki_node;
+
+		batch_complete_aio(&batch_stack);
+	}
 }
-EXPORT_SYMBOL(aio_complete);
+EXPORT_SYMBOL(aio_complete_batch);
 
-/* aio_read_evt
- *	Pull an event off of the ioctx's event ring.  Returns the number of 
- *	events fetched (0 or 1 ;-)
- *	FIXME: make this use cmpxchg.
- *	TODO: make the ringbuffer user mmap()able (requires FIXME).
+/* aio_read_events
+ *	Pull an event off of the ioctx's event ring.  Returns the number of
+ *	events fetched
  */
-static int aio_read_evt(struct kioctx *ioctx, struct io_event *ent)
+static long aio_read_events_ring(struct kioctx *ctx,
+				 struct io_event __user *event, long nr)
 {
-	struct aio_ring_info *info = &ioctx->ring_info;
 	struct aio_ring *ring;
-	unsigned long head;
-	int ret = 0;
-
-	ring = kmap_atomic(info->ring_pages[0]);
-	dprintk("in aio_read_evt h%lu t%lu m%lu\n",
-		 (unsigned long)ring->head, (unsigned long)ring->tail,
-		 (unsigned long)ring->nr);
-
-	if (ring->head == ring->tail)
-		goto out;
+	unsigned head, pos;
+	long ret = 0;
+	int copy_ret;
 
-	spin_lock(&info->ring_lock);
-
-	head = ring->head % info->nr;
-	if (head != ring->tail) {
-		struct io_event *evp = aio_ring_event(info, head);
-		*ent = *evp;
-		head = (head + 1) % info->nr;
-		smp_mb(); /* finish reading the event before updatng the head */
-		ring->head = head;
-		ret = 1;
-		put_aio_ring_event(evp);
-	}
-	spin_unlock(&info->ring_lock);
+	mutex_lock(&ctx->ring_lock);
 
-out:
+	ring = kmap_atomic(ctx->ring_pages[0]);
+	head = ring->head;
 	kunmap_atomic(ring);
-	dprintk("leaving aio_read_evt: %d  h%lu t%lu\n", ret,
-		 (unsigned long)ring->head, (unsigned long)ring->tail);
-	return ret;
-}
-
-struct aio_timeout {
-	struct timer_list	timer;
-	int			timed_out;
-	struct task_struct	*p;
-};
 
-static void timeout_func(unsigned long data)
-{
-	struct aio_timeout *to = (struct aio_timeout *)data;
+	pr_debug("h%u t%u m%u\n", head, ctx->shadow_tail, ctx->nr_events);
 
-	to->timed_out = 1;
-	wake_up_process(to->p);
-}
+	if (head == ctx->shadow_tail)
+		goto out;
 
-static inline void init_timeout(struct aio_timeout *to)
-{
-	setup_timer_on_stack(&to->timer, timeout_func, (unsigned long) to);
-	to->timed_out = 0;
-	to->p = current;
-}
+	while (ret < nr) {
+		long avail;
+		struct io_event *ev;
+		struct page *page;
 
-static inline void set_timeout(long start_jiffies, struct aio_timeout *to,
-			       const struct timespec *ts)
-{
-	to->timer.expires = start_jiffies + timespec_to_jiffies(ts);
-	if (time_after(to->timer.expires, jiffies))
-		add_timer(&to->timer);
-	else
-		to->timed_out = 1;
-}
+		avail = (head <= ctx->shadow_tail ?
+				ctx->shadow_tail : ctx->nr_events) - head;
+		if (head == ctx->shadow_tail)
+			break;
 
-static inline void clear_timeout(struct aio_timeout *to)
-{
-	del_singleshot_timer_sync(&to->timer);
-}
+		avail = min(avail, nr - ret);
+		avail = min_t(long, avail, AIO_EVENTS_PER_PAGE -
+			    ((head + AIO_EVENTS_OFFSET) % AIO_EVENTS_PER_PAGE));
 
-static int read_events(struct kioctx *ctx,
-			long min_nr, long nr,
-			struct io_event __user *event,
-			struct timespec __user *timeout)
-{
-	long			start_jiffies = jiffies;
-	struct task_struct	*tsk = current;
-	DECLARE_WAITQUEUE(wait, tsk);
-	int			ret;
-	int			i = 0;
-	struct io_event		ent;
-	struct aio_timeout	to;
-	int			retry = 0;
-
-	/* needed to zero any padding within an entry (there shouldn't be 
-	 * any, but C is fun!
-	 */
-	memset(&ent, 0, sizeof(ent));
-retry:
-	ret = 0;
-	while (likely(i < nr)) {
-		ret = aio_read_evt(ctx, &ent);
-		if (unlikely(ret <= 0))
-			break;
+		pos = head + AIO_EVENTS_OFFSET;
+		page = ctx->ring_pages[pos / AIO_EVENTS_PER_PAGE];
+		pos %= AIO_EVENTS_PER_PAGE;
 
-		dprintk("read event: %Lx %Lx %Lx %Lx\n",
-			ent.data, ent.obj, ent.res, ent.res2);
+		ev = kmap(page);
+		copy_ret = copy_to_user(event + ret, ev + pos,
+					sizeof(*ev) * avail);
+		kunmap(page);
 
-		/* Could we split the check in two? */
-		ret = -EFAULT;
-		if (unlikely(copy_to_user(event, &ent, sizeof(ent)))) {
-			dprintk("aio: lost an event due to EFAULT.\n");
-			break;
+		if (unlikely(copy_ret)) {
+			ret = -EFAULT;
+			goto out;
 		}
-		ret = 0;
 
-		/* Good, event copied to userland, update counts. */
-		event ++;
-		i ++;
+		ret += avail;
+		head += avail;
+		head %= ctx->nr_events;
 	}
 
-	if (min_nr <= i)
-		return i;
-	if (ret)
-		return ret;
-
-	/* End fast path */
-
-	/* racey check, but it gets redone */
-	if (!retry && unlikely(!list_empty(&ctx->run_list))) {
-		retry = 1;
-		aio_run_all_iocbs(ctx);
-		goto retry;
-	}
+	ring = kmap_atomic(ctx->ring_pages[0]);
+	ring->head = head;
+	kunmap_atomic(ring);
+	flush_dcache_page(ctx->ring_pages[0]);
 
-	init_timeout(&to);
-	if (timeout) {
-		struct timespec	ts;
-		ret = -EFAULT;
-		if (unlikely(copy_from_user(&ts, timeout, sizeof(ts))))
-			goto out;
+	pr_debug("%li  h%u t%u\n", ret, head, ctx->shadow_tail);
 
-		set_timeout(start_jiffies, &to, &ts);
-	}
+	put_reqs_available(ctx, ret);
+out:
+	mutex_unlock(&ctx->ring_lock);
 
-	while (likely(i < nr)) {
-		add_wait_queue_exclusive(&ctx->wait, &wait);
-		do {
-			set_task_state(tsk, TASK_INTERRUPTIBLE);
-			ret = aio_read_evt(ctx, &ent);
-			if (ret)
-				break;
-			if (min_nr <= i)
-				break;
-			if (unlikely(ctx->dead)) {
-				ret = -EINVAL;
-				break;
-			}
-			if (to.timed_out)	/* Only check after read evt */
-				break;
-			/* Try to only show up in io wait if there are ops
-			 *  in flight */
-			if (ctx->reqs_active)
-				io_schedule();
-			else
-				schedule();
-			if (signal_pending(tsk)) {
-				ret = -EINTR;
-				break;
-			}
-			/*ret = aio_read_evt(ctx, &ent);*/
-		} while (1) ;
+	return ret;
+}
 
-		set_task_state(tsk, TASK_RUNNING);
-		remove_wait_queue(&ctx->wait, &wait);
+static bool aio_read_events(struct kioctx *ctx, long min_nr, long nr,
+			    struct io_event __user *event, long *i)
+{
+	long ret = aio_read_events_ring(ctx, event + *i, nr - *i);
 
-		if (unlikely(ret <= 0))
-			break;
+	if (ret > 0)
+		*i += ret;
 
-		ret = -EFAULT;
-		if (unlikely(copy_to_user(event, &ent, sizeof(ent)))) {
-			dprintk("aio: lost an event due to EFAULT.\n");
-			break;
-		}
+	if (unlikely(percpu_ref_dead(&ctx->users)))
+		ret = -EINVAL;
 
-		/* Good, event copied to userland, update counts. */
-		event ++;
-		i ++;
-	}
+	if (!*i)
+		*i = ret;
 
-	if (timeout)
-		clear_timeout(&to);
-out:
-	destroy_timer_on_stack(&to.timer);
-	return i ? i : ret;
+	return ret < 0 || *i >= min_nr;
 }
 
-/* Take an ioctx and remove it from the list of ioctx's.  Protects 
- * against races with itself via ->dead.
- */
-static void io_destroy(struct kioctx *ioctx)
+static long read_events(struct kioctx *ctx, long min_nr, long nr,
+			struct io_event __user *event,
+			struct timespec __user *timeout)
 {
-	struct mm_struct *mm = current->mm;
-	int was_dead;
+	ktime_t until = { .tv64 = KTIME_MAX };
+	long ret = 0;
 
-	/* delete the entry from the list is someone else hasn't already */
-	spin_lock(&mm->ioctx_lock);
-	was_dead = ioctx->dead;
-	ioctx->dead = 1;
-	hlist_del_rcu(&ioctx->list);
-	spin_unlock(&mm->ioctx_lock);
+	if (timeout) {
+		struct timespec	ts;
 
-	dprintk("aio_release(%p)\n", ioctx);
-	if (likely(!was_dead))
-		put_ioctx(ioctx);	/* twice for the list */
+		if (unlikely(copy_from_user(&ts, timeout, sizeof(ts))))
+			return -EFAULT;
 
-	kill_ctx(ioctx);
+		until = timespec_to_ktime(ts);
+	}
 
 	/*
-	 * Wake up any waiters.  The setting of ctx->dead must be seen
-	 * by other CPUs at this point.  Right now, we rely on the
-	 * locking done by the above calls to ensure this consistency.
+	 * Note that aio_read_events() is being called as the conditional - i.e.
+	 * we're calling it after prepare_to_wait() has set task state to
+	 * TASK_INTERRUPTIBLE.
+	 *
+	 * But aio_read_events() can block, and if it blocks it's going to flip
+	 * the task state back to TASK_RUNNING.
+	 *
+	 * This should be ok, provided it doesn't flip the state back to
+	 * TASK_RUNNING and return 0 too much - that causes us to spin. That
+	 * will only happen if the mutex_lock() call blocks, and we then find
+	 * the ringbuffer empty. So in practice we should be ok, but it's
+	 * something to be aware of when touching this code.
 	 */
-	wake_up_all(&ioctx->wait);
+	wait_event_interruptible_hrtimeout(ctx->wait,
+			aio_read_events(ctx, min_nr, nr, event, &ret), until);
+
+	if (!ret && signal_pending(current))
+		ret = -EINTR;
+
+	return ret;
 }
 
 /* sys_io_setup:
@@ -1252,7 +1040,7 @@ SYSCALL_DEFINE2(io_setup, unsigned, nr_events, aio_context_t __user *, ctxp)
 	if (!IS_ERR(ioctx)) {
 		ret = put_user(ioctx->user_id, ctxp);
 		if (ret)
-			io_destroy(ioctx);
+			kill_ioctx(ioctx);
 		put_ioctx(ioctx);
 	}
 
@@ -1270,7 +1058,7 @@ SYSCALL_DEFINE1(io_destroy, aio_context_t, ctx)
 {
 	struct kioctx *ioctx = lookup_ioctx(ctx);
 	if (likely(NULL != ioctx)) {
-		io_destroy(ioctx);
+		kill_ioctx(ioctx);
 		put_ioctx(ioctx);
 		return 0;
 	}
@@ -1301,29 +1089,22 @@ static void aio_advance_iovec(struct kiocb *iocb, ssize_t ret)
 	BUG_ON(ret > 0 && iocb->ki_left == 0);
 }
 
-static ssize_t aio_rw_vect_retry(struct kiocb *iocb)
+typedef ssize_t (aio_rw_op)(struct kiocb *, const struct iovec *,
+			    unsigned long, loff_t);
+
+static ssize_t aio_rw_vect_retry(struct kiocb *iocb, int rw, aio_rw_op *rw_op)
 {
 	struct file *file = iocb->ki_filp;
 	struct address_space *mapping = file->f_mapping;
 	struct inode *inode = mapping->host;
-	ssize_t (*rw_op)(struct kiocb *, const struct iovec *,
-			 unsigned long, loff_t);
 	ssize_t ret = 0;
-	unsigned short opcode;
-
-	if ((iocb->ki_opcode == IOCB_CMD_PREADV) ||
-		(iocb->ki_opcode == IOCB_CMD_PREAD)) {
-		rw_op = file->f_op->aio_read;
-		opcode = IOCB_CMD_PREADV;
-	} else {
-		rw_op = file->f_op->aio_write;
-		opcode = IOCB_CMD_PWRITEV;
-	}
 
 	/* This matches the pread()/pwrite() logic */
 	if (iocb->ki_pos < 0)
 		return -EINVAL;
 
+	if (rw == WRITE)
+		file_start_write(file);
 	do {
 		ret = rw_op(iocb, &iocb->ki_iovec[iocb->ki_cur_seg],
 			    iocb->ki_nr_segs - iocb->ki_cur_seg,
@@ -1334,8 +1115,10 @@ static ssize_t aio_rw_vect_retry(struct kiocb *iocb)
 	/* retry all partial writes.  retry partial reads as long as its a
 	 * regular file. */
 	} while (ret > 0 && iocb->ki_left > 0 &&
-		 (opcode == IOCB_CMD_PWRITEV ||
+		 (rw == WRITE ||
 		  (!S_ISFIFO(inode->i_mode) && !S_ISSOCK(inode->i_mode))));
+	if (rw == WRITE)
+		file_end_write(file);
 
 	/* This means we must have transferred all that we could */
 	/* No need to retry anymore */
@@ -1344,81 +1127,49 @@ static ssize_t aio_rw_vect_retry(struct kiocb *iocb)
 
 	/* If we managed to write some out we return that, rather than
 	 * the eventual error. */
-	if (opcode == IOCB_CMD_PWRITEV
-	    && ret < 0 && ret != -EIOCBQUEUED && ret != -EIOCBRETRY
+	if (rw == WRITE
+	    && ret < 0 && ret != -EIOCBQUEUED
 	    && iocb->ki_nbytes - iocb->ki_left)
 		ret = iocb->ki_nbytes - iocb->ki_left;
 
 	return ret;
 }
 
-static ssize_t aio_fdsync(struct kiocb *iocb)
-{
-	struct file *file = iocb->ki_filp;
-	ssize_t ret = -EINVAL;
-
-	if (file->f_op->aio_fsync)
-		ret = file->f_op->aio_fsync(iocb, 1);
-	return ret;
-}
-
-static ssize_t aio_fsync(struct kiocb *iocb)
-{
-	struct file *file = iocb->ki_filp;
-	ssize_t ret = -EINVAL;
-
-	if (file->f_op->aio_fsync)
-		ret = file->f_op->aio_fsync(iocb, 0);
-	return ret;
-}
-
-static ssize_t aio_setup_vectored_rw(int type, struct kiocb *kiocb, bool compat)
+static ssize_t aio_setup_vectored_rw(int rw, struct kiocb *kiocb, bool compat)
 {
 	ssize_t ret;
 
+	kiocb->ki_nr_segs = kiocb->ki_nbytes;
+
 #ifdef CONFIG_COMPAT
 	if (compat)
-		ret = compat_rw_copy_check_uvector(type,
+		ret = compat_rw_copy_check_uvector(rw,
 				(struct compat_iovec __user *)kiocb->ki_buf,
-				kiocb->ki_nbytes, 1, &kiocb->ki_inline_vec,
+				kiocb->ki_nr_segs, 1, &kiocb->ki_inline_vec,
 				&kiocb->ki_iovec);
 	else
 #endif
-		ret = rw_copy_check_uvector(type,
+		ret = rw_copy_check_uvector(rw,
 				(struct iovec __user *)kiocb->ki_buf,
-				kiocb->ki_nbytes, 1, &kiocb->ki_inline_vec,
+				kiocb->ki_nr_segs, 1, &kiocb->ki_inline_vec,
 				&kiocb->ki_iovec);
 	if (ret < 0)
-		goto out;
-
-	ret = rw_verify_area(type, kiocb->ki_filp, &kiocb->ki_pos, ret);
-	if (ret < 0)
-		goto out;
+		return ret;
 
-	kiocb->ki_nr_segs = kiocb->ki_nbytes;
-	kiocb->ki_cur_seg = 0;
-	/* ki_nbytes/left now reflect bytes instead of segs */
+	/* ki_nbytes now reflect bytes instead of segs */
 	kiocb->ki_nbytes = ret;
-	kiocb->ki_left = ret;
-
-	ret = 0;
-out:
-	return ret;
+	return 0;
 }
 
-static ssize_t aio_setup_single_vector(int type, struct file * file, struct kiocb *kiocb)
+static ssize_t aio_setup_single_vector(int rw, struct kiocb *kiocb)
 {
-	int bytes;
-
-	bytes = rw_verify_area(type, file, &kiocb->ki_pos, kiocb->ki_left);
-	if (bytes < 0)
-		return bytes;
+	if (unlikely(!access_ok(!rw, kiocb->ki_buf, kiocb->ki_nbytes)))
+		return -EFAULT;
 
 	kiocb->ki_iovec = &kiocb->ki_inline_vec;
 	kiocb->ki_iovec->iov_base = kiocb->ki_buf;
-	kiocb->ki_iovec->iov_len = bytes;
+	kiocb->ki_iovec->iov_len = kiocb->ki_nbytes;
 	kiocb->ki_nr_segs = 1;
-	kiocb->ki_cur_seg = 0;
 	return 0;
 }
 
@@ -1427,96 +1178,95 @@ static ssize_t aio_setup_single_vector(int type, struct file * file, struct kioc
  *	Performs the initial checks and aio retry method
  *	setup for the kiocb at the time of io submission.
  */
-static ssize_t aio_setup_iocb(struct kiocb *kiocb, bool compat)
+static ssize_t aio_run_iocb(struct kiocb *req, bool compat)
 {
-	struct file *file = kiocb->ki_filp;
-	ssize_t ret = 0;
+	struct file *file = req->ki_filp;
+	ssize_t ret;
+	int rw;
+	fmode_t mode;
+	aio_rw_op *rw_op;
 
-	switch (kiocb->ki_opcode) {
+	switch (req->ki_opcode) {
 	case IOCB_CMD_PREAD:
-		ret = -EBADF;
-		if (unlikely(!(file->f_mode & FMODE_READ)))
-			break;
-		ret = -EFAULT;
-		if (unlikely(!access_ok(VERIFY_WRITE, kiocb->ki_buf,
-			kiocb->ki_left)))
-			break;
-		ret = aio_setup_single_vector(READ, file, kiocb);
-		if (ret)
-			break;
-		ret = -EINVAL;
-		if (file->f_op->aio_read)
-			kiocb->ki_retry = aio_rw_vect_retry;
-		break;
-	case IOCB_CMD_PWRITE:
-		ret = -EBADF;
-		if (unlikely(!(file->f_mode & FMODE_WRITE)))
-			break;
-		ret = -EFAULT;
-		if (unlikely(!access_ok(VERIFY_READ, kiocb->ki_buf,
-			kiocb->ki_left)))
-			break;
-		ret = aio_setup_single_vector(WRITE, file, kiocb);
-		if (ret)
-			break;
-		ret = -EINVAL;
-		if (file->f_op->aio_write)
-			kiocb->ki_retry = aio_rw_vect_retry;
-		break;
 	case IOCB_CMD_PREADV:
-		ret = -EBADF;
-		if (unlikely(!(file->f_mode & FMODE_READ)))
-			break;
-		ret = aio_setup_vectored_rw(READ, kiocb, compat);
-		if (ret)
-			break;
-		ret = -EINVAL;
-		if (file->f_op->aio_read)
-			kiocb->ki_retry = aio_rw_vect_retry;
-		break;
+		mode	= FMODE_READ;
+		rw	= READ;
+		rw_op	= file->f_op->aio_read;
+		goto rw_common;
+
+	case IOCB_CMD_PWRITE:
 	case IOCB_CMD_PWRITEV:
-		ret = -EBADF;
-		if (unlikely(!(file->f_mode & FMODE_WRITE)))
-			break;
-		ret = aio_setup_vectored_rw(WRITE, kiocb, compat);
+		mode	= FMODE_WRITE;
+		rw	= WRITE;
+		rw_op	= file->f_op->aio_write;
+		goto rw_common;
+rw_common:
+		if (unlikely(!(file->f_mode & mode)))
+			return -EBADF;
+
+		if (!rw_op)
+			return -EINVAL;
+
+		ret = (req->ki_opcode == IOCB_CMD_PREADV ||
+		       req->ki_opcode == IOCB_CMD_PWRITEV)
+			? aio_setup_vectored_rw(rw, req, compat)
+			: aio_setup_single_vector(rw, req);
 		if (ret)
-			break;
-		ret = -EINVAL;
-		if (file->f_op->aio_write)
-			kiocb->ki_retry = aio_rw_vect_retry;
+			return ret;
+
+		ret = rw_verify_area(rw, file, &req->ki_pos, req->ki_nbytes);
+		if (ret < 0)
+			return ret;
+
+		req->ki_nbytes = ret;
+		req->ki_left = ret;
+
+		ret = aio_rw_vect_retry(req, rw, rw_op);
 		break;
+
 	case IOCB_CMD_FDSYNC:
-		ret = -EINVAL;
-		if (file->f_op->aio_fsync)
-			kiocb->ki_retry = aio_fdsync;
+		if (!file->f_op->aio_fsync)
+			return -EINVAL;
+
+		ret = file->f_op->aio_fsync(req, 1);
 		break;
+
 	case IOCB_CMD_FSYNC:
-		ret = -EINVAL;
-		if (file->f_op->aio_fsync)
-			kiocb->ki_retry = aio_fsync;
+		if (!file->f_op->aio_fsync)
+			return -EINVAL;
+
+		ret = file->f_op->aio_fsync(req, 0);
 		break;
+
 	default:
-		dprintk("EINVAL: io_submit: no operation provided\n");
-		ret = -EINVAL;
+		pr_debug("EINVAL: no operation provided\n");
+		return -EINVAL;
 	}
 
-	if (!kiocb->ki_retry)
-		return ret;
+	if (ret != -EIOCBQUEUED) {
+		/*
+		 * There's no easy way to restart the syscall since other AIO's
+		 * may be already running. Just fail this IO with EINTR.
+		 */
+		if (unlikely(ret == -ERESTARTSYS || ret == -ERESTARTNOINTR ||
+			     ret == -ERESTARTNOHAND ||
+			     ret == -ERESTART_RESTARTBLOCK))
+			ret = -EINTR;
+		aio_complete(req, ret, 0);
+	}
 
 	return 0;
 }
 
 static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
-			 struct iocb *iocb, struct kiocb_batch *batch,
-			 bool compat)
+			 struct iocb *iocb, bool compat)
 {
 	struct kiocb *req;
-	struct file *file;
 	ssize_t ret;
 
 	/* enforce forwards compatibility on users */
 	if (unlikely(iocb->aio_reserved1 || iocb->aio_reserved2)) {
-		pr_debug("EINVAL: io_submit: reserve field set\n");
+		pr_debug("EINVAL: reserve field set\n");
 		return -EINVAL;
 	}
 
@@ -1530,16 +1280,16 @@ static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
 		return -EINVAL;
 	}
 
-	file = fget(iocb->aio_fildes);
-	if (unlikely(!file))
-		return -EBADF;
-
-	req = aio_get_req(ctx, batch);  /* returns with 2 references to req */
-	if (unlikely(!req)) {
-		fput(file);
+	req = aio_get_req(ctx);
+	if (unlikely(!req))
 		return -EAGAIN;
+
+	req->ki_filp = fget(iocb->aio_fildes);
+	if (unlikely(!req->ki_filp)) {
+		ret = -EBADF;
+		goto out_put_req;
 	}
-	req->ki_filp = file;
+
 	if (iocb->aio_flags & IOCB_FLAG_RESFD) {
 		/*
 		 * If the IOCB_FLAG_RESFD flag of aio_flags is set, get an
@@ -1555,9 +1305,9 @@ static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
 		}
 	}
 
-	ret = put_user(req->ki_key, &user_iocb->aio_key);
+	ret = put_user(KIOCB_KEY, &user_iocb->aio_key);
 	if (unlikely(ret)) {
-		dprintk("EFAULT: aio_key\n");
+		pr_debug("EFAULT: aio_key\n");
 		goto out_put_req;
 	}
 
@@ -1569,41 +1319,14 @@ static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
 	req->ki_left = req->ki_nbytes = iocb->aio_nbytes;
 	req->ki_opcode = iocb->aio_lio_opcode;
 
-	ret = aio_setup_iocb(req, compat);
-
+	ret = aio_run_iocb(req, compat);
 	if (ret)
 		goto out_put_req;
 
-	spin_lock_irq(&ctx->ctx_lock);
-	/*
-	 * We could have raced with io_destroy() and are currently holding a
-	 * reference to ctx which should be destroyed. We cannot submit IO
-	 * since ctx gets freed as soon as io_submit() puts its reference.  The
-	 * check here is reliable: io_destroy() sets ctx->dead before waiting
-	 * for outstanding IO and the barrier between these two is realized by
-	 * unlock of mm->ioctx_lock and lock of ctx->ctx_lock.  Analogously we
-	 * increment ctx->reqs_active before checking for ctx->dead and the
-	 * barrier is realized by unlock and lock of ctx->ctx_lock. Thus if we
-	 * don't see ctx->dead set here, io_destroy() waits for our IO to
-	 * finish.
-	 */
-	if (ctx->dead) {
-		spin_unlock_irq(&ctx->ctx_lock);
-		ret = -EINVAL;
-		goto out_put_req;
-	}
-	aio_run_iocb(req);
-	if (!list_empty(&ctx->run_list)) {
-		/* drain the run list */
-		while (__aio_run_iocbs(ctx))
-			;
-	}
-	spin_unlock_irq(&ctx->ctx_lock);
-
 	aio_put_req(req);	/* drop extra ref to req */
 	return 0;
-
 out_put_req:
+	put_reqs_available(ctx, 1);
 	aio_put_req(req);	/* drop extra ref to req */
 	aio_put_req(req);	/* drop i/o ref to req */
 	return ret;
@@ -1616,7 +1339,6 @@ long do_io_submit(aio_context_t ctx_id, long nr,
 	long ret = 0;
 	int i = 0;
 	struct blk_plug plug;
-	struct kiocb_batch batch;
 
 	if (unlikely(nr < 0))
 		return -EINVAL;
@@ -1629,12 +1351,10 @@ long do_io_submit(aio_context_t ctx_id, long nr,
 
 	ctx = lookup_ioctx(ctx_id);
 	if (unlikely(!ctx)) {
-		pr_debug("EINVAL: io_submit: invalid context id\n");
+		pr_debug("EINVAL: invalid context id\n");
 		return -EINVAL;
 	}
 
-	kiocb_batch_init(&batch, nr);
-
 	blk_start_plug(&plug);
 
 	/*
@@ -1655,13 +1375,12 @@ long do_io_submit(aio_context_t ctx_id, long nr,
 			break;
 		}
 
-		ret = io_submit_one(ctx, user_iocb, &tmp, &batch, compat);
+		ret = io_submit_one(ctx, user_iocb, &tmp, compat);
 		if (ret)
 			break;
 	}
 	blk_finish_plug(&plug);
 
-	kiocb_batch_free(ctx, &batch);
 	put_ioctx(ctx);
 	return i ? i : ret;
 }
@@ -1694,10 +1413,13 @@ static struct kiocb *lookup_kiocb(struct kioctx *ctx, struct iocb __user *iocb,
 
 	assert_spin_locked(&ctx->ctx_lock);
 
+	if (key != KIOCB_KEY)
+		return NULL;
+
 	/* TODO: use a hash or array, this sucks. */
 	list_for_each(pos, &ctx->active_reqs) {
 		struct kiocb *kiocb = list_kiocb(pos);
-		if (kiocb->ki_obj.user == iocb && kiocb->ki_key == key)
+		if (kiocb->ki_obj.user == iocb)
 			return kiocb;
 	}
 	return NULL;
@@ -1716,7 +1438,7 @@ static struct kiocb *lookup_kiocb(struct kioctx *ctx, struct iocb __user *iocb,
 SYSCALL_DEFINE3(io_cancel, aio_context_t, ctx_id, struct iocb __user *, iocb,
 		struct io_event __user *, result)
 {
-	int (*cancel)(struct kiocb *iocb, struct io_event *res);
+	struct io_event res;
 	struct kioctx *ctx;
 	struct kiocb *kiocb;
 	u32 key;
@@ -1731,32 +1453,22 @@ SYSCALL_DEFINE3(io_cancel, aio_context_t, ctx_id, struct iocb __user *, iocb,
 		return -EINVAL;
 
 	spin_lock_irq(&ctx->ctx_lock);
-	ret = -EAGAIN;
+
 	kiocb = lookup_kiocb(ctx, iocb, key);
-	if (kiocb && kiocb->ki_cancel) {
-		cancel = kiocb->ki_cancel;
-		kiocb->ki_users ++;
-		kiocbSetCancelled(kiocb);
-	} else
-		cancel = NULL;
+	if (kiocb)
+		ret = kiocb_cancel(ctx, kiocb, &res);
+	else
+		ret = -EINVAL;
+
 	spin_unlock_irq(&ctx->ctx_lock);
 
-	if (NULL != cancel) {
-		struct io_event tmp;
-		pr_debug("calling cancel\n");
-		memset(&tmp, 0, sizeof(tmp));
-		tmp.obj = (u64)(unsigned long)kiocb->ki_obj.user;
-		tmp.data = kiocb->ki_user_data;
-		ret = cancel(kiocb, &tmp);
-		if (!ret) {
-			/* Cancellation succeeded -- copy the result
-			 * into the user's buffer.
-			 */
-			if (copy_to_user(result, &tmp, sizeof(tmp)))
-				ret = -EFAULT;
-		}
-	} else
-		ret = -EINVAL;
+	if (!ret) {
+		/* Cancellation succeeded -- copy the result
+		 * into the user's buffer.
+		 */
+		if (copy_to_user(result, &res, sizeof(res)))
+			ret = -EFAULT;
+	}
 
 	put_ioctx(ctx);
 
@@ -1790,7 +1502,5 @@ SYSCALL_DEFINE5(io_getevents, aio_context_t, ctx_id,
 			ret = read_events(ioctx, min_nr, nr, events, timeout);
 		put_ioctx(ioctx);
 	}
-
-	asmlinkage_protect(5, ret, ctx_id, min_nr, nr, events, timeout);
 	return ret;
 }
diff --git a/fs/befs/btree.c b/fs/befs/btree.c
index a66c9b1..74e397d 100644
--- a/fs/befs/btree.c
+++ b/fs/befs/btree.c
@@ -436,8 +436,7 @@ befs_btree_read(struct super_block *sb, befs_data_stream * ds,
 		goto error;
 	}
 
-	if ((this_node = (befs_btree_node *)
-	     kmalloc(sizeof (befs_btree_node), GFP_NOFS)) == NULL) {
+	if ((this_node = kmalloc(sizeof (befs_btree_node), GFP_NOFS)) == NULL) {
 		befs_error(sb, "befs_btree_read() failed to allocate %u "
 			   "bytes of memory", sizeof (befs_btree_node));
 		goto error;
diff --git a/fs/binfmt_aout.c b/fs/binfmt_aout.c
index bbc8f88..14b7ea3 100644
--- a/fs/binfmt_aout.c
+++ b/fs/binfmt_aout.c
@@ -62,7 +62,6 @@ static int aout_core_dump(struct coredump_params *cprm)
 	fs = get_fs();
 	set_fs(KERNEL_DS);
 	has_dumped = 1;
-	current->flags |= PF_DUMPCORE;
        	strncpy(dump.u_comm, current->comm, sizeof(dump.u_comm));
 	dump.u_ar0 = offsetof(struct user, regs);
 	dump.signal = cprm->siginfo->si_signo;
@@ -256,8 +255,6 @@ static int load_aout_binary(struct linux_binprm * bprm)
 		(current->mm->start_data = N_DATADDR(ex));
 	current->mm->brk = ex.a_bss +
 		(current->mm->start_brk = N_BSSADDR(ex));
-	current->mm->free_area_cache = current->mm->mmap_base;
-	current->mm->cached_hole_size = 0;
 
 	retval = setup_arg_pages(bprm, STACK_TOP, EXSTACK_DEFAULT);
 	if (retval < 0) {
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 3939829..ced3dcf 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -140,6 +140,25 @@ static int padzero(unsigned long elf_bss)
 #define ELF_BASE_PLATFORM NULL
 #endif
 
+/*
+ * Use get_random_int() to implement AT_RANDOM while avoiding depletion
+ * of the entropy pool.
+ */
+static void get_atrandom_bytes(unsigned char *buf, size_t nbytes)
+{
+	unsigned char *p = buf;
+
+	while (nbytes) {
+		unsigned int random_variable;
+		size_t chunk = min(nbytes, sizeof(random_variable));
+
+		random_variable = get_random_int();
+		memcpy(p, &random_variable, chunk);
+		p += chunk;
+		nbytes -= chunk;
+	}
+}
+
 static int
 create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec,
 		unsigned long load_addr, unsigned long interp_load_addr)
@@ -201,7 +220,7 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec,
 	/*
 	 * Generate 16 random bytes for userspace PRNG seeding.
 	 */
-	get_random_bytes(k_rand_bytes, sizeof(k_rand_bytes));
+	get_atrandom_bytes(k_rand_bytes, sizeof(k_rand_bytes));
 	u_rand_bytes = (elf_addr_t __user *)
 		       STACK_ALLOC(p, sizeof(k_rand_bytes));
 	if (__copy_to_user(u_rand_bytes, k_rand_bytes, sizeof(k_rand_bytes)))
@@ -735,8 +754,6 @@ static int load_elf_binary(struct linux_binprm *bprm)
 
 	/* Do this so that we can load the interpreter, if need be.  We will
 	   change some of these later */
-	current->mm->free_area_cache = current->mm->mmap_base;
-	current->mm->cached_hole_size = 0;
 	retval = setup_arg_pages(bprm, randomize_stack_top(STACK_TOP),
 				 executable_stack);
 	if (retval < 0) {
@@ -2090,8 +2107,7 @@ static int elf_core_dump(struct coredump_params *cprm)
 		goto cleanup;
 
 	has_dumped = 1;
-	current->flags |= PF_DUMPCORE;
-  
+
 	fs = get_fs();
 	set_fs(KERNEL_DS);
 
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
index 9c13e02..c1cc06a 100644
--- a/fs/binfmt_elf_fdpic.c
+++ b/fs/binfmt_elf_fdpic.c
@@ -1687,8 +1687,6 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
 	fill_elf_fdpic_header(elf, e_phnum);
 
 	has_dumped = 1;
-	current->flags |= PF_DUMPCORE;
-
 	/*
 	 * Set up the notes in similar form to SVR4 core dumps made
 	 * with info from their /proc.
diff --git a/fs/bio-integrity.c b/fs/bio-integrity.c
index a3f28f3..69f6f80 100644
--- a/fs/bio-integrity.c
+++ b/fs/bio-integrity.c
@@ -27,48 +27,11 @@
 #include <linux/workqueue.h>
 #include <linux/slab.h>
 
-struct integrity_slab {
-	struct kmem_cache *slab;
-	unsigned short nr_vecs;
-	char name[8];
-};
-
-#define IS(x) { .nr_vecs = x, .name = "bip-"__stringify(x) }
-struct integrity_slab bip_slab[BIOVEC_NR_POOLS] __read_mostly = {
-	IS(1), IS(4), IS(16), IS(64), IS(128), IS(BIO_MAX_PAGES),
-};
-#undef IS
+#define BIP_INLINE_VECS	4
 
+static struct kmem_cache *bip_slab;
 static struct workqueue_struct *kintegrityd_wq;
 
-static inline unsigned int vecs_to_idx(unsigned int nr)
-{
-	switch (nr) {
-	case 1:
-		return 0;
-	case 2 ... 4:
-		return 1;
-	case 5 ... 16:
-		return 2;
-	case 17 ... 64:
-		return 3;
-	case 65 ... 128:
-		return 4;
-	case 129 ... BIO_MAX_PAGES:
-		return 5;
-	default:
-		BUG();
-	}
-}
-
-static inline int use_bip_pool(unsigned int idx)
-{
-	if (idx == BIOVEC_MAX_IDX)
-		return 1;
-
-	return 0;
-}
-
 /**
  * bio_integrity_alloc - Allocate integrity payload and attach it to bio
  * @bio:	bio to attach integrity metadata to
@@ -84,37 +47,41 @@ struct bio_integrity_payload *bio_integrity_alloc(struct bio *bio,
 						  unsigned int nr_vecs)
 {
 	struct bio_integrity_payload *bip;
-	unsigned int idx = vecs_to_idx(nr_vecs);
 	struct bio_set *bs = bio->bi_pool;
-
-	if (!bs)
-		bs = fs_bio_set;
-
-	BUG_ON(bio == NULL);
-	bip = NULL;
-
-	/* Lower order allocations come straight from slab */
-	if (!use_bip_pool(idx))
-		bip = kmem_cache_alloc(bip_slab[idx].slab, gfp_mask);
-
-	/* Use mempool if lower order alloc failed or max vecs were requested */
-	if (bip == NULL) {
-		idx = BIOVEC_MAX_IDX;  /* so we free the payload properly later */
+	unsigned long idx = BIO_POOL_NONE;
+	unsigned inline_vecs;
+
+	if (!bs) {
+		bip = kmalloc(sizeof(struct bio_integrity_payload) +
+			      sizeof(struct bio_vec) * nr_vecs, gfp_mask);
+		inline_vecs = nr_vecs;
+	} else {
 		bip = mempool_alloc(bs->bio_integrity_pool, gfp_mask);
-
-		if (unlikely(bip == NULL)) {
-			printk(KERN_ERR "%s: could not alloc bip\n", __func__);
-			return NULL;
-		}
+		inline_vecs = BIP_INLINE_VECS;
 	}
 
+	if (unlikely(!bip))
+		return NULL;
+
 	memset(bip, 0, sizeof(*bip));
 
+	if (nr_vecs > inline_vecs) {
+		bip->bip_vec = bvec_alloc(gfp_mask, nr_vecs, &idx,
+					  bs->bvec_integrity_pool);
+		if (!bip->bip_vec)
+			goto err;
+	} else {
+		bip->bip_vec = bip->bip_inline_vecs;
+	}
+
 	bip->bip_slab = idx;
 	bip->bip_bio = bio;
 	bio->bi_integrity = bip;
 
 	return bip;
+err:
+	mempool_free(bip, bs->bio_integrity_pool);
+	return NULL;
 }
 EXPORT_SYMBOL(bio_integrity_alloc);
 
@@ -130,20 +97,18 @@ void bio_integrity_free(struct bio *bio)
 	struct bio_integrity_payload *bip = bio->bi_integrity;
 	struct bio_set *bs = bio->bi_pool;
 
-	if (!bs)
-		bs = fs_bio_set;
-
-	BUG_ON(bip == NULL);
-
-	/* A cloned bio doesn't own the integrity metadata */
-	if (!bio_flagged(bio, BIO_CLONED) && !bio_flagged(bio, BIO_FS_INTEGRITY)
-	    && bip->bip_buf != NULL)
+	if (bip->bip_owns_buf)
 		kfree(bip->bip_buf);
 
-	if (use_bip_pool(bip->bip_slab))
+	if (bs) {
+		if (bip->bip_slab != BIO_POOL_NONE)
+			bvec_free(bs->bvec_integrity_pool, bip->bip_vec,
+				  bip->bip_slab);
+
 		mempool_free(bip, bs->bio_integrity_pool);
-	else
-		kmem_cache_free(bip_slab[bip->bip_slab].slab, bip);
+	} else {
+		kfree(bip);
+	}
 
 	bio->bi_integrity = NULL;
 }
@@ -419,6 +384,7 @@ int bio_integrity_prep(struct bio *bio)
 		return -EIO;
 	}
 
+	bip->bip_owns_buf = 1;
 	bip->bip_buf = buf;
 	bip->bip_size = len;
 	bip->bip_sector = bio->bi_sector;
@@ -544,7 +510,8 @@ static void bio_integrity_verify_fn(struct work_struct *work)
  * in process context.	This function postpones completion
  * accordingly.
  */
-void bio_integrity_endio(struct bio *bio, int error)
+void bio_integrity_endio(struct bio *bio, int error,
+			 struct batch_complete *batch)
 {
 	struct bio_integrity_payload *bip = bio->bi_integrity;
 
@@ -694,11 +661,11 @@ void bio_integrity_split(struct bio *bio, struct bio_pair *bp, int sectors)
 	bp->bio1.bi_integrity = &bp->bip1;
 	bp->bio2.bi_integrity = &bp->bip2;
 
-	bp->iv1 = bip->bip_vec[0];
-	bp->iv2 = bip->bip_vec[0];
+	bp->iv1 = bip->bip_vec[bip->bip_idx];
+	bp->iv2 = bip->bip_vec[bip->bip_idx];
 
-	bp->bip1.bip_vec[0] = bp->iv1;
-	bp->bip2.bip_vec[0] = bp->iv2;
+	bp->bip1.bip_vec = &bp->iv1;
+	bp->bip2.bip_vec = &bp->iv2;
 
 	bp->iv1.bv_len = sectors * bi->tuple_size;
 	bp->iv2.bv_offset += sectors * bi->tuple_size;
@@ -746,13 +713,14 @@ EXPORT_SYMBOL(bio_integrity_clone);
 
 int bioset_integrity_create(struct bio_set *bs, int pool_size)
 {
-	unsigned int max_slab = vecs_to_idx(BIO_MAX_PAGES);
-
 	if (bs->bio_integrity_pool)
 		return 0;
 
-	bs->bio_integrity_pool =
-		mempool_create_slab_pool(pool_size, bip_slab[max_slab].slab);
+	bs->bio_integrity_pool = mempool_create_slab_pool(pool_size, bip_slab);
+
+	bs->bvec_integrity_pool = biovec_create_pool(bs, pool_size);
+	if (!bs->bvec_integrity_pool)
+		return -1;
 
 	if (!bs->bio_integrity_pool)
 		return -1;
@@ -765,13 +733,14 @@ void bioset_integrity_free(struct bio_set *bs)
 {
 	if (bs->bio_integrity_pool)
 		mempool_destroy(bs->bio_integrity_pool);
+
+	if (bs->bvec_integrity_pool)
+		mempool_destroy(bs->bio_integrity_pool);
 }
 EXPORT_SYMBOL(bioset_integrity_free);
 
 void __init bio_integrity_init(void)
 {
-	unsigned int i;
-
 	/*
 	 * kintegrityd won't block much but may burn a lot of CPU cycles.
 	 * Make it highpri CPU intensive wq with max concurrency of 1.
@@ -781,14 +750,10 @@ void __init bio_integrity_init(void)
 	if (!kintegrityd_wq)
 		panic("Failed to create kintegrityd\n");
 
-	for (i = 0 ; i < BIOVEC_NR_POOLS ; i++) {
-		unsigned int size;
-
-		size = sizeof(struct bio_integrity_payload)
-			+ bip_slab[i].nr_vecs * sizeof(struct bio_vec);
-
-		bip_slab[i].slab =
-			kmem_cache_create(bip_slab[i].name, size, 0,
-					  SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);
-	}
+	bip_slab = kmem_cache_create("bio_integrity_payload",
+				     sizeof(struct bio_integrity_payload) +
+				     sizeof(struct bio_vec) * BIP_INLINE_VECS,
+				     0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);
+	if (!bip_slab)
+		panic("Failed to create slab\n");
 }
diff --git a/fs/bio.c b/fs/bio.c
index bb5768f..a8081ae 100644
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -19,6 +19,7 @@
 #include <linux/swap.h>
 #include <linux/bio.h>
 #include <linux/blkdev.h>
+#include <linux/uio.h>
 #include <linux/iocontext.h>
 #include <linux/slab.h>
 #include <linux/init.h>
@@ -27,6 +28,7 @@
 #include <linux/mempool.h>
 #include <linux/workqueue.h>
 #include <linux/cgroup.h>
+#include <linux/aio.h>
 #include <scsi/sg.h>		/* for struct sg_iovec */
 
 #include <trace/events/block.h>
@@ -160,12 +162,12 @@ unsigned int bvec_nr_vecs(unsigned short idx)
 	return bvec_slabs[idx].nr_vecs;
 }
 
-void bvec_free_bs(struct bio_set *bs, struct bio_vec *bv, unsigned int idx)
+void bvec_free(mempool_t *pool, struct bio_vec *bv, unsigned int idx)
 {
 	BIO_BUG_ON(idx >= BIOVEC_NR_POOLS);
 
 	if (idx == BIOVEC_MAX_IDX)
-		mempool_free(bv, bs->bvec_pool);
+		mempool_free(bv, pool);
 	else {
 		struct biovec_slab *bvs = bvec_slabs + idx;
 
@@ -173,8 +175,8 @@ void bvec_free_bs(struct bio_set *bs, struct bio_vec *bv, unsigned int idx)
 	}
 }
 
-struct bio_vec *bvec_alloc_bs(gfp_t gfp_mask, int nr, unsigned long *idx,
-			      struct bio_set *bs)
+struct bio_vec *bvec_alloc(gfp_t gfp_mask, int nr, unsigned long *idx,
+			   mempool_t *pool)
 {
 	struct bio_vec *bvl;
 
@@ -210,7 +212,7 @@ struct bio_vec *bvec_alloc_bs(gfp_t gfp_mask, int nr, unsigned long *idx,
 	 */
 	if (*idx == BIOVEC_MAX_IDX) {
 fallback:
-		bvl = mempool_alloc(bs->bvec_pool, gfp_mask);
+		bvl = mempool_alloc(pool, gfp_mask);
 	} else {
 		struct biovec_slab *bvs = bvec_slabs + *idx;
 		gfp_t __gfp_mask = gfp_mask & ~(__GFP_WAIT | __GFP_IO);
@@ -252,8 +254,8 @@ static void bio_free(struct bio *bio)
 	__bio_free(bio);
 
 	if (bs) {
-		if (bio_has_allocated_vec(bio))
-			bvec_free_bs(bs, bio->bi_io_vec, BIO_POOL_IDX(bio));
+		if (bio_flagged(bio, BIO_OWNS_VEC))
+			bvec_free(bs->bvec_pool, bio->bi_io_vec, BIO_POOL_IDX(bio));
 
 		/*
 		 * If we have front padding, adjust the bio pointer before freeing
@@ -297,6 +299,54 @@ void bio_reset(struct bio *bio)
 }
 EXPORT_SYMBOL(bio_reset);
 
+static void bio_alloc_rescue(struct work_struct *work)
+{
+	struct bio_set *bs = container_of(work, struct bio_set, rescue_work);
+	struct bio *bio;
+
+	while (1) {
+		spin_lock(&bs->rescue_lock);
+		bio = bio_list_pop(&bs->rescue_list);
+		spin_unlock(&bs->rescue_lock);
+
+		if (!bio)
+			break;
+
+		generic_make_request(bio);
+	}
+}
+
+static void punt_bios_to_rescuer(struct bio_set *bs)
+{
+	struct bio_list punt, nopunt;
+	struct bio *bio;
+
+	/*
+	 * In order to guarantee forward progress we must punt only bios that
+	 * were allocated from this bio_set; otherwise, if there was a bio on
+	 * there for a stacking driver higher up in the stack, processing it
+	 * could require allocating bios from this bio_set, and doing that from
+	 * our own rescuer would be bad.
+	 *
+	 * Since bio lists are singly linked, pop them all instead of trying to
+	 * remove from the middle of the list:
+	 */
+
+	bio_list_init(&punt);
+	bio_list_init(&nopunt);
+
+	while ((bio = bio_list_pop(current->bio_list)))
+		bio_list_add(bio->bi_pool == bs ? &punt : &nopunt, bio);
+
+	*current->bio_list = nopunt;
+
+	spin_lock(&bs->rescue_lock);
+	bio_list_merge(&bs->rescue_list, &punt);
+	spin_unlock(&bs->rescue_lock);
+
+	queue_work(bs->rescue_workqueue, &bs->rescue_work);
+}
+
 /**
  * bio_alloc_bioset - allocate a bio for I/O
  * @gfp_mask:   the GFP_ mask given to the slab allocator
@@ -314,11 +364,27 @@ EXPORT_SYMBOL(bio_reset);
  *   previously allocated bio for IO before attempting to allocate a new one.
  *   Failure to do so can cause deadlocks under memory pressure.
  *
+ *   Note that when running under generic_make_request() (i.e. any block
+ *   driver), bios are not submitted until after you return - see the code in
+ *   generic_make_request() that converts recursion into iteration, to prevent
+ *   stack overflows.
+ *
+ *   This would normally mean allocating multiple bios under
+ *   generic_make_request() would be susceptible to deadlocks, but we have
+ *   deadlock avoidance code that resubmits any blocked bios from a rescuer
+ *   thread.
+ *
+ *   However, we do not guarantee forward progress for allocations from other
+ *   mempools. Doing multiple allocations from the same mempool under
+ *   generic_make_request() should be avoided - instead, use bio_set's front_pad
+ *   for per bio allocations.
+ *
  *   RETURNS:
  *   Pointer to new bio on success, NULL on failure.
  */
 struct bio *bio_alloc_bioset(gfp_t gfp_mask, int nr_iovecs, struct bio_set *bs)
 {
+	gfp_t saved_gfp = gfp_mask;
 	unsigned front_pad;
 	unsigned inline_vecs;
 	unsigned long idx = BIO_POOL_NONE;
@@ -336,7 +402,37 @@ struct bio *bio_alloc_bioset(gfp_t gfp_mask, int nr_iovecs, struct bio_set *bs)
 		front_pad = 0;
 		inline_vecs = nr_iovecs;
 	} else {
+		/*
+		 * generic_make_request() converts recursion to iteration; this
+		 * means if we're running beneath it, any bios we allocate and
+		 * submit will not be submitted (and thus freed) until after we
+		 * return.
+		 *
+		 * This exposes us to a potential deadlock if we allocate
+		 * multiple bios from the same bio_set() while running
+		 * underneath generic_make_request(). If we were to allocate
+		 * multiple bios (say a stacking block driver that was splitting
+		 * bios), we would deadlock if we exhausted the mempool's
+		 * reserve.
+		 *
+		 * We solve this, and guarantee forward progress, with a rescuer
+		 * workqueue per bio_set. If we go to allocate and there are
+		 * bios on current->bio_list, we first try the allocation
+		 * without __GFP_WAIT; if that fails, we punt those bios we
+		 * would be blocking to the rescuer workqueue before we retry
+		 * with the original gfp_flags.
+		 */
+
+		if (current->bio_list && !bio_list_empty(current->bio_list))
+			gfp_mask &= ~__GFP_WAIT;
+
 		p = mempool_alloc(bs->bio_pool, gfp_mask);
+		if (!p && gfp_mask != saved_gfp) {
+			punt_bios_to_rescuer(bs);
+			gfp_mask = saved_gfp;
+			p = mempool_alloc(bs->bio_pool, gfp_mask);
+		}
+
 		front_pad = bs->front_pad;
 		inline_vecs = BIO_INLINE_VECS;
 	}
@@ -348,9 +444,17 @@ struct bio *bio_alloc_bioset(gfp_t gfp_mask, int nr_iovecs, struct bio_set *bs)
 	bio_init(bio);
 
 	if (nr_iovecs > inline_vecs) {
-		bvl = bvec_alloc_bs(gfp_mask, nr_iovecs, &idx, bs);
+		bvl = bvec_alloc(gfp_mask, nr_iovecs, &idx, bs->bvec_pool);
+		if (!bvl && gfp_mask != saved_gfp) {
+			punt_bios_to_rescuer(bs);
+			gfp_mask = saved_gfp;
+			bvl = bvec_alloc(gfp_mask, nr_iovecs, &idx, bs->bvec_pool);
+		}
+
 		if (unlikely(!bvl))
 			goto err_free;
+
+		bio->bi_flags |= 1 << BIO_OWNS_VEC;
 	} else if (nr_iovecs) {
 		bvl = bio->bi_inline_vecs;
 	}
@@ -652,6 +756,182 @@ int bio_add_page(struct bio *bio, struct page *page, unsigned int len,
 }
 EXPORT_SYMBOL(bio_add_page);
 
+struct submit_bio_ret {
+	struct completion event;
+	int error;
+};
+
+static void submit_bio_wait_endio(struct bio *bio, int error,
+				  struct batch_complete *batch)
+{
+	struct submit_bio_ret *ret = bio->bi_private;
+
+	ret->error = error;
+	complete(&ret->event);
+}
+
+/**
+ * submit_bio_wait - submit a bio, and wait until it completes
+ * @rw: whether to %READ or %WRITE, or maybe to %READA (read ahead)
+ * @bio: The &struct bio which describes the I/O
+ *
+ * Simple wrapper around submit_bio(). Returns 0 on success, or the error from
+ * bio_endio() on failure.
+ */
+int submit_bio_wait(int rw, struct bio *bio)
+{
+	struct submit_bio_ret ret;
+
+	rw |= REQ_SYNC;
+	init_completion(&ret.event);
+	bio->bi_private = &ret;
+	bio->bi_end_io = submit_bio_wait_endio;
+	submit_bio(rw, bio);
+	wait_for_completion(&ret.event);
+
+	return ret.error;
+}
+EXPORT_SYMBOL(submit_bio_wait);
+
+/**
+ * bio_advance - increment/complete a bio by some number of bytes
+ * @bio:	bio to advance
+ * @bytes:	number of bytes to complete
+ *
+ * This updates bi_sector, bi_size and bi_idx; if the number of bytes to
+ * complete doesn't align with a bvec boundary, then bv_len and bv_offset will
+ * be updated on the last bvec as well.
+ *
+ * @bio will then represent the remaining, uncompleted portion of the io.
+ */
+void bio_advance(struct bio *bio, unsigned bytes)
+{
+	if (bio_integrity(bio))
+		bio_integrity_advance(bio, bytes);
+
+	bio->bi_sector += bytes >> 9;
+	bio->bi_size -= bytes;
+
+	if (bio->bi_rw & BIO_NO_ADVANCE_ITER_MASK)
+		return;
+
+	while (bytes) {
+		if (unlikely(bio->bi_idx >= bio->bi_vcnt)) {
+			WARN_ONCE(1, "bio idx %d >= vcnt %d\n",
+				  bio->bi_idx, bio->bi_vcnt);
+			break;
+		}
+
+		if (bytes >= bio_iovec(bio)->bv_len) {
+			bytes -= bio_iovec(bio)->bv_len;
+			bio->bi_idx++;
+		} else {
+			bio_iovec(bio)->bv_len -= bytes;
+			bio_iovec(bio)->bv_offset += bytes;
+			bytes = 0;
+		}
+	}
+}
+EXPORT_SYMBOL(bio_advance);
+
+/**
+ * bio_alloc_pages - allocates a single page for each bvec in a bio
+ * @bio: bio to allocate pages for
+ * @gfp_mask: flags for allocation
+ *
+ * Allocates pages up to @bio->bi_vcnt.
+ *
+ * Returns 0 on success, -ENOMEM on failure. On failure, any allocated pages are
+ * freed.
+ */
+int bio_alloc_pages(struct bio *bio, gfp_t gfp_mask)
+{
+	int i;
+	struct bio_vec *bv;
+
+	bio_for_each_segment_all(bv, bio, i) {
+		bv->bv_page = alloc_page(gfp_mask);
+		if (!bv->bv_page) {
+			while (--bv >= bio->bi_io_vec)
+				__free_page(bv->bv_page);
+			return -ENOMEM;
+		}
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(bio_alloc_pages);
+
+/**
+ * bio_copy_data - copy contents of data buffers from one chain of bios to
+ * another
+ * @src: source bio list
+ * @dst: destination bio list
+ *
+ * If @src and @dst are single bios, bi_next must be NULL - otherwise, treats
+ * @src and @dst as linked lists of bios.
+ *
+ * Stops when it reaches the end of either @src or @dst - that is, copies
+ * min(src->bi_size, dst->bi_size) bytes (or the equivalent for lists of bios).
+ */
+void bio_copy_data(struct bio *dst, struct bio *src)
+{
+	struct bio_vec *src_bv, *dst_bv;
+	unsigned src_offset, dst_offset, bytes;
+	void *src_p, *dst_p;
+
+	src_bv = bio_iovec(src);
+	dst_bv = bio_iovec(dst);
+
+	src_offset = src_bv->bv_offset;
+	dst_offset = dst_bv->bv_offset;
+
+	while (1) {
+		if (src_offset == src_bv->bv_offset + src_bv->bv_len) {
+			src_bv++;
+			if (src_bv == bio_iovec_idx(src, src->bi_vcnt)) {
+				src = src->bi_next;
+				if (!src)
+					break;
+
+				src_bv = bio_iovec(src);
+			}
+
+			src_offset = src_bv->bv_offset;
+		}
+
+		if (dst_offset == dst_bv->bv_offset + dst_bv->bv_len) {
+			dst_bv++;
+			if (dst_bv == bio_iovec_idx(dst, dst->bi_vcnt)) {
+				dst = dst->bi_next;
+				if (!dst)
+					break;
+
+				dst_bv = bio_iovec(dst);
+			}
+
+			dst_offset = dst_bv->bv_offset;
+		}
+
+		bytes = min(dst_bv->bv_offset + dst_bv->bv_len - dst_offset,
+			    src_bv->bv_offset + src_bv->bv_len - src_offset);
+
+		src_p = kmap_atomic(src_bv->bv_page);
+		dst_p = kmap_atomic(dst_bv->bv_page);
+
+		memcpy(dst_p + dst_bv->bv_offset,
+		       src_p + src_bv->bv_offset,
+		       bytes);
+
+		kunmap_atomic(dst_p);
+		kunmap_atomic(src_p);
+
+		src_offset += bytes;
+		dst_offset += bytes;
+	}
+}
+EXPORT_SYMBOL(bio_copy_data);
+
 struct bio_map_data {
 	struct bio_vec *iovecs;
 	struct sg_iovec *sgvecs;
@@ -714,7 +994,7 @@ static int __bio_copy_iov(struct bio *bio, struct bio_vec *iovecs,
 	int iov_idx = 0;
 	unsigned int iov_off = 0;
 
-	__bio_for_each_segment(bvec, bio, i, 0) {
+	bio_for_each_segment_all(bvec, bio, i) {
 		char *bv_addr = page_address(bvec->bv_page);
 		unsigned int bv_len = iovecs[i].bv_len;
 
@@ -896,7 +1176,7 @@ struct bio *bio_copy_user_iov(struct request_queue *q,
 	return bio;
 cleanup:
 	if (!map_data)
-		bio_for_each_segment(bvec, bio, i)
+		bio_for_each_segment_all(bvec, bio, i)
 			__free_page(bvec->bv_page);
 
 	bio_put(bio);
@@ -1110,7 +1390,7 @@ static void __bio_unmap_user(struct bio *bio)
 	/*
 	 * make sure we dirty pages we wrote to
 	 */
-	__bio_for_each_segment(bvec, bio, i, 0) {
+	bio_for_each_segment_all(bvec, bio, i) {
 		if (bio_data_dir(bio) == READ)
 			set_page_dirty_lock(bvec->bv_page);
 
@@ -1136,7 +1416,8 @@ void bio_unmap_user(struct bio *bio)
 }
 EXPORT_SYMBOL(bio_unmap_user);
 
-static void bio_map_kern_endio(struct bio *bio, int err)
+static void bio_map_kern_endio(struct bio *bio, int err,
+			       struct batch_complete *batch)
 {
 	bio_put(bio);
 }
@@ -1208,7 +1489,8 @@ struct bio *bio_map_kern(struct request_queue *q, void *data, unsigned int len,
 }
 EXPORT_SYMBOL(bio_map_kern);
 
-static void bio_copy_kern_endio(struct bio *bio, int err)
+static void bio_copy_kern_endio(struct bio *bio, int err,
+				struct batch_complete *batch)
 {
 	struct bio_vec *bvec;
 	const int read = bio_data_dir(bio) == READ;
@@ -1216,7 +1498,7 @@ static void bio_copy_kern_endio(struct bio *bio, int err)
 	int i;
 	char *p = bmd->sgvecs[0].iov_base;
 
-	__bio_for_each_segment(bvec, bio, i, 0) {
+	bio_for_each_segment_all(bvec, bio, i) {
 		char *addr = page_address(bvec->bv_page);
 		int len = bmd->iovecs[i].bv_len;
 
@@ -1256,7 +1538,7 @@ struct bio *bio_copy_kern(struct request_queue *q, void *data, unsigned int len,
 	if (!reading) {
 		void *p = data;
 
-		bio_for_each_segment(bvec, bio, i) {
+		bio_for_each_segment_all(bvec, bio, i) {
 			char *addr = page_address(bvec->bv_page);
 
 			memcpy(addr, p, bvec->bv_len);
@@ -1301,11 +1583,11 @@ EXPORT_SYMBOL(bio_copy_kern);
  */
 void bio_set_pages_dirty(struct bio *bio)
 {
-	struct bio_vec *bvec = bio->bi_io_vec;
+	struct bio_vec *bvec;
 	int i;
 
-	for (i = 0; i < bio->bi_vcnt; i++) {
-		struct page *page = bvec[i].bv_page;
+	bio_for_each_segment_all(bvec, bio, i) {
+		struct page *page = bvec->bv_page;
 
 		if (page && !PageCompound(page))
 			set_page_dirty_lock(page);
@@ -1314,11 +1596,11 @@ void bio_set_pages_dirty(struct bio *bio)
 
 static void bio_release_pages(struct bio *bio)
 {
-	struct bio_vec *bvec = bio->bi_io_vec;
+	struct bio_vec *bvec;
 	int i;
 
-	for (i = 0; i < bio->bi_vcnt; i++) {
-		struct page *page = bvec[i].bv_page;
+	bio_for_each_segment_all(bvec, bio, i) {
+		struct page *page = bvec->bv_page;
 
 		if (page)
 			put_page(page);
@@ -1367,16 +1649,16 @@ static void bio_dirty_fn(struct work_struct *work)
 
 void bio_check_pages_dirty(struct bio *bio)
 {
-	struct bio_vec *bvec = bio->bi_io_vec;
+	struct bio_vec *bvec;
 	int nr_clean_pages = 0;
 	int i;
 
-	for (i = 0; i < bio->bi_vcnt; i++) {
-		struct page *page = bvec[i].bv_page;
+	bio_for_each_segment_all(bvec, bio, i) {
+		struct page *page = bvec->bv_page;
 
 		if (PageDirty(page) || PageCompound(page)) {
 			page_cache_release(page);
-			bvec[i].bv_page = NULL;
+			bvec->bv_page = NULL;
 		} else {
 			nr_clean_pages++;
 		}
@@ -1407,33 +1689,42 @@ void bio_flush_dcache_pages(struct bio *bi)
 EXPORT_SYMBOL(bio_flush_dcache_pages);
 #endif
 
-/**
- * bio_endio - end I/O on a bio
- * @bio:	bio
- * @error:	error, if any
- *
- * Description:
- *   bio_endio() will end I/O on the whole bio. bio_endio() is the
- *   preferred way to end I/O on a bio, it takes care of clearing
- *   BIO_UPTODATE on error. @error is 0 on success, and and one of the
- *   established -Exxxx (-EIO, for instance) error values in case
- *   something went wrong. No one should call bi_end_io() directly on a
- *   bio unless they own it and thus know that it has an end_io
- *   function.
- **/
-void bio_endio(struct bio *bio, int error)
+static inline void __bio_endio(struct bio *bio, struct batch_complete *batch)
 {
-	if (error)
+	if (bio->bi_error)
 		clear_bit(BIO_UPTODATE, &bio->bi_flags);
 	else if (!test_bit(BIO_UPTODATE, &bio->bi_flags))
-		error = -EIO;
+		bio->bi_error = -EIO;
+
+	if (bio->bi_end_io)
+		bio->bi_end_io(bio, bio->bi_error, batch);
+}
+
+void bio_endio_batch(struct bio *bio, int error, struct batch_complete *batch)
+{
+	if (error)
+		bio->bi_error = error;
 
 	trace_block_bio_complete(bio, error);
 
-	if (bio->bi_end_io)
-		bio->bi_end_io(bio, error);
+	if (batch)
+		bio_list_add(&batch->bio, bio);
+	else
+		__bio_endio(bio, batch);
+
+}
+EXPORT_SYMBOL(bio_endio_batch);
+
+void batch_complete(struct batch_complete *batch)
+{
+	struct bio *bio;
+
+	while ((bio = bio_list_pop(&batch->bio)))
+		__bio_endio(bio, batch);
+
+	batch_complete_aio(batch);
 }
-EXPORT_SYMBOL(bio_endio);
+EXPORT_SYMBOL(batch_complete);
 
 void bio_pair_release(struct bio_pair *bp)
 {
@@ -1446,7 +1737,8 @@ void bio_pair_release(struct bio_pair *bp)
 }
 EXPORT_SYMBOL(bio_pair_release);
 
-static void bio_pair_end_1(struct bio *bi, int err)
+static void bio_pair_end_1(struct bio *bi, int err,
+			   struct batch_complete *batch)
 {
 	struct bio_pair *bp = container_of(bi, struct bio_pair, bio1);
 
@@ -1456,7 +1748,8 @@ static void bio_pair_end_1(struct bio *bi, int err)
 	bio_pair_release(bp);
 }
 
-static void bio_pair_end_2(struct bio *bi, int err)
+static void bio_pair_end_2(struct bio *bi, int err,
+			   struct batch_complete *batch)
 {
 	struct bio_pair *bp = container_of(bi, struct bio_pair, bio2);
 
@@ -1479,8 +1772,7 @@ struct bio_pair *bio_split(struct bio *bi, int first_sectors)
 	trace_block_split(bdev_get_queue(bi->bi_bdev), bi,
 				bi->bi_sector + first_sectors);
 
-	BUG_ON(bi->bi_vcnt != 1 && bi->bi_vcnt != 0);
-	BUG_ON(bi->bi_idx != 0);
+	BUG_ON(bio_segments(bi) > 1);
 	atomic_set(&bp->cnt, 3);
 	bp->error = 0;
 	bp->bio1 = *bi;
@@ -1490,8 +1782,8 @@ struct bio_pair *bio_split(struct bio *bi, int first_sectors)
 	bp->bio1.bi_size = first_sectors << 9;
 
 	if (bi->bi_vcnt != 0) {
-		bp->bv1 = bi->bi_io_vec[0];
-		bp->bv2 = bi->bi_io_vec[0];
+		bp->bv1 = *bio_iovec(bi);
+		bp->bv2 = *bio_iovec(bi);
 
 		if (bio_is_rw(bi)) {
 			bp->bv2.bv_offset += first_sectors << 9;
@@ -1543,7 +1835,7 @@ sector_t bio_sector_offset(struct bio *bio, unsigned short index,
 	if (index >= bio->bi_idx)
 		index = bio->bi_vcnt - 1;
 
-	__bio_for_each_segment(bv, bio, i, 0) {
+	bio_for_each_segment_all(bv, bio, i) {
 		if (i == index) {
 			if (offset > bv->bv_offset)
 				sectors += (offset - bv->bv_offset) / sector_sz;
@@ -1561,29 +1853,25 @@ EXPORT_SYMBOL(bio_sector_offset);
  * create memory pools for biovec's in a bio_set.
  * use the global biovec slabs created for general use.
  */
-static int biovec_create_pools(struct bio_set *bs, int pool_entries)
+mempool_t *biovec_create_pool(struct bio_set *bs, int pool_entries)
 {
 	struct biovec_slab *bp = bvec_slabs + BIOVEC_MAX_IDX;
 
-	bs->bvec_pool = mempool_create_slab_pool(pool_entries, bp->slab);
-	if (!bs->bvec_pool)
-		return -ENOMEM;
-
-	return 0;
-}
-
-static void biovec_free_pools(struct bio_set *bs)
-{
-	mempool_destroy(bs->bvec_pool);
+	return mempool_create_slab_pool(pool_entries, bp->slab);
 }
 
 void bioset_free(struct bio_set *bs)
 {
+	if (bs->rescue_workqueue)
+		destroy_workqueue(bs->rescue_workqueue);
+
 	if (bs->bio_pool)
 		mempool_destroy(bs->bio_pool);
 
+	if (bs->bvec_pool)
+		mempool_destroy(bs->bvec_pool);
+
 	bioset_integrity_free(bs);
-	biovec_free_pools(bs);
 	bio_put_slab(bs);
 
 	kfree(bs);
@@ -1614,6 +1902,10 @@ struct bio_set *bioset_create(unsigned int pool_size, unsigned int front_pad)
 
 	bs->front_pad = front_pad;
 
+	spin_lock_init(&bs->rescue_lock);
+	bio_list_init(&bs->rescue_list);
+	INIT_WORK(&bs->rescue_work, bio_alloc_rescue);
+
 	bs->bio_slab = bio_find_or_create_slab(front_pad + back_pad);
 	if (!bs->bio_slab) {
 		kfree(bs);
@@ -1624,9 +1916,15 @@ struct bio_set *bioset_create(unsigned int pool_size, unsigned int front_pad)
 	if (!bs->bio_pool)
 		goto bad;
 
-	if (!biovec_create_pools(bs, pool_size))
-		return bs;
+	bs->bvec_pool = biovec_create_pool(bs, pool_size);
+	if (!bs->bvec_pool)
+		goto bad;
+
+	bs->rescue_workqueue = alloc_workqueue("bioset", WQ_MEM_RECLAIM, 0);
+	if (!bs->rescue_workqueue)
+		goto bad;
 
+	return bs;
 bad:
 	bioset_free(bs);
 	return NULL;
diff --git a/fs/block_dev.c b/fs/block_dev.c
index aea605c..95ff88b 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -27,6 +27,7 @@
 #include <linux/namei.h>
 #include <linux/log2.h>
 #include <linux/cleancache.h>
+#include <linux/aio.h>
 #include <asm/uaccess.h>
 #include "internal.h"
 
@@ -551,6 +552,7 @@ struct block_device *bdgrab(struct block_device *bdev)
 	ihold(bdev->bd_inode);
 	return bdev;
 }
+EXPORT_SYMBOL(bdgrab);
 
 long nr_blockdev_pages(void)
 {
@@ -616,11 +618,9 @@ void bd_forget(struct inode *inode)
 	struct block_device *bdev = NULL;
 
 	spin_lock(&bdev_lock);
-	if (inode->i_bdev) {
-		if (!sb_is_blkdev_sb(inode->i_sb))
-			bdev = inode->i_bdev;
-		__bd_forget(inode);
-	}
+	if (!sb_is_blkdev_sb(inode->i_sb))
+		bdev = inode->i_bdev;
+	__bd_forget(inode);
 	spin_unlock(&bdev_lock);
 
 	if (bdev)
diff --git a/fs/btrfs/check-integrity.c b/fs/btrfs/check-integrity.c
index 18af6f4..3c617b3 100644
--- a/fs/btrfs/check-integrity.c
+++ b/fs/btrfs/check-integrity.c
@@ -323,7 +323,8 @@ static void btrfsic_release_block_ctx(struct btrfsic_block_data_ctx *block_ctx);
 static int btrfsic_read_block(struct btrfsic_state *state,
 			      struct btrfsic_block_data_ctx *block_ctx);
 static void btrfsic_dump_database(struct btrfsic_state *state);
-static void btrfsic_complete_bio_end_io(struct bio *bio, int err);
+static void btrfsic_complete_bio_end_io(struct bio *bio, int err,
+					struct batch_complete *batch);
 static int btrfsic_test_for_metadata(struct btrfsic_state *state,
 				     char **datav, unsigned int num_pages);
 static void btrfsic_process_written_block(struct btrfsic_dev_state *dev_state,
@@ -336,7 +337,8 @@ static int btrfsic_process_written_superblock(
 		struct btrfsic_state *state,
 		struct btrfsic_block *const block,
 		struct btrfs_super_block *const super_hdr);
-static void btrfsic_bio_end_io(struct bio *bp, int bio_error_status);
+static void btrfsic_bio_end_io(struct bio *bp, int bio_error_status,
+			       struct batch_complete *batch);
 static void btrfsic_bh_end_io(struct buffer_head *bh, int uptodate);
 static int btrfsic_is_block_ref_by_superblock(const struct btrfsic_state *state,
 					      const struct btrfsic_block *block,
@@ -1751,7 +1753,8 @@ static int btrfsic_read_block(struct btrfsic_state *state,
 	return block_ctx->len;
 }
 
-static void btrfsic_complete_bio_end_io(struct bio *bio, int err)
+static void btrfsic_complete_bio_end_io(struct bio *bio, int err,
+					struct batch_complete *batch)
 {
 	complete((struct completion *)bio->bi_private);
 }
@@ -2294,7 +2297,8 @@ continue_loop:
 	goto again;
 }
 
-static void btrfsic_bio_end_io(struct bio *bp, int bio_error_status)
+static void btrfsic_bio_end_io(struct bio *bp, int bio_error_status,
+			       struct batch_complete *batch)
 {
 	struct btrfsic_block *block = (struct btrfsic_block *)bp->bi_private;
 	int iodone_w_error;
@@ -2342,7 +2346,7 @@ static void btrfsic_bio_end_io(struct bio *bp, int bio_error_status)
 		block = next_block;
 	} while (NULL != block);
 
-	bp->bi_end_io(bp, bio_error_status);
+	bp->bi_end_io(bp, bio_error_status, batch);
 }
 
 static void btrfsic_bh_end_io(struct buffer_head *bh, int uptodate)
diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c
index 15b9408..74ae115 100644
--- a/fs/btrfs/compression.c
+++ b/fs/btrfs/compression.c
@@ -153,7 +153,8 @@ fail:
  * The compressed pages are freed here, and it must be run
  * in process context
  */
-static void end_compressed_bio_read(struct bio *bio, int err)
+static void end_compressed_bio_read(struct bio *bio, int err,
+				    struct batch_complete *batch)
 {
 	struct compressed_bio *cb = bio->bi_private;
 	struct inode *inode;
@@ -263,7 +264,8 @@ static noinline void end_compressed_writeback(struct inode *inode, u64 start,
  * This also calls the writeback end hooks for the file pages so that
  * metadata and checksums can be updated in the file.
  */
-static void end_compressed_bio_write(struct bio *bio, int err)
+static void end_compressed_bio_write(struct bio *bio, int err,
+				     struct batch_complete *batch)
 {
 	struct extent_io_tree *tree;
 	struct compressed_bio *cb = bio->bi_private;
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 6d19a0a..8e72500 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -669,7 +669,8 @@ static int btree_io_failed_hook(struct page *page, int failed_mirror)
 	return -EIO;	/* we fixed nothing */
 }
 
-static void end_workqueue_bio(struct bio *bio, int err)
+static void end_workqueue_bio(struct bio *bio, int err,
+			      struct batch_complete *batch)
 {
 	struct end_io_wq *end_io_wq = bio->bi_private;
 	struct btrfs_fs_info *fs_info;
@@ -2957,7 +2958,8 @@ static int write_dev_supers(struct btrfs_device *device,
  * endio for the write_dev_flush, this will wake anyone waiting
  * for the barrier when it is done
  */
-static void btrfs_end_empty_barrier(struct bio *bio, int err)
+static void btrfs_end_empty_barrier(struct bio *bio, int err,
+				    struct batch_complete *batch)
 {
 	if (err) {
 		if (err == -EOPNOTSUPP)
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index cdee391..fbf0d44 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -1937,7 +1937,8 @@ static int free_io_failure(struct inode *inode, struct io_failure_record *rec,
 	return err;
 }
 
-static void repair_io_failure_callback(struct bio *bio, int err)
+static void repair_io_failure_callback(struct bio *bio, int err,
+				       struct batch_complete *batch)
 {
 	complete(bio->bi_private);
 }
@@ -2317,7 +2318,8 @@ int end_extent_writepage(struct page *page, int err, u64 start, u64 end)
  * Scheduling is not allowed, so the extent state tree is expected
  * to have one and only one object corresponding to this IO.
  */
-static void end_bio_extent_writepage(struct bio *bio, int err)
+static void end_bio_extent_writepage(struct bio *bio, int err,
+				     struct batch_complete *batch)
 {
 	struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1;
 	struct extent_io_tree *tree;
@@ -2363,7 +2365,8 @@ static void end_bio_extent_writepage(struct bio *bio, int err)
  * Scheduling is not allowed, so the extent state tree is expected
  * to have one and only one object corresponding to this IO.
  */
-static void end_bio_extent_readpage(struct bio *bio, int err)
+static void end_bio_extent_readpage(struct bio *bio, int err,
+				    struct batch_complete *batch)
 {
 	int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
 	struct bio_vec *bvec_end = bio->bi_io_vec + bio->bi_vcnt - 1;
@@ -2560,8 +2563,7 @@ static int submit_extent_page(int rw, struct extent_io_tree *tree,
 		if (old_compressed)
 			contig = bio->bi_sector == sector;
 		else
-			contig = bio->bi_sector + (bio->bi_size >> 9) ==
-				sector;
+			contig = bio_end_sector(bio) == sector;
 
 		if (prev_bio_flags != bio_flags || !contig ||
 		    merge_bio(rw, tree, page, offset, page_size, bio, bio_flags) ||
@@ -3187,7 +3189,8 @@ static void end_extent_buffer_writeback(struct extent_buffer *eb)
 	wake_up_bit(&eb->bflags, EXTENT_BUFFER_WRITEBACK);
 }
 
-static void end_bio_extent_buffer_writepage(struct bio *bio, int err)
+static void end_bio_extent_buffer_writepage(struct bio *bio, int err,
+					    struct batch_complete *batch)
 {
 	int uptodate = err == 0;
 	struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1;
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index ade03e6..bc4d54c 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -24,6 +24,7 @@
 #include <linux/string.h>
 #include <linux/backing-dev.h>
 #include <linux/mpage.h>
+#include <linux/aio.h>
 #include <linux/falloc.h>
 #include <linux/swap.h>
 #include <linux/writeback.h>
@@ -1514,8 +1515,6 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb,
 	size_t count, ocount;
 	bool sync = (file->f_flags & O_DSYNC) || IS_SYNC(file->f_mapping->host);
 
-	sb_start_write(inode->i_sb);
-
 	mutex_lock(&inode->i_mutex);
 
 	err = generic_segment_checks(iov, &nr_segs, &ocount, VERIFY_READ);
@@ -1617,7 +1616,6 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb,
 	if (sync)
 		atomic_dec(&BTRFS_I(inode)->sync_writers);
 out:
-	sb_end_write(inode->i_sb);
 	current->backing_dev_info = NULL;
 	return num_written ? num_written : err;
 }
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 09c58a3..0031305 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -32,6 +32,7 @@
 #include <linux/writeback.h>
 #include <linux/statfs.h>
 #include <linux/compat.h>
+#include <linux/aio.h>
 #include <linux/bit_spinlock.h>
 #include <linux/xattr.h>
 #include <linux/posix_acl.h>
@@ -6913,7 +6914,8 @@ struct btrfs_dio_private {
 	struct bio *orig_bio;
 };
 
-static void btrfs_endio_direct_read(struct bio *bio, int err)
+static void btrfs_endio_direct_read(struct bio *bio, int err,
+				    struct batch_complete *batch)
 {
 	struct btrfs_dio_private *dip = bio->bi_private;
 	struct bio_vec *bvec_end = bio->bi_io_vec + bio->bi_vcnt - 1;
@@ -6967,10 +6969,11 @@ failed:
 	/* If we had a csum failure make sure to clear the uptodate flag */
 	if (err)
 		clear_bit(BIO_UPTODATE, &bio->bi_flags);
-	dio_end_io(bio, err);
+	dio_end_io(bio, err, batch);
 }
 
-static void btrfs_endio_direct_write(struct bio *bio, int err)
+static void btrfs_endio_direct_write(struct bio *bio, int err,
+				     struct batch_complete *batch)
 {
 	struct btrfs_dio_private *dip = bio->bi_private;
 	struct inode *inode = dip->inode;
@@ -7012,7 +7015,7 @@ out_done:
 	/* If we had an error make sure to clear the uptodate flag */
 	if (err)
 		clear_bit(BIO_UPTODATE, &bio->bi_flags);
-	dio_end_io(bio, err);
+	dio_end_io(bio, err, batch);
 }
 
 static int __btrfs_submit_bio_start_direct_io(struct inode *inode, int rw,
@@ -7026,7 +7029,8 @@ static int __btrfs_submit_bio_start_direct_io(struct inode *inode, int rw,
 	return 0;
 }
 
-static void btrfs_end_dio_bio(struct bio *bio, int err)
+static void btrfs_end_dio_bio(struct bio *bio, int err,
+			      struct batch_complete *batch)
 {
 	struct btrfs_dio_private *dip = bio->bi_private;
 
diff --git a/fs/btrfs/raid56.c b/fs/btrfs/raid56.c
index 9a79fb7..6df1ac8 100644
--- a/fs/btrfs/raid56.c
+++ b/fs/btrfs/raid56.c
@@ -850,7 +850,8 @@ static void rbio_orig_end_io(struct btrfs_raid_bio *rbio, int err, int uptodate)
  * end io function used by finish_rmw.  When we finally
  * get here, we've written a full stripe
  */
-static void raid_write_end_io(struct bio *bio, int err)
+static void raid_write_end_io(struct bio *bio, int err,
+			      struct batch_complete *batch)
 {
 	struct btrfs_raid_bio *rbio = bio->bi_private;
 
@@ -1384,7 +1385,8 @@ static void set_bio_pages_uptodate(struct bio *bio)
  * This will usually kick off finish_rmw once all the bios are read in, but it
  * may trigger parity reconstruction if we had any errors along the way
  */
-static void raid_rmw_end_io(struct bio *bio, int err)
+static void raid_rmw_end_io(struct bio *bio, int err,
+			    struct batch_complete *batch)
 {
 	struct btrfs_raid_bio *rbio = bio->bi_private;
 
@@ -1905,7 +1907,8 @@ cleanup_io:
  * This is called only for stripes we've read from disk to
  * reconstruct the parity.
  */
-static void raid_recover_end_io(struct bio *bio, int err)
+static void raid_recover_end_io(struct bio *bio, int err,
+				struct batch_complete *batch)
 {
 	struct btrfs_raid_bio *rbio = bio->bi_private;
 
diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c
index 85e072b..fc29a11 100644
--- a/fs/btrfs/scrub.c
+++ b/fs/btrfs/scrub.c
@@ -200,7 +200,8 @@ static void scrub_recheck_block_checksum(struct btrfs_fs_info *fs_info,
 					 int is_metadata, int have_csum,
 					 const u8 *csum, u64 generation,
 					 u16 csum_size);
-static void scrub_complete_bio_end_io(struct bio *bio, int err);
+static void scrub_complete_bio_end_io(struct bio *bio, int err,
+				      struct batch_complete *batch);
 static int scrub_repair_block_from_good_copy(struct scrub_block *sblock_bad,
 					     struct scrub_block *sblock_good,
 					     int force_write);
@@ -223,7 +224,8 @@ static int scrub_pages(struct scrub_ctx *sctx, u64 logical, u64 len,
 		       u64 physical, struct btrfs_device *dev, u64 flags,
 		       u64 gen, int mirror_num, u8 *csum, int force,
 		       u64 physical_for_dev_replace);
-static void scrub_bio_end_io(struct bio *bio, int err);
+static void scrub_bio_end_io(struct bio *bio, int err,
+			     struct batch_complete *batch);
 static void scrub_bio_end_io_worker(struct btrfs_work *work);
 static void scrub_block_complete(struct scrub_block *sblock);
 static void scrub_remap_extent(struct btrfs_fs_info *fs_info,
@@ -240,7 +242,8 @@ static void scrub_free_wr_ctx(struct scrub_wr_ctx *wr_ctx);
 static int scrub_add_page_to_wr_bio(struct scrub_ctx *sctx,
 				    struct scrub_page *spage);
 static void scrub_wr_submit(struct scrub_ctx *sctx);
-static void scrub_wr_bio_end_io(struct bio *bio, int err);
+static void scrub_wr_bio_end_io(struct bio *bio, int err,
+				struct batch_complete *batch);
 static void scrub_wr_bio_end_io_worker(struct btrfs_work *work);
 static int write_page_nocow(struct scrub_ctx *sctx,
 			    u64 physical_for_dev_replace, struct page *page);
@@ -1386,7 +1389,8 @@ static void scrub_recheck_block_checksum(struct btrfs_fs_info *fs_info,
 		sblock->checksum_error = 1;
 }
 
-static void scrub_complete_bio_end_io(struct bio *bio, int err)
+static void scrub_complete_bio_end_io(struct bio *bio, int err,
+				      struct batch_complete *batch)
 {
 	complete((struct completion *)bio->bi_private);
 }
@@ -1586,7 +1590,8 @@ static void scrub_wr_submit(struct scrub_ctx *sctx)
 	btrfsic_submit_bio(WRITE, sbio->bio);
 }
 
-static void scrub_wr_bio_end_io(struct bio *bio, int err)
+static void scrub_wr_bio_end_io(struct bio *bio, int err,
+				struct batch_complete *batch)
 {
 	struct scrub_bio *sbio = bio->bi_private;
 	struct btrfs_fs_info *fs_info = sbio->dev->dev_root->fs_info;
@@ -2056,7 +2061,8 @@ leave_nomem:
 	return 0;
 }
 
-static void scrub_bio_end_io(struct bio *bio, int err)
+static void scrub_bio_end_io(struct bio *bio, int err,
+			     struct batch_complete *batch)
 {
 	struct scrub_bio *sbio = bio->bi_private;
 	struct btrfs_fs_info *fs_info = sbio->dev->dev_root->fs_info;
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 2854c82..0182898 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -5029,7 +5029,8 @@ static unsigned int extract_stripe_index_from_bio_private(void *bi_private)
 	return (unsigned int)((uintptr_t)bi_private) & 3;
 }
 
-static void btrfs_end_bio(struct bio *bio, int err)
+static void btrfs_end_bio(struct bio *bio, int err,
+			  struct batch_complete *batch)
 {
 	struct btrfs_bio *bbio = extract_bbio_from_bio_private(bio->bi_private);
 	int is_orig_bio = 0;
@@ -5086,7 +5087,7 @@ static void btrfs_end_bio(struct bio *bio, int err)
 		}
 		kfree(bbio);
 
-		bio_endio(bio, err);
+		bio_endio_batch(bio, err, batch);
 	} else if (!is_orig_bio) {
 		bio_put(bio);
 	}
@@ -5177,7 +5178,7 @@ static int bio_size_ok(struct block_device *bdev, struct bio *bio,
 	}
 
 	prev = &bio->bi_io_vec[bio->bi_vcnt - 1];
-	if ((bio->bi_size >> 9) > max_sectors)
+	if (bio_sectors(bio) > max_sectors)
 		return 0;
 
 	if (!q->merge_bvec_fn)
diff --git a/fs/buffer.c b/fs/buffer.c
index b4dcb34..b22d0bb 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -2884,7 +2884,8 @@ sector_t generic_block_bmap(struct address_space *mapping, sector_t block,
 }
 EXPORT_SYMBOL(generic_block_bmap);
 
-static void end_bio_bh_io_sync(struct bio *bio, int err)
+static void end_bio_bh_io_sync(struct bio *bio, int err,
+			       struct batch_complete *batch)
 {
 	struct buffer_head *bh = bio->bi_private;
 
@@ -2949,7 +2950,7 @@ static void guard_bh_eod(int rw, struct bio *bio, struct buffer_head *bh)
 	}
 }
 
-int submit_bh(int rw, struct buffer_head * bh)
+int _submit_bh(int rw, struct buffer_head *bh, unsigned long bio_flags)
 {
 	struct bio *bio;
 	int ret = 0;
@@ -2979,11 +2980,11 @@ int submit_bh(int rw, struct buffer_head * bh)
 	bio->bi_io_vec[0].bv_offset = bh_offset(bh);
 
 	bio->bi_vcnt = 1;
-	bio->bi_idx = 0;
 	bio->bi_size = bh->b_size;
 
 	bio->bi_end_io = end_bio_bh_io_sync;
 	bio->bi_private = bh;
+	bio->bi_flags |= bio_flags;
 
 	/* Take care of bh's that straddle the end of the device */
 	guard_bh_eod(rw, bio, bh);
@@ -2997,6 +2998,12 @@ int submit_bh(int rw, struct buffer_head * bh)
 	bio_put(bio);
 	return ret;
 }
+EXPORT_SYMBOL_GPL(_submit_bh);
+
+int submit_bh(int rw, struct buffer_head * bh)
+{
+	return _submit_bh(rw, bh, 0);
+}
 EXPORT_SYMBOL(submit_bh);
 
 /**
diff --git a/fs/cachefiles/rdwr.c b/fs/cachefiles/rdwr.c
index 4809922..317f9ee 100644
--- a/fs/cachefiles/rdwr.c
+++ b/fs/cachefiles/rdwr.c
@@ -962,12 +962,14 @@ int cachefiles_write_page(struct fscache_storage *op, struct page *page)
 			}
 
 			data = kmap(page);
+			file_start_write(file);
 			old_fs = get_fs();
 			set_fs(KERNEL_DS);
 			ret = file->f_op->write(
 				file, (const void __user *) data, len, &pos);
 			set_fs(old_fs);
 			kunmap(page);
+			file_end_write(file);
 			if (ret != len)
 				ret = -EIO;
 		}
diff --git a/fs/ceph/file.c b/fs/ceph/file.c
index bf338d9..eb09f41 100644
--- a/fs/ceph/file.c
+++ b/fs/ceph/file.c
@@ -7,6 +7,7 @@
 #include <linux/mount.h>
 #include <linux/namei.h>
 #include <linux/writeback.h>
+#include <linux/aio.h>
 
 #include "super.h"
 #include "mds_client.h"
diff --git a/fs/cifs/asn1.c b/fs/cifs/asn1.c
index 1d36db1..a3b5654 100644
--- a/fs/cifs/asn1.c
+++ b/fs/cifs/asn1.c
@@ -506,11 +506,11 @@ decode_negTokenInit(unsigned char *security_blob, int length,
 
 	/* GSSAPI header */
 	if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
-		cFYI(1, "Error decoding negTokenInit header");
+		cifs_dbg(FYI, "Error decoding negTokenInit header\n");
 		return 0;
 	} else if ((cls != ASN1_APL) || (con != ASN1_CON)
 		   || (tag != ASN1_EOC)) {
-		cFYI(1, "cls = %d con = %d tag = %d", cls, con, tag);
+		cifs_dbg(FYI, "cls = %d con = %d tag = %d\n", cls, con, tag);
 		return 0;
 	}
 
@@ -531,52 +531,52 @@ decode_negTokenInit(unsigned char *security_blob, int length,
 
 	/* SPNEGO OID not present or garbled -- bail out */
 	if (!rc) {
-		cFYI(1, "Error decoding negTokenInit header");
+		cifs_dbg(FYI, "Error decoding negTokenInit header\n");
 		return 0;
 	}
 
 	/* SPNEGO */
 	if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
-		cFYI(1, "Error decoding negTokenInit");
+		cifs_dbg(FYI, "Error decoding negTokenInit\n");
 		return 0;
 	} else if ((cls != ASN1_CTX) || (con != ASN1_CON)
 		   || (tag != ASN1_EOC)) {
-		cFYI(1, "cls = %d con = %d tag = %d end = %p (%d) exit 0",
-		     cls, con, tag, end, *end);
+		cifs_dbg(FYI, "cls = %d con = %d tag = %d end = %p (%d) exit 0\n",
+			 cls, con, tag, end, *end);
 		return 0;
 	}
 
 	/* negTokenInit */
 	if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
-		cFYI(1, "Error decoding negTokenInit");
+		cifs_dbg(FYI, "Error decoding negTokenInit\n");
 		return 0;
 	} else if ((cls != ASN1_UNI) || (con != ASN1_CON)
 		   || (tag != ASN1_SEQ)) {
-		cFYI(1, "cls = %d con = %d tag = %d end = %p (%d) exit 1",
-		     cls, con, tag, end, *end);
+		cifs_dbg(FYI, "cls = %d con = %d tag = %d end = %p (%d) exit 1\n",
+			 cls, con, tag, end, *end);
 		return 0;
 	}
 
 	/* sequence */
 	if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
-		cFYI(1, "Error decoding 2nd part of negTokenInit");
+		cifs_dbg(FYI, "Error decoding 2nd part of negTokenInit\n");
 		return 0;
 	} else if ((cls != ASN1_CTX) || (con != ASN1_CON)
 		   || (tag != ASN1_EOC)) {
-		cFYI(1, "cls = %d con = %d tag = %d end = %p (%d) exit 0",
-		     cls, con, tag, end, *end);
+		cifs_dbg(FYI, "cls = %d con = %d tag = %d end = %p (%d) exit 0\n",
+			 cls, con, tag, end, *end);
 		return 0;
 	}
 
 	/* sequence of */
 	if (asn1_header_decode
 	    (&ctx, &sequence_end, &cls, &con, &tag) == 0) {
-		cFYI(1, "Error decoding 2nd part of negTokenInit");
+		cifs_dbg(FYI, "Error decoding 2nd part of negTokenInit\n");
 		return 0;
 	} else if ((cls != ASN1_UNI) || (con != ASN1_CON)
 		   || (tag != ASN1_SEQ)) {
-		cFYI(1, "cls = %d con = %d tag = %d end = %p (%d) exit 1",
-		     cls, con, tag, end, *end);
+		cifs_dbg(FYI, "cls = %d con = %d tag = %d end = %p (%d) exit 1\n",
+			 cls, con, tag, end, *end);
 		return 0;
 	}
 
@@ -584,15 +584,15 @@ decode_negTokenInit(unsigned char *security_blob, int length,
 	while (!asn1_eoc_decode(&ctx, sequence_end)) {
 		rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag);
 		if (!rc) {
-			cFYI(1, "Error decoding negTokenInit hdr exit2");
+			cifs_dbg(FYI, "Error decoding negTokenInit hdr exit2\n");
 			return 0;
 		}
 		if ((tag == ASN1_OJI) && (con == ASN1_PRI)) {
 			if (asn1_oid_decode(&ctx, end, &oid, &oidlen)) {
 
-				cFYI(1, "OID len = %d oid = 0x%lx 0x%lx "
-					"0x%lx 0x%lx", oidlen, *oid,
-					*(oid + 1), *(oid + 2), *(oid + 3));
+				cifs_dbg(FYI, "OID len = %d oid = 0x%lx 0x%lx 0x%lx 0x%lx\n",
+					 oidlen, *oid, *(oid + 1), *(oid + 2),
+					 *(oid + 3));
 
 				if (compare_oid(oid, oidlen, MSKRB5_OID,
 						MSKRB5_OID_LEN))
@@ -610,7 +610,7 @@ decode_negTokenInit(unsigned char *security_blob, int length,
 				kfree(oid);
 			}
 		} else {
-			cFYI(1, "Should be an oid what is going on?");
+			cifs_dbg(FYI, "Should be an oid what is going on?\n");
 		}
 	}
 
diff --git a/fs/cifs/cache.c b/fs/cifs/cache.c
index 282d6de..6c665bf 100644
--- a/fs/cifs/cache.c
+++ b/fs/cifs/cache.c
@@ -92,7 +92,7 @@ static uint16_t cifs_server_get_key(const void *cookie_netfs_data,
 		break;
 
 	default:
-		cERROR(1, "Unknown network family '%d'", sa->sa_family);
+		cifs_dbg(VFS, "Unknown network family '%d'\n", sa->sa_family);
 		key_len = 0;
 		break;
 	}
@@ -152,7 +152,7 @@ static uint16_t cifs_super_get_key(const void *cookie_netfs_data, void *buffer,
 
 	sharename = extract_sharename(tcon->treeName);
 	if (IS_ERR(sharename)) {
-		cFYI(1, "%s: couldn't extract sharename", __func__);
+		cifs_dbg(FYI, "%s: couldn't extract sharename\n", __func__);
 		sharename = NULL;
 		return 0;
 	}
@@ -302,7 +302,7 @@ static void cifs_fscache_inode_now_uncached(void *cookie_netfs_data)
 	pagevec_init(&pvec, 0);
 	first = 0;
 
-	cFYI(1, "%s: cifs inode 0x%p now uncached", __func__, cifsi);
+	cifs_dbg(FYI, "%s: cifs inode 0x%p now uncached\n", __func__, cifsi);
 
 	for (;;) {
 		nr_pages = pagevec_lookup(&pvec,
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
index d9ea6ed..d597483 100644
--- a/fs/cifs/cifs_debug.c
+++ b/fs/cifs/cifs_debug.c
@@ -57,15 +57,32 @@ cifs_dump_mem(char *label, void *data, int length)
 	}
 }
 
+#ifdef CONFIG_CIFS_DEBUG
+void cifs_vfs_err(const char *fmt, ...)
+{
+	struct va_format vaf;
+	va_list args;
+
+	va_start(args, fmt);
+
+	vaf.fmt = fmt;
+	vaf.va = &args;
+
+	printk(KERN_ERR "CIFS VFS: %pV", &vaf);
+
+	va_end(args);
+}
+#endif
+
 void cifs_dump_detail(void *buf)
 {
 #ifdef CONFIG_CIFS_DEBUG2
 	struct smb_hdr *smb = (struct smb_hdr *)buf;
 
-	cERROR(1, "Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d",
-		  smb->Command, smb->Status.CifsError,
-		  smb->Flags, smb->Flags2, smb->Mid, smb->Pid);
-	cERROR(1, "smb buf %p len %u", smb, smbCalcSize(smb));
+	cifs_dbg(VFS, "Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d\n",
+		 smb->Command, smb->Status.CifsError,
+		 smb->Flags, smb->Flags2, smb->Mid, smb->Pid);
+	cifs_dbg(VFS, "smb buf %p len %u\n", smb, smbCalcSize(smb));
 #endif /* CONFIG_CIFS_DEBUG2 */
 }
 
@@ -78,25 +95,25 @@ void cifs_dump_mids(struct TCP_Server_Info *server)
 	if (server == NULL)
 		return;
 
-	cERROR(1, "Dump pending requests:");
+	cifs_dbg(VFS, "Dump pending requests:\n");
 	spin_lock(&GlobalMid_Lock);
 	list_for_each(tmp, &server->pending_mid_q) {
 		mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
-		cERROR(1, "State: %d Cmd: %d Pid: %d Cbdata: %p Mid %llu",
-			mid_entry->mid_state,
-			le16_to_cpu(mid_entry->command),
-			mid_entry->pid,
-			mid_entry->callback_data,
-			mid_entry->mid);
+		cifs_dbg(VFS, "State: %d Cmd: %d Pid: %d Cbdata: %p Mid %llu\n",
+			 mid_entry->mid_state,
+			 le16_to_cpu(mid_entry->command),
+			 mid_entry->pid,
+			 mid_entry->callback_data,
+			 mid_entry->mid);
 #ifdef CONFIG_CIFS_STATS2
-		cERROR(1, "IsLarge: %d buf: %p time rcv: %ld now: %ld",
-			mid_entry->large_buf,
-			mid_entry->resp_buf,
-			mid_entry->when_received,
-			jiffies);
+		cifs_dbg(VFS, "IsLarge: %d buf: %p time rcv: %ld now: %ld\n",
+			 mid_entry->large_buf,
+			 mid_entry->resp_buf,
+			 mid_entry->when_received,
+			 jiffies);
 #endif /* STATS2 */
-		cERROR(1, "IsMult: %d IsEnd: %d", mid_entry->multiRsp,
-			  mid_entry->multiEnd);
+		cifs_dbg(VFS, "IsMult: %d IsEnd: %d\n",
+			 mid_entry->multiRsp, mid_entry->multiEnd);
 		if (mid_entry->resp_buf) {
 			cifs_dump_detail(mid_entry->resp_buf);
 			cifs_dump_mem("existing buf: ",
@@ -603,7 +620,7 @@ static ssize_t cifs_security_flags_proc_write(struct file *file,
 			global_secflags = CIFSSEC_MAX;
 			return count;
 		} else if (!isdigit(c)) {
-			cERROR(1, "invalid flag %c", c);
+			cifs_dbg(VFS, "invalid flag %c\n", c);
 			return -EINVAL;
 		}
 	}
@@ -611,16 +628,16 @@ static ssize_t cifs_security_flags_proc_write(struct file *file,
 
 	flags = simple_strtoul(flags_string, NULL, 0);
 
-	cFYI(1, "sec flags 0x%x", flags);
+	cifs_dbg(FYI, "sec flags 0x%x\n", flags);
 
 	if (flags <= 0)  {
-		cERROR(1, "invalid security flags %s", flags_string);
+		cifs_dbg(VFS, "invalid security flags %s\n", flags_string);
 		return -EINVAL;
 	}
 
 	if (flags & ~CIFSSEC_MASK) {
-		cERROR(1, "attempt to set unsupported security flags 0x%x",
-			flags & ~CIFSSEC_MASK);
+		cifs_dbg(VFS, "attempt to set unsupported security flags 0x%x\n",
+			 flags & ~CIFSSEC_MASK);
 		return -EINVAL;
 	}
 	/* flags look ok - update the global security flags for cifs module */
@@ -628,9 +645,9 @@ static ssize_t cifs_security_flags_proc_write(struct file *file,
 	if (global_secflags & CIFSSEC_MUST_SIGN) {
 		/* requiring signing implies signing is allowed */
 		global_secflags |= CIFSSEC_MAY_SIGN;
-		cFYI(1, "packet signing now required");
+		cifs_dbg(FYI, "packet signing now required\n");
 	} else if ((global_secflags & CIFSSEC_MAY_SIGN) == 0) {
-		cFYI(1, "packet signing disabled");
+		cifs_dbg(FYI, "packet signing disabled\n");
 	}
 	/* BB should we turn on MAY flags for other MUST options? */
 	return count;
diff --git a/fs/cifs/cifs_debug.h b/fs/cifs/cifs_debug.h
index 69ae3d3..c99b40f 100644
--- a/fs/cifs/cifs_debug.h
+++ b/fs/cifs/cifs_debug.h
@@ -25,18 +25,20 @@
 void cifs_dump_mem(char *label, void *data, int length);
 void cifs_dump_detail(void *);
 void cifs_dump_mids(struct TCP_Server_Info *);
-#ifdef CONFIG_CIFS_DEBUG2
-#define DBG2 2
-#else
-#define DBG2 0
-#endif
 extern int traceSMB;		/* flag which enables the function below */
 void dump_smb(void *, int);
 #define CIFS_INFO	0x01
 #define CIFS_RC		0x02
 #define CIFS_TIMER	0x04
 
+#define VFS 1
+#define FYI 2
 extern int cifsFYI;
+#ifdef CONFIG_CIFS_DEBUG2
+#define NOISY 4
+#else
+#define NOISY 0
+#endif
 
 /*
  *	debug ON
@@ -44,31 +46,21 @@ extern int cifsFYI;
  */
 #ifdef CONFIG_CIFS_DEBUG
 
-/* information message: e.g., configuration, major event */
-#define cifsfyi(fmt, ...)						\
-do {									\
-	if (cifsFYI & CIFS_INFO)					\
-		printk(KERN_DEBUG "%s: " fmt "\n",			\
-		       __FILE__, ##__VA_ARGS__);			\
-} while (0)
-
-#define cFYI(set, fmt, ...)						\
-do {									\
-	if (set)							\
-		cifsfyi(fmt, ##__VA_ARGS__);				\
-} while (0)
+__printf(1, 2) void cifs_vfs_err(const char *fmt, ...);
 
-#define cifswarn(fmt, ...)						\
-	printk(KERN_WARNING fmt "\n", ##__VA_ARGS__)
-
-/* error event message: e.g., i/o error */
-#define cifserror(fmt, ...)						\
-	printk(KERN_ERR "CIFS VFS: " fmt "\n", ##__VA_ARGS__);		\
-
-#define cERROR(set, fmt, ...)						\
+/* information message: e.g., configuration, major event */
+#define cifs_dbg(type, fmt, ...)					\
 do {									\
-	if (set)							\
-		cifserror(fmt, ##__VA_ARGS__);				\
+	if (type == FYI) {						\
+		if (cifsFYI & CIFS_INFO) {				\
+			printk(KERN_DEBUG "%s: " fmt,			\
+			       __FILE__, ##__VA_ARGS__);		\
+		}							\
+	} else if (type == VFS) {					\
+		cifs_vfs_err(fmt, ##__VA_ARGS__);			\
+	} else if (type == NOISY && type != 0) {			\
+		printk(KERN_DEBUG fmt, ##__VA_ARGS__);			\
+	}								\
 } while (0)
 
 /*
@@ -76,27 +68,11 @@ do {									\
  *	---------
  */
 #else		/* _CIFS_DEBUG */
-#define cifsfyi(fmt, ...)						\
+#define cifs_dbg(type, fmt, ...)					\
 do {									\
 	if (0)								\
-		printk(KERN_DEBUG "%s: " fmt "\n",			\
-		       __FILE__, ##__VA_ARGS__);			\
+		printk(KERN_DEBUG fmt, ##__VA_ARGS__);			\
 } while (0)
-#define cFYI(set, fmt, ...)						\
-do {									\
-	if (0 && set)							\
-		cifsfyi(fmt, ##__VA_ARGS__);				\
-} while (0)
-#define cifserror(fmt, ...)						\
-do {									\
-	if (0)								\
-		printk(KERN_ERR "CIFS VFS: " fmt "\n", ##__VA_ARGS__);	\
-} while (0)
-#define cERROR(set, fmt, ...)						\
-do {									\
-	if (0 && set)							\
-		cifserror(fmt, ##__VA_ARGS__);				\
-} while (0)
-#endif		/* _CIFS_DEBUG */
+#endif
 
 #endif				/* _H_CIFS_DEBUG */
diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c
index 210fce2..8e33ec6 100644
--- a/fs/cifs/cifs_dfs_ref.c
+++ b/fs/cifs/cifs_dfs_ref.c
@@ -84,8 +84,8 @@ static char *cifs_get_share_name(const char *node_name)
 	/* find server name end */
 	pSep = memchr(UNC+2, '\\', len-2);
 	if (!pSep) {
-		cERROR(1, "%s: no server name end in node name: %s",
-			__func__, node_name);
+		cifs_dbg(VFS, "%s: no server name end in node name: %s\n",
+			 __func__, node_name);
 		kfree(UNC);
 		return ERR_PTR(-EINVAL);
 	}
@@ -141,8 +141,8 @@ char *cifs_compose_mount_options(const char *sb_mountdata,
 
 	rc = dns_resolve_server_name_to_ip(*devname, &srvIP);
 	if (rc < 0) {
-		cFYI(1, "%s: Failed to resolve server part of %s to IP: %d",
-			__func__, *devname, rc);
+		cifs_dbg(FYI, "%s: Failed to resolve server part of %s to IP: %d\n",
+			 __func__, *devname, rc);
 		goto compose_mount_options_err;
 	}
 
@@ -216,8 +216,8 @@ char *cifs_compose_mount_options(const char *sb_mountdata,
 		strcat(mountdata, fullpath + ref->path_consumed);
 	}
 
-	/*cFYI(1, "%s: parent mountdata: %s", __func__,sb_mountdata);*/
-	/*cFYI(1, "%s: submount mountdata: %s", __func__, mountdata );*/
+	/*cifs_dbg(FYI, "%s: parent mountdata: %s\n", __func__, sb_mountdata);*/
+	/*cifs_dbg(FYI, "%s: submount mountdata: %s\n", __func__, mountdata );*/
 
 compose_mount_options_out:
 	kfree(srvIP);
@@ -260,11 +260,12 @@ static struct vfsmount *cifs_dfs_do_refmount(struct cifs_sb_info *cifs_sb,
 
 static void dump_referral(const struct dfs_info3_param *ref)
 {
-	cFYI(1, "DFS: ref path: %s", ref->path_name);
-	cFYI(1, "DFS: node path: %s", ref->node_name);
-	cFYI(1, "DFS: fl: %hd, srv_type: %hd", ref->flags, ref->server_type);
-	cFYI(1, "DFS: ref_flags: %hd, path_consumed: %hd", ref->ref_flag,
-				ref->path_consumed);
+	cifs_dbg(FYI, "DFS: ref path: %s\n", ref->path_name);
+	cifs_dbg(FYI, "DFS: node path: %s\n", ref->node_name);
+	cifs_dbg(FYI, "DFS: fl: %hd, srv_type: %hd\n",
+		 ref->flags, ref->server_type);
+	cifs_dbg(FYI, "DFS: ref_flags: %hd, path_consumed: %hd\n",
+		 ref->ref_flag, ref->path_consumed);
 }
 
 /*
@@ -283,7 +284,7 @@ static struct vfsmount *cifs_dfs_do_automount(struct dentry *mntpt)
 	struct vfsmount *mnt;
 	struct tcon_link *tlink;
 
-	cFYI(1, "in %s", __func__);
+	cifs_dbg(FYI, "in %s\n", __func__);
 	BUG_ON(IS_ROOT(mntpt));
 
 	/*
@@ -320,15 +321,15 @@ static struct vfsmount *cifs_dfs_do_automount(struct dentry *mntpt)
 		/* connect to a node */
 		len = strlen(referrals[i].node_name);
 		if (len < 2) {
-			cERROR(1, "%s: Net Address path too short: %s",
-					__func__, referrals[i].node_name);
+			cifs_dbg(VFS, "%s: Net Address path too short: %s\n",
+				 __func__, referrals[i].node_name);
 			mnt = ERR_PTR(-EINVAL);
 			break;
 		}
 		mnt = cifs_dfs_do_refmount(cifs_sb,
 				full_path, referrals + i);
-		cFYI(1, "%s: cifs_dfs_do_refmount:%s , mnt:%p", __func__,
-					referrals[i].node_name, mnt);
+		cifs_dbg(FYI, "%s: cifs_dfs_do_refmount:%s , mnt:%p\n",
+			 __func__, referrals[i].node_name, mnt);
 		if (!IS_ERR(mnt))
 			goto success;
 	}
@@ -343,7 +344,7 @@ success:
 free_full_path:
 	kfree(full_path);
 cdda_exit:
-	cFYI(1, "leaving %s" , __func__);
+	cifs_dbg(FYI, "leaving %s\n" , __func__);
 	return mnt;
 }
 
@@ -354,11 +355,11 @@ struct vfsmount *cifs_dfs_d_automount(struct path *path)
 {
 	struct vfsmount *newmnt;
 
-	cFYI(1, "in %s", __func__);
+	cifs_dbg(FYI, "in %s\n", __func__);
 
 	newmnt = cifs_dfs_do_automount(path->dentry);
 	if (IS_ERR(newmnt)) {
-		cFYI(1, "leaving %s [automount failed]" , __func__);
+		cifs_dbg(FYI, "leaving %s [automount failed]\n" , __func__);
 		return newmnt;
 	}
 
@@ -366,7 +367,7 @@ struct vfsmount *cifs_dfs_d_automount(struct path *path)
 	mnt_set_expiry(newmnt, &cifs_dfs_automount_list);
 	schedule_delayed_work(&cifs_dfs_automount_task,
 			      cifs_dfs_mountpoint_expiry_timeout);
-	cFYI(1, "leaving %s [ok]" , __func__);
+	cifs_dbg(FYI, "leaving %s [ok]\n" , __func__);
 	return newmnt;
 }
 
diff --git a/fs/cifs/cifs_spnego.c b/fs/cifs/cifs_spnego.c
index 10e7747..a3e9325 100644
--- a/fs/cifs/cifs_spnego.c
+++ b/fs/cifs/cifs_spnego.c
@@ -37,12 +37,11 @@ cifs_spnego_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
 	int ret;
 
 	ret = -ENOMEM;
-	payload = kmalloc(prep->datalen, GFP_KERNEL);
+	payload = kmemdup(prep->data, prep->datalen, GFP_KERNEL);
 	if (!payload)
 		goto error;
 
 	/* attach the data */
-	memcpy(payload, prep->data, prep->datalen);
 	key->payload.data = payload;
 	ret = 0;
 
@@ -164,7 +163,7 @@ cifs_get_spnego_key(struct cifs_ses *sesInfo)
 	dp = description + strlen(description);
 	sprintf(dp, ";pid=0x%x", current->pid);
 
-	cFYI(1, "key description = %s", description);
+	cifs_dbg(FYI, "key description = %s\n", description);
 	spnego_key = request_key(&cifs_spnego_key_type, description, "");
 
 #ifdef CONFIG_CIFS_DEBUG2
diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c
index 71d5d0a..0227b45 100644
--- a/fs/cifs/cifs_unicode.c
+++ b/fs/cifs/cifs_unicode.c
@@ -227,8 +227,8 @@ cifs_strtoUTF16(__le16 *to, const char *from, int len,
 	for (i = 0; len && *from; i++, from += charlen, len -= charlen) {
 		charlen = codepage->char2uni(from, len, &wchar_to);
 		if (charlen < 1) {
-			cERROR(1, "strtoUTF16: char2uni of 0x%x returned %d",
-				*from, charlen);
+			cifs_dbg(VFS, "strtoUTF16: char2uni of 0x%x returned %d\n",
+				 *from, charlen);
 			/* A question mark */
 			wchar_to = 0x003f;
 			charlen = 1;
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c
index f1e3f25..51f5e0e 100644
--- a/fs/cifs/cifsacl.c
+++ b/fs/cifs/cifsacl.c
@@ -63,11 +63,10 @@ cifs_idmap_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
 		key->datalen = prep->datalen;
 		return 0;
 	}
-	payload = kmalloc(prep->datalen, GFP_KERNEL);
+	payload = kmemdup(prep->data, prep->datalen, GFP_KERNEL);
 	if (!payload)
 		return -ENOMEM;
 
-	memcpy(payload, prep->data, prep->datalen);
 	key->payload.data = payload;
 	key->datalen = prep->datalen;
 	return 0;
@@ -219,13 +218,13 @@ id_to_sid(unsigned int cid, uint sidtype, struct cifs_sid *ssid)
 	sidkey = request_key(&cifs_idmap_key_type, desc, "");
 	if (IS_ERR(sidkey)) {
 		rc = -EINVAL;
-		cFYI(1, "%s: Can't map %cid %u to a SID", __func__,
-			sidtype == SIDOWNER ? 'u' : 'g', cid);
+		cifs_dbg(FYI, "%s: Can't map %cid %u to a SID\n",
+			 __func__, sidtype == SIDOWNER ? 'u' : 'g', cid);
 		goto out_revert_creds;
 	} else if (sidkey->datalen < CIFS_SID_BASE_SIZE) {
 		rc = -EIO;
-		cFYI(1, "%s: Downcall contained malformed key "
-			"(datalen=%hu)", __func__, sidkey->datalen);
+		cifs_dbg(FYI, "%s: Downcall contained malformed key (datalen=%hu)\n",
+			 __func__, sidkey->datalen);
 		goto invalidate_key;
 	}
 
@@ -241,8 +240,8 @@ id_to_sid(unsigned int cid, uint sidtype, struct cifs_sid *ssid)
 	ksid_size = CIFS_SID_BASE_SIZE + (ksid->num_subauth * sizeof(__le32));
 	if (ksid_size > sidkey->datalen) {
 		rc = -EIO;
-		cFYI(1, "%s: Downcall contained malformed key (datalen=%hu, "
-			"ksid_size=%u)", __func__, sidkey->datalen, ksid_size);
+		cifs_dbg(FYI, "%s: Downcall contained malformed key (datalen=%hu, ksid_size=%u)\n",
+			 __func__, sidkey->datalen, ksid_size);
 		goto invalidate_key;
 	}
 
@@ -274,8 +273,8 @@ sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,
 	 * Just return an error.
 	 */
 	if (unlikely(psid->num_subauth > SID_MAX_SUB_AUTHORITIES)) {
-		cFYI(1, "%s: %u subauthorities is too many!", __func__,
-			psid->num_subauth);
+		cifs_dbg(FYI, "%s: %u subauthorities is too many!\n",
+			 __func__, psid->num_subauth);
 		return -EIO;
 	}
 
@@ -287,8 +286,8 @@ sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,
 	sidkey = request_key(&cifs_idmap_key_type, sidstr, "");
 	if (IS_ERR(sidkey)) {
 		rc = -EINVAL;
-		cFYI(1, "%s: Can't map SID %s to a %cid", __func__, sidstr,
-			sidtype == SIDOWNER ? 'u' : 'g');
+		cifs_dbg(FYI, "%s: Can't map SID %s to a %cid\n",
+			 __func__, sidstr, sidtype == SIDOWNER ? 'u' : 'g');
 		goto out_revert_creds;
 	}
 
@@ -300,8 +299,8 @@ sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,
 	BUILD_BUG_ON(sizeof(uid_t) != sizeof(gid_t));
 	if (sidkey->datalen != sizeof(uid_t)) {
 		rc = -EIO;
-		cFYI(1, "%s: Downcall contained malformed key "
-			"(datalen=%hu)", __func__, sidkey->datalen);
+		cifs_dbg(FYI, "%s: Downcall contained malformed key (datalen=%hu)\n",
+			 __func__, sidkey->datalen);
 		key_invalidate(sidkey);
 		goto out_key_put;
 	}
@@ -346,7 +345,8 @@ init_cifs_idmap(void)
 	struct key *keyring;
 	int ret;
 
-	cFYI(1, "Registering the %s key type", cifs_idmap_key_type.name);
+	cifs_dbg(FYI, "Registering the %s key type\n",
+		 cifs_idmap_key_type.name);
 
 	/* create an override credential set with a special thread keyring in
 	 * which requests are cached
@@ -379,7 +379,7 @@ init_cifs_idmap(void)
 	cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;
 	root_cred = cred;
 
-	cFYI(1, "cifs idmap keyring: %d", key_serial(keyring));
+	cifs_dbg(FYI, "cifs idmap keyring: %d\n", key_serial(keyring));
 	return 0;
 
 failed_put_key:
@@ -395,7 +395,7 @@ exit_cifs_idmap(void)
 	key_revoke(root_cred->thread_keyring);
 	unregister_key_type(&cifs_idmap_key_type);
 	put_cred(root_cred);
-	cFYI(1, "Unregistered %s key type", cifs_idmap_key_type.name);
+	cifs_dbg(FYI, "Unregistered %s key type\n", cifs_idmap_key_type.name);
 }
 
 /* copy ntsd, owner sid, and group sid from a security descriptor to another */
@@ -462,14 +462,14 @@ static void access_flags_to_mode(__le32 ace_flags, int type, umode_t *pmode,
 			*pbits_to_set &= ~S_IXUGO;
 		return;
 	} else if (type != ACCESS_ALLOWED) {
-		cERROR(1, "unknown access control type %d", type);
+		cifs_dbg(VFS, "unknown access control type %d\n", type);
 		return;
 	}
 	/* else ACCESS_ALLOWED type */
 
 	if (flags & GENERIC_ALL) {
 		*pmode |= (S_IRWXUGO & (*pbits_to_set));
-		cFYI(DBG2, "all perms");
+		cifs_dbg(NOISY, "all perms\n");
 		return;
 	}
 	if ((flags & GENERIC_WRITE) ||
@@ -482,7 +482,7 @@ static void access_flags_to_mode(__le32 ace_flags, int type, umode_t *pmode,
 			((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS))
 		*pmode |= (S_IXUGO & (*pbits_to_set));
 
-	cFYI(DBG2, "access flags 0x%x mode now 0x%x", flags, *pmode);
+	cifs_dbg(NOISY, "access flags 0x%x mode now 0x%x\n", flags, *pmode);
 	return;
 }
 
@@ -511,7 +511,8 @@ static void mode_to_access_flags(umode_t mode, umode_t bits_to_use,
 	if (mode & S_IXUGO)
 		*pace_flags |= SET_FILE_EXEC_RIGHTS;
 
-	cFYI(DBG2, "mode: 0x%x, access flags now 0x%x", mode, *pace_flags);
+	cifs_dbg(NOISY, "mode: 0x%x, access flags now 0x%x\n",
+		 mode, *pace_flags);
 	return;
 }
 
@@ -551,24 +552,24 @@ static void dump_ace(struct cifs_ace *pace, char *end_of_acl)
 	/* validate that we do not go past end of acl */
 
 	if (le16_to_cpu(pace->size) < 16) {
-		cERROR(1, "ACE too small %d", le16_to_cpu(pace->size));
+		cifs_dbg(VFS, "ACE too small %d\n", le16_to_cpu(pace->size));
 		return;
 	}
 
 	if (end_of_acl < (char *)pace + le16_to_cpu(pace->size)) {
-		cERROR(1, "ACL too small to parse ACE");
+		cifs_dbg(VFS, "ACL too small to parse ACE\n");
 		return;
 	}
 
 	num_subauth = pace->sid.num_subauth;
 	if (num_subauth) {
 		int i;
-		cFYI(1, "ACE revision %d num_auth %d type %d flags %d size %d",
-			pace->sid.revision, pace->sid.num_subauth, pace->type,
-			pace->flags, le16_to_cpu(pace->size));
+		cifs_dbg(FYI, "ACE revision %d num_auth %d type %d flags %d size %d\n",
+			 pace->sid.revision, pace->sid.num_subauth, pace->type,
+			 pace->flags, le16_to_cpu(pace->size));
 		for (i = 0; i < num_subauth; ++i) {
-			cFYI(1, "ACE sub_auth[%d]: 0x%x", i,
-				le32_to_cpu(pace->sid.sub_auth[i]));
+			cifs_dbg(FYI, "ACE sub_auth[%d]: 0x%x\n",
+				 i, le32_to_cpu(pace->sid.sub_auth[i]));
 		}
 
 		/* BB add length check to make sure that we do not have huge
@@ -601,13 +602,13 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
 
 	/* validate that we do not go past end of acl */
 	if (end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size)) {
-		cERROR(1, "ACL too small to parse DACL");
+		cifs_dbg(VFS, "ACL too small to parse DACL\n");
 		return;
 	}
 
-	cFYI(DBG2, "DACL revision %d size %d num aces %d",
-		le16_to_cpu(pdacl->revision), le16_to_cpu(pdacl->size),
-		le32_to_cpu(pdacl->num_aces));
+	cifs_dbg(NOISY, "DACL revision %d size %d num aces %d\n",
+		 le16_to_cpu(pdacl->revision), le16_to_cpu(pdacl->size),
+		 le32_to_cpu(pdacl->num_aces));
 
 	/* reset rwx permissions for user/group/other.
 	   Also, if num_aces is 0 i.e. DACL has no ACEs,
@@ -627,10 +628,8 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
 			return;
 		ppace = kmalloc(num_aces * sizeof(struct cifs_ace *),
 				GFP_KERNEL);
-		if (!ppace) {
-			cERROR(1, "DACL memory allocation error");
+		if (!ppace)
 			return;
-		}
 
 		for (i = 0; i < num_aces; ++i) {
 			ppace[i] = (struct cifs_ace *) (acl_base + acl_size);
@@ -703,25 +702,25 @@ static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
 	/* validate that we do not go past end of ACL - sid must be at least 8
 	   bytes long (assuming no sub-auths - e.g. the null SID */
 	if (end_of_acl < (char *)psid + 8) {
-		cERROR(1, "ACL too small to parse SID %p", psid);
+		cifs_dbg(VFS, "ACL too small to parse SID %p\n", psid);
 		return -EINVAL;
 	}
 
 #ifdef CONFIG_CIFS_DEBUG2
 	if (psid->num_subauth) {
 		int i;
-		cFYI(1, "SID revision %d num_auth %d",
-			psid->revision, psid->num_subauth);
+		cifs_dbg(FYI, "SID revision %d num_auth %d\n",
+			 psid->revision, psid->num_subauth);
 
 		for (i = 0; i < psid->num_subauth; i++) {
-			cFYI(1, "SID sub_auth[%d]: 0x%x ", i,
-				le32_to_cpu(psid->sub_auth[i]));
+			cifs_dbg(FYI, "SID sub_auth[%d]: 0x%x\n",
+				 i, le32_to_cpu(psid->sub_auth[i]));
 		}
 
 		/* BB add length check to make sure that we do not have huge
 			num auths and therefore go off the end */
-		cFYI(1, "RID 0x%x",
-			le32_to_cpu(psid->sub_auth[psid->num_subauth-1]));
+		cifs_dbg(FYI, "RID 0x%x\n",
+			 le32_to_cpu(psid->sub_auth[psid->num_subauth-1]));
 	}
 #endif
 
@@ -748,31 +747,33 @@ static int parse_sec_desc(struct cifs_sb_info *cifs_sb,
 				le32_to_cpu(pntsd->gsidoffset));
 	dacloffset = le32_to_cpu(pntsd->dacloffset);
 	dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
-	cFYI(DBG2, "revision %d type 0x%x ooffset 0x%x goffset 0x%x "
-		 "sacloffset 0x%x dacloffset 0x%x",
+	cifs_dbg(NOISY, "revision %d type 0x%x ooffset 0x%x goffset 0x%x sacloffset 0x%x dacloffset 0x%x\n",
 		 pntsd->revision, pntsd->type, le32_to_cpu(pntsd->osidoffset),
 		 le32_to_cpu(pntsd->gsidoffset),
 		 le32_to_cpu(pntsd->sacloffset), dacloffset);
 /*	cifs_dump_mem("owner_sid: ", owner_sid_ptr, 64); */
 	rc = parse_sid(owner_sid_ptr, end_of_acl);
 	if (rc) {
-		cFYI(1, "%s: Error %d parsing Owner SID", __func__, rc);
+		cifs_dbg(FYI, "%s: Error %d parsing Owner SID\n", __func__, rc);
 		return rc;
 	}
 	rc = sid_to_id(cifs_sb, owner_sid_ptr, fattr, SIDOWNER);
 	if (rc) {
-		cFYI(1, "%s: Error %d mapping Owner SID to uid", __func__, rc);
+		cifs_dbg(FYI, "%s: Error %d mapping Owner SID to uid\n",
+			 __func__, rc);
 		return rc;
 	}
 
 	rc = parse_sid(group_sid_ptr, end_of_acl);
 	if (rc) {
-		cFYI(1, "%s: Error %d mapping Owner SID to gid", __func__, rc);
+		cifs_dbg(FYI, "%s: Error %d mapping Owner SID to gid\n",
+			 __func__, rc);
 		return rc;
 	}
 	rc = sid_to_id(cifs_sb, group_sid_ptr, fattr, SIDGROUP);
 	if (rc) {
-		cFYI(1, "%s: Error %d mapping Group SID to gid", __func__, rc);
+		cifs_dbg(FYI, "%s: Error %d mapping Group SID to gid\n",
+			 __func__, rc);
 		return rc;
 	}
 
@@ -780,7 +781,7 @@ static int parse_sec_desc(struct cifs_sb_info *cifs_sb,
 		parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr,
 			   group_sid_ptr, fattr);
 	else
-		cFYI(1, "no ACL"); /* BB grant all or default perms? */
+		cifs_dbg(FYI, "no ACL\n"); /* BB grant all or default perms? */
 
 	return rc;
 }
@@ -830,8 +831,8 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
 			id = from_kuid(&init_user_ns, uid);
 			rc = id_to_sid(id, SIDOWNER, nowner_sid_ptr);
 			if (rc) {
-				cFYI(1, "%s: Mapping error %d for owner id %d",
-						__func__, rc, id);
+				cifs_dbg(FYI, "%s: Mapping error %d for owner id %d\n",
+					 __func__, rc, id);
 				kfree(nowner_sid_ptr);
 				return rc;
 			}
@@ -850,8 +851,8 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
 			id = from_kgid(&init_user_ns, gid);
 			rc = id_to_sid(id, SIDGROUP, ngroup_sid_ptr);
 			if (rc) {
-				cFYI(1, "%s: Mapping error %d for group id %d",
-						__func__, rc, id);
+				cifs_dbg(FYI, "%s: Mapping error %d for group id %d\n",
+					 __func__, rc, id);
 				kfree(ngroup_sid_ptr);
 				return rc;
 			}
@@ -881,7 +882,7 @@ static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
 
 	cifs_put_tlink(tlink);
 
-	cFYI(1, "%s: rc = %d ACL len %d", __func__, rc, *pacllen);
+	cifs_dbg(FYI, "%s: rc = %d ACL len %d\n", __func__, rc, *pacllen);
 	if (rc)
 		return ERR_PTR(rc);
 	return pntsd;
@@ -918,7 +919,7 @@ static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
 	cifs_put_tlink(tlink);
 	free_xid(xid);
 
-	cFYI(1, "%s: rc = %d ACL len %d", __func__, rc, *pacllen);
+	cifs_dbg(FYI, "%s: rc = %d ACL len %d\n", __func__, rc, *pacllen);
 	if (rc)
 		return ERR_PTR(rc);
 	return pntsd;
@@ -972,12 +973,12 @@ int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
 			create_options, &fid, &oplock, NULL, cifs_sb->local_nls,
 			cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
 	if (rc) {
-		cERROR(1, "Unable to open file to set ACL");
+		cifs_dbg(VFS, "Unable to open file to set ACL\n");
 		goto out;
 	}
 
 	rc = CIFSSMBSetCIFSACL(xid, tcon, fid, pnntsd, acllen, aclflag);
-	cFYI(DBG2, "SetCIFSACL rc = %d", rc);
+	cifs_dbg(NOISY, "SetCIFSACL rc = %d\n", rc);
 
 	CIFSSMBClose(xid, tcon, fid);
 out:
@@ -995,7 +996,7 @@ cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
 	u32 acllen = 0;
 	int rc = 0;
 
-	cFYI(DBG2, "converting ACL to mode for %s", path);
+	cifs_dbg(NOISY, "converting ACL to mode for %s\n", path);
 
 	if (pfid)
 		pntsd = get_cifs_acl_by_fid(cifs_sb, *pfid, &acllen);
@@ -1005,12 +1006,12 @@ cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
 	/* if we can retrieve the ACL, now parse Access Control Entries, ACEs */
 	if (IS_ERR(pntsd)) {
 		rc = PTR_ERR(pntsd);
-		cERROR(1, "%s: error %d getting sec desc", __func__, rc);
+		cifs_dbg(VFS, "%s: error %d getting sec desc\n", __func__, rc);
 	} else {
 		rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr);
 		kfree(pntsd);
 		if (rc)
-			cERROR(1, "parse sec desc failed rc = %d", rc);
+			cifs_dbg(VFS, "parse sec desc failed rc = %d\n", rc);
 	}
 
 	return rc;
@@ -1027,13 +1028,13 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode,
 	struct cifs_ntsd *pntsd = NULL; /* acl obtained from server */
 	struct cifs_ntsd *pnntsd = NULL; /* modified acl to be sent to server */
 
-	cFYI(DBG2, "set ACL from mode for %s", path);
+	cifs_dbg(NOISY, "set ACL from mode for %s\n", path);
 
 	/* Get the security descriptor */
 	pntsd = get_cifs_acl(CIFS_SB(inode->i_sb), inode, path, &secdesclen);
 	if (IS_ERR(pntsd)) {
 		rc = PTR_ERR(pntsd);
-		cERROR(1, "%s: error %d getting sec desc", __func__, rc);
+		cifs_dbg(VFS, "%s: error %d getting sec desc\n", __func__, rc);
 		goto out;
 	}
 
@@ -1046,7 +1047,6 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode,
 	secdesclen = max_t(u32, secdesclen, DEFAULT_SEC_DESC_LEN);
 	pnntsd = kmalloc(secdesclen, GFP_KERNEL);
 	if (!pnntsd) {
-		cERROR(1, "Unable to allocate security descriptor");
 		kfree(pntsd);
 		return -ENOMEM;
 	}
@@ -1054,12 +1054,12 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode,
 	rc = build_sec_desc(pntsd, pnntsd, secdesclen, nmode, uid, gid,
 				&aclflag);
 
-	cFYI(DBG2, "build_sec_desc rc: %d", rc);
+	cifs_dbg(NOISY, "build_sec_desc rc: %d\n", rc);
 
 	if (!rc) {
 		/* Set the security descriptor */
 		rc = set_cifs_acl(pnntsd, secdesclen, inode, path, aclflag);
-		cFYI(DBG2, "set_cifs_acl rc: %d", rc);
+		cifs_dbg(NOISY, "set_cifs_acl rc: %d\n", rc);
 	}
 
 	kfree(pnntsd);
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index 652f505..71436d1 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -50,20 +50,20 @@ static int cifs_calc_signature(struct smb_rqst *rqst,
 		return -EINVAL;
 
 	if (!server->secmech.sdescmd5) {
-		cERROR(1, "%s: Can't generate signature", __func__);
+		cifs_dbg(VFS, "%s: Can't generate signature\n", __func__);
 		return -1;
 	}
 
 	rc = crypto_shash_init(&server->secmech.sdescmd5->shash);
 	if (rc) {
-		cERROR(1, "%s: Could not init md5", __func__);
+		cifs_dbg(VFS, "%s: Could not init md5\n", __func__);
 		return rc;
 	}
 
 	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", __func__);
+		cifs_dbg(VFS, "%s: Could not update with response\n", __func__);
 		return rc;
 	}
 
@@ -71,7 +71,7 @@ static int cifs_calc_signature(struct smb_rqst *rqst,
 		if (iov[i].iov_len == 0)
 			continue;
 		if (iov[i].iov_base == NULL) {
-			cERROR(1, "null iovec entry");
+			cifs_dbg(VFS, "null iovec entry\n");
 			return -EIO;
 		}
 		/* The first entry includes a length field (which does not get
@@ -88,8 +88,8 @@ static int cifs_calc_signature(struct smb_rqst *rqst,
 				iov[i].iov_base, iov[i].iov_len);
 		}
 		if (rc) {
-			cERROR(1, "%s: Could not update with payload",
-							__func__);
+			cifs_dbg(VFS, "%s: Could not update with payload\n",
+				 __func__);
 			return rc;
 		}
 	}
@@ -106,7 +106,7 @@ static int cifs_calc_signature(struct smb_rqst *rqst,
 
 	rc = crypto_shash_final(&server->secmech.sdescmd5->shash, signature);
 	if (rc)
-		cERROR(1, "%s: Could not generate md5 hash", __func__);
+		cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__);
 
 	return rc;
 }
@@ -135,8 +135,8 @@ int cifs_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server,
 				cpu_to_le32(server->sequence_number);
 	cifs_pdu->Signature.Sequence.Reserved = 0;
 
-	*pexpected_response_sequence_number = server->sequence_number++;
-	server->sequence_number++;
+	*pexpected_response_sequence_number = ++server->sequence_number;
+	++server->sequence_number;
 
 	rc = cifs_calc_signature(rqst, server, smb_signature);
 	if (rc)
@@ -196,8 +196,8 @@ int cifs_verify_signature(struct smb_rqst *rqst,
 
 	/* Do not need to verify session setups with signature "BSRSPYL "  */
 	if (memcmp(cifs_pdu->Signature.SecuritySignature, "BSRSPYL ", 8) == 0)
-		cFYI(1, "dummy signature received for smb command 0x%x",
-			cifs_pdu->Command);
+		cifs_dbg(FYI, "dummy signature received for smb command 0x%x\n",
+			 cifs_pdu->Command);
 
 	/* save off the origiginal signature so we can modify the smb and check
 		its signature against what the server sent */
@@ -235,30 +235,30 @@ int setup_ntlm_response(struct cifs_ses *ses, const struct nls_table *nls_cp)
 		return -EINVAL;
 
 	ses->auth_key.response = kmalloc(temp_len, GFP_KERNEL);
-	if (!ses->auth_key.response) {
-		cERROR(1, "NTLM can't allocate (%u bytes) memory", temp_len);
+	if (!ses->auth_key.response)
 		return -ENOMEM;
-	}
+
 	ses->auth_key.len = temp_len;
 
 	rc = SMBNTencrypt(ses->password, ses->server->cryptkey,
 			ses->auth_key.response + CIFS_SESS_KEY_SIZE, nls_cp);
 	if (rc) {
-		cFYI(1, "%s Can't generate NTLM response, error: %d",
-			__func__, rc);
+		cifs_dbg(FYI, "%s Can't generate NTLM response, error: %d\n",
+			 __func__, rc);
 		return rc;
 	}
 
 	rc = E_md4hash(ses->password, temp_key, nls_cp);
 	if (rc) {
-		cFYI(1, "%s Can't generate NT hash, error: %d", __func__, rc);
+		cifs_dbg(FYI, "%s Can't generate NT hash, error: %d\n",
+			 __func__, rc);
 		return rc;
 	}
 
 	rc = mdfour(ses->auth_key.response, temp_key, CIFS_SESS_KEY_SIZE);
 	if (rc)
-		cFYI(1, "%s Can't generate NTLM session key, error: %d",
-			__func__, rc);
+		cifs_dbg(FYI, "%s Can't generate NTLM session key, error: %d\n",
+			 __func__, rc);
 
 	return rc;
 }
@@ -334,7 +334,6 @@ build_avpair_blob(struct cifs_ses *ses, const struct nls_table *nls_cp)
 	ses->auth_key.response = kzalloc(ses->auth_key.len, GFP_KERNEL);
 	if (!ses->auth_key.response) {
 		ses->auth_key.len = 0;
-		cERROR(1, "Challenge target info allocation failure");
 		return -ENOMEM;
 	}
 
@@ -420,7 +419,7 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
 	wchar_t *server;
 
 	if (!ses->server->secmech.sdeschmacmd5) {
-		cERROR(1, "calc_ntlmv2_hash: can't generate ntlmv2 hash");
+		cifs_dbg(VFS, "%s: can't generate ntlmv2 hash\n", __func__);
 		return -1;
 	}
 
@@ -430,13 +429,13 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_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__);
+		cifs_dbg(VFS, "%s: Could not set NT Hash as a key\n", __func__);
 		return rc;
 	}
 
 	rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash);
 	if (rc) {
-		cERROR(1, "calc_ntlmv2_hash: could not init hmacmd5");
+		cifs_dbg(VFS, "%s: could not init hmacmd5\n", __func__);
 		return rc;
 	}
 
@@ -444,7 +443,6 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
 	len = ses->user_name ? strlen(ses->user_name) : 0;
 	user = kmalloc(2 + (len * 2), GFP_KERNEL);
 	if (user == NULL) {
-		cERROR(1, "calc_ntlmv2_hash: user mem alloc failure");
 		rc = -ENOMEM;
 		return rc;
 	}
@@ -460,7 +458,7 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
 				(char *)user, 2 * len);
 	kfree(user);
 	if (rc) {
-		cERROR(1, "%s: Could not update with user", __func__);
+		cifs_dbg(VFS, "%s: Could not update with user\n", __func__);
 		return rc;
 	}
 
@@ -470,7 +468,6 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
 
 		domain = kmalloc(2 + (len * 2), GFP_KERNEL);
 		if (domain == NULL) {
-			cERROR(1, "calc_ntlmv2_hash: domain mem alloc failure");
 			rc = -ENOMEM;
 			return rc;
 		}
@@ -481,8 +478,8 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
 					(char *)domain, 2 * len);
 		kfree(domain);
 		if (rc) {
-			cERROR(1, "%s: Could not update with domain",
-								__func__);
+			cifs_dbg(VFS, "%s: Could not update with domain\n",
+				 __func__);
 			return rc;
 		}
 	} else if (ses->serverName) {
@@ -490,7 +487,6 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
 
 		server = kmalloc(2 + (len * 2), GFP_KERNEL);
 		if (server == NULL) {
-			cERROR(1, "calc_ntlmv2_hash: server mem alloc failure");
 			rc = -ENOMEM;
 			return rc;
 		}
@@ -501,8 +497,8 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
 					(char *)server, 2 * len);
 		kfree(server);
 		if (rc) {
-			cERROR(1, "%s: Could not update with server",
-								__func__);
+			cifs_dbg(VFS, "%s: Could not update with server\n",
+				 __func__);
 			return rc;
 		}
 	}
@@ -510,7 +506,7 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
 	rc = crypto_shash_final(&ses->server->secmech.sdeschmacmd5->shash,
 					ntlmv2_hash);
 	if (rc)
-		cERROR(1, "%s: Could not generate md5 hash", __func__);
+		cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__);
 
 	return rc;
 }
@@ -522,20 +518,21 @@ CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash)
 	unsigned int offset = CIFS_SESS_KEY_SIZE + 8;
 
 	if (!ses->server->secmech.sdeschmacmd5) {
-		cERROR(1, "calc_ntlmv2_hash: can't generate ntlmv2 hash");
+		cifs_dbg(VFS, "%s: can't generate ntlmv2 hash\n", __func__);
 		return -1;
 	}
 
 	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__);
+		cifs_dbg(VFS, "%s: Could not set NTLMV2 Hash as a key\n",
+			 __func__);
 		return rc;
 	}
 
 	rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash);
 	if (rc) {
-		cERROR(1, "CalcNTLMv2_response: could not init hmacmd5");
+		cifs_dbg(VFS, "%s: could not init hmacmd5\n", __func__);
 		return rc;
 	}
 
@@ -548,14 +545,14 @@ CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash)
 	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", __func__);
+		cifs_dbg(VFS, "%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", __func__);
+		cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__);
 
 	return rc;
 }
@@ -575,14 +572,15 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
 		if (!ses->domainName) {
 			rc = find_domain_name(ses, nls_cp);
 			if (rc) {
-				cERROR(1, "error %d finding domain name", rc);
+				cifs_dbg(VFS, "error %d finding domain name\n",
+					 rc);
 				goto setup_ntlmv2_rsp_ret;
 			}
 		}
 	} else {
 		rc = build_avpair_blob(ses, nls_cp);
 		if (rc) {
-			cERROR(1, "error %d building av pair blob", rc);
+			cifs_dbg(VFS, "error %d building av pair blob\n", rc);
 			goto setup_ntlmv2_rsp_ret;
 		}
 	}
@@ -595,7 +593,6 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
 	if (!ses->auth_key.response) {
 		rc = ENOMEM;
 		ses->auth_key.len = 0;
-		cERROR(1, "%s: Can't allocate auth blob", __func__);
 		goto setup_ntlmv2_rsp_ret;
 	}
 	ses->auth_key.len += baselen;
@@ -613,14 +610,14 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
 	/* calculate ntlmv2_hash */
 	rc = calc_ntlmv2_hash(ses, ntlmv2_hash, nls_cp);
 	if (rc) {
-		cERROR(1, "could not get v2 hash rc %d", rc);
+		cifs_dbg(VFS, "could not get v2 hash rc %d\n", rc);
 		goto setup_ntlmv2_rsp_ret;
 	}
 
 	/* calculate first part of the client response (CR1) */
 	rc = CalcNTLMv2_response(ses, ntlmv2_hash);
 	if (rc) {
-		cERROR(1, "Could not calculate CR1  rc: %d", rc);
+		cifs_dbg(VFS, "Could not calculate CR1 rc: %d\n", rc);
 		goto setup_ntlmv2_rsp_ret;
 	}
 
@@ -628,13 +625,14 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
 	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__);
+		cifs_dbg(VFS, "%s: Could not set NTLMV2 Hash as a key\n",
+			 __func__);
 		goto setup_ntlmv2_rsp_ret;
 	}
 
 	rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash);
 	if (rc) {
-		cERROR(1, "%s: Could not init hmacmd5", __func__);
+		cifs_dbg(VFS, "%s: Could not init hmacmd5\n", __func__);
 		goto setup_ntlmv2_rsp_ret;
 	}
 
@@ -642,14 +640,14 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
 		ses->auth_key.response + CIFS_SESS_KEY_SIZE,
 		CIFS_HMAC_MD5_HASH_SIZE);
 	if (rc) {
-		cERROR(1, "%s: Could not update with response", __func__);
+		cifs_dbg(VFS, "%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", __func__);
+		cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__);
 
 setup_ntlmv2_rsp_ret:
 	kfree(tiblob);
@@ -671,7 +669,7 @@ calc_seckey(struct cifs_ses *ses)
 	tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC);
 	if (IS_ERR(tfm_arc4)) {
 		rc = PTR_ERR(tfm_arc4);
-		cERROR(1, "could not allocate crypto API arc4");
+		cifs_dbg(VFS, "could not allocate crypto API arc4\n");
 		return rc;
 	}
 
@@ -680,7 +678,8 @@ calc_seckey(struct cifs_ses *ses)
 	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__);
+		cifs_dbg(VFS, "%s: Could not set response as a key\n",
+			 __func__);
 		return rc;
 	}
 
@@ -689,7 +688,7 @@ calc_seckey(struct cifs_ses *ses)
 
 	rc = crypto_blkcipher_encrypt(&desc, &sgout, &sgin, CIFS_CPHTXT_SIZE);
 	if (rc) {
-		cERROR(1, "could not encrypt session key rc: %d", rc);
+		cifs_dbg(VFS, "could not encrypt session key rc: %d\n", rc);
 		crypto_free_blkcipher(tfm_arc4);
 		return rc;
 	}
@@ -731,20 +730,20 @@ cifs_crypto_shash_allocate(struct TCP_Server_Info *server)
 
 	server->secmech.hmacmd5 = crypto_alloc_shash("hmac(md5)", 0, 0);
 	if (IS_ERR(server->secmech.hmacmd5)) {
-		cERROR(1, "could not allocate crypto hmacmd5");
+		cifs_dbg(VFS, "could not allocate crypto hmacmd5\n");
 		return PTR_ERR(server->secmech.hmacmd5);
 	}
 
 	server->secmech.md5 = crypto_alloc_shash("md5", 0, 0);
 	if (IS_ERR(server->secmech.md5)) {
-		cERROR(1, "could not allocate crypto md5");
+		cifs_dbg(VFS, "could not allocate crypto md5\n");
 		rc = PTR_ERR(server->secmech.md5);
 		goto crypto_allocate_md5_fail;
 	}
 
 	server->secmech.hmacsha256 = crypto_alloc_shash("hmac(sha256)", 0, 0);
 	if (IS_ERR(server->secmech.hmacsha256)) {
-		cERROR(1, "could not allocate crypto hmacsha256\n");
+		cifs_dbg(VFS, "could not allocate crypto hmacsha256\n");
 		rc = PTR_ERR(server->secmech.hmacsha256);
 		goto crypto_allocate_hmacsha256_fail;
 	}
@@ -753,7 +752,6 @@ cifs_crypto_shash_allocate(struct TCP_Server_Info *server)
 			crypto_shash_descsize(server->secmech.hmacmd5);
 	server->secmech.sdeschmacmd5 = kmalloc(size, GFP_KERNEL);
 	if (!server->secmech.sdeschmacmd5) {
-		cERROR(1, "cifs_crypto_shash_allocate: can't alloc hmacmd5");
 		rc = -ENOMEM;
 		goto crypto_allocate_hmacmd5_sdesc_fail;
 	}
@@ -764,7 +762,6 @@ cifs_crypto_shash_allocate(struct TCP_Server_Info *server)
 			crypto_shash_descsize(server->secmech.md5);
 	server->secmech.sdescmd5 = kmalloc(size, GFP_KERNEL);
 	if (!server->secmech.sdescmd5) {
-		cERROR(1, "cifs_crypto_shash_allocate: can't alloc md5");
 		rc = -ENOMEM;
 		goto crypto_allocate_md5_sdesc_fail;
 	}
@@ -775,7 +772,6 @@ cifs_crypto_shash_allocate(struct TCP_Server_Info *server)
 			crypto_shash_descsize(server->secmech.hmacsha256);
 	server->secmech.sdeschmacsha256 = kmalloc(size, GFP_KERNEL);
 	if (!server->secmech.sdeschmacsha256) {
-		cERROR(1, "%s: Can't alloc hmacsha256\n", __func__);
 		rc = -ENOMEM;
 		goto crypto_allocate_hmacsha256_sdesc_fail;
 	}
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 345fc89..72e4efe 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -161,7 +161,7 @@ cifs_read_super(struct super_block *sb)
 
 #ifdef CONFIG_CIFS_NFSD_EXPORT
 	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
-		cFYI(1, "export ops supported");
+		cifs_dbg(FYI, "export ops supported\n");
 		sb->s_export_op = &cifs_export_ops;
 	}
 #endif /* CONFIG_CIFS_NFSD_EXPORT */
@@ -169,7 +169,7 @@ cifs_read_super(struct super_block *sb)
 	return 0;
 
 out_no_root:
-	cERROR(1, "cifs_read_super: get root inode failed");
+	cifs_dbg(VFS, "%s: get root inode failed\n", __func__);
 	return rc;
 }
 
@@ -502,7 +502,7 @@ static void cifs_umount_begin(struct super_block *sb)
 	/* cancel_brl_requests(tcon); */ /* BB mark all brl mids as exiting */
 	/* cancel_notify_requests(tcon); */
 	if (tcon->ses && tcon->ses->server) {
-		cFYI(1, "wake up tasks now - umount begin not complete");
+		cifs_dbg(FYI, "wake up tasks now - umount begin not complete\n");
 		wake_up_all(&tcon->ses->server->request_q);
 		wake_up_all(&tcon->ses->server->response_q);
 		msleep(1); /* yield */
@@ -573,7 +573,7 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb)
 	if (full_path == NULL)
 		return ERR_PTR(-ENOMEM);
 
-	cFYI(1, "Get root dentry for %s", full_path);
+	cifs_dbg(FYI, "Get root dentry for %s\n", full_path);
 
 	sep = CIFS_DIR_SEP(cifs_sb);
 	dentry = dget(sb->s_root);
@@ -632,7 +632,7 @@ cifs_do_mount(struct file_system_type *fs_type,
 	struct cifs_mnt_data mnt_data;
 	struct dentry *root;
 
-	cFYI(1, "Devname: %s flags: %d ", dev_name, flags);
+	cifs_dbg(FYI, "Devname: %s flags: %d\n", dev_name, flags);
 
 	volume_info = cifs_get_volume_info((char *)data, dev_name);
 	if (IS_ERR(volume_info))
@@ -655,7 +655,8 @@ cifs_do_mount(struct file_system_type *fs_type,
 	rc = cifs_mount(cifs_sb, volume_info);
 	if (rc) {
 		if (!(flags & MS_SILENT))
-			cERROR(1, "cifs_mount failed w/return code = %d", rc);
+			cifs_dbg(VFS, "cifs_mount failed w/return code = %d\n",
+				 rc);
 		root = ERR_PTR(rc);
 		goto out_mountdata;
 	}
@@ -675,7 +676,7 @@ cifs_do_mount(struct file_system_type *fs_type,
 	}
 
 	if (sb->s_root) {
-		cFYI(1, "Use existing superblock");
+		cifs_dbg(FYI, "Use existing superblock\n");
 		cifs_umount(cifs_sb);
 	} else {
 		rc = cifs_read_super(sb);
@@ -691,7 +692,7 @@ cifs_do_mount(struct file_system_type *fs_type,
 	if (IS_ERR(root))
 		goto out_super;
 
-	cFYI(1, "dentry root is: %p", root);
+	cifs_dbg(FYI, "dentry root is: %p\n", root);
 	goto out;
 
 out_super:
@@ -723,7 +724,8 @@ static ssize_t cifs_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
 
 	rc = filemap_fdatawrite(inode->i_mapping);
 	if (rc)
-		cFYI(1, "cifs_file_aio_write: %d rc on %p inode", rc, inode);
+		cifs_dbg(FYI, "cifs_file_aio_write: %d rc on %p inode\n",
+			 rc, inode);
 
 	return written;
 }
@@ -1030,7 +1032,10 @@ cifs_init_request_bufs(void)
 	} else {
 		CIFSMaxBufSize &= 0x1FE00; /* Round size to even 512 byte mult*/
 	}
-/*	cERROR(1, "CIFSMaxBufSize %d 0x%x",CIFSMaxBufSize,CIFSMaxBufSize); */
+/*
+	cifs_dbg(VFS, "CIFSMaxBufSize %d 0x%x\n",
+		 CIFSMaxBufSize, CIFSMaxBufSize);
+*/
 	cifs_req_cachep = kmem_cache_create("cifs_request",
 					    CIFSMaxBufSize + max_hdr_size, 0,
 					    SLAB_HWCACHE_ALIGN, NULL);
@@ -1041,7 +1046,7 @@ cifs_init_request_bufs(void)
 		cifs_min_rcv = 1;
 	else if (cifs_min_rcv > 64) {
 		cifs_min_rcv = 64;
-		cERROR(1, "cifs_min_rcv set to maximum (64)");
+		cifs_dbg(VFS, "cifs_min_rcv set to maximum (64)\n");
 	}
 
 	cifs_req_poolp = mempool_create_slab_pool(cifs_min_rcv,
@@ -1072,7 +1077,7 @@ cifs_init_request_bufs(void)
 		cifs_min_small = 2;
 	else if (cifs_min_small > 256) {
 		cifs_min_small = 256;
-		cFYI(1, "cifs_min_small set to maximum (256)");
+		cifs_dbg(FYI, "cifs_min_small set to maximum (256)\n");
 	}
 
 	cifs_sm_req_poolp = mempool_create_slab_pool(cifs_min_small,
@@ -1163,10 +1168,11 @@ init_cifs(void)
 
 	if (cifs_max_pending < 2) {
 		cifs_max_pending = 2;
-		cFYI(1, "cifs_max_pending set to min of 2");
+		cifs_dbg(FYI, "cifs_max_pending set to min of 2\n");
 	} else if (cifs_max_pending > CIFS_MAX_REQ) {
 		cifs_max_pending = CIFS_MAX_REQ;
-		cFYI(1, "cifs_max_pending set to max of %u", CIFS_MAX_REQ);
+		cifs_dbg(FYI, "cifs_max_pending set to max of %u\n",
+			 CIFS_MAX_REQ);
 	}
 
 	cifsiod_wq = alloc_workqueue("cifsiod", WQ_FREEZABLE|WQ_MEM_RECLAIM, 0);
@@ -1235,7 +1241,7 @@ out_clean_proc:
 static void __exit
 exit_cifs(void)
 {
-	cFYI(DBG2, "exit_cifs");
+	cifs_dbg(NOISY, "exit_cifs\n");
 	unregister_filesystem(&cifs_fs_type);
 	cifs_dfs_release_automount_timer();
 #ifdef CONFIG_CIFS_ACL
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index f450f06..dda188a 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -45,17 +45,17 @@ extern void _free_xid(unsigned int);
 #define get_xid()						\
 ({								\
 	unsigned int __xid = _get_xid();				\
-	cFYI(1, "CIFS VFS: in %s as Xid: %u with uid: %d",	\
-	     __func__, __xid,					\
-	     from_kuid(&init_user_ns, current_fsuid()));	\
+	cifs_dbg(FYI, "CIFS VFS: in %s as Xid: %u with uid: %d\n",	\
+		 __func__, __xid,					\
+		 from_kuid(&init_user_ns, current_fsuid()));		\
 	__xid;							\
 })
 
 #define free_xid(curr_xid)					\
 do {								\
 	_free_xid(curr_xid);					\
-	cFYI(1, "CIFS VFS: leaving %s (xid = %u) rc = %d",	\
-	     __func__, curr_xid, (int)rc);			\
+	cifs_dbg(FYI, "CIFS VFS: leaving %s (xid = %u) rc = %d\n",	\
+		 __func__, curr_xid, (int)rc);				\
 } while (0)
 extern int init_cifs_idmap(void);
 extern void exit_cifs_idmap(void);
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 8e2e799..a58dc77 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -139,8 +139,8 @@ cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
 		if (smb_command != SMB_COM_WRITE_ANDX &&
 		    smb_command != SMB_COM_OPEN_ANDX &&
 		    smb_command != SMB_COM_TREE_DISCONNECT) {
-			cFYI(1, "can not send cmd %d while umounting",
-				smb_command);
+			cifs_dbg(FYI, "can not send cmd %d while umounting\n",
+				 smb_command);
 			return -ENODEV;
 		}
 	}
@@ -163,7 +163,7 @@ cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
 		 * back on-line
 		 */
 		if (!tcon->retry) {
-			cFYI(1, "gave up waiting on reconnect in smb_init");
+			cifs_dbg(FYI, "gave up waiting on reconnect in smb_init\n");
 			return -EHOSTDOWN;
 		}
 	}
@@ -191,7 +191,7 @@ cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
 	cifs_mark_open_files_invalid(tcon);
 	rc = CIFSTCon(0, ses, tcon->treeName, tcon, nls_codepage);
 	mutex_unlock(&ses->session_mutex);
-	cFYI(1, "reconnect tcon rc = %d", rc);
+	cifs_dbg(FYI, "reconnect tcon rc = %d\n", rc);
 
 	if (rc)
 		goto out;
@@ -396,7 +396,7 @@ CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses)
 	else /* if override flags set only sign/seal OR them with global auth */
 		secFlags = global_secflags | ses->overrideSecFlg;
 
-	cFYI(1, "secFlags 0x%x", secFlags);
+	cifs_dbg(FYI, "secFlags 0x%x\n", secFlags);
 
 	pSMB->hdr.Mid = get_next_mid(server);
 	pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
@@ -404,12 +404,12 @@ CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses)
 	if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
 		pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
 	else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) {
-		cFYI(1, "Kerberos only mechanism, enable extended security");
+		cifs_dbg(FYI, "Kerberos only mechanism, enable extended security\n");
 		pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
 	} else if ((secFlags & CIFSSEC_MUST_NTLMSSP) == CIFSSEC_MUST_NTLMSSP)
 		pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
 	else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_NTLMSSP) {
-		cFYI(1, "NTLMSSP only mechanism, enable extended security");
+		cifs_dbg(FYI, "NTLMSSP only mechanism, enable extended security\n");
 		pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
 	}
 
@@ -428,7 +428,7 @@ CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses)
 		goto neg_err_exit;
 
 	server->dialect = le16_to_cpu(pSMBr->DialectIndex);
-	cFYI(1, "Dialect: %d", server->dialect);
+	cifs_dbg(FYI, "Dialect: %d\n", server->dialect);
 	/* Check wct = 1 error case */
 	if ((pSMBr->hdr.WordCount < 13) || (server->dialect == BAD_PROT)) {
 		/* core returns wct = 1, but we do not ask for core - otherwise
@@ -447,8 +447,7 @@ CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses)
 			(secFlags & CIFSSEC_MAY_PLNTXT))
 			server->secType = LANMAN;
 		else {
-			cERROR(1, "mount failed weak security disabled"
-				   " in /proc/fs/cifs/SecurityFlags");
+			cifs_dbg(VFS, "mount failed weak security disabled in /proc/fs/cifs/SecurityFlags\n");
 			rc = -EOPNOTSUPP;
 			goto neg_err_exit;
 		}
@@ -482,9 +481,9 @@ CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses)
 			utc = CURRENT_TIME;
 			ts = cnvrtDosUnixTm(rsp->SrvTime.Date,
 					    rsp->SrvTime.Time, 0);
-			cFYI(1, "SrvTime %d sec since 1970 (utc: %d) diff: %d",
-				(int)ts.tv_sec, (int)utc.tv_sec,
-				(int)(utc.tv_sec - ts.tv_sec));
+			cifs_dbg(FYI, "SrvTime %d sec since 1970 (utc: %d) diff: %d\n",
+				 (int)ts.tv_sec, (int)utc.tv_sec,
+				 (int)(utc.tv_sec - ts.tv_sec));
 			val = (int)(utc.tv_sec - ts.tv_sec);
 			seconds = abs(val);
 			result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
@@ -498,7 +497,7 @@ CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses)
 			server->timeAdj = (int)tmp;
 			server->timeAdj *= 60; /* also in seconds */
 		}
-		cFYI(1, "server->timeAdj: %d seconds", server->timeAdj);
+		cifs_dbg(FYI, "server->timeAdj: %d seconds\n", server->timeAdj);
 
 
 		/* BB get server time for time conversions and add
@@ -513,14 +512,13 @@ CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses)
 			goto neg_err_exit;
 		}
 
-		cFYI(1, "LANMAN negotiated");
+		cifs_dbg(FYI, "LANMAN negotiated\n");
 		/* we will not end up setting signing flags - as no signing
 		was in LANMAN and server did not return the flags on */
 		goto signing_check;
 #else /* weak security disabled */
 	} else if (pSMBr->hdr.WordCount == 13) {
-		cERROR(1, "mount failed, cifs module not built "
-			  "with CIFS_WEAK_PW_HASH support");
+		cifs_dbg(VFS, "mount failed, cifs module not built with CIFS_WEAK_PW_HASH support\n");
 		rc = -EOPNOTSUPP;
 #endif /* WEAK_PW_HASH */
 		goto neg_err_exit;
@@ -532,14 +530,13 @@ CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses)
 	/* else wct == 17 NTLM */
 	server->sec_mode = pSMBr->SecurityMode;
 	if ((server->sec_mode & SECMODE_USER) == 0)
-		cFYI(1, "share mode security");
+		cifs_dbg(FYI, "share mode security\n");
 
 	if ((server->sec_mode & SECMODE_PW_ENCRYPT) == 0)
 #ifdef CONFIG_CIFS_WEAK_PW_HASH
 		if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
 #endif /* CIFS_WEAK_PW_HASH */
-			cERROR(1, "Server requests plain text password"
-				  " but client support disabled");
+			cifs_dbg(VFS, "Server requests plain text password but client support disabled\n");
 
 	if ((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
 		server->secType = NTLMv2;
@@ -555,7 +552,7 @@ CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses)
 		server->secType = LANMAN;
 	else {
 		rc = -EOPNOTSUPP;
-		cERROR(1, "Invalid security type");
+		cifs_dbg(VFS, "Invalid security type\n");
 		goto neg_err_exit;
 	}
 	/* else ... any others ...? */
@@ -568,7 +565,7 @@ CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses)
 	/* probably no need to store and check maxvcs */
 	server->maxBuf = le32_to_cpu(pSMBr->MaxBufferSize);
 	server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
-	cFYI(DBG2, "Max buf = %d", ses->server->maxBuf);
+	cifs_dbg(NOISY, "Max buf = %d\n", ses->server->maxBuf);
 	server->capabilities = le32_to_cpu(pSMBr->Capabilities);
 	server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
 	server->timeAdj *= 60;
@@ -590,7 +587,7 @@ CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses)
 			if (memcmp(server->server_GUID,
 				   pSMBr->u.extended_response.
 				   GUID, 16) != 0) {
-				cFYI(1, "server UID changed");
+				cifs_dbg(FYI, "server UID changed\n");
 				memcpy(server->server_GUID,
 					pSMBr->u.extended_response.GUID,
 					16);
@@ -633,21 +630,19 @@ signing_check:
 	if ((secFlags & CIFSSEC_MAY_SIGN) == 0) {
 		/* MUST_SIGN already includes the MAY_SIGN FLAG
 		   so if this is zero it means that signing is disabled */
-		cFYI(1, "Signing disabled");
+		cifs_dbg(FYI, "Signing disabled\n");
 		if (server->sec_mode & SECMODE_SIGN_REQUIRED) {
-			cERROR(1, "Server requires "
-				   "packet signing to be enabled in "
-				   "/proc/fs/cifs/SecurityFlags.");
+			cifs_dbg(VFS, "Server requires packet signing to be enabled in /proc/fs/cifs/SecurityFlags\n");
 			rc = -EOPNOTSUPP;
 		}
 		server->sec_mode &=
 			~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
 	} else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) {
 		/* signing required */
-		cFYI(1, "Must sign - secFlags 0x%x", secFlags);
+		cifs_dbg(FYI, "Must sign - secFlags 0x%x\n", secFlags);
 		if ((server->sec_mode &
 			(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
-			cERROR(1, "signing required but server lacks support");
+			cifs_dbg(VFS, "signing required but server lacks support\n");
 			rc = -EOPNOTSUPP;
 		} else
 			server->sec_mode |= SECMODE_SIGN_REQUIRED;
@@ -661,7 +656,7 @@ signing_check:
 neg_err_exit:
 	cifs_buf_release(pSMB);
 
-	cFYI(1, "negprot rc %d", rc);
+	cifs_dbg(FYI, "negprot rc %d\n", rc);
 	return rc;
 }
 
@@ -671,7 +666,7 @@ CIFSSMBTDis(const unsigned int xid, struct cifs_tcon *tcon)
 	struct smb_hdr *smb_buffer;
 	int rc = 0;
 
-	cFYI(1, "In tree disconnect");
+	cifs_dbg(FYI, "In tree disconnect\n");
 
 	/* BB: do we need to check this? These should never be NULL. */
 	if ((tcon->ses == NULL) || (tcon->ses->server == NULL))
@@ -693,7 +688,7 @@ CIFSSMBTDis(const unsigned int xid, struct cifs_tcon *tcon)
 
 	rc = SendReceiveNoRsp(xid, tcon->ses, (char *)smb_buffer, 0);
 	if (rc)
-		cFYI(1, "Tree disconnect failed %d", rc);
+		cifs_dbg(FYI, "Tree disconnect failed %d\n", rc);
 
 	/* No need to return error on this operation if tid invalidated and
 	   closed on server already e.g. due to tcp session crashing */
@@ -728,7 +723,7 @@ CIFSSMBEcho(struct TCP_Server_Info *server)
 	struct smb_rqst rqst = { .rq_iov = &iov,
 				 .rq_nvec = 1 };
 
-	cFYI(1, "In echo request");
+	cifs_dbg(FYI, "In echo request\n");
 
 	rc = small_smb_init(SMB_COM_ECHO, 0, NULL, (void **)&smb);
 	if (rc)
@@ -747,7 +742,7 @@ CIFSSMBEcho(struct TCP_Server_Info *server)
 	rc = cifs_call_async(server, &rqst, NULL, cifs_echo_callback,
 			     server, CIFS_ASYNC_OP | CIFS_ECHO_OP);
 	if (rc)
-		cFYI(1, "Echo request failed: %d", rc);
+		cifs_dbg(FYI, "Echo request failed: %d\n", rc);
 
 	cifs_small_buf_release(smb);
 
@@ -760,7 +755,7 @@ CIFSSMBLogoff(const unsigned int xid, struct cifs_ses *ses)
 	LOGOFF_ANDX_REQ *pSMB;
 	int rc = 0;
 
-	cFYI(1, "In SMBLogoff for session disconnect");
+	cifs_dbg(FYI, "In SMBLogoff for session disconnect\n");
 
 	/*
 	 * BB: do we need to check validity of ses and server? They should
@@ -814,7 +809,7 @@ CIFSPOSIXDelFile(const unsigned int xid, struct cifs_tcon *tcon,
 	int bytes_returned = 0;
 	__u16 params, param_offset, offset, byte_count;
 
-	cFYI(1, "In POSIX delete");
+	cifs_dbg(FYI, "In POSIX delete\n");
 PsxDelete:
 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
 		      (void **) &pSMBr);
@@ -866,7 +861,7 @@ PsxDelete:
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc)
-		cFYI(1, "Posix delete returned %d", rc);
+		cifs_dbg(FYI, "Posix delete returned %d\n", rc);
 	cifs_buf_release(pSMB);
 
 	cifs_stats_inc(&tcon->stats.cifs_stats.num_deletes);
@@ -914,7 +909,7 @@ DelFileRetry:
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	cifs_stats_inc(&tcon->stats.cifs_stats.num_deletes);
 	if (rc)
-		cFYI(1, "Error in RMFile = %d", rc);
+		cifs_dbg(FYI, "Error in RMFile = %d\n", rc);
 
 	cifs_buf_release(pSMB);
 	if (rc == -EAGAIN)
@@ -934,7 +929,7 @@ CIFSSMBRmDir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
 	int name_len;
 	int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR;
 
-	cFYI(1, "In CIFSSMBRmDir");
+	cifs_dbg(FYI, "In CIFSSMBRmDir\n");
 RmDirRetry:
 	rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
 		      (void **) &pSMBr);
@@ -960,7 +955,7 @@ RmDirRetry:
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	cifs_stats_inc(&tcon->stats.cifs_stats.num_rmdirs);
 	if (rc)
-		cFYI(1, "Error in RMDir = %d", rc);
+		cifs_dbg(FYI, "Error in RMDir = %d\n", rc);
 
 	cifs_buf_release(pSMB);
 	if (rc == -EAGAIN)
@@ -979,7 +974,7 @@ CIFSSMBMkDir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
 	int name_len;
 	int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR;
 
-	cFYI(1, "In CIFSSMBMkDir");
+	cifs_dbg(FYI, "In CIFSSMBMkDir\n");
 MkDirRetry:
 	rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
 		      (void **) &pSMBr);
@@ -1005,7 +1000,7 @@ MkDirRetry:
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	cifs_stats_inc(&tcon->stats.cifs_stats.num_mkdirs);
 	if (rc)
-		cFYI(1, "Error in Mkdir = %d", rc);
+		cifs_dbg(FYI, "Error in Mkdir = %d\n", rc);
 
 	cifs_buf_release(pSMB);
 	if (rc == -EAGAIN)
@@ -1029,7 +1024,7 @@ CIFSPOSIXCreate(const unsigned int xid, struct cifs_tcon *tcon,
 	OPEN_PSX_REQ *pdata;
 	OPEN_PSX_RSP *psx_rsp;
 
-	cFYI(1, "In POSIX Create");
+	cifs_dbg(FYI, "In POSIX Create\n");
 PsxCreat:
 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
 		      (void **) &pSMBr);
@@ -1083,11 +1078,11 @@ PsxCreat:
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
-		cFYI(1, "Posix create returned %d", rc);
+		cifs_dbg(FYI, "Posix create returned %d\n", rc);
 		goto psx_create_err;
 	}
 
-	cFYI(1, "copying inode info");
+	cifs_dbg(FYI, "copying inode info\n");
 	rc = validate_t2((struct smb_t2_rsp *)pSMBr);
 
 	if (rc || get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)) {
@@ -1109,11 +1104,11 @@ PsxCreat:
 	/* check to make sure response data is there */
 	if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
 		pRetData->Type = cpu_to_le32(-1); /* unknown */
-		cFYI(DBG2, "unknown type");
+		cifs_dbg(NOISY, "unknown type\n");
 	} else {
 		if (get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)
 					+ sizeof(FILE_UNIX_BASIC_INFO)) {
-			cERROR(1, "Open response data too small");
+			cifs_dbg(VFS, "Open response data too small\n");
 			pRetData->Type = cpu_to_le32(-1);
 			goto psx_create_err;
 		}
@@ -1160,7 +1155,7 @@ static __u16 convert_disposition(int disposition)
 			ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
 			break;
 		default:
-			cFYI(1, "unknown disposition %d", disposition);
+			cifs_dbg(FYI, "unknown disposition %d\n", disposition);
 			ofun =  SMBOPEN_OAPPEND; /* regular open */
 	}
 	return ofun;
@@ -1251,7 +1246,7 @@ OldOpenRetry:
 			(struct smb_hdr *)pSMBr, &bytes_returned, 0);
 	cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);
 	if (rc) {
-		cFYI(1, "Error in Open = %d", rc);
+		cifs_dbg(FYI, "Error in Open = %d\n", rc);
 	} else {
 	/* BB verify if wct == 15 */
 
@@ -1364,7 +1359,7 @@ openRetry:
 			(struct smb_hdr *)pSMBr, &bytes_returned, 0);
 	cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);
 	if (rc) {
-		cFYI(1, "Error in Open = %d", rc);
+		cifs_dbg(FYI, "Error in Open = %d\n", rc);
 	} else {
 		*pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
 		*netfid = pSMBr->Fid;	/* cifs fid stays in le */
@@ -1425,8 +1420,8 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
 	char *buf = server->smallbuf;
 	unsigned int buflen = get_rfc1002_length(buf) + 4;
 
-	cFYI(1, "%s: mid=%llu offset=%llu bytes=%u", __func__,
-		mid->mid, rdata->offset, rdata->bytes);
+	cifs_dbg(FYI, "%s: mid=%llu offset=%llu bytes=%u\n",
+		 __func__, mid->mid, rdata->offset, rdata->bytes);
 
 	/*
 	 * read the rest of READ_RSP header (sans Data array), or whatever we
@@ -1447,16 +1442,16 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
 	/* Was the SMB read successful? */
 	rdata->result = server->ops->map_error(buf, false);
 	if (rdata->result != 0) {
-		cFYI(1, "%s: server returned error %d", __func__,
-			rdata->result);
+		cifs_dbg(FYI, "%s: server returned error %d\n",
+			 __func__, rdata->result);
 		return cifs_readv_discard(server, mid);
 	}
 
 	/* Is there enough to get to the rest of the READ_RSP header? */
 	if (server->total_read < server->vals->read_rsp_size) {
-		cFYI(1, "%s: server returned short header. got=%u expected=%zu",
-			__func__, server->total_read,
-			server->vals->read_rsp_size);
+		cifs_dbg(FYI, "%s: server returned short header. got=%u expected=%zu\n",
+			 __func__, server->total_read,
+			 server->vals->read_rsp_size);
 		rdata->result = -EIO;
 		return cifs_readv_discard(server, mid);
 	}
@@ -1468,19 +1463,19 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
 		 * is beyond the EOF. Treat it as if the data starts just after
 		 * the header.
 		 */
-		cFYI(1, "%s: data offset (%u) inside read response header",
-			__func__, data_offset);
+		cifs_dbg(FYI, "%s: data offset (%u) inside read response header\n",
+			 __func__, data_offset);
 		data_offset = server->total_read;
 	} else if (data_offset > MAX_CIFS_SMALL_BUFFER_SIZE) {
 		/* data_offset is beyond the end of smallbuf */
-		cFYI(1, "%s: data offset (%u) beyond end of smallbuf",
-			__func__, data_offset);
+		cifs_dbg(FYI, "%s: data offset (%u) beyond end of smallbuf\n",
+			 __func__, data_offset);
 		rdata->result = -EIO;
 		return cifs_readv_discard(server, mid);
 	}
 
-	cFYI(1, "%s: total_read=%u data_offset=%u", __func__,
-		server->total_read, data_offset);
+	cifs_dbg(FYI, "%s: total_read=%u data_offset=%u\n",
+		 __func__, server->total_read, data_offset);
 
 	len = data_offset - server->total_read;
 	if (len > 0) {
@@ -1496,8 +1491,8 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
 	/* set up first iov for signature check */
 	rdata->iov.iov_base = buf;
 	rdata->iov.iov_len = server->total_read;
-	cFYI(1, "0: iov_base=%p iov_len=%zu",
-		rdata->iov.iov_base, rdata->iov.iov_len);
+	cifs_dbg(FYI, "0: iov_base=%p iov_len=%zu\n",
+		 rdata->iov.iov_base, rdata->iov.iov_len);
 
 	/* how much data is in the response? */
 	data_len = server->ops->read_data_length(buf);
@@ -1514,8 +1509,8 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
 	server->total_read += length;
 	rdata->bytes = length;
 
-	cFYI(1, "total_read=%u buflen=%u remaining=%u", server->total_read,
-		buflen, data_len);
+	cifs_dbg(FYI, "total_read=%u buflen=%u remaining=%u\n",
+		 server->total_read, buflen, data_len);
 
 	/* discard anything left over */
 	if (server->total_read < buflen)
@@ -1538,8 +1533,9 @@ cifs_readv_callback(struct mid_q_entry *mid)
 				 .rq_pagesz = rdata->pagesz,
 				 .rq_tailsz = rdata->tailsz };
 
-	cFYI(1, "%s: mid=%llu state=%d result=%d bytes=%u", __func__,
-		mid->mid, mid->mid_state, rdata->result, rdata->bytes);
+	cifs_dbg(FYI, "%s: mid=%llu state=%d result=%d bytes=%u\n",
+		 __func__, mid->mid, mid->mid_state, rdata->result,
+		 rdata->bytes);
 
 	switch (mid->mid_state) {
 	case MID_RESPONSE_RECEIVED:
@@ -1549,10 +1545,10 @@ cifs_readv_callback(struct mid_q_entry *mid)
 			int rc = 0;
 
 			rc = cifs_verify_signature(&rqst, server,
-						  mid->sequence_number + 1);
+						  mid->sequence_number);
 			if (rc)
-				cERROR(1, "SMB signature verification returned "
-				       "error = %d", rc);
+				cifs_dbg(VFS, "SMB signature verification returned error = %d\n",
+					 rc);
 		}
 		/* FIXME: should this be counted toward the initiating task? */
 		task_io_account_read(rdata->bytes);
@@ -1582,8 +1578,8 @@ cifs_async_readv(struct cifs_readdata *rdata)
 	struct smb_rqst rqst = { .rq_iov = &rdata->iov,
 				 .rq_nvec = 1 };
 
-	cFYI(1, "%s: offset=%llu bytes=%u", __func__,
-		rdata->offset, rdata->bytes);
+	cifs_dbg(FYI, "%s: offset=%llu bytes=%u\n",
+		 __func__, rdata->offset, rdata->bytes);
 
 	if (tcon->ses->capabilities & CAP_LARGE_FILES)
 		wct = 12;
@@ -1653,7 +1649,7 @@ CIFSSMBRead(const unsigned int xid, struct cifs_io_parms *io_parms,
 	struct cifs_tcon *tcon = io_parms->tcon;
 	unsigned int count = io_parms->length;
 
-	cFYI(1, "Reading %d bytes on fid %d", count, netfid);
+	cifs_dbg(FYI, "Reading %d bytes on fid %d\n", count, netfid);
 	if (tcon->ses->capabilities & CAP_LARGE_FILES)
 		wct = 12;
 	else {
@@ -1701,7 +1697,7 @@ CIFSSMBRead(const unsigned int xid, struct cifs_io_parms *io_parms,
 	cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
 	pSMBr = (READ_RSP *)iov[0].iov_base;
 	if (rc) {
-		cERROR(1, "Send error in read = %d", rc);
+		cifs_dbg(VFS, "Send error in read = %d\n", rc);
 	} else {
 		int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
 		data_length = data_length << 16;
@@ -1711,7 +1707,7 @@ CIFSSMBRead(const unsigned int xid, struct cifs_io_parms *io_parms,
 		/*check that DataLength would not go beyond end of SMB */
 		if ((data_length > CIFSMaxBufSize)
 				|| (data_length > count)) {
-			cFYI(1, "bad length %d for count %d",
+			cifs_dbg(FYI, "bad length %d for count %d\n",
 				 data_length, count);
 			rc = -EIO;
 			*nbytes = 0;
@@ -1719,7 +1715,7 @@ CIFSSMBRead(const unsigned int xid, struct cifs_io_parms *io_parms,
 			pReadData = (char *) (&pSMBr->hdr.Protocol) +
 					le16_to_cpu(pSMBr->DataOffset);
 /*			if (rc = copy_to_user(buf, pReadData, data_length)) {
-				cERROR(1, "Faulting on read rc = %d",rc);
+				cifs_dbg(VFS, "Faulting on read rc = %d\n",rc);
 				rc = -EFAULT;
 			}*/ /* can not use copy_to_user when using page cache*/
 			if (*buf)
@@ -1767,7 +1763,7 @@ CIFSSMBWrite(const unsigned int xid, struct cifs_io_parms *io_parms,
 
 	*nbytes = 0;
 
-	/* cFYI(1, "write at %lld %d bytes", offset, count);*/
+	/* cifs_dbg(FYI, "write at %lld %d bytes\n", offset, count);*/
 	if (tcon->ses == NULL)
 		return -ECONNABORTED;
 
@@ -1852,7 +1848,7 @@ CIFSSMBWrite(const unsigned int xid, struct cifs_io_parms *io_parms,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
 	cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
 	if (rc) {
-		cFYI(1, "Send error in write = %d", rc);
+		cifs_dbg(FYI, "Send error in write = %d\n", rc);
 	} else {
 		*nbytes = le16_to_cpu(pSMBr->CountHigh);
 		*nbytes = (*nbytes) << 16;
@@ -1959,7 +1955,7 @@ cifs_writedata_alloc(unsigned int nr_pages, work_func_t complete)
 
 	/* this would overflow */
 	if (nr_pages == 0) {
-		cERROR(1, "%s: called with nr_pages == 0!", __func__);
+		cifs_dbg(VFS, "%s: called with nr_pages == 0!\n", __func__);
 		return NULL;
 	}
 
@@ -2075,7 +2071,8 @@ cifs_async_writev(struct cifs_writedata *wdata)
 	rqst.rq_pagesz = wdata->pagesz;
 	rqst.rq_tailsz = wdata->tailsz;
 
-	cFYI(1, "async write at %llu %u bytes", wdata->offset, wdata->bytes);
+	cifs_dbg(FYI, "async write at %llu %u bytes\n",
+		 wdata->offset, wdata->bytes);
 
 	smb->DataLengthLow = cpu_to_le16(wdata->bytes & 0xFFFF);
 	smb->DataLengthHigh = cpu_to_le16(wdata->bytes >> 16);
@@ -2123,7 +2120,7 @@ CIFSSMBWrite2(const unsigned int xid, struct cifs_io_parms *io_parms,
 
 	*nbytes = 0;
 
-	cFYI(1, "write2 at %lld %d bytes", (long long)offset, count);
+	cifs_dbg(FYI, "write2 at %lld %d bytes\n", (long long)offset, count);
 
 	if (tcon->ses->capabilities & CAP_LARGE_FILES) {
 		wct = 14;
@@ -2182,7 +2179,7 @@ CIFSSMBWrite2(const unsigned int xid, struct cifs_io_parms *io_parms,
 	rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type, 0);
 	cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
 	if (rc) {
-		cFYI(1, "Send error Write2 = %d", rc);
+		cifs_dbg(FYI, "Send error Write2 = %d\n", rc);
 	} else if (resp_buf_type == 0) {
 		/* presumably this can not happen, but best to be safe */
 		rc = -EIO;
@@ -2223,7 +2220,8 @@ int cifs_lockv(const unsigned int xid, struct cifs_tcon *tcon,
 	int resp_buf_type;
 	__u16 count;
 
-	cFYI(1, "cifs_lockv num lock %d num unlock %d", num_lock, num_unlock);
+	cifs_dbg(FYI, "cifs_lockv num lock %d num unlock %d\n",
+		 num_lock, num_unlock);
 
 	rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
 	if (rc)
@@ -2249,7 +2247,7 @@ int cifs_lockv(const unsigned int xid, struct cifs_tcon *tcon,
 	cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
 	rc = SendReceive2(xid, tcon->ses, iov, 2, &resp_buf_type, CIFS_NO_RESP);
 	if (rc)
-		cFYI(1, "Send error in cifs_lockv = %d", rc);
+		cifs_dbg(FYI, "Send error in cifs_lockv = %d\n", rc);
 
 	return rc;
 }
@@ -2268,7 +2266,8 @@ CIFSSMBLock(const unsigned int xid, struct cifs_tcon *tcon,
 	int flags = 0;
 	__u16 count;
 
-	cFYI(1, "CIFSSMBLock timeout %d numLock %d", (int)waitFlag, numLock);
+	cifs_dbg(FYI, "CIFSSMBLock timeout %d numLock %d\n",
+		 (int)waitFlag, numLock);
 	rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
 
 	if (rc)
@@ -2317,7 +2316,7 @@ CIFSSMBLock(const unsigned int xid, struct cifs_tcon *tcon,
 	}
 	cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
 	if (rc)
-		cFYI(1, "Send error in Lock = %d", rc);
+		cifs_dbg(FYI, "Send error in Lock = %d\n", rc);
 
 	/* Note: On -EAGAIN error only caller can retry on handle based calls
 	since file handle passed in no longer valid */
@@ -2341,7 +2340,7 @@ CIFSSMBPosixLock(const unsigned int xid, struct cifs_tcon *tcon,
 	__u16 params, param_offset, offset, byte_count, count;
 	struct kvec iov[1];
 
-	cFYI(1, "Posix Lock");
+	cifs_dbg(FYI, "Posix Lock\n");
 
 	rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
 
@@ -2408,7 +2407,7 @@ CIFSSMBPosixLock(const unsigned int xid, struct cifs_tcon *tcon,
 	}
 
 	if (rc) {
-		cFYI(1, "Send error in Posix Lock = %d", rc);
+		cifs_dbg(FYI, "Send error in Posix Lock = %d\n", rc);
 	} else if (pLockData) {
 		/* lock structure can be returned on get */
 		__u16 data_offset;
@@ -2465,7 +2464,7 @@ CIFSSMBClose(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
 {
 	int rc = 0;
 	CLOSE_REQ *pSMB = NULL;
-	cFYI(1, "In CIFSSMBClose");
+	cifs_dbg(FYI, "In CIFSSMBClose\n");
 
 /* do not retry on dead session on close */
 	rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
@@ -2482,7 +2481,7 @@ CIFSSMBClose(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
 	if (rc) {
 		if (rc != -EINTR) {
 			/* EINTR is expected when user ctl-c to kill app */
-			cERROR(1, "Send error in Close = %d", rc);
+			cifs_dbg(VFS, "Send error in Close = %d\n", rc);
 		}
 	}
 
@@ -2498,7 +2497,7 @@ CIFSSMBFlush(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
 {
 	int rc = 0;
 	FLUSH_REQ *pSMB = NULL;
-	cFYI(1, "In CIFSSMBFlush");
+	cifs_dbg(FYI, "In CIFSSMBFlush\n");
 
 	rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
 	if (rc)
@@ -2509,7 +2508,7 @@ CIFSSMBFlush(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
 	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
 	cifs_stats_inc(&tcon->stats.cifs_stats.num_flushes);
 	if (rc)
-		cERROR(1, "Send error in Flush = %d", rc);
+		cifs_dbg(VFS, "Send error in Flush = %d\n", rc);
 
 	return rc;
 }
@@ -2527,7 +2526,7 @@ CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon,
 	__u16 count;
 	int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR;
 
-	cFYI(1, "In CIFSSMBRename");
+	cifs_dbg(FYI, "In CIFSSMBRename\n");
 renameRetry:
 	rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
 		      (void **) &pSMBr);
@@ -2574,7 +2573,7 @@ renameRetry:
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	cifs_stats_inc(&tcon->stats.cifs_stats.num_renames);
 	if (rc)
-		cFYI(1, "Send error in rename = %d", rc);
+		cifs_dbg(FYI, "Send error in rename = %d\n", rc);
 
 	cifs_buf_release(pSMB);
 
@@ -2598,7 +2597,7 @@ int CIFSSMBRenameOpenFile(const unsigned int xid, struct cifs_tcon *pTcon,
 	int len_of_str;
 	__u16 params, param_offset, offset, count, byte_count;
 
-	cFYI(1, "Rename to File by handle");
+	cifs_dbg(FYI, "Rename to File by handle\n");
 	rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
 			(void **) &pSMBr);
 	if (rc)
@@ -2655,7 +2654,8 @@ int CIFSSMBRenameOpenFile(const unsigned int xid, struct cifs_tcon *pTcon,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	cifs_stats_inc(&pTcon->stats.cifs_stats.num_t2renames);
 	if (rc)
-		cFYI(1, "Send error in Rename (by file handle) = %d", rc);
+		cifs_dbg(FYI, "Send error in Rename (by file handle) = %d\n",
+			 rc);
 
 	cifs_buf_release(pSMB);
 
@@ -2677,7 +2677,7 @@ CIFSSMBCopy(const unsigned int xid, struct cifs_tcon *tcon,
 	int name_len, name_len2;
 	__u16 count;
 
-	cFYI(1, "In CIFSSMBCopy");
+	cifs_dbg(FYI, "In CIFSSMBCopy\n");
 copyRetry:
 	rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
 			(void **) &pSMBr);
@@ -2722,8 +2722,8 @@ copyRetry:
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
-		cFYI(1, "Send error in copy = %d with %d files copied",
-			rc, le16_to_cpu(pSMBr->CopyCount));
+		cifs_dbg(FYI, "Send error in copy = %d with %d files copied\n",
+			 rc, le16_to_cpu(pSMBr->CopyCount));
 	}
 	cifs_buf_release(pSMB);
 
@@ -2747,7 +2747,7 @@ CIFSUnixCreateSymLink(const unsigned int xid, struct cifs_tcon *tcon,
 	int bytes_returned = 0;
 	__u16 params, param_offset, offset, byte_count;
 
-	cFYI(1, "In Symlink Unix style");
+	cifs_dbg(FYI, "In Symlink Unix style\n");
 createSymLinkRetry:
 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
 		      (void **) &pSMBr);
@@ -2812,7 +2812,8 @@ createSymLinkRetry:
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	cifs_stats_inc(&tcon->stats.cifs_stats.num_symlinks);
 	if (rc)
-		cFYI(1, "Send error in SetPathInfo create symlink = %d", rc);
+		cifs_dbg(FYI, "Send error in SetPathInfo create symlink = %d\n",
+			 rc);
 
 	cifs_buf_release(pSMB);
 
@@ -2836,7 +2837,7 @@ CIFSUnixCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
 	int bytes_returned = 0;
 	__u16 params, param_offset, offset, byte_count;
 
-	cFYI(1, "In Create Hard link Unix style");
+	cifs_dbg(FYI, "In Create Hard link Unix style\n");
 createHardLinkRetry:
 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
 		      (void **) &pSMBr);
@@ -2898,7 +2899,8 @@ createHardLinkRetry:
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
 	if (rc)
-		cFYI(1, "Send error in SetPathInfo (hard link) = %d", rc);
+		cifs_dbg(FYI, "Send error in SetPathInfo (hard link) = %d\n",
+			 rc);
 
 	cifs_buf_release(pSMB);
 	if (rc == -EAGAIN)
@@ -2920,7 +2922,7 @@ CIFSCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
 	__u16 count;
 	int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR;
 
-	cFYI(1, "In CIFSCreateHardLink");
+	cifs_dbg(FYI, "In CIFSCreateHardLink\n");
 winCreateHardLinkRetry:
 
 	rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
@@ -2972,7 +2974,7 @@ winCreateHardLinkRetry:
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
 	if (rc)
-		cFYI(1, "Send error in hard link (NT rename) = %d", rc);
+		cifs_dbg(FYI, "Send error in hard link (NT rename) = %d\n", rc);
 
 	cifs_buf_release(pSMB);
 	if (rc == -EAGAIN)
@@ -2995,7 +2997,7 @@ CIFSSMBUnixQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
 	__u16 params, byte_count;
 	char *data_start;
 
-	cFYI(1, "In QPathSymLinkInfo (Unix) for path %s", searchName);
+	cifs_dbg(FYI, "In QPathSymLinkInfo (Unix) for path %s\n", searchName);
 
 querySymLinkRetry:
 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
@@ -3042,7 +3044,7 @@ querySymLinkRetry:
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
-		cFYI(1, "Send error in QuerySymLinkInfo = %d", rc);
+		cifs_dbg(FYI, "Send error in QuerySymLinkInfo = %d\n", rc);
 	} else {
 		/* decode response */
 
@@ -3097,7 +3099,8 @@ CIFSSMBQueryReparseLinkInfo(const unsigned int xid, struct cifs_tcon *tcon,
 	struct smb_com_transaction_ioctl_req *pSMB;
 	struct smb_com_transaction_ioctl_rsp *pSMBr;
 
-	cFYI(1, "In Windows reparse style QueryLink for path %s", searchName);
+	cifs_dbg(FYI, "In Windows reparse style QueryLink for path %s\n",
+		 searchName);
 	rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
 		      (void **) &pSMBr);
 	if (rc)
@@ -3125,7 +3128,7 @@ CIFSSMBQueryReparseLinkInfo(const unsigned int xid, struct cifs_tcon *tcon,
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
-		cFYI(1, "Send error in QueryReparseLinkInfo = %d", rc);
+		cifs_dbg(FYI, "Send error in QueryReparseLinkInfo = %d\n", rc);
 	} else {		/* decode response */
 		__u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
 		__u32 data_count = le32_to_cpu(pSMBr->DataCount);
@@ -3149,7 +3152,7 @@ CIFSSMBQueryReparseLinkInfo(const unsigned int xid, struct cifs_tcon *tcon,
 			if ((reparse_buf->LinkNamesBuf +
 				reparse_buf->TargetNameOffset +
 				reparse_buf->TargetNameLen) > end_of_smb) {
-				cFYI(1, "reparse buf beyond SMB");
+				cifs_dbg(FYI, "reparse buf beyond SMB\n");
 				rc = -EIO;
 				goto qreparse_out;
 			}
@@ -3170,12 +3173,11 @@ CIFSSMBQueryReparseLinkInfo(const unsigned int xid, struct cifs_tcon *tcon,
 			}
 		} else {
 			rc = -EIO;
-			cFYI(1, "Invalid return data count on "
-				 "get reparse info ioctl");
+			cifs_dbg(FYI, "Invalid return data count on get reparse info ioctl\n");
 		}
 		symlinkinfo[buflen] = 0; /* just in case so the caller
 					does not go off the end of the buffer */
-		cFYI(1, "readlink result - %s", symlinkinfo);
+		cifs_dbg(FYI, "readlink result - %s\n", symlinkinfo);
 	}
 
 qreparse_out:
@@ -3198,7 +3200,10 @@ static void cifs_convert_ace(posix_acl_xattr_entry *ace,
 	ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
 	ace->e_tag  = cpu_to_le16(cifs_ace->cifs_e_tag);
 	ace->e_id   = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
-	/* cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id); */
+/*
+	cifs_dbg(FYI, "perm %d tag %d id %d\n",
+		 ace->e_perm, ace->e_tag, ace->e_id);
+*/
 
 	return;
 }
@@ -3224,8 +3229,8 @@ static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
 		size += sizeof(struct cifs_posix_ace) * count;
 		/* check if we would go beyond end of SMB */
 		if (size_of_data_area < size) {
-			cFYI(1, "bad CIFS POSIX ACL size %d vs. %d",
-				size_of_data_area, size);
+			cifs_dbg(FYI, "bad CIFS POSIX ACL size %d vs. %d\n",
+				 size_of_data_area, size);
 			return -EINVAL;
 		}
 	} else if (acl_type & ACL_TYPE_DEFAULT) {
@@ -3272,7 +3277,10 @@ static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
 		cifs_ace->cifs_uid = cpu_to_le64(-1);
 	} else
 		cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
-	/*cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id);*/
+/*
+	cifs_dbg(FYI, "perm %d tag %d id %d\n",
+		 ace->e_perm, ace->e_tag, ace->e_id);
+*/
 	return rc;
 }
 
@@ -3290,12 +3298,11 @@ static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
 		return 0;
 
 	count = posix_acl_xattr_count((size_t)buflen);
-	cFYI(1, "setting acl with %d entries from buf of length %d and "
-		"version of %d",
-		count, buflen, le32_to_cpu(local_acl->a_version));
+	cifs_dbg(FYI, "setting acl with %d entries from buf of length %d and version of %d\n",
+		 count, buflen, le32_to_cpu(local_acl->a_version));
 	if (le32_to_cpu(local_acl->a_version) != 2) {
-		cFYI(1, "unknown POSIX ACL version %d",
-		     le32_to_cpu(local_acl->a_version));
+		cifs_dbg(FYI, "unknown POSIX ACL version %d\n",
+			 le32_to_cpu(local_acl->a_version));
 		return 0;
 	}
 	cifs_acl->version = cpu_to_le16(1);
@@ -3304,7 +3311,7 @@ static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
 	else if (acl_type == ACL_TYPE_DEFAULT)
 		cifs_acl->default_entry_count = cpu_to_le16(count);
 	else {
-		cFYI(1, "unknown ACL type %d", acl_type);
+		cifs_dbg(FYI, "unknown ACL type %d\n", acl_type);
 		return 0;
 	}
 	for (i = 0; i < count; i++) {
@@ -3337,7 +3344,7 @@ CIFSSMBGetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
 	int name_len;
 	__u16 params, byte_count;
 
-	cFYI(1, "In GetPosixACL (Unix) for path %s", searchName);
+	cifs_dbg(FYI, "In GetPosixACL (Unix) for path %s\n", searchName);
 
 queryAclRetry:
 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
@@ -3390,7 +3397,7 @@ queryAclRetry:
 		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
 	if (rc) {
-		cFYI(1, "Send error in Query POSIX ACL = %d", rc);
+		cifs_dbg(FYI, "Send error in Query POSIX ACL = %d\n", rc);
 	} else {
 		/* decode response */
 
@@ -3427,7 +3434,7 @@ CIFSSMBSetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
 	int bytes_returned = 0;
 	__u16 params, byte_count, data_count, param_offset, offset;
 
-	cFYI(1, "In SetPosixACL (Unix) for path %s", fileName);
+	cifs_dbg(FYI, "In SetPosixACL (Unix) for path %s\n", fileName);
 setAclRetry:
 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
 		      (void **) &pSMBr);
@@ -3482,7 +3489,7 @@ setAclRetry:
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc)
-		cFYI(1, "Set POSIX ACL returned %d", rc);
+		cifs_dbg(FYI, "Set POSIX ACL returned %d\n", rc);
 
 setACLerrorExit:
 	cifs_buf_release(pSMB);
@@ -3502,7 +3509,7 @@ CIFSGetExtAttr(const unsigned int xid, struct cifs_tcon *tcon,
 	int bytes_returned;
 	__u16 params, byte_count;
 
-	cFYI(1, "In GetExtAttr");
+	cifs_dbg(FYI, "In GetExtAttr\n");
 	if (tcon == NULL)
 		return -ENODEV;
 
@@ -3541,7 +3548,7 @@ GetExtAttrRetry:
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
-		cFYI(1, "error %d in GetExtAttr", rc);
+		cifs_dbg(FYI, "error %d in GetExtAttr\n", rc);
 	} else {
 		/* decode response */
 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
@@ -3556,7 +3563,7 @@ GetExtAttrRetry:
 			struct file_chattr_info *pfinfo;
 			/* BB Do we need a cast or hash here ? */
 			if (count != 16) {
-				cFYI(1, "Illegal size ret in GetExtAttr");
+				cifs_dbg(FYI, "Illegal size ret in GetExtAttr\n");
 				rc = -EIO;
 				goto GetExtAttrOut;
 			}
@@ -3644,21 +3651,21 @@ validate_ntransact(char *buf, char **ppparm, char **ppdata,
 
 	/* should we also check that parm and data areas do not overlap? */
 	if (*ppparm > end_of_smb) {
-		cFYI(1, "parms start after end of smb");
+		cifs_dbg(FYI, "parms start after end of smb\n");
 		return -EINVAL;
 	} else if (parm_count + *ppparm > end_of_smb) {
-		cFYI(1, "parm end after end of smb");
+		cifs_dbg(FYI, "parm end after end of smb\n");
 		return -EINVAL;
 	} else if (*ppdata > end_of_smb) {
-		cFYI(1, "data starts after end of smb");
+		cifs_dbg(FYI, "data starts after end of smb\n");
 		return -EINVAL;
 	} else if (data_count + *ppdata > end_of_smb) {
-		cFYI(1, "data %p + count %d (%p) past smb end %p start %p",
-			*ppdata, data_count, (data_count + *ppdata),
-			end_of_smb, pSMBr);
+		cifs_dbg(FYI, "data %p + count %d (%p) past smb end %p start %p\n",
+			 *ppdata, data_count, (data_count + *ppdata),
+			 end_of_smb, pSMBr);
 		return -EINVAL;
 	} else if (parm_count + data_count > bcc) {
-		cFYI(1, "parm count and data count larger than SMB");
+		cifs_dbg(FYI, "parm count and data count larger than SMB\n");
 		return -EINVAL;
 	}
 	*pdatalen = data_count;
@@ -3676,7 +3683,7 @@ CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
 	QUERY_SEC_DESC_REQ *pSMB;
 	struct kvec iov[1];
 
-	cFYI(1, "GetCifsACL");
+	cifs_dbg(FYI, "GetCifsACL\n");
 
 	*pbuflen = 0;
 	*acl_inf = NULL;
@@ -3701,7 +3708,7 @@ CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
 			 0);
 	cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
 	if (rc) {
-		cFYI(1, "Send error in QuerySecDesc = %d", rc);
+		cifs_dbg(FYI, "Send error in QuerySecDesc = %d\n", rc);
 	} else {                /* decode response */
 		__le32 *parm;
 		__u32 parm_len;
@@ -3716,7 +3723,8 @@ CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
 			goto qsec_out;
 		pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
 
-		cFYI(1, "smb %p parm %p data %p", pSMBr, parm, *acl_inf);
+		cifs_dbg(FYI, "smb %p parm %p data %p\n",
+			 pSMBr, parm, *acl_inf);
 
 		if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
 			rc = -EIO;      /* bad smb */
@@ -3728,8 +3736,8 @@ CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
 
 		acl_len = le32_to_cpu(*parm);
 		if (acl_len != *pbuflen) {
-			cERROR(1, "acl length %d does not match %d",
-				   acl_len, *pbuflen);
+			cifs_dbg(VFS, "acl length %d does not match %d\n",
+				 acl_len, *pbuflen);
 			if (*pbuflen > acl_len)
 				*pbuflen = acl_len;
 		}
@@ -3738,16 +3746,15 @@ CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
 		   header followed by the smallest SID */
 		if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
 		    (*pbuflen >= 64 * 1024)) {
-			cERROR(1, "bad acl length %d", *pbuflen);
+			cifs_dbg(VFS, "bad acl length %d\n", *pbuflen);
 			rc = -EINVAL;
 			*pbuflen = 0;
 		} else {
-			*acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
+			*acl_inf = kmemdup(pdata, *pbuflen, GFP_KERNEL);
 			if (*acl_inf == NULL) {
 				*pbuflen = 0;
 				rc = -ENOMEM;
 			}
-			memcpy(*acl_inf, pdata, *pbuflen);
 		}
 	}
 qsec_out:
@@ -3809,9 +3816,10 @@ setCifsAclRetry:
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
 
-	cFYI(1, "SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc);
+	cifs_dbg(FYI, "SetCIFSACL bytes_returned: %d, rc: %d\n",
+		 bytes_returned, rc);
 	if (rc)
-		cFYI(1, "Set CIFS ACL returned %d", rc);
+		cifs_dbg(FYI, "Set CIFS ACL returned %d\n", rc);
 	cifs_buf_release(pSMB);
 
 	if (rc == -EAGAIN)
@@ -3835,7 +3843,7 @@ SMBQueryInformation(const unsigned int xid, struct cifs_tcon *tcon,
 	int bytes_returned;
 	int name_len;
 
-	cFYI(1, "In SMBQPath path %s", search_name);
+	cifs_dbg(FYI, "In SMBQPath path %s\n", search_name);
 QInfRetry:
 	rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
 		      (void **) &pSMBr);
@@ -3862,7 +3870,7 @@ QInfRetry:
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
-		cFYI(1, "Send error in QueryInfo = %d", rc);
+		cifs_dbg(FYI, "Send error in QueryInfo = %d\n", rc);
 	} else if (data) {
 		struct timespec ts;
 		__u32 time = le32_to_cpu(pSMBr->last_write_time);
@@ -3936,7 +3944,7 @@ QFileInfoRetry:
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
-		cFYI(1, "Send error in QPathInfo = %d", rc);
+		cifs_dbg(FYI, "Send error in QPathInfo = %d\n", rc);
 	} else {		/* decode response */
 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
 
@@ -3973,7 +3981,7 @@ CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
 	int name_len;
 	__u16 params, byte_count;
 
-	/* cFYI(1, "In QPathInfo path %s", search_name); */
+	/* cifs_dbg(FYI, "In QPathInfo path %s\n", search_name); */
 QPathInfoRetry:
 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
 		      (void **) &pSMBr);
@@ -4023,7 +4031,7 @@ QPathInfoRetry:
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
-		cFYI(1, "Send error in QPathInfo = %d", rc);
+		cifs_dbg(FYI, "Send error in QPathInfo = %d\n", rc);
 	} else {		/* decode response */
 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
 
@@ -4104,14 +4112,12 @@ UnixQFileInfoRetry:
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
-		cFYI(1, "Send error in QPathInfo = %d", rc);
+		cifs_dbg(FYI, "Send error in QPathInfo = %d\n", rc);
 	} else {		/* decode response */
 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
 
 		if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
-			cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response. "
-				   "Unix Extensions can be disabled on mount "
-				   "by specifying the nosfu mount option.");
+			cifs_dbg(VFS, "Malformed FILE_UNIX_BASIC_INFO response. Unix Extensions can be disabled on mount by specifying the nosfu mount option.\n");
 			rc = -EIO;	/* bad smb */
 		} else {
 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
@@ -4143,7 +4149,7 @@ CIFSSMBUnixQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
 	int name_len;
 	__u16 params, byte_count;
 
-	cFYI(1, "In QPathInfo (Unix) the path %s", searchName);
+	cifs_dbg(FYI, "In QPathInfo (Unix) the path %s\n", searchName);
 UnixQPathInfoRetry:
 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
 		      (void **) &pSMBr);
@@ -4190,14 +4196,12 @@ UnixQPathInfoRetry:
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
-		cFYI(1, "Send error in QPathInfo = %d", rc);
+		cifs_dbg(FYI, "Send error in QPathInfo = %d\n", rc);
 	} else {		/* decode response */
 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
 
 		if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
-			cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response. "
-				   "Unix Extensions can be disabled on mount "
-				   "by specifying the nosfu mount option.");
+			cifs_dbg(VFS, "Malformed FILE_UNIX_BASIC_INFO response. Unix Extensions can be disabled on mount by specifying the nosfu mount option.\n");
 			rc = -EIO;	/* bad smb */
 		} else {
 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
@@ -4231,7 +4235,7 @@ CIFSFindFirst(const unsigned int xid, struct cifs_tcon *tcon,
 	__u16 params, byte_count;
 	struct nls_table *nls_codepage;
 
-	cFYI(1, "In FindFirst for %s", searchName);
+	cifs_dbg(FYI, "In FindFirst for %s\n", searchName);
 
 findFirstRetry:
 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
@@ -4314,7 +4318,7 @@ findFirstRetry:
 	if (rc) {/* BB add logic to retry regular search if Unix search
 			rejected unexpectedly by server */
 		/* BB Add code to handle unsupported level rc */
-		cFYI(1, "Error in FindFirst = %d", rc);
+		cifs_dbg(FYI, "Error in FindFirst = %d\n", rc);
 
 		cifs_buf_release(pSMB);
 
@@ -4352,7 +4356,7 @@ findFirstRetry:
 				psrch_inf->entries_in_buffer;
 			lnoff = le16_to_cpu(parms->LastNameOffset);
 			if (CIFSMaxBufSize < lnoff) {
-				cERROR(1, "ignoring corrupt resume name");
+				cifs_dbg(VFS, "ignoring corrupt resume name\n");
 				psrch_inf->last_entry = NULL;
 				return rc;
 			}
@@ -4383,7 +4387,7 @@ int CIFSFindNext(const unsigned int xid, struct cifs_tcon *tcon,
 	unsigned int name_len;
 	__u16 params, byte_count;
 
-	cFYI(1, "In FindNext");
+	cifs_dbg(FYI, "In FindNext\n");
 
 	if (psrch_inf->endOfSearch)
 		return -ENOENT;
@@ -4444,7 +4448,7 @@ int CIFSFindNext(const unsigned int xid, struct cifs_tcon *tcon,
 			cifs_buf_release(pSMB);
 			rc = 0; /* search probably was closed at end of search*/
 		} else
-			cFYI(1, "FindNext returned = %d", rc);
+			cifs_dbg(FYI, "FindNext returned = %d\n", rc);
 	} else {                /* decode response */
 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
 
@@ -4479,15 +4483,15 @@ int CIFSFindNext(const unsigned int xid, struct cifs_tcon *tcon,
 				psrch_inf->entries_in_buffer;
 			lnoff = le16_to_cpu(parms->LastNameOffset);
 			if (CIFSMaxBufSize < lnoff) {
-				cERROR(1, "ignoring corrupt resume name");
+				cifs_dbg(VFS, "ignoring corrupt resume name\n");
 				psrch_inf->last_entry = NULL;
 				return rc;
 			} else
 				psrch_inf->last_entry =
 					psrch_inf->srch_entries_start + lnoff;
 
-/*  cFYI(1, "fnxt2 entries in buf %d index_of_last %d",
-	    psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry); */
+/*  cifs_dbg(FYI, "fnxt2 entries in buf %d index_of_last %d\n",
+    psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry); */
 
 			/* BB fixme add unlock here */
 		}
@@ -4512,7 +4516,7 @@ CIFSFindClose(const unsigned int xid, struct cifs_tcon *tcon,
 	int rc = 0;
 	FINDCLOSE_REQ *pSMB = NULL;
 
-	cFYI(1, "In CIFSSMBFindClose");
+	cifs_dbg(FYI, "In CIFSSMBFindClose\n");
 	rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
 
 	/* no sense returning error if session restarted
@@ -4526,7 +4530,7 @@ CIFSFindClose(const unsigned int xid, struct cifs_tcon *tcon,
 	pSMB->ByteCount = 0;
 	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
 	if (rc)
-		cERROR(1, "Send error in FindClose = %d", rc);
+		cifs_dbg(VFS, "Send error in FindClose = %d\n", rc);
 
 	cifs_stats_inc(&tcon->stats.cifs_stats.num_fclose);
 
@@ -4548,7 +4552,7 @@ CIFSGetSrvInodeNumber(const unsigned int xid, struct cifs_tcon *tcon,
 	int name_len, bytes_returned;
 	__u16 params, byte_count;
 
-	cFYI(1, "In GetSrvInodeNum for %s", search_name);
+	cifs_dbg(FYI, "In GetSrvInodeNum for %s\n", search_name);
 	if (tcon == NULL)
 		return -ENODEV;
 
@@ -4599,7 +4603,7 @@ GetInodeNumberRetry:
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
-		cFYI(1, "error %d in QueryInternalInfo", rc);
+		cifs_dbg(FYI, "error %d in QueryInternalInfo\n", rc);
 	} else {
 		/* decode response */
 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
@@ -4614,7 +4618,7 @@ GetInodeNumberRetry:
 			struct file_internal_info *pfinfo;
 			/* BB Do we need a cast or hash here ? */
 			if (count < 8) {
-				cFYI(1, "Illegal size ret in QryIntrnlInf");
+				cifs_dbg(FYI, "Illegal size ret in QryIntrnlInf\n");
 				rc = -EIO;
 				goto GetInodeNumOut;
 			}
@@ -4655,16 +4659,16 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
 	*num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
 
 	if (*num_of_nodes < 1) {
-		cERROR(1, "num_referrals: must be at least > 0,"
-			"but we get num_referrals = %d", *num_of_nodes);
+		cifs_dbg(VFS, "num_referrals: must be at least > 0, but we get num_referrals = %d\n",
+			 *num_of_nodes);
 		rc = -EINVAL;
 		goto parse_DFS_referrals_exit;
 	}
 
 	ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
 	if (ref->VersionNumber != cpu_to_le16(3)) {
-		cERROR(1, "Referrals of V%d version are not supported,"
-			"should be V3", le16_to_cpu(ref->VersionNumber));
+		cifs_dbg(VFS, "Referrals of V%d version are not supported, should be V3\n",
+			 le16_to_cpu(ref->VersionNumber));
 		rc = -EINVAL;
 		goto parse_DFS_referrals_exit;
 	}
@@ -4673,14 +4677,12 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
 	data_end = (char *)(&(pSMBr->PathConsumed)) +
 				le16_to_cpu(pSMBr->t2.DataCount);
 
-	cFYI(1, "num_referrals: %d dfs flags: 0x%x ...",
-			*num_of_nodes,
-			le32_to_cpu(pSMBr->DFSFlags));
+	cifs_dbg(FYI, "num_referrals: %d dfs flags: 0x%x ...\n",
+		 *num_of_nodes, le32_to_cpu(pSMBr->DFSFlags));
 
-	*target_nodes = kzalloc(sizeof(struct dfs_info3_param) *
-			*num_of_nodes, GFP_KERNEL);
+	*target_nodes = kcalloc(*num_of_nodes, sizeof(struct dfs_info3_param),
+				GFP_KERNEL);
 	if (*target_nodes == NULL) {
-		cERROR(1, "Failed to allocate buffer for target_nodes");
 		rc = -ENOMEM;
 		goto parse_DFS_referrals_exit;
 	}
@@ -4759,7 +4761,7 @@ CIFSGetDFSRefer(const unsigned int xid, struct cifs_ses *ses,
 	*num_of_nodes = 0;
 	*target_nodes = NULL;
 
-	cFYI(1, "In GetDFSRefer the path %s", search_name);
+	cifs_dbg(FYI, "In GetDFSRefer the path %s\n", search_name);
 	if (ses == NULL)
 		return -ENODEV;
 getDFSRetry:
@@ -4827,7 +4829,7 @@ getDFSRetry:
 	rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
-		cFYI(1, "Send error in GetDFSRefer = %d", rc);
+		cifs_dbg(FYI, "Send error in GetDFSRefer = %d\n", rc);
 		goto GetDFSRefExit;
 	}
 	rc = validate_t2((struct smb_t2_rsp *)pSMBr);
@@ -4838,9 +4840,8 @@ getDFSRetry:
 		goto GetDFSRefExit;
 	}
 
-	cFYI(1, "Decoding GetDFSRefer response BCC: %d  Offset %d",
-				get_bcc(&pSMBr->hdr),
-				le16_to_cpu(pSMBr->t2.DataOffset));
+	cifs_dbg(FYI, "Decoding GetDFSRefer response BCC: %d  Offset %d\n",
+		 get_bcc(&pSMBr->hdr), le16_to_cpu(pSMBr->t2.DataOffset));
 
 	/* parse returned result into more usable form */
 	rc = parse_DFS_referrals(pSMBr, num_of_nodes,
@@ -4869,7 +4870,7 @@ SMBOldQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
 	int bytes_returned = 0;
 	__u16 params, byte_count;
 
-	cFYI(1, "OldQFSInfo");
+	cifs_dbg(FYI, "OldQFSInfo\n");
 oldQFSInfoRetry:
 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
 		(void **) &pSMBr);
@@ -4902,7 +4903,7 @@ oldQFSInfoRetry:
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
-		cFYI(1, "Send error in QFSInfo = %d", rc);
+		cifs_dbg(FYI, "Send error in QFSInfo = %d\n", rc);
 	} else {                /* decode response */
 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
 
@@ -4910,7 +4911,7 @@ oldQFSInfoRetry:
 			rc = -EIO;      /* bad smb */
 		else {
 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
-			cFYI(1, "qfsinf resp BCC: %d  Offset %d",
+			cifs_dbg(FYI, "qfsinf resp BCC: %d  Offset %d\n",
 				 get_bcc(&pSMBr->hdr), data_offset);
 
 			response_data = (FILE_SYSTEM_ALLOC_INFO *)
@@ -4923,10 +4924,10 @@ oldQFSInfoRetry:
 			       le32_to_cpu(response_data->TotalAllocationUnits);
 			FSData->f_bfree = FSData->f_bavail =
 				le32_to_cpu(response_data->FreeAllocationUnits);
-			cFYI(1, "Blocks: %lld  Free: %lld Block size %ld",
-			     (unsigned long long)FSData->f_blocks,
-			     (unsigned long long)FSData->f_bfree,
-			     FSData->f_bsize);
+			cifs_dbg(FYI, "Blocks: %lld  Free: %lld Block size %ld\n",
+				 (unsigned long long)FSData->f_blocks,
+				 (unsigned long long)FSData->f_bfree,
+				 FSData->f_bsize);
 		}
 	}
 	cifs_buf_release(pSMB);
@@ -4949,7 +4950,7 @@ CIFSSMBQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
 	int bytes_returned = 0;
 	__u16 params, byte_count;
 
-	cFYI(1, "In QFSInfo");
+	cifs_dbg(FYI, "In QFSInfo\n");
 QFSInfoRetry:
 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
 		      (void **) &pSMBr);
@@ -4982,7 +4983,7 @@ QFSInfoRetry:
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
-		cFYI(1, "Send error in QFSInfo = %d", rc);
+		cifs_dbg(FYI, "Send error in QFSInfo = %d\n", rc);
 	} else {		/* decode response */
 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
 
@@ -5003,10 +5004,10 @@ QFSInfoRetry:
 			    le64_to_cpu(response_data->TotalAllocationUnits);
 			FSData->f_bfree = FSData->f_bavail =
 			    le64_to_cpu(response_data->FreeAllocationUnits);
-			cFYI(1, "Blocks: %lld  Free: %lld Block size %ld",
-			     (unsigned long long)FSData->f_blocks,
-			     (unsigned long long)FSData->f_bfree,
-			     FSData->f_bsize);
+			cifs_dbg(FYI, "Blocks: %lld  Free: %lld Block size %ld\n",
+				 (unsigned long long)FSData->f_blocks,
+				 (unsigned long long)FSData->f_bfree,
+				 FSData->f_bsize);
 		}
 	}
 	cifs_buf_release(pSMB);
@@ -5028,7 +5029,7 @@ CIFSSMBQFSAttributeInfo(const unsigned int xid, struct cifs_tcon *tcon)
 	int bytes_returned = 0;
 	__u16 params, byte_count;
 
-	cFYI(1, "In QFSAttributeInfo");
+	cifs_dbg(FYI, "In QFSAttributeInfo\n");
 QFSAttributeRetry:
 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
 		      (void **) &pSMBr);
@@ -5062,7 +5063,7 @@ QFSAttributeRetry:
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
-		cERROR(1, "Send error in QFSAttributeInfo = %d", rc);
+		cifs_dbg(VFS, "Send error in QFSAttributeInfo = %d\n", rc);
 	} else {		/* decode response */
 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
 
@@ -5098,7 +5099,7 @@ CIFSSMBQFSDeviceInfo(const unsigned int xid, struct cifs_tcon *tcon)
 	int bytes_returned = 0;
 	__u16 params, byte_count;
 
-	cFYI(1, "In QFSDeviceInfo");
+	cifs_dbg(FYI, "In QFSDeviceInfo\n");
 QFSDeviceRetry:
 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
 		      (void **) &pSMBr);
@@ -5133,7 +5134,7 @@ QFSDeviceRetry:
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
-		cFYI(1, "Send error in QFSDeviceInfo = %d", rc);
+		cifs_dbg(FYI, "Send error in QFSDeviceInfo = %d\n", rc);
 	} else {		/* decode response */
 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
 
@@ -5169,7 +5170,7 @@ CIFSSMBQFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon)
 	int bytes_returned = 0;
 	__u16 params, byte_count;
 
-	cFYI(1, "In QFSUnixInfo");
+	cifs_dbg(FYI, "In QFSUnixInfo\n");
 QFSUnixRetry:
 	rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
 				   (void **) &pSMB, (void **) &pSMBr);
@@ -5203,7 +5204,7 @@ QFSUnixRetry:
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
-		cERROR(1, "Send error in QFSUnixInfo = %d", rc);
+		cifs_dbg(VFS, "Send error in QFSUnixInfo = %d\n", rc);
 	} else {		/* decode response */
 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
 
@@ -5238,7 +5239,7 @@ CIFSSMBSetFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon, __u64 cap)
 	int bytes_returned = 0;
 	__u16 params, param_offset, offset, byte_count;
 
-	cFYI(1, "In SETFSUnixInfo");
+	cifs_dbg(FYI, "In SETFSUnixInfo\n");
 SETFSUnixRetry:
 	/* BB switch to small buf init to save memory */
 	rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
@@ -5286,7 +5287,7 @@ SETFSUnixRetry:
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
-		cERROR(1, "Send error in SETFSUnixInfo = %d", rc);
+		cifs_dbg(VFS, "Send error in SETFSUnixInfo = %d\n", rc);
 	} else {		/* decode response */
 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
 		if (rc)
@@ -5314,7 +5315,7 @@ CIFSSMBQFSPosixInfo(const unsigned int xid, struct cifs_tcon *tcon,
 	int bytes_returned = 0;
 	__u16 params, byte_count;
 
-	cFYI(1, "In QFSPosixInfo");
+	cifs_dbg(FYI, "In QFSPosixInfo\n");
 QFSPosixRetry:
 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
 		      (void **) &pSMBr);
@@ -5348,7 +5349,7 @@ QFSPosixRetry:
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
-		cFYI(1, "Send error in QFSUnixInfo = %d", rc);
+		cifs_dbg(FYI, "Send error in QFSUnixInfo = %d\n", rc);
 	} else {		/* decode response */
 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
 
@@ -5410,7 +5411,7 @@ CIFSSMBSetEOF(const unsigned int xid, struct cifs_tcon *tcon,
 
 	__u16 params, byte_count, data_count, param_offset, offset;
 
-	cFYI(1, "In SetEOF");
+	cifs_dbg(FYI, "In SetEOF\n");
 SetEOFRetry:
 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
 		      (void **) &pSMBr);
@@ -5476,7 +5477,7 @@ SetEOFRetry:
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc)
-		cFYI(1, "SetPathInfo (file size) returned %d", rc);
+		cifs_dbg(FYI, "SetPathInfo (file size) returned %d\n", rc);
 
 	cifs_buf_release(pSMB);
 
@@ -5495,8 +5496,8 @@ CIFSSMBSetFileSize(const unsigned int xid, struct cifs_tcon *tcon,
 	int rc = 0;
 	__u16 params, param_offset, offset, byte_count, count;
 
-	cFYI(1, "SetFileSize (via SetFileInfo) %lld",
-			(long long)size);
+	cifs_dbg(FYI, "SetFileSize (via SetFileInfo) %lld\n",
+		 (long long)size);
 	rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
 
 	if (rc)
@@ -5553,7 +5554,8 @@ CIFSSMBSetFileSize(const unsigned int xid, struct cifs_tcon *tcon,
 	pSMB->ByteCount = cpu_to_le16(byte_count);
 	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
 	if (rc) {
-		cFYI(1, "Send error in SetFileInfo (SetFileSize) = %d", rc);
+		cifs_dbg(FYI, "Send error in SetFileInfo (SetFileSize) = %d\n",
+			 rc);
 	}
 
 	/* Note: On -EAGAIN error only caller can retry on handle based calls
@@ -5577,7 +5579,7 @@ CIFSSMBSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
 	int rc = 0;
 	__u16 params, param_offset, offset, byte_count, count;
 
-	cFYI(1, "Set Times (via SetFileInfo)");
+	cifs_dbg(FYI, "Set Times (via SetFileInfo)\n");
 	rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
 
 	if (rc)
@@ -5623,7 +5625,8 @@ CIFSSMBSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
 	memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
 	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
 	if (rc)
-		cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc);
+		cifs_dbg(FYI, "Send error in Set Time (SetFileInfo) = %d\n",
+			 rc);
 
 	/* Note: On -EAGAIN error only caller can retry on handle based calls
 		since file handle passed in no longer valid */
@@ -5640,7 +5643,7 @@ CIFSSMBSetFileDisposition(const unsigned int xid, struct cifs_tcon *tcon,
 	int rc = 0;
 	__u16 params, param_offset, offset, byte_count, count;
 
-	cFYI(1, "Set File Disposition (via SetFileInfo)");
+	cifs_dbg(FYI, "Set File Disposition (via SetFileInfo)\n");
 	rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
 
 	if (rc)
@@ -5682,7 +5685,7 @@ CIFSSMBSetFileDisposition(const unsigned int xid, struct cifs_tcon *tcon,
 	*data_offset = delete_file ? 1 : 0;
 	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
 	if (rc)
-		cFYI(1, "Send error in SetFileDisposition = %d", rc);
+		cifs_dbg(FYI, "Send error in SetFileDisposition = %d\n", rc);
 
 	return rc;
 }
@@ -5700,7 +5703,7 @@ CIFSSMBSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
 	char *data_offset;
 	__u16 params, param_offset, offset, byte_count, count;
 
-	cFYI(1, "In SetTimes");
+	cifs_dbg(FYI, "In SetTimes\n");
 
 SetTimesRetry:
 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
@@ -5756,7 +5759,7 @@ SetTimesRetry:
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc)
-		cFYI(1, "SetPathInfo (times) returned %d", rc);
+		cifs_dbg(FYI, "SetPathInfo (times) returned %d\n", rc);
 
 	cifs_buf_release(pSMB);
 
@@ -5781,7 +5784,7 @@ CIFSSMBSetAttrLegacy(unsigned int xid, struct cifs_tcon *tcon, char *fileName,
 	int bytes_returned;
 	int name_len;
 
-	cFYI(1, "In SetAttrLegacy");
+	cifs_dbg(FYI, "In SetAttrLegacy\n");
 
 SetAttrLgcyRetry:
 	rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
@@ -5807,7 +5810,7 @@ SetAttrLgcyRetry:
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc)
-		cFYI(1, "Error in LegacySetAttr = %d", rc);
+		cifs_dbg(FYI, "Error in LegacySetAttr = %d\n", rc);
 
 	cifs_buf_release(pSMB);
 
@@ -5875,7 +5878,7 @@ CIFSSMBUnixSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
 	int rc = 0;
 	u16 params, param_offset, offset, byte_count, count;
 
-	cFYI(1, "Set Unix Info (via SetFileInfo)");
+	cifs_dbg(FYI, "Set Unix Info (via SetFileInfo)\n");
 	rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
 
 	if (rc)
@@ -5921,7 +5924,8 @@ CIFSSMBUnixSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
 
 	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
 	if (rc)
-		cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc);
+		cifs_dbg(FYI, "Send error in Set Time (SetFileInfo) = %d\n",
+			 rc);
 
 	/* Note: On -EAGAIN error only caller can retry on handle based calls
 		since file handle passed in no longer valid */
@@ -5943,7 +5947,7 @@ CIFSSMBUnixSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
 	FILE_UNIX_BASIC_INFO *data_offset;
 	__u16 params, param_offset, offset, count, byte_count;
 
-	cFYI(1, "In SetUID/GID/Mode");
+	cifs_dbg(FYI, "In SetUID/GID/Mode\n");
 setPermsRetry:
 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
 		      (void **) &pSMBr);
@@ -5999,7 +6003,7 @@ setPermsRetry:
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc)
-		cFYI(1, "SetPathInfo (perms) returned %d", rc);
+		cifs_dbg(FYI, "SetPathInfo (perms) returned %d\n", rc);
 
 	cifs_buf_release(pSMB);
 	if (rc == -EAGAIN)
@@ -6036,7 +6040,7 @@ CIFSSMBQAllEAs(const unsigned int xid, struct cifs_tcon *tcon,
 	__u16 params, byte_count, data_offset;
 	unsigned int ea_name_len = ea_name ? strlen(ea_name) : 0;
 
-	cFYI(1, "In Query All EAs path %s", searchName);
+	cifs_dbg(FYI, "In Query All EAs path %s\n", searchName);
 QAllEAsRetry:
 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
 		      (void **) &pSMBr);
@@ -6083,7 +6087,7 @@ QAllEAsRetry:
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
-		cFYI(1, "Send error in QueryAllEAs = %d", rc);
+		cifs_dbg(FYI, "Send error in QueryAllEAs = %d\n", rc);
 		goto QAllEAsOut;
 	}
 
@@ -6111,16 +6115,16 @@ QAllEAsRetry:
 				(((char *) &pSMBr->hdr.Protocol) + data_offset);
 
 	list_len = le32_to_cpu(ea_response_data->list_len);
-	cFYI(1, "ea length %d", list_len);
+	cifs_dbg(FYI, "ea length %d\n", list_len);
 	if (list_len <= 8) {
-		cFYI(1, "empty EA list returned from server");
+		cifs_dbg(FYI, "empty EA list returned from server\n");
 		goto QAllEAsOut;
 	}
 
 	/* make sure list_len doesn't go past end of SMB */
 	end_of_smb = (char *)pByteArea(&pSMBr->hdr) + get_bcc(&pSMBr->hdr);
 	if ((char *)ea_response_data + list_len > end_of_smb) {
-		cFYI(1, "EA list appears to go beyond SMB");
+		cifs_dbg(FYI, "EA list appears to go beyond SMB\n");
 		rc = -EIO;
 		goto QAllEAsOut;
 	}
@@ -6137,7 +6141,7 @@ QAllEAsRetry:
 		temp_ptr += 4;
 		/* make sure we can read name_len and value_len */
 		if (list_len < 0) {
-			cFYI(1, "EA entry goes beyond length of list");
+			cifs_dbg(FYI, "EA entry goes beyond length of list\n");
 			rc = -EIO;
 			goto QAllEAsOut;
 		}
@@ -6146,7 +6150,7 @@ QAllEAsRetry:
 		value_len = le16_to_cpu(temp_fea->value_len);
 		list_len -= name_len + 1 + value_len;
 		if (list_len < 0) {
-			cFYI(1, "EA entry goes beyond length of list");
+			cifs_dbg(FYI, "EA entry goes beyond length of list\n");
 			rc = -EIO;
 			goto QAllEAsOut;
 		}
@@ -6214,7 +6218,7 @@ CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon,
 	int bytes_returned = 0;
 	__u16 params, param_offset, byte_count, offset, count;
 
-	cFYI(1, "In SetEA");
+	cifs_dbg(FYI, "In SetEA\n");
 SetEARetry:
 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
 		      (void **) &pSMBr);
@@ -6296,7 +6300,7 @@ SetEARetry:
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc)
-		cFYI(1, "SetPathInfo (EA) returned %d", rc);
+		cifs_dbg(FYI, "SetPathInfo (EA) returned %d\n", rc);
 
 	cifs_buf_release(pSMB);
 
@@ -6339,7 +6343,7 @@ int CIFSSMBNotify(const unsigned int xid, struct cifs_tcon *tcon,
 	struct dir_notify_req *dnotify_req;
 	int bytes_returned;
 
-	cFYI(1, "In CIFSSMBNotify for file handle %d", (int)netfid);
+	cifs_dbg(FYI, "In CIFSSMBNotify for file handle %d\n", (int)netfid);
 	rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
 		      (void **) &pSMBr);
 	if (rc)
@@ -6368,7 +6372,7 @@ int CIFSSMBNotify(const unsigned int xid, struct cifs_tcon *tcon,
 			 (struct smb_hdr *)pSMBr, &bytes_returned,
 			 CIFS_ASYNC_OP);
 	if (rc) {
-		cFYI(1, "Error in Notify = %d", rc);
+		cifs_dbg(FYI, "Error in Notify = %d\n", rc);
 	} else {
 		/* Add file to outstanding requests */
 		/* BB change to kmem cache alloc */
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 991c63c..edb2220 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -95,9 +95,7 @@ enum {
 
 	/* Mount options which take string value */
 	Opt_user, Opt_pass, Opt_ip,
-	Opt_unc, Opt_domain,
-	Opt_srcaddr, Opt_prefixpath,
-	Opt_iocharset,
+	Opt_domain, Opt_srcaddr, Opt_iocharset,
 	Opt_netbiosname, Opt_servern,
 	Opt_ver, Opt_vers, Opt_sec, Opt_cache,
 
@@ -193,14 +191,14 @@ static const match_table_t cifs_mount_option_tokens = {
 	{ Opt_blank_ip, "addr=" },
 	{ Opt_ip, "ip=%s" },
 	{ Opt_ip, "addr=%s" },
-	{ Opt_unc, "unc=%s" },
-	{ Opt_unc, "target=%s" },
-	{ Opt_unc, "path=%s" },
+	{ Opt_ignore, "unc=%s" },
+	{ Opt_ignore, "target=%s" },
+	{ Opt_ignore, "path=%s" },
 	{ Opt_domain, "dom=%s" },
 	{ Opt_domain, "domain=%s" },
 	{ Opt_domain, "workgroup=%s" },
 	{ Opt_srcaddr, "srcaddr=%s" },
-	{ Opt_prefixpath, "prefixpath=%s" },
+	{ Opt_ignore, "prefixpath=%s" },
 	{ Opt_iocharset, "iocharset=%s" },
 	{ Opt_netbiosname, "netbiosname=%s" },
 	{ Opt_servern, "servern=%s" },
@@ -318,11 +316,12 @@ cifs_reconnect(struct TCP_Server_Info *server)
 	server->max_read = 0;
 #endif
 
-	cFYI(1, "Reconnecting tcp session");
+	cifs_dbg(FYI, "Reconnecting tcp session\n");
 
 	/* before reconnecting the tcp session, mark the smb session (uid)
 		and the tid bad so they are not used until reconnected */
-	cFYI(1, "%s: marking sessions and tcons for reconnect", __func__);
+	cifs_dbg(FYI, "%s: marking sessions and tcons for reconnect\n",
+		 __func__);
 	spin_lock(&cifs_tcp_ses_lock);
 	list_for_each(tmp, &server->smb_ses_list) {
 		ses = list_entry(tmp, struct cifs_ses, smb_ses_list);
@@ -336,15 +335,14 @@ cifs_reconnect(struct TCP_Server_Info *server)
 	spin_unlock(&cifs_tcp_ses_lock);
 
 	/* do not want to be sending data on a socket we are freeing */
-	cFYI(1, "%s: tearing down socket", __func__);
+	cifs_dbg(FYI, "%s: tearing down socket\n", __func__);
 	mutex_lock(&server->srv_mutex);
 	if (server->ssocket) {
-		cFYI(1, "State: 0x%x Flags: 0x%lx", server->ssocket->state,
-			server->ssocket->flags);
+		cifs_dbg(FYI, "State: 0x%x Flags: 0x%lx\n",
+			 server->ssocket->state, server->ssocket->flags);
 		kernel_sock_shutdown(server->ssocket, SHUT_WR);
-		cFYI(1, "Post shutdown state: 0x%x Flags: 0x%lx",
-			server->ssocket->state,
-			server->ssocket->flags);
+		cifs_dbg(FYI, "Post shutdown state: 0x%x Flags: 0x%lx\n",
+			 server->ssocket->state, server->ssocket->flags);
 		sock_release(server->ssocket);
 		server->ssocket = NULL;
 	}
@@ -358,7 +356,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
 
 	/* mark submitted MIDs for retry and issue callback */
 	INIT_LIST_HEAD(&retry_list);
-	cFYI(1, "%s: moving mids to private list", __func__);
+	cifs_dbg(FYI, "%s: moving mids to private list\n", __func__);
 	spin_lock(&GlobalMid_Lock);
 	list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
 		mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
@@ -368,7 +366,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
 	}
 	spin_unlock(&GlobalMid_Lock);
 
-	cFYI(1, "%s: issuing mid callbacks", __func__);
+	cifs_dbg(FYI, "%s: issuing mid callbacks\n", __func__);
 	list_for_each_safe(tmp, tmp2, &retry_list) {
 		mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
 		list_del_init(&mid_entry->qhead);
@@ -381,7 +379,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
 		/* we should try only the port we connected to before */
 		rc = generic_ip_connect(server);
 		if (rc) {
-			cFYI(1, "reconnect error %d", rc);
+			cifs_dbg(FYI, "reconnect error %d\n", rc);
 			msleep(3000);
 		} else {
 			atomic_inc(&tcpSesReconnectCount);
@@ -415,8 +413,8 @@ cifs_echo_request(struct work_struct *work)
 
 	rc = server->ops->echo ? server->ops->echo(server) : -ENOSYS;
 	if (rc)
-		cFYI(1, "Unable to send echo request to server: %s",
-			server->hostname);
+		cifs_dbg(FYI, "Unable to send echo request to server: %s\n",
+			 server->hostname);
 
 requeue_echo:
 	queue_delayed_work(cifsiod_wq, &server->echo, SMB_ECHO_INTERVAL);
@@ -428,7 +426,7 @@ allocate_buffers(struct TCP_Server_Info *server)
 	if (!server->bigbuf) {
 		server->bigbuf = (char *)cifs_buf_get();
 		if (!server->bigbuf) {
-			cERROR(1, "No memory for large SMB response");
+			cifs_dbg(VFS, "No memory for large SMB response\n");
 			msleep(3000);
 			/* retry will check if exiting */
 			return false;
@@ -441,7 +439,7 @@ allocate_buffers(struct TCP_Server_Info *server)
 	if (!server->smallbuf) {
 		server->smallbuf = (char *)cifs_small_buf_get();
 		if (!server->smallbuf) {
-			cERROR(1, "No memory for SMB response");
+			cifs_dbg(VFS, "No memory for SMB response\n");
 			msleep(1000);
 			/* retry will check if exiting */
 			return false;
@@ -471,9 +469,8 @@ server_unresponsive(struct TCP_Server_Info *server)
 	 */
 	if (server->tcpStatus == CifsGood &&
 	    time_after(jiffies, server->lstrp + 2 * SMB_ECHO_INTERVAL)) {
-		cERROR(1, "Server %s has not responded in %d seconds. "
-			  "Reconnecting...", server->hostname,
-			  (2 * SMB_ECHO_INTERVAL) / HZ);
+		cifs_dbg(VFS, "Server %s has not responded in %d seconds. Reconnecting...\n",
+			 server->hostname, (2 * SMB_ECHO_INTERVAL) / HZ);
 		cifs_reconnect(server);
 		wake_up(&server->response_q);
 		return true;
@@ -584,8 +581,8 @@ cifs_readv_from_socket(struct TCP_Server_Info *server, struct kvec *iov_orig,
 			length = 0;
 			continue;
 		} else if (length <= 0) {
-			cFYI(1, "Received no data or error: expecting %d "
-				"got %d", to_read, length);
+			cifs_dbg(FYI, "Received no data or error: expecting %d\n"
+				 "got %d", to_read, length);
 			cifs_reconnect(server);
 			total_read = -EAGAIN;
 			break;
@@ -619,17 +616,17 @@ is_smb_response(struct TCP_Server_Info *server, unsigned char type)
 		/* Regular SMB response */
 		return true;
 	case RFC1002_SESSION_KEEP_ALIVE:
-		cFYI(1, "RFC 1002 session keep alive");
+		cifs_dbg(FYI, "RFC 1002 session keep alive\n");
 		break;
 	case RFC1002_POSITIVE_SESSION_RESPONSE:
-		cFYI(1, "RFC 1002 positive session response");
+		cifs_dbg(FYI, "RFC 1002 positive session response\n");
 		break;
 	case RFC1002_NEGATIVE_SESSION_RESPONSE:
 		/*
 		 * We get this from Windows 98 instead of an error on
 		 * SMB negprot response.
 		 */
-		cFYI(1, "RFC 1002 negative session response");
+		cifs_dbg(FYI, "RFC 1002 negative session response\n");
 		/* give server a second to clean up */
 		msleep(1000);
 		/*
@@ -643,7 +640,7 @@ is_smb_response(struct TCP_Server_Info *server, unsigned char type)
 		wake_up(&server->response_q);
 		break;
 	default:
-		cERROR(1, "RFC 1002 unknown response type 0x%x", type);
+		cifs_dbg(VFS, "RFC 1002 unknown response type 0x%x\n", type);
 		cifs_reconnect(server);
 	}
 
@@ -729,7 +726,7 @@ static void clean_demultiplex_info(struct TCP_Server_Info *server)
 		spin_lock(&GlobalMid_Lock);
 		list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
 			mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
-			cFYI(1, "Clearing mid 0x%llx", mid_entry->mid);
+			cifs_dbg(FYI, "Clearing mid 0x%llx\n", mid_entry->mid);
 			mid_entry->mid_state = MID_SHUTDOWN;
 			list_move(&mid_entry->qhead, &dispose_list);
 		}
@@ -738,7 +735,7 @@ static void clean_demultiplex_info(struct TCP_Server_Info *server)
 		/* now walk dispose list and issue callbacks */
 		list_for_each_safe(tmp, tmp2, &dispose_list) {
 			mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
-			cFYI(1, "Callback mid 0x%llx", mid_entry->mid);
+			cifs_dbg(FYI, "Callback mid 0x%llx\n", mid_entry->mid);
 			list_del_init(&mid_entry->qhead);
 			mid_entry->callback(mid_entry);
 		}
@@ -755,7 +752,7 @@ static void clean_demultiplex_info(struct TCP_Server_Info *server)
 		 * least 45 seconds before giving up on a request getting a
 		 * response and going ahead and killing cifsd.
 		 */
-		cFYI(1, "Wait for exit from demultiplex thread");
+		cifs_dbg(FYI, "Wait for exit from demultiplex thread\n");
 		msleep(46000);
 		/*
 		 * If threads still have not exited they are probably never
@@ -782,8 +779,7 @@ standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
 
 	/* make sure this will fit in a large buffer */
 	if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) - 4) {
-		cERROR(1, "SMB response too long (%u bytes)",
-			pdu_length);
+		cifs_dbg(VFS, "SMB response too long (%u bytes)\n", pdu_length);
 		cifs_reconnect(server);
 		wake_up(&server->response_q);
 		return -EAGAIN;
@@ -841,7 +837,7 @@ cifs_demultiplex_thread(void *p)
 	struct mid_q_entry *mid_entry;
 
 	current->flags |= PF_MEMALLOC;
-	cFYI(1, "Demultiplex PID: %d", task_pid_nr(current));
+	cifs_dbg(FYI, "Demultiplex PID: %d\n", task_pid_nr(current));
 
 	length = atomic_inc_return(&tcpSesAllocCount);
 	if (length > 1)
@@ -871,14 +867,14 @@ cifs_demultiplex_thread(void *p)
 		 */
 		pdu_length = get_rfc1002_length(buf);
 
-		cFYI(1, "RFC1002 header 0x%x", pdu_length);
+		cifs_dbg(FYI, "RFC1002 header 0x%x\n", pdu_length);
 		if (!is_smb_response(server, buf[0]))
 			continue;
 
 		/* make sure we have enough to get to the MID */
 		if (pdu_length < HEADER_SIZE(server) - 1 - 4) {
-			cERROR(1, "SMB response too short (%u bytes)",
-				pdu_length);
+			cifs_dbg(VFS, "SMB response too short (%u bytes)\n",
+				 pdu_length);
 			cifs_reconnect(server);
 			wake_up(&server->response_q);
 			continue;
@@ -910,8 +906,8 @@ cifs_demultiplex_thread(void *p)
 				mid_entry->callback(mid_entry);
 		} else if (!server->ops->is_oplock_break ||
 			   !server->ops->is_oplock_break(buf, server)) {
-			cERROR(1, "No task to wake, unknown frame received! "
-				   "NumMids %d", atomic_read(&midCount));
+			cifs_dbg(VFS, "No task to wake, unknown frame received! NumMids %d\n",
+				 atomic_read(&midCount));
 			cifs_dump_mem("Received Data is: ", buf,
 				      HEADER_SIZE(server));
 #ifdef CONFIG_CIFS_DEBUG2
@@ -1037,7 +1033,7 @@ static int cifs_parse_security_flavors(char *value,
 		break;
 	case Opt_sec_krb5p:
 		/* vol->secFlg |= CIFSSEC_MUST_SEAL | CIFSSEC_MAY_KRB5; */
-		cERROR(1, "Krb5 cifs privacy not supported");
+		cifs_dbg(VFS, "Krb5 cifs privacy not supported\n");
 		break;
 	case Opt_sec_ntlmssp:
 		vol->secFlg |= CIFSSEC_MAY_NTLMSSP;
@@ -1067,7 +1063,7 @@ static int cifs_parse_security_flavors(char *value,
 		vol->nullauth = 1;
 		break;
 	default:
-		cERROR(1, "bad security option: %s", value);
+		cifs_dbg(VFS, "bad security option: %s\n", value);
 		return 1;
 	}
 
@@ -1093,7 +1089,7 @@ cifs_parse_cache_flavor(char *value, struct smb_vol *vol)
 		vol->strict_io = false;
 		break;
 	default:
-		cERROR(1, "bad cache= option: %s", value);
+		cifs_dbg(VFS, "bad cache= option: %s\n", value);
 		return 1;
 	}
 	return 0;
@@ -1124,7 +1120,7 @@ cifs_parse_smb_version(char *value, struct smb_vol *vol)
 		break;
 #endif
 	default:
-		cERROR(1, "Unknown vers= option specified: %s", value);
+		cifs_dbg(VFS, "Unknown vers= option specified: %s\n", value);
 		return 1;
 	}
 	return 0;
@@ -1255,7 +1251,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
 			separator[0] = options[4];
 			options += 5;
 		} else {
-			cFYI(1, "Null separator not allowed");
+			cifs_dbg(FYI, "Null separator not allowed\n");
 		}
 	}
 	vol->backupuid_specified = false; /* no backup intent for a user */
@@ -1440,8 +1436,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
 			break;
 		case Opt_fsc:
 #ifndef CONFIG_CIFS_FSCACHE
-			cERROR(1, "FS-Cache support needs CONFIG_CIFS_FSCACHE "
-				  "kernel config option set");
+			cifs_dbg(VFS, "FS-Cache support needs CONFIG_CIFS_FSCACHE kernel config option set\n");
 			goto cifs_parse_mount_err;
 #endif
 			vol->fsc = true;
@@ -1459,55 +1454,55 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
 		/* Numeric Values */
 		case Opt_backupuid:
 			if (get_option_uid(args, &vol->backupuid)) {
-				cERROR(1, "%s: Invalid backupuid value",
-					__func__);
+				cifs_dbg(VFS, "%s: Invalid backupuid value\n",
+					 __func__);
 				goto cifs_parse_mount_err;
 			}
 			vol->backupuid_specified = true;
 			break;
 		case Opt_backupgid:
 			if (get_option_gid(args, &vol->backupgid)) {
-				cERROR(1, "%s: Invalid backupgid value",
-					__func__);
+				cifs_dbg(VFS, "%s: Invalid backupgid value\n",
+					 __func__);
 				goto cifs_parse_mount_err;
 			}
 			vol->backupgid_specified = true;
 			break;
 		case Opt_uid:
 			if (get_option_uid(args, &vol->linux_uid)) {
-				cERROR(1, "%s: Invalid uid value",
-					__func__);
+				cifs_dbg(VFS, "%s: Invalid uid value\n",
+					 __func__);
 				goto cifs_parse_mount_err;
 			}
 			uid_specified = true;
 			break;
 		case Opt_cruid:
 			if (get_option_uid(args, &vol->cred_uid)) {
-				cERROR(1, "%s: Invalid cruid value",
-					__func__);
+				cifs_dbg(VFS, "%s: Invalid cruid value\n",
+					 __func__);
 				goto cifs_parse_mount_err;
 			}
 			break;
 		case Opt_gid:
 			if (get_option_gid(args, &vol->linux_gid)) {
-				cERROR(1, "%s: Invalid gid value",
-						__func__);
+				cifs_dbg(VFS, "%s: Invalid gid value\n",
+					 __func__);
 				goto cifs_parse_mount_err;
 			}
 			gid_specified = true;
 			break;
 		case Opt_file_mode:
 			if (get_option_ul(args, &option)) {
-				cERROR(1, "%s: Invalid file_mode value",
-					__func__);
+				cifs_dbg(VFS, "%s: Invalid file_mode value\n",
+					 __func__);
 				goto cifs_parse_mount_err;
 			}
 			vol->file_mode = option;
 			break;
 		case Opt_dirmode:
 			if (get_option_ul(args, &option)) {
-				cERROR(1, "%s: Invalid dir_mode value",
-					__func__);
+				cifs_dbg(VFS, "%s: Invalid dir_mode value\n",
+					 __func__);
 				goto cifs_parse_mount_err;
 			}
 			vol->dir_mode = option;
@@ -1515,37 +1510,37 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
 		case Opt_port:
 			if (get_option_ul(args, &option) ||
 			    option > USHRT_MAX) {
-				cERROR(1, "%s: Invalid port value", __func__);
+				cifs_dbg(VFS, "%s: Invalid port value\n",
+					 __func__);
 				goto cifs_parse_mount_err;
 			}
 			port = (unsigned short)option;
 			break;
 		case Opt_rsize:
 			if (get_option_ul(args, &option)) {
-				cERROR(1, "%s: Invalid rsize value",
-					__func__);
+				cifs_dbg(VFS, "%s: Invalid rsize value\n",
+					 __func__);
 				goto cifs_parse_mount_err;
 			}
 			vol->rsize = option;
 			break;
 		case Opt_wsize:
 			if (get_option_ul(args, &option)) {
-				cERROR(1, "%s: Invalid wsize value",
-					__func__);
+				cifs_dbg(VFS, "%s: Invalid wsize value\n",
+					 __func__);
 				goto cifs_parse_mount_err;
 			}
 			vol->wsize = option;
 			break;
 		case Opt_actimeo:
 			if (get_option_ul(args, &option)) {
-				cERROR(1, "%s: Invalid actimeo value",
-					__func__);
+				cifs_dbg(VFS, "%s: Invalid actimeo value\n",
+					 __func__);
 				goto cifs_parse_mount_err;
 			}
 			vol->actimeo = HZ * option;
 			if (vol->actimeo > CIFS_MAX_ACTIMEO) {
-				cERROR(1, "CIFS: attribute cache"
-					  "timeout too large");
+				cifs_dbg(VFS, "attribute cache timeout too large\n");
 				goto cifs_parse_mount_err;
 			}
 			break;
@@ -1568,11 +1563,8 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
 				goto cifs_parse_mount_err;
 			}
 			vol->username = kstrdup(string, GFP_KERNEL);
-			if (!vol->username) {
-				printk(KERN_WARNING "CIFS: no memory "
-						    "for username\n");
+			if (!vol->username)
 				goto cifs_parse_mount_err;
-			}
 			break;
 		case Opt_blank_pass:
 			vol->password = NULL;
@@ -1650,30 +1642,6 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
 			}
 			got_ip = true;
 			break;
-		case Opt_unc:
-			string = vol->UNC;
-			vol->UNC = match_strdup(args);
-			if (vol->UNC == NULL)
-				goto out_nomem;
-
-			convert_delimiter(vol->UNC, '\\');
-			if (vol->UNC[0] != '\\' || vol->UNC[1] != '\\') {
-				printk(KERN_ERR "CIFS: UNC Path does not "
-						"begin with // or \\\\\n");
-				goto cifs_parse_mount_err;
-			}
-
-			/* Compare old unc= option to new one */
-			if (!string || strcmp(string, vol->UNC))
-				printk(KERN_WARNING "CIFS: the value of the "
-					"unc= mount option does not match the "
-					"device string. Using the unc= option "
-					"for now. In 3.10, that option will "
-					"be ignored and the contents of the "
-					"device string will be used "
-					"instead. (%s != %s)\n", string,
-					vol->UNC);
-			break;
 		case Opt_domain:
 			string = match_strdup(args);
 			if (string == NULL)
@@ -1691,7 +1659,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
 						    "for domainname\n");
 				goto cifs_parse_mount_err;
 			}
-			cFYI(1, "Domain name set");
+			cifs_dbg(FYI, "Domain name set\n");
 			break;
 		case Opt_srcaddr:
 			string = match_strdup(args);
@@ -1706,26 +1674,6 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
 				goto cifs_parse_mount_err;
 			}
 			break;
-		case Opt_prefixpath:
-			/* skip over any leading delimiter */
-			if (*args[0].from == '/' || *args[0].from == '\\')
-				args[0].from++;
-
-			string = vol->prepath;
-			vol->prepath = match_strdup(args);
-			if (vol->prepath == NULL)
-				goto out_nomem;
-			/* Compare old prefixpath= option to new one */
-			if (!string || strcmp(string, vol->prepath))
-				printk(KERN_WARNING "CIFS: the value of the "
-					"prefixpath= mount option does not "
-					"match the device string. Using the "
-					"prefixpath= option for now. In 3.10, "
-					"that option will be ignored and the "
-					"contents of the device string will be "
-					"used instead.(%s != %s)\n", string,
-					vol->prepath);
-			break;
 		case Opt_iocharset:
 			string = match_strdup(args);
 			if (string == NULL)
@@ -1749,7 +1697,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
 			/* if iocharset not set then load_nls_default
 			 * is used by caller
 			 */
-			cFYI(1, "iocharset set to %s", string);
+			 cifs_dbg(FYI, "iocharset set to %s\n", string);
 			break;
 		case Opt_netbiosname:
 			string = match_strdup(args);
@@ -1863,20 +1811,18 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
 #ifndef CONFIG_KEYS
 	/* Muliuser mounts require CONFIG_KEYS support */
 	if (vol->multiuser) {
-		cERROR(1, "Multiuser mounts require kernels with "
-			  "CONFIG_KEYS enabled.");
+		cifs_dbg(VFS, "Multiuser mounts require kernels with CONFIG_KEYS enabled\n");
 		goto cifs_parse_mount_err;
 	}
 #endif
 	if (!vol->UNC) {
-		cERROR(1, "CIFS mount error: No usable UNC path provided in "
-			  "device string or in unc= option!");
+		cifs_dbg(VFS, "CIFS mount error: No usable UNC path provided in device string or in unc= option!\n");
 		goto cifs_parse_mount_err;
 	}
 
 	/* make sure UNC has a share name */
 	if (!strchr(vol->UNC + 3, '\\')) {
-		cERROR(1, "Malformed UNC. Unable to find share name.");
+		cifs_dbg(VFS, "Malformed UNC. Unable to find share name.\n");
 		goto cifs_parse_mount_err;
 	}
 
@@ -2097,7 +2043,7 @@ cifs_find_tcp_session(struct smb_vol *vol)
 
 		++server->srv_count;
 		spin_unlock(&cifs_tcp_ses_lock);
-		cFYI(1, "Existing tcp session with server found");
+		cifs_dbg(FYI, "Existing tcp session with server found\n");
 		return server;
 	}
 	spin_unlock(&cifs_tcp_ses_lock);
@@ -2144,7 +2090,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
 	struct TCP_Server_Info *tcp_ses = NULL;
 	int rc;
 
-	cFYI(1, "UNC: %s", volume_info->UNC);
+	cifs_dbg(FYI, "UNC: %s\n", volume_info->UNC);
 
 	/* see if we already have a matching tcp_ses */
 	tcp_ses = cifs_find_tcp_session(volume_info);
@@ -2159,7 +2105,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
 
 	rc = cifs_crypto_shash_allocate(tcp_ses);
 	if (rc) {
-		cERROR(1, "could not setup hash structures rc %d", rc);
+		cifs_dbg(VFS, "could not setup hash structures rc %d\n", rc);
 		goto out_err;
 	}
 
@@ -2206,7 +2152,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
 
 	rc = ip_connect(tcp_ses);
 	if (rc < 0) {
-		cERROR(1, "Error connecting to socket. Aborting operation");
+		cifs_dbg(VFS, "Error connecting to socket. Aborting operation.\n");
 		goto out_err_crypto_release;
 	}
 
@@ -2219,7 +2165,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
 				  tcp_ses, "cifsd");
 	if (IS_ERR(tcp_ses->tsk)) {
 		rc = PTR_ERR(tcp_ses->tsk);
-		cERROR(1, "error %d create cifsd thread", rc);
+		cifs_dbg(VFS, "error %d create cifsd thread\n", rc);
 		module_put(THIS_MODULE);
 		goto out_err_crypto_release;
 	}
@@ -2306,7 +2252,7 @@ cifs_put_smb_ses(struct cifs_ses *ses)
 	unsigned int xid;
 	struct TCP_Server_Info *server = ses->server;
 
-	cFYI(1, "%s: ses_count=%d", __func__, ses->ses_count);
+	cifs_dbg(FYI, "%s: ses_count=%d\n", __func__, ses->ses_count);
 	spin_lock(&cifs_tcp_ses_lock);
 	if (--ses->ses_count > 0) {
 		spin_unlock(&cifs_tcp_ses_lock);
@@ -2358,23 +2304,24 @@ cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
 		sprintf(desc, "cifs:a:%pI6c", &sa6->sin6_addr.s6_addr);
 		break;
 	default:
-		cFYI(1, "Bad ss_family (%hu)", server->dstaddr.ss_family);
+		cifs_dbg(FYI, "Bad ss_family (%hu)\n",
+			 server->dstaddr.ss_family);
 		rc = -EINVAL;
 		goto out_err;
 	}
 
-	cFYI(1, "%s: desc=%s", __func__, desc);
+	cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
 	key = request_key(&key_type_logon, desc, "");
 	if (IS_ERR(key)) {
 		if (!ses->domainName) {
-			cFYI(1, "domainName is NULL");
+			cifs_dbg(FYI, "domainName is NULL\n");
 			rc = PTR_ERR(key);
 			goto out_err;
 		}
 
 		/* didn't work, try to find a domain key */
 		sprintf(desc, "cifs:d:%s", ses->domainName);
-		cFYI(1, "%s: desc=%s", __func__, desc);
+		cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
 		key = request_key(&key_type_logon, desc, "");
 		if (IS_ERR(key)) {
 			rc = PTR_ERR(key);
@@ -2392,32 +2339,34 @@ cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
 	/* find first : in payload */
 	payload = (char *)upayload->data;
 	delim = strnchr(payload, upayload->datalen, ':');
-	cFYI(1, "payload=%s", payload);
+	cifs_dbg(FYI, "payload=%s\n", payload);
 	if (!delim) {
-		cFYI(1, "Unable to find ':' in payload (datalen=%d)",
-				upayload->datalen);
+		cifs_dbg(FYI, "Unable to find ':' in payload (datalen=%d)\n",
+			 upayload->datalen);
 		rc = -EINVAL;
 		goto out_key_put;
 	}
 
 	len = delim - payload;
 	if (len > MAX_USERNAME_SIZE || len <= 0) {
-		cFYI(1, "Bad value from username search (len=%zd)", len);
+		cifs_dbg(FYI, "Bad value from username search (len=%zd)\n",
+			 len);
 		rc = -EINVAL;
 		goto out_key_put;
 	}
 
 	vol->username = kstrndup(payload, len, GFP_KERNEL);
 	if (!vol->username) {
-		cFYI(1, "Unable to allocate %zd bytes for username", len);
+		cifs_dbg(FYI, "Unable to allocate %zd bytes for username\n",
+			 len);
 		rc = -ENOMEM;
 		goto out_key_put;
 	}
-	cFYI(1, "%s: username=%s", __func__, vol->username);
+	cifs_dbg(FYI, "%s: username=%s\n", __func__, vol->username);
 
 	len = key->datalen - (len + 1);
 	if (len > MAX_PASSWORD_SIZE || len <= 0) {
-		cFYI(1, "Bad len for password search (len=%zd)", len);
+		cifs_dbg(FYI, "Bad len for password search (len=%zd)\n", len);
 		rc = -EINVAL;
 		kfree(vol->username);
 		vol->username = NULL;
@@ -2427,7 +2376,8 @@ cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
 	++delim;
 	vol->password = kstrndup(delim, len, GFP_KERNEL);
 	if (!vol->password) {
-		cFYI(1, "Unable to allocate %zd bytes for password", len);
+		cifs_dbg(FYI, "Unable to allocate %zd bytes for password\n",
+			 len);
 		rc = -ENOMEM;
 		kfree(vol->username);
 		vol->username = NULL;
@@ -2439,7 +2389,7 @@ out_key_put:
 	key_put(key);
 out_err:
 	kfree(desc);
-	cFYI(1, "%s: returning %d", __func__, rc);
+	cifs_dbg(FYI, "%s: returning %d\n", __func__, rc);
 	return rc;
 }
 #else /* ! CONFIG_KEYS */
@@ -2464,7 +2414,8 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
 
 	ses = cifs_find_smb_ses(server, volume_info);
 	if (ses) {
-		cFYI(1, "Existing smb sess found (status=%d)", ses->status);
+		cifs_dbg(FYI, "Existing smb sess found (status=%d)\n",
+			 ses->status);
 
 		mutex_lock(&ses->session_mutex);
 		rc = cifs_negotiate_protocol(xid, ses);
@@ -2476,7 +2427,7 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
 			return ERR_PTR(rc);
 		}
 		if (ses->need_reconnect) {
-			cFYI(1, "Session needs reconnect");
+			cifs_dbg(FYI, "Session needs reconnect\n");
 			rc = cifs_setup_session(xid, ses,
 						volume_info->local_nls);
 			if (rc) {
@@ -2495,7 +2446,7 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
 		return ses;
 	}
 
-	cFYI(1, "Existing smb sess not found");
+	cifs_dbg(FYI, "Existing smb sess not found\n");
 	ses = sesInfoAlloc();
 	if (ses == NULL)
 		goto get_ses_fail;
@@ -2585,7 +2536,7 @@ cifs_put_tcon(struct cifs_tcon *tcon)
 	unsigned int xid;
 	struct cifs_ses *ses = tcon->ses;
 
-	cFYI(1, "%s: tc_count=%d", __func__, tcon->tc_count);
+	cifs_dbg(FYI, "%s: tc_count=%d\n", __func__, tcon->tc_count);
 	spin_lock(&cifs_tcp_ses_lock);
 	if (--tcon->tc_count > 0) {
 		spin_unlock(&cifs_tcp_ses_lock);
@@ -2613,12 +2564,11 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
 
 	tcon = cifs_find_tcon(ses, volume_info->UNC);
 	if (tcon) {
-		cFYI(1, "Found match on UNC path");
+		cifs_dbg(FYI, "Found match on UNC path\n");
 		/* existing tcon already has a reference */
 		cifs_put_smb_ses(ses);
 		if (tcon->seal != volume_info->seal)
-			cERROR(1, "transport encryption setting "
-				   "conflicts with existing tid");
+			cifs_dbg(VFS, "transport encryption setting conflicts with existing tid\n");
 		return tcon;
 	}
 
@@ -2650,13 +2600,13 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
 	rc = ses->server->ops->tree_connect(xid, ses, volume_info->UNC, tcon,
 					    volume_info->local_nls);
 	free_xid(xid);
-	cFYI(1, "Tcon rc = %d", rc);
+	cifs_dbg(FYI, "Tcon rc = %d\n", rc);
 	if (rc)
 		goto out_fail;
 
 	if (volume_info->nodfs) {
 		tcon->Flags &= ~SMB_SHARE_IS_IN_DFS;
-		cFYI(1, "DFS disabled (%d)", tcon->Flags);
+		cifs_dbg(FYI, "DFS disabled (%d)\n", tcon->Flags);
 	}
 	tcon->seal = volume_info->seal;
 	/*
@@ -2810,7 +2760,7 @@ get_dfs_path(const unsigned int xid, struct cifs_ses *ses, const char *old_path,
 		strcpy(temp_unc + 2 + strlen(ses->serverName), "\\IPC$");
 		rc = ses->server->ops->tree_connect(xid, ses, temp_unc, NULL,
 						    nls_codepage);
-		cFYI(1, "Tcon rc = %d ipc_tid = %d", rc, ses->ipc_tid);
+		cifs_dbg(FYI, "Tcon rc = %d ipc_tid = %d\n", rc, ses->ipc_tid);
 		kfree(temp_unc);
 	}
 	if (rc == 0)
@@ -2888,13 +2838,11 @@ bind_socket(struct TCP_Server_Info *server)
 			saddr4 = (struct sockaddr_in *)&server->srcaddr;
 			saddr6 = (struct sockaddr_in6 *)&server->srcaddr;
 			if (saddr6->sin6_family == AF_INET6)
-				cERROR(1, "cifs: "
-				       "Failed to bind to: %pI6c, error: %d",
-				       &saddr6->sin6_addr, rc);
+				cifs_dbg(VFS, "Failed to bind to: %pI6c, error: %d\n",
+					 &saddr6->sin6_addr, rc);
 			else
-				cERROR(1, "cifs: "
-				       "Failed to bind to: %pI4, error: %d",
-				       &saddr4->sin_addr.s_addr, rc);
+				cifs_dbg(VFS, "Failed to bind to: %pI4, error: %d\n",
+					 &saddr4->sin_addr.s_addr, rc);
 		}
 	}
 	return rc;
@@ -2999,13 +2947,13 @@ generic_ip_connect(struct TCP_Server_Info *server)
 		rc = __sock_create(cifs_net_ns(server), sfamily, SOCK_STREAM,
 				   IPPROTO_TCP, &socket, 1);
 		if (rc < 0) {
-			cERROR(1, "Error %d creating socket", rc);
+			cifs_dbg(VFS, "Error %d creating socket\n", rc);
 			server->ssocket = NULL;
 			return rc;
 		}
 
 		/* BB other socket options to set KEEPALIVE, NODELAY? */
-		cFYI(1, "Socket created");
+		cifs_dbg(FYI, "Socket created\n");
 		server->ssocket = socket;
 		socket->sk->sk_allocation = GFP_NOFS;
 		if (sfamily == AF_INET6)
@@ -3039,16 +2987,17 @@ generic_ip_connect(struct TCP_Server_Info *server)
 		rc = kernel_setsockopt(socket, SOL_TCP, TCP_NODELAY,
 				(char *)&val, sizeof(val));
 		if (rc)
-			cFYI(1, "set TCP_NODELAY socket option error %d", rc);
+			cifs_dbg(FYI, "set TCP_NODELAY socket option error %d\n",
+				 rc);
 	}
 
-	 cFYI(1, "sndbuf %d rcvbuf %d rcvtimeo 0x%lx",
+	cifs_dbg(FYI, "sndbuf %d rcvbuf %d rcvtimeo 0x%lx\n",
 		 socket->sk->sk_sndbuf,
 		 socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo);
 
 	rc = socket->ops->connect(socket, saddr, slen, 0);
 	if (rc < 0) {
-		cFYI(1, "Error %d connecting to server", rc);
+		cifs_dbg(FYI, "Error %d connecting to server\n", rc);
 		sock_release(socket);
 		server->ssocket = NULL;
 		return rc;
@@ -3106,19 +3055,19 @@ void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon,
 	if (vol_info && vol_info->no_linux_ext) {
 		tcon->fsUnixInfo.Capability = 0;
 		tcon->unix_ext = 0; /* Unix Extensions disabled */
-		cFYI(1, "Linux protocol extensions disabled");
+		cifs_dbg(FYI, "Linux protocol extensions disabled\n");
 		return;
 	} else if (vol_info)
 		tcon->unix_ext = 1; /* Unix Extensions supported */
 
 	if (tcon->unix_ext == 0) {
-		cFYI(1, "Unix extensions disabled so not set on reconnect");
+		cifs_dbg(FYI, "Unix extensions disabled so not set on reconnect\n");
 		return;
 	}
 
 	if (!CIFSSMBQFSUnixInfo(xid, tcon)) {
 		__u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
-		cFYI(1, "unix caps which server supports %lld", cap);
+		cifs_dbg(FYI, "unix caps which server supports %lld\n", cap);
 		/* check for reconnect case in which we do not
 		   want to change the mount behavior if we can avoid it */
 		if (vol_info == NULL) {
@@ -3128,22 +3077,22 @@ void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon,
 				cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
 			if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
 				if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
-					cERROR(1, "POSIXPATH support change");
+					cifs_dbg(VFS, "POSIXPATH support change\n");
 				cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
 			} else if ((cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
-				cERROR(1, "possible reconnect error");
-				cERROR(1, "server disabled POSIX path support");
+				cifs_dbg(VFS, "possible reconnect error\n");
+				cifs_dbg(VFS, "server disabled POSIX path support\n");
 			}
 		}
 
 		if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
-			cERROR(1, "per-share encryption not supported yet");
+			cifs_dbg(VFS, "per-share encryption not supported yet\n");
 
 		cap &= CIFS_UNIX_CAP_MASK;
 		if (vol_info && vol_info->no_psx_acl)
 			cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
 		else if (CIFS_UNIX_POSIX_ACL_CAP & cap) {
-			cFYI(1, "negotiated posix acl support");
+			cifs_dbg(FYI, "negotiated posix acl support\n");
 			if (cifs_sb)
 				cifs_sb->mnt_cifs_flags |=
 					CIFS_MOUNT_POSIXACL;
@@ -3152,43 +3101,38 @@ void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon,
 		if (vol_info && vol_info->posix_paths == 0)
 			cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
 		else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
-			cFYI(1, "negotiate posix pathnames");
+			cifs_dbg(FYI, "negotiate posix pathnames\n");
 			if (cifs_sb)
 				cifs_sb->mnt_cifs_flags |=
 					CIFS_MOUNT_POSIX_PATHS;
 		}
 
-		cFYI(1, "Negotiate caps 0x%x", (int)cap);
+		cifs_dbg(FYI, "Negotiate caps 0x%x\n", (int)cap);
 #ifdef CONFIG_CIFS_DEBUG2
 		if (cap & CIFS_UNIX_FCNTL_CAP)
-			cFYI(1, "FCNTL cap");
+			cifs_dbg(FYI, "FCNTL cap\n");
 		if (cap & CIFS_UNIX_EXTATTR_CAP)
-			cFYI(1, "EXTATTR cap");
+			cifs_dbg(FYI, "EXTATTR cap\n");
 		if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
-			cFYI(1, "POSIX path cap");
+			cifs_dbg(FYI, "POSIX path cap\n");
 		if (cap & CIFS_UNIX_XATTR_CAP)
-			cFYI(1, "XATTR cap");
+			cifs_dbg(FYI, "XATTR cap\n");
 		if (cap & CIFS_UNIX_POSIX_ACL_CAP)
-			cFYI(1, "POSIX ACL cap");
+			cifs_dbg(FYI, "POSIX ACL cap\n");
 		if (cap & CIFS_UNIX_LARGE_READ_CAP)
-			cFYI(1, "very large read cap");
+			cifs_dbg(FYI, "very large read cap\n");
 		if (cap & CIFS_UNIX_LARGE_WRITE_CAP)
-			cFYI(1, "very large write cap");
+			cifs_dbg(FYI, "very large write cap\n");
 		if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)
-			cFYI(1, "transport encryption cap");
+			cifs_dbg(FYI, "transport encryption cap\n");
 		if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
-			cFYI(1, "mandatory transport encryption cap");
+			cifs_dbg(FYI, "mandatory transport encryption cap\n");
 #endif /* CIFS_DEBUG2 */
 		if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
 			if (vol_info == NULL) {
-				cFYI(1, "resetting capabilities failed");
+				cifs_dbg(FYI, "resetting capabilities failed\n");
 			} else
-				cERROR(1, "Negotiating Unix capabilities "
-					   "with the server failed. Consider "
-					   "mounting with the Unix Extensions "
-					   "disabled if problems are found "
-					   "by specifying the nounix mount "
-					   "option.");
+				cifs_dbg(VFS, "Negotiating Unix capabilities with the server failed. Consider mounting with the Unix Extensions disabled if problems are found by specifying the nounix mount option.\n");
 
 		}
 	}
@@ -3213,8 +3157,8 @@ void cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
 	cifs_sb->mnt_gid = pvolume_info->linux_gid;
 	cifs_sb->mnt_file_mode = pvolume_info->file_mode;
 	cifs_sb->mnt_dir_mode = pvolume_info->dir_mode;
-	cFYI(1, "file mode: 0x%hx  dir mode: 0x%hx",
-		cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode);
+	cifs_dbg(FYI, "file mode: 0x%hx  dir mode: 0x%hx\n",
+		 cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode);
 
 	cifs_sb->actimeo = pvolume_info->actimeo;
 	cifs_sb->local_nls = pvolume_info->local_nls;
@@ -3263,21 +3207,19 @@ void cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
 	if (pvolume_info->strict_io)
 		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_STRICT_IO;
 	if (pvolume_info->direct_io) {
-		cFYI(1, "mounting share using direct i/o");
+		cifs_dbg(FYI, "mounting share using direct i/o\n");
 		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
 	}
 	if (pvolume_info->mfsymlinks) {
 		if (pvolume_info->sfu_emul) {
-			cERROR(1,  "mount option mfsymlinks ignored if sfu "
-				   "mount option is used");
+			cifs_dbg(VFS, "mount option mfsymlinks ignored if sfu mount option is used\n");
 		} else {
 			cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MF_SYMLINKS;
 		}
 	}
 
 	if ((pvolume_info->cifs_acl) && (pvolume_info->dynperm))
-		cERROR(1, "mount option dynperm ignored if cifsacl "
-			   "mount option supported");
+		cifs_dbg(VFS, "mount option dynperm ignored if cifsacl mount option supported\n");
 }
 
 static void
@@ -3329,7 +3271,7 @@ build_unc_path_to_root(const struct smb_vol *vol,
 
 	*pos = '\0'; /* add trailing null */
 	convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
-	cFYI(1, "%s: full_path=%s", __func__, full_path);
+	cifs_dbg(FYI, "%s: full_path=%s\n", __func__, full_path);
 	return full_path;
 }
 
@@ -3400,14 +3342,14 @@ cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
 		return -EINVAL;
 
 	if (volume_info->nullauth) {
-		cFYI(1, "Anonymous login");
+		cifs_dbg(FYI, "Anonymous login\n");
 		kfree(volume_info->username);
 		volume_info->username = NULL;
 	} else if (volume_info->username) {
 		/* BB fixme parse for domain name here */
-		cFYI(1, "Username: %s", volume_info->username);
+		cifs_dbg(FYI, "Username: %s\n", volume_info->username);
 	} else {
-		cifserror("No username specified");
+		cifs_dbg(VFS, "No username specified\n");
 	/* In userspace mount helper we can get user name from alternate
 	   locations such as env variables and files on disk */
 		return -EINVAL;
@@ -3420,7 +3362,7 @@ cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
 	} else {
 		volume_info->local_nls = load_nls(volume_info->iocharset);
 		if (volume_info->local_nls == NULL) {
-			cERROR(1, "CIFS mount error: iocharset %s not found",
+			cifs_dbg(VFS, "CIFS mount error: iocharset %s not found\n",
 				 volume_info->iocharset);
 			return -ELIBACC;
 		}
@@ -3770,13 +3712,13 @@ CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
 		if (length == 3) {
 			if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
 			    (bcc_ptr[2] == 'C')) {
-				cFYI(1, "IPC connection");
+				cifs_dbg(FYI, "IPC connection\n");
 				tcon->ipc = 1;
 			}
 		} else if (length == 2) {
 			if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) {
 				/* the most common case */
-				cFYI(1, "disk share connection");
+				cifs_dbg(FYI, "disk share connection\n");
 			}
 		}
 		bcc_ptr += length + 1;
@@ -3789,7 +3731,7 @@ CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
 						      bytes_left, is_unicode,
 						      nls_codepage);
 
-		cFYI(1, "nativeFileSystem=%s", tcon->nativeFileSystem);
+		cifs_dbg(FYI, "nativeFileSystem=%s\n", tcon->nativeFileSystem);
 
 		if ((smb_buffer_response->WordCount == 3) ||
 			 (smb_buffer_response->WordCount == 7))
@@ -3797,7 +3739,7 @@ CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
 			tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
 		else
 			tcon->Flags = 0;
-		cFYI(1, "Tcon flags: 0x%x ", tcon->Flags);
+		cifs_dbg(FYI, "Tcon flags: 0x%x\n", tcon->Flags);
 	} else if ((rc == 0) && tcon == NULL) {
 		/* all we need to save for IPC$ connection */
 		ses->ipc_tid = smb_buffer_response->Tid;
@@ -3875,14 +3817,14 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
 	if (linuxExtEnabled == 0)
 		ses->capabilities &= (~server->vals->cap_unix);
 
-	cFYI(1, "Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d",
+	cifs_dbg(FYI, "Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d\n",
 		 server->sec_mode, server->capabilities, server->timeAdj);
 
 	if (server->ops->sess_setup)
 		rc = server->ops->sess_setup(xid, ses, nls_info);
 
 	if (rc) {
-		cERROR(1, "Send error in SessSetup = %d", rc);
+		cifs_dbg(VFS, "Send error in SessSetup = %d\n", rc);
 	} else {
 		mutex_lock(&ses->server->srv_mutex);
 		if (!server->session_estab) {
@@ -3894,7 +3836,7 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
 		}
 		mutex_unlock(&server->srv_mutex);
 
-		cFYI(1, "CIFS Session Established successfully");
+		cifs_dbg(FYI, "CIFS Session Established successfully\n");
 		spin_lock(&GlobalMid_Lock);
 		ses->status = CifsGood;
 		ses->need_reconnect = false;
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 1cd0162..46e455e 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -102,7 +102,7 @@ cifs_bp_rename_retry:
 		namelen += (1 + temp->d_name.len);
 		temp = temp->d_parent;
 		if (temp == NULL) {
-			cERROR(1, "corrupt dentry");
+			cifs_dbg(VFS, "corrupt dentry\n");
 			rcu_read_unlock();
 			return NULL;
 		}
@@ -124,12 +124,12 @@ cifs_bp_rename_retry:
 			full_path[namelen] = dirsep;
 			strncpy(full_path + namelen + 1, temp->d_name.name,
 				temp->d_name.len);
-			cFYI(0, "name: %s", full_path + namelen);
+			cifs_dbg(FYI, "name: %s\n", full_path + namelen);
 		}
 		spin_unlock(&temp->d_lock);
 		temp = temp->d_parent;
 		if (temp == NULL) {
-			cERROR(1, "corrupt dentry");
+			cifs_dbg(VFS, "corrupt dentry\n");
 			rcu_read_unlock();
 			kfree(full_path);
 			return NULL;
@@ -137,8 +137,8 @@ cifs_bp_rename_retry:
 	}
 	rcu_read_unlock();
 	if (namelen != dfsplen || read_seqretry(&rename_lock, seq)) {
-		cFYI(1, "did not end path lookup where expected. namelen=%d "
-			"dfsplen=%d", namelen, dfsplen);
+		cifs_dbg(FYI, "did not end path lookup where expected. namelen=%ddfsplen=%d\n",
+			 namelen, dfsplen);
 		/* presumably this is only possible if racing with a rename
 		of one of the parent directories  (we can not lock the dentries
 		above us to prevent this, but retrying should be harmless) */
@@ -178,7 +178,7 @@ check_name(struct dentry *direntry)
 	if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)) {
 		for (i = 0; i < direntry->d_name.len; i++) {
 			if (direntry->d_name.name[i] == '\\') {
-				cFYI(1, "Invalid file name");
+				cifs_dbg(FYI, "Invalid file name\n");
 				return -EINVAL;
 			}
 		}
@@ -291,7 +291,7 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
 	else if ((oflags & O_CREAT) == O_CREAT)
 		disposition = FILE_OPEN_IF;
 	else
-		cFYI(1, "Create flag not set in create function");
+		cifs_dbg(FYI, "Create flag not set in create function\n");
 
 	/*
 	 * BB add processing to set equivalent of mode - e.g. via CreateX with
@@ -323,7 +323,7 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
 			       desired_access, create_options, fid, oplock,
 			       buf, cifs_sb);
 	if (rc) {
-		cFYI(1, "cifs_create returned 0x%x", rc);
+		cifs_dbg(FYI, "cifs_create returned 0x%x\n", rc);
 		goto out;
 	}
 
@@ -389,7 +389,8 @@ cifs_create_get_file_info:
 
 cifs_create_set_dentry:
 	if (rc != 0) {
-		cFYI(1, "Create worked, get_inode_info failed rc = %d", rc);
+		cifs_dbg(FYI, "Create worked, get_inode_info failed rc = %d\n",
+			 rc);
 		if (server->ops->close)
 			server->ops->close(xid, tcon, fid);
 		goto out;
@@ -452,8 +453,8 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry,
 
 	xid = get_xid();
 
-	cFYI(1, "parent inode = 0x%p name is: %s and dentry = 0x%p",
-	     inode, direntry->d_name.name, direntry);
+	cifs_dbg(FYI, "parent inode = 0x%p name is: %s and dentry = 0x%p\n",
+		 inode, direntry->d_name.name, direntry);
 
 	tlink = cifs_sb_tlink(CIFS_SB(inode->i_sb));
 	if (IS_ERR(tlink))
@@ -518,8 +519,8 @@ int cifs_create(struct inode *inode, struct dentry *direntry, umode_t mode,
 	__u32 oplock;
 	int created = FILE_CREATED;
 
-	cFYI(1, "cifs_create parent inode = 0x%p name is: %s and dentry = 0x%p",
-	     inode, direntry->d_name.name, direntry);
+	cifs_dbg(FYI, "cifs_create parent inode = 0x%p name is: %s and dentry = 0x%p\n",
+		 inode, direntry->d_name.name, direntry);
 
 	tlink = cifs_sb_tlink(CIFS_SB(inode->i_sb));
 	rc = PTR_ERR(tlink);
@@ -613,7 +614,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode,
 		goto mknod_out;
 
 
-	cFYI(1, "sfu compat create special file");
+	cifs_dbg(FYI, "sfu compat create special file\n");
 
 	buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
 	if (buf == NULL) {
@@ -688,8 +689,8 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
 
 	xid = get_xid();
 
-	cFYI(1, "parent inode = 0x%p name is: %s and dentry = 0x%p",
-	      parent_dir_inode, direntry->d_name.name, direntry);
+	cifs_dbg(FYI, "parent inode = 0x%p name is: %s and dentry = 0x%p\n",
+		 parent_dir_inode, direntry->d_name.name, direntry);
 
 	/* check whether path exists */
 
@@ -715,11 +716,12 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
 	}
 
 	if (direntry->d_inode != NULL) {
-		cFYI(1, "non-NULL inode in lookup");
+		cifs_dbg(FYI, "non-NULL inode in lookup\n");
 	} else {
-		cFYI(1, "NULL inode in lookup");
+		cifs_dbg(FYI, "NULL inode in lookup\n");
 	}
-	cFYI(1, "Full path: %s inode = 0x%p", full_path, direntry->d_inode);
+	cifs_dbg(FYI, "Full path: %s inode = 0x%p\n",
+		 full_path, direntry->d_inode);
 
 	if (pTcon->unix_ext) {
 		rc = cifs_get_inode_info_unix(&newInode, full_path,
@@ -742,7 +744,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
 	/*	if it was once a directory (but how can we tell?) we could do
 		shrink_dcache_parent(direntry); */
 	} else if (rc != -EACCES) {
-		cERROR(1, "Unexpected lookup error %d", rc);
+		cifs_dbg(VFS, "Unexpected lookup error %d\n", rc);
 		/* We special case check for Access Denied - since that
 		is a common return code */
 	}
@@ -807,7 +809,7 @@ cifs_d_revalidate(struct dentry *direntry, unsigned int flags)
 {
 	int rc = 0;
 
-	cFYI(1, "In cifs d_delete, name = %s", direntry->d_name.name);
+	cifs_dbg(FYI, "In cifs d_delete, name = %s\n", direntry->d_name.name);
 
 	return rc;
 }     */
diff --git a/fs/cifs/dns_resolve.c b/fs/cifs/dns_resolve.c
index 1d2d91d..e7512e4 100644
--- a/fs/cifs/dns_resolve.c
+++ b/fs/cifs/dns_resolve.c
@@ -55,7 +55,7 @@ dns_resolve_server_name_to_ip(const char *unc, char **ip_addr)
 
 	len = strlen(unc);
 	if (len < 3) {
-		cFYI(1, "%s: unc is too short: %s", __func__, unc);
+		cifs_dbg(FYI, "%s: unc is too short: %s\n", __func__, unc);
 		return -EINVAL;
 	}
 
@@ -68,8 +68,8 @@ dns_resolve_server_name_to_ip(const char *unc, char **ip_addr)
 	if (sep)
 		len = sep - hostname;
 	else
-		cFYI(1, "%s: probably server name is whole unc: %s",
-		     __func__, unc);
+		cifs_dbg(FYI, "%s: probably server name is whole unc: %s\n",
+			 __func__, unc);
 
 	/* Try to interpret hostname as an IPv4 or IPv6 address */
 	rc = cifs_convert_address((struct sockaddr *)&ss, hostname, len);
@@ -79,11 +79,11 @@ dns_resolve_server_name_to_ip(const char *unc, char **ip_addr)
 	/* Perform the upcall */
 	rc = dns_query(NULL, hostname, len, NULL, ip_addr, NULL);
 	if (rc < 0)
-		cFYI(1, "%s: unable to resolve: %*.*s",
-			__func__, len, len, hostname);
+		cifs_dbg(FYI, "%s: unable to resolve: %*.*s\n",
+			 __func__, len, len, hostname);
 	else
-		cFYI(1, "%s: resolved: %*.*s to %s",
-		     __func__, len, len, hostname, *ip_addr);
+		cifs_dbg(FYI, "%s: resolved: %*.*s to %s\n",
+			 __func__, len, len, hostname, *ip_addr);
 	return rc;
 
 name_is_IP_address:
@@ -92,7 +92,8 @@ name_is_IP_address:
 		return -ENOMEM;
 	memcpy(name, hostname, len);
 	name[len] = 0;
-	cFYI(1, "%s: unc is IP, skipping dns upcall: %s", __func__, name);
+	cifs_dbg(FYI, "%s: unc is IP, skipping dns upcall: %s\n",
+		 __func__, name);
 	*ip_addr = name;
 	return 0;
 }
diff --git a/fs/cifs/export.c b/fs/cifs/export.c
index 9c7ecdc..ce8b7f6 100644
--- a/fs/cifs/export.c
+++ b/fs/cifs/export.c
@@ -49,7 +49,7 @@
 static struct dentry *cifs_get_parent(struct dentry *dentry)
 {
 	/* BB need to add code here eventually to enable export via NFSD */
-	cFYI(1, "get parent for %p", dentry);
+	cifs_dbg(FYI, "get parent for %p\n", dentry);
 	return ERR_PTR(-EACCES);
 }
 
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 7a0dd99..48b29d2 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -78,9 +78,8 @@ static u32 cifs_posix_convert_flags(unsigned int flags)
 		if (flags & O_EXCL)
 			posix_flags |= SMB_O_EXCL;
 	} else if (flags & O_EXCL)
-		cFYI(1, "Application %s pid %d has incorrectly set O_EXCL flag"
-			"but not O_CREAT on file open. Ignoring O_EXCL",
-			current->comm, current->tgid);
+		cifs_dbg(FYI, "Application %s pid %d has incorrectly set O_EXCL flag but not O_CREAT on file open. Ignoring O_EXCL\n",
+			 current->comm, current->tgid);
 
 	if (flags & O_TRUNC)
 		posix_flags |= SMB_O_TRUNC;
@@ -123,7 +122,7 @@ int cifs_posix_open(char *full_path, struct inode **pinode,
 	struct tcon_link *tlink;
 	struct cifs_tcon *tcon;
 
-	cFYI(1, "posix open %s", full_path);
+	cifs_dbg(FYI, "posix open %s\n", full_path);
 
 	presp_data = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
 	if (presp_data == NULL)
@@ -308,7 +307,7 @@ cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
 	 */
 	if (oplock == server->vals->oplock_read &&
 						cifs_has_mand_locks(cinode)) {
-		cFYI(1, "Reset oplock val from read to None due to mand locks");
+		cifs_dbg(FYI, "Reset oplock val from read to None due to mand locks\n");
 		oplock = 0;
 	}
 
@@ -374,8 +373,8 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file)
 	list_del(&cifs_file->tlist);
 
 	if (list_empty(&cifsi->openFileList)) {
-		cFYI(1, "closing last open instance for inode %p",
-			cifs_file->dentry->d_inode);
+		cifs_dbg(FYI, "closing last open instance for inode %p\n",
+			 cifs_file->dentry->d_inode);
 		/*
 		 * In strict cache mode we need invalidate mapping on the last
 		 * close  because it may cause a error when we open this file
@@ -454,7 +453,7 @@ int cifs_open(struct inode *inode, struct file *file)
 		goto out;
 	}
 
-	cFYI(1, "inode = 0x%p file flags are 0x%x for %s",
+	cifs_dbg(FYI, "inode = 0x%p file flags are 0x%x for %s\n",
 		 inode, file->f_flags, full_path);
 
 	if (server->oplocks)
@@ -470,16 +469,13 @@ int cifs_open(struct inode *inode, struct file *file)
 				cifs_sb->mnt_file_mode /* ignored */,
 				file->f_flags, &oplock, &fid.netfid, xid);
 		if (rc == 0) {
-			cFYI(1, "posix open succeeded");
+			cifs_dbg(FYI, "posix open succeeded\n");
 			posix_open_ok = true;
 		} else if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
 			if (tcon->ses->serverNOS)
-				cERROR(1, "server %s of type %s returned"
-					   " unexpected error on SMB posix open"
-					   ", disabling posix open support."
-					   " Check if server update available.",
-					   tcon->ses->serverName,
-					   tcon->ses->serverNOS);
+				cifs_dbg(VFS, "server %s of type %s returned unexpected error on SMB posix open, disabling posix open support. Check if server update available.\n",
+					 tcon->ses->serverName,
+					 tcon->ses->serverNOS);
 			tcon->broken_posix_open = true;
 		} else if ((rc != -EIO) && (rc != -EREMOTE) &&
 			 (rc != -EOPNOTSUPP)) /* path not found or net err */
@@ -621,8 +617,8 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush)
 		return rc;
 	}
 
-	cFYI(1, "inode = 0x%p file flags 0x%x for %s", inode, cfile->f_flags,
-	     full_path);
+	cifs_dbg(FYI, "inode = 0x%p file flags 0x%x for %s\n",
+		 inode, cfile->f_flags, full_path);
 
 	if (tcon->ses->server->oplocks)
 		oplock = REQ_OPLOCK;
@@ -643,7 +639,7 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush)
 				     cifs_sb->mnt_file_mode /* ignored */,
 				     oflags, &oplock, &fid.netfid, xid);
 		if (rc == 0) {
-			cFYI(1, "posix reopen succeeded");
+			cifs_dbg(FYI, "posix reopen succeeded\n");
 			goto reopen_success;
 		}
 		/*
@@ -672,8 +668,8 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush)
 			       NULL, cifs_sb);
 	if (rc) {
 		mutex_unlock(&cfile->fh_mutex);
-		cFYI(1, "cifs_reopen returned 0x%x", rc);
-		cFYI(1, "oplock: %d", oplock);
+		cifs_dbg(FYI, "cifs_reopen returned 0x%x\n", rc);
+		cifs_dbg(FYI, "oplock: %d\n", oplock);
 		goto reopen_error_exit;
 	}
 
@@ -729,7 +725,7 @@ int cifs_closedir(struct inode *inode, struct file *file)
 	struct TCP_Server_Info *server;
 	char *buf;
 
-	cFYI(1, "Closedir inode = 0x%p", inode);
+	cifs_dbg(FYI, "Closedir inode = 0x%p\n", inode);
 
 	if (cfile == NULL)
 		return rc;
@@ -738,7 +734,7 @@ int cifs_closedir(struct inode *inode, struct file *file)
 	tcon = tlink_tcon(cfile->tlink);
 	server = tcon->ses->server;
 
-	cFYI(1, "Freeing private data in close dir");
+	cifs_dbg(FYI, "Freeing private data in close dir\n");
 	spin_lock(&cifs_file_list_lock);
 	if (!cfile->srch_inf.endOfSearch && !cfile->invalidHandle) {
 		cfile->invalidHandle = true;
@@ -747,7 +743,7 @@ int cifs_closedir(struct inode *inode, struct file *file)
 			rc = server->ops->close_dir(xid, tcon, &cfile->fid);
 		else
 			rc = -ENOSYS;
-		cFYI(1, "Closing uncompleted readdir with rc %d", rc);
+		cifs_dbg(FYI, "Closing uncompleted readdir with rc %d\n", rc);
 		/* not much we can do if it fails anyway, ignore rc */
 		rc = 0;
 	} else
@@ -755,7 +751,7 @@ int cifs_closedir(struct inode *inode, struct file *file)
 
 	buf = cfile->srch_inf.ntwrk_buf_start;
 	if (buf) {
-		cFYI(1, "closedir free smb buf in srch struct");
+		cifs_dbg(FYI, "closedir free smb buf in srch struct\n");
 		cfile->srch_inf.ntwrk_buf_start = NULL;
 		if (cfile->srch_inf.smallBuf)
 			cifs_small_buf_release(buf);
@@ -1140,7 +1136,7 @@ cifs_push_posix_locks(struct cifsFileInfo *cfile)
 			 * The list ended. We don't have enough allocated
 			 * structures - something is really wrong.
 			 */
-			cERROR(1, "Can't push all brlocks!");
+			cifs_dbg(VFS, "Can't push all brlocks!\n");
 			break;
 		}
 		length = 1 + flock->fl_end - flock->fl_start;
@@ -1213,47 +1209,46 @@ cifs_read_flock(struct file_lock *flock, __u32 *type, int *lock, int *unlock,
 		bool *wait_flag, struct TCP_Server_Info *server)
 {
 	if (flock->fl_flags & FL_POSIX)
-		cFYI(1, "Posix");
+		cifs_dbg(FYI, "Posix\n");
 	if (flock->fl_flags & FL_FLOCK)
-		cFYI(1, "Flock");
+		cifs_dbg(FYI, "Flock\n");
 	if (flock->fl_flags & FL_SLEEP) {
-		cFYI(1, "Blocking lock");
+		cifs_dbg(FYI, "Blocking lock\n");
 		*wait_flag = true;
 	}
 	if (flock->fl_flags & FL_ACCESS)
-		cFYI(1, "Process suspended by mandatory locking - "
-			"not implemented yet");
+		cifs_dbg(FYI, "Process suspended by mandatory locking - not implemented yet\n");
 	if (flock->fl_flags & FL_LEASE)
-		cFYI(1, "Lease on file - not implemented yet");
+		cifs_dbg(FYI, "Lease on file - not implemented yet\n");
 	if (flock->fl_flags &
 	    (~(FL_POSIX | FL_FLOCK | FL_SLEEP |
 	       FL_ACCESS | FL_LEASE | FL_CLOSE)))
-		cFYI(1, "Unknown lock flags 0x%x", flock->fl_flags);
+		cifs_dbg(FYI, "Unknown lock flags 0x%x\n", flock->fl_flags);
 
 	*type = server->vals->large_lock_type;
 	if (flock->fl_type == F_WRLCK) {
-		cFYI(1, "F_WRLCK ");
+		cifs_dbg(FYI, "F_WRLCK\n");
 		*type |= server->vals->exclusive_lock_type;
 		*lock = 1;
 	} else if (flock->fl_type == F_UNLCK) {
-		cFYI(1, "F_UNLCK");
+		cifs_dbg(FYI, "F_UNLCK\n");
 		*type |= server->vals->unlock_lock_type;
 		*unlock = 1;
 		/* Check if unlock includes more than one lock range */
 	} else if (flock->fl_type == F_RDLCK) {
-		cFYI(1, "F_RDLCK");
+		cifs_dbg(FYI, "F_RDLCK\n");
 		*type |= server->vals->shared_lock_type;
 		*lock = 1;
 	} else if (flock->fl_type == F_EXLCK) {
-		cFYI(1, "F_EXLCK");
+		cifs_dbg(FYI, "F_EXLCK\n");
 		*type |= server->vals->exclusive_lock_type;
 		*lock = 1;
 	} else if (flock->fl_type == F_SHLCK) {
-		cFYI(1, "F_SHLCK");
+		cifs_dbg(FYI, "F_SHLCK\n");
 		*type |= server->vals->shared_lock_type;
 		*lock = 1;
 	} else
-		cFYI(1, "Unknown type of lock");
+		cifs_dbg(FYI, "Unknown type of lock\n");
 }
 
 static int
@@ -1296,8 +1291,8 @@ cifs_getlk(struct file *file, struct file_lock *flock, __u32 type,
 					    type, 0, 1, false);
 		flock->fl_type = F_UNLCK;
 		if (rc != 0)
-			cERROR(1, "Error unlocking previously locked "
-				  "range %d during test of lock", rc);
+			cifs_dbg(VFS, "Error unlocking previously locked range %d during test of lock\n",
+				 rc);
 		return 0;
 	}
 
@@ -1316,8 +1311,8 @@ cifs_getlk(struct file *file, struct file_lock *flock, __u32 type,
 			type | server->vals->shared_lock_type, 0, 1, false);
 		flock->fl_type = F_RDLCK;
 		if (rc != 0)
-			cERROR(1, "Error unlocking previously locked "
-				  "range %d during test of lock", rc);
+			cifs_dbg(VFS, "Error unlocking previously locked range %d during test of lock\n",
+				 rc);
 	} else
 		flock->fl_type = F_WRLCK;
 
@@ -1508,8 +1503,8 @@ cifs_setlk(struct file *file, struct file_lock *flock, __u32 type,
 		if (!CIFS_I(inode)->clientCanCacheAll &&
 					CIFS_I(inode)->clientCanCacheRead) {
 			cifs_invalidate_mapping(inode);
-			cFYI(1, "Set no oplock for inode=%p due to mand locks",
-			     inode);
+			cifs_dbg(FYI, "Set no oplock for inode=%p due to mand locks\n",
+				 inode);
 			CIFS_I(inode)->clientCanCacheRead = false;
 		}
 
@@ -1546,9 +1541,9 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *flock)
 	rc = -EACCES;
 	xid = get_xid();
 
-	cFYI(1, "Lock parm: 0x%x flockflags: 0x%x flocktype: 0x%x start: %lld "
-		"end: %lld", cmd, flock->fl_flags, flock->fl_type,
-		flock->fl_start, flock->fl_end);
+	cifs_dbg(FYI, "Lock parm: 0x%x flockflags: 0x%x flocktype: 0x%x start: %lld end: %lld\n",
+		 cmd, flock->fl_flags, flock->fl_type,
+		 flock->fl_start, flock->fl_end);
 
 	cfile = (struct cifsFileInfo *)file->private_data;
 	tcon = tlink_tcon(cfile->tlink);
@@ -1620,8 +1615,8 @@ cifs_write(struct cifsFileInfo *open_file, __u32 pid, const char *write_data,
 
 	cifs_sb = CIFS_SB(dentry->d_sb);
 
-	cFYI(1, "write %zd bytes to offset %lld of %s", write_size,
-	     *offset, dentry->d_name.name);
+	cifs_dbg(FYI, "write %zd bytes to offset %lld of %s\n",
+		 write_size, *offset, dentry->d_name.name);
 
 	tcon = tlink_tcon(open_file->tlink);
 	server = tcon->ses->server;
@@ -1736,7 +1731,7 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
 	it being zero) during stress testcases so we need to check for it */
 
 	if (cifs_inode == NULL) {
-		cERROR(1, "Null inode passed to cifs_writeable_file");
+		cifs_dbg(VFS, "Null inode passed to cifs_writeable_file\n");
 		dump_stack();
 		return NULL;
 	}
@@ -1848,7 +1843,7 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
 		else if (bytes_written < 0)
 			rc = bytes_written;
 	} else {
-		cFYI(1, "No writeable filehandles for inode");
+		cifs_dbg(FYI, "No writeable filehandles for inode\n");
 		rc = -EIO;
 	}
 
@@ -2015,7 +2010,7 @@ retry:
 			wdata->cfile = find_writable_file(CIFS_I(mapping->host),
 							  false);
 			if (!wdata->cfile) {
-				cERROR(1, "No writable handles for inode");
+				cifs_dbg(VFS, "No writable handles for inode\n");
 				rc = -EBADF;
 				break;
 			}
@@ -2076,7 +2071,7 @@ cifs_writepage_locked(struct page *page, struct writeback_control *wbc)
 /* BB add check for wbc flags */
 	page_cache_get(page);
 	if (!PageUptodate(page))
-		cFYI(1, "ppw - page not up to date");
+		cifs_dbg(FYI, "ppw - page not up to date\n");
 
 	/*
 	 * Set the "writeback" flag, and clear "dirty" in the radix tree.
@@ -2127,7 +2122,7 @@ static int cifs_write_end(struct file *file, struct address_space *mapping,
 	else
 		pid = current->tgid;
 
-	cFYI(1, "write_end for page %p from pos %lld with %d bytes",
+	cifs_dbg(FYI, "write_end for page %p from pos %lld with %d bytes\n",
 		 page, pos, copied);
 
 	if (PageChecked(page)) {
@@ -2191,13 +2186,13 @@ int cifs_strict_fsync(struct file *file, loff_t start, loff_t end,
 
 	xid = get_xid();
 
-	cFYI(1, "Sync file - name: %s datasync: 0x%x",
-		file->f_path.dentry->d_name.name, datasync);
+	cifs_dbg(FYI, "Sync file - name: %s datasync: 0x%x\n",
+		 file->f_path.dentry->d_name.name, datasync);
 
 	if (!CIFS_I(inode)->clientCanCacheRead) {
 		rc = cifs_invalidate_mapping(inode);
 		if (rc) {
-			cFYI(1, "rc: %d during invalidate phase", rc);
+			cifs_dbg(FYI, "rc: %d during invalidate phase\n", rc);
 			rc = 0; /* don't care about it in fsync */
 		}
 	}
@@ -2233,8 +2228,8 @@ int cifs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
 
 	xid = get_xid();
 
-	cFYI(1, "Sync file - name: %s datasync: 0x%x",
-		file->f_path.dentry->d_name.name, datasync);
+	cifs_dbg(FYI, "Sync file - name: %s datasync: 0x%x\n",
+		 file->f_path.dentry->d_name.name, datasync);
 
 	tcon = tlink_tcon(smbfile->tlink);
 	if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) {
@@ -2262,7 +2257,7 @@ int cifs_flush(struct file *file, fl_owner_t id)
 	if (file->f_mode & FMODE_WRITE)
 		rc = filemap_write_and_wait(inode->i_mapping);
 
-	cFYI(1, "Flush inode %p file %p rc %d", inode, file, rc);
+	cifs_dbg(FYI, "Flush inode %p file %p rc %d\n", inode, file, rc);
 
 	return rc;
 }
@@ -2520,8 +2515,6 @@ cifs_writev(struct kiocb *iocb, const struct iovec *iov,
 
 	BUG_ON(iocb->ki_pos != pos);
 
-	sb_start_write(inode->i_sb);
-
 	/*
 	 * We need to hold the sem to be sure nobody modifies lock list
 	 * with a brlock that prevents writing.
@@ -2545,7 +2538,6 @@ cifs_writev(struct kiocb *iocb, const struct iovec *iov,
 	}
 
 	up_read(&cinode->lock_sem);
-	sb_end_write(inode->i_sb);
 	return rc;
 }
 
@@ -2582,8 +2574,8 @@ cifs_strict_writev(struct kiocb *iocb, const struct iovec *iov,
 		 * an old data.
 		 */
 		cifs_invalidate_mapping(inode);
-		cFYI(1, "Set no oplock for inode=%p after a write operation",
-		     inode);
+		cifs_dbg(FYI, "Set no oplock for inode=%p after a write operation\n",
+			 inode);
 		cinode->clientCanCacheRead = false;
 	}
 	return written;
@@ -2759,15 +2751,15 @@ cifs_uncached_read_into_pages(struct TCP_Server_Info *server,
 			/* enough data to fill the page */
 			iov.iov_base = kmap(page);
 			iov.iov_len = PAGE_SIZE;
-			cFYI(1, "%u: iov_base=%p iov_len=%zu",
-				i, iov.iov_base, iov.iov_len);
+			cifs_dbg(FYI, "%u: iov_base=%p iov_len=%zu\n",
+				 i, iov.iov_base, iov.iov_len);
 			len -= PAGE_SIZE;
 		} else if (len > 0) {
 			/* enough for partial page, fill and zero the rest */
 			iov.iov_base = kmap(page);
 			iov.iov_len = len;
-			cFYI(1, "%u: iov_base=%p iov_len=%zu",
-				i, iov.iov_base, iov.iov_len);
+			cifs_dbg(FYI, "%u: iov_base=%p iov_len=%zu\n",
+				 i, iov.iov_base, iov.iov_len);
 			memset(iov.iov_base + len, '\0', PAGE_SIZE - len);
 			rdata->tailsz = len;
 			len = 0;
@@ -2827,7 +2819,7 @@ cifs_iovec_read(struct file *file, const struct iovec *iov,
 		pid = current->tgid;
 
 	if ((file->f_flags & O_ACCMODE) == O_WRONLY)
-		cFYI(1, "attempting read on write only file instance");
+		cifs_dbg(FYI, "attempting read on write only file instance\n");
 
 	do {
 		cur_len = min_t(const size_t, len - total_read, cifs_sb->rsize);
@@ -3006,7 +2998,7 @@ cifs_read(struct file *file, char *read_data, size_t read_size, loff_t *offset)
 		pid = current->tgid;
 
 	if ((file->f_flags & O_ACCMODE) == O_WRONLY)
-		cFYI(1, "attempting read on write only file instance");
+		cifs_dbg(FYI, "attempting read on write only file instance\n");
 
 	for (total_read = 0, cur_offset = read_data; read_size > total_read;
 	     total_read += bytes_read, cur_offset += bytes_read) {
@@ -3097,7 +3089,8 @@ int cifs_file_mmap(struct file *file, struct vm_area_struct *vma)
 	xid = get_xid();
 	rc = cifs_revalidate_file(file);
 	if (rc) {
-		cFYI(1, "Validation prior to mmap failed, error=%d", rc);
+		cifs_dbg(FYI, "Validation prior to mmap failed, error=%d\n",
+			 rc);
 		free_xid(xid);
 		return rc;
 	}
@@ -3150,7 +3143,7 @@ cifs_readpages_read_into_pages(struct TCP_Server_Info *server,
 	/* determine the eof that the server (probably) has */
 	eof = CIFS_I(rdata->mapping->host)->server_eof;
 	eof_index = eof ? (eof - 1) >> PAGE_CACHE_SHIFT : 0;
-	cFYI(1, "eof=%llu eof_index=%lu", eof, eof_index);
+	cifs_dbg(FYI, "eof=%llu eof_index=%lu\n", eof, eof_index);
 
 	rdata->tailsz = PAGE_CACHE_SIZE;
 	for (i = 0; i < nr_pages; i++) {
@@ -3160,15 +3153,15 @@ cifs_readpages_read_into_pages(struct TCP_Server_Info *server,
 			/* enough data to fill the page */
 			iov.iov_base = kmap(page);
 			iov.iov_len = PAGE_CACHE_SIZE;
-			cFYI(1, "%u: idx=%lu iov_base=%p iov_len=%zu",
-				i, page->index, iov.iov_base, iov.iov_len);
+			cifs_dbg(FYI, "%u: idx=%lu iov_base=%p iov_len=%zu\n",
+				 i, page->index, iov.iov_base, iov.iov_len);
 			len -= PAGE_CACHE_SIZE;
 		} else if (len > 0) {
 			/* enough for partial page, fill and zero the rest */
 			iov.iov_base = kmap(page);
 			iov.iov_len = len;
-			cFYI(1, "%u: idx=%lu iov_base=%p iov_len=%zu",
-				i, page->index, iov.iov_base, iov.iov_len);
+			cifs_dbg(FYI, "%u: idx=%lu iov_base=%p iov_len=%zu\n",
+				 i, page->index, iov.iov_base, iov.iov_len);
 			memset(iov.iov_base + len,
 				'\0', PAGE_CACHE_SIZE - len);
 			rdata->tailsz = len;
@@ -3248,8 +3241,8 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
 	rc = 0;
 	INIT_LIST_HEAD(&tmplist);
 
-	cFYI(1, "%s: file=%p mapping=%p num_pages=%u", __func__, file,
-		mapping, num_pages);
+	cifs_dbg(FYI, "%s: file=%p mapping=%p num_pages=%u\n",
+		 __func__, file, mapping, num_pages);
 
 	/*
 	 * Start with the page at end of list and move it to private
@@ -3379,7 +3372,7 @@ static int cifs_readpage_worker(struct file *file, struct page *page,
 	if (rc < 0)
 		goto io_error;
 	else
-		cFYI(1, "Bytes read %d", rc);
+		cifs_dbg(FYI, "Bytes read %d\n", rc);
 
 	file_inode(file)->i_atime =
 		current_fs_time(file_inode(file)->i_sb);
@@ -3417,7 +3410,7 @@ static int cifs_readpage(struct file *file, struct page *page)
 		return rc;
 	}
 
-	cFYI(1, "readpage %p at offset %d 0x%x",
+	cifs_dbg(FYI, "readpage %p at offset %d 0x%x\n",
 		 page, (int)offset, (int)offset);
 
 	rc = cifs_readpage_worker(file, page, &offset);
@@ -3484,7 +3477,7 @@ static int cifs_write_begin(struct file *file, struct address_space *mapping,
 	struct page *page;
 	int rc = 0;
 
-	cFYI(1, "write_begin from %lld len %d", (long long)pos, len);
+	cifs_dbg(FYI, "write_begin from %lld len %d\n", (long long)pos, len);
 
 	page = grab_cache_page_write_begin(mapping, index, flags);
 	if (!page) {
@@ -3573,7 +3566,7 @@ static int cifs_launder_page(struct page *page)
 		.range_end = range_end,
 	};
 
-	cFYI(1, "Launder page: %p", page);
+	cifs_dbg(FYI, "Launder page: %p\n", page);
 
 	if (clear_page_dirty_for_io(page))
 		rc = cifs_writepage_locked(page, &wbc);
@@ -3593,8 +3586,8 @@ void cifs_oplock_break(struct work_struct *work)
 
 	if (!cinode->clientCanCacheAll && cinode->clientCanCacheRead &&
 						cifs_has_mand_locks(cinode)) {
-		cFYI(1, "Reset oplock to None for inode=%p due to mand locks",
-		     inode);
+		cifs_dbg(FYI, "Reset oplock to None for inode=%p due to mand locks\n",
+			 inode);
 		cinode->clientCanCacheRead = false;
 	}
 
@@ -3609,12 +3602,12 @@ void cifs_oplock_break(struct work_struct *work)
 			mapping_set_error(inode->i_mapping, rc);
 			cifs_invalidate_mapping(inode);
 		}
-		cFYI(1, "Oplock flush inode %p rc %d", inode, rc);
+		cifs_dbg(FYI, "Oplock flush inode %p rc %d\n", inode, rc);
 	}
 
 	rc = cifs_push_locks(cfile);
 	if (rc)
-		cERROR(1, "Push locks rc = %d", rc);
+		cifs_dbg(VFS, "Push locks rc = %d\n", rc);
 
 	/*
 	 * releasing stale oplock after recent reconnect of smb session using
@@ -3625,7 +3618,7 @@ void cifs_oplock_break(struct work_struct *work)
 	if (!cfile->oplock_break_cancelled) {
 		rc = tcon->ses->server->ops->oplock_response(tcon, &cfile->fid,
 							     cinode);
-		cFYI(1, "Oplock release rc = %d", rc);
+		cifs_dbg(FYI, "Oplock release rc = %d\n", rc);
 	}
 }
 
diff --git a/fs/cifs/fscache.c b/fs/cifs/fscache.c
index 42e5363..2f4bc5a 100644
--- a/fs/cifs/fscache.c
+++ b/fs/cifs/fscache.c
@@ -28,14 +28,14 @@ void cifs_fscache_get_client_cookie(struct TCP_Server_Info *server)
 	server->fscache =
 		fscache_acquire_cookie(cifs_fscache_netfs.primary_index,
 				&cifs_fscache_server_index_def, server);
-	cFYI(1, "%s: (0x%p/0x%p)", __func__, server,
-			server->fscache);
+	cifs_dbg(FYI, "%s: (0x%p/0x%p)\n",
+		 __func__, server, server->fscache);
 }
 
 void cifs_fscache_release_client_cookie(struct TCP_Server_Info *server)
 {
-	cFYI(1, "%s: (0x%p/0x%p)", __func__, server,
-			server->fscache);
+	cifs_dbg(FYI, "%s: (0x%p/0x%p)\n",
+		 __func__, server, server->fscache);
 	fscache_relinquish_cookie(server->fscache, 0);
 	server->fscache = NULL;
 }
@@ -47,13 +47,13 @@ void cifs_fscache_get_super_cookie(struct cifs_tcon *tcon)
 	tcon->fscache =
 		fscache_acquire_cookie(server->fscache,
 				&cifs_fscache_super_index_def, tcon);
-	cFYI(1, "%s: (0x%p/0x%p)", __func__, server->fscache,
-			tcon->fscache);
+	cifs_dbg(FYI, "%s: (0x%p/0x%p)\n",
+		 __func__, server->fscache, tcon->fscache);
 }
 
 void cifs_fscache_release_super_cookie(struct cifs_tcon *tcon)
 {
-	cFYI(1, "%s: (0x%p)", __func__, tcon->fscache);
+	cifs_dbg(FYI, "%s: (0x%p)\n", __func__, tcon->fscache);
 	fscache_relinquish_cookie(tcon->fscache, 0);
 	tcon->fscache = NULL;
 }
@@ -70,8 +70,8 @@ static void cifs_fscache_enable_inode_cookie(struct inode *inode)
 	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_FSCACHE) {
 		cifsi->fscache = fscache_acquire_cookie(tcon->fscache,
 				&cifs_fscache_inode_object_def, cifsi);
-		cFYI(1, "%s: got FH cookie (0x%p/0x%p)", __func__,
-				tcon->fscache, cifsi->fscache);
+		cifs_dbg(FYI, "%s: got FH cookie (0x%p/0x%p)\n",
+			 __func__, tcon->fscache, cifsi->fscache);
 	}
 }
 
@@ -80,7 +80,7 @@ void cifs_fscache_release_inode_cookie(struct inode *inode)
 	struct cifsInodeInfo *cifsi = CIFS_I(inode);
 
 	if (cifsi->fscache) {
-		cFYI(1, "%s: (0x%p)", __func__, cifsi->fscache);
+		cifs_dbg(FYI, "%s: (0x%p)\n", __func__, cifsi->fscache);
 		fscache_relinquish_cookie(cifsi->fscache, 0);
 		cifsi->fscache = NULL;
 	}
@@ -91,7 +91,7 @@ static void cifs_fscache_disable_inode_cookie(struct inode *inode)
 	struct cifsInodeInfo *cifsi = CIFS_I(inode);
 
 	if (cifsi->fscache) {
-		cFYI(1, "%s: (0x%p)", __func__, cifsi->fscache);
+		cifs_dbg(FYI, "%s: (0x%p)\n", __func__, cifsi->fscache);
 		fscache_uncache_all_inode_pages(cifsi->fscache, inode);
 		fscache_relinquish_cookie(cifsi->fscache, 1);
 		cifsi->fscache = NULL;
@@ -120,8 +120,8 @@ void cifs_fscache_reset_inode_cookie(struct inode *inode)
 					cifs_sb_master_tcon(cifs_sb)->fscache,
 					&cifs_fscache_inode_object_def,
 					cifsi);
-		cFYI(1, "%s: new cookie 0x%p oldcookie 0x%p",
-				__func__, cifsi->fscache, old);
+		cifs_dbg(FYI, "%s: new cookie 0x%p oldcookie 0x%p\n",
+			 __func__, cifsi->fscache, old);
 	}
 }
 
@@ -131,8 +131,8 @@ int cifs_fscache_release_page(struct page *page, gfp_t gfp)
 		struct inode *inode = page->mapping->host;
 		struct cifsInodeInfo *cifsi = CIFS_I(inode);
 
-		cFYI(1, "%s: (0x%p/0x%p)", __func__, page,
-				cifsi->fscache);
+		cifs_dbg(FYI, "%s: (0x%p/0x%p)\n",
+			 __func__, page, cifsi->fscache);
 		if (!fscache_maybe_release_page(cifsi->fscache, page, gfp))
 			return 0;
 	}
@@ -143,7 +143,7 @@ int cifs_fscache_release_page(struct page *page, gfp_t gfp)
 static void cifs_readpage_from_fscache_complete(struct page *page, void *ctx,
 						int error)
 {
-	cFYI(1, "%s: (0x%p/%d)", __func__, page, error);
+	cifs_dbg(FYI, "%s: (0x%p/%d)\n", __func__, page, error);
 	if (!error)
 		SetPageUptodate(page);
 	unlock_page(page);
@@ -156,8 +156,8 @@ int __cifs_readpage_from_fscache(struct inode *inode, struct page *page)
 {
 	int ret;
 
-	cFYI(1, "%s: (fsc:%p, p:%p, i:0x%p", __func__,
-			CIFS_I(inode)->fscache, page, inode);
+	cifs_dbg(FYI, "%s: (fsc:%p, p:%p, i:0x%p\n",
+		 __func__, CIFS_I(inode)->fscache, page, inode);
 	ret = fscache_read_or_alloc_page(CIFS_I(inode)->fscache, page,
 					 cifs_readpage_from_fscache_complete,
 					 NULL,
@@ -165,15 +165,15 @@ int __cifs_readpage_from_fscache(struct inode *inode, struct page *page)
 	switch (ret) {
 
 	case 0: /* page found in fscache, read submitted */
-		cFYI(1, "%s: submitted", __func__);
+		cifs_dbg(FYI, "%s: submitted\n", __func__);
 		return ret;
 	case -ENOBUFS:	/* page won't be cached */
 	case -ENODATA:	/* page not in cache */
-		cFYI(1, "%s: %d", __func__, ret);
+		cifs_dbg(FYI, "%s: %d\n", __func__, ret);
 		return 1;
 
 	default:
-		cERROR(1, "unknown error ret = %d", ret);
+		cifs_dbg(VFS, "unknown error ret = %d\n", ret);
 	}
 	return ret;
 }
@@ -188,8 +188,8 @@ int __cifs_readpages_from_fscache(struct inode *inode,
 {
 	int ret;
 
-	cFYI(1, "%s: (0x%p/%u/0x%p)", __func__,
-			CIFS_I(inode)->fscache, *nr_pages, inode);
+	cifs_dbg(FYI, "%s: (0x%p/%u/0x%p)\n",
+		 __func__, CIFS_I(inode)->fscache, *nr_pages, inode);
 	ret = fscache_read_or_alloc_pages(CIFS_I(inode)->fscache, mapping,
 					  pages, nr_pages,
 					  cifs_readpage_from_fscache_complete,
@@ -197,16 +197,16 @@ int __cifs_readpages_from_fscache(struct inode *inode,
 					  mapping_gfp_mask(mapping));
 	switch (ret) {
 	case 0:	/* read submitted to the cache for all pages */
-		cFYI(1, "%s: submitted", __func__);
+		cifs_dbg(FYI, "%s: submitted\n", __func__);
 		return ret;
 
 	case -ENOBUFS:	/* some pages are not cached and can't be */
 	case -ENODATA:	/* some pages are not cached */
-		cFYI(1, "%s: no page", __func__);
+		cifs_dbg(FYI, "%s: no page\n", __func__);
 		return 1;
 
 	default:
-		cFYI(1, "unknown error ret = %d", ret);
+		cifs_dbg(FYI, "unknown error ret = %d\n", ret);
 	}
 
 	return ret;
@@ -216,8 +216,8 @@ void __cifs_readpage_to_fscache(struct inode *inode, struct page *page)
 {
 	int ret;
 
-	cFYI(1, "%s: (fsc: %p, p: %p, i: %p)", __func__,
-			CIFS_I(inode)->fscache, page, inode);
+	cifs_dbg(FYI, "%s: (fsc: %p, p: %p, i: %p)\n",
+		 __func__, CIFS_I(inode)->fscache, page, inode);
 	ret = fscache_write_page(CIFS_I(inode)->fscache, page, GFP_KERNEL);
 	if (ret != 0)
 		fscache_uncache_page(CIFS_I(inode)->fscache, page);
@@ -228,7 +228,7 @@ void __cifs_fscache_invalidate_page(struct page *page, struct inode *inode)
 	struct cifsInodeInfo *cifsi = CIFS_I(inode);
 	struct fscache_cookie *cookie = cifsi->fscache;
 
-	cFYI(1, "%s: (0x%p/0x%p)", __func__, page, cookie);
+	cifs_dbg(FYI, "%s: (0x%p/0x%p)\n", __func__, page, cookie);
 	fscache_wait_on_page_write(cookie, page);
 	fscache_uncache_page(cookie, page);
 }
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 20887bf..fc30251 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -91,30 +91,32 @@ cifs_revalidate_cache(struct inode *inode, struct cifs_fattr *fattr)
 {
 	struct cifsInodeInfo *cifs_i = CIFS_I(inode);
 
-	cFYI(1, "%s: revalidating inode %llu", __func__, cifs_i->uniqueid);
+	cifs_dbg(FYI, "%s: revalidating inode %llu\n",
+		 __func__, cifs_i->uniqueid);
 
 	if (inode->i_state & I_NEW) {
-		cFYI(1, "%s: inode %llu is new", __func__, cifs_i->uniqueid);
+		cifs_dbg(FYI, "%s: inode %llu is new\n",
+			 __func__, cifs_i->uniqueid);
 		return;
 	}
 
 	/* don't bother with revalidation if we have an oplock */
 	if (cifs_i->clientCanCacheRead) {
-		cFYI(1, "%s: inode %llu is oplocked", __func__,
-			 cifs_i->uniqueid);
+		cifs_dbg(FYI, "%s: inode %llu is oplocked\n",
+			 __func__, cifs_i->uniqueid);
 		return;
 	}
 
 	 /* revalidate if mtime or size have changed */
 	if (timespec_equal(&inode->i_mtime, &fattr->cf_mtime) &&
 	    cifs_i->server_eof == fattr->cf_eof) {
-		cFYI(1, "%s: inode %llu is unchanged", __func__,
-			 cifs_i->uniqueid);
+		cifs_dbg(FYI, "%s: inode %llu is unchanged\n",
+			 __func__, cifs_i->uniqueid);
 		return;
 	}
 
-	cFYI(1, "%s: invalidating inode %llu mapping", __func__,
-		 cifs_i->uniqueid);
+	cifs_dbg(FYI, "%s: invalidating inode %llu mapping\n",
+		 __func__, cifs_i->uniqueid);
 	cifs_i->invalid_mapping = true;
 }
 
@@ -240,7 +242,7 @@ cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, FILE_UNIX_BASIC_INFO *info,
 		/* safest to call it a file if we do not know */
 		fattr->cf_mode |= S_IFREG;
 		fattr->cf_dtype = DT_REG;
-		cFYI(1, "unknown type %d", le32_to_cpu(info->Type));
+		cifs_dbg(FYI, "unknown type %d\n", le32_to_cpu(info->Type));
 		break;
 	}
 
@@ -279,7 +281,7 @@ cifs_create_dfs_fattr(struct cifs_fattr *fattr, struct super_block *sb)
 {
 	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
 
-	cFYI(1, "creating fake fattr for DFS referral");
+	cifs_dbg(FYI, "creating fake fattr for DFS referral\n");
 
 	memset(fattr, 0, sizeof(*fattr));
 	fattr->cf_mode = S_IFDIR | S_IXUGO | S_IRWXU;
@@ -329,7 +331,7 @@ int cifs_get_inode_info_unix(struct inode **pinode,
 	struct tcon_link *tlink;
 	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
 
-	cFYI(1, "Getting info on %s", full_path);
+	cifs_dbg(FYI, "Getting info on %s\n", full_path);
 
 	tlink = cifs_sb_tlink(cifs_sb);
 	if (IS_ERR(tlink))
@@ -355,7 +357,7 @@ int cifs_get_inode_info_unix(struct inode **pinode,
 	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
 		int tmprc = CIFSCheckMFSymlink(&fattr, full_path, cifs_sb, xid);
 		if (tmprc)
-			cFYI(1, "CIFSCheckMFSymlink: %d", tmprc);
+			cifs_dbg(FYI, "CIFSCheckMFSymlink: %d\n", tmprc);
 	}
 
 	if (*pinode == NULL) {
@@ -422,7 +424,7 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path,
 				 &buf_type);
 		if ((rc == 0) && (bytes_read >= 8)) {
 			if (memcmp("IntxBLK", pbuf, 8) == 0) {
-				cFYI(1, "Block device");
+				cifs_dbg(FYI, "Block device\n");
 				fattr->cf_mode |= S_IFBLK;
 				fattr->cf_dtype = DT_BLK;
 				if (bytes_read == 24) {
@@ -434,7 +436,7 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path,
 					fattr->cf_rdev = MKDEV(mjr, mnr);
 				}
 			} else if (memcmp("IntxCHR", pbuf, 8) == 0) {
-				cFYI(1, "Char device");
+				cifs_dbg(FYI, "Char device\n");
 				fattr->cf_mode |= S_IFCHR;
 				fattr->cf_dtype = DT_CHR;
 				if (bytes_read == 24) {
@@ -446,7 +448,7 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path,
 					fattr->cf_rdev = MKDEV(mjr, mnr);
 				}
 			} else if (memcmp("IntxLNK", pbuf, 7) == 0) {
-				cFYI(1, "Symlink");
+				cifs_dbg(FYI, "Symlink\n");
 				fattr->cf_mode |= S_IFLNK;
 				fattr->cf_dtype = DT_LNK;
 			} else {
@@ -497,10 +499,10 @@ static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path,
 	else if (rc > 3) {
 		mode = le32_to_cpu(*((__le32 *)ea_value));
 		fattr->cf_mode &= ~SFBITS_MASK;
-		cFYI(1, "special bits 0%o org mode 0%o", mode,
-			 fattr->cf_mode);
+		cifs_dbg(FYI, "special bits 0%o org mode 0%o\n",
+			 mode, fattr->cf_mode);
 		fattr->cf_mode = (mode & SFBITS_MASK) | fattr->cf_mode;
-		cFYI(1, "special mode bits 0%o", mode);
+		cifs_dbg(FYI, "special mode bits 0%o\n", mode);
 	}
 
 	return 0;
@@ -635,11 +637,11 @@ cifs_get_inode_info(struct inode **inode, const char *full_path,
 	tcon = tlink_tcon(tlink);
 	server = tcon->ses->server;
 
-	cFYI(1, "Getting info on %s", full_path);
+	cifs_dbg(FYI, "Getting info on %s\n", full_path);
 
 	if ((data == NULL) && (*inode != NULL)) {
 		if (CIFS_I(*inode)->clientCanCacheRead) {
-			cFYI(1, "No need to revalidate cached inode sizes");
+			cifs_dbg(FYI, "No need to revalidate cached inode sizes\n");
 			goto cgii_exit;
 		}
 	}
@@ -714,7 +716,8 @@ cifs_get_inode_info(struct inode **inode, const char *full_path,
 						tcon, cifs_sb, full_path,
 						&fattr.cf_uniqueid, data);
 				if (tmprc) {
-					cFYI(1, "GetSrvInodeNum rc %d", tmprc);
+					cifs_dbg(FYI, "GetSrvInodeNum rc %d\n",
+						 tmprc);
 					fattr.cf_uniqueid = iunique(sb, ROOT_I);
 					cifs_autodisable_serverino(cifs_sb);
 				}
@@ -729,7 +732,7 @@ cifs_get_inode_info(struct inode **inode, const char *full_path,
 	    cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
 		tmprc = cifs_sfu_type(&fattr, full_path, cifs_sb, xid);
 		if (tmprc)
-			cFYI(1, "cifs_sfu_type failed: %d", tmprc);
+			cifs_dbg(FYI, "cifs_sfu_type failed: %d\n", tmprc);
 	}
 
 #ifdef CONFIG_CIFS_ACL
@@ -737,8 +740,8 @@ cifs_get_inode_info(struct inode **inode, const char *full_path,
 	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
 		rc = cifs_acl_to_fattr(cifs_sb, &fattr, *inode, full_path, fid);
 		if (rc) {
-			cFYI(1, "%s: Getting ACL failed with error: %d",
-				__func__, rc);
+			cifs_dbg(FYI, "%s: Getting ACL failed with error: %d\n",
+				 __func__, rc);
 			goto cgii_exit;
 		}
 	}
@@ -752,7 +755,7 @@ cifs_get_inode_info(struct inode **inode, const char *full_path,
 	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
 		tmprc = CIFSCheckMFSymlink(&fattr, full_path, cifs_sb, xid);
 		if (tmprc)
-			cFYI(1, "CIFSCheckMFSymlink: %d", tmprc);
+			cifs_dbg(FYI, "CIFSCheckMFSymlink: %d\n", tmprc);
 	}
 
 	if (!*inode) {
@@ -836,7 +839,7 @@ cifs_iget(struct super_block *sb, struct cifs_fattr *fattr)
 	struct inode *inode;
 
 retry_iget5_locked:
-	cFYI(1, "looking for uniqueid=%llu", fattr->cf_uniqueid);
+	cifs_dbg(FYI, "looking for uniqueid=%llu\n", fattr->cf_uniqueid);
 
 	/* hash down to 32-bits on 32-bit arch */
 	hash = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid);
@@ -899,7 +902,7 @@ struct inode *cifs_root_iget(struct super_block *sb)
 #endif
 
 	if (rc && tcon->ipc) {
-		cFYI(1, "ipc connection - fake read inode");
+		cifs_dbg(FYI, "ipc connection - fake read inode\n");
 		spin_lock(&inode->i_lock);
 		inode->i_mode |= S_IFDIR;
 		set_nlink(inode, 2);
@@ -958,7 +961,7 @@ cifs_set_file_info(struct inode *inode, struct iattr *attrs, unsigned int xid,
 	 * server times.
 	 */
 	if (set_time && (attrs->ia_valid & ATTR_CTIME)) {
-		cFYI(1, "CIFS - CTIME changed");
+		cifs_dbg(FYI, "CIFS - CTIME changed\n");
 		info_buf.ChangeTime =
 		    cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
 	} else
@@ -1127,7 +1130,7 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry)
 	struct iattr *attrs = NULL;
 	__u32 dosattr = 0, origattr = 0;
 
-	cFYI(1, "cifs_unlink, dir=0x%p, dentry=0x%p", dir, dentry);
+	cifs_dbg(FYI, "cifs_unlink, dir=0x%p, dentry=0x%p\n", dir, dentry);
 
 	tlink = cifs_sb_tlink(cifs_sb);
 	if (IS_ERR(tlink))
@@ -1150,7 +1153,7 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry)
 		rc = CIFSPOSIXDelFile(xid, tcon, full_path,
 			SMB_POSIX_UNLINK_FILE_TARGET, cifs_sb->local_nls,
 			cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
-		cFYI(1, "posix del rc %d", rc);
+		cifs_dbg(FYI, "posix del rc %d\n", rc);
 		if ((rc == 0) || (rc == -ENOENT))
 			goto psx_del_no_retry;
 	}
@@ -1320,7 +1323,7 @@ cifs_posix_mkdir(struct inode *inode, struct dentry *dentry, umode_t mode,
 	if (rc == -EOPNOTSUPP)
 		goto posix_mkdir_out;
 	else if (rc) {
-		cFYI(1, "posix mkdir returned 0x%x", rc);
+		cifs_dbg(FYI, "posix mkdir returned 0x%x\n", rc);
 		d_drop(dentry);
 		goto posix_mkdir_out;
 	}
@@ -1342,11 +1345,12 @@ cifs_posix_mkdir(struct inode *inode, struct dentry *dentry, umode_t mode,
 	d_instantiate(dentry, newinode);
 
 #ifdef CONFIG_CIFS_DEBUG2
-	cFYI(1, "instantiated dentry %p %s to inode %p", dentry,
-	     dentry->d_name.name, newinode);
+	cifs_dbg(FYI, "instantiated dentry %p %s to inode %p\n",
+		 dentry, dentry->d_name.name, newinode);
 
 	if (newinode->i_nlink != 2)
-		cFYI(1, "unexpected number of links %d", newinode->i_nlink);
+		cifs_dbg(FYI, "unexpected number of links %d\n",
+			 newinode->i_nlink);
 #endif
 
 posix_mkdir_out:
@@ -1368,7 +1372,8 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode)
 	struct TCP_Server_Info *server;
 	char *full_path;
 
-	cFYI(1, "In cifs_mkdir, mode = 0x%hx inode = 0x%p", mode, inode);
+	cifs_dbg(FYI, "In cifs_mkdir, mode = 0x%hx inode = 0x%p\n",
+		 mode, inode);
 
 	cifs_sb = CIFS_SB(inode->i_sb);
 	tlink = cifs_sb_tlink(cifs_sb);
@@ -1402,7 +1407,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode)
 	/* BB add setting the equivalent of mode via CreateX w/ACLs */
 	rc = server->ops->mkdir(xid, tcon, full_path, cifs_sb);
 	if (rc) {
-		cFYI(1, "cifs_mkdir returned 0x%x", rc);
+		cifs_dbg(FYI, "cifs_mkdir returned 0x%x\n", rc);
 		d_drop(direntry);
 		goto mkdir_out;
 	}
@@ -1432,7 +1437,7 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
 	char *full_path = NULL;
 	struct cifsInodeInfo *cifsInode;
 
-	cFYI(1, "cifs_rmdir, inode = 0x%p", inode);
+	cifs_dbg(FYI, "cifs_rmdir, inode = 0x%p\n", inode);
 
 	xid = get_xid();
 
@@ -1681,8 +1686,8 @@ cifs_invalidate_mapping(struct inode *inode)
 	if (inode->i_mapping && inode->i_mapping->nrpages != 0) {
 		rc = invalidate_inode_pages2(inode->i_mapping);
 		if (rc) {
-			cERROR(1, "%s: could not invalidate inode %p", __func__,
-			       inode);
+			cifs_dbg(VFS, "%s: could not invalidate inode %p\n",
+				 __func__, inode);
 			cifs_i->invalid_mapping = true;
 		}
 	}
@@ -1732,8 +1737,8 @@ int cifs_revalidate_dentry_attr(struct dentry *dentry)
 		goto out;
 	}
 
-	cFYI(1, "Update attributes: %s inode 0x%p count %d dentry: 0x%p d_time "
-		 "%ld jiffies %ld", full_path, inode, inode->i_count.counter,
+	cifs_dbg(FYI, "Update attributes: %s inode 0x%p count %d dentry: 0x%p d_time %ld jiffies %ld\n",
+		 full_path, inode, inode->i_count.counter,
 		 dentry, dentry->d_time, jiffies);
 
 	if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext)
@@ -1883,7 +1888,7 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs,
 		else
 			rc = -ENOSYS;
 		cifsFileInfo_put(open_file);
-		cFYI(1, "SetFSize for attrs rc = %d", rc);
+		cifs_dbg(FYI, "SetFSize for attrs rc = %d\n", rc);
 		if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
 			unsigned int bytes_written;
 
@@ -1894,7 +1899,7 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs,
 			io_parms.length = attrs->ia_size;
 			rc = CIFSSMBWrite(xid, &io_parms, &bytes_written,
 					  NULL, NULL, 1);
-			cFYI(1, "Wrt seteof rc %d", rc);
+			cifs_dbg(FYI, "Wrt seteof rc %d\n", rc);
 		}
 	} else
 		rc = -EINVAL;
@@ -1920,7 +1925,7 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs,
 						attrs->ia_size, cifs_sb, false);
 	else
 		rc = -ENOSYS;
-	cFYI(1, "SetEOF by path (setattrs) rc = %d", rc);
+	cifs_dbg(FYI, "SetEOF by path (setattrs) rc = %d\n", rc);
 	if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
 		__u16 netfid;
 		int oplock = 0;
@@ -1940,7 +1945,7 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs,
 			io_parms.length = attrs->ia_size;
 			rc = CIFSSMBWrite(xid, &io_parms, &bytes_written, NULL,
 					  NULL,  1);
-			cFYI(1, "wrt seteof rc %d", rc);
+			cifs_dbg(FYI, "wrt seteof rc %d\n", rc);
 			CIFSSMBClose(xid, tcon, netfid);
 		}
 	}
@@ -1971,7 +1976,7 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
 	struct cifs_unix_set_info_args *args = NULL;
 	struct cifsFileInfo *open_file;
 
-	cFYI(1, "setattr_unix on file %s attrs->ia_valid=0x%x",
+	cifs_dbg(FYI, "setattr_unix on file %s attrs->ia_valid=0x%x\n",
 		 direntry->d_name.name, attrs->ia_valid);
 
 	xid = get_xid();
@@ -2114,7 +2119,7 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
 
 	xid = get_xid();
 
-	cFYI(1, "setattr on file %s attrs->iavalid 0x%x",
+	cifs_dbg(FYI, "setattr on file %s attrs->iavalid 0x%x\n",
 		 direntry->d_name.name, attrs->ia_valid);
 
 	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
@@ -2166,8 +2171,8 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
 			rc = id_mode_to_cifs_acl(inode, full_path, NO_CHANGE_64,
 							uid, gid);
 			if (rc) {
-				cFYI(1, "%s: Setting id failed with error: %d",
-					__func__, rc);
+				cifs_dbg(FYI, "%s: Setting id failed with error: %d\n",
+					 __func__, rc);
 				goto cifs_setattr_exit;
 			}
 		}
@@ -2188,8 +2193,8 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
 			rc = id_mode_to_cifs_acl(inode, full_path, mode,
 						INVALID_UID, INVALID_GID);
 			if (rc) {
-				cFYI(1, "%s: Setting ACL failed with error: %d",
-					__func__, rc);
+				cifs_dbg(FYI, "%s: Setting ACL failed with error: %d\n",
+					 __func__, rc);
 				goto cifs_setattr_exit;
 			}
 		} else
@@ -2277,7 +2282,7 @@ cifs_setattr(struct dentry *direntry, struct iattr *attrs)
 #if 0
 void cifs_delete_inode(struct inode *inode)
 {
-	cFYI(1, "In cifs_delete_inode, inode = 0x%p", inode);
+	cifs_dbg(FYI, "In cifs_delete_inode, inode = 0x%p\n", inode);
 	/* may have to add back in if and when safe distributed caching of
 	   directories added e.g. via FindNotify */
 }
diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c
index 6c9f121..3e08455 100644
--- a/fs/cifs/ioctl.c
+++ b/fs/cifs/ioctl.c
@@ -44,7 +44,7 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
 
 	xid = get_xid();
 
-	cFYI(1, "ioctl file %p  cmd %u  arg %lu", filep, command, arg);
+	cifs_dbg(FYI, "ioctl file %p  cmd %u  arg %lu\n", filep, command, arg);
 
 	cifs_sb = CIFS_SB(inode->i_sb);
 
@@ -83,11 +83,11 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
 				 *		       &ExtAttrMask);
 				 */
 			}
-			cFYI(1, "set flags not implemented yet");
+			cifs_dbg(FYI, "set flags not implemented yet\n");
 			break;
 #endif /* CONFIG_CIFS_POSIX */
 		default:
-			cFYI(1, "unsupported ioctl");
+			cifs_dbg(FYI, "unsupported ioctl\n");
 			break;
 	}
 
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index 9f6c4c4..b83c3f5 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -56,14 +56,14 @@ symlink_hash(unsigned int link_len, const char *link_str, u8 *md5_hash)
 	md5 = crypto_alloc_shash("md5", 0, 0);
 	if (IS_ERR(md5)) {
 		rc = PTR_ERR(md5);
-		cERROR(1, "%s: Crypto md5 allocation error %d", __func__, rc);
+		cifs_dbg(VFS, "%s: Crypto md5 allocation error %d\n",
+			 __func__, rc);
 		return rc;
 	}
 	size = sizeof(struct shash_desc) + crypto_shash_descsize(md5);
 	sdescmd5 = kmalloc(size, GFP_KERNEL);
 	if (!sdescmd5) {
 		rc = -ENOMEM;
-		cERROR(1, "%s: Memory allocation failure", __func__);
 		goto symlink_hash_err;
 	}
 	sdescmd5->shash.tfm = md5;
@@ -71,17 +71,17 @@ symlink_hash(unsigned int link_len, const char *link_str, u8 *md5_hash)
 
 	rc = crypto_shash_init(&sdescmd5->shash);
 	if (rc) {
-		cERROR(1, "%s: Could not init md5 shash", __func__);
+		cifs_dbg(VFS, "%s: Could not init md5 shash\n", __func__);
 		goto symlink_hash_err;
 	}
 	rc = crypto_shash_update(&sdescmd5->shash, link_str, link_len);
 	if (rc) {
-		cERROR(1, "%s: Could not update with link_str", __func__);
+		cifs_dbg(VFS, "%s: Could not update with 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", __func__);
+		cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__);
 
 symlink_hash_err:
 	crypto_free_shash(md5);
@@ -115,7 +115,7 @@ CIFSParseMFSymlink(const u8 *buf,
 
 	rc = symlink_hash(link_len, link_str, md5_hash);
 	if (rc) {
-		cFYI(1, "%s: MD5 hash failure: %d", __func__, rc);
+		cifs_dbg(FYI, "%s: MD5 hash failure: %d\n", __func__, rc);
 		return rc;
 	}
 
@@ -154,7 +154,7 @@ CIFSFormatMFSymlink(u8 *buf, unsigned int buf_len, const char *link_str)
 
 	rc = symlink_hash(link_len, link_str, md5_hash);
 	if (rc) {
-		cFYI(1, "%s: MD5 hash failure: %d", __func__, rc);
+		cifs_dbg(FYI, "%s: MD5 hash failure: %d\n", __func__, rc);
 		return rc;
 	}
 
@@ -521,7 +521,7 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
 	if (!full_path)
 		goto out;
 
-	cFYI(1, "Full path: %s inode = 0x%p", full_path, inode);
+	cifs_dbg(FYI, "Full path: %s inode = 0x%p\n", full_path, inode);
 
 	rc = -EACCES;
 	/*
@@ -578,8 +578,8 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
 		goto symlink_exit;
 	}
 
-	cFYI(1, "Full path: %s", full_path);
-	cFYI(1, "symname is %s", symname);
+	cifs_dbg(FYI, "Full path: %s\n", full_path);
+	cifs_dbg(FYI, "symname is %s\n", symname);
 
 	/* BB what if DFS and this volume is on different share? BB */
 	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS)
@@ -601,8 +601,8 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
 						 inode->i_sb, xid, NULL);
 
 		if (rc != 0) {
-			cFYI(1, "Create symlink ok, getinodeinfo fail rc = %d",
-			      rc);
+			cifs_dbg(FYI, "Create symlink ok, getinodeinfo fail rc = %d\n",
+				 rc);
 		} else {
 			d_instantiate(direntry, newinode);
 		}
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 1b15bf8..1bec014 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -54,7 +54,7 @@ _get_xid(void)
 	if (GlobalTotalActiveXid > GlobalMaxActiveXid)
 		GlobalMaxActiveXid = GlobalTotalActiveXid;
 	if (GlobalTotalActiveXid > 65000)
-		cFYI(1, "warning: more than 65000 requests active");
+		cifs_dbg(FYI, "warning: more than 65000 requests active\n");
 	xid = GlobalCurrentXid++;
 	spin_unlock(&GlobalMid_Lock);
 	return xid;
@@ -91,7 +91,7 @@ void
 sesInfoFree(struct cifs_ses *buf_to_free)
 {
 	if (buf_to_free == NULL) {
-		cFYI(1, "Null buffer passed to sesInfoFree");
+		cifs_dbg(FYI, "Null buffer passed to sesInfoFree\n");
 		return;
 	}
 
@@ -130,7 +130,7 @@ void
 tconInfoFree(struct cifs_tcon *buf_to_free)
 {
 	if (buf_to_free == NULL) {
-		cFYI(1, "Null buffer passed to tconInfoFree");
+		cifs_dbg(FYI, "Null buffer passed to tconInfoFree\n");
 		return;
 	}
 	atomic_dec(&tconInfoAllocCount);
@@ -180,7 +180,7 @@ void
 cifs_buf_release(void *buf_to_free)
 {
 	if (buf_to_free == NULL) {
-		/* cFYI(1, "Null buffer passed to cifs_buf_release");*/
+		/* cifs_dbg(FYI, "Null buffer passed to cifs_buf_release\n");*/
 		return;
 	}
 	mempool_free(buf_to_free, cifs_req_poolp);
@@ -216,7 +216,7 @@ cifs_small_buf_release(void *buf_to_free)
 {
 
 	if (buf_to_free == NULL) {
-		cFYI(1, "Null buffer passed to cifs_small_buf_release");
+		cifs_dbg(FYI, "Null buffer passed to cifs_small_buf_release\n");
 		return;
 	}
 	mempool_free(buf_to_free, cifs_sm_req_poolp);
@@ -282,15 +282,15 @@ check_smb_hdr(struct smb_hdr *smb, __u16 mid)
 {
 	/* does it have the right SMB "signature" ? */
 	if (*(__le32 *) smb->Protocol != cpu_to_le32(0x424d53ff)) {
-		cERROR(1, "Bad protocol string signature header 0x%x",
-			*(unsigned int *)smb->Protocol);
+		cifs_dbg(VFS, "Bad protocol string signature header 0x%x\n",
+			 *(unsigned int *)smb->Protocol);
 		return 1;
 	}
 
 	/* Make sure that message ids match */
 	if (mid != smb->Mid) {
-		cERROR(1, "Mids do not match. received=%u expected=%u",
-			smb->Mid, mid);
+		cifs_dbg(VFS, "Mids do not match. received=%u expected=%u\n",
+			 smb->Mid, mid);
 		return 1;
 	}
 
@@ -302,7 +302,7 @@ check_smb_hdr(struct smb_hdr *smb, __u16 mid)
 	if (smb->Command == SMB_COM_LOCKING_ANDX)
 		return 0;
 
-	cERROR(1, "Server sent request, not response. mid=%u", smb->Mid);
+	cifs_dbg(VFS, "Server sent request, not response. mid=%u\n", smb->Mid);
 	return 1;
 }
 
@@ -313,8 +313,8 @@ checkSMB(char *buf, unsigned int total_read)
 	__u16 mid = smb->Mid;
 	__u32 rfclen = be32_to_cpu(smb->smb_buf_length);
 	__u32 clc_len;  /* calculated length */
-	cFYI(0, "checkSMB Length: 0x%x, smb_buf_length: 0x%x",
-		total_read, rfclen);
+	cifs_dbg(FYI, "checkSMB Length: 0x%x, smb_buf_length: 0x%x\n",
+		 total_read, rfclen);
 
 	/* is this frame too small to even get to a BCC? */
 	if (total_read < 2 + sizeof(struct smb_hdr)) {
@@ -340,9 +340,9 @@ checkSMB(char *buf, unsigned int total_read)
 				tmp[sizeof(struct smb_hdr)+1] = 0;
 				return 0;
 			}
-			cERROR(1, "rcvd invalid byte count (bcc)");
+			cifs_dbg(VFS, "rcvd invalid byte count (bcc)\n");
 		} else {
-			cERROR(1, "Length less than smb header size");
+			cifs_dbg(VFS, "Length less than smb header size\n");
 		}
 		return -EIO;
 	}
@@ -353,8 +353,8 @@ checkSMB(char *buf, unsigned int total_read)
 	clc_len = smbCalcSize(smb);
 
 	if (4 + rfclen != total_read) {
-		cERROR(1, "Length read does not match RFC1001 length %d",
-				rfclen);
+		cifs_dbg(VFS, "Length read does not match RFC1001 length %d\n",
+			 rfclen);
 		return -EIO;
 	}
 
@@ -365,12 +365,12 @@ checkSMB(char *buf, unsigned int total_read)
 			if (((4 + rfclen) & 0xFFFF) == (clc_len & 0xFFFF))
 				return 0; /* bcc wrapped */
 		}
-		cFYI(1, "Calculated size %u vs length %u mismatch for mid=%u",
-				clc_len, 4 + rfclen, smb->Mid);
+		cifs_dbg(FYI, "Calculated size %u vs length %u mismatch for mid=%u\n",
+			 clc_len, 4 + rfclen, smb->Mid);
 
 		if (4 + rfclen < clc_len) {
-			cERROR(1, "RFC1001 size %u smaller than SMB for mid=%u",
-					rfclen, smb->Mid);
+			cifs_dbg(VFS, "RFC1001 size %u smaller than SMB for mid=%u\n",
+				 rfclen, smb->Mid);
 			return -EIO;
 		} else if (rfclen > clc_len + 512) {
 			/*
@@ -382,8 +382,8 @@ checkSMB(char *buf, unsigned int total_read)
 			 * trailing data, we choose limit the amount of extra
 			 * data to 512 bytes.
 			 */
-			cERROR(1, "RFC1001 size %u more than 512 bytes larger "
-				  "than SMB for mid=%u", rfclen, smb->Mid);
+			cifs_dbg(VFS, "RFC1001 size %u more than 512 bytes larger than SMB for mid=%u\n",
+				 rfclen, smb->Mid);
 			return -EIO;
 		}
 	}
@@ -401,7 +401,7 @@ is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv)
 	struct cifsInodeInfo *pCifsInode;
 	struct cifsFileInfo *netfile;
 
-	cFYI(1, "Checking for oplock break or dnotify response");
+	cifs_dbg(FYI, "Checking for oplock break or dnotify response\n");
 	if ((pSMB->hdr.Command == SMB_COM_NT_TRANSACT) &&
 	   (pSMB->hdr.Flags & SMBFLG_RESPONSE)) {
 		struct smb_com_transaction_change_notify_rsp *pSMBr =
@@ -413,15 +413,15 @@ is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv)
 
 			pnotify = (struct file_notify_information *)
 				((char *)&pSMBr->hdr.Protocol + data_offset);
-			cFYI(1, "dnotify on %s Action: 0x%x",
+			cifs_dbg(FYI, "dnotify on %s Action: 0x%x\n",
 				 pnotify->FileName, pnotify->Action);
 			/*   cifs_dump_mem("Rcvd notify Data: ",buf,
 				sizeof(struct smb_hdr)+60); */
 			return true;
 		}
 		if (pSMBr->hdr.Status.CifsError) {
-			cFYI(1, "notify err 0x%d",
-				pSMBr->hdr.Status.CifsError);
+			cifs_dbg(FYI, "notify err 0x%d\n",
+				 pSMBr->hdr.Status.CifsError);
 			return true;
 		}
 		return false;
@@ -435,7 +435,7 @@ is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv)
 		   large dirty files cached on the client */
 		if ((NT_STATUS_INVALID_HANDLE) ==
 		   le32_to_cpu(pSMB->hdr.Status.CifsError)) {
-			cFYI(1, "invalid handle on oplock break");
+			cifs_dbg(FYI, "invalid handle on oplock break\n");
 			return true;
 		} else if (ERRbadfid ==
 		   le16_to_cpu(pSMB->hdr.Status.DosError.Error)) {
@@ -447,7 +447,7 @@ is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv)
 	if (pSMB->hdr.WordCount != 8)
 		return false;
 
-	cFYI(1, "oplock type 0x%d level 0x%d",
+	cifs_dbg(FYI, "oplock type 0x%d level 0x%d\n",
 		 pSMB->LockType, pSMB->OplockLevel);
 	if (!(pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE))
 		return false;
@@ -469,7 +469,7 @@ is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv)
 				if (pSMB->Fid != netfile->fid.netfid)
 					continue;
 
-				cFYI(1, "file id match, oplock break");
+				cifs_dbg(FYI, "file id match, oplock break\n");
 				pCifsInode = CIFS_I(netfile->dentry->d_inode);
 
 				cifs_set_oplock_level(pCifsInode,
@@ -484,12 +484,12 @@ is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv)
 			}
 			spin_unlock(&cifs_file_list_lock);
 			spin_unlock(&cifs_tcp_ses_lock);
-			cFYI(1, "No matching file for oplock break");
+			cifs_dbg(FYI, "No matching file for oplock break\n");
 			return true;
 		}
 	}
 	spin_unlock(&cifs_tcp_ses_lock);
-	cFYI(1, "Can not process oplock break for non-existent connection");
+	cifs_dbg(FYI, "Can not process oplock break for non-existent connection\n");
 	return true;
 }
 
@@ -536,12 +536,8 @@ cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb)
 {
 	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
 		cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM;
-		cERROR(1, "Autodisabling the use of server inode numbers on "
-			   "%s. This server doesn't seem to support them "
-			   "properly. Hardlinks will not be recognized on this "
-			   "mount. Consider mounting with the \"noserverino\" "
-			   "option to silence this message.",
-			   cifs_sb_master_tcon(cifs_sb)->treeName);
+		cifs_dbg(VFS, "Autodisabling the use of server inode numbers on %s. This server doesn't seem to support them properly. Hardlinks will not be recognized on this mount. Consider mounting with the \"noserverino\" option to silence this message.\n",
+			 cifs_sb_master_tcon(cifs_sb)->treeName);
 	}
 }
 
@@ -552,13 +548,13 @@ void cifs_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock)
 	if (oplock == OPLOCK_EXCLUSIVE) {
 		cinode->clientCanCacheAll = true;
 		cinode->clientCanCacheRead = true;
-		cFYI(1, "Exclusive Oplock granted on inode %p",
-		     &cinode->vfs_inode);
+		cifs_dbg(FYI, "Exclusive Oplock granted on inode %p\n",
+			 &cinode->vfs_inode);
 	} else if (oplock == OPLOCK_READ) {
 		cinode->clientCanCacheAll = false;
 		cinode->clientCanCacheRead = true;
-		cFYI(1, "Level II Oplock granted on inode %p",
-		    &cinode->vfs_inode);
+		cifs_dbg(FYI, "Level II Oplock granted on inode %p\n",
+			 &cinode->vfs_inode);
 	} else {
 		cinode->clientCanCacheAll = false;
 		cinode->clientCanCacheRead = false;
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c
index c0b25b2..af847e1 100644
--- a/fs/cifs/netmisc.c
+++ b/fs/cifs/netmisc.c
@@ -150,8 +150,8 @@ cifs_inet_pton(const int address_family, const char *cp, int len, void *dst)
 	else if (address_family == AF_INET6)
 		ret = in6_pton(cp, len, dst , '\\', NULL);
 
-	cFYI(DBG2, "address conversion returned %d for %*.*s",
-	     ret, len, len, cp);
+	cifs_dbg(NOISY, "address conversion returned %d for %*.*s\n",
+		 ret, len, len, cp);
 	if (ret > 0)
 		ret = 1;
 	return ret;
@@ -887,7 +887,7 @@ map_smb_to_linux_error(char *buf, bool logErr)
 	}
 	/* else ERRHRD class errors or junk  - return EIO */
 
-	cFYI(1, "Mapping smb error code 0x%x to POSIX err %d",
+	cifs_dbg(FYI, "Mapping smb error code 0x%x to POSIX err %d\n",
 		 le32_to_cpu(smb->Status.CifsError), rc);
 
 	/* generic corrective action e.g. reconnect SMB session on
@@ -951,20 +951,20 @@ struct timespec cnvrtDosUnixTm(__le16 le_date, __le16 le_time, int offset)
 	SMB_TIME *st = (SMB_TIME *)&time;
 	SMB_DATE *sd = (SMB_DATE *)&date;
 
-	cFYI(1, "date %d time %d", date, time);
+	cifs_dbg(FYI, "date %d time %d\n", date, time);
 
 	sec = 2 * st->TwoSeconds;
 	min = st->Minutes;
 	if ((sec > 59) || (min > 59))
-		cERROR(1, "illegal time min %d sec %d", min, sec);
+		cifs_dbg(VFS, "illegal time min %d sec %d\n", min, sec);
 	sec += (min * 60);
 	sec += 60 * 60 * st->Hours;
 	if (st->Hours > 24)
-		cERROR(1, "illegal hours %d", st->Hours);
+		cifs_dbg(VFS, "illegal hours %d\n", st->Hours);
 	days = sd->Day;
 	month = sd->Month;
 	if ((days > 31) || (month > 12)) {
-		cERROR(1, "illegal date, month %d day: %d", month, days);
+		cifs_dbg(VFS, "illegal date, month %d day: %d\n", month, days);
 		if (month > 12)
 			month = 12;
 	}
@@ -990,7 +990,7 @@ struct timespec cnvrtDosUnixTm(__le16 le_date, __le16 le_time, int offset)
 
 	ts.tv_sec = sec + offset;
 
-	/* cFYI(1, "sec after cnvrt dos to unix time %d",sec); */
+	/* cifs_dbg(FYI, "sec after cnvrt dos to unix time %d\n",sec); */
 
 	ts.tv_nsec = 0;
 	return ts;
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index df40cc5..770d5a9 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -48,15 +48,15 @@ static void dump_cifs_file_struct(struct file *file, char *label)
 	if (file) {
 		cf = file->private_data;
 		if (cf == NULL) {
-			cFYI(1, "empty cifs private file data");
+			cifs_dbg(FYI, "empty cifs private file data\n");
 			return;
 		}
 		if (cf->invalidHandle)
-			cFYI(1, "invalid handle");
+			cifs_dbg(FYI, "invalid handle\n");
 		if (cf->srch_inf.endOfSearch)
-			cFYI(1, "end of search");
+			cifs_dbg(FYI, "end of search\n");
 		if (cf->srch_inf.emptyDir)
-			cFYI(1, "empty dir");
+			cifs_dbg(FYI, "empty dir\n");
 	}
 }
 #else
@@ -80,7 +80,7 @@ cifs_prime_dcache(struct dentry *parent, struct qstr *name,
 	struct super_block *sb = parent->d_inode->i_sb;
 	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
 
-	cFYI(1, "%s: for %s", __func__, name->name);
+	cifs_dbg(FYI, "%s: for %s\n", __func__, name->name);
 
 	dentry = d_hash_and_lookup(parent, name);
 	if (unlikely(IS_ERR(dentry)))
@@ -233,7 +233,7 @@ int get_symlink_reparse_path(char *full_path, struct cifs_sb_info *cifs_sb,
 				fid,
 				cifs_sb->local_nls);
 		if (CIFSSMBClose(xid, ptcon, fid)) {
-			cFYI(1, "Error closing temporary reparsepoint open");
+			cifs_dbg(FYI, "Error closing temporary reparsepoint open\n");
 		}
 	}
 }
@@ -285,7 +285,7 @@ initiate_cifs_search(const unsigned int xid, struct file *file)
 		goto error_exit;
 	}
 
-	cFYI(1, "Full path: %s start at: %lld", full_path, file->f_pos);
+	cifs_dbg(FYI, "Full path: %s start at: %lld\n", full_path, file->f_pos);
 
 ffirst_retry:
 	/* test for Unix extensions */
@@ -336,7 +336,7 @@ static int cifs_unicode_bytelen(const char *str)
 		if (ustr[len] == 0)
 			return len << 1;
 	}
-	cFYI(1, "Unicode string longer than PATH_MAX found");
+	cifs_dbg(FYI, "Unicode string longer than PATH_MAX found\n");
 	return len << 1;
 }
 
@@ -353,18 +353,18 @@ static char *nxt_dir_entry(char *old_entry, char *end_of_smb, int level)
 				pfData->FileNameLength;
 	} else
 		new_entry = old_entry + le32_to_cpu(pDirInfo->NextEntryOffset);
-	cFYI(1, "new entry %p old entry %p", new_entry, old_entry);
+	cifs_dbg(FYI, "new entry %p old entry %p\n", new_entry, old_entry);
 	/* validate that new_entry is not past end of SMB */
 	if (new_entry >= end_of_smb) {
-		cERROR(1, "search entry %p began after end of SMB %p old entry %p",
-			new_entry, end_of_smb, old_entry);
+		cifs_dbg(VFS, "search entry %p began after end of SMB %p old entry %p\n",
+			 new_entry, end_of_smb, old_entry);
 		return NULL;
 	} else if (((level == SMB_FIND_FILE_INFO_STANDARD) &&
 		    (new_entry + sizeof(FIND_FILE_STANDARD_INFO) > end_of_smb))
 		  || ((level != SMB_FIND_FILE_INFO_STANDARD) &&
 		   (new_entry + sizeof(FILE_DIRECTORY_INFO) > end_of_smb)))  {
-		cERROR(1, "search entry %p extends after end of SMB %p",
-			new_entry, end_of_smb);
+		cifs_dbg(VFS, "search entry %p extends after end of SMB %p\n",
+			 new_entry, end_of_smb);
 		return NULL;
 	} else
 		return new_entry;
@@ -457,7 +457,7 @@ static int cifs_fill_dirent(struct cifs_dirent *de, const void *info,
 		cifs_fill_dirent_std(de, info);
 		break;
 	default:
-		cFYI(1, "Unknown findfirst level %d", level);
+		cifs_dbg(FYI, "Unknown findfirst level %d\n", level);
 		return -EINVAL;
 	}
 
@@ -572,7 +572,7 @@ find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon,
 	if (((index_to_find < cfile->srch_inf.index_of_last_entry) &&
 	     is_dir_changed(file)) || (index_to_find < first_entry_in_buffer)) {
 		/* close and restart search */
-		cFYI(1, "search backing up - close and restart search");
+		cifs_dbg(FYI, "search backing up - close and restart search\n");
 		spin_lock(&cifs_file_list_lock);
 		if (!cfile->srch_inf.endOfSearch && !cfile->invalidHandle) {
 			cfile->invalidHandle = true;
@@ -582,7 +582,7 @@ find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon,
 		} else
 			spin_unlock(&cifs_file_list_lock);
 		if (cfile->srch_inf.ntwrk_buf_start) {
-			cFYI(1, "freeing SMB ff cache buf on search rewind");
+			cifs_dbg(FYI, "freeing SMB ff cache buf on search rewind\n");
 			if (cfile->srch_inf.smallBuf)
 				cifs_small_buf_release(cfile->srch_inf.
 						ntwrk_buf_start);
@@ -593,7 +593,7 @@ find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon,
 		}
 		rc = initiate_cifs_search(xid, file);
 		if (rc) {
-			cFYI(1, "error %d reinitiating a search on rewind",
+			cifs_dbg(FYI, "error %d reinitiating a search on rewind\n",
 				 rc);
 			return rc;
 		}
@@ -608,7 +608,7 @@ find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon,
 
 	while ((index_to_find >= cfile->srch_inf.index_of_last_entry) &&
 	       (rc == 0) && !cfile->srch_inf.endOfSearch) {
-		cFYI(1, "calling findnext2");
+		cifs_dbg(FYI, "calling findnext2\n");
 		rc = server->ops->query_dir_next(xid, tcon, &cfile->fid,
 						 search_flags,
 						 &cfile->srch_inf);
@@ -631,7 +631,7 @@ find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon,
 		first_entry_in_buffer = cfile->srch_inf.index_of_last_entry
 					- cfile->srch_inf.entries_in_buffer;
 		pos_in_buf = index_to_find - first_entry_in_buffer;
-		cFYI(1, "found entry - pos_in_buf %d", pos_in_buf);
+		cifs_dbg(FYI, "found entry - pos_in_buf %d\n", pos_in_buf);
 
 		for (i = 0; (i < (pos_in_buf)) && (cur_ent != NULL); i++) {
 			/* go entry by entry figuring out which is first */
@@ -640,19 +640,18 @@ find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon,
 		}
 		if ((cur_ent == NULL) && (i < pos_in_buf)) {
 			/* BB fixme - check if we should flag this error */
-			cERROR(1, "reached end of buf searching for pos in buf"
-				  " %d index to find %lld rc %d", pos_in_buf,
-				  index_to_find, rc);
+			cifs_dbg(VFS, "reached end of buf searching for pos in buf %d index to find %lld rc %d\n",
+				 pos_in_buf, index_to_find, rc);
 		}
 		rc = 0;
 		*current_entry = cur_ent;
 	} else {
-		cFYI(1, "index not in buffer - could not findnext into it");
+		cifs_dbg(FYI, "index not in buffer - could not findnext into it\n");
 		return 0;
 	}
 
 	if (pos_in_buf >= cfile->srch_inf.entries_in_buffer) {
-		cFYI(1, "can not return entries pos_in_buf beyond last");
+		cifs_dbg(FYI, "can not return entries pos_in_buf beyond last\n");
 		*num_to_ret = 0;
 	} else
 		*num_to_ret = cfile->srch_inf.entries_in_buffer - pos_in_buf;
@@ -678,8 +677,8 @@ static int cifs_filldir(char *find_entry, struct file *file, filldir_t filldir,
 		return rc;
 
 	if (de.namelen > max_len) {
-		cERROR(1, "bad search response length %zd past smb end",
-			  de.namelen);
+		cifs_dbg(VFS, "bad search response length %zd past smb end\n",
+			 de.namelen);
 		return -EINVAL;
 	}
 
@@ -768,7 +767,7 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
 	 */
 	if (file->private_data == NULL) {
 		rc = initiate_cifs_search(xid, file);
-		cFYI(1, "initiate cifs search rc %d", rc);
+		cifs_dbg(FYI, "initiate cifs search rc %d\n", rc);
 		if (rc)
 			goto rddir2_exit;
 	}
@@ -777,7 +776,7 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
 	case 0:
 		if (filldir(direntry, ".", 1, file->f_pos,
 		     file_inode(file)->i_ino, DT_DIR) < 0) {
-			cERROR(1, "Filldir for current dir failed");
+			cifs_dbg(VFS, "Filldir for current dir failed\n");
 			rc = -ENOMEM;
 			break;
 		}
@@ -785,7 +784,7 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
 	case 1:
 		if (filldir(direntry, "..", 2, file->f_pos,
 		     parent_ino(file->f_path.dentry), DT_DIR) < 0) {
-			cERROR(1, "Filldir for parent dir failed");
+			cifs_dbg(VFS, "Filldir for parent dir failed\n");
 			rc = -ENOMEM;
 			break;
 		}
@@ -804,7 +803,7 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
 		cifsFile = file->private_data;
 		if (cifsFile->srch_inf.endOfSearch) {
 			if (cifsFile->srch_inf.emptyDir) {
-				cFYI(1, "End of search, empty dir");
+				cifs_dbg(FYI, "End of search, empty dir\n");
 				rc = 0;
 				break;
 			}
@@ -817,16 +816,16 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
 		rc = find_cifs_entry(xid, tcon, file, &current_entry,
 				     &num_to_fill);
 		if (rc) {
-			cFYI(1, "fce error %d", rc);
+			cifs_dbg(FYI, "fce error %d\n", rc);
 			goto rddir2_exit;
 		} else if (current_entry != NULL) {
-			cFYI(1, "entry %lld found", file->f_pos);
+			cifs_dbg(FYI, "entry %lld found\n", file->f_pos);
 		} else {
-			cFYI(1, "could not find entry");
+			cifs_dbg(FYI, "could not find entry\n");
 			goto rddir2_exit;
 		}
-		cFYI(1, "loop through %d times filling dir for net buf %p",
-			num_to_fill, cifsFile->srch_inf.ntwrk_buf_start);
+		cifs_dbg(FYI, "loop through %d times filling dir for net buf %p\n",
+			 num_to_fill, cifsFile->srch_inf.ntwrk_buf_start);
 		max_len = tcon->ses->server->ops->calc_smb_size(
 				cifsFile->srch_inf.ntwrk_buf_start);
 		end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len;
@@ -840,8 +839,8 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
 		for (i = 0; (i < num_to_fill) && (rc == 0); i++) {
 			if (current_entry == NULL) {
 				/* evaluate whether this case is an error */
-				cERROR(1, "past SMB end,  num to fill %d i %d",
-					  num_to_fill, i);
+				cifs_dbg(VFS, "past SMB end,  num to fill %d i %d\n",
+					 num_to_fill, i);
 				break;
 			}
 			/*
@@ -858,8 +857,8 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
 			file->f_pos++;
 			if (file->f_pos ==
 				cifsFile->srch_inf.index_of_last_entry) {
-				cFYI(1, "last entry in buf at pos %lld %s",
-					file->f_pos, tmp_buf);
+				cifs_dbg(FYI, "last entry in buf at pos %lld %s\n",
+					 file->f_pos, tmp_buf);
 				cifs_save_resume_key(current_entry, cifsFile);
 				break;
 			} else
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
index 76809f4..f230571 100644
--- a/fs/cifs/sess.c
+++ b/fs/cifs/sess.c
@@ -283,11 +283,11 @@ decode_unicode_ssetup(char **pbcc_area, int bleft, struct cifs_ses *ses,
 	int len;
 	char *data = *pbcc_area;
 
-	cFYI(1, "bleft %d", bleft);
+	cifs_dbg(FYI, "bleft %d\n", bleft);
 
 	kfree(ses->serverOS);
 	ses->serverOS = cifs_strndup_from_utf16(data, bleft, true, nls_cp);
-	cFYI(1, "serverOS=%s", ses->serverOS);
+	cifs_dbg(FYI, "serverOS=%s\n", ses->serverOS);
 	len = (UniStrnlen((wchar_t *) data, bleft / 2) * 2) + 2;
 	data += len;
 	bleft -= len;
@@ -296,7 +296,7 @@ decode_unicode_ssetup(char **pbcc_area, int bleft, struct cifs_ses *ses,
 
 	kfree(ses->serverNOS);
 	ses->serverNOS = cifs_strndup_from_utf16(data, bleft, true, nls_cp);
-	cFYI(1, "serverNOS=%s", ses->serverNOS);
+	cifs_dbg(FYI, "serverNOS=%s\n", ses->serverNOS);
 	len = (UniStrnlen((wchar_t *) data, bleft / 2) * 2) + 2;
 	data += len;
 	bleft -= len;
@@ -305,7 +305,7 @@ decode_unicode_ssetup(char **pbcc_area, int bleft, struct cifs_ses *ses,
 
 	kfree(ses->serverDomain);
 	ses->serverDomain = cifs_strndup_from_utf16(data, bleft, true, nls_cp);
-	cFYI(1, "serverDomain=%s", ses->serverDomain);
+	cifs_dbg(FYI, "serverDomain=%s\n", ses->serverDomain);
 
 	return;
 }
@@ -318,7 +318,7 @@ static int decode_ascii_ssetup(char **pbcc_area, __u16 bleft,
 	int len;
 	char *bcc_ptr = *pbcc_area;
 
-	cFYI(1, "decode sessetup ascii. bleft %d", bleft);
+	cifs_dbg(FYI, "decode sessetup ascii. bleft %d\n", bleft);
 
 	len = strnlen(bcc_ptr, bleft);
 	if (len >= bleft)
@@ -330,7 +330,7 @@ static int decode_ascii_ssetup(char **pbcc_area, __u16 bleft,
 	if (ses->serverOS)
 		strncpy(ses->serverOS, bcc_ptr, len);
 	if (strncmp(ses->serverOS, "OS/2", 4) == 0) {
-			cFYI(1, "OS/2 server");
+		cifs_dbg(FYI, "OS/2 server\n");
 			ses->flags |= CIFS_SES_OS2;
 	}
 
@@ -359,7 +359,7 @@ static int decode_ascii_ssetup(char **pbcc_area, __u16 bleft,
 	/* BB For newer servers which do not support Unicode,
 	   but thus do return domain here we could add parsing
 	   for it later, but it is not very important */
-	cFYI(1, "ascii: bytes left %d", bleft);
+	cifs_dbg(FYI, "ascii: bytes left %d\n", bleft);
 
 	return rc;
 }
@@ -373,16 +373,18 @@ int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len,
 	CHALLENGE_MESSAGE *pblob = (CHALLENGE_MESSAGE *)bcc_ptr;
 
 	if (blob_len < sizeof(CHALLENGE_MESSAGE)) {
-		cERROR(1, "challenge blob len %d too small", blob_len);
+		cifs_dbg(VFS, "challenge blob len %d too small\n", blob_len);
 		return -EINVAL;
 	}
 
 	if (memcmp(pblob->Signature, "NTLMSSP", 8)) {
-		cERROR(1, "blob signature incorrect %s", pblob->Signature);
+		cifs_dbg(VFS, "blob signature incorrect %s\n",
+			 pblob->Signature);
 		return -EINVAL;
 	}
 	if (pblob->MessageType != NtLmChallenge) {
-		cERROR(1, "Incorrect message type %d", pblob->MessageType);
+		cifs_dbg(VFS, "Incorrect message type %d\n",
+			 pblob->MessageType);
 		return -EINVAL;
 	}
 
@@ -395,16 +397,17 @@ int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len,
 	tioffset = le32_to_cpu(pblob->TargetInfoArray.BufferOffset);
 	tilen = le16_to_cpu(pblob->TargetInfoArray.Length);
 	if (tioffset > blob_len || tioffset + tilen > blob_len) {
-		cERROR(1, "tioffset + tilen too high %u + %u", tioffset, tilen);
+		cifs_dbg(VFS, "tioffset + tilen too high %u + %u",
+			tioffset, tilen);
 		return -EINVAL;
 	}
 	if (tilen) {
-		ses->auth_key.response = kmalloc(tilen, GFP_KERNEL);
+		ses->auth_key.response = kmemdup(bcc_ptr + tioffset, tilen,
+						 GFP_KERNEL);
 		if (!ses->auth_key.response) {
-			cERROR(1, "Challenge target info allocation failure");
+			cifs_dbg(VFS, "Challenge target info alloc failure");
 			return -ENOMEM;
 		}
-		memcpy(ses->auth_key.response, bcc_ptr + tioffset, tilen);
 		ses->auth_key.len = tilen;
 	}
 
@@ -486,7 +489,7 @@ int build_ntlmssp_auth_blob(unsigned char *pbuffer,
 	sec_blob->NtChallengeResponse.BufferOffset = cpu_to_le32(tmp - pbuffer);
 	rc = setup_ntlmv2_rsp(ses, nls_cp);
 	if (rc) {
-		cERROR(1, "Error %d during NTLMSSP authentication", rc);
+		cifs_dbg(VFS, "Error %d during NTLMSSP authentication\n", rc);
 		goto setup_ntlmv2_ret;
 	}
 	memcpy(tmp, ses->auth_key.response + CIFS_SESS_KEY_SIZE,
@@ -580,7 +583,7 @@ CIFS_SessSetup(const unsigned int xid, struct cifs_ses *ses,
 		return -EINVAL;
 
 	type = ses->server->secType;
-	cFYI(1, "sess setup type %d", type);
+	cifs_dbg(FYI, "sess setup type %d\n", type);
 	if (type == RawNTLMSSP) {
 		/* if memory allocation is successful, caller of this function
 		 * frees it.
@@ -674,7 +677,7 @@ ssetup_ntlmssp_authenticate:
 		changed to do higher than lanman dialect and
 		we reconnected would we ever calc signing_key? */
 
-		cFYI(1, "Negotiating LANMAN setting up strings");
+		cifs_dbg(FYI, "Negotiating LANMAN setting up strings\n");
 		/* Unicode not allowed for LANMAN dialects */
 		ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
 #endif
@@ -688,7 +691,8 @@ ssetup_ntlmssp_authenticate:
 		/* calculate ntlm response and session key */
 		rc = setup_ntlm_response(ses, nls_cp);
 		if (rc) {
-			cERROR(1, "Error %d during NTLM authentication", rc);
+			cifs_dbg(VFS, "Error %d during NTLM authentication\n",
+				 rc);
 			goto ssetup_exit;
 		}
 
@@ -718,7 +722,8 @@ ssetup_ntlmssp_authenticate:
 		/* calculate nlmv2 response and session key */
 		rc = setup_ntlmv2_rsp(ses, nls_cp);
 		if (rc) {
-			cERROR(1, "Error %d during NTLMv2 authentication", rc);
+			cifs_dbg(VFS, "Error %d during NTLMv2 authentication\n",
+				 rc);
 			goto ssetup_exit;
 		}
 		memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE,
@@ -754,21 +759,21 @@ ssetup_ntlmssp_authenticate:
 		/* check version field to make sure that cifs.upcall is
 		   sending us a response in an expected form */
 		if (msg->version != CIFS_SPNEGO_UPCALL_VERSION) {
-			cERROR(1, "incorrect version of cifs.upcall (expected"
-				   " %d but got %d)",
+			cifs_dbg(VFS, "incorrect version of cifs.upcall "
+				   "expected %d but got %d)",
 				   CIFS_SPNEGO_UPCALL_VERSION, msg->version);
 			rc = -EKEYREJECTED;
 			goto ssetup_exit;
 		}
 
-		ses->auth_key.response = kmalloc(msg->sesskey_len, GFP_KERNEL);
+		ses->auth_key.response = kmemdup(msg->data, msg->sesskey_len,
+						 GFP_KERNEL);
 		if (!ses->auth_key.response) {
-			cERROR(1, "Kerberos can't allocate (%u bytes) memory",
+			cifs_dbg(VFS, "Kerberos can't allocate (%u bytes) memory",
 					msg->sesskey_len);
 			rc = -ENOMEM;
 			goto ssetup_exit;
 		}
-		memcpy(ses->auth_key.response, msg->data, msg->sesskey_len);
 		ses->auth_key.len = msg->sesskey_len;
 
 		pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
@@ -790,18 +795,18 @@ ssetup_ntlmssp_authenticate:
 		/* BB: is this right? */
 			ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
 #else /* ! CONFIG_CIFS_UPCALL */
-		cERROR(1, "Kerberos negotiated but upcall support disabled!");
+		cifs_dbg(VFS, "Kerberos negotiated but upcall support disabled!\n");
 		rc = -ENOSYS;
 		goto ssetup_exit;
 #endif /* CONFIG_CIFS_UPCALL */
 	} else if (type == RawNTLMSSP) {
 		if ((pSMB->req.hdr.Flags2 & SMBFLG2_UNICODE) == 0) {
-			cERROR(1, "NTLMSSP requires Unicode support");
+			cifs_dbg(VFS, "NTLMSSP requires Unicode support\n");
 			rc = -ENOSYS;
 			goto ssetup_exit;
 		}
 
-		cFYI(1, "ntlmssp session setup phase %d", phase);
+		cifs_dbg(FYI, "ntlmssp session setup phase %d\n", phase);
 		pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
 		capabilities |= CAP_EXTENDED_SECURITY;
 		pSMB->req.Capabilities |= cpu_to_le32(capabilities);
@@ -824,7 +829,6 @@ ssetup_ntlmssp_authenticate:
 				5*sizeof(struct _AUTHENTICATE_MESSAGE),
 				GFP_KERNEL);
 			if (!ntlmsspblob) {
-				cERROR(1, "Can't allocate NTLMSSP blob");
 				rc = -ENOMEM;
 				goto ssetup_exit;
 			}
@@ -844,7 +848,7 @@ ssetup_ntlmssp_authenticate:
 			smb_buf->Uid = ses->Suid;
 			break;
 		default:
-			cERROR(1, "invalid phase %d", phase);
+			cifs_dbg(VFS, "invalid phase %d\n", phase);
 			rc = -ENOSYS;
 			goto ssetup_exit;
 		}
@@ -855,7 +859,7 @@ ssetup_ntlmssp_authenticate:
 		}
 		unicode_oslm_strings(&bcc_ptr, nls_cp);
 	} else {
-		cERROR(1, "secType %d not supported!", type);
+		cifs_dbg(VFS, "secType %d not supported!\n", type);
 		rc = -ENOSYS;
 		goto ssetup_exit;
 	}
@@ -880,7 +884,7 @@ ssetup_ntlmssp_authenticate:
 	    (smb_buf->Status.CifsError ==
 			cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))) {
 		if (phase != NtLmNegotiate) {
-			cERROR(1, "Unexpected more processing error");
+			cifs_dbg(VFS, "Unexpected more processing error\n");
 			goto ssetup_exit;
 		}
 		/* NTLMSSP Negotiate sent now processing challenge (response) */
@@ -892,14 +896,14 @@ ssetup_ntlmssp_authenticate:
 
 	if ((smb_buf->WordCount != 3) && (smb_buf->WordCount != 4)) {
 		rc = -EIO;
-		cERROR(1, "bad word count %d", smb_buf->WordCount);
+		cifs_dbg(VFS, "bad word count %d\n", smb_buf->WordCount);
 		goto ssetup_exit;
 	}
 	action = le16_to_cpu(pSMB->resp.Action);
 	if (action & GUEST_LOGIN)
-		cFYI(1, "Guest login"); /* BB mark SesInfo struct? */
+		cifs_dbg(FYI, "Guest login\n"); /* BB mark SesInfo struct? */
 	ses->Suid = smb_buf->Uid;   /* UID left in wire format (le) */
-	cFYI(1, "UID = %llu ", ses->Suid);
+	cifs_dbg(FYI, "UID = %llu\n", ses->Suid);
 	/* response can have either 3 or 4 word count - Samba sends 3 */
 	/* and lanman response is 3 */
 	bytes_remaining = get_bcc(smb_buf);
@@ -908,7 +912,8 @@ ssetup_ntlmssp_authenticate:
 	if (smb_buf->WordCount == 4) {
 		blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength);
 		if (blob_len > bytes_remaining) {
-			cERROR(1, "bad security blob length %d", blob_len);
+			cifs_dbg(VFS, "bad security blob length %d\n",
+				 blob_len);
 			rc = -EINVAL;
 			goto ssetup_exit;
 		}
@@ -946,7 +951,7 @@ ssetup_exit:
 	kfree(ntlmsspblob);
 	ntlmsspblob = NULL;
 	if (resp_buf_type == CIFS_SMALL_BUFFER) {
-		cFYI(1, "ssetup freeing small buf %p", iov[0].iov_base);
+		cifs_dbg(FYI, "ssetup freeing small buf %p\n", iov[0].iov_base);
 		cifs_small_buf_release(iov[0].iov_base);
 	} else if (resp_buf_type == CIFS_LARGE_BUFFER)
 		cifs_buf_release(iov[0].iov_base);
diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c
index 47bc5a8..3efdb9d 100644
--- a/fs/cifs/smb1ops.c
+++ b/fs/cifs/smb1ops.c
@@ -61,10 +61,13 @@ send_nt_cancel(struct TCP_Server_Info *server, void *buf,
 	 */
 	--server->sequence_number;
 	rc = smb_send(server, in_buf, be32_to_cpu(in_buf->smb_buf_length));
+	if (rc < 0)
+		server->sequence_number--;
+
 	mutex_unlock(&server->srv_mutex);
 
-	cFYI(1, "issued NT_CANCEL for mid %u, rc = %d",
-		in_buf->Mid, rc);
+	cifs_dbg(FYI, "issued NT_CANCEL for mid %u, rc = %d\n",
+		 in_buf->Mid, rc);
 
 	return rc;
 }
@@ -249,7 +252,7 @@ check2ndT2(char *buf)
 	/* check for plausible wct, bcc and t2 data and parm sizes */
 	/* check for parm and data offset going beyond end of smb */
 	if (pSMB->WordCount != 10) { /* coalesce_t2 depends on this */
-		cFYI(1, "invalid transact2 word count");
+		cifs_dbg(FYI, "invalid transact2 word count\n");
 		return -EINVAL;
 	}
 
@@ -261,18 +264,18 @@ check2ndT2(char *buf)
 	if (total_data_size == data_in_this_rsp)
 		return 0;
 	else if (total_data_size < data_in_this_rsp) {
-		cFYI(1, "total data %d smaller than data in frame %d",
-			total_data_size, data_in_this_rsp);
+		cifs_dbg(FYI, "total data %d smaller than data in frame %d\n",
+			 total_data_size, data_in_this_rsp);
 		return -EINVAL;
 	}
 
 	remaining = total_data_size - data_in_this_rsp;
 
-	cFYI(1, "missing %d bytes from transact2, check next response",
-		remaining);
+	cifs_dbg(FYI, "missing %d bytes from transact2, check next response\n",
+		 remaining);
 	if (total_data_size > CIFSMaxBufSize) {
-		cERROR(1, "TotalDataSize %d is over maximum buffer %d",
-			total_data_size, CIFSMaxBufSize);
+		cifs_dbg(VFS, "TotalDataSize %d is over maximum buffer %d\n",
+			 total_data_size, CIFSMaxBufSize);
 		return -EINVAL;
 	}
 	return remaining;
@@ -293,28 +296,28 @@ coalesce_t2(char *second_buf, struct smb_hdr *target_hdr)
 	tgt_total_cnt = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount);
 
 	if (tgt_total_cnt != src_total_cnt)
-		cFYI(1, "total data count of primary and secondary t2 differ "
-			"source=%hu target=%hu", src_total_cnt, tgt_total_cnt);
+		cifs_dbg(FYI, "total data count of primary and secondary t2 differ source=%hu target=%hu\n",
+			 src_total_cnt, tgt_total_cnt);
 
 	total_in_tgt = get_unaligned_le16(&pSMBt->t2_rsp.DataCount);
 
 	remaining = tgt_total_cnt - total_in_tgt;
 
 	if (remaining < 0) {
-		cFYI(1, "Server sent too much data. tgt_total_cnt=%hu "
-			"total_in_tgt=%hu", tgt_total_cnt, total_in_tgt);
+		cifs_dbg(FYI, "Server sent too much data. tgt_total_cnt=%hu total_in_tgt=%hu\n",
+			 tgt_total_cnt, total_in_tgt);
 		return -EPROTO;
 	}
 
 	if (remaining == 0) {
 		/* nothing to do, ignore */
-		cFYI(1, "no more data remains");
+		cifs_dbg(FYI, "no more data remains\n");
 		return 0;
 	}
 
 	total_in_src = get_unaligned_le16(&pSMBs->t2_rsp.DataCount);
 	if (remaining < total_in_src)
-		cFYI(1, "transact2 2nd response contains too much data");
+		cifs_dbg(FYI, "transact2 2nd response contains too much data\n");
 
 	/* find end of first SMB data area */
 	data_area_of_tgt = (char *)&pSMBt->hdr.Protocol +
@@ -329,7 +332,8 @@ coalesce_t2(char *second_buf, struct smb_hdr *target_hdr)
 	total_in_tgt += total_in_src;
 	/* is the result too big for the field? */
 	if (total_in_tgt > USHRT_MAX) {
-		cFYI(1, "coalesced DataCount too large (%u)", total_in_tgt);
+		cifs_dbg(FYI, "coalesced DataCount too large (%u)\n",
+			 total_in_tgt);
 		return -EPROTO;
 	}
 	put_unaligned_le16(total_in_tgt, &pSMBt->t2_rsp.DataCount);
@@ -339,7 +343,7 @@ coalesce_t2(char *second_buf, struct smb_hdr *target_hdr)
 	byte_count += total_in_src;
 	/* is the result too big for the field? */
 	if (byte_count > USHRT_MAX) {
-		cFYI(1, "coalesced BCC too large (%u)", byte_count);
+		cifs_dbg(FYI, "coalesced BCC too large (%u)\n", byte_count);
 		return -EPROTO;
 	}
 	put_bcc(byte_count, target_hdr);
@@ -348,7 +352,8 @@ coalesce_t2(char *second_buf, struct smb_hdr *target_hdr)
 	byte_count += total_in_src;
 	/* don't allow buffer to overflow */
 	if (byte_count > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
-		cFYI(1, "coalesced BCC exceeds buffer size (%u)", byte_count);
+		cifs_dbg(FYI, "coalesced BCC exceeds buffer size (%u)\n",
+			 byte_count);
 		return -ENOBUFS;
 	}
 	target_hdr->smb_buf_length = cpu_to_be32(byte_count);
@@ -358,12 +363,12 @@ coalesce_t2(char *second_buf, struct smb_hdr *target_hdr)
 
 	if (remaining != total_in_src) {
 		/* more responses to go */
-		cFYI(1, "waiting for more secondary responses");
+		cifs_dbg(FYI, "waiting for more secondary responses\n");
 		return 1;
 	}
 
 	/* we are done */
-	cFYI(1, "found the last secondary response");
+	cifs_dbg(FYI, "found the last secondary response\n");
 	return 0;
 }
 
@@ -388,7 +393,7 @@ cifs_check_trans2(struct mid_q_entry *mid, struct TCP_Server_Info *server,
 	}
 	if (!server->large_buf) {
 		/*FIXME: switch to already allocated largebuf?*/
-		cERROR(1, "1st trans2 resp needs bigbuf");
+		cifs_dbg(VFS, "1st trans2 resp needs bigbuf\n");
 	} else {
 		/* Have first buffer */
 		mid->resp_buf = buf;
@@ -776,8 +781,7 @@ smb_set_file_info(struct inode *inode, const char *full_path,
 			goto out;
 	}
 
-	cFYI(1, "calling SetFileInfo since SetPathInfo for times not supported "
-		"by this server");
+	cifs_dbg(FYI, "calling SetFileInfo since SetPathInfo for times not supported by this server\n");
 	rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN,
 			 SYNCHRONIZE | FILE_WRITE_ATTRIBUTES, CREATE_NOT_DIR,
 			 &netfid, &oplock, NULL, cifs_sb->local_nls,
diff --git a/fs/cifs/smb2file.c b/fs/cifs/smb2file.c
index 71e6aed..5da1b55 100644
--- a/fs/cifs/smb2file.c
+++ b/fs/cifs/smb2file.c
@@ -43,13 +43,13 @@ smb2_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock)
 	if (oplock == SMB2_OPLOCK_LEVEL_EXCLUSIVE) {
 		cinode->clientCanCacheAll = true;
 		cinode->clientCanCacheRead = true;
-		cFYI(1, "Exclusive Oplock granted on inode %p",
-		     &cinode->vfs_inode);
+		cifs_dbg(FYI, "Exclusive Oplock granted on inode %p\n",
+			 &cinode->vfs_inode);
 	} else if (oplock == SMB2_OPLOCK_LEVEL_II) {
 		cinode->clientCanCacheAll = false;
 		cinode->clientCanCacheRead = true;
-		cFYI(1, "Level II Oplock granted on inode %p",
-		    &cinode->vfs_inode);
+		cifs_dbg(FYI, "Level II Oplock granted on inode %p\n",
+			 &cinode->vfs_inode);
 	} else {
 		cinode->clientCanCacheAll = false;
 		cinode->clientCanCacheRead = false;
diff --git a/fs/cifs/smb2inode.c b/fs/cifs/smb2inode.c
index 7064824..fff6dfb 100644
--- a/fs/cifs/smb2inode.c
+++ b/fs/cifs/smb2inode.c
@@ -92,7 +92,7 @@ smb2_open_op_close(const unsigned int xid, struct cifs_tcon *tcon,
 				      (FILE_BASIC_INFO *)data);
 		break;
 	default:
-		cERROR(1, "Invalid command");
+		cifs_dbg(VFS, "Invalid command\n");
 		break;
 	}
 
diff --git a/fs/cifs/smb2maperror.c b/fs/cifs/smb2maperror.c
index 494c912..7c2f45c 100644
--- a/fs/cifs/smb2maperror.c
+++ b/fs/cifs/smb2maperror.c
@@ -2472,7 +2472,7 @@ map_smb2_to_linux_error(char *buf, bool log_err)
 
 	/* on error mapping not found  - return EIO */
 
-	cFYI(1, "Mapping SMB2 status code %d to POSIX err %d",
+	cifs_dbg(FYI, "Mapping SMB2 status code %d to POSIX err %d\n",
 		 smb2err, rc);
 
 	return rc;
diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c
index 7b1c5e3..10383d8 100644
--- a/fs/cifs/smb2misc.c
+++ b/fs/cifs/smb2misc.c
@@ -45,17 +45,17 @@ check_smb2_hdr(struct smb2_hdr *hdr, __u64 mid)
 			if (hdr->Command == SMB2_OPLOCK_BREAK)
 				return 0;
 			else
-				cERROR(1, "Received Request not response");
+				cifs_dbg(VFS, "Received Request not response\n");
 		}
 	} else { /* bad signature or mid */
 		if (*(__le32 *)hdr->ProtocolId != SMB2_PROTO_NUMBER)
-			cERROR(1, "Bad protocol string signature header %x",
-				  *(unsigned int *) hdr->ProtocolId);
+			cifs_dbg(VFS, "Bad protocol string signature header %x\n",
+				 *(unsigned int *) hdr->ProtocolId);
 		if (mid != hdr->MessageId)
-			cERROR(1, "Mids do not match: %llu and %llu", mid,
-				  hdr->MessageId);
+			cifs_dbg(VFS, "Mids do not match: %llu and %llu\n",
+				 mid, hdr->MessageId);
 	}
-	cERROR(1, "Bad SMB detected. The Mid=%llu", hdr->MessageId);
+	cifs_dbg(VFS, "Bad SMB detected. The Mid=%llu\n", hdr->MessageId);
 	return 1;
 }
 
@@ -101,7 +101,8 @@ smb2_check_message(char *buf, unsigned int length)
 	int command;
 
 	/* BB disable following printk later */
-	cFYI(1, "%s length: 0x%x, smb_buf_length: 0x%x", __func__, length, len);
+	cifs_dbg(FYI, "%s length: 0x%x, smb_buf_length: 0x%x\n",
+		 __func__, length, len);
 
 	/*
 	 * Add function to do table lookup of StructureSize by command
@@ -117,12 +118,13 @@ smb2_check_message(char *buf, unsigned int length)
 			 */
 			return 0;
 		} else {
-			cERROR(1, "Length less than SMB header size");
+			cifs_dbg(VFS, "Length less than SMB header size\n");
 		}
 		return 1;
 	}
 	if (len > CIFSMaxBufSize + MAX_SMB2_HDR_SIZE - 4) {
-		cERROR(1, "SMB length greater than maximum, mid=%llu", mid);
+		cifs_dbg(VFS, "SMB length greater than maximum, mid=%llu\n",
+			 mid);
 		return 1;
 	}
 
@@ -130,14 +132,14 @@ smb2_check_message(char *buf, unsigned int length)
 		return 1;
 
 	if (hdr->StructureSize != SMB2_HEADER_STRUCTURE_SIZE) {
-		cERROR(1, "Illegal structure size %u",
-			  le16_to_cpu(hdr->StructureSize));
+		cifs_dbg(VFS, "Illegal structure size %u\n",
+			 le16_to_cpu(hdr->StructureSize));
 		return 1;
 	}
 
 	command = le16_to_cpu(hdr->Command);
 	if (command >= NUMBER_OF_SMB2_COMMANDS) {
-		cERROR(1, "Illegal SMB2 command %d", command);
+		cifs_dbg(VFS, "Illegal SMB2 command %d\n", command);
 		return 1;
 	}
 
@@ -145,30 +147,30 @@ smb2_check_message(char *buf, unsigned int length)
 		if (command != SMB2_OPLOCK_BREAK_HE && (hdr->Status == 0 ||
 		    pdu->StructureSize2 != SMB2_ERROR_STRUCTURE_SIZE2)) {
 			/* error packets have 9 byte structure size */
-			cERROR(1, "Illegal response size %u for command %d",
-				   le16_to_cpu(pdu->StructureSize2), command);
+			cifs_dbg(VFS, "Illegal response size %u for command %d\n",
+				 le16_to_cpu(pdu->StructureSize2), command);
 			return 1;
 		} else if (command == SMB2_OPLOCK_BREAK_HE && (hdr->Status == 0)
 			   && (le16_to_cpu(pdu->StructureSize2) != 44)
 			   && (le16_to_cpu(pdu->StructureSize2) != 36)) {
 			/* special case for SMB2.1 lease break message */
-			cERROR(1, "Illegal response size %d for oplock break",
-				   le16_to_cpu(pdu->StructureSize2));
+			cifs_dbg(VFS, "Illegal response size %d for oplock break\n",
+				 le16_to_cpu(pdu->StructureSize2));
 			return 1;
 		}
 	}
 
 	if (4 + len != length) {
-		cERROR(1, "Total length %u RFC1002 length %u mismatch mid %llu",
-			  length, 4 + len, mid);
+		cifs_dbg(VFS, "Total length %u RFC1002 length %u mismatch mid %llu\n",
+			 length, 4 + len, mid);
 		return 1;
 	}
 
 	clc_len = smb2_calc_size(hdr);
 
 	if (4 + len != clc_len) {
-		cFYI(1, "Calculated size %u length %u mismatch mid %llu",
-			clc_len, 4 + len, mid);
+		cifs_dbg(FYI, "Calculated size %u length %u mismatch mid %llu\n",
+			 clc_len, 4 + len, mid);
 		/* Windows 7 server returns 24 bytes more */
 		if (clc_len + 20 == len && command == SMB2_OPLOCK_BREAK_HE)
 			return 0;
@@ -267,7 +269,7 @@ smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr)
 	case SMB2_CHANGE_NOTIFY:
 	default:
 		/* BB FIXME for unimplemented cases above */
-		cERROR(1, "no length check for command");
+		cifs_dbg(VFS, "no length check for command\n");
 		break;
 	}
 
@@ -276,20 +278,20 @@ smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr)
 	 * we have little choice but to ignore the data area in this case.
 	 */
 	if (*off > 4096) {
-		cERROR(1, "offset %d too large, data area ignored", *off);
+		cifs_dbg(VFS, "offset %d too large, data area ignored\n", *off);
 		*len = 0;
 		*off = 0;
 	} else if (*off < 0) {
-		cERROR(1, "negative offset %d to data invalid ignore data area",
-			  *off);
+		cifs_dbg(VFS, "negative offset %d to data invalid ignore data area\n",
+			 *off);
 		*off = 0;
 		*len = 0;
 	} else if (*len < 0) {
-		cERROR(1, "negative data length %d invalid, data area ignored",
-			  *len);
+		cifs_dbg(VFS, "negative data length %d invalid, data area ignored\n",
+			 *len);
 		*len = 0;
 	} else if (*len > 128 * 1024) {
-		cERROR(1, "data area larger than 128K: %d", *len);
+		cifs_dbg(VFS, "data area larger than 128K: %d\n", *len);
 		*len = 0;
 	}
 
@@ -324,7 +326,7 @@ smb2_calc_size(void *buf)
 		goto calc_size_exit;
 
 	smb2_get_data_area_len(&offset, &data_length, hdr);
-	cFYI(1, "SMB2 data length %d offset %d", data_length, offset);
+	cifs_dbg(FYI, "SMB2 data length %d offset %d\n", data_length, offset);
 
 	if (data_length > 0) {
 		/*
@@ -335,15 +337,15 @@ smb2_calc_size(void *buf)
 		 * the size of the RFC1001 hdr.
 		 */
 		if (offset + 4 + 1 < len) {
-			cERROR(1, "data area offset %d overlaps SMB2 header %d",
-				  offset + 4 + 1, len);
+			cifs_dbg(VFS, "data area offset %d overlaps SMB2 header %d\n",
+				 offset + 4 + 1, len);
 			data_length = 0;
 		} else {
 			len = 4 + offset + data_length;
 		}
 	}
 calc_size_exit:
-	cFYI(1, "SMB2 len %d", len);
+	cifs_dbg(FYI, "SMB2 len %d\n", len);
 	return len;
 }
 
@@ -405,7 +407,7 @@ cifs_ses_oplock_break(struct work_struct *work)
 
 	rc = SMB2_lease_break(0, tlink_tcon(lw->tlink), lw->lease_key,
 			      lw->lease_state);
-	cFYI(1, "Lease release rc %d", rc);
+	cifs_dbg(FYI, "Lease release rc %d\n", rc);
 	cifs_put_tlink(lw->tlink);
 	kfree(lw);
 }
@@ -426,15 +428,13 @@ smb2_is_valid_lease_break(char *buffer, struct TCP_Server_Info *server)
 				  SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED);
 
 	lw = kmalloc(sizeof(struct smb2_lease_break_work), GFP_KERNEL);
-	if (!lw) {
-		cERROR(1, "Memory allocation failed during lease break check");
+	if (!lw)
 		return false;
-	}
 
 	INIT_WORK(&lw->lease_break, cifs_ses_oplock_break);
 	lw->lease_state = rsp->NewLeaseState;
 
-	cFYI(1, "Checking for lease break");
+	cifs_dbg(FYI, "Checking for lease break\n");
 
 	/* look up tcon based on tid & uid */
 	spin_lock(&cifs_tcp_ses_lock);
@@ -455,9 +455,9 @@ smb2_is_valid_lease_break(char *buffer, struct TCP_Server_Info *server)
 					   SMB2_LEASE_KEY_SIZE))
 					continue;
 
-				cFYI(1, "found in the open list");
-				cFYI(1, "lease key match, lease break 0x%d",
-				     le32_to_cpu(rsp->NewLeaseState));
+				cifs_dbg(FYI, "found in the open list\n");
+				cifs_dbg(FYI, "lease key match, lease break 0x%d\n",
+					 le32_to_cpu(rsp->NewLeaseState));
 
 				smb2_set_oplock_level(cinode,
 				  smb2_map_lease_to_oplock(rsp->NewLeaseState));
@@ -489,9 +489,9 @@ smb2_is_valid_lease_break(char *buffer, struct TCP_Server_Info *server)
 						   &lw->lease_break);
 				}
 
-				cFYI(1, "found in the pending open list");
-				cFYI(1, "lease key match, lease break 0x%d",
-				     le32_to_cpu(rsp->NewLeaseState));
+				cifs_dbg(FYI, "found in the pending open list\n");
+				cifs_dbg(FYI, "lease key match, lease break 0x%d\n",
+					 le32_to_cpu(rsp->NewLeaseState));
 
 				open->oplock =
 				  smb2_map_lease_to_oplock(rsp->NewLeaseState);
@@ -506,7 +506,7 @@ smb2_is_valid_lease_break(char *buffer, struct TCP_Server_Info *server)
 	}
 	spin_unlock(&cifs_tcp_ses_lock);
 	kfree(lw);
-	cFYI(1, "Can not process lease break - no lease matched");
+	cifs_dbg(FYI, "Can not process lease break - no lease matched\n");
 	return false;
 }
 
@@ -520,7 +520,7 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
 	struct cifsInodeInfo *cinode;
 	struct cifsFileInfo *cfile;
 
-	cFYI(1, "Checking for oplock break");
+	cifs_dbg(FYI, "Checking for oplock break\n");
 
 	if (rsp->hdr.Command != SMB2_OPLOCK_BREAK)
 		return false;
@@ -533,7 +533,7 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
 			return false;
 	}
 
-	cFYI(1, "oplock level 0x%d", rsp->OplockLevel);
+	cifs_dbg(FYI, "oplock level 0x%d\n", rsp->OplockLevel);
 
 	/* look up tcon based on tid & uid */
 	spin_lock(&cifs_tcp_ses_lock);
@@ -553,7 +553,7 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
 				    cfile->fid.volatile_fid)
 					continue;
 
-				cFYI(1, "file id match, oplock break");
+				cifs_dbg(FYI, "file id match, oplock break\n");
 				cinode = CIFS_I(cfile->dentry->d_inode);
 
 				if (!cinode->clientCanCacheAll &&
@@ -573,11 +573,11 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
 			}
 			spin_unlock(&cifs_file_list_lock);
 			spin_unlock(&cifs_tcp_ses_lock);
-			cFYI(1, "No matching file for oplock break");
+			cifs_dbg(FYI, "No matching file for oplock break\n");
 			return true;
 		}
 	}
 	spin_unlock(&cifs_tcp_ses_lock);
-	cFYI(1, "Can not process oplock break for non-existent connection");
+	cifs_dbg(FYI, "Can not process oplock break for non-existent connection\n");
 	return false;
 }
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index bceffe7..f2e76f3 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -38,13 +38,13 @@ change_conf(struct TCP_Server_Info *server)
 	case 1:
 		server->echoes = false;
 		server->oplocks = false;
-		cERROR(1, "disabling echoes and oplocks");
+		cifs_dbg(VFS, "disabling echoes and oplocks\n");
 		break;
 	case 2:
 		server->echoes = true;
 		server->oplocks = false;
 		server->echo_credits = 1;
-		cFYI(1, "disabling oplocks");
+		cifs_dbg(FYI, "disabling oplocks\n");
 		break;
 	default:
 		server->echoes = true;
@@ -147,10 +147,10 @@ smb2_dump_detail(void *buf)
 #ifdef CONFIG_CIFS_DEBUG2
 	struct smb2_hdr *smb = (struct smb2_hdr *)buf;
 
-	cERROR(1, "Cmd: %d Err: 0x%x Flags: 0x%x Mid: %llu Pid: %d",
-		  smb->Command, smb->Status, smb->Flags, smb->MessageId,
-		  smb->ProcessId);
-	cERROR(1, "smb buf %p len %u", smb, smb2_calc_size(smb));
+	cifs_dbg(VFS, "Cmd: %d Err: 0x%x Flags: 0x%x Mid: %llu Pid: %d\n",
+		 smb->Command, smb->Status, smb->Flags, smb->MessageId,
+		 smb->ProcessId);
+	cifs_dbg(VFS, "smb buf %p len %u\n", smb, smb2_calc_size(smb));
 #endif
 }
 
@@ -436,7 +436,7 @@ smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon,
 		       &oplock, NULL);
 	kfree(utf16_path);
 	if (rc) {
-		cERROR(1, "open dir failed");
+		cifs_dbg(VFS, "open dir failed\n");
 		return rc;
 	}
 
@@ -448,7 +448,7 @@ smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon,
 	rc = SMB2_query_directory(xid, tcon, persistent_fid, volatile_fid, 0,
 				  srch_inf);
 	if (rc) {
-		cERROR(1, "query directory failed");
+		cifs_dbg(VFS, "query directory failed\n");
 		SMB2_close(xid, tcon, persistent_fid, volatile_fid);
 	}
 	return rc;
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index 41d9d07..2b95ce2 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -155,8 +155,8 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon)
 		if ((smb2_command != SMB2_WRITE) &&
 		   (smb2_command != SMB2_CREATE) &&
 		   (smb2_command != SMB2_TREE_DISCONNECT)) {
-			cFYI(1, "can not send cmd %d while umounting",
-				smb2_command);
+			cifs_dbg(FYI, "can not send cmd %d while umounting\n",
+				 smb2_command);
 			return -ENODEV;
 		}
 	}
@@ -200,7 +200,7 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon)
 		 * back on-line
 		 */
 		if (!tcon->retry) {
-			cFYI(1, "gave up waiting on reconnect in smb_init");
+			cifs_dbg(FYI, "gave up waiting on reconnect in smb_init\n");
 			return -EHOSTDOWN;
 		}
 	}
@@ -227,7 +227,7 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon)
 	cifs_mark_open_files_invalid(tcon);
 	rc = SMB2_tcon(0, tcon->ses, tcon->treeName, tcon, nls_codepage);
 	mutex_unlock(&tcon->ses->session_mutex);
-	cFYI(1, "reconnect tcon rc = %d", rc);
+	cifs_dbg(FYI, "reconnect tcon rc = %d\n", rc);
 	if (rc)
 		goto out;
 	atomic_inc(&tconInfoReconnectCount);
@@ -335,7 +335,7 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses)
 	char *security_blob;
 	int flags = CIFS_NEG_OP;
 
-	cFYI(1, "Negotiate protocol");
+	cifs_dbg(FYI, "Negotiate protocol\n");
 
 	if (ses->server)
 		server = ses->server;
@@ -354,7 +354,7 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses)
 	else /* if override flags set only sign/seal OR them with global auth */
 		sec_flags = global_secflags | ses->overrideSecFlg;
 
-	cFYI(1, "sec_flags 0x%x", sec_flags);
+	cifs_dbg(FYI, "sec_flags 0x%x\n", sec_flags);
 
 	req->hdr.SessionId = 0;
 
@@ -389,19 +389,19 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses)
 	if (rc != 0)
 		goto neg_exit;
 
-	cFYI(1, "mode 0x%x", rsp->SecurityMode);
+	cifs_dbg(FYI, "mode 0x%x\n", rsp->SecurityMode);
 
 	/* BB we may eventually want to match the negotiated vs. requested
 	   dialect, even though we are only requesting one at a time */
 	if (rsp->DialectRevision == cpu_to_le16(SMB20_PROT_ID))
-		cFYI(1, "negotiated smb2.0 dialect");
+		cifs_dbg(FYI, "negotiated smb2.0 dialect\n");
 	else if (rsp->DialectRevision == cpu_to_le16(SMB21_PROT_ID))
-		cFYI(1, "negotiated smb2.1 dialect");
+		cifs_dbg(FYI, "negotiated smb2.1 dialect\n");
 	else if (rsp->DialectRevision == cpu_to_le16(SMB30_PROT_ID))
-		cFYI(1, "negotiated smb3.0 dialect");
+		cifs_dbg(FYI, "negotiated smb3.0 dialect\n");
 	else {
-		cERROR(1, "Illegal dialect returned by server %d",
-			   le16_to_cpu(rsp->DialectRevision));
+		cifs_dbg(VFS, "Illegal dialect returned by server %d\n",
+			 le16_to_cpu(rsp->DialectRevision));
 		rc = -EIO;
 		goto neg_exit;
 	}
@@ -419,35 +419,34 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses)
 	security_blob = smb2_get_data_area_len(&blob_offset, &blob_length,
 					       &rsp->hdr);
 	if (blob_length == 0) {
-		cERROR(1, "missing security blob on negprot");
+		cifs_dbg(VFS, "missing security blob on negprot\n");
 		rc = -EIO;
 		goto neg_exit;
 	}
 
-	cFYI(1, "sec_flags 0x%x", sec_flags);
+	cifs_dbg(FYI, "sec_flags 0x%x\n", sec_flags);
 	if ((sec_flags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) {
-		cFYI(1, "Signing required");
+		cifs_dbg(FYI, "Signing required\n");
 		if (!(server->sec_mode & (SMB2_NEGOTIATE_SIGNING_REQUIRED |
 		      SMB2_NEGOTIATE_SIGNING_ENABLED))) {
-			cERROR(1, "signing required but server lacks support");
+			cifs_dbg(VFS, "signing required but server lacks support\n");
 			rc = -EOPNOTSUPP;
 			goto neg_exit;
 		}
 		server->sec_mode |= SECMODE_SIGN_REQUIRED;
 	} else if (sec_flags & CIFSSEC_MAY_SIGN) {
-		cFYI(1, "Signing optional");
+		cifs_dbg(FYI, "Signing optional\n");
 		if (server->sec_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) {
-			cFYI(1, "Server requires signing");
+			cifs_dbg(FYI, "Server requires signing\n");
 			server->sec_mode |= SECMODE_SIGN_REQUIRED;
 		} else {
 			server->sec_mode &=
 				~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
 		}
 	} else {
-		cFYI(1, "Signing disabled");
+		cifs_dbg(FYI, "Signing disabled\n");
 		if (server->sec_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) {
-			cERROR(1, "Server requires packet signing to be enabled"
-				  " in /proc/fs/cifs/SecurityFlags.");
+			cifs_dbg(VFS, "Server requires packet signing to be enabled in /proc/fs/cifs/SecurityFlags\n");
 			rc = -EOPNOTSUPP;
 			goto neg_exit;
 		}
@@ -489,7 +488,7 @@ SMB2_sess_setup(const unsigned int xid, struct cifs_ses *ses,
 	char *ntlmssp_blob = NULL;
 	bool use_spnego = false; /* else use raw ntlmssp */
 
-	cFYI(1, "Session Setup");
+	cifs_dbg(FYI, "Session Setup\n");
 
 	if (ses->server)
 		server = ses->server;
@@ -522,7 +521,7 @@ ssetup_ntlmssp_authenticate:
 	else /* if override flags set only sign/seal OR them with global auth */
 		sec_flags = global_secflags | ses->overrideSecFlg;
 
-	cFYI(1, "sec_flags 0x%x", sec_flags);
+	cifs_dbg(FYI, "sec_flags 0x%x\n", sec_flags);
 
 	req->hdr.SessionId = 0; /* First session, not a reauthenticate */
 	req->VcNumber = 0; /* MBZ */
@@ -558,7 +557,7 @@ ssetup_ntlmssp_authenticate:
 					sizeof(struct _NEGOTIATE_MESSAGE),
 					ntlmssp_blob); */
 			/* BB eventually need to add this */
-			cERROR(1, "spnego not supported for SMB2 yet");
+			cifs_dbg(VFS, "spnego not supported for SMB2 yet\n");
 			rc = -EOPNOTSUPP;
 			kfree(ntlmssp_blob);
 			goto ssetup_exit;
@@ -572,14 +571,14 @@ ssetup_ntlmssp_authenticate:
 		ntlmssp_blob = kzalloc(sizeof(struct _NEGOTIATE_MESSAGE) + 500,
 				       GFP_KERNEL);
 		if (ntlmssp_blob == NULL) {
-			cERROR(1, "failed to malloc ntlmssp blob");
 			rc = -ENOMEM;
 			goto ssetup_exit;
 		}
 		rc = build_ntlmssp_auth_blob(ntlmssp_blob, &blob_length, ses,
 					     nls_cp);
 		if (rc) {
-			cFYI(1, "build_ntlmssp_auth_blob failed %d", rc);
+			cifs_dbg(FYI, "build_ntlmssp_auth_blob failed %d\n",
+				 rc);
 			goto ssetup_exit; /* BB double check error handling */
 		}
 		if (use_spnego) {
@@ -587,7 +586,7 @@ ssetup_ntlmssp_authenticate:
 							&security_blob,
 							blob_length,
 							ntlmssp_blob); */
-			cERROR(1, "spnego not supported for SMB2 yet");
+			cifs_dbg(VFS, "spnego not supported for SMB2 yet\n");
 			rc = -EOPNOTSUPP;
 			kfree(ntlmssp_blob);
 			goto ssetup_exit;
@@ -595,7 +594,7 @@ ssetup_ntlmssp_authenticate:
 			security_blob = ntlmssp_blob;
 		}
 	} else {
-		cERROR(1, "illegal ntlmssp phase");
+		cifs_dbg(VFS, "illegal ntlmssp phase\n");
 		rc = -EIO;
 		goto ssetup_exit;
 	}
@@ -620,13 +619,13 @@ ssetup_ntlmssp_authenticate:
 	if (resp_buftype != CIFS_NO_BUFFER &&
 	    rsp->hdr.Status == STATUS_MORE_PROCESSING_REQUIRED) {
 		if (phase != NtLmNegotiate) {
-			cERROR(1, "Unexpected more processing error");
+			cifs_dbg(VFS, "Unexpected more processing error\n");
 			goto ssetup_exit;
 		}
 		if (offsetof(struct smb2_sess_setup_rsp, Buffer) - 4 !=
 				le16_to_cpu(rsp->SecurityBufferOffset)) {
-			cERROR(1, "Invalid security buffer offset %d",
-				  le16_to_cpu(rsp->SecurityBufferOffset));
+			cifs_dbg(VFS, "Invalid security buffer offset %d\n",
+				 le16_to_cpu(rsp->SecurityBufferOffset));
 			rc = -EIO;
 			goto ssetup_exit;
 		}
@@ -667,7 +666,7 @@ SMB2_logoff(const unsigned int xid, struct cifs_ses *ses)
 	int rc = 0;
 	struct TCP_Server_Info *server;
 
-	cFYI(1, "disconnect session %p", ses);
+	cifs_dbg(FYI, "disconnect session %p\n", ses);
 
 	if (ses && (ses->server))
 		server = ses->server;
@@ -711,7 +710,7 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
 	struct TCP_Server_Info *server;
 	__le16 *unc_path = NULL;
 
-	cFYI(1, "TCON");
+	cifs_dbg(FYI, "TCON\n");
 
 	if ((ses->server) && tree)
 		server = ses->server;
@@ -775,15 +774,15 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
 	}
 
 	if (rsp->ShareType & SMB2_SHARE_TYPE_DISK)
-		cFYI(1, "connection to disk share");
+		cifs_dbg(FYI, "connection to disk share\n");
 	else if (rsp->ShareType & SMB2_SHARE_TYPE_PIPE) {
 		tcon->ipc = true;
-		cFYI(1, "connection to pipe share");
+		cifs_dbg(FYI, "connection to pipe share\n");
 	} else if (rsp->ShareType & SMB2_SHARE_TYPE_PRINT) {
 		tcon->print = true;
-		cFYI(1, "connection to printer");
+		cifs_dbg(FYI, "connection to printer\n");
 	} else {
-		cERROR(1, "unknown share type %d", rsp->ShareType);
+		cifs_dbg(VFS, "unknown share type %d\n", rsp->ShareType);
 		rc = -EOPNOTSUPP;
 		goto tcon_error_exit;
 	}
@@ -797,7 +796,7 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
 
 	if ((rsp->Capabilities & SMB2_SHARE_CAP_DFS) &&
 	    ((tcon->share_flags & SHI1005_FLAGS_DFS) == 0))
-		cERROR(1, "DFS capability contradicts DFS flag");
+		cifs_dbg(VFS, "DFS capability contradicts DFS flag\n");
 
 tcon_exit:
 	free_rsp_buf(resp_buftype, rsp);
@@ -806,7 +805,7 @@ tcon_exit:
 
 tcon_error_exit:
 	if (rsp->hdr.Status == STATUS_BAD_NETWORK_NAME) {
-		cERROR(1, "BAD_NETWORK_NAME: %s", tree);
+		cifs_dbg(VFS, "BAD_NETWORK_NAME: %s\n", tree);
 		tcon->bad_network_name = true;
 	}
 	goto tcon_exit;
@@ -820,7 +819,7 @@ SMB2_tdis(const unsigned int xid, struct cifs_tcon *tcon)
 	struct TCP_Server_Info *server;
 	struct cifs_ses *ses = tcon->ses;
 
-	cFYI(1, "Tree Disconnect");
+	cifs_dbg(FYI, "Tree Disconnect\n");
 
 	if (ses && (ses->server))
 		server = ses->server;
@@ -846,12 +845,10 @@ create_lease_buf(u8 *lease_key, u8 oplock)
 {
 	struct create_lease *buf;
 
-	buf = kmalloc(sizeof(struct create_lease), GFP_KERNEL);
+	buf = kzalloc(sizeof(struct create_lease), GFP_KERNEL);
 	if (!buf)
 		return NULL;
 
-	memset(buf, 0, sizeof(struct create_lease));
-
 	buf->lcontext.LeaseKeyLow = cpu_to_le64(*((u64 *)lease_key));
 	buf->lcontext.LeaseKeyHigh = cpu_to_le64(*((u64 *)(lease_key + 8)));
 	if (oplock == SMB2_OPLOCK_LEVEL_EXCLUSIVE)
@@ -925,7 +922,7 @@ SMB2_open(const unsigned int xid, struct cifs_tcon *tcon, __le16 *path,
 	int rc = 0;
 	int num_iovecs = 2;
 
-	cFYI(1, "create/open");
+	cifs_dbg(FYI, "create/open\n");
 
 	if (ses && (ses->server))
 		server = ses->server;
@@ -1051,7 +1048,7 @@ SMB2_close(const unsigned int xid, struct cifs_tcon *tcon,
 	int resp_buftype;
 	int rc = 0;
 
-	cFYI(1, "Close");
+	cifs_dbg(FYI, "Close\n");
 
 	if (ses && (ses->server))
 		server = ses->server;
@@ -1097,20 +1094,20 @@ validate_buf(unsigned int offset, unsigned int buffer_length,
 
 
 	if (buffer_length < min_buf_size) {
-		cERROR(1, "buffer length %d smaller than minimum size %d",
-			   buffer_length, min_buf_size);
+		cifs_dbg(VFS, "buffer length %d smaller than minimum size %d\n",
+			 buffer_length, min_buf_size);
 		return -EINVAL;
 	}
 
 	/* check if beyond RFC1001 maximum length */
 	if ((smb_len > 0x7FFFFF) || (buffer_length > 0x7FFFFF)) {
-		cERROR(1, "buffer length %d or smb length %d too large",
-			   buffer_length, smb_len);
+		cifs_dbg(VFS, "buffer length %d or smb length %d too large\n",
+			 buffer_length, smb_len);
 		return -EINVAL;
 	}
 
 	if ((begin_of_buf > end_of_smb) || (end_of_buf > end_of_smb)) {
-		cERROR(1, "illegal server response, bad offset to data");
+		cifs_dbg(VFS, "illegal server response, bad offset to data\n");
 		return -EINVAL;
 	}
 
@@ -1155,7 +1152,7 @@ query_info(const unsigned int xid, struct cifs_tcon *tcon,
 	struct TCP_Server_Info *server;
 	struct cifs_ses *ses = tcon->ses;
 
-	cFYI(1, "Query Info");
+	cifs_dbg(FYI, "Query Info\n");
 
 	if (ses && (ses->server))
 		server = ses->server;
@@ -1247,7 +1244,7 @@ SMB2_echo(struct TCP_Server_Info *server)
 	struct smb_rqst rqst = { .rq_iov = &iov,
 				 .rq_nvec = 1 };
 
-	cFYI(1, "In echo request");
+	cifs_dbg(FYI, "In echo request\n");
 
 	rc = small_smb2_init(SMB2_ECHO, NULL, (void **)&req);
 	if (rc)
@@ -1262,7 +1259,7 @@ SMB2_echo(struct TCP_Server_Info *server)
 	rc = cifs_call_async(server, &rqst, NULL, smb2_echo_callback, server,
 			     CIFS_ECHO_OP);
 	if (rc)
-		cFYI(1, "Echo request failed: %d", rc);
+		cifs_dbg(FYI, "Echo request failed: %d\n", rc);
 
 	cifs_small_buf_release(req);
 	return rc;
@@ -1279,7 +1276,7 @@ SMB2_flush(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
 	int resp_buftype;
 	int rc = 0;
 
-	cFYI(1, "Flush");
+	cifs_dbg(FYI, "Flush\n");
 
 	if (ses && (ses->server))
 		server = ses->server;
@@ -1379,8 +1376,9 @@ smb2_readv_callback(struct mid_q_entry *mid)
 				 .rq_pagesz = rdata->pagesz,
 				 .rq_tailsz = rdata->tailsz };
 
-	cFYI(1, "%s: mid=%llu state=%d result=%d bytes=%u", __func__,
-		mid->mid, mid->mid_state, rdata->result, rdata->bytes);
+	cifs_dbg(FYI, "%s: mid=%llu state=%d result=%d bytes=%u\n",
+		 __func__, mid->mid, mid->mid_state, rdata->result,
+		 rdata->bytes);
 
 	switch (mid->mid_state) {
 	case MID_RESPONSE_RECEIVED:
@@ -1392,8 +1390,8 @@ smb2_readv_callback(struct mid_q_entry *mid)
 
 			rc = smb2_verify_signature(&rqst, server);
 			if (rc)
-				cERROR(1, "SMB signature verification returned "
-				       "error = %d", rc);
+				cifs_dbg(VFS, "SMB signature verification returned error = %d\n",
+					 rc);
 		}
 		/* FIXME: should this be counted toward the initiating task? */
 		task_io_account_read(rdata->bytes);
@@ -1426,8 +1424,8 @@ smb2_async_readv(struct cifs_readdata *rdata)
 	struct smb_rqst rqst = { .rq_iov = &rdata->iov,
 				 .rq_nvec = 1 };
 
-	cFYI(1, "%s: offset=%llu bytes=%u", __func__,
-		rdata->offset, rdata->bytes);
+	cifs_dbg(FYI, "%s: offset=%llu bytes=%u\n",
+		 __func__, rdata->offset, rdata->bytes);
 
 	io_parms.tcon = tlink_tcon(rdata->cfile->tlink);
 	io_parms.offset = rdata->offset;
@@ -1481,13 +1479,13 @@ SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms,
 
 	if (rc) {
 		cifs_stats_fail_inc(io_parms->tcon, SMB2_READ_HE);
-		cERROR(1, "Send error in read = %d", rc);
+		cifs_dbg(VFS, "Send error in read = %d\n", rc);
 	} else {
 		*nbytes = le32_to_cpu(rsp->DataLength);
 		if ((*nbytes > CIFS_MAX_MSGSIZE) ||
 		    (*nbytes > io_parms->length)) {
-			cFYI(1, "bad length %d for count %d", *nbytes,
-				io_parms->length);
+			cifs_dbg(FYI, "bad length %d for count %d\n",
+				 *nbytes, io_parms->length);
 			rc = -EIO;
 			*nbytes = 0;
 		}
@@ -1597,7 +1595,8 @@ smb2_async_writev(struct cifs_writedata *wdata)
 	rqst.rq_pagesz = wdata->pagesz;
 	rqst.rq_tailsz = wdata->tailsz;
 
-	cFYI(1, "async write at %llu %u bytes", wdata->offset, wdata->bytes);
+	cifs_dbg(FYI, "async write at %llu %u bytes\n",
+		 wdata->offset, wdata->bytes);
 
 	req->Length = cpu_to_le32(wdata->bytes);
 
@@ -1670,7 +1669,7 @@ SMB2_write(const unsigned int xid, struct cifs_io_parms *io_parms,
 
 	if (rc) {
 		cifs_stats_fail_inc(io_parms->tcon, SMB2_WRITE_HE);
-		cERROR(1, "Send error in write = %d", rc);
+		cifs_dbg(VFS, "Send error in write = %d\n", rc);
 	} else
 		*nbytes = le32_to_cpu(rsp->DataLength);
 
@@ -1696,14 +1695,14 @@ num_entries(char *bufstart, char *end_of_buf, char **lastentry, size_t size)
 					((char *)entryptr + next_offset);
 
 		if ((char *)entryptr + size > end_of_buf) {
-			cERROR(1, "malformed search entry would overflow");
+			cifs_dbg(VFS, "malformed search entry would overflow\n");
 			break;
 		}
 
 		len = le32_to_cpu(entryptr->FileNameLength);
 		if ((char *)entryptr + len + size > end_of_buf) {
-			cERROR(1, "directory entry name would overflow frame "
-				  "end of buf %p", end_of_buf);
+			cifs_dbg(VFS, "directory entry name would overflow frame end of buf %p\n",
+				 end_of_buf);
 			break;
 		}
 
@@ -1759,8 +1758,8 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon,
 		info_buf_size = sizeof(SEARCH_ID_FULL_DIR_INFO) - 1;
 		break;
 	default:
-		cERROR(1, "info level %u isn't supported",
-		       srch_inf->info_level);
+		cifs_dbg(VFS, "info level %u isn't supported\n",
+			 srch_inf->info_level);
 		rc = -EINVAL;
 		goto qdir_exit;
 	}
@@ -1824,15 +1823,15 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon,
 			num_entries(srch_inf->srch_entries_start, end_of_smb,
 				    &srch_inf->last_entry, info_buf_size);
 	srch_inf->index_of_last_entry += srch_inf->entries_in_buffer;
-	cFYI(1, "num entries %d last_index %lld srch start %p srch end %p",
-		srch_inf->entries_in_buffer, srch_inf->index_of_last_entry,
-		srch_inf->srch_entries_start, srch_inf->last_entry);
+	cifs_dbg(FYI, "num entries %d last_index %lld srch start %p srch end %p\n",
+		 srch_inf->entries_in_buffer, srch_inf->index_of_last_entry,
+		 srch_inf->srch_entries_start, srch_inf->last_entry);
 	if (resp_buftype == CIFS_LARGE_BUFFER)
 		srch_inf->smallBuf = false;
 	else if (resp_buftype == CIFS_SMALL_BUFFER)
 		srch_inf->smallBuf = true;
 	else
-		cERROR(1, "illegal search buffer type");
+		cifs_dbg(VFS, "illegal search buffer type\n");
 
 	if (rsp->hdr.Status == STATUS_NO_MORE_FILES)
 		srch_inf->endOfSearch = 1;
@@ -2017,7 +2016,7 @@ SMB2_oplock_break(const unsigned int xid, struct cifs_tcon *tcon,
 	int rc;
 	struct smb2_oplock_break *req = NULL;
 
-	cFYI(1, "SMB2_oplock_break");
+	cifs_dbg(FYI, "SMB2_oplock_break\n");
 	rc = small_smb2_init(SMB2_OPLOCK_BREAK, tcon, (void **) &req);
 
 	if (rc)
@@ -2033,7 +2032,7 @@ SMB2_oplock_break(const unsigned int xid, struct cifs_tcon *tcon,
 
 	if (rc) {
 		cifs_stats_fail_inc(tcon, SMB2_OPLOCK_BREAK_HE);
-		cFYI(1, "Send error in Oplock Break = %d", rc);
+		cifs_dbg(FYI, "Send error in Oplock Break = %d\n", rc);
 	}
 
 	return rc;
@@ -2058,7 +2057,7 @@ build_qfs_info_req(struct kvec *iov, struct cifs_tcon *tcon, int level,
 	int rc;
 	struct smb2_query_info_req *req;
 
-	cFYI(1, "Query FSInfo level %d", level);
+	cifs_dbg(FYI, "Query FSInfo level %d\n", level);
 
 	if ((tcon->ses == NULL) || (tcon->ses->server == NULL))
 		return -EIO;
@@ -2131,7 +2130,7 @@ smb2_lockv(const unsigned int xid, struct cifs_tcon *tcon,
 	int resp_buf_type;
 	unsigned int count;
 
-	cFYI(1, "smb2_lockv num lock %d", num_lock);
+	cifs_dbg(FYI, "smb2_lockv num lock %d\n", num_lock);
 
 	rc = small_smb2_init(SMB2_LOCK, tcon, (void **) &req);
 	if (rc)
@@ -2155,7 +2154,7 @@ smb2_lockv(const unsigned int xid, struct cifs_tcon *tcon,
 	cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
 	rc = SendReceive2(xid, tcon->ses, iov, 2, &resp_buf_type, CIFS_NO_RESP);
 	if (rc) {
-		cFYI(1, "Send error in smb2_lockv = %d", rc);
+		cifs_dbg(FYI, "Send error in smb2_lockv = %d\n", rc);
 		cifs_stats_fail_inc(tcon, SMB2_LOCK_HE);
 	}
 
@@ -2186,7 +2185,7 @@ SMB2_lease_break(const unsigned int xid, struct cifs_tcon *tcon,
 	int rc;
 	struct smb2_lease_ack *req = NULL;
 
-	cFYI(1, "SMB2_lease_break");
+	cifs_dbg(FYI, "SMB2_lease_break\n");
 	rc = small_smb2_init(SMB2_OPLOCK_BREAK, tcon, (void **) &req);
 
 	if (rc)
@@ -2204,7 +2203,7 @@ SMB2_lease_break(const unsigned int xid, struct cifs_tcon *tcon,
 
 	if (rc) {
 		cifs_stats_fail_inc(tcon, SMB2_OPLOCK_BREAK_HE);
-		cFYI(1, "Send error in Lease Break = %d", rc);
+		cifs_dbg(FYI, "Send error in Lease Break = %d\n", rc);
 	}
 
 	return rc;
diff --git a/fs/cifs/smb2transport.c b/fs/cifs/smb2transport.c
index 8dd73e6..01f0ac8 100644
--- a/fs/cifs/smb2transport.c
+++ b/fs/cifs/smb2transport.c
@@ -55,13 +55,13 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
 	rc = crypto_shash_setkey(server->secmech.hmacsha256,
 		server->session_key.response, SMB2_NTLMV2_SESSKEY_SIZE);
 	if (rc) {
-		cERROR(1, "%s: Could not update with response\n", __func__);
+		cifs_dbg(VFS, "%s: Could not update with response\n", __func__);
 		return rc;
 	}
 
 	rc = crypto_shash_init(&server->secmech.sdeschmacsha256->shash);
 	if (rc) {
-		cERROR(1, "%s: Could not init md5\n", __func__);
+		cifs_dbg(VFS, "%s: Could not init md5\n", __func__);
 		return rc;
 	}
 
@@ -69,7 +69,7 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
 		if (iov[i].iov_len == 0)
 			continue;
 		if (iov[i].iov_base == NULL) {
-			cERROR(1, "null iovec entry");
+			cifs_dbg(VFS, "null iovec entry\n");
 			return -EIO;
 		}
 		/*
@@ -90,8 +90,8 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
 				iov[i].iov_base, iov[i].iov_len);
 		}
 		if (rc) {
-			cERROR(1, "%s: Could not update with payload\n",
-							__func__);
+			cifs_dbg(VFS, "%s: Could not update with payload\n",
+				 __func__);
 			return rc;
 		}
 	}
@@ -109,7 +109,7 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
 	rc = crypto_shash_final(&server->secmech.sdeschmacsha256->shash,
 				sigptr);
 	if (rc)
-		cERROR(1, "%s: Could not generate sha256 hash\n", __func__);
+		cifs_dbg(VFS, "%s: Could not generate sha256 hash\n", __func__);
 
 	memcpy(smb2_pdu->Signature, sigptr, SMB2_SIGNATURE_SIZE);
 
@@ -119,7 +119,7 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
 int
 smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
 {
-	cFYI(1, "smb3 signatures not supported yet");
+	cifs_dbg(FYI, "smb3 signatures not supported yet\n");
 	return -EOPNOTSUPP;
 }
 
@@ -163,8 +163,8 @@ smb2_verify_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
 
 	/* Do not need to verify session setups with signature "BSRSPYL " */
 	if (memcmp(smb2_pdu->Signature, "BSRSPYL ", 8) == 0)
-		cFYI(1, "dummy signature received for smb command 0x%x",
-			smb2_pdu->Command);
+		cifs_dbg(FYI, "dummy signature received for smb command 0x%x\n",
+			 smb2_pdu->Command);
 
 	/*
 	 * Save off the origiginal signature so we can modify the smb and check
@@ -205,7 +205,7 @@ smb2_mid_entry_alloc(const struct smb2_hdr *smb_buffer,
 	struct mid_q_entry *temp;
 
 	if (server == NULL) {
-		cERROR(1, "Null TCP session in smb2_mid_entry_alloc");
+		cifs_dbg(VFS, "Null TCP session in smb2_mid_entry_alloc\n");
 		return NULL;
 	}
 
@@ -241,7 +241,7 @@ smb2_get_mid_entry(struct cifs_ses *ses, struct smb2_hdr *buf,
 		return -ENOENT;
 
 	if (ses->server->tcpStatus == CifsNeedReconnect) {
-		cFYI(1, "tcp session dead - return to caller to retry");
+		cifs_dbg(FYI, "tcp session dead - return to caller to retry\n");
 		return -EAGAIN;
 	}
 
@@ -281,8 +281,8 @@ smb2_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,
 
 		rc = smb2_verify_signature(&rqst, server);
 		if (rc)
-			cERROR(1, "SMB signature verification returned error = "
-			       "%d", rc);
+			cifs_dbg(VFS, "SMB signature verification returned error = %d\n",
+				 rc);
 	}
 
 	return map_smb2_to_linux_error(mid->resp_buf, log_error);
diff --git a/fs/cifs/smbencrypt.c b/fs/cifs/smbencrypt.c
index a0a58fb..43eb136 100644
--- a/fs/cifs/smbencrypt.c
+++ b/fs/cifs/smbencrypt.c
@@ -78,7 +78,7 @@ smbhash(unsigned char *out, const unsigned char *in, unsigned char *key)
 	tfm_des = crypto_alloc_blkcipher("ecb(des)", 0, CRYPTO_ALG_ASYNC);
 	if (IS_ERR(tfm_des)) {
 		rc = PTR_ERR(tfm_des);
-		cERROR(1, "could not allocate des crypto API");
+		cifs_dbg(VFS, "could not allocate des crypto API\n");
 		goto smbhash_err;
 	}
 
@@ -91,7 +91,7 @@ smbhash(unsigned char *out, const unsigned char *in, unsigned char *key)
 
 	rc = crypto_blkcipher_encrypt(&desc, &sgout, &sgin, 8);
 	if (rc)
-		cERROR(1, "could not encrypt crypt key rc: %d", rc);
+		cifs_dbg(VFS, "could not encrypt crypt key rc: %d\n", rc);
 
 	crypto_free_blkcipher(tfm_des);
 smbhash_err:
@@ -139,14 +139,14 @@ mdfour(unsigned char *md4_hash, unsigned char *link_str, int link_len)
 	md4 = crypto_alloc_shash("md4", 0, 0);
 	if (IS_ERR(md4)) {
 		rc = PTR_ERR(md4);
-		cERROR(1, "%s: Crypto md4 allocation error %d", __func__, rc);
+		cifs_dbg(VFS, "%s: Crypto md4 allocation error %d\n",
+			 __func__, rc);
 		return rc;
 	}
 	size = sizeof(struct shash_desc) + crypto_shash_descsize(md4);
 	sdescmd4 = kmalloc(size, GFP_KERNEL);
 	if (!sdescmd4) {
 		rc = -ENOMEM;
-		cERROR(1, "%s: Memory allocation failure", __func__);
 		goto mdfour_err;
 	}
 	sdescmd4->shash.tfm = md4;
@@ -154,17 +154,17 @@ mdfour(unsigned char *md4_hash, unsigned char *link_str, int link_len)
 
 	rc = crypto_shash_init(&sdescmd4->shash);
 	if (rc) {
-		cERROR(1, "%s: Could not init md4 shash", __func__);
+		cifs_dbg(VFS, "%s: Could not init md4 shash\n", __func__);
 		goto mdfour_err;
 	}
 	rc = crypto_shash_update(&sdescmd4->shash, link_str, link_len);
 	if (rc) {
-		cERROR(1, "%s: Could not update with link_str", __func__);
+		cifs_dbg(VFS, "%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", __func__);
+		cifs_dbg(VFS, "%s: Could not generate md4 hash\n", __func__);
 
 mdfour_err:
 	crypto_free_shash(md4);
@@ -238,7 +238,8 @@ SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24,
 
 	rc = E_md4hash(passwd, p16, codepage);
 	if (rc) {
-		cFYI(1, "%s Can't generate NT hash, error: %d", __func__, rc);
+		cifs_dbg(FYI, "%s Can't generate NT hash, error: %d\n",
+			 __func__, rc);
 		return rc;
 	}
 	memcpy(p21, p16, 16);
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 1a52868..bfbf470 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -49,7 +49,7 @@ AllocMidQEntry(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server)
 	struct mid_q_entry *temp;
 
 	if (server == NULL) {
-		cERROR(1, "Null TCP session in AllocMidQEntry");
+		cifs_dbg(VFS, "Null TCP session in AllocMidQEntry\n");
 		return NULL;
 	}
 
@@ -61,7 +61,7 @@ AllocMidQEntry(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server)
 		temp->mid = smb_buffer->Mid;	/* always LE */
 		temp->pid = current->pid;
 		temp->command = cpu_to_le16(smb_buffer->Command);
-		cFYI(1, "For smb_command %d", smb_buffer->Command);
+		cifs_dbg(FYI, "For smb_command %d\n", smb_buffer->Command);
 	/*	do_gettimeofday(&temp->when_sent);*/ /* easier to use jiffies */
 		/* when mid allocated can be before when sent */
 		temp->when_alloc = jiffies;
@@ -179,17 +179,11 @@ smb_send_kvec(struct TCP_Server_Info *server, struct kvec *iov, size_t n_vec,
 		 */
 		rc = kernel_sendmsg(ssocket, &smb_msg, &iov[first_vec],
 				    n_vec - first_vec, remaining);
-		if (rc == -ENOSPC || rc == -EAGAIN) {
-			/*
-			 * Catch if a low level driver returns -ENOSPC. This
-			 * WARN_ON will be removed by 3.10 if no one reports
-			 * seeing this.
-			 */
-			WARN_ON_ONCE(rc == -ENOSPC);
+		if (rc == -EAGAIN) {
 			i++;
 			if (i >= 14 || (!server->noblocksnd && (i > 2))) {
-				cERROR(1, "sends on sock %p stuck for 15 "
-					  "seconds", ssocket);
+				cifs_dbg(VFS, "sends on sock %p stuck for 15 seconds\n",
+					 ssocket);
 				rc = -EAGAIN;
 				break;
 			}
@@ -209,14 +203,14 @@ smb_send_kvec(struct TCP_Server_Info *server, struct kvec *iov, size_t n_vec,
 		}
 
 		if (rc > remaining) {
-			cERROR(1, "sent %d requested %d", rc, remaining);
+			cifs_dbg(VFS, "sent %d requested %d\n", rc, remaining);
 			break;
 		}
 
 		if (rc == 0) {
 			/* should never happen, letting socket clear before
 			   retrying is our only obvious option here */
-			cERROR(1, "tcp sent no data");
+			cifs_dbg(VFS, "tcp sent no data\n");
 			msleep(500);
 			continue;
 		}
@@ -291,7 +285,7 @@ smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst)
 	if (ssocket == NULL)
 		return -ENOTSOCK;
 
-	cFYI(1, "Sending smb: smb_len=%u", smb_buf_length);
+	cifs_dbg(FYI, "Sending smb: smb_len=%u\n", smb_buf_length);
 	dump_smb(iov[0].iov_base, iov[0].iov_len);
 
 	/* cork the socket */
@@ -324,8 +318,8 @@ uncork:
 				(char *)&val, sizeof(val));
 
 	if ((total_len > 0) && (total_len != smb_buf_length + 4)) {
-		cFYI(1, "partial send (wanted=%u sent=%zu): terminating "
-			"session", smb_buf_length + 4, total_len);
+		cifs_dbg(FYI, "partial send (wanted=%u sent=%zu): terminating session\n",
+			 smb_buf_length + 4, total_len);
 		/*
 		 * If we have only sent part of an SMB then the next SMB could
 		 * be taken as the remainder of this one. We need to kill the
@@ -335,7 +329,8 @@ uncork:
 	}
 
 	if (rc < 0 && rc != -EINTR)
-		cERROR(1, "Error %d sending data on socket to server", rc);
+		cifs_dbg(VFS, "Error %d sending data on socket to server\n",
+			 rc);
 	else
 		rc = 0;
 
@@ -427,7 +422,7 @@ static int allocate_mid(struct cifs_ses *ses, struct smb_hdr *in_buf,
 	}
 
 	if (ses->server->tcpStatus == CifsNeedReconnect) {
-		cFYI(1, "tcp session dead - return to caller to retry");
+		cifs_dbg(FYI, "tcp session dead - return to caller to retry\n");
 		return -EAGAIN;
 	}
 
@@ -527,6 +522,9 @@ cifs_call_async(struct TCP_Server_Info *server, struct smb_rqst *rqst,
 	rc = smb_send_rqst(server, rqst);
 	cifs_in_send_dec(server);
 	cifs_save_when_sent(mid);
+
+	if (rc < 0)
+		server->sequence_number -= 2;
 	mutex_unlock(&server->srv_mutex);
 
 	if (rc == 0)
@@ -559,7 +557,7 @@ SendReceiveNoRsp(const unsigned int xid, struct cifs_ses *ses,
 	iov[0].iov_len = get_rfc1002_length(in_buf) + 4;
 	flags |= CIFS_NO_RESP;
 	rc = SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags);
-	cFYI(DBG2, "SendRcvNoRsp flags %d rc %d", flags, rc);
+	cifs_dbg(NOISY, "SendRcvNoRsp flags %d rc %d\n", flags, rc);
 
 	return rc;
 }
@@ -569,8 +567,8 @@ cifs_sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server)
 {
 	int rc = 0;
 
-	cFYI(1, "%s: cmd=%d mid=%llu state=%d", __func__,
-	     le16_to_cpu(mid->command), mid->mid, mid->mid_state);
+	cifs_dbg(FYI, "%s: cmd=%d mid=%llu state=%d\n",
+		 __func__, le16_to_cpu(mid->command), mid->mid, mid->mid_state);
 
 	spin_lock(&GlobalMid_Lock);
 	switch (mid->mid_state) {
@@ -588,8 +586,8 @@ cifs_sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server)
 		break;
 	default:
 		list_del_init(&mid->qhead);
-		cERROR(1, "%s: invalid mid state mid=%llu state=%d", __func__,
-		       mid->mid, mid->mid_state);
+		cifs_dbg(VFS, "%s: invalid mid state mid=%llu state=%d\n",
+			 __func__, mid->mid, mid->mid_state);
 		rc = -EIO;
 	}
 	spin_unlock(&GlobalMid_Lock);
@@ -624,10 +622,10 @@ cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,
 		iov.iov_len = len;
 		/* FIXME: add code to kill session */
 		rc = cifs_verify_signature(&rqst, server,
-					   mid->sequence_number + 1);
+					   mid->sequence_number);
 		if (rc)
-			cERROR(1, "SMB signature verification returned error = "
-			       "%d", rc);
+			cifs_dbg(VFS, "SMB signature verification returned error = %d\n",
+				 rc);
 	}
 
 	/* BB special case reconnect tid and uid here? */
@@ -672,7 +670,7 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses,
 
 	if ((ses == NULL) || (ses->server == NULL)) {
 		cifs_small_buf_release(buf);
-		cERROR(1, "Null session");
+		cifs_dbg(VFS, "Null session\n");
 		return -EIO;
 	}
 
@@ -716,6 +714,8 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses,
 	cifs_in_send_dec(ses->server);
 	cifs_save_when_sent(midQ);
 
+	if (rc < 0)
+		ses->server->sequence_number -= 2;
 	mutex_unlock(&ses->server->srv_mutex);
 
 	if (rc < 0) {
@@ -752,7 +752,7 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses,
 
 	if (!midQ->resp_buf || midQ->mid_state != MID_RESPONSE_RECEIVED) {
 		rc = -EIO;
-		cFYI(1, "Bad MID state?");
+		cifs_dbg(FYI, "Bad MID state?\n");
 		goto out;
 	}
 
@@ -788,11 +788,11 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses,
 	struct mid_q_entry *midQ;
 
 	if (ses == NULL) {
-		cERROR(1, "Null smb session");
+		cifs_dbg(VFS, "Null smb session\n");
 		return -EIO;
 	}
 	if (ses->server == NULL) {
-		cERROR(1, "Null tcp session");
+		cifs_dbg(VFS, "Null tcp session\n");
 		return -EIO;
 	}
 
@@ -805,8 +805,8 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses,
 
 	if (be32_to_cpu(in_buf->smb_buf_length) > CIFSMaxBufSize +
 			MAX_CIFS_HDR_SIZE - 4) {
-		cERROR(1, "Illegal length, greater than maximum frame, %d",
-			   be32_to_cpu(in_buf->smb_buf_length));
+		cifs_dbg(VFS, "Illegal length, greater than maximum frame, %d\n",
+			 be32_to_cpu(in_buf->smb_buf_length));
 		return -EIO;
 	}
 
@@ -840,6 +840,10 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses,
 	rc = smb_send(ses->server, in_buf, be32_to_cpu(in_buf->smb_buf_length));
 	cifs_in_send_dec(ses->server);
 	cifs_save_when_sent(midQ);
+
+	if (rc < 0)
+		ses->server->sequence_number -= 2;
+
 	mutex_unlock(&ses->server->srv_mutex);
 
 	if (rc < 0)
@@ -871,7 +875,7 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses,
 	if (!midQ->resp_buf || !out_buf ||
 	    midQ->mid_state != MID_RESPONSE_RECEIVED) {
 		rc = -EIO;
-		cERROR(1, "Bad MID state?");
+		cifs_dbg(VFS, "Bad MID state?\n");
 		goto out;
 	}
 
@@ -921,13 +925,13 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon,
 	struct cifs_ses *ses;
 
 	if (tcon == NULL || tcon->ses == NULL) {
-		cERROR(1, "Null smb session");
+		cifs_dbg(VFS, "Null smb session\n");
 		return -EIO;
 	}
 	ses = tcon->ses;
 
 	if (ses->server == NULL) {
-		cERROR(1, "Null tcp session");
+		cifs_dbg(VFS, "Null tcp session\n");
 		return -EIO;
 	}
 
@@ -940,8 +944,8 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon,
 
 	if (be32_to_cpu(in_buf->smb_buf_length) > CIFSMaxBufSize +
 			MAX_CIFS_HDR_SIZE - 4) {
-		cERROR(1, "Illegal length, greater than maximum frame, %d",
-			   be32_to_cpu(in_buf->smb_buf_length));
+		cifs_dbg(VFS, "Illegal length, greater than maximum frame, %d\n",
+			 be32_to_cpu(in_buf->smb_buf_length));
 		return -EIO;
 	}
 
@@ -973,6 +977,10 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon,
 	rc = smb_send(ses->server, in_buf, be32_to_cpu(in_buf->smb_buf_length));
 	cifs_in_send_dec(ses->server);
 	cifs_save_when_sent(midQ);
+
+	if (rc < 0)
+		ses->server->sequence_number -= 2;
+
 	mutex_unlock(&ses->server->srv_mutex);
 
 	if (rc < 0) {
@@ -1038,7 +1046,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon,
 	/* rcvd frame is ok */
 	if (out_buf == NULL || midQ->mid_state != MID_RESPONSE_RECEIVED) {
 		rc = -EIO;
-		cERROR(1, "Bad MID state?");
+		cifs_dbg(VFS, "Bad MID state?\n");
 		goto out;
 	}
 
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c
index 5142f2c..09afda4 100644
--- a/fs/cifs/xattr.c
+++ b/fs/cifs/xattr.c
@@ -68,12 +68,12 @@ int cifs_removexattr(struct dentry *direntry, const char *ea_name)
 		goto remove_ea_exit;
 	}
 	if (ea_name == NULL) {
-		cFYI(1, "Null xattr names not supported");
+		cifs_dbg(FYI, "Null xattr names not supported\n");
 	} else if (strncmp(ea_name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)
 		&& (strncmp(ea_name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN))) {
-		cFYI(1,
-		     "illegal xattr request %s (only user namespace supported)",
-		     ea_name);
+		cifs_dbg(FYI,
+			 "illegal xattr request %s (only user namespace supported)\n",
+			 ea_name);
 		/* BB what if no namespace prefix? */
 		/* Should we just pass them to server, except for
 		system and perhaps security prefixes? */
@@ -134,19 +134,19 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name,
 		search server for EAs or streams to
 		returns as xattrs */
 	if (value_size > MAX_EA_VALUE_SIZE) {
-		cFYI(1, "size of EA value too large");
+		cifs_dbg(FYI, "size of EA value too large\n");
 		rc = -EOPNOTSUPP;
 		goto set_ea_exit;
 	}
 
 	if (ea_name == NULL) {
-		cFYI(1, "Null xattr names not supported");
+		cifs_dbg(FYI, "Null xattr names not supported\n");
 	} else if (strncmp(ea_name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)
 		   == 0) {
 		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
 			goto set_ea_exit;
 		if (strncmp(ea_name, CIFS_XATTR_DOS_ATTRIB, 14) == 0)
-			cFYI(1, "attempt to set cifs inode metadata");
+			cifs_dbg(FYI, "attempt to set cifs inode metadata\n");
 
 		ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */
 		rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, ea_value,
@@ -167,8 +167,6 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name,
 		struct cifs_ntsd *pacl;
 		pacl = kmalloc(value_size, GFP_KERNEL);
 		if (!pacl) {
-			cFYI(1, "%s: Can't allocate memory for ACL",
-					__func__);
 			rc = -ENOMEM;
 		} else {
 			memcpy(pacl, ea_value, value_size);
@@ -179,7 +177,7 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name,
 			kfree(pacl);
 		}
 #else
-			cFYI(1, "Set CIFS ACL not supported yet");
+		cifs_dbg(FYI, "Set CIFS ACL not supported yet\n");
 #endif /* CONFIG_CIFS_ACL */
 	} else {
 		int temp;
@@ -193,9 +191,9 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name,
 					ACL_TYPE_ACCESS, cifs_sb->local_nls,
 					cifs_sb->mnt_cifs_flags &
 						CIFS_MOUNT_MAP_SPECIAL_CHR);
-			cFYI(1, "set POSIX ACL rc %d", rc);
+			cifs_dbg(FYI, "set POSIX ACL rc %d\n", rc);
 #else
-			cFYI(1, "set POSIX ACL not supported");
+			cifs_dbg(FYI, "set POSIX ACL not supported\n");
 #endif
 		} else if (strncmp(ea_name, POSIX_ACL_XATTR_DEFAULT,
 				   strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) {
@@ -206,13 +204,13 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name,
 					ACL_TYPE_DEFAULT, cifs_sb->local_nls,
 					cifs_sb->mnt_cifs_flags &
 						CIFS_MOUNT_MAP_SPECIAL_CHR);
-			cFYI(1, "set POSIX default ACL rc %d", rc);
+			cifs_dbg(FYI, "set POSIX default ACL rc %d\n", rc);
 #else
-			cFYI(1, "set default POSIX ACL not supported");
+			cifs_dbg(FYI, "set default POSIX ACL not supported\n");
 #endif
 		} else {
-			cFYI(1, "illegal xattr request %s (only user namespace"
-				" supported)", ea_name);
+			cifs_dbg(FYI, "illegal xattr request %s (only user namespace supported)\n",
+				 ea_name);
 		  /* BB what if no namespace prefix? */
 		  /* Should we just pass them to server, except for
 		  system and perhaps security prefixes? */
@@ -263,14 +261,14 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name,
 	/* return dos attributes as pseudo xattr */
 	/* return alt name if available as pseudo attr */
 	if (ea_name == NULL) {
-		cFYI(1, "Null xattr names not supported");
+		cifs_dbg(FYI, "Null xattr names not supported\n");
 	} else if (strncmp(ea_name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)
 		   == 0) {
 		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
 			goto get_ea_exit;
 
 		if (strncmp(ea_name, CIFS_XATTR_DOS_ATTRIB, 14) == 0) {
-			cFYI(1, "attempt to query cifs inode metadata");
+			cifs_dbg(FYI, "attempt to query cifs inode metadata\n");
 			/* revalidate/getattr then populate from inode */
 		} /* BB add else when above is implemented */
 		ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */
@@ -295,7 +293,7 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name,
 				cifs_sb->mnt_cifs_flags &
 					CIFS_MOUNT_MAP_SPECIAL_CHR);
 #else
-		cFYI(1, "Query POSIX ACL not supported yet");
+		cifs_dbg(FYI, "Query POSIX ACL not supported yet\n");
 #endif /* CONFIG_CIFS_POSIX */
 	} else if (strncmp(ea_name, POSIX_ACL_XATTR_DEFAULT,
 			  strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) {
@@ -307,7 +305,7 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name,
 				cifs_sb->mnt_cifs_flags &
 					CIFS_MOUNT_MAP_SPECIAL_CHR);
 #else
-		cFYI(1, "Query POSIX default ACL not supported yet");
+		cifs_dbg(FYI, "Query POSIX default ACL not supported yet\n");
 #endif /* CONFIG_CIFS_POSIX */
 	} else if (strncmp(ea_name, CIFS_XATTR_CIFS_ACL,
 				strlen(CIFS_XATTR_CIFS_ACL)) == 0) {
@@ -319,8 +317,8 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name,
 						full_path, &acllen);
 			if (IS_ERR(pacl)) {
 				rc = PTR_ERR(pacl);
-				cERROR(1, "%s: error %zd getting sec desc",
-						__func__, rc);
+				cifs_dbg(VFS, "%s: error %zd getting sec desc\n",
+					 __func__, rc);
 			} else {
 				if (ea_value) {
 					if (acllen > buf_size)
@@ -332,18 +330,18 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name,
 				kfree(pacl);
 			}
 #else
-		cFYI(1, "Query CIFS ACL not supported yet");
+			cifs_dbg(FYI, "Query CIFS ACL not supported yet\n");
 #endif /* CONFIG_CIFS_ACL */
 	} else if (strncmp(ea_name,
 		  XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) == 0) {
-		cFYI(1, "Trusted xattr namespace not supported yet");
+		cifs_dbg(FYI, "Trusted xattr namespace not supported yet\n");
 	} else if (strncmp(ea_name,
 		  XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) == 0) {
-		cFYI(1, "Security xattr namespace not supported yet");
+		cifs_dbg(FYI, "Security xattr namespace not supported yet\n");
 	} else
-		cFYI(1,
-		    "illegal xattr request %s (only user namespace supported)",
-		     ea_name);
+		cifs_dbg(FYI,
+			 "illegal xattr request %s (only user namespace supported)\n",
+			 ea_name);
 
 	/* We could add an additional check for streams ie
 	    if proc/fs/cifs/streamstoxattr is set then
diff --git a/fs/coda/file.c b/fs/coda/file.c
index fa4c100..380b798 100644
--- a/fs/coda/file.c
+++ b/fs/coda/file.c
@@ -79,6 +79,7 @@ coda_file_write(struct file *coda_file, const char __user *buf, size_t count, lo
 		return -EINVAL;
 
 	host_inode = file_inode(host_file);
+	file_start_write(host_file);
 	mutex_lock(&coda_inode->i_mutex);
 
 	ret = host_file->f_op->write(host_file, buf, count, ppos);
@@ -87,6 +88,7 @@ coda_file_write(struct file *coda_file, const char __user *buf, size_t count, lo
 	coda_inode->i_blocks = (coda_inode->i_size + 511) >> 9;
 	coda_inode->i_mtime = coda_inode->i_ctime = CURRENT_TIME_SEC;
 	mutex_unlock(&coda_inode->i_mutex);
+	file_end_write(host_file);
 
 	return ret;
 }
diff --git a/fs/compat.c b/fs/compat.c
index d487985..d172b71 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -44,10 +44,10 @@
 #include <linux/signal.h>
 #include <linux/poll.h>
 #include <linux/mm.h>
-#include <linux/eventpoll.h>
 #include <linux/fs_struct.h>
 #include <linux/slab.h>
 #include <linux/pagemap.h>
+#include <linux/aio.h>
 
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
@@ -1069,210 +1069,6 @@ asmlinkage long compat_sys_getdents64(unsigned int fd,
 }
 #endif /* ! __ARCH_OMIT_COMPAT_SYS_GETDENTS64 */
 
-static ssize_t compat_do_readv_writev(int type, struct file *file,
-			       const struct compat_iovec __user *uvector,
-			       unsigned long nr_segs, loff_t *pos)
-{
-	compat_ssize_t tot_len;
-	struct iovec iovstack[UIO_FASTIOV];
-	struct iovec *iov = iovstack;
-	ssize_t ret;
-	io_fn_t fn;
-	iov_fn_t fnv;
-
-	ret = -EINVAL;
-	if (!file->f_op)
-		goto out;
-
-	ret = compat_rw_copy_check_uvector(type, uvector, nr_segs,
-					       UIO_FASTIOV, iovstack, &iov);
-	if (ret <= 0)
-		goto out;
-
-	tot_len = ret;
-	ret = rw_verify_area(type, file, pos, tot_len);
-	if (ret < 0)
-		goto out;
-
-	fnv = NULL;
-	if (type == READ) {
-		fn = file->f_op->read;
-		fnv = file->f_op->aio_read;
-	} else {
-		fn = (io_fn_t)file->f_op->write;
-		fnv = file->f_op->aio_write;
-	}
-
-	if (fnv)
-		ret = do_sync_readv_writev(file, iov, nr_segs, tot_len,
-						pos, fnv);
-	else
-		ret = do_loop_readv_writev(file, iov, nr_segs, pos, fn);
-
-out:
-	if (iov != iovstack)
-		kfree(iov);
-	if ((ret + (type == READ)) > 0) {
-		if (type == READ)
-			fsnotify_access(file);
-		else
-			fsnotify_modify(file);
-	}
-	return ret;
-}
-
-static size_t compat_readv(struct file *file,
-			   const struct compat_iovec __user *vec,
-			   unsigned long vlen, loff_t *pos)
-{
-	ssize_t ret = -EBADF;
-
-	if (!(file->f_mode & FMODE_READ))
-		goto out;
-
-	ret = -EINVAL;
-	if (!file->f_op || (!file->f_op->aio_read && !file->f_op->read))
-		goto out;
-
-	ret = compat_do_readv_writev(READ, file, vec, vlen, pos);
-
-out:
-	if (ret > 0)
-		add_rchar(current, ret);
-	inc_syscr(current);
-	return ret;
-}
-
-asmlinkage ssize_t
-compat_sys_readv(unsigned long fd, const struct compat_iovec __user *vec,
-		 unsigned long vlen)
-{
-	struct fd f = fdget(fd);
-	ssize_t ret;
-	loff_t pos;
-
-	if (!f.file)
-		return -EBADF;
-	pos = f.file->f_pos;
-	ret = compat_readv(f.file, vec, vlen, &pos);
-	f.file->f_pos = pos;
-	fdput(f);
-	return ret;
-}
-
-asmlinkage ssize_t
-compat_sys_preadv64(unsigned long fd, const struct compat_iovec __user *vec,
-		    unsigned long vlen, loff_t pos)
-{
-	struct fd f;
-	ssize_t ret;
-
-	if (pos < 0)
-		return -EINVAL;
-	f = fdget(fd);
-	if (!f.file)
-		return -EBADF;
-	ret = -ESPIPE;
-	if (f.file->f_mode & FMODE_PREAD)
-		ret = compat_readv(f.file, vec, vlen, &pos);
-	fdput(f);
-	return ret;
-}
-
-asmlinkage ssize_t
-compat_sys_preadv(unsigned long fd, const struct compat_iovec __user *vec,
-		  unsigned long vlen, u32 pos_low, u32 pos_high)
-{
-	loff_t pos = ((loff_t)pos_high << 32) | pos_low;
-	return compat_sys_preadv64(fd, vec, vlen, pos);
-}
-
-static size_t compat_writev(struct file *file,
-			    const struct compat_iovec __user *vec,
-			    unsigned long vlen, loff_t *pos)
-{
-	ssize_t ret = -EBADF;
-
-	if (!(file->f_mode & FMODE_WRITE))
-		goto out;
-
-	ret = -EINVAL;
-	if (!file->f_op || (!file->f_op->aio_write && !file->f_op->write))
-		goto out;
-
-	ret = compat_do_readv_writev(WRITE, file, vec, vlen, pos);
-
-out:
-	if (ret > 0)
-		add_wchar(current, ret);
-	inc_syscw(current);
-	return ret;
-}
-
-asmlinkage ssize_t
-compat_sys_writev(unsigned long fd, const struct compat_iovec __user *vec,
-		  unsigned long vlen)
-{
-	struct fd f = fdget(fd);
-	ssize_t ret;
-	loff_t pos;
-
-	if (!f.file)
-		return -EBADF;
-	pos = f.file->f_pos;
-	ret = compat_writev(f.file, vec, vlen, &pos);
-	f.file->f_pos = pos;
-	fdput(f);
-	return ret;
-}
-
-asmlinkage ssize_t
-compat_sys_pwritev64(unsigned long fd, const struct compat_iovec __user *vec,
-		     unsigned long vlen, loff_t pos)
-{
-	struct fd f;
-	ssize_t ret;
-
-	if (pos < 0)
-		return -EINVAL;
-	f = fdget(fd);
-	if (!f.file)
-		return -EBADF;
-	ret = -ESPIPE;
-	if (f.file->f_mode & FMODE_PWRITE)
-		ret = compat_writev(f.file, vec, vlen, &pos);
-	fdput(f);
-	return ret;
-}
-
-asmlinkage ssize_t
-compat_sys_pwritev(unsigned long fd, const struct compat_iovec __user *vec,
-		   unsigned long vlen, u32 pos_low, u32 pos_high)
-{
-	loff_t pos = ((loff_t)pos_high << 32) | pos_low;
-	return compat_sys_pwritev64(fd, vec, vlen, pos);
-}
-
-asmlinkage long
-compat_sys_vmsplice(int fd, const struct compat_iovec __user *iov32,
-		    unsigned int nr_segs, unsigned int flags)
-{
-	unsigned i;
-	struct iovec __user *iov;
-	if (nr_segs > UIO_MAXIOV)
-		return -EINVAL;
-	iov = compat_alloc_user_space(nr_segs * sizeof(struct iovec));
-	for (i = 0; i < nr_segs; i++) {
-		struct compat_iovec v;
-		if (get_user(v.iov_base, &iov32[i].iov_base) ||
-		    get_user(v.iov_len, &iov32[i].iov_len) ||
-		    put_user(compat_ptr(v.iov_base), &iov[i].iov_base) ||
-		    put_user(v.iov_len, &iov[i].iov_len))
-			return -EFAULT;
-	}
-	return sys_vmsplice(fd, iov, nr_segs, flags);
-}
-
 /*
  * Exactly like fs/open.c:sys_open(), except that it doesn't set the
  * O_LARGEFILE flag.
@@ -1658,84 +1454,6 @@ asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds,
 	return ret;
 }
 
-#ifdef CONFIG_EPOLL
-
-asmlinkage long compat_sys_epoll_pwait(int epfd,
-			struct compat_epoll_event __user *events,
-			int maxevents, int timeout,
-			const compat_sigset_t __user *sigmask,
-			compat_size_t sigsetsize)
-{
-	long err;
-	compat_sigset_t csigmask;
-	sigset_t ksigmask, sigsaved;
-
-	/*
-	 * If the caller wants a certain signal mask to be set during the wait,
-	 * we apply it here.
-	 */
-	if (sigmask) {
-		if (sigsetsize != sizeof(compat_sigset_t))
-			return -EINVAL;
-		if (copy_from_user(&csigmask, sigmask, sizeof(csigmask)))
-			return -EFAULT;
-		sigset_from_compat(&ksigmask, &csigmask);
-		sigdelsetmask(&ksigmask, sigmask(SIGKILL) | sigmask(SIGSTOP));
-		sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
-	}
-
-	err = sys_epoll_wait(epfd, events, maxevents, timeout);
-
-	/*
-	 * If we changed the signal mask, we need to restore the original one.
-	 * In case we've got a signal while waiting, we do not restore the
-	 * signal mask yet, and we allow do_signal() to deliver the signal on
-	 * the way back to userspace, before the signal mask is restored.
-	 */
-	if (sigmask) {
-		if (err == -EINTR) {
-			memcpy(&current->saved_sigmask, &sigsaved,
-			       sizeof(sigsaved));
-			set_restore_sigmask();
-		} else
-			sigprocmask(SIG_SETMASK, &sigsaved, NULL);
-	}
-
-	return err;
-}
-
-#endif /* CONFIG_EPOLL */
-
-#ifdef CONFIG_SIGNALFD
-
-asmlinkage long compat_sys_signalfd4(int ufd,
-				     const compat_sigset_t __user *sigmask,
-				     compat_size_t sigsetsize, int flags)
-{
-	compat_sigset_t ss32;
-	sigset_t tmp;
-	sigset_t __user *ksigmask;
-
-	if (sigsetsize != sizeof(compat_sigset_t))
-		return -EINVAL;
-	if (copy_from_user(&ss32, sigmask, sizeof(ss32)))
-		return -EFAULT;
-	sigset_from_compat(&tmp, &ss32);
-	ksigmask = compat_alloc_user_space(sizeof(sigset_t));
-	if (copy_to_user(ksigmask, &tmp, sizeof(sigset_t)))
-		return -EFAULT;
-
-	return sys_signalfd4(ufd, ksigmask, sizeof(sigset_t), flags);
-}
-
-asmlinkage long compat_sys_signalfd(int ufd,
-				    const compat_sigset_t __user *sigmask,
-				    compat_size_t sigsetsize)
-{
-	return compat_sys_signalfd4(ufd, sigmask, sigsetsize, 0);
-}
-#endif /* CONFIG_SIGNALFD */
-
 #ifdef CONFIG_FHANDLE
 /*
  * Exactly like fs/open.c:sys_open_by_handle_at(), except that it
@@ -1747,25 +1465,3 @@ COMPAT_SYSCALL_DEFINE3(open_by_handle_at, int, mountdirfd,
 	return do_handle_open(mountdirfd, handle, flags);
 }
 #endif
-
-#ifdef __ARCH_WANT_COMPAT_SYS_SENDFILE
-asmlinkage long compat_sys_sendfile(int out_fd, int in_fd,
-				    compat_off_t __user *offset, compat_size_t count)
-{
-	loff_t pos;
-	off_t off;
-	ssize_t ret;
-
-	if (offset) {
-		if (unlikely(get_user(off, offset)))
-			return -EFAULT;
-		pos = off;
-		ret = do_sendfile(out_fd, in_fd, &pos, count, MAX_NON_LFS);
-		if (unlikely(put_user(pos, offset)))
-			return -EFAULT;
-		return ret;
-	}
-
-	return do_sendfile(out_fd, in_fd, NULL, count, 0);
-}
-#endif /* __ARCH_WANT_COMPAT_SYS_SENDFILE */
diff --git a/fs/coredump.c b/fs/coredump.c
index c647965..1355e6e 100644
--- a/fs/coredump.c
+++ b/fs/coredump.c
@@ -263,7 +263,6 @@ static int zap_process(struct task_struct *start, int exit_code)
 	struct task_struct *t;
 	int nr = 0;
 
-	start->signal->flags = SIGNAL_GROUP_EXIT;
 	start->signal->group_exit_code = exit_code;
 	start->signal->group_stop_count = 0;
 
@@ -280,8 +279,8 @@ static int zap_process(struct task_struct *start, int exit_code)
 	return nr;
 }
 
-static inline int zap_threads(struct task_struct *tsk, struct mm_struct *mm,
-				struct core_state *core_state, int exit_code)
+static int zap_threads(struct task_struct *tsk, struct mm_struct *mm,
+			struct core_state *core_state, int exit_code)
 {
 	struct task_struct *g, *p;
 	unsigned long flags;
@@ -291,11 +290,16 @@ static inline int zap_threads(struct task_struct *tsk, struct mm_struct *mm,
 	if (!signal_group_exit(tsk->signal)) {
 		mm->core_state = core_state;
 		nr = zap_process(tsk, exit_code);
+		tsk->signal->group_exit_task = tsk;
+		/* ignore all signals except SIGKILL, see prepare_signal() */
+		tsk->signal->flags = SIGNAL_GROUP_COREDUMP;
+		clear_tsk_thread_flag(tsk, TIF_SIGPENDING);
 	}
 	spin_unlock_irq(&tsk->sighand->siglock);
 	if (unlikely(nr < 0))
 		return nr;
 
+	tsk->flags = PF_DUMPCORE;
 	if (atomic_read(&mm->mm_users) == nr + 1)
 		goto done;
 	/*
@@ -340,6 +344,7 @@ static inline int zap_threads(struct task_struct *tsk, struct mm_struct *mm,
 				if (unlikely(p->mm == mm)) {
 					lock_task_sighand(p, &flags);
 					nr += zap_process(p, exit_code);
+					p->signal->flags = SIGNAL_GROUP_EXIT;
 					unlock_task_sighand(p, &flags);
 				}
 				break;
@@ -386,11 +391,18 @@ static int coredump_wait(int exit_code, struct core_state *core_state)
 	return core_waiters;
 }
 
-static void coredump_finish(struct mm_struct *mm)
+static void coredump_finish(struct mm_struct *mm, bool core_dumped)
 {
 	struct core_thread *curr, *next;
 	struct task_struct *task;
 
+	spin_lock_irq(&current->sighand->siglock);
+	if (core_dumped && !__fatal_signal_pending(current))
+		current->signal->group_exit_code |= 0x80;
+	current->signal->group_exit_task = NULL;
+	current->signal->flags = SIGNAL_GROUP_EXIT;
+	spin_unlock_irq(&current->sighand->siglock);
+
 	next = mm->core_state->dumper.next;
 	while ((curr = next) != NULL) {
 		next = curr->next;
@@ -407,26 +419,38 @@ static void coredump_finish(struct mm_struct *mm)
 	mm->core_state = NULL;
 }
 
-static void wait_for_dump_helpers(struct file *file)
+static bool dump_interrupted(void)
 {
-	struct pipe_inode_info *pipe;
+	/*
+	 * SIGKILL or freezing() interrupt the coredumping. Perhaps we
+	 * can do try_to_freeze() and check __fatal_signal_pending(),
+	 * but then we need to teach dump_write() to restart and clear
+	 * TIF_SIGPENDING.
+	 */
+	return signal_pending(current);
+}
 
-	pipe = file_inode(file)->i_pipe;
+static void wait_for_dump_helpers(struct file *file)
+{
+	struct pipe_inode_info *pipe = file->private_data;
 
 	pipe_lock(pipe);
 	pipe->readers++;
 	pipe->writers--;
+	wake_up_interruptible_sync(&pipe->wait);
+	kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
+	pipe_unlock(pipe);
 
-	while ((pipe->readers > 1) && (!signal_pending(current))) {
-		wake_up_interruptible_sync(&pipe->wait);
-		kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
-		pipe_wait(pipe);
-	}
+	/*
+	 * We actually want wait_event_freezable() but then we need
+	 * to clear TIF_SIGPENDING and improve dump_interrupted().
+	 */
+	wait_event_interruptible(pipe->wait, pipe->readers == 1);
 
+	pipe_lock(pipe);
 	pipe->readers--;
 	pipe->writers++;
 	pipe_unlock(pipe);
-
 }
 
 /*
@@ -471,6 +495,7 @@ void do_coredump(siginfo_t *siginfo)
 	int ispipe;
 	struct files_struct *displaced;
 	bool need_nonrelative = false;
+	bool core_dumped = false;
 	static atomic_t core_dump_count = ATOMIC_INIT(0);
 	struct coredump_params cprm = {
 		.siginfo = siginfo,
@@ -514,17 +539,12 @@ void do_coredump(siginfo_t *siginfo)
 
 	old_cred = override_creds(cred);
 
-	/*
-	 * Clear any false indication of pending signals that might
-	 * be seen by the filesystem code called to write the core file.
-	 */
-	clear_thread_flag(TIF_SIGPENDING);
-
 	ispipe = format_corename(&cn, &cprm);
 
- 	if (ispipe) {
+	if (ispipe) {
 		int dump_count;
 		char **helper_argv;
+		struct subprocess_info *sub_info;
 
 		if (ispipe < 0) {
 			printk(KERN_WARNING "format_corename failed\n");
@@ -571,15 +591,20 @@ void do_coredump(siginfo_t *siginfo)
 			goto fail_dropcount;
 		}
 
-		retval = call_usermodehelper_fns(helper_argv[0], helper_argv,
-					NULL, UMH_WAIT_EXEC, umh_pipe_setup,
-					NULL, &cprm);
+		retval = -ENOMEM;
+		sub_info = call_usermodehelper_setup(helper_argv[0],
+						helper_argv, NULL, GFP_KERNEL,
+						umh_pipe_setup, NULL, &cprm);
+		if (sub_info)
+			retval = call_usermodehelper_exec(sub_info,
+							  UMH_WAIT_EXEC);
+
 		argv_free(helper_argv);
 		if (retval) {
- 			printk(KERN_INFO "Core dump to %s pipe failed\n",
+			printk(KERN_INFO "Core dump to %s pipe failed\n",
 			       cn.corename);
 			goto close_fail;
- 		}
+		}
 	} else {
 		struct inode *inode;
 
@@ -629,9 +654,10 @@ void do_coredump(siginfo_t *siginfo)
 		goto close_fail;
 	if (displaced)
 		put_files_struct(displaced);
-	retval = binfmt->core_dump(&cprm);
-	if (retval)
-		current->signal->group_exit_code |= 0x80;
+
+	file_start_write(cprm.file);
+	core_dumped = !dump_interrupted() && binfmt->core_dump(&cprm);
+	file_end_write(cprm.file);
 
 	if (ispipe && core_pipe_limit)
 		wait_for_dump_helpers(cprm.file);
@@ -644,7 +670,7 @@ fail_dropcount:
 fail_unlock:
 	kfree(cn.corename);
 fail_corename:
-	coredump_finish(mm);
+	coredump_finish(mm, core_dumped);
 	revert_creds(old_cred);
 fail_creds:
 	put_cred(cred);
@@ -659,7 +685,9 @@ fail:
  */
 int dump_write(struct file *file, const void *addr, int nr)
 {
-	return access_ok(VERIFY_READ, addr, nr) && file->f_op->write(file, addr, nr, &file->f_pos) == nr;
+	return !dump_interrupted() &&
+		access_ok(VERIFY_READ, addr, nr) &&
+		file->f_op->write(file, addr, nr, &file->f_pos) == nr;
 }
 EXPORT_SYMBOL(dump_write);
 
@@ -668,7 +696,8 @@ int dump_seek(struct file *file, loff_t off)
 	int ret = 1;
 
 	if (file->f_op->llseek && file->f_op->llseek != no_llseek) {
-		if (file->f_op->llseek(file, off, SEEK_CUR) < 0)
+		if (dump_interrupted() ||
+		    file->f_op->llseek(file, off, SEEK_CUR) < 0)
 			return 0;
 	} else {
 		char *buf = (char *)get_zeroed_page(GFP_KERNEL);
diff --git a/fs/dcookies.c b/fs/dcookies.c
index 17c7799..ab5954b 100644
--- a/fs/dcookies.c
+++ b/fs/dcookies.c
@@ -25,6 +25,7 @@
 #include <linux/dcookies.h>
 #include <linux/mutex.h>
 #include <linux/path.h>
+#include <linux/compat.h>
 #include <asm/uaccess.h>
 
 /* The dcookies are allocated from a kmem_cache and
@@ -145,7 +146,7 @@ out:
 /* And here is where the userspace process can look up the cookie value
  * to retrieve the path.
  */
-SYSCALL_DEFINE(lookup_dcookie)(u64 cookie64, char __user * buf, size_t len)
+SYSCALL_DEFINE3(lookup_dcookie, u64, cookie64, char __user *, buf, size_t, len)
 {
 	unsigned long cookie = (unsigned long)cookie64;
 	int err = -EINVAL;
@@ -201,12 +202,16 @@ out:
 	mutex_unlock(&dcookie_mutex);
 	return err;
 }
-#ifdef CONFIG_HAVE_SYSCALL_WRAPPERS
-asmlinkage long SyS_lookup_dcookie(u64 cookie64, long buf, long len)
+
+#ifdef CONFIG_COMPAT
+COMPAT_SYSCALL_DEFINE4(lookup_dcookie, u32, w0, u32, w1, char __user *, buf, size_t, len)
 {
-	return SYSC_lookup_dcookie(cookie64, (char __user *) buf, (size_t) len);
+#ifdef __BIG_ENDIAN
+	return sys_lookup_dcookie(((u64)w0 << 32) | w1, buf, len);
+#else
+	return sys_lookup_dcookie(((u64)w1 << 32) | w0, buf, len);
+#endif
 }
-SYSCALL_ALIAS(sys_lookup_dcookie, SyS_lookup_dcookie);
 #endif
 
 static int dcookie_init(void)
diff --git a/fs/direct-io.c b/fs/direct-io.c
index f853263..ff53e4a 100644
--- a/fs/direct-io.c
+++ b/fs/direct-io.c
@@ -37,6 +37,7 @@
 #include <linux/uio.h>
 #include <linux/atomic.h>
 #include <linux/prefetch.h>
+#include <linux/aio.h>
 
 /*
  * How many user pages to map in one call to get_user_pages().  This determines
@@ -229,7 +230,8 @@ static inline struct page *dio_get_page(struct dio *dio,
  * filesystems can use it to hold additional state between get_block calls and
  * dio_complete.
  */
-static ssize_t dio_complete(struct dio *dio, loff_t offset, ssize_t ret, bool is_async)
+static ssize_t dio_complete(struct dio *dio, loff_t offset, ssize_t ret,
+			    bool is_async, struct batch_complete *batch)
 {
 	ssize_t transferred = 0;
 
@@ -263,7 +265,7 @@ static ssize_t dio_complete(struct dio *dio, loff_t offset, ssize_t ret, bool is
 	} else {
 		inode_dio_done(dio->inode);
 		if (is_async)
-			aio_complete(dio->iocb, ret, 0);
+			aio_complete_batch(dio->iocb, ret, 0, batch);
 	}
 
 	return ret;
@@ -273,7 +275,8 @@ static int dio_bio_complete(struct dio *dio, struct bio *bio);
 /*
  * Asynchronous IO callback. 
  */
-static void dio_bio_end_aio(struct bio *bio, int error)
+static void dio_bio_end_aio(struct bio *bio, int error,
+			    struct batch_complete *batch)
 {
 	struct dio *dio = bio->bi_private;
 	unsigned long remaining;
@@ -289,7 +292,7 @@ static void dio_bio_end_aio(struct bio *bio, int error)
 	spin_unlock_irqrestore(&dio->bio_lock, flags);
 
 	if (remaining == 0) {
-		dio_complete(dio, dio->iocb->ki_pos, 0, true);
+		dio_complete(dio, dio->iocb->ki_pos, 0, true, batch);
 		kmem_cache_free(dio_cache, dio);
 	}
 }
@@ -323,12 +326,12 @@ static void dio_bio_end_io(struct bio *bio, int error)
  * so that the DIO specific endio actions are dealt with after the filesystem
  * has done it's completion work.
  */
-void dio_end_io(struct bio *bio, int error)
+void dio_end_io(struct bio *bio, int error, struct batch_complete *batch)
 {
 	struct dio *dio = bio->bi_private;
 
 	if (dio->is_async)
-		dio_bio_end_aio(bio, error);
+		dio_bio_end_aio(bio, error, batch);
 	else
 		dio_bio_end_io(bio, error);
 }
@@ -349,10 +352,7 @@ dio_bio_alloc(struct dio *dio, struct dio_submit *sdio,
 
 	bio->bi_bdev = bdev;
 	bio->bi_sector = first_sector;
-	if (dio->is_async)
-		bio->bi_end_io = dio_bio_end_aio;
-	else
-		bio->bi_end_io = dio_bio_end_io;
+	bio->bi_end_io = dio_end_io;
 
 	sdio->bio = bio;
 	sdio->logical_offset_in_bio = sdio->cur_page_fs_offset;
@@ -441,8 +441,8 @@ static struct bio *dio_await_one(struct dio *dio)
 static int dio_bio_complete(struct dio *dio, struct bio *bio)
 {
 	const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
-	struct bio_vec *bvec = bio->bi_io_vec;
-	int page_no;
+	struct bio_vec *bvec;
+	unsigned i;
 
 	if (!uptodate)
 		dio->io_error = -EIO;
@@ -450,8 +450,8 @@ static int dio_bio_complete(struct dio *dio, struct bio *bio)
 	if (dio->is_async && dio->rw == READ) {
 		bio_check_pages_dirty(bio);	/* transfers ownership */
 	} else {
-		for (page_no = 0; page_no < bio->bi_vcnt; page_no++) {
-			struct page *page = bvec[page_no].bv_page;
+		bio_for_each_segment_all(bvec, bio, i) {
+			struct page *page = bvec->bv_page;
 
 			if (dio->rw == READ && !PageCompound(page))
 				set_page_dirty_lock(page);
@@ -969,7 +969,8 @@ do_holes:
 			this_chunk_bytes = this_chunk_blocks << blkbits;
 			BUG_ON(this_chunk_bytes == 0);
 
-			sdio->boundary = buffer_boundary(map_bh);
+			if (this_chunk_blocks == sdio->blocks_available)
+				sdio->boundary = buffer_boundary(map_bh);
 			ret = submit_page_section(dio, sdio, page,
 						  offset_in_page,
 						  this_chunk_bytes,
@@ -1272,7 +1273,7 @@ do_blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
 		dio_await_completion(dio);
 
 	if (drop_refcount(dio) == 0) {
-		retval = dio_complete(dio, offset, retval, false);
+		retval = dio_complete(dio, offset, retval, false, NULL);
 		kmem_cache_free(dio_cache, dio);
 	} else
 		BUG_ON(retval != -EIOCBQUEUED);
diff --git a/fs/dlm/plock.c b/fs/dlm/plock.c
index 01fd5c1..f704458 100644
--- a/fs/dlm/plock.c
+++ b/fs/dlm/plock.c
@@ -247,6 +247,7 @@ int dlm_posix_unlock(dlm_lockspace_t *lockspace, u64 number, struct file *file,
 	struct dlm_ls *ls;
 	struct plock_op *op;
 	int rv;
+	unsigned char fl_flags = fl->fl_flags;
 
 	ls = dlm_find_lockspace_local(lockspace);
 	if (!ls)
@@ -258,9 +259,18 @@ int dlm_posix_unlock(dlm_lockspace_t *lockspace, u64 number, struct file *file,
 		goto out;
 	}
 
-	if (posix_lock_file_wait(file, fl) < 0)
-		log_error(ls, "dlm_posix_unlock: vfs unlock error %llx",
-			  (unsigned long long)number);
+	/* cause the vfs unlock to return ENOENT if lock is not found */
+	fl->fl_flags |= FL_EXISTS;
+
+	rv = posix_lock_file_wait(file, fl);
+	if (rv == -ENOENT) {
+		rv = 0;
+		goto out_free;
+	}
+	if (rv < 0) {
+		log_error(ls, "dlm_posix_unlock: vfs unlock error %d %llx",
+			  rv, (unsigned long long)number);
+	}
 
 	op->info.optype		= DLM_PLOCK_OP_UNLOCK;
 	op->info.pid		= fl->fl_pid;
@@ -296,9 +306,11 @@ int dlm_posix_unlock(dlm_lockspace_t *lockspace, u64 number, struct file *file,
 	if (rv == -ENOENT)
 		rv = 0;
 
+out_free:
 	kfree(op);
 out:
 	dlm_put_lockspace(ls);
+	fl->fl_flags = fl_flags;
 	return rv;
 }
 EXPORT_SYMBOL_GPL(dlm_posix_unlock);
diff --git a/fs/drop_caches.c b/fs/drop_caches.c
index c00e055..f23d2a7 100644
--- a/fs/drop_caches.c
+++ b/fs/drop_caches.c
@@ -58,6 +58,8 @@ int drop_caches_sysctl_handler(ctl_table *table, int write,
 	if (ret)
 		return ret;
 	if (write) {
+		printk(KERN_NOTICE "%s (%d): dropped kernel caches: %d\n",
+		       current->comm, task_pid_nr(current), sysctl_drop_caches);
 		if (sysctl_drop_caches & 1)
 			iterate_supers(drop_pagecache_sb, NULL);
 		if (sysctl_drop_caches & 2)
diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c
index 63b1f54..201f0a0 100644
--- a/fs/ecryptfs/file.c
+++ b/fs/ecryptfs/file.c
@@ -31,6 +31,7 @@
 #include <linux/security.h>
 #include <linux/compat.h>
 #include <linux/fs_stack.h>
+#include <linux/aio.h>
 #include "ecryptfs_kernel.h"
 
 /**
diff --git a/fs/ecryptfs/miscdev.c b/fs/ecryptfs/miscdev.c
index 412e6ed..e4141f2 100644
--- a/fs/ecryptfs/miscdev.c
+++ b/fs/ecryptfs/miscdev.c
@@ -80,13 +80,6 @@ ecryptfs_miscdev_open(struct inode *inode, struct file *file)
 	int rc;
 
 	mutex_lock(&ecryptfs_daemon_hash_mux);
-	rc = try_module_get(THIS_MODULE);
-	if (rc == 0) {
-		rc = -EIO;
-		printk(KERN_ERR "%s: Error attempting to increment module use "
-		       "count; rc = [%d]\n", __func__, rc);
-		goto out_unlock_daemon_list;
-	}
 	rc = ecryptfs_find_daemon_by_euid(&daemon);
 	if (!rc) {
 		rc = -EINVAL;
@@ -96,7 +89,7 @@ ecryptfs_miscdev_open(struct inode *inode, struct file *file)
 	if (rc) {
 		printk(KERN_ERR "%s: Error attempting to spawn daemon; "
 		       "rc = [%d]\n", __func__, rc);
-		goto out_module_put_unlock_daemon_list;
+		goto out_unlock_daemon_list;
 	}
 	mutex_lock(&daemon->mux);
 	if (daemon->flags & ECRYPTFS_DAEMON_MISCDEV_OPEN) {
@@ -108,9 +101,6 @@ ecryptfs_miscdev_open(struct inode *inode, struct file *file)
 	atomic_inc(&ecryptfs_num_miscdev_opens);
 out_unlock_daemon:
 	mutex_unlock(&daemon->mux);
-out_module_put_unlock_daemon_list:
-	if (rc)
-		module_put(THIS_MODULE);
 out_unlock_daemon_list:
 	mutex_unlock(&ecryptfs_daemon_hash_mux);
 	return rc;
@@ -147,7 +137,6 @@ ecryptfs_miscdev_release(struct inode *inode, struct file *file)
 		       "bug.\n", __func__, rc);
 		BUG();
 	}
-	module_put(THIS_MODULE);
 	return rc;
 }
 
@@ -471,6 +460,7 @@ out_free:
 
 
 static const struct file_operations ecryptfs_miscdev_fops = {
+	.owner   = THIS_MODULE,
 	.open    = ecryptfs_miscdev_open,
 	.poll    = ecryptfs_miscdev_poll,
 	.read    = ecryptfs_miscdev_read,
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index 9fec183..227747b 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -40,6 +40,7 @@
 #include <linux/atomic.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
+#include <linux/compat.h>
 
 /*
  * LOCKING:
@@ -104,7 +105,7 @@
 struct epoll_filefd {
 	struct file *file;
 	int fd;
-};
+} __packed;
 
 /*
  * Structure used to track possible nested calls, for too deep recursions
@@ -128,6 +129,8 @@ struct nested_calls {
 /*
  * Each file descriptor added to the eventpoll interface will
  * have an entry of this type linked to the "rbr" RB tree.
+ * Avoid increasing the size of this struct, there can be many thousands
+ * of these on a server and we do not want this to take another cache line.
  */
 struct epitem {
 	/* RB tree node used to link this structure to the eventpoll RB tree */
@@ -158,7 +161,7 @@ struct epitem {
 	struct list_head fllink;
 
 	/* wakeup_source used when EPOLLWAKEUP is set */
-	struct wakeup_source *ws;
+	struct wakeup_source __rcu *ws;
 
 	/* The structure that describe the interested events and the source fd */
 	struct epoll_event event;
@@ -348,7 +351,7 @@ static inline struct epitem *ep_item_from_epqueue(poll_table *p)
 /* Tells if the epoll_ctl(2) operation needs an event copy from userspace */
 static inline int ep_op_has_event(int op)
 {
-	return op != EPOLL_CTL_DEL;
+	return op == EPOLL_CTL_ADD || op == EPOLL_CTL_MOD;
 }
 
 /* Initialize the poll safe wake up structure */
@@ -536,6 +539,38 @@ static void ep_unregister_pollwait(struct eventpoll *ep, struct epitem *epi)
 	}
 }
 
+/* call only when ep->mtx is held */
+static inline struct wakeup_source *ep_wakeup_source(struct epitem *epi)
+{
+	return rcu_dereference_check(epi->ws, lockdep_is_held(&epi->ep->mtx));
+}
+
+/* call only when ep->mtx is held */
+static inline void ep_pm_stay_awake(struct epitem *epi)
+{
+	struct wakeup_source *ws = ep_wakeup_source(epi);
+
+	if (ws)
+		__pm_stay_awake(ws);
+}
+
+static inline bool ep_has_wakeup_source(struct epitem *epi)
+{
+	return rcu_access_pointer(epi->ws) ? true : false;
+}
+
+/* call when ep->mtx cannot be held (ep_poll_callback) */
+static inline void ep_pm_stay_awake_rcu(struct epitem *epi)
+{
+	struct wakeup_source *ws;
+
+	rcu_read_lock();
+	ws = rcu_dereference(epi->ws);
+	if (ws)
+		__pm_stay_awake(ws);
+	rcu_read_unlock();
+}
+
 /**
  * ep_scan_ready_list - Scans the ready list in a way that makes possible for
  *                      the scan code, to call f_op->poll(). Also allows for
@@ -599,7 +634,7 @@ static int ep_scan_ready_list(struct eventpoll *ep,
 		 */
 		if (!ep_is_linked(&epi->rdllink)) {
 			list_add_tail(&epi->rdllink, &ep->rdllist);
-			__pm_stay_awake(epi->ws);
+			ep_pm_stay_awake(epi);
 		}
 	}
 	/*
@@ -668,7 +703,7 @@ static int ep_remove(struct eventpoll *ep, struct epitem *epi)
 		list_del_init(&epi->rdllink);
 	spin_unlock_irqrestore(&ep->lock, flags);
 
-	wakeup_source_unregister(epi->ws);
+	wakeup_source_unregister(ep_wakeup_source(epi));
 
 	/* At this point it is safe to free the eventpoll item */
 	kmem_cache_free(epi_cache, epi);
@@ -678,6 +713,36 @@ static int ep_remove(struct eventpoll *ep, struct epitem *epi)
 	return 0;
 }
 
+/*
+ * Disables a "struct epitem" in the eventpoll set. Returns -EBUSY if the item
+ * had no event flags set, indicating that another thread may be currently
+ * handling that item's events (in the case that EPOLLONESHOT was being
+ * used). Otherwise a zero result indicates that the item has been disabled
+ * from receiving events. A disabled item may be re-enabled via
+ * EPOLL_CTL_MOD. Must be called with "mtx" held.
+ */
+static int ep_disable(struct eventpoll *ep, struct epitem *epi)
+{
+	int result = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ep->lock, flags);
+	if (epi->event.events & EPOLLONESHOT) {
+		if (epi->event.events & ~EP_PRIVATE_BITS) {
+			if (ep_is_linked(&epi->rdllink))
+				list_del_init(&epi->rdllink);
+			/* Ensure ep_poll_callback will not add epi back onto
+			   ready list: */
+			epi->event.events &= EP_PRIVATE_BITS;
+		} else
+			result = -EBUSY;
+	} else
+		result = -EINVAL;
+	spin_unlock_irqrestore(&ep->lock, flags);
+
+	return result;
+}
+
 static void ep_free(struct eventpoll *ep)
 {
 	struct rb_node *rbp;
@@ -711,11 +776,15 @@ static void ep_free(struct eventpoll *ep)
 	 * point we are sure no poll callbacks will be lingering around, and also by
 	 * holding "epmutex" we can be sure that no file cleanup code will hit
 	 * us during this operation. So we can avoid the lock on "ep->lock".
+	 * We do not need to lock ep->mtx, either, we only do it to prevent
+	 * a lockdep warning.
 	 */
+	mutex_lock(&ep->mtx);
 	while ((rbp = rb_first(&ep->rbr)) != NULL) {
 		epi = rb_entry(rbp, struct epitem, rbn);
 		ep_remove(ep, epi);
 	}
+	mutex_unlock(&ep->mtx);
 
 	mutex_unlock(&epmutex);
 	mutex_destroy(&ep->mtx);
@@ -734,6 +803,13 @@ static int ep_eventpoll_release(struct inode *inode, struct file *file)
 	return 0;
 }
 
+static inline unsigned int ep_item_poll(struct epitem *epi, poll_table *pt)
+{
+	pt->_key = epi->event.events;
+
+	return epi->ffd.file->f_op->poll(epi->ffd.file, pt) & epi->event.events;
+}
+
 static int ep_read_events_proc(struct eventpoll *ep, struct list_head *head,
 			       void *priv)
 {
@@ -741,10 +817,9 @@ static int ep_read_events_proc(struct eventpoll *ep, struct list_head *head,
 	poll_table pt;
 
 	init_poll_funcptr(&pt, NULL);
+
 	list_for_each_entry_safe(epi, tmp, head, rdllink) {
-		pt._key = epi->event.events;
-		if (epi->ffd.file->f_op->poll(epi->ffd.file, &pt) &
-		    epi->event.events)
+		if (ep_item_poll(epi, &pt))
 			return POLLIN | POLLRDNORM;
 		else {
 			/*
@@ -752,7 +827,7 @@ static int ep_read_events_proc(struct eventpoll *ep, struct list_head *head,
 			 * callback, but it's not actually ready, as far as
 			 * caller requested events goes. We can remove it here.
 			 */
-			__pm_relax(epi->ws);
+			__pm_relax(ep_wakeup_source(epi));
 			list_del_init(&epi->rdllink);
 		}
 	}
@@ -984,7 +1059,7 @@ static int ep_poll_callback(wait_queue_t *wait, unsigned mode, int sync, void *k
 	/* If this file is already in the ready list we exit soon */
 	if (!ep_is_linked(&epi->rdllink)) {
 		list_add_tail(&epi->rdllink, &ep->rdllist);
-		__pm_stay_awake(epi->ws);
+		ep_pm_stay_awake_rcu(epi);
 	}
 
 	/*
@@ -1048,8 +1123,6 @@ static void ep_rbtree_insert(struct eventpoll *ep, struct epitem *epi)
 	rb_insert_color(&epi->rbn, &ep->rbr);
 }
 
-
-
 #define PATH_ARR_SIZE 5
 /*
  * These are the number paths of length 1 to 5, that we are allowing to emanate
@@ -1146,6 +1219,7 @@ static int reverse_path_check(void)
 static int ep_create_wakeup_source(struct epitem *epi)
 {
 	const char *name;
+	struct wakeup_source *ws;
 
 	if (!epi->ep->ws) {
 		epi->ep->ws = wakeup_source_register("eventpoll");
@@ -1154,17 +1228,29 @@ static int ep_create_wakeup_source(struct epitem *epi)
 	}
 
 	name = epi->ffd.file->f_path.dentry->d_name.name;
-	epi->ws = wakeup_source_register(name);
-	if (!epi->ws)
+	ws = wakeup_source_register(name);
+
+	if (!ws)
 		return -ENOMEM;
+	rcu_assign_pointer(epi->ws, ws);
 
 	return 0;
 }
 
-static void ep_destroy_wakeup_source(struct epitem *epi)
+/* rare code path, only used when EPOLL_CTL_MOD removes a wakeup source */
+static noinline void ep_destroy_wakeup_source(struct epitem *epi)
 {
-	wakeup_source_unregister(epi->ws);
-	epi->ws = NULL;
+	struct wakeup_source *ws = ep_wakeup_source(epi);
+
+	rcu_assign_pointer(epi->ws, NULL);
+
+	/*
+	 * wait for ep_pm_stay_awake_rcu to finish, synchronize_rcu is
+	 * used internally by wakeup_source_remove, too (called by
+	 * wakeup_source_unregister), so we cannot use call_rcu
+	 */
+	synchronize_rcu();
+	wakeup_source_unregister(ws);
 }
 
 /*
@@ -1199,13 +1285,12 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event,
 		if (error)
 			goto error_create_wakeup_source;
 	} else {
-		epi->ws = NULL;
+		RCU_INIT_POINTER(epi->ws, NULL);
 	}
 
 	/* Initialize the poll table using the queue callback */
 	epq.epi = epi;
 	init_poll_funcptr(&epq.pt, ep_ptable_queue_proc);
-	epq.pt._key = event->events;
 
 	/*
 	 * Attach the item to the poll hooks and get current event bits.
@@ -1214,7 +1299,7 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event,
 	 * this operation completes, the poll callback can start hitting
 	 * the new item.
 	 */
-	revents = tfile->f_op->poll(tfile, &epq.pt);
+	revents = ep_item_poll(epi, &epq.pt);
 
 	/*
 	 * We have to check if something went wrong during the poll wait queue
@@ -1247,7 +1332,7 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event,
 	/* If the file is already "ready" we drop it inside the ready list */
 	if ((revents & event->events) && !ep_is_linked(&epi->rdllink)) {
 		list_add_tail(&epi->rdllink, &ep->rdllist);
-		__pm_stay_awake(epi->ws);
+		ep_pm_stay_awake(epi);
 
 		/* Notify waiting tasks that events are available */
 		if (waitqueue_active(&ep->wq))
@@ -1288,7 +1373,7 @@ error_unregister:
 		list_del_init(&epi->rdllink);
 	spin_unlock_irqrestore(&ep->lock, flags);
 
-	wakeup_source_unregister(epi->ws);
+	wakeup_source_unregister(ep_wakeup_source(epi));
 
 error_create_wakeup_source:
 	kmem_cache_free(epi_cache, epi);
@@ -1314,12 +1399,11 @@ static int ep_modify(struct eventpoll *ep, struct epitem *epi, struct epoll_even
 	 * f_op->poll() call and the new event set registering.
 	 */
 	epi->event.events = event->events; /* need barrier below */
-	pt._key = event->events;
 	epi->event.data = event->data; /* protected by mtx */
 	if (epi->event.events & EPOLLWAKEUP) {
-		if (!epi->ws)
+		if (!ep_has_wakeup_source(epi))
 			ep_create_wakeup_source(epi);
-	} else if (epi->ws) {
+	} else if (ep_has_wakeup_source(epi)) {
 		ep_destroy_wakeup_source(epi);
 	}
 
@@ -1347,7 +1431,7 @@ static int ep_modify(struct eventpoll *ep, struct epitem *epi, struct epoll_even
 	 * Get current event bits. We can safely use the file* here because
 	 * its usage count has been increased by the caller of this function.
 	 */
-	revents = epi->ffd.file->f_op->poll(epi->ffd.file, &pt);
+	revents = ep_item_poll(epi, &pt);
 
 	/*
 	 * If the item is "hot" and it is not registered inside the ready
@@ -1357,7 +1441,7 @@ static int ep_modify(struct eventpoll *ep, struct epitem *epi, struct epoll_even
 		spin_lock_irq(&ep->lock);
 		if (!ep_is_linked(&epi->rdllink)) {
 			list_add_tail(&epi->rdllink, &ep->rdllist);
-			__pm_stay_awake(epi->ws);
+			ep_pm_stay_awake(epi);
 
 			/* Notify waiting tasks that events are available */
 			if (waitqueue_active(&ep->wq))
@@ -1383,6 +1467,7 @@ static int ep_send_events_proc(struct eventpoll *ep, struct list_head *head,
 	unsigned int revents;
 	struct epitem *epi;
 	struct epoll_event __user *uevent;
+	struct wakeup_source *ws;
 	poll_table pt;
 
 	init_poll_funcptr(&pt, NULL);
@@ -1405,14 +1490,16 @@ static int ep_send_events_proc(struct eventpoll *ep, struct list_head *head,
 		 * instead, but then epi->ws would temporarily be out of sync
 		 * with ep_is_linked().
 		 */
-		if (epi->ws && epi->ws->active)
-			__pm_stay_awake(ep->ws);
-		__pm_relax(epi->ws);
+		ws = ep_wakeup_source(epi);
+		if (ws) {
+			if (ws->active)
+				__pm_stay_awake(ep->ws);
+			__pm_relax(ws);
+		}
+
 		list_del_init(&epi->rdllink);
 
-		pt._key = epi->event.events;
-		revents = epi->ffd.file->f_op->poll(epi->ffd.file, &pt) &
-			epi->event.events;
+		revents = ep_item_poll(epi, &pt);
 
 		/*
 		 * If the event mask intersect the caller-requested one,
@@ -1424,7 +1511,7 @@ static int ep_send_events_proc(struct eventpoll *ep, struct list_head *head,
 			if (__put_user(revents, &uevent->events) ||
 			    __put_user(epi->event.data, &uevent->data)) {
 				list_add(&epi->rdllink, head);
-				__pm_stay_awake(epi->ws);
+				ep_pm_stay_awake(epi);
 				return eventcnt ? eventcnt : -EFAULT;
 			}
 			eventcnt++;
@@ -1444,7 +1531,7 @@ static int ep_send_events_proc(struct eventpoll *ep, struct list_head *head,
 				 * poll callback will queue them in ep->ovflist.
 				 */
 				list_add_tail(&epi->rdllink, &ep->rdllist);
-				__pm_stay_awake(epi->ws);
+				ep_pm_stay_awake(epi);
 			}
 		}
 	}
@@ -1835,6 +1922,12 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
 		} else
 			error = -ENOENT;
 		break;
+	case EPOLL_CTL_DISABLE:
+		if (epi)
+			error = ep_disable(ep, epi);
+		else
+			error = -ENOENT;
+		break;
 	}
 	mutex_unlock(&ep->mtx);
 
@@ -1940,6 +2033,52 @@ SYSCALL_DEFINE6(epoll_pwait, int, epfd, struct epoll_event __user *, events,
 	return error;
 }
 
+#ifdef CONFIG_COMPAT
+COMPAT_SYSCALL_DEFINE6(epoll_pwait, int, epfd,
+			struct epoll_event __user *, events,
+			int, maxevents, int, timeout,
+			const compat_sigset_t __user *, sigmask,
+			compat_size_t, sigsetsize)
+{
+	long err;
+	compat_sigset_t csigmask;
+	sigset_t ksigmask, sigsaved;
+
+	/*
+	 * If the caller wants a certain signal mask to be set during the wait,
+	 * we apply it here.
+	 */
+	if (sigmask) {
+		if (sigsetsize != sizeof(compat_sigset_t))
+			return -EINVAL;
+		if (copy_from_user(&csigmask, sigmask, sizeof(csigmask)))
+			return -EFAULT;
+		sigset_from_compat(&ksigmask, &csigmask);
+		sigdelsetmask(&ksigmask, sigmask(SIGKILL) | sigmask(SIGSTOP));
+		sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
+	}
+
+	err = sys_epoll_wait(epfd, events, maxevents, timeout);
+
+	/*
+	 * If we changed the signal mask, we need to restore the original one.
+	 * In case we've got a signal while waiting, we do not restore the
+	 * signal mask yet, and we allow do_signal() to deliver the signal on
+	 * the way back to userspace, before the signal mask is restored.
+	 */
+	if (sigmask) {
+		if (err == -EINTR) {
+			memcpy(&current->saved_sigmask, &sigsaved,
+			       sizeof(sigsaved));
+			set_restore_sigmask();
+		} else
+			sigprocmask(SIG_SETMASK, &sigsaved, NULL);
+	}
+
+	return err;
+}
+#endif
+
 static int __init eventpoll_init(void)
 {
 	struct sysinfo si;
@@ -1964,6 +2103,12 @@ static int __init eventpoll_init(void)
 	/* Initialize the structure used to perform file's f_op->poll() calls */
 	ep_nested_calls_init(&poll_readywalk_ncalls);
 
+	/*
+	 * We can have many thousands of epitems, so prevent this from
+	 * using an extra cache line on 64-bit (and smaller) CPUs
+	 */
+	BUILD_BUG_ON(sizeof(void *) <= 8 && sizeof(struct epitem) > 128);
+
 	/* Allocates slab cache used to allocate "struct epitem" items */
 	epi_cache = kmem_cache_create("eventpoll_epi", sizeof(struct epitem),
 			0, SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL);
diff --git a/fs/exec.c b/fs/exec.c
index a96a488..963f510 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -613,7 +613,7 @@ static int shift_arg_pages(struct vm_area_struct *vma, unsigned long shift)
 		 * when the old and new regions overlap clear from new_end.
 		 */
 		free_pgd_range(&tlb, new_end, old_end, new_end,
-			vma->vm_next ? vma->vm_next->vm_start : 0);
+			vma->vm_next ? vma->vm_next->vm_start : USER_PGTABLES_CEILING);
 	} else {
 		/*
 		 * otherwise, clean from old_start; this is done to not touch
@@ -622,7 +622,7 @@ static int shift_arg_pages(struct vm_area_struct *vma, unsigned long shift)
 		 * for the others its just a little faster.
 		 */
 		free_pgd_range(&tlb, old_start, old_end, new_end,
-			vma->vm_next ? vma->vm_next->vm_start : 0);
+			vma->vm_next ? vma->vm_next->vm_start : USER_PGTABLES_CEILING);
 	}
 	tlb_finish_mmu(&tlb, new_end, old_end);
 
@@ -898,11 +898,13 @@ static int de_thread(struct task_struct *tsk)
 
 		sig->notify_count = -1;	/* for exit_notify() */
 		for (;;) {
+			threadgroup_change_begin(tsk);
 			write_lock_irq(&tasklist_lock);
 			if (likely(leader->exit_state))
 				break;
 			__set_current_state(TASK_KILLABLE);
 			write_unlock_irq(&tasklist_lock);
+			threadgroup_change_end(tsk);
 			schedule();
 			if (unlikely(__fatal_signal_pending(tsk)))
 				goto killed;
@@ -960,6 +962,7 @@ static int de_thread(struct task_struct *tsk)
 		if (unlikely(leader->ptrace))
 			__wake_up_parent(leader, leader->parent);
 		write_unlock_irq(&tasklist_lock);
+		threadgroup_change_end(tsk);
 
 		release_task(leader);
 	}
@@ -1027,17 +1030,7 @@ EXPORT_SYMBOL_GPL(get_task_comm);
 void set_task_comm(struct task_struct *tsk, char *buf)
 {
 	task_lock(tsk);
-
 	trace_task_rename(tsk, buf);
-
-	/*
-	 * Threads may access current->comm without holding
-	 * the task lock, so write the string carefully.
-	 * Readers without a lock may see incomplete new
-	 * names but are safe from non-terminating string reads.
-	 */
-	memset(tsk->comm, 0, TASK_COMM_LEN);
-	wmb();
 	strlcpy(tsk->comm, buf, sizeof(tsk->comm));
 	task_unlock(tsk);
 	perf_event_comm(tsk);
diff --git a/fs/exofs/ore.c b/fs/exofs/ore.c
index f936cb5..b744228 100644
--- a/fs/exofs/ore.c
+++ b/fs/exofs/ore.c
@@ -401,7 +401,7 @@ static void _clear_bio(struct bio *bio)
 	struct bio_vec *bv;
 	unsigned i;
 
-	__bio_for_each_segment(bv, bio, i, 0) {
+	bio_for_each_segment_all(bv, bio, i) {
 		unsigned this_count = bv->bv_len;
 
 		if (likely(PAGE_SIZE == this_count))
diff --git a/fs/exofs/ore_raid.c b/fs/exofs/ore_raid.c
index b963f38..7682b97 100644
--- a/fs/exofs/ore_raid.c
+++ b/fs/exofs/ore_raid.c
@@ -432,7 +432,7 @@ static void _mark_read4write_pages_uptodate(struct ore_io_state *ios, int ret)
 		if (!bio)
 			continue;
 
-		__bio_for_each_segment(bv, bio, i, 0) {
+		bio_for_each_segment_all(bv, bio, i) {
 			struct page *page = bv->bv_page;
 
 			SetPageUptodate(page);
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
index fe60cc1..0a87bb1 100644
--- a/fs/ext2/inode.c
+++ b/fs/ext2/inode.c
@@ -31,6 +31,7 @@
 #include <linux/mpage.h>
 #include <linux/fiemap.h>
 #include <linux/namei.h>
+#include <linux/aio.h>
 #include "ext2.h"
 #include "acl.h"
 #include "xip.h"
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index d512c4b..23c7128 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -27,6 +27,7 @@
 #include <linux/writeback.h>
 #include <linux/mpage.h>
 #include <linux/namei.h>
+#include <linux/aio.h>
 #include "ext3.h"
 #include "xattr.h"
 #include "acl.h"
@@ -218,7 +219,8 @@ void ext3_evict_inode (struct inode *inode)
 	 */
 	if (inode->i_nlink && ext3_should_journal_data(inode) &&
 	    EXT3_SB(inode->i_sb)->s_journal &&
-	    (S_ISLNK(inode->i_mode) || S_ISREG(inode->i_mode))) {
+	    (S_ISLNK(inode->i_mode) || S_ISREG(inode->i_mode)) &&
+	    inode->i_ino != EXT3_JOURNAL_INO) {
 		tid_t commit_tid = atomic_read(&ei->i_datasync_tid);
 		journal_t *journal = EXT3_SB(inode->i_sb)->s_journal;
 
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index fb5120a..3dc48cc 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -2067,7 +2067,6 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
 		test_opt(sb,DATA_FLAGS) == EXT3_MOUNT_JOURNAL_DATA ? "journal":
 		test_opt(sb,DATA_FLAGS) == EXT3_MOUNT_ORDERED_DATA ? "ordered":
 		"writeback");
-	sb->s_flags |= MS_SNAP_STABLE;
 
 	return 0;
 
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index 92e68b3..9e8d8ff 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -30,6 +30,23 @@ static unsigned ext4_num_base_meta_clusters(struct super_block *sb,
  */
 
 /*
+ * Calculate block group number for a given block number
+ */
+ext4_group_t ext4_get_group_number(struct super_block *sb,
+				   ext4_fsblk_t block)
+{
+	ext4_group_t group;
+
+	if (test_opt2(sb, STD_GROUP_SIZE))
+		group = (le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block) +
+			 block) >>
+			(EXT4_BLOCK_SIZE_BITS(sb) + EXT4_CLUSTER_BITS(sb) + 3);
+	else
+		ext4_get_group_no_and_offset(sb, block, &group, NULL);
+	return group;
+}
+
+/*
  * Calculate the block group number and offset into the block/cluster
  * allocation bitmap, given a block number
  */
@@ -49,14 +66,18 @@ void ext4_get_group_no_and_offset(struct super_block *sb, ext4_fsblk_t blocknr,
 
 }
 
-static int ext4_block_in_group(struct super_block *sb, ext4_fsblk_t block,
-			ext4_group_t block_group)
+/*
+ * Check whether the 'block' lives within the 'block_group'. Returns 1 if so
+ * and 0 otherwise.
+ */
+static inline int ext4_block_in_group(struct super_block *sb,
+				      ext4_fsblk_t block,
+				      ext4_group_t block_group)
 {
 	ext4_group_t actual_group;
-	ext4_get_group_no_and_offset(sb, block, &actual_group, NULL);
-	if (actual_group == block_group)
-		return 1;
-	return 0;
+
+	actual_group = ext4_get_group_number(sb, block);
+	return (actual_group == block_group) ? 1 : 0;
 }
 
 /* Return the number of clusters used for file system metadata; this
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 3b83cd6..a0637e5 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -403,7 +403,7 @@ struct flex_groups {
 #define EXT4_RESERVED_FL		0x80000000 /* reserved for ext4 lib */
 
 #define EXT4_FL_USER_VISIBLE		0x004BDFFF /* User visible flags */
-#define EXT4_FL_USER_MODIFIABLE		0x004B80FF /* User modifiable flags */
+#define EXT4_FL_USER_MODIFIABLE		0x004380FF /* User modifiable flags */
 
 /* Flags that should be inherited by new inodes from their parent. */
 #define EXT4_FL_INHERITED (EXT4_SECRM_FL | EXT4_UNRM_FL | EXT4_COMPR_FL |\
@@ -949,7 +949,7 @@ struct ext4_inode_info {
 #define EXT2_FLAGS_TEST_FILESYS		0x0004	/* to test development code */
 
 /*
- * Mount flags
+ * Mount flags set via mount options or defaults
  */
 #define EXT4_MOUNT_GRPID		0x00004	/* Create files with directory's group */
 #define EXT4_MOUNT_DEBUG		0x00008	/* Some debugging messages */
@@ -981,8 +981,16 @@ struct ext4_inode_info {
 #define EXT4_MOUNT_DISCARD		0x40000000 /* Issue DISCARD requests */
 #define EXT4_MOUNT_INIT_INODE_TABLE	0x80000000 /* Initialize uninitialized itables */
 
+/*
+ * Mount flags set either automatically (could not be set by mount option)
+ * based on per file system feature or property or in special cases such as
+ * distinguishing between explicit mount option definition and default.
+ */
 #define EXT4_MOUNT2_EXPLICIT_DELALLOC	0x00000001 /* User explicitly
 						      specified delalloc */
+#define EXT4_MOUNT2_STD_GROUP_SIZE	0x00000002 /* We have standard group
+						      size of blocksize * 8
+						      blocks */
 
 #define clear_opt(sb, opt)		EXT4_SB(sb)->s_mount_opt &= \
 						~EXT4_MOUNT_##opt
@@ -1374,6 +1382,7 @@ enum {
 	EXT4_STATE_DIOREAD_LOCK,	/* Disable support for dio read
 					   nolocking */
 	EXT4_STATE_MAY_INLINE_DATA,	/* may have in-inode data */
+	EXT4_STATE_ORDERED_MODE,	/* data=ordered mode */
 };
 
 #define EXT4_INODE_BIT_FNS(name, field, offset)				\
@@ -1784,9 +1793,6 @@ ext4_group_first_block_no(struct super_block *sb, ext4_group_t group_no)
  */
 #define ERR_BAD_DX_DIR	-75000
 
-void ext4_get_group_no_and_offset(struct super_block *sb, ext4_fsblk_t blocknr,
-			ext4_group_t *blockgrpp, ext4_grpblk_t *offsetp);
-
 /*
  * Timeout and state flag for lazy initialization inode thread.
  */
@@ -1908,6 +1914,13 @@ int ext4_block_bitmap_csum_verify(struct super_block *sb, ext4_group_t group,
 				  struct buffer_head *bh);
 
 /* balloc.c */
+extern void ext4_get_group_no_and_offset(struct super_block *sb,
+					 ext4_fsblk_t blocknr,
+					 ext4_group_t *blockgrpp,
+					 ext4_grpblk_t *offsetp);
+extern ext4_group_t ext4_get_group_number(struct super_block *sb,
+					  ext4_fsblk_t block);
+
 extern void ext4_validate_block_bitmap(struct super_block *sb,
 				       struct ext4_group_desc *desc,
 				       unsigned int block_group,
@@ -2108,8 +2121,9 @@ extern ssize_t ext4_ind_direct_IO(int rw, struct kiocb *iocb,
 				unsigned long nr_segs);
 extern int ext4_ind_calc_metadata_amount(struct inode *inode, sector_t lblock);
 extern int ext4_ind_trans_blocks(struct inode *inode, int nrblocks, int chunk);
-extern void ext4_ind_truncate(struct inode *inode);
-extern int ext4_ind_punch_hole(struct file *file, loff_t offset, loff_t length);
+extern void ext4_ind_truncate(handle_t *, struct inode *inode);
+extern int ext4_free_hole_blocks(handle_t *handle, struct inode *inode,
+				 ext4_lblk_t first, ext4_lblk_t stop);
 
 /* ioctl.c */
 extern long ext4_ioctl(struct file *, unsigned int, unsigned long);
@@ -2573,9 +2587,9 @@ extern int ext4_ext_index_trans_blocks(struct inode *inode, int nrblocks,
 				       int chunk);
 extern int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
 			       struct ext4_map_blocks *map, int flags);
-extern void ext4_ext_truncate(struct inode *);
-extern int ext4_ext_punch_hole(struct file *file, loff_t offset,
-				loff_t length);
+extern void ext4_ext_truncate(handle_t *, struct inode *);
+extern int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start,
+				 ext4_lblk_t end);
 extern void ext4_ext_init(struct super_block *);
 extern void ext4_ext_release(struct super_block *);
 extern long ext4_fallocate(struct file *file, int mode, loff_t offset,
@@ -2606,6 +2620,7 @@ extern int ext4_find_delalloc_range(struct inode *inode,
 extern int ext4_find_delalloc_cluster(struct inode *inode, ext4_lblk_t lblk);
 extern int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
 			__u64 start, __u64 len);
+extern int ext4_ind_migrate(struct inode *inode);
 
 
 /* move_extent.c */
diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c
index 7058975..0e1dc9e 100644
--- a/fs/ext4/ext4_jbd2.c
+++ b/fs/ext4/ext4_jbd2.c
@@ -43,6 +43,8 @@ handle_t *__ext4_journal_start_sb(struct super_block *sb, unsigned int line,
 {
 	journal_t *journal;
 
+	might_sleep();
+
 	trace_ext4_journal_start(sb, nblocks, _RET_IP_);
 	if (sb->s_flags & MS_RDONLY)
 		return ERR_PTR(-EROFS);
@@ -113,6 +115,8 @@ int __ext4_journal_get_write_access(const char *where, unsigned int line,
 {
 	int err = 0;
 
+	might_sleep();
+
 	if (ext4_handle_valid(handle)) {
 		err = jbd2_journal_get_write_access(handle, bh);
 		if (err)
@@ -209,6 +213,8 @@ int __ext4_handle_dirty_metadata(const char *where, unsigned int line,
 {
 	int err = 0;
 
+	might_sleep();
+
 	if (ext4_handle_valid(handle)) {
 		err = jbd2_journal_dirty_metadata(handle, bh);
 		if (err) {
diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h
index 4c216b1..aeed0ba 100644
--- a/fs/ext4/ext4_jbd2.h
+++ b/fs/ext4/ext4_jbd2.h
@@ -194,16 +194,20 @@ static inline void ext4_journal_callback_add(handle_t *handle,
  * ext4_journal_callback_del: delete a registered callback
  * @handle: active journal transaction handle on which callback was registered
  * @jce: registered journal callback entry to unregister
+ * Return true if object was sucessfully removed
  */
-static inline void ext4_journal_callback_del(handle_t *handle,
+static inline bool ext4_journal_callback_try_del(handle_t *handle,
 					     struct ext4_journal_cb_entry *jce)
 {
+	bool deleted;
 	struct ext4_sb_info *sbi =
 			EXT4_SB(handle->h_transaction->t_journal->j_private);
 
 	spin_lock(&sbi->s_md_lock);
+	deleted = !list_empty(&jce->jce_list);
 	list_del_init(&jce->jce_list);
 	spin_unlock(&sbi->s_md_lock);
+	return deleted;
 }
 
 int
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 56efcaa..6c5a70a 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -1813,39 +1813,101 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
 	}
 	depth = ext_depth(inode);
 	ex = path[depth].p_ext;
+	eh = path[depth].p_hdr;
 	if (unlikely(path[depth].p_hdr == NULL)) {
 		EXT4_ERROR_INODE(inode, "path[%d].p_hdr == NULL", depth);
 		return -EIO;
 	}
 
 	/* try to insert block into found extent and return */
-	if (ex && !(flag & EXT4_GET_BLOCKS_PRE_IO)
-		&& ext4_can_extents_be_merged(inode, ex, newext)) {
-		ext_debug("append [%d]%d block to %u:[%d]%d (from %llu)\n",
-			  ext4_ext_is_uninitialized(newext),
-			  ext4_ext_get_actual_len(newext),
-			  le32_to_cpu(ex->ee_block),
-			  ext4_ext_is_uninitialized(ex),
-			  ext4_ext_get_actual_len(ex),
-			  ext4_ext_pblock(ex));
-		err = ext4_ext_get_access(handle, inode, path + depth);
-		if (err)
-			return err;
+	if (ex && !(flag & EXT4_GET_BLOCKS_PRE_IO)) {
 
 		/*
-		 * ext4_can_extents_be_merged should have checked that either
-		 * both extents are uninitialized, or both aren't. Thus we
-		 * need to check only one of them here.
+		 * Try to see whether we should rather test the extent on
+		 * right from ex, or from the left of ex. This is because
+		 * ext4_ext_find_extent() can return either extent on the
+		 * left, or on the right from the searched position. This
+		 * will make merging more effective.
 		 */
-		if (ext4_ext_is_uninitialized(ex))
-			uninitialized = 1;
-		ex->ee_len = cpu_to_le16(ext4_ext_get_actual_len(ex)
+		if (ex < EXT_LAST_EXTENT(eh) &&
+		    (le32_to_cpu(ex->ee_block) +
+		    ext4_ext_get_actual_len(ex) <
+		    le32_to_cpu(newext->ee_block))) {
+			ex += 1;
+			goto prepend;
+		} else if ((ex > EXT_FIRST_EXTENT(eh)) &&
+			   (le32_to_cpu(newext->ee_block) +
+			   ext4_ext_get_actual_len(newext) <
+			   le32_to_cpu(ex->ee_block)))
+			ex -= 1;
+
+		/* Try to append newex to the ex */
+		if (ext4_can_extents_be_merged(inode, ex, newext)) {
+			ext_debug("append [%d]%d block to %u:[%d]%d"
+				  "(from %llu)\n",
+				  ext4_ext_is_uninitialized(newext),
+				  ext4_ext_get_actual_len(newext),
+				  le32_to_cpu(ex->ee_block),
+				  ext4_ext_is_uninitialized(ex),
+				  ext4_ext_get_actual_len(ex),
+				  ext4_ext_pblock(ex));
+			err = ext4_ext_get_access(handle, inode,
+						  path + depth);
+			if (err)
+				return err;
+
+			/*
+			 * ext4_can_extents_be_merged should have checked
+			 * that either both extents are uninitialized, or
+			 * both aren't. Thus we need to check only one of
+			 * them here.
+			 */
+			if (ext4_ext_is_uninitialized(ex))
+				uninitialized = 1;
+			ex->ee_len = cpu_to_le16(ext4_ext_get_actual_len(ex)
 					+ ext4_ext_get_actual_len(newext));
-		if (uninitialized)
-			ext4_ext_mark_uninitialized(ex);
-		eh = path[depth].p_hdr;
-		nearex = ex;
-		goto merge;
+			if (uninitialized)
+				ext4_ext_mark_uninitialized(ex);
+			eh = path[depth].p_hdr;
+			nearex = ex;
+			goto merge;
+		}
+
+prepend:
+		/* Try to prepend newex to the ex */
+		if (ext4_can_extents_be_merged(inode, newext, ex)) {
+			ext_debug("prepend %u[%d]%d block to %u:[%d]%d"
+				  "(from %llu)\n",
+				  le32_to_cpu(newext->ee_block),
+				  ext4_ext_is_uninitialized(newext),
+				  ext4_ext_get_actual_len(newext),
+				  le32_to_cpu(ex->ee_block),
+				  ext4_ext_is_uninitialized(ex),
+				  ext4_ext_get_actual_len(ex),
+				  ext4_ext_pblock(ex));
+			err = ext4_ext_get_access(handle, inode,
+						  path + depth);
+			if (err)
+				return err;
+
+			/*
+			 * ext4_can_extents_be_merged should have checked
+			 * that either both extents are uninitialized, or
+			 * both aren't. Thus we need to check only one of
+			 * them here.
+			 */
+			if (ext4_ext_is_uninitialized(ex))
+				uninitialized = 1;
+			ex->ee_block = newext->ee_block;
+			ext4_ext_store_pblock(ex, ext4_ext_pblock(newext));
+			ex->ee_len = cpu_to_le16(ext4_ext_get_actual_len(ex)
+					+ ext4_ext_get_actual_len(newext));
+			if (uninitialized)
+				ext4_ext_mark_uninitialized(ex);
+			eh = path[depth].p_hdr;
+			nearex = ex;
+			goto merge;
+		}
 	}
 
 	depth = ext_depth(inode);
@@ -2599,8 +2661,8 @@ ext4_ext_more_to_rm(struct ext4_ext_path *path)
 	return 1;
 }
 
-static int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start,
-				 ext4_lblk_t end)
+int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start,
+			  ext4_lblk_t end)
 {
 	struct super_block *sb = inode->i_sb;
 	int depth = ext_depth(inode);
@@ -2999,20 +3061,23 @@ static int ext4_split_extent_at(handle_t *handle,
 			if (split_flag & EXT4_EXT_DATA_VALID1) {
 				err = ext4_ext_zeroout(inode, ex2);
 				zero_ex.ee_block = ex2->ee_block;
-				zero_ex.ee_len = ext4_ext_get_actual_len(ex2);
+				zero_ex.ee_len = cpu_to_le16(
+						ext4_ext_get_actual_len(ex2));
 				ext4_ext_store_pblock(&zero_ex,
 						      ext4_ext_pblock(ex2));
 			} else {
 				err = ext4_ext_zeroout(inode, ex);
 				zero_ex.ee_block = ex->ee_block;
-				zero_ex.ee_len = ext4_ext_get_actual_len(ex);
+				zero_ex.ee_len = cpu_to_le16(
+						ext4_ext_get_actual_len(ex));
 				ext4_ext_store_pblock(&zero_ex,
 						      ext4_ext_pblock(ex));
 			}
 		} else {
 			err = ext4_ext_zeroout(inode, &orig_ex);
 			zero_ex.ee_block = orig_ex.ee_block;
-			zero_ex.ee_len = ext4_ext_get_actual_len(&orig_ex);
+			zero_ex.ee_len = cpu_to_le16(
+						ext4_ext_get_actual_len(&orig_ex));
 			ext4_ext_store_pblock(&zero_ex,
 					      ext4_ext_pblock(&orig_ex));
 		}
@@ -3150,29 +3215,28 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
 	struct ext4_extent_header *eh;
 	struct ext4_map_blocks split_map;
 	struct ext4_extent zero_ex;
-	struct ext4_extent *ex;
+	struct ext4_extent *ex, *abut_ex;
 	ext4_lblk_t ee_block, eof_block;
-	unsigned int ee_len, depth;
-	int allocated, max_zeroout = 0;
+	unsigned int ee_len, depth, map_len = map->m_len;
+	int allocated = 0, max_zeroout = 0;
 	int err = 0;
 	int split_flag = 0;
 
 	ext_debug("ext4_ext_convert_to_initialized: inode %lu, logical"
 		"block %llu, max_blocks %u\n", inode->i_ino,
-		(unsigned long long)map->m_lblk, map->m_len);
+		(unsigned long long)map->m_lblk, map_len);
 
 	sbi = EXT4_SB(inode->i_sb);
 	eof_block = (inode->i_size + inode->i_sb->s_blocksize - 1) >>
 		inode->i_sb->s_blocksize_bits;
-	if (eof_block < map->m_lblk + map->m_len)
-		eof_block = map->m_lblk + map->m_len;
+	if (eof_block < map->m_lblk + map_len)
+		eof_block = map->m_lblk + map_len;
 
 	depth = ext_depth(inode);
 	eh = path[depth].p_hdr;
 	ex = path[depth].p_ext;
 	ee_block = le32_to_cpu(ex->ee_block);
 	ee_len = ext4_ext_get_actual_len(ex);
-	allocated = ee_len - (map->m_lblk - ee_block);
 	zero_ex.ee_len = 0;
 
 	trace_ext4_ext_convert_to_initialized_enter(inode, map, ex);
@@ -3183,77 +3247,121 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
 
 	/*
 	 * Attempt to transfer newly initialized blocks from the currently
-	 * uninitialized extent to its left neighbor. This is much cheaper
+	 * uninitialized extent to its neighbor. This is much cheaper
 	 * than an insertion followed by a merge as those involve costly
-	 * memmove() calls. This is the common case in steady state for
-	 * workloads doing fallocate(FALLOC_FL_KEEP_SIZE) followed by append
-	 * writes.
+	 * memmove() calls. Transferring to the left is the common case in
+	 * steady state for workloads doing fallocate(FALLOC_FL_KEEP_SIZE)
+	 * followed by append writes.
 	 *
 	 * Limitations of the current logic:
-	 *  - L1: we only deal with writes at the start of the extent.
-	 *    The approach could be extended to writes at the end
-	 *    of the extent but this scenario was deemed less common.
-	 *  - L2: we do not deal with writes covering the whole extent.
+	 *  - L1: we do not deal with writes covering the whole extent.
 	 *    This would require removing the extent if the transfer
 	 *    is possible.
-	 *  - L3: we only attempt to merge with an extent stored in the
+	 *  - L2: we only attempt to merge with an extent stored in the
 	 *    same extent tree node.
 	 */
-	if ((map->m_lblk == ee_block) &&	/*L1*/
-		(map->m_len < ee_len) &&	/*L2*/
-		(ex > EXT_FIRST_EXTENT(eh))) {	/*L3*/
-		struct ext4_extent *prev_ex;
+	if ((map->m_lblk == ee_block) &&
+		/* See if we can merge left */
+		(map_len < ee_len) &&		/*L1*/
+		(ex > EXT_FIRST_EXTENT(eh))) {	/*L2*/
 		ext4_lblk_t prev_lblk;
 		ext4_fsblk_t prev_pblk, ee_pblk;
-		unsigned int prev_len, write_len;
+		unsigned int prev_len;
 
-		prev_ex = ex - 1;
-		prev_lblk = le32_to_cpu(prev_ex->ee_block);
-		prev_len = ext4_ext_get_actual_len(prev_ex);
-		prev_pblk = ext4_ext_pblock(prev_ex);
+		abut_ex = ex - 1;
+		prev_lblk = le32_to_cpu(abut_ex->ee_block);
+		prev_len = ext4_ext_get_actual_len(abut_ex);
+		prev_pblk = ext4_ext_pblock(abut_ex);
 		ee_pblk = ext4_ext_pblock(ex);
-		write_len = map->m_len;
 
 		/*
-		 * A transfer of blocks from 'ex' to 'prev_ex' is allowed
+		 * A transfer of blocks from 'ex' to 'abut_ex' is allowed
 		 * upon those conditions:
-		 * - C1: prev_ex is initialized,
-		 * - C2: prev_ex is logically abutting ex,
-		 * - C3: prev_ex is physically abutting ex,
-		 * - C4: prev_ex can receive the additional blocks without
+		 * - C1: abut_ex is initialized,
+		 * - C2: abut_ex is logically abutting ex,
+		 * - C3: abut_ex is physically abutting ex,
+		 * - C4: abut_ex can receive the additional blocks without
 		 *   overflowing the (initialized) length limit.
 		 */
-		if ((!ext4_ext_is_uninitialized(prev_ex)) &&		/*C1*/
+		if ((!ext4_ext_is_uninitialized(abut_ex)) &&		/*C1*/
 			((prev_lblk + prev_len) == ee_block) &&		/*C2*/
 			((prev_pblk + prev_len) == ee_pblk) &&		/*C3*/
-			(prev_len < (EXT_INIT_MAX_LEN - write_len))) {	/*C4*/
+			(prev_len < (EXT_INIT_MAX_LEN - map_len))) {	/*C4*/
 			err = ext4_ext_get_access(handle, inode, path + depth);
 			if (err)
 				goto out;
 
 			trace_ext4_ext_convert_to_initialized_fastpath(inode,
-				map, ex, prev_ex);
+				map, ex, abut_ex);
 
-			/* Shift the start of ex by 'write_len' blocks */
-			ex->ee_block = cpu_to_le32(ee_block + write_len);
-			ext4_ext_store_pblock(ex, ee_pblk + write_len);
-			ex->ee_len = cpu_to_le16(ee_len - write_len);
+			/* Shift the start of ex by 'map_len' blocks */
+			ex->ee_block = cpu_to_le32(ee_block + map_len);
+			ext4_ext_store_pblock(ex, ee_pblk + map_len);
+			ex->ee_len = cpu_to_le16(ee_len - map_len);
 			ext4_ext_mark_uninitialized(ex); /* Restore the flag */
 
-			/* Extend prev_ex by 'write_len' blocks */
-			prev_ex->ee_len = cpu_to_le16(prev_len + write_len);
+			/* Extend abut_ex by 'map_len' blocks */
+			abut_ex->ee_len = cpu_to_le16(prev_len + map_len);
 
-			/* Mark the block containing both extents as dirty */
-			ext4_ext_dirty(handle, inode, path + depth);
+			/* Result: number of initialized blocks past m_lblk */
+			allocated = map_len;
+		}
+	} else if (((map->m_lblk + map_len) == (ee_block + ee_len)) &&
+		   (map_len < ee_len) &&	/*L1*/
+		   ex < EXT_LAST_EXTENT(eh)) {	/*L2*/
+		/* See if we can merge right */
+		ext4_lblk_t next_lblk;
+		ext4_fsblk_t next_pblk, ee_pblk;
+		unsigned int next_len;
+
+		abut_ex = ex + 1;
+		next_lblk = le32_to_cpu(abut_ex->ee_block);
+		next_len = ext4_ext_get_actual_len(abut_ex);
+		next_pblk = ext4_ext_pblock(abut_ex);
+		ee_pblk = ext4_ext_pblock(ex);
 
-			/* Update path to point to the right extent */
-			path[depth].p_ext = prev_ex;
+		/*
+		 * A transfer of blocks from 'ex' to 'abut_ex' is allowed
+		 * upon those conditions:
+		 * - C1: abut_ex is initialized,
+		 * - C2: abut_ex is logically abutting ex,
+		 * - C3: abut_ex is physically abutting ex,
+		 * - C4: abut_ex can receive the additional blocks without
+		 *   overflowing the (initialized) length limit.
+		 */
+		if ((!ext4_ext_is_uninitialized(abut_ex)) &&		/*C1*/
+		    ((map->m_lblk + map_len) == next_lblk) &&		/*C2*/
+		    ((ee_pblk + ee_len) == next_pblk) &&		/*C3*/
+		    (next_len < (EXT_INIT_MAX_LEN - map_len))) {	/*C4*/
+			err = ext4_ext_get_access(handle, inode, path + depth);
+			if (err)
+				goto out;
+
+			trace_ext4_ext_convert_to_initialized_fastpath(inode,
+				map, ex, abut_ex);
+
+			/* Shift the start of abut_ex by 'map_len' blocks */
+			abut_ex->ee_block = cpu_to_le32(next_lblk - map_len);
+			ext4_ext_store_pblock(abut_ex, next_pblk - map_len);
+			ex->ee_len = cpu_to_le16(ee_len - map_len);
+			ext4_ext_mark_uninitialized(ex); /* Restore the flag */
+
+			/* Extend abut_ex by 'map_len' blocks */
+			abut_ex->ee_len = cpu_to_le16(next_len + map_len);
 
 			/* Result: number of initialized blocks past m_lblk */
-			allocated = write_len;
-			goto out;
+			allocated = map_len;
 		}
 	}
+	if (allocated) {
+		/* Mark the block containing both extents as dirty */
+		ext4_ext_dirty(handle, inode, path + depth);
+
+		/* Update path to point to the right extent */
+		path[depth].p_ext = abut_ex;
+		goto out;
+	} else
+		allocated = ee_len - (map->m_lblk - ee_block);
 
 	WARN_ON(map->m_lblk < ee_block);
 	/*
@@ -3272,7 +3380,7 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
 		if (err)
 			goto out;
 		zero_ex.ee_block = ex->ee_block;
-		zero_ex.ee_len = ext4_ext_get_actual_len(ex);
+		zero_ex.ee_len = cpu_to_le16(ext4_ext_get_actual_len(ex));
 		ext4_ext_store_pblock(&zero_ex, ext4_ext_pblock(ex));
 
 		err = ext4_ext_get_access(handle, inode, path + depth);
@@ -4254,48 +4362,13 @@ out3:
 	return err ? err : allocated;
 }
 
-void ext4_ext_truncate(struct inode *inode)
+void ext4_ext_truncate(handle_t *handle, struct inode *inode)
 {
-	struct address_space *mapping = inode->i_mapping;
 	struct super_block *sb = inode->i_sb;
 	ext4_lblk_t last_block;
-	handle_t *handle;
-	loff_t page_len;
 	int err = 0;
 
 	/*
-	 * finish any pending end_io work so we won't run the risk of
-	 * converting any truncated blocks to initialized later
-	 */
-	ext4_flush_unwritten_io(inode);
-
-	/*
-	 * probably first extent we're gonna free will be last in block
-	 */
-	err = ext4_writepage_trans_blocks(inode);
-	handle = ext4_journal_start(inode, EXT4_HT_TRUNCATE, err);
-	if (IS_ERR(handle))
-		return;
-
-	if (inode->i_size % PAGE_CACHE_SIZE != 0) {
-		page_len = PAGE_CACHE_SIZE -
-			(inode->i_size & (PAGE_CACHE_SIZE - 1));
-
-		err = ext4_discard_partial_page_buffers(handle,
-			mapping, inode->i_size, page_len, 0);
-
-		if (err)
-			goto out_stop;
-	}
-
-	if (ext4_orphan_add(handle, inode))
-		goto out_stop;
-
-	down_write(&EXT4_I(inode)->i_data_sem);
-
-	ext4_discard_preallocations(inode);
-
-	/*
 	 * TODO: optimization is possible here.
 	 * Probably we need not scan at all,
 	 * because page truncation is enough.
@@ -4310,29 +4383,6 @@ void ext4_ext_truncate(struct inode *inode)
 	err = ext4_es_remove_extent(inode, last_block,
 				    EXT_MAX_BLOCKS - last_block);
 	err = ext4_ext_remove_space(inode, last_block, EXT_MAX_BLOCKS - 1);
-
-	/* In a multi-transaction truncate, we only make the final
-	 * transaction synchronous.
-	 */
-	if (IS_SYNC(inode))
-		ext4_handle_sync(handle);
-
-	up_write(&EXT4_I(inode)->i_data_sem);
-
-out_stop:
-	/*
-	 * If this was a simple ftruncate() and the file will remain alive,
-	 * then we need to clear up the orphan record which we created above.
-	 * However, if this was a real unlink then we were called by
-	 * ext4_delete_inode(), and we allow that function to clean up the
-	 * orphan info for us.
-	 */
-	if (inode->i_nlink)
-		ext4_orphan_del(handle, inode);
-
-	inode->i_mtime = inode->i_ctime = ext4_current_time(inode);
-	ext4_mark_inode_dirty(handle, inode);
-	ext4_journal_stop(handle);
 }
 
 static void ext4_falloc_update_inode(struct inode *inode,
@@ -4620,187 +4670,6 @@ static int ext4_xattr_fiemap(struct inode *inode,
 	return (error < 0 ? error : 0);
 }
 
-/*
- * ext4_ext_punch_hole
- *
- * Punches a hole of "length" bytes in a file starting
- * at byte "offset"
- *
- * @inode:  The inode of the file to punch a hole in
- * @offset: The starting byte offset of the hole
- * @length: The length of the hole
- *
- * Returns the number of blocks removed or negative on err
- */
-int ext4_ext_punch_hole(struct file *file, loff_t offset, loff_t length)
-{
-	struct inode *inode = file_inode(file);
-	struct super_block *sb = inode->i_sb;
-	ext4_lblk_t first_block, stop_block;
-	struct address_space *mapping = inode->i_mapping;
-	handle_t *handle;
-	loff_t first_page, last_page, page_len;
-	loff_t first_page_offset, last_page_offset;
-	int credits, err = 0;
-
-	/*
-	 * Write out all dirty pages to avoid race conditions
-	 * Then release them.
-	 */
-	if (mapping->nrpages && mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) {
-		err = filemap_write_and_wait_range(mapping,
-			offset, offset + length - 1);
-
-		if (err)
-			return err;
-	}
-
-	mutex_lock(&inode->i_mutex);
-	/* It's not possible punch hole on append only file */
-	if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) {
-		err = -EPERM;
-		goto out_mutex;
-	}
-	if (IS_SWAPFILE(inode)) {
-		err = -ETXTBSY;
-		goto out_mutex;
-	}
-
-	/* No need to punch hole beyond i_size */
-	if (offset >= inode->i_size)
-		goto out_mutex;
-
-	/*
-	 * If the hole extends beyond i_size, set the hole
-	 * to end after the page that contains i_size
-	 */
-	if (offset + length > inode->i_size) {
-		length = inode->i_size +
-		   PAGE_CACHE_SIZE - (inode->i_size & (PAGE_CACHE_SIZE - 1)) -
-		   offset;
-	}
-
-	first_page = (offset + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
-	last_page = (offset + length) >> PAGE_CACHE_SHIFT;
-
-	first_page_offset = first_page << PAGE_CACHE_SHIFT;
-	last_page_offset = last_page << PAGE_CACHE_SHIFT;
-
-	/* Now release the pages */
-	if (last_page_offset > first_page_offset) {
-		truncate_pagecache_range(inode, first_page_offset,
-					 last_page_offset - 1);
-	}
-
-	/* Wait all existing dio workers, newcomers will block on i_mutex */
-	ext4_inode_block_unlocked_dio(inode);
-	err = ext4_flush_unwritten_io(inode);
-	if (err)
-		goto out_dio;
-	inode_dio_wait(inode);
-
-	credits = ext4_writepage_trans_blocks(inode);
-	handle = ext4_journal_start(inode, EXT4_HT_TRUNCATE, credits);
-	if (IS_ERR(handle)) {
-		err = PTR_ERR(handle);
-		goto out_dio;
-	}
-
-
-	/*
-	 * Now we need to zero out the non-page-aligned data in the
-	 * pages at the start and tail of the hole, and unmap the buffer
-	 * heads for the block aligned regions of the page that were
-	 * completely zeroed.
-	 */
-	if (first_page > last_page) {
-		/*
-		 * If the file space being truncated is contained within a page
-		 * just zero out and unmap the middle of that page
-		 */
-		err = ext4_discard_partial_page_buffers(handle,
-			mapping, offset, length, 0);
-
-		if (err)
-			goto out;
-	} else {
-		/*
-		 * zero out and unmap the partial page that contains
-		 * the start of the hole
-		 */
-		page_len  = first_page_offset - offset;
-		if (page_len > 0) {
-			err = ext4_discard_partial_page_buffers(handle, mapping,
-						   offset, page_len, 0);
-			if (err)
-				goto out;
-		}
-
-		/*
-		 * zero out and unmap the partial page that contains
-		 * the end of the hole
-		 */
-		page_len = offset + length - last_page_offset;
-		if (page_len > 0) {
-			err = ext4_discard_partial_page_buffers(handle, mapping,
-					last_page_offset, page_len, 0);
-			if (err)
-				goto out;
-		}
-	}
-
-	/*
-	 * If i_size is contained in the last page, we need to
-	 * unmap and zero the partial page after i_size
-	 */
-	if (inode->i_size >> PAGE_CACHE_SHIFT == last_page &&
-	   inode->i_size % PAGE_CACHE_SIZE != 0) {
-
-		page_len = PAGE_CACHE_SIZE -
-			(inode->i_size & (PAGE_CACHE_SIZE - 1));
-
-		if (page_len > 0) {
-			err = ext4_discard_partial_page_buffers(handle,
-			  mapping, inode->i_size, page_len, 0);
-
-			if (err)
-				goto out;
-		}
-	}
-
-	first_block = (offset + sb->s_blocksize - 1) >>
-		EXT4_BLOCK_SIZE_BITS(sb);
-	stop_block = (offset + length) >> EXT4_BLOCK_SIZE_BITS(sb);
-
-	/* If there are no blocks to remove, return now */
-	if (first_block >= stop_block)
-		goto out;
-
-	down_write(&EXT4_I(inode)->i_data_sem);
-	ext4_discard_preallocations(inode);
-
-	err = ext4_es_remove_extent(inode, first_block,
-				    stop_block - first_block);
-	err = ext4_ext_remove_space(inode, first_block, stop_block - 1);
-
-	ext4_discard_preallocations(inode);
-
-	if (IS_SYNC(inode))
-		ext4_handle_sync(handle);
-
-	up_write(&EXT4_I(inode)->i_data_sem);
-
-out:
-	inode->i_mtime = inode->i_ctime = ext4_current_time(inode);
-	ext4_mark_inode_dirty(handle, inode);
-	ext4_journal_stop(handle);
-out_dio:
-	ext4_inode_resume_unlocked_dio(inode);
-out_mutex:
-	mutex_unlock(&inode->i_mutex);
-	return err;
-}
-
 int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
 		__u64 start, __u64 len)
 {
@@ -4846,3 +4715,62 @@ int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
 
 	return error;
 }
+
+/*
+ * Migrate a simple extent-based inode to use the i_blocks[] array
+ */
+int ext4_ind_migrate(struct inode *inode)
+{
+	struct ext4_extent_header	*eh;
+	struct ext4_super_block		*es = EXT4_SB(inode->i_sb)->s_es;
+	struct ext4_inode_info		*ei = EXT4_I(inode);
+	struct ext4_extent		*ex;
+	unsigned int			i, len;
+	ext4_fsblk_t			blk;
+	handle_t			*handle;
+	int				ret;
+
+	if (!EXT4_HAS_INCOMPAT_FEATURE(inode->i_sb,
+				       EXT4_FEATURE_INCOMPAT_EXTENTS) ||
+	    (!ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)))
+		return -EINVAL;
+
+	down_write(&EXT4_I(inode)->i_data_sem);
+	ret = ext4_ext_check_inode(inode);
+	if (ret)
+		goto errout;
+
+	eh = ext_inode_hdr(inode);
+	ex  = EXT_FIRST_EXTENT(eh);
+	if (ext4_blocks_count(es) > EXT4_MAX_BLOCK_FILE_PHYS ||
+	    eh->eh_depth != 0 || eh->eh_entries > 1) {
+		ret = -EOPNOTSUPP;
+		goto errout;
+	}
+	if (eh->eh_entries == 0)
+		blk = len = 0;
+	else {
+		len = le16_to_cpu(ex->ee_len);
+		blk = ext4_ext_pblock(ex);
+		if (len > EXT4_NDIR_BLOCKS) {
+			ret = -EOPNOTSUPP;
+			goto errout;
+		}
+	}
+
+	handle = ext4_journal_start(inode, EXT4_HT_MIGRATE, 1);
+	if (IS_ERR(handle)) {
+		ret = PTR_ERR(handle);
+		goto errout;
+	}
+
+	ext4_clear_inode_flag(inode, EXT4_INODE_EXTENTS);
+	memset(ei->i_data, 0, sizeof(ei->i_data));
+	for (i=0; i < len; i++)
+		ei->i_data[i] = cpu_to_le32(blk++);
+	ext4_mark_inode_dirty(handle, inode);
+	ext4_journal_stop(handle);
+errout:
+	up_write(&EXT4_I(inode)->i_data_sem);
+	return ret;
+}
diff --git a/fs/ext4/file.c b/fs/ext4/file.c
index 64848b5..4959e29 100644
--- a/fs/ext4/file.c
+++ b/fs/ext4/file.c
@@ -23,6 +23,7 @@
 #include <linux/jbd2.h>
 #include <linux/mount.h>
 #include <linux/path.h>
+#include <linux/aio.h>
 #include <linux/quotaops.h>
 #include <linux/pagevec.h>
 #include "ext4.h"
diff --git a/fs/ext4/fsync.c b/fs/ext4/fsync.c
index 3278e64..e0ba8a4 100644
--- a/fs/ext4/fsync.c
+++ b/fs/ext4/fsync.c
@@ -166,8 +166,7 @@ int ext4_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
 	if (journal->j_flags & JBD2_BARRIER &&
 	    !jbd2_trans_will_send_data_barrier(journal, commit_tid))
 		needs_barrier = true;
-	jbd2_log_start_commit(journal, commit_tid);
-	ret = jbd2_log_wait_commit(journal, commit_tid);
+	ret = jbd2_complete_transaction(journal, commit_tid);
 	if (needs_barrier) {
 		err = blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL);
 		if (!ret)
diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c
index b505a14..b8d5d35 100644
--- a/fs/ext4/indirect.c
+++ b/fs/ext4/indirect.c
@@ -20,6 +20,7 @@
  *	(sct@redhat.com), 1993, 1998
  */
 
+#include <linux/aio.h>
 #include "ext4_jbd2.h"
 #include "truncate.h"
 #include "ext4_extents.h"	/* Needed for EXT_MAX_BLOCKS */
@@ -292,131 +293,6 @@ static int ext4_blks_to_allocate(Indirect *branch, int k, unsigned int blks,
 }
 
 /**
- *	ext4_alloc_blocks: multiple allocate blocks needed for a branch
- *	@handle: handle for this transaction
- *	@inode: inode which needs allocated blocks
- *	@iblock: the logical block to start allocated at
- *	@goal: preferred physical block of allocation
- *	@indirect_blks: the number of blocks need to allocate for indirect
- *			blocks
- *	@blks: number of desired blocks
- *	@new_blocks: on return it will store the new block numbers for
- *	the indirect blocks(if needed) and the first direct block,
- *	@err: on return it will store the error code
- *
- *	This function will return the number of blocks allocated as
- *	requested by the passed-in parameters.
- */
-static int ext4_alloc_blocks(handle_t *handle, struct inode *inode,
-			     ext4_lblk_t iblock, ext4_fsblk_t goal,
-			     int indirect_blks, int blks,
-			     ext4_fsblk_t new_blocks[4], int *err)
-{
-	struct ext4_allocation_request ar;
-	int target, i;
-	unsigned long count = 0, blk_allocated = 0;
-	int index = 0;
-	ext4_fsblk_t current_block = 0;
-	int ret = 0;
-
-	/*
-	 * Here we try to allocate the requested multiple blocks at once,
-	 * on a best-effort basis.
-	 * To build a branch, we should allocate blocks for
-	 * the indirect blocks(if not allocated yet), and at least
-	 * the first direct block of this branch.  That's the
-	 * minimum number of blocks need to allocate(required)
-	 */
-	/* first we try to allocate the indirect blocks */
-	target = indirect_blks;
-	while (target > 0) {
-		count = target;
-		/* allocating blocks for indirect blocks and direct blocks */
-		current_block = ext4_new_meta_blocks(handle, inode, goal,
-						     0, &count, err);
-		if (*err)
-			goto failed_out;
-
-		if (unlikely(current_block + count > EXT4_MAX_BLOCK_FILE_PHYS)) {
-			EXT4_ERROR_INODE(inode,
-					 "current_block %llu + count %lu > %d!",
-					 current_block, count,
-					 EXT4_MAX_BLOCK_FILE_PHYS);
-			*err = -EIO;
-			goto failed_out;
-		}
-
-		target -= count;
-		/* allocate blocks for indirect blocks */
-		while (index < indirect_blks && count) {
-			new_blocks[index++] = current_block++;
-			count--;
-		}
-		if (count > 0) {
-			/*
-			 * save the new block number
-			 * for the first direct block
-			 */
-			new_blocks[index] = current_block;
-			WARN(1, KERN_INFO "%s returned more blocks than "
-						"requested\n", __func__);
-			break;
-		}
-	}
-
-	target = blks - count ;
-	blk_allocated = count;
-	if (!target)
-		goto allocated;
-	/* Now allocate data blocks */
-	memset(&ar, 0, sizeof(ar));
-	ar.inode = inode;
-	ar.goal = goal;
-	ar.len = target;
-	ar.logical = iblock;
-	if (S_ISREG(inode->i_mode))
-		/* enable in-core preallocation only for regular files */
-		ar.flags = EXT4_MB_HINT_DATA;
-
-	current_block = ext4_mb_new_blocks(handle, &ar, err);
-	if (unlikely(current_block + ar.len > EXT4_MAX_BLOCK_FILE_PHYS)) {
-		EXT4_ERROR_INODE(inode,
-				 "current_block %llu + ar.len %d > %d!",
-				 current_block, ar.len,
-				 EXT4_MAX_BLOCK_FILE_PHYS);
-		*err = -EIO;
-		goto failed_out;
-	}
-
-	if (*err && (target == blks)) {
-		/*
-		 * if the allocation failed and we didn't allocate
-		 * any blocks before
-		 */
-		goto failed_out;
-	}
-	if (!*err) {
-		if (target == blks) {
-			/*
-			 * save the new block number
-			 * for the first direct block
-			 */
-			new_blocks[index] = current_block;
-		}
-		blk_allocated += ar.len;
-	}
-allocated:
-	/* total number of blocks allocated for direct blocks */
-	ret = blk_allocated;
-	*err = 0;
-	return ret;
-failed_out:
-	for (i = 0; i < index; i++)
-		ext4_free_blocks(handle, inode, NULL, new_blocks[i], 1, 0);
-	return ret;
-}
-
-/**
  *	ext4_alloc_branch - allocate and set up a chain of blocks.
  *	@handle: handle for this transaction
  *	@inode: owner
@@ -448,60 +324,59 @@ static int ext4_alloc_branch(handle_t *handle, struct inode *inode,
 			     int *blks, ext4_fsblk_t goal,
 			     ext4_lblk_t *offsets, Indirect *branch)
 {
-	int blocksize = inode->i_sb->s_blocksize;
-	int i, n = 0;
-	int err = 0;
-	struct buffer_head *bh;
-	int num;
-	ext4_fsblk_t new_blocks[4];
-	ext4_fsblk_t current_block;
-
-	num = ext4_alloc_blocks(handle, inode, iblock, goal, indirect_blks,
-				*blks, new_blocks, &err);
-	if (err)
-		return err;
+	struct ext4_allocation_request	ar;
+	struct buffer_head *		bh;
+	ext4_fsblk_t			b, new_blocks[4];
+	__le32				*p;
+	int				i, j, err, len = 1;
 
-	branch[0].key = cpu_to_le32(new_blocks[0]);
 	/*
-	 * metadata blocks and data blocks are allocated.
+	 * Set up for the direct block allocation
 	 */
-	for (n = 1; n <= indirect_blks;  n++) {
-		/*
-		 * Get buffer_head for parent block, zero it out
-		 * and set the pointer to new one, then send
-		 * parent to disk.
-		 */
-		bh = sb_getblk(inode->i_sb, new_blocks[n-1]);
+	memset(&ar, 0, sizeof(ar));
+	ar.inode = inode;
+	ar.len = *blks;
+	ar.logical = iblock;
+	if (S_ISREG(inode->i_mode))
+		ar.flags = EXT4_MB_HINT_DATA;
+
+	for (i = 0; i <= indirect_blks; i++) {
+		if (i == indirect_blks) {
+			ar.goal = goal;
+			new_blocks[i] = ext4_mb_new_blocks(handle, &ar, &err);
+		} else
+			goal = new_blocks[i] = ext4_new_meta_blocks(handle, inode,
+							goal, 0, NULL, &err);
+		if (err) {
+			i--;
+			goto failed;
+		}
+		branch[i].key = cpu_to_le32(new_blocks[i]);
+		if (i == 0)
+			continue;
+
+		bh = branch[i].bh = sb_getblk(inode->i_sb, new_blocks[i-1]);
 		if (unlikely(!bh)) {
 			err = -ENOMEM;
 			goto failed;
 		}
-
-		branch[n].bh = bh;
 		lock_buffer(bh);
 		BUFFER_TRACE(bh, "call get_create_access");
 		err = ext4_journal_get_create_access(handle, bh);
 		if (err) {
-			/* Don't brelse(bh) here; it's done in
-			 * ext4_journal_forget() below */
 			unlock_buffer(bh);
 			goto failed;
 		}
 
-		memset(bh->b_data, 0, blocksize);
-		branch[n].p = (__le32 *) bh->b_data + offsets[n];
-		branch[n].key = cpu_to_le32(new_blocks[n]);
-		*branch[n].p = branch[n].key;
-		if (n == indirect_blks) {
-			current_block = new_blocks[n];
-			/*
-			 * End of chain, update the last new metablock of
-			 * the chain to point to the new allocated
-			 * data blocks numbers
-			 */
-			for (i = 1; i < num; i++)
-				*(branch[n].p + i) = cpu_to_le32(++current_block);
-		}
+		memset(bh->b_data, 0, bh->b_size);
+		p = branch[i].p = (__le32 *) bh->b_data + offsets[i];
+		b = new_blocks[i];
+
+		if (i == indirect_blks)
+			len = ar.len;
+		for (j = 0; j < len; j++)
+			*p++ = cpu_to_le32(b++);
+
 		BUFFER_TRACE(bh, "marking uptodate");
 		set_buffer_uptodate(bh);
 		unlock_buffer(bh);
@@ -511,25 +386,16 @@ static int ext4_alloc_branch(handle_t *handle, struct inode *inode,
 		if (err)
 			goto failed;
 	}
-	*blks = num;
-	return err;
+	*blks = ar.len;
+	return 0;
 failed:
-	/* Allocation failed, free what we already allocated */
-	ext4_free_blocks(handle, inode, NULL, new_blocks[0], 1, 0);
-	for (i = 1; i <= n ; i++) {
-		/*
-		 * branch[i].bh is newly allocated, so there is no
-		 * need to revoke the block, which is why we don't
-		 * need to set EXT4_FREE_BLOCKS_METADATA.
-		 */
-		ext4_free_blocks(handle, inode, NULL, new_blocks[i], 1,
-				 EXT4_FREE_BLOCKS_FORGET);
+	for (; i >= 0; i--) {
+		if (i != indirect_blks && branch[i].bh)
+			ext4_forget(handle, 1, inode, branch[i].bh,
+				    branch[i].bh->b_blocknr);
+		ext4_free_blocks(handle, inode, NULL, new_blocks[i],
+				 (i == indirect_blks) ? ar.len : 1, 0);
 	}
-	for (i = n+1; i < indirect_blks; i++)
-		ext4_free_blocks(handle, inode, NULL, new_blocks[i], 1, 0);
-
-	ext4_free_blocks(handle, inode, NULL, new_blocks[i], num, 0);
-
 	return err;
 }
 
@@ -941,26 +807,9 @@ int ext4_ind_trans_blocks(struct inode *inode, int nrblocks, int chunk)
  * be able to restart the transaction at a conventient checkpoint to make
  * sure we don't overflow the journal.
  *
- * start_transaction gets us a new handle for a truncate transaction,
- * and extend_transaction tries to extend the existing one a bit.  If
+ * Try to extend this transaction for the purposes of truncation.  If
  * extend fails, we need to propagate the failure up and restart the
  * transaction in the top-level truncate loop. --sct
- */
-static handle_t *start_transaction(struct inode *inode)
-{
-	handle_t *result;
-
-	result = ext4_journal_start(inode, EXT4_HT_TRUNCATE,
-				    ext4_blocks_for_truncate(inode));
-	if (!IS_ERR(result))
-		return result;
-
-	ext4_std_error(inode->i_sb, PTR_ERR(result));
-	return result;
-}
-
-/*
- * Try to extend this transaction for the purposes of truncation.
  *
  * Returns 0 if we managed to create more room.  If we can't create more
  * room, and the transaction must be restarted we return 1.
@@ -1353,68 +1202,30 @@ static void ext4_free_branches(handle_t *handle, struct inode *inode,
 	}
 }
 
-void ext4_ind_truncate(struct inode *inode)
+void ext4_ind_truncate(handle_t *handle, struct inode *inode)
 {
-	handle_t *handle;
 	struct ext4_inode_info *ei = EXT4_I(inode);
 	__le32 *i_data = ei->i_data;
 	int addr_per_block = EXT4_ADDR_PER_BLOCK(inode->i_sb);
-	struct address_space *mapping = inode->i_mapping;
 	ext4_lblk_t offsets[4];
 	Indirect chain[4];
 	Indirect *partial;
 	__le32 nr = 0;
 	int n = 0;
 	ext4_lblk_t last_block, max_block;
-	loff_t page_len;
 	unsigned blocksize = inode->i_sb->s_blocksize;
-	int err;
-
-	handle = start_transaction(inode);
-	if (IS_ERR(handle))
-		return;		/* AKPM: return what? */
 
 	last_block = (inode->i_size + blocksize-1)
 					>> EXT4_BLOCK_SIZE_BITS(inode->i_sb);
 	max_block = (EXT4_SB(inode->i_sb)->s_bitmap_maxbytes + blocksize-1)
 					>> EXT4_BLOCK_SIZE_BITS(inode->i_sb);
 
-	if (inode->i_size % PAGE_CACHE_SIZE != 0) {
-		page_len = PAGE_CACHE_SIZE -
-			(inode->i_size & (PAGE_CACHE_SIZE - 1));
-
-		err = ext4_discard_partial_page_buffers(handle,
-			mapping, inode->i_size, page_len, 0);
-
-		if (err)
-			goto out_stop;
-	}
-
 	if (last_block != max_block) {
 		n = ext4_block_to_path(inode, last_block, offsets, NULL);
 		if (n == 0)
-			goto out_stop;	/* error */
+			return;
 	}
 
-	/*
-	 * OK.  This truncate is going to happen.  We add the inode to the
-	 * orphan list, so that if this truncate spans multiple transactions,
-	 * and we crash, we will resume the truncate when the filesystem
-	 * recovers.  It also marks the inode dirty, to catch the new size.
-	 *
-	 * Implication: the file must always be in a sane, consistent
-	 * truncatable state while each transaction commits.
-	 */
-	if (ext4_orphan_add(handle, inode))
-		goto out_stop;
-
-	/*
-	 * From here we block out all ext4_get_block() callers who want to
-	 * modify the block allocation tree.
-	 */
-	down_write(&ei->i_data_sem);
-
-	ext4_discard_preallocations(inode);
 	ext4_es_remove_extent(inode, last_block, EXT_MAX_BLOCKS - last_block);
 
 	/*
@@ -1431,7 +1242,7 @@ void ext4_ind_truncate(struct inode *inode)
 		 * It is unnecessary to free any data blocks if last_block is
 		 * equal to the indirect block limit.
 		 */
-		goto out_unlock;
+		return;
 	} else if (n == 1) {		/* direct blocks */
 		ext4_free_data(handle, inode, NULL, i_data+offsets[0],
 			       i_data + EXT4_NDIR_BLOCKS);
@@ -1491,31 +1302,6 @@ do_indirects:
 	case EXT4_TIND_BLOCK:
 		;
 	}
-
-out_unlock:
-	up_write(&ei->i_data_sem);
-	inode->i_mtime = inode->i_ctime = ext4_current_time(inode);
-	ext4_mark_inode_dirty(handle, inode);
-
-	/*
-	 * In a multi-transaction truncate, we only make the final transaction
-	 * synchronous
-	 */
-	if (IS_SYNC(inode))
-		ext4_handle_sync(handle);
-out_stop:
-	/*
-	 * If this was a simple ftruncate(), and the file will remain alive
-	 * then we need to clear up the orphan record which we created above.
-	 * However, if this was a real unlink then we were called by
-	 * ext4_delete_inode(), and we allow that function to clean up the
-	 * orphan info for us.
-	 */
-	if (inode->i_nlink)
-		ext4_orphan_del(handle, inode);
-
-	ext4_journal_stop(handle);
-	trace_ext4_truncate_exit(inode);
 }
 
 static int free_hole_blocks(handle_t *handle, struct inode *inode,
@@ -1539,9 +1325,9 @@ static int free_hole_blocks(handle_t *handle, struct inode *inode,
 		blk = *i_data;
 		if (level > 0) {
 			ext4_lblk_t first2;
-			bh = sb_bread(inode->i_sb, blk);
+			bh = sb_bread(inode->i_sb, le32_to_cpu(blk));
 			if (!bh) {
-				EXT4_ERROR_INODE_BLOCK(inode, blk,
+				EXT4_ERROR_INODE_BLOCK(inode, le32_to_cpu(blk),
 						       "Read failure");
 				return -EIO;
 			}
@@ -1569,8 +1355,8 @@ err:
 	return ret;
 }
 
-static int ext4_free_hole_blocks(handle_t *handle, struct inode *inode,
-				 ext4_lblk_t first, ext4_lblk_t stop)
+int ext4_free_hole_blocks(handle_t *handle, struct inode *inode,
+			  ext4_lblk_t first, ext4_lblk_t stop)
 {
 	int addr_per_block = EXT4_ADDR_PER_BLOCK(inode->i_sb);
 	int level, ret = 0;
@@ -1604,157 +1390,3 @@ err:
 	return ret;
 }
 
-int ext4_ind_punch_hole(struct file *file, loff_t offset, loff_t length)
-{
-	struct inode *inode = file_inode(file);
-	struct super_block *sb = inode->i_sb;
-	ext4_lblk_t first_block, stop_block;
-	struct address_space *mapping = inode->i_mapping;
-	handle_t *handle = NULL;
-	loff_t first_page, last_page, page_len;
-	loff_t first_page_offset, last_page_offset;
-	int err = 0;
-
-	/*
-	 * Write out all dirty pages to avoid race conditions
-	 * Then release them.
-	 */
-	if (mapping->nrpages && mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) {
-		err = filemap_write_and_wait_range(mapping,
-			offset, offset + length - 1);
-		if (err)
-			return err;
-	}
-
-	mutex_lock(&inode->i_mutex);
-	/* It's not possible punch hole on append only file */
-	if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) {
-		err = -EPERM;
-		goto out_mutex;
-	}
-	if (IS_SWAPFILE(inode)) {
-		err = -ETXTBSY;
-		goto out_mutex;
-	}
-
-	/* No need to punch hole beyond i_size */
-	if (offset >= inode->i_size)
-		goto out_mutex;
-
-	/*
-	 * If the hole extents beyond i_size, set the hole
-	 * to end after the page that contains i_size
-	 */
-	if (offset + length > inode->i_size) {
-		length = inode->i_size +
-		    PAGE_CACHE_SIZE - (inode->i_size & (PAGE_CACHE_SIZE - 1)) -
-		    offset;
-	}
-
-	first_page = (offset + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
-	last_page = (offset + length) >> PAGE_CACHE_SHIFT;
-
-	first_page_offset = first_page << PAGE_CACHE_SHIFT;
-	last_page_offset = last_page << PAGE_CACHE_SHIFT;
-
-	/* Now release the pages */
-	if (last_page_offset > first_page_offset) {
-		truncate_pagecache_range(inode, first_page_offset,
-					 last_page_offset - 1);
-	}
-
-	/* Wait all existing dio works, newcomers will block on i_mutex */
-	inode_dio_wait(inode);
-
-	handle = start_transaction(inode);
-	if (IS_ERR(handle))
-		goto out_mutex;
-
-	/*
-	 * Now we need to zero out the non-page-aligned data in the
-	 * pages at the start and tail of the hole, and unmap the buffer
-	 * heads for the block aligned regions of the page that were
-	 * completely zerod.
-	 */
-	if (first_page > last_page) {
-		/*
-		 * If the file space being truncated is contained within a page
-		 * just zero out and unmap the middle of that page
-		 */
-		err = ext4_discard_partial_page_buffers(handle,
-			mapping, offset, length, 0);
-		if (err)
-			goto out;
-	} else {
-		/*
-		 * Zero out and unmap the paritial page that contains
-		 * the start of the hole
-		 */
-		page_len = first_page_offset - offset;
-		if (page_len > 0) {
-			err = ext4_discard_partial_page_buffers(handle, mapping,
-							offset, page_len, 0);
-			if (err)
-				goto out;
-		}
-
-		/*
-		 * Zero out and unmap the partial page that contains
-		 * the end of the hole
-		 */
-		page_len = offset + length - last_page_offset;
-		if (page_len > 0) {
-			err = ext4_discard_partial_page_buffers(handle, mapping,
-						last_page_offset, page_len, 0);
-			if (err)
-				goto out;
-		}
-	}
-
-	/*
-	 * If i_size contained in the last page, we need to
-	 * unmap and zero the paritial page after i_size
-	 */
-	if (inode->i_size >> PAGE_CACHE_SHIFT == last_page &&
-	    inode->i_size % PAGE_CACHE_SIZE != 0) {
-		page_len = PAGE_CACHE_SIZE -
-			(inode->i_size & (PAGE_CACHE_SIZE - 1));
-		if (page_len > 0) {
-			err = ext4_discard_partial_page_buffers(handle,
-				mapping, inode->i_size, page_len, 0);
-			if (err)
-				goto out;
-		}
-	}
-
-	first_block = (offset + sb->s_blocksize - 1) >>
-		EXT4_BLOCK_SIZE_BITS(sb);
-	stop_block = (offset + length) >> EXT4_BLOCK_SIZE_BITS(sb);
-
-	if (first_block >= stop_block)
-		goto out;
-
-	down_write(&EXT4_I(inode)->i_data_sem);
-	ext4_discard_preallocations(inode);
-
-	err = ext4_es_remove_extent(inode, first_block,
-				    stop_block - first_block);
-	err = ext4_free_hole_blocks(handle, inode, first_block, stop_block);
-
-	ext4_discard_preallocations(inode);
-
-	if (IS_SYNC(inode))
-		ext4_handle_sync(handle);
-
-	up_write(&EXT4_I(inode)->i_data_sem);
-
-out:
-	inode->i_mtime = inode->i_ctime = ext4_current_time(inode);
-	ext4_mark_inode_dirty(handle, inode);
-	ext4_journal_stop(handle);
-
-out_mutex:
-	mutex_unlock(&inode->i_mutex);
-
-	return err;
-}
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index b3a5213..3d74813 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -37,6 +37,7 @@
 #include <linux/printk.h>
 #include <linux/slab.h>
 #include <linux/ratelimit.h>
+#include <linux/aio.h>
 
 #include "ext4_jbd2.h"
 #include "xattr.h"
@@ -210,8 +211,7 @@ void ext4_evict_inode(struct inode *inode)
 			journal_t *journal = EXT4_SB(inode->i_sb)->s_journal;
 			tid_t commit_tid = EXT4_I(inode)->i_datasync_tid;
 
-			jbd2_log_start_commit(journal, commit_tid);
-			jbd2_log_wait_commit(journal, commit_tid);
+			jbd2_complete_transaction(journal, commit_tid);
 			filemap_write_and_wait(&inode->i_data);
 		}
 		truncate_inode_pages(&inode->i_data, 0);
@@ -1087,14 +1087,32 @@ static int write_end_fn(handle_t *handle, struct buffer_head *bh)
 	return ext4_handle_dirty_metadata(handle, NULL, bh);
 }
 
-static int ext4_generic_write_end(struct file *file,
-				  struct address_space *mapping,
-				  loff_t pos, unsigned len, unsigned copied,
-				  struct page *page, void *fsdata)
+/*
+ * We need to pick up the new inode size which generic_commit_write gave us
+ * `file' can be NULL - eg, when called from page_symlink().
+ *
+ * ext4 never places buffers on inode->i_mapping->private_list.  metadata
+ * buffers are managed internally.
+ */
+static int ext4_write_end(struct file *file,
+			  struct address_space *mapping,
+			  loff_t pos, unsigned len, unsigned copied,
+			  struct page *page, void *fsdata)
 {
-	int i_size_changed = 0;
-	struct inode *inode = mapping->host;
 	handle_t *handle = ext4_journal_current_handle();
+	struct inode *inode = mapping->host;
+	int ret = 0, ret2;
+	int i_size_changed = 0;
+
+	trace_ext4_write_end(inode, pos, len, copied);
+	if (ext4_test_inode_state(inode, EXT4_STATE_ORDERED_MODE)) {
+		ret = ext4_jbd2_file_inode(handle, inode);
+		if (ret) {
+			unlock_page(page);
+			page_cache_release(page);
+			goto errout;
+		}
+	}
 
 	if (ext4_has_inline_data(inode))
 		copied = ext4_write_inline_data_end(inode, pos, len,
@@ -1105,7 +1123,7 @@ static int ext4_generic_write_end(struct file *file,
 
 	/*
 	 * No need to use i_size_read() here, the i_size
-	 * cannot change under us because we hold i_mutex.
+	 * cannot change under us because we hole i_mutex.
 	 *
 	 * But it's important to update i_size while still holding page lock:
 	 * page writeout could otherwise come in and zero beyond i_size.
@@ -1115,10 +1133,10 @@ static int ext4_generic_write_end(struct file *file,
 		i_size_changed = 1;
 	}
 
-	if (pos + copied >  EXT4_I(inode)->i_disksize) {
+	if (pos + copied > EXT4_I(inode)->i_disksize) {
 		/* We need to mark inode dirty even if
 		 * new_i_size is less that inode->i_size
-		 * bu greater than i_disksize.(hint delalloc)
+		 * but greater than i_disksize. (hint delalloc)
 		 */
 		ext4_update_i_disksize(inode, (pos + copied));
 		i_size_changed = 1;
@@ -1135,87 +1153,15 @@ static int ext4_generic_write_end(struct file *file,
 	if (i_size_changed)
 		ext4_mark_inode_dirty(handle, inode);
 
-	return copied;
-}
-
-/*
- * We need to pick up the new inode size which generic_commit_write gave us
- * `file' can be NULL - eg, when called from page_symlink().
- *
- * ext4 never places buffers on inode->i_mapping->private_list.  metadata
- * buffers are managed internally.
- */
-static int ext4_ordered_write_end(struct file *file,
-				  struct address_space *mapping,
-				  loff_t pos, unsigned len, unsigned copied,
-				  struct page *page, void *fsdata)
-{
-	handle_t *handle = ext4_journal_current_handle();
-	struct inode *inode = mapping->host;
-	int ret = 0, ret2;
-
-	trace_ext4_ordered_write_end(inode, pos, len, copied);
-	ret = ext4_jbd2_file_inode(handle, inode);
-
-	if (ret == 0) {
-		ret2 = ext4_generic_write_end(file, mapping, pos, len, copied,
-							page, fsdata);
-		copied = ret2;
-		if (pos + len > inode->i_size && ext4_can_truncate(inode))
-			/* if we have allocated more blocks and copied
-			 * less. We will have blocks allocated outside
-			 * inode->i_size. So truncate them
-			 */
-			ext4_orphan_add(handle, inode);
-		if (ret2 < 0)
-			ret = ret2;
-	} else {
-		unlock_page(page);
-		page_cache_release(page);
-	}
-
-	ret2 = ext4_journal_stop(handle);
-	if (!ret)
-		ret = ret2;
-
-	if (pos + len > inode->i_size) {
-		ext4_truncate_failed_write(inode);
-		/*
-		 * If truncate failed early the inode might still be
-		 * on the orphan list; we need to make sure the inode
-		 * is removed from the orphan list in that case.
-		 */
-		if (inode->i_nlink)
-			ext4_orphan_del(NULL, inode);
-	}
-
-
-	return ret ? ret : copied;
-}
-
-static int ext4_writeback_write_end(struct file *file,
-				    struct address_space *mapping,
-				    loff_t pos, unsigned len, unsigned copied,
-				    struct page *page, void *fsdata)
-{
-	handle_t *handle = ext4_journal_current_handle();
-	struct inode *inode = mapping->host;
-	int ret = 0, ret2;
-
-	trace_ext4_writeback_write_end(inode, pos, len, copied);
-	ret2 = ext4_generic_write_end(file, mapping, pos, len, copied,
-							page, fsdata);
-	copied = ret2;
+	if (copied < 0)
+		ret = copied;
 	if (pos + len > inode->i_size && ext4_can_truncate(inode))
 		/* if we have allocated more blocks and copied
 		 * less. We will have blocks allocated outside
 		 * inode->i_size. So truncate them
 		 */
 		ext4_orphan_add(handle, inode);
-
-	if (ret2 < 0)
-		ret = ret2;
-
+errout:
 	ret2 = ext4_journal_stop(handle);
 	if (!ret)
 		ret = ret2;
@@ -1670,22 +1616,25 @@ static void ext4_print_free_blocks(struct inode *inode)
 {
 	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
 	struct super_block *sb = inode->i_sb;
+	struct ext4_inode_info *ei = EXT4_I(inode);
 
 	ext4_msg(sb, KERN_CRIT, "Total free blocks count %lld",
 	       EXT4_C2B(EXT4_SB(inode->i_sb),
-			ext4_count_free_clusters(inode->i_sb)));
+			ext4_count_free_clusters(sb)));
 	ext4_msg(sb, KERN_CRIT, "Free/Dirty block details");
 	ext4_msg(sb, KERN_CRIT, "free_blocks=%lld",
-	       (long long) EXT4_C2B(EXT4_SB(inode->i_sb),
+	       (long long) EXT4_C2B(EXT4_SB(sb),
 		percpu_counter_sum(&sbi->s_freeclusters_counter)));
 	ext4_msg(sb, KERN_CRIT, "dirty_blocks=%lld",
-	       (long long) EXT4_C2B(EXT4_SB(inode->i_sb),
+	       (long long) EXT4_C2B(EXT4_SB(sb),
 		percpu_counter_sum(&sbi->s_dirtyclusters_counter)));
 	ext4_msg(sb, KERN_CRIT, "Block reservation details");
 	ext4_msg(sb, KERN_CRIT, "i_reserved_data_blocks=%u",
-		 EXT4_I(inode)->i_reserved_data_blocks);
+		 ei->i_reserved_data_blocks);
 	ext4_msg(sb, KERN_CRIT, "i_reserved_meta_blocks=%u",
-	       EXT4_I(inode)->i_reserved_meta_blocks);
+	       ei->i_reserved_meta_blocks);
+	ext4_msg(sb, KERN_CRIT, "i_allocated_meta_blocks=%u",
+	       ei->i_allocated_meta_blocks);
 	return;
 }
 
@@ -2818,18 +2767,9 @@ static int ext4_da_write_end(struct file *file,
 	unsigned long start, end;
 	int write_mode = (int)(unsigned long)fsdata;
 
-	if (write_mode == FALL_BACK_TO_NONDELALLOC) {
-		switch (ext4_inode_journal_mode(inode)) {
-		case EXT4_INODE_ORDERED_DATA_MODE:
-			return ext4_ordered_write_end(file, mapping, pos,
-					len, copied, page, fsdata);
-		case EXT4_INODE_WRITEBACK_DATA_MODE:
-			return ext4_writeback_write_end(file, mapping, pos,
-					len, copied, page, fsdata);
-		default:
-			BUG();
-		}
-	}
+	if (write_mode == FALL_BACK_TO_NONDELALLOC)
+		return ext4_write_end(file, mapping, pos,
+				      len, copied, page, fsdata);
 
 	trace_ext4_da_write_end(inode, pos, len, copied);
 	start = pos & (PAGE_CACHE_SIZE - 1);
@@ -3334,27 +3274,12 @@ static int ext4_journalled_set_page_dirty(struct page *page)
 	return __set_page_dirty_nobuffers(page);
 }
 
-static const struct address_space_operations ext4_ordered_aops = {
-	.readpage		= ext4_readpage,
-	.readpages		= ext4_readpages,
-	.writepage		= ext4_writepage,
-	.write_begin		= ext4_write_begin,
-	.write_end		= ext4_ordered_write_end,
-	.bmap			= ext4_bmap,
-	.invalidatepage		= ext4_invalidatepage,
-	.releasepage		= ext4_releasepage,
-	.direct_IO		= ext4_direct_IO,
-	.migratepage		= buffer_migrate_page,
-	.is_partially_uptodate  = block_is_partially_uptodate,
-	.error_remove_page	= generic_error_remove_page,
-};
-
-static const struct address_space_operations ext4_writeback_aops = {
+static const struct address_space_operations ext4_aops = {
 	.readpage		= ext4_readpage,
 	.readpages		= ext4_readpages,
 	.writepage		= ext4_writepage,
 	.write_begin		= ext4_write_begin,
-	.write_end		= ext4_writeback_write_end,
+	.write_end		= ext4_write_end,
 	.bmap			= ext4_bmap,
 	.invalidatepage		= ext4_invalidatepage,
 	.releasepage		= ext4_releasepage,
@@ -3399,23 +3324,21 @@ void ext4_set_aops(struct inode *inode)
 {
 	switch (ext4_inode_journal_mode(inode)) {
 	case EXT4_INODE_ORDERED_DATA_MODE:
-		if (test_opt(inode->i_sb, DELALLOC))
-			inode->i_mapping->a_ops = &ext4_da_aops;
-		else
-			inode->i_mapping->a_ops = &ext4_ordered_aops;
+		ext4_set_inode_state(inode, EXT4_STATE_ORDERED_MODE);
 		break;
 	case EXT4_INODE_WRITEBACK_DATA_MODE:
-		if (test_opt(inode->i_sb, DELALLOC))
-			inode->i_mapping->a_ops = &ext4_da_aops;
-		else
-			inode->i_mapping->a_ops = &ext4_writeback_aops;
+		ext4_clear_inode_state(inode, EXT4_STATE_ORDERED_MODE);
 		break;
 	case EXT4_INODE_JOURNAL_DATA_MODE:
 		inode->i_mapping->a_ops = &ext4_journalled_aops;
-		break;
+		return;
 	default:
 		BUG();
 	}
+	if (test_opt(inode->i_sb, DELALLOC))
+		inode->i_mapping->a_ops = &ext4_da_aops;
+	else
+		inode->i_mapping->a_ops = &ext4_aops;
 }
 
 
@@ -3646,20 +3569,190 @@ int ext4_can_truncate(struct inode *inode)
 int ext4_punch_hole(struct file *file, loff_t offset, loff_t length)
 {
 	struct inode *inode = file_inode(file);
+	struct super_block *sb = inode->i_sb;
+	ext4_lblk_t first_block, stop_block;
+	struct address_space *mapping = inode->i_mapping;
+	loff_t first_page, last_page, page_len;
+	loff_t first_page_offset, last_page_offset;
+	handle_t *handle;
+	unsigned int credits;
+	int ret = 0;
+
 	if (!S_ISREG(inode->i_mode))
 		return -EOPNOTSUPP;
 
-	if (!ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
-		return ext4_ind_punch_hole(file, offset, length);
-
-	if (EXT4_SB(inode->i_sb)->s_cluster_ratio > 1) {
+	if (EXT4_SB(sb)->s_cluster_ratio > 1) {
 		/* TODO: Add support for bigalloc file systems */
 		return -EOPNOTSUPP;
 	}
 
 	trace_ext4_punch_hole(inode, offset, length);
 
-	return ext4_ext_punch_hole(file, offset, length);
+	/*
+	 * Write out all dirty pages to avoid race conditions
+	 * Then release them.
+	 */
+	if (mapping->nrpages && mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) {
+		ret = filemap_write_and_wait_range(mapping, offset,
+						   offset + length - 1);
+		if (ret)
+			return ret;
+	}
+
+	mutex_lock(&inode->i_mutex);
+	/* It's not possible punch hole on append only file */
+	if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) {
+		ret = -EPERM;
+		goto out_mutex;
+	}
+	if (IS_SWAPFILE(inode)) {
+		ret = -ETXTBSY;
+		goto out_mutex;
+	}
+
+	/* No need to punch hole beyond i_size */
+	if (offset >= inode->i_size)
+		goto out_mutex;
+
+	/*
+	 * If the hole extends beyond i_size, set the hole
+	 * to end after the page that contains i_size
+	 */
+	if (offset + length > inode->i_size) {
+		length = inode->i_size +
+		   PAGE_CACHE_SIZE - (inode->i_size & (PAGE_CACHE_SIZE - 1)) -
+		   offset;
+	}
+
+	first_page = (offset + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+	last_page = (offset + length) >> PAGE_CACHE_SHIFT;
+
+	first_page_offset = first_page << PAGE_CACHE_SHIFT;
+	last_page_offset = last_page << PAGE_CACHE_SHIFT;
+
+	/* Now release the pages */
+	if (last_page_offset > first_page_offset) {
+		truncate_pagecache_range(inode, first_page_offset,
+					 last_page_offset - 1);
+	}
+
+	/* Wait all existing dio workers, newcomers will block on i_mutex */
+	ext4_inode_block_unlocked_dio(inode);
+	ret = ext4_flush_unwritten_io(inode);
+	if (ret)
+		goto out_dio;
+	inode_dio_wait(inode);
+
+	if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
+		credits = ext4_writepage_trans_blocks(inode);
+	else
+		credits = ext4_blocks_for_truncate(inode);
+	handle = ext4_journal_start(inode, EXT4_HT_TRUNCATE, credits);
+	if (IS_ERR(handle)) {
+		ret = PTR_ERR(handle);
+		ext4_std_error(sb, ret);
+		goto out_dio;
+	}
+
+	/*
+	 * Now we need to zero out the non-page-aligned data in the
+	 * pages at the start and tail of the hole, and unmap the
+	 * buffer heads for the block aligned regions of the page that
+	 * were completely zeroed.
+	 */
+	if (first_page > last_page) {
+		/*
+		 * If the file space being truncated is contained
+		 * within a page just zero out and unmap the middle of
+		 * that page
+		 */
+		ret = ext4_discard_partial_page_buffers(handle,
+			mapping, offset, length, 0);
+
+		if (ret)
+			goto out_stop;
+	} else {
+		/*
+		 * zero out and unmap the partial page that contains
+		 * the start of the hole
+		 */
+		page_len = first_page_offset - offset;
+		if (page_len > 0) {
+			ret = ext4_discard_partial_page_buffers(handle, mapping,
+						offset, page_len, 0);
+			if (ret)
+				goto out_stop;
+		}
+
+		/*
+		 * zero out and unmap the partial page that contains
+		 * the end of the hole
+		 */
+		page_len = offset + length - last_page_offset;
+		if (page_len > 0) {
+			ret = ext4_discard_partial_page_buffers(handle, mapping,
+					last_page_offset, page_len, 0);
+			if (ret)
+				goto out_stop;
+		}
+	}
+
+	/*
+	 * If i_size is contained in the last page, we need to
+	 * unmap and zero the partial page after i_size
+	 */
+	if (inode->i_size >> PAGE_CACHE_SHIFT == last_page &&
+	   inode->i_size % PAGE_CACHE_SIZE != 0) {
+		page_len = PAGE_CACHE_SIZE -
+			(inode->i_size & (PAGE_CACHE_SIZE - 1));
+
+		if (page_len > 0) {
+			ret = ext4_discard_partial_page_buffers(handle,
+					mapping, inode->i_size, page_len, 0);
+
+			if (ret)
+				goto out_stop;
+		}
+	}
+
+	first_block = (offset + sb->s_blocksize - 1) >>
+		EXT4_BLOCK_SIZE_BITS(sb);
+	stop_block = (offset + length) >> EXT4_BLOCK_SIZE_BITS(sb);
+
+	/* If there are no blocks to remove, return now */
+	if (first_block >= stop_block)
+		goto out_stop;
+
+	down_write(&EXT4_I(inode)->i_data_sem);
+	ext4_discard_preallocations(inode);
+
+	ret = ext4_es_remove_extent(inode, first_block,
+				    stop_block - first_block);
+	if (ret) {
+		up_write(&EXT4_I(inode)->i_data_sem);
+		goto out_stop;
+	}
+
+	if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
+		ret = ext4_ext_remove_space(inode, first_block,
+					    stop_block - 1);
+	else
+		ret = ext4_free_hole_blocks(handle, inode, first_block,
+					    stop_block);
+
+	ext4_discard_preallocations(inode);
+	up_write(&EXT4_I(inode)->i_data_sem);
+	if (IS_SYNC(inode))
+		ext4_handle_sync(handle);
+	inode->i_mtime = inode->i_ctime = ext4_current_time(inode);
+	ext4_mark_inode_dirty(handle, inode);
+out_stop:
+	ext4_journal_stop(handle);
+out_dio:
+	ext4_inode_resume_unlocked_dio(inode);
+out_mutex:
+	mutex_unlock(&inode->i_mutex);
+	return ret;
 }
 
 /*
@@ -3692,6 +3785,19 @@ int ext4_punch_hole(struct file *file, loff_t offset, loff_t length)
  */
 void ext4_truncate(struct inode *inode)
 {
+	struct ext4_inode_info *ei = EXT4_I(inode);
+	unsigned int credits;
+	handle_t *handle;
+	struct address_space *mapping = inode->i_mapping;
+	loff_t page_len;
+
+	/*
+	 * There is a possibility that we're either freeing the inode
+	 * or it completely new indode. In those cases we might not
+	 * have i_mutex locked because it's not necessary.
+	 */
+	if (!(inode->i_state & (I_NEW|I_FREEING)))
+		WARN_ON(!mutex_is_locked(&inode->i_mutex));
 	trace_ext4_truncate_enter(inode);
 
 	if (!ext4_can_truncate(inode))
@@ -3710,10 +3816,72 @@ void ext4_truncate(struct inode *inode)
 			return;
 	}
 
+	/*
+	 * finish any pending end_io work so we won't run the risk of
+	 * converting any truncated blocks to initialized later
+	 */
+	ext4_flush_unwritten_io(inode);
+
 	if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
-		ext4_ext_truncate(inode);
+		credits = ext4_writepage_trans_blocks(inode);
 	else
-		ext4_ind_truncate(inode);
+		credits = ext4_blocks_for_truncate(inode);
+
+	handle = ext4_journal_start(inode, EXT4_HT_TRUNCATE, credits);
+	if (IS_ERR(handle)) {
+		ext4_std_error(inode->i_sb, PTR_ERR(handle));
+		return;
+	}
+
+	if (inode->i_size % PAGE_CACHE_SIZE != 0) {
+		page_len = PAGE_CACHE_SIZE -
+			(inode->i_size & (PAGE_CACHE_SIZE - 1));
+
+		if (ext4_discard_partial_page_buffers(handle,
+				mapping, inode->i_size, page_len, 0))
+			goto out_stop;
+	}
+
+	/*
+	 * We add the inode to the orphan list, so that if this
+	 * truncate spans multiple transactions, and we crash, we will
+	 * resume the truncate when the filesystem recovers.  It also
+	 * marks the inode dirty, to catch the new size.
+	 *
+	 * Implication: the file must always be in a sane, consistent
+	 * truncatable state while each transaction commits.
+	 */
+	if (ext4_orphan_add(handle, inode))
+		goto out_stop;
+
+	down_write(&EXT4_I(inode)->i_data_sem);
+
+	ext4_discard_preallocations(inode);
+
+	if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
+		ext4_ext_truncate(handle, inode);
+	else
+		ext4_ind_truncate(handle, inode);
+
+	up_write(&ei->i_data_sem);
+
+	if (IS_SYNC(inode))
+		ext4_handle_sync(handle);
+
+out_stop:
+	/*
+	 * If this was a simple ftruncate() and the file will remain alive,
+	 * then we need to clear up the orphan record which we created above.
+	 * However, if this was a real unlink then we were called by
+	 * ext4_delete_inode(), and we allow that function to clean up the
+	 * orphan info for us.
+	 */
+	if (inode->i_nlink)
+		ext4_orphan_del(handle, inode);
+
+	inode->i_mtime = inode->i_ctime = ext4_current_time(inode);
+	ext4_mark_inode_dirty(handle, inode);
+	ext4_journal_stop(handle);
 
 	trace_ext4_truncate_exit(inode);
 }
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
index 721f4d3..a07b7bc 100644
--- a/fs/ext4/ioctl.c
+++ b/fs/ext4/ioctl.c
@@ -83,17 +83,8 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 			if (!capable(CAP_SYS_RESOURCE))
 				goto flags_out;
 		}
-		if (oldflags & EXT4_EXTENTS_FL) {
-			/* We don't support clearning extent flags */
-			if (!(flags & EXT4_EXTENTS_FL)) {
-				err = -EOPNOTSUPP;
-				goto flags_out;
-			}
-		} else if (flags & EXT4_EXTENTS_FL) {
-			/* migrate the file */
+		if ((flags ^ oldflags) & EXT4_EXTENTS_FL)
 			migrate = 1;
-			flags &= ~EXT4_EXTENTS_FL;
-		}
 
 		if (flags & EXT4_EOFBLOCKS_FL) {
 			/* we don't support adding EOFBLOCKS flag */
@@ -137,8 +128,13 @@ flags_err:
 			err = ext4_change_inode_journal_flag(inode, jflag);
 		if (err)
 			goto flags_out;
-		if (migrate)
-			err = ext4_ext_migrate(inode);
+		if (migrate) {
+			if (flags & EXT4_EXTENTS_FL)
+				err = ext4_ext_migrate(inode);
+			else
+				err = ext4_ind_migrate(inode);
+		}
+
 flags_out:
 		mutex_unlock(&inode->i_mutex);
 		mnt_drop_write_file(filp);
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index ee6614b..7198351 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -1011,6 +1011,7 @@ int ext4_mb_init_group(struct super_block *sb, ext4_group_t group)
 	struct page *page;
 	int ret = 0;
 
+	might_sleep();
 	mb_debug(1, "init group %u\n", group);
 	this_grp = ext4_get_group_info(sb, group);
 	/*
@@ -1082,6 +1083,7 @@ ext4_mb_load_buddy(struct super_block *sb, ext4_group_t group,
 	struct ext4_sb_info *sbi = EXT4_SB(sb);
 	struct inode *inode = sbi->s_buddy_cache;
 
+	might_sleep();
 	mb_debug(1, "load group %u\n", group);
 
 	blocks_per_page = PAGE_CACHE_SIZE / sb->s_blocksize;
@@ -2149,7 +2151,7 @@ static const struct seq_operations ext4_mb_seq_groups_ops = {
 
 static int ext4_mb_seq_groups_open(struct inode *inode, struct file *file)
 {
-	struct super_block *sb = PDE(inode)->data;
+	struct super_block *sb = PDE_DATA(inode);
 	int rc;
 
 	rc = seq_open(file, &ext4_mb_seq_groups_ops);
@@ -3342,7 +3344,7 @@ static void ext4_mb_put_pa(struct ext4_allocation_context *ac,
 	if (pa->pa_type == MB_GROUP_PA)
 		grp_blk--;
 
-	ext4_get_group_no_and_offset(sb, grp_blk, &grp, NULL);
+	grp = ext4_get_group_number(sb, grp_blk);
 
 	/*
 	 * possible race:
@@ -3807,7 +3809,7 @@ repeat:
 
 	list_for_each_entry_safe(pa, tmp, &list, u.pa_tmp_list) {
 		BUG_ON(pa->pa_type != MB_INODE_PA);
-		ext4_get_group_no_and_offset(sb, pa->pa_pstart, &group, NULL);
+		group = ext4_get_group_number(sb, pa->pa_pstart);
 
 		err = ext4_mb_load_buddy(sb, group, &e4b);
 		if (err) {
@@ -4069,7 +4071,7 @@ ext4_mb_discard_lg_preallocations(struct super_block *sb,
 
 	list_for_each_entry_safe(pa, tmp, &discard_list, u.pa_tmp_list) {
 
-		ext4_get_group_no_and_offset(sb, pa->pa_pstart, &group, NULL);
+		group = ext4_get_group_number(sb, pa->pa_pstart);
 		if (ext4_mb_load_buddy(sb, group, &e4b)) {
 			ext4_error(sb, "Error loading buddy information for %u",
 					group);
@@ -4217,6 +4219,7 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
 	unsigned int inquota = 0;
 	unsigned int reserv_clstrs = 0;
 
+	might_sleep();
 	sb = ar->inode->i_sb;
 	sbi = EXT4_SB(sb);
 
@@ -4420,11 +4423,11 @@ ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b,
 	node = rb_prev(new_node);
 	if (node) {
 		entry = rb_entry(node, struct ext4_free_data, efd_node);
-		if (can_merge(entry, new_entry)) {
+		if (can_merge(entry, new_entry) &&
+		    ext4_journal_callback_try_del(handle, &entry->efd_jce)) {
 			new_entry->efd_start_cluster = entry->efd_start_cluster;
 			new_entry->efd_count += entry->efd_count;
 			rb_erase(node, &(db->bb_free_root));
-			ext4_journal_callback_del(handle, &entry->efd_jce);
 			kmem_cache_free(ext4_free_data_cachep, entry);
 		}
 	}
@@ -4432,10 +4435,10 @@ ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b,
 	node = rb_next(new_node);
 	if (node) {
 		entry = rb_entry(node, struct ext4_free_data, efd_node);
-		if (can_merge(new_entry, entry)) {
+		if (can_merge(new_entry, entry) &&
+		    ext4_journal_callback_try_del(handle, &entry->efd_jce)) {
 			new_entry->efd_count += entry->efd_count;
 			rb_erase(node, &(db->bb_free_root));
-			ext4_journal_callback_del(handle, &entry->efd_jce);
 			kmem_cache_free(ext4_free_data_cachep, entry);
 		}
 	}
@@ -4470,6 +4473,7 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
 	int err = 0;
 	int ret;
 
+	might_sleep();
 	if (bh) {
 		if (block)
 			BUG_ON(block != bh->b_blocknr);
diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c
index 047a6de..a9afb18 100644
--- a/fs/ext4/page-io.c
+++ b/fs/ext4/page-io.c
@@ -18,6 +18,7 @@
 #include <linux/pagevec.h>
 #include <linux/mpage.h>
 #include <linux/namei.h>
+#include <linux/aio.h>
 #include <linux/uio.h>
 #include <linux/bio.h>
 #include <linux/workqueue.h>
@@ -238,7 +239,8 @@ static void buffer_io_error(struct buffer_head *bh)
 			(unsigned long long)bh->b_blocknr);
 }
 
-static void ext4_end_bio(struct bio *bio, int error)
+static void ext4_end_bio(struct bio *bio, int error,
+			 struct batch_complete *batch)
 {
 	ext4_io_end_t *io_end = bio->bi_private;
 	struct inode *inode;
diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
index c169477..e349853 100644
--- a/fs/ext4/resize.c
+++ b/fs/ext4/resize.c
@@ -272,7 +272,7 @@ next_group:
 		if (start_blk >= last_blk)
 			goto next_group;
 		group_data[bb_index].block_bitmap = start_blk++;
-		ext4_get_group_no_and_offset(sb, start_blk - 1, &group, NULL);
+		group = ext4_get_group_number(sb, start_blk - 1);
 		group -= group_data[0].group;
 		group_data[group].free_blocks_count--;
 		if (flexbg_size > 1)
@@ -284,7 +284,7 @@ next_group:
 		if (start_blk >= last_blk)
 			goto next_group;
 		group_data[ib_index].inode_bitmap = start_blk++;
-		ext4_get_group_no_and_offset(sb, start_blk - 1, &group, NULL);
+		group = ext4_get_group_number(sb, start_blk - 1);
 		group -= group_data[0].group;
 		group_data[group].free_blocks_count--;
 		if (flexbg_size > 1)
@@ -296,7 +296,7 @@ next_group:
 		if (start_blk + EXT4_SB(sb)->s_itb_per_group > last_blk)
 			goto next_group;
 		group_data[it_index].inode_table = start_blk;
-		ext4_get_group_no_and_offset(sb, start_blk, &group, NULL);
+		group = ext4_get_group_number(sb, start_blk - 1);
 		group -= group_data[0].group;
 		group_data[group].free_blocks_count -=
 					EXT4_SB(sb)->s_itb_per_group;
@@ -392,7 +392,7 @@ static int set_flexbg_block_bitmap(struct super_block *sb, handle_t *handle,
 		ext4_group_t group;
 		int err;
 
-		ext4_get_group_no_and_offset(sb, block, &group, NULL);
+		group = ext4_get_group_number(sb, block);
 		start = ext4_group_first_block_no(sb, group);
 		group -= flex_gd->groups[0].group;
 
@@ -1879,7 +1879,7 @@ retry:
 		/* Nothing need to do */
 		return 0;
 
-	ext4_get_group_no_and_offset(sb, n_blocks_count - 1, &n_group, &offset);
+	n_group = ext4_get_group_number(sb, n_blocks_count - 1);
 	ext4_get_group_no_and_offset(sb, o_blocks_count - 1, &o_group, &offset);
 
 	n_desc_blocks = num_desc_blocks(sb, n_group + 1);
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 5d6d5357..ac43444 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -353,10 +353,13 @@ static void ext4_journal_commit_callback(journal_t *journal, transaction_t *txn)
 	struct super_block		*sb = journal->j_private;
 	struct ext4_sb_info		*sbi = EXT4_SB(sb);
 	int				error = is_journal_aborted(journal);
-	struct ext4_journal_cb_entry	*jce, *tmp;
+	struct ext4_journal_cb_entry	*jce;
 
+	BUG_ON(txn->t_state == T_FINISHED);
 	spin_lock(&sbi->s_md_lock);
-	list_for_each_entry_safe(jce, tmp, &txn->t_private_list, jce_list) {
+	while (!list_empty(&txn->t_private_list)) {
+		jce = list_entry(txn->t_private_list.next,
+				 struct ext4_journal_cb_entry, jce_list);
 		list_del_init(&jce->jce_list);
 		spin_unlock(&sbi->s_md_lock);
 		jce->jce_func(sb, jce, error);
@@ -1802,7 +1805,7 @@ static int options_seq_show(struct seq_file *seq, void *offset)
 
 static int options_open_fs(struct inode *inode, struct file *file)
 {
-	return single_open(file, options_seq_show, PDE(inode)->data);
+	return single_open(file, options_seq_show, PDE_DATA(inode));
 }
 
 static const struct file_operations ext4_seq_options_fops = {
@@ -3526,6 +3529,10 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
 	sbi->s_addr_per_block_bits = ilog2(EXT4_ADDR_PER_BLOCK(sb));
 	sbi->s_desc_per_block_bits = ilog2(EXT4_DESC_PER_BLOCK(sb));
 
+	/* Do we have standard group size of blocksize * 8 blocks ? */
+	if (sbi->s_blocks_per_group == blocksize << 3)
+		set_opt2(sb, STD_GROUP_SIZE);
+
 	for (i = 0; i < 4; i++)
 		sbi->s_hash_seed[i] = le32_to_cpu(es->s_hash_seed[i]);
 	sbi->s_def_hash_version = es->s_def_hash_version;
@@ -3698,6 +3705,9 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
 	sbi->s_err_report.function = print_daily_error_info;
 	sbi->s_err_report.data = (unsigned long) sb;
 
+	/* Register extent status tree shrinker */
+	ext4_es_register_shrinker(sb);
+
 	err = percpu_counter_init(&sbi->s_freeclusters_counter,
 			ext4_count_free_clusters(sb));
 	if (!err) {
@@ -3723,9 +3733,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
 	sbi->s_max_writeback_mb_bump = 128;
 	sbi->s_extent_max_zeroout_kb = 32;
 
-	/* Register extent status tree shrinker */
-	ext4_es_register_shrinker(sb);
-
 	/*
 	 * set up enough so that it can read an inode
 	 */
@@ -4010,6 +4017,7 @@ failed_mount_wq:
 		sbi->s_journal = NULL;
 	}
 failed_mount3:
+	ext4_es_unregister_shrinker(sb);
 	del_timer(&sbi->s_err_report);
 	if (sbi->s_flex_groups)
 		ext4_kvfree(sbi->s_flex_groups);
diff --git a/fs/f2fs/acl.c b/fs/f2fs/acl.c
index 137af42..44abc2f 100644
--- a/fs/f2fs/acl.c
+++ b/fs/f2fs/acl.c
@@ -299,7 +299,7 @@ int f2fs_acl_chmod(struct inode *inode)
 	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
 	struct posix_acl *acl;
 	int error;
-	mode_t mode = get_inode_mode(inode);
+	umode_t mode = get_inode_mode(inode);
 
 	if (!test_opt(sbi, POSIX_ACL))
 		return 0;
diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
index 2b6fc13..93fd57d 100644
--- a/fs/f2fs/checkpoint.c
+++ b/fs/f2fs/checkpoint.c
@@ -57,13 +57,15 @@ repeat:
 		cond_resched();
 		goto repeat;
 	}
-	if (f2fs_readpage(sbi, page, index, READ_SYNC)) {
-		f2fs_put_page(page, 1);
+	if (PageUptodate(page))
+		goto out;
+
+	if (f2fs_readpage(sbi, page, index, READ_SYNC))
 		goto repeat;
-	}
-	mark_page_accessed(page);
 
-	/* We do not allow returning an errorneous page */
+	lock_page(page);
+out:
+	mark_page_accessed(page);
 	return page;
 }
 
@@ -746,8 +748,6 @@ void write_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
 	flush_nat_entries(sbi);
 	flush_sit_entries(sbi);
 
-	reset_victim_segmap(sbi);
-
 	/* unlock all the fs_lock[] in do_checkpoint() */
 	do_checkpoint(sbi, is_umount);
 
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 7bd22a2..4f4da0d 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -12,6 +12,7 @@
 #include <linux/f2fs_fs.h>
 #include <linux/buffer_head.h>
 #include <linux/mpage.h>
+#include <linux/aio.h>
 #include <linux/writeback.h>
 #include <linux/backing-dev.h>
 #include <linux/blkdev.h>
@@ -183,7 +184,7 @@ struct page *find_data_page(struct inode *inode, pgoff_t index)
 	f2fs_put_page(page, 0);
 
 	set_new_dnode(&dn, inode, NULL, NULL, 0);
-	err = get_dnode_of_data(&dn, index, RDONLY_NODE);
+	err = get_dnode_of_data(&dn, index, LOOKUP_NODE);
 	if (err)
 		return ERR_PTR(err);
 	f2fs_put_dnode(&dn);
@@ -199,12 +200,17 @@ struct page *find_data_page(struct inode *inode, pgoff_t index)
 	if (!page)
 		return ERR_PTR(-ENOMEM);
 
+	if (PageUptodate(page)) {
+		unlock_page(page);
+		return page;
+	}
+
 	err = f2fs_readpage(sbi, page, dn.data_blkaddr, READ_SYNC);
-	if (err) {
-		f2fs_put_page(page, 1);
-		return ERR_PTR(err);
+	wait_on_page_locked(page);
+	if (!PageUptodate(page)) {
+		f2fs_put_page(page, 0);
+		return ERR_PTR(-EIO);
 	}
-	unlock_page(page);
 	return page;
 }
 
@@ -222,7 +228,7 @@ struct page *get_lock_data_page(struct inode *inode, pgoff_t index)
 	int err;
 
 	set_new_dnode(&dn, inode, NULL, NULL, 0);
-	err = get_dnode_of_data(&dn, index, RDONLY_NODE);
+	err = get_dnode_of_data(&dn, index, LOOKUP_NODE);
 	if (err)
 		return ERR_PTR(err);
 	f2fs_put_dnode(&dn);
@@ -241,9 +247,13 @@ struct page *get_lock_data_page(struct inode *inode, pgoff_t index)
 	BUG_ON(dn.data_blkaddr == NULL_ADDR);
 
 	err = f2fs_readpage(sbi, page, dn.data_blkaddr, READ_SYNC);
-	if (err) {
-		f2fs_put_page(page, 1);
+	if (err)
 		return ERR_PTR(err);
+
+	lock_page(page);
+	if (!PageUptodate(page)) {
+		f2fs_put_page(page, 1);
+		return ERR_PTR(-EIO);
 	}
 	return page;
 }
@@ -262,7 +272,7 @@ struct page *get_new_data_page(struct inode *inode, pgoff_t index,
 	int err;
 
 	set_new_dnode(&dn, inode, NULL, NULL, 0);
-	err = get_dnode_of_data(&dn, index, 0);
+	err = get_dnode_of_data(&dn, index, ALLOC_NODE);
 	if (err)
 		return ERR_PTR(err);
 
@@ -283,14 +293,17 @@ struct page *get_new_data_page(struct inode *inode, pgoff_t index,
 
 	if (dn.data_blkaddr == NEW_ADDR) {
 		zero_user_segment(page, 0, PAGE_CACHE_SIZE);
+		SetPageUptodate(page);
 	} else {
 		err = f2fs_readpage(sbi, page, dn.data_blkaddr, READ_SYNC);
-		if (err) {
-			f2fs_put_page(page, 1);
+		if (err)
 			return ERR_PTR(err);
+		lock_page(page);
+		if (!PageUptodate(page)) {
+			f2fs_put_page(page, 1);
+			return ERR_PTR(-EIO);
 		}
 	}
-	SetPageUptodate(page);
 
 	if (new_i_size &&
 		i_size_read(inode) < ((index + 1) << PAGE_CACHE_SHIFT)) {
@@ -300,7 +313,7 @@ struct page *get_new_data_page(struct inode *inode, pgoff_t index,
 	return page;
 }
 
-static void read_end_io(struct bio *bio, int err)
+static void read_end_io(struct bio *bio, int err, struct batch_complete *batch)
 {
 	const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
 	struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1;
@@ -325,22 +338,14 @@ static void read_end_io(struct bio *bio, int err)
 
 /*
  * Fill the locked page with data located in the block address.
- * Read operation is synchronous, and caller must unlock the page.
+ * Return unlocked page.
  */
 int f2fs_readpage(struct f2fs_sb_info *sbi, struct page *page,
 					block_t blk_addr, int type)
 {
 	struct block_device *bdev = sbi->sb->s_bdev;
-	bool sync = (type == READ_SYNC);
 	struct bio *bio;
 
-	/* This page can be already read by other threads */
-	if (PageUptodate(page)) {
-		if (!sync)
-			unlock_page(page);
-		return 0;
-	}
-
 	down_read(&sbi->bio_sem);
 
 	/* Allocate a new bio */
@@ -354,18 +359,12 @@ int f2fs_readpage(struct f2fs_sb_info *sbi, struct page *page,
 		kfree(bio->bi_private);
 		bio_put(bio);
 		up_read(&sbi->bio_sem);
+		f2fs_put_page(page, 1);
 		return -EFAULT;
 	}
 
 	submit_bio(type, bio);
 	up_read(&sbi->bio_sem);
-
-	/* wait for read completion if sync */
-	if (sync) {
-		lock_page(page);
-		if (PageError(page))
-			return -EIO;
-	}
 	return 0;
 }
 
@@ -392,7 +391,7 @@ static int get_data_block_ro(struct inode *inode, sector_t iblock,
 
 	/* When reading holes, we need its node page */
 	set_new_dnode(&dn, inode, NULL, NULL, 0);
-	err = get_dnode_of_data(&dn, pgofs, RDONLY_NODE);
+	err = get_dnode_of_data(&dn, pgofs, LOOKUP_NODE_RA);
 	if (err)
 		return (err == -ENOENT) ? 0 : err;
 
@@ -437,13 +436,12 @@ static int f2fs_read_data_pages(struct file *file,
 int do_write_data_page(struct page *page)
 {
 	struct inode *inode = page->mapping->host;
-	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
 	block_t old_blk_addr, new_blk_addr;
 	struct dnode_of_data dn;
 	int err = 0;
 
 	set_new_dnode(&dn, inode, NULL, NULL, 0);
-	err = get_dnode_of_data(&dn, page->index, RDONLY_NODE);
+	err = get_dnode_of_data(&dn, page->index, LOOKUP_NODE);
 	if (err)
 		return err;
 
@@ -467,8 +465,6 @@ int do_write_data_page(struct page *page)
 		write_data_page(inode, page, &dn,
 				old_blk_addr, &new_blk_addr);
 		update_extent_cache(new_blk_addr, &dn);
-		F2FS_I(inode)->data_version =
-			le64_to_cpu(F2FS_CKPT(sbi)->checkpoint_ver);
 	}
 out_writepage:
 	f2fs_put_dnode(&dn);
@@ -607,7 +603,7 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping,
 	mutex_lock_op(sbi, DATA_NEW);
 
 	set_new_dnode(&dn, inode, NULL, NULL, 0);
-	err = get_dnode_of_data(&dn, index, 0);
+	err = get_dnode_of_data(&dn, index, ALLOC_NODE);
 	if (err) {
 		mutex_unlock_op(sbi, DATA_NEW);
 		f2fs_put_page(page, 1);
@@ -636,18 +632,22 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping,
 
 		/* Reading beyond i_size is simple: memset to zero */
 		zero_user_segments(page, 0, start, end, PAGE_CACHE_SIZE);
-		return 0;
+		goto out;
 	}
 
 	if (dn.data_blkaddr == NEW_ADDR) {
 		zero_user_segment(page, 0, PAGE_CACHE_SIZE);
 	} else {
 		err = f2fs_readpage(sbi, page, dn.data_blkaddr, READ_SYNC);
-		if (err) {
-			f2fs_put_page(page, 1);
+		if (err)
 			return err;
+		lock_page(page);
+		if (!PageUptodate(page)) {
+			f2fs_put_page(page, 1);
+			return -EIO;
 		}
 	}
+out:
 	SetPageUptodate(page);
 	clear_cold_data(page);
 	return 0;
@@ -681,7 +681,7 @@ static void f2fs_invalidate_data_page(struct page *page, unsigned long offset)
 static int f2fs_release_data_page(struct page *page, gfp_t wait)
 {
 	ClearPagePrivate(page);
-	return 0;
+	return 1;
 }
 
 static int f2fs_set_data_page_dirty(struct page *page)
diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c
index 025b9e2..c3bf343 100644
--- a/fs/f2fs/debug.c
+++ b/fs/f2fs/debug.c
@@ -106,7 +106,7 @@ static void update_sit_info(struct f2fs_sb_info *sbi)
 		}
 	}
 	mutex_unlock(&sit_i->sentry_lock);
-	dist = sbi->total_sections * hblks_per_sec * hblks_per_sec / 100;
+	dist = TOTAL_SECS(sbi) * hblks_per_sec * hblks_per_sec / 100;
 	si->bimodal = bimodal / dist;
 	if (si->dirty_count)
 		si->avg_vblocks = total_vblocks / ndirty;
@@ -138,14 +138,13 @@ static void update_mem_info(struct f2fs_sb_info *sbi)
 	si->base_mem += f2fs_bitmap_size(TOTAL_SEGS(sbi));
 	si->base_mem += 2 * SIT_VBLOCK_MAP_SIZE * TOTAL_SEGS(sbi);
 	if (sbi->segs_per_sec > 1)
-		si->base_mem += sbi->total_sections *
-			sizeof(struct sec_entry);
+		si->base_mem += TOTAL_SECS(sbi) * sizeof(struct sec_entry);
 	si->base_mem += __bitmap_size(sbi, SIT_BITMAP);
 
 	/* build free segmap */
 	si->base_mem += sizeof(struct free_segmap_info);
 	si->base_mem += f2fs_bitmap_size(TOTAL_SEGS(sbi));
-	si->base_mem += f2fs_bitmap_size(sbi->total_sections);
+	si->base_mem += f2fs_bitmap_size(TOTAL_SECS(sbi));
 
 	/* build curseg */
 	si->base_mem += sizeof(struct curseg_info) * NR_CURSEG_TYPE;
@@ -154,7 +153,7 @@ static void update_mem_info(struct f2fs_sb_info *sbi)
 	/* build dirty segmap */
 	si->base_mem += sizeof(struct dirty_seglist_info);
 	si->base_mem += NR_DIRTY_TYPE * f2fs_bitmap_size(TOTAL_SEGS(sbi));
-	si->base_mem += 2 * f2fs_bitmap_size(TOTAL_SEGS(sbi));
+	si->base_mem += f2fs_bitmap_size(TOTAL_SECS(sbi));
 
 	/* buld nm */
 	si->base_mem += sizeof(struct f2fs_nm_info);
diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c
index a1f3844..907b97b 100644
--- a/fs/f2fs/dir.c
+++ b/fs/f2fs/dir.c
@@ -60,7 +60,7 @@ static unsigned char f2fs_type_by_mode[S_IFMT >> S_SHIFT] = {
 
 static void set_de_type(struct f2fs_dir_entry *de, struct inode *inode)
 {
-	mode_t mode = inode->i_mode;
+	umode_t mode = inode->i_mode;
 	de->file_type = f2fs_type_by_mode[(mode & S_IFMT) >> S_SHIFT];
 }
 
@@ -189,6 +189,9 @@ struct f2fs_dir_entry *f2fs_find_entry(struct inode *dir,
 	unsigned int max_depth;
 	unsigned int level;
 
+	if (namelen > F2FS_NAME_LEN)
+		return NULL;
+
 	if (npages == 0)
 		return NULL;
 
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index cc2213a..71eacd3 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -125,11 +125,15 @@ static inline int update_sits_in_cursum(struct f2fs_summary_block *rs, int i)
 					 * file keeping -1 as its node offset to
 					 * distinguish from index node blocks.
 					 */
-#define RDONLY_NODE		1	/*
-					 * specify a read-only mode when getting
-					 * a node block. 0 is read-write mode.
-					 * used by get_dnode_of_data().
+enum {
+	ALLOC_NODE,			/* allocate a new node page if needed */
+	LOOKUP_NODE,			/* look up a node without readahead */
+	LOOKUP_NODE_RA,			/*
+					 * look up a node with readahead called
+					 * by get_datablock_ro.
 					 */
+};
+
 #define F2FS_LINK_MAX		32000	/* maximum link count per file */
 
 /* for in-memory extent cache entry */
@@ -137,13 +141,14 @@ struct extent_info {
 	rwlock_t ext_lock;	/* rwlock for consistency */
 	unsigned int fofs;	/* start offset in a file */
 	u32 blk_addr;		/* start block address of the extent */
-	unsigned int len;	/* lenth of the extent */
+	unsigned int len;	/* length of the extent */
 };
 
 /*
  * i_advise uses FADVISE_XXX_BIT. We can add additional hints later.
  */
 #define FADVISE_COLD_BIT	0x01
+#define FADVISE_CP_BIT		0x02
 
 struct f2fs_inode_info {
 	struct inode vfs_inode;		/* serve a vfs inode */
@@ -155,7 +160,6 @@ struct f2fs_inode_info {
 
 	/* Use below internally in f2fs*/
 	unsigned long flags;		/* use to pass per-file flags */
-	unsigned long long data_version;/* latest version of data for fsync */
 	atomic_t dirty_dents;		/* # of dirty dentry pages */
 	f2fs_hash_t chash;		/* hash value of given file name */
 	unsigned int clevel;		/* maximum level of given file name */
@@ -406,6 +410,7 @@ struct f2fs_sb_info {
 	/* for cleaning operations */
 	struct mutex gc_mutex;			/* mutex for GC */
 	struct f2fs_gc_kthread	*gc_thread;	/* GC thread */
+	unsigned int cur_victim_sec;		/* current victim section num */
 
 	/*
 	 * for stat information.
@@ -511,9 +516,12 @@ static inline void mutex_unlock_op(struct f2fs_sb_info *sbi, enum lock_type t)
 /*
  * Check whether the given nid is within node id range.
  */
-static inline void check_nid_range(struct f2fs_sb_info *sbi, nid_t nid)
+static inline int check_nid_range(struct f2fs_sb_info *sbi, nid_t nid)
 {
-	BUG_ON((nid >= NM_I(sbi)->max_nid));
+	WARN_ON((nid >= NM_I(sbi)->max_nid));
+	if (nid >= NM_I(sbi)->max_nid)
+		return -EINVAL;
+	return 0;
 }
 
 #define F2FS_DEFAULT_ALLOCATED_BLOCKS	1
@@ -819,7 +827,6 @@ static inline int f2fs_clear_bit(unsigned int nr, char *addr)
 /* used for f2fs_inode_info->flags */
 enum {
 	FI_NEW_INODE,		/* indicate newly allocated inode */
-	FI_NEED_CP,		/* need to do checkpoint during fsync */
 	FI_INC_LINK,		/* need to increment i_nlink */
 	FI_ACL_MODE,		/* indicate acl mode */
 	FI_NO_ALLOC,		/* should not allocate any blocks */
@@ -973,7 +980,6 @@ int lookup_journal_in_cursum(struct f2fs_summary_block *,
 					int, unsigned int, int);
 void flush_sit_entries(struct f2fs_sb_info *);
 int build_segment_manager(struct f2fs_sb_info *);
-void reset_victim_segmap(struct f2fs_sb_info *);
 void destroy_segment_manager(struct f2fs_sb_info *);
 
 /*
@@ -1020,7 +1026,7 @@ void destroy_gc_caches(void);
 /*
  * recovery.c
  */
-void recover_fsync_data(struct f2fs_sb_info *);
+int recover_fsync_data(struct f2fs_sb_info *);
 bool space_for_roll_forward(struct f2fs_sb_info *);
 
 /*
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 958a46d..ac8cbb2 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -13,6 +13,7 @@
 #include <linux/stat.h>
 #include <linux/buffer_head.h>
 #include <linux/writeback.h>
+#include <linux/blkdev.h>
 #include <linux/falloc.h>
 #include <linux/types.h>
 #include <linux/compat.h>
@@ -43,7 +44,7 @@ static int f2fs_vm_page_mkwrite(struct vm_area_struct *vma,
 
 	/* block allocation */
 	set_new_dnode(&dn, inode, NULL, NULL, 0);
-	err = get_dnode_of_data(&dn, page->index, 0);
+	err = get_dnode_of_data(&dn, page->index, ALLOC_NODE);
 	if (err) {
 		mutex_unlock_op(sbi, DATA_NEW);
 		goto out;
@@ -102,28 +103,10 @@ static const struct vm_operations_struct f2fs_file_vm_ops = {
 	.remap_pages	= generic_file_remap_pages,
 };
 
-static int need_to_sync_dir(struct f2fs_sb_info *sbi, struct inode *inode)
-{
-	struct dentry *dentry;
-	nid_t pino;
-
-	inode = igrab(inode);
-	dentry = d_find_any_alias(inode);
-	if (!dentry) {
-		iput(inode);
-		return 0;
-	}
-	pino = dentry->d_parent->d_inode->i_ino;
-	dput(dentry);
-	iput(inode);
-	return !is_checkpointed_node(sbi, pino);
-}
-
 int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
 {
 	struct inode *inode = file->f_mapping->host;
 	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
-	unsigned long long cur_version;
 	int ret = 0;
 	bool need_cp = false;
 	struct writeback_control wbc = {
@@ -147,28 +130,18 @@ int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
 	if (datasync && !(inode->i_state & I_DIRTY_DATASYNC))
 		goto out;
 
-	mutex_lock(&sbi->cp_mutex);
-	cur_version = le64_to_cpu(F2FS_CKPT(sbi)->checkpoint_ver);
-	mutex_unlock(&sbi->cp_mutex);
-
-	if (F2FS_I(inode)->data_version != cur_version &&
-					!(inode->i_state & I_DIRTY))
-		goto out;
-	F2FS_I(inode)->data_version--;
-
 	if (!S_ISREG(inode->i_mode) || inode->i_nlink != 1)
 		need_cp = true;
-	else if (is_inode_flag_set(F2FS_I(inode), FI_NEED_CP))
+	else if (is_cp_file(inode))
 		need_cp = true;
 	else if (!space_for_roll_forward(sbi))
 		need_cp = true;
-	else if (need_to_sync_dir(sbi, inode))
+	else if (!is_checkpointed_node(sbi, F2FS_I(inode)->i_pino))
 		need_cp = true;
 
 	if (need_cp) {
 		/* all the dirty node pages should be flushed for POR */
 		ret = f2fs_sync_fs(inode->i_sb, 1);
-		clear_inode_flag(F2FS_I(inode), FI_NEED_CP);
 	} else {
 		/* if there is no written node page, write its inode page */
 		while (!sync_node_pages(sbi, inode->i_ino, &wbc)) {
@@ -178,6 +151,7 @@ int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
 		}
 		filemap_fdatawait_range(sbi->node_inode->i_mapping,
 							0, LONG_MAX);
+		ret = blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL);
 	}
 out:
 	mutex_unlock(&inode->i_mutex);
@@ -258,7 +232,7 @@ static int truncate_blocks(struct inode *inode, u64 from)
 	mutex_lock_op(sbi, DATA_TRUNC);
 
 	set_new_dnode(&dn, inode, NULL, NULL, 0);
-	err = get_dnode_of_data(&dn, free_from, RDONLY_NODE);
+	err = get_dnode_of_data(&dn, free_from, LOOKUP_NODE);
 	if (err) {
 		if (err == -ENOENT)
 			goto free_next;
@@ -420,7 +394,7 @@ int truncate_hole(struct inode *inode, pgoff_t pg_start, pgoff_t pg_end)
 
 		mutex_lock_op(sbi, DATA_TRUNC);
 		set_new_dnode(&dn, inode, NULL, NULL, 0);
-		err = get_dnode_of_data(&dn, index, RDONLY_NODE);
+		err = get_dnode_of_data(&dn, index, LOOKUP_NODE);
 		if (err) {
 			mutex_unlock_op(sbi, DATA_TRUNC);
 			if (err == -ENOENT)
@@ -504,7 +478,7 @@ static int expand_inode_data(struct inode *inode, loff_t offset,
 		mutex_lock_op(sbi, DATA_NEW);
 
 		set_new_dnode(&dn, inode, NULL, NULL, 0);
-		ret = get_dnode_of_data(&dn, index, 0);
+		ret = get_dnode_of_data(&dn, index, ALLOC_NODE);
 		if (ret) {
 			mutex_unlock_op(sbi, DATA_NEW);
 			break;
@@ -590,7 +564,7 @@ long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 	{
 		unsigned int oldflags;
 
-		ret = mnt_want_write(filp->f_path.mnt);
+		ret = mnt_want_write_file(filp);
 		if (ret)
 			return ret;
 
@@ -627,7 +601,7 @@ long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 		inode->i_ctime = CURRENT_TIME;
 		mark_inode_dirty(inode);
 out:
-		mnt_drop_write(filp->f_path.mnt);
+		mnt_drop_write_file(filp);
 		return ret;
 	}
 	default:
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index 94b8a0c..54ac13d 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -131,7 +131,7 @@ static void select_policy(struct f2fs_sb_info *sbi, int gc_type,
 {
 	struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
 
-	if (p->alloc_mode) {
+	if (p->alloc_mode == SSR) {
 		p->gc_mode = GC_GREEDY;
 		p->dirty_segmap = dirty_i->dirty_segmap[type];
 		p->ofs_unit = 1;
@@ -160,18 +160,21 @@ static unsigned int get_max_cost(struct f2fs_sb_info *sbi,
 static unsigned int check_bg_victims(struct f2fs_sb_info *sbi)
 {
 	struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
-	unsigned int segno;
+	unsigned int hint = 0;
+	unsigned int secno;
 
 	/*
 	 * If the gc_type is FG_GC, we can select victim segments
 	 * selected by background GC before.
 	 * Those segments guarantee they have small valid blocks.
 	 */
-	segno = find_next_bit(dirty_i->victim_segmap[BG_GC],
-						TOTAL_SEGS(sbi), 0);
-	if (segno < TOTAL_SEGS(sbi)) {
-		clear_bit(segno, dirty_i->victim_segmap[BG_GC]);
-		return segno;
+next:
+	secno = find_next_bit(dirty_i->victim_secmap, TOTAL_SECS(sbi), hint++);
+	if (secno < TOTAL_SECS(sbi)) {
+		if (sec_usage_check(sbi, secno))
+			goto next;
+		clear_bit(secno, dirty_i->victim_secmap);
+		return secno * sbi->segs_per_sec;
 	}
 	return NULL_SEGNO;
 }
@@ -222,7 +225,7 @@ static unsigned int get_gc_cost(struct f2fs_sb_info *sbi, unsigned int segno,
 }
 
 /*
- * This function is called from two pathes.
+ * This function is called from two paths.
  * One is garbage collection and the other is SSR segment selection.
  * When it is called during GC, it just gets a victim segment
  * and it does not remove it from dirty seglist.
@@ -234,7 +237,6 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi,
 {
 	struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
 	struct victim_sel_policy p;
-	unsigned int segno;
 	int nsearched = 0;
 
 	p.alloc_mode = alloc_mode;
@@ -253,6 +255,7 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi,
 
 	while (1) {
 		unsigned long cost;
+		unsigned int segno, secno;
 
 		segno = find_next_bit(p.dirty_segmap,
 						TOTAL_SEGS(sbi), p.offset);
@@ -265,13 +268,11 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi,
 			break;
 		}
 		p.offset = ((segno / p.ofs_unit) * p.ofs_unit) + p.ofs_unit;
+		secno = GET_SECNO(sbi, segno);
 
-		if (test_bit(segno, dirty_i->victim_segmap[FG_GC]))
+		if (sec_usage_check(sbi, secno))
 			continue;
-		if (gc_type == BG_GC &&
-				test_bit(segno, dirty_i->victim_segmap[BG_GC]))
-			continue;
-		if (IS_CURSEC(sbi, GET_SECNO(sbi, segno)))
+		if (gc_type == BG_GC && test_bit(secno, dirty_i->victim_secmap))
 			continue;
 
 		cost = get_gc_cost(sbi, segno, &p);
@@ -291,13 +292,14 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi,
 	}
 got_it:
 	if (p.min_segno != NULL_SEGNO) {
-		*result = (p.min_segno / p.ofs_unit) * p.ofs_unit;
 		if (p.alloc_mode == LFS) {
-			int i;
-			for (i = 0; i < p.ofs_unit; i++)
-				set_bit(*result + i,
-					dirty_i->victim_segmap[gc_type]);
+			unsigned int secno = GET_SECNO(sbi, p.min_segno);
+			if (gc_type == FG_GC)
+				sbi->cur_victim_sec = secno;
+			else
+				set_bit(secno, dirty_i->victim_secmap);
 		}
+		*result = (p.min_segno / p.ofs_unit) * p.ofs_unit;
 	}
 	mutex_unlock(&dirty_i->seglist_lock);
 
@@ -401,8 +403,14 @@ next_step:
 			continue;
 
 		/* set page dirty and write it */
-		if (!PageWriteback(node_page))
+		if (gc_type == FG_GC) {
+			f2fs_submit_bio(sbi, NODE, true);
+			wait_on_page_writeback(node_page);
 			set_page_dirty(node_page);
+		} else {
+			if (!PageWriteback(node_page))
+				set_page_dirty(node_page);
+		}
 		f2fs_put_page(node_page, 1);
 		stat_inc_node_blk_count(sbi, 1);
 	}
@@ -418,6 +426,13 @@ next_step:
 			.for_reclaim = 0,
 		};
 		sync_node_pages(sbi, 0, &wbc);
+
+		/*
+		 * In the case of FG_GC, it'd be better to reclaim this victim
+		 * completely.
+		 */
+		if (get_valid_blocks(sbi, segno, 1) != 0)
+			goto next_step;
 	}
 }
 
@@ -481,20 +496,19 @@ static int check_dnode(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
 
 static void move_data_page(struct inode *inode, struct page *page, int gc_type)
 {
-	if (page->mapping != inode->i_mapping)
-		goto out;
-
-	if (inode != page->mapping->host)
-		goto out;
-
-	if (PageWriteback(page))
-		goto out;
-
 	if (gc_type == BG_GC) {
+		if (PageWriteback(page))
+			goto out;
 		set_page_dirty(page);
 		set_cold_data(page);
 	} else {
 		struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+
+		if (PageWriteback(page)) {
+			f2fs_submit_bio(sbi, DATA, true);
+			wait_on_page_writeback(page);
+		}
+
 		mutex_lock_op(sbi, DATA_WRITE);
 		if (clear_page_dirty_for_io(page) &&
 			S_ISDIR(inode->i_mode)) {
@@ -591,8 +605,18 @@ next_iput:
 	if (++phase < 4)
 		goto next_step;
 
-	if (gc_type == FG_GC)
+	if (gc_type == FG_GC) {
 		f2fs_submit_bio(sbi, DATA, true);
+
+		/*
+		 * In the case of FG_GC, it'd be better to reclaim this victim
+		 * completely.
+		 */
+		if (get_valid_blocks(sbi, segno, 1) != 0) {
+			phase = 2;
+			goto next_step;
+		}
+	}
 }
 
 static int __get_victim(struct f2fs_sb_info *sbi, unsigned int *victim,
@@ -617,12 +641,6 @@ static void do_garbage_collect(struct f2fs_sb_info *sbi, unsigned int segno,
 	if (IS_ERR(sum_page))
 		return;
 
-	/*
-	 * CP needs to lock sum_page. In this time, we don't need
-	 * to lock this page, because this summary page is not gone anywhere.
-	 * Also, this page is not gonna be updated before GC is done.
-	 */
-	unlock_page(sum_page);
 	sum = page_address(sum_page);
 
 	switch (GET_SUM_TYPE((&sum->footer))) {
@@ -636,7 +654,7 @@ static void do_garbage_collect(struct f2fs_sb_info *sbi, unsigned int segno,
 	stat_inc_seg_count(sbi, GET_SUM_TYPE((&sum->footer)));
 	stat_inc_call_count(sbi->stat_info);
 
-	f2fs_put_page(sum_page, 0);
+	f2fs_put_page(sum_page, 1);
 }
 
 int f2fs_gc(struct f2fs_sb_info *sbi)
@@ -662,9 +680,11 @@ gc_more:
 	for (i = 0; i < sbi->segs_per_sec; i++)
 		do_garbage_collect(sbi, segno + i, &ilist, gc_type);
 
-	if (gc_type == FG_GC &&
-			get_valid_blocks(sbi, segno, sbi->segs_per_sec) == 0)
+	if (gc_type == FG_GC) {
+		sbi->cur_victim_sec = NULL_SEGNO;
 		nfree++;
+		WARN_ON(get_valid_blocks(sbi, segno, sbi->segs_per_sec));
+	}
 
 	if (has_not_enough_free_secs(sbi, nfree))
 		goto gc_more;
diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
index ddae412..f798ddf 100644
--- a/fs/f2fs/inode.c
+++ b/fs/f2fs/inode.c
@@ -44,7 +44,11 @@ static int do_read_inode(struct inode *inode)
 	struct f2fs_inode *ri;
 
 	/* Check if ino is within scope */
-	check_nid_range(sbi, inode->i_ino);
+	if (check_nid_range(sbi, inode->i_ino)) {
+		f2fs_msg(inode->i_sb, KERN_ERR, "bad inode number: %lu",
+			 (unsigned long) inode->i_ino);
+		return -EINVAL;
+	}
 
 	node_page = get_node_page(sbi, inode->i_ino);
 	if (IS_ERR(node_page))
@@ -76,7 +80,6 @@ static int do_read_inode(struct inode *inode)
 	fi->i_xattr_nid = le32_to_cpu(ri->i_xattr_nid);
 	fi->i_flags = le32_to_cpu(ri->i_flags);
 	fi->flags = 0;
-	fi->data_version = le64_to_cpu(F2FS_CKPT(sbi)->checkpoint_ver) - 1;
 	fi->i_advise = ri->i_advise;
 	fi->i_pino = le32_to_cpu(ri->i_pino);
 	get_extent_info(&fi->ext, ri->i_ext);
diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c
index 1a49b88..7c6e219 100644
--- a/fs/f2fs/namei.c
+++ b/fs/f2fs/namei.c
@@ -15,6 +15,7 @@
 #include <linux/ctype.h>
 
 #include "f2fs.h"
+#include "node.h"
 #include "xattr.h"
 #include "acl.h"
 
@@ -99,7 +100,7 @@ static int is_multimedia_file(const unsigned char *s, const char *sub)
 /*
  * Set multimedia files as cold files for hot/cold data separation
  */
-static inline void set_cold_file(struct f2fs_sb_info *sbi, struct inode *inode,
+static inline void set_cold_files(struct f2fs_sb_info *sbi, struct inode *inode,
 		const unsigned char *name)
 {
 	int i;
@@ -108,7 +109,7 @@ static inline void set_cold_file(struct f2fs_sb_info *sbi, struct inode *inode,
 	int count = le32_to_cpu(sbi->raw_super->extension_count);
 	for (i = 0; i < count; i++) {
 		if (!is_multimedia_file(name, extlist[i])) {
-			F2FS_I(inode)->i_advise |= FADVISE_COLD_BIT;
+			set_cold_file(inode);
 			break;
 		}
 	}
@@ -130,7 +131,7 @@ static int f2fs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
 		return PTR_ERR(inode);
 
 	if (!test_opt(sbi, DISABLE_EXT_IDENTIFY))
-		set_cold_file(sbi, inode, dentry->d_name.name);
+		set_cold_files(sbi, inode, dentry->d_name.name);
 
 	inode->i_op = &f2fs_file_inode_operations;
 	inode->i_fop = &f2fs_file_operations;
@@ -173,6 +174,12 @@ static int f2fs_link(struct dentry *old_dentry, struct inode *dir,
 	if (err)
 		goto out;
 
+	/*
+	 * This file should be checkpointed during fsync.
+	 * We lost i_pino from now on.
+	 */
+	set_cp_file(inode);
+
 	d_instantiate(dentry, inode);
 	return 0;
 out:
@@ -197,7 +204,7 @@ static struct dentry *f2fs_lookup(struct inode *dir, struct dentry *dentry,
 	struct f2fs_dir_entry *de;
 	struct page *page;
 
-	if (dentry->d_name.len > F2FS_MAX_NAME_LEN)
+	if (dentry->d_name.len > F2FS_NAME_LEN)
 		return ERR_PTR(-ENAMETOOLONG);
 
 	de = f2fs_find_entry(dir, &dentry->d_name, &page);
@@ -425,7 +432,6 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry,
 	}
 
 	old_inode->i_ctime = CURRENT_TIME;
-	set_inode_flag(F2FS_I(old_inode), FI_NEED_CP);
 	mark_inode_dirty(old_inode);
 
 	f2fs_delete_entry(old_entry, old_page, NULL);
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index e275218..7555fb7 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -100,10 +100,13 @@ static void ra_nat_pages(struct f2fs_sb_info *sbi, int nid)
 		page = grab_cache_page(mapping, index);
 		if (!page)
 			continue;
-		if (f2fs_readpage(sbi, page, index, READ)) {
+		if (PageUptodate(page)) {
 			f2fs_put_page(page, 1);
 			continue;
 		}
+		if (f2fs_readpage(sbi, page, index, READ))
+			continue;
+
 		f2fs_put_page(page, 0);
 	}
 }
@@ -320,15 +323,14 @@ static int get_node_path(long block, int offset[4], unsigned int noffset[4])
 	noffset[0] = 0;
 
 	if (block < direct_index) {
-		offset[n++] = block;
-		level = 0;
+		offset[n] = block;
 		goto got;
 	}
 	block -= direct_index;
 	if (block < direct_blks) {
 		offset[n++] = NODE_DIR1_BLOCK;
 		noffset[n] = 1;
-		offset[n++] = block;
+		offset[n] = block;
 		level = 1;
 		goto got;
 	}
@@ -336,7 +338,7 @@ static int get_node_path(long block, int offset[4], unsigned int noffset[4])
 	if (block < direct_blks) {
 		offset[n++] = NODE_DIR2_BLOCK;
 		noffset[n] = 2;
-		offset[n++] = block;
+		offset[n] = block;
 		level = 1;
 		goto got;
 	}
@@ -346,7 +348,7 @@ static int get_node_path(long block, int offset[4], unsigned int noffset[4])
 		noffset[n] = 3;
 		offset[n++] = block / direct_blks;
 		noffset[n] = 4 + offset[n - 1];
-		offset[n++] = block % direct_blks;
+		offset[n] = block % direct_blks;
 		level = 2;
 		goto got;
 	}
@@ -356,7 +358,7 @@ static int get_node_path(long block, int offset[4], unsigned int noffset[4])
 		noffset[n] = 4 + dptrs_per_blk;
 		offset[n++] = block / direct_blks;
 		noffset[n] = 5 + dptrs_per_blk + offset[n - 1];
-		offset[n++] = block % direct_blks;
+		offset[n] = block % direct_blks;
 		level = 2;
 		goto got;
 	}
@@ -371,7 +373,7 @@ static int get_node_path(long block, int offset[4], unsigned int noffset[4])
 		noffset[n] = 7 + (dptrs_per_blk * 2) +
 			      offset[n - 2] * (dptrs_per_blk + 1) +
 			      offset[n - 1];
-		offset[n++] = block % direct_blks;
+		offset[n] = block % direct_blks;
 		level = 3;
 		goto got;
 	} else {
@@ -384,7 +386,7 @@ got:
 /*
  * Caller should call f2fs_put_dnode(dn).
  */
-int get_dnode_of_data(struct dnode_of_data *dn, pgoff_t index, int ro)
+int get_dnode_of_data(struct dnode_of_data *dn, pgoff_t index, int mode)
 {
 	struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb);
 	struct page *npage[4];
@@ -403,7 +405,8 @@ int get_dnode_of_data(struct dnode_of_data *dn, pgoff_t index, int ro)
 		return PTR_ERR(npage[0]);
 
 	parent = npage[0];
-	nids[1] = get_nid(parent, offset[0], true);
+	if (level != 0)
+		nids[1] = get_nid(parent, offset[0], true);
 	dn->inode_page = npage[0];
 	dn->inode_page_locked = true;
 
@@ -411,7 +414,7 @@ int get_dnode_of_data(struct dnode_of_data *dn, pgoff_t index, int ro)
 	for (i = 1; i <= level; i++) {
 		bool done = false;
 
-		if (!nids[i] && !ro) {
+		if (!nids[i] && mode == ALLOC_NODE) {
 			mutex_lock_op(sbi, NODE_NEW);
 
 			/* alloc new node */
@@ -434,7 +437,7 @@ int get_dnode_of_data(struct dnode_of_data *dn, pgoff_t index, int ro)
 			alloc_nid_done(sbi, nids[i]);
 			mutex_unlock_op(sbi, NODE_NEW);
 			done = true;
-		} else if (ro && i == level && level > 1) {
+		} else if (mode == LOOKUP_NODE_RA && i == level && level > 1) {
 			npage[i] = get_node_page_ra(parent, offset[i - 1]);
 			if (IS_ERR(npage[i])) {
 				err = PTR_ERR(npage[i]);
@@ -844,59 +847,69 @@ fail:
 	return ERR_PTR(err);
 }
 
-static int read_node_page(struct page *page, int type)
-{
-	struct f2fs_sb_info *sbi = F2FS_SB(page->mapping->host->i_sb);
-	struct node_info ni;
-
-	get_node_info(sbi, page->index, &ni);
-
-	if (ni.blk_addr == NULL_ADDR)
-		return -ENOENT;
-	return f2fs_readpage(sbi, page, ni.blk_addr, type);
-}
-
 /*
  * Readahead a node page
  */
 void ra_node_page(struct f2fs_sb_info *sbi, nid_t nid)
 {
 	struct address_space *mapping = sbi->node_inode->i_mapping;
+	struct node_info ni;
 	struct page *apage;
 
 	apage = find_get_page(mapping, nid);
-	if (apage && PageUptodate(apage))
-		goto release_out;
+	if (apage && PageUptodate(apage)) {
+		f2fs_put_page(apage, 0);
+		return;
+	}
 	f2fs_put_page(apage, 0);
 
 	apage = grab_cache_page(mapping, nid);
 	if (!apage)
 		return;
 
-	if (read_node_page(apage, READA))
-		unlock_page(apage);
+	get_node_info(sbi, nid, &ni);
 
-release_out:
-	f2fs_put_page(apage, 0);
+	if (ni.blk_addr == NULL_ADDR || PageUptodate(apage)) {
+		f2fs_put_page(apage, 1);
+		return;
+	}
+
+	if (f2fs_readpage(sbi, apage, ni.blk_addr, READA) == 0)
+		f2fs_put_page(apage, 0);
 	return;
 }
 
 struct page *get_node_page(struct f2fs_sb_info *sbi, pgoff_t nid)
 {
-	int err;
-	struct page *page;
 	struct address_space *mapping = sbi->node_inode->i_mapping;
+	struct page *page;
+	struct node_info ni;
+	int err;
 
 	page = grab_cache_page(mapping, nid);
 	if (!page)
 		return ERR_PTR(-ENOMEM);
 
-	err = read_node_page(page, READ_SYNC);
-	if (err) {
+	get_node_info(sbi, nid, &ni);
+
+	if (ni.blk_addr == NULL_ADDR) {
 		f2fs_put_page(page, 1);
-		return ERR_PTR(err);
+		return ERR_PTR(-ENOENT);
 	}
 
+	if (PageUptodate(page))
+		goto got_it;
+
+	err = f2fs_readpage(sbi, page, ni.blk_addr, READ_SYNC);
+	if (err)
+		return ERR_PTR(err);
+
+	lock_page(page);
+	if (!PageUptodate(page)) {
+		f2fs_put_page(page, 1);
+		return ERR_PTR(-EIO);
+	}
+got_it:
 	BUG_ON(nid != nid_of_node(page));
 	mark_page_accessed(page);
 	return page;
@@ -910,6 +923,7 @@ struct page *get_node_page_ra(struct page *parent, int start)
 {
 	struct f2fs_sb_info *sbi = F2FS_SB(parent->mapping->host->i_sb);
 	struct address_space *mapping = sbi->node_inode->i_mapping;
+	struct node_info ni;
 	int i, end;
 	int err = 0;
 	nid_t nid;
@@ -920,22 +934,24 @@ struct page *get_node_page_ra(struct page *parent, int start)
 	if (!nid)
 		return ERR_PTR(-ENOENT);
 
-	page = find_get_page(mapping, nid);
-	if (page && PageUptodate(page))
-		goto page_hit;
-	f2fs_put_page(page, 0);
-
-repeat:
 	page = grab_cache_page(mapping, nid);
 	if (!page)
 		return ERR_PTR(-ENOMEM);
 
-	err = read_node_page(page, READA);
-	if (err) {
+	get_node_info(sbi, nid, &ni);
+
+	if (ni.blk_addr == NULL_ADDR) {
 		f2fs_put_page(page, 1);
-		return ERR_PTR(err);
+		return ERR_PTR(-ENOENT);
 	}
 
+	if (PageUptodate(page))
+		goto page_hit;
+
+	err = f2fs_readpage(sbi, page, ni.blk_addr, READ_SYNC);
+	if (err)
+		return ERR_PTR(err);
+
 	/* Then, try readahead for siblings of the desired node */
 	end = start + MAX_RA_NODE;
 	end = min(end, NIDS_PER_BLOCK);
@@ -946,18 +962,14 @@ repeat:
 		ra_node_page(sbi, nid);
 	}
 
-page_hit:
 	lock_page(page);
-	if (PageError(page)) {
-		f2fs_put_page(page, 1);
-		return ERR_PTR(-EIO);
-	}
 
-	/* Has the page been truncated? */
-	if (page->mapping != mapping) {
+page_hit:
+	if (!PageUptodate(page)) {
 		f2fs_put_page(page, 1);
-		goto repeat;
+		return ERR_PTR(-EIO);
 	}
+	mark_page_accessed(page);
 	return page;
 }
 
@@ -1087,13 +1099,6 @@ static int f2fs_write_node_page(struct page *page,
 	block_t new_addr;
 	struct node_info ni;
 
-	if (wbc->for_reclaim) {
-		dec_page_count(sbi, F2FS_DIRTY_NODES);
-		wbc->pages_skipped++;
-		set_page_dirty(page);
-		return AOP_WRITEPAGE_ACTIVATE;
-	}
-
 	wait_on_page_writeback(page);
 
 	mutex_lock_op(sbi, NODE_WRITE);
@@ -1106,15 +1111,23 @@ static int f2fs_write_node_page(struct page *page,
 
 	/* This page is already truncated */
 	if (ni.blk_addr == NULL_ADDR)
-		return 0;
+		goto out;
+
+	if (wbc->for_reclaim) {
+		dec_page_count(sbi, F2FS_DIRTY_NODES);
+		wbc->pages_skipped++;
+		set_page_dirty(page);
+		mutex_unlock_op(sbi, NODE_WRITE);
+		return AOP_WRITEPAGE_ACTIVATE;
+	}
 
 	set_page_writeback(page);
 
 	/* insert node offset */
 	write_node_page(sbi, page, nid, ni.blk_addr, &new_addr);
 	set_node_addr(sbi, &ni, new_addr);
+out:
 	dec_page_count(sbi, F2FS_DIRTY_NODES);
-
 	mutex_unlock_op(sbi, NODE_WRITE);
 	unlock_page(page);
 	return 0;
@@ -1135,7 +1148,7 @@ static int f2fs_write_node_pages(struct address_space *mapping,
 
 	/* First check balancing cached NAT entries */
 	if (try_to_free_nats(sbi, NAT_ENTRY_PER_BLOCK)) {
-		write_checkpoint(sbi, false);
+		f2fs_sync_fs(sbi->sb, true);
 		return 0;
 	}
 
@@ -1178,7 +1191,7 @@ static void f2fs_invalidate_node_page(struct page *page, unsigned long offset)
 static int f2fs_release_node_page(struct page *page, gfp_t wait)
 {
 	ClearPagePrivate(page);
-	return 0;
+	return 1;
 }
 
 /*
@@ -1195,14 +1208,13 @@ const struct address_space_operations f2fs_node_aops = {
 static struct free_nid *__lookup_free_nid_list(nid_t n, struct list_head *head)
 {
 	struct list_head *this;
-	struct free_nid *i = NULL;
+	struct free_nid *i;
 	list_for_each(this, head) {
 		i = list_entry(this, struct free_nid, list);
 		if (i->nid == n)
-			break;
-		i = NULL;
+			return i;
 	}
-	return i;
+	return NULL;
 }
 
 static void __del_from_free_nid_list(struct free_nid *i)
@@ -1265,6 +1277,8 @@ static int scan_nat_page(struct f2fs_nm_info *nm_i,
 	i = start_nid % NAT_ENTRY_PER_BLOCK;
 
 	for (; i < NAT_ENTRY_PER_BLOCK; i++, start_nid++) {
+		if (start_nid >= nm_i->max_nid)
+			break;
 		blk_addr  = le32_to_cpu(nat_blk->entries[i].block_addr);
 		BUG_ON(blk_addr == NEW_ADDR);
 		if (blk_addr == NULL_ADDR)
@@ -1307,7 +1321,8 @@ static void build_free_nids(struct f2fs_sb_info *sbi)
 			break;
 	}
 
-	nm_i->next_scan_nid = nid;
+	/* go to the next nat page in order to reuse free nids first */
+	nm_i->next_scan_nid = nm_i->init_scan_nid + NAT_ENTRY_PER_BLOCK;
 
 	/* find free nids from current sum_pages */
 	mutex_lock(&curseg->curseg_mutex);
@@ -1475,23 +1490,24 @@ int restore_node_summary(struct f2fs_sb_info *sbi,
 	sum_entry = &sum->entries[0];
 
 	for (i = 0; i < last_offset; i++, sum_entry++) {
+		/*
+		 * In order to read next node page,
+		 * we must clear PageUptodate flag.
+		 */
+		ClearPageUptodate(page);
+
 		if (f2fs_readpage(sbi, page, addr, READ_SYNC))
 			goto out;
 
+		lock_page(page);
 		rn = (struct f2fs_node *)page_address(page);
 		sum_entry->nid = rn->footer.nid;
 		sum_entry->version = 0;
 		sum_entry->ofs_in_node = 0;
 		addr++;
-
-		/*
-		 * In order to read next node page,
-		 * we must clear PageUptodate flag.
-		 */
-		ClearPageUptodate(page);
 	}
-out:
 	unlock_page(page);
+out:
 	__free_pages(page, 0);
 	return 0;
 }
@@ -1614,13 +1630,11 @@ flush_now:
 			nid_in_journal(sum, offset) = cpu_to_le32(nid);
 		}
 
-		if (nat_get_blkaddr(ne) == NULL_ADDR) {
+		if (nat_get_blkaddr(ne) == NULL_ADDR &&
+					!add_free_nid(NM_I(sbi), nid)) {
 			write_lock(&nm_i->nat_tree_lock);
 			__del_from_nat_cache(nm_i, ne);
 			write_unlock(&nm_i->nat_tree_lock);
-
-			/* We can reuse this freed nid at this point */
-			add_free_nid(NM_I(sbi), nid);
 		} else {
 			write_lock(&nm_i->nat_tree_lock);
 			__clear_nat_cache_dirty(nm_i, ne);
@@ -1661,19 +1675,17 @@ static int init_node_manager(struct f2fs_sb_info *sbi)
 	spin_lock_init(&nm_i->free_nid_list_lock);
 	rwlock_init(&nm_i->nat_tree_lock);
 
-	nm_i->bitmap_size = __bitmap_size(sbi, NAT_BITMAP);
 	nm_i->init_scan_nid = le32_to_cpu(sbi->ckpt->next_free_nid);
 	nm_i->next_scan_nid = le32_to_cpu(sbi->ckpt->next_free_nid);
-
-	nm_i->nat_bitmap = kzalloc(nm_i->bitmap_size, GFP_KERNEL);
-	if (!nm_i->nat_bitmap)
-		return -ENOMEM;
+	nm_i->bitmap_size = __bitmap_size(sbi, NAT_BITMAP);
 	version_bitmap = __bitmap_ptr(sbi, NAT_BITMAP);
 	if (!version_bitmap)
 		return -EFAULT;
 
-	/* copy version bitmap */
-	memcpy(nm_i->nat_bitmap, version_bitmap, nm_i->bitmap_size);
+	nm_i->nat_bitmap = kmemdup(version_bitmap, nm_i->bitmap_size,
+					GFP_KERNEL);
+	if (!nm_i->nat_bitmap)
+		return -ENOMEM;
 	return 0;
 }
 
diff --git a/fs/f2fs/node.h b/fs/f2fs/node.h
index afdb130..d009cdf 100644
--- a/fs/f2fs/node.h
+++ b/fs/f2fs/node.h
@@ -277,6 +277,21 @@ static inline int is_cold_file(struct inode *inode)
 	return F2FS_I(inode)->i_advise & FADVISE_COLD_BIT;
 }
 
+static inline void set_cold_file(struct inode *inode)
+{
+	F2FS_I(inode)->i_advise |= FADVISE_COLD_BIT;
+}
+
+static inline int is_cp_file(struct inode *inode)
+{
+	return F2FS_I(inode)->i_advise & FADVISE_CP_BIT;
+}
+
+static inline void set_cp_file(struct inode *inode)
+{
+	F2FS_I(inode)->i_advise |= FADVISE_CP_BIT;
+}
+
 static inline int is_cold_data(struct page *page)
 {
 	return PageChecked(page);
diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c
index b235215..61bdaa7 100644
--- a/fs/f2fs/recovery.c
+++ b/fs/f2fs/recovery.c
@@ -112,11 +112,14 @@ static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head)
 	while (1) {
 		struct fsync_inode_entry *entry;
 
-		if (f2fs_readpage(sbi, page, blkaddr, READ_SYNC))
+		err = f2fs_readpage(sbi, page, blkaddr, READ_SYNC);
+		if (err)
 			goto out;
 
+		lock_page(page);
+
 		if (cp_ver != cpver_of_node(page))
-			goto out;
+			goto unlock_out;
 
 		if (!is_fsync_dnode(page))
 			goto next;
@@ -129,24 +132,23 @@ static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head)
 							FI_INC_LINK);
 		} else {
 			if (IS_INODE(page) && is_dent_dnode(page)) {
-				if (recover_inode_page(sbi, page)) {
-					err = -ENOMEM;
-					goto out;
-				}
+				err = recover_inode_page(sbi, page);
+				if (err)
+					goto unlock_out;
 			}
 
 			/* add this fsync inode to the list */
 			entry = kmem_cache_alloc(fsync_entry_slab, GFP_NOFS);
 			if (!entry) {
 				err = -ENOMEM;
-				goto out;
+				goto unlock_out;
 			}
 
 			entry->inode = f2fs_iget(sbi->sb, ino_of_node(page));
 			if (IS_ERR(entry->inode)) {
 				err = PTR_ERR(entry->inode);
 				kmem_cache_free(fsync_entry_slab, entry);
-				goto out;
+				goto unlock_out;
 			}
 
 			list_add_tail(&entry->list, head);
@@ -155,15 +157,15 @@ static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head)
 		if (IS_INODE(page)) {
 			err = recover_inode(entry->inode, page);
 			if (err)
-				goto out;
+				goto unlock_out;
 		}
 next:
 		/* check next segment */
 		blkaddr = next_blkaddr_of_node(page);
-		ClearPageUptodate(page);
 	}
-out:
+unlock_out:
 	unlock_page(page);
+out:
 	__free_pages(page, 0);
 	return err;
 }
@@ -232,13 +234,14 @@ static void check_index_in_prev_nodes(struct f2fs_sb_info *sbi,
 	iput(inode);
 }
 
-static void do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode,
+static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode,
 					struct page *page, block_t blkaddr)
 {
 	unsigned int start, end;
 	struct dnode_of_data dn;
 	struct f2fs_summary sum;
 	struct node_info ni;
+	int err = 0;
 
 	start = start_bidx_of_node(ofs_of_node(page));
 	if (IS_INODE(page))
@@ -247,8 +250,9 @@ static void do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode,
 		end = start + ADDRS_PER_BLOCK;
 
 	set_new_dnode(&dn, inode, NULL, NULL, 0);
-	if (get_dnode_of_data(&dn, start, 0))
-		return;
+	err = get_dnode_of_data(&dn, start, ALLOC_NODE);
+	if (err)
+		return err;
 
 	wait_on_page_writeback(dn.node_page);
 
@@ -293,14 +297,16 @@ static void do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode,
 
 	recover_node_page(sbi, dn.node_page, &sum, &ni, blkaddr);
 	f2fs_put_dnode(&dn);
+	return 0;
 }
 
-static void recover_data(struct f2fs_sb_info *sbi,
+static int recover_data(struct f2fs_sb_info *sbi,
 				struct list_head *head, int type)
 {
 	unsigned long long cp_ver = le64_to_cpu(sbi->ckpt->checkpoint_ver);
 	struct curseg_info *curseg;
 	struct page *page;
+	int err = 0;
 	block_t blkaddr;
 
 	/* get node pages in the current segment */
@@ -310,23 +316,29 @@ static void recover_data(struct f2fs_sb_info *sbi,
 	/* read node page */
 	page = alloc_page(GFP_NOFS | __GFP_ZERO);
 	if (IS_ERR(page))
-		return;
+		return -ENOMEM;
+
 	lock_page(page);
 
 	while (1) {
 		struct fsync_inode_entry *entry;
 
-		if (f2fs_readpage(sbi, page, blkaddr, READ_SYNC))
+		err = f2fs_readpage(sbi, page, blkaddr, READ_SYNC);
+		if (err)
 			goto out;
 
+		lock_page(page);
+
 		if (cp_ver != cpver_of_node(page))
-			goto out;
+			goto unlock_out;
 
 		entry = get_fsync_inode(head, ino_of_node(page));
 		if (!entry)
 			goto next;
 
-		do_recover_data(sbi, entry->inode, page, blkaddr);
+		err = do_recover_data(sbi, entry->inode, page, blkaddr);
+		if (err)
+			goto out;
 
 		if (entry->blkaddr == blkaddr) {
 			iput(entry->inode);
@@ -336,28 +348,32 @@ static void recover_data(struct f2fs_sb_info *sbi,
 next:
 		/* check next segment */
 		blkaddr = next_blkaddr_of_node(page);
-		ClearPageUptodate(page);
 	}
-out:
+unlock_out:
 	unlock_page(page);
+out:
 	__free_pages(page, 0);
 
-	allocate_new_segments(sbi);
+	if (!err)
+		allocate_new_segments(sbi);
+	return err;
 }
 
-void recover_fsync_data(struct f2fs_sb_info *sbi)
+int recover_fsync_data(struct f2fs_sb_info *sbi)
 {
 	struct list_head inode_list;
+	int err;
 
 	fsync_entry_slab = f2fs_kmem_cache_create("f2fs_fsync_inode_entry",
 			sizeof(struct fsync_inode_entry), NULL);
 	if (unlikely(!fsync_entry_slab))
-		return;
+		return -ENOMEM;
 
 	INIT_LIST_HEAD(&inode_list);
 
 	/* step #1: find fsynced inode numbers */
-	if (find_fsync_dnodes(sbi, &inode_list))
+	err = find_fsync_dnodes(sbi, &inode_list);
+	if (err)
 		goto out;
 
 	if (list_empty(&inode_list))
@@ -365,11 +381,12 @@ void recover_fsync_data(struct f2fs_sb_info *sbi)
 
 	/* step #2: recover data */
 	sbi->por_doing = 1;
-	recover_data(sbi, &inode_list, CURSEG_WARM_NODE);
+	err = recover_data(sbi, &inode_list, CURSEG_WARM_NODE);
 	sbi->por_doing = 0;
 	BUG_ON(!list_empty(&inode_list));
 out:
 	destroy_fsync_dnodes(sbi, &inode_list);
 	kmem_cache_destroy(fsync_entry_slab);
 	write_checkpoint(sbi, false);
+	return err;
 }
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index 777f17e..c83a59a 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -49,9 +49,20 @@ static void __locate_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno,
 
 	if (dirty_type == DIRTY) {
 		struct seg_entry *sentry = get_seg_entry(sbi, segno);
+		enum dirty_type t = DIRTY_HOT_DATA;
+
 		dirty_type = sentry->type;
+
 		if (!test_and_set_bit(segno, dirty_i->dirty_segmap[dirty_type]))
 			dirty_i->nr_dirty[dirty_type]++;
+
+		/* Only one bitmap should be set */
+		for (; t <= DIRTY_COLD_NODE; t++) {
+			if (t == dirty_type)
+				continue;
+			if (test_and_clear_bit(segno, dirty_i->dirty_segmap[t]))
+				dirty_i->nr_dirty[t]--;
+		}
 	}
 }
 
@@ -64,13 +75,16 @@ static void __remove_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno,
 		dirty_i->nr_dirty[dirty_type]--;
 
 	if (dirty_type == DIRTY) {
-		struct seg_entry *sentry = get_seg_entry(sbi, segno);
-		dirty_type = sentry->type;
-		if (test_and_clear_bit(segno,
-					dirty_i->dirty_segmap[dirty_type]))
-			dirty_i->nr_dirty[dirty_type]--;
-		clear_bit(segno, dirty_i->victim_segmap[FG_GC]);
-		clear_bit(segno, dirty_i->victim_segmap[BG_GC]);
+		enum dirty_type t = DIRTY_HOT_DATA;
+
+		/* clear all the bitmaps */
+		for (; t <= DIRTY_COLD_NODE; t++)
+			if (test_and_clear_bit(segno, dirty_i->dirty_segmap[t]))
+				dirty_i->nr_dirty[t]--;
+
+		if (get_valid_blocks(sbi, segno, sbi->segs_per_sec) == 0)
+			clear_bit(GET_SECNO(sbi, segno),
+						dirty_i->victim_secmap);
 	}
 }
 
@@ -296,13 +310,12 @@ static void write_sum_page(struct f2fs_sb_info *sbi,
 	f2fs_put_page(page, 1);
 }
 
-static unsigned int check_prefree_segments(struct f2fs_sb_info *sbi,
-					int ofs_unit, int type)
+static unsigned int check_prefree_segments(struct f2fs_sb_info *sbi, int type)
 {
 	struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
 	unsigned long *prefree_segmap = dirty_i->dirty_segmap[PRE];
-	unsigned int segno, next_segno, i;
-	int ofs = 0;
+	unsigned int segno;
+	unsigned int ofs = 0;
 
 	/*
 	 * If there is not enough reserved sections,
@@ -318,28 +331,46 @@ static unsigned int check_prefree_segments(struct f2fs_sb_info *sbi,
 	if (IS_NODESEG(type))
 		return NULL_SEGNO;
 next:
-	segno = find_next_bit(prefree_segmap, TOTAL_SEGS(sbi), ofs++);
-	ofs = ((segno / ofs_unit) * ofs_unit) + ofs_unit;
+	segno = find_next_bit(prefree_segmap, TOTAL_SEGS(sbi), ofs);
+	ofs += sbi->segs_per_sec;
+
 	if (segno < TOTAL_SEGS(sbi)) {
+		int i;
+
 		/* skip intermediate segments in a section */
-		if (segno % ofs_unit)
+		if (segno % sbi->segs_per_sec)
 			goto next;
 
-		/* skip if whole section is not prefree */
-		next_segno = find_next_zero_bit(prefree_segmap,
-						TOTAL_SEGS(sbi), segno + 1);
-		if (next_segno - segno < ofs_unit)
+		/* skip if the section is currently used */
+		if (sec_usage_check(sbi, GET_SECNO(sbi, segno)))
 			goto next;
 
+		/* skip if whole section is not prefree */
+		for (i = 1; i < sbi->segs_per_sec; i++)
+			if (!test_bit(segno + i, prefree_segmap))
+				goto next;
+
 		/* skip if whole section was not free at the last checkpoint */
-		for (i = 0; i < ofs_unit; i++)
-			if (get_seg_entry(sbi, segno)->ckpt_valid_blocks)
+		for (i = 0; i < sbi->segs_per_sec; i++)
+			if (get_seg_entry(sbi, segno + i)->ckpt_valid_blocks)
 				goto next;
+
 		return segno;
 	}
 	return NULL_SEGNO;
 }
 
+static int is_next_segment_free(struct f2fs_sb_info *sbi, int type)
+{
+	struct curseg_info *curseg = CURSEG_I(sbi, type);
+	unsigned int segno = curseg->segno;
+	struct free_segmap_info *free_i = FREE_I(sbi);
+
+	if (segno + 1 < TOTAL_SEGS(sbi) && (segno + 1) % sbi->segs_per_sec)
+		return !test_bit(segno + 1, free_i->free_segmap);
+	return 0;
+}
+
 /*
  * Find a new segment from the free segments bitmap to right order
  * This function should be returned with success, otherwise BUG
@@ -348,9 +379,8 @@ static void get_new_segment(struct f2fs_sb_info *sbi,
 			unsigned int *newseg, bool new_sec, int dir)
 {
 	struct free_segmap_info *free_i = FREE_I(sbi);
-	unsigned int total_secs = sbi->total_sections;
 	unsigned int segno, secno, zoneno;
-	unsigned int total_zones = sbi->total_sections / sbi->secs_per_zone;
+	unsigned int total_zones = TOTAL_SECS(sbi) / sbi->secs_per_zone;
 	unsigned int hint = *newseg / sbi->segs_per_sec;
 	unsigned int old_zoneno = GET_ZONENO_FROM_SEGNO(sbi, *newseg);
 	unsigned int left_start = hint;
@@ -363,16 +393,17 @@ static void get_new_segment(struct f2fs_sb_info *sbi,
 	if (!new_sec && ((*newseg + 1) % sbi->segs_per_sec)) {
 		segno = find_next_zero_bit(free_i->free_segmap,
 					TOTAL_SEGS(sbi), *newseg + 1);
-		if (segno < TOTAL_SEGS(sbi))
+		if (segno - *newseg < sbi->segs_per_sec -
+					(*newseg % sbi->segs_per_sec))
 			goto got_it;
 	}
 find_other_zone:
-	secno = find_next_zero_bit(free_i->free_secmap, total_secs, hint);
-	if (secno >= total_secs) {
+	secno = find_next_zero_bit(free_i->free_secmap, TOTAL_SECS(sbi), hint);
+	if (secno >= TOTAL_SECS(sbi)) {
 		if (dir == ALLOC_RIGHT) {
 			secno = find_next_zero_bit(free_i->free_secmap,
-						total_secs, 0);
-			BUG_ON(secno >= total_secs);
+							TOTAL_SECS(sbi), 0);
+			BUG_ON(secno >= TOTAL_SECS(sbi));
 		} else {
 			go_left = 1;
 			left_start = hint - 1;
@@ -387,8 +418,8 @@ find_other_zone:
 			continue;
 		}
 		left_start = find_next_zero_bit(free_i->free_secmap,
-						total_secs, 0);
-		BUG_ON(left_start >= total_secs);
+							TOTAL_SECS(sbi), 0);
+		BUG_ON(left_start >= TOTAL_SECS(sbi));
 		break;
 	}
 	secno = left_start;
@@ -561,20 +592,20 @@ static void allocate_segment_by_default(struct f2fs_sb_info *sbi,
 						int type, bool force)
 {
 	struct curseg_info *curseg = CURSEG_I(sbi, type);
-	unsigned int ofs_unit;
 
 	if (force) {
 		new_curseg(sbi, type, true);
 		goto out;
 	}
 
-	ofs_unit = need_SSR(sbi) ? 1 : sbi->segs_per_sec;
-	curseg->next_segno = check_prefree_segments(sbi, ofs_unit, type);
+	curseg->next_segno = check_prefree_segments(sbi, type);
 
 	if (curseg->next_segno != NULL_SEGNO)
 		change_curseg(sbi, type, false);
 	else if (type == CURSEG_WARM_NODE)
 		new_curseg(sbi, type, false);
+	else if (curseg->alloc_type == LFS && is_next_segment_free(sbi, type))
+		new_curseg(sbi, type, false);
 	else if (need_SSR(sbi) && get_ssr_segment(sbi, type))
 		change_curseg(sbi, type, true);
 	else
@@ -601,7 +632,8 @@ static const struct segment_allocation default_salloc_ops = {
 	.allocate_segment = allocate_segment_by_default,
 };
 
-static void f2fs_end_io_write(struct bio *bio, int err)
+static void f2fs_end_io_write(struct bio *bio, int err,
+			      struct batch_complete *batch)
 {
 	const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
 	struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1;
@@ -1390,7 +1422,7 @@ static int build_sit_info(struct f2fs_sb_info *sbi)
 	}
 
 	if (sbi->segs_per_sec > 1) {
-		sit_i->sec_entries = vzalloc(sbi->total_sections *
+		sit_i->sec_entries = vzalloc(TOTAL_SECS(sbi) *
 					sizeof(struct sec_entry));
 		if (!sit_i->sec_entries)
 			return -ENOMEM;
@@ -1403,10 +1435,9 @@ static int build_sit_info(struct f2fs_sb_info *sbi)
 	bitmap_size = __bitmap_size(sbi, SIT_BITMAP);
 	src_bitmap = __bitmap_ptr(sbi, SIT_BITMAP);
 
-	dst_bitmap = kzalloc(bitmap_size, GFP_KERNEL);
+	dst_bitmap = kmemdup(src_bitmap, bitmap_size, GFP_KERNEL);
 	if (!dst_bitmap)
 		return -ENOMEM;
-	memcpy(dst_bitmap, src_bitmap, bitmap_size);
 
 	/* init SIT information */
 	sit_i->s_ops = &default_salloc_ops;
@@ -1442,7 +1473,7 @@ static int build_free_segmap(struct f2fs_sb_info *sbi)
 	if (!free_i->free_segmap)
 		return -ENOMEM;
 
-	sec_bitmap_size = f2fs_bitmap_size(sbi->total_sections);
+	sec_bitmap_size = f2fs_bitmap_size(TOTAL_SECS(sbi));
 	free_i->free_secmap = kmalloc(sec_bitmap_size, GFP_KERNEL);
 	if (!free_i->free_secmap)
 		return -ENOMEM;
@@ -1559,14 +1590,13 @@ static void init_dirty_segmap(struct f2fs_sb_info *sbi)
 	}
 }
 
-static int init_victim_segmap(struct f2fs_sb_info *sbi)
+static int init_victim_secmap(struct f2fs_sb_info *sbi)
 {
 	struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
-	unsigned int bitmap_size = f2fs_bitmap_size(TOTAL_SEGS(sbi));
+	unsigned int bitmap_size = f2fs_bitmap_size(TOTAL_SECS(sbi));
 
-	dirty_i->victim_segmap[FG_GC] = kzalloc(bitmap_size, GFP_KERNEL);
-	dirty_i->victim_segmap[BG_GC] = kzalloc(bitmap_size, GFP_KERNEL);
-	if (!dirty_i->victim_segmap[FG_GC] || !dirty_i->victim_segmap[BG_GC])
+	dirty_i->victim_secmap = kzalloc(bitmap_size, GFP_KERNEL);
+	if (!dirty_i->victim_secmap)
 		return -ENOMEM;
 	return 0;
 }
@@ -1593,7 +1623,7 @@ static int build_dirty_segmap(struct f2fs_sb_info *sbi)
 	}
 
 	init_dirty_segmap(sbi);
-	return init_victim_segmap(sbi);
+	return init_victim_secmap(sbi);
 }
 
 /*
@@ -1680,18 +1710,10 @@ static void discard_dirty_segmap(struct f2fs_sb_info *sbi,
 	mutex_unlock(&dirty_i->seglist_lock);
 }
 
-void reset_victim_segmap(struct f2fs_sb_info *sbi)
-{
-	unsigned int bitmap_size = f2fs_bitmap_size(TOTAL_SEGS(sbi));
-	memset(DIRTY_I(sbi)->victim_segmap[FG_GC], 0, bitmap_size);
-}
-
-static void destroy_victim_segmap(struct f2fs_sb_info *sbi)
+static void destroy_victim_secmap(struct f2fs_sb_info *sbi)
 {
 	struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
-
-	kfree(dirty_i->victim_segmap[FG_GC]);
-	kfree(dirty_i->victim_segmap[BG_GC]);
+	kfree(dirty_i->victim_secmap);
 }
 
 static void destroy_dirty_segmap(struct f2fs_sb_info *sbi)
@@ -1706,7 +1728,7 @@ static void destroy_dirty_segmap(struct f2fs_sb_info *sbi)
 	for (i = 0; i < NR_DIRTY_TYPE; i++)
 		discard_dirty_segmap(sbi, i);
 
-	destroy_victim_segmap(sbi);
+	destroy_victim_secmap(sbi);
 	SM_I(sbi)->dirty_info = NULL;
 	kfree(dirty_i);
 }
diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h
index 552dadb..4c2cd9e 100644
--- a/fs/f2fs/segment.h
+++ b/fs/f2fs/segment.h
@@ -23,13 +23,13 @@
 	((t == CURSEG_HOT_NODE) || (t == CURSEG_COLD_NODE) ||		\
 	(t == CURSEG_WARM_NODE))
 
-#define IS_CURSEG(sbi, segno)						\
-	((segno == CURSEG_I(sbi, CURSEG_HOT_DATA)->segno) ||	\
-	 (segno == CURSEG_I(sbi, CURSEG_WARM_DATA)->segno) ||	\
-	 (segno == CURSEG_I(sbi, CURSEG_COLD_DATA)->segno) ||	\
-	 (segno == CURSEG_I(sbi, CURSEG_HOT_NODE)->segno) ||	\
-	 (segno == CURSEG_I(sbi, CURSEG_WARM_NODE)->segno) ||	\
-	 (segno == CURSEG_I(sbi, CURSEG_COLD_NODE)->segno))
+#define IS_CURSEG(sbi, seg)						\
+	((seg == CURSEG_I(sbi, CURSEG_HOT_DATA)->segno) ||	\
+	 (seg == CURSEG_I(sbi, CURSEG_WARM_DATA)->segno) ||	\
+	 (seg == CURSEG_I(sbi, CURSEG_COLD_DATA)->segno) ||	\
+	 (seg == CURSEG_I(sbi, CURSEG_HOT_NODE)->segno) ||	\
+	 (seg == CURSEG_I(sbi, CURSEG_WARM_NODE)->segno) ||	\
+	 (seg == CURSEG_I(sbi, CURSEG_COLD_NODE)->segno))
 
 #define IS_CURSEC(sbi, secno)						\
 	((secno == CURSEG_I(sbi, CURSEG_HOT_DATA)->segno /		\
@@ -81,6 +81,7 @@
 #define f2fs_bitmap_size(nr)			\
 	(BITS_TO_LONGS(nr) * sizeof(unsigned long))
 #define TOTAL_SEGS(sbi)	(SM_I(sbi)->main_segments)
+#define TOTAL_SECS(sbi)	(sbi->total_sections)
 
 #define SECTOR_FROM_BLOCK(sbi, blk_addr)				\
 	(blk_addr << ((sbi)->log_blocksize - F2FS_LOG_SECTOR_SIZE))
@@ -213,7 +214,7 @@ struct dirty_seglist_info {
 	unsigned long *dirty_segmap[NR_DIRTY_TYPE];
 	struct mutex seglist_lock;		/* lock for segment bitmaps */
 	int nr_dirty[NR_DIRTY_TYPE];		/* # of dirty segments */
-	unsigned long *victim_segmap[2];	/* BG_GC, FG_GC */
+	unsigned long *victim_secmap;		/* background GC victims */
 };
 
 /* victim selection function for cleaning and SSR */
@@ -464,8 +465,7 @@ static inline bool has_not_enough_free_secs(struct f2fs_sb_info *sbi, int freed)
 
 static inline int utilization(struct f2fs_sb_info *sbi)
 {
-	return (long int)valid_user_blocks(sbi) * 100 /
-			(long int)sbi->user_block_count;
+	return div_u64(valid_user_blocks(sbi) * 100, sbi->user_block_count);
 }
 
 /*
@@ -616,3 +616,12 @@ static inline block_t sum_blk_addr(struct f2fs_sb_info *sbi, int base, int type)
 		le32_to_cpu(F2FS_CKPT(sbi)->cp_pack_total_block_count)
 				- (base + 1) + type;
 }
+
+static inline int sec_usage_check(struct f2fs_sb_info *sbi, unsigned int secno)
+{
+	if (IS_CURSEC(sbi, secno))
+		return -1;
+	if (sbi->cur_victim_sec == secno)
+		return -1;
+	return 0;
+}
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index fea6e58..a756204 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -21,10 +21,12 @@
 #include <linux/seq_file.h>
 #include <linux/random.h>
 #include <linux/exportfs.h>
+#include <linux/blkdev.h>
 #include <linux/f2fs_fs.h>
 
 #include "f2fs.h"
 #include "node.h"
+#include "segment.h"
 #include "xattr.h"
 
 static struct kmem_cache *f2fs_inode_cachep;
@@ -82,7 +84,7 @@ static struct inode *f2fs_alloc_inode(struct super_block *sb)
 
 	init_once((void *) fi);
 
-	/* Initilize f2fs-specific inode info */
+	/* Initialize f2fs-specific inode info */
 	fi->vfs_inode.i_version = 1;
 	atomic_set(&fi->dirty_dents, 0);
 	fi->i_current_depth = 1;
@@ -135,10 +137,13 @@ int f2fs_sync_fs(struct super_block *sb, int sync)
 	if (!sbi->s_dirty && !get_pages(sbi, F2FS_DIRTY_NODES))
 		return 0;
 
-	if (sync)
+	if (sync) {
+		mutex_lock(&sbi->gc_mutex);
 		write_checkpoint(sbi, false);
-	else
+		mutex_unlock(&sbi->gc_mutex);
+	} else {
 		f2fs_balance_fs(sbi);
+	}
 
 	return 0;
 }
@@ -180,7 +185,7 @@ static int f2fs_statfs(struct dentry *dentry, struct kstatfs *buf)
 	buf->f_files = sbi->total_node_count;
 	buf->f_ffree = sbi->total_node_count - valid_inode_count(sbi);
 
-	buf->f_namelen = F2FS_MAX_NAME_LEN;
+	buf->f_namelen = F2FS_NAME_LEN;
 	buf->f_fsid.val[0] = (u32)id;
 	buf->f_fsid.val[1] = (u32)(id >> 32);
 
@@ -457,6 +462,7 @@ static void init_sb_info(struct f2fs_sb_info *sbi)
 	sbi->root_ino_num = le32_to_cpu(raw_super->root_ino);
 	sbi->node_ino_num = le32_to_cpu(raw_super->node_ino);
 	sbi->meta_ino_num = le32_to_cpu(raw_super->meta_ino);
+	sbi->cur_victim_sec = NULL_SEGNO;
 
 	for (i = 0; i < NR_COUNT_TYPE; i++)
 		atomic_set(&sbi->nr_pages[i], 0);
@@ -473,7 +479,7 @@ static int validate_superblock(struct super_block *sb,
 	if (!*raw_super_buf) {
 		f2fs_msg(sb, KERN_ERR, "unable to read %s superblock",
 				super);
-		return 1;
+		return -EIO;
 	}
 
 	*raw_super = (struct f2fs_super_block *)
@@ -485,7 +491,7 @@ static int validate_superblock(struct super_block *sb,
 
 	f2fs_msg(sb, KERN_ERR, "Can't find a valid F2FS filesystem "
 				"in %s superblock", super);
-	return 1;
+	return -EINVAL;
 }
 
 static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
@@ -508,9 +514,12 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
 		goto free_sbi;
 	}
 
-	if (validate_superblock(sb, &raw_super, &raw_super_buf, 0)) {
+	err = validate_superblock(sb, &raw_super, &raw_super_buf, 0);
+	if (err) {
 		brelse(raw_super_buf);
-		if (validate_superblock(sb, &raw_super, &raw_super_buf, 1))
+		/* check secondary superblock when primary failed */
+		err = validate_superblock(sb, &raw_super, &raw_super_buf, 1);
+		if (err)
 			goto free_sb_buf;
 	}
 	/* init some FS parameters */
@@ -638,8 +647,13 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
 	}
 
 	/* recover fsynced data */
-	if (!test_opt(sbi, DISABLE_ROLL_FORWARD))
-		recover_fsync_data(sbi);
+	if (!test_opt(sbi, DISABLE_ROLL_FORWARD)) {
+		err = recover_fsync_data(sbi);
+		if (err) {
+			f2fs_msg(sb, KERN_ERR, "Failed to recover fsync data");
+			goto free_root_inode;
+		}
+	}
 
 	/* After POR, we can run background GC thread */
 	err = start_gc_thread(sbi);
@@ -650,6 +664,14 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
 	if (err)
 		goto fail;
 
+	if (test_opt(sbi, DISCARD)) {
+		struct request_queue *q = bdev_get_queue(sb->s_bdev);
+		if (!blk_queue_discard(q))
+			f2fs_msg(sb, KERN_WARNING,
+					"mounting with \"discard\" option, but "
+					"the device does not support discard");
+	}
+
 	return 0;
 fail:
 	stop_gc_thread(sbi);
diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c
index 8038c04..3bfea80 100644
--- a/fs/f2fs/xattr.c
+++ b/fs/f2fs/xattr.c
@@ -310,12 +310,13 @@ int f2fs_setxattr(struct inode *inode, int name_index, const char *name,
 
 	if (name == NULL)
 		return -EINVAL;
-	name_len = strlen(name);
 
 	if (value == NULL)
 		value_len = 0;
 
-	if (name_len > 255 || value_len > MAX_VALUE_LEN)
+	name_len = strlen(name);
+
+	if (name_len > F2FS_NAME_LEN || value_len > MAX_VALUE_LEN)
 		return -ERANGE;
 
 	f2fs_balance_fs(sbi);
@@ -326,8 +327,8 @@ int f2fs_setxattr(struct inode *inode, int name_index, const char *name,
 		struct dnode_of_data dn;
 
 		if (!alloc_nid(sbi, &fi->i_xattr_nid)) {
-			mutex_unlock_op(sbi, NODE_NEW);
-			return -ENOSPC;
+			error = -ENOSPC;
+			goto exit;
 		}
 		set_new_dnode(&dn, inode, NULL, NULL, fi->i_xattr_nid);
 		mark_inode_dirty(inode);
@@ -336,8 +337,8 @@ int f2fs_setxattr(struct inode *inode, int name_index, const char *name,
 		if (IS_ERR(page)) {
 			alloc_nid_failed(sbi, fi->i_xattr_nid);
 			fi->i_xattr_nid = 0;
-			mutex_unlock_op(sbi, NODE_NEW);
-			return PTR_ERR(page);
+			error = PTR_ERR(page);
+			goto exit;
 		}
 
 		alloc_nid_done(sbi, fi->i_xattr_nid);
@@ -349,8 +350,8 @@ int f2fs_setxattr(struct inode *inode, int name_index, const char *name,
 		/* The inode already has an extended attribute block. */
 		page = get_node_page(sbi, fi->i_xattr_nid);
 		if (IS_ERR(page)) {
-			mutex_unlock_op(sbi, NODE_NEW);
-			return PTR_ERR(page);
+			error = PTR_ERR(page);
+			goto exit;
 		}
 
 		base_addr = page_address(page);
@@ -438,6 +439,7 @@ int f2fs_setxattr(struct inode *inode, int name_index, const char *name,
 	return 0;
 cleanup:
 	f2fs_put_page(page, 1);
+exit:
 	mutex_unlock_op(sbi, NODE_NEW);
 	return error;
 }
diff --git a/fs/fat/dir.c b/fs/fat/dir.c
index 165012e..7a6f02c 100644
--- a/fs/fat/dir.c
+++ b/fs/fat/dir.c
@@ -964,6 +964,29 @@ int fat_scan(struct inode *dir, const unsigned char *name,
 }
 EXPORT_SYMBOL_GPL(fat_scan);
 
+/*
+ * Scans a directory for a given logstart.
+ * Returns an error code or zero.
+ */
+int fat_scan_logstart(struct inode *dir, int i_logstart,
+		      struct fat_slot_info *sinfo)
+{
+	struct super_block *sb = dir->i_sb;
+
+	sinfo->slot_off = 0;
+	sinfo->bh = NULL;
+	while (fat_get_short_entry(dir, &sinfo->slot_off, &sinfo->bh,
+				   &sinfo->de) >= 0) {
+		if (fat_get_start(MSDOS_SB(sb), sinfo->de) == i_logstart) {
+			sinfo->slot_off -= sizeof(*sinfo->de);
+			sinfo->nr_slots = 1;
+			sinfo->i_pos = fat_make_i_pos(sb, sinfo->bh, sinfo->de);
+			return 0;
+		}
+	}
+	return -ENOENT;
+}
+
 static int __fat_remove_entries(struct inode *dir, loff_t pos, int nr_slots)
 {
 	struct super_block *sb = dir->i_sb;
diff --git a/fs/fat/fat.h b/fs/fat/fat.h
index e9cc3f0..21664fc 100644
--- a/fs/fat/fat.h
+++ b/fs/fat/fat.h
@@ -23,6 +23,9 @@
 #define FAT_ERRORS_PANIC	2      /* panic on error */
 #define FAT_ERRORS_RO		3      /* remount r/o on error */
 
+#define FAT_NFS_STALE_RW	1      /* NFS RW support, can cause ESTALE */
+#define FAT_NFS_NOSTALE_RO	2      /* NFS RO support, no ESTALE issue */
+
 struct fat_mount_options {
 	kuid_t fs_uid;
 	kgid_t fs_gid;
@@ -34,6 +37,7 @@ struct fat_mount_options {
 	unsigned short shortname;  /* flags for shortname display/create rule */
 	unsigned char name_check;  /* r = relaxed, n = normal, s = strict */
 	unsigned char errors;	   /* On error: continue, panic, remount-ro */
+	unsigned char nfs;	  /* NFS support: nostale_ro, stale_rw */
 	unsigned short allow_utime;/* permission for setting the [am]time */
 	unsigned quiet:1,          /* set = fake successful chmods and chowns */
 		 showexec:1,       /* set = only set x bit for com/exe/bat */
@@ -48,8 +52,7 @@ struct fat_mount_options {
 		 usefree:1,	   /* Use free_clusters for FAT32 */
 		 tz_set:1,	   /* Filesystem timestamps' offset set */
 		 rodir:1,	   /* allow ATTR_RO for directory */
-		 discard:1,	   /* Issue discard requests on deletions */
-		 nfs:1;		   /* Do extra work needed for NFS export */
+		 discard:1;	   /* Issue discard requests on deletions */
 };
 
 #define FAT_HASH_BITS	8
@@ -72,6 +75,7 @@ struct msdos_sb_info {
 	unsigned long root_cluster;   /* first cluster of the root directory */
 	unsigned long fsinfo_sector;  /* sector number of FAT32 fsinfo */
 	struct mutex fat_lock;
+	struct mutex nfs_build_inode_lock;
 	struct mutex s_lock;
 	unsigned int prev_free;      /* previously allocated cluster number */
 	unsigned int free_clusters;  /* -1 if undefined */
@@ -215,6 +219,27 @@ static inline sector_t fat_clus_to_blknr(struct msdos_sb_info *sbi, int clus)
 		+ sbi->data_start;
 }
 
+static inline void fat_get_blknr_offset(struct msdos_sb_info *sbi,
+				loff_t i_pos, sector_t *blknr, int *offset)
+{
+	*blknr = i_pos >> sbi->dir_per_block_bits;
+	*offset = i_pos & (sbi->dir_per_block - 1);
+}
+
+static inline loff_t fat_i_pos_read(struct msdos_sb_info *sbi,
+					struct inode *inode)
+{
+	loff_t i_pos;
+#if BITS_PER_LONG == 32
+	spin_lock(&sbi->inode_hash_lock);
+#endif
+	i_pos = MSDOS_I(inode)->i_pos;
+#if BITS_PER_LONG == 32
+	spin_unlock(&sbi->inode_hash_lock);
+#endif
+	return i_pos;
+}
+
 static inline void fat16_towchar(wchar_t *dst, const __u8 *src, size_t len)
 {
 #ifdef __BIG_ENDIAN
@@ -271,6 +296,8 @@ extern int fat_dir_empty(struct inode *dir);
 extern int fat_subdirs(struct inode *dir);
 extern int fat_scan(struct inode *dir, const unsigned char *name,
 		    struct fat_slot_info *sinfo);
+extern int fat_scan_logstart(struct inode *dir, int i_logstart,
+			     struct fat_slot_info *sinfo);
 extern int fat_get_dotdot_entry(struct inode *dir, struct buffer_head **bh,
 				struct msdos_dir_entry **de);
 extern int fat_alloc_new_dir(struct inode *dir, struct timespec *ts);
@@ -348,6 +375,7 @@ extern struct inode *fat_build_inode(struct super_block *sb,
 extern int fat_sync_inode(struct inode *inode);
 extern int fat_fill_super(struct super_block *sb, void *data, int silent,
 			  int isvfat, void (*setup)(struct super_block *));
+extern int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de);
 
 extern int fat_flush_inodes(struct super_block *sb, struct inode *i1,
 			    struct inode *i2);
@@ -382,12 +410,8 @@ int fat_cache_init(void);
 void fat_cache_destroy(void);
 
 /* fat/nfs.c */
-struct fid;
-extern struct dentry *fat_fh_to_dentry(struct super_block *sb, struct fid *fid,
-				       int fh_len, int fh_type);
-extern struct dentry *fat_fh_to_parent(struct super_block *sb, struct fid *fid,
-				       int fh_len, int fh_type);
-extern struct dentry *fat_get_parent(struct dentry *child_dir);
+extern const struct export_operations fat_export_ops;
+extern const struct export_operations fat_export_ops_nostale;
 
 /* helper for printk */
 typedef unsigned long long	llu;
diff --git a/fs/fat/file.c b/fs/fat/file.c
index 3978f8c..b0b632e 100644
--- a/fs/fat/file.c
+++ b/fs/fat/file.c
@@ -306,6 +306,11 @@ int fat_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
 	struct inode *inode = dentry->d_inode;
 	generic_fillattr(inode, stat);
 	stat->blksize = MSDOS_SB(inode->i_sb)->cluster_size;
+
+	if (MSDOS_SB(inode->i_sb)->options.nfs == FAT_NFS_NOSTALE_RO) {
+		/* Use i_pos for ino. This is used as fileid of nfs. */
+		stat->ino = fat_i_pos_read(MSDOS_SB(inode->i_sb), inode);
+	}
 	return 0;
 }
 EXPORT_SYMBOL_GPL(fat_getattr);
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index acf6e47..dfce656 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -18,8 +18,8 @@
 #include <linux/pagemap.h>
 #include <linux/mpage.h>
 #include <linux/buffer_head.h>
-#include <linux/exportfs.h>
 #include <linux/mount.h>
+#include <linux/aio.h>
 #include <linux/vfs.h>
 #include <linux/parser.h>
 #include <linux/uio.h>
@@ -385,7 +385,7 @@ static int fat_calc_dir_size(struct inode *inode)
 }
 
 /* doesn't deal with root inode */
-static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de)
+int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de)
 {
 	struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
 	int error;
@@ -444,12 +444,25 @@ static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de)
 	return 0;
 }
 
+static inline void fat_lock_build_inode(struct msdos_sb_info *sbi)
+{
+	if (sbi->options.nfs == FAT_NFS_NOSTALE_RO)
+		mutex_lock(&sbi->nfs_build_inode_lock);
+}
+
+static inline void fat_unlock_build_inode(struct msdos_sb_info *sbi)
+{
+	if (sbi->options.nfs == FAT_NFS_NOSTALE_RO)
+		mutex_unlock(&sbi->nfs_build_inode_lock);
+}
+
 struct inode *fat_build_inode(struct super_block *sb,
 			struct msdos_dir_entry *de, loff_t i_pos)
 {
 	struct inode *inode;
 	int err;
 
+	fat_lock_build_inode(MSDOS_SB(sb));
 	inode = fat_iget(sb, i_pos);
 	if (inode)
 		goto out;
@@ -469,6 +482,7 @@ struct inode *fat_build_inode(struct super_block *sb,
 	fat_attach(inode, i_pos);
 	insert_inode_hash(inode);
 out:
+	fat_unlock_build_inode(MSDOS_SB(sb));
 	return inode;
 }
 
@@ -655,20 +669,6 @@ static int fat_statfs(struct dentry *dentry, struct kstatfs *buf)
 	return 0;
 }
 
-static inline loff_t fat_i_pos_read(struct msdos_sb_info *sbi,
-				    struct inode *inode)
-{
-	loff_t i_pos;
-#if BITS_PER_LONG == 32
-	spin_lock(&sbi->inode_hash_lock);
-#endif
-	i_pos = MSDOS_I(inode)->i_pos;
-#if BITS_PER_LONG == 32
-	spin_unlock(&sbi->inode_hash_lock);
-#endif
-	return i_pos;
-}
-
 static int __fat_write_inode(struct inode *inode, int wait)
 {
 	struct super_block *sb = inode->i_sb;
@@ -676,7 +676,8 @@ static int __fat_write_inode(struct inode *inode, int wait)
 	struct buffer_head *bh;
 	struct msdos_dir_entry *raw_entry;
 	loff_t i_pos;
-	int err;
+	sector_t blocknr;
+	int err, offset;
 
 	if (inode->i_ino == MSDOS_ROOT_INO)
 		return 0;
@@ -686,7 +687,8 @@ retry:
 	if (!i_pos)
 		return 0;
 
-	bh = sb_bread(sb, i_pos >> sbi->dir_per_block_bits);
+	fat_get_blknr_offset(sbi, i_pos, &blocknr, &offset);
+	bh = sb_bread(sb, blocknr);
 	if (!bh) {
 		fat_msg(sb, KERN_ERR, "unable to read inode block "
 		       "for updating (i_pos %lld)", i_pos);
@@ -699,8 +701,7 @@ retry:
 		goto retry;
 	}
 
-	raw_entry = &((struct msdos_dir_entry *) (bh->b_data))
-	    [i_pos & (sbi->dir_per_block - 1)];
+	raw_entry = &((struct msdos_dir_entry *) (bh->b_data))[offset];
 	if (S_ISDIR(inode->i_mode))
 		raw_entry->size = 0;
 	else
@@ -761,12 +762,6 @@ static const struct super_operations fat_sops = {
 	.show_options	= fat_show_options,
 };
 
-static const struct export_operations fat_export_ops = {
-	.fh_to_dentry	= fat_fh_to_dentry,
-	.fh_to_parent	= fat_fh_to_parent,
-	.get_parent	= fat_get_parent,
-};
-
 static int fat_show_options(struct seq_file *m, struct dentry *root)
 {
 	struct msdos_sb_info *sbi = MSDOS_SB(root->d_sb);
@@ -814,8 +809,6 @@ static int fat_show_options(struct seq_file *m, struct dentry *root)
 		seq_puts(m, ",usefree");
 	if (opts->quiet)
 		seq_puts(m, ",quiet");
-	if (opts->nfs)
-		seq_puts(m, ",nfs");
 	if (opts->showexec)
 		seq_puts(m, ",showexec");
 	if (opts->sys_immutable)
@@ -849,6 +842,10 @@ static int fat_show_options(struct seq_file *m, struct dentry *root)
 		seq_puts(m, ",errors=panic");
 	else
 		seq_puts(m, ",errors=remount-ro");
+	if (opts->nfs == FAT_NFS_NOSTALE_RO)
+		seq_puts(m, ",nfs=nostale_ro");
+	else if (opts->nfs)
+		seq_puts(m, ",nfs=stale_rw");
 	if (opts->discard)
 		seq_puts(m, ",discard");
 
@@ -865,7 +862,7 @@ enum {
 	Opt_uni_xl_no, Opt_uni_xl_yes, Opt_nonumtail_no, Opt_nonumtail_yes,
 	Opt_obsolete, Opt_flush, Opt_tz_utc, Opt_rodir, Opt_err_cont,
 	Opt_err_panic, Opt_err_ro, Opt_discard, Opt_nfs, Opt_time_offset,
-	Opt_err,
+	Opt_nfs_stale_rw, Opt_nfs_nostale_ro, Opt_err,
 };
 
 static const match_table_t fat_tokens = {
@@ -895,7 +892,9 @@ static const match_table_t fat_tokens = {
 	{Opt_err_panic, "errors=panic"},
 	{Opt_err_ro, "errors=remount-ro"},
 	{Opt_discard, "discard"},
-	{Opt_nfs, "nfs"},
+	{Opt_nfs_stale_rw, "nfs"},
+	{Opt_nfs_stale_rw, "nfs=stale_rw"},
+	{Opt_nfs_nostale_ro, "nfs=nostale_ro"},
 	{Opt_obsolete, "conv=binary"},
 	{Opt_obsolete, "conv=text"},
 	{Opt_obsolete, "conv=auto"},
@@ -1092,6 +1091,12 @@ static int parse_options(struct super_block *sb, char *options, int is_vfat,
 		case Opt_err_ro:
 			opts->errors = FAT_ERRORS_RO;
 			break;
+		case Opt_nfs_stale_rw:
+			opts->nfs = FAT_NFS_STALE_RW;
+			break;
+		case Opt_nfs_nostale_ro:
+			opts->nfs = FAT_NFS_NOSTALE_RO;
+			break;
 
 		/* msdos specific */
 		case Opt_dots:
@@ -1150,9 +1155,6 @@ static int parse_options(struct super_block *sb, char *options, int is_vfat,
 		case Opt_discard:
 			opts->discard = 1;
 			break;
-		case Opt_nfs:
-			opts->nfs = 1;
-			break;
 
 		/* obsolete mount options */
 		case Opt_obsolete:
@@ -1183,6 +1185,10 @@ out:
 		opts->allow_utime = ~opts->fs_dmask & (S_IWGRP | S_IWOTH);
 	if (opts->unicode_xlate)
 		opts->utf8 = 0;
+	if (opts->nfs == FAT_NFS_NOSTALE_RO) {
+		sb->s_flags |= MS_RDONLY;
+		sb->s_export_op = &fat_export_ops_nostale;
+	}
 
 	return 0;
 }
@@ -1193,7 +1199,7 @@ static int fat_read_root(struct inode *inode)
 	struct msdos_sb_info *sbi = MSDOS_SB(sb);
 	int error;
 
-	MSDOS_I(inode)->i_pos = 0;
+	MSDOS_I(inode)->i_pos = MSDOS_ROOT_INO;
 	inode->i_uid = sbi->options.fs_uid;
 	inode->i_gid = sbi->options.fs_gid;
 	inode->i_version++;
@@ -1256,6 +1262,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat,
 	sb->s_magic = MSDOS_SUPER_MAGIC;
 	sb->s_op = &fat_sops;
 	sb->s_export_op = &fat_export_ops;
+	mutex_init(&sbi->nfs_build_inode_lock);
 	ratelimit_state_init(&sbi->ratelimit, DEFAULT_RATELIMIT_INTERVAL,
 			     DEFAULT_RATELIMIT_BURST);
 
diff --git a/fs/fat/nfs.c b/fs/fat/nfs.c
index 499c104..93e1493 100644
--- a/fs/fat/nfs.c
+++ b/fs/fat/nfs.c
@@ -14,6 +14,18 @@
 #include <linux/exportfs.h>
 #include "fat.h"
 
+struct fat_fid {
+	u32 i_gen;
+	u32 i_pos_low;
+	u16 i_pos_hi;
+	u16 parent_i_pos_hi;
+	u32 parent_i_pos_low;
+	u32 parent_i_gen;
+};
+
+#define FAT_FID_SIZE_WITHOUT_PARENT 3
+#define FAT_FID_SIZE_WITH_PARENT (sizeof(struct fat_fid)/sizeof(u32))
+
 /**
  * Look up a directory inode given its starting cluster.
  */
@@ -38,63 +50,252 @@ static struct inode *fat_dget(struct super_block *sb, int i_logstart)
 	return inode;
 }
 
-static struct inode *fat_nfs_get_inode(struct super_block *sb,
-				       u64 ino, u32 generation)
+static struct inode *fat_ilookup(struct super_block *sb, u64 ino, loff_t i_pos)
 {
-	struct inode *inode;
+	if (MSDOS_SB(sb)->options.nfs == FAT_NFS_NOSTALE_RO)
+		return fat_iget(sb, i_pos);
 
-	if ((ino < MSDOS_ROOT_INO) || (ino == MSDOS_FSINFO_INO))
-		return NULL;
+	else {
+		if ((ino < MSDOS_ROOT_INO) || (ino == MSDOS_FSINFO_INO))
+			return NULL;
+		return ilookup(sb, ino);
+	}
+}
+
+static struct inode *__fat_nfs_get_inode(struct super_block *sb,
+				       u64 ino, u32 generation, loff_t i_pos)
+{
+	struct inode *inode = fat_ilookup(sb, ino, i_pos);
 
-	inode = ilookup(sb, ino);
 	if (inode && generation && (inode->i_generation != generation)) {
 		iput(inode);
 		inode = NULL;
 	}
+	if (inode == NULL && MSDOS_SB(sb)->options.nfs == FAT_NFS_NOSTALE_RO) {
+		struct buffer_head *bh = NULL;
+		struct msdos_dir_entry *de ;
+		sector_t blocknr;
+		int offset;
+		fat_get_blknr_offset(MSDOS_SB(sb), i_pos, &blocknr, &offset);
+		bh = sb_bread(sb, blocknr);
+		if (!bh) {
+			fat_msg(sb, KERN_ERR,
+				"unable to read block(%llu) for building NFS inode",
+				(llu)blocknr);
+			return inode;
+		}
+		de = (struct msdos_dir_entry *)bh->b_data;
+		/* If a file is deleted on server and client is not updated
+		 * yet, we must not build the inode upon a lookup call.
+		 */
+		if (IS_FREE(de[offset].name))
+			inode = NULL;
+		else
+			inode = fat_build_inode(sb, &de[offset], i_pos);
+		brelse(bh);
+	}
 
 	return inode;
 }
 
+static struct inode *fat_nfs_get_inode(struct super_block *sb,
+				       u64 ino, u32 generation)
+{
+
+	return __fat_nfs_get_inode(sb, ino, generation, 0);
+}
+
+static int
+fat_encode_fh_nostale(struct inode *inode, __u32 *fh, int *lenp,
+		      struct inode *parent)
+{
+	int len = *lenp;
+	struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
+	struct fat_fid *fid = (struct fat_fid *) fh;
+	loff_t i_pos;
+	int type = FILEID_FAT_WITHOUT_PARENT;
+
+	if (parent) {
+		if (len < FAT_FID_SIZE_WITH_PARENT) {
+			*lenp = FAT_FID_SIZE_WITH_PARENT;
+			return FILEID_INVALID;
+		}
+	} else {
+		if (len < FAT_FID_SIZE_WITHOUT_PARENT) {
+			*lenp = FAT_FID_SIZE_WITHOUT_PARENT;
+			return FILEID_INVALID;
+		}
+	}
+
+	i_pos = fat_i_pos_read(sbi, inode);
+	*lenp = FAT_FID_SIZE_WITHOUT_PARENT;
+	fid->i_gen = inode->i_generation;
+	fid->i_pos_low = i_pos & 0xFFFFFFFF;
+	fid->i_pos_hi = (i_pos >> 32) & 0xFFFF;
+	if (parent) {
+		i_pos = fat_i_pos_read(sbi, parent);
+		fid->parent_i_pos_hi = (i_pos >> 32) & 0xFFFF;
+		fid->parent_i_pos_low = i_pos & 0xFFFFFFFF;
+		fid->parent_i_gen = parent->i_generation;
+		type = FILEID_FAT_WITH_PARENT;
+		*lenp = FAT_FID_SIZE_WITH_PARENT;
+	}
+
+	return type;
+}
+
 /**
  * Map a NFS file handle to a corresponding dentry.
  * The dentry may or may not be connected to the filesystem root.
  */
-struct dentry *fat_fh_to_dentry(struct super_block *sb, struct fid *fid,
+static struct dentry *fat_fh_to_dentry(struct super_block *sb, struct fid *fid,
 				int fh_len, int fh_type)
 {
 	return generic_fh_to_dentry(sb, fid, fh_len, fh_type,
 				    fat_nfs_get_inode);
 }
 
+static struct dentry *fat_fh_to_dentry_nostale(struct super_block *sb,
+					       struct fid *fh, int fh_len,
+					       int fh_type)
+{
+	struct inode *inode = NULL;
+	struct fat_fid *fid = (struct fat_fid *)fh;
+	loff_t i_pos;
+
+	switch (fh_type) {
+	case FILEID_FAT_WITHOUT_PARENT:
+		if (fh_len < FAT_FID_SIZE_WITHOUT_PARENT)
+			return NULL;
+		break;
+	case FILEID_FAT_WITH_PARENT:
+		if (fh_len < FAT_FID_SIZE_WITH_PARENT)
+			return NULL;
+		break;
+	default:
+		return NULL;
+	}
+	i_pos = fid->i_pos_hi;
+	i_pos = (i_pos << 32) | (fid->i_pos_low);
+	inode = __fat_nfs_get_inode(sb, 0, fid->i_gen, i_pos);
+
+	return d_obtain_alias(inode);
+}
+
 /*
  * Find the parent for a file specified by NFS handle.
  * This requires that the handle contain the i_ino of the parent.
  */
-struct dentry *fat_fh_to_parent(struct super_block *sb, struct fid *fid,
+static struct dentry *fat_fh_to_parent(struct super_block *sb, struct fid *fid,
 				int fh_len, int fh_type)
 {
 	return generic_fh_to_parent(sb, fid, fh_len, fh_type,
 				    fat_nfs_get_inode);
 }
 
+static struct dentry *fat_fh_to_parent_nostale(struct super_block *sb,
+					       struct fid *fh, int fh_len,
+					       int fh_type)
+{
+	struct inode *inode = NULL;
+	struct fat_fid *fid = (struct fat_fid *)fh;
+	loff_t i_pos;
+
+	if (fh_len < FAT_FID_SIZE_WITH_PARENT)
+		return NULL;
+
+	switch (fh_type) {
+	case FILEID_FAT_WITH_PARENT:
+		i_pos = fid->parent_i_pos_hi;
+		i_pos = (i_pos << 32) | (fid->parent_i_pos_low);
+		inode = __fat_nfs_get_inode(sb, 0, fid->parent_i_gen, i_pos);
+		break;
+	}
+
+	return d_obtain_alias(inode);
+}
+
+/*
+ * Rebuild the parent for a directory that is not connected
+ *  to the filesystem root
+ */
+static
+struct inode *fat_rebuild_parent(struct super_block *sb, int parent_logstart)
+{
+	int search_clus, clus_to_match;
+	struct msdos_dir_entry *de;
+	struct inode *parent = NULL;
+	struct inode *dummy_grand_parent = NULL;
+	struct fat_slot_info sinfo;
+	struct msdos_sb_info *sbi = MSDOS_SB(sb);
+	sector_t blknr = fat_clus_to_blknr(sbi, parent_logstart);
+	struct buffer_head *parent_bh = sb_bread(sb, blknr);
+	if (!parent_bh) {
+		fat_msg(sb, KERN_ERR,
+			"unable to read cluster of parent directory");
+		return NULL;
+	}
+
+	de = (struct msdos_dir_entry *) parent_bh->b_data;
+	clus_to_match = fat_get_start(sbi, &de[0]);
+	search_clus = fat_get_start(sbi, &de[1]);
+
+	dummy_grand_parent = fat_dget(sb, search_clus);
+	if (!dummy_grand_parent) {
+		dummy_grand_parent = new_inode(sb);
+		if (!dummy_grand_parent) {
+			brelse(parent_bh);
+			return parent;
+		}
+
+		dummy_grand_parent->i_ino = iunique(sb, MSDOS_ROOT_INO);
+		fat_fill_inode(dummy_grand_parent, &de[1]);
+		MSDOS_I(dummy_grand_parent)->i_pos = -1;
+	}
+
+	if (!fat_scan_logstart(dummy_grand_parent, clus_to_match, &sinfo))
+		parent = fat_build_inode(sb, sinfo.de, sinfo.i_pos);
+
+	brelse(parent_bh);
+	iput(dummy_grand_parent);
+
+	return parent;
+}
+
 /*
  * Find the parent for a directory that is not currently connected to
  * the filesystem root.
  *
  * On entry, the caller holds child_dir->d_inode->i_mutex.
  */
-struct dentry *fat_get_parent(struct dentry *child_dir)
+static struct dentry *fat_get_parent(struct dentry *child_dir)
 {
 	struct super_block *sb = child_dir->d_sb;
 	struct buffer_head *bh = NULL;
 	struct msdos_dir_entry *de;
 	struct inode *parent_inode = NULL;
+	struct msdos_sb_info *sbi = MSDOS_SB(sb);
 
 	if (!fat_get_dotdot_entry(child_dir->d_inode, &bh, &de)) {
-		int parent_logstart = fat_get_start(MSDOS_SB(sb), de);
+		int parent_logstart = fat_get_start(sbi, de);
 		parent_inode = fat_dget(sb, parent_logstart);
+		if (!parent_inode && sbi->options.nfs == FAT_NFS_NOSTALE_RO)
+			parent_inode = fat_rebuild_parent(sb, parent_logstart);
 	}
 	brelse(bh);
 
 	return d_obtain_alias(parent_inode);
 }
+
+const struct export_operations fat_export_ops = {
+	.fh_to_dentry   = fat_fh_to_dentry,
+	.fh_to_parent   = fat_fh_to_parent,
+	.get_parent     = fat_get_parent,
+};
+
+const struct export_operations fat_export_ops_nostale = {
+	.encode_fh      = fat_encode_fh_nostale,
+	.fh_to_dentry   = fat_fh_to_dentry_nostale,
+	.fh_to_parent   = fat_fh_to_parent_nostale,
+	.get_parent     = fat_get_parent,
+};
diff --git a/fs/fifo.c b/fs/fifo.c
deleted file mode 100644
index cf6f434..0000000
--- a/fs/fifo.c
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- *  linux/fs/fifo.c
- *
- *  written by Paul H. Hargrove
- *
- *  Fixes:
- *	10-06-1999, AV: fixed OOM handling in fifo_open(), moved
- *			initialization there, switched to external
- *			allocation of pipe_inode_info.
- */
-
-#include <linux/mm.h>
-#include <linux/fs.h>
-#include <linux/sched.h>
-#include <linux/pipe_fs_i.h>
-
-static int wait_for_partner(struct inode* inode, unsigned int *cnt)
-{
-	int cur = *cnt;	
-
-	while (cur == *cnt) {
-		pipe_wait(inode->i_pipe);
-		if (signal_pending(current))
-			break;
-	}
-	return cur == *cnt ? -ERESTARTSYS : 0;
-}
-
-static void wake_up_partner(struct inode* inode)
-{
-	wake_up_interruptible(&inode->i_pipe->wait);
-}
-
-static int fifo_open(struct inode *inode, struct file *filp)
-{
-	struct pipe_inode_info *pipe;
-	int ret;
-
-	mutex_lock(&inode->i_mutex);
-	pipe = inode->i_pipe;
-	if (!pipe) {
-		ret = -ENOMEM;
-		pipe = alloc_pipe_info(inode);
-		if (!pipe)
-			goto err_nocleanup;
-		inode->i_pipe = pipe;
-	}
-	filp->f_version = 0;
-
-	/* We can only do regular read/write on fifos */
-	filp->f_mode &= (FMODE_READ | FMODE_WRITE);
-
-	switch (filp->f_mode) {
-	case FMODE_READ:
-	/*
-	 *  O_RDONLY
-	 *  POSIX.1 says that O_NONBLOCK means return with the FIFO
-	 *  opened, even when there is no process writing the FIFO.
-	 */
-		filp->f_op = &read_pipefifo_fops;
-		pipe->r_counter++;
-		if (pipe->readers++ == 0)
-			wake_up_partner(inode);
-
-		if (!pipe->writers) {
-			if ((filp->f_flags & O_NONBLOCK)) {
-				/* suppress POLLHUP until we have
-				 * seen a writer */
-				filp->f_version = pipe->w_counter;
-			} else {
-				if (wait_for_partner(inode, &pipe->w_counter))
-					goto err_rd;
-			}
-		}
-		break;
-	
-	case FMODE_WRITE:
-	/*
-	 *  O_WRONLY
-	 *  POSIX.1 says that O_NONBLOCK means return -1 with
-	 *  errno=ENXIO when there is no process reading the FIFO.
-	 */
-		ret = -ENXIO;
-		if ((filp->f_flags & O_NONBLOCK) && !pipe->readers)
-			goto err;
-
-		filp->f_op = &write_pipefifo_fops;
-		pipe->w_counter++;
-		if (!pipe->writers++)
-			wake_up_partner(inode);
-
-		if (!pipe->readers) {
-			if (wait_for_partner(inode, &pipe->r_counter))
-				goto err_wr;
-		}
-		break;
-	
-	case FMODE_READ | FMODE_WRITE:
-	/*
-	 *  O_RDWR
-	 *  POSIX.1 leaves this case "undefined" when O_NONBLOCK is set.
-	 *  This implementation will NEVER block on a O_RDWR open, since
-	 *  the process can at least talk to itself.
-	 */
-		filp->f_op = &rdwr_pipefifo_fops;
-
-		pipe->readers++;
-		pipe->writers++;
-		pipe->r_counter++;
-		pipe->w_counter++;
-		if (pipe->readers == 1 || pipe->writers == 1)
-			wake_up_partner(inode);
-		break;
-
-	default:
-		ret = -EINVAL;
-		goto err;
-	}
-
-	/* Ok! */
-	mutex_unlock(&inode->i_mutex);
-	return 0;
-
-err_rd:
-	if (!--pipe->readers)
-		wake_up_interruptible(&pipe->wait);
-	ret = -ERESTARTSYS;
-	goto err;
-
-err_wr:
-	if (!--pipe->writers)
-		wake_up_interruptible(&pipe->wait);
-	ret = -ERESTARTSYS;
-	goto err;
-
-err:
-	if (!pipe->readers && !pipe->writers)
-		free_pipe_info(inode);
-
-err_nocleanup:
-	mutex_unlock(&inode->i_mutex);
-	return ret;
-}
-
-/*
- * Dummy default file-operations: the only thing this does
- * is contain the open that then fills in the correct operations
- * depending on the access mode of the file...
- */
-const struct file_operations def_fifo_fops = {
-	.open		= fifo_open,	/* will set read_ or write_pipefifo_fops */
-	.llseek		= noop_llseek,
-};
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index 21f46fb..8067d37 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -22,7 +22,6 @@
 #include <linux/mm.h>
 #include <linux/pagemap.h>
 #include <linux/kthread.h>
-#include <linux/freezer.h>
 #include <linux/writeback.h>
 #include <linux/blkdev.h>
 #include <linux/backing-dev.h>
@@ -88,20 +87,6 @@ static inline struct inode *wb_inode(struct list_head *head)
 #define CREATE_TRACE_POINTS
 #include <trace/events/writeback.h>
 
-/* Wakeup flusher thread or forker thread to fork it. Requires bdi->wb_lock. */
-static void bdi_wakeup_flusher(struct backing_dev_info *bdi)
-{
-	if (bdi->wb.task) {
-		wake_up_process(bdi->wb.task);
-	} else {
-		/*
-		 * The bdi thread isn't there, wake up the forker thread which
-		 * will create and run it.
-		 */
-		wake_up_process(default_backing_dev_info.wb.task);
-	}
-}
-
 static void bdi_queue_work(struct backing_dev_info *bdi,
 			   struct wb_writeback_work *work)
 {
@@ -109,10 +94,9 @@ static void bdi_queue_work(struct backing_dev_info *bdi,
 
 	spin_lock_bh(&bdi->wb_lock);
 	list_add_tail(&work->list, &bdi->work_list);
-	if (!bdi->wb.task)
-		trace_writeback_nothread(bdi, work);
-	bdi_wakeup_flusher(bdi);
 	spin_unlock_bh(&bdi->wb_lock);
+
+	mod_delayed_work(bdi_wq, &bdi->wb.dwork, 0);
 }
 
 static void
@@ -127,10 +111,8 @@ __bdi_start_writeback(struct backing_dev_info *bdi, long nr_pages,
 	 */
 	work = kzalloc(sizeof(*work), GFP_ATOMIC);
 	if (!work) {
-		if (bdi->wb.task) {
-			trace_writeback_nowork(bdi);
-			wake_up_process(bdi->wb.task);
-		}
+		trace_writeback_nowork(bdi);
+		mod_delayed_work(bdi_wq, &bdi->wb.dwork, 0);
 		return;
 	}
 
@@ -177,9 +159,7 @@ void bdi_start_background_writeback(struct backing_dev_info *bdi)
 	 * writeback as soon as there is no other work to do.
 	 */
 	trace_writeback_wake_background(bdi);
-	spin_lock_bh(&bdi->wb_lock);
-	bdi_wakeup_flusher(bdi);
-	spin_unlock_bh(&bdi->wb_lock);
+	mod_delayed_work(bdi_wq, &bdi->wb.dwork, 0);
 }
 
 /*
@@ -1020,66 +1000,48 @@ long wb_do_writeback(struct bdi_writeback *wb, int force_wait)
 
 /*
  * Handle writeback of dirty data for the device backed by this bdi. Also
- * wakes up periodically and does kupdated style flushing.
+ * reschedules periodically and does kupdated style flushing.
  */
-int bdi_writeback_thread(void *data)
+void bdi_writeback_workfn(struct work_struct *work)
 {
-	struct bdi_writeback *wb = data;
+	struct bdi_writeback *wb = container_of(to_delayed_work(work),
+						struct bdi_writeback, dwork);
 	struct backing_dev_info *bdi = wb->bdi;
 	long pages_written;
 
 	current->flags |= PF_SWAPWRITE;
-	set_freezable();
-	wb->last_active = jiffies;
-
-	/*
-	 * Our parent may run at a different priority, just set us to normal
-	 */
-	set_user_nice(current, 0);
-
-	trace_writeback_thread_start(bdi);
 
-	while (!kthread_freezable_should_stop(NULL)) {
+	if (likely(!current_is_workqueue_rescuer() ||
+		   list_empty(&bdi->bdi_list))) {
 		/*
-		 * Remove own delayed wake-up timer, since we are already awake
-		 * and we'll take care of the periodic write-back.
+		 * The normal path.  Keep writing back @bdi until its
+		 * work_list is empty.  Note that this path is also taken
+		 * if @bdi is shutting down even when we're running off the
+		 * rescuer as work_list needs to be drained.
 		 */
-		del_timer(&wb->wakeup_timer);
-
-		pages_written = wb_do_writeback(wb, 0);
-
+		do {
+			pages_written = wb_do_writeback(wb, 0);
+			trace_writeback_pages_written(pages_written);
+		} while (!list_empty(&bdi->work_list));
+	} else {
+		/*
+		 * bdi_wq can't get enough workers and we're running off
+		 * the emergency worker.  Don't hog it.  Hopefully, 1024 is
+		 * enough for efficient IO.
+		 */
+		pages_written = writeback_inodes_wb(&bdi->wb, 1024,
+						    WB_REASON_FORKER_THREAD);
 		trace_writeback_pages_written(pages_written);
-
-		if (pages_written)
-			wb->last_active = jiffies;
-
-		set_current_state(TASK_INTERRUPTIBLE);
-		if (!list_empty(&bdi->work_list) || kthread_should_stop()) {
-			__set_current_state(TASK_RUNNING);
-			continue;
-		}
-
-		if (wb_has_dirty_io(wb) && dirty_writeback_interval)
-			schedule_timeout(msecs_to_jiffies(dirty_writeback_interval * 10));
-		else {
-			/*
-			 * We have nothing to do, so can go sleep without any
-			 * timeout and save power. When a work is queued or
-			 * something is made dirty - we will be woken up.
-			 */
-			schedule();
-		}
 	}
 
-	/* Flush any work that raced with us exiting */
-	if (!list_empty(&bdi->work_list))
-		wb_do_writeback(wb, 1);
+	if (!list_empty(&bdi->work_list) ||
+	    (wb_has_dirty_io(wb) && dirty_writeback_interval))
+		queue_delayed_work(bdi_wq, &wb->dwork,
+			msecs_to_jiffies(dirty_writeback_interval * 10));
 
-	trace_writeback_thread_stop(bdi);
-	return 0;
+	current->flags &= ~PF_SWAPWRITE;
 }
 
-
 /*
  * Start writeback of `nr_pages' pages.  If `nr_pages' is zero, write back
  * the whole world.
diff --git a/fs/fuse/cuse.c b/fs/fuse/cuse.c
index 6f96a8d..06b5e08 100644
--- a/fs/fuse/cuse.c
+++ b/fs/fuse/cuse.c
@@ -38,6 +38,7 @@
 #include <linux/device.h>
 #include <linux/file.h>
 #include <linux/fs.h>
+#include <linux/aio.h>
 #include <linux/kdev_t.h>
 #include <linux/kthread.h>
 #include <linux/list.h>
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 11dfa0c..a45c190 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -19,6 +19,7 @@
 #include <linux/pipe_fs_i.h>
 #include <linux/swap.h>
 #include <linux/splice.h>
+#include <linux/aio.h>
 
 MODULE_ALIAS_MISCDEV(FUSE_MINOR);
 MODULE_ALIAS("devname:fuse");
@@ -1319,7 +1320,7 @@ static ssize_t fuse_dev_splice_read(struct file *in, loff_t *ppos,
 		page_nr++;
 		ret += buf->len;
 
-		if (pipe->inode)
+		if (pipe->files)
 			do_wakeup = 1;
 	}
 
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 34b80ba..82f7ee5 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -15,6 +15,7 @@
 #include <linux/module.h>
 #include <linux/compat.h>
 #include <linux/swap.h>
+#include <linux/aio.h>
 
 static const struct file_operations fuse_direct_io_file_operations;
 
@@ -971,7 +972,6 @@ static ssize_t fuse_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
 		return err;
 
 	count = ocount;
-	sb_start_write(inode->i_sb);
 	mutex_lock(&inode->i_mutex);
 
 	/* We can write back this queue in page reclaim */
@@ -1030,7 +1030,6 @@ static ssize_t fuse_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
 out:
 	current->backing_dev_info = NULL;
 	mutex_unlock(&inode->i_mutex);
-	sb_end_write(inode->i_sb);
 
 	return written ? written : err;
 }
diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c
index 24f414f..371bd14 100644
--- a/fs/gfs2/aops.c
+++ b/fs/gfs2/aops.c
@@ -20,6 +20,7 @@
 #include <linux/swap.h>
 #include <linux/gfs2_ondisk.h>
 #include <linux/backing-dev.h>
+#include <linux/aio.h>
 
 #include "gfs2.h"
 #include "incore.h"
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
index 5e83657..1dc9a13 100644
--- a/fs/gfs2/bmap.c
+++ b/fs/gfs2/bmap.c
@@ -787,7 +787,7 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh,
 		goto out_rlist;
 
 	if (gfs2_rs_active(ip->i_res)) /* needs to be done with the rgrp glock held */
-		gfs2_rs_deltree(ip, ip->i_res);
+		gfs2_rs_deltree(ip->i_res);
 
 	error = gfs2_trans_begin(sdp, rg_blocks + RES_DINODE +
 				 RES_INDIRECT + RES_STATFS + RES_QUOTA,
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c
index 019f45e..acd1676 100644
--- a/fs/gfs2/file.c
+++ b/fs/gfs2/file.c
@@ -25,6 +25,7 @@
 #include <asm/uaccess.h>
 #include <linux/dlm.h>
 #include <linux/dlm_plock.h>
+#include <linux/aio.h>
 
 #include "gfs2.h"
 #include "incore.h"
@@ -923,8 +924,11 @@ static int gfs2_lock(struct file *file, int cmd, struct file_lock *fl)
 		cmd = F_SETLK;
 		fl->fl_type = F_UNLCK;
 	}
-	if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
+	if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) {
+		if (fl->fl_type == F_UNLCK)
+			posix_lock_file_wait(file, fl);
 		return -EIO;
+	}
 	if (IS_GETLK(cmd))
 		return dlm_posix_get(ls->ls_dlm, ip->i_no_addr, file, fl);
 	else if (fl->fl_type == F_UNLCK)
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
index cf35155..6e30fd1 100644
--- a/fs/gfs2/glock.c
+++ b/fs/gfs2/glock.c
@@ -1279,19 +1279,6 @@ void gfs2_glock_dq_m(unsigned int num_gh, struct gfs2_holder *ghs)
 		gfs2_glock_dq(&ghs[num_gh]);
 }
 
-/**
- * gfs2_glock_dq_uninit_m - release multiple glocks
- * @num_gh: the number of structures
- * @ghs: an array of struct gfs2_holder structures
- *
- */
-
-void gfs2_glock_dq_uninit_m(unsigned int num_gh, struct gfs2_holder *ghs)
-{
-	while (num_gh--)
-		gfs2_glock_dq_uninit(&ghs[num_gh]);
-}
-
 void gfs2_glock_cb(struct gfs2_glock *gl, unsigned int state)
 {
 	unsigned long delay = 0;
diff --git a/fs/gfs2/glock.h b/fs/gfs2/glock.h
index fd580b7..69f66e3 100644
--- a/fs/gfs2/glock.h
+++ b/fs/gfs2/glock.h
@@ -201,7 +201,6 @@ extern int gfs2_glock_nq_num(struct gfs2_sbd *sdp, u64 number,
 			     struct gfs2_holder *gh);
 extern int gfs2_glock_nq_m(unsigned int num_gh, struct gfs2_holder *ghs);
 extern void gfs2_glock_dq_m(unsigned int num_gh, struct gfs2_holder *ghs);
-extern void gfs2_glock_dq_uninit_m(unsigned int num_gh, struct gfs2_holder *ghs);
 extern int gfs2_dump_glock(struct seq_file *seq, const struct gfs2_glock *gl);
 #define GLOCK_BUG_ON(gl,x) do { if (unlikely(x)) { gfs2_dump_glock(NULL, gl); BUG(); } } while(0)
 extern __printf(2, 3)
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index 156e42e..5c29216 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -588,6 +588,7 @@ struct lm_lockstruct {
 	struct dlm_lksb ls_control_lksb; /* control_lock */
 	char ls_control_lvb[GDLM_LVB_SIZE]; /* control_lock lvb */
 	struct completion ls_sync_wait; /* {control,mounted}_{lock,unlock} */
+	char *ls_lvb_bits;
 
 	spinlock_t ls_recover_spin; /* protects following fields */
 	unsigned long ls_recover_flags; /* DFL_ */
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index cc00bd1..8833a4f 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -392,11 +392,15 @@ static int alloc_dinode(struct gfs2_inode *ip, u32 flags)
 	int error;
 	int dblocks = 1;
 
-	error = gfs2_inplace_reserve(ip, RES_DINODE, flags);
+	error = gfs2_quota_lock_check(ip);
 	if (error)
 		goto out;
 
-	error = gfs2_trans_begin(sdp, RES_RG_BIT + RES_STATFS, 0);
+	error = gfs2_inplace_reserve(ip, RES_DINODE, flags);
+	if (error)
+		goto out_quota;
+
+	error = gfs2_trans_begin(sdp, RES_RG_BIT + RES_STATFS + RES_QUOTA, 0);
 	if (error)
 		goto out_ipreserv;
 
@@ -409,6 +413,8 @@ static int alloc_dinode(struct gfs2_inode *ip, u32 flags)
 
 out_ipreserv:
 	gfs2_inplace_release(ip);
+out_quota:
+	gfs2_quota_unlock(ip);
 out:
 	return error;
 }
@@ -440,59 +446,27 @@ static void gfs2_init_dir(struct buffer_head *dibh,
  */
 
 static void init_dinode(struct gfs2_inode *dip, struct gfs2_inode *ip,
-			const char *symname, struct buffer_head **bhp)
+			const char *symname)
 {
-	struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
 	struct gfs2_dinode *di;
 	struct buffer_head *dibh;
-	struct timespec tv = CURRENT_TIME;
 
 	dibh = gfs2_meta_new(ip->i_gl, ip->i_no_addr);
 	gfs2_trans_add_meta(ip->i_gl, dibh);
-	gfs2_metatype_set(dibh, GFS2_METATYPE_DI, GFS2_FORMAT_DI);
-	gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode));
 	di = (struct gfs2_dinode *)dibh->b_data;
+	gfs2_dinode_out(ip, di);
 
-	di->di_num.no_formal_ino = cpu_to_be64(ip->i_no_formal_ino);
-	di->di_num.no_addr = cpu_to_be64(ip->i_no_addr);
-	di->di_mode = cpu_to_be32(ip->i_inode.i_mode);
-	di->di_uid = cpu_to_be32(i_uid_read(&ip->i_inode));
-	di->di_gid = cpu_to_be32(i_gid_read(&ip->i_inode));
-	di->di_nlink = 0;
-	di->di_size = cpu_to_be64(ip->i_inode.i_size);
-	di->di_blocks = cpu_to_be64(1);
-	di->di_atime = di->di_mtime = di->di_ctime = cpu_to_be64(tv.tv_sec);
 	di->di_major = cpu_to_be32(MAJOR(ip->i_inode.i_rdev));
 	di->di_minor = cpu_to_be32(MINOR(ip->i_inode.i_rdev));
-	di->di_goal_meta = di->di_goal_data = cpu_to_be64(ip->i_no_addr);
-	di->di_generation = cpu_to_be64(ip->i_generation);
-	di->di_flags = 0;
 	di->__pad1 = 0;
-	di->di_payload_format = cpu_to_be32(S_ISDIR(ip->i_inode.i_mode) ? GFS2_FORMAT_DE : 0);
-	di->di_height = 0;
 	di->__pad2 = 0;
 	di->__pad3 = 0;
-	di->di_depth = 0;
-	di->di_entries = 0;
 	memset(&di->__pad4, 0, sizeof(di->__pad4));
-	di->di_eattr = 0;
-	di->di_atime_nsec = cpu_to_be32(tv.tv_nsec);
-	di->di_mtime_nsec = cpu_to_be32(tv.tv_nsec);
-	di->di_ctime_nsec = cpu_to_be32(tv.tv_nsec);
 	memset(&di->di_reserved, 0, sizeof(di->di_reserved));
+	gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode));
 
 	switch(ip->i_inode.i_mode & S_IFMT) {
-	case S_IFREG:
-		if ((dip->i_diskflags & GFS2_DIF_INHERIT_JDATA) ||
-		    gfs2_tune_get(sdp, gt_new_files_jdata))
-			di->di_flags |= cpu_to_be32(GFS2_DIF_JDATA);
-		break;
 	case S_IFDIR:
-		di->di_flags |= cpu_to_be32(dip->i_diskflags &
-					    GFS2_DIF_INHERIT_JDATA);
-		di->di_flags |= cpu_to_be32(GFS2_DIF_JDATA);
-		di->di_size = cpu_to_be64(sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode));
-		di->di_entries = cpu_to_be32(2);
 		gfs2_init_dir(dibh, dip);
 		break;
 	case S_IFLNK:
@@ -501,63 +475,17 @@ static void init_dinode(struct gfs2_inode *dip, struct gfs2_inode *ip,
 	}
 
 	set_buffer_uptodate(dibh);
-
-	*bhp = dibh;
-}
-
-static int make_dinode(struct gfs2_inode *dip, struct gfs2_inode *ip,
-		       const char *symname, struct buffer_head **bhp)
-{
-	struct inode *inode = &ip->i_inode;
-	struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
-	int error;
-
-	error = gfs2_rindex_update(sdp);
-	if (error)
-		return error;
-
-	error = gfs2_quota_lock(dip, inode->i_uid, inode->i_gid);
-	if (error)
-		return error;
-
-	error = gfs2_quota_check(dip, inode->i_uid, inode->i_gid);
-	if (error)
-		goto out_quota;
-
-	error = gfs2_trans_begin(sdp, RES_DINODE + RES_QUOTA, 0);
-	if (error)
-		goto out_quota;
-
-	init_dinode(dip, ip, symname, bhp);
-	gfs2_quota_change(dip, +1, inode->i_uid, inode->i_gid);
-	gfs2_trans_end(sdp);
-
-out_quota:
-	gfs2_quota_unlock(dip);
-	return error;
+	brelse(dibh);
 }
 
 static int link_dinode(struct gfs2_inode *dip, const struct qstr *name,
-		       struct gfs2_inode *ip)
+		       struct gfs2_inode *ip, int arq)
 {
 	struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
-	int alloc_required;
-	struct buffer_head *dibh;
 	int error;
 
-	error = gfs2_rindex_update(sdp);
-	if (error)
-		return error;
-
-	error = gfs2_quota_lock(dip, NO_UID_QUOTA_CHANGE, NO_GID_QUOTA_CHANGE);
-	if (error)
-		goto fail;
-
-	error = alloc_required = gfs2_diradd_alloc_required(&dip->i_inode, name);
-	if (alloc_required < 0)
-		goto fail_quota_locks;
-	if (alloc_required) {
-		error = gfs2_quota_check(dip, dip->i_inode.i_uid, dip->i_inode.i_gid);
+	if (arq) {
+		error = gfs2_quota_lock_check(dip);
 		if (error)
 			goto fail_quota_locks;
 
@@ -581,26 +509,12 @@ static int link_dinode(struct gfs2_inode *dip, const struct qstr *name,
 	if (error)
 		goto fail_end_trans;
 
-	error = gfs2_meta_inode_buffer(ip, &dibh);
-	if (error)
-		goto fail_end_trans;
-	set_nlink(&ip->i_inode, S_ISDIR(ip->i_inode.i_mode) ? 2 : 1);
-	gfs2_trans_add_meta(ip->i_gl, dibh);
-	gfs2_dinode_out(ip, dibh->b_data);
-	brelse(dibh);
-	return 0;
-
 fail_end_trans:
 	gfs2_trans_end(sdp);
-
 fail_ipreserv:
-	if (alloc_required)
-		gfs2_inplace_release(dip);
-
+	gfs2_inplace_release(dip);
 fail_quota_locks:
 	gfs2_quota_unlock(dip);
-
-fail:
 	return error;
 }
 
@@ -650,8 +564,8 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
 	struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
 	struct gfs2_glock *io_gl;
 	int error;
-	struct buffer_head *bh = NULL;
 	u32 aflags = 0;
+	int arq;
 
 	if (!name->len || name->len > GFS2_FNAMESIZE)
 		return -ENAMETOOLONG;
@@ -660,6 +574,10 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
 	if (error)
 		return error;
 
+	error = gfs2_rindex_update(sdp);
+	if (error)
+		return error;
+
 	error = gfs2_glock_nq_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs);
 	if (error)
 		goto fail;
@@ -674,22 +592,48 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
 	if (error)
 		goto fail_gunlock;
 
+	arq = error = gfs2_diradd_alloc_required(dir, name);
+	if (error < 0)
+		goto fail_gunlock;
+
 	inode = new_inode(sdp->sd_vfs);
-	if (!inode) {
-		gfs2_glock_dq_uninit(ghs);
-		return -ENOMEM;
-	}
+	error = -ENOMEM;
+	if (!inode)
+		goto fail_gunlock;
+
 	ip = GFS2_I(inode);
 	error = gfs2_rs_alloc(ip);
 	if (error)
 		goto fail_free_inode;
 
-	set_bit(GIF_INVALID, &ip->i_flags);
 	inode->i_mode = mode;
+	set_nlink(inode, S_ISDIR(mode) ? 2 : 1);
 	inode->i_rdev = dev;
 	inode->i_size = size;
+	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+	gfs2_set_inode_blocks(inode, 1);
 	munge_mode_uid_gid(dip, inode);
 	ip->i_goal = dip->i_goal;
+	ip->i_diskflags = 0;
+	ip->i_eattr = 0;
+	ip->i_height = 0;
+	ip->i_depth = 0;
+	ip->i_entries = 0;
+
+	switch(mode & S_IFMT) {
+	case S_IFREG:
+		if ((dip->i_diskflags & GFS2_DIF_INHERIT_JDATA) ||
+		    gfs2_tune_get(sdp, gt_new_files_jdata))
+			ip->i_diskflags |= GFS2_DIF_JDATA;
+		gfs2_set_aops(inode);
+		break;
+	case S_IFDIR:
+		ip->i_diskflags |= (dip->i_diskflags & GFS2_DIF_INHERIT_JDATA);
+		ip->i_diskflags |= GFS2_DIF_JDATA;
+		ip->i_entries = 2;
+		break;
+	}
+	gfs2_set_inode_flags(inode);
 
 	if ((GFS2_I(sdp->sd_root_dir->d_inode) == dip) ||
 	    (dip->i_diskflags & GFS2_DIF_TOPDIR))
@@ -708,10 +652,13 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
 	if (error)
 		goto fail_free_inode;
 
-	error = make_dinode(dip, ip, symname, &bh);
+	error = gfs2_trans_begin(sdp, RES_DINODE, 0);
 	if (error)
 		goto fail_gunlock2;
 
+	init_dinode(dip, ip, symname);
+	gfs2_trans_end(sdp);
+
 	error = gfs2_glock_get(sdp, ip->i_no_addr, &gfs2_iopen_glops, CREATE, &io_gl);
 	if (error)
 		goto fail_gunlock2;
@@ -725,10 +672,6 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
 	gfs2_set_iop(inode);
 	insert_inode_hash(inode);
 
-	error = gfs2_inode_refresh(ip);
-	if (error)
-		goto fail_gunlock3;
-
 	error = gfs2_acl_create(dip, inode);
 	if (error)
 		goto fail_gunlock3;
@@ -737,18 +680,13 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
 	if (error)
 		goto fail_gunlock3;
 
-	error = link_dinode(dip, name, ip);
+	error = link_dinode(dip, name, ip, arq);
 	if (error)
 		goto fail_gunlock3;
 
-	if (bh)
-		brelse(bh);
-
-	gfs2_trans_end(sdp);
-	gfs2_inplace_release(dip);
-	gfs2_quota_unlock(dip);
 	mark_inode_dirty(inode);
-	gfs2_glock_dq_uninit_m(2, ghs);
+	gfs2_glock_dq_uninit(ghs);
+	gfs2_glock_dq_uninit(ghs + 1);
 	d_instantiate(dentry, inode);
 	return 0;
 
@@ -769,12 +707,12 @@ fail_free_inode:
 fail_gunlock:
 	gfs2_glock_dq_uninit(ghs);
 	if (inode && !IS_ERR(inode)) {
+		clear_nlink(inode);
+		mark_inode_dirty(inode);
 		set_bit(GIF_ALLOC_FAILED, &GFS2_I(inode)->i_flags);
 		iput(inode);
 	}
 fail:
-	if (bh)
-		brelse(bh);
 	return error;
 }
 
@@ -1151,7 +1089,9 @@ static int gfs2_symlink(struct inode *dir, struct dentry *dentry,
 
 static int gfs2_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
 {
-	return gfs2_create_inode(dir, dentry, S_IFDIR | mode, 0, NULL, 0, 0);
+	struct gfs2_sbd *sdp = GFS2_SB(dir);
+	unsigned dsize = sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode);
+	return gfs2_create_inode(dir, dentry, S_IFDIR | mode, 0, NULL, dsize, 0);
 }
 
 /**
diff --git a/fs/gfs2/lock_dlm.c b/fs/gfs2/lock_dlm.c
index 9802de0..c8423d6 100644
--- a/fs/gfs2/lock_dlm.c
+++ b/fs/gfs2/lock_dlm.c
@@ -483,12 +483,8 @@ static void control_lvb_write(struct lm_lockstruct *ls, uint32_t lvb_gen,
 
 static int all_jid_bits_clear(char *lvb)
 {
-	int i;
-	for (i = JID_BITMAP_OFFSET; i < GDLM_LVB_SIZE; i++) {
-		if (lvb[i])
-			return 0;
-	}
-	return 1;
+	return !memchr_inv(lvb + JID_BITMAP_OFFSET, 0,
+			GDLM_LVB_SIZE - JID_BITMAP_OFFSET);
 }
 
 static void sync_wait_cb(void *arg)
@@ -580,7 +576,6 @@ static void gfs2_control_func(struct work_struct *work)
 {
 	struct gfs2_sbd *sdp = container_of(work, struct gfs2_sbd, sd_control_work.work);
 	struct lm_lockstruct *ls = &sdp->sd_lockstruct;
-	char lvb_bits[GDLM_LVB_SIZE];
 	uint32_t block_gen, start_gen, lvb_gen, flags;
 	int recover_set = 0;
 	int write_lvb = 0;
@@ -634,7 +629,7 @@ static void gfs2_control_func(struct work_struct *work)
 		return;
 	}
 
-	control_lvb_read(ls, &lvb_gen, lvb_bits);
+	control_lvb_read(ls, &lvb_gen, ls->ls_lvb_bits);
 
 	spin_lock(&ls->ls_recover_spin);
 	if (block_gen != ls->ls_recover_block ||
@@ -664,10 +659,10 @@ static void gfs2_control_func(struct work_struct *work)
 
 			ls->ls_recover_result[i] = 0;
 
-			if (!test_bit_le(i, lvb_bits + JID_BITMAP_OFFSET))
+			if (!test_bit_le(i, ls->ls_lvb_bits + JID_BITMAP_OFFSET))
 				continue;
 
-			__clear_bit_le(i, lvb_bits + JID_BITMAP_OFFSET);
+			__clear_bit_le(i, ls->ls_lvb_bits + JID_BITMAP_OFFSET);
 			write_lvb = 1;
 		}
 	}
@@ -691,7 +686,7 @@ static void gfs2_control_func(struct work_struct *work)
 				continue;
 			if (ls->ls_recover_submit[i] < start_gen) {
 				ls->ls_recover_submit[i] = 0;
-				__set_bit_le(i, lvb_bits + JID_BITMAP_OFFSET);
+				__set_bit_le(i, ls->ls_lvb_bits + JID_BITMAP_OFFSET);
 			}
 		}
 		/* even if there are no bits to set, we need to write the
@@ -705,7 +700,7 @@ static void gfs2_control_func(struct work_struct *work)
 	spin_unlock(&ls->ls_recover_spin);
 
 	if (write_lvb) {
-		control_lvb_write(ls, start_gen, lvb_bits);
+		control_lvb_write(ls, start_gen, ls->ls_lvb_bits);
 		flags = DLM_LKF_CONVERT | DLM_LKF_VALBLK;
 	} else {
 		flags = DLM_LKF_CONVERT;
@@ -725,7 +720,7 @@ static void gfs2_control_func(struct work_struct *work)
 	 */
 
 	for (i = 0; i < recover_size; i++) {
-		if (test_bit_le(i, lvb_bits + JID_BITMAP_OFFSET)) {
+		if (test_bit_le(i, ls->ls_lvb_bits + JID_BITMAP_OFFSET)) {
 			fs_info(sdp, "recover generation %u jid %d\n",
 				start_gen, i);
 			gfs2_recover_set(sdp, i);
@@ -758,7 +753,6 @@ static void gfs2_control_func(struct work_struct *work)
 static int control_mount(struct gfs2_sbd *sdp)
 {
 	struct lm_lockstruct *ls = &sdp->sd_lockstruct;
-	char lvb_bits[GDLM_LVB_SIZE];
 	uint32_t start_gen, block_gen, mount_gen, lvb_gen;
 	int mounted_mode;
 	int retries = 0;
@@ -857,7 +851,7 @@ locks_done:
 	 * lvb_gen will be non-zero.
 	 */
 
-	control_lvb_read(ls, &lvb_gen, lvb_bits);
+	control_lvb_read(ls, &lvb_gen, ls->ls_lvb_bits);
 
 	if (lvb_gen == 0xFFFFFFFF) {
 		/* special value to force mount attempts to fail */
@@ -887,7 +881,7 @@ locks_done:
 	 * and all lvb bits to be clear (no pending journal recoveries.)
 	 */
 
-	if (!all_jid_bits_clear(lvb_bits)) {
+	if (!all_jid_bits_clear(ls->ls_lvb_bits)) {
 		/* journals need recovery, wait until all are clear */
 		fs_info(sdp, "control_mount wait for journal recovery\n");
 		goto restart;
@@ -949,7 +943,6 @@ static int dlm_recovery_wait(void *word)
 static int control_first_done(struct gfs2_sbd *sdp)
 {
 	struct lm_lockstruct *ls = &sdp->sd_lockstruct;
-	char lvb_bits[GDLM_LVB_SIZE];
 	uint32_t start_gen, block_gen;
 	int error;
 
@@ -991,8 +984,8 @@ restart:
 	memset(ls->ls_recover_result, 0, ls->ls_recover_size*sizeof(uint32_t));
 	spin_unlock(&ls->ls_recover_spin);
 
-	memset(lvb_bits, 0, sizeof(lvb_bits));
-	control_lvb_write(ls, start_gen, lvb_bits);
+	memset(ls->ls_lvb_bits, 0, GDLM_LVB_SIZE);
+	control_lvb_write(ls, start_gen, ls->ls_lvb_bits);
 
 	error = mounted_lock(sdp, DLM_LOCK_PR, DLM_LKF_CONVERT);
 	if (error)
@@ -1022,6 +1015,12 @@ static int set_recover_size(struct gfs2_sbd *sdp, struct dlm_slot *slots,
 	uint32_t old_size, new_size;
 	int i, max_jid;
 
+	if (!ls->ls_lvb_bits) {
+		ls->ls_lvb_bits = kzalloc(GDLM_LVB_SIZE, GFP_NOFS);
+		if (!ls->ls_lvb_bits)
+			return -ENOMEM;
+	}
+
 	max_jid = 0;
 	for (i = 0; i < num_slots; i++) {
 		if (max_jid < slots[i].slot - 1)
@@ -1057,6 +1056,7 @@ static int set_recover_size(struct gfs2_sbd *sdp, struct dlm_slot *slots,
 
 static void free_recover_size(struct lm_lockstruct *ls)
 {
+	kfree(ls->ls_lvb_bits);
 	kfree(ls->ls_recover_submit);
 	kfree(ls->ls_recover_result);
 	ls->ls_recover_submit = NULL;
@@ -1205,6 +1205,7 @@ static int gdlm_mount(struct gfs2_sbd *sdp, const char *table)
 	ls->ls_recover_size = 0;
 	ls->ls_recover_submit = NULL;
 	ls->ls_recover_result = NULL;
+	ls->ls_lvb_bits = NULL;
 
 	error = set_recover_size(sdp, NULL, 0);
 	if (error)
diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c
index a505597..562adf3 100644
--- a/fs/gfs2/lops.c
+++ b/fs/gfs2/lops.c
@@ -200,7 +200,8 @@ static void gfs2_end_log_write_bh(struct gfs2_sbd *sdp, struct bio_vec *bvec,
  *
  */
 
-static void gfs2_end_log_write(struct bio *bio, int error)
+static void gfs2_end_log_write(struct bio *bio, int error,
+			       struct batch_complete *batch)
 {
 	struct gfs2_sbd *sdp = bio->bi_private;
 	struct bio_vec *bvec;
@@ -300,7 +301,7 @@ static struct bio *gfs2_log_get_bio(struct gfs2_sbd *sdp, u64 blkno)
 	u64 nblk;
 
 	if (bio) {
-		nblk = bio->bi_sector + bio_sectors(bio);
+		nblk = bio_end_sector(bio);
 		nblk >>= sdp->sd_fsb2bb_shift;
 		if (blkno == nblk)
 			return bio;
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c
index 60ede2a..86eb657 100644
--- a/fs/gfs2/ops_fstype.c
+++ b/fs/gfs2/ops_fstype.c
@@ -155,7 +155,8 @@ static int gfs2_check_sb(struct gfs2_sbd *sdp, int silent)
 	return -EINVAL;
 }
 
-static void end_bio_io_page(struct bio *bio, int error)
+static void end_bio_io_page(struct bio *bio, int error,
+			    struct batch_complete *batch)
 {
 	struct page *page = bio->bi_private;
 
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index d1f51fd..0c5a575 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -576,7 +576,7 @@ int gfs2_rs_alloc(struct gfs2_inode *ip)
 	RB_CLEAR_NODE(&ip->i_res->rs_node);
 out:
 	up_write(&ip->i_rw_mutex);
-	return 0;
+	return error;
 }
 
 static void dump_rs(struct seq_file *seq, const struct gfs2_blkreserv *rs)
@@ -592,7 +592,7 @@ static void dump_rs(struct seq_file *seq, const struct gfs2_blkreserv *rs)
  * @rs: The reservation to remove
  *
  */
-static void __rs_deltree(struct gfs2_inode *ip, struct gfs2_blkreserv *rs)
+static void __rs_deltree(struct gfs2_blkreserv *rs)
 {
 	struct gfs2_rgrpd *rgd;
 
@@ -605,7 +605,7 @@ static void __rs_deltree(struct gfs2_inode *ip, struct gfs2_blkreserv *rs)
 	RB_CLEAR_NODE(&rs->rs_node);
 
 	if (rs->rs_free) {
-		/* return reserved blocks to the rgrp and the ip */
+		/* return reserved blocks to the rgrp */
 		BUG_ON(rs->rs_rbm.rgd->rd_reserved < rs->rs_free);
 		rs->rs_rbm.rgd->rd_reserved -= rs->rs_free;
 		rs->rs_free = 0;
@@ -619,14 +619,14 @@ static void __rs_deltree(struct gfs2_inode *ip, struct gfs2_blkreserv *rs)
  * @rs: The reservation to remove
  *
  */
-void gfs2_rs_deltree(struct gfs2_inode *ip, struct gfs2_blkreserv *rs)
+void gfs2_rs_deltree(struct gfs2_blkreserv *rs)
 {
 	struct gfs2_rgrpd *rgd;
 
 	rgd = rs->rs_rbm.rgd;
 	if (rgd) {
 		spin_lock(&rgd->rd_rsspin);
-		__rs_deltree(ip, rs);
+		__rs_deltree(rs);
 		spin_unlock(&rgd->rd_rsspin);
 	}
 }
@@ -640,7 +640,7 @@ void gfs2_rs_delete(struct gfs2_inode *ip)
 {
 	down_write(&ip->i_rw_mutex);
 	if (ip->i_res) {
-		gfs2_rs_deltree(ip, ip->i_res);
+		gfs2_rs_deltree(ip->i_res);
 		BUG_ON(ip->i_res->rs_free);
 		kmem_cache_free(gfs2_rsrv_cachep, ip->i_res);
 		ip->i_res = NULL;
@@ -664,7 +664,7 @@ static void return_all_reservations(struct gfs2_rgrpd *rgd)
 	spin_lock(&rgd->rd_rsspin);
 	while ((n = rb_first(&rgd->rd_rstree))) {
 		rs = rb_entry(n, struct gfs2_blkreserv, rs_node);
-		__rs_deltree(NULL, rs);
+		__rs_deltree(rs);
 	}
 	spin_unlock(&rgd->rd_rsspin);
 }
@@ -1181,12 +1181,9 @@ int gfs2_rgrp_send_discards(struct gfs2_sbd *sdp, u64 offset,
 			     const struct gfs2_bitmap *bi, unsigned minlen, u64 *ptrimmed)
 {
 	struct super_block *sb = sdp->sd_vfs;
-	struct block_device *bdev = sb->s_bdev;
-	const unsigned int sects_per_blk = sdp->sd_sb.sb_bsize /
-					   bdev_logical_block_size(sb->s_bdev);
 	u64 blk;
 	sector_t start = 0;
-	sector_t nr_sects = 0;
+	sector_t nr_blks = 0;
 	int rv;
 	unsigned int x;
 	u32 trimmed = 0;
@@ -1206,35 +1203,34 @@ int gfs2_rgrp_send_discards(struct gfs2_sbd *sdp, u64 offset,
 		if (diff == 0)
 			continue;
 		blk = offset + ((bi->bi_start + x) * GFS2_NBBY);
-		blk *= sects_per_blk; /* convert to sectors */
 		while(diff) {
 			if (diff & 1) {
-				if (nr_sects == 0)
+				if (nr_blks == 0)
 					goto start_new_extent;
-				if ((start + nr_sects) != blk) {
-					if (nr_sects >= minlen) {
-						rv = blkdev_issue_discard(bdev,
-							start, nr_sects,
+				if ((start + nr_blks) != blk) {
+					if (nr_blks >= minlen) {
+						rv = sb_issue_discard(sb,
+							start, nr_blks,
 							GFP_NOFS, 0);
 						if (rv)
 							goto fail;
-						trimmed += nr_sects;
+						trimmed += nr_blks;
 					}
-					nr_sects = 0;
+					nr_blks = 0;
 start_new_extent:
 					start = blk;
 				}
-				nr_sects += sects_per_blk;
+				nr_blks++;
 			}
 			diff >>= 2;
-			blk += sects_per_blk;
+			blk++;
 		}
 	}
-	if (nr_sects >= minlen) {
-		rv = blkdev_issue_discard(bdev, start, nr_sects, GFP_NOFS, 0);
+	if (nr_blks >= minlen) {
+		rv = sb_issue_discard(sb, start, nr_blks, GFP_NOFS, 0);
 		if (rv)
 			goto fail;
-		trimmed += nr_sects;
+		trimmed += nr_blks;
 	}
 	if (ptrimmed)
 		*ptrimmed = trimmed;
@@ -1878,7 +1874,7 @@ int gfs2_inplace_reserve(struct gfs2_inode *ip, u32 requested, u32 aflags)
 
 		/* Drop reservation, if we couldn't use reserved rgrp */
 		if (gfs2_rs_active(rs))
-			gfs2_rs_deltree(ip, rs);
+			gfs2_rs_deltree(rs);
 check_rgrp:
 		/* Check for unlinked inodes which can be reclaimed */
 		if (rs->rs_rbm.rgd->rd_flags & GFS2_RDF_CHECK)
@@ -2091,7 +2087,7 @@ static void gfs2_adjust_reservation(struct gfs2_inode *ip,
 			if (rs->rs_free && !ret)
 				goto out;
 		}
-		__rs_deltree(ip, rs);
+		__rs_deltree(rs);
 	}
 out:
 	spin_unlock(&rgd->rd_rsspin);
@@ -2184,13 +2180,7 @@ int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *nblocks,
 	if (dinode)
 		gfs2_trans_add_unrevoke(sdp, block, 1);
 
-	/*
-	 * This needs reviewing to see why we cannot do the quota change
-	 * at this point in the dinode case.
-	 */
-	if (ndata)
-		gfs2_quota_change(ip, ndata, ip->i_inode.i_uid,
-				  ip->i_inode.i_gid);
+	gfs2_quota_change(ip, *nblocks, ip->i_inode.i_uid, ip->i_inode.i_gid);
 
 	rbm.rgd->rd_free_clone -= *nblocks;
 	trace_gfs2_block_alloc(ip, rbm.rgd, block, *nblocks,
diff --git a/fs/gfs2/rgrp.h b/fs/gfs2/rgrp.h
index 8421858..5b3f4a8 100644
--- a/fs/gfs2/rgrp.h
+++ b/fs/gfs2/rgrp.h
@@ -47,7 +47,7 @@ extern int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *n,
 			     bool dinode, u64 *generation);
 
 extern int gfs2_rs_alloc(struct gfs2_inode *ip);
-extern void gfs2_rs_deltree(struct gfs2_inode *ip, struct gfs2_blkreserv *rs);
+extern void gfs2_rs_deltree(struct gfs2_blkreserv *rs);
 extern void gfs2_rs_delete(struct gfs2_inode *ip);
 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);
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c
index cab77b8..917c8e1 100644
--- a/fs/gfs2/super.c
+++ b/fs/gfs2/super.c
@@ -1512,7 +1512,7 @@ out_truncate:
 out_unlock:
 	/* Error path for case 1 */
 	if (gfs2_rs_active(ip->i_res))
-		gfs2_rs_deltree(ip, ip->i_res);
+		gfs2_rs_deltree(ip->i_res);
 
 	if (test_bit(HIF_HOLDER, &ip->i_iopen_gh.gh_iflags))
 		gfs2_glock_dq(&ip->i_iopen_gh);
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
index 3031dfd..a9d60d4 100644
--- a/fs/hfs/inode.c
+++ b/fs/hfs/inode.c
@@ -14,6 +14,7 @@
 #include <linux/pagemap.h>
 #include <linux/mpage.h>
 #include <linux/sched.h>
+#include <linux/aio.h>
 
 #include "hfs_fs.h"
 #include "btree.h"
diff --git a/fs/hfsplus/bfind.c b/fs/hfsplus/bfind.c
index d73c98d..bbfdc17 100644
--- a/fs/hfsplus/bfind.c
+++ b/fs/hfsplus/bfind.c
@@ -56,7 +56,8 @@ int hfs_find_1st_rec_by_cnid(struct hfs_bnode *bnode,
 				int *end,
 				int *cur_rec)
 {
-	__be32 cur_cnid, search_cnid;
+	__be32 cur_cnid;
+	__be32 search_cnid;
 
 	if (bnode->tree->cnid == HFSPLUS_EXT_CNID) {
 		cur_cnid = fd->key->ext.cnid;
@@ -67,8 +68,11 @@ int hfs_find_1st_rec_by_cnid(struct hfs_bnode *bnode,
 	} else if (bnode->tree->cnid == HFSPLUS_ATTR_CNID) {
 		cur_cnid = fd->key->attr.cnid;
 		search_cnid = fd->search_key->attr.cnid;
-	} else
+	} else {
+		cur_cnid = 0;	/* used-uninitialized warning */
+		search_cnid = 0;
 		BUG();
+	}
 
 	if (cur_cnid == search_cnid) {
 		(*end) = (*cur_rec);
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
index 160ccc9..cdd181d 100644
--- a/fs/hfsplus/inode.c
+++ b/fs/hfsplus/inode.c
@@ -14,6 +14,7 @@
 #include <linux/pagemap.h>
 #include <linux/mpage.h>
 #include <linux/sched.h>
+#include <linux/aio.h>
 
 #include "hfsplus_fs.h"
 #include "hfsplus_raw.h"
diff --git a/fs/hfsplus/wrapper.c b/fs/hfsplus/wrapper.c
index 90effcc..2e7ffba 100644
--- a/fs/hfsplus/wrapper.c
+++ b/fs/hfsplus/wrapper.c
@@ -24,7 +24,8 @@ struct hfsplus_wd {
 	u16 embed_count;
 };
 
-static void hfsplus_end_io_sync(struct bio *bio, int err)
+static void hfsplus_end_io_sync(struct bio *bio, int err,
+				struct batch_complete *batch)
 {
 	if (err)
 		clear_bit(BIO_UPTODATE, &bio->bi_flags);
diff --git a/fs/hpfs/file.c b/fs/hpfs/file.c
index 9f9dbec..3027f4d 100644
--- a/fs/hpfs/file.c
+++ b/fs/hpfs/file.c
@@ -131,6 +131,24 @@ static int hpfs_write_begin(struct file *file, struct address_space *mapping,
 	return ret;
 }
 
+static int hpfs_write_end(struct file *file, struct address_space *mapping,
+			loff_t pos, unsigned len, unsigned copied,
+			struct page *pagep, void *fsdata)
+{
+	struct inode *inode = mapping->host;
+	int err;
+	err = generic_write_end(file, mapping, pos, len, copied, pagep, fsdata);
+	if (err < len)
+		hpfs_write_failed(mapping, pos + len);
+	if (!(err < 0)) {
+		/* make sure we write it on close, if not earlier */
+		hpfs_lock(inode->i_sb);
+		hpfs_i(inode)->i_dirty = 1;
+		hpfs_unlock(inode->i_sb);
+	}
+	return err;
+}
+
 static sector_t _hpfs_bmap(struct address_space *mapping, sector_t block)
 {
 	return generic_block_bmap(mapping,block,hpfs_get_block);
@@ -140,30 +158,16 @@ const struct address_space_operations hpfs_aops = {
 	.readpage = hpfs_readpage,
 	.writepage = hpfs_writepage,
 	.write_begin = hpfs_write_begin,
-	.write_end = generic_write_end,
+	.write_end = hpfs_write_end,
 	.bmap = _hpfs_bmap
 };
 
-static ssize_t hpfs_file_write(struct file *file, const char __user *buf,
-			size_t count, loff_t *ppos)
-{
-	ssize_t retval;
-
-	retval = do_sync_write(file, buf, count, ppos);
-	if (retval > 0) {
-		hpfs_lock(file->f_path.dentry->d_sb);
-		hpfs_i(file_inode(file))->i_dirty = 1;
-		hpfs_unlock(file->f_path.dentry->d_sb);
-	}
-	return retval;
-}
-
 const struct file_operations hpfs_file_ops =
 {
 	.llseek		= generic_file_llseek,
 	.read		= do_sync_read,
 	.aio_read	= generic_file_aio_read,
-	.write		= hpfs_file_write,
+	.write		= do_sync_write,
 	.aio_write	= generic_file_aio_write,
 	.mmap		= generic_file_mmap,
 	.release	= hpfs_file_release,
diff --git a/fs/inode.c b/fs/inode.c
index f5f7c06..5b76d9b 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -1803,7 +1803,7 @@ void init_special_inode(struct inode *inode, umode_t mode, dev_t rdev)
 		inode->i_fop = &def_blk_fops;
 		inode->i_rdev = rdev;
 	} else if (S_ISFIFO(mode))
-		inode->i_fop = &def_fifo_fops;
+		inode->i_fop = &pipefifo_fops;
 	else if (S_ISSOCK(mode))
 		inode->i_fop = &bad_sock_fops;
 	else
diff --git a/fs/internal.h b/fs/internal.h
index 4be7823..eaa75f7 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -130,3 +130,8 @@ extern struct dentry *__d_alloc(struct super_block *, const struct qstr *);
  * read_write.c
  */
 extern ssize_t __kernel_write(struct file *, const char *, size_t, loff_t *);
+
+/*
+ * pipe.c
+ */
+extern const struct file_operations pipefifo_fops;
diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c
index 86b39b1..b91b688 100644
--- a/fs/jbd/commit.c
+++ b/fs/jbd/commit.c
@@ -163,7 +163,7 @@ static void journal_do_submit_data(struct buffer_head **wbuf, int bufs,
 	for (i = 0; i < bufs; i++) {
 		wbuf[i]->b_end_io = end_buffer_write_sync;
 		/* We use-up our safety reference in submit_bh() */
-		submit_bh(write_op, wbuf[i]);
+		_submit_bh(write_op, wbuf[i], 1 << BIO_SNAP_STABLE);
 	}
 }
 
@@ -667,7 +667,7 @@ start_journal_io:
 				clear_buffer_dirty(bh);
 				set_buffer_uptodate(bh);
 				bh->b_end_io = journal_end_buffer_io_sync;
-				submit_bh(write_op, bh);
+				_submit_bh(write_op, bh, 1 << BIO_SNAP_STABLE);
 			}
 			cond_resched();
 
diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c
index 81cc7ea..81880c6 100644
--- a/fs/jbd/journal.c
+++ b/fs/jbd/journal.c
@@ -564,6 +564,16 @@ int log_wait_commit(journal_t *journal, tid_t tid)
 	spin_unlock(&journal->j_state_lock);
 #endif
 	spin_lock(&journal->j_state_lock);
+	/*
+	 * Not running or committing trans? Must be already committed. This
+	 * saves us from waiting for a *long* time when tid overflows.
+	 */
+	if (!((journal->j_running_transaction &&
+	       journal->j_running_transaction->t_tid == tid) ||
+	      (journal->j_committing_transaction &&
+	       journal->j_committing_transaction->t_tid == tid)))
+		goto out_unlock;
+
 	if (!tid_geq(journal->j_commit_waited, tid))
 		journal->j_commit_waited = tid;
 	while (tid_gt(tid, journal->j_commit_sequence)) {
@@ -575,6 +585,7 @@ int log_wait_commit(journal_t *journal, tid_t tid)
 				!tid_gt(tid, journal->j_commit_sequence));
 		spin_lock(&journal->j_state_lock);
 	}
+out_unlock:
 	spin_unlock(&journal->j_state_lock);
 
 	if (unlikely(is_journal_aborted(journal))) {
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
index 750c701..0f53946 100644
--- a/fs/jbd2/commit.c
+++ b/fs/jbd2/commit.c
@@ -382,7 +382,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
 	int space_left = 0;
 	int first_tag = 0;
 	int tag_flag;
-	int i, to_free = 0;
+	int i;
 	int tag_bytes = journal_tag_bytes(journal);
 	struct buffer_head *cbh = NULL; /* For transactional checksums */
 	__u32 crc32_sum = ~0;
@@ -1134,7 +1134,7 @@ restart_loop:
 	journal->j_stats.run.rs_blocks_logged += stats.run.rs_blocks_logged;
 	spin_unlock(&journal->j_history_lock);
 
-	commit_transaction->t_state = T_FINISHED;
+	commit_transaction->t_state = T_COMMIT_CALLBACK;
 	J_ASSERT(commit_transaction == journal->j_committing_transaction);
 	journal->j_commit_sequence = commit_transaction->t_tid;
 	journal->j_committing_transaction = NULL;
@@ -1149,38 +1149,44 @@ restart_loop:
 				journal->j_average_commit_time*3) / 4;
 	else
 		journal->j_average_commit_time = commit_time;
+
 	write_unlock(&journal->j_state_lock);
 
-	if (commit_transaction->t_checkpoint_list == NULL &&
-	    commit_transaction->t_checkpoint_io_list == NULL) {
-		__jbd2_journal_drop_transaction(journal, commit_transaction);
-		to_free = 1;
+	if (journal->j_checkpoint_transactions == NULL) {
+		journal->j_checkpoint_transactions = commit_transaction;
+		commit_transaction->t_cpnext = commit_transaction;
+		commit_transaction->t_cpprev = commit_transaction;
 	} else {
-		if (journal->j_checkpoint_transactions == NULL) {
-			journal->j_checkpoint_transactions = commit_transaction;
-			commit_transaction->t_cpnext = commit_transaction;
-			commit_transaction->t_cpprev = commit_transaction;
-		} else {
-			commit_transaction->t_cpnext =
-				journal->j_checkpoint_transactions;
-			commit_transaction->t_cpprev =
-				commit_transaction->t_cpnext->t_cpprev;
-			commit_transaction->t_cpnext->t_cpprev =
-				commit_transaction;
-			commit_transaction->t_cpprev->t_cpnext =
+		commit_transaction->t_cpnext =
+			journal->j_checkpoint_transactions;
+		commit_transaction->t_cpprev =
+			commit_transaction->t_cpnext->t_cpprev;
+		commit_transaction->t_cpnext->t_cpprev =
+			commit_transaction;
+		commit_transaction->t_cpprev->t_cpnext =
 				commit_transaction;
-		}
 	}
 	spin_unlock(&journal->j_list_lock);
-
+	/* Drop all spin_locks because commit_callback may be block.
+	 * __journal_remove_checkpoint() can not destroy transaction
+	 * under us because it is not marked as T_FINISHED yet */
 	if (journal->j_commit_callback)
 		journal->j_commit_callback(journal, commit_transaction);
 
 	trace_jbd2_end_commit(journal, commit_transaction);
 	jbd_debug(1, "JBD2: commit %d complete, head %d\n",
 		  journal->j_commit_sequence, journal->j_tail_sequence);
-	if (to_free)
-		jbd2_journal_free_transaction(commit_transaction);
 
+	write_lock(&journal->j_state_lock);
+	spin_lock(&journal->j_list_lock);
+	commit_transaction->t_state = T_FINISHED;
+	/* Recheck checkpoint lists after j_list_lock was dropped */
+	if (commit_transaction->t_checkpoint_list == NULL &&
+	    commit_transaction->t_checkpoint_io_list == NULL) {
+		__jbd2_journal_drop_transaction(journal, commit_transaction);
+		jbd2_journal_free_transaction(commit_transaction);
+	}
+	spin_unlock(&journal->j_list_lock);
+	write_unlock(&journal->j_state_lock);
 	wake_up(&journal->j_wait_done_commit);
 }
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
index ed10991..9b0273f 100644
--- a/fs/jbd2/journal.c
+++ b/fs/jbd2/journal.c
@@ -710,6 +710,37 @@ int jbd2_log_wait_commit(journal_t *journal, tid_t tid)
 }
 
 /*
+ * When this function returns the transaction corresponding to tid
+ * will be completed.  If the transaction has currently running, start
+ * committing that transaction before waiting for it to complete.  If
+ * the transaction id is stale, it is by definition already completed,
+ * so just return SUCCESS.
+ */
+int jbd2_complete_transaction(journal_t *journal, tid_t tid)
+{
+	int	need_to_wait = 1;
+
+	read_lock(&journal->j_state_lock);
+	if (journal->j_running_transaction &&
+	    journal->j_running_transaction->t_tid == tid) {
+		if (journal->j_commit_request != tid) {
+			/* transaction not yet started, so request it */
+			read_unlock(&journal->j_state_lock);
+			jbd2_log_start_commit(journal, tid);
+			goto wait_commit;
+		}
+	} else if (!(journal->j_committing_transaction &&
+		     journal->j_committing_transaction->t_tid == tid))
+		need_to_wait = 0;
+	read_unlock(&journal->j_state_lock);
+	if (!need_to_wait)
+		return 0;
+wait_commit:
+	return jbd2_log_wait_commit(journal, tid);
+}
+EXPORT_SYMBOL(jbd2_complete_transaction);
+
+/*
  * Log buffer allocation routines:
  */
 
@@ -950,7 +981,7 @@ static const struct seq_operations jbd2_seq_info_ops = {
 
 static int jbd2_seq_info_open(struct inode *inode, struct file *file)
 {
-	journal_t *journal = PDE(inode)->data;
+	journal_t *journal = PDE_DATA(inode);
 	struct jbd2_stats_proc_session *s;
 	int rc, size;
 
diff --git a/fs/jfs/inode.c b/fs/jfs/inode.c
index b7dc47b..1781f06 100644
--- a/fs/jfs/inode.c
+++ b/fs/jfs/inode.c
@@ -23,6 +23,7 @@
 #include <linux/pagemap.h>
 #include <linux/quotaops.h>
 #include <linux/writeback.h>
+#include <linux/aio.h>
 #include "jfs_incore.h"
 #include "jfs_inode.h"
 #include "jfs_filsys.h"
diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c
index 6ba4006..f7e042b 100644
--- a/fs/jfs/jfs_imap.c
+++ b/fs/jfs/jfs_imap.c
@@ -1493,7 +1493,7 @@ int diAlloc(struct inode *pip, bool dir, struct inode *ip)
 		/* mask any prior bits for the starting words of the
 		 * summary map.
 		 */
-		mask = ONES << (EXTSPERSUM - bitno);
+		mask = (bitno == 0) ? 0 : (ONES << (EXTSPERSUM - bitno));
 		inosmap = le32_to_cpu(iagp->inosmap[sword]) | mask;
 		extsmap = le32_to_cpu(iagp->extsmap[sword]) | mask;
 
diff --git a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c
index 2eb952c..e641f6e 100644
--- a/fs/jfs/jfs_logmgr.c
+++ b/fs/jfs/jfs_logmgr.c
@@ -2004,7 +2004,6 @@ static int lbmRead(struct jfs_log * log, int pn, struct lbuf ** bpp)
 	bio->bi_io_vec[0].bv_offset = bp->l_offset;
 
 	bio->bi_vcnt = 1;
-	bio->bi_idx = 0;
 	bio->bi_size = LOGPSIZE;
 
 	bio->bi_end_io = lbmIODone;
@@ -2145,7 +2144,6 @@ static void lbmStartIO(struct lbuf * bp)
 	bio->bi_io_vec[0].bv_offset = bp->l_offset;
 
 	bio->bi_vcnt = 1;
-	bio->bi_idx = 0;
 	bio->bi_size = LOGPSIZE;
 
 	bio->bi_end_io = lbmIODone;
@@ -2154,7 +2152,7 @@ static void lbmStartIO(struct lbuf * bp)
 	/* check if journaling to disk has been disabled */
 	if (log->no_integrity) {
 		bio->bi_size = 0;
-		lbmIODone(bio, 0);
+		lbmIODone(bio, 0, NULL);
 	} else {
 		submit_bio(WRITE_SYNC, bio);
 		INCREMENT(lmStat.submitted);
@@ -2192,7 +2190,7 @@ static int lbmIOWait(struct lbuf * bp, int flag)
  *
  * executed at INTIODONE level
  */
-static void lbmIODone(struct bio *bio, int error)
+static void lbmIODone(struct bio *bio, int error, struct batch_complete *batch)
 {
 	struct lbuf *bp = bio->bi_private;
 	struct lbuf *nextbp, *tail;
diff --git a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c
index 6740d34..6ba6757 100644
--- a/fs/jfs/jfs_metapage.c
+++ b/fs/jfs/jfs_metapage.c
@@ -283,7 +283,8 @@ static void last_read_complete(struct page *page)
 	unlock_page(page);
 }
 
-static void metapage_read_end_io(struct bio *bio, int err)
+static void metapage_read_end_io(struct bio *bio, int err,
+				 struct batch_complete *batch)
 {
 	struct page *page = bio->bi_private;
 
@@ -338,7 +339,8 @@ static void last_write_complete(struct page *page)
 	end_page_writeback(page);
 }
 
-static void metapage_write_end_io(struct bio *bio, int err)
+static void metapage_write_end_io(struct bio *bio, int err,
+				  struct batch_complete *batch)
 {
 	struct page *page = bio->bi_private;
 
diff --git a/fs/logfs/dev_bdev.c b/fs/logfs/dev_bdev.c
index e784a21..0ae2254 100644
--- a/fs/logfs/dev_bdev.c
+++ b/fs/logfs/dev_bdev.c
@@ -14,7 +14,8 @@
 
 #define PAGE_OFS(ofs) ((ofs) & (PAGE_SIZE-1))
 
-static void request_complete(struct bio *bio, int err)
+static void request_complete(struct bio *bio, int err,
+			     struct batch_complete *batch)
 {
 	complete((struct completion *)bio->bi_private);
 }
@@ -32,7 +33,6 @@ static int sync_request(struct page *page, struct block_device *bdev, int rw)
 	bio_vec.bv_len = PAGE_SIZE;
 	bio_vec.bv_offset = 0;
 	bio.bi_vcnt = 1;
-	bio.bi_idx = 0;
 	bio.bi_size = PAGE_SIZE;
 	bio.bi_bdev = bdev;
 	bio.bi_sector = page->index * (PAGE_SIZE >> 9);
@@ -65,7 +65,8 @@ static int bdev_readpage(void *_sb, struct page *page)
 
 static DECLARE_WAIT_QUEUE_HEAD(wq);
 
-static void writeseg_end_io(struct bio *bio, int err)
+static void writeseg_end_io(struct bio *bio, int err,
+			    struct batch_complete *batch)
 {
 	const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
 	struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1;
@@ -108,7 +109,6 @@ static int __bdev_writeseg(struct super_block *sb, u64 ofs, pgoff_t index,
 		if (i >= max_pages) {
 			/* Block layer cannot split bios :( */
 			bio->bi_vcnt = i;
-			bio->bi_idx = 0;
 			bio->bi_size = i * PAGE_SIZE;
 			bio->bi_bdev = super->s_bdev;
 			bio->bi_sector = ofs >> 9;
@@ -136,7 +136,6 @@ static int __bdev_writeseg(struct super_block *sb, u64 ofs, pgoff_t index,
 		unlock_page(page);
 	}
 	bio->bi_vcnt = nr_pages;
-	bio->bi_idx = 0;
 	bio->bi_size = nr_pages * PAGE_SIZE;
 	bio->bi_bdev = super->s_bdev;
 	bio->bi_sector = ofs >> 9;
@@ -171,7 +170,7 @@ static void bdev_writeseg(struct super_block *sb, u64 ofs, size_t len)
 }
 
 
-static void erase_end_io(struct bio *bio, int err) 
+static void erase_end_io(struct bio *bio, int err, struct batch_complete *batch)
 { 
 	const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); 
 	struct super_block *sb = bio->bi_private; 
@@ -202,7 +201,6 @@ static int do_erase(struct super_block *sb, u64 ofs, pgoff_t index,
 		if (i >= max_pages) {
 			/* Block layer cannot split bios :( */
 			bio->bi_vcnt = i;
-			bio->bi_idx = 0;
 			bio->bi_size = i * PAGE_SIZE;
 			bio->bi_bdev = super->s_bdev;
 			bio->bi_sector = ofs >> 9;
@@ -224,7 +222,6 @@ static int do_erase(struct super_block *sb, u64 ofs, pgoff_t index,
 		bio->bi_io_vec[i].bv_offset = 0;
 	}
 	bio->bi_vcnt = nr_pages;
-	bio->bi_idx = 0;
 	bio->bi_size = nr_pages * PAGE_SIZE;
 	bio->bi_bdev = super->s_bdev;
 	bio->bi_sector = ofs >> 9;
diff --git a/fs/logfs/dev_mtd.c b/fs/logfs/dev_mtd.c
index 9c50144..427bb73 100644
--- a/fs/logfs/dev_mtd.c
+++ b/fs/logfs/dev_mtd.c
@@ -245,8 +245,8 @@ static int logfs_mtd_can_write_buf(struct super_block *sb, u64 ofs)
 		goto out;
 	if (memchr_inv(buf, 0xff, super->s_writesize))
 		err = -EIO;
-	kfree(buf);
 out:
+	kfree(buf);
 	return err;
 }
 
diff --git a/fs/logfs/super.c b/fs/logfs/super.c
index 5436029..b256c06 100644
--- a/fs/logfs/super.c
+++ b/fs/logfs/super.c
@@ -287,14 +287,14 @@ static int logfs_make_writeable(struct super_block *sb)
 	if (err)
 		return err;
 
+	/* Do one GC pass before any data gets dirtied */
+	logfs_gc_pass(sb);
+
 	/* Check areas for trailing unaccounted data */
 	err = logfs_check_areas(sb);
 	if (err)
 		return err;
 
-	/* Do one GC pass before any data gets dirtied */
-	logfs_gc_pass(sb);
-
 	/* after all initializations are done, replay the journal
 	 * for rw-mounts, if necessary */
 	err = logfs_replay_journal(sb);
diff --git a/fs/mount.h b/fs/mount.h
index cd50079..64a8581 100644
--- a/fs/mount.h
+++ b/fs/mount.h
@@ -18,6 +18,12 @@ struct mnt_pcp {
 	int mnt_writers;
 };
 
+struct mountpoint {
+	struct list_head m_hash;
+	struct dentry *m_dentry;
+	int m_count;
+};
+
 struct mount {
 	struct list_head mnt_hash;
 	struct mount *mnt_parent;
@@ -40,6 +46,7 @@ struct mount {
 	struct list_head mnt_slave;	/* slave list entry */
 	struct mount *mnt_master;	/* slave is on master->mnt_slave_list */
 	struct mnt_namespace *mnt_ns;	/* containing namespace */
+	struct mountpoint *mnt_mp;	/* where is it mounted */
 #ifdef CONFIG_FSNOTIFY
 	struct hlist_head mnt_fsnotify_marks;
 	__u32 mnt_fsnotify_mask;
diff --git a/fs/mpage.c b/fs/mpage.c
index 0face1c..a4089bb 100644
--- a/fs/mpage.c
+++ b/fs/mpage.c
@@ -41,7 +41,7 @@
  * status of that page is hard.  See end_buffer_async_read() for the details.
  * There is no point in duplicating all that complexity.
  */
-static void mpage_end_io(struct bio *bio, int err)
+static void mpage_end_io(struct bio *bio, int err, struct batch_complete *batch)
 {
 	const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
 	struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1;
diff --git a/fs/namespace.c b/fs/namespace.c
index d581e45..af73554 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -36,6 +36,7 @@ static int mnt_id_start = 0;
 static int mnt_group_start = 1;
 
 static struct list_head *mount_hashtable __read_mostly;
+static struct list_head *mountpoint_hashtable __read_mostly;
 static struct kmem_cache *mnt_cache __read_mostly;
 static struct rw_semaphore namespace_sem;
 
@@ -605,6 +606,51 @@ struct vfsmount *lookup_mnt(struct path *path)
 	}
 }
 
+static struct mountpoint *new_mountpoint(struct dentry *dentry)
+{
+	struct list_head *chain = mountpoint_hashtable + hash(NULL, dentry);
+	struct mountpoint *mp;
+
+	list_for_each_entry(mp, chain, m_hash) {
+		if (mp->m_dentry == dentry) {
+			/* might be worth a WARN_ON() */
+			if (d_unlinked(dentry))
+				return ERR_PTR(-ENOENT);
+			mp->m_count++;
+			return mp;
+		}
+	}
+
+	mp = kmalloc(sizeof(struct mountpoint), GFP_KERNEL);
+	if (!mp)
+		return ERR_PTR(-ENOMEM);
+
+	spin_lock(&dentry->d_lock);
+	if (d_unlinked(dentry)) {
+		spin_unlock(&dentry->d_lock);
+		kfree(mp);
+		return ERR_PTR(-ENOENT);
+	}
+	dentry->d_flags |= DCACHE_MOUNTED;
+	spin_unlock(&dentry->d_lock);
+	mp->m_dentry = dentry;
+	mp->m_count = 1;
+	list_add(&mp->m_hash, chain);
+	return mp;
+}
+
+static void put_mountpoint(struct mountpoint *mp)
+{
+	if (!--mp->m_count) {
+		struct dentry *dentry = mp->m_dentry;
+		spin_lock(&dentry->d_lock);
+		dentry->d_flags &= ~DCACHE_MOUNTED;
+		spin_unlock(&dentry->d_lock);
+		list_del(&mp->m_hash);
+		kfree(mp);
+	}
+}
+
 static inline int check_mnt(struct mount *mnt)
 {
 	return mnt->mnt_ns == current->nsproxy->mnt_ns;
@@ -633,27 +679,6 @@ static void __touch_mnt_namespace(struct mnt_namespace *ns)
 }
 
 /*
- * Clear dentry's mounted state if it has no remaining mounts.
- * vfsmount_lock must be held for write.
- */
-static void dentry_reset_mounted(struct dentry *dentry)
-{
-	unsigned u;
-
-	for (u = 0; u < HASH_SIZE; u++) {
-		struct mount *p;
-
-		list_for_each_entry(p, &mount_hashtable[u], mnt_hash) {
-			if (p->mnt_mountpoint == dentry)
-				return;
-		}
-	}
-	spin_lock(&dentry->d_lock);
-	dentry->d_flags &= ~DCACHE_MOUNTED;
-	spin_unlock(&dentry->d_lock);
-}
-
-/*
  * vfsmount lock must be held for write
  */
 static void detach_mnt(struct mount *mnt, struct path *old_path)
@@ -664,32 +689,35 @@ static void detach_mnt(struct mount *mnt, struct path *old_path)
 	mnt->mnt_mountpoint = mnt->mnt.mnt_root;
 	list_del_init(&mnt->mnt_child);
 	list_del_init(&mnt->mnt_hash);
-	dentry_reset_mounted(old_path->dentry);
+	put_mountpoint(mnt->mnt_mp);
+	mnt->mnt_mp = NULL;
 }
 
 /*
  * vfsmount lock must be held for write
  */
-void mnt_set_mountpoint(struct mount *mnt, struct dentry *dentry,
+void mnt_set_mountpoint(struct mount *mnt,
+			struct mountpoint *mp,
 			struct mount *child_mnt)
 {
+	mp->m_count++;
 	mnt_add_count(mnt, 1);	/* essentially, that's mntget */
-	child_mnt->mnt_mountpoint = dget(dentry);
+	child_mnt->mnt_mountpoint = dget(mp->m_dentry);
 	child_mnt->mnt_parent = mnt;
-	spin_lock(&dentry->d_lock);
-	dentry->d_flags |= DCACHE_MOUNTED;
-	spin_unlock(&dentry->d_lock);
+	child_mnt->mnt_mp = mp;
 }
 
 /*
  * vfsmount lock must be held for write
  */
-static void attach_mnt(struct mount *mnt, struct path *path)
+static void attach_mnt(struct mount *mnt,
+			struct mount *parent,
+			struct mountpoint *mp)
 {
-	mnt_set_mountpoint(real_mount(path->mnt), path->dentry, mnt);
+	mnt_set_mountpoint(parent, mp, mnt);
 	list_add_tail(&mnt->mnt_hash, mount_hashtable +
-			hash(path->mnt, path->dentry));
-	list_add_tail(&mnt->mnt_child, &real_mount(path->mnt)->mnt_mounts);
+			hash(&parent->mnt, mp->m_dentry));
+	list_add_tail(&mnt->mnt_child, &parent->mnt_mounts);
 }
 
 /*
@@ -1095,11 +1123,23 @@ int may_umount(struct vfsmount *mnt)
 
 EXPORT_SYMBOL(may_umount);
 
-void release_mounts(struct list_head *head)
+static LIST_HEAD(unmounted);	/* protected by namespace_sem */
+
+static void namespace_unlock(void)
 {
 	struct mount *mnt;
-	while (!list_empty(head)) {
-		mnt = list_first_entry(head, struct mount, mnt_hash);
+	LIST_HEAD(head);
+
+	if (likely(list_empty(&unmounted))) {
+		up_write(&namespace_sem);
+		return;
+	}
+
+	list_splice_init(&unmounted, &head);
+	up_write(&namespace_sem);
+
+	while (!list_empty(&head)) {
+		mnt = list_first_entry(&head, struct mount, mnt_hash);
 		list_del_init(&mnt->mnt_hash);
 		if (mnt_has_parent(mnt)) {
 			struct dentry *dentry;
@@ -1119,11 +1159,16 @@ void release_mounts(struct list_head *head)
 	}
 }
 
+static inline void namespace_lock(void)
+{
+	down_write(&namespace_sem);
+}
+
 /*
  * vfsmount lock must be held for write
  * namespace_sem must be held for write
  */
-void umount_tree(struct mount *mnt, int propagate, struct list_head *kill)
+void umount_tree(struct mount *mnt, int propagate)
 {
 	LIST_HEAD(tmp_list);
 	struct mount *p;
@@ -1142,20 +1187,20 @@ void umount_tree(struct mount *mnt, int propagate, struct list_head *kill)
 		list_del_init(&p->mnt_child);
 		if (mnt_has_parent(p)) {
 			p->mnt_parent->mnt_ghosts++;
-			dentry_reset_mounted(p->mnt_mountpoint);
+			put_mountpoint(p->mnt_mp);
+			p->mnt_mp = NULL;
 		}
 		change_mnt_propagation(p, MS_PRIVATE);
 	}
-	list_splice(&tmp_list, kill);
+	list_splice(&tmp_list, &unmounted);
 }
 
-static void shrink_submounts(struct mount *mnt, struct list_head *umounts);
+static void shrink_submounts(struct mount *mnt);
 
 static int do_umount(struct mount *mnt, int flags)
 {
 	struct super_block *sb = mnt->mnt.mnt_sb;
 	int retval;
-	LIST_HEAD(umount_list);
 
 	retval = security_sb_umount(&mnt->mnt, flags);
 	if (retval)
@@ -1222,22 +1267,21 @@ static int do_umount(struct mount *mnt, int flags)
 		return retval;
 	}
 
-	down_write(&namespace_sem);
+	namespace_lock();
 	br_write_lock(&vfsmount_lock);
 	event++;
 
 	if (!(flags & MNT_DETACH))
-		shrink_submounts(mnt, &umount_list);
+		shrink_submounts(mnt);
 
 	retval = -EBUSY;
 	if (flags & MNT_DETACH || !propagate_mount_busy(mnt, 2)) {
 		if (!list_empty(&mnt->mnt_list))
-			umount_tree(mnt, 1, &umount_list);
+			umount_tree(mnt, 1);
 		retval = 0;
 	}
 	br_write_unlock(&vfsmount_lock);
-	up_write(&namespace_sem);
-	release_mounts(&umount_list);
+	namespace_unlock();
 	return retval;
 }
 
@@ -1327,8 +1371,7 @@ static bool mnt_ns_loop(struct path *path)
 struct mount *copy_tree(struct mount *mnt, struct dentry *dentry,
 					int flag)
 {
-	struct mount *res, *p, *q, *r;
-	struct path path;
+	struct mount *res, *p, *q, *r, *parent;
 
 	if (!(flag & CL_COPY_ALL) && IS_MNT_UNBINDABLE(mnt))
 		return ERR_PTR(-EINVAL);
@@ -1355,25 +1398,22 @@ struct mount *copy_tree(struct mount *mnt, struct dentry *dentry,
 				q = q->mnt_parent;
 			}
 			p = s;
-			path.mnt = &q->mnt;
-			path.dentry = p->mnt_mountpoint;
+			parent = q;
 			q = clone_mnt(p, p->mnt.mnt_root, flag);
 			if (IS_ERR(q))
 				goto out;
 			br_write_lock(&vfsmount_lock);
 			list_add_tail(&q->mnt_list, &res->mnt_list);
-			attach_mnt(q, &path);
+			attach_mnt(q, parent, p->mnt_mp);
 			br_write_unlock(&vfsmount_lock);
 		}
 	}
 	return res;
 out:
 	if (res) {
-		LIST_HEAD(umount_list);
 		br_write_lock(&vfsmount_lock);
-		umount_tree(res, 0, &umount_list);
+		umount_tree(res, 0);
 		br_write_unlock(&vfsmount_lock);
-		release_mounts(&umount_list);
 	}
 	return q;
 }
@@ -1383,10 +1423,10 @@ out:
 struct vfsmount *collect_mounts(struct path *path)
 {
 	struct mount *tree;
-	down_write(&namespace_sem);
+	namespace_lock();
 	tree = copy_tree(real_mount(path->mnt), path->dentry,
 			 CL_COPY_ALL | CL_PRIVATE);
-	up_write(&namespace_sem);
+	namespace_unlock();
 	if (IS_ERR(tree))
 		return NULL;
 	return &tree->mnt;
@@ -1394,13 +1434,11 @@ struct vfsmount *collect_mounts(struct path *path)
 
 void drop_collected_mounts(struct vfsmount *mnt)
 {
-	LIST_HEAD(umount_list);
-	down_write(&namespace_sem);
+	namespace_lock();
 	br_write_lock(&vfsmount_lock);
-	umount_tree(real_mount(mnt), 0, &umount_list);
+	umount_tree(real_mount(mnt), 0);
 	br_write_unlock(&vfsmount_lock);
-	up_write(&namespace_sem);
-	release_mounts(&umount_list);
+	namespace_unlock();
 }
 
 int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg,
@@ -1509,11 +1547,11 @@ static int invent_group_ids(struct mount *mnt, bool recurse)
  * in allocations.
  */
 static int attach_recursive_mnt(struct mount *source_mnt,
-			struct path *path, struct path *parent_path)
+			struct mount *dest_mnt,
+			struct mountpoint *dest_mp,
+			struct path *parent_path)
 {
 	LIST_HEAD(tree_list);
-	struct mount *dest_mnt = real_mount(path->mnt);
-	struct dentry *dest_dentry = path->dentry;
 	struct mount *child, *p;
 	int err;
 
@@ -1522,7 +1560,7 @@ static int attach_recursive_mnt(struct mount *source_mnt,
 		if (err)
 			goto out;
 	}
-	err = propagate_mnt(dest_mnt, dest_dentry, source_mnt, &tree_list);
+	err = propagate_mnt(dest_mnt, dest_mp, source_mnt, &tree_list);
 	if (err)
 		goto out_cleanup_ids;
 
@@ -1534,10 +1572,10 @@ static int attach_recursive_mnt(struct mount *source_mnt,
 	}
 	if (parent_path) {
 		detach_mnt(source_mnt, parent_path);
-		attach_mnt(source_mnt, path);
+		attach_mnt(source_mnt, dest_mnt, dest_mp);
 		touch_mnt_namespace(source_mnt->mnt_ns);
 	} else {
-		mnt_set_mountpoint(dest_mnt, dest_dentry, source_mnt);
+		mnt_set_mountpoint(dest_mnt, dest_mp, source_mnt);
 		commit_tree(source_mnt);
 	}
 
@@ -1556,46 +1594,53 @@ static int attach_recursive_mnt(struct mount *source_mnt,
 	return err;
 }
 
-static int lock_mount(struct path *path)
+static struct mountpoint *lock_mount(struct path *path)
 {
 	struct vfsmount *mnt;
+	struct dentry *dentry = path->dentry;
 retry:
-	mutex_lock(&path->dentry->d_inode->i_mutex);
-	if (unlikely(cant_mount(path->dentry))) {
-		mutex_unlock(&path->dentry->d_inode->i_mutex);
-		return -ENOENT;
+	mutex_lock(&dentry->d_inode->i_mutex);
+	if (unlikely(cant_mount(dentry))) {
+		mutex_unlock(&dentry->d_inode->i_mutex);
+		return ERR_PTR(-ENOENT);
 	}
-	down_write(&namespace_sem);
+	namespace_lock();
 	mnt = lookup_mnt(path);
-	if (likely(!mnt))
-		return 0;
-	up_write(&namespace_sem);
+	if (likely(!mnt)) {
+		struct mountpoint *mp = new_mountpoint(dentry);
+		if (IS_ERR(mp)) {
+			namespace_unlock();
+			mutex_unlock(&dentry->d_inode->i_mutex);
+			return mp;
+		}
+		return mp;
+	}
+	namespace_unlock();
 	mutex_unlock(&path->dentry->d_inode->i_mutex);
 	path_put(path);
 	path->mnt = mnt;
-	path->dentry = dget(mnt->mnt_root);
+	dentry = path->dentry = dget(mnt->mnt_root);
 	goto retry;
 }
 
-static void unlock_mount(struct path *path)
+static void unlock_mount(struct mountpoint *where)
 {
-	up_write(&namespace_sem);
-	mutex_unlock(&path->dentry->d_inode->i_mutex);
+	struct dentry *dentry = where->m_dentry;
+	put_mountpoint(where);
+	namespace_unlock();
+	mutex_unlock(&dentry->d_inode->i_mutex);
 }
 
-static int graft_tree(struct mount *mnt, struct path *path)
+static int graft_tree(struct mount *mnt, struct mount *p, struct mountpoint *mp)
 {
 	if (mnt->mnt.mnt_sb->s_flags & MS_NOUSER)
 		return -EINVAL;
 
-	if (S_ISDIR(path->dentry->d_inode->i_mode) !=
+	if (S_ISDIR(mp->m_dentry->d_inode->i_mode) !=
 	      S_ISDIR(mnt->mnt.mnt_root->d_inode->i_mode))
 		return -ENOTDIR;
 
-	if (d_unlinked(path->dentry))
-		return -ENOENT;
-
-	return attach_recursive_mnt(mnt, path, NULL);
+	return attach_recursive_mnt(mnt, p, mp, NULL);
 }
 
 /*
@@ -1633,7 +1678,7 @@ static int do_change_type(struct path *path, int flag)
 	if (!type)
 		return -EINVAL;
 
-	down_write(&namespace_sem);
+	namespace_lock();
 	if (type == MS_SHARED) {
 		err = invent_group_ids(mnt, recurse);
 		if (err)
@@ -1646,7 +1691,7 @@ static int do_change_type(struct path *path, int flag)
 	br_write_unlock(&vfsmount_lock);
 
  out_unlock:
-	up_write(&namespace_sem);
+	namespace_unlock();
 	return err;
 }
 
@@ -1656,9 +1701,9 @@ static int do_change_type(struct path *path, int flag)
 static int do_loopback(struct path *path, const char *old_name,
 				int recurse)
 {
-	LIST_HEAD(umount_list);
 	struct path old_path;
-	struct mount *mnt = NULL, *old;
+	struct mount *mnt = NULL, *old, *parent;
+	struct mountpoint *mp;
 	int err;
 	if (!old_name || !*old_name)
 		return -EINVAL;
@@ -1670,17 +1715,19 @@ static int do_loopback(struct path *path, const char *old_name,
 	if (mnt_ns_loop(&old_path))
 		goto out; 
 
-	err = lock_mount(path);
-	if (err)
+	mp = lock_mount(path);
+	err = PTR_ERR(mp);
+	if (IS_ERR(mp))
 		goto out;
 
 	old = real_mount(old_path.mnt);
+	parent = real_mount(path->mnt);
 
 	err = -EINVAL;
 	if (IS_MNT_UNBINDABLE(old))
 		goto out2;
 
-	if (!check_mnt(real_mount(path->mnt)) || !check_mnt(old))
+	if (!check_mnt(parent) || !check_mnt(old))
 		goto out2;
 
 	if (recurse)
@@ -1693,15 +1740,14 @@ static int do_loopback(struct path *path, const char *old_name,
 		goto out;
 	}
 
-	err = graft_tree(mnt, path);
+	err = graft_tree(mnt, parent, mp);
 	if (err) {
 		br_write_lock(&vfsmount_lock);
-		umount_tree(mnt, 0, &umount_list);
+		umount_tree(mnt, 0);
 		br_write_unlock(&vfsmount_lock);
 	}
 out2:
-	unlock_mount(path);
-	release_mounts(&umount_list);
+	unlock_mount(mp);
 out:
 	path_put(&old_path);
 	return err;
@@ -1786,6 +1832,7 @@ static int do_move_mount(struct path *path, const char *old_name)
 	struct path old_path, parent_path;
 	struct mount *p;
 	struct mount *old;
+	struct mountpoint *mp;
 	int err;
 	if (!old_name || !*old_name)
 		return -EINVAL;
@@ -1793,8 +1840,9 @@ static int do_move_mount(struct path *path, const char *old_name)
 	if (err)
 		return err;
 
-	err = lock_mount(path);
-	if (err < 0)
+	mp = lock_mount(path);
+	err = PTR_ERR(mp);
+	if (IS_ERR(mp))
 		goto out;
 
 	old = real_mount(old_path.mnt);
@@ -1804,9 +1852,6 @@ static int do_move_mount(struct path *path, const char *old_name)
 	if (!check_mnt(p) || !check_mnt(old))
 		goto out1;
 
-	if (d_unlinked(path->dentry))
-		goto out1;
-
 	err = -EINVAL;
 	if (old_path.dentry != old_path.mnt->mnt_root)
 		goto out1;
@@ -1833,7 +1878,7 @@ static int do_move_mount(struct path *path, const char *old_name)
 		if (p == old)
 			goto out1;
 
-	err = attach_recursive_mnt(old, path, &parent_path);
+	err = attach_recursive_mnt(old, real_mount(path->mnt), mp, &parent_path);
 	if (err)
 		goto out1;
 
@@ -1841,7 +1886,7 @@ static int do_move_mount(struct path *path, const char *old_name)
 	 * automatically */
 	list_del_init(&old->mnt_expire);
 out1:
-	unlock_mount(path);
+	unlock_mount(mp);
 out:
 	if (!err)
 		path_put(&parent_path);
@@ -1877,21 +1922,24 @@ static struct vfsmount *fs_set_subtype(struct vfsmount *mnt, const char *fstype)
  */
 static int do_add_mount(struct mount *newmnt, struct path *path, int mnt_flags)
 {
+	struct mountpoint *mp;
+	struct mount *parent;
 	int err;
 
 	mnt_flags &= ~(MNT_SHARED | MNT_WRITE_HOLD | MNT_INTERNAL);
 
-	err = lock_mount(path);
-	if (err)
-		return err;
+	mp = lock_mount(path);
+	if (IS_ERR(mp))
+		return PTR_ERR(mp);
 
+	parent = real_mount(path->mnt);
 	err = -EINVAL;
-	if (unlikely(!check_mnt(real_mount(path->mnt)))) {
+	if (unlikely(!check_mnt(parent))) {
 		/* that's acceptable only for automounts done in private ns */
 		if (!(mnt_flags & MNT_SHRINKABLE))
 			goto unlock;
 		/* ... and for those we'd better have mountpoint still alive */
-		if (!real_mount(path->mnt)->mnt_ns)
+		if (!parent->mnt_ns)
 			goto unlock;
 	}
 
@@ -1906,10 +1954,10 @@ static int do_add_mount(struct mount *newmnt, struct path *path, int mnt_flags)
 		goto unlock;
 
 	newmnt->mnt.mnt_flags = mnt_flags;
-	err = graft_tree(newmnt, path);
+	err = graft_tree(newmnt, parent, mp);
 
 unlock:
-	unlock_mount(path);
+	unlock_mount(mp);
 	return err;
 }
 
@@ -1982,11 +2030,11 @@ int finish_automount(struct vfsmount *m, struct path *path)
 fail:
 	/* remove m from any expiration list it may be on */
 	if (!list_empty(&mnt->mnt_expire)) {
-		down_write(&namespace_sem);
+		namespace_lock();
 		br_write_lock(&vfsmount_lock);
 		list_del_init(&mnt->mnt_expire);
 		br_write_unlock(&vfsmount_lock);
-		up_write(&namespace_sem);
+		namespace_unlock();
 	}
 	mntput(m);
 	mntput(m);
@@ -2000,13 +2048,13 @@ fail:
  */
 void mnt_set_expiry(struct vfsmount *mnt, struct list_head *expiry_list)
 {
-	down_write(&namespace_sem);
+	namespace_lock();
 	br_write_lock(&vfsmount_lock);
 
 	list_add_tail(&real_mount(mnt)->mnt_expire, expiry_list);
 
 	br_write_unlock(&vfsmount_lock);
-	up_write(&namespace_sem);
+	namespace_unlock();
 }
 EXPORT_SYMBOL(mnt_set_expiry);
 
@@ -2019,12 +2067,11 @@ void mark_mounts_for_expiry(struct list_head *mounts)
 {
 	struct mount *mnt, *next;
 	LIST_HEAD(graveyard);
-	LIST_HEAD(umounts);
 
 	if (list_empty(mounts))
 		return;
 
-	down_write(&namespace_sem);
+	namespace_lock();
 	br_write_lock(&vfsmount_lock);
 
 	/* extract from the expiration list every vfsmount that matches the
@@ -2042,12 +2089,10 @@ void mark_mounts_for_expiry(struct list_head *mounts)
 	while (!list_empty(&graveyard)) {
 		mnt = list_first_entry(&graveyard, struct mount, mnt_expire);
 		touch_mnt_namespace(mnt->mnt_ns);
-		umount_tree(mnt, 1, &umounts);
+		umount_tree(mnt, 1);
 	}
 	br_write_unlock(&vfsmount_lock);
-	up_write(&namespace_sem);
-
-	release_mounts(&umounts);
+	namespace_unlock();
 }
 
 EXPORT_SYMBOL_GPL(mark_mounts_for_expiry);
@@ -2104,7 +2149,7 @@ resume:
  *
  * vfsmount_lock must be held for write
  */
-static void shrink_submounts(struct mount *mnt, struct list_head *umounts)
+static void shrink_submounts(struct mount *mnt)
 {
 	LIST_HEAD(graveyard);
 	struct mount *m;
@@ -2115,7 +2160,7 @@ static void shrink_submounts(struct mount *mnt, struct list_head *umounts)
 			m = list_first_entry(&graveyard, struct mount,
 						mnt_expire);
 			touch_mnt_namespace(m->mnt_ns);
-			umount_tree(m, 1, umounts);
+			umount_tree(m, 1);
 		}
 	}
 }
@@ -2342,14 +2387,14 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns,
 	if (IS_ERR(new_ns))
 		return new_ns;
 
-	down_write(&namespace_sem);
+	namespace_lock();
 	/* First pass: copy the tree topology */
 	copy_flags = CL_COPY_ALL | CL_EXPIRE;
 	if (user_ns != mnt_ns->user_ns)
 		copy_flags |= CL_SHARED_TO_SLAVE | CL_UNPRIVILEGED;
 	new = copy_tree(old, old->mnt.mnt_root, copy_flags);
 	if (IS_ERR(new)) {
-		up_write(&namespace_sem);
+		namespace_unlock();
 		free_mnt_ns(new_ns);
 		return ERR_CAST(new);
 	}
@@ -2380,7 +2425,7 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns,
 		p = next_mnt(p, old);
 		q = next_mnt(q, new);
 	}
-	up_write(&namespace_sem);
+	namespace_unlock();
 
 	if (rootmnt)
 		mntput(rootmnt);
@@ -2550,7 +2595,8 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root,
 		const char __user *, put_old)
 {
 	struct path new, old, parent_path, root_parent, root;
-	struct mount *new_mnt, *root_mnt;
+	struct mount *new_mnt, *root_mnt, *old_mnt;
+	struct mountpoint *old_mp, *root_mp;
 	int error;
 
 	if (!may_mount())
@@ -2569,14 +2615,16 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root,
 		goto out2;
 
 	get_fs_root(current->fs, &root);
-	error = lock_mount(&old);
-	if (error)
+	old_mp = lock_mount(&old);
+	error = PTR_ERR(old_mp);
+	if (IS_ERR(old_mp))
 		goto out3;
 
 	error = -EINVAL;
 	new_mnt = real_mount(new.mnt);
 	root_mnt = real_mount(root.mnt);
-	if (IS_MNT_SHARED(real_mount(old.mnt)) ||
+	old_mnt = real_mount(old.mnt);
+	if (IS_MNT_SHARED(old_mnt) ||
 		IS_MNT_SHARED(new_mnt->mnt_parent) ||
 		IS_MNT_SHARED(root_mnt->mnt_parent))
 		goto out4;
@@ -2585,37 +2633,37 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root,
 	error = -ENOENT;
 	if (d_unlinked(new.dentry))
 		goto out4;
-	if (d_unlinked(old.dentry))
-		goto out4;
 	error = -EBUSY;
-	if (new.mnt == root.mnt ||
-	    old.mnt == root.mnt)
+	if (new_mnt == root_mnt || old_mnt == root_mnt)
 		goto out4; /* loop, on the same file system  */
 	error = -EINVAL;
 	if (root.mnt->mnt_root != root.dentry)
 		goto out4; /* not a mountpoint */
 	if (!mnt_has_parent(root_mnt))
 		goto out4; /* not attached */
+	root_mp = root_mnt->mnt_mp;
 	if (new.mnt->mnt_root != new.dentry)
 		goto out4; /* not a mountpoint */
 	if (!mnt_has_parent(new_mnt))
 		goto out4; /* not attached */
 	/* make sure we can reach put_old from new_root */
-	if (!is_path_reachable(real_mount(old.mnt), old.dentry, &new))
+	if (!is_path_reachable(old_mnt, old.dentry, &new))
 		goto out4;
+	root_mp->m_count++; /* pin it so it won't go away */
 	br_write_lock(&vfsmount_lock);
 	detach_mnt(new_mnt, &parent_path);
 	detach_mnt(root_mnt, &root_parent);
 	/* mount old root on put_old */
-	attach_mnt(root_mnt, &old);
+	attach_mnt(root_mnt, old_mnt, old_mp);
 	/* mount new_root on / */
-	attach_mnt(new_mnt, &root_parent);
+	attach_mnt(new_mnt, real_mount(root_parent.mnt), root_mp);
 	touch_mnt_namespace(current->nsproxy->mnt_ns);
 	br_write_unlock(&vfsmount_lock);
 	chroot_fs_refs(&root, &new);
+	put_mountpoint(root_mp);
 	error = 0;
 out4:
-	unlock_mount(&old);
+	unlock_mount(old_mp);
 	if (!error) {
 		path_put(&root_parent);
 		path_put(&parent_path);
@@ -2670,14 +2718,17 @@ void __init mnt_init(void)
 			0, SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL);
 
 	mount_hashtable = (struct list_head *)__get_free_page(GFP_ATOMIC);
+	mountpoint_hashtable = (struct list_head *)__get_free_page(GFP_ATOMIC);
 
-	if (!mount_hashtable)
+	if (!mount_hashtable || !mountpoint_hashtable)
 		panic("Failed to allocate mount hash table\n");
 
 	printk(KERN_INFO "Mount-cache hash table entries: %lu\n", HASH_SIZE);
 
 	for (u = 0; u < HASH_SIZE; u++)
 		INIT_LIST_HEAD(&mount_hashtable[u]);
+	for (u = 0; u < HASH_SIZE; u++)
+		INIT_LIST_HEAD(&mountpoint_hashtable[u]);
 
 	br_lock_init(&vfsmount_lock);
 
@@ -2694,16 +2745,13 @@ void __init mnt_init(void)
 
 void put_mnt_ns(struct mnt_namespace *ns)
 {
-	LIST_HEAD(umount_list);
-
 	if (!atomic_dec_and_test(&ns->count))
 		return;
-	down_write(&namespace_sem);
+	namespace_lock();
 	br_write_lock(&vfsmount_lock);
-	umount_tree(ns->root, 0, &umount_list);
+	umount_tree(ns->root, 0);
 	br_write_unlock(&vfsmount_lock);
-	up_write(&namespace_sem);
-	release_mounts(&umount_list);
+	namespace_unlock();
 	free_mnt_ns(ns);
 }
 
diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c
index 434b93e..76cf695 100644
--- a/fs/nfs/blocklayout/blocklayout.c
+++ b/fs/nfs/blocklayout/blocklayout.c
@@ -143,7 +143,7 @@ bl_submit_bio(int rw, struct bio *bio)
 
 static struct bio *bl_alloc_init_bio(int npg, sector_t isect,
 				     struct pnfs_block_extent *be,
-				     void (*end_io)(struct bio *, int err),
+				     bio_end_io_t *end_io,
 				     struct parallel_io *par)
 {
 	struct bio *bio;
@@ -167,7 +167,7 @@ static struct bio *bl_alloc_init_bio(int npg, sector_t isect,
 static struct bio *do_add_page_to_bio(struct bio *bio, int npg, int rw,
 				      sector_t isect, struct page *page,
 				      struct pnfs_block_extent *be,
-				      void (*end_io)(struct bio *, int err),
+				      bio_end_io_t *end_io,
 				      struct parallel_io *par,
 				      unsigned int offset, int len)
 {
@@ -190,7 +190,7 @@ retry:
 static struct bio *bl_add_page_to_bio(struct bio *bio, int npg, int rw,
 				      sector_t isect, struct page *page,
 				      struct pnfs_block_extent *be,
-				      void (*end_io)(struct bio *, int err),
+				      bio_end_io_t *end_io,
 				      struct parallel_io *par)
 {
 	return do_add_page_to_bio(bio, npg, rw, isect, page, be,
@@ -198,7 +198,8 @@ static struct bio *bl_add_page_to_bio(struct bio *bio, int npg, int rw,
 }
 
 /* This is basically copied from mpage_end_io_read */
-static void bl_end_io_read(struct bio *bio, int err)
+static void bl_end_io_read(struct bio *bio, int err,
+			   struct batch_complete *batch)
 {
 	struct parallel_io *par = bio->bi_private;
 	const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
@@ -380,7 +381,8 @@ static void mark_extents_written(struct pnfs_block_layout *bl,
 	}
 }
 
-static void bl_end_io_write_zero(struct bio *bio, int err)
+static void bl_end_io_write_zero(struct bio *bio, int err,
+				 struct batch_complete *batch)
 {
 	struct parallel_io *par = bio->bi_private;
 	const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
@@ -408,7 +410,8 @@ static void bl_end_io_write_zero(struct bio *bio, int err)
 	put_parallel(par);
 }
 
-static void bl_end_io_write(struct bio *bio, int err)
+static void bl_end_io_write(struct bio *bio, int err,
+			    struct batch_complete *batch)
 {
 	struct parallel_io *par = bio->bi_private;
 	const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
@@ -487,7 +490,7 @@ map_block(struct buffer_head *bh, sector_t isect, struct pnfs_block_extent *be)
 }
 
 static void
-bl_read_single_end_io(struct bio *bio, int error)
+bl_read_single_end_io(struct bio *bio, int error, struct batch_complete *batch)
 {
 	struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1;
 	struct page *page = bvec->bv_page;
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
index 5088b57..cff089a 100644
--- a/fs/nfs/callback.c
+++ b/fs/nfs/callback.c
@@ -125,6 +125,9 @@ nfs41_callback_svc(void *vrqstp)
 	set_freezable();
 
 	while (!kthread_should_stop()) {
+		if (try_to_freeze())
+			continue;
+
 		prepare_to_wait(&serv->sv_cb_waitq, &wq, TASK_INTERRUPTIBLE);
 		spin_lock_bh(&serv->sv_cb_lock);
 		if (!list_empty(&serv->sv_cb_list)) {
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c
index 2960512..a13d26e 100644
--- a/fs/nfs/callback_proc.c
+++ b/fs/nfs/callback_proc.c
@@ -500,7 +500,7 @@ __be32 nfs4_callback_recallany(struct cb_recallanyargs *args, void *dummy,
 		     &args->craa_type_mask))
 		pnfs_recall_all_layouts(cps->clp);
 	if (flags)
-		nfs_expire_all_delegation_types(cps->clp, flags);
+		nfs_expire_unused_delegation_types(cps->clp, flags);
 out:
 	dprintk("%s: exit with status = %d\n", __func__, ntohl(status));
 	return status;
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index 6390a4b..f30bd1e 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/delegation.c
@@ -64,7 +64,7 @@ int nfs4_have_delegation(struct inode *inode, fmode_t flags)
 	return ret;
 }
 
-static int nfs_delegation_claim_locks(struct nfs_open_context *ctx, struct nfs4_state *state)
+static int nfs_delegation_claim_locks(struct nfs_open_context *ctx, struct nfs4_state *state, const nfs4_stateid *stateid)
 {
 	struct inode *inode = state->inode;
 	struct file_lock *fl;
@@ -83,7 +83,7 @@ static int nfs_delegation_claim_locks(struct nfs_open_context *ctx, struct nfs4_
 		if (nfs_file_open_context(fl->fl_file) != ctx)
 			continue;
 		unlock_flocks();
-		status = nfs4_lock_delegation_recall(state, fl);
+		status = nfs4_lock_delegation_recall(fl, state, stateid);
 		if (status < 0)
 			goto out;
 		lock_flocks();
@@ -120,7 +120,7 @@ again:
 		seq = raw_seqcount_begin(&sp->so_reclaim_seqcount);
 		err = nfs4_open_delegation_recall(ctx, state, stateid);
 		if (!err)
-			err = nfs_delegation_claim_locks(ctx, state);
+			err = nfs_delegation_claim_locks(ctx, state, stateid);
 		if (!err && read_seqcount_retry(&sp->so_reclaim_seqcount, seq))
 			err = -EAGAIN;
 		mutex_unlock(&sp->so_delegreturn_mutex);
@@ -389,6 +389,24 @@ out:
 	return err;
 }
 
+static bool nfs_delegation_need_return(struct nfs_delegation *delegation)
+{
+	bool ret = false;
+
+	if (test_and_clear_bit(NFS_DELEGATION_RETURN, &delegation->flags))
+		ret = true;
+	if (test_and_clear_bit(NFS_DELEGATION_RETURN_IF_CLOSED, &delegation->flags) && !ret) {
+		struct inode *inode;
+
+		spin_lock(&delegation->lock);
+		inode = delegation->inode;
+		if (inode && list_empty(&NFS_I(inode)->open_files))
+			ret = true;
+		spin_unlock(&delegation->lock);
+	}
+	return ret;
+}
+
 /**
  * nfs_client_return_marked_delegations - return previously marked delegations
  * @clp: nfs_client to process
@@ -411,8 +429,7 @@ restart:
 	list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
 		list_for_each_entry_rcu(delegation, &server->delegations,
 								super_list) {
-			if (!test_and_clear_bit(NFS_DELEGATION_RETURN,
-							&delegation->flags))
+			if (!nfs_delegation_need_return(delegation))
 				continue;
 			inode = nfs_delegation_grab_inode(delegation);
 			if (inode == NULL)
@@ -471,6 +488,13 @@ int nfs4_inode_return_delegation(struct inode *inode)
 	return err;
 }
 
+static void nfs_mark_return_if_closed_delegation(struct nfs_server *server,
+		struct nfs_delegation *delegation)
+{
+	set_bit(NFS_DELEGATION_RETURN_IF_CLOSED, &delegation->flags);
+	set_bit(NFS4CLNT_DELEGRETURN, &server->nfs_client->cl_state);
+}
+
 static void nfs_mark_return_delegation(struct nfs_server *server,
 		struct nfs_delegation *delegation)
 {
@@ -478,6 +502,45 @@ static void nfs_mark_return_delegation(struct nfs_server *server,
 	set_bit(NFS4CLNT_DELEGRETURN, &server->nfs_client->cl_state);
 }
 
+static bool nfs_server_mark_return_all_delegations(struct nfs_server *server)
+{
+	struct nfs_delegation *delegation;
+	bool ret = false;
+
+	list_for_each_entry_rcu(delegation, &server->delegations, super_list) {
+		nfs_mark_return_delegation(server, delegation);
+		ret = true;
+	}
+	return ret;
+}
+
+static void nfs_client_mark_return_all_delegations(struct nfs_client *clp)
+{
+	struct nfs_server *server;
+
+	rcu_read_lock();
+	list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link)
+		nfs_server_mark_return_all_delegations(server);
+	rcu_read_unlock();
+}
+
+static void nfs_delegation_run_state_manager(struct nfs_client *clp)
+{
+	if (test_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state))
+		nfs4_schedule_state_manager(clp);
+}
+
+/**
+ * nfs_expire_all_delegations
+ * @clp: client to process
+ *
+ */
+void nfs_expire_all_delegations(struct nfs_client *clp)
+{
+	nfs_client_mark_return_all_delegations(clp);
+	nfs_delegation_run_state_manager(clp);
+}
+
 /**
  * nfs_super_return_all_delegations - return delegations for one superblock
  * @sb: sb to process
@@ -486,24 +549,22 @@ static void nfs_mark_return_delegation(struct nfs_server *server,
 void nfs_server_return_all_delegations(struct nfs_server *server)
 {
 	struct nfs_client *clp = server->nfs_client;
-	struct nfs_delegation *delegation;
+	bool need_wait;
 
 	if (clp == NULL)
 		return;
 
 	rcu_read_lock();
-	list_for_each_entry_rcu(delegation, &server->delegations, super_list) {
-		spin_lock(&delegation->lock);
-		set_bit(NFS_DELEGATION_RETURN, &delegation->flags);
-		spin_unlock(&delegation->lock);
-	}
+	need_wait = nfs_server_mark_return_all_delegations(server);
 	rcu_read_unlock();
 
-	if (nfs_client_return_marked_delegations(clp) != 0)
+	if (need_wait) {
 		nfs4_schedule_state_manager(clp);
+		nfs4_wait_clnt_recover(clp);
+	}
 }
 
-static void nfs_mark_return_all_delegation_types(struct nfs_server *server,
+static void nfs_mark_return_unused_delegation_types(struct nfs_server *server,
 						 fmode_t flags)
 {
 	struct nfs_delegation *delegation;
@@ -512,27 +573,21 @@ 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(server, delegation);
+			nfs_mark_return_if_closed_delegation(server, delegation);
 	}
 }
 
-static void nfs_client_mark_return_all_delegation_types(struct nfs_client *clp,
+static void nfs_client_mark_return_unused_delegation_types(struct nfs_client *clp,
 							fmode_t flags)
 {
 	struct nfs_server *server;
 
 	rcu_read_lock();
 	list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link)
-		nfs_mark_return_all_delegation_types(server, flags);
+		nfs_mark_return_unused_delegation_types(server, flags);
 	rcu_read_unlock();
 }
 
-static void nfs_delegation_run_state_manager(struct nfs_client *clp)
-{
-	if (test_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state))
-		nfs4_schedule_state_manager(clp);
-}
-
 void nfs_remove_bad_delegation(struct inode *inode)
 {
 	struct nfs_delegation *delegation;
@@ -546,27 +601,17 @@ void nfs_remove_bad_delegation(struct inode *inode)
 EXPORT_SYMBOL_GPL(nfs_remove_bad_delegation);
 
 /**
- * nfs_expire_all_delegation_types
+ * nfs_expire_unused_delegation_types
  * @clp: client to process
  * @flags: delegation types to expire
  *
  */
-void nfs_expire_all_delegation_types(struct nfs_client *clp, fmode_t flags)
+void nfs_expire_unused_delegation_types(struct nfs_client *clp, fmode_t flags)
 {
-	nfs_client_mark_return_all_delegation_types(clp, flags);
+	nfs_client_mark_return_unused_delegation_types(clp, flags);
 	nfs_delegation_run_state_manager(clp);
 }
 
-/**
- * nfs_expire_all_delegations
- * @clp: client to process
- *
- */
-void nfs_expire_all_delegations(struct nfs_client *clp)
-{
-	nfs_expire_all_delegation_types(clp, FMODE_READ|FMODE_WRITE);
-}
-
 static void nfs_mark_return_unreferenced_delegations(struct nfs_server *server)
 {
 	struct nfs_delegation *delegation;
@@ -574,7 +619,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(server, delegation);
+		nfs_mark_return_if_closed_delegation(server, delegation);
 	}
 }
 
diff --git a/fs/nfs/delegation.h b/fs/nfs/delegation.h
index d54d4fc..9a79c7a 100644
--- a/fs/nfs/delegation.h
+++ b/fs/nfs/delegation.h
@@ -28,6 +28,7 @@ struct nfs_delegation {
 enum {
 	NFS_DELEGATION_NEED_RECLAIM = 0,
 	NFS_DELEGATION_RETURN,
+	NFS_DELEGATION_RETURN_IF_CLOSED,
 	NFS_DELEGATION_REFERENCED,
 	NFS_DELEGATION_RETURNING,
 };
@@ -41,7 +42,7 @@ void nfs_inode_return_delegation_noreclaim(struct inode *inode);
 struct inode *nfs_delegation_find_inode(struct nfs_client *clp, const struct nfs_fh *fhandle);
 void nfs_server_return_all_delegations(struct nfs_server *);
 void nfs_expire_all_delegations(struct nfs_client *clp);
-void nfs_expire_all_delegation_types(struct nfs_client *clp, fmode_t flags);
+void nfs_expire_unused_delegation_types(struct nfs_client *clp, fmode_t flags);
 void nfs_expire_unreferenced_delegations(struct nfs_client *clp);
 int nfs_client_return_marked_delegations(struct nfs_client *clp);
 int nfs_delegations_present(struct nfs_client *clp);
@@ -53,7 +54,7 @@ void nfs_delegation_reap_unclaimed(struct nfs_client *clp);
 /* NFSv4 delegation-related procedures */
 int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid, int issync);
 int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state *state, const nfs4_stateid *stateid);
-int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl);
+int nfs4_lock_delegation_recall(struct file_lock *fl, struct nfs4_state *state, const nfs4_stateid *stateid);
 bool nfs4_copy_delegation_stateid(nfs4_stateid *dst, struct inode *inode, fmode_t flags);
 
 void nfs_mark_delegation_referenced(struct nfs_delegation *delegation);
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index f23f455..e093e73 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -1486,6 +1486,8 @@ static int nfs4_lookup_revalidate(struct dentry *dentry, unsigned int flags)
 		goto no_open;
 	if (d_mountpoint(dentry))
 		goto no_open;
+	if (NFS_SB(dentry->d_sb)->caps & NFS_CAP_ATOMIC_OPEN_V1)
+		goto no_open;
 
 	inode = dentry->d_inode;
 	parent = dget_parent(dentry);
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 1f94167..55b840f 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -565,16 +565,17 @@ static void nfs_init_lock_context(struct nfs_lock_context *l_ctx)
 
 static struct nfs_lock_context *__nfs_find_lock_context(struct nfs_open_context *ctx)
 {
-	struct nfs_lock_context *pos;
+	struct nfs_lock_context *head = &ctx->lock_context;
+	struct nfs_lock_context *pos = head;
 
-	list_for_each_entry(pos, &ctx->lock_context.list, list) {
+	do {
 		if (pos->lockowner.l_owner != current->files)
 			continue;
 		if (pos->lockowner.l_pid != current->tgid)
 			continue;
 		atomic_inc(&pos->count);
 		return pos;
-	}
+	} while ((pos = list_entry(pos->list.next, typeof(*pos), list)) != head);
 	return NULL;
 }
 
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 944c9a5..7ef19ce 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -36,6 +36,7 @@ enum nfs4_client_state {
 
 struct nfs4_minor_version_ops {
 	u32	minor_version;
+	unsigned init_caps;
 
 	int	(*call_sync)(struct rpc_clnt *clnt,
 			struct nfs_server *server,
@@ -149,6 +150,7 @@ enum {
 	NFS_STATE_RECLAIM_REBOOT,	/* OPEN stateid server rebooted */
 	NFS_STATE_RECLAIM_NOGRACE,	/* OPEN stateid needs to recover state */
 	NFS_STATE_POSIX_LOCKS,		/* Posix locks are supported */
+	NFS_STATE_RECOVERY_FAILED,	/* OPEN stateid state recovery failed */
 };
 
 struct nfs4_state {
@@ -233,6 +235,10 @@ extern struct rpc_clnt *nfs4_proc_lookup_mountpoint(struct inode *, struct qstr
 extern int nfs4_proc_secinfo(struct inode *, const struct qstr *, struct nfs4_secinfo_flavors *);
 extern int nfs4_release_lockowner(struct nfs4_lock_state *);
 extern const struct xattr_handler *nfs4_xattr_handlers[];
+extern int nfs4_set_rw_stateid(nfs4_stateid *stateid,
+		const struct nfs_open_context *ctx,
+		const struct nfs_lock_context *l_ctx,
+		fmode_t fmode);
 
 #if defined(CONFIG_NFS_V4_1)
 static inline struct nfs4_session *nfs4_get_session(const struct nfs_server *server)
@@ -347,13 +353,13 @@ extern int nfs4_wait_clnt_recover(struct nfs_client *clp);
 extern int nfs4_client_recover_expired_lease(struct nfs_client *clp);
 extern void nfs4_schedule_state_manager(struct nfs_client *);
 extern void nfs4_schedule_path_down_recovery(struct nfs_client *clp);
-extern void nfs4_schedule_stateid_recovery(const struct nfs_server *, struct nfs4_state *);
+extern int 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_server_scope(struct nfs_client *,
 				      struct nfs41_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_select_rw_stateid(nfs4_stateid *, struct nfs4_state *,
+extern int nfs4_select_rw_stateid(nfs4_stateid *, struct nfs4_state *,
 		fmode_t, const struct nfs_lockowner *);
 
 extern struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter, gfp_t gfp_mask);
@@ -412,6 +418,11 @@ static inline bool nfs4_stateid_match(const nfs4_stateid *dst, const nfs4_statei
 	return memcmp(dst, src, sizeof(*dst)) == 0;
 }
 
+static inline bool nfs4_valid_open_stateid(const struct nfs4_state *state)
+{
+	return test_bit(NFS_STATE_RECOVERY_FAILED, &state->flags) == 0;
+}
+
 #else
 
 #define nfs4_close_state(a, b) do { } while (0)
diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c
index ac4fc9a..a4f2100 100644
--- a/fs/nfs/nfs4client.c
+++ b/fs/nfs/nfs4client.c
@@ -199,7 +199,9 @@ struct nfs_client *nfs4_init_client(struct nfs_client *clp,
 	clp->rpc_ops = &nfs_v4_clientops;
 
 	__set_bit(NFS_CS_DISCRTRY, &clp->cl_flags);
-	error = nfs_create_rpc_client(clp, timeparms, authflavour);
+	error = nfs_create_rpc_client(clp, timeparms, RPC_AUTH_GSS_KRB5I);
+	if (error == -EINVAL)
+		error = nfs_create_rpc_client(clp, timeparms, RPC_AUTH_NULL);
 	if (error < 0)
 		goto error;
 
@@ -717,6 +719,19 @@ static int nfs4_server_common_setup(struct nfs_server *server,
 	if (error < 0)
 		goto out;
 
+	/* Set the basic capabilities */
+	server->caps |= server->nfs_client->cl_mvops->init_caps;
+	if (server->flags & NFS_MOUNT_NORDIRPLUS)
+			server->caps &= ~NFS_CAP_READDIRPLUS;
+	/*
+	 * Don't use NFS uid/gid mapping if we're using AUTH_SYS or lower
+	 * authentication.
+	 */
+	if (nfs4_disable_idmapping &&
+			server->client->cl_auth->au_flavor == RPC_AUTH_UNIX)
+		server->caps |= NFS_CAP_UIDGID_NOMAP;
+
+
 	/* Probe the root fh to retrieve its FSID and filehandle */
 	error = nfs4_get_rootfh(server, mntfh);
 	if (error < 0)
@@ -760,9 +775,6 @@ static int nfs4_init_server(struct nfs_server *server,
 
 	/* Initialise the client representation from the mount data */
 	server->flags = data->flags;
-	server->caps |= NFS_CAP_ATOMIC_OPEN|NFS_CAP_CHANGE_ATTR|NFS_CAP_POSIX_LOCK;
-	if (!(data->flags & NFS_MOUNT_NORDIRPLUS))
-			server->caps |= NFS_CAP_READDIRPLUS;
 	server->options = data->options;
 
 	/* Get a client record */
@@ -779,13 +791,6 @@ static int nfs4_init_server(struct nfs_server *server,
 	if (error < 0)
 		goto error;
 
-	/*
-	 * Don't use NFS uid/gid mapping if we're using AUTH_SYS or lower
-	 * authentication.
-	 */
-	if (nfs4_disable_idmapping && data->auth_flavors[0] == RPC_AUTH_UNIX)
-		server->caps |= NFS_CAP_UIDGID_NOMAP;
-
 	if (data->rsize)
 		server->rsize = nfs_block_size(data->rsize, NULL);
 	if (data->wsize)
@@ -863,7 +868,6 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data,
 
 	/* Initialise the client representation from the parent server */
 	nfs_server_copy_userdata(server, parent_server);
-	server->caps |= NFS_CAP_ATOMIC_OPEN|NFS_CAP_CHANGE_ATTR;
 
 	/* Get a client representation.
 	 * Note: NFSv4 always uses TCP, */
diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c
index 4fb234d..22d1062 100644
--- a/fs/nfs/nfs4filelayout.c
+++ b/fs/nfs/nfs4filelayout.c
@@ -158,11 +158,14 @@ static int filelayout_async_handle_error(struct rpc_task *task,
 	case -NFS4ERR_OPENMODE:
 		if (state == NULL)
 			break;
-		nfs4_schedule_stateid_recovery(mds_server, state);
+		if (nfs4_schedule_stateid_recovery(mds_server, state) < 0)
+			goto out_bad_stateid;
 		goto wait_on_recovery;
 	case -NFS4ERR_EXPIRED:
-		if (state != NULL)
-			nfs4_schedule_stateid_recovery(mds_server, state);
+		if (state != NULL) {
+			if (nfs4_schedule_stateid_recovery(mds_server, state) < 0)
+				goto out_bad_stateid;
+		}
 		nfs4_schedule_lease_recovery(mds_client);
 		goto wait_on_recovery;
 	/* DS session errors */
@@ -226,6 +229,9 @@ reset:
 out:
 	task->tk_status = 0;
 	return -EAGAIN;
+out_bad_stateid:
+	task->tk_status = -EIO;
+	return 0;
 wait_on_recovery:
 	rpc_sleep_on(&mds_client->cl_rpcwaitq, task, NULL);
 	if (test_bit(NFS4CLNT_MANAGER_RUNNING, &mds_client->cl_state) == 0)
@@ -299,6 +305,10 @@ static void filelayout_read_prepare(struct rpc_task *task, void *data)
 {
 	struct nfs_read_data *rdata = data;
 
+	if (unlikely(test_bit(NFS_CONTEXT_BAD, &rdata->args.context->flags))) {
+		rpc_exit(task, -EIO);
+		return;
+	}
 	if (filelayout_reset_to_mds(rdata->header->lseg)) {
 		dprintk("%s task %u reset io to MDS\n", __func__, task->tk_pid);
 		filelayout_reset_read(rdata);
@@ -307,10 +317,13 @@ static void filelayout_read_prepare(struct rpc_task *task, void *data)
 	}
 	rdata->read_done_cb = filelayout_read_done_cb;
 
-	nfs41_setup_sequence(rdata->ds_clp->cl_session,
+	if (nfs41_setup_sequence(rdata->ds_clp->cl_session,
 			&rdata->args.seq_args,
 			&rdata->res.seq_res,
-			task);
+			task))
+		return;
+	nfs4_set_rw_stateid(&rdata->args.stateid, rdata->args.context,
+			rdata->args.lock_context, FMODE_READ);
 }
 
 static void filelayout_read_call_done(struct rpc_task *task, void *data)
@@ -401,16 +414,23 @@ static void filelayout_write_prepare(struct rpc_task *task, void *data)
 {
 	struct nfs_write_data *wdata = data;
 
+	if (unlikely(test_bit(NFS_CONTEXT_BAD, &wdata->args.context->flags))) {
+		rpc_exit(task, -EIO);
+		return;
+	}
 	if (filelayout_reset_to_mds(wdata->header->lseg)) {
 		dprintk("%s task %u reset io to MDS\n", __func__, task->tk_pid);
 		filelayout_reset_write(wdata);
 		rpc_exit(task, 0);
 		return;
 	}
-	nfs41_setup_sequence(wdata->ds_clp->cl_session,
+	if (nfs41_setup_sequence(wdata->ds_clp->cl_session,
 			&wdata->args.seq_args,
 			&wdata->res.seq_res,
-			task);
+			task))
+		return;
+	nfs4_set_rw_stateid(&wdata->args.stateid, wdata->args.context,
+			wdata->args.lock_context, FMODE_WRITE);
 }
 
 static void filelayout_write_call_done(struct rpc_task *task, void *data)
diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4namespace.c
index 0dd7660..cdb0b41 100644
--- a/fs/nfs/nfs4namespace.c
+++ b/fs/nfs/nfs4namespace.c
@@ -134,33 +134,38 @@ static size_t nfs_parse_server_name(char *string, size_t len,
 	return ret;
 }
 
+/**
+ * nfs_find_best_sec - Find a security mechanism supported locally
+ * @flavors: List of security tuples returned by SECINFO procedure
+ *
+ * Return the pseudoflavor of the first security mechanism in
+ * "flavors" that is locally supported.  Return RPC_AUTH_UNIX if
+ * no matching flavor is found in the array.  The "flavors" array
+ * is searched in the order returned from the server, per RFC 3530
+ * recommendation.
+ */
 rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *flavors)
 {
-	struct gss_api_mech *mech;
-	struct xdr_netobj oid;
-	int i;
-	rpc_authflavor_t pseudoflavor = RPC_AUTH_UNIX;
+	rpc_authflavor_t pseudoflavor;
+	struct nfs4_secinfo4 *secinfo;
+	unsigned int i;
 
 	for (i = 0; i < flavors->num_flavors; i++) {
-		struct nfs4_secinfo_flavor *flavor;
-		flavor = &flavors->flavors[i];
-
-		if (flavor->flavor == RPC_AUTH_NULL || flavor->flavor == RPC_AUTH_UNIX) {
-			pseudoflavor = flavor->flavor;
-			break;
-		} else if (flavor->flavor == RPC_AUTH_GSS) {
-			oid.len  = flavor->gss.sec_oid4.len;
-			oid.data = flavor->gss.sec_oid4.data;
-			mech = gss_mech_get_by_OID(&oid);
-			if (!mech)
-				continue;
-			pseudoflavor = gss_svc_to_pseudoflavor(mech, flavor->gss.service);
-			gss_mech_put(mech);
+		secinfo = &flavors->flavors[i];
+
+		switch (secinfo->flavor) {
+		case RPC_AUTH_NULL:
+		case RPC_AUTH_UNIX:
+		case RPC_AUTH_GSS:
+			pseudoflavor = rpcauth_get_pseudoflavor(secinfo->flavor,
+							&secinfo->flavor_info);
+			if (pseudoflavor != RPC_AUTH_MAXFLAVOR)
+				return pseudoflavor;
 			break;
 		}
 	}
 
-	return pseudoflavor;
+	return RPC_AUTH_UNIX;
 }
 
 static rpc_authflavor_t nfs4_negotiate_security(struct inode *inode, struct qstr *name)
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 26431cf..e3b8848 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -107,6 +107,8 @@ static int nfs4_map_errors(int err)
 		return -EPROTONOSUPPORT;
 	case -NFS4ERR_ACCESS:
 		return -EACCES;
+	case -NFS4ERR_FILE_OPEN:
+		return -EBUSY;
 	default:
 		dprintk("%s could not handle NFSv4 error %d\n",
 				__func__, -err);
@@ -295,7 +297,9 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc
 			}
 			if (state == NULL)
 				break;
-			nfs4_schedule_stateid_recovery(server, state);
+			ret = nfs4_schedule_stateid_recovery(server, state);
+			if (ret < 0)
+				break;
 			goto wait_on_recovery;
 		case -NFS4ERR_DELEG_REVOKED:
 		case -NFS4ERR_ADMIN_REVOKED:
@@ -303,11 +307,16 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc
 			if (state == NULL)
 				break;
 			nfs_remove_bad_delegation(state->inode);
-			nfs4_schedule_stateid_recovery(server, state);
+			ret = nfs4_schedule_stateid_recovery(server, state);
+			if (ret < 0)
+				break;
 			goto wait_on_recovery;
 		case -NFS4ERR_EXPIRED:
-			if (state != NULL)
-				nfs4_schedule_stateid_recovery(server, state);
+			if (state != NULL) {
+				ret = nfs4_schedule_stateid_recovery(server, state);
+				if (ret < 0)
+					break;
+			}
 		case -NFS4ERR_STALE_STATEID:
 		case -NFS4ERR_STALE_CLIENTID:
 			nfs4_schedule_lease_recovery(clp);
@@ -760,6 +769,35 @@ struct nfs4_opendata {
 	int cancelled;
 };
 
+static bool nfs4_clear_cap_atomic_open_v1(struct nfs_server *server,
+		int err, struct nfs4_exception *exception)
+{
+	if (err != -EINVAL)
+		return false;
+	if (!(server->caps & NFS_CAP_ATOMIC_OPEN_V1))
+		return false;
+	server->caps &= ~NFS_CAP_ATOMIC_OPEN_V1;
+	exception->retry = 1;
+	return true;
+}
+
+static enum open_claim_type4
+nfs4_map_atomic_open_claim(struct nfs_server *server,
+		enum open_claim_type4 claim)
+{
+	if (server->caps & NFS_CAP_ATOMIC_OPEN_V1)
+		return claim;
+	switch (claim) {
+	default:
+		return claim;
+	case NFS4_OPEN_CLAIM_FH:
+		return NFS4_OPEN_CLAIM_NULL;
+	case NFS4_OPEN_CLAIM_DELEG_CUR_FH:
+		return NFS4_OPEN_CLAIM_DELEGATE_CUR;
+	case NFS4_OPEN_CLAIM_DELEG_PREV_FH:
+		return NFS4_OPEN_CLAIM_DELEGATE_PREV;
+	}
+}
 
 static void nfs4_init_opendata_res(struct nfs4_opendata *p)
 {
@@ -775,6 +813,7 @@ static void nfs4_init_opendata_res(struct nfs4_opendata *p)
 static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry,
 		struct nfs4_state_owner *sp, fmode_t fmode, int flags,
 		const struct iattr *attrs,
+		enum open_claim_type4 claim,
 		gfp_t gfp_mask)
 {
 	struct dentry *parent = dget_parent(dentry);
@@ -793,7 +832,6 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry,
 	p->dir = parent;
 	p->owner = sp;
 	atomic_inc(&sp->so_count);
-	p->o_arg.fh = NFS_FH(dir);
 	p->o_arg.open_flags = flags;
 	p->o_arg.fmode = fmode & (FMODE_READ|FMODE_WRITE);
 	/* don't put an ACCESS op in OPEN compound if O_EXCL, because ACCESS
@@ -811,7 +849,19 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry,
 	p->o_arg.server = server;
 	p->o_arg.bitmask = server->attr_bitmask;
 	p->o_arg.open_bitmap = &nfs4_fattr_bitmap[0];
-	p->o_arg.claim = NFS4_OPEN_CLAIM_NULL;
+	p->o_arg.claim = nfs4_map_atomic_open_claim(server, claim);
+	switch (p->o_arg.claim) {
+	case NFS4_OPEN_CLAIM_NULL:
+	case NFS4_OPEN_CLAIM_DELEGATE_CUR:
+	case NFS4_OPEN_CLAIM_DELEGATE_PREV:
+		p->o_arg.fh = NFS_FH(dir);
+		break;
+	case NFS4_OPEN_CLAIM_PREVIOUS:
+	case NFS4_OPEN_CLAIM_FH:
+	case NFS4_OPEN_CLAIM_DELEG_CUR_FH:
+	case NFS4_OPEN_CLAIM_DELEG_PREV_FH:
+		p->o_arg.fh = NFS_FH(dentry->d_inode);
+	}
 	if (attrs != NULL && attrs->ia_valid != 0) {
 		__be32 verf[2];
 
@@ -1193,11 +1243,13 @@ static struct nfs_open_context *nfs4_state_find_open_context(struct nfs4_state *
 	return ERR_PTR(-ENOENT);
 }
 
-static struct nfs4_opendata *nfs4_open_recoverdata_alloc(struct nfs_open_context *ctx, struct nfs4_state *state)
+static struct nfs4_opendata *nfs4_open_recoverdata_alloc(struct nfs_open_context *ctx,
+		struct nfs4_state *state, enum open_claim_type4 claim)
 {
 	struct nfs4_opendata *opendata;
 
-	opendata = nfs4_opendata_alloc(ctx->dentry, state->owner, 0, 0, NULL, GFP_NOFS);
+	opendata = nfs4_opendata_alloc(ctx->dentry, state->owner, 0, 0,
+			NULL, claim, GFP_NOFS);
 	if (opendata == NULL)
 		return ERR_PTR(-ENOMEM);
 	opendata->state = state;
@@ -1283,11 +1335,10 @@ static int _nfs4_do_open_reclaim(struct nfs_open_context *ctx, struct nfs4_state
 	fmode_t delegation_type = 0;
 	int status;
 
-	opendata = nfs4_open_recoverdata_alloc(ctx, state);
+	opendata = nfs4_open_recoverdata_alloc(ctx, state,
+			NFS4_OPEN_CLAIM_PREVIOUS);
 	if (IS_ERR(opendata))
 		return PTR_ERR(opendata);
-	opendata->o_arg.claim = NFS4_OPEN_CLAIM_PREVIOUS;
-	opendata->o_arg.fh = NFS_FH(state->inode);
 	rcu_read_lock();
 	delegation = rcu_dereference(NFS_I(state->inode)->delegation);
 	if (delegation != NULL && test_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags) != 0)
@@ -1306,6 +1357,8 @@ static int nfs4_do_open_reclaim(struct nfs_open_context *ctx, struct nfs4_state
 	int err;
 	do {
 		err = _nfs4_do_open_reclaim(ctx, state);
+		if (nfs4_clear_cap_atomic_open_v1(server, err, &exception))
+			continue;
 		if (err != -NFS4ERR_DELAY)
 			break;
 		nfs4_handle_exception(server, err, &exception);
@@ -1320,71 +1373,72 @@ static int nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *sta
 
 	ctx = nfs4_state_find_open_context(state);
 	if (IS_ERR(ctx))
-		return PTR_ERR(ctx);
+		return -EAGAIN;
 	ret = nfs4_do_open_reclaim(ctx, state);
 	put_nfs_open_context(ctx);
 	return ret;
 }
 
-static int _nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state *state, const nfs4_stateid *stateid)
+static int nfs4_handle_delegation_recall_error(struct nfs_server *server, struct nfs4_state *state, const nfs4_stateid *stateid, int err)
 {
-	struct nfs4_opendata *opendata;
-	int ret;
-
-	opendata = nfs4_open_recoverdata_alloc(ctx, state);
-	if (IS_ERR(opendata))
-		return PTR_ERR(opendata);
-	opendata->o_arg.claim = NFS4_OPEN_CLAIM_DELEGATE_CUR;
-	nfs4_stateid_copy(&opendata->o_arg.u.delegation, stateid);
-	ret = nfs4_open_recover(opendata, state);
-	nfs4_opendata_put(opendata);
-	return ret;
+	switch (err) {
+		default:
+			printk(KERN_ERR "NFS: %s: unhandled error "
+					"%d.\n", __func__, err);
+		case 0:
+		case -ENOENT:
+		case -ESTALE:
+			break;
+		case -NFS4ERR_BADSESSION:
+		case -NFS4ERR_BADSLOT:
+		case -NFS4ERR_BAD_HIGH_SLOT:
+		case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
+		case -NFS4ERR_DEADSESSION:
+			set_bit(NFS_DELEGATED_STATE, &state->flags);
+			nfs4_schedule_session_recovery(server->nfs_client->cl_session, err);
+			return -EAGAIN;
+		case -NFS4ERR_STALE_CLIENTID:
+		case -NFS4ERR_STALE_STATEID:
+			set_bit(NFS_DELEGATED_STATE, &state->flags);
+		case -NFS4ERR_EXPIRED:
+			/* Don't recall a delegation if it was lost */
+			nfs4_schedule_lease_recovery(server->nfs_client);
+			return -EAGAIN;
+		case -NFS4ERR_DELEG_REVOKED:
+		case -NFS4ERR_ADMIN_REVOKED:
+		case -NFS4ERR_BAD_STATEID:
+		case -NFS4ERR_OPENMODE:
+			nfs_inode_find_state_and_recover(state->inode,
+					stateid);
+			nfs4_schedule_stateid_recovery(server, state);
+			return 0;
+		case -NFS4ERR_DELAY:
+		case -NFS4ERR_GRACE:
+			set_bit(NFS_DELEGATED_STATE, &state->flags);
+			ssleep(1);
+			return -EAGAIN;
+		case -ENOMEM:
+		case -NFS4ERR_DENIED:
+			/* kill_proc(fl->fl_pid, SIGLOST, 1); */
+			return 0;
+	}
+	return err;
 }
 
 int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state *state, const nfs4_stateid *stateid)
 {
-	struct nfs4_exception exception = { };
 	struct nfs_server *server = NFS_SERVER(state->inode);
+	struct nfs4_opendata *opendata;
 	int err;
-	do {
-		err = _nfs4_open_delegation_recall(ctx, state, stateid);
-		switch (err) {
-			case 0:
-			case -ENOENT:
-			case -ESTALE:
-				goto out;
-			case -NFS4ERR_BADSESSION:
-			case -NFS4ERR_BADSLOT:
-			case -NFS4ERR_BAD_HIGH_SLOT:
-			case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
-			case -NFS4ERR_DEADSESSION:
-				set_bit(NFS_DELEGATED_STATE, &state->flags);
-				nfs4_schedule_session_recovery(server->nfs_client->cl_session, err);
-				err = -EAGAIN;
-				goto out;
-			case -NFS4ERR_STALE_CLIENTID:
-			case -NFS4ERR_STALE_STATEID:
-				set_bit(NFS_DELEGATED_STATE, &state->flags);
-			case -NFS4ERR_EXPIRED:
-				/* Don't recall a delegation if it was lost */
-				nfs4_schedule_lease_recovery(server->nfs_client);
-				err = -EAGAIN;
-				goto out;
-			case -NFS4ERR_DELEG_REVOKED:
-			case -NFS4ERR_ADMIN_REVOKED:
-			case -NFS4ERR_BAD_STATEID:
-				nfs_inode_find_state_and_recover(state->inode,
-						stateid);
-				nfs4_schedule_stateid_recovery(server, state);
-			case -ENOMEM:
-				err = 0;
-				goto out;
-		}
-		set_bit(NFS_DELEGATED_STATE, &state->flags);
-		err = nfs4_handle_exception(server, err, &exception);
-	} while (exception.retry);
-out:
-	return err;
+
+	opendata = nfs4_open_recoverdata_alloc(ctx, state,
+			NFS4_OPEN_CLAIM_DELEG_CUR_FH);
+	if (IS_ERR(opendata))
+		return PTR_ERR(opendata);
+	nfs4_stateid_copy(&opendata->o_arg.u.delegation, stateid);
+	err = nfs4_open_recover(opendata, state);
+	nfs4_opendata_put(opendata);
+	return nfs4_handle_delegation_recall_error(server, state, stateid, err);
 }
 
 static void nfs4_open_confirm_done(struct rpc_task *task, void *calldata)
@@ -1720,7 +1774,8 @@ static int _nfs4_open_expired(struct nfs_open_context *ctx, struct nfs4_state *s
 	struct nfs4_opendata *opendata;
 	int ret;
 
-	opendata = nfs4_open_recoverdata_alloc(ctx, state);
+	opendata = nfs4_open_recoverdata_alloc(ctx, state,
+			NFS4_OPEN_CLAIM_FH);
 	if (IS_ERR(opendata))
 		return PTR_ERR(opendata);
 	ret = nfs4_open_recover(opendata, state);
@@ -1738,6 +1793,8 @@ static int nfs4_do_open_expired(struct nfs_open_context *ctx, struct nfs4_state
 
 	do {
 		err = _nfs4_open_expired(ctx, state);
+		if (nfs4_clear_cap_atomic_open_v1(server, err, &exception))
+			continue;
 		switch (err) {
 		default:
 			goto out;
@@ -1758,7 +1815,7 @@ static int nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *sta
 
 	ctx = nfs4_state_find_open_context(state);
 	if (IS_ERR(ctx))
-		return PTR_ERR(ctx);
+		return -EAGAIN;
 	ret = nfs4_do_open_expired(ctx, state);
 	put_nfs_open_context(ctx);
 	return ret;
@@ -1880,10 +1937,8 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata,
 	if (ret != 0)
 		goto out;
 
-	if (read_seqcount_retry(&sp->so_reclaim_seqcount, seq)) {
+	if (read_seqcount_retry(&sp->so_reclaim_seqcount, seq))
 		nfs4_schedule_stateid_recovery(server, state);
-		nfs4_wait_clnt_recover(server->nfs_client);
-	}
 	*res = state;
 out:
 	return ret;
@@ -1905,6 +1960,7 @@ static int _nfs4_do_open(struct inode *dir,
 	struct nfs4_state     *state = NULL;
 	struct nfs_server       *server = NFS_SERVER(dir);
 	struct nfs4_opendata *opendata;
+	enum open_claim_type4 claim = NFS4_OPEN_CLAIM_NULL;
 	int status;
 
 	/* Protect against reboot recovery conflicts */
@@ -1920,7 +1976,10 @@ static int _nfs4_do_open(struct inode *dir,
 	if (dentry->d_inode != NULL)
 		nfs4_return_incompatible_delegation(dentry->d_inode, fmode);
 	status = -ENOMEM;
-	opendata = nfs4_opendata_alloc(dentry, sp, fmode, flags, sattr, GFP_KERNEL);
+	if (dentry->d_inode)
+		claim = NFS4_OPEN_CLAIM_FH;
+	opendata = nfs4_opendata_alloc(dentry, sp, fmode, flags, sattr,
+			claim, GFP_KERNEL);
 	if (opendata == NULL)
 		goto err_put_state_owner;
 
@@ -1978,6 +2037,7 @@ static struct nfs4_state *nfs4_do_open(struct inode *dir,
 					struct rpc_cred *cred,
 					struct nfs4_threshold **ctx_th)
 {
+	struct nfs_server *server = NFS_SERVER(dir);
 	struct nfs4_exception exception = { };
 	struct nfs4_state *res;
 	int status;
@@ -2021,7 +2081,9 @@ static struct nfs4_state *nfs4_do_open(struct inode *dir,
 			exception.retry = 1;
 			continue;
 		}
-		res = ERR_PTR(nfs4_handle_exception(NFS_SERVER(dir),
+		if (nfs4_clear_cap_atomic_open_v1(server, status, &exception))
+			continue;
+		res = ERR_PTR(nfs4_handle_exception(server,
 					status, &exception));
 	} while (exception.retry);
 	return res;
@@ -2053,7 +2115,7 @@ static int _nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred,
 
 	nfs_fattr_init(fattr);
 
-	if (state != NULL) {
+	if (state != NULL && nfs4_valid_open_stateid(state)) {
 		struct nfs_lockowner lockowner = {
 			.l_owner = current->files,
 			.l_pid = current->tgid,
@@ -2201,6 +2263,8 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
 			calldata->arg.fmode &= ~FMODE_WRITE;
 		}
 	}
+	if (!nfs4_valid_open_stateid(state))
+		call_close = 0;
 	spin_unlock(&state->owner->so_lock);
 
 	if (!call_close) {
@@ -2443,7 +2507,7 @@ static int nfs4_lookup_root_sec(struct nfs_server *server, struct nfs_fh *fhandl
 
 	auth = rpcauth_create(flavor, server->client);
 	if (IS_ERR(auth)) {
-		ret = -EIO;
+		ret = -EACCES;
 		goto out;
 	}
 	ret = nfs4_lookup_root(server, fhandle, info);
@@ -2451,27 +2515,36 @@ out:
 	return ret;
 }
 
+/*
+ * Retry pseudoroot lookup with various security flavors.  We do this when:
+ *
+ *   NFSv4.0: the PUTROOTFH operation returns NFS4ERR_WRONGSEC
+ *   NFSv4.1: the server does not support the SECINFO_NO_NAME operation
+ *
+ * Returns zero on success, or a negative NFS4ERR value, or a
+ * negative errno value.
+ */
 static int nfs4_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle,
 			      struct nfs_fsinfo *info)
 {
-	int i, len, status = 0;
-	rpc_authflavor_t flav_array[NFS_MAX_SECFLAVORS];
-
-	len = rpcauth_list_flavors(flav_array, ARRAY_SIZE(flav_array));
-	if (len < 0)
-		return len;
-
-	for (i = 0; i < len; i++) {
-		/* AUTH_UNIX is the default flavor if none was specified,
-		 * thus has already been tried. */
-		if (flav_array[i] == RPC_AUTH_UNIX)
-			continue;
+	/* Per 3530bis 15.33.5 */
+	static const rpc_authflavor_t flav_array[] = {
+		RPC_AUTH_GSS_KRB5P,
+		RPC_AUTH_GSS_KRB5I,
+		RPC_AUTH_GSS_KRB5,
+		RPC_AUTH_UNIX,			/* courtesy */
+		RPC_AUTH_NULL,
+	};
+	int status = -EPERM;
+	size_t i;
 
+	for (i = 0; i < ARRAY_SIZE(flav_array); i++) {
 		status = nfs4_lookup_root_sec(server, fhandle, info, flav_array[i]);
 		if (status == -NFS4ERR_WRONGSEC || status == -EACCES)
 			continue;
 		break;
 	}
+
 	/*
 	 * -EACCESS could mean that the user doesn't have correct permissions
 	 * to access the mount.  It could also mean that we tried to mount
@@ -2484,24 +2557,36 @@ static int nfs4_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle,
 	return status;
 }
 
-/*
- * get the file handle for the "/" directory on the server
+static int nfs4_do_find_root_sec(struct nfs_server *server,
+		struct nfs_fh *fhandle, struct nfs_fsinfo *info)
+{
+	int mv = server->nfs_client->cl_minorversion;
+	return nfs_v4_minor_ops[mv]->find_root_sec(server, fhandle, info);
+}
+
+/**
+ * nfs4_proc_get_rootfh - get file handle for server's pseudoroot
+ * @server: initialized nfs_server handle
+ * @fhandle: we fill in the pseudo-fs root file handle
+ * @info: we fill in an FSINFO struct
+ *
+ * Returns zero on success, or a negative errno.
  */
 int nfs4_proc_get_rootfh(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 = nfs_v4_minor_ops[minor_version]->find_root_sec(server, fhandle, info);
+	int status;
+
+	status = nfs4_lookup_root(server, fhandle, info);
+	if ((status == -NFS4ERR_WRONGSEC) &&
+	    !(server->flags & NFS_MOUNT_SECFLAVOUR))
+		status = nfs4_do_find_root_sec(server, fhandle, info);
+
 	if (status == 0)
 		status = nfs4_server_capabilities(server, fhandle);
 	if (status == 0)
 		status = nfs4_do_fsinfo(server, fhandle, info);
+
 	return nfs4_map_errors(status);
 }
 
@@ -3380,12 +3465,21 @@ static int _nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle,
 static int nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *fsinfo)
 {
 	struct nfs4_exception exception = { };
+	unsigned long now = jiffies;
 	int err;
 
 	do {
-		err = nfs4_handle_exception(server,
-				_nfs4_do_fsinfo(server, fhandle, fsinfo),
-				&exception);
+		err = _nfs4_do_fsinfo(server, fhandle, fsinfo);
+		if (err == 0) {
+			struct nfs_client *clp = server->nfs_client;
+
+			spin_lock(&clp->cl_lock);
+			clp->cl_lease_time = fsinfo->lease_time * HZ;
+			clp->cl_last_renewal = now;
+			spin_unlock(&clp->cl_lock);
+			break;
+		}
+		err = nfs4_handle_exception(server, err, &exception);
 	} while (exception.retry);
 	return err;
 }
@@ -3445,6 +3539,46 @@ static int nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
 	return err;
 }
 
+int nfs4_set_rw_stateid(nfs4_stateid *stateid,
+		const struct nfs_open_context *ctx,
+		const struct nfs_lock_context *l_ctx,
+		fmode_t fmode)
+{
+	const struct nfs_lockowner *lockowner = NULL;
+
+	if (l_ctx != NULL)
+		lockowner = &l_ctx->lockowner;
+	return nfs4_select_rw_stateid(stateid, ctx->state, fmode, lockowner);
+}
+EXPORT_SYMBOL_GPL(nfs4_set_rw_stateid);
+
+static bool nfs4_stateid_is_current(nfs4_stateid *stateid,
+		const struct nfs_open_context *ctx,
+		const struct nfs_lock_context *l_ctx,
+		fmode_t fmode)
+{
+	nfs4_stateid current_stateid;
+
+	if (nfs4_set_rw_stateid(&current_stateid, ctx, l_ctx, fmode))
+		return false;
+	return nfs4_stateid_match(stateid, &current_stateid);
+}
+
+static bool nfs4_error_stateid_expired(int err)
+{
+	switch (err) {
+	case -NFS4ERR_DELEG_REVOKED:
+	case -NFS4ERR_ADMIN_REVOKED:
+	case -NFS4ERR_BAD_STATEID:
+	case -NFS4ERR_STALE_STATEID:
+	case -NFS4ERR_OLD_STATEID:
+	case -NFS4ERR_OPENMODE:
+	case -NFS4ERR_EXPIRED:
+		return true;
+	}
+	return false;
+}
+
 void __nfs4_read_done_cb(struct nfs_read_data *data)
 {
 	nfs_invalidate_atime(data->header->inode);
@@ -3465,6 +3599,20 @@ static int nfs4_read_done_cb(struct rpc_task *task, struct nfs_read_data *data)
 	return 0;
 }
 
+static bool nfs4_read_stateid_changed(struct rpc_task *task,
+		struct nfs_readargs *args)
+{
+
+	if (!nfs4_error_stateid_expired(task->tk_status) ||
+		nfs4_stateid_is_current(&args->stateid,
+				args->context,
+				args->lock_context,
+				FMODE_READ))
+		return false;
+	rpc_restart_call_prepare(task);
+	return true;
+}
+
 static int nfs4_read_done(struct rpc_task *task, struct nfs_read_data *data)
 {
 
@@ -3472,7 +3620,8 @@ static int nfs4_read_done(struct rpc_task *task, struct nfs_read_data *data)
 
 	if (!nfs4_sequence_done(task, &data->res.seq_res))
 		return -EAGAIN;
-
+	if (nfs4_read_stateid_changed(task, &data->args))
+		return -EAGAIN;
 	return data->read_done_cb ? data->read_done_cb(task, data) :
 				    nfs4_read_done_cb(task, data);
 }
@@ -3487,10 +3636,13 @@ static void nfs4_proc_read_setup(struct nfs_read_data *data, struct rpc_message
 
 static void nfs4_proc_read_rpc_prepare(struct rpc_task *task, struct nfs_read_data *data)
 {
-	nfs4_setup_sequence(NFS_SERVER(data->header->inode),
+	if (nfs4_setup_sequence(NFS_SERVER(data->header->inode),
 			&data->args.seq_args,
 			&data->res.seq_res,
-			task);
+			task))
+		return;
+	nfs4_set_rw_stateid(&data->args.stateid, data->args.context,
+			data->args.lock_context, FMODE_READ);
 }
 
 static int nfs4_write_done_cb(struct rpc_task *task, struct nfs_write_data *data)
@@ -3508,10 +3660,26 @@ static int nfs4_write_done_cb(struct rpc_task *task, struct nfs_write_data *data
 	return 0;
 }
 
+static bool nfs4_write_stateid_changed(struct rpc_task *task,
+		struct nfs_writeargs *args)
+{
+
+	if (!nfs4_error_stateid_expired(task->tk_status) ||
+		nfs4_stateid_is_current(&args->stateid,
+				args->context,
+				args->lock_context,
+				FMODE_WRITE))
+		return false;
+	rpc_restart_call_prepare(task);
+	return true;
+}
+
 static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data)
 {
 	if (!nfs4_sequence_done(task, &data->res.seq_res))
 		return -EAGAIN;
+	if (nfs4_write_stateid_changed(task, &data->args))
+		return -EAGAIN;
 	return data->write_done_cb ? data->write_done_cb(task, data) :
 		nfs4_write_done_cb(task, data);
 }
@@ -3551,10 +3719,13 @@ static void nfs4_proc_write_setup(struct nfs_write_data *data, struct rpc_messag
 
 static void nfs4_proc_write_rpc_prepare(struct rpc_task *task, struct nfs_write_data *data)
 {
-	nfs4_setup_sequence(NFS_SERVER(data->header->inode),
+	if (nfs4_setup_sequence(NFS_SERVER(data->header->inode),
 			&data->args.seq_args,
 			&data->res.seq_res,
-			task);
+			task))
+		return;
+	nfs4_set_rw_stateid(&data->args.stateid, data->args.context,
+			data->args.lock_context, FMODE_WRITE);
 }
 
 static void nfs4_proc_commit_rpc_prepare(struct rpc_task *task, struct nfs_commit_data *data)
@@ -3980,11 +4151,14 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server,
 		case -NFS4ERR_OPENMODE:
 			if (state == NULL)
 				break;
-			nfs4_schedule_stateid_recovery(server, state);
+			if (nfs4_schedule_stateid_recovery(server, state) < 0)
+				goto stateid_invalid;
 			goto wait_on_recovery;
 		case -NFS4ERR_EXPIRED:
-			if (state != NULL)
-				nfs4_schedule_stateid_recovery(server, state);
+			if (state != NULL) {
+				if (nfs4_schedule_stateid_recovery(server, state) < 0)
+					goto stateid_invalid;
+			}
 		case -NFS4ERR_STALE_STATEID:
 		case -NFS4ERR_STALE_CLIENTID:
 			nfs4_schedule_lease_recovery(clp);
@@ -4016,6 +4190,9 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server,
 	}
 	task->tk_status = nfs4_map_errors(task->tk_status);
 	return 0;
+stateid_invalid:
+	task->tk_status = -EIO;
+	return 0;
 wait_on_recovery:
 	rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL);
 	if (test_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) == 0)
@@ -4143,27 +4320,17 @@ int nfs4_proc_setclientid_confirm(struct nfs_client *clp,
 		struct nfs4_setclientid_res *arg,
 		struct rpc_cred *cred)
 {
-	struct nfs_fsinfo fsinfo;
 	struct rpc_message msg = {
 		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETCLIENTID_CONFIRM],
 		.rpc_argp = arg,
-		.rpc_resp = &fsinfo,
 		.rpc_cred = cred,
 	};
-	unsigned long now;
 	int status;
 
 	dprintk("NFS call  setclientid_confirm auth=%s, (client ID %llx)\n",
 		clp->cl_rpcclient->cl_auth->au_ops->au_name,
 		clp->cl_clientid);
-	now = jiffies;
 	status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
-	if (status == 0) {
-		spin_lock(&clp->cl_lock);
-		clp->cl_lease_time = fsinfo.lease_time * HZ;
-		clp->cl_last_renewal = now;
-		spin_unlock(&clp->cl_lock);
-	}
 	dprintk("NFS reply setclientid_confirm: %d\n", status);
 	return status;
 }
@@ -4632,12 +4799,18 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata)
 		data->res.open_seqid = data->arg.open_seqid;
 	} else
 		data->arg.new_lock_owner = 0;
+	if (!nfs4_valid_open_stateid(state)) {
+		data->rpc_status = -EBADF;
+		task->tk_action = NULL;
+		goto out_release_open_seqid;
+	}
 	data->timestamp = jiffies;
 	if (nfs4_setup_sequence(data->server,
 				&data->arg.seq_args,
 				&data->res.seq_res,
 				task) == 0)
 		return;
+out_release_open_seqid:
 	nfs_release_seqid(data->arg.open_seqid);
 out_release_lock_seqid:
 	nfs_release_seqid(data->arg.lock_seqid);
@@ -4983,58 +5156,16 @@ nfs4_proc_lock(struct file *filp, int cmd, struct file_lock *request)
 	return status;
 }
 
-int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl)
+int nfs4_lock_delegation_recall(struct file_lock *fl, struct nfs4_state *state, const nfs4_stateid *stateid)
 {
 	struct nfs_server *server = NFS_SERVER(state->inode);
-	struct nfs4_exception exception = { };
 	int err;
 
 	err = nfs4_set_lock_state(state, fl);
 	if (err != 0)
-		goto out;
-	do {
-		err = _nfs4_do_setlk(state, F_SETLK, fl, NFS_LOCK_NEW);
-		switch (err) {
-			default:
-				printk(KERN_ERR "NFS: %s: unhandled error "
-					"%d.\n", __func__, err);
-			case 0:
-			case -ESTALE:
-				goto out;
-			case -NFS4ERR_STALE_CLIENTID:
-			case -NFS4ERR_STALE_STATEID:
-				set_bit(NFS_DELEGATED_STATE, &state->flags);
-			case -NFS4ERR_EXPIRED:
-				nfs4_schedule_lease_recovery(server->nfs_client);
-				err = -EAGAIN;
-				goto out;
-			case -NFS4ERR_BADSESSION:
-			case -NFS4ERR_BADSLOT:
-			case -NFS4ERR_BAD_HIGH_SLOT:
-			case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
-			case -NFS4ERR_DEADSESSION:
-				set_bit(NFS_DELEGATED_STATE, &state->flags);
-				nfs4_schedule_session_recovery(server->nfs_client->cl_session, err);
-				err = -EAGAIN;
-				goto out;
-			case -NFS4ERR_DELEG_REVOKED:
-			case -NFS4ERR_ADMIN_REVOKED:
-			case -NFS4ERR_BAD_STATEID:
-			case -NFS4ERR_OPENMODE:
-				nfs4_schedule_stateid_recovery(server, state);
-				err = 0;
-				goto out;
-			case -ENOMEM:
-			case -NFS4ERR_DENIED:
-				/* kill_proc(fl->fl_pid, SIGLOST, 1); */
-				err = 0;
-				goto out;
-		}
-		set_bit(NFS_DELEGATED_STATE, &state->flags);
-		err = nfs4_handle_exception(server, err, &exception);
-	} while (exception.retry);
-out:
-	return err;
+		return err;
+	err = _nfs4_do_setlk(state, F_SETLK, fl, NFS_LOCK_NEW);
+	return nfs4_handle_delegation_recall_error(server, state, stateid, err);
 }
 
 struct nfs_release_lockowner_data {
@@ -6725,6 +6856,10 @@ static const struct nfs4_state_maintenance_ops nfs41_state_renewal_ops = {
 
 static const struct nfs4_minor_version_ops nfs_v4_0_minor_ops = {
 	.minor_version = 0,
+	.init_caps = NFS_CAP_READDIRPLUS
+		| NFS_CAP_ATOMIC_OPEN
+		| NFS_CAP_CHANGE_ATTR
+		| NFS_CAP_POSIX_LOCK,
 	.call_sync = _nfs4_call_sync,
 	.match_stateid = nfs4_match_stateid,
 	.find_root_sec = nfs4_find_root_sec,
@@ -6736,6 +6871,12 @@ static const struct nfs4_minor_version_ops nfs_v4_0_minor_ops = {
 #if defined(CONFIG_NFS_V4_1)
 static const struct nfs4_minor_version_ops nfs_v4_1_minor_ops = {
 	.minor_version = 1,
+	.init_caps = NFS_CAP_READDIRPLUS
+		| NFS_CAP_ATOMIC_OPEN
+		| NFS_CAP_CHANGE_ATTR
+		| NFS_CAP_POSIX_LOCK
+		| NFS_CAP_STATEID_NFSV41
+		| NFS_CAP_ATOMIC_OPEN_V1,
 	.call_sync = nfs4_call_sync_sequence,
 	.match_stateid = nfs41_match_stateid,
 	.find_root_sec = nfs41_find_root_sec,
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 6ace365..9a22dd4 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -699,6 +699,8 @@ __nfs4_find_state_byowner(struct inode *inode, struct nfs4_state_owner *owner)
 	list_for_each_entry(state, &nfsi->open_states, inode_states) {
 		if (state->owner != owner)
 			continue;
+		if (!nfs4_valid_open_stateid(state))
+			continue;
 		if (atomic_inc_not_zero(&state->count))
 			return state;
 	}
@@ -987,13 +989,14 @@ int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl)
 	return 0;
 }
 
-static bool nfs4_copy_lock_stateid(nfs4_stateid *dst, struct nfs4_state *state,
+static int nfs4_copy_lock_stateid(nfs4_stateid *dst,
+		struct nfs4_state *state,
 		const struct nfs_lockowner *lockowner)
 {
 	struct nfs4_lock_state *lsp;
 	fl_owner_t fl_owner;
 	pid_t fl_pid;
-	bool ret = false;
+	int ret = -ENOENT;
 
 
 	if (lockowner == NULL)
@@ -1008,7 +1011,10 @@ static bool nfs4_copy_lock_stateid(nfs4_stateid *dst, struct nfs4_state *state,
 	lsp = __nfs4_find_lock_state(state, fl_owner, fl_pid, NFS4_ANY_LOCK_TYPE);
 	if (lsp != NULL && test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags) != 0) {
 		nfs4_stateid_copy(dst, &lsp->ls_stateid);
-		ret = true;
+		ret = 0;
+		smp_rmb();
+		if (!list_empty(&lsp->ls_seqid.list))
+			ret = -EWOULDBLOCK;
 	}
 	spin_unlock(&state->state_lock);
 	nfs4_put_lock_state(lsp);
@@ -1016,28 +1022,40 @@ out:
 	return ret;
 }
 
-static void nfs4_copy_open_stateid(nfs4_stateid *dst, struct nfs4_state *state)
+static int nfs4_copy_open_stateid(nfs4_stateid *dst, struct nfs4_state *state)
 {
+	int ret;
 	int seq;
 
 	do {
 		seq = read_seqbegin(&state->seqlock);
 		nfs4_stateid_copy(dst, &state->stateid);
+		ret = 0;
+		smp_rmb();
+		if (!list_empty(&state->owner->so_seqid.list))
+			ret = -EWOULDBLOCK;
 	} while (read_seqretry(&state->seqlock, seq));
+	return ret;
 }
 
 /*
  * Byte-range lock aware utility to initialize the stateid of read/write
  * requests.
  */
-void nfs4_select_rw_stateid(nfs4_stateid *dst, struct nfs4_state *state,
+int nfs4_select_rw_stateid(nfs4_stateid *dst, struct nfs4_state *state,
 		fmode_t fmode, const struct nfs_lockowner *lockowner)
 {
+	int ret = 0;
 	if (nfs4_copy_delegation_stateid(dst, state->inode, fmode))
-		return;
-	if (nfs4_copy_lock_stateid(dst, state, lockowner))
-		return;
-	nfs4_copy_open_stateid(dst, state);
+		goto out;
+	ret = nfs4_copy_lock_stateid(dst, state, lockowner);
+	if (ret != -ENOENT)
+		goto out;
+	ret = nfs4_copy_open_stateid(dst, state);
+out:
+	if (nfs_server_capable(state->inode, NFS_CAP_STATEID_NFSV41))
+		dst->seqid = 0;
+	return ret;
 }
 
 struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter, gfp_t gfp_mask)
@@ -1286,14 +1304,17 @@ static int nfs4_state_mark_reclaim_nograce(struct nfs_client *clp, struct nfs4_s
 	return 1;
 }
 
-void nfs4_schedule_stateid_recovery(const struct nfs_server *server, struct nfs4_state *state)
+int nfs4_schedule_stateid_recovery(const struct nfs_server *server, struct nfs4_state *state)
 {
 	struct nfs_client *clp = server->nfs_client;
 
+	if (!nfs4_valid_open_stateid(state))
+		return -EBADF;
 	nfs4_state_mark_reclaim_nograce(clp, state);
 	dprintk("%s: scheduling stateid recovery for server %s\n", __func__,
 			clp->cl_hostname);
 	nfs4_schedule_state_manager(clp);
+	return 0;
 }
 EXPORT_SYMBOL_GPL(nfs4_schedule_stateid_recovery);
 
@@ -1323,6 +1344,27 @@ void nfs_inode_find_state_and_recover(struct inode *inode,
 		nfs4_schedule_state_manager(clp);
 }
 
+static void nfs4_state_mark_open_context_bad(struct nfs4_state *state)
+{
+	struct inode *inode = state->inode;
+	struct nfs_inode *nfsi = NFS_I(inode);
+	struct nfs_open_context *ctx;
+
+	spin_lock(&inode->i_lock);
+	list_for_each_entry(ctx, &nfsi->open_files, list) {
+		if (ctx->state != state)
+			continue;
+		set_bit(NFS_CONTEXT_BAD, &ctx->flags);
+	}
+	spin_unlock(&inode->i_lock);
+}
+
+static void nfs4_state_mark_recovery_failed(struct nfs4_state *state, int error)
+{
+	set_bit(NFS_STATE_RECOVERY_FAILED, &state->flags);
+	nfs4_state_mark_open_context_bad(state);
+}
+
 
 static int nfs4_reclaim_locks(struct nfs4_state *state, const struct nfs4_state_recovery_ops *ops)
 {
@@ -1398,6 +1440,8 @@ restart:
 	list_for_each_entry(state, &sp->so_states, open_states) {
 		if (!test_and_clear_bit(ops->state_flag_bit, &state->flags))
 			continue;
+		if (!nfs4_valid_open_stateid(state))
+			continue;
 		if (state->state == 0)
 			continue;
 		atomic_inc(&state->count);
@@ -1430,11 +1474,10 @@ restart:
 				 * Open state on this file cannot be recovered
 				 * All we can do is revert to using the zero stateid.
 				 */
-				memset(&state->stateid, 0,
-					sizeof(state->stateid));
-				/* Mark the file as being 'closed' */
-				state->state = 0;
+				nfs4_state_mark_recovery_failed(state, status);
 				break;
+			case -EAGAIN:
+				ssleep(1);
 			case -NFS4ERR_ADMIN_REVOKED:
 			case -NFS4ERR_STALE_STATEID:
 			case -NFS4ERR_BAD_STATEID:
@@ -1823,26 +1866,13 @@ int nfs4_discover_server_trunking(struct nfs_client *clp,
 {
 	const struct nfs4_state_recovery_ops *ops =
 				clp->cl_mvops->reboot_recovery_ops;
-	rpc_authflavor_t *flavors, flav, save;
 	struct rpc_clnt *clnt;
 	struct rpc_cred *cred;
-	int i, len, status;
+	int i, status;
 
 	dprintk("NFS: %s: testing '%s'\n", __func__, clp->cl_hostname);
 
-	len = NFS_MAX_SECFLAVORS;
-	flavors = kcalloc(len, sizeof(*flavors), GFP_KERNEL);
-	if (flavors == NULL) {
-		status = -ENOMEM;
-		goto out;
-	}
-	len = rpcauth_list_flavors(flavors, len);
-	if (len < 0) {
-		status = len;
-		goto out_free;
-	}
 	clnt = clp->cl_rpcclient;
-	save = clnt->cl_auth->au_flavor;
 	i = 0;
 
 	mutex_lock(&nfs_clid_init_mutex);
@@ -1857,12 +1887,6 @@ again:
 	switch (status) {
 	case 0:
 		break;
-
-	case -EACCES:
-		if (clp->cl_machine_cred == NULL)
-			break;
-		/* Handle case where the user hasn't set up machine creds */
-		nfs4_clear_machine_cred(clp);
 	case -NFS4ERR_DELAY:
 	case -ETIMEDOUT:
 	case -EAGAIN:
@@ -1871,22 +1895,23 @@ again:
 		dprintk("NFS: %s after status %d, retrying\n",
 			__func__, status);
 		goto again;
-
+	case -EACCES:
+		if (i++)
+			break;
 	case -NFS4ERR_CLID_INUSE:
 	case -NFS4ERR_WRONGSEC:
-		status = -EPERM;
-		if (i >= len)
-			break;
-
-		flav = flavors[i++];
-		if (flav == save)
-			flav = flavors[i++];
-		clnt = rpc_clone_client_set_auth(clnt, flav);
+		clnt = rpc_clone_client_set_auth(clnt, RPC_AUTH_NULL);
 		if (IS_ERR(clnt)) {
 			status = PTR_ERR(clnt);
 			break;
 		}
-		clp->cl_rpcclient = clnt;
+		/* Note: this is safe because we haven't yet marked the
+		 * client as ready, so we are the only user of
+		 * clp->cl_rpcclient
+		 */
+		clnt = xchg(&clp->cl_rpcclient, clnt);
+		rpc_shutdown_client(clnt);
+		clnt = clp->cl_rpcclient;
 		goto again;
 
 	case -NFS4ERR_MINOR_VERS_MISMATCH:
@@ -1901,9 +1926,6 @@ again:
 
 out_unlock:
 	mutex_unlock(&nfs_clid_init_mutex);
-out_free:
-	kfree(flavors);
-out:
 	dprintk("NFS: %s: status = %d\n", __func__, status);
 	return status;
 }
diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c
index 569b166..a5e1a30 100644
--- a/fs/nfs/nfs4super.c
+++ b/fs/nfs/nfs4super.c
@@ -252,6 +252,8 @@ struct dentry *nfs4_try_mount(int flags, const char *dev_name,
 
 	dfprintk(MOUNT, "--> nfs4_try_mount()\n");
 
+	if (data->auth_flavors[0] == RPC_AUTH_MAXFLAVOR)
+		data->auth_flavors[0] = RPC_AUTH_UNIX;
 	export_path = data->nfs_server.export_path;
 	data->nfs_server.export_path = "/";
 	root_mnt = nfs_do_root_mount(&nfs4_remote_fs_type, flags, mount_info,
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index e3edda5..ae0190b 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -530,14 +530,10 @@ static int nfs4_stat_to_errno(int);
 				decode_setclientid_maxsz)
 #define NFS4_enc_setclientid_confirm_sz \
 				(compound_encode_hdr_maxsz + \
-				encode_setclientid_confirm_maxsz + \
-				encode_putrootfh_maxsz + \
-				encode_fsinfo_maxsz)
+				encode_setclientid_confirm_maxsz)
 #define NFS4_dec_setclientid_confirm_sz \
 				(compound_decode_hdr_maxsz + \
-				decode_setclientid_confirm_maxsz + \
-				decode_putrootfh_maxsz + \
-				decode_fsinfo_maxsz)
+				decode_setclientid_confirm_maxsz)
 #define NFS4_enc_lock_sz        (compound_encode_hdr_maxsz + \
 				encode_sequence_maxsz + \
 				encode_putfh_maxsz + \
@@ -1459,6 +1455,23 @@ static inline void encode_claim_delegate_cur(struct xdr_stream *xdr, const struc
 	encode_string(xdr, name->len, name->name);
 }
 
+static inline void encode_claim_fh(struct xdr_stream *xdr)
+{
+	__be32 *p;
+
+	p = reserve_space(xdr, 4);
+	*p = cpu_to_be32(NFS4_OPEN_CLAIM_FH);
+}
+
+static inline void encode_claim_delegate_cur_fh(struct xdr_stream *xdr, const nfs4_stateid *stateid)
+{
+	__be32 *p;
+
+	p = reserve_space(xdr, 4);
+	*p = cpu_to_be32(NFS4_OPEN_CLAIM_DELEG_CUR_FH);
+	encode_nfs4_stateid(xdr, stateid);
+}
+
 static void encode_open(struct xdr_stream *xdr, const struct nfs_openargs *arg, struct compound_hdr *hdr)
 {
 	encode_op_hdr(xdr, OP_OPEN, decode_open_maxsz, hdr);
@@ -1474,6 +1487,12 @@ static void encode_open(struct xdr_stream *xdr, const struct nfs_openargs *arg,
 	case NFS4_OPEN_CLAIM_DELEGATE_CUR:
 		encode_claim_delegate_cur(xdr, arg->name, &arg->u.delegation);
 		break;
+	case NFS4_OPEN_CLAIM_FH:
+		encode_claim_fh(xdr);
+		break;
+	case NFS4_OPEN_CLAIM_DELEG_CUR_FH:
+		encode_claim_delegate_cur_fh(xdr, &arg->u.delegation);
+		break;
 	default:
 		BUG();
 	}
@@ -1506,35 +1525,12 @@ static void encode_putrootfh(struct xdr_stream *xdr, struct compound_hdr *hdr)
 	encode_op_hdr(xdr, OP_PUTROOTFH, decode_putrootfh_maxsz, hdr);
 }
 
-static void encode_open_stateid(struct xdr_stream *xdr,
-		const struct nfs_open_context *ctx,
-		const struct nfs_lock_context *l_ctx,
-		fmode_t fmode,
-		int zero_seqid)
-{
-	nfs4_stateid stateid;
-
-	if (ctx->state != NULL) {
-		const struct nfs_lockowner *lockowner = NULL;
-
-		if (l_ctx != NULL)
-			lockowner = &l_ctx->lockowner;
-		nfs4_select_rw_stateid(&stateid, ctx->state,
-				fmode, lockowner);
-		if (zero_seqid)
-			stateid.seqid = 0;
-		encode_nfs4_stateid(xdr, &stateid);
-	} else
-		encode_nfs4_stateid(xdr, &zero_stateid);
-}
-
 static void encode_read(struct xdr_stream *xdr, const struct nfs_readargs *args, struct compound_hdr *hdr)
 {
 	__be32 *p;
 
 	encode_op_hdr(xdr, OP_READ, decode_read_maxsz, hdr);
-	encode_open_stateid(xdr, args->context, args->lock_context,
-			FMODE_READ, hdr->minorversion);
+	encode_nfs4_stateid(xdr, &args->stateid);
 
 	p = reserve_space(xdr, 12);
 	p = xdr_encode_hyper(p, args->offset);
@@ -1670,8 +1666,7 @@ static void encode_write(struct xdr_stream *xdr, const struct nfs_writeargs *arg
 	__be32 *p;
 
 	encode_op_hdr(xdr, OP_WRITE, decode_write_maxsz, hdr);
-	encode_open_stateid(xdr, args->context, args->lock_context,
-			FMODE_WRITE, hdr->minorversion);
+	encode_nfs4_stateid(xdr, &args->stateid);
 
 	p = reserve_space(xdr, 16);
 	p = xdr_encode_hyper(p, args->offset);
@@ -2609,12 +2604,9 @@ static void nfs4_xdr_enc_setclientid_confirm(struct rpc_rqst *req,
 	struct compound_hdr hdr = {
 		.nops	= 0,
 	};
-	const u32 lease_bitmap[3] = { FATTR4_WORD0_LEASE_TIME };
 
 	encode_compound_hdr(xdr, req, &hdr);
 	encode_setclientid_confirm(xdr, arg, &hdr);
-	encode_putrootfh(xdr, &hdr);
-	encode_fsinfo(xdr, lease_bitmap, &hdr);
 	encode_nops(&hdr);
 }
 
@@ -3497,8 +3489,11 @@ static int decode_pathname(struct xdr_stream *xdr, struct nfs4_pathname *path)
 	if (n == 0)
 		goto root_path;
 	dprintk("pathname4: ");
-	path->ncomponents = 0;
-	while (path->ncomponents < n) {
+	if (n > NFS4_PATHNAME_MAXCOMPONENTS) {
+		dprintk("cannot parse %d components in path\n", n);
+		goto out_eio;
+	}
+	for (path->ncomponents = 0; path->ncomponents < n; path->ncomponents++) {
 		struct nfs4_string *component = &path->components[path->ncomponents];
 		status = decode_opaque_inline(xdr, &component->len, &component->data);
 		if (unlikely(status != 0))
@@ -3507,12 +3502,6 @@ static int decode_pathname(struct xdr_stream *xdr, struct nfs4_pathname *path)
 			pr_cont("%s%.*s ",
 				(path->ncomponents != n ? "/ " : ""),
 				component->len, component->data);
-		if (path->ncomponents < NFS4_PATHNAME_MAXCOMPONENTS)
-			path->ncomponents++;
-		else {
-			dprintk("cannot parse %d components in path\n", n);
-			goto out_eio;
-		}
 	}
 out:
 	return status;
@@ -3557,27 +3546,23 @@ static int decode_attr_fs_locations(struct xdr_stream *xdr, uint32_t *bitmap, st
 	n = be32_to_cpup(p);
 	if (n <= 0)
 		goto out_eio;
-	res->nlocations = 0;
-	while (res->nlocations < n) {
+	for (res->nlocations = 0; res->nlocations < n; res->nlocations++) {
 		u32 m;
-		struct nfs4_fs_location *loc = &res->locations[res->nlocations];
+		struct nfs4_fs_location *loc;
 
+		if (res->nlocations == NFS4_FS_LOCATIONS_MAXENTRIES)
+			break;
+		loc = &res->locations[res->nlocations];
 		p = xdr_inline_decode(xdr, 4);
 		if (unlikely(!p))
 			goto out_overflow;
 		m = be32_to_cpup(p);
 
-		loc->nservers = 0;
 		dprintk("%s: servers:\n", __func__);
-		while (loc->nservers < m) {
-			struct nfs4_string *server = &loc->servers[loc->nservers];
-			status = decode_opaque_inline(xdr, &server->len, &server->data);
-			if (unlikely(status != 0))
-				goto out_eio;
-			dprintk("%s ", server->data);
-			if (loc->nservers < NFS4_FS_LOCATION_MAXSERVERS)
-				loc->nservers++;
-			else {
+		for (loc->nservers = 0; loc->nservers < m; loc->nservers++) {
+			struct nfs4_string *server;
+
+			if (loc->nservers == NFS4_FS_LOCATION_MAXSERVERS) {
 				unsigned int i;
 				dprintk("%s: using first %u of %u servers "
 					"returned for location %u\n",
@@ -3591,13 +3576,17 @@ static int decode_attr_fs_locations(struct xdr_stream *xdr, uint32_t *bitmap, st
 					if (unlikely(status != 0))
 						goto out_eio;
 				}
+				break;
 			}
+			server = &loc->servers[loc->nservers];
+			status = decode_opaque_inline(xdr, &server->len, &server->data);
+			if (unlikely(status != 0))
+				goto out_eio;
+			dprintk("%s ", server->data);
 		}
 		status = decode_pathname(xdr, &loc->rootpath);
 		if (unlikely(status != 0))
 			goto out_eio;
-		if (res->nlocations < NFS4_FS_LOCATIONS_MAXENTRIES)
-			res->nlocations++;
 	}
 	if (res->nlocations != 0)
 		status = NFS_ATTR_FATTR_V4_LOCATIONS;
@@ -5209,27 +5198,30 @@ static int decode_delegreturn(struct xdr_stream *xdr)
 	return decode_op_hdr(xdr, OP_DELEGRETURN);
 }
 
-static int decode_secinfo_gss(struct xdr_stream *xdr, struct nfs4_secinfo_flavor *flavor)
+static int decode_secinfo_gss(struct xdr_stream *xdr,
+			      struct nfs4_secinfo4 *flavor)
 {
+	u32 oid_len;
 	__be32 *p;
 
 	p = xdr_inline_decode(xdr, 4);
 	if (unlikely(!p))
 		goto out_overflow;
-	flavor->gss.sec_oid4.len = be32_to_cpup(p);
-	if (flavor->gss.sec_oid4.len > GSS_OID_MAX_LEN)
+	oid_len = be32_to_cpup(p);
+	if (oid_len > GSS_OID_MAX_LEN)
 		goto out_err;
 
-	p = xdr_inline_decode(xdr, flavor->gss.sec_oid4.len);
+	p = xdr_inline_decode(xdr, oid_len);
 	if (unlikely(!p))
 		goto out_overflow;
-	memcpy(flavor->gss.sec_oid4.data, p, flavor->gss.sec_oid4.len);
+	memcpy(flavor->flavor_info.oid.data, p, oid_len);
+	flavor->flavor_info.oid.len = oid_len;
 
 	p = xdr_inline_decode(xdr, 8);
 	if (unlikely(!p))
 		goto out_overflow;
-	flavor->gss.qop4 = be32_to_cpup(p++);
-	flavor->gss.service = be32_to_cpup(p);
+	flavor->flavor_info.qop = be32_to_cpup(p++);
+	flavor->flavor_info.service = be32_to_cpup(p);
 
 	return 0;
 
@@ -5242,10 +5234,10 @@ out_err:
 
 static int decode_secinfo_common(struct xdr_stream *xdr, struct nfs4_secinfo_res *res)
 {
-	struct nfs4_secinfo_flavor *sec_flavor;
+	struct nfs4_secinfo4 *sec_flavor;
+	unsigned int i, num_flavors;
 	int status;
 	__be32 *p;
-	int i, num_flavors;
 
 	p = xdr_inline_decode(xdr, 4);
 	if (unlikely(!p))
@@ -6648,8 +6640,7 @@ static int nfs4_xdr_dec_setclientid(struct rpc_rqst *req,
  * Decode SETCLIENTID_CONFIRM response
  */
 static int nfs4_xdr_dec_setclientid_confirm(struct rpc_rqst *req,
-					    struct xdr_stream *xdr,
-					    struct nfs_fsinfo *fsinfo)
+					    struct xdr_stream *xdr)
 {
 	struct compound_hdr hdr;
 	int status;
@@ -6657,10 +6648,6 @@ static int nfs4_xdr_dec_setclientid_confirm(struct rpc_rqst *req,
 	status = decode_compound_hdr(xdr, &hdr);
 	if (!status)
 		status = decode_setclientid_confirm(xdr);
-	if (!status)
-		status = decode_putrootfh(xdr);
-	if (!status)
-		status = decode_fsinfo(xdr, fsinfo);
 	return status;
 }
 
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c
index e56e846..7f09330 100644
--- a/fs/nfs/pagelist.c
+++ b/fs/nfs/pagelist.c
@@ -104,6 +104,8 @@ nfs_create_request(struct nfs_open_context *ctx, struct inode *inode,
 	struct nfs_page		*req;
 	struct nfs_lock_context *l_ctx;
 
+	if (test_bit(NFS_CONTEXT_BAD, &ctx->flags))
+		return ERR_PTR(-EBADF);
 	/* try to allocate the request struct */
 	req = nfs_page_alloc();
 	if (req == NULL)
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 4bdffe0..c5bd758e 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -718,6 +718,8 @@ pnfs_choose_layoutget_stateid(nfs4_stateid *dst, struct pnfs_layout_hdr *lo,
 	spin_lock(&lo->plh_inode->i_lock);
 	if (pnfs_layoutgets_blocked(lo, 1)) {
 		status = -EAGAIN;
+	} else if (!nfs4_valid_open_stateid(open_state)) {
+		status = -EBADF;
 	} else if (list_empty(&lo->plh_segs)) {
 		int seq;
 
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index a5e5d98..70a26c6 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -514,6 +514,8 @@ void nfs_read_prepare(struct rpc_task *task, void *calldata)
 {
 	struct nfs_read_data *data = calldata;
 	NFS_PROTO(data->header->inode)->read_rpc_prepare(task, data);
+	if (unlikely(test_bit(NFS_CONTEXT_BAD, &data->args.context->flags)))
+		rpc_exit(task, -EIO);
 }
 
 static const struct rpc_call_ops nfs_read_common_ops = {
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 2f8a29d..1bb071d 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -920,7 +920,7 @@ static struct nfs_parsed_mount_data *nfs_alloc_parsed_mount_data(void)
 		data->mount_server.port	= NFS_UNSPEC_PORT;
 		data->nfs_server.port	= NFS_UNSPEC_PORT;
 		data->nfs_server.protocol = XPRT_TRANSPORT_TCP;
-		data->auth_flavors[0]	= RPC_AUTH_UNIX;
+		data->auth_flavors[0]	= RPC_AUTH_MAXFLAVOR;
 		data->auth_flavor_len	= 1;
 		data->minorversion	= 0;
 		data->need_mount	= true;
@@ -1608,49 +1608,57 @@ out_security_failure:
 }
 
 /*
- * Match the requested auth flavors with the list returned by
- * the server.  Returns zero and sets the mount's authentication
- * flavor on success; returns -EACCES if server does not support
- * the requested flavor.
+ * Select a security flavor for this mount.  The selected flavor
+ * is planted in args->auth_flavors[0].
  */
-static int nfs_walk_authlist(struct nfs_parsed_mount_data *args,
-			     struct nfs_mount_request *request)
+static void nfs_select_flavor(struct nfs_parsed_mount_data *args,
+			      struct nfs_mount_request *request)
 {
-	unsigned int i, j, server_authlist_len = *(request->auth_flav_len);
+	unsigned int i, count = *(request->auth_flav_len);
+	rpc_authflavor_t flavor;
+
+	if (args->auth_flavors[0] != RPC_AUTH_MAXFLAVOR)
+		goto out;
+
+	/*
+	 * The NFSv2 MNT operation does not return a flavor list.
+	 */
+	if (args->mount_server.version != NFS_MNT3_VERSION)
+		goto out_default;
 
 	/*
 	 * Certain releases of Linux's mountd return an empty
-	 * flavor list.  To prevent behavioral regression with
-	 * these servers (ie. rejecting mounts that used to
-	 * succeed), revert to pre-2.6.32 behavior (no checking)
-	 * if the returned flavor list is empty.
+	 * flavor list in some cases.
 	 */
-	if (server_authlist_len == 0)
-		return 0;
+	if (count == 0)
+		goto out_default;
 
 	/*
-	 * We avoid sophisticated negotiating here, as there are
-	 * plenty of cases where we can get it wrong, providing
-	 * either too little or too much security.
-	 *
 	 * RFC 2623, section 2.7 suggests we SHOULD prefer the
 	 * flavor listed first.  However, some servers list
-	 * AUTH_NULL first.  Our caller plants AUTH_SYS, the
-	 * preferred default, in args->auth_flavors[0] if user
-	 * didn't specify sec= mount option.
+	 * AUTH_NULL first.  Avoid ever choosing AUTH_NULL.
 	 */
-	for (i = 0; i < args->auth_flavor_len; i++)
-		for (j = 0; j < server_authlist_len; j++)
-			if (args->auth_flavors[i] == request->auth_flavs[j]) {
-				dfprintk(MOUNT, "NFS: using auth flavor %d\n",
-					request->auth_flavs[j]);
-				args->auth_flavors[0] = request->auth_flavs[j];
-				return 0;
-			}
+	for (i = 0; i < count; i++) {
+		struct rpcsec_gss_info info;
+
+		flavor = request->auth_flavs[i];
+		switch (flavor) {
+		case RPC_AUTH_UNIX:
+			goto out_set;
+		case RPC_AUTH_NULL:
+			continue;
+		default:
+			if (rpcauth_get_gssinfo(flavor, &info) == 0)
+				goto out_set;
+		}
+	}
 
-	dfprintk(MOUNT, "NFS: server does not support requested auth flavor\n");
-	nfs_umount(request);
-	return -EACCES;
+out_default:
+	flavor = RPC_AUTH_UNIX;
+out_set:
+	args->auth_flavors[0] = flavor;
+out:
+	dfprintk(MOUNT, "NFS: using auth flavor %d\n", args->auth_flavors[0]);
 }
 
 /*
@@ -1713,12 +1721,8 @@ static int nfs_request_mount(struct nfs_parsed_mount_data *args,
 		return status;
 	}
 
-	/*
-	 * MNTv1 (NFSv2) does not support auth flavor negotiation.
-	 */
-	if (args->mount_server.version != NFS_MNT3_VERSION)
-		return 0;
-	return nfs_walk_authlist(args, &request);
+	nfs_select_flavor(args, &request);
+	return 0;
 }
 
 struct dentry *nfs_try_mount(int flags, const char *dev_name,
@@ -2381,10 +2385,9 @@ int nfs_clone_sb_security(struct super_block *s, struct dentry *mntroot,
 			  struct nfs_mount_info *mount_info)
 {
 	/* clone any lsm security options from the parent to the new sb */
-	security_sb_clone_mnt_opts(mount_info->cloned->sb, s);
 	if (mntroot->d_inode->i_op != NFS_SB(s)->nfs_client->rpc_ops->dir_inode_ops)
 		return -ESTALE;
-	return 0;
+	return security_sb_clone_mnt_opts(mount_info->cloned->sb, s);
 }
 EXPORT_SYMBOL_GPL(nfs_clone_sb_security);
 
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index c483cc5..a2c7c28 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -1251,6 +1251,8 @@ void nfs_write_prepare(struct rpc_task *task, void *calldata)
 {
 	struct nfs_write_data *data = calldata;
 	NFS_PROTO(data->header->inode)->write_rpc_prepare(task, data);
+	if (unlikely(test_bit(NFS_CONTEXT_BAD, &data->args.context->flags)))
+		rpc_exit(task, -EIO);
 }
 
 void nfs_commit_prepare(struct rpc_task *task, void *calldata)
diff --git a/fs/nfsd/cache.h b/fs/nfsd/cache.h
index 87fd141..d5c5b3e 100644
--- a/fs/nfsd/cache.h
+++ b/fs/nfsd/cache.h
@@ -82,6 +82,7 @@ int	nfsd_reply_cache_init(void);
 void	nfsd_reply_cache_shutdown(void);
 int	nfsd_cache_lookup(struct svc_rqst *);
 void	nfsd_cache_update(struct svc_rqst *, int, __be32 *);
+int	nfsd_reply_cache_stats_open(struct inode *, struct file *);
 
 #ifdef CONFIG_NFSD_V4
 void	nfsd4_set_statp(struct svc_rqst *rqstp, __be32 *statp);
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index ae73175..a9b707b 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -351,6 +351,10 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 	}
 	if (status)
 		goto out;
+	if (open->op_xdr_error) {
+		status = open->op_xdr_error;
+		goto out;
+	}
 
 	status = nfsd4_check_open_attributes(rqstp, cstate, open);
 	if (status)
@@ -417,6 +421,24 @@ out:
 }
 
 /*
+ * OPEN is the only seqid-mutating operation whose decoding can fail
+ * with a seqid-mutating error (specifically, decoding of user names in
+ * the attributes).  Therefore we have to do some processing to look up
+ * the stateowner so that we can bump the seqid.
+ */
+static __be32 nfsd4_open_omfg(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct nfsd4_op *op)
+{
+	struct nfsd4_open *open = (struct nfsd4_open *)&op->u;
+
+	if (!seqid_mutating_err(ntohl(op->status)))
+		return op->status;
+	if (nfsd4_has_session(cstate))
+		return op->status;
+	open->op_xdr_error = op->status;
+	return nfsd4_open(rqstp, cstate, open);
+}
+
+/*
  * filehandle-manipulating ops.
  */
 static __be32
@@ -931,14 +953,14 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 	nfs4_lock_state();
 	status = nfs4_preprocess_stateid_op(SVC_NET(rqstp),
 					cstate, stateid, WR_STATE, &filp);
-	if (filp)
-		get_file(filp);
-	nfs4_unlock_state();
-
 	if (status) {
+		nfs4_unlock_state();
 		dprintk("NFSD: nfsd4_write: couldn't process stateid!\n");
 		return status;
 	}
+	if (filp)
+		get_file(filp);
+	nfs4_unlock_state();
 
 	cnt = write->wr_buflen;
 	write->wr_how_written = write->wr_stable_how;
@@ -1244,8 +1266,11 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
 		 * for example, if there is a miscellaneous XDR error
 		 * it will be set to nfserr_bad_xdr.
 		 */
-		if (op->status)
+		if (op->status) {
+			if (op->opnum == OP_OPEN)
+				op->status = nfsd4_open_omfg(rqstp, cstate, op);
 			goto encode_op;
+		}
 
 		/* We must be able to encode a successful response to
 		 * this operation, with enough room left over to encode a
@@ -1282,12 +1307,9 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
 		if (op->status)
 			goto encode_op;
 
-		if (opdesc->op_func) {
-			if (opdesc->op_get_currentstateid)
-				opdesc->op_get_currentstateid(cstate, &op->u);
-			op->status = opdesc->op_func(rqstp, cstate, &op->u);
-		} else
-			BUG_ON(op->status == nfs_ok);
+		if (opdesc->op_get_currentstateid)
+			opdesc->op_get_currentstateid(cstate, &op->u);
+		op->status = opdesc->op_func(rqstp, cstate, &op->u);
 
 		if (!op->status) {
 			if (opdesc->op_set_currentstateid)
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 2e27430..7293e29 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -94,17 +94,32 @@ nfs4_lock_state(void)
 	mutex_lock(&client_mutex);
 }
 
-static void free_session(struct kref *);
+static void free_session(struct nfsd4_session *);
 
-/* Must be called under the client_lock */
-static void nfsd4_put_session_locked(struct nfsd4_session *ses)
+void nfsd4_put_session(struct nfsd4_session *ses)
+{
+	atomic_dec(&ses->se_ref);
+}
+
+static bool is_session_dead(struct nfsd4_session *ses)
 {
-	kref_put(&ses->se_ref, free_session);
+	return ses->se_flags & NFS4_SESSION_DEAD;
 }
 
-static void nfsd4_get_session(struct nfsd4_session *ses)
+static __be32 mark_session_dead_locked(struct nfsd4_session *ses)
 {
-	kref_get(&ses->se_ref);
+	if (atomic_read(&ses->se_ref))
+		return nfserr_jukebox;
+	ses->se_flags |= NFS4_SESSION_DEAD;
+	return nfs_ok;
+}
+
+static __be32 nfsd4_get_session_locked(struct nfsd4_session *ses)
+{
+	if (is_session_dead(ses))
+		return nfserr_badsession;
+	atomic_inc(&ses->se_ref);
+	return nfs_ok;
 }
 
 void
@@ -113,6 +128,90 @@ nfs4_unlock_state(void)
 	mutex_unlock(&client_mutex);
 }
 
+static bool is_client_expired(struct nfs4_client *clp)
+{
+	return clp->cl_time == 0;
+}
+
+static __be32 mark_client_expired_locked(struct nfs4_client *clp)
+{
+	if (atomic_read(&clp->cl_refcount))
+		return nfserr_jukebox;
+	clp->cl_time = 0;
+	return nfs_ok;
+}
+
+static __be32 mark_client_expired(struct nfs4_client *clp)
+{
+	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
+	__be32 ret;
+
+	spin_lock(&nn->client_lock);
+	ret = mark_client_expired_locked(clp);
+	spin_unlock(&nn->client_lock);
+	return ret;
+}
+
+static __be32 get_client_locked(struct nfs4_client *clp)
+{
+	if (is_client_expired(clp))
+		return nfserr_expired;
+	atomic_inc(&clp->cl_refcount);
+	return nfs_ok;
+}
+
+/* must be called under the client_lock */
+static inline void
+renew_client_locked(struct nfs4_client *clp)
+{
+	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
+
+	if (is_client_expired(clp)) {
+		WARN_ON(1);
+		printk("%s: client (clientid %08x/%08x) already expired\n",
+			__func__,
+			clp->cl_clientid.cl_boot,
+			clp->cl_clientid.cl_id);
+		return;
+	}
+
+	dprintk("renewing client (clientid %08x/%08x)\n",
+			clp->cl_clientid.cl_boot,
+			clp->cl_clientid.cl_id);
+	list_move_tail(&clp->cl_lru, &nn->client_lru);
+	clp->cl_time = get_seconds();
+}
+
+static inline void
+renew_client(struct nfs4_client *clp)
+{
+	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
+
+	spin_lock(&nn->client_lock);
+	renew_client_locked(clp);
+	spin_unlock(&nn->client_lock);
+}
+
+void put_client_renew_locked(struct nfs4_client *clp)
+{
+	if (!atomic_dec_and_test(&clp->cl_refcount))
+		return;
+	if (!is_client_expired(clp))
+		renew_client_locked(clp);
+}
+
+void put_client_renew(struct nfs4_client *clp)
+{
+	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
+
+	if (!atomic_dec_and_lock(&clp->cl_refcount, &nn->client_lock))
+		return;
+	if (!is_client_expired(clp))
+		renew_client_locked(clp);
+	spin_unlock(&nn->client_lock);
+}
+
+
 static inline u32
 opaque_hashval(const void *ptr, int nbytes)
 {
@@ -137,7 +236,7 @@ static inline void
 put_nfs4_file(struct nfs4_file *fi)
 {
 	if (atomic_dec_and_lock(&fi->fi_ref, &recall_lock)) {
-		list_del(&fi->fi_hash);
+		hlist_del(&fi->fi_hash);
 		spin_unlock(&recall_lock);
 		iput(fi->fi_inode);
 		nfsd4_free_file(fi);
@@ -181,7 +280,7 @@ static unsigned int file_hashval(struct inode *ino)
 	return hash_ptr(ino, FILE_HASH_BITS);
 }
 
-static struct list_head file_hashtbl[FILE_HASH_SIZE];
+static struct hlist_head file_hashtbl[FILE_HASH_SIZE];
 
 static void __nfs4_file_get_access(struct nfs4_file *fp, int oflag)
 {
@@ -761,8 +860,8 @@ static void nfsd4_conn_lost(struct svc_xpt_user *u)
 		list_del(&c->cn_persession);
 		free_conn(c);
 	}
-	spin_unlock(&clp->cl_lock);
 	nfsd4_probe_callback(clp);
+	spin_unlock(&clp->cl_lock);
 }
 
 static struct nfsd4_conn *alloc_conn(struct svc_rqst *rqstp, u32 flags)
@@ -851,28 +950,15 @@ static void __free_session(struct nfsd4_session *ses)
 	kfree(ses);
 }
 
-static void free_session(struct kref *kref)
+static void free_session(struct nfsd4_session *ses)
 {
-	struct nfsd4_session *ses;
-	struct nfsd_net *nn;
-
-	ses = container_of(kref, struct nfsd4_session, se_ref);
-	nn = net_generic(ses->se_client->net, nfsd_net_id);
+	struct nfsd_net *nn = net_generic(ses->se_client->net, nfsd_net_id);
 
 	lockdep_assert_held(&nn->client_lock);
 	nfsd4_del_conns(ses);
 	__free_session(ses);
 }
 
-void nfsd4_put_session(struct nfsd4_session *ses)
-{
-	struct nfsd_net *nn = net_generic(ses->se_client->net, nfsd_net_id);
-
-	spin_lock(&nn->client_lock);
-	nfsd4_put_session_locked(ses);
-	spin_unlock(&nn->client_lock);
-}
-
 static struct nfsd4_session *alloc_session(struct nfsd4_channel_attrs *fchan,
 					   struct nfsd_net *nn)
 {
@@ -913,7 +999,7 @@ static void init_session(struct svc_rqst *rqstp, struct nfsd4_session *new, stru
 	new->se_flags = cses->flags;
 	new->se_cb_prog = cses->callback_prog;
 	new->se_cb_sec = cses->cb_sec;
-	kref_init(&new->se_ref);
+	atomic_set(&new->se_ref, 0);
 	idx = hash_sessionid(&new->se_sessionid);
 	spin_lock(&nn->client_lock);
 	list_add(&new->se_hash, &nn->sessionid_hashtbl[idx]);
@@ -968,38 +1054,6 @@ unhash_session(struct nfsd4_session *ses)
 	spin_unlock(&ses->se_client->cl_lock);
 }
 
-/* must be called under the client_lock */
-static inline void
-renew_client_locked(struct nfs4_client *clp)
-{
-	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
-
-	if (is_client_expired(clp)) {
-		WARN_ON(1);
-		printk("%s: client (clientid %08x/%08x) already expired\n",
-			__func__,
-			clp->cl_clientid.cl_boot,
-			clp->cl_clientid.cl_id);
-		return;
-	}
-
-	dprintk("renewing client (clientid %08x/%08x)\n", 
-			clp->cl_clientid.cl_boot, 
-			clp->cl_clientid.cl_id);
-	list_move_tail(&clp->cl_lru, &nn->client_lru);
-	clp->cl_time = get_seconds();
-}
-
-static inline void
-renew_client(struct nfs4_client *clp)
-{
-	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
-
-	spin_lock(&nn->client_lock);
-	renew_client_locked(clp);
-	spin_unlock(&nn->client_lock);
-}
-
 /* SETCLIENTID and SETCLIENTID_CONFIRM Helper functions */
 static int
 STALE_CLIENTID(clientid_t *clid, struct nfsd_net *nn)
@@ -1043,7 +1097,8 @@ free_client(struct nfs4_client *clp)
 		ses = list_entry(clp->cl_sessions.next, struct nfsd4_session,
 				se_perclnt);
 		list_del(&ses->se_perclnt);
-		nfsd4_put_session_locked(ses);
+		WARN_ON_ONCE(atomic_read(&ses->se_ref));
+		free_session(ses);
 	}
 	free_svc_cred(&clp->cl_cred);
 	kfree(clp->cl_name.data);
@@ -1051,29 +1106,12 @@ free_client(struct nfs4_client *clp)
 	kfree(clp);
 }
 
-void
-release_session_client(struct nfsd4_session *session)
-{
-	struct nfs4_client *clp = session->se_client;
-	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
-
-	if (!atomic_dec_and_lock(&clp->cl_refcount, &nn->client_lock))
-		return;
-	if (is_client_expired(clp)) {
-		free_client(clp);
-		session->se_client = NULL;
-	} else
-		renew_client_locked(clp);
-	spin_unlock(&nn->client_lock);
-}
-
 /* must be called under the client_lock */
 static inline void
 unhash_client_locked(struct nfs4_client *clp)
 {
 	struct nfsd4_session *ses;
 
-	mark_client_expired(clp);
 	list_del(&clp->cl_lru);
 	spin_lock(&clp->cl_lock);
 	list_for_each_entry(ses, &clp->cl_sessions, se_perclnt)
@@ -1115,8 +1153,8 @@ destroy_client(struct nfs4_client *clp)
 		rb_erase(&clp->cl_namenode, &nn->unconf_name_tree);
 	spin_lock(&nn->client_lock);
 	unhash_client_locked(clp);
-	if (atomic_read(&clp->cl_refcount) == 0)
-		free_client(clp);
+	WARN_ON_ONCE(atomic_read(&clp->cl_refcount));
+	free_client(clp);
 	spin_unlock(&nn->client_lock);
 }
 
@@ -1376,12 +1414,12 @@ move_to_confirmed(struct nfs4_client *clp)
 }
 
 static struct nfs4_client *
-find_confirmed_client(clientid_t *clid, bool sessions, struct nfsd_net *nn)
+find_client_in_id_table(struct list_head *tbl, clientid_t *clid, bool sessions)
 {
 	struct nfs4_client *clp;
 	unsigned int idhashval = clientid_hashval(clid->cl_id);
 
-	list_for_each_entry(clp, &nn->conf_id_hashtbl[idhashval], cl_idhash) {
+	list_for_each_entry(clp, &tbl[idhashval], cl_idhash) {
 		if (same_clid(&clp->cl_clientid, clid)) {
 			if ((bool)clp->cl_minorversion != sessions)
 				return NULL;
@@ -1393,19 +1431,19 @@ find_confirmed_client(clientid_t *clid, bool sessions, struct nfsd_net *nn)
 }
 
 static struct nfs4_client *
+find_confirmed_client(clientid_t *clid, bool sessions, struct nfsd_net *nn)
+{
+	struct list_head *tbl = nn->conf_id_hashtbl;
+
+	return find_client_in_id_table(tbl, clid, sessions);
+}
+
+static struct nfs4_client *
 find_unconfirmed_client(clientid_t *clid, bool sessions, struct nfsd_net *nn)
 {
-	struct nfs4_client *clp;
-	unsigned int idhashval = clientid_hashval(clid->cl_id);
+	struct list_head *tbl = nn->unconf_id_hashtbl;
 
-	list_for_each_entry(clp, &nn->unconf_id_hashtbl[idhashval], cl_idhash) {
-		if (same_clid(&clp->cl_clientid, clid)) {
-			if ((bool)clp->cl_minorversion != sessions)
-				return NULL;
-			return clp;
-		}
-	}
-	return NULL;
+	return find_client_in_id_table(tbl, clid, sessions);
 }
 
 static bool clp_used_exchangeid(struct nfs4_client *clp)
@@ -1784,6 +1822,7 @@ nfsd4_create_session(struct svc_rqst *rqstp,
 	nfs4_lock_state();
 	unconf = find_unconfirmed_client(&cr_ses->clientid, true, nn);
 	conf = find_confirmed_client(&cr_ses->clientid, true, nn);
+	WARN_ON_ONCE(conf && unconf);
 
 	if (conf) {
 		cs_slot = &conf->cl_cs_slot;
@@ -1810,8 +1849,12 @@ nfsd4_create_session(struct svc_rqst *rqstp,
 			goto out_free_conn;
 		}
 		old = find_confirmed_client_by_name(&unconf->cl_name, nn);
-		if (old)
+		if (old) {
+			status = mark_client_expired(old);
+			if (status)
+				goto out_free_conn;
 			expire_client(old);
+		}
 		move_to_confirmed(unconf);
 		conf = unconf;
 	} else {
@@ -1838,15 +1881,13 @@ nfsd4_create_session(struct svc_rqst *rqstp,
 	/* cache solo and embedded create sessions under the state lock */
 	nfsd4_cache_create_session(cr_ses, cs_slot, status);
 	nfs4_unlock_state();
-out:
-	dprintk("%s returns %d\n", __func__, ntohl(status));
 	return status;
 out_free_conn:
 	nfs4_unlock_state();
 	free_conn(conn);
 out_free_session:
 	__free_session(new);
-	goto out;
+	return status;
 }
 
 static __be32 nfsd4_map_bcts_dir(u32 *dir)
@@ -1884,30 +1925,30 @@ __be32 nfsd4_bind_conn_to_session(struct svc_rqst *rqstp,
 {
 	__be32 status;
 	struct nfsd4_conn *conn;
+	struct nfsd4_session *session;
 	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
 
 	if (!nfsd4_last_compound_op(rqstp))
 		return nfserr_not_only_op;
+	nfs4_lock_state();
 	spin_lock(&nn->client_lock);
-	cstate->session = find_in_sessionid_hashtbl(&bcts->sessionid, SVC_NET(rqstp));
-	/* Sorta weird: we only need the refcnt'ing because new_conn acquires
-	 * client_lock iself: */
-	if (cstate->session) {
-		nfsd4_get_session(cstate->session);
-		atomic_inc(&cstate->session->se_client->cl_refcount);
-	}
+	session = find_in_sessionid_hashtbl(&bcts->sessionid, SVC_NET(rqstp));
 	spin_unlock(&nn->client_lock);
-	if (!cstate->session)
-		return nfserr_badsession;
-
+	status = nfserr_badsession;
+	if (!session)
+		goto out;
 	status = nfsd4_map_bcts_dir(&bcts->dir);
 	if (status)
-		return status;
+		goto out;
 	conn = alloc_conn(rqstp, bcts->dir);
+	status = nfserr_jukebox;
 	if (!conn)
-		return nfserr_jukebox;
-	nfsd4_init_conn(rqstp, conn, cstate->session);
-	return nfs_ok;
+		goto out;
+	nfsd4_init_conn(rqstp, conn, session);
+	status = nfs_ok;
+out:
+	nfs4_unlock_state();
+	return status;
 }
 
 static bool nfsd4_compound_in_session(struct nfsd4_session *session, struct nfs4_sessionid *sid)
@@ -1923,42 +1964,36 @@ nfsd4_destroy_session(struct svc_rqst *r,
 		      struct nfsd4_destroy_session *sessionid)
 {
 	struct nfsd4_session *ses;
-	__be32 status = nfserr_badsession;
+	__be32 status;
 	struct nfsd_net *nn = net_generic(SVC_NET(r), nfsd_net_id);
 
-	/* Notes:
-	 * - The confirmed nfs4_client->cl_sessionid holds destroyed sessinid
-	 * - Should we return nfserr_back_chan_busy if waiting for
-	 *   callbacks on to-be-destroyed session?
-	 * - Do we need to clear any callback info from previous session?
-	 */
-
+	nfs4_lock_state();
+	status = nfserr_not_only_op;
 	if (nfsd4_compound_in_session(cstate->session, &sessionid->sessionid)) {
 		if (!nfsd4_last_compound_op(r))
-			return nfserr_not_only_op;
+			goto out;
 	}
 	dump_sessionid(__func__, &sessionid->sessionid);
 	spin_lock(&nn->client_lock);
 	ses = find_in_sessionid_hashtbl(&sessionid->sessionid, SVC_NET(r));
-	if (!ses) {
-		spin_unlock(&nn->client_lock);
-		goto out;
-	}
-
+	status = nfserr_badsession;
+	if (!ses)
+		goto out_client_lock;
+	status = mark_session_dead_locked(ses);
+	if (status)
+		goto out_client_lock;
 	unhash_session(ses);
 	spin_unlock(&nn->client_lock);
 
-	nfs4_lock_state();
 	nfsd4_probe_callback_sync(ses->se_client);
-	nfs4_unlock_state();
 
 	spin_lock(&nn->client_lock);
-	nfsd4_del_conns(ses);
-	nfsd4_put_session_locked(ses);
-	spin_unlock(&nn->client_lock);
+	free_session(ses);
 	status = nfs_ok;
+out_client_lock:
+	spin_unlock(&nn->client_lock);
 out:
-	dprintk("%s returns %d\n", __func__, ntohl(status));
+	nfs4_unlock_state();
 	return status;
 }
 
@@ -2018,6 +2053,7 @@ nfsd4_sequence(struct svc_rqst *rqstp,
 {
 	struct nfsd4_compoundres *resp = rqstp->rq_resp;
 	struct nfsd4_session *session;
+	struct nfs4_client *clp;
 	struct nfsd4_slot *slot;
 	struct nfsd4_conn *conn;
 	__be32 status;
@@ -2038,19 +2074,26 @@ nfsd4_sequence(struct svc_rqst *rqstp,
 	status = nfserr_badsession;
 	session = find_in_sessionid_hashtbl(&seq->sessionid, SVC_NET(rqstp));
 	if (!session)
-		goto out;
+		goto out_no_session;
+	clp = session->se_client;
+	status = get_client_locked(clp);
+	if (status)
+		goto out_no_session;
+	status = nfsd4_get_session_locked(session);
+	if (status)
+		goto out_put_client;
 
 	status = nfserr_too_many_ops;
 	if (nfsd4_session_too_many_ops(rqstp, session))
-		goto out;
+		goto out_put_session;
 
 	status = nfserr_req_too_big;
 	if (nfsd4_request_too_big(rqstp, session))
-		goto out;
+		goto out_put_session;
 
 	status = nfserr_badslot;
 	if (seq->slotid >= session->se_fchannel.maxreqs)
-		goto out;
+		goto out_put_session;
 
 	slot = session->se_slots[seq->slotid];
 	dprintk("%s: slotid %d\n", __func__, seq->slotid);
@@ -2065,7 +2108,7 @@ nfsd4_sequence(struct svc_rqst *rqstp,
 	if (status == nfserr_replay_cache) {
 		status = nfserr_seq_misordered;
 		if (!(slot->sl_flags & NFSD4_SLOT_INITIALIZED))
-			goto out;
+			goto out_put_session;
 		cstate->slot = slot;
 		cstate->session = session;
 		/* Return the cached reply status and set cstate->status
@@ -2075,7 +2118,7 @@ nfsd4_sequence(struct svc_rqst *rqstp,
 		goto out;
 	}
 	if (status)
-		goto out;
+		goto out_put_session;
 
 	nfsd4_sequence_check_conn(conn, session);
 	conn = NULL;
@@ -2092,27 +2135,25 @@ nfsd4_sequence(struct svc_rqst *rqstp,
 	cstate->session = session;
 
 out:
-	/* Hold a session reference until done processing the compound. */
-	if (cstate->session) {
-		struct nfs4_client *clp = session->se_client;
-
-		nfsd4_get_session(cstate->session);
-		atomic_inc(&clp->cl_refcount);
-		switch (clp->cl_cb_state) {
-		case NFSD4_CB_DOWN:
-			seq->status_flags = SEQ4_STATUS_CB_PATH_DOWN;
-			break;
-		case NFSD4_CB_FAULT:
-			seq->status_flags = SEQ4_STATUS_BACKCHANNEL_FAULT;
-			break;
-		default:
-			seq->status_flags = 0;
-		}
+	switch (clp->cl_cb_state) {
+	case NFSD4_CB_DOWN:
+		seq->status_flags = SEQ4_STATUS_CB_PATH_DOWN;
+		break;
+	case NFSD4_CB_FAULT:
+		seq->status_flags = SEQ4_STATUS_BACKCHANNEL_FAULT;
+		break;
+	default:
+		seq->status_flags = 0;
 	}
+out_no_session:
 	kfree(conn);
 	spin_unlock(&nn->client_lock);
-	dprintk("%s: return %d\n", __func__, ntohl(status));
 	return status;
+out_put_session:
+	nfsd4_put_session(session);
+out_put_client:
+	put_client_renew_locked(clp);
+	goto out_no_session;
 }
 
 __be32
@@ -2125,17 +2166,12 @@ nfsd4_destroy_clientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *csta
 	nfs4_lock_state();
 	unconf = find_unconfirmed_client(&dc->clientid, true, nn);
 	conf = find_confirmed_client(&dc->clientid, true, nn);
+	WARN_ON_ONCE(conf && unconf);
 
 	if (conf) {
 		clp = conf;
 
-		if (!is_client_expired(conf) && client_has_state(conf)) {
-			status = nfserr_clientid_busy;
-			goto out;
-		}
-
-		/* rfc5661 18.50.3 */
-		if (cstate->session && conf == cstate->session->se_client) {
+		if (client_has_state(conf)) {
 			status = nfserr_clientid_busy;
 			goto out;
 		}
@@ -2149,7 +2185,6 @@ nfsd4_destroy_clientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *csta
 	expire_client(clp);
 out:
 	nfs4_unlock_state();
-	dprintk("%s return %d\n", __func__, ntohl(status));
 	return status;
 }
 
@@ -2287,8 +2322,12 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
 		expire_client(unconf);
 	} else { /* case 3: normal case; new or rebooted client */
 		conf = find_confirmed_client_by_name(&unconf->cl_name, nn);
-		if (conf)
+		if (conf) {
+			status = mark_client_expired(conf);
+			if (status)
+				goto out;
 			expire_client(conf);
+		}
 		move_to_confirmed(unconf);
 		nfsd4_probe_callback(unconf);
 	}
@@ -2308,7 +2347,6 @@ static void nfsd4_init_file(struct nfs4_file *fp, struct inode *ino)
 	unsigned int hashval = file_hashval(ino);
 
 	atomic_set(&fp->fi_ref, 1);
-	INIT_LIST_HEAD(&fp->fi_hash);
 	INIT_LIST_HEAD(&fp->fi_stateids);
 	INIT_LIST_HEAD(&fp->fi_delegations);
 	fp->fi_inode = igrab(ino);
@@ -2317,7 +2355,7 @@ static void nfsd4_init_file(struct nfs4_file *fp, struct inode *ino)
 	memset(fp->fi_fds, 0, sizeof(fp->fi_fds));
 	memset(fp->fi_access, 0, sizeof(fp->fi_access));
 	spin_lock(&recall_lock);
-	list_add(&fp->fi_hash, &file_hashtbl[hashval]);
+	hlist_add_head(&fp->fi_hash, &file_hashtbl[hashval]);
 	spin_unlock(&recall_lock);
 }
 
@@ -2503,7 +2541,7 @@ find_file(struct inode *ino)
 	struct nfs4_file *fp;
 
 	spin_lock(&recall_lock);
-	list_for_each_entry(fp, &file_hashtbl[hashval], fi_hash) {
+	hlist_for_each_entry(fp, &file_hashtbl[hashval], fi_hash) {
 		if (fp->fi_inode == ino) {
 			get_nfs4_file(fp);
 			spin_unlock(&recall_lock);
@@ -2526,8 +2564,6 @@ nfs4_share_conflict(struct svc_fh *current_fh, unsigned int deny_type)
 	struct nfs4_ol_stateid *stp;
 	__be32 ret;
 
-	dprintk("NFSD: nfs4_share_conflict\n");
-
 	fp = find_file(ino);
 	if (!fp)
 		return nfs_ok;
@@ -3202,13 +3238,12 @@ nfs4_laundromat(struct nfsd_net *nn)
 				clientid_val = t;
 			break;
 		}
-		if (atomic_read(&clp->cl_refcount)) {
+		if (mark_client_expired_locked(clp)) {
 			dprintk("NFSD: client in use (clientid %08x)\n",
 				clp->cl_clientid.cl_id);
 			continue;
 		}
-		unhash_client_locked(clp);
-		list_add(&clp->cl_lru, &reaplist);
+		list_move(&clp->cl_lru, &reaplist);
 	}
 	spin_unlock(&nn->client_lock);
 	list_for_each_safe(pos, next, &reaplist) {
@@ -3276,16 +3311,6 @@ static inline __be32 nfs4_check_fh(struct svc_fh *fhp, struct nfs4_ol_stateid *s
 	return nfs_ok;
 }
 
-static int
-STALE_STATEID(stateid_t *stateid, struct nfsd_net *nn)
-{
-	if (stateid->si_opaque.so_clid.cl_boot == nn->boot_time)
-		return 0;
-	dprintk("NFSD: stale stateid " STATEID_FMT "!\n",
-		STATEID_VAL(stateid));
-	return 1;
-}
-
 static inline int
 access_permit_read(struct nfs4_ol_stateid *stp)
 {
@@ -3416,19 +3441,20 @@ static __be32 nfsd4_lookup_stateid(stateid_t *stateid, unsigned char typemask,
 				   struct nfsd_net *nn)
 {
 	struct nfs4_client *cl;
+	__be32 status;
 
 	if (ZERO_STATEID(stateid) || ONE_STATEID(stateid))
 		return nfserr_bad_stateid;
-	if (STALE_STATEID(stateid, nn))
+	status = lookup_clientid(&stateid->si_opaque.so_clid, sessions,
+							nn, &cl);
+	if (status == nfserr_stale_clientid)
 		return nfserr_stale_stateid;
-	cl = find_confirmed_client(&stateid->si_opaque.so_clid, sessions, nn);
-	if (!cl)
-		return nfserr_expired;
+	if (status)
+		return status;
 	*s = find_stateid_by_type(cl, stateid, typemask);
 	if (!*s)
 		return nfserr_bad_stateid;
 	return nfs_ok;
-
 }
 
 /*
@@ -3819,6 +3845,7 @@ nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 
 	nfsd4_close_open_stateid(stp);
 	release_last_closed_stateid(oo);
+	oo->oo_flags &= ~NFS4_OO_PURGE_CLOSE;
 	oo->oo_last_closed_stid = stp;
 
 	if (list_empty(&oo->oo_owner.so_stateids)) {
@@ -4602,6 +4629,8 @@ nfs4_check_open_reclaim(clientid_t *clid, bool sessions, struct nfsd_net *nn)
 
 u64 nfsd_forget_client(struct nfs4_client *clp, u64 max)
 {
+	if (mark_client_expired(clp))
+		return 0;
 	expire_client(clp);
 	return 1;
 }
@@ -4780,11 +4809,6 @@ struct nfs4_client *nfsd_find_client(struct sockaddr_storage *addr, size_t addr_
 void
 nfs4_state_init(void)
 {
-	int i;
-
-	for (i = 0; i < FILE_HASH_SIZE; i++) {
-		INIT_LIST_HEAD(&file_hashtbl[i]);
-	}
 	INIT_LIST_HEAD(&del_recall_lru);
 }
 
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 0116886..79401f1 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -264,7 +264,7 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
 		iattr->ia_valid |= ATTR_SIZE;
 	}
 	if (bmval[0] & FATTR4_WORD0_ACL) {
-		int nace;
+		u32 nace;
 		struct nfs4_ace *ace;
 
 		READ_BUF(4); len += 4;
@@ -804,6 +804,7 @@ nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
 	open->op_iattr.ia_valid = 0;
 	open->op_openowner = NULL;
 
+	open->op_xdr_error = 0;
 	/* seqid, share_access, share_deny, clientid, ownerlen */
 	READ_BUF(4);
 	READ32(open->op_seqid);
@@ -3138,10 +3139,9 @@ nfsd4_encode_rename(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_
 
 static __be32
 nfsd4_do_encode_secinfo(struct nfsd4_compoundres *resp,
-			 __be32 nfserr,struct svc_export *exp)
+			 __be32 nfserr, struct svc_export *exp)
 {
-	int i = 0;
-	u32 nflavs;
+	u32 i, nflavs;
 	struct exp_flavor_info *flavs;
 	struct exp_flavor_info def_flavs[2];
 	__be32 *p;
@@ -3172,30 +3172,29 @@ nfsd4_do_encode_secinfo(struct nfsd4_compoundres *resp,
 	WRITE32(nflavs);
 	ADJUST_ARGS();
 	for (i = 0; i < nflavs; i++) {
-		u32 flav = flavs[i].pseudoflavor;
-		struct gss_api_mech *gm = gss_mech_get_by_pseudoflavor(flav);
+		struct rpcsec_gss_info info;
 
-		if (gm) {
+		if (rpcauth_get_gssinfo(flavs[i].pseudoflavor, &info) == 0) {
 			RESERVE_SPACE(4);
 			WRITE32(RPC_AUTH_GSS);
 			ADJUST_ARGS();
-			RESERVE_SPACE(4 + gm->gm_oid.len);
-			WRITE32(gm->gm_oid.len);
-			WRITEMEM(gm->gm_oid.data, gm->gm_oid.len);
+			RESERVE_SPACE(4 + info.oid.len);
+			WRITE32(info.oid.len);
+			WRITEMEM(info.oid.data, info.oid.len);
 			ADJUST_ARGS();
 			RESERVE_SPACE(4);
-			WRITE32(0); /* qop */
+			WRITE32(info.qop);
 			ADJUST_ARGS();
 			RESERVE_SPACE(4);
-			WRITE32(gss_pseudoflavor_to_service(gm, flav));
+			WRITE32(info.service);
 			ADJUST_ARGS();
-			gss_mech_put(gm);
 		} else {
 			RESERVE_SPACE(4);
-			WRITE32(flav);
+			WRITE32(flavs[i].pseudoflavor);
 			ADJUST_ARGS();
 		}
 	}
+
 out:
 	if (exp)
 		exp_put(exp);
@@ -3683,7 +3682,7 @@ nfs4svc_encode_compoundres(struct svc_rqst *rqstp, __be32 *p, struct nfsd4_compo
 			cs->slot->sl_flags &= ~NFSD4_SLOT_INUSE;
 		}
 		/* Renew the clientid on success and on replay */
-		release_session_client(cs->session);
+		put_client_renew(cs->session->se_client);
 		nfsd4_put_session(cs->session);
 	}
 	return 1;
diff --git a/fs/nfsd/nfscache.c b/fs/nfsd/nfscache.c
index ca05f6d..eb25877 100644
--- a/fs/nfsd/nfscache.c
+++ b/fs/nfsd/nfscache.c
@@ -11,6 +11,8 @@
 #include <linux/slab.h>
 #include <linux/sunrpc/addr.h>
 #include <linux/highmem.h>
+#include <linux/log2.h>
+#include <linux/hash.h>
 #include <net/checksum.h>
 
 #include "nfsd.h"
@@ -18,23 +20,42 @@
 
 #define NFSDDBG_FACILITY	NFSDDBG_REPCACHE
 
-#define HASHSIZE		64
+/*
+ * We use this value to determine the number of hash buckets from the max
+ * cache size, the idea being that when the cache is at its maximum number
+ * of entries, then this should be the average number of entries per bucket.
+ */
+#define TARGET_BUCKET_SIZE	64
 
 static struct hlist_head *	cache_hash;
 static struct list_head 	lru_head;
 static struct kmem_cache	*drc_slab;
-static unsigned int		num_drc_entries;
+
+/* max number of entries allowed in the cache */
 static unsigned int		max_drc_entries;
 
+/* number of significant bits in the hash value */
+static unsigned int		maskbits;
+
 /*
- * Calculate the hash index from an XID.
+ * Stats and other tracking of on the duplicate reply cache. All of these and
+ * the "rc" fields in nfsdstats are protected by the cache_lock
  */
-static inline u32 request_hash(u32 xid)
-{
-	u32 h = xid;
-	h ^= (xid >> 24);
-	return h & (HASHSIZE-1);
-}
+
+/* total number of entries */
+static unsigned int		num_drc_entries;
+
+/* cache misses due only to checksum comparison failures */
+static unsigned int		payload_misses;
+
+/* amount of memory (in bytes) currently consumed by the DRC */
+static unsigned int		drc_mem_usage;
+
+/* longest hash chain seen */
+static unsigned int		longest_chain;
+
+/* size of cache when we saw the longest hash chain */
+static unsigned int		longest_chain_cachesize;
 
 static int	nfsd_cache_append(struct svc_rqst *rqstp, struct kvec *vec);
 static void	cache_cleaner_func(struct work_struct *unused);
@@ -82,6 +103,16 @@ nfsd_cache_size_limit(void)
 	return min_t(unsigned int, limit, 256*1024);
 }
 
+/*
+ * Compute the number of hash buckets we need. Divide the max cachesize by
+ * the "target" max bucket size, and round up to next power of two.
+ */
+static unsigned int
+nfsd_hashsize(unsigned int limit)
+{
+	return roundup_pow_of_two(limit / TARGET_BUCKET_SIZE);
+}
+
 static struct svc_cacherep *
 nfsd_reply_cache_alloc(void)
 {
@@ -100,12 +131,15 @@ nfsd_reply_cache_alloc(void)
 static void
 nfsd_reply_cache_free_locked(struct svc_cacherep *rp)
 {
-	if (rp->c_type == RC_REPLBUFF)
+	if (rp->c_type == RC_REPLBUFF && rp->c_replvec.iov_base) {
+		drc_mem_usage -= rp->c_replvec.iov_len;
 		kfree(rp->c_replvec.iov_base);
+	}
 	if (!hlist_unhashed(&rp->c_hash))
 		hlist_del(&rp->c_hash);
 	list_del(&rp->c_lru);
 	--num_drc_entries;
+	drc_mem_usage -= sizeof(*rp);
 	kmem_cache_free(drc_slab, rp);
 }
 
@@ -119,9 +153,13 @@ nfsd_reply_cache_free(struct svc_cacherep *rp)
 
 int nfsd_reply_cache_init(void)
 {
+	unsigned int hashsize;
+
 	INIT_LIST_HEAD(&lru_head);
 	max_drc_entries = nfsd_cache_size_limit();
 	num_drc_entries = 0;
+	hashsize = nfsd_hashsize(max_drc_entries);
+	maskbits = ilog2(hashsize);
 
 	register_shrinker(&nfsd_reply_cache_shrinker);
 	drc_slab = kmem_cache_create("nfsd_drc", sizeof(struct svc_cacherep),
@@ -129,7 +167,7 @@ int nfsd_reply_cache_init(void)
 	if (!drc_slab)
 		goto out_nomem;
 
-	cache_hash = kcalloc(HASHSIZE, sizeof(struct hlist_head), GFP_KERNEL);
+	cache_hash = kcalloc(hashsize, sizeof(struct hlist_head), GFP_KERNEL);
 	if (!cache_hash)
 		goto out_nomem;
 
@@ -180,7 +218,7 @@ static void
 hash_refile(struct svc_cacherep *rp)
 {
 	hlist_del_init(&rp->c_hash);
-	hlist_add_head(&rp->c_hash, cache_hash + request_hash(rp->c_xid));
+	hlist_add_head(&rp->c_hash, cache_hash + hash_32(rp->c_xid, maskbits));
 }
 
 static inline bool
@@ -273,6 +311,26 @@ nfsd_cache_csum(struct svc_rqst *rqstp)
 	return csum;
 }
 
+static bool
+nfsd_cache_match(struct svc_rqst *rqstp, __wsum csum, struct svc_cacherep *rp)
+{
+	/* Check RPC header info first */
+	if (rqstp->rq_xid != rp->c_xid || rqstp->rq_proc != rp->c_proc ||
+	    rqstp->rq_prot != rp->c_prot || rqstp->rq_vers != rp->c_vers ||
+	    rqstp->rq_arg.len != rp->c_len ||
+	    !rpc_cmp_addr(svc_addr(rqstp), (struct sockaddr *)&rp->c_addr) ||
+	    rpc_get_port(svc_addr(rqstp)) != rpc_get_port((struct sockaddr *)&rp->c_addr))
+		return false;
+
+	/* compare checksum of NFS data */
+	if (csum != rp->c_csum) {
+		++payload_misses;
+		return false;
+	}
+
+	return true;
+}
+
 /*
  * Search the request hash for an entry that matches the given rqstp.
  * Must be called with cache_lock held. Returns the found entry or
@@ -281,23 +339,30 @@ nfsd_cache_csum(struct svc_rqst *rqstp)
 static struct svc_cacherep *
 nfsd_cache_search(struct svc_rqst *rqstp, __wsum csum)
 {
-	struct svc_cacherep	*rp;
+	struct svc_cacherep	*rp, *ret = NULL;
 	struct hlist_head 	*rh;
-	__be32			xid = rqstp->rq_xid;
-	u32			proto =  rqstp->rq_prot,
-				vers = rqstp->rq_vers,
-				proc = rqstp->rq_proc;
+	unsigned int		entries = 0;
 
-	rh = &cache_hash[request_hash(xid)];
+	rh = &cache_hash[hash_32(rqstp->rq_xid, maskbits)];
 	hlist_for_each_entry(rp, rh, c_hash) {
-		if (xid == rp->c_xid && proc == rp->c_proc &&
-		    proto == rp->c_prot && vers == rp->c_vers &&
-		    rqstp->rq_arg.len == rp->c_len && csum == rp->c_csum &&
-		    rpc_cmp_addr(svc_addr(rqstp), (struct sockaddr *)&rp->c_addr) &&
-		    rpc_get_port(svc_addr(rqstp)) == rpc_get_port((struct sockaddr *)&rp->c_addr))
-			return rp;
+		++entries;
+		if (nfsd_cache_match(rqstp, csum, rp)) {
+			ret = rp;
+			break;
+		}
 	}
-	return NULL;
+
+	/* tally hash chain length stats */
+	if (entries > longest_chain) {
+		longest_chain = entries;
+		longest_chain_cachesize = num_drc_entries;
+	} else if (entries == longest_chain) {
+		/* prefer to keep the smallest cachesize possible here */
+		longest_chain_cachesize = min(longest_chain_cachesize,
+						num_drc_entries);
+	}
+
+	return ret;
 }
 
 /*
@@ -318,55 +383,55 @@ nfsd_cache_lookup(struct svc_rqst *rqstp)
 	__wsum			csum;
 	unsigned long		age;
 	int type = rqstp->rq_cachetype;
-	int rtn;
+	int rtn = RC_DOIT;
 
 	rqstp->rq_cacherep = NULL;
 	if (type == RC_NOCACHE) {
 		nfsdstats.rcnocache++;
-		return RC_DOIT;
+		return rtn;
 	}
 
 	csum = nfsd_cache_csum(rqstp);
 
+	/*
+	 * Since the common case is a cache miss followed by an insert,
+	 * preallocate an entry. First, try to reuse the first entry on the LRU
+	 * if it works, then go ahead and prune the LRU list.
+	 */
 	spin_lock(&cache_lock);
-	rtn = RC_DOIT;
-
-	rp = nfsd_cache_search(rqstp, csum);
-	if (rp)
-		goto found_entry;
-
-	/* Try to use the first entry on the LRU */
 	if (!list_empty(&lru_head)) {
 		rp = list_first_entry(&lru_head, struct svc_cacherep, c_lru);
 		if (nfsd_cache_entry_expired(rp) ||
 		    num_drc_entries >= max_drc_entries) {
 			lru_put_end(rp);
 			prune_cache_entries();
-			goto setup_entry;
+			goto search_cache;
 		}
 	}
 
-	/* Drop the lock and allocate a new entry */
+	/* No expired ones available, allocate a new one. */
 	spin_unlock(&cache_lock);
 	rp = nfsd_reply_cache_alloc();
-	if (!rp) {
-		dprintk("nfsd: unable to allocate DRC entry!\n");
-		return RC_DOIT;
-	}
 	spin_lock(&cache_lock);
-	++num_drc_entries;
+	if (likely(rp)) {
+		++num_drc_entries;
+		drc_mem_usage += sizeof(*rp);
+	}
 
-	/*
-	 * Must search again just in case someone inserted one
-	 * after we dropped the lock above.
-	 */
+search_cache:
 	found = nfsd_cache_search(rqstp, csum);
 	if (found) {
-		nfsd_reply_cache_free_locked(rp);
+		if (likely(rp))
+			nfsd_reply_cache_free_locked(rp);
 		rp = found;
 		goto found_entry;
 	}
 
+	if (!rp) {
+		dprintk("nfsd: unable to allocate DRC entry!\n");
+		goto out;
+	}
+
 	/*
 	 * We're keeping the one we just allocated. Are we now over the
 	 * limit? Prune one off the tip of the LRU in trade for the one we
@@ -376,7 +441,6 @@ nfsd_cache_lookup(struct svc_rqst *rqstp)
 		nfsd_reply_cache_free_locked(list_first_entry(&lru_head,
 						struct svc_cacherep, c_lru));
 
-setup_entry:
 	nfsdstats.rcmisses++;
 	rqstp->rq_cacherep = rp;
 	rp->c_state = RC_INPROG;
@@ -394,6 +458,7 @@ setup_entry:
 
 	/* release any buffer */
 	if (rp->c_type == RC_REPLBUFF) {
+		drc_mem_usage -= rp->c_replvec.iov_len;
 		kfree(rp->c_replvec.iov_base);
 		rp->c_replvec.iov_base = NULL;
 	}
@@ -462,6 +527,7 @@ nfsd_cache_update(struct svc_rqst *rqstp, int cachetype, __be32 *statp)
 	struct svc_cacherep *rp = rqstp->rq_cacherep;
 	struct kvec	*resv = &rqstp->rq_res.head[0], *cachv;
 	int		len;
+	size_t		bufsize = 0;
 
 	if (!rp)
 		return;
@@ -483,19 +549,21 @@ nfsd_cache_update(struct svc_rqst *rqstp, int cachetype, __be32 *statp)
 		break;
 	case RC_REPLBUFF:
 		cachv = &rp->c_replvec;
-		cachv->iov_base = kmalloc(len << 2, GFP_KERNEL);
+		bufsize = len << 2;
+		cachv->iov_base = kmalloc(bufsize, GFP_KERNEL);
 		if (!cachv->iov_base) {
 			nfsd_reply_cache_free(rp);
 			return;
 		}
-		cachv->iov_len = len << 2;
-		memcpy(cachv->iov_base, statp, len << 2);
+		cachv->iov_len = bufsize;
+		memcpy(cachv->iov_base, statp, bufsize);
 		break;
 	case RC_NOCACHE:
 		nfsd_reply_cache_free(rp);
 		return;
 	}
 	spin_lock(&cache_lock);
+	drc_mem_usage += bufsize;
 	lru_put_end(rp);
 	rp->c_secure = rqstp->rq_secure;
 	rp->c_type = cachetype;
@@ -523,3 +591,30 @@ nfsd_cache_append(struct svc_rqst *rqstp, struct kvec *data)
 	vec->iov_len += data->iov_len;
 	return 1;
 }
+
+/*
+ * Note that fields may be added, removed or reordered in the future. Programs
+ * scraping this file for info should test the labels to ensure they're
+ * getting the correct field.
+ */
+static int nfsd_reply_cache_stats_show(struct seq_file *m, void *v)
+{
+	spin_lock(&cache_lock);
+	seq_printf(m, "max entries:           %u\n", max_drc_entries);
+	seq_printf(m, "num entries:           %u\n", num_drc_entries);
+	seq_printf(m, "hash buckets:          %u\n", 1 << maskbits);
+	seq_printf(m, "mem usage:             %u\n", drc_mem_usage);
+	seq_printf(m, "cache hits:            %u\n", nfsdstats.rchits);
+	seq_printf(m, "cache misses:          %u\n", nfsdstats.rcmisses);
+	seq_printf(m, "not cached:            %u\n", nfsdstats.rcnocache);
+	seq_printf(m, "payload misses:        %u\n", payload_misses);
+	seq_printf(m, "longest chain len:     %u\n", longest_chain);
+	seq_printf(m, "cachesize at longest:  %u\n", longest_chain_cachesize);
+	spin_unlock(&cache_lock);
+	return 0;
+}
+
+int nfsd_reply_cache_stats_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, nfsd_reply_cache_stats_show, NULL);
+}
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index f33455b..68a4d32 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -35,6 +35,7 @@ enum {
 	NFSD_Threads,
 	NFSD_Pool_Threads,
 	NFSD_Pool_Stats,
+	NFSD_Reply_Cache_Stats,
 	NFSD_Versions,
 	NFSD_Ports,
 	NFSD_MaxBlkSize,
@@ -212,6 +213,13 @@ static const struct file_operations pool_stats_operations = {
 	.owner		= THIS_MODULE,
 };
 
+static struct file_operations reply_cache_stats_operations = {
+	.open		= nfsd_reply_cache_stats_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
 /*----------------------------------------------------------------------------*/
 /*
  * payload - write methods
@@ -1047,6 +1055,7 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent)
 		[NFSD_Threads] = {"threads", &transaction_ops, S_IWUSR|S_IRUSR},
 		[NFSD_Pool_Threads] = {"pool_threads", &transaction_ops, S_IWUSR|S_IRUSR},
 		[NFSD_Pool_Stats] = {"pool_stats", &pool_stats_operations, S_IRUGO},
+		[NFSD_Reply_Cache_Stats] = {"reply_cache_stats", &reply_cache_stats_operations, S_IRUGO},
 		[NFSD_Versions] = {"versions", &transaction_ops, S_IWUSR|S_IRUSR},
 		[NFSD_Ports] = {"portlist", &transaction_ops, S_IWUSR|S_IRUGO},
 		[NFSD_MaxBlkSize] = {"max_block_size", &transaction_ops, S_IWUSR|S_IRUGO},
@@ -1102,8 +1111,10 @@ static int create_proc_exports_entry(void)
 		return -ENOMEM;
 	entry = proc_create("exports", 0, entry,
 				 &exports_proc_operations);
-	if (!entry)
+	if (!entry) {
+		remove_proc_entry("fs/nfs", NULL);
 		return -ENOMEM;
+	}
 	return 0;
 }
 #else /* CONFIG_PROC_FS */
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
index 1a8c739..7674bc8 100644
--- a/fs/nfsd/state.h
+++ b/fs/nfsd/state.h
@@ -194,9 +194,11 @@ struct nfsd4_conn {
 };
 
 struct nfsd4_session {
-	struct kref		se_ref;
+	atomic_t		se_ref;
 	struct list_head	se_hash;	/* hash by sessionid */
 	struct list_head	se_perclnt;
+/* See SESSION4_PERSIST, etc. for standard flags; this is internal-only: */
+#define NFS4_SESSION_DEAD	0x010
 	u32			se_flags;
 	struct nfs4_client	*se_client;
 	struct nfs4_sessionid	se_sessionid;
@@ -286,18 +288,6 @@ struct nfs4_client {
 	struct net		*net;
 };
 
-static inline void
-mark_client_expired(struct nfs4_client *clp)
-{
-	clp->cl_time = 0;
-}
-
-static inline bool
-is_client_expired(struct nfs4_client *clp)
-{
-	return clp->cl_time == 0;
-}
-
 /* struct nfs4_client_reset
  * one per old client. Populates reset_str_hashtbl. Filled from conf_id_hashtbl
  * upon lease reset, or from upcall to state_daemon (to read in state
@@ -390,7 +380,7 @@ static inline struct nfs4_lockowner * lockowner(struct nfs4_stateowner *so)
 /* nfs4_file: a file opened by some number of (open) nfs4_stateowners. */
 struct nfs4_file {
 	atomic_t		fi_ref;
-	struct list_head        fi_hash;    /* hash by "struct inode *" */
+	struct hlist_node       fi_hash;    /* hash by "struct inode *" */
 	struct list_head        fi_stateids;
 	struct list_head	fi_delegations;
 	/* One each for O_RDONLY, O_WRONLY, O_RDWR: */
@@ -486,7 +476,7 @@ extern void nfs4_put_delegation(struct nfs4_delegation *dp);
 extern struct nfs4_client_reclaim *nfs4_client_to_reclaim(const char *name,
 							struct nfsd_net *nn);
 extern bool nfs4_has_reclaimed_state(const char *name, struct nfsd_net *nn);
-extern void release_session_client(struct nfsd4_session *);
+extern void put_client_renew(struct nfs4_client *clp);
 extern void nfsd4_purge_closed_stateid(struct nfs4_stateowner *);
 
 /* nfs4recover operations */
diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h
index 546f898..40e05e6 100644
--- a/fs/nfsd/xdr4.h
+++ b/fs/nfsd/xdr4.h
@@ -184,7 +184,6 @@ struct nfsd4_lock {
 #define lk_old_lock_stateid     v.old.lock_stateid
 #define lk_old_lock_seqid       v.old.lock_seqid
 
-#define lk_rflags       u.ok.rflags
 #define lk_resp_stateid u.ok.stateid
 #define lk_denied       u.denied
 
@@ -237,6 +236,7 @@ struct nfsd4_open {
 	u32		op_share_deny;      /* request */
 	u32		op_deleg_want;      /* request */
 	stateid_t	op_stateid;         /* response */
+	__be32		op_xdr_error;       /* see nfsd4_open_omfg() */
 	u32		op_recall;          /* recall */
 	struct nfsd4_change_info  op_cinfo; /* response */
 	u32		op_rflags;          /* response */
diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c
index 6b49f14..1e92930 100644
--- a/fs/nilfs2/inode.c
+++ b/fs/nilfs2/inode.c
@@ -25,7 +25,7 @@
 #include <linux/gfp.h>
 #include <linux/mpage.h>
 #include <linux/writeback.h>
-#include <linux/uio.h>
+#include <linux/aio.h>
 #include "nilfs.h"
 #include "btnode.h"
 #include "segment.h"
diff --git a/fs/nilfs2/segbuf.c b/fs/nilfs2/segbuf.c
index dc9a913..680b65b 100644
--- a/fs/nilfs2/segbuf.c
+++ b/fs/nilfs2/segbuf.c
@@ -338,7 +338,8 @@ void nilfs_add_checksums_on_logs(struct list_head *logs, u32 seed)
 /*
  * BIO operations
  */
-static void nilfs_end_bio_write(struct bio *bio, int err)
+static void nilfs_end_bio_write(struct bio *bio, int err,
+				struct batch_complete *batch)
 {
 	const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
 	struct nilfs_segment_buffer *segbuf = bio->bi_private;
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c
index 5d84442..d0be29f 100644
--- a/fs/notify/fanotify/fanotify_user.c
+++ b/fs/notify/fanotify/fanotify_user.c
@@ -755,9 +755,9 @@ out_destroy_group:
 	return fd;
 }
 
-SYSCALL_DEFINE(fanotify_mark)(int fanotify_fd, unsigned int flags,
-			      __u64 mask, int dfd,
-			      const char  __user * pathname)
+SYSCALL_DEFINE5(fanotify_mark, int, fanotify_fd, unsigned int, flags,
+			      __u64, mask, int, dfd,
+			      const char  __user *, pathname)
 {
 	struct inode *inode = NULL;
 	struct vfsmount *mnt = NULL;
@@ -857,17 +857,6 @@ fput_and_out:
 	return ret;
 }
 
-#ifdef CONFIG_HAVE_SYSCALL_WRAPPERS
-asmlinkage long SyS_fanotify_mark(long fanotify_fd, long flags, __u64 mask,
-				  long dfd, long pathname)
-{
-	return SYSC_fanotify_mark((int) fanotify_fd, (unsigned int) flags,
-				  mask, (int) dfd,
-				  (const char  __user *) pathname);
-}
-SYSCALL_ALIAS(sys_fanotify_mark, SyS_fanotify_mark);
-#endif
-
 /*
  * fanotify_user_setup - Our initialization function.  Note that we cannot return
  * error because we have compiled-in VFS hooks.  So an (unlikely) failure here
diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c
index 5b2d4f0..c5670b8 100644
--- a/fs/ntfs/file.c
+++ b/fs/ntfs/file.c
@@ -27,6 +27,7 @@
 #include <linux/swap.h>
 #include <linux/uio.h>
 #include <linux/writeback.h>
+#include <linux/aio.h>
 
 #include <asm/page.h>
 #include <asm/uaccess.h>
@@ -2129,7 +2130,6 @@ static ssize_t ntfs_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
 
 	BUG_ON(iocb->ki_pos != pos);
 
-	sb_start_write(inode->i_sb);
 	mutex_lock(&inode->i_mutex);
 	ret = ntfs_file_aio_write_nolock(iocb, iov, nr_segs, &iocb->ki_pos);
 	mutex_unlock(&inode->i_mutex);
@@ -2138,7 +2138,6 @@ static ssize_t ntfs_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
 		if (err < 0)
 			ret = err;
 	}
-	sb_end_write(inode->i_sb);
 	return ret;
 }
 
diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c
index d3e118c..2778b02 100644
--- a/fs/ntfs/inode.c
+++ b/fs/ntfs/inode.c
@@ -28,6 +28,7 @@
 #include <linux/quotaops.h>
 #include <linux/slab.h>
 #include <linux/log2.h>
+#include <linux/aio.h>
 
 #include "aops.h"
 #include "attrib.h"
diff --git a/fs/ocfs2/aops.h b/fs/ocfs2/aops.h
index ffb2da3..f671e49 100644
--- a/fs/ocfs2/aops.h
+++ b/fs/ocfs2/aops.h
@@ -22,6 +22,8 @@
 #ifndef OCFS2_AOPS_H
 #define OCFS2_AOPS_H
 
+#include <linux/aio.h>
+
 handle_t *ocfs2_start_walk_page_trans(struct inode *inode,
 							 struct page *page,
 							 unsigned from,
diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c
index 42252bf..0cc19d0 100644
--- a/fs/ocfs2/cluster/heartbeat.c
+++ b/fs/ocfs2/cluster/heartbeat.c
@@ -35,6 +35,7 @@
 #include <linux/time.h>
 #include <linux/debugfs.h>
 #include <linux/slab.h>
+#include <linux/bitmap.h>
 
 #include "heartbeat.h"
 #include "tcp.h"
@@ -282,15 +283,6 @@ struct o2hb_bio_wait_ctxt {
 	int               wc_error;
 };
 
-static int o2hb_pop_count(void *map, int count)
-{
-	int i = -1, pop = 0;
-
-	while ((i = find_next_bit(map, count, i + 1)) < count)
-		pop++;
-	return pop;
-}
-
 static void o2hb_write_timeout(struct work_struct *work)
 {
 	int failed, quorum;
@@ -307,9 +299,9 @@ static void o2hb_write_timeout(struct work_struct *work)
 		spin_lock_irqsave(&o2hb_live_lock, flags);
 		if (test_bit(reg->hr_region_num, o2hb_quorum_region_bitmap))
 			set_bit(reg->hr_region_num, o2hb_failed_region_bitmap);
-		failed = o2hb_pop_count(&o2hb_failed_region_bitmap,
+		failed = bitmap_weight(o2hb_failed_region_bitmap,
 					O2NM_MAX_REGIONS);
-		quorum = o2hb_pop_count(&o2hb_quorum_region_bitmap,
+		quorum = bitmap_weight(o2hb_quorum_region_bitmap,
 					O2NM_MAX_REGIONS);
 		spin_unlock_irqrestore(&o2hb_live_lock, flags);
 
@@ -380,8 +372,8 @@ static void o2hb_wait_on_io(struct o2hb_region *reg,
 	wait_for_completion(&wc->wc_io_complete);
 }
 
-static void o2hb_bio_end_io(struct bio *bio,
-			   int error)
+static void o2hb_bio_end_io(struct bio *bio, int error,
+			    struct batch_complete *batch)
 {
 	struct o2hb_bio_wait_ctxt *wc = bio->bi_private;
 
@@ -771,7 +763,7 @@ static void o2hb_set_quorum_device(struct o2hb_region *reg)
 	 * If global heartbeat active, unpin all regions if the
 	 * region count > CUT_OFF
 	 */
-	if (o2hb_pop_count(&o2hb_quorum_region_bitmap,
+	if (bitmap_weight(o2hb_quorum_region_bitmap,
 			   O2NM_MAX_REGIONS) > O2HB_PIN_CUT_OFF)
 		o2hb_region_unpin(NULL);
 unlock:
@@ -956,23 +948,9 @@ out:
 	return changed;
 }
 
-/* This could be faster if we just implmented a find_last_bit, but I
- * don't think the circumstances warrant it. */
-static int o2hb_highest_node(unsigned long *nodes,
-			     int numbits)
+static int o2hb_highest_node(unsigned long *nodes, int numbits)
 {
-	int highest, node;
-
-	highest = numbits;
-	node = -1;
-	while ((node = find_next_bit(nodes, numbits, node + 1)) != -1) {
-		if (node >= numbits)
-			break;
-
-		highest = node;
-	}
-
-	return highest;
+	return find_last_bit(nodes, numbits);
 }
 
 static int o2hb_do_disk_heartbeat(struct o2hb_region *reg)
@@ -1831,7 +1809,7 @@ static ssize_t o2hb_region_dev_write(struct o2hb_region *reg,
 	live_threshold = O2HB_LIVE_THRESHOLD;
 	if (o2hb_global_heartbeat_active()) {
 		spin_lock(&o2hb_live_lock);
-		if (o2hb_pop_count(&o2hb_region_bitmap, O2NM_MAX_REGIONS) == 1)
+		if (bitmap_weight(o2hb_region_bitmap, O2NM_MAX_REGIONS) == 1)
 			live_threshold <<= 1;
 		spin_unlock(&o2hb_live_lock);
 	}
@@ -2182,7 +2160,7 @@ static void o2hb_heartbeat_group_drop_item(struct config_group *group,
 	if (!o2hb_dependent_users)
 		goto unlock;
 
-	if (o2hb_pop_count(&o2hb_quorum_region_bitmap,
+	if (bitmap_weight(o2hb_quorum_region_bitmap,
 			   O2NM_MAX_REGIONS) <= O2HB_PIN_CUT_OFF)
 		o2hb_region_pin(NULL);
 
@@ -2476,7 +2454,7 @@ static int o2hb_region_inc_user(const char *region_uuid)
 	if (o2hb_dependent_users > 1)
 		goto unlock;
 
-	if (o2hb_pop_count(&o2hb_quorum_region_bitmap,
+	if (bitmap_weight(o2hb_quorum_region_bitmap,
 			   O2NM_MAX_REGIONS) <= O2HB_PIN_CUT_OFF)
 		ret = o2hb_region_pin(NULL);
 
diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h
index baa2b9e..2260fb9 100644
--- a/fs/ocfs2/cluster/masklog.h
+++ b/fs/ocfs2/cluster/masklog.h
@@ -199,7 +199,8 @@ extern struct mlog_bits mlog_and_bits, mlog_not_bits;
 #define mlog_errno(st) do {						\
 	int _st = (st);							\
 	if (_st != -ERESTARTSYS && _st != -EINTR &&			\
-	    _st != AOP_TRUNCATED_PAGE && _st != -ENOSPC)		\
+	    _st != AOP_TRUNCATED_PAGE && _st != -ENOSPC &&		\
+	    _st != -EDQUOT)						\
 		mlog(ML_ERROR, "status = %lld\n", (long long)_st);	\
 } while (0)
 
diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c
index 33ecbe0..3d09a94 100644
--- a/fs/ocfs2/dlm/dlmmaster.c
+++ b/fs/ocfs2/dlm/dlmmaster.c
@@ -1888,8 +1888,10 @@ ok:
 			 * up nodes that this node contacted */
 			while ((nn = find_next_bit (mle->response_map, O2NM_MAX_NODES,
 						    nn+1)) < O2NM_MAX_NODES) {
-				if (nn != dlm->node_num && nn != assert->node_idx)
+				if (nn != dlm->node_num && nn != assert->node_idx) {
 					master_request = 1;
+					break;
+				}
 			}
 		}
 		mle->master = assert->node_idx;
@@ -2357,6 +2359,10 @@ static int dlm_is_lockres_migrateable(struct dlm_ctxt *dlm,
 
 	assert_spin_locked(&res->spinlock);
 
+	/* delay migration when the lockres is in MIGRATING state */
+	if (res->state & DLM_LOCK_RES_MIGRATING)
+		return 0;
+
 	if (res->owner != dlm->node_num)
 		return 0;
 
diff --git a/fs/ocfs2/dlm/dlmrecovery.c b/fs/ocfs2/dlm/dlmrecovery.c
index eeac97b..ba1e689 100644
--- a/fs/ocfs2/dlm/dlmrecovery.c
+++ b/fs/ocfs2/dlm/dlmrecovery.c
@@ -1887,6 +1887,13 @@ static int dlm_process_recovery_data(struct dlm_ctxt *dlm,
 
 		if (ml->type == LKM_NLMODE)
 			goto skip_lvb;
+		
+		/*
+		 * If the lock is in the blocked list it can't have a valid lvb,
+		 * so skip it
+		 */
+		if (ml->list == DLM_BLOCKED_LIST)
+			goto skip_lvb;
 
 		if (!dlm_lvb_is_empty(mres->lvb)) {
 			if (lksb->flags & DLM_LKSB_PUT_LVB) {
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c
index 12ae194..3a44a64 100644
--- a/fs/ocfs2/dlmglue.c
+++ b/fs/ocfs2/dlmglue.c
@@ -2322,7 +2322,7 @@ int ocfs2_inode_lock_full_nested(struct inode *inode,
 	status = __ocfs2_cluster_lock(osb, lockres, level, dlm_flags,
 				      arg_flags, subclass, _RET_IP_);
 	if (status < 0) {
-		if (status != -EAGAIN && status != -EIOCBRETRY)
+		if (status != -EAGAIN)
 			mlog_errno(status);
 		goto bail;
 	}
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index 6474cb4..8a7509f 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -2248,8 +2248,6 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
 	if (iocb->ki_left == 0)
 		return 0;
 
-	sb_start_write(inode->i_sb);
-
 	appending = file->f_flags & O_APPEND ? 1 : 0;
 	direct_io = file->f_flags & O_DIRECT ? 1 : 0;
 
@@ -2423,7 +2421,6 @@ out_sems:
 		ocfs2_iocb_clear_sem_locked(iocb);
 
 	mutex_unlock(&inode->i_mutex);
-	sb_end_write(inode->i_sb);
 
 	if (written)
 		ret = written;
@@ -2468,8 +2465,7 @@ static ssize_t ocfs2_file_splice_write(struct pipe_inode_info *pipe,
 			out->f_path.dentry->d_name.len,
 			out->f_path.dentry->d_name.name, len);
 
-	if (pipe->inode)
-		mutex_lock_nested(&pipe->inode->i_mutex, I_MUTEX_PARENT);
+	pipe_lock(pipe);
 
 	splice_from_pipe_begin(&sd);
 	do {
@@ -2489,8 +2485,7 @@ static ssize_t ocfs2_file_splice_write(struct pipe_inode_info *pipe,
 	} while (ret > 0);
 	splice_from_pipe_end(pipe, &sd);
 
-	if (pipe->inode)
-		mutex_unlock(&pipe->inode->i_mutex);
+	pipe_unlock(pipe);
 
 	if (sd.num_spliced)
 		ret = sd.num_spliced;
diff --git a/fs/ocfs2/inode.h b/fs/ocfs2/inode.h
index 88924a3..c765bdf 100644
--- a/fs/ocfs2/inode.h
+++ b/fs/ocfs2/inode.h
@@ -28,6 +28,8 @@
 
 #include "extent_map.h"
 
+struct iocb;
+
 /* OCFS2 Inode Private Data */
 struct ocfs2_inode_info
 {
diff --git a/fs/ocfs2/ioctl.c b/fs/ocfs2/ioctl.c
index 752f0b2..6cab301 100644
--- a/fs/ocfs2/ioctl.c
+++ b/fs/ocfs2/ioctl.c
@@ -101,13 +101,6 @@ static int ocfs2_set_inode_attr(struct inode *inode, unsigned flags,
 	if (!S_ISDIR(inode->i_mode))
 		flags &= ~OCFS2_DIRSYNC_FL;
 
-	handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
-	if (IS_ERR(handle)) {
-		status = PTR_ERR(handle);
-		mlog_errno(status);
-		goto bail_unlock;
-	}
-
 	oldflags = ocfs2_inode->ip_attr;
 	flags = flags & mask;
 	flags |= oldflags & ~mask;
@@ -120,7 +113,14 @@ static int ocfs2_set_inode_attr(struct inode *inode, unsigned flags,
 	if ((oldflags & OCFS2_IMMUTABLE_FL) || ((flags ^ oldflags) &
 		(OCFS2_APPEND_FL | OCFS2_IMMUTABLE_FL))) {
 		if (!capable(CAP_LINUX_IMMUTABLE))
-			goto bail_commit;
+			goto bail_unlock;
+	}
+
+	handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
+	if (IS_ERR(handle)) {
+		status = PTR_ERR(handle);
+		mlog_errno(status);
+		goto bail_unlock;
 	}
 
 	ocfs2_inode->ip_attr = flags;
@@ -130,8 +130,8 @@ static int ocfs2_set_inode_attr(struct inode *inode, unsigned flags,
 	if (status < 0)
 		mlog_errno(status);
 
-bail_commit:
 	ocfs2_commit_trans(osb, handle);
+
 bail_unlock:
 	ocfs2_inode_unlock(inode, 1);
 bail:
diff --git a/fs/open.c b/fs/open.c
index 6835446..8c74100 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -197,10 +197,7 @@ out:
 
 SYSCALL_DEFINE2(ftruncate, unsigned int, fd, unsigned long, length)
 {
-	long ret = do_sys_ftruncate(fd, length, 1);
-	/* avoid REGPARM breakage on x86: */
-	asmlinkage_protect(2, ret, fd, length);
-	return ret;
+	return do_sys_ftruncate(fd, length, 1);
 }
 
 #ifdef CONFIG_COMPAT
@@ -212,32 +209,15 @@ COMPAT_SYSCALL_DEFINE2(ftruncate, unsigned int, fd, compat_ulong_t, length)
 
 /* LFS versions of truncate are only needed on 32 bit machines */
 #if BITS_PER_LONG == 32
-SYSCALL_DEFINE(truncate64)(const char __user * path, loff_t length)
+SYSCALL_DEFINE2(truncate64, const char __user *, path, loff_t, length)
 {
 	return do_sys_truncate(path, length);
 }
-#ifdef CONFIG_HAVE_SYSCALL_WRAPPERS
-asmlinkage long SyS_truncate64(long path, loff_t length)
-{
-	return SYSC_truncate64((const char __user *) path, length);
-}
-SYSCALL_ALIAS(sys_truncate64, SyS_truncate64);
-#endif
 
-SYSCALL_DEFINE(ftruncate64)(unsigned int fd, loff_t length)
+SYSCALL_DEFINE2(ftruncate64, unsigned int, fd, loff_t, length)
 {
-	long ret = do_sys_ftruncate(fd, length, 0);
-	/* avoid REGPARM breakage on x86: */
-	asmlinkage_protect(2, ret, fd, length);
-	return ret;
-}
-#ifdef CONFIG_HAVE_SYSCALL_WRAPPERS
-asmlinkage long SyS_ftruncate64(long fd, loff_t length)
-{
-	return SYSC_ftruncate64((unsigned int) fd, length);
+	return do_sys_ftruncate(fd, length, 0);
 }
-SYSCALL_ALIAS(sys_ftruncate64, SyS_ftruncate64);
-#endif
 #endif /* BITS_PER_LONG == 32 */
 
 
@@ -299,7 +279,7 @@ int do_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
 	return ret;
 }
 
-SYSCALL_DEFINE(fallocate)(int fd, int mode, loff_t offset, loff_t len)
+SYSCALL_DEFINE4(fallocate, int, fd, int, mode, loff_t, offset, loff_t, len)
 {
 	struct fd f = fdget(fd);
 	int error = -EBADF;
@@ -311,14 +291,6 @@ SYSCALL_DEFINE(fallocate)(int fd, int mode, loff_t offset, loff_t len)
 	return error;
 }
 
-#ifdef CONFIG_HAVE_SYSCALL_WRAPPERS
-asmlinkage long SyS_fallocate(long fd, long mode, loff_t offset, loff_t len)
-{
-	return SYSC_fallocate((int)fd, (int)mode, offset, len);
-}
-SYSCALL_ALIAS(sys_fallocate, SyS_fallocate);
-#endif
-
 /*
  * access() needs to use the real uid/gid, not the effective uid/gid.
  * We do this by temporarily clearing all FS-related capabilities and
@@ -983,29 +955,19 @@ long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode)
 
 SYSCALL_DEFINE3(open, const char __user *, filename, int, flags, umode_t, mode)
 {
-	long ret;
-
 	if (force_o_largefile())
 		flags |= O_LARGEFILE;
 
-	ret = do_sys_open(AT_FDCWD, filename, flags, mode);
-	/* avoid REGPARM breakage on x86: */
-	asmlinkage_protect(3, ret, filename, flags, mode);
-	return ret;
+	return do_sys_open(AT_FDCWD, filename, flags, mode);
 }
 
 SYSCALL_DEFINE4(openat, int, dfd, const char __user *, filename, int, flags,
 		umode_t, mode)
 {
-	long ret;
-
 	if (force_o_largefile())
 		flags |= O_LARGEFILE;
 
-	ret = do_sys_open(dfd, filename, flags, mode);
-	/* avoid REGPARM breakage on x86: */
-	asmlinkage_protect(4, ret, dfd, filename, flags, mode);
-	return ret;
+	return do_sys_open(dfd, filename, flags, mode);
 }
 
 #ifndef __alpha__
diff --git a/fs/pipe.c b/fs/pipe.c
index 2234f3f..b499f3b 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -21,10 +21,13 @@
 #include <linux/audit.h>
 #include <linux/syscalls.h>
 #include <linux/fcntl.h>
+#include <linux/aio.h>
 
 #include <asm/uaccess.h>
 #include <asm/ioctls.h>
 
+#include "internal.h"
+
 /*
  * The max size that a non-root user is allowed to grow the pipe. Can
  * be set by root in /proc/sys/fs/pipe-max-size
@@ -53,8 +56,8 @@ unsigned int pipe_min_size = PAGE_SIZE;
 
 static void pipe_lock_nested(struct pipe_inode_info *pipe, int subclass)
 {
-	if (pipe->inode)
-		mutex_lock_nested(&pipe->inode->i_mutex, subclass);
+	if (pipe->files)
+		mutex_lock_nested(&pipe->mutex, subclass);
 }
 
 void pipe_lock(struct pipe_inode_info *pipe)
@@ -68,11 +71,21 @@ EXPORT_SYMBOL(pipe_lock);
 
 void pipe_unlock(struct pipe_inode_info *pipe)
 {
-	if (pipe->inode)
-		mutex_unlock(&pipe->inode->i_mutex);
+	if (pipe->files)
+		mutex_unlock(&pipe->mutex);
 }
 EXPORT_SYMBOL(pipe_unlock);
 
+static inline void __pipe_lock(struct pipe_inode_info *pipe)
+{
+	mutex_lock_nested(&pipe->mutex, I_MUTEX_PARENT);
+}
+
+static inline void __pipe_unlock(struct pipe_inode_info *pipe)
+{
+	mutex_unlock(&pipe->mutex);
+}
+
 void pipe_double_lock(struct pipe_inode_info *pipe1,
 		      struct pipe_inode_info *pipe2)
 {
@@ -361,8 +374,7 @@ pipe_read(struct kiocb *iocb, const struct iovec *_iov,
 	   unsigned long nr_segs, loff_t pos)
 {
 	struct file *filp = iocb->ki_filp;
-	struct inode *inode = file_inode(filp);
-	struct pipe_inode_info *pipe;
+	struct pipe_inode_info *pipe = filp->private_data;
 	int do_wakeup;
 	ssize_t ret;
 	struct iovec *iov = (struct iovec *)_iov;
@@ -375,8 +387,7 @@ pipe_read(struct kiocb *iocb, const struct iovec *_iov,
 
 	do_wakeup = 0;
 	ret = 0;
-	mutex_lock(&inode->i_mutex);
-	pipe = inode->i_pipe;
+	__pipe_lock(pipe);
 	for (;;) {
 		int bufs = pipe->nrbufs;
 		if (bufs) {
@@ -464,7 +475,7 @@ redo:
 		}
 		pipe_wait(pipe);
 	}
-	mutex_unlock(&inode->i_mutex);
+	__pipe_unlock(pipe);
 
 	/* Signal writers asynchronously that there is more room. */
 	if (do_wakeup) {
@@ -486,8 +497,7 @@ pipe_write(struct kiocb *iocb, const struct iovec *_iov,
 	    unsigned long nr_segs, loff_t ppos)
 {
 	struct file *filp = iocb->ki_filp;
-	struct inode *inode = file_inode(filp);
-	struct pipe_inode_info *pipe;
+	struct pipe_inode_info *pipe = filp->private_data;
 	ssize_t ret;
 	int do_wakeup;
 	struct iovec *iov = (struct iovec *)_iov;
@@ -501,8 +511,7 @@ pipe_write(struct kiocb *iocb, const struct iovec *_iov,
 
 	do_wakeup = 0;
 	ret = 0;
-	mutex_lock(&inode->i_mutex);
-	pipe = inode->i_pipe;
+	__pipe_lock(pipe);
 
 	if (!pipe->readers) {
 		send_sig(SIGPIPE, current, 0);
@@ -649,7 +658,7 @@ redo2:
 		pipe->waiting_writers--;
 	}
 out:
-	mutex_unlock(&inode->i_mutex);
+	__pipe_unlock(pipe);
 	if (do_wakeup) {
 		wake_up_interruptible_sync_poll(&pipe->wait, POLLIN | POLLRDNORM);
 		kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
@@ -662,29 +671,14 @@ out:
 	return ret;
 }
 
-static ssize_t
-bad_pipe_r(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
-{
-	return -EBADF;
-}
-
-static ssize_t
-bad_pipe_w(struct file *filp, const char __user *buf, size_t count,
-	   loff_t *ppos)
-{
-	return -EBADF;
-}
-
 static long pipe_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
-	struct inode *inode = file_inode(filp);
-	struct pipe_inode_info *pipe;
+	struct pipe_inode_info *pipe = filp->private_data;
 	int count, buf, nrbufs;
 
 	switch (cmd) {
 		case FIONREAD:
-			mutex_lock(&inode->i_mutex);
-			pipe = inode->i_pipe;
+			__pipe_lock(pipe);
 			count = 0;
 			buf = pipe->curbuf;
 			nrbufs = pipe->nrbufs;
@@ -692,7 +686,7 @@ static long pipe_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 				count += pipe->bufs[buf].len;
 				buf = (buf+1) & (pipe->buffers - 1);
 			}
-			mutex_unlock(&inode->i_mutex);
+			__pipe_unlock(pipe);
 
 			return put_user(count, (int __user *)arg);
 		default:
@@ -705,8 +699,7 @@ static unsigned int
 pipe_poll(struct file *filp, poll_table *wait)
 {
 	unsigned int mask;
-	struct inode *inode = file_inode(filp);
-	struct pipe_inode_info *pipe = inode->i_pipe;
+	struct pipe_inode_info *pipe = filp->private_data;
 	int nrbufs;
 
 	poll_wait(filp, &pipe->wait, wait);
@@ -734,197 +727,56 @@ pipe_poll(struct file *filp, poll_table *wait)
 }
 
 static int
-pipe_release(struct inode *inode, int decr, int decw)
+pipe_release(struct inode *inode, struct file *file)
 {
-	struct pipe_inode_info *pipe;
+	struct pipe_inode_info *pipe = inode->i_pipe;
+	int kill = 0;
 
-	mutex_lock(&inode->i_mutex);
-	pipe = inode->i_pipe;
-	pipe->readers -= decr;
-	pipe->writers -= decw;
+	__pipe_lock(pipe);
+	if (file->f_mode & FMODE_READ)
+		pipe->readers--;
+	if (file->f_mode & FMODE_WRITE)
+		pipe->writers--;
 
-	if (!pipe->readers && !pipe->writers) {
-		free_pipe_info(inode);
-	} else {
+	if (pipe->readers || pipe->writers) {
 		wake_up_interruptible_sync_poll(&pipe->wait, POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM | POLLERR | POLLHUP);
 		kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
 		kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
 	}
-	mutex_unlock(&inode->i_mutex);
-
-	return 0;
-}
-
-static int
-pipe_read_fasync(int fd, struct file *filp, int on)
-{
-	struct inode *inode = file_inode(filp);
-	int retval;
-
-	mutex_lock(&inode->i_mutex);
-	retval = fasync_helper(fd, filp, on, &inode->i_pipe->fasync_readers);
-	mutex_unlock(&inode->i_mutex);
-
-	return retval;
-}
-
-
-static int
-pipe_write_fasync(int fd, struct file *filp, int on)
-{
-	struct inode *inode = file_inode(filp);
-	int retval;
+	spin_lock(&inode->i_lock);
+	if (!--pipe->files) {
+		inode->i_pipe = NULL;
+		kill = 1;
+	}
+	spin_unlock(&inode->i_lock);
+	__pipe_unlock(pipe);
 
-	mutex_lock(&inode->i_mutex);
-	retval = fasync_helper(fd, filp, on, &inode->i_pipe->fasync_writers);
-	mutex_unlock(&inode->i_mutex);
+	if (kill)
+		free_pipe_info(pipe);
 
-	return retval;
+	return 0;
 }
 
-
 static int
-pipe_rdwr_fasync(int fd, struct file *filp, int on)
+pipe_fasync(int fd, struct file *filp, int on)
 {
-	struct inode *inode = file_inode(filp);
-	struct pipe_inode_info *pipe = inode->i_pipe;
-	int retval;
+	struct pipe_inode_info *pipe = filp->private_data;
+	int retval = 0;
 
-	mutex_lock(&inode->i_mutex);
-	retval = fasync_helper(fd, filp, on, &pipe->fasync_readers);
-	if (retval >= 0) {
+	__pipe_lock(pipe);
+	if (filp->f_mode & FMODE_READ)
+		retval = fasync_helper(fd, filp, on, &pipe->fasync_readers);
+	if ((filp->f_mode & FMODE_WRITE) && retval >= 0) {
 		retval = fasync_helper(fd, filp, on, &pipe->fasync_writers);
-		if (retval < 0) /* this can happen only if on == T */
+		if (retval < 0 && (filp->f_mode & FMODE_READ))
+			/* this can happen only if on == T */
 			fasync_helper(-1, filp, 0, &pipe->fasync_readers);
 	}
-	mutex_unlock(&inode->i_mutex);
+	__pipe_unlock(pipe);
 	return retval;
 }
 
-
-static int
-pipe_read_release(struct inode *inode, struct file *filp)
-{
-	return pipe_release(inode, 1, 0);
-}
-
-static int
-pipe_write_release(struct inode *inode, struct file *filp)
-{
-	return pipe_release(inode, 0, 1);
-}
-
-static int
-pipe_rdwr_release(struct inode *inode, struct file *filp)
-{
-	int decr, decw;
-
-	decr = (filp->f_mode & FMODE_READ) != 0;
-	decw = (filp->f_mode & FMODE_WRITE) != 0;
-	return pipe_release(inode, decr, decw);
-}
-
-static int
-pipe_read_open(struct inode *inode, struct file *filp)
-{
-	int ret = -ENOENT;
-
-	mutex_lock(&inode->i_mutex);
-
-	if (inode->i_pipe) {
-		ret = 0;
-		inode->i_pipe->readers++;
-	}
-
-	mutex_unlock(&inode->i_mutex);
-
-	return ret;
-}
-
-static int
-pipe_write_open(struct inode *inode, struct file *filp)
-{
-	int ret = -ENOENT;
-
-	mutex_lock(&inode->i_mutex);
-
-	if (inode->i_pipe) {
-		ret = 0;
-		inode->i_pipe->writers++;
-	}
-
-	mutex_unlock(&inode->i_mutex);
-
-	return ret;
-}
-
-static int
-pipe_rdwr_open(struct inode *inode, struct file *filp)
-{
-	int ret = -ENOENT;
-
-	if (!(filp->f_mode & (FMODE_READ|FMODE_WRITE)))
-		return -EINVAL;
-
-	mutex_lock(&inode->i_mutex);
-
-	if (inode->i_pipe) {
-		ret = 0;
-		if (filp->f_mode & FMODE_READ)
-			inode->i_pipe->readers++;
-		if (filp->f_mode & FMODE_WRITE)
-			inode->i_pipe->writers++;
-	}
-
-	mutex_unlock(&inode->i_mutex);
-
-	return ret;
-}
-
-/*
- * The file_operations structs are not static because they
- * are also used in linux/fs/fifo.c to do operations on FIFOs.
- *
- * Pipes reuse fifos' file_operations structs.
- */
-const struct file_operations read_pipefifo_fops = {
-	.llseek		= no_llseek,
-	.read		= do_sync_read,
-	.aio_read	= pipe_read,
-	.write		= bad_pipe_w,
-	.poll		= pipe_poll,
-	.unlocked_ioctl	= pipe_ioctl,
-	.open		= pipe_read_open,
-	.release	= pipe_read_release,
-	.fasync		= pipe_read_fasync,
-};
-
-const struct file_operations write_pipefifo_fops = {
-	.llseek		= no_llseek,
-	.read		= bad_pipe_r,
-	.write		= do_sync_write,
-	.aio_write	= pipe_write,
-	.poll		= pipe_poll,
-	.unlocked_ioctl	= pipe_ioctl,
-	.open		= pipe_write_open,
-	.release	= pipe_write_release,
-	.fasync		= pipe_write_fasync,
-};
-
-const struct file_operations rdwr_pipefifo_fops = {
-	.llseek		= no_llseek,
-	.read		= do_sync_read,
-	.aio_read	= pipe_read,
-	.write		= do_sync_write,
-	.aio_write	= pipe_write,
-	.poll		= pipe_poll,
-	.unlocked_ioctl	= pipe_ioctl,
-	.open		= pipe_rdwr_open,
-	.release	= pipe_rdwr_release,
-	.fasync		= pipe_rdwr_fasync,
-};
-
-struct pipe_inode_info * alloc_pipe_info(struct inode *inode)
+struct pipe_inode_info *alloc_pipe_info(void)
 {
 	struct pipe_inode_info *pipe;
 
@@ -934,8 +786,8 @@ struct pipe_inode_info * alloc_pipe_info(struct inode *inode)
 		if (pipe->bufs) {
 			init_waitqueue_head(&pipe->wait);
 			pipe->r_counter = pipe->w_counter = 1;
-			pipe->inode = inode;
 			pipe->buffers = PIPE_DEF_BUFFERS;
+			mutex_init(&pipe->mutex);
 			return pipe;
 		}
 		kfree(pipe);
@@ -944,7 +796,7 @@ struct pipe_inode_info * alloc_pipe_info(struct inode *inode)
 	return NULL;
 }
 
-void __free_pipe_info(struct pipe_inode_info *pipe)
+void free_pipe_info(struct pipe_inode_info *pipe)
 {
 	int i;
 
@@ -959,12 +811,6 @@ void __free_pipe_info(struct pipe_inode_info *pipe)
 	kfree(pipe);
 }
 
-void free_pipe_info(struct inode *inode)
-{
-	__free_pipe_info(inode->i_pipe);
-	inode->i_pipe = NULL;
-}
-
 static struct vfsmount *pipe_mnt __read_mostly;
 
 /*
@@ -990,13 +836,14 @@ static struct inode * get_pipe_inode(void)
 
 	inode->i_ino = get_next_ino();
 
-	pipe = alloc_pipe_info(inode);
+	pipe = alloc_pipe_info();
 	if (!pipe)
 		goto fail_iput;
-	inode->i_pipe = pipe;
 
+	inode->i_pipe = pipe;
+	pipe->files = 2;
 	pipe->readers = pipe->writers = 1;
-	inode->i_fop = &rdwr_pipefifo_fops;
+	inode->i_fop = &pipefifo_fops;
 
 	/*
 	 * Mark the inode dirty from the very beginning,
@@ -1039,17 +886,19 @@ int create_pipe_files(struct file **res, int flags)
 	d_instantiate(path.dentry, inode);
 
 	err = -ENFILE;
-	f = alloc_file(&path, FMODE_WRITE, &write_pipefifo_fops);
+	f = alloc_file(&path, FMODE_WRITE, &pipefifo_fops);
 	if (IS_ERR(f))
 		goto err_dentry;
 
 	f->f_flags = O_WRONLY | (flags & (O_NONBLOCK | O_DIRECT));
+	f->private_data = inode->i_pipe;
 
-	res[0] = alloc_file(&path, FMODE_READ, &read_pipefifo_fops);
+	res[0] = alloc_file(&path, FMODE_READ, &pipefifo_fops);
 	if (IS_ERR(res[0]))
 		goto err_file;
 
 	path_get(&path);
+	res[0]->private_data = inode->i_pipe;
 	res[0]->f_flags = O_RDONLY | (flags & O_NONBLOCK);
 	res[1] = f;
 	return 0;
@@ -1057,12 +906,12 @@ int create_pipe_files(struct file **res, int flags)
 err_file:
 	put_filp(f);
 err_dentry:
-	free_pipe_info(inode);
+	free_pipe_info(inode->i_pipe);
 	path_put(&path);
 	return err;
 
 err_inode:
-	free_pipe_info(inode);
+	free_pipe_info(inode->i_pipe);
 	iput(inode);
 	return err;
 }
@@ -1144,6 +993,167 @@ SYSCALL_DEFINE1(pipe, int __user *, fildes)
 	return sys_pipe2(fildes, 0);
 }
 
+static int wait_for_partner(struct pipe_inode_info *pipe, unsigned int *cnt)
+{
+	int cur = *cnt;	
+
+	while (cur == *cnt) {
+		pipe_wait(pipe);
+		if (signal_pending(current))
+			break;
+	}
+	return cur == *cnt ? -ERESTARTSYS : 0;
+}
+
+static void wake_up_partner(struct pipe_inode_info *pipe)
+{
+	wake_up_interruptible(&pipe->wait);
+}
+
+static int fifo_open(struct inode *inode, struct file *filp)
+{
+	struct pipe_inode_info *pipe;
+	int kill = 0;
+	int ret;
+
+	filp->f_version = 0;
+
+	spin_lock(&inode->i_lock);
+	if (inode->i_pipe) {
+		pipe = inode->i_pipe;
+		pipe->files++;
+		spin_unlock(&inode->i_lock);
+	} else {
+		spin_unlock(&inode->i_lock);
+		pipe = alloc_pipe_info();
+		if (!pipe)
+			return -ENOMEM;
+		pipe->files = 1;
+		spin_lock(&inode->i_lock);
+		if (unlikely(inode->i_pipe)) {
+			inode->i_pipe->files++;
+			spin_unlock(&inode->i_lock);
+			free_pipe_info(pipe);
+			pipe = inode->i_pipe;
+		} else {
+			inode->i_pipe = pipe;
+			spin_unlock(&inode->i_lock);
+		}
+	}
+	filp->private_data = pipe;
+	/* OK, we have a pipe and it's pinned down */
+
+	__pipe_lock(pipe);
+
+	/* We can only do regular read/write on fifos */
+	filp->f_mode &= (FMODE_READ | FMODE_WRITE);
+
+	switch (filp->f_mode) {
+	case FMODE_READ:
+	/*
+	 *  O_RDONLY
+	 *  POSIX.1 says that O_NONBLOCK means return with the FIFO
+	 *  opened, even when there is no process writing the FIFO.
+	 */
+		pipe->r_counter++;
+		if (pipe->readers++ == 0)
+			wake_up_partner(pipe);
+
+		if (!pipe->writers) {
+			if ((filp->f_flags & O_NONBLOCK)) {
+				/* suppress POLLHUP until we have
+				 * seen a writer */
+				filp->f_version = pipe->w_counter;
+			} else {
+				if (wait_for_partner(pipe, &pipe->w_counter))
+					goto err_rd;
+			}
+		}
+		break;
+	
+	case FMODE_WRITE:
+	/*
+	 *  O_WRONLY
+	 *  POSIX.1 says that O_NONBLOCK means return -1 with
+	 *  errno=ENXIO when there is no process reading the FIFO.
+	 */
+		ret = -ENXIO;
+		if ((filp->f_flags & O_NONBLOCK) && !pipe->readers)
+			goto err;
+
+		pipe->w_counter++;
+		if (!pipe->writers++)
+			wake_up_partner(pipe);
+
+		if (!pipe->readers) {
+			if (wait_for_partner(pipe, &pipe->r_counter))
+				goto err_wr;
+		}
+		break;
+	
+	case FMODE_READ | FMODE_WRITE:
+	/*
+	 *  O_RDWR
+	 *  POSIX.1 leaves this case "undefined" when O_NONBLOCK is set.
+	 *  This implementation will NEVER block on a O_RDWR open, since
+	 *  the process can at least talk to itself.
+	 */
+
+		pipe->readers++;
+		pipe->writers++;
+		pipe->r_counter++;
+		pipe->w_counter++;
+		if (pipe->readers == 1 || pipe->writers == 1)
+			wake_up_partner(pipe);
+		break;
+
+	default:
+		ret = -EINVAL;
+		goto err;
+	}
+
+	/* Ok! */
+	__pipe_unlock(pipe);
+	return 0;
+
+err_rd:
+	if (!--pipe->readers)
+		wake_up_interruptible(&pipe->wait);
+	ret = -ERESTARTSYS;
+	goto err;
+
+err_wr:
+	if (!--pipe->writers)
+		wake_up_interruptible(&pipe->wait);
+	ret = -ERESTARTSYS;
+	goto err;
+
+err:
+	spin_lock(&inode->i_lock);
+	if (!--pipe->files) {
+		inode->i_pipe = NULL;
+		kill = 1;
+	}
+	spin_unlock(&inode->i_lock);
+	__pipe_unlock(pipe);
+	if (kill)
+		free_pipe_info(pipe);
+	return ret;
+}
+
+const struct file_operations pipefifo_fops = {
+	.open		= fifo_open,
+	.llseek		= no_llseek,
+	.read		= do_sync_read,
+	.aio_read	= pipe_read,
+	.write		= do_sync_write,
+	.aio_write	= pipe_write,
+	.poll		= pipe_poll,
+	.unlocked_ioctl	= pipe_ioctl,
+	.release	= pipe_release,
+	.fasync		= pipe_fasync,
+};
+
 /*
  * Allocate a new array of pipe buffers and copy the info over. Returns the
  * pipe size if successful, or return -ERROR on error.
@@ -1229,9 +1239,7 @@ int pipe_proc_fn(struct ctl_table *table, int write, void __user *buf,
  */
 struct pipe_inode_info *get_pipe_info(struct file *file)
 {
-	struct inode *i = file_inode(file);
-
-	return S_ISFIFO(i->i_mode) ? i->i_pipe : NULL;
+	return file->f_op == &pipefifo_fops ? file->private_data : NULL;
 }
 
 long pipe_fcntl(struct file *file, unsigned int cmd, unsigned long arg)
@@ -1243,7 +1251,7 @@ long pipe_fcntl(struct file *file, unsigned int cmd, unsigned long arg)
 	if (!pipe)
 		return -EBADF;
 
-	mutex_lock(&pipe->inode->i_mutex);
+	__pipe_lock(pipe);
 
 	switch (cmd) {
 	case F_SETPIPE_SZ: {
@@ -1272,7 +1280,7 @@ long pipe_fcntl(struct file *file, unsigned int cmd, unsigned long arg)
 	}
 
 out:
-	mutex_unlock(&pipe->inode->i_mutex);
+	__pipe_unlock(pipe);
 	return ret;
 }
 
diff --git a/fs/pnode.c b/fs/pnode.c
index 8b29d21..3d2a714 100644
--- a/fs/pnode.c
+++ b/fs/pnode.c
@@ -218,7 +218,7 @@ static struct mount *get_source(struct mount *dest,
  * @source_mnt: source mount.
  * @tree_list : list of heads of trees to be attached.
  */
-int propagate_mnt(struct mount *dest_mnt, struct dentry *dest_dentry,
+int propagate_mnt(struct mount *dest_mnt, struct mountpoint *dest_mp,
 		    struct mount *source_mnt, struct list_head *tree_list)
 {
 	struct user_namespace *user_ns = current->nsproxy->mnt_ns->user_ns;
@@ -227,7 +227,6 @@ int propagate_mnt(struct mount *dest_mnt, struct dentry *dest_dentry,
 	struct mount *prev_dest_mnt = dest_mnt;
 	struct mount *prev_src_mnt  = source_mnt;
 	LIST_HEAD(tmp_list);
-	LIST_HEAD(umount_list);
 
 	for (m = propagation_next(dest_mnt, dest_mnt); m;
 			m = propagation_next(m, dest_mnt)) {
@@ -250,8 +249,8 @@ int propagate_mnt(struct mount *dest_mnt, struct dentry *dest_dentry,
 			goto out;
 		}
 
-		if (is_subdir(dest_dentry, m->mnt.mnt_root)) {
-			mnt_set_mountpoint(m, dest_dentry, child);
+		if (is_subdir(dest_mp->m_dentry, m->mnt.mnt_root)) {
+			mnt_set_mountpoint(m, dest_mp, child);
 			list_add_tail(&child->mnt_hash, tree_list);
 		} else {
 			/*
@@ -267,10 +266,9 @@ out:
 	br_write_lock(&vfsmount_lock);
 	while (!list_empty(&tmp_list)) {
 		child = list_first_entry(&tmp_list, struct mount, mnt_hash);
-		umount_tree(child, 0, &umount_list);
+		umount_tree(child, 0);
 	}
 	br_write_unlock(&vfsmount_lock);
-	release_mounts(&umount_list);
 	return ret;
 }
 
diff --git a/fs/pnode.h b/fs/pnode.h
index a0493d5..b091445 100644
--- a/fs/pnode.h
+++ b/fs/pnode.h
@@ -32,17 +32,16 @@ static inline void set_mnt_shared(struct mount *mnt)
 }
 
 void change_mnt_propagation(struct mount *, int);
-int propagate_mnt(struct mount *, struct dentry *, struct mount *,
+int propagate_mnt(struct mount *, struct mountpoint *, struct mount *,
 		struct list_head *);
 int propagate_umount(struct list_head *);
 int propagate_mount_busy(struct mount *, int);
 void mnt_release_group_id(struct mount *);
 int get_dominating_id(struct mount *mnt, const struct path *root);
 unsigned int mnt_get_count(struct mount *mnt);
-void mnt_set_mountpoint(struct mount *, struct dentry *,
+void mnt_set_mountpoint(struct mount *, struct mountpoint *,
 			struct mount *);
-void release_mounts(struct list_head *);
-void umount_tree(struct mount *, int, struct list_head *);
+void umount_tree(struct mount *, int);
 struct mount *copy_tree(struct mount *, struct dentry *, int);
 bool is_path_reachable(struct mount *, struct dentry *,
 			 const struct path *root);
diff --git a/fs/proc/Makefile b/fs/proc/Makefile
index 712f24d..ab30716 100644
--- a/fs/proc/Makefile
+++ b/fs/proc/Makefile
@@ -5,7 +5,7 @@
 obj-y   += proc.o
 
 proc-y			:= nommu.o task_nommu.o
-proc-$(CONFIG_MMU)	:= mmu.o task_mmu.o
+proc-$(CONFIG_MMU)	:= task_mmu.o
 
 proc-y       += inode.o root.o base.o generic.o array.o \
 		fd.o
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 69078c7..593e7c5 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -2794,7 +2794,7 @@ retry:
 	return iter;
 }
 
-#define TGID_OFFSET (FIRST_PROCESS_ENTRY)
+#define TGID_OFFSET (FIRST_PROCESS_ENTRY + 1)
 
 static int proc_pid_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
 	struct tgid_iter iter)
@@ -2817,13 +2817,21 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir)
 	struct tgid_iter iter;
 	struct pid_namespace *ns;
 	filldir_t __filldir;
+	loff_t pos = filp->f_pos;
 
-	if (filp->f_pos >= PID_MAX_LIMIT + TGID_OFFSET)
+	if (pos >= PID_MAX_LIMIT + TGID_OFFSET)
 		goto out;
 
-	ns = filp->f_dentry->d_sb->s_fs_info;
+	if (pos == TGID_OFFSET - 1) {
+		if (proc_fill_cache(filp, dirent, filldir, "self", 4,
+					NULL, NULL, NULL) < 0)
+			goto out;
+		iter.tgid = 0;
+	} else {
+		iter.tgid = pos - TGID_OFFSET;
+	}
 	iter.task = NULL;
-	iter.tgid = filp->f_pos - TGID_OFFSET;
+	ns = filp->f_dentry->d_sb->s_fs_info;
 	for (iter = next_tgid(ns, iter);
 	     iter.task;
 	     iter.tgid += 1, iter = next_tgid(ns, iter)) {
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index 4b3b3ff..c0ad720 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -196,30 +196,6 @@ proc_file_read(struct file *file, char __user *buf, size_t nbytes,
 	return rv;
 }
 
-static ssize_t
-proc_file_write(struct file *file, const char __user *buffer,
-		size_t count, loff_t *ppos)
-{
-	struct proc_dir_entry *pde = PDE(file_inode(file));
-	ssize_t rv = -EIO;
-
-	if (pde->write_proc) {
-		spin_lock(&pde->pde_unload_lock);
-		if (!pde->proc_fops) {
-			spin_unlock(&pde->pde_unload_lock);
-			return rv;
-		}
-		pde->pde_users++;
-		spin_unlock(&pde->pde_unload_lock);
-
-		/* FIXME: does this routine need ppos?  probably... */
-		rv = pde->write_proc(file, buffer, count, pde->data);
-		pde_users_dec(pde);
-	}
-	return rv;
-}
-
-
 static loff_t
 proc_file_lseek(struct file *file, loff_t offset, int orig)
 {
@@ -239,7 +215,6 @@ proc_file_lseek(struct file *file, loff_t offset, int orig)
 static const struct file_operations proc_file_operations = {
 	.llseek		= proc_file_lseek,
 	.read		= proc_file_read,
-	.write		= proc_file_write,
 };
 
 static int proc_notify_change(struct dentry *dentry, struct iattr *iattr)
@@ -371,7 +346,7 @@ void proc_free_inum(unsigned int inum)
 
 static void *proc_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
-	nd_set_link(nd, PDE(dentry->d_inode)->data);
+	nd_set_link(nd, PDE_DATA(dentry->d_inode));
 	return NULL;
 }
 
@@ -541,19 +516,18 @@ static int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp
 		return ret;
 
 	if (S_ISDIR(dp->mode)) {
-		if (dp->proc_iops == NULL) {
-			dp->proc_fops = &proc_dir_operations;
-			dp->proc_iops = &proc_dir_inode_operations;
-		}
+		dp->proc_fops = &proc_dir_operations;
+		dp->proc_iops = &proc_dir_inode_operations;
 		dir->nlink++;
 	} else if (S_ISLNK(dp->mode)) {
-		if (dp->proc_iops == NULL)
-			dp->proc_iops = &proc_link_inode_operations;
+		dp->proc_iops = &proc_link_inode_operations;
 	} else if (S_ISREG(dp->mode)) {
 		if (dp->proc_fops == NULL)
 			dp->proc_fops = &proc_file_operations;
-		if (dp->proc_iops == NULL)
-			dp->proc_iops = &proc_file_inode_operations;
+		dp->proc_iops = &proc_file_inode_operations;
+	} else {
+		WARN_ON(1);
+		return -EINVAL;
 	}
 
 	spin_lock(&proc_subdir_lock);
@@ -680,21 +654,19 @@ struct proc_dir_entry *create_proc_entry(const char *name, umode_t mode,
 					 struct proc_dir_entry *parent)
 {
 	struct proc_dir_entry *ent;
-	nlink_t nlink;
 
-	if (S_ISDIR(mode)) {
-		if ((mode & S_IALLUGO) == 0)
-			mode |= S_IRUGO | S_IXUGO;
-		nlink = 2;
-	} else {
-		if ((mode & S_IFMT) == 0)
-			mode |= S_IFREG;
-		if ((mode & S_IALLUGO) == 0)
-			mode |= S_IRUGO;
-		nlink = 1;
+	if ((mode & S_IFMT) == 0)
+		mode |= S_IFREG;
+
+	if (!S_ISREG(mode)) {
+		WARN_ON(1);	/* use proc_mkdir(), damnit */
+		return NULL;
 	}
 
-	ent = __proc_create(&parent, name, mode, nlink);
+	if ((mode & S_IALLUGO) == 0)
+		mode |= S_IRUGO;
+
+	ent = __proc_create(&parent, name, mode, 1);
 	if (ent) {
 		if (proc_register(parent, ent) < 0) {
 			kfree(ent);
@@ -711,21 +683,17 @@ struct proc_dir_entry *proc_create_data(const char *name, umode_t mode,
 					void *data)
 {
 	struct proc_dir_entry *pde;
-	nlink_t nlink;
+	if ((mode & S_IFMT) == 0)
+		mode |= S_IFREG;
 
-	if (S_ISDIR(mode)) {
-		if ((mode & S_IALLUGO) == 0)
-			mode |= S_IRUGO | S_IXUGO;
-		nlink = 2;
-	} else {
-		if ((mode & S_IFMT) == 0)
-			mode |= S_IFREG;
-		if ((mode & S_IALLUGO) == 0)
-			mode |= S_IRUGO;
-		nlink = 1;
+	if (!S_ISREG(mode)) {
+		WARN_ON(1);	/* use proc_mkdir() */
+		return NULL;
 	}
 
-	pde = __proc_create(&parent, name, mode, nlink);
+	if ((mode & S_IALLUGO) == 0)
+		mode |= S_IRUGO;
+	pde = __proc_create(&parent, name, mode, 1);
 	if (!pde)
 		goto out;
 	pde->proc_fops = proc_fops;
@@ -755,37 +723,8 @@ void pde_put(struct proc_dir_entry *pde)
 		free_proc_entry(pde);
 }
 
-/*
- * Remove a /proc entry and free it if it's not currently in use.
- */
-void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
+static void entry_rundown(struct proc_dir_entry *de)
 {
-	struct proc_dir_entry **p;
-	struct proc_dir_entry *de = NULL;
-	const char *fn = name;
-	unsigned int len;
-
-	spin_lock(&proc_subdir_lock);
-	if (__xlate_proc_name(name, &parent, &fn) != 0) {
-		spin_unlock(&proc_subdir_lock);
-		return;
-	}
-	len = strlen(fn);
-
-	for (p = &parent->subdir; *p; p=&(*p)->next ) {
-		if (proc_match(len, fn, *p)) {
-			de = *p;
-			*p = de->next;
-			de->next = NULL;
-			break;
-		}
-	}
-	spin_unlock(&proc_subdir_lock);
-	if (!de) {
-		WARN(1, "name '%s'\n", name);
-		return;
-	}
-
 	spin_lock(&de->pde_unload_lock);
 	/*
 	 * Stop accepting new callers into module. If you're
@@ -817,6 +756,40 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
 		spin_lock(&de->pde_unload_lock);
 	}
 	spin_unlock(&de->pde_unload_lock);
+}
+
+/*
+ * Remove a /proc entry and free it if it's not currently in use.
+ */
+void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
+{
+	struct proc_dir_entry **p;
+	struct proc_dir_entry *de = NULL;
+	const char *fn = name;
+	unsigned int len;
+
+	spin_lock(&proc_subdir_lock);
+	if (__xlate_proc_name(name, &parent, &fn) != 0) {
+		spin_unlock(&proc_subdir_lock);
+		return;
+	}
+	len = strlen(fn);
+
+	for (p = &parent->subdir; *p; p=&(*p)->next ) {
+		if (proc_match(len, fn, *p)) {
+			de = *p;
+			*p = de->next;
+			de->next = NULL;
+			break;
+		}
+	}
+	spin_unlock(&proc_subdir_lock);
+	if (!de) {
+		WARN(1, "name '%s'\n", name);
+		return;
+	}
+
+	entry_rundown(de);
 
 	if (S_ISDIR(de->mode))
 		parent->nlink--;
@@ -827,3 +800,57 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
 	pde_put(de);
 }
 EXPORT_SYMBOL(remove_proc_entry);
+
+int remove_proc_subtree(const char *name, struct proc_dir_entry *parent)
+{
+	struct proc_dir_entry **p;
+	struct proc_dir_entry *root = NULL, *de, *next;
+	const char *fn = name;
+	unsigned int len;
+
+	spin_lock(&proc_subdir_lock);
+	if (__xlate_proc_name(name, &parent, &fn) != 0) {
+		spin_unlock(&proc_subdir_lock);
+		return -ENOENT;
+	}
+	len = strlen(fn);
+
+	for (p = &parent->subdir; *p; p=&(*p)->next ) {
+		if (proc_match(len, fn, *p)) {
+			root = *p;
+			*p = root->next;
+			root->next = NULL;
+			break;
+		}
+	}
+	if (!root) {
+		spin_unlock(&proc_subdir_lock);
+		return -ENOENT;
+	}
+	de = root;
+	while (1) {
+		next = de->subdir;
+		if (next) {
+			de->subdir = next->next;
+			next->next = NULL;
+			de = next;
+			continue;
+		}
+		spin_unlock(&proc_subdir_lock);
+
+		entry_rundown(de);
+		next = de->parent;
+		if (S_ISDIR(de->mode))
+			next->nlink--;
+		de->nlink = 0;
+		if (de == root)
+			break;
+		pde_put(de);
+
+		spin_lock(&proc_subdir_lock);
+		de = next;
+	}
+	pde_put(root);
+	return 0;
+}
+EXPORT_SYMBOL(remove_proc_subtree);
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index 869116c..a4aaaee 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -462,8 +462,8 @@ struct inode *proc_get_inode(struct super_block *sb, struct proc_dir_entry *de)
 			inode->i_size = de->size;
 		if (de->nlink)
 			set_nlink(inode, de->nlink);
-		if (de->proc_iops)
-			inode->i_op = de->proc_iops;
+		WARN_ON(!de->proc_iops);
+		inode->i_op = de->proc_iops;
 		if (de->proc_fops) {
 			if (S_ISREG(inode->i_mode)) {
 #ifdef CONFIG_COMPAT
@@ -506,5 +506,5 @@ int proc_fill_super(struct super_block *s)
 		return -ENOMEM;
 	}
 
-	return 0;
+	return proc_setup_self(s);
 }
diff --git a/fs/proc/internal.h b/fs/proc/internal.h
index 85ff3a4..c3b7044 100644
--- a/fs/proc/internal.h
+++ b/fs/proc/internal.h
@@ -30,24 +30,6 @@ extern int proc_net_init(void);
 static inline int proc_net_init(void) { return 0; }
 #endif
 
-struct vmalloc_info {
-	unsigned long	used;
-	unsigned long	largest_chunk;
-};
-
-#ifdef CONFIG_MMU
-#define VMALLOC_TOTAL (VMALLOC_END - VMALLOC_START)
-extern void get_vmalloc_info(struct vmalloc_info *vmi);
-#else
-
-#define VMALLOC_TOTAL 0UL
-#define get_vmalloc_info(vmi)			\
-do {						\
-	(vmi)->used = 0;			\
-	(vmi)->largest_chunk = 0;		\
-} while(0)
-#endif
-
 extern int proc_tid_stat(struct seq_file *m, struct pid_namespace *ns,
 				struct pid *pid, struct task_struct *task);
 extern int proc_tgid_stat(struct seq_file *m, struct pid_namespace *ns,
@@ -205,3 +187,4 @@ int proc_setattr(struct dentry *dentry, struct iattr *attr);
 extern const struct inode_operations proc_ns_dir_inode_operations;
 extern const struct file_operations proc_ns_dir_operations;
 
+extern int proc_setup_self(struct super_block *);
diff --git a/fs/proc/meminfo.c b/fs/proc/meminfo.c
index 1efaaa1..5aa847a 100644
--- a/fs/proc/meminfo.c
+++ b/fs/proc/meminfo.c
@@ -11,6 +11,7 @@
 #include <linux/swap.h>
 #include <linux/vmstat.h>
 #include <linux/atomic.h>
+#include <linux/vmalloc.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include "internal.h"
diff --git a/fs/proc/mmu.c b/fs/proc/mmu.c
deleted file mode 100644
index 8ae221d..0000000
--- a/fs/proc/mmu.c
+++ /dev/null
@@ -1,60 +0,0 @@
-/* mmu.c: mmu memory info files
- *
- * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-#include <linux/spinlock.h>
-#include <linux/vmalloc.h>
-#include <linux/highmem.h>
-#include <asm/pgtable.h>
-#include "internal.h"
-
-void get_vmalloc_info(struct vmalloc_info *vmi)
-{
-	struct vm_struct *vma;
-	unsigned long free_area_size;
-	unsigned long prev_end;
-
-	vmi->used = 0;
-
-	if (!vmlist) {
-		vmi->largest_chunk = VMALLOC_TOTAL;
-	}
-	else {
-		vmi->largest_chunk = 0;
-
-		prev_end = VMALLOC_START;
-
-		read_lock(&vmlist_lock);
-
-		for (vma = vmlist; vma; vma = vma->next) {
-			unsigned long addr = (unsigned long) vma->addr;
-
-			/*
-			 * Some archs keep another range for modules in vmlist
-			 */
-			if (addr < VMALLOC_START)
-				continue;
-			if (addr >= VMALLOC_END)
-				break;
-
-			vmi->used += vma->size;
-
-			free_area_size = addr - prev_end;
-			if (vmi->largest_chunk < free_area_size)
-				vmi->largest_chunk = free_area_size;
-
-			prev_end = vma->size + addr;
-		}
-
-		if (VMALLOC_END - prev_end > vmi->largest_chunk)
-			vmi->largest_chunk = VMALLOC_END - prev_end;
-
-		read_unlock(&vmlist_lock);
-	}
-}
diff --git a/fs/proc/proc_devtree.c b/fs/proc/proc_devtree.c
index 30b590f..e0043c7 100644
--- a/fs/proc/proc_devtree.c
+++ b/fs/proc/proc_devtree.c
@@ -41,7 +41,7 @@ static int property_proc_show(struct seq_file *m, void *v)
 
 static int property_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, property_proc_show, PDE(inode)->data);
+	return single_open(file, property_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations property_proc_fops = {
diff --git a/fs/proc/root.c b/fs/proc/root.c
index 9c7fab1..04ec276 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -110,7 +110,8 @@ static struct dentry *proc_mount(struct file_system_type *fs_type,
 		ns = task_active_pid_ns(current);
 		options = data;
 
-		if (!current_user_ns()->may_mount_proc)
+		if (!current_user_ns()->may_mount_proc ||
+		    !ns_capable(ns->user_ns, CAP_SYS_ADMIN))
 			return ERR_PTR(-EPERM);
 	}
 
@@ -141,6 +142,8 @@ static void proc_kill_sb(struct super_block *sb)
 	struct pid_namespace *ns;
 
 	ns = (struct pid_namespace *)sb->s_fs_info;
+	if (ns->proc_self)
+		dput(ns->proc_self);
 	kill_anon_super(sb);
 	put_pid_ns(ns);
 }
diff --git a/fs/proc/self.c b/fs/proc/self.c
index aa5cc3b..21940d8 100644
--- a/fs/proc/self.c
+++ b/fs/proc/self.c
@@ -1,6 +1,7 @@
-#include <linux/proc_fs.h>
 #include <linux/sched.h>
 #include <linux/namei.h>
+#include <linux/pid_namespace.h>
+#include "internal.h"
 
 /*
  * /proc/self:
@@ -48,12 +49,43 @@ static const struct inode_operations proc_self_inode_operations = {
 	.put_link	= proc_self_put_link,
 };
 
-void __init proc_self_init(void)
+static unsigned self_inum;
+
+int proc_setup_self(struct super_block *s)
 {
-	struct proc_dir_entry *proc_self_symlink;
-	mode_t mode;
+	struct inode *root_inode = s->s_root->d_inode;
+	struct pid_namespace *ns = s->s_fs_info;
+	struct dentry *self;
+	
+	mutex_lock(&root_inode->i_mutex);
+	self = d_alloc_name(s->s_root, "self");
+	if (self) {
+		struct inode *inode = new_inode_pseudo(s);
+		if (inode) {
+			inode->i_ino = self_inum;
+			inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+			inode->i_mode = S_IFLNK | S_IRWXUGO;
+			inode->i_uid = GLOBAL_ROOT_UID;
+			inode->i_gid = GLOBAL_ROOT_GID;
+			inode->i_op = &proc_self_inode_operations;
+			d_add(self, inode);
+		} else {
+			dput(self);
+			self = ERR_PTR(-ENOMEM);
+		}
+	} else {
+		self = ERR_PTR(-ENOMEM);
+	}
+	mutex_unlock(&root_inode->i_mutex);
+	if (IS_ERR(self)) {
+		pr_err("proc_fill_super: can't allocate /proc/self\n");
+		return PTR_ERR(self);
+	}
+	ns->proc_self = self;
+	return 0;
+}
 
-	mode = S_IFLNK | S_IRWXUGO;
-	proc_self_symlink = proc_create("self", mode, NULL, NULL );
-	proc_self_symlink->proc_iops = &proc_self_inode_operations;
+void __init proc_self_init(void)
+{
+	proc_alloc_inum(&self_inum);
 }
diff --git a/fs/proc/stat.c b/fs/proc/stat.c
index e296572..1cf86c0 100644
--- a/fs/proc/stat.c
+++ b/fs/proc/stat.c
@@ -184,7 +184,7 @@ static int show_stat(struct seq_file *p, void *v)
 
 static int stat_open(struct inode *inode, struct file *file)
 {
-	unsigned size = 1024 + 128 * num_possible_cpus();
+	size_t size = 1024 + 128 * num_possible_cpus();
 	char *buf;
 	struct seq_file *m;
 	int res;
diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c
index 288f068..32cbd7c 100644
--- a/fs/pstore/ram.c
+++ b/fs/pstore/ram.c
@@ -83,7 +83,7 @@ struct ramoops_context {
 	size_t console_size;
 	size_t ftrace_size;
 	int dump_oops;
-	int ecc_size;
+	struct persistent_ram_ecc_info ecc_info;
 	unsigned int max_dump_cnt;
 	unsigned int dump_write_cnt;
 	unsigned int dump_read_cnt;
@@ -136,6 +136,7 @@ static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type,
 				   char **buf, struct pstore_info *psi)
 {
 	ssize_t size;
+	ssize_t ecc_notice_size;
 	struct ramoops_context *cxt = psi->data;
 	struct persistent_ram_zone *prz;
 
@@ -156,12 +157,18 @@ static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type,
 	time->tv_nsec = 0;
 
 	size = persistent_ram_old_size(prz);
-	*buf = kmalloc(size, GFP_KERNEL);
+
+	/* ECC correction notice */
+	ecc_notice_size = persistent_ram_ecc_string(prz, NULL, 0);
+
+	*buf = kmalloc(size + ecc_notice_size + 1, GFP_KERNEL);
 	if (*buf == NULL)
 		return -ENOMEM;
+
 	memcpy(*buf, persistent_ram_old(prz), size);
+	persistent_ram_ecc_string(prz, *buf + size, ecc_notice_size + 1);
 
-	return size;
+	return size + ecc_notice_size;
 }
 
 static size_t ramoops_write_kmsg_hdr(struct persistent_ram_zone *prz)
@@ -323,7 +330,8 @@ static int ramoops_init_przs(struct device *dev, struct ramoops_context *cxt,
 	for (i = 0; i < cxt->max_dump_cnt; i++) {
 		size_t sz = cxt->record_size;
 
-		cxt->przs[i] = persistent_ram_new(*paddr, sz, 0, cxt->ecc_size);
+		cxt->przs[i] = persistent_ram_new(*paddr, sz, 0,
+						  &cxt->ecc_info);
 		if (IS_ERR(cxt->przs[i])) {
 			err = PTR_ERR(cxt->przs[i]);
 			dev_err(dev, "failed to request mem region (0x%zx@0x%llx): %d\n",
@@ -353,7 +361,7 @@ static int ramoops_init_prz(struct device *dev, struct ramoops_context *cxt,
 		return -ENOMEM;
 	}
 
-	*prz = persistent_ram_new(*paddr, sz, sig, cxt->ecc_size);
+	*prz = persistent_ram_new(*paddr, sz, sig, &cxt->ecc_info);
 	if (IS_ERR(*prz)) {
 		int err = PTR_ERR(*prz);
 
@@ -407,7 +415,7 @@ static int ramoops_probe(struct platform_device *pdev)
 	cxt->console_size = pdata->console_size;
 	cxt->ftrace_size = pdata->ftrace_size;
 	cxt->dump_oops = pdata->dump_oops;
-	cxt->ecc_size = pdata->ecc_size;
+	cxt->ecc_info = pdata->ecc_info;
 
 	paddr = cxt->phys_addr;
 
@@ -465,9 +473,9 @@ static int ramoops_probe(struct platform_device *pdev)
 	record_size = pdata->record_size;
 	dump_oops = pdata->dump_oops;
 
-	pr_info("attached 0x%lx@0x%llx, ecc: %d\n",
+	pr_info("attached 0x%lx@0x%llx, ecc: %d/%d\n",
 		cxt->size, (unsigned long long)cxt->phys_addr,
-		cxt->ecc_size);
+		cxt->ecc_info.ecc_size, cxt->ecc_info.block_size);
 
 	return 0;
 
@@ -539,7 +547,7 @@ static void ramoops_register_dummy(void)
 	 * For backwards compatibility ramoops.ecc=1 means 16 bytes ECC
 	 * (using 1 byte for ECC isn't much of use anyway).
 	 */
-	dummy_data->ecc_size = ramoops_ecc == 1 ? 16 : ramoops_ecc;
+	dummy_data->ecc_info.ecc_size = ramoops_ecc == 1 ? 16 : ramoops_ecc;
 
 	dummy = platform_device_register_data(NULL, "ramoops", -1,
 			dummy_data, sizeof(struct ramoops_platform_data));
diff --git a/fs/pstore/ram_core.c b/fs/pstore/ram_core.c
index 0306303..5933732 100644
--- a/fs/pstore/ram_core.c
+++ b/fs/pstore/ram_core.c
@@ -82,12 +82,12 @@ static void notrace persistent_ram_encode_rs8(struct persistent_ram_zone *prz,
 	uint8_t *data, size_t len, uint8_t *ecc)
 {
 	int i;
-	uint16_t par[prz->ecc_size];
+	uint16_t par[prz->ecc_info.ecc_size];
 
 	/* Initialize the parity buffer */
 	memset(par, 0, sizeof(par));
 	encode_rs8(prz->rs_decoder, data, len, par, 0);
-	for (i = 0; i < prz->ecc_size; i++)
+	for (i = 0; i < prz->ecc_info.ecc_size; i++)
 		ecc[i] = par[i];
 }
 
@@ -95,9 +95,9 @@ static int persistent_ram_decode_rs8(struct persistent_ram_zone *prz,
 	void *data, size_t len, uint8_t *ecc)
 {
 	int i;
-	uint16_t par[prz->ecc_size];
+	uint16_t par[prz->ecc_info.ecc_size];
 
-	for (i = 0; i < prz->ecc_size; i++)
+	for (i = 0; i < prz->ecc_info.ecc_size; i++)
 		par[i] = ecc[i];
 	return decode_rs8(prz->rs_decoder, data, par, len,
 				NULL, 0, NULL, 0, NULL);
@@ -110,15 +110,15 @@ static void notrace persistent_ram_update_ecc(struct persistent_ram_zone *prz,
 	uint8_t *buffer_end = buffer->data + prz->buffer_size;
 	uint8_t *block;
 	uint8_t *par;
-	int ecc_block_size = prz->ecc_block_size;
-	int ecc_size = prz->ecc_size;
-	int size = prz->ecc_block_size;
+	int ecc_block_size = prz->ecc_info.block_size;
+	int ecc_size = prz->ecc_info.ecc_size;
+	int size = ecc_block_size;
 
-	if (!prz->ecc_size)
+	if (!ecc_size)
 		return;
 
 	block = buffer->data + (start & ~(ecc_block_size - 1));
-	par = prz->par_buffer + (start / ecc_block_size) * prz->ecc_size;
+	par = prz->par_buffer + (start / ecc_block_size) * ecc_size;
 
 	do {
 		if (block + ecc_block_size > buffer_end)
@@ -133,7 +133,7 @@ static void persistent_ram_update_header_ecc(struct persistent_ram_zone *prz)
 {
 	struct persistent_ram_buffer *buffer = prz->buffer;
 
-	if (!prz->ecc_size)
+	if (!prz->ecc_info.ecc_size)
 		return;
 
 	persistent_ram_encode_rs8(prz, (uint8_t *)buffer, sizeof(*buffer),
@@ -146,14 +146,14 @@ static void persistent_ram_ecc_old(struct persistent_ram_zone *prz)
 	uint8_t *block;
 	uint8_t *par;
 
-	if (!prz->ecc_size)
+	if (!prz->ecc_info.ecc_size)
 		return;
 
 	block = buffer->data;
 	par = prz->par_buffer;
 	while (block < buffer->data + buffer_size(prz)) {
 		int numerr;
-		int size = prz->ecc_block_size;
+		int size = prz->ecc_info.block_size;
 		if (block + size > buffer->data + prz->buffer_size)
 			size = buffer->data + prz->buffer_size - block;
 		numerr = persistent_ram_decode_rs8(prz, block, size, par);
@@ -166,44 +166,49 @@ static void persistent_ram_ecc_old(struct persistent_ram_zone *prz)
 				block);
 			prz->bad_blocks++;
 		}
-		block += prz->ecc_block_size;
-		par += prz->ecc_size;
+		block += prz->ecc_info.block_size;
+		par += prz->ecc_info.ecc_size;
 	}
 }
 
 static int persistent_ram_init_ecc(struct persistent_ram_zone *prz,
-				   int ecc_size)
+				   struct persistent_ram_ecc_info *ecc_info)
 {
 	int numerr;
 	struct persistent_ram_buffer *buffer = prz->buffer;
 	int ecc_blocks;
 	size_t ecc_total;
-	int ecc_symsize = 8;
-	int ecc_poly = 0x11d;
 
-	if (!ecc_size)
+	if (!ecc_info || !ecc_info->ecc_size)
 		return 0;
 
-	prz->ecc_block_size = 128;
-	prz->ecc_size = ecc_size;
+	prz->ecc_info.block_size = ecc_info->block_size ?: 128;
+	prz->ecc_info.ecc_size = ecc_info->ecc_size ?: 16;
+	prz->ecc_info.symsize = ecc_info->symsize ?: 8;
+	prz->ecc_info.poly = ecc_info->poly ?: 0x11d;
 
-	ecc_blocks = DIV_ROUND_UP(prz->buffer_size, prz->ecc_block_size);
-	ecc_total = (ecc_blocks + 1) * prz->ecc_size;
+	ecc_blocks = DIV_ROUND_UP(prz->buffer_size - prz->ecc_info.ecc_size,
+				  prz->ecc_info.block_size +
+				  prz->ecc_info.ecc_size);
+	ecc_total = (ecc_blocks + 1) * prz->ecc_info.ecc_size;
 	if (ecc_total >= prz->buffer_size) {
 		pr_err("%s: invalid ecc_size %u (total %zu, buffer size %zu)\n",
-		       __func__, prz->ecc_size, ecc_total, prz->buffer_size);
+		       __func__, prz->ecc_info.ecc_size,
+		       ecc_total, prz->buffer_size);
 		return -EINVAL;
 	}
 
 	prz->buffer_size -= ecc_total;
 	prz->par_buffer = buffer->data + prz->buffer_size;
-	prz->par_header = prz->par_buffer + ecc_blocks * prz->ecc_size;
+	prz->par_header = prz->par_buffer +
+			  ecc_blocks * prz->ecc_info.ecc_size;
 
 	/*
 	 * first consecutive root is 0
 	 * primitive element to generate roots = 1
 	 */
-	prz->rs_decoder = init_rs(ecc_symsize, ecc_poly, 0, 1, prz->ecc_size);
+	prz->rs_decoder = init_rs(prz->ecc_info.symsize, prz->ecc_info.poly,
+				  0, 1, prz->ecc_info.ecc_size);
 	if (prz->rs_decoder == NULL) {
 		pr_info("persistent_ram: init_rs failed\n");
 		return -EINVAL;
@@ -230,6 +235,9 @@ ssize_t persistent_ram_ecc_string(struct persistent_ram_zone *prz,
 {
 	ssize_t ret;
 
+	if (!prz->ecc_info.ecc_size)
+		return 0;
+
 	if (prz->corrected_bytes || prz->bad_blocks)
 		ret = snprintf(str, len, ""
 			"\n%d Corrected bytes, %d unrecoverable blocks\n",
@@ -391,11 +399,11 @@ static int persistent_ram_buffer_map(phys_addr_t start, phys_addr_t size,
 }
 
 static int persistent_ram_post_init(struct persistent_ram_zone *prz, u32 sig,
-				    int ecc_size)
+				    struct persistent_ram_ecc_info *ecc_info)
 {
 	int ret;
 
-	ret = persistent_ram_init_ecc(prz, ecc_size);
+	ret = persistent_ram_init_ecc(prz, ecc_info);
 	if (ret)
 		return ret;
 
@@ -444,7 +452,7 @@ void persistent_ram_free(struct persistent_ram_zone *prz)
 }
 
 struct persistent_ram_zone *persistent_ram_new(phys_addr_t start, size_t size,
-					       u32 sig, int ecc_size)
+			u32 sig, struct persistent_ram_ecc_info *ecc_info)
 {
 	struct persistent_ram_zone *prz;
 	int ret = -ENOMEM;
@@ -459,7 +467,7 @@ struct persistent_ram_zone *persistent_ram_new(phys_addr_t start, size_t size,
 	if (ret)
 		goto err;
 
-	ret = persistent_ram_post_init(prz, sig, ecc_size);
+	ret = persistent_ram_post_init(prz, sig, ecc_info);
 	if (ret)
 		goto err;
 
diff --git a/fs/read_write.c b/fs/read_write.c
index e6ddc8d..7eb7ef3 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -9,6 +9,7 @@
 #include <linux/fcntl.h>
 #include <linux/file.h>
 #include <linux/uio.h>
+#include <linux/aio.h>
 #include <linux/fsnotify.h>
 #include <linux/security.h>
 #include <linux/export.h>
@@ -326,16 +327,6 @@ int rw_verify_area(int read_write, struct file *file, loff_t *ppos, size_t count
 	return count > MAX_RW_COUNT ? MAX_RW_COUNT : count;
 }
 
-static void wait_on_retry_sync_kiocb(struct kiocb *iocb)
-{
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	if (!kiocbIsKicked(iocb))
-		schedule();
-	else
-		kiocbClearKicked(iocb);
-	__set_current_state(TASK_RUNNING);
-}
-
 ssize_t do_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos)
 {
 	struct iovec iov = { .iov_base = buf, .iov_len = len };
@@ -347,13 +338,7 @@ ssize_t do_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *pp
 	kiocb.ki_left = len;
 	kiocb.ki_nbytes = len;
 
-	for (;;) {
-		ret = filp->f_op->aio_read(&kiocb, &iov, 1, kiocb.ki_pos);
-		if (ret != -EIOCBRETRY)
-			break;
-		wait_on_retry_sync_kiocb(&kiocb);
-	}
-
+	ret = filp->f_op->aio_read(&kiocb, &iov, 1, kiocb.ki_pos);
 	if (-EIOCBQUEUED == ret)
 		ret = wait_on_sync_kiocb(&kiocb);
 	*ppos = kiocb.ki_pos;
@@ -403,13 +388,7 @@ ssize_t do_sync_write(struct file *filp, const char __user *buf, size_t len, lof
 	kiocb.ki_left = len;
 	kiocb.ki_nbytes = len;
 
-	for (;;) {
-		ret = filp->f_op->aio_write(&kiocb, &iov, 1, kiocb.ki_pos);
-		if (ret != -EIOCBRETRY)
-			break;
-		wait_on_retry_sync_kiocb(&kiocb);
-	}
-
+	ret = filp->f_op->aio_write(&kiocb, &iov, 1, kiocb.ki_pos);
 	if (-EIOCBQUEUED == ret)
 		ret = wait_on_sync_kiocb(&kiocb);
 	*ppos = kiocb.ki_pos;
@@ -459,6 +438,7 @@ ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_
 	ret = rw_verify_area(WRITE, file, pos, count);
 	if (ret >= 0) {
 		count = ret;
+		file_start_write(file);
 		if (file->f_op->write)
 			ret = file->f_op->write(file, buf, count, pos);
 		else
@@ -468,6 +448,7 @@ ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_
 			add_wchar(current, ret);
 		}
 		inc_syscw(current);
+		file_end_write(file);
 	}
 
 	return ret;
@@ -515,8 +496,8 @@ SYSCALL_DEFINE3(write, unsigned int, fd, const char __user *, buf,
 	return ret;
 }
 
-SYSCALL_DEFINE(pread64)(unsigned int fd, char __user *buf,
-			size_t count, loff_t pos)
+SYSCALL_DEFINE4(pread64, unsigned int, fd, char __user *, buf,
+			size_t, count, loff_t, pos)
 {
 	struct fd f;
 	ssize_t ret = -EBADF;
@@ -534,17 +515,9 @@ SYSCALL_DEFINE(pread64)(unsigned int fd, char __user *buf,
 
 	return ret;
 }
-#ifdef CONFIG_HAVE_SYSCALL_WRAPPERS
-asmlinkage long SyS_pread64(long fd, long buf, long count, loff_t pos)
-{
-	return SYSC_pread64((unsigned int) fd, (char __user *) buf,
-			    (size_t) count, pos);
-}
-SYSCALL_ALIAS(sys_pread64, SyS_pread64);
-#endif
 
-SYSCALL_DEFINE(pwrite64)(unsigned int fd, const char __user *buf,
-			 size_t count, loff_t pos)
+SYSCALL_DEFINE4(pwrite64, unsigned int, fd, const char __user *, buf,
+			 size_t, count, loff_t, pos)
 {
 	struct fd f;
 	ssize_t ret = -EBADF;
@@ -562,14 +535,6 @@ SYSCALL_DEFINE(pwrite64)(unsigned int fd, const char __user *buf,
 
 	return ret;
 }
-#ifdef CONFIG_HAVE_SYSCALL_WRAPPERS
-asmlinkage long SyS_pwrite64(long fd, long buf, long count, loff_t pos)
-{
-	return SYSC_pwrite64((unsigned int) fd, (const char __user *) buf,
-			     (size_t) count, pos);
-}
-SYSCALL_ALIAS(sys_pwrite64, SyS_pwrite64);
-#endif
 
 /*
  * Reduce an iovec's length in-place.  Return the resulting number of segments
@@ -592,7 +557,7 @@ unsigned long iov_shorten(struct iovec *iov, unsigned long nr_segs, size_t to)
 }
 EXPORT_SYMBOL(iov_shorten);
 
-ssize_t do_sync_readv_writev(struct file *filp, const struct iovec *iov,
+static ssize_t do_sync_readv_writev(struct file *filp, const struct iovec *iov,
 		unsigned long nr_segs, size_t len, loff_t *ppos, iov_fn_t fn)
 {
 	struct kiocb kiocb;
@@ -603,13 +568,7 @@ ssize_t do_sync_readv_writev(struct file *filp, const struct iovec *iov,
 	kiocb.ki_left = len;
 	kiocb.ki_nbytes = len;
 
-	for (;;) {
-		ret = fn(&kiocb, iov, nr_segs, kiocb.ki_pos);
-		if (ret != -EIOCBRETRY)
-			break;
-		wait_on_retry_sync_kiocb(&kiocb);
-	}
-
+	ret = fn(&kiocb, iov, nr_segs, kiocb.ki_pos);
 	if (ret == -EIOCBQUEUED)
 		ret = wait_on_sync_kiocb(&kiocb);
 	*ppos = kiocb.ki_pos;
@@ -617,7 +576,7 @@ ssize_t do_sync_readv_writev(struct file *filp, const struct iovec *iov,
 }
 
 /* Do it by hand, with file-ops */
-ssize_t do_loop_readv_writev(struct file *filp, struct iovec *iov,
+static ssize_t do_loop_readv_writev(struct file *filp, struct iovec *iov,
 		unsigned long nr_segs, loff_t *ppos, io_fn_t fn)
 {
 	struct iovec *vector = iov;
@@ -759,6 +718,7 @@ static ssize_t do_readv_writev(int type, struct file *file,
 	} else {
 		fn = (io_fn_t)file->f_op->write;
 		fnv = file->f_op->aio_write;
+		file_start_write(file);
 	}
 
 	if (fnv)
@@ -767,6 +727,9 @@ static ssize_t do_readv_writev(int type, struct file *file,
 	else
 		ret = do_loop_readv_writev(file, iov, nr_segs, pos, fn);
 
+	if (type != READ)
+		file_end_write(file);
+
 out:
 	if (iov != iovstack)
 		kfree(iov);
@@ -897,8 +860,203 @@ SYSCALL_DEFINE5(pwritev, unsigned long, fd, const struct iovec __user *, vec,
 	return ret;
 }
 
-ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos, size_t count,
-		    loff_t max)
+#ifdef CONFIG_COMPAT
+
+static ssize_t compat_do_readv_writev(int type, struct file *file,
+			       const struct compat_iovec __user *uvector,
+			       unsigned long nr_segs, loff_t *pos)
+{
+	compat_ssize_t tot_len;
+	struct iovec iovstack[UIO_FASTIOV];
+	struct iovec *iov = iovstack;
+	ssize_t ret;
+	io_fn_t fn;
+	iov_fn_t fnv;
+
+	ret = -EINVAL;
+	if (!file->f_op)
+		goto out;
+
+	ret = -EFAULT;
+	if (!access_ok(VERIFY_READ, uvector, nr_segs*sizeof(*uvector)))
+		goto out;
+
+	ret = compat_rw_copy_check_uvector(type, uvector, nr_segs,
+					       UIO_FASTIOV, iovstack, &iov);
+	if (ret <= 0)
+		goto out;
+
+	tot_len = ret;
+	ret = rw_verify_area(type, file, pos, tot_len);
+	if (ret < 0)
+		goto out;
+
+	fnv = NULL;
+	if (type == READ) {
+		fn = file->f_op->read;
+		fnv = file->f_op->aio_read;
+	} else {
+		fn = (io_fn_t)file->f_op->write;
+		fnv = file->f_op->aio_write;
+		file_start_write(file);
+	}
+
+	if (fnv)
+		ret = do_sync_readv_writev(file, iov, nr_segs, tot_len,
+						pos, fnv);
+	else
+		ret = do_loop_readv_writev(file, iov, nr_segs, pos, fn);
+
+	if (type != READ)
+		file_end_write(file);
+
+out:
+	if (iov != iovstack)
+		kfree(iov);
+	if ((ret + (type == READ)) > 0) {
+		if (type == READ)
+			fsnotify_access(file);
+		else
+			fsnotify_modify(file);
+	}
+	return ret;
+}
+
+static size_t compat_readv(struct file *file,
+			   const struct compat_iovec __user *vec,
+			   unsigned long vlen, loff_t *pos)
+{
+	ssize_t ret = -EBADF;
+
+	if (!(file->f_mode & FMODE_READ))
+		goto out;
+
+	ret = -EINVAL;
+	if (!file->f_op || (!file->f_op->aio_read && !file->f_op->read))
+		goto out;
+
+	ret = compat_do_readv_writev(READ, file, vec, vlen, pos);
+
+out:
+	if (ret > 0)
+		add_rchar(current, ret);
+	inc_syscr(current);
+	return ret;
+}
+
+COMPAT_SYSCALL_DEFINE3(readv, unsigned long, fd,
+		const struct compat_iovec __user *,vec,
+		unsigned long, vlen)
+{
+	struct fd f = fdget(fd);
+	ssize_t ret;
+	loff_t pos;
+
+	if (!f.file)
+		return -EBADF;
+	pos = f.file->f_pos;
+	ret = compat_readv(f.file, vec, vlen, &pos);
+	f.file->f_pos = pos;
+	fdput(f);
+	return ret;
+}
+
+COMPAT_SYSCALL_DEFINE4(preadv64, unsigned long, fd,
+		const struct compat_iovec __user *,vec,
+		unsigned long, vlen, loff_t, pos)
+{
+	struct fd f;
+	ssize_t ret;
+
+	if (pos < 0)
+		return -EINVAL;
+	f = fdget(fd);
+	if (!f.file)
+		return -EBADF;
+	ret = -ESPIPE;
+	if (f.file->f_mode & FMODE_PREAD)
+		ret = compat_readv(f.file, vec, vlen, &pos);
+	fdput(f);
+	return ret;
+}
+
+COMPAT_SYSCALL_DEFINE5(preadv, unsigned long, fd,
+		const struct compat_iovec __user *,vec,
+		unsigned long, vlen, u32, pos_low, u32, pos_high)
+{
+	loff_t pos = ((loff_t)pos_high << 32) | pos_low;
+	return compat_sys_preadv64(fd, vec, vlen, pos);
+}
+
+static size_t compat_writev(struct file *file,
+			    const struct compat_iovec __user *vec,
+			    unsigned long vlen, loff_t *pos)
+{
+	ssize_t ret = -EBADF;
+
+	if (!(file->f_mode & FMODE_WRITE))
+		goto out;
+
+	ret = -EINVAL;
+	if (!file->f_op || (!file->f_op->aio_write && !file->f_op->write))
+		goto out;
+
+	ret = compat_do_readv_writev(WRITE, file, vec, vlen, pos);
+
+out:
+	if (ret > 0)
+		add_wchar(current, ret);
+	inc_syscw(current);
+	return ret;
+}
+
+COMPAT_SYSCALL_DEFINE3(writev, unsigned long, fd,
+		const struct compat_iovec __user *, vec,
+		unsigned long, vlen)
+{
+	struct fd f = fdget(fd);
+	ssize_t ret;
+	loff_t pos;
+
+	if (!f.file)
+		return -EBADF;
+	pos = f.file->f_pos;
+	ret = compat_writev(f.file, vec, vlen, &pos);
+	f.file->f_pos = pos;
+	fdput(f);
+	return ret;
+}
+
+COMPAT_SYSCALL_DEFINE4(pwritev64, unsigned long, fd,
+		const struct compat_iovec __user *,vec,
+		unsigned long, vlen, loff_t, pos)
+{
+	struct fd f;
+	ssize_t ret;
+
+	if (pos < 0)
+		return -EINVAL;
+	f = fdget(fd);
+	if (!f.file)
+		return -EBADF;
+	ret = -ESPIPE;
+	if (f.file->f_mode & FMODE_PWRITE)
+		ret = compat_writev(f.file, vec, vlen, &pos);
+	fdput(f);
+	return ret;
+}
+
+COMPAT_SYSCALL_DEFINE5(pwritev, unsigned long, fd,
+		const struct compat_iovec __user *,vec,
+		unsigned long, vlen, u32, pos_low, u32, pos_high)
+{
+	loff_t pos = ((loff_t)pos_high << 32) | pos_low;
+	return compat_sys_pwritev64(fd, vec, vlen, pos);
+}
+#endif
+
+static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
+		  	   size_t count, loff_t max)
 {
 	struct fd in, out;
 	struct inode *in_inode, *out_inode;
@@ -1022,3 +1180,43 @@ SYSCALL_DEFINE4(sendfile64, int, out_fd, int, in_fd, loff_t __user *, offset, si
 
 	return do_sendfile(out_fd, in_fd, NULL, count, 0);
 }
+
+#ifdef CONFIG_COMPAT
+COMPAT_SYSCALL_DEFINE4(sendfile, int, out_fd, int, in_fd,
+		compat_off_t __user *, offset, compat_size_t, count)
+{
+	loff_t pos;
+	off_t off;
+	ssize_t ret;
+
+	if (offset) {
+		if (unlikely(get_user(off, offset)))
+			return -EFAULT;
+		pos = off;
+		ret = do_sendfile(out_fd, in_fd, &pos, count, MAX_NON_LFS);
+		if (unlikely(put_user(pos, offset)))
+			return -EFAULT;
+		return ret;
+	}
+
+	return do_sendfile(out_fd, in_fd, NULL, count, 0);
+}
+
+COMPAT_SYSCALL_DEFINE4(sendfile64, int, out_fd, int, in_fd,
+		compat_loff_t __user *, offset, compat_size_t, count)
+{
+	loff_t pos;
+	ssize_t ret;
+
+	if (offset) {
+		if (unlikely(copy_from_user(&pos, offset, sizeof(loff_t))))
+			return -EFAULT;
+		ret = do_sendfile(out_fd, in_fd, &pos, count, 0);
+		if (unlikely(put_user(pos, offset)))
+			return -EFAULT;
+		return ret;
+	}
+
+	return do_sendfile(out_fd, in_fd, NULL, count, 0);
+}
+#endif
diff --git a/fs/read_write.h b/fs/read_write.h
index d3e00ef..e6d4696 100644
--- a/fs/read_write.h
+++ b/fs/read_write.h
@@ -8,9 +8,3 @@ typedef ssize_t (*io_fn_t)(struct file *, char __user *, size_t, loff_t *);
 typedef ssize_t (*iov_fn_t)(struct kiocb *, const struct iovec *,
 		unsigned long, loff_t);
 
-ssize_t do_sync_readv_writev(struct file *filp, const struct iovec *iov,
-		unsigned long nr_segs, size_t len, loff_t *ppos, iov_fn_t fn);
-ssize_t do_loop_readv_writev(struct file *filp, struct iovec *iov,
-		unsigned long nr_segs, loff_t *ppos, io_fn_t fn);
-ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos, size_t count,
-		    loff_t max);
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c
index 6165bd4..dcaafcf 100644
--- a/fs/reiserfs/file.c
+++ b/fs/reiserfs/file.c
@@ -234,68 +234,9 @@ int reiserfs_commit_page(struct inode *inode, struct page *page,
 	return ret;
 }
 
-/* Write @count bytes at position @ppos in a file indicated by @file
-   from the buffer @buf.
-
-   generic_file_write() is only appropriate for filesystems that are not seeking to optimize performance and want
-   something simple that works.  It is not for serious use by general purpose filesystems, excepting the one that it was
-   written for (ext2/3).  This is for several reasons:
-
-   * It has no understanding of any filesystem specific optimizations.
-
-   * It enters the filesystem repeatedly for each page that is written.
-
-   * It depends on reiserfs_get_block() function which if implemented by reiserfs performs costly search_by_key
-   * operation for each page it is supplied with. By contrast reiserfs_file_write() feeds as much as possible at a time
-   * to reiserfs which allows for fewer tree traversals.
-
-   * Each indirect pointer insertion takes a lot of cpu, because it involves memory moves inside of blocks.
-
-   * Asking the block allocation code for blocks one at a time is slightly less efficient.
-
-   All of these reasons for not using only generic file write were understood back when reiserfs was first miscoded to
-   use it, but we were in a hurry to make code freeze, and so it couldn't be revised then.  This new code should make
-   things right finally.
-
-   Future Features: providing search_by_key with hints.
-
-*/
-static ssize_t reiserfs_file_write(struct file *file,	/* the file we are going to write into */
-				   const char __user * buf,	/*  pointer to user supplied data
-								   (in userspace) */
-				   size_t count,	/* amount of bytes to write */
-				   loff_t * ppos	/* pointer to position in file that we start writing at. Should be updated to
-							 * new current position before returning. */
-				   )
-{
-	struct inode *inode = file_inode(file);	// Inode of the file that we are writing to.
-	/* To simplify coding at this time, we store
-	   locked pages in array for now */
-	struct reiserfs_transaction_handle th;
-	th.t_trans_id = 0;
-
-	/* If a filesystem is converted from 3.5 to 3.6, we'll have v3.5 items
-	* lying around (most of the disk, in fact). Despite the filesystem
-	* now being a v3.6 format, the old items still can't support large
-	* file sizes. Catch this case here, as the rest of the VFS layer is
-	* oblivious to the different limitations between old and new items.
-	* reiserfs_setattr catches this for truncates. This chunk is lifted
-	* from generic_write_checks. */
-	if (get_inode_item_key_version (inode) == KEY_FORMAT_3_5 &&
-	    *ppos + count > MAX_NON_LFS) {
-		if (*ppos >= MAX_NON_LFS) {
-			return -EFBIG;
-		}
-		if (count > MAX_NON_LFS - (unsigned long)*ppos)
-			count = MAX_NON_LFS - (unsigned long)*ppos;
-	}
-
-	return do_sync_write(file, buf, count, ppos);
-}
-
 const struct file_operations reiserfs_file_operations = {
 	.read = do_sync_read,
-	.write = reiserfs_file_write,
+	.write = do_sync_write,
 	.unlocked_ioctl = reiserfs_ioctl,
 #ifdef CONFIG_COMPAT
 	.compat_ioctl = reiserfs_compat_ioctl,
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index ea5061f..77d6d47 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -18,6 +18,7 @@
 #include <linux/writeback.h>
 #include <linux/quotaops.h>
 #include <linux/swap.h>
+#include <linux/aio.h>
 
 int reiserfs_commit_write(struct file *f, struct page *page,
 			  unsigned from, unsigned to);
diff --git a/fs/reiserfs/procfs.c b/fs/reiserfs/procfs.c
index 9cc0740a..274adea 100644
--- a/fs/reiserfs/procfs.c
+++ b/fs/reiserfs/procfs.c
@@ -499,29 +499,17 @@ int reiserfs_proc_info_init(struct super_block *sb)
 int reiserfs_proc_info_done(struct super_block *sb)
 {
 	struct proc_dir_entry *de = REISERFS_SB(sb)->procdir;
-	char b[BDEVNAME_SIZE];
-	char *s;
+	if (de) {
+		char b[BDEVNAME_SIZE];
+		char *s;
 
-	/* Some block devices use /'s */
-	strlcpy(b, reiserfs_bdevname(sb), BDEVNAME_SIZE);
-	s = strchr(b, '/');
-	if (s)
-		*s = '!';
+		/* Some block devices use /'s */
+		strlcpy(b, reiserfs_bdevname(sb), BDEVNAME_SIZE);
+		s = strchr(b, '/');
+		if (s)
+			*s = '!';
 
-	if (de) {
-		remove_proc_entry("journal", de);
-		remove_proc_entry("oidmap", de);
-		remove_proc_entry("on-disk-super", de);
-		remove_proc_entry("bitmap", de);
-		remove_proc_entry("per-level", de);
-		remove_proc_entry("super", de);
-		remove_proc_entry("version", de);
-	}
-	spin_lock(&__PINFO(sb).lock);
-	__PINFO(sb).exiting = 1;
-	spin_unlock(&__PINFO(sb).lock);
-	if (proc_info_root) {
-		remove_proc_entry(b, proc_info_root);
+		remove_proc_subtree(b, proc_info_root);
 		REISERFS_SB(sb)->procdir = NULL;
 	}
 	return 0;
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c
index c196369..4cce1d9 100644
--- a/fs/reiserfs/xattr.c
+++ b/fs/reiserfs/xattr.c
@@ -187,8 +187,8 @@ fill_with_dentries(void *buf, const char *name, int namelen, loff_t offset,
 	if (dbuf->count == ARRAY_SIZE(dbuf->dentries))
 		return -ENOSPC;
 
-	if (name[0] == '.' && (name[1] == '\0' ||
-			       (name[1] == '.' && name[2] == '\0')))
+	if (name[0] == '.' && (namelen < 2 ||
+			       (namelen == 2 && name[1] == '.')))
 		return 0;
 
 	dentry = lookup_one_len(name, dbuf->xadir, namelen);
diff --git a/fs/seq_file.c b/fs/seq_file.c
index 38bb59f..774c1eb 100644
--- a/fs/seq_file.c
+++ b/fs/seq_file.c
@@ -599,6 +599,24 @@ int single_open(struct file *file, int (*show)(struct seq_file *, void *),
 }
 EXPORT_SYMBOL(single_open);
 
+int single_open_size(struct file *file, int (*show)(struct seq_file *, void *),
+		void *data, size_t size)
+{
+	char *buf = kmalloc(size, GFP_KERNEL);
+	int ret;
+	if (!buf)
+		return -ENOMEM;
+	ret = single_open(file, show, data);
+	if (ret) {
+		kfree(buf);
+		return ret;
+	}
+	((struct seq_file *)file->private_data)->buf = buf;
+	((struct seq_file *)file->private_data)->size = size;
+	return 0;
+}
+EXPORT_SYMBOL(single_open_size);
+
 int single_release(struct inode *inode, struct file *file)
 {
 	const struct seq_operations *op = ((struct seq_file *)file->private_data)->op;
diff --git a/fs/signalfd.c b/fs/signalfd.c
index b534869..424b7b6 100644
--- a/fs/signalfd.c
+++ b/fs/signalfd.c
@@ -30,6 +30,7 @@
 #include <linux/signalfd.h>
 #include <linux/syscalls.h>
 #include <linux/proc_fs.h>
+#include <linux/compat.h>
 
 void signalfd_cleanup(struct sighand_struct *sighand)
 {
@@ -311,3 +312,33 @@ SYSCALL_DEFINE3(signalfd, int, ufd, sigset_t __user *, user_mask,
 {
 	return sys_signalfd4(ufd, user_mask, sizemask, 0);
 }
+
+#ifdef CONFIG_COMPAT
+COMPAT_SYSCALL_DEFINE4(signalfd4, int, ufd,
+		     const compat_sigset_t __user *,sigmask,
+		     compat_size_t, sigsetsize,
+		     int, flags)
+{
+	compat_sigset_t ss32;
+	sigset_t tmp;
+	sigset_t __user *ksigmask;
+
+	if (sigsetsize != sizeof(compat_sigset_t))
+		return -EINVAL;
+	if (copy_from_user(&ss32, sigmask, sizeof(ss32)))
+		return -EFAULT;
+	sigset_from_compat(&tmp, &ss32);
+	ksigmask = compat_alloc_user_space(sizeof(sigset_t));
+	if (copy_to_user(ksigmask, &tmp, sizeof(sigset_t)))
+		return -EFAULT;
+
+	return sys_signalfd4(ufd, ksigmask, sizeof(sigset_t), flags);
+}
+
+COMPAT_SYSCALL_DEFINE3(signalfd, int, ufd,
+		     const compat_sigset_t __user *,sigmask,
+		     compat_size_t, sigsetsize)
+{
+	return compat_sys_signalfd4(ufd, sigmask, sigsetsize, 0);
+}
+#endif
diff --git a/fs/splice.c b/fs/splice.c
index 29e394e..e6b2559 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -31,6 +31,7 @@
 #include <linux/security.h>
 #include <linux/gfp.h>
 #include <linux/socket.h>
+#include <linux/compat.h>
 #include "internal.h"
 
 /*
@@ -218,7 +219,7 @@ ssize_t splice_to_pipe(struct pipe_inode_info *pipe,
 			page_nr++;
 			ret += buf->len;
 
-			if (pipe->inode)
+			if (pipe->files)
 				do_wakeup = 1;
 
 			if (!--spd->nr_pages)
@@ -828,7 +829,7 @@ int splice_from_pipe_feed(struct pipe_inode_info *pipe, struct splice_desc *sd,
 			ops->release(pipe, buf);
 			pipe->curbuf = (pipe->curbuf + 1) & (pipe->buffers - 1);
 			pipe->nrbufs--;
-			if (pipe->inode)
+			if (pipe->files)
 				sd->need_wakeup = true;
 		}
 
@@ -1000,8 +1001,6 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out,
 	};
 	ssize_t ret;
 
-	sb_start_write(inode->i_sb);
-
 	pipe_lock(pipe);
 
 	splice_from_pipe_begin(&sd);
@@ -1037,7 +1036,6 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out,
 			*ppos += ret;
 		balance_dirty_pages_ratelimited(mapping);
 	}
-	sb_end_write(inode->i_sb);
 
 	return ret;
 }
@@ -1117,7 +1115,10 @@ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
 	else
 		splice_write = default_file_splice_write;
 
-	return splice_write(pipe, out, ppos, len, flags);
+	file_start_write(out);
+	ret = splice_write(pipe, out, ppos, len, flags);
+	file_end_write(out);
+	return ret;
 }
 
 /*
@@ -1183,7 +1184,7 @@ ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd,
 	 */
 	pipe = current->splice_pipe;
 	if (unlikely(!pipe)) {
-		pipe = alloc_pipe_info(NULL);
+		pipe = alloc_pipe_info();
 		if (!pipe)
 			return -ENOMEM;
 
@@ -1690,6 +1691,27 @@ SYSCALL_DEFINE4(vmsplice, int, fd, const struct iovec __user *, iov,
 	return error;
 }
 
+#ifdef CONFIG_COMPAT
+COMPAT_SYSCALL_DEFINE4(vmsplice, int, fd, const struct compat_iovec __user *, iov32,
+		    unsigned int, nr_segs, unsigned int, flags)
+{
+	unsigned i;
+	struct iovec __user *iov;
+	if (nr_segs > UIO_MAXIOV)
+		return -EINVAL;
+	iov = compat_alloc_user_space(nr_segs * sizeof(struct iovec));
+	for (i = 0; i < nr_segs; i++) {
+		struct compat_iovec v;
+		if (get_user(v.iov_base, &iov32[i].iov_base) ||
+		    get_user(v.iov_len, &iov32[i].iov_len) ||
+		    put_user(compat_ptr(v.iov_base), &iov[i].iov_base) ||
+		    put_user(v.iov_len, &iov[i].iov_len))
+			return -EFAULT;
+	}
+	return sys_vmsplice(fd, iov, nr_segs, flags);
+}
+#endif
+
 SYSCALL_DEFINE6(splice, int, fd_in, loff_t __user *, off_in,
 		int, fd_out, loff_t __user *, off_out,
 		size_t, len, unsigned int, flags)
diff --git a/fs/sync.c b/fs/sync.c
index 2c5d663..905f3f6 100644
--- a/fs/sync.c
+++ b/fs/sync.c
@@ -283,8 +283,8 @@ EXPORT_SYMBOL(generic_write_sync);
  * already-instantiated disk blocks, there are no guarantees here that the data
  * will be available after a crash.
  */
-SYSCALL_DEFINE(sync_file_range)(int fd, loff_t offset, loff_t nbytes,
-				unsigned int flags)
+SYSCALL_DEFINE4(sync_file_range, int, fd, loff_t, offset, loff_t, nbytes,
+				unsigned int, flags)
 {
 	int ret;
 	struct fd f;
@@ -365,29 +365,11 @@ out_put:
 out:
 	return ret;
 }
-#ifdef CONFIG_HAVE_SYSCALL_WRAPPERS
-asmlinkage long SyS_sync_file_range(long fd, loff_t offset, loff_t nbytes,
-				    long flags)
-{
-	return SYSC_sync_file_range((int) fd, offset, nbytes,
-				    (unsigned int) flags);
-}
-SYSCALL_ALIAS(sys_sync_file_range, SyS_sync_file_range);
-#endif
 
 /* It would be nice if people remember that not all the world's an i386
    when they introduce new system calls */
-SYSCALL_DEFINE(sync_file_range2)(int fd, unsigned int flags,
-				 loff_t offset, loff_t nbytes)
+SYSCALL_DEFINE4(sync_file_range2, int, fd, unsigned int, flags,
+				 loff_t, offset, loff_t, nbytes)
 {
 	return sys_sync_file_range(fd, offset, nbytes, flags);
 }
-#ifdef CONFIG_HAVE_SYSCALL_WRAPPERS
-asmlinkage long SyS_sync_file_range2(long fd, long flags,
-				     loff_t offset, loff_t nbytes)
-{
-	return SYSC_sync_file_range2((int) fd, (unsigned int) flags,
-				     offset, nbytes);
-}
-SYSCALL_ALIAS(sys_sync_file_range2, SyS_sync_file_range2);
-#endif
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index e145126..1bf016b 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -165,21 +165,8 @@ struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd)
 	if (unlikely(!sd))
 		return NULL;
 
-	while (1) {
-		int v, t;
-
-		v = atomic_read(&sd->s_active);
-		if (unlikely(v < 0))
-			return NULL;
-
-		t = atomic_cmpxchg(&sd->s_active, v, v + 1);
-		if (likely(t == v))
-			break;
-		if (t < 0)
-			return NULL;
-
-		cpu_relax();
-	}
+	if (!atomic_inc_unless_negative(&sd->s_active))
+		return NULL;
 
 	if (likely(!ignore_lockdep(sd)))
 		rwsem_acquire_read(&sd->dep_map, 0, 1, _RET_IP_);
@@ -1012,6 +999,7 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
 	enum kobj_ns_type type;
 	const void *ns;
 	ino_t ino;
+	loff_t off;
 
 	type = sysfs_ns_type(parent_sd);
 	ns = sysfs_info(dentry->d_sb)->ns[type];
@@ -1034,6 +1022,7 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
 			return 0;
 	}
 	mutex_lock(&sysfs_mutex);
+	off = filp->f_pos;
 	for (pos = sysfs_dir_pos(ns, parent_sd, filp->f_pos, pos);
 	     pos;
 	     pos = sysfs_dir_next_pos(ns, parent_sd, filp->f_pos, pos)) {
@@ -1045,19 +1034,24 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
 		len = strlen(name);
 		ino = pos->s_ino;
 		type = dt_type(pos);
-		filp->f_pos = pos->s_hash;
+		off = filp->f_pos = pos->s_hash;
 		filp->private_data = sysfs_get(pos);
 
 		mutex_unlock(&sysfs_mutex);
-		ret = filldir(dirent, name, len, filp->f_pos, ino, type);
+		ret = filldir(dirent, name, len, off, ino, type);
 		mutex_lock(&sysfs_mutex);
 		if (ret < 0)
 			break;
 	}
 	mutex_unlock(&sysfs_mutex);
-	if ((filp->f_pos > 1) && !pos) { /* EOF */
-		filp->f_pos = INT_MAX;
+
+	/* don't reference last entry if its refcount is dropped */
+	if (!pos) {
 		filp->private_data = NULL;
+
+		/* EOF and not changed as 0 or 1 in read/write path */
+		if (off == filp->f_pos && off > 1)
+			filp->f_pos = INT_MAX;
 	}
 	return 0;
 }
diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c
index f12189d..1437453 100644
--- a/fs/ubifs/file.c
+++ b/fs/ubifs/file.c
@@ -50,6 +50,7 @@
  */
 
 #include "ubifs.h"
+#include <linux/aio.h>
 #include <linux/mount.h>
 #include <linux/namei.h>
 #include <linux/slab.h>
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index ac838b8..f21acf0 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -1568,6 +1568,12 @@ static int ubifs_remount_rw(struct ubifs_info *c)
 	c->remounting_rw = 1;
 	c->ro_mount = 0;
 
+	if (c->space_fixup) {
+		err = ubifs_fixup_free_space(c);
+		if (err)
+			return err;
+	}
+
 	err = check_free_space(c);
 	if (err)
 		goto out;
@@ -1684,12 +1690,6 @@ static int ubifs_remount_rw(struct ubifs_info *c)
 		err = dbg_check_space_info(c);
 	}
 
-	if (c->space_fixup) {
-		err = ubifs_fixup_free_space(c);
-		if (err)
-			goto out;
-	}
-
 	mutex_unlock(&c->umount_mutex);
 	return err;
 
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index 7a12e48..b6d15d3 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -38,6 +38,7 @@
 #include <linux/slab.h>
 #include <linux/crc-itu-t.h>
 #include <linux/mpage.h>
+#include <linux/aio.h>
 
 #include "udf_i.h"
 #include "udf_sb.h"
diff --git a/fs/ufs/util.c b/fs/ufs/util.c
index 95425b5..b6c2f94 100644
--- a/fs/ufs/util.c
+++ b/fs/ufs/util.c
@@ -26,8 +26,7 @@ struct ufs_buffer_head * _ubh_bread_ (struct ufs_sb_private_info * uspi,
 	count = size >> uspi->s_fshift;
 	if (count > UFS_MAXFRAG)
 		return NULL;
-	ubh = (struct ufs_buffer_head *)
-		kmalloc (sizeof (struct ufs_buffer_head), GFP_NOFS);
+	ubh = kmalloc (sizeof (struct ufs_buffer_head), GFP_NOFS);
 	if (!ubh)
 		return NULL;
 	ubh->fragment = fragment;
diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c
index 0ad2325..a8beb5c 100644
--- a/fs/xfs/xfs_alloc.c
+++ b/fs/xfs/xfs_alloc.c
@@ -842,7 +842,7 @@ xfs_alloc_ag_vextent_near(
 	 */
 	int		dofirst;	/* set to do first algorithm */
 
-	dofirst = random32() & 1;
+	dofirst = prandom_u32() & 1;
 #endif
 
 restart:
diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c
index 5f707e5..f64ee71 100644
--- a/fs/xfs/xfs_aops.c
+++ b/fs/xfs/xfs_aops.c
@@ -31,6 +31,7 @@
 #include "xfs_vnodeops.h"
 #include "xfs_trace.h"
 #include "xfs_bmap.h"
+#include <linux/aio.h>
 #include <linux/gfp.h>
 #include <linux/mpage.h>
 #include <linux/pagevec.h>
@@ -379,7 +380,8 @@ xfs_imap_valid(
 STATIC void
 xfs_end_bio(
 	struct bio		*bio,
-	int			error)
+	int			error,
+	struct batch_complete *batch)
 {
 	xfs_ioend_t		*ioend = bio->bi_private;
 
@@ -953,13 +955,13 @@ xfs_vm_writepage(
 		unsigned offset_into_page = offset & (PAGE_CACHE_SIZE - 1);
 
 		/*
-		 * Just skip the page if it is fully outside i_size, e.g. due
-		 * to a truncate operation that is in progress.
+		 * Skip the page if it is fully outside i_size, e.g. due to a
+		 * truncate operation that is in progress. We must redirty the
+		 * page so that reclaim stops reclaiming it. Otherwise
+		 * xfs_vm_releasepage() is called on it and gets confused.
 		 */
-		if (page->index >= end_index + 1 || offset_into_page == 0) {
-			unlock_page(page);
-			return 0;
-		}
+		if (page->index >= end_index + 1 || offset_into_page == 0)
+			goto redirty;
 
 		/*
 		 * The page straddles i_size.  It must be zeroed out on each
diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c
index ee24993..f96a734 100644
--- a/fs/xfs/xfs_attr_leaf.c
+++ b/fs/xfs/xfs_attr_leaf.c
@@ -172,7 +172,8 @@ xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes)
 	int dsize;
 	xfs_mount_t *mp = dp->i_mount;
 
-	offset = (XFS_LITINO(mp) - bytes) >> 3; /* rounded down */
+	/* rounded down */
+	offset = (XFS_LITINO(mp, dp->i_d.di_version) - bytes) >> 3;
 
 	switch (dp->i_d.di_format) {
 	case XFS_DINODE_FMT_DEV:
@@ -243,7 +244,8 @@ xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes)
 	minforkoff = roundup(minforkoff, 8) >> 3;
 
 	/* attr fork btree root can have at least this many key/ptr pairs */
-	maxforkoff = XFS_LITINO(mp) - XFS_BMDR_SPACE_CALC(MINABTPTRS);
+	maxforkoff = XFS_LITINO(mp, dp->i_d.di_version) -
+			XFS_BMDR_SPACE_CALC(MINABTPTRS);
 	maxforkoff = maxforkoff >> 3;	/* rounded down */
 
 	if (offset >= maxforkoff)
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index b44af92..20efb39 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -52,175 +52,72 @@
 kmem_zone_t		*xfs_bmap_free_item_zone;
 
 /*
- * Prototypes for internal bmap routines.
+ * Miscellaneous helper functions
  */
 
-#ifdef DEBUG
-STATIC void
-xfs_bmap_check_leaf_extents(
-	struct xfs_btree_cur	*cur,
-	struct xfs_inode	*ip,
-	int			whichfork);
-#else
-#define xfs_bmap_check_leaf_extents(cur, ip, whichfork)		do { } while (0)
-#endif
-
-
-/*
- * Called from xfs_bmap_add_attrfork to handle extents format files.
- */
-STATIC int					/* error */
-xfs_bmap_add_attrfork_extents(
-	xfs_trans_t		*tp,		/* transaction pointer */
-	xfs_inode_t		*ip,		/* incore inode pointer */
-	xfs_fsblock_t		*firstblock,	/* first block allocated */
-	xfs_bmap_free_t		*flist,		/* blocks to free at commit */
-	int			*flags);	/* inode logging flags */
-
-/*
- * Called from xfs_bmap_add_attrfork to handle local format files.
- */
-STATIC int					/* error */
-xfs_bmap_add_attrfork_local(
-	xfs_trans_t		*tp,		/* transaction pointer */
-	xfs_inode_t		*ip,		/* incore inode pointer */
-	xfs_fsblock_t		*firstblock,	/* first block allocated */
-	xfs_bmap_free_t		*flist,		/* blocks to free at commit */
-	int			*flags);	/* inode logging flags */
-
-/*
- * xfs_bmap_alloc is called by xfs_bmapi to allocate an extent for a file.
- * It figures out where to ask the underlying allocator to put the new extent.
- */
-STATIC int				/* error */
-xfs_bmap_alloc(
-	xfs_bmalloca_t		*ap);	/* bmap alloc argument struct */
-
-/*
- * Transform a btree format file with only one leaf node, where the
- * extents list will fit in the inode, into an extents format file.
- * Since the file extents are already in-core, all we have to do is
- * give up the space for the btree root and pitch the leaf block.
- */
-STATIC int				/* error */
-xfs_bmap_btree_to_extents(
-	xfs_trans_t		*tp,	/* transaction pointer */
-	xfs_inode_t		*ip,	/* incore inode pointer */
-	xfs_btree_cur_t		*cur,	/* btree cursor */
-	int			*logflagsp, /* inode logging flags */
-	int			whichfork); /* data or attr fork */
-
-/*
- * Remove the entry "free" from the free item list.  Prev points to the
- * previous entry, unless "free" is the head of the list.
- */
-STATIC void
-xfs_bmap_del_free(
-	xfs_bmap_free_t		*flist,	/* free item list header */
-	xfs_bmap_free_item_t	*prev,	/* previous item on list, if any */
-	xfs_bmap_free_item_t	*free);	/* list item to be freed */
-
-/*
- * Convert an extents-format file into a btree-format file.
- * The new file will have a root block (in the inode) and a single child block.
- */
-STATIC int					/* error */
-xfs_bmap_extents_to_btree(
-	xfs_trans_t		*tp,		/* transaction pointer */
-	xfs_inode_t		*ip,		/* incore inode pointer */
-	xfs_fsblock_t		*firstblock,	/* first-block-allocated */
-	xfs_bmap_free_t		*flist,		/* blocks freed in xaction */
-	xfs_btree_cur_t		**curp,		/* cursor returned to caller */
-	int			wasdel,		/* converting a delayed alloc */
-	int			*logflagsp,	/* inode logging flags */
-	int			whichfork);	/* data or attr fork */
-
-/*
- * Convert a local file to an extents file.
- * This code is sort of bogus, since the file data needs to get
- * logged so it won't be lost.  The bmap-level manipulations are ok, though.
- */
-STATIC int				/* error */
-xfs_bmap_local_to_extents(
-	xfs_trans_t	*tp,		/* transaction pointer */
-	xfs_inode_t	*ip,		/* incore inode pointer */
-	xfs_fsblock_t	*firstblock,	/* first block allocated in xaction */
-	xfs_extlen_t	total,		/* total blocks needed by transaction */
-	int		*logflagsp,	/* inode logging flags */
-	int		whichfork,	/* data or attr fork */
-	void		(*init_fn)(struct xfs_buf *bp,
-				   struct xfs_inode *ip,
-				   struct xfs_ifork *ifp));
-
-/*
- * Search the extents list for the inode, for the extent containing bno.
- * If bno lies in a hole, point to the next entry.  If bno lies past eof,
- * *eofp will be set, and *prevp will contain the last entry (null if none).
- * Else, *lastxp will be set to the index of the found
- * entry; *gotp will contain the entry.
- */
-STATIC xfs_bmbt_rec_host_t *		/* pointer to found extent entry */
-xfs_bmap_search_extents(
-	xfs_inode_t	*ip,		/* incore inode pointer */
-	xfs_fileoff_t	bno,		/* block number searched for */
-	int		whichfork,	/* data or attr fork */
-	int		*eofp,		/* out: end of file found */
-	xfs_extnum_t	*lastxp,	/* out: last extent index */
-	xfs_bmbt_irec_t	*gotp,		/* out: extent entry found */
-	xfs_bmbt_irec_t	*prevp);	/* out: previous extent entry found */
-
-/*
- * Compute the worst-case number of indirect blocks that will be used
- * for ip's delayed extent of length "len".
- */
-STATIC xfs_filblks_t
-xfs_bmap_worst_indlen(
-	xfs_inode_t		*ip,	/* incore inode pointer */
-	xfs_filblks_t		len);	/* delayed extent length */
-
-#ifdef DEBUG
 /*
- * Perform various validation checks on the values being returned
- * from xfs_bmapi().
+ * Compute and fill in the value of the maximum depth of a bmap btree
+ * in this filesystem.  Done once, during mount.
  */
-STATIC void
-xfs_bmap_validate_ret(
-	xfs_fileoff_t		bno,
-	xfs_filblks_t		len,
-	int			flags,
-	xfs_bmbt_irec_t		*mval,
-	int			nmap,
-	int			ret_nmap);
-#else
-#define	xfs_bmap_validate_ret(bno,len,flags,mval,onmap,nmap)
-#endif /* DEBUG */
-
-STATIC int
-xfs_bmap_count_tree(
-	xfs_mount_t     *mp,
-	xfs_trans_t     *tp,
-	xfs_ifork_t	*ifp,
-	xfs_fsblock_t   blockno,
-	int             levelin,
-	int		*count);
-
-STATIC void
-xfs_bmap_count_leaves(
-	xfs_ifork_t		*ifp,
-	xfs_extnum_t		idx,
-	int			numrecs,
-	int			*count);
+void
+xfs_bmap_compute_maxlevels(
+	xfs_mount_t	*mp,		/* file system mount structure */
+	int		whichfork)	/* data or attr fork */
+{
+	int		level;		/* btree level */
+	uint		maxblocks;	/* max blocks at this level */
+	uint		maxleafents;	/* max leaf entries possible */
+	int		maxrootrecs;	/* max records in root block */
+	int		minleafrecs;	/* min records in leaf block */
+	int		minnoderecs;	/* min records in node block */
+	int		sz;		/* root block size */
 
-STATIC void
-xfs_bmap_disk_count_leaves(
-	struct xfs_mount	*mp,
-	struct xfs_btree_block	*block,
-	int			numrecs,
-	int			*count);
+	/*
+	 * The maximum number of extents in a file, hence the maximum
+	 * number of leaf entries, is controlled by the type of di_nextents
+	 * (a signed 32-bit number, xfs_extnum_t), or by di_anextents
+	 * (a signed 16-bit number, xfs_aextnum_t).
+	 *
+	 * Note that we can no longer assume that if we are in ATTR1 that
+	 * the fork offset of all the inodes will be
+	 * (xfs_default_attroffset(ip) >> 3) because we could have mounted
+	 * with ATTR2 and then mounted back with ATTR1, keeping the
+	 * di_forkoff's fixed but probably at various positions. Therefore,
+	 * for both ATTR1 and ATTR2 we have to assume the worst case scenario
+	 * of a minimum size available.
+	 */
+	if (whichfork == XFS_DATA_FORK) {
+		maxleafents = MAXEXTNUM;
+		sz = XFS_BMDR_SPACE_CALC(MINDBTPTRS);
+	} else {
+		maxleafents = MAXAEXTNUM;
+		sz = XFS_BMDR_SPACE_CALC(MINABTPTRS);
+	}
+	maxrootrecs = xfs_bmdr_maxrecs(mp, sz, 0);
+	minleafrecs = mp->m_bmap_dmnr[0];
+	minnoderecs = mp->m_bmap_dmnr[1];
+	maxblocks = (maxleafents + minleafrecs - 1) / minleafrecs;
+	for (level = 1; maxblocks > 1; level++) {
+		if (maxblocks <= maxrootrecs)
+			maxblocks = 1;
+		else
+			maxblocks = (maxblocks + minnoderecs - 1) / minnoderecs;
+	}
+	mp->m_bm_maxlevels[whichfork] = level;
+}
 
 /*
- * Bmap internal routines.
+ * Convert the given file system block to a disk block.  We have to treat it
+ * differently based on whether the file is a real time file or not, because the
+ * bmap code does.
  */
+xfs_daddr_t
+xfs_fsb_to_db(struct xfs_inode *ip, xfs_fsblock_t fsb)
+{
+	return (XFS_IS_REALTIME_INODE(ip) ? \
+		 (xfs_daddr_t)XFS_FSB_TO_BB((ip)->i_mount, (fsb)) : \
+		 XFS_FSB_TO_DADDR((ip)->i_mount, (fsb)));
+}
 
 STATIC int				/* error */
 xfs_bmbt_lookup_eq(
@@ -290,5935 +187,5914 @@ xfs_bmbt_update(
 }
 
 /*
- * Called from xfs_bmap_add_attrfork to handle btree format files.
+ * Compute the worst-case number of indirect blocks that will be used
+ * for ip's delayed extent of length "len".
  */
-STATIC int					/* error */
-xfs_bmap_add_attrfork_btree(
-	xfs_trans_t		*tp,		/* transaction pointer */
-	xfs_inode_t		*ip,		/* incore inode pointer */
-	xfs_fsblock_t		*firstblock,	/* first block allocated */
-	xfs_bmap_free_t		*flist,		/* blocks to free at commit */
-	int			*flags)		/* inode logging flags */
+STATIC xfs_filblks_t
+xfs_bmap_worst_indlen(
+	xfs_inode_t	*ip,		/* incore inode pointer */
+	xfs_filblks_t	len)		/* delayed extent length */
 {
-	xfs_btree_cur_t		*cur;		/* btree cursor */
-	int			error;		/* error return value */
-	xfs_mount_t		*mp;		/* file system mount struct */
-	int			stat;		/* newroot status */
+	int		level;		/* btree level number */
+	int		maxrecs;	/* maximum record count at this level */
+	xfs_mount_t	*mp;		/* mount structure */
+	xfs_filblks_t	rval;		/* return value */
 
 	mp = ip->i_mount;
-	if (ip->i_df.if_broot_bytes <= XFS_IFORK_DSIZE(ip))
-		*flags |= XFS_ILOG_DBROOT;
-	else {
-		cur = xfs_bmbt_init_cursor(mp, tp, ip, XFS_DATA_FORK);
-		cur->bc_private.b.flist = flist;
-		cur->bc_private.b.firstblock = *firstblock;
-		if ((error = xfs_bmbt_lookup_ge(cur, 0, 0, 0, &stat)))
-			goto error0;
-		/* must be at least one entry */
-		XFS_WANT_CORRUPTED_GOTO(stat == 1, error0);
-		if ((error = xfs_btree_new_iroot(cur, flags, &stat)))
-			goto error0;
-		if (stat == 0) {
-			xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
-			return XFS_ERROR(ENOSPC);
-		}
-		*firstblock = cur->bc_private.b.firstblock;
-		cur->bc_private.b.allocated = 0;
-		xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
+	maxrecs = mp->m_bmap_dmxr[0];
+	for (level = 0, rval = 0;
+	     level < XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK);
+	     level++) {
+		len += maxrecs - 1;
+		do_div(len, maxrecs);
+		rval += len;
+		if (len == 1)
+			return rval + XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) -
+				level - 1;
+		if (level == 0)
+			maxrecs = mp->m_bmap_dmxr[1];
 	}
-	return 0;
-error0:
-	xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
-	return error;
+	return rval;
 }
 
 /*
- * Called from xfs_bmap_add_attrfork to handle extents format files.
+ * Calculate the default attribute fork offset for newly created inodes.
  */
-STATIC int					/* error */
-xfs_bmap_add_attrfork_extents(
-	xfs_trans_t		*tp,		/* transaction pointer */
-	xfs_inode_t		*ip,		/* incore inode pointer */
-	xfs_fsblock_t		*firstblock,	/* first block allocated */
-	xfs_bmap_free_t		*flist,		/* blocks to free at commit */
-	int			*flags)		/* inode logging flags */
+uint
+xfs_default_attroffset(
+	struct xfs_inode	*ip)
 {
-	xfs_btree_cur_t		*cur;		/* bmap btree cursor */
-	int			error;		/* error return value */
+	struct xfs_mount	*mp = ip->i_mount;
+	uint			offset;
 
-	if (ip->i_d.di_nextents * sizeof(xfs_bmbt_rec_t) <= XFS_IFORK_DSIZE(ip))
-		return 0;
-	cur = NULL;
-	error = xfs_bmap_extents_to_btree(tp, ip, firstblock, flist, &cur, 0,
-		flags, XFS_DATA_FORK);
-	if (cur) {
-		cur->bc_private.b.allocated = 0;
-		xfs_btree_del_cursor(cur,
-			error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR);
+	if (mp->m_sb.sb_inodesize == 256) {
+		offset = XFS_LITINO(mp, ip->i_d.di_version) -
+				XFS_BMDR_SPACE_CALC(MINABTPTRS);
+	} else {
+		offset = XFS_BMDR_SPACE_CALC(6 * MINABTPTRS);
 	}
-	return error;
+
+	ASSERT(offset < XFS_LITINO(mp, ip->i_d.di_version));
+	return offset;
 }
 
 /*
- * Block initialisation functions for local to extent format conversion.
- * As these get more complex, they will be moved to the relevant files,
- * but for now they are too simple to worry about.
+ * Helper routine to reset inode di_forkoff field when switching
+ * attribute fork from local to extent format - we reset it where
+ * possible to make space available for inline data fork extents.
  */
 STATIC void
-xfs_bmap_local_to_extents_init_fn(
-	struct xfs_buf		*bp,
-	struct xfs_inode	*ip,
-	struct xfs_ifork	*ifp)
+xfs_bmap_forkoff_reset(
+	xfs_mount_t	*mp,
+	xfs_inode_t	*ip,
+	int		whichfork)
 {
-	bp->b_ops = &xfs_bmbt_buf_ops;
-	memcpy(bp->b_addr, ifp->if_u1.if_data, ifp->if_bytes);
+	if (whichfork == XFS_ATTR_FORK &&
+	    ip->i_d.di_format != XFS_DINODE_FMT_DEV &&
+	    ip->i_d.di_format != XFS_DINODE_FMT_UUID &&
+	    ip->i_d.di_format != XFS_DINODE_FMT_BTREE) {
+		uint	dfl_forkoff = xfs_default_attroffset(ip) >> 3;
+
+		if (dfl_forkoff > ip->i_d.di_forkoff)
+			ip->i_d.di_forkoff = dfl_forkoff;
+	}
 }
 
+/*
+ * Extent tree block counting routines.
+ */
+
+/*
+ * Count leaf blocks given a range of extent records.
+ */
 STATIC void
-xfs_symlink_local_to_remote(
-	struct xfs_buf		*bp,
-	struct xfs_inode	*ip,
-	struct xfs_ifork	*ifp)
+xfs_bmap_count_leaves(
+	xfs_ifork_t		*ifp,
+	xfs_extnum_t		idx,
+	int			numrecs,
+	int			*count)
 {
-	/* remote symlink blocks are not verifiable until CRCs come along */
-	bp->b_ops = NULL;
-	memcpy(bp->b_addr, ifp->if_u1.if_data, ifp->if_bytes);
+	int		b;
+
+	for (b = 0; b < numrecs; b++) {
+		xfs_bmbt_rec_host_t *frp = xfs_iext_get_ext(ifp, idx + b);
+		*count += xfs_bmbt_get_blockcount(frp);
+	}
 }
 
 /*
- * Called from xfs_bmap_add_attrfork to handle local format files. Each
- * different data fork content type needs a different callout to do the
- * conversion. Some are basic and only require special block initialisation
- * callouts for the data formating, others (directories) are so specialised they
- * handle everything themselves.
- *
- * XXX (dgc): investigate whether directory conversion can use the generic
- * formatting callout. It should be possible - it's just a very complex
- * formatter. it would also require passing the transaction through to the init
- * function.
+ * Count leaf blocks given a range of extent records originally
+ * in btree format.
  */
-STATIC int					/* error */
-xfs_bmap_add_attrfork_local(
-	xfs_trans_t		*tp,		/* transaction pointer */
-	xfs_inode_t		*ip,		/* incore inode pointer */
-	xfs_fsblock_t		*firstblock,	/* first block allocated */
-	xfs_bmap_free_t		*flist,		/* blocks to free at commit */
-	int			*flags)		/* inode logging flags */
+STATIC void
+xfs_bmap_disk_count_leaves(
+	struct xfs_mount	*mp,
+	struct xfs_btree_block	*block,
+	int			numrecs,
+	int			*count)
 {
-	xfs_da_args_t		dargs;		/* args for dir/attr code */
-
-	if (ip->i_df.if_bytes <= XFS_IFORK_DSIZE(ip))
-		return 0;
+	int		b;
+	xfs_bmbt_rec_t	*frp;
 
-	if (S_ISDIR(ip->i_d.di_mode)) {
-		memset(&dargs, 0, sizeof(dargs));
-		dargs.dp = ip;
-		dargs.firstblock = firstblock;
-		dargs.flist = flist;
-		dargs.total = ip->i_mount->m_dirblkfsbs;
-		dargs.whichfork = XFS_DATA_FORK;
-		dargs.trans = tp;
-		return xfs_dir2_sf_to_block(&dargs);
+	for (b = 1; b <= numrecs; b++) {
+		frp = XFS_BMBT_REC_ADDR(mp, block, b);
+		*count += xfs_bmbt_disk_get_blockcount(frp);
 	}
-
-	if (S_ISLNK(ip->i_d.di_mode))
-		return xfs_bmap_local_to_extents(tp, ip, firstblock, 1,
-						 flags, XFS_DATA_FORK,
-						 xfs_symlink_local_to_remote);
-
-	return xfs_bmap_local_to_extents(tp, ip, firstblock, 1, flags,
-					 XFS_DATA_FORK,
-					 xfs_bmap_local_to_extents_init_fn);
 }
 
 /*
- * Convert a delayed allocation to a real allocation.
+ * Recursively walks each level of a btree
+ * to count total fsblocks is use.
  */
-STATIC int				/* error */
-xfs_bmap_add_extent_delay_real(
-	struct xfs_bmalloca	*bma)
+STATIC int                                     /* error */
+xfs_bmap_count_tree(
+	xfs_mount_t     *mp,            /* file system mount point */
+	xfs_trans_t     *tp,            /* transaction pointer */
+	xfs_ifork_t	*ifp,		/* inode fork pointer */
+	xfs_fsblock_t   blockno,	/* file system block number */
+	int             levelin,	/* level in btree */
+	int		*count)		/* Count of blocks */
 {
-	struct xfs_bmbt_irec	*new = &bma->got;
-	int			diff;	/* temp value */
-	xfs_bmbt_rec_host_t	*ep;	/* extent entry for idx */
-	int			error;	/* error return value */
-	int			i;	/* temp state */
-	xfs_ifork_t		*ifp;	/* inode fork pointer */
-	xfs_fileoff_t		new_endoff;	/* end offset of new entry */
-	xfs_bmbt_irec_t		r[3];	/* neighbor extent entries */
-					/* left is 0, right is 1, prev is 2 */
-	int			rval=0;	/* return value (logging flags) */
-	int			state = 0;/* state bits, accessed thru macros */
-	xfs_filblks_t		da_new; /* new count del alloc blocks used */
-	xfs_filblks_t		da_old; /* old count del alloc blocks used */
-	xfs_filblks_t		temp=0;	/* value for da_new calculations */
-	xfs_filblks_t		temp2=0;/* value for da_new calculations */
-	int			tmp_rval;	/* partial logging flags */
+	int			error;
+	xfs_buf_t		*bp, *nbp;
+	int			level = levelin;
+	__be64			*pp;
+	xfs_fsblock_t           bno = blockno;
+	xfs_fsblock_t		nextbno;
+	struct xfs_btree_block	*block, *nextblock;
+	int			numrecs;
 
-	ifp = XFS_IFORK_PTR(bma->ip, XFS_DATA_FORK);
+	error = xfs_btree_read_bufl(mp, tp, bno, 0, &bp, XFS_BMAP_BTREE_REF,
+						&xfs_bmbt_buf_ops);
+	if (error)
+		return error;
+	*count += 1;
+	block = XFS_BUF_TO_BLOCK(bp);
 
-	ASSERT(bma->idx >= 0);
-	ASSERT(bma->idx <= ifp->if_bytes / sizeof(struct xfs_bmbt_rec));
-	ASSERT(!isnullstartblock(new->br_startblock));
-	ASSERT(!bma->cur ||
-	       (bma->cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL));
+	if (--level) {
+		/* Not at node above leaves, count this level of nodes */
+		nextbno = be64_to_cpu(block->bb_u.l.bb_rightsib);
+		while (nextbno != NULLFSBLOCK) {
+			error = xfs_btree_read_bufl(mp, tp, nextbno, 0, &nbp,
+						XFS_BMAP_BTREE_REF,
+						&xfs_bmbt_buf_ops);
+			if (error)
+				return error;
+			*count += 1;
+			nextblock = XFS_BUF_TO_BLOCK(nbp);
+			nextbno = be64_to_cpu(nextblock->bb_u.l.bb_rightsib);
+			xfs_trans_brelse(tp, nbp);
+		}
 
-	XFS_STATS_INC(xs_add_exlist);
+		/* Dive to the next level */
+		pp = XFS_BMBT_PTR_ADDR(mp, block, 1, mp->m_bmap_dmxr[1]);
+		bno = be64_to_cpu(*pp);
+		if (unlikely((error =
+		     xfs_bmap_count_tree(mp, tp, ifp, bno, level, count)) < 0)) {
+			xfs_trans_brelse(tp, bp);
+			XFS_ERROR_REPORT("xfs_bmap_count_tree(1)",
+					 XFS_ERRLEVEL_LOW, mp);
+			return XFS_ERROR(EFSCORRUPTED);
+		}
+		xfs_trans_brelse(tp, bp);
+	} else {
+		/* count all level 1 nodes and their leaves */
+		for (;;) {
+			nextbno = be64_to_cpu(block->bb_u.l.bb_rightsib);
+			numrecs = be16_to_cpu(block->bb_numrecs);
+			xfs_bmap_disk_count_leaves(mp, block, numrecs, count);
+			xfs_trans_brelse(tp, bp);
+			if (nextbno == NULLFSBLOCK)
+				break;
+			bno = nextbno;
+			error = xfs_btree_read_bufl(mp, tp, bno, 0, &bp,
+						XFS_BMAP_BTREE_REF,
+						&xfs_bmbt_buf_ops);
+			if (error)
+				return error;
+			*count += 1;
+			block = XFS_BUF_TO_BLOCK(bp);
+		}
+	}
+	return 0;
+}
 
-#define	LEFT		r[0]
-#define	RIGHT		r[1]
-#define	PREV		r[2]
+/*
+ * Count fsblocks of the given fork.
+ */
+int						/* error */
+xfs_bmap_count_blocks(
+	xfs_trans_t		*tp,		/* transaction pointer */
+	xfs_inode_t		*ip,		/* incore inode */
+	int			whichfork,	/* data or attr fork */
+	int			*count)		/* out: count of blocks */
+{
+	struct xfs_btree_block	*block;	/* current btree block */
+	xfs_fsblock_t		bno;	/* block # of "block" */
+	xfs_ifork_t		*ifp;	/* fork structure */
+	int			level;	/* btree level, for checking */
+	xfs_mount_t		*mp;	/* file system mount structure */
+	__be64			*pp;	/* pointer to block address */
+
+	bno = NULLFSBLOCK;
+	mp = ip->i_mount;
+	ifp = XFS_IFORK_PTR(ip, whichfork);
+	if ( XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS ) {
+		xfs_bmap_count_leaves(ifp, 0,
+			ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t),
+			count);
+		return 0;
+	}
 
 	/*
-	 * Set up a bunch of variables to make the tests simpler.
+	 * Root level must use BMAP_BROOT_PTR_ADDR macro to get ptr out.
 	 */
-	ep = xfs_iext_get_ext(ifp, bma->idx);
-	xfs_bmbt_get_all(ep, &PREV);
-	new_endoff = new->br_startoff + new->br_blockcount;
-	ASSERT(PREV.br_startoff <= new->br_startoff);
-	ASSERT(PREV.br_startoff + PREV.br_blockcount >= new_endoff);
+	block = ifp->if_broot;
+	level = be16_to_cpu(block->bb_level);
+	ASSERT(level > 0);
+	pp = XFS_BMAP_BROOT_PTR_ADDR(mp, block, 1, ifp->if_broot_bytes);
+	bno = be64_to_cpu(*pp);
+	ASSERT(bno != NULLDFSBNO);
+	ASSERT(XFS_FSB_TO_AGNO(mp, bno) < mp->m_sb.sb_agcount);
+	ASSERT(XFS_FSB_TO_AGBNO(mp, bno) < mp->m_sb.sb_agblocks);
 
-	da_old = startblockval(PREV.br_startblock);
-	da_new = 0;
+	if (unlikely(xfs_bmap_count_tree(mp, tp, ifp, bno, level, count) < 0)) {
+		XFS_ERROR_REPORT("xfs_bmap_count_blocks(2)", XFS_ERRLEVEL_LOW,
+				 mp);
+		return XFS_ERROR(EFSCORRUPTED);
+	}
 
-	/*
-	 * Set flags determining what part of the previous delayed allocation
-	 * extent is being replaced by a real allocation.
-	 */
-	if (PREV.br_startoff == new->br_startoff)
-		state |= BMAP_LEFT_FILLING;
-	if (PREV.br_startoff + PREV.br_blockcount == new_endoff)
-		state |= BMAP_RIGHT_FILLING;
+	return 0;
+}
 
-	/*
-	 * Check and set flags if this segment has a left neighbor.
-	 * Don't set contiguous if the combined extent would be too large.
-	 */
-	if (bma->idx > 0) {
-		state |= BMAP_LEFT_VALID;
-		xfs_bmbt_get_all(xfs_iext_get_ext(ifp, bma->idx - 1), &LEFT);
+/*
+ * Debug/sanity checking code
+ */
 
-		if (isnullstartblock(LEFT.br_startblock))
-			state |= BMAP_LEFT_DELAY;
-	}
+STATIC int
+xfs_bmap_sanity_check(
+	struct xfs_mount	*mp,
+	struct xfs_buf		*bp,
+	int			level)
+{
+	struct xfs_btree_block  *block = XFS_BUF_TO_BLOCK(bp);
 
-	if ((state & BMAP_LEFT_VALID) && !(state & BMAP_LEFT_DELAY) &&
-	    LEFT.br_startoff + LEFT.br_blockcount == new->br_startoff &&
-	    LEFT.br_startblock + LEFT.br_blockcount == new->br_startblock &&
-	    LEFT.br_state == new->br_state &&
-	    LEFT.br_blockcount + new->br_blockcount <= MAXEXTLEN)
-		state |= BMAP_LEFT_CONTIG;
+	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])
+		return 0;
+	return 1;
+}
 
-	/*
-	 * Check and set flags if this segment has a right neighbor.
-	 * Don't set contiguous if the combined extent would be too large.
-	 * Also check for all-three-contiguous being too large.
-	 */
-	if (bma->idx < bma->ip->i_df.if_bytes / (uint)sizeof(xfs_bmbt_rec_t) - 1) {
-		state |= BMAP_RIGHT_VALID;
-		xfs_bmbt_get_all(xfs_iext_get_ext(ifp, bma->idx + 1), &RIGHT);
+#ifdef DEBUG
+STATIC struct xfs_buf *
+xfs_bmap_get_bp(
+	struct xfs_btree_cur	*cur,
+	xfs_fsblock_t		bno)
+{
+	struct xfs_log_item_desc *lidp;
+	int			i;
 
-		if (isnullstartblock(RIGHT.br_startblock))
-			state |= BMAP_RIGHT_DELAY;
+	if (!cur)
+		return NULL;
+
+	for (i = 0; i < XFS_BTREE_MAXLEVELS; i++) {
+		if (!cur->bc_bufs[i])
+			break;
+		if (XFS_BUF_ADDR(cur->bc_bufs[i]) == bno)
+			return cur->bc_bufs[i];
 	}
 
-	if ((state & BMAP_RIGHT_VALID) && !(state & BMAP_RIGHT_DELAY) &&
-	    new_endoff == RIGHT.br_startoff &&
-	    new->br_startblock + new->br_blockcount == RIGHT.br_startblock &&
-	    new->br_state == RIGHT.br_state &&
-	    new->br_blockcount + RIGHT.br_blockcount <= MAXEXTLEN &&
-	    ((state & (BMAP_LEFT_CONTIG | BMAP_LEFT_FILLING |
-		       BMAP_RIGHT_FILLING)) !=
-		      (BMAP_LEFT_CONTIG | BMAP_LEFT_FILLING |
-		       BMAP_RIGHT_FILLING) ||
-	     LEFT.br_blockcount + new->br_blockcount + RIGHT.br_blockcount
-			<= MAXEXTLEN))
-		state |= BMAP_RIGHT_CONTIG;
+	/* Chase down all the log items to see if the bp is there */
+	list_for_each_entry(lidp, &cur->bc_tp->t_items, lid_trans) {
+		struct xfs_buf_log_item	*bip;
+		bip = (struct xfs_buf_log_item *)lidp->lid_item;
+		if (bip->bli_item.li_type == XFS_LI_BUF &&
+		    XFS_BUF_ADDR(bip->bli_buf) == bno)
+			return bip->bli_buf;
+	}
 
-	error = 0;
-	/*
-	 * Switch out based on the FILLING and CONTIG state bits.
-	 */
-	switch (state & (BMAP_LEFT_FILLING | BMAP_LEFT_CONTIG |
-			 BMAP_RIGHT_FILLING | BMAP_RIGHT_CONTIG)) {
-	case BMAP_LEFT_FILLING | BMAP_LEFT_CONTIG |
-	     BMAP_RIGHT_FILLING | BMAP_RIGHT_CONTIG:
-		/*
-		 * Filling in all of a previously delayed allocation extent.
-		 * The left and right neighbors are both contiguous with new.
-		 */
-		bma->idx--;
-		trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_);
-		xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, bma->idx),
-			LEFT.br_blockcount + PREV.br_blockcount +
-			RIGHT.br_blockcount);
-		trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_);
+	return NULL;
+}
 
-		xfs_iext_remove(bma->ip, bma->idx + 1, 2, state);
-		bma->ip->i_d.di_nextents--;
-		if (bma->cur == NULL)
-			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
-		else {
-			rval = XFS_ILOG_CORE;
-			error = xfs_bmbt_lookup_eq(bma->cur, RIGHT.br_startoff,
-					RIGHT.br_startblock,
-					RIGHT.br_blockcount, &i);
-			if (error)
-				goto done;
-			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
-			error = xfs_btree_delete(bma->cur, &i);
-			if (error)
-				goto done;
-			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
-			error = xfs_btree_decrement(bma->cur, 0, &i);
-			if (error)
-				goto done;
-			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
-			error = xfs_bmbt_update(bma->cur, LEFT.br_startoff,
-					LEFT.br_startblock,
-					LEFT.br_blockcount +
-					PREV.br_blockcount +
-					RIGHT.br_blockcount, LEFT.br_state);
-			if (error)
-				goto done;
-		}
-		break;
+STATIC void
+xfs_check_block(
+	struct xfs_btree_block	*block,
+	xfs_mount_t		*mp,
+	int			root,
+	short			sz)
+{
+	int			i, j, dmxr;
+	__be64			*pp, *thispa;	/* pointer to block address */
+	xfs_bmbt_key_t		*prevp, *keyp;
 
-	case BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING | BMAP_LEFT_CONTIG:
-		/*
-		 * Filling in all of a previously delayed allocation extent.
-		 * The left neighbor is contiguous, the right is not.
-		 */
-		bma->idx--;
+	ASSERT(be16_to_cpu(block->bb_level) > 0);
 
-		trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_);
-		xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, bma->idx),
-			LEFT.br_blockcount + PREV.br_blockcount);
-		trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_);
+	prevp = NULL;
+	for( i = 1; i <= xfs_btree_get_numrecs(block); i++) {
+		dmxr = mp->m_bmap_dmxr[0];
+		keyp = XFS_BMBT_KEY_ADDR(mp, block, i);
 
-		xfs_iext_remove(bma->ip, bma->idx + 1, 1, state);
-		if (bma->cur == NULL)
-			rval = XFS_ILOG_DEXT;
-		else {
-			rval = 0;
-			error = xfs_bmbt_lookup_eq(bma->cur, LEFT.br_startoff,
-					LEFT.br_startblock, LEFT.br_blockcount,
-					&i);
-			if (error)
-				goto done;
-			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
-			error = xfs_bmbt_update(bma->cur, LEFT.br_startoff,
-					LEFT.br_startblock,
-					LEFT.br_blockcount +
-					PREV.br_blockcount, LEFT.br_state);
-			if (error)
-				goto done;
+		if (prevp) {
+			ASSERT(be64_to_cpu(prevp->br_startoff) <
+			       be64_to_cpu(keyp->br_startoff));
 		}
-		break;
+		prevp = keyp;
 
-	case BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING | BMAP_RIGHT_CONTIG:
 		/*
-		 * Filling in all of a previously delayed allocation extent.
-		 * The right neighbor is contiguous, the left is not.
+		 * Compare the block numbers to see if there are dups.
 		 */
-		trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_);
-		xfs_bmbt_set_startblock(ep, new->br_startblock);
-		xfs_bmbt_set_blockcount(ep,
-			PREV.br_blockcount + RIGHT.br_blockcount);
-		trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_);
+		if (root)
+			pp = XFS_BMAP_BROOT_PTR_ADDR(mp, block, i, sz);
+		else
+			pp = XFS_BMBT_PTR_ADDR(mp, block, i, dmxr);
 
-		xfs_iext_remove(bma->ip, bma->idx + 1, 1, state);
-		if (bma->cur == NULL)
-			rval = XFS_ILOG_DEXT;
-		else {
-			rval = 0;
-			error = xfs_bmbt_lookup_eq(bma->cur, RIGHT.br_startoff,
-					RIGHT.br_startblock,
-					RIGHT.br_blockcount, &i);
-			if (error)
-				goto done;
-			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
-			error = xfs_bmbt_update(bma->cur, PREV.br_startoff,
-					new->br_startblock,
-					PREV.br_blockcount +
-					RIGHT.br_blockcount, PREV.br_state);
-			if (error)
-				goto done;
+		for (j = i+1; j <= be16_to_cpu(block->bb_numrecs); j++) {
+			if (root)
+				thispa = XFS_BMAP_BROOT_PTR_ADDR(mp, block, j, sz);
+			else
+				thispa = XFS_BMBT_PTR_ADDR(mp, block, j, dmxr);
+			if (*thispa == *pp) {
+				xfs_warn(mp, "%s: thispa(%d) == pp(%d) %Ld",
+					__func__, j, i,
+					(unsigned long long)be64_to_cpu(*thispa));
+				panic("%s: ptrs are equal in node\n",
+					__func__);
+			}
 		}
-		break;
+	}
+}
 
-	case BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING:
-		/*
-		 * Filling in all of a previously delayed allocation extent.
-		 * Neither the left nor right neighbors are contiguous with
-		 * the new one.
-		 */
-		trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_);
-		xfs_bmbt_set_startblock(ep, new->br_startblock);
-		trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_);
+/*
+ * Check that the extents for the inode ip are in the right order in all
+ * btree leaves.
+ */
 
-		bma->ip->i_d.di_nextents++;
-		if (bma->cur == NULL)
-			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
-		else {
-			rval = XFS_ILOG_CORE;
-			error = xfs_bmbt_lookup_eq(bma->cur, new->br_startoff,
-					new->br_startblock, new->br_blockcount,
-					&i);
-			if (error)
-				goto done;
-			XFS_WANT_CORRUPTED_GOTO(i == 0, done);
-			bma->cur->bc_rec.b.br_state = XFS_EXT_NORM;
-			error = xfs_btree_insert(bma->cur, &i);
+STATIC void
+xfs_bmap_check_leaf_extents(
+	xfs_btree_cur_t		*cur,	/* btree cursor or null */
+	xfs_inode_t		*ip,		/* incore inode pointer */
+	int			whichfork)	/* data or attr fork */
+{
+	struct xfs_btree_block	*block;	/* current btree block */
+	xfs_fsblock_t		bno;	/* block # of "block" */
+	xfs_buf_t		*bp;	/* buffer for "block" */
+	int			error;	/* error return value */
+	xfs_extnum_t		i=0, j;	/* index into the extents list */
+	xfs_ifork_t		*ifp;	/* fork structure */
+	int			level;	/* btree level, for checking */
+	xfs_mount_t		*mp;	/* file system mount structure */
+	__be64			*pp;	/* pointer to block address */
+	xfs_bmbt_rec_t		*ep;	/* pointer to current extent */
+	xfs_bmbt_rec_t		last = {0, 0}; /* last extent in prev block */
+	xfs_bmbt_rec_t		*nextp;	/* pointer to next extent */
+	int			bp_release = 0;
+
+	if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE) {
+		return;
+	}
+
+	bno = NULLFSBLOCK;
+	mp = ip->i_mount;
+	ifp = XFS_IFORK_PTR(ip, whichfork);
+	block = ifp->if_broot;
+	/*
+	 * Root level must use BMAP_BROOT_PTR_ADDR macro to get ptr out.
+	 */
+	level = be16_to_cpu(block->bb_level);
+	ASSERT(level > 0);
+	xfs_check_block(block, mp, 1, ifp->if_broot_bytes);
+	pp = XFS_BMAP_BROOT_PTR_ADDR(mp, block, 1, ifp->if_broot_bytes);
+	bno = be64_to_cpu(*pp);
+
+	ASSERT(bno != NULLDFSBNO);
+	ASSERT(XFS_FSB_TO_AGNO(mp, bno) < mp->m_sb.sb_agcount);
+	ASSERT(XFS_FSB_TO_AGBNO(mp, bno) < mp->m_sb.sb_agblocks);
+
+	/*
+	 * Go down the tree until leaf level is reached, following the first
+	 * pointer (leftmost) at each level.
+	 */
+	while (level-- > 0) {
+		/* See if buf is in cur first */
+		bp_release = 0;
+		bp = xfs_bmap_get_bp(cur, XFS_FSB_TO_DADDR(mp, bno));
+		if (!bp) {
+			bp_release = 1;
+			error = xfs_btree_read_bufl(mp, NULL, bno, 0, &bp,
+						XFS_BMAP_BTREE_REF,
+						&xfs_bmbt_buf_ops);
 			if (error)
-				goto done;
-			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+				goto error_norelse;
 		}
-		break;
+		block = XFS_BUF_TO_BLOCK(bp);
+		XFS_WANT_CORRUPTED_GOTO(
+			xfs_bmap_sanity_check(mp, bp, level),
+			error0);
+		if (level == 0)
+			break;
 
-	case BMAP_LEFT_FILLING | BMAP_LEFT_CONTIG:
 		/*
-		 * Filling in the first part of a previous delayed allocation.
-		 * The left neighbor is contiguous.
+		 * Check this block for basic sanity (increasing keys and
+		 * no duplicate blocks).
 		 */
-		trace_xfs_bmap_pre_update(bma->ip, bma->idx - 1, state, _THIS_IP_);
-		xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, bma->idx - 1),
-			LEFT.br_blockcount + new->br_blockcount);
-		xfs_bmbt_set_startoff(ep,
-			PREV.br_startoff + new->br_blockcount);
-		trace_xfs_bmap_post_update(bma->ip, bma->idx - 1, state, _THIS_IP_);
 
-		temp = PREV.br_blockcount - new->br_blockcount;
-		trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_);
-		xfs_bmbt_set_blockcount(ep, temp);
-		if (bma->cur == NULL)
-			rval = XFS_ILOG_DEXT;
-		else {
-			rval = 0;
-			error = xfs_bmbt_lookup_eq(bma->cur, LEFT.br_startoff,
-					LEFT.br_startblock, LEFT.br_blockcount,
-					&i);
-			if (error)
-				goto done;
-			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
-			error = xfs_bmbt_update(bma->cur, LEFT.br_startoff,
-					LEFT.br_startblock,
-					LEFT.br_blockcount +
-					new->br_blockcount,
-					LEFT.br_state);
-			if (error)
-				goto done;
+		xfs_check_block(block, mp, 0, 0);
+		pp = XFS_BMBT_PTR_ADDR(mp, block, 1, mp->m_bmap_dmxr[1]);
+		bno = be64_to_cpu(*pp);
+		XFS_WANT_CORRUPTED_GOTO(XFS_FSB_SANITY_CHECK(mp, bno), error0);
+		if (bp_release) {
+			bp_release = 0;
+			xfs_trans_brelse(NULL, bp);
 		}
-		da_new = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(bma->ip, temp),
-			startblockval(PREV.br_startblock));
-		xfs_bmbt_set_startblock(ep, nullstartblock(da_new));
-		trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_);
+	}
 
-		bma->idx--;
-		break;
+	/*
+	 * Here with bp and block set to the leftmost leaf node in the tree.
+	 */
+	i = 0;
+
+	/*
+	 * Loop over all leaf nodes checking that all extents are in the right order.
+	 */
+	for (;;) {
+		xfs_fsblock_t	nextbno;
+		xfs_extnum_t	num_recs;
+
+
+		num_recs = xfs_btree_get_numrecs(block);
 
-	case BMAP_LEFT_FILLING:
 		/*
-		 * Filling in the first part of a previous delayed allocation.
-		 * The left neighbor is not contiguous.
+		 * Read-ahead the next leaf block, if any.
 		 */
-		trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_);
-		xfs_bmbt_set_startoff(ep, new_endoff);
-		temp = PREV.br_blockcount - new->br_blockcount;
-		xfs_bmbt_set_blockcount(ep, temp);
-		xfs_iext_insert(bma->ip, bma->idx, 1, new, state);
-		bma->ip->i_d.di_nextents++;
-		if (bma->cur == NULL)
-			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
-		else {
-			rval = XFS_ILOG_CORE;
-			error = xfs_bmbt_lookup_eq(bma->cur, new->br_startoff,
-					new->br_startblock, new->br_blockcount,
-					&i);
-			if (error)
-				goto done;
-			XFS_WANT_CORRUPTED_GOTO(i == 0, done);
-			bma->cur->bc_rec.b.br_state = XFS_EXT_NORM;
-			error = xfs_btree_insert(bma->cur, &i);
-			if (error)
-				goto done;
-			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
-		}
 
-		if (xfs_bmap_needs_btree(bma->ip, XFS_DATA_FORK)) {
-			error = xfs_bmap_extents_to_btree(bma->tp, bma->ip,
-					bma->firstblock, bma->flist,
-					&bma->cur, 1, &tmp_rval, XFS_DATA_FORK);
-			rval |= tmp_rval;
-			if (error)
-				goto done;
-		}
-		da_new = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(bma->ip, temp),
-			startblockval(PREV.br_startblock) -
-			(bma->cur ? bma->cur->bc_private.b.allocated : 0));
-		ep = xfs_iext_get_ext(ifp, bma->idx + 1);
-		xfs_bmbt_set_startblock(ep, nullstartblock(da_new));
-		trace_xfs_bmap_post_update(bma->ip, bma->idx + 1, state, _THIS_IP_);
-		break;
+		nextbno = be64_to_cpu(block->bb_u.l.bb_rightsib);
 
-	case BMAP_RIGHT_FILLING | BMAP_RIGHT_CONTIG:
 		/*
-		 * Filling in the last part of a previous delayed allocation.
-		 * The right neighbor is contiguous with the new allocation.
+		 * Check all the extents to make sure they are OK.
+		 * If we had a previous block, the last entry should
+		 * conform with the first entry in this one.
 		 */
-		temp = PREV.br_blockcount - new->br_blockcount;
-		trace_xfs_bmap_pre_update(bma->ip, bma->idx + 1, state, _THIS_IP_);
-		xfs_bmbt_set_blockcount(ep, temp);
-		xfs_bmbt_set_allf(xfs_iext_get_ext(ifp, bma->idx + 1),
-			new->br_startoff, new->br_startblock,
-			new->br_blockcount + RIGHT.br_blockcount,
-			RIGHT.br_state);
-		trace_xfs_bmap_post_update(bma->ip, bma->idx + 1, state, _THIS_IP_);
-		if (bma->cur == NULL)
-			rval = XFS_ILOG_DEXT;
-		else {
-			rval = 0;
-			error = xfs_bmbt_lookup_eq(bma->cur, RIGHT.br_startoff,
-					RIGHT.br_startblock,
-					RIGHT.br_blockcount, &i);
-			if (error)
-				goto done;
-			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
-			error = xfs_bmbt_update(bma->cur, new->br_startoff,
-					new->br_startblock,
-					new->br_blockcount +
-					RIGHT.br_blockcount,
-					RIGHT.br_state);
-			if (error)
-				goto done;
-		}
-
-		da_new = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(bma->ip, temp),
-			startblockval(PREV.br_startblock));
-		trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_);
-		xfs_bmbt_set_startblock(ep, nullstartblock(da_new));
-		trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_);
 
-		bma->idx++;
-		break;
+		ep = XFS_BMBT_REC_ADDR(mp, block, 1);
+		if (i) {
+			ASSERT(xfs_bmbt_disk_get_startoff(&last) +
+			       xfs_bmbt_disk_get_blockcount(&last) <=
+			       xfs_bmbt_disk_get_startoff(ep));
+		}
+		for (j = 1; j < num_recs; j++) {
+			nextp = XFS_BMBT_REC_ADDR(mp, block, j + 1);
+			ASSERT(xfs_bmbt_disk_get_startoff(ep) +
+			       xfs_bmbt_disk_get_blockcount(ep) <=
+			       xfs_bmbt_disk_get_startoff(nextp));
+			ep = nextp;
+		}
 
-	case BMAP_RIGHT_FILLING:
+		last = *ep;
+		i += num_recs;
+		if (bp_release) {
+			bp_release = 0;
+			xfs_trans_brelse(NULL, bp);
+		}
+		bno = nextbno;
 		/*
-		 * Filling in the last part of a previous delayed allocation.
-		 * The right neighbor is not contiguous.
+		 * If we've reached the end, stop.
 		 */
-		temp = PREV.br_blockcount - new->br_blockcount;
-		trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_);
-		xfs_bmbt_set_blockcount(ep, temp);
-		xfs_iext_insert(bma->ip, bma->idx + 1, 1, new, state);
-		bma->ip->i_d.di_nextents++;
-		if (bma->cur == NULL)
-			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
-		else {
-			rval = XFS_ILOG_CORE;
-			error = xfs_bmbt_lookup_eq(bma->cur, new->br_startoff,
-					new->br_startblock, new->br_blockcount,
-					&i);
-			if (error)
-				goto done;
-			XFS_WANT_CORRUPTED_GOTO(i == 0, done);
-			bma->cur->bc_rec.b.br_state = XFS_EXT_NORM;
-			error = xfs_btree_insert(bma->cur, &i);
-			if (error)
-				goto done;
-			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
-		}
-
-		if (xfs_bmap_needs_btree(bma->ip, XFS_DATA_FORK)) {
-			error = xfs_bmap_extents_to_btree(bma->tp, bma->ip,
-				bma->firstblock, bma->flist, &bma->cur, 1,
-				&tmp_rval, XFS_DATA_FORK);
-			rval |= tmp_rval;
-			if (error)
-				goto done;
-		}
-		da_new = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(bma->ip, temp),
-			startblockval(PREV.br_startblock) -
-			(bma->cur ? bma->cur->bc_private.b.allocated : 0));
-		ep = xfs_iext_get_ext(ifp, bma->idx);
-		xfs_bmbt_set_startblock(ep, nullstartblock(da_new));
-		trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_);
-
-		bma->idx++;
-		break;
-
-	case 0:
-		/*
-		 * Filling in the middle part of a previous delayed allocation.
-		 * Contiguity is impossible here.
-		 * This case is avoided almost all the time.
-		 *
-		 * We start with a delayed allocation:
-		 *
-		 * +ddddddddddddddddddddddddddddddddddddddddddddddddddddddd+
-		 *  PREV @ idx
-		 *
-	         * and we are allocating:
-		 *                     +rrrrrrrrrrrrrrrrr+
-		 *			      new
-		 *
-		 * and we set it up for insertion as:
-		 * +ddddddddddddddddddd+rrrrrrrrrrrrrrrrr+ddddddddddddddddd+
-		 *                            new
-		 *  PREV @ idx          LEFT              RIGHT
-		 *                      inserted at idx + 1
-		 */
-		temp = new->br_startoff - PREV.br_startoff;
-		temp2 = PREV.br_startoff + PREV.br_blockcount - new_endoff;
-		trace_xfs_bmap_pre_update(bma->ip, bma->idx, 0, _THIS_IP_);
-		xfs_bmbt_set_blockcount(ep, temp);	/* truncate PREV */
-		LEFT = *new;
-		RIGHT.br_state = PREV.br_state;
-		RIGHT.br_startblock = nullstartblock(
-				(int)xfs_bmap_worst_indlen(bma->ip, temp2));
-		RIGHT.br_startoff = new_endoff;
-		RIGHT.br_blockcount = temp2;
-		/* insert LEFT (r[0]) and RIGHT (r[1]) at the same time */
-		xfs_iext_insert(bma->ip, bma->idx + 1, 2, &LEFT, state);
-		bma->ip->i_d.di_nextents++;
-		if (bma->cur == NULL)
-			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
-		else {
-			rval = XFS_ILOG_CORE;
-			error = xfs_bmbt_lookup_eq(bma->cur, new->br_startoff,
-					new->br_startblock, new->br_blockcount,
-					&i);
-			if (error)
-				goto done;
-			XFS_WANT_CORRUPTED_GOTO(i == 0, done);
-			bma->cur->bc_rec.b.br_state = XFS_EXT_NORM;
-			error = xfs_btree_insert(bma->cur, &i);
-			if (error)
-				goto done;
-			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
-		}
+		if (bno == NULLFSBLOCK)
+			break;
 
-		if (xfs_bmap_needs_btree(bma->ip, XFS_DATA_FORK)) {
-			error = xfs_bmap_extents_to_btree(bma->tp, bma->ip,
-					bma->firstblock, bma->flist, &bma->cur,
-					1, &tmp_rval, XFS_DATA_FORK);
-			rval |= tmp_rval;
-			if (error)
-				goto done;
-		}
-		temp = xfs_bmap_worst_indlen(bma->ip, temp);
-		temp2 = xfs_bmap_worst_indlen(bma->ip, temp2);
-		diff = (int)(temp + temp2 - startblockval(PREV.br_startblock) -
-			(bma->cur ? bma->cur->bc_private.b.allocated : 0));
-		if (diff > 0) {
-			error = xfs_icsb_modify_counters(bma->ip->i_mount,
-					XFS_SBS_FDBLOCKS,
-					-((int64_t)diff), 0);
-			ASSERT(!error);
+		bp_release = 0;
+		bp = xfs_bmap_get_bp(cur, XFS_FSB_TO_DADDR(mp, bno));
+		if (!bp) {
+			bp_release = 1;
+			error = xfs_btree_read_bufl(mp, NULL, bno, 0, &bp,
+						XFS_BMAP_BTREE_REF,
+						&xfs_bmbt_buf_ops);
 			if (error)
-				goto done;
+				goto error_norelse;
 		}
-
-		ep = xfs_iext_get_ext(ifp, bma->idx);
-		xfs_bmbt_set_startblock(ep, nullstartblock((int)temp));
-		trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_);
-		trace_xfs_bmap_pre_update(bma->ip, bma->idx + 2, state, _THIS_IP_);
-		xfs_bmbt_set_startblock(xfs_iext_get_ext(ifp, bma->idx + 2),
-			nullstartblock((int)temp2));
-		trace_xfs_bmap_post_update(bma->ip, bma->idx + 2, state, _THIS_IP_);
-
-		bma->idx++;
-		da_new = temp + temp2;
-		break;
-
-	case BMAP_LEFT_FILLING | BMAP_LEFT_CONTIG | BMAP_RIGHT_CONTIG:
-	case BMAP_RIGHT_FILLING | BMAP_LEFT_CONTIG | BMAP_RIGHT_CONTIG:
-	case BMAP_LEFT_FILLING | BMAP_RIGHT_CONTIG:
-	case BMAP_RIGHT_FILLING | BMAP_LEFT_CONTIG:
-	case BMAP_LEFT_CONTIG | BMAP_RIGHT_CONTIG:
-	case BMAP_LEFT_CONTIG:
-	case BMAP_RIGHT_CONTIG:
-		/*
-		 * These cases are all impossible.
-		 */
-		ASSERT(0);
-	}
-
-	/* convert to a btree if necessary */
-	if (xfs_bmap_needs_btree(bma->ip, XFS_DATA_FORK)) {
-		int	tmp_logflags;	/* partial log flag return val */
-
-		ASSERT(bma->cur == NULL);
-		error = xfs_bmap_extents_to_btree(bma->tp, bma->ip,
-				bma->firstblock, bma->flist, &bma->cur,
-				da_old > 0, &tmp_logflags, XFS_DATA_FORK);
-		bma->logflags |= tmp_logflags;
-		if (error)
-			goto done;
+		block = XFS_BUF_TO_BLOCK(bp);
 	}
-
-	/* adjust for changes in reserved delayed indirect blocks */
-	if (da_old || da_new) {
-		temp = da_new;
-		if (bma->cur)
-			temp += bma->cur->bc_private.b.allocated;
-		ASSERT(temp <= da_old);
-		if (temp < da_old)
-			xfs_icsb_modify_counters(bma->ip->i_mount,
-					XFS_SBS_FDBLOCKS,
-					(int64_t)(da_old - temp), 0);
+	if (bp_release) {
+		bp_release = 0;
+		xfs_trans_brelse(NULL, bp);
 	}
+	return;
 
-	/* clear out the allocated field, done with it now in any case. */
-	if (bma->cur)
-		bma->cur->bc_private.b.allocated = 0;
-
-	xfs_bmap_check_leaf_extents(bma->cur, bma->ip, XFS_DATA_FORK);
-done:
-	bma->logflags |= rval;
-	return error;
-#undef	LEFT
-#undef	RIGHT
-#undef	PREV
+error0:
+	xfs_warn(mp, "%s: at error0", __func__);
+	if (bp_release)
+		xfs_trans_brelse(NULL, bp);
+error_norelse:
+	xfs_warn(mp, "%s: BAD after btree leaves for %d extents",
+		__func__, i);
+	panic("%s: CORRUPTED BTREE OR SOMETHING", __func__);
+	return;
 }
 
 /*
- * Convert an unwritten allocation to a real allocation or vice versa.
+ * Add bmap trace insert entries for all the contents of the extent records.
  */
-STATIC int				/* error */
-xfs_bmap_add_extent_unwritten_real(
-	struct xfs_trans	*tp,
-	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 */
-	xfs_bmbt_irec_t		*new,	/* new data to add to file extents */
-	xfs_fsblock_t		*first,	/* pointer to firstblock variable */
-	xfs_bmap_free_t		*flist,	/* list of extents to be freed */
-	int			*logflagsp) /* inode logging flags */
+void
+xfs_bmap_trace_exlist(
+	xfs_inode_t	*ip,		/* incore inode pointer */
+	xfs_extnum_t	cnt,		/* count of entries in the list */
+	int		whichfork,	/* data or attr fork */
+	unsigned long	caller_ip)
 {
-	xfs_btree_cur_t		*cur;	/* btree cursor */
-	xfs_bmbt_rec_host_t	*ep;	/* extent entry for idx */
-	int			error;	/* error return value */
-	int			i;	/* temp state */
-	xfs_ifork_t		*ifp;	/* inode fork pointer */
-	xfs_fileoff_t		new_endoff;	/* end offset of new entry */
-	xfs_exntst_t		newext;	/* new extent state */
-	xfs_exntst_t		oldext;	/* old extent state */
-	xfs_bmbt_irec_t		r[3];	/* neighbor extent entries */
-					/* left is 0, right is 1, prev is 2 */
-	int			rval=0;	/* return value (logging flags) */
-	int			state = 0;/* state bits, accessed thru macros */
-
-	*logflagsp = 0;
+	xfs_extnum_t	idx;		/* extent record index */
+	xfs_ifork_t	*ifp;		/* inode fork pointer */
+	int		state = 0;
 
-	cur = *curp;
-	ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
+	if (whichfork == XFS_ATTR_FORK)
+		state |= BMAP_ATTRFORK;
 
-	ASSERT(*idx >= 0);
-	ASSERT(*idx <= ifp->if_bytes / sizeof(struct xfs_bmbt_rec));
-	ASSERT(!isnullstartblock(new->br_startblock));
+	ifp = XFS_IFORK_PTR(ip, whichfork);
+	ASSERT(cnt == (ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t)));
+	for (idx = 0; idx < cnt; idx++)
+		trace_xfs_extlist(ip, idx, whichfork, caller_ip);
+}
 
-	XFS_STATS_INC(xs_add_exlist);
+/*
+ * Validate that the bmbt_irecs being returned from bmapi are valid
+ * given the callers original parameters.  Specifically check the
+ * ranges of the returned irecs to ensure that they only extent beyond
+ * the given parameters if the XFS_BMAPI_ENTIRE flag was set.
+ */
+STATIC void
+xfs_bmap_validate_ret(
+	xfs_fileoff_t		bno,
+	xfs_filblks_t		len,
+	int			flags,
+	xfs_bmbt_irec_t		*mval,
+	int			nmap,
+	int			ret_nmap)
+{
+	int			i;		/* index to map values */
 
-#define	LEFT		r[0]
-#define	RIGHT		r[1]
-#define	PREV		r[2]
+	ASSERT(ret_nmap <= nmap);
 
-	/*
-	 * Set up a bunch of variables to make the tests simpler.
-	 */
-	error = 0;
-	ep = xfs_iext_get_ext(ifp, *idx);
-	xfs_bmbt_get_all(ep, &PREV);
-	newext = new->br_state;
-	oldext = (newext == XFS_EXT_UNWRITTEN) ?
-		XFS_EXT_NORM : XFS_EXT_UNWRITTEN;
-	ASSERT(PREV.br_state == oldext);
-	new_endoff = new->br_startoff + new->br_blockcount;
-	ASSERT(PREV.br_startoff <= new->br_startoff);
-	ASSERT(PREV.br_startoff + PREV.br_blockcount >= new_endoff);
+	for (i = 0; i < ret_nmap; i++) {
+		ASSERT(mval[i].br_blockcount > 0);
+		if (!(flags & XFS_BMAPI_ENTIRE)) {
+			ASSERT(mval[i].br_startoff >= bno);
+			ASSERT(mval[i].br_blockcount <= len);
+			ASSERT(mval[i].br_startoff + mval[i].br_blockcount <=
+			       bno + len);
+		} else {
+			ASSERT(mval[i].br_startoff < bno + len);
+			ASSERT(mval[i].br_startoff + mval[i].br_blockcount >
+			       bno);
+		}
+		ASSERT(i == 0 ||
+		       mval[i - 1].br_startoff + mval[i - 1].br_blockcount ==
+		       mval[i].br_startoff);
+		ASSERT(mval[i].br_startblock != DELAYSTARTBLOCK &&
+		       mval[i].br_startblock != HOLESTARTBLOCK);
+		ASSERT(mval[i].br_state == XFS_EXT_NORM ||
+		       mval[i].br_state == XFS_EXT_UNWRITTEN);
+	}
+}
 
-	/*
-	 * Set flags determining what part of the previous oldext allocation
-	 * extent is being replaced by a newext allocation.
-	 */
-	if (PREV.br_startoff == new->br_startoff)
-		state |= BMAP_LEFT_FILLING;
-	if (PREV.br_startoff + PREV.br_blockcount == new_endoff)
-		state |= BMAP_RIGHT_FILLING;
+#else
+#define xfs_bmap_check_leaf_extents(cur, ip, whichfork)		do { } while (0)
+#define	xfs_bmap_validate_ret(bno,len,flags,mval,onmap,nmap)
+#endif /* DEBUG */
 
-	/*
-	 * Check and set flags if this segment has a left neighbor.
-	 * Don't set contiguous if the combined extent would be too large.
-	 */
-	if (*idx > 0) {
-		state |= BMAP_LEFT_VALID;
-		xfs_bmbt_get_all(xfs_iext_get_ext(ifp, *idx - 1), &LEFT);
+/*
+ * bmap free list manipulation functions
+ */
 
-		if (isnullstartblock(LEFT.br_startblock))
-			state |= BMAP_LEFT_DELAY;
+/*
+ * Add the extent to the list of extents to be free at transaction end.
+ * The list is maintained sorted (by block number).
+ */
+void
+xfs_bmap_add_free(
+	xfs_fsblock_t		bno,		/* fs block number of extent */
+	xfs_filblks_t		len,		/* length of extent */
+	xfs_bmap_free_t		*flist,		/* list of extents */
+	xfs_mount_t		*mp)		/* mount point structure */
+{
+	xfs_bmap_free_item_t	*cur;		/* current (next) element */
+	xfs_bmap_free_item_t	*new;		/* new element */
+	xfs_bmap_free_item_t	*prev;		/* previous element */
+#ifdef DEBUG
+	xfs_agnumber_t		agno;
+	xfs_agblock_t		agbno;
+
+	ASSERT(bno != NULLFSBLOCK);
+	ASSERT(len > 0);
+	ASSERT(len <= MAXEXTLEN);
+	ASSERT(!isnullstartblock(bno));
+	agno = XFS_FSB_TO_AGNO(mp, bno);
+	agbno = XFS_FSB_TO_AGBNO(mp, bno);
+	ASSERT(agno < mp->m_sb.sb_agcount);
+	ASSERT(agbno < mp->m_sb.sb_agblocks);
+	ASSERT(len < mp->m_sb.sb_agblocks);
+	ASSERT(agbno + len <= mp->m_sb.sb_agblocks);
+#endif
+	ASSERT(xfs_bmap_free_item_zone != NULL);
+	new = kmem_zone_alloc(xfs_bmap_free_item_zone, KM_SLEEP);
+	new->xbfi_startblock = bno;
+	new->xbfi_blockcount = (xfs_extlen_t)len;
+	for (prev = NULL, cur = flist->xbf_first;
+	     cur != NULL;
+	     prev = cur, cur = cur->xbfi_next) {
+		if (cur->xbfi_startblock >= bno)
+			break;
 	}
+	if (prev)
+		prev->xbfi_next = new;
+	else
+		flist->xbf_first = new;
+	new->xbfi_next = cur;
+	flist->xbf_count++;
+}
 
-	if ((state & BMAP_LEFT_VALID) && !(state & BMAP_LEFT_DELAY) &&
-	    LEFT.br_startoff + LEFT.br_blockcount == new->br_startoff &&
-	    LEFT.br_startblock + LEFT.br_blockcount == new->br_startblock &&
-	    LEFT.br_state == newext &&
-	    LEFT.br_blockcount + new->br_blockcount <= MAXEXTLEN)
-		state |= BMAP_LEFT_CONTIG;
+/*
+ * Remove the entry "free" from the free item list.  Prev points to the
+ * previous entry, unless "free" is the head of the list.
+ */
+STATIC void
+xfs_bmap_del_free(
+	xfs_bmap_free_t		*flist,	/* free item list header */
+	xfs_bmap_free_item_t	*prev,	/* previous item on list, if any */
+	xfs_bmap_free_item_t	*free)	/* list item to be freed */
+{
+	if (prev)
+		prev->xbfi_next = free->xbfi_next;
+	else
+		flist->xbf_first = free->xbfi_next;
+	flist->xbf_count--;
+	kmem_zone_free(xfs_bmap_free_item_zone, free);
+}
+
+
+/*
+ * Routine to be called at transaction's end by xfs_bmapi, xfs_bunmapi
+ * caller.  Frees all the extents that need freeing, which must be done
+ * last due to locking considerations.  We never free any extents in
+ * the first transaction.
+ *
+ * Return 1 if the given transaction was committed and a new one
+ * started, and 0 otherwise in the committed parameter.
+ */
+int						/* error */
+xfs_bmap_finish(
+	xfs_trans_t		**tp,		/* transaction pointer addr */
+	xfs_bmap_free_t		*flist,		/* i/o: list extents to free */
+	int			*committed)	/* xact committed or not */
+{
+	xfs_efd_log_item_t	*efd;		/* extent free data */
+	xfs_efi_log_item_t	*efi;		/* extent free intention */
+	int			error;		/* error return value */
+	xfs_bmap_free_item_t	*free;		/* free extent item */
+	unsigned int		logres;		/* new log reservation */
+	unsigned int		logcount;	/* new log count */
+	xfs_mount_t		*mp;		/* filesystem mount structure */
+	xfs_bmap_free_item_t	*next;		/* next item on free list */
+	xfs_trans_t		*ntp;		/* new transaction pointer */
 
+	ASSERT((*tp)->t_flags & XFS_TRANS_PERM_LOG_RES);
+	if (flist->xbf_count == 0) {
+		*committed = 0;
+		return 0;
+	}
+	ntp = *tp;
+	efi = xfs_trans_get_efi(ntp, flist->xbf_count);
+	for (free = flist->xbf_first; free; free = free->xbfi_next)
+		xfs_trans_log_efi_extent(ntp, efi, free->xbfi_startblock,
+			free->xbfi_blockcount);
+	logres = ntp->t_log_res;
+	logcount = ntp->t_log_count;
+	ntp = xfs_trans_dup(*tp);
+	error = xfs_trans_commit(*tp, 0);
+	*tp = ntp;
+	*committed = 1;
 	/*
-	 * Check and set flags if this segment has a right neighbor.
-	 * Don't set contiguous if the combined extent would be too large.
-	 * Also check for all-three-contiguous being too large.
+	 * We have a new transaction, so we should return committed=1,
+	 * even though we're returning an error.
 	 */
-	if (*idx < ip->i_df.if_bytes / (uint)sizeof(xfs_bmbt_rec_t) - 1) {
-		state |= BMAP_RIGHT_VALID;
-		xfs_bmbt_get_all(xfs_iext_get_ext(ifp, *idx + 1), &RIGHT);
-		if (isnullstartblock(RIGHT.br_startblock))
-			state |= BMAP_RIGHT_DELAY;
-	}
-
-	if ((state & BMAP_RIGHT_VALID) && !(state & BMAP_RIGHT_DELAY) &&
-	    new_endoff == RIGHT.br_startoff &&
-	    new->br_startblock + new->br_blockcount == RIGHT.br_startblock &&
-	    newext == RIGHT.br_state &&
-	    new->br_blockcount + RIGHT.br_blockcount <= MAXEXTLEN &&
-	    ((state & (BMAP_LEFT_CONTIG | BMAP_LEFT_FILLING |
-		       BMAP_RIGHT_FILLING)) !=
-		      (BMAP_LEFT_CONTIG | BMAP_LEFT_FILLING |
-		       BMAP_RIGHT_FILLING) ||
-	     LEFT.br_blockcount + new->br_blockcount + RIGHT.br_blockcount
-			<= MAXEXTLEN))
-		state |= BMAP_RIGHT_CONTIG;
+	if (error)
+		return error;
 
 	/*
-	 * Switch out based on the FILLING and CONTIG state bits.
+	 * transaction commit worked ok so we can drop the extra ticket
+	 * reference that we gained in xfs_trans_dup()
 	 */
-	switch (state & (BMAP_LEFT_FILLING | BMAP_LEFT_CONTIG |
-			 BMAP_RIGHT_FILLING | BMAP_RIGHT_CONTIG)) {
-	case BMAP_LEFT_FILLING | BMAP_LEFT_CONTIG |
-	     BMAP_RIGHT_FILLING | BMAP_RIGHT_CONTIG:
-		/*
-		 * Setting all of a previous oldext extent to newext.
-		 * The left and right neighbors are both contiguous with new.
-		 */
-		--*idx;
+	xfs_log_ticket_put(ntp->t_ticket);
 
-		trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_);
-		xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, *idx),
-			LEFT.br_blockcount + PREV.br_blockcount +
-			RIGHT.br_blockcount);
-		trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_);
+	if ((error = xfs_trans_reserve(ntp, 0, logres, 0, XFS_TRANS_PERM_LOG_RES,
+			logcount)))
+		return error;
+	efd = xfs_trans_get_efd(ntp, efi, flist->xbf_count);
+	for (free = flist->xbf_first; free != NULL; free = next) {
+		next = free->xbfi_next;
+		if ((error = xfs_free_extent(ntp, free->xbfi_startblock,
+				free->xbfi_blockcount))) {
+			/*
+			 * The bmap free list will be cleaned up at a
+			 * higher level.  The EFI will be canceled when
+			 * this transaction is aborted.
+			 * Need to force shutdown here to make sure it
+			 * happens, since this transaction may not be
+			 * dirty yet.
+			 */
+			mp = ntp->t_mountp;
+			if (!XFS_FORCED_SHUTDOWN(mp))
+				xfs_force_shutdown(mp,
+						   (error == EFSCORRUPTED) ?
+						   SHUTDOWN_CORRUPT_INCORE :
+						   SHUTDOWN_META_IO_ERROR);
+			return error;
+		}
+		xfs_trans_log_efd_extent(ntp, efd, free->xbfi_startblock,
+			free->xbfi_blockcount);
+		xfs_bmap_del_free(flist, NULL, free);
+	}
+	return 0;
+}
 
-		xfs_iext_remove(ip, *idx + 1, 2, state);
-		ip->i_d.di_nextents -= 2;
-		if (cur == NULL)
-			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
-		else {
-			rval = XFS_ILOG_CORE;
-			if ((error = xfs_bmbt_lookup_eq(cur, RIGHT.br_startoff,
-					RIGHT.br_startblock,
-					RIGHT.br_blockcount, &i)))
-				goto done;
-			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
-			if ((error = xfs_btree_delete(cur, &i)))
-				goto done;
-			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
-			if ((error = xfs_btree_decrement(cur, 0, &i)))
-				goto done;
-			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
-			if ((error = xfs_btree_delete(cur, &i)))
-				goto done;
-			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
-			if ((error = xfs_btree_decrement(cur, 0, &i)))
-				goto done;
-			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
-			if ((error = xfs_bmbt_update(cur, LEFT.br_startoff,
-				LEFT.br_startblock,
-				LEFT.br_blockcount + PREV.br_blockcount +
-				RIGHT.br_blockcount, LEFT.br_state)))
-				goto done;
-		}
-		break;
-
-	case BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING | BMAP_LEFT_CONTIG:
-		/*
-		 * Setting all of a previous oldext extent to newext.
-		 * The left neighbor is contiguous, the right is not.
-		 */
-		--*idx;
+/*
+ * Free up any items left in the list.
+ */
+void
+xfs_bmap_cancel(
+	xfs_bmap_free_t		*flist)	/* list of bmap_free_items */
+{
+	xfs_bmap_free_item_t	*free;	/* free list item */
+	xfs_bmap_free_item_t	*next;
 
-		trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_);
-		xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, *idx),
-			LEFT.br_blockcount + PREV.br_blockcount);
-		trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_);
+	if (flist->xbf_count == 0)
+		return;
+	ASSERT(flist->xbf_first != NULL);
+	for (free = flist->xbf_first; free; free = next) {
+		next = free->xbfi_next;
+		xfs_bmap_del_free(flist, NULL, free);
+	}
+	ASSERT(flist->xbf_count == 0);
+}
 
-		xfs_iext_remove(ip, *idx + 1, 1, state);
-		ip->i_d.di_nextents--;
-		if (cur == NULL)
-			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
-		else {
-			rval = XFS_ILOG_CORE;
-			if ((error = xfs_bmbt_lookup_eq(cur, PREV.br_startoff,
-					PREV.br_startblock, PREV.br_blockcount,
-					&i)))
-				goto done;
-			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
-			if ((error = xfs_btree_delete(cur, &i)))
-				goto done;
-			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
-			if ((error = xfs_btree_decrement(cur, 0, &i)))
-				goto done;
-			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
-			if ((error = xfs_bmbt_update(cur, LEFT.br_startoff,
-				LEFT.br_startblock,
-				LEFT.br_blockcount + PREV.br_blockcount,
-				LEFT.br_state)))
-				goto done;
-		}
-		break;
+/*
+ * Inode fork format manipulation functions
+ */
 
-	case BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING | BMAP_RIGHT_CONTIG:
-		/*
-		 * Setting all of a previous oldext extent to newext.
-		 * The right neighbor is contiguous, the left is not.
-		 */
-		trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_);
-		xfs_bmbt_set_blockcount(ep,
-			PREV.br_blockcount + RIGHT.br_blockcount);
-		xfs_bmbt_set_state(ep, newext);
-		trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_);
-		xfs_iext_remove(ip, *idx + 1, 1, state);
-		ip->i_d.di_nextents--;
-		if (cur == NULL)
-			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
-		else {
-			rval = XFS_ILOG_CORE;
-			if ((error = xfs_bmbt_lookup_eq(cur, RIGHT.br_startoff,
-					RIGHT.br_startblock,
-					RIGHT.br_blockcount, &i)))
-				goto done;
-			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
-			if ((error = xfs_btree_delete(cur, &i)))
-				goto done;
-			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
-			if ((error = xfs_btree_decrement(cur, 0, &i)))
-				goto done;
-			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
-			if ((error = xfs_bmbt_update(cur, new->br_startoff,
-				new->br_startblock,
-				new->br_blockcount + RIGHT.br_blockcount,
-				newext)))
-				goto done;
-		}
-		break;
+/*
+ * Transform a btree format file with only one leaf node, where the
+ * extents list will fit in the inode, into an extents format file.
+ * Since the file extents are already in-core, all we have to do is
+ * give up the space for the btree root and pitch the leaf block.
+ */
+STATIC int				/* error */
+xfs_bmap_btree_to_extents(
+	xfs_trans_t		*tp,	/* transaction pointer */
+	xfs_inode_t		*ip,	/* incore inode pointer */
+	xfs_btree_cur_t		*cur,	/* btree cursor */
+	int			*logflagsp, /* inode logging flags */
+	int			whichfork)  /* data or attr fork */
+{
+	/* REFERENCED */
+	struct xfs_btree_block	*cblock;/* child btree block */
+	xfs_fsblock_t		cbno;	/* child block number */
+	xfs_buf_t		*cbp;	/* child block's buffer */
+	int			error;	/* error return value */
+	xfs_ifork_t		*ifp;	/* inode fork data */
+	xfs_mount_t		*mp;	/* mount point structure */
+	__be64			*pp;	/* ptr to block address */
+	struct xfs_btree_block	*rblock;/* root btree block */
 
-	case BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING:
-		/*
-		 * Setting all of a previous oldext extent to newext.
-		 * Neither the left nor right neighbors are contiguous with
-		 * the new one.
-		 */
-		trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_);
-		xfs_bmbt_set_state(ep, newext);
-		trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_);
+	mp = ip->i_mount;
+	ifp = XFS_IFORK_PTR(ip, whichfork);
+	ASSERT(ifp->if_flags & XFS_IFEXTENTS);
+	ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE);
+	rblock = ifp->if_broot;
+	ASSERT(be16_to_cpu(rblock->bb_level) == 1);
+	ASSERT(be16_to_cpu(rblock->bb_numrecs) == 1);
+	ASSERT(xfs_bmbt_maxrecs(mp, ifp->if_broot_bytes, 0) == 1);
+	pp = XFS_BMAP_BROOT_PTR_ADDR(mp, rblock, 1, ifp->if_broot_bytes);
+	cbno = be64_to_cpu(*pp);
+	*logflagsp = 0;
+#ifdef DEBUG
+	if ((error = xfs_btree_check_lptr(cur, cbno, 1)))
+		return error;
+#endif
+	error = xfs_btree_read_bufl(mp, tp, cbno, 0, &cbp, XFS_BMAP_BTREE_REF,
+				&xfs_bmbt_buf_ops);
+	if (error)
+		return error;
+	cblock = XFS_BUF_TO_BLOCK(cbp);
+	if ((error = xfs_btree_check_block(cur, cblock, 0, cbp)))
+		return error;
+	xfs_bmap_add_free(cbno, 1, cur->bc_private.b.flist, mp);
+	ip->i_d.di_nblocks--;
+	xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, -1L);
+	xfs_trans_binval(tp, cbp);
+	if (cur->bc_bufs[0] == cbp)
+		cur->bc_bufs[0] = NULL;
+	xfs_iroot_realloc(ip, -1, whichfork);
+	ASSERT(ifp->if_broot == NULL);
+	ASSERT((ifp->if_flags & XFS_IFBROOT) == 0);
+	XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_EXTENTS);
+	*logflagsp = XFS_ILOG_CORE | xfs_ilog_fext(whichfork);
+	return 0;
+}
 
-		if (cur == NULL)
-			rval = XFS_ILOG_DEXT;
-		else {
-			rval = 0;
-			if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff,
-					new->br_startblock, new->br_blockcount,
-					&i)))
-				goto done;
-			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
-			if ((error = xfs_bmbt_update(cur, new->br_startoff,
-				new->br_startblock, new->br_blockcount,
-				newext)))
-				goto done;
-		}
-		break;
+/*
+ * Convert an extents-format file into a btree-format file.
+ * The new file will have a root block (in the inode) and a single child block.
+ */
+STATIC int					/* error */
+xfs_bmap_extents_to_btree(
+	xfs_trans_t		*tp,		/* transaction pointer */
+	xfs_inode_t		*ip,		/* incore inode pointer */
+	xfs_fsblock_t		*firstblock,	/* first-block-allocated */
+	xfs_bmap_free_t		*flist,		/* blocks freed in xaction */
+	xfs_btree_cur_t		**curp,		/* cursor returned to caller */
+	int			wasdel,		/* converting a delayed alloc */
+	int			*logflagsp,	/* inode logging flags */
+	int			whichfork)	/* data or attr fork */
+{
+	struct xfs_btree_block	*ablock;	/* allocated (child) bt block */
+	xfs_buf_t		*abp;		/* buffer for ablock */
+	xfs_alloc_arg_t		args;		/* allocation arguments */
+	xfs_bmbt_rec_t		*arp;		/* child record pointer */
+	struct xfs_btree_block	*block;		/* btree root block */
+	xfs_btree_cur_t		*cur;		/* bmap btree cursor */
+	xfs_bmbt_rec_host_t	*ep;		/* extent record pointer */
+	int			error;		/* error return value */
+	xfs_extnum_t		i, cnt;		/* extent record index */
+	xfs_ifork_t		*ifp;		/* inode fork pointer */
+	xfs_bmbt_key_t		*kp;		/* root block key pointer */
+	xfs_mount_t		*mp;		/* mount structure */
+	xfs_extnum_t		nextents;	/* number of file extents */
+	xfs_bmbt_ptr_t		*pp;		/* root block address pointer */
 
-	case BMAP_LEFT_FILLING | BMAP_LEFT_CONTIG:
-		/*
-		 * Setting the first part of a previous oldext extent to newext.
-		 * The left neighbor is contiguous.
-		 */
-		trace_xfs_bmap_pre_update(ip, *idx - 1, state, _THIS_IP_);
-		xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, *idx - 1),
-			LEFT.br_blockcount + new->br_blockcount);
-		xfs_bmbt_set_startoff(ep,
-			PREV.br_startoff + new->br_blockcount);
-		trace_xfs_bmap_post_update(ip, *idx - 1, state, _THIS_IP_);
+	ifp = XFS_IFORK_PTR(ip, whichfork);
+	ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS);
 
-		trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_);
-		xfs_bmbt_set_startblock(ep,
-			new->br_startblock + new->br_blockcount);
-		xfs_bmbt_set_blockcount(ep,
-			PREV.br_blockcount - new->br_blockcount);
-		trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_);
+	/*
+	 * Make space in the inode incore.
+	 */
+	xfs_iroot_realloc(ip, 1, whichfork);
+	ifp->if_flags |= XFS_IFBROOT;
 
-		--*idx;
+	/*
+	 * Fill in the root.
+	 */
+	block = ifp->if_broot;
+	block->bb_magic = cpu_to_be32(XFS_BMAP_MAGIC);
+	block->bb_level = cpu_to_be16(1);
+	block->bb_numrecs = cpu_to_be16(1);
+	block->bb_u.l.bb_leftsib = cpu_to_be64(NULLDFSBNO);
+	block->bb_u.l.bb_rightsib = cpu_to_be64(NULLDFSBNO);
 
-		if (cur == NULL)
-			rval = XFS_ILOG_DEXT;
-		else {
-			rval = 0;
-			if ((error = xfs_bmbt_lookup_eq(cur, PREV.br_startoff,
-					PREV.br_startblock, PREV.br_blockcount,
-					&i)))
-				goto done;
-			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
-			if ((error = xfs_bmbt_update(cur,
-				PREV.br_startoff + new->br_blockcount,
-				PREV.br_startblock + new->br_blockcount,
-				PREV.br_blockcount - new->br_blockcount,
-				oldext)))
-				goto done;
-			if ((error = xfs_btree_decrement(cur, 0, &i)))
-				goto done;
-			error = xfs_bmbt_update(cur, LEFT.br_startoff,
-				LEFT.br_startblock,
-				LEFT.br_blockcount + new->br_blockcount,
-				LEFT.br_state);
-			if (error)
-				goto done;
-		}
-		break;
-
-	case BMAP_LEFT_FILLING:
-		/*
-		 * Setting the first part of a previous oldext extent to newext.
-		 * The left neighbor is not contiguous.
-		 */
-		trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_);
-		ASSERT(ep && xfs_bmbt_get_state(ep) == oldext);
-		xfs_bmbt_set_startoff(ep, new_endoff);
-		xfs_bmbt_set_blockcount(ep,
-			PREV.br_blockcount - new->br_blockcount);
-		xfs_bmbt_set_startblock(ep,
-			new->br_startblock + new->br_blockcount);
-		trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_);
-
-		xfs_iext_insert(ip, *idx, 1, new, state);
-		ip->i_d.di_nextents++;
-		if (cur == NULL)
-			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
-		else {
-			rval = XFS_ILOG_CORE;
-			if ((error = xfs_bmbt_lookup_eq(cur, PREV.br_startoff,
-					PREV.br_startblock, PREV.br_blockcount,
-					&i)))
-				goto done;
-			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
-			if ((error = xfs_bmbt_update(cur,
-				PREV.br_startoff + new->br_blockcount,
-				PREV.br_startblock + new->br_blockcount,
-				PREV.br_blockcount - new->br_blockcount,
-				oldext)))
-				goto done;
-			cur->bc_rec.b = *new;
-			if ((error = xfs_btree_insert(cur, &i)))
-				goto done;
-			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+	/*
+	 * Need a cursor.  Can't allocate until bb_level is filled in.
+	 */
+	mp = ip->i_mount;
+	cur = xfs_bmbt_init_cursor(mp, tp, ip, whichfork);
+	cur->bc_private.b.firstblock = *firstblock;
+	cur->bc_private.b.flist = flist;
+	cur->bc_private.b.flags = wasdel ? XFS_BTCUR_BPRV_WASDEL : 0;
+	/*
+	 * Convert to a btree with two levels, one record in root.
+	 */
+	XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_BTREE);
+	memset(&args, 0, sizeof(args));
+	args.tp = tp;
+	args.mp = mp;
+	args.firstblock = *firstblock;
+	if (*firstblock == NULLFSBLOCK) {
+		args.type = XFS_ALLOCTYPE_START_BNO;
+		args.fsbno = XFS_INO_TO_FSB(mp, ip->i_ino);
+	} else if (flist->xbf_low) {
+		args.type = XFS_ALLOCTYPE_START_BNO;
+		args.fsbno = *firstblock;
+	} else {
+		args.type = XFS_ALLOCTYPE_NEAR_BNO;
+		args.fsbno = *firstblock;
+	}
+	args.minlen = args.maxlen = args.prod = 1;
+	args.wasdel = wasdel;
+	*logflagsp = 0;
+	if ((error = xfs_alloc_vextent(&args))) {
+		xfs_iroot_realloc(ip, -1, whichfork);
+		xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
+		return error;
+	}
+	/*
+	 * Allocation can't fail, the space was reserved.
+	 */
+	ASSERT(args.fsbno != NULLFSBLOCK);
+	ASSERT(*firstblock == NULLFSBLOCK ||
+	       args.agno == XFS_FSB_TO_AGNO(mp, *firstblock) ||
+	       (flist->xbf_low &&
+		args.agno > XFS_FSB_TO_AGNO(mp, *firstblock)));
+	*firstblock = cur->bc_private.b.firstblock = args.fsbno;
+	cur->bc_private.b.allocated++;
+	ip->i_d.di_nblocks++;
+	xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, 1L);
+	abp = xfs_btree_get_bufl(mp, tp, args.fsbno, 0);
+	/*
+	 * Fill in the child block.
+	 */
+	abp->b_ops = &xfs_bmbt_buf_ops;
+	ablock = XFS_BUF_TO_BLOCK(abp);
+	ablock->bb_magic = cpu_to_be32(XFS_BMAP_MAGIC);
+	ablock->bb_level = 0;
+	ablock->bb_u.l.bb_leftsib = cpu_to_be64(NULLDFSBNO);
+	ablock->bb_u.l.bb_rightsib = cpu_to_be64(NULLDFSBNO);
+	arp = XFS_BMBT_REC_ADDR(mp, ablock, 1);
+	nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
+	for (cnt = i = 0; i < nextents; i++) {
+		ep = xfs_iext_get_ext(ifp, i);
+		if (!isnullstartblock(xfs_bmbt_get_startblock(ep))) {
+			arp->l0 = cpu_to_be64(ep->l0);
+			arp->l1 = cpu_to_be64(ep->l1);
+			arp++; cnt++;
 		}
-		break;
+	}
+	ASSERT(cnt == XFS_IFORK_NEXTENTS(ip, whichfork));
+	xfs_btree_set_numrecs(ablock, cnt);
 
-	case BMAP_RIGHT_FILLING | BMAP_RIGHT_CONTIG:
-		/*
-		 * Setting the last part of a previous oldext extent to newext.
-		 * The right neighbor is contiguous with the new allocation.
-		 */
-		trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_);
-		xfs_bmbt_set_blockcount(ep,
-			PREV.br_blockcount - new->br_blockcount);
-		trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_);
+	/*
+	 * Fill in the root key and pointer.
+	 */
+	kp = XFS_BMBT_KEY_ADDR(mp, block, 1);
+	arp = XFS_BMBT_REC_ADDR(mp, ablock, 1);
+	kp->br_startoff = cpu_to_be64(xfs_bmbt_disk_get_startoff(arp));
+	pp = XFS_BMBT_PTR_ADDR(mp, block, 1, xfs_bmbt_get_maxrecs(cur,
+						be16_to_cpu(block->bb_level)));
+	*pp = cpu_to_be64(args.fsbno);
 
-		++*idx;
+	/*
+	 * Do all this logging at the end so that
+	 * the root is at the right level.
+	 */
+	xfs_btree_log_block(cur, abp, XFS_BB_ALL_BITS);
+	xfs_btree_log_recs(cur, abp, 1, be16_to_cpu(ablock->bb_numrecs));
+	ASSERT(*curp == NULL);
+	*curp = cur;
+	*logflagsp = XFS_ILOG_CORE | xfs_ilog_fbroot(whichfork);
+	return 0;
+}
 
-		trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_);
-		xfs_bmbt_set_allf(xfs_iext_get_ext(ifp, *idx),
-			new->br_startoff, new->br_startblock,
-			new->br_blockcount + RIGHT.br_blockcount, newext);
-		trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_);
+/*
+ * Convert a local file to an extents file.
+ * This code is out of bounds for data forks of regular files,
+ * since the file data needs to get logged so things will stay consistent.
+ * (The bmap-level manipulations are ok, though).
+ */
+STATIC int				/* error */
+xfs_bmap_local_to_extents(
+	xfs_trans_t	*tp,		/* transaction pointer */
+	xfs_inode_t	*ip,		/* incore inode pointer */
+	xfs_fsblock_t	*firstblock,	/* first block allocated in xaction */
+	xfs_extlen_t	total,		/* total blocks needed by transaction */
+	int		*logflagsp,	/* inode logging flags */
+	int		whichfork,
+	void		(*init_fn)(struct xfs_buf *bp,
+				   struct xfs_inode *ip,
+				   struct xfs_ifork *ifp))
+{
+	int		error;		/* error return value */
+	int		flags;		/* logging flags returned */
+	xfs_ifork_t	*ifp;		/* inode fork pointer */
 
-		if (cur == NULL)
-			rval = XFS_ILOG_DEXT;
-		else {
-			rval = 0;
-			if ((error = xfs_bmbt_lookup_eq(cur, PREV.br_startoff,
-					PREV.br_startblock,
-					PREV.br_blockcount, &i)))
-				goto done;
-			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
-			if ((error = xfs_bmbt_update(cur, PREV.br_startoff,
-				PREV.br_startblock,
-				PREV.br_blockcount - new->br_blockcount,
-				oldext)))
-				goto done;
-			if ((error = xfs_btree_increment(cur, 0, &i)))
-				goto done;
-			if ((error = xfs_bmbt_update(cur, new->br_startoff,
-				new->br_startblock,
-				new->br_blockcount + RIGHT.br_blockcount,
-				newext)))
-				goto done;
-		}
-		break;
+	/*
+	 * 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(!(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;
+	error = 0;
+	if (ifp->if_bytes) {
+		xfs_alloc_arg_t	args;	/* allocation arguments */
+		xfs_buf_t	*bp;	/* buffer for extent block */
+		xfs_bmbt_rec_host_t *ep;/* extent record pointer */
 
-	case BMAP_RIGHT_FILLING:
+		ASSERT((ifp->if_flags &
+			(XFS_IFINLINE|XFS_IFEXTENTS|XFS_IFEXTIREC)) == XFS_IFINLINE);
+		memset(&args, 0, sizeof(args));
+		args.tp = tp;
+		args.mp = ip->i_mount;
+		args.firstblock = *firstblock;
 		/*
-		 * Setting the last part of a previous oldext extent to newext.
-		 * The right neighbor is not contiguous.
+		 * Allocate a block.  We know we need only one, since the
+		 * file currently fits in an inode.
 		 */
-		trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_);
-		xfs_bmbt_set_blockcount(ep,
-			PREV.br_blockcount - new->br_blockcount);
-		trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_);
+		if (*firstblock == NULLFSBLOCK) {
+			args.fsbno = XFS_INO_TO_FSB(args.mp, ip->i_ino);
+			args.type = XFS_ALLOCTYPE_START_BNO;
+		} else {
+			args.fsbno = *firstblock;
+			args.type = XFS_ALLOCTYPE_NEAR_BNO;
+		}
+		args.total = total;
+		args.minlen = args.maxlen = args.prod = 1;
+		error = xfs_alloc_vextent(&args);
+		if (error)
+			goto done;
 
-		++*idx;
-		xfs_iext_insert(ip, *idx, 1, new, state);
+		/* Can't fail, the space was reserved. */
+		ASSERT(args.fsbno != NULLFSBLOCK);
+		ASSERT(args.len == 1);
+		*firstblock = args.fsbno;
+		bp = xfs_btree_get_bufl(args.mp, tp, args.fsbno, 0);
 
-		ip->i_d.di_nextents++;
-		if (cur == NULL)
-			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
-		else {
-			rval = XFS_ILOG_CORE;
-			if ((error = xfs_bmbt_lookup_eq(cur, PREV.br_startoff,
-					PREV.br_startblock, PREV.br_blockcount,
-					&i)))
-				goto done;
-			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
-			if ((error = xfs_bmbt_update(cur, PREV.br_startoff,
-				PREV.br_startblock,
-				PREV.br_blockcount - new->br_blockcount,
-				oldext)))
-				goto done;
-			if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff,
-					new->br_startblock, new->br_blockcount,
-					&i)))
-				goto done;
-			XFS_WANT_CORRUPTED_GOTO(i == 0, done);
-			cur->bc_rec.b.br_state = XFS_EXT_NORM;
-			if ((error = xfs_btree_insert(cur, &i)))
-				goto done;
-			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
-		}
-		break;
-
-	case 0:
-		/*
-		 * Setting the middle part of a previous oldext extent to
-		 * newext.  Contiguity is impossible here.
-		 * One extent becomes three extents.
-		 */
-		trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_);
-		xfs_bmbt_set_blockcount(ep,
-			new->br_startoff - PREV.br_startoff);
-		trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_);
+		/* initialise the block and copy the data */
+		init_fn(bp, ip, ifp);
 
-		r[0] = *new;
-		r[1].br_startoff = new_endoff;
-		r[1].br_blockcount =
-			PREV.br_startoff + PREV.br_blockcount - new_endoff;
-		r[1].br_startblock = new->br_startblock + new->br_blockcount;
-		r[1].br_state = oldext;
+		/* account for the change in fork size and log everything */
+		xfs_trans_log_buf(tp, bp, 0, ifp->if_bytes - 1);
+		xfs_bmap_forkoff_reset(args.mp, ip, whichfork);
+		xfs_idata_realloc(ip, -ifp->if_bytes, whichfork);
+		xfs_iext_add(ifp, 0, 1);
+		ep = xfs_iext_get_ext(ifp, 0);
+		xfs_bmbt_set_allf(ep, 0, args.fsbno, 1, XFS_EXT_NORM);
+		trace_xfs_bmap_post_update(ip, 0,
+				whichfork == XFS_ATTR_FORK ? BMAP_ATTRFORK : 0,
+				_THIS_IP_);
+		XFS_IFORK_NEXT_SET(ip, whichfork, 1);
+		ip->i_d.di_nblocks = 1;
+		xfs_trans_mod_dquot_byino(tp, ip,
+			XFS_TRANS_DQ_BCOUNT, 1L);
+		flags |= xfs_ilog_fext(whichfork);
+	} else {
+		ASSERT(XFS_IFORK_NEXTENTS(ip, whichfork) == 0);
+		xfs_bmap_forkoff_reset(ip->i_mount, ip, whichfork);
+	}
+	ifp->if_flags &= ~XFS_IFINLINE;
+	ifp->if_flags |= XFS_IFEXTENTS;
+	XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_EXTENTS);
+	flags |= XFS_ILOG_CORE;
+done:
+	*logflagsp = flags;
+	return error;
+}
 
-		++*idx;
-		xfs_iext_insert(ip, *idx, 2, &r[0], state);
+/*
+ * Called from xfs_bmap_add_attrfork to handle btree format files.
+ */
+STATIC int					/* error */
+xfs_bmap_add_attrfork_btree(
+	xfs_trans_t		*tp,		/* transaction pointer */
+	xfs_inode_t		*ip,		/* incore inode pointer */
+	xfs_fsblock_t		*firstblock,	/* first block allocated */
+	xfs_bmap_free_t		*flist,		/* blocks to free at commit */
+	int			*flags)		/* inode logging flags */
+{
+	xfs_btree_cur_t		*cur;		/* btree cursor */
+	int			error;		/* error return value */
+	xfs_mount_t		*mp;		/* file system mount struct */
+	int			stat;		/* newroot status */
 
-		ip->i_d.di_nextents += 2;
-		if (cur == NULL)
-			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
-		else {
-			rval = XFS_ILOG_CORE;
-			if ((error = xfs_bmbt_lookup_eq(cur, PREV.br_startoff,
-					PREV.br_startblock, PREV.br_blockcount,
-					&i)))
-				goto done;
-			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
-			/* new right extent - oldext */
-			if ((error = xfs_bmbt_update(cur, r[1].br_startoff,
-				r[1].br_startblock, r[1].br_blockcount,
-				r[1].br_state)))
-				goto done;
-			/* new left extent - oldext */
-			cur->bc_rec.b = PREV;
-			cur->bc_rec.b.br_blockcount =
-				new->br_startoff - PREV.br_startoff;
-			if ((error = xfs_btree_insert(cur, &i)))
-				goto done;
-			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
-			/*
-			 * Reset the cursor to the position of the new extent
-			 * we are about to insert as we can't trust it after
-			 * the previous insert.
-			 */
-			if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff,
-					new->br_startblock, new->br_blockcount,
-					&i)))
-				goto done;
-			XFS_WANT_CORRUPTED_GOTO(i == 0, done);
-			/* new middle extent - newext */
-			cur->bc_rec.b.br_state = new->br_state;
-			if ((error = xfs_btree_insert(cur, &i)))
-				goto done;
-			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+	mp = ip->i_mount;
+	if (ip->i_df.if_broot_bytes <= XFS_IFORK_DSIZE(ip))
+		*flags |= XFS_ILOG_DBROOT;
+	else {
+		cur = xfs_bmbt_init_cursor(mp, tp, ip, XFS_DATA_FORK);
+		cur->bc_private.b.flist = flist;
+		cur->bc_private.b.firstblock = *firstblock;
+		if ((error = xfs_bmbt_lookup_ge(cur, 0, 0, 0, &stat)))
+			goto error0;
+		/* must be at least one entry */
+		XFS_WANT_CORRUPTED_GOTO(stat == 1, error0);
+		if ((error = xfs_btree_new_iroot(cur, flags, &stat)))
+			goto error0;
+		if (stat == 0) {
+			xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
+			return XFS_ERROR(ENOSPC);
 		}
-		break;
-
-	case BMAP_LEFT_FILLING | BMAP_LEFT_CONTIG | BMAP_RIGHT_CONTIG:
-	case BMAP_RIGHT_FILLING | BMAP_LEFT_CONTIG | BMAP_RIGHT_CONTIG:
-	case BMAP_LEFT_FILLING | BMAP_RIGHT_CONTIG:
-	case BMAP_RIGHT_FILLING | BMAP_LEFT_CONTIG:
-	case BMAP_LEFT_CONTIG | BMAP_RIGHT_CONTIG:
-	case BMAP_LEFT_CONTIG:
-	case BMAP_RIGHT_CONTIG:
-		/*
-		 * These cases are all impossible.
-		 */
-		ASSERT(0);
+		*firstblock = cur->bc_private.b.firstblock;
+		cur->bc_private.b.allocated = 0;
+		xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
 	}
+	return 0;
+error0:
+	xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
+	return error;
+}
 
-	/* convert to a btree if necessary */
-	if (xfs_bmap_needs_btree(ip, XFS_DATA_FORK)) {
-		int	tmp_logflags;	/* partial log flag return val */
-
-		ASSERT(cur == NULL);
-		error = xfs_bmap_extents_to_btree(tp, ip, first, flist, &cur,
-				0, &tmp_logflags, XFS_DATA_FORK);
-		*logflagsp |= tmp_logflags;
-		if (error)
-			goto done;
-	}
+/*
+ * Called from xfs_bmap_add_attrfork to handle extents format files.
+ */
+STATIC int					/* error */
+xfs_bmap_add_attrfork_extents(
+	xfs_trans_t		*tp,		/* transaction pointer */
+	xfs_inode_t		*ip,		/* incore inode pointer */
+	xfs_fsblock_t		*firstblock,	/* first block allocated */
+	xfs_bmap_free_t		*flist,		/* blocks to free at commit */
+	int			*flags)		/* inode logging flags */
+{
+	xfs_btree_cur_t		*cur;		/* bmap btree cursor */
+	int			error;		/* error return value */
 
-	/* clear out the allocated field, done with it now in any case. */
+	if (ip->i_d.di_nextents * sizeof(xfs_bmbt_rec_t) <= XFS_IFORK_DSIZE(ip))
+		return 0;
+	cur = NULL;
+	error = xfs_bmap_extents_to_btree(tp, ip, firstblock, flist, &cur, 0,
+		flags, XFS_DATA_FORK);
 	if (cur) {
 		cur->bc_private.b.allocated = 0;
-		*curp = cur;
+		xfs_btree_del_cursor(cur,
+			error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR);
 	}
-
-	xfs_bmap_check_leaf_extents(*curp, ip, XFS_DATA_FORK);
-done:
-	*logflagsp |= rval;
 	return error;
-#undef	LEFT
-#undef	RIGHT
-#undef	PREV
 }
 
 /*
- * Convert a hole to a delayed allocation.
+ * Block initialisation functions for local to extent format conversion.
+ * As these get more complex, they will be moved to the relevant files,
+ * but for now they are too simple to worry about.
  */
 STATIC void
-xfs_bmap_add_extent_hole_delay(
-	xfs_inode_t		*ip,	/* incore inode pointer */
-	xfs_extnum_t		*idx,	/* extent number to update/insert */
-	xfs_bmbt_irec_t		*new)	/* new data to add to file extents */
+xfs_bmap_local_to_extents_init_fn(
+	struct xfs_buf		*bp,
+	struct xfs_inode	*ip,
+	struct xfs_ifork	*ifp)
 {
-	xfs_ifork_t		*ifp;	/* inode fork pointer */
-	xfs_bmbt_irec_t		left;	/* left neighbor extent entry */
-	xfs_filblks_t		newlen=0;	/* new indirect size */
-	xfs_filblks_t		oldlen=0;	/* old indirect size */
-	xfs_bmbt_irec_t		right;	/* right neighbor extent entry */
-	int			state;  /* state bits, accessed thru macros */
-	xfs_filblks_t		temp=0;	/* temp for indirect calculations */
+	bp->b_ops = &xfs_bmbt_buf_ops;
+	memcpy(bp->b_addr, ifp->if_u1.if_data, ifp->if_bytes);
+}
 
-	ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
-	state = 0;
-	ASSERT(isnullstartblock(new->br_startblock));
+STATIC void
+xfs_symlink_local_to_remote(
+	struct xfs_buf		*bp,
+	struct xfs_inode	*ip,
+	struct xfs_ifork	*ifp)
+{
+	/* remote symlink blocks are not verifiable until CRCs come along */
+	bp->b_ops = NULL;
+	memcpy(bp->b_addr, ifp->if_u1.if_data, ifp->if_bytes);
+}
 
-	/*
-	 * Check and set flags if this segment has a left neighbor
-	 */
-	if (*idx > 0) {
-		state |= BMAP_LEFT_VALID;
-		xfs_bmbt_get_all(xfs_iext_get_ext(ifp, *idx - 1), &left);
+/*
+ * Called from xfs_bmap_add_attrfork to handle local format files. Each
+ * different data fork content type needs a different callout to do the
+ * conversion. Some are basic and only require special block initialisation
+ * callouts for the data formating, others (directories) are so specialised they
+ * handle everything themselves.
+ *
+ * XXX (dgc): investigate whether directory conversion can use the generic
+ * formatting callout. It should be possible - it's just a very complex
+ * formatter. it would also require passing the transaction through to the init
+ * function.
+ */
+STATIC int					/* error */
+xfs_bmap_add_attrfork_local(
+	xfs_trans_t		*tp,		/* transaction pointer */
+	xfs_inode_t		*ip,		/* incore inode pointer */
+	xfs_fsblock_t		*firstblock,	/* first block allocated */
+	xfs_bmap_free_t		*flist,		/* blocks to free at commit */
+	int			*flags)		/* inode logging flags */
+{
+	xfs_da_args_t		dargs;		/* args for dir/attr code */
 
-		if (isnullstartblock(left.br_startblock))
-			state |= BMAP_LEFT_DELAY;
-	}
+	if (ip->i_df.if_bytes <= XFS_IFORK_DSIZE(ip))
+		return 0;
 
-	/*
-	 * Check and set flags if the current (right) segment exists.
-	 * If it doesn't exist, we're converting the hole at end-of-file.
-	 */
-	if (*idx < ip->i_df.if_bytes / (uint)sizeof(xfs_bmbt_rec_t)) {
-		state |= BMAP_RIGHT_VALID;
-		xfs_bmbt_get_all(xfs_iext_get_ext(ifp, *idx), &right);
-
-		if (isnullstartblock(right.br_startblock))
-			state |= BMAP_RIGHT_DELAY;
+	if (S_ISDIR(ip->i_d.di_mode)) {
+		memset(&dargs, 0, sizeof(dargs));
+		dargs.dp = ip;
+		dargs.firstblock = firstblock;
+		dargs.flist = flist;
+		dargs.total = ip->i_mount->m_dirblkfsbs;
+		dargs.whichfork = XFS_DATA_FORK;
+		dargs.trans = tp;
+		return xfs_dir2_sf_to_block(&dargs);
 	}
 
-	/*
-	 * Set contiguity flags on the left and right neighbors.
-	 * Don't let extents get too large, even if the pieces are contiguous.
-	 */
-	if ((state & BMAP_LEFT_VALID) && (state & BMAP_LEFT_DELAY) &&
-	    left.br_startoff + left.br_blockcount == new->br_startoff &&
-	    left.br_blockcount + new->br_blockcount <= MAXEXTLEN)
-		state |= BMAP_LEFT_CONTIG;
-
-	if ((state & BMAP_RIGHT_VALID) && (state & BMAP_RIGHT_DELAY) &&
-	    new->br_startoff + new->br_blockcount == right.br_startoff &&
-	    new->br_blockcount + right.br_blockcount <= MAXEXTLEN &&
-	    (!(state & BMAP_LEFT_CONTIG) ||
-	     (left.br_blockcount + new->br_blockcount +
-	      right.br_blockcount <= MAXEXTLEN)))
-		state |= BMAP_RIGHT_CONTIG;
+	if (S_ISLNK(ip->i_d.di_mode))
+		return xfs_bmap_local_to_extents(tp, ip, firstblock, 1,
+						 flags, XFS_DATA_FORK,
+						 xfs_symlink_local_to_remote);
 
-	/*
-	 * Switch out based on the contiguity flags.
-	 */
-	switch (state & (BMAP_LEFT_CONTIG | BMAP_RIGHT_CONTIG)) {
-	case BMAP_LEFT_CONTIG | BMAP_RIGHT_CONTIG:
-		/*
-		 * New allocation is contiguous with delayed allocations
-		 * on the left and on the right.
-		 * Merge all three into a single extent record.
-		 */
-		--*idx;
-		temp = left.br_blockcount + new->br_blockcount +
-			right.br_blockcount;
+	return xfs_bmap_local_to_extents(tp, ip, firstblock, 1, flags,
+					 XFS_DATA_FORK,
+					 xfs_bmap_local_to_extents_init_fn);
+}
 
-		trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_);
-		xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, *idx), temp);
-		oldlen = startblockval(left.br_startblock) +
-			startblockval(new->br_startblock) +
-			startblockval(right.br_startblock);
-		newlen = xfs_bmap_worst_indlen(ip, temp);
-		xfs_bmbt_set_startblock(xfs_iext_get_ext(ifp, *idx),
-			nullstartblock((int)newlen));
-		trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_);
+/*
+ * Convert inode from non-attributed to attributed.
+ * Must not be in a transaction, ip must not be locked.
+ */
+int						/* error code */
+xfs_bmap_add_attrfork(
+	xfs_inode_t		*ip,		/* incore inode pointer */
+	int			size,		/* space new attribute needs */
+	int			rsvd)		/* xact may use reserved blks */
+{
+	xfs_fsblock_t		firstblock;	/* 1st block/ag allocated */
+	xfs_bmap_free_t		flist;		/* freed extent records */
+	xfs_mount_t		*mp;		/* mount structure */
+	xfs_trans_t		*tp;		/* transaction pointer */
+	int			blks;		/* space reservation */
+	int			version = 1;	/* superblock attr version */
+	int			committed;	/* xaction was committed */
+	int			logflags;	/* logging flags */
+	int			error;		/* error return value */
 
-		xfs_iext_remove(ip, *idx + 1, 1, state);
-		break;
+	ASSERT(XFS_IFORK_Q(ip) == 0);
 
-	case BMAP_LEFT_CONTIG:
+	mp = ip->i_mount;
+	ASSERT(!XFS_NOT_DQATTACHED(mp, ip));
+	tp = xfs_trans_alloc(mp, XFS_TRANS_ADDAFORK);
+	blks = XFS_ADDAFORK_SPACE_RES(mp);
+	if (rsvd)
+		tp->t_flags |= XFS_TRANS_RESERVE;
+	if ((error = xfs_trans_reserve(tp, blks, XFS_ADDAFORK_LOG_RES(mp), 0,
+			XFS_TRANS_PERM_LOG_RES, XFS_ADDAFORK_LOG_COUNT)))
+		goto error0;
+	xfs_ilock(ip, XFS_ILOCK_EXCL);
+	error = xfs_trans_reserve_quota_nblks(tp, ip, blks, 0, rsvd ?
+			XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_FORCE_RES :
+			XFS_QMOPT_RES_REGBLKS);
+	if (error) {
+		xfs_iunlock(ip, XFS_ILOCK_EXCL);
+		xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES);
+		return error;
+	}
+	if (XFS_IFORK_Q(ip))
+		goto error1;
+	if (ip->i_d.di_aformat != XFS_DINODE_FMT_EXTENTS) {
 		/*
-		 * New allocation is contiguous with a delayed allocation
-		 * on the left.
-		 * Merge the new allocation with the left neighbor.
+		 * For inodes coming from pre-6.2 filesystems.
 		 */
-		--*idx;
-		temp = left.br_blockcount + new->br_blockcount;
+		ASSERT(ip->i_d.di_aformat == 0);
+		ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;
+	}
+	ASSERT(ip->i_d.di_anextents == 0);
 
-		trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_);
-		xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, *idx), temp);
-		oldlen = startblockval(left.br_startblock) +
-			startblockval(new->br_startblock);
-		newlen = xfs_bmap_worst_indlen(ip, temp);
-		xfs_bmbt_set_startblock(xfs_iext_get_ext(ifp, *idx),
-			nullstartblock((int)newlen));
-		trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_);
-		break;
+	xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
+	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
 
-	case BMAP_RIGHT_CONTIG:
-		/*
-		 * New allocation is contiguous with a delayed allocation
-		 * on the right.
-		 * Merge the new allocation with the right neighbor.
-		 */
-		trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_);
-		temp = new->br_blockcount + right.br_blockcount;
-		oldlen = startblockval(new->br_startblock) +
-			startblockval(right.br_startblock);
-		newlen = xfs_bmap_worst_indlen(ip, temp);
-		xfs_bmbt_set_allf(xfs_iext_get_ext(ifp, *idx),
-			new->br_startoff,
-			nullstartblock((int)newlen), temp, right.br_state);
-		trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_);
+	switch (ip->i_d.di_format) {
+	case XFS_DINODE_FMT_DEV:
+		ip->i_d.di_forkoff = roundup(sizeof(xfs_dev_t), 8) >> 3;
+		break;
+	case XFS_DINODE_FMT_UUID:
+		ip->i_d.di_forkoff = roundup(sizeof(uuid_t), 8) >> 3;
+		break;
+	case XFS_DINODE_FMT_LOCAL:
+	case XFS_DINODE_FMT_EXTENTS:
+	case XFS_DINODE_FMT_BTREE:
+		ip->i_d.di_forkoff = xfs_attr_shortform_bytesfit(ip, size);
+		if (!ip->i_d.di_forkoff)
+			ip->i_d.di_forkoff = xfs_default_attroffset(ip) >> 3;
+		else if (mp->m_flags & XFS_MOUNT_ATTR2)
+			version = 2;
 		break;
+	default:
+		ASSERT(0);
+		error = XFS_ERROR(EINVAL);
+		goto error1;
+	}
 
-	case 0:
-		/*
-		 * New allocation is not contiguous with another
-		 * delayed allocation.
-		 * Insert a new entry.
-		 */
-		oldlen = newlen = 0;
-		xfs_iext_insert(ip, *idx, 1, new, state);
+	ASSERT(ip->i_afp == NULL);
+	ip->i_afp = kmem_zone_zalloc(xfs_ifork_zone, KM_SLEEP);
+	ip->i_afp->if_flags = XFS_IFEXTENTS;
+	logflags = 0;
+	xfs_bmap_init(&flist, &firstblock);
+	switch (ip->i_d.di_format) {
+	case XFS_DINODE_FMT_LOCAL:
+		error = xfs_bmap_add_attrfork_local(tp, ip, &firstblock, &flist,
+			&logflags);
+		break;
+	case XFS_DINODE_FMT_EXTENTS:
+		error = xfs_bmap_add_attrfork_extents(tp, ip, &firstblock,
+			&flist, &logflags);
+		break;
+	case XFS_DINODE_FMT_BTREE:
+		error = xfs_bmap_add_attrfork_btree(tp, ip, &firstblock, &flist,
+			&logflags);
+		break;
+	default:
+		error = 0;
 		break;
 	}
-	if (oldlen != newlen) {
-		ASSERT(oldlen > newlen);
-		xfs_icsb_modify_counters(ip->i_mount, XFS_SBS_FDBLOCKS,
-			(int64_t)(oldlen - newlen), 0);
-		/*
-		 * Nothing to do for disk quota accounting here.
-		 */
+	if (logflags)
+		xfs_trans_log_inode(tp, ip, logflags);
+	if (error)
+		goto error2;
+	if (!xfs_sb_version_hasattr(&mp->m_sb) ||
+	   (!xfs_sb_version_hasattr2(&mp->m_sb) && version == 2)) {
+		__int64_t sbfields = 0;
+
+		spin_lock(&mp->m_sb_lock);
+		if (!xfs_sb_version_hasattr(&mp->m_sb)) {
+			xfs_sb_version_addattr(&mp->m_sb);
+			sbfields |= XFS_SB_VERSIONNUM;
+		}
+		if (!xfs_sb_version_hasattr2(&mp->m_sb) && version == 2) {
+			xfs_sb_version_addattr2(&mp->m_sb);
+			sbfields |= (XFS_SB_VERSIONNUM | XFS_SB_FEATURES2);
+		}
+		if (sbfields) {
+			spin_unlock(&mp->m_sb_lock);
+			xfs_mod_sb(tp, sbfields);
+		} else
+			spin_unlock(&mp->m_sb_lock);
 	}
+
+	error = xfs_bmap_finish(&tp, &flist, &committed);
+	if (error)
+		goto error2;
+	return xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
+error2:
+	xfs_bmap_cancel(&flist);
+error1:
+	xfs_iunlock(ip, XFS_ILOCK_EXCL);
+error0:
+	xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT);
+	return error;
 }
 
 /*
- * Convert a hole to a real allocation.
+ * Internal and external extent tree search functions.
  */
-STATIC int				/* error */
-xfs_bmap_add_extent_hole_real(
-	struct xfs_bmalloca	*bma,
-	int			whichfork)
+
+/*
+ * Read in the extents to if_extents.
+ * All inode fields are set up by caller, we just traverse the btree
+ * and copy the records in. If the file system cannot contain unwritten
+ * extents, the records are checked for no "state" flags.
+ */
+int					/* error */
+xfs_bmap_read_extents(
+	xfs_trans_t		*tp,	/* transaction pointer */
+	xfs_inode_t		*ip,	/* incore inode */
+	int			whichfork) /* data or attr fork */
 {
-	struct xfs_bmbt_irec	*new = &bma->got;
+	struct xfs_btree_block	*block;	/* current btree block */
+	xfs_fsblock_t		bno;	/* block # of "block" */
+	xfs_buf_t		*bp;	/* buffer for "block" */
 	int			error;	/* error return value */
-	int			i;	/* temp state */
-	xfs_ifork_t		*ifp;	/* inode fork pointer */
-	xfs_bmbt_irec_t		left;	/* left neighbor extent entry */
-	xfs_bmbt_irec_t		right;	/* right neighbor extent entry */
-	int			rval=0;	/* return value (logging flags) */
-	int			state;	/* state bits, accessed thru macros */
-
-	ifp = XFS_IFORK_PTR(bma->ip, whichfork);
-
-	ASSERT(bma->idx >= 0);
-	ASSERT(bma->idx <= ifp->if_bytes / sizeof(struct xfs_bmbt_rec));
-	ASSERT(!isnullstartblock(new->br_startblock));
-	ASSERT(!bma->cur ||
-	       !(bma->cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL));
-
-	XFS_STATS_INC(xs_add_exlist);
-
-	state = 0;
-	if (whichfork == XFS_ATTR_FORK)
-		state |= BMAP_ATTRFORK;
+	xfs_exntfmt_t		exntf;	/* XFS_EXTFMT_NOSTATE, if checking */
+	xfs_extnum_t		i, j;	/* index into the extents list */
+	xfs_ifork_t		*ifp;	/* fork structure */
+	int			level;	/* btree level, for checking */
+	xfs_mount_t		*mp;	/* file system mount structure */
+	__be64			*pp;	/* pointer to block address */
+	/* REFERENCED */
+	xfs_extnum_t		room;	/* number of entries there's room for */
 
+	bno = NULLFSBLOCK;
+	mp = ip->i_mount;
+	ifp = XFS_IFORK_PTR(ip, whichfork);
+	exntf = (whichfork != XFS_DATA_FORK) ? XFS_EXTFMT_NOSTATE :
+					XFS_EXTFMT_INODE(ip);
+	block = ifp->if_broot;
 	/*
-	 * Check and set flags if this segment has a left neighbor.
+	 * Root level must use BMAP_BROOT_PTR_ADDR macro to get ptr out.
 	 */
-	if (bma->idx > 0) {
-		state |= BMAP_LEFT_VALID;
-		xfs_bmbt_get_all(xfs_iext_get_ext(ifp, bma->idx - 1), &left);
-		if (isnullstartblock(left.br_startblock))
-			state |= BMAP_LEFT_DELAY;
-	}
-
+	level = be16_to_cpu(block->bb_level);
+	ASSERT(level > 0);
+	pp = XFS_BMAP_BROOT_PTR_ADDR(mp, block, 1, ifp->if_broot_bytes);
+	bno = be64_to_cpu(*pp);
+	ASSERT(bno != NULLDFSBNO);
+	ASSERT(XFS_FSB_TO_AGNO(mp, bno) < mp->m_sb.sb_agcount);
+	ASSERT(XFS_FSB_TO_AGBNO(mp, bno) < mp->m_sb.sb_agblocks);
 	/*
-	 * Check and set flags if this segment has a current value.
-	 * Not true if we're inserting into the "hole" at eof.
+	 * Go down the tree until leaf level is reached, following the first
+	 * pointer (leftmost) at each level.
 	 */
-	if (bma->idx < ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t)) {
-		state |= BMAP_RIGHT_VALID;
-		xfs_bmbt_get_all(xfs_iext_get_ext(ifp, bma->idx), &right);
-		if (isnullstartblock(right.br_startblock))
-			state |= BMAP_RIGHT_DELAY;
+	while (level-- > 0) {
+		error = xfs_btree_read_bufl(mp, tp, bno, 0, &bp,
+				XFS_BMAP_BTREE_REF, &xfs_bmbt_buf_ops);
+		if (error)
+			return error;
+		block = XFS_BUF_TO_BLOCK(bp);
+		XFS_WANT_CORRUPTED_GOTO(
+			xfs_bmap_sanity_check(mp, bp, level),
+			error0);
+		if (level == 0)
+			break;
+		pp = XFS_BMBT_PTR_ADDR(mp, block, 1, mp->m_bmap_dmxr[1]);
+		bno = be64_to_cpu(*pp);
+		XFS_WANT_CORRUPTED_GOTO(XFS_FSB_SANITY_CHECK(mp, bno), error0);
+		xfs_trans_brelse(tp, bp);
 	}
-
 	/*
-	 * We're inserting a real allocation between "left" and "right".
-	 * Set the contiguity flags.  Don't let extents get too large.
+	 * Here with bp and block set to the leftmost leaf node in the tree.
 	 */
-	if ((state & BMAP_LEFT_VALID) && !(state & BMAP_LEFT_DELAY) &&
-	    left.br_startoff + left.br_blockcount == new->br_startoff &&
-	    left.br_startblock + left.br_blockcount == new->br_startblock &&
-	    left.br_state == new->br_state &&
-	    left.br_blockcount + new->br_blockcount <= MAXEXTLEN)
-		state |= BMAP_LEFT_CONTIG;
-
-	if ((state & BMAP_RIGHT_VALID) && !(state & BMAP_RIGHT_DELAY) &&
-	    new->br_startoff + new->br_blockcount == right.br_startoff &&
-	    new->br_startblock + new->br_blockcount == right.br_startblock &&
-	    new->br_state == right.br_state &&
-	    new->br_blockcount + right.br_blockcount <= MAXEXTLEN &&
-	    (!(state & BMAP_LEFT_CONTIG) ||
-	     left.br_blockcount + new->br_blockcount +
-	     right.br_blockcount <= MAXEXTLEN))
-		state |= BMAP_RIGHT_CONTIG;
-
-	error = 0;
+	room = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
+	i = 0;
 	/*
-	 * Select which case we're in here, and implement it.
+	 * Loop over all leaf nodes.  Copy information to the extent records.
 	 */
-	switch (state & (BMAP_LEFT_CONTIG | BMAP_RIGHT_CONTIG)) {
-	case BMAP_LEFT_CONTIG | BMAP_RIGHT_CONTIG:
-		/*
-		 * New allocation is contiguous with real allocations on the
-		 * left and on the right.
-		 * Merge all three into a single extent record.
-		 */
-		--bma->idx;
-		trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_);
-		xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, bma->idx),
-			left.br_blockcount + new->br_blockcount +
-			right.br_blockcount);
-		trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_);
-
-		xfs_iext_remove(bma->ip, bma->idx + 1, 1, state);
+	for (;;) {
+		xfs_bmbt_rec_t	*frp;
+		xfs_fsblock_t	nextbno;
+		xfs_extnum_t	num_recs;
+		xfs_extnum_t	start;
 
-		XFS_IFORK_NEXT_SET(bma->ip, whichfork,
-			XFS_IFORK_NEXTENTS(bma->ip, whichfork) - 1);
-		if (bma->cur == NULL) {
-			rval = XFS_ILOG_CORE | xfs_ilog_fext(whichfork);
-		} else {
-			rval = XFS_ILOG_CORE;
-			error = xfs_bmbt_lookup_eq(bma->cur, right.br_startoff,
-					right.br_startblock, right.br_blockcount,
-					&i);
-			if (error)
-				goto done;
-			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
-			error = xfs_btree_delete(bma->cur, &i);
-			if (error)
-				goto done;
-			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
-			error = xfs_btree_decrement(bma->cur, 0, &i);
-			if (error)
-				goto done;
-			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
-			error = xfs_bmbt_update(bma->cur, left.br_startoff,
-					left.br_startblock,
-					left.br_blockcount +
-						new->br_blockcount +
-						right.br_blockcount,
-					left.br_state);
-			if (error)
-				goto done;
+		num_recs = xfs_btree_get_numrecs(block);
+		if (unlikely(i + num_recs > room)) {
+			ASSERT(i + num_recs <= room);
+			xfs_warn(ip->i_mount,
+				"corrupt dinode %Lu, (btree extents).",
+				(unsigned long long) ip->i_ino);
+			XFS_CORRUPTION_ERROR("xfs_bmap_read_extents(1)",
+				XFS_ERRLEVEL_LOW, ip->i_mount, block);
+			goto error0;
 		}
-		break;
-
-	case BMAP_LEFT_CONTIG:
+		XFS_WANT_CORRUPTED_GOTO(
+			xfs_bmap_sanity_check(mp, bp, 0),
+			error0);
 		/*
-		 * New allocation is contiguous with a real allocation
-		 * on the left.
-		 * Merge the new allocation with the left neighbor.
+		 * Read-ahead the next leaf block, if any.
 		 */
-		--bma->idx;
-		trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_);
-		xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, bma->idx),
-			left.br_blockcount + new->br_blockcount);
-		trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_);
-
-		if (bma->cur == NULL) {
-			rval = xfs_ilog_fext(whichfork);
-		} else {
-			rval = 0;
-			error = xfs_bmbt_lookup_eq(bma->cur, left.br_startoff,
-					left.br_startblock, left.br_blockcount,
-					&i);
-			if (error)
-				goto done;
-			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
-			error = xfs_bmbt_update(bma->cur, left.br_startoff,
-					left.br_startblock,
-					left.br_blockcount +
-						new->br_blockcount,
-					left.br_state);
-			if (error)
-				goto done;
-		}
-		break;
-
-	case BMAP_RIGHT_CONTIG:
+		nextbno = be64_to_cpu(block->bb_u.l.bb_rightsib);
+		if (nextbno != NULLFSBLOCK)
+			xfs_btree_reada_bufl(mp, nextbno, 1,
+					     &xfs_bmbt_buf_ops);
 		/*
-		 * New allocation is contiguous with a real allocation
-		 * on the right.
-		 * Merge the new allocation with the right neighbor.
+		 * Copy records into the extent records.
 		 */
-		trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_);
-		xfs_bmbt_set_allf(xfs_iext_get_ext(ifp, bma->idx),
-			new->br_startoff, new->br_startblock,
-			new->br_blockcount + right.br_blockcount,
-			right.br_state);
-		trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_);
-
-		if (bma->cur == NULL) {
-			rval = xfs_ilog_fext(whichfork);
-		} else {
-			rval = 0;
-			error = xfs_bmbt_lookup_eq(bma->cur,
-					right.br_startoff,
-					right.br_startblock,
-					right.br_blockcount, &i);
-			if (error)
-				goto done;
-			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
-			error = xfs_bmbt_update(bma->cur, new->br_startoff,
-					new->br_startblock,
-					new->br_blockcount +
-						right.br_blockcount,
-					right.br_state);
-			if (error)
-				goto done;
+		frp = XFS_BMBT_REC_ADDR(mp, block, 1);
+		start = i;
+		for (j = 0; j < num_recs; j++, i++, frp++) {
+			xfs_bmbt_rec_host_t *trp = xfs_iext_get_ext(ifp, i);
+			trp->l0 = be64_to_cpu(frp->l0);
+			trp->l1 = be64_to_cpu(frp->l1);
 		}
-		break;
-
-	case 0:
+		if (exntf == XFS_EXTFMT_NOSTATE) {
+			/*
+			 * Check all attribute bmap btree records and
+			 * any "older" data bmap btree records for a
+			 * set bit in the "extent flag" position.
+			 */
+			if (unlikely(xfs_check_nostate_extents(ifp,
+					start, num_recs))) {
+				XFS_ERROR_REPORT("xfs_bmap_read_extents(2)",
+						 XFS_ERRLEVEL_LOW,
+						 ip->i_mount);
+				goto error0;
+			}
+		}
+		xfs_trans_brelse(tp, bp);
+		bno = nextbno;
 		/*
-		 * New allocation is not contiguous with another
-		 * real allocation.
-		 * Insert a new entry.
+		 * If we've reached the end, stop.
 		 */
-		xfs_iext_insert(bma->ip, bma->idx, 1, new, state);
-		XFS_IFORK_NEXT_SET(bma->ip, whichfork,
-			XFS_IFORK_NEXTENTS(bma->ip, whichfork) + 1);
-		if (bma->cur == NULL) {
-			rval = XFS_ILOG_CORE | xfs_ilog_fext(whichfork);
-		} else {
-			rval = XFS_ILOG_CORE;
-			error = xfs_bmbt_lookup_eq(bma->cur,
-					new->br_startoff,
-					new->br_startblock,
-					new->br_blockcount, &i);
-			if (error)
-				goto done;
-			XFS_WANT_CORRUPTED_GOTO(i == 0, done);
-			bma->cur->bc_rec.b.br_state = new->br_state;
-			error = xfs_btree_insert(bma->cur, &i);
-			if (error)
-				goto done;
-			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
-		}
-		break;
+		if (bno == NULLFSBLOCK)
+			break;
+		error = xfs_btree_read_bufl(mp, tp, bno, 0, &bp,
+				XFS_BMAP_BTREE_REF, &xfs_bmbt_buf_ops);
+		if (error)
+			return error;
+		block = XFS_BUF_TO_BLOCK(bp);
 	}
+	ASSERT(i == (ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t)));
+	ASSERT(i == XFS_IFORK_NEXTENTS(ip, whichfork));
+	XFS_BMAP_TRACE_EXLIST(ip, i, whichfork);
+	return 0;
+error0:
+	xfs_trans_brelse(tp, bp);
+	return XFS_ERROR(EFSCORRUPTED);
+}
 
-	/* convert to a btree if necessary */
-	if (xfs_bmap_needs_btree(bma->ip, whichfork)) {
-		int	tmp_logflags;	/* partial log flag return val */
 
-		ASSERT(bma->cur == NULL);
-		error = xfs_bmap_extents_to_btree(bma->tp, bma->ip,
-				bma->firstblock, bma->flist, &bma->cur,
-				0, &tmp_logflags, whichfork);
-		bma->logflags |= tmp_logflags;
-		if (error)
-			goto done;
-	}
+/*
+ * Search the extent records for the entry containing block bno.
+ * If bno lies in a hole, point to the next entry.  If bno lies
+ * past eof, *eofp will be set, and *prevp will contain the last
+ * entry (null if none).  Else, *lastxp will be set to the index
+ * of the found entry; *gotp will contain the entry.
+ */
+STATIC xfs_bmbt_rec_host_t *		/* pointer to found extent entry */
+xfs_bmap_search_multi_extents(
+	xfs_ifork_t	*ifp,		/* inode fork pointer */
+	xfs_fileoff_t	bno,		/* block number searched for */
+	int		*eofp,		/* out: end of file found */
+	xfs_extnum_t	*lastxp,	/* out: last extent index */
+	xfs_bmbt_irec_t	*gotp,		/* out: extent entry found */
+	xfs_bmbt_irec_t	*prevp)		/* out: previous extent entry found */
+{
+	xfs_bmbt_rec_host_t *ep;		/* extent record pointer */
+	xfs_extnum_t	lastx;		/* last extent index */
 
-	/* clear out the allocated field, done with it now in any case. */
-	if (bma->cur)
-		bma->cur->bc_private.b.allocated = 0;
+	/*
+	 * Initialize the extent entry structure to catch access to
+	 * uninitialized br_startblock field.
+	 */
+	gotp->br_startoff = 0xffa5a5a5a5a5a5a5LL;
+	gotp->br_blockcount = 0xa55a5a5a5a5a5a5aLL;
+	gotp->br_state = XFS_EXT_INVALID;
+#if XFS_BIG_BLKNOS
+	gotp->br_startblock = 0xffffa5a5a5a5a5a5LL;
+#else
+	gotp->br_startblock = 0xffffa5a5;
+#endif
+	prevp->br_startoff = NULLFILEOFF;
 
-	xfs_bmap_check_leaf_extents(bma->cur, bma->ip, whichfork);
-done:
-	bma->logflags |= rval;
-	return error;
+	ep = xfs_iext_bno_to_ext(ifp, bno, &lastx);
+	if (lastx > 0) {
+		xfs_bmbt_get_all(xfs_iext_get_ext(ifp, lastx - 1), prevp);
+	}
+	if (lastx < (ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t))) {
+		xfs_bmbt_get_all(ep, gotp);
+		*eofp = 0;
+	} else {
+		if (lastx > 0) {
+			*gotp = *prevp;
+		}
+		*eofp = 1;
+		ep = NULL;
+	}
+	*lastxp = lastx;
+	return ep;
 }
 
 /*
- * Adjust the size of the new extent based on di_extsize and rt extsize.
+ * Search the extents list for the inode, for the extent containing bno.
+ * If bno lies in a hole, point to the next entry.  If bno lies past eof,
+ * *eofp will be set, and *prevp will contain the last entry (null if none).
+ * Else, *lastxp will be set to the index of the found
+ * entry; *gotp will contain the entry.
  */
-STATIC int
-xfs_bmap_extsize_align(
-	xfs_mount_t	*mp,
-	xfs_bmbt_irec_t	*gotp,		/* next extent pointer */
-	xfs_bmbt_irec_t	*prevp,		/* previous extent pointer */
-	xfs_extlen_t	extsz,		/* align to this extent size */
-	int		rt,		/* is this a realtime inode? */
-	int		eof,		/* is extent at end-of-file? */
-	int		delay,		/* creating delalloc extent? */
-	int		convert,	/* overwriting unwritten extent? */
-	xfs_fileoff_t	*offp,		/* in/out: aligned offset */
-	xfs_extlen_t	*lenp)		/* in/out: aligned length */
+STATIC xfs_bmbt_rec_host_t *                 /* pointer to found extent entry */
+xfs_bmap_search_extents(
+	xfs_inode_t     *ip,            /* incore inode pointer */
+	xfs_fileoff_t   bno,            /* block number searched for */
+	int             fork,      	/* data or attr fork */
+	int             *eofp,          /* out: end of file found */
+	xfs_extnum_t    *lastxp,        /* out: last extent index */
+	xfs_bmbt_irec_t *gotp,          /* out: extent entry found */
+	xfs_bmbt_irec_t *prevp)         /* out: previous extent entry found */
 {
-	xfs_fileoff_t	orig_off;	/* original offset */
-	xfs_extlen_t	orig_alen;	/* original length */
-	xfs_fileoff_t	orig_end;	/* original off+len */
-	xfs_fileoff_t	nexto;		/* next file offset */
-	xfs_fileoff_t	prevo;		/* previous file offset */
-	xfs_fileoff_t	align_off;	/* temp for offset */
-	xfs_extlen_t	align_alen;	/* temp for length */
-	xfs_extlen_t	temp;		/* temp for calculations */
+	xfs_ifork_t	*ifp;		/* inode fork pointer */
+	xfs_bmbt_rec_host_t  *ep;            /* extent record pointer */
 
-	if (convert)
-		return 0;
+	XFS_STATS_INC(xs_look_exlist);
+	ifp = XFS_IFORK_PTR(ip, fork);
 
-	orig_off = align_off = *offp;
-	orig_alen = align_alen = *lenp;
-	orig_end = orig_off + orig_alen;
+	ep = xfs_bmap_search_multi_extents(ifp, bno, eofp, lastxp, gotp, prevp);
 
-	/*
-	 * If this request overlaps an existing extent, then don't
-	 * attempt to perform any additional alignment.
-	 */
-	if (!delay && !eof &&
-	    (orig_off >= gotp->br_startoff) &&
-	    (orig_end <= gotp->br_startoff + gotp->br_blockcount)) {
-		return 0;
+	if (unlikely(!(gotp->br_startblock) && (*lastxp != NULLEXTNUM) &&
+		     !(XFS_IS_REALTIME_INODE(ip) && fork == XFS_DATA_FORK))) {
+		xfs_alert_tag(ip->i_mount, XFS_PTAG_FSBLOCK_ZERO,
+				"Access to block zero in inode %llu "
+				"start_block: %llx start_off: %llx "
+				"blkcnt: %llx extent-state: %x lastx: %x\n",
+			(unsigned long long)ip->i_ino,
+			(unsigned long long)gotp->br_startblock,
+			(unsigned long long)gotp->br_startoff,
+			(unsigned long long)gotp->br_blockcount,
+			gotp->br_state, *lastxp);
+		*lastxp = NULLEXTNUM;
+		*eofp = 1;
+		return NULL;
 	}
+	return ep;
+}
 
-	/*
-	 * If the file offset is unaligned vs. the extent size
-	 * we need to align it.  This will be possible unless
-	 * the file was previously written with a kernel that didn't
-	 * perform this alignment, or if a truncate shot us in the
-	 * foot.
-	 */
-	temp = do_mod(orig_off, extsz);
-	if (temp) {
-		align_alen += temp;
-		align_off -= temp;
+/*
+ * Returns the file-relative block number of the first unused block(s)
+ * in the file with at least "len" logically contiguous blocks free.
+ * This is the lowest-address hole if the file has holes, else the first block
+ * past the end of file.
+ * Return 0 if the file is currently local (in-inode).
+ */
+int						/* error */
+xfs_bmap_first_unused(
+	xfs_trans_t	*tp,			/* transaction pointer */
+	xfs_inode_t	*ip,			/* incore inode */
+	xfs_extlen_t	len,			/* size of hole to find */
+	xfs_fileoff_t	*first_unused,		/* unused block */
+	int		whichfork)		/* data or attr fork */
+{
+	int		error;			/* error return value */
+	int		idx;			/* extent record index */
+	xfs_ifork_t	*ifp;			/* inode fork pointer */
+	xfs_fileoff_t	lastaddr;		/* last block number seen */
+	xfs_fileoff_t	lowest;			/* lowest useful block */
+	xfs_fileoff_t	max;			/* starting useful block */
+	xfs_fileoff_t	off;			/* offset for this block */
+	xfs_extnum_t	nextents;		/* number of extent entries */
+
+	ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE ||
+	       XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS ||
+	       XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL);
+	if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) {
+		*first_unused = 0;
+		return 0;
 	}
-	/*
-	 * Same adjustment for the end of the requested area.
-	 */
-	if ((temp = (align_alen % extsz))) {
-		align_alen += extsz - temp;
+	ifp = XFS_IFORK_PTR(ip, whichfork);
+	if (!(ifp->if_flags & XFS_IFEXTENTS) &&
+	    (error = xfs_iread_extents(tp, ip, whichfork)))
+		return error;
+	lowest = *first_unused;
+	nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
+	for (idx = 0, lastaddr = 0, max = lowest; idx < nextents; idx++) {
+		xfs_bmbt_rec_host_t *ep = xfs_iext_get_ext(ifp, idx);
+		off = xfs_bmbt_get_startoff(ep);
+		/*
+		 * See if the hole before this extent will work.
+		 */
+		if (off >= lowest + len && off - max >= len) {
+			*first_unused = max;
+			return 0;
+		}
+		lastaddr = off + xfs_bmbt_get_blockcount(ep);
+		max = XFS_FILEOFF_MAX(lastaddr, lowest);
 	}
-	/*
-	 * If the previous block overlaps with this proposed allocation
-	 * then move the start forward without adjusting the length.
-	 */
-	if (prevp->br_startoff != NULLFILEOFF) {
-		if (prevp->br_startblock == HOLESTARTBLOCK)
-			prevo = prevp->br_startoff;
-		else
-			prevo = prevp->br_startoff + prevp->br_blockcount;
-	} else
-		prevo = 0;
-	if (align_off != orig_off && align_off < prevo)
-		align_off = prevo;
-	/*
-	 * If the next block overlaps with this proposed allocation
-	 * then move the start back without adjusting the length,
-	 * but not before offset 0.
-	 * This may of course make the start overlap previous block,
-	 * and if we hit the offset 0 limit then the next block
-	 * can still overlap too.
-	 */
-	if (!eof && gotp->br_startoff != NULLFILEOFF) {
-		if ((delay && gotp->br_startblock == HOLESTARTBLOCK) ||
-		    (!delay && gotp->br_startblock == DELAYSTARTBLOCK))
-			nexto = gotp->br_startoff + gotp->br_blockcount;
+	*first_unused = max;
+	return 0;
+}
+
+/*
+ * Returns the file-relative block number of the last block + 1 before
+ * last_block (input value) in the file.
+ * This is not based on i_size, it is based on the extent records.
+ * Returns 0 for local files, as they do not have extent records.
+ */
+int						/* error */
+xfs_bmap_last_before(
+	xfs_trans_t	*tp,			/* transaction pointer */
+	xfs_inode_t	*ip,			/* incore inode */
+	xfs_fileoff_t	*last_block,		/* last block */
+	int		whichfork)		/* data or attr fork */
+{
+	xfs_fileoff_t	bno;			/* input file offset */
+	int		eof;			/* hit end of file */
+	xfs_bmbt_rec_host_t *ep;		/* pointer to last extent */
+	int		error;			/* error return value */
+	xfs_bmbt_irec_t	got;			/* current extent value */
+	xfs_ifork_t	*ifp;			/* inode fork pointer */
+	xfs_extnum_t	lastx;			/* last extent used */
+	xfs_bmbt_irec_t	prev;			/* previous extent value */
+
+	if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE &&
+	    XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
+	    XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL)
+	       return XFS_ERROR(EIO);
+	if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) {
+		*last_block = 0;
+		return 0;
+	}
+	ifp = XFS_IFORK_PTR(ip, whichfork);
+	if (!(ifp->if_flags & XFS_IFEXTENTS) &&
+	    (error = xfs_iread_extents(tp, ip, whichfork)))
+		return error;
+	bno = *last_block - 1;
+	ep = xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got,
+		&prev);
+	if (eof || xfs_bmbt_get_startoff(ep) > bno) {
+		if (prev.br_startoff == NULLFILEOFF)
+			*last_block = 0;
 		else
-			nexto = gotp->br_startoff;
-	} else
-		nexto = NULLFILEOFF;
-	if (!eof &&
-	    align_off + align_alen != orig_end &&
-	    align_off + align_alen > nexto)
-		align_off = nexto > align_alen ? nexto - align_alen : 0;
-	/*
-	 * If we're now overlapping the next or previous extent that
-	 * means we can't fit an extsz piece in this hole.  Just move
-	 * the start forward to the first valid spot and set
-	 * the length so we hit the end.
-	 */
-	if (align_off != orig_off && align_off < prevo)
-		align_off = prevo;
-	if (align_off + align_alen != orig_end &&
-	    align_off + align_alen > nexto &&
-	    nexto != NULLFILEOFF) {
-		ASSERT(nexto > prevo);
-		align_alen = nexto - align_off;
+			*last_block = prev.br_startoff + prev.br_blockcount;
 	}
-
 	/*
-	 * If realtime, and the result isn't a multiple of the realtime
-	 * extent size we need to remove blocks until it is.
+	 * Otherwise *last_block is already the right answer.
 	 */
-	if (rt && (temp = (align_alen % mp->m_sb.sb_rextsize))) {
-		/*
-		 * We're not covering the original request, or
-		 * we won't be able to once we fix the length.
-		 */
-		if (orig_off < align_off ||
-		    orig_end > align_off + align_alen ||
-		    align_alen - temp < orig_alen)
-			return XFS_ERROR(EINVAL);
-		/*
-		 * Try to fix it by moving the start up.
-		 */
-		if (align_off + temp <= orig_off) {
-			align_alen -= temp;
-			align_off += temp;
-		}
-		/*
-		 * Try to fix it by moving the end in.
-		 */
-		else if (align_off + align_alen - temp >= orig_end)
-			align_alen -= temp;
-		/*
-		 * Set the start to the minimum then trim the length.
-		 */
-		else {
-			align_alen -= orig_off - align_off;
-			align_off = orig_off;
-			align_alen -= align_alen % mp->m_sb.sb_rextsize;
-		}
-		/*
-		 * Result doesn't cover the request, fail it.
-		 */
-		if (orig_off < align_off || orig_end > align_off + align_alen)
-			return XFS_ERROR(EINVAL);
-	} else {
-		ASSERT(orig_off >= align_off);
-		ASSERT(orig_end <= align_off + align_alen);
+	return 0;
+}
+
+STATIC int
+xfs_bmap_last_extent(
+	struct xfs_trans	*tp,
+	struct xfs_inode	*ip,
+	int			whichfork,
+	struct xfs_bmbt_irec	*rec,
+	int			*is_empty)
+{
+	struct xfs_ifork	*ifp = XFS_IFORK_PTR(ip, whichfork);
+	int			error;
+	int			nextents;
+
+	if (!(ifp->if_flags & XFS_IFEXTENTS)) {
+		error = xfs_iread_extents(tp, ip, whichfork);
+		if (error)
+			return error;
 	}
 
-#ifdef DEBUG
-	if (!eof && gotp->br_startoff != NULLFILEOFF)
-		ASSERT(align_off + align_alen <= gotp->br_startoff);
-	if (prevp->br_startoff != NULLFILEOFF)
-		ASSERT(align_off >= prevp->br_startoff + prevp->br_blockcount);
-#endif
+	nextents = ifp->if_bytes / sizeof(xfs_bmbt_rec_t);
+	if (nextents == 0) {
+		*is_empty = 1;
+		return 0;
+	}
 
-	*lenp = align_alen;
-	*offp = align_off;
+	xfs_bmbt_get_all(xfs_iext_get_ext(ifp, nextents - 1), rec);
+	*is_empty = 0;
 	return 0;
 }
 
-#define XFS_ALLOC_GAP_UNITS	4
-
-STATIC void
-xfs_bmap_adjacent(
-	xfs_bmalloca_t	*ap)		/* bmap alloc argument struct */
+/*
+ * Check the last inode extent to determine whether this allocation will result
+ * in blocks being allocated at the end of the file. When we allocate new data
+ * blocks at the end of the file which do not start at the previous data block,
+ * we will try to align the new blocks at stripe unit boundaries.
+ *
+ * Returns 0 in bma->aeof if the file (fork) is empty as any new write will be
+ * at, or past the EOF.
+ */
+STATIC int
+xfs_bmap_isaeof(
+	struct xfs_bmalloca	*bma,
+	int			whichfork)
 {
-	xfs_fsblock_t	adjust;		/* adjustment to block numbers */
-	xfs_agnumber_t	fb_agno;	/* ag number of ap->firstblock */
-	xfs_mount_t	*mp;		/* mount point structure */
-	int		nullfb;		/* true if ap->firstblock isn't set */
-	int		rt;		/* true if inode is realtime */
+	struct xfs_bmbt_irec	rec;
+	int			is_empty;
+	int			error;
 
-#define	ISVALID(x,y)	\
-	(rt ? \
-		(x) < mp->m_sb.sb_rblocks : \
-		XFS_FSB_TO_AGNO(mp, x) == XFS_FSB_TO_AGNO(mp, y) && \
-		XFS_FSB_TO_AGNO(mp, x) < mp->m_sb.sb_agcount && \
-		XFS_FSB_TO_AGBNO(mp, x) < mp->m_sb.sb_agblocks)
+	bma->aeof = 0;
+	error = xfs_bmap_last_extent(NULL, bma->ip, whichfork, &rec,
+				     &is_empty);
+	if (error || is_empty)
+		return error;
 
-	mp = ap->ip->i_mount;
-	nullfb = *ap->firstblock == NULLFSBLOCK;
-	rt = XFS_IS_REALTIME_INODE(ap->ip) && ap->userdata;
-	fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, *ap->firstblock);
-	/*
-	 * If allocating at eof, and there's a previous real block,
-	 * try to use its last block as our starting point.
-	 */
-	if (ap->eof && ap->prev.br_startoff != NULLFILEOFF &&
-	    !isnullstartblock(ap->prev.br_startblock) &&
-	    ISVALID(ap->prev.br_startblock + ap->prev.br_blockcount,
-		    ap->prev.br_startblock)) {
-		ap->blkno = ap->prev.br_startblock + ap->prev.br_blockcount;
-		/*
-		 * Adjust for the gap between prevp and us.
-		 */
-		adjust = ap->offset -
-			(ap->prev.br_startoff + ap->prev.br_blockcount);
-		if (adjust &&
-		    ISVALID(ap->blkno + adjust, ap->prev.br_startblock))
-			ap->blkno += adjust;
-	}
 	/*
-	 * If not at eof, then compare the two neighbor blocks.
-	 * Figure out whether either one gives us a good starting point,
-	 * and pick the better one.
+	 * Check if we are allocation or past the last extent, or at least into
+	 * the last delayed allocated extent.
 	 */
-	else if (!ap->eof) {
-		xfs_fsblock_t	gotbno;		/* right side block number */
-		xfs_fsblock_t	gotdiff=0;	/* right side difference */
-		xfs_fsblock_t	prevbno;	/* left side block number */
-		xfs_fsblock_t	prevdiff=0;	/* left side difference */
+	bma->aeof = bma->offset >= rec.br_startoff + rec.br_blockcount ||
+		(bma->offset >= rec.br_startoff &&
+		 isnullstartblock(rec.br_startblock));
+	return 0;
+}
 
-		/*
-		 * If there's a previous (left) block, select a requested
-		 * start block based on it.
-		 */
-		if (ap->prev.br_startoff != NULLFILEOFF &&
-		    !isnullstartblock(ap->prev.br_startblock) &&
-		    (prevbno = ap->prev.br_startblock +
-			       ap->prev.br_blockcount) &&
-		    ISVALID(prevbno, ap->prev.br_startblock)) {
-			/*
-			 * Calculate gap to end of previous block.
-			 */
-			adjust = prevdiff = ap->offset -
-				(ap->prev.br_startoff +
-				 ap->prev.br_blockcount);
-			/*
-			 * Figure the startblock based on the previous block's
-			 * end and the gap size.
-			 * Heuristic!
-			 * If the gap is large relative to the piece we're
-			 * allocating, or using it gives us an invalid block
-			 * number, then just use the end of the previous block.
-			 */
-			if (prevdiff <= XFS_ALLOC_GAP_UNITS * ap->length &&
-			    ISVALID(prevbno + prevdiff,
-				    ap->prev.br_startblock))
-				prevbno += adjust;
-			else
-				prevdiff += adjust;
-			/*
-			 * If the firstblock forbids it, can't use it,
-			 * must use default.
-			 */
-			if (!rt && !nullfb &&
-			    XFS_FSB_TO_AGNO(mp, prevbno) != fb_agno)
-				prevbno = NULLFSBLOCK;
-		}
-		/*
-		 * No previous block or can't follow it, just default.
-		 */
-		else
-			prevbno = NULLFSBLOCK;
-		/*
-		 * If there's a following (right) block, select a requested
-		 * start block based on it.
-		 */
-		if (!isnullstartblock(ap->got.br_startblock)) {
-			/*
-			 * Calculate gap to start of next block.
-			 */
-			adjust = gotdiff = ap->got.br_startoff - ap->offset;
-			/*
-			 * Figure the startblock based on the next block's
-			 * start and the gap size.
-			 */
-			gotbno = ap->got.br_startblock;
-			/*
-			 * Heuristic!
-			 * If the gap is large relative to the piece we're
-			 * allocating, or using it gives us an invalid block
-			 * number, then just use the start of the next block
-			 * offset by our length.
-			 */
-			if (gotdiff <= XFS_ALLOC_GAP_UNITS * ap->length &&
-			    ISVALID(gotbno - gotdiff, gotbno))
-				gotbno -= adjust;
-			else if (ISVALID(gotbno - ap->length, gotbno)) {
-				gotbno -= ap->length;
-				gotdiff += adjust - ap->length;
-			} else
-				gotdiff += adjust;
-			/*
-			 * If the firstblock forbids it, can't use it,
-			 * must use default.
-			 */
-			if (!rt && !nullfb &&
-			    XFS_FSB_TO_AGNO(mp, gotbno) != fb_agno)
-				gotbno = NULLFSBLOCK;
-		}
-		/*
-		 * No next block, just default.
-		 */
-		else
-			gotbno = NULLFSBLOCK;
-		/*
-		 * If both valid, pick the better one, else the only good
-		 * one, else ap->blkno is already set (to 0 or the inode block).
-		 */
-		if (prevbno != NULLFSBLOCK && gotbno != NULLFSBLOCK)
-			ap->blkno = prevdiff <= gotdiff ? prevbno : gotbno;
-		else if (prevbno != NULLFSBLOCK)
-			ap->blkno = prevbno;
-		else if (gotbno != NULLFSBLOCK)
-			ap->blkno = gotbno;
-	}
-#undef ISVALID
-}
-
-STATIC int
-xfs_bmap_rtalloc(
-	xfs_bmalloca_t	*ap)		/* bmap alloc argument struct */
+/*
+ * Check if the endoff is outside the last extent. If so the caller will grow
+ * the allocation to a stripe unit boundary.  All offsets are considered outside
+ * the end of file for an empty fork, so 1 is returned in *eof in that case.
+ */
+int
+xfs_bmap_eof(
+	struct xfs_inode	*ip,
+	xfs_fileoff_t		endoff,
+	int			whichfork,
+	int			*eof)
 {
-	xfs_alloctype_t	atype = 0;	/* type for allocation routines */
-	int		error;		/* error return value */
-	xfs_mount_t	*mp;		/* mount point structure */
-	xfs_extlen_t	prod = 0;	/* product factor for allocators */
-	xfs_extlen_t	ralen = 0;	/* realtime allocation length */
-	xfs_extlen_t	align;		/* minimum allocation alignment */
-	xfs_rtblock_t	rtb;
+	struct xfs_bmbt_irec	rec;
+	int			error;
 
-	mp = ap->ip->i_mount;
-	align = xfs_get_extsz_hint(ap->ip);
-	prod = align / mp->m_sb.sb_rextsize;
-	error = xfs_bmap_extsize_align(mp, &ap->got, &ap->prev,
-					align, 1, ap->eof, 0,
-					ap->conv, &ap->offset, &ap->length);
-	if (error)
+	error = xfs_bmap_last_extent(NULL, ip, whichfork, &rec, eof);
+	if (error || *eof)
 		return error;
-	ASSERT(ap->length);
-	ASSERT(ap->length % mp->m_sb.sb_rextsize == 0);
 
-	/*
-	 * If the offset & length are not perfectly aligned
-	 * then kill prod, it will just get us in trouble.
-	 */
-	if (do_mod(ap->offset, align) || ap->length % align)
-		prod = 1;
-	/*
-	 * Set ralen to be the actual requested length in rtextents.
-	 */
-	ralen = ap->length / mp->m_sb.sb_rextsize;
-	/*
-	 * If the old value was close enough to MAXEXTLEN that
-	 * we rounded up to it, cut it back so it's valid again.
-	 * Note that if it's a really large request (bigger than
-	 * MAXEXTLEN), we don't hear about that number, and can't
-	 * adjust the starting point to match it.
-	 */
-	if (ralen * mp->m_sb.sb_rextsize >= MAXEXTLEN)
-		ralen = MAXEXTLEN / mp->m_sb.sb_rextsize;
+	*eof = endoff >= rec.br_startoff + rec.br_blockcount;
+	return 0;
+}
 
-	/*
-	 * Lock out other modifications to the RT bitmap inode.
-	 */
-	xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL);
-	xfs_trans_ijoin(ap->tp, mp->m_rbmip, XFS_ILOCK_EXCL);
+/*
+ * Returns the file-relative block number of the first block past eof in
+ * the file.  This is not based on i_size, it is based on the extent records.
+ * Returns 0 for local files, as they do not have extent records.
+ */
+int
+xfs_bmap_last_offset(
+	struct xfs_trans	*tp,
+	struct xfs_inode	*ip,
+	xfs_fileoff_t		*last_block,
+	int			whichfork)
+{
+	struct xfs_bmbt_irec	rec;
+	int			is_empty;
+	int			error;
 
-	/*
-	 * If it's an allocation to an empty file at offset 0,
-	 * pick an extent that will space things out in the rt area.
-	 */
-	if (ap->eof && ap->offset == 0) {
-		xfs_rtblock_t uninitialized_var(rtx); /* realtime extent no */
+	*last_block = 0;
 
-		error = xfs_rtpick_extent(mp, ap->tp, ralen, &rtx);
-		if (error)
-			return error;
-		ap->blkno = rtx * mp->m_sb.sb_rextsize;
-	} else {
-		ap->blkno = 0;
-	}
+	if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL)
+		return 0;
 
-	xfs_bmap_adjacent(ap);
+	if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE &&
+	    XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS)
+	       return XFS_ERROR(EIO);
 
-	/*
-	 * Realtime allocation, done through xfs_rtallocate_extent.
-	 */
-	atype = ap->blkno == 0 ?  XFS_ALLOCTYPE_ANY_AG : XFS_ALLOCTYPE_NEAR_BNO;
-	do_div(ap->blkno, mp->m_sb.sb_rextsize);
-	rtb = ap->blkno;
-	ap->length = ralen;
-	if ((error = xfs_rtallocate_extent(ap->tp, ap->blkno, 1, ap->length,
-				&ralen, atype, ap->wasdel, prod, &rtb)))
-		return error;
-	if (rtb == NULLFSBLOCK && prod > 1 &&
-	    (error = xfs_rtallocate_extent(ap->tp, ap->blkno, 1,
-					   ap->length, &ralen, atype,
-					   ap->wasdel, 1, &rtb)))
+	error = xfs_bmap_last_extent(NULL, ip, whichfork, &rec, &is_empty);
+	if (error || is_empty)
 		return error;
-	ap->blkno = rtb;
-	if (ap->blkno != NULLFSBLOCK) {
-		ap->blkno *= mp->m_sb.sb_rextsize;
-		ralen *= mp->m_sb.sb_rextsize;
-		ap->length = ralen;
-		ap->ip->i_d.di_nblocks += ralen;
-		xfs_trans_log_inode(ap->tp, ap->ip, XFS_ILOG_CORE);
-		if (ap->wasdel)
-			ap->ip->i_delayed_blks -= ralen;
-		/*
-		 * Adjust the disk quota also. This was reserved
-		 * earlier.
-		 */
-		xfs_trans_mod_dquot_byino(ap->tp, ap->ip,
-			ap->wasdel ? XFS_TRANS_DQ_DELRTBCOUNT :
-					XFS_TRANS_DQ_RTBCOUNT, (long) ralen);
-	} else {
-		ap->length = 0;
-	}
+
+	*last_block = rec.br_startoff + rec.br_blockcount;
 	return 0;
 }
 
-STATIC int
-xfs_bmap_btalloc_nullfb(
-	struct xfs_bmalloca	*ap,
-	struct xfs_alloc_arg	*args,
-	xfs_extlen_t		*blen)
+/*
+ * Returns whether the selected fork of the inode has exactly one
+ * block or not.  For the data fork we check this matches di_size,
+ * implying the file's range is 0..bsize-1.
+ */
+int					/* 1=>1 block, 0=>otherwise */
+xfs_bmap_one_block(
+	xfs_inode_t	*ip,		/* incore inode */
+	int		whichfork)	/* data or attr fork */
 {
-	struct xfs_mount	*mp = ap->ip->i_mount;
-	struct xfs_perag	*pag;
-	xfs_agnumber_t		ag, startag;
-	int			notinit = 0;
-	int			error;
+	xfs_bmbt_rec_host_t *ep;	/* ptr to fork's extent */
+	xfs_ifork_t	*ifp;		/* inode fork pointer */
+	int		rval;		/* return value */
+	xfs_bmbt_irec_t	s;		/* internal version of extent */
 
-	if (ap->userdata && xfs_inode_is_filestream(ap->ip))
-		args->type = XFS_ALLOCTYPE_NEAR_BNO;
-	else
-		args->type = XFS_ALLOCTYPE_START_BNO;
-	args->total = ap->total;
+#ifndef DEBUG
+	if (whichfork == XFS_DATA_FORK)
+		return XFS_ISIZE(ip) == ip->i_mount->m_sb.sb_blocksize;
+#endif	/* !DEBUG */
+	if (XFS_IFORK_NEXTENTS(ip, whichfork) != 1)
+		return 0;
+	if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS)
+		return 0;
+	ifp = XFS_IFORK_PTR(ip, whichfork);
+	ASSERT(ifp->if_flags & XFS_IFEXTENTS);
+	ep = xfs_iext_get_ext(ifp, 0);
+	xfs_bmbt_get_all(ep, &s);
+	rval = s.br_startoff == 0 && s.br_blockcount == 1;
+	if (rval && whichfork == XFS_DATA_FORK)
+		ASSERT(XFS_ISIZE(ip) == ip->i_mount->m_sb.sb_blocksize);
+	return rval;
+}
 
-	/*
-	 * Search for an allocation group with a single extent large enough
-	 * for the request.  If one isn't found, then adjust the minimum
-	 * allocation size to the largest space found.
-	 */
-	startag = ag = XFS_FSB_TO_AGNO(mp, args->fsbno);
-	if (startag == NULLAGNUMBER)
-		startag = ag = 0;
+/*
+ * Extent tree manipulation functions used during allocation.
+ */
 
-	pag = xfs_perag_get(mp, ag);
-	while (*blen < args->maxlen) {
-		if (!pag->pagf_init) {
-			error = xfs_alloc_pagf_init(mp, args->tp, ag,
-						    XFS_ALLOC_FLAG_TRYLOCK);
-			if (error) {
-				xfs_perag_put(pag);
-				return error;
-			}
-		}
-
-		/*
-		 * See xfs_alloc_fix_freelist...
-		 */
-		if (pag->pagf_init) {
-			xfs_extlen_t	longest;
-			longest = xfs_alloc_longest_free_extent(mp, pag);
-			if (*blen < longest)
-				*blen = longest;
-		} else
-			notinit = 1;
+/*
+ * Convert a delayed allocation to a real allocation.
+ */
+STATIC int				/* error */
+xfs_bmap_add_extent_delay_real(
+	struct xfs_bmalloca	*bma)
+{
+	struct xfs_bmbt_irec	*new = &bma->got;
+	int			diff;	/* temp value */
+	xfs_bmbt_rec_host_t	*ep;	/* extent entry for idx */
+	int			error;	/* error return value */
+	int			i;	/* temp state */
+	xfs_ifork_t		*ifp;	/* inode fork pointer */
+	xfs_fileoff_t		new_endoff;	/* end offset of new entry */
+	xfs_bmbt_irec_t		r[3];	/* neighbor extent entries */
+					/* left is 0, right is 1, prev is 2 */
+	int			rval=0;	/* return value (logging flags) */
+	int			state = 0;/* state bits, accessed thru macros */
+	xfs_filblks_t		da_new; /* new count del alloc blocks used */
+	xfs_filblks_t		da_old; /* old count del alloc blocks used */
+	xfs_filblks_t		temp=0;	/* value for da_new calculations */
+	xfs_filblks_t		temp2=0;/* value for da_new calculations */
+	int			tmp_rval;	/* partial logging flags */
 
-		if (xfs_inode_is_filestream(ap->ip)) {
-			if (*blen >= args->maxlen)
-				break;
+	ifp = XFS_IFORK_PTR(bma->ip, XFS_DATA_FORK);
 
-			if (ap->userdata) {
-				/*
-				 * If startag is an invalid AG, we've
-				 * come here once before and
-				 * xfs_filestream_new_ag picked the
-				 * best currently available.
-				 *
-				 * Don't continue looping, since we
-				 * could loop forever.
-				 */
-				if (startag == NULLAGNUMBER)
-					break;
+	ASSERT(bma->idx >= 0);
+	ASSERT(bma->idx <= ifp->if_bytes / sizeof(struct xfs_bmbt_rec));
+	ASSERT(!isnullstartblock(new->br_startblock));
+	ASSERT(!bma->cur ||
+	       (bma->cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL));
 
-				error = xfs_filestream_new_ag(ap, &ag);
-				xfs_perag_put(pag);
-				if (error)
-					return error;
+	XFS_STATS_INC(xs_add_exlist);
 
-				/* loop again to set 'blen'*/
-				startag = NULLAGNUMBER;
-				pag = xfs_perag_get(mp, ag);
-				continue;
-			}
-		}
-		if (++ag == mp->m_sb.sb_agcount)
-			ag = 0;
-		if (ag == startag)
-			break;
-		xfs_perag_put(pag);
-		pag = xfs_perag_get(mp, ag);
-	}
-	xfs_perag_put(pag);
+#define	LEFT		r[0]
+#define	RIGHT		r[1]
+#define	PREV		r[2]
 
 	/*
-	 * Since the above loop did a BUF_TRYLOCK, it is
-	 * possible that there is space for this request.
-	 */
-	if (notinit || *blen < ap->minlen)
-		args->minlen = ap->minlen;
-	/*
-	 * If the best seen length is less than the request
-	 * length, use the best as the minimum.
+	 * Set up a bunch of variables to make the tests simpler.
 	 */
-	else if (*blen < args->maxlen)
-		args->minlen = *blen;
+	ep = xfs_iext_get_ext(ifp, bma->idx);
+	xfs_bmbt_get_all(ep, &PREV);
+	new_endoff = new->br_startoff + new->br_blockcount;
+	ASSERT(PREV.br_startoff <= new->br_startoff);
+	ASSERT(PREV.br_startoff + PREV.br_blockcount >= new_endoff);
+
+	da_old = startblockval(PREV.br_startblock);
+	da_new = 0;
+
 	/*
-	 * Otherwise we've seen an extent as big as maxlen,
-	 * use that as the minimum.
+	 * Set flags determining what part of the previous delayed allocation
+	 * extent is being replaced by a real allocation.
 	 */
-	else
-		args->minlen = args->maxlen;
+	if (PREV.br_startoff == new->br_startoff)
+		state |= BMAP_LEFT_FILLING;
+	if (PREV.br_startoff + PREV.br_blockcount == new_endoff)
+		state |= BMAP_RIGHT_FILLING;
 
 	/*
-	 * set the failure fallback case to look in the selected
-	 * AG as the stream may have moved.
+	 * Check and set flags if this segment has a left neighbor.
+	 * Don't set contiguous if the combined extent would be too large.
 	 */
-	if (xfs_inode_is_filestream(ap->ip))
-		ap->blkno = args->fsbno = XFS_AGB_TO_FSB(mp, ag, 0);
-
-	return 0;
-}
-
-STATIC int
-xfs_bmap_btalloc(
-	xfs_bmalloca_t	*ap)		/* bmap alloc argument struct */
-{
-	xfs_mount_t	*mp;		/* mount point structure */
-	xfs_alloctype_t	atype = 0;	/* type for allocation routines */
-	xfs_extlen_t	align;		/* minimum allocation alignment */
-	xfs_agnumber_t	fb_agno;	/* ag number of ap->firstblock */
-	xfs_agnumber_t	ag;
-	xfs_alloc_arg_t	args;
-	xfs_extlen_t	blen;
-	xfs_extlen_t	nextminlen = 0;
-	int		nullfb;		/* true if ap->firstblock isn't set */
-	int		isaligned;
-	int		tryagain;
-	int		error;
-
-	ASSERT(ap->length);
+	if (bma->idx > 0) {
+		state |= BMAP_LEFT_VALID;
+		xfs_bmbt_get_all(xfs_iext_get_ext(ifp, bma->idx - 1), &LEFT);
 
-	mp = ap->ip->i_mount;
-	align = ap->userdata ? xfs_get_extsz_hint(ap->ip) : 0;
-	if (unlikely(align)) {
-		error = xfs_bmap_extsize_align(mp, &ap->got, &ap->prev,
-						align, 0, ap->eof, 0, ap->conv,
-						&ap->offset, &ap->length);
-		ASSERT(!error);
-		ASSERT(ap->length);
+		if (isnullstartblock(LEFT.br_startblock))
+			state |= BMAP_LEFT_DELAY;
 	}
-	nullfb = *ap->firstblock == NULLFSBLOCK;
-	fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, *ap->firstblock);
-	if (nullfb) {
-		if (ap->userdata && xfs_inode_is_filestream(ap->ip)) {
-			ag = xfs_filestream_lookup_ag(ap->ip);
-			ag = (ag != NULLAGNUMBER) ? ag : 0;
-			ap->blkno = XFS_AGB_TO_FSB(mp, ag, 0);
-		} else {
-			ap->blkno = XFS_INO_TO_FSB(mp, ap->ip->i_ino);
-		}
-	} else
-		ap->blkno = *ap->firstblock;
 
-	xfs_bmap_adjacent(ap);
+	if ((state & BMAP_LEFT_VALID) && !(state & BMAP_LEFT_DELAY) &&
+	    LEFT.br_startoff + LEFT.br_blockcount == new->br_startoff &&
+	    LEFT.br_startblock + LEFT.br_blockcount == new->br_startblock &&
+	    LEFT.br_state == new->br_state &&
+	    LEFT.br_blockcount + new->br_blockcount <= MAXEXTLEN)
+		state |= BMAP_LEFT_CONTIG;
 
 	/*
-	 * If allowed, use ap->blkno; otherwise must use firstblock since
-	 * it's in the right allocation group.
-	 */
-	if (nullfb || XFS_FSB_TO_AGNO(mp, ap->blkno) == fb_agno)
-		;
-	else
-		ap->blkno = *ap->firstblock;
-	/*
-	 * Normal allocation, done through xfs_alloc_vextent.
+	 * Check and set flags if this segment has a right neighbor.
+	 * Don't set contiguous if the combined extent would be too large.
+	 * Also check for all-three-contiguous being too large.
 	 */
-	tryagain = isaligned = 0;
-	memset(&args, 0, sizeof(args));
-	args.tp = ap->tp;
-	args.mp = mp;
-	args.fsbno = ap->blkno;
+	if (bma->idx < bma->ip->i_df.if_bytes / (uint)sizeof(xfs_bmbt_rec_t) - 1) {
+		state |= BMAP_RIGHT_VALID;
+		xfs_bmbt_get_all(xfs_iext_get_ext(ifp, bma->idx + 1), &RIGHT);
 
-	/* Trim the allocation back to the maximum an AG can fit. */
-	args.maxlen = MIN(ap->length, XFS_ALLOC_AG_MAX_USABLE(mp));
-	args.firstblock = *ap->firstblock;
-	blen = 0;
-	if (nullfb) {
-		error = xfs_bmap_btalloc_nullfb(ap, &args, &blen);
-		if (error)
-			return error;
-	} else if (ap->flist->xbf_low) {
-		if (xfs_inode_is_filestream(ap->ip))
-			args.type = XFS_ALLOCTYPE_FIRST_AG;
-		else
-			args.type = XFS_ALLOCTYPE_START_BNO;
-		args.total = args.minlen = ap->minlen;
-	} else {
-		args.type = XFS_ALLOCTYPE_NEAR_BNO;
-		args.total = ap->total;
-		args.minlen = ap->minlen;
-	}
-	/* apply extent size hints if obtained earlier */
-	if (unlikely(align)) {
-		args.prod = align;
-		if ((args.mod = (xfs_extlen_t)do_mod(ap->offset, args.prod)))
-			args.mod = (xfs_extlen_t)(args.prod - args.mod);
-	} else if (mp->m_sb.sb_blocksize >= PAGE_CACHE_SIZE) {
-		args.prod = 1;
-		args.mod = 0;
-	} else {
-		args.prod = PAGE_CACHE_SIZE >> mp->m_sb.sb_blocklog;
-		if ((args.mod = (xfs_extlen_t)(do_mod(ap->offset, args.prod))))
-			args.mod = (xfs_extlen_t)(args.prod - args.mod);
+		if (isnullstartblock(RIGHT.br_startblock))
+			state |= BMAP_RIGHT_DELAY;
 	}
+
+	if ((state & BMAP_RIGHT_VALID) && !(state & BMAP_RIGHT_DELAY) &&
+	    new_endoff == RIGHT.br_startoff &&
+	    new->br_startblock + new->br_blockcount == RIGHT.br_startblock &&
+	    new->br_state == RIGHT.br_state &&
+	    new->br_blockcount + RIGHT.br_blockcount <= MAXEXTLEN &&
+	    ((state & (BMAP_LEFT_CONTIG | BMAP_LEFT_FILLING |
+		       BMAP_RIGHT_FILLING)) !=
+		      (BMAP_LEFT_CONTIG | BMAP_LEFT_FILLING |
+		       BMAP_RIGHT_FILLING) ||
+	     LEFT.br_blockcount + new->br_blockcount + RIGHT.br_blockcount
+			<= MAXEXTLEN))
+		state |= BMAP_RIGHT_CONTIG;
+
+	error = 0;
 	/*
-	 * If we are not low on available data blocks, and the
-	 * underlying logical volume manager is a stripe, and
-	 * the file offset is zero then try to allocate data
-	 * blocks on stripe unit boundary.
-	 * NOTE: ap->aeof is only set if the allocation length
-	 * is >= the stripe unit and the allocation offset is
-	 * at the end of file.
+	 * Switch out based on the FILLING and CONTIG state bits.
 	 */
-	if (!ap->flist->xbf_low && ap->aeof) {
-		if (!ap->offset) {
-			args.alignment = mp->m_dalign;
-			atype = args.type;
-			isaligned = 1;
-			/*
-			 * Adjust for alignment
-			 */
-			if (blen > args.alignment && blen <= args.maxlen)
-				args.minlen = blen - args.alignment;
-			args.minalignslop = 0;
-		} else {
-			/*
-			 * First try an exact bno allocation.
-			 * If it fails then do a near or start bno
-			 * allocation with alignment turned on.
-			 */
-			atype = args.type;
-			tryagain = 1;
-			args.type = XFS_ALLOCTYPE_THIS_BNO;
-			args.alignment = 1;
-			/*
-			 * Compute the minlen+alignment for the
-			 * next case.  Set slop so that the value
-			 * of minlen+alignment+slop doesn't go up
-			 * between the calls.
-			 */
-			if (blen > mp->m_dalign && blen <= args.maxlen)
-				nextminlen = blen - mp->m_dalign;
-			else
-				nextminlen = args.minlen;
-			if (nextminlen + mp->m_dalign > args.minlen + 1)
-				args.minalignslop =
-					nextminlen + mp->m_dalign -
-					args.minlen - 1;
-			else
-				args.minalignslop = 0;
-		}
-	} else {
-		args.alignment = 1;
-		args.minalignslop = 0;
-	}
-	args.minleft = ap->minleft;
-	args.wasdel = ap->wasdel;
-	args.isfl = 0;
-	args.userdata = ap->userdata;
-	if ((error = xfs_alloc_vextent(&args)))
-		return error;
-	if (tryagain && args.fsbno == NULLFSBLOCK) {
+	switch (state & (BMAP_LEFT_FILLING | BMAP_LEFT_CONTIG |
+			 BMAP_RIGHT_FILLING | BMAP_RIGHT_CONTIG)) {
+	case BMAP_LEFT_FILLING | BMAP_LEFT_CONTIG |
+	     BMAP_RIGHT_FILLING | BMAP_RIGHT_CONTIG:
 		/*
-		 * Exact allocation failed. Now try with alignment
-		 * turned on.
+		 * Filling in all of a previously delayed allocation extent.
+		 * The left and right neighbors are both contiguous with new.
 		 */
-		args.type = atype;
-		args.fsbno = ap->blkno;
-		args.alignment = mp->m_dalign;
-		args.minlen = nextminlen;
-		args.minalignslop = 0;
-		isaligned = 1;
-		if ((error = xfs_alloc_vextent(&args)))
-			return error;
-	}
-	if (isaligned && args.fsbno == NULLFSBLOCK) {
+		bma->idx--;
+		trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_);
+		xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, bma->idx),
+			LEFT.br_blockcount + PREV.br_blockcount +
+			RIGHT.br_blockcount);
+		trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_);
+
+		xfs_iext_remove(bma->ip, bma->idx + 1, 2, state);
+		bma->ip->i_d.di_nextents--;
+		if (bma->cur == NULL)
+			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
+		else {
+			rval = XFS_ILOG_CORE;
+			error = xfs_bmbt_lookup_eq(bma->cur, RIGHT.br_startoff,
+					RIGHT.br_startblock,
+					RIGHT.br_blockcount, &i);
+			if (error)
+				goto done;
+			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+			error = xfs_btree_delete(bma->cur, &i);
+			if (error)
+				goto done;
+			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+			error = xfs_btree_decrement(bma->cur, 0, &i);
+			if (error)
+				goto done;
+			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+			error = xfs_bmbt_update(bma->cur, LEFT.br_startoff,
+					LEFT.br_startblock,
+					LEFT.br_blockcount +
+					PREV.br_blockcount +
+					RIGHT.br_blockcount, LEFT.br_state);
+			if (error)
+				goto done;
+		}
+		break;
+
+	case BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING | BMAP_LEFT_CONTIG:
 		/*
-		 * allocation failed, so turn off alignment and
-		 * try again.
+		 * Filling in all of a previously delayed allocation extent.
+		 * The left neighbor is contiguous, the right is not.
 		 */
-		args.type = atype;
-		args.fsbno = ap->blkno;
-		args.alignment = 0;
-		if ((error = xfs_alloc_vextent(&args)))
-			return error;
-	}
-	if (args.fsbno == NULLFSBLOCK && nullfb &&
-	    args.minlen > ap->minlen) {
-		args.minlen = ap->minlen;
-		args.type = XFS_ALLOCTYPE_START_BNO;
-		args.fsbno = ap->blkno;
-		if ((error = xfs_alloc_vextent(&args)))
-			return error;
-	}
-	if (args.fsbno == NULLFSBLOCK && nullfb) {
-		args.fsbno = 0;
-		args.type = XFS_ALLOCTYPE_FIRST_AG;
-		args.total = ap->minlen;
-		args.minleft = 0;
-		if ((error = xfs_alloc_vextent(&args)))
-			return error;
-		ap->flist->xbf_low = 1;
-	}
-	if (args.fsbno != NULLFSBLOCK) {
+		bma->idx--;
+
+		trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_);
+		xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, bma->idx),
+			LEFT.br_blockcount + PREV.br_blockcount);
+		trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_);
+
+		xfs_iext_remove(bma->ip, bma->idx + 1, 1, state);
+		if (bma->cur == NULL)
+			rval = XFS_ILOG_DEXT;
+		else {
+			rval = 0;
+			error = xfs_bmbt_lookup_eq(bma->cur, LEFT.br_startoff,
+					LEFT.br_startblock, LEFT.br_blockcount,
+					&i);
+			if (error)
+				goto done;
+			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+			error = xfs_bmbt_update(bma->cur, LEFT.br_startoff,
+					LEFT.br_startblock,
+					LEFT.br_blockcount +
+					PREV.br_blockcount, LEFT.br_state);
+			if (error)
+				goto done;
+		}
+		break;
+
+	case BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING | BMAP_RIGHT_CONTIG:
 		/*
-		 * check the allocation happened at the same or higher AG than
-		 * the first block that was allocated.
+		 * Filling in all of a previously delayed allocation extent.
+		 * The right neighbor is contiguous, the left is not.
 		 */
-		ASSERT(*ap->firstblock == NULLFSBLOCK ||
-		       XFS_FSB_TO_AGNO(mp, *ap->firstblock) ==
-		       XFS_FSB_TO_AGNO(mp, args.fsbno) ||
-		       (ap->flist->xbf_low &&
-			XFS_FSB_TO_AGNO(mp, *ap->firstblock) <
-			XFS_FSB_TO_AGNO(mp, args.fsbno)));
+		trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_);
+		xfs_bmbt_set_startblock(ep, new->br_startblock);
+		xfs_bmbt_set_blockcount(ep,
+			PREV.br_blockcount + RIGHT.br_blockcount);
+		trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_);
 
-		ap->blkno = args.fsbno;
-		if (*ap->firstblock == NULLFSBLOCK)
-			*ap->firstblock = args.fsbno;
-		ASSERT(nullfb || fb_agno == args.agno ||
-		       (ap->flist->xbf_low && fb_agno < args.agno));
-		ap->length = args.len;
-		ap->ip->i_d.di_nblocks += args.len;
-		xfs_trans_log_inode(ap->tp, ap->ip, XFS_ILOG_CORE);
-		if (ap->wasdel)
-			ap->ip->i_delayed_blks -= args.len;
+		xfs_iext_remove(bma->ip, bma->idx + 1, 1, state);
+		if (bma->cur == NULL)
+			rval = XFS_ILOG_DEXT;
+		else {
+			rval = 0;
+			error = xfs_bmbt_lookup_eq(bma->cur, RIGHT.br_startoff,
+					RIGHT.br_startblock,
+					RIGHT.br_blockcount, &i);
+			if (error)
+				goto done;
+			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+			error = xfs_bmbt_update(bma->cur, PREV.br_startoff,
+					new->br_startblock,
+					PREV.br_blockcount +
+					RIGHT.br_blockcount, PREV.br_state);
+			if (error)
+				goto done;
+		}
+		break;
+
+	case BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING:
 		/*
-		 * Adjust the disk quota also. This was reserved
-		 * earlier.
+		 * Filling in all of a previously delayed allocation extent.
+		 * Neither the left nor right neighbors are contiguous with
+		 * the new one.
 		 */
-		xfs_trans_mod_dquot_byino(ap->tp, ap->ip,
-			ap->wasdel ? XFS_TRANS_DQ_DELBCOUNT :
-					XFS_TRANS_DQ_BCOUNT,
-			(long) args.len);
-	} else {
-		ap->blkno = NULLFSBLOCK;
-		ap->length = 0;
-	}
-	return 0;
-}
+		trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_);
+		xfs_bmbt_set_startblock(ep, new->br_startblock);
+		trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_);
 
-/*
- * xfs_bmap_alloc is called by xfs_bmapi to allocate an extent for a file.
- * It figures out where to ask the underlying allocator to put the new extent.
- */
-STATIC int
-xfs_bmap_alloc(
-	xfs_bmalloca_t	*ap)		/* bmap alloc argument struct */
-{
-	if (XFS_IS_REALTIME_INODE(ap->ip) && ap->userdata)
-		return xfs_bmap_rtalloc(ap);
-	return xfs_bmap_btalloc(ap);
-}
+		bma->ip->i_d.di_nextents++;
+		if (bma->cur == NULL)
+			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
+		else {
+			rval = XFS_ILOG_CORE;
+			error = xfs_bmbt_lookup_eq(bma->cur, new->br_startoff,
+					new->br_startblock, new->br_blockcount,
+					&i);
+			if (error)
+				goto done;
+			XFS_WANT_CORRUPTED_GOTO(i == 0, done);
+			bma->cur->bc_rec.b.br_state = XFS_EXT_NORM;
+			error = xfs_btree_insert(bma->cur, &i);
+			if (error)
+				goto done;
+			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+		}
+		break;
 
-/*
- * Transform a btree format file with only one leaf node, where the
- * extents list will fit in the inode, into an extents format file.
- * Since the file extents are already in-core, all we have to do is
- * give up the space for the btree root and pitch the leaf block.
- */
-STATIC int				/* error */
-xfs_bmap_btree_to_extents(
-	xfs_trans_t		*tp,	/* transaction pointer */
-	xfs_inode_t		*ip,	/* incore inode pointer */
-	xfs_btree_cur_t		*cur,	/* btree cursor */
-	int			*logflagsp, /* inode logging flags */
-	int			whichfork)  /* data or attr fork */
-{
-	/* REFERENCED */
-	struct xfs_btree_block	*cblock;/* child btree block */
-	xfs_fsblock_t		cbno;	/* child block number */
-	xfs_buf_t		*cbp;	/* child block's buffer */
-	int			error;	/* error return value */
-	xfs_ifork_t		*ifp;	/* inode fork data */
-	xfs_mount_t		*mp;	/* mount point structure */
-	__be64			*pp;	/* ptr to block address */
-	struct xfs_btree_block	*rblock;/* root btree block */
-
-	mp = ip->i_mount;
-	ifp = XFS_IFORK_PTR(ip, whichfork);
-	ASSERT(ifp->if_flags & XFS_IFEXTENTS);
-	ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE);
-	rblock = ifp->if_broot;
-	ASSERT(be16_to_cpu(rblock->bb_level) == 1);
-	ASSERT(be16_to_cpu(rblock->bb_numrecs) == 1);
-	ASSERT(xfs_bmbt_maxrecs(mp, ifp->if_broot_bytes, 0) == 1);
-	pp = XFS_BMAP_BROOT_PTR_ADDR(mp, rblock, 1, ifp->if_broot_bytes);
-	cbno = be64_to_cpu(*pp);
-	*logflagsp = 0;
-#ifdef DEBUG
-	if ((error = xfs_btree_check_lptr(cur, cbno, 1)))
-		return error;
-#endif
-	error = xfs_btree_read_bufl(mp, tp, cbno, 0, &cbp, XFS_BMAP_BTREE_REF,
-				&xfs_bmbt_buf_ops);
-	if (error)
-		return error;
-	cblock = XFS_BUF_TO_BLOCK(cbp);
-	if ((error = xfs_btree_check_block(cur, cblock, 0, cbp)))
-		return error;
-	xfs_bmap_add_free(cbno, 1, cur->bc_private.b.flist, mp);
-	ip->i_d.di_nblocks--;
-	xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, -1L);
-	xfs_trans_binval(tp, cbp);
-	if (cur->bc_bufs[0] == cbp)
-		cur->bc_bufs[0] = NULL;
-	xfs_iroot_realloc(ip, -1, whichfork);
-	ASSERT(ifp->if_broot == NULL);
-	ASSERT((ifp->if_flags & XFS_IFBROOT) == 0);
-	XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_EXTENTS);
-	*logflagsp = XFS_ILOG_CORE | xfs_ilog_fext(whichfork);
-	return 0;
-}
-
-/*
- * Called by xfs_bmapi to update file extent records and the btree
- * after removing space (or undoing a delayed allocation).
- */
-STATIC int				/* error */
-xfs_bmap_del_extent(
-	xfs_inode_t		*ip,	/* incore inode pointer */
-	xfs_trans_t		*tp,	/* current transaction pointer */
-	xfs_extnum_t		*idx,	/* extent number to update/delete */
-	xfs_bmap_free_t		*flist,	/* list of extents to be freed */
-	xfs_btree_cur_t		*cur,	/* if null, not a btree */
-	xfs_bmbt_irec_t		*del,	/* data to remove from extents */
-	int			*logflagsp, /* inode logging flags */
-	int			whichfork) /* data or attr fork */
-{
-	xfs_filblks_t		da_new;	/* new delay-alloc indirect blocks */
-	xfs_filblks_t		da_old;	/* old delay-alloc indirect blocks */
-	xfs_fsblock_t		del_endblock=0;	/* first block past del */
-	xfs_fileoff_t		del_endoff;	/* first offset past del */
-	int			delay;	/* current block is delayed allocated */
-	int			do_fx;	/* free extent at end of routine */
-	xfs_bmbt_rec_host_t	*ep;	/* current extent entry pointer */
-	int			error;	/* error return value */
-	int			flags;	/* inode logging flags */
-	xfs_bmbt_irec_t		got;	/* current extent entry */
-	xfs_fileoff_t		got_endoff;	/* first offset past got */
-	int			i;	/* temp state */
-	xfs_ifork_t		*ifp;	/* inode fork pointer */
-	xfs_mount_t		*mp;	/* mount structure */
-	xfs_filblks_t		nblks;	/* quota/sb block count */
-	xfs_bmbt_irec_t		new;	/* new record to be inserted */
-	/* REFERENCED */
-	uint			qfield;	/* quota field to update */
-	xfs_filblks_t		temp;	/* for indirect length calculations */
-	xfs_filblks_t		temp2;	/* for indirect length calculations */
-	int			state = 0;
-
-	XFS_STATS_INC(xs_del_exlist);
-
-	if (whichfork == XFS_ATTR_FORK)
-		state |= BMAP_ATTRFORK;
-
-	mp = ip->i_mount;
-	ifp = XFS_IFORK_PTR(ip, whichfork);
-	ASSERT((*idx >= 0) && (*idx < ifp->if_bytes /
-		(uint)sizeof(xfs_bmbt_rec_t)));
-	ASSERT(del->br_blockcount > 0);
-	ep = xfs_iext_get_ext(ifp, *idx);
-	xfs_bmbt_get_all(ep, &got);
-	ASSERT(got.br_startoff <= del->br_startoff);
-	del_endoff = del->br_startoff + del->br_blockcount;
-	got_endoff = got.br_startoff + got.br_blockcount;
-	ASSERT(got_endoff >= del_endoff);
-	delay = isnullstartblock(got.br_startblock);
-	ASSERT(isnullstartblock(del->br_startblock) == delay);
-	flags = 0;
-	qfield = 0;
-	error = 0;
-	/*
-	 * If deleting a real allocation, must free up the disk space.
-	 */
-	if (!delay) {
-		flags = XFS_ILOG_CORE;
+	case BMAP_LEFT_FILLING | BMAP_LEFT_CONTIG:
 		/*
-		 * Realtime allocation.  Free it and record di_nblocks update.
+		 * Filling in the first part of a previous delayed allocation.
+		 * The left neighbor is contiguous.
 		 */
-		if (whichfork == XFS_DATA_FORK && XFS_IS_REALTIME_INODE(ip)) {
-			xfs_fsblock_t	bno;
-			xfs_filblks_t	len;
+		trace_xfs_bmap_pre_update(bma->ip, bma->idx - 1, state, _THIS_IP_);
+		xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, bma->idx - 1),
+			LEFT.br_blockcount + new->br_blockcount);
+		xfs_bmbt_set_startoff(ep,
+			PREV.br_startoff + new->br_blockcount);
+		trace_xfs_bmap_post_update(bma->ip, bma->idx - 1, state, _THIS_IP_);
 
-			ASSERT(do_mod(del->br_blockcount,
-				      mp->m_sb.sb_rextsize) == 0);
-			ASSERT(do_mod(del->br_startblock,
-				      mp->m_sb.sb_rextsize) == 0);
-			bno = del->br_startblock;
-			len = del->br_blockcount;
-			do_div(bno, mp->m_sb.sb_rextsize);
-			do_div(len, mp->m_sb.sb_rextsize);
-			error = xfs_rtfree_extent(tp, bno, (xfs_extlen_t)len);
+		temp = PREV.br_blockcount - new->br_blockcount;
+		trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_);
+		xfs_bmbt_set_blockcount(ep, temp);
+		if (bma->cur == NULL)
+			rval = XFS_ILOG_DEXT;
+		else {
+			rval = 0;
+			error = xfs_bmbt_lookup_eq(bma->cur, LEFT.br_startoff,
+					LEFT.br_startblock, LEFT.br_blockcount,
+					&i);
+			if (error)
+				goto done;
+			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+			error = xfs_bmbt_update(bma->cur, LEFT.br_startoff,
+					LEFT.br_startblock,
+					LEFT.br_blockcount +
+					new->br_blockcount,
+					LEFT.br_state);
 			if (error)
 				goto done;
-			do_fx = 0;
-			nblks = len * mp->m_sb.sb_rextsize;
-			qfield = XFS_TRANS_DQ_RTBCOUNT;
 		}
+		da_new = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(bma->ip, temp),
+			startblockval(PREV.br_startblock));
+		xfs_bmbt_set_startblock(ep, nullstartblock(da_new));
+		trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_);
+
+		bma->idx--;
+		break;
+
+	case BMAP_LEFT_FILLING:
 		/*
-		 * Ordinary allocation.
+		 * Filling in the first part of a previous delayed allocation.
+		 * The left neighbor is not contiguous.
 		 */
+		trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_);
+		xfs_bmbt_set_startoff(ep, new_endoff);
+		temp = PREV.br_blockcount - new->br_blockcount;
+		xfs_bmbt_set_blockcount(ep, temp);
+		xfs_iext_insert(bma->ip, bma->idx, 1, new, state);
+		bma->ip->i_d.di_nextents++;
+		if (bma->cur == NULL)
+			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
 		else {
-			do_fx = 1;
-			nblks = del->br_blockcount;
-			qfield = XFS_TRANS_DQ_BCOUNT;
-		}
-		/*
-		 * Set up del_endblock and cur for later.
-		 */
-		del_endblock = del->br_startblock + del->br_blockcount;
-		if (cur) {
-			if ((error = xfs_bmbt_lookup_eq(cur, got.br_startoff,
-					got.br_startblock, got.br_blockcount,
-					&i)))
+			rval = XFS_ILOG_CORE;
+			error = xfs_bmbt_lookup_eq(bma->cur, new->br_startoff,
+					new->br_startblock, new->br_blockcount,
+					&i);
+			if (error)
+				goto done;
+			XFS_WANT_CORRUPTED_GOTO(i == 0, done);
+			bma->cur->bc_rec.b.br_state = XFS_EXT_NORM;
+			error = xfs_btree_insert(bma->cur, &i);
+			if (error)
 				goto done;
 			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
 		}
-		da_old = da_new = 0;
-	} else {
-		da_old = startblockval(got.br_startblock);
-		da_new = 0;
-		nblks = 0;
-		do_fx = 0;
-	}
-	/*
-	 * Set flag value to use in switch statement.
-	 * Left-contig is 2, right-contig is 1.
-	 */
-	switch (((got.br_startoff == del->br_startoff) << 1) |
-		(got_endoff == del_endoff)) {
-	case 3:
-		/*
-		 * Matches the whole extent.  Delete the entry.
-		 */
-		xfs_iext_remove(ip, *idx, 1,
-				whichfork == XFS_ATTR_FORK ? BMAP_ATTRFORK : 0);
-		--*idx;
-		if (delay)
-			break;
 
-		XFS_IFORK_NEXT_SET(ip, whichfork,
-			XFS_IFORK_NEXTENTS(ip, whichfork) - 1);
-		flags |= XFS_ILOG_CORE;
-		if (!cur) {
-			flags |= xfs_ilog_fext(whichfork);
-			break;
+		if (xfs_bmap_needs_btree(bma->ip, XFS_DATA_FORK)) {
+			error = xfs_bmap_extents_to_btree(bma->tp, bma->ip,
+					bma->firstblock, bma->flist,
+					&bma->cur, 1, &tmp_rval, XFS_DATA_FORK);
+			rval |= tmp_rval;
+			if (error)
+				goto done;
 		}
-		if ((error = xfs_btree_delete(cur, &i)))
-			goto done;
-		XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+		da_new = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(bma->ip, temp),
+			startblockval(PREV.br_startblock) -
+			(bma->cur ? bma->cur->bc_private.b.allocated : 0));
+		ep = xfs_iext_get_ext(ifp, bma->idx + 1);
+		xfs_bmbt_set_startblock(ep, nullstartblock(da_new));
+		trace_xfs_bmap_post_update(bma->ip, bma->idx + 1, state, _THIS_IP_);
 		break;
 
-	case 2:
+	case BMAP_RIGHT_FILLING | BMAP_RIGHT_CONTIG:
 		/*
-		 * Deleting the first part of the extent.
+		 * Filling in the last part of a previous delayed allocation.
+		 * The right neighbor is contiguous with the new allocation.
 		 */
-		trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_);
-		xfs_bmbt_set_startoff(ep, del_endoff);
-		temp = got.br_blockcount - del->br_blockcount;
+		temp = PREV.br_blockcount - new->br_blockcount;
+		trace_xfs_bmap_pre_update(bma->ip, bma->idx + 1, state, _THIS_IP_);
 		xfs_bmbt_set_blockcount(ep, temp);
-		if (delay) {
-			temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp),
-				da_old);
-			xfs_bmbt_set_startblock(ep, nullstartblock((int)temp));
-			trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_);
-			da_new = temp;
-			break;
-		}
-		xfs_bmbt_set_startblock(ep, del_endblock);
-		trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_);
-		if (!cur) {
-			flags |= xfs_ilog_fext(whichfork);
-			break;
+		xfs_bmbt_set_allf(xfs_iext_get_ext(ifp, bma->idx + 1),
+			new->br_startoff, new->br_startblock,
+			new->br_blockcount + RIGHT.br_blockcount,
+			RIGHT.br_state);
+		trace_xfs_bmap_post_update(bma->ip, bma->idx + 1, state, _THIS_IP_);
+		if (bma->cur == NULL)
+			rval = XFS_ILOG_DEXT;
+		else {
+			rval = 0;
+			error = xfs_bmbt_lookup_eq(bma->cur, RIGHT.br_startoff,
+					RIGHT.br_startblock,
+					RIGHT.br_blockcount, &i);
+			if (error)
+				goto done;
+			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+			error = xfs_bmbt_update(bma->cur, new->br_startoff,
+					new->br_startblock,
+					new->br_blockcount +
+					RIGHT.br_blockcount,
+					RIGHT.br_state);
+			if (error)
+				goto done;
 		}
-		if ((error = xfs_bmbt_update(cur, del_endoff, del_endblock,
-				got.br_blockcount - del->br_blockcount,
-				got.br_state)))
-			goto done;
+
+		da_new = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(bma->ip, temp),
+			startblockval(PREV.br_startblock));
+		trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_);
+		xfs_bmbt_set_startblock(ep, nullstartblock(da_new));
+		trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_);
+
+		bma->idx++;
 		break;
 
-	case 1:
+	case BMAP_RIGHT_FILLING:
 		/*
-		 * Deleting the last part of the extent.
+		 * Filling in the last part of a previous delayed allocation.
+		 * The right neighbor is not contiguous.
 		 */
-		temp = got.br_blockcount - del->br_blockcount;
-		trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_);
+		temp = PREV.br_blockcount - new->br_blockcount;
+		trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_);
 		xfs_bmbt_set_blockcount(ep, temp);
-		if (delay) {
-			temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp),
-				da_old);
-			xfs_bmbt_set_startblock(ep, nullstartblock((int)temp));
-			trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_);
-			da_new = temp;
-			break;
+		xfs_iext_insert(bma->ip, bma->idx + 1, 1, new, state);
+		bma->ip->i_d.di_nextents++;
+		if (bma->cur == NULL)
+			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
+		else {
+			rval = XFS_ILOG_CORE;
+			error = xfs_bmbt_lookup_eq(bma->cur, new->br_startoff,
+					new->br_startblock, new->br_blockcount,
+					&i);
+			if (error)
+				goto done;
+			XFS_WANT_CORRUPTED_GOTO(i == 0, done);
+			bma->cur->bc_rec.b.br_state = XFS_EXT_NORM;
+			error = xfs_btree_insert(bma->cur, &i);
+			if (error)
+				goto done;
+			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
 		}
-		trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_);
-		if (!cur) {
-			flags |= xfs_ilog_fext(whichfork);
-			break;
+
+		if (xfs_bmap_needs_btree(bma->ip, XFS_DATA_FORK)) {
+			error = xfs_bmap_extents_to_btree(bma->tp, bma->ip,
+				bma->firstblock, bma->flist, &bma->cur, 1,
+				&tmp_rval, XFS_DATA_FORK);
+			rval |= tmp_rval;
+			if (error)
+				goto done;
 		}
-		if ((error = xfs_bmbt_update(cur, got.br_startoff,
-				got.br_startblock,
-				got.br_blockcount - del->br_blockcount,
-				got.br_state)))
-			goto done;
+		da_new = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(bma->ip, temp),
+			startblockval(PREV.br_startblock) -
+			(bma->cur ? bma->cur->bc_private.b.allocated : 0));
+		ep = xfs_iext_get_ext(ifp, bma->idx);
+		xfs_bmbt_set_startblock(ep, nullstartblock(da_new));
+		trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_);
+
+		bma->idx++;
 		break;
 
 	case 0:
 		/*
-		 * Deleting the middle of the extent.
+		 * Filling in the middle part of a previous delayed allocation.
+		 * Contiguity is impossible here.
+		 * This case is avoided almost all the time.
+		 *
+		 * We start with a delayed allocation:
+		 *
+		 * +ddddddddddddddddddddddddddddddddddddddddddddddddddddddd+
+		 *  PREV @ idx
+		 *
+	         * and we are allocating:
+		 *                     +rrrrrrrrrrrrrrrrr+
+		 *			      new
+		 *
+		 * and we set it up for insertion as:
+		 * +ddddddddddddddddddd+rrrrrrrrrrrrrrrrr+ddddddddddddddddd+
+		 *                            new
+		 *  PREV @ idx          LEFT              RIGHT
+		 *                      inserted at idx + 1
 		 */
-		temp = del->br_startoff - got.br_startoff;
-		trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_);
-		xfs_bmbt_set_blockcount(ep, temp);
-		new.br_startoff = del_endoff;
-		temp2 = got_endoff - del_endoff;
-		new.br_blockcount = temp2;
-		new.br_state = got.br_state;
-		if (!delay) {
-			new.br_startblock = del_endblock;
-			flags |= XFS_ILOG_CORE;
-			if (cur) {
-				if ((error = xfs_bmbt_update(cur,
-						got.br_startoff,
-						got.br_startblock, temp,
-						got.br_state)))
-					goto done;
-				if ((error = xfs_btree_increment(cur, 0, &i)))
-					goto done;
-				cur->bc_rec.b = new;
-				error = xfs_btree_insert(cur, &i);
-				if (error && error != ENOSPC)
-					goto done;
-				/*
-				 * If get no-space back from btree insert,
-				 * it tried a split, and we have a zero
-				 * block reservation.
-				 * Fix up our state and return the error.
-				 */
-				if (error == ENOSPC) {
-					/*
-					 * Reset the cursor, don't trust
-					 * it after any insert operation.
-					 */
-					if ((error = xfs_bmbt_lookup_eq(cur,
-							got.br_startoff,
-							got.br_startblock,
-							temp, &i)))
-						goto done;
-					XFS_WANT_CORRUPTED_GOTO(i == 1, done);
-					/*
-					 * Update the btree record back
-					 * to the original value.
-					 */
-					if ((error = xfs_bmbt_update(cur,
-							got.br_startoff,
-							got.br_startblock,
-							got.br_blockcount,
-							got.br_state)))
-						goto done;
-					/*
-					 * Reset the extent record back
-					 * to the original value.
-					 */
-					xfs_bmbt_set_blockcount(ep,
-						got.br_blockcount);
-					flags = 0;
-					error = XFS_ERROR(ENOSPC);
-					goto done;
-				}
-				XFS_WANT_CORRUPTED_GOTO(i == 1, done);
-			} else
-				flags |= xfs_ilog_fext(whichfork);
-			XFS_IFORK_NEXT_SET(ip, whichfork,
-				XFS_IFORK_NEXTENTS(ip, whichfork) + 1);
-		} else {
-			ASSERT(whichfork == XFS_DATA_FORK);
-			temp = xfs_bmap_worst_indlen(ip, temp);
-			xfs_bmbt_set_startblock(ep, nullstartblock((int)temp));
-			temp2 = xfs_bmap_worst_indlen(ip, temp2);
-			new.br_startblock = nullstartblock((int)temp2);
-			da_new = temp + temp2;
-			while (da_new > da_old) {
-				if (temp) {
-					temp--;
-					da_new--;
-					xfs_bmbt_set_startblock(ep,
-						nullstartblock((int)temp));
-				}
-				if (da_new == da_old)
-					break;
-				if (temp2) {
-					temp2--;
-					da_new--;
-					new.br_startblock =
-						nullstartblock((int)temp2);
-				}
-			}
+		temp = new->br_startoff - PREV.br_startoff;
+		temp2 = PREV.br_startoff + PREV.br_blockcount - new_endoff;
+		trace_xfs_bmap_pre_update(bma->ip, bma->idx, 0, _THIS_IP_);
+		xfs_bmbt_set_blockcount(ep, temp);	/* truncate PREV */
+		LEFT = *new;
+		RIGHT.br_state = PREV.br_state;
+		RIGHT.br_startblock = nullstartblock(
+				(int)xfs_bmap_worst_indlen(bma->ip, temp2));
+		RIGHT.br_startoff = new_endoff;
+		RIGHT.br_blockcount = temp2;
+		/* insert LEFT (r[0]) and RIGHT (r[1]) at the same time */
+		xfs_iext_insert(bma->ip, bma->idx + 1, 2, &LEFT, state);
+		bma->ip->i_d.di_nextents++;
+		if (bma->cur == NULL)
+			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
+		else {
+			rval = XFS_ILOG_CORE;
+			error = xfs_bmbt_lookup_eq(bma->cur, new->br_startoff,
+					new->br_startblock, new->br_blockcount,
+					&i);
+			if (error)
+				goto done;
+			XFS_WANT_CORRUPTED_GOTO(i == 0, done);
+			bma->cur->bc_rec.b.br_state = XFS_EXT_NORM;
+			error = xfs_btree_insert(bma->cur, &i);
+			if (error)
+				goto done;
+			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
 		}
-		trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_);
-		xfs_iext_insert(ip, *idx + 1, 1, &new, state);
-		++*idx;
-		break;
-	}
-	/*
-	 * If we need to, add to list of extents to delete.
-	 */
-	if (do_fx)
-		xfs_bmap_add_free(del->br_startblock, del->br_blockcount, flist,
-			mp);
-	/*
-	 * Adjust inode # blocks in the file.
-	 */
-	if (nblks)
-		ip->i_d.di_nblocks -= nblks;
-	/*
-	 * Adjust quota data.
-	 */
-	if (qfield)
-		xfs_trans_mod_dquot_byino(tp, ip, qfield, (long)-nblks);
 
-	/*
-	 * Account for change in delayed indirect blocks.
-	 * Nothing to do for disk quota accounting here.
-	 */
-	ASSERT(da_old >= da_new);
-	if (da_old > da_new) {
-		xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS,
-			(int64_t)(da_old - da_new), 0);
+		if (xfs_bmap_needs_btree(bma->ip, XFS_DATA_FORK)) {
+			error = xfs_bmap_extents_to_btree(bma->tp, bma->ip,
+					bma->firstblock, bma->flist, &bma->cur,
+					1, &tmp_rval, XFS_DATA_FORK);
+			rval |= tmp_rval;
+			if (error)
+				goto done;
+		}
+		temp = xfs_bmap_worst_indlen(bma->ip, temp);
+		temp2 = xfs_bmap_worst_indlen(bma->ip, temp2);
+		diff = (int)(temp + temp2 - startblockval(PREV.br_startblock) -
+			(bma->cur ? bma->cur->bc_private.b.allocated : 0));
+		if (diff > 0) {
+			error = xfs_icsb_modify_counters(bma->ip->i_mount,
+					XFS_SBS_FDBLOCKS,
+					-((int64_t)diff), 0);
+			ASSERT(!error);
+			if (error)
+				goto done;
+		}
+
+		ep = xfs_iext_get_ext(ifp, bma->idx);
+		xfs_bmbt_set_startblock(ep, nullstartblock((int)temp));
+		trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_);
+		trace_xfs_bmap_pre_update(bma->ip, bma->idx + 2, state, _THIS_IP_);
+		xfs_bmbt_set_startblock(xfs_iext_get_ext(ifp, bma->idx + 2),
+			nullstartblock((int)temp2));
+		trace_xfs_bmap_post_update(bma->ip, bma->idx + 2, state, _THIS_IP_);
+
+		bma->idx++;
+		da_new = temp + temp2;
+		break;
+
+	case BMAP_LEFT_FILLING | BMAP_LEFT_CONTIG | BMAP_RIGHT_CONTIG:
+	case BMAP_RIGHT_FILLING | BMAP_LEFT_CONTIG | BMAP_RIGHT_CONTIG:
+	case BMAP_LEFT_FILLING | BMAP_RIGHT_CONTIG:
+	case BMAP_RIGHT_FILLING | BMAP_LEFT_CONTIG:
+	case BMAP_LEFT_CONTIG | BMAP_RIGHT_CONTIG:
+	case BMAP_LEFT_CONTIG:
+	case BMAP_RIGHT_CONTIG:
+		/*
+		 * These cases are all impossible.
+		 */
+		ASSERT(0);
+	}
+
+	/* convert to a btree if necessary */
+	if (xfs_bmap_needs_btree(bma->ip, XFS_DATA_FORK)) {
+		int	tmp_logflags;	/* partial log flag return val */
+
+		ASSERT(bma->cur == NULL);
+		error = xfs_bmap_extents_to_btree(bma->tp, bma->ip,
+				bma->firstblock, bma->flist, &bma->cur,
+				da_old > 0, &tmp_logflags, XFS_DATA_FORK);
+		bma->logflags |= tmp_logflags;
+		if (error)
+			goto done;
+	}
+
+	/* adjust for changes in reserved delayed indirect blocks */
+	if (da_old || da_new) {
+		temp = da_new;
+		if (bma->cur)
+			temp += bma->cur->bc_private.b.allocated;
+		ASSERT(temp <= da_old);
+		if (temp < da_old)
+			xfs_icsb_modify_counters(bma->ip->i_mount,
+					XFS_SBS_FDBLOCKS,
+					(int64_t)(da_old - temp), 0);
 	}
+
+	/* clear out the allocated field, done with it now in any case. */
+	if (bma->cur)
+		bma->cur->bc_private.b.allocated = 0;
+
+	xfs_bmap_check_leaf_extents(bma->cur, bma->ip, XFS_DATA_FORK);
 done:
-	*logflagsp = flags;
+	bma->logflags |= rval;
 	return error;
+#undef	LEFT
+#undef	RIGHT
+#undef	PREV
 }
 
 /*
- * Remove the entry "free" from the free item list.  Prev points to the
- * previous entry, unless "free" is the head of the list.
+ * Convert an unwritten allocation to a real allocation or vice versa.
  */
-STATIC void
-xfs_bmap_del_free(
-	xfs_bmap_free_t		*flist,	/* free item list header */
-	xfs_bmap_free_item_t	*prev,	/* previous item on list, if any */
-	xfs_bmap_free_item_t	*free)	/* list item to be freed */
+STATIC int				/* error */
+xfs_bmap_add_extent_unwritten_real(
+	struct xfs_trans	*tp,
+	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 */
+	xfs_bmbt_irec_t		*new,	/* new data to add to file extents */
+	xfs_fsblock_t		*first,	/* pointer to firstblock variable */
+	xfs_bmap_free_t		*flist,	/* list of extents to be freed */
+	int			*logflagsp) /* inode logging flags */
 {
-	if (prev)
-		prev->xbfi_next = free->xbfi_next;
-	else
-		flist->xbf_first = free->xbfi_next;
-	flist->xbf_count--;
-	kmem_zone_free(xfs_bmap_free_item_zone, free);
-}
+	xfs_btree_cur_t		*cur;	/* btree cursor */
+	xfs_bmbt_rec_host_t	*ep;	/* extent entry for idx */
+	int			error;	/* error return value */
+	int			i;	/* temp state */
+	xfs_ifork_t		*ifp;	/* inode fork pointer */
+	xfs_fileoff_t		new_endoff;	/* end offset of new entry */
+	xfs_exntst_t		newext;	/* new extent state */
+	xfs_exntst_t		oldext;	/* old extent state */
+	xfs_bmbt_irec_t		r[3];	/* neighbor extent entries */
+					/* left is 0, right is 1, prev is 2 */
+	int			rval=0;	/* return value (logging flags) */
+	int			state = 0;/* state bits, accessed thru macros */
 
-/*
- * Convert an extents-format file into a btree-format file.
- * The new file will have a root block (in the inode) and a single child block.
- */
-STATIC int					/* error */
-xfs_bmap_extents_to_btree(
-	xfs_trans_t		*tp,		/* transaction pointer */
-	xfs_inode_t		*ip,		/* incore inode pointer */
-	xfs_fsblock_t		*firstblock,	/* first-block-allocated */
-	xfs_bmap_free_t		*flist,		/* blocks freed in xaction */
-	xfs_btree_cur_t		**curp,		/* cursor returned to caller */
-	int			wasdel,		/* converting a delayed alloc */
-	int			*logflagsp,	/* inode logging flags */
-	int			whichfork)	/* data or attr fork */
-{
-	struct xfs_btree_block	*ablock;	/* allocated (child) bt block */
-	xfs_buf_t		*abp;		/* buffer for ablock */
-	xfs_alloc_arg_t		args;		/* allocation arguments */
-	xfs_bmbt_rec_t		*arp;		/* child record pointer */
-	struct xfs_btree_block	*block;		/* btree root block */
-	xfs_btree_cur_t		*cur;		/* bmap btree cursor */
-	xfs_bmbt_rec_host_t	*ep;		/* extent record pointer */
-	int			error;		/* error return value */
-	xfs_extnum_t		i, cnt;		/* extent record index */
-	xfs_ifork_t		*ifp;		/* inode fork pointer */
-	xfs_bmbt_key_t		*kp;		/* root block key pointer */
-	xfs_mount_t		*mp;		/* mount structure */
-	xfs_extnum_t		nextents;	/* number of file extents */
-	xfs_bmbt_ptr_t		*pp;		/* root block address pointer */
+	*logflagsp = 0;
 
-	ifp = XFS_IFORK_PTR(ip, whichfork);
-	ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS);
+	cur = *curp;
+	ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
 
-	/*
-	 * Make space in the inode incore.
-	 */
-	xfs_iroot_realloc(ip, 1, whichfork);
-	ifp->if_flags |= XFS_IFBROOT;
+	ASSERT(*idx >= 0);
+	ASSERT(*idx <= ifp->if_bytes / sizeof(struct xfs_bmbt_rec));
+	ASSERT(!isnullstartblock(new->br_startblock));
+
+	XFS_STATS_INC(xs_add_exlist);
+
+#define	LEFT		r[0]
+#define	RIGHT		r[1]
+#define	PREV		r[2]
 
 	/*
-	 * Fill in the root.
+	 * Set up a bunch of variables to make the tests simpler.
 	 */
-	block = ifp->if_broot;
-	block->bb_magic = cpu_to_be32(XFS_BMAP_MAGIC);
-	block->bb_level = cpu_to_be16(1);
-	block->bb_numrecs = cpu_to_be16(1);
-	block->bb_u.l.bb_leftsib = cpu_to_be64(NULLDFSBNO);
-	block->bb_u.l.bb_rightsib = cpu_to_be64(NULLDFSBNO);
+	error = 0;
+	ep = xfs_iext_get_ext(ifp, *idx);
+	xfs_bmbt_get_all(ep, &PREV);
+	newext = new->br_state;
+	oldext = (newext == XFS_EXT_UNWRITTEN) ?
+		XFS_EXT_NORM : XFS_EXT_UNWRITTEN;
+	ASSERT(PREV.br_state == oldext);
+	new_endoff = new->br_startoff + new->br_blockcount;
+	ASSERT(PREV.br_startoff <= new->br_startoff);
+	ASSERT(PREV.br_startoff + PREV.br_blockcount >= new_endoff);
 
 	/*
-	 * Need a cursor.  Can't allocate until bb_level is filled in.
+	 * Set flags determining what part of the previous oldext allocation
+	 * extent is being replaced by a newext allocation.
 	 */
-	mp = ip->i_mount;
-	cur = xfs_bmbt_init_cursor(mp, tp, ip, whichfork);
-	cur->bc_private.b.firstblock = *firstblock;
-	cur->bc_private.b.flist = flist;
-	cur->bc_private.b.flags = wasdel ? XFS_BTCUR_BPRV_WASDEL : 0;
+	if (PREV.br_startoff == new->br_startoff)
+		state |= BMAP_LEFT_FILLING;
+	if (PREV.br_startoff + PREV.br_blockcount == new_endoff)
+		state |= BMAP_RIGHT_FILLING;
+
 	/*
-	 * Convert to a btree with two levels, one record in root.
+	 * Check and set flags if this segment has a left neighbor.
+	 * Don't set contiguous if the combined extent would be too large.
 	 */
-	XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_BTREE);
-	memset(&args, 0, sizeof(args));
-	args.tp = tp;
-	args.mp = mp;
-	args.firstblock = *firstblock;
-	if (*firstblock == NULLFSBLOCK) {
-		args.type = XFS_ALLOCTYPE_START_BNO;
-		args.fsbno = XFS_INO_TO_FSB(mp, ip->i_ino);
-	} else if (flist->xbf_low) {
-		args.type = XFS_ALLOCTYPE_START_BNO;
-		args.fsbno = *firstblock;
-	} else {
-		args.type = XFS_ALLOCTYPE_NEAR_BNO;
-		args.fsbno = *firstblock;
-	}
-	args.minlen = args.maxlen = args.prod = 1;
-	args.wasdel = wasdel;
-	*logflagsp = 0;
-	if ((error = xfs_alloc_vextent(&args))) {
-		xfs_iroot_realloc(ip, -1, whichfork);
-		xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
-		return error;
+	if (*idx > 0) {
+		state |= BMAP_LEFT_VALID;
+		xfs_bmbt_get_all(xfs_iext_get_ext(ifp, *idx - 1), &LEFT);
+
+		if (isnullstartblock(LEFT.br_startblock))
+			state |= BMAP_LEFT_DELAY;
 	}
+
+	if ((state & BMAP_LEFT_VALID) && !(state & BMAP_LEFT_DELAY) &&
+	    LEFT.br_startoff + LEFT.br_blockcount == new->br_startoff &&
+	    LEFT.br_startblock + LEFT.br_blockcount == new->br_startblock &&
+	    LEFT.br_state == newext &&
+	    LEFT.br_blockcount + new->br_blockcount <= MAXEXTLEN)
+		state |= BMAP_LEFT_CONTIG;
+
 	/*
-	 * Allocation can't fail, the space was reserved.
-	 */
-	ASSERT(args.fsbno != NULLFSBLOCK);
-	ASSERT(*firstblock == NULLFSBLOCK ||
-	       args.agno == XFS_FSB_TO_AGNO(mp, *firstblock) ||
-	       (flist->xbf_low &&
-		args.agno > XFS_FSB_TO_AGNO(mp, *firstblock)));
-	*firstblock = cur->bc_private.b.firstblock = args.fsbno;
-	cur->bc_private.b.allocated++;
-	ip->i_d.di_nblocks++;
-	xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, 1L);
-	abp = xfs_btree_get_bufl(mp, tp, args.fsbno, 0);
-	/*
-	 * Fill in the child block.
+	 * Check and set flags if this segment has a right neighbor.
+	 * Don't set contiguous if the combined extent would be too large.
+	 * Also check for all-three-contiguous being too large.
 	 */
-	abp->b_ops = &xfs_bmbt_buf_ops;
-	ablock = XFS_BUF_TO_BLOCK(abp);
-	ablock->bb_magic = cpu_to_be32(XFS_BMAP_MAGIC);
-	ablock->bb_level = 0;
-	ablock->bb_u.l.bb_leftsib = cpu_to_be64(NULLDFSBNO);
-	ablock->bb_u.l.bb_rightsib = cpu_to_be64(NULLDFSBNO);
-	arp = XFS_BMBT_REC_ADDR(mp, ablock, 1);
-	nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
-	for (cnt = i = 0; i < nextents; i++) {
-		ep = xfs_iext_get_ext(ifp, i);
-		if (!isnullstartblock(xfs_bmbt_get_startblock(ep))) {
-			arp->l0 = cpu_to_be64(ep->l0);
-			arp->l1 = cpu_to_be64(ep->l1);
-			arp++; cnt++;
-		}
+	if (*idx < ip->i_df.if_bytes / (uint)sizeof(xfs_bmbt_rec_t) - 1) {
+		state |= BMAP_RIGHT_VALID;
+		xfs_bmbt_get_all(xfs_iext_get_ext(ifp, *idx + 1), &RIGHT);
+		if (isnullstartblock(RIGHT.br_startblock))
+			state |= BMAP_RIGHT_DELAY;
 	}
-	ASSERT(cnt == XFS_IFORK_NEXTENTS(ip, whichfork));
-	xfs_btree_set_numrecs(ablock, cnt);
 
-	/*
-	 * Fill in the root key and pointer.
-	 */
-	kp = XFS_BMBT_KEY_ADDR(mp, block, 1);
-	arp = XFS_BMBT_REC_ADDR(mp, ablock, 1);
-	kp->br_startoff = cpu_to_be64(xfs_bmbt_disk_get_startoff(arp));
-	pp = XFS_BMBT_PTR_ADDR(mp, block, 1, xfs_bmbt_get_maxrecs(cur,
-						be16_to_cpu(block->bb_level)));
-	*pp = cpu_to_be64(args.fsbno);
+	if ((state & BMAP_RIGHT_VALID) && !(state & BMAP_RIGHT_DELAY) &&
+	    new_endoff == RIGHT.br_startoff &&
+	    new->br_startblock + new->br_blockcount == RIGHT.br_startblock &&
+	    newext == RIGHT.br_state &&
+	    new->br_blockcount + RIGHT.br_blockcount <= MAXEXTLEN &&
+	    ((state & (BMAP_LEFT_CONTIG | BMAP_LEFT_FILLING |
+		       BMAP_RIGHT_FILLING)) !=
+		      (BMAP_LEFT_CONTIG | BMAP_LEFT_FILLING |
+		       BMAP_RIGHT_FILLING) ||
+	     LEFT.br_blockcount + new->br_blockcount + RIGHT.br_blockcount
+			<= MAXEXTLEN))
+		state |= BMAP_RIGHT_CONTIG;
 
 	/*
-	 * Do all this logging at the end so that
-	 * the root is at the right level.
+	 * Switch out based on the FILLING and CONTIG state bits.
 	 */
-	xfs_btree_log_block(cur, abp, XFS_BB_ALL_BITS);
-	xfs_btree_log_recs(cur, abp, 1, be16_to_cpu(ablock->bb_numrecs));
-	ASSERT(*curp == NULL);
-	*curp = cur;
-	*logflagsp = XFS_ILOG_CORE | xfs_ilog_fbroot(whichfork);
-	return 0;
-}
-
-/*
- * Calculate the default attribute fork offset for newly created inodes.
- */
-uint
-xfs_default_attroffset(
-	struct xfs_inode	*ip)
-{
-	struct xfs_mount	*mp = ip->i_mount;
-	uint			offset;
-
-	if (mp->m_sb.sb_inodesize == 256) {
-		offset = XFS_LITINO(mp) -
-				XFS_BMDR_SPACE_CALC(MINABTPTRS);
-	} else {
-		offset = XFS_BMDR_SPACE_CALC(6 * MINABTPTRS);
-	}
+	switch (state & (BMAP_LEFT_FILLING | BMAP_LEFT_CONTIG |
+			 BMAP_RIGHT_FILLING | BMAP_RIGHT_CONTIG)) {
+	case BMAP_LEFT_FILLING | BMAP_LEFT_CONTIG |
+	     BMAP_RIGHT_FILLING | BMAP_RIGHT_CONTIG:
+		/*
+		 * Setting all of a previous oldext extent to newext.
+		 * The left and right neighbors are both contiguous with new.
+		 */
+		--*idx;
 
-	ASSERT(offset < XFS_LITINO(mp));
-	return offset;
-}
+		trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_);
+		xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, *idx),
+			LEFT.br_blockcount + PREV.br_blockcount +
+			RIGHT.br_blockcount);
+		trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_);
 
-/*
- * Helper routine to reset inode di_forkoff field when switching
- * attribute fork from local to extent format - we reset it where
- * possible to make space available for inline data fork extents.
- */
-STATIC void
-xfs_bmap_forkoff_reset(
-	xfs_mount_t	*mp,
-	xfs_inode_t	*ip,
-	int		whichfork)
-{
-	if (whichfork == XFS_ATTR_FORK &&
-	    ip->i_d.di_format != XFS_DINODE_FMT_DEV &&
-	    ip->i_d.di_format != XFS_DINODE_FMT_UUID &&
-	    ip->i_d.di_format != XFS_DINODE_FMT_BTREE) {
-		uint	dfl_forkoff = xfs_default_attroffset(ip) >> 3;
+		xfs_iext_remove(ip, *idx + 1, 2, state);
+		ip->i_d.di_nextents -= 2;
+		if (cur == NULL)
+			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
+		else {
+			rval = XFS_ILOG_CORE;
+			if ((error = xfs_bmbt_lookup_eq(cur, RIGHT.br_startoff,
+					RIGHT.br_startblock,
+					RIGHT.br_blockcount, &i)))
+				goto done;
+			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+			if ((error = xfs_btree_delete(cur, &i)))
+				goto done;
+			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+			if ((error = xfs_btree_decrement(cur, 0, &i)))
+				goto done;
+			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+			if ((error = xfs_btree_delete(cur, &i)))
+				goto done;
+			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+			if ((error = xfs_btree_decrement(cur, 0, &i)))
+				goto done;
+			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+			if ((error = xfs_bmbt_update(cur, LEFT.br_startoff,
+				LEFT.br_startblock,
+				LEFT.br_blockcount + PREV.br_blockcount +
+				RIGHT.br_blockcount, LEFT.br_state)))
+				goto done;
+		}
+		break;
 
-		if (dfl_forkoff > ip->i_d.di_forkoff)
-			ip->i_d.di_forkoff = dfl_forkoff;
-	}
-}
+	case BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING | BMAP_LEFT_CONTIG:
+		/*
+		 * Setting all of a previous oldext extent to newext.
+		 * The left neighbor is contiguous, the right is not.
+		 */
+		--*idx;
 
-/*
- * Convert a local file to an extents file.
- * This code is out of bounds for data forks of regular files,
- * since the file data needs to get logged so things will stay consistent.
- * (The bmap-level manipulations are ok, though).
- */
-STATIC int				/* error */
-xfs_bmap_local_to_extents(
-	xfs_trans_t	*tp,		/* transaction pointer */
-	xfs_inode_t	*ip,		/* incore inode pointer */
-	xfs_fsblock_t	*firstblock,	/* first block allocated in xaction */
-	xfs_extlen_t	total,		/* total blocks needed by transaction */
-	int		*logflagsp,	/* inode logging flags */
-	int		whichfork,
-	void		(*init_fn)(struct xfs_buf *bp,
-				   struct xfs_inode *ip,
-				   struct xfs_ifork *ifp))
-{
-	int		error;		/* error return value */
-	int		flags;		/* logging flags returned */
-	xfs_ifork_t	*ifp;		/* inode fork pointer */
+		trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_);
+		xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, *idx),
+			LEFT.br_blockcount + PREV.br_blockcount);
+		trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_);
 
-	/*
-	 * 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(!(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;
-	error = 0;
-	if (ifp->if_bytes) {
-		xfs_alloc_arg_t	args;	/* allocation arguments */
-		xfs_buf_t	*bp;	/* buffer for extent block */
-		xfs_bmbt_rec_host_t *ep;/* extent record pointer */
+		xfs_iext_remove(ip, *idx + 1, 1, state);
+		ip->i_d.di_nextents--;
+		if (cur == NULL)
+			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
+		else {
+			rval = XFS_ILOG_CORE;
+			if ((error = xfs_bmbt_lookup_eq(cur, PREV.br_startoff,
+					PREV.br_startblock, PREV.br_blockcount,
+					&i)))
+				goto done;
+			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+			if ((error = xfs_btree_delete(cur, &i)))
+				goto done;
+			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+			if ((error = xfs_btree_decrement(cur, 0, &i)))
+				goto done;
+			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+			if ((error = xfs_bmbt_update(cur, LEFT.br_startoff,
+				LEFT.br_startblock,
+				LEFT.br_blockcount + PREV.br_blockcount,
+				LEFT.br_state)))
+				goto done;
+		}
+		break;
 
-		ASSERT((ifp->if_flags &
-			(XFS_IFINLINE|XFS_IFEXTENTS|XFS_IFEXTIREC)) == XFS_IFINLINE);
-		memset(&args, 0, sizeof(args));
-		args.tp = tp;
-		args.mp = ip->i_mount;
-		args.firstblock = *firstblock;
+	case BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING | BMAP_RIGHT_CONTIG:
 		/*
-		 * Allocate a block.  We know we need only one, since the
-		 * file currently fits in an inode.
+		 * Setting all of a previous oldext extent to newext.
+		 * The right neighbor is contiguous, the left is not.
 		 */
-		if (*firstblock == NULLFSBLOCK) {
-			args.fsbno = XFS_INO_TO_FSB(args.mp, ip->i_ino);
-			args.type = XFS_ALLOCTYPE_START_BNO;
-		} else {
-			args.fsbno = *firstblock;
-			args.type = XFS_ALLOCTYPE_NEAR_BNO;
+		trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_);
+		xfs_bmbt_set_blockcount(ep,
+			PREV.br_blockcount + RIGHT.br_blockcount);
+		xfs_bmbt_set_state(ep, newext);
+		trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_);
+		xfs_iext_remove(ip, *idx + 1, 1, state);
+		ip->i_d.di_nextents--;
+		if (cur == NULL)
+			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
+		else {
+			rval = XFS_ILOG_CORE;
+			if ((error = xfs_bmbt_lookup_eq(cur, RIGHT.br_startoff,
+					RIGHT.br_startblock,
+					RIGHT.br_blockcount, &i)))
+				goto done;
+			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+			if ((error = xfs_btree_delete(cur, &i)))
+				goto done;
+			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+			if ((error = xfs_btree_decrement(cur, 0, &i)))
+				goto done;
+			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+			if ((error = xfs_bmbt_update(cur, new->br_startoff,
+				new->br_startblock,
+				new->br_blockcount + RIGHT.br_blockcount,
+				newext)))
+				goto done;
 		}
-		args.total = total;
-		args.minlen = args.maxlen = args.prod = 1;
-		error = xfs_alloc_vextent(&args);
-		if (error)
-			goto done;
+		break;
 
-		/* Can't fail, the space was reserved. */
-		ASSERT(args.fsbno != NULLFSBLOCK);
-		ASSERT(args.len == 1);
-		*firstblock = args.fsbno;
-		bp = xfs_btree_get_bufl(args.mp, tp, args.fsbno, 0);
+	case BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING:
+		/*
+		 * Setting all of a previous oldext extent to newext.
+		 * Neither the left nor right neighbors are contiguous with
+		 * the new one.
+		 */
+		trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_);
+		xfs_bmbt_set_state(ep, newext);
+		trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_);
 
-		/* initialise the block and copy the data */
-		init_fn(bp, ip, ifp);
+		if (cur == NULL)
+			rval = XFS_ILOG_DEXT;
+		else {
+			rval = 0;
+			if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff,
+					new->br_startblock, new->br_blockcount,
+					&i)))
+				goto done;
+			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+			if ((error = xfs_bmbt_update(cur, new->br_startoff,
+				new->br_startblock, new->br_blockcount,
+				newext)))
+				goto done;
+		}
+		break;
 
-		/* account for the change in fork size and log everything */
-		xfs_trans_log_buf(tp, bp, 0, ifp->if_bytes - 1);
-		xfs_bmap_forkoff_reset(args.mp, ip, whichfork);
-		xfs_idata_realloc(ip, -ifp->if_bytes, whichfork);
-		xfs_iext_add(ifp, 0, 1);
-		ep = xfs_iext_get_ext(ifp, 0);
-		xfs_bmbt_set_allf(ep, 0, args.fsbno, 1, XFS_EXT_NORM);
-		trace_xfs_bmap_post_update(ip, 0,
-				whichfork == XFS_ATTR_FORK ? BMAP_ATTRFORK : 0,
-				_THIS_IP_);
-		XFS_IFORK_NEXT_SET(ip, whichfork, 1);
-		ip->i_d.di_nblocks = 1;
-		xfs_trans_mod_dquot_byino(tp, ip,
-			XFS_TRANS_DQ_BCOUNT, 1L);
-		flags |= xfs_ilog_fext(whichfork);
-	} else {
-		ASSERT(XFS_IFORK_NEXTENTS(ip, whichfork) == 0);
-		xfs_bmap_forkoff_reset(ip->i_mount, ip, whichfork);
-	}
-	ifp->if_flags &= ~XFS_IFINLINE;
-	ifp->if_flags |= XFS_IFEXTENTS;
-	XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_EXTENTS);
-	flags |= XFS_ILOG_CORE;
-done:
-	*logflagsp = flags;
-	return error;
-}
+	case BMAP_LEFT_FILLING | BMAP_LEFT_CONTIG:
+		/*
+		 * Setting the first part of a previous oldext extent to newext.
+		 * The left neighbor is contiguous.
+		 */
+		trace_xfs_bmap_pre_update(ip, *idx - 1, state, _THIS_IP_);
+		xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, *idx - 1),
+			LEFT.br_blockcount + new->br_blockcount);
+		xfs_bmbt_set_startoff(ep,
+			PREV.br_startoff + new->br_blockcount);
+		trace_xfs_bmap_post_update(ip, *idx - 1, state, _THIS_IP_);
 
-/*
- * Search the extent records for the entry containing block bno.
- * If bno lies in a hole, point to the next entry.  If bno lies
- * past eof, *eofp will be set, and *prevp will contain the last
- * entry (null if none).  Else, *lastxp will be set to the index
- * of the found entry; *gotp will contain the entry.
- */
-STATIC xfs_bmbt_rec_host_t *		/* pointer to found extent entry */
-xfs_bmap_search_multi_extents(
-	xfs_ifork_t	*ifp,		/* inode fork pointer */
-	xfs_fileoff_t	bno,		/* block number searched for */
-	int		*eofp,		/* out: end of file found */
-	xfs_extnum_t	*lastxp,	/* out: last extent index */
-	xfs_bmbt_irec_t	*gotp,		/* out: extent entry found */
-	xfs_bmbt_irec_t	*prevp)		/* out: previous extent entry found */
-{
-	xfs_bmbt_rec_host_t *ep;		/* extent record pointer */
-	xfs_extnum_t	lastx;		/* last extent index */
+		trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_);
+		xfs_bmbt_set_startblock(ep,
+			new->br_startblock + new->br_blockcount);
+		xfs_bmbt_set_blockcount(ep,
+			PREV.br_blockcount - new->br_blockcount);
+		trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_);
 
-	/*
-	 * Initialize the extent entry structure to catch access to
-	 * uninitialized br_startblock field.
-	 */
-	gotp->br_startoff = 0xffa5a5a5a5a5a5a5LL;
-	gotp->br_blockcount = 0xa55a5a5a5a5a5a5aLL;
-	gotp->br_state = XFS_EXT_INVALID;
-#if XFS_BIG_BLKNOS
-	gotp->br_startblock = 0xffffa5a5a5a5a5a5LL;
-#else
-	gotp->br_startblock = 0xffffa5a5;
-#endif
-	prevp->br_startoff = NULLFILEOFF;
+		--*idx;
 
-	ep = xfs_iext_bno_to_ext(ifp, bno, &lastx);
-	if (lastx > 0) {
-		xfs_bmbt_get_all(xfs_iext_get_ext(ifp, lastx - 1), prevp);
-	}
-	if (lastx < (ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t))) {
-		xfs_bmbt_get_all(ep, gotp);
-		*eofp = 0;
-	} else {
-		if (lastx > 0) {
-			*gotp = *prevp;
+		if (cur == NULL)
+			rval = XFS_ILOG_DEXT;
+		else {
+			rval = 0;
+			if ((error = xfs_bmbt_lookup_eq(cur, PREV.br_startoff,
+					PREV.br_startblock, PREV.br_blockcount,
+					&i)))
+				goto done;
+			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+			if ((error = xfs_bmbt_update(cur,
+				PREV.br_startoff + new->br_blockcount,
+				PREV.br_startblock + new->br_blockcount,
+				PREV.br_blockcount - new->br_blockcount,
+				oldext)))
+				goto done;
+			if ((error = xfs_btree_decrement(cur, 0, &i)))
+				goto done;
+			error = xfs_bmbt_update(cur, LEFT.br_startoff,
+				LEFT.br_startblock,
+				LEFT.br_blockcount + new->br_blockcount,
+				LEFT.br_state);
+			if (error)
+				goto done;
 		}
-		*eofp = 1;
-		ep = NULL;
-	}
-	*lastxp = lastx;
-	return ep;
-}
+		break;
 
-/*
- * Search the extents list for the inode, for the extent containing bno.
- * If bno lies in a hole, point to the next entry.  If bno lies past eof,
- * *eofp will be set, and *prevp will contain the last entry (null if none).
- * Else, *lastxp will be set to the index of the found
- * entry; *gotp will contain the entry.
- */
-STATIC xfs_bmbt_rec_host_t *                 /* pointer to found extent entry */
-xfs_bmap_search_extents(
-	xfs_inode_t     *ip,            /* incore inode pointer */
-	xfs_fileoff_t   bno,            /* block number searched for */
-	int             fork,      	/* data or attr fork */
-	int             *eofp,          /* out: end of file found */
-	xfs_extnum_t    *lastxp,        /* out: last extent index */
-	xfs_bmbt_irec_t *gotp,          /* out: extent entry found */
-	xfs_bmbt_irec_t *prevp)         /* out: previous extent entry found */
-{
-	xfs_ifork_t	*ifp;		/* inode fork pointer */
-	xfs_bmbt_rec_host_t  *ep;            /* extent record pointer */
+	case BMAP_LEFT_FILLING:
+		/*
+		 * Setting the first part of a previous oldext extent to newext.
+		 * The left neighbor is not contiguous.
+		 */
+		trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_);
+		ASSERT(ep && xfs_bmbt_get_state(ep) == oldext);
+		xfs_bmbt_set_startoff(ep, new_endoff);
+		xfs_bmbt_set_blockcount(ep,
+			PREV.br_blockcount - new->br_blockcount);
+		xfs_bmbt_set_startblock(ep,
+			new->br_startblock + new->br_blockcount);
+		trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_);
 
-	XFS_STATS_INC(xs_look_exlist);
-	ifp = XFS_IFORK_PTR(ip, fork);
+		xfs_iext_insert(ip, *idx, 1, new, state);
+		ip->i_d.di_nextents++;
+		if (cur == NULL)
+			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
+		else {
+			rval = XFS_ILOG_CORE;
+			if ((error = xfs_bmbt_lookup_eq(cur, PREV.br_startoff,
+					PREV.br_startblock, PREV.br_blockcount,
+					&i)))
+				goto done;
+			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+			if ((error = xfs_bmbt_update(cur,
+				PREV.br_startoff + new->br_blockcount,
+				PREV.br_startblock + new->br_blockcount,
+				PREV.br_blockcount - new->br_blockcount,
+				oldext)))
+				goto done;
+			cur->bc_rec.b = *new;
+			if ((error = xfs_btree_insert(cur, &i)))
+				goto done;
+			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+		}
+		break;
 
-	ep = xfs_bmap_search_multi_extents(ifp, bno, eofp, lastxp, gotp, prevp);
+	case BMAP_RIGHT_FILLING | BMAP_RIGHT_CONTIG:
+		/*
+		 * Setting the last part of a previous oldext extent to newext.
+		 * The right neighbor is contiguous with the new allocation.
+		 */
+		trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_);
+		xfs_bmbt_set_blockcount(ep,
+			PREV.br_blockcount - new->br_blockcount);
+		trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_);
 
-	if (unlikely(!(gotp->br_startblock) && (*lastxp != NULLEXTNUM) &&
-		     !(XFS_IS_REALTIME_INODE(ip) && fork == XFS_DATA_FORK))) {
-		xfs_alert_tag(ip->i_mount, XFS_PTAG_FSBLOCK_ZERO,
-				"Access to block zero in inode %llu "
-				"start_block: %llx start_off: %llx "
-				"blkcnt: %llx extent-state: %x lastx: %x\n",
-			(unsigned long long)ip->i_ino,
-			(unsigned long long)gotp->br_startblock,
-			(unsigned long long)gotp->br_startoff,
-			(unsigned long long)gotp->br_blockcount,
-			gotp->br_state, *lastxp);
-		*lastxp = NULLEXTNUM;
-		*eofp = 1;
-		return NULL;
-	}
-	return ep;
-}
+		++*idx;
 
-/*
- * Compute the worst-case number of indirect blocks that will be used
- * for ip's delayed extent of length "len".
- */
-STATIC xfs_filblks_t
-xfs_bmap_worst_indlen(
-	xfs_inode_t	*ip,		/* incore inode pointer */
-	xfs_filblks_t	len)		/* delayed extent length */
-{
-	int		level;		/* btree level number */
-	int		maxrecs;	/* maximum record count at this level */
-	xfs_mount_t	*mp;		/* mount structure */
-	xfs_filblks_t	rval;		/* return value */
+		trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_);
+		xfs_bmbt_set_allf(xfs_iext_get_ext(ifp, *idx),
+			new->br_startoff, new->br_startblock,
+			new->br_blockcount + RIGHT.br_blockcount, newext);
+		trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_);
 
-	mp = ip->i_mount;
-	maxrecs = mp->m_bmap_dmxr[0];
-	for (level = 0, rval = 0;
-	     level < XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK);
-	     level++) {
-		len += maxrecs - 1;
-		do_div(len, maxrecs);
-		rval += len;
-		if (len == 1)
-			return rval + XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) -
-				level - 1;
-		if (level == 0)
-			maxrecs = mp->m_bmap_dmxr[1];
-	}
-	return rval;
-}
+		if (cur == NULL)
+			rval = XFS_ILOG_DEXT;
+		else {
+			rval = 0;
+			if ((error = xfs_bmbt_lookup_eq(cur, PREV.br_startoff,
+					PREV.br_startblock,
+					PREV.br_blockcount, &i)))
+				goto done;
+			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+			if ((error = xfs_bmbt_update(cur, PREV.br_startoff,
+				PREV.br_startblock,
+				PREV.br_blockcount - new->br_blockcount,
+				oldext)))
+				goto done;
+			if ((error = xfs_btree_increment(cur, 0, &i)))
+				goto done;
+			if ((error = xfs_bmbt_update(cur, new->br_startoff,
+				new->br_startblock,
+				new->br_blockcount + RIGHT.br_blockcount,
+				newext)))
+				goto done;
+		}
+		break;
 
-/*
- * Convert inode from non-attributed to attributed.
- * Must not be in a transaction, ip must not be locked.
- */
-int						/* error code */
-xfs_bmap_add_attrfork(
-	xfs_inode_t		*ip,		/* incore inode pointer */
-	int			size,		/* space new attribute needs */
-	int			rsvd)		/* xact may use reserved blks */
-{
-	xfs_fsblock_t		firstblock;	/* 1st block/ag allocated */
-	xfs_bmap_free_t		flist;		/* freed extent records */
-	xfs_mount_t		*mp;		/* mount structure */
-	xfs_trans_t		*tp;		/* transaction pointer */
-	int			blks;		/* space reservation */
-	int			version = 1;	/* superblock attr version */
-	int			committed;	/* xaction was committed */
-	int			logflags;	/* logging flags */
-	int			error;		/* error return value */
+	case BMAP_RIGHT_FILLING:
+		/*
+		 * Setting the last part of a previous oldext extent to newext.
+		 * The right neighbor is not contiguous.
+		 */
+		trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_);
+		xfs_bmbt_set_blockcount(ep,
+			PREV.br_blockcount - new->br_blockcount);
+		trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_);
 
-	ASSERT(XFS_IFORK_Q(ip) == 0);
+		++*idx;
+		xfs_iext_insert(ip, *idx, 1, new, state);
 
-	mp = ip->i_mount;
-	ASSERT(!XFS_NOT_DQATTACHED(mp, ip));
-	tp = xfs_trans_alloc(mp, XFS_TRANS_ADDAFORK);
-	blks = XFS_ADDAFORK_SPACE_RES(mp);
-	if (rsvd)
-		tp->t_flags |= XFS_TRANS_RESERVE;
-	if ((error = xfs_trans_reserve(tp, blks, XFS_ADDAFORK_LOG_RES(mp), 0,
-			XFS_TRANS_PERM_LOG_RES, XFS_ADDAFORK_LOG_COUNT)))
-		goto error0;
-	xfs_ilock(ip, XFS_ILOCK_EXCL);
-	error = xfs_trans_reserve_quota_nblks(tp, ip, blks, 0, rsvd ?
-			XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_FORCE_RES :
-			XFS_QMOPT_RES_REGBLKS);
-	if (error) {
-		xfs_iunlock(ip, XFS_ILOCK_EXCL);
-		xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES);
-		return error;
-	}
-	if (XFS_IFORK_Q(ip))
-		goto error1;
-	if (ip->i_d.di_aformat != XFS_DINODE_FMT_EXTENTS) {
+		ip->i_d.di_nextents++;
+		if (cur == NULL)
+			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
+		else {
+			rval = XFS_ILOG_CORE;
+			if ((error = xfs_bmbt_lookup_eq(cur, PREV.br_startoff,
+					PREV.br_startblock, PREV.br_blockcount,
+					&i)))
+				goto done;
+			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+			if ((error = xfs_bmbt_update(cur, PREV.br_startoff,
+				PREV.br_startblock,
+				PREV.br_blockcount - new->br_blockcount,
+				oldext)))
+				goto done;
+			if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff,
+					new->br_startblock, new->br_blockcount,
+					&i)))
+				goto done;
+			XFS_WANT_CORRUPTED_GOTO(i == 0, done);
+			cur->bc_rec.b.br_state = XFS_EXT_NORM;
+			if ((error = xfs_btree_insert(cur, &i)))
+				goto done;
+			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+		}
+		break;
+
+	case 0:
 		/*
-		 * For inodes coming from pre-6.2 filesystems.
+		 * Setting the middle part of a previous oldext extent to
+		 * newext.  Contiguity is impossible here.
+		 * One extent becomes three extents.
 		 */
-		ASSERT(ip->i_d.di_aformat == 0);
-		ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;
-	}
-	ASSERT(ip->i_d.di_anextents == 0);
+		trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_);
+		xfs_bmbt_set_blockcount(ep,
+			new->br_startoff - PREV.br_startoff);
+		trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_);
 
-	xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
-	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
+		r[0] = *new;
+		r[1].br_startoff = new_endoff;
+		r[1].br_blockcount =
+			PREV.br_startoff + PREV.br_blockcount - new_endoff;
+		r[1].br_startblock = new->br_startblock + new->br_blockcount;
+		r[1].br_state = oldext;
 
-	switch (ip->i_d.di_format) {
-	case XFS_DINODE_FMT_DEV:
-		ip->i_d.di_forkoff = roundup(sizeof(xfs_dev_t), 8) >> 3;
-		break;
-	case XFS_DINODE_FMT_UUID:
-		ip->i_d.di_forkoff = roundup(sizeof(uuid_t), 8) >> 3;
-		break;
-	case XFS_DINODE_FMT_LOCAL:
-	case XFS_DINODE_FMT_EXTENTS:
-	case XFS_DINODE_FMT_BTREE:
-		ip->i_d.di_forkoff = xfs_attr_shortform_bytesfit(ip, size);
-		if (!ip->i_d.di_forkoff)
-			ip->i_d.di_forkoff = xfs_default_attroffset(ip) >> 3;
-		else if (mp->m_flags & XFS_MOUNT_ATTR2)
-			version = 2;
+		++*idx;
+		xfs_iext_insert(ip, *idx, 2, &r[0], state);
+
+		ip->i_d.di_nextents += 2;
+		if (cur == NULL)
+			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
+		else {
+			rval = XFS_ILOG_CORE;
+			if ((error = xfs_bmbt_lookup_eq(cur, PREV.br_startoff,
+					PREV.br_startblock, PREV.br_blockcount,
+					&i)))
+				goto done;
+			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+			/* new right extent - oldext */
+			if ((error = xfs_bmbt_update(cur, r[1].br_startoff,
+				r[1].br_startblock, r[1].br_blockcount,
+				r[1].br_state)))
+				goto done;
+			/* new left extent - oldext */
+			cur->bc_rec.b = PREV;
+			cur->bc_rec.b.br_blockcount =
+				new->br_startoff - PREV.br_startoff;
+			if ((error = xfs_btree_insert(cur, &i)))
+				goto done;
+			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+			/*
+			 * Reset the cursor to the position of the new extent
+			 * we are about to insert as we can't trust it after
+			 * the previous insert.
+			 */
+			if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff,
+					new->br_startblock, new->br_blockcount,
+					&i)))
+				goto done;
+			XFS_WANT_CORRUPTED_GOTO(i == 0, done);
+			/* new middle extent - newext */
+			cur->bc_rec.b.br_state = new->br_state;
+			if ((error = xfs_btree_insert(cur, &i)))
+				goto done;
+			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+		}
 		break;
-	default:
+
+	case BMAP_LEFT_FILLING | BMAP_LEFT_CONTIG | BMAP_RIGHT_CONTIG:
+	case BMAP_RIGHT_FILLING | BMAP_LEFT_CONTIG | BMAP_RIGHT_CONTIG:
+	case BMAP_LEFT_FILLING | BMAP_RIGHT_CONTIG:
+	case BMAP_RIGHT_FILLING | BMAP_LEFT_CONTIG:
+	case BMAP_LEFT_CONTIG | BMAP_RIGHT_CONTIG:
+	case BMAP_LEFT_CONTIG:
+	case BMAP_RIGHT_CONTIG:
+		/*
+		 * These cases are all impossible.
+		 */
 		ASSERT(0);
-		error = XFS_ERROR(EINVAL);
-		goto error1;
 	}
 
-	ASSERT(ip->i_afp == NULL);
-	ip->i_afp = kmem_zone_zalloc(xfs_ifork_zone, KM_SLEEP);
-	ip->i_afp->if_flags = XFS_IFEXTENTS;
-	logflags = 0;
-	xfs_bmap_init(&flist, &firstblock);
-	switch (ip->i_d.di_format) {
-	case XFS_DINODE_FMT_LOCAL:
-		error = xfs_bmap_add_attrfork_local(tp, ip, &firstblock, &flist,
-			&logflags);
-		break;
-	case XFS_DINODE_FMT_EXTENTS:
-		error = xfs_bmap_add_attrfork_extents(tp, ip, &firstblock,
-			&flist, &logflags);
-		break;
-	case XFS_DINODE_FMT_BTREE:
-		error = xfs_bmap_add_attrfork_btree(tp, ip, &firstblock, &flist,
-			&logflags);
-		break;
-	default:
-		error = 0;
-		break;
+	/* convert to a btree if necessary */
+	if (xfs_bmap_needs_btree(ip, XFS_DATA_FORK)) {
+		int	tmp_logflags;	/* partial log flag return val */
+
+		ASSERT(cur == NULL);
+		error = xfs_bmap_extents_to_btree(tp, ip, first, flist, &cur,
+				0, &tmp_logflags, XFS_DATA_FORK);
+		*logflagsp |= tmp_logflags;
+		if (error)
+			goto done;
 	}
-	if (logflags)
-		xfs_trans_log_inode(tp, ip, logflags);
-	if (error)
-		goto error2;
-	if (!xfs_sb_version_hasattr(&mp->m_sb) ||
-	   (!xfs_sb_version_hasattr2(&mp->m_sb) && version == 2)) {
-		__int64_t sbfields = 0;
 
-		spin_lock(&mp->m_sb_lock);
-		if (!xfs_sb_version_hasattr(&mp->m_sb)) {
-			xfs_sb_version_addattr(&mp->m_sb);
-			sbfields |= XFS_SB_VERSIONNUM;
-		}
-		if (!xfs_sb_version_hasattr2(&mp->m_sb) && version == 2) {
-			xfs_sb_version_addattr2(&mp->m_sb);
-			sbfields |= (XFS_SB_VERSIONNUM | XFS_SB_FEATURES2);
-		}
-		if (sbfields) {
-			spin_unlock(&mp->m_sb_lock);
-			xfs_mod_sb(tp, sbfields);
-		} else
-			spin_unlock(&mp->m_sb_lock);
+	/* clear out the allocated field, done with it now in any case. */
+	if (cur) {
+		cur->bc_private.b.allocated = 0;
+		*curp = cur;
 	}
 
-	error = xfs_bmap_finish(&tp, &flist, &committed);
-	if (error)
-		goto error2;
-	return xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
-error2:
-	xfs_bmap_cancel(&flist);
-error1:
-	xfs_iunlock(ip, XFS_ILOCK_EXCL);
-error0:
-	xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT);
+	xfs_bmap_check_leaf_extents(*curp, ip, XFS_DATA_FORK);
+done:
+	*logflagsp |= rval;
 	return error;
+#undef	LEFT
+#undef	RIGHT
+#undef	PREV
 }
 
 /*
- * Add the extent to the list of extents to be free at transaction end.
- * The list is maintained sorted (by block number).
+ * Convert a hole to a delayed allocation.
  */
-/* ARGSUSED */
-void
-xfs_bmap_add_free(
-	xfs_fsblock_t		bno,		/* fs block number of extent */
-	xfs_filblks_t		len,		/* length of extent */
-	xfs_bmap_free_t		*flist,		/* list of extents */
-	xfs_mount_t		*mp)		/* mount point structure */
+STATIC void
+xfs_bmap_add_extent_hole_delay(
+	xfs_inode_t		*ip,	/* incore inode pointer */
+	xfs_extnum_t		*idx,	/* extent number to update/insert */
+	xfs_bmbt_irec_t		*new)	/* new data to add to file extents */
 {
-	xfs_bmap_free_item_t	*cur;		/* current (next) element */
-	xfs_bmap_free_item_t	*new;		/* new element */
-	xfs_bmap_free_item_t	*prev;		/* previous element */
-#ifdef DEBUG
-	xfs_agnumber_t		agno;
-	xfs_agblock_t		agbno;
-
-	ASSERT(bno != NULLFSBLOCK);
-	ASSERT(len > 0);
-	ASSERT(len <= MAXEXTLEN);
-	ASSERT(!isnullstartblock(bno));
-	agno = XFS_FSB_TO_AGNO(mp, bno);
-	agbno = XFS_FSB_TO_AGBNO(mp, bno);
-	ASSERT(agno < mp->m_sb.sb_agcount);
-	ASSERT(agbno < mp->m_sb.sb_agblocks);
-	ASSERT(len < mp->m_sb.sb_agblocks);
-	ASSERT(agbno + len <= mp->m_sb.sb_agblocks);
-#endif
-	ASSERT(xfs_bmap_free_item_zone != NULL);
-	new = kmem_zone_alloc(xfs_bmap_free_item_zone, KM_SLEEP);
-	new->xbfi_startblock = bno;
-	new->xbfi_blockcount = (xfs_extlen_t)len;
-	for (prev = NULL, cur = flist->xbf_first;
-	     cur != NULL;
-	     prev = cur, cur = cur->xbfi_next) {
-		if (cur->xbfi_startblock >= bno)
-			break;
-	}
-	if (prev)
-		prev->xbfi_next = new;
-	else
-		flist->xbf_first = new;
-	new->xbfi_next = cur;
-	flist->xbf_count++;
-}
+	xfs_ifork_t		*ifp;	/* inode fork pointer */
+	xfs_bmbt_irec_t		left;	/* left neighbor extent entry */
+	xfs_filblks_t		newlen=0;	/* new indirect size */
+	xfs_filblks_t		oldlen=0;	/* old indirect size */
+	xfs_bmbt_irec_t		right;	/* right neighbor extent entry */
+	int			state;  /* state bits, accessed thru macros */
+	xfs_filblks_t		temp=0;	/* temp for indirect calculations */
 
-/*
- * Compute and fill in the value of the maximum depth of a bmap btree
- * in this filesystem.  Done once, during mount.
- */
-void
-xfs_bmap_compute_maxlevels(
-	xfs_mount_t	*mp,		/* file system mount structure */
-	int		whichfork)	/* data or attr fork */
-{
-	int		level;		/* btree level */
-	uint		maxblocks;	/* max blocks at this level */
-	uint		maxleafents;	/* max leaf entries possible */
-	int		maxrootrecs;	/* max records in root block */
-	int		minleafrecs;	/* min records in leaf block */
-	int		minnoderecs;	/* min records in node block */
-	int		sz;		/* root block size */
+	ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
+	state = 0;
+	ASSERT(isnullstartblock(new->br_startblock));
 
 	/*
-	 * The maximum number of extents in a file, hence the maximum
-	 * number of leaf entries, is controlled by the type of di_nextents
-	 * (a signed 32-bit number, xfs_extnum_t), or by di_anextents
-	 * (a signed 16-bit number, xfs_aextnum_t).
-	 *
-	 * Note that we can no longer assume that if we are in ATTR1 that
-	 * the fork offset of all the inodes will be
-	 * (xfs_default_attroffset(ip) >> 3) because we could have mounted
-	 * with ATTR2 and then mounted back with ATTR1, keeping the
-	 * di_forkoff's fixed but probably at various positions. Therefore,
-	 * for both ATTR1 and ATTR2 we have to assume the worst case scenario
-	 * of a minimum size available.
+	 * Check and set flags if this segment has a left neighbor
 	 */
-	if (whichfork == XFS_DATA_FORK) {
-		maxleafents = MAXEXTNUM;
-		sz = XFS_BMDR_SPACE_CALC(MINDBTPTRS);
-	} else {
-		maxleafents = MAXAEXTNUM;
-		sz = XFS_BMDR_SPACE_CALC(MINABTPTRS);
-	}
-	maxrootrecs = xfs_bmdr_maxrecs(mp, sz, 0);
-	minleafrecs = mp->m_bmap_dmnr[0];
-	minnoderecs = mp->m_bmap_dmnr[1];
-	maxblocks = (maxleafents + minleafrecs - 1) / minleafrecs;
-	for (level = 1; maxblocks > 1; level++) {
-		if (maxblocks <= maxrootrecs)
-			maxblocks = 1;
-		else
-			maxblocks = (maxblocks + minnoderecs - 1) / minnoderecs;
+	if (*idx > 0) {
+		state |= BMAP_LEFT_VALID;
+		xfs_bmbt_get_all(xfs_iext_get_ext(ifp, *idx - 1), &left);
+
+		if (isnullstartblock(left.br_startblock))
+			state |= BMAP_LEFT_DELAY;
 	}
-	mp->m_bm_maxlevels[whichfork] = level;
-}
 
-/*
- * Routine to be called at transaction's end by xfs_bmapi, xfs_bunmapi
- * caller.  Frees all the extents that need freeing, which must be done
- * last due to locking considerations.  We never free any extents in
- * the first transaction.
- *
- * Return 1 if the given transaction was committed and a new one
- * started, and 0 otherwise in the committed parameter.
- */
-int						/* error */
-xfs_bmap_finish(
-	xfs_trans_t		**tp,		/* transaction pointer addr */
-	xfs_bmap_free_t		*flist,		/* i/o: list extents to free */
-	int			*committed)	/* xact committed or not */
-{
-	xfs_efd_log_item_t	*efd;		/* extent free data */
-	xfs_efi_log_item_t	*efi;		/* extent free intention */
-	int			error;		/* error return value */
-	xfs_bmap_free_item_t	*free;		/* free extent item */
-	unsigned int		logres;		/* new log reservation */
-	unsigned int		logcount;	/* new log count */
-	xfs_mount_t		*mp;		/* filesystem mount structure */
-	xfs_bmap_free_item_t	*next;		/* next item on free list */
-	xfs_trans_t		*ntp;		/* new transaction pointer */
+	/*
+	 * Check and set flags if the current (right) segment exists.
+	 * If it doesn't exist, we're converting the hole at end-of-file.
+	 */
+	if (*idx < ip->i_df.if_bytes / (uint)sizeof(xfs_bmbt_rec_t)) {
+		state |= BMAP_RIGHT_VALID;
+		xfs_bmbt_get_all(xfs_iext_get_ext(ifp, *idx), &right);
 
-	ASSERT((*tp)->t_flags & XFS_TRANS_PERM_LOG_RES);
-	if (flist->xbf_count == 0) {
-		*committed = 0;
-		return 0;
+		if (isnullstartblock(right.br_startblock))
+			state |= BMAP_RIGHT_DELAY;
 	}
-	ntp = *tp;
-	efi = xfs_trans_get_efi(ntp, flist->xbf_count);
-	for (free = flist->xbf_first; free; free = free->xbfi_next)
-		xfs_trans_log_efi_extent(ntp, efi, free->xbfi_startblock,
-			free->xbfi_blockcount);
-	logres = ntp->t_log_res;
-	logcount = ntp->t_log_count;
-	ntp = xfs_trans_dup(*tp);
-	error = xfs_trans_commit(*tp, 0);
-	*tp = ntp;
-	*committed = 1;
+
 	/*
-	 * We have a new transaction, so we should return committed=1,
-	 * even though we're returning an error.
+	 * Set contiguity flags on the left and right neighbors.
+	 * Don't let extents get too large, even if the pieces are contiguous.
 	 */
-	if (error)
-		return error;
+	if ((state & BMAP_LEFT_VALID) && (state & BMAP_LEFT_DELAY) &&
+	    left.br_startoff + left.br_blockcount == new->br_startoff &&
+	    left.br_blockcount + new->br_blockcount <= MAXEXTLEN)
+		state |= BMAP_LEFT_CONTIG;
+
+	if ((state & BMAP_RIGHT_VALID) && (state & BMAP_RIGHT_DELAY) &&
+	    new->br_startoff + new->br_blockcount == right.br_startoff &&
+	    new->br_blockcount + right.br_blockcount <= MAXEXTLEN &&
+	    (!(state & BMAP_LEFT_CONTIG) ||
+	     (left.br_blockcount + new->br_blockcount +
+	      right.br_blockcount <= MAXEXTLEN)))
+		state |= BMAP_RIGHT_CONTIG;
 
 	/*
-	 * transaction commit worked ok so we can drop the extra ticket
-	 * reference that we gained in xfs_trans_dup()
+	 * Switch out based on the contiguity flags.
 	 */
-	xfs_log_ticket_put(ntp->t_ticket);
+	switch (state & (BMAP_LEFT_CONTIG | BMAP_RIGHT_CONTIG)) {
+	case BMAP_LEFT_CONTIG | BMAP_RIGHT_CONTIG:
+		/*
+		 * New allocation is contiguous with delayed allocations
+		 * on the left and on the right.
+		 * Merge all three into a single extent record.
+		 */
+		--*idx;
+		temp = left.br_blockcount + new->br_blockcount +
+			right.br_blockcount;
 
-	if ((error = xfs_trans_reserve(ntp, 0, logres, 0, XFS_TRANS_PERM_LOG_RES,
-			logcount)))
-		return error;
-	efd = xfs_trans_get_efd(ntp, efi, flist->xbf_count);
-	for (free = flist->xbf_first; free != NULL; free = next) {
-		next = free->xbfi_next;
-		if ((error = xfs_free_extent(ntp, free->xbfi_startblock,
-				free->xbfi_blockcount))) {
-			/*
-			 * The bmap free list will be cleaned up at a
-			 * higher level.  The EFI will be canceled when
-			 * this transaction is aborted.
-			 * Need to force shutdown here to make sure it
-			 * happens, since this transaction may not be
-			 * dirty yet.
-			 */
-			mp = ntp->t_mountp;
-			if (!XFS_FORCED_SHUTDOWN(mp))
-				xfs_force_shutdown(mp,
-						   (error == EFSCORRUPTED) ?
-						   SHUTDOWN_CORRUPT_INCORE :
-						   SHUTDOWN_META_IO_ERROR);
-			return error;
-		}
-		xfs_trans_log_efd_extent(ntp, efd, free->xbfi_startblock,
-			free->xbfi_blockcount);
-		xfs_bmap_del_free(flist, NULL, free);
-	}
-	return 0;
-}
+		trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_);
+		xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, *idx), temp);
+		oldlen = startblockval(left.br_startblock) +
+			startblockval(new->br_startblock) +
+			startblockval(right.br_startblock);
+		newlen = xfs_bmap_worst_indlen(ip, temp);
+		xfs_bmbt_set_startblock(xfs_iext_get_ext(ifp, *idx),
+			nullstartblock((int)newlen));
+		trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_);
 
-/*
- * Free up any items left in the list.
- */
-void
-xfs_bmap_cancel(
-	xfs_bmap_free_t		*flist)	/* list of bmap_free_items */
-{
-	xfs_bmap_free_item_t	*free;	/* free list item */
-	xfs_bmap_free_item_t	*next;
+		xfs_iext_remove(ip, *idx + 1, 1, state);
+		break;
 
-	if (flist->xbf_count == 0)
-		return;
-	ASSERT(flist->xbf_first != NULL);
-	for (free = flist->xbf_first; free; free = next) {
-		next = free->xbfi_next;
-		xfs_bmap_del_free(flist, NULL, free);
-	}
-	ASSERT(flist->xbf_count == 0);
-}
+	case BMAP_LEFT_CONTIG:
+		/*
+		 * New allocation is contiguous with a delayed allocation
+		 * on the left.
+		 * Merge the new allocation with the left neighbor.
+		 */
+		--*idx;
+		temp = left.br_blockcount + new->br_blockcount;
 
-/*
- * Returns the file-relative block number of the first unused block(s)
- * in the file with at least "len" logically contiguous blocks free.
- * This is the lowest-address hole if the file has holes, else the first block
- * past the end of file.
- * Return 0 if the file is currently local (in-inode).
- */
-int						/* error */
-xfs_bmap_first_unused(
-	xfs_trans_t	*tp,			/* transaction pointer */
-	xfs_inode_t	*ip,			/* incore inode */
-	xfs_extlen_t	len,			/* size of hole to find */
-	xfs_fileoff_t	*first_unused,		/* unused block */
-	int		whichfork)		/* data or attr fork */
-{
-	int		error;			/* error return value */
-	int		idx;			/* extent record index */
-	xfs_ifork_t	*ifp;			/* inode fork pointer */
-	xfs_fileoff_t	lastaddr;		/* last block number seen */
-	xfs_fileoff_t	lowest;			/* lowest useful block */
-	xfs_fileoff_t	max;			/* starting useful block */
-	xfs_fileoff_t	off;			/* offset for this block */
-	xfs_extnum_t	nextents;		/* number of extent entries */
+		trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_);
+		xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, *idx), temp);
+		oldlen = startblockval(left.br_startblock) +
+			startblockval(new->br_startblock);
+		newlen = xfs_bmap_worst_indlen(ip, temp);
+		xfs_bmbt_set_startblock(xfs_iext_get_ext(ifp, *idx),
+			nullstartblock((int)newlen));
+		trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_);
+		break;
 
-	ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE ||
-	       XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS ||
-	       XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL);
-	if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) {
-		*first_unused = 0;
-		return 0;
+	case BMAP_RIGHT_CONTIG:
+		/*
+		 * New allocation is contiguous with a delayed allocation
+		 * on the right.
+		 * Merge the new allocation with the right neighbor.
+		 */
+		trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_);
+		temp = new->br_blockcount + right.br_blockcount;
+		oldlen = startblockval(new->br_startblock) +
+			startblockval(right.br_startblock);
+		newlen = xfs_bmap_worst_indlen(ip, temp);
+		xfs_bmbt_set_allf(xfs_iext_get_ext(ifp, *idx),
+			new->br_startoff,
+			nullstartblock((int)newlen), temp, right.br_state);
+		trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_);
+		break;
+
+	case 0:
+		/*
+		 * New allocation is not contiguous with another
+		 * delayed allocation.
+		 * Insert a new entry.
+		 */
+		oldlen = newlen = 0;
+		xfs_iext_insert(ip, *idx, 1, new, state);
+		break;
 	}
-	ifp = XFS_IFORK_PTR(ip, whichfork);
-	if (!(ifp->if_flags & XFS_IFEXTENTS) &&
-	    (error = xfs_iread_extents(tp, ip, whichfork)))
-		return error;
-	lowest = *first_unused;
-	nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
-	for (idx = 0, lastaddr = 0, max = lowest; idx < nextents; idx++) {
-		xfs_bmbt_rec_host_t *ep = xfs_iext_get_ext(ifp, idx);
-		off = xfs_bmbt_get_startoff(ep);
+	if (oldlen != newlen) {
+		ASSERT(oldlen > newlen);
+		xfs_icsb_modify_counters(ip->i_mount, XFS_SBS_FDBLOCKS,
+			(int64_t)(oldlen - newlen), 0);
 		/*
-		 * See if the hole before this extent will work.
+		 * Nothing to do for disk quota accounting here.
 		 */
-		if (off >= lowest + len && off - max >= len) {
-			*first_unused = max;
-			return 0;
-		}
-		lastaddr = off + xfs_bmbt_get_blockcount(ep);
-		max = XFS_FILEOFF_MAX(lastaddr, lowest);
 	}
-	*first_unused = max;
-	return 0;
 }
 
 /*
- * Returns the file-relative block number of the last block + 1 before
- * last_block (input value) in the file.
- * This is not based on i_size, it is based on the extent records.
- * Returns 0 for local files, as they do not have extent records.
+ * Convert a hole to a real allocation.
  */
-int						/* error */
-xfs_bmap_last_before(
-	xfs_trans_t	*tp,			/* transaction pointer */
-	xfs_inode_t	*ip,			/* incore inode */
-	xfs_fileoff_t	*last_block,		/* last block */
-	int		whichfork)		/* data or attr fork */
+STATIC int				/* error */
+xfs_bmap_add_extent_hole_real(
+	struct xfs_bmalloca	*bma,
+	int			whichfork)
 {
-	xfs_fileoff_t	bno;			/* input file offset */
-	int		eof;			/* hit end of file */
-	xfs_bmbt_rec_host_t *ep;		/* pointer to last extent */
-	int		error;			/* error return value */
-	xfs_bmbt_irec_t	got;			/* current extent value */
-	xfs_ifork_t	*ifp;			/* inode fork pointer */
-	xfs_extnum_t	lastx;			/* last extent used */
-	xfs_bmbt_irec_t	prev;			/* previous extent value */
-
-	if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE &&
-	    XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
-	    XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL)
-	       return XFS_ERROR(EIO);
-	if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) {
-		*last_block = 0;
-		return 0;
-	}
-	ifp = XFS_IFORK_PTR(ip, whichfork);
-	if (!(ifp->if_flags & XFS_IFEXTENTS) &&
-	    (error = xfs_iread_extents(tp, ip, whichfork)))
-		return error;
-	bno = *last_block - 1;
-	ep = xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got,
-		&prev);
-	if (eof || xfs_bmbt_get_startoff(ep) > bno) {
-		if (prev.br_startoff == NULLFILEOFF)
-			*last_block = 0;
-		else
-			*last_block = prev.br_startoff + prev.br_blockcount;
-	}
-	/*
-	 * Otherwise *last_block is already the right answer.
-	 */
-	return 0;
-}
+	struct xfs_bmbt_irec	*new = &bma->got;
+	int			error;	/* error return value */
+	int			i;	/* temp state */
+	xfs_ifork_t		*ifp;	/* inode fork pointer */
+	xfs_bmbt_irec_t		left;	/* left neighbor extent entry */
+	xfs_bmbt_irec_t		right;	/* right neighbor extent entry */
+	int			rval=0;	/* return value (logging flags) */
+	int			state;	/* state bits, accessed thru macros */
 
-STATIC int
-xfs_bmap_last_extent(
-	struct xfs_trans	*tp,
-	struct xfs_inode	*ip,
-	int			whichfork,
-	struct xfs_bmbt_irec	*rec,
-	int			*is_empty)
-{
-	struct xfs_ifork	*ifp = XFS_IFORK_PTR(ip, whichfork);
-	int			error;
-	int			nextents;
+	ifp = XFS_IFORK_PTR(bma->ip, whichfork);
 
-	if (!(ifp->if_flags & XFS_IFEXTENTS)) {
-		error = xfs_iread_extents(tp, ip, whichfork);
-		if (error)
-			return error;
-	}
+	ASSERT(bma->idx >= 0);
+	ASSERT(bma->idx <= ifp->if_bytes / sizeof(struct xfs_bmbt_rec));
+	ASSERT(!isnullstartblock(new->br_startblock));
+	ASSERT(!bma->cur ||
+	       !(bma->cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL));
 
-	nextents = ifp->if_bytes / sizeof(xfs_bmbt_rec_t);
-	if (nextents == 0) {
-		*is_empty = 1;
-		return 0;
-	}
+	XFS_STATS_INC(xs_add_exlist);
 
-	xfs_bmbt_get_all(xfs_iext_get_ext(ifp, nextents - 1), rec);
-	*is_empty = 0;
-	return 0;
-}
+	state = 0;
+	if (whichfork == XFS_ATTR_FORK)
+		state |= BMAP_ATTRFORK;
 
-/*
- * Check the last inode extent to determine whether this allocation will result
- * in blocks being allocated at the end of the file. When we allocate new data
- * blocks at the end of the file which do not start at the previous data block,
- * we will try to align the new blocks at stripe unit boundaries.
- *
- * Returns 0 in bma->aeof if the file (fork) is empty as any new write will be
- * at, or past the EOF.
- */
-STATIC int
-xfs_bmap_isaeof(
-	struct xfs_bmalloca	*bma,
-	int			whichfork)
-{
-	struct xfs_bmbt_irec	rec;
-	int			is_empty;
-	int			error;
+	/*
+	 * Check and set flags if this segment has a left neighbor.
+	 */
+	if (bma->idx > 0) {
+		state |= BMAP_LEFT_VALID;
+		xfs_bmbt_get_all(xfs_iext_get_ext(ifp, bma->idx - 1), &left);
+		if (isnullstartblock(left.br_startblock))
+			state |= BMAP_LEFT_DELAY;
+	}
 
-	bma->aeof = 0;
-	error = xfs_bmap_last_extent(NULL, bma->ip, whichfork, &rec,
-				     &is_empty);
-	if (error || is_empty)
-		return error;
+	/*
+	 * Check and set flags if this segment has a current value.
+	 * Not true if we're inserting into the "hole" at eof.
+	 */
+	if (bma->idx < ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t)) {
+		state |= BMAP_RIGHT_VALID;
+		xfs_bmbt_get_all(xfs_iext_get_ext(ifp, bma->idx), &right);
+		if (isnullstartblock(right.br_startblock))
+			state |= BMAP_RIGHT_DELAY;
+	}
 
 	/*
-	 * Check if we are allocation or past the last extent, or at least into
-	 * the last delayed allocated extent.
+	 * We're inserting a real allocation between "left" and "right".
+	 * Set the contiguity flags.  Don't let extents get too large.
 	 */
-	bma->aeof = bma->offset >= rec.br_startoff + rec.br_blockcount ||
-		(bma->offset >= rec.br_startoff &&
-		 isnullstartblock(rec.br_startblock));
-	return 0;
-}
+	if ((state & BMAP_LEFT_VALID) && !(state & BMAP_LEFT_DELAY) &&
+	    left.br_startoff + left.br_blockcount == new->br_startoff &&
+	    left.br_startblock + left.br_blockcount == new->br_startblock &&
+	    left.br_state == new->br_state &&
+	    left.br_blockcount + new->br_blockcount <= MAXEXTLEN)
+		state |= BMAP_LEFT_CONTIG;
 
-/*
- * Check if the endoff is outside the last extent. If so the caller will grow
- * the allocation to a stripe unit boundary.  All offsets are considered outside
- * the end of file for an empty fork, so 1 is returned in *eof in that case.
- */
-int
-xfs_bmap_eof(
-	struct xfs_inode	*ip,
-	xfs_fileoff_t		endoff,
-	int			whichfork,
-	int			*eof)
-{
-	struct xfs_bmbt_irec	rec;
-	int			error;
+	if ((state & BMAP_RIGHT_VALID) && !(state & BMAP_RIGHT_DELAY) &&
+	    new->br_startoff + new->br_blockcount == right.br_startoff &&
+	    new->br_startblock + new->br_blockcount == right.br_startblock &&
+	    new->br_state == right.br_state &&
+	    new->br_blockcount + right.br_blockcount <= MAXEXTLEN &&
+	    (!(state & BMAP_LEFT_CONTIG) ||
+	     left.br_blockcount + new->br_blockcount +
+	     right.br_blockcount <= MAXEXTLEN))
+		state |= BMAP_RIGHT_CONTIG;
 
-	error = xfs_bmap_last_extent(NULL, ip, whichfork, &rec, eof);
-	if (error || *eof)
-		return error;
+	error = 0;
+	/*
+	 * Select which case we're in here, and implement it.
+	 */
+	switch (state & (BMAP_LEFT_CONTIG | BMAP_RIGHT_CONTIG)) {
+	case BMAP_LEFT_CONTIG | BMAP_RIGHT_CONTIG:
+		/*
+		 * New allocation is contiguous with real allocations on the
+		 * left and on the right.
+		 * Merge all three into a single extent record.
+		 */
+		--bma->idx;
+		trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_);
+		xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, bma->idx),
+			left.br_blockcount + new->br_blockcount +
+			right.br_blockcount);
+		trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_);
 
-	*eof = endoff >= rec.br_startoff + rec.br_blockcount;
-	return 0;
-}
+		xfs_iext_remove(bma->ip, bma->idx + 1, 1, state);
 
-/*
- * Returns the file-relative block number of the first block past eof in
- * the file.  This is not based on i_size, it is based on the extent records.
- * Returns 0 for local files, as they do not have extent records.
- */
-int
-xfs_bmap_last_offset(
-	struct xfs_trans	*tp,
-	struct xfs_inode	*ip,
-	xfs_fileoff_t		*last_block,
-	int			whichfork)
-{
-	struct xfs_bmbt_irec	rec;
-	int			is_empty;
-	int			error;
+		XFS_IFORK_NEXT_SET(bma->ip, whichfork,
+			XFS_IFORK_NEXTENTS(bma->ip, whichfork) - 1);
+		if (bma->cur == NULL) {
+			rval = XFS_ILOG_CORE | xfs_ilog_fext(whichfork);
+		} else {
+			rval = XFS_ILOG_CORE;
+			error = xfs_bmbt_lookup_eq(bma->cur, right.br_startoff,
+					right.br_startblock, right.br_blockcount,
+					&i);
+			if (error)
+				goto done;
+			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+			error = xfs_btree_delete(bma->cur, &i);
+			if (error)
+				goto done;
+			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+			error = xfs_btree_decrement(bma->cur, 0, &i);
+			if (error)
+				goto done;
+			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+			error = xfs_bmbt_update(bma->cur, left.br_startoff,
+					left.br_startblock,
+					left.br_blockcount +
+						new->br_blockcount +
+						right.br_blockcount,
+					left.br_state);
+			if (error)
+				goto done;
+		}
+		break;
 
-	*last_block = 0;
+	case BMAP_LEFT_CONTIG:
+		/*
+		 * New allocation is contiguous with a real allocation
+		 * on the left.
+		 * Merge the new allocation with the left neighbor.
+		 */
+		--bma->idx;
+		trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_);
+		xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, bma->idx),
+			left.br_blockcount + new->br_blockcount);
+		trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_);
 
-	if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL)
-		return 0;
+		if (bma->cur == NULL) {
+			rval = xfs_ilog_fext(whichfork);
+		} else {
+			rval = 0;
+			error = xfs_bmbt_lookup_eq(bma->cur, left.br_startoff,
+					left.br_startblock, left.br_blockcount,
+					&i);
+			if (error)
+				goto done;
+			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+			error = xfs_bmbt_update(bma->cur, left.br_startoff,
+					left.br_startblock,
+					left.br_blockcount +
+						new->br_blockcount,
+					left.br_state);
+			if (error)
+				goto done;
+		}
+		break;
 
-	if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE &&
-	    XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS)
-	       return XFS_ERROR(EIO);
+	case BMAP_RIGHT_CONTIG:
+		/*
+		 * New allocation is contiguous with a real allocation
+		 * on the right.
+		 * Merge the new allocation with the right neighbor.
+		 */
+		trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_);
+		xfs_bmbt_set_allf(xfs_iext_get_ext(ifp, bma->idx),
+			new->br_startoff, new->br_startblock,
+			new->br_blockcount + right.br_blockcount,
+			right.br_state);
+		trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_);
 
-	error = xfs_bmap_last_extent(NULL, ip, whichfork, &rec, &is_empty);
-	if (error || is_empty)
-		return error;
+		if (bma->cur == NULL) {
+			rval = xfs_ilog_fext(whichfork);
+		} else {
+			rval = 0;
+			error = xfs_bmbt_lookup_eq(bma->cur,
+					right.br_startoff,
+					right.br_startblock,
+					right.br_blockcount, &i);
+			if (error)
+				goto done;
+			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+			error = xfs_bmbt_update(bma->cur, new->br_startoff,
+					new->br_startblock,
+					new->br_blockcount +
+						right.br_blockcount,
+					right.br_state);
+			if (error)
+				goto done;
+		}
+		break;
 
-	*last_block = rec.br_startoff + rec.br_blockcount;
-	return 0;
-}
+	case 0:
+		/*
+		 * New allocation is not contiguous with another
+		 * real allocation.
+		 * Insert a new entry.
+		 */
+		xfs_iext_insert(bma->ip, bma->idx, 1, new, state);
+		XFS_IFORK_NEXT_SET(bma->ip, whichfork,
+			XFS_IFORK_NEXTENTS(bma->ip, whichfork) + 1);
+		if (bma->cur == NULL) {
+			rval = XFS_ILOG_CORE | xfs_ilog_fext(whichfork);
+		} else {
+			rval = XFS_ILOG_CORE;
+			error = xfs_bmbt_lookup_eq(bma->cur,
+					new->br_startoff,
+					new->br_startblock,
+					new->br_blockcount, &i);
+			if (error)
+				goto done;
+			XFS_WANT_CORRUPTED_GOTO(i == 0, done);
+			bma->cur->bc_rec.b.br_state = new->br_state;
+			error = xfs_btree_insert(bma->cur, &i);
+			if (error)
+				goto done;
+			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+		}
+		break;
+	}
 
-/*
- * Returns whether the selected fork of the inode has exactly one
- * block or not.  For the data fork we check this matches di_size,
- * implying the file's range is 0..bsize-1.
- */
-int					/* 1=>1 block, 0=>otherwise */
-xfs_bmap_one_block(
-	xfs_inode_t	*ip,		/* incore inode */
-	int		whichfork)	/* data or attr fork */
-{
-	xfs_bmbt_rec_host_t *ep;	/* ptr to fork's extent */
-	xfs_ifork_t	*ifp;		/* inode fork pointer */
-	int		rval;		/* return value */
-	xfs_bmbt_irec_t	s;		/* internal version of extent */
+	/* convert to a btree if necessary */
+	if (xfs_bmap_needs_btree(bma->ip, whichfork)) {
+		int	tmp_logflags;	/* partial log flag return val */
 
-#ifndef DEBUG
-	if (whichfork == XFS_DATA_FORK)
-		return XFS_ISIZE(ip) == ip->i_mount->m_sb.sb_blocksize;
-#endif	/* !DEBUG */
-	if (XFS_IFORK_NEXTENTS(ip, whichfork) != 1)
-		return 0;
-	if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS)
-		return 0;
-	ifp = XFS_IFORK_PTR(ip, whichfork);
-	ASSERT(ifp->if_flags & XFS_IFEXTENTS);
-	ep = xfs_iext_get_ext(ifp, 0);
-	xfs_bmbt_get_all(ep, &s);
-	rval = s.br_startoff == 0 && s.br_blockcount == 1;
-	if (rval && whichfork == XFS_DATA_FORK)
-		ASSERT(XFS_ISIZE(ip) == ip->i_mount->m_sb.sb_blocksize);
-	return rval;
-}
+		ASSERT(bma->cur == NULL);
+		error = xfs_bmap_extents_to_btree(bma->tp, bma->ip,
+				bma->firstblock, bma->flist, &bma->cur,
+				0, &tmp_logflags, whichfork);
+		bma->logflags |= tmp_logflags;
+		if (error)
+			goto done;
+	}
 
-STATIC int
-xfs_bmap_sanity_check(
-	struct xfs_mount	*mp,
-	struct xfs_buf		*bp,
-	int			level)
-{
-	struct xfs_btree_block  *block = XFS_BUF_TO_BLOCK(bp);
+	/* clear out the allocated field, done with it now in any case. */
+	if (bma->cur)
+		bma->cur->bc_private.b.allocated = 0;
 
-	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])
-		return 0;
-	return 1;
+	xfs_bmap_check_leaf_extents(bma->cur, bma->ip, whichfork);
+done:
+	bma->logflags |= rval;
+	return error;
 }
 
 /*
- * Read in the extents to if_extents.
- * All inode fields are set up by caller, we just traverse the btree
- * and copy the records in. If the file system cannot contain unwritten
- * extents, the records are checked for no "state" flags.
+ * Functions used in the extent read, allocate and remove paths
  */
-int					/* error */
-xfs_bmap_read_extents(
-	xfs_trans_t		*tp,	/* transaction pointer */
-	xfs_inode_t		*ip,	/* incore inode */
-	int			whichfork) /* data or attr fork */
+
+/*
+ * Adjust the size of the new extent based on di_extsize and rt extsize.
+ */
+STATIC int
+xfs_bmap_extsize_align(
+	xfs_mount_t	*mp,
+	xfs_bmbt_irec_t	*gotp,		/* next extent pointer */
+	xfs_bmbt_irec_t	*prevp,		/* previous extent pointer */
+	xfs_extlen_t	extsz,		/* align to this extent size */
+	int		rt,		/* is this a realtime inode? */
+	int		eof,		/* is extent at end-of-file? */
+	int		delay,		/* creating delalloc extent? */
+	int		convert,	/* overwriting unwritten extent? */
+	xfs_fileoff_t	*offp,		/* in/out: aligned offset */
+	xfs_extlen_t	*lenp)		/* in/out: aligned length */
 {
-	struct xfs_btree_block	*block;	/* current btree block */
-	xfs_fsblock_t		bno;	/* block # of "block" */
-	xfs_buf_t		*bp;	/* buffer for "block" */
-	int			error;	/* error return value */
-	xfs_exntfmt_t		exntf;	/* XFS_EXTFMT_NOSTATE, if checking */
-	xfs_extnum_t		i, j;	/* index into the extents list */
-	xfs_ifork_t		*ifp;	/* fork structure */
-	int			level;	/* btree level, for checking */
-	xfs_mount_t		*mp;	/* file system mount structure */
-	__be64			*pp;	/* pointer to block address */
-	/* REFERENCED */
-	xfs_extnum_t		room;	/* number of entries there's room for */
+	xfs_fileoff_t	orig_off;	/* original offset */
+	xfs_extlen_t	orig_alen;	/* original length */
+	xfs_fileoff_t	orig_end;	/* original off+len */
+	xfs_fileoff_t	nexto;		/* next file offset */
+	xfs_fileoff_t	prevo;		/* previous file offset */
+	xfs_fileoff_t	align_off;	/* temp for offset */
+	xfs_extlen_t	align_alen;	/* temp for length */
+	xfs_extlen_t	temp;		/* temp for calculations */
+
+	if (convert)
+		return 0;
+
+	orig_off = align_off = *offp;
+	orig_alen = align_alen = *lenp;
+	orig_end = orig_off + orig_alen;
 
-	bno = NULLFSBLOCK;
-	mp = ip->i_mount;
-	ifp = XFS_IFORK_PTR(ip, whichfork);
-	exntf = (whichfork != XFS_DATA_FORK) ? XFS_EXTFMT_NOSTATE :
-					XFS_EXTFMT_INODE(ip);
-	block = ifp->if_broot;
 	/*
-	 * Root level must use BMAP_BROOT_PTR_ADDR macro to get ptr out.
+	 * If this request overlaps an existing extent, then don't
+	 * attempt to perform any additional alignment.
 	 */
-	level = be16_to_cpu(block->bb_level);
-	ASSERT(level > 0);
-	pp = XFS_BMAP_BROOT_PTR_ADDR(mp, block, 1, ifp->if_broot_bytes);
-	bno = be64_to_cpu(*pp);
-	ASSERT(bno != NULLDFSBNO);
-	ASSERT(XFS_FSB_TO_AGNO(mp, bno) < mp->m_sb.sb_agcount);
-	ASSERT(XFS_FSB_TO_AGBNO(mp, bno) < mp->m_sb.sb_agblocks);
+	if (!delay && !eof &&
+	    (orig_off >= gotp->br_startoff) &&
+	    (orig_end <= gotp->br_startoff + gotp->br_blockcount)) {
+		return 0;
+	}
+
 	/*
-	 * Go down the tree until leaf level is reached, following the first
-	 * pointer (leftmost) at each level.
+	 * If the file offset is unaligned vs. the extent size
+	 * we need to align it.  This will be possible unless
+	 * the file was previously written with a kernel that didn't
+	 * perform this alignment, or if a truncate shot us in the
+	 * foot.
 	 */
-	while (level-- > 0) {
-		error = xfs_btree_read_bufl(mp, tp, bno, 0, &bp,
-				XFS_BMAP_BTREE_REF, &xfs_bmbt_buf_ops);
-		if (error)
-			return error;
-		block = XFS_BUF_TO_BLOCK(bp);
-		XFS_WANT_CORRUPTED_GOTO(
-			xfs_bmap_sanity_check(mp, bp, level),
-			error0);
-		if (level == 0)
-			break;
-		pp = XFS_BMBT_PTR_ADDR(mp, block, 1, mp->m_bmap_dmxr[1]);
-		bno = be64_to_cpu(*pp);
-		XFS_WANT_CORRUPTED_GOTO(XFS_FSB_SANITY_CHECK(mp, bno), error0);
-		xfs_trans_brelse(tp, bp);
+	temp = do_mod(orig_off, extsz);
+	if (temp) {
+		align_alen += temp;
+		align_off -= temp;
 	}
 	/*
-	 * Here with bp and block set to the leftmost leaf node in the tree.
+	 * Same adjustment for the end of the requested area.
 	 */
-	room = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
-	i = 0;
+	if ((temp = (align_alen % extsz))) {
+		align_alen += extsz - temp;
+	}
 	/*
-	 * Loop over all leaf nodes.  Copy information to the extent records.
+	 * If the previous block overlaps with this proposed allocation
+	 * then move the start forward without adjusting the length.
 	 */
-	for (;;) {
-		xfs_bmbt_rec_t	*frp;
-		xfs_fsblock_t	nextbno;
-		xfs_extnum_t	num_recs;
-		xfs_extnum_t	start;
+	if (prevp->br_startoff != NULLFILEOFF) {
+		if (prevp->br_startblock == HOLESTARTBLOCK)
+			prevo = prevp->br_startoff;
+		else
+			prevo = prevp->br_startoff + prevp->br_blockcount;
+	} else
+		prevo = 0;
+	if (align_off != orig_off && align_off < prevo)
+		align_off = prevo;
+	/*
+	 * If the next block overlaps with this proposed allocation
+	 * then move the start back without adjusting the length,
+	 * but not before offset 0.
+	 * This may of course make the start overlap previous block,
+	 * and if we hit the offset 0 limit then the next block
+	 * can still overlap too.
+	 */
+	if (!eof && gotp->br_startoff != NULLFILEOFF) {
+		if ((delay && gotp->br_startblock == HOLESTARTBLOCK) ||
+		    (!delay && gotp->br_startblock == DELAYSTARTBLOCK))
+			nexto = gotp->br_startoff + gotp->br_blockcount;
+		else
+			nexto = gotp->br_startoff;
+	} else
+		nexto = NULLFILEOFF;
+	if (!eof &&
+	    align_off + align_alen != orig_end &&
+	    align_off + align_alen > nexto)
+		align_off = nexto > align_alen ? nexto - align_alen : 0;
+	/*
+	 * If we're now overlapping the next or previous extent that
+	 * means we can't fit an extsz piece in this hole.  Just move
+	 * the start forward to the first valid spot and set
+	 * the length so we hit the end.
+	 */
+	if (align_off != orig_off && align_off < prevo)
+		align_off = prevo;
+	if (align_off + align_alen != orig_end &&
+	    align_off + align_alen > nexto &&
+	    nexto != NULLFILEOFF) {
+		ASSERT(nexto > prevo);
+		align_alen = nexto - align_off;
+	}
 
-		num_recs = xfs_btree_get_numrecs(block);
-		if (unlikely(i + num_recs > room)) {
-			ASSERT(i + num_recs <= room);
-			xfs_warn(ip->i_mount,
-				"corrupt dinode %Lu, (btree extents).",
-				(unsigned long long) ip->i_ino);
-			XFS_CORRUPTION_ERROR("xfs_bmap_read_extents(1)",
-				XFS_ERRLEVEL_LOW, ip->i_mount, block);
-			goto error0;
-		}
-		XFS_WANT_CORRUPTED_GOTO(
-			xfs_bmap_sanity_check(mp, bp, 0),
-			error0);
+	/*
+	 * If realtime, and the result isn't a multiple of the realtime
+	 * extent size we need to remove blocks until it is.
+	 */
+	if (rt && (temp = (align_alen % mp->m_sb.sb_rextsize))) {
 		/*
-		 * Read-ahead the next leaf block, if any.
+		 * We're not covering the original request, or
+		 * we won't be able to once we fix the length.
 		 */
-		nextbno = be64_to_cpu(block->bb_u.l.bb_rightsib);
-		if (nextbno != NULLFSBLOCK)
-			xfs_btree_reada_bufl(mp, nextbno, 1,
-					     &xfs_bmbt_buf_ops);
+		if (orig_off < align_off ||
+		    orig_end > align_off + align_alen ||
+		    align_alen - temp < orig_alen)
+			return XFS_ERROR(EINVAL);
 		/*
-		 * Copy records into the extent records.
+		 * Try to fix it by moving the start up.
 		 */
-		frp = XFS_BMBT_REC_ADDR(mp, block, 1);
-		start = i;
-		for (j = 0; j < num_recs; j++, i++, frp++) {
-			xfs_bmbt_rec_host_t *trp = xfs_iext_get_ext(ifp, i);
-			trp->l0 = be64_to_cpu(frp->l0);
-			trp->l1 = be64_to_cpu(frp->l1);
+		if (align_off + temp <= orig_off) {
+			align_alen -= temp;
+			align_off += temp;
 		}
-		if (exntf == XFS_EXTFMT_NOSTATE) {
-			/*
-			 * Check all attribute bmap btree records and
-			 * any "older" data bmap btree records for a
-			 * set bit in the "extent flag" position.
-			 */
-			if (unlikely(xfs_check_nostate_extents(ifp,
-					start, num_recs))) {
-				XFS_ERROR_REPORT("xfs_bmap_read_extents(2)",
-						 XFS_ERRLEVEL_LOW,
-						 ip->i_mount);
-				goto error0;
-			}
+		/*
+		 * Try to fix it by moving the end in.
+		 */
+		else if (align_off + align_alen - temp >= orig_end)
+			align_alen -= temp;
+		/*
+		 * Set the start to the minimum then trim the length.
+		 */
+		else {
+			align_alen -= orig_off - align_off;
+			align_off = orig_off;
+			align_alen -= align_alen % mp->m_sb.sb_rextsize;
 		}
-		xfs_trans_brelse(tp, bp);
-		bno = nextbno;
 		/*
-		 * If we've reached the end, stop.
+		 * Result doesn't cover the request, fail it.
 		 */
-		if (bno == NULLFSBLOCK)
-			break;
-		error = xfs_btree_read_bufl(mp, tp, bno, 0, &bp,
-				XFS_BMAP_BTREE_REF, &xfs_bmbt_buf_ops);
-		if (error)
-			return error;
-		block = XFS_BUF_TO_BLOCK(bp);
+		if (orig_off < align_off || orig_end > align_off + align_alen)
+			return XFS_ERROR(EINVAL);
+	} else {
+		ASSERT(orig_off >= align_off);
+		ASSERT(orig_end <= align_off + align_alen);
 	}
-	ASSERT(i == (ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t)));
-	ASSERT(i == XFS_IFORK_NEXTENTS(ip, whichfork));
-	XFS_BMAP_TRACE_EXLIST(ip, i, whichfork);
+
+#ifdef DEBUG
+	if (!eof && gotp->br_startoff != NULLFILEOFF)
+		ASSERT(align_off + align_alen <= gotp->br_startoff);
+	if (prevp->br_startoff != NULLFILEOFF)
+		ASSERT(align_off >= prevp->br_startoff + prevp->br_blockcount);
+#endif
+
+	*lenp = align_alen;
+	*offp = align_off;
 	return 0;
-error0:
-	xfs_trans_brelse(tp, bp);
-	return XFS_ERROR(EFSCORRUPTED);
 }
 
-#ifdef DEBUG
-/*
- * Add bmap trace insert entries for all the contents of the extent records.
- */
-void
-xfs_bmap_trace_exlist(
-	xfs_inode_t	*ip,		/* incore inode pointer */
-	xfs_extnum_t	cnt,		/* count of entries in the list */
-	int		whichfork,	/* data or attr fork */
-	unsigned long	caller_ip)
-{
-	xfs_extnum_t	idx;		/* extent record index */
-	xfs_ifork_t	*ifp;		/* inode fork pointer */
-	int		state = 0;
-
-	if (whichfork == XFS_ATTR_FORK)
-		state |= BMAP_ATTRFORK;
-
-	ifp = XFS_IFORK_PTR(ip, whichfork);
-	ASSERT(cnt == (ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t)));
-	for (idx = 0; idx < cnt; idx++)
-		trace_xfs_extlist(ip, idx, whichfork, caller_ip);
-}
+#define XFS_ALLOC_GAP_UNITS	4
 
-/*
- * Validate that the bmbt_irecs being returned from bmapi are valid
- * given the callers original parameters.  Specifically check the
- * ranges of the returned irecs to ensure that they only extent beyond
- * the given parameters if the XFS_BMAPI_ENTIRE flag was set.
- */
 STATIC void
-xfs_bmap_validate_ret(
-	xfs_fileoff_t		bno,
-	xfs_filblks_t		len,
-	int			flags,
-	xfs_bmbt_irec_t		*mval,
-	int			nmap,
-	int			ret_nmap)
+xfs_bmap_adjacent(
+	xfs_bmalloca_t	*ap)		/* bmap alloc argument struct */
 {
-	int			i;		/* index to map values */
+	xfs_fsblock_t	adjust;		/* adjustment to block numbers */
+	xfs_agnumber_t	fb_agno;	/* ag number of ap->firstblock */
+	xfs_mount_t	*mp;		/* mount point structure */
+	int		nullfb;		/* true if ap->firstblock isn't set */
+	int		rt;		/* true if inode is realtime */
 
-	ASSERT(ret_nmap <= nmap);
+#define	ISVALID(x,y)	\
+	(rt ? \
+		(x) < mp->m_sb.sb_rblocks : \
+		XFS_FSB_TO_AGNO(mp, x) == XFS_FSB_TO_AGNO(mp, y) && \
+		XFS_FSB_TO_AGNO(mp, x) < mp->m_sb.sb_agcount && \
+		XFS_FSB_TO_AGBNO(mp, x) < mp->m_sb.sb_agblocks)
 
-	for (i = 0; i < ret_nmap; i++) {
-		ASSERT(mval[i].br_blockcount > 0);
-		if (!(flags & XFS_BMAPI_ENTIRE)) {
-			ASSERT(mval[i].br_startoff >= bno);
-			ASSERT(mval[i].br_blockcount <= len);
-			ASSERT(mval[i].br_startoff + mval[i].br_blockcount <=
-			       bno + len);
-		} else {
-			ASSERT(mval[i].br_startoff < bno + len);
-			ASSERT(mval[i].br_startoff + mval[i].br_blockcount >
-			       bno);
+	mp = ap->ip->i_mount;
+	nullfb = *ap->firstblock == NULLFSBLOCK;
+	rt = XFS_IS_REALTIME_INODE(ap->ip) && ap->userdata;
+	fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, *ap->firstblock);
+	/*
+	 * If allocating at eof, and there's a previous real block,
+	 * try to use its last block as our starting point.
+	 */
+	if (ap->eof && ap->prev.br_startoff != NULLFILEOFF &&
+	    !isnullstartblock(ap->prev.br_startblock) &&
+	    ISVALID(ap->prev.br_startblock + ap->prev.br_blockcount,
+		    ap->prev.br_startblock)) {
+		ap->blkno = ap->prev.br_startblock + ap->prev.br_blockcount;
+		/*
+		 * Adjust for the gap between prevp and us.
+		 */
+		adjust = ap->offset -
+			(ap->prev.br_startoff + ap->prev.br_blockcount);
+		if (adjust &&
+		    ISVALID(ap->blkno + adjust, ap->prev.br_startblock))
+			ap->blkno += adjust;
+	}
+	/*
+	 * If not at eof, then compare the two neighbor blocks.
+	 * Figure out whether either one gives us a good starting point,
+	 * and pick the better one.
+	 */
+	else if (!ap->eof) {
+		xfs_fsblock_t	gotbno;		/* right side block number */
+		xfs_fsblock_t	gotdiff=0;	/* right side difference */
+		xfs_fsblock_t	prevbno;	/* left side block number */
+		xfs_fsblock_t	prevdiff=0;	/* left side difference */
+
+		/*
+		 * If there's a previous (left) block, select a requested
+		 * start block based on it.
+		 */
+		if (ap->prev.br_startoff != NULLFILEOFF &&
+		    !isnullstartblock(ap->prev.br_startblock) &&
+		    (prevbno = ap->prev.br_startblock +
+			       ap->prev.br_blockcount) &&
+		    ISVALID(prevbno, ap->prev.br_startblock)) {
+			/*
+			 * Calculate gap to end of previous block.
+			 */
+			adjust = prevdiff = ap->offset -
+				(ap->prev.br_startoff +
+				 ap->prev.br_blockcount);
+			/*
+			 * Figure the startblock based on the previous block's
+			 * end and the gap size.
+			 * Heuristic!
+			 * If the gap is large relative to the piece we're
+			 * allocating, or using it gives us an invalid block
+			 * number, then just use the end of the previous block.
+			 */
+			if (prevdiff <= XFS_ALLOC_GAP_UNITS * ap->length &&
+			    ISVALID(prevbno + prevdiff,
+				    ap->prev.br_startblock))
+				prevbno += adjust;
+			else
+				prevdiff += adjust;
+			/*
+			 * If the firstblock forbids it, can't use it,
+			 * must use default.
+			 */
+			if (!rt && !nullfb &&
+			    XFS_FSB_TO_AGNO(mp, prevbno) != fb_agno)
+				prevbno = NULLFSBLOCK;
 		}
-		ASSERT(i == 0 ||
-		       mval[i - 1].br_startoff + mval[i - 1].br_blockcount ==
-		       mval[i].br_startoff);
-		ASSERT(mval[i].br_startblock != DELAYSTARTBLOCK &&
-		       mval[i].br_startblock != HOLESTARTBLOCK);
-		ASSERT(mval[i].br_state == XFS_EXT_NORM ||
-		       mval[i].br_state == XFS_EXT_UNWRITTEN);
+		/*
+		 * No previous block or can't follow it, just default.
+		 */
+		else
+			prevbno = NULLFSBLOCK;
+		/*
+		 * If there's a following (right) block, select a requested
+		 * start block based on it.
+		 */
+		if (!isnullstartblock(ap->got.br_startblock)) {
+			/*
+			 * Calculate gap to start of next block.
+			 */
+			adjust = gotdiff = ap->got.br_startoff - ap->offset;
+			/*
+			 * Figure the startblock based on the next block's
+			 * start and the gap size.
+			 */
+			gotbno = ap->got.br_startblock;
+			/*
+			 * Heuristic!
+			 * If the gap is large relative to the piece we're
+			 * allocating, or using it gives us an invalid block
+			 * number, then just use the start of the next block
+			 * offset by our length.
+			 */
+			if (gotdiff <= XFS_ALLOC_GAP_UNITS * ap->length &&
+			    ISVALID(gotbno - gotdiff, gotbno))
+				gotbno -= adjust;
+			else if (ISVALID(gotbno - ap->length, gotbno)) {
+				gotbno -= ap->length;
+				gotdiff += adjust - ap->length;
+			} else
+				gotdiff += adjust;
+			/*
+			 * If the firstblock forbids it, can't use it,
+			 * must use default.
+			 */
+			if (!rt && !nullfb &&
+			    XFS_FSB_TO_AGNO(mp, gotbno) != fb_agno)
+				gotbno = NULLFSBLOCK;
+		}
+		/*
+		 * No next block, just default.
+		 */
+		else
+			gotbno = NULLFSBLOCK;
+		/*
+		 * If both valid, pick the better one, else the only good
+		 * one, else ap->blkno is already set (to 0 or the inode block).
+		 */
+		if (prevbno != NULLFSBLOCK && gotbno != NULLFSBLOCK)
+			ap->blkno = prevdiff <= gotdiff ? prevbno : gotbno;
+		else if (prevbno != NULLFSBLOCK)
+			ap->blkno = prevbno;
+		else if (gotbno != NULLFSBLOCK)
+			ap->blkno = gotbno;
 	}
+#undef ISVALID
 }
-#endif /* DEBUG */
-
 
-/*
- * Trim the returned map to the required bounds
- */
-STATIC void
-xfs_bmapi_trim_map(
-	struct xfs_bmbt_irec	*mval,
-	struct xfs_bmbt_irec	*got,
-	xfs_fileoff_t		*bno,
-	xfs_filblks_t		len,
-	xfs_fileoff_t		obno,
-	xfs_fileoff_t		end,
-	int			n,
-	int			flags)
+STATIC int
+xfs_bmap_rtalloc(
+	xfs_bmalloca_t	*ap)		/* bmap alloc argument struct */
 {
-	if ((flags & XFS_BMAPI_ENTIRE) ||
-	    got->br_startoff + got->br_blockcount <= obno) {
-		*mval = *got;
-		if (isnullstartblock(got->br_startblock))
-			mval->br_startblock = DELAYSTARTBLOCK;
-		return;
-	}
+	xfs_alloctype_t	atype = 0;	/* type for allocation routines */
+	int		error;		/* error return value */
+	xfs_mount_t	*mp;		/* mount point structure */
+	xfs_extlen_t	prod = 0;	/* product factor for allocators */
+	xfs_extlen_t	ralen = 0;	/* realtime allocation length */
+	xfs_extlen_t	align;		/* minimum allocation alignment */
+	xfs_rtblock_t	rtb;
+
+	mp = ap->ip->i_mount;
+	align = xfs_get_extsz_hint(ap->ip);
+	prod = align / mp->m_sb.sb_rextsize;
+	error = xfs_bmap_extsize_align(mp, &ap->got, &ap->prev,
+					align, 1, ap->eof, 0,
+					ap->conv, &ap->offset, &ap->length);
+	if (error)
+		return error;
+	ASSERT(ap->length);
+	ASSERT(ap->length % mp->m_sb.sb_rextsize == 0);
 
-	if (obno > *bno)
-		*bno = obno;
-	ASSERT((*bno >= obno) || (n == 0));
-	ASSERT(*bno < end);
-	mval->br_startoff = *bno;
-	if (isnullstartblock(got->br_startblock))
-		mval->br_startblock = DELAYSTARTBLOCK;
-	else
-		mval->br_startblock = got->br_startblock +
-					(*bno - got->br_startoff);
 	/*
-	 * Return the minimum of what we got and what we asked for for
-	 * the length.  We can use the len variable here because it is
-	 * modified below and we could have been there before coming
-	 * here if the first part of the allocation didn't overlap what
-	 * was asked for.
+	 * If the offset & length are not perfectly aligned
+	 * then kill prod, it will just get us in trouble.
 	 */
-	mval->br_blockcount = XFS_FILBLKS_MIN(end - *bno,
-			got->br_blockcount - (*bno - got->br_startoff));
-	mval->br_state = got->br_state;
-	ASSERT(mval->br_blockcount <= len);
-	return;
-}
-
-/*
- * Update and validate the extent map to return
- */
-STATIC void
-xfs_bmapi_update_map(
-	struct xfs_bmbt_irec	**map,
-	xfs_fileoff_t		*bno,
-	xfs_filblks_t		*len,
-	xfs_fileoff_t		obno,
-	xfs_fileoff_t		end,
-	int			*n,
-	int			flags)
-{
-	xfs_bmbt_irec_t	*mval = *map;
-
-	ASSERT((flags & XFS_BMAPI_ENTIRE) ||
-	       ((mval->br_startoff + mval->br_blockcount) <= end));
-	ASSERT((flags & XFS_BMAPI_ENTIRE) || (mval->br_blockcount <= *len) ||
-	       (mval->br_startoff < obno));
-
-	*bno = mval->br_startoff + mval->br_blockcount;
-	*len = end - *bno;
-	if (*n > 0 && mval->br_startoff == mval[-1].br_startoff) {
-		/* update previous map with new information */
-		ASSERT(mval->br_startblock == mval[-1].br_startblock);
-		ASSERT(mval->br_blockcount > mval[-1].br_blockcount);
-		ASSERT(mval->br_state == mval[-1].br_state);
-		mval[-1].br_blockcount = mval->br_blockcount;
-		mval[-1].br_state = mval->br_state;
-	} else if (*n > 0 && mval->br_startblock != DELAYSTARTBLOCK &&
-		   mval[-1].br_startblock != DELAYSTARTBLOCK &&
-		   mval[-1].br_startblock != HOLESTARTBLOCK &&
-		   mval->br_startblock == mval[-1].br_startblock +
-					  mval[-1].br_blockcount &&
-		   ((flags & XFS_BMAPI_IGSTATE) ||
-			mval[-1].br_state == mval->br_state)) {
-		ASSERT(mval->br_startoff ==
-		       mval[-1].br_startoff + mval[-1].br_blockcount);
-		mval[-1].br_blockcount += mval->br_blockcount;
-	} else if (*n > 0 &&
-		   mval->br_startblock == DELAYSTARTBLOCK &&
-		   mval[-1].br_startblock == DELAYSTARTBLOCK &&
-		   mval->br_startoff ==
-		   mval[-1].br_startoff + mval[-1].br_blockcount) {
-		mval[-1].br_blockcount += mval->br_blockcount;
-		mval[-1].br_state = mval->br_state;
-	} else if (!((*n == 0) &&
-		     ((mval->br_startoff + mval->br_blockcount) <=
-		      obno))) {
-		mval++;
-		(*n)++;
-	}
-	*map = mval;
-}
-
-/*
- * Map file blocks to filesystem blocks without allocation.
- */
-int
-xfs_bmapi_read(
-	struct xfs_inode	*ip,
-	xfs_fileoff_t		bno,
-	xfs_filblks_t		len,
-	struct xfs_bmbt_irec	*mval,
-	int			*nmap,
-	int			flags)
-{
-	struct xfs_mount	*mp = ip->i_mount;
-	struct xfs_ifork	*ifp;
-	struct xfs_bmbt_irec	got;
-	struct xfs_bmbt_irec	prev;
-	xfs_fileoff_t		obno;
-	xfs_fileoff_t		end;
-	xfs_extnum_t		lastx;
-	int			error;
-	int			eof;
-	int			n = 0;
-	int			whichfork = (flags & XFS_BMAPI_ATTRFORK) ?
-						XFS_ATTR_FORK : XFS_DATA_FORK;
-
-	ASSERT(*nmap >= 1);
-	ASSERT(!(flags & ~(XFS_BMAPI_ATTRFORK|XFS_BMAPI_ENTIRE|
-			   XFS_BMAPI_IGSTATE)));
-
-	if (unlikely(XFS_TEST_ERROR(
-	    (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
-	     XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE),
-	     mp, XFS_ERRTAG_BMAPIFORMAT, XFS_RANDOM_BMAPIFORMAT))) {
-		XFS_ERROR_REPORT("xfs_bmapi_read", XFS_ERRLEVEL_LOW, mp);
-		return XFS_ERROR(EFSCORRUPTED);
-	}
-
-	if (XFS_FORCED_SHUTDOWN(mp))
-		return XFS_ERROR(EIO);
+	if (do_mod(ap->offset, align) || ap->length % align)
+		prod = 1;
+	/*
+	 * Set ralen to be the actual requested length in rtextents.
+	 */
+	ralen = ap->length / mp->m_sb.sb_rextsize;
+	/*
+	 * If the old value was close enough to MAXEXTLEN that
+	 * we rounded up to it, cut it back so it's valid again.
+	 * Note that if it's a really large request (bigger than
+	 * MAXEXTLEN), we don't hear about that number, and can't
+	 * adjust the starting point to match it.
+	 */
+	if (ralen * mp->m_sb.sb_rextsize >= MAXEXTLEN)
+		ralen = MAXEXTLEN / mp->m_sb.sb_rextsize;
 
-	XFS_STATS_INC(xs_blk_mapr);
+	/*
+	 * Lock out other modifications to the RT bitmap inode.
+	 */
+	xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL);
+	xfs_trans_ijoin(ap->tp, mp->m_rbmip, XFS_ILOCK_EXCL);
 
-	ifp = XFS_IFORK_PTR(ip, whichfork);
+	/*
+	 * If it's an allocation to an empty file at offset 0,
+	 * pick an extent that will space things out in the rt area.
+	 */
+	if (ap->eof && ap->offset == 0) {
+		xfs_rtblock_t uninitialized_var(rtx); /* realtime extent no */
 
-	if (!(ifp->if_flags & XFS_IFEXTENTS)) {
-		error = xfs_iread_extents(NULL, ip, whichfork);
+		error = xfs_rtpick_extent(mp, ap->tp, ralen, &rtx);
 		if (error)
 			return error;
+		ap->blkno = rtx * mp->m_sb.sb_rextsize;
+	} else {
+		ap->blkno = 0;
 	}
 
-	xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got, &prev);
-	end = bno + len;
-	obno = bno;
-
-	while (bno < end && n < *nmap) {
-		/* Reading past eof, act as though there's a hole up to end. */
-		if (eof)
-			got.br_startoff = end;
-		if (got.br_startoff > bno) {
-			/* Reading in a hole.  */
-			mval->br_startoff = bno;
-			mval->br_startblock = HOLESTARTBLOCK;
-			mval->br_blockcount =
-				XFS_FILBLKS_MIN(len, got.br_startoff - bno);
-			mval->br_state = XFS_EXT_NORM;
-			bno += mval->br_blockcount;
-			len -= mval->br_blockcount;
-			mval++;
-			n++;
-			continue;
-		}
-
-		/* set up the extent map to return. */
-		xfs_bmapi_trim_map(mval, &got, &bno, len, obno, end, n, flags);
-		xfs_bmapi_update_map(&mval, &bno, &len, obno, end, &n, flags);
-
-		/* If we're done, stop now. */
-		if (bno >= end || n >= *nmap)
-			break;
+	xfs_bmap_adjacent(ap);
 
-		/* Else go on to the next record. */
-		if (++lastx < ifp->if_bytes / sizeof(xfs_bmbt_rec_t))
-			xfs_bmbt_get_all(xfs_iext_get_ext(ifp, lastx), &got);
-		else
-			eof = 1;
+	/*
+	 * Realtime allocation, done through xfs_rtallocate_extent.
+	 */
+	atype = ap->blkno == 0 ?  XFS_ALLOCTYPE_ANY_AG : XFS_ALLOCTYPE_NEAR_BNO;
+	do_div(ap->blkno, mp->m_sb.sb_rextsize);
+	rtb = ap->blkno;
+	ap->length = ralen;
+	if ((error = xfs_rtallocate_extent(ap->tp, ap->blkno, 1, ap->length,
+				&ralen, atype, ap->wasdel, prod, &rtb)))
+		return error;
+	if (rtb == NULLFSBLOCK && prod > 1 &&
+	    (error = xfs_rtallocate_extent(ap->tp, ap->blkno, 1,
+					   ap->length, &ralen, atype,
+					   ap->wasdel, 1, &rtb)))
+		return error;
+	ap->blkno = rtb;
+	if (ap->blkno != NULLFSBLOCK) {
+		ap->blkno *= mp->m_sb.sb_rextsize;
+		ralen *= mp->m_sb.sb_rextsize;
+		ap->length = ralen;
+		ap->ip->i_d.di_nblocks += ralen;
+		xfs_trans_log_inode(ap->tp, ap->ip, XFS_ILOG_CORE);
+		if (ap->wasdel)
+			ap->ip->i_delayed_blks -= ralen;
+		/*
+		 * Adjust the disk quota also. This was reserved
+		 * earlier.
+		 */
+		xfs_trans_mod_dquot_byino(ap->tp, ap->ip,
+			ap->wasdel ? XFS_TRANS_DQ_DELRTBCOUNT :
+					XFS_TRANS_DQ_RTBCOUNT, (long) ralen);
+	} else {
+		ap->length = 0;
 	}
-	*nmap = n;
 	return 0;
 }
 
 STATIC int
-xfs_bmapi_reserve_delalloc(
-	struct xfs_inode	*ip,
-	xfs_fileoff_t		aoff,
-	xfs_filblks_t		len,
-	struct xfs_bmbt_irec	*got,
-	struct xfs_bmbt_irec	*prev,
-	xfs_extnum_t		*lastx,
-	int			eof)
+xfs_bmap_btalloc_nullfb(
+	struct xfs_bmalloca	*ap,
+	struct xfs_alloc_arg	*args,
+	xfs_extlen_t		*blen)
 {
-	struct xfs_mount	*mp = ip->i_mount;
-	struct xfs_ifork	*ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
-	xfs_extlen_t		alen;
-	xfs_extlen_t		indlen;
-	char			rt = XFS_IS_REALTIME_INODE(ip);
-	xfs_extlen_t		extsz;
+	struct xfs_mount	*mp = ap->ip->i_mount;
+	struct xfs_perag	*pag;
+	xfs_agnumber_t		ag, startag;
+	int			notinit = 0;
 	int			error;
 
-	alen = XFS_FILBLKS_MIN(len, MAXEXTLEN);
-	if (!eof)
-		alen = XFS_FILBLKS_MIN(alen, got->br_startoff - aoff);
-
-	/* Figure out the extent size, adjust alen */
-	extsz = xfs_get_extsz_hint(ip);
-	if (extsz) {
-		/*
-		 * Make sure we don't exceed a single extent length when we
-		 * align the extent by reducing length we are going to
-		 * allocate by the maximum amount extent size aligment may
-		 * require.
-		 */
-		alen = XFS_FILBLKS_MIN(len, MAXEXTLEN - (2 * extsz - 1));
-		error = xfs_bmap_extsize_align(mp, got, prev, extsz, rt, eof,
-					       1, 0, &aoff, &alen);
-		ASSERT(!error);
-	}
-
-	if (rt)
-		extsz = alen / mp->m_sb.sb_rextsize;
+	if (ap->userdata && xfs_inode_is_filestream(ap->ip))
+		args->type = XFS_ALLOCTYPE_NEAR_BNO;
+	else
+		args->type = XFS_ALLOCTYPE_START_BNO;
+	args->total = ap->total;
 
 	/*
-	 * Make a transaction-less quota reservation for delayed allocation
-	 * blocks.  This number gets adjusted later.  We return if we haven't
-	 * allocated blocks already inside this loop.
-	 */
-	error = xfs_trans_reserve_quota_nblks(NULL, ip, (long)alen, 0,
-			rt ? XFS_QMOPT_RES_RTBLKS : XFS_QMOPT_RES_REGBLKS);
-	if (error)
-		return error;
-
-	/*
-	 * Split changing sb for alen and indlen since they could be coming
-	 * from different places.
+	 * Search for an allocation group with a single extent large enough
+	 * for the request.  If one isn't found, then adjust the minimum
+	 * allocation size to the largest space found.
 	 */
-	indlen = (xfs_extlen_t)xfs_bmap_worst_indlen(ip, alen);
-	ASSERT(indlen > 0);
+	startag = ag = XFS_FSB_TO_AGNO(mp, args->fsbno);
+	if (startag == NULLAGNUMBER)
+		startag = ag = 0;
 
-	if (rt) {
-		error = xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS,
-					  -((int64_t)extsz), 0);
-	} else {
-		error = xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS,
-						 -((int64_t)alen), 0);
-	}
+	pag = xfs_perag_get(mp, ag);
+	while (*blen < args->maxlen) {
+		if (!pag->pagf_init) {
+			error = xfs_alloc_pagf_init(mp, args->tp, ag,
+						    XFS_ALLOC_FLAG_TRYLOCK);
+			if (error) {
+				xfs_perag_put(pag);
+				return error;
+			}
+		}
 
-	if (error)
-		goto out_unreserve_quota;
+		/*
+		 * See xfs_alloc_fix_freelist...
+		 */
+		if (pag->pagf_init) {
+			xfs_extlen_t	longest;
+			longest = xfs_alloc_longest_free_extent(mp, pag);
+			if (*blen < longest)
+				*blen = longest;
+		} else
+			notinit = 1;
 
-	error = xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS,
-					 -((int64_t)indlen), 0);
-	if (error)
-		goto out_unreserve_blocks;
+		if (xfs_inode_is_filestream(ap->ip)) {
+			if (*blen >= args->maxlen)
+				break;
 
+			if (ap->userdata) {
+				/*
+				 * If startag is an invalid AG, we've
+				 * come here once before and
+				 * xfs_filestream_new_ag picked the
+				 * best currently available.
+				 *
+				 * Don't continue looping, since we
+				 * could loop forever.
+				 */
+				if (startag == NULLAGNUMBER)
+					break;
 
-	ip->i_delayed_blks += alen;
+				error = xfs_filestream_new_ag(ap, &ag);
+				xfs_perag_put(pag);
+				if (error)
+					return error;
 
-	got->br_startoff = aoff;
-	got->br_startblock = nullstartblock(indlen);
-	got->br_blockcount = alen;
-	got->br_state = XFS_EXT_NORM;
-	xfs_bmap_add_extent_hole_delay(ip, lastx, got);
+				/* loop again to set 'blen'*/
+				startag = NULLAGNUMBER;
+				pag = xfs_perag_get(mp, ag);
+				continue;
+			}
+		}
+		if (++ag == mp->m_sb.sb_agcount)
+			ag = 0;
+		if (ag == startag)
+			break;
+		xfs_perag_put(pag);
+		pag = xfs_perag_get(mp, ag);
+	}
+	xfs_perag_put(pag);
 
 	/*
-	 * Update our extent pointer, given that xfs_bmap_add_extent_hole_delay
-	 * might have merged it into one of the neighbouring ones.
+	 * Since the above loop did a BUF_TRYLOCK, it is
+	 * possible that there is space for this request.
 	 */
-	xfs_bmbt_get_all(xfs_iext_get_ext(ifp, *lastx), got);
+	if (notinit || *blen < ap->minlen)
+		args->minlen = ap->minlen;
+	/*
+	 * If the best seen length is less than the request
+	 * length, use the best as the minimum.
+	 */
+	else if (*blen < args->maxlen)
+		args->minlen = *blen;
+	/*
+	 * Otherwise we've seen an extent as big as maxlen,
+	 * use that as the minimum.
+	 */
+	else
+		args->minlen = args->maxlen;
 
-	ASSERT(got->br_startoff <= aoff);
-	ASSERT(got->br_startoff + got->br_blockcount >= aoff + alen);
-	ASSERT(isnullstartblock(got->br_startblock));
-	ASSERT(got->br_state == XFS_EXT_NORM);
-	return 0;
+	/*
+	 * set the failure fallback case to look in the selected
+	 * AG as the stream may have moved.
+	 */
+	if (xfs_inode_is_filestream(ap->ip))
+		ap->blkno = args->fsbno = XFS_AGB_TO_FSB(mp, ag, 0);
 
-out_unreserve_blocks:
-	if (rt)
-		xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS, extsz, 0);
-	else
-		xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS, alen, 0);
-out_unreserve_quota:
-	if (XFS_IS_QUOTA_ON(mp))
-		xfs_trans_unreserve_quota_nblks(NULL, ip, (long)alen, 0, rt ?
-				XFS_QMOPT_RES_RTBLKS : XFS_QMOPT_RES_REGBLKS);
-	return error;
+	return 0;
 }
 
-/*
- * Map file blocks to filesystem blocks, adding delayed allocations as needed.
- */
-int
-xfs_bmapi_delay(
-	struct xfs_inode	*ip,	/* incore inode */
-	xfs_fileoff_t		bno,	/* starting file offs. mapped */
-	xfs_filblks_t		len,	/* length to map in file */
-	struct xfs_bmbt_irec	*mval,	/* output: map values */
-	int			*nmap,	/* i/o: mval size/count */
-	int			flags)	/* XFS_BMAPI_... */
+STATIC int
+xfs_bmap_btalloc(
+	xfs_bmalloca_t	*ap)		/* bmap alloc argument struct */
 {
-	struct xfs_mount	*mp = ip->i_mount;
-	struct xfs_ifork	*ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
-	struct xfs_bmbt_irec	got;	/* current file extent record */
-	struct xfs_bmbt_irec	prev;	/* previous file extent record */
-	xfs_fileoff_t		obno;	/* old block number (offset) */
-	xfs_fileoff_t		end;	/* end of mapped file region */
-	xfs_extnum_t		lastx;	/* last useful extent number */
-	int			eof;	/* we've hit the end of extents */
-	int			n = 0;	/* current extent index */
-	int			error = 0;
+	xfs_mount_t	*mp;		/* mount point structure */
+	xfs_alloctype_t	atype = 0;	/* type for allocation routines */
+	xfs_extlen_t	align;		/* minimum allocation alignment */
+	xfs_agnumber_t	fb_agno;	/* ag number of ap->firstblock */
+	xfs_agnumber_t	ag;
+	xfs_alloc_arg_t	args;
+	xfs_extlen_t	blen;
+	xfs_extlen_t	nextminlen = 0;
+	int		nullfb;		/* true if ap->firstblock isn't set */
+	int		isaligned;
+	int		tryagain;
+	int		error;
 
-	ASSERT(*nmap >= 1);
-	ASSERT(*nmap <= XFS_BMAP_MAX_NMAP);
-	ASSERT(!(flags & ~XFS_BMAPI_ENTIRE));
+	ASSERT(ap->length);
 
-	if (unlikely(XFS_TEST_ERROR(
-	    (XFS_IFORK_FORMAT(ip, XFS_DATA_FORK) != XFS_DINODE_FMT_EXTENTS &&
-	     XFS_IFORK_FORMAT(ip, XFS_DATA_FORK) != XFS_DINODE_FMT_BTREE),
-	     mp, XFS_ERRTAG_BMAPIFORMAT, XFS_RANDOM_BMAPIFORMAT))) {
-		XFS_ERROR_REPORT("xfs_bmapi_delay", XFS_ERRLEVEL_LOW, mp);
-		return XFS_ERROR(EFSCORRUPTED);
+	mp = ap->ip->i_mount;
+	align = ap->userdata ? xfs_get_extsz_hint(ap->ip) : 0;
+	if (unlikely(align)) {
+		error = xfs_bmap_extsize_align(mp, &ap->got, &ap->prev,
+						align, 0, ap->eof, 0, ap->conv,
+						&ap->offset, &ap->length);
+		ASSERT(!error);
+		ASSERT(ap->length);
 	}
+	nullfb = *ap->firstblock == NULLFSBLOCK;
+	fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, *ap->firstblock);
+	if (nullfb) {
+		if (ap->userdata && xfs_inode_is_filestream(ap->ip)) {
+			ag = xfs_filestream_lookup_ag(ap->ip);
+			ag = (ag != NULLAGNUMBER) ? ag : 0;
+			ap->blkno = XFS_AGB_TO_FSB(mp, ag, 0);
+		} else {
+			ap->blkno = XFS_INO_TO_FSB(mp, ap->ip->i_ino);
+		}
+	} else
+		ap->blkno = *ap->firstblock;
 
-	if (XFS_FORCED_SHUTDOWN(mp))
-		return XFS_ERROR(EIO);
+	xfs_bmap_adjacent(ap);
 
-	XFS_STATS_INC(xs_blk_mapw);
+	/*
+	 * If allowed, use ap->blkno; otherwise must use firstblock since
+	 * it's in the right allocation group.
+	 */
+	if (nullfb || XFS_FSB_TO_AGNO(mp, ap->blkno) == fb_agno)
+		;
+	else
+		ap->blkno = *ap->firstblock;
+	/*
+	 * Normal allocation, done through xfs_alloc_vextent.
+	 */
+	tryagain = isaligned = 0;
+	memset(&args, 0, sizeof(args));
+	args.tp = ap->tp;
+	args.mp = mp;
+	args.fsbno = ap->blkno;
 
-	if (!(ifp->if_flags & XFS_IFEXTENTS)) {
-		error = xfs_iread_extents(NULL, ip, XFS_DATA_FORK);
+	/* Trim the allocation back to the maximum an AG can fit. */
+	args.maxlen = MIN(ap->length, XFS_ALLOC_AG_MAX_USABLE(mp));
+	args.firstblock = *ap->firstblock;
+	blen = 0;
+	if (nullfb) {
+		error = xfs_bmap_btalloc_nullfb(ap, &args, &blen);
 		if (error)
 			return error;
+	} else if (ap->flist->xbf_low) {
+		if (xfs_inode_is_filestream(ap->ip))
+			args.type = XFS_ALLOCTYPE_FIRST_AG;
+		else
+			args.type = XFS_ALLOCTYPE_START_BNO;
+		args.total = args.minlen = ap->minlen;
+	} else {
+		args.type = XFS_ALLOCTYPE_NEAR_BNO;
+		args.total = ap->total;
+		args.minlen = ap->minlen;
 	}
-
-	xfs_bmap_search_extents(ip, bno, XFS_DATA_FORK, &eof, &lastx, &got, &prev);
-	end = bno + len;
-	obno = bno;
-
-	while (bno < end && n < *nmap) {
-		if (eof || got.br_startoff > bno) {
-			error = xfs_bmapi_reserve_delalloc(ip, bno, len, &got,
-							   &prev, &lastx, eof);
-			if (error) {
-				if (n == 0) {
-					*nmap = 0;
-					return error;
-				}
-				break;
-			}
-		}
-
-		/* set up the extent map to return. */
-		xfs_bmapi_trim_map(mval, &got, &bno, len, obno, end, n, flags);
-		xfs_bmapi_update_map(&mval, &bno, &len, obno, end, &n, flags);
-
-		/* If we're done, stop now. */
-		if (bno >= end || n >= *nmap)
-			break;
-
-		/* Else go on to the next record. */
-		prev = got;
-		if (++lastx < ifp->if_bytes / sizeof(xfs_bmbt_rec_t))
-			xfs_bmbt_get_all(xfs_iext_get_ext(ifp, lastx), &got);
-		else
-			eof = 1;
+	/* apply extent size hints if obtained earlier */
+	if (unlikely(align)) {
+		args.prod = align;
+		if ((args.mod = (xfs_extlen_t)do_mod(ap->offset, args.prod)))
+			args.mod = (xfs_extlen_t)(args.prod - args.mod);
+	} else if (mp->m_sb.sb_blocksize >= PAGE_CACHE_SIZE) {
+		args.prod = 1;
+		args.mod = 0;
+	} else {
+		args.prod = PAGE_CACHE_SIZE >> mp->m_sb.sb_blocklog;
+		if ((args.mod = (xfs_extlen_t)(do_mod(ap->offset, args.prod))))
+			args.mod = (xfs_extlen_t)(args.prod - args.mod);
 	}
-
-	*nmap = n;
-	return 0;
-}
-
-
-STATIC int
-__xfs_bmapi_allocate(
-	struct xfs_bmalloca	*bma)
-{
-	struct xfs_mount	*mp = bma->ip->i_mount;
-	int			whichfork = (bma->flags & XFS_BMAPI_ATTRFORK) ?
-						XFS_ATTR_FORK : XFS_DATA_FORK;
-	struct xfs_ifork	*ifp = XFS_IFORK_PTR(bma->ip, whichfork);
-	int			tmp_logflags = 0;
-	int			error;
-	int			rt;
-
-	ASSERT(bma->length > 0);
-
-	rt = (whichfork == XFS_DATA_FORK) && XFS_IS_REALTIME_INODE(bma->ip);
-
 	/*
-	 * For the wasdelay case, we could also just allocate the stuff asked
-	 * for in this bmap call but that wouldn't be as good.
+	 * If we are not low on available data blocks, and the
+	 * underlying logical volume manager is a stripe, and
+	 * the file offset is zero then try to allocate data
+	 * blocks on stripe unit boundary.
+	 * NOTE: ap->aeof is only set if the allocation length
+	 * is >= the stripe unit and the allocation offset is
+	 * at the end of file.
 	 */
-	if (bma->wasdel) {
-		bma->length = (xfs_extlen_t)bma->got.br_blockcount;
-		bma->offset = bma->got.br_startoff;
-		if (bma->idx != NULLEXTNUM && bma->idx) {
-			xfs_bmbt_get_all(xfs_iext_get_ext(ifp, bma->idx - 1),
-					 &bma->prev);
+	if (!ap->flist->xbf_low && ap->aeof) {
+		if (!ap->offset) {
+			args.alignment = mp->m_dalign;
+			atype = args.type;
+			isaligned = 1;
+			/*
+			 * Adjust for alignment
+			 */
+			if (blen > args.alignment && blen <= args.maxlen)
+				args.minlen = blen - args.alignment;
+			args.minalignslop = 0;
+		} else {
+			/*
+			 * First try an exact bno allocation.
+			 * If it fails then do a near or start bno
+			 * allocation with alignment turned on.
+			 */
+			atype = args.type;
+			tryagain = 1;
+			args.type = XFS_ALLOCTYPE_THIS_BNO;
+			args.alignment = 1;
+			/*
+			 * Compute the minlen+alignment for the
+			 * next case.  Set slop so that the value
+			 * of minlen+alignment+slop doesn't go up
+			 * between the calls.
+			 */
+			if (blen > mp->m_dalign && blen <= args.maxlen)
+				nextminlen = blen - mp->m_dalign;
+			else
+				nextminlen = args.minlen;
+			if (nextminlen + mp->m_dalign > args.minlen + 1)
+				args.minalignslop =
+					nextminlen + mp->m_dalign -
+					args.minlen - 1;
+			else
+				args.minalignslop = 0;
 		}
 	} else {
-		bma->length = XFS_FILBLKS_MIN(bma->length, MAXEXTLEN);
-		if (!bma->eof)
-			bma->length = XFS_FILBLKS_MIN(bma->length,
-					bma->got.br_startoff - bma->offset);
+		args.alignment = 1;
+		args.minalignslop = 0;
 	}
-
-	/*
-	 * Indicate if this is the first user data in the file, or just any
-	 * user data.
-	 */
-	if (!(bma->flags & XFS_BMAPI_METADATA)) {
-		bma->userdata = (bma->offset == 0) ?
-			XFS_ALLOC_INITIAL_USER_DATA : XFS_ALLOC_USERDATA;
+	args.minleft = ap->minleft;
+	args.wasdel = ap->wasdel;
+	args.isfl = 0;
+	args.userdata = ap->userdata;
+	if ((error = xfs_alloc_vextent(&args)))
+		return error;
+	if (tryagain && args.fsbno == NULLFSBLOCK) {
+		/*
+		 * Exact allocation failed. Now try with alignment
+		 * turned on.
+		 */
+		args.type = atype;
+		args.fsbno = ap->blkno;
+		args.alignment = mp->m_dalign;
+		args.minlen = nextminlen;
+		args.minalignslop = 0;
+		isaligned = 1;
+		if ((error = xfs_alloc_vextent(&args)))
+			return error;
 	}
-
-	bma->minlen = (bma->flags & XFS_BMAPI_CONTIG) ? bma->length : 1;
-
-	/*
-	 * Only want to do the alignment at the eof if it is userdata and
-	 * allocation length is larger than a stripe unit.
-	 */
-	if (mp->m_dalign && bma->length >= mp->m_dalign &&
-	    !(bma->flags & XFS_BMAPI_METADATA) && whichfork == XFS_DATA_FORK) {
-		error = xfs_bmap_isaeof(bma, whichfork);
-		if (error)
+	if (isaligned && args.fsbno == NULLFSBLOCK) {
+		/*
+		 * allocation failed, so turn off alignment and
+		 * try again.
+		 */
+		args.type = atype;
+		args.fsbno = ap->blkno;
+		args.alignment = 0;
+		if ((error = xfs_alloc_vextent(&args)))
 			return error;
 	}
-
-	error = xfs_bmap_alloc(bma);
-	if (error)
-		return error;
-
-	if (bma->flist->xbf_low)
-		bma->minleft = 0;
-	if (bma->cur)
-		bma->cur->bc_private.b.firstblock = *bma->firstblock;
-	if (bma->blkno == NULLFSBLOCK)
-		return 0;
-	if ((ifp->if_flags & XFS_IFBROOT) && !bma->cur) {
-		bma->cur = xfs_bmbt_init_cursor(mp, bma->tp, bma->ip, whichfork);
-		bma->cur->bc_private.b.firstblock = *bma->firstblock;
-		bma->cur->bc_private.b.flist = bma->flist;
+	if (args.fsbno == NULLFSBLOCK && nullfb &&
+	    args.minlen > ap->minlen) {
+		args.minlen = ap->minlen;
+		args.type = XFS_ALLOCTYPE_START_BNO;
+		args.fsbno = ap->blkno;
+		if ((error = xfs_alloc_vextent(&args)))
+			return error;
 	}
-	/*
-	 * Bump the number of extents we've allocated
-	 * in this call.
-	 */
-	bma->nallocs++;
-
-	if (bma->cur)
-		bma->cur->bc_private.b.flags =
-			bma->wasdel ? XFS_BTCUR_BPRV_WASDEL : 0;
-
-	bma->got.br_startoff = bma->offset;
-	bma->got.br_startblock = bma->blkno;
-	bma->got.br_blockcount = bma->length;
-	bma->got.br_state = XFS_EXT_NORM;
-
-	/*
-	 * A wasdelay extent has been initialized, so shouldn't be flagged
-	 * as unwritten.
-	 */
-	if (!bma->wasdel && (bma->flags & XFS_BMAPI_PREALLOC) &&
-	    xfs_sb_version_hasextflgbit(&mp->m_sb))
-		bma->got.br_state = XFS_EXT_UNWRITTEN;
-
-	if (bma->wasdel)
-		error = xfs_bmap_add_extent_delay_real(bma);
-	else
-		error = xfs_bmap_add_extent_hole_real(bma, whichfork);
-
-	bma->logflags |= tmp_logflags;
-	if (error)
-		return error;
-
-	/*
-	 * Update our extent pointer, given that xfs_bmap_add_extent_delay_real
-	 * or xfs_bmap_add_extent_hole_real might have merged it into one of
-	 * the neighbouring ones.
-	 */
-	xfs_bmbt_get_all(xfs_iext_get_ext(ifp, bma->idx), &bma->got);
+	if (args.fsbno == NULLFSBLOCK && nullfb) {
+		args.fsbno = 0;
+		args.type = XFS_ALLOCTYPE_FIRST_AG;
+		args.total = ap->minlen;
+		args.minleft = 0;
+		if ((error = xfs_alloc_vextent(&args)))
+			return error;
+		ap->flist->xbf_low = 1;
+	}
+	if (args.fsbno != NULLFSBLOCK) {
+		/*
+		 * check the allocation happened at the same or higher AG than
+		 * the first block that was allocated.
+		 */
+		ASSERT(*ap->firstblock == NULLFSBLOCK ||
+		       XFS_FSB_TO_AGNO(mp, *ap->firstblock) ==
+		       XFS_FSB_TO_AGNO(mp, args.fsbno) ||
+		       (ap->flist->xbf_low &&
+			XFS_FSB_TO_AGNO(mp, *ap->firstblock) <
+			XFS_FSB_TO_AGNO(mp, args.fsbno)));
 
-	ASSERT(bma->got.br_startoff <= bma->offset);
-	ASSERT(bma->got.br_startoff + bma->got.br_blockcount >=
-	       bma->offset + bma->length);
-	ASSERT(bma->got.br_state == XFS_EXT_NORM ||
-	       bma->got.br_state == XFS_EXT_UNWRITTEN);
+		ap->blkno = args.fsbno;
+		if (*ap->firstblock == NULLFSBLOCK)
+			*ap->firstblock = args.fsbno;
+		ASSERT(nullfb || fb_agno == args.agno ||
+		       (ap->flist->xbf_low && fb_agno < args.agno));
+		ap->length = args.len;
+		ap->ip->i_d.di_nblocks += args.len;
+		xfs_trans_log_inode(ap->tp, ap->ip, XFS_ILOG_CORE);
+		if (ap->wasdel)
+			ap->ip->i_delayed_blks -= args.len;
+		/*
+		 * Adjust the disk quota also. This was reserved
+		 * earlier.
+		 */
+		xfs_trans_mod_dquot_byino(ap->tp, ap->ip,
+			ap->wasdel ? XFS_TRANS_DQ_DELBCOUNT :
+					XFS_TRANS_DQ_BCOUNT,
+			(long) args.len);
+	} else {
+		ap->blkno = NULLFSBLOCK;
+		ap->length = 0;
+	}
 	return 0;
 }
 
-static void
-xfs_bmapi_allocate_worker(
-	struct work_struct	*work)
-{
-	struct xfs_bmalloca	*args = container_of(work,
-						struct xfs_bmalloca, work);
-	unsigned long		pflags;
-
-	/* we are in a transaction context here */
-	current_set_flags_nested(&pflags, PF_FSTRANS);
-
-	args->result = __xfs_bmapi_allocate(args);
-	complete(args->done);
-
-	current_restore_flags_nested(&pflags, PF_FSTRANS);
-}
-
 /*
- * Some allocation requests often come in with little stack to work on. Push
- * them off to a worker thread so there is lots of stack to use. Otherwise just
- * call directly to avoid the context switch overhead here.
+ * xfs_bmap_alloc is called by xfs_bmapi to allocate an extent for a file.
+ * It figures out where to ask the underlying allocator to put the new extent.
  */
-int
-xfs_bmapi_allocate(
-	struct xfs_bmalloca	*args)
+STATIC int
+xfs_bmap_alloc(
+	xfs_bmalloca_t	*ap)		/* bmap alloc argument struct */
 {
-	DECLARE_COMPLETION_ONSTACK(done);
-
-	if (!args->stack_switch)
-		return __xfs_bmapi_allocate(args);
-
-
-	args->done = &done;
-	INIT_WORK_ONSTACK(&args->work, xfs_bmapi_allocate_worker);
-	queue_work(xfs_alloc_wq, &args->work);
-	wait_for_completion(&done);
-	return args->result;
+	if (XFS_IS_REALTIME_INODE(ap->ip) && ap->userdata)
+		return xfs_bmap_rtalloc(ap);
+	return xfs_bmap_btalloc(ap);
 }
 
-STATIC int
-xfs_bmapi_convert_unwritten(
-	struct xfs_bmalloca	*bma,
+/*
+ * Trim the returned map to the required bounds
+ */
+STATIC void
+xfs_bmapi_trim_map(
 	struct xfs_bmbt_irec	*mval,
+	struct xfs_bmbt_irec	*got,
+	xfs_fileoff_t		*bno,
 	xfs_filblks_t		len,
+	xfs_fileoff_t		obno,
+	xfs_fileoff_t		end,
+	int			n,
 	int			flags)
 {
-	int			whichfork = (flags & XFS_BMAPI_ATTRFORK) ?
-						XFS_ATTR_FORK : XFS_DATA_FORK;
-	struct xfs_ifork	*ifp = XFS_IFORK_PTR(bma->ip, whichfork);
-	int			tmp_logflags = 0;
-	int			error;
-
-	/* check if we need to do unwritten->real conversion */
-	if (mval->br_state == XFS_EXT_UNWRITTEN &&
-	    (flags & XFS_BMAPI_PREALLOC))
-		return 0;
-
-	/* check if we need to do real->unwritten conversion */
-	if (mval->br_state == XFS_EXT_NORM &&
-	    (flags & (XFS_BMAPI_PREALLOC | XFS_BMAPI_CONVERT)) !=
-			(XFS_BMAPI_PREALLOC | XFS_BMAPI_CONVERT))
-		return 0;
+	if ((flags & XFS_BMAPI_ENTIRE) ||
+	    got->br_startoff + got->br_blockcount <= obno) {
+		*mval = *got;
+		if (isnullstartblock(got->br_startblock))
+			mval->br_startblock = DELAYSTARTBLOCK;
+		return;
+	}
 
+	if (obno > *bno)
+		*bno = obno;
+	ASSERT((*bno >= obno) || (n == 0));
+	ASSERT(*bno < end);
+	mval->br_startoff = *bno;
+	if (isnullstartblock(got->br_startblock))
+		mval->br_startblock = DELAYSTARTBLOCK;
+	else
+		mval->br_startblock = got->br_startblock +
+					(*bno - got->br_startoff);
 	/*
-	 * Modify (by adding) the state flag, if writing.
+	 * Return the minimum of what we got and what we asked for for
+	 * the length.  We can use the len variable here because it is
+	 * modified below and we could have been there before coming
+	 * here if the first part of the allocation didn't overlap what
+	 * was asked for.
 	 */
+	mval->br_blockcount = XFS_FILBLKS_MIN(end - *bno,
+			got->br_blockcount - (*bno - got->br_startoff));
+	mval->br_state = got->br_state;
 	ASSERT(mval->br_blockcount <= len);
-	if ((ifp->if_flags & XFS_IFBROOT) && !bma->cur) {
-		bma->cur = xfs_bmbt_init_cursor(bma->ip->i_mount, bma->tp,
-					bma->ip, whichfork);
-		bma->cur->bc_private.b.firstblock = *bma->firstblock;
-		bma->cur->bc_private.b.flist = bma->flist;
-	}
-	mval->br_state = (mval->br_state == XFS_EXT_UNWRITTEN)
-				? XFS_EXT_NORM : XFS_EXT_UNWRITTEN;
+	return;
+}
 
-	error = xfs_bmap_add_extent_unwritten_real(bma->tp, bma->ip, &bma->idx,
-			&bma->cur, mval, bma->firstblock, bma->flist,
-			&tmp_logflags);
-	bma->logflags |= tmp_logflags;
-	if (error)
-		return error;
+/*
+ * Update and validate the extent map to return
+ */
+STATIC void
+xfs_bmapi_update_map(
+	struct xfs_bmbt_irec	**map,
+	xfs_fileoff_t		*bno,
+	xfs_filblks_t		*len,
+	xfs_fileoff_t		obno,
+	xfs_fileoff_t		end,
+	int			*n,
+	int			flags)
+{
+	xfs_bmbt_irec_t	*mval = *map;
 
-	/*
-	 * Update our extent pointer, given that
-	 * xfs_bmap_add_extent_unwritten_real might have merged it into one
-	 * of the neighbouring ones.
-	 */
-	xfs_bmbt_get_all(xfs_iext_get_ext(ifp, bma->idx), &bma->got);
+	ASSERT((flags & XFS_BMAPI_ENTIRE) ||
+	       ((mval->br_startoff + mval->br_blockcount) <= end));
+	ASSERT((flags & XFS_BMAPI_ENTIRE) || (mval->br_blockcount <= *len) ||
+	       (mval->br_startoff < obno));
 
-	/*
-	 * We may have combined previously unwritten space with written space,
-	 * so generate another request.
-	 */
-	if (mval->br_blockcount < len)
-		return EAGAIN;
-	return 0;
+	*bno = mval->br_startoff + mval->br_blockcount;
+	*len = end - *bno;
+	if (*n > 0 && mval->br_startoff == mval[-1].br_startoff) {
+		/* update previous map with new information */
+		ASSERT(mval->br_startblock == mval[-1].br_startblock);
+		ASSERT(mval->br_blockcount > mval[-1].br_blockcount);
+		ASSERT(mval->br_state == mval[-1].br_state);
+		mval[-1].br_blockcount = mval->br_blockcount;
+		mval[-1].br_state = mval->br_state;
+	} else if (*n > 0 && mval->br_startblock != DELAYSTARTBLOCK &&
+		   mval[-1].br_startblock != DELAYSTARTBLOCK &&
+		   mval[-1].br_startblock != HOLESTARTBLOCK &&
+		   mval->br_startblock == mval[-1].br_startblock +
+					  mval[-1].br_blockcount &&
+		   ((flags & XFS_BMAPI_IGSTATE) ||
+			mval[-1].br_state == mval->br_state)) {
+		ASSERT(mval->br_startoff ==
+		       mval[-1].br_startoff + mval[-1].br_blockcount);
+		mval[-1].br_blockcount += mval->br_blockcount;
+	} else if (*n > 0 &&
+		   mval->br_startblock == DELAYSTARTBLOCK &&
+		   mval[-1].br_startblock == DELAYSTARTBLOCK &&
+		   mval->br_startoff ==
+		   mval[-1].br_startoff + mval[-1].br_blockcount) {
+		mval[-1].br_blockcount += mval->br_blockcount;
+		mval[-1].br_state = mval->br_state;
+	} else if (!((*n == 0) &&
+		     ((mval->br_startoff + mval->br_blockcount) <=
+		      obno))) {
+		mval++;
+		(*n)++;
+	}
+	*map = mval;
 }
 
 /*
- * Map file blocks to filesystem blocks, and allocate blocks or convert the
- * extent state if necessary.  Details behaviour is controlled by the flags
- * parameter.  Only allocates blocks from a single allocation group, to avoid
- * locking problems.
- *
- * The returned value in "firstblock" from the first call in a transaction
- * must be remembered and presented to subsequent calls in "firstblock".
- * An upper bound for the number of blocks to be allocated is supplied to
- * the first call in "total"; if no allocation group has that many free
- * blocks then the call will fail (return NULLFSBLOCK in "firstblock").
+ * Map file blocks to filesystem blocks without allocation.
  */
 int
-xfs_bmapi_write(
-	struct xfs_trans	*tp,		/* transaction pointer */
-	struct xfs_inode	*ip,		/* incore inode */
-	xfs_fileoff_t		bno,		/* starting file offs. mapped */
-	xfs_filblks_t		len,		/* length to map in file */
-	int			flags,		/* XFS_BMAPI_... */
-	xfs_fsblock_t		*firstblock,	/* first allocated block
-						   controls a.g. for allocs */
-	xfs_extlen_t		total,		/* total blocks needed */
-	struct xfs_bmbt_irec	*mval,		/* output: map values */
-	int			*nmap,		/* i/o: mval size/count */
-	struct xfs_bmap_free	*flist)		/* i/o: list extents to free */
+xfs_bmapi_read(
+	struct xfs_inode	*ip,
+	xfs_fileoff_t		bno,
+	xfs_filblks_t		len,
+	struct xfs_bmbt_irec	*mval,
+	int			*nmap,
+	int			flags)
 {
 	struct xfs_mount	*mp = ip->i_mount;
 	struct xfs_ifork	*ifp;
-	struct xfs_bmalloca	bma = { 0 };	/* args for xfs_bmap_alloc */
-	xfs_fileoff_t		end;		/* end of mapped file region */
-	int			eof;		/* after the end of extents */
-	int			error;		/* error return */
-	int			n;		/* current extent index */
-	xfs_fileoff_t		obno;		/* old block number (offset) */
-	int			whichfork;	/* data or attr fork */
-	char			inhole;		/* current location is hole in file */
-	char			wasdelay;	/* old extent was delayed */
-
-#ifdef DEBUG
-	xfs_fileoff_t		orig_bno;	/* original block number value */
-	int			orig_flags;	/* original flags arg value */
-	xfs_filblks_t		orig_len;	/* original value of len arg */
-	struct xfs_bmbt_irec	*orig_mval;	/* original value of mval */
-	int			orig_nmap;	/* original value of *nmap */
-
-	orig_bno = bno;
-	orig_len = len;
-	orig_flags = flags;
-	orig_mval = mval;
-	orig_nmap = *nmap;
-#endif
+	struct xfs_bmbt_irec	got;
+	struct xfs_bmbt_irec	prev;
+	xfs_fileoff_t		obno;
+	xfs_fileoff_t		end;
+	xfs_extnum_t		lastx;
+	int			error;
+	int			eof;
+	int			n = 0;
+	int			whichfork = (flags & XFS_BMAPI_ATTRFORK) ?
+						XFS_ATTR_FORK : XFS_DATA_FORK;
 
 	ASSERT(*nmap >= 1);
-	ASSERT(*nmap <= XFS_BMAP_MAX_NMAP);
-	ASSERT(!(flags & XFS_BMAPI_IGSTATE));
-	ASSERT(tp != NULL);
-	ASSERT(len > 0);
-
-	whichfork = (flags & XFS_BMAPI_ATTRFORK) ?
-		XFS_ATTR_FORK : XFS_DATA_FORK;
+	ASSERT(!(flags & ~(XFS_BMAPI_ATTRFORK|XFS_BMAPI_ENTIRE|
+			   XFS_BMAPI_IGSTATE)));
 
 	if (unlikely(XFS_TEST_ERROR(
 	    (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
-	     XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE &&
-	     XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL),
+	     XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE),
 	     mp, XFS_ERRTAG_BMAPIFORMAT, XFS_RANDOM_BMAPIFORMAT))) {
-		XFS_ERROR_REPORT("xfs_bmapi_write", XFS_ERRLEVEL_LOW, mp);
+		XFS_ERROR_REPORT("xfs_bmapi_read", XFS_ERRLEVEL_LOW, mp);
 		return XFS_ERROR(EFSCORRUPTED);
 	}
 
 	if (XFS_FORCED_SHUTDOWN(mp))
 		return XFS_ERROR(EIO);
 
+	XFS_STATS_INC(xs_blk_mapr);
+
 	ifp = XFS_IFORK_PTR(ip, whichfork);
 
-	XFS_STATS_INC(xs_blk_mapw);
-
-	if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) {
-		/*
-		 * XXX (dgc): This assumes we are only called for inodes that
-		 * contain content neutral data in local format. Anything that
-		 * contains caller-specific data in local format that needs
-		 * transformation to move to a block format needs to do the
-		 * conversion to extent format itself.
-		 *
-		 * Directory data forks and attribute forks handle this
-		 * themselves, but with the addition of metadata verifiers every
-		 * data fork in local format now contains caller specific data
-		 * and as such conversion through this function is likely to be
-		 * broken.
-		 *
-		 * The only likely user of this branch is for remote symlinks,
-		 * but we cannot overwrite the data fork contents of the symlink
-		 * (EEXIST occurs higher up the stack) and so it will never go
-		 * from local format to extent format here. Hence I don't think
-		 * this branch is ever executed intentionally and we should
-		 * consider removing it and asserting that xfs_bmapi_write()
-		 * cannot be called directly on local format forks. i.e. callers
-		 * are completely responsible for local to extent format
-		 * conversion, not xfs_bmapi_write().
-		 */
-		error = xfs_bmap_local_to_extents(tp, ip, firstblock, total,
-					&bma.logflags, whichfork,
-					xfs_bmap_local_to_extents_init_fn);
-		if (error)
-			goto error0;
-	}
-
-	if (*firstblock == NULLFSBLOCK) {
-		if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE)
-			bma.minleft = be16_to_cpu(ifp->if_broot->bb_level) + 1;
-		else
-			bma.minleft = 1;
-	} else {
-		bma.minleft = 0;
-	}
-
 	if (!(ifp->if_flags & XFS_IFEXTENTS)) {
-		error = xfs_iread_extents(tp, ip, whichfork);
+		error = xfs_iread_extents(NULL, ip, whichfork);
 		if (error)
-			goto error0;
+			return error;
 	}
 
-	xfs_bmap_search_extents(ip, bno, whichfork, &eof, &bma.idx, &bma.got,
-				&bma.prev);
-	n = 0;
+	xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got, &prev);
 	end = bno + len;
 	obno = bno;
 
-	bma.tp = tp;
-	bma.ip = ip;
-	bma.total = total;
-	bma.userdata = 0;
-	bma.flist = flist;
-	bma.firstblock = firstblock;
-
-	if (flags & XFS_BMAPI_STACK_SWITCH)
-		bma.stack_switch = 1;
-
 	while (bno < end && n < *nmap) {
-		inhole = eof || bma.got.br_startoff > bno;
-		wasdelay = !inhole && isnullstartblock(bma.got.br_startblock);
-
-		/*
-		 * First, deal with the hole before the allocated space
-		 * that we found, if any.
-		 */
-		if (inhole || wasdelay) {
-			bma.eof = eof;
-			bma.conv = !!(flags & XFS_BMAPI_CONVERT);
-			bma.wasdel = wasdelay;
-			bma.offset = bno;
-			bma.flags = flags;
-
-			/*
-			 * There's a 32/64 bit type mismatch between the
-			 * allocation length request (which can be 64 bits in
-			 * length) and the bma length request, which is
-			 * xfs_extlen_t and therefore 32 bits. Hence we have to
-			 * check for 32-bit overflows and handle them here.
-			 */
-			if (len > (xfs_filblks_t)MAXEXTLEN)
-				bma.length = MAXEXTLEN;
-			else
-				bma.length = len;
-
-			ASSERT(len > 0);
-			ASSERT(bma.length > 0);
-			error = xfs_bmapi_allocate(&bma);
-			if (error)
-				goto error0;
-			if (bma.blkno == NULLFSBLOCK)
-				break;
-		}
-
-		/* Deal with the allocated space we found.  */
-		xfs_bmapi_trim_map(mval, &bma.got, &bno, len, obno,
-							end, n, flags);
-
-		/* Execute unwritten extent conversion if necessary */
-		error = xfs_bmapi_convert_unwritten(&bma, mval, len, flags);
-		if (error == EAGAIN)
+		/* Reading past eof, act as though there's a hole up to end. */
+		if (eof)
+			got.br_startoff = end;
+		if (got.br_startoff > bno) {
+			/* Reading in a hole.  */
+			mval->br_startoff = bno;
+			mval->br_startblock = HOLESTARTBLOCK;
+			mval->br_blockcount =
+				XFS_FILBLKS_MIN(len, got.br_startoff - bno);
+			mval->br_state = XFS_EXT_NORM;
+			bno += mval->br_blockcount;
+			len -= mval->br_blockcount;
+			mval++;
+			n++;
 			continue;
-		if (error)
-			goto error0;
+		}
 
-		/* update the extent map to return */
+		/* set up the extent map to return. */
+		xfs_bmapi_trim_map(mval, &got, &bno, len, obno, end, n, flags);
 		xfs_bmapi_update_map(&mval, &bno, &len, obno, end, &n, flags);
 
-		/*
-		 * If we're done, stop now.  Stop when we've allocated
-		 * XFS_BMAP_MAX_NMAP extents no matter what.  Otherwise
-		 * the transaction may get too big.
-		 */
-		if (bno >= end || n >= *nmap || bma.nallocs >= *nmap)
+		/* If we're done, stop now. */
+		if (bno >= end || n >= *nmap)
 			break;
 
 		/* Else go on to the next record. */
-		bma.prev = bma.got;
-		if (++bma.idx < ifp->if_bytes / sizeof(xfs_bmbt_rec_t)) {
-			xfs_bmbt_get_all(xfs_iext_get_ext(ifp, bma.idx),
-					 &bma.got);
-		} else
+		if (++lastx < ifp->if_bytes / sizeof(xfs_bmbt_rec_t))
+			xfs_bmbt_get_all(xfs_iext_get_ext(ifp, lastx), &got);
+		else
 			eof = 1;
 	}
 	*nmap = n;
+	return 0;
+}
 
-	/*
-	 * Transform from btree to extents, give it cur.
-	 */
-	if (xfs_bmap_wants_extents(ip, whichfork)) {
-		int		tmp_logflags = 0;
+STATIC int
+xfs_bmapi_reserve_delalloc(
+	struct xfs_inode	*ip,
+	xfs_fileoff_t		aoff,
+	xfs_filblks_t		len,
+	struct xfs_bmbt_irec	*got,
+	struct xfs_bmbt_irec	*prev,
+	xfs_extnum_t		*lastx,
+	int			eof)
+{
+	struct xfs_mount	*mp = ip->i_mount;
+	struct xfs_ifork	*ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
+	xfs_extlen_t		alen;
+	xfs_extlen_t		indlen;
+	char			rt = XFS_IS_REALTIME_INODE(ip);
+	xfs_extlen_t		extsz;
+	int			error;
 
-		ASSERT(bma.cur);
-		error = xfs_bmap_btree_to_extents(tp, ip, bma.cur,
-			&tmp_logflags, whichfork);
-		bma.logflags |= tmp_logflags;
-		if (error)
-			goto error0;
+	alen = XFS_FILBLKS_MIN(len, MAXEXTLEN);
+	if (!eof)
+		alen = XFS_FILBLKS_MIN(alen, got->br_startoff - aoff);
+
+	/* Figure out the extent size, adjust alen */
+	extsz = xfs_get_extsz_hint(ip);
+	if (extsz) {
+		/*
+		 * Make sure we don't exceed a single extent length when we
+		 * align the extent by reducing length we are going to
+		 * allocate by the maximum amount extent size aligment may
+		 * require.
+		 */
+		alen = XFS_FILBLKS_MIN(len, MAXEXTLEN - (2 * extsz - 1));
+		error = xfs_bmap_extsize_align(mp, got, prev, extsz, rt, eof,
+					       1, 0, &aoff, &alen);
+		ASSERT(!error);
 	}
 
-	ASSERT(XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE ||
-	       XFS_IFORK_NEXTENTS(ip, whichfork) >
-		XFS_IFORK_MAXEXT(ip, whichfork));
-	error = 0;
-error0:
+	if (rt)
+		extsz = alen / mp->m_sb.sb_rextsize;
+
 	/*
-	 * Log everything.  Do this after conversion, there's no point in
-	 * logging the extent records if we've converted to btree format.
+	 * Make a transaction-less quota reservation for delayed allocation
+	 * blocks.  This number gets adjusted later.  We return if we haven't
+	 * allocated blocks already inside this loop.
 	 */
-	if ((bma.logflags & xfs_ilog_fext(whichfork)) &&
-	    XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS)
-		bma.logflags &= ~xfs_ilog_fext(whichfork);
-	else if ((bma.logflags & xfs_ilog_fbroot(whichfork)) &&
-		 XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE)
-		bma.logflags &= ~xfs_ilog_fbroot(whichfork);
+	error = xfs_trans_reserve_quota_nblks(NULL, ip, (long)alen, 0,
+			rt ? XFS_QMOPT_RES_RTBLKS : XFS_QMOPT_RES_REGBLKS);
+	if (error)
+		return error;
+
 	/*
-	 * Log whatever the flags say, even if error.  Otherwise we might miss
-	 * detecting a case where the data is changed, there's an error,
-	 * and it's not logged so we don't shutdown when we should.
+	 * Split changing sb for alen and indlen since they could be coming
+	 * from different places.
 	 */
-	if (bma.logflags)
-		xfs_trans_log_inode(tp, ip, bma.logflags);
+	indlen = (xfs_extlen_t)xfs_bmap_worst_indlen(ip, alen);
+	ASSERT(indlen > 0);
 
-	if (bma.cur) {
-		if (!error) {
-			ASSERT(*firstblock == NULLFSBLOCK ||
-			       XFS_FSB_TO_AGNO(mp, *firstblock) ==
-			       XFS_FSB_TO_AGNO(mp,
-				       bma.cur->bc_private.b.firstblock) ||
-			       (flist->xbf_low &&
-				XFS_FSB_TO_AGNO(mp, *firstblock) <
-				XFS_FSB_TO_AGNO(mp,
-					bma.cur->bc_private.b.firstblock)));
-			*firstblock = bma.cur->bc_private.b.firstblock;
-		}
-		xfs_btree_del_cursor(bma.cur,
-			error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR);
+	if (rt) {
+		error = xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS,
+					  -((int64_t)extsz), 0);
+	} else {
+		error = xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS,
+						 -((int64_t)alen), 0);
 	}
-	if (!error)
-		xfs_bmap_validate_ret(orig_bno, orig_len, orig_flags, orig_mval,
-			orig_nmap, *nmap);
-	return error;
-}
 
-/*
- * Unmap (remove) blocks from a file.
- * If nexts is nonzero then the number of extents to remove is limited to
- * that value.  If not all extents in the block range can be removed then
- * *done is set.
- */
-int						/* error */
-xfs_bunmapi(
-	xfs_trans_t		*tp,		/* transaction pointer */
-	struct xfs_inode	*ip,		/* incore inode */
-	xfs_fileoff_t		bno,		/* starting offset to unmap */
-	xfs_filblks_t		len,		/* length to unmap in file */
-	int			flags,		/* misc flags */
-	xfs_extnum_t		nexts,		/* number of extents max */
-	xfs_fsblock_t		*firstblock,	/* first allocated block
-						   controls a.g. for allocs */
-	xfs_bmap_free_t		*flist,		/* i/o: list extents to free */
-	int			*done)		/* set if not done yet */
+	if (error)
+		goto out_unreserve_quota;
+
+	error = xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS,
+					 -((int64_t)indlen), 0);
+	if (error)
+		goto out_unreserve_blocks;
+
+
+	ip->i_delayed_blks += alen;
+
+	got->br_startoff = aoff;
+	got->br_startblock = nullstartblock(indlen);
+	got->br_blockcount = alen;
+	got->br_state = XFS_EXT_NORM;
+	xfs_bmap_add_extent_hole_delay(ip, lastx, got);
+
+	/*
+	 * Update our extent pointer, given that xfs_bmap_add_extent_hole_delay
+	 * might have merged it into one of the neighbouring ones.
+	 */
+	xfs_bmbt_get_all(xfs_iext_get_ext(ifp, *lastx), got);
+
+	ASSERT(got->br_startoff <= aoff);
+	ASSERT(got->br_startoff + got->br_blockcount >= aoff + alen);
+	ASSERT(isnullstartblock(got->br_startblock));
+	ASSERT(got->br_state == XFS_EXT_NORM);
+	return 0;
+
+out_unreserve_blocks:
+	if (rt)
+		xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS, extsz, 0);
+	else
+		xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS, alen, 0);
+out_unreserve_quota:
+	if (XFS_IS_QUOTA_ON(mp))
+		xfs_trans_unreserve_quota_nblks(NULL, ip, (long)alen, 0, rt ?
+				XFS_QMOPT_RES_RTBLKS : XFS_QMOPT_RES_REGBLKS);
+	return error;
+}
+
+/*
+ * Map file blocks to filesystem blocks, adding delayed allocations as needed.
+ */
+int
+xfs_bmapi_delay(
+	struct xfs_inode	*ip,	/* incore inode */
+	xfs_fileoff_t		bno,	/* starting file offs. mapped */
+	xfs_filblks_t		len,	/* length to map in file */
+	struct xfs_bmbt_irec	*mval,	/* output: map values */
+	int			*nmap,	/* i/o: mval size/count */
+	int			flags)	/* XFS_BMAPI_... */
 {
-	xfs_btree_cur_t		*cur;		/* bmap btree cursor */
-	xfs_bmbt_irec_t		del;		/* extent being deleted */
-	int			eof;		/* is deleting at eof */
-	xfs_bmbt_rec_host_t	*ep;		/* extent record pointer */
-	int			error;		/* error return value */
-	xfs_extnum_t		extno;		/* extent number in list */
-	xfs_bmbt_irec_t		got;		/* current extent record */
-	xfs_ifork_t		*ifp;		/* inode fork pointer */
-	int			isrt;		/* freeing in rt area */
-	xfs_extnum_t		lastx;		/* last extent index used */
-	int			logflags;	/* transaction logging flags */
-	xfs_extlen_t		mod;		/* rt extent offset */
-	xfs_mount_t		*mp;		/* mount structure */
-	xfs_extnum_t		nextents;	/* number of file extents */
-	xfs_bmbt_irec_t		prev;		/* previous extent record */
-	xfs_fileoff_t		start;		/* first file offset deleted */
-	int			tmp_logflags;	/* partial logging flags */
-	int			wasdel;		/* was a delayed alloc extent */
-	int			whichfork;	/* data or attribute fork */
-	xfs_fsblock_t		sum;
+	struct xfs_mount	*mp = ip->i_mount;
+	struct xfs_ifork	*ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
+	struct xfs_bmbt_irec	got;	/* current file extent record */
+	struct xfs_bmbt_irec	prev;	/* previous file extent record */
+	xfs_fileoff_t		obno;	/* old block number (offset) */
+	xfs_fileoff_t		end;	/* end of mapped file region */
+	xfs_extnum_t		lastx;	/* last useful extent number */
+	int			eof;	/* we've hit the end of extents */
+	int			n = 0;	/* current extent index */
+	int			error = 0;
 
-	trace_xfs_bunmap(ip, bno, len, flags, _RET_IP_);
+	ASSERT(*nmap >= 1);
+	ASSERT(*nmap <= XFS_BMAP_MAX_NMAP);
+	ASSERT(!(flags & ~XFS_BMAPI_ENTIRE));
 
-	whichfork = (flags & XFS_BMAPI_ATTRFORK) ?
-		XFS_ATTR_FORK : XFS_DATA_FORK;
-	ifp = XFS_IFORK_PTR(ip, whichfork);
-	if (unlikely(
-	    XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
-	    XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE)) {
-		XFS_ERROR_REPORT("xfs_bunmapi", XFS_ERRLEVEL_LOW,
-				 ip->i_mount);
+	if (unlikely(XFS_TEST_ERROR(
+	    (XFS_IFORK_FORMAT(ip, XFS_DATA_FORK) != XFS_DINODE_FMT_EXTENTS &&
+	     XFS_IFORK_FORMAT(ip, XFS_DATA_FORK) != XFS_DINODE_FMT_BTREE),
+	     mp, XFS_ERRTAG_BMAPIFORMAT, XFS_RANDOM_BMAPIFORMAT))) {
+		XFS_ERROR_REPORT("xfs_bmapi_delay", XFS_ERRLEVEL_LOW, mp);
 		return XFS_ERROR(EFSCORRUPTED);
 	}
-	mp = ip->i_mount;
+
 	if (XFS_FORCED_SHUTDOWN(mp))
 		return XFS_ERROR(EIO);
 
-	ASSERT(len > 0);
-	ASSERT(nexts >= 0);
+	XFS_STATS_INC(xs_blk_mapw);
 
-	if (!(ifp->if_flags & XFS_IFEXTENTS) &&
-	    (error = xfs_iread_extents(tp, ip, whichfork)))
-		return error;
-	nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
-	if (nextents == 0) {
-		*done = 1;
-		return 0;
+	if (!(ifp->if_flags & XFS_IFEXTENTS)) {
+		error = xfs_iread_extents(NULL, ip, XFS_DATA_FORK);
+		if (error)
+			return error;
 	}
-	XFS_STATS_INC(xs_blk_unmap);
-	isrt = (whichfork == XFS_DATA_FORK) && XFS_IS_REALTIME_INODE(ip);
-	start = bno;
-	bno = start + len - 1;
-	ep = xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got,
-		&prev);
+
+	xfs_bmap_search_extents(ip, bno, XFS_DATA_FORK, &eof, &lastx, &got, &prev);
+	end = bno + len;
+	obno = bno;
+
+	while (bno < end && n < *nmap) {
+		if (eof || got.br_startoff > bno) {
+			error = xfs_bmapi_reserve_delalloc(ip, bno, len, &got,
+							   &prev, &lastx, eof);
+			if (error) {
+				if (n == 0) {
+					*nmap = 0;
+					return error;
+				}
+				break;
+			}
+		}
+
+		/* set up the extent map to return. */
+		xfs_bmapi_trim_map(mval, &got, &bno, len, obno, end, n, flags);
+		xfs_bmapi_update_map(&mval, &bno, &len, obno, end, &n, flags);
+
+		/* If we're done, stop now. */
+		if (bno >= end || n >= *nmap)
+			break;
+
+		/* Else go on to the next record. */
+		prev = got;
+		if (++lastx < ifp->if_bytes / sizeof(xfs_bmbt_rec_t))
+			xfs_bmbt_get_all(xfs_iext_get_ext(ifp, lastx), &got);
+		else
+			eof = 1;
+	}
+
+	*nmap = n;
+	return 0;
+}
+
+
+STATIC int
+__xfs_bmapi_allocate(
+	struct xfs_bmalloca	*bma)
+{
+	struct xfs_mount	*mp = bma->ip->i_mount;
+	int			whichfork = (bma->flags & XFS_BMAPI_ATTRFORK) ?
+						XFS_ATTR_FORK : XFS_DATA_FORK;
+	struct xfs_ifork	*ifp = XFS_IFORK_PTR(bma->ip, whichfork);
+	int			tmp_logflags = 0;
+	int			error;
+	int			rt;
+
+	ASSERT(bma->length > 0);
+
+	rt = (whichfork == XFS_DATA_FORK) && XFS_IS_REALTIME_INODE(bma->ip);
 
 	/*
-	 * Check to see if the given block number is past the end of the
-	 * file, back up to the last block if so...
+	 * For the wasdelay case, we could also just allocate the stuff asked
+	 * for in this bmap call but that wouldn't be as good.
 	 */
-	if (eof) {
-		ep = xfs_iext_get_ext(ifp, --lastx);
-		xfs_bmbt_get_all(ep, &got);
-		bno = got.br_startoff + got.br_blockcount - 1;
+	if (bma->wasdel) {
+		bma->length = (xfs_extlen_t)bma->got.br_blockcount;
+		bma->offset = bma->got.br_startoff;
+		if (bma->idx != NULLEXTNUM && bma->idx) {
+			xfs_bmbt_get_all(xfs_iext_get_ext(ifp, bma->idx - 1),
+					 &bma->prev);
+		}
+	} else {
+		bma->length = XFS_FILBLKS_MIN(bma->length, MAXEXTLEN);
+		if (!bma->eof)
+			bma->length = XFS_FILBLKS_MIN(bma->length,
+					bma->got.br_startoff - bma->offset);
 	}
-	logflags = 0;
-	if (ifp->if_flags & XFS_IFBROOT) {
-		ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE);
-		cur = xfs_bmbt_init_cursor(mp, tp, ip, whichfork);
-		cur->bc_private.b.firstblock = *firstblock;
-		cur->bc_private.b.flist = flist;
-		cur->bc_private.b.flags = 0;
-	} else
-		cur = NULL;
 
-	if (isrt) {
-		/*
-		 * Synchronize by locking the bitmap inode.
-		 */
-		xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL);
-		xfs_trans_ijoin(tp, mp->m_rbmip, XFS_ILOCK_EXCL);
+	/*
+	 * Indicate if this is the first user data in the file, or just any
+	 * user data.
+	 */
+	if (!(bma->flags & XFS_BMAPI_METADATA)) {
+		bma->userdata = (bma->offset == 0) ?
+			XFS_ALLOC_INITIAL_USER_DATA : XFS_ALLOC_USERDATA;
 	}
 
-	extno = 0;
-	while (bno != (xfs_fileoff_t)-1 && bno >= start && lastx >= 0 &&
-	       (nexts == 0 || extno < nexts)) {
-		/*
-		 * Is the found extent after a hole in which bno lives?
-		 * Just back up to the previous extent, if so.
-		 */
-		if (got.br_startoff > bno) {
-			if (--lastx < 0)
-				break;
-			ep = xfs_iext_get_ext(ifp, lastx);
-			xfs_bmbt_get_all(ep, &got);
-		}
-		/*
-		 * Is the last block of this extent before the range
-		 * we're supposed to delete?  If so, we're done.
-		 */
-		bno = XFS_FILEOFF_MIN(bno,
-			got.br_startoff + got.br_blockcount - 1);
-		if (bno < start)
-			break;
-		/*
-		 * Then deal with the (possibly delayed) allocated space
-		 * we found.
-		 */
-		ASSERT(ep != NULL);
-		del = got;
-		wasdel = isnullstartblock(del.br_startblock);
-		if (got.br_startoff < start) {
-			del.br_startoff = start;
-			del.br_blockcount -= start - got.br_startoff;
-			if (!wasdel)
-				del.br_startblock += start - got.br_startoff;
-		}
-		if (del.br_startoff + del.br_blockcount > bno + 1)
-			del.br_blockcount = bno + 1 - del.br_startoff;
-		sum = del.br_startblock + del.br_blockcount;
-		if (isrt &&
-		    (mod = do_mod(sum, mp->m_sb.sb_rextsize))) {
-			/*
-			 * Realtime extent not lined up at the end.
-			 * The extent could have been split into written
-			 * and unwritten pieces, or we could just be
-			 * unmapping part of it.  But we can't really
-			 * get rid of part of a realtime extent.
-			 */
-			if (del.br_state == XFS_EXT_UNWRITTEN ||
-			    !xfs_sb_version_hasextflgbit(&mp->m_sb)) {
-				/*
-				 * This piece is unwritten, or we're not
-				 * using unwritten extents.  Skip over it.
-				 */
-				ASSERT(bno >= mod);
-				bno -= mod > del.br_blockcount ?
-					del.br_blockcount : mod;
-				if (bno < got.br_startoff) {
-					if (--lastx >= 0)
-						xfs_bmbt_get_all(xfs_iext_get_ext(
-							ifp, lastx), &got);
-				}
-				continue;
-			}
-			/*
-			 * It's written, turn it unwritten.
-			 * This is better than zeroing it.
-			 */
-			ASSERT(del.br_state == XFS_EXT_NORM);
-			ASSERT(xfs_trans_get_block_res(tp) > 0);
-			/*
-			 * If this spans a realtime extent boundary,
-			 * chop it back to the start of the one we end at.
-			 */
-			if (del.br_blockcount > mod) {
-				del.br_startoff += del.br_blockcount - mod;
-				del.br_startblock += del.br_blockcount - mod;
-				del.br_blockcount = mod;
-			}
-			del.br_state = XFS_EXT_UNWRITTEN;
-			error = xfs_bmap_add_extent_unwritten_real(tp, ip,
-					&lastx, &cur, &del, firstblock, flist,
-					&logflags);
-			if (error)
-				goto error0;
-			goto nodelete;
-		}
-		if (isrt && (mod = do_mod(del.br_startblock, mp->m_sb.sb_rextsize))) {
-			/*
-			 * Realtime extent is lined up at the end but not
-			 * at the front.  We'll get rid of full extents if
-			 * we can.
-			 */
-			mod = mp->m_sb.sb_rextsize - mod;
-			if (del.br_blockcount > mod) {
-				del.br_blockcount -= mod;
-				del.br_startoff += mod;
-				del.br_startblock += mod;
-			} else if ((del.br_startoff == start &&
-				    (del.br_state == XFS_EXT_UNWRITTEN ||
-				     xfs_trans_get_block_res(tp) == 0)) ||
-				   !xfs_sb_version_hasextflgbit(&mp->m_sb)) {
-				/*
-				 * Can't make it unwritten.  There isn't
-				 * a full extent here so just skip it.
-				 */
-				ASSERT(bno >= del.br_blockcount);
-				bno -= del.br_blockcount;
-				if (got.br_startoff > bno) {
-					if (--lastx >= 0) {
-						ep = xfs_iext_get_ext(ifp,
-								      lastx);
-						xfs_bmbt_get_all(ep, &got);
-					}
-				}
-				continue;
-			} else if (del.br_state == XFS_EXT_UNWRITTEN) {
-				/*
-				 * This one is already unwritten.
-				 * It must have a written left neighbor.
-				 * Unwrite the killed part of that one and
-				 * try again.
-				 */
-				ASSERT(lastx > 0);
-				xfs_bmbt_get_all(xfs_iext_get_ext(ifp,
-						lastx - 1), &prev);
-				ASSERT(prev.br_state == XFS_EXT_NORM);
-				ASSERT(!isnullstartblock(prev.br_startblock));
-				ASSERT(del.br_startblock ==
-				       prev.br_startblock + prev.br_blockcount);
-				if (prev.br_startoff < start) {
-					mod = start - prev.br_startoff;
-					prev.br_blockcount -= mod;
-					prev.br_startblock += mod;
-					prev.br_startoff = start;
-				}
-				prev.br_state = XFS_EXT_UNWRITTEN;
-				lastx--;
-				error = xfs_bmap_add_extent_unwritten_real(tp,
-						ip, &lastx, &cur, &prev,
-						firstblock, flist, &logflags);
-				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_unwritten_real(tp,
-						ip, &lastx, &cur, &del,
-						firstblock, flist, &logflags);
-				if (error)
-					goto error0;
-				goto nodelete;
-			}
+	bma->minlen = (bma->flags & XFS_BMAPI_CONTIG) ? bma->length : 1;
+
+	/*
+	 * Only want to do the alignment at the eof if it is userdata and
+	 * allocation length is larger than a stripe unit.
+	 */
+	if (mp->m_dalign && bma->length >= mp->m_dalign &&
+	    !(bma->flags & XFS_BMAPI_METADATA) && whichfork == XFS_DATA_FORK) {
+		error = xfs_bmap_isaeof(bma, whichfork);
+		if (error)
+			return error;
+	}
+
+	error = xfs_bmap_alloc(bma);
+	if (error)
+		return error;
+
+	if (bma->flist->xbf_low)
+		bma->minleft = 0;
+	if (bma->cur)
+		bma->cur->bc_private.b.firstblock = *bma->firstblock;
+	if (bma->blkno == NULLFSBLOCK)
+		return 0;
+	if ((ifp->if_flags & XFS_IFBROOT) && !bma->cur) {
+		bma->cur = xfs_bmbt_init_cursor(mp, bma->tp, bma->ip, whichfork);
+		bma->cur->bc_private.b.firstblock = *bma->firstblock;
+		bma->cur->bc_private.b.flist = bma->flist;
+	}
+	/*
+	 * Bump the number of extents we've allocated
+	 * in this call.
+	 */
+	bma->nallocs++;
+
+	if (bma->cur)
+		bma->cur->bc_private.b.flags =
+			bma->wasdel ? XFS_BTCUR_BPRV_WASDEL : 0;
+
+	bma->got.br_startoff = bma->offset;
+	bma->got.br_startblock = bma->blkno;
+	bma->got.br_blockcount = bma->length;
+	bma->got.br_state = XFS_EXT_NORM;
+
+	/*
+	 * A wasdelay extent has been initialized, so shouldn't be flagged
+	 * as unwritten.
+	 */
+	if (!bma->wasdel && (bma->flags & XFS_BMAPI_PREALLOC) &&
+	    xfs_sb_version_hasextflgbit(&mp->m_sb))
+		bma->got.br_state = XFS_EXT_UNWRITTEN;
+
+	if (bma->wasdel)
+		error = xfs_bmap_add_extent_delay_real(bma);
+	else
+		error = xfs_bmap_add_extent_hole_real(bma, whichfork);
+
+	bma->logflags |= tmp_logflags;
+	if (error)
+		return error;
+
+	/*
+	 * Update our extent pointer, given that xfs_bmap_add_extent_delay_real
+	 * or xfs_bmap_add_extent_hole_real might have merged it into one of
+	 * the neighbouring ones.
+	 */
+	xfs_bmbt_get_all(xfs_iext_get_ext(ifp, bma->idx), &bma->got);
+
+	ASSERT(bma->got.br_startoff <= bma->offset);
+	ASSERT(bma->got.br_startoff + bma->got.br_blockcount >=
+	       bma->offset + bma->length);
+	ASSERT(bma->got.br_state == XFS_EXT_NORM ||
+	       bma->got.br_state == XFS_EXT_UNWRITTEN);
+	return 0;
+}
+
+static void
+xfs_bmapi_allocate_worker(
+	struct work_struct	*work)
+{
+	struct xfs_bmalloca	*args = container_of(work,
+						struct xfs_bmalloca, work);
+	unsigned long		pflags;
+
+	/* we are in a transaction context here */
+	current_set_flags_nested(&pflags, PF_FSTRANS);
+
+	args->result = __xfs_bmapi_allocate(args);
+	complete(args->done);
+
+	current_restore_flags_nested(&pflags, PF_FSTRANS);
+}
+
+/*
+ * Some allocation requests often come in with little stack to work on. Push
+ * them off to a worker thread so there is lots of stack to use. Otherwise just
+ * call directly to avoid the context switch overhead here.
+ */
+int
+xfs_bmapi_allocate(
+	struct xfs_bmalloca	*args)
+{
+	DECLARE_COMPLETION_ONSTACK(done);
+
+	if (!args->stack_switch)
+		return __xfs_bmapi_allocate(args);
+
+
+	args->done = &done;
+	INIT_WORK_ONSTACK(&args->work, xfs_bmapi_allocate_worker);
+	queue_work(xfs_alloc_wq, &args->work);
+	wait_for_completion(&done);
+	return args->result;
+}
+
+STATIC int
+xfs_bmapi_convert_unwritten(
+	struct xfs_bmalloca	*bma,
+	struct xfs_bmbt_irec	*mval,
+	xfs_filblks_t		len,
+	int			flags)
+{
+	int			whichfork = (flags & XFS_BMAPI_ATTRFORK) ?
+						XFS_ATTR_FORK : XFS_DATA_FORK;
+	struct xfs_ifork	*ifp = XFS_IFORK_PTR(bma->ip, whichfork);
+	int			tmp_logflags = 0;
+	int			error;
+
+	/* check if we need to do unwritten->real conversion */
+	if (mval->br_state == XFS_EXT_UNWRITTEN &&
+	    (flags & XFS_BMAPI_PREALLOC))
+		return 0;
+
+	/* check if we need to do real->unwritten conversion */
+	if (mval->br_state == XFS_EXT_NORM &&
+	    (flags & (XFS_BMAPI_PREALLOC | XFS_BMAPI_CONVERT)) !=
+			(XFS_BMAPI_PREALLOC | XFS_BMAPI_CONVERT))
+		return 0;
+
+	/*
+	 * Modify (by adding) the state flag, if writing.
+	 */
+	ASSERT(mval->br_blockcount <= len);
+	if ((ifp->if_flags & XFS_IFBROOT) && !bma->cur) {
+		bma->cur = xfs_bmbt_init_cursor(bma->ip->i_mount, bma->tp,
+					bma->ip, whichfork);
+		bma->cur->bc_private.b.firstblock = *bma->firstblock;
+		bma->cur->bc_private.b.flist = bma->flist;
+	}
+	mval->br_state = (mval->br_state == XFS_EXT_UNWRITTEN)
+				? XFS_EXT_NORM : XFS_EXT_UNWRITTEN;
+
+	error = xfs_bmap_add_extent_unwritten_real(bma->tp, bma->ip, &bma->idx,
+			&bma->cur, mval, bma->firstblock, bma->flist,
+			&tmp_logflags);
+	bma->logflags |= tmp_logflags;
+	if (error)
+		return error;
+
+	/*
+	 * Update our extent pointer, given that
+	 * xfs_bmap_add_extent_unwritten_real might have merged it into one
+	 * of the neighbouring ones.
+	 */
+	xfs_bmbt_get_all(xfs_iext_get_ext(ifp, bma->idx), &bma->got);
+
+	/*
+	 * We may have combined previously unwritten space with written space,
+	 * so generate another request.
+	 */
+	if (mval->br_blockcount < len)
+		return EAGAIN;
+	return 0;
+}
+
+/*
+ * Map file blocks to filesystem blocks, and allocate blocks or convert the
+ * extent state if necessary.  Details behaviour is controlled by the flags
+ * parameter.  Only allocates blocks from a single allocation group, to avoid
+ * locking problems.
+ *
+ * The returned value in "firstblock" from the first call in a transaction
+ * must be remembered and presented to subsequent calls in "firstblock".
+ * An upper bound for the number of blocks to be allocated is supplied to
+ * the first call in "total"; if no allocation group has that many free
+ * blocks then the call will fail (return NULLFSBLOCK in "firstblock").
+ */
+int
+xfs_bmapi_write(
+	struct xfs_trans	*tp,		/* transaction pointer */
+	struct xfs_inode	*ip,		/* incore inode */
+	xfs_fileoff_t		bno,		/* starting file offs. mapped */
+	xfs_filblks_t		len,		/* length to map in file */
+	int			flags,		/* XFS_BMAPI_... */
+	xfs_fsblock_t		*firstblock,	/* first allocated block
+						   controls a.g. for allocs */
+	xfs_extlen_t		total,		/* total blocks needed */
+	struct xfs_bmbt_irec	*mval,		/* output: map values */
+	int			*nmap,		/* i/o: mval size/count */
+	struct xfs_bmap_free	*flist)		/* i/o: list extents to free */
+{
+	struct xfs_mount	*mp = ip->i_mount;
+	struct xfs_ifork	*ifp;
+	struct xfs_bmalloca	bma = { 0 };	/* args for xfs_bmap_alloc */
+	xfs_fileoff_t		end;		/* end of mapped file region */
+	int			eof;		/* after the end of extents */
+	int			error;		/* error return */
+	int			n;		/* current extent index */
+	xfs_fileoff_t		obno;		/* old block number (offset) */
+	int			whichfork;	/* data or attr fork */
+	char			inhole;		/* current location is hole in file */
+	char			wasdelay;	/* old extent was delayed */
+
+#ifdef DEBUG
+	xfs_fileoff_t		orig_bno;	/* original block number value */
+	int			orig_flags;	/* original flags arg value */
+	xfs_filblks_t		orig_len;	/* original value of len arg */
+	struct xfs_bmbt_irec	*orig_mval;	/* original value of mval */
+	int			orig_nmap;	/* original value of *nmap */
+
+	orig_bno = bno;
+	orig_len = len;
+	orig_flags = flags;
+	orig_mval = mval;
+	orig_nmap = *nmap;
+#endif
+
+	ASSERT(*nmap >= 1);
+	ASSERT(*nmap <= XFS_BMAP_MAX_NMAP);
+	ASSERT(!(flags & XFS_BMAPI_IGSTATE));
+	ASSERT(tp != NULL);
+	ASSERT(len > 0);
+
+	whichfork = (flags & XFS_BMAPI_ATTRFORK) ?
+		XFS_ATTR_FORK : XFS_DATA_FORK;
+
+	if (unlikely(XFS_TEST_ERROR(
+	    (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
+	     XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE &&
+	     XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL),
+	     mp, XFS_ERRTAG_BMAPIFORMAT, XFS_RANDOM_BMAPIFORMAT))) {
+		XFS_ERROR_REPORT("xfs_bmapi_write", XFS_ERRLEVEL_LOW, mp);
+		return XFS_ERROR(EFSCORRUPTED);
+	}
+
+	if (XFS_FORCED_SHUTDOWN(mp))
+		return XFS_ERROR(EIO);
+
+	ifp = XFS_IFORK_PTR(ip, whichfork);
+
+	XFS_STATS_INC(xs_blk_mapw);
+
+	if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) {
+		/*
+		 * XXX (dgc): This assumes we are only called for inodes that
+		 * contain content neutral data in local format. Anything that
+		 * contains caller-specific data in local format that needs
+		 * transformation to move to a block format needs to do the
+		 * conversion to extent format itself.
+		 *
+		 * Directory data forks and attribute forks handle this
+		 * themselves, but with the addition of metadata verifiers every
+		 * data fork in local format now contains caller specific data
+		 * and as such conversion through this function is likely to be
+		 * broken.
+		 *
+		 * The only likely user of this branch is for remote symlinks,
+		 * but we cannot overwrite the data fork contents of the symlink
+		 * (EEXIST occurs higher up the stack) and so it will never go
+		 * from local format to extent format here. Hence I don't think
+		 * this branch is ever executed intentionally and we should
+		 * consider removing it and asserting that xfs_bmapi_write()
+		 * cannot be called directly on local format forks. i.e. callers
+		 * are completely responsible for local to extent format
+		 * conversion, not xfs_bmapi_write().
+		 */
+		error = xfs_bmap_local_to_extents(tp, ip, firstblock, total,
+					&bma.logflags, whichfork,
+					xfs_bmap_local_to_extents_init_fn);
+		if (error)
+			goto error0;
+	}
+
+	if (*firstblock == NULLFSBLOCK) {
+		if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE)
+			bma.minleft = be16_to_cpu(ifp->if_broot->bb_level) + 1;
+		else
+			bma.minleft = 1;
+	} else {
+		bma.minleft = 0;
+	}
+
+	if (!(ifp->if_flags & XFS_IFEXTENTS)) {
+		error = xfs_iread_extents(tp, ip, whichfork);
+		if (error)
+			goto error0;
+	}
+
+	xfs_bmap_search_extents(ip, bno, whichfork, &eof, &bma.idx, &bma.got,
+				&bma.prev);
+	n = 0;
+	end = bno + len;
+	obno = bno;
+
+	bma.tp = tp;
+	bma.ip = ip;
+	bma.total = total;
+	bma.userdata = 0;
+	bma.flist = flist;
+	bma.firstblock = firstblock;
+
+	if (flags & XFS_BMAPI_STACK_SWITCH)
+		bma.stack_switch = 1;
+
+	while (bno < end && n < *nmap) {
+		inhole = eof || bma.got.br_startoff > bno;
+		wasdelay = !inhole && isnullstartblock(bma.got.br_startblock);
+
+		/*
+		 * First, deal with the hole before the allocated space
+		 * that we found, if any.
+		 */
+		if (inhole || wasdelay) {
+			bma.eof = eof;
+			bma.conv = !!(flags & XFS_BMAPI_CONVERT);
+			bma.wasdel = wasdelay;
+			bma.offset = bno;
+			bma.flags = flags;
+
+			/*
+			 * There's a 32/64 bit type mismatch between the
+			 * allocation length request (which can be 64 bits in
+			 * length) and the bma length request, which is
+			 * xfs_extlen_t and therefore 32 bits. Hence we have to
+			 * check for 32-bit overflows and handle them here.
+			 */
+			if (len > (xfs_filblks_t)MAXEXTLEN)
+				bma.length = MAXEXTLEN;
+			else
+				bma.length = len;
+
+			ASSERT(len > 0);
+			ASSERT(bma.length > 0);
+			error = xfs_bmapi_allocate(&bma);
+			if (error)
+				goto error0;
+			if (bma.blkno == NULLFSBLOCK)
+				break;
 		}
-		if (wasdel) {
-			ASSERT(startblockval(del.br_startblock) > 0);
-			/* Update realtime/data freespace, unreserve quota */
-			if (isrt) {
-				xfs_filblks_t rtexts;
 
-				rtexts = XFS_FSB_TO_B(mp, del.br_blockcount);
-				do_div(rtexts, mp->m_sb.sb_rextsize);
-				xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS,
-						(int64_t)rtexts, 0);
-				(void)xfs_trans_reserve_quota_nblks(NULL,
-					ip, -((long)del.br_blockcount), 0,
-					XFS_QMOPT_RES_RTBLKS);
-			} else {
-				xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS,
-						(int64_t)del.br_blockcount, 0);
-				(void)xfs_trans_reserve_quota_nblks(NULL,
-					ip, -((long)del.br_blockcount), 0,
-					XFS_QMOPT_RES_REGBLKS);
-			}
-			ip->i_delayed_blks -= del.br_blockcount;
-			if (cur)
-				cur->bc_private.b.flags |=
-					XFS_BTCUR_BPRV_WASDEL;
-		} else if (cur)
-			cur->bc_private.b.flags &= ~XFS_BTCUR_BPRV_WASDEL;
+		/* Deal with the allocated space we found.  */
+		xfs_bmapi_trim_map(mval, &bma.got, &bno, len, obno,
+							end, n, flags);
+
+		/* Execute unwritten extent conversion if necessary */
+		error = xfs_bmapi_convert_unwritten(&bma, mval, len, flags);
+		if (error == EAGAIN)
+			continue;
+		if (error)
+			goto error0;
+
+		/* update the extent map to return */
+		xfs_bmapi_update_map(&mval, &bno, &len, obno, end, &n, flags);
+
+		/*
+		 * If we're done, stop now.  Stop when we've allocated
+		 * XFS_BMAP_MAX_NMAP extents no matter what.  Otherwise
+		 * the transaction may get too big.
+		 */
+		if (bno >= end || n >= *nmap || bma.nallocs >= *nmap)
+			break;
+
+		/* Else go on to the next record. */
+		bma.prev = bma.got;
+		if (++bma.idx < ifp->if_bytes / sizeof(xfs_bmbt_rec_t)) {
+			xfs_bmbt_get_all(xfs_iext_get_ext(ifp, bma.idx),
+					 &bma.got);
+		} else
+			eof = 1;
+	}
+	*nmap = n;
+
+	/*
+	 * Transform from btree to extents, give it cur.
+	 */
+	if (xfs_bmap_wants_extents(ip, whichfork)) {
+		int		tmp_logflags = 0;
+
+		ASSERT(bma.cur);
+		error = xfs_bmap_btree_to_extents(tp, ip, bma.cur,
+			&tmp_logflags, whichfork);
+		bma.logflags |= tmp_logflags;
+		if (error)
+			goto error0;
+	}
+
+	ASSERT(XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE ||
+	       XFS_IFORK_NEXTENTS(ip, whichfork) >
+		XFS_IFORK_MAXEXT(ip, whichfork));
+	error = 0;
+error0:
+	/*
+	 * Log everything.  Do this after conversion, there's no point in
+	 * logging the extent records if we've converted to btree format.
+	 */
+	if ((bma.logflags & xfs_ilog_fext(whichfork)) &&
+	    XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS)
+		bma.logflags &= ~xfs_ilog_fext(whichfork);
+	else if ((bma.logflags & xfs_ilog_fbroot(whichfork)) &&
+		 XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE)
+		bma.logflags &= ~xfs_ilog_fbroot(whichfork);
+	/*
+	 * Log whatever the flags say, even if error.  Otherwise we might miss
+	 * detecting a case where the data is changed, there's an error,
+	 * and it's not logged so we don't shutdown when we should.
+	 */
+	if (bma.logflags)
+		xfs_trans_log_inode(tp, ip, bma.logflags);
+
+	if (bma.cur) {
+		if (!error) {
+			ASSERT(*firstblock == NULLFSBLOCK ||
+			       XFS_FSB_TO_AGNO(mp, *firstblock) ==
+			       XFS_FSB_TO_AGNO(mp,
+				       bma.cur->bc_private.b.firstblock) ||
+			       (flist->xbf_low &&
+				XFS_FSB_TO_AGNO(mp, *firstblock) <
+				XFS_FSB_TO_AGNO(mp,
+					bma.cur->bc_private.b.firstblock)));
+			*firstblock = bma.cur->bc_private.b.firstblock;
+		}
+		xfs_btree_del_cursor(bma.cur,
+			error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR);
+	}
+	if (!error)
+		xfs_bmap_validate_ret(orig_bno, orig_len, orig_flags, orig_mval,
+			orig_nmap, *nmap);
+	return error;
+}
+
+/*
+ * Called by xfs_bmapi to update file extent records and the btree
+ * after removing space (or undoing a delayed allocation).
+ */
+STATIC int				/* error */
+xfs_bmap_del_extent(
+	xfs_inode_t		*ip,	/* incore inode pointer */
+	xfs_trans_t		*tp,	/* current transaction pointer */
+	xfs_extnum_t		*idx,	/* extent number to update/delete */
+	xfs_bmap_free_t		*flist,	/* list of extents to be freed */
+	xfs_btree_cur_t		*cur,	/* if null, not a btree */
+	xfs_bmbt_irec_t		*del,	/* data to remove from extents */
+	int			*logflagsp, /* inode logging flags */
+	int			whichfork) /* data or attr fork */
+{
+	xfs_filblks_t		da_new;	/* new delay-alloc indirect blocks */
+	xfs_filblks_t		da_old;	/* old delay-alloc indirect blocks */
+	xfs_fsblock_t		del_endblock=0;	/* first block past del */
+	xfs_fileoff_t		del_endoff;	/* first offset past del */
+	int			delay;	/* current block is delayed allocated */
+	int			do_fx;	/* free extent at end of routine */
+	xfs_bmbt_rec_host_t	*ep;	/* current extent entry pointer */
+	int			error;	/* error return value */
+	int			flags;	/* inode logging flags */
+	xfs_bmbt_irec_t		got;	/* current extent entry */
+	xfs_fileoff_t		got_endoff;	/* first offset past got */
+	int			i;	/* temp state */
+	xfs_ifork_t		*ifp;	/* inode fork pointer */
+	xfs_mount_t		*mp;	/* mount structure */
+	xfs_filblks_t		nblks;	/* quota/sb block count */
+	xfs_bmbt_irec_t		new;	/* new record to be inserted */
+	/* REFERENCED */
+	uint			qfield;	/* quota field to update */
+	xfs_filblks_t		temp;	/* for indirect length calculations */
+	xfs_filblks_t		temp2;	/* for indirect length calculations */
+	int			state = 0;
+
+	XFS_STATS_INC(xs_del_exlist);
+
+	if (whichfork == XFS_ATTR_FORK)
+		state |= BMAP_ATTRFORK;
+
+	mp = ip->i_mount;
+	ifp = XFS_IFORK_PTR(ip, whichfork);
+	ASSERT((*idx >= 0) && (*idx < ifp->if_bytes /
+		(uint)sizeof(xfs_bmbt_rec_t)));
+	ASSERT(del->br_blockcount > 0);
+	ep = xfs_iext_get_ext(ifp, *idx);
+	xfs_bmbt_get_all(ep, &got);
+	ASSERT(got.br_startoff <= del->br_startoff);
+	del_endoff = del->br_startoff + del->br_blockcount;
+	got_endoff = got.br_startoff + got.br_blockcount;
+	ASSERT(got_endoff >= del_endoff);
+	delay = isnullstartblock(got.br_startblock);
+	ASSERT(isnullstartblock(del->br_startblock) == delay);
+	flags = 0;
+	qfield = 0;
+	error = 0;
+	/*
+	 * If deleting a real allocation, must free up the disk space.
+	 */
+	if (!delay) {
+		flags = XFS_ILOG_CORE;
+		/*
+		 * Realtime allocation.  Free it and record di_nblocks update.
+		 */
+		if (whichfork == XFS_DATA_FORK && XFS_IS_REALTIME_INODE(ip)) {
+			xfs_fsblock_t	bno;
+			xfs_filblks_t	len;
+
+			ASSERT(do_mod(del->br_blockcount,
+				      mp->m_sb.sb_rextsize) == 0);
+			ASSERT(do_mod(del->br_startblock,
+				      mp->m_sb.sb_rextsize) == 0);
+			bno = del->br_startblock;
+			len = del->br_blockcount;
+			do_div(bno, mp->m_sb.sb_rextsize);
+			do_div(len, mp->m_sb.sb_rextsize);
+			error = xfs_rtfree_extent(tp, bno, (xfs_extlen_t)len);
+			if (error)
+				goto done;
+			do_fx = 0;
+			nblks = len * mp->m_sb.sb_rextsize;
+			qfield = XFS_TRANS_DQ_RTBCOUNT;
+		}
 		/*
-		 * If it's the case where the directory code is running
-		 * with no block reservation, and the deleted block is in
-		 * the middle of its extent, and the resulting insert
-		 * of an extent would cause transformation to btree format,
-		 * then reject it.  The calling code will then swap
-		 * blocks around instead.
-		 * We have to do this now, rather than waiting for the
-		 * conversion to btree format, since the transaction
-		 * will be dirty.
+		 * Ordinary allocation.
 		 */
-		if (!wasdel && xfs_trans_get_block_res(tp) == 0 &&
-		    XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS &&
-		    XFS_IFORK_NEXTENTS(ip, whichfork) >= /* Note the >= */
-			XFS_IFORK_MAXEXT(ip, whichfork) &&
-		    del.br_startoff > got.br_startoff &&
-		    del.br_startoff + del.br_blockcount <
-		    got.br_startoff + got.br_blockcount) {
-			error = XFS_ERROR(ENOSPC);
-			goto error0;
+		else {
+			do_fx = 1;
+			nblks = del->br_blockcount;
+			qfield = XFS_TRANS_DQ_BCOUNT;
 		}
-		error = xfs_bmap_del_extent(ip, tp, &lastx, flist, cur, &del,
-				&tmp_logflags, whichfork);
-		logflags |= tmp_logflags;
-		if (error)
-			goto error0;
-		bno = del.br_startoff - 1;
-nodelete:
 		/*
-		 * If not done go on to the next (previous) record.
+		 * Set up del_endblock and cur for later.
 		 */
-		if (bno != (xfs_fileoff_t)-1 && bno >= start) {
-			if (lastx >= 0) {
-				ep = xfs_iext_get_ext(ifp, lastx);
-				if (xfs_bmbt_get_startoff(ep) > bno) {
-					if (--lastx >= 0)
-						ep = xfs_iext_get_ext(ifp,
-								      lastx);
-				}
-				xfs_bmbt_get_all(ep, &got);
-			}
-			extno++;
+		del_endblock = del->br_startblock + del->br_blockcount;
+		if (cur) {
+			if ((error = xfs_bmbt_lookup_eq(cur, got.br_startoff,
+					got.br_startblock, got.br_blockcount,
+					&i)))
+				goto done;
+			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
 		}
-	}
-	*done = bno == (xfs_fileoff_t)-1 || bno < start || lastx < 0;
-
-	/*
-	 * Convert to a btree if necessary.
-	 */
-	if (xfs_bmap_needs_btree(ip, whichfork)) {
-		ASSERT(cur == NULL);
-		error = xfs_bmap_extents_to_btree(tp, ip, firstblock, flist,
-			&cur, 0, &tmp_logflags, whichfork);
-		logflags |= tmp_logflags;
-		if (error)
-			goto error0;
+		da_old = da_new = 0;
+	} else {
+		da_old = startblockval(got.br_startblock);
+		da_new = 0;
+		nblks = 0;
+		do_fx = 0;
 	}
 	/*
-	 * transform from btree to extents, give it cur
+	 * Set flag value to use in switch statement.
+	 * Left-contig is 2, right-contig is 1.
 	 */
-	else if (xfs_bmap_wants_extents(ip, whichfork)) {
-		ASSERT(cur != NULL);
-		error = xfs_bmap_btree_to_extents(tp, ip, cur, &tmp_logflags,
-			whichfork);
-		logflags |= tmp_logflags;
-		if (error)
-			goto error0;
+	switch (((got.br_startoff == del->br_startoff) << 1) |
+		(got_endoff == del_endoff)) {
+	case 3:
+		/*
+		 * Matches the whole extent.  Delete the entry.
+		 */
+		xfs_iext_remove(ip, *idx, 1,
+				whichfork == XFS_ATTR_FORK ? BMAP_ATTRFORK : 0);
+		--*idx;
+		if (delay)
+			break;
+
+		XFS_IFORK_NEXT_SET(ip, whichfork,
+			XFS_IFORK_NEXTENTS(ip, whichfork) - 1);
+		flags |= XFS_ILOG_CORE;
+		if (!cur) {
+			flags |= xfs_ilog_fext(whichfork);
+			break;
+		}
+		if ((error = xfs_btree_delete(cur, &i)))
+			goto done;
+		XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+		break;
+
+	case 2:
+		/*
+		 * Deleting the first part of the extent.
+		 */
+		trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_);
+		xfs_bmbt_set_startoff(ep, del_endoff);
+		temp = got.br_blockcount - del->br_blockcount;
+		xfs_bmbt_set_blockcount(ep, temp);
+		if (delay) {
+			temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp),
+				da_old);
+			xfs_bmbt_set_startblock(ep, nullstartblock((int)temp));
+			trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_);
+			da_new = temp;
+			break;
+		}
+		xfs_bmbt_set_startblock(ep, del_endblock);
+		trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_);
+		if (!cur) {
+			flags |= xfs_ilog_fext(whichfork);
+			break;
+		}
+		if ((error = xfs_bmbt_update(cur, del_endoff, del_endblock,
+				got.br_blockcount - del->br_blockcount,
+				got.br_state)))
+			goto done;
+		break;
+
+	case 1:
+		/*
+		 * Deleting the last part of the extent.
+		 */
+		temp = got.br_blockcount - del->br_blockcount;
+		trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_);
+		xfs_bmbt_set_blockcount(ep, temp);
+		if (delay) {
+			temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp),
+				da_old);
+			xfs_bmbt_set_startblock(ep, nullstartblock((int)temp));
+			trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_);
+			da_new = temp;
+			break;
+		}
+		trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_);
+		if (!cur) {
+			flags |= xfs_ilog_fext(whichfork);
+			break;
+		}
+		if ((error = xfs_bmbt_update(cur, got.br_startoff,
+				got.br_startblock,
+				got.br_blockcount - del->br_blockcount,
+				got.br_state)))
+			goto done;
+		break;
+
+	case 0:
+		/*
+		 * Deleting the middle of the extent.
+		 */
+		temp = del->br_startoff - got.br_startoff;
+		trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_);
+		xfs_bmbt_set_blockcount(ep, temp);
+		new.br_startoff = del_endoff;
+		temp2 = got_endoff - del_endoff;
+		new.br_blockcount = temp2;
+		new.br_state = got.br_state;
+		if (!delay) {
+			new.br_startblock = del_endblock;
+			flags |= XFS_ILOG_CORE;
+			if (cur) {
+				if ((error = xfs_bmbt_update(cur,
+						got.br_startoff,
+						got.br_startblock, temp,
+						got.br_state)))
+					goto done;
+				if ((error = xfs_btree_increment(cur, 0, &i)))
+					goto done;
+				cur->bc_rec.b = new;
+				error = xfs_btree_insert(cur, &i);
+				if (error && error != ENOSPC)
+					goto done;
+				/*
+				 * If get no-space back from btree insert,
+				 * it tried a split, and we have a zero
+				 * block reservation.
+				 * Fix up our state and return the error.
+				 */
+				if (error == ENOSPC) {
+					/*
+					 * Reset the cursor, don't trust
+					 * it after any insert operation.
+					 */
+					if ((error = xfs_bmbt_lookup_eq(cur,
+							got.br_startoff,
+							got.br_startblock,
+							temp, &i)))
+						goto done;
+					XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+					/*
+					 * Update the btree record back
+					 * to the original value.
+					 */
+					if ((error = xfs_bmbt_update(cur,
+							got.br_startoff,
+							got.br_startblock,
+							got.br_blockcount,
+							got.br_state)))
+						goto done;
+					/*
+					 * Reset the extent record back
+					 * to the original value.
+					 */
+					xfs_bmbt_set_blockcount(ep,
+						got.br_blockcount);
+					flags = 0;
+					error = XFS_ERROR(ENOSPC);
+					goto done;
+				}
+				XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+			} else
+				flags |= xfs_ilog_fext(whichfork);
+			XFS_IFORK_NEXT_SET(ip, whichfork,
+				XFS_IFORK_NEXTENTS(ip, whichfork) + 1);
+		} else {
+			ASSERT(whichfork == XFS_DATA_FORK);
+			temp = xfs_bmap_worst_indlen(ip, temp);
+			xfs_bmbt_set_startblock(ep, nullstartblock((int)temp));
+			temp2 = xfs_bmap_worst_indlen(ip, temp2);
+			new.br_startblock = nullstartblock((int)temp2);
+			da_new = temp + temp2;
+			while (da_new > da_old) {
+				if (temp) {
+					temp--;
+					da_new--;
+					xfs_bmbt_set_startblock(ep,
+						nullstartblock((int)temp));
+				}
+				if (da_new == da_old)
+					break;
+				if (temp2) {
+					temp2--;
+					da_new--;
+					new.br_startblock =
+						nullstartblock((int)temp2);
+				}
+			}
+		}
+		trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_);
+		xfs_iext_insert(ip, *idx + 1, 1, &new, state);
+		++*idx;
+		break;
 	}
 	/*
-	 * transform from extents to local?
+	 * If we need to, add to list of extents to delete.
 	 */
-	error = 0;
-error0:
+	if (do_fx)
+		xfs_bmap_add_free(del->br_startblock, del->br_blockcount, flist,
+			mp);
 	/*
-	 * Log everything.  Do this after conversion, there's no point in
-	 * logging the extent records if we've converted to btree format.
+	 * Adjust inode # blocks in the file.
 	 */
-	if ((logflags & xfs_ilog_fext(whichfork)) &&
-	    XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS)
-		logflags &= ~xfs_ilog_fext(whichfork);
-	else if ((logflags & xfs_ilog_fbroot(whichfork)) &&
-		 XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE)
-		logflags &= ~xfs_ilog_fbroot(whichfork);
+	if (nblks)
+		ip->i_d.di_nblocks -= nblks;
 	/*
-	 * Log inode even in the error case, if the transaction
-	 * is dirty we'll need to shut down the filesystem.
+	 * Adjust quota data.
 	 */
-	if (logflags)
-		xfs_trans_log_inode(tp, ip, logflags);
-	if (cur) {
-		if (!error) {
-			*firstblock = cur->bc_private.b.firstblock;
-			cur->bc_private.b.allocated = 0;
-		}
-		xfs_btree_del_cursor(cur,
-			error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR);
+	if (qfield)
+		xfs_trans_mod_dquot_byino(tp, ip, qfield, (long)-nblks);
+
+	/*
+	 * Account for change in delayed indirect blocks.
+	 * Nothing to do for disk quota accounting here.
+	 */
+	ASSERT(da_old >= da_new);
+	if (da_old > da_new) {
+		xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS,
+			(int64_t)(da_old - da_new), 0);
 	}
+done:
+	*logflagsp = flags;
 	return error;
 }
 
 /*
- * returns 1 for success, 0 if we failed to map the extent.
+ * Unmap (remove) blocks from a file.
+ * If nexts is nonzero then the number of extents to remove is limited to
+ * that value.  If not all extents in the block range can be removed then
+ * *done is set.
  */
-STATIC int
-xfs_getbmapx_fix_eof_hole(
-	xfs_inode_t		*ip,		/* xfs incore inode pointer */
-	struct getbmapx		*out,		/* output structure */
-	int			prealloced,	/* this is a file with
-						 * preallocated data space */
-	__int64_t		end,		/* last block requested */
-	xfs_fsblock_t		startblock)
+int						/* error */
+xfs_bunmapi(
+	xfs_trans_t		*tp,		/* transaction pointer */
+	struct xfs_inode	*ip,		/* incore inode */
+	xfs_fileoff_t		bno,		/* starting offset to unmap */
+	xfs_filblks_t		len,		/* length to unmap in file */
+	int			flags,		/* misc flags */
+	xfs_extnum_t		nexts,		/* number of extents max */
+	xfs_fsblock_t		*firstblock,	/* first allocated block
+						   controls a.g. for allocs */
+	xfs_bmap_free_t		*flist,		/* i/o: list extents to free */
+	int			*done)		/* set if not done yet */
 {
-	__int64_t		fixlen;
-	xfs_mount_t		*mp;		/* file system mount point */
+	xfs_btree_cur_t		*cur;		/* bmap btree cursor */
+	xfs_bmbt_irec_t		del;		/* extent being deleted */
+	int			eof;		/* is deleting at eof */
+	xfs_bmbt_rec_host_t	*ep;		/* extent record pointer */
+	int			error;		/* error return value */
+	xfs_extnum_t		extno;		/* extent number in list */
+	xfs_bmbt_irec_t		got;		/* current extent record */
 	xfs_ifork_t		*ifp;		/* inode fork pointer */
-	xfs_extnum_t		lastx;		/* last extent pointer */
-	xfs_fileoff_t		fileblock;
-
-	if (startblock == HOLESTARTBLOCK) {
-		mp = ip->i_mount;
-		out->bmv_block = -1;
-		fixlen = XFS_FSB_TO_BB(mp, XFS_B_TO_FSB(mp, XFS_ISIZE(ip)));
-		fixlen -= out->bmv_offset;
-		if (prealloced && out->bmv_offset + out->bmv_length == end) {
-			/* Came to hole at EOF. Trim it. */
-			if (fixlen <= 0)
-				return 0;
-			out->bmv_length = fixlen;
-		}
-	} else {
-		if (startblock == DELAYSTARTBLOCK)
-			out->bmv_block = -2;
-		else
-			out->bmv_block = xfs_fsb_to_db(ip, startblock);
-		fileblock = XFS_BB_TO_FSB(ip->i_mount, out->bmv_offset);
-		ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
-		if (xfs_iext_bno_to_ext(ifp, fileblock, &lastx) &&
-		   (lastx == (ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t))-1))
-			out->bmv_oflags |= BMV_OF_LAST;
-	}
-
-	return 1;
-}
-
-/*
- * Get inode's extents as described in bmv, and format for output.
- * Calls formatter to fill the user's buffer until all extents
- * are mapped, until the passed-in bmv->bmv_count slots have
- * been filled, or until the formatter short-circuits the loop,
- * if it is tracking filled-in extents on its own.
- */
-int						/* error code */
-xfs_getbmap(
-	xfs_inode_t		*ip,
-	struct getbmapx		*bmv,		/* user bmap structure */
-	xfs_bmap_format_t	formatter,	/* format to user */
-	void			*arg)		/* formatter arg */
-{
-	__int64_t		bmvend;		/* last block requested */
-	int			error = 0;	/* return value */
-	__int64_t		fixlen;		/* length for -1 case */
-	int			i;		/* extent number */
-	int			lock;		/* lock state */
-	xfs_bmbt_irec_t		*map;		/* buffer for user's data */
-	xfs_mount_t		*mp;		/* file system mount point */
-	int			nex;		/* # of user extents can do */
-	int			nexleft;	/* # of user extents left */
-	int			subnex;		/* # of bmapi's can do */
-	int			nmap;		/* number of map entries */
-	struct getbmapx		*out;		/* output structure */
-	int			whichfork;	/* data or attr fork */
-	int			prealloced;	/* this is a file with
-						 * preallocated data space */
-	int			iflags;		/* interface flags */
-	int			bmapi_flags;	/* flags for xfs_bmapi */
-	int			cur_ext = 0;
-
-	mp = ip->i_mount;
-	iflags = bmv->bmv_iflags;
-	whichfork = iflags & BMV_IF_ATTRFORK ? XFS_ATTR_FORK : XFS_DATA_FORK;
-
-	if (whichfork == XFS_ATTR_FORK) {
-		if (XFS_IFORK_Q(ip)) {
-			if (ip->i_d.di_aformat != XFS_DINODE_FMT_EXTENTS &&
-			    ip->i_d.di_aformat != XFS_DINODE_FMT_BTREE &&
-			    ip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL)
-				return XFS_ERROR(EINVAL);
-		} else if (unlikely(
-			   ip->i_d.di_aformat != 0 &&
-			   ip->i_d.di_aformat != XFS_DINODE_FMT_EXTENTS)) {
-			XFS_ERROR_REPORT("xfs_getbmap", XFS_ERRLEVEL_LOW,
-					 ip->i_mount);
-			return XFS_ERROR(EFSCORRUPTED);
-		}
-
-		prealloced = 0;
-		fixlen = 1LL << 32;
-	} else {
-		if (ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS &&
-		    ip->i_d.di_format != XFS_DINODE_FMT_BTREE &&
-		    ip->i_d.di_format != XFS_DINODE_FMT_LOCAL)
-			return XFS_ERROR(EINVAL);
-
-		if (xfs_get_extsz_hint(ip) ||
-		    ip->i_d.di_flags & (XFS_DIFLAG_PREALLOC|XFS_DIFLAG_APPEND)){
-			prealloced = 1;
-			fixlen = mp->m_super->s_maxbytes;
-		} else {
-			prealloced = 0;
-			fixlen = XFS_ISIZE(ip);
-		}
-	}
-
-	if (bmv->bmv_length == -1) {
-		fixlen = XFS_FSB_TO_BB(mp, XFS_B_TO_FSB(mp, fixlen));
-		bmv->bmv_length =
-			max_t(__int64_t, fixlen - bmv->bmv_offset, 0);
-	} else if (bmv->bmv_length == 0) {
-		bmv->bmv_entries = 0;
-		return 0;
-	} else if (bmv->bmv_length < 0) {
-		return XFS_ERROR(EINVAL);
-	}
-
-	nex = bmv->bmv_count - 1;
-	if (nex <= 0)
-		return XFS_ERROR(EINVAL);
-	bmvend = bmv->bmv_offset + bmv->bmv_length;
-
-
-	if (bmv->bmv_count > ULONG_MAX / sizeof(struct getbmapx))
-		return XFS_ERROR(ENOMEM);
-	out = kmem_zalloc(bmv->bmv_count * sizeof(struct getbmapx), KM_MAYFAIL);
-	if (!out) {
-		out = kmem_zalloc_large(bmv->bmv_count *
-					sizeof(struct getbmapx));
-		if (!out)
-			return XFS_ERROR(ENOMEM);
-	}
-
-	xfs_ilock(ip, XFS_IOLOCK_SHARED);
-	if (whichfork == XFS_DATA_FORK && !(iflags & BMV_IF_DELALLOC)) {
-		if (ip->i_delayed_blks || XFS_ISIZE(ip) > ip->i_d.di_size) {
-			error = -filemap_write_and_wait(VFS_I(ip)->i_mapping);
-			if (error)
-				goto out_unlock_iolock;
-		}
-		/*
-		 * even after flushing the inode, there can still be delalloc
-		 * blocks on the inode beyond EOF due to speculative
-		 * preallocation. These are not removed until the release
-		 * function is called or the inode is inactivated. Hence we
-		 * cannot assert here that ip->i_delayed_blks == 0.
-		 */
-	}
-
-	lock = xfs_ilock_map_shared(ip);
-
-	/*
-	 * Don't let nex be bigger than the number of extents
-	 * we can have assuming alternating holes and real extents.
-	 */
-	if (nex > XFS_IFORK_NEXTENTS(ip, whichfork) * 2 + 1)
-		nex = XFS_IFORK_NEXTENTS(ip, whichfork) * 2 + 1;
-
-	bmapi_flags = xfs_bmapi_aflag(whichfork);
-	if (!(iflags & BMV_IF_PREALLOC))
-		bmapi_flags |= XFS_BMAPI_IGSTATE;
-
-	/*
-	 * Allocate enough space to handle "subnex" maps at a time.
-	 */
-	error = ENOMEM;
-	subnex = 16;
-	map = kmem_alloc(subnex * sizeof(*map), KM_MAYFAIL | KM_NOFS);
-	if (!map)
-		goto out_unlock_ilock;
+	int			isrt;		/* freeing in rt area */
+	xfs_extnum_t		lastx;		/* last extent index used */
+	int			logflags;	/* transaction logging flags */
+	xfs_extlen_t		mod;		/* rt extent offset */
+	xfs_mount_t		*mp;		/* mount structure */
+	xfs_extnum_t		nextents;	/* number of file extents */
+	xfs_bmbt_irec_t		prev;		/* previous extent record */
+	xfs_fileoff_t		start;		/* first file offset deleted */
+	int			tmp_logflags;	/* partial logging flags */
+	int			wasdel;		/* was a delayed alloc extent */
+	int			whichfork;	/* data or attribute fork */
+	xfs_fsblock_t		sum;
 
-	bmv->bmv_entries = 0;
+	trace_xfs_bunmap(ip, bno, len, flags, _RET_IP_);
 
-	if (XFS_IFORK_NEXTENTS(ip, whichfork) == 0 &&
-	    (whichfork == XFS_ATTR_FORK || !(iflags & BMV_IF_DELALLOC))) {
-		error = 0;
-		goto out_free_map;
+	whichfork = (flags & XFS_BMAPI_ATTRFORK) ?
+		XFS_ATTR_FORK : XFS_DATA_FORK;
+	ifp = XFS_IFORK_PTR(ip, whichfork);
+	if (unlikely(
+	    XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
+	    XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE)) {
+		XFS_ERROR_REPORT("xfs_bunmapi", XFS_ERRLEVEL_LOW,
+				 ip->i_mount);
+		return XFS_ERROR(EFSCORRUPTED);
 	}
+	mp = ip->i_mount;
+	if (XFS_FORCED_SHUTDOWN(mp))
+		return XFS_ERROR(EIO);
 
-	nexleft = nex;
+	ASSERT(len > 0);
+	ASSERT(nexts >= 0);
 
-	do {
-		nmap = (nexleft > subnex) ? subnex : nexleft;
-		error = xfs_bmapi_read(ip, XFS_BB_TO_FSBT(mp, bmv->bmv_offset),
-				       XFS_BB_TO_FSB(mp, bmv->bmv_length),
-				       map, &nmap, bmapi_flags);
-		if (error)
-			goto out_free_map;
-		ASSERT(nmap <= subnex);
+	if (!(ifp->if_flags & XFS_IFEXTENTS) &&
+	    (error = xfs_iread_extents(tp, ip, whichfork)))
+		return error;
+	nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
+	if (nextents == 0) {
+		*done = 1;
+		return 0;
+	}
+	XFS_STATS_INC(xs_blk_unmap);
+	isrt = (whichfork == XFS_DATA_FORK) && XFS_IS_REALTIME_INODE(ip);
+	start = bno;
+	bno = start + len - 1;
+	ep = xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got,
+		&prev);
 
-		for (i = 0; i < nmap && nexleft && bmv->bmv_length; i++) {
-			out[cur_ext].bmv_oflags = 0;
-			if (map[i].br_state == XFS_EXT_UNWRITTEN)
-				out[cur_ext].bmv_oflags |= BMV_OF_PREALLOC;
-			else if (map[i].br_startblock == DELAYSTARTBLOCK)
-				out[cur_ext].bmv_oflags |= BMV_OF_DELALLOC;
-			out[cur_ext].bmv_offset =
-				XFS_FSB_TO_BB(mp, map[i].br_startoff);
-			out[cur_ext].bmv_length =
-				XFS_FSB_TO_BB(mp, map[i].br_blockcount);
-			out[cur_ext].bmv_unused1 = 0;
-			out[cur_ext].bmv_unused2 = 0;
+	/*
+	 * Check to see if the given block number is past the end of the
+	 * file, back up to the last block if so...
+	 */
+	if (eof) {
+		ep = xfs_iext_get_ext(ifp, --lastx);
+		xfs_bmbt_get_all(ep, &got);
+		bno = got.br_startoff + got.br_blockcount - 1;
+	}
+	logflags = 0;
+	if (ifp->if_flags & XFS_IFBROOT) {
+		ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE);
+		cur = xfs_bmbt_init_cursor(mp, tp, ip, whichfork);
+		cur->bc_private.b.firstblock = *firstblock;
+		cur->bc_private.b.flist = flist;
+		cur->bc_private.b.flags = 0;
+	} else
+		cur = NULL;
+
+	if (isrt) {
+		/*
+		 * Synchronize by locking the bitmap inode.
+		 */
+		xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL);
+		xfs_trans_ijoin(tp, mp->m_rbmip, XFS_ILOCK_EXCL);
+	}
 
+	extno = 0;
+	while (bno != (xfs_fileoff_t)-1 && bno >= start && lastx >= 0 &&
+	       (nexts == 0 || extno < nexts)) {
+		/*
+		 * Is the found extent after a hole in which bno lives?
+		 * Just back up to the previous extent, if so.
+		 */
+		if (got.br_startoff > bno) {
+			if (--lastx < 0)
+				break;
+			ep = xfs_iext_get_ext(ifp, lastx);
+			xfs_bmbt_get_all(ep, &got);
+		}
+		/*
+		 * Is the last block of this extent before the range
+		 * we're supposed to delete?  If so, we're done.
+		 */
+		bno = XFS_FILEOFF_MIN(bno,
+			got.br_startoff + got.br_blockcount - 1);
+		if (bno < start)
+			break;
+		/*
+		 * Then deal with the (possibly delayed) allocated space
+		 * we found.
+		 */
+		ASSERT(ep != NULL);
+		del = got;
+		wasdel = isnullstartblock(del.br_startblock);
+		if (got.br_startoff < start) {
+			del.br_startoff = start;
+			del.br_blockcount -= start - got.br_startoff;
+			if (!wasdel)
+				del.br_startblock += start - got.br_startoff;
+		}
+		if (del.br_startoff + del.br_blockcount > bno + 1)
+			del.br_blockcount = bno + 1 - del.br_startoff;
+		sum = del.br_startblock + del.br_blockcount;
+		if (isrt &&
+		    (mod = do_mod(sum, mp->m_sb.sb_rextsize))) {
 			/*
-			 * delayed allocation extents that start beyond EOF can
-			 * occur due to speculative EOF allocation when the
-			 * delalloc extent is larger than the largest freespace
-			 * extent at conversion time. These extents cannot be
-			 * converted by data writeback, so can exist here even
-			 * if we are not supposed to be finding delalloc
-			 * extents.
+			 * Realtime extent not lined up at the end.
+			 * The extent could have been split into written
+			 * and unwritten pieces, or we could just be
+			 * unmapping part of it.  But we can't really
+			 * get rid of part of a realtime extent.
 			 */
-			if (map[i].br_startblock == DELAYSTARTBLOCK &&
-			    map[i].br_startoff <= XFS_B_TO_FSB(mp, XFS_ISIZE(ip)))
-				ASSERT((iflags & BMV_IF_DELALLOC) != 0);
-
-                        if (map[i].br_startblock == HOLESTARTBLOCK &&
-			    whichfork == XFS_ATTR_FORK) {
-				/* came to the end of attribute fork */
-				out[cur_ext].bmv_oflags |= BMV_OF_LAST;
-				goto out_free_map;
+			if (del.br_state == XFS_EXT_UNWRITTEN ||
+			    !xfs_sb_version_hasextflgbit(&mp->m_sb)) {
+				/*
+				 * This piece is unwritten, or we're not
+				 * using unwritten extents.  Skip over it.
+				 */
+				ASSERT(bno >= mod);
+				bno -= mod > del.br_blockcount ?
+					del.br_blockcount : mod;
+				if (bno < got.br_startoff) {
+					if (--lastx >= 0)
+						xfs_bmbt_get_all(xfs_iext_get_ext(
+							ifp, lastx), &got);
+				}
+				continue;
 			}
-
-			if (!xfs_getbmapx_fix_eof_hole(ip, &out[cur_ext],
-					prealloced, bmvend,
-					map[i].br_startblock))
-				goto out_free_map;
-
-			bmv->bmv_offset =
-				out[cur_ext].bmv_offset +
-				out[cur_ext].bmv_length;
-			bmv->bmv_length =
-				max_t(__int64_t, 0, bmvend - bmv->bmv_offset);
-
 			/*
-			 * In case we don't want to return the hole,
-			 * don't increase cur_ext so that we can reuse
-			 * it in the next loop.
+			 * It's written, turn it unwritten.
+			 * This is better than zeroing it.
 			 */
-			if ((iflags & BMV_IF_NO_HOLES) &&
-			    map[i].br_startblock == HOLESTARTBLOCK) {
-				memset(&out[cur_ext], 0, sizeof(out[cur_ext]));
+			ASSERT(del.br_state == XFS_EXT_NORM);
+			ASSERT(xfs_trans_get_block_res(tp) > 0);
+			/*
+			 * If this spans a realtime extent boundary,
+			 * chop it back to the start of the one we end at.
+			 */
+			if (del.br_blockcount > mod) {
+				del.br_startoff += del.br_blockcount - mod;
+				del.br_startblock += del.br_blockcount - mod;
+				del.br_blockcount = mod;
+			}
+			del.br_state = XFS_EXT_UNWRITTEN;
+			error = xfs_bmap_add_extent_unwritten_real(tp, ip,
+					&lastx, &cur, &del, firstblock, flist,
+					&logflags);
+			if (error)
+				goto error0;
+			goto nodelete;
+		}
+		if (isrt && (mod = do_mod(del.br_startblock, mp->m_sb.sb_rextsize))) {
+			/*
+			 * Realtime extent is lined up at the end but not
+			 * at the front.  We'll get rid of full extents if
+			 * we can.
+			 */
+			mod = mp->m_sb.sb_rextsize - mod;
+			if (del.br_blockcount > mod) {
+				del.br_blockcount -= mod;
+				del.br_startoff += mod;
+				del.br_startblock += mod;
+			} else if ((del.br_startoff == start &&
+				    (del.br_state == XFS_EXT_UNWRITTEN ||
+				     xfs_trans_get_block_res(tp) == 0)) ||
+				   !xfs_sb_version_hasextflgbit(&mp->m_sb)) {
+				/*
+				 * Can't make it unwritten.  There isn't
+				 * a full extent here so just skip it.
+				 */
+				ASSERT(bno >= del.br_blockcount);
+				bno -= del.br_blockcount;
+				if (got.br_startoff > bno) {
+					if (--lastx >= 0) {
+						ep = xfs_iext_get_ext(ifp,
+								      lastx);
+						xfs_bmbt_get_all(ep, &got);
+					}
+				}
 				continue;
+			} else if (del.br_state == XFS_EXT_UNWRITTEN) {
+				/*
+				 * This one is already unwritten.
+				 * It must have a written left neighbor.
+				 * Unwrite the killed part of that one and
+				 * try again.
+				 */
+				ASSERT(lastx > 0);
+				xfs_bmbt_get_all(xfs_iext_get_ext(ifp,
+						lastx - 1), &prev);
+				ASSERT(prev.br_state == XFS_EXT_NORM);
+				ASSERT(!isnullstartblock(prev.br_startblock));
+				ASSERT(del.br_startblock ==
+				       prev.br_startblock + prev.br_blockcount);
+				if (prev.br_startoff < start) {
+					mod = start - prev.br_startoff;
+					prev.br_blockcount -= mod;
+					prev.br_startblock += mod;
+					prev.br_startoff = start;
+				}
+				prev.br_state = XFS_EXT_UNWRITTEN;
+				lastx--;
+				error = xfs_bmap_add_extent_unwritten_real(tp,
+						ip, &lastx, &cur, &prev,
+						firstblock, flist, &logflags);
+				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_unwritten_real(tp,
+						ip, &lastx, &cur, &del,
+						firstblock, flist, &logflags);
+				if (error)
+					goto error0;
+				goto nodelete;
 			}
-
-			nexleft--;
-			bmv->bmv_entries++;
-			cur_ext++;
 		}
-	} while (nmap && nexleft && bmv->bmv_length);
-
- out_free_map:
-	kmem_free(map);
- out_unlock_ilock:
-	xfs_iunlock_map_shared(ip, lock);
- out_unlock_iolock:
-	xfs_iunlock(ip, XFS_IOLOCK_SHARED);
-
-	for (i = 0; i < cur_ext; i++) {
-		int full = 0;	/* user array is full */
-
-		/* format results & advance arg */
-		error = formatter(&arg, &out[i], &full);
-		if (error || full)
-			break;
-	}
-
-	if (is_vmalloc_addr(out))
-		kmem_free_large(out);
-	else
-		kmem_free(out);
-	return error;
-}
-
-#ifdef DEBUG
-STATIC struct xfs_buf *
-xfs_bmap_get_bp(
-	struct xfs_btree_cur	*cur,
-	xfs_fsblock_t		bno)
-{
-	struct xfs_log_item_desc *lidp;
-	int			i;
-
-	if (!cur)
-		return NULL;
-
-	for (i = 0; i < XFS_BTREE_MAXLEVELS; i++) {
-		if (!cur->bc_bufs[i])
-			break;
-		if (XFS_BUF_ADDR(cur->bc_bufs[i]) == bno)
-			return cur->bc_bufs[i];
-	}
-
-	/* Chase down all the log items to see if the bp is there */
-	list_for_each_entry(lidp, &cur->bc_tp->t_items, lid_trans) {
-		struct xfs_buf_log_item	*bip;
-		bip = (struct xfs_buf_log_item *)lidp->lid_item;
-		if (bip->bli_item.li_type == XFS_LI_BUF &&
-		    XFS_BUF_ADDR(bip->bli_buf) == bno)
-			return bip->bli_buf;
-	}
-
-	return NULL;
-}
-
-STATIC void
-xfs_check_block(
-	struct xfs_btree_block	*block,
-	xfs_mount_t		*mp,
-	int			root,
-	short			sz)
-{
-	int			i, j, dmxr;
-	__be64			*pp, *thispa;	/* pointer to block address */
-	xfs_bmbt_key_t		*prevp, *keyp;
-
-	ASSERT(be16_to_cpu(block->bb_level) > 0);
-
-	prevp = NULL;
-	for( i = 1; i <= xfs_btree_get_numrecs(block); i++) {
-		dmxr = mp->m_bmap_dmxr[0];
-		keyp = XFS_BMBT_KEY_ADDR(mp, block, i);
+		if (wasdel) {
+			ASSERT(startblockval(del.br_startblock) > 0);
+			/* Update realtime/data freespace, unreserve quota */
+			if (isrt) {
+				xfs_filblks_t rtexts;
 
-		if (prevp) {
-			ASSERT(be64_to_cpu(prevp->br_startoff) <
-			       be64_to_cpu(keyp->br_startoff));
+				rtexts = XFS_FSB_TO_B(mp, del.br_blockcount);
+				do_div(rtexts, mp->m_sb.sb_rextsize);
+				xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS,
+						(int64_t)rtexts, 0);
+				(void)xfs_trans_reserve_quota_nblks(NULL,
+					ip, -((long)del.br_blockcount), 0,
+					XFS_QMOPT_RES_RTBLKS);
+			} else {
+				xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS,
+						(int64_t)del.br_blockcount, 0);
+				(void)xfs_trans_reserve_quota_nblks(NULL,
+					ip, -((long)del.br_blockcount), 0,
+					XFS_QMOPT_RES_REGBLKS);
+			}
+			ip->i_delayed_blks -= del.br_blockcount;
+			if (cur)
+				cur->bc_private.b.flags |=
+					XFS_BTCUR_BPRV_WASDEL;
+		} else if (cur)
+			cur->bc_private.b.flags &= ~XFS_BTCUR_BPRV_WASDEL;
+		/*
+		 * If it's the case where the directory code is running
+		 * with no block reservation, and the deleted block is in
+		 * the middle of its extent, and the resulting insert
+		 * of an extent would cause transformation to btree format,
+		 * then reject it.  The calling code will then swap
+		 * blocks around instead.
+		 * We have to do this now, rather than waiting for the
+		 * conversion to btree format, since the transaction
+		 * will be dirty.
+		 */
+		if (!wasdel && xfs_trans_get_block_res(tp) == 0 &&
+		    XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS &&
+		    XFS_IFORK_NEXTENTS(ip, whichfork) >= /* Note the >= */
+			XFS_IFORK_MAXEXT(ip, whichfork) &&
+		    del.br_startoff > got.br_startoff &&
+		    del.br_startoff + del.br_blockcount <
+		    got.br_startoff + got.br_blockcount) {
+			error = XFS_ERROR(ENOSPC);
+			goto error0;
 		}
-		prevp = keyp;
-
+		error = xfs_bmap_del_extent(ip, tp, &lastx, flist, cur, &del,
+				&tmp_logflags, whichfork);
+		logflags |= tmp_logflags;
+		if (error)
+			goto error0;
+		bno = del.br_startoff - 1;
+nodelete:
 		/*
-		 * Compare the block numbers to see if there are dups.
+		 * If not done go on to the next (previous) record.
 		 */
-		if (root)
-			pp = XFS_BMAP_BROOT_PTR_ADDR(mp, block, i, sz);
-		else
-			pp = XFS_BMBT_PTR_ADDR(mp, block, i, dmxr);
-
-		for (j = i+1; j <= be16_to_cpu(block->bb_numrecs); j++) {
-			if (root)
-				thispa = XFS_BMAP_BROOT_PTR_ADDR(mp, block, j, sz);
-			else
-				thispa = XFS_BMBT_PTR_ADDR(mp, block, j, dmxr);
-			if (*thispa == *pp) {
-				xfs_warn(mp, "%s: thispa(%d) == pp(%d) %Ld",
-					__func__, j, i,
-					(unsigned long long)be64_to_cpu(*thispa));
-				panic("%s: ptrs are equal in node\n",
-					__func__);
+		if (bno != (xfs_fileoff_t)-1 && bno >= start) {
+			if (lastx >= 0) {
+				ep = xfs_iext_get_ext(ifp, lastx);
+				if (xfs_bmbt_get_startoff(ep) > bno) {
+					if (--lastx >= 0)
+						ep = xfs_iext_get_ext(ifp,
+								      lastx);
+				}
+				xfs_bmbt_get_all(ep, &got);
 			}
+			extno++;
 		}
 	}
-}
-
-/*
- * Check that the extents for the inode ip are in the right order in all
- * btree leaves.
- */
-
-STATIC void
-xfs_bmap_check_leaf_extents(
-	xfs_btree_cur_t		*cur,	/* btree cursor or null */
-	xfs_inode_t		*ip,		/* incore inode pointer */
-	int			whichfork)	/* data or attr fork */
-{
-	struct xfs_btree_block	*block;	/* current btree block */
-	xfs_fsblock_t		bno;	/* block # of "block" */
-	xfs_buf_t		*bp;	/* buffer for "block" */
-	int			error;	/* error return value */
-	xfs_extnum_t		i=0, j;	/* index into the extents list */
-	xfs_ifork_t		*ifp;	/* fork structure */
-	int			level;	/* btree level, for checking */
-	xfs_mount_t		*mp;	/* file system mount structure */
-	__be64			*pp;	/* pointer to block address */
-	xfs_bmbt_rec_t		*ep;	/* pointer to current extent */
-	xfs_bmbt_rec_t		last = {0, 0}; /* last extent in prev block */
-	xfs_bmbt_rec_t		*nextp;	/* pointer to next extent */
-	int			bp_release = 0;
-
-	if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE) {
-		return;
-	}
-
-	bno = NULLFSBLOCK;
-	mp = ip->i_mount;
-	ifp = XFS_IFORK_PTR(ip, whichfork);
-	block = ifp->if_broot;
-	/*
-	 * Root level must use BMAP_BROOT_PTR_ADDR macro to get ptr out.
-	 */
-	level = be16_to_cpu(block->bb_level);
-	ASSERT(level > 0);
-	xfs_check_block(block, mp, 1, ifp->if_broot_bytes);
-	pp = XFS_BMAP_BROOT_PTR_ADDR(mp, block, 1, ifp->if_broot_bytes);
-	bno = be64_to_cpu(*pp);
-
-	ASSERT(bno != NULLDFSBNO);
-	ASSERT(XFS_FSB_TO_AGNO(mp, bno) < mp->m_sb.sb_agcount);
-	ASSERT(XFS_FSB_TO_AGBNO(mp, bno) < mp->m_sb.sb_agblocks);
+	*done = bno == (xfs_fileoff_t)-1 || bno < start || lastx < 0;
 
 	/*
-	 * Go down the tree until leaf level is reached, following the first
-	 * pointer (leftmost) at each level.
+	 * Convert to a btree if necessary.
 	 */
-	while (level-- > 0) {
-		/* See if buf is in cur first */
-		bp_release = 0;
-		bp = xfs_bmap_get_bp(cur, XFS_FSB_TO_DADDR(mp, bno));
-		if (!bp) {
-			bp_release = 1;
-			error = xfs_btree_read_bufl(mp, NULL, bno, 0, &bp,
-						XFS_BMAP_BTREE_REF,
-						&xfs_bmbt_buf_ops);
-			if (error)
-				goto error_norelse;
-		}
-		block = XFS_BUF_TO_BLOCK(bp);
-		XFS_WANT_CORRUPTED_GOTO(
-			xfs_bmap_sanity_check(mp, bp, level),
-			error0);
-		if (level == 0)
-			break;
-
-		/*
-		 * Check this block for basic sanity (increasing keys and
-		 * no duplicate blocks).
-		 */
-
-		xfs_check_block(block, mp, 0, 0);
-		pp = XFS_BMBT_PTR_ADDR(mp, block, 1, mp->m_bmap_dmxr[1]);
-		bno = be64_to_cpu(*pp);
-		XFS_WANT_CORRUPTED_GOTO(XFS_FSB_SANITY_CHECK(mp, bno), error0);
-		if (bp_release) {
-			bp_release = 0;
-			xfs_trans_brelse(NULL, bp);
-		}
+	if (xfs_bmap_needs_btree(ip, whichfork)) {
+		ASSERT(cur == NULL);
+		error = xfs_bmap_extents_to_btree(tp, ip, firstblock, flist,
+			&cur, 0, &tmp_logflags, whichfork);
+		logflags |= tmp_logflags;
+		if (error)
+			goto error0;
 	}
-
 	/*
-	 * Here with bp and block set to the leftmost leaf node in the tree.
+	 * transform from btree to extents, give it cur
 	 */
-	i = 0;
-
+	else if (xfs_bmap_wants_extents(ip, whichfork)) {
+		ASSERT(cur != NULL);
+		error = xfs_bmap_btree_to_extents(tp, ip, cur, &tmp_logflags,
+			whichfork);
+		logflags |= tmp_logflags;
+		if (error)
+			goto error0;
+	}
 	/*
-	 * Loop over all leaf nodes checking that all extents are in the right order.
+	 * transform from extents to local?
 	 */
-	for (;;) {
-		xfs_fsblock_t	nextbno;
-		xfs_extnum_t	num_recs;
+	error = 0;
+error0:
+	/*
+	 * Log everything.  Do this after conversion, there's no point in
+	 * logging the extent records if we've converted to btree format.
+	 */
+	if ((logflags & xfs_ilog_fext(whichfork)) &&
+	    XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS)
+		logflags &= ~xfs_ilog_fext(whichfork);
+	else if ((logflags & xfs_ilog_fbroot(whichfork)) &&
+		 XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE)
+		logflags &= ~xfs_ilog_fbroot(whichfork);
+	/*
+	 * Log inode even in the error case, if the transaction
+	 * is dirty we'll need to shut down the filesystem.
+	 */
+	if (logflags)
+		xfs_trans_log_inode(tp, ip, logflags);
+	if (cur) {
+		if (!error) {
+			*firstblock = cur->bc_private.b.firstblock;
+			cur->bc_private.b.allocated = 0;
+		}
+		xfs_btree_del_cursor(cur,
+			error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR);
+	}
+	return error;
+}
 
+/*
+ * returns 1 for success, 0 if we failed to map the extent.
+ */
+STATIC int
+xfs_getbmapx_fix_eof_hole(
+	xfs_inode_t		*ip,		/* xfs incore inode pointer */
+	struct getbmapx		*out,		/* output structure */
+	int			prealloced,	/* this is a file with
+						 * preallocated data space */
+	__int64_t		end,		/* last block requested */
+	xfs_fsblock_t		startblock)
+{
+	__int64_t		fixlen;
+	xfs_mount_t		*mp;		/* file system mount point */
+	xfs_ifork_t		*ifp;		/* inode fork pointer */
+	xfs_extnum_t		lastx;		/* last extent pointer */
+	xfs_fileoff_t		fileblock;
 
-		num_recs = xfs_btree_get_numrecs(block);
+	if (startblock == HOLESTARTBLOCK) {
+		mp = ip->i_mount;
+		out->bmv_block = -1;
+		fixlen = XFS_FSB_TO_BB(mp, XFS_B_TO_FSB(mp, XFS_ISIZE(ip)));
+		fixlen -= out->bmv_offset;
+		if (prealloced && out->bmv_offset + out->bmv_length == end) {
+			/* Came to hole at EOF. Trim it. */
+			if (fixlen <= 0)
+				return 0;
+			out->bmv_length = fixlen;
+		}
+	} else {
+		if (startblock == DELAYSTARTBLOCK)
+			out->bmv_block = -2;
+		else
+			out->bmv_block = xfs_fsb_to_db(ip, startblock);
+		fileblock = XFS_BB_TO_FSB(ip->i_mount, out->bmv_offset);
+		ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
+		if (xfs_iext_bno_to_ext(ifp, fileblock, &lastx) &&
+		   (lastx == (ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t))-1))
+			out->bmv_oflags |= BMV_OF_LAST;
+	}
 
-		/*
-		 * Read-ahead the next leaf block, if any.
-		 */
+	return 1;
+}
 
-		nextbno = be64_to_cpu(block->bb_u.l.bb_rightsib);
+/*
+ * Get inode's extents as described in bmv, and format for output.
+ * Calls formatter to fill the user's buffer until all extents
+ * are mapped, until the passed-in bmv->bmv_count slots have
+ * been filled, or until the formatter short-circuits the loop,
+ * if it is tracking filled-in extents on its own.
+ */
+int						/* error code */
+xfs_getbmap(
+	xfs_inode_t		*ip,
+	struct getbmapx		*bmv,		/* user bmap structure */
+	xfs_bmap_format_t	formatter,	/* format to user */
+	void			*arg)		/* formatter arg */
+{
+	__int64_t		bmvend;		/* last block requested */
+	int			error = 0;	/* return value */
+	__int64_t		fixlen;		/* length for -1 case */
+	int			i;		/* extent number */
+	int			lock;		/* lock state */
+	xfs_bmbt_irec_t		*map;		/* buffer for user's data */
+	xfs_mount_t		*mp;		/* file system mount point */
+	int			nex;		/* # of user extents can do */
+	int			nexleft;	/* # of user extents left */
+	int			subnex;		/* # of bmapi's can do */
+	int			nmap;		/* number of map entries */
+	struct getbmapx		*out;		/* output structure */
+	int			whichfork;	/* data or attr fork */
+	int			prealloced;	/* this is a file with
+						 * preallocated data space */
+	int			iflags;		/* interface flags */
+	int			bmapi_flags;	/* flags for xfs_bmapi */
+	int			cur_ext = 0;
 
-		/*
-		 * Check all the extents to make sure they are OK.
-		 * If we had a previous block, the last entry should
-		 * conform with the first entry in this one.
-		 */
+	mp = ip->i_mount;
+	iflags = bmv->bmv_iflags;
+	whichfork = iflags & BMV_IF_ATTRFORK ? XFS_ATTR_FORK : XFS_DATA_FORK;
 
-		ep = XFS_BMBT_REC_ADDR(mp, block, 1);
-		if (i) {
-			ASSERT(xfs_bmbt_disk_get_startoff(&last) +
-			       xfs_bmbt_disk_get_blockcount(&last) <=
-			       xfs_bmbt_disk_get_startoff(ep));
-		}
-		for (j = 1; j < num_recs; j++) {
-			nextp = XFS_BMBT_REC_ADDR(mp, block, j + 1);
-			ASSERT(xfs_bmbt_disk_get_startoff(ep) +
-			       xfs_bmbt_disk_get_blockcount(ep) <=
-			       xfs_bmbt_disk_get_startoff(nextp));
-			ep = nextp;
+	if (whichfork == XFS_ATTR_FORK) {
+		if (XFS_IFORK_Q(ip)) {
+			if (ip->i_d.di_aformat != XFS_DINODE_FMT_EXTENTS &&
+			    ip->i_d.di_aformat != XFS_DINODE_FMT_BTREE &&
+			    ip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL)
+				return XFS_ERROR(EINVAL);
+		} else if (unlikely(
+			   ip->i_d.di_aformat != 0 &&
+			   ip->i_d.di_aformat != XFS_DINODE_FMT_EXTENTS)) {
+			XFS_ERROR_REPORT("xfs_getbmap", XFS_ERRLEVEL_LOW,
+					 ip->i_mount);
+			return XFS_ERROR(EFSCORRUPTED);
 		}
 
-		last = *ep;
-		i += num_recs;
-		if (bp_release) {
-			bp_release = 0;
-			xfs_trans_brelse(NULL, bp);
-		}
-		bno = nextbno;
-		/*
-		 * If we've reached the end, stop.
-		 */
-		if (bno == NULLFSBLOCK)
-			break;
+		prealloced = 0;
+		fixlen = 1LL << 32;
+	} else {
+		if (ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS &&
+		    ip->i_d.di_format != XFS_DINODE_FMT_BTREE &&
+		    ip->i_d.di_format != XFS_DINODE_FMT_LOCAL)
+			return XFS_ERROR(EINVAL);
 
-		bp_release = 0;
-		bp = xfs_bmap_get_bp(cur, XFS_FSB_TO_DADDR(mp, bno));
-		if (!bp) {
-			bp_release = 1;
-			error = xfs_btree_read_bufl(mp, NULL, bno, 0, &bp,
-						XFS_BMAP_BTREE_REF,
-						&xfs_bmbt_buf_ops);
-			if (error)
-				goto error_norelse;
+		if (xfs_get_extsz_hint(ip) ||
+		    ip->i_d.di_flags & (XFS_DIFLAG_PREALLOC|XFS_DIFLAG_APPEND)){
+			prealloced = 1;
+			fixlen = mp->m_super->s_maxbytes;
+		} else {
+			prealloced = 0;
+			fixlen = XFS_ISIZE(ip);
 		}
-		block = XFS_BUF_TO_BLOCK(bp);
 	}
-	if (bp_release) {
-		bp_release = 0;
-		xfs_trans_brelse(NULL, bp);
+
+	if (bmv->bmv_length == -1) {
+		fixlen = XFS_FSB_TO_BB(mp, XFS_B_TO_FSB(mp, fixlen));
+		bmv->bmv_length =
+			max_t(__int64_t, fixlen - bmv->bmv_offset, 0);
+	} else if (bmv->bmv_length == 0) {
+		bmv->bmv_entries = 0;
+		return 0;
+	} else if (bmv->bmv_length < 0) {
+		return XFS_ERROR(EINVAL);
 	}
-	return;
 
-error0:
-	xfs_warn(mp, "%s: at error0", __func__);
-	if (bp_release)
-		xfs_trans_brelse(NULL, bp);
-error_norelse:
-	xfs_warn(mp, "%s: BAD after btree leaves for %d extents",
-		__func__, i);
-	panic("%s: CORRUPTED BTREE OR SOMETHING", __func__);
-	return;
-}
-#endif
+	nex = bmv->bmv_count - 1;
+	if (nex <= 0)
+		return XFS_ERROR(EINVAL);
+	bmvend = bmv->bmv_offset + bmv->bmv_length;
 
-/*
- * Count fsblocks of the given fork.
- */
-int						/* error */
-xfs_bmap_count_blocks(
-	xfs_trans_t		*tp,		/* transaction pointer */
-	xfs_inode_t		*ip,		/* incore inode */
-	int			whichfork,	/* data or attr fork */
-	int			*count)		/* out: count of blocks */
-{
-	struct xfs_btree_block	*block;	/* current btree block */
-	xfs_fsblock_t		bno;	/* block # of "block" */
-	xfs_ifork_t		*ifp;	/* fork structure */
-	int			level;	/* btree level, for checking */
-	xfs_mount_t		*mp;	/* file system mount structure */
-	__be64			*pp;	/* pointer to block address */
 
-	bno = NULLFSBLOCK;
-	mp = ip->i_mount;
-	ifp = XFS_IFORK_PTR(ip, whichfork);
-	if ( XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS ) {
-		xfs_bmap_count_leaves(ifp, 0,
-			ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t),
-			count);
-		return 0;
+	if (bmv->bmv_count > ULONG_MAX / sizeof(struct getbmapx))
+		return XFS_ERROR(ENOMEM);
+	out = kmem_zalloc(bmv->bmv_count * sizeof(struct getbmapx), KM_MAYFAIL);
+	if (!out) {
+		out = kmem_zalloc_large(bmv->bmv_count *
+					sizeof(struct getbmapx));
+		if (!out)
+			return XFS_ERROR(ENOMEM);
+	}
+
+	xfs_ilock(ip, XFS_IOLOCK_SHARED);
+	if (whichfork == XFS_DATA_FORK && !(iflags & BMV_IF_DELALLOC)) {
+		if (ip->i_delayed_blks || XFS_ISIZE(ip) > ip->i_d.di_size) {
+			error = -filemap_write_and_wait(VFS_I(ip)->i_mapping);
+			if (error)
+				goto out_unlock_iolock;
+		}
+		/*
+		 * even after flushing the inode, there can still be delalloc
+		 * blocks on the inode beyond EOF due to speculative
+		 * preallocation. These are not removed until the release
+		 * function is called or the inode is inactivated. Hence we
+		 * cannot assert here that ip->i_delayed_blks == 0.
+		 */
 	}
 
+	lock = xfs_ilock_map_shared(ip);
+
 	/*
-	 * Root level must use BMAP_BROOT_PTR_ADDR macro to get ptr out.
+	 * Don't let nex be bigger than the number of extents
+	 * we can have assuming alternating holes and real extents.
 	 */
-	block = ifp->if_broot;
-	level = be16_to_cpu(block->bb_level);
-	ASSERT(level > 0);
-	pp = XFS_BMAP_BROOT_PTR_ADDR(mp, block, 1, ifp->if_broot_bytes);
-	bno = be64_to_cpu(*pp);
-	ASSERT(bno != NULLDFSBNO);
-	ASSERT(XFS_FSB_TO_AGNO(mp, bno) < mp->m_sb.sb_agcount);
-	ASSERT(XFS_FSB_TO_AGBNO(mp, bno) < mp->m_sb.sb_agblocks);
+	if (nex > XFS_IFORK_NEXTENTS(ip, whichfork) * 2 + 1)
+		nex = XFS_IFORK_NEXTENTS(ip, whichfork) * 2 + 1;
 
-	if (unlikely(xfs_bmap_count_tree(mp, tp, ifp, bno, level, count) < 0)) {
-		XFS_ERROR_REPORT("xfs_bmap_count_blocks(2)", XFS_ERRLEVEL_LOW,
-				 mp);
-		return XFS_ERROR(EFSCORRUPTED);
+	bmapi_flags = xfs_bmapi_aflag(whichfork);
+	if (!(iflags & BMV_IF_PREALLOC))
+		bmapi_flags |= XFS_BMAPI_IGSTATE;
+
+	/*
+	 * Allocate enough space to handle "subnex" maps at a time.
+	 */
+	error = ENOMEM;
+	subnex = 16;
+	map = kmem_alloc(subnex * sizeof(*map), KM_MAYFAIL | KM_NOFS);
+	if (!map)
+		goto out_unlock_ilock;
+
+	bmv->bmv_entries = 0;
+
+	if (XFS_IFORK_NEXTENTS(ip, whichfork) == 0 &&
+	    (whichfork == XFS_ATTR_FORK || !(iflags & BMV_IF_DELALLOC))) {
+		error = 0;
+		goto out_free_map;
 	}
 
-	return 0;
-}
+	nexleft = nex;
 
-/*
- * Recursively walks each level of a btree
- * to count total fsblocks is use.
- */
-STATIC int                                     /* error */
-xfs_bmap_count_tree(
-	xfs_mount_t     *mp,            /* file system mount point */
-	xfs_trans_t     *tp,            /* transaction pointer */
-	xfs_ifork_t	*ifp,		/* inode fork pointer */
-	xfs_fsblock_t   blockno,	/* file system block number */
-	int             levelin,	/* level in btree */
-	int		*count)		/* Count of blocks */
-{
-	int			error;
-	xfs_buf_t		*bp, *nbp;
-	int			level = levelin;
-	__be64			*pp;
-	xfs_fsblock_t           bno = blockno;
-	xfs_fsblock_t		nextbno;
-	struct xfs_btree_block	*block, *nextblock;
-	int			numrecs;
+	do {
+		nmap = (nexleft > subnex) ? subnex : nexleft;
+		error = xfs_bmapi_read(ip, XFS_BB_TO_FSBT(mp, bmv->bmv_offset),
+				       XFS_BB_TO_FSB(mp, bmv->bmv_length),
+				       map, &nmap, bmapi_flags);
+		if (error)
+			goto out_free_map;
+		ASSERT(nmap <= subnex);
 
-	error = xfs_btree_read_bufl(mp, tp, bno, 0, &bp, XFS_BMAP_BTREE_REF,
-						&xfs_bmbt_buf_ops);
-	if (error)
-		return error;
-	*count += 1;
-	block = XFS_BUF_TO_BLOCK(bp);
+		for (i = 0; i < nmap && nexleft && bmv->bmv_length; i++) {
+			out[cur_ext].bmv_oflags = 0;
+			if (map[i].br_state == XFS_EXT_UNWRITTEN)
+				out[cur_ext].bmv_oflags |= BMV_OF_PREALLOC;
+			else if (map[i].br_startblock == DELAYSTARTBLOCK)
+				out[cur_ext].bmv_oflags |= BMV_OF_DELALLOC;
+			out[cur_ext].bmv_offset =
+				XFS_FSB_TO_BB(mp, map[i].br_startoff);
+			out[cur_ext].bmv_length =
+				XFS_FSB_TO_BB(mp, map[i].br_blockcount);
+			out[cur_ext].bmv_unused1 = 0;
+			out[cur_ext].bmv_unused2 = 0;
 
-	if (--level) {
-		/* Not at node above leaves, count this level of nodes */
-		nextbno = be64_to_cpu(block->bb_u.l.bb_rightsib);
-		while (nextbno != NULLFSBLOCK) {
-			error = xfs_btree_read_bufl(mp, tp, nextbno, 0, &nbp,
-						XFS_BMAP_BTREE_REF,
-						&xfs_bmbt_buf_ops);
-			if (error)
-				return error;
-			*count += 1;
-			nextblock = XFS_BUF_TO_BLOCK(nbp);
-			nextbno = be64_to_cpu(nextblock->bb_u.l.bb_rightsib);
-			xfs_trans_brelse(tp, nbp);
-		}
+			/*
+			 * delayed allocation extents that start beyond EOF can
+			 * occur due to speculative EOF allocation when the
+			 * delalloc extent is larger than the largest freespace
+			 * extent at conversion time. These extents cannot be
+			 * converted by data writeback, so can exist here even
+			 * if we are not supposed to be finding delalloc
+			 * extents.
+			 */
+			if (map[i].br_startblock == DELAYSTARTBLOCK &&
+			    map[i].br_startoff <= XFS_B_TO_FSB(mp, XFS_ISIZE(ip)))
+				ASSERT((iflags & BMV_IF_DELALLOC) != 0);
 
-		/* Dive to the next level */
-		pp = XFS_BMBT_PTR_ADDR(mp, block, 1, mp->m_bmap_dmxr[1]);
-		bno = be64_to_cpu(*pp);
-		if (unlikely((error =
-		     xfs_bmap_count_tree(mp, tp, ifp, bno, level, count)) < 0)) {
-			xfs_trans_brelse(tp, bp);
-			XFS_ERROR_REPORT("xfs_bmap_count_tree(1)",
-					 XFS_ERRLEVEL_LOW, mp);
-			return XFS_ERROR(EFSCORRUPTED);
-		}
-		xfs_trans_brelse(tp, bp);
-	} else {
-		/* count all level 1 nodes and their leaves */
-		for (;;) {
-			nextbno = be64_to_cpu(block->bb_u.l.bb_rightsib);
-			numrecs = be16_to_cpu(block->bb_numrecs);
-			xfs_bmap_disk_count_leaves(mp, block, numrecs, count);
-			xfs_trans_brelse(tp, bp);
-			if (nextbno == NULLFSBLOCK)
-				break;
-			bno = nextbno;
-			error = xfs_btree_read_bufl(mp, tp, bno, 0, &bp,
-						XFS_BMAP_BTREE_REF,
-						&xfs_bmbt_buf_ops);
-			if (error)
-				return error;
-			*count += 1;
-			block = XFS_BUF_TO_BLOCK(bp);
-		}
-	}
-	return 0;
-}
+                        if (map[i].br_startblock == HOLESTARTBLOCK &&
+			    whichfork == XFS_ATTR_FORK) {
+				/* came to the end of attribute fork */
+				out[cur_ext].bmv_oflags |= BMV_OF_LAST;
+				goto out_free_map;
+			}
 
-/*
- * Count leaf blocks given a range of extent records.
- */
-STATIC void
-xfs_bmap_count_leaves(
-	xfs_ifork_t		*ifp,
-	xfs_extnum_t		idx,
-	int			numrecs,
-	int			*count)
-{
-	int		b;
+			if (!xfs_getbmapx_fix_eof_hole(ip, &out[cur_ext],
+					prealloced, bmvend,
+					map[i].br_startblock))
+				goto out_free_map;
 
-	for (b = 0; b < numrecs; b++) {
-		xfs_bmbt_rec_host_t *frp = xfs_iext_get_ext(ifp, idx + b);
-		*count += xfs_bmbt_get_blockcount(frp);
-	}
-}
+			bmv->bmv_offset =
+				out[cur_ext].bmv_offset +
+				out[cur_ext].bmv_length;
+			bmv->bmv_length =
+				max_t(__int64_t, 0, bmvend - bmv->bmv_offset);
 
-/*
- * Count leaf blocks given a range of extent records originally
- * in btree format.
- */
-STATIC void
-xfs_bmap_disk_count_leaves(
-	struct xfs_mount	*mp,
-	struct xfs_btree_block	*block,
-	int			numrecs,
-	int			*count)
-{
-	int		b;
-	xfs_bmbt_rec_t	*frp;
+			/*
+			 * In case we don't want to return the hole,
+			 * don't increase cur_ext so that we can reuse
+			 * it in the next loop.
+			 */
+			if ((iflags & BMV_IF_NO_HOLES) &&
+			    map[i].br_startblock == HOLESTARTBLOCK) {
+				memset(&out[cur_ext], 0, sizeof(out[cur_ext]));
+				continue;
+			}
 
-	for (b = 1; b <= numrecs; b++) {
-		frp = XFS_BMBT_REC_ADDR(mp, block, b);
-		*count += xfs_bmbt_disk_get_blockcount(frp);
+			nexleft--;
+			bmv->bmv_entries++;
+			cur_ext++;
+		}
+	} while (nmap && nexleft && bmv->bmv_length);
+
+ out_free_map:
+	kmem_free(map);
+ out_unlock_ilock:
+	xfs_iunlock_map_shared(ip, lock);
+ out_unlock_iolock:
+	xfs_iunlock(ip, XFS_IOLOCK_SHARED);
+
+	for (i = 0; i < cur_ext; i++) {
+		int full = 0;	/* user array is full */
+
+		/* format results & advance arg */
+		error = formatter(&arg, &out[i], &full);
+		if (error || full)
+			break;
 	}
+
+	if (is_vmalloc_addr(out))
+		kmem_free_large(out);
+	else
+		kmem_free(out);
+	return error;
 }
 
 /*
@@ -6295,16 +6171,3 @@ next_block:
 
 	return error;
 }
-
-/*
- * Convert the given file system block to a disk block.  We have to treat it
- * differently based on whether the file is a real time file or not, because the
- * bmap code does.
- */
-xfs_daddr_t
-xfs_fsb_to_db(struct xfs_inode *ip, xfs_fsblock_t fsb)
-{
-	return (XFS_IS_REALTIME_INODE(ip) ? \
-		 (xfs_daddr_t)XFS_FSB_TO_BB((ip)->i_mount, (fsb)) : \
-		 XFS_FSB_TO_DADDR((ip)->i_mount, (fsb)));
-}
diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c
index 8459b5d..cee0e42 100644
--- a/fs/xfs/xfs_buf.c
+++ b/fs/xfs/xfs_buf.c
@@ -1022,7 +1022,9 @@ xfs_buf_iodone_work(
 	bool			read = !!(bp->b_flags & XBF_READ);
 
 	bp->b_flags &= ~(XBF_READ | XBF_WRITE | XBF_READ_AHEAD);
-	if (read && bp->b_ops)
+
+	/* only validate buffers that were read without errors */
+	if (read && bp->b_ops && !bp->b_error && (bp->b_flags & XBF_DONE))
 		bp->b_ops->verify_read(bp);
 
 	if (bp->b_iodone)
@@ -1222,7 +1224,8 @@ _xfs_buf_ioend(
 STATIC void
 xfs_buf_bio_end_io(
 	struct bio		*bio,
-	int			error)
+	int			error,
+	struct batch_complete *batch)
 {
 	xfs_buf_t		*bp = (xfs_buf_t *)bio->bi_private;
 
diff --git a/fs/xfs/xfs_dinode.h b/fs/xfs/xfs_dinode.h
index 1d9643b..88a3368 100644
--- a/fs/xfs/xfs_dinode.h
+++ b/fs/xfs/xfs_dinode.h
@@ -104,7 +104,7 @@ typedef enum xfs_dinode_fmt {
 /*
  * Inode size for given fs.
  */
-#define XFS_LITINO(mp) \
+#define XFS_LITINO(mp, version) \
 	((int)(((mp)->m_sb.sb_inodesize) - sizeof(struct xfs_dinode)))
 
 #define	XFS_BROOT_SIZE_ADJ	\
@@ -119,10 +119,10 @@ typedef enum xfs_dinode_fmt {
 #define XFS_DFORK_DSIZE(dip,mp) \
 	(XFS_DFORK_Q(dip) ? \
 		XFS_DFORK_BOFF(dip) : \
-		XFS_LITINO(mp))
+		XFS_LITINO(mp, (dip)->di_version))
 #define XFS_DFORK_ASIZE(dip,mp) \
 	(XFS_DFORK_Q(dip) ? \
-		XFS_LITINO(mp) - XFS_DFORK_BOFF(dip) : \
+		XFS_LITINO(mp, (dip)->di_version) - XFS_DFORK_BOFF(dip) : \
 		0)
 #define XFS_DFORK_SIZE(dip,mp,w) \
 	((w) == XFS_DATA_FORK ? \
diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c
index 8025eb2..45bb08f 100644
--- a/fs/xfs/xfs_dquot.c
+++ b/fs/xfs/xfs_dquot.c
@@ -85,17 +85,23 @@ xfs_qm_dqdestroy(
  */
 void
 xfs_qm_adjust_dqlimits(
-	xfs_mount_t		*mp,
-	xfs_disk_dquot_t	*d)
+	struct xfs_mount	*mp,
+	struct xfs_dquot	*dq)
 {
-	xfs_quotainfo_t		*q = mp->m_quotainfo;
+	struct xfs_quotainfo	*q = mp->m_quotainfo;
+	struct xfs_disk_dquot	*d = &dq->q_core;
+	int			prealloc = 0;
 
 	ASSERT(d->d_id);
 
-	if (q->qi_bsoftlimit && !d->d_blk_softlimit)
+	if (q->qi_bsoftlimit && !d->d_blk_softlimit) {
 		d->d_blk_softlimit = cpu_to_be64(q->qi_bsoftlimit);
-	if (q->qi_bhardlimit && !d->d_blk_hardlimit)
+		prealloc = 1;
+	}
+	if (q->qi_bhardlimit && !d->d_blk_hardlimit) {
 		d->d_blk_hardlimit = cpu_to_be64(q->qi_bhardlimit);
+		prealloc = 1;
+	}
 	if (q->qi_isoftlimit && !d->d_ino_softlimit)
 		d->d_ino_softlimit = cpu_to_be64(q->qi_isoftlimit);
 	if (q->qi_ihardlimit && !d->d_ino_hardlimit)
@@ -104,6 +110,9 @@ xfs_qm_adjust_dqlimits(
 		d->d_rtb_softlimit = cpu_to_be64(q->qi_rtbsoftlimit);
 	if (q->qi_rtbhardlimit && !d->d_rtb_hardlimit)
 		d->d_rtb_hardlimit = cpu_to_be64(q->qi_rtbhardlimit);
+
+	if (prealloc)
+		xfs_dquot_set_prealloc_limits(dq);
 }
 
 /*
@@ -248,6 +257,32 @@ xfs_qm_init_dquot_blk(
 	xfs_trans_log_buf(tp, bp, 0, BBTOB(q->qi_dqchunklen) - 1);
 }
 
+/*
+ * Initialize the dynamic speculative preallocation thresholds. The lo/hi
+ * watermarks correspond to the soft and hard limits by default. If a soft limit
+ * is not specified, we use 95% of the hard limit.
+ */
+void
+xfs_dquot_set_prealloc_limits(struct xfs_dquot *dqp)
+{
+	__uint64_t space;
+
+	dqp->q_prealloc_hi_wmark = be64_to_cpu(dqp->q_core.d_blk_hardlimit);
+	dqp->q_prealloc_lo_wmark = be64_to_cpu(dqp->q_core.d_blk_softlimit);
+	if (!dqp->q_prealloc_lo_wmark) {
+		dqp->q_prealloc_lo_wmark = dqp->q_prealloc_hi_wmark;
+		do_div(dqp->q_prealloc_lo_wmark, 100);
+		dqp->q_prealloc_lo_wmark *= 95;
+	}
+
+	space = dqp->q_prealloc_hi_wmark;
+
+	do_div(space, 100);
+	dqp->q_low_space[XFS_QLOWSP_1_PCNT] = space;
+	dqp->q_low_space[XFS_QLOWSP_3_PCNT] = space * 3;
+	dqp->q_low_space[XFS_QLOWSP_5_PCNT] = space * 5;
+}
+
 static void
 xfs_dquot_buf_verify(
 	struct xfs_buf		*bp)
@@ -648,6 +683,9 @@ xfs_qm_dqread(
 	dqp->q_res_icount = be64_to_cpu(ddqp->d_icount);
 	dqp->q_res_rtbcount = be64_to_cpu(ddqp->d_rtbcount);
 
+	/* initialize the dquot speculative prealloc thresholds */
+	xfs_dquot_set_prealloc_limits(dqp);
+
 	/* Mark the buf so that this will stay incore a little longer */
 	xfs_buf_set_ref(bp, XFS_DQUOT_REF);
 
diff --git a/fs/xfs/xfs_dquot.h b/fs/xfs/xfs_dquot.h
index c694a84..4f0ebfc 100644
--- a/fs/xfs/xfs_dquot.h
+++ b/fs/xfs/xfs_dquot.h
@@ -32,6 +32,13 @@
 struct xfs_mount;
 struct xfs_trans;
 
+enum {
+	XFS_QLOWSP_1_PCNT = 0,
+	XFS_QLOWSP_3_PCNT,
+	XFS_QLOWSP_5_PCNT,
+	XFS_QLOWSP_MAX
+};
+
 /*
  * The incore dquot structure
  */
@@ -51,6 +58,9 @@ typedef struct xfs_dquot {
 	xfs_qcnt_t	 q_res_bcount;	/* total regular nblks used+reserved */
 	xfs_qcnt_t	 q_res_icount;	/* total inos allocd+reserved */
 	xfs_qcnt_t	 q_res_rtbcount;/* total realtime blks used+reserved */
+	xfs_qcnt_t	 q_prealloc_lo_wmark;/* prealloc throttle wmark */
+	xfs_qcnt_t	 q_prealloc_hi_wmark;/* prealloc disabled wmark */
+	int64_t		 q_low_space[XFS_QLOWSP_MAX];
 	struct mutex	 q_qlock;	/* quota lock */
 	struct completion q_flush;	/* flush completion queue */
 	atomic_t          q_pincount;	/* dquot pin count */
@@ -145,14 +155,16 @@ extern int		xfs_qm_dqflush(struct xfs_dquot *, struct xfs_buf **);
 extern void		xfs_qm_dqunpin_wait(xfs_dquot_t *);
 extern void		xfs_qm_adjust_dqtimers(xfs_mount_t *,
 					xfs_disk_dquot_t *);
-extern void		xfs_qm_adjust_dqlimits(xfs_mount_t *,
-					xfs_disk_dquot_t *);
+extern void		xfs_qm_adjust_dqlimits(struct xfs_mount *,
+					       struct xfs_dquot *);
 extern int		xfs_qm_dqget(xfs_mount_t *, xfs_inode_t *,
 					xfs_dqid_t, uint, uint, xfs_dquot_t **);
 extern void		xfs_qm_dqput(xfs_dquot_t *);
 
 extern void		xfs_dqlock2(struct xfs_dquot *, struct xfs_dquot *);
 
+extern void		xfs_dquot_set_prealloc_limits(struct xfs_dquot *);
+
 static inline struct xfs_dquot *xfs_qm_dqhold(struct xfs_dquot *dqp)
 {
 	xfs_dqlock(dqp);
diff --git a/fs/xfs/xfs_error.c b/fs/xfs/xfs_error.c
index 6104560..07bf3b9 100644
--- a/fs/xfs/xfs_error.c
+++ b/fs/xfs/xfs_error.c
@@ -66,7 +66,7 @@ xfs_error_test(int error_tag, int *fsidp, char *expression,
 	int i;
 	int64_t fsid;
 
-	if (random32() % randfactor)
+	if (prandom_u32() % randfactor)
 		return 0;
 
 	memcpy(&fsid, fsidp, sizeof(xfs_fsid_t));
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index f03bf1a..baa88dd 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -36,6 +36,7 @@
 #include "xfs_ioctl.h"
 #include "xfs_trace.h"
 
+#include <linux/aio.h>
 #include <linux/dcache.h>
 #include <linux/falloc.h>
 #include <linux/pagevec.h>
@@ -775,8 +776,6 @@ xfs_file_aio_write(
 	if (ocount == 0)
 		return 0;
 
-	sb_start_write(inode->i_sb);
-
 	if (XFS_FORCED_SHUTDOWN(ip->i_mount)) {
 		ret = -EIO;
 		goto out;
@@ -800,7 +799,6 @@ xfs_file_aio_write(
 	}
 
 out:
-	sb_end_write(inode->i_sb);
 	return ret;
 }
 
diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c
index 515bf71..ba62661 100644
--- a/fs/xfs/xfs_ialloc.c
+++ b/fs/xfs/xfs_ialloc.c
@@ -369,7 +369,7 @@ xfs_ialloc_ag_alloc(
 	 * number from being easily guessable.
 	 */
 	error = xfs_ialloc_inode_init(args.mp, tp, agno, args.agbno,
-			args.len, random32());
+			args.len, prandom_u32());
 
 	if (error)
 		return error;
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index 237e7f6..b8520b5 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -180,10 +180,11 @@ typedef struct xfs_icdinode {
 #define XFS_IFORK_DSIZE(ip) \
 	(XFS_IFORK_Q(ip) ? \
 		XFS_IFORK_BOFF(ip) : \
-		XFS_LITINO((ip)->i_mount))
+		XFS_LITINO((ip)->i_mount, (ip)->i_d.di_version))
 #define XFS_IFORK_ASIZE(ip) \
 	(XFS_IFORK_Q(ip) ? \
-		XFS_LITINO((ip)->i_mount) - XFS_IFORK_BOFF(ip) : \
+		XFS_LITINO((ip)->i_mount, (ip)->i_d.di_version) - \
+			XFS_IFORK_BOFF(ip) : \
 		0)
 #define XFS_IFORK_SIZE(ip,w) \
 	((w) == XFS_DATA_FORK ? \
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index 5a30dd8..8f8aaee 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -42,6 +42,8 @@
 #include "xfs_iomap.h"
 #include "xfs_trace.h"
 #include "xfs_icache.h"
+#include "xfs_dquot_item.h"
+#include "xfs_dquot.h"
 
 
 #define XFS_WRITEIO_ALIGN(mp,off)	(((off) >> mp->m_writeio_log) \
@@ -362,10 +364,65 @@ xfs_iomap_eof_prealloc_initial_size(
 	if (imap[0].br_startblock == HOLESTARTBLOCK)
 		return 0;
 	if (imap[0].br_blockcount <= (MAXEXTLEN >> 1))
-		return imap[0].br_blockcount;
+		return imap[0].br_blockcount << 1;
 	return XFS_B_TO_FSB(mp, offset);
 }
 
+STATIC bool
+xfs_quota_need_throttle(
+	struct xfs_inode *ip,
+	int type,
+	xfs_fsblock_t alloc_blocks)
+{
+	struct xfs_dquot *dq = xfs_inode_dquot(ip, type);
+
+	if (!dq || !xfs_this_quota_on(ip->i_mount, type))
+		return false;
+
+	/* no hi watermark, no throttle */
+	if (!dq->q_prealloc_hi_wmark)
+		return false;
+
+	/* under the lo watermark, no throttle */
+	if (dq->q_res_bcount + alloc_blocks < dq->q_prealloc_lo_wmark)
+		return false;
+
+	return true;
+}
+
+STATIC void
+xfs_quota_calc_throttle(
+	struct xfs_inode *ip,
+	int type,
+	xfs_fsblock_t *qblocks,
+	int *qshift)
+{
+	int64_t freesp;
+	int shift = 0;
+	struct xfs_dquot *dq = xfs_inode_dquot(ip, type);
+
+	/* over hi wmark, squash the prealloc completely */
+	if (dq->q_res_bcount >= dq->q_prealloc_hi_wmark) {
+		*qblocks = 0;
+		return;
+	}
+
+	freesp = dq->q_prealloc_hi_wmark - dq->q_res_bcount;
+	if (freesp < dq->q_low_space[XFS_QLOWSP_5_PCNT]) {
+		shift = 2;
+		if (freesp < dq->q_low_space[XFS_QLOWSP_3_PCNT])
+			shift += 2;
+		if (freesp < dq->q_low_space[XFS_QLOWSP_1_PCNT])
+			shift += 2;
+	}
+
+	/* only overwrite the throttle values if we are more aggressive */
+	if ((freesp >> shift) < (*qblocks >> *qshift)) {
+		*qblocks = freesp;
+		*qshift = shift;
+	}
+}
+
 /*
  * If we don't have a user specified preallocation size, dynamically increase
  * the preallocation size as the size of the file grows. Cap the maximum size
@@ -381,45 +438,89 @@ xfs_iomap_prealloc_size(
 	int			nimaps)
 {
 	xfs_fsblock_t		alloc_blocks = 0;
+	int			shift = 0;
+	int64_t			freesp;
+	xfs_fsblock_t		qblocks;
+	int			qshift = 0;
 
 	alloc_blocks = xfs_iomap_eof_prealloc_initial_size(mp, ip, offset,
 							   imap, nimaps);
-	if (alloc_blocks > 0) {
-		int shift = 0;
-		int64_t freesp;
-
-		alloc_blocks = XFS_FILEOFF_MIN(MAXEXTLEN,
-					rounddown_pow_of_two(alloc_blocks));
-
-		xfs_icsb_sync_counters(mp, XFS_ICSB_LAZY_COUNT);
-		freesp = mp->m_sb.sb_fdblocks;
-		if (freesp < mp->m_low_space[XFS_LOWSP_5_PCNT]) {
-			shift = 2;
-			if (freesp < mp->m_low_space[XFS_LOWSP_4_PCNT])
-				shift++;
-			if (freesp < mp->m_low_space[XFS_LOWSP_3_PCNT])
-				shift++;
-			if (freesp < mp->m_low_space[XFS_LOWSP_2_PCNT])
-				shift++;
-			if (freesp < mp->m_low_space[XFS_LOWSP_1_PCNT])
-				shift++;
-		}
-		if (shift)
-			alloc_blocks >>= shift;
+	if (!alloc_blocks)
+		goto check_writeio;
+	qblocks = alloc_blocks;
 
-		/*
-		 * If we are still trying to allocate more space than is
-		 * available, squash the prealloc hard. This can happen if we
-		 * have a large file on a small filesystem and the above
-		 * lowspace thresholds are smaller than MAXEXTLEN.
-		 */
-		while (alloc_blocks && alloc_blocks >= freesp)
-			alloc_blocks >>= 4;
+	/*
+	 * MAXEXTLEN is not a power of two value but we round the prealloc down
+	 * to the nearest power of two value after throttling. To prevent the
+	 * round down from unconditionally reducing the maximum supported prealloc
+	 * size, we round up first, apply appropriate throttling, round down and
+	 * cap the value to MAXEXTLEN.
+	 */
+	alloc_blocks = XFS_FILEOFF_MIN(roundup_pow_of_two(MAXEXTLEN),
+				       alloc_blocks);
+
+	xfs_icsb_sync_counters(mp, XFS_ICSB_LAZY_COUNT);
+	freesp = mp->m_sb.sb_fdblocks;
+	if (freesp < mp->m_low_space[XFS_LOWSP_5_PCNT]) {
+		shift = 2;
+		if (freesp < mp->m_low_space[XFS_LOWSP_4_PCNT])
+			shift++;
+		if (freesp < mp->m_low_space[XFS_LOWSP_3_PCNT])
+			shift++;
+		if (freesp < mp->m_low_space[XFS_LOWSP_2_PCNT])
+			shift++;
+		if (freesp < mp->m_low_space[XFS_LOWSP_1_PCNT])
+			shift++;
 	}
 
+	/*
+	 * Check each quota to cap the prealloc size and provide a shift
+	 * value to throttle with.
+	 */
+	if (xfs_quota_need_throttle(ip, XFS_DQ_USER, alloc_blocks))
+		xfs_quota_calc_throttle(ip, XFS_DQ_USER, &qblocks, &qshift);
+	if (xfs_quota_need_throttle(ip, XFS_DQ_GROUP, alloc_blocks))
+		xfs_quota_calc_throttle(ip, XFS_DQ_GROUP, &qblocks, &qshift);
+	if (xfs_quota_need_throttle(ip, XFS_DQ_PROJ, alloc_blocks))
+		xfs_quota_calc_throttle(ip, XFS_DQ_PROJ, &qblocks, &qshift);
+
+	/*
+	 * The final prealloc size is set to the minimum of free space available
+	 * in each of the quotas and the overall filesystem.
+	 *
+	 * The shift throttle value is set to the maximum value as determined by
+	 * the global low free space values and per-quota low free space values.
+	 */
+	alloc_blocks = MIN(alloc_blocks, qblocks);
+	shift = MAX(shift, qshift);
+
+	if (shift)
+		alloc_blocks >>= shift;
+	/*
+	 * rounddown_pow_of_two() returns an undefined result if we pass in
+	 * alloc_blocks = 0.
+	 */
+	if (alloc_blocks)
+		alloc_blocks = rounddown_pow_of_two(alloc_blocks);
+	if (alloc_blocks > MAXEXTLEN)
+		alloc_blocks = MAXEXTLEN;
+
+	/*
+	 * If we are still trying to allocate more space than is
+	 * available, squash the prealloc hard. This can happen if we
+	 * have a large file on a small filesystem and the above
+	 * lowspace thresholds are smaller than MAXEXTLEN.
+	 */
+	while (alloc_blocks && alloc_blocks >= freesp)
+		alloc_blocks >>= 4;
+
+check_writeio:
 	if (alloc_blocks < mp->m_writeio_blocks)
 		alloc_blocks = mp->m_writeio_blocks;
 
+	trace_xfs_iomap_prealloc_size(ip, alloc_blocks, shift,
+				      mp->m_writeio_blocks);
+
 	return alloc_blocks;
 }
 
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index eec226f..b345a7c 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -3485,7 +3485,7 @@ xlog_ticket_alloc(
 	tic->t_curr_res		= unit_bytes;
 	tic->t_cnt		= cnt;
 	tic->t_ocnt		= cnt;
-	tic->t_tid		= random32();
+	tic->t_tid		= prandom_u32();
 	tic->t_clientid		= client;
 	tic->t_flags		= XLOG_TIC_INITED;
 	tic->t_trans_type	= 0;
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index bc90706..687c171 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -207,7 +207,6 @@ typedef struct xfs_mount {
 						     trimming */
 	__int64_t		m_update_flags;	/* sb flags we need to update
 						   on the next remount,rw */
-	struct shrinker		m_inode_shrink;	/* inode reclaim shrinker */
 	int64_t			m_low_space[XFS_LOWSP_MAX];
 						/* low free space thresholds */
 
diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c
index e5b5cf9..d0acb4e 100644
--- a/fs/xfs/xfs_qm.c
+++ b/fs/xfs/xfs_qm.c
@@ -1057,7 +1057,7 @@ xfs_qm_quotacheck_dqadjust(
 	 * There are no timers for the default values set in the root dquot.
 	 */
 	if (dqp->q_core.d_id) {
-		xfs_qm_adjust_dqlimits(mp, &dqp->q_core);
+		xfs_qm_adjust_dqlimits(mp, dqp);
 		xfs_qm_adjust_dqtimers(mp, &dqp->q_core);
 	}
 
diff --git a/fs/xfs/xfs_qm.h b/fs/xfs/xfs_qm.h
index 44b858b..82c2108 100644
--- a/fs/xfs/xfs_qm.h
+++ b/fs/xfs/xfs_qm.h
@@ -116,7 +116,7 @@ extern void		xfs_qm_dqrele_all_inodes(xfs_mount_t *, uint);
 extern int		xfs_qm_scall_trunc_qfiles(xfs_mount_t *, uint);
 extern int		xfs_qm_scall_getquota(xfs_mount_t *, xfs_dqid_t, uint,
 					fs_disk_quota_t *);
-extern int		xfs_qm_scall_setqlim(xfs_mount_t *, xfs_dqid_t, uint,
+extern int		xfs_qm_scall_setqlim(struct xfs_mount *, xfs_dqid_t, uint,
 					fs_disk_quota_t *);
 extern int		xfs_qm_scall_getqstat(xfs_mount_t *, fs_quota_stat_t *);
 extern int		xfs_qm_scall_quotaon(xfs_mount_t *, uint);
diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c
index cf9a340..c41190c 100644
--- a/fs/xfs/xfs_qm_syscalls.c
+++ b/fs/xfs/xfs_qm_syscalls.c
@@ -472,15 +472,15 @@ xfs_qm_scall_getqstat(
  */
 int
 xfs_qm_scall_setqlim(
-	xfs_mount_t		*mp,
+	struct xfs_mount	*mp,
 	xfs_dqid_t		id,
 	uint			type,
 	fs_disk_quota_t		*newlim)
 {
 	struct xfs_quotainfo	*q = mp->m_quotainfo;
-	xfs_disk_dquot_t	*ddq;
-	xfs_dquot_t		*dqp;
-	xfs_trans_t		*tp;
+	struct xfs_disk_dquot	*ddq;
+	struct xfs_dquot	*dqp;
+	struct xfs_trans	*tp;
 	int			error;
 	xfs_qcnt_t		hard, soft;
 
@@ -529,6 +529,7 @@ xfs_qm_scall_setqlim(
 	if (hard == 0 || hard >= soft) {
 		ddq->d_blk_hardlimit = cpu_to_be64(hard);
 		ddq->d_blk_softlimit = cpu_to_be64(soft);
+		xfs_dquot_set_prealloc_limits(dqp);
 		if (id == 0) {
 			q->qi_bhardlimit = hard;
 			q->qi_bsoftlimit = soft;
diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h
index 16a8129..aa4db33 100644
--- a/fs/xfs/xfs_trace.h
+++ b/fs/xfs/xfs_trace.h
@@ -619,6 +619,30 @@ DECLARE_EVENT_CLASS(xfs_iref_class,
 		  (char *)__entry->caller_ip)
 )
 
+TRACE_EVENT(xfs_iomap_prealloc_size,
+	TP_PROTO(struct xfs_inode *ip, xfs_fsblock_t blocks, int shift,
+		 unsigned int writeio_blocks),
+	TP_ARGS(ip, blocks, shift, writeio_blocks),
+	TP_STRUCT__entry(
+		__field(dev_t, dev)
+		__field(xfs_ino_t, ino)
+		__field(xfs_fsblock_t, blocks)
+		__field(int, shift)
+		__field(unsigned int, writeio_blocks)
+	),
+	TP_fast_assign(
+		__entry->dev = VFS_I(ip)->i_sb->s_dev;
+		__entry->ino = ip->i_ino;
+		__entry->blocks = blocks;
+		__entry->shift = shift;
+		__entry->writeio_blocks = writeio_blocks;
+	),
+	TP_printk("dev %d:%d ino 0x%llx prealloc blocks %llu shift %d "
+		  "m_writeio_blocks %u",
+		  MAJOR(__entry->dev), MINOR(__entry->dev), __entry->ino,
+		  __entry->blocks, __entry->shift, __entry->writeio_blocks)
+)
+
 #define DEFINE_IREF_EVENT(name) \
 DEFINE_EVENT(xfs_iref_class, name, \
 	TP_PROTO(struct xfs_inode *ip, unsigned long caller_ip), \
diff --git a/fs/xfs/xfs_trans_dquot.c b/fs/xfs/xfs_trans_dquot.c
index 642c2d6..fec75d0 100644
--- a/fs/xfs/xfs_trans_dquot.c
+++ b/fs/xfs/xfs_trans_dquot.c
@@ -326,12 +326,12 @@ xfs_trans_dqlockedjoin(
  */
 void
 xfs_trans_apply_dquot_deltas(
-	xfs_trans_t		*tp)
+	struct xfs_trans	*tp)
 {
 	int			i, j;
-	xfs_dquot_t		*dqp;
-	xfs_dqtrx_t		*qtrx, *qa;
-	xfs_disk_dquot_t	*d;
+	struct xfs_dquot	*dqp;
+	struct xfs_dqtrx	*qtrx, *qa;
+	struct xfs_disk_dquot	*d;
 	long			totalbdelta;
 	long			totalrtbdelta;
 
@@ -412,7 +412,7 @@ xfs_trans_apply_dquot_deltas(
 			 * Start/reset the timer(s) if needed.
 			 */
 			if (d->d_id) {
-				xfs_qm_adjust_dqlimits(tp->t_mountp, d);
+				xfs_qm_adjust_dqlimits(tp->t_mountp, dqp);
 				xfs_qm_adjust_dqtimers(tp->t_mountp, d);
 			}
 
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index 77ad748..aa0c066 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -1420,7 +1420,7 @@ xfs_symlink(
 	 * The symlink will fit into the inode data fork?
 	 * There can't be any attributes so we get the whole variable part.
 	 */
-	if (pathlen <= XFS_LITINO(mp))
+	if (pathlen <= XFS_LITINO(mp, dp->i_d.di_version))
 		fs_blocks = 0;
 	else
 		fs_blocks = XFS_B_TO_FSB(mp, pathlen);
diff --git a/include/Kbuild b/include/Kbuild
index 1dfd33e..bab1145 100644
--- a/include/Kbuild
+++ b/include/Kbuild
@@ -1,5 +1,2 @@
 # Top-level Makefile calls into asm-$(ARCH)
 # List only non-arch directories below
-
-header-y += video/
-header-y += scsi/
diff --git a/include/acpi/acexcep.h b/include/acpi/acexcep.h
index 9bf59d0..cf051e0 100644
--- a/include/acpi/acexcep.h
+++ b/include/acpi/acexcep.h
@@ -44,17 +44,50 @@
 #ifndef __ACEXCEP_H__
 #define __ACEXCEP_H__
 
+/* This module contains all possible exception codes for acpi_status */
+
 /*
- * Exceptions returned by external ACPI interfaces
+ * Exception code classes
  */
-#define AE_CODE_ENVIRONMENTAL           0x0000
-#define AE_CODE_PROGRAMMER              0x1000
-#define AE_CODE_ACPI_TABLES             0x2000
-#define AE_CODE_AML                     0x3000
-#define AE_CODE_CONTROL                 0x4000
+#define AE_CODE_ENVIRONMENTAL           0x0000	/* General ACPICA environment */
+#define AE_CODE_PROGRAMMER              0x1000	/* External ACPICA interface caller */
+#define AE_CODE_ACPI_TABLES             0x2000	/* ACPI tables */
+#define AE_CODE_AML                     0x3000	/* From executing AML code */
+#define AE_CODE_CONTROL                 0x4000	/* Internal control codes */
+
 #define AE_CODE_MAX                     0x4000
 #define AE_CODE_MASK                    0xF000
 
+/*
+ * Macros to insert the exception code classes
+ */
+#define EXCEP_ENV(code)                 ((acpi_status) (code | AE_CODE_ENVIRONMENTAL))
+#define EXCEP_PGM(code)                 ((acpi_status) (code | AE_CODE_PROGRAMMER))
+#define EXCEP_TBL(code)                 ((acpi_status) (code | AE_CODE_ACPI_TABLES))
+#define EXCEP_AML(code)                 ((acpi_status) (code | AE_CODE_AML))
+#define EXCEP_CTL(code)                 ((acpi_status) (code | AE_CODE_CONTROL))
+
+/*
+ * Exception info table. The "Description" field is used only by the
+ * ACPICA help application (acpihelp).
+ */
+struct acpi_exception_info {
+	char *name;
+
+#ifdef ACPI_HELP_APP
+	char *description;
+#endif
+};
+
+#ifdef ACPI_HELP_APP
+#define EXCEP_TXT(name,description)     {name, description}
+#else
+#define EXCEP_TXT(name,description)     {name}
+#endif
+
+/*
+ * Success is always zero, failure is non-zero
+ */
 #define ACPI_SUCCESS(a)                 (!(a))
 #define ACPI_FAILURE(a)                 (a)
 
@@ -64,60 +97,60 @@
 /*
  * Environmental exceptions
  */
-#define AE_ERROR                        (acpi_status) (0x0001 | AE_CODE_ENVIRONMENTAL)
-#define AE_NO_ACPI_TABLES               (acpi_status) (0x0002 | AE_CODE_ENVIRONMENTAL)
-#define AE_NO_NAMESPACE                 (acpi_status) (0x0003 | AE_CODE_ENVIRONMENTAL)
-#define AE_NO_MEMORY                    (acpi_status) (0x0004 | AE_CODE_ENVIRONMENTAL)
-#define AE_NOT_FOUND                    (acpi_status) (0x0005 | AE_CODE_ENVIRONMENTAL)
-#define AE_NOT_EXIST                    (acpi_status) (0x0006 | AE_CODE_ENVIRONMENTAL)
-#define AE_ALREADY_EXISTS               (acpi_status) (0x0007 | AE_CODE_ENVIRONMENTAL)
-#define AE_TYPE                         (acpi_status) (0x0008 | AE_CODE_ENVIRONMENTAL)
-#define AE_NULL_OBJECT                  (acpi_status) (0x0009 | AE_CODE_ENVIRONMENTAL)
-#define AE_NULL_ENTRY                   (acpi_status) (0x000A | AE_CODE_ENVIRONMENTAL)
-#define AE_BUFFER_OVERFLOW              (acpi_status) (0x000B | AE_CODE_ENVIRONMENTAL)
-#define AE_STACK_OVERFLOW               (acpi_status) (0x000C | AE_CODE_ENVIRONMENTAL)
-#define AE_STACK_UNDERFLOW              (acpi_status) (0x000D | AE_CODE_ENVIRONMENTAL)
-#define AE_NOT_IMPLEMENTED              (acpi_status) (0x000E | AE_CODE_ENVIRONMENTAL)
-#define AE_SUPPORT                      (acpi_status) (0x000F | AE_CODE_ENVIRONMENTAL)
-#define AE_LIMIT                        (acpi_status) (0x0010 | AE_CODE_ENVIRONMENTAL)
-#define AE_TIME                         (acpi_status) (0x0011 | AE_CODE_ENVIRONMENTAL)
-#define AE_ACQUIRE_DEADLOCK             (acpi_status) (0x0012 | AE_CODE_ENVIRONMENTAL)
-#define AE_RELEASE_DEADLOCK             (acpi_status) (0x0013 | AE_CODE_ENVIRONMENTAL)
-#define AE_NOT_ACQUIRED                 (acpi_status) (0x0014 | AE_CODE_ENVIRONMENTAL)
-#define AE_ALREADY_ACQUIRED             (acpi_status) (0x0015 | AE_CODE_ENVIRONMENTAL)
-#define AE_NO_HARDWARE_RESPONSE         (acpi_status) (0x0016 | AE_CODE_ENVIRONMENTAL)
-#define AE_NO_GLOBAL_LOCK               (acpi_status) (0x0017 | AE_CODE_ENVIRONMENTAL)
-#define AE_ABORT_METHOD                 (acpi_status) (0x0018 | AE_CODE_ENVIRONMENTAL)
-#define AE_SAME_HANDLER                 (acpi_status) (0x0019 | AE_CODE_ENVIRONMENTAL)
-#define AE_NO_HANDLER                   (acpi_status) (0x001A | AE_CODE_ENVIRONMENTAL)
-#define AE_OWNER_ID_LIMIT               (acpi_status) (0x001B | AE_CODE_ENVIRONMENTAL)
-#define AE_NOT_CONFIGURED               (acpi_status) (0x001C | AE_CODE_ENVIRONMENTAL)
+#define AE_ERROR                        EXCEP_ENV (0x0001)
+#define AE_NO_ACPI_TABLES               EXCEP_ENV (0x0002)
+#define AE_NO_NAMESPACE                 EXCEP_ENV (0x0003)
+#define AE_NO_MEMORY                    EXCEP_ENV (0x0004)
+#define AE_NOT_FOUND                    EXCEP_ENV (0x0005)
+#define AE_NOT_EXIST                    EXCEP_ENV (0x0006)
+#define AE_ALREADY_EXISTS               EXCEP_ENV (0x0007)
+#define AE_TYPE                         EXCEP_ENV (0x0008)
+#define AE_NULL_OBJECT                  EXCEP_ENV (0x0009)
+#define AE_NULL_ENTRY                   EXCEP_ENV (0x000A)
+#define AE_BUFFER_OVERFLOW              EXCEP_ENV (0x000B)
+#define AE_STACK_OVERFLOW               EXCEP_ENV (0x000C)
+#define AE_STACK_UNDERFLOW              EXCEP_ENV (0x000D)
+#define AE_NOT_IMPLEMENTED              EXCEP_ENV (0x000E)
+#define AE_SUPPORT                      EXCEP_ENV (0x000F)
+#define AE_LIMIT                        EXCEP_ENV (0x0010)
+#define AE_TIME                         EXCEP_ENV (0x0011)
+#define AE_ACQUIRE_DEADLOCK             EXCEP_ENV (0x0012)
+#define AE_RELEASE_DEADLOCK             EXCEP_ENV (0x0013)
+#define AE_NOT_ACQUIRED                 EXCEP_ENV (0x0014)
+#define AE_ALREADY_ACQUIRED             EXCEP_ENV (0x0015)
+#define AE_NO_HARDWARE_RESPONSE         EXCEP_ENV (0x0016)
+#define AE_NO_GLOBAL_LOCK               EXCEP_ENV (0x0017)
+#define AE_ABORT_METHOD                 EXCEP_ENV (0x0018)
+#define AE_SAME_HANDLER                 EXCEP_ENV (0x0019)
+#define AE_NO_HANDLER                   EXCEP_ENV (0x001A)
+#define AE_OWNER_ID_LIMIT               EXCEP_ENV (0x001B)
+#define AE_NOT_CONFIGURED               EXCEP_ENV (0x001C)
 
 #define AE_CODE_ENV_MAX                 0x001C
 
 /*
  * Programmer exceptions
  */
-#define AE_BAD_PARAMETER                (acpi_status) (0x0001 | AE_CODE_PROGRAMMER)
-#define AE_BAD_CHARACTER                (acpi_status) (0x0002 | AE_CODE_PROGRAMMER)
-#define AE_BAD_PATHNAME                 (acpi_status) (0x0003 | AE_CODE_PROGRAMMER)
-#define AE_BAD_DATA                     (acpi_status) (0x0004 | AE_CODE_PROGRAMMER)
-#define AE_BAD_HEX_CONSTANT             (acpi_status) (0x0005 | AE_CODE_PROGRAMMER)
-#define AE_BAD_OCTAL_CONSTANT           (acpi_status) (0x0006 | AE_CODE_PROGRAMMER)
-#define AE_BAD_DECIMAL_CONSTANT         (acpi_status) (0x0007 | AE_CODE_PROGRAMMER)
-#define AE_MISSING_ARGUMENTS            (acpi_status) (0x0008 | AE_CODE_PROGRAMMER)
-#define AE_BAD_ADDRESS                  (acpi_status) (0x0009 | AE_CODE_PROGRAMMER)
+#define AE_BAD_PARAMETER                EXCEP_PGM (0x0001)
+#define AE_BAD_CHARACTER                EXCEP_PGM (0x0002)
+#define AE_BAD_PATHNAME                 EXCEP_PGM (0x0003)
+#define AE_BAD_DATA                     EXCEP_PGM (0x0004)
+#define AE_BAD_HEX_CONSTANT             EXCEP_PGM (0x0005)
+#define AE_BAD_OCTAL_CONSTANT           EXCEP_PGM (0x0006)
+#define AE_BAD_DECIMAL_CONSTANT         EXCEP_PGM (0x0007)
+#define AE_MISSING_ARGUMENTS            EXCEP_PGM (0x0008)
+#define AE_BAD_ADDRESS                  EXCEP_PGM (0x0009)
 
 #define AE_CODE_PGM_MAX                 0x0009
 
 /*
  * Acpi table exceptions
  */
-#define AE_BAD_SIGNATURE                (acpi_status) (0x0001 | AE_CODE_ACPI_TABLES)
-#define AE_BAD_HEADER                   (acpi_status) (0x0002 | AE_CODE_ACPI_TABLES)
-#define AE_BAD_CHECKSUM                 (acpi_status) (0x0003 | AE_CODE_ACPI_TABLES)
-#define AE_BAD_VALUE                    (acpi_status) (0x0004 | AE_CODE_ACPI_TABLES)
-#define AE_INVALID_TABLE_LENGTH         (acpi_status) (0x0005 | AE_CODE_ACPI_TABLES)
+#define AE_BAD_SIGNATURE                EXCEP_TBL (0x0001)
+#define AE_BAD_HEADER                   EXCEP_TBL (0x0002)
+#define AE_BAD_CHECKSUM                 EXCEP_TBL (0x0003)
+#define AE_BAD_VALUE                    EXCEP_TBL (0x0004)
+#define AE_INVALID_TABLE_LENGTH         EXCEP_TBL (0x0005)
 
 #define AE_CODE_TBL_MAX                 0x0005
 
@@ -125,58 +158,58 @@
  * AML exceptions. These are caused by problems with
  * the actual AML byte stream
  */
-#define AE_AML_BAD_OPCODE               (acpi_status) (0x0001 | AE_CODE_AML)
-#define AE_AML_NO_OPERAND               (acpi_status) (0x0002 | AE_CODE_AML)
-#define AE_AML_OPERAND_TYPE             (acpi_status) (0x0003 | AE_CODE_AML)
-#define AE_AML_OPERAND_VALUE            (acpi_status) (0x0004 | AE_CODE_AML)
-#define AE_AML_UNINITIALIZED_LOCAL      (acpi_status) (0x0005 | AE_CODE_AML)
-#define AE_AML_UNINITIALIZED_ARG        (acpi_status) (0x0006 | AE_CODE_AML)
-#define AE_AML_UNINITIALIZED_ELEMENT    (acpi_status) (0x0007 | AE_CODE_AML)
-#define AE_AML_NUMERIC_OVERFLOW         (acpi_status) (0x0008 | AE_CODE_AML)
-#define AE_AML_REGION_LIMIT             (acpi_status) (0x0009 | AE_CODE_AML)
-#define AE_AML_BUFFER_LIMIT             (acpi_status) (0x000A | AE_CODE_AML)
-#define AE_AML_PACKAGE_LIMIT            (acpi_status) (0x000B | AE_CODE_AML)
-#define AE_AML_DIVIDE_BY_ZERO           (acpi_status) (0x000C | AE_CODE_AML)
-#define AE_AML_BAD_NAME                 (acpi_status) (0x000D | AE_CODE_AML)
-#define AE_AML_NAME_NOT_FOUND           (acpi_status) (0x000E | AE_CODE_AML)
-#define AE_AML_INTERNAL                 (acpi_status) (0x000F | AE_CODE_AML)
-#define AE_AML_INVALID_SPACE_ID         (acpi_status) (0x0010 | AE_CODE_AML)
-#define AE_AML_STRING_LIMIT             (acpi_status) (0x0011 | AE_CODE_AML)
-#define AE_AML_NO_RETURN_VALUE          (acpi_status) (0x0012 | AE_CODE_AML)
-#define AE_AML_METHOD_LIMIT             (acpi_status) (0x0013 | AE_CODE_AML)
-#define AE_AML_NOT_OWNER                (acpi_status) (0x0014 | AE_CODE_AML)
-#define AE_AML_MUTEX_ORDER              (acpi_status) (0x0015 | AE_CODE_AML)
-#define AE_AML_MUTEX_NOT_ACQUIRED       (acpi_status) (0x0016 | AE_CODE_AML)
-#define AE_AML_INVALID_RESOURCE_TYPE    (acpi_status) (0x0017 | AE_CODE_AML)
-#define AE_AML_INVALID_INDEX            (acpi_status) (0x0018 | AE_CODE_AML)
-#define AE_AML_REGISTER_LIMIT           (acpi_status) (0x0019 | AE_CODE_AML)
-#define AE_AML_NO_WHILE                 (acpi_status) (0x001A | AE_CODE_AML)
-#define AE_AML_ALIGNMENT                (acpi_status) (0x001B | AE_CODE_AML)
-#define AE_AML_NO_RESOURCE_END_TAG      (acpi_status) (0x001C | AE_CODE_AML)
-#define AE_AML_BAD_RESOURCE_VALUE       (acpi_status) (0x001D | AE_CODE_AML)
-#define AE_AML_CIRCULAR_REFERENCE       (acpi_status) (0x001E | AE_CODE_AML)
-#define AE_AML_BAD_RESOURCE_LENGTH      (acpi_status) (0x001F | AE_CODE_AML)
-#define AE_AML_ILLEGAL_ADDRESS          (acpi_status) (0x0020 | AE_CODE_AML)
-#define AE_AML_INFINITE_LOOP            (acpi_status) (0x0021 | AE_CODE_AML)
+#define AE_AML_BAD_OPCODE               EXCEP_AML (0x0001)
+#define AE_AML_NO_OPERAND               EXCEP_AML (0x0002)
+#define AE_AML_OPERAND_TYPE             EXCEP_AML (0x0003)
+#define AE_AML_OPERAND_VALUE            EXCEP_AML (0x0004)
+#define AE_AML_UNINITIALIZED_LOCAL      EXCEP_AML (0x0005)
+#define AE_AML_UNINITIALIZED_ARG        EXCEP_AML (0x0006)
+#define AE_AML_UNINITIALIZED_ELEMENT    EXCEP_AML (0x0007)
+#define AE_AML_NUMERIC_OVERFLOW         EXCEP_AML (0x0008)
+#define AE_AML_REGION_LIMIT             EXCEP_AML (0x0009)
+#define AE_AML_BUFFER_LIMIT             EXCEP_AML (0x000A)
+#define AE_AML_PACKAGE_LIMIT            EXCEP_AML (0x000B)
+#define AE_AML_DIVIDE_BY_ZERO           EXCEP_AML (0x000C)
+#define AE_AML_BAD_NAME                 EXCEP_AML (0x000D)
+#define AE_AML_NAME_NOT_FOUND           EXCEP_AML (0x000E)
+#define AE_AML_INTERNAL                 EXCEP_AML (0x000F)
+#define AE_AML_INVALID_SPACE_ID         EXCEP_AML (0x0010)
+#define AE_AML_STRING_LIMIT             EXCEP_AML (0x0011)
+#define AE_AML_NO_RETURN_VALUE          EXCEP_AML (0x0012)
+#define AE_AML_METHOD_LIMIT             EXCEP_AML (0x0013)
+#define AE_AML_NOT_OWNER                EXCEP_AML (0x0014)
+#define AE_AML_MUTEX_ORDER              EXCEP_AML (0x0015)
+#define AE_AML_MUTEX_NOT_ACQUIRED       EXCEP_AML (0x0016)
+#define AE_AML_INVALID_RESOURCE_TYPE    EXCEP_AML (0x0017)
+#define AE_AML_INVALID_INDEX            EXCEP_AML (0x0018)
+#define AE_AML_REGISTER_LIMIT           EXCEP_AML (0x0019)
+#define AE_AML_NO_WHILE                 EXCEP_AML (0x001A)
+#define AE_AML_ALIGNMENT                EXCEP_AML (0x001B)
+#define AE_AML_NO_RESOURCE_END_TAG      EXCEP_AML (0x001C)
+#define AE_AML_BAD_RESOURCE_VALUE       EXCEP_AML (0x001D)
+#define AE_AML_CIRCULAR_REFERENCE       EXCEP_AML (0x001E)
+#define AE_AML_BAD_RESOURCE_LENGTH      EXCEP_AML (0x001F)
+#define AE_AML_ILLEGAL_ADDRESS          EXCEP_AML (0x0020)
+#define AE_AML_INFINITE_LOOP            EXCEP_AML (0x0021)
 
 #define AE_CODE_AML_MAX                 0x0021
 
 /*
  * Internal exceptions used for control
  */
-#define AE_CTRL_RETURN_VALUE            (acpi_status) (0x0001 | AE_CODE_CONTROL)
-#define AE_CTRL_PENDING                 (acpi_status) (0x0002 | AE_CODE_CONTROL)
-#define AE_CTRL_TERMINATE               (acpi_status) (0x0003 | AE_CODE_CONTROL)
-#define AE_CTRL_TRUE                    (acpi_status) (0x0004 | AE_CODE_CONTROL)
-#define AE_CTRL_FALSE                   (acpi_status) (0x0005 | AE_CODE_CONTROL)
-#define AE_CTRL_DEPTH                   (acpi_status) (0x0006 | AE_CODE_CONTROL)
-#define AE_CTRL_END                     (acpi_status) (0x0007 | AE_CODE_CONTROL)
-#define AE_CTRL_TRANSFER                (acpi_status) (0x0008 | AE_CODE_CONTROL)
-#define AE_CTRL_BREAK                   (acpi_status) (0x0009 | AE_CODE_CONTROL)
-#define AE_CTRL_CONTINUE                (acpi_status) (0x000A | AE_CODE_CONTROL)
-#define AE_CTRL_SKIP                    (acpi_status) (0x000B | AE_CODE_CONTROL)
-#define AE_CTRL_PARSE_CONTINUE          (acpi_status) (0x000C | AE_CODE_CONTROL)
-#define AE_CTRL_PARSE_PENDING           (acpi_status) (0x000D | AE_CODE_CONTROL)
+#define AE_CTRL_RETURN_VALUE            EXCEP_CTL (0x0001)
+#define AE_CTRL_PENDING                 EXCEP_CTL (0x0002)
+#define AE_CTRL_TERMINATE               EXCEP_CTL (0x0003)
+#define AE_CTRL_TRUE                    EXCEP_CTL (0x0004)
+#define AE_CTRL_FALSE                   EXCEP_CTL (0x0005)
+#define AE_CTRL_DEPTH                   EXCEP_CTL (0x0006)
+#define AE_CTRL_END                     EXCEP_CTL (0x0007)
+#define AE_CTRL_TRANSFER                EXCEP_CTL (0x0008)
+#define AE_CTRL_BREAK                   EXCEP_CTL (0x0009)
+#define AE_CTRL_CONTINUE                EXCEP_CTL (0x000A)
+#define AE_CTRL_SKIP                    EXCEP_CTL (0x000B)
+#define AE_CTRL_PARSE_CONTINUE          EXCEP_CTL (0x000C)
+#define AE_CTRL_PARSE_PENDING           EXCEP_CTL (0x000D)
 
 #define AE_CODE_CTRL_MAX                0x000D
 
@@ -188,112 +221,156 @@
  * String versions of the exception codes above
  * These strings must match the corresponding defines exactly
  */
-char const *acpi_gbl_exception_names_env[] = {
-	"AE_OK",
-	"AE_ERROR",
-	"AE_NO_ACPI_TABLES",
-	"AE_NO_NAMESPACE",
-	"AE_NO_MEMORY",
-	"AE_NOT_FOUND",
-	"AE_NOT_EXIST",
-	"AE_ALREADY_EXISTS",
-	"AE_TYPE",
-	"AE_NULL_OBJECT",
-	"AE_NULL_ENTRY",
-	"AE_BUFFER_OVERFLOW",
-	"AE_STACK_OVERFLOW",
-	"AE_STACK_UNDERFLOW",
-	"AE_NOT_IMPLEMENTED",
-	"AE_SUPPORT",
-	"AE_LIMIT",
-	"AE_TIME",
-	"AE_ACQUIRE_DEADLOCK",
-	"AE_RELEASE_DEADLOCK",
-	"AE_NOT_ACQUIRED",
-	"AE_ALREADY_ACQUIRED",
-	"AE_NO_HARDWARE_RESPONSE",
-	"AE_NO_GLOBAL_LOCK",
-	"AE_ABORT_METHOD",
-	"AE_SAME_HANDLER",
-	"AE_NO_HANDLER",
-	"AE_OWNER_ID_LIMIT",
-	"AE_NOT_CONFIGURED"
+static const struct acpi_exception_info acpi_gbl_exception_names_env[] = {
+	EXCEP_TXT("AE_OK", "No error"),
+	EXCEP_TXT("AE_ERROR", "Unspecified error"),
+	EXCEP_TXT("AE_NO_ACPI_TABLES", "ACPI tables could not be found"),
+	EXCEP_TXT("AE_NO_NAMESPACE", "A namespace has not been loaded"),
+	EXCEP_TXT("AE_NO_MEMORY", "Insufficient dynamic memory"),
+	EXCEP_TXT("AE_NOT_FOUND", "The name was not found in the namespace"),
+	EXCEP_TXT("AE_NOT_EXIST", "A required entity does not exist"),
+	EXCEP_TXT("AE_ALREADY_EXISTS", "An entity already exists"),
+	EXCEP_TXT("AE_TYPE", "The object type is incorrect"),
+	EXCEP_TXT("AE_NULL_OBJECT", "A required object was missing"),
+	EXCEP_TXT("AE_NULL_ENTRY", "The requested object does not exist"),
+	EXCEP_TXT("AE_BUFFER_OVERFLOW", "The buffer provided is too small"),
+	EXCEP_TXT("AE_STACK_OVERFLOW", "An internal stack overflowed"),
+	EXCEP_TXT("AE_STACK_UNDERFLOW", "An internal stack underflowed"),
+	EXCEP_TXT("AE_NOT_IMPLEMENTED", "The feature is not implemented"),
+	EXCEP_TXT("AE_SUPPORT", "The feature is not supported"),
+	EXCEP_TXT("AE_LIMIT", "A predefined limit was exceeded"),
+	EXCEP_TXT("AE_TIME", "A time limit or timeout expired"),
+	EXCEP_TXT("AE_ACQUIRE_DEADLOCK",
+		  "Internal error, attempt was made to acquire a mutex in improper order"),
+	EXCEP_TXT("AE_RELEASE_DEADLOCK",
+		  "Internal error, attempt was made to release a mutex in improper order"),
+	EXCEP_TXT("AE_NOT_ACQUIRED",
+		  "An attempt to release a mutex or Global Lock without a previous acquire"),
+	EXCEP_TXT("AE_ALREADY_ACQUIRED",
+		  "Internal error, attempt was made to acquire a mutex twice"),
+	EXCEP_TXT("AE_NO_HARDWARE_RESPONSE",
+		  "Hardware did not respond after an I/O operation"),
+	EXCEP_TXT("AE_NO_GLOBAL_LOCK", "There is no FACS Global Lock"),
+	EXCEP_TXT("AE_ABORT_METHOD", "A control method was aborted"),
+	EXCEP_TXT("AE_SAME_HANDLER",
+		  "Attempt was made to install the same handler that is already installed"),
+	EXCEP_TXT("AE_NO_HANDLER",
+		  "A handler for the operation is not installed"),
+	EXCEP_TXT("AE_OWNER_ID_LIMIT",
+		  "There are no more Owner IDs available for ACPI tables or control methods"),
+	EXCEP_TXT("AE_NOT_CONFIGURED",
+		  "The interface is not part of the current subsystem configuration")
 };
 
-char const *acpi_gbl_exception_names_pgm[] = {
-	NULL,
-	"AE_BAD_PARAMETER",
-	"AE_BAD_CHARACTER",
-	"AE_BAD_PATHNAME",
-	"AE_BAD_DATA",
-	"AE_BAD_HEX_CONSTANT",
-	"AE_BAD_OCTAL_CONSTANT",
-	"AE_BAD_DECIMAL_CONSTANT",
-	"AE_MISSING_ARGUMENTS",
-	"AE_BAD_ADDRESS"
+static const struct acpi_exception_info acpi_gbl_exception_names_pgm[] = {
+	EXCEP_TXT(NULL, NULL),
+	EXCEP_TXT("AE_BAD_PARAMETER", "A parameter is out of range or invalid"),
+	EXCEP_TXT("AE_BAD_CHARACTER",
+		  "An invalid character was found in a name"),
+	EXCEP_TXT("AE_BAD_PATHNAME",
+		  "An invalid character was found in a pathname"),
+	EXCEP_TXT("AE_BAD_DATA",
+		  "A package or buffer contained incorrect data"),
+	EXCEP_TXT("AE_BAD_HEX_CONSTANT", "Invalid character in a Hex constant"),
+	EXCEP_TXT("AE_BAD_OCTAL_CONSTANT",
+		  "Invalid character in an Octal constant"),
+	EXCEP_TXT("AE_BAD_DECIMAL_CONSTANT",
+		  "Invalid character in a Decimal constant"),
+	EXCEP_TXT("AE_MISSING_ARGUMENTS",
+		  "Too few arguments were passed to a control method"),
+	EXCEP_TXT("AE_BAD_ADDRESS", "An illegal null I/O address")
 };
 
-char const *acpi_gbl_exception_names_tbl[] = {
-	NULL,
-	"AE_BAD_SIGNATURE",
-	"AE_BAD_HEADER",
-	"AE_BAD_CHECKSUM",
-	"AE_BAD_VALUE",
-	"AE_INVALID_TABLE_LENGTH"
+static const struct acpi_exception_info acpi_gbl_exception_names_tbl[] = {
+	EXCEP_TXT(NULL, NULL),
+	EXCEP_TXT("AE_BAD_SIGNATURE", "An ACPI table has an invalid signature"),
+	EXCEP_TXT("AE_BAD_HEADER", "Invalid field in an ACPI table header"),
+	EXCEP_TXT("AE_BAD_CHECKSUM", "An ACPI table checksum is not correct"),
+	EXCEP_TXT("AE_BAD_VALUE", "An invalid value was found in a table"),
+	EXCEP_TXT("AE_INVALID_TABLE_LENGTH",
+		  "The FADT or FACS has improper length")
 };
 
-char const *acpi_gbl_exception_names_aml[] = {
-	NULL,
-	"AE_AML_BAD_OPCODE",
-	"AE_AML_NO_OPERAND",
-	"AE_AML_OPERAND_TYPE",
-	"AE_AML_OPERAND_VALUE",
-	"AE_AML_UNINITIALIZED_LOCAL",
-	"AE_AML_UNINITIALIZED_ARG",
-	"AE_AML_UNINITIALIZED_ELEMENT",
-	"AE_AML_NUMERIC_OVERFLOW",
-	"AE_AML_REGION_LIMIT",
-	"AE_AML_BUFFER_LIMIT",
-	"AE_AML_PACKAGE_LIMIT",
-	"AE_AML_DIVIDE_BY_ZERO",
-	"AE_AML_BAD_NAME",
-	"AE_AML_NAME_NOT_FOUND",
-	"AE_AML_INTERNAL",
-	"AE_AML_INVALID_SPACE_ID",
-	"AE_AML_STRING_LIMIT",
-	"AE_AML_NO_RETURN_VALUE",
-	"AE_AML_METHOD_LIMIT",
-	"AE_AML_NOT_OWNER",
-	"AE_AML_MUTEX_ORDER",
-	"AE_AML_MUTEX_NOT_ACQUIRED",
-	"AE_AML_INVALID_RESOURCE_TYPE",
-	"AE_AML_INVALID_INDEX",
-	"AE_AML_REGISTER_LIMIT",
-	"AE_AML_NO_WHILE",
-	"AE_AML_ALIGNMENT",
-	"AE_AML_NO_RESOURCE_END_TAG",
-	"AE_AML_BAD_RESOURCE_VALUE",
-	"AE_AML_CIRCULAR_REFERENCE",
-	"AE_AML_BAD_RESOURCE_LENGTH",
-	"AE_AML_ILLEGAL_ADDRESS",
-	"AE_AML_INFINITE_LOOP"
+static const struct acpi_exception_info acpi_gbl_exception_names_aml[] = {
+	EXCEP_TXT(NULL, NULL),
+	EXCEP_TXT("AE_AML_BAD_OPCODE", "Invalid AML opcode encountered"),
+	EXCEP_TXT("AE_AML_NO_OPERAND", "A required operand is missing"),
+	EXCEP_TXT("AE_AML_OPERAND_TYPE",
+		  "An operand of an incorrect type was encountered"),
+	EXCEP_TXT("AE_AML_OPERAND_VALUE",
+		  "The operand had an inappropriate or invalid value"),
+	EXCEP_TXT("AE_AML_UNINITIALIZED_LOCAL",
+		  "Method tried to use an uninitialized local variable"),
+	EXCEP_TXT("AE_AML_UNINITIALIZED_ARG",
+		  "Method tried to use an uninitialized argument"),
+	EXCEP_TXT("AE_AML_UNINITIALIZED_ELEMENT",
+		  "Method tried to use an empty package element"),
+	EXCEP_TXT("AE_AML_NUMERIC_OVERFLOW",
+		  "Overflow during BCD conversion or other"),
+	EXCEP_TXT("AE_AML_REGION_LIMIT",
+		  "Tried to access beyond the end of an Operation Region"),
+	EXCEP_TXT("AE_AML_BUFFER_LIMIT",
+		  "Tried to access beyond the end of a buffer"),
+	EXCEP_TXT("AE_AML_PACKAGE_LIMIT",
+		  "Tried to access beyond the end of a package"),
+	EXCEP_TXT("AE_AML_DIVIDE_BY_ZERO",
+		  "During execution of AML Divide operator"),
+	EXCEP_TXT("AE_AML_BAD_NAME",
+		  "An ACPI name contains invalid character(s)"),
+	EXCEP_TXT("AE_AML_NAME_NOT_FOUND",
+		  "Could not resolve a named reference"),
+	EXCEP_TXT("AE_AML_INTERNAL", "An internal error within the interprete"),
+	EXCEP_TXT("AE_AML_INVALID_SPACE_ID",
+		  "An Operation Region SpaceID is invalid"),
+	EXCEP_TXT("AE_AML_STRING_LIMIT",
+		  "String is longer than 200 characters"),
+	EXCEP_TXT("AE_AML_NO_RETURN_VALUE",
+		  "A method did not return a required value"),
+	EXCEP_TXT("AE_AML_METHOD_LIMIT",
+		  "A control method reached the maximum reentrancy limit of 255"),
+	EXCEP_TXT("AE_AML_NOT_OWNER",
+		  "A thread tried to release a mutex that it does not own"),
+	EXCEP_TXT("AE_AML_MUTEX_ORDER", "Mutex SyncLevel release mismatch"),
+	EXCEP_TXT("AE_AML_MUTEX_NOT_ACQUIRED",
+		  "Attempt to release a mutex that was not previously acquired"),
+	EXCEP_TXT("AE_AML_INVALID_RESOURCE_TYPE",
+		  "Invalid resource type in resource list"),
+	EXCEP_TXT("AE_AML_INVALID_INDEX",
+		  "Invalid Argx or Localx (x too large)"),
+	EXCEP_TXT("AE_AML_REGISTER_LIMIT",
+		  "Bank value or Index value beyond range of register"),
+	EXCEP_TXT("AE_AML_NO_WHILE", "Break or Continue without a While"),
+	EXCEP_TXT("AE_AML_ALIGNMENT",
+		  "Non-aligned memory transfer on platform that does not support this"),
+	EXCEP_TXT("AE_AML_NO_RESOURCE_END_TAG",
+		  "No End Tag in a resource list"),
+	EXCEP_TXT("AE_AML_BAD_RESOURCE_VALUE",
+		  "Invalid value of a resource element"),
+	EXCEP_TXT("AE_AML_CIRCULAR_REFERENCE",
+		  "Two references refer to each other"),
+	EXCEP_TXT("AE_AML_BAD_RESOURCE_LENGTH",
+		  "The length of a Resource Descriptor in the AML is incorrect"),
+	EXCEP_TXT("AE_AML_ILLEGAL_ADDRESS",
+		  "A memory, I/O, or PCI configuration address is invalid"),
+	EXCEP_TXT("AE_AML_INFINITE_LOOP",
+		  "An apparent infinite AML While loop, method was aborted")
 };
 
-char const *acpi_gbl_exception_names_ctrl[] = {
-	NULL,
-	"AE_CTRL_RETURN_VALUE",
-	"AE_CTRL_PENDING",
-	"AE_CTRL_TERMINATE",
-	"AE_CTRL_TRUE",
-	"AE_CTRL_FALSE",
-	"AE_CTRL_DEPTH",
-	"AE_CTRL_END",
-	"AE_CTRL_TRANSFER",
-	"AE_CTRL_BREAK",
-	"AE_CTRL_CONTINUE",
-	"AE_CTRL_SKIP",
-	"AE_CTRL_PARSE_CONTINUE",
-	"AE_CTRL_PARSE_PENDING"
+static const struct acpi_exception_info acpi_gbl_exception_names_ctrl[] = {
+	EXCEP_TXT(NULL, NULL),
+	EXCEP_TXT("AE_CTRL_RETURN_VALUE", "A Method returned a value"),
+	EXCEP_TXT("AE_CTRL_PENDING", "Method is calling another method"),
+	EXCEP_TXT("AE_CTRL_TERMINATE", "Terminate the executing method"),
+	EXCEP_TXT("AE_CTRL_TRUE", "An If or While predicate result"),
+	EXCEP_TXT("AE_CTRL_FALSE", "An If or While predicate result"),
+	EXCEP_TXT("AE_CTRL_DEPTH", "Maximum search depth has been reached"),
+	EXCEP_TXT("AE_CTRL_END", "An If or While predicate is false"),
+	EXCEP_TXT("AE_CTRL_TRANSFER", "Transfer control to called method"),
+	EXCEP_TXT("AE_CTRL_BREAK", "A Break has been executed"),
+	EXCEP_TXT("AE_CTRL_CONTINUE", "A Continue has been executed"),
+	EXCEP_TXT("AE_CTRL_SKIP", "Not currently used"),
+	EXCEP_TXT("AE_CTRL_PARSE_CONTINUE", "Used to skip over bad opcodes"),
+	EXCEP_TXT("AE_CTRL_PARSE_PENDING", "Used to implement AML While loops")
 };
 
 #endif				/* EXCEPTION_TABLE */
diff --git a/include/acpi/acoutput.h b/include/acpi/acoutput.h
index 9885276..4f52ea7 100644
--- a/include/acpi/acoutput.h
+++ b/include/acpi/acoutput.h
@@ -324,9 +324,9 @@
 
 /* Helper macro */
 
-#define ACPI_TRACE_ENTRY(name, function, cast, param) \
+#define ACPI_TRACE_ENTRY(name, function, type, param) \
 	ACPI_FUNCTION_NAME (name) \
-	function (ACPI_DEBUG_PARAMETERS, cast (param))
+	function (ACPI_DEBUG_PARAMETERS, (type) (param))
 
 /* The actual entry trace macros */
 
@@ -335,13 +335,13 @@
 	acpi_ut_trace (ACPI_DEBUG_PARAMETERS)
 
 #define ACPI_FUNCTION_TRACE_PTR(name, pointer) \
-	ACPI_TRACE_ENTRY (name, acpi_ut_trace_ptr, (void *), pointer)
+	ACPI_TRACE_ENTRY (name, acpi_ut_trace_ptr, void *, pointer)
 
 #define ACPI_FUNCTION_TRACE_U32(name, value) \
-	ACPI_TRACE_ENTRY (name, acpi_ut_trace_u32, (u32), value)
+	ACPI_TRACE_ENTRY (name, acpi_ut_trace_u32, u32, value)
 
 #define ACPI_FUNCTION_TRACE_STR(name, string) \
-	ACPI_TRACE_ENTRY (name, acpi_ut_trace_str, (char *), string)
+	ACPI_TRACE_ENTRY (name, acpi_ut_trace_str, char *, string)
 
 #define ACPI_FUNCTION_ENTRY() \
 	acpi_ut_track_stack_ptr()
@@ -355,16 +355,37 @@
  *
  * One of the FUNCTION_TRACE macros above must be used in conjunction
  * with these macros so that "_AcpiFunctionName" is defined.
+ *
+ * There are two versions of most of the return macros. The default version is
+ * safer, since it avoids side-effects by guaranteeing that the argument will
+ * not be evaluated twice.
+ *
+ * A less-safe version of the macros is provided for optional use if the
+ * compiler uses excessive CPU stack (for example, this may happen in the
+ * debug case if code optimzation is disabled.)
  */
 
 /* Exit trace helper macro */
 
-#define ACPI_TRACE_EXIT(function, cast, param) \
+#ifndef ACPI_SIMPLE_RETURN_MACROS
+
+#define ACPI_TRACE_EXIT(function, type, param) \
+	ACPI_DO_WHILE0 ({ \
+		register type _param = (type) (param); \
+		function (ACPI_DEBUG_PARAMETERS, _param); \
+		return (_param); \
+	})
+
+#else				/* Use original less-safe macros */
+
+#define ACPI_TRACE_EXIT(function, type, param) \
 	ACPI_DO_WHILE0 ({ \
-		function (ACPI_DEBUG_PARAMETERS, cast (param)); \
-		return ((param)); \
+		function (ACPI_DEBUG_PARAMETERS, (type) (param)); \
+		return (param); \
 	})
 
+#endif				/* ACPI_SIMPLE_RETURN_MACROS */
+
 /* The actual exit macros */
 
 #define return_VOID \
@@ -374,13 +395,19 @@
 	})
 
 #define return_ACPI_STATUS(status) \
-	ACPI_TRACE_EXIT (acpi_ut_status_exit, (acpi_status), status)
+	ACPI_TRACE_EXIT (acpi_ut_status_exit, acpi_status, status)
 
 #define return_PTR(pointer) \
-	ACPI_TRACE_EXIT (acpi_ut_ptr_exit, (u8 *), pointer)
+	ACPI_TRACE_EXIT (acpi_ut_ptr_exit, void *, pointer)
 
 #define return_VALUE(value) \
-	ACPI_TRACE_EXIT (acpi_ut_value_exit, (u64), value)
+	ACPI_TRACE_EXIT (acpi_ut_value_exit, u64, value)
+
+#define return_UINT32(value) \
+	ACPI_TRACE_EXIT (acpi_ut_value_exit, u32, value)
+
+#define return_UINT8(value) \
+	ACPI_TRACE_EXIT (acpi_ut_value_exit, u8, value)
 
 /* Conditional execution */
 
@@ -428,8 +455,10 @@
 
 #define return_VOID                     return
 #define return_ACPI_STATUS(s)           return(s)
-#define return_VALUE(s)                 return(s)
 #define return_PTR(s)                   return(s)
+#define return_VALUE(s)                 return(s)
+#define return_UINT8(s)                 return(s)
+#define return_UINT32(s)                return(s)
 
 #endif				/* ACPI_DEBUG_OUTPUT */
 
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index 22ba56e..98db31d 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -88,11 +88,30 @@ struct acpi_device;
  * -----------------
  */
 
+enum acpi_hotplug_mode {
+	AHM_GENERIC = 0,
+	AHM_CONTAINER,
+	AHM_COUNT
+};
+
+struct acpi_hotplug_profile {
+	struct kobject kobj;
+	bool enabled:1;
+	enum acpi_hotplug_mode mode;
+};
+
+static inline struct acpi_hotplug_profile *to_acpi_hotplug_profile(
+						struct kobject *kobj)
+{
+	return container_of(kobj, struct acpi_hotplug_profile, kobj);
+}
+
 struct acpi_scan_handler {
 	const struct acpi_device_id *ids;
 	struct list_head list_node;
 	int (*attach)(struct acpi_device *dev, const struct acpi_device_id *id);
 	void (*detach)(struct acpi_device *dev);
+	struct acpi_hotplug_profile hotplug;
 };
 
 /*
@@ -142,7 +161,6 @@ struct acpi_device_status {
 
 struct acpi_device_flags {
 	u32 dynamic_status:1;
-	u32 bus_address:1;
 	u32 removable:1;
 	u32 ejectable:1;
 	u32 suprise_removal_ok:1;
@@ -150,7 +168,7 @@ struct acpi_device_flags {
 	u32 performance_manageable:1;
 	u32 eject_pending:1;
 	u32 match_driver:1;
-	u32 reserved:23;
+	u32 reserved:24;
 };
 
 /* File System */
@@ -173,10 +191,17 @@ struct acpi_hardware_id {
 	char *id;
 };
 
+struct acpi_pnp_type {
+	u32 hardware_id:1;
+	u32 bus_address:1;
+	u32 reserved:30;
+};
+
 struct acpi_device_pnp {
-	acpi_bus_id bus_id;	/* Object name */
+	acpi_bus_id bus_id;		/* Object name */
+	struct acpi_pnp_type type;	/* ID type */
 	acpi_bus_address bus_address;	/* _ADR */
-	char *unique_id;	/* _UID */
+	char *unique_id;		/* _UID */
 	struct list_head ids;		/* _HID and _CIDs */
 	acpi_device_name device_name;	/* Driver-determined */
 	acpi_device_class device_class;	/*        "          */
diff --git a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h
index 627749a..e6168a2 100644
--- a/include/acpi/acpi_drivers.h
+++ b/include/acpi/acpi_drivers.h
@@ -95,7 +95,6 @@ int acpi_pci_link_free_irq(acpi_handle handle);
 struct pci_bus;
 
 struct pci_dev *acpi_get_pci_dev(acpi_handle);
-int acpi_pci_bind_root(struct acpi_device *device);
 
 /* Arch-defined function to add a bus to the system */
 
diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h
index 03322dd..7aa231b 100644
--- a/include/acpi/acpixf.h
+++ b/include/acpi/acpixf.h
@@ -46,7 +46,7 @@
 
 /* Current ACPICA subsystem version in YYYYMMDD format */
 
-#define ACPI_CA_VERSION                 0x20130117
+#define ACPI_CA_VERSION                 0x20130214
 
 #include <acpi/acconfig.h>
 #include <acpi/actypes.h>
diff --git a/include/acpi/actbl2.h b/include/acpi/actbl2.h
index 77dc7a4..ffaac0e 100644
--- a/include/acpi/actbl2.h
+++ b/include/acpi/actbl2.h
@@ -72,11 +72,13 @@
 #define ACPI_SIG_IVRS           "IVRS"	/* I/O Virtualization Reporting Structure */
 #define ACPI_SIG_MCFG           "MCFG"	/* PCI Memory Mapped Configuration table */
 #define ACPI_SIG_MCHI           "MCHI"	/* Management Controller Host Interface table */
+#define ACPI_SIG_MTMR           "MTMR"	/* MID Timer table */
 #define ACPI_SIG_SLIC           "SLIC"	/* Software Licensing Description Table */
 #define ACPI_SIG_SPCR           "SPCR"	/* Serial Port Console Redirection table */
 #define ACPI_SIG_SPMI           "SPMI"	/* Server Platform Management Interface table */
 #define ACPI_SIG_TCPA           "TCPA"	/* Trusted Computing Platform Alliance table */
 #define ACPI_SIG_UEFI           "UEFI"	/* Uefi Boot Optimization Table */
+#define ACPI_SIG_VRTC           "VRTC"	/* Virtual Real Time Clock Table */
 #define ACPI_SIG_WAET           "WAET"	/* Windows ACPI Emulated devices Table */
 #define ACPI_SIG_WDAT           "WDAT"	/* Watchdog Action Table */
 #define ACPI_SIG_WDDT           "WDDT"	/* Watchdog Timer Description Table */
@@ -852,6 +854,29 @@ struct acpi_table_mchi {
 
 /*******************************************************************************
  *
+ * MTMR - MID Timer Table
+ *        Version 1
+ *
+ * Conforms to "Simple Firmware Interface Specification",
+ * Draft 0.8.2, Oct 19, 2010
+ * NOTE: The ACPI MTMR is equivalent to the SFI MTMR table.
+ *
+ ******************************************************************************/
+
+struct acpi_table_mtmr {
+	struct acpi_table_header header;	/* Common ACPI table header */
+};
+
+/* MTMR entry */
+
+struct acpi_mtmr_entry {
+	struct acpi_generic_address physical_address;
+	u32 frequency;
+	u32 irq;
+};
+
+/*******************************************************************************
+ *
  * SLIC - Software Licensing Description Table
  *        Version 1
  *
@@ -1025,6 +1050,28 @@ struct acpi_table_uefi {
 
 /*******************************************************************************
  *
+ * VRTC - Virtual Real Time Clock Table
+ *        Version 1
+ *
+ * Conforms to "Simple Firmware Interface Specification",
+ * Draft 0.8.2, Oct 19, 2010
+ * NOTE: The ACPI VRTC is equivalent to The SFI MRTC table.
+ *
+ ******************************************************************************/
+
+struct acpi_table_vrtc {
+	struct acpi_table_header header;	/* Common ACPI table header */
+};
+
+/* VRTC entry */
+
+struct acpi_vrtc_entry {
+	struct acpi_generic_address physical_address;
+	u32 irq;
+};
+
+/*******************************************************************************
+ *
  * WAET - Windows ACPI Emulated devices Table
  *        Version 1
  *
diff --git a/include/acpi/actbl3.h b/include/acpi/actbl3.h
index 332b17e..e2c0931 100644
--- a/include/acpi/actbl3.h
+++ b/include/acpi/actbl3.h
@@ -174,7 +174,7 @@ struct acpi_fpdt_header {
 
 enum acpi_fpdt_type {
 	ACPI_FPDT_TYPE_BOOT = 0,
-	ACPI_FPDT_TYPE_S3PERF = 1,
+	ACPI_FPDT_TYPE_S3PERF = 1
 };
 
 /*
@@ -223,7 +223,7 @@ struct acpi_s3pt_header {
 
 enum acpi_s3pt_type {
 	ACPI_S3PT_TYPE_RESUME = 0,
-	ACPI_S3PT_TYPE_SUSPEND = 1,
+	ACPI_S3PT_TYPE_SUSPEND = 1
 };
 
 struct acpi_s3pt_resume {
@@ -505,26 +505,59 @@ struct acpi_rasf_shared_memory {
 	u32 signature;
 	u16 command;
 	u16 status;
-	u64 requested_address;
-	u64 requested_length;
-	u64 actual_address;
-	u64 actual_length;
+	u16 version;
+	u8 capabilities[16];
+	u8 set_capabilities[16];
+	u16 num_parameter_blocks;
+	u32 set_capabilities_status;
+};
+
+/* RASF Parameter Block Structure Header */
+
+struct acpi_rasf_parameter_block {
+	u16 type;
+	u16 version;
+	u16 length;
+};
+
+/* RASF Parameter Block Structure for PATROL_SCRUB */
+
+struct acpi_rasf_patrol_scrub_parameter {
+	struct acpi_rasf_parameter_block header;
+	u16 patrol_scrub_command;
+	u64 requested_address_range[2];
+	u64 actual_address_range[2];
 	u16 flags;
-	u8 speed;
+	u8 requested_speed;
 };
 
 /* Masks for Flags and Speed fields above */
 
 #define ACPI_RASF_SCRUBBER_RUNNING      1
 #define ACPI_RASF_SPEED                 (7<<1)
+#define ACPI_RASF_SPEED_SLOW            (0<<1)
+#define ACPI_RASF_SPEED_MEDIUM          (4<<1)
+#define ACPI_RASF_SPEED_FAST            (7<<1)
 
 /* Channel Commands */
 
 enum acpi_rasf_commands {
-	ACPI_RASF_GET_RAS_CAPABILITIES = 1,
-	ACPI_RASF_GET_PATROL_PARAMETERS = 2,
-	ACPI_RASF_START_PATROL_SCRUBBER = 3,
-	ACPI_RASF_STOP_PATROL_SCRUBBER = 4
+	ACPI_RASF_EXECUTE_RASF_COMMAND = 1
+};
+
+/* Platform RAS Capabilities */
+
+enum acpi_rasf_capabiliities {
+	ACPI_HW_PATROL_SCRUB_SUPPORTED = 0,
+	ACPI_SW_PATROL_SCRUB_EXPOSED = 1
+};
+
+/* Patrol Scrub Commands */
+
+enum acpi_rasf_patrol_scrub_commands {
+	ACPI_RASF_GET_PATROL_PARAMETERS = 1,
+	ACPI_RASF_START_PATROL_SCRUBBER = 2,
+	ACPI_RASF_STOP_PATROL_SCRUBBER = 3
 };
 
 /* Channel Command flags */
diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h
index 845e75f..3fac1be 100644
--- a/include/acpi/actypes.h
+++ b/include/acpi/actypes.h
@@ -1128,7 +1128,6 @@ struct acpi_memory_list {
 	u16 object_size;
 	u16 max_depth;
 	u16 current_depth;
-	u16 link_offset;
 
 #ifdef ACPI_DBG_TRACK_ALLOCATIONS
 
diff --git a/include/asm-generic/hugetlb.h b/include/asm-generic/hugetlb.h
new file mode 100644
index 0000000..d06079c
--- /dev/null
+++ b/include/asm-generic/hugetlb.h
@@ -0,0 +1,40 @@
+#ifndef _ASM_GENERIC_HUGETLB_H
+#define _ASM_GENERIC_HUGETLB_H
+
+static inline pte_t mk_huge_pte(struct page *page, pgprot_t pgprot)
+{
+	return mk_pte(page, pgprot);
+}
+
+static inline int huge_pte_write(pte_t pte)
+{
+	return pte_write(pte);
+}
+
+static inline int huge_pte_dirty(pte_t pte)
+{
+	return pte_dirty(pte);
+}
+
+static inline pte_t huge_pte_mkwrite(pte_t pte)
+{
+	return pte_mkwrite(pte);
+}
+
+static inline pte_t huge_pte_mkdirty(pte_t pte)
+{
+	return pte_mkdirty(pte);
+}
+
+static inline pte_t huge_pte_modify(pte_t pte, pgprot_t newprot)
+{
+	return pte_modify(pte, newprot);
+}
+
+static inline void huge_pte_clear(struct mm_struct *mm, unsigned long addr,
+				  pte_t *ptep)
+{
+	pte_clear(mm, addr, ptep);
+}
+
+#endif /* _ASM_GENERIC_HUGETLB_H */
diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h
index bfd8768..a59ff51 100644
--- a/include/asm-generic/pgtable.h
+++ b/include/asm-generic/pgtable.h
@@ -7,6 +7,16 @@
 #include <linux/mm_types.h>
 #include <linux/bug.h>
 
+/*
+ * On almost all architectures and configurations, 0 can be used as the
+ * upper ceiling to free_pgtables(): on many architectures it has the same
+ * effect as using TASK_SIZE.  However, there is one configuration which
+ * must impose a more careful limit, to avoid freeing kernel pgtables.
+ */
+#ifndef USER_PGTABLES_CEILING
+#define USER_PGTABLES_CEILING	0UL
+#endif
+
 #ifndef __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
 extern int ptep_set_access_flags(struct vm_area_struct *vma,
 				 unsigned long address, pte_t *ptep,
diff --git a/include/asm-generic/unistd.h b/include/asm-generic/unistd.h
index 4077b5d..cccc86e 100644
--- a/include/asm-generic/unistd.h
+++ b/include/asm-generic/unistd.h
@@ -1,4 +1,5 @@
 #include <uapi/asm-generic/unistd.h>
+#include <linux/export.h>
 
 /*
  * These are required system calls, we should
@@ -9,20 +10,3 @@
 #define __ARCH_WANT_STAT64
 #define __ARCH_WANT_SYS_LLSEEK
 #endif
-
-/*
- * "Conditional" syscalls
- *
- * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
- * but it doesn't work on all toolchains, so we just do it by hand
- */
-#ifndef cond_syscall
-#ifdef CONFIG_SYMBOL_PREFIX
-#define __SYMBOL_PREFIX CONFIG_SYMBOL_PREFIX
-#else
-#define __SYMBOL_PREFIX
-#endif
-#define cond_syscall(x) asm(".weak\t" __SYMBOL_PREFIX #x "\n\t" \
-			    ".set\t" __SYMBOL_PREFIX #x "," \
-			    __SYMBOL_PREFIX "sys_ni_syscall")
-#endif
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index afa12c7..eb58d2d 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -52,13 +52,7 @@
 #define LOAD_OFFSET 0
 #endif
 
-#ifndef SYMBOL_PREFIX
-#define VMLINUX_SYMBOL(sym) sym
-#else
-#define PASTE2(x,y) x##y
-#define PASTE(x,y) PASTE2(x,y)
-#define VMLINUX_SYMBOL(sym) PASTE(SYMBOL_PREFIX, sym)
-#endif
+#include <linux/export.h>
 
 /* Align . to a 8 byte boundary equals to maximum function alignment. */
 #define ALIGN_FUNCTION()  . = ALIGN(8)
diff --git a/include/crypto/sha.h b/include/crypto/sha.h
index c6c9c1f..190f8a0 100644
--- a/include/crypto/sha.h
+++ b/include/crypto/sha.h
@@ -87,4 +87,9 @@ struct shash_desc;
 extern int crypto_sha1_update(struct shash_desc *desc, const u8 *data,
 			      unsigned int len);
 
+extern int crypto_sha256_update(struct shash_desc *desc, const u8 *data,
+			      unsigned int len);
+
+extern int crypto_sha512_update(struct shash_desc *desc, const u8 *data,
+			      unsigned int len);
 #endif
diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h
index c095116..f97a8ef 100644
--- a/include/drm/drm_fb_helper.h
+++ b/include/drm/drm_fb_helper.h
@@ -68,6 +68,10 @@ struct drm_fb_helper_funcs {
 
 	int (*fb_probe)(struct drm_fb_helper *helper,
 			struct drm_fb_helper_surface_size *sizes);
+	bool (*initial_config)(struct drm_fb_helper *fb_helper,
+			       struct drm_fb_helper_crtc **crtcs,
+			       struct drm_display_mode **modes,
+			       bool *enabled, int width, int height);
 };
 
 struct drm_fb_helper_connector {
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index bcbdd74..edaf311 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -204,7 +204,7 @@ extern bool wmi_has_guid(const char *guid);
 #if defined(CONFIG_ACPI_VIDEO) || defined(CONFIG_ACPI_VIDEO_MODULE)
 
 extern long acpi_video_get_capabilities(acpi_handle graphics_dev_handle);
-extern long acpi_is_video_device(struct acpi_device *device);
+extern long acpi_is_video_device(acpi_handle handle);
 extern void acpi_video_dmi_promote_vendor(void);
 extern void acpi_video_dmi_demote_vendor(void);
 extern int acpi_video_backlight_support(void);
@@ -217,7 +217,7 @@ static inline long acpi_video_get_capabilities(acpi_handle graphics_dev_handle)
 	return 0;
 }
 
-static inline long acpi_is_video_device(struct acpi_device *device)
+static inline long acpi_is_video_device(acpi_handle handle)
 {
 	return 0;
 }
diff --git a/include/linux/aio.h b/include/linux/aio.h
index 31ff6db..a7e4c59 100644
--- a/include/linux/aio.h
+++ b/include/linux/aio.h
@@ -6,94 +6,38 @@
 #include <linux/aio_abi.h>
 #include <linux/uio.h>
 #include <linux/rcupdate.h>
-
 #include <linux/atomic.h>
-
-#define AIO_MAXSEGS		4
-#define AIO_KIOGRP_NR_ATOMIC	8
+#include <linux/batch_complete.h>
 
 struct kioctx;
+struct kiocb;
+struct batch_complete;
 
-/* Notes on cancelling a kiocb:
- *	If a kiocb is cancelled, aio_complete may return 0 to indicate 
- *	that cancel has not yet disposed of the kiocb.  All cancel 
- *	operations *must* call aio_put_req to dispose of the kiocb 
- *	to guard against races with the completion code.
- */
-#define KIOCB_C_CANCELLED	0x01
-#define KIOCB_C_COMPLETE	0x02
-
-#define KIOCB_SYNC_KEY		(~0U)
+#define KIOCB_KEY		0
 
-/* ki_flags bits */
 /*
- * This may be used for cancel/retry serialization in the future, but
- * for now it's unused and we probably don't want modules to even
- * think they can use it.
+ * We use ki_cancel == KIOCB_CANCELLED to indicate that a kiocb has been either
+ * cancelled or completed (this makes a certain amount of sense because
+ * successful cancellation - io_cancel() - does deliver the completion to
+ * userspace).
+ *
+ * And since most things don't implement kiocb cancellation and we'd really like
+ * kiocb completion to be lockless when possible, we use ki_cancel to
+ * synchronize cancellation and completion - we only set it to KIOCB_CANCELLED
+ * with xchg() or cmpxchg(), see batch_complete_aio() and kiocb_cancel().
  */
-/* #define KIF_LOCKED		0 */
-#define KIF_KICKED		1
-#define KIF_CANCELLED		2
-
-#define kiocbTryLock(iocb)	test_and_set_bit(KIF_LOCKED, &(iocb)->ki_flags)
-#define kiocbTryKick(iocb)	test_and_set_bit(KIF_KICKED, &(iocb)->ki_flags)
+#define KIOCB_CANCELLED		((void *) (~0ULL))
 
-#define kiocbSetLocked(iocb)	set_bit(KIF_LOCKED, &(iocb)->ki_flags)
-#define kiocbSetKicked(iocb)	set_bit(KIF_KICKED, &(iocb)->ki_flags)
-#define kiocbSetCancelled(iocb)	set_bit(KIF_CANCELLED, &(iocb)->ki_flags)
+typedef int (kiocb_cancel_fn)(struct kiocb *, struct io_event *);
 
-#define kiocbClearLocked(iocb)	clear_bit(KIF_LOCKED, &(iocb)->ki_flags)
-#define kiocbClearKicked(iocb)	clear_bit(KIF_KICKED, &(iocb)->ki_flags)
-#define kiocbClearCancelled(iocb)	clear_bit(KIF_CANCELLED, &(iocb)->ki_flags)
-
-#define kiocbIsLocked(iocb)	test_bit(KIF_LOCKED, &(iocb)->ki_flags)
-#define kiocbIsKicked(iocb)	test_bit(KIF_KICKED, &(iocb)->ki_flags)
-#define kiocbIsCancelled(iocb)	test_bit(KIF_CANCELLED, &(iocb)->ki_flags)
-
-/* is there a better place to document function pointer methods? */
-/**
- * ki_retry	-	iocb forward progress callback
- * @kiocb:	The kiocb struct to advance by performing an operation.
- *
- * This callback is called when the AIO core wants a given AIO operation
- * to make forward progress.  The kiocb argument describes the operation
- * that is to be performed.  As the operation proceeds, perhaps partially,
- * ki_retry is expected to update the kiocb with progress made.  Typically
- * ki_retry is set in the AIO core and it itself calls file_operations
- * helpers.
- *
- * ki_retry's return value determines when the AIO operation is completed
- * and an event is generated in the AIO event ring.  Except the special
- * return values described below, the value that is returned from ki_retry
- * is transferred directly into the completion ring as the operation's
- * resulting status.  Once this has happened ki_retry *MUST NOT* reference
- * the kiocb pointer again.
- *
- * If ki_retry returns -EIOCBQUEUED it has made a promise that aio_complete()
- * will be called on the kiocb pointer in the future.  The AIO core will
- * not ask the method again -- ki_retry must ensure forward progress.
- * aio_complete() must be called once and only once in the future, multiple
- * calls may result in undefined behaviour.
- *
- * If ki_retry returns -EIOCBRETRY it has made a promise that kick_iocb()
- * will be called on the kiocb pointer in the future.  This may happen
- * through generic helpers that associate kiocb->ki_wait with a wait
- * queue head that ki_retry uses via current->io_wait.  It can also happen
- * with custom tracking and manual calls to kick_iocb(), though that is
- * discouraged.  In either case, kick_iocb() must be called once and only
- * once.  ki_retry must ensure forward progress, the AIO core will wait
- * indefinitely for kick_iocb() to be called.
- */
 struct kiocb {
-	struct list_head	ki_run_list;
-	unsigned long		ki_flags;
-	int			ki_users;
-	unsigned		ki_key;		/* id of this request */
+	struct rb_node		ki_node;
+
+	atomic_t		ki_users;
 
 	struct file		*ki_filp;
-	struct kioctx		*ki_ctx;	/* may be NULL for sync ops */
-	int			(*ki_cancel)(struct kiocb *, struct io_event *);
-	ssize_t			(*ki_retry)(struct kiocb *);
+	struct kioctx		*ki_ctx;	/* NULL for sync ops */
+	kiocb_cancel_fn		*ki_cancel;
 	void			(*ki_dtor)(struct kiocb *);
 
 	union {
@@ -102,6 +46,9 @@ struct kiocb {
 	} ki_obj;
 
 	__u64			ki_user_data;	/* user's data for completion */
+	long			ki_res;
+	long			ki_res2;
+
 	loff_t			ki_pos;
 
 	void			*private;
@@ -117,7 +64,6 @@ struct kiocb {
 
 	struct list_head	ki_list;	/* the aio core uses this
 						 * for cancellation */
-	struct list_head	ki_batch;	/* batch allocation */
 
 	/*
 	 * If the aio_resfd field of the userspace iocb is not zero,
@@ -128,108 +74,55 @@ struct kiocb {
 
 static inline bool is_sync_kiocb(struct kiocb *kiocb)
 {
-	return kiocb->ki_key == KIOCB_SYNC_KEY;
+	return kiocb->ki_ctx == NULL;
 }
 
 static inline void init_sync_kiocb(struct kiocb *kiocb, struct file *filp)
 {
 	*kiocb = (struct kiocb) {
-			.ki_users = 1,
-			.ki_key = KIOCB_SYNC_KEY,
+			.ki_users = ATOMIC_INIT(1),
+			.ki_ctx = NULL,
 			.ki_filp = filp,
 			.ki_obj.tsk = current,
 		};
 }
 
-#define AIO_RING_MAGIC			0xa10a10a1
-#define AIO_RING_COMPAT_FEATURES	1
-#define AIO_RING_INCOMPAT_FEATURES	0
-struct aio_ring {
-	unsigned	id;	/* kernel internal index number */
-	unsigned	nr;	/* number of io_events */
-	unsigned	head;
-	unsigned	tail;
-
-	unsigned	magic;
-	unsigned	compat_features;
-	unsigned	incompat_features;
-	unsigned	header_length;	/* size of aio_ring */
-
-
-	struct io_event		io_events[0];
-}; /* 128 bytes + ring size */
-
-#define AIO_RING_PAGES	8
-struct aio_ring_info {
-	unsigned long		mmap_base;
-	unsigned long		mmap_size;
-
-	struct page		**ring_pages;
-	spinlock_t		ring_lock;
-	long			nr_pages;
-
-	unsigned		nr, tail;
-
-	struct page		*internal_pages[AIO_RING_PAGES];
-};
-
-static inline unsigned aio_ring_avail(struct aio_ring_info *info,
-					struct aio_ring *ring)
-{
-	return (ring->head + info->nr - 1 - ring->tail) % info->nr;
-}
-
-struct kioctx {
-	atomic_t		users;
-	int			dead;
-	struct mm_struct	*mm;
-
-	/* This needs improving */
-	unsigned long		user_id;
-	struct hlist_node	list;
-
-	wait_queue_head_t	wait;
-
-	spinlock_t		ctx_lock;
-
-	int			reqs_active;
-	struct list_head	active_reqs;	/* used for cancellation */
-	struct list_head	run_list;	/* used for kicked reqs */
-
-	/* sys_io_setup currently limits this to an unsigned int */
-	unsigned		max_reqs;
-
-	struct aio_ring_info	ring_info;
-
-	struct delayed_work	wq;
-
-	struct rcu_head		rcu_head;
-};
-
 /* prototypes */
-extern unsigned aio_max_size;
-
 #ifdef CONFIG_AIO
 extern ssize_t wait_on_sync_kiocb(struct kiocb *iocb);
-extern int aio_put_req(struct kiocb *iocb);
-extern void kick_iocb(struct kiocb *iocb);
-extern int aio_complete(struct kiocb *iocb, long res, long res2);
+extern void aio_put_req(struct kiocb *iocb);
+extern void batch_complete_aio(struct batch_complete *batch);
+extern void aio_complete_batch(struct kiocb *iocb, long res, long res2,
+			       struct batch_complete *batch);
 struct mm_struct;
 extern void exit_aio(struct mm_struct *mm);
 extern long do_io_submit(aio_context_t ctx_id, long nr,
 			 struct iocb __user *__user *iocbpp, bool compat);
+void kiocb_set_cancel_fn(struct kiocb *req, kiocb_cancel_fn *cancel);
 #else
 static inline ssize_t wait_on_sync_kiocb(struct kiocb *iocb) { return 0; }
-static inline int aio_put_req(struct kiocb *iocb) { return 0; }
-static inline void kick_iocb(struct kiocb *iocb) { }
-static inline int aio_complete(struct kiocb *iocb, long res, long res2) { return 0; }
+static inline void aio_put_req(struct kiocb *iocb) { }
+
+static inline void batch_complete_aio(struct batch_complete *batch) { }
+static inline void aio_complete_batch(struct kiocb *iocb, long res, long res2,
+				      struct batch_complete *batch)
+{
+	return;
+}
 struct mm_struct;
 static inline void exit_aio(struct mm_struct *mm) { }
 static inline long do_io_submit(aio_context_t ctx_id, long nr,
 				struct iocb __user * __user *iocbpp,
 				bool compat) { return 0; }
+static inline void kiocb_set_cancel_fn(struct kiocb *req,
+				       kiocb_cancel_fn *cancel) { }
 #endif /* CONFIG_AIO */
 
+static inline void aio_complete(struct kiocb *iocb, long res, long res2)
+{
+	aio_complete_batch(iocb, res, res2, NULL);
+}
+
 static inline struct kiocb *list_kiocb(struct list_head *h)
 {
 	return list_entry(h, struct kiocb, ki_list);
diff --git a/include/linux/amba/serial.h b/include/linux/amba/serial.h
index f612c78..62d9303 100644
--- a/include/linux/amba/serial.h
+++ b/include/linux/amba/serial.h
@@ -203,6 +203,9 @@ struct amba_pl011_data {
 	bool (*dma_filter)(struct dma_chan *chan, void *filter_param);
 	void *dma_rx_param;
 	void *dma_tx_param;
+	bool dma_rx_poll_enable;
+	unsigned int dma_rx_poll_rate;
+	unsigned int dma_rx_poll_timeout;
         void (*init) (void);
 	void (*exit) (void);
 };
diff --git a/include/linux/async.h b/include/linux/async.h
index a2e3f18..6b0226b 100644
--- a/include/linux/async.h
+++ b/include/linux/async.h
@@ -16,9 +16,8 @@
 #include <linux/list.h>
 
 typedef u64 async_cookie_t;
-typedef void (async_func_ptr) (void *data, async_cookie_t cookie);
+typedef void (*async_func_t) (void *data, async_cookie_t cookie);
 struct async_domain {
-	struct list_head node;
 	struct list_head pending;
 	unsigned registered:1;
 };
@@ -27,8 +26,7 @@ struct async_domain {
  * domain participates in global async_synchronize_full
  */
 #define ASYNC_DOMAIN(_name) \
-	struct async_domain _name = { .node = LIST_HEAD_INIT(_name.node), \
-				      .pending = LIST_HEAD_INIT(_name.pending), \
+	struct async_domain _name = { .pending = LIST_HEAD_INIT(_name.pending),	\
 				      .registered = 1 }
 
 /*
@@ -36,12 +34,11 @@ struct async_domain {
  * complete, this domain does not participate in async_synchronize_full
  */
 #define ASYNC_DOMAIN_EXCLUSIVE(_name) \
-	struct async_domain _name = { .node = LIST_HEAD_INIT(_name.node), \
-				      .pending = LIST_HEAD_INIT(_name.pending), \
+	struct async_domain _name = { .pending = LIST_HEAD_INIT(_name.pending), \
 				      .registered = 0 }
 
-extern async_cookie_t async_schedule(async_func_ptr *ptr, void *data);
-extern async_cookie_t async_schedule_domain(async_func_ptr *ptr, void *data,
+extern async_cookie_t async_schedule(async_func_t func, void *data);
+extern async_cookie_t async_schedule_domain(async_func_t func, void *data,
 					    struct async_domain *domain);
 void async_unregister_domain(struct async_domain *domain);
 extern void async_synchronize_full(void);
diff --git a/include/linux/ata.h b/include/linux/ata.h
index 8f7a3d6..ee0bd95 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -954,7 +954,7 @@ static inline int atapi_cdb_len(const u16 *dev_id)
 	}
 }
 
-static inline bool atapi_command_packet_set(const u16 *dev_id)
+static inline int atapi_command_packet_set(const u16 *dev_id)
 {
 	return (dev_id[ATA_ID_CONFIG] >> 8) & 0x1f;
 }
diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h
index 3504599..c388155 100644
--- a/include/linux/backing-dev.h
+++ b/include/linux/backing-dev.h
@@ -18,6 +18,7 @@
 #include <linux/writeback.h>
 #include <linux/atomic.h>
 #include <linux/sysctl.h>
+#include <linux/workqueue.h>
 
 struct page;
 struct device;
@@ -27,7 +28,6 @@ struct dentry;
  * Bits in backing_dev_info.state
  */
 enum bdi_state {
-	BDI_pending,		/* On its way to being activated */
 	BDI_wb_alloc,		/* Default embedded wb allocated */
 	BDI_async_congested,	/* The async (write) queue is getting full */
 	BDI_sync_congested,	/* The sync queue is getting full */
@@ -53,10 +53,8 @@ struct bdi_writeback {
 	unsigned int nr;
 
 	unsigned long last_old_flush;	/* last old data flush */
-	unsigned long last_active;	/* last time bdi thread was active */
 
-	struct task_struct *task;	/* writeback thread */
-	struct timer_list wakeup_timer; /* used for delayed bdi thread wakeup */
+	struct delayed_work dwork;	/* work item used for 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 */
@@ -123,14 +121,15 @@ int bdi_setup_and_register(struct backing_dev_info *, char *, unsigned int);
 void bdi_start_writeback(struct backing_dev_info *bdi, long nr_pages,
 			enum wb_reason reason);
 void bdi_start_background_writeback(struct backing_dev_info *bdi);
-int bdi_writeback_thread(void *data);
+void bdi_writeback_workfn(struct work_struct *work);
 int bdi_has_dirty_io(struct backing_dev_info *bdi);
 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;
-extern struct list_head bdi_pending_list;
+
+extern struct workqueue_struct *bdi_wq;
 
 static inline int wb_has_dirty_io(struct bdi_writeback *wb)
 {
@@ -336,11 +335,6 @@ static inline bool bdi_cap_swap_backed(struct backing_dev_info *bdi)
 	return bdi->capabilities & BDI_CAP_SWAP_BACKED;
 }
 
-static inline bool bdi_cap_flush_forker(struct backing_dev_info *bdi)
-{
-	return bdi == &default_backing_dev_info;
-}
-
 static inline bool mapping_cap_writeback_dirty(struct address_space *mapping)
 {
 	return bdi_cap_writeback_dirty(mapping->backing_dev_info);
diff --git a/include/linux/balloon_compaction.h b/include/linux/balloon_compaction.h
index f7f1d71..6fd5cc8 100644
--- a/include/linux/balloon_compaction.h
+++ b/include/linux/balloon_compaction.h
@@ -213,8 +213,15 @@ static inline bool balloon_compaction_check(void)
 	return true;
 }
 
+static inline void balloon_event_count(enum vm_event_item item)
+{
+	count_vm_event(item);
+}
 #else /* !CONFIG_BALLOON_COMPACTION */
 
+/* A macro, to avoid generating references to the undefined COMPACTBALLOON* */
+#define balloon_event_count(item) do { } while (0)
+
 static inline void *balloon_mapping_alloc(void *balloon_device,
 				const struct address_space_operations *a_ops)
 {
diff --git a/include/linux/batch_complete.h b/include/linux/batch_complete.h
new file mode 100644
index 0000000..8167a9d
--- /dev/null
+++ b/include/linux/batch_complete.h
@@ -0,0 +1,23 @@
+#ifndef _LINUX_BATCH_COMPLETE_H
+#define _LINUX_BATCH_COMPLETE_H
+
+#include <linux/rbtree.h>
+
+/*
+ * Common stuff to the aio and block code for batch completion. Everything
+ * important is elsewhere:
+ */
+
+struct bio;
+
+struct bio_list {
+	struct bio *head;
+	struct bio *tail;
+};
+
+struct batch_complete {
+	struct bio_list		bio;
+	struct rb_root		kiocb;
+};
+
+#endif
diff --git a/include/linux/bcma/bcma.h b/include/linux/bcma/bcma.h
index e0ce311..0ab6712 100644
--- a/include/linux/bcma/bcma.h
+++ b/include/linux/bcma/bcma.h
@@ -173,6 +173,60 @@ struct bcma_host_ops {
 #define BCMA_CHIP_ID_BCM53572	53572
 #define  BCMA_PKG_ID_BCM47188	9
 
+/* Board types (on PCI usually equals to the subsystem dev id) */
+/* BCM4313 */
+#define BCMA_BOARD_TYPE_BCM94313BU	0X050F
+#define BCMA_BOARD_TYPE_BCM94313HM	0X0510
+#define BCMA_BOARD_TYPE_BCM94313EPA	0X0511
+#define BCMA_BOARD_TYPE_BCM94313HMG	0X051C
+/* BCM4716 */
+#define BCMA_BOARD_TYPE_BCM94716NR2	0X04CD
+/* BCM43224 */
+#define BCMA_BOARD_TYPE_BCM943224X21	0X056E
+#define BCMA_BOARD_TYPE_BCM943224X21_FCC	0X00D1
+#define BCMA_BOARD_TYPE_BCM943224X21B	0X00E9
+#define BCMA_BOARD_TYPE_BCM943224M93	0X008B
+#define BCMA_BOARD_TYPE_BCM943224M93A	0X0090
+#define BCMA_BOARD_TYPE_BCM943224X16	0X0093
+#define BCMA_BOARD_TYPE_BCM94322X9	0X008D
+#define BCMA_BOARD_TYPE_BCM94322M35E	0X008E
+/* BCM43228 */
+#define BCMA_BOARD_TYPE_BCM943228BU8	0X0540
+#define BCMA_BOARD_TYPE_BCM943228BU9	0X0541
+#define BCMA_BOARD_TYPE_BCM943228BU	0X0542
+#define BCMA_BOARD_TYPE_BCM943227HM4L	0X0543
+#define BCMA_BOARD_TYPE_BCM943227HMB	0X0544
+#define BCMA_BOARD_TYPE_BCM943228HM4L	0X0545
+#define BCMA_BOARD_TYPE_BCM943228SD	0X0573
+/* BCM4331 */
+#define BCMA_BOARD_TYPE_BCM94331X19	0X00D6
+#define BCMA_BOARD_TYPE_BCM94331X28	0X00E4
+#define BCMA_BOARD_TYPE_BCM94331X28B	0X010E
+#define BCMA_BOARD_TYPE_BCM94331PCIEBT3AX	0X00E4
+#define BCMA_BOARD_TYPE_BCM94331X12_2G	0X00EC
+#define BCMA_BOARD_TYPE_BCM94331X12_5G	0X00ED
+#define BCMA_BOARD_TYPE_BCM94331X29B	0X00EF
+#define BCMA_BOARD_TYPE_BCM94331CSAX	0X00EF
+#define BCMA_BOARD_TYPE_BCM94331X19C	0X00F5
+#define BCMA_BOARD_TYPE_BCM94331X33	0X00F4
+#define BCMA_BOARD_TYPE_BCM94331BU	0X0523
+#define BCMA_BOARD_TYPE_BCM94331S9BU	0X0524
+#define BCMA_BOARD_TYPE_BCM94331MC	0X0525
+#define BCMA_BOARD_TYPE_BCM94331MCI	0X0526
+#define BCMA_BOARD_TYPE_BCM94331PCIEBT4	0X0527
+#define BCMA_BOARD_TYPE_BCM94331HM	0X0574
+#define BCMA_BOARD_TYPE_BCM94331PCIEDUAL	0X059B
+#define BCMA_BOARD_TYPE_BCM94331MCH5	0X05A9
+#define BCMA_BOARD_TYPE_BCM94331CS	0X05C6
+#define BCMA_BOARD_TYPE_BCM94331CD	0X05DA
+/* BCM53572 */
+#define BCMA_BOARD_TYPE_BCM953572BU	0X058D
+#define BCMA_BOARD_TYPE_BCM953572NR2	0X058E
+#define BCMA_BOARD_TYPE_BCM947188NR2	0X058F
+#define BCMA_BOARD_TYPE_BCM953572SDRNR2	0X0590
+/* BCM43142 */
+#define BCMA_BOARD_TYPE_BCM943142HM	0X05E0
+
 struct bcma_device {
 	struct bcma_bus *bus;
 	struct bcma_device_id id;
diff --git a/include/linux/bcma/bcma_driver_chipcommon.h b/include/linux/bcma/bcma_driver_chipcommon.h
index 8390c47..453fcc9 100644
--- a/include/linux/bcma/bcma_driver_chipcommon.h
+++ b/include/linux/bcma/bcma_driver_chipcommon.h
@@ -104,6 +104,7 @@
 #define  BCMA_CC_CHIPST_4706_MIPS_BENDIAN	BIT(3) /* 0: little, 1: big endian */
 #define  BCMA_CC_CHIPST_4706_PCIE1_DISABLE	BIT(5) /* PCIE1 enable strap pin */
 #define  BCMA_CC_CHIPST_5357_NAND_BOOT		BIT(4) /* NAND boot, valid for CC rev 38 and/or BCM5357 */
+#define  BCMA_CC_CHIPST_4360_XTAL_40MZ		0x00000001
 #define BCMA_CC_JCMD			0x0030		/* Rev >= 10 only */
 #define  BCMA_CC_JCMD_START		0x80000000
 #define  BCMA_CC_JCMD_BUSY		0x80000000
@@ -607,6 +608,8 @@ void bcma_chipco_bcm4331_ext_pa_lines_ctl(struct bcma_drv_cc *cc, bool enable);
 
 extern u32 bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, u32 ticks);
 
+extern u32 bcma_chipco_get_alp_clock(struct bcma_drv_cc *cc);
+
 void bcma_chipco_irq_mask(struct bcma_drv_cc *cc, u32 mask, u32 value);
 
 u32 bcma_chipco_irq_status(struct bcma_drv_cc *cc, u32 mask);
diff --git a/include/linux/bio.h b/include/linux/bio.h
index 820e7aa..5db8a51 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -24,6 +24,7 @@
 #include <linux/mempool.h>
 #include <linux/ioprio.h>
 #include <linux/bug.h>
+#include <linux/batch_complete.h>
 
 #ifdef CONFIG_BLOCK
 
@@ -67,6 +68,9 @@
 #define bio_offset(bio)		bio_iovec((bio))->bv_offset
 #define bio_segments(bio)	((bio)->bi_vcnt - (bio)->bi_idx)
 #define bio_sectors(bio)	((bio)->bi_size >> 9)
+#define bio_end_sector(bio)	((bio)->bi_sector + bio_sectors((bio)))
+
+void bio_endio_batch(struct bio *bio, int error, struct batch_complete *batch);
 
 static inline unsigned int bio_cur_bytes(struct bio *bio)
 {
@@ -84,11 +88,6 @@ static inline void *bio_data(struct bio *bio)
 	return NULL;
 }
 
-static inline int bio_has_allocated_vec(struct bio *bio)
-{
-	return bio->bi_io_vec && bio->bi_io_vec != bio->bi_inline_vecs;
-}
-
 /*
  * will die
  */
@@ -136,16 +135,27 @@ static inline int bio_has_allocated_vec(struct bio *bio)
 #define bio_io_error(bio) bio_endio((bio), -EIO)
 
 /*
- * drivers should not use the __ version unless they _really_ want to
- * run through the entire bio and not just pending pieces
+ * drivers should not use the __ version unless they _really_ know what
+ * they're doing
  */
 #define __bio_for_each_segment(bvl, bio, i, start_idx)			\
 	for (bvl = bio_iovec_idx((bio), (start_idx)), i = (start_idx);	\
 	     i < (bio)->bi_vcnt;					\
 	     bvl++, i++)
 
+/*
+ * drivers should _never_ use the all version - the bio may have been split
+ * before it got to the driver and the driver won't own all of it
+ */
+#define bio_for_each_segment_all(bvl, bio, i)				\
+	for (i = 0;							\
+	     bvl = bio_iovec_idx((bio), (i)), i < (bio)->bi_vcnt;	\
+	     i++)
+
 #define bio_for_each_segment(bvl, bio, i)				\
-	__bio_for_each_segment(bvl, bio, i, (bio)->bi_idx)
+	for (i = (bio)->bi_idx;						\
+	     bvl = bio_iovec_idx((bio), (i)), i < (bio)->bi_vcnt;	\
+	     i++)
 
 /*
  * get a reference to a bio, so it won't disappear. the intended use is
@@ -180,9 +190,12 @@ struct bio_integrity_payload {
 	unsigned short		bip_slab;	/* slab the bip came from */
 	unsigned short		bip_vcnt;	/* # of integrity bio_vecs */
 	unsigned short		bip_idx;	/* current bip_vec index */
+	unsigned		bip_owns_buf:1;	/* should free bip_buf */
 
 	struct work_struct	bip_work;	/* I/O completion */
-	struct bio_vec		bip_vec[0];	/* embedded bvec array */
+
+	struct bio_vec		*bip_vec;
+	struct bio_vec		bip_inline_vecs[0];/* embedded bvec array */
 };
 #endif /* CONFIG_BLK_DEV_INTEGRITY */
 
@@ -211,6 +224,7 @@ extern void bio_pair_release(struct bio_pair *dbio);
 
 extern struct bio_set *bioset_create(unsigned int, unsigned int);
 extern void bioset_free(struct bio_set *);
+extern mempool_t *biovec_create_pool(struct bio_set *bs, int pool_entries);
 
 extern struct bio *bio_alloc_bioset(gfp_t, int, struct bio_set *);
 extern void bio_put(struct bio *);
@@ -241,10 +255,31 @@ static inline struct bio *bio_clone_kmalloc(struct bio *bio, gfp_t gfp_mask)
 
 }
 
-extern void bio_endio(struct bio *, int);
+/**
+ * bio_endio - end I/O on a bio
+ * @bio:	bio
+ * @error:	error, if any
+ *
+ * Description:
+ *   bio_endio() will end I/O on the whole bio. bio_endio() is the
+ *   preferred way to end I/O on a bio, it takes care of clearing
+ *   BIO_UPTODATE on error. @error is 0 on success, and and one of the
+ *   established -Exxxx (-EIO, for instance) error values in case
+ *   something went wrong. No one should call bi_end_io() directly on a
+ *   bio unless they own it and thus know that it has an end_io
+ *   function.
+ **/
+static inline void bio_endio(struct bio *bio, int error)
+{
+	bio_endio_batch(bio, error, NULL);
+}
+
 struct request_queue;
 extern int bio_phys_segments(struct request_queue *, struct bio *);
 
+extern int submit_bio_wait(int rw, struct bio *bio);
+extern void bio_advance(struct bio *, unsigned);
+
 extern void bio_init(struct bio *);
 extern void bio_reset(struct bio *);
 
@@ -279,6 +314,9 @@ static inline void bio_flush_dcache_pages(struct bio *bi)
 }
 #endif
 
+extern void bio_copy_data(struct bio *dst, struct bio *src);
+extern int bio_alloc_pages(struct bio *bio, gfp_t gfp);
+
 extern struct bio *bio_copy_user(struct request_queue *, struct rq_map_data *,
 				 unsigned long, unsigned int, int, gfp_t);
 extern struct bio *bio_copy_user_iov(struct request_queue *,
@@ -286,8 +324,8 @@ extern struct bio *bio_copy_user_iov(struct request_queue *,
 				     int, int, gfp_t);
 extern int bio_uncopy_user(struct bio *);
 void zero_fill_bio(struct bio *bio);
-extern struct bio_vec *bvec_alloc_bs(gfp_t, int, unsigned long *, struct bio_set *);
-extern void bvec_free_bs(struct bio_set *, struct bio_vec *, unsigned int);
+extern struct bio_vec *bvec_alloc(gfp_t, int, unsigned long *, mempool_t *);
+extern void bvec_free(mempool_t *, struct bio_vec *, unsigned int);
 extern unsigned int bvec_nr_vecs(unsigned short idx);
 
 #ifdef CONFIG_BLK_CGROUP
@@ -298,39 +336,6 @@ static inline int bio_associate_current(struct bio *bio) { return -ENOENT; }
 static inline void bio_disassociate_task(struct bio *bio) { }
 #endif	/* CONFIG_BLK_CGROUP */
 
-/*
- * bio_set is used to allow other portions of the IO system to
- * allocate their own private memory pools for bio and iovec structures.
- * These memory pools in turn all allocate from the bio_slab
- * and the bvec_slabs[].
- */
-#define BIO_POOL_SIZE 2
-#define BIOVEC_NR_POOLS 6
-#define BIOVEC_MAX_IDX	(BIOVEC_NR_POOLS - 1)
-
-struct bio_set {
-	struct kmem_cache *bio_slab;
-	unsigned int front_pad;
-
-	mempool_t *bio_pool;
-#if defined(CONFIG_BLK_DEV_INTEGRITY)
-	mempool_t *bio_integrity_pool;
-#endif
-	mempool_t *bvec_pool;
-};
-
-struct biovec_slab {
-	int nr_vecs;
-	char *name;
-	struct kmem_cache *slab;
-};
-
-/*
- * a small number of entries is fine, not going to be performance critical.
- * basically we just need to survive
- */
-#define BIO_SPLIT_ENTRIES 2
-
 #ifdef CONFIG_HIGHMEM
 /*
  * remember never ever reenable interrupts between a bvec_kmap_irq and
@@ -420,10 +425,6 @@ static inline bool bio_mergeable(struct bio *bio)
  * member of the bio.  The bio_list also caches the last list member to allow
  * fast access to the tail.
  */
-struct bio_list {
-	struct bio *head;
-	struct bio *tail;
-};
 
 static inline int bio_list_empty(const struct bio_list *bl)
 {
@@ -527,6 +528,58 @@ static inline struct bio *bio_list_get(struct bio_list *bl)
 	return bio;
 }
 
+/*
+ * bio_set is used to allow other portions of the IO system to
+ * allocate their own private memory pools for bio and iovec structures.
+ * These memory pools in turn all allocate from the bio_slab
+ * and the bvec_slabs[].
+ */
+#define BIO_POOL_SIZE 2
+#define BIOVEC_NR_POOLS 6
+#define BIOVEC_MAX_IDX	(BIOVEC_NR_POOLS - 1)
+
+struct bio_set {
+	struct kmem_cache *bio_slab;
+	unsigned int front_pad;
+
+	mempool_t *bio_pool;
+	mempool_t *bvec_pool;
+#if defined(CONFIG_BLK_DEV_INTEGRITY)
+	mempool_t *bio_integrity_pool;
+	mempool_t *bvec_integrity_pool;
+#endif
+
+	/*
+	 * Deadlock avoidance for stacking block drivers: see comments in
+	 * bio_alloc_bioset() for details
+	 */
+	spinlock_t		rescue_lock;
+	struct bio_list		rescue_list;
+	struct work_struct	rescue_work;
+	struct workqueue_struct	*rescue_workqueue;
+};
+
+struct biovec_slab {
+	int nr_vecs;
+	char *name;
+	struct kmem_cache *slab;
+};
+
+/*
+ * a small number of entries is fine, not going to be performance critical.
+ * basically we just need to survive
+ */
+#define BIO_SPLIT_ENTRIES 2
+
+static inline void batch_complete_init(struct batch_complete *batch)
+{
+	bio_list_init(&batch->bio);
+	batch->kiocb = RB_ROOT;
+}
+
+void batch_complete(struct batch_complete *batch);
+
+
 #if defined(CONFIG_BLK_DEV_INTEGRITY)
 
 #define bip_vec_idx(bip, idx)	(&(bip->bip_vec[(idx)]))
@@ -553,7 +606,7 @@ extern int bio_integrity_enabled(struct bio *bio);
 extern int bio_integrity_set_tag(struct bio *, void *, unsigned int);
 extern int bio_integrity_get_tag(struct bio *, void *, unsigned int);
 extern int bio_integrity_prep(struct bio *);
-extern void bio_integrity_endio(struct bio *, int);
+extern void bio_integrity_endio(struct bio *, int, struct batch_complete *);
 extern void bio_integrity_advance(struct bio *, unsigned int);
 extern void bio_integrity_trim(struct bio *, unsigned int, unsigned int);
 extern void bio_integrity_split(struct bio *, struct bio_pair *, int);
diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h
index cdf1119..bd5fe42 100644
--- a/include/linux/blk_types.h
+++ b/include/linux/blk_types.h
@@ -16,7 +16,8 @@ struct page;
 struct block_device;
 struct io_context;
 struct cgroup_subsys_state;
-typedef void (bio_end_io_t) (struct bio *, int);
+struct batch_complete;
+typedef void (bio_end_io_t) (struct bio *, int, struct batch_complete *);
 typedef void (bio_destructor_t) (struct bio *);
 
 /*
@@ -42,6 +43,7 @@ struct bio {
 						 * top bits priority
 						 */
 
+	short			bi_error;
 	unsigned short		bi_vcnt;	/* how many bio_vec's */
 	unsigned short		bi_idx;		/* current index into bvl_vec */
 
@@ -111,12 +113,13 @@ struct bio {
 #define BIO_FS_INTEGRITY 9	/* fs owns integrity data, not block layer */
 #define BIO_QUIET	10	/* Make BIO Quiet */
 #define BIO_MAPPED_INTEGRITY 11/* integrity metadata has been remapped */
-
+#define BIO_SNAP_STABLE	12	/* bio data must be snapshotted during write */
 /*
  * Flags starting here get preserved by bio_reset() - this includes
  * BIO_POOL_IDX()
  */
-#define BIO_RESET_BITS	12
+#define BIO_RESET_BITS	13
+#define BIO_OWNS_VEC	13	/* bio_free() should free bvec */
 
 #define bio_flagged(bio, flag)	((bio)->bi_flags & (1 << (flag)))
 
@@ -175,6 +178,7 @@ enum rq_flag_bits {
 	__REQ_IO_STAT,		/* account I/O stat */
 	__REQ_MIXED_MERGE,	/* merge of different types, fail separately */
 	__REQ_KERNEL, 		/* direct IO to kernel pages */
+	__REQ_PM,		/* runtime pm request */
 	__REQ_NR_BITS,		/* stops here */
 };
 
@@ -197,6 +201,8 @@ enum rq_flag_bits {
 	 REQ_SECURE)
 #define REQ_CLONE_MASK		REQ_COMMON_MASK
 
+#define BIO_NO_ADVANCE_ITER_MASK	(REQ_DISCARD|REQ_WRITE_SAME)
+
 /* This mask is used for both bio and request merge checking */
 #define REQ_NOMERGE_FLAGS \
 	(REQ_NOMERGE | REQ_STARTED | REQ_SOFTBARRIER | REQ_FLUSH | REQ_FUA)
@@ -223,5 +229,6 @@ enum rq_flag_bits {
 #define REQ_MIXED_MERGE		(1 << __REQ_MIXED_MERGE)
 #define REQ_SECURE		(1 << __REQ_SECURE)
 #define REQ_KERNEL		(1 << __REQ_KERNEL)
+#define REQ_PM			(1 << __REQ_PM)
 
 #endif /* __LINUX_BLK_TYPES_H */
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 78feda9..07aa5f6 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -361,6 +361,12 @@ struct request_queue {
 	 */
 	struct kobject kobj;
 
+#ifdef CONFIG_PM_RUNTIME
+	struct device		*dev;
+	int			rpm_status;
+	unsigned int		nr_pending;
+#endif
+
 	/*
 	 * queue settings
 	 */
@@ -877,7 +883,8 @@ extern struct request *blk_fetch_request(struct request_queue *q);
  * This prevents code duplication in drivers.
  */
 extern bool blk_update_request(struct request *rq, int error,
-			       unsigned int nr_bytes);
+			       unsigned int nr_bytes,
+			       struct batch_complete *batch);
 extern bool blk_end_request(struct request *rq, int error,
 			    unsigned int nr_bytes);
 extern void blk_end_request_all(struct request *rq, int error);
@@ -885,10 +892,17 @@ extern bool blk_end_request_cur(struct request *rq, int error);
 extern bool blk_end_request_err(struct request *rq, int error);
 extern bool __blk_end_request(struct request *rq, int error,
 			      unsigned int nr_bytes);
-extern void __blk_end_request_all(struct request *rq, int error);
 extern bool __blk_end_request_cur(struct request *rq, int error);
 extern bool __blk_end_request_err(struct request *rq, int error);
 
+extern void blk_end_request_all_batch(struct request *rq, int error,
+				      struct batch_complete *batch);
+
+static inline void __blk_end_request_all(struct request *rq, int error)
+{
+	blk_end_request_all_batch(rq, error, NULL);
+}
+
 extern void blk_complete_request(struct request *);
 extern void __blk_complete_request(struct request *);
 extern void blk_abort_request(struct request *);
@@ -961,6 +975,27 @@ struct request_queue *blk_alloc_queue_node(gfp_t, int);
 extern void blk_put_queue(struct request_queue *);
 
 /*
+ * block layer runtime pm functions
+ */
+#ifdef CONFIG_PM_RUNTIME
+extern void blk_pm_runtime_init(struct request_queue *q, struct device *dev);
+extern int blk_pre_runtime_suspend(struct request_queue *q);
+extern void blk_post_runtime_suspend(struct request_queue *q, int err);
+extern void blk_pre_runtime_resume(struct request_queue *q);
+extern void blk_post_runtime_resume(struct request_queue *q, int err);
+#else
+static inline void blk_pm_runtime_init(struct request_queue *q,
+	struct device *dev) {}
+static inline int blk_pre_runtime_suspend(struct request_queue *q)
+{
+	return -ENOSYS;
+}
+static inline void blk_post_runtime_suspend(struct request_queue *q, int err) {}
+static inline void blk_pre_runtime_resume(struct request_queue *q) {}
+static inline void blk_post_runtime_resume(struct request_queue *q, int err) {}
+#endif
+
+/*
  * blk_plug permits building a queue of related requests by holding the I/O
  * fragments for a short period. This allows merging of sequential requests
  * into single larger request. As the requests are moved from a per-task list to
diff --git a/include/linux/blockconsole.h b/include/linux/blockconsole.h
new file mode 100644
index 0000000..114f7c5
--- /dev/null
+++ b/include/linux/blockconsole.h
@@ -0,0 +1,7 @@
+#ifndef LINUX_BLOCKCONSOLE_H
+#define LINUX_BLOCKCONSOLE_H
+
+int bcon_magic_present(const void *data);
+void bcon_add(const char *name);
+
+#endif
diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h
index 5afc4f9..4c16c4a 100644
--- a/include/linux/buffer_head.h
+++ b/include/linux/buffer_head.h
@@ -181,6 +181,7 @@ void ll_rw_block(int, int, struct buffer_head * bh[]);
 int sync_dirty_buffer(struct buffer_head *bh);
 int __sync_dirty_buffer(struct buffer_head *bh, int rw);
 void write_dirty_buffer(struct buffer_head *bh, int rw);
+int _submit_bh(int rw, struct buffer_head *bh, unsigned long bio_flags);
 int submit_bh(int, struct buffer_head *);
 void write_boundary_block(struct block_device *bdev,
 			sector_t bblock, unsigned blocksize);
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index 900af59..2eaedc1 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -27,6 +27,7 @@ struct cgroup_subsys;
 struct inode;
 struct cgroup;
 struct css_id;
+struct eventfd_ctx;
 
 extern int cgroup_init_early(void);
 extern int cgroup_init(void);
@@ -44,14 +45,25 @@ extern void cgroup_unload_subsys(struct cgroup_subsys *ss);
 
 extern const struct file_operations proc_cgroup_operations;
 
-/* Define the enumeration of all builtin cgroup subsystems */
+/*
+ * Define the enumeration of all cgroup subsystems.
+ *
+ * We define ids for builtin subsystems and then modular ones.
+ */
 #define SUBSYS(_x) _x ## _subsys_id,
-#define IS_SUBSYS_ENABLED(option) IS_ENABLED(option)
 enum cgroup_subsys_id {
+#define IS_SUBSYS_ENABLED(option) IS_BUILTIN(option)
 #include <linux/cgroup_subsys.h>
+#undef IS_SUBSYS_ENABLED
+	CGROUP_BUILTIN_SUBSYS_COUNT,
+
+	__CGROUP_SUBSYS_TEMP_PLACEHOLDER = CGROUP_BUILTIN_SUBSYS_COUNT - 1,
+
+#define IS_SUBSYS_ENABLED(option) IS_MODULE(option)
+#include <linux/cgroup_subsys.h>
+#undef IS_SUBSYS_ENABLED
 	CGROUP_SUBSYS_COUNT,
 };
-#undef IS_SUBSYS_ENABLED
 #undef SUBSYS
 
 /* Per-subsystem/per-cgroup state maintained by the system. */
@@ -150,6 +162,11 @@ enum {
 	CGRP_CPUSET_CLONE_CHILDREN,
 };
 
+struct cgroup_name {
+	struct rcu_head rcu_head;
+	char name[];
+};
+
 struct cgroup {
 	unsigned long flags;		/* "unsigned long" so bitops work */
 
@@ -172,6 +189,19 @@ struct cgroup {
 	struct cgroup *parent;		/* my parent */
 	struct dentry *dentry;		/* cgroup fs entry, RCU protected */
 
+	/*
+	 * This is a copy of dentry->d_name, and it's needed because
+	 * we can't use dentry->d_name in cgroup_path().
+	 *
+	 * You must acquire rcu_read_lock() to access cgrp->name, and
+	 * the only place that can change it is rename(), which is
+	 * protected by parent dir's i_mutex.
+	 *
+	 * Normally you should use cgroup_name() wrapper rather than
+	 * access it directly.
+	 */
+	struct cgroup_name __rcu *name;
+
 	/* Private pointers for each registered subsystem */
 	struct cgroup_subsys_state *subsys[CGROUP_SUBSYS_COUNT];
 
@@ -404,6 +434,12 @@ struct cgroup_scanner {
 	void *data;
 };
 
+/* Caller should hold rcu_read_lock() */
+static inline const char *cgroup_name(const struct cgroup *cgrp)
+{
+	return rcu_dereference(cgrp->name)->name;
+}
+
 int cgroup_add_cftypes(struct cgroup_subsys *ss, struct cftype *cfts);
 int cgroup_rm_cftypes(struct cgroup_subsys *ss, struct cftype *cfts);
 
@@ -413,9 +449,6 @@ int cgroup_path(const struct cgroup *cgrp, char *buf, int buflen);
 
 int cgroup_task_count(const struct cgroup *cgrp);
 
-/* Return true if cgrp is a descendant of the task's cgroup */
-int cgroup_is_descendant(const struct cgroup *cgrp, struct task_struct *task);
-
 /*
  * Control Group taskset, used to pass around set of tasks to cgroup_subsys
  * methods.
@@ -661,7 +694,8 @@ struct task_struct *cgroup_iter_next(struct cgroup *cgrp,
 					struct cgroup_iter *it);
 void cgroup_iter_end(struct cgroup *cgrp, struct cgroup_iter *it);
 int cgroup_scan_tasks(struct cgroup_scanner *scan);
-int cgroup_attach_task(struct cgroup *, struct task_struct *);
+int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk,
+		       bool threadgroup);
 int cgroup_attach_task_all(struct task_struct *from, struct task_struct *);
 
 /*
@@ -687,13 +721,6 @@ void free_css_id(struct cgroup_subsys *ss, struct cgroup_subsys_state *css);
 
 struct cgroup_subsys_state *css_lookup(struct cgroup_subsys *ss, int id);
 
-/*
- * Get a cgroup whose id is greater than or equal to id under tree of root.
- * Returning a cgroup_subsys_state or NULL.
- */
-struct cgroup_subsys_state *css_get_next(struct cgroup_subsys *ss, int id,
-		struct cgroup_subsys_state *root, int *foundid);
-
 /* Returns true if root is ancestor of cg */
 bool css_is_ancestor(struct cgroup_subsys_state *cg,
 		     const struct cgroup_subsys_state *root);
diff --git a/include/linux/cgroup_subsys.h b/include/linux/cgroup_subsys.h
index f204a7a..6e7ec64 100644
--- a/include/linux/cgroup_subsys.h
+++ b/include/linux/cgroup_subsys.h
@@ -78,3 +78,9 @@ SUBSYS(hugetlb)
 #endif
 
 /* */
+
+#ifdef CONFIG_CGROUP_BCACHE
+SUBSYS(bcache)
+#endif
+
+/* */
diff --git a/include/linux/cleancache.h b/include/linux/cleancache.h
index 42e55de..4ce9056 100644
--- a/include/linux/cleancache.h
+++ b/include/linux/cleancache.h
@@ -33,7 +33,7 @@ struct cleancache_ops {
 	void (*invalidate_fs)(int);
 };
 
-extern struct cleancache_ops
+extern struct cleancache_ops *
 	cleancache_register_ops(struct cleancache_ops *ops);
 extern void __cleancache_init_fs(struct super_block *);
 extern void __cleancache_init_shared_fs(char *, struct super_block *);
@@ -42,9 +42,9 @@ extern void __cleancache_put_page(struct page *);
 extern void __cleancache_invalidate_page(struct address_space *, struct page *);
 extern void __cleancache_invalidate_inode(struct address_space *);
 extern void __cleancache_invalidate_fs(struct super_block *);
-extern int cleancache_enabled;
 
 #ifdef CONFIG_CLEANCACHE
+#define cleancache_enabled (1)
 static inline bool cleancache_fs_enabled(struct page *page)
 {
 	return page->mapping->host->i_sb->cleancache_poolid >= 0;
diff --git a/include/linux/clk-private.h b/include/linux/clk-private.h
index 9c7f580..dd7adff 100644
--- a/include/linux/clk-private.h
+++ b/include/linux/clk-private.h
@@ -152,7 +152,7 @@ struct clk {
 		},						\
 		.reg = _reg,					\
 		.shift = _shift,				\
-		.width = _width,				\
+		.mask = BIT(_width) - 1,			\
 		.flags = _mux_flags,				\
 		.lock = _lock,					\
 	};							\
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 7f197d7..9fdfae7 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -45,6 +45,14 @@ struct clk_hw;
  * 		undo any work done in the @prepare callback. Called with
  * 		prepare_lock held.
  *
+ * @is_prepared: Queries the hardware to determine if the clock is prepared.
+ *		This function is allowed to sleep. Optional, if this op is not
+ *		set then the prepare count will be used.
+ *
+ * @unprepare_unused: Unprepare the clock atomically.  Only called from
+ *		clk_disable_unused for prepare clocks with special needs.
+ *		Called with prepare mutex held. This function may sleep.
+ *
  * @enable:	Enable the clock atomically. This must not return until the
  * 		clock is generating a valid clock signal, usable by consumer
  * 		devices. Called with enable_lock held. This function must not
@@ -108,6 +116,8 @@ struct clk_hw;
 struct clk_ops {
 	int		(*prepare)(struct clk_hw *hw);
 	void		(*unprepare)(struct clk_hw *hw);
+	int		(*is_prepared)(struct clk_hw *hw);
+	void		(*unprepare_unused)(struct clk_hw *hw);
 	int		(*enable)(struct clk_hw *hw);
 	void		(*disable)(struct clk_hw *hw);
 	int		(*is_enabled)(struct clk_hw *hw);
@@ -239,9 +249,14 @@ struct clk_div_table {
  * CLK_DIVIDER_ONE_BASED - by default the divisor is the value read from the
  * 	register plus one.  If CLK_DIVIDER_ONE_BASED is set then the divider is
  * 	the raw value read from the register, with the value of zero considered
- * 	invalid
+ *	invalid, unless CLK_DIVIDER_ALLOW_ZERO is set.
  * CLK_DIVIDER_POWER_OF_TWO - clock divisor is 2 raised to the value read from
  * 	the hardware register
+ * CLK_DIVIDER_ALLOW_ZERO - Allow zero divisors.  For dividers which have
+ *	CLK_DIVIDER_ONE_BASED set, it is possible to end up with a zero divisor.
+ *	Some hardware implementations gracefully handle this case and allow a
+ *	zero divisor by not modifying their input clock
+ *	(divide by one / bypass).
  */
 struct clk_divider {
 	struct clk_hw	hw;
@@ -255,6 +270,7 @@ struct clk_divider {
 
 #define CLK_DIVIDER_ONE_BASED		BIT(0)
 #define CLK_DIVIDER_POWER_OF_TWO	BIT(1)
+#define CLK_DIVIDER_ALLOW_ZERO		BIT(2)
 
 extern const struct clk_ops clk_divider_ops;
 struct clk *clk_register_divider(struct device *dev, const char *name,
@@ -274,7 +290,7 @@ struct clk *clk_register_divider_table(struct device *dev, const char *name,
  * @reg:	register controlling multiplexer
  * @shift:	shift to multiplexer bit field
  * @width:	width of mutliplexer bit field
- * @num_clks:	number of parent clocks
+ * @flags:	hardware-specific flags
  * @lock:	register lock
  *
  * Clock with multiple selectable parents.  Implements .get_parent, .set_parent
@@ -287,8 +303,9 @@ struct clk *clk_register_divider_table(struct device *dev, const char *name,
 struct clk_mux {
 	struct clk_hw	hw;
 	void __iomem	*reg;
+	u32		*table;
+	u32		mask;
 	u8		shift;
-	u8		width;
 	u8		flags;
 	spinlock_t	*lock;
 };
@@ -297,11 +314,17 @@ struct clk_mux {
 #define CLK_MUX_INDEX_BIT		BIT(1)
 
 extern const struct clk_ops clk_mux_ops;
+
 struct clk *clk_register_mux(struct device *dev, const char *name,
 		const char **parent_names, u8 num_parents, unsigned long flags,
 		void __iomem *reg, u8 shift, u8 width,
 		u8 clk_mux_flags, spinlock_t *lock);
 
+struct clk *clk_register_mux_table(struct device *dev, const char *name,
+		const char **parent_names, u8 num_parents, unsigned long flags,
+		void __iomem *reg, u8 shift, u32 mask,
+		u8 clk_mux_flags, u32 *table, spinlock_t *lock);
+
 /**
  * struct clk_fixed_factor - fixed multiplier and divider clock
  *
@@ -325,6 +348,37 @@ struct clk *clk_register_fixed_factor(struct device *dev, const char *name,
 		const char *parent_name, unsigned long flags,
 		unsigned int mult, unsigned int div);
 
+/***
+ * struct clk_composite - aggregate clock of mux, divider and gate clocks
+ *
+ * @hw:		handle between common and hardware-specific interfaces
+ * @mux_hw:	handle between composite and hardware-specifix mux clock
+ * @div_hw:	handle between composite and hardware-specifix divider clock
+ * @gate_hw:	handle between composite and hardware-specifix gate clock
+ * @mux_ops:	clock ops for mux
+ * @div_ops:	clock ops for divider
+ * @gate_ops:	clock ops for gate
+ */
+struct clk_composite {
+	struct clk_hw	hw;
+	struct clk_ops	ops;
+
+	struct clk_hw	*mux_hw;
+	struct clk_hw	*div_hw;
+	struct clk_hw	*gate_hw;
+
+	const struct clk_ops	*mux_ops;
+	const struct clk_ops	*div_ops;
+	const struct clk_ops	*gate_ops;
+};
+
+struct clk *clk_register_composite(struct device *dev, const char *name,
+		const char **parent_names, int num_parents,
+		struct clk_hw *mux_hw, const struct clk_ops *mux_ops,
+		struct clk_hw *div_hw, const struct clk_ops *div_ops,
+		struct clk_hw *gate_hw, const struct clk_ops *gate_ops,
+		unsigned long flags);
+
 /**
  * clk_register - allocate a new clock, register it and return an opaque cookie
  * @dev: device that is registering this clock
@@ -351,6 +405,7 @@ unsigned int __clk_get_enable_count(struct clk *clk);
 unsigned int __clk_get_prepare_count(struct clk *clk);
 unsigned long __clk_get_rate(struct clk *clk);
 unsigned long __clk_get_flags(struct clk *clk);
+bool __clk_is_prepared(struct clk *clk);
 bool __clk_is_enabled(struct clk *clk);
 struct clk *__clk_lookup(const char *name);
 
diff --git a/include/linux/clk/mxs.h b/include/linux/clk/mxs.h
new file mode 100644
index 0000000..90c30dc
--- /dev/null
+++ b/include/linux/clk/mxs.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2013 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __LINUX_CLK_MXS_H
+#define __LINUX_CLK_MXS_H
+
+int mx23_clocks_init(void);
+int mx28_clocks_init(void);
+int mxs_saif_clkmux_select(unsigned int clkmux);
+
+#endif
diff --git a/include/linux/clk/sunxi.h b/include/linux/clk/sunxi.h
new file mode 100644
index 0000000..e074fdd
--- /dev/null
+++ b/include/linux/clk/sunxi.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2012 Maxime Ripard
+ *
+ * Maxime Ripard <maxime.ripard@free-electrons.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.
+ */
+
+#ifndef __LINUX_CLK_SUNXI_H_
+#define __LINUX_CLK_SUNXI_H_
+
+void __init sunxi_init_clocks(void);
+
+#endif
diff --git a/include/linux/clockchips.h b/include/linux/clockchips.h
index 6634652..0a78a74 100644
--- a/include/linux/clockchips.h
+++ b/include/linux/clockchips.h
@@ -8,6 +8,20 @@
 #ifndef _LINUX_CLOCKCHIPS_H
 #define _LINUX_CLOCKCHIPS_H
 
+/* Clock event notification values */
+enum clock_event_nofitiers {
+	CLOCK_EVT_NOTIFY_ADD,
+	CLOCK_EVT_NOTIFY_BROADCAST_ON,
+	CLOCK_EVT_NOTIFY_BROADCAST_OFF,
+	CLOCK_EVT_NOTIFY_BROADCAST_FORCE,
+	CLOCK_EVT_NOTIFY_BROADCAST_ENTER,
+	CLOCK_EVT_NOTIFY_BROADCAST_EXIT,
+	CLOCK_EVT_NOTIFY_SUSPEND,
+	CLOCK_EVT_NOTIFY_RESUME,
+	CLOCK_EVT_NOTIFY_CPU_DYING,
+	CLOCK_EVT_NOTIFY_CPU_DEAD,
+};
+
 #ifdef CONFIG_GENERIC_CLOCKEVENTS_BUILD
 
 #include <linux/clocksource.h>
@@ -26,20 +40,6 @@ enum clock_event_mode {
 	CLOCK_EVT_MODE_RESUME,
 };
 
-/* Clock event notification values */
-enum clock_event_nofitiers {
-	CLOCK_EVT_NOTIFY_ADD,
-	CLOCK_EVT_NOTIFY_BROADCAST_ON,
-	CLOCK_EVT_NOTIFY_BROADCAST_OFF,
-	CLOCK_EVT_NOTIFY_BROADCAST_FORCE,
-	CLOCK_EVT_NOTIFY_BROADCAST_ENTER,
-	CLOCK_EVT_NOTIFY_BROADCAST_EXIT,
-	CLOCK_EVT_NOTIFY_SUSPEND,
-	CLOCK_EVT_NOTIFY_RESUME,
-	CLOCK_EVT_NOTIFY_CPU_DYING,
-	CLOCK_EVT_NOTIFY_CPU_DEAD,
-};
-
 /*
  * Clock event features
  */
@@ -55,6 +55,11 @@ enum clock_event_nofitiers {
 #define CLOCK_EVT_FEAT_C3STOP		0x000008
 #define CLOCK_EVT_FEAT_DUMMY		0x000010
 
+/*
+ * Core shall set the interrupt affinity dynamically in broadcast mode
+ */
+#define CLOCK_EVT_FEAT_DYNIRQ		0x000020
+
 /**
  * struct clock_event_device - clock event device descriptor
  * @event_handler:	Assigned by the framework to be called by the low
@@ -173,7 +178,7 @@ extern int tick_receive_broadcast(void);
 #ifdef CONFIG_GENERIC_CLOCKEVENTS
 extern void clockevents_notify(unsigned long reason, void *arg);
 #else
-# define clockevents_notify(reason, arg) do { } while (0)
+static inline void clockevents_notify(unsigned long reason, void *arg) {}
 #endif
 
 #else /* CONFIG_GENERIC_CLOCKEVENTS_BUILD */
@@ -181,7 +186,7 @@ extern void clockevents_notify(unsigned long reason, void *arg);
 static inline void clockevents_suspend(void) {}
 static inline void clockevents_resume(void) {}
 
-#define clockevents_notify(reason, arg) do { } while (0)
+static inline void clockevents_notify(unsigned long reason, void *arg) {}
 
 #endif
 
diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h
index 27cfda4..192d6d1 100644
--- a/include/linux/clocksource.h
+++ b/include/linux/clocksource.h
@@ -332,15 +332,23 @@ extern int clocksource_mmio_init(void __iomem *, const char *,
 
 extern int clocksource_i8253_init(void);
 
+struct device_node;
+typedef void(*clocksource_of_init_fn)(struct device_node *);
 #ifdef CONFIG_CLKSRC_OF
 extern void clocksource_of_init(void);
 
 #define CLOCKSOURCE_OF_DECLARE(name, compat, fn)			\
 	static const struct of_device_id __clksrc_of_table_##name	\
 		__used __section(__clksrc_of_table)			\
-		 = { .compatible = compat, .data = fn };
+		 = { .compatible = compat,				\
+		     .data = (fn == (clocksource_of_init_fn)NULL) ? fn : fn }
 #else
-#define CLOCKSOURCE_OF_DECLARE(name, compat, fn)
+static inline void clocksource_of_init(void) {}
+#define CLOCKSOURCE_OF_DECLARE(name, compat, fn)			\
+	static const struct of_device_id __clksrc_of_table_##name	\
+		__attribute__((unused))					\
+		 = { .compatible = compat,				\
+		     .data = (fn == (clocksource_of_init_fn)NULL) ? fn : fn }
 #endif
 
 #endif /* _LINUX_CLOCKSOURCE_H */
diff --git a/include/linux/cn_proc.h b/include/linux/cn_proc.h
index 2c1bc1e..1d5b02a 100644
--- a/include/linux/cn_proc.h
+++ b/include/linux/cn_proc.h
@@ -26,6 +26,7 @@ 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_comm_connector(struct task_struct *task);
+void proc_coredump_connector(struct task_struct *task);
 void proc_exit_connector(struct task_struct *task);
 #else
 static inline void proc_fork_connector(struct task_struct *task)
@@ -48,6 +49,9 @@ static inline void proc_ptrace_connector(struct task_struct *task,
 					 int ptrace_id)
 {}
 
+static inline void proc_coredump_connector(struct task_struct *task)
+{}
+
 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 76a87fb..d53c353 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -27,12 +27,6 @@
 #define __SC_DELOUSE(t,v) ((t)(unsigned long)(v))
 #endif
 
-#define __SC_CCAST1(t1, a1)      __SC_DELOUSE(t1,a1)
-#define __SC_CCAST2(t2, a2, ...) __SC_DELOUSE(t2,a2), __SC_CCAST1(__VA_ARGS__)
-#define __SC_CCAST3(t3, a3, ...) __SC_DELOUSE(t3,a3), __SC_CCAST2(__VA_ARGS__)
-#define __SC_CCAST4(t4, a4, ...) __SC_DELOUSE(t4,a4), __SC_CCAST3(__VA_ARGS__)
-#define __SC_CCAST5(t5, a5, ...) __SC_DELOUSE(t5,a5), __SC_CCAST4(__VA_ARGS__)
-#define __SC_CCAST6(t6, a6, ...) __SC_DELOUSE(t6,a6), __SC_CCAST5(__VA_ARGS__)
 #define COMPAT_SYSCALL_DEFINE1(name, ...) \
         COMPAT_SYSCALL_DEFINEx(1, _##name, __VA_ARGS__)
 #define COMPAT_SYSCALL_DEFINE2(name, ...) \
@@ -46,24 +40,15 @@
 #define COMPAT_SYSCALL_DEFINE6(name, ...) \
 	COMPAT_SYSCALL_DEFINEx(6, _##name, __VA_ARGS__)
 
-#ifdef CONFIG_HAVE_SYSCALL_WRAPPERS
-
 #define COMPAT_SYSCALL_DEFINEx(x, name, ...)				\
-	asmlinkage long compat_sys##name(__SC_DECL##x(__VA_ARGS__));	\
-	static inline long C_SYSC##name(__SC_DECL##x(__VA_ARGS__));	\
-	asmlinkage long compat_SyS##name(__SC_LONG##x(__VA_ARGS__))	\
+	asmlinkage long compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));\
+	static inline long C_SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__));\
+	asmlinkage long compat_SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__))\
 	{								\
-		return (long) C_SYSC##name(__SC_CCAST##x(__VA_ARGS__));	\
+		return C_SYSC##name(__MAP(x,__SC_DELOUSE,__VA_ARGS__));	\
 	}								\
 	SYSCALL_ALIAS(compat_sys##name, compat_SyS##name);		\
-	static inline long C_SYSC##name(__SC_DECL##x(__VA_ARGS__))
-
-#else /* CONFIG_HAVE_SYSCALL_WRAPPERS */
-
-#define COMPAT_SYSCALL_DEFINEx(x, name, ...)				\
-	asmlinkage long compat_sys##name(__SC_DECL##x(__VA_ARGS__))
-
-#endif /* CONFIG_HAVE_SYSCALL_WRAPPERS */
+	static inline long C_SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__))
 
 #ifndef compat_user_stack_pointer
 #define compat_user_stack_pointer() current_user_stack_pointer()
@@ -141,11 +126,11 @@ typedef struct {
 } compat_sigset_t;
 
 struct compat_sigaction {
-#ifndef __ARCH_HAS_ODD_SIGACTION
+#ifndef __ARCH_HAS_IRIX_SIGACTION
 	compat_uptr_t			sa_handler;
 	compat_ulong_t			sa_flags;
 #else
-	compat_ulong_t			sa_flags;
+	compat_uint_t			sa_flags;
 	compat_uptr_t			sa_handler;
 #endif
 #ifdef __ARCH_HAS_SA_RESTORER
@@ -326,21 +311,13 @@ asmlinkage long
 compat_sys_get_robust_list(int pid, compat_uptr_t __user *head_ptr,
 			   compat_size_t __user *len_ptr);
 
-#ifdef CONFIG_ARCH_WANT_OLD_COMPAT_IPC
-long compat_sys_semctl(int first, int second, int third, void __user *uptr);
-long compat_sys_msgsnd(int first, int second, int third, void __user *uptr);
-long compat_sys_msgrcv(int first, int second, int msgtyp, int third,
-		int version, void __user *uptr);
-long compat_sys_shmat(int first, int second, compat_uptr_t third, int version,
-		void __user *uptr);
-#else
-long compat_sys_semctl(int semid, int semnum, int cmd, int arg);
-long compat_sys_msgsnd(int msqid, struct compat_msgbuf __user *msgp,
+asmlinkage long compat_sys_ipc(u32, int, int, u32, compat_uptr_t, u32);
+asmlinkage long compat_sys_shmat(int shmid, compat_uptr_t shmaddr, int shmflg);
+asmlinkage long compat_sys_semctl(int semid, int semnum, int cmd, int arg);
+asmlinkage long compat_sys_msgsnd(int msqid, compat_uptr_t msgp,
 		compat_ssize_t msgsz, int msgflg);
-long compat_sys_msgrcv(int msqid, struct compat_msgbuf __user *msgp,
+asmlinkage long compat_sys_msgrcv(int msqid, compat_uptr_t msgp,
 		compat_ssize_t msgsz, long msgtyp, int msgflg);
-long compat_sys_shmat(int shmid, compat_uptr_t shmaddr, int shmflg);
-#endif
 long compat_sys_msgctl(int first, int second, void __user *uptr);
 long compat_sys_shmctl(int first, int second, void __user *uptr);
 long compat_sys_semtimedop(int semid, struct sembuf __user *tsems,
@@ -444,13 +421,13 @@ extern long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
 asmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid,
 				  compat_long_t addr, compat_long_t data);
 
+asmlinkage long compat_sys_lookup_dcookie(u32, u32, char __user *, size_t);
 /*
  * epoll (fs/eventpoll.c) compat bits follow ...
  */
-struct epoll_event;
-#define compat_epoll_event	epoll_event
+struct epoll_event;	/* fortunately, this one is fixed-layout */
 asmlinkage long compat_sys_epoll_pwait(int epfd,
-			struct compat_epoll_event __user *events,
+			struct epoll_event __user *events,
 			int maxevents, int timeout,
 			const compat_sigset_t __user *sigmask,
 			compat_size_t sigsetsize);
@@ -685,6 +662,8 @@ asmlinkage ssize_t compat_sys_process_vm_writev(compat_pid_t pid,
 
 asmlinkage long compat_sys_sendfile(int out_fd, int in_fd,
 				    compat_off_t __user *offset, compat_size_t count);
+asmlinkage long compat_sys_sendfile64(int out_fd, int in_fd,
+				    compat_loff_t __user *offset, compat_size_t count);
 asmlinkage long compat_sys_sigaltstack(const compat_stack_t __user *uss_ptr,
 				       compat_stack_t __user *uoss_ptr);
 
diff --git a/include/linux/console.h b/include/linux/console.h
index 29680a8..c5448f3 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -118,6 +118,7 @@ static inline int con_debug_leave(void)
 #define CON_BOOT	(8)
 #define CON_ANYTIME	(16) /* Safe to call when cpu is offline */
 #define CON_BRL		(32) /* Used for a braille device */
+#define CON_ALLDATA	(64) /* per-console ignore_loglevel */
 
 struct console {
 	char	name[16];
@@ -141,6 +142,7 @@ struct console {
 	for (con = console_drivers; con != NULL; con = con->next)
 
 extern int console_set_on_cmdline;
+extern struct console *early_console;
 
 extern int add_preferred_console(char *name, int idx, char *options);
 extern int update_console_cmdline(char *name, int idx, char *name_new, int idx_new, char *options);
diff --git a/include/linux/context_tracking.h b/include/linux/context_tracking.h
index b28d161..365f4a6 100644
--- a/include/linux/context_tracking.h
+++ b/include/linux/context_tracking.h
@@ -1,9 +1,9 @@
 #ifndef _LINUX_CONTEXT_TRACKING_H
 #define _LINUX_CONTEXT_TRACKING_H
 
-#ifdef CONFIG_CONTEXT_TRACKING
 #include <linux/sched.h>
 #include <linux/percpu.h>
+#include <asm/ptrace.h>
 
 struct context_tracking {
 	/*
@@ -13,12 +13,13 @@ struct context_tracking {
 	 * may be further optimized using static keys.
 	 */
 	bool active;
-	enum {
+	enum ctx_state {
 		IN_KERNEL = 0,
 		IN_USER,
 	} state;
 };
 
+#ifdef CONFIG_CONTEXT_TRACKING
 DECLARE_PER_CPU(struct context_tracking, context_tracking);
 
 static inline bool context_tracking_in_user(void)
@@ -33,12 +34,31 @@ static inline bool context_tracking_active(void)
 
 extern void user_enter(void);
 extern void user_exit(void);
+
+static inline enum ctx_state exception_enter(void)
+{
+	enum ctx_state prev_ctx;
+
+	prev_ctx = this_cpu_read(context_tracking.state);
+	user_exit();
+
+	return prev_ctx;
+}
+
+static inline void exception_exit(enum ctx_state prev_ctx)
+{
+	if (prev_ctx == IN_USER)
+		user_enter();
+}
+
 extern void context_tracking_task_switch(struct task_struct *prev,
 					 struct task_struct *next);
 #else
 static inline bool context_tracking_in_user(void) { return false; }
 static inline void user_enter(void) { }
 static inline void user_exit(void) { }
+static inline enum ctx_state exception_enter(void) { return 0; }
+static inline void exception_exit(enum ctx_state prev_ctx) { }
 static inline void context_tracking_task_switch(struct task_struct *prev,
 						struct task_struct *next) { }
 #endif /* !CONFIG_CONTEXT_TRACKING */
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index a22944c..037d36a 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -106,6 +106,7 @@ struct cpufreq_policy {
 					 * governors are used */
 	unsigned int		policy; /* see above */
 	struct cpufreq_governor	*governor; /* see below */
+	void			*governor_data;
 
 	struct work_struct	update; /* if update_policy() needs to be
 					 * called, but you're in IRQ context */
@@ -178,9 +179,11 @@ static inline unsigned long cpufreq_scale(unsigned long old, u_int div, u_int mu
  *                          CPUFREQ GOVERNORS                        *
  *********************************************************************/
 
-#define CPUFREQ_GOV_START  1
-#define CPUFREQ_GOV_STOP   2
-#define CPUFREQ_GOV_LIMITS 3
+#define CPUFREQ_GOV_START	1
+#define CPUFREQ_GOV_STOP	2
+#define CPUFREQ_GOV_LIMITS	3
+#define CPUFREQ_GOV_POLICY_INIT	4
+#define CPUFREQ_GOV_POLICY_EXIT	5
 
 struct cpufreq_governor {
 	char	name[CPUFREQ_NAME_LEN];
@@ -229,6 +232,13 @@ struct cpufreq_driver {
 	struct module           *owner;
 	char			name[CPUFREQ_NAME_LEN];
 	u8			flags;
+	/*
+	 * This should be set by platforms having multiple clock-domains, i.e.
+	 * supporting multiple policies. With this sysfs directories of governor
+	 * would be created in cpu/cpu<num>/cpufreq/ directory and so they can
+	 * use the same governor with different tunables for different clusters.
+	 */
+	bool			have_governor_per_policy;
 
 	/* needed by all drivers */
 	int	(*init)		(struct cpufreq_policy *policy);
@@ -268,8 +278,8 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data);
 int cpufreq_unregister_driver(struct cpufreq_driver *driver_data);
 
 
-void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state);
-
+void cpufreq_notify_transition(struct cpufreq_policy *policy,
+		struct cpufreq_freqs *freqs, unsigned int state);
 
 static inline void cpufreq_verify_within_limits(struct cpufreq_policy *policy, unsigned int min, unsigned int max)
 {
@@ -329,6 +339,7 @@ const char *cpufreq_get_current_driver(void);
  *********************************************************************/
 int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu);
 int cpufreq_update_policy(unsigned int cpu);
+bool have_governor_per_policy(void);
 
 #ifdef CONFIG_CPU_FREQ
 /* query the current CPU frequency (in kHz). If zero, cpufreq couldn't detect it */
diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h
index 480c14d..fc3e580 100644
--- a/include/linux/cpuidle.h
+++ b/include/linux/cpuidle.h
@@ -57,6 +57,7 @@ struct cpuidle_state {
 /* Idle State Flags */
 #define CPUIDLE_FLAG_TIME_VALID	(0x01) /* is residency time measurable? */
 #define CPUIDLE_FLAG_COUPLED	(0x02) /* state applies to multiple cpus */
+#define CPUIDLE_FLAG_TIMER_STOP (0x04)  /* timer is stopped on this state */
 
 #define CPUIDLE_DRIVER_FLAGS_MASK (0xFFFF0000)
 
@@ -106,6 +107,8 @@ struct cpuidle_driver {
 
 	/* set to 1 to use the core cpuidle time keeping (for all states). */
 	unsigned int		en_core_tk_irqen:1;
+        /* used by the cpuidle framework to setup the broadcast timer */
+	unsigned int            bctimer:1;
 	/* states array must be ordered in decreasing power consumption */
 	struct cpuidle_state	states[CPUIDLE_STATE_MAX];
 	int			state_count;
diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h
index 0325602..d08e4d2 100644
--- a/include/linux/cpumask.h
+++ b/include/linux/cpumask.h
@@ -591,6 +591,21 @@ static inline int cpulist_scnprintf(char *buf, int len,
 }
 
 /**
+ * cpumask_parse - extract a cpumask from from a string
+ * @buf: the buffer to extract from
+ * @dstp: the cpumask to set.
+ *
+ * Returns -errno, or 0 for success.
+ */
+static inline int cpumask_parse(const char *buf, struct cpumask *dstp)
+{
+	char *nl = strchr(buf, '\n');
+	int len = nl ? nl - buf : strlen(buf);
+
+	return bitmap_parse(buf, len, cpumask_bits(dstp), nr_cpumask_bits);
+}
+
+/**
  * cpulist_parse - extract a cpumask from a user string of ranges
  * @buf: the buffer to extract from
  * @dstp: the cpumask to set.
diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h
index 8c8a60d..ccd1de8 100644
--- a/include/linux/cpuset.h
+++ b/include/linux/cpuset.h
@@ -11,7 +11,6 @@
 #include <linux/sched.h>
 #include <linux/cpumask.h>
 #include <linux/nodemask.h>
-#include <linux/cgroup.h>
 #include <linux/mm.h>
 
 #ifdef CONFIG_CPUSETS
diff --git a/include/linux/debug_locks.h b/include/linux/debug_locks.h
index 3bd46f7..21ca773 100644
--- a/include/linux/debug_locks.h
+++ b/include/linux/debug_locks.h
@@ -27,7 +27,7 @@ extern int debug_locks_off(void);
 									\
 	if (!oops_in_progress && unlikely(c)) {				\
 		if (debug_locks_off() && !debug_locks_silent)		\
-			WARN_ON(1);					\
+			WARN(1, "DEBUG_LOCKS_WARN_ON(%s)", #c);		\
 		__ret = 1;						\
 	}								\
 	__ret;								\
diff --git a/include/linux/decompress/unlz4.h b/include/linux/decompress/unlz4.h
new file mode 100644
index 0000000..d5b68bf
--- /dev/null
+++ b/include/linux/decompress/unlz4.h
@@ -0,0 +1,10 @@
+#ifndef DECOMPRESS_UNLZ4_H
+#define DECOMPRESS_UNLZ4_H
+
+int unlz4(unsigned char *inbuf, int len,
+	int(*fill)(void*, unsigned int),
+	int(*flush)(void*, unsigned int),
+	unsigned char *output,
+	int *pos,
+	void(*error)(char *x));
+#endif
diff --git a/include/linux/devfreq.h b/include/linux/devfreq.h
index e83ef39..fe8c447 100644
--- a/include/linux/devfreq.h
+++ b/include/linux/devfreq.h
@@ -213,7 +213,7 @@ struct devfreq_simple_ondemand_data {
 #endif
 
 #else /* !CONFIG_PM_DEVFREQ */
-static struct devfreq *devfreq_add_device(struct device *dev,
+static inline struct devfreq *devfreq_add_device(struct device *dev,
 					  struct devfreq_dev_profile *profile,
 					  const char *governor_name,
 					  void *data)
@@ -221,34 +221,34 @@ static struct devfreq *devfreq_add_device(struct device *dev,
 	return NULL;
 }
 
-static int devfreq_remove_device(struct devfreq *devfreq)
+static inline int devfreq_remove_device(struct devfreq *devfreq)
 {
 	return 0;
 }
 
-static int devfreq_suspend_device(struct devfreq *devfreq)
+static inline int devfreq_suspend_device(struct devfreq *devfreq)
 {
 	return 0;
 }
 
-static int devfreq_resume_device(struct devfreq *devfreq)
+static inline int devfreq_resume_device(struct devfreq *devfreq)
 {
 	return 0;
 }
 
-static struct opp *devfreq_recommended_opp(struct device *dev,
+static inline struct opp *devfreq_recommended_opp(struct device *dev,
 					   unsigned long *freq, u32 flags)
 {
-	return -EINVAL;
+	return ERR_PTR(-EINVAL);
 }
 
-static int devfreq_register_opp_notifier(struct device *dev,
+static inline int devfreq_register_opp_notifier(struct device *dev,
 					 struct devfreq *devfreq)
 {
 	return -EINVAL;
 }
 
-static int devfreq_unregister_opp_notifier(struct device *dev,
+static inline int devfreq_unregister_opp_notifier(struct device *dev,
 					   struct devfreq *devfreq)
 {
 	return -EINVAL;
diff --git a/include/linux/device.h b/include/linux/device.h
index 9d6464e..85733ca 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -111,17 +111,11 @@ struct bus_type {
 	struct iommu_ops *iommu_ops;
 
 	struct subsys_private *p;
+	struct lock_class_key lock_key;
 };
 
-/* This is a #define to keep the compiler from merging different
- * instances of the __key variable */
-#define bus_register(subsys)			\
-({						\
-	static struct lock_class_key __key;	\
-	__bus_register(subsys, &__key);	\
-})
-extern int __must_check __bus_register(struct bus_type *bus,
-				       struct lock_class_key *key);
+extern int __must_check bus_register(struct bus_type *bus);
+
 extern void bus_unregister(struct bus_type *bus);
 
 extern int __must_check bus_rescan_devices(struct bus_type *bus);
@@ -302,6 +296,8 @@ void subsys_interface_unregister(struct subsys_interface *sif);
 
 int subsys_system_register(struct bus_type *subsys,
 			   const struct attribute_group **groups);
+int subsys_virtual_register(struct bus_type *subsys,
+			    const struct attribute_group **groups);
 
 /**
  * struct class - device classes
@@ -578,6 +574,10 @@ void __iomem *devm_ioremap_resource(struct device *dev, struct resource *res);
 void __iomem *devm_request_and_ioremap(struct device *dev,
 			struct resource *res);
 
+/* allows to add/remove a custom action to devres stack */
+int devm_add_action(struct device *dev, void (*action)(void *), void *data);
+void devm_remove_action(struct device *dev, void (*action)(void *), void *data);
+
 struct device_dma_parameters {
 	/*
 	 * a low level driver may set these to teach IOMMU code about
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
index 91ac8da..96d3e4a 100644
--- a/include/linux/dmaengine.h
+++ b/include/linux/dmaengine.h
@@ -967,8 +967,9 @@ enum dma_status dma_sync_wait(struct dma_chan *chan, dma_cookie_t cookie);
 #ifdef CONFIG_DMA_ENGINE
 enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx);
 void dma_issue_pending_all(void);
-struct dma_chan *__dma_request_channel(dma_cap_mask_t *mask, dma_filter_fn fn, void *fn_param);
-struct dma_chan *dma_request_slave_channel(struct device *dev, char *name);
+struct dma_chan *__dma_request_channel(const dma_cap_mask_t *mask,
+					dma_filter_fn fn, void *fn_param);
+struct dma_chan *dma_request_slave_channel(struct device *dev, const char *name);
 void dma_release_channel(struct dma_chan *chan);
 #else
 static inline enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx)
@@ -978,13 +979,13 @@ static inline enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descript
 static inline void dma_issue_pending_all(void)
 {
 }
-static inline struct dma_chan *__dma_request_channel(dma_cap_mask_t *mask,
+static inline struct dma_chan *__dma_request_channel(const dma_cap_mask_t *mask,
 					      dma_filter_fn fn, void *fn_param)
 {
 	return NULL;
 }
 static inline struct dma_chan *dma_request_slave_channel(struct device *dev,
-							 char *name)
+							 const char *name)
 {
 	return NULL;
 }
@@ -1005,9 +1006,9 @@ struct dma_chan *net_dma_find_channel(void);
 	__dma_request_slave_channel_compat(&(mask), x, y, dev, name)
 
 static inline struct dma_chan
-*__dma_request_slave_channel_compat(dma_cap_mask_t *mask, dma_filter_fn fn,
-				  void *fn_param, struct device *dev,
-				  char *name)
+*__dma_request_slave_channel_compat(const dma_cap_mask_t *mask,
+				  dma_filter_fn fn, void *fn_param,
+				  struct device *dev, char *name)
 {
 	struct dma_chan *chan;
 
diff --git a/include/linux/drbd.h b/include/linux/drbd.h
index 0c5a18e..1b4d4ee 100644
--- a/include/linux/drbd.h
+++ b/include/linux/drbd.h
@@ -52,7 +52,7 @@
 #endif
 
 extern const char *drbd_buildtag(void);
-#define REL_VERSION "8.4.2"
+#define REL_VERSION "8.4.3"
 #define API_VERSION 1
 #define PRO_VERSION_MIN 86
 #define PRO_VERSION_MAX 101
@@ -319,7 +319,8 @@ enum drbd_state_rv {
 	SS_IN_TRANSIENT_STATE = -18,  /* Retry after the next state change */
 	SS_CONCURRENT_ST_CHG = -19,   /* Concurrent cluster side state change! */
 	SS_O_VOL_PEER_PRI = -20,
-	SS_AFTER_LAST_ERROR = -21,    /* Keep this at bottom */
+	SS_OUTDATE_WO_CONN = -21,
+	SS_AFTER_LAST_ERROR = -22,    /* Keep this at bottom */
 };
 
 /* from drbd_strings.c */
diff --git a/include/linux/drbd_limits.h b/include/linux/drbd_limits.h
index 1fa19c5..1fedf2b 100644
--- a/include/linux/drbd_limits.h
+++ b/include/linux/drbd_limits.h
@@ -126,13 +126,12 @@
 #define DRBD_RESYNC_RATE_DEF 250
 #define DRBD_RESYNC_RATE_SCALE 'k'  /* kilobytes */
 
-  /* less than 7 would hit performance unnecessarily.
-   * 919 slots context information per transaction,
-   * 32k activity log, 4k transaction size,
-   * one transaction in flight:
-   * 919 * 7 = 6433 */
+  /* less than 7 would hit performance unnecessarily. */
 #define DRBD_AL_EXTENTS_MIN  7
-#define DRBD_AL_EXTENTS_MAX  6433
+  /* we use u16 as "slot number", (u16)~0 is "FREE".
+   * If you use >= 292 kB on-disk ring buffer,
+   * this is the maximum you can use: */
+#define DRBD_AL_EXTENTS_MAX  0xfffe
 #define DRBD_AL_EXTENTS_DEF  1237
 #define DRBD_AL_EXTENTS_SCALE '1'
 
diff --git a/include/linux/errno.h b/include/linux/errno.h
index f6bf082..89627b9 100644
--- a/include/linux/errno.h
+++ b/include/linux/errno.h
@@ -28,6 +28,5 @@
 #define EBADTYPE	527	/* Type not supported by server */
 #define EJUKEBOX	528	/* Request initiated, but will not complete before timeout */
 #define EIOCBQUEUED	529	/* iocb queued, will get completion event */
-#define EIOCBRETRY	530	/* iocb queued, will trigger a retry */
 
 #endif
diff --git a/include/linux/evm.h b/include/linux/evm.h
index 9fc13a7..1fcb88c 100644
--- a/include/linux/evm.h
+++ b/include/linux/evm.h
@@ -96,5 +96,5 @@ static inline int evm_inode_init_security(struct inode *inode,
 	return 0;
 }
 
-#endif /* CONFIG_EVM_H */
+#endif /* CONFIG_EVM */
 #endif /* LINUX_EVM_H */
diff --git a/include/linux/export.h b/include/linux/export.h
index 696c0f4..412cd50 100644
--- a/include/linux/export.h
+++ b/include/linux/export.h
@@ -5,17 +5,24 @@
  * to reduce the amount of pointless cruft we feed to gcc when only
  * exporting a simple symbol or two.
  *
- * If you feel the need to add #include <linux/foo.h> to this file
- * then you are doing something wrong and should go away silently.
+ * Try not to add #includes here.  It slows compilation and makes kernel
+ * hackers place grumpy comments in header files.
  */
 
 /* Some toolchains use a `_' prefix for all user symbols. */
-#ifdef CONFIG_SYMBOL_PREFIX
-#define MODULE_SYMBOL_PREFIX CONFIG_SYMBOL_PREFIX
+#ifdef CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX
+#define __VMLINUX_SYMBOL(x) _##x
+#define __VMLINUX_SYMBOL_STR(x) "_" #x
 #else
-#define MODULE_SYMBOL_PREFIX ""
+#define __VMLINUX_SYMBOL(x) x
+#define __VMLINUX_SYMBOL_STR(x) #x
 #endif
 
+/* Indirect, so macros are expanded before pasting. */
+#define VMLINUX_SYMBOL(x) __VMLINUX_SYMBOL(x)
+#define VMLINUX_SYMBOL_STR(x) __VMLINUX_SYMBOL_STR(x)
+
+#ifndef __ASSEMBLY__
 struct kernel_symbol
 {
 	unsigned long value;
@@ -51,7 +58,7 @@ extern struct module __this_module;
 	__CRC_SYMBOL(sym, sec)					\
 	static const char __kstrtab_##sym[]			\
 	__attribute__((section("__ksymtab_strings"), aligned(1))) \
-	= MODULE_SYMBOL_PREFIX #sym;				\
+	= VMLINUX_SYMBOL_STR(sym);				\
 	static const struct kernel_symbol __ksymtab_##sym	\
 	__used							\
 	__attribute__((section("___ksymtab" sec "+" #sym), unused))	\
@@ -85,5 +92,6 @@ extern struct module __this_module;
 #define EXPORT_UNUSED_SYMBOL_GPL(sym)
 
 #endif /* CONFIG_MODULES */
+#endif /* !__ASSEMBLY__ */
 
 #endif /* _LINUX_EXPORT_H */
diff --git a/include/linux/exportfs.h b/include/linux/exportfs.h
index 5b9b5b3..41b223a 100644
--- a/include/linux/exportfs.h
+++ b/include/linux/exportfs.h
@@ -85,6 +85,17 @@ enum fid_type {
 	FILEID_NILFS_WITH_PARENT = 0x62,
 
 	/*
+	 * 32 bit generation number, 40 bit i_pos.
+	 */
+	FILEID_FAT_WITHOUT_PARENT = 0x71,
+
+	/*
+	 * 32 bit generation number, 40 bit i_pos,
+	 * 32 bit parent generation number, 40 bit parent i_pos
+	 */
+	FILEID_FAT_WITH_PARENT = 0x72,
+
+	/*
 	 * Filesystems must not use 0xff file ID.
 	 */
 	FILEID_INVALID = 0xff,
diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h
index f9a12f6..df6fab8 100644
--- a/include/linux/f2fs_fs.h
+++ b/include/linux/f2fs_fs.h
@@ -139,7 +139,7 @@ struct f2fs_extent {
 	__le32 len;		/* lengh of the extent */
 } __packed;
 
-#define F2FS_MAX_NAME_LEN	256
+#define F2FS_NAME_LEN		255
 #define ADDRS_PER_INODE         923	/* Address Pointers in an Inode */
 #define ADDRS_PER_BLOCK         1018	/* Address Pointers in a Direct Block */
 #define NIDS_PER_BLOCK          1018	/* Node IDs in an Indirect Block */
@@ -165,7 +165,8 @@ struct f2fs_inode {
 	__le32 i_flags;			/* file attributes */
 	__le32 i_pino;			/* parent inode number */
 	__le32 i_namelen;		/* file name length */
-	__u8 i_name[F2FS_MAX_NAME_LEN];	/* file name for SPOR */
+	__u8 i_name[F2FS_NAME_LEN];	/* file name for SPOR */
+	__u8 i_reserved2;		/* for backward compatibility */
 
 	struct f2fs_extent i_ext;	/* caching a largest extent */
 
@@ -362,10 +363,10 @@ struct f2fs_summary_block {
 typedef __le32	f2fs_hash_t;
 
 /* One directory entry slot covers 8bytes-long file name */
-#define F2FS_NAME_LEN		8
-#define F2FS_NAME_LEN_BITS	3
+#define F2FS_SLOT_LEN		8
+#define F2FS_SLOT_LEN_BITS	3
 
-#define GET_DENTRY_SLOTS(x)	((x + F2FS_NAME_LEN - 1) >> F2FS_NAME_LEN_BITS)
+#define GET_DENTRY_SLOTS(x)	((x + F2FS_SLOT_LEN - 1) >> F2FS_SLOT_LEN_BITS)
 
 /* the number of dentry in a block */
 #define NR_DENTRY_IN_BLOCK	214
@@ -377,10 +378,10 @@ typedef __le32	f2fs_hash_t;
 #define SIZE_OF_DENTRY_BITMAP	((NR_DENTRY_IN_BLOCK + BITS_PER_BYTE - 1) / \
 					BITS_PER_BYTE)
 #define SIZE_OF_RESERVED	(PAGE_SIZE - ((SIZE_OF_DIR_ENTRY + \
-				F2FS_NAME_LEN) * \
+				F2FS_SLOT_LEN) * \
 				NR_DENTRY_IN_BLOCK + SIZE_OF_DENTRY_BITMAP))
 
-/* One directory entry slot representing F2FS_NAME_LEN-sized file name */
+/* One directory entry slot representing F2FS_SLOT_LEN-sized file name */
 struct f2fs_dir_entry {
 	__le32 hash_code;	/* hash code of file name */
 	__le32 ino;		/* inode number */
@@ -394,7 +395,7 @@ struct f2fs_dentry_block {
 	__u8 dentry_bitmap[SIZE_OF_DENTRY_BITMAP];
 	__u8 reserved[SIZE_OF_RESERVED];
 	struct f2fs_dir_entry dentry[NR_DENTRY_IN_BLOCK];
-	__u8 filename[NR_DENTRY_IN_BLOCK][F2FS_NAME_LEN];
+	__u8 filename[NR_DENTRY_IN_BLOCK][F2FS_SLOT_LEN];
 } __packed;
 
 /* file types used in inode_info->flags */
diff --git a/include/linux/fb.h b/include/linux/fb.h
index 58b9860..d49c60f 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -501,6 +501,8 @@ struct fb_info {
 			resource_size_t size;
 		} ranges[0];
 	} *apertures;
+
+	bool skip_vt_switch; /* no VT switch on suspend/resume required */
 };
 
 static inline struct apertures_struct *alloc_apertures(unsigned int max_num) {
diff --git a/include/linux/filter.h b/include/linux/filter.h
index c45eabc..d1248f4 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -48,8 +48,21 @@ extern int sk_chk_filter(struct sock_filter *filter, unsigned int flen);
 extern int sk_get_filter(struct sock *sk, struct sock_filter __user *filter, unsigned len);
 
 #ifdef CONFIG_BPF_JIT
+#include <linux/linkage.h>
+#include <linux/printk.h>
+
 extern void bpf_jit_compile(struct sk_filter *fp);
 extern void bpf_jit_free(struct sk_filter *fp);
+
+static inline void bpf_jit_dump(unsigned int flen, unsigned int proglen,
+				u32 pass, void *image)
+{
+	pr_err("flen=%u proglen=%u pass=%u image=%p\n",
+	       flen, proglen, pass, image);
+	if (image)
+		print_hex_dump(KERN_ERR, "JIT code: ", DUMP_PREFIX_ADDRESS,
+			       16, 1, image, proglen, false);
+}
 #define SK_RUN_FILTER(FILTER, SKB) (*FILTER->bpf_func)(SKB, FILTER->insns)
 #else
 static inline void bpf_jit_compile(struct sk_filter *fp)
@@ -126,6 +139,7 @@ enum {
 	BPF_S_ANC_SECCOMP_LD_W,
 	BPF_S_ANC_VLAN_TAG,
 	BPF_S_ANC_VLAN_TAG_PRESENT,
+	BPF_S_ANC_PAY_OFFSET,
 };
 
 #endif /* __LINUX_FILTER_H__ */
diff --git a/include/linux/frontswap.h b/include/linux/frontswap.h
index 3044254..8293262 100644
--- a/include/linux/frontswap.h
+++ b/include/linux/frontswap.h
@@ -14,7 +14,7 @@ struct frontswap_ops {
 };
 
 extern bool frontswap_enabled;
-extern struct frontswap_ops
+extern struct frontswap_ops *
 	frontswap_register_ops(struct frontswap_ops *ops);
 extern void frontswap_shrink(unsigned long);
 extern unsigned long frontswap_curr_pages(void);
@@ -22,33 +22,19 @@ extern void frontswap_writethrough(bool);
 #define FRONTSWAP_HAS_EXCLUSIVE_GETS
 extern void frontswap_tmem_exclusive_gets(bool);
 
-extern void __frontswap_init(unsigned type);
+extern bool __frontswap_test(struct swap_info_struct *, pgoff_t);
+extern void __frontswap_init(unsigned type, unsigned long *map);
 extern int __frontswap_store(struct page *page);
 extern int __frontswap_load(struct page *page);
 extern void __frontswap_invalidate_page(unsigned, pgoff_t);
 extern void __frontswap_invalidate_area(unsigned);
 
 #ifdef CONFIG_FRONTSWAP
+#define frontswap_enabled (1)
 
 static inline bool frontswap_test(struct swap_info_struct *sis, pgoff_t offset)
 {
-	bool ret = false;
-
-	if (frontswap_enabled && sis->frontswap_map)
-		ret = test_bit(offset, sis->frontswap_map);
-	return ret;
-}
-
-static inline void frontswap_set(struct swap_info_struct *sis, pgoff_t offset)
-{
-	if (frontswap_enabled && sis->frontswap_map)
-		set_bit(offset, sis->frontswap_map);
-}
-
-static inline void frontswap_clear(struct swap_info_struct *sis, pgoff_t offset)
-{
-	if (frontswap_enabled && sis->frontswap_map)
-		clear_bit(offset, sis->frontswap_map);
+	return __frontswap_test(sis, offset);
 }
 
 static inline void frontswap_map_set(struct swap_info_struct *p,
@@ -71,14 +57,6 @@ static inline bool frontswap_test(struct swap_info_struct *sis, pgoff_t offset)
 	return false;
 }
 
-static inline void frontswap_set(struct swap_info_struct *sis, pgoff_t offset)
-{
-}
-
-static inline void frontswap_clear(struct swap_info_struct *sis, pgoff_t offset)
-{
-}
-
 static inline void frontswap_map_set(struct swap_info_struct *p,
 				     unsigned long *map)
 {
@@ -120,10 +98,10 @@ static inline void frontswap_invalidate_area(unsigned type)
 		__frontswap_invalidate_area(type);
 }
 
-static inline void frontswap_init(unsigned type)
+static inline void frontswap_init(unsigned type, unsigned long *map)
 {
 	if (frontswap_enabled)
-		__frontswap_init(type);
+		__frontswap_init(type, map);
 }
 
 #endif /* _LINUX_FRONTSWAP_H */
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 2c28271..8d47c9a 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -675,9 +675,11 @@ static inline loff_t i_size_read(const struct inode *inode)
 static inline void i_size_write(struct inode *inode, loff_t i_size)
 {
 #if BITS_PER_LONG==32 && defined(CONFIG_SMP)
+	preempt_disable();
 	write_seqcount_begin(&inode->i_size_seqcount);
 	inode->i_size = i_size;
 	write_seqcount_end(&inode->i_size_seqcount);
+	preempt_enable();
 #elif BITS_PER_LONG==32 && defined(CONFIG_PREEMPT)
 	preempt_disable();
 	inode->i_size = i_size;
@@ -2080,7 +2082,6 @@ extern int sync_filesystem(struct super_block *);
 extern const struct file_operations def_blk_fops;
 extern const struct file_operations def_chr_fops;
 extern const struct file_operations bad_sock_fops;
-extern const struct file_operations def_fifo_fops;
 #ifdef CONFIG_BLOCK
 extern int ioctl_by_bdev(struct block_device *, unsigned, unsigned long);
 extern int blkdev_ioctl(struct block_device *, fmode_t, unsigned, unsigned long);
@@ -2152,10 +2153,6 @@ extern void init_special_inode(struct inode *, umode_t, dev_t);
 extern void make_bad_inode(struct inode *);
 extern int is_bad_inode(struct inode *);
 
-extern const struct file_operations read_pipefifo_fops;
-extern const struct file_operations write_pipefifo_fops;
-extern const struct file_operations rdwr_pipefifo_fops;
-
 #ifdef CONFIG_BLOCK
 /*
  * return READ, READA, or WRITE
@@ -2223,6 +2220,20 @@ static inline struct inode *file_inode(struct file *f)
 	return f->f_inode;
 }
 
+static inline void file_start_write(struct file *file)
+{
+	if (!S_ISREG(file_inode(file)->i_mode))
+		return;
+	__sb_start_write(file_inode(file)->i_sb, SB_FREEZE_WRITE, true);
+}
+
+static inline void file_end_write(struct file *file)
+{
+	if (!S_ISREG(file_inode(file)->i_mode))
+		return;
+	__sb_end_write(file_inode(file)->i_sb, SB_FREEZE_WRITE);
+}
+
 /*
  * get_write_access() gets write permission for a file.
  * put_write_access() releases this write permission.
@@ -2435,7 +2446,7 @@ enum {
 	DIO_SKIP_HOLES	= 0x02,
 };
 
-void dio_end_io(struct bio *bio, int error);
+void dio_end_io(struct bio *bio, int error, struct batch_complete *batch);
 
 ssize_t __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
 	struct block_device *bdev, const struct iovec *iov, loff_t offset,
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
index e5ca8ef..832422d 100644
--- a/include/linux/ftrace.h
+++ b/include/linux/ftrace.h
@@ -259,8 +259,10 @@ struct ftrace_probe_ops {
 	void			(*func)(unsigned long ip,
 					unsigned long parent_ip,
 					void **data);
-	int			(*callback)(unsigned long ip, void **data);
-	void			(*free)(void **data);
+	int			(*init)(struct ftrace_probe_ops *ops,
+					unsigned long ip, void **data);
+	void			(*free)(struct ftrace_probe_ops *ops,
+					unsigned long ip, void **data);
 	int			(*print)(struct seq_file *m,
 					 unsigned long ip,
 					 struct ftrace_probe_ops *ops,
diff --git a/include/linux/ftrace_event.h b/include/linux/ftrace_event.h
index 13a54d0..4e28b01 100644
--- a/include/linux/ftrace_event.h
+++ b/include/linux/ftrace_event.h
@@ -8,6 +8,7 @@
 #include <linux/perf_event.h>
 
 struct trace_array;
+struct trace_buffer;
 struct tracer;
 struct dentry;
 
@@ -38,6 +39,12 @@ const char *ftrace_print_symbols_seq_u64(struct trace_seq *p,
 const char *ftrace_print_hex_seq(struct trace_seq *p,
 				 const unsigned char *buf, int len);
 
+struct trace_iterator;
+struct trace_event;
+
+int ftrace_raw_output_prep(struct trace_iterator *iter,
+			   struct trace_event *event);
+
 /*
  * The trace entry - the most basic unit of tracing. This is what
  * is printed in the end as a single line in the trace output, such as:
@@ -61,6 +68,7 @@ struct trace_entry {
 struct trace_iterator {
 	struct trace_array	*tr;
 	struct tracer		*trace;
+	struct trace_buffer	*trace_buffer;
 	void			*private;
 	int			cpu_file;
 	struct mutex		mutex;
@@ -95,8 +103,6 @@ enum trace_iter_flags {
 };
 
 
-struct trace_event;
-
 typedef enum print_line_t (*trace_print_func)(struct trace_iterator *iter,
 				      int flags, struct trace_event *event);
 
@@ -128,6 +134,13 @@ enum print_line_t {
 void tracing_generic_entry_update(struct trace_entry *entry,
 				  unsigned long flags,
 				  int pc);
+struct ftrace_event_file;
+
+struct ring_buffer_event *
+trace_event_buffer_lock_reserve(struct ring_buffer **current_buffer,
+				struct ftrace_event_file *ftrace_file,
+				int type, unsigned long len,
+				unsigned long flags, int pc);
 struct ring_buffer_event *
 trace_current_buffer_lock_reserve(struct ring_buffer **current_buffer,
 				  int type, unsigned long len,
@@ -182,53 +195,49 @@ extern int ftrace_event_reg(struct ftrace_event_call *event,
 			    enum trace_reg type, void *data);
 
 enum {
-	TRACE_EVENT_FL_ENABLED_BIT,
 	TRACE_EVENT_FL_FILTERED_BIT,
-	TRACE_EVENT_FL_RECORDED_CMD_BIT,
 	TRACE_EVENT_FL_CAP_ANY_BIT,
 	TRACE_EVENT_FL_NO_SET_FILTER_BIT,
 	TRACE_EVENT_FL_IGNORE_ENABLE_BIT,
+	TRACE_EVENT_FL_WAS_ENABLED_BIT,
 };
 
+/*
+ * Event flags:
+ *  FILTERED	  - The event has a filter attached
+ *  CAP_ANY	  - Any user can enable for perf
+ *  NO_SET_FILTER - Set when filter has error and is to be ignored
+ *  IGNORE_ENABLE - For ftrace internal events, do not enable with debugfs file
+ *  WAS_ENABLED   - Set and stays set when an event was ever enabled
+ *                    (used for module unloading, if a module event is enabled,
+ *                     it is best to clear the buffers that used it).
+ */
 enum {
-	TRACE_EVENT_FL_ENABLED		= (1 << TRACE_EVENT_FL_ENABLED_BIT),
 	TRACE_EVENT_FL_FILTERED		= (1 << TRACE_EVENT_FL_FILTERED_BIT),
-	TRACE_EVENT_FL_RECORDED_CMD	= (1 << TRACE_EVENT_FL_RECORDED_CMD_BIT),
 	TRACE_EVENT_FL_CAP_ANY		= (1 << TRACE_EVENT_FL_CAP_ANY_BIT),
 	TRACE_EVENT_FL_NO_SET_FILTER	= (1 << TRACE_EVENT_FL_NO_SET_FILTER_BIT),
 	TRACE_EVENT_FL_IGNORE_ENABLE	= (1 << TRACE_EVENT_FL_IGNORE_ENABLE_BIT),
+	TRACE_EVENT_FL_WAS_ENABLED	= (1 << TRACE_EVENT_FL_WAS_ENABLED_BIT),
 };
 
 struct ftrace_event_call {
 	struct list_head	list;
 	struct ftrace_event_class *class;
 	char			*name;
-	struct dentry		*dir;
 	struct trace_event	event;
 	const char		*print_fmt;
 	struct event_filter	*filter;
+	struct list_head	*files;
 	void			*mod;
 	void			*data;
-
 	/*
-	 * 32 bit flags:
-	 *   bit 1:		enabled
-	 *   bit 2:		filter_active
-	 *   bit 3:		enabled cmd record
-	 *   bit 4:		allow trace by non root (cap any)
-	 *   bit 5:		failed to apply filter
-	 *   bit 6:		ftrace internal event (do not enable)
-	 *
-	 * Changes to flags must hold the event_mutex.
-	 *
-	 * Note: Reads of flags do not hold the event_mutex since
-	 * they occur in critical sections. But the way flags
-	 * is currently used, these changes do no affect the code
-	 * except that when a change is made, it may have a slight
-	 * delay in propagating the changes to other CPUs due to
-	 * caching and such.
+	 *   bit 0:		filter_active
+	 *   bit 1:		allow trace by non root (cap any)
+	 *   bit 2:		failed to apply filter
+	 *   bit 3:		ftrace internal event (do not enable)
+	 *   bit 4:		Event was enabled by module
 	 */
-	unsigned int		flags;
+	int			flags; /* static flags of different events */
 
 #ifdef CONFIG_PERF_EVENTS
 	int				perf_refcount;
@@ -236,6 +245,56 @@ struct ftrace_event_call {
 #endif
 };
 
+struct trace_array;
+struct ftrace_subsystem_dir;
+
+enum {
+	FTRACE_EVENT_FL_ENABLED_BIT,
+	FTRACE_EVENT_FL_RECORDED_CMD_BIT,
+	FTRACE_EVENT_FL_SOFT_MODE_BIT,
+	FTRACE_EVENT_FL_SOFT_DISABLED_BIT,
+};
+
+/*
+ * Ftrace event file flags:
+ *  ENABLED	  - The event is enabled
+ *  RECORDED_CMD  - The comms should be recorded at sched_switch
+ *  SOFT_MODE     - The event is enabled/disabled by SOFT_DISABLED
+ *  SOFT_DISABLED - When set, do not trace the event (even though its
+ *                   tracepoint may be enabled)
+ */
+enum {
+	FTRACE_EVENT_FL_ENABLED		= (1 << FTRACE_EVENT_FL_ENABLED_BIT),
+	FTRACE_EVENT_FL_RECORDED_CMD	= (1 << FTRACE_EVENT_FL_RECORDED_CMD_BIT),
+	FTRACE_EVENT_FL_SOFT_MODE	= (1 << FTRACE_EVENT_FL_SOFT_MODE_BIT),
+	FTRACE_EVENT_FL_SOFT_DISABLED	= (1 << FTRACE_EVENT_FL_SOFT_DISABLED_BIT),
+};
+
+struct ftrace_event_file {
+	struct list_head		list;
+	struct ftrace_event_call	*event_call;
+	struct dentry			*dir;
+	struct trace_array		*tr;
+	struct ftrace_subsystem_dir	*system;
+
+	/*
+	 * 32 bit flags:
+	 *   bit 0:		enabled
+	 *   bit 1:		enabled cmd record
+	 *   bit 2:		enable/disable with the soft disable bit
+	 *   bit 3:		soft disabled
+	 *
+	 * Note: The bits must be set atomically to prevent races
+	 * from other writers. Reads of flags do not need to be in
+	 * sync as they occur in critical sections. But the way flags
+	 * is currently used, these changes do not affect the code
+	 * except that when a change is made, it may have a slight
+	 * delay in propagating the changes to other CPUs due to
+	 * caching and such. Which is mostly OK ;-)
+	 */
+	unsigned long		flags;
+};
+
 #define __TRACE_EVENT_FLAGS(name, value)				\
 	static int __init trace_init_flags_##name(void)			\
 	{								\
diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h
index c1d6555..f3cec68 100644
--- a/include/linux/hardirq.h
+++ b/include/linux/hardirq.h
@@ -94,6 +94,11 @@
  */
 #define in_nmi()	(preempt_count() & NMI_MASK)
 
+/*
+ * Are we in nmi,irq context, or softirq context?
+ */
+#define in_serving_irq() (in_nmi() || in_irq() || in_serving_softirq())
+
 #if defined(CONFIG_PREEMPT_COUNT)
 # define PREEMPT_CHECK_OFFSET 1
 #else
diff --git a/include/linux/hid.h b/include/linux/hid.h
index e14b465..b7b5ff2 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -282,6 +282,7 @@ struct hid_item {
 #define HID_QUIRK_BADPAD			0x00000020
 #define HID_QUIRK_MULTI_INPUT			0x00000040
 #define HID_QUIRK_HIDINPUT_FORCE		0x00000080
+#define HID_QUIRK_NO_EMPTY_INPUT		0x00000100
 #define HID_QUIRK_SKIP_OUTPUT_REPORTS		0x00010000
 #define HID_QUIRK_FULLSPEED_INTERVAL		0x10000000
 #define HID_QUIRK_NO_INIT_REPORTS		0x20000000
@@ -456,7 +457,8 @@ struct hid_device {							/* device report descriptor */
 	unsigned country;						/* HID country */
 	struct hid_report_enum report_enum[HID_REPORT_TYPES];
 
-	struct semaphore driver_lock;					/* protects the current driver */
+	struct semaphore driver_lock;					/* protects the current driver, except during input */
+	struct semaphore driver_input_lock;				/* protects the current driver */
 	struct device dev;						/* device */
 	struct hid_driver *driver;
 	struct hid_ll_driver *ll_driver;
@@ -477,6 +479,7 @@ struct hid_device {							/* device report descriptor */
 	unsigned int status;						/* see STAT flags above */
 	unsigned claimed;						/* Claimed by hidinput, hiddev? */
 	unsigned quirks;						/* Various quirks the device can pull on us */
+	bool io_started;						/* Protected by driver_lock. If IO has started */
 
 	struct list_head inputs;					/* The list of inputs */
 	void *hiddev;							/* The hiddev structure */
@@ -599,6 +602,10 @@ struct hid_usage_id {
  * @resume: invoked on resume if device was not reset (NULL means nop)
  * @reset_resume: invoked on resume if device was reset (NULL means nop)
  *
+ * probe should return -errno on error, or 0 on success. During probe,
+ * input will not be passed to raw_event unless hid_device_io_start is
+ * called.
+ *
  * raw_event and event should return 0 on no action performed, 1 when no
  * further processing should be done and negative on error
  *
@@ -662,6 +669,9 @@ struct hid_driver {
  * @hidinput_input_event: event input event (e.g. ff or leds)
  * @parse: this method is called only once to parse the device data,
  *	   shouldn't allocate anything to not leak memory
+ * @request: send report request to device (e.g. feature report)
+ * @wait: wait for buffered io to complete (send/recv reports)
+ * @idle: send idle request to device
  */
 struct hid_ll_driver {
 	int (*start)(struct hid_device *hdev);
@@ -676,6 +686,13 @@ struct hid_ll_driver {
 			unsigned int code, int value);
 
 	int (*parse)(struct hid_device *hdev);
+
+	void (*request)(struct hid_device *hdev,
+			struct hid_report *report, int reqtype);
+
+	int (*wait)(struct hid_device *hdev);
+	int (*idle)(struct hid_device *hdev, int report, int idle, int reqtype);
+
 };
 
 #define	PM_HINT_FULLON	1<<5
@@ -738,6 +755,44 @@ const struct hid_device_id *hid_match_id(struct hid_device *hdev,
 s32 hid_snto32(__u32 value, unsigned n);
 
 /**
+ * hid_device_io_start - enable HID input during probe, remove
+ *
+ * @hid - the device
+ *
+ * This should only be called during probe or remove and only be
+ * called by the thread calling probe or remove. It will allow
+ * incoming packets to be delivered to the driver.
+ */
+static inline void hid_device_io_start(struct hid_device *hid) {
+	if (hid->io_started) {
+		dev_warn(&hid->dev, "io already started");
+		return;
+	}
+	hid->io_started = true;
+	up(&hid->driver_input_lock);
+}
+
+/**
+ * hid_device_io_stop - disable HID input during probe, remove
+ *
+ * @hid - the device
+ *
+ * Should only be called after hid_device_io_start. It will prevent
+ * incoming packets from going to the driver for the duration of
+ * probe, remove. If called during probe, packets will still go to the
+ * driver after probe is complete. This function should only be called
+ * by the thread calling probe or remove.
+ */
+static inline void hid_device_io_stop(struct hid_device *hid) {
+	if (!hid->io_started) {
+		dev_warn(&hid->dev, "io already stopped");
+		return;
+	}
+	hid->io_started = false;
+	down(&hid->driver_input_lock);
+}
+
+/**
  * hid_map_usage - map usage input bits
  *
  * @hidinput: hidinput which we are interested in
@@ -883,6 +938,49 @@ static inline int hid_hw_power(struct hid_device *hdev, int level)
 	return hdev->ll_driver->power ? hdev->ll_driver->power(hdev, level) : 0;
 }
 
+
+/**
+ * hid_hw_request - send report request to device
+ *
+ * @hdev: hid device
+ * @report: report to send
+ * @reqtype: hid request type
+ */
+static inline void hid_hw_request(struct hid_device *hdev,
+				  struct hid_report *report, int reqtype)
+{
+	if (hdev->ll_driver->request)
+		hdev->ll_driver->request(hdev, report, reqtype);
+}
+
+/**
+ * hid_hw_idle - send idle request to device
+ *
+ * @hdev: hid device
+ * @report: report to control
+ * @idle: idle state
+ * @reqtype: hid request type
+ */
+static inline int hid_hw_idle(struct hid_device *hdev, int report, int idle,
+		int reqtype)
+{
+	if (hdev->ll_driver->idle)
+		return hdev->ll_driver->idle(hdev, report, idle, reqtype);
+
+	return 0;
+}
+
+/**
+ * hid_hw_wait - wait for buffered io to complete
+ *
+ * @hdev: hid device
+ */
+static inline void hid_hw_wait(struct hid_device *hdev)
+{
+	if (hdev->ll_driver->wait)
+		hdev->ll_driver->wait(hdev);
+}
+
 int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size,
 		int interrupt);
 
diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h
index 16e4e9a..3a62df3 100644
--- a/include/linux/hugetlb.h
+++ b/include/linux/hugetlb.h
@@ -58,6 +58,7 @@ void __unmap_hugepage_range(struct mmu_gather *tlb, struct vm_area_struct *vma,
 int hugetlb_prefault(struct address_space *, struct vm_area_struct *);
 void hugetlb_report_meminfo(struct seq_file *);
 int hugetlb_report_node_meminfo(int, char *);
+void hugetlb_show_meminfo(void);
 unsigned long hugetlb_total_pages(void);
 int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,
 			unsigned long address, unsigned int flags);
@@ -114,6 +115,9 @@ static inline void hugetlb_report_meminfo(struct seq_file *m)
 {
 }
 #define hugetlb_report_node_meminfo(n, buf)	0
+static inline void hugetlb_show_meminfo(void)
+{
+}
 #define follow_huge_pmd(mm, addr, pmd, write)	NULL
 #define follow_huge_pud(mm, addr, pud, write)	NULL
 #define prepare_hugepage_range(file, addr, len)	(-EINVAL)
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
index df77ba9..c255984 100644
--- a/include/linux/hyperv.h
+++ b/include/linux/hyperv.h
@@ -27,6 +27,63 @@
 
 #include <linux/types.h>
 
+
+/*
+ * Implementation of host controlled snapshot of the guest.
+ */
+
+#define VSS_OP_REGISTER 128
+
+enum hv_vss_op {
+	VSS_OP_CREATE = 0,
+	VSS_OP_DELETE,
+	VSS_OP_HOT_BACKUP,
+	VSS_OP_GET_DM_INFO,
+	VSS_OP_BU_COMPLETE,
+	/*
+	 * Following operations are only supported with IC version >= 5.0
+	 */
+	VSS_OP_FREEZE, /* Freeze the file systems in the VM */
+	VSS_OP_THAW, /* Unfreeze the file systems */
+	VSS_OP_AUTO_RECOVER,
+	VSS_OP_COUNT /* Number of operations, must be last */
+};
+
+
+/*
+ * Header for all VSS messages.
+ */
+struct hv_vss_hdr {
+	__u8 operation;
+	__u8 reserved[7];
+} __attribute__((packed));
+
+
+/*
+ * Flag values for the hv_vss_check_feature. Linux supports only
+ * one value.
+ */
+#define VSS_HBU_NO_AUTO_RECOVERY	0x00000005
+
+struct hv_vss_check_feature {
+	__u32 flags;
+} __attribute__((packed));
+
+struct hv_vss_check_dm_info {
+	__u32 flags;
+} __attribute__((packed));
+
+struct hv_vss_msg {
+	union {
+		struct hv_vss_hdr vss_hdr;
+		int error;
+	};
+	union {
+		struct hv_vss_check_feature vss_cf;
+		struct hv_vss_check_dm_info dm_info;
+	};
+} __attribute__((packed));
+
 /*
  * An implementation of HyperV key value pair (KVP) functionality for Linux.
  *
@@ -1253,6 +1310,25 @@ void vmbus_driver_unregister(struct hv_driver *hv_driver);
 		}
 
 /*
+ * VSS (Backup/Restore) GUID
+ */
+#define HV_VSS_GUID \
+	.guid = { \
+			0x29, 0x2e, 0xfa, 0x35, 0x23, 0xea, 0x36, 0x42, \
+			0x96, 0xae, 0x3a, 0x6e, 0xba, 0xcb, 0xa4,  0x40 \
+		}
+/*
+ * Synthetic Video GUID
+ * {DA0A7802-E377-4aac-8E77-0558EB1073F8}
+ */
+#define HV_SYNTHVID_GUID \
+	.guid = { \
+			0x02, 0x78, 0x0a, 0xda, 0x77, 0xe3, 0xac, 0x4a, \
+			0x8e, 0x77, 0x05, 0x58, 0xeb, 0x10, 0x73, 0xf8 \
+		}
+
+
+/*
  * Common header for Hyper-V ICs
  */
 
@@ -1356,6 +1432,10 @@ int hv_kvp_init(struct hv_util_service *);
 void hv_kvp_deinit(void);
 void hv_kvp_onchannelcallback(void *);
 
+int hv_vss_init(struct hv_util_service *);
+void hv_vss_deinit(void);
+void hv_vss_onchannelcallback(void *);
+
 /*
  * Negotiated version with the Host.
  */
diff --git a/include/linux/i2c-mux.h b/include/linux/i2c-mux.h
index 40cb05a..b5f9a00 100644
--- a/include/linux/i2c-mux.h
+++ b/include/linux/i2c-mux.h
@@ -42,7 +42,7 @@ struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent,
 				int (*deselect) (struct i2c_adapter *,
 						 void *mux_dev, u32 chan_id));
 
-int i2c_del_mux_adapter(struct i2c_adapter *adap);
+void i2c_del_mux_adapter(struct i2c_adapter *adap);
 
 #endif /* __KERNEL__ */
 
diff --git a/include/linux/i2c-tegra.h b/include/linux/i2c-tegra.h
deleted file mode 100644
index 9c85da4..0000000
--- a/include/linux/i2c-tegra.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * drivers/i2c/busses/i2c-tegra.c
- *
- * Copyright (C) 2010 Google, Inc.
- * Author: Colin Cross <ccross@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.
- *
- */
-
-#ifndef _LINUX_I2C_TEGRA_H
-#define _LINUX_I2C_TEGRA_H
-
-struct tegra_i2c_platform_data {
-	unsigned long bus_clk_rate;
-};
-
-#endif /* _LINUX_I2C_TEGRA_H */
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index d0c4db7..e988fa9 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -125,7 +125,6 @@ extern s32 i2c_smbus_write_i2c_block_data(const struct i2c_client *client,
  * struct i2c_driver - represent an I2C device driver
  * @class: What kind of i2c device we instantiate (for detect)
  * @attach_adapter: Callback for bus addition (deprecated)
- * @detach_adapter: Callback for bus removal (deprecated)
  * @probe: Callback for device binding
  * @remove: Callback for device unbinding
  * @shutdown: Callback for device shutdown
@@ -162,12 +161,10 @@ extern s32 i2c_smbus_write_i2c_block_data(const struct i2c_client *client,
 struct i2c_driver {
 	unsigned int class;
 
-	/* Notifies the driver that a new bus has appeared or is about to be
-	 * removed. You should avoid using this, it will be removed in a
-	 * near future.
+	/* Notifies the driver that a new bus has appeared. You should avoid
+	 * using this, it will be removed in a near future.
 	 */
 	int (*attach_adapter)(struct i2c_adapter *) __deprecated;
-	int (*detach_adapter)(struct i2c_adapter *) __deprecated;
 
 	/* Standard driver model interfaces */
 	int (*probe)(struct i2c_client *, const struct i2c_device_id *);
@@ -370,6 +367,45 @@ struct i2c_algorithm {
 	u32 (*functionality) (struct i2c_adapter *);
 };
 
+/**
+ * struct i2c_bus_recovery_info - I2C bus recovery information
+ * @recover_bus: Recover routine. Either pass driver's recover_bus() routine, or
+ *	i2c_generic_scl_recovery() or i2c_generic_gpio_recovery().
+ * @get_scl: This gets current value of SCL line. Mandatory for generic SCL
+ *      recovery. Used internally for generic GPIO recovery.
+ * @set_scl: This sets/clears SCL line. Mandatory for generic SCL recovery. Used
+ *      internally for generic GPIO recovery.
+ * @get_sda: This gets current value of SDA line. Optional for generic SCL
+ *      recovery. Used internally, if sda_gpio is a valid GPIO, for generic GPIO
+ *      recovery.
+ * @prepare_recovery: This will be called before starting recovery. Platform may
+ *	configure padmux here for SDA/SCL line or something else they want.
+ * @unprepare_recovery: This will be called after completing recovery. Platform
+ *	may configure padmux here for SDA/SCL line or something else they want.
+ * @scl_gpio: gpio number of the SCL line. Only required for GPIO recovery.
+ * @sda_gpio: gpio number of the SDA line. Only required for GPIO recovery.
+ */
+struct i2c_bus_recovery_info {
+	int (*recover_bus)(struct i2c_adapter *);
+
+	int (*get_scl)(struct i2c_adapter *);
+	void (*set_scl)(struct i2c_adapter *, int val);
+	int (*get_sda)(struct i2c_adapter *);
+
+	void (*prepare_recovery)(struct i2c_bus_recovery_info *bri);
+	void (*unprepare_recovery)(struct i2c_bus_recovery_info *bri);
+
+	/* gpio recovery */
+	int scl_gpio;
+	int sda_gpio;
+};
+
+int i2c_recover_bus(struct i2c_adapter *adap);
+
+/* Generic recovery routines */
+int i2c_generic_gpio_recovery(struct i2c_adapter *adap);
+int i2c_generic_scl_recovery(struct i2c_adapter *adap);
+
 /*
  * i2c_adapter is the structure used to identify a physical i2c bus along
  * with the access algorithms necessary to access it.
@@ -393,6 +429,8 @@ struct i2c_adapter {
 
 	struct mutex userspace_clients_lock;
 	struct list_head userspace_clients;
+
+	struct i2c_bus_recovery_info *bus_recovery_info;
 };
 #define to_i2c_adapter(d) container_of(d, struct i2c_adapter, dev)
 
@@ -450,7 +488,7 @@ void i2c_unlock_adapter(struct i2c_adapter *);
  */
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 extern int i2c_add_adapter(struct i2c_adapter *);
-extern int i2c_del_adapter(struct i2c_adapter *);
+extern void i2c_del_adapter(struct i2c_adapter *);
 extern int i2c_add_numbered_adapter(struct i2c_adapter *);
 
 extern int i2c_register_driver(struct module *, struct i2c_driver *);
diff --git a/include/linux/idr.h b/include/linux/idr.h
index 2640c7e..6ece058 100644
--- a/include/linux/idr.h
+++ b/include/linux/idr.h
@@ -122,11 +122,13 @@ static inline void *idr_find(struct idr *idr, int id)
  * @idp:     idr handle
  * @entry:   the type * to use as cursor
  * @id:      id entry's key
+ *
+ * @entry and @id do not need to be initialized before the loop, and
+ * after normal terminatinon @entry is left with the value NULL.  This
+ * is convenient for a "not found" value.
  */
-#define idr_for_each_entry(idp, entry, id)				\
-	for (id = 0, entry = (typeof(entry))idr_get_next((idp), &(id)); \
-	     entry != NULL;                                             \
-	     ++id, entry = (typeof(entry))idr_get_next((idp), &(id)))
+#define idr_for_each_entry(idp, entry, id)			\
+	for (id = 0; ((entry) = idr_get_next(idp, &(id))) != NULL; ++id)
 
 /*
  * Don't use the following functions.  These exist only to suppress
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 7e24fe0..4cf0c9e 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -113,6 +113,34 @@
 #define IEEE80211_CTL_EXT_SSW_FBACK	0x9000
 #define IEEE80211_CTL_EXT_SSW_ACK	0xa000
 
+
+#define IEEE80211_SN_MASK		((IEEE80211_SCTL_SEQ) >> 4)
+#define IEEE80211_MAX_SN		IEEE80211_SN_MASK
+#define IEEE80211_SN_MODULO		(IEEE80211_MAX_SN + 1)
+
+static inline int ieee80211_sn_less(u16 sn1, u16 sn2)
+{
+	return ((sn1 - sn2) & IEEE80211_SN_MASK) > (IEEE80211_SN_MODULO >> 1);
+}
+
+static inline u16 ieee80211_sn_add(u16 sn1, u16 sn2)
+{
+	return (sn1 + sn2) & IEEE80211_SN_MASK;
+}
+
+static inline u16 ieee80211_sn_inc(u16 sn)
+{
+	return ieee80211_sn_add(sn, 1);
+}
+
+static inline u16 ieee80211_sn_sub(u16 sn1, u16 sn2)
+{
+	return (sn1 - sn2) & IEEE80211_SN_MASK;
+}
+
+#define IEEE80211_SEQ_TO_SN(seq)	(((seq) & IEEE80211_SCTL_SEQ) >> 4)
+#define IEEE80211_SN_TO_SEQ(ssn)	(((ssn) << 4) & IEEE80211_SCTL_SEQ)
+
 /* miscellaneous IEEE 802.11 constants */
 #define IEEE80211_MAX_FRAG_THRESHOLD	2352
 #define IEEE80211_MAX_RTS_THRESHOLD	2353
@@ -185,7 +213,7 @@ struct ieee80211_hdr {
 	u8 addr3[6];
 	__le16 seq_ctrl;
 	u8 addr4[6];
-} __packed;
+} __packed __aligned(2);
 
 struct ieee80211_hdr_3addr {
 	__le16 frame_control;
@@ -194,7 +222,7 @@ struct ieee80211_hdr_3addr {
 	u8 addr2[6];
 	u8 addr3[6];
 	__le16 seq_ctrl;
-} __packed;
+} __packed __aligned(2);
 
 struct ieee80211_qos_hdr {
 	__le16 frame_control;
@@ -204,7 +232,7 @@ struct ieee80211_qos_hdr {
 	u8 addr3[6];
 	__le16 seq_ctrl;
 	__le16 qos_ctrl;
-} __packed;
+} __packed __aligned(2);
 
 /**
  * ieee80211_has_tods - check if IEEE80211_FCTL_TODS is set
@@ -581,7 +609,7 @@ struct ieee80211s_hdr {
 	__le32 seqnum;
 	u8 eaddr1[6];
 	u8 eaddr2[6];
-} __packed;
+} __packed __aligned(2);
 
 /* Mesh flags */
 #define MESH_FLAGS_AE_A4 	0x1
@@ -875,7 +903,7 @@ struct ieee80211_mgmt {
 			} u;
 		} __packed action;
 	} u;
-} __packed;
+} __packed __aligned(2);
 
 /* Supported Rates value encodings in 802.11n-2009 7.3.2.2 */
 #define BSS_MEMBERSHIP_SELECTOR_HT_PHY	127
@@ -906,20 +934,20 @@ struct ieee80211_rts {
 	__le16 duration;
 	u8 ra[6];
 	u8 ta[6];
-} __packed;
+} __packed __aligned(2);
 
 struct ieee80211_cts {
 	__le16 frame_control;
 	__le16 duration;
 	u8 ra[6];
-} __packed;
+} __packed __aligned(2);
 
 struct ieee80211_pspoll {
 	__le16 frame_control;
 	__le16 aid;
 	u8 bssid[6];
 	u8 ta[6];
-} __packed;
+} __packed __aligned(2);
 
 /* TDLS */
 
@@ -1290,11 +1318,6 @@ struct ieee80211_vht_operation {
 } __packed;
 
 
-#define IEEE80211_VHT_MCS_ZERO_TO_SEVEN_SUPPORT 0
-#define IEEE80211_VHT_MCS_ZERO_TO_EIGHT_SUPPORT 1
-#define IEEE80211_VHT_MCS_ZERO_TO_NINE_SUPPORT  2
-#define IEEE80211_VHT_MCS_NOT_SUPPORTED 3
-
 /* 802.11ac VHT Capabilities */
 #define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895			0x00000000
 #define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991			0x00000001
@@ -1310,10 +1333,11 @@ struct ieee80211_vht_operation {
 #define IEEE80211_VHT_CAP_RXSTBC_2				0x00000200
 #define IEEE80211_VHT_CAP_RXSTBC_3				0x00000300
 #define IEEE80211_VHT_CAP_RXSTBC_4				0x00000400
+#define IEEE80211_VHT_CAP_RXSTBC_MASK				0x00000700
 #define IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE			0x00000800
 #define IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE			0x00001000
 #define IEEE80211_VHT_CAP_BEAMFORMER_ANTENNAS_MAX		0x00006000
-#define IEEE80211_VHT_CAP_SOUNDING_DIMENTION_MAX		0x00030000
+#define IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MAX		0x00030000
 #define IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE			0x00080000
 #define IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE			0x00100000
 #define IEEE80211_VHT_CAP_VHT_TXOP_PS				0x00200000
diff --git a/include/linux/if_arp.h b/include/linux/if_arp.h
index 89b4614..f563907 100644
--- a/include/linux/if_arp.h
+++ b/include/linux/if_arp.h
@@ -33,7 +33,15 @@ static inline struct arphdr *arp_hdr(const struct sk_buff *skb)
 
 static inline int arp_hdr_len(struct net_device *dev)
 {
-	/* ARP header, plus 2 device addresses, plus 2 IP addresses. */
-	return sizeof(struct arphdr) + (dev->addr_len + sizeof(u32)) * 2;
+	switch (dev->type) {
+#if IS_ENABLED(CONFIG_FIREWIRE_NET)
+	case ARPHRD_IEEE1394:
+		/* ARP header, device address and 2 IP addresses */
+		return sizeof(struct arphdr) + dev->addr_len + sizeof(u32) * 2;
+#endif
+	default:
+		/* ARP header, plus 2 device addresses, plus 2 IP addresses. */
+		return sizeof(struct arphdr) + (dev->addr_len + sizeof(u32)) * 2;
+	}
 }
 #endif	/* _LINUX_IF_ARP_H */
diff --git a/include/linux/if_team.h b/include/linux/if_team.h
index cfd21e3..4474557 100644
--- a/include/linux/if_team.h
+++ b/include/linux/if_team.h
@@ -112,6 +112,10 @@ struct team_mode_ops {
 	void (*port_disabled)(struct team *team, struct team_port *port);
 };
 
+extern int team_modeop_port_enter(struct team *team, struct team_port *port);
+extern void team_modeop_port_change_dev_addr(struct team *team,
+					     struct team_port *port);
+
 enum team_option_type {
 	TEAM_OPTION_TYPE_U32,
 	TEAM_OPTION_TYPE_STRING,
@@ -236,7 +240,26 @@ static inline struct team_port *team_get_port_by_index_rcu(struct team *team,
 	return NULL;
 }
 
-extern int team_port_set_team_dev_addr(struct team_port *port);
+static inline struct team_port *
+team_get_first_port_txable_rcu(struct team *team, struct team_port *port)
+{
+	struct team_port *cur;
+
+	if (likely(team_port_txable(port)))
+		return port;
+	cur = port;
+	list_for_each_entry_continue_rcu(cur, &team->port_list, list)
+		if (team_port_txable(port))
+			return cur;
+	list_for_each_entry_rcu(cur, &team->port_list, list) {
+		if (cur == port)
+			break;
+		if (team_port_txable(port))
+			return cur;
+	}
+	return NULL;
+}
+
 extern int team_options_register(struct team *team,
 				 const struct team_option *option,
 				 size_t option_count);
diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
index 218a3b6..70962f3 100644
--- a/include/linux/if_vlan.h
+++ b/include/linux/if_vlan.h
@@ -339,7 +339,7 @@ static inline void vlan_set_encap_proto(struct sk_buff *skb,
 	 */
 
 	proto = vhdr->h_vlan_encapsulated_proto;
-	if (ntohs(proto) >= 1536) {
+	if (ntohs(proto) >= ETH_P_802_3_MIN) {
 		skb->protocol = proto;
 		return;
 	}
diff --git a/include/linux/iio/adc/ad_sigma_delta.h b/include/linux/iio/adc/ad_sigma_delta.h
index 2e4eab9..e7fdec4 100644
--- a/include/linux/iio/adc/ad_sigma_delta.h
+++ b/include/linux/iio/adc/ad_sigma_delta.h
@@ -133,9 +133,9 @@ int ad_sd_validate_trigger(struct iio_dev *indio_dev, struct iio_trigger *trig);
 		.channel2 = (_channel2), \
 		.address = (_address), \
 		.extend_name = (_extend_name), \
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
-			IIO_CHAN_INFO_SCALE_SHARED_BIT | \
-			IIO_CHAN_INFO_OFFSET_SEPARATE_BIT, \
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+			BIT(IIO_CHAN_INFO_OFFSET), \
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
 		.scan_index = (_si), \
 		.scan_type = { \
 			.sign = 'u', \
diff --git a/include/linux/iio/common/st_sensors.h b/include/linux/iio/common/st_sensors.h
index 8bd12be..172c5b2 100644
--- a/include/linux/iio/common/st_sensors.h
+++ b/include/linux/iio/common/st_sensors.h
@@ -15,6 +15,7 @@
 #include <linux/spi/spi.h>
 #include <linux/irqreturn.h>
 #include <linux/iio/trigger.h>
+#include <linux/bitops.h>
 
 #define ST_SENSORS_TX_MAX_LENGTH		2
 #define ST_SENSORS_RX_MAX_LENGTH		6
@@ -45,8 +46,8 @@
 { \
 	.type = device_type, \
 	.modified = 1, \
-	.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
-			IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+			BIT(IIO_CHAN_INFO_SCALE), \
 	.scan_index = index, \
 	.channel2 = mod, \
 	.address = addr, \
diff --git a/include/linux/iio/gyro/itg3200.h b/include/linux/iio/gyro/itg3200.h
index c53f169..2a82085 100644
--- a/include/linux/iio/gyro/itg3200.h
+++ b/include/linux/iio/gyro/itg3200.h
@@ -149,6 +149,6 @@ static inline void itg3200_buffer_unconfigure(struct iio_dev *indio_dev)
 {
 }
 
-#endif  /* CONFIG_IIO_RING_BUFFER */
+#endif  /* CONFIG_IIO_BUFFER */
 
 #endif /* ITG3200_H_ */
diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h
index da8c776..8d171f4 100644
--- a/include/linux/iio/iio.h
+++ b/include/linux/iio/iio.h
@@ -38,76 +38,6 @@ enum iio_chan_info_enum {
 	IIO_CHAN_INFO_HYSTERESIS,
 };
 
-#define IIO_CHAN_INFO_SHARED_BIT(type) BIT(type*2)
-#define IIO_CHAN_INFO_SEPARATE_BIT(type) BIT(type*2 + 1)
-#define IIO_CHAN_INFO_BITS(type) (IIO_CHAN_INFO_SHARED_BIT(type) | \
-				    IIO_CHAN_INFO_SEPARATE_BIT(type))
-
-#define IIO_CHAN_INFO_RAW_SEPARATE_BIT			\
-	IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_RAW)
-#define IIO_CHAN_INFO_PROCESSED_SEPARATE_BIT			\
-	IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_PROCESSED)
-#define IIO_CHAN_INFO_SCALE_SEPARATE_BIT		\
-	IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_SCALE)
-#define IIO_CHAN_INFO_SCALE_SHARED_BIT			\
-	IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_SCALE)
-#define IIO_CHAN_INFO_OFFSET_SEPARATE_BIT			\
-	IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_OFFSET)
-#define IIO_CHAN_INFO_OFFSET_SHARED_BIT			\
-	IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_OFFSET)
-#define IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT			\
-	IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_CALIBSCALE)
-#define IIO_CHAN_INFO_CALIBSCALE_SHARED_BIT			\
-	IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_CALIBSCALE)
-#define IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT			\
-	IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_CALIBBIAS)
-#define IIO_CHAN_INFO_CALIBBIAS_SHARED_BIT			\
-	IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_CALIBBIAS)
-#define IIO_CHAN_INFO_PEAK_SEPARATE_BIT			\
-	IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_PEAK)
-#define IIO_CHAN_INFO_PEAK_SHARED_BIT			\
-	IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_PEAK)
-#define IIO_CHAN_INFO_PEAKSCALE_SEPARATE_BIT			\
-	IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_PEAKSCALE)
-#define IIO_CHAN_INFO_PEAKSCALE_SHARED_BIT			\
-	IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_PEAKSCALE)
-#define IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SEPARATE_BIT	\
-	IIO_CHAN_INFO_SEPARATE_BIT(				\
-		IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW)
-#define IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SHARED_BIT	\
-	IIO_CHAN_INFO_SHARED_BIT(				\
-		IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW)
-#define IIO_CHAN_INFO_AVERAGE_RAW_SEPARATE_BIT			\
-	IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_AVERAGE_RAW)
-#define IIO_CHAN_INFO_AVERAGE_RAW_SHARED_BIT			\
-	IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_AVERAGE_RAW)
-#define IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT \
-	IIO_CHAN_INFO_SHARED_BIT(			       \
-		IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY)
-#define IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SEPARATE_BIT \
-	IIO_CHAN_INFO_SEPARATE_BIT(			       \
-		IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY)
-#define IIO_CHAN_INFO_SAMP_FREQ_SEPARATE_BIT		\
-	IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_SAMP_FREQ)
-#define IIO_CHAN_INFO_SAMP_FREQ_SHARED_BIT			\
-	IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_SAMP_FREQ)
-#define IIO_CHAN_INFO_FREQUENCY_SEPARATE_BIT			\
-	IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_FREQUENCY)
-#define IIO_CHAN_INFO_FREQUENCY_SHARED_BIT			\
-	IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_FREQUENCY)
-#define IIO_CHAN_INFO_PHASE_SEPARATE_BIT			\
-	IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_PHASE)
-#define IIO_CHAN_INFO_PHASE_SHARED_BIT			\
-	IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_PHASE)
-#define IIO_CHAN_INFO_HARDWAREGAIN_SEPARATE_BIT			\
-	IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_HARDWAREGAIN)
-#define IIO_CHAN_INFO_HARDWAREGAIN_SHARED_BIT			\
-	IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_HARDWAREGAIN)
-#define IIO_CHAN_INFO_HYSTERESIS_SEPARATE_BIT			\
-	IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_HYSTERESIS)
-#define IIO_CHAN_INFO_HYSTERESIS_SHARED_BIT			\
-	IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_HYSTERESIS)
-
 enum iio_endian {
 	IIO_CPU,
 	IIO_BE,
@@ -218,6 +148,10 @@ ssize_t iio_enum_write(struct iio_dev *indio_dev,
  *			endianness:	little or big endian
  * @info_mask:		What information is to be exported about this channel.
  *			This includes calibbias, scale etc.
+ * @info_mask_separate: What information is to be exported that is specific to
+ *			this channel.
+ * @info_mask_shared_by_type: What information is to be exported that is shared
+*			by all channels of the same type.
  * @event_mask:		What events can this channel produce.
  * @ext_info:		Array of extended info attributes for this channel.
  *			The array is NULL terminated, the last element should
@@ -253,6 +187,8 @@ struct iio_chan_spec {
 		enum iio_endian endianness;
 	} scan_type;
 	long			info_mask;
+	long			info_mask_separate;
+	long			info_mask_shared_by_type;
 	long			event_mask;
 	const struct iio_chan_spec_ext_info *ext_info;
 	const char		*extend_name;
@@ -275,7 +211,8 @@ struct iio_chan_spec {
 static inline bool iio_channel_has_info(const struct iio_chan_spec *chan,
 	enum iio_chan_info_enum type)
 {
-	return chan->info_mask & IIO_CHAN_INFO_BITS(type);
+	return (chan->info_mask_separate & type) |
+	       (chan->info_mask_shared_by_type & type);
 }
 
 #define IIO_ST(si, rb, sb, sh)						\
diff --git a/include/linux/iio/imu/adis.h b/include/linux/iio/imu/adis.h
index ff781dc..b665dc7 100644
--- a/include/linux/iio/imu/adis.h
+++ b/include/linux/iio/imu/adis.h
@@ -162,8 +162,8 @@ int adis_single_conversion(struct iio_dev *indio_dev,
 	.indexed = 1, \
 	.channel = (chan), \
 	.extend_name = name, \
-	.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
-		IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+		BIT(IIO_CHAN_INFO_SCALE), \
 	.address = (addr), \
 	.scan_index = (si), \
 	.scan_type = { \
@@ -184,9 +184,9 @@ int adis_single_conversion(struct iio_dev *indio_dev,
 	.type = IIO_TEMP, \
 	.indexed = 1, \
 	.channel = 0, \
-	.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
-		IIO_CHAN_INFO_SCALE_SEPARATE_BIT | \
-		IIO_CHAN_INFO_OFFSET_SEPARATE_BIT, \
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+		BIT(IIO_CHAN_INFO_SCALE) | \
+		BIT(IIO_CHAN_INFO_OFFSET), \
 	.address = (addr), \
 	.scan_index = (si), \
 	.scan_type = { \
@@ -197,13 +197,13 @@ int adis_single_conversion(struct iio_dev *indio_dev,
 	}, \
 }
 
-#define ADIS_MOD_CHAN(_type, mod, addr, si, info, bits) { \
+#define ADIS_MOD_CHAN(_type, mod, addr, si, info_sep, bits) { \
 	.type = (_type), \
 	.modified = 1, \
 	.channel2 = IIO_MOD_ ## mod, \
-	.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
-		 IIO_CHAN_INFO_SCALE_SHARED_BIT | \
-		 info, \
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+		 info_sep, \
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
 	.address = (addr), \
 	.scan_index = (si), \
 	.scan_type = { \
@@ -214,17 +214,17 @@ int adis_single_conversion(struct iio_dev *indio_dev,
 	}, \
 }
 
-#define ADIS_ACCEL_CHAN(mod, addr, si, info, bits) \
-	ADIS_MOD_CHAN(IIO_ACCEL, mod, addr, si, info, bits)
+#define ADIS_ACCEL_CHAN(mod, addr, si, info_sep, bits) \
+	ADIS_MOD_CHAN(IIO_ACCEL, mod, addr, si, info_sep, bits)
 
-#define ADIS_GYRO_CHAN(mod, addr, si, info, bits) \
-	ADIS_MOD_CHAN(IIO_ANGL_VEL, mod, addr, si, info, bits)
+#define ADIS_GYRO_CHAN(mod, addr, si, info_sep, bits) \
+	ADIS_MOD_CHAN(IIO_ANGL_VEL, mod, addr, si, info_sep, bits)
 
-#define ADIS_INCLI_CHAN(mod, addr, si, info, bits) \
-	ADIS_MOD_CHAN(IIO_INCLI, mod, addr, si, info, bits)
+#define ADIS_INCLI_CHAN(mod, addr, si, info_sep, bits) \
+	ADIS_MOD_CHAN(IIO_INCLI, mod, addr, si, info_sep, bits)
 
-#define ADIS_ROT_CHAN(mod, addr, si, info, bits) \
-	ADIS_MOD_CHAN(IIO_ROT, mod, addr, si, info, bits)
+#define ADIS_ROT_CHAN(mod, addr, si, info_sep, bits) \
+	ADIS_MOD_CHAN(IIO_ROT, mod, addr, si, info_sep, bits)
 
 #ifdef CONFIG_IIO_ADIS_LIB_BUFFER
 
diff --git a/include/linux/iio/trigger.h b/include/linux/iio/trigger.h
index c66e0a9..3869c52 100644
--- a/include/linux/iio/trigger.h
+++ b/include/linux/iio/trigger.h
@@ -44,7 +44,6 @@ struct iio_trigger_ops {
  * @id:			[INTERN] unique id number
  * @name:		[DRIVER] unique name
  * @dev:		[DRIVER] associated device (if relevant)
- * @private_data:	[DRIVER] device specific data
  * @list:		[INTERN] used in maintenance of global trigger list
  * @alloc_list:		[DRIVER] used for driver specific trigger list
  * @use_count:		use count for the trigger
@@ -60,7 +59,6 @@ struct iio_trigger {
 	const char			*name;
 	struct device			dev;
 
-	void				*private_data;
 	struct list_head		list;
 	struct list_head		alloc_list;
 	int use_count;
@@ -92,6 +90,30 @@ static inline void iio_trigger_get(struct iio_trigger *trig)
 }
 
 /**
+ * iio_device_set_drvdata() - Set trigger driver data
+ * @trig: IIO trigger structure
+ * @data: Driver specific data
+ *
+ * Allows to attach an arbitrary pointer to an IIO trigger, which can later be
+ * retrieved by iio_trigger_get_drvdata().
+ */
+static inline void iio_trigger_set_drvdata(struct iio_trigger *trig, void *data)
+{
+	dev_set_drvdata(&trig->dev, data);
+}
+
+/**
+ * iio_trigger_get_drvdata() - Get trigger driver data
+ * @trig: IIO trigger structure
+ *
+ * Returns the data previously set with iio_trigger_set_drvdata()
+ */
+static inline void *iio_trigger_get_drvdata(struct iio_trigger *trig)
+{
+	return dev_get_drvdata(&trig->dev);
+}
+
+/**
  * iio_trigger_register() - register a trigger with the IIO core
  * @trig_info:	trigger to be registered
  **/
diff --git a/include/linux/ima.h b/include/linux/ima.h
index 86c361e..1b7f268 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -46,7 +46,7 @@ static inline int ima_module_check(struct file *file)
 	return 0;
 }
 
-#endif /* CONFIG_IMA_H */
+#endif /* CONFIG_IMA */
 
 #ifdef CONFIG_IMA_APPRAISE
 extern void ima_inode_post_setattr(struct dentry *dentry);
@@ -72,5 +72,5 @@ static inline int ima_inode_removexattr(struct dentry *dentry,
 {
 	return 0;
 }
-#endif /* CONFIG_IMA_APPRAISE_H */
+#endif /* CONFIG_IMA_APPRAISE */
 #endif /* _LINUX_IMA_H */
diff --git a/include/linux/input/auo-pixcir-ts.h b/include/linux/input/auo-pixcir-ts.h
index 75d4be7..5049f21 100644
--- a/include/linux/input/auo-pixcir-ts.h
+++ b/include/linux/input/auo-pixcir-ts.h
@@ -43,12 +43,10 @@
  */
 struct auo_pixcir_ts_platdata {
 	int gpio_int;
+	int gpio_rst;
 
 	int int_setting;
 
-	void (*init_hw)(struct i2c_client *);
-	void (*exit_hw)(struct i2c_client *);
-
 	unsigned int x_max;
 	unsigned int y_max;
 };
diff --git a/include/linux/input/matrix_keypad.h b/include/linux/input/matrix_keypad.h
index 5f3aa6b..27e06ac 100644
--- a/include/linux/input/matrix_keypad.h
+++ b/include/linux/input/matrix_keypad.h
@@ -81,4 +81,23 @@ int matrix_keypad_build_keymap(const struct matrix_keymap_data *keymap_data,
 			       unsigned short *keymap,
 			       struct input_dev *input_dev);
 
+#ifdef CONFIG_OF
+/**
+ * matrix_keypad_parse_of_params() - Read parameters from matrix-keypad node
+ *
+ * @dev: Device containing of_node
+ * @rows: Returns number of matrix rows
+ * @cols: Returns number of matrix columns
+ * @return 0 if OK, <0 on error
+ */
+int matrix_keypad_parse_of_params(struct device *dev,
+				  unsigned int *rows, unsigned int *cols);
+#else
+static inline int matrix_keypad_parse_of_params(struct device *dev,
+				  unsigned int *rows, unsigned int *cols)
+{
+	return -ENOSYS;
+}
+#endif /* CONFIG_OF */
+
 #endif /* _MATRIX_KEYPAD_H */
diff --git a/include/linux/input/mt.h b/include/linux/input/mt.h
index 2e86bd0..1b1dfa8 100644
--- a/include/linux/input/mt.h
+++ b/include/linux/input/mt.h
@@ -19,6 +19,7 @@
 #define INPUT_MT_DIRECT		0x0002	/* direct device, e.g. touchscreen */
 #define INPUT_MT_DROP_UNUSED	0x0004	/* drop contacts not seen in frame */
 #define INPUT_MT_TRACK		0x0008	/* use in-kernel tracking */
+#define INPUT_MT_SEMI_MT	0x0010	/* semi-mt device, finger count handled manually */
 
 /**
  * struct input_mt_slot - represents the state of an input MT slot
diff --git a/include/linux/integrity.h b/include/linux/integrity.h
index 66c5fe9..83222ce 100644
--- a/include/linux/integrity.h
+++ b/include/linux/integrity.h
@@ -36,5 +36,5 @@ static inline void integrity_inode_free(struct inode *inode)
 {
 	return;
 }
-#endif /* CONFIG_INTEGRITY_H */
+#endif /* CONFIG_INTEGRITY */
 #endif /* _LINUX_INTEGRITY_H */
diff --git a/include/linux/ipack.h b/include/linux/ipack.h
index fea12cb..1888e06 100644
--- a/include/linux/ipack.h
+++ b/include/linux/ipack.h
@@ -207,19 +207,41 @@ int ipack_driver_register(struct ipack_driver *edrv, struct module *owner,
 void ipack_driver_unregister(struct ipack_driver *edrv);
 
 /**
- *	ipack_device_register -- register an IPack device with the kernel
- *	@dev: the new device to register.
+ *	ipack_device_init -- initialize an IPack device
+ * @dev: the new device to initialize.
  *
- *	Register a new IPack device ("module" in IndustryPack jargon). The call
- *	is done by the carrier driver.  The carrier should populate the fields
- *	bus and slot as well as the region array of @dev prior to calling this
- *	function.  The rest of the fields will be allocated and populated
- *	during registration.
+ * Initialize a new IPack device ("module" in IndustryPack jargon). The call
+ * is done by the carrier driver.  The carrier should populate the fields
+ * bus and slot as well as the region array of @dev prior to calling this
+ * function.  The rest of the fields will be allocated and populated
+ * during initalization.
  *
- *	Return zero on success or error code on failure.
+ * Return zero on success or error code on failure.
+ *
+ * NOTE: _Never_ directly free @dev after calling this function, even
+ * if it returned an error! Always use ipack_put_device() to give up the
+ * reference initialized in this function instead.
+ */
+int ipack_device_init(struct ipack_device *dev);
+
+/**
+ *	ipack_device_add -- Add an IPack device
+ * @dev: the new device to add.
+ *
+ * Add a new IPack device. The call is done by the carrier driver
+ * after calling ipack_device_init().
+ *
+ * Return zero on success or error code on failure.
+ *
+ * NOTE: _Never_ directly free @dev after calling this function, even
+ * if it returned an error! Always use ipack_put_device() to give up the
+ * reference initialized in this function instead.
  */
-int ipack_device_register(struct ipack_device *dev);
-void ipack_device_unregister(struct ipack_device *dev);
+int ipack_device_add(struct ipack_device *dev);
+void ipack_device_del(struct ipack_device *dev);
+
+void ipack_get_device(struct ipack_device *dev);
+void ipack_put_device(struct ipack_device *dev);
 
 /**
  * DEFINE_IPACK_DEVICE_TABLE - macro used to describe a IndustryPack table
diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h
index 3fd8e42..3e203eb 100644
--- a/include/linux/irqchip/arm-gic.h
+++ b/include/linux/irqchip/arm-gic.h
@@ -65,7 +65,6 @@ extern struct irq_chip gic_arch_extn;
 
 void gic_init_bases(unsigned int, int, void __iomem *, void __iomem *,
 		    u32 offset, struct device_node *);
-void gic_secondary_init(unsigned int);
 void gic_cascade_irq(unsigned int gic_nr, unsigned int irq);
 
 static inline void gic_init(unsigned int nr, int start,
diff --git a/include/linux/irqchip/chained_irq.h b/include/linux/irqchip/chained_irq.h
new file mode 100644
index 0000000..adf4c30
--- /dev/null
+++ b/include/linux/irqchip/chained_irq.h
@@ -0,0 +1,52 @@
+/*
+ * Chained IRQ handlers support.
+ *
+ * Copyright (C) 2011 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU 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 __IRQCHIP_CHAINED_IRQ_H
+#define __IRQCHIP_CHAINED_IRQ_H
+
+#include <linux/irq.h>
+
+/*
+ * Entry/exit functions for chained handlers where the primary IRQ chip
+ * may implement either fasteoi or level-trigger flow control.
+ */
+static inline void chained_irq_enter(struct irq_chip *chip,
+				     struct irq_desc *desc)
+{
+	/* FastEOI controllers require no action on entry. */
+	if (chip->irq_eoi)
+		return;
+
+	if (chip->irq_mask_ack) {
+		chip->irq_mask_ack(&desc->irq_data);
+	} else {
+		chip->irq_mask(&desc->irq_data);
+		if (chip->irq_ack)
+			chip->irq_ack(&desc->irq_data);
+	}
+}
+
+static inline void chained_irq_exit(struct irq_chip *chip,
+				    struct irq_desc *desc)
+{
+	if (chip->irq_eoi)
+		chip->irq_eoi(&desc->irq_data);
+	else
+		chip->irq_unmask(&desc->irq_data);
+}
+
+#endif /* __IRQCHIP_CHAINED_IRQ_H */
diff --git a/include/linux/irqchip/mxs.h b/include/linux/irqchip/mxs.h
new file mode 100644
index 0000000..9039a53
--- /dev/null
+++ b/include/linux/irqchip/mxs.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) 2013 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __LINUX_IRQCHIP_MXS_H
+#define __LINUX_IRQCHIP_MXS_H
+
+extern void icoll_handle_irq(struct pt_regs *);
+
+#endif
diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
index 50e5a5e..f9fe889 100644
--- a/include/linux/jbd2.h
+++ b/include/linux/jbd2.h
@@ -480,6 +480,7 @@ struct transaction_s
 		T_COMMIT,
 		T_COMMIT_DFLUSH,
 		T_COMMIT_JFLUSH,
+		T_COMMIT_CALLBACK,
 		T_FINISHED
 	}			t_state;
 
@@ -1200,6 +1201,7 @@ int __jbd2_log_start_commit(journal_t *journal, tid_t tid);
 int jbd2_journal_start_commit(journal_t *journal, tid_t *tid);
 int jbd2_journal_force_commit_nested(journal_t *journal);
 int jbd2_log_wait_commit(journal_t *journal, tid_t tid);
+int jbd2_complete_transaction(journal_t *journal, tid_t tid);
 int jbd2_log_do_checkpoint(journal_t *journal);
 int jbd2_trans_will_send_data_barrier(journal_t *journal, tid_t tid);
 
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 79fdd80..a661acf 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -486,6 +486,8 @@ enum ftrace_dump_mode {
 void tracing_on(void);
 void tracing_off(void);
 int tracing_is_on(void);
+void tracing_snapshot(void);
+void tracing_snapshot_alloc(void);
 
 extern void tracing_start(void);
 extern void tracing_stop(void);
@@ -515,10 +517,32 @@ do {									\
  *
  * This is intended as a debugging tool for the developer only.
  * Please refrain from leaving trace_printks scattered around in
- * your code.
+ * your code. (Extra memory is used for special buffers that are
+ * allocated when trace_printk() is used)
+ *
+ * A little optization trick is done here. If there's only one
+ * argument, there's no need to scan the string for printf formats.
+ * The trace_puts() will suffice. But how can we take advantage of
+ * using trace_puts() when trace_printk() has only one argument?
+ * By stringifying the args and checking the size we can tell
+ * whether or not there are args. __stringify((__VA_ARGS__)) will
+ * turn into "()\0" with a size of 3 when there are no args, anything
+ * else will be bigger. All we need to do is define a string to this,
+ * and then take its size and compare to 3. If it's bigger, use
+ * do_trace_printk() otherwise, optimize it to trace_puts(). Then just
+ * let gcc optimize the rest.
  */
 
-#define trace_printk(fmt, args...)					\
+#define trace_printk(fmt, ...)				\
+do {							\
+	char _______STR[] = __stringify((__VA_ARGS__));	\
+	if (sizeof(_______STR) > 3)			\
+		do_trace_printk(fmt, ##__VA_ARGS__);	\
+	else						\
+		trace_puts(fmt);			\
+} while (0)
+
+#define do_trace_printk(fmt, args...)					\
 do {									\
 	static const char *trace_printk_fmt				\
 		__attribute__((section("__trace_printk_fmt"))) =	\
@@ -538,7 +562,45 @@ int __trace_bprintk(unsigned long ip, const char *fmt, ...);
 extern __printf(2, 3)
 int __trace_printk(unsigned long ip, const char *fmt, ...);
 
-extern void trace_dump_stack(void);
+/**
+ * trace_puts - write a string into the ftrace buffer
+ * @str: the string to record
+ *
+ * Note: __trace_bputs is an internal function for trace_puts and
+ *       the @ip is passed in via the trace_puts macro.
+ *
+ * This is similar to trace_printk() but is made for those really fast
+ * paths that a developer wants the least amount of "Heisenbug" affects,
+ * where the processing of the print format is still too much.
+ *
+ * This function allows a kernel developer to debug fast path sections
+ * that printk is not appropriate for. By scattering in various
+ * printk like tracing in the code, a developer can quickly see
+ * where problems are occurring.
+ *
+ * This is intended as a debugging tool for the developer only.
+ * Please refrain from leaving trace_puts scattered around in
+ * your code. (Extra memory is used for special buffers that are
+ * allocated when trace_puts() is used)
+ *
+ * Returns: 0 if nothing was written, positive # if string was.
+ *  (1 when __trace_bputs is used, strlen(str) when __trace_puts is used)
+ */
+
+extern int __trace_bputs(unsigned long ip, const char *str);
+extern int __trace_puts(unsigned long ip, const char *str, int size);
+#define trace_puts(str) ({						\
+	static const char *trace_printk_fmt				\
+		__attribute__((section("__trace_printk_fmt"))) =	\
+		__builtin_constant_p(str) ? str : NULL;			\
+									\
+	if (__builtin_constant_p(str))					\
+		__trace_bputs(_THIS_IP_, trace_printk_fmt);		\
+	else								\
+		__trace_puts(_THIS_IP_, str, strlen(str));		\
+})
+
+extern void trace_dump_stack(int skip);
 
 /*
  * The double __builtin_constant_p is because gcc will give us an error
@@ -573,6 +635,8 @@ static inline void trace_dump_stack(void) { }
 static inline void tracing_on(void) { }
 static inline void tracing_off(void) { }
 static inline int tracing_is_on(void) { return 0; }
+static inline void tracing_snapshot(void) { }
+static inline void tracing_snapshot_alloc(void) { }
 
 static inline __printf(1, 2)
 int trace_printk(const char *fmt, ...)
@@ -722,13 +786,6 @@ static inline void ftrace_dump(enum ftrace_dump_mode oops_dump_mode) { }
 /* Trap pasters of __FUNCTION__ at compile-time */
 #define __FUNCTION__ (__func__)
 
-/* This helps us to avoid #ifdef CONFIG_SYMBOL_PREFIX */
-#ifdef CONFIG_SYMBOL_PREFIX
-#define SYMBOL_PREFIX CONFIG_SYMBOL_PREFIX
-#else
-#define SYMBOL_PREFIX ""
-#endif
-
 /* Rebuild everything on CONFIG_FTRACE_MCOUNT_RECORD */
 #ifdef CONFIG_FTRACE_MCOUNT_RECORD
 # define REBUILD_DUE_TO_FTRACE_MCOUNT_RECORD
diff --git a/include/linux/kmalloc_sizes.h b/include/linux/kmalloc_sizes.h
deleted file mode 100644
index e576b84..0000000
--- a/include/linux/kmalloc_sizes.h
+++ /dev/null
@@ -1,45 +0,0 @@
-#if (PAGE_SIZE == 4096)
-	CACHE(32)
-#endif
-	CACHE(64)
-#if L1_CACHE_BYTES < 64
-	CACHE(96)
-#endif
-	CACHE(128)
-#if L1_CACHE_BYTES < 128
-	CACHE(192)
-#endif
-	CACHE(256)
-	CACHE(512)
-	CACHE(1024)
-	CACHE(2048)
-	CACHE(4096)
-	CACHE(8192)
-	CACHE(16384)
-	CACHE(32768)
-	CACHE(65536)
-	CACHE(131072)
-#if KMALLOC_MAX_SIZE >= 262144
-	CACHE(262144)
-#endif
-#if KMALLOC_MAX_SIZE >= 524288
-	CACHE(524288)
-#endif
-#if KMALLOC_MAX_SIZE >= 1048576
-	CACHE(1048576)
-#endif
-#if KMALLOC_MAX_SIZE >= 2097152
-	CACHE(2097152)
-#endif
-#if KMALLOC_MAX_SIZE >= 4194304
-	CACHE(4194304)
-#endif
-#if KMALLOC_MAX_SIZE >= 8388608
-	CACHE(8388608)
-#endif
-#if KMALLOC_MAX_SIZE >= 16777216
-	CACHE(16777216)
-#endif
-#if KMALLOC_MAX_SIZE >= 33554432
-	CACHE(33554432)
-#endif
diff --git a/include/linux/kmod.h b/include/linux/kmod.h
index 5398d58..0555cc6 100644
--- a/include/linux/kmod.h
+++ b/include/linux/kmod.h
@@ -67,16 +67,15 @@ struct subprocess_info {
 };
 
 extern int
-call_usermodehelper_fns(char *path, char **argv, char **envp, int wait,
-			int (*init)(struct subprocess_info *info, struct cred *new),
-			void (*cleanup)(struct subprocess_info *), void *data);
+call_usermodehelper(char *path, char **argv, char **envp, int wait);
 
-static inline int
-call_usermodehelper(char *path, char **argv, char **envp, int wait)
-{
-	return call_usermodehelper_fns(path, argv, envp, wait,
-				       NULL, NULL, NULL);
-}
+extern struct subprocess_info *
+call_usermodehelper_setup(char *path, char **argv, char **envp, gfp_t gfp_mask,
+			  int (*init)(struct subprocess_info *info, struct cred *new),
+			  void (*cleanup)(struct subprocess_info *), void *data);
+
+extern int
+call_usermodehelper_exec(struct subprocess_info *info, int wait);
 
 extern struct ctl_table usermodehelper_table[];
 
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index cad77fe..31dcb37 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -149,6 +149,8 @@ struct kvm_io_bus {
 enum kvm_bus {
 	KVM_MMIO_BUS,
 	KVM_PIO_BUS,
+	KVM_VIRTIO_CCW_NOTIFY_BUS,
+	KVM_PV_MMIO_BUS,
 	KVM_NR_BUSES
 };
 
@@ -252,6 +254,7 @@ struct kvm_vcpu {
 		bool dy_eligible;
 	} spin_loop;
 #endif
+	bool preempted;
 	struct kvm_vcpu_arch arch;
 };
 
@@ -424,6 +427,19 @@ void kvm_vcpu_uninit(struct kvm_vcpu *vcpu);
 int __must_check vcpu_load(struct kvm_vcpu *vcpu);
 void vcpu_put(struct kvm_vcpu *vcpu);
 
+#ifdef __KVM_HAVE_IOAPIC
+int kvm_irqfd_init(void);
+void kvm_irqfd_exit(void);
+#else
+static inline int kvm_irqfd_init(void)
+{
+	return 0;
+}
+
+static inline void kvm_irqfd_exit(void)
+{
+}
+#endif
 int kvm_init(void *opaque, unsigned vcpu_size, unsigned vcpu_align,
 		  struct module *module);
 void kvm_exit(void);
@@ -452,24 +468,39 @@ id_to_memslot(struct kvm_memslots *slots, int id)
 	return slot;
 }
 
+/*
+ * KVM_SET_USER_MEMORY_REGION ioctl allows the following operations:
+ * - create a new memory slot
+ * - delete an existing memory slot
+ * - modify an existing memory slot
+ *   -- move it in the guest physical memory space
+ *   -- just change its flags
+ *
+ * Since flags can be changed by some of these operations, the following
+ * differentiation is the best we can do for __kvm_set_memory_region():
+ */
+enum kvm_mr_change {
+	KVM_MR_CREATE,
+	KVM_MR_DELETE,
+	KVM_MR_MOVE,
+	KVM_MR_FLAGS_ONLY,
+};
+
 int kvm_set_memory_region(struct kvm *kvm,
-			  struct kvm_userspace_memory_region *mem,
-			  bool user_alloc);
+			  struct kvm_userspace_memory_region *mem);
 int __kvm_set_memory_region(struct kvm *kvm,
-			    struct kvm_userspace_memory_region *mem,
-			    bool user_alloc);
+			    struct kvm_userspace_memory_region *mem);
 void kvm_arch_free_memslot(struct kvm_memory_slot *free,
 			   struct kvm_memory_slot *dont);
 int kvm_arch_create_memslot(struct kvm_memory_slot *slot, unsigned long npages);
 int kvm_arch_prepare_memory_region(struct kvm *kvm,
 				struct kvm_memory_slot *memslot,
-				struct kvm_memory_slot old,
 				struct kvm_userspace_memory_region *mem,
-				bool user_alloc);
+				enum kvm_mr_change change);
 void kvm_arch_commit_memory_region(struct kvm *kvm,
 				struct kvm_userspace_memory_region *mem,
-				struct kvm_memory_slot old,
-				bool user_alloc);
+				const struct kvm_memory_slot *old,
+				enum kvm_mr_change change);
 bool kvm_largepages_enabled(void);
 void kvm_disable_largepages(void);
 /* flush all memory translations */
@@ -555,9 +586,7 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,
 				struct kvm_dirty_log *log);
 
 int kvm_vm_ioctl_set_memory_region(struct kvm *kvm,
-				   struct
-				   kvm_userspace_memory_region *mem,
-				   bool user_alloc);
+				   struct kvm_userspace_memory_region *mem);
 int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *irq_level);
 long kvm_arch_vm_ioctl(struct file *filp,
 		       unsigned int ioctl, unsigned long arg);
diff --git a/include/linux/leds.h b/include/linux/leds.h
index 0d9b5ee..0287ab2 100644
--- a/include/linux/leds.h
+++ b/include/linux/leds.h
@@ -142,6 +142,10 @@ extern void led_set_brightness(struct led_classdev *led_cdev,
 /*
  * LED Triggers
  */
+/* Registration functions for simple triggers */
+#define DEFINE_LED_TRIGGER(x)		static struct led_trigger *x;
+#define DEFINE_LED_TRIGGER_GLOBAL(x)	struct led_trigger *x;
+
 #ifdef CONFIG_LEDS_TRIGGERS
 
 #define TRIG_NAME_MAX 50
@@ -164,9 +168,6 @@ struct led_trigger {
 extern int led_trigger_register(struct led_trigger *trigger);
 extern void led_trigger_unregister(struct led_trigger *trigger);
 
-/* Registration functions for simple triggers */
-#define DEFINE_LED_TRIGGER(x)		static struct led_trigger *x;
-#define DEFINE_LED_TRIGGER_GLOBAL(x)	struct led_trigger *x;
 extern void led_trigger_register_simple(const char *name,
 				struct led_trigger **trigger);
 extern void led_trigger_unregister_simple(struct led_trigger *trigger);
@@ -199,20 +200,30 @@ extern void led_trigger_rename_static(const char *name,
 
 #else
 
-/* Triggers aren't active - null macros */
-#define DEFINE_LED_TRIGGER(x)
-#define DEFINE_LED_TRIGGER_GLOBAL(x)
-#define led_trigger_register_simple(x, y) do {} while(0)
-#define led_trigger_unregister_simple(x) do {} while(0)
-#define led_trigger_event(x, y) do {} while(0)
+/* Trigger has no members */
+struct led_trigger {};
 
-#endif
+/* Trigger inline empty functions */
+static inline void led_trigger_register_simple(const char *name,
+					struct led_trigger **trigger) {}
+static inline void led_trigger_unregister_simple(struct led_trigger *trigger) {}
+static inline void led_trigger_event(struct led_trigger *trigger,
+				enum led_brightness event) {}
+#endif /* CONFIG_LEDS_TRIGGERS */
 
 /* Trigger specific functions */
 #ifdef CONFIG_LEDS_TRIGGER_IDE_DISK
 extern void ledtrig_ide_activity(void);
 #else
-#define ledtrig_ide_activity() do {} while(0)
+static inline void ledtrig_ide_activity(void) {}
+#endif
+
+#if defined(CONFIG_LEDS_TRIGGER_CAMERA) || defined(CONFIG_LEDS_TRIGGER_CAMERA_MODULE)
+extern void ledtrig_flash_ctrl(bool on);
+extern void ledtrig_torch_ctrl(bool on);
+#else
+static inline void ledtrig_flash_ctrl(bool on) {}
+static inline void ledtrig_torch_ctrl(bool on) {}
 #endif
 
 /*
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 91c9d10..eae7a05 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -398,6 +398,7 @@ enum {
 	ATA_HORKAGE_NOSETXFER	= (1 << 14),	/* skip SETXFER, SATA only */
 	ATA_HORKAGE_BROKEN_FPDMA_AA	= (1 << 15),	/* skip AA */
 	ATA_HORKAGE_DUMP_ID	= (1 << 16),	/* dump IDENTIFY data */
+	ATA_HORKAGE_MAX_SEC_LBA48 = (1 << 17),	/* Set max sects to 65535 */
 
 	 /* DMA mask for user DMA control: User visible values; DO NOT
 	    renumber */
diff --git a/include/linux/linkage.h b/include/linux/linkage.h
index 807f1e5..bedcddf 100644
--- a/include/linux/linkage.h
+++ b/include/linux/linkage.h
@@ -2,6 +2,7 @@
 #define _LINUX_LINKAGE_H
 
 #include <linux/compiler.h>
+#include <linux/export.h>
 #include <asm/linkage.h>
 
 #ifdef __cplusplus
@@ -14,6 +15,18 @@
 #define asmlinkage CPP_ASMLINKAGE
 #endif
 
+#ifndef cond_syscall
+#define cond_syscall(x) asm(".weak\t" VMLINUX_SYMBOL_STR(x) "\n\t"	\
+			    ".set\t" VMLINUX_SYMBOL_STR(x) ","	\
+			    VMLINUX_SYMBOL_STR(sys_ni_syscall))
+#endif
+
+#ifndef SYSCALL_ALIAS
+#define SYSCALL_ALIAS(alias, name)				\
+	asm ("\t.globl " VMLINUX_SYMBOL_STR(alias)			\
+	"\n\t.set\t" VMLINUX_SYMBOL_STR(alias) "," VMLINUX_SYMBOL_STR(name))
+#endif
+
 #define __page_aligned_data	__section(.data..page_aligned) __aligned(PAGE_SIZE)
 #define __page_aligned_bss	__section(.bss..page_aligned) __aligned(PAGE_SIZE)
 
diff --git a/include/linux/list_bl.h b/include/linux/list_bl.h
index 31f9d75..2eb8855 100644
--- a/include/linux/list_bl.h
+++ b/include/linux/list_bl.h
@@ -125,6 +125,11 @@ static inline void hlist_bl_unlock(struct hlist_bl_head *b)
 	__bit_spin_unlock(0, (unsigned long *)b);
 }
 
+static inline bool hlist_bl_is_locked(struct hlist_bl_head *b)
+{
+	return bit_spin_is_locked(0, (unsigned long *)b);
+}
+
 /**
  * hlist_bl_for_each_entry	- iterate over list of given type
  * @tpos:	the type * to use as a loop cursor.
diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h
index f1e877b..cfc2f11 100644
--- a/include/linux/lockdep.h
+++ b/include/linux/lockdep.h
@@ -365,7 +365,7 @@ extern void lockdep_trace_alloc(gfp_t mask);
 
 #define lockdep_recursing(tsk)	((tsk)->lockdep_recursion)
 
-#else /* !LOCKDEP */
+#else /* !CONFIG_LOCKDEP */
 
 static inline void lockdep_off(void)
 {
@@ -479,82 +479,36 @@ static inline void print_irqtrace_events(struct task_struct *curr)
  * on the per lock-class debug mode:
  */
 
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
-# ifdef CONFIG_PROVE_LOCKING
-#  define spin_acquire(l, s, t, i)		lock_acquire(l, s, t, 0, 2, NULL, i)
-#  define spin_acquire_nest(l, s, t, n, i)	lock_acquire(l, s, t, 0, 2, n, i)
-# else
-#  define spin_acquire(l, s, t, i)		lock_acquire(l, s, t, 0, 1, NULL, i)
-#  define spin_acquire_nest(l, s, t, n, i)	lock_acquire(l, s, t, 0, 1, NULL, i)
-# endif
-# define spin_release(l, n, i)			lock_release(l, n, i)
+#ifdef CONFIG_PROVE_LOCKING
+ #define lock_acquire_exclusive(l, s, t, n, i)		lock_acquire(l, s, t, 0, 2, n, i)
+ #define lock_acquire_shared(l, s, t, n, i)		lock_acquire(l, s, t, 1, 2, n, i)
+ #define lock_acquire_shared_recursive(l, s, t, n, i)	lock_acquire(l, s, t, 2, 2, n, i)
 #else
-# define spin_acquire(l, s, t, i)		do { } while (0)
-# define spin_release(l, n, i)			do { } while (0)
+ #define lock_acquire_exclusive(l, s, t, n, i)		lock_acquire(l, s, t, 0, 1, n, i)
+ #define lock_acquire_shared(l, s, t, n, i)		lock_acquire(l, s, t, 1, 1, n, i)
+ #define lock_acquire_shared_recursive(l, s, t, n, i)	lock_acquire(l, s, t, 2, 1, n, i)
 #endif
 
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
-# ifdef CONFIG_PROVE_LOCKING
-#  define rwlock_acquire(l, s, t, i)		lock_acquire(l, s, t, 0, 2, NULL, i)
-#  define rwlock_acquire_read(l, s, t, i)	lock_acquire(l, s, t, 2, 2, NULL, i)
-# else
-#  define rwlock_acquire(l, s, t, i)		lock_acquire(l, s, t, 0, 1, NULL, i)
-#  define rwlock_acquire_read(l, s, t, i)	lock_acquire(l, s, t, 2, 1, NULL, i)
-# endif
-# define rwlock_release(l, n, i)		lock_release(l, n, i)
-#else
-# define rwlock_acquire(l, s, t, i)		do { } while (0)
-# define rwlock_acquire_read(l, s, t, i)	do { } while (0)
-# define rwlock_release(l, n, i)		do { } while (0)
-#endif
+#define spin_acquire(l, s, t, i)		lock_acquire_exclusive(l, s, t, NULL, i)
+#define spin_acquire_nest(l, s, t, n, i)	lock_acquire_exclusive(l, s, t, n, i)
+#define spin_release(l, n, i)			lock_release(l, n, i)
 
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
-# ifdef CONFIG_PROVE_LOCKING
-#  define mutex_acquire(l, s, t, i)		lock_acquire(l, s, t, 0, 2, NULL, i)
-#  define mutex_acquire_nest(l, s, t, n, i)	lock_acquire(l, s, t, 0, 2, n, i)
-# else
-#  define mutex_acquire(l, s, t, i)		lock_acquire(l, s, t, 0, 1, NULL, i)
-#  define mutex_acquire_nest(l, s, t, n, i)	lock_acquire(l, s, t, 0, 1, n, i)
-# endif
-# define mutex_release(l, n, i)			lock_release(l, n, i)
-#else
-# define mutex_acquire(l, s, t, i)		do { } while (0)
-# define mutex_acquire_nest(l, s, t, n, i)	do { } while (0)
-# define mutex_release(l, n, i)			do { } while (0)
-#endif
+#define rwlock_acquire(l, s, t, i)		lock_acquire_exclusive(l, s, t, NULL, i)
+#define rwlock_acquire_read(l, s, t, i)		lock_acquire_shared_recursive(l, s, t, NULL, i)
+#define rwlock_release(l, n, i)			lock_release(l, n, i)
 
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
-# ifdef CONFIG_PROVE_LOCKING
-#  define rwsem_acquire(l, s, t, i)		lock_acquire(l, s, t, 0, 2, NULL, i)
-#  define rwsem_acquire_nest(l, s, t, n, i)	lock_acquire(l, s, t, 0, 2, n, i)
-#  define rwsem_acquire_read(l, s, t, i)	lock_acquire(l, s, t, 1, 2, NULL, i)
-# else
-#  define rwsem_acquire(l, s, t, i)		lock_acquire(l, s, t, 0, 1, NULL, i)
-#  define rwsem_acquire_nest(l, s, t, n, i)	lock_acquire(l, s, t, 0, 1, n, i)
-#  define rwsem_acquire_read(l, s, t, i)	lock_acquire(l, s, t, 1, 1, NULL, i)
-# endif
+#define mutex_acquire(l, s, t, i)		lock_acquire_exclusive(l, s, t, NULL, i)
+#define mutex_acquire_nest(l, s, t, n, i)	lock_acquire_exclusive(l, s, t, n, i)
+#define mutex_release(l, n, i)			lock_release(l, n, i)
+
+#define rwsem_acquire(l, s, t, i)		lock_acquire_exclusive(l, s, t, NULL, i)
+#define rwsem_acquire_nest(l, s, t, n, i)	lock_acquire_exclusive(l, s, t, n, i)
+#define rwsem_acquire_read(l, s, t, i)		lock_acquire_shared(l, s, t, NULL, i)
 # define rwsem_release(l, n, i)			lock_release(l, n, i)
-#else
-# define rwsem_acquire(l, s, t, i)		do { } while (0)
-# define rwsem_acquire_nest(l, s, t, n, i)	do { } while (0)
-# define rwsem_acquire_read(l, s, t, i)		do { } while (0)
-# define rwsem_release(l, n, i)			do { } while (0)
-#endif
 
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
-# ifdef CONFIG_PROVE_LOCKING
-#  define lock_map_acquire(l)		lock_acquire(l, 0, 0, 0, 2, NULL, _THIS_IP_)
-#  define lock_map_acquire_read(l)	lock_acquire(l, 0, 0, 2, 2, NULL, _THIS_IP_)
-# else
-#  define lock_map_acquire(l)		lock_acquire(l, 0, 0, 0, 1, NULL, _THIS_IP_)
-#  define lock_map_acquire_read(l)	lock_acquire(l, 0, 0, 2, 1, NULL, _THIS_IP_)
-# endif
+#define lock_map_acquire(l)			lock_acquire_exclusive(l, 0, 0, NULL, _THIS_IP_)
+#define lock_map_acquire_read(l)		lock_acquire_shared_recursive(l, 0, 0, NULL, _THIS_IP_)
 # define lock_map_release(l)			lock_release(l, 1, _THIS_IP_)
-#else
-# define lock_map_acquire(l)			do { } while (0)
-# define lock_map_acquire_read(l)		do { } while (0)
-# define lock_map_release(l)			do { } while (0)
-#endif
 
 #ifdef CONFIG_PROVE_LOCKING
 # define might_lock(lock) 						\
diff --git a/include/linux/lru_cache.h b/include/linux/lru_cache.h
index 4019013..4626228 100644
--- a/include/linux/lru_cache.h
+++ b/include/linux/lru_cache.h
@@ -256,6 +256,7 @@ extern void lc_destroy(struct lru_cache *lc);
 extern void lc_set(struct lru_cache *lc, unsigned int enr, int index);
 extern void lc_del(struct lru_cache *lc, struct lc_element *element);
 
+extern struct lc_element *lc_get_cumulative(struct lru_cache *lc, unsigned int enr);
 extern struct lc_element *lc_try_get(struct lru_cache *lc, unsigned int enr);
 extern struct lc_element *lc_find(struct lru_cache *lc, unsigned int enr);
 extern struct lc_element *lc_get(struct lru_cache *lc, unsigned int enr);
diff --git a/include/linux/lz4.h b/include/linux/lz4.h
new file mode 100644
index 0000000..d21c13f
--- /dev/null
+++ b/include/linux/lz4.h
@@ -0,0 +1,87 @@
+#ifndef __LZ4_H__
+#define __LZ4_H__
+/*
+ * LZ4 Kernel Interface
+ *
+ * Copyright (C) 2013, LG Electronics, Kyungsik Lee <kyungsik.lee@lge.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#define LZ4_MEM_COMPRESS	(4096 * sizeof(unsigned char *))
+#define LZ4HC_MEM_COMPRESS	(65538 * sizeof(unsigned char *))
+
+/*
+ * lz4_compressbound()
+ * Provides the maximum size that LZ4 may output in a "worst case" scenario
+ * (input data not compressible)
+ */
+static inline size_t lz4_compressbound(size_t isize)
+{
+	return isize + (isize / 255) + 16;
+}
+
+/*
+ * lz4_compress()
+ *	src     : source address of the original data
+ *	src_len : size of the original data
+ *	dst	: output buffer address of the compressed data
+ *		This requires 'dst' of size LZ4_COMPRESSBOUND.
+ *	dst_len : is the output size, which is returned after compress done
+ *	workmem : address of the working memory.
+ *		This requires 'workmem' of size LZ4_MEM_COMPRESS.
+ *	return  : Success if return 0
+ *		  Error if return (< 0)
+ *	note :  Destination buffer and workmem must be already allocated with
+ *		the defined size.
+ */
+int lz4_compress(const unsigned char *src, size_t src_len,
+		unsigned char *dst, size_t *dst_len, void *wrkmem);
+
+ /*
+  * lz4hc_compress()
+  *	 src	 : source address of the original data
+  *	 src_len : size of the original data
+  *	 dst	 : output buffer address of the compressed data
+  *		This requires 'dst' of size LZ4_COMPRESSBOUND.
+  *	 dst_len : is the output size, which is returned after compress done
+  *	 workmem : address of the working memory.
+  *		This requires 'workmem' of size LZ4HC_MEM_COMPRESS.
+  *	 return  : Success if return 0
+  *		   Error if return (< 0)
+  *	 note :  Destination buffer and workmem must be already allocated with
+  *		 the defined size.
+  */
+int lz4hc_compress(const unsigned char *src, size_t src_len,
+		unsigned char *dst, size_t *dst_len, void *wrkmem);
+
+/*
+ * lz4_decompress()
+ *	src     : source address of the compressed data
+ *	src_len : is the input size, whcih is returned after decompress done
+ *	dest	: output buffer address of the decompressed data
+ *	actual_dest_len: is the size of uncompressed data, supposing it's known
+ *	return  : Success if return 0
+ *		  Error if return (< 0)
+ *	note :  Destination buffer must be already allocated.
+ *		slightly faster than lz4_decompress_unknownoutputsize()
+ */
+int lz4_decompress(const char *src, size_t *src_len, char *dest,
+		size_t actual_dest_len);
+
+/*
+ * lz4_decompress_unknownoutputsize()
+ *	src     : source address of the compressed data
+ *	src_len : is the input size, therefore the compressed size
+ *	dest	: output buffer address of the decompressed data
+ *	dest_len: is the max size of the destination buffer, which is
+ *			returned with actual size of decompressed data after
+ *			decompress done
+ *	return  : Success if return 0
+ *		  Error if return (< 0)
+ *	note :  Destination buffer must be already allocated.
+ */
+int lz4_decompress_unknownoutputsize(const char *src, size_t src_len,
+		char *dest, size_t *dest_len);
+#endif
diff --git a/include/linux/mailbox.h b/include/linux/mailbox.h
index 5161f63..a41b67d 100644
--- a/include/linux/mailbox.h
+++ b/include/linux/mailbox.h
@@ -1,17 +1,43 @@
 /*
- * 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.
+ * mailbox: interprocessor communication module
  *
- * 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, see <http://www.gnu.org/licenses/>.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
  */
 
-int pl320_ipc_transmit(u32 *data);
-int pl320_ipc_register_notifier(struct notifier_block *nb);
-int pl320_ipc_unregister_notifier(struct notifier_block *nb);
+#ifndef MAILBOX_H
+#define MAILBOX_H
+
+struct mailbox;
+
+typedef int __bitwise mailbox_irq_t;
+#define IRQ_TX ((__force mailbox_irq_t) 1)
+#define IRQ_RX ((__force mailbox_irq_t) 2)
+
+struct mailbox_msg {
+	int		size;
+	u32		header;
+	void		*pdata;
+};
+
+#define MAILBOX_FILL_MSG(_msg, _header, _pdata, _size) { \
+	_msg.header = _header; \
+	_msg.pdata = (void *)_pdata; \
+	_msg.size = _size; \
+}
+
+int mailbox_msg_send(struct mailbox *, struct mailbox_msg *msg);
+struct mailbox_msg *mailbox_msg_send_receive_no_irq(struct mailbox *,
+		struct mailbox_msg *msg);
+int mailbox_msg_send_no_irq(struct mailbox *, struct mailbox_msg *msg);
+
+struct mailbox *mailbox_get(const char *, struct notifier_block *nb);
+void mailbox_put(struct mailbox *mbox, struct notifier_block *nb);
+
+void mailbox_save_ctx(struct mailbox *mbox);
+void mailbox_restore_ctx(struct mailbox *mbox);
+void mailbox_enable_irq(struct mailbox *mbox, mailbox_irq_t irq);
+void mailbox_disable_irq(struct mailbox *mbox, mailbox_irq_t irq);
+
+#endif /* MAILBOX_H */
diff --git a/include/linux/mei_cl_bus.h b/include/linux/mei_cl_bus.h
new file mode 100644
index 0000000..1bece18
--- /dev/null
+++ b/include/linux/mei_cl_bus.h
@@ -0,0 +1,41 @@
+#ifndef _LINUX_MEI_CL_BUS_H
+#define _LINUX_MEI_CL_BUS_H
+
+#include <linux/device.h>
+#include <linux/uuid.h>
+
+struct mei_cl_device;
+
+struct mei_cl_driver {
+	struct device_driver driver;
+	const char *name;
+
+	const struct mei_cl_device_id *id_table;
+
+	int (*probe)(struct mei_cl_device *dev,
+		     const struct mei_cl_device_id *id);
+	int (*remove)(struct mei_cl_device *dev);
+};
+
+int __mei_cl_driver_register(struct mei_cl_driver *driver,
+				struct module *owner);
+#define mei_cl_driver_register(driver)             \
+	__mei_cl_driver_register(driver, THIS_MODULE)
+
+void mei_cl_driver_unregister(struct mei_cl_driver *driver);
+
+int mei_cl_send(struct mei_cl_device *device, u8 *buf, size_t length);
+int mei_cl_recv(struct mei_cl_device *device, u8 *buf, size_t length);
+
+typedef void (*mei_cl_event_cb_t)(struct mei_cl_device *device,
+			       u32 events, void *context);
+int mei_cl_register_event_cb(struct mei_cl_device *device,
+			  mei_cl_event_cb_t read_cb, void *context);
+
+#define MEI_CL_EVENT_RX 0
+#define MEI_CL_EVENT_TX 1
+
+void *mei_cl_get_drvdata(const struct mei_cl_device *device);
+void mei_cl_set_drvdata(struct mei_cl_device *device, void *data);
+
+#endif /* _LINUX_MEI_CL_BUS_H */
diff --git a/include/linux/mfd/abx500.h b/include/linux/mfd/abx500.h
index 9ead60b..33b0253 100644
--- a/include/linux/mfd/abx500.h
+++ b/include/linux/mfd/abx500.h
@@ -89,6 +89,11 @@ struct abx500_fg;
  *				points.
  * @maint_thres			This is the threshold where we stop reporting
  *				battery full while in maintenance, in per cent
+ * @pcut_enable:			Enable power cut feature in ab8505
+ * @pcut_max_time:		Max time threshold
+ * @pcut_flag_time:		Flagtime threshold
+ * @pcut_max_restart:		Max number of restarts
+ * @pcut_debounce_time:		Sets battery debounce time
  */
 struct abx500_fg_parameters {
 	int recovery_sleep_timer;
@@ -106,6 +111,11 @@ struct abx500_fg_parameters {
 	int battok_raising_th_sel1;
 	int user_cap_limit;
 	int maint_thres;
+	bool pcut_enable;
+	u8 pcut_max_time;
+	u8 pcut_flag_time;
+	u8 pcut_max_restart;
+	u8 pcut_debounce_time;
 };
 
 /**
@@ -236,7 +246,11 @@ struct abx500_bm_charger_parameters {
  * @interval_not_charging charge alg cycle period time when not charging (sec)
  * @temp_hysteresis	temperature hysteresis
  * @gnd_lift_resistance	Battery ground to phone ground resistance (mOhm)
- * @maxi:		maximization parameters
+ * @n_chg_out_curr		number of elements in array chg_output_curr
+ * @n_chg_in_curr		number of elements in array chg_input_curr
+ * @chg_output_curr	charger output current level map
+ * @chg_input_curr		charger input current level map
+ * @maxi		maximization parameters
  * @cap_levels		capacity in percent for the different capacity levels
  * @bat_type		table of supported battery types
  * @chg_params		charger parameters
@@ -257,6 +271,7 @@ struct abx500_bm_data {
 	bool autopower_cfg;
 	bool ac_enabled;
 	bool usb_enabled;
+	bool usb_power_path;
 	bool no_maintenance;
 	bool capacity_scaling;
 	bool chg_unknown_bat;
@@ -270,6 +285,10 @@ struct abx500_bm_data {
 	int interval_not_charging;
 	int temp_hysteresis;
 	int gnd_lift_resistance;
+	int n_chg_out_curr;
+	int n_chg_in_curr;
+	int *chg_output_curr;
+	int *chg_input_curr;
 	const struct abx500_maxim_parameters *maxi;
 	const struct abx500_bm_capacity_levels *cap_levels;
 	struct abx500_battery_type *bat_type;
diff --git a/include/linux/mfd/abx500/ab8500-bm.h b/include/linux/mfd/abx500/ab8500-bm.h
index 8d35bfe..f5214dc 100644
--- a/include/linux/mfd/abx500/ab8500-bm.h
+++ b/include/linux/mfd/abx500/ab8500-bm.h
@@ -23,6 +23,7 @@
  * Bank : 0x5
  */
 #define AB8500_USB_LINE_STAT_REG	0x80
+#define AB8500_USB_LINE_CTRL2_REG	0x82
 #define AB8500_USB_LINK1_STAT_REG	0x94
 
 /*
@@ -33,7 +34,7 @@
 #define AB8500_CH_STATUS2_REG		0x01
 #define AB8500_CH_USBCH_STAT1_REG	0x02
 #define AB8500_CH_USBCH_STAT2_REG	0x03
-#define AB8500_CH_FSM_STAT_REG		0x04
+#define AB8540_CH_USBCH_STAT3_REG	0x04
 #define AB8500_CH_STAT_REG		0x05
 
 /*
@@ -69,6 +70,8 @@
 #define AB8500_USBCH_CTRL1_REG		0xC0
 #define AB8500_USBCH_CTRL2_REG		0xC1
 #define AB8500_USBCH_IPT_CRNTLVL_REG	0xC2
+#define AB8540_USB_PP_MODE_REG		0xC5
+#define AB8540_USB_PP_CHR_REG		0xC6
 
 /*
  * Gas Gauge register offsets
@@ -105,6 +108,7 @@
 #define AB8500_RTC_BACKUP_CHG_REG	0x0C
 #define AB8500_RTC_CC_CONF_REG		0x01
 #define AB8500_RTC_CTRL_REG		0x0B
+#define AB8500_RTC_CTRL1_REG		0x11
 
 /*
  * OTP register offsets
@@ -154,6 +158,7 @@
 #define CH_OP_CUR_LVL_1P4		0x0D
 #define CH_OP_CUR_LVL_1P5		0x0E
 #define CH_OP_CUR_LVL_1P6		0x0F
+#define CH_OP_CUR_LVL_2P		0x3F
 
 /* BTEMP High thermal limits */
 #define BTEMP_HIGH_TH_57_0		0x00
@@ -179,10 +184,25 @@
 #define BUP_ICH_SEL_300UA		0x08
 #define BUP_ICH_SEL_700UA		0x0C
 
-#define BUP_VCH_SEL_2P5V		0x00
-#define BUP_VCH_SEL_2P6V		0x01
-#define BUP_VCH_SEL_2P8V		0x02
-#define BUP_VCH_SEL_3P1V		0x03
+enum bup_vch_sel {
+	BUP_VCH_SEL_2P5V,
+	BUP_VCH_SEL_2P6V,
+	BUP_VCH_SEL_2P8V,
+	BUP_VCH_SEL_3P1V,
+	/*
+	 * Note that the following 5 values 2.7v, 2.9v, 3.0v, 3.2v, 3.3v
+	 * are only available on ab8540. You can't choose these 5
+	 * voltage on ab8500/ab8505/ab9540.
+	 */
+	BUP_VCH_SEL_2P7V,
+	BUP_VCH_SEL_2P9V,
+	BUP_VCH_SEL_3P0V,
+	BUP_VCH_SEL_3P2V,
+	BUP_VCH_SEL_3P3V,
+};
+
+#define BUP_VCH_RANGE		0x02
+#define VBUP33_VRTCN		0x01
 
 /* Battery OVV constants */
 #define BATT_OVV_ENA			0x02
@@ -228,6 +248,8 @@
 #define BAT_CTRL_20U_ENA		0x02
 #define BAT_CTRL_18U_ENA		0x01
 #define BAT_CTRL_16U_ENA		0x02
+#define BAT_CTRL_60U_ENA		0x01
+#define BAT_CTRL_120U_ENA		0x02
 #define BAT_CTRL_CMP_ENA		0x04
 #define FORCE_BAT_CTRL_CMP_HIGH		0x08
 #define BAT_CTRL_PULL_UP_ENA		0x10
@@ -235,6 +257,24 @@
 /* Battery type */
 #define BATTERY_UNKNOWN			00
 
+/* Registers for pcut feature in ab8505 and ab9540 */
+#define AB8505_RTC_PCUT_CTL_STATUS_REG	0x12
+#define AB8505_RTC_PCUT_TIME_REG	0x13
+#define AB8505_RTC_PCUT_MAX_TIME_REG	0x14
+#define AB8505_RTC_PCUT_FLAG_TIME_REG	0x15
+#define AB8505_RTC_PCUT_RESTART_REG	0x16
+#define AB8505_RTC_PCUT_DEBOUNCE_REG	0x17
+
+/* USB Power Path constants for ab8540 */
+#define BUS_VSYS_VOL_SELECT_MASK		0x06
+#define BUS_VSYS_VOL_SELECT_3P6V		0x00
+#define BUS_VSYS_VOL_SELECT_3P325V		0x02
+#define BUS_VSYS_VOL_SELECT_3P9V		0x04
+#define BUS_VSYS_VOL_SELECT_4P3V		0x06
+#define BUS_POWER_PATH_MODE_ENA			0x01
+#define BUS_PP_PRECHG_CURRENT_MASK		0x0E
+#define BUS_POWER_PATH_PRECHG_ENA		0x01
+
 /**
  * struct res_to_temp - defines one point in a temp to res curve. To
  * be used in battery packs that combines the identification resistor with a
@@ -283,6 +323,11 @@ struct ab8500_fg;
  *				points.
  * @maint_thres			This is the threshold where we stop reporting
  *				battery full while in maintenance, in per cent
+ * @pcut_enable:			Enable power cut feature in ab8505
+ * @pcut_max_time:		Max time threshold
+ * @pcut_flag_time:		Flagtime threshold
+ * @pcut_max_restart:		Max number of restarts
+ * @pcut_debunce_time:	Sets battery debounce time
  */
 struct ab8500_fg_parameters {
 	int recovery_sleep_timer;
@@ -299,6 +344,11 @@ struct ab8500_fg_parameters {
 	int battok_raising_th_sel1;
 	int user_cap_limit;
 	int maint_thres;
+	bool pcut_enable;
+	u8 pcut_max_time;
+	u8 pcut_flag_time;
+	u8 pcut_max_restart;
+	u8 pcut_debunce_time;
 };
 
 /**
diff --git a/include/linux/mfd/abx500/ab8500-gpadc.h b/include/linux/mfd/abx500/ab8500-gpadc.h
index 2529667..49ded00 100644
--- a/include/linux/mfd/abx500/ab8500-gpadc.h
+++ b/include/linux/mfd/abx500/ab8500-gpadc.h
@@ -4,32 +4,72 @@
  *
  * Author: Arun R Murthy <arun.murthy@stericsson.com>
  * Author: Daniel Willerud <daniel.willerud@stericsson.com>
+ * Author: M'boumba Cedric Madianga <cedric.madianga@stericsson.com>
  */
 
 #ifndef	_AB8500_GPADC_H
 #define _AB8500_GPADC_H
 
-/* GPADC source: From datasheet(ADCSwSel[4:0] in GPADCCtrl2) */
-#define BAT_CTRL	0x01
-#define BTEMP_BALL	0x02
-#define MAIN_CHARGER_V	0x03
-#define ACC_DETECT1	0x04
-#define ACC_DETECT2	0x05
-#define ADC_AUX1	0x06
-#define ADC_AUX2	0x07
-#define MAIN_BAT_V	0x08
-#define VBUS_V		0x09
-#define MAIN_CHARGER_C	0x0A
-#define USB_CHARGER_C	0x0B
-#define BK_BAT_V	0x0C
-#define DIE_TEMP	0x0D
+/* GPADC source: From datasheet(ADCSwSel[4:0] in GPADCCtrl2
+ * and ADCHwSel[4:0] in GPADCCtrl3 ) */
+#define BAT_CTRL		0x01
+#define BTEMP_BALL		0x02
+#define MAIN_CHARGER_V		0x03
+#define ACC_DETECT1		0x04
+#define ACC_DETECT2		0x05
+#define ADC_AUX1		0x06
+#define ADC_AUX2		0x07
+#define MAIN_BAT_V		0x08
+#define VBUS_V			0x09
+#define MAIN_CHARGER_C		0x0A
+#define USB_CHARGER_C		0x0B
+#define BK_BAT_V		0x0C
+#define DIE_TEMP		0x0D
+#define USB_ID			0x0E
+#define XTAL_TEMP		0x12
+#define VBAT_TRUE_MEAS		0x13
+#define BAT_CTRL_AND_IBAT	0x1C
+#define VBAT_MEAS_AND_IBAT	0x1D
+#define VBAT_TRUE_MEAS_AND_IBAT	0x1E
+#define BAT_TEMP_AND_IBAT	0x1F
+
+/* Virtual channel used only for ibat convertion to ampere
+ * Battery current conversion (ibat) cannot be requested as a single conversion
+ *  but it is always in combination with other input requests
+ */
+#define IBAT_VIRTUAL_CHANNEL		0xFF
+
+#define SAMPLE_1        1
+#define SAMPLE_4        4
+#define SAMPLE_8        8
+#define SAMPLE_16       16
+#define RISING_EDGE     0
+#define FALLING_EDGE    1
+
+/* Arbitrary ADC conversion type constants */
+#define ADC_SW				0
+#define ADC_HW				1
 
 struct ab8500_gpadc;
 
 struct ab8500_gpadc *ab8500_gpadc_get(char *name);
-int ab8500_gpadc_convert(struct ab8500_gpadc *gpadc, u8 channel);
-int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel);
+int ab8500_gpadc_sw_hw_convert(struct ab8500_gpadc *gpadc, u8 channel,
+		u8 avg_sample, u8 trig_edge, u8 trig_timer, u8 conv_type);
+static inline int ab8500_gpadc_convert(struct ab8500_gpadc *gpadc, u8 channel)
+{
+	return ab8500_gpadc_sw_hw_convert(gpadc, channel,
+			SAMPLE_16, 0, 0, ADC_SW);
+}
+
+int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel,
+		u8 avg_sample, u8 trig_edge, u8 trig_timer, u8 conv_type);
+int ab8500_gpadc_double_read_raw(struct ab8500_gpadc *gpadc, u8 channel,
+		u8 avg_sample, u8 trig_edge, u8 trig_timer, u8 conv_type,
+		int *ibat);
 int ab8500_gpadc_ad_to_voltage(struct ab8500_gpadc *gpadc,
-    u8 channel, int ad_value);
+		u8 channel, int ad_value);
+void ab8540_gpadc_get_otp(struct ab8500_gpadc *gpadc,
+			u16 *vmain_l, u16 *vmain_h, u16 *btemp_l, u16 *btemp_h,
+			u16 *vbat_l, u16 *vbat_h, u16 *ibat_l, u16 *ibat_h);
 
 #endif /* _AB8500_GPADC_H */
diff --git a/include/linux/mfd/abx500/ab8500-sysctrl.h b/include/linux/mfd/abx500/ab8500-sysctrl.h
index ebf12e7..990bc93 100644
--- a/include/linux/mfd/abx500/ab8500-sysctrl.h
+++ b/include/linux/mfd/abx500/ab8500-sysctrl.h
@@ -12,6 +12,7 @@
 
 int ab8500_sysctrl_read(u16 reg, u8 *value);
 int ab8500_sysctrl_write(u16 reg, u8 mask, u8 value);
+void ab8500_restart(char mode, const char *cmd);
 
 #else
 
@@ -40,6 +41,7 @@ static inline int ab8500_sysctrl_clear(u16 reg, u8 bits)
 /* Configuration data for SysClkReq1RfClkBuf - SysClkReq8RfClkBuf */
 struct ab8500_sysctrl_platform_data {
 	u8 initial_req_buf_config[8];
+	u16 (*reboot_reason_code)(const char *cmd);
 };
 
 /* Registers */
@@ -299,4 +301,8 @@ struct ab8500_sysctrl_platform_data {
 #define AB9540_SYSCLK12BUF4VALID_SYSCLK12BUF4VALID_MASK 0xFF
 #define AB9540_SYSCLK12BUF4VALID_SYSCLK12BUF4VALID_SHIFT 0
 
+#define AB8500_ENABLE_WD 0x1
+#define AB8500_KICK_WD 0x2
+#define AB8500_WD_RESTART_ON_EXPIRE 0x10
+
 #endif /* __AB8500_SYSCTRL_H */
diff --git a/include/linux/mfd/abx500/ab8500.h b/include/linux/mfd/abx500/ab8500.h
index 9db0bda..fb1bf7d 100644
--- a/include/linux/mfd/abx500/ab8500.h
+++ b/include/linux/mfd/abx500/ab8500.h
@@ -362,10 +362,10 @@ struct ab8500 {
 	u8 *oldmask;
 	int mask_size;
 	const int *irq_reg_offset;
+	int it_latchhier_num;
 };
 
-struct regulator_reg_init;
-struct regulator_init_data;
+struct ab8500_regulator_platform_data;
 struct ab8500_gpio_platform_data;
 struct ab8500_codec_platform_data;
 struct ab8500_sysctrl_platform_data;
@@ -375,19 +375,13 @@ struct ab8500_sysctrl_platform_data;
  * @irq_base: start of AB8500 IRQs, AB8500_NR_IRQS will be used
  * @pm_power_off: Should machine pm power off hook be registered or not
  * @init: board-specific initialization after detection of ab8500
- * @num_regulator_reg_init: number of regulator init registers
- * @regulator_reg_init: regulator init registers
- * @num_regulator: number of regulators
  * @regulator: machine-specific constraints for regulators
  */
 struct ab8500_platform_data {
 	int irq_base;
 	bool pm_power_off;
 	void (*init) (struct ab8500 *);
-	int num_regulator_reg_init;
-	struct ab8500_regulator_reg_init *regulator_reg_init;
-	int num_regulator;
-	struct regulator_init_data *regulator;
+	struct ab8500_regulator_platform_data *regulator;
 	struct abx500_gpio_platform_data *gpio;
 	struct ab8500_codec_platform_data *codec;
 	struct ab8500_sysctrl_platform_data *sysctrl;
@@ -512,6 +506,8 @@ static inline int is_ab9540_2p0_or_earlier(struct ab8500 *ab)
 	return (is_ab9540(ab) && (ab->chip_id < AB8500_CUT2P0));
 }
 
+void ab8500_override_turn_on_stat(u8 mask, u8 set);
+
 #ifdef CONFIG_AB8500_DEBUG
 void ab8500_dump_all_banks(struct device *dev);
 void ab8500_debug_register_interrupt(int line);
diff --git a/include/linux/mfd/abx500/ux500_chargalg.h b/include/linux/mfd/abx500/ux500_chargalg.h
index d43ac0f..234c991 100644
--- a/include/linux/mfd/abx500/ux500_chargalg.h
+++ b/include/linux/mfd/abx500/ux500_chargalg.h
@@ -17,8 +17,11 @@ struct ux500_charger;
 
 struct ux500_charger_ops {
 	int (*enable) (struct ux500_charger *, int, int, int);
+	int (*check_enable) (struct ux500_charger *, int, int);
 	int (*kick_wd) (struct ux500_charger *);
 	int (*update_curr) (struct ux500_charger *, int);
+	int (*pp_enable) (struct ux500_charger *, bool);
+	int (*pre_chg_enable) (struct ux500_charger *, bool);
 };
 
 /**
@@ -29,6 +32,7 @@ struct ux500_charger_ops {
  * @max_out_curr	maximum output charger current in mA
  * @enabled		indicates if this charger is used or not
  * @external		external charger unit (pm2xxx)
+ * @power_path		USB power path support
  */
 struct ux500_charger {
 	struct power_supply psy;
@@ -38,6 +42,9 @@ struct ux500_charger {
 	int wdt_refresh;
 	bool enabled;
 	bool external;
+	bool power_path;
 };
 
+extern struct blocking_notifier_head charger_notifier_list;
+
 #endif
diff --git a/include/linux/mfd/arizona/core.h b/include/linux/mfd/arizona/core.h
index a710255..cc28136 100644
--- a/include/linux/mfd/arizona/core.h
+++ b/include/linux/mfd/arizona/core.h
@@ -100,6 +100,9 @@ struct arizona {
 	struct regmap_irq_chip_data *aod_irq_chip;
 	struct regmap_irq_chip_data *irq_chip;
 
+	bool hpdet_magic;
+	unsigned int hp_ena;
+
 	struct mutex clk_lock;
 	int clk32k_ref;
 
diff --git a/include/linux/mfd/arizona/pdata.h b/include/linux/mfd/arizona/pdata.h
index 455c51d..a0f9409 100644
--- a/include/linux/mfd/arizona/pdata.h
+++ b/include/linux/mfd/arizona/pdata.h
@@ -86,6 +86,11 @@ struct arizona_micd_config {
 	bool gpio;
 };
 
+struct arizona_micd_range {
+	int max;  /** Ohms */
+	int key;  /** Key to report to input layer */
+};
+
 struct arizona_pdata {
 	int reset;      /** GPIO controlling /RESET, if any */
 	int ldoena;     /** GPIO controlling LODENA, if any */
@@ -117,12 +122,21 @@ struct arizona_pdata {
 	/** GPIO5 is used for jack detection */
 	bool jd_gpio5;
 
+	/** Internal pull on GPIO5 is disabled when used for jack detection */
+	bool jd_gpio5_nopull;
+
 	/** Use the headphone detect circuit to identify the accessory */
 	bool hpdet_acc_id;
 
+	/** Check for line output with HPDET method */
+	bool hpdet_acc_id_line;
+
 	/** GPIO used for mic isolation with HPDET */
 	int hpdet_id_gpio;
 
+	/** Extra debounce timeout used during initial mic detection (ms) */
+	int micd_detect_debounce;
+
 	/** GPIO for mic detection polarity */
 	int micd_pol_gpio;
 
@@ -135,9 +149,16 @@ struct arizona_pdata {
 	/** Mic detect debounce level */
 	int micd_dbtime;
 
+	/** Mic detect timeout (ms) */
+	int micd_timeout;
+
 	/** Force MICBIAS on for mic detect */
 	bool micd_force_micbias;
 
+	/** Mic detect level parameters */
+	const struct arizona_micd_range *micd_ranges;
+	int num_micd_ranges;
+
 	/** Headset polarity configurations */
 	struct arizona_micd_config *micd_configs;
 	int num_micd_configs;
diff --git a/include/linux/mfd/arizona/registers.h b/include/linux/mfd/arizona/registers.h
index 3403551..715b6ba 100644
--- a/include/linux/mfd/arizona/registers.h
+++ b/include/linux/mfd/arizona/registers.h
@@ -85,12 +85,14 @@
 #define ARIZONA_FLL1_CONTROL_6                   0x176
 #define ARIZONA_FLL1_LOOP_FILTER_TEST_1          0x177
 #define ARIZONA_FLL1_NCO_TEST_0                  0x178
+#define ARIZONA_FLL1_CONTROL_7                   0x179
 #define ARIZONA_FLL1_SYNCHRONISER_1              0x181
 #define ARIZONA_FLL1_SYNCHRONISER_2              0x182
 #define ARIZONA_FLL1_SYNCHRONISER_3              0x183
 #define ARIZONA_FLL1_SYNCHRONISER_4              0x184
 #define ARIZONA_FLL1_SYNCHRONISER_5              0x185
 #define ARIZONA_FLL1_SYNCHRONISER_6              0x186
+#define ARIZONA_FLL1_SYNCHRONISER_7              0x187
 #define ARIZONA_FLL1_SPREAD_SPECTRUM             0x189
 #define ARIZONA_FLL1_GPIO_CLOCK                  0x18A
 #define ARIZONA_FLL2_CONTROL_1                   0x191
@@ -101,12 +103,14 @@
 #define ARIZONA_FLL2_CONTROL_6                   0x196
 #define ARIZONA_FLL2_LOOP_FILTER_TEST_1          0x197
 #define ARIZONA_FLL2_NCO_TEST_0                  0x198
+#define ARIZONA_FLL2_CONTROL_7                   0x199
 #define ARIZONA_FLL2_SYNCHRONISER_1              0x1A1
 #define ARIZONA_FLL2_SYNCHRONISER_2              0x1A2
 #define ARIZONA_FLL2_SYNCHRONISER_3              0x1A3
 #define ARIZONA_FLL2_SYNCHRONISER_4              0x1A4
 #define ARIZONA_FLL2_SYNCHRONISER_5              0x1A5
 #define ARIZONA_FLL2_SYNCHRONISER_6              0x1A6
+#define ARIZONA_FLL2_SYNCHRONISER_7              0x1A7
 #define ARIZONA_FLL2_SPREAD_SPECTRUM             0x1A9
 #define ARIZONA_FLL2_GPIO_CLOCK                  0x1AA
 #define ARIZONA_MIC_CHARGE_PUMP_1                0x200
@@ -124,6 +128,10 @@
 #define ARIZONA_MIC_DETECT_1                     0x2A3
 #define ARIZONA_MIC_DETECT_2                     0x2A4
 #define ARIZONA_MIC_DETECT_3                     0x2A5
+#define ARIZONA_MIC_DETECT_LEVEL_1		 0x2A6
+#define ARIZONA_MIC_DETECT_LEVEL_2		 0x2A7
+#define ARIZONA_MIC_DETECT_LEVEL_3		 0x2A8
+#define ARIZONA_MIC_DETECT_LEVEL_4		 0x2A9
 #define ARIZONA_MIC_NOISE_MIX_CONTROL_1          0x2C3
 #define ARIZONA_ISOLATION_CONTROL                0x2CB
 #define ARIZONA_JACK_DETECT_ANALOGUE             0x2D3
@@ -213,6 +221,8 @@
 #define ARIZONA_PDM_SPK1_CTRL_2                  0x491
 #define ARIZONA_PDM_SPK2_CTRL_1                  0x492
 #define ARIZONA_PDM_SPK2_CTRL_2                  0x493
+#define ARIZONA_SPK_CTRL_2                       0x4B5
+#define ARIZONA_SPK_CTRL_3                       0x4B6
 #define ARIZONA_DAC_COMP_1                       0x4DC
 #define ARIZONA_DAC_COMP_2                       0x4DD
 #define ARIZONA_DAC_COMP_3                       0x4DE
@@ -1678,6 +1688,13 @@
 #define ARIZONA_FLL1_FRC_INTEG_VAL_WIDTH             12  /* FLL1_FRC_INTEG_VAL - [11:0] */
 
 /*
+ * R377 (0x179) - FLL1 Control 7
+ */
+#define ARIZONA_FLL1_GAIN_MASK                   0x003c  /* FLL1_GAIN */
+#define ARIZONA_FLL1_GAIN_SHIFT                       2  /* FLL1_GAIN */
+#define ARIZONA_FLL1_GAIN_WIDTH                       4  /* FLL1_GAIN */
+
+/*
  * R385 (0x181) - FLL1 Synchroniser 1
  */
 #define ARIZONA_FLL1_SYNC_ENA                    0x0001  /* FLL1_SYNC_ENA */
@@ -1724,6 +1741,17 @@
 #define ARIZONA_FLL1_CLK_SYNC_SRC_WIDTH               4  /* FLL1_CLK_SYNC_SRC - [3:0] */
 
 /*
+ * R391 (0x187) - FLL1 Synchroniser 7
+ */
+#define ARIZONA_FLL1_SYNC_GAIN_MASK              0x003c  /* FLL1_SYNC_GAIN */
+#define ARIZONA_FLL1_SYNC_GAIN_SHIFT                  2  /* FLL1_SYNC_GAIN */
+#define ARIZONA_FLL1_SYNC_GAIN_WIDTH                  4  /* FLL1_SYNC_GAIN */
+#define ARIZONA_FLL1_SYNC_BW                     0x0001  /* FLL1_SYNC_BW */
+#define ARIZONA_FLL1_SYNC_BW_MASK                0x0001  /* FLL1_SYNC_BW */
+#define ARIZONA_FLL1_SYNC_BW_SHIFT                    0  /* FLL1_SYNC_BW */
+#define ARIZONA_FLL1_SYNC_BW_WIDTH                    1  /* FLL1_SYNC_BW */
+
+/*
  * R393 (0x189) - FLL1 Spread Spectrum
  */
 #define ARIZONA_FLL1_SS_AMPL_MASK                0x0030  /* FLL1_SS_AMPL - [5:4] */
@@ -1816,6 +1844,13 @@
 #define ARIZONA_FLL2_FRC_INTEG_VAL_WIDTH             12  /* FLL2_FRC_INTEG_VAL - [11:0] */
 
 /*
+ * R409 (0x199) - FLL2 Control 7
+ */
+#define ARIZONA_FLL2_GAIN_MASK                   0x003c  /* FLL2_GAIN */
+#define ARIZONA_FLL2_GAIN_SHIFT                       2  /* FLL2_GAIN */
+#define ARIZONA_FLL2_GAIN_WIDTH                       4  /* FLL2_GAIN */
+
+/*
  * R417 (0x1A1) - FLL2 Synchroniser 1
  */
 #define ARIZONA_FLL2_SYNC_ENA                    0x0001  /* FLL2_SYNC_ENA */
@@ -1862,6 +1897,17 @@
 #define ARIZONA_FLL2_CLK_SYNC_SRC_WIDTH               4  /* FLL2_CLK_SYNC_SRC - [3:0] */
 
 /*
+ * R423 (0x1A7) - FLL2 Synchroniser 7
+ */
+#define ARIZONA_FLL2_SYNC_GAIN_MASK              0x003c  /* FLL2_SYNC_GAIN */
+#define ARIZONA_FLL2_SYNC_GAIN_SHIFT                  2  /* FLL2_SYNC_GAIN */
+#define ARIZONA_FLL2_SYNC_GAIN_WIDTH                  4  /* FLL2_SYNC_GAIN */
+#define ARIZONA_FLL2_SYNC_BW_MASK                0x0001  /* FLL2_SYNC_BW */
+#define ARIZONA_FLL2_SYNC_BW_MASK                0x0001  /* FLL2_SYNC_BW */
+#define ARIZONA_FLL2_SYNC_BW_SHIFT                    0  /* FLL2_SYNC_BW */
+#define ARIZONA_FLL2_SYNC_BW_WIDTH                    1  /* FLL2_SYNC_BW */
+
+/*
  * R425 (0x1A9) - FLL2 Spread Spectrum
  */
 #define ARIZONA_FLL2_SS_AMPL_MASK                0x0030  /* FLL2_SS_AMPL - [5:4] */
diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
new file mode 100644
index 0000000..032af7f
--- /dev/null
+++ b/include/linux/mfd/cros_ec.h
@@ -0,0 +1,170 @@
+/*
+ * ChromeOS EC multi-function device
+ *
+ * Copyright (C) 2012 Google, 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 __LINUX_MFD_CROS_EC_H
+#define __LINUX_MFD_CROS_EC_H
+
+#include <linux/mfd/cros_ec_commands.h>
+
+/*
+ * Command interface between EC and AP, for LPC, I2C and SPI interfaces.
+ */
+enum {
+	EC_MSG_TX_HEADER_BYTES	= 3,
+	EC_MSG_TX_TRAILER_BYTES	= 1,
+	EC_MSG_TX_PROTO_BYTES	= EC_MSG_TX_HEADER_BYTES +
+					EC_MSG_TX_TRAILER_BYTES,
+	EC_MSG_RX_PROTO_BYTES	= 3,
+
+	/* Max length of messages */
+	EC_MSG_BYTES		= EC_HOST_PARAM_SIZE + EC_MSG_TX_PROTO_BYTES,
+
+};
+
+/**
+ * struct cros_ec_msg - A message sent to the EC, and its reply
+ *
+ * @version: Command version number (often 0)
+ * @cmd: Command to send (EC_CMD_...)
+ * @out_buf: Outgoing payload (to EC)
+ * @outlen: Outgoing length
+ * @in_buf: Incoming payload (from EC)
+ * @in_len: Incoming length
+ */
+struct cros_ec_msg {
+	u8 version;
+	u8 cmd;
+	uint8_t *out_buf;
+	int out_len;
+	uint8_t *in_buf;
+	int in_len;
+};
+
+/**
+ * struct cros_ec_device - Information about a ChromeOS EC device
+ *
+ * @name: Name of this EC interface
+ * @priv: Private data
+ * @irq: Interrupt to use
+ * @din: input buffer (from EC)
+ * @dout: output buffer (to EC)
+ * \note
+ * These two buffers will always be dword-aligned and include enough
+ * space for up to 7 word-alignment bytes also, so we can ensure that
+ * the body of the message is always dword-aligned (64-bit).
+ *
+ * We use this alignment to keep ARM and x86 happy. Probably word
+ * alignment would be OK, there might be a small performance advantage
+ * to using dword.
+ * @din_size: size of din buffer
+ * @dout_size: size of dout buffer
+ * @command_send: send a command
+ * @command_recv: receive a command
+ * @ec_name: name of EC device (e.g. 'chromeos-ec')
+ * @phys_name: name of physical comms layer (e.g. 'i2c-4')
+ * @parent: pointer to parent device (e.g. i2c or spi device)
+ * @dev: Device pointer
+ * dev_lock: Lock to prevent concurrent access
+ * @wake_enabled: true if this device can wake the system from sleep
+ * @was_wake_device: true if this device was set to wake the system from
+ * sleep at the last suspend
+ * @event_notifier: interrupt event notifier for transport devices
+ */
+struct cros_ec_device {
+	const char *name;
+	void *priv;
+	int irq;
+	uint8_t *din;
+	uint8_t *dout;
+	int din_size;
+	int dout_size;
+	int (*command_send)(struct cros_ec_device *ec,
+			uint16_t cmd, void *out_buf, int out_len);
+	int (*command_recv)(struct cros_ec_device *ec,
+			uint16_t cmd, void *in_buf, int in_len);
+	int (*command_sendrecv)(struct cros_ec_device *ec,
+			uint16_t cmd, void *out_buf, int out_len,
+			void *in_buf, int in_len);
+	int (*command_xfer)(struct cros_ec_device *ec,
+			struct cros_ec_msg *msg);
+
+	const char *ec_name;
+	const char *phys_name;
+	struct device *parent;
+
+	/* These are --private-- fields - do not assign */
+	struct device *dev;
+	struct mutex dev_lock;
+	bool wake_enabled;
+	bool was_wake_device;
+	struct blocking_notifier_head event_notifier;
+};
+
+/**
+ * cros_ec_suspend - Handle a suspend operation for the ChromeOS EC device
+ *
+ * This can be called by drivers to handle a suspend event.
+ *
+ * ec_dev: Device to suspend
+ * @return 0 if ok, -ve on error
+ */
+int cros_ec_suspend(struct cros_ec_device *ec_dev);
+
+/**
+ * cros_ec_resume - Handle a resume operation for the ChromeOS EC device
+ *
+ * This can be called by drivers to handle a resume event.
+ *
+ * @ec_dev: Device to resume
+ * @return 0 if ok, -ve on error
+ */
+int cros_ec_resume(struct cros_ec_device *ec_dev);
+
+/**
+ * cros_ec_prepare_tx - Prepare an outgoing message in the output buffer
+ *
+ * This is intended to be used by all ChromeOS EC drivers, but at present
+ * only SPI uses it. Once LPC uses the same protocol it can start using it.
+ * I2C could use it now, with a refactor of the existing code.
+ *
+ * @ec_dev: Device to register
+ * @msg: Message to write
+ */
+int cros_ec_prepare_tx(struct cros_ec_device *ec_dev,
+		       struct cros_ec_msg *msg);
+
+/**
+ * cros_ec_remove - Remove a ChromeOS EC
+ *
+ * Call this to deregister a ChromeOS EC. After this you should call
+ * cros_ec_free().
+ *
+ * @ec_dev: Device to register
+ * @return 0 if ok, -ve on error
+ */
+int cros_ec_remove(struct cros_ec_device *ec_dev);
+
+/**
+ * cros_ec_register - Register a new ChromeOS EC, using the provided info
+ *
+ * Before calling this, allocate a pointer to a new device and then fill
+ * in all the fields up to the --private-- marker.
+ *
+ * @ec_dev: Device to register
+ * @return 0 if ok, -ve on error
+ */
+int cros_ec_register(struct cros_ec_device *ec_dev);
+
+#endif /* __LINUX_MFD_CROS_EC_H */
diff --git a/include/linux/mfd/cros_ec_commands.h b/include/linux/mfd/cros_ec_commands.h
new file mode 100644
index 0000000..86fd069
--- /dev/null
+++ b/include/linux/mfd/cros_ec_commands.h
@@ -0,0 +1,1369 @@
+/*
+ * Host communication command constants for ChromeOS EC
+ *
+ * Copyright (C) 2012 Google, 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.
+ *
+ * The ChromeOS EC multi function device is used to mux all the requests
+ * to the EC device for its multiple features: keyboard controller,
+ * battery charging and regulator control, firmware update.
+ *
+ * NOTE: This file is copied verbatim from the ChromeOS EC Open Source
+ * project in an attempt to make future updates easy to make.
+ */
+
+#ifndef __CROS_EC_COMMANDS_H
+#define __CROS_EC_COMMANDS_H
+
+/*
+ * Protocol overview
+ *
+ * request:  CMD [ P0 P1 P2 ... Pn S ]
+ * response: ERR [ P0 P1 P2 ... Pn S ]
+ *
+ * where the bytes are defined as follow :
+ *      - CMD is the command code. (defined by EC_CMD_ constants)
+ *      - ERR is the error code. (defined by EC_RES_ constants)
+ *      - Px is the optional payload.
+ *        it is not sent if the error code is not success.
+ *        (defined by ec_params_ and ec_response_ structures)
+ *      - S is the checksum which is the sum of all payload bytes.
+ *
+ * On LPC, CMD and ERR are sent/received at EC_LPC_ADDR_KERNEL|USER_CMD
+ * and the payloads are sent/received at EC_LPC_ADDR_KERNEL|USER_PARAM.
+ * On I2C, all bytes are sent serially in the same message.
+ */
+
+/* Current version of this protocol */
+#define EC_PROTO_VERSION          0x00000002
+
+/* Command version mask */
+#define EC_VER_MASK(version) (1UL << (version))
+
+/* I/O addresses for ACPI commands */
+#define EC_LPC_ADDR_ACPI_DATA  0x62
+#define EC_LPC_ADDR_ACPI_CMD   0x66
+
+/* I/O addresses for host command */
+#define EC_LPC_ADDR_HOST_DATA  0x200
+#define EC_LPC_ADDR_HOST_CMD   0x204
+
+/* I/O addresses for host command args and params */
+#define EC_LPC_ADDR_HOST_ARGS  0x800
+#define EC_LPC_ADDR_HOST_PARAM 0x804
+#define EC_HOST_PARAM_SIZE     0x0fc  /* Size of param area in bytes */
+
+/* I/O addresses for host command params, old interface */
+#define EC_LPC_ADDR_OLD_PARAM  0x880
+#define EC_OLD_PARAM_SIZE      0x080  /* Size of param area in bytes */
+
+/* EC command register bit functions */
+#define EC_LPC_CMDR_DATA	(1 << 0)  /* Data ready for host to read */
+#define EC_LPC_CMDR_PENDING	(1 << 1)  /* Write pending to EC */
+#define EC_LPC_CMDR_BUSY	(1 << 2)  /* EC is busy processing a command */
+#define EC_LPC_CMDR_CMD		(1 << 3)  /* Last host write was a command */
+#define EC_LPC_CMDR_ACPI_BRST	(1 << 4)  /* Burst mode (not used) */
+#define EC_LPC_CMDR_SCI		(1 << 5)  /* SCI event is pending */
+#define EC_LPC_CMDR_SMI		(1 << 6)  /* SMI event is pending */
+
+#define EC_LPC_ADDR_MEMMAP       0x900
+#define EC_MEMMAP_SIZE         255 /* ACPI IO buffer max is 255 bytes */
+#define EC_MEMMAP_TEXT_MAX     8   /* Size of a string in the memory map */
+
+/* The offset address of each type of data in mapped memory. */
+#define EC_MEMMAP_TEMP_SENSOR      0x00 /* Temp sensors */
+#define EC_MEMMAP_FAN              0x10 /* Fan speeds */
+#define EC_MEMMAP_TEMP_SENSOR_B    0x18 /* Temp sensors (second set) */
+#define EC_MEMMAP_ID               0x20 /* 'E' 'C' */
+#define EC_MEMMAP_ID_VERSION       0x22 /* Version of data in 0x20 - 0x2f */
+#define EC_MEMMAP_THERMAL_VERSION  0x23 /* Version of data in 0x00 - 0x1f */
+#define EC_MEMMAP_BATTERY_VERSION  0x24 /* Version of data in 0x40 - 0x7f */
+#define EC_MEMMAP_SWITCHES_VERSION 0x25 /* Version of data in 0x30 - 0x33 */
+#define EC_MEMMAP_EVENTS_VERSION   0x26 /* Version of data in 0x34 - 0x3f */
+#define EC_MEMMAP_HOST_CMD_FLAGS   0x27 /* Host command interface flags */
+#define EC_MEMMAP_SWITCHES         0x30
+#define EC_MEMMAP_HOST_EVENTS      0x34
+#define EC_MEMMAP_BATT_VOLT        0x40 /* Battery Present Voltage */
+#define EC_MEMMAP_BATT_RATE        0x44 /* Battery Present Rate */
+#define EC_MEMMAP_BATT_CAP         0x48 /* Battery Remaining Capacity */
+#define EC_MEMMAP_BATT_FLAG        0x4c /* Battery State, defined below */
+#define EC_MEMMAP_BATT_DCAP        0x50 /* Battery Design Capacity */
+#define EC_MEMMAP_BATT_DVLT        0x54 /* Battery Design Voltage */
+#define EC_MEMMAP_BATT_LFCC        0x58 /* Battery Last Full Charge Capacity */
+#define EC_MEMMAP_BATT_CCNT        0x5c /* Battery Cycle Count */
+#define EC_MEMMAP_BATT_MFGR        0x60 /* Battery Manufacturer String */
+#define EC_MEMMAP_BATT_MODEL       0x68 /* Battery Model Number String */
+#define EC_MEMMAP_BATT_SERIAL      0x70 /* Battery Serial Number String */
+#define EC_MEMMAP_BATT_TYPE        0x78 /* Battery Type String */
+
+/* Number of temp sensors at EC_MEMMAP_TEMP_SENSOR */
+#define EC_TEMP_SENSOR_ENTRIES     16
+/*
+ * Number of temp sensors at EC_MEMMAP_TEMP_SENSOR_B.
+ *
+ * Valid only if EC_MEMMAP_THERMAL_VERSION returns >= 2.
+ */
+#define EC_TEMP_SENSOR_B_ENTRIES      8
+#define EC_TEMP_SENSOR_NOT_PRESENT    0xff
+#define EC_TEMP_SENSOR_ERROR          0xfe
+#define EC_TEMP_SENSOR_NOT_POWERED    0xfd
+#define EC_TEMP_SENSOR_NOT_CALIBRATED 0xfc
+/*
+ * The offset of temperature value stored in mapped memory.  This allows
+ * reporting a temperature range of 200K to 454K = -73C to 181C.
+ */
+#define EC_TEMP_SENSOR_OFFSET      200
+
+#define EC_FAN_SPEED_ENTRIES       4       /* Number of fans at EC_MEMMAP_FAN */
+#define EC_FAN_SPEED_NOT_PRESENT   0xffff  /* Entry not present */
+#define EC_FAN_SPEED_STALLED       0xfffe  /* Fan stalled */
+
+/* Battery bit flags at EC_MEMMAP_BATT_FLAG. */
+#define EC_BATT_FLAG_AC_PRESENT   0x01
+#define EC_BATT_FLAG_BATT_PRESENT 0x02
+#define EC_BATT_FLAG_DISCHARGING  0x04
+#define EC_BATT_FLAG_CHARGING     0x08
+#define EC_BATT_FLAG_LEVEL_CRITICAL 0x10
+
+/* Switch flags at EC_MEMMAP_SWITCHES */
+#define EC_SWITCH_LID_OPEN               0x01
+#define EC_SWITCH_POWER_BUTTON_PRESSED   0x02
+#define EC_SWITCH_WRITE_PROTECT_DISABLED 0x04
+/* Recovery requested via keyboard */
+#define EC_SWITCH_KEYBOARD_RECOVERY      0x08
+/* Recovery requested via dedicated signal (from servo board) */
+#define EC_SWITCH_DEDICATED_RECOVERY     0x10
+/* Was fake developer mode switch; now unused.  Remove in next refactor. */
+#define EC_SWITCH_IGNORE0                0x20
+
+/* Host command interface flags */
+/* Host command interface supports LPC args (LPC interface only) */
+#define EC_HOST_CMD_FLAG_LPC_ARGS_SUPPORTED  0x01
+
+/* Wireless switch flags */
+#define EC_WIRELESS_SWITCH_WLAN      0x01
+#define EC_WIRELESS_SWITCH_BLUETOOTH 0x02
+
+/*
+ * This header file is used in coreboot both in C and ACPI code.  The ACPI code
+ * is pre-processed to handle constants but the ASL compiler is unable to
+ * handle actual C code so keep it separate.
+ */
+#ifndef __ACPI__
+
+/* LPC command status byte masks */
+/* EC has written a byte in the data register and host hasn't read it yet */
+#define EC_LPC_STATUS_TO_HOST     0x01
+/* Host has written a command/data byte and the EC hasn't read it yet */
+#define EC_LPC_STATUS_FROM_HOST   0x02
+/* EC is processing a command */
+#define EC_LPC_STATUS_PROCESSING  0x04
+/* Last write to EC was a command, not data */
+#define EC_LPC_STATUS_LAST_CMD    0x08
+/* EC is in burst mode.  Unsupported by Chrome EC, so this bit is never set */
+#define EC_LPC_STATUS_BURST_MODE  0x10
+/* SCI event is pending (requesting SCI query) */
+#define EC_LPC_STATUS_SCI_PENDING 0x20
+/* SMI event is pending (requesting SMI query) */
+#define EC_LPC_STATUS_SMI_PENDING 0x40
+/* (reserved) */
+#define EC_LPC_STATUS_RESERVED    0x80
+
+/*
+ * EC is busy.  This covers both the EC processing a command, and the host has
+ * written a new command but the EC hasn't picked it up yet.
+ */
+#define EC_LPC_STATUS_BUSY_MASK \
+	(EC_LPC_STATUS_FROM_HOST | EC_LPC_STATUS_PROCESSING)
+
+/* Host command response codes */
+enum ec_status {
+	EC_RES_SUCCESS = 0,
+	EC_RES_INVALID_COMMAND = 1,
+	EC_RES_ERROR = 2,
+	EC_RES_INVALID_PARAM = 3,
+	EC_RES_ACCESS_DENIED = 4,
+	EC_RES_INVALID_RESPONSE = 5,
+	EC_RES_INVALID_VERSION = 6,
+	EC_RES_INVALID_CHECKSUM = 7,
+	EC_RES_IN_PROGRESS = 8,		/* Accepted, command in progress */
+	EC_RES_UNAVAILABLE = 9,		/* No response available */
+	EC_RES_TIMEOUT = 10,		/* We got a timeout */
+	EC_RES_OVERFLOW = 11,		/* Table / data overflow */
+};
+
+/*
+ * Host event codes.  Note these are 1-based, not 0-based, because ACPI query
+ * EC command uses code 0 to mean "no event pending".  We explicitly specify
+ * each value in the enum listing so they won't change if we delete/insert an
+ * item or rearrange the list (it needs to be stable across platforms, not
+ * just within a single compiled instance).
+ */
+enum host_event_code {
+	EC_HOST_EVENT_LID_CLOSED = 1,
+	EC_HOST_EVENT_LID_OPEN = 2,
+	EC_HOST_EVENT_POWER_BUTTON = 3,
+	EC_HOST_EVENT_AC_CONNECTED = 4,
+	EC_HOST_EVENT_AC_DISCONNECTED = 5,
+	EC_HOST_EVENT_BATTERY_LOW = 6,
+	EC_HOST_EVENT_BATTERY_CRITICAL = 7,
+	EC_HOST_EVENT_BATTERY = 8,
+	EC_HOST_EVENT_THERMAL_THRESHOLD = 9,
+	EC_HOST_EVENT_THERMAL_OVERLOAD = 10,
+	EC_HOST_EVENT_THERMAL = 11,
+	EC_HOST_EVENT_USB_CHARGER = 12,
+	EC_HOST_EVENT_KEY_PRESSED = 13,
+	/*
+	 * EC has finished initializing the host interface.  The host can check
+	 * for this event following sending a EC_CMD_REBOOT_EC command to
+	 * determine when the EC is ready to accept subsequent commands.
+	 */
+	EC_HOST_EVENT_INTERFACE_READY = 14,
+	/* Keyboard recovery combo has been pressed */
+	EC_HOST_EVENT_KEYBOARD_RECOVERY = 15,
+
+	/* Shutdown due to thermal overload */
+	EC_HOST_EVENT_THERMAL_SHUTDOWN = 16,
+	/* Shutdown due to battery level too low */
+	EC_HOST_EVENT_BATTERY_SHUTDOWN = 17,
+
+	/*
+	 * The high bit of the event mask is not used as a host event code.  If
+	 * it reads back as set, then the entire event mask should be
+	 * considered invalid by the host.  This can happen when reading the
+	 * raw event status via EC_MEMMAP_HOST_EVENTS but the LPC interface is
+	 * not initialized on the EC, or improperly configured on the host.
+	 */
+	EC_HOST_EVENT_INVALID = 32
+};
+/* Host event mask */
+#define EC_HOST_EVENT_MASK(event_code) (1UL << ((event_code) - 1))
+
+/* Arguments at EC_LPC_ADDR_HOST_ARGS */
+struct ec_lpc_host_args {
+	uint8_t flags;
+	uint8_t command_version;
+	uint8_t data_size;
+	/*
+	 * Checksum; sum of command + flags + command_version + data_size +
+	 * all params/response data bytes.
+	 */
+	uint8_t checksum;
+} __packed;
+
+/* Flags for ec_lpc_host_args.flags */
+/*
+ * Args are from host.  Data area at EC_LPC_ADDR_HOST_PARAM contains command
+ * params.
+ *
+ * If EC gets a command and this flag is not set, this is an old-style command.
+ * Command version is 0 and params from host are at EC_LPC_ADDR_OLD_PARAM with
+ * unknown length.  EC must respond with an old-style response (that is,
+ * withouth setting EC_HOST_ARGS_FLAG_TO_HOST).
+ */
+#define EC_HOST_ARGS_FLAG_FROM_HOST 0x01
+/*
+ * Args are from EC.  Data area at EC_LPC_ADDR_HOST_PARAM contains response.
+ *
+ * If EC responds to a command and this flag is not set, this is an old-style
+ * response.  Command version is 0 and response data from EC is at
+ * EC_LPC_ADDR_OLD_PARAM with unknown length.
+ */
+#define EC_HOST_ARGS_FLAG_TO_HOST   0x02
+
+/*
+ * Notes on commands:
+ *
+ * Each command is an 8-byte command value.  Commands which take params or
+ * return response data specify structs for that data.  If no struct is
+ * specified, the command does not input or output data, respectively.
+ * Parameter/response length is implicit in the structs.  Some underlying
+ * communication protocols (I2C, SPI) may add length or checksum headers, but
+ * those are implementation-dependent and not defined here.
+ */
+
+/*****************************************************************************/
+/* General / test commands */
+
+/*
+ * Get protocol version, used to deal with non-backward compatible protocol
+ * changes.
+ */
+#define EC_CMD_PROTO_VERSION 0x00
+
+struct ec_response_proto_version {
+	uint32_t version;
+} __packed;
+
+/*
+ * Hello.  This is a simple command to test the EC is responsive to
+ * commands.
+ */
+#define EC_CMD_HELLO 0x01
+
+struct ec_params_hello {
+	uint32_t in_data;  /* Pass anything here */
+} __packed;
+
+struct ec_response_hello {
+	uint32_t out_data;  /* Output will be in_data + 0x01020304 */
+} __packed;
+
+/* Get version number */
+#define EC_CMD_GET_VERSION 0x02
+
+enum ec_current_image {
+	EC_IMAGE_UNKNOWN = 0,
+	EC_IMAGE_RO,
+	EC_IMAGE_RW
+};
+
+struct ec_response_get_version {
+	/* Null-terminated version strings for RO, RW */
+	char version_string_ro[32];
+	char version_string_rw[32];
+	char reserved[32];       /* Was previously RW-B string */
+	uint32_t current_image;  /* One of ec_current_image */
+} __packed;
+
+/* Read test */
+#define EC_CMD_READ_TEST 0x03
+
+struct ec_params_read_test {
+	uint32_t offset;   /* Starting value for read buffer */
+	uint32_t size;     /* Size to read in bytes */
+} __packed;
+
+struct ec_response_read_test {
+	uint32_t data[32];
+} __packed;
+
+/*
+ * Get build information
+ *
+ * Response is null-terminated string.
+ */
+#define EC_CMD_GET_BUILD_INFO 0x04
+
+/* Get chip info */
+#define EC_CMD_GET_CHIP_INFO 0x05
+
+struct ec_response_get_chip_info {
+	/* Null-terminated strings */
+	char vendor[32];
+	char name[32];
+	char revision[32];  /* Mask version */
+} __packed;
+
+/* Get board HW version */
+#define EC_CMD_GET_BOARD_VERSION 0x06
+
+struct ec_response_board_version {
+	uint16_t board_version;  /* A monotonously incrementing number. */
+} __packed;
+
+/*
+ * Read memory-mapped data.
+ *
+ * This is an alternate interface to memory-mapped data for bus protocols
+ * which don't support direct-mapped memory - I2C, SPI, etc.
+ *
+ * Response is params.size bytes of data.
+ */
+#define EC_CMD_READ_MEMMAP 0x07
+
+struct ec_params_read_memmap {
+	uint8_t offset;   /* Offset in memmap (EC_MEMMAP_*) */
+	uint8_t size;     /* Size to read in bytes */
+} __packed;
+
+/* Read versions supported for a command */
+#define EC_CMD_GET_CMD_VERSIONS 0x08
+
+struct ec_params_get_cmd_versions {
+	uint8_t cmd;      /* Command to check */
+} __packed;
+
+struct ec_response_get_cmd_versions {
+	/*
+	 * Mask of supported versions; use EC_VER_MASK() to compare with a
+	 * desired version.
+	 */
+	uint32_t version_mask;
+} __packed;
+
+/*
+ * Check EC communcations status (busy). This is needed on i2c/spi but not
+ * on lpc since it has its own out-of-band busy indicator.
+ *
+ * lpc must read the status from the command register. Attempting this on
+ * lpc will overwrite the args/parameter space and corrupt its data.
+ */
+#define EC_CMD_GET_COMMS_STATUS		0x09
+
+/* Avoid using ec_status which is for return values */
+enum ec_comms_status {
+	EC_COMMS_STATUS_PROCESSING	= 1 << 0,	/* Processing cmd */
+};
+
+struct ec_response_get_comms_status {
+	uint32_t flags;		/* Mask of enum ec_comms_status */
+} __packed;
+
+
+/*****************************************************************************/
+/* Flash commands */
+
+/* Get flash info */
+#define EC_CMD_FLASH_INFO 0x10
+
+struct ec_response_flash_info {
+	/* Usable flash size, in bytes */
+	uint32_t flash_size;
+	/*
+	 * Write block size.  Write offset and size must be a multiple
+	 * of this.
+	 */
+	uint32_t write_block_size;
+	/*
+	 * Erase block size.  Erase offset and size must be a multiple
+	 * of this.
+	 */
+	uint32_t erase_block_size;
+	/*
+	 * Protection block size.  Protection offset and size must be a
+	 * multiple of this.
+	 */
+	uint32_t protect_block_size;
+} __packed;
+
+/*
+ * Read flash
+ *
+ * Response is params.size bytes of data.
+ */
+#define EC_CMD_FLASH_READ 0x11
+
+struct ec_params_flash_read {
+	uint32_t offset;   /* Byte offset to read */
+	uint32_t size;     /* Size to read in bytes */
+} __packed;
+
+/* Write flash */
+#define EC_CMD_FLASH_WRITE 0x12
+
+struct ec_params_flash_write {
+	uint32_t offset;   /* Byte offset to write */
+	uint32_t size;     /* Size to write in bytes */
+	/*
+	 * Data to write.  Could really use EC_PARAM_SIZE - 8, but tidiest to
+	 * use a power of 2 so writes stay aligned.
+	 */
+	uint8_t data[64];
+} __packed;
+
+/* Erase flash */
+#define EC_CMD_FLASH_ERASE 0x13
+
+struct ec_params_flash_erase {
+	uint32_t offset;   /* Byte offset to erase */
+	uint32_t size;     /* Size to erase in bytes */
+} __packed;
+
+/*
+ * Get/set flash protection.
+ *
+ * If mask!=0, sets/clear the requested bits of flags.  Depending on the
+ * firmware write protect GPIO, not all flags will take effect immediately;
+ * some flags require a subsequent hard reset to take effect.  Check the
+ * returned flags bits to see what actually happened.
+ *
+ * If mask=0, simply returns the current flags state.
+ */
+#define EC_CMD_FLASH_PROTECT 0x15
+#define EC_VER_FLASH_PROTECT 1  /* Command version 1 */
+
+/* Flags for flash protection */
+/* RO flash code protected when the EC boots */
+#define EC_FLASH_PROTECT_RO_AT_BOOT         (1 << 0)
+/*
+ * RO flash code protected now.  If this bit is set, at-boot status cannot
+ * be changed.
+ */
+#define EC_FLASH_PROTECT_RO_NOW             (1 << 1)
+/* Entire flash code protected now, until reboot. */
+#define EC_FLASH_PROTECT_ALL_NOW            (1 << 2)
+/* Flash write protect GPIO is asserted now */
+#define EC_FLASH_PROTECT_GPIO_ASSERTED      (1 << 3)
+/* Error - at least one bank of flash is stuck locked, and cannot be unlocked */
+#define EC_FLASH_PROTECT_ERROR_STUCK        (1 << 4)
+/*
+ * Error - flash protection is in inconsistent state.  At least one bank of
+ * flash which should be protected is not protected.  Usually fixed by
+ * re-requesting the desired flags, or by a hard reset if that fails.
+ */
+#define EC_FLASH_PROTECT_ERROR_INCONSISTENT (1 << 5)
+/* Entile flash code protected when the EC boots */
+#define EC_FLASH_PROTECT_ALL_AT_BOOT        (1 << 6)
+
+struct ec_params_flash_protect {
+	uint32_t mask;   /* Bits in flags to apply */
+	uint32_t flags;  /* New flags to apply */
+} __packed;
+
+struct ec_response_flash_protect {
+	/* Current value of flash protect flags */
+	uint32_t flags;
+	/*
+	 * Flags which are valid on this platform.  This allows the caller
+	 * to distinguish between flags which aren't set vs. flags which can't
+	 * be set on this platform.
+	 */
+	uint32_t valid_flags;
+	/* Flags which can be changed given the current protection state */
+	uint32_t writable_flags;
+} __packed;
+
+/*
+ * Note: commands 0x14 - 0x19 version 0 were old commands to get/set flash
+ * write protect.  These commands may be reused with version > 0.
+ */
+
+/* Get the region offset/size */
+#define EC_CMD_FLASH_REGION_INFO 0x16
+#define EC_VER_FLASH_REGION_INFO 1
+
+enum ec_flash_region {
+	/* Region which holds read-only EC image */
+	EC_FLASH_REGION_RO,
+	/* Region which holds rewritable EC image */
+	EC_FLASH_REGION_RW,
+	/*
+	 * Region which should be write-protected in the factory (a superset of
+	 * EC_FLASH_REGION_RO)
+	 */
+	EC_FLASH_REGION_WP_RO,
+};
+
+struct ec_params_flash_region_info {
+	uint32_t region;  /* enum ec_flash_region */
+} __packed;
+
+struct ec_response_flash_region_info {
+	uint32_t offset;
+	uint32_t size;
+} __packed;
+
+/* Read/write VbNvContext */
+#define EC_CMD_VBNV_CONTEXT 0x17
+#define EC_VER_VBNV_CONTEXT 1
+#define EC_VBNV_BLOCK_SIZE 16
+
+enum ec_vbnvcontext_op {
+	EC_VBNV_CONTEXT_OP_READ,
+	EC_VBNV_CONTEXT_OP_WRITE,
+};
+
+struct ec_params_vbnvcontext {
+	uint32_t op;
+	uint8_t block[EC_VBNV_BLOCK_SIZE];
+} __packed;
+
+struct ec_response_vbnvcontext {
+	uint8_t block[EC_VBNV_BLOCK_SIZE];
+} __packed;
+
+/*****************************************************************************/
+/* PWM commands */
+
+/* Get fan target RPM */
+#define EC_CMD_PWM_GET_FAN_TARGET_RPM 0x20
+
+struct ec_response_pwm_get_fan_rpm {
+	uint32_t rpm;
+} __packed;
+
+/* Set target fan RPM */
+#define EC_CMD_PWM_SET_FAN_TARGET_RPM 0x21
+
+struct ec_params_pwm_set_fan_target_rpm {
+	uint32_t rpm;
+} __packed;
+
+/* Get keyboard backlight */
+#define EC_CMD_PWM_GET_KEYBOARD_BACKLIGHT 0x22
+
+struct ec_response_pwm_get_keyboard_backlight {
+	uint8_t percent;
+	uint8_t enabled;
+} __packed;
+
+/* Set keyboard backlight */
+#define EC_CMD_PWM_SET_KEYBOARD_BACKLIGHT 0x23
+
+struct ec_params_pwm_set_keyboard_backlight {
+	uint8_t percent;
+} __packed;
+
+/* Set target fan PWM duty cycle */
+#define EC_CMD_PWM_SET_FAN_DUTY 0x24
+
+struct ec_params_pwm_set_fan_duty {
+	uint32_t percent;
+} __packed;
+
+/*****************************************************************************/
+/*
+ * Lightbar commands. This looks worse than it is. Since we only use one HOST
+ * command to say "talk to the lightbar", we put the "and tell it to do X" part
+ * into a subcommand. We'll make separate structs for subcommands with
+ * different input args, so that we know how much to expect.
+ */
+#define EC_CMD_LIGHTBAR_CMD 0x28
+
+struct rgb_s {
+	uint8_t r, g, b;
+};
+
+#define LB_BATTERY_LEVELS 4
+/* List of tweakable parameters. NOTE: It's __packed so it can be sent in a
+ * host command, but the alignment is the same regardless. Keep it that way.
+ */
+struct lightbar_params {
+	/* Timing */
+	int google_ramp_up;
+	int google_ramp_down;
+	int s3s0_ramp_up;
+	int s0_tick_delay[2];			/* AC=0/1 */
+	int s0a_tick_delay[2];			/* AC=0/1 */
+	int s0s3_ramp_down;
+	int s3_sleep_for;
+	int s3_ramp_up;
+	int s3_ramp_down;
+
+	/* Oscillation */
+	uint8_t new_s0;
+	uint8_t osc_min[2];			/* AC=0/1 */
+	uint8_t osc_max[2];			/* AC=0/1 */
+	uint8_t w_ofs[2];			/* AC=0/1 */
+
+	/* Brightness limits based on the backlight and AC. */
+	uint8_t bright_bl_off_fixed[2];		/* AC=0/1 */
+	uint8_t bright_bl_on_min[2];		/* AC=0/1 */
+	uint8_t bright_bl_on_max[2];		/* AC=0/1 */
+
+	/* Battery level thresholds */
+	uint8_t battery_threshold[LB_BATTERY_LEVELS - 1];
+
+	/* Map [AC][battery_level] to color index */
+	uint8_t s0_idx[2][LB_BATTERY_LEVELS];	/* AP is running */
+	uint8_t s3_idx[2][LB_BATTERY_LEVELS];	/* AP is sleeping */
+
+	/* Color palette */
+	struct rgb_s color[8];			/* 0-3 are Google colors */
+} __packed;
+
+struct ec_params_lightbar {
+	uint8_t cmd;		      /* Command (see enum lightbar_command) */
+	union {
+		struct {
+			/* no args */
+		} dump, off, on, init, get_seq, get_params;
+
+		struct num {
+			uint8_t num;
+		} brightness, seq, demo;
+
+		struct reg {
+			uint8_t ctrl, reg, value;
+		} reg;
+
+		struct rgb {
+			uint8_t led, red, green, blue;
+		} rgb;
+
+		struct lightbar_params set_params;
+	};
+} __packed;
+
+struct ec_response_lightbar {
+	union {
+		struct dump {
+			struct {
+				uint8_t reg;
+				uint8_t ic0;
+				uint8_t ic1;
+			} vals[23];
+		} dump;
+
+		struct get_seq {
+			uint8_t num;
+		} get_seq;
+
+		struct lightbar_params get_params;
+
+		struct {
+			/* no return params */
+		} off, on, init, brightness, seq, reg, rgb, demo, set_params;
+	};
+} __packed;
+
+/* Lightbar commands */
+enum lightbar_command {
+	LIGHTBAR_CMD_DUMP = 0,
+	LIGHTBAR_CMD_OFF = 1,
+	LIGHTBAR_CMD_ON = 2,
+	LIGHTBAR_CMD_INIT = 3,
+	LIGHTBAR_CMD_BRIGHTNESS = 4,
+	LIGHTBAR_CMD_SEQ = 5,
+	LIGHTBAR_CMD_REG = 6,
+	LIGHTBAR_CMD_RGB = 7,
+	LIGHTBAR_CMD_GET_SEQ = 8,
+	LIGHTBAR_CMD_DEMO = 9,
+	LIGHTBAR_CMD_GET_PARAMS = 10,
+	LIGHTBAR_CMD_SET_PARAMS = 11,
+	LIGHTBAR_NUM_CMDS
+};
+
+/*****************************************************************************/
+/* Verified boot commands */
+
+/*
+ * Note: command code 0x29 version 0 was VBOOT_CMD in Link EVT; it may be
+ * reused for other purposes with version > 0.
+ */
+
+/* Verified boot hash command */
+#define EC_CMD_VBOOT_HASH 0x2A
+
+struct ec_params_vboot_hash {
+	uint8_t cmd;             /* enum ec_vboot_hash_cmd */
+	uint8_t hash_type;       /* enum ec_vboot_hash_type */
+	uint8_t nonce_size;      /* Nonce size; may be 0 */
+	uint8_t reserved0;       /* Reserved; set 0 */
+	uint32_t offset;         /* Offset in flash to hash */
+	uint32_t size;           /* Number of bytes to hash */
+	uint8_t nonce_data[64];  /* Nonce data; ignored if nonce_size=0 */
+} __packed;
+
+struct ec_response_vboot_hash {
+	uint8_t status;          /* enum ec_vboot_hash_status */
+	uint8_t hash_type;       /* enum ec_vboot_hash_type */
+	uint8_t digest_size;     /* Size of hash digest in bytes */
+	uint8_t reserved0;       /* Ignore; will be 0 */
+	uint32_t offset;         /* Offset in flash which was hashed */
+	uint32_t size;           /* Number of bytes hashed */
+	uint8_t hash_digest[64]; /* Hash digest data */
+} __packed;
+
+enum ec_vboot_hash_cmd {
+	EC_VBOOT_HASH_GET = 0,       /* Get current hash status */
+	EC_VBOOT_HASH_ABORT = 1,     /* Abort calculating current hash */
+	EC_VBOOT_HASH_START = 2,     /* Start computing a new hash */
+	EC_VBOOT_HASH_RECALC = 3,    /* Synchronously compute a new hash */
+};
+
+enum ec_vboot_hash_type {
+	EC_VBOOT_HASH_TYPE_SHA256 = 0, /* SHA-256 */
+};
+
+enum ec_vboot_hash_status {
+	EC_VBOOT_HASH_STATUS_NONE = 0, /* No hash (not started, or aborted) */
+	EC_VBOOT_HASH_STATUS_DONE = 1, /* Finished computing a hash */
+	EC_VBOOT_HASH_STATUS_BUSY = 2, /* Busy computing a hash */
+};
+
+/*
+ * Special values for offset for EC_VBOOT_HASH_START and EC_VBOOT_HASH_RECALC.
+ * If one of these is specified, the EC will automatically update offset and
+ * size to the correct values for the specified image (RO or RW).
+ */
+#define EC_VBOOT_HASH_OFFSET_RO 0xfffffffe
+#define EC_VBOOT_HASH_OFFSET_RW 0xfffffffd
+
+/*****************************************************************************/
+/* USB charging control commands */
+
+/* Set USB port charging mode */
+#define EC_CMD_USB_CHARGE_SET_MODE 0x30
+
+struct ec_params_usb_charge_set_mode {
+	uint8_t usb_port_id;
+	uint8_t mode;
+} __packed;
+
+/*****************************************************************************/
+/* Persistent storage for host */
+
+/* Maximum bytes that can be read/written in a single command */
+#define EC_PSTORE_SIZE_MAX 64
+
+/* Get persistent storage info */
+#define EC_CMD_PSTORE_INFO 0x40
+
+struct ec_response_pstore_info {
+	/* Persistent storage size, in bytes */
+	uint32_t pstore_size;
+	/* Access size; read/write offset and size must be a multiple of this */
+	uint32_t access_size;
+} __packed;
+
+/*
+ * Read persistent storage
+ *
+ * Response is params.size bytes of data.
+ */
+#define EC_CMD_PSTORE_READ 0x41
+
+struct ec_params_pstore_read {
+	uint32_t offset;   /* Byte offset to read */
+	uint32_t size;     /* Size to read in bytes */
+} __packed;
+
+/* Write persistent storage */
+#define EC_CMD_PSTORE_WRITE 0x42
+
+struct ec_params_pstore_write {
+	uint32_t offset;   /* Byte offset to write */
+	uint32_t size;     /* Size to write in bytes */
+	uint8_t data[EC_PSTORE_SIZE_MAX];
+} __packed;
+
+/*****************************************************************************/
+/* Real-time clock */
+
+/* RTC params and response structures */
+struct ec_params_rtc {
+	uint32_t time;
+} __packed;
+
+struct ec_response_rtc {
+	uint32_t time;
+} __packed;
+
+/* These use ec_response_rtc */
+#define EC_CMD_RTC_GET_VALUE 0x44
+#define EC_CMD_RTC_GET_ALARM 0x45
+
+/* These all use ec_params_rtc */
+#define EC_CMD_RTC_SET_VALUE 0x46
+#define EC_CMD_RTC_SET_ALARM 0x47
+
+/*****************************************************************************/
+/* Port80 log access */
+
+/* Get last port80 code from previous boot */
+#define EC_CMD_PORT80_LAST_BOOT 0x48
+
+struct ec_response_port80_last_boot {
+	uint16_t code;
+} __packed;
+
+/*****************************************************************************/
+/* Thermal engine commands */
+
+/* Set thershold value */
+#define EC_CMD_THERMAL_SET_THRESHOLD 0x50
+
+struct ec_params_thermal_set_threshold {
+	uint8_t sensor_type;
+	uint8_t threshold_id;
+	uint16_t value;
+} __packed;
+
+/* Get threshold value */
+#define EC_CMD_THERMAL_GET_THRESHOLD 0x51
+
+struct ec_params_thermal_get_threshold {
+	uint8_t sensor_type;
+	uint8_t threshold_id;
+} __packed;
+
+struct ec_response_thermal_get_threshold {
+	uint16_t value;
+} __packed;
+
+/* Toggle automatic fan control */
+#define EC_CMD_THERMAL_AUTO_FAN_CTRL 0x52
+
+/* Get TMP006 calibration data */
+#define EC_CMD_TMP006_GET_CALIBRATION 0x53
+
+struct ec_params_tmp006_get_calibration {
+	uint8_t index;
+} __packed;
+
+struct ec_response_tmp006_get_calibration {
+	float s0;
+	float b0;
+	float b1;
+	float b2;
+} __packed;
+
+/* Set TMP006 calibration data */
+#define EC_CMD_TMP006_SET_CALIBRATION 0x54
+
+struct ec_params_tmp006_set_calibration {
+	uint8_t index;
+	uint8_t reserved[3];  /* Reserved; set 0 */
+	float s0;
+	float b0;
+	float b1;
+	float b2;
+} __packed;
+
+/*****************************************************************************/
+/* MKBP - Matrix KeyBoard Protocol */
+
+/*
+ * Read key state
+ *
+ * Returns raw data for keyboard cols; see ec_response_mkbp_info.cols for
+ * expected response size.
+ */
+#define EC_CMD_MKBP_STATE 0x60
+
+/* Provide information about the matrix : number of rows and columns */
+#define EC_CMD_MKBP_INFO 0x61
+
+struct ec_response_mkbp_info {
+	uint32_t rows;
+	uint32_t cols;
+	uint8_t switches;
+} __packed;
+
+/* Simulate key press */
+#define EC_CMD_MKBP_SIMULATE_KEY 0x62
+
+struct ec_params_mkbp_simulate_key {
+	uint8_t col;
+	uint8_t row;
+	uint8_t pressed;
+} __packed;
+
+/* Configure keyboard scanning */
+#define EC_CMD_MKBP_SET_CONFIG 0x64
+#define EC_CMD_MKBP_GET_CONFIG 0x65
+
+/* flags */
+enum mkbp_config_flags {
+	EC_MKBP_FLAGS_ENABLE = 1,	/* Enable keyboard scanning */
+};
+
+enum mkbp_config_valid {
+	EC_MKBP_VALID_SCAN_PERIOD		= 1 << 0,
+	EC_MKBP_VALID_POLL_TIMEOUT		= 1 << 1,
+	EC_MKBP_VALID_MIN_POST_SCAN_DELAY	= 1 << 3,
+	EC_MKBP_VALID_OUTPUT_SETTLE		= 1 << 4,
+	EC_MKBP_VALID_DEBOUNCE_DOWN		= 1 << 5,
+	EC_MKBP_VALID_DEBOUNCE_UP		= 1 << 6,
+	EC_MKBP_VALID_FIFO_MAX_DEPTH		= 1 << 7,
+};
+
+/* Configuration for our key scanning algorithm */
+struct ec_mkbp_config {
+	uint32_t valid_mask;		/* valid fields */
+	uint8_t flags;		/* some flags (enum mkbp_config_flags) */
+	uint8_t valid_flags;		/* which flags are valid */
+	uint16_t scan_period_us;	/* period between start of scans */
+	/* revert to interrupt mode after no activity for this long */
+	uint32_t poll_timeout_us;
+	/*
+	 * minimum post-scan relax time. Once we finish a scan we check
+	 * the time until we are due to start the next one. If this time is
+	 * shorter this field, we use this instead.
+	 */
+	uint16_t min_post_scan_delay_us;
+	/* delay between setting up output and waiting for it to settle */
+	uint16_t output_settle_us;
+	uint16_t debounce_down_us;	/* time for debounce on key down */
+	uint16_t debounce_up_us;	/* time for debounce on key up */
+	/* maximum depth to allow for fifo (0 = no keyscan output) */
+	uint8_t fifo_max_depth;
+} __packed;
+
+struct ec_params_mkbp_set_config {
+	struct ec_mkbp_config config;
+} __packed;
+
+struct ec_response_mkbp_get_config {
+	struct ec_mkbp_config config;
+} __packed;
+
+/* Run the key scan emulation */
+#define EC_CMD_KEYSCAN_SEQ_CTRL 0x66
+
+enum ec_keyscan_seq_cmd {
+	EC_KEYSCAN_SEQ_STATUS = 0,	/* Get status information */
+	EC_KEYSCAN_SEQ_CLEAR = 1,	/* Clear sequence */
+	EC_KEYSCAN_SEQ_ADD = 2,		/* Add item to sequence */
+	EC_KEYSCAN_SEQ_START = 3,	/* Start running sequence */
+	EC_KEYSCAN_SEQ_COLLECT = 4,	/* Collect sequence summary data */
+};
+
+enum ec_collect_flags {
+	/*
+	 * Indicates this scan was processed by the EC. Due to timing, some
+	 * scans may be skipped.
+	 */
+	EC_KEYSCAN_SEQ_FLAG_DONE	= 1 << 0,
+};
+
+struct ec_collect_item {
+	uint8_t flags;		/* some flags (enum ec_collect_flags) */
+};
+
+struct ec_params_keyscan_seq_ctrl {
+	uint8_t cmd;	/* Command to send (enum ec_keyscan_seq_cmd) */
+	union {
+		struct {
+			uint8_t active;		/* still active */
+			uint8_t num_items;	/* number of items */
+			/* Current item being presented */
+			uint8_t cur_item;
+		} status;
+		struct {
+			/*
+			 * Absolute time for this scan, measured from the
+			 * start of the sequence.
+			 */
+			uint32_t time_us;
+			uint8_t scan[0];	/* keyscan data */
+		} add;
+		struct {
+			uint8_t start_item;	/* First item to return */
+			uint8_t num_items;	/* Number of items to return */
+		} collect;
+	};
+} __packed;
+
+struct ec_result_keyscan_seq_ctrl {
+	union {
+		struct {
+			uint8_t num_items;	/* Number of items */
+			/* Data for each item */
+			struct ec_collect_item item[0];
+		} collect;
+	};
+} __packed;
+
+/*****************************************************************************/
+/* Temperature sensor commands */
+
+/* Read temperature sensor info */
+#define EC_CMD_TEMP_SENSOR_GET_INFO 0x70
+
+struct ec_params_temp_sensor_get_info {
+	uint8_t id;
+} __packed;
+
+struct ec_response_temp_sensor_get_info {
+	char sensor_name[32];
+	uint8_t sensor_type;
+} __packed;
+
+/*****************************************************************************/
+
+/*
+ * Note: host commands 0x80 - 0x87 are reserved to avoid conflict with ACPI
+ * commands accidentally sent to the wrong interface.  See the ACPI section
+ * below.
+ */
+
+/*****************************************************************************/
+/* Host event commands */
+
+/*
+ * Host event mask params and response structures, shared by all of the host
+ * event commands below.
+ */
+struct ec_params_host_event_mask {
+	uint32_t mask;
+} __packed;
+
+struct ec_response_host_event_mask {
+	uint32_t mask;
+} __packed;
+
+/* These all use ec_response_host_event_mask */
+#define EC_CMD_HOST_EVENT_GET_B         0x87
+#define EC_CMD_HOST_EVENT_GET_SMI_MASK  0x88
+#define EC_CMD_HOST_EVENT_GET_SCI_MASK  0x89
+#define EC_CMD_HOST_EVENT_GET_WAKE_MASK 0x8d
+
+/* These all use ec_params_host_event_mask */
+#define EC_CMD_HOST_EVENT_SET_SMI_MASK  0x8a
+#define EC_CMD_HOST_EVENT_SET_SCI_MASK  0x8b
+#define EC_CMD_HOST_EVENT_CLEAR         0x8c
+#define EC_CMD_HOST_EVENT_SET_WAKE_MASK 0x8e
+#define EC_CMD_HOST_EVENT_CLEAR_B       0x8f
+
+/*****************************************************************************/
+/* Switch commands */
+
+/* Enable/disable LCD backlight */
+#define EC_CMD_SWITCH_ENABLE_BKLIGHT 0x90
+
+struct ec_params_switch_enable_backlight {
+	uint8_t enabled;
+} __packed;
+
+/* Enable/disable WLAN/Bluetooth */
+#define EC_CMD_SWITCH_ENABLE_WIRELESS 0x91
+
+struct ec_params_switch_enable_wireless {
+	uint8_t enabled;
+} __packed;
+
+/*****************************************************************************/
+/* GPIO commands. Only available on EC if write protect has been disabled. */
+
+/* Set GPIO output value */
+#define EC_CMD_GPIO_SET 0x92
+
+struct ec_params_gpio_set {
+	char name[32];
+	uint8_t val;
+} __packed;
+
+/* Get GPIO value */
+#define EC_CMD_GPIO_GET 0x93
+
+struct ec_params_gpio_get {
+	char name[32];
+} __packed;
+struct ec_response_gpio_get {
+	uint8_t val;
+} __packed;
+
+/*****************************************************************************/
+/* I2C commands. Only available when flash write protect is unlocked. */
+
+/* Read I2C bus */
+#define EC_CMD_I2C_READ 0x94
+
+struct ec_params_i2c_read {
+	uint16_t addr;
+	uint8_t read_size; /* Either 8 or 16. */
+	uint8_t port;
+	uint8_t offset;
+} __packed;
+struct ec_response_i2c_read {
+	uint16_t data;
+} __packed;
+
+/* Write I2C bus */
+#define EC_CMD_I2C_WRITE 0x95
+
+struct ec_params_i2c_write {
+	uint16_t data;
+	uint16_t addr;
+	uint8_t write_size; /* Either 8 or 16. */
+	uint8_t port;
+	uint8_t offset;
+} __packed;
+
+/*****************************************************************************/
+/* Charge state commands. Only available when flash write protect unlocked. */
+
+/* Force charge state machine to stop in idle mode */
+#define EC_CMD_CHARGE_FORCE_IDLE 0x96
+
+struct ec_params_force_idle {
+	uint8_t enabled;
+} __packed;
+
+/*****************************************************************************/
+/* Console commands. Only available when flash write protect is unlocked. */
+
+/* Snapshot console output buffer for use by EC_CMD_CONSOLE_READ. */
+#define EC_CMD_CONSOLE_SNAPSHOT 0x97
+
+/*
+ * Read next chunk of data from saved snapshot.
+ *
+ * Response is null-terminated string.  Empty string, if there is no more
+ * remaining output.
+ */
+#define EC_CMD_CONSOLE_READ 0x98
+
+/*****************************************************************************/
+
+/*
+ * Cut off battery power output if the battery supports.
+ *
+ * For unsupported battery, just don't implement this command and lets EC
+ * return EC_RES_INVALID_COMMAND.
+ */
+#define EC_CMD_BATTERY_CUT_OFF 0x99
+
+/*****************************************************************************/
+/* Temporary debug commands. TODO: remove this crosbug.com/p/13849 */
+
+/*
+ * Dump charge state machine context.
+ *
+ * Response is a binary dump of charge state machine context.
+ */
+#define EC_CMD_CHARGE_DUMP 0xa0
+
+/*
+ * Set maximum battery charging current.
+ */
+#define EC_CMD_CHARGE_CURRENT_LIMIT 0xa1
+
+struct ec_params_current_limit {
+	uint32_t limit;
+} __packed;
+
+/*****************************************************************************/
+/* System commands */
+
+/*
+ * TODO: this is a confusing name, since it doesn't necessarily reboot the EC.
+ * Rename to "set image" or something similar.
+ */
+#define EC_CMD_REBOOT_EC 0xd2
+
+/* Command */
+enum ec_reboot_cmd {
+	EC_REBOOT_CANCEL = 0,        /* Cancel a pending reboot */
+	EC_REBOOT_JUMP_RO = 1,       /* Jump to RO without rebooting */
+	EC_REBOOT_JUMP_RW = 2,       /* Jump to RW without rebooting */
+	/* (command 3 was jump to RW-B) */
+	EC_REBOOT_COLD = 4,          /* Cold-reboot */
+	EC_REBOOT_DISABLE_JUMP = 5,  /* Disable jump until next reboot */
+	EC_REBOOT_HIBERNATE = 6      /* Hibernate EC */
+};
+
+/* Flags for ec_params_reboot_ec.reboot_flags */
+#define EC_REBOOT_FLAG_RESERVED0      (1 << 0)  /* Was recovery request */
+#define EC_REBOOT_FLAG_ON_AP_SHUTDOWN (1 << 1)  /* Reboot after AP shutdown */
+
+struct ec_params_reboot_ec {
+	uint8_t cmd;           /* enum ec_reboot_cmd */
+	uint8_t flags;         /* See EC_REBOOT_FLAG_* */
+} __packed;
+
+/*
+ * Get information on last EC panic.
+ *
+ * Returns variable-length platform-dependent panic information.  See panic.h
+ * for details.
+ */
+#define EC_CMD_GET_PANIC_INFO 0xd3
+
+/*****************************************************************************/
+/*
+ * ACPI commands
+ *
+ * These are valid ONLY on the ACPI command/data port.
+ */
+
+/*
+ * ACPI Read Embedded Controller
+ *
+ * This reads from ACPI memory space on the EC (EC_ACPI_MEM_*).
+ *
+ * Use the following sequence:
+ *
+ *    - Write EC_CMD_ACPI_READ to EC_LPC_ADDR_ACPI_CMD
+ *    - Wait for EC_LPC_CMDR_PENDING bit to clear
+ *    - Write address to EC_LPC_ADDR_ACPI_DATA
+ *    - Wait for EC_LPC_CMDR_DATA bit to set
+ *    - Read value from EC_LPC_ADDR_ACPI_DATA
+ */
+#define EC_CMD_ACPI_READ 0x80
+
+/*
+ * ACPI Write Embedded Controller
+ *
+ * This reads from ACPI memory space on the EC (EC_ACPI_MEM_*).
+ *
+ * Use the following sequence:
+ *
+ *    - Write EC_CMD_ACPI_WRITE to EC_LPC_ADDR_ACPI_CMD
+ *    - Wait for EC_LPC_CMDR_PENDING bit to clear
+ *    - Write address to EC_LPC_ADDR_ACPI_DATA
+ *    - Wait for EC_LPC_CMDR_PENDING bit to clear
+ *    - Write value to EC_LPC_ADDR_ACPI_DATA
+ */
+#define EC_CMD_ACPI_WRITE 0x81
+
+/*
+ * ACPI Query Embedded Controller
+ *
+ * This clears the lowest-order bit in the currently pending host events, and
+ * sets the result code to the 1-based index of the bit (event 0x00000001 = 1,
+ * event 0x80000000 = 32), or 0 if no event was pending.
+ */
+#define EC_CMD_ACPI_QUERY_EVENT 0x84
+
+/* Valid addresses in ACPI memory space, for read/write commands */
+/* Memory space version; set to EC_ACPI_MEM_VERSION_CURRENT */
+#define EC_ACPI_MEM_VERSION            0x00
+/*
+ * Test location; writing value here updates test compliment byte to (0xff -
+ * value).
+ */
+#define EC_ACPI_MEM_TEST               0x01
+/* Test compliment; writes here are ignored. */
+#define EC_ACPI_MEM_TEST_COMPLIMENT    0x02
+/* Keyboard backlight brightness percent (0 - 100) */
+#define EC_ACPI_MEM_KEYBOARD_BACKLIGHT 0x03
+
+/* Current version of ACPI memory address space */
+#define EC_ACPI_MEM_VERSION_CURRENT 1
+
+
+/*****************************************************************************/
+/*
+ * Special commands
+ *
+ * These do not follow the normal rules for commands.  See each command for
+ * details.
+ */
+
+/*
+ * Reboot NOW
+ *
+ * This command will work even when the EC LPC interface is busy, because the
+ * reboot command is processed at interrupt level.  Note that when the EC
+ * reboots, the host will reboot too, so there is no response to this command.
+ *
+ * Use EC_CMD_REBOOT_EC to reboot the EC more politely.
+ */
+#define EC_CMD_REBOOT 0xd1  /* Think "die" */
+
+/*
+ * Resend last response (not supported on LPC).
+ *
+ * Returns EC_RES_UNAVAILABLE if there is no response available - for example,
+ * there was no previous command, or the previous command's response was too
+ * big to save.
+ */
+#define EC_CMD_RESEND_RESPONSE 0xdb
+
+/*
+ * This header byte on a command indicate version 0. Any header byte less
+ * than this means that we are talking to an old EC which doesn't support
+ * versioning. In that case, we assume version 0.
+ *
+ * Header bytes greater than this indicate a later version. For example,
+ * EC_CMD_VERSION0 + 1 means we are using version 1.
+ *
+ * The old EC interface must not use commands 0dc or higher.
+ */
+#define EC_CMD_VERSION0 0xdc
+
+#endif  /* !__ACPI__ */
+
+#endif  /* __CROS_EC_COMMANDS_H */
diff --git a/include/linux/mfd/tps65090.h b/include/linux/mfd/tps65090.h
index 6694cf4..998628a 100644
--- a/include/linux/mfd/tps65090.h
+++ b/include/linux/mfd/tps65090.h
@@ -86,6 +86,11 @@ struct tps65090_regulator_plat_data {
 
 struct tps65090_platform_data {
 	int irq_base;
+
+	char **supplied_to;
+	size_t num_supplicants;
+	int enable_low_current_chrg;
+
 	struct tps65090_regulator_plat_data *reg_pdata[TPS65090_REGULATOR_MAX];
 };
 
diff --git a/include/linux/mfd/wm8994/pdata.h b/include/linux/mfd/wm8994/pdata.h
index 8e21a09..68e7765 100644
--- a/include/linux/mfd/wm8994/pdata.h
+++ b/include/linux/mfd/wm8994/pdata.h
@@ -17,6 +17,7 @@
 
 #define WM8994_NUM_LDO   2
 #define WM8994_NUM_GPIO 11
+#define WM8994_NUM_AIF   3
 
 struct wm8994_ldo_pdata {
 	/** GPIOs to enable regulator, 0 or less if not available */
@@ -215,6 +216,13 @@ struct wm8994_pdata {
 	 * system.
 	 */
 	bool spkmode_pu;
+
+	/**
+	 * Maximum number of channels clocks will be generated for,
+	 * useful for systems where and I2S bus with multiple data
+	 * lines is mastered.
+	 */
+	int max_channels_clocked[WM8994_NUM_AIF];
 };
 
 #endif
diff --git a/include/linux/micrel_phy.h b/include/linux/micrel_phy.h
index 9dbb41a..8752dbb 100644
--- a/include/linux/micrel_phy.h
+++ b/include/linux/micrel_phy.h
@@ -19,6 +19,7 @@
 #define PHY_ID_KSZ9021		0x00221610
 #define PHY_ID_KS8737		0x00221720
 #define PHY_ID_KSZ8021		0x00221555
+#define PHY_ID_KSZ8031		0x00221556
 #define PHY_ID_KSZ8041		0x00221510
 #define PHY_ID_KSZ8051		0x00221550
 /* same id: ks8001 Rev. A/B, and ks8721 Rev 3. */
diff --git a/include/linux/mm.h b/include/linux/mm.h
index e19ff30..62b0164 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -899,7 +899,8 @@ extern void pagefault_out_of_memory(void);
  * Flags passed to show_mem() and show_free_areas() to suppress output in
  * various contexts.
  */
-#define SHOW_MEM_FILTER_NODES	(0x0001u)	/* filter disallowed nodes */
+#define SHOW_MEM_FILTER_NODES		(0x0001u)	/* disallowed nodes */
+#define SHOW_MEM_FILTER_PAGE_COUNT	(0x0002u)	/* page type count */
 
 extern void show_free_areas(unsigned int flags);
 extern bool skip_free_areas_node(unsigned int flags, int nid);
@@ -1078,9 +1079,6 @@ extern unsigned long move_page_tables(struct vm_area_struct *vma,
 		unsigned long old_addr, struct vm_area_struct *new_vma,
 		unsigned long new_addr, unsigned long len,
 		bool need_rmap_locks);
-extern unsigned long do_mremap(unsigned long addr,
-			       unsigned long old_len, unsigned long new_len,
-			       unsigned long flags, unsigned long new_addr);
 extern unsigned long change_protection(struct vm_area_struct *vma, unsigned long start,
 			      unsigned long end, pgprot_t newprot,
 			      int dirty_accountable, int prot_numa);
@@ -1294,6 +1292,61 @@ extern void free_area_init_node(int nid, unsigned long * zones_size,
 		unsigned long zone_start_pfn, unsigned long *zholes_size);
 extern void free_initmem(void);
 
+/*
+ * Free reserved pages within range [PAGE_ALIGN(start), end & PAGE_MASK)
+ * into the buddy system. The freed pages will be poisoned with pattern
+ * "poison" if it's non-zero.
+ * Return pages freed into the buddy system.
+ */
+extern unsigned long free_reserved_area(unsigned long start, unsigned long end,
+					int poison, char *s);
+#ifdef	CONFIG_HIGHMEM
+/*
+ * Free a highmem page into the buddy system, adjusting totalhigh_pages
+ * and totalram_pages.
+ */
+extern void free_highmem_page(struct page *page);
+#endif
+
+static inline void adjust_managed_page_count(struct page *page, long count)
+{
+	totalram_pages += count;
+}
+
+/* Free the reserved page into the buddy system, so it gets managed. */
+static inline void __free_reserved_page(struct page *page)
+{
+	ClearPageReserved(page);
+	init_page_count(page);
+	__free_page(page);
+}
+
+static inline void free_reserved_page(struct page *page)
+{
+	__free_reserved_page(page);
+	adjust_managed_page_count(page, 1);
+}
+
+static inline void mark_page_reserved(struct page *page)
+{
+	SetPageReserved(page);
+	adjust_managed_page_count(page, -1);
+}
+
+/*
+ * Default method to free all the __init memory into the buddy system.
+ * The freed pages will be poisoned with pattern "poison" if it is
+ * non-zero. Return pages freed into the buddy system.
+ */
+static inline unsigned long free_initmem_default(int poison)
+{
+	extern char __init_begin[], __init_end[];
+
+	return free_reserved_area(PAGE_ALIGN((unsigned long)&__init_begin) ,
+				  ((unsigned long)&__init_end) & PAGE_MASK,
+				  poison, "unused kernel");
+}
+
 #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
 /*
  * With CONFIG_HAVE_MEMBLOCK_NODE_MAP set, an architecture may initialise its
@@ -1673,8 +1726,12 @@ int in_gate_area_no_mm(unsigned long addr);
 #define in_gate_area(mm, addr) ({(void)mm; in_gate_area_no_mm(addr);})
 #endif	/* __HAVE_ARCH_GATE_AREA */
 
+#ifdef CONFIG_SYSCTL
+extern int sysctl_drop_caches;
 int drop_caches_sysctl_handler(struct ctl_table *, int,
 					void __user *, size_t *, loff_t *);
+#endif
+
 unsigned long shrink_slab(struct shrink_control *shrink,
 			  unsigned long nr_pages_scanned,
 			  unsigned long lru_pages);
@@ -1702,12 +1759,12 @@ pte_t *vmemmap_pte_populate(pmd_t *pmd, unsigned long addr, int node);
 void *vmemmap_alloc_block(unsigned long size, int node);
 void *vmemmap_alloc_block_buf(unsigned long size, int node);
 void vmemmap_verify(pte_t *, int, unsigned long, unsigned long);
-int vmemmap_populate_basepages(struct page *start_page,
-						unsigned long pages, int node);
-int vmemmap_populate(struct page *start_page, unsigned long pages, int node);
+int vmemmap_populate_basepages(unsigned long start, unsigned long end,
+			       int node);
+int vmemmap_populate(unsigned long start, unsigned long end, int node);
 void vmemmap_populate_print_last(void);
 #ifdef CONFIG_MEMORY_HOTPLUG
-void vmemmap_free(struct page *memmap, unsigned long nr_pages);
+void vmemmap_free(unsigned long start, unsigned long end);
 #endif
 void register_page_bootmem_memmap(unsigned long section_nr, struct page *map,
 				  unsigned long size);
@@ -1754,5 +1811,11 @@ static inline unsigned int debug_guardpage_minorder(void) { return 0; }
 static inline bool page_is_guard(struct page *page) { return false; }
 #endif /* CONFIG_DEBUG_PAGEALLOC */
 
+#if MAX_NUMNODES > 1
+void __init setup_nr_node_ids(void);
+#else
+static inline void setup_nr_node_ids(void) {}
+#endif
+
 #endif /* __KERNEL__ */
 #endif /* _LINUX_MM_H */
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index ace9a5f..fb425aa 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -330,12 +330,9 @@ struct mm_struct {
 	unsigned long (*get_unmapped_area) (struct file *filp,
 				unsigned long addr, unsigned long len,
 				unsigned long pgoff, unsigned long flags);
-	void (*unmap_area) (struct mm_struct *mm, unsigned long addr);
 #endif
 	unsigned long mmap_base;		/* base of mmap area */
 	unsigned long task_size;		/* size of task vm space */
-	unsigned long cached_hole_size; 	/* if non-zero, the largest hole below free_area_cache */
-	unsigned long free_area_cache;		/* first hole of size cached_hole_size or larger */
 	unsigned long highest_vm_end;		/* highest vma end address */
 	pgd_t * pgd;
 	atomic_t mm_users;			/* How many users with user space? */
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index 61b2c30..f31725b 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -17,6 +17,7 @@
 struct mmc_cid {
 	unsigned int		manfid;
 	char			prod_name[8];
+	unsigned char		prv;
 	unsigned int		serial;
 	unsigned short		oemid;
 	unsigned short		year;
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index d6f20cc..257ad3b 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -341,9 +341,7 @@ struct mmc_host {
 
 	mmc_pm_flag_t		pm_flags;	/* requested pm features */
 
-#ifdef CONFIG_LEDS_TRIGGERS
 	struct led_trigger	*led;		/* activity led */
-#endif
 
 #ifdef CONFIG_REGULATOR
 	bool			regulator_enabled; /* regulator state */
@@ -361,6 +359,8 @@ struct mmc_host {
 
 	unsigned int		actual_clock;	/* Actual HC clock rate */
 
+	unsigned int		slotno;	/* used for sdio acpi binding */
+
 	unsigned long		private[0] ____cacheline_aligned;
 };
 
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index c74092e..8c9f859 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -450,7 +450,7 @@ struct zone {
 	 *
 	 * present_pages is physical pages existing within the zone, which
 	 * is calculated as:
-	 *	present_pages = spanned_pages - absent_pages(pags in holes);
+	 *	present_pages = spanned_pages - absent_pages(pages in holes);
 	 *
 	 * managed_pages is present pages managed by the buddy system, which
 	 * is calculated as (reserved_pages includes pages allocated by the
@@ -815,7 +815,10 @@ unsigned long __init node_memmap_size_bytes(int, unsigned long, unsigned long);
 /*
  * zone_idx() returns 0 for the ZONE_DMA zone, 1 for the ZONE_NORMAL zone, etc.
  */
-#define zone_idx(zone)		((zone) - (zone)->zone_pgdat->node_zones)
+static inline enum zone_type zone_idx(struct zone *zone)
+{
+	return zone - zone->zone_pgdat->node_zones;
+}
 
 static inline int populated_zone(struct zone *zone)
 {
@@ -856,25 +859,18 @@ static inline int is_normal_idx(enum zone_type idx)
  */
 static inline int is_highmem(struct zone *zone)
 {
-#ifdef CONFIG_HIGHMEM
-	int zone_off = (char *)zone - (char *)zone->zone_pgdat->node_zones;
-	return zone_off == ZONE_HIGHMEM * sizeof(*zone) ||
-	       (zone_off == ZONE_MOVABLE * sizeof(*zone) &&
-		zone_movable_is_highmem());
-#else
-	return 0;
-#endif
+	return is_highmem_idx(zone_idx(zone));
 }
 
 static inline int is_normal(struct zone *zone)
 {
-	return zone == zone->zone_pgdat->node_zones + ZONE_NORMAL;
+	return zone_idx(zone) == ZONE_NORMAL;
 }
 
 static inline int is_dma32(struct zone *zone)
 {
 #ifdef CONFIG_ZONE_DMA32
-	return zone == zone->zone_pgdat->node_zones + ZONE_DMA32;
+	return zone_idx(zone) == ZONE_DMA32;
 #else
 	return 0;
 #endif
@@ -883,7 +879,7 @@ static inline int is_dma32(struct zone *zone)
 static inline int is_dma(struct zone *zone)
 {
 #ifdef CONFIG_ZONE_DMA
-	return zone == zone->zone_pgdat->node_zones + ZONE_DMA;
+	return zone_idx(zone) == ZONE_DMA;
 #else
 	return 0;
 #endif
diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
index 779cf7c..b508016 100644
--- a/include/linux/mod_devicetable.h
+++ b/include/linux/mod_devicetable.h
@@ -9,6 +9,7 @@
 
 #ifdef __KERNEL__
 #include <linux/types.h>
+#include <linux/uuid.h>
 typedef unsigned long kernel_ulong_t;
 #endif
 
@@ -568,4 +569,12 @@ struct ipack_device_id {
 	__u32 device;			/* Device ID or IPACK_ANY_ID */
 };
 
+#define MEI_CL_MODULE_PREFIX "mei:"
+#define MEI_CL_NAME_SIZE 32
+
+struct mei_cl_device_id {
+	char name[MEI_CL_NAME_SIZE];
+	kernel_ulong_t driver_info;
+};
+
 #endif /* LINUX_MOD_DEVICETABLE_H */
diff --git a/include/linux/module.h b/include/linux/module.h
index ead1b57..46f1ea0 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -190,7 +190,7 @@ extern int modules_disabled; /* for sysctl */
 /* Get/put a kernel symbol (calls must be symmetric) */
 void *__symbol_get(const char *symbol);
 void *__symbol_get_gpl(const char *symbol);
-#define symbol_get(x) ((typeof(&x))(__symbol_get(MODULE_SYMBOL_PREFIX #x)))
+#define symbol_get(x) ((typeof(&x))(__symbol_get(VMLINUX_SYMBOL_STR(x))))
 
 /* modules using other modules: kdb wants to see this. */
 struct module_use {
@@ -453,7 +453,7 @@ extern void __module_put_and_exit(struct module *mod, long code)
 #ifdef CONFIG_MODULE_UNLOAD
 unsigned long module_refcount(struct module *mod);
 void __symbol_put(const char *symbol);
-#define symbol_put(x) __symbol_put(MODULE_SYMBOL_PREFIX #x)
+#define symbol_put(x) __symbol_put(VMLINUX_SYMBOL_STR(x))
 void symbol_put_addr(void *addr);
 
 /* Sometimes we know we already have a refcount, and it's easier not
diff --git a/include/linux/mount.h b/include/linux/mount.h
index 73005f9..b024d5c 100644
--- a/include/linux/mount.h
+++ b/include/linux/mount.h
@@ -76,6 +76,6 @@ extern struct vfsmount *vfs_kern_mount(struct file_system_type *type,
 extern void mnt_set_expiry(struct vfsmount *mnt, struct list_head *expiry_list);
 extern void mark_mounts_for_expiry(struct list_head *mounts);
 
-extern dev_t name_to_dev_t(char *name);
+extern dev_t name_to_dev_t(const char *name);
 
 #endif /* _LINUX_MOUNT_H */
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index f9ac289..a5cf4e8 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -362,10 +362,10 @@ struct mtd_partition;
 struct mtd_part_parser_data;
 
 extern int mtd_device_parse_register(struct mtd_info *mtd,
-			      const char **part_probe_types,
-			      struct mtd_part_parser_data *parser_data,
-			      const struct mtd_partition *defparts,
-			      int defnr_parts);
+				     const char * const *part_probe_types,
+				     struct mtd_part_parser_data *parser_data,
+				     const struct mtd_partition *defparts,
+				     int defnr_parts);
 #define mtd_device_register(master, parts, nr_parts)	\
 	mtd_device_parse_register(master, NULL, NULL, parts, nr_parts)
 extern int mtd_device_unregister(struct mtd_info *master);
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index ef52d9c..dd7953b 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -86,7 +86,6 @@ extern int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
 #define NAND_CMD_READOOB	0x50
 #define NAND_CMD_ERASE1		0x60
 #define NAND_CMD_STATUS		0x70
-#define NAND_CMD_STATUS_MULTI	0x71
 #define NAND_CMD_SEQIN		0x80
 #define NAND_CMD_RNDIN		0x85
 #define NAND_CMD_READID		0x90
@@ -105,25 +104,6 @@ extern int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
 #define NAND_CMD_RNDOUTSTART	0xE0
 #define NAND_CMD_CACHEDPROG	0x15
 
-/* Extended commands for AG-AND device */
-/*
- * Note: the command for NAND_CMD_DEPLETE1 is really 0x00 but
- *       there is no way to distinguish that from NAND_CMD_READ0
- *       until the remaining sequence of commands has been completed
- *       so add a high order bit and mask it off in the command.
- */
-#define NAND_CMD_DEPLETE1	0x100
-#define NAND_CMD_DEPLETE2	0x38
-#define NAND_CMD_STATUS_MULTI	0x71
-#define NAND_CMD_STATUS_ERROR	0x72
-/* multi-bank error status (banks 0-3) */
-#define NAND_CMD_STATUS_ERROR0	0x73
-#define NAND_CMD_STATUS_ERROR1	0x74
-#define NAND_CMD_STATUS_ERROR2	0x75
-#define NAND_CMD_STATUS_ERROR3	0x76
-#define NAND_CMD_STATUS_RESET	0x7f
-#define NAND_CMD_STATUS_CLEAR	0xff
-
 #define NAND_CMD_NONE		-1
 
 /* Status bits */
@@ -165,28 +145,8 @@ typedef enum {
  */
 /* Buswidth is 16 bit */
 #define NAND_BUSWIDTH_16	0x00000002
-/* Device supports partial programming without padding */
-#define NAND_NO_PADDING		0x00000004
 /* Chip has cache program function */
 #define NAND_CACHEPRG		0x00000008
-/* Chip has copy back function */
-#define NAND_COPYBACK		0x00000010
-/*
- * AND Chip which has 4 banks and a confusing page / block
- * assignment. See Renesas datasheet for further information.
- */
-#define NAND_IS_AND		0x00000020
-/*
- * Chip has a array of 4 pages which can be read without
- * additional ready /busy waits.
- */
-#define NAND_4PAGE_ARRAY	0x00000040
-/*
- * Chip requires that BBT is periodically rewritten to prevent
- * bits from adjacent blocks from 'leaking' in altering data.
- * This happens with the Renesas AG-AND chips, possibly others.
- */
-#define BBT_AUTO_REFRESH	0x00000080
 /*
  * Chip requires ready check on read (for auto-incremented sequential read).
  * True only for small page devices; large page devices do not support
@@ -207,13 +167,10 @@ typedef enum {
 #define NAND_SUBPAGE_READ	0x00001000
 
 /* Options valid for Samsung large page devices */
-#define NAND_SAMSUNG_LP_OPTIONS \
-	(NAND_NO_PADDING | NAND_CACHEPRG | NAND_COPYBACK)
+#define NAND_SAMSUNG_LP_OPTIONS NAND_CACHEPRG
 
 /* Macros to identify the above */
-#define NAND_MUST_PAD(chip) (!(chip->options & NAND_NO_PADDING))
 #define NAND_HAS_CACHEPROG(chip) ((chip->options & NAND_CACHEPRG))
-#define NAND_HAS_COPYBACK(chip) ((chip->options & NAND_COPYBACK))
 #define NAND_HAS_SUBPAGE_READ(chip) ((chip->options & NAND_SUBPAGE_READ))
 
 /* Non chip related options */
@@ -426,6 +383,8 @@ struct nand_buffers {
  *			flash device.
  * @read_byte:		[REPLACEABLE] read one byte from the chip
  * @read_word:		[REPLACEABLE] read one word from the chip
+ * @write_byte		[REPLACEABLE] write a single byte to the chip on the
+ *			low 8 I/O lines
  * @write_buf:		[REPLACEABLE] write data from the buffer to the chip
  * @read_buf:		[REPLACEABLE] read data from the chip into the buffer
  * @select_chip:	[REPLACEABLE] select chip nr
@@ -510,6 +469,7 @@ struct nand_chip {
 
 	uint8_t (*read_byte)(struct mtd_info *mtd);
 	u16 (*read_word)(struct mtd_info *mtd);
+	void (*write_byte)(struct mtd_info *mtd, uint8_t byte);
 	void (*write_buf)(struct mtd_info *mtd, const uint8_t *buf, int len);
 	void (*read_buf)(struct mtd_info *mtd, uint8_t *buf, int len);
 	void (*select_chip)(struct mtd_info *mtd, int chip);
@@ -589,25 +549,65 @@ struct nand_chip {
 #define NAND_MFR_MACRONIX	0xc2
 #define NAND_MFR_EON		0x92
 
+/* The maximum expected count of bytes in the NAND ID sequence */
+#define NAND_MAX_ID_LEN 8
+
+/*
+ * A helper for defining older NAND chips where the second ID byte fully
+ * defined the chip, including the geometry (chip size, eraseblock size, page
+ * size). All these chips have 512 bytes NAND page size.
+ */
+#define LEGACY_ID_NAND(nm, devid, chipsz, erasesz, opts)          \
+	{ .name = (nm), {{ .dev_id = (devid) }}, .pagesize = 512, \
+	  .chipsize = (chipsz), .erasesize = (erasesz), .options = (opts) }
+
+/*
+ * A helper for defining newer chips which report their page size and
+ * eraseblock size via the extended ID bytes.
+ *
+ * The real difference between LEGACY_ID_NAND and EXTENDED_ID_NAND is that with
+ * EXTENDED_ID_NAND, manufacturers overloaded the same device ID so that the
+ * device ID now only represented a particular total chip size (and voltage,
+ * buswidth), and the page size, eraseblock size, and OOB size could vary while
+ * using the same device ID.
+ */
+#define EXTENDED_ID_NAND(nm, devid, chipsz, opts)                      \
+	{ .name = (nm), {{ .dev_id = (devid) }}, .chipsize = (chipsz), \
+	  .options = (opts) }
+
 /**
  * struct nand_flash_dev - NAND Flash Device ID Structure
- * @name:	Identify the device type
- * @id:		device ID code
- * @pagesize:	Pagesize in bytes. Either 256 or 512 or 0
- *		If the pagesize is 0, then the real pagesize
- *		and the eraseize are determined from the
- *		extended id bytes in the chip
- * @erasesize:	Size of an erase block in the flash device.
- * @chipsize:	Total chipsize in Mega Bytes
- * @options:	Bitfield to store chip relevant options
+ * @name: a human-readable name of the NAND chip
+ * @dev_id: the device ID (the second byte of the full chip ID array)
+ * @mfr_id: manufecturer ID part of the full chip ID array (refers the same
+ *          memory address as @id[0])
+ * @dev_id: device ID part of the full chip ID array (refers the same memory
+ *          address as @id[1])
+ * @id: full device ID array
+ * @pagesize: size of the NAND page in bytes; if 0, then the real page size (as
+ *            well as the eraseblock size) is determined from the extended NAND
+ *            chip ID array)
+ * @chipsize: total chip size in MiB
+ * @erasesize: eraseblock size in bytes (determined from the extended ID if 0)
+ * @options: stores various chip bit options
+ * @id_len: The valid length of the @id.
+ * @oobsize: OOB size
  */
 struct nand_flash_dev {
 	char *name;
-	int id;
-	unsigned long pagesize;
-	unsigned long chipsize;
-	unsigned long erasesize;
-	unsigned long options;
+	union {
+		struct {
+			uint8_t mfr_id;
+			uint8_t dev_id;
+		};
+		uint8_t id[NAND_MAX_ID_LEN];
+	};
+	unsigned int pagesize;
+	unsigned int chipsize;
+	unsigned int erasesize;
+	unsigned int options;
+	uint16_t id_len;
+	uint16_t oobsize;
 };
 
 /**
diff --git a/include/linux/mtd/physmap.h b/include/linux/mtd/physmap.h
index d2887e7..aa6a263 100644
--- a/include/linux/mtd/physmap.h
+++ b/include/linux/mtd/physmap.h
@@ -30,7 +30,7 @@ struct physmap_flash_data {
 	unsigned int		pfow_base;
 	char                    *probe_type;
 	struct mtd_partition	*parts;
-	const char		**part_probe_types;
+	const char * const	*part_probe_types;
 };
 
 #endif /* __LINUX_MTD_PHYSMAP__ */
diff --git a/include/linux/mtd/plat-ram.h b/include/linux/mtd/plat-ram.h
index e07890a..44212d6 100644
--- a/include/linux/mtd/plat-ram.h
+++ b/include/linux/mtd/plat-ram.h
@@ -20,8 +20,8 @@
 
 struct platdata_mtd_ram {
 	const char		*mapname;
-	const char		**map_probes;
-	const char		**probes;
+	const char * const      *map_probes;
+	const char * const      *probes;
 	struct mtd_partition	*partitions;
 	int			 nr_partitions;
 	int			 bankwidth;
diff --git a/include/linux/mv643xx_eth.h b/include/linux/mv643xx_eth.h
index 49258e0..141d395 100644
--- a/include/linux/mv643xx_eth.h
+++ b/include/linux/mv643xx_eth.h
@@ -19,7 +19,6 @@
 
 struct mv643xx_eth_shared_platform_data {
 	struct mbus_dram_target_info	*dram;
-	struct platform_device	*shared_smi;
 	/*
 	 * Max packet size for Tx IP/Layer 4 checksum, when set to 0, default
 	 * limit of 9KiB will be used.
diff --git a/include/linux/mxsfb.h b/include/linux/mxsfb.h
deleted file mode 100644
index f80af86..0000000
--- a/include/linux/mxsfb.h
+++ /dev/null
@@ -1,52 +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., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#ifndef __LINUX_MXSFB_H
-#define __LINUX_MXSFB_H
-
-#include <linux/fb.h>
-
-#define STMLCDIF_8BIT 1	/** pixel data bus to the display is of 8 bit width */
-#define STMLCDIF_16BIT 0 /** pixel data bus to the display is of 16 bit width */
-#define STMLCDIF_18BIT 2 /** pixel data bus to the display is of 18 bit width */
-#define STMLCDIF_24BIT 3 /** pixel data bus to the display is of 24 bit width */
-
-#define MXSFB_SYNC_DATA_ENABLE_HIGH_ACT	(1 << 6)
-#define MXSFB_SYNC_DOTCLK_FAILING_ACT	(1 << 7) /* failing/negtive edge sampling */
-
-struct mxsfb_platform_data {
-	struct fb_videomode *mode_list;
-	unsigned mode_count;
-
-	unsigned default_bpp;
-
-	unsigned dotclk_delay;	/* refer manual HW_LCDIF_VDCTRL4 register */
-	unsigned ld_intf_width;	/* refer STMLCDIF_* macros */
-
-	unsigned fb_size;	/* Size of the video memory. If zero a
-				 * default will be used
-				 */
-	unsigned long fb_phys;	/* physical address for the video memory. If
-				 * zero the framebuffer memory will be dynamically
-				 * allocated. If specified,fb_size must also be specified.
-				 * fb_phys must be unused by Linux.
-				 */
-	u32 sync;		/* sync mask, contains MXSFB specifics not
-				 * carried in fb_info->var.sync
-				 */
-};
-
-#endif /* __LINUX_MXSFB_H */
diff --git a/include/linux/net.h b/include/linux/net.h
index aa16731..99c9f0c 100644
--- a/include/linux/net.h
+++ b/include/linux/net.h
@@ -240,8 +240,8 @@ do {								\
 #define net_dbg_ratelimited(fmt, ...)				\
 	net_ratelimited_function(pr_debug, fmt, ##__VA_ARGS__)
 
-#define net_random()		random32()
-#define net_srandom(seed)	srandom32((__force u32)seed)
+#define net_random()		prandom_u32()
+#define net_srandom(seed)	prandom_seed((__force u32)(seed))
 
 extern int   	     kernel_sendmsg(struct socket *sock, struct msghdr *msg,
 				    struct kvec *vec, size_t num, size_t len);
diff --git a/include/linux/netdev_features.h b/include/linux/netdev_features.h
index 3dd3934..d6ee2d0 100644
--- a/include/linux/netdev_features.h
+++ b/include/linux/netdev_features.h
@@ -42,9 +42,9 @@ enum {
 	NETIF_F_TSO6_BIT,		/* ... TCPv6 segmentation */
 	NETIF_F_FSO_BIT,		/* ... FCoE segmentation */
 	NETIF_F_GSO_GRE_BIT,		/* ... GRE with TSO */
-	/**/NETIF_F_GSO_LAST,		/* [can't be last bit, see GSO_MASK] */
-	NETIF_F_GSO_RESERVED2		/* ... free (fill GSO_MASK to 8 bits) */
-		= NETIF_F_GSO_LAST,
+	NETIF_F_GSO_UDP_TUNNEL_BIT,	/* ... UDP TUNNEL with TSO */
+	/**/NETIF_F_GSO_LAST =		/* last bit, see GSO_MASK */
+		NETIF_F_GSO_UDP_TUNNEL_BIT,
 
 	NETIF_F_FCOE_CRC_BIT,		/* FCoE CRC32 */
 	NETIF_F_SCTP_CSUM_BIT,		/* SCTP checksum offload */
@@ -102,7 +102,8 @@ enum {
 #define NETIF_F_VLAN_CHALLENGED	__NETIF_F(VLAN_CHALLENGED)
 #define NETIF_F_RXFCS		__NETIF_F(RXFCS)
 #define NETIF_F_RXALL		__NETIF_F(RXALL)
-#define NETIF_F_GRE_GSO		__NETIF_F(GSO_GRE)
+#define NETIF_F_GSO_GRE		__NETIF_F(GSO_GRE)
+#define NETIF_F_GSO_UDP_TUNNEL	__NETIF_F(GSO_UDP_TUNNEL)
 
 /* Features valid for ethtool to change */
 /* = all defined minus driver/device-class-related */
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index b3d00fa..a302f7f 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -144,8 +144,6 @@ static inline bool dev_xmit_complete(int rc)
 # else
 #  define LL_MAX_HEADER 96
 # endif
-#elif IS_ENABLED(CONFIG_TR)
-# define LL_MAX_HEADER 48
 #else
 # define LL_MAX_HEADER 32
 #endif
@@ -895,7 +893,7 @@ struct netdev_fcoe_hbainfo {
  *
  * int (*ndo_bridge_setlink)(struct net_device *dev, struct nlmsghdr *nlh)
  * int (*ndo_bridge_getlink)(struct sk_buff *skb, u32 pid, u32 seq,
- *			     struct net_device *dev)
+ *			     struct net_device *dev, u32 filter_mask)
  *
  * int (*ndo_change_carrier)(struct net_device *dev, bool new_carrier);
  *	Called to change device carrier. Soft-devices (like dummy, team, etc)
@@ -1073,6 +1071,8 @@ struct net_device {
 	struct list_head	dev_list;
 	struct list_head	napi_list;
 	struct list_head	unreg_list;
+	struct list_head	upper_dev_list; /* List of upper devices */
+
 
 	/* currently active device features */
 	netdev_features_t	features;
@@ -1145,6 +1145,13 @@ 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 */
+	struct netdev_hw_addr_list	dev_addrs; /* list of device
+						    * hw addresses
+						    */
+#ifdef CONFIG_SYSFS
+	struct kset		*queues_kset;
+#endif
+
 	bool			uc_promisc;
 	unsigned int		promiscuity;
 	unsigned int		allmulti;
@@ -1177,21 +1184,11 @@ struct net_device {
 						 * avoid dirtying this cache line.
 						 */
 
-	struct list_head	upper_dev_list; /* List of upper devices */
-
 	/* Interface address info used in eth_type_trans() */
 	unsigned char		*dev_addr;	/* hw address, (before bcast
 						   because most packets are
 						   unicast) */
 
-	struct netdev_hw_addr_list	dev_addrs; /* list of device
-						      hw addresses */
-
-	unsigned char		broadcast[MAX_ADDR_LEN];	/* hw bcast add	*/
-
-#ifdef CONFIG_SYSFS
-	struct kset		*queues_kset;
-#endif
 
 #ifdef CONFIG_RPS
 	struct netdev_rx_queue	*_rx;
@@ -1202,18 +1199,14 @@ struct net_device {
 	/* Number of RX queues currently active in device */
 	unsigned int		real_num_rx_queues;
 
-#ifdef CONFIG_RFS_ACCEL
-	/* CPU reverse-mapping for RX completion interrupts, indexed
-	 * by RX queue number.  Assigned by driver.  This must only be
-	 * set if the ndo_rx_flow_steer operation is defined. */
-	struct cpu_rmap		*rx_cpu_rmap;
-#endif
 #endif
 
 	rx_handler_func_t __rcu	*rx_handler;
 	void __rcu		*rx_handler_data;
 
 	struct netdev_queue __rcu *ingress_queue;
+	unsigned char		broadcast[MAX_ADDR_LEN];	/* hw bcast add	*/
+
 
 /*
  * Cache lines mostly used on transmit path
@@ -1235,6 +1228,12 @@ struct net_device {
 #ifdef CONFIG_XPS
 	struct xps_dev_maps __rcu *xps_maps;
 #endif
+#ifdef CONFIG_RFS_ACCEL
+	/* CPU reverse-mapping for RX completion interrupts, indexed
+	 * by RX queue number.  Assigned by driver.  This must only be
+	 * set if the ndo_rx_flow_steer operation is defined. */
+	struct cpu_rmap		*rx_cpu_rmap;
+#endif
 
 	/* These may be needed for future network-power-down code. */
 
@@ -1475,6 +1474,11 @@ static inline void *netdev_priv(const struct net_device *dev)
  */
 #define SET_NETDEV_DEVTYPE(net, devtype)	((net)->dev.type = (devtype))
 
+/* Default NAPI poll() weight
+ * Device drivers are strongly advised to not use bigger value
+ */
+#define NAPI_POLL_WEIGHT 64
+
 /**
  *	netif_napi_add - initialize a napi context
  *	@dev:  network device
@@ -1612,6 +1616,9 @@ extern seqcount_t	devnet_rename_seq;	/* Device rename seq */
 		list_for_each_entry_continue(d, &(net)->dev_base_head, dev_list)
 #define for_each_netdev_continue_rcu(net, d)		\
 	list_for_each_entry_continue_rcu(d, &(net)->dev_base_head, dev_list)
+#define for_each_netdev_in_bond_rcu(bond, slave)	\
+		for_each_netdev_rcu(&init_net, slave)	\
+			if (netdev_master_upper_dev_get_rcu(slave) == bond)
 #define net_device_entry(lh)	list_entry(lh, struct net_device, dev_list)
 
 static inline struct net_device *next_net_device(struct net_device *dev)
@@ -1684,7 +1691,6 @@ 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		init_dummy_netdev(struct net_device *dev);
-extern void		netdev_resync_ops(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);
@@ -2678,6 +2684,19 @@ struct sk_buff *skb_gso_segment(struct sk_buff *skb, netdev_features_t features)
 {
 	return __skb_gso_segment(skb, features, true);
 }
+__be16 skb_network_protocol(struct sk_buff *skb);
+
+static inline bool can_checksum_protocol(netdev_features_t features,
+					 __be16 protocol)
+{
+	return ((features & NETIF_F_GEN_CSUM) ||
+		((features & NETIF_F_V4_CSUM) &&
+		 protocol == htons(ETH_P_IP)) ||
+		((features & NETIF_F_V6_CSUM) &&
+		 protocol == htons(ETH_P_IPV6)) ||
+		((features & NETIF_F_FCOE_CRC) &&
+		 protocol == htons(ETH_P_FCOE)));
+}
 
 #ifdef CONFIG_BUG
 extern void netdev_rx_csum_fault(struct net_device *dev);
@@ -2756,6 +2775,11 @@ static inline void netif_set_gso_max_size(struct net_device *dev,
 	dev->gso_max_size = size;
 }
 
+static inline bool netif_is_bond_master(struct net_device *dev)
+{
+	return dev->flags & IFF_MASTER && dev->priv_flags & IFF_BONDING;
+}
+
 static inline bool netif_is_bond_slave(struct net_device *dev)
 {
 	return dev->flags & IFF_SLAVE && dev->priv_flags & IFF_BONDING;
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 1cc2568..f6b1956 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -77,6 +77,7 @@ struct nfs_open_context {
 	unsigned long flags;
 #define NFS_CONTEXT_ERROR_WRITE		(0)
 #define NFS_CONTEXT_RESEND_WRITES	(1)
+#define NFS_CONTEXT_BAD			(2)
 	int error;
 
 	struct list_head list;
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index 6c6ed15..d8fdfdc 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -197,5 +197,7 @@ struct nfs_server {
 #define NFS_CAP_MTIME		(1U << 13)
 #define NFS_CAP_POSIX_LOCK	(1U << 14)
 #define NFS_CAP_UIDGID_NOMAP	(1U << 15)
+#define NFS_CAP_STATEID_NFSV41	(1U << 16)
+#define NFS_CAP_ATOMIC_OPEN_V1	(1U << 17)
 
 #endif
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 4b993d3..b759467 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -14,9 +14,6 @@
 #define NFS_DEF_FILE_IO_SIZE	(4096U)
 #define NFS_MIN_FILE_IO_SIZE	(1024U)
 
-/* Forward declaration for NFS v3 */
-struct nfs4_secinfo_flavors;
-
 struct nfs4_string {
 	unsigned int len;
 	char *data;
@@ -486,6 +483,7 @@ struct nfs_readargs {
 	struct nfs_fh *		fh;
 	struct nfs_open_context *context;
 	struct nfs_lock_context *lock_context;
+	nfs4_stateid		stateid;
 	__u64			offset;
 	__u32			count;
 	unsigned int		pgbase;
@@ -507,6 +505,7 @@ struct nfs_writeargs {
 	struct nfs_fh *		fh;
 	struct nfs_open_context *context;
 	struct nfs_lock_context *lock_context;
+	nfs4_stateid		stateid;
 	__u64			offset;
 	__u32			count;
 	enum nfs3_stable_how	stable;
@@ -1050,25 +1049,14 @@ struct nfs4_fs_locations_res {
 	struct nfs4_fs_locations       *fs_locations;
 };
 
-struct nfs4_secinfo_oid {
-	unsigned int len;
-	char data[GSS_OID_MAX_LEN];
-};
-
-struct nfs4_secinfo_gss {
-	struct nfs4_secinfo_oid sec_oid4;
-	unsigned int qop4;
-	unsigned int service;
-};
-
-struct nfs4_secinfo_flavor {
-	unsigned int 		flavor;
-	struct nfs4_secinfo_gss	gss;
+struct nfs4_secinfo4 {
+	u32			flavor;
+	struct rpcsec_gss_info	flavor_info;
 };
 
 struct nfs4_secinfo_flavors {
-	unsigned int num_flavors;
-	struct nfs4_secinfo_flavor flavors[0];
+	unsigned int		num_flavors;
+	struct nfs4_secinfo4	flavors[0];
 };
 
 struct nfs4_secinfo_arg {
diff --git a/include/linux/of_dma.h b/include/linux/of_dma.h
index d15073e..ce6a8ab 100644
--- a/include/linux/of_dma.h
+++ b/include/linux/of_dma.h
@@ -40,7 +40,7 @@ extern int of_dma_controller_register(struct device_node *np,
 		void *data);
 extern int of_dma_controller_free(struct device_node *np);
 extern struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
-						     char *name);
+						     const char *name);
 extern struct dma_chan *of_dma_simple_xlate(struct of_phandle_args *dma_spec,
 		struct of_dma *ofdma);
 #else
@@ -58,7 +58,7 @@ static inline int of_dma_controller_free(struct device_node *np)
 }
 
 static inline struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
-						     char *name)
+						     const char *name)
 {
 	return NULL;
 }
diff --git a/include/linux/of_net.h b/include/linux/of_net.h
index f474641..61bf53b 100644
--- a/include/linux/of_net.h
+++ b/include/linux/of_net.h
@@ -11,6 +11,16 @@
 #include <linux/of.h>
 extern const int of_get_phy_mode(struct device_node *np);
 extern const void *of_get_mac_address(struct device_node *np);
+#else
+static inline const int of_get_phy_mode(struct device_node *np)
+{
+	return -ENODEV;
+}
+
+static inline const void *of_get_mac_address(struct device_node *np)
+{
+	return NULL;
+}
 #endif
 
 #endif /* __LINUX_OF_NET_H */
diff --git a/include/linux/openvswitch.h b/include/linux/openvswitch.h
index d42e174..67d6c7b 100644
--- a/include/linux/openvswitch.h
+++ b/include/linux/openvswitch.h
@@ -94,7 +94,7 @@ struct ovs_vport_stats {
 };
 
 /* Fixed logical ports. */
-#define OVSP_LOCAL      ((__u16)0)
+#define OVSP_LOCAL      ((__u32)0)
 
 /* Packet transfer. */
 
@@ -127,7 +127,8 @@ enum ovs_packet_cmd {
  * for %OVS_PACKET_CMD_EXECUTE.  It has nested %OVS_ACTION_ATTR_* attributes.
  * @OVS_PACKET_ATTR_USERDATA: Present for an %OVS_PACKET_CMD_ACTION
  * notification if the %OVS_ACTION_ATTR_USERSPACE action specified an
- * %OVS_USERSPACE_ATTR_USERDATA attribute.
+ * %OVS_USERSPACE_ATTR_USERDATA attribute, with the same length and content
+ * specified there.
  *
  * These attributes follow the &struct ovs_header within the Generic Netlink
  * payload for %OVS_PACKET_* commands.
@@ -137,7 +138,7 @@ enum ovs_packet_attr {
 	OVS_PACKET_ATTR_PACKET,      /* Packet data. */
 	OVS_PACKET_ATTR_KEY,         /* Nested OVS_KEY_ATTR_* attributes. */
 	OVS_PACKET_ATTR_ACTIONS,     /* Nested OVS_ACTION_ATTR_* attributes. */
-	OVS_PACKET_ATTR_USERDATA,    /* u64 OVS_ACTION_ATTR_USERSPACE arg. */
+	OVS_PACKET_ATTR_USERDATA,    /* OVS_ACTION_ATTR_USERSPACE arg. */
 	__OVS_PACKET_ATTR_MAX
 };
 
@@ -389,13 +390,13 @@ enum ovs_sample_attr {
  * enum ovs_userspace_attr - Attributes for %OVS_ACTION_ATTR_USERSPACE action.
  * @OVS_USERSPACE_ATTR_PID: u32 Netlink PID to which the %OVS_PACKET_CMD_ACTION
  * message should be sent.  Required.
- * @OVS_USERSPACE_ATTR_USERDATA: If present, its u64 argument is copied to the
- * %OVS_PACKET_CMD_ACTION message as %OVS_PACKET_ATTR_USERDATA,
+ * @OVS_USERSPACE_ATTR_USERDATA: If present, its variable-length argument is
+ * copied to the %OVS_PACKET_CMD_ACTION message as %OVS_PACKET_ATTR_USERDATA.
  */
 enum ovs_userspace_attr {
 	OVS_USERSPACE_ATTR_UNSPEC,
 	OVS_USERSPACE_ATTR_PID,	      /* u32 Netlink PID to receive upcalls. */
-	OVS_USERSPACE_ATTR_USERDATA,  /* u64 optional user-specified cookie. */
+	OVS_USERSPACE_ATTR_USERDATA,  /* Optional user-specified cookie. */
 	__OVS_USERSPACE_ATTR_MAX
 };
 
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
index 0e38e13..e3dea75 100644
--- a/include/linux/pagemap.h
+++ b/include/linux/pagemap.h
@@ -149,7 +149,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_TINY_RCU
 # ifdef CONFIG_PREEMPT_COUNT
 	VM_BUG_ON(!in_atomic());
 # endif
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 2461033a..f42cdc6 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -35,6 +35,21 @@
 /* Include the ID list */
 #include <linux/pci_ids.h>
 
+/*
+ * The PCI interface treats multi-function devices as independent
+ * devices.  The slot/function address of each device is encoded
+ * in a single byte as follows:
+ *
+ *	7:3 = slot
+ *	2:0 = function
+ * PCI_DEVFN(), PCI_SLOT(), and PCI_FUNC() are defined uapi/linux/pci.h
+ * In the interest of not exposing interfaces to user-space unnecessarily,
+ * the following kernel only defines are being added here.
+ */
+#define PCI_DEVID(bus, devfn)  ((((u16)bus) << 8) | devfn)
+/* return bus from PCI devid = ((u16)bus_number) << 8) | devfn */
+#define PCI_BUS_NUM(x) (((x) >> 8) & 0xff)
+
 /* pci_slot represents a physical slot */
 struct pci_slot {
 	struct pci_bus *bus;		/* The bus this slot is on */
@@ -916,6 +931,7 @@ void pci_disable_rom(struct pci_dev *pdev);
 void __iomem __must_check *pci_map_rom(struct pci_dev *pdev, size_t *size);
 void pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom);
 size_t pci_get_rom_size(struct pci_dev *pdev, void __iomem *rom, size_t size);
+void __iomem __must_check *pci_platform_rom(struct pci_dev *pdev, size_t *size);
 
 /* Power management related routines */
 int pci_save_state(struct pci_dev *dev);
diff --git a/include/linux/percpu-refcount.h b/include/linux/percpu-refcount.h
new file mode 100644
index 0000000..d0cf887
--- /dev/null
+++ b/include/linux/percpu-refcount.h
@@ -0,0 +1,114 @@
+/*
+ * Dynamic percpu refcounts:
+ * (C) 2012 Google, Inc.
+ * Author: Kent Overstreet <koverstreet@google.com>
+ *
+ * This implements a refcount with similar semantics to atomic_t - atomic_inc(),
+ * atomic_dec_and_test() - but potentially percpu.
+ *
+ * There's one important difference between percpu refs and normal atomic_t
+ * refcounts; you have to keep track of your initial refcount, and then when you
+ * start shutting down you call percpu_ref_kill() _before_ dropping the initial
+ * refcount.
+ *
+ * Before you call percpu_ref_kill(), percpu_ref_put() does not check for the
+ * refcount hitting 0 - it can't, if it was in percpu mode. percpu_ref_kill()
+ * puts the ref back in single atomic_t mode, collecting the per cpu refs and
+ * issuing the appropriate barriers, and then marks the ref as shutting down so
+ * that percpu_ref_put() will check for the ref hitting 0.  After it returns,
+ * it's safe to drop the initial ref.
+ *
+ * BACKGROUND:
+ *
+ * Percpu refcounts are quite useful for performance, but if we blindly
+ * converted all refcounts to percpu counters we'd waste quite a bit of memory.
+ *
+ * Think about all the refcounts embedded in kobjects, files, etc. most of which
+ * aren't used much. These start out as simple atomic counters - a little bigger
+ * than a bare atomic_t, 16 bytes instead of 4 - but if we exceed some arbitrary
+ * number of gets in one second, we then switch to percpu counters.
+ *
+ * This heuristic isn't perfect because it'll fire if the refcount was only
+ * being used on one cpu; ideally we'd be able to count the number of cache
+ * misses on percpu_ref_get() or something similar, but that'd make the non
+ * percpu path significantly heavier/more complex. We can count the number of
+ * gets() without any extra atomic instructions on arches that support
+ * atomic64_t - simply by changing the atomic_inc() to atomic_add_return().
+ *
+ * USAGE:
+ *
+ * See fs/aio.c for some example usage; it's used there for struct kioctx, which
+ * is created when userspaces calls io_setup(), and destroyed when userspace
+ * calls io_destroy() or the process exits.
+ *
+ * In the aio code, kill_ioctx() is called when we wish to destroy a kioctx; it
+ * calls percpu_ref_kill(), then hlist_del_rcu() and sychronize_rcu() to remove
+ * the kioctx from the proccess's list of kioctxs - after that, there can't be
+ * any new users of the kioctx (from lookup_ioctx()) and it's then safe to drop
+ * the initial ref with percpu_ref_put().
+ *
+ * Code that does a two stage shutdown like this often needs some kind of
+ * explicit synchronization to ensure the initial refcount can only be dropped
+ * once - percpu_ref_kill() does this for you, it returns true once and false if
+ * someone else already called it. The aio code uses it this way, but it's not
+ * necessary if the code has some other mechanism to synchronize teardown.
+ *
+ * As mentioned previously, we decide when to convert a ref to percpu counters
+ * in percpu_ref_get(). However, since percpu_ref_get() will often be called
+ * with rcu_read_lock() held, it's not done there - percpu_ref_get() returns
+ * true if the ref should be converted to percpu counters.
+ *
+ * The caller should then call percpu_ref_alloc() after dropping
+ * rcu_read_lock(); if there is an uncommonly used codepath where it's
+ * inconvenient to call percpu_ref_alloc() after get(), it may be safely skipped
+ * and percpu_ref_get() will return true again the next time the counter wraps
+ * around.
+ */
+
+#ifndef _LINUX_PERCPU_REFCOUNT_H
+#define _LINUX_PERCPU_REFCOUNT_H
+
+#include <linux/atomic.h>
+#include <linux/percpu.h>
+
+struct percpu_ref {
+	atomic64_t		count;
+	unsigned long		pcpu_count;
+};
+
+void percpu_ref_init(struct percpu_ref *ref);
+void __percpu_ref_get(struct percpu_ref *ref, bool alloc);
+int percpu_ref_put(struct percpu_ref *ref);
+
+int percpu_ref_kill(struct percpu_ref *ref);
+int percpu_ref_dead(struct percpu_ref *ref);
+
+/**
+ * percpu_ref_get - increment a dynamic percpu refcount
+ *
+ * Increments @ref and possibly converts it to percpu counters. Must be called
+ * with rcu_read_lock() held, and may potentially drop/reacquire rcu_read_lock()
+ * to allocate percpu counters - if sleeping/allocation isn't safe for some
+ * other reason (e.g. a spinlock), see percpu_ref_get_noalloc().
+ *
+ * Analagous to atomic_inc().
+  */
+static inline void percpu_ref_get(struct percpu_ref *ref)
+{
+	__percpu_ref_get(ref, true);
+}
+
+/**
+ * percpu_ref_get_noalloc - increment a dynamic percpu refcount
+ *
+ * Increments @ref, to be used when it's not safe to allocate percpu counters.
+ * Must be called with rcu_read_lock() held.
+ *
+ * Analagous to atomic_inc().
+  */
+static inline void percpu_ref_get_noalloc(struct percpu_ref *ref)
+{
+	__percpu_ref_get(ref, false);
+}
+
+#endif
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 1d795df..12a1aa2 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -21,7 +21,6 @@
  */
 
 #ifdef CONFIG_PERF_EVENTS
-# include <linux/cgroup.h>
 # include <asm/perf_event.h>
 # include <asm/local64.h>
 #endif
@@ -299,22 +298,7 @@ struct swevent_hlist {
 #define PERF_ATTACH_GROUP	0x02
 #define PERF_ATTACH_TASK	0x04
 
-#ifdef CONFIG_CGROUP_PERF
-/*
- * perf_cgroup_info keeps track of time_enabled for a cgroup.
- * This is a per-cpu dynamically allocated data structure.
- */
-struct perf_cgroup_info {
-	u64				time;
-	u64				timestamp;
-};
-
-struct perf_cgroup {
-	struct				cgroup_subsys_state css;
-	struct				perf_cgroup_info *info;	/* timing info, one per cpu */
-};
-#endif
-
+struct perf_cgroup;
 struct ring_buffer;
 
 /**
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 33999ad..9e11039 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -455,6 +455,14 @@ struct phy_driver {
 	 */
 	void (*txtstamp)(struct phy_device *dev, struct sk_buff *skb, int type);
 
+	/* Some devices (e.g. qnap TS-119P II) require PHY register changes to
+	 * enable Wake on LAN, so set_wol is provided to be called in the
+	 * ethernet driver's set_wol function. */
+	int (*set_wol)(struct phy_device *dev, struct ethtool_wolinfo *wol);
+
+	/* See set_wol, but for checking whether Wake on LAN is enabled. */
+	void (*get_wol)(struct phy_device *dev, struct ethtool_wolinfo *wol);
+
 	struct device_driver driver;
 };
 #define to_phy_driver(d) container_of(d, struct phy_driver, driver)
@@ -560,6 +568,8 @@ int phy_init_eee(struct phy_device *phydev, bool clk_stop_enable);
 int phy_get_eee_err(struct phy_device *phydev);
 int phy_ethtool_set_eee(struct phy_device *phydev, struct ethtool_eee *data);
 int phy_ethtool_get_eee(struct phy_device *phydev, struct ethtool_eee *data);
+int phy_ethtool_set_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol);
+void phy_ethtool_get_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol);
 
 int __init mdio_bus_init(void);
 void mdio_bus_exit(void);
diff --git a/include/linux/pid_namespace.h b/include/linux/pid_namespace.h
index 215e5e3..e277266 100644
--- a/include/linux/pid_namespace.h
+++ b/include/linux/pid_namespace.h
@@ -4,6 +4,7 @@
 #include <linux/sched.h>
 #include <linux/bug.h>
 #include <linux/mm.h>
+#include <linux/workqueue.h>
 #include <linux/threads.h>
 #include <linux/nsproxy.h>
 #include <linux/kref.h>
@@ -13,7 +14,9 @@ struct pidmap {
        void *page;
 };
 
-#define PIDMAP_ENTRIES         ((PID_MAX_LIMIT + 8*PAGE_SIZE - 1)/PAGE_SIZE/8)
+#define BITS_PER_PAGE		(PAGE_SIZE * 8)
+#define BITS_PER_PAGE_MASK	(BITS_PER_PAGE-1)
+#define PIDMAP_ENTRIES		((PID_MAX_LIMIT+BITS_PER_PAGE-1)/BITS_PER_PAGE)
 
 struct bsd_acct_struct;
 
@@ -28,6 +31,7 @@ struct pid_namespace {
 	struct pid_namespace *parent;
 #ifdef CONFIG_PROC_FS
 	struct vfsmount *proc_mnt;
+	struct dentry *proc_self;
 #endif
 #ifdef CONFIG_BSD_PROCESS_ACCT
 	struct bsd_acct_struct *bacct;
diff --git a/include/linux/pinctrl/pinctrl.h b/include/linux/pinctrl/pinctrl.h
index 778804d..2c2a9e8 100644
--- a/include/linux/pinctrl/pinctrl.h
+++ b/include/linux/pinctrl/pinctrl.h
@@ -118,9 +118,9 @@ struct pinctrl_desc {
 	const char *name;
 	struct pinctrl_pin_desc const *pins;
 	unsigned int npins;
-	struct pinctrl_ops *pctlops;
-	struct pinmux_ops *pmxops;
-	struct pinconf_ops *confops;
+	const struct pinctrl_ops *pctlops;
+	const struct pinmux_ops *pmxops;
+	const struct pinconf_ops *confops;
 	struct module *owner;
 };
 
diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h
index ad1a427..b8809fe 100644
--- a/include/linux/pipe_fs_i.h
+++ b/include/linux/pipe_fs_i.h
@@ -27,6 +27,7 @@ struct pipe_buffer {
 
 /**
  *	struct pipe_inode_info - a linux kernel pipe
+ *	@mutex: mutex protecting the whole thing
  *	@wait: reader/writer wait point in case of empty/full pipe
  *	@nrbufs: the number of non-empty pipe buffers in this pipe
  *	@buffers: total number of buffers (should be a power of 2)
@@ -34,26 +35,27 @@ struct pipe_buffer {
  *	@tmp_page: cached released page
  *	@readers: number of current readers of this pipe
  *	@writers: number of current writers of this pipe
+ *	@files: number of struct file refering this pipe (protected by ->i_lock)
  *	@waiting_writers: number of writers blocked waiting for room
  *	@r_counter: reader counter
  *	@w_counter: writer counter
  *	@fasync_readers: reader side fasync
  *	@fasync_writers: writer side fasync
- *	@inode: inode this pipe is attached to
  *	@bufs: the circular array of pipe buffers
  **/
 struct pipe_inode_info {
+	struct mutex mutex;
 	wait_queue_head_t wait;
 	unsigned int nrbufs, curbuf, buffers;
 	unsigned int readers;
 	unsigned int writers;
+	unsigned int files;
 	unsigned int waiting_writers;
 	unsigned int r_counter;
 	unsigned int w_counter;
 	struct page *tmp_page;
 	struct fasync_struct *fasync_readers;
 	struct fasync_struct *fasync_writers;
-	struct inode *inode;
 	struct pipe_buffer *bufs;
 };
 
@@ -144,9 +146,8 @@ int pipe_proc_fn(struct ctl_table *, int, void __user *, size_t *, loff_t *);
 /* Drop the inode semaphore and wait for a pipe event, atomically */
 void pipe_wait(struct pipe_inode_info *pipe);
 
-struct pipe_inode_info * alloc_pipe_info(struct inode * inode);
-void free_pipe_info(struct inode * inode);
-void __free_pipe_info(struct pipe_inode_info *);
+struct pipe_inode_info *alloc_pipe_info(void);
+void free_pipe_info(struct pipe_inode_info *);
 
 /* Generic pipe buffer ops functions */
 void *generic_pipe_buf_map(struct pipe_inode_info *, struct pipe_buffer *, int);
diff --git a/include/linux/pl320-ipc.h b/include/linux/pl320-ipc.h
new file mode 100644
index 0000000..5161f63
--- /dev/null
+++ b/include/linux/pl320-ipc.h
@@ -0,0 +1,17 @@
+/*
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+int pl320_ipc_transmit(u32 *data);
+int pl320_ipc_register_notifier(struct notifier_block *nb);
+int pl320_ipc_unregister_notifier(struct notifier_block *nb);
diff --git a/include/linux/platform_data/atmel-aes.h b/include/linux/platform_data/atmel-aes.h
deleted file mode 100644
index ab68082..0000000
--- a/include/linux/platform_data/atmel-aes.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef __LINUX_ATMEL_AES_H
-#define __LINUX_ATMEL_AES_H
-
-#include <linux/platform_data/dma-atmel.h>
-
-/**
- * struct aes_dma_data - DMA data for AES
- */
-struct aes_dma_data {
-	struct at_dma_slave	txdata;
-	struct at_dma_slave	rxdata;
-};
-
-/**
- * struct aes_platform_data - board-specific AES configuration
- * @dma_slave: DMA slave interface to use in data transfers.
- */
-struct aes_platform_data {
-	struct aes_dma_data	*dma_slave;
-};
-
-#endif /* __LINUX_ATMEL_AES_H */
diff --git a/include/linux/platform_data/clk-lpss.h b/include/linux/platform_data/clk-lpss.h
new file mode 100644
index 0000000..528e73c
--- /dev/null
+++ b/include/linux/platform_data/clk-lpss.h
@@ -0,0 +1,18 @@
+/*
+ * Intel Low Power Subsystem clocks.
+ *
+ * Copyright (C) 2013, Intel Corporation
+ * Authors: Mika Westerberg <mika.westerberg@linux.intel.com>
+ *          Rafael J. Wysocki <rafael.j.wysocki@intel.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 __CLK_LPSS_H
+#define __CLK_LPSS_H
+
+extern int lpt_clk_init(void);
+
+#endif /* __CLK_LPSS_H */
diff --git a/include/linux/platform_data/cpsw.h b/include/linux/platform_data/cpsw.h
index 798fb80..bb3cd58 100644
--- a/include/linux/platform_data/cpsw.h
+++ b/include/linux/platform_data/cpsw.h
@@ -30,7 +30,7 @@ struct cpsw_platform_data {
 	u32	channels;	/* number of cpdma channels (symmetric) */
 	u32	slaves;		/* number of slave cpgmac ports */
 	struct cpsw_slave_data	*slave_data;
-	u32	cpts_active_slave; /* time stamping slave */
+	u32	active_slave; /* time stamping, ethtool and SIOCGMIIPHY slave */
 	u32	cpts_clock_mult;  /* convert input clock ticks to nanoseconds */
 	u32	cpts_clock_shift; /* convert input clock ticks to nanoseconds */
 	u32	ale_entries;	/* ale table size */
diff --git a/include/linux/platform_data/crypto-atmel.h b/include/linux/platform_data/crypto-atmel.h
new file mode 100644
index 0000000..b46e0d9
--- /dev/null
+++ b/include/linux/platform_data/crypto-atmel.h
@@ -0,0 +1,22 @@
+#ifndef __LINUX_CRYPTO_ATMEL_H
+#define __LINUX_CRYPTO_ATMEL_H
+
+#include <linux/platform_data/dma-atmel.h>
+
+/**
+ * struct crypto_dma_data - DMA data for AES/TDES/SHA
+ */
+struct crypto_dma_data {
+	struct at_dma_slave	txdata;
+	struct at_dma_slave	rxdata;
+};
+
+/**
+ * struct crypto_platform_data - board-specific AES/TDES/SHA configuration
+ * @dma_slave: DMA slave interface to use in data transfers.
+ */
+struct crypto_platform_data {
+	struct crypto_dma_data	*dma_slave;
+};
+
+#endif /* __LINUX_CRYPTO_ATMEL_H */
diff --git a/include/linux/platform_data/dwc3-omap.h b/include/linux/platform_data/dwc3-omap.h
index ada4012..1d36ca8 100644
--- a/include/linux/platform_data/dwc3-omap.h
+++ b/include/linux/platform_data/dwc3-omap.h
@@ -41,7 +41,3 @@ enum dwc3_omap_utmi_mode {
 	DWC3_OMAP_UTMI_MODE_HW,
 	DWC3_OMAP_UTMI_MODE_SW,
 };
-
-struct dwc3_omap_data {
-	enum dwc3_omap_utmi_mode	utmi_mode;
-};
diff --git a/include/linux/platform_data/elm.h b/include/linux/platform_data/elm.h
index 1bd5244..bf0a83b 100644
--- a/include/linux/platform_data/elm.h
+++ b/include/linux/platform_data/elm.h
@@ -50,5 +50,5 @@ struct elm_errorvec {
 
 void elm_decode_bch_error_page(struct device *dev, u8 *ecc_calc,
 		struct elm_errorvec *err_vec);
-void elm_config(struct device *dev, enum bch_ecc bch_type);
+int elm_config(struct device *dev, enum bch_ecc bch_type);
 #endif /* __ELM_H */
diff --git a/include/linux/platform_data/emif_plat.h b/include/linux/platform_data/emif_plat.h
index 03378ca..5c19a2a 100644
--- a/include/linux/platform_data/emif_plat.h
+++ b/include/linux/platform_data/emif_plat.h
@@ -40,6 +40,7 @@
 /* Custom config requests */
 #define EMIF_CUSTOM_CONFIG_LPMODE			0x00000001
 #define EMIF_CUSTOM_CONFIG_TEMP_ALERT_POLL_INTERVAL	0x00000002
+#define EMIF_CUSTOM_CONFIG_EXTENDED_TEMP_PART		0x00000004
 
 #ifndef __ASSEMBLY__
 /**
diff --git a/include/linux/platform_data/gpio-rcar.h b/include/linux/platform_data/gpio-rcar.h
new file mode 100644
index 0000000..b253f77
--- /dev/null
+++ b/include/linux/platform_data/gpio-rcar.h
@@ -0,0 +1,26 @@
+/*
+ * Renesas R-Car GPIO Support
+ *
+ *  Copyright (C) 2013 Magnus Damm
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either 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.
+ */
+
+#ifndef __GPIO_RCAR_H__
+#define __GPIO_RCAR_H__
+
+struct gpio_rcar_config {
+	unsigned int gpio_base;
+	unsigned int irq_base;
+	unsigned int number_of_pins;
+	const char *pctl_name;
+};
+
+#endif /* __GPIO_RCAR_H__ */
diff --git a/include/linux/platform_data/irq-renesas-intc-irqpin.h b/include/linux/platform_data/irq-renesas-intc-irqpin.h
new file mode 100644
index 0000000..e4cb911
--- /dev/null
+++ b/include/linux/platform_data/irq-renesas-intc-irqpin.h
@@ -0,0 +1,29 @@
+/*
+ * Renesas INTC External IRQ Pin Driver
+ *
+ *  Copyright (C) 2013 Magnus Damm
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either 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
+ */
+
+#ifndef __IRQ_RENESAS_INTC_IRQPIN_H__
+#define __IRQ_RENESAS_INTC_IRQPIN_H__
+
+struct renesas_intc_irqpin_config {
+	unsigned int sense_bitfield_width;
+	unsigned int irq_base;
+	bool control_parent;
+};
+
+#endif /* __IRQ_RENESAS_INTC_IRQPIN_H__ */
diff --git a/include/linux/platform_data/irq-renesas-irqc.h b/include/linux/platform_data/irq-renesas-irqc.h
new file mode 100644
index 0000000..3ae17b3
--- /dev/null
+++ b/include/linux/platform_data/irq-renesas-irqc.h
@@ -0,0 +1,27 @@
+/*
+ * Renesas IRQC Driver
+ *
+ *  Copyright (C) 2013 Magnus Damm
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either 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
+ */
+
+#ifndef __IRQ_RENESAS_IRQC_H__
+#define __IRQ_RENESAS_IRQC_H__
+
+struct renesas_irqc_config {
+	unsigned int irq_base;
+};
+
+#endif /* __IRQ_RENESAS_IRQC_H__ */
diff --git a/include/linux/platform_data/leds-lp55xx.h b/include/linux/platform_data/leds-lp55xx.h
index 1509570..202e290 100644
--- a/include/linux/platform_data/leds-lp55xx.h
+++ b/include/linux/platform_data/leds-lp55xx.h
@@ -20,18 +20,6 @@
 #define LP55XX_CLOCK_INT	1
 #define LP55XX_CLOCK_EXT	2
 
-/* Bits in LP5521 CONFIG register. 'update_config' in lp55xx_platform_data */
-#define LP5521_PWM_HF			0x40	/* PWM: 0 = 256Hz, 1 = 558Hz */
-#define LP5521_PWRSAVE_EN		0x20	/* 1 = Power save mode */
-#define LP5521_CP_MODE_OFF		0	/* Charge pump (CP) off */
-#define LP5521_CP_MODE_BYPASS		8	/* CP forced to bypass mode */
-#define LP5521_CP_MODE_1X5		0x10	/* CP forced to 1.5x mode */
-#define LP5521_CP_MODE_AUTO		0x18	/* Automatic mode selection */
-#define LP5521_R_TO_BATT		4	/* R out: 0 = CP, 1 = Vbat */
-#define LP5521_CLK_SRC_EXT		0	/* Ext-clk source (CLK_32K) */
-#define LP5521_CLK_INT			1	/* Internal clock */
-#define LP5521_CLK_AUTO			2	/* Automatic clock selection */
-
 struct lp55xx_led_config {
 	const char *name;
 	u8 chan_nr;
@@ -40,9 +28,9 @@ struct lp55xx_led_config {
 };
 
 struct lp55xx_predef_pattern {
-	u8 *r;
-	u8 *g;
-	u8 *b;
+	const u8 *r;
+	const u8 *g;
+	const u8 *b;
 	u8 size_r;
 	u8 size_g;
 	u8 size_b;
@@ -79,9 +67,6 @@ struct lp55xx_platform_data {
 	/* Predefined pattern data */
 	struct lp55xx_predef_pattern *patterns;
 	unsigned int num_patterns;
-
-	/* _CONFIG register */
-	u8 update_config;
 };
 
 #endif /* _LEDS_LP55XX_H */
diff --git a/include/linux/platform_data/mailbox-dbx500.h b/include/linux/platform_data/mailbox-dbx500.h
new file mode 100644
index 0000000..d5aebd9
--- /dev/null
+++ b/include/linux/platform_data/mailbox-dbx500.h
@@ -0,0 +1,12 @@
+/*
+ * mailbox-dbx500.h
+ *
+ * Copyright (C) ST-Ericsson SA 2012
+ * Author:  <loic.pallardy@st.com> for ST-Ericsson.
+ * License terms:  GNU General Public License (GPL), version 2
+ */
+
+struct dbx500_plat_data {
+	unsigned int legacy_offset;
+	unsigned int upap_offset;
+};
diff --git a/include/linux/platform_data/mailbox-omap.h b/include/linux/platform_data/mailbox-omap.h
new file mode 100644
index 0000000..676cd64
--- /dev/null
+++ b/include/linux/platform_data/mailbox-omap.h
@@ -0,0 +1,53 @@
+/*
+ * mailbox-omap.h
+ *
+ * Copyright (C) 2013 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.
+ */
+
+#ifndef _PLAT_MAILBOX_H
+#define _PLAT_MAILBOX_H
+
+/* Interrupt register configuration types */
+#define MBOX_INTR_CFG_TYPE1	(0)
+#define MBOX_INTR_CFG_TYPE2	(1)
+
+/**
+ * struct omap_mbox_dev_info - OMAP mailbox device attribute info
+ * @name:	name of the mailbox device
+ * @tx_id:	mailbox queue id used for transmitting messages
+ * @rx_id:	mailbox queue id on which messages are received
+ * @irq_id:	irq identifier number to use from the hwmod data
+ * @usr_id:	mailbox user id for identifying the interrupt into
+ *			the MPU interrupt controller.
+ */
+struct omap_mbox_dev_info {
+	const char *name;
+	u32 tx_id;
+	u32 rx_id;
+	u32 irq_id;
+	u32 usr_id;
+};
+
+/**
+ * struct omap_mbox_pdata - OMAP mailbox platform data
+ * @intr_type:	type of interrupt configuration registers used
+			while programming mailbox queue interrupts
+ * @info_cnt:	number of mailbox devices for the platform
+ * @info:	array of mailbox device attributes
+ */
+struct omap_mbox_pdata {
+	u32 intr_type;
+	u32 info_cnt;
+	struct omap_mbox_dev_info *info;
+};
+
+#endif /* _PLAT_MAILBOX_H */
diff --git a/include/linux/platform_data/mv_usb.h b/include/linux/platform_data/mv_usb.h
index 944b01d..98b7925 100644
--- a/include/linux/platform_data/mv_usb.h
+++ b/include/linux/platform_data/mv_usb.h
@@ -34,8 +34,6 @@ struct mv_usb_addon_irq {
 };
 
 struct mv_usb_platform_data {
-	unsigned int		clknum;
-	char			**clkname;
 	struct mv_usb_addon_irq	*id;	/* Only valid for OTG. ID pin change*/
 	struct mv_usb_addon_irq	*vbus;	/* valid for OTG/UDC. VBUS change*/
 
diff --git a/include/linux/platform_data/ntc_thermistor.h b/include/linux/platform_data/ntc_thermistor.h
index 88734e8..c7285b5 100644
--- a/include/linux/platform_data/ntc_thermistor.h
+++ b/include/linux/platform_data/ntc_thermistor.h
@@ -21,6 +21,8 @@
 #ifndef _LINUX_NTC_H
 #define _LINUX_NTC_H
 
+struct iio_channel;
+
 enum ntc_thermistor_type {
 	TYPE_NCPXXWB473,
 	TYPE_NCPXXWL333,
@@ -39,13 +41,17 @@ struct ntc_thermistor_platform_data {
 	 * described at Documentation/hwmon/ntc_thermistor
 	 *
 	 * pullup/down_ohm: 0 for infinite / not-connected
+	 *
+	 * chan: iio_channel pointer to communicate with the ADC which the
+	 * thermistor is using for conversion of the analog values.
 	 */
-	int (*read_uV)(void);
-	unsigned int pullup_uV;
+	int (*read_uv)(struct ntc_thermistor_platform_data *);
+	unsigned int pullup_uv;
 
 	unsigned int pullup_ohm;
 	unsigned int pulldown_ohm;
 	enum { NTC_CONNECTED_POSITIVE, NTC_CONNECTED_GROUND } connect;
+	struct iio_channel *chan;
 
 	int (*read_ohm)(void);
 };
diff --git a/include/linux/platform_data/video-vt8500lcdfb.h b/include/linux/platform_data/video-vt8500lcdfb.h
deleted file mode 100644
index 7f399c3..0000000
--- a/include/linux/platform_data/video-vt8500lcdfb.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- *  VT8500/WM8505 Frame Buffer platform data definitions
- *
- *  Copyright (C) 2010 Ed Spiridonov <edo.rus@gmail.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 _VT8500FB_H
-#define _VT8500FB_H
-
-#include <linux/fb.h>
-
-struct vt8500fb_platform_data {
-	struct fb_videomode	mode;
-	u32			xres_virtual;
-	u32			yres_virtual;
-	u32			bpp;
-	unsigned long		video_mem_phys;
-	void			*video_mem_virt;
-	unsigned long		video_mem_len;
-};
-
-#endif /* _VT8500FB_H */
diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h
index c082c71..9abf1db 100644
--- a/include/linux/platform_device.h
+++ b/include/linux/platform_device.h
@@ -20,12 +20,12 @@
 struct mfd_cell;
 
 struct platform_device {
-	const char	* name;
+	const char	*name;
 	int		id;
 	bool		id_auto;
 	struct device	dev;
 	u32		num_resources;
-	struct resource	* resource;
+	struct resource	*resource;
 
 	const struct platform_device_id	*id_entry;
 
@@ -47,9 +47,12 @@ 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 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 *);
+extern struct resource *platform_get_resource_byname(struct platform_device *,
+						     unsigned int,
+						     const char *);
 extern int platform_get_irq_byname(struct platform_device *, const char *);
 extern int platform_add_devices(struct platform_device **, int);
 
@@ -161,7 +164,8 @@ extern struct platform_device *platform_device_alloc(const char *name, int id);
 extern int platform_device_add_resources(struct platform_device *pdev,
 					 const struct resource *res,
 					 unsigned int num);
-extern int platform_device_add_data(struct platform_device *pdev, const void *data, size_t size);
+extern int platform_device_add_data(struct platform_device *pdev,
+				    const void *data, size_t size);
 extern int platform_device_add(struct platform_device *pdev);
 extern void platform_device_del(struct platform_device *pdev);
 extern void platform_device_put(struct platform_device *pdev);
@@ -190,7 +194,8 @@ static inline void *platform_get_drvdata(const struct platform_device *pdev)
 	return dev_get_drvdata(&pdev->dev);
 }
 
-static inline void platform_set_drvdata(struct platform_device *pdev, void *data)
+static inline void platform_set_drvdata(struct platform_device *pdev,
+					void *data)
 {
 	dev_set_drvdata(&pdev->dev, data);
 }
@@ -222,10 +227,10 @@ static void __exit __platform_driver##_exit(void) \
 } \
 module_exit(__platform_driver##_exit);
 
-extern struct platform_device *platform_create_bundle(struct platform_driver *driver,
-					int (*probe)(struct platform_device *),
-					struct resource *res, unsigned int n_res,
-					const void *data, size_t size);
+extern struct platform_device *platform_create_bundle(
+	struct platform_driver *driver, int (*probe)(struct platform_device *),
+	struct resource *res, unsigned int n_res,
+	const void *data, size_t size);
 
 /* early platform driver interface */
 struct early_platform_driver {
diff --git a/include/linux/pm.h b/include/linux/pm.h
index e5d7230..a224c7f 100644
--- a/include/linux/pm.h
+++ b/include/linux/pm.h
@@ -34,6 +34,19 @@
 extern void (*pm_power_off)(void);
 extern void (*pm_power_off_prepare)(void);
 
+struct device; /* we have a circular dep with device.h */
+#ifdef CONFIG_VT_CONSOLE_SLEEP
+extern void pm_vt_switch_required(struct device *dev, bool required);
+extern void pm_vt_switch_unregister(struct device *dev);
+#else
+static inline void pm_vt_switch_required(struct device *dev, bool required)
+{
+}
+static inline void pm_vt_switch_unregister(struct device *dev)
+{
+}
+#endif /* CONFIG_VT_CONSOLE_SLEEP */
+
 /*
  * Device power management
  */
diff --git a/include/linux/pm2301_charger.h b/include/linux/pm2301_charger.h
index fc3f026..85c16de 100644
--- a/include/linux/pm2301_charger.h
+++ b/include/linux/pm2301_charger.h
@@ -48,7 +48,7 @@ struct pm2xxx_charger_platform_data {
 	size_t num_supplicants;
 	int i2c_bus;
 	const char *label;
-	int irq_number;
+	int gpio_irq_number;
 	unsigned int lpn_gpio;
 	int irq_type;
 };
diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h
index 042058f..92a51df 100644
--- a/include/linux/posix-timers.h
+++ b/include/linux/posix-timers.h
@@ -7,14 +7,20 @@
 #include <linux/timex.h>
 #include <linux/alarmtimer.h>
 
-union cpu_time_count {
-	cputime_t cpu;
-	unsigned long long sched;
-};
+
+static inline unsigned long long cputime_to_expires(cputime_t expires)
+{
+	return (__force unsigned long long)expires;
+}
+
+static inline cputime_t expires_to_cputime(unsigned long long expires)
+{
+	return (__force cputime_t)expires;
+}
 
 struct cpu_timer_list {
 	struct list_head entry;
-	union cpu_time_count expires, incr;
+	unsigned long long expires, incr;
 	struct task_struct *task;
 	int firing;
 };
diff --git a/include/linux/printk.h b/include/linux/printk.h
index 822171f..4890fe6 100644
--- a/include/linux/printk.h
+++ b/include/linux/printk.h
@@ -1,6 +1,7 @@
 #ifndef __KERNEL_PRINTK__
 #define __KERNEL_PRINTK__
 
+#include <stdarg.h>
 #include <linux/init.h>
 #include <linux/kern_levels.h>
 
@@ -95,8 +96,14 @@ int no_printk(const char *fmt, ...)
 	return 0;
 }
 
+#ifdef CONFIG_EARLY_PRINTK
 extern asmlinkage __printf(1, 2)
 void early_printk(const char *fmt, ...);
+void early_vprintk(const char *fmt, va_list ap);
+#else
+static inline __printf(1, 2) __cold
+void early_printk(const char *s, ...) { }
+#endif
 
 #ifdef CONFIG_PRINTK
 asmlinkage __printf(5, 0)
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
index 8307f2f..5ae73e2 100644
--- a/include/linux/proc_fs.h
+++ b/include/linux/proc_fs.h
@@ -72,7 +72,6 @@ struct proc_dir_entry {
 	struct proc_dir_entry *next, *parent, *subdir;
 	void *data;
 	read_proc_t *read_proc;
-	write_proc_t *write_proc;
 	atomic_t count;		/* use count */
 	int pde_users;	/* number of callers into module in progress */
 	struct completion *pde_unload_completion;
@@ -117,6 +116,7 @@ struct proc_dir_entry *proc_create_data(const char *name, umode_t mode,
 				const struct file_operations *proc_fops,
 				void *data);
 extern void remove_proc_entry(const char *name, struct proc_dir_entry *parent);
+extern int remove_proc_subtree(const char *name, struct proc_dir_entry *parent);
 
 struct pid_namespace;
 
@@ -202,6 +202,7 @@ static inline struct proc_dir_entry *proc_create_data(const char *name,
 	return NULL;
 }
 #define remove_proc_entry(name, parent) do {} while (0)
+#define remove_proc_subtree(name, parent) do {} while (0)
 
 static inline struct proc_dir_entry *proc_symlink(const char *name,
 		struct proc_dir_entry *parent,const char *dest) {return NULL;}
@@ -305,6 +306,11 @@ static inline struct proc_dir_entry *PDE(const struct inode *inode)
 	return PROC_I(inode)->pde;
 }
 
+static inline void *PDE_DATA(const struct inode *inode)
+{
+	return PROC_I(inode)->pde->data;
+}
+
 static inline struct net *PDE_NET(struct proc_dir_entry *pde)
 {
 	return pde->parent->data;
diff --git a/include/linux/profile.h b/include/linux/profile.h
index 2112390..aaad386 100644
--- a/include/linux/profile.h
+++ b/include/linux/profile.h
@@ -18,10 +18,10 @@ struct pt_regs;
 struct notifier_block;
 
 #if defined(CONFIG_PROFILING) && defined(CONFIG_PROC_FS)
-void create_prof_cpu_mask(struct proc_dir_entry *de);
+void create_prof_cpu_mask(void);
 int create_proc_profile(void);
 #else
-static inline void create_prof_cpu_mask(struct proc_dir_entry *de)
+static inline void create_prof_cpu_mask(void)
 {
 }
 
diff --git a/include/linux/pstore_ram.h b/include/linux/pstore_ram.h
index cb6ab5f..9974975 100644
--- a/include/linux/pstore_ram.h
+++ b/include/linux/pstore_ram.h
@@ -26,6 +26,13 @@
 struct persistent_ram_buffer;
 struct rs_control;
 
+struct persistent_ram_ecc_info {
+	int block_size;
+	int ecc_size;
+	int symsize;
+	int poly;
+};
+
 struct persistent_ram_zone {
 	phys_addr_t paddr;
 	size_t size;
@@ -39,15 +46,14 @@ struct persistent_ram_zone {
 	struct rs_control *rs_decoder;
 	int corrected_bytes;
 	int bad_blocks;
-	int ecc_block_size;
-	int ecc_size;
+	struct persistent_ram_ecc_info ecc_info;
 
 	char *old_log;
 	size_t old_log_size;
 };
 
 struct persistent_ram_zone *persistent_ram_new(phys_addr_t start, size_t size,
-					       u32 sig, int ecc_size);
+			u32 sig, struct persistent_ram_ecc_info *ecc_info);
 void persistent_ram_free(struct persistent_ram_zone *prz);
 void persistent_ram_zap(struct persistent_ram_zone *prz);
 
@@ -74,7 +80,7 @@ struct ramoops_platform_data {
 	unsigned long	console_size;
 	unsigned long	ftrace_size;
 	int		dump_oops;
-	int		ecc_size;
+	struct persistent_ram_ecc_info ecc_info;
 };
 
 #endif
diff --git a/include/linux/ramfs.h b/include/linux/ramfs.h
index 5bf5500..69e37c2 100644
--- a/include/linux/ramfs.h
+++ b/include/linux/ramfs.h
@@ -6,7 +6,13 @@ struct inode *ramfs_get_inode(struct super_block *sb, const struct inode *dir,
 extern struct dentry *ramfs_mount(struct file_system_type *fs_type,
 	 int flags, const char *dev_name, void *data);
 
-#ifndef CONFIG_MMU
+#ifdef CONFIG_MMU
+static inline int
+ramfs_nommu_expand_for_mapping(struct inode *inode, size_t newsize)
+{
+	return 0;
+}
+#else
 extern int ramfs_nommu_expand_for_mapping(struct inode *inode, size_t newsize);
 extern unsigned long ramfs_nommu_get_unmapped_area(struct file *file,
 						   unsigned long addr,
diff --git a/include/linux/random.h b/include/linux/random.h
index 347ce55..3b9377d 100644
--- a/include/linux/random.h
+++ b/include/linux/random.h
@@ -29,13 +29,6 @@ u32 prandom_u32(void);
 void prandom_bytes(void *buf, int nbytes);
 void prandom_seed(u32 seed);
 
-/*
- * These macros are preserved for backward compatibility and should be
- * removed as soon as a transition is finished.
- */
-#define random32() prandom_u32()
-#define srandom32(seed) prandom_seed(seed)
-
 u32 prandom_u32_state(struct rnd_state *);
 void prandom_bytes_state(struct rnd_state *state, void *buf, int nbytes);
 
diff --git a/include/linux/rculist_bl.h b/include/linux/rculist_bl.h
index cf1244f..4f216c5 100644
--- a/include/linux/rculist_bl.h
+++ b/include/linux/rculist_bl.h
@@ -20,7 +20,7 @@ static inline void hlist_bl_set_first_rcu(struct hlist_bl_head *h,
 static inline struct hlist_bl_node *hlist_bl_first_rcu(struct hlist_bl_head *h)
 {
 	return (struct hlist_bl_node *)
-		((unsigned long)rcu_dereference(h->first) & ~LIST_BL_LOCKMASK);
+		((unsigned long)rcu_dereference_check(h->first, hlist_bl_is_locked(h)) & ~LIST_BL_LOCKMASK);
 }
 
 /**
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index b758ce1..9ed2c9a 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -80,6 +80,7 @@ extern void do_trace_rcu_torture_read(char *rcutorturename,
 #define UINT_CMP_LT(a, b)	(UINT_MAX / 2 < (a) - (b))
 #define ULONG_CMP_GE(a, b)	(ULONG_MAX / 2 >= (a) - (b))
 #define ULONG_CMP_LT(a, b)	(ULONG_MAX / 2 < (a) - (b))
+#define ulong2long(a)		(*(long *)(&(a)))
 
 /* Exported common interfaces */
 
diff --git a/include/linux/regmap.h b/include/linux/regmap.h
index bf77dfd..02d84e2 100644
--- a/include/linux/regmap.h
+++ b/include/linux/regmap.h
@@ -389,6 +389,7 @@ int regmap_update_bits_check(struct regmap *map, unsigned int reg,
 			     bool *change);
 int regmap_get_val_bytes(struct regmap *map);
 int regmap_async_complete(struct regmap *map);
+bool regmap_can_raw_write(struct regmap *map);
 
 int regcache_sync(struct regmap *map);
 int regcache_sync_region(struct regmap *map, unsigned int min,
diff --git a/include/linux/regulator/ab8500.h b/include/linux/regulator/ab8500.h
index 7bd73bb..90b8b5a 100644
--- a/include/linux/regulator/ab8500.h
+++ b/include/linux/regulator/ab8500.h
@@ -5,11 +5,14 @@
  *
  * Authors: Sundar Iyer <sundar.iyer@stericsson.com> for ST-Ericsson
  *          Bengt Jonsson <bengt.g.jonsson@stericsson.com> for ST-Ericsson
+ *          Daniel Willerud <daniel.willerud@stericsson.com> for ST-Ericsson
  */
 
 #ifndef __LINUX_MFD_AB8500_REGULATOR_H
 #define __LINUX_MFD_AB8500_REGULATOR_H
 
+#include <linux/platform_device.h>
+
 /* AB8500 regulators */
 enum ab8500_regulator_id {
 	AB8500_LDO_AUX1,
@@ -17,7 +20,6 @@ enum ab8500_regulator_id {
 	AB8500_LDO_AUX3,
 	AB8500_LDO_INTCORE,
 	AB8500_LDO_TVOUT,
-	AB8500_LDO_USB,
 	AB8500_LDO_AUDIO,
 	AB8500_LDO_ANAMIC1,
 	AB8500_LDO_ANAMIC2,
@@ -26,7 +28,28 @@ enum ab8500_regulator_id {
 	AB8500_NUM_REGULATORS,
 };
 
-/* AB9450 regulators */
+/* AB8505 regulators */
+enum ab8505_regulator_id {
+	AB8505_LDO_AUX1,
+	AB8505_LDO_AUX2,
+	AB8505_LDO_AUX3,
+	AB8505_LDO_AUX4,
+	AB8505_LDO_AUX5,
+	AB8505_LDO_AUX6,
+	AB8505_LDO_INTCORE,
+	AB8505_LDO_ADC,
+	AB8505_LDO_USB,
+	AB8505_LDO_AUDIO,
+	AB8505_LDO_ANAMIC1,
+	AB8505_LDO_ANAMIC2,
+	AB8505_LDO_AUX8,
+	AB8505_LDO_ANA,
+	AB8505_SYSCLKREQ_2,
+	AB8505_SYSCLKREQ_4,
+	AB8505_NUM_REGULATORS,
+};
+
+/* AB9540 regulators */
 enum ab9540_regulator_id {
 	AB9540_LDO_AUX1,
 	AB9540_LDO_AUX2,
@@ -45,16 +68,39 @@ enum ab9540_regulator_id {
 	AB9540_NUM_REGULATORS,
 };
 
-/* AB8500 and AB9540 register initialization */
+/* AB8540 regulators */
+enum ab8540_regulator_id {
+	AB8540_LDO_AUX1,
+	AB8540_LDO_AUX2,
+	AB8540_LDO_AUX3,
+	AB8540_LDO_AUX4,
+	AB8540_LDO_AUX5,
+	AB8540_LDO_AUX6,
+	AB8540_LDO_INTCORE,
+	AB8540_LDO_TVOUT,
+	AB8540_LDO_AUDIO,
+	AB8540_LDO_ANAMIC1,
+	AB8540_LDO_ANAMIC2,
+	AB8540_LDO_DMIC,
+	AB8540_LDO_ANA,
+	AB8540_LDO_SDIO,
+	AB8540_SYSCLKREQ_2,
+	AB8540_SYSCLKREQ_4,
+	AB8540_NUM_REGULATORS,
+};
+
+/* AB8500, AB8505, and AB9540 register initialization */
 struct ab8500_regulator_reg_init {
 	int id;
+	u8 mask;
 	u8 value;
 };
 
-#define INIT_REGULATOR_REGISTER(_id, _value)	\
-	{					\
-		.id = _id,			\
-		.value = _value,		\
+#define INIT_REGULATOR_REGISTER(_id, _mask, _value)	\
+	{						\
+		.id = _id,				\
+		.mask = _mask,				\
+		.value = _value,			\
 	}
 
 /* AB8500 registers */
@@ -86,10 +132,58 @@ enum ab8500_regulator_reg {
 	AB8500_REGUCTRL2SPARE,
 	AB8500_REGUCTRLDISCH,
 	AB8500_REGUCTRLDISCH2,
-	AB8500_VSMPS1SEL1,
 	AB8500_NUM_REGULATOR_REGISTERS,
 };
 
+/* AB8505 registers */
+enum ab8505_regulator_reg {
+	AB8505_REGUREQUESTCTRL1,
+	AB8505_REGUREQUESTCTRL2,
+	AB8505_REGUREQUESTCTRL3,
+	AB8505_REGUREQUESTCTRL4,
+	AB8505_REGUSYSCLKREQ1HPVALID1,
+	AB8505_REGUSYSCLKREQ1HPVALID2,
+	AB8505_REGUHWHPREQ1VALID1,
+	AB8505_REGUHWHPREQ1VALID2,
+	AB8505_REGUHWHPREQ2VALID1,
+	AB8505_REGUHWHPREQ2VALID2,
+	AB8505_REGUSWHPREQVALID1,
+	AB8505_REGUSWHPREQVALID2,
+	AB8505_REGUSYSCLKREQVALID1,
+	AB8505_REGUSYSCLKREQVALID2,
+	AB8505_REGUVAUX4REQVALID,
+	AB8505_REGUMISC1,
+	AB8505_VAUDIOSUPPLY,
+	AB8505_REGUCTRL1VAMIC,
+	AB8505_VSMPSAREGU,
+	AB8505_VSMPSBREGU,
+	AB8505_VSAFEREGU, /* NOTE! PRCMU register */
+	AB8505_VPLLVANAREGU,
+	AB8505_EXTSUPPLYREGU,
+	AB8505_VAUX12REGU,
+	AB8505_VRF1VAUX3REGU,
+	AB8505_VSMPSASEL1,
+	AB8505_VSMPSASEL2,
+	AB8505_VSMPSASEL3,
+	AB8505_VSMPSBSEL1,
+	AB8505_VSMPSBSEL2,
+	AB8505_VSMPSBSEL3,
+	AB8505_VSAFESEL1, /* NOTE! PRCMU register */
+	AB8505_VSAFESEL2, /* NOTE! PRCMU register */
+	AB8505_VSAFESEL3, /* NOTE! PRCMU register */
+	AB8505_VAUX1SEL,
+	AB8505_VAUX2SEL,
+	AB8505_VRF1VAUX3SEL,
+	AB8505_VAUX4REQCTRL,
+	AB8505_VAUX4REGU,
+	AB8505_VAUX4SEL,
+	AB8505_REGUCTRLDISCH,
+	AB8505_REGUCTRLDISCH2,
+	AB8505_REGUCTRLDISCH3,
+	AB8505_CTRLVAUX5,
+	AB8505_CTRLVAUX6,
+	AB8505_NUM_REGULATOR_REGISTERS,
+};
 
 /* AB9540 registers */
 enum ab9540_regulator_reg {
@@ -139,4 +233,111 @@ enum ab9540_regulator_reg {
 	AB9540_NUM_REGULATOR_REGISTERS,
 };
 
+/* AB8540 registers */
+enum ab8540_regulator_reg {
+	AB8540_REGUREQUESTCTRL1,
+	AB8540_REGUREQUESTCTRL2,
+	AB8540_REGUREQUESTCTRL3,
+	AB8540_REGUREQUESTCTRL4,
+	AB8540_REGUSYSCLKREQ1HPVALID1,
+	AB8540_REGUSYSCLKREQ1HPVALID2,
+	AB8540_REGUHWHPREQ1VALID1,
+	AB8540_REGUHWHPREQ1VALID2,
+	AB8540_REGUHWHPREQ2VALID1,
+	AB8540_REGUHWHPREQ2VALID2,
+	AB8540_REGUSWHPREQVALID1,
+	AB8540_REGUSWHPREQVALID2,
+	AB8540_REGUSYSCLKREQVALID1,
+	AB8540_REGUSYSCLKREQVALID2,
+	AB8540_REGUVAUX4REQVALID,
+	AB8540_REGUVAUX5REQVALID,
+	AB8540_REGUVAUX6REQVALID,
+	AB8540_REGUVCLKBREQVALID,
+	AB8540_REGUVRF1REQVALID,
+	AB8540_REGUMISC1,
+	AB8540_VAUDIOSUPPLY,
+	AB8540_REGUCTRL1VAMIC,
+	AB8540_VHSIC,
+	AB8540_VSDIO,
+	AB8540_VSMPS1REGU,
+	AB8540_VSMPS2REGU,
+	AB8540_VSMPS3REGU,
+	AB8540_VPLLVANAREGU,
+	AB8540_EXTSUPPLYREGU,
+	AB8540_VAUX12REGU,
+	AB8540_VRF1VAUX3REGU,
+	AB8540_VSMPS1SEL1,
+	AB8540_VSMPS1SEL2,
+	AB8540_VSMPS1SEL3,
+	AB8540_VSMPS2SEL1,
+	AB8540_VSMPS2SEL2,
+	AB8540_VSMPS2SEL3,
+	AB8540_VSMPS3SEL1,
+	AB8540_VSMPS3SEL2,
+	AB8540_VAUX1SEL,
+	AB8540_VAUX2SEL,
+	AB8540_VRF1VAUX3SEL,
+	AB8540_REGUCTRL2SPARE,
+	AB8540_VAUX4REQCTRL,
+	AB8540_VAUX4REGU,
+	AB8540_VAUX4SEL,
+	AB8540_VAUX5REQCTRL,
+	AB8540_VAUX5REGU,
+	AB8540_VAUX5SEL,
+	AB8540_VAUX6REQCTRL,
+	AB8540_VAUX6REGU,
+	AB8540_VAUX6SEL,
+	AB8540_VCLKBREQCTRL,
+	AB8540_VCLKBREGU,
+	AB8540_VCLKBSEL,
+	AB8540_VRF1REQCTRL,
+	AB8540_REGUCTRLDISCH,
+	AB8540_REGUCTRLDISCH2,
+	AB8540_REGUCTRLDISCH3,
+	AB8540_REGUCTRLDISCH4,
+	AB8540_VSIMSYSCLKCTRL,
+	AB8540_VANAVPLLSEL,
+	AB8540_NUM_REGULATOR_REGISTERS,
+};
+
+/* AB8500 external regulators */
+struct ab8500_ext_regulator_cfg {
+	bool hwreq; /* requires hw mode or high power mode */
+};
+
+enum ab8500_ext_regulator_id {
+	AB8500_EXT_SUPPLY1,
+	AB8500_EXT_SUPPLY2,
+	AB8500_EXT_SUPPLY3,
+	AB8500_NUM_EXT_REGULATORS,
+};
+
+/* AB8500 regulator platform data */
+struct ab8500_regulator_platform_data {
+	int num_reg_init;
+	struct ab8500_regulator_reg_init *reg_init;
+	int num_regulator;
+	struct regulator_init_data *regulator;
+	int num_ext_regulator;
+	struct regulator_init_data *ext_regulator;
+};
+
+#ifdef CONFIG_REGULATOR_AB8500_DEBUG
+int ab8500_regulator_debug_init(struct platform_device *pdev);
+int ab8500_regulator_debug_exit(struct platform_device *pdev);
+#else
+static inline int ab8500_regulator_debug_init(struct platform_device *pdev)
+{
+	return 0;
+}
+static inline int ab8500_regulator_debug_exit(struct platform_device *pdev)
+{
+	return 0;
+}
+#endif
+
+/* AB8500 external regulator functions. */
+int ab8500_ext_regulator_init(struct platform_device *pdev);
+int ab8500_ext_regulator_exit(struct platform_device *pdev);
+
 #endif
diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h
index 7bc732c..145022a 100644
--- a/include/linux/regulator/consumer.h
+++ b/include/linux/regulator/consumer.h
@@ -141,18 +141,18 @@ void regulator_put(struct regulator *regulator);
 void devm_regulator_put(struct regulator *regulator);
 
 /* regulator output control and status */
-int regulator_enable(struct regulator *regulator);
+int __must_check regulator_enable(struct regulator *regulator);
 int regulator_disable(struct regulator *regulator);
 int regulator_force_disable(struct regulator *regulator);
 int regulator_is_enabled(struct regulator *regulator);
 int regulator_disable_deferred(struct regulator *regulator, int ms);
 
-int regulator_bulk_get(struct device *dev, int num_consumers,
-		       struct regulator_bulk_data *consumers);
-int devm_regulator_bulk_get(struct device *dev, int num_consumers,
-			    struct regulator_bulk_data *consumers);
-int regulator_bulk_enable(int num_consumers,
-			  struct regulator_bulk_data *consumers);
+int __must_check regulator_bulk_get(struct device *dev, int num_consumers,
+				    struct regulator_bulk_data *consumers);
+int __must_check devm_regulator_bulk_get(struct device *dev, int num_consumers,
+					 struct regulator_bulk_data *consumers);
+int __must_check regulator_bulk_enable(int num_consumers,
+				       struct regulator_bulk_data *consumers);
 int regulator_bulk_disable(int num_consumers,
 			   struct regulator_bulk_data *consumers);
 int regulator_bulk_force_disable(int num_consumers,
diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h
index 7df93f5..5e2d13d 100644
--- a/include/linux/regulator/driver.h
+++ b/include/linux/regulator/driver.h
@@ -22,6 +22,7 @@
 struct regmap;
 struct regulator_dev;
 struct regulator_init_data;
+struct regulator_enable_gpio;
 
 enum regulator_status {
 	REGULATOR_STATUS_OFF,
@@ -199,6 +200,8 @@ enum regulator_type {
  *                output when using regulator_set_voltage_sel_regmap
  * @enable_reg: Register for control when using regmap enable/disable ops
  * @enable_mask: Mask for control when using regmap enable/disable ops
+ * @enable_is_inverted: A flag to indicate set enable_mask bits to disable
+ *                      when using regulator_enable_regmap and friends APIs.
  * @bypass_reg: Register for control when using regmap set_bypass
  * @bypass_mask: Mask for control when using regmap set_bypass
  *
@@ -228,6 +231,7 @@ struct regulator_desc {
 	unsigned int apply_bit;
 	unsigned int enable_reg;
 	unsigned int enable_mask;
+	bool enable_is_inverted;
 	unsigned int bypass_reg;
 	unsigned int bypass_mask;
 
@@ -302,8 +306,7 @@ struct regulator_dev {
 
 	struct dentry *debugfs;
 
-	int ena_gpio;
-	unsigned int ena_gpio_invert:1;
+	struct regulator_enable_gpio *ena_pin;
 	unsigned int ena_gpio_state:1;
 };
 
diff --git a/include/linux/relay.h b/include/linux/relay.h
index 91cacc3..d7c8359 100644
--- a/include/linux/relay.h
+++ b/include/linux/relay.h
@@ -20,9 +20,6 @@
 #include <linux/poll.h>
 #include <linux/kref.h>
 
-/* Needs a _much_ better name... */
-#define FIX_SIZE(x) ((((x) - 1) & PAGE_MASK) + PAGE_SIZE)
-
 /*
  * Tracks changes to rchan/rchan_buf structs
  */
diff --git a/include/linux/res_counter.h b/include/linux/res_counter.h
index c230994..f9822dc 100644
--- a/include/linux/res_counter.h
+++ b/include/linux/res_counter.h
@@ -13,8 +13,8 @@
  * info about what this counter is.
  */
 
-#include <linux/cgroup.h>
 #include <linux/errno.h>
+#include <linux/spinlock.h>
 
 /*
  * The core object. the cgroup that wishes to account for some
diff --git a/include/linux/reset-controller.h b/include/linux/reset-controller.h
new file mode 100644
index 0000000..2f61311
--- /dev/null
+++ b/include/linux/reset-controller.h
@@ -0,0 +1,51 @@
+#ifndef _LINUX_RESET_CONTROLLER_H_
+#define _LINUX_RESET_CONTROLLER_H_
+
+#include <linux/list.h>
+
+struct reset_controller_dev;
+
+/**
+ * struct reset_control_ops
+ *
+ * @reset: for self-deasserting resets, does all necessary
+ *         things to reset the device
+ * @assert: manually assert the reset line, if supported
+ * @deassert: manually deassert the reset line, if supported
+ */
+struct reset_control_ops {
+	int (*reset)(struct reset_controller_dev *rcdev, unsigned long id);
+	int (*assert)(struct reset_controller_dev *rcdev, unsigned long id);
+	int (*deassert)(struct reset_controller_dev *rcdev, unsigned long id);
+};
+
+struct module;
+struct device_node;
+
+/**
+ * struct reset_controller_dev - reset controller entity that might
+ *                               provide multiple reset controls
+ * @ops: a pointer to device specific struct reset_control_ops
+ * @owner: kernel module of the reset controller driver
+ * @list: internal list of reset controller devices
+ * @of_node: corresponding device tree node as phandle target
+ * @of_reset_n_cells: number of cells in reset line specifiers
+ * @of_xlate: translation function to translate from specifier as found in the
+ *            device tree to id as given to the reset control ops
+ * @nr_resets: number of reset controls in this reset controller device
+ */
+struct reset_controller_dev {
+	struct reset_control_ops *ops;
+	struct module *owner;
+	struct list_head list;
+	struct device_node *of_node;
+	int of_reset_n_cells;
+	int (*of_xlate)(struct reset_controller_dev *rcdev,
+			const struct of_phandle_args *reset_spec);
+	unsigned int nr_resets;
+};
+
+int reset_controller_register(struct reset_controller_dev *rcdev);
+void reset_controller_unregister(struct reset_controller_dev *rcdev);
+
+#endif
diff --git a/include/linux/reset.h b/include/linux/reset.h
new file mode 100644
index 0000000..6082247
--- /dev/null
+++ b/include/linux/reset.h
@@ -0,0 +1,17 @@
+#ifndef _LINUX_RESET_H_
+#define _LINUX_RESET_H_
+
+struct device;
+struct reset_control;
+
+int reset_control_reset(struct reset_control *rstc);
+int reset_control_assert(struct reset_control *rstc);
+int reset_control_deassert(struct reset_control *rstc);
+
+struct reset_control *reset_control_get(struct device *dev, const char *id);
+void reset_control_put(struct reset_control *rstc);
+struct reset_control *devm_reset_control_get(struct device *dev, const char *id);
+
+int device_reset(struct device *dev);
+
+#endif
diff --git a/include/linux/ring_buffer.h b/include/linux/ring_buffer.h
index 1342e69..d69cf63 100644
--- a/include/linux/ring_buffer.h
+++ b/include/linux/ring_buffer.h
@@ -4,6 +4,7 @@
 #include <linux/kmemcheck.h>
 #include <linux/mm.h>
 #include <linux/seq_file.h>
+#include <linux/poll.h>
 
 struct ring_buffer;
 struct ring_buffer_iter;
@@ -96,6 +97,11 @@ __ring_buffer_alloc(unsigned long size, unsigned flags, struct lock_class_key *k
 	__ring_buffer_alloc((size), (flags), &__key);	\
 })
 
+void ring_buffer_wait(struct ring_buffer *buffer, int cpu);
+int ring_buffer_poll_wait(struct ring_buffer *buffer, int cpu,
+			  struct file *filp, poll_table *poll_table);
+
+
 #define RING_BUFFER_ALL_CPUS -1
 
 void ring_buffer_free(struct ring_buffer *buffer);
diff --git a/include/linux/rtc-pxa.h b/include/linux/rtc-pxa.h
new file mode 100644
index 0000000..71bc45f
--- /dev/null
+++ b/include/linux/rtc-pxa.h
@@ -0,0 +1,18 @@
+/*
+ * include/linux/rtc-pxa.h
+ *
+ * RTC PXA Header file
+ *
+ * Copyright (C) 2010 Marvell International Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __LINUX_RTC_PXA_H
+#define __LINUX_RTC_PXA_H
+
+extern int pxa_rtc_sync_time(unsigned int ticks);
+
+#endif /* __LINUX_RTC_PXA_H */
diff --git a/include/linux/rtc.h b/include/linux/rtc.h
index 580b24c..c2c2897 100644
--- a/include/linux/rtc.h
+++ b/include/linux/rtc.h
@@ -133,7 +133,13 @@ extern struct rtc_device *rtc_device_register(const char *name,
 					struct device *dev,
 					const struct rtc_class_ops *ops,
 					struct module *owner);
+extern struct rtc_device *devm_rtc_device_register(struct device *dev,
+					const char *name,
+					const struct rtc_class_ops *ops,
+					struct module *owner);
 extern void rtc_device_unregister(struct rtc_device *rtc);
+extern void devm_rtc_device_unregister(struct device *dev,
+					struct rtc_device *rtc);
 
 extern int rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm);
 extern int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm);
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index 489dd7bb..f28544b 100644
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -69,6 +69,15 @@ extern int ndo_dflt_fdb_dump(struct sk_buff *skb,
 			     struct netlink_callback *cb,
 			     struct net_device *dev,
 			     int idx);
+extern int ndo_dflt_fdb_add(struct ndmsg *ndm,
+			    struct nlattr *tb[],
+			    struct net_device *dev,
+			    const unsigned char *addr,
+			     u16 flags);
+extern int ndo_dflt_fdb_del(struct ndmsg *ndm,
+			    struct nlattr *tb[],
+			    struct net_device *dev,
+			    const unsigned char *addr);
 
 extern int ndo_dflt_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
 				   struct net_device *dev, u16 mode);
diff --git a/include/linux/rwsem.h b/include/linux/rwsem.h
index 8da67d6..0616ffe 100644
--- a/include/linux/rwsem.h
+++ b/include/linux/rwsem.h
@@ -133,10 +133,20 @@ do {								\
 	_down_write_nest_lock(sem, &(nest_lock)->dep_map);	\
 } while (0);
 
+/*
+ * 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_nest_lock(sem, nest_lock)	down_write(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/scatterlist.h b/include/linux/scatterlist.h
index 2d8bdae..5951e3f 100644
--- a/include/linux/scatterlist.h
+++ b/include/linux/scatterlist.h
@@ -172,6 +172,22 @@ static inline void sg_mark_end(struct scatterlist *sg)
 }
 
 /**
+ * sg_unmark_end - Undo setting the end of the scatterlist
+ * @sg:		 SG entryScatterlist
+ *
+ * Description:
+ *   Removes the termination marker from the given entry of the scatterlist.
+ *
+ **/
+static inline void sg_unmark_end(struct scatterlist *sg)
+{
+#ifdef CONFIG_DEBUG_SG
+	BUG_ON(sg->sg_magic != SG_MAGIC);
+#endif
+	sg->page_link &= ~0x02;
+}
+
+/**
  * sg_phys - Return physical address of an sg entry
  * @sg:	     SG entry
  *
@@ -235,13 +251,13 @@ size_t sg_copy_to_buffer(struct scatterlist *sgl, unsigned int nents,
  * sg page iterator
  *
  * Iterates over sg entries page-by-page.  On each successful iteration,
- * @piter->page points to the current page, @piter->sg to the sg holding this
- * page and @piter->sg_pgoffset to the page's page offset within the sg. The
- * iteration will stop either when a maximum number of sg entries was reached
- * or a terminating sg (sg_last(sg) == true) was reached.
+ * you can call sg_page_iter_page(@piter) and sg_page_iter_dma_address(@piter)
+ * to get the current page and its dma address. @piter->sg will point to the
+ * sg holding this page and @piter->sg_pgoffset to the page's page offset
+ * within the sg. The iteration will stop either when a maximum number of sg
+ * entries was reached or a terminating sg (sg_last(sg) == true) was reached.
  */
 struct sg_page_iter {
-	struct page		*page;		/* current page */
 	struct scatterlist	*sg;		/* sg holding the page */
 	unsigned int		sg_pgoffset;	/* page offset within the sg */
 
@@ -255,6 +271,24 @@ bool __sg_page_iter_next(struct sg_page_iter *piter);
 void __sg_page_iter_start(struct sg_page_iter *piter,
 			  struct scatterlist *sglist, unsigned int nents,
 			  unsigned long pgoffset);
+/**
+ * sg_page_iter_page - get the current page held by the page iterator
+ * @piter:	page iterator holding the page
+ */
+static inline struct page *sg_page_iter_page(struct sg_page_iter *piter)
+{
+	return nth_page(sg_page(piter->sg), piter->sg_pgoffset);
+}
+
+/**
+ * sg_page_iter_dma_address - get the dma address of the current page held by
+ * the page iterator.
+ * @piter:	page iterator holding the page
+ */
+static inline dma_addr_t sg_page_iter_dma_address(struct sg_page_iter *piter)
+{
+	return sg_dma_address(piter->sg) + (piter->sg_pgoffset << PAGE_SHIFT);
+}
 
 /**
  * for_each_sg_page - iterate over the pages of the given sg list
diff --git a/include/linux/sched.h b/include/linux/sched.h
index d35d2b6..b0204cd 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -127,18 +127,6 @@ extern void proc_sched_show_task(struct task_struct *p, struct seq_file *m);
 extern void proc_sched_set_task(struct task_struct *p);
 extern void
 print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq);
-#else
-static inline void
-proc_sched_show_task(struct task_struct *p, struct seq_file *m)
-{
-}
-static inline void proc_sched_set_task(struct task_struct *p)
-{
-}
-static inline void
-print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq)
-{
-}
 #endif
 
 /*
@@ -325,8 +313,6 @@ extern int mutex_spin_on_owner(struct mutex *lock, struct task_struct *owner);
 struct nsproxy;
 struct user_namespace;
 
-#include <linux/aio.h>
-
 #ifdef CONFIG_MMU
 extern void arch_pick_mmap_layout(struct mm_struct *mm);
 extern unsigned long
@@ -336,8 +322,6 @@ extern unsigned long
 arch_get_unmapped_area_topdown(struct file *filp, unsigned long addr,
 			  unsigned long len, unsigned long pgoff,
 			  unsigned long flags);
-extern void arch_unmap_area(struct mm_struct *, unsigned long);
-extern void arch_unmap_area_topdown(struct mm_struct *, unsigned long);
 #else
 static inline void arch_pick_mmap_layout(struct mm_struct *mm) {}
 #endif
@@ -570,7 +554,7 @@ struct signal_struct {
 	cputime_t utime, stime, cutime, cstime;
 	cputime_t gtime;
 	cputime_t cgtime;
-#ifndef CONFIG_VIRT_CPU_ACCOUNTING
+#ifndef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
 	struct cputime prev_cputime;
 #endif
 	unsigned long nvcsw, nivcsw, cnvcsw, cnivcsw;
@@ -637,6 +621,7 @@ struct signal_struct {
 #define SIGNAL_STOP_STOPPED	0x00000001 /* job control stop in effect */
 #define SIGNAL_STOP_CONTINUED	0x00000002 /* SIGCONT since WCONTINUED reap */
 #define SIGNAL_GROUP_EXIT	0x00000004 /* group exit in progress */
+#define SIGNAL_GROUP_COREDUMP	0x00000008 /* coredump in progress */
 /*
  * Pending notifications to parent.
  */
@@ -768,31 +753,6 @@ enum cpu_idle_type {
 };
 
 /*
- * Increase resolution of nice-level calculations for 64-bit architectures.
- * The extra resolution improves shares distribution and load balancing of
- * low-weight task groups (eg. nice +19 on an autogroup), deeper taskgroup
- * hierarchies, especially on larger systems. This is not a user-visible change
- * and does not change the user-interface for setting shares/weights.
- *
- * We increase resolution only if we have enough bits to allow this increased
- * resolution (i.e. BITS_PER_LONG > 32). The costs for increasing resolution
- * when BITS_PER_LONG <= 32 are pretty high and the returns do not justify the
- * increased costs.
- */
-#if 0 /* BITS_PER_LONG > 32 -- currently broken: it increases power usage under light load  */
-# define SCHED_LOAD_RESOLUTION	10
-# define scale_load(w)		((w) << SCHED_LOAD_RESOLUTION)
-# define scale_load_down(w)	((w) >> SCHED_LOAD_RESOLUTION)
-#else
-# define SCHED_LOAD_RESOLUTION	0
-# define scale_load(w)		(w)
-# define scale_load_down(w)	(w)
-#endif
-
-#define SCHED_LOAD_SHIFT	(10 + SCHED_LOAD_RESOLUTION)
-#define SCHED_LOAD_SCALE	(1L << SCHED_LOAD_SHIFT)
-
-/*
  * Increase resolution of cpu_power calculations
  */
 #define SCHED_POWER_SHIFT	10
@@ -817,62 +777,6 @@ enum cpu_idle_type {
 
 extern int __weak arch_sd_sibiling_asym_packing(void);
 
-struct sched_group_power {
-	atomic_t ref;
-	/*
-	 * CPU power of this group, SCHED_LOAD_SCALE being max power for a
-	 * single CPU.
-	 */
-	unsigned int power, power_orig;
-	unsigned long next_update;
-	/*
-	 * Number of busy cpus in this group.
-	 */
-	atomic_t nr_busy_cpus;
-
-	unsigned long cpumask[0]; /* iteration mask */
-};
-
-struct sched_group {
-	struct sched_group *next;	/* Must be a circular list */
-	atomic_t ref;
-
-	unsigned int group_weight;
-	struct sched_group_power *sgp;
-
-	/*
-	 * The CPUs this group covers.
-	 *
-	 * NOTE: this field is variable length. (Allocated dynamically
-	 * by attaching extra space to the end of the structure,
-	 * depending on how many CPUs the kernel has booted up with)
-	 */
-	unsigned long cpumask[0];
-};
-
-static inline struct cpumask *sched_group_cpus(struct sched_group *sg)
-{
-	return to_cpumask(sg->cpumask);
-}
-
-/*
- * cpumask masking which cpus in the group are allowed to iterate up the domain
- * tree.
- */
-static inline struct cpumask *sched_group_mask(struct sched_group *sg)
-{
-	return to_cpumask(sg->sgp->cpumask);
-}
-
-/**
- * group_first_cpu - Returns the first cpu in the cpumask of a sched_group.
- * @group: The group whose first cpu is to be returned.
- */
-static inline unsigned int group_first_cpu(struct sched_group *group)
-{
-	return cpumask_first(sched_group_cpus(group));
-}
-
 struct sched_domain_attr {
 	int relax_domain_level;
 };
@@ -883,6 +787,8 @@ struct sched_domain_attr {
 
 extern int sched_domain_level_max;
 
+struct sched_group;
+
 struct sched_domain {
 	/* These fields must be setup */
 	struct sched_domain *parent;	/* top domain must be null terminated */
@@ -971,18 +877,6 @@ extern void partition_sched_domains(int ndoms_new, cpumask_var_t doms_new[],
 cpumask_var_t *alloc_sched_domains(unsigned int ndoms);
 void free_sched_domains(cpumask_var_t doms[], unsigned int ndoms);
 
-/* Test a flag in parent sched domain */
-static inline int test_sd_parent(struct sched_domain *sd, int flag)
-{
-	if (sd->parent && (sd->parent->flags & flag))
-		return 1;
-
-	return 0;
-}
-
-unsigned long default_scale_freq_power(struct sched_domain *sd, int cpu);
-unsigned long default_scale_smt_power(struct sched_domain *sd, int cpu);
-
 bool cpus_share_cache(int this_cpu, int that_cpu);
 
 #else /* CONFIG_SMP */
@@ -1017,72 +911,6 @@ struct mempolicy;
 struct pipe_inode_info;
 struct uts_namespace;
 
-struct rq;
-struct sched_domain;
-
-/*
- * wake flags
- */
-#define WF_SYNC		0x01		/* waker goes to sleep after wakup */
-#define WF_FORK		0x02		/* child wakeup after fork */
-#define WF_MIGRATED	0x04		/* internal use, task got migrated */
-
-#define ENQUEUE_WAKEUP		1
-#define ENQUEUE_HEAD		2
-#ifdef CONFIG_SMP
-#define ENQUEUE_WAKING		4	/* sched_class::task_waking was called */
-#else
-#define ENQUEUE_WAKING		0
-#endif
-
-#define DEQUEUE_SLEEP		1
-
-struct sched_class {
-	const struct sched_class *next;
-
-	void (*enqueue_task) (struct rq *rq, struct task_struct *p, int flags);
-	void (*dequeue_task) (struct rq *rq, struct task_struct *p, int flags);
-	void (*yield_task) (struct rq *rq);
-	bool (*yield_to_task) (struct rq *rq, struct task_struct *p, bool preempt);
-
-	void (*check_preempt_curr) (struct rq *rq, struct task_struct *p, int flags);
-
-	struct task_struct * (*pick_next_task) (struct rq *rq);
-	void (*put_prev_task) (struct rq *rq, struct task_struct *p);
-
-#ifdef CONFIG_SMP
-	int  (*select_task_rq)(struct task_struct *p, int sd_flag, int flags);
-	void (*migrate_task_rq)(struct task_struct *p, int next_cpu);
-
-	void (*pre_schedule) (struct rq *this_rq, struct task_struct *task);
-	void (*post_schedule) (struct rq *this_rq);
-	void (*task_waking) (struct task_struct *task);
-	void (*task_woken) (struct rq *this_rq, struct task_struct *task);
-
-	void (*set_cpus_allowed)(struct task_struct *p,
-				 const struct cpumask *newmask);
-
-	void (*rq_online)(struct rq *rq);
-	void (*rq_offline)(struct rq *rq);
-#endif
-
-	void (*set_curr_task) (struct rq *rq);
-	void (*task_tick) (struct rq *rq, struct task_struct *p, int queued);
-	void (*task_fork) (struct task_struct *p);
-
-	void (*switched_from) (struct rq *this_rq, struct task_struct *task);
-	void (*switched_to) (struct rq *this_rq, struct task_struct *task);
-	void (*prio_changed) (struct rq *this_rq, struct task_struct *task,
-			     int oldprio);
-
-	unsigned int (*get_rr_interval) (struct rq *rq,
-					 struct task_struct *task);
-
-#ifdef CONFIG_FAIR_GROUP_SCHED
-	void (*task_move_group) (struct task_struct *p, int on_rq);
-#endif
-};
-
 struct load_weight {
 	unsigned long weight, inv_weight;
 };
@@ -1327,7 +1155,7 @@ struct task_struct {
 
 	cputime_t utime, stime, utimescaled, stimescaled;
 	cputime_t gtime;
-#ifndef CONFIG_VIRT_CPU_ACCOUNTING
+#ifndef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
 	struct cputime prev_cputime;
 #endif
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN
@@ -1576,6 +1404,10 @@ struct task_struct {
 #ifdef CONFIG_UPROBES
 	struct uprobe_task *utask;
 #endif
+#if defined(CONFIG_BCACHE) || defined(CONFIG_BCACHE_MODULE)
+	unsigned int	sequential_io;
+	unsigned int	sequential_io_avg;
+#endif
 };
 
 /* Future-safe accessor for struct task_struct's cpus_allowed. */
@@ -1793,7 +1625,7 @@ extern void thread_group_cputime_adjusted(struct task_struct *p, cputime_t *ut,
 #define PF_SWAPWRITE	0x00800000	/* Allowed to write to swap */
 #define PF_SPREAD_PAGE	0x01000000	/* Spread page cache over cpuset */
 #define PF_SPREAD_SLAB	0x02000000	/* Spread some slab caches over cpuset */
-#define PF_THREAD_BOUND	0x04000000	/* Thread bound to specific cpu */
+#define PF_NO_SETAFFINITY 0x04000000	/* Userland is not allowed to meddle with cpus_allowed */
 #define PF_MCE_EARLY    0x08000000      /* Early kill for mce process policy */
 #define PF_MEMPOLICY	0x10000000	/* Non-default NUMA mempolicy */
 #define PF_MUTEX_TESTER	0x20000000	/* Thread belongs to the rt mutex tester */
@@ -2412,27 +2244,18 @@ static inline void threadgroup_change_end(struct task_struct *tsk)
  *
  * Lock the threadgroup @tsk belongs to.  No new task is allowed to enter
  * and member tasks aren't allowed to exit (as indicated by PF_EXITING) or
- * perform exec.  This is useful for cases where the threadgroup needs to
- * stay stable across blockable operations.
+ * change ->group_leader/pid.  This is useful for cases where the threadgroup
+ * needs to stay stable across blockable operations.
  *
  * fork and exit paths explicitly call threadgroup_change_{begin|end}() for
  * synchronization.  While held, no new task will be added to threadgroup
  * and no existing live task will have its PF_EXITING set.
  *
- * During exec, a task goes and puts its thread group through unusual
- * changes.  After de-threading, exclusive access is assumed to resources
- * which are usually shared by tasks in the same group - e.g. sighand may
- * be replaced with a new one.  Also, the exec'ing task takes over group
- * leader role including its pid.  Exclude these changes while locked by
- * grabbing cred_guard_mutex which is used to synchronize exec path.
+ * de_thread() does threadgroup_change_{begin|end}() when a non-leader
+ * sub-thread becomes a new leader.
  */
 static inline void threadgroup_lock(struct task_struct *tsk)
 {
-	/*
-	 * exec uses exit for de-threading nesting group_rwsem inside
-	 * cred_guard_mutex. Grab cred_guard_mutex first.
-	 */
-	mutex_lock(&tsk->signal->cred_guard_mutex);
 	down_write(&tsk->signal->group_rwsem);
 }
 
@@ -2445,7 +2268,6 @@ static inline void threadgroup_lock(struct task_struct *tsk)
 static inline void threadgroup_unlock(struct task_struct *tsk)
 {
 	up_write(&tsk->signal->group_rwsem);
-	mutex_unlock(&tsk->signal->cred_guard_mutex);
 }
 #else
 static inline void threadgroup_change_begin(struct task_struct *tsk) {}
@@ -2681,28 +2503,7 @@ extern long sched_setaffinity(pid_t pid, const struct cpumask *new_mask);
 extern long sched_getaffinity(pid_t pid, struct cpumask *mask);
 
 #ifdef CONFIG_CGROUP_SCHED
-
 extern struct task_group root_task_group;
-
-extern struct task_group *sched_create_group(struct task_group *parent);
-extern void sched_online_group(struct task_group *tg,
-			       struct task_group *parent);
-extern void sched_destroy_group(struct task_group *tg);
-extern void sched_offline_group(struct task_group *tg);
-extern void sched_move_task(struct task_struct *tsk);
-#ifdef CONFIG_FAIR_GROUP_SCHED
-extern int sched_group_set_shares(struct task_group *tg, unsigned long shares);
-extern unsigned long sched_group_shares(struct task_group *tg);
-#endif
-#ifdef CONFIG_RT_GROUP_SCHED
-extern int sched_group_set_rt_runtime(struct task_group *tg,
-				      long rt_runtime_us);
-extern long sched_group_rt_runtime(struct task_group *tg);
-extern int sched_group_set_rt_period(struct task_group *tg,
-				      long rt_period_us);
-extern long sched_group_rt_period(struct task_group *tg);
-extern int sched_rt_can_attach(struct task_group *tg, struct task_struct *tsk);
-#endif
 #endif /* CONFIG_CGROUP_SCHED */
 
 extern int task_can_switch_user(struct user_struct *up,
diff --git a/include/linux/security.h b/include/linux/security.h
index eee7478..4c7058d 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -1436,7 +1436,7 @@ struct security_operations {
 			     struct path *new_path);
 	int (*sb_set_mnt_opts) (struct super_block *sb,
 				struct security_mnt_opts *opts);
-	void (*sb_clone_mnt_opts) (const struct super_block *oldsb,
+	int (*sb_clone_mnt_opts) (const struct super_block *oldsb,
 				   struct super_block *newsb);
 	int (*sb_parse_opts_str) (char *options, struct security_mnt_opts *opts);
 
@@ -1721,7 +1721,7 @@ int security_sb_mount(const char *dev_name, struct path *path,
 int security_sb_umount(struct vfsmount *mnt, int flags);
 int security_sb_pivotroot(struct path *old_path, struct path *new_path);
 int security_sb_set_mnt_opts(struct super_block *sb, struct security_mnt_opts *opts);
-void security_sb_clone_mnt_opts(const struct super_block *oldsb,
+int security_sb_clone_mnt_opts(const struct super_block *oldsb,
 				struct super_block *newsb);
 int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts);
 
@@ -2011,9 +2011,11 @@ static inline int security_sb_set_mnt_opts(struct super_block *sb,
 	return 0;
 }
 
-static inline void security_sb_clone_mnt_opts(const struct super_block *oldsb,
+static inline int security_sb_clone_mnt_opts(const struct super_block *oldsb,
 					      struct super_block *newsb)
-{ }
+{
+	return 0;
+}
 
 static inline int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts)
 {
diff --git a/include/linux/seq_file.h b/include/linux/seq_file.h
index 68a04a3..2da29ac 100644
--- a/include/linux/seq_file.h
+++ b/include/linux/seq_file.h
@@ -123,6 +123,7 @@ static inline int seq_nodemask_list(struct seq_file *m, nodemask_t *mask)
 }
 
 int single_open(struct file *, int (*)(struct seq_file *, void *), void *);
+int single_open_size(struct file *, int (*)(struct seq_file *, void *), void *, size_t);
 int single_release(struct inode *, struct file *);
 void *__seq_open_private(struct file *, const struct seq_operations *, int);
 int seq_open_private(struct file *, const struct seq_operations *, int);
diff --git a/include/linux/serial_sci.h b/include/linux/serial_sci.h
index eb763ad..857eec4 100644
--- a/include/linux/serial_sci.h
+++ b/include/linux/serial_sci.h
@@ -11,11 +11,15 @@
 #define SCIx_NOT_SUPPORTED	(-1)
 
 enum {
+	SCBRR_ALGO_INVALID,
+
 	SCBRR_ALGO_1,		/* ((clk + 16 * bps) / (16 * bps) - 1) */
 	SCBRR_ALGO_2,		/* ((clk + 16 * bps) / (32 * bps) - 1) */
 	SCBRR_ALGO_3,		/* (((clk * 2) + 16 * bps) / (16 * bps) - 1) */
 	SCBRR_ALGO_4,		/* (((clk * 2) + 16 * bps) / (32 * bps) - 1) */
 	SCBRR_ALGO_5,		/* (((clk * 1000 / 32) / bps) - 1) */
+
+	SCBRR_NR_ALGOS,
 };
 
 #define SCSCR_TIE	(1 << 7)
diff --git a/include/linux/sh_eth.h b/include/linux/sh_eth.h
index b17d765d..fc30571 100644
--- a/include/linux/sh_eth.h
+++ b/include/linux/sh_eth.h
@@ -6,6 +6,7 @@
 enum {EDMAC_LITTLE_ENDIAN, EDMAC_BIG_ENDIAN};
 enum {
 	SH_ETH_REG_GIGABIT,
+	SH_ETH_REG_FAST_RCAR,
 	SH_ETH_REG_FAST_SH4,
 	SH_ETH_REG_FAST_SH3_SH2
 };
diff --git a/include/linux/signal.h b/include/linux/signal.h
index a2dcb94..9475c5c 100644
--- a/include/linux/signal.h
+++ b/include/linux/signal.h
@@ -250,11 +250,11 @@ extern int show_unhandled_signals;
 extern int sigsuspend(sigset_t *);
 
 struct sigaction {
-#ifndef __ARCH_HAS_ODD_SIGACTION
+#ifndef __ARCH_HAS_IRIX_SIGACTION
 	__sighandler_t	sa_handler;
 	unsigned long	sa_flags;
 #else
-	unsigned long	sa_flags;
+	unsigned int	sa_flags;
 	__sighandler_t	sa_handler;
 #endif
 #ifdef __ARCH_HAS_SA_RESTORER
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 441f5bf..b2b0926 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -32,6 +32,7 @@
 #include <linux/hrtimer.h>
 #include <linux/dma-mapping.h>
 #include <linux/netdev_features.h>
+#include <net/flow_keys.h>
 
 /* Don't change this without changing skb_csum_unnecessary! */
 #define CHECKSUM_NONE 0
@@ -316,6 +317,8 @@ enum {
 	SKB_GSO_FCOE = 1 << 5,
 
 	SKB_GSO_GRE = 1 << 6,
+
+	SKB_GSO_UDP_TUNNEL = 1 << 7,
 };
 
 #if BITS_PER_LONG > 32
@@ -387,6 +390,7 @@ typedef unsigned char *sk_buff_data_t;
  *	@vlan_tci: vlan tag control information
  *	@inner_transport_header: Inner transport layer header (encapsulation)
  *	@inner_network_header: Network layer header (encapsulation)
+ *	@inner_mac_header: Link layer header (encapsulation)
  *	@transport_header: Transport layer header
  *	@network_header: Network layer header
  *	@mac_header: Link layer header
@@ -505,6 +509,7 @@ struct sk_buff {
 
 	sk_buff_data_t		inner_transport_header;
 	sk_buff_data_t		inner_network_header;
+	sk_buff_data_t		inner_mac_header;
 	sk_buff_data_t		transport_header;
 	sk_buff_data_t		network_header;
 	sk_buff_data_t		mac_header;
@@ -1471,6 +1476,7 @@ static inline void skb_reserve(struct sk_buff *skb, int len)
 
 static inline void skb_reset_inner_headers(struct sk_buff *skb)
 {
+	skb->inner_mac_header = skb->mac_header;
 	skb->inner_network_header = skb->network_header;
 	skb->inner_transport_header = skb->transport_header;
 }
@@ -1516,6 +1522,22 @@ static inline void skb_set_inner_network_header(struct sk_buff *skb,
 	skb->inner_network_header += offset;
 }
 
+static inline unsigned char *skb_inner_mac_header(const struct sk_buff *skb)
+{
+	return skb->head + skb->inner_mac_header;
+}
+
+static inline void skb_reset_inner_mac_header(struct sk_buff *skb)
+{
+	skb->inner_mac_header = skb->data - skb->head;
+}
+
+static inline void skb_set_inner_mac_header(struct sk_buff *skb,
+					    const int offset)
+{
+	skb_reset_inner_mac_header(skb);
+	skb->inner_mac_header += offset;
+}
 static inline bool skb_transport_header_was_set(const struct sk_buff *skb)
 {
 	return skb->transport_header != ~0U;
@@ -1609,6 +1631,21 @@ static inline void skb_set_inner_network_header(struct sk_buff *skb,
 	skb->inner_network_header = skb->data + offset;
 }
 
+static inline unsigned char *skb_inner_mac_header(const struct sk_buff *skb)
+{
+	return skb->inner_mac_header;
+}
+
+static inline void skb_reset_inner_mac_header(struct sk_buff *skb)
+{
+	skb->inner_mac_header = skb->data;
+}
+
+static inline void skb_set_inner_mac_header(struct sk_buff *skb,
+						const int offset)
+{
+	skb->inner_mac_header = skb->data + offset;
+}
 static inline bool skb_transport_header_was_set(const struct sk_buff *skb)
 {
 	return skb->transport_header != NULL;
@@ -1666,6 +1703,19 @@ static inline void skb_set_mac_header(struct sk_buff *skb, const int offset)
 }
 #endif /* NET_SKBUFF_DATA_USES_OFFSET */
 
+static inline void skb_probe_transport_header(struct sk_buff *skb,
+					      const int offset_hint)
+{
+	struct flow_keys keys;
+
+	if (skb_transport_header_was_set(skb))
+		return;
+	else if (skb_flow_dissect(skb, &keys))
+		skb_set_transport_header(skb, keys.thoff);
+	else
+		skb_set_transport_header(skb, offset_hint);
+}
+
 static inline void skb_mac_header_rebuild(struct sk_buff *skb)
 {
 	if (skb_mac_header_was_set(skb)) {
@@ -2641,6 +2691,9 @@ static inline void nf_reset(struct sk_buff *skb)
 	nf_bridge_put(skb->nf_bridge);
 	skb->nf_bridge = NULL;
 #endif
+#if IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TRACE)
+	skb->nf_trace = 0;
+#endif
 }
 
 /* Note: This doesn't put any conntrack and bridge info in dst. */
@@ -2804,6 +2857,8 @@ static inline void skb_checksum_none_assert(const struct sk_buff *skb)
 
 bool skb_partial_csum_set(struct sk_buff *skb, u16 start, u16 off);
 
+u32 __skb_get_poff(const struct sk_buff *skb);
+
 /**
  * skb_head_is_locked - Determine if the skb->head is locked down
  * @skb: skb to check
diff --git a/include/linux/slab.h b/include/linux/slab.h
index 5d168d7..0c62175 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -94,29 +94,6 @@
 #define ZERO_OR_NULL_PTR(x) ((unsigned long)(x) <= \
 				(unsigned long)ZERO_SIZE_PTR)
 
-/*
- * Common fields provided in kmem_cache by all slab allocators
- * This struct is either used directly by the allocator (SLOB)
- * or the allocator must include definitions for all fields
- * provided in kmem_cache_common in their definition of kmem_cache.
- *
- * Once we can do anonymous structs (C11 standard) we could put a
- * anonymous struct definition in these allocators so that the
- * separate allocations in the kmem_cache structure of SLAB and
- * SLUB is no longer needed.
- */
-#ifdef CONFIG_SLOB
-struct kmem_cache {
-	unsigned int object_size;/* The original size of the object */
-	unsigned int size;	/* The aligned/padded/added on size  */
-	unsigned int align;	/* Alignment as calculated */
-	unsigned long flags;	/* Active flags on the slab */
-	const char *name;	/* Slab name for sysfs */
-	int refcount;		/* Use counter */
-	void (*ctor)(void *);	/* Called on object slot creation */
-	struct list_head list;	/* List of all slab caches on the system */
-};
-#endif
 
 struct mem_cgroup;
 /*
@@ -148,7 +125,63 @@ void kmem_cache_free(struct kmem_cache *, void *);
 		(__flags), NULL)
 
 /*
- * The largest kmalloc size supported by the slab allocators is
+ * Common kmalloc functions provided by all allocators
+ */
+void * __must_check __krealloc(const void *, size_t, gfp_t);
+void * __must_check krealloc(const void *, size_t, gfp_t);
+void kfree(const void *);
+void kzfree(const void *);
+size_t ksize(const void *);
+
+/*
+ * 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.
+ */
+#if defined(ARCH_DMA_MINALIGN) && ARCH_DMA_MINALIGN > 8
+#define ARCH_KMALLOC_MINALIGN ARCH_DMA_MINALIGN
+#define KMALLOC_MIN_SIZE ARCH_DMA_MINALIGN
+#define KMALLOC_SHIFT_LOW ilog2(ARCH_DMA_MINALIGN)
+#else
+#define ARCH_KMALLOC_MINALIGN __alignof__(unsigned long long)
+#endif
+
+#ifdef CONFIG_SLOB
+/*
+ * Common fields provided in kmem_cache by all slab allocators
+ * This struct is either used directly by the allocator (SLOB)
+ * or the allocator must include definitions for all fields
+ * provided in kmem_cache_common in their definition of kmem_cache.
+ *
+ * Once we can do anonymous structs (C11 standard) we could put a
+ * anonymous struct definition in these allocators so that the
+ * separate allocations in the kmem_cache structure of SLAB and
+ * SLUB is no longer needed.
+ */
+struct kmem_cache {
+	unsigned int object_size;/* The original size of the object */
+	unsigned int size;	/* The aligned/padded/added on size  */
+	unsigned int align;	/* Alignment as calculated */
+	unsigned long flags;	/* Active flags on the slab */
+	const char *name;	/* Slab name for sysfs */
+	int refcount;		/* Use counter */
+	void (*ctor)(void *);	/* Called on object slot creation */
+	struct list_head list;	/* List of all slab caches on the system */
+};
+
+#define KMALLOC_MAX_SIZE (1UL << 30)
+
+#include <linux/slob_def.h>
+
+#else /* CONFIG_SLOB */
+
+/*
+ * Kmalloc array related definitions
+ */
+
+#ifdef CONFIG_SLAB
+/*
+ * The largest kmalloc size supported by the SLAB allocators is
  * 32 megabyte (2^25) or the maximum allocatable page order if that is
  * less than 32 MB.
  *
@@ -158,22 +191,120 @@ void kmem_cache_free(struct kmem_cache *, void *);
  */
 #define KMALLOC_SHIFT_HIGH	((MAX_ORDER + PAGE_SHIFT - 1) <= 25 ? \
 				(MAX_ORDER + PAGE_SHIFT - 1) : 25)
+#define KMALLOC_SHIFT_MAX	KMALLOC_SHIFT_HIGH
+#ifndef KMALLOC_SHIFT_LOW
+#define KMALLOC_SHIFT_LOW	5
+#endif
+#else
+/*
+ * SLUB allocates up to order 2 pages directly and otherwise
+ * passes the request to the page allocator.
+ */
+#define KMALLOC_SHIFT_HIGH	(PAGE_SHIFT + 1)
+#define KMALLOC_SHIFT_MAX	(MAX_ORDER + PAGE_SHIFT)
+#ifndef KMALLOC_SHIFT_LOW
+#define KMALLOC_SHIFT_LOW	3
+#endif
+#endif
 
-#define KMALLOC_MAX_SIZE	(1UL << KMALLOC_SHIFT_HIGH)
-#define KMALLOC_MAX_ORDER	(KMALLOC_SHIFT_HIGH - PAGE_SHIFT)
+/* Maximum allocatable size */
+#define KMALLOC_MAX_SIZE	(1UL << KMALLOC_SHIFT_MAX)
+/* Maximum size for which we actually use a slab cache */
+#define KMALLOC_MAX_CACHE_SIZE	(1UL << KMALLOC_SHIFT_HIGH)
+/* Maximum order allocatable via the slab allocagtor */
+#define KMALLOC_MAX_ORDER	(KMALLOC_SHIFT_MAX - 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.
+ * Kmalloc subsystem.
  */
-#ifdef ARCH_DMA_MINALIGN
-#define ARCH_KMALLOC_MINALIGN ARCH_DMA_MINALIGN
+#ifndef KMALLOC_MIN_SIZE
+#define KMALLOC_MIN_SIZE (1 << KMALLOC_SHIFT_LOW)
+#endif
+
+extern struct kmem_cache *kmalloc_caches[KMALLOC_SHIFT_HIGH + 1];
+#ifdef CONFIG_ZONE_DMA
+extern struct kmem_cache *kmalloc_dma_caches[KMALLOC_SHIFT_HIGH + 1];
+#endif
+
+/*
+ * Figure out which kmalloc slab an allocation of a certain size
+ * belongs to.
+ * 0 = zero alloc
+ * 1 =  65 .. 96 bytes
+ * 2 = 120 .. 192 bytes
+ * n = 2^(n-1) .. 2^n -1
+ */
+static __always_inline int kmalloc_index(size_t size)
+{
+	if (!size)
+		return 0;
+
+	if (size <= KMALLOC_MIN_SIZE)
+		return KMALLOC_SHIFT_LOW;
+
+	if (KMALLOC_MIN_SIZE <= 32 && size > 64 && size <= 96)
+		return 1;
+	if (KMALLOC_MIN_SIZE <= 64 && size > 128 && size <= 192)
+		return 2;
+	if (size <=          8) return 3;
+	if (size <=         16) return 4;
+	if (size <=         32) return 5;
+	if (size <=         64) return 6;
+	if (size <=        128) return 7;
+	if (size <=        256) return 8;
+	if (size <=        512) return 9;
+	if (size <=       1024) return 10;
+	if (size <=   2 * 1024) return 11;
+	if (size <=   4 * 1024) return 12;
+	if (size <=   8 * 1024) return 13;
+	if (size <=  16 * 1024) return 14;
+	if (size <=  32 * 1024) return 15;
+	if (size <=  64 * 1024) return 16;
+	if (size <= 128 * 1024) return 17;
+	if (size <= 256 * 1024) return 18;
+	if (size <= 512 * 1024) return 19;
+	if (size <= 1024 * 1024) return 20;
+	if (size <=  2 * 1024 * 1024) return 21;
+	if (size <=  4 * 1024 * 1024) return 22;
+	if (size <=  8 * 1024 * 1024) return 23;
+	if (size <=  16 * 1024 * 1024) return 24;
+	if (size <=  32 * 1024 * 1024) return 25;
+	if (size <=  64 * 1024 * 1024) return 26;
+	BUG();
+
+	/* Will never be reached. Needed because the compiler may complain */
+	return -1;
+}
+
+#ifdef CONFIG_SLAB
+#include <linux/slab_def.h>
+#elif defined(CONFIG_SLUB)
+#include <linux/slub_def.h>
 #else
-#define ARCH_KMALLOC_MINALIGN __alignof__(unsigned long long)
+#error "Unknown slab allocator"
 #endif
 
 /*
+ * Determine size used for the nth kmalloc cache.
+ * return size or 0 if a kmalloc cache for that
+ * size does not exist
+ */
+static __always_inline int kmalloc_size(int n)
+{
+	if (n > 2)
+		return 1 << n;
+
+	if (n == 1 && KMALLOC_MIN_SIZE <= 32)
+		return 96;
+
+	if (n == 2 && KMALLOC_MIN_SIZE <= 64)
+		return 192;
+
+	return 0;
+}
+#endif /* !CONFIG_SLOB */
+
+/*
  * 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.
@@ -224,42 +355,6 @@ struct seq_file;
 int cache_show(struct kmem_cache *s, struct seq_file *m);
 void print_slabinfo_header(struct seq_file *m);
 
-/*
- * Common kmalloc functions provided by all allocators
- */
-void * __must_check __krealloc(const void *, size_t, gfp_t);
-void * __must_check krealloc(const void *, size_t, gfp_t);
-void kfree(const void *);
-void kzfree(const void *);
-size_t ksize(const void *);
-
-/*
- * Allocator specific definitions. These are mainly used to establish optimized
- * ways to convert kmalloc() calls to kmem_cache_alloc() invocations by
- * selecting the appropriate general cache at compile time.
- *
- * Allocators must define at least:
- *
- *	kmem_cache_alloc()
- *	__kmalloc()
- *	kmalloc()
- *
- * Those wishing to support NUMA must also define:
- *
- *	kmem_cache_alloc_node()
- *	kmalloc_node()
- *
- * See each allocator definition file for additional comments and
- * implementation notes.
- */
-#ifdef CONFIG_SLUB
-#include <linux/slub_def.h>
-#elif defined(CONFIG_SLOB)
-#include <linux/slob_def.h>
-#else
-#include <linux/slab_def.h>
-#endif
-
 /**
  * kmalloc_array - allocate memory for an array.
  * @n: number of elements.
diff --git a/include/linux/slab_def.h b/include/linux/slab_def.h
index 8bb6e0e..113ec08 100644
--- a/include/linux/slab_def.h
+++ b/include/linux/slab_def.h
@@ -11,8 +11,6 @@
  */
 
 #include <linux/init.h>
-#include <asm/page.h>		/* kmalloc_sizes.h needs PAGE_SIZE */
-#include <asm/cache.h>		/* kmalloc_sizes.h needs L1_CACHE_BYTES */
 #include <linux/compiler.h>
 
 /*
@@ -97,23 +95,13 @@ struct kmem_cache {
 	 * pointer for each node since "nodelists" uses the remainder of
 	 * available pointers.
 	 */
-	struct kmem_list3 **nodelists;
+	struct kmem_cache_node **node;
 	struct array_cache *array[NR_CPUS + MAX_NUMNODES];
 	/*
 	 * Do not add fields after array[]
 	 */
 };
 
-/* Size description struct for general caches. */
-struct cache_sizes {
-	size_t		 	cs_size;
-	struct kmem_cache	*cs_cachep;
-#ifdef CONFIG_ZONE_DMA
-	struct kmem_cache	*cs_dmacachep;
-#endif
-};
-extern struct cache_sizes malloc_sizes[];
-
 void *kmem_cache_alloc(struct kmem_cache *, gfp_t);
 void *__kmalloc(size_t size, gfp_t flags);
 
@@ -133,26 +121,19 @@ static __always_inline void *kmalloc(size_t size, gfp_t flags)
 	void *ret;
 
 	if (__builtin_constant_p(size)) {
-		int i = 0;
+		int i;
 
 		if (!size)
 			return ZERO_SIZE_PTR;
 
-#define CACHE(x) \
-		if (size <= x) \
-			goto found; \
-		else \
-			i++;
-#include <linux/kmalloc_sizes.h>
-#undef CACHE
-		return NULL;
-found:
+		i = kmalloc_index(size);
+
 #ifdef CONFIG_ZONE_DMA
 		if (flags & GFP_DMA)
-			cachep = malloc_sizes[i].cs_dmacachep;
+			cachep = kmalloc_dma_caches[i];
 		else
 #endif
-			cachep = malloc_sizes[i].cs_cachep;
+			cachep = kmalloc_caches[i];
 
 		ret = kmem_cache_alloc_trace(cachep, flags, size);
 
@@ -186,26 +167,19 @@ static __always_inline void *kmalloc_node(size_t size, gfp_t flags, int node)
 	struct kmem_cache *cachep;
 
 	if (__builtin_constant_p(size)) {
-		int i = 0;
+		int i;
 
 		if (!size)
 			return ZERO_SIZE_PTR;
 
-#define CACHE(x) \
-		if (size <= x) \
-			goto found; \
-		else \
-			i++;
-#include <linux/kmalloc_sizes.h>
-#undef CACHE
-		return NULL;
-found:
+		i = kmalloc_index(size);
+
 #ifdef CONFIG_ZONE_DMA
 		if (flags & GFP_DMA)
-			cachep = malloc_sizes[i].cs_dmacachep;
+			cachep = kmalloc_dma_caches[i];
 		else
 #endif
-			cachep = malloc_sizes[i].cs_cachep;
+			cachep = kmalloc_caches[i];
 
 		return kmem_cache_alloc_node_trace(cachep, flags, node, size);
 	}
diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h
index 9db4825..027276f 100644
--- a/include/linux/slub_def.h
+++ b/include/linux/slub_def.h
@@ -53,17 +53,6 @@ struct kmem_cache_cpu {
 #endif
 };
 
-struct kmem_cache_node {
-	spinlock_t list_lock;	/* Protect partial list and nr_partial */
-	unsigned long nr_partial;
-	struct list_head partial;
-#ifdef CONFIG_SLUB_DEBUG
-	atomic_long_t nr_slabs;
-	atomic_long_t total_objects;
-	struct list_head full;
-#endif
-};
-
 /*
  * Word size structure that can be atomically updated or read and that
  * contains both the order and the number of objects that a slab of the
@@ -115,111 +104,6 @@ struct kmem_cache {
 	struct kmem_cache_node *node[MAX_NUMNODES];
 };
 
-/*
- * Kmalloc subsystem.
- */
-#if defined(ARCH_DMA_MINALIGN) && ARCH_DMA_MINALIGN > 8
-#define KMALLOC_MIN_SIZE ARCH_DMA_MINALIGN
-#else
-#define KMALLOC_MIN_SIZE 8
-#endif
-
-#define KMALLOC_SHIFT_LOW ilog2(KMALLOC_MIN_SIZE)
-
-/*
- * Maximum kmalloc object size handled by SLUB. Larger object allocations
- * are passed through to the page allocator. The page allocator "fastpath"
- * is relatively slow so we need this value sufficiently high so that
- * performance critical objects are allocated through the SLUB fastpath.
- *
- * This should be dropped to PAGE_SIZE / 2 once the page allocator
- * "fastpath" becomes competitive with the slab allocator fastpaths.
- */
-#define SLUB_MAX_SIZE (2 * PAGE_SIZE)
-
-#define SLUB_PAGE_SHIFT (PAGE_SHIFT + 2)
-
-#ifdef CONFIG_ZONE_DMA
-#define SLUB_DMA __GFP_DMA
-#else
-/* Disable DMA functionality */
-#define SLUB_DMA (__force gfp_t)0
-#endif
-
-/*
- * We keep the general caches in an array of slab caches that are used for
- * 2^x bytes of allocations.
- */
-extern struct kmem_cache *kmalloc_caches[SLUB_PAGE_SHIFT];
-
-/*
- * Sorry that the following has to be that ugly but some versions of GCC
- * have trouble with constant propagation and loops.
- */
-static __always_inline int kmalloc_index(size_t size)
-{
-	if (!size)
-		return 0;
-
-	if (size <= KMALLOC_MIN_SIZE)
-		return KMALLOC_SHIFT_LOW;
-
-	if (KMALLOC_MIN_SIZE <= 32 && size > 64 && size <= 96)
-		return 1;
-	if (KMALLOC_MIN_SIZE <= 64 && size > 128 && size <= 192)
-		return 2;
-	if (size <=          8) return 3;
-	if (size <=         16) return 4;
-	if (size <=         32) return 5;
-	if (size <=         64) return 6;
-	if (size <=        128) return 7;
-	if (size <=        256) return 8;
-	if (size <=        512) return 9;
-	if (size <=       1024) return 10;
-	if (size <=   2 * 1024) return 11;
-	if (size <=   4 * 1024) return 12;
-/*
- * The following is only needed to support architectures with a larger page
- * size than 4k. We need to support 2 * PAGE_SIZE here. So for a 64k page
- * size we would have to go up to 128k.
- */
-	if (size <=   8 * 1024) return 13;
-	if (size <=  16 * 1024) return 14;
-	if (size <=  32 * 1024) return 15;
-	if (size <=  64 * 1024) return 16;
-	if (size <= 128 * 1024) return 17;
-	if (size <= 256 * 1024) return 18;
-	if (size <= 512 * 1024) return 19;
-	if (size <= 1024 * 1024) return 20;
-	if (size <=  2 * 1024 * 1024) return 21;
-	BUG();
-	return -1; /* Will never be reached */
-
-/*
- * What we really wanted to do and cannot do because of compiler issues is:
- *	int i;
- *	for (i = KMALLOC_SHIFT_LOW; i <= KMALLOC_SHIFT_HIGH; i++)
- *		if (size <= (1 << i))
- *			return i;
- */
-}
-
-/*
- * Find the slab cache for a given combination of allocation flags and size.
- *
- * This ought to end up with a global pointer to the right cache
- * in kmalloc_caches.
- */
-static __always_inline struct kmem_cache *kmalloc_slab(size_t size)
-{
-	int index = kmalloc_index(size);
-
-	if (index == 0)
-		return NULL;
-
-	return kmalloc_caches[index];
-}
-
 void *kmem_cache_alloc(struct kmem_cache *, gfp_t);
 void *__kmalloc(size_t size, gfp_t flags);
 
@@ -274,16 +158,17 @@ static __always_inline void *kmalloc_large(size_t size, gfp_t flags)
 static __always_inline void *kmalloc(size_t size, gfp_t flags)
 {
 	if (__builtin_constant_p(size)) {
-		if (size > SLUB_MAX_SIZE)
+		if (size > KMALLOC_MAX_CACHE_SIZE)
 			return kmalloc_large(size, flags);
 
-		if (!(flags & SLUB_DMA)) {
-			struct kmem_cache *s = kmalloc_slab(size);
+		if (!(flags & GFP_DMA)) {
+			int index = kmalloc_index(size);
 
-			if (!s)
+			if (!index)
 				return ZERO_SIZE_PTR;
 
-			return kmem_cache_alloc_trace(s, flags, size);
+			return kmem_cache_alloc_trace(kmalloc_caches[index],
+					flags, size);
 		}
 	}
 	return __kmalloc(size, flags);
@@ -310,13 +195,14 @@ kmem_cache_alloc_node_trace(struct kmem_cache *s,
 static __always_inline void *kmalloc_node(size_t size, gfp_t flags, int node)
 {
 	if (__builtin_constant_p(size) &&
-		size <= SLUB_MAX_SIZE && !(flags & SLUB_DMA)) {
-			struct kmem_cache *s = kmalloc_slab(size);
+		size <= KMALLOC_MAX_CACHE_SIZE && !(flags & GFP_DMA)) {
+		int index = kmalloc_index(size);
 
-		if (!s)
+		if (!index)
 			return ZERO_SIZE_PTR;
 
-		return kmem_cache_alloc_node_trace(s, flags, node, size);
+		return kmem_cache_alloc_node_trace(kmalloc_caches[index],
+			       flags, node, size);
 	}
 	return __kmalloc_node(size, flags, node);
 }
diff --git a/include/linux/socket.h b/include/linux/socket.h
index 2b9f74b..428c37a 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -298,6 +298,7 @@ struct ucred {
 #define SOL_IUCV	277
 #define SOL_CAIF	278
 #define SOL_ALG		279
+#define SOL_NFC		280
 
 /* IPX options */
 #define IPX_TYPE	1
diff --git a/include/linux/spi/mxs-spi.h b/include/linux/spi/mxs-spi.h
index 61ae130..4835486 100644
--- a/include/linux/spi/mxs-spi.h
+++ b/include/linux/spi/mxs-spi.h
@@ -24,7 +24,7 @@
 #ifndef __LINUX_SPI_MXS_SPI_H__
 #define __LINUX_SPI_MXS_SPI_H__
 
-#include <linux/fsl/mxs-dma.h>
+#include <linux/dmaengine.h>
 
 #define ssp_is_old(host)	((host)->devid == IMX23_SSP)
 
@@ -137,9 +137,7 @@ struct mxs_ssp {
 	unsigned int			clk_rate;
 	enum mxs_ssp_id			devid;
 
-	int				dma_channel;
 	struct dma_chan			*dmach;
-	struct mxs_dma_data		dma_data;
 	unsigned int			dma_dir;
 	enum dma_transfer_direction	slave_dirn;
 	u32				ssp_pio_words[SSP_PIO_NUM];
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index 38c2b92..733eb5e 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -228,6 +228,11 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
  *	every chipselect is connected to a slave.
  * @dma_alignment: SPI controller constraint on DMA buffers alignment.
  * @mode_bits: flags understood by this controller driver
+ * @bits_per_word_mask: A mask indicating which values of bits_per_word are
+ *	supported by the driver. Bit n indicates that a bits_per_word n+1 is
+ *	suported. If set, the SPI core will reject any transfer with an
+ *	unsupported bits_per_word. If not set, this value is simply ignored,
+ *	and it's up to the individual driver to perform any validation.
  * @flags: other constraints relevant to this driver
  * @bus_lock_spinlock: spinlock for SPI bus locking
  * @bus_lock_mutex: mutex for SPI bus locking
@@ -301,6 +306,9 @@ struct spi_master {
 	/* spi_device.mode flags understood by this controller driver */
 	u16			mode_bits;
 
+	/* bitmask of supported bits_per_word for transfers */
+	u32			bits_per_word_mask;
+
 	/* other constraints relevant to this driver */
 	u16			flags;
 #define SPI_MASTER_HALF_DUPLEX	BIT(0)		/* can't do full duplex */
diff --git a/include/linux/ssb/ssb.h b/include/linux/ssb/ssb.h
index 22958d6..c64999f 100644
--- a/include/linux/ssb/ssb.h
+++ b/include/linux/ssb/ssb.h
@@ -26,9 +26,9 @@ struct ssb_sprom_core_pwr_info {
 
 struct ssb_sprom {
 	u8 revision;
-	u8 il0mac[6];		/* MAC address for 802.11b/g */
-	u8 et0mac[6];		/* MAC address for Ethernet */
-	u8 et1mac[6];		/* MAC address for 802.11a */
+	u8 il0mac[6] __aligned(sizeof(u16));	/* MAC address for 802.11b/g */
+	u8 et0mac[6] __aligned(sizeof(u16));	/* MAC address for Ethernet */
+	u8 et1mac[6] __aligned(sizeof(u16));	/* MAC address for 802.11a */
 	u8 et0phyaddr;		/* MII address for enet0 */
 	u8 et1phyaddr;		/* MII address for enet1 */
 	u8 et0mdcport;		/* MDIO for enet0 */
@@ -340,13 +340,61 @@ enum ssb_bustype {
 #define SSB_BOARDVENDOR_DELL	0x1028	/* Dell */
 #define SSB_BOARDVENDOR_HP	0x0E11	/* HP */
 /* board_type */
+#define SSB_BOARD_BCM94301CB	0x0406
+#define SSB_BOARD_BCM94301MP	0x0407
+#define SSB_BOARD_BU4309	0x040A
+#define SSB_BOARD_BCM94309CB	0x040B
+#define SSB_BOARD_BCM4309MP	0x040C
+#define SSB_BOARD_BU4306	0x0416
 #define SSB_BOARD_BCM94306MP	0x0418
 #define SSB_BOARD_BCM4309G	0x0421
 #define SSB_BOARD_BCM4306CB	0x0417
-#define SSB_BOARD_BCM4309MP	0x040C
+#define SSB_BOARD_BCM94306PC	0x0425	/* pcmcia 3.3v 4306 card */
+#define SSB_BOARD_BCM94306CBSG	0x042B	/* with SiGe PA */
+#define SSB_BOARD_PCSG94306	0x042D	/* with SiGe PA */
+#define SSB_BOARD_BU4704SD	0x042E	/* with sdram */
+#define SSB_BOARD_BCM94704AGR	0x042F	/* dual 11a/11g Router */
+#define SSB_BOARD_BCM94308MP	0x0430	/* 11a-only minipci */
+#define SSB_BOARD_BU4318	0x0447
+#define SSB_BOARD_CB4318	0x0448
+#define SSB_BOARD_MPG4318	0x0449
 #define SSB_BOARD_MP4318	0x044A
-#define SSB_BOARD_BU4306	0x0416
-#define SSB_BOARD_BU4309	0x040A
+#define SSB_BOARD_SD4318	0x044B
+#define SSB_BOARD_BCM94306P	0x044C	/* with SiGe */
+#define SSB_BOARD_BCM94303MP	0x044E
+#define SSB_BOARD_BCM94306MPM	0x0450
+#define SSB_BOARD_BCM94306MPL	0x0453
+#define SSB_BOARD_PC4303	0x0454	/* pcmcia */
+#define SSB_BOARD_BCM94306MPLNA	0x0457
+#define SSB_BOARD_BCM94306MPH	0x045B
+#define SSB_BOARD_BCM94306PCIV	0x045C
+#define SSB_BOARD_BCM94318MPGH	0x0463
+#define SSB_BOARD_BU4311	0x0464
+#define SSB_BOARD_BCM94311MC	0x0465
+#define SSB_BOARD_BCM94311MCAG	0x0466
+/* 4321 boards */
+#define SSB_BOARD_BU4321	0x046B
+#define SSB_BOARD_BU4321E	0x047C
+#define SSB_BOARD_MP4321	0x046C
+#define SSB_BOARD_CB2_4321	0x046D
+#define SSB_BOARD_CB2_4321_AG	0x0066
+#define SSB_BOARD_MC4321	0x046E
+/* 4325 boards */
+#define SSB_BOARD_BCM94325DEVBU	0x0490
+#define SSB_BOARD_BCM94325BGABU	0x0491
+#define SSB_BOARD_BCM94325SDGWB	0x0492
+#define SSB_BOARD_BCM94325SDGMDL	0x04AA
+#define SSB_BOARD_BCM94325SDGMDL2	0x04C6
+#define SSB_BOARD_BCM94325SDGMDL3	0x04C9
+#define SSB_BOARD_BCM94325SDABGWBA	0x04E1
+/* 4322 boards */
+#define SSB_BOARD_BCM94322MC	0x04A4
+#define SSB_BOARD_BCM94322USB	0x04A8	/* dualband */
+#define SSB_BOARD_BCM94322HM	0x04B0
+#define SSB_BOARD_BCM94322USB2D	0x04Bf	/* single band discrete front end */
+/* 4312 boards */
+#define SSB_BOARD_BU4312	0x048A
+#define SSB_BOARD_BCM4312MCGSG	0x04B5
 /* chip_package */
 #define SSB_CHIPPACK_BCM4712S	1	/* Small 200pin 4712 */
 #define SSB_CHIPPACK_BCM4712M	2	/* Medium 225pin 4712 */
diff --git a/include/linux/ssb/ssb_regs.h b/include/linux/ssb/ssb_regs.h
index 6ecfa02..3a72569 100644
--- a/include/linux/ssb/ssb_regs.h
+++ b/include/linux/ssb/ssb_regs.h
@@ -289,11 +289,11 @@
 #define  SSB_SPROM4_ETHPHY_ET1A_SHIFT	5
 #define  SSB_SPROM4_ETHPHY_ET0M		(1<<14)	/* MDIO for enet0 */
 #define  SSB_SPROM4_ETHPHY_ET1M		(1<<15)	/* MDIO for enet1 */
-#define SSB_SPROM4_ANTAVAIL		0x005D  /* Antenna available bitfields */
-#define  SSB_SPROM4_ANTAVAIL_A		0x00FF	/* A-PHY bitfield */
-#define  SSB_SPROM4_ANTAVAIL_A_SHIFT	0
-#define  SSB_SPROM4_ANTAVAIL_BG		0xFF00	/* B-PHY and G-PHY bitfield */
-#define  SSB_SPROM4_ANTAVAIL_BG_SHIFT	8
+#define SSB_SPROM4_ANTAVAIL		0x005C  /* Antenna available bitfields */
+#define  SSB_SPROM4_ANTAVAIL_BG		0x00FF	/* B-PHY and G-PHY bitfield */
+#define  SSB_SPROM4_ANTAVAIL_BG_SHIFT	0
+#define  SSB_SPROM4_ANTAVAIL_A		0xFF00	/* A-PHY bitfield */
+#define  SSB_SPROM4_ANTAVAIL_A_SHIFT	8
 #define SSB_SPROM4_AGAIN01		0x005E	/* Antenna Gain (in dBm Q5.2) */
 #define  SSB_SPROM4_AGAIN0		0x00FF	/* Antenna 0 */
 #define  SSB_SPROM4_AGAIN0_SHIFT	0
diff --git a/include/linux/ssbi.h b/include/linux/ssbi.h
new file mode 100644
index 0000000..44ef5da
--- /dev/null
+++ b/include/linux/ssbi.h
@@ -0,0 +1,38 @@
+/* Copyright (C) 2010 Google, Inc.
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Author: Dima Zavin <dima@android.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 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 _LINUX_SSBI_H
+#define _LINUX_SSBI_H
+
+#include <linux/types.h>
+
+struct ssbi_slave_info {
+	const char	*name;
+	void		*platform_data;
+};
+
+enum ssbi_controller_type {
+	MSM_SBI_CTRL_SSBI = 0,
+	MSM_SBI_CTRL_SSBI2,
+	MSM_SBI_CTRL_PMIC_ARBITER,
+};
+
+struct ssbi_platform_data {
+	struct ssbi_slave_info	slave;
+	enum ssbi_controller_type controller_type;
+};
+
+int ssbi_write(struct device *dev, u16 addr, u8 *buf, int len);
+int ssbi_read(struct device *dev, u16 addr, u8 *buf, int len);
+#endif
diff --git a/include/linux/sunrpc/auth.h b/include/linux/sunrpc/auth.h
index 58fda1c..0dd00f4 100644
--- a/include/linux/sunrpc/auth.h
+++ b/include/linux/sunrpc/auth.h
@@ -22,6 +22,8 @@
 /* size of the nodename buffer */
 #define UNX_MAXNODENAME	32
 
+struct rpcsec_gss_info;
+
 /* Work around the lack of a VFS credential */
 struct auth_cred {
 	kuid_t	uid;
@@ -103,6 +105,9 @@ struct rpc_authops {
 	int			(*pipes_create)(struct rpc_auth *);
 	void			(*pipes_destroy)(struct rpc_auth *);
 	int			(*list_pseudoflavors)(rpc_authflavor_t *, int);
+	rpc_authflavor_t	(*info2flavor)(struct rpcsec_gss_info *);
+	int			(*flavor2info)(rpc_authflavor_t,
+						struct rpcsec_gss_info *);
 };
 
 struct rpc_credops {
@@ -137,6 +142,10 @@ int			rpcauth_register(const struct rpc_authops *);
 int			rpcauth_unregister(const struct rpc_authops *);
 struct rpc_auth *	rpcauth_create(rpc_authflavor_t, struct rpc_clnt *);
 void			rpcauth_release(struct rpc_auth *);
+rpc_authflavor_t	rpcauth_get_pseudoflavor(rpc_authflavor_t,
+				struct rpcsec_gss_info *);
+int			rpcauth_get_gssinfo(rpc_authflavor_t,
+				struct rpcsec_gss_info *);
 int			rpcauth_list_flavors(rpc_authflavor_t *, int);
 struct rpc_cred *	rpcauth_lookup_credcache(struct rpc_auth *, struct auth_cred *, int);
 void			rpcauth_init_cred(struct rpc_cred *, const struct auth_cred *, struct rpc_auth *, const struct rpc_credops *);
diff --git a/include/linux/sunrpc/gss_api.h b/include/linux/sunrpc/gss_api.h
index a19e254..f32b7a4 100644
--- a/include/linux/sunrpc/gss_api.h
+++ b/include/linux/sunrpc/gss_api.h
@@ -25,10 +25,21 @@ struct gss_ctx {
 
 #define GSS_C_NO_BUFFER		((struct xdr_netobj) 0)
 #define GSS_C_NO_CONTEXT	((struct gss_ctx *) 0)
-#define GSS_C_NULL_OID		((struct xdr_netobj) 0)
+#define GSS_C_QOP_DEFAULT	(0)
 
 /*XXX  arbitrary length - is this set somewhere? */
 #define GSS_OID_MAX_LEN 32
+struct rpcsec_gss_oid {
+	unsigned int	len;
+	u8		data[GSS_OID_MAX_LEN];
+};
+
+/* From RFC 3530 */
+struct rpcsec_gss_info {
+	struct rpcsec_gss_oid	oid;
+	u32			qop;
+	u32			service;
+};
 
 /* gss-api prototypes; note that these are somewhat simplified versions of
  * the prototypes specified in RFC 2744. */
@@ -58,12 +69,14 @@ u32 gss_unwrap(
 u32 gss_delete_sec_context(
 		struct gss_ctx		**ctx_id);
 
-u32 gss_svc_to_pseudoflavor(struct gss_api_mech *, u32 service);
+rpc_authflavor_t gss_svc_to_pseudoflavor(struct gss_api_mech *, u32 qop,
+					u32 service);
 u32 gss_pseudoflavor_to_service(struct gss_api_mech *, u32 pseudoflavor);
 char *gss_service_to_auth_domain_name(struct gss_api_mech *, u32 service);
 
 struct pf_desc {
 	u32	pseudoflavor;
+	u32	qop;
 	u32	service;
 	char	*name;
 	char	*auth_domain_name;
@@ -76,7 +89,7 @@ struct pf_desc {
 struct gss_api_mech {
 	struct list_head	gm_list;
 	struct module		*gm_owner;
-	struct xdr_netobj	gm_oid;
+	struct rpcsec_gss_oid	gm_oid;
 	char			*gm_name;
 	const struct gss_api_ops *gm_ops;
 	/* pseudoflavors supported by this mechanism: */
@@ -117,9 +130,11 @@ struct gss_api_ops {
 int gss_mech_register(struct gss_api_mech *);
 void gss_mech_unregister(struct gss_api_mech *);
 
-/* returns a mechanism descriptor given an OID, and increments the mechanism's
- * reference count. */
-struct gss_api_mech * gss_mech_get_by_OID(struct xdr_netobj *);
+/* Given a GSS security tuple, look up a pseudoflavor */
+rpc_authflavor_t gss_mech_info2flavor(struct rpcsec_gss_info *);
+
+/* Given a pseudoflavor, look up a GSS security tuple */
+int gss_mech_flavor2info(rpc_authflavor_t, struct rpcsec_gss_info *);
 
 /* Returns a reference to a mechanism, given a name like "krb5" etc. */
 struct gss_api_mech *gss_mech_get_by_name(const char *);
@@ -130,9 +145,6 @@ struct gss_api_mech *gss_mech_get_by_pseudoflavor(u32);
 /* Fill in an array with a list of supported pseudoflavors */
 int gss_mech_list_pseudoflavors(rpc_authflavor_t *, int);
 
-/* Just increments the mechanism's reference count and returns its input: */
-struct gss_api_mech * gss_mech_get(struct gss_api_mech *);
-
 /* For every successful gss_mech_get or gss_mech_get_by_* call there must be a
  * corresponding call to gss_mech_put. */
 void gss_mech_put(struct gss_api_mech *);
diff --git a/include/linux/swap.h b/include/linux/swap.h
index 2818a12..7429973 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -331,7 +331,8 @@ static inline void mem_cgroup_uncharge_swap(swp_entry_t ent)
 extern int swap_readpage(struct page *);
 extern int swap_writepage(struct page *page, struct writeback_control *wbc);
 extern int swap_set_page_dirty(struct page *page);
-extern void end_swap_bio_read(struct bio *bio, int err);
+extern void end_swap_bio_read(struct bio *bio, int err,
+			      struct batch_complete *batch);
 
 int add_swap_extent(struct swap_info_struct *sis, unsigned long start_page,
 		unsigned long nr_pages, sector_t start_block);
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 313a8e0..4147d70 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -78,49 +78,34 @@ struct sigaltstack;
 #include <linux/key.h>
 #include <trace/syscall.h>
 
-#define __SC_DECL1(t1, a1)	t1 a1
-#define __SC_DECL2(t2, a2, ...) t2 a2, __SC_DECL1(__VA_ARGS__)
-#define __SC_DECL3(t3, a3, ...) t3 a3, __SC_DECL2(__VA_ARGS__)
-#define __SC_DECL4(t4, a4, ...) t4 a4, __SC_DECL3(__VA_ARGS__)
-#define __SC_DECL5(t5, a5, ...) t5 a5, __SC_DECL4(__VA_ARGS__)
-#define __SC_DECL6(t6, a6, ...) t6 a6, __SC_DECL5(__VA_ARGS__)
-
-#define __SC_LONG1(t1, a1) 	long a1
-#define __SC_LONG2(t2, a2, ...) long a2, __SC_LONG1(__VA_ARGS__)
-#define __SC_LONG3(t3, a3, ...) long a3, __SC_LONG2(__VA_ARGS__)
-#define __SC_LONG4(t4, a4, ...) long a4, __SC_LONG3(__VA_ARGS__)
-#define __SC_LONG5(t5, a5, ...) long a5, __SC_LONG4(__VA_ARGS__)
-#define __SC_LONG6(t6, a6, ...) long a6, __SC_LONG5(__VA_ARGS__)
-
-#define __SC_CAST1(t1, a1)	(t1) a1
-#define __SC_CAST2(t2, a2, ...) (t2) a2, __SC_CAST1(__VA_ARGS__)
-#define __SC_CAST3(t3, a3, ...) (t3) a3, __SC_CAST2(__VA_ARGS__)
-#define __SC_CAST4(t4, a4, ...) (t4) a4, __SC_CAST3(__VA_ARGS__)
-#define __SC_CAST5(t5, a5, ...) (t5) a5, __SC_CAST4(__VA_ARGS__)
-#define __SC_CAST6(t6, a6, ...) (t6) a6, __SC_CAST5(__VA_ARGS__)
-
-#define __SC_TEST(type)		BUILD_BUG_ON(sizeof(type) > sizeof(long))
-#define __SC_TEST1(t1, a1)	__SC_TEST(t1)
-#define __SC_TEST2(t2, a2, ...)	__SC_TEST(t2); __SC_TEST1(__VA_ARGS__)
-#define __SC_TEST3(t3, a3, ...)	__SC_TEST(t3); __SC_TEST2(__VA_ARGS__)
-#define __SC_TEST4(t4, a4, ...)	__SC_TEST(t4); __SC_TEST3(__VA_ARGS__)
-#define __SC_TEST5(t5, a5, ...)	__SC_TEST(t5); __SC_TEST4(__VA_ARGS__)
-#define __SC_TEST6(t6, a6, ...)	__SC_TEST(t6); __SC_TEST5(__VA_ARGS__)
+/*
+ * __MAP - apply a macro to syscall arguments
+ * __MAP(n, m, t1, a1, t2, a2, ..., tn, an) will expand to
+ *    m(t1, a1), m(t2, a2), ..., m(tn, an)
+ * The first argument must be equal to the amount of type/name
+ * pairs given.  Note that this list of pairs (i.e. the arguments
+ * of __MAP starting at the third one) is in the same format as
+ * for SYSCALL_DEFINE<n>/COMPAT_SYSCALL_DEFINE<n>
+ */
+#define __MAP0(m,...)
+#define __MAP1(m,t,a) m(t,a)
+#define __MAP2(m,t,a,...) m(t,a), __MAP1(m,__VA_ARGS__)
+#define __MAP3(m,t,a,...) m(t,a), __MAP2(m,__VA_ARGS__)
+#define __MAP4(m,t,a,...) m(t,a), __MAP3(m,__VA_ARGS__)
+#define __MAP5(m,t,a,...) m(t,a), __MAP4(m,__VA_ARGS__)
+#define __MAP6(m,t,a,...) m(t,a), __MAP5(m,__VA_ARGS__)
+#define __MAP(n,...) __MAP##n(__VA_ARGS__)
+
+#define __SC_DECL(t, a)	t a
+#define __TYPE_IS_LL(t) (__same_type((t)0, 0LL) || __same_type((t)0, 0ULL))
+#define __SC_LONG(t, a) __typeof(__builtin_choose_expr(__TYPE_IS_LL(t), 0LL, 0L)) a
+#define __SC_CAST(t, a)	(t) a
+#define __SC_ARGS(t, a)	a
+#define __SC_TEST(t, a) (void)BUILD_BUG_ON_ZERO(!__TYPE_IS_LL(t) && sizeof(t) > sizeof(long))
 
 #ifdef CONFIG_FTRACE_SYSCALLS
-#define __SC_STR_ADECL1(t, a)		#a
-#define __SC_STR_ADECL2(t, a, ...)	#a, __SC_STR_ADECL1(__VA_ARGS__)
-#define __SC_STR_ADECL3(t, a, ...)	#a, __SC_STR_ADECL2(__VA_ARGS__)
-#define __SC_STR_ADECL4(t, a, ...)	#a, __SC_STR_ADECL3(__VA_ARGS__)
-#define __SC_STR_ADECL5(t, a, ...)	#a, __SC_STR_ADECL4(__VA_ARGS__)
-#define __SC_STR_ADECL6(t, a, ...)	#a, __SC_STR_ADECL5(__VA_ARGS__)
-
-#define __SC_STR_TDECL1(t, a)		#t
-#define __SC_STR_TDECL2(t, a, ...)	#t, __SC_STR_TDECL1(__VA_ARGS__)
-#define __SC_STR_TDECL3(t, a, ...)	#t, __SC_STR_TDECL2(__VA_ARGS__)
-#define __SC_STR_TDECL4(t, a, ...)	#t, __SC_STR_TDECL3(__VA_ARGS__)
-#define __SC_STR_TDECL5(t, a, ...)	#t, __SC_STR_TDECL4(__VA_ARGS__)
-#define __SC_STR_TDECL6(t, a, ...)	#t, __SC_STR_TDECL5(__VA_ARGS__)
+#define __SC_STR_ADECL(t, a)	#a
+#define __SC_STR_TDECL(t, a)	#t
 
 extern struct ftrace_event_class event_class_syscall_enter;
 extern struct ftrace_event_class event_class_syscall_exit;
@@ -155,7 +140,13 @@ extern struct trace_event_functions exit_syscall_print_funcs;
 	  __attribute__((section("_ftrace_events")))			\
 	*__event_exit_##sname = &event_exit_##sname;
 
-#define SYSCALL_METADATA(sname, nb)				\
+#define SYSCALL_METADATA(sname, nb, ...)			\
+	static const char *types_##sname[] = {			\
+		__MAP(nb,__SC_STR_TDECL,__VA_ARGS__)		\
+	};							\
+	static const char *args_##sname[] = {			\
+		__MAP(nb,__SC_STR_ADECL,__VA_ARGS__)		\
+	};							\
 	SYSCALL_TRACE_ENTER_EVENT(sname);			\
 	SYSCALL_TRACE_EXIT_EVENT(sname);			\
 	static struct syscall_metadata __used			\
@@ -163,8 +154,8 @@ extern struct trace_event_functions exit_syscall_print_funcs;
 		.name 		= "sys"#sname,			\
 		.syscall_nr	= -1,	/* Filled in at boot */	\
 		.nb_args 	= nb,				\
-		.types		= types_##sname,		\
-		.args		= args_##sname,			\
+		.types		= nb ? types_##sname : NULL,	\
+		.args		= nb ? args_##sname : NULL,	\
 		.enter_event	= &event_enter_##sname,		\
 		.exit_event	= &event_exit_##sname,		\
 		.enter_fields	= LIST_HEAD_INIT(__syscall_meta_##sname.enter_fields), \
@@ -172,26 +163,13 @@ extern struct trace_event_functions exit_syscall_print_funcs;
 	static struct syscall_metadata __used			\
 	  __attribute__((section("__syscalls_metadata")))	\
 	 *__p_syscall_meta_##sname = &__syscall_meta_##sname;
+#else
+#define SYSCALL_METADATA(sname, nb, ...)
+#endif
 
 #define SYSCALL_DEFINE0(sname)					\
-	SYSCALL_TRACE_ENTER_EVENT(_##sname);			\
-	SYSCALL_TRACE_EXIT_EVENT(_##sname);			\
-	static struct syscall_metadata __used			\
-	  __syscall_meta__##sname = {				\
-		.name 		= "sys_"#sname,			\
-		.syscall_nr	= -1,	/* Filled in at boot */	\
-		.nb_args 	= 0,				\
-		.enter_event	= &event_enter__##sname,	\
-		.exit_event	= &event_exit__##sname,		\
-		.enter_fields	= LIST_HEAD_INIT(__syscall_meta__##sname.enter_fields), \
-	};							\
-	static struct syscall_metadata __used			\
-	  __attribute__((section("__syscalls_metadata")))	\
-	 *__p_syscall_meta_##sname = &__syscall_meta__##sname;	\
+	SYSCALL_METADATA(_##sname, 0);				\
 	asmlinkage long sys_##sname(void)
-#else
-#define SYSCALL_DEFINE0(name)	   asmlinkage long sys_##name(void)
-#endif
 
 #define SYSCALL_DEFINE1(name, ...) SYSCALL_DEFINEx(1, _##name, __VA_ARGS__)
 #define SYSCALL_DEFINE2(name, ...) SYSCALL_DEFINEx(2, _##name, __VA_ARGS__)
@@ -200,57 +178,23 @@ extern struct trace_event_functions exit_syscall_print_funcs;
 #define SYSCALL_DEFINE5(name, ...) SYSCALL_DEFINEx(5, _##name, __VA_ARGS__)
 #define SYSCALL_DEFINE6(name, ...) SYSCALL_DEFINEx(6, _##name, __VA_ARGS__)
 
-#ifdef CONFIG_PPC64
-#define SYSCALL_ALIAS(alias, name)					\
-	asm ("\t.globl " #alias "\n\t.set " #alias ", " #name "\n"	\
-	     "\t.globl ." #alias "\n\t.set ." #alias ", ." #name)
-#else
-#if defined(CONFIG_ALPHA) || defined(CONFIG_MIPS)
-#define SYSCALL_ALIAS(alias, name)					\
-	asm ( #alias " = " #name "\n\t.globl " #alias)
-#else
-#define SYSCALL_ALIAS(alias, name)					\
-	asm ("\t.globl " #alias "\n\t.set " #alias ", " #name)
-#endif
-#endif
-
-#ifdef CONFIG_FTRACE_SYSCALLS
 #define SYSCALL_DEFINEx(x, sname, ...)				\
-	static const char *types_##sname[] = {			\
-		__SC_STR_TDECL##x(__VA_ARGS__)			\
-	};							\
-	static const char *args_##sname[] = {			\
-		__SC_STR_ADECL##x(__VA_ARGS__)			\
-	};							\
-	SYSCALL_METADATA(sname, x);				\
+	SYSCALL_METADATA(sname, x, __VA_ARGS__)			\
 	__SYSCALL_DEFINEx(x, sname, __VA_ARGS__)
-#else
-#define SYSCALL_DEFINEx(x, sname, ...)				\
-	__SYSCALL_DEFINEx(x, sname, __VA_ARGS__)
-#endif
-
-#ifdef CONFIG_HAVE_SYSCALL_WRAPPERS
-
-#define SYSCALL_DEFINE(name) static inline long SYSC_##name
 
+#define __PROTECT(...) asmlinkage_protect(__VA_ARGS__)
 #define __SYSCALL_DEFINEx(x, name, ...)					\
-	asmlinkage long sys##name(__SC_DECL##x(__VA_ARGS__));		\
-	static inline long SYSC##name(__SC_DECL##x(__VA_ARGS__));	\
-	asmlinkage long SyS##name(__SC_LONG##x(__VA_ARGS__))		\
+	asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));	\
+	static inline long SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__));	\
+	asmlinkage long SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__))	\
 	{								\
-		__SC_TEST##x(__VA_ARGS__);				\
-		return (long) SYSC##name(__SC_CAST##x(__VA_ARGS__));	\
+		long ret = SYSC##name(__MAP(x,__SC_CAST,__VA_ARGS__));	\
+		__MAP(x,__SC_TEST,__VA_ARGS__);				\
+		__PROTECT(x, ret,__MAP(x,__SC_ARGS,__VA_ARGS__));	\
+		return ret;						\
 	}								\
 	SYSCALL_ALIAS(sys##name, SyS##name);				\
-	static inline long SYSC##name(__SC_DECL##x(__VA_ARGS__))
-
-#else /* CONFIG_HAVE_SYSCALL_WRAPPERS */
-
-#define SYSCALL_DEFINE(name) asmlinkage long sys_##name
-#define __SYSCALL_DEFINEx(x, name, ...)					\
-	asmlinkage long sys##name(__SC_DECL##x(__VA_ARGS__))
-
-#endif /* CONFIG_HAVE_SYSCALL_WRAPPERS */
+	static inline long SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__))
 
 asmlinkage long sys_time(time_t __user *tloc);
 asmlinkage long sys_stime(time_t __user *tptr);
@@ -694,7 +638,7 @@ asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf);
 asmlinkage long sys_semget(key_t key, int nsems, int semflg);
 asmlinkage long sys_semop(int semid, struct sembuf __user *sops,
 				unsigned nsops);
-asmlinkage long sys_semctl(int semid, int semnum, int cmd, union semun arg);
+asmlinkage long sys_semctl(int semid, int semnum, int cmd, unsigned long arg);
 asmlinkage long sys_semtimedop(int semid, struct sembuf __user *sops,
 				unsigned nsops,
 				const struct timespec __user *timeout);
diff --git a/include/linux/tcp.h b/include/linux/tcp.h
index f28408c..5adbc33 100644
--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -90,9 +90,6 @@ struct tcp_options_received {
 		sack_ok : 4,	/* SACK seen on SYN packet		*/
 		snd_wscale : 4,	/* Window scaling received from sender	*/
 		rcv_wscale : 4;	/* Window scaling to send to receiver	*/
-	u8	cookie_plus:6,	/* bytes in authenticator/cookie option	*/
-		cookie_out_never:1,
-		cookie_in_always:1;
 	u8	num_sacks;	/* Number of SACK blocks		*/
 	u16	user_mss;	/* mss requested by user in ioctl	*/
 	u16	mss_clamp;	/* Maximal mss, negotiated at connection setup */
@@ -102,7 +99,6 @@ static inline void tcp_clear_options(struct tcp_options_received *rx_opt)
 {
 	rx_opt->tstamp_ok = rx_opt->sack_ok = 0;
 	rx_opt->wscale_ok = rx_opt->snd_wscale = 0;
-	rx_opt->cookie_plus = 0;
 }
 
 /* This is the max number of SACKS that we'll generate and process. It's safe
@@ -191,20 +187,19 @@ struct tcp_sock {
 	u32	window_clamp;	/* Maximal window to advertise		*/
 	u32	rcv_ssthresh;	/* Current window clamp			*/
 
-	u32	frto_highmark;	/* snd_nxt when RTO occurred */
 	u16	advmss;		/* Advertised MSS			*/
-	u8	frto_counter;	/* Number of new acks after RTO */
+	u8	unused;
 	u8	nonagle     : 4,/* Disable Nagle algorithm?             */
 		thin_lto    : 1,/* Use linear timeouts for thin streams */
 		thin_dupack : 1,/* Fast retransmit on first dupack      */
 		repair      : 1,
-		unused      : 1;
+		frto        : 1;/* F-RTO (RFC5682) activated in CA_Loss */
 	u8	repair_queue;
 	u8	do_early_retrans:1,/* Enable RFC5827 early-retransmit  */
-		early_retrans_delayed:1, /* Delayed ER timer installed */
 		syn_data:1,	/* SYN includes data */
 		syn_fastopen:1,	/* SYN includes Fast Open option */
 		syn_data_acked:1;/* data in SYN is acked by SYN-ACK */
+	u32	tlp_high_seq;	/* snd_nxt at the time of TLP retransmit. */
 
 /* RTT measurement */
 	u32	srtt;		/* smoothed round trip time << 3	*/
@@ -320,12 +315,6 @@ struct tcp_sock {
 	struct tcp_md5sig_info	__rcu *md5sig_info;
 #endif
 
-	/* When the cookie options are generated and exchanged, then this
-	 * object holds a reference to them (cookie_values->kref).  Also
-	 * contains related tcp_cookie_transactions fields.
-	 */
-	struct tcp_cookie_values  *cookie_values;
-
 /* TCP fastopen related information */
 	struct tcp_fastopen_request *fastopen_req;
 	/* fastopen_rsk points to request_sock that resulted in this big
@@ -361,10 +350,6 @@ struct tcp_timewait_sock {
 #ifdef CONFIG_TCP_MD5SIG
 	struct tcp_md5sig_key	  *tw_md5_key;
 #endif
-	/* Few sockets in timewait have cookies; in that case, then this
-	 * object holds a reference to them (tw_cookie_values->kref).
-	 */
-	struct tcp_cookie_values  *tw_cookie_values;
 };
 
 static inline struct tcp_timewait_sock *tcp_twsk(const struct sock *sk)
diff --git a/include/linux/tegra-powergate.h b/include/linux/tegra-powergate.h
new file mode 100644
index 0000000..55c29a8
--- /dev/null
+++ b/include/linux/tegra-powergate.h
@@ -0,0 +1,49 @@
+/*
+ * 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_TEGRA_POWERGATE_H_
+#define _MACH_TEGRA_POWERGATE_H_
+
+struct clk;
+
+#define TEGRA_POWERGATE_CPU	0
+#define TEGRA_POWERGATE_3D	1
+#define TEGRA_POWERGATE_VENC	2
+#define TEGRA_POWERGATE_PCIE	3
+#define TEGRA_POWERGATE_VDEC	4
+#define TEGRA_POWERGATE_L2	5
+#define TEGRA_POWERGATE_MPE	6
+#define TEGRA_POWERGATE_HEG	7
+#define TEGRA_POWERGATE_SATA	8
+#define TEGRA_POWERGATE_CPU1	9
+#define TEGRA_POWERGATE_CPU2	10
+#define TEGRA_POWERGATE_CPU3	11
+#define TEGRA_POWERGATE_CELP	12
+#define TEGRA_POWERGATE_3D1	13
+
+#define TEGRA_POWERGATE_CPU0	TEGRA_POWERGATE_CPU
+#define TEGRA_POWERGATE_3D0	TEGRA_POWERGATE_3D
+
+int tegra_powergate_is_powered(int id);
+int tegra_powergate_power_on(int id);
+int tegra_powergate_power_off(int id);
+int tegra_powergate_remove_clamping(int id);
+
+/* Must be called with clk disabled, and returns with clk enabled */
+int tegra_powergate_sequence_power_up(int id, struct clk *clk);
+
+#endif /* _MACH_TEGRA_POWERGATE_H_ */
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index e3c0ae9..cf919a4 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -251,7 +251,7 @@ void thermal_unregister_governor(struct thermal_governor *);
 extern int thermal_generate_netlink_event(struct thermal_zone_device *tz,
 						enum events event);
 #else
-static int thermal_generate_netlink_event(struct thermal_zone_device *tz,
+static inline int thermal_generate_netlink_event(struct thermal_zone_device *tz,
 						enum events event)
 {
 	return 0;
diff --git a/include/linux/timeriomem-rng.h b/include/linux/timeriomem-rng.h
index 3e08a1c..46eb27d 100644
--- a/include/linux/timeriomem-rng.h
+++ b/include/linux/timeriomem-rng.h
@@ -8,12 +8,7 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/completion.h>
-
 struct timeriomem_rng_data {
-	struct completion	completion;
-	unsigned int		present:1;
-
 	void __iomem		*address;
 
 	/* measures in usecs */
diff --git a/include/linux/trace_clock.h b/include/linux/trace_clock.h
index d563f37..1d7ca27 100644
--- a/include/linux/trace_clock.h
+++ b/include/linux/trace_clock.h
@@ -16,6 +16,7 @@
 
 extern u64 notrace trace_clock_local(void);
 extern u64 notrace trace_clock(void);
+extern u64 notrace trace_clock_jiffies(void);
 extern u64 notrace trace_clock_global(void);
 extern u64 notrace trace_clock_counter(void);
 
diff --git a/include/linux/tty.h b/include/linux/tty.h
index c75d886..367a9df 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -255,9 +255,9 @@ struct tty_struct {
 	int count;
 	struct winsize winsize;		/* termios mutex */
 	unsigned char stopped:1, hw_stopped:1, flow_stopped:1, packet:1;
-	unsigned char warned:1;
 	unsigned char ctrl_status;	/* ctrl_lock */
 	unsigned int receive_room;	/* Bytes free for queue */
+	int flow_change;
 
 	struct tty_struct *link;
 	struct fasync_struct *fasync;
@@ -315,9 +315,25 @@ struct tty_file_private {
 #define TTY_NO_WRITE_SPLIT 	17	/* Preserve write boundaries to driver */
 #define TTY_HUPPED 		18	/* Post driver->hangup() */
 #define TTY_HUPPING 		21	/* ->hangup() in progress */
+#define TTY_LDISC_HALTED	22	/* Line discipline is halted */
 
 #define TTY_WRITE_FLUSH(tty) tty_write_flush((tty))
 
+/* Values for tty->flow_change */
+#define TTY_THROTTLE_SAFE 1
+#define TTY_UNTHROTTLE_SAFE 2
+
+static inline void __tty_set_flow_change(struct tty_struct *tty, int val)
+{
+	tty->flow_change = val;
+}
+
+static inline void tty_set_flow_change(struct tty_struct *tty, int val)
+{
+	tty->flow_change = val;
+	smp_mb();
+}
+
 #ifdef CONFIG_TTY
 extern void console_init(void);
 extern void tty_kref_put(struct tty_struct *tty);
@@ -400,6 +416,8 @@ extern int tty_write_room(struct tty_struct *tty);
 extern void tty_driver_flush_buffer(struct tty_struct *tty);
 extern void tty_throttle(struct tty_struct *tty);
 extern void tty_unthrottle(struct tty_struct *tty);
+extern int tty_throttle_safe(struct tty_struct *tty);
+extern int tty_unthrottle_safe(struct tty_struct *tty);
 extern int tty_do_resize(struct tty_struct *tty, struct winsize *ws);
 extern void tty_driver_remove_tty(struct tty_driver *driver,
 				  struct tty_struct *tty);
@@ -419,13 +437,28 @@ extern void tty_flush_to_ldisc(struct tty_struct *tty);
 extern void tty_buffer_free_all(struct tty_port *port);
 extern void tty_buffer_flush(struct tty_struct *tty);
 extern void tty_buffer_init(struct tty_port *port);
-extern speed_t tty_get_baud_rate(struct tty_struct *tty);
 extern speed_t tty_termios_baud_rate(struct ktermios *termios);
 extern speed_t tty_termios_input_baud_rate(struct ktermios *termios);
 extern void tty_termios_encode_baud_rate(struct ktermios *termios,
 						speed_t ibaud, speed_t obaud);
 extern void tty_encode_baud_rate(struct tty_struct *tty,
 						speed_t ibaud, speed_t obaud);
+
+/**
+ *	tty_get_baud_rate	-	get tty bit rates
+ *	@tty: tty to query
+ *
+ *	Returns the baud rate as an integer for this terminal. The
+ *	termios lock must be held by the caller and the terminal bit
+ *	flags may be updated.
+ *
+ *	Locking: none
+ */
+static inline speed_t tty_get_baud_rate(struct tty_struct *tty)
+{
+	return tty_termios_baud_rate(&tty->termios);
+}
+
 extern void tty_termios_copy_hw(struct ktermios *new, struct ktermios *old);
 extern int tty_termios_hw_change(struct ktermios *a, struct ktermios *b);
 extern int tty_set_termios(struct tty_struct *tty, struct ktermios *kt);
@@ -502,6 +535,8 @@ extern int tty_port_carrier_raised(struct tty_port *port);
 extern void tty_port_raise_dtr_rts(struct tty_port *port);
 extern void tty_port_lower_dtr_rts(struct tty_port *port);
 extern void tty_port_hangup(struct tty_port *port);
+extern void tty_port_tty_hangup(struct tty_port *port, bool check_clocal);
+extern void tty_port_tty_wakeup(struct tty_port *port);
 extern int tty_port_block_til_ready(struct tty_port *port,
 				struct tty_struct *tty, struct file *filp);
 extern int tty_port_close_start(struct tty_port *port,
@@ -526,8 +561,6 @@ extern void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty);
 extern void tty_ldisc_init(struct tty_struct *tty);
 extern void tty_ldisc_deinit(struct tty_struct *tty);
 extern void tty_ldisc_begin(void);
-/* This last one is just for the tty layer internals and shouldn't be used elsewhere */
-extern void tty_ldisc_enable(struct tty_struct *tty);
 
 
 /* n_tty.c */
diff --git a/include/linux/tty_ldisc.h b/include/linux/tty_ldisc.h
index 455a0d7..58390c7 100644
--- a/include/linux/tty_ldisc.h
+++ b/include/linux/tty_ldisc.h
@@ -9,89 +9,89 @@
  *
  * int	(*open)(struct tty_struct *);
  *
- * 	This function is called when the line discipline is associated
- * 	with the tty.  The line discipline can use this as an
- * 	opportunity to initialize any state needed by the ldisc routines.
- * 
+ *	This function is called when the line discipline is associated
+ *	with the tty.  The line discipline can use this as an
+ *	opportunity to initialize any state needed by the ldisc routines.
+ *
  * void	(*close)(struct tty_struct *);
  *
  *	This function is called when the line discipline is being
- * 	shutdown, either because the tty is being closed or because
- * 	the tty is being changed to use a new line discipline
- * 
+ *	shutdown, either because the tty is being closed or because
+ *	the tty is being changed to use a new line discipline
+ *
  * void	(*flush_buffer)(struct tty_struct *tty);
  *
- * 	This function instructs the line discipline to clear its
- * 	buffers of any input characters it may have queued to be
- * 	delivered to the user mode process.
- * 
+ *	This function instructs the line discipline to clear its
+ *	buffers of any input characters it may have queued to be
+ *	delivered to the user mode process.
+ *
  * ssize_t (*chars_in_buffer)(struct tty_struct *tty);
  *
- * 	This function returns the number of input characters the line
+ *	This function returns the number of input characters the line
  *	discipline may have queued up to be delivered to the user mode
  *	process.
- * 
+ *
  * ssize_t (*read)(struct tty_struct * tty, struct file * file,
  *		   unsigned char * buf, size_t nr);
  *
- * 	This function is called when the user requests to read from
- * 	the tty.  The line discipline will return whatever characters
- * 	it has buffered up for the user.  If this function is not
- * 	defined, the user will receive an EIO error.
- * 
+ *	This function is called when the user requests to read from
+ *	the tty.  The line discipline will return whatever characters
+ *	it has buffered up for the user.  If this function is not
+ *	defined, the user will receive an EIO error.
+ *
  * ssize_t (*write)(struct tty_struct * tty, struct file * file,
- * 		    const unsigned char * buf, size_t nr);
- *
- * 	This function is called when the user requests to write to the
- * 	tty.  The line discipline will deliver the characters to the
- * 	low-level tty device for transmission, optionally performing
- * 	some processing on the characters first.  If this function is
- * 	not defined, the user will receive an EIO error.
- * 
+ *		    const unsigned char * buf, size_t nr);
+ *
+ *	This function is called when the user requests to write to the
+ *	tty.  The line discipline will deliver the characters to the
+ *	low-level tty device for transmission, optionally performing
+ *	some processing on the characters first.  If this function is
+ *	not defined, the user will receive an EIO error.
+ *
  * int	(*ioctl)(struct tty_struct * tty, struct file * file,
- * 		 unsigned int cmd, unsigned long arg);
+ *		 unsigned int cmd, unsigned long arg);
  *
  *	This function is called when the user requests an ioctl which
- * 	is not handled by the tty layer or the low-level tty driver.
- * 	It is intended for ioctls which affect line discpline
- * 	operation.  Note that the search order for ioctls is (1) tty
- * 	layer, (2) tty low-level driver, (3) line discpline.  So a
- * 	low-level driver can "grab" an ioctl request before the line
- * 	discpline has a chance to see it.
- * 
+ *	is not handled by the tty layer or the low-level tty driver.
+ *	It is intended for ioctls which affect line discpline
+ *	operation.  Note that the search order for ioctls is (1) tty
+ *	layer, (2) tty low-level driver, (3) line discpline.  So a
+ *	low-level driver can "grab" an ioctl request before the line
+ *	discpline has a chance to see it.
+ *
  * long	(*compat_ioctl)(struct tty_struct * tty, struct file * file,
- * 		        unsigned int cmd, unsigned long arg);
+ *		        unsigned int cmd, unsigned long arg);
  *
- *      Process ioctl calls from 32-bit process on 64-bit system
+ *	Process ioctl calls from 32-bit process on 64-bit system
  *
  * void	(*set_termios)(struct tty_struct *tty, struct ktermios * old);
  *
- * 	This function notifies the line discpline that a change has
- * 	been made to the termios structure.
- * 
+ *	This function notifies the line discpline that a change has
+ *	been made to the termios structure.
+ *
  * int	(*poll)(struct tty_struct * tty, struct file * file,
- * 		  poll_table *wait);
+ *		  poll_table *wait);
  *
- * 	This function is called when a user attempts to select/poll on a
- * 	tty device.  It is solely the responsibility of the line
- * 	discipline to handle poll requests.
+ *	This function is called when a user attempts to select/poll on a
+ *	tty device.  It is solely the responsibility of the line
+ *	discipline to handle poll requests.
  *
  * void	(*receive_buf)(struct tty_struct *, const unsigned char *cp,
- * 		       char *fp, int count);
- *
- * 	This function is called by the low-level tty driver to send
- * 	characters received by the hardware to the line discpline for
- * 	processing.  <cp> is a pointer to the buffer of input
- * 	character received by the device.  <fp> is a pointer to a
- * 	pointer of flag bytes which indicate whether a character was
- * 	received with a parity error, etc.
- * 
+ *		       char *fp, int count);
+ *
+ *	This function is called by the low-level tty driver to send
+ *	characters received by the hardware to the line discpline for
+ *	processing.  <cp> is a pointer to the buffer of input
+ *	character received by the device.  <fp> is a pointer to a
+ *	pointer of flag bytes which indicate whether a character was
+ *	received with a parity error, etc.
+ *
  * void	(*write_wakeup)(struct tty_struct *);
  *
- * 	This function is called by the low-level tty driver to signal
- * 	that line discpline should try to send more characters to the
- * 	low-level driver for transmission.  If the line discpline does
- * 	not have any more data to send, it can just return.
+ *	This function is called by the low-level tty driver to signal
+ *	that line discpline should try to send more characters to the
+ *	low-level driver for transmission.  If the line discpline does
+ *	not have any more data to send, it can just return.
  *
  * int (*hangup)(struct tty_struct *)
  *
@@ -115,7 +115,7 @@ struct tty_ldisc_ops {
 	char	*name;
 	int	num;
 	int	flags;
-	
+
 	/*
 	 * The following routines are called from above.
 	 */
@@ -123,19 +123,19 @@ struct tty_ldisc_ops {
 	void	(*close)(struct tty_struct *);
 	void	(*flush_buffer)(struct tty_struct *tty);
 	ssize_t	(*chars_in_buffer)(struct tty_struct *tty);
-	ssize_t	(*read)(struct tty_struct * tty, struct file * file,
-			unsigned char __user * buf, size_t nr);
-	ssize_t	(*write)(struct tty_struct * tty, struct file * file,
-			 const unsigned char * buf, size_t nr);	
-	int	(*ioctl)(struct tty_struct * tty, struct file * file,
+	ssize_t	(*read)(struct tty_struct *tty, struct file *file,
+			unsigned char __user *buf, size_t nr);
+	ssize_t	(*write)(struct tty_struct *tty, struct file *file,
+			 const unsigned char *buf, size_t nr);
+	int	(*ioctl)(struct tty_struct *tty, struct file *file,
 			 unsigned int cmd, unsigned long arg);
-	long	(*compat_ioctl)(struct tty_struct * tty, struct file * file,
+	long	(*compat_ioctl)(struct tty_struct *tty, struct file *file,
 				unsigned int cmd, unsigned long arg);
-	void	(*set_termios)(struct tty_struct *tty, struct ktermios * old);
+	void	(*set_termios)(struct tty_struct *tty, struct ktermios *old);
 	unsigned int (*poll)(struct tty_struct *, struct file *,
 			     struct poll_table_struct *);
 	int	(*hangup)(struct tty_struct *tty);
-	
+
 	/*
 	 * The following routines are called from below.
 	 */
@@ -145,7 +145,7 @@ struct tty_ldisc_ops {
 	void	(*dcd_change)(struct tty_struct *, unsigned int);
 
 	struct  module *owner;
-	
+
 	int refcount;
 };
 
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 4d22d0f..a0bee5a 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -469,14 +469,12 @@ struct usb3_lpm_parameters {
  * @lpm_capable: device supports LPM
  * @usb2_hw_lpm_capable: device can perform USB2 hardware LPM
  * @usb2_hw_lpm_enabled: USB2 hardware LPM enabled
+ * @usb3_lpm_enabled: USB3 hardware LPM enabled
  * @string_langid: language ID for strings
  * @product: iProduct string, if present (static)
  * @manufacturer: iManufacturer string, if present (static)
  * @serial: iSerialNumber string, if present (static)
  * @filelist: usbfs files that are open to this device
- * @usb_classdev: USB class device that was created for usbfs device
- *	access from userspace
- * @usbfs_dentry: usbfs dentry entry for the device
  * @maxchild: number of ports if hub
  * @quirks: quirks of the whole device
  * @urbnum: number of URBs submitted for the whole device
@@ -619,7 +617,7 @@ static inline bool usb_acpi_power_manageable(struct usb_device *hdev, int index)
 #endif
 
 /* USB autosuspend and autoresume */
-#ifdef CONFIG_USB_SUSPEND
+#ifdef CONFIG_PM_RUNTIME
 extern void usb_enable_autosuspend(struct usb_device *udev);
 extern void usb_disable_autosuspend(struct usb_device *udev);
 
@@ -978,7 +976,12 @@ struct usbdrv_wrap {
  *	the "usbfs" filesystem.  This lets devices provide ways to
  *	expose information to user space regardless of where they
  *	do (or don't) show up otherwise in the filesystem.
- * @suspend: Called when the device is going to be suspended by the system.
+ * @suspend: Called when the device is going to be suspended by the
+ *	system either from system sleep or runtime suspend context. The
+ *	return value will be ignored in system sleep context, so do NOT
+ *	try to continue using the device if suspend fails in this case.
+ *	Instead, let the resume or reset-resume routine recover from
+ *	the failure.
  * @resume: Called when the device is being resumed by the system.
  * @reset_resume: Called when the suspended device has been reset instead
  *	of being resumed.
diff --git a/include/linux/usb/audio-v2.h b/include/linux/usb/audio-v2.h
index ed13053..c5f2158 100644
--- a/include/linux/usb/audio-v2.h
+++ b/include/linux/usb/audio-v2.h
@@ -170,6 +170,8 @@ struct uac2_as_header_descriptor {
 	__u8 iChannelNames;
 } __attribute__((packed));
 
+#define UAC2_FORMAT_TYPE_I_RAW_DATA	(1 << 31)
+
 /* 4.10.1.2 Class-Specific AS Isochronous Audio Data Endpoint Descriptor */
 
 struct uac2_iso_endpoint_descriptor {
diff --git a/include/linux/usb/cdc-wdm.h b/include/linux/usb/cdc-wdm.h
index 719c332..0b3f429 100644
--- a/include/linux/usb/cdc-wdm.h
+++ b/include/linux/usb/cdc-wdm.h
@@ -11,6 +11,8 @@
 #ifndef __LINUX_USB_CDC_WDM_H
 #define __LINUX_USB_CDC_WDM_H
 
+#include <uapi/linux/usb/cdc-wdm.h>
+
 extern struct usb_driver *usb_cdc_wdm_register(struct usb_interface *intf,
 					struct usb_endpoint_descriptor *ep,
 					int bufsize,
diff --git a/include/linux/usb/ch9.h b/include/linux/usb/ch9.h
index 9c210f2..27603bc 100644
--- a/include/linux/usb/ch9.h
+++ b/include/linux/usb/ch9.h
@@ -43,4 +43,13 @@
  */
 extern const char *usb_speed_string(enum usb_device_speed speed);
 
+
+/**
+ * usb_state_string - Returns human readable name for the state.
+ * @state: The state to return a human-readable name for. If it's not
+ *	any of the states devices in usb_device_state_string enum,
+ *	the string UNKNOWN will be returned.
+ */
+extern const char *usb_state_string(enum usb_device_state state);
+
 #endif /* __LINUX_USB_CH9_H */
diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h
index 8860594..5e61589 100644
--- a/include/linux/usb/composite.h
+++ b/include/linux/usb/composite.h
@@ -39,6 +39,7 @@
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
 #include <linux/log2.h>
+#include <linux/configfs.h>
 
 /*
  * USB function drivers should return USB_GADGET_DELAYED_STATUS if they
@@ -464,6 +465,8 @@ struct usb_function_driver {
 };
 
 struct usb_function_instance {
+	struct config_group group;
+	struct list_head cfs_list;
 	struct usb_function_driver *fd;
 	void (*free_func_inst)(struct usb_function_instance *inst);
 };
diff --git a/include/linux/usb/dwc3-omap.h b/include/linux/usb/dwc3-omap.h
index 51eae14..5615f4d 100644
--- a/include/linux/usb/dwc3-omap.h
+++ b/include/linux/usb/dwc3-omap.h
@@ -19,11 +19,11 @@ enum omap_dwc3_vbus_id_status {
 };
 
 #if (defined(CONFIG_USB_DWC3) || defined(CONFIG_USB_DWC3_MODULE))
-extern void dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status);
+extern int dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status);
 #else
-static inline void dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status)
+static inline int dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status)
 {
-	return;
+	return -ENODEV;
 }
 #endif
 
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index 2e297e8..c454a88 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -482,6 +482,7 @@ struct usb_gadget_ops {
  * @speed: Speed of current connection to USB host.
  * @max_speed: Maximal speed the UDC can handle.  UDC must support this
  *      and all slower speeds.
+ * @state: the state we are now (attached, suspended, configured, etc)
  * @sg_supported: true if we can handle scatter-gather
  * @is_otg: True if the USB device port uses a Mini-AB jack, so that the
  *	gadget driver must provide a USB OTG descriptor.
@@ -525,6 +526,7 @@ struct usb_gadget {
 	struct list_head		ep_list;	/* of usb_ep */
 	enum usb_device_speed		speed;
 	enum usb_device_speed		max_speed;
+	enum usb_device_state		state;
 	unsigned			sg_supported:1;
 	unsigned			is_otg:1;
 	unsigned			is_a_peripheral:1;
@@ -872,6 +874,8 @@ 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_release(struct device *parent,
+		struct usb_gadget *gadget, void (*release)(struct device *dev));
 extern int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget);
 extern void usb_del_gadget_udc(struct usb_gadget *gadget);
 extern int udc_attach_driver(const char *name,
@@ -959,6 +963,13 @@ extern void usb_gadget_unmap_request(struct usb_gadget *gadget,
 
 /*-------------------------------------------------------------------------*/
 
+/* utility to set gadget state properly */
+
+extern void usb_gadget_set_state(struct usb_gadget *gadget,
+		enum usb_device_state state);
+
+/*-------------------------------------------------------------------------*/
+
 /* utility wrapping a simple endpoint selection policy */
 
 extern struct usb_ep *usb_ep_autoconfig(struct usb_gadget *,
diff --git a/include/linux/usb/gadget_configfs.h b/include/linux/usb/gadget_configfs.h
new file mode 100644
index 0000000..d74c0ae
--- /dev/null
+++ b/include/linux/usb/gadget_configfs.h
@@ -0,0 +1,110 @@
+#ifndef __GADGET_CONFIGFS__
+#define __GADGET_CONFIGFS__
+
+#include <linux/configfs.h>
+
+int check_user_usb_string(const char *name,
+		struct usb_gadget_strings *stringtab_dev);
+
+#define GS_STRINGS_W(__struct, __name)	\
+	static ssize_t __struct##_##__name##_store(struct __struct *gs, \
+		const char *page, size_t len)		\
+{							\
+	int ret;					\
+							\
+	ret = usb_string_copy(page, &gs->__name);	\
+	if (ret)					\
+		return ret;				\
+	return len;					\
+}
+
+#define GS_STRINGS_R(__struct, __name)	\
+	static ssize_t __struct##_##__name##_show(struct __struct *gs, \
+			char *page)	\
+{	\
+	return sprintf(page, "%s\n", gs->__name ?: "");	\
+}
+
+#define GS_STRING_ITEM_ATTR(struct_name, name)	\
+	static struct struct_name##_attribute struct_name##_##name = \
+		__CONFIGFS_ATTR(name,  S_IRUGO | S_IWUSR,		\
+				struct_name##_##name##_show,		\
+				struct_name##_##name##_store)
+
+#define GS_STRINGS_RW(struct_name, _name)	\
+	GS_STRINGS_R(struct_name, _name)	\
+	GS_STRINGS_W(struct_name, _name)	\
+	GS_STRING_ITEM_ATTR(struct_name, _name)
+
+#define USB_CONFIG_STRING_RW_OPS(struct_in)				\
+	CONFIGFS_ATTR_OPS(struct_in);					\
+									\
+static struct configfs_item_operations struct_in##_langid_item_ops = {	\
+	.release                = struct_in##_attr_release,		\
+	.show_attribute         = struct_in##_attr_show,		\
+	.store_attribute        = struct_in##_attr_store,		\
+};									\
+									\
+static struct config_item_type struct_in##_langid_type = {		\
+	.ct_item_ops	= &struct_in##_langid_item_ops,			\
+	.ct_attrs	= struct_in##_langid_attrs,			\
+	.ct_owner	= THIS_MODULE,					\
+}
+
+#define USB_CONFIG_STRINGS_LANG(struct_in, struct_member)	\
+	static struct config_group *struct_in##_strings_make(		\
+			struct config_group *group,			\
+			const char *name)				\
+	{								\
+	struct struct_member *gi;					\
+	struct struct_in *gs;						\
+	struct struct_in *new;						\
+	int langs = 0;							\
+	int ret;							\
+									\
+	new = kzalloc(sizeof(*new), GFP_KERNEL);			\
+	if (!new)							\
+		return ERR_PTR(-ENOMEM);				\
+									\
+	ret = check_user_usb_string(name, &new->stringtab_dev);		\
+	if (ret)							\
+		goto err;						\
+	config_group_init_type_name(&new->group, name,			\
+			&struct_in##_langid_type);			\
+									\
+	gi = container_of(group, struct struct_member, strings_group);	\
+	ret = -EEXIST;							\
+	list_for_each_entry(gs, &gi->string_list, list) {		\
+		if (gs->stringtab_dev.language == new->stringtab_dev.language) \
+			goto err;					\
+		langs++;						\
+	}								\
+	ret = -EOVERFLOW;						\
+	if (langs >= MAX_USB_STRING_LANGS)				\
+		goto err;						\
+									\
+	list_add_tail(&new->list, &gi->string_list);			\
+	return &new->group;						\
+err:									\
+	kfree(new);							\
+	return ERR_PTR(ret);						\
+}									\
+									\
+static void struct_in##_strings_drop(					\
+		struct config_group *group,				\
+		struct config_item *item)				\
+{									\
+	config_item_put(item);						\
+}									\
+									\
+static struct configfs_group_operations struct_in##_strings_ops = {	\
+	.make_group     = &struct_in##_strings_make,			\
+	.drop_item      = &struct_in##_strings_drop,			\
+};									\
+									\
+static struct config_item_type struct_in##_strings_type = {		\
+	.ct_group_ops   = &struct_in##_strings_ops,			\
+	.ct_owner       = THIS_MODULE,					\
+}
+
+#endif
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
index 59694b5..f5f5c7d 100644
--- a/include/linux/usb/hcd.h
+++ b/include/linux/usb/hcd.h
@@ -84,7 +84,7 @@ struct usb_hcd {
 
 	struct timer_list	rh_timer;	/* drives root-hub polling */
 	struct urb		*status_urb;	/* the current status urb */
-#ifdef CONFIG_USB_SUSPEND
+#ifdef CONFIG_PM_RUNTIME
 	struct work_struct	wakeup_work;	/* for remote wakeup */
 #endif
 
@@ -593,14 +593,14 @@ extern int hcd_bus_suspend(struct usb_device *rhdev, pm_message_t msg);
 extern int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg);
 #endif /* CONFIG_PM */
 
-#ifdef CONFIG_USB_SUSPEND
+#ifdef CONFIG_PM_RUNTIME
 extern void usb_hcd_resume_root_hub(struct usb_hcd *hcd);
 #else
 static inline void usb_hcd_resume_root_hub(struct usb_hcd *hcd)
 {
 	return;
 }
-#endif /* CONFIG_USB_SUSPEND */
+#endif /* CONFIG_PM_RUNTIME */
 
 /*-------------------------------------------------------------------------*/
 
diff --git a/include/linux/usb/musb-ux500.h b/include/linux/usb/musb-ux500.h
new file mode 100644
index 0000000..1e2c713
--- /dev/null
+++ b/include/linux/usb/musb-ux500.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2013 ST-Ericsson 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.
+ */
+
+#ifndef __MUSB_UX500_H__
+#define __MUSB_UX500_H__
+
+enum ux500_musb_vbus_id_status {
+	UX500_MUSB_NONE = 0,
+	UX500_MUSB_VBUS,
+	UX500_MUSB_ID,
+	UX500_MUSB_CHARGER,
+	UX500_MUSB_ENUMERATED,
+	UX500_MUSB_RIDA,
+	UX500_MUSB_RIDB,
+	UX500_MUSB_RIDC,
+	UX500_MUSB_PREPARE,
+	UX500_MUSB_CLEAN,
+};
+
+#endif	/* __MUSB_UX500_H__ */
diff --git a/include/linux/usb/nop-usb-xceiv.h b/include/linux/usb/nop-usb-xceiv.h
index 28884c7..148d351 100644
--- a/include/linux/usb/nop-usb-xceiv.h
+++ b/include/linux/usb/nop-usb-xceiv.h
@@ -5,6 +5,11 @@
 
 struct nop_usb_xceiv_platform_data {
 	enum usb_phy_type type;
+	unsigned long clk_rate;
+
+	/* if set fails with -EPROBE_DEFER if can't get regulator */
+	unsigned int needs_vcc:1;
+	unsigned int needs_reset:1;
 };
 
 #if defined(CONFIG_NOP_USB_XCEIV) || (defined(CONFIG_NOP_USB_XCEIV_MODULE) && defined(MODULE))
diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h
index e8a5fe8..291e01b 100644
--- a/include/linux/usb/otg.h
+++ b/include/linux/usb/otg.h
@@ -36,14 +36,7 @@ struct usb_otg {
 
 };
 
-#ifdef CONFIG_USB_OTG_UTILS
-extern const char *otg_state_string(enum usb_otg_state state);
-#else
-static inline const char *otg_state_string(enum usb_otg_state state)
-{
-	return NULL;
-}
-#endif
+extern const char *usb_otg_state_string(enum usb_otg_state state);
 
 /* Context: can sleep */
 static inline int
diff --git a/include/linux/usb/phy.h b/include/linux/usb/phy.h
index 15847cb..6b5978f 100644
--- a/include/linux/usb/phy.h
+++ b/include/linux/usb/phy.h
@@ -91,6 +91,9 @@ struct usb_phy {
 	int	(*init)(struct usb_phy *x);
 	void	(*shutdown)(struct usb_phy *x);
 
+	/* enable/disable VBUS */
+	int	(*set_vbus)(struct usb_phy *x, int on);
+
 	/* effective for B devices, ignored for A-peripheral */
 	int	(*set_power)(struct usb_phy *x,
 				unsigned mA);
@@ -160,8 +163,26 @@ usb_phy_shutdown(struct usb_phy *x)
 		x->shutdown(x);
 }
 
+static inline int
+usb_phy_vbus_on(struct usb_phy *x)
+{
+	if (!x->set_vbus)
+		return 0;
+
+	return x->set_vbus(x, true);
+}
+
+static inline int
+usb_phy_vbus_off(struct usb_phy *x)
+{
+	if (!x->set_vbus)
+		return 0;
+
+	return x->set_vbus(x, false);
+}
+
 /* for usb host and peripheral controller drivers */
-#ifdef CONFIG_USB_OTG_UTILS
+#if IS_ENABLED(CONFIG_USB_PHY)
 extern struct usb_phy *usb_get_phy(enum usb_phy_type type);
 extern struct usb_phy *devm_usb_get_phy(struct device *dev,
 	enum usb_phy_type type);
@@ -176,29 +197,29 @@ extern int usb_bind_phy(const char *dev_name, u8 index,
 #else
 static inline struct usb_phy *usb_get_phy(enum usb_phy_type type)
 {
-	return NULL;
+	return ERR_PTR(-ENXIO);
 }
 
 static inline struct usb_phy *devm_usb_get_phy(struct device *dev,
 	enum usb_phy_type type)
 {
-	return NULL;
+	return ERR_PTR(-ENXIO);
 }
 
 static inline struct usb_phy *usb_get_phy_dev(struct device *dev, u8 index)
 {
-	return NULL;
+	return ERR_PTR(-ENXIO);
 }
 
 static inline struct usb_phy *devm_usb_get_phy_dev(struct device *dev, u8 index)
 {
-	return NULL;
+	return ERR_PTR(-ENXIO);
 }
 
 static inline struct usb_phy *devm_usb_get_phy_by_phandle(struct device *dev,
 	const char *phandle, u8 index)
 {
-	return NULL;
+	return ERR_PTR(-ENXIO);
 }
 
 static inline void usb_put_phy(struct usb_phy *x)
diff --git a/include/linux/usb/renesas_usbhs.h b/include/linux/usb/renesas_usbhs.h
index c5d36c6..e452ba6 100644
--- a/include/linux/usb/renesas_usbhs.h
+++ b/include/linux/usb/renesas_usbhs.h
@@ -62,14 +62,14 @@ struct renesas_usbhs_platform_callback {
 	 * Hardware exit function for platform.
 	 * it is called when driver was removed
 	 */
-	void (*hardware_exit)(struct platform_device *pdev);
+	int (*hardware_exit)(struct platform_device *pdev);
 
 	/*
 	 * option:
 	 *
 	 * for board specific clock control
 	 */
-	void (*power_ctrl)(struct platform_device *pdev,
+	int (*power_ctrl)(struct platform_device *pdev,
 			   void __iomem *base, int enable);
 
 	/*
@@ -77,7 +77,7 @@ struct renesas_usbhs_platform_callback {
 	 *
 	 * Phy reset for platform
 	 */
-	void (*phy_reset)(struct platform_device *pdev);
+	int (*phy_reset)(struct platform_device *pdev);
 
 	/*
 	 * get USB ID function
diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h
index 1819b59..b9b0f7b4 100644
--- a/include/linux/usb/serial.h
+++ b/include/linux/usb/serial.h
@@ -15,6 +15,7 @@
 
 #include <linux/kref.h>
 #include <linux/mutex.h>
+#include <linux/serial.h>
 #include <linux/sysrq.h>
 #include <linux/kfifo.h>
 
@@ -61,12 +62,12 @@
  * @bulk_out_buffers: pointers to the bulk out buffers for this port
  * @write_urbs: pointers to the bulk out urbs for this port
  * @write_urbs_free: status bitmap the for bulk out urbs
+ * @icount: interrupt counters
  * @tx_bytes: number of bytes currently in host stack queues
  * @bulk_out_endpointAddress: endpoint address for the bulk out pipe for this
  *	port.
  * @flags: usb serial port flags
  * @write_wait: a wait_queue_head_t used by the port.
- * @delta_msr_wait: modem-status-change wait queue
  * @work: work queue entry for the line discipline waking up.
  * @throttled: nonzero if the read urb is inactive to throttle the device
  * @throttle_req: nonzero if the tty wants to throttle us
@@ -109,11 +110,11 @@ struct usb_serial_port {
 	unsigned long		write_urbs_free;
 	__u8			bulk_out_endpointAddress;
 
+	struct async_icount	icount;
 	int			tx_bytes;
 
 	unsigned long		flags;
 	wait_queue_head_t	write_wait;
-	wait_queue_head_t	delta_msr_wait;
 	struct work_struct	work;
 	char			throttled;
 	char			throttle_req;
@@ -272,6 +273,7 @@ struct usb_serial_driver {
 	int  (*tiocmget)(struct tty_struct *tty);
 	int  (*tiocmset)(struct tty_struct *tty,
 			 unsigned int set, unsigned int clear);
+	int  (*tiocmiwait)(struct tty_struct *tty, unsigned long arg);
 	int  (*get_icount)(struct tty_struct *tty,
 			struct serial_icounter_struct *icount);
 	/* Called by the tty layer for port level work. There may or may not
@@ -329,8 +331,10 @@ extern void usb_serial_generic_read_bulk_callback(struct urb *urb);
 extern void usb_serial_generic_write_bulk_callback(struct urb *urb);
 extern void usb_serial_generic_throttle(struct tty_struct *tty);
 extern void usb_serial_generic_unthrottle(struct tty_struct *tty);
-extern void usb_serial_generic_disconnect(struct usb_serial *serial);
-extern void usb_serial_generic_release(struct usb_serial *serial);
+extern int usb_serial_generic_tiocmiwait(struct tty_struct *tty,
+							unsigned long arg);
+extern int usb_serial_generic_get_icount(struct tty_struct *tty,
+					struct serial_icounter_struct *icount);
 extern int usb_serial_generic_register(void);
 extern void usb_serial_generic_deregister(void);
 extern int usb_serial_generic_submit_read_urbs(struct usb_serial_port *port,
diff --git a/include/linux/vexpress.h b/include/linux/vexpress.h
index 7581874..ea7168a 100644
--- a/include/linux/vexpress.h
+++ b/include/linux/vexpress.h
@@ -115,9 +115,6 @@ unsigned __vexpress_get_site(struct device *dev, struct device_node *node);
 void vexpress_sysreg_early_init(void __iomem *base);
 void vexpress_sysreg_of_early_init(void);
 
-void vexpress_power_off(void);
-void vexpress_restart(char str, const char *cmd);
-
 /* Clocks */
 
 struct clk *vexpress_osc_setup(struct device *dev);
diff --git a/include/linux/vfio.h b/include/linux/vfio.h
index ab9e862..ac8d488 100644
--- a/include/linux/vfio.h
+++ b/include/linux/vfio.h
@@ -45,6 +45,9 @@ extern int vfio_add_group_dev(struct device *dev,
 			      void *device_data);
 
 extern void *vfio_del_group_dev(struct device *dev);
+extern struct vfio_device *vfio_device_get_from_dev(struct device *dev);
+extern void vfio_device_put(struct vfio_device *device);
+extern void *vfio_device_data(struct vfio_device *device);
 
 /**
  * struct vfio_iommu_driver_ops - VFIO IOMMU driver callbacks
diff --git a/include/linux/virtio.h b/include/linux/virtio.h
index ff6714e..9ff8645 100644
--- a/include/linux/virtio.h
+++ b/include/linux/virtio.h
@@ -8,6 +8,7 @@
 #include <linux/device.h>
 #include <linux/mod_devicetable.h>
 #include <linux/gfp.h>
+#include <linux/vringh.h>
 
 /**
  * virtqueue - a queue to register buffers for sending or receiving.
@@ -40,6 +41,23 @@ int virtqueue_add_buf(struct virtqueue *vq,
 		      void *data,
 		      gfp_t gfp);
 
+int virtqueue_add_outbuf(struct virtqueue *vq,
+			 struct scatterlist sg[], unsigned int num,
+			 void *data,
+			 gfp_t gfp);
+
+int virtqueue_add_inbuf(struct virtqueue *vq,
+			struct scatterlist sg[], unsigned int num,
+			void *data,
+			gfp_t gfp);
+
+int virtqueue_add_sgs(struct virtqueue *vq,
+		      struct scatterlist *sgs[],
+		      unsigned int out_sgs,
+		      unsigned int in_sgs,
+		      void *data,
+		      gfp_t gfp);
+
 void virtqueue_kick(struct virtqueue *vq);
 
 bool virtqueue_kick_prepare(struct virtqueue *vq);
@@ -58,18 +76,13 @@ void *virtqueue_detach_unused_buf(struct virtqueue *vq);
 
 unsigned int virtqueue_get_vring_size(struct virtqueue *vq);
 
-/* FIXME: Obsolete accessor, but required for virtio_net merge. */
-static inline unsigned int virtqueue_get_queue_index(struct virtqueue *vq)
-{
-	return vq->index;
-}
-
 /**
  * virtio_device - representation of a device using virtio
  * @index: unique position on the virtio bus
  * @dev: underlying device.
  * @id: the device type identification (used to match it with a driver).
  * @config: the configuration ops for this device.
+ * @vringh_config: configuration ops for host vrings.
  * @vqs: the list of virtqueues for this device.
  * @features: the features supported by both driver and device.
  * @priv: private pointer for the driver's use.
@@ -79,6 +92,7 @@ struct virtio_device {
 	struct device dev;
 	struct virtio_device_id id;
 	const struct virtio_config_ops *config;
+	const struct vringh_config_ops *vringh_config;
 	struct list_head vqs;
 	/* Note that this is a Linux set_bit-style bitmap. */
 	unsigned long features[1];
diff --git a/include/linux/virtio_caif.h b/include/linux/virtio_caif.h
new file mode 100644
index 0000000..5d2d312
--- /dev/null
+++ b/include/linux/virtio_caif.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) ST-Ericsson AB 2012
+ * Author: Sjur Brændeland <sjur.brandeland@stericsson.com>
+ *
+ * This header is BSD licensed so
+ * anyone can use the definitions to implement compatible remote processors
+ */
+
+#ifndef VIRTIO_CAIF_H
+#define VIRTIO_CAIF_H
+
+#include <linux/types.h>
+struct virtio_caif_transf_config {
+	u16 headroom;
+	u16 tailroom;
+	u32 mtu;
+	u8 reserved[4];
+};
+
+struct virtio_caif_config {
+	struct virtio_caif_transf_config uplink, downlink;
+	u8 reserved[8];
+};
+#endif
diff --git a/include/linux/virtio_ring.h b/include/linux/virtio_ring.h
index 63c6ea1..ca3ad41 100644
--- a/include/linux/virtio_ring.h
+++ b/include/linux/virtio_ring.h
@@ -4,6 +4,63 @@
 #include <linux/irqreturn.h>
 #include <uapi/linux/virtio_ring.h>
 
+/*
+ * Barriers in virtio are tricky.  Non-SMP virtio guests can't assume
+ * they're not on an SMP host system, so they need to assume real
+ * barriers.  Non-SMP virtio hosts could skip the barriers, but does
+ * anyone care?
+ *
+ * For virtio_pci on SMP, we don't need to order with respect to MMIO
+ * accesses through relaxed memory I/O windows, so smp_mb() et al are
+ * sufficient.
+ *
+ * For using virtio to talk to real devices (eg. other heterogeneous
+ * CPUs) we do need real barriers.  In theory, we could be using both
+ * kinds of virtio, so it's a runtime decision, and the branch is
+ * actually quite cheap.
+ */
+
+#ifdef CONFIG_SMP
+static inline void virtio_mb(bool weak_barriers)
+{
+	if (weak_barriers)
+		smp_mb();
+	else
+		mb();
+}
+
+static inline void virtio_rmb(bool weak_barriers)
+{
+	if (weak_barriers)
+		smp_rmb();
+	else
+		rmb();
+}
+
+static inline void virtio_wmb(bool weak_barriers)
+{
+	if (weak_barriers)
+		smp_wmb();
+	else
+		wmb();
+}
+#else
+static inline void virtio_mb(bool weak_barriers)
+{
+	mb();
+}
+
+static inline void virtio_rmb(bool weak_barriers)
+{
+	rmb();
+}
+
+static inline void virtio_wmb(bool weak_barriers)
+{
+	wmb();
+}
+#endif
+
 struct virtio_device;
 struct virtqueue;
 
diff --git a/include/linux/vm_event_item.h b/include/linux/vm_event_item.h
index bd6cf61..d4b7a18 100644
--- a/include/linux/vm_event_item.h
+++ b/include/linux/vm_event_item.h
@@ -50,7 +50,12 @@ enum vm_event_item { PGPGIN, PGPGOUT, PSWPIN, PSWPOUT,
 		COMPACTMIGRATE_SCANNED, COMPACTFREE_SCANNED,
 		COMPACTISOLATED,
 		COMPACTSTALL, COMPACTFAIL, COMPACTSUCCESS,
-#endif
+#ifdef CONFIG_BALLOON_COMPACTION
+		COMPACTBALLOONISOLATED, /* isolated from balloon pagelist */
+		COMPACTBALLOONMIGRATED, /* balloon page sucessfully migrated */
+		COMPACTBALLOONRETURNED, /* putback to pagelist, not-migrated */
+#endif /* CONFIG_BALLOON_COMPACTION */
+#endif /* CONFIG_COMPACTION */
 #ifdef CONFIG_HUGETLB_PAGE
 		HTLB_BUDDY_PGALLOC, HTLB_BUDDY_PGALLOC_FAIL,
 #endif
diff --git a/include/linux/vm_sockets.h b/include/linux/vm_sockets.h
new file mode 100644
index 0000000..0805eec
--- /dev/null
+++ b/include/linux/vm_sockets.h
@@ -0,0 +1,23 @@
+/*
+ * VMware vSockets Driver
+ *
+ * Copyright (C) 2007-2013 VMware, 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 version 2 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * 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 _VM_SOCKETS_H
+#define _VM_SOCKETS_H
+
+#include <uapi/linux/vm_sockets.h>
+
+int vm_sockets_get_local_cid(void);
+
+#endif /* _VM_SOCKETS_H */
diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h
index 6071e91..7d5773a 100644
--- a/include/linux/vmalloc.h
+++ b/include/linux/vmalloc.h
@@ -3,7 +3,9 @@
 
 #include <linux/spinlock.h>
 #include <linux/init.h>
+#include <linux/list.h>
 #include <asm/page.h>		/* pgprot_t */
+#include <linux/rbtree.h>
 
 struct vm_area_struct;		/* vma defining user mapping in mm_types.h */
 
@@ -35,6 +37,17 @@ struct vm_struct {
 	const void		*caller;
 };
 
+struct vmap_area {
+	unsigned long va_start;
+	unsigned long va_end;
+	unsigned long flags;
+	struct rb_node rb_node;         /* address sorted rbtree */
+	struct list_head list;          /* address sorted list */
+	struct list_head purge_list;    /* "lazy purge" list */
+	struct vm_struct *vm;
+	struct rcu_head rcu_head;
+};
+
 /*
  *	Highlevel APIs for driver use
  */
@@ -130,8 +143,7 @@ extern long vwrite(char *buf, char *addr, unsigned long count);
 /*
  *	Internals.  Dont't use..
  */
-extern rwlock_t vmlist_lock;
-extern struct vm_struct *vmlist;
+extern struct list_head vmap_area_list;
 extern __init void vm_area_add_early(struct vm_struct *vm);
 extern __init void vm_area_register_early(struct vm_struct *vm, size_t align);
 
@@ -158,4 +170,22 @@ pcpu_free_vm_areas(struct vm_struct **vms, int nr_vms)
 # endif
 #endif
 
+struct vmalloc_info {
+	unsigned long   used;
+	unsigned long   largest_chunk;
+};
+
+#ifdef CONFIG_MMU
+#define VMALLOC_TOTAL (VMALLOC_END - VMALLOC_START)
+extern void get_vmalloc_info(struct vmalloc_info *vmi);
+#else
+
+#define VMALLOC_TOTAL 0UL
+#define get_vmalloc_info(vmi)			\
+do {						\
+	(vmi)->used = 0;			\
+	(vmi)->largest_chunk = 0;		\
+} while (0)
+#endif
+
 #endif /* _LINUX_VMALLOC_H */
diff --git a/include/linux/vringh.h b/include/linux/vringh.h
new file mode 100644
index 0000000..749cde2
--- /dev/null
+++ b/include/linux/vringh.h
@@ -0,0 +1,225 @@
+/*
+ * Linux host-side vring helpers; for when the kernel needs to access
+ * someone else's vring.
+ *
+ * Copyright IBM Corporation, 2013.
+ * Parts taken from drivers/vhost/vhost.c Copyright 2009 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You 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.
+ *
+ * Written by: Rusty Russell <rusty@rustcorp.com.au>
+ */
+#ifndef _LINUX_VRINGH_H
+#define _LINUX_VRINGH_H
+#include <uapi/linux/virtio_ring.h>
+#include <linux/uio.h>
+#include <linux/slab.h>
+#include <asm/barrier.h>
+
+/* virtio_ring with information needed for host access. */
+struct vringh {
+	/* Guest publishes used event idx (note: we always do). */
+	bool event_indices;
+
+	/* Can we get away with weak barriers? */
+	bool weak_barriers;
+
+	/* Last available index we saw (ie. where we're up to). */
+	u16 last_avail_idx;
+
+	/* Last index we used. */
+	u16 last_used_idx;
+
+	/* How many descriptors we've completed since last need_notify(). */
+	u32 completed;
+
+	/* The vring (note: it may contain user pointers!) */
+	struct vring vring;
+
+	/* The function to call to notify the guest about added buffers */
+	void (*notify)(struct vringh *);
+};
+
+/**
+ * struct vringh_config_ops - ops for creating a host vring from a virtio driver
+ * @find_vrhs: find the host vrings and instantiate them
+ *	vdev: the virtio_device
+ *	nhvrs: the number of host vrings to find
+ *	hvrs: on success, includes new host vrings
+ *	callbacks: array of driver callbacks, for each host vring
+ *		include a NULL entry for vqs that do not need a callback
+ *	Returns 0 on success or error status
+ * @del_vrhs: free the host vrings found by find_vrhs().
+ */
+struct virtio_device;
+typedef void vrh_callback_t(struct virtio_device *, struct vringh *);
+struct vringh_config_ops {
+	int (*find_vrhs)(struct virtio_device *vdev, unsigned nhvrs,
+			 struct vringh *vrhs[], vrh_callback_t *callbacks[]);
+	void (*del_vrhs)(struct virtio_device *vdev);
+};
+
+/* The memory the vring can access, and what offset to apply. */
+struct vringh_range {
+	u64 start, end_incl;
+	u64 offset;
+};
+
+/**
+ * struct vringh_iov - iovec mangler.
+ *
+ * Mangles iovec in place, and restores it.
+ * Remaining data is iov + i, of used - i elements.
+ */
+struct vringh_iov {
+	struct iovec *iov;
+	size_t consumed; /* Within iov[i] */
+	unsigned i, used, max_num;
+};
+
+/**
+ * struct vringh_iov - kvec mangler.
+ *
+ * Mangles kvec in place, and restores it.
+ * Remaining data is iov + i, of used - i elements.
+ */
+struct vringh_kiov {
+	struct kvec *iov;
+	size_t consumed; /* Within iov[i] */
+	unsigned i, used, max_num;
+};
+
+/* Flag on max_num to indicate we're kmalloced. */
+#define VRINGH_IOV_ALLOCATED 0x8000000
+
+/* Helpers for userspace vrings. */
+int vringh_init_user(struct vringh *vrh, u32 features,
+		     unsigned int num, bool weak_barriers,
+		     struct vring_desc __user *desc,
+		     struct vring_avail __user *avail,
+		     struct vring_used __user *used);
+
+static inline void vringh_iov_init(struct vringh_iov *iov,
+				   struct iovec *iovec, unsigned num)
+{
+	iov->used = iov->i = 0;
+	iov->consumed = 0;
+	iov->max_num = num;
+	iov->iov = iovec;
+}
+
+static inline void vringh_iov_reset(struct vringh_iov *iov)
+{
+	iov->iov[iov->i].iov_len += iov->consumed;
+	iov->iov[iov->i].iov_base -= iov->consumed;
+	iov->consumed = 0;
+	iov->i = 0;
+}
+
+static inline void vringh_iov_cleanup(struct vringh_iov *iov)
+{
+	if (iov->max_num & VRINGH_IOV_ALLOCATED)
+		kfree(iov->iov);
+	iov->max_num = iov->used = iov->i = iov->consumed = 0;
+	iov->iov = NULL;
+}
+
+/* Convert a descriptor into iovecs. */
+int vringh_getdesc_user(struct vringh *vrh,
+			struct vringh_iov *riov,
+			struct vringh_iov *wiov,
+			bool (*getrange)(struct vringh *vrh,
+					 u64 addr, struct vringh_range *r),
+			u16 *head);
+
+/* Copy bytes from readable vsg, consuming it (and incrementing wiov->i). */
+ssize_t vringh_iov_pull_user(struct vringh_iov *riov, void *dst, size_t len);
+
+/* Copy bytes into writable vsg, consuming it (and incrementing wiov->i). */
+ssize_t vringh_iov_push_user(struct vringh_iov *wiov,
+			     const void *src, size_t len);
+
+/* Mark a descriptor as used. */
+int vringh_complete_user(struct vringh *vrh, u16 head, u32 len);
+int vringh_complete_multi_user(struct vringh *vrh,
+			       const struct vring_used_elem used[],
+			       unsigned num_used);
+
+/* Pretend we've never seen descriptor (for easy error handling). */
+void vringh_abandon_user(struct vringh *vrh, unsigned int num);
+
+/* Do we need to fire the eventfd to notify the other side? */
+int vringh_need_notify_user(struct vringh *vrh);
+
+bool vringh_notify_enable_user(struct vringh *vrh);
+void vringh_notify_disable_user(struct vringh *vrh);
+
+/* Helpers for kernelspace vrings. */
+int vringh_init_kern(struct vringh *vrh, u32 features,
+		     unsigned int num, bool weak_barriers,
+		     struct vring_desc *desc,
+		     struct vring_avail *avail,
+		     struct vring_used *used);
+
+static inline void vringh_kiov_init(struct vringh_kiov *kiov,
+				    struct kvec *kvec, unsigned num)
+{
+	kiov->used = kiov->i = 0;
+	kiov->consumed = 0;
+	kiov->max_num = num;
+	kiov->iov = kvec;
+}
+
+static inline void vringh_kiov_reset(struct vringh_kiov *kiov)
+{
+	kiov->iov[kiov->i].iov_len += kiov->consumed;
+	kiov->iov[kiov->i].iov_base -= kiov->consumed;
+	kiov->consumed = 0;
+	kiov->i = 0;
+}
+
+static inline void vringh_kiov_cleanup(struct vringh_kiov *kiov)
+{
+	if (kiov->max_num & VRINGH_IOV_ALLOCATED)
+		kfree(kiov->iov);
+	kiov->max_num = kiov->used = kiov->i = kiov->consumed = 0;
+	kiov->iov = NULL;
+}
+
+int vringh_getdesc_kern(struct vringh *vrh,
+			struct vringh_kiov *riov,
+			struct vringh_kiov *wiov,
+			u16 *head,
+			gfp_t gfp);
+
+ssize_t vringh_iov_pull_kern(struct vringh_kiov *riov, void *dst, size_t len);
+ssize_t vringh_iov_push_kern(struct vringh_kiov *wiov,
+			     const void *src, size_t len);
+void vringh_abandon_kern(struct vringh *vrh, unsigned int num);
+int vringh_complete_kern(struct vringh *vrh, u16 head, u32 len);
+
+bool vringh_notify_enable_kern(struct vringh *vrh);
+void vringh_notify_disable_kern(struct vringh *vrh);
+
+int vringh_need_notify_kern(struct vringh *vrh);
+
+/* Notify the guest about buffers added to the used ring */
+static inline void vringh_notify(struct vringh *vrh)
+{
+	if (vrh->notify)
+		vrh->notify(vrh);
+}
+
+#endif /* _LINUX_VRINGH_H */
diff --git a/include/linux/wait.h b/include/linux/wait.h
index 7cb64d4..ac38be2 100644
--- a/include/linux/wait.h
+++ b/include/linux/wait.h
@@ -330,6 +330,92 @@ do {									\
 	__ret;								\
 })
 
+#define __wait_event_hrtimeout(wq, condition, timeout, state)		\
+({									\
+	int __ret = 0;							\
+	DEFINE_WAIT(__wait);						\
+	struct hrtimer_sleeper __t;					\
+									\
+	hrtimer_init_on_stack(&__t.timer, CLOCK_MONOTONIC,		\
+			      HRTIMER_MODE_REL);			\
+	hrtimer_init_sleeper(&__t, current);				\
+	if ((timeout).tv64 != KTIME_MAX)				\
+		hrtimer_start_range_ns(&__t.timer, timeout,		\
+				       current->timer_slack_ns,		\
+				       HRTIMER_MODE_REL);		\
+									\
+	for (;;) {							\
+		prepare_to_wait(&wq, &__wait, state);			\
+		if (condition)						\
+			break;						\
+		if (state == TASK_INTERRUPTIBLE &&			\
+		    signal_pending(current)) {				\
+			__ret = -ERESTARTSYS;				\
+			break;						\
+		}							\
+		if (!__t.task) {					\
+			__ret = -ETIME;					\
+			break;						\
+		}							\
+		schedule();						\
+	}								\
+									\
+	hrtimer_cancel(&__t.timer);					\
+	destroy_hrtimer_on_stack(&__t.timer);				\
+	finish_wait(&wq, &__wait);					\
+	__ret;								\
+})
+
+/**
+ * wait_event_hrtimeout - sleep until a condition gets true or a timeout elapses
+ * @wq: the waitqueue to wait on
+ * @condition: a C expression for the event to wait for
+ * @timeout: timeout, as a ktime_t
+ *
+ * The process is put to sleep (TASK_UNINTERRUPTIBLE) until the
+ * @condition evaluates to true or a signal is received.
+ * The @condition is checked each time the waitqueue @wq is woken up.
+ *
+ * wake_up() has to be called after changing any variable that could
+ * change the result of the wait condition.
+ *
+ * The function returns 0 if @condition became true, or -ETIME if the timeout
+ * elapsed.
+ */
+#define wait_event_hrtimeout(wq, condition, timeout)			\
+({									\
+	int __ret = 0;							\
+	if (!(condition))						\
+		__ret = __wait_event_hrtimeout(wq, condition, timeout,	\
+					       TASK_UNINTERRUPTIBLE);	\
+	__ret;								\
+})
+
+/**
+ * wait_event_interruptible_hrtimeout - sleep until a condition gets true or a timeout elapses
+ * @wq: the waitqueue to wait on
+ * @condition: a C expression for the event to wait for
+ * @timeout: timeout, as a ktime_t
+ *
+ * The process is put to sleep (TASK_INTERRUPTIBLE) until the
+ * @condition evaluates to true or a signal is received.
+ * The @condition is checked each time the waitqueue @wq is woken up.
+ *
+ * wake_up() has to be called after changing any variable that could
+ * change the result of the wait condition.
+ *
+ * The function returns 0 if @condition became true, -ERESTARTSYS if it was
+ * interrupted by a signal, or -ETIME if the timeout elapsed.
+ */
+#define wait_event_interruptible_hrtimeout(wq, condition, timeout)	\
+({									\
+	long __ret = 0;							\
+	if (!(condition))						\
+		__ret = __wait_event_hrtimeout(wq, condition, timeout,	\
+					       TASK_INTERRUPTIBLE);	\
+	__ret;								\
+})
+
 #define __wait_event_interruptible_exclusive(wq, condition, ret)	\
 do {									\
 	DEFINE_WAIT(__wait);						\
diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h
index 8afab27..7179756 100644
--- a/include/linux/workqueue.h
+++ b/include/linux/workqueue.h
@@ -11,6 +11,7 @@
 #include <linux/lockdep.h>
 #include <linux/threads.h>
 #include <linux/atomic.h>
+#include <linux/cpumask.h>
 
 struct workqueue_struct;
 
@@ -68,7 +69,7 @@ enum {
 				  WORK_STRUCT_COLOR_BITS,
 
 	/* data contains off-queue information when !WORK_STRUCT_PWQ */
-	WORK_OFFQ_FLAG_BASE	= WORK_STRUCT_FLAG_BITS,
+	WORK_OFFQ_FLAG_BASE	= WORK_STRUCT_COLOR_SHIFT,
 
 	WORK_OFFQ_CANCELING	= (1 << WORK_OFFQ_FLAG_BASE),
 
@@ -115,6 +116,20 @@ struct delayed_work {
 	int cpu;
 };
 
+/*
+ * A struct for workqueue attributes.  This can be used to change
+ * attributes of an unbound workqueue.
+ *
+ * Unlike other fields, ->no_numa isn't a property of a worker_pool.  It
+ * only modifies how apply_workqueue_attrs() select pools and thus doesn't
+ * participate in pool hash calculations or equality comparisons.
+ */
+struct workqueue_attrs {
+	int			nice;		/* nice level */
+	cpumask_var_t		cpumask;	/* allowed CPUs */
+	bool			no_numa;	/* disable NUMA affinity */
+};
+
 static inline struct delayed_work *to_delayed_work(struct work_struct *work)
 {
 	return container_of(work, struct delayed_work, work);
@@ -283,9 +298,10 @@ enum {
 	WQ_MEM_RECLAIM		= 1 << 3, /* may be used for memory reclaim */
 	WQ_HIGHPRI		= 1 << 4, /* high priority */
 	WQ_CPU_INTENSIVE	= 1 << 5, /* cpu instensive workqueue */
+	WQ_SYSFS		= 1 << 6, /* visible in sysfs, see wq_sysfs_register() */
 
-	WQ_DRAINING		= 1 << 6, /* internal: workqueue is draining */
-	WQ_RESCUER		= 1 << 7, /* internal: workqueue has rescuer */
+	__WQ_DRAINING		= 1 << 16, /* internal: workqueue is draining */
+	__WQ_ORDERED		= 1 << 17, /* internal: workqueue is ordered */
 
 	WQ_MAX_ACTIVE		= 512,	  /* I like 512, better ideas? */
 	WQ_MAX_UNBOUND_PER_CPU	= 4,	  /* 4 * #cpus for unbound wq */
@@ -388,7 +404,7 @@ __alloc_workqueue_key(const char *fmt, unsigned int flags, int max_active,
  * Pointer to the allocated workqueue on success, %NULL on failure.
  */
 #define alloc_ordered_workqueue(fmt, flags, args...)			\
-	alloc_workqueue(fmt, WQ_UNBOUND | (flags), 1, ##args)
+	alloc_workqueue(fmt, WQ_UNBOUND | __WQ_ORDERED | (flags), 1, ##args)
 
 #define create_workqueue(name)						\
 	alloc_workqueue((name), WQ_MEM_RECLAIM, 1)
@@ -399,30 +415,23 @@ __alloc_workqueue_key(const char *fmt, unsigned int flags, int max_active,
 
 extern void destroy_workqueue(struct workqueue_struct *wq);
 
+struct workqueue_attrs *alloc_workqueue_attrs(gfp_t gfp_mask);
+void free_workqueue_attrs(struct workqueue_attrs *attrs);
+int apply_workqueue_attrs(struct workqueue_struct *wq,
+			  const struct workqueue_attrs *attrs);
+
 extern bool queue_work_on(int cpu, struct workqueue_struct *wq,
 			struct work_struct *work);
-extern bool queue_work(struct workqueue_struct *wq, struct work_struct *work);
 extern bool queue_delayed_work_on(int cpu, struct workqueue_struct *wq,
 			struct delayed_work *work, unsigned long delay);
-extern bool queue_delayed_work(struct workqueue_struct *wq,
-			struct delayed_work *work, unsigned long delay);
 extern bool mod_delayed_work_on(int cpu, struct workqueue_struct *wq,
 			struct delayed_work *dwork, unsigned long delay);
-extern bool mod_delayed_work(struct workqueue_struct *wq,
-			struct delayed_work *dwork, 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 bool schedule_work_on(int cpu, struct work_struct *work);
-extern bool schedule_work(struct work_struct *work);
-extern bool schedule_delayed_work_on(int cpu, struct delayed_work *work,
-				     unsigned long delay);
-extern bool schedule_delayed_work(struct delayed_work *work,
-				  unsigned long delay);
 extern int schedule_on_each_cpu(work_func_t func);
-extern int keventd_up(void);
 
 int execute_in_process_context(work_func_t fn, struct execute_work *);
 
@@ -435,9 +444,121 @@ extern bool cancel_delayed_work_sync(struct delayed_work *dwork);
 
 extern void workqueue_set_max_active(struct workqueue_struct *wq,
 				     int max_active);
-extern bool workqueue_congested(unsigned int cpu, struct workqueue_struct *wq);
+extern bool current_is_workqueue_rescuer(void);
+extern bool workqueue_congested(int cpu, struct workqueue_struct *wq);
 extern unsigned int work_busy(struct work_struct *work);
 
+/**
+ * queue_work - queue work on a workqueue
+ * @wq: workqueue to use
+ * @work: work to queue
+ *
+ * Returns %false if @work was already on a queue, %true otherwise.
+ *
+ * We queue the work to the CPU on which it was submitted, but if the CPU dies
+ * it can be processed by another CPU.
+ */
+static inline bool queue_work(struct workqueue_struct *wq,
+			      struct work_struct *work)
+{
+	return queue_work_on(WORK_CPU_UNBOUND, wq, work);
+}
+
+/**
+ * queue_delayed_work - queue work on a workqueue after delay
+ * @wq: workqueue to use
+ * @dwork: delayable work to queue
+ * @delay: number of jiffies to wait before queueing
+ *
+ * Equivalent to queue_delayed_work_on() but tries to use the local CPU.
+ */
+static inline bool queue_delayed_work(struct workqueue_struct *wq,
+				      struct delayed_work *dwork,
+				      unsigned long delay)
+{
+	return queue_delayed_work_on(WORK_CPU_UNBOUND, wq, dwork, delay);
+}
+
+/**
+ * mod_delayed_work - modify delay of or queue a delayed work
+ * @wq: workqueue to use
+ * @dwork: work to queue
+ * @delay: number of jiffies to wait before queueing
+ *
+ * mod_delayed_work_on() on local CPU.
+ */
+static inline bool mod_delayed_work(struct workqueue_struct *wq,
+				    struct delayed_work *dwork,
+				    unsigned long delay)
+{
+	return mod_delayed_work_on(WORK_CPU_UNBOUND, wq, dwork, delay);
+}
+
+/**
+ * schedule_work_on - put work task on a specific cpu
+ * @cpu: cpu to put the work task on
+ * @work: job to be done
+ *
+ * This puts a job on a specific cpu
+ */
+static inline bool schedule_work_on(int cpu, struct work_struct *work)
+{
+	return queue_work_on(cpu, system_wq, work);
+}
+
+/**
+ * schedule_work - put work task in global workqueue
+ * @work: job to be done
+ *
+ * Returns %false if @work was already on the kernel-global workqueue and
+ * %true otherwise.
+ *
+ * This puts a job in the kernel-global workqueue if it was not already
+ * queued and leaves it in the same position on the kernel-global
+ * workqueue otherwise.
+ */
+static inline bool schedule_work(struct work_struct *work)
+{
+	return queue_work(system_wq, work);
+}
+
+/**
+ * schedule_delayed_work_on - queue work in global workqueue on CPU after delay
+ * @cpu: cpu to use
+ * @dwork: job to be done
+ * @delay: number of jiffies to wait
+ *
+ * After waiting for a given time this puts a job in the kernel-global
+ * workqueue on the specified CPU.
+ */
+static inline bool schedule_delayed_work_on(int cpu, struct delayed_work *dwork,
+					    unsigned long delay)
+{
+	return queue_delayed_work_on(cpu, system_wq, dwork, delay);
+}
+
+/**
+ * schedule_delayed_work - put work task in global workqueue after delay
+ * @dwork: job to be done
+ * @delay: number of jiffies to wait or 0 for immediate execution
+ *
+ * After waiting for a given time this puts a job in the kernel-global
+ * workqueue.
+ */
+static inline bool schedule_delayed_work(struct delayed_work *dwork,
+					 unsigned long delay)
+{
+	return queue_delayed_work(system_wq, dwork, delay);
+}
+
+/**
+ * keventd_up - is workqueue initialized yet?
+ */
+static inline bool keventd_up(void)
+{
+	return system_wq != NULL;
+}
+
 /*
  * Like above, but uses del_timer() instead of del_timer_sync(). This means,
  * if it returns 0 the timer function may be running and the queueing is in
@@ -466,12 +587,12 @@ static inline bool __deprecated flush_delayed_work_sync(struct delayed_work *dwo
 }
 
 #ifndef CONFIG_SMP
-static inline long work_on_cpu(unsigned int cpu, long (*fn)(void *), void *arg)
+static inline long work_on_cpu(int cpu, long (*fn)(void *), void *arg)
 {
 	return fn(arg);
 }
 #else
-long work_on_cpu(unsigned int cpu, long (*fn)(void *), void *arg);
+long work_on_cpu(int cpu, long (*fn)(void *), void *arg);
 #endif /* CONFIG_SMP */
 
 #ifdef CONFIG_FREEZER
@@ -480,4 +601,11 @@ extern bool freeze_workqueues_busy(void);
 extern void thaw_workqueues(void);
 #endif /* CONFIG_FREEZER */
 
+#ifdef CONFIG_SYSFS
+int workqueue_sysfs_register(struct workqueue_struct *wq);
+#else	/* CONFIG_SYSFS */
+static inline int workqueue_sysfs_register(struct workqueue_struct *wq)
+{ return 0; }
+#endif	/* CONFIG_SYSFS */
+
 #endif
diff --git a/include/linux/writeback.h b/include/linux/writeback.h
index 9a9367c..579a500 100644
--- a/include/linux/writeback.h
+++ b/include/linux/writeback.h
@@ -5,6 +5,7 @@
 #define WRITEBACK_H
 
 #include <linux/sched.h>
+#include <linux/workqueue.h>
 #include <linux/fs.h>
 
 DECLARE_PER_CPU(int, dirty_throttle_leaks);
diff --git a/include/media/davinci/dm355_ccdc.h b/include/media/davinci/dm355_ccdc.h
index adf2fe4..c669a9f 100644
--- a/include/media/davinci/dm355_ccdc.h
+++ b/include/media/davinci/dm355_ccdc.h
@@ -38,7 +38,7 @@ enum ccdc_sample_line {
 	CCDC_SAMPLE_16LINES
 };
 
-/* enum for Alaw gama width */
+/* enum for Alaw gamma width */
 enum ccdc_gamma_width {
 	CCDC_GAMMA_BITS_13_4,
 	CCDC_GAMMA_BITS_12_3,
@@ -97,8 +97,8 @@ enum ccdc_mfilt2 {
 struct ccdc_a_law {
 	/* Enable/disable A-Law */
 	unsigned char enable;
-	/* Gama Width Input */
-	enum ccdc_gamma_width gama_wd;
+	/* Gamma Width Input */
+	enum ccdc_gamma_width gamma_wd;
 };
 
 /* structure for Black Clamping */
diff --git a/include/media/davinci/dm644x_ccdc.h b/include/media/davinci/dm644x_ccdc.h
index 3e178eb..852e96c 100644
--- a/include/media/davinci/dm644x_ccdc.h
+++ b/include/media/davinci/dm644x_ccdc.h
@@ -38,17 +38,23 @@ enum ccdc_sample_line {
 	CCDC_SAMPLE_16LINES
 };
 
-/* enum for Alaw gama width */
-enum ccdc_gama_width {
-	CCDC_GAMMA_BITS_15_6,
+/* enum for Alaw gamma width */
+enum ccdc_gamma_width {
+	CCDC_GAMMA_BITS_15_6,	/* use bits 15-6 for gamma */
 	CCDC_GAMMA_BITS_14_5,
 	CCDC_GAMMA_BITS_13_4,
 	CCDC_GAMMA_BITS_12_3,
 	CCDC_GAMMA_BITS_11_2,
 	CCDC_GAMMA_BITS_10_1,
-	CCDC_GAMMA_BITS_09_0
+	CCDC_GAMMA_BITS_09_0	/* use bits 9-0 for gamma */
 };
 
+/* returns the highest bit used for the gamma */
+static inline u8 ccdc_gamma_width_max_bit(enum ccdc_gamma_width width)
+{
+	return 15 - width;
+}
+
 enum ccdc_data_size {
 	CCDC_DATA_16BITS,
 	CCDC_DATA_15BITS,
@@ -60,12 +66,18 @@ enum ccdc_data_size {
 	CCDC_DATA_8BITS
 };
 
+/* returns the highest bit used for this data size */
+static inline u8 ccdc_data_size_max_bit(enum ccdc_data_size sz)
+{
+	return sz == CCDC_DATA_8BITS ? 7 : 15 - sz;
+}
+
 /* structure for ALaw */
 struct ccdc_a_law {
 	/* Enable/disable A-Law */
 	unsigned char enable;
-	/* Gama Width Input */
-	enum ccdc_gama_width gama_wd;
+	/* Gamma Width Input */
+	enum ccdc_gamma_width gamma_wd;
 };
 
 /* structure for Black Clamping */
diff --git a/include/media/davinci/vpbe.h b/include/media/davinci/vpbe.h
index a7ca488..57585c7 100644
--- a/include/media/davinci/vpbe.h
+++ b/include/media/davinci/vpbe.h
@@ -132,7 +132,7 @@ struct vpbe_device_ops {
 			       struct v4l2_enum_dv_timings *timings_info);
 
 	/* Set std at the output */
-	int (*s_std)(struct vpbe_device *vpbe_dev, v4l2_std_id *std_id);
+	int (*s_std)(struct vpbe_device *vpbe_dev, v4l2_std_id std_id);
 
 	/* Get the current std at the output */
 	int (*g_std)(struct vpbe_device *vpbe_dev, v4l2_std_id *std_id);
diff --git a/include/media/davinci/vpbe_types.h b/include/media/davinci/vpbe_types.h
index 9b85396..05dbe0b 100644
--- a/include/media/davinci/vpbe_types.h
+++ b/include/media/davinci/vpbe_types.h
@@ -26,8 +26,7 @@ enum vpbe_version {
 /* vpbe_timing_type - Timing types used in vpbe device */
 enum vpbe_enc_timings_type {
 	VPBE_ENC_STD = 0x1,
-	VPBE_ENC_DV_PRESET = 0x2,
-	VPBE_ENC_CUSTOM_TIMINGS = 0x4,
+	VPBE_ENC_DV_TIMINGS = 0x4,
 	/* Used when set timings through FB device interface */
 	VPBE_ENC_TIMINGS_INVALID = 0x8,
 };
diff --git a/include/media/media-devnode.h b/include/media/media-devnode.h
index f6caafc..3446af2 100644
--- a/include/media/media-devnode.h
+++ b/include/media/media-devnode.h
@@ -46,6 +46,7 @@ struct media_file_operations {
 	ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
 	unsigned int (*poll) (struct file *, struct poll_table_struct *);
 	long (*ioctl) (struct file *, unsigned int, unsigned long);
+	long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
 	int (*open) (struct file *);
 	int (*release) (struct file *);
 };
diff --git a/include/media/rc-core.h b/include/media/rc-core.h
index f03445f..06a75de 100644
--- a/include/media/rc-core.h
+++ b/include/media/rc-core.h
@@ -51,6 +51,7 @@ enum rc_driver_type {
  * @driver_type: specifies if protocol decoding is done in hardware or software
  * @idle: used to keep track of RX state
  * @allowed_protos: bitmask with the supported RC_BIT_* protocols
+ * @enabled_protocols: bitmask with the enabled RC_BIT_* protocols
  * @scanmask: some hardware decoders are not capable of providing the full
  *	scancode to the application. As this is a hardware limit, we can't do
  *	anything with it. Yet, as the same keycode table can be used with other
@@ -99,6 +100,7 @@ struct rc_dev {
 	enum rc_driver_type		driver_type;
 	bool				idle;
 	u64				allowed_protos;
+	u64				enabled_protocols;
 	u32				scanmask;
 	void				*priv;
 	spinlock_t			keylock;
diff --git a/include/media/saa7115.h b/include/media/saa7115.h
index bab2127..4079186 100644
--- a/include/media/saa7115.h
+++ b/include/media/saa7115.h
@@ -21,6 +21,8 @@
 #ifndef _SAA7115_H_
 #define _SAA7115_H_
 
+/* s_routing inputs, outputs, and config */
+
 /* SAA7111/3/4/5 HW inputs */
 #define SAA7115_COMPOSITE0 0
 #define SAA7115_COMPOSITE1 1
@@ -33,24 +35,34 @@
 #define SAA7115_SVIDEO2    8
 #define SAA7115_SVIDEO3    9
 
-/* SAA7115 v4l2_crystal_freq frequency values */
-#define SAA7115_FREQ_32_11_MHZ  32110000   /* 32.11 MHz crystal, SAA7114/5 only */
-#define SAA7115_FREQ_24_576_MHZ 24576000   /* 24.576 MHz crystal */
-
-/* SAA7115 v4l2_crystal_freq audio clock control flags */
-#define SAA7115_FREQ_FL_UCGC   (1 << 0)	   /* SA 3A[7], UCGC, SAA7115 only */
-#define SAA7115_FREQ_FL_CGCDIV (1 << 1)	   /* SA 3A[6], CGCDIV, SAA7115 only */
-#define SAA7115_FREQ_FL_APLL   (1 << 2)	   /* SA 3A[3], APLL, SAA7114/5 only */
-
+/* outputs */
 #define SAA7115_IPORT_ON    	1
 #define SAA7115_IPORT_OFF   	0
 
-/* SAA7111 specific output flags */
+/* SAA7111 specific outputs. */
 #define SAA7111_VBI_BYPASS 	2
 #define SAA7111_FMT_YUV422      0x00
 #define SAA7111_FMT_RGB 	0x40
 #define SAA7111_FMT_CCIR 	0x80
 #define SAA7111_FMT_YUV411 	0xc0
 
+/* config flags */
+/* Register 0x85 should set bit 0 to 0 (it's 1 by default). This bit
+ * controls the IDQ signal polarity which is set to 'inverted' if the bit
+ * it 1 and to 'default' if it is 0. */
+#define SAA7115_IDQ_IS_DEFAULT  (1 << 0)
+
+/* s_crystal_freq values and flags */
+
+/* SAA7115 v4l2_crystal_freq frequency values */
+#define SAA7115_FREQ_32_11_MHZ  32110000   /* 32.11 MHz crystal, SAA7114/5 only */
+#define SAA7115_FREQ_24_576_MHZ 24576000   /* 24.576 MHz crystal */
+
+/* SAA7115 v4l2_crystal_freq audio clock control flags */
+#define SAA7115_FREQ_FL_UCGC         (1 << 0) /* SA 3A[7], UCGC, SAA7115 only */
+#define SAA7115_FREQ_FL_CGCDIV       (1 << 1) /* SA 3A[6], CGCDIV, SAA7115 only */
+#define SAA7115_FREQ_FL_APLL         (1 << 2) /* SA 3A[3], APLL, SAA7114/5 only */
+#define SAA7115_FREQ_FL_DOUBLE_ASCLK (1 << 3) /* SA 39, LRDIV, SAA7114/5 only */
+
 #endif
 
diff --git a/include/media/ths7303.h b/include/media/ths7303.h
new file mode 100644
index 0000000..980ec51
--- /dev/null
+++ b/include/media/ths7303.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2013 Texas Instruments Inc
+ *
+ * Copyright 2013 Cisco Systems, Inc. and/or its affiliates.
+ *
+ * Contributors:
+ *     Hans Verkuil <hans.verkuil@cisco.com>
+ *     Lad, Prabhakar <prabhakar.lad@ti.com>
+ *     Martin Bugge <marbugge@cisco.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You 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 THS7353_H
+#define THS7353_H
+
+/**
+ * struct ths7303_platform_data - Platform dependent data
+ * @ch_1: Bias value for channel one.
+ * @ch_2: Bias value for channel two.
+ * @ch_3: Bias value for channel three.
+ * @init_enable: initalize on init.
+ */
+struct ths7303_platform_data {
+	u8 ch_1;
+	u8 ch_2;
+	u8 ch_3;
+	u8 init_enable;
+};
+
+#endif
diff --git a/include/media/tuner.h b/include/media/tuner.h
index 926aff9..24eaafe 100644
--- a/include/media/tuner.h
+++ b/include/media/tuner.h
@@ -138,6 +138,10 @@
 #define TUNER_XC4000			87	/* Xceive Silicon Tuner */
 #define TUNER_XC5000C			88	/* Xceive Silicon Tuner */
 
+#define TUNER_SONY_BTF_PG472Z		89	/* PAL+SECAM */
+#define TUNER_SONY_BTF_PK467Z		90	/* NTSC_JP */
+#define TUNER_SONY_BTF_PB463Z		91	/* NTSC */
+
 /* tv card specific */
 #define TDA9887_PRESENT 		(1<<0)
 #define TDA9887_PORT1_INACTIVE 		(1<<1)
diff --git a/include/media/uda1342.h b/include/media/uda1342.h
new file mode 100644
index 0000000..cd15640
--- /dev/null
+++ b/include/media/uda1342.h
@@ -0,0 +1,29 @@
+/*
+ * uda1342.h - definition for uda1342 inputs
+ *
+ * Copyright 2013 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
+ *
+ * This program is free software; you may 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.
+ *
+ * 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.
+ *
+ */
+
+#ifndef _UDA1342_H_
+#define _UDA1342_H_
+
+/* The UDA1342 has 2 inputs */
+
+#define UDA1342_IN1 1
+#define UDA1342_IN2 2
+
+#endif
diff --git a/include/media/v4l2-chip-ident.h b/include/media/v4l2-chip-ident.h
index 4ee125b..c259b36 100644
--- a/include/media/v4l2-chip-ident.h
+++ b/include/media/v4l2-chip-ident.h
@@ -96,12 +96,20 @@ enum {
 	/* module au0828 */
 	V4L2_IDENT_AU0828 = 828,
 
+	/* module bttv: ident 848 + 849 */
+	V4L2_IDENT_BT848 = 848,
+	V4L2_IDENT_BT849 = 849,
+
 	/* module bt856: just ident 856 */
 	V4L2_IDENT_BT856 = 856,
 
 	/* module bt866: just ident 866 */
 	V4L2_IDENT_BT866 = 866,
 
+	/* module bttv: ident 878 + 879 */
+	V4L2_IDENT_BT878 = 878,
+	V4L2_IDENT_BT879 = 879,
+
 	/* module ks0127: reserved range 1120-1129 */
 	V4L2_IDENT_KS0122S = 1122,
 	V4L2_IDENT_KS0127  = 1127,
@@ -180,6 +188,9 @@ enum {
 	/* module adv7343: just ident 7343 */
 	V4L2_IDENT_ADV7343 = 7343,
 
+	/* module ths7353: just ident 7353 */
+	V4L2_IDENT_THS7353 = 7353,
+
 	/* module adv7393: just ident 7393 */
 	V4L2_IDENT_ADV7393 = 7393,
 
diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h
index ec7c9c0..1d93c48 100644
--- a/include/media/v4l2-common.h
+++ b/include/media/v4l2-common.h
@@ -201,7 +201,6 @@ void v4l_bound_align_image(unsigned int *w, unsigned int wmin,
 			   unsigned int *h, unsigned int hmin,
 			   unsigned int hmax, unsigned int halign,
 			   unsigned int salign);
-int v4l_fill_dv_preset_info(u32 preset, struct v4l2_dv_enum_preset *info);
 
 struct v4l2_discrete_probe {
 	const struct v4l2_frmsize_discrete	*sizes;
diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h
index f00d42b..7343a27 100644
--- a/include/media/v4l2-ctrls.h
+++ b/include/media/v4l2-ctrls.h
@@ -259,7 +259,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
 		    s32 *min, s32 *max, s32 *step, s32 *def, u32 *flags);
 
 
-/** v4l2_ctrl_handler_init() - Initialize the control handler.
+/** v4l2_ctrl_handler_init_class() - Initialize the control handler.
   * @hdl:	The control handler.
   * @nr_of_controls_hint: A hint of how many controls this handler is
   *		expected to refer to. This is the total number, so including
@@ -268,12 +268,35 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
   *		are allocated) or the control lookup becomes slower (not enough
   *		buckets are allocated, so there are more slow list lookups).
   *		It will always work, though.
+  * @key:	Used by the lock validator if CONFIG_LOCKDEP is set.
+  * @name:	Used by the lock validator if CONFIG_LOCKDEP is set.
   *
   * Returns an error if the buckets could not be allocated. This error will
   * also be stored in @hdl->error.
+  *
+  * Never use this call directly, always use the v4l2_ctrl_handler_init
+  * macro that hides the @key and @name arguments.
   */
-int v4l2_ctrl_handler_init(struct v4l2_ctrl_handler *hdl,
-			   unsigned nr_of_controls_hint);
+int v4l2_ctrl_handler_init_class(struct v4l2_ctrl_handler *hdl,
+				 unsigned nr_of_controls_hint,
+				 struct lock_class_key *key, const char *name);
+
+#ifdef CONFIG_LOCKDEP
+#define v4l2_ctrl_handler_init(hdl, nr_of_controls_hint)		\
+(									\
+	({								\
+		static struct lock_class_key _key;			\
+		v4l2_ctrl_handler_init_class(hdl, nr_of_controls_hint,	\
+					&_key,				\
+					KBUILD_BASENAME ":"		\
+					__stringify(__LINE__) ":"	\
+					"(" #hdl ")->_lock");		\
+	})								\
+)
+#else
+#define v4l2_ctrl_handler_init(hdl, nr_of_controls_hint)		\
+	v4l2_ctrl_handler_init_class(hdl, nr_of_controls_hint, NULL, NULL)
+#endif
 
 /** v4l2_ctrl_handler_free() - Free all controls owned by the handler and free
   * the control list.
diff --git a/include/media/v4l2-device.h b/include/media/v4l2-device.h
index d61febf..c9b1593 100644
--- a/include/media/v4l2-device.h
+++ b/include/media/v4l2-device.h
@@ -190,4 +190,17 @@ v4l2_device_register_subdev_nodes(struct v4l2_device *v4l2_dev);
 			##args);					\
 })
 
+#define v4l2_device_has_op(v4l2_dev, o, f)				\
+({									\
+	struct v4l2_subdev *__sd;					\
+	bool __result = false;						\
+	list_for_each_entry(__sd, &(v4l2_dev)->subdevs, list) {		\
+		if (v4l2_subdev_has_op(__sd, o, f)) {			\
+			__result = true;				\
+			break;						\
+		}							\
+	}								\
+	__result;							\
+})
+
 #endif
diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h
index 4118ad1..b273f0e 100644
--- a/include/media/v4l2-ioctl.h
+++ b/include/media/v4l2-ioctl.h
@@ -132,7 +132,7 @@ struct v4l2_ioctl_ops {
 			ENUMSTD is handled by videodev.c
 		 */
 	int (*vidioc_g_std) (struct file *file, void *fh, v4l2_std_id *norm);
-	int (*vidioc_s_std) (struct file *file, void *fh, v4l2_std_id *norm);
+	int (*vidioc_s_std) (struct file *file, void *fh, v4l2_std_id norm);
 	int (*vidioc_querystd) (struct file *file, void *fh, v4l2_std_id *a);
 
 		/* Input handling */
@@ -219,11 +219,11 @@ struct v4l2_ioctl_ops {
 	int (*vidioc_g_tuner)          (struct file *file, void *fh,
 					struct v4l2_tuner *a);
 	int (*vidioc_s_tuner)          (struct file *file, void *fh,
-					struct v4l2_tuner *a);
+					const struct v4l2_tuner *a);
 	int (*vidioc_g_frequency)      (struct file *file, void *fh,
 					struct v4l2_frequency *a);
 	int (*vidioc_s_frequency)      (struct file *file, void *fh,
-					struct v4l2_frequency *a);
+					const struct v4l2_frequency *a);
 	int (*vidioc_enum_freq_bands) (struct file *file, void *fh,
 				    struct v4l2_frequency_band *band);
 
@@ -242,11 +242,14 @@ struct v4l2_ioctl_ops {
 	int (*vidioc_g_register)       (struct file *file, void *fh,
 					struct v4l2_dbg_register *reg);
 	int (*vidioc_s_register)       (struct file *file, void *fh,
-					struct v4l2_dbg_register *reg);
+					const struct v4l2_dbg_register *reg);
 #endif
 	int (*vidioc_g_chip_ident)     (struct file *file, void *fh,
 					struct v4l2_dbg_chip_ident *chip);
 
+	int (*vidioc_g_chip_name)      (struct file *file, void *fh,
+					struct v4l2_dbg_chip_name *chip);
+
 	int (*vidioc_enum_framesizes)   (struct file *file, void *fh,
 					 struct v4l2_frmsizeenum *fsize);
 
@@ -254,15 +257,6 @@ struct v4l2_ioctl_ops {
 					   struct v4l2_frmivalenum *fival);
 
 	/* DV Timings IOCTLs */
-	int (*vidioc_enum_dv_presets) (struct file *file, void *fh,
-				       struct v4l2_dv_enum_preset *preset);
-
-	int (*vidioc_s_dv_preset) (struct file *file, void *fh,
-				   struct v4l2_dv_preset *preset);
-	int (*vidioc_g_dv_preset) (struct file *file, void *fh,
-				   struct v4l2_dv_preset *preset);
-	int (*vidioc_query_dv_preset) (struct file *file, void *fh,
-					struct v4l2_dv_preset *qpreset);
 	int (*vidioc_s_dv_timings) (struct file *file, void *fh,
 				    struct v4l2_dv_timings *timings);
 	int (*vidioc_g_dv_timings) (struct file *file, void *fh,
@@ -281,7 +275,7 @@ struct v4l2_ioctl_ops {
 
 	/* For other private ioctls */
 	long (*vidioc_default)	       (struct file *file, void *fh,
-					bool valid_prio, int cmd, void *arg);
+					bool valid_prio, unsigned int cmd, void *arg);
 };
 
 
diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
index b137a5e..5298d67 100644
--- a/include/media/v4l2-subdev.h
+++ b/include/media/v4l2-subdev.h
@@ -165,7 +165,7 @@ struct v4l2_subdev_core_ops {
 	long (*ioctl)(struct v4l2_subdev *sd, unsigned int cmd, void *arg);
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 	int (*g_register)(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg);
-	int (*s_register)(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg);
+	int (*s_register)(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg);
 #endif
 	int (*s_power)(struct v4l2_subdev *sd, int on);
 	int (*interrupt_service_routine)(struct v4l2_subdev *sd,
@@ -191,10 +191,10 @@ struct v4l2_subdev_core_ops {
  */
 struct v4l2_subdev_tuner_ops {
 	int (*s_radio)(struct v4l2_subdev *sd);
-	int (*s_frequency)(struct v4l2_subdev *sd, struct v4l2_frequency *freq);
+	int (*s_frequency)(struct v4l2_subdev *sd, const struct v4l2_frequency *freq);
 	int (*g_frequency)(struct v4l2_subdev *sd, struct v4l2_frequency *freq);
 	int (*g_tuner)(struct v4l2_subdev *sd, struct v4l2_tuner *vt);
-	int (*s_tuner)(struct v4l2_subdev *sd, struct v4l2_tuner *vt);
+	int (*s_tuner)(struct v4l2_subdev *sd, const struct v4l2_tuner *vt);
 	int (*g_modulator)(struct v4l2_subdev *sd, struct v4l2_modulator *vm);
 	int (*s_modulator)(struct v4l2_subdev *sd, const struct v4l2_modulator *vm);
 	int (*s_type_addr)(struct v4l2_subdev *sd, struct tuner_setup *type);
@@ -279,14 +279,6 @@ struct v4l2_mbus_frame_desc {
    s_routing: see s_routing in audio_ops, except this version is for video
 	devices.
 
-   s_dv_preset: set dv (Digital Video) preset in the sub device. Similar to
-	s_std()
-
-   g_dv_preset: get current dv (Digital Video) preset in the sub device.
-
-   query_dv_preset: query dv preset in the sub device. This is similar to
-	querystd()
-
    s_dv_timings(): Set custom dv timings in the sub device. This is used
 	when sub device is capable of setting detailed timing information
 	in the hardware to generate/detect the video signal.
@@ -331,14 +323,6 @@ struct v4l2_subdev_video_ops {
 				struct v4l2_subdev_frame_interval *interval);
 	int (*enum_framesizes)(struct v4l2_subdev *sd, struct v4l2_frmsizeenum *fsize);
 	int (*enum_frameintervals)(struct v4l2_subdev *sd, struct v4l2_frmivalenum *fival);
-	int (*enum_dv_presets) (struct v4l2_subdev *sd,
-			struct v4l2_dv_enum_preset *preset);
-	int (*s_dv_preset)(struct v4l2_subdev *sd,
-			struct v4l2_dv_preset *preset);
-	int (*g_dv_preset)(struct v4l2_subdev *sd,
-			struct v4l2_dv_preset *preset);
-	int (*query_dv_preset)(struct v4l2_subdev *sd,
-			struct v4l2_dv_preset *preset);
 	int (*s_dv_timings)(struct v4l2_subdev *sd,
 			struct v4l2_dv_timings *timings);
 	int (*g_dv_timings)(struct v4l2_subdev *sd,
@@ -687,4 +671,7 @@ void v4l2_subdev_init(struct v4l2_subdev *sd,
 	((!(sd) || !(sd)->v4l2_dev || !(sd)->v4l2_dev->notify) ? -ENODEV : \
 	 (sd)->v4l2_dev->notify((sd), (notification), (arg)))
 
+#define v4l2_subdev_has_op(sd, o, f) \
+	((sd)->ops->o && (sd)->ops->o->f)
+
 #endif
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index 9cfd4ee..d88a098 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -27,7 +27,9 @@ struct vb2_fileio_data;
  *		return NULL on failure or a pointer to allocator private,
  *		per-buffer data on success; the returned private structure
  *		will then be passed as buf_priv argument to other ops in this
- *		structure
+ *		structure. Additional gfp_flags to use when allocating the
+ *		are also passed to this operation. These flags are from the
+ *		gfp_flags field of vb2_queue.
  * @put:	inform the allocator that the buffer will no longer be used;
  *		usually will result in the allocator freeing the buffer (if
  *		no other users of this buffer are present); the buf_priv
@@ -79,7 +81,7 @@ struct vb2_fileio_data;
  *				  unmap_dmabuf.
  */
 struct vb2_mem_ops {
-	void		*(*alloc)(void *alloc_ctx, unsigned long size);
+	void		*(*alloc)(void *alloc_ctx, unsigned long size, gfp_t gfp_flags);
 	void		(*put)(void *buf_priv);
 	struct dma_buf *(*get_dmabuf)(void *buf_priv);
 
@@ -302,6 +304,9 @@ struct v4l2_fh;
  * @buf_struct_size: size of the driver-specific buffer structure;
  *		"0" indicates the driver doesn't want to use a custom buffer
  *		structure type, so sizeof(struct vb2_buffer) will is used
+ * @gfp_flags:	additional gfp flags used when allocating the buffers.
+ *		Typically this is 0, but it may be e.g. GFP_DMA or __GFP_DMA32
+ *		to force the buffer allocation to a specific memory zone.
  *
  * @memory:	current memory type used
  * @bufs:	videobuf buffer structures
@@ -326,6 +331,8 @@ struct vb2_queue {
 	const struct vb2_mem_ops	*mem_ops;
 	void				*drv_priv;
 	unsigned int			buf_struct_size;
+	u32				timestamp_type;
+	gfp_t				gfp_flags;
 
 /* private: internal use only */
 	enum v4l2_memory		memory;
diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
index 9531bee..591fee7 100644
--- a/include/net/bluetooth/bluetooth.h
+++ b/include/net/bluetooth/bluetooth.h
@@ -232,7 +232,7 @@ struct bt_sock_list {
 };
 
 int  bt_sock_register(int proto, const struct net_proto_family *ops);
-int  bt_sock_unregister(int proto);
+void 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,
@@ -260,12 +260,23 @@ struct l2cap_ctrl {
 	__u8		retries;
 };
 
+struct hci_dev;
+
+typedef void (*hci_req_complete_t)(struct hci_dev *hdev, u8 status);
+
+struct hci_req_ctrl {
+	bool			start;
+	u8			event;
+	hci_req_complete_t	complete;
+};
+
 struct bt_skb_cb {
 	__u8 pkt_type;
 	__u8 incoming;
 	__u16 expect;
 	__u8 force_active;
 	struct l2cap_ctrl control;
+	struct hci_req_ctrl req;
 };
 #define bt_cb(skb) ((struct bt_skb_cb *)((skb)->cb))
 
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 7f12c25f..b330892 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -119,10 +119,16 @@ enum {
 	HCI_CONNECTABLE,
 	HCI_DISCOVERABLE,
 	HCI_LINK_SECURITY,
-	HCI_PENDING_CLASS,
 	HCI_PERIODIC_INQ,
+	HCI_FAST_CONNECTABLE,
 };
 
+/* A mask for the flags that are supposed to remain when a reset happens
+ * or the HCI device is closed.
+ */
+#define HCI_PERSISTENT_MASK (BIT(HCI_LE_SCAN) | BIT(HCI_PERIODIC_INQ) | \
+			      BIT(HCI_FAST_CONNECTABLE))
+
 /* HCI ioctl defines */
 #define HCIDEVUP	_IOW('H', 201, int)
 #define HCIDEVDOWN	_IOW('H', 202, int)
@@ -881,12 +887,25 @@ struct hci_rp_read_data_block_size {
 	__le16   num_blocks;
 } __packed;
 
+#define HCI_OP_READ_PAGE_SCAN_ACTIVITY	0x0c1b
+struct hci_rp_read_page_scan_activity {
+	__u8     status;
+	__le16   interval;
+	__le16   window;
+} __packed;
+
 #define HCI_OP_WRITE_PAGE_SCAN_ACTIVITY	0x0c1c
 struct hci_cp_write_page_scan_activity {
 	__le16   interval;
 	__le16   window;
 } __packed;
 
+#define HCI_OP_READ_PAGE_SCAN_TYPE	0x0c46
+struct hci_rp_read_page_scan_type {
+	__u8     status;
+	__u8     type;
+} __packed;
+
 #define HCI_OP_WRITE_PAGE_SCAN_TYPE	0x0c47
 	#define PAGE_SCAN_TYPE_STANDARD		0x00
 	#define PAGE_SCAN_TYPE_INTERLACED	0x01
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 90cf75a..d4e13bf 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -165,6 +165,10 @@ struct hci_dev {
 	__u16		voice_setting;
 	__u8		io_capability;
 	__s8		inq_tx_power;
+	__u16		page_scan_interval;
+	__u16		page_scan_window;
+	__u8		page_scan_type;
+
 	__u16		devid_source;
 	__u16		devid_vendor;
 	__u16		devid_product;
@@ -240,6 +244,7 @@ struct hci_dev {
 	struct sk_buff_head	raw_q;
 	struct sk_buff_head	cmd_q;
 
+	struct sk_buff		*recv_evt;
 	struct sk_buff		*sent_cmd;
 	struct sk_buff		*reassembly[NUM_REASSEMBLY];
 
@@ -248,8 +253,6 @@ struct hci_dev {
 	__u32			req_status;
 	__u32			req_result;
 
-	__u16			init_last_cmd;
-
 	struct list_head	mgmt_pending;
 
 	struct discovery_state	discovery;
@@ -266,8 +269,6 @@ struct hci_dev {
 
 	struct hci_dev_stats	stat;
 
-	struct sk_buff_head	driver_init;
-
 	atomic_t		promisc;
 
 	struct dentry		*debugfs;
@@ -290,6 +291,7 @@ struct hci_dev {
 	int (*open)(struct hci_dev *hdev);
 	int (*close)(struct hci_dev *hdev);
 	int (*flush)(struct hci_dev *hdev);
+	int (*setup)(struct hci_dev *hdev);
 	int (*send)(struct sk_buff *skb);
 	void (*notify)(struct hci_dev *hdev, unsigned int evt);
 	int (*ioctl)(struct hci_dev *hdev, unsigned int cmd, unsigned long arg);
@@ -574,7 +576,7 @@ static inline struct hci_conn *hci_conn_hash_lookup_state(struct hci_dev *hdev,
 	return NULL;
 }
 
-void hci_acl_disconn(struct hci_conn *conn, __u8 reason);
+void hci_disconnect(struct hci_conn *conn, __u8 reason);
 void hci_setup_sync(struct hci_conn *conn, __u16 handle);
 void hci_sco_setup(struct hci_conn *conn, __u8 status);
 
@@ -742,8 +744,6 @@ 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);
 
-int hci_update_ad(struct hci_dev *hdev);
-
 void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb);
 
 int hci_recv_frame(struct sk_buff *skb);
@@ -1041,6 +1041,28 @@ static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
 int hci_register_cb(struct hci_cb *hcb);
 int hci_unregister_cb(struct hci_cb *hcb);
 
+struct hci_request {
+	struct hci_dev		*hdev;
+	struct sk_buff_head	cmd_q;
+
+	/* If something goes wrong when building the HCI request, the error
+	 * value is stored in this field.
+	 */
+	int			err;
+};
+
+void hci_req_init(struct hci_request *req, struct hci_dev *hdev);
+int hci_req_run(struct hci_request *req, hci_req_complete_t complete);
+void hci_req_add(struct hci_request *req, u16 opcode, u32 plen, void *param);
+void hci_req_add_ev(struct hci_request *req, u16 opcode, u32 plen, void *param,
+		    u8 event);
+void hci_req_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 status);
+
+struct sk_buff *__hci_cmd_sync(struct hci_dev *hdev, u16 opcode, u32 plen,
+			       void *param, u32 timeout);
+struct sk_buff *__hci_cmd_sync_ev(struct hci_dev *hdev, u16 opcode, u32 plen,
+				  void *param, u8 event, u32 timeout);
+
 int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param);
 void hci_send_acl(struct hci_chan *chan, struct sk_buff *skb, __u16 flags);
 void hci_send_sco(struct hci_conn *conn, struct sk_buff *skb);
@@ -1153,7 +1175,7 @@ struct hci_sec_filter {
 #define hci_req_lock(d)		mutex_lock(&d->req_lock)
 #define hci_req_unlock(d)	mutex_unlock(&d->req_lock)
 
-void hci_req_complete(struct hci_dev *hdev, __u16 cmd, int result);
+void hci_update_ad(struct hci_request *req);
 
 void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max,
 					u16 latency, u16 to_multiplier);
diff --git a/include/net/bluetooth/rfcomm.h b/include/net/bluetooth/rfcomm.h
index e2e3eca..7afd419 100644
--- a/include/net/bluetooth/rfcomm.h
+++ b/include/net/bluetooth/rfcomm.h
@@ -158,7 +158,6 @@ struct rfcomm_session {
 	struct timer_list timer;
 	unsigned long    state;
 	unsigned long    flags;
-	atomic_t         refcnt;
 	int              initiator;
 
 	/* Default DLC parameters */
@@ -276,11 +275,6 @@ static inline void rfcomm_dlc_unthrottle(struct rfcomm_dlc *d)
 void   rfcomm_session_getaddr(struct rfcomm_session *s, bdaddr_t *src,
 								bdaddr_t *dst);
 
-static inline void rfcomm_session_hold(struct rfcomm_session *s)
-{
-	atomic_inc(&s->refcnt);
-}
-
 /* ---- RFCOMM sockets ---- */
 struct sockaddr_rc {
 	sa_family_t	rc_family;
diff --git a/include/net/caif/caif_shm.h b/include/net/caif/caif_shm.h
deleted file mode 100644
index 5bcce55..0000000
--- a/include/net/caif/caif_shm.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson AB 2010
- * Contact: Sjur Brendeland / sjur.brandeland@stericsson.com
- * Author: Amarnath Revanna / amarnath.bangalore.revanna@stericsson.com
- * License terms: GNU General Public License (GPL) version 2
- */
-
-#ifndef CAIF_SHM_H_
-#define CAIF_SHM_H_
-
-struct shmdev_layer {
-	u32 shm_base_addr;
-	u32 shm_total_sz;
-	u32 shm_id;
-	u32 shm_loopback;
-	void *hmbx;
-	int (*pshmdev_mbxsend) (u32 shm_id, u32 mbx_msg);
-	int (*pshmdev_mbxsetup) (void *pshmdrv_cb,
-				struct shmdev_layer *pshm_dev, void *pshm_drv);
-	struct net_device *pshm_netdev;
-};
-
-extern int caif_shmcore_probe(struct shmdev_layer *pshm_dev);
-extern void caif_shmcore_remove(struct net_device *pshm_netdev);
-
-#endif
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index d581c6d..bdba9b6 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -611,22 +611,10 @@ struct cfg80211_ap_settings {
 };
 
 /**
- * enum plink_action - actions to perform in mesh peers
- *
- * @PLINK_ACTION_INVALID: action 0 is reserved
- * @PLINK_ACTION_OPEN: start mesh peer link establishment
- * @PLINK_ACTION_BLOCK: block traffic from this mesh peer
- */
-enum plink_actions {
-	PLINK_ACTION_INVALID,
-	PLINK_ACTION_OPEN,
-	PLINK_ACTION_BLOCK,
-};
-
-/**
  * enum station_parameters_apply_mask - station parameter values to apply
  * @STATION_PARAM_APPLY_UAPSD: apply new uAPSD parameters (uapsd_queues, max_sp)
  * @STATION_PARAM_APPLY_CAPABILITY: apply new capability
+ * @STATION_PARAM_APPLY_PLINK_STATE: apply new plink state
  *
  * Not all station parameters have in-band "no change" signalling,
  * for those that don't these flags will are used.
@@ -634,6 +622,7 @@ enum plink_actions {
 enum station_parameters_apply_mask {
 	STATION_PARAM_APPLY_UAPSD = BIT(0),
 	STATION_PARAM_APPLY_CAPABILITY = BIT(1),
+	STATION_PARAM_APPLY_PLINK_STATE = BIT(2),
 };
 
 /**
@@ -669,7 +658,7 @@ enum station_parameters_apply_mask {
  * @ext_capab_len: number of extended capabilities
  */
 struct station_parameters {
-	u8 *supported_rates;
+	const u8 *supported_rates;
 	struct net_device *vlan;
 	u32 sta_flags_mask, sta_flags_set;
 	u32 sta_modify_mask;
@@ -678,17 +667,60 @@ struct station_parameters {
 	u8 supported_rates_len;
 	u8 plink_action;
 	u8 plink_state;
-	struct ieee80211_ht_cap *ht_capa;
-	struct ieee80211_vht_cap *vht_capa;
+	const struct ieee80211_ht_cap *ht_capa;
+	const struct ieee80211_vht_cap *vht_capa;
 	u8 uapsd_queues;
 	u8 max_sp;
 	enum nl80211_mesh_power_mode local_pm;
 	u16 capability;
-	u8 *ext_capab;
+	const u8 *ext_capab;
 	u8 ext_capab_len;
 };
 
 /**
+ * enum cfg80211_station_type - the type of station being modified
+ * @CFG80211_STA_AP_CLIENT: client of an AP interface
+ * @CFG80211_STA_AP_MLME_CLIENT: client of an AP interface that has
+ *	the AP MLME in the device
+ * @CFG80211_STA_AP_STA: AP station on managed interface
+ * @CFG80211_STA_IBSS: IBSS station
+ * @CFG80211_STA_TDLS_PEER_SETUP: TDLS peer on managed interface (dummy entry
+ *	while TDLS setup is in progress, it moves out of this state when
+ *	being marked authorized; use this only if TDLS with external setup is
+ *	supported/used)
+ * @CFG80211_STA_TDLS_PEER_ACTIVE: TDLS peer on managed interface (active
+ *	entry that is operating, has been marked authorized by userspace)
+ * @CFG80211_STA_MESH_PEER_KERNEL: peer on mesh interface (kernel managed)
+ * @CFG80211_STA_MESH_PEER_USER: peer on mesh interface (user managed)
+ */
+enum cfg80211_station_type {
+	CFG80211_STA_AP_CLIENT,
+	CFG80211_STA_AP_MLME_CLIENT,
+	CFG80211_STA_AP_STA,
+	CFG80211_STA_IBSS,
+	CFG80211_STA_TDLS_PEER_SETUP,
+	CFG80211_STA_TDLS_PEER_ACTIVE,
+	CFG80211_STA_MESH_PEER_KERNEL,
+	CFG80211_STA_MESH_PEER_USER,
+};
+
+/**
+ * cfg80211_check_station_change - validate parameter changes
+ * @wiphy: the wiphy this operates on
+ * @params: the new parameters for a station
+ * @statype: the type of station being modified
+ *
+ * Utility function for the @change_station driver method. Call this function
+ * with the appropriate station type looking up the station (and checking that
+ * it exists). It will verify whether the station change is acceptable, and if
+ * not will return an error code. Note that it may modify the parameters for
+ * backward compatibility reasons, so don't use them before calling this.
+ */
+int cfg80211_check_station_change(struct wiphy *wiphy,
+				  struct station_parameters *params,
+				  enum cfg80211_station_type statype);
+
+/**
  * enum station_info_flags - station information flags
  *
  * Used by the driver to indicate which info in &struct station_info
@@ -1119,6 +1151,7 @@ struct mesh_config {
  * @ie_len: length of vendor information elements
  * @is_authenticated: this mesh requires authentication
  * @is_secure: this mesh uses security
+ * @user_mpm: userspace handles all MPM functions
  * @dtim_period: DTIM period to use
  * @beacon_interval: beacon interval to use
  * @mcast_rate: multicat rate for Mesh Node [6Mbps is the default for 802.11a]
@@ -1136,6 +1169,7 @@ struct mesh_setup {
 	u8 ie_len;
 	bool is_authenticated;
 	bool is_secure;
+	bool user_mpm;
 	u8 dtim_period;
 	u16 beacon_interval;
 	int mcast_rate[IEEE80211_NUM_BANDS];
@@ -1398,9 +1432,11 @@ struct cfg80211_auth_request {
  * enum cfg80211_assoc_req_flags - Over-ride default behaviour in association.
  *
  * @ASSOC_REQ_DISABLE_HT:  Disable HT (802.11n)
+ * @ASSOC_REQ_DISABLE_VHT:  Disable VHT
  */
 enum cfg80211_assoc_req_flags {
 	ASSOC_REQ_DISABLE_HT		= BIT(0),
+	ASSOC_REQ_DISABLE_VHT		= BIT(1),
 };
 
 /**
@@ -1422,6 +1458,8 @@ enum cfg80211_assoc_req_flags {
  * @ht_capa:  HT Capabilities over-rides.  Values set in ht_capa_mask
  *   will be used in ht_capa.  Un-supported values will be ignored.
  * @ht_capa_mask:  The bits of ht_capa which are to be used.
+ * @vht_capa: VHT capability override
+ * @vht_capa_mask: VHT capability mask indicating which fields to use
  */
 struct cfg80211_assoc_request {
 	struct cfg80211_bss *bss;
@@ -1432,6 +1470,7 @@ struct cfg80211_assoc_request {
 	u32 flags;
 	struct ieee80211_ht_cap ht_capa;
 	struct ieee80211_ht_cap ht_capa_mask;
+	struct ieee80211_vht_cap vht_capa, vht_capa_mask;
 };
 
 /**
@@ -1542,6 +1581,8 @@ struct cfg80211_ibss_params {
  * @ht_capa:  HT Capabilities over-rides.  Values set in ht_capa_mask
  *   will be used in ht_capa.  Un-supported values will be ignored.
  * @ht_capa_mask:  The bits of ht_capa which are to be used.
+ * @vht_capa:  VHT Capability overrides
+ * @vht_capa_mask: The bits of vht_capa which are to be used.
  */
 struct cfg80211_connect_params {
 	struct ieee80211_channel *channel;
@@ -1560,6 +1601,8 @@ struct cfg80211_connect_params {
 	int bg_scan_period;
 	struct ieee80211_ht_cap ht_capa;
 	struct ieee80211_ht_cap ht_capa_mask;
+	struct ieee80211_vht_cap vht_capa;
+	struct ieee80211_vht_cap vht_capa_mask;
 };
 
 /**
@@ -1722,6 +1765,21 @@ struct cfg80211_gtk_rekey_data {
 };
 
 /**
+ * struct cfg80211_update_ft_ies_params - FT IE Information
+ *
+ * This structure provides information needed to update the fast transition IE
+ *
+ * @md: The Mobility Domain ID, 2 Octet value
+ * @ie: Fast Transition IEs
+ * @ie_len: Length of ft_ie in octets
+ */
+struct cfg80211_update_ft_ies_params {
+	u16 md;
+	const u8 *ie;
+	size_t ie_len;
+};
+
+/**
  * struct cfg80211_ops - backend description for wireless configuration
  *
  * This struct is registered by fullmac card drivers and/or wireless stacks
@@ -1781,9 +1839,8 @@ struct cfg80211_gtk_rekey_data {
  * @change_station: Modify a given station. Note that flags changes are not much
  *	validated in cfg80211, in particular the auth/assoc/authorized flags
  *	might come to the driver in invalid combinations -- make sure to check
- *	them, also against the existing state! Also, supported_rates changes are
- *	not checked in station mode -- drivers need to reject (or ignore) them
- *	for anything but TDLS peers.
+ *	them, also against the existing state! Drivers must call
+ *	cfg80211_check_station_change() to validate the information.
  * @get_station: get station information for the station identified by @mac
  * @dump_station: dump station callback -- resume dump at index @idx
  *
@@ -2168,6 +2225,8 @@ struct cfg80211_ops {
 	int	(*start_radar_detection)(struct wiphy *wiphy,
 					 struct net_device *dev,
 					 struct cfg80211_chan_def *chandef);
+	int	(*update_ft_ies)(struct wiphy *wiphy, struct net_device *dev,
+				 struct cfg80211_update_ft_ies_params *ftie);
 };
 
 /*
@@ -2485,6 +2544,8 @@ struct wiphy_wowlan_support {
  * @ap_sme_capa: AP SME capabilities, flags from &enum nl80211_ap_sme_features.
  * @ht_capa_mod_mask:  Specify what ht_cap values can be over-ridden.
  *	If null, then none can be over-ridden.
+ * @vht_capa_mod_mask:  Specify what VHT capabilities can be over-ridden.
+ *	If null, then none can be over-ridden.
  *
  * @max_acl_mac_addrs: Maximum number of MAC addresses that the device
  *	supports for ACL.
@@ -2593,6 +2654,7 @@ struct wiphy {
 	struct dentry *debugfsdir;
 
 	const struct ieee80211_ht_cap *ht_capa_mod_mask;
+	const struct ieee80211_vht_cap *vht_capa_mod_mask;
 
 #ifdef CONFIG_NET_NS
 	/* the network namespace this phy lives in currently */
@@ -4002,6 +4064,30 @@ u32 cfg80211_calculate_bitrate(struct rate_info *rate);
 void cfg80211_unregister_wdev(struct wireless_dev *wdev);
 
 /**
+ * struct cfg80211_ft_event - FT Information Elements
+ * @ies: FT IEs
+ * @ies_len: length of the FT IE in bytes
+ * @target_ap: target AP's MAC address
+ * @ric_ies: RIC IE
+ * @ric_ies_len: length of the RIC IE in bytes
+ */
+struct cfg80211_ft_event_params {
+	const u8 *ies;
+	size_t ies_len;
+	const u8 *target_ap;
+	const u8 *ric_ies;
+	size_t ric_ies_len;
+};
+
+/**
+ * cfg80211_ft_event - notify userspace about FT IE and RIC IE
+ * @netdev: network device
+ * @ft_event: IE information
+ */
+void cfg80211_ft_event(struct net_device *netdev,
+		       struct cfg80211_ft_event_params *ft_event);
+
+/**
  * cfg80211_get_p2p_attr - find and copy a P2P attribute from IE buffer
  * @ies: the input IE buffer
  * @len: the input length
diff --git a/include/net/dn_fib.h b/include/net/dn_fib.h
index 1ee9d4b..74004af 100644
--- a/include/net/dn_fib.h
+++ b/include/net/dn_fib.h
@@ -1,24 +1,9 @@
 #ifndef _NET_DN_FIB_H
 #define _NET_DN_FIB_H
 
-/* WARNING: The ordering of these elements must match ordering
- *          of RTA_* rtnetlink attribute numbers.
- */
-struct dn_kern_rta {
-        void            *rta_dst;
-        void            *rta_src;
-        int             *rta_iif;
-        int             *rta_oif;
-        void            *rta_gw;
-        u32             *rta_priority;
-        void            *rta_prefsrc;
-        struct rtattr   *rta_mx;
-        struct rtattr   *rta_mp;
-        unsigned char   *rta_protoinfo;
-        u32             *rta_flow;
-        struct rta_cacheinfo *rta_ci;
-	struct rta_session *rta_sess;
-};
+#include <linux/netlink.h>
+
+extern const struct nla_policy rtm_dn_policy[];
 
 struct dn_fib_res {
 	struct fib_rule *r;
@@ -93,10 +78,10 @@ struct dn_fib_table {
 	u32 n;
 
 	int (*insert)(struct dn_fib_table *t, struct rtmsg *r, 
-			struct dn_kern_rta *rta, struct nlmsghdr *n, 
+			struct nlattr *attrs[], struct nlmsghdr *n,
 			struct netlink_skb_parms *req);
 	int (*delete)(struct dn_fib_table *t, struct rtmsg *r,
-			struct dn_kern_rta *rta, struct nlmsghdr *n,
+			struct nlattr *attrs[], struct nlmsghdr *n,
 			struct netlink_skb_parms *req);
 	int (*lookup)(struct dn_fib_table *t, const struct flowidn *fld,
 			struct dn_fib_res *res);
@@ -116,13 +101,12 @@ extern void dn_fib_cleanup(void);
 extern int dn_fib_ioctl(struct socket *sock, unsigned int cmd, 
 			unsigned long arg);
 extern struct dn_fib_info *dn_fib_create_info(const struct rtmsg *r, 
-				struct dn_kern_rta *rta, 
+				struct nlattr *attrs[],
 				const struct nlmsghdr *nlh, int *errp);
 extern int dn_fib_semantic_match(int type, struct dn_fib_info *fi, 
 			const struct flowidn *fld,
 			struct dn_fib_res *res);
 extern void dn_fib_release_info(struct dn_fib_info *fi);
-extern __le16 dn_fib_get_attr16(struct rtattr *attr, int attrlen, int type);
 extern void dn_fib_flush(void);
 extern void dn_fib_select_multipath(const struct flowidn *fld,
 					struct dn_fib_res *res);
diff --git a/include/net/firewire.h b/include/net/firewire.h
new file mode 100644
index 0000000..31bcbfe
--- /dev/null
+++ b/include/net/firewire.h
@@ -0,0 +1,25 @@
+#ifndef _NET_FIREWIRE_H
+#define _NET_FIREWIRE_H
+
+/* Pseudo L2 address */
+#define FWNET_ALEN	16
+union fwnet_hwaddr {
+	u8 u[FWNET_ALEN];
+	/* "Hardware address" defined in RFC2734/RF3146 */
+	struct {
+		__be64 uniq_id;		/* EUI-64			*/
+		u8 max_rec;		/* max packet size		*/
+		u8 sspd;		/* max speed			*/
+		__be16 fifo_hi;		/* hi 16bits of FIFO addr	*/
+		__be32 fifo_lo;		/* lo 32bits of FIFO addr	*/
+	} __packed uc;
+};
+
+/* Pseudo L2 Header */
+#define FWNET_HLEN	18
+struct fwnet_header {
+	u8 h_dest[FWNET_ALEN];	/* destination address */
+	__be16 h_proto;		/* packet type ID field */
+} __packed;
+
+#endif
diff --git a/include/net/gre.h b/include/net/gre.h
index 8266547..9f03a39 100644
--- a/include/net/gre.h
+++ b/include/net/gre.h
@@ -2,6 +2,7 @@
 #define __LINUX_GRE_H
 
 #include <linux/skbuff.h>
+#include <net/ip_tunnels.h>
 
 #define GREPROTO_CISCO		0
 #define GREPROTO_PPTP		1
@@ -12,7 +13,57 @@ struct gre_protocol {
 	void (*err_handler)(struct sk_buff *skb, u32 info);
 };
 
+struct gre_base_hdr {
+	__be16 flags;
+	__be16 protocol;
+};
+#define GRE_HEADER_SECTION 4
+
 int gre_add_protocol(const struct gre_protocol *proto, u8 version);
 int gre_del_protocol(const struct gre_protocol *proto, u8 version);
 
+static inline __be16 gre_flags_to_tnl_flags(__be16 flags)
+{
+	__be16 tflags = 0;
+
+	if (flags & GRE_CSUM)
+		tflags |= TUNNEL_CSUM;
+	if (flags & GRE_ROUTING)
+		tflags |= TUNNEL_ROUTING;
+	if (flags & GRE_KEY)
+		tflags |= TUNNEL_KEY;
+	if (flags & GRE_SEQ)
+		tflags |= TUNNEL_SEQ;
+	if (flags & GRE_STRICT)
+		tflags |= TUNNEL_STRICT;
+	if (flags & GRE_REC)
+		tflags |= TUNNEL_REC;
+	if (flags & GRE_VERSION)
+		tflags |= TUNNEL_VERSION;
+
+	return tflags;
+}
+
+static inline __be16 tnl_flags_to_gre_flags(__be16 tflags)
+{
+	__be16 flags = 0;
+
+	if (tflags & TUNNEL_CSUM)
+		flags |= GRE_CSUM;
+	if (tflags & TUNNEL_ROUTING)
+		flags |= GRE_ROUTING;
+	if (tflags & TUNNEL_KEY)
+		flags |= GRE_KEY;
+	if (tflags & TUNNEL_SEQ)
+		flags |= GRE_SEQ;
+	if (tflags & TUNNEL_STRICT)
+		flags |= GRE_STRICT;
+	if (tflags & TUNNEL_REC)
+		flags |= GRE_REC;
+	if (tflags & TUNNEL_VERSION)
+		flags |= GRE_VERSION;
+
+	return flags;
+}
+
 #endif
diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h
index 1832927..de2c785 100644
--- a/include/net/inet_connection_sock.h
+++ b/include/net/inet_connection_sock.h
@@ -133,6 +133,8 @@ struct inet_connection_sock {
 #define ICSK_TIME_RETRANS	1	/* Retransmit timer */
 #define ICSK_TIME_DACK		2	/* Delayed ack timer */
 #define ICSK_TIME_PROBE0	3	/* Zero window probe timer */
+#define ICSK_TIME_EARLY_RETRANS 4	/* Early retransmit timer */
+#define ICSK_TIME_LOSS_PROBE	5	/* Tail loss probe timer */
 
 static inline struct inet_connection_sock *inet_csk(const struct sock *sk)
 {
@@ -222,7 +224,8 @@ static inline void inet_csk_reset_xmit_timer(struct sock *sk, const int what,
 		when = max_when;
 	}
 
-	if (what == ICSK_TIME_RETRANS || what == ICSK_TIME_PROBE0) {
+	if (what == ICSK_TIME_RETRANS || what == ICSK_TIME_PROBE0 ||
+	    what == ICSK_TIME_EARLY_RETRANS || what ==  ICSK_TIME_LOSS_PROBE) {
 		icsk->icsk_pending = what;
 		icsk->icsk_timeout = jiffies + when;
 		sk_reset_timer(sk, &icsk->icsk_retransmit_timer, icsk->icsk_timeout);
diff --git a/include/net/inet_frag.h b/include/net/inet_frag.h
index 0a1dcc2..6f41b45 100644
--- a/include/net/inet_frag.h
+++ b/include/net/inet_frag.h
@@ -50,10 +50,16 @@ struct inet_frag_queue {
  */
 #define INETFRAGS_MAXDEPTH		128
 
+struct inet_frag_bucket {
+	struct hlist_head	chain;
+	spinlock_t		chain_lock;
+};
+
 struct inet_frags {
-	struct hlist_head	hash[INETFRAGS_HASHSZ];
+	struct inet_frag_bucket	hash[INETFRAGS_HASHSZ];
 	/* This rwlock is a global lock (seperate per IPv4, IPv6 and
 	 * netfilter). Important to keep this on a seperate cacheline.
+	 * Its primarily a rebuild protection rwlock.
 	 */
 	rwlock_t		lock ____cacheline_aligned_in_smp;
 	int			secret_interval;
@@ -143,6 +149,7 @@ static inline void inet_frag_lru_del(struct inet_frag_queue *q)
 {
 	spin_lock(&q->net->lru_lock);
 	list_del(&q->lru_list);
+	q->net->nqueues--;
 	spin_unlock(&q->net->lru_lock);
 }
 
@@ -151,6 +158,19 @@ static inline void inet_frag_lru_add(struct netns_frags *nf,
 {
 	spin_lock(&nf->lru_lock);
 	list_add_tail(&q->lru_list, &nf->lru_list);
+	q->net->nqueues++;
 	spin_unlock(&nf->lru_lock);
 }
+
+/* RFC 3168 support :
+ * We want to check ECN values of all fragments, do detect invalid combinations.
+ * In ipq->ecn, we store the OR value of each ip4_frag_ecn() fragment value.
+ */
+#define	IPFRAG_ECN_NOT_ECT	0x01 /* one frag had ECN_NOT_ECT */
+#define	IPFRAG_ECN_ECT_1	0x02 /* one frag had ECN_ECT_1 */
+#define	IPFRAG_ECN_ECT_0	0x04 /* one frag had ECN_ECT_0 */
+#define	IPFRAG_ECN_CE		0x08 /* one frag had ECN_CE */
+
+extern const u8 ip_frag_ecn_table[16];
+
 #endif
diff --git a/include/net/ip6_tunnel.h b/include/net/ip6_tunnel.h
index e03047f..4da5de1 100644
--- a/include/net/ip6_tunnel.h
+++ b/include/net/ip6_tunnel.h
@@ -3,6 +3,7 @@
 
 #include <linux/ipv6.h>
 #include <linux/netdevice.h>
+#include <linux/if_tunnel.h>
 #include <linux/ip6_tunnel.h>
 
 #define IP6TUNNEL_ERR_TIMEO (30*HZ)
@@ -68,4 +69,24 @@ __u16 ip6_tnl_parse_tlv_enc_lim(struct sk_buff *skb, __u8 *raw);
 __u32 ip6_tnl_get_cap(struct ip6_tnl *t, const struct in6_addr *laddr,
 			     const struct in6_addr *raddr);
 
+static inline void ip6tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct net_device_stats *stats = &dev->stats;
+	int pkt_len, err;
+
+	nf_reset(skb);
+	pkt_len = skb->len;
+	err = ip6_local_out(skb);
+
+	if (net_xmit_eval(err) == 0) {
+		struct pcpu_tstats *tstats = this_cpu_ptr(dev->tstats);
+		u64_stats_update_begin(&tstats->syncp);
+		tstats->tx_bytes += pkt_len;
+		tstats->tx_packets++;
+		u64_stats_update_end(&tstats->syncp);
+	} else {
+		stats->tx_errors++;
+		stats->tx_aborted_errors++;
+	}
+}
 #endif
diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h
new file mode 100644
index 0000000..4b6f0b2
--- /dev/null
+++ b/include/net/ip_tunnels.h
@@ -0,0 +1,177 @@
+#ifndef __NET_IP_TUNNELS_H
+#define __NET_IP_TUNNELS_H 1
+
+#include <linux/if_tunnel.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/types.h>
+#include <linux/u64_stats_sync.h>
+#include <net/dsfield.h>
+#include <net/gro_cells.h>
+#include <net/inet_ecn.h>
+#include <net/ip.h>
+#include <net/rtnetlink.h>
+
+#if IS_ENABLED(CONFIG_IPV6)
+#include <net/ipv6.h>
+#include <net/ip6_fib.h>
+#include <net/ip6_route.h>
+#endif
+
+/* Keep error state on tunnel for 30 sec */
+#define IPTUNNEL_ERR_TIMEO	(30*HZ)
+
+/* 6rd prefix/relay information */
+#ifdef CONFIG_IPV6_SIT_6RD
+struct ip_tunnel_6rd_parm {
+	struct in6_addr		prefix;
+	__be32			relay_prefix;
+	u16			prefixlen;
+	u16			relay_prefixlen;
+};
+#endif
+
+struct ip_tunnel_prl_entry {
+	struct ip_tunnel_prl_entry __rcu *next;
+	__be32				addr;
+	u16				flags;
+	struct rcu_head			rcu_head;
+};
+
+struct ip_tunnel {
+	struct ip_tunnel __rcu	*next;
+	struct hlist_node hash_node;
+	struct net_device	*dev;
+
+	int		err_count;	/* Number of arrived ICMP errors */
+	unsigned long	err_time;	/* Time when the last ICMP error
+					 * arrived */
+
+	/* These four fields used only by GRE */
+	__u32		i_seqno;	/* The last seen seqno	*/
+	__u32		o_seqno;	/* The last output seqno */
+	int		hlen;		/* Precalculated header length */
+	int		mlink;
+
+	struct ip_tunnel_parm parms;
+
+	/* for SIT */
+#ifdef CONFIG_IPV6_SIT_6RD
+	struct ip_tunnel_6rd_parm ip6rd;
+#endif
+	struct ip_tunnel_prl_entry __rcu *prl;	/* potential router list */
+	unsigned int		prl_count;	/* # of entries in PRL */
+	int			ip_tnl_net_id;
+	struct gro_cells	gro_cells;
+};
+
+#define TUNNEL_CSUM	__cpu_to_be16(0x01)
+#define TUNNEL_ROUTING	__cpu_to_be16(0x02)
+#define TUNNEL_KEY	__cpu_to_be16(0x04)
+#define TUNNEL_SEQ	__cpu_to_be16(0x08)
+#define TUNNEL_STRICT	__cpu_to_be16(0x10)
+#define TUNNEL_REC	__cpu_to_be16(0x20)
+#define TUNNEL_VERSION	__cpu_to_be16(0x40)
+#define TUNNEL_NO_KEY	__cpu_to_be16(0x80)
+
+struct tnl_ptk_info {
+	__be16 flags;
+	__be16 proto;
+	__be32 key;
+	__be32 seq;
+};
+
+#define PACKET_RCVD	0
+#define PACKET_REJECT	1
+
+#define IP_TNL_HASH_BITS   10
+#define IP_TNL_HASH_SIZE   (1 << IP_TNL_HASH_BITS)
+
+struct ip_tunnel_net {
+	struct hlist_head *tunnels;
+	struct net_device *fb_tunnel_dev;
+};
+
+int ip_tunnel_init(struct net_device *dev);
+void ip_tunnel_uninit(struct net_device *dev);
+void  ip_tunnel_dellink(struct net_device *dev, struct list_head *head);
+int __net_init ip_tunnel_init_net(struct net *net, int ip_tnl_net_id,
+				  struct rtnl_link_ops *ops, char *devname);
+
+void __net_exit ip_tunnel_delete_net(struct ip_tunnel_net *itn);
+
+void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
+		    const struct iphdr *tnl_params);
+int ip_tunnel_ioctl(struct net_device *dev, struct ip_tunnel_parm *p, int cmd);
+int ip_tunnel_change_mtu(struct net_device *dev, int new_mtu);
+
+struct rtnl_link_stats64 *ip_tunnel_get_stats64(struct net_device *dev,
+						struct rtnl_link_stats64 *tot);
+struct ip_tunnel *ip_tunnel_lookup(struct ip_tunnel_net *itn,
+				   int link, __be16 flags,
+				   __be32 remote, __be32 local,
+				   __be32 key);
+
+int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb,
+		  const struct tnl_ptk_info *tpi, bool log_ecn_error);
+int ip_tunnel_changelink(struct net_device *dev, struct nlattr *tb[],
+			 struct ip_tunnel_parm *p);
+int ip_tunnel_newlink(struct net_device *dev, struct nlattr *tb[],
+		      struct ip_tunnel_parm *p);
+void ip_tunnel_setup(struct net_device *dev, int net_id);
+
+/* Extract dsfield from inner protocol */
+static inline u8 ip_tunnel_get_dsfield(const struct iphdr *iph,
+				       const struct sk_buff *skb)
+{
+	if (skb->protocol == htons(ETH_P_IP))
+		return iph->tos;
+	else if (skb->protocol == htons(ETH_P_IPV6))
+		return ipv6_get_dsfield((const struct ipv6hdr *)iph);
+	else
+		return 0;
+}
+
+/* Propogate ECN bits out */
+static inline u8 ip_tunnel_ecn_encap(u8 tos, const struct iphdr *iph,
+				     const struct sk_buff *skb)
+{
+	u8 inner = ip_tunnel_get_dsfield(iph, skb);
+
+	return INET_ECN_encapsulate(tos, inner);
+}
+
+static inline void tunnel_ip_select_ident(struct sk_buff *skb,
+					  const struct iphdr  *old_iph,
+					  struct dst_entry *dst)
+{
+	struct iphdr *iph = ip_hdr(skb);
+
+	/* Use inner packet iph-id if possible. */
+	if (skb->protocol == htons(ETH_P_IP) && old_iph->id)
+		iph->id	= old_iph->id;
+	else
+		__ip_select_ident(iph, dst,
+				  (skb_shinfo(skb)->gso_segs ?: 1) - 1);
+}
+
+static inline void iptunnel_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	int err;
+	int pkt_len = skb->len - skb_transport_offset(skb);
+	struct pcpu_tstats *tstats = this_cpu_ptr(dev->tstats);
+
+	nf_reset(skb);
+
+	err = ip_local_out(skb);
+	if (likely(net_xmit_eval(err) == 0)) {
+		u64_stats_update_begin(&tstats->syncp);
+		tstats->tx_bytes += pkt_len;
+		tstats->tx_packets++;
+		u64_stats_update_end(&tstats->syncp);
+	} else {
+		dev->stats.tx_errors++;
+		dev->stats.tx_aborted_errors++;
+	}
+}
+#endif /* __NET_IP_TUNNELS_H */
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index fce8e6b..85996db 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -459,7 +459,7 @@ struct ip_vs_estimator {
 struct ip_vs_stats {
 	struct ip_vs_stats_user	ustats;		/* statistics */
 	struct ip_vs_estimator	est;		/* estimator */
-	struct ip_vs_cpu_stats	*cpustats;	/* per cpu counters */
+	struct ip_vs_cpu_stats __percpu	*cpustats;	/* per cpu counters */
 	spinlock_t		lock;		/* spin lock */
 	struct ip_vs_stats_user	ustats0;	/* reset values */
 };
@@ -874,7 +874,7 @@ struct ip_vs_app {
 struct ipvs_master_sync_state {
 	struct list_head	sync_queue;
 	struct ip_vs_sync_buff	*sync_buff;
-	int			sync_queue_len;
+	unsigned long		sync_queue_len;
 	unsigned int		sync_queue_delay;
 	struct task_struct	*master_thread;
 	struct delayed_work	master_wakeup_work;
@@ -966,7 +966,7 @@ struct netns_ipvs {
 	int			sysctl_snat_reroute;
 	int			sysctl_sync_ver;
 	int			sysctl_sync_ports;
-	int			sysctl_sync_qlen_max;
+	unsigned long		sysctl_sync_qlen_max;
 	int			sysctl_sync_sock_size;
 	int			sysctl_cache_bypass;
 	int			sysctl_expire_nodest_conn;
@@ -1053,7 +1053,7 @@ static inline int sysctl_sync_ports(struct netns_ipvs *ipvs)
 	return ACCESS_ONCE(ipvs->sysctl_sync_ports);
 }
 
-static inline int sysctl_sync_qlen_max(struct netns_ipvs *ipvs)
+static inline unsigned long sysctl_sync_qlen_max(struct netns_ipvs *ipvs)
 {
 	return ipvs->sysctl_sync_qlen_max;
 }
@@ -1106,7 +1106,7 @@ static inline int sysctl_sync_ports(struct netns_ipvs *ipvs)
 	return 1;
 }
 
-static inline int sysctl_sync_qlen_max(struct netns_ipvs *ipvs)
+static inline unsigned long sysctl_sync_qlen_max(struct netns_ipvs *ipvs)
 {
 	return IPVS_SYNC_QLEN_MAX;
 }
diff --git a/include/net/ipip.h b/include/net/ipip.h
deleted file mode 100644
index 982141c..0000000
--- a/include/net/ipip.h
+++ /dev/null
@@ -1,87 +0,0 @@
-#ifndef __NET_IPIP_H
-#define __NET_IPIP_H 1
-
-#include <linux/if_tunnel.h>
-#include <net/gro_cells.h>
-#include <net/ip.h>
-
-/* Keep error state on tunnel for 30 sec */
-#define IPTUNNEL_ERR_TIMEO	(30*HZ)
-
-/* 6rd prefix/relay information */
-struct ip_tunnel_6rd_parm {
-	struct in6_addr		prefix;
-	__be32			relay_prefix;
-	u16			prefixlen;
-	u16			relay_prefixlen;
-};
-
-struct ip_tunnel {
-	struct ip_tunnel __rcu	*next;
-	struct net_device	*dev;
-
-	int			err_count;	/* Number of arrived ICMP errors */
-	unsigned long		err_time;	/* Time when the last ICMP error arrived */
-
-	/* These four fields used only by GRE */
-	__u32			i_seqno;	/* The last seen seqno	*/
-	__u32			o_seqno;	/* The last output seqno */
-	int			hlen;		/* Precalculated GRE header length */
-	int			mlink;
-
-	struct ip_tunnel_parm	parms;
-
-	/* for SIT */
-#ifdef CONFIG_IPV6_SIT_6RD
-	struct ip_tunnel_6rd_parm	ip6rd;
-#endif
-	struct ip_tunnel_prl_entry __rcu *prl;		/* potential router list */
-	unsigned int			prl_count;	/* # of entries in PRL */
-
-	struct gro_cells		gro_cells;
-};
-
-struct ip_tunnel_prl_entry {
-	struct ip_tunnel_prl_entry __rcu *next;
-	__be32				addr;
-	u16				flags;
-	struct rcu_head			rcu_head;
-};
-
-static inline void iptunnel_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	int err;
-	struct iphdr *iph = ip_hdr(skb);
-	int pkt_len = skb->len - skb_transport_offset(skb);
-	struct pcpu_tstats *tstats = this_cpu_ptr(dev->tstats);
-
-	nf_reset(skb);
-	skb->ip_summed = CHECKSUM_NONE;
-	ip_select_ident(iph, skb_dst(skb), NULL);
-
-	err = ip_local_out(skb);
-	if (likely(net_xmit_eval(err) == 0)) {
-		u64_stats_update_begin(&tstats->syncp);
-		tstats->tx_bytes += pkt_len;
-		tstats->tx_packets++;
-		u64_stats_update_end(&tstats->syncp);
-	} else {
-		dev->stats.tx_errors++;
-		dev->stats.tx_aborted_errors++;
-	}
-}
-
-static inline void tunnel_ip_select_ident(struct sk_buff *skb,
-					  const struct iphdr  *old_iph,
-					  struct dst_entry *dst)
-{
-	struct iphdr *iph = ip_hdr(skb);
-
-	/* Use inner packet iph-id if possible. */
-	if (skb->protocol == htons(ETH_P_IP) && old_iph->id)
-		iph->id	= old_iph->id;
-	else
-		__ip_select_ident(iph, dst,
-				  (skb_shinfo(skb)->gso_segs ?: 1) - 1);
-}
-#endif
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 64d12e7..0810aa5 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -217,7 +217,7 @@ struct ipv6_txoptions {
 };
 
 struct ip6_flowlabel {
-	struct ip6_flowlabel	*next;
+	struct ip6_flowlabel __rcu *next;
 	__be32			label;
 	atomic_t		users;
 	struct in6_addr		dst;
@@ -238,9 +238,9 @@ struct ip6_flowlabel {
 #define IPV6_FLOWLABEL_MASK	cpu_to_be32(0x000FFFFF)
 
 struct ipv6_fl_socklist {
-	struct ipv6_fl_socklist	*next;
-	struct ip6_flowlabel	*fl;
-	struct rcu_head		rcu;
+	struct ipv6_fl_socklist	__rcu	*next;
+	struct ip6_flowlabel		*fl;
+	struct rcu_head			rcu;
 };
 
 extern struct ip6_flowlabel	*fl6_sock_lookup(struct sock *sk, __be32 label);
@@ -320,6 +320,18 @@ static inline int ipv6_addr_src_scope(const struct in6_addr *addr)
 	return __ipv6_addr_src_scope(__ipv6_addr_type(addr));
 }
 
+static inline bool __ipv6_addr_needs_scope_id(int type)
+{
+	return type & IPV6_ADDR_LINKLOCAL ||
+	       (type & IPV6_ADDR_MULTICAST &&
+		(type & (IPV6_ADDR_LOOPBACK|IPV6_ADDR_LINKLOCAL)));
+}
+
+static inline __u32 ipv6_iface_scope_id(const struct in6_addr *addr, int iface)
+{
+	return __ipv6_addr_needs_scope_id(__ipv6_addr_type(addr)) ? iface : 0;
+}
+
 static inline int ipv6_addr_cmp(const struct in6_addr *a1, const struct in6_addr *a2)
 {
 	return memcmp(a1, a2, sizeof(struct in6_addr));
@@ -466,6 +478,7 @@ struct ip6_create_arg {
 	u32 user;
 	const struct in6_addr *src;
 	const struct in6_addr *dst;
+	u8 ecn;
 };
 
 void ip6_frag_init(struct inet_frag_queue *q, void *a);
@@ -485,6 +498,7 @@ struct frag_queue {
 	int			iif;
 	unsigned int		csum;
 	__u16			nhoffset;
+	u8			ecn;
 };
 
 void ip6_expire_frag_queue(struct net *net, struct frag_queue *fq,
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index f7eba13..dd73b8c 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -93,9 +93,11 @@ struct device;
  * enum ieee80211_max_queues - maximum number of queues
  *
  * @IEEE80211_MAX_QUEUES: Maximum number of regular device queues.
+ * @IEEE80211_MAX_QUEUE_MAP: bitmap with maximum queues set
  */
 enum ieee80211_max_queues {
 	IEEE80211_MAX_QUEUES =		16,
+	IEEE80211_MAX_QUEUE_MAP =	BIT(IEEE80211_MAX_QUEUES) - 1,
 };
 
 #define IEEE80211_INVAL_HW_QUEUE	0xff
@@ -1067,6 +1069,9 @@ enum ieee80211_vif_flags {
  *	path needing to access it; even though the netdev carrier will always
  *	be off when it is %NULL there can still be races and packets could be
  *	processed after it switches back to %NULL.
+ * @debugfs_dir: debugfs dentry, can be used by drivers to create own per
+ *      interface debug files. Note that it will be NULL for the virtual
+ *	monitor interface (if that is requested.)
  * @drv_priv: data area for driver use, will always be aligned to
  *	sizeof(void *).
  */
@@ -1083,6 +1088,10 @@ struct ieee80211_vif {
 
 	u32 driver_flags;
 
+#ifdef CONFIG_MAC80211_DEBUGFS
+	struct dentry *debugfs_dir;
+#endif
+
 	/* must be last */
 	u8 drv_priv[0] __aligned(sizeof(void *));
 };
@@ -1101,8 +1110,6 @@ static inline bool ieee80211_vif_is_mesh(struct ieee80211_vif *vif)
  * These flags are used for communication about keys between the driver
  * and mac80211, with the @flags parameter of &struct ieee80211_key_conf.
  *
- * @IEEE80211_KEY_FLAG_WMM_STA: Set by mac80211, this flag indicates
- *	that the STA this key will be used with could be using QoS.
  * @IEEE80211_KEY_FLAG_GENERATE_IV: This flag should be set by the
  *	driver to indicate that it requires IV generation for this
  *	particular key.
@@ -1127,7 +1134,6 @@ static inline bool ieee80211_vif_is_mesh(struct ieee80211_vif *vif)
  *	%IEEE80211_KEY_FLAG_SW_MGMT_TX flag to encrypt such frames in SW.
  */
 enum ieee80211_key_flags {
-	IEEE80211_KEY_FLAG_WMM_STA	= 1<<0,
 	IEEE80211_KEY_FLAG_GENERATE_IV	= 1<<1,
 	IEEE80211_KEY_FLAG_GENERATE_MMIC= 1<<2,
 	IEEE80211_KEY_FLAG_PAIRWISE	= 1<<3,
@@ -1231,9 +1237,8 @@ enum ieee80211_sta_rx_bandwidth {
  * @addr: MAC address
  * @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
- * @vht_cap: VHT capabilities of this STA; Not restricting any capabilities
- * 	of remote STA. Taking as is.
+ * @ht_cap: HT capabilities of this STA; restricted to our own capabilities
+ * @vht_cap: VHT capabilities of this STA; restricted to our own 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.
@@ -1950,14 +1955,14 @@ void ieee80211_free_txskb(struct ieee80211_hw *hw, struct sk_buff *skb);
  * filter those response frames except in the case of frames that
  * are buffered in the driver -- those must remain buffered to avoid
  * reordering. Because it is possible that no frames are released
- * in this case, the driver must call ieee80211_sta_eosp_irqsafe()
+ * in this case, the driver must call ieee80211_sta_eosp()
  * to indicate to mac80211 that the service period ended anyway.
  *
  * Finally, if frames from multiple TIDs are released from mac80211
  * but the driver might reorder them, it must clear & set the flags
  * appropriately (only the last frame may have %IEEE80211_TX_STATUS_EOSP)
  * and also take care of the EOSP and MORE_DATA bits in the frame.
- * The driver may also use ieee80211_sta_eosp_irqsafe() in this case.
+ * The driver may also use ieee80211_sta_eosp() in this case.
  */
 
 /**
@@ -2135,6 +2140,24 @@ enum ieee80211_rate_control_changed {
 };
 
 /**
+ * enum ieee80211_roc_type - remain on channel type
+ *
+ * With the support for multi channel contexts and multi channel operations,
+ * remain on channel operations might be limited/deferred/aborted by other
+ * flows/operations which have higher priority (and vise versa).
+ * Specifying the ROC type can be used by devices to prioritize the ROC
+ * operations compared to other operations/flows.
+ *
+ * @IEEE80211_ROC_TYPE_NORMAL: There are no special requirements for this ROC.
+ * @IEEE80211_ROC_TYPE_MGMT_TX: The remain on channel request is required
+ *	for sending managment frames offchannel.
+ */
+enum ieee80211_roc_type {
+	IEEE80211_ROC_TYPE_NORMAL = 0,
+	IEEE80211_ROC_TYPE_MGMT_TX,
+};
+
+/**
  * struct ieee80211_ops - callbacks from mac80211 to the driver
  *
  * This structure contains various callbacks that the driver may
@@ -2212,18 +2235,6 @@ enum ieee80211_rate_control_changed {
  *	MAC address of the device going away.
  *	Hence, this callback must be implemented. It can sleep.
  *
- * @add_interface_debugfs: Drivers can use this callback to add debugfs files
- *	when a vif is added to mac80211. This callback and
- *	@remove_interface_debugfs should be within a CONFIG_MAC80211_DEBUGFS
- *	conditional. @remove_interface_debugfs must be provided for cleanup.
- *	This callback can sleep.
- *
- * @remove_interface_debugfs: Remove the debugfs files which were added using
- *	@add_interface_debugfs. This callback must remove all debugfs entries
- *	that were added because mac80211 only removes interface debugfs when the
- *	interface is destroyed, not when it is removed from the driver.
- *	This callback can sleep.
- *
  * @config: Handler for configuration requests. IEEE 802.11 code calls this
  *	function to change hardware configuration, e.g., channel.
  *	This function should never fail but returns a negative error code
@@ -2245,6 +2256,9 @@ enum ieee80211_rate_control_changed {
  *	See the section "Frame filtering" for more information.
  *	This callback must be implemented and can sleep.
  *
+ * @set_multicast_list: Configure the device's interface specific RX multicast
+ *	filter. This callback is optional. This callback must be atomic.
+ *
  * @set_tim: Set TIM bit. mac80211 calls this function when a TIM bit
  * 	must be set or cleared for a given STA. Must be atomic.
  *
@@ -2426,8 +2440,11 @@ enum ieee80211_rate_control_changed {
  * @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
- *	to %true, pending frames may be dropped. The callback can sleep.
+ *	that the hardware queues are empty. The @queues parameter is a bitmap
+ *	of queues to flush, which is useful if different virtual interfaces
+ *	use different hardware queues; it may also indicate all queues.
+ *	If the parameter @drop is set to %true, pending frames may be dropped.
+ *	The callback can sleep.
  *
  * @channel_switch: Drivers that need (or want) to offload the channel
  *	switch operation for CSAs received from the AP may implement this
@@ -2492,7 +2509,7 @@ enum ieee80211_rate_control_changed {
  *	setting the EOSP flag in the QoS header of the frames. Also, when the
  *	service period ends, the driver must set %IEEE80211_TX_STATUS_EOSP
  *	on the last frame in the SP. Alternatively, it may call the function
- *	ieee80211_sta_eosp_irqsafe() to inform mac80211 of the end of the SP.
+ *	ieee80211_sta_eosp() to inform mac80211 of the end of the SP.
  *	This callback must be atomic.
  * @allow_buffered_frames: Prepare device to allow the given number of frames
  *	to go out to the given station. The frames will be sent by mac80211
@@ -2503,7 +2520,7 @@ enum ieee80211_rate_control_changed {
  *	them between the TIDs, it must set the %IEEE80211_TX_STATUS_EOSP flag
  *	on the last frame and clear it on all others and also handle the EOSP
  *	bit in the QoS header correctly. Alternatively, it can also call the
- *	ieee80211_sta_eosp_irqsafe() function.
+ *	ieee80211_sta_eosp() function.
  *	The @tids parameter is a bitmap and tells the driver which TIDs the
  *	frames will be on; it will at most have two bits set.
  *	This callback must be atomic.
@@ -2591,6 +2608,10 @@ struct ieee80211_ops {
 				 unsigned int changed_flags,
 				 unsigned int *total_flags,
 				 u64 multicast);
+	void (*set_multicast_list)(struct ieee80211_hw *hw,
+				   struct ieee80211_vif *vif, bool allmulti,
+				   struct netdev_hw_addr_list *mc_list);
+
 	int (*set_tim)(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
 		       bool set);
 	int (*set_key)(struct ieee80211_hw *hw, enum set_key_cmd cmd,
@@ -2637,12 +2658,6 @@ struct ieee80211_ops {
 				   struct ieee80211_vif *vif,
 				   struct ieee80211_sta *sta,
 				   struct dentry *dir);
-	void (*add_interface_debugfs)(struct ieee80211_hw *hw,
-				      struct ieee80211_vif *vif,
-				      struct dentry *dir);
-	void (*remove_interface_debugfs)(struct ieee80211_hw *hw,
-					 struct ieee80211_vif *vif,
-					 struct dentry *dir);
 #endif
 	void (*sta_notify)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 			enum sta_notify_cmd, struct ieee80211_sta *sta);
@@ -2677,7 +2692,7 @@ struct ieee80211_ops {
 			     struct netlink_callback *cb,
 			     void *data, int len);
 #endif
-	void (*flush)(struct ieee80211_hw *hw, bool drop);
+	void (*flush)(struct ieee80211_hw *hw, u32 queues, bool drop);
 	void (*channel_switch)(struct ieee80211_hw *hw,
 			       struct ieee80211_channel_switch *ch_switch);
 	int (*napi_poll)(struct ieee80211_hw *hw, int budget);
@@ -2687,7 +2702,8 @@ struct ieee80211_ops {
 	int (*remain_on_channel)(struct ieee80211_hw *hw,
 				 struct ieee80211_vif *vif,
 				 struct ieee80211_channel *chan,
-				 int duration);
+				 int duration,
+				 enum ieee80211_roc_type type);
 	int (*cancel_remain_on_channel)(struct ieee80211_hw *hw);
 	int (*set_ringparam)(struct ieee80211_hw *hw, u32 tx, u32 rx);
 	void (*get_ringparam)(struct ieee80211_hw *hw,
@@ -3842,14 +3858,17 @@ void ieee80211_sta_block_awake(struct ieee80211_hw *hw,
  * %IEEE80211_TX_STATUS_EOSP bit and call this function instead.
  * This applies for PS-Poll as well as uAPSD.
  *
- * Note that there is no non-_irqsafe version right now as
- * it wasn't needed, but just like _tx_status() and _rx()
- * must not be mixed in irqsafe/non-irqsafe versions, this
- * function must not be mixed with those either. Use the
- * all irqsafe, or all non-irqsafe, don't mix! If you need
- * the non-irqsafe version of this, you need to add it.
+ * Note that just like with _tx_status() and _rx() drivers must
+ * not mix calls to irqsafe/non-irqsafe versions, this function
+ * must not be mixed with those either. Use the all irqsafe, or
+ * all non-irqsafe, don't mix!
+ *
+ * NB: the _irqsafe version of this function doesn't exist, no
+ *     driver needs it right now. Don't call this function if
+ *     you'd need the _irqsafe version, look at the git history
+ *     and restore the _irqsafe version!
  */
-void ieee80211_sta_eosp_irqsafe(struct ieee80211_sta *pubsta);
+void ieee80211_sta_eosp(struct ieee80211_sta *pubsta);
 
 /**
  * ieee80211_iter_keys - iterate keys programmed into the device
diff --git a/include/net/netfilter/nf_conntrack_core.h b/include/net/netfilter/nf_conntrack_core.h
index 930275fa..fb2b623 100644
--- a/include/net/netfilter/nf_conntrack_core.h
+++ b/include/net/netfilter/nf_conntrack_core.h
@@ -27,6 +27,7 @@ extern unsigned int nf_conntrack_in(struct net *net,
 
 extern int nf_conntrack_init_net(struct net *net);
 extern void nf_conntrack_cleanup_net(struct net *net);
+extern void nf_conntrack_cleanup_net_list(struct list_head *net_exit_list);
 
 extern int nf_conntrack_proto_pernet_init(struct net *net);
 extern void nf_conntrack_proto_pernet_fini(struct net *net);
diff --git a/include/net/netns/ipv6.h b/include/net/netns/ipv6.h
index 1242f37..005e2c2 100644
--- a/include/net/netns/ipv6.h
+++ b/include/net/netns/ipv6.h
@@ -71,6 +71,7 @@ struct netns_ipv6 {
 	struct fib_rules_ops	*mr6_rules_ops;
 #endif
 #endif
+	atomic_t		dev_addr_genid;
 };
 
 #if IS_ENABLED(CONFIG_NF_DEFRAG_IPV6)
diff --git a/include/net/request_sock.h b/include/net/request_sock.h
index a51dbd1..9069e65 100644
--- a/include/net/request_sock.h
+++ b/include/net/request_sock.h
@@ -27,19 +27,13 @@ struct sk_buff;
 struct dst_entry;
 struct proto;
 
-/* empty to "strongly type" an otherwise void parameter.
- */
-struct request_values {
-};
-
 struct request_sock_ops {
 	int		family;
 	int		obj_size;
 	struct kmem_cache	*slab;
 	char		*slab_name;
 	int		(*rtx_syn_ack)(struct sock *sk,
-				       struct request_sock *req,
-				       struct request_values *rvp);
+				       struct request_sock *req);
 	void		(*send_ack)(struct sock *sk, struct sk_buff *skb,
 				    struct request_sock *req);
 	void		(*send_reset)(struct sock *sk,
diff --git a/include/net/rtnetlink.h b/include/net/rtnetlink.h
index 5a15fab..7026648 100644
--- a/include/net/rtnetlink.h
+++ b/include/net/rtnetlink.h
@@ -4,7 +4,7 @@
 #include <linux/rtnetlink.h>
 #include <net/netlink.h>
 
-typedef int (*rtnl_doit_func)(struct sk_buff *, struct nlmsghdr *, void *);
+typedef int (*rtnl_doit_func)(struct sk_buff *, struct nlmsghdr *);
 typedef int (*rtnl_dumpit_func)(struct sk_buff *, struct netlink_callback *);
 typedef u16 (*rtnl_calcit_func)(struct sk_buff *, struct nlmsghdr *);
 
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index df85a0c..cd89510 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -576,7 +576,7 @@ for (pos = chunk->subh.fwdtsn_hdr->skip;\
 #define WORD_ROUND(s) (((s)+3)&~3)
 
 /* Make a new instance of type.  */
-#define t_new(type, flags)	(type *)kzalloc(sizeof(type), flags)
+#define t_new(type, flags)	kzalloc(sizeof(type), flags)
 
 /* Compare two timevals.  */
 #define tv_lt(s, t) \
diff --git a/include/net/sock.h b/include/net/sock.h
index 14f6e9d..08f05f9 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -667,6 +667,7 @@ enum sock_flags {
 		     * user-space instead.
 		     */
 	SOCK_FILTER_LOCKED, /* Filter cannot be changed anymore */
+	SOCK_SELECT_ERR_QUEUE, /* Wake select on error queue */
 };
 
 static inline void sock_copy_flags(struct sock *nsk, struct sock *osk)
diff --git a/include/net/tcp.h b/include/net/tcp.h
index cf0694d..4475aaf 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -179,7 +179,6 @@ extern void tcp_time_wait(struct sock *sk, int state, int timeo);
 #define TCPOPT_SACK             5       /* SACK Block */
 #define TCPOPT_TIMESTAMP	8	/* Better RTT estimations/PAWS */
 #define TCPOPT_MD5SIG		19	/* MD5 Signature (RFC2385) */
-#define TCPOPT_COOKIE		253	/* Cookie extension (experimental) */
 #define TCPOPT_EXP		254	/* Experimental */
 /* Magic number to be after the option value for sharing TCP
  * experimental options. See draft-ietf-tcpm-experimental-options-00.txt
@@ -273,7 +272,6 @@ extern int sysctl_tcp_app_win;
 extern int sysctl_tcp_adv_win_scale;
 extern int sysctl_tcp_tw_reuse;
 extern int sysctl_tcp_frto;
-extern int sysctl_tcp_frto_response;
 extern int sysctl_tcp_low_latency;
 extern int sysctl_tcp_dma_copybreak;
 extern int sysctl_tcp_nometrics_save;
@@ -284,7 +282,6 @@ extern int sysctl_tcp_base_mss;
 extern int sysctl_tcp_workaround_signed_windows;
 extern int sysctl_tcp_slow_start_after_idle;
 extern int sysctl_tcp_max_ssthresh;
-extern int sysctl_tcp_cookie_size;
 extern int sysctl_tcp_thin_linear_timeouts;
 extern int sysctl_tcp_thin_dupack;
 extern int sysctl_tcp_early_retrans;
@@ -425,8 +422,6 @@ extern struct sock * tcp_check_req(struct sock *sk,struct sk_buff *skb,
 				   bool fastopen);
 extern int tcp_child_process(struct sock *parent, struct sock *child,
 			     struct sk_buff *skb);
-extern bool tcp_use_frto(struct sock *sk);
-extern void tcp_enter_frto(struct sock *sk);
 extern void tcp_enter_loss(struct sock *sk, int how);
 extern void tcp_clear_retrans(struct tcp_sock *tp);
 extern void tcp_update_metrics(struct sock *sk);
@@ -454,7 +449,7 @@ extern void tcp_syn_ack_timeout(struct sock *sk, struct request_sock *req);
 extern int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
 		       size_t len, int nonblock, int flags, int *addr_len);
 extern void tcp_parse_options(const struct sk_buff *skb,
-			      struct tcp_options_received *opt_rx, const u8 **hvpp,
+			      struct tcp_options_received *opt_rx,
 			      int estab, struct tcp_fastopen_cookie *foc);
 extern const u8 *tcp_parse_md5sig_option(const struct tcphdr *th);
 
@@ -476,7 +471,6 @@ extern int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr,
 extern int tcp_connect(struct sock *sk);
 extern struct sk_buff * tcp_make_synack(struct sock *sk, struct dst_entry *dst,
 					struct request_sock *req,
-					struct request_values *rvp,
 					struct tcp_fastopen_cookie *foc);
 extern int tcp_disconnect(struct sock *sk, int flags);
 
@@ -543,6 +537,8 @@ extern bool tcp_syn_flood_action(struct sock *sk,
 extern void tcp_push_one(struct sock *, unsigned int mss_now);
 extern void tcp_send_ack(struct sock *sk);
 extern void tcp_send_delayed_ack(struct sock *sk);
+extern void tcp_send_loss_probe(struct sock *sk);
+extern bool tcp_schedule_loss_probe(struct sock *sk);
 
 /* tcp_input.c */
 extern void tcp_cwnd_application_limited(struct sock *sk);
@@ -756,7 +752,6 @@ enum tcp_ca_event {
 	CA_EVENT_TX_START,	/* first transmit when no packets in flight */
 	CA_EVENT_CWND_RESTART,	/* congestion window restart */
 	CA_EVENT_COMPLETE_CWR,	/* end of congestion recovery */
-	CA_EVENT_FRTO,		/* fast recovery timeout */
 	CA_EVENT_LOSS,		/* loss timeout */
 	CA_EVENT_FAST_ACK,	/* in sequence ack */
 	CA_EVENT_SLOW_ACK,	/* other ack */
@@ -873,8 +868,8 @@ static inline void tcp_enable_fack(struct tcp_sock *tp)
 static inline void tcp_enable_early_retrans(struct tcp_sock *tp)
 {
 	tp->do_early_retrans = sysctl_tcp_early_retrans &&
-		!sysctl_tcp_thin_dupack && sysctl_tcp_reordering == 3;
-	tp->early_retrans_delayed = 0;
+		sysctl_tcp_early_retrans < 4 && !sysctl_tcp_thin_dupack &&
+		sysctl_tcp_reordering == 3;
 }
 
 static inline void tcp_disable_early_retrans(struct tcp_sock *tp)
@@ -1030,50 +1025,7 @@ static inline void tcp_prequeue_init(struct tcp_sock *tp)
 #endif
 }
 
-/* Packet is added to VJ-style prequeue for processing in process
- * context, if a reader task is waiting. Apparently, this exciting
- * idea (VJ's mail "Re: query about TCP header on tcp-ip" of 07 Sep 93)
- * failed somewhere. Latency? Burstiness? Well, at least now we will
- * see, why it failed. 8)8)				  --ANK
- *
- * NOTE: is this not too big to inline?
- */
-static inline bool tcp_prequeue(struct sock *sk, struct sk_buff *skb)
-{
-	struct tcp_sock *tp = tcp_sk(sk);
-
-	if (sysctl_tcp_low_latency || !tp->ucopy.task)
-		return false;
-
-	if (skb->len <= tcp_hdrlen(skb) &&
-	    skb_queue_len(&tp->ucopy.prequeue) == 0)
-		return false;
-
-	__skb_queue_tail(&tp->ucopy.prequeue, skb);
-	tp->ucopy.memory += skb->truesize;
-	if (tp->ucopy.memory > sk->sk_rcvbuf) {
-		struct sk_buff *skb1;
-
-		BUG_ON(sock_owned_by_user(sk));
-
-		while ((skb1 = __skb_dequeue(&tp->ucopy.prequeue)) != NULL) {
-			sk_backlog_rcv(sk, skb1);
-			NET_INC_STATS_BH(sock_net(sk),
-					 LINUX_MIB_TCPPREQUEUEDROPPED);
-		}
-
-		tp->ucopy.memory = 0;
-	} else if (skb_queue_len(&tp->ucopy.prequeue) == 1) {
-		wake_up_interruptible_sync_poll(sk_sleep(sk),
-					   POLLIN | POLLRDNORM | POLLRDBAND);
-		if (!inet_csk_ack_scheduled(sk))
-			inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK,
-						  (3 * tcp_rto_min(sk)) / 4,
-						  TCP_RTO_MAX);
-	}
-	return true;
-}
-
+extern bool tcp_prequeue(struct sock *sk, struct sk_buff *skb);
 
 #undef STATE_TRACE
 
@@ -1630,91 +1582,6 @@ struct tcp_request_sock_ops {
 #endif
 };
 
-/* Using SHA1 for now, define some constants.
- */
-#define COOKIE_DIGEST_WORDS (SHA_DIGEST_WORDS)
-#define COOKIE_MESSAGE_WORDS (SHA_MESSAGE_BYTES / 4)
-#define COOKIE_WORKSPACE_WORDS (COOKIE_DIGEST_WORDS + COOKIE_MESSAGE_WORDS)
-
-extern int tcp_cookie_generator(u32 *bakery);
-
-/**
- *	struct tcp_cookie_values - each socket needs extra space for the
- *	cookies, together with (optional) space for any SYN data.
- *
- *	A tcp_sock contains a pointer to the current value, and this is
- *	cloned to the tcp_timewait_sock.
- *
- * @cookie_pair:	variable data from the option exchange.
- *
- * @cookie_desired:	user specified tcpct_cookie_desired.  Zero
- *			indicates default (sysctl_tcp_cookie_size).
- *			After cookie sent, remembers size of cookie.
- *			Range 0, TCP_COOKIE_MIN to TCP_COOKIE_MAX.
- *
- * @s_data_desired:	user specified tcpct_s_data_desired.  When the
- *			constant payload is specified (@s_data_constant),
- *			holds its length instead.
- *			Range 0 to TCP_MSS_DESIRED.
- *
- * @s_data_payload:	constant data that is to be included in the
- *			payload of SYN or SYNACK segments when the
- *			cookie option is present.
- */
-struct tcp_cookie_values {
-	struct kref	kref;
-	u8		cookie_pair[TCP_COOKIE_PAIR_SIZE];
-	u8		cookie_pair_size;
-	u8		cookie_desired;
-	u16		s_data_desired:11,
-			s_data_constant:1,
-			s_data_in:1,
-			s_data_out:1,
-			s_data_unused:2;
-	u8		s_data_payload[0];
-};
-
-static inline void tcp_cookie_values_release(struct kref *kref)
-{
-	kfree(container_of(kref, struct tcp_cookie_values, kref));
-}
-
-/* The length of constant payload data.  Note that s_data_desired is
- * overloaded, depending on s_data_constant: either the length of constant
- * data (returned here) or the limit on variable data.
- */
-static inline int tcp_s_data_size(const struct tcp_sock *tp)
-{
-	return (tp->cookie_values != NULL && tp->cookie_values->s_data_constant)
-		? tp->cookie_values->s_data_desired
-		: 0;
-}
-
-/**
- *	struct tcp_extend_values - tcp_ipv?.c to tcp_output.c workspace.
- *
- *	As tcp_request_sock has already been extended in other places, the
- *	only remaining method is to pass stack values along as function
- *	parameters.  These parameters are not needed after sending SYNACK.
- *
- * @cookie_bakery:	cryptographic secret and message workspace.
- *
- * @cookie_plus:	bytes in authenticator/cookie option, copied from
- *			struct tcp_options_received (above).
- */
-struct tcp_extend_values {
-	struct request_values		rv;
-	u32				cookie_bakery[COOKIE_WORKSPACE_WORDS];
-	u8				cookie_plus:6,
-					cookie_out_never:1,
-					cookie_in_always:1;
-};
-
-static inline struct tcp_extend_values *tcp_xv(struct request_values *rvp)
-{
-	return (struct tcp_extend_values *)rvp;
-}
-
 extern void tcp_v4_init(void);
 extern void tcp_init(void);
 
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 24c8886..ae16531 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -162,6 +162,7 @@ struct xfrm_state {
 		xfrm_address_t	saddr;
 		int		header_len;
 		int		trailer_len;
+		u32		extra_flags;
 	} props;
 
 	struct xfrm_lifetime_cfg lft;
diff --git a/include/pcmcia/ds.h b/include/pcmcia/ds.h
index 3bbbd78..2d56e42 100644
--- a/include/pcmcia/ds.h
+++ b/include/pcmcia/ds.h
@@ -65,6 +65,18 @@ struct pcmcia_driver {
 int pcmcia_register_driver(struct pcmcia_driver *driver);
 void pcmcia_unregister_driver(struct pcmcia_driver *driver);
 
+/**
+ * module_pcmcia_driver() - Helper macro for registering a pcmcia driver
+ * @__pcmcia_driver: pcmcia_driver struct
+ *
+ * Helper macro for pcmcia drivers which do not do anything special in module
+ * init/exit. This eliminates a lot of boilerplate. Each module may only use
+ * this macro once, and calling it replaces module_init() and module_exit().
+ */
+#define module_pcmcia_driver(__pcmcia_driver) \
+	module_driver(__pcmcia_driver, pcmcia_register_driver, \
+			pcmcia_unregister_driver)
+
 /* for struct resource * array embedded in struct pcmcia_device */
 enum {
 	PCMCIA_IOPORT_0,
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index 98cc4b2..2e6e13c 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -871,7 +871,14 @@ enum ib_access_flags {
 	IB_ACCESS_REMOTE_READ	= (1<<2),
 	IB_ACCESS_REMOTE_ATOMIC	= (1<<3),
 	IB_ACCESS_MW_BIND	= (1<<4),
-	IB_ZERO_BASED		= (1<<5)
+	IB_ZERO_BASED		= (1<<5),
+	/*
+	 * IB_ACCESS_GIFT: This memory is a gift to the adapter.  If memory is
+	 * modified after registration, the local version and data seen by the
+	 * adapter through this region rkey may differ.
+	 * Only legal with IB_ACCESS_REMOTE_READ or no permissions.
+	 */
+	IB_ACCESS_GIFT		= (1<<6)
 };
 
 struct ib_phys_buf {
diff --git a/include/scsi/Kbuild b/include/scsi/Kbuild
deleted file mode 100644
index 562ff9d..0000000
--- a/include/scsi/Kbuild
+++ /dev/null
@@ -1 +0,0 @@
-header-y += fc/
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index 399162b..e1379b4 100644
--- a/include/scsi/libfc.h
+++ b/include/scsi/libfc.h
@@ -1074,7 +1074,8 @@ void fc_rport_terminate_io(struct fc_rport *);
 /*
  * DISCOVERY LAYER
  *****************************/
-int fc_disc_init(struct fc_lport *);
+void fc_disc_init(struct fc_lport *);
+void fc_disc_config(struct fc_lport *, void *);
 
 static inline struct fc_lport *fc_disc_lport(struct fc_disc *disc)
 {
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index 2b6956e..7552435 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -6,6 +6,7 @@
 #include <linux/types.h>
 #include <linux/workqueue.h>
 #include <linux/mutex.h>
+#include <linux/seq_file.h>
 #include <scsi/scsi.h>
 
 struct request_queue;
@@ -340,7 +341,8 @@ struct scsi_host_template {
 	 *
 	 * Status: OBSOLETE
 	 */
-	int (*proc_info)(struct Scsi_Host *, char *, char **, off_t, int, int);
+	int (*show_info)(struct seq_file *, struct Scsi_Host *);
+	int (*write_info)(struct Scsi_Host *, char *, int);
 
 	/*
 	 * This is an optional routine that allows the transport to become
@@ -375,7 +377,7 @@ struct scsi_host_template {
 
 	/*
 	 * Used to store the procfs directory if a driver implements the
-	 * proc_info method.
+	 * show_info method.
 	 */
 	struct proc_dir_entry *proc_dir;
 
diff --git a/include/sound/control.h b/include/sound/control.h
index 8332e86..34bc93d 100644
--- a/include/sound/control.h
+++ b/include/sound/control.h
@@ -189,7 +189,6 @@ int _snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave,
  *
  * Add a virtual slave control to the given master element created via
  * snd_ctl_create_virtual_master() beforehand.
- * Returns zero if successful or a negative error code.
  *
  * All slaves must be the same type (returning the same information
  * via info callback).  The function doesn't check it, so it's your
@@ -199,6 +198,8 @@ int _snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave,
  * at most two channels,
  * logarithmic volume control (dB level) thus no linear volume,
  * master can only attenuate the volume without gain
+ *
+ * Return: Zero if successful or a negative error code.
  */
 static inline int
 snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave)
@@ -219,6 +220,8 @@ snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave)
  * When the control peeks the hardware values directly and the value
  * can be changed by other means than the put callback of the element,
  * this function should be used to keep the value always up-to-date.
+ *
+ * Return: Zero if successful or a negative error code.
  */
 static inline int
 snd_ctl_add_slave_uncached(struct snd_kcontrol *master,
diff --git a/include/sound/core.h b/include/sound/core.h
index 7cede2d..5bfe513 100644
--- a/include/sound/core.h
+++ b/include/sound/core.h
@@ -229,7 +229,7 @@ int snd_register_device_for_dev(int type, struct snd_card *card,
  * This function uses the card's device pointer to link to the
  * correct &struct device.
  *
- * Returns zero if successful, or a negative error code on failure.
+ * Return: Zero if successful, or a negative error code on failure.
  */
 static inline int snd_register_device(int type, struct snd_card *card, int dev,
 				      const struct file_operations *f_ops,
@@ -379,18 +379,10 @@ void __snd_printk(unsigned int level, const char *file, int line,
  * snd_BUG_ON - debugging check macro
  * @cond: condition to evaluate
  *
- * When CONFIG_SND_DEBUG is set, this macro evaluates the given condition,
- * and call WARN() and returns the value if it's non-zero.
- * 
- * When CONFIG_SND_DEBUG is not set, this just returns zero, and the given
- * condition is ignored.
- *
- * NOTE: the argument won't be evaluated at all when CONFIG_SND_DEBUG=n.
- * Thus, don't put any statement that influences on the code behavior,
- * such as pre/post increment, to the argument of this macro.
- * If you want to evaluate and give a warning, use standard WARN_ON().
+ * Has the same behavior as WARN_ON when CONFIG_SND_DEBUG is set,
+ * otherwise just evaluates the conditional and returns the value.
  */
-#define snd_BUG_ON(cond)	WARN((cond), "BUG? (%s)\n", __stringify(cond))
+#define snd_BUG_ON(cond)	WARN_ON((cond))
 
 #else /* !CONFIG_SND_DEBUG */
 
@@ -400,11 +392,11 @@ __printf(2, 3)
 static inline void _snd_printd(int level, const char *format, ...) {}
 
 #define snd_BUG()			do { } while (0)
-static inline int __snd_bug_on(int cond)
-{
-	return 0;
-}
-#define snd_BUG_ON(cond)	__snd_bug_on(0 && (cond))  /* always false */
+
+#define snd_BUG_ON(condition) ({ \
+	int __ret_warn_on = !!(condition); \
+	unlikely(__ret_warn_on); \
+})
 
 #endif /* CONFIG_SND_DEBUG */
 
diff --git a/include/sound/dmaengine_pcm.h b/include/sound/dmaengine_pcm.h
index b877334..9562042 100644
--- a/include/sound/dmaengine_pcm.h
+++ b/include/sound/dmaengine_pcm.h
@@ -32,9 +32,6 @@ snd_pcm_substream_to_dma_direction(const struct snd_pcm_substream *substream)
 		return DMA_DEV_TO_MEM;
 }
 
-void snd_dmaengine_pcm_set_data(struct snd_pcm_substream *substream, void *data);
-void *snd_dmaengine_pcm_get_data(struct snd_pcm_substream *substream);
-
 int snd_hwparams_to_dma_slave_config(const struct snd_pcm_substream *substream,
 	const struct snd_pcm_hw_params *params, struct dma_slave_config *slave_config);
 int snd_dmaengine_pcm_trigger(struct snd_pcm_substream *substream, int cmd);
@@ -47,4 +44,28 @@ int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream);
 
 struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream);
 
+/**
+ * struct snd_dmaengine_dai_dma_data - DAI DMA configuration data
+ * @addr: Address of the DAI data source or destination register.
+ * @addr_width: Width of the DAI data source or destination register.
+ * @maxburst: Maximum number of words(note: words, as in units of the
+ * src_addr_width member, not bytes) that can be send to or received from the
+ * DAI in one burst.
+ * @slave_id: Slave requester id for the DMA channel.
+ * @filter_data: Custom DMA channel filter data, this will usually be used when
+ * requesting the DMA channel.
+ */
+struct snd_dmaengine_dai_dma_data {
+	dma_addr_t addr;
+	enum dma_slave_buswidth addr_width;
+	u32 maxburst;
+	unsigned int slave_id;
+	void *filter_data;
+};
+
+void snd_dmaengine_pcm_set_config_from_dai_data(
+	const struct snd_pcm_substream *substream,
+	const struct snd_dmaengine_dai_dma_data *dma_data,
+	struct dma_slave_config *config);
+
 #endif
diff --git a/include/sound/max98090.h b/include/sound/max98090.h
old mode 100755
new mode 100644
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index 45c1981..aa7b0a8 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -659,7 +659,7 @@ static inline snd_pcm_sframes_t snd_pcm_capture_hw_avail(struct snd_pcm_runtime
  *
  * Checks whether enough free space is available on the playback buffer.
  *
- * Returns non-zero if available, or zero if not.
+ * Return: Non-zero if available, or zero if not.
  */
 static inline int snd_pcm_playback_ready(struct snd_pcm_substream *substream)
 {
@@ -673,7 +673,7 @@ static inline int snd_pcm_playback_ready(struct snd_pcm_substream *substream)
  *
  * Checks whether enough capture data is available on the capture buffer.
  *
- * Returns non-zero if available, or zero if not.
+ * Return: Non-zero if available, or zero if not.
  */
 static inline int snd_pcm_capture_ready(struct snd_pcm_substream *substream)
 {
@@ -685,10 +685,10 @@ static inline int snd_pcm_capture_ready(struct snd_pcm_substream *substream)
  * snd_pcm_playback_data - check whether any data exists on the playback buffer
  * @substream: the pcm substream instance
  *
- * Checks whether any data exists on the playback buffer. If stop_threshold
- * is bigger or equal to boundary, then this function returns always non-zero.
+ * Checks whether any data exists on the playback buffer.
  *
- * Returns non-zero if exists, or zero if not.
+ * Return: Non-zero if any data exists, or zero if not. If stop_threshold
+ * is bigger or equal to boundary, then this function returns always non-zero.
  */
 static inline int snd_pcm_playback_data(struct snd_pcm_substream *substream)
 {
@@ -705,7 +705,7 @@ static inline int snd_pcm_playback_data(struct snd_pcm_substream *substream)
  *
  * Checks whether the playback buffer is empty.
  *
- * Returns non-zero if empty, or zero if not.
+ * Return: Non-zero if empty, or zero if not.
  */
 static inline int snd_pcm_playback_empty(struct snd_pcm_substream *substream)
 {
@@ -719,7 +719,7 @@ static inline int snd_pcm_playback_empty(struct snd_pcm_substream *substream)
  *
  * Checks whether the capture buffer is empty.
  *
- * Returns non-zero if empty, or zero if not.
+ * Return: Non-zero if empty, or zero if not.
  */
 static inline int snd_pcm_capture_empty(struct snd_pcm_substream *substream)
 {
@@ -852,7 +852,7 @@ int snd_pcm_format_big_endian(snd_pcm_format_t format);
  * snd_pcm_format_cpu_endian - Check the PCM format is CPU-endian
  * @format: the format to check
  *
- * Returns 1 if the given PCM format is CPU-endian, 0 if
+ * Return: 1 if the given PCM format is CPU-endian, 0 if
  * opposite, or a negative error code if endian not specified.
  */
 int snd_pcm_format_cpu_endian(snd_pcm_format_t format);
@@ -963,7 +963,7 @@ struct page *snd_pcm_lib_get_vmalloc_page(struct snd_pcm_substream *substream,
  * contiguous in kernel virtual space, but not in physical memory.  Use this
  * if the buffer is accessed by kernel code but not by device DMA.
  *
- * Returns 1 if the buffer was changed, 0 if not changed, or a negative error
+ * Return: 1 if the buffer was changed, 0 if not changed, or a negative error
  * code.
  */
 static int snd_pcm_lib_alloc_vmalloc_buffer
@@ -975,6 +975,9 @@ static int snd_pcm_lib_alloc_vmalloc_buffer
  *
  * This function works like snd_pcm_lib_alloc_vmalloc_buffer(), but uses
  * vmalloc_32(), i.e., the pages are allocated from 32-bit-addressable memory.
+ *
+ * Return: 1 if the buffer was changed, 0 if not changed, or a negative error
+ * code.
  */
 static int snd_pcm_lib_alloc_vmalloc_32_buffer
 			(struct snd_pcm_substream *substream, size_t size);
@@ -1070,6 +1073,8 @@ const char *snd_pcm_format_name(snd_pcm_format_t format);
 /**
  * snd_pcm_stream_str - Get a string naming the direction of a stream
  * @substream: the pcm substream instance
+ *
+ * Return: A string naming the direction of the stream.
  */
 static inline const char *snd_pcm_stream_str(struct snd_pcm_substream *substream)
 {
diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h
index 3d84808..ae9a227 100644
--- a/include/sound/soc-dai.h
+++ b/include/sound/soc-dai.h
@@ -95,14 +95,6 @@ struct snd_soc_dai_driver;
 struct snd_soc_dai;
 struct snd_ac97_bus_ops;
 
-/* Digital Audio Interface registration */
-int snd_soc_register_dai(struct device *dev,
-		struct snd_soc_dai_driver *dai_drv);
-void snd_soc_unregister_dai(struct device *dev);
-int snd_soc_register_dais(struct device *dev,
-		struct snd_soc_dai_driver *dai_drv, size_t count);
-void snd_soc_unregister_dais(struct device *dev, size_t count);
-
 /* Digital Audio Interface clocking API.*/
 int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
 	unsigned int freq, int dir);
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h
index e1ef63d..d460902 100644
--- a/include/sound/soc-dapm.h
+++ b/include/sound/soc-dapm.h
@@ -488,6 +488,7 @@ struct snd_soc_dapm_path {
 	/* status */
 	u32 connect:1;	/* source and sink widgets are connected */
 	u32 walked:1;	/* path has been walked */
+	u32 walking:1;  /* path is in the process of being walked */
 	u32 weak:1;	/* path ignored for power management */
 
 	int (*connected)(struct snd_soc_dapm_widget *source,
@@ -565,7 +566,6 @@ struct snd_soc_dapm_update {
 
 /* DAPM context */
 struct snd_soc_dapm_context {
-	int n_widgets; /* number of widgets in this context */
 	enum snd_soc_bias_level bias_level;
 	enum snd_soc_bias_level suspend_bias_level;
 	struct delayed_work delayed_work;
diff --git a/include/sound/soc.h b/include/sound/soc.h
index a6a059c..9eb0e4d 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -324,6 +324,8 @@ struct snd_soc_dai_link;
 struct snd_soc_platform_driver;
 struct snd_soc_codec;
 struct snd_soc_codec_driver;
+struct snd_soc_component;
+struct snd_soc_component_driver;
 struct soc_enum;
 struct snd_soc_jack;
 struct snd_soc_jack_zone;
@@ -371,12 +373,16 @@ int snd_soc_suspend(struct device *dev);
 int snd_soc_resume(struct device *dev);
 int snd_soc_poweroff(struct device *dev);
 int snd_soc_register_platform(struct device *dev,
-		struct snd_soc_platform_driver *platform_drv);
+		const struct snd_soc_platform_driver *platform_drv);
 void snd_soc_unregister_platform(struct device *dev);
 int snd_soc_register_codec(struct device *dev,
 		const struct snd_soc_codec_driver *codec_drv,
 		struct snd_soc_dai_driver *dai_drv, int num_dai);
 void snd_soc_unregister_codec(struct device *dev);
+int snd_soc_register_component(struct device *dev,
+			 const struct snd_soc_component_driver *cmpnt_drv,
+			 struct snd_soc_dai_driver *dai_drv, int num_dai);
+void snd_soc_unregister_component(struct device *dev);
 int snd_soc_codec_volatile_register(struct snd_soc_codec *codec,
 				    unsigned int reg);
 int snd_soc_codec_readable_register(struct snd_soc_codec *codec,
@@ -801,10 +807,10 @@ struct snd_soc_platform_driver {
 		struct snd_soc_dai *);
 
 	/* platform stream pcm ops */
-	struct snd_pcm_ops *ops;
+	const struct snd_pcm_ops *ops;
 
 	/* platform stream compress ops */
-	struct snd_compr_ops *compr_ops;
+	const struct snd_compr_ops *compr_ops;
 
 	/* platform stream completion event */
 	int (*stream_event)(struct snd_soc_dapm_context *dapm, int event);
@@ -823,7 +829,7 @@ struct snd_soc_platform {
 	const char *name;
 	int id;
 	struct device *dev;
-	struct snd_soc_platform_driver *driver;
+	const struct snd_soc_platform_driver *driver;
 	struct mutex mutex;
 
 	unsigned int suspended:1; /* platform is suspended */
@@ -841,6 +847,20 @@ struct snd_soc_platform {
 #endif
 };
 
+struct snd_soc_component_driver {
+	const char *name;
+};
+
+struct snd_soc_component {
+	const char *name;
+	int id;
+	int num_dai;
+	struct device *dev;
+	struct list_head list;
+
+	const struct snd_soc_component_driver *driver;
+};
+
 struct snd_soc_dai_link {
 	/* config - must be set by machine driver */
 	const char *name;			/* Codec name */
@@ -1086,7 +1106,6 @@ struct soc_enum {
 	unsigned int mask;
 	const char * const *texts;
 	const unsigned int *values;
-	void *dapm;
 };
 
 /* codec IO */
diff --git a/include/sound/tas5086.h b/include/sound/tas5086.h
new file mode 100644
index 0000000..aac481b
--- /dev/null
+++ b/include/sound/tas5086.h
@@ -0,0 +1,7 @@
+#ifndef _SND_SOC_CODEC_TAS5086_H_
+#define _SND_SOC_CODEC_TAS5086_H_
+
+#define TAS5086_CLK_IDX_MCLK	0
+#define TAS5086_CLK_IDX_SCLK	1
+
+#endif /* _SND_SOC_CODEC_TAS5086_H_ */
diff --git a/include/sound/tegra_wm8903.h b/include/sound/tegra_wm8903.h
deleted file mode 100644
index 57b202e..0000000
--- a/include/sound/tegra_wm8903.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright 2011 NVIDIA, 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 __SOUND_TEGRA_WM38903_H
-#define __SOUND_TEGRA_WM38903_H
-
-struct tegra_wm8903_platform_data {
-	int gpio_spkr_en;
-	int gpio_hp_det;
-	int gpio_hp_mute;
-	int gpio_int_mic_en;
-	int gpio_ext_mic_en;
-};
-
-#endif
diff --git a/include/target/iscsi/iscsi_transport.h b/include/target/iscsi/iscsi_transport.h
new file mode 100644
index 0000000..23a87d0
--- /dev/null
+++ b/include/target/iscsi/iscsi_transport.h
@@ -0,0 +1,83 @@
+#include <linux/module.h>
+#include <linux/list.h>
+#include "../../../drivers/target/iscsi/iscsi_target_core.h"
+
+struct iscsit_transport {
+#define ISCSIT_TRANSPORT_NAME	16
+	char name[ISCSIT_TRANSPORT_NAME];
+	int transport_type;
+	struct module *owner;
+	struct list_head t_node;
+	int (*iscsit_setup_np)(struct iscsi_np *, struct __kernel_sockaddr_storage *);
+	int (*iscsit_accept_np)(struct iscsi_np *, struct iscsi_conn *);
+	void (*iscsit_free_np)(struct iscsi_np *);
+	void (*iscsit_free_conn)(struct iscsi_conn *);
+	struct iscsi_cmd *(*iscsit_alloc_cmd)(struct iscsi_conn *, gfp_t);
+	int (*iscsit_get_login_rx)(struct iscsi_conn *, struct iscsi_login *);
+	int (*iscsit_put_login_tx)(struct iscsi_conn *, struct iscsi_login *, u32);
+	int (*iscsit_immediate_queue)(struct iscsi_conn *, struct iscsi_cmd *, int);
+	int (*iscsit_response_queue)(struct iscsi_conn *, struct iscsi_cmd *, int);
+	int (*iscsit_get_dataout)(struct iscsi_conn *, struct iscsi_cmd *, bool);
+	int (*iscsit_queue_data_in)(struct iscsi_conn *, struct iscsi_cmd *);
+	int (*iscsit_queue_status)(struct iscsi_conn *, struct iscsi_cmd *);
+};
+
+/*
+ * From iscsi_target_transport.c
+ */
+
+extern int iscsit_register_transport(struct iscsit_transport *);
+extern void iscsit_unregister_transport(struct iscsit_transport *);
+extern struct iscsit_transport *iscsit_get_transport(int);
+extern void iscsit_put_transport(struct iscsit_transport *);
+
+/*
+ * From iscsi_target.c
+ */
+extern int iscsit_add_reject_from_cmd(u8, int, int, unsigned char *,
+				struct iscsi_cmd *);
+extern int iscsit_setup_scsi_cmd(struct iscsi_conn *, struct iscsi_cmd *,
+				unsigned char *);
+extern void iscsit_set_unsoliticed_dataout(struct iscsi_cmd *);
+extern int iscsit_process_scsi_cmd(struct iscsi_conn *, struct iscsi_cmd *,
+				struct iscsi_scsi_req *);
+extern int iscsit_check_dataout_hdr(struct iscsi_conn *, unsigned char *,
+				struct iscsi_cmd **);
+extern int iscsit_check_dataout_payload(struct iscsi_cmd *, struct iscsi_data *,
+				bool);
+extern int iscsit_handle_nop_out(struct iscsi_conn *, struct iscsi_cmd *,
+				unsigned char *);
+extern int iscsit_handle_logout_cmd(struct iscsi_conn *, struct iscsi_cmd *,
+				unsigned char *);
+extern int iscsit_handle_task_mgt_cmd(struct iscsi_conn *, struct iscsi_cmd *,
+				unsigned char *);
+extern void iscsit_build_rsp_pdu(struct iscsi_cmd *, struct iscsi_conn *,
+				bool, struct iscsi_scsi_rsp *);
+extern void iscsit_build_nopin_rsp(struct iscsi_cmd *, struct iscsi_conn *,
+				struct iscsi_nopin *, bool);
+extern void iscsit_build_task_mgt_rsp(struct iscsi_cmd *, struct iscsi_conn *,
+				struct iscsi_tm_rsp *);
+extern void iscsit_build_reject(struct iscsi_cmd *, struct iscsi_conn *,
+				struct iscsi_reject *);
+extern int iscsit_build_logout_rsp(struct iscsi_cmd *, struct iscsi_conn *,
+				struct iscsi_logout_rsp *);
+extern int iscsit_logout_post_handler(struct iscsi_cmd *, struct iscsi_conn *);
+/*
+ * From iscsi_target_device.c
+ */
+extern void iscsit_increment_maxcmdsn(struct iscsi_cmd *, struct iscsi_session *);
+/*
+ * From iscsi_target_erl1.c
+ */
+extern void iscsit_stop_dataout_timer(struct iscsi_cmd *);
+
+/*
+ * From iscsi_target_tmr.c
+ */
+extern int iscsit_tmr_post_handler(struct iscsi_cmd *, struct iscsi_conn *);
+
+/*
+ * From iscsi_target_util.c
+ */
+extern struct iscsi_cmd *iscsit_allocate_cmd(struct iscsi_conn *, gfp_t);
+extern int iscsit_sequence_cmd(struct iscsi_conn *, struct iscsi_cmd *, __be32);
diff --git a/include/target/target_core_fabric.h b/include/target/target_core_fabric.h
index aaa1ee6..ba3471b 100644
--- a/include/target/target_core_fabric.h
+++ b/include/target/target_core_fabric.h
@@ -120,7 +120,7 @@ bool	transport_wait_for_tasks(struct se_cmd *);
 int	transport_check_aborted_status(struct se_cmd *, int);
 int	transport_send_check_condition_and_sense(struct se_cmd *,
 		sense_reason_t, int);
-
+int	target_get_sess_cmd(struct se_session *, struct se_cmd *, bool);
 int	target_put_sess_cmd(struct se_session *, struct se_cmd *);
 void	target_sess_cmd_list_set_waiting(struct se_session *);
 void	target_wait_for_sess_cmds(struct se_session *, int);
diff --git a/include/trace/events/bcache.h b/include/trace/events/bcache.h
new file mode 100644
index 0000000..3cc5a0b
--- /dev/null
+++ b/include/trace/events/bcache.h
@@ -0,0 +1,271 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM bcache
+
+#if !defined(_TRACE_BCACHE_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_BCACHE_H
+
+#include <linux/tracepoint.h>
+
+struct search;
+
+DECLARE_EVENT_CLASS(bcache_request,
+
+	TP_PROTO(struct search *s, struct bio *bio),
+
+	TP_ARGS(s, bio),
+
+	TP_STRUCT__entry(
+		__field(dev_t,		dev			)
+		__field(unsigned int,	orig_major		)
+		__field(unsigned int,	orig_minor		)
+		__field(sector_t,	sector			)
+		__field(dev_t,		orig_sector		)
+		__field(unsigned int,	nr_sector		)
+		__array(char,		rwbs,	6		)
+		__array(char,		comm,	TASK_COMM_LEN	)
+	),
+
+	TP_fast_assign(
+		__entry->dev		= bio->bi_bdev->bd_dev;
+		__entry->orig_major	= s->d->disk->major;
+		__entry->orig_minor	= s->d->disk->first_minor;
+		__entry->sector		= bio->bi_sector;
+		__entry->orig_sector	= bio->bi_sector - 16;
+		__entry->nr_sector	= bio->bi_size >> 9;
+		blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_size);
+		memcpy(__entry->comm, current->comm, TASK_COMM_LEN);
+	),
+
+	TP_printk("%d,%d %s %llu + %u [%s] (from %d,%d @ %llu)",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  __entry->rwbs,
+		  (unsigned long long)__entry->sector,
+		  __entry->nr_sector, __entry->comm,
+		  __entry->orig_major, __entry->orig_minor,
+		  (unsigned long long)__entry->orig_sector)
+);
+
+DEFINE_EVENT(bcache_request, bcache_request_start,
+
+	TP_PROTO(struct search *s, struct bio *bio),
+
+	TP_ARGS(s, bio)
+);
+
+DEFINE_EVENT(bcache_request, bcache_request_end,
+
+	TP_PROTO(struct search *s, struct bio *bio),
+
+	TP_ARGS(s, bio)
+);
+
+DECLARE_EVENT_CLASS(bcache_bio,
+
+	TP_PROTO(struct bio *bio),
+
+	TP_ARGS(bio),
+
+	TP_STRUCT__entry(
+		__field(dev_t,		dev			)
+		__field(sector_t,	sector			)
+		__field(unsigned int,	nr_sector		)
+		__array(char,		rwbs,	6		)
+		__array(char,		comm,	TASK_COMM_LEN	)
+	),
+
+	TP_fast_assign(
+		__entry->dev		= bio->bi_bdev->bd_dev;
+		__entry->sector		= bio->bi_sector;
+		__entry->nr_sector	= bio->bi_size >> 9;
+		blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_size);
+		memcpy(__entry->comm, current->comm, TASK_COMM_LEN);
+	),
+
+	TP_printk("%d,%d  %s %llu + %u [%s]",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  __entry->rwbs,
+		  (unsigned long long)__entry->sector,
+		  __entry->nr_sector, __entry->comm)
+);
+
+
+DEFINE_EVENT(bcache_bio, bcache_passthrough,
+
+	TP_PROTO(struct bio *bio),
+
+	TP_ARGS(bio)
+);
+
+DEFINE_EVENT(bcache_bio, bcache_cache_hit,
+
+	TP_PROTO(struct bio *bio),
+
+	TP_ARGS(bio)
+);
+
+DEFINE_EVENT(bcache_bio, bcache_cache_miss,
+
+	TP_PROTO(struct bio *bio),
+
+	TP_ARGS(bio)
+);
+
+DEFINE_EVENT(bcache_bio, bcache_read_retry,
+
+	TP_PROTO(struct bio *bio),
+
+	TP_ARGS(bio)
+);
+
+DEFINE_EVENT(bcache_bio, bcache_writethrough,
+
+	TP_PROTO(struct bio *bio),
+
+	TP_ARGS(bio)
+);
+
+DEFINE_EVENT(bcache_bio, bcache_writeback,
+
+	TP_PROTO(struct bio *bio),
+
+	TP_ARGS(bio)
+);
+
+DEFINE_EVENT(bcache_bio, bcache_write_skip,
+
+	TP_PROTO(struct bio *bio),
+
+	TP_ARGS(bio)
+);
+
+DEFINE_EVENT(bcache_bio, bcache_btree_read,
+
+	TP_PROTO(struct bio *bio),
+
+	TP_ARGS(bio)
+);
+
+DEFINE_EVENT(bcache_bio, bcache_btree_write,
+
+	TP_PROTO(struct bio *bio),
+
+	TP_ARGS(bio)
+);
+
+DEFINE_EVENT(bcache_bio, bcache_write_dirty,
+
+	TP_PROTO(struct bio *bio),
+
+	TP_ARGS(bio)
+);
+
+DEFINE_EVENT(bcache_bio, bcache_read_dirty,
+
+	TP_PROTO(struct bio *bio),
+
+	TP_ARGS(bio)
+);
+
+DEFINE_EVENT(bcache_bio, bcache_write_moving,
+
+	TP_PROTO(struct bio *bio),
+
+	TP_ARGS(bio)
+);
+
+DEFINE_EVENT(bcache_bio, bcache_read_moving,
+
+	TP_PROTO(struct bio *bio),
+
+	TP_ARGS(bio)
+);
+
+DEFINE_EVENT(bcache_bio, bcache_journal_write,
+
+	TP_PROTO(struct bio *bio),
+
+	TP_ARGS(bio)
+);
+
+DECLARE_EVENT_CLASS(bcache_cache_bio,
+
+	TP_PROTO(struct bio *bio,
+		 sector_t orig_sector,
+		 struct block_device* orig_bdev),
+
+	TP_ARGS(bio, orig_sector, orig_bdev),
+
+	TP_STRUCT__entry(
+		__field(dev_t,		dev			)
+		__field(dev_t,		orig_dev		)
+		__field(sector_t,	sector			)
+		__field(sector_t,	orig_sector		)
+		__field(unsigned int,	nr_sector		)
+		__array(char,		rwbs,	6		)
+		__array(char,		comm,	TASK_COMM_LEN	)
+	),
+
+	TP_fast_assign(
+		__entry->dev		= bio->bi_bdev->bd_dev;
+		__entry->orig_dev	= orig_bdev->bd_dev;
+		__entry->sector		= bio->bi_sector;
+		__entry->orig_sector	= orig_sector;
+		__entry->nr_sector	= bio->bi_size >> 9;
+		blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_size);
+		memcpy(__entry->comm, current->comm, TASK_COMM_LEN);
+	),
+
+	TP_printk("%d,%d  %s %llu + %u [%s] (from %d,%d %llu)",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  __entry->rwbs,
+		  (unsigned long long)__entry->sector,
+		  __entry->nr_sector, __entry->comm,
+		  MAJOR(__entry->orig_dev), MINOR(__entry->orig_dev),
+		  (unsigned long long)__entry->orig_sector)
+);
+
+DEFINE_EVENT(bcache_cache_bio, bcache_cache_insert,
+
+	TP_PROTO(struct bio *bio,
+		 sector_t orig_sector,
+		 struct block_device *orig_bdev),
+
+	TP_ARGS(bio, orig_sector, orig_bdev)
+);
+
+DECLARE_EVENT_CLASS(bcache_gc,
+
+	TP_PROTO(uint8_t *uuid),
+
+	TP_ARGS(uuid),
+
+	TP_STRUCT__entry(
+		__field(uint8_t *,	uuid)
+	),
+
+	TP_fast_assign(
+		__entry->uuid		= uuid;
+	),
+
+	TP_printk("%pU", __entry->uuid)
+);
+
+
+DEFINE_EVENT(bcache_gc, bcache_gc_start,
+
+	     TP_PROTO(uint8_t *uuid),
+
+	     TP_ARGS(uuid)
+);
+
+DEFINE_EVENT(bcache_gc, bcache_gc_end,
+
+	     TP_PROTO(uint8_t *uuid),
+
+	     TP_ARGS(uuid)
+);
+
+#endif /* _TRACE_BCACHE_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/include/trace/events/block.h b/include/trace/events/block.h
index 9961726..5a28843 100644
--- a/include/trace/events/block.h
+++ b/include/trace/events/block.h
@@ -244,7 +244,7 @@ TRACE_EVENT(block_bio_bounce,
 		__entry->dev		= bio->bi_bdev ?
 					  bio->bi_bdev->bd_dev : 0;
 		__entry->sector		= bio->bi_sector;
-		__entry->nr_sector	= bio->bi_size >> 9;
+		__entry->nr_sector	= bio_sectors(bio);
 		blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_size);
 		memcpy(__entry->comm, current->comm, TASK_COMM_LEN);
 	),
@@ -281,7 +281,7 @@ TRACE_EVENT(block_bio_complete,
 		__entry->dev		= bio->bi_bdev ?
 					  bio->bi_bdev->bd_dev : 0;
 		__entry->sector		= bio->bi_sector;
-		__entry->nr_sector	= bio->bi_size >> 9;
+		__entry->nr_sector	= bio_sectors(bio);
 		__entry->error		= error;
 		blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_size);
 	),
@@ -309,7 +309,7 @@ DECLARE_EVENT_CLASS(block_bio_merge,
 	TP_fast_assign(
 		__entry->dev		= bio->bi_bdev->bd_dev;
 		__entry->sector		= bio->bi_sector;
-		__entry->nr_sector	= bio->bi_size >> 9;
+		__entry->nr_sector	= bio_sectors(bio);
 		blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_size);
 		memcpy(__entry->comm, current->comm, TASK_COMM_LEN);
 	),
@@ -376,7 +376,7 @@ TRACE_EVENT(block_bio_queue,
 	TP_fast_assign(
 		__entry->dev		= bio->bi_bdev->bd_dev;
 		__entry->sector		= bio->bi_sector;
-		__entry->nr_sector	= bio->bi_size >> 9;
+		__entry->nr_sector	= bio_sectors(bio);
 		blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_size);
 		memcpy(__entry->comm, current->comm, TASK_COMM_LEN);
 	),
@@ -404,7 +404,7 @@ DECLARE_EVENT_CLASS(block_get_rq,
 	TP_fast_assign(
 		__entry->dev		= bio ? bio->bi_bdev->bd_dev : 0;
 		__entry->sector		= bio ? bio->bi_sector : 0;
-		__entry->nr_sector	= bio ? bio->bi_size >> 9 : 0;
+		__entry->nr_sector	= bio ? bio_sectors(bio) : 0;
 		blk_fill_rwbs(__entry->rwbs,
 			      bio ? bio->bi_rw : 0, __entry->nr_sector);
 		memcpy(__entry->comm, current->comm, TASK_COMM_LEN);
@@ -580,7 +580,7 @@ TRACE_EVENT(block_bio_remap,
 	TP_fast_assign(
 		__entry->dev		= bio->bi_bdev->bd_dev;
 		__entry->sector		= bio->bi_sector;
-		__entry->nr_sector	= bio->bi_size >> 9;
+		__entry->nr_sector	= bio_sectors(bio);
 		__entry->old_dev	= dev;
 		__entry->old_sector	= from;
 		blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_size);
diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h
index 4ee4710..58459b7 100644
--- a/include/trace/events/ext4.h
+++ b/include/trace/events/ext4.h
@@ -257,15 +257,7 @@ DECLARE_EVENT_CLASS(ext4__write_end,
 		  __entry->pos, __entry->len, __entry->copied)
 );
 
-DEFINE_EVENT(ext4__write_end, ext4_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(ext4__write_end, ext4_writeback_write_end,
+DEFINE_EVENT(ext4__write_end, ext4_write_end,
 
 	TP_PROTO(struct inode *inode, loff_t pos, unsigned int len,
 		 unsigned int copied),
diff --git a/include/trace/events/filemap.h b/include/trace/events/filemap.h
new file mode 100644
index 0000000..0421f49
--- /dev/null
+++ b/include/trace/events/filemap.h
@@ -0,0 +1,58 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM filemap
+
+#if !defined(_TRACE_FILEMAP_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_FILEMAP_H
+
+#include <linux/types.h>
+#include <linux/tracepoint.h>
+#include <linux/mm.h>
+#include <linux/memcontrol.h>
+#include <linux/device.h>
+#include <linux/kdev_t.h>
+
+DECLARE_EVENT_CLASS(mm_filemap_op_page_cache,
+
+	TP_PROTO(struct page *page),
+
+	TP_ARGS(page),
+
+	TP_STRUCT__entry(
+		__field(struct page *, page)
+		__field(unsigned long, i_ino)
+		__field(unsigned long, index)
+		__field(dev_t, s_dev)
+	),
+
+	TP_fast_assign(
+		__entry->page = page;
+		__entry->i_ino = page->mapping->host->i_ino;
+		__entry->index = page->index;
+		if (page->mapping->host->i_sb)
+			__entry->s_dev = page->mapping->host->i_sb->s_dev;
+		else
+			__entry->s_dev = page->mapping->host->i_rdev;
+	),
+
+	TP_printk("dev %d:%d ino %lx page=%p pfn=%lu ofs=%lu",
+		MAJOR(__entry->s_dev), MINOR(__entry->s_dev),
+		__entry->i_ino,
+		__entry->page,
+		page_to_pfn(__entry->page),
+		__entry->index << PAGE_SHIFT)
+);
+
+DEFINE_EVENT(mm_filemap_op_page_cache, mm_filemap_delete_from_page_cache,
+	TP_PROTO(struct page *page),
+	TP_ARGS(page)
+	);
+
+DEFINE_EVENT(mm_filemap_op_page_cache, mm_filemap_add_to_page_cache,
+	TP_PROTO(struct page *page),
+	TP_ARGS(page)
+	);
+
+#endif /* _TRACE_FILEMAP_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/include/trace/events/printk.h b/include/trace/events/printk.h
index 94ec79c..c008bc9 100644
--- a/include/trace/events/printk.h
+++ b/include/trace/events/printk.h
@@ -6,31 +6,18 @@
 
 #include <linux/tracepoint.h>
 
-TRACE_EVENT_CONDITION(console,
-	TP_PROTO(const char *log_buf, unsigned start, unsigned end,
-		 unsigned log_buf_len),
+TRACE_EVENT(console,
+	TP_PROTO(const char *text, size_t len),
 
-	TP_ARGS(log_buf, start, end, log_buf_len),
-
-	TP_CONDITION(start != end),
+	TP_ARGS(text, len),
 
 	TP_STRUCT__entry(
-		__dynamic_array(char, msg, end - start + 1)
+		__dynamic_array(char, msg, len + 1)
 	),
 
 	TP_fast_assign(
-		if ((start & (log_buf_len - 1)) > (end & (log_buf_len - 1))) {
-			memcpy(__get_dynamic_array(msg),
-			       log_buf + (start & (log_buf_len - 1)),
-			       log_buf_len - (start & (log_buf_len - 1)));
-			memcpy((char *)__get_dynamic_array(msg) +
-			       log_buf_len - (start & (log_buf_len - 1)),
-			       log_buf, end & (log_buf_len - 1));
-		} else
-			memcpy(__get_dynamic_array(msg),
-			       log_buf + (start & (log_buf_len - 1)),
-			       end - start);
-		((char *)__get_dynamic_array(msg))[end - start] = 0;
+		memcpy(__get_dynamic_array(msg), text, len);
+		((char *)__get_dynamic_array(msg))[len] = 0;
 	),
 
 	TP_printk("%s", __get_str(msg))
diff --git a/include/trace/events/rcu.h b/include/trace/events/rcu.h
index 1918e83..59ebcc8 100644
--- a/include/trace/events/rcu.h
+++ b/include/trace/events/rcu.h
@@ -72,6 +72,58 @@ TRACE_EVENT(rcu_grace_period,
 );
 
 /*
+ * Tracepoint for future grace-period events, including those for no-callbacks
+ * CPUs.  The caller should pull the data from the rcu_node structure,
+ * other than rcuname, which comes from the rcu_state structure, and event,
+ * which is one of the following:
+ *
+ * "Startleaf": Request a nocb grace period based on leaf-node data.
+ * "Startedleaf": Leaf-node start proved sufficient.
+ * "Startedleafroot": Leaf-node start proved sufficient after checking root.
+ * "Startedroot": Requested a nocb grace period based on root-node data.
+ * "StartWait": Start waiting for the requested grace period.
+ * "ResumeWait": Resume waiting after signal.
+ * "EndWait": Complete wait.
+ * "Cleanup": Clean up rcu_node structure after previous GP.
+ * "CleanupMore": Clean up, and another no-CB GP is needed.
+ */
+TRACE_EVENT(rcu_future_grace_period,
+
+	TP_PROTO(char *rcuname, unsigned long gpnum, unsigned long completed,
+		 unsigned long c, u8 level, int grplo, int grphi,
+		 char *gpevent),
+
+	TP_ARGS(rcuname, gpnum, completed, c, level, grplo, grphi, gpevent),
+
+	TP_STRUCT__entry(
+		__field(char *, rcuname)
+		__field(unsigned long, gpnum)
+		__field(unsigned long, completed)
+		__field(unsigned long, c)
+		__field(u8, level)
+		__field(int, grplo)
+		__field(int, grphi)
+		__field(char *, gpevent)
+	),
+
+	TP_fast_assign(
+		__entry->rcuname = rcuname;
+		__entry->gpnum = gpnum;
+		__entry->completed = completed;
+		__entry->c = c;
+		__entry->level = level;
+		__entry->grplo = grplo;
+		__entry->grphi = grphi;
+		__entry->gpevent = gpevent;
+	),
+
+	TP_printk("%s %lu %lu %lu %u %d %d %s",
+		  __entry->rcuname, __entry->gpnum, __entry->completed,
+		  __entry->c, __entry->level, __entry->grplo, __entry->grphi,
+		  __entry->gpevent)
+);
+
+/*
  * Tracepoint for grace-period-initialization events.  These are
  * distinguished by the type of RCU, the new grace-period number, the
  * rcu_node structure level, the starting and ending CPU covered by the
@@ -601,6 +653,9 @@ TRACE_EVENT(rcu_barrier,
 #define trace_rcu_grace_period(rcuname, gpnum, gpevent) do { } while (0)
 #define trace_rcu_grace_period_init(rcuname, gpnum, level, grplo, grphi, \
 				    qsmask) do { } while (0)
+#define trace_rcu_future_grace_period(rcuname, gpnum, completed, c, \
+				      level, grplo, grphi, event) \
+				      do { } while (0)
 #define trace_rcu_preempt_task(rcuname, pid, gpnum) do { } while (0)
 #define trace_rcu_unlock_preempted_task(rcuname, gpnum, pid) do { } while (0)
 #define trace_rcu_quiescent_state_report(rcuname, gpnum, mask, qsmask, level, \
diff --git a/include/trace/events/regmap.h b/include/trace/events/regmap.h
index 41a7dbd..a43a2f6 100644
--- a/include/trace/events/regmap.h
+++ b/include/trace/events/regmap.h
@@ -175,6 +175,54 @@ DEFINE_EVENT(regmap_bool, regmap_cache_bypass,
 
 );
 
+DECLARE_EVENT_CLASS(regmap_async,
+
+	TP_PROTO(struct device *dev),
+
+	TP_ARGS(dev),
+
+	TP_STRUCT__entry(
+		__string(	name,		dev_name(dev)	)
+	),
+
+	TP_fast_assign(
+		__assign_str(name, dev_name(dev));
+	),
+
+	TP_printk("%s", __get_str(name))
+);
+
+DEFINE_EVENT(regmap_block, regmap_async_write_start,
+
+	TP_PROTO(struct device *dev, unsigned int reg, int count),
+
+	TP_ARGS(dev, reg, count)
+);
+
+DEFINE_EVENT(regmap_async, regmap_async_io_complete,
+
+	TP_PROTO(struct device *dev),
+
+	TP_ARGS(dev)
+
+);
+
+DEFINE_EVENT(regmap_async, regmap_async_complete_start,
+
+	TP_PROTO(struct device *dev),
+
+	TP_ARGS(dev)
+
+);
+
+DEFINE_EVENT(regmap_async, regmap_async_complete_done,
+
+	TP_PROTO(struct device *dev),
+
+	TP_ARGS(dev)
+
+);
+
 #endif /* _TRACE_REGMAP_H */
 
 /* This part must be outside protection */
diff --git a/include/trace/events/timer.h b/include/trace/events/timer.h
index 425bcfe..8d21947 100644
--- a/include/trace/events/timer.h
+++ b/include/trace/events/timer.h
@@ -123,7 +123,7 @@ DEFINE_EVENT(timer_class, timer_cancel,
 
 /**
  * hrtimer_init - called when the hrtimer is initialized
- * @timer:	pointer to struct hrtimer
+ * @hrtimer:	pointer to struct hrtimer
  * @clockid:	the hrtimers clock
  * @mode:	the hrtimers mode
  */
@@ -155,7 +155,7 @@ TRACE_EVENT(hrtimer_init,
 
 /**
  * hrtimer_start - called when the hrtimer is started
- * @timer: pointer to struct hrtimer
+ * @hrtimer: pointer to struct hrtimer
  */
 TRACE_EVENT(hrtimer_start,
 
@@ -186,8 +186,8 @@ TRACE_EVENT(hrtimer_start,
 );
 
 /**
- * htimmer_expire_entry - called immediately before the hrtimer callback
- * @timer:	pointer to struct hrtimer
+ * hrtimer_expire_entry - called immediately before the hrtimer callback
+ * @hrtimer:	pointer to struct hrtimer
  * @now:	pointer to variable which contains current time of the
  *		timers base.
  *
@@ -234,7 +234,7 @@ DECLARE_EVENT_CLASS(hrtimer_class,
 
 /**
  * hrtimer_expire_exit - called immediately after the hrtimer callback returns
- * @timer:	pointer to struct hrtimer
+ * @hrtimer:	pointer to struct hrtimer
  *
  * When used in combination with the hrtimer_expire_entry tracepoint we can
  * determine the runtime of the callback function.
diff --git a/include/trace/events/writeback.h b/include/trace/events/writeback.h
index 6a16fd2..464ea82 100644
--- a/include/trace/events/writeback.h
+++ b/include/trace/events/writeback.h
@@ -183,7 +183,6 @@ DECLARE_EVENT_CLASS(writeback_work_class,
 DEFINE_EVENT(writeback_work_class, name, \
 	TP_PROTO(struct backing_dev_info *bdi, struct wb_writeback_work *work), \
 	TP_ARGS(bdi, work))
-DEFINE_WRITEBACK_WORK_EVENT(writeback_nothread);
 DEFINE_WRITEBACK_WORK_EVENT(writeback_queue);
 DEFINE_WRITEBACK_WORK_EVENT(writeback_exec);
 DEFINE_WRITEBACK_WORK_EVENT(writeback_start);
@@ -222,12 +221,8 @@ DEFINE_EVENT(writeback_class, name, \
 
 DEFINE_WRITEBACK_EVENT(writeback_nowork);
 DEFINE_WRITEBACK_EVENT(writeback_wake_background);
-DEFINE_WRITEBACK_EVENT(writeback_wake_thread);
-DEFINE_WRITEBACK_EVENT(writeback_wake_forker_thread);
 DEFINE_WRITEBACK_EVENT(writeback_bdi_register);
 DEFINE_WRITEBACK_EVENT(writeback_bdi_unregister);
-DEFINE_WRITEBACK_EVENT(writeback_thread_start);
-DEFINE_WRITEBACK_EVENT(writeback_thread_stop);
 
 DECLARE_EVENT_CLASS(wbc_class,
 	TP_PROTO(struct writeback_control *wbc, struct backing_dev_info *bdi),
diff --git a/include/trace/ftrace.h b/include/trace/ftrace.h
index 40dc5e8..4bda044 100644
--- a/include/trace/ftrace.h
+++ b/include/trace/ftrace.h
@@ -227,29 +227,18 @@ static notrace enum print_line_t					\
 ftrace_raw_output_##call(struct trace_iterator *iter, int flags,	\
 			 struct trace_event *trace_event)		\
 {									\
-	struct ftrace_event_call *event;				\
 	struct trace_seq *s = &iter->seq;				\
+	struct trace_seq __maybe_unused *p = &iter->tmp_seq;		\
 	struct ftrace_raw_##call *field;				\
-	struct trace_entry *entry;					\
-	struct trace_seq *p = &iter->tmp_seq;				\
 	int ret;							\
 									\
-	event = container_of(trace_event, struct ftrace_event_call,	\
-			     event);					\
-									\
-	entry = iter->ent;						\
-									\
-	if (entry->type != event->event.type) {				\
-		WARN_ON_ONCE(1);					\
-		return TRACE_TYPE_UNHANDLED;				\
-	}								\
-									\
-	field = (typeof(field))entry;					\
+	field = (typeof(field))iter->ent;				\
 									\
-	trace_seq_init(p);						\
-	ret = trace_seq_printf(s, "%s: ", event->name);			\
+	ret = ftrace_raw_output_prep(iter, trace_event);		\
 	if (ret)							\
-		ret = trace_seq_printf(s, print);			\
+		return ret;						\
+									\
+	ret = trace_seq_printf(s, print);				\
 	if (!ret)							\
 		return TRACE_TYPE_PARTIAL_LINE;				\
 									\
@@ -335,7 +324,7 @@ static struct trace_event_functions ftrace_event_type_funcs_##call = {	\
 
 #undef DECLARE_EVENT_CLASS
 #define DECLARE_EVENT_CLASS(call, proto, args, tstruct, func, print)	\
-static int notrace							\
+static int notrace __init						\
 ftrace_define_fields_##call(struct ftrace_event_call *event_call)	\
 {									\
 	struct ftrace_raw_##call field;					\
@@ -414,7 +403,8 @@ static inline notrace int ftrace_get_offsets_##call(			\
  *
  * static void ftrace_raw_event_<call>(void *__data, proto)
  * {
- *	struct ftrace_event_call *event_call = __data;
+ *	struct ftrace_event_file *ftrace_file = __data;
+ *	struct ftrace_event_call *event_call = ftrace_file->event_call;
  *	struct ftrace_data_offsets_<call> __maybe_unused __data_offsets;
  *	struct ring_buffer_event *event;
  *	struct ftrace_raw_<call> *entry; <-- defined in stage 1
@@ -423,12 +413,16 @@ static inline notrace int ftrace_get_offsets_##call(			\
  *	int __data_size;
  *	int pc;
  *
+ *	if (test_bit(FTRACE_EVENT_FL_SOFT_DISABLED_BIT,
+ *		     &ftrace_file->flags))
+ *		return;
+ *
  *	local_save_flags(irq_flags);
  *	pc = preempt_count();
  *
  *	__data_size = ftrace_get_offsets_<call>(&__data_offsets, args);
  *
- *	event = trace_current_buffer_lock_reserve(&buffer,
+ *	event = trace_event_buffer_lock_reserve(&buffer, ftrace_file,
  *				  event_<call>->event.type,
  *				  sizeof(*entry) + __data_size,
  *				  irq_flags, pc);
@@ -440,7 +434,7 @@ static inline notrace int ftrace_get_offsets_##call(			\
  *			   __array macros.
  *
  *	if (!filter_current_check_discard(buffer, event_call, entry, event))
- *		trace_current_buffer_unlock_commit(buffer,
+ *		trace_nowake_buffer_unlock_commit(buffer,
  *						   event, irq_flags, pc);
  * }
  *
@@ -518,7 +512,8 @@ static inline notrace int ftrace_get_offsets_##call(			\
 static notrace void							\
 ftrace_raw_event_##call(void *__data, proto)				\
 {									\
-	struct ftrace_event_call *event_call = __data;			\
+	struct ftrace_event_file *ftrace_file = __data;			\
+	struct ftrace_event_call *event_call = ftrace_file->event_call;	\
 	struct ftrace_data_offsets_##call __maybe_unused __data_offsets;\
 	struct ring_buffer_event *event;				\
 	struct ftrace_raw_##call *entry;				\
@@ -527,12 +522,16 @@ ftrace_raw_event_##call(void *__data, proto)				\
 	int __data_size;						\
 	int pc;								\
 									\
+	if (test_bit(FTRACE_EVENT_FL_SOFT_DISABLED_BIT,			\
+		     &ftrace_file->flags))				\
+		return;							\
+									\
 	local_save_flags(irq_flags);					\
 	pc = preempt_count();						\
 									\
 	__data_size = ftrace_get_offsets_##call(&__data_offsets, args); \
 									\
-	event = trace_current_buffer_lock_reserve(&buffer,		\
+	event = trace_event_buffer_lock_reserve(&buffer, ftrace_file,	\
 				 event_call->event.type,		\
 				 sizeof(*entry) + __data_size,		\
 				 irq_flags, pc);			\
@@ -581,7 +580,7 @@ static inline void ftrace_test_probe_##call(void)			\
 #define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print)	\
 _TRACE_PERF_PROTO(call, PARAMS(proto));					\
 static const char print_fmt_##call[] = print;				\
-static struct ftrace_event_class __used event_class_##call = {		\
+static struct ftrace_event_class __used __refdata event_class_##call = { \
 	.system			= __stringify(TRACE_SYSTEM),		\
 	.define_fields		= ftrace_define_fields_##call,		\
 	.fields			= LIST_HEAD_INIT(event_class_##call.fields),\
diff --git a/include/uapi/asm-generic/socket.h b/include/uapi/asm-generic/socket.h
index 4ef3acb..c5d2e3a 100644
--- a/include/uapi/asm-generic/socket.h
+++ b/include/uapi/asm-generic/socket.h
@@ -74,4 +74,6 @@
 
 #define SO_LOCK_FILTER		44
 
+#define SO_SELECT_ERR_QUEUE	45
+
 #endif /* __ASM_GENERIC_SOCKET_H */
diff --git a/include/uapi/linux/cn_proc.h b/include/uapi/linux/cn_proc.h
index 0d7b499..f6c2710 100644
--- a/include/uapi/linux/cn_proc.h
+++ b/include/uapi/linux/cn_proc.h
@@ -56,7 +56,9 @@ struct proc_event {
 		PROC_EVENT_PTRACE = 0x00000100,
 		PROC_EVENT_COMM = 0x00000200,
 		/* "next" should be 0x00000400 */
-		/* "last" is the last process event: exit */
+		/* "last" is the last process event: exit,
+		 * while "next to last" is coredumping event */
+		PROC_EVENT_COREDUMP = 0x40000000,
 		PROC_EVENT_EXIT = 0x80000000
 	} what;
 	__u32 cpu;
@@ -110,11 +112,17 @@ struct proc_event {
 			char           comm[16];
 		} comm;
 
+		struct coredump_proc_event {
+			__kernel_pid_t process_pid;
+			__kernel_pid_t process_tgid;
+		} coredump;
+
 		struct exit_proc_event {
 			__kernel_pid_t process_pid;
 			__kernel_pid_t process_tgid;
 			__u32 exit_code, exit_signal;
 		} exit;
+
 	} event_data;
 };
 
diff --git a/include/uapi/linux/connector.h b/include/uapi/linux/connector.h
index 8761a03..4cb2835 100644
--- a/include/uapi/linux/connector.h
+++ b/include/uapi/linux/connector.h
@@ -44,8 +44,11 @@
 #define CN_VAL_DRBD			0x1
 #define CN_KVP_IDX			0x9	/* HyperV KVP */
 #define CN_KVP_VAL			0x1	/* queries from the kernel */
+#define CN_VSS_IDX			0xA     /* HyperV VSS */
+#define CN_VSS_VAL			0x1     /* queries from the kernel */
 
-#define CN_NETLINK_USERS		10	/* Highest index + 1 */
+
+#define CN_NETLINK_USERS		11	/* Highest index + 1 */
 
 /*
  * Maximum connector's message size.
diff --git a/include/uapi/linux/elf.h b/include/uapi/linux/elf.h
index 8072d35..ef6103b 100644
--- a/include/uapi/linux/elf.h
+++ b/include/uapi/linux/elf.h
@@ -397,6 +397,7 @@ typedef struct elf64_shdr {
 #define NT_ARM_HW_WATCH	0x403		/* ARM hardware watchpoint registers */
 #define NT_METAG_CBUF	0x500		/* Metag catch buffer registers */
 #define NT_METAG_RPIPE	0x501		/* Metag read pipeline state */
+#define NT_METAG_TLS	0x502		/* Metag TLS pointer */
 
 
 /* Note header in a PT_NOTE section */
diff --git a/include/uapi/linux/eventpoll.h b/include/uapi/linux/eventpoll.h
index 2c267bc..8c99ce7 100644
--- a/include/uapi/linux/eventpoll.h
+++ b/include/uapi/linux/eventpoll.h
@@ -25,6 +25,7 @@
 #define EPOLL_CTL_ADD 1
 #define EPOLL_CTL_DEL 2
 #define EPOLL_CTL_MOD 3
+#define EPOLL_CTL_DISABLE 4
 
 /*
  * Request the handling of system wakeup events so as to prevent system suspends
diff --git a/include/uapi/linux/filter.h b/include/uapi/linux/filter.h
index 9cfde69..8eb9cca 100644
--- a/include/uapi/linux/filter.h
+++ b/include/uapi/linux/filter.h
@@ -129,7 +129,8 @@ struct sock_fprog {	/* Required for SO_ATTACH_FILTER. */
 #define SKF_AD_ALU_XOR_X	40
 #define SKF_AD_VLAN_TAG	44
 #define SKF_AD_VLAN_TAG_PRESENT 48
-#define SKF_AD_MAX	52
+#define SKF_AD_PAY_OFFSET	52
+#define SKF_AD_MAX	56
 #define SKF_NET_OFF   (-0x100000)
 #define SKF_LL_OFF    (-0x200000)
 
diff --git a/include/uapi/linux/fs.h b/include/uapi/linux/fs.h
index c7fc1e6..a4ed56c 100644
--- a/include/uapi/linux/fs.h
+++ b/include/uapi/linux/fs.h
@@ -88,7 +88,6 @@ struct inodes_stat_t {
 #define MS_STRICTATIME	(1<<24) /* Always perform atime updates */
 
 /* These sb flags are internal to the kernel */
-#define MS_SNAP_STABLE	(1<<27) /* Snapshot pages during writeback, if needed */
 #define MS_NOSEC	(1<<28)
 #define MS_BORN		(1<<29)
 #define MS_ACTIVE	(1<<30)
diff --git a/include/uapi/linux/if_ether.h b/include/uapi/linux/if_ether.h
index 798032d..ade07f1 100644
--- a/include/uapi/linux/if_ether.h
+++ b/include/uapi/linux/if_ether.h
@@ -94,6 +94,9 @@
 #define ETH_P_EDSA	0xDADA		/* Ethertype DSA [ NOT AN OFFICIALLY REGISTERED ID ] */
 #define ETH_P_AF_IUCV   0xFBFB		/* IBM af_iucv [ NOT AN OFFICIALLY REGISTERED ID ] */
 
+#define ETH_P_802_3_MIN	0x0600		/* If the value in the ethernet type is less than this value
+					 * then the frame is Ethernet II. Else it is 802.3 */
+
 /*
  *	Non DIX types. Won't clash for 1500 types.
  */
diff --git a/include/uapi/linux/if_packet.h b/include/uapi/linux/if_packet.h
index f9a6037..8136658 100644
--- a/include/uapi/linux/if_packet.h
+++ b/include/uapi/linux/if_packet.h
@@ -55,6 +55,8 @@ struct sockaddr_ll {
 #define PACKET_FANOUT_HASH		0
 #define PACKET_FANOUT_LB		1
 #define PACKET_FANOUT_CPU		2
+#define PACKET_FANOUT_ROLLOVER		3
+#define PACKET_FANOUT_FLAG_ROLLOVER	0x1000
 #define PACKET_FANOUT_FLAG_DEFRAG	0x8000
 
 struct tpacket_stats {
diff --git a/include/uapi/linux/input.h b/include/uapi/linux/input.h
index 935119c..4649ee3 100644
--- a/include/uapi/linux/input.h
+++ b/include/uapi/linux/input.h
@@ -702,6 +702,11 @@ struct input_keymap_entry {
 #define KEY_CAMERA_LEFT		0x219
 #define KEY_CAMERA_RIGHT	0x21a
 
+#define KEY_ATTENDANT_ON	0x21b
+#define KEY_ATTENDANT_OFF	0x21c
+#define KEY_ATTENDANT_TOGGLE	0x21d	/* Attendant call on or off */
+#define KEY_LIGHTS_TOGGLE	0x21e	/* Reading light on or off */
+
 #define BTN_TRIGGER_HAPPY		0x2c0
 #define BTN_TRIGGER_HAPPY1		0x2c0
 #define BTN_TRIGGER_HAPPY2		0x2c1
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index 3c56ba3..67c65f0 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -449,12 +449,23 @@ enum {
 	kvm_ioeventfd_flag_nr_datamatch,
 	kvm_ioeventfd_flag_nr_pio,
 	kvm_ioeventfd_flag_nr_deassign,
+	kvm_ioeventfd_flag_nr_virtio_ccw_notify,
+	kvm_ioeventfd_flag_nr_pv_mmio,
 	kvm_ioeventfd_flag_nr_max,
 };
 
 #define KVM_IOEVENTFD_FLAG_DATAMATCH (1 << kvm_ioeventfd_flag_nr_datamatch)
 #define KVM_IOEVENTFD_FLAG_PIO       (1 << kvm_ioeventfd_flag_nr_pio)
+/*
+ * PV_MMIO - Guest can promise us that all accesses touching this address
+ * are writes of specified length, starting at the specified address.
+ * If not - it's a Guest bug.
+ * Can not be used together with either PIO or DATAMATCH.
+ */
+#define KVM_IOEVENTFD_FLAG_PV_MMIO   (1 << kvm_ioeventfd_flag_nr_pv_mmio)
 #define KVM_IOEVENTFD_FLAG_DEASSIGN  (1 << kvm_ioeventfd_flag_nr_deassign)
+#define KVM_IOEVENTFD_FLAG_VIRTIO_CCW_NOTIFY \
+	(1 << kvm_ioeventfd_flag_nr_virtio_ccw_notify)
 
 #define KVM_IOEVENTFD_VALID_FLAG_MASK  ((1 << kvm_ioeventfd_flag_nr_max) - 1)
 
@@ -665,6 +676,7 @@ struct kvm_ppc_smmu_info {
 #define KVM_CAP_PPC_EPR 86
 #define KVM_CAP_ARM_PSCI 87
 #define KVM_CAP_ARM_SET_DEVICE_ADDR 88
+#define KVM_CAP_IOEVENTFD_PV_MMIO 89
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
diff --git a/include/uapi/linux/magic.h b/include/uapi/linux/magic.h
index 873e086..249df37 100644
--- a/include/uapi/linux/magic.h
+++ b/include/uapi/linux/magic.h
@@ -11,6 +11,7 @@
 #define DEBUGFS_MAGIC          0x64626720
 #define SECURITYFS_MAGIC	0x73636673
 #define SELINUX_MAGIC		0xf97cff8c
+#define SMACK_MAGIC		0x43415d53	/* "SMAC" */
 #define RAMFS_MAGIC		0x858458f6	/* some random number */
 #define TMPFS_MAGIC		0x01021994
 #define HUGETLBFS_MAGIC 	0x958458f6	/* some random number */
diff --git a/include/uapi/linux/media.h b/include/uapi/linux/media.h
index 0ef8833..ed49574 100644
--- a/include/uapi/linux/media.h
+++ b/include/uapi/linux/media.h
@@ -56,6 +56,8 @@ struct media_device_info {
 #define MEDIA_ENT_T_V4L2_SUBDEV_SENSOR	(MEDIA_ENT_T_V4L2_SUBDEV + 1)
 #define MEDIA_ENT_T_V4L2_SUBDEV_FLASH	(MEDIA_ENT_T_V4L2_SUBDEV + 2)
 #define MEDIA_ENT_T_V4L2_SUBDEV_LENS	(MEDIA_ENT_T_V4L2_SUBDEV + 3)
+/* A converter of analogue video to its digital representation. */
+#define MEDIA_ENT_T_V4L2_SUBDEV_DECODER	(MEDIA_ENT_T_V4L2_SUBDEV + 4)
 
 #define MEDIA_ENT_FL_DEFAULT		(1 << 0)
 
diff --git a/include/uapi/linux/neighbour.h b/include/uapi/linux/neighbour.h
index adb068c..f175212 100644
--- a/include/uapi/linux/neighbour.h
+++ b/include/uapi/linux/neighbour.h
@@ -21,6 +21,9 @@ enum {
 	NDA_CACHEINFO,
 	NDA_PROBES,
 	NDA_VLAN,
+	NDA_PORT,
+	NDA_VNI,
+	NDA_IFINDEX,
 	__NDA_MAX
 };
 
diff --git a/include/uapi/linux/netlink.h b/include/uapi/linux/netlink.h
index 78d5b8a..32a354f 100644
--- a/include/uapi/linux/netlink.h
+++ b/include/uapi/linux/netlink.h
@@ -78,7 +78,7 @@ struct nlmsghdr {
 #define NLMSG_ALIGNTO	4U
 #define NLMSG_ALIGN(len) ( ((len)+NLMSG_ALIGNTO-1) & ~(NLMSG_ALIGNTO-1) )
 #define NLMSG_HDRLEN	 ((int) NLMSG_ALIGN(sizeof(struct nlmsghdr)))
-#define NLMSG_LENGTH(len) ((len)+NLMSG_ALIGN(NLMSG_HDRLEN))
+#define NLMSG_LENGTH(len) ((len) + NLMSG_HDRLEN)
 #define NLMSG_SPACE(len) NLMSG_ALIGN(NLMSG_LENGTH(len))
 #define NLMSG_DATA(nlh)  ((void*)(((char*)nlh) + NLMSG_LENGTH(0)))
 #define NLMSG_NEXT(nlh,len)	 ((len) -= NLMSG_ALIGN((nlh)->nlmsg_len), \
diff --git a/include/uapi/linux/netlink_diag.h b/include/uapi/linux/netlink_diag.h
new file mode 100644
index 0000000..88009a3
--- /dev/null
+++ b/include/uapi/linux/netlink_diag.h
@@ -0,0 +1,42 @@
+#ifndef __NETLINK_DIAG_H__
+#define __NETLINK_DIAG_H__
+
+#include <linux/types.h>
+
+struct netlink_diag_req {
+	__u8	sdiag_family;
+	__u8	sdiag_protocol;
+	__u16	pad;
+	__u32	ndiag_ino;
+	__u32	ndiag_show;
+	__u32	ndiag_cookie[2];
+};
+
+struct netlink_diag_msg {
+	__u8	ndiag_family;
+	__u8	ndiag_type;
+	__u8	ndiag_protocol;
+	__u8	ndiag_state;
+
+	__u32	ndiag_portid;
+	__u32	ndiag_dst_portid;
+	__u32	ndiag_dst_group;
+	__u32	ndiag_ino;
+	__u32	ndiag_cookie[2];
+};
+
+enum {
+	NETLINK_DIAG_MEMINFO,
+	NETLINK_DIAG_GROUPS,
+
+	__NETLINK_DIAG_MAX,
+};
+
+#define NETLINK_DIAG_MAX (__NETLINK_DIAG_MAX - 1)
+
+#define NDIAG_PROTO_ALL		((__u8) ~0)
+
+#define NDIAG_SHOW_MEMINFO	0x00000001 /* show memory info of a socket */
+#define NDIAG_SHOW_GROUPS	0x00000002 /* show groups of a netlink socket */
+
+#endif
diff --git a/include/uapi/linux/nfc.h b/include/uapi/linux/nfc.h
index 7969f46..7440bc8 100644
--- a/include/uapi/linux/nfc.h
+++ b/include/uapi/linux/nfc.h
@@ -90,6 +90,8 @@ enum nfc_commands {
 	NFC_CMD_LLC_SET_PARAMS,
 	NFC_CMD_ENABLE_SE,
 	NFC_CMD_DISABLE_SE,
+	NFC_CMD_LLC_SDREQ,
+	NFC_EVENT_LLC_SDRES,
 /* private: internal use only */
 	__NFC_CMD_AFTER_LAST
 };
@@ -140,11 +142,21 @@ enum nfc_attrs {
 	NFC_ATTR_LLC_PARAM_RW,
 	NFC_ATTR_LLC_PARAM_MIUX,
 	NFC_ATTR_SE,
+	NFC_ATTR_LLC_SDP,
 /* private: internal use only */
 	__NFC_ATTR_AFTER_LAST
 };
 #define NFC_ATTR_MAX (__NFC_ATTR_AFTER_LAST - 1)
 
+enum nfc_sdp_attr {
+	NFC_SDP_ATTR_UNSPEC,
+	NFC_SDP_ATTR_URI,
+	NFC_SDP_ATTR_SAP,
+/* private: internal use only */
+	__NFC_SDP_ATTR_AFTER_LAST
+};
+#define NFC_SDP_ATTR_MAX (__NFC_SDP_ATTR_AFTER_LAST - 1)
+
 #define NFC_DEVICE_NAME_MAXSIZE 8
 #define NFC_NFCID1_MAXSIZE 10
 #define NFC_SENSB_RES_MAXSIZE 12
@@ -220,4 +232,8 @@ struct sockaddr_nfc_llcp {
 #define NFC_LLCP_DIRECTION_RX		0x00
 #define NFC_LLCP_DIRECTION_TX		0x01
 
+/* socket option names */
+#define NFC_LLCP_RW   0
+#define NFC_LLCP_MIUX 1
+
 #endif /*__LINUX_NFC_H */
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index c46bb01..79da871 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -36,7 +36,21 @@
  * The station is still assumed to belong to the AP interface it was added
  * to.
  *
- * TODO: need more info?
+ * Station handling varies per interface type and depending on the driver's
+ * capabilities.
+ *
+ * For drivers supporting TDLS with external setup (WIPHY_FLAG_SUPPORTS_TDLS
+ * and WIPHY_FLAG_TDLS_EXTERNAL_SETUP), the station lifetime is as follows:
+ *  - a setup station entry is added, not yet authorized, without any rate
+ *    or capability information, this just exists to avoid race conditions
+ *  - when the TDLS setup is done, a single NL80211_CMD_SET_STATION is valid
+ *    to add rate and capability information to the station and at the same
+ *    time mark it authorized.
+ *  - %NL80211_TDLS_ENABLE_LINK is then used
+ *  - after this, the only valid operation is to remove it by tearing down
+ *    the TDLS link (%NL80211_TDLS_DISABLE_LINK)
+ *
+ * TODO: need more info for other interface types
  */
 
 /**
@@ -499,9 +513,11 @@
  * @NL80211_CMD_NEW_PEER_CANDIDATE: Notification on the reception of a
  *      beacon or probe response from a compatible mesh peer.  This is only
  *      sent while no station information (sta_info) exists for the new peer
- *      candidate and when @NL80211_MESH_SETUP_USERSPACE_AUTH is set.  On
- *      reception of this notification, userspace may decide to create a new
- *      station (@NL80211_CMD_NEW_STATION).  To stop this notification from
+ *      candidate and when @NL80211_MESH_SETUP_USERSPACE_AUTH,
+ *      @NL80211_MESH_SETUP_USERSPACE_AMPE, or
+ *      @NL80211_MESH_SETUP_USERSPACE_MPM is set.  On reception of this
+ *      notification, userspace may decide to create a new station
+ *      (@NL80211_CMD_NEW_STATION).  To stop this notification from
  *      reoccurring, the userspace authentication daemon may want to create the
  *      new station with the AUTHENTICATED flag unset and maybe change it later
  *      depending on the authentication result.
@@ -611,6 +627,18 @@
  *	%NL80211_ATTR_RADAR_EVENT is used to inform about the type of the
  *	event.
  *
+ * @NL80211_CMD_GET_PROTOCOL_FEATURES: Get global nl80211 protocol features,
+ *	i.e. features for the nl80211 protocol rather than device features.
+ *	Returns the features in the %NL80211_ATTR_PROTOCOL_FEATURES bitmap.
+ *
+ * @NL80211_CMD_UPDATE_FT_IES: Pass down the most up-to-date Fast Transition
+ *	Information Element to the WLAN driver
+ *
+ * @NL80211_CMD_FT_EVENT: Send a Fast transition event from the WLAN driver
+ *	to the supplicant. This will carry the target AP's MAC address along
+ *	with the relevant Information Elements. This event is used to report
+ *	received FT IEs (MDIE, FTIE, RSN IE, TIE, RICIE).
+ *
  * @NL80211_CMD_MAX: highest used command number
  * @__NL80211_CMD_AFTER_LAST: internal use
  */
@@ -765,6 +793,11 @@ enum nl80211_commands {
 
 	NL80211_CMD_RADAR_DETECT,
 
+	NL80211_CMD_GET_PROTOCOL_FEATURES,
+
+	NL80211_CMD_UPDATE_FT_IES,
+	NL80211_CMD_FT_EVENT,
+
 	/* add new commands above here */
 
 	/* used to define NL80211_CMD_MAX below */
@@ -884,7 +917,8 @@ enum nl80211_commands {
  *	consisting of a nested array.
  *
  * @NL80211_ATTR_MESH_ID: mesh id (1-32 bytes).
- * @NL80211_ATTR_STA_PLINK_ACTION: action to perform on the mesh peer link.
+ * @NL80211_ATTR_STA_PLINK_ACTION: action to perform on the mesh peer link
+ *	(see &enum nl80211_plink_action).
  * @NL80211_ATTR_MPATH_NEXT_HOP: MAC address of the next hop for a mesh path.
  * @NL80211_ATTR_MPATH_INFO: information about a mesh_path, part of mesh path
  * 	info given for %NL80211_CMD_GET_MPATH, nested attribute described at
@@ -1167,10 +1201,10 @@ enum nl80211_commands {
  * @NL80211_ATTR_SUPPORT_MESH_AUTH: Currently, this means the underlying driver
  *	allows auth frames in a mesh to be passed to userspace for processing via
  *	the @NL80211_MESH_SETUP_USERSPACE_AUTH flag.
- * @NL80211_ATTR_STA_PLINK_STATE: The state of a mesh peer link as
- *	defined in &enum nl80211_plink_state. Used when userspace is
- *	driving the peer link management state machine.
- *	@NL80211_MESH_SETUP_USERSPACE_AMPE must be enabled.
+ * @NL80211_ATTR_STA_PLINK_STATE: The state of a mesh peer link as defined in
+ *	&enum nl80211_plink_state. Used when userspace is driving the peer link
+ *	management state machine.  @NL80211_MESH_SETUP_USERSPACE_AMPE or
+ *	@NL80211_MESH_SETUP_USERSPACE_MPM must be enabled.
  *
  * @NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED: indicates, as part of the wiphy
  *	capabilities, the supported WoWLAN triggers
@@ -1368,6 +1402,18 @@ enum nl80211_commands {
  *	advertised to the driver, e.g., to enable TDLS off channel operations
  *	and PU-APSD.
  *
+ * @NL80211_ATTR_PROTOCOL_FEATURES: global nl80211 feature flags, see
+ *	&enum nl80211_protocol_features, the attribute is a u32.
+ *
+ * @NL80211_ATTR_SPLIT_WIPHY_DUMP: flag attribute, userspace supports
+ *	receiving the data for a single wiphy split across multiple
+ *	messages, given with wiphy dump message
+ *
+ * @NL80211_ATTR_MDID: Mobility Domain Identifier
+ *
+ * @NL80211_ATTR_IE_RIC: Resource Information Container Information
+ *	Element
+ *
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
  */
@@ -1654,6 +1700,15 @@ enum nl80211_attrs {
 	NL80211_ATTR_STA_CAPABILITY,
 	NL80211_ATTR_STA_EXT_CAPABILITY,
 
+	NL80211_ATTR_PROTOCOL_FEATURES,
+	NL80211_ATTR_SPLIT_WIPHY_DUMP,
+
+	NL80211_ATTR_DISABLE_VHT,
+	NL80211_ATTR_VHT_CAPABILITY_MASK,
+
+	NL80211_ATTR_MDID,
+	NL80211_ATTR_IE_RIC,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
@@ -2412,8 +2467,10 @@ enum nl80211_mesh_power_mode {
  * @NL80211_MESHCONF_TTL: specifies the value of TTL field set at a source mesh
  *	point.
  *
- * @NL80211_MESHCONF_AUTO_OPEN_PLINKS: whether we should automatically
- *	open peer links when we detect compatible mesh peers.
+ * @NL80211_MESHCONF_AUTO_OPEN_PLINKS: whether we should automatically open
+ *	peer links when we detect compatible mesh peers. Disabled if
+ *	@NL80211_MESH_SETUP_USERSPACE_MPM or @NL80211_MESH_SETUP_USERSPACE_AMPE are
+ *	set.
  *
  * @NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES: the number of action frames
  *	containing a PREQ that an MP can send to a particular destination (path
@@ -2559,6 +2616,9 @@ enum nl80211_meshconf_params {
  *	vendor specific synchronization method or disable it to use the default
  *	neighbor offset synchronization
  *
+ * @NL80211_MESH_SETUP_USERSPACE_MPM: Enable this option if userspace will
+ *	implement an MPM which handles peer allocation and state.
+ *
  * @NL80211_MESH_SETUP_ATTR_MAX: highest possible mesh setup attribute number
  *
  * @__NL80211_MESH_SETUP_ATTR_AFTER_LAST: Internal use
@@ -2571,6 +2631,7 @@ enum nl80211_mesh_setup_params {
 	NL80211_MESH_SETUP_USERSPACE_AUTH,
 	NL80211_MESH_SETUP_USERSPACE_AMPE,
 	NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC,
+	NL80211_MESH_SETUP_USERSPACE_MPM,
 
 	/* keep last */
 	__NL80211_MESH_SETUP_ATTR_AFTER_LAST,
@@ -3307,6 +3368,23 @@ enum nl80211_plink_state {
 	MAX_NL80211_PLINK_STATES = NUM_NL80211_PLINK_STATES - 1
 };
 
+/**
+ * enum nl80211_plink_action - actions to perform in mesh peers
+ *
+ * @NL80211_PLINK_ACTION_NO_ACTION: perform no action
+ * @NL80211_PLINK_ACTION_OPEN: start mesh peer link establishment
+ * @NL80211_PLINK_ACTION_BLOCK: block traffic from this mesh peer
+ * @NUM_NL80211_PLINK_ACTIONS: number of possible actions
+ */
+enum plink_actions {
+	NL80211_PLINK_ACTION_NO_ACTION,
+	NL80211_PLINK_ACTION_OPEN,
+	NL80211_PLINK_ACTION_BLOCK,
+
+	NUM_NL80211_PLINK_ACTIONS,
+};
+
+
 #define NL80211_KCK_LEN			16
 #define NL80211_KEK_LEN			16
 #define NL80211_REPLAY_CTR_LEN		8
@@ -3456,6 +3534,10 @@ enum nl80211_ap_sme_features {
  *	stations the authenticated/associated bits have to be set in the mask.
  * @NL80211_FEATURE_ADVERTISE_CHAN_LIMITS: cfg80211 advertises channel limits
  *	(HT40, VHT 80/160 MHz) if this flag is set
+ * @NL80211_FEATURE_USERSPACE_MPM: This driver supports a userspace Mesh
+ *	Peering Management entity which may be implemented by registering for
+ *	beacons or NL80211_CMD_NEW_PEER_CANDIDATE events. The mesh beacon is
+ *	still generated by the driver.
  */
 enum nl80211_feature_flags {
 	NL80211_FEATURE_SK_TX_STATUS			= 1 << 0,
@@ -3474,6 +3556,7 @@ enum nl80211_feature_flags {
 	/* bit 13 is reserved */
 	NL80211_FEATURE_ADVERTISE_CHAN_LIMITS		= 1 << 14,
 	NL80211_FEATURE_FULL_AP_CLIENT_STATE		= 1 << 15,
+	NL80211_FEATURE_USERSPACE_MPM			= 1 << 16,
 };
 
 /**
@@ -3587,4 +3670,16 @@ enum nl80211_dfs_state {
 	NL80211_DFS_AVAILABLE,
 };
 
+/**
+ * enum enum nl80211_protocol_features - nl80211 protocol features
+ * @NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP: nl80211 supports splitting
+ *	wiphy dumps (if requested by the application with the attribute
+ *	%NL80211_ATTR_SPLIT_WIPHY_DUMP. Also supported is filtering the
+ *	wiphy dump by %NL80211_ATTR_WIPHY, %NL80211_ATTR_IFINDEX or
+ *	%NL80211_ATTR_WDEV.
+ */
+enum nl80211_protocol_features {
+	NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP =	1 << 0,
+};
+
 #endif /* __LINUX_NL80211_H */
diff --git a/include/uapi/linux/pkt_sched.h b/include/uapi/linux/pkt_sched.h
index 32aef0a..dbd71b0 100644
--- a/include/uapi/linux/pkt_sched.h
+++ b/include/uapi/linux/pkt_sched.h
@@ -348,6 +348,7 @@ enum {
 	TCA_HTB_INIT,
 	TCA_HTB_CTAB,
 	TCA_HTB_RTAB,
+	TCA_HTB_DIRECT_QLEN,
 	__TCA_HTB_MAX,
 };
 
diff --git a/include/uapi/linux/ptrace.h b/include/uapi/linux/ptrace.h
index 022ab18..52ebcc8 100644
--- a/include/uapi/linux/ptrace.h
+++ b/include/uapi/linux/ptrace.h
@@ -5,6 +5,7 @@
 
 /* has the defines to get at the registers. */
 
+#include <linux/types.h>
 
 #define PTRACE_TRACEME		   0
 #define PTRACE_PEEKTEXT		   1
@@ -52,6 +53,17 @@
 #define PTRACE_INTERRUPT	0x4207
 #define PTRACE_LISTEN		0x4208
 
+#define PTRACE_PEEKSIGINFO	0x4209
+
+struct ptrace_peeksiginfo_args {
+	__u64 off;	/* from which siginfo to start */
+	__u32 flags;
+	__s32 nr;	/* how may siginfos to take */
+};
+
+/* Read signals from a shared (process wide) queue */
+#define PTRACE_PEEKSIGINFO_SHARED	(1 << 0)
+
 /* Wait extended result codes for the above trace options.  */
 #define PTRACE_EVENT_FORK	1
 #define PTRACE_EVENT_VFORK	2
diff --git a/include/uapi/linux/snmp.h b/include/uapi/linux/snmp.h
index b49eab8..e00013a 100644
--- a/include/uapi/linux/snmp.h
+++ b/include/uapi/linux/snmp.h
@@ -202,6 +202,8 @@ enum
 	LINUX_MIB_TCPFORWARDRETRANS,		/* TCPForwardRetrans */
 	LINUX_MIB_TCPSLOWSTARTRETRANS,		/* TCPSlowStartRetrans */
 	LINUX_MIB_TCPTIMEOUTS,			/* TCPTimeouts */
+	LINUX_MIB_TCPLOSSPROBES,		/* TCPLossProbes */
+	LINUX_MIB_TCPLOSSPROBERECOVERY,		/* TCPLossProbeRecovery */
 	LINUX_MIB_TCPRENORECOVERYFAIL,		/* TCPRenoRecoveryFail */
 	LINUX_MIB_TCPSACKRECOVERYFAIL,		/* TCPSackRecoveryFail */
 	LINUX_MIB_TCPSCHEDULERFAILED,		/* TCPSchedulerFailed */
diff --git a/include/uapi/linux/tcp.h b/include/uapi/linux/tcp.h
index 6b1ead0..8d776eb 100644
--- a/include/uapi/linux/tcp.h
+++ b/include/uapi/linux/tcp.h
@@ -102,7 +102,6 @@ enum {
 #define TCP_QUICKACK		12	/* Block/reenable quick acks */
 #define TCP_CONGESTION		13	/* Congestion control algorithm */
 #define TCP_MD5SIG		14	/* TCP MD5 Signature (RFC2385) */
-#define TCP_COOKIE_TRANSACTIONS	15	/* TCP Cookie Transactions */
 #define TCP_THIN_LINEAR_TIMEOUTS 16      /* Use linear timeouts for thin streams*/
 #define TCP_THIN_DUPACK         17      /* Fast retrans. after 1 dupack */
 #define TCP_USER_TIMEOUT	18	/* How long for loss retry before timeout */
@@ -199,29 +198,4 @@ struct tcp_md5sig {
 	__u8	tcpm_key[TCP_MD5SIG_MAXKEYLEN];		/* key (binary) */
 };
 
-/* for TCP_COOKIE_TRANSACTIONS (TCPCT) socket option */
-#define TCP_COOKIE_MIN		 8		/*  64-bits */
-#define TCP_COOKIE_MAX		16		/* 128-bits */
-#define TCP_COOKIE_PAIR_SIZE	(2*TCP_COOKIE_MAX)
-
-/* Flags for both getsockopt and setsockopt */
-#define TCP_COOKIE_IN_ALWAYS	(1 << 0)	/* Discard SYN without cookie */
-#define TCP_COOKIE_OUT_NEVER	(1 << 1)	/* Prohibit outgoing cookies,
-						 * supercedes everything. */
-
-/* Flags for getsockopt */
-#define TCP_S_DATA_IN		(1 << 2)	/* Was data received? */
-#define TCP_S_DATA_OUT		(1 << 3)	/* Was data sent? */
-
-/* TCP_COOKIE_TRANSACTIONS data */
-struct tcp_cookie_transactions {
-	__u16	tcpct_flags;			/* see above */
-	__u8	__tcpct_pad1;			/* zero */
-	__u8	tcpct_cookie_desired;		/* bytes */
-	__u16	tcpct_s_data_desired;		/* bytes of variable data */
-	__u16	tcpct_used;			/* bytes in value */
-	__u8	tcpct_value[TCP_MSS_DEFAULT];
-};
-
-
 #endif /* _UAPI_LINUX_TCP_H */
diff --git a/include/uapi/linux/usb/cdc-wdm.h b/include/uapi/linux/usb/cdc-wdm.h
new file mode 100644
index 0000000..f03134f
--- /dev/null
+++ b/include/uapi/linux/usb/cdc-wdm.h
@@ -0,0 +1,21 @@
+/*
+ * USB CDC Device Management userspace API 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 _UAPI__LINUX_USB_CDC_WDM_H
+#define _UAPI__LINUX_USB_CDC_WDM_H
+
+/*
+ * This IOCTL is used to retrieve the wMaxCommand for the device,
+ * defining the message limit for both reading and writing.
+ *
+ * For CDC WDM functions this will be the wMaxCommand field of the
+ * Device Management Functional Descriptor.
+ */
+#define IOCTL_WDM_MAX_COMMAND _IOR('H', 0xA0, __u16)
+
+#endif /* _UAPI__LINUX_USB_CDC_WDM_H */
diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h
index dcd6374..844dc02 100644
--- a/include/uapi/linux/v4l2-controls.h
+++ b/include/uapi/linux/v4l2-controls.h
@@ -146,6 +146,15 @@ enum v4l2_colorfx {
  * of controls. We reserve 16 controls for this driver. */
 #define V4L2_CID_USER_MEYE_BASE			(V4L2_CID_USER_BASE + 0x1000)
 
+/* The base for the bttv driver controls.
+ * We reserve 32 controls for this driver. */
+#define V4L2_CID_USER_BTTV_BASE			(V4L2_CID_USER_BASE + 0x1010)
+
+
+/* The base for the s2255 driver controls.
+ * We reserve 8 controls for this driver. */
+#define V4L2_CID_USER_S2255_BASE		(V4L2_CID_USER_BASE + 0x1010)
+
 /* MPEG-class control IDs */
 
 #define V4L2_CID_MPEG_BASE 			(V4L2_CTRL_CLASS_MPEG | 0x900)
@@ -351,6 +360,7 @@ enum v4l2_mpeg_video_multi_slice_mode {
 #define V4L2_CID_MPEG_VIDEO_DEC_PTS			(V4L2_CID_MPEG_BASE+223)
 #define V4L2_CID_MPEG_VIDEO_DEC_FRAME			(V4L2_CID_MPEG_BASE+224)
 #define V4L2_CID_MPEG_VIDEO_VBV_DELAY			(V4L2_CID_MPEG_BASE+225)
+#define V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER		(V4L2_CID_MPEG_BASE+226)
 
 #define V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP		(V4L2_CID_MPEG_BASE+300)
 #define V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP		(V4L2_CID_MPEG_BASE+301)
diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
index 4f41f30..284ff24 100644
--- a/include/uapi/linux/vfio.h
+++ b/include/uapi/linux/vfio.h
@@ -319,6 +319,7 @@ enum {
 	VFIO_PCI_INTX_IRQ_INDEX,
 	VFIO_PCI_MSI_IRQ_INDEX,
 	VFIO_PCI_MSIX_IRQ_INDEX,
+	VFIO_PCI_ERR_IRQ_INDEX,
 	VFIO_PCI_NUM_IRQS
 };
 
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 234d1d8..e9c49c5 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -705,6 +705,7 @@ struct v4l2_buffer {
 #define V4L2_BUF_FLAG_TIMESTAMP_MASK		0xe000
 #define V4L2_BUF_FLAG_TIMESTAMP_UNKNOWN		0x0000
 #define V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC	0x2000
+#define V4L2_BUF_FLAG_TIMESTAMP_COPY		0x4000
 
 /**
  * struct v4l2_exportbuffer - export of video buffer as DMABUF file descriptor
@@ -980,52 +981,6 @@ struct v4l2_standard {
 	__u32		     reserved[4];
 };
 
-/* The DV Preset API is deprecated in favor of the DV Timings API.
-   New drivers shouldn't use this anymore! */
-
-/*
- *	V I D E O	T I M I N G S	D V	P R E S E T
- */
-struct v4l2_dv_preset {
-	__u32	preset;
-	__u32	reserved[4];
-};
-
-/*
- *	D V	P R E S E T S	E N U M E R A T I O N
- */
-struct v4l2_dv_enum_preset {
-	__u32	index;
-	__u32	preset;
-	__u8	name[32]; /* Name of the preset timing */
-	__u32	width;
-	__u32	height;
-	__u32	reserved[4];
-};
-
-/*
- * 	D V	P R E S E T	V A L U E S
- */
-#define		V4L2_DV_INVALID		0
-#define		V4L2_DV_480P59_94	1 /* BT.1362 */
-#define		V4L2_DV_576P50		2 /* BT.1362 */
-#define		V4L2_DV_720P24		3 /* SMPTE 296M */
-#define		V4L2_DV_720P25		4 /* SMPTE 296M */
-#define		V4L2_DV_720P30		5 /* SMPTE 296M */
-#define		V4L2_DV_720P50		6 /* SMPTE 296M */
-#define		V4L2_DV_720P59_94	7 /* SMPTE 274M */
-#define		V4L2_DV_720P60		8 /* SMPTE 274M/296M */
-#define		V4L2_DV_1080I29_97	9 /* BT.1120/ SMPTE 274M */
-#define		V4L2_DV_1080I30		10 /* BT.1120/ SMPTE 274M */
-#define		V4L2_DV_1080I25		11 /* BT.1120 */
-#define		V4L2_DV_1080I50		12 /* SMPTE 296M */
-#define		V4L2_DV_1080I60		13 /* SMPTE 296M */
-#define		V4L2_DV_1080P24		14 /* SMPTE 296M */
-#define		V4L2_DV_1080P25		15 /* SMPTE 296M */
-#define		V4L2_DV_1080P30		16 /* SMPTE 296M */
-#define		V4L2_DV_1080P50		17 /* BT.1120 */
-#define		V4L2_DV_1080P60		18 /* BT.1120 */
-
 /*
  *	D V 	B T	T I M I N G S
  */
@@ -1239,7 +1194,6 @@ struct v4l2_input {
 #define V4L2_IN_ST_VTR         0x04000000  /* VTR time constant */
 
 /* capabilities flags */
-#define V4L2_IN_CAP_PRESETS		0x00000001 /* Supports S_DV_PRESET */
 #define V4L2_IN_CAP_DV_TIMINGS		0x00000002 /* Supports S_DV_TIMINGS */
 #define V4L2_IN_CAP_CUSTOM_TIMINGS	V4L2_IN_CAP_DV_TIMINGS /* For compatibility */
 #define V4L2_IN_CAP_STD			0x00000004 /* Supports S_STD */
@@ -1263,7 +1217,6 @@ struct v4l2_output {
 #define V4L2_OUTPUT_TYPE_ANALOGVGAOVERLAY	3
 
 /* capabilities flags */
-#define V4L2_OUT_CAP_PRESETS		0x00000001 /* Supports S_DV_PRESET */
 #define V4L2_OUT_CAP_DV_TIMINGS		0x00000002 /* Supports S_DV_TIMINGS */
 #define V4L2_OUT_CAP_CUSTOM_TIMINGS	V4L2_OUT_CAP_DV_TIMINGS /* For compatibility */
 #define V4L2_OUT_CAP_STD		0x00000004 /* Supports S_STD */
@@ -1854,10 +1807,13 @@ struct v4l2_event_subscription {
 
 /* VIDIOC_DBG_G_REGISTER and VIDIOC_DBG_S_REGISTER */
 
-#define V4L2_CHIP_MATCH_HOST       0  /* Match against chip ID on host (0 for the host) */
-#define V4L2_CHIP_MATCH_I2C_DRIVER 1  /* Match against I2C driver name */
-#define V4L2_CHIP_MATCH_I2C_ADDR   2  /* Match against I2C 7-bit address */
-#define V4L2_CHIP_MATCH_AC97       3  /* Match against anciliary AC97 chip */
+#define V4L2_CHIP_MATCH_BRIDGE      0  /* Match against chip ID on the bridge (0 for the bridge) */
+#define V4L2_CHIP_MATCH_HOST V4L2_CHIP_MATCH_BRIDGE
+#define V4L2_CHIP_MATCH_I2C_DRIVER  1  /* Match against I2C driver name */
+#define V4L2_CHIP_MATCH_I2C_ADDR    2  /* Match against I2C 7-bit address */
+#define V4L2_CHIP_MATCH_AC97        3  /* Match against anciliary AC97 chip */
+#define V4L2_CHIP_MATCH_SUBDEV_NAME 4  /* Match against subdev name */
+#define V4L2_CHIP_MATCH_SUBDEV_IDX  5  /* Match against subdev index */
 
 struct v4l2_dbg_match {
 	__u32 type; /* Match type */
@@ -1881,6 +1837,17 @@ struct v4l2_dbg_chip_ident {
 	__u32 revision;    /* chip revision, chip specific */
 } __attribute__ ((packed));
 
+#define V4L2_CHIP_FL_READABLE (1 << 0)
+#define V4L2_CHIP_FL_WRITABLE (1 << 1)
+
+/* VIDIOC_DBG_G_CHIP_NAME */
+struct v4l2_dbg_chip_name {
+	struct v4l2_dbg_match match;
+	char name[32];
+	__u32 flags;
+	__u32 reserved[8];
+} __attribute__ ((packed));
+
 /**
  * struct v4l2_create_buffers - VIDIOC_CREATE_BUFS argument
  * @index:	on return, index of the first created buffer
@@ -1958,15 +1925,12 @@ struct v4l2_create_buffers {
 #define VIDIOC_G_EXT_CTRLS	_IOWR('V', 71, struct v4l2_ext_controls)
 #define VIDIOC_S_EXT_CTRLS	_IOWR('V', 72, struct v4l2_ext_controls)
 #define VIDIOC_TRY_EXT_CTRLS	_IOWR('V', 73, struct v4l2_ext_controls)
-#if 1
 #define VIDIOC_ENUM_FRAMESIZES	_IOWR('V', 74, struct v4l2_frmsizeenum)
 #define VIDIOC_ENUM_FRAMEINTERVALS _IOWR('V', 75, struct v4l2_frmivalenum)
 #define VIDIOC_G_ENC_INDEX       _IOR('V', 76, struct v4l2_enc_idx)
 #define VIDIOC_ENCODER_CMD      _IOWR('V', 77, struct v4l2_encoder_cmd)
 #define VIDIOC_TRY_ENCODER_CMD  _IOWR('V', 78, struct v4l2_encoder_cmd)
-#endif
 
-#if 1
 /* Experimental, meant for debugging, testing and internal use.
    Only implemented if CONFIG_VIDEO_ADV_DEBUG is defined.
    You must be root to use these ioctls. Never use these in applications! */
@@ -1974,18 +1938,13 @@ struct v4l2_create_buffers {
 #define	VIDIOC_DBG_G_REGISTER 	_IOWR('V', 80, struct v4l2_dbg_register)
 
 /* Experimental, meant for debugging, testing and internal use.
-   Never use this ioctl in applications! */
+   Never use this ioctl in applications!
+   Note: this ioctl is deprecated in favor of VIDIOC_DBG_G_CHIP_NAME and
+   will go away in the future. */
 #define VIDIOC_DBG_G_CHIP_IDENT _IOWR('V', 81, struct v4l2_dbg_chip_ident)
-#endif
 
 #define VIDIOC_S_HW_FREQ_SEEK	 _IOW('V', 82, struct v4l2_hw_freq_seek)
 
-/* These four DV Preset ioctls are deprecated in favor of the DV Timings
-   ioctls. */
-#define	VIDIOC_ENUM_DV_PRESETS	_IOWR('V', 83, struct v4l2_dv_enum_preset)
-#define	VIDIOC_S_DV_PRESET	_IOWR('V', 84, struct v4l2_dv_preset)
-#define	VIDIOC_G_DV_PRESET	_IOWR('V', 85, struct v4l2_dv_preset)
-#define	VIDIOC_QUERY_DV_PRESET	_IOR('V',  86, struct v4l2_dv_preset)
 #define	VIDIOC_S_DV_TIMINGS	_IOWR('V', 87, struct v4l2_dv_timings)
 #define	VIDIOC_G_DV_TIMINGS	_IOWR('V', 88, struct v4l2_dv_timings)
 #define	VIDIOC_DQEVENT		 _IOR('V', 89, struct v4l2_event)
@@ -2016,6 +1975,10 @@ struct v4l2_create_buffers {
    versions. */
 #define VIDIOC_ENUM_FREQ_BANDS	_IOWR('V', 101, struct v4l2_frequency_band)
 
+/* Experimental, meant for debugging, testing and internal use.
+   Never use these in applications! */
+#define VIDIOC_DBG_G_CHIP_NAME  _IOWR('V', 102, struct v4l2_dbg_chip_name)
+
 /* Reminder: when adding new ioctls please add support for them to
    drivers/media/video/v4l2-compat-ioctl32.c as well! */
 
diff --git a/include/uapi/linux/virtio_balloon.h b/include/uapi/linux/virtio_balloon.h
index 652dc8b..5e26f61 100644
--- a/include/uapi/linux/virtio_balloon.h
+++ b/include/uapi/linux/virtio_balloon.h
@@ -52,8 +52,8 @@ struct virtio_balloon_config
 #define VIRTIO_BALLOON_S_NR       6
 
 struct virtio_balloon_stat {
-	u16 tag;
-	u64 val;
+	__u16 tag;
+	__u64 val;
 } __attribute__((packed));
 
 #endif /* _LINUX_VIRTIO_BALLOON_H */
diff --git a/include/uapi/linux/virtio_ids.h b/include/uapi/linux/virtio_ids.h
index a7630d0..284fc3a 100644
--- a/include/uapi/linux/virtio_ids.h
+++ b/include/uapi/linux/virtio_ids.h
@@ -38,5 +38,6 @@
 #define VIRTIO_ID_SCSI		8 /* virtio scsi */
 #define VIRTIO_ID_9P		9 /* 9p virtio console */
 #define VIRTIO_ID_RPROC_SERIAL 11 /* virtio remoteproc serial link */
+#define VIRTIO_ID_CAIF	       12 /* Virtio caif */
 
 #endif /* _LINUX_VIRTIO_IDS_H */
diff --git a/include/uapi/linux/vm_sockets.h b/include/uapi/linux/vm_sockets.h
index df91301..b4ed5d8 100644
--- a/include/uapi/linux/vm_sockets.h
+++ b/include/uapi/linux/vm_sockets.h
@@ -13,12 +13,10 @@
  * more details.
  */
 
-#ifndef _VM_SOCKETS_H_
-#define _VM_SOCKETS_H_
+#ifndef _UAPI_VM_SOCKETS_H
+#define _UAPI_VM_SOCKETS_H
 
-#if !defined(__KERNEL__)
-#include <sys/socket.h>
-#endif
+#include <linux/socket.h>
 
 /* Option name for STREAM socket buffer size.  Use as the option name in
  * setsockopt(3) or getsockopt(3) to set or get an unsigned long long that
@@ -137,14 +135,13 @@
 #define VM_SOCKETS_VERSION_MINOR(_v) (((_v) & 0x0000FFFF))
 
 /* Address structure for vSockets.   The address family should be set to
- * whatever vmci_sock_get_af_value_fd() returns.  The structure members should
- * all align on their natural boundaries without resorting to compiler packing
- * directives.  The total size of this structure should be exactly the same as
- * that of struct sockaddr.
+ * AF_VSOCK.  The structure members should all align on their natural
+ * boundaries without resorting to compiler packing directives.  The total size
+ * of this structure should be exactly the same as that of struct sockaddr.
  */
 
 struct sockaddr_vm {
-	sa_family_t svm_family;
+	__kernel_sa_family_t svm_family;
 	unsigned short svm_reserved1;
 	unsigned int svm_port;
 	unsigned int svm_cid;
@@ -156,8 +153,4 @@ struct sockaddr_vm {
 
 #define IOCTL_VM_SOCKETS_GET_LOCAL_CID		_IO(7, 0xb9)
 
-#if defined(__KERNEL__)
-int vm_sockets_get_local_cid(void);
-#endif
-
-#endif
+#endif /* _UAPI_VM_SOCKETS_H */
diff --git a/include/uapi/linux/xfrm.h b/include/uapi/linux/xfrm.h
index 28e493b..a8cd6a4 100644
--- a/include/uapi/linux/xfrm.h
+++ b/include/uapi/linux/xfrm.h
@@ -297,6 +297,7 @@ enum xfrm_attr_type_t {
 	XFRMA_MARK,		/* struct xfrm_mark */
 	XFRMA_TFCPAD,		/* __u32 */
 	XFRMA_REPLAY_ESN_VAL,	/* struct xfrm_replay_esn */
+	XFRMA_SA_EXTRA_FLAGS,	/* __u32 */
 	__XFRMA_MAX
 
 #define XFRMA_MAX (__XFRMA_MAX - 1)
@@ -367,6 +368,8 @@ struct xfrm_usersa_info {
 #define XFRM_STATE_ESN		128
 };
 
+#define XFRM_SA_XFLAG_DONT_ENCAP_DSCP	1
+
 struct xfrm_usersa_id {
 	xfrm_address_t			daddr;
 	__be32				spi;
diff --git a/include/video/atmel_lcdc.h b/include/video/atmel_lcdc.h
index 8deb226..0f5a2fc 100644
--- a/include/video/atmel_lcdc.h
+++ b/include/video/atmel_lcdc.h
@@ -31,6 +31,7 @@
 #define ATMEL_LCDC_WIRING_BGR	0
 #define ATMEL_LCDC_WIRING_RGB	1
 
+struct atmel_lcdfb_config;
 
  /* LCD Controller info data structure, stored in device platform_data */
 struct atmel_lcdfb_info {
@@ -61,7 +62,8 @@ struct atmel_lcdfb_info {
 	void (*atmel_lcdfb_power_control)(int on);
 	struct fb_monspecs	*default_monspecs;
 	u32			pseudo_palette[16];
-	bool			have_intensity_bit;
+
+	struct atmel_lcdfb_config *config;
 };
 
 #define ATMEL_LCDC_DMABADDR1	0x00
diff --git a/include/video/auo_k190xfb.h b/include/video/auo_k190xfb.h
index 609efe8..ac329ee 100644
--- a/include/video/auo_k190xfb.h
+++ b/include/video/auo_k190xfb.h
@@ -22,6 +22,8 @@
  */
 #define AUOK190X_RESOLUTION_800_600		0
 #define AUOK190X_RESOLUTION_1024_768		1
+#define AUOK190X_RESOLUTION_600_800		4
+#define AUOK190X_RESOLUTION_768_1024		5
 
 /*
  * struct used by auok190x. board specific stuff comes from *board
@@ -98,7 +100,6 @@ struct auok190x_board {
 	int gpio_nbusy;
 
 	int resolution;
-	int rotation;
 	int quirks;
 	int fps;
 };
diff --git a/include/video/omap-panel-data.h b/include/video/omap-panel-data.h
new file mode 100644
index 0000000..0c3b46d
--- /dev/null
+++ b/include/video/omap-panel-data.h
@@ -0,0 +1,150 @@
+/*
+ * Header containing platform_data structs for omap panels
+ *
+ * Copyright (C) 2013 Texas Instruments
+ * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
+ *	   Archit Taneja <archit@ti.com>
+ *
+ * Copyright (C) 2011 Texas Instruments
+ * Author: Mayuresh Janorkar <mayur@ti.com>
+ *
+ * Copyright (C) 2010 Canonical Ltd.
+ * Author: Bryan Wu <bryan.wu@canonical.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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __OMAP_PANEL_DATA_H
+#define __OMAP_PANEL_DATA_H
+
+struct omap_dss_device;
+
+/**
+ * struct panel_generic_dpi_data - panel driver configuration data
+ * @name: panel name
+ * @platform_enable: platform specific panel enable function
+ * @platform_disable: platform specific panel disable function
+ * @num_gpios: number of gpios connected to panel
+ * @gpios: gpio numbers on the platform
+ * @gpio_invert: configure gpio as active high or low
+ */
+struct panel_generic_dpi_data {
+	const char *name;
+	int (*platform_enable)(struct omap_dss_device *dssdev);
+	void (*platform_disable)(struct omap_dss_device *dssdev);
+
+	int num_gpios;
+	int gpios[10];
+	bool gpio_invert[10];
+};
+
+/**
+ * struct panel_n8x0_data - N800 panel driver configuration data
+ */
+struct panel_n8x0_data {
+	int (*platform_enable)(struct omap_dss_device *dssdev);
+	void (*platform_disable)(struct omap_dss_device *dssdev);
+	int panel_reset;
+	int ctrl_pwrdown;
+};
+
+/**
+ * struct nokia_dsi_panel_data - Nokia DSI panel driver configuration data
+ * @name: panel name
+ * @use_ext_te: use external TE
+ * @ext_te_gpio: external TE GPIO
+ * @esd_interval: interval of ESD checks, 0 = disabled (ms)
+ * @ulps_timeout: time to wait before entering ULPS, 0 = disabled (ms)
+ * @use_dsi_backlight: true if panel uses DSI command to control backlight
+ * @pin_config: DSI pin configuration
+ */
+
+struct nokia_dsi_panel_data {
+	const char *name;
+
+	int reset_gpio;
+
+	bool use_ext_te;
+	int ext_te_gpio;
+
+	unsigned esd_interval;
+	unsigned ulps_timeout;
+
+	bool use_dsi_backlight;
+
+	struct omap_dsi_pin_config pin_config;
+};
+
+/**
+ * struct picodlp_panel_data - picodlp panel driver configuration data
+ * @picodlp_adapter_id:	i2c_adapter number for picodlp
+ */
+struct picodlp_panel_data {
+	int picodlp_adapter_id;
+	int emu_done_gpio;
+	int pwrgood_gpio;
+};
+
+/**
+ * struct tfp410_platform_data - tfp410 panel driver configuration data
+ * @i2c_bus_num: i2c bus id for the panel
+ * @power_down_gpio: gpio number for PD pin (or -1 if not available)
+ */
+struct tfp410_platform_data {
+	int i2c_bus_num;
+	int power_down_gpio;
+};
+
+/**
+ * sharp ls panel driver configuration data
+ * @resb_gpio: reset signal
+ * @ini_gpio: power on control
+ * @mo_gpio: selection for resolution(VGA/QVGA)
+ * @lr_gpio: selection for horizontal scanning direction
+ * @ud_gpio: selection for vertical scanning direction
+ */
+struct panel_sharp_ls037v7dw01_data {
+	int resb_gpio;
+	int ini_gpio;
+	int mo_gpio;
+	int lr_gpio;
+	int ud_gpio;
+};
+
+/**
+ * acx565akm panel driver configuration data
+ * @reset_gpio: reset signal
+ */
+struct panel_acx565akm_data {
+	int reset_gpio;
+};
+
+/**
+ * nec nl8048 panel driver configuration data
+ * @res_gpio: reset signal
+ * @qvga_gpio: selection for resolution(QVGA/WVGA)
+ */
+struct panel_nec_nl8048_data {
+	int res_gpio;
+	int qvga_gpio;
+};
+
+/**
+ * tpo td043 panel driver configuration data
+ * @nreset_gpio: reset signal
+ */
+struct panel_tpo_td043_data {
+	int nreset_gpio;
+};
+
+#endif /* __OMAP_PANEL_DATA_H */
diff --git a/include/video/omap-panel-generic-dpi.h b/include/video/omap-panel-generic-dpi.h
deleted file mode 100644
index 127e3f2..0000000
--- a/include/video/omap-panel-generic-dpi.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Header for generic DPI panel driver
- *
- * Copyright (C) 2010 Canonical Ltd.
- * Author: Bryan Wu <bryan.wu@canonical.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, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __OMAP_PANEL_GENERIC_DPI_H
-#define __OMAP_PANEL_GENERIC_DPI_H
-
-struct omap_dss_device;
-
-/**
- * struct panel_generic_dpi_data - panel driver configuration data
- * @name: panel name
- * @platform_enable: platform specific panel enable function
- * @platform_disable: platform specific panel disable function
- */
-struct panel_generic_dpi_data {
-	const char *name;
-	int (*platform_enable)(struct omap_dss_device *dssdev);
-	void (*platform_disable)(struct omap_dss_device *dssdev);
-};
-
-#endif /* __OMAP_PANEL_GENERIC_DPI_H */
diff --git a/include/video/omap-panel-n8x0.h b/include/video/omap-panel-n8x0.h
deleted file mode 100644
index 50a1302..0000000
--- a/include/video/omap-panel-n8x0.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef __OMAP_PANEL_N8X0_H
-#define __OMAP_PANEL_N8X0_H
-
-struct omap_dss_device;
-
-struct panel_n8x0_data {
-	int (*platform_enable)(struct omap_dss_device *dssdev);
-	void (*platform_disable)(struct omap_dss_device *dssdev);
-	int panel_reset;
-	int ctrl_pwrdown;
-
-	int (*set_backlight)(struct omap_dss_device *dssdev, int level);
-};
-
-#endif
diff --git a/include/video/omap-panel-nokia-dsi.h b/include/video/omap-panel-nokia-dsi.h
deleted file mode 100644
index 04219a2..0000000
--- a/include/video/omap-panel-nokia-dsi.h
+++ /dev/null
@@ -1,32 +0,0 @@
-#ifndef __OMAP_NOKIA_DSI_PANEL_H
-#define __OMAP_NOKIA_DSI_PANEL_H
-
-struct omap_dss_device;
-
-/**
- * struct nokia_dsi_panel_data - Nokia DSI panel driver configuration
- * @name: panel name
- * @use_ext_te: use external TE
- * @ext_te_gpio: external TE GPIO
- * @esd_interval: interval of ESD checks, 0 = disabled (ms)
- * @ulps_timeout: time to wait before entering ULPS, 0 = disabled (ms)
- * @use_dsi_backlight: true if panel uses DSI command to control backlight
- * @pin_config: DSI pin configuration
- */
-struct nokia_dsi_panel_data {
-	const char *name;
-
-	int reset_gpio;
-
-	bool use_ext_te;
-	int ext_te_gpio;
-
-	unsigned esd_interval;
-	unsigned ulps_timeout;
-
-	bool use_dsi_backlight;
-
-	struct omap_dsi_pin_config pin_config;
-};
-
-#endif /* __OMAP_NOKIA_DSI_PANEL_H */
diff --git a/include/video/omap-panel-picodlp.h b/include/video/omap-panel-picodlp.h
deleted file mode 100644
index 1c342ef..0000000
--- a/include/video/omap-panel-picodlp.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * panel data for picodlp panel
- *
- * Copyright (C) 2011 Texas Instruments
- *
- * Author: Mayuresh Janorkar <mayur@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.
- */
-#ifndef __PANEL_PICODLP_H
-#define __PANEL_PICODLP_H
-/**
- * struct : picodlp panel data
- * picodlp_adapter_id:	i2c_adapter number for picodlp
- */
-struct picodlp_panel_data {
-	int picodlp_adapter_id;
-	int emu_done_gpio;
-	int pwrgood_gpio;
-};
-#endif /* __PANEL_PICODLP_H */
diff --git a/include/video/omap-panel-tfp410.h b/include/video/omap-panel-tfp410.h
deleted file mode 100644
index aef35e4..0000000
--- a/include/video/omap-panel-tfp410.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Header for TFP410 chip driver
- *
- * Copyright (C) 2011 Texas Instruments Inc
- * Author: Tomi Valkeinen <tomi.valkeinen@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, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __OMAP_PANEL_TFP410_H
-#define __OMAP_PANEL_TFP410_H
-
-struct omap_dss_device;
-
-/**
- * struct tfp410_platform_data - panel driver configuration data
- * @i2c_bus_num: i2c bus id for the panel
- * @power_down_gpio: gpio number for PD pin (or -1 if not available)
- */
-struct tfp410_platform_data {
-	int i2c_bus_num;
-	int power_down_gpio;
-};
-
-#endif /* __OMAP_PANEL_TFP410_H */
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index caefa09..62ca9a7 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -257,10 +257,31 @@ void rfbi_bus_unlock(void);
 
 /* DSI */
 
+enum omap_dss_dsi_trans_mode {
+	/* Sync Pulses: both sync start and end packets sent */
+	OMAP_DSS_DSI_PULSE_MODE,
+	/* Sync Events: only sync start packets sent */
+	OMAP_DSS_DSI_EVENT_MODE,
+	/* Burst: only sync start packets sent, pixels are time compressed */
+	OMAP_DSS_DSI_BURST_MODE,
+};
+
 struct omap_dss_dsi_videomode_timings {
+	unsigned long hsclk;
+
+	unsigned ndl;
+	unsigned bitspp;
+
+	/* pixels */
+	u16 hact;
+	/* lines */
+	u16 vact;
+
 	/* DSI video mode blanking data */
 	/* Unit: byte clock cycles */
+	u16 hss;
 	u16 hsa;
+	u16 hse;
 	u16 hfp;
 	u16 hbp;
 	/* Unit: line clocks */
@@ -274,14 +295,24 @@ struct omap_dss_dsi_videomode_timings {
 	int hbp_blanking_mode;
 	int hfp_blanking_mode;
 
-	/* Video port sync events */
-	bool vp_vsync_end;
-	bool vp_hsync_end;
+	enum omap_dss_dsi_trans_mode trans_mode;
 
 	bool ddr_clk_always_on;
 	int window_sync;
 };
 
+struct omap_dss_dsi_config {
+	enum omap_dss_dsi_mode mode;
+	enum omap_dss_dsi_pixel_format pixel_format;
+	const struct omap_video_timings *timings;
+
+	unsigned long hs_clk_min, hs_clk_max;
+	unsigned long lp_clk_min, lp_clk_max;
+
+	bool ddr_clk_always_on;
+	enum omap_dss_dsi_trans_mode trans_mode;
+};
+
 void dsi_bus_lock(struct omap_dss_device *dssdev);
 void dsi_bus_unlock(struct omap_dss_device *dssdev);
 int dsi_vc_dcs_write(struct omap_dss_device *dssdev, int channel, u8 *data,
@@ -541,9 +572,14 @@ struct omap_dss_writeback_info {
 struct omap_dss_output {
 	struct list_head list;
 
+	const char *name;
+
 	/* display type supported by the output */
 	enum omap_display_type type;
 
+	/* DISPC channel for this output */
+	enum omap_channel dispc_channel;
+
 	/* output instance */
 	enum omap_dss_output_id id;
 
@@ -561,6 +597,7 @@ struct omap_dss_device {
 
 	enum omap_display_type type;
 
+	/* obsolete, to be removed */
 	enum omap_channel channel;
 
 	union {
@@ -591,40 +628,10 @@ struct omap_dss_device {
 	} phy;
 
 	struct {
-		struct {
-			struct {
-				u16 lck_div;
-				u16 pck_div;
-				enum omap_dss_clk_source lcd_clk_src;
-			} channel;
-
-			enum omap_dss_clk_source dispc_fclk_src;
-		} dispc;
-
-		struct {
-			/* regn is one greater than TRM's REGN value */
-			u16 regn;
-			u16 regm;
-			u16 regm_dispc;
-			u16 regm_dsi;
-
-			u16 lp_clk_div;
-			enum omap_dss_clk_source dsi_fclk_src;
-		} dsi;
-
-		struct {
-			/* regn is one greater than TRM's REGN value */
-			u16 regn;
-			u16 regm2;
-		} hdmi;
-	} clocks;
-
-	struct {
 		struct omap_video_timings timings;
 
 		enum omap_dss_dsi_pixel_format dsi_pix_fmt;
 		enum omap_dss_dsi_mode dsi_mode;
-		struct omap_dss_dsi_videomode_timings dsi_vm_timings;
 	} panel;
 
 	struct {
@@ -829,15 +836,8 @@ int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
 void omapdss_dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel,
 		bool enable);
 int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable);
-void omapdss_dsi_set_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings);
-void omapdss_dsi_set_size(struct omap_dss_device *dssdev, u16 w, u16 h);
-void omapdss_dsi_set_pixel_format(struct omap_dss_device *dssdev,
-		enum omap_dss_dsi_pixel_format fmt);
-void omapdss_dsi_set_operation_mode(struct omap_dss_device *dssdev,
-		enum omap_dss_dsi_mode mode);
-void omapdss_dsi_set_videomode_timings(struct omap_dss_device *dssdev,
-		struct omap_dss_dsi_videomode_timings *timings);
+int omapdss_dsi_set_config(struct omap_dss_device *dssdev,
+		const struct omap_dss_dsi_config *config);
 
 int omap_dsi_update(struct omap_dss_device *dssdev, int channel,
 		void (*callback)(int, void *), void *data);
@@ -846,8 +846,6 @@ int omap_dsi_set_vc_id(struct omap_dss_device *dssdev, int channel, int vc_id);
 void omap_dsi_release_vc(struct omap_dss_device *dssdev, int channel);
 int omapdss_dsi_configure_pins(struct omap_dss_device *dssdev,
 		const struct omap_dsi_pin_config *pin_cfg);
-int omapdss_dsi_set_clocks(struct omap_dss_device *dssdev,
-		unsigned long ddr_clk, unsigned long lp_clk);
 
 int omapdss_dsi_display_enable(struct omap_dss_device *dssdev);
 void omapdss_dsi_display_disable(struct omap_dss_device *dssdev,
diff --git a/include/xen/tmem.h b/include/xen/tmem.h
index 591550a..3930a90 100644
--- a/include/xen/tmem.h
+++ b/include/xen/tmem.h
@@ -3,7 +3,15 @@
 
 #include <linux/types.h>
 
+#ifdef CONFIG_XEN_TMEM_MODULE
+#define tmem_enabled true
+#else
 /* defined in drivers/xen/tmem.c */
 extern bool tmem_enabled;
+#endif
+
+#ifdef CONFIG_XEN_SELFBALLOONING
+extern int xen_selfballoon_init(bool, bool);
+#endif
 
 #endif /* _XEN_TMEM_H */
diff --git a/init/Kconfig b/init/Kconfig
index 5341d72..0573d0a 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -98,10 +98,13 @@ config HAVE_KERNEL_XZ
 config HAVE_KERNEL_LZO
 	bool
 
+config HAVE_KERNEL_LZ4
+	bool
+
 choice
 	prompt "Kernel compression mode"
 	default KERNEL_GZIP
-	depends on HAVE_KERNEL_GZIP || HAVE_KERNEL_BZIP2 || HAVE_KERNEL_LZMA || HAVE_KERNEL_XZ || HAVE_KERNEL_LZO
+	depends on HAVE_KERNEL_GZIP || HAVE_KERNEL_BZIP2 || HAVE_KERNEL_LZMA || HAVE_KERNEL_XZ || HAVE_KERNEL_LZO || HAVE_KERNEL_LZ4
 	help
 	  The linux kernel is a kind of self-extracting executable.
 	  Several compression algorithms are available, which differ
@@ -168,6 +171,18 @@ config KERNEL_LZO
 	  size is about 10% bigger than gzip; however its speed
 	  (both compression and decompression) is the fastest.
 
+config KERNEL_LZ4
+	bool "LZ4"
+	depends on HAVE_KERNEL_LZ4
+	help
+	  LZ4 is an LZ77-type compressor with a fixed, byte-oriented encoding.
+	  A preliminary version of LZ4 de/compression tool is available at
+	  <https://code.google.com/p/lz4/>.
+
+	  Its compression ratio is worse than LZO. The size of the kernel
+	  is about 8% bigger than LZO. But the decompression speed is
+	  faster than LZO.
+
 endchoice
 
 config DEFAULT_HOSTNAME
@@ -505,6 +520,7 @@ config RCU_USER_QS
 config CONTEXT_TRACKING_FORCE
 	bool "Force context tracking"
 	depends on CONTEXT_TRACKING
+	default CONTEXT_TRACKING
 	help
 	  Probe on user/kernel boundaries by default in order to
 	  test the features that rely on it such as userspace RCU extended
@@ -578,13 +594,16 @@ config RCU_FAST_NO_HZ
 	depends on NO_HZ && SMP
 	default n
 	help
-	  This option causes RCU to attempt to accelerate grace periods in
-	  order to allow CPUs to enter dynticks-idle state more quickly.
-	  On the other hand, this option increases the overhead of the
-	  dynticks-idle checking, thus degrading scheduling latency.
+	  This option permits CPUs to enter dynticks-idle state even if
+	  they have RCU callbacks queued, and prevents RCU from waking
+	  these CPUs up more than roughly once every four jiffies (by
+	  default, you can adjust this using the rcutree.rcu_idle_gp_delay
+	  parameter), thus improving energy efficiency.  On the other
+	  hand, this option increases the duration of RCU grace periods,
+	  for example, slowing down synchronize_rcu().
 
-	  Say Y if energy efficiency is critically important, and you don't
-	  	care about real-time response.
+	  Say Y if energy efficiency is critically important, and you
+	  	don't care about increased grace-period durations.
 
 	  Say N if you are unsure.
 
@@ -651,7 +670,7 @@ config RCU_BOOST_DELAY
 	  Accept the default if unsure.
 
 config RCU_NOCB_CPU
-	bool "Offload RCU callback processing from boot-selected CPUs"
+	bool "Offload RCU callback processing from boot-selected CPUs (EXPERIMENTAL"
 	depends on TREE_RCU || TREE_PREEMPT_RCU
 	default n
 	help
@@ -662,16 +681,56 @@ config RCU_NOCB_CPU
 
 	  This option offloads callback invocation from the set of
 	  CPUs specified at boot time by the rcu_nocbs parameter.
-	  For each such CPU, a kthread ("rcuoN") will be created to
-	  invoke callbacks, where the "N" is the CPU being offloaded.
-	  Nothing prevents this kthread from running on the specified
-	  CPUs, but (1) the kthreads may be preempted between each
-	  callback, and (2) affinity or cgroups can be used to force
-	  the kthreads to run on whatever set of CPUs is desired.
-
-	  Say Y here if you want reduced OS jitter on selected CPUs.
+	  For each such CPU, a kthread ("rcuox/N") will be created to
+	  invoke callbacks, where the "N" is the CPU being offloaded,
+	  and where the "x" is "b" for RCU-bh, "p" for RCU-preempt, and
+	  "s" for RCU-sched.  Nothing prevents this kthread from running
+	  on the specified CPUs, but (1) the kthreads may be preempted
+	  between each callback, and (2) affinity or cgroups can be used
+	  to force the kthreads to run on whatever set of CPUs is desired.
+
+	  Say Y here if you want to help to debug reduced OS jitter.
 	  Say N here if you are unsure.
 
+choice
+	prompt "Build-forced no-CBs CPUs"
+	default RCU_NOCB_CPU_NONE
+	help
+	  This option allows no-CBs CPUs to be specified at build time.
+	  Additional no-CBs CPUs may be specified by the rcu_nocbs=
+	  boot parameter.
+
+config RCU_NOCB_CPU_NONE
+	bool "No build_forced no-CBs CPUs"
+	depends on RCU_NOCB_CPU
+	help
+	  This option does not force any of the CPUs to be no-CBs CPUs.
+	  Only CPUs designated by the rcu_nocbs= boot parameter will be
+	  no-CBs CPUs.
+
+config RCU_NOCB_CPU_ZERO
+	bool "CPU 0 is a build_forced no-CBs CPU"
+	depends on RCU_NOCB_CPU
+	help
+	  This option forces CPU 0 to be a no-CBs CPU.  Additional CPUs
+	  may be designated as no-CBs CPUs using the rcu_nocbs= boot
+	  parameter will be no-CBs CPUs.
+
+	  Select this if CPU 0 needs to be a no-CBs CPU for real-time
+	  or energy-efficiency reasons.
+
+config RCU_NOCB_CPU_ALL
+	bool "All CPUs are build_forced no-CBs CPUs"
+	depends on RCU_NOCB_CPU
+	help
+	  This option forces all CPUs to be no-CBs CPUs.  The rcu_nocbs=
+	  boot parameter will be ignored.
+
+	  Select this if all CPUs need to be no-CBs CPUs for real-time
+	  or energy-efficiency reasons.
+
+endchoice
+
 endmenu # "RCU Subsystem"
 
 config IKCONFIG
@@ -887,6 +946,23 @@ config MEMCG_KMEM
 	  the kmem extension can use it to guarantee that no group of processes
 	  will ever exhaust kernel resources alone.
 
+config MEMCG_DEBUG_ASYNC_DESTROY
+	bool "Memory Resource Controller Debug asynchronous object destruction"
+	depends on MEMCG_KMEM || MEMCG_SWAP
+	default n
+	help
+	  When a memcg is destroyed, the memory consumed by it may not be
+	  immediately freed. This is because when some extensions are used, such
+	  as swap or kernel memory, objects can outlive the group and hold a
+	  reference to it.
+
+	  If this is the case, the dangling_memcgs file will show information
+	  about what are the memcgs still alive, and which references are still
+	  preventing it to be freed. There is nothing wrong with that, but it is
+	  very useful when debugging, to know where this memory is being held.
+	  This is a developer-oriented debugging facility only, and no
+	  guarantees of interface stability will be given.
+
 config CGROUP_HUGETLB
 	bool "HugeTLB Resource Controller for Control Groups"
 	depends on RESOURCE_COUNTERS && HUGETLB_PAGE
@@ -1177,7 +1253,7 @@ config SYSCTL
 config ANON_INODES
 	bool
 
-menuconfig EXPERT
+config EXPERT
 	bool "Configure standard kernel features (expert users)"
 	# Unhide debug options, to make the on-by-default options visible
 	select DEBUG_KERNEL
diff --git a/init/do_mounts.c b/init/do_mounts.c
index a2b49f2..33d060e 100644
--- a/init/do_mounts.c
+++ b/init/do_mounts.c
@@ -202,7 +202,7 @@ done:
  *	bangs.
  */
 
-dev_t name_to_dev_t(char *name)
+dev_t name_to_dev_t(const char *name)
 {
 	char s[32];
 	char *p;
diff --git a/init/do_mounts_initrd.c b/init/do_mounts_initrd.c
index a32ec1c..3e0878e 100644
--- a/init/do_mounts_initrd.c
+++ b/init/do_mounts_initrd.c
@@ -50,6 +50,7 @@ static int init_linuxrc(struct subprocess_info *info, struct cred *new)
 
 static void __init handle_initrd(void)
 {
+	struct subprocess_info *info;
 	static char *argv[] = { "linuxrc", NULL, };
 	extern char *envp_init[];
 	int error;
@@ -70,8 +71,11 @@ static void __init handle_initrd(void)
 	 */
 	current->flags |= PF_FREEZER_SKIP;
 
-	call_usermodehelper_fns("/linuxrc", argv, envp_init, UMH_WAIT_PROC,
-			init_linuxrc, NULL, NULL);
+	info = call_usermodehelper_setup("/linuxrc", argv, envp_init,
+					 GFP_KERNEL, init_linuxrc, NULL, NULL);
+	if (!info)
+		return;
+	call_usermodehelper_exec(info, UMH_WAIT_PROC);
 
 	current->flags &= ~PF_FREEZER_SKIP;
 
diff --git a/init/main.c b/init/main.c
index 63534a1..a55dbe5 100644
--- a/init/main.c
+++ b/init/main.c
@@ -174,8 +174,8 @@ static int __init obsolete_checksetup(char *line)
 				if (line[n] == '\0' || line[n] == '=')
 					had_early_param = 1;
 			} else if (!p->setup_func) {
-				printk(KERN_WARNING "Parameter %s is obsolete,"
-				       " ignored\n", p->str);
+				pr_warn("Parameter %s is obsolete, ignored\n",
+					p->str);
 				return 1;
 			} else if (p->setup_func(line + n))
 				return 1;
@@ -398,8 +398,7 @@ static int __init do_early_param(char *param, char *val, const char *unused)
 		     strcmp(p->str, "earlycon") == 0)
 		) {
 			if (p->setup_func(val) != 0)
-				printk(KERN_WARNING
-				       "Malformed early option '%s'\n", param);
+				pr_warn("Malformed early option '%s'\n", param);
 		}
 	}
 	/* We accept everything at this stage. */
@@ -494,10 +493,9 @@ asmlinkage void __init start_kernel(void)
  * Interrupts are still disabled. Do necessary setups, then
  * enable them
  */
-	tick_init();
 	boot_cpu_init();
 	page_address_init();
-	printk(KERN_NOTICE "%s", linux_banner);
+	pr_notice("%s", linux_banner);
 	setup_arch(&command_line);
 	mm_init_owner(&init_mm, &init_task);
 	mm_init_cpumask(&init_mm);
@@ -509,7 +507,7 @@ asmlinkage void __init start_kernel(void)
 	build_all_zonelists(NULL, NULL);
 	page_alloc_init();
 
-	printk(KERN_NOTICE "Kernel command line: %s\n", boot_command_line);
+	pr_notice("Kernel command line: %s\n", boot_command_line);
 	parse_early_param();
 	parse_args("Booting kernel", static_command_line, __start___param,
 		   __stop___param - __start___param,
@@ -539,11 +537,8 @@ asmlinkage void __init start_kernel(void)
 	 * fragile until we cpu_idle() for the first time.
 	 */
 	preempt_disable();
-	if (!irqs_disabled()) {
-		printk(KERN_WARNING "start_kernel(): bug: interrupts were "
-				"enabled *very* early, fixing it\n");
+	if (WARN(!irqs_disabled(), "Interrupts were enabled *very* early, fixing it\n"))
 		local_irq_disable();
-	}
 	idr_init_cache();
 	perf_event_init();
 	rcu_init();
@@ -551,6 +546,7 @@ asmlinkage void __init start_kernel(void)
 	/* init some links before init_ISA_irqs() */
 	early_irq_init();
 	init_IRQ();
+	tick_init();
 	init_timers();
 	hrtimers_init();
 	softirq_init();
@@ -558,9 +554,7 @@ asmlinkage void __init start_kernel(void)
 	time_init();
 	profile_init();
 	call_function_init();
-	if (!irqs_disabled())
-		printk(KERN_CRIT "start_kernel(): bug: interrupts were "
-				 "enabled early\n");
+	WARN(!irqs_disabled(), "Interrupts were enabled early\n");
 	early_boot_irqs_disabled = false;
 	local_irq_enable();
 
@@ -587,8 +581,7 @@ asmlinkage void __init start_kernel(void)
 #ifdef CONFIG_BLK_DEV_INITRD
 	if (initrd_start && !initrd_below_start_ok &&
 	    page_to_pfn(virt_to_page((void *)initrd_start)) < min_low_pfn) {
-		printk(KERN_CRIT "initrd overwritten (0x%08lx < 0x%08lx) - "
-		    "disabling it.\n",
+		pr_crit("initrd overwritten (0x%08lx < 0x%08lx) - disabling it.\n",
 		    page_to_pfn(virt_to_page((void *)initrd_start)),
 		    min_low_pfn);
 		initrd_start = 0;
@@ -667,14 +660,14 @@ static int __init_or_module do_one_initcall_debug(initcall_t fn)
 	unsigned long long duration;
 	int ret;
 
-	printk(KERN_DEBUG "calling  %pF @ %i\n", fn, task_pid_nr(current));
+	pr_debug("calling  %pF @ %i\n", fn, task_pid_nr(current));
 	calltime = ktime_get();
 	ret = fn();
 	rettime = ktime_get();
 	delta = ktime_sub(rettime, calltime);
 	duration = (unsigned long long) ktime_to_ns(delta) >> 10;
-	printk(KERN_DEBUG "initcall %pF returned %d after %lld usecs\n", fn,
-		ret, duration);
+	pr_debug("initcall %pF returned %d after %lld usecs\n",
+		 fn, ret, duration);
 
 	return ret;
 }
@@ -702,9 +695,7 @@ int __init_or_module do_one_initcall(initcall_t fn)
 		strlcat(msgbuf, "disabled interrupts ", sizeof(msgbuf));
 		local_irq_enable();
 	}
-	if (msgbuf[0]) {
-		printk("initcall %pF returned with %s\n", fn, msgbuf);
-	}
+	WARN(msgbuf[0], "initcall %pF returned with %s\n", fn, msgbuf);
 
 	return ret;
 }
@@ -832,8 +823,7 @@ static int __ref kernel_init(void *unused)
 	if (ramdisk_execute_command) {
 		if (!run_init_process(ramdisk_execute_command))
 			return 0;
-		printk(KERN_WARNING "Failed to execute %s\n",
-				ramdisk_execute_command);
+		pr_err("Failed to execute %s\n", ramdisk_execute_command);
 	}
 
 	/*
@@ -845,8 +835,8 @@ static int __ref kernel_init(void *unused)
 	if (execute_command) {
 		if (!run_init_process(execute_command))
 			return 0;
-		printk(KERN_WARNING "Failed to execute %s.  Attempting "
-					"defaults...\n", execute_command);
+		pr_err("Failed to execute %s.  Attempting defaults...\n",
+			execute_command);
 	}
 	if (!run_init_process("/sbin/init") ||
 	    !run_init_process("/etc/init") ||
@@ -891,7 +881,7 @@ static noinline void __init kernel_init_freeable(void)
 
 	/* Open the /dev/console on the rootfs, this should never fail */
 	if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
-		printk(KERN_WARNING "Warning: unable to open an initial console.\n");
+		pr_err("Warning: unable to open an initial console.\n");
 
 	(void) sys_dup(0);
 	(void) sys_dup(0);
diff --git a/ipc/compat.c b/ipc/compat.c
index 2547f29..892f658 100644
--- a/ipc/compat.c
+++ b/ipc/compat.c
@@ -240,7 +240,7 @@ static inline int put_compat_semid_ds(struct semid64_ds *s,
 
 static long do_compat_semctl(int first, int second, int third, u32 pad)
 {
-	union semun fourth;
+	unsigned long fourth;
 	int err, err2;
 	struct semid64_ds s64;
 	struct semid64_ds __user *up64;
@@ -249,9 +249,13 @@ static long do_compat_semctl(int first, int second, int third, u32 pad)
 	memset(&s64, 0, sizeof(s64));
 
 	if ((third & (~IPC_64)) == SETVAL)
-		fourth.val = (int) pad;
+#ifdef __BIG_ENDIAN
+		fourth = (unsigned long)pad << 32;
+#else
+		fourth = pad;
+#endif
 	else
-		fourth.__pad = compat_ptr(pad);
+		fourth = (unsigned long)compat_ptr(pad);
 	switch (third & (~IPC_64)) {
 	case IPC_INFO:
 	case IPC_RMID:
@@ -269,7 +273,7 @@ static long do_compat_semctl(int first, int second, int third, u32 pad)
 	case IPC_STAT:
 	case SEM_STAT:
 		up64 = compat_alloc_user_space(sizeof(s64));
-		fourth.__pad = up64;
+		fourth = (unsigned long)up64;
 		err = sys_semctl(first, second, third, fourth);
 		if (err < 0)
 			break;
@@ -295,7 +299,7 @@ static long do_compat_semctl(int first, int second, int third, u32 pad)
 		if (err)
 			break;
 
-		fourth.__pad = up64;
+		fourth = (unsigned long)up64;
 		err = sys_semctl(first, second, third, fourth);
 		break;
 
@@ -306,7 +310,7 @@ static long do_compat_semctl(int first, int second, int third, u32 pad)
 	return err;
 }
 
-long compat_do_msg_fill(void __user *dest, struct msg_msg *msg, size_t bufsz)
+static long compat_do_msg_fill(void __user *dest, struct msg_msg *msg, size_t bufsz)
 {
 	struct compat_msgbuf __user *msgp = dest;
 	size_t msgsz;
@@ -320,77 +324,117 @@ long compat_do_msg_fill(void __user *dest, struct msg_msg *msg, size_t bufsz)
 	return msgsz;
 }
 
+#ifndef COMPAT_SHMLBA
+#define COMPAT_SHMLBA	SHMLBA
+#endif
+
 #ifdef CONFIG_ARCH_WANT_OLD_COMPAT_IPC
-long compat_sys_semctl(int first, int second, int third, void __user *uptr)
+COMPAT_SYSCALL_DEFINE6(ipc, u32, call, int, first, int, second,
+	u32, third, compat_uptr_t, ptr, u32, fifth)
 {
+	int version;
 	u32 pad;
 
-	if (!uptr)
-		return -EINVAL;
-	if (get_user(pad, (u32 __user *) uptr))
-		return -EFAULT;
-	return do_compat_semctl(first, second, third, pad);
-}
+	version = call >> 16; /* hack for backward compatibility */
+	call &= 0xffff;
+
+	switch (call) {
+	case SEMOP:
+		/* struct sembuf is the same on 32 and 64bit :)) */
+		return sys_semtimedop(first, compat_ptr(ptr), second, NULL);
+	case SEMTIMEDOP:
+		return compat_sys_semtimedop(first, compat_ptr(ptr), second,
+						compat_ptr(fifth));
+	case SEMGET:
+		return sys_semget(first, second, third);
+	case SEMCTL:
+		if (!ptr)
+			return -EINVAL;
+		if (get_user(pad, (u32 __user *) compat_ptr(ptr)))
+			return -EFAULT;
+		return do_compat_semctl(first, second, third, pad);
 
-long compat_sys_msgsnd(int first, int second, int third, void __user *uptr)
-{
-	struct compat_msgbuf __user *up = uptr;
-	long type;
+	case MSGSND: {
+		struct compat_msgbuf __user *up = compat_ptr(ptr);
+		compat_long_t type;
 
-	if (first < 0)
-		return -EINVAL;
-	if (second < 0)
-		return -EINVAL;
+		if (first < 0 || second < 0)
+			return -EINVAL;
 
-	if (get_user(type, &up->mtype))
-		return -EFAULT;
+		if (get_user(type, &up->mtype))
+			return -EFAULT;
 
-	return do_msgsnd(first, type, up->mtext, second, third);
-}
+		return do_msgsnd(first, type, up->mtext, second, third);
+	}
+	case MSGRCV: {
+		void __user *uptr = compat_ptr(ptr);
 
-long compat_sys_msgrcv(int first, int second, int msgtyp, int third,
-			   int version, void __user *uptr)
-{
-	if (first < 0)
-		return -EINVAL;
-	if (second < 0)
-		return -EINVAL;
-
-	if (!version) {
-		struct compat_ipc_kludge ipck;
-		if (!uptr)
+		if (first < 0 || second < 0)
 			return -EINVAL;
-		if (copy_from_user (&ipck, uptr, sizeof(ipck)))
-			return -EFAULT;
-		uptr = compat_ptr(ipck.msgp);
-		msgtyp = ipck.msgtyp;
+
+		if (!version) {
+			struct compat_ipc_kludge ipck;
+			if (!uptr)
+				return -EINVAL;
+			if (copy_from_user (&ipck, uptr, sizeof(ipck)))
+				return -EFAULT;
+			uptr = compat_ptr(ipck.msgp);
+			fifth = ipck.msgtyp;
+		}
+		return do_msgrcv(first, uptr, second, fifth, third,
+				 compat_do_msg_fill);
 	}
-	return do_msgrcv(first, uptr, second, msgtyp, third,
-			 compat_do_msg_fill);
+	case MSGGET:
+		return sys_msgget(first, second);
+	case MSGCTL:
+		return compat_sys_msgctl(first, second, compat_ptr(ptr));
+
+	case SHMAT: {
+		int err;
+		unsigned long raddr;
+
+		if (version == 1)
+			return -EINVAL;
+		err = do_shmat(first, compat_ptr(ptr), second, &raddr,
+			       COMPAT_SHMLBA);
+		if (err < 0)
+			return err;
+		return put_user(raddr, (compat_ulong_t *)compat_ptr(third));
+	}
+	case SHMDT:
+		return sys_shmdt(compat_ptr(ptr));
+	case SHMGET:
+		return sys_shmget(first, (unsigned)second, third);
+	case SHMCTL:
+		return compat_sys_shmctl(first, second, compat_ptr(ptr));
+	}
+
+	return -ENOSYS;
 }
-#else
-long compat_sys_semctl(int semid, int semnum, int cmd, int arg)
+#endif
+
+COMPAT_SYSCALL_DEFINE4(semctl, int, semid, int, semnum, int, cmd, int, arg)
 {
 	return do_compat_semctl(semid, semnum, cmd, arg);
 }
 
-long compat_sys_msgsnd(int msqid, struct compat_msgbuf __user *msgp,
-		       compat_ssize_t msgsz, int msgflg)
+COMPAT_SYSCALL_DEFINE4(msgsnd, int, msqid, compat_uptr_t, msgp,
+		       compat_ssize_t, msgsz, int, msgflg)
 {
+	struct compat_msgbuf __user *up = compat_ptr(msgp);
 	compat_long_t mtype;
 
-	if (get_user(mtype, &msgp->mtype))
+	if (get_user(mtype, &up->mtype))
 		return -EFAULT;
-	return do_msgsnd(msqid, mtype, msgp->mtext, (ssize_t)msgsz, msgflg);
+	return do_msgsnd(msqid, mtype, up->mtext, (ssize_t)msgsz, msgflg);
 }
 
-long compat_sys_msgrcv(int msqid, struct compat_msgbuf __user *msgp,
-		       compat_ssize_t msgsz, long msgtyp, int msgflg)
+COMPAT_SYSCALL_DEFINE5(msgrcv, int, msqid, compat_uptr_t, msgp,
+		       compat_ssize_t, msgsz, long, msgtyp, int, msgflg)
 {
-	return do_msgrcv(msqid, msgp, (ssize_t)msgsz, msgtyp, msgflg,
-			 compat_do_msg_fill);
+	return do_msgrcv(msqid, compat_ptr(msgp), (ssize_t)msgsz, msgtyp,
+			 msgflg, compat_do_msg_fill);
 }
-#endif
 
 static inline int get_compat_msqid64(struct msqid64_ds *m64,
 				     struct compat_msqid64_ds __user *up64)
@@ -508,28 +552,7 @@ long compat_sys_msgctl(int first, int second, void __user *uptr)
 	return err;
 }
 
-#ifndef COMPAT_SHMLBA
-#define COMPAT_SHMLBA	SHMLBA
-#endif
-
-#ifdef CONFIG_ARCH_WANT_OLD_COMPAT_IPC
-long compat_sys_shmat(int first, int second, compat_uptr_t third, int version,
-			void __user *uptr)
-{
-	int err;
-	unsigned long raddr;
-	compat_ulong_t __user *uaddr;
-
-	if (version == 1)
-		return -EINVAL;
-	err = do_shmat(first, uptr, second, &raddr, COMPAT_SHMLBA);
-	if (err < 0)
-		return err;
-	uaddr = compat_ptr(third);
-	return put_user(raddr, uaddr);
-}
-#else
-long compat_sys_shmat(int shmid, compat_uptr_t shmaddr, int shmflg)
+COMPAT_SYSCALL_DEFINE3(shmat, int, shmid, compat_uptr_t, shmaddr, int, shmflg)
 {
 	unsigned long ret;
 	long err;
@@ -540,7 +563,6 @@ long compat_sys_shmat(int shmid, compat_uptr_t shmaddr, int shmflg)
 	force_successful_syscall_return();
 	return (long)ret;
 }
-#endif
 
 static inline int get_compat_shmid64_ds(struct shmid64_ds *s64,
 					struct compat_shmid64_ds __user *up64)
diff --git a/ipc/msg.c b/ipc/msg.c
index 31cd1bf..fcaf2d8 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -66,6 +66,7 @@ struct msg_sender {
 #define SEARCH_EQUAL		2
 #define SEARCH_NOTEQUAL		3
 #define SEARCH_LESSEQUAL	4
+#define SEARCH_NUMBER		5
 
 #define msg_ids(ns)	((ns)->ids[IPC_MSG_IDS])
 
@@ -583,6 +584,7 @@ static int testmsg(struct msg_msg *msg, long type, int mode)
 	switch(mode)
 	{
 		case SEARCH_ANY:
+		case SEARCH_NUMBER:
 			return 1;
 		case SEARCH_LESSEQUAL:
 			if (msg->m_type <=type)
@@ -738,6 +740,8 @@ SYSCALL_DEFINE4(msgsnd, int, msqid, struct msgbuf __user *, msgp, size_t, msgsz,
 
 static inline int convert_mode(long *msgtyp, int msgflg)
 {
+	if (msgflg & MSG_COPY)
+		return SEARCH_NUMBER;
 	/*
 	 *  find message of correct type.
 	 *  msgtyp = 0 => get first.
@@ -774,14 +778,10 @@ static long do_msg_fill(void __user *dest, struct msg_msg *msg, size_t bufsz)
  * This function creates new kernel message structure, large enough to store
  * bufsz message bytes.
  */
-static inline struct msg_msg *prepare_copy(void __user *buf, size_t bufsz,
-					   int msgflg, long *msgtyp,
-					   unsigned long *copy_number)
+static inline struct msg_msg *prepare_copy(void __user *buf, size_t bufsz)
 {
 	struct msg_msg *copy;
 
-	*copy_number = *msgtyp;
-	*msgtyp = 0;
 	/*
 	 * Create dummy message to copy real message to.
 	 */
@@ -797,9 +797,7 @@ static inline void free_copy(struct msg_msg *copy)
 		free_msg(copy);
 }
 #else
-static inline struct msg_msg *prepare_copy(void __user *buf, size_t bufsz,
-					   int msgflg, long *msgtyp,
-					   unsigned long *copy_number)
+static inline struct msg_msg *prepare_copy(void __user *buf, size_t bufsz)
 {
 	return ERR_PTR(-ENOSYS);
 }
@@ -809,6 +807,30 @@ static inline void free_copy(struct msg_msg *copy)
 }
 #endif
 
+static struct msg_msg *find_msg(struct msg_queue *msq, long *msgtyp, int mode)
+{
+	struct msg_msg *msg;
+	long count = 0;
+
+	list_for_each_entry(msg, &msq->q_messages, m_list) {
+		if (testmsg(msg, *msgtyp, mode) &&
+		    !security_msg_queue_msgrcv(msq, msg, current,
+					       *msgtyp, mode)) {
+			if (mode == SEARCH_LESSEQUAL && msg->m_type != 1) {
+				*msgtyp = msg->m_type - 1;
+			} else if (mode == SEARCH_NUMBER) {
+				if (*msgtyp == count)
+					return msg;
+			} else
+				return msg;
+			count++;
+		}
+	}
+
+	return ERR_PTR(-EAGAIN);
+}
+
+
 long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp,
 	       int msgflg,
 	       long (*msg_handler)(void __user *, struct msg_msg *, size_t))
@@ -818,19 +840,16 @@ long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp,
 	int mode;
 	struct ipc_namespace *ns;
 	struct msg_msg *copy = NULL;
-	unsigned long copy_number = 0;
-
-	ns = current->nsproxy->ipc_ns;
 
 	if (msqid < 0 || (long) bufsz < 0)
 		return -EINVAL;
 	if (msgflg & MSG_COPY) {
-		copy = prepare_copy(buf, min_t(size_t, bufsz, ns->msg_ctlmax),
-				    msgflg, &msgtyp, &copy_number);
+		copy = prepare_copy(buf, bufsz);
 		if (IS_ERR(copy))
 			return PTR_ERR(copy);
 	}
 	mode = convert_mode(&msgtyp, msgflg);
+	ns = current->nsproxy->ipc_ns;
 
 	msq = msg_lock_check(ns, msqid);
 	if (IS_ERR(msq)) {
@@ -840,44 +859,13 @@ long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp,
 
 	for (;;) {
 		struct msg_receiver msr_d;
-		struct list_head *tmp;
-		long msg_counter = 0;
 
 		msg = ERR_PTR(-EACCES);
 		if (ipcperms(ns, &msq->q_perm, S_IRUGO))
 			goto out_unlock;
 
-		msg = ERR_PTR(-EAGAIN);
-		tmp = msq->q_messages.next;
-		while (tmp != &msq->q_messages) {
-			struct msg_msg *walk_msg;
-
-			walk_msg = list_entry(tmp, struct msg_msg, m_list);
-			if (testmsg(walk_msg, msgtyp, mode) &&
-			    !security_msg_queue_msgrcv(msq, walk_msg, current,
-						       msgtyp, mode)) {
-
-				msg = walk_msg;
-				if (mode == SEARCH_LESSEQUAL &&
-						walk_msg->m_type != 1) {
-					msgtyp = walk_msg->m_type - 1;
-				} else if (msgflg & MSG_COPY) {
-					if (copy_number == msg_counter) {
-						/*
-						 * Found requested message.
-						 * Copy it.
-						 */
-						msg = copy_msg(msg, copy);
-						if (IS_ERR(msg))
-							goto out_unlock;
-						break;
-					}
-				} else
-					break;
-				msg_counter++;
-			}
-			tmp = tmp->next;
-		}
+		msg = find_msg(msq, &msgtyp, mode);
+
 		if (!IS_ERR(msg)) {
 			/*
 			 * Found a suitable message.
@@ -891,8 +879,10 @@ long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp,
 			 * If we are copying, then do not unlink message and do
 			 * not update queue parameters.
 			 */
-			if (msgflg & MSG_COPY)
+			if (msgflg & MSG_COPY) {
+				msg = copy_msg(msg, copy);
 				goto out_unlock;
+			}
 			list_del(&msg->m_list);
 			msq->q_qnum--;
 			msq->q_rtime = get_seconds();
diff --git a/ipc/msgutil.c b/ipc/msgutil.c
index 5df8e4b..d43439e 100644
--- a/ipc/msgutil.c
+++ b/ipc/msgutil.c
@@ -17,7 +17,7 @@
 #include <linux/ipc_namespace.h>
 #include <linux/utsname.h>
 #include <linux/proc_fs.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include "util.h"
 
@@ -37,59 +37,70 @@ struct ipc_namespace init_ipc_ns = {
 atomic_t nr_ipc_ns = ATOMIC_INIT(1);
 
 struct msg_msgseg {
-	struct msg_msgseg* next;
+	struct msg_msgseg *next;
 	/* the next part of the message follows immediately */
 };
 
-#define DATALEN_MSG	(PAGE_SIZE-sizeof(struct msg_msg))
-#define DATALEN_SEG	(PAGE_SIZE-sizeof(struct msg_msgseg))
+#define DATALEN_MSG	(int)(PAGE_SIZE-sizeof(struct msg_msg))
+#define DATALEN_SEG	(int)(PAGE_SIZE-sizeof(struct msg_msgseg))
 
-struct msg_msg *load_msg(const void __user *src, int len)
+
+static struct msg_msg *alloc_msg(int len)
 {
 	struct msg_msg *msg;
 	struct msg_msgseg **pseg;
-	int err;
 	int alen;
 
-	alen = len;
-	if (alen > DATALEN_MSG)
-		alen = DATALEN_MSG;
-
+	alen = min(len, DATALEN_MSG);
 	msg = kmalloc(sizeof(*msg) + alen, GFP_KERNEL);
 	if (msg == NULL)
-		return ERR_PTR(-ENOMEM);
+		return NULL;
 
 	msg->next = NULL;
 	msg->security = NULL;
 
-	if (copy_from_user(msg + 1, src, alen)) {
-		err = -EFAULT;
-		goto out_err;
-	}
-
 	len -= alen;
-	src = ((char __user *)src) + alen;
 	pseg = &msg->next;
 	while (len > 0) {
 		struct msg_msgseg *seg;
-		alen = len;
-		if (alen > DATALEN_SEG)
-			alen = DATALEN_SEG;
-		seg = kmalloc(sizeof(*seg) + alen,
-						 GFP_KERNEL);
-		if (seg == NULL) {
-			err = -ENOMEM;
+		alen = min(len, DATALEN_SEG);
+		seg = kmalloc(sizeof(*seg) + alen, GFP_KERNEL);
+		if (seg == NULL)
 			goto out_err;
-		}
 		*pseg = seg;
 		seg->next = NULL;
-		if (copy_from_user(seg + 1, src, alen)) {
-			err = -EFAULT;
-			goto out_err;
-		}
 		pseg = &seg->next;
 		len -= alen;
-		src = ((char __user *)src) + alen;
+	}
+
+	return msg;
+
+out_err:
+	free_msg(msg);
+	return NULL;
+}
+
+struct msg_msg *load_msg(const void __user *src, int len)
+{
+	struct msg_msg *msg;
+	struct msg_msgseg *seg;
+	int err = -EFAULT;
+	int alen;
+
+	msg = alloc_msg(len);
+	if (msg == NULL)
+		return ERR_PTR(-ENOMEM);
+
+	alen = min(len, DATALEN_MSG);
+	if (copy_from_user(msg + 1, src, alen))
+		goto out_err;
+
+	for (seg = msg->next; seg != NULL; seg = seg->next) {
+		len -= alen;
+		src = (char __user *)src + alen;
+		alen = min(len, DATALEN_SEG);
+		if (copy_from_user(seg + 1, src, alen))
+			goto out_err;
 	}
 
 	err = security_msg_msg_alloc(msg);
@@ -113,23 +124,16 @@ struct msg_msg *copy_msg(struct msg_msg *src, struct msg_msg *dst)
 	if (src->m_ts > dst->m_ts)
 		return ERR_PTR(-EINVAL);
 
-	alen = len;
-	if (alen > DATALEN_MSG)
-		alen = DATALEN_MSG;
-
+	alen = min(len, DATALEN_MSG);
 	memcpy(dst + 1, src + 1, alen);
 
-	len -= alen;
-	dst_pseg = dst->next;
-	src_pseg = src->next;
-	while (len > 0) {
-		alen = len;
-		if (alen > DATALEN_SEG)
-			alen = DATALEN_SEG;
-		memcpy(dst_pseg + 1, src_pseg + 1, alen);
-		dst_pseg = dst_pseg->next;
+	for (dst_pseg = dst->next, src_pseg = src->next;
+	     src_pseg != NULL;
+	     dst_pseg = dst_pseg->next, src_pseg = src_pseg->next) {
+
 		len -= alen;
-		src_pseg = src_pseg->next;
+		alen = min(len, DATALEN_SEG);
+		memcpy(dst_pseg + 1, src_pseg + 1, alen);
 	}
 
 	dst->m_type = src->m_type;
@@ -148,24 +152,16 @@ int store_msg(void __user *dest, struct msg_msg *msg, int len)
 	int alen;
 	struct msg_msgseg *seg;
 
-	alen = len;
-	if (alen > DATALEN_MSG)
-		alen = DATALEN_MSG;
+	alen = min(len, DATALEN_MSG);
 	if (copy_to_user(dest, msg + 1, alen))
 		return -1;
 
-	len -= alen;
-	dest = ((char __user *)dest) + alen;
-	seg = msg->next;
-	while (len > 0) {
-		alen = len;
-		if (alen > DATALEN_SEG)
-			alen = DATALEN_SEG;
+	for (seg = msg->next; seg != NULL; seg = seg->next) {
+		len -= alen;
+		dest = (char __user *)dest + alen;
+		alen = min(len, DATALEN_SEG);
 		if (copy_to_user(dest, seg + 1, alen))
 			return -1;
-		len -= alen;
-		dest = ((char __user *)dest) + alen;
-		seg = seg->next;
 	}
 	return 0;
 }
diff --git a/ipc/sem.c b/ipc/sem.c
index 58d31f1..f257afe 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -61,8 +61,8 @@
  * - A woken up task may not even touch the semaphore array anymore, it may
  *   have been destroyed already by a semctl(RMID).
  * - The synchronizations between wake-ups due to a timeout/signal and a
- *   wake-up due to a completed semaphore operation is achieved by using an
- *   intermediate state (IN_WAKEUP).
+ *   wake-up due to a completed semaphore operation is achieved by using a
+ *   special wakeup scheme (queuewakeup_wait and support functions)
  * - UNDO values are stored in an array (one per process and per
  *   semaphore array, lazily allocated). For backwards compatibility, multiple
  *   modes for the UNDO variables are supported (per process, per thread)
@@ -90,16 +90,145 @@
 #include <asm/uaccess.h>
 #include "util.h"
 
+
+#ifdef CONFIG_PREEMPT_RT_BASE
+	#define SYSVSEM_COMPLETION 1
+#else
+	#define SYSVSEM_CUSTOM 1
+#endif
+
+#ifdef SYSVSEM_COMPLETION
+	/* Using a completion causes some overhead, but avoids a busy loop
+	 * that increases the worst case latency.
+	 */
+	struct queue_done {
+		struct completion done;
+	};
+
+	static void queuewakeup_prepare(void)
+	{
+		/* no preparation necessary */
+	}
+
+	static void queuewakeup_completed(void)
+	{
+		/* empty */
+	}
+
+	static void queuewakeup_block(struct queue_done *qd)
+	{
+		/* empty */
+	}
+
+	static void queuewakeup_handsoff(struct queue_done *qd)
+	{
+		complete_all(&qd->done);
+	}
+
+	static void queuewakeup_init(struct queue_done *qd)
+	{
+		init_completion(&qd->done);
+	}
+
+	static void queuewakeup_wait(struct queue_done *qd)
+	{
+		wait_for_completion(&qd->done);
+	}
+
+#elif defined(SYSVSEM_SPINLOCK)
+	/* Note: Spinlocks do not work because:
+	 * - lockdep complains [could be fixed]
+	 * - only 255 concurrent spin_lock() calls are permitted, then the
+	 *   preempt-counter overflows
+	 */
+#error SYSVSEM_SPINLOCK is a prove of concept, does not work.
+	struct queue_done {
+		spinlock_t done;
+	};
+
+	static void queuewakeup_prepare(void)
+	{
+		/* empty */
+	}
+
+	static void queuewakeup_completed(void)
+	{
+		/* empty */
+	}
+
+	static void queuewakeup_block(struct queue_done *qd)
+	{
+		BUG_ON(spin_is_locked(&qd->done));
+		spin_lock(&qd->done);
+	}
+
+	static void queuewakeup_handsoff(struct queue_done *qd)
+	{
+		spin_unlock(&qd->done);
+	}
+
+	static void queuewakeup_init(struct queue_done *qd)
+	{
+		spin_lock_init(&qd->done);
+	}
+
+	static void queuewakeup_wait(struct queue_done *qd)
+	{
+		spin_unlock_wait(&qd->done);
+	}
+#else
+	struct queue_done {
+		atomic_t done;
+	};
+
+	static void queuewakeup_prepare(void)
+	{
+		preempt_disable();
+	}
+
+	static void queuewakeup_completed(void)
+	{
+		preempt_enable();
+	}
+
+	static void queuewakeup_block(struct queue_done *qd)
+	{
+		BUG_ON(atomic_read(&qd->done) != 1);
+		atomic_set(&qd->done, 2);
+	}
+
+	static void queuewakeup_handsoff(struct queue_done *qd)
+	{
+		BUG_ON(atomic_read(&qd->done) != 2);
+		smp_mb();
+		atomic_set(&qd->done, 1);
+	}
+
+	static void queuewakeup_init(struct queue_done *qd)
+	{
+		atomic_set(&qd->done, 1);
+	}
+
+	static void queuewakeup_wait(struct queue_done *qd)
+	{
+		while (atomic_read(&qd->done) != 1)
+			cpu_relax();
+
+		smp_mb();
+	}
+#endif
+
+
 /* One semaphore structure for each semaphore in the system. */
 struct sem {
 	int	semval;		/* current value */
 	int	sempid;		/* pid of last operation */
+	spinlock_t	lock;	/* spinlock for fine-grained semtimedop */
 	struct list_head sem_pending; /* pending single-sop operations */
 };
 
 /* One queue for each sleeping process in the system. */
 struct sem_queue {
-	struct list_head	simple_list; /* queue of pending operations */
 	struct list_head	list;	 /* queue of pending operations */
 	struct task_struct	*sleeper; /* this process */
 	struct sem_undo		*undo;	 /* undo structure */
@@ -108,6 +237,7 @@ struct sem_queue {
 	struct sembuf		*sops;	 /* array of pending operations */
 	int			nsops;	 /* number of operations */
 	int			alter;	 /* does *sops alter the array? */
+	struct queue_done	done;	 /* completion synchronization */
 };
 
 /* Each task has a list of undo requests. They are executed automatically
@@ -138,7 +268,6 @@ struct sem_undo_list {
 
 #define sem_ids(ns)	((ns)->ids[IPC_SEM_IDS])
 
-#define sem_unlock(sma)		ipc_unlock(&(sma)->sem_perm)
 #define sem_checkid(sma, semid)	ipc_checkid(&sma->sem_perm, semid)
 
 static int newary(struct ipc_namespace *, struct ipc_params *);
@@ -191,47 +320,147 @@ void __init sem_init (void)
 }
 
 /*
+ * If the sem_array contains just one semaphore, or if multiple
+ * semops are performed in one syscall, or if there are complex
+ * operations pending, the whole sem_array is locked.
+ * If one semop is performed on an array with multiple semaphores,
+ * get a shared lock on the array, and lock the individual semaphore.
+ *
+ * Carefully guard against sma->complex_count changing between zero
+ * and non-zero while we are spinning for the lock. The value of
+ * sma->complex_count cannot change while we are holding the lock,
+ * so sem_unlock should be fine.
+ */
+static inline int sem_lock(struct sem_array *sma, struct sembuf *sops,
+			      int nsops)
+{
+	int locknum;
+	if (nsops == 1 && !sma->complex_count) {
+		struct sem *sem = sma->sem_base + sops->sem_num;
+
+		/* Lock just the semaphore we are interested in. */
+		spin_lock(&sem->lock);
+
+		/*
+		 * If sma->complex_count was set while we were spinning,
+		 * we may need to look at things we did not lock here.
+		 */
+		if (unlikely(sma->complex_count)) {
+			spin_unlock(&sem->lock);
+			goto lock_all;
+		}
+		locknum = sops->sem_num;
+	} else {
+		int i;
+		/* Lock the sem_array, and all the semaphore locks */
+ lock_all:
+		spin_lock(&sma->sem_perm.lock);
+		for (i = 0; i < sma->sem_nsems; i++) {
+			struct sem *sem = sma->sem_base + i;
+			spin_lock(&sem->lock);
+		}
+		locknum = -1;
+	}
+	return locknum;
+}
+
+static inline void sem_unlock(struct sem_array *sma, int locknum)
+{
+	if (locknum == -1) {
+		int i;
+		for (i = 0; i < sma->sem_nsems; i++) {
+			struct sem *sem = sma->sem_base + i;
+			spin_unlock(&sem->lock);
+		}
+		spin_unlock(&sma->sem_perm.lock);
+	} else {
+		struct sem *sem = sma->sem_base + locknum;
+		spin_unlock(&sem->lock);
+	}
+	rcu_read_unlock();
+}
+
+/*
  * sem_lock_(check_) routines are called in the paths where the rw_mutex
  * is not held.
  */
-static inline struct sem_array *sem_lock(struct ipc_namespace *ns, int id)
+static inline struct sem_array *sem_obtain_lock(struct ipc_namespace *ns,
+			int id, struct sembuf *sops, int nsops, int *locknum)
+{
+	struct kern_ipc_perm *ipcp;
+	struct sem_array *sma;
+
+	rcu_read_lock();
+	ipcp = ipc_obtain_object(&sem_ids(ns), id);
+	if (IS_ERR(ipcp)) {
+		sma = ERR_CAST(ipcp);
+		goto err;
+	}
+
+	sma = container_of(ipcp, struct sem_array, sem_perm);
+	*locknum = sem_lock(sma, sops, nsops);
+
+	/* ipc_rmid() may have already freed the ID while sem_lock
+	 * was spinning: verify that the structure is still valid
+	 */
+	if (!ipcp->deleted)
+		return container_of(ipcp, struct sem_array, sem_perm);
+
+	sem_unlock(sma, *locknum);
+	sma = ERR_PTR(-EINVAL);
+err:
+	rcu_read_unlock();
+	return sma;
+}
+
+static inline struct sem_array *sem_obtain_object(struct ipc_namespace *ns, int id)
 {
-	struct kern_ipc_perm *ipcp = ipc_lock(&sem_ids(ns), id);
+	struct kern_ipc_perm *ipcp = ipc_obtain_object(&sem_ids(ns), id);
 
 	if (IS_ERR(ipcp))
-		return (struct sem_array *)ipcp;
+		return ERR_CAST(ipcp);
 
 	return container_of(ipcp, struct sem_array, sem_perm);
 }
 
-static inline struct sem_array *sem_lock_check(struct ipc_namespace *ns,
-						int id)
+static inline struct sem_array *sem_obtain_object_check(struct ipc_namespace *ns,
+							int id)
 {
-	struct kern_ipc_perm *ipcp = ipc_lock_check(&sem_ids(ns), id);
+	struct kern_ipc_perm *ipcp = ipc_obtain_object_check(&sem_ids(ns), id);
 
 	if (IS_ERR(ipcp))
-		return (struct sem_array *)ipcp;
+		return ERR_CAST(ipcp);
 
 	return container_of(ipcp, struct sem_array, sem_perm);
 }
 
 static inline void sem_lock_and_putref(struct sem_array *sma)
 {
-	ipc_lock_by_ptr(&sma->sem_perm);
+	rcu_read_lock();
+	sem_lock(sma, NULL, -1);
 	ipc_rcu_putref(sma);
 }
 
 static inline void sem_getref_and_unlock(struct sem_array *sma)
 {
 	ipc_rcu_getref(sma);
-	ipc_unlock(&(sma)->sem_perm);
+	sem_unlock(sma, -1);
 }
 
 static inline void sem_putref(struct sem_array *sma)
 {
-	ipc_lock_by_ptr(&sma->sem_perm);
-	ipc_rcu_putref(sma);
-	ipc_unlock(&(sma)->sem_perm);
+	sem_lock_and_putref(sma);
+	sem_unlock(sma, -1);
+}
+
+/*
+ * Call inside the rcu read section.
+ */
+static inline void sem_getref(struct sem_array *sma)
+{
+	sem_lock(sma, NULL, -1);
+	ipc_rcu_getref(sma);
+	sem_unlock(sma, -1);
 }
 
 static inline void sem_rmid(struct ipc_namespace *ns, struct sem_array *s)
@@ -245,23 +474,27 @@ static inline void sem_rmid(struct ipc_namespace *ns, struct sem_array *s)
  * - queue.status is initialized to -EINTR before blocking.
  * - wakeup is performed by
  *	* unlinking the queue entry from sma->sem_pending
- *	* setting queue.status to IN_WAKEUP
- *	  This is the notification for the blocked thread that a
- *	  result value is imminent.
+ *	* setting queue.status to the actual result code
+ *	  This is the notification for the blocked thread that someone
+ *	  (usually: update_queue()) completed the semtimedop() operation.
  *	* call wake_up_process
- *	* set queue.status to the final value.
+ *	* queuewakeup_handsoff(&q->done);
  * - the previously blocked thread checks queue.status:
- *   	* if it's IN_WAKEUP, then it must wait until the value changes
- *   	* if it's not -EINTR, then the operation was completed by
- *   	  update_queue. semtimedop can return queue.status without
- *   	  performing any operation on the sem array.
- *   	* otherwise it must acquire the spinlock and check what's up.
+ *	* if it's not -EINTR, then someone completed the operation.
+ *	  First, queuewakeup_wait() must be called. Afterwards,
+ *	  semtimedop must return queue.status without performing any
+ *	  operation on the sem array.
+ *	  - otherwise it must acquire the spinlock and repeat the test
+ *	  - If it is still -EINTR, then no update_queue() completed the
+ *	    operation, thus semtimedop() can proceed normally.
  *
- * The two-stage algorithm is necessary to protect against the following
+ * queuewakeup_wait() is necessary to protect against the following
  * races:
  * - if queue.status is set after wake_up_process, then the woken up idle
  *   thread could race forward and try (and fail) to acquire sma->lock
- *   before update_queue had a chance to set queue.status
+ *   before update_queue had a chance to set queue.status.
+ *   More importantly, it would mean that wake_up_process must be done
+ *   while holding sma->lock, i.e. this would reduce the scalability.
  * - if queue.status is written before wake_up_process and if the
  *   blocked process is woken up by a signal between writing
  *   queue.status and the wake_up_process, then the woken up
@@ -271,7 +504,6 @@ static inline void sem_rmid(struct ipc_namespace *ns, struct sem_array *s)
  *   (yes, this happened on s390 with sysv msg).
  *
  */
-#define IN_WAKEUP	1
 
 /**
  * newary - Create a new semaphore set
@@ -324,15 +556,18 @@ static int newary(struct ipc_namespace *ns, struct ipc_params *params)
 
 	sma->sem_base = (struct sem *) &sma[1];
 
-	for (i = 0; i < nsems; i++)
+	for (i = 0; i < nsems; i++) {
 		INIT_LIST_HEAD(&sma->sem_base[i].sem_pending);
+		spin_lock_init(&sma->sem_base[i].lock);
+		spin_lock(&sma->sem_base[i].lock);
+	}
 
 	sma->complex_count = 0;
 	INIT_LIST_HEAD(&sma->sem_pending);
 	INIT_LIST_HEAD(&sma->list_id);
 	sma->sem_nsems = nsems;
 	sma->sem_ctime = get_seconds();
-	sem_unlock(sma);
+	sem_unlock(sma, -1);
 
 	return sma->sem_perm.id;
 }
@@ -461,17 +696,13 @@ undo:
 static void wake_up_sem_queue_prepare(struct list_head *pt,
 				struct sem_queue *q, int error)
 {
-	if (list_empty(pt)) {
-		/*
-		 * Hold preempt off so that we don't get preempted and have the
-		 * wakee busy-wait until we're scheduled back on.
-		 */
-		preempt_disable();
-	}
-	q->status = IN_WAKEUP;
-	q->pid = error;
+	if (list_empty(pt))
+		queuewakeup_prepare();
+
+	queuewakeup_block(&q->done);
+	q->status = error;
 
-	list_add_tail(&q->simple_list, pt);
+	list_add_tail(&q->list, pt);
 }
 
 /**
@@ -480,8 +711,8 @@ static void wake_up_sem_queue_prepare(struct list_head *pt,
  *
  * Do the actual wake-up.
  * The function is called without any locks held, thus the semaphore array
- * could be destroyed already and the tasks can disappear as soon as the
- * status is set to the actual return code.
+ * could be destroyed already and the tasks can disappear as soon as
+ * queuewakeup_handsoff() is called.
  */
 static void wake_up_sem_queue_do(struct list_head *pt)
 {
@@ -489,22 +720,19 @@ static void wake_up_sem_queue_do(struct list_head *pt)
 	int did_something;
 
 	did_something = !list_empty(pt);
-	list_for_each_entry_safe(q, t, pt, simple_list) {
+	list_for_each_entry_safe(q, t, pt, list) {
 		wake_up_process(q->sleeper);
-		/* q can disappear immediately after writing q->status. */
-		smp_wmb();
-		q->status = q->pid;
+		/* q can disappear immediately after completing q->done */
+		queuewakeup_handsoff(&q->done);
 	}
 	if (did_something)
-		preempt_enable();
+		queuewakeup_completed();
 }
 
 static void unlink_queue(struct sem_array *sma, struct sem_queue *q)
 {
 	list_del(&q->list);
-	if (q->nsops == 1)
-		list_del(&q->simple_list);
-	else
+	if (q->nsops > 1)
 		sma->complex_count--;
 }
 
@@ -557,9 +785,9 @@ static int check_restart(struct sem_array *sma, struct sem_queue *q)
 	}
 	/*
 	 * semval is 0. Check if there are wait-for-zero semops.
-	 * They must be the first entries in the per-semaphore simple queue
+	 * They must be the first entries in the per-semaphore queue
 	 */
-	h = list_first_entry(&curr->sem_pending, struct sem_queue, simple_list);
+	h = list_first_entry(&curr->sem_pending, struct sem_queue, list);
 	BUG_ON(h->nsops != 1);
 	BUG_ON(h->sops[0].sem_num != q->sops[0].sem_num);
 
@@ -579,8 +807,9 @@ static int check_restart(struct sem_array *sma, struct sem_queue *q)
  * @pt: list head for the tasks that must be woken up.
  *
  * update_queue must be called after a semaphore in a semaphore array
- * was modified. If multiple semaphore were modified, then @semnum
- * must be set to -1.
+ * was modified. If multiple semaphores were modified, update_queue must
+ * be called with semnum = -1, as well as with the number of each modified
+ * semaphore.
  * The tasks that must be woken up are added to @pt. The return code
  * is stored in q->pid.
  * The function return 1 if at least one semop was completed successfully.
@@ -590,30 +819,19 @@ static int update_queue(struct sem_array *sma, int semnum, struct list_head *pt)
 	struct sem_queue *q;
 	struct list_head *walk;
 	struct list_head *pending_list;
-	int offset;
 	int semop_completed = 0;
 
-	/* if there are complex operations around, then knowing the semaphore
-	 * that was modified doesn't help us. Assume that multiple semaphores
-	 * were modified.
-	 */
-	if (sma->complex_count)
-		semnum = -1;
-
-	if (semnum == -1) {
+	if (semnum == -1)
 		pending_list = &sma->sem_pending;
-		offset = offsetof(struct sem_queue, list);
-	} else {
+	else
 		pending_list = &sma->sem_base[semnum].sem_pending;
-		offset = offsetof(struct sem_queue, simple_list);
-	}
 
 again:
 	walk = pending_list->next;
 	while (walk != pending_list) {
 		int error, restart;
 
-		q = (struct sem_queue *)((char *)walk - offset);
+		q = container_of(walk, struct sem_queue, list);
 		walk = walk->next;
 
 		/* If we are scanning the single sop, per-semaphore list of
@@ -672,9 +890,18 @@ static void do_smart_update(struct sem_array *sma, struct sembuf *sops, int nsop
 	if (sma->complex_count || sops == NULL) {
 		if (update_queue(sma, -1, pt))
 			otime = 1;
+	}
+
+	if (!sops) {
+		/* No semops; something special is going on. */
+		for (i = 0; i < sma->sem_nsems; i++) {
+			if (update_queue(sma, i, pt))
+				otime = 1;
+		}
 		goto done;
 	}
 
+	/* Check the semaphores that were modified. */
 	for (i = 0; i < nsops; i++) {
 		if (sops[i].sem_op > 0 ||
 			(sops[i].sem_op < 0 &&
@@ -745,6 +972,7 @@ static void freeary(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp)
 	struct sem_queue *q, *tq;
 	struct sem_array *sma = container_of(ipcp, struct sem_array, sem_perm);
 	struct list_head tasks;
+	int i;
 
 	/* Free the existing undo structures for this semaphore set.  */
 	assert_spin_locked(&sma->sem_perm.lock);
@@ -763,10 +991,17 @@ static void freeary(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp)
 		unlink_queue(sma, q);
 		wake_up_sem_queue_prepare(&tasks, q, -EIDRM);
 	}
+	for (i = 0; i < sma->sem_nsems; i++) {
+		struct sem *sem = sma->sem_base + i;
+		list_for_each_entry_safe(q, tq, &sem->sem_pending, list) {
+			unlink_queue(sma, q);
+			wake_up_sem_queue_prepare(&tasks, q, -EIDRM);
+		}
+	}
 
 	/* Remove the semaphore set from the IDR */
 	sem_rmid(ns, sma);
-	sem_unlock(sma);
+	sem_unlock(sma, -1);
 
 	wake_up_sem_queue_do(&tasks);
 	ns->used_sems -= sma->sem_nsems;
@@ -799,7 +1034,7 @@ static unsigned long copy_semid_to_user(void __user *buf, struct semid64_ds *in,
 }
 
 static int semctl_nolock(struct ipc_namespace *ns, int semid,
-			 int cmd, int version, union semun arg)
+			 int cmd, int version, void __user *p)
 {
 	int err;
 	struct sem_array *sma;
@@ -834,7 +1069,7 @@ static int semctl_nolock(struct ipc_namespace *ns, int semid,
 		}
 		max_id = ipc_get_maxid(&sem_ids(ns));
 		up_read(&sem_ids(ns).rw_mutex);
-		if (copy_to_user (arg.__buf, &seminfo, sizeof(struct seminfo))) 
+		if (copy_to_user(p, &seminfo, sizeof(struct seminfo))) 
 			return -EFAULT;
 		return (max_id < 0) ? 0: max_id;
 	}
@@ -842,18 +1077,25 @@ static int semctl_nolock(struct ipc_namespace *ns, int semid,
 	case SEM_STAT:
 	{
 		struct semid64_ds tbuf;
-		int id;
+		int id = 0;
+
+		memset(&tbuf, 0, sizeof(tbuf));
 
 		if (cmd == SEM_STAT) {
-			sma = sem_lock(ns, semid);
-			if (IS_ERR(sma))
-				return PTR_ERR(sma);
+			rcu_read_lock();
+			sma = sem_obtain_object(ns, semid);
+			if (IS_ERR(sma)) {
+				err = PTR_ERR(sma);
+				goto out_unlock;
+			}
 			id = sma->sem_perm.id;
 		} else {
-			sma = sem_lock_check(ns, semid);
-			if (IS_ERR(sma))
-				return PTR_ERR(sma);
-			id = 0;
+			rcu_read_lock();
+			sma = sem_obtain_object_check(ns, semid);
+			if (IS_ERR(sma)) {
+				err = PTR_ERR(sma);
+				goto out_unlock;
+			}
 		}
 
 		err = -EACCES;
@@ -864,14 +1106,12 @@ static int semctl_nolock(struct ipc_namespace *ns, int semid,
 		if (err)
 			goto out_unlock;
 
-		memset(&tbuf, 0, sizeof(tbuf));
-
 		kernel_to_ipc64_perm(&sma->sem_perm, &tbuf.sem_perm);
 		tbuf.sem_otime  = sma->sem_otime;
 		tbuf.sem_ctime  = sma->sem_ctime;
 		tbuf.sem_nsems  = sma->sem_nsems;
-		sem_unlock(sma);
-		if (copy_semid_to_user (arg.buf, &tbuf, version))
+		rcu_read_unlock();
+		if (copy_semid_to_user(p, &tbuf, version))
 			return -EFAULT;
 		return id;
 	}
@@ -879,46 +1119,117 @@ static int semctl_nolock(struct ipc_namespace *ns, int semid,
 		return -EINVAL;
 	}
 out_unlock:
-	sem_unlock(sma);
+	rcu_read_unlock();
 	return err;
 }
 
-static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
-		int cmd, int version, union semun arg)
+static int semctl_setval(struct ipc_namespace *ns, int semid, int semnum,
+		unsigned long arg)
 {
+	struct sem_undo *un;
 	struct sem_array *sma;
 	struct sem* curr;
 	int err;
+	struct list_head tasks;
+	int val;
+#if defined(CONFIG_64BIT) && defined(__BIG_ENDIAN)
+	/* big-endian 64bit */
+	val = arg >> 32;
+#else
+	/* 32bit or little-endian 64bit */
+	val = arg;
+#endif
+
+	if (val > SEMVMX || val < 0)
+		return -ERANGE;
+
+	INIT_LIST_HEAD(&tasks);
+
+	rcu_read_lock();
+	sma = sem_obtain_object_check(ns, semid);
+	if (IS_ERR(sma)) {
+		rcu_read_unlock();
+		return PTR_ERR(sma);
+	}
+
+	if (semnum < 0 || semnum >= sma->sem_nsems) {
+		rcu_read_unlock();
+		return -EINVAL;
+	}
+
+
+	if (ipcperms(ns, &sma->sem_perm, S_IWUGO)) {
+		rcu_read_unlock();
+		return -EACCES;
+	}
+
+	err = security_sem_semctl(sma, SETVAL);
+	if (err) {
+		rcu_read_unlock();
+		return -EACCES;
+	}
+
+	sem_lock(sma, NULL, -1);
+
+	curr = &sma->sem_base[semnum];
+
+	assert_spin_locked(&sma->sem_perm.lock);
+	list_for_each_entry(un, &sma->list_id, list_id)
+		un->semadj[semnum] = 0;
+
+	curr->semval = val;
+	curr->sempid = task_tgid_vnr(current);
+	sma->sem_ctime = get_seconds();
+	/* maybe some queued-up processes were waiting for this */
+	do_smart_update(sma, NULL, 0, 0, &tasks);
+	sem_unlock(sma, -1);
+	wake_up_sem_queue_do(&tasks);
+	return 0;
+}
+
+static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
+		int cmd, void __user *p)
+{
+	struct sem_array *sma;
+	struct sem* curr;
+	int err, nsems;
 	ushort fast_sem_io[SEMMSL_FAST];
 	ushort* sem_io = fast_sem_io;
-	int nsems;
 	struct list_head tasks;
 
-	sma = sem_lock_check(ns, semid);
-	if (IS_ERR(sma))
+	INIT_LIST_HEAD(&tasks);
+
+	rcu_read_lock();
+	sma = sem_obtain_object_check(ns, semid);
+	if (IS_ERR(sma)) {
+		rcu_read_unlock();
 		return PTR_ERR(sma);
+	}
 
-	INIT_LIST_HEAD(&tasks);
 	nsems = sma->sem_nsems;
 
 	err = -EACCES;
 	if (ipcperms(ns, &sma->sem_perm,
-			(cmd == SETVAL || cmd == SETALL) ? S_IWUGO : S_IRUGO))
-		goto out_unlock;
+			cmd == SETALL ? S_IWUGO : S_IRUGO)) {
+		rcu_read_unlock();
+		goto out_wakeup;
+	}
 
 	err = security_sem_semctl(sma, cmd);
-	if (err)
-		goto out_unlock;
+	if (err) {
+		rcu_read_unlock();
+		goto out_wakeup;
+	}
 
 	err = -EACCES;
 	switch (cmd) {
 	case GETALL:
 	{
-		ushort __user *array = arg.array;
+		ushort __user *array = p;
 		int i;
 
 		if(nsems > SEMMSL_FAST) {
-			sem_getref_and_unlock(sma);
+			sem_getref(sma);
 
 			sem_io = ipc_alloc(sizeof(ushort)*nsems);
 			if(sem_io == NULL) {
@@ -928,15 +1239,17 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
 
 			sem_lock_and_putref(sma);
 			if (sma->sem_perm.deleted) {
-				sem_unlock(sma);
+				sem_unlock(sma, -1);
 				err = -EIDRM;
 				goto out_free;
 			}
+			sem_unlock(sma, -1);
 		}
 
+		sem_lock(sma, NULL, -1);
 		for (i = 0; i < sma->sem_nsems; i++)
 			sem_io[i] = sma->sem_base[i].semval;
-		sem_unlock(sma);
+		sem_unlock(sma, -1);
 		err = 0;
 		if(copy_to_user(array, sem_io, nsems*sizeof(ushort)))
 			err = -EFAULT;
@@ -947,7 +1260,8 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
 		int i;
 		struct sem_undo *un;
 
-		sem_getref_and_unlock(sma);
+		ipc_rcu_getref(sma);
+		rcu_read_unlock();
 
 		if(nsems > SEMMSL_FAST) {
 			sem_io = ipc_alloc(sizeof(ushort)*nsems);
@@ -957,7 +1271,7 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
 			}
 		}
 
-		if (copy_from_user (sem_io, arg.array, nsems*sizeof(ushort))) {
+		if (copy_from_user (sem_io, p, nsems*sizeof(ushort))) {
 			sem_putref(sma);
 			err = -EFAULT;
 			goto out_free;
@@ -972,7 +1286,7 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
 		}
 		sem_lock_and_putref(sma);
 		if (sma->sem_perm.deleted) {
-			sem_unlock(sma);
+			sem_unlock(sma, -1);
 			err = -EIDRM;
 			goto out_free;
 		}
@@ -991,12 +1305,13 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
 		err = 0;
 		goto out_unlock;
 	}
-	/* GETVAL, GETPID, GETNCTN, GETZCNT, SETVAL: fall-through */
+	/* GETVAL, GETPID, GETNCTN, GETZCNT: fall-through */
 	}
 	err = -EINVAL;
 	if(semnum < 0 || semnum >= nsems)
 		goto out_unlock;
 
+	sem_lock(sma, NULL, -1);
 	curr = &sma->sem_base[semnum];
 
 	switch (cmd) {
@@ -1012,32 +1327,12 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
 	case GETZCNT:
 		err = count_semzcnt(sma,semnum);
 		goto out_unlock;
-	case SETVAL:
-	{
-		int val = arg.val;
-		struct sem_undo *un;
-
-		err = -ERANGE;
-		if (val > SEMVMX || val < 0)
-			goto out_unlock;
-
-		assert_spin_locked(&sma->sem_perm.lock);
-		list_for_each_entry(un, &sma->list_id, list_id)
-			un->semadj[semnum] = 0;
-
-		curr->semval = val;
-		curr->sempid = task_tgid_vnr(current);
-		sma->sem_ctime = get_seconds();
-		/* maybe some queued-up processes were waiting for this */
-		do_smart_update(sma, NULL, 0, 0, &tasks);
-		err = 0;
-		goto out_unlock;
-	}
 	}
+
 out_unlock:
-	sem_unlock(sma);
+	sem_unlock(sma, -1);
+out_wakeup:
 	wake_up_sem_queue_do(&tasks);
-
 out_free:
 	if(sem_io != fast_sem_io)
 		ipc_free(sem_io, sizeof(ushort)*nsems);
@@ -1076,7 +1371,7 @@ copy_semid_from_user(struct semid64_ds *out, void __user *buf, int version)
  * NOTE: no locks must be held, the rw_mutex is taken inside this function.
  */
 static int semctl_down(struct ipc_namespace *ns, int semid,
-		       int cmd, int version, union semun arg)
+		       int cmd, int version, void __user *p)
 {
 	struct sem_array *sma;
 	int err;
@@ -1084,47 +1379,53 @@ static int semctl_down(struct ipc_namespace *ns, int semid,
 	struct kern_ipc_perm *ipcp;
 
 	if(cmd == IPC_SET) {
-		if (copy_semid_from_user(&semid64, arg.buf, version))
+		if (copy_semid_from_user(&semid64, p, version))
 			return -EFAULT;
 	}
 
-	ipcp = ipcctl_pre_down(ns, &sem_ids(ns), semid, cmd,
-			       &semid64.sem_perm, 0);
+	ipcp = ipcctl_pre_down_nolock(ns, &sem_ids(ns), semid, cmd,
+				      &semid64.sem_perm, 0);
 	if (IS_ERR(ipcp))
 		return PTR_ERR(ipcp);
 
 	sma = container_of(ipcp, struct sem_array, sem_perm);
 
 	err = security_sem_semctl(sma, cmd);
-	if (err)
+	if (err) {
+		rcu_read_unlock();
 		goto out_unlock;
+	}
 
 	switch(cmd){
 	case IPC_RMID:
+		sem_lock(sma, NULL, -1);
 		freeary(ns, ipcp);
 		goto out_up;
 	case IPC_SET:
+		sem_lock(sma, NULL, -1);
 		err = ipc_update_perm(&semid64.sem_perm, ipcp);
 		if (err)
 			goto out_unlock;
 		sma->sem_ctime = get_seconds();
 		break;
 	default:
+		rcu_read_unlock();
 		err = -EINVAL;
+		goto out_up;
 	}
 
 out_unlock:
-	sem_unlock(sma);
+	sem_unlock(sma, -1);
 out_up:
 	up_write(&sem_ids(ns).rw_mutex);
 	return err;
 }
 
-SYSCALL_DEFINE(semctl)(int semid, int semnum, int cmd, union semun arg)
+SYSCALL_DEFINE4(semctl, int, semid, int, semnum, int, cmd, unsigned long, arg)
 {
-	int err = -EINVAL;
 	int version;
 	struct ipc_namespace *ns;
+	void __user *p = (void __user *)arg;
 
 	if (semid < 0)
 		return -EINVAL;
@@ -1137,32 +1438,23 @@ SYSCALL_DEFINE(semctl)(int semid, int semnum, int cmd, union semun arg)
 	case SEM_INFO:
 	case IPC_STAT:
 	case SEM_STAT:
-		err = semctl_nolock(ns, semid, cmd, version, arg);
-		return err;
+		return semctl_nolock(ns, semid, cmd, version, p);
 	case GETALL:
 	case GETVAL:
 	case GETPID:
 	case GETNCNT:
 	case GETZCNT:
-	case SETVAL:
 	case SETALL:
-		err = semctl_main(ns,semid,semnum,cmd,version,arg);
-		return err;
+		return semctl_main(ns, semid, semnum, cmd, p);
+	case SETVAL:
+		return semctl_setval(ns, semid, semnum, arg);
 	case IPC_RMID:
 	case IPC_SET:
-		err = semctl_down(ns, semid, cmd, version, arg);
-		return err;
+		return semctl_down(ns, semid, cmd, version, p);
 	default:
 		return -EINVAL;
 	}
 }
-#ifdef CONFIG_HAVE_SYSCALL_WRAPPERS
-asmlinkage long SyS_semctl(int semid, int semnum, int cmd, union semun arg)
-{
-	return SYSC_semctl((int) semid, (int) semnum, (int) cmd, arg);
-}
-SYSCALL_ALIAS(sys_semctl, SyS_semctl);
-#endif
 
 /* If the task doesn't already have a undo_list, then allocate one
  * here.  We guarantee there is only one thread using this undo list,
@@ -1248,16 +1540,18 @@ static struct sem_undo *find_alloc_undo(struct ipc_namespace *ns, int semid)
 	spin_unlock(&ulp->lock);
 	if (likely(un!=NULL))
 		goto out;
-	rcu_read_unlock();
 
 	/* no undo structure around - allocate one. */
 	/* step 1: figure out the size of the semaphore array */
-	sma = sem_lock_check(ns, semid);
-	if (IS_ERR(sma))
+	sma = sem_obtain_object_check(ns, semid);
+	if (IS_ERR(sma)) {
+		rcu_read_unlock();
 		return ERR_CAST(sma);
+	}
 
 	nsems = sma->sem_nsems;
-	sem_getref_and_unlock(sma);
+	ipc_rcu_getref(sma);
+	rcu_read_unlock();
 
 	/* step 2: allocate new undo structure */
 	new = kzalloc(sizeof(struct sem_undo) + sizeof(short)*nsems, GFP_KERNEL);
@@ -1269,7 +1563,7 @@ static struct sem_undo *find_alloc_undo(struct ipc_namespace *ns, int semid)
 	/* step 3: Acquire the lock on semaphore array */
 	sem_lock_and_putref(sma);
 	if (sma->sem_perm.deleted) {
-		sem_unlock(sma);
+		sem_unlock(sma, -1);
 		kfree(new);
 		un = ERR_PTR(-EIDRM);
 		goto out;
@@ -1297,38 +1591,11 @@ static struct sem_undo *find_alloc_undo(struct ipc_namespace *ns, int semid)
 success:
 	spin_unlock(&ulp->lock);
 	rcu_read_lock();
-	sem_unlock(sma);
+	sem_unlock(sma, -1);
 out:
 	return un;
 }
 
-
-/**
- * get_queue_result - Retrieve the result code from sem_queue
- * @q: Pointer to queue structure
- *
- * Retrieve the return code from the pending queue. If IN_WAKEUP is found in
- * q->status, then we must loop until the value is replaced with the final
- * value: This may happen if a task is woken up by an unrelated event (e.g.
- * signal) and in parallel the task is woken up by another task because it got
- * the requested semaphores.
- *
- * The function can be called with or without holding the semaphore spinlock.
- */
-static int get_queue_result(struct sem_queue *q)
-{
-	int error;
-
-	error = q->status;
-	while (unlikely(error == IN_WAKEUP)) {
-		cpu_relax();
-		error = q->status;
-	}
-
-	return error;
-}
-
-
 SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
 		unsigned, nsops, const struct timespec __user *, timeout)
 {
@@ -1337,7 +1604,7 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
 	struct sembuf fast_sops[SEMOPM_FAST];
 	struct sembuf* sops = fast_sops, *sop;
 	struct sem_undo *un;
-	int undos = 0, alter = 0, max;
+	int undos = 0, alter = 0, max, locknum;
 	struct sem_queue queue;
 	unsigned long jiffies_left = 0;
 	struct ipc_namespace *ns;
@@ -1392,7 +1659,8 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
 
 	INIT_LIST_HEAD(&tasks);
 
-	sma = sem_lock_check(ns, semid);
+	rcu_read_lock();
+	sma = sem_obtain_object_check(ns, semid);
 	if (IS_ERR(sma)) {
 		if (un)
 			rcu_read_unlock();
@@ -1400,6 +1668,24 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
 		goto out_free;
 	}
 
+	error = -EFBIG;
+	if (max >= sma->sem_nsems) {
+		rcu_read_unlock();
+		goto out_wakeup;
+	}
+
+	error = -EACCES;
+	if (ipcperms(ns, &sma->sem_perm, alter ? S_IWUGO : S_IRUGO)) {
+		rcu_read_unlock();
+		goto out_wakeup;
+	}
+
+	error = security_sem_semop(sma, sops, nsops, alter);
+	if (error) {
+		rcu_read_unlock();
+		goto out_wakeup;
+	}
+
 	/*
 	 * semid identifiers are not unique - find_alloc_undo may have
 	 * allocated an undo structure, it was invalidated by an RMID
@@ -1408,6 +1694,7 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
 	 * "un" itself is guaranteed by rcu.
 	 */
 	error = -EIDRM;
+	locknum = sem_lock(sma, sops, nsops);
 	if (un) {
 		if (un->semid == -1) {
 			rcu_read_unlock();
@@ -1425,18 +1712,6 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
 		}
 	}
 
-	error = -EFBIG;
-	if (max >= sma->sem_nsems)
-		goto out_unlock_free;
-
-	error = -EACCES;
-	if (ipcperms(ns, &sma->sem_perm, alter ? S_IWUGO : S_IRUGO))
-		goto out_unlock_free;
-
-	error = security_sem_semop(sma, sops, nsops, alter);
-	if (error)
-		goto out_unlock_free;
-
 	error = try_atomic_semop (sma, sops, nsops, un, task_tgid_vnr(current));
 	if (error <= 0) {
 		if (alter && error == 0)
@@ -1454,73 +1729,63 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
 	queue.undo = un;
 	queue.pid = task_tgid_vnr(current);
 	queue.alter = alter;
-	if (alter)
-		list_add_tail(&queue.list, &sma->sem_pending);
-	else
-		list_add(&queue.list, &sma->sem_pending);
 
 	if (nsops == 1) {
 		struct sem *curr;
 		curr = &sma->sem_base[sops->sem_num];
 
 		if (alter)
-			list_add_tail(&queue.simple_list, &curr->sem_pending);
+			list_add_tail(&queue.list, &curr->sem_pending);
 		else
-			list_add(&queue.simple_list, &curr->sem_pending);
+			list_add(&queue.list, &curr->sem_pending);
 	} else {
-		INIT_LIST_HEAD(&queue.simple_list);
+		if (alter)
+			list_add_tail(&queue.list, &sma->sem_pending);
+		else
+			list_add(&queue.list, &sma->sem_pending);
 		sma->complex_count++;
 	}
 
 	queue.status = -EINTR;
 	queue.sleeper = current;
+	queuewakeup_init(&queue.done);
 
 sleep_again:
 	current->state = TASK_INTERRUPTIBLE;
-	sem_unlock(sma);
+	sem_unlock(sma, locknum);
 
 	if (timeout)
 		jiffies_left = schedule_timeout(jiffies_left);
 	else
 		schedule();
 
-	error = get_queue_result(&queue);
+	error = queue.status;
 
 	if (error != -EINTR) {
 		/* fast path: update_queue already obtained all requested
-		 * resources.
-		 * Perform a smp_mb(): User space could assume that semop()
-		 * is a memory barrier: Without the mb(), the cpu could
-		 * speculatively read in user space stale data that was
-		 * overwritten by the previous owner of the semaphore.
+		 * resources. Just ensure that update_queue completed
+		 * it's access to &queue.
 		 */
-		smp_mb();
+		queuewakeup_wait(&queue.done);
 
 		goto out_free;
 	}
 
-	sma = sem_lock(ns, semid);
+	sma = sem_obtain_lock(ns, semid, sops, nsops, &locknum);
 
 	/*
 	 * 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)) {
-		goto out_free;
-	}
-
-
-	/*
-	 * If queue.status != -EINTR we are woken up by another process.
-	 * Leave without unlink_queue(), but with sem_unlock().
-	 */
-
+	error = queue.status;
 	if (error != -EINTR) {
-		goto out_unlock_free;
+		/* If there is a return code, then we can leave immediately. */
+		if (!IS_ERR(sma)) {
+			/* sem_lock() succeeded - then unlock */
+			sem_unlock(sma, locknum);
+		}
+		/* Except that we must wait for the hands-off */
+		queuewakeup_wait(&queue.done);
+		goto out_free;
 	}
 
 	/*
@@ -1538,8 +1803,8 @@ sleep_again:
 	unlink_queue(sma, &queue);
 
 out_unlock_free:
-	sem_unlock(sma);
-
+	sem_unlock(sma, locknum);
+out_wakeup:
 	wake_up_sem_queue_do(&tasks);
 out_free:
 	if(sops != fast_sops)
@@ -1612,12 +1877,14 @@ void exit_sem(struct task_struct *tsk)
 			semid = -1;
 		 else
 			semid = un->semid;
-		rcu_read_unlock();
 
-		if (semid == -1)
+		if (semid == -1) {
+			rcu_read_unlock();
 			break;
+		}
 
-		sma = sem_lock_check(tsk->nsproxy->ipc_ns, un->semid);
+		sma = sem_obtain_object_check(tsk->nsproxy->ipc_ns, un->semid);
+		sem_lock(sma, NULL, -1);
 
 		/* exit_sem raced with IPC_RMID, nothing to do */
 		if (IS_ERR(sma))
@@ -1628,7 +1895,7 @@ void exit_sem(struct task_struct *tsk)
 			/* exit_sem raced with IPC_RMID+semget() that created
 			 * exactly the same semid. Nothing to do.
 			 */
-			sem_unlock(sma);
+			sem_unlock(sma, -1);
 			continue;
 		}
 
@@ -1668,7 +1935,7 @@ void exit_sem(struct task_struct *tsk)
 		/* maybe some queued-up processes were waiting for this */
 		INIT_LIST_HEAD(&tasks);
 		do_smart_update(sma, NULL, 0, 1, &tasks);
-		sem_unlock(sma);
+		sem_unlock(sma, -1);
 		wake_up_sem_queue_do(&tasks);
 
 		kfree_rcu(un, rcu);
diff --git a/ipc/syscall.c b/ipc/syscall.c
index 0d1e32ce..5242948 100644
--- a/ipc/syscall.c
+++ b/ipc/syscall.c
@@ -33,12 +33,12 @@ SYSCALL_DEFINE6(ipc, unsigned int, call, int, first, unsigned long, second,
 	case SEMGET:
 		return sys_semget(first, second, third);
 	case SEMCTL: {
-		union semun fourth;
+		unsigned long arg;
 		if (!ptr)
 			return -EINVAL;
-		if (get_user(fourth.__pad, (void __user * __user *) ptr))
+		if (get_user(arg, (unsigned long __user *) ptr))
 			return -EFAULT;
-		return sys_semctl(first, second, third, fourth);
+		return sys_semctl(first, second, third, arg);
 	}
 
 	case MSGSND:
diff --git a/ipc/util.c b/ipc/util.c
index 464a8ab..602ef2f 100644
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -668,38 +668,81 @@ void ipc64_perm_to_ipc_perm (struct ipc64_perm *in, struct ipc_perm *out)
 }
 
 /**
+ * ipc_obtain_object
+ * @ids: ipc identifier set
+ * @id: ipc id to look for
+ *
+ * Look for an id in the ipc ids idr and return associated ipc object.
+ *
+ * Call inside the RCU critical section.
+ * The ipc object is *not* locked on exit.
+ */
+struct kern_ipc_perm *ipc_obtain_object(struct ipc_ids *ids, int id)
+{
+	struct kern_ipc_perm *out;
+	int lid = ipcid_to_idx(id);
+
+	out = idr_find(&ids->ipcs_idr, lid);
+	if (!out)
+		return ERR_PTR(-EINVAL);
+
+	return out;
+}
+
+/**
  * ipc_lock - Lock an ipc structure without rw_mutex held
  * @ids: IPC identifier set
  * @id: ipc id to look for
  *
  * Look for an id in the ipc ids idr and lock the associated ipc object.
  *
- * The ipc object is locked on exit.
+ * The ipc object is locked on successful exit.
  */
-
 struct kern_ipc_perm *ipc_lock(struct ipc_ids *ids, int id)
 {
 	struct kern_ipc_perm *out;
-	int lid = ipcid_to_idx(id);
 
 	rcu_read_lock();
-	out = idr_find(&ids->ipcs_idr, lid);
-	if (out == NULL) {
-		rcu_read_unlock();
-		return ERR_PTR(-EINVAL);
-	}
+	out = ipc_obtain_object(ids, id);
+	if (IS_ERR(out))
+		goto err1;
 
 	spin_lock(&out->lock);
-	
+
 	/* ipc_rmid() may have already freed the ID while ipc_lock
 	 * was spinning: here verify that the structure is still valid
 	 */
-	if (out->deleted) {
-		spin_unlock(&out->lock);
-		rcu_read_unlock();
-		return ERR_PTR(-EINVAL);
-	}
+	if (!out->deleted)
+		return out;
+
+	spin_unlock(&out->lock);
+	out = ERR_PTR(-EINVAL);
+err1:
+	rcu_read_unlock();
+	return out;
+}
+
+/**
+ * ipc_obtain_object_check
+ * @ids: ipc identifier set
+ * @id: ipc id to look for
+ *
+ * Similar to ipc_obtain_object() but also checks
+ * the ipc object reference counter.
+ *
+ * Call inside the RCU critical section.
+ * The ipc object is *not* locked on exit.
+ */
+struct kern_ipc_perm *ipc_obtain_object_check(struct ipc_ids *ids, int id)
+{
+	struct kern_ipc_perm *out = ipc_obtain_object(ids, id);
 
+	if (IS_ERR(out))
+		goto out;
+
+	if (ipc_checkid(out, id))
+		return ERR_PTR(-EIDRM);
+out:
 	return out;
 }
 
@@ -780,11 +823,28 @@ struct kern_ipc_perm *ipcctl_pre_down(struct ipc_namespace *ns,
 				      struct ipc64_perm *perm, int extra_perm)
 {
 	struct kern_ipc_perm *ipcp;
+
+	ipcp = ipcctl_pre_down_nolock(ns, ids, id, cmd, perm, extra_perm);
+	if (IS_ERR(ipcp))
+		goto out;
+
+	spin_lock(&ipcp->lock);
+out:
+	return ipcp;
+}
+
+struct kern_ipc_perm *ipcctl_pre_down_nolock(struct ipc_namespace *ns,
+					     struct ipc_ids *ids, int id, int cmd,
+					     struct ipc64_perm *perm, int extra_perm)
+{
 	kuid_t euid;
-	int err;
+	int err = -EPERM;
+	struct kern_ipc_perm *ipcp;
 
 	down_write(&ids->rw_mutex);
-	ipcp = ipc_lock_check(ids, id);
+	rcu_read_lock();
+
+	ipcp = ipc_obtain_object_check(ids, id);
 	if (IS_ERR(ipcp)) {
 		err = PTR_ERR(ipcp);
 		goto out_up;
@@ -793,17 +853,21 @@ struct kern_ipc_perm *ipcctl_pre_down(struct ipc_namespace *ns,
 	audit_ipc_obj(ipcp);
 	if (cmd == IPC_SET)
 		audit_ipc_set_perm(extra_perm, perm->uid,
-					 perm->gid, perm->mode);
+				   perm->gid, perm->mode);
 
 	euid = current_euid();
 	if (uid_eq(euid, ipcp->cuid) || uid_eq(euid, ipcp->uid)  ||
 	    ns_capable(ns->user_ns, CAP_SYS_ADMIN))
 		return ipcp;
 
-	err = -EPERM;
-	ipc_unlock(ipcp);
 out_up:
+	/*
+	 * Unsuccessful lookup, unlock and return
+	 * the corresponding error.
+	 */
+	rcu_read_unlock();
 	up_write(&ids->rw_mutex);
+
 	return ERR_PTR(err);
 }
 
@@ -964,7 +1028,7 @@ static int sysvipc_proc_open(struct inode *inode, struct file *file)
 	seq = file->private_data;
 	seq->private = iter;
 
-	iter->iface = PDE(inode)->data;
+	iter->iface = PDE_DATA(inode);
 	iter->ns    = get_ipc_ns(current->nsproxy->ipc_ns);
 out:
 	return ret;
diff --git a/ipc/util.h b/ipc/util.h
index eeb79a1..c36b997 100644
--- a/ipc/util.h
+++ b/ipc/util.h
@@ -123,10 +123,14 @@ void ipc_rcu_getref(void *ptr);
 void ipc_rcu_putref(void *ptr);
 
 struct kern_ipc_perm *ipc_lock(struct ipc_ids *, int);
+struct kern_ipc_perm *ipc_obtain_object(struct ipc_ids *ids, int id);
 
 void kernel_to_ipc64_perm(struct kern_ipc_perm *in, struct ipc64_perm *out);
 void ipc64_perm_to_ipc_perm(struct ipc64_perm *in, struct ipc_perm *out);
 int ipc_update_perm(struct ipc64_perm *in, struct kern_ipc_perm *out);
+struct kern_ipc_perm *ipcctl_pre_down_nolock(struct ipc_namespace *ns,
+					     struct ipc_ids *ids, int id, int cmd,
+					     struct ipc64_perm *perm, int extra_perm);
 struct kern_ipc_perm *ipcctl_pre_down(struct ipc_namespace *ns,
 				      struct ipc_ids *ids, int id, int cmd,
 				      struct ipc64_perm *perm, int extra_perm);
@@ -150,14 +154,9 @@ static inline int ipc_buildid(int id, int seq)
 	return SEQ_MULTIPLIER * seq + id;
 }
 
-/*
- * Must be called with ipcp locked
- */
 static inline int ipc_checkid(struct kern_ipc_perm *ipcp, int uid)
 {
-	if (uid / SEQ_MULTIPLIER != ipcp->seq)
-		return 1;
-	return 0;
+	return uid / SEQ_MULTIPLIER != ipcp->seq;
 }
 
 static inline void ipc_lock_by_ptr(struct kern_ipc_perm *perm)
@@ -172,7 +171,13 @@ static inline void ipc_unlock(struct kern_ipc_perm *perm)
 	rcu_read_unlock();
 }
 
+static inline void ipc_lock_object(struct kern_ipc_perm *perm)
+{
+	spin_lock(&perm->lock);
+}
+
 struct kern_ipc_perm *ipc_lock_check(struct ipc_ids *ids, int id);
+struct kern_ipc_perm *ipc_obtain_object_check(struct ipc_ids *ids, int id);
 int ipcget(struct ipc_namespace *ns, struct ipc_ids *ids,
 			struct ipc_ops *ops, struct ipc_params *params);
 void free_ipcs(struct ipc_namespace *ns, struct ipc_ids *ids,
diff --git a/kernel/.gitignore b/kernel/.gitignore
index ab4f109..b3097bd 100644
--- a/kernel/.gitignore
+++ b/kernel/.gitignore
@@ -4,3 +4,4 @@
 config_data.h
 config_data.gz
 timeconst.h
+hz.bc
diff --git a/kernel/acct.c b/kernel/acct.c
index b9bd7f0..85389fe 100644
--- a/kernel/acct.c
+++ b/kernel/acct.c
@@ -543,6 +543,7 @@ static void do_acct_process(struct bsd_acct_struct *acct,
 	 * Kernel segment override to datasegment and write it
 	 * to the accounting file.
 	 */
+	file_start_write(file);
 	fs = get_fs();
 	set_fs(KERNEL_DS);
 	/*
@@ -554,6 +555,7 @@ static void do_acct_process(struct bsd_acct_struct *acct,
 			       sizeof(acct_t), &file->f_pos);
 	current->signal->rlim[RLIMIT_FSIZE].rlim_cur = flim;
 	set_fs(fs);
+	file_end_write(file);
 out:
 	revert_creds(orig_cred);
 }
diff --git a/kernel/async.c b/kernel/async.c
index 8ddee2c..61f023c 100644
--- a/kernel/async.c
+++ b/kernel/async.c
@@ -73,7 +73,7 @@ struct async_entry {
 	struct list_head	global_list;
 	struct work_struct	work;
 	async_cookie_t		cookie;
-	async_func_ptr		*func;
+	async_func_t		func;
 	void			*data;
 	struct async_domain	*domain;
 };
@@ -84,24 +84,20 @@ static atomic_t entry_count;
 
 static async_cookie_t lowest_in_progress(struct async_domain *domain)
 {
-	struct async_entry *first = NULL;
+	struct list_head *pending;
 	async_cookie_t ret = ASYNC_COOKIE_MAX;
 	unsigned long flags;
 
 	spin_lock_irqsave(&async_lock, flags);
 
-	if (domain) {
-		if (!list_empty(&domain->pending))
-			first = list_first_entry(&domain->pending,
-					struct async_entry, domain_list);
-	} else {
-		if (!list_empty(&async_global_pending))
-			first = list_first_entry(&async_global_pending,
-					struct async_entry, global_list);
-	}
+	if (domain)
+		pending = &domain->pending;
+	else
+		pending = &async_global_pending;
 
-	if (first)
-		ret = first->cookie;
+	if (!list_empty(pending))
+		ret = list_first_entry(pending, struct async_entry,
+				       domain_list)->cookie;
 
 	spin_unlock_irqrestore(&async_lock, flags);
 	return ret;
@@ -149,7 +145,7 @@ static void async_run_entry_fn(struct work_struct *work)
 	wake_up(&async_done);
 }
 
-static async_cookie_t __async_schedule(async_func_ptr *ptr, void *data, struct async_domain *domain)
+static async_cookie_t __async_schedule(async_func_t func, void *data, struct async_domain *domain)
 {
 	struct async_entry *entry;
 	unsigned long flags;
@@ -169,13 +165,13 @@ static async_cookie_t __async_schedule(async_func_ptr *ptr, void *data, struct a
 		spin_unlock_irqrestore(&async_lock, flags);
 
 		/* low on memory.. run synchronously */
-		ptr(data, newcookie);
+		func(data, newcookie);
 		return newcookie;
 	}
 	INIT_LIST_HEAD(&entry->domain_list);
 	INIT_LIST_HEAD(&entry->global_list);
 	INIT_WORK(&entry->work, async_run_entry_fn);
-	entry->func = ptr;
+	entry->func = func;
 	entry->data = data;
 	entry->domain = domain;
 
@@ -202,21 +198,21 @@ static async_cookie_t __async_schedule(async_func_ptr *ptr, void *data, struct a
 
 /**
  * async_schedule - schedule a function for asynchronous execution
- * @ptr: function to execute asynchronously
+ * @func: function to execute asynchronously
  * @data: data pointer to pass to the function
  *
  * Returns an async_cookie_t that may be used for checkpointing later.
  * Note: This function may be called from atomic or non-atomic contexts.
  */
-async_cookie_t async_schedule(async_func_ptr *ptr, void *data)
+async_cookie_t async_schedule(async_func_t func, void *data)
 {
-	return __async_schedule(ptr, data, &async_dfl_domain);
+	return __async_schedule(func, data, &async_dfl_domain);
 }
 EXPORT_SYMBOL_GPL(async_schedule);
 
 /**
  * async_schedule_domain - schedule a function for asynchronous execution within a certain domain
- * @ptr: function to execute asynchronously
+ * @func: function to execute asynchronously
  * @data: data pointer to pass to the function
  * @domain: the domain
  *
@@ -226,10 +222,10 @@ EXPORT_SYMBOL_GPL(async_schedule);
  * synchronization domain is specified via @domain.  Note: This function
  * may be called from atomic or non-atomic contexts.
  */
-async_cookie_t async_schedule_domain(async_func_ptr *ptr, void *data,
+async_cookie_t async_schedule_domain(async_func_t func, void *data,
 				     struct async_domain *domain)
 {
-	return __async_schedule(ptr, data, domain);
+	return __async_schedule(func, data, domain);
 }
 EXPORT_SYMBOL_GPL(async_schedule_domain);
 
diff --git a/kernel/audit.c b/kernel/audit.c
index d596e53..488f85f 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -58,7 +58,7 @@
 #ifdef CONFIG_SECURITY
 #include <linux/security.h>
 #endif
-#include <linux/netlink.h>
+#include <net/netlink.h>
 #include <linux/freezer.h>
 #include <linux/tty.h>
 #include <linux/pid_namespace.h>
@@ -910,7 +910,7 @@ static void audit_receive_skb(struct sk_buff *skb)
 {
 	struct nlmsghdr *nlh;
 	/*
-	 * len MUST be signed for NLMSG_NEXT to be able to dec it below 0
+	 * len MUST be signed for nlmsg_next to be able to dec it below 0
 	 * if the nlmsg_len was not aligned
 	 */
 	int len;
@@ -919,13 +919,13 @@ static void audit_receive_skb(struct sk_buff *skb)
 	nlh = nlmsg_hdr(skb);
 	len = skb->len;
 
-	while (NLMSG_OK(nlh, len)) {
+	while (nlmsg_ok(nlh, len)) {
 		err = audit_receive_msg(skb, nlh);
 		/* if err or if this message says it wants a response */
 		if (err || (nlh->nlmsg_flags & NLM_F_ACK))
 			netlink_ack(skb, nlh, err);
 
-		nlh = NLMSG_NEXT(nlh, len);
+		nlh = nlmsg_next(nlh, &len);
 	}
 }
 
@@ -1483,7 +1483,7 @@ void audit_log_end(struct audit_buffer *ab)
 		audit_log_lost("rate limit exceeded");
 	} else {
 		struct nlmsghdr *nlh = nlmsg_hdr(ab->skb);
-		nlh->nlmsg_len = ab->skb->len - NLMSG_SPACE(0);
+		nlh->nlmsg_len = ab->skb->len - NLMSG_HDRLEN;
 
 		if (audit_pid) {
 			skb_queue_tail(&audit_skb_queue, ab->skb);
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index a32f943..06aeb42 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -59,7 +59,7 @@
 #include <linux/vmalloc.h> /* TODO: replace with more sophisticated array */
 #include <linux/eventfd.h>
 #include <linux/poll.h>
-#include <linux/flex_array.h> /* used in cgroup_attach_proc */
+#include <linux/flex_array.h> /* used in cgroup_attach_task */
 #include <linux/kthread.h>
 
 #include <linux/atomic.h>
@@ -238,6 +238,8 @@ static DEFINE_SPINLOCK(hierarchy_id_lock);
 /* dummytop is a shorthand for the dummy hierarchy's top cgroup */
 #define dummytop (&rootnode.top_cgroup)
 
+static struct cgroup_name root_cgroup_name = { .name = "/" };
+
 /* This flag indicates whether tasks in the fork and exit paths should
  * check for fork/exit handlers to call. This avoids us having to do
  * extra work in the fork/exit path if none of the subsystems need to
@@ -859,6 +861,17 @@ static struct inode *cgroup_new_inode(umode_t mode, struct super_block *sb)
 	return inode;
 }
 
+static struct cgroup_name *cgroup_alloc_name(struct dentry *dentry)
+{
+	struct cgroup_name *name;
+
+	name = kmalloc(sizeof(*name) + dentry->d_name.len + 1, GFP_KERNEL);
+	if (!name)
+		return NULL;
+	strcpy(name->name, dentry->d_name.name);
+	return name;
+}
+
 static void cgroup_free_fn(struct work_struct *work)
 {
 	struct cgroup *cgrp = container_of(work, struct cgroup, free_work);
@@ -889,6 +902,7 @@ static void cgroup_free_fn(struct work_struct *work)
 	simple_xattrs_free(&cgrp->xattrs);
 
 	ida_simple_remove(&cgrp->root->cgroup_ida, cgrp->id);
+	kfree(rcu_dereference_raw(cgrp->name));
 	kfree(cgrp);
 }
 
@@ -1421,6 +1435,7 @@ static void init_cgroup_root(struct cgroupfs_root *root)
 	INIT_LIST_HEAD(&root->allcg_list);
 	root->number_of_cgroups = 1;
 	cgrp->root = root;
+	cgrp->name = &root_cgroup_name;
 	cgrp->top_cgroup = cgrp;
 	init_cgroup_housekeeping(cgrp);
 	list_add_tail(&cgrp->allcg_node, &root->allcg_list);
@@ -1769,49 +1784,45 @@ static struct kobject *cgroup_kobj;
  * @buf: the buffer to write the path into
  * @buflen: the length of the buffer
  *
- * Called with cgroup_mutex held or else with an RCU-protected cgroup
- * reference.  Writes path of cgroup into buf.  Returns 0 on success,
- * -errno on error.
+ * Writes path of cgroup into buf.  Returns 0 on success, -errno on error.
+ *
+ * We can't generate cgroup path using dentry->d_name, as accessing
+ * dentry->name must be protected by irq-unsafe dentry->d_lock or parent
+ * inode's i_mutex, while on the other hand cgroup_path() can be called
+ * with some irq-safe spinlocks held.
  */
 int cgroup_path(const struct cgroup *cgrp, char *buf, int buflen)
 {
-	struct dentry *dentry = cgrp->dentry;
+	int ret = -ENAMETOOLONG;
 	char *start;
 
-	rcu_lockdep_assert(rcu_read_lock_held() || cgroup_lock_is_held(),
-			   "cgroup_path() called without proper locking");
-
-	if (cgrp == dummytop) {
-		/*
-		 * Inactive subsystems have no dentry for their root
-		 * cgroup
-		 */
-		strcpy(buf, "/");
-		return 0;
-	}
-
 	start = buf + buflen - 1;
-
 	*start = '\0';
-	for (;;) {
-		int len = dentry->d_name.len;
 
+	rcu_read_lock();
+	while (cgrp) {
+		const char *name = cgroup_name(cgrp);
+		int len;
+
+		len = strlen(name);
 		if ((start -= len) < buf)
-			return -ENAMETOOLONG;
-		memcpy(start, dentry->d_name.name, len);
-		cgrp = cgrp->parent;
-		if (!cgrp)
-			break;
+			goto out;
+		memcpy(start, name, len);
 
-		dentry = cgrp->dentry;
 		if (!cgrp->parent)
-			continue;
+			break;
+
 		if (--start < buf)
-			return -ENAMETOOLONG;
+			goto out;
 		*start = '/';
+
+		cgrp = cgrp->parent;
 	}
+	ret = 0;
 	memmove(buf, start, buf + buflen - start);
-	return 0;
+out:
+	rcu_read_unlock();
+	return ret;
 }
 EXPORT_SYMBOL_GPL(cgroup_path);
 
@@ -1933,82 +1944,6 @@ static void cgroup_task_migrate(struct cgroup *cgrp, struct cgroup *oldcgrp,
 }
 
 /**
- * cgroup_attach_task - attach task 'tsk' to cgroup 'cgrp'
- * @cgrp: the cgroup the task is attaching to
- * @tsk: the task to be attached
- *
- * Call with cgroup_mutex and threadgroup locked. May take task_lock of
- * @tsk during call.
- */
-int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk)
-{
-	int retval = 0;
-	struct cgroup_subsys *ss, *failed_ss = NULL;
-	struct cgroup *oldcgrp;
-	struct cgroupfs_root *root = cgrp->root;
-	struct cgroup_taskset tset = { };
-	struct css_set *newcg;
-
-	/* @tsk either already exited or can't exit until the end */
-	if (tsk->flags & PF_EXITING)
-		return -ESRCH;
-
-	/* Nothing to do if the task is already in that cgroup */
-	oldcgrp = task_cgroup_from_root(tsk, root);
-	if (cgrp == oldcgrp)
-		return 0;
-
-	tset.single.task = tsk;
-	tset.single.cgrp = oldcgrp;
-
-	for_each_subsys(root, ss) {
-		if (ss->can_attach) {
-			retval = ss->can_attach(cgrp, &tset);
-			if (retval) {
-				/*
-				 * Remember on which subsystem the can_attach()
-				 * failed, so that we only call cancel_attach()
-				 * against the subsystems whose can_attach()
-				 * succeeded. (See below)
-				 */
-				failed_ss = ss;
-				goto out;
-			}
-		}
-	}
-
-	newcg = find_css_set(tsk->cgroups, cgrp);
-	if (!newcg) {
-		retval = -ENOMEM;
-		goto out;
-	}
-
-	cgroup_task_migrate(cgrp, oldcgrp, tsk, newcg);
-
-	for_each_subsys(root, ss) {
-		if (ss->attach)
-			ss->attach(cgrp, &tset);
-	}
-
-out:
-	if (retval) {
-		for_each_subsys(root, ss) {
-			if (ss == failed_ss)
-				/*
-				 * This subsystem was the one that failed the
-				 * can_attach() check earlier, so we don't need
-				 * to call cancel_attach() against it or any
-				 * remaining subsystems.
-				 */
-				break;
-			if (ss->cancel_attach)
-				ss->cancel_attach(cgrp, &tset);
-		}
-	}
-	return retval;
-}
-
-/**
  * cgroup_attach_task_all - attach task 'tsk' to all cgroups of task 'from'
  * @from: attach to all cgroups of a given task
  * @tsk: the task to be attached
@@ -2022,7 +1957,7 @@ int cgroup_attach_task_all(struct task_struct *from, struct task_struct *tsk)
 	for_each_active_root(root) {
 		struct cgroup *from_cg = task_cgroup_from_root(from, root);
 
-		retval = cgroup_attach_task(from_cg, tsk);
+		retval = cgroup_attach_task(from_cg, tsk, false);
 		if (retval)
 			break;
 	}
@@ -2033,21 +1968,22 @@ int cgroup_attach_task_all(struct task_struct *from, struct task_struct *tsk)
 EXPORT_SYMBOL_GPL(cgroup_attach_task_all);
 
 /**
- * cgroup_attach_proc - attach all threads in a threadgroup to a cgroup
+ * cgroup_attach_task - attach a task or a whole threadgroup to a cgroup
  * @cgrp: the cgroup to attach to
- * @leader: the threadgroup leader task_struct of the group to be attached
+ * @tsk: the task or the leader of the threadgroup to be attached
+ * @threadgroup: attach the whole threadgroup?
  *
  * Call holding cgroup_mutex and the group_rwsem of the leader. Will take
- * task_lock of each thread in leader's threadgroup individually in turn.
+ * task_lock of @tsk or each thread in the threadgroup individually in turn.
  */
-static int cgroup_attach_proc(struct cgroup *cgrp, struct task_struct *leader)
+int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk,
+		       bool threadgroup)
 {
 	int retval, i, group_size;
 	struct cgroup_subsys *ss, *failed_ss = NULL;
-	/* guaranteed to be initialized later, but the compiler needs this */
 	struct cgroupfs_root *root = cgrp->root;
 	/* threadgroup list cursor and array */
-	struct task_struct *tsk;
+	struct task_struct *leader = tsk;
 	struct task_and_cgroup *tc;
 	struct flex_array *group;
 	struct cgroup_taskset tset = { };
@@ -2059,17 +1995,19 @@ static int cgroup_attach_proc(struct cgroup *cgrp, struct task_struct *leader)
 	 * group - group_rwsem prevents new threads from appearing, and if
 	 * threads exit, this will just be an over-estimate.
 	 */
-	group_size = get_nr_threads(leader);
+	if (threadgroup)
+		group_size = get_nr_threads(tsk);
+	else
+		group_size = 1;
 	/* flex_array supports very large thread-groups better than kmalloc. */
 	group = flex_array_alloc(sizeof(*tc), group_size, GFP_KERNEL);
 	if (!group)
 		return -ENOMEM;
 	/* pre-allocate to guarantee space while iterating in rcu read-side. */
-	retval = flex_array_prealloc(group, 0, group_size - 1, GFP_KERNEL);
+	retval = flex_array_prealloc(group, 0, group_size, GFP_KERNEL);
 	if (retval)
 		goto out_free_group_list;
 
-	tsk = leader;
 	i = 0;
 	/*
 	 * Prevent freeing of tasks while we take a snapshot. Tasks that are
@@ -2098,6 +2036,9 @@ static int cgroup_attach_proc(struct cgroup *cgrp, struct task_struct *leader)
 		retval = flex_array_put(group, i, &ent, GFP_ATOMIC);
 		BUG_ON(retval != 0);
 		i++;
+
+		if (!threadgroup)
+			break;
 	} while_each_thread(leader, tsk);
 	rcu_read_unlock();
 	/* remember the number of threads in the array for later. */
@@ -2224,11 +2165,11 @@ retry_find_task:
 		tsk = tsk->group_leader;
 
 	/*
-	 * Workqueue threads may acquire PF_THREAD_BOUND and become
+	 * Workqueue threads may acquire PF_NO_SETAFFINITY and become
 	 * trapped in a cpuset, or RT worker may be born in a cgroup
 	 * with no rt_runtime allocated.  Just say no.
 	 */
-	if (tsk == kthreadd_task || (tsk->flags & PF_THREAD_BOUND)) {
+	if (tsk == kthreadd_task || (tsk->flags & PF_NO_SETAFFINITY)) {
 		ret = -EINVAL;
 		rcu_read_unlock();
 		goto out_unlock_cgroup;
@@ -2251,9 +2192,10 @@ retry_find_task:
 			put_task_struct(tsk);
 			goto retry_find_task;
 		}
-		ret = cgroup_attach_proc(cgrp, tsk);
-	} else
-		ret = cgroup_attach_task(cgrp, tsk);
+	}
+
+	ret = cgroup_attach_task(cgrp, tsk, threadgroup);
+
 	threadgroup_unlock(tsk);
 
 	put_task_struct(tsk);
@@ -2537,13 +2479,40 @@ static int cgroup_file_release(struct inode *inode, struct file *file)
 static int cgroup_rename(struct inode *old_dir, struct dentry *old_dentry,
 			    struct inode *new_dir, struct dentry *new_dentry)
 {
+	int ret;
+	struct cgroup_name *name, *old_name;
+	struct cgroup *cgrp;
+
+	/*
+	 * It's convinient to use parent dir's i_mutex to protected
+	 * cgrp->name.
+	 */
+	lockdep_assert_held(&old_dir->i_mutex);
+
 	if (!S_ISDIR(old_dentry->d_inode->i_mode))
 		return -ENOTDIR;
 	if (new_dentry->d_inode)
 		return -EEXIST;
 	if (old_dir != new_dir)
 		return -EIO;
-	return simple_rename(old_dir, old_dentry, new_dir, new_dentry);
+
+	cgrp = __d_cgrp(old_dentry);
+
+	name = cgroup_alloc_name(new_dentry);
+	if (!name)
+		return -ENOMEM;
+
+	ret = simple_rename(old_dir, old_dentry, new_dir, new_dentry);
+	if (ret) {
+		kfree(name);
+		return ret;
+	}
+
+	old_name = cgrp->name;
+	rcu_assign_pointer(cgrp->name, name);
+
+	kfree_rcu(old_name, rcu_head);
+	return 0;
 }
 
 static struct simple_xattrs *__d_xattrs(struct dentry *dentry)
@@ -3362,35 +3331,14 @@ static void pidlist_free(void *p)
 	else
 		kfree(p);
 }
-static void *pidlist_resize(void *p, int newcount)
-{
-	void *newlist;
-	/* note: if new alloc fails, old p will still be valid either way */
-	if (is_vmalloc_addr(p)) {
-		newlist = vmalloc(newcount * sizeof(pid_t));
-		if (!newlist)
-			return NULL;
-		memcpy(newlist, p, newcount * sizeof(pid_t));
-		vfree(p);
-	} else {
-		newlist = krealloc(p, newcount * sizeof(pid_t), GFP_KERNEL);
-	}
-	return newlist;
-}
 
 /*
  * pidlist_uniq - given a kmalloc()ed list, strip out all duplicate entries
- * If the new stripped list is sufficiently smaller and there's enough memory
- * to allocate a new buffer, will let go of the unneeded memory. Returns the
- * number of unique elements.
+ * Returns the number of unique elements.
  */
-/* is the size difference enough that we should re-allocate the array? */
-#define PIDLIST_REALLOC_DIFFERENCE(old, new) ((old) - PAGE_SIZE >= (new))
-static int pidlist_uniq(pid_t **p, int length)
+static int pidlist_uniq(pid_t *list, int length)
 {
 	int src, dest = 1;
-	pid_t *list = *p;
-	pid_t *newlist;
 
 	/*
 	 * we presume the 0th element is unique, so i starts at 1. trivial
@@ -3411,16 +3359,6 @@ static int pidlist_uniq(pid_t **p, int length)
 		dest++;
 	}
 after:
-	/*
-	 * if the length difference is large enough, we want to allocate a
-	 * smaller buffer to save memory. if this fails due to out of memory,
-	 * we'll just stay with what we've got.
-	 */
-	if (PIDLIST_REALLOC_DIFFERENCE(length, dest)) {
-		newlist = pidlist_resize(list, dest);
-		if (newlist)
-			*p = newlist;
-	}
 	return dest;
 }
 
@@ -3516,7 +3454,7 @@ static int pidlist_array_load(struct cgroup *cgrp, enum cgroup_filetype type,
 	/* now sort & (if procs) strip out duplicates */
 	sort(array, length, sizeof(pid_t), cmppid, NULL);
 	if (type == CGROUP_FILE_PROCS)
-		length = pidlist_uniq(&array, length);
+		length = pidlist_uniq(array, length);
 	l = cgroup_pidlist_find(cgrp, type);
 	if (!l) {
 		pidlist_free(array);
@@ -3930,12 +3868,6 @@ static int cgroup_write_event_control(struct cgroup *cgrp, struct cftype *cft,
 	if (ret)
 		goto fail;
 
-	if (efile->f_op->poll(efile, &event->pt) & POLLHUP) {
-		event->cft->unregister_event(cgrp, event->cft, event->eventfd);
-		ret = 0;
-		goto fail;
-	}
-
 	/*
 	 * Events should be removed after rmdir of cgroup directory, but before
 	 * destroying subsystem state objects. Let's take reference to cgroup
@@ -4131,17 +4063,8 @@ static void offline_css(struct cgroup_subsys *ss, struct cgroup *cgrp)
 	if (!(css->flags & CSS_ONLINE))
 		return;
 
-	/*
-	 * css_offline() should be called with cgroup_mutex unlocked.  See
-	 * 3fa59dfbc3 ("cgroup: fix potential deadlock in pre_destroy") for
-	 * details.  This temporary unlocking should go away once
-	 * cgroup_mutex is unexported from controllers.
-	 */
-	if (ss->css_offline) {
-		mutex_unlock(&cgroup_mutex);
+	if (ss->css_offline)
 		ss->css_offline(cgrp);
-		mutex_lock(&cgroup_mutex);
-	}
 
 	cgrp->subsys[ss->subsys_id]->flags &= ~CSS_ONLINE;
 }
@@ -4158,6 +4081,7 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
 			     umode_t mode)
 {
 	struct cgroup *cgrp;
+	struct cgroup_name *name;
 	struct cgroupfs_root *root = parent->root;
 	int err = 0;
 	struct cgroup_subsys *ss;
@@ -4168,9 +4092,14 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
 	if (!cgrp)
 		return -ENOMEM;
 
+	name = cgroup_alloc_name(dentry);
+	if (!name)
+		goto err_free_cgrp;
+	rcu_assign_pointer(cgrp->name, name);
+
 	cgrp->id = ida_simple_get(&root->cgroup_ida, 1, 0, GFP_KERNEL);
 	if (cgrp->id < 0)
-		goto err_free_cgrp;
+		goto err_free_name;
 
 	/*
 	 * Only live parents can have children.  Note that the liveliness
@@ -4276,6 +4205,8 @@ err_free_all:
 	deactivate_super(sb);
 err_free_id:
 	ida_simple_remove(&root->cgroup_ida, cgrp->id);
+err_free_name:
+	kfree(rcu_dereference_raw(cgrp->name));
 err_free_cgrp:
 	kfree(cgrp);
 	return err;
@@ -4295,56 +4226,13 @@ static int cgroup_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
 	return cgroup_create(c_parent, dentry, mode | S_IFDIR);
 }
 
-/*
- * Check the reference count on each subsystem. Since we already
- * established that there are no tasks in the cgroup, if the css refcount
- * is also 1, then there should be no outstanding references, so the
- * subsystem is safe to destroy. We scan across all subsystems rather than
- * using the per-hierarchy linked list of mounted subsystems since we can
- * be called via check_for_release() with no synchronization other than
- * RCU, and the subsystem linked list isn't RCU-safe.
- */
-static int cgroup_has_css_refs(struct cgroup *cgrp)
-{
-	int i;
-
-	/*
-	 * We won't need to lock the subsys array, because the subsystems
-	 * we're concerned about aren't going anywhere since our cgroup root
-	 * has a reference on them.
-	 */
-	for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
-		struct cgroup_subsys *ss = subsys[i];
-		struct cgroup_subsys_state *css;
-
-		/* Skip subsystems not present or not in this hierarchy */
-		if (ss == NULL || ss->root != cgrp->root)
-			continue;
-
-		css = cgrp->subsys[ss->subsys_id];
-		/*
-		 * When called from check_for_release() it's possible
-		 * that by this point the cgroup has been removed
-		 * and the css deleted. But a false-positive doesn't
-		 * matter, since it can only happen if the cgroup
-		 * has been deleted and hence no longer needs the
-		 * release agent to be called anyway.
-		 */
-		if (css && css_refcnt(css) > 1)
-			return 1;
-	}
-	return 0;
-}
-
 static int cgroup_destroy_locked(struct cgroup *cgrp)
 	__releases(&cgroup_mutex) __acquires(&cgroup_mutex)
 {
 	struct dentry *d = cgrp->dentry;
 	struct cgroup *parent = cgrp->parent;
-	DEFINE_WAIT(wait);
 	struct cgroup_event *event, *tmp;
 	struct cgroup_subsys *ss;
-	LIST_HEAD(tmp_list);
 
 	lockdep_assert_held(&d->d_inode->i_mutex);
 	lockdep_assert_held(&cgroup_mutex);
@@ -4935,17 +4823,17 @@ void cgroup_post_fork(struct task_struct *child)
 	 * and addition to css_set.
 	 */
 	if (need_forkexit_callback) {
-		for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
+		/*
+		 * fork/exit callbacks are supported only for builtin
+		 * subsystems, and the builtin section of the subsys
+		 * array is immutable, so we don't need to lock the
+		 * subsys array here. On the other hand, modular section
+		 * of the array can be freed at module unload, so we
+		 * can't touch that.
+		 */
+		for (i = 0; i < CGROUP_BUILTIN_SUBSYS_COUNT; i++) {
 			struct cgroup_subsys *ss = subsys[i];
 
-			/*
-			 * fork/exit callbacks are supported only for
-			 * builtin subsystems and we don't need further
-			 * synchronization as they never go away.
-			 */
-			if (!ss || ss->module)
-				continue;
-
 			if (ss->fork)
 				ss->fork(child);
 		}
@@ -5010,13 +4898,13 @@ void cgroup_exit(struct task_struct *tsk, int run_callbacks)
 	tsk->cgroups = &init_css_set;
 
 	if (run_callbacks && need_forkexit_callback) {
-		for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
+		/*
+		 * fork/exit callbacks are supported only for builtin
+		 * subsystems, see cgroup_post_fork() for details.
+		 */
+		for (i = 0; i < CGROUP_BUILTIN_SUBSYS_COUNT; i++) {
 			struct cgroup_subsys *ss = subsys[i];
 
-			/* modular subsystems can't use callbacks */
-			if (!ss || ss->module)
-				continue;
-
 			if (ss->exit) {
 				struct cgroup *old_cgrp =
 					rcu_dereference_raw(cg->subsys[i])->cgroup;
@@ -5030,44 +4918,19 @@ void cgroup_exit(struct task_struct *tsk, int run_callbacks)
 	put_css_set_taskexit(cg);
 }
 
-/**
- * cgroup_is_descendant - see if @cgrp is a descendant of @task's cgrp
- * @cgrp: the cgroup in question
- * @task: the task in question
- *
- * See if @cgrp is a descendant of @task's cgroup in the appropriate
- * hierarchy.
- *
- * If we are sending in dummytop, then presumably we are creating
- * the top cgroup in the subsystem.
- *
- * Called only by the ns (nsproxy) cgroup.
- */
-int cgroup_is_descendant(const struct cgroup *cgrp, struct task_struct *task)
-{
-	int ret;
-	struct cgroup *target;
-
-	if (cgrp == dummytop)
-		return 1;
-
-	target = task_cgroup_from_root(task, cgrp->root);
-	while (cgrp != target && cgrp!= cgrp->top_cgroup)
-		cgrp = cgrp->parent;
-	ret = (cgrp == target);
-	return ret;
-}
-
 static void check_for_release(struct cgroup *cgrp)
 {
 	/* All of these checks rely on RCU to keep the cgroup
 	 * structure alive */
-	if (cgroup_is_releasable(cgrp) && !atomic_read(&cgrp->count)
-	    && list_empty(&cgrp->children) && !cgroup_has_css_refs(cgrp)) {
-		/* Control Group is currently removeable. If it's not
+	if (cgroup_is_releasable(cgrp) &&
+	    !atomic_read(&cgrp->count) && list_empty(&cgrp->children)) {
+		/*
+		 * Control Group is currently removeable. If it's not
 		 * already queued for a userspace notification, queue
-		 * it now */
+		 * it now
+		 */
 		int need_schedule_work = 0;
+
 		raw_spin_lock(&release_list_lock);
 		if (!cgroup_is_removed(cgrp) &&
 		    list_empty(&cgrp->release_list)) {
@@ -5100,24 +4963,11 @@ EXPORT_SYMBOL_GPL(__css_tryget);
 /* Caller must verify that the css is not for root cgroup */
 void __css_put(struct cgroup_subsys_state *css)
 {
-	struct cgroup *cgrp = css->cgroup;
 	int v;
 
-	rcu_read_lock();
 	v = css_unbias_refcnt(atomic_dec_return(&css->refcnt));
-
-	switch (v) {
-	case 1:
-		if (notify_on_release(cgrp)) {
-			set_bit(CGRP_RELEASABLE, &cgrp->flags);
-			check_for_release(cgrp);
-		}
-		break;
-	case 0:
+	if (v == 0)
 		schedule_work(&css->dput_work);
-		break;
-	}
-	rcu_read_unlock();
 }
 EXPORT_SYMBOL_GPL(__css_put);
 
@@ -5416,55 +5266,6 @@ struct cgroup_subsys_state *css_lookup(struct cgroup_subsys *ss, int id)
 }
 EXPORT_SYMBOL_GPL(css_lookup);
 
-/**
- * css_get_next - lookup next cgroup under specified hierarchy.
- * @ss: pointer to subsystem
- * @id: current position of iteration.
- * @root: pointer to css. search tree under this.
- * @foundid: position of found object.
- *
- * Search next css under the specified hierarchy of rootid. Calling under
- * rcu_read_lock() is necessary. Returns NULL if it reaches the end.
- */
-struct cgroup_subsys_state *
-css_get_next(struct cgroup_subsys *ss, int id,
-	     struct cgroup_subsys_state *root, int *foundid)
-{
-	struct cgroup_subsys_state *ret = NULL;
-	struct css_id *tmp;
-	int tmpid;
-	int rootid = css_id(root);
-	int depth = css_depth(root);
-
-	if (!rootid)
-		return NULL;
-
-	BUG_ON(!ss->use_id);
-	WARN_ON_ONCE(!rcu_read_lock_held());
-
-	/* fill start point for scan */
-	tmpid = id;
-	while (1) {
-		/*
-		 * scan next entry from bitmap(tree), tmpid is updated after
-		 * idr_get_next().
-		 */
-		tmp = idr_get_next(&ss->idr, &tmpid);
-		if (!tmp)
-			break;
-		if (tmp->depth >= depth && tmp->stack[depth] == rootid) {
-			ret = rcu_dereference(tmp->css);
-			if (ret) {
-				*foundid = tmpid;
-				break;
-			}
-		}
-		/* continue to scan from next id */
-		tmpid = tmpid + 1;
-	}
-	return ret;
-}
-
 /*
  * get corresponding css from file open on cgroupfs directory
  */
diff --git a/kernel/compat.c b/kernel/compat.c
index 19971d8..c5620d6 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -516,25 +516,6 @@ int put_compat_rusage(const struct rusage *r, struct compat_rusage __user *ru)
 	return 0;
 }
 
-asmlinkage long compat_sys_getrusage(int who, struct compat_rusage __user *ru)
-{
-	struct rusage r;
-	int ret;
-	mm_segment_t old_fs = get_fs();
-
-	set_fs(KERNEL_DS);
-	ret = sys_getrusage(who, (struct rusage __user *) &r);
-	set_fs(old_fs);
-
-	if (ret)
-		return ret;
-
-	if (put_compat_rusage(&r, ru))
-		return -EFAULT;
-
-	return 0;
-}
-
 COMPAT_SYSCALL_DEFINE4(wait4,
 	compat_pid_t, pid,
 	compat_uint_t __user *, stat_addr,
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index 4f9dfe4..f129b13 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -265,17 +265,6 @@ static DEFINE_MUTEX(cpuset_mutex);
 static DEFINE_MUTEX(callback_mutex);
 
 /*
- * cpuset_buffer_lock protects both the cpuset_name and cpuset_nodelist
- * buffers.  They are statically allocated to prevent using excess stack
- * when calling cpuset_print_task_mems_allowed().
- */
-#define CPUSET_NAME_LEN		(128)
-#define	CPUSET_NODELIST_LEN	(256)
-static char cpuset_name[CPUSET_NAME_LEN];
-static char cpuset_nodelist[CPUSET_NODELIST_LEN];
-static DEFINE_SPINLOCK(cpuset_buffer_lock);
-
-/*
  * CPU / memory hotplug is handled asynchronously.
  */
 static struct workqueue_struct *cpuset_propagate_hotplug_wq;
@@ -1388,16 +1377,16 @@ static int cpuset_can_attach(struct cgroup *cgrp, struct cgroup_taskset *tset)
 
 	cgroup_taskset_for_each(task, cgrp, tset) {
 		/*
-		 * Kthreads bound to specific cpus cannot be moved to a new
-		 * cpuset; we cannot change their cpu affinity and
-		 * isolating such threads by their set of allowed nodes is
-		 * unnecessary.  Thus, cpusets are not applicable for such
-		 * threads.  This prevents checking for success of
-		 * set_cpus_allowed_ptr() on all attached tasks before
-		 * cpus_allowed may be changed.
+		 * Kthreads which disallow setaffinity shouldn't be moved
+		 * to a new cpuset; we don't want to change their cpu
+		 * affinity and isolating such threads by their set of
+		 * allowed nodes is unnecessary.  Thus, cpusets are not
+		 * applicable for such threads.  This prevents checking for
+		 * success of set_cpus_allowed_ptr() on all attached tasks
+		 * before cpus_allowed may be changed.
 		 */
 		ret = -EINVAL;
-		if (task->flags & PF_THREAD_BOUND)
+		if (task->flags & PF_NO_SETAFFINITY)
 			goto out_unlock;
 		ret = security_task_setscheduler(task);
 		if (ret)
@@ -2019,7 +2008,7 @@ static void cpuset_do_move_task(struct task_struct *tsk,
 	struct cgroup *new_cgroup = scan->data;
 
 	cgroup_lock();
-	cgroup_attach_task(new_cgroup, tsk);
+	cgroup_attach_task(new_cgroup, tsk, false);
 	cgroup_unlock();
 }
 
@@ -2592,6 +2581,8 @@ int cpuset_mems_allowed_intersects(const struct task_struct *tsk1,
 	return nodes_intersects(tsk1->mems_allowed, tsk2->mems_allowed);
 }
 
+#define CPUSET_NODELIST_LEN	(256)
+
 /**
  * cpuset_print_task_mems_allowed - prints task's cpuset and mems_allowed
  * @task: pointer to task_struct of some task.
@@ -2602,25 +2593,22 @@ int cpuset_mems_allowed_intersects(const struct task_struct *tsk1,
  */
 void cpuset_print_task_mems_allowed(struct task_struct *tsk)
 {
-	struct dentry *dentry;
+	 /* Statically allocated to prevent using excess stack. */
+	static char cpuset_nodelist[CPUSET_NODELIST_LEN];
+	static DEFINE_SPINLOCK(cpuset_buffer_lock);
 
-	dentry = task_cs(tsk)->css.cgroup->dentry;
-	spin_lock(&cpuset_buffer_lock);
+	struct cgroup *cgrp = task_cs(tsk)->css.cgroup;
 
-	if (!dentry) {
-		strcpy(cpuset_name, "/");
-	} else {
-		spin_lock(&dentry->d_lock);
-		strlcpy(cpuset_name, (const char *)dentry->d_name.name,
-			CPUSET_NAME_LEN);
-		spin_unlock(&dentry->d_lock);
-	}
+	rcu_read_lock();
+	spin_lock(&cpuset_buffer_lock);
 
 	nodelist_scnprintf(cpuset_nodelist, CPUSET_NODELIST_LEN,
 			   tsk->mems_allowed);
 	printk(KERN_INFO "%s cpuset=%s mems_allowed=%s\n",
-	       tsk->comm, cpuset_name, cpuset_nodelist);
+	       tsk->comm, cgroup_name(cgrp), cpuset_nodelist);
+
 	spin_unlock(&cpuset_buffer_lock);
+	rcu_read_unlock();
 }
 
 /*
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 59412d0..4757941 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -37,6 +37,7 @@
 #include <linux/ftrace_event.h>
 #include <linux/hw_breakpoint.h>
 #include <linux/mm_types.h>
+#include <linux/cgroup.h>
 
 #include "internal.h"
 
@@ -234,6 +235,20 @@ static void perf_ctx_unlock(struct perf_cpu_context *cpuctx,
 #ifdef CONFIG_CGROUP_PERF
 
 /*
+ * perf_cgroup_info keeps track of time_enabled for a cgroup.
+ * This is a per-cpu dynamically allocated data structure.
+ */
+struct perf_cgroup_info {
+	u64				time;
+	u64				timestamp;
+};
+
+struct perf_cgroup {
+	struct cgroup_subsys_state	css;
+	struct perf_cgroup_info		*info;
+};
+
+/*
  * Must ensure cgroup is pinned (css_get) before calling
  * this function. In other words, we cannot call this function
  * if there is no cgroup event for the current CPU context.
diff --git a/kernel/exit.c b/kernel/exit.c
index 60bc027..af2eb3c 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -847,7 +847,7 @@ void do_exit(long code)
 		exit_io_context(tsk);
 
 	if (tsk->splice_pipe)
-		__free_pipe_info(tsk->splice_pipe);
+		free_pipe_info(tsk->splice_pipe);
 
 	if (tsk->task_frag.page)
 		put_page(tsk->task_frag.page);
@@ -1629,9 +1629,6 @@ SYSCALL_DEFINE5(waitid, int, which, pid_t, upid, struct siginfo __user *,
 	}
 
 	put_pid(pid);
-
-	/* avoid REGPARM breakage on x86: */
-	asmlinkage_protect(5, ret, which, upid, infop, options, ru);
 	return ret;
 }
 
@@ -1669,8 +1666,6 @@ SYSCALL_DEFINE4(wait4, pid_t, upid, int __user *, stat_addr,
 	ret = do_wait(&wo);
 	put_pid(pid);
 
-	/* avoid REGPARM breakage on x86: */
-	asmlinkage_protect(4, ret, upid, stat_addr, options, ru);
 	return ret;
 }
 
diff --git a/kernel/fork.c b/kernel/fork.c
index 1766d32..6fcc2e2 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -70,6 +70,7 @@
 #include <linux/khugepaged.h>
 #include <linux/signalfd.h>
 #include <linux/uprobes.h>
+#include <linux/aio.h>
 
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
@@ -364,8 +365,6 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm)
 	mm->locked_vm = 0;
 	mm->mmap = NULL;
 	mm->mmap_cache = NULL;
-	mm->free_area_cache = oldmm->mmap_base;
-	mm->cached_hole_size = ~0UL;
 	mm->map_count = 0;
 	cpumask_clear(mm_cpumask(mm));
 	mm->mm_rb = RB_ROOT;
@@ -539,8 +538,6 @@ static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p)
 	mm->nr_ptes = 0;
 	memset(&mm->rss_stat, 0, sizeof(mm->rss_stat));
 	spin_lock_init(&mm->page_table_lock);
-	mm->free_area_cache = TASK_UNMAPPED_BASE;
-	mm->cached_hole_size = ~0UL;
 	mm_init_aio(mm);
 	mm_init_owner(mm, p);
 
@@ -1233,7 +1230,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
 
 	p->utime = p->stime = p->gtime = 0;
 	p->utimescaled = p->stimescaled = 0;
-#ifndef CONFIG_VIRT_CPU_ACCOUNTING
+#ifndef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
 	p->prev_cputime.utime = p->prev_cputime.stime = 0;
 #endif
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN
@@ -1303,6 +1300,10 @@ static struct task_struct *copy_process(unsigned long clone_flags,
 	p->memcg_batch.do_batch = 0;
 	p->memcg_batch.memcg = NULL;
 #endif
+#ifdef CONFIG_BCACHE
+	p->sequential_io	= 0;
+	p->sequential_io_avg	= 0;
+#endif
 
 	/* Perform scheduler related setup. Assign this task to a CPU. */
 	sched_fork(p);
@@ -1677,10 +1678,7 @@ SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp,
 		 int, tls_val)
 #endif
 {
-	long ret = do_fork(clone_flags, newsp, 0, parent_tidptr, child_tidptr);
-	asmlinkage_protect(5, ret, clone_flags, newsp,
-			parent_tidptr, child_tidptr, tls_val);
-	return ret;
+	return do_fork(clone_flags, newsp, 0, parent_tidptr, child_tidptr);
 }
 #endif
 
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index cc47812..320a7aa 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -275,6 +275,10 @@ ktime_t ktime_add_ns(const ktime_t kt, u64 nsec)
 	} else {
 		unsigned long rem = do_div(nsec, NSEC_PER_SEC);
 
+		/* Make sure nsec fits into long */
+		if (unlikely(nsec > KTIME_SEC_MAX))
+			return (ktime_t){ .tv64 = KTIME_MAX };
+
 		tmp = ktime_set((long)nsec, rem);
 	}
 
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 96f3a1d..059a280 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -143,7 +143,10 @@ static unsigned int irq_domain_legacy_revmap(struct irq_domain *domain,
  * irq_domain_add_simple() - Allocate and register a simple irq_domain.
  * @of_node: pointer to interrupt controller's device tree node.
  * @size: total number of irqs in mapping
- * @first_irq: first number of irq block assigned to the domain
+ * @first_irq: first number of irq block assigned to the domain,
+ *	pass zero to assign irqs on-the-fly. This will result in a
+ *	linear IRQ domain so it is important to use irq_create_mapping()
+ *	for each used IRQ, especially when SPARSE_IRQ is enabled.
  * @ops: map/unmap domain callbacks
  * @host_data: Controller private data pointer
  *
diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c
index 397db02..d59ae37 100644
--- a/kernel/irq/proc.c
+++ b/kernel/irq/proc.c
@@ -76,7 +76,7 @@ static int irq_affinity_list_proc_show(struct seq_file *m, void *v)
 static ssize_t write_irq_affinity(int type, struct file *file,
 		const char __user *buffer, size_t count, loff_t *pos)
 {
-	unsigned int irq = (int)(long)PDE(file_inode(file))->data;
+	unsigned int irq = (int)(long)PDE_DATA(file_inode(file));
 	cpumask_var_t new_value;
 	int err;
 
@@ -131,17 +131,17 @@ static ssize_t irq_affinity_list_proc_write(struct file *file,
 
 static int irq_affinity_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, irq_affinity_proc_show, PDE(inode)->data);
+	return single_open(file, irq_affinity_proc_show, PDE_DATA(inode));
 }
 
 static int irq_affinity_list_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, irq_affinity_list_proc_show, PDE(inode)->data);
+	return single_open(file, irq_affinity_list_proc_show, PDE_DATA(inode));
 }
 
 static int irq_affinity_hint_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, irq_affinity_hint_proc_show, PDE(inode)->data);
+	return single_open(file, irq_affinity_hint_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations irq_affinity_proc_fops = {
@@ -212,7 +212,7 @@ out:
 
 static int default_affinity_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, default_affinity_show, PDE(inode)->data);
+	return single_open(file, default_affinity_show, PDE_DATA(inode));
 }
 
 static const struct file_operations default_affinity_proc_fops = {
@@ -233,7 +233,7 @@ static int irq_node_proc_show(struct seq_file *m, void *v)
 
 static int irq_node_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, irq_node_proc_show, PDE(inode)->data);
+	return single_open(file, irq_node_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations irq_node_proc_fops = {
@@ -256,7 +256,7 @@ static int irq_spurious_proc_show(struct seq_file *m, void *v)
 
 static int irq_spurious_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, irq_spurious_proc_show, PDE(inode)->data);
+	return single_open(file, irq_spurious_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations irq_spurious_proc_fops = {
diff --git a/kernel/kexec.c b/kernel/kexec.c
index bddd3d7..38f5fab 100644
--- a/kernel/kexec.c
+++ b/kernel/kexec.c
@@ -786,7 +786,7 @@ static int kimage_load_normal_segment(struct kimage *image,
 					 struct kexec_segment *segment)
 {
 	unsigned long maddr;
-	unsigned long ubytes, mbytes;
+	size_t ubytes, mbytes;
 	int result;
 	unsigned char __user *buf;
 
@@ -819,13 +819,9 @@ static int kimage_load_normal_segment(struct kimage *image,
 		/* Start with a clear page */
 		clear_page(ptr);
 		ptr += maddr & ~PAGE_MASK;
-		mchunk = PAGE_SIZE - (maddr & ~PAGE_MASK);
-		if (mchunk > mbytes)
-			mchunk = mbytes;
-
-		uchunk = mchunk;
-		if (uchunk > ubytes)
-			uchunk = ubytes;
+		mchunk = min_t(size_t, mbytes,
+				PAGE_SIZE - (maddr & ~PAGE_MASK));
+		uchunk = min(ubytes, mchunk);
 
 		result = copy_from_user(ptr, buf, uchunk);
 		kunmap(page);
@@ -850,7 +846,7 @@ static int kimage_load_crash_segment(struct kimage *image,
 	 * We do things a page at a time for the sake of kmap.
 	 */
 	unsigned long maddr;
-	unsigned long ubytes, mbytes;
+	size_t ubytes, mbytes;
 	int result;
 	unsigned char __user *buf;
 
@@ -871,13 +867,10 @@ static int kimage_load_crash_segment(struct kimage *image,
 		}
 		ptr = kmap(page);
 		ptr += maddr & ~PAGE_MASK;
-		mchunk = PAGE_SIZE - (maddr & ~PAGE_MASK);
-		if (mchunk > mbytes)
-			mchunk = mbytes;
-
-		uchunk = mchunk;
-		if (uchunk > ubytes) {
-			uchunk = ubytes;
+		mchunk = min_t(size_t, mbytes,
+				PAGE_SIZE - (maddr & ~PAGE_MASK));
+		uchunk = min(ubytes, mchunk);
+		if (mchunk > uchunk) {
 			/* Zero the trailing part of the page */
 			memset(ptr + uchunk, 0, mchunk - uchunk);
 		}
@@ -1118,12 +1111,8 @@ void __weak crash_free_reserved_phys_range(unsigned long begin,
 {
 	unsigned long addr;
 
-	for (addr = begin; addr < end; addr += PAGE_SIZE) {
-		ClearPageReserved(pfn_to_page(addr >> PAGE_SHIFT));
-		init_page_count(pfn_to_page(addr >> PAGE_SHIFT));
-		free_page((unsigned long)__va(addr));
-		totalram_pages++;
-	}
+	for (addr = begin; addr < end; addr += PAGE_SIZE)
+		free_reserved_page(pfn_to_page(addr >> PAGE_SHIFT));
 }
 
 int crash_shrink_memory(unsigned long new_size)
@@ -1452,14 +1441,13 @@ void vmcoreinfo_append_str(const char *fmt, ...)
 {
 	va_list args;
 	char buf[0x50];
-	int r;
+	size_t r;
 
 	va_start(args, fmt);
 	r = vsnprintf(buf, sizeof(buf), fmt, args);
 	va_end(args);
 
-	if (r + vmcoreinfo_size > vmcoreinfo_max_size)
-		r = vmcoreinfo_max_size - vmcoreinfo_size;
+	r = min(r, vmcoreinfo_max_size - vmcoreinfo_size);
 
 	memcpy(&vmcoreinfo_data[vmcoreinfo_size], buf, r);
 
@@ -1489,7 +1477,7 @@ static int __init crash_save_vmcoreinfo_init(void)
 	VMCOREINFO_SYMBOL(swapper_pg_dir);
 #endif
 	VMCOREINFO_SYMBOL(_stext);
-	VMCOREINFO_SYMBOL(vmlist);
+	VMCOREINFO_SYMBOL(vmap_area_list);
 
 #ifndef CONFIG_NEED_MULTIPLE_NODES
 	VMCOREINFO_SYMBOL(mem_map);
@@ -1527,7 +1515,8 @@ static int __init crash_save_vmcoreinfo_init(void)
 	VMCOREINFO_OFFSET(free_area, free_list);
 	VMCOREINFO_OFFSET(list_head, next);
 	VMCOREINFO_OFFSET(list_head, prev);
-	VMCOREINFO_OFFSET(vm_struct, addr);
+	VMCOREINFO_OFFSET(vmap_area, va_start);
+	VMCOREINFO_OFFSET(vmap_area, list);
 	VMCOREINFO_LENGTH(zone.free_area, MAX_ORDER);
 	log_buf_kexec_setup();
 	VMCOREINFO_LENGTH(free_area.free_list, MIGRATE_TYPES);
diff --git a/kernel/kmod.c b/kernel/kmod.c
index 56dd349..1296e72 100644
--- a/kernel/kmod.c
+++ b/kernel/kmod.c
@@ -77,6 +77,7 @@ static void free_modprobe_argv(struct subprocess_info *info)
 
 static int call_modprobe(char *module_name, int wait)
 {
+	struct subprocess_info *info;
 	static char *envp[] = {
 		"HOME=/",
 		"TERM=linux",
@@ -98,8 +99,15 @@ static int call_modprobe(char *module_name, int wait)
 	argv[3] = module_name;	/* check free_modprobe_argv() */
 	argv[4] = NULL;
 
-	return call_usermodehelper_fns(modprobe_path, argv, envp,
-		wait | UMH_KILLABLE, NULL, free_modprobe_argv, NULL);
+	info = call_usermodehelper_setup(modprobe_path, argv, envp, GFP_KERNEL,
+					 NULL, free_modprobe_argv, NULL);
+	if (!info)
+		goto free_module_name;
+
+	return call_usermodehelper_exec(info, wait | UMH_KILLABLE);
+
+free_module_name:
+	kfree(module_name);
 free_argv:
 	kfree(argv);
 out:
@@ -502,14 +510,28 @@ static void helper_unlock(void)
  * @argv: arg vector for process
  * @envp: environment for process
  * @gfp_mask: gfp mask for memory allocation
+ * @cleanup: a cleanup function
+ * @init: an init function
+ * @data: arbitrary context sensitive data
  *
  * Returns either %NULL on allocation failure, or a subprocess_info
  * structure.  This should be passed to call_usermodehelper_exec to
  * exec the process and free the structure.
+ *
+ * The init function is used to customize the helper process prior to
+ * exec.  A non-zero return code causes the process to error out, exit,
+ * and return the failure to the calling process
+ *
+ * The cleanup function is just before ethe subprocess_info is about to
+ * be freed.  This can be used for freeing the argv and envp.  The
+ * Function must be runnable in either a process context or the
+ * context in which call_usermodehelper_exec is called.
  */
-static
 struct subprocess_info *call_usermodehelper_setup(char *path, char **argv,
-						  char **envp, gfp_t gfp_mask)
+		char **envp, gfp_t gfp_mask,
+		int (*init)(struct subprocess_info *info, struct cred *new),
+		void (*cleanup)(struct subprocess_info *info),
+		void *data)
 {
 	struct subprocess_info *sub_info;
 	sub_info = kzalloc(sizeof(struct subprocess_info), gfp_mask);
@@ -520,50 +542,27 @@ struct subprocess_info *call_usermodehelper_setup(char *path, char **argv,
 	sub_info->path = path;
 	sub_info->argv = argv;
 	sub_info->envp = envp;
+
+	sub_info->cleanup = cleanup;
+	sub_info->init = init;
+	sub_info->data = data;
   out:
 	return sub_info;
 }
-
-/**
- * call_usermodehelper_setfns - set a cleanup/init function
- * @info: a subprocess_info returned by call_usermodehelper_setup
- * @cleanup: a cleanup function
- * @init: an init function
- * @data: arbitrary context sensitive data
- *
- * The init function is used to customize the helper process prior to
- * exec.  A non-zero return code causes the process to error out, exit,
- * and return the failure to the calling process
- *
- * The cleanup function is just before ethe subprocess_info is about to
- * be freed.  This can be used for freeing the argv and envp.  The
- * Function must be runnable in either a process context or the
- * context in which call_usermodehelper_exec is called.
- */
-static
-void call_usermodehelper_setfns(struct subprocess_info *info,
-		    int (*init)(struct subprocess_info *info, struct cred *new),
-		    void (*cleanup)(struct subprocess_info *info),
-		    void *data)
-{
-	info->cleanup = cleanup;
-	info->init = init;
-	info->data = data;
-}
+EXPORT_SYMBOL(call_usermodehelper_setup);
 
 /**
  * call_usermodehelper_exec - start a usermode application
  * @sub_info: information about the subprocessa
  * @wait: wait for the application to finish and return status.
- *        when -1 don't wait at all, but you get no useful error back when
- *        the program couldn't be exec'ed. This makes it safe to call
+ *        when UMH_NO_WAIT don't wait at all, but you get no useful error back
+ *        when the program couldn't be exec'ed. This makes it safe to call
  *        from interrupt context.
  *
  * Runs a user-space application.  The application is started
  * asynchronously if wait is not set, and runs as a child of keventd.
  * (ie. it runs with full root capabilities).
  */
-static
 int call_usermodehelper_exec(struct subprocess_info *sub_info, int wait)
 {
 	DECLARE_COMPLETION_ONSTACK(done);
@@ -615,31 +614,34 @@ unlock:
 	helper_unlock();
 	return retval;
 }
+EXPORT_SYMBOL(call_usermodehelper_exec);
 
-/*
- * call_usermodehelper_fns() will not run the caller-provided cleanup function
- * if a memory allocation failure is experienced.  So the caller might need to
- * check the call_usermodehelper_fns() return value: if it is -ENOMEM, perform
- * the necessaary cleanup within the caller.
+/**
+ * call_usermodehelper() - prepare and start a usermode application
+ * @path: path to usermode executable
+ * @argv: arg vector for process
+ * @envp: environment for process
+ * @wait: wait for the application to finish and return status.
+ *        when UMH_NO_WAIT don't wait at all, but you get no useful error back
+ *        when the program couldn't be exec'ed. This makes it safe to call
+ *        from interrupt context.
+ *
+ * This function is the equivalent to use call_usermodehelper_setup() and
+ * call_usermodehelper_exec().
  */
-int call_usermodehelper_fns(
-	char *path, char **argv, char **envp, int wait,
-	int (*init)(struct subprocess_info *info, struct cred *new),
-	void (*cleanup)(struct subprocess_info *), void *data)
+int call_usermodehelper(char *path, char **argv, char **envp, int wait)
 {
 	struct subprocess_info *info;
 	gfp_t gfp_mask = (wait == UMH_NO_WAIT) ? GFP_ATOMIC : GFP_KERNEL;
 
-	info = call_usermodehelper_setup(path, argv, envp, gfp_mask);
-
+	info = call_usermodehelper_setup(path, argv, envp, gfp_mask,
+					 NULL, NULL, NULL);
 	if (info == NULL)
 		return -ENOMEM;
 
-	call_usermodehelper_setfns(info, init, cleanup, data);
-
 	return call_usermodehelper_exec(info, wait);
 }
-EXPORT_SYMBOL(call_usermodehelper_fns);
+EXPORT_SYMBOL(call_usermodehelper);
 
 static int proc_cap_handler(struct ctl_table *table, int write,
 			 void __user *buffer, size_t *lenp, loff_t *ppos)
diff --git a/kernel/kthread.c b/kernel/kthread.c
index 691dc2e..b9db231 100644
--- a/kernel/kthread.c
+++ b/kernel/kthread.c
@@ -52,8 +52,21 @@ enum KTHREAD_BITS {
 	KTHREAD_IS_PARKED,
 };
 
-#define to_kthread(tsk)	\
-	container_of((tsk)->vfork_done, struct kthread, exited)
+#define __to_kthread(vfork)	\
+	container_of(vfork, struct kthread, exited)
+
+static inline struct kthread *to_kthread(struct task_struct *k)
+{
+	return __to_kthread(k->vfork_done);
+}
+
+static struct kthread *to_live_kthread(struct task_struct *k)
+{
+	struct completion *vfork = ACCESS_ONCE(k->vfork_done);
+	if (likely(vfork))
+		return __to_kthread(vfork);
+	return NULL;
+}
 
 /**
  * kthread_should_stop - should this kthread return now?
@@ -260,7 +273,7 @@ static void __kthread_bind(struct task_struct *p, unsigned int cpu)
 {
 	/* It's safe because the task is inactive. */
 	do_set_cpus_allowed(p, cpumask_of(cpu));
-	p->flags |= PF_THREAD_BOUND;
+	p->flags |= PF_NO_SETAFFINITY;
 }
 
 /**
@@ -311,19 +324,6 @@ struct task_struct *kthread_create_on_cpu(int (*threadfn)(void *data),
 	return p;
 }
 
-static struct kthread *task_get_live_kthread(struct task_struct *k)
-{
-	struct kthread *kthread;
-
-	get_task_struct(k);
-	kthread = to_kthread(k);
-	/* It might have exited */
-	barrier();
-	if (k->vfork_done != NULL)
-		return kthread;
-	return NULL;
-}
-
 /**
  * kthread_unpark - unpark a thread created by kthread_create().
  * @k:		thread created by kthread_create().
@@ -334,7 +334,7 @@ static struct kthread *task_get_live_kthread(struct task_struct *k)
  */
 void kthread_unpark(struct task_struct *k)
 {
-	struct kthread *kthread = task_get_live_kthread(k);
+	struct kthread *kthread = to_live_kthread(k);
 
 	if (kthread) {
 		clear_bit(KTHREAD_SHOULD_PARK, &kthread->flags);
@@ -350,7 +350,6 @@ void kthread_unpark(struct task_struct *k)
 			wake_up_process(k);
 		}
 	}
-	put_task_struct(k);
 }
 
 /**
@@ -367,7 +366,7 @@ void kthread_unpark(struct task_struct *k)
  */
 int kthread_park(struct task_struct *k)
 {
-	struct kthread *kthread = task_get_live_kthread(k);
+	struct kthread *kthread = to_live_kthread(k);
 	int ret = -ENOSYS;
 
 	if (kthread) {
@@ -380,7 +379,6 @@ int kthread_park(struct task_struct *k)
 		}
 		ret = 0;
 	}
-	put_task_struct(k);
 	return ret;
 }
 
@@ -401,10 +399,13 @@ int kthread_park(struct task_struct *k)
  */
 int kthread_stop(struct task_struct *k)
 {
-	struct kthread *kthread = task_get_live_kthread(k);
+	struct kthread *kthread;
 	int ret;
 
 	trace_sched_kthread_stop(k);
+
+	get_task_struct(k);
+	kthread = to_live_kthread(k);
 	if (kthread) {
 		set_bit(KTHREAD_SHOULD_STOP, &kthread->flags);
 		clear_bit(KTHREAD_SHOULD_PARK, &kthread->flags);
@@ -412,10 +413,9 @@ int kthread_stop(struct task_struct *k)
 		wait_for_completion(&kthread->exited);
 	}
 	ret = k->exit_code;
-
 	put_task_struct(k);
-	trace_sched_kthread_stop_ret(ret);
 
+	trace_sched_kthread_stop_ret(ret);
 	return ret;
 }
 EXPORT_SYMBOL(kthread_stop);
diff --git a/kernel/lglock.c b/kernel/lglock.c
index 6535a66..86ae2ae 100644
--- a/kernel/lglock.c
+++ b/kernel/lglock.c
@@ -21,7 +21,7 @@ void lg_local_lock(struct lglock *lg)
 	arch_spinlock_t *lock;
 
 	preempt_disable();
-	rwlock_acquire_read(&lg->lock_dep_map, 0, 0, _RET_IP_);
+	lock_acquire_shared(&lg->lock_dep_map, 0, 0, NULL, _RET_IP_);
 	lock = this_cpu_ptr(lg->lock);
 	arch_spin_lock(lock);
 }
@@ -31,7 +31,7 @@ void lg_local_unlock(struct lglock *lg)
 {
 	arch_spinlock_t *lock;
 
-	rwlock_release(&lg->lock_dep_map, 1, _RET_IP_);
+	lock_release(&lg->lock_dep_map, 1, _RET_IP_);
 	lock = this_cpu_ptr(lg->lock);
 	arch_spin_unlock(lock);
 	preempt_enable();
@@ -43,7 +43,7 @@ void lg_local_lock_cpu(struct lglock *lg, int cpu)
 	arch_spinlock_t *lock;
 
 	preempt_disable();
-	rwlock_acquire_read(&lg->lock_dep_map, 0, 0, _RET_IP_);
+	lock_acquire_shared(&lg->lock_dep_map, 0, 0, NULL, _RET_IP_);
 	lock = per_cpu_ptr(lg->lock, cpu);
 	arch_spin_lock(lock);
 }
@@ -53,7 +53,7 @@ void lg_local_unlock_cpu(struct lglock *lg, int cpu)
 {
 	arch_spinlock_t *lock;
 
-	rwlock_release(&lg->lock_dep_map, 1, _RET_IP_);
+	lock_release(&lg->lock_dep_map, 1, _RET_IP_);
 	lock = per_cpu_ptr(lg->lock, cpu);
 	arch_spin_unlock(lock);
 	preempt_enable();
@@ -65,7 +65,7 @@ void lg_global_lock(struct lglock *lg)
 	int i;
 
 	preempt_disable();
-	rwlock_acquire(&lg->lock_dep_map, 0, 0, _RET_IP_);
+	lock_acquire_exclusive(&lg->lock_dep_map, 0, 0, NULL, _RET_IP_);
 	for_each_possible_cpu(i) {
 		arch_spinlock_t *lock;
 		lock = per_cpu_ptr(lg->lock, i);
@@ -78,7 +78,7 @@ void lg_global_unlock(struct lglock *lg)
 {
 	int i;
 
-	rwlock_release(&lg->lock_dep_map, 1, _RET_IP_);
+	lock_release(&lg->lock_dep_map, 1, _RET_IP_);
 	for_each_possible_cpu(i) {
 		arch_spinlock_t *lock;
 		lock = per_cpu_ptr(lg->lock, i);
diff --git a/kernel/lockdep.c b/kernel/lockdep.c
index 8a0efac..8b3dbe0 100644
--- a/kernel/lockdep.c
+++ b/kernel/lockdep.c
@@ -2997,6 +2997,7 @@ void lockdep_init_map(struct lockdep_map *lock, const char *name,
 EXPORT_SYMBOL_GPL(lockdep_init_map);
 
 struct lock_class_key __lockdep_no_validate__;
+EXPORT_SYMBOL_GPL(__lockdep_no_validate__);
 
 static int
 print_lock_nested_lock_not_held(struct task_struct *curr,
diff --git a/kernel/modsign_certificate.S b/kernel/modsign_certificate.S
index 246b4c6..4a9a86d 100644
--- a/kernel/modsign_certificate.S
+++ b/kernel/modsign_certificate.S
@@ -1,15 +1,8 @@
-/* SYMBOL_PREFIX defined on commandline from CONFIG_SYMBOL_PREFIX */
-#ifndef SYMBOL_PREFIX
-#define ASM_SYMBOL(sym) sym
-#else
-#define PASTE2(x,y) x##y
-#define PASTE(x,y) PASTE2(x,y)
-#define ASM_SYMBOL(sym) PASTE(SYMBOL_PREFIX, sym)
-#endif
+#include <linux/export.h>
 
 #define GLOBAL(name)	\
-	.globl ASM_SYMBOL(name);	\
-	ASM_SYMBOL(name):
+	.globl VMLINUX_SYMBOL(name);	\
+	VMLINUX_SYMBOL(name):
 
 	.section ".init.data","aw"
 
diff --git a/kernel/module.c b/kernel/module.c
index 0925c9a..3c2c72d 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -1209,10 +1209,11 @@ static inline int check_modstruct_version(Elf_Shdr *sechdrs,
 
 	/* Since this should be found in kernel (which can't be removed),
 	 * no locking is necessary. */
-	if (!find_symbol(MODULE_SYMBOL_PREFIX "module_layout", NULL,
+	if (!find_symbol(VMLINUX_SYMBOL_STR(module_layout), NULL,
 			 &crc, true, false))
 		BUG();
-	return check_version(sechdrs, versindex, "module_layout", mod, crc,
+	return check_version(sechdrs, versindex,
+			     VMLINUX_SYMBOL_STR(module_layout), mod, crc,
 			     NULL);
 }
 
diff --git a/kernel/params.c b/kernel/params.c
index ed35345..53b958f 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -613,10 +613,13 @@ static __modinit int add_sysfs_param(struct module_kobject *mk,
 		       sizeof(*mk->mp) + sizeof(mk->mp->attrs[0]) * (num+1),
 		       GFP_KERNEL);
 	if (!new) {
-		kfree(mk->mp);
+		kfree(attrs);
 		err = -ENOMEM;
 		goto fail;
 	}
+	/* Despite looking like the typical realloc() bug, this is safe.
+	 * We *want* the old 'attrs' to be freed either way, and we'll store
+	 * the new one in the success case. */
 	attrs = krealloc(attrs, sizeof(new->grp.attrs[0])*(num+2), GFP_KERNEL);
 	if (!attrs) {
 		err = -ENOMEM;
diff --git a/kernel/pid.c b/kernel/pid.c
index 047dc62..6283d64 100644
--- a/kernel/pid.c
+++ b/kernel/pid.c
@@ -51,9 +51,6 @@ int pid_max = PID_MAX_DEFAULT;
 int pid_max_min = RESERVED_PIDS + 1;
 int pid_max_max = PID_MAX_LIMIT;
 
-#define BITS_PER_PAGE		(PAGE_SIZE*8)
-#define BITS_PER_PAGE_MASK	(BITS_PER_PAGE-1)
-
 static inline int mk_pid(struct pid_namespace *pid_ns,
 		struct pidmap *map, int off)
 {
@@ -183,15 +180,19 @@ static int alloc_pidmap(struct pid_namespace *pid_ns)
 				break;
 		}
 		if (likely(atomic_read(&map->nr_free))) {
-			do {
+			for ( ; ; ) {
 				if (!test_and_set_bit(offset, map->page)) {
 					atomic_dec(&map->nr_free);
 					set_last_pid(pid_ns, last, pid);
 					return pid;
 				}
 				offset = find_next_offset(map, offset);
+				if (offset >= BITS_PER_PAGE)
+					break;
 				pid = mk_pid(pid_ns, map, offset);
-			} while (offset < BITS_PER_PAGE && pid < pid_max);
+				if (pid >= pid_max)
+					break;
+			}
 		}
 		if (map < &pid_ns->pidmap[(pid_max-1)/BITS_PER_PAGE]) {
 			++map;
diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c
index bea15bd..69473c4 100644
--- a/kernel/pid_namespace.c
+++ b/kernel/pid_namespace.c
@@ -19,8 +19,6 @@
 #include <linux/reboot.h>
 #include <linux/export.h>
 
-#define BITS_PER_PAGE		(PAGE_SIZE*8)
-
 struct pid_cache {
 	int nr_ids;
 	char name[16];
diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c
index 8fd709c..edf94b6 100644
--- a/kernel/posix-cpu-timers.c
+++ b/kernel/posix-cpu-timers.c
@@ -49,59 +49,28 @@ static int check_clock(const clockid_t which_clock)
 	return error;
 }
 
-static inline union cpu_time_count
+static inline unsigned long long
 timespec_to_sample(const clockid_t which_clock, const struct timespec *tp)
 {
-	union cpu_time_count ret;
-	ret.sched = 0;		/* high half always zero when .cpu used */
+	unsigned long long ret;
+
+	ret = 0;		/* high half always zero when .cpu used */
 	if (CPUCLOCK_WHICH(which_clock) == CPUCLOCK_SCHED) {
-		ret.sched = (unsigned long long)tp->tv_sec * NSEC_PER_SEC + tp->tv_nsec;
+		ret = (unsigned long long)tp->tv_sec * NSEC_PER_SEC + tp->tv_nsec;
 	} else {
-		ret.cpu = timespec_to_cputime(tp);
+		ret = cputime_to_expires(timespec_to_cputime(tp));
 	}
 	return ret;
 }
 
 static void sample_to_timespec(const clockid_t which_clock,
-			       union cpu_time_count cpu,
+			       unsigned long long expires,
 			       struct timespec *tp)
 {
 	if (CPUCLOCK_WHICH(which_clock) == CPUCLOCK_SCHED)
-		*tp = ns_to_timespec(cpu.sched);
+		*tp = ns_to_timespec(expires);
 	else
-		cputime_to_timespec(cpu.cpu, tp);
-}
-
-static inline int cpu_time_before(const clockid_t which_clock,
-				  union cpu_time_count now,
-				  union cpu_time_count then)
-{
-	if (CPUCLOCK_WHICH(which_clock) == CPUCLOCK_SCHED) {
-		return now.sched < then.sched;
-	}  else {
-		return now.cpu < then.cpu;
-	}
-}
-static inline void cpu_time_add(const clockid_t which_clock,
-				union cpu_time_count *acc,
-			        union cpu_time_count val)
-{
-	if (CPUCLOCK_WHICH(which_clock) == CPUCLOCK_SCHED) {
-		acc->sched += val.sched;
-	}  else {
-		acc->cpu += val.cpu;
-	}
-}
-static inline union cpu_time_count cpu_time_sub(const clockid_t which_clock,
-						union cpu_time_count a,
-						union cpu_time_count b)
-{
-	if (CPUCLOCK_WHICH(which_clock) == CPUCLOCK_SCHED) {
-		a.sched -= b.sched;
-	}  else {
-		a.cpu -= b.cpu;
-	}
-	return a;
+		cputime_to_timespec((__force cputime_t)expires, tp);
 }
 
 /*
@@ -109,65 +78,49 @@ static inline union cpu_time_count cpu_time_sub(const clockid_t which_clock,
  * given the current clock sample.
  */
 static void bump_cpu_timer(struct k_itimer *timer,
-				  union cpu_time_count now)
+			   unsigned long long now)
 {
 	int i;
+	unsigned long long delta, incr;
 
-	if (timer->it.cpu.incr.sched == 0)
+	if (timer->it.cpu.incr == 0)
 		return;
 
-	if (CPUCLOCK_WHICH(timer->it_clock) == CPUCLOCK_SCHED) {
-		unsigned long long delta, incr;
+	if (now < timer->it.cpu.expires)
+		return;
 
-		if (now.sched < timer->it.cpu.expires.sched)
-			return;
-		incr = timer->it.cpu.incr.sched;
-		delta = now.sched + incr - timer->it.cpu.expires.sched;
-		/* Don't use (incr*2 < delta), incr*2 might overflow. */
-		for (i = 0; incr < delta - incr; i++)
-			incr = incr << 1;
-		for (; i >= 0; incr >>= 1, i--) {
-			if (delta < incr)
-				continue;
-			timer->it.cpu.expires.sched += incr;
-			timer->it_overrun += 1 << i;
-			delta -= incr;
-		}
-	} else {
-		cputime_t delta, incr;
+	incr = timer->it.cpu.incr;
+	delta = now + incr - timer->it.cpu.expires;
 
-		if (now.cpu < timer->it.cpu.expires.cpu)
-			return;
-		incr = timer->it.cpu.incr.cpu;
-		delta = now.cpu + incr - timer->it.cpu.expires.cpu;
-		/* Don't use (incr*2 < delta), incr*2 might overflow. */
-		for (i = 0; incr < delta - incr; i++)
-			     incr += incr;
-		for (; i >= 0; incr = incr >> 1, i--) {
-			if (delta < incr)
-				continue;
-			timer->it.cpu.expires.cpu += incr;
-			timer->it_overrun += 1 << i;
-			delta -= incr;
-		}
+	/* Don't use (incr*2 < delta), incr*2 might overflow. */
+	for (i = 0; incr < delta - incr; i++)
+		incr = incr << 1;
+
+	for (; i >= 0; incr >>= 1, i--) {
+		if (delta < incr)
+			continue;
+
+		timer->it.cpu.expires += incr;
+		timer->it_overrun += 1 << i;
+		delta -= incr;
 	}
 }
 
-static inline cputime_t prof_ticks(struct task_struct *p)
+static inline unsigned long long prof_ticks(struct task_struct *p)
 {
 	cputime_t utime, stime;
 
 	task_cputime(p, &utime, &stime);
 
-	return utime + stime;
+	return cputime_to_expires(utime + stime);
 }
-static inline cputime_t virt_ticks(struct task_struct *p)
+static inline unsigned long long virt_ticks(struct task_struct *p)
 {
 	cputime_t utime;
 
 	task_cputime(p, &utime, NULL);
 
-	return utime;
+	return cputime_to_expires(utime);
 }
 
 static int
@@ -208,19 +161,19 @@ posix_cpu_clock_set(const clockid_t which_clock, const struct timespec *tp)
  * Sample a per-thread clock for the given task.
  */
 static int cpu_clock_sample(const clockid_t which_clock, struct task_struct *p,
-			    union cpu_time_count *cpu)
+			    unsigned long long *sample)
 {
 	switch (CPUCLOCK_WHICH(which_clock)) {
 	default:
 		return -EINVAL;
 	case CPUCLOCK_PROF:
-		cpu->cpu = prof_ticks(p);
+		*sample = prof_ticks(p);
 		break;
 	case CPUCLOCK_VIRT:
-		cpu->cpu = virt_ticks(p);
+		*sample = virt_ticks(p);
 		break;
 	case CPUCLOCK_SCHED:
-		cpu->sched = task_sched_runtime(p);
+		*sample = task_sched_runtime(p);
 		break;
 	}
 	return 0;
@@ -267,7 +220,7 @@ void thread_group_cputimer(struct task_struct *tsk, struct task_cputime *times)
  */
 static int cpu_clock_sample_group(const clockid_t which_clock,
 				  struct task_struct *p,
-				  union cpu_time_count *cpu)
+				  unsigned long long *sample)
 {
 	struct task_cputime cputime;
 
@@ -276,15 +229,15 @@ static int cpu_clock_sample_group(const clockid_t which_clock,
 		return -EINVAL;
 	case CPUCLOCK_PROF:
 		thread_group_cputime(p, &cputime);
-		cpu->cpu = cputime.utime + cputime.stime;
+		*sample = cputime_to_expires(cputime.utime + cputime.stime);
 		break;
 	case CPUCLOCK_VIRT:
 		thread_group_cputime(p, &cputime);
-		cpu->cpu = cputime.utime;
+		*sample = cputime_to_expires(cputime.utime);
 		break;
 	case CPUCLOCK_SCHED:
 		thread_group_cputime(p, &cputime);
-		cpu->sched = cputime.sum_exec_runtime;
+		*sample = cputime.sum_exec_runtime;
 		break;
 	}
 	return 0;
@@ -295,7 +248,7 @@ static int posix_cpu_clock_get(const clockid_t which_clock, struct timespec *tp)
 {
 	const pid_t pid = CPUCLOCK_PID(which_clock);
 	int error = -EINVAL;
-	union cpu_time_count rtn;
+	unsigned long long rtn;
 
 	if (pid == 0) {
 		/*
@@ -429,6 +382,21 @@ static int posix_cpu_timer_del(struct k_itimer *timer)
 	return ret;
 }
 
+static void cleanup_timers_list(struct list_head *head,
+				unsigned long long curr)
+{
+	struct cpu_timer_list *timer, *next;
+
+	list_for_each_entry_safe(timer, next, head, entry) {
+		list_del_init(&timer->entry);
+		if (timer->expires < curr) {
+			timer->expires = 0;
+		} else {
+			timer->expires -= curr;
+		}
+	}
+}
+
 /*
  * Clean out CPU timers still ticking when a thread exited.  The task
  * pointer is cleared, and the expiry time is replaced with the residual
@@ -439,37 +407,12 @@ static void cleanup_timers(struct list_head *head,
 			   cputime_t utime, cputime_t stime,
 			   unsigned long long sum_exec_runtime)
 {
-	struct cpu_timer_list *timer, *next;
-	cputime_t ptime = utime + stime;
-
-	list_for_each_entry_safe(timer, next, head, entry) {
-		list_del_init(&timer->entry);
-		if (timer->expires.cpu < ptime) {
-			timer->expires.cpu = 0;
-		} else {
-			timer->expires.cpu -= ptime;
-		}
-	}
 
-	++head;
-	list_for_each_entry_safe(timer, next, head, entry) {
-		list_del_init(&timer->entry);
-		if (timer->expires.cpu < utime) {
-			timer->expires.cpu = 0;
-		} else {
-			timer->expires.cpu -= utime;
-		}
-	}
+	cputime_t ptime = utime + stime;
 
-	++head;
-	list_for_each_entry_safe(timer, next, head, entry) {
-		list_del_init(&timer->entry);
-		if (timer->expires.sched < sum_exec_runtime) {
-			timer->expires.sched = 0;
-		} else {
-			timer->expires.sched -= sum_exec_runtime;
-		}
-	}
+	cleanup_timers_list(head, cputime_to_expires(ptime));
+	cleanup_timers_list(++head, cputime_to_expires(utime));
+	cleanup_timers_list(++head, sum_exec_runtime);
 }
 
 /*
@@ -499,7 +442,7 @@ void posix_cpu_timers_exit_group(struct task_struct *tsk)
 		       tsk->se.sum_exec_runtime + sig->sum_sched_runtime);
 }
 
-static void clear_dead_task(struct k_itimer *timer, union cpu_time_count now)
+static void clear_dead_task(struct k_itimer *timer, unsigned long long now)
 {
 	/*
 	 * That's all for this thread or process.
@@ -507,9 +450,7 @@ static void clear_dead_task(struct k_itimer *timer, union cpu_time_count now)
 	 */
 	put_task_struct(timer->it.cpu.task);
 	timer->it.cpu.task = NULL;
-	timer->it.cpu.expires = cpu_time_sub(timer->it_clock,
-					     timer->it.cpu.expires,
-					     now);
+	timer->it.cpu.expires -= now;
 }
 
 static inline int expires_gt(cputime_t expires, cputime_t new_exp)
@@ -541,14 +482,14 @@ static void arm_timer(struct k_itimer *timer)
 
 	listpos = head;
 	list_for_each_entry(next, head, entry) {
-		if (cpu_time_before(timer->it_clock, nt->expires, next->expires))
+		if (nt->expires < next->expires)
 			break;
 		listpos = &next->entry;
 	}
 	list_add(&nt->entry, listpos);
 
 	if (listpos == head) {
-		union cpu_time_count *exp = &nt->expires;
+		unsigned long long exp = nt->expires;
 
 		/*
 		 * We are the new earliest-expiring POSIX 1.b timer, hence
@@ -559,17 +500,17 @@ static void arm_timer(struct k_itimer *timer)
 
 		switch (CPUCLOCK_WHICH(timer->it_clock)) {
 		case CPUCLOCK_PROF:
-			if (expires_gt(cputime_expires->prof_exp, exp->cpu))
-				cputime_expires->prof_exp = exp->cpu;
+			if (expires_gt(cputime_expires->prof_exp, expires_to_cputime(exp)))
+				cputime_expires->prof_exp = expires_to_cputime(exp);
 			break;
 		case CPUCLOCK_VIRT:
-			if (expires_gt(cputime_expires->virt_exp, exp->cpu))
-				cputime_expires->virt_exp = exp->cpu;
+			if (expires_gt(cputime_expires->virt_exp, expires_to_cputime(exp)))
+				cputime_expires->virt_exp = expires_to_cputime(exp);
 			break;
 		case CPUCLOCK_SCHED:
 			if (cputime_expires->sched_exp == 0 ||
-			    cputime_expires->sched_exp > exp->sched)
-				cputime_expires->sched_exp = exp->sched;
+			    cputime_expires->sched_exp > exp)
+				cputime_expires->sched_exp = exp;
 			break;
 		}
 	}
@@ -584,20 +525,20 @@ static void cpu_timer_fire(struct k_itimer *timer)
 		/*
 		 * User don't want any signal.
 		 */
-		timer->it.cpu.expires.sched = 0;
+		timer->it.cpu.expires = 0;
 	} else if (unlikely(timer->sigq == NULL)) {
 		/*
 		 * This a special case for clock_nanosleep,
 		 * not a normal timer from sys_timer_create.
 		 */
 		wake_up_process(timer->it_process);
-		timer->it.cpu.expires.sched = 0;
-	} else if (timer->it.cpu.incr.sched == 0) {
+		timer->it.cpu.expires = 0;
+	} else if (timer->it.cpu.incr == 0) {
 		/*
 		 * One-shot timer.  Clear it as soon as it's fired.
 		 */
 		posix_timer_event(timer, 0);
-		timer->it.cpu.expires.sched = 0;
+		timer->it.cpu.expires = 0;
 	} else if (posix_timer_event(timer, ++timer->it_requeue_pending)) {
 		/*
 		 * The signal did not get queued because the signal
@@ -615,7 +556,7 @@ static void cpu_timer_fire(struct k_itimer *timer)
  */
 static int cpu_timer_sample_group(const clockid_t which_clock,
 				  struct task_struct *p,
-				  union cpu_time_count *cpu)
+				  unsigned long long *sample)
 {
 	struct task_cputime cputime;
 
@@ -624,13 +565,13 @@ static int cpu_timer_sample_group(const clockid_t which_clock,
 	default:
 		return -EINVAL;
 	case CPUCLOCK_PROF:
-		cpu->cpu = cputime.utime + cputime.stime;
+		*sample = cputime_to_expires(cputime.utime + cputime.stime);
 		break;
 	case CPUCLOCK_VIRT:
-		cpu->cpu = cputime.utime;
+		*sample = cputime_to_expires(cputime.utime);
 		break;
 	case CPUCLOCK_SCHED:
-		cpu->sched = cputime.sum_exec_runtime + task_delta_exec(p);
+		*sample = cputime.sum_exec_runtime + task_delta_exec(p);
 		break;
 	}
 	return 0;
@@ -646,7 +587,7 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int flags,
 			       struct itimerspec *new, struct itimerspec *old)
 {
 	struct task_struct *p = timer->it.cpu.task;
-	union cpu_time_count old_expires, new_expires, old_incr, val;
+	unsigned long long old_expires, new_expires, old_incr, val;
 	int ret;
 
 	if (unlikely(p == NULL)) {
@@ -701,7 +642,7 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int flags,
 	}
 
 	if (old) {
-		if (old_expires.sched == 0) {
+		if (old_expires == 0) {
 			old->it_value.tv_sec = 0;
 			old->it_value.tv_nsec = 0;
 		} else {
@@ -716,11 +657,8 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int flags,
 			 * new setting.
 			 */
 			bump_cpu_timer(timer, val);
-			if (cpu_time_before(timer->it_clock, val,
-					    timer->it.cpu.expires)) {
-				old_expires = cpu_time_sub(
-					timer->it_clock,
-					timer->it.cpu.expires, val);
+			if (val < timer->it.cpu.expires) {
+				old_expires = timer->it.cpu.expires - val;
 				sample_to_timespec(timer->it_clock,
 						   old_expires,
 						   &old->it_value);
@@ -743,8 +681,8 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int flags,
 		goto out;
 	}
 
-	if (new_expires.sched != 0 && !(flags & TIMER_ABSTIME)) {
-		cpu_time_add(timer->it_clock, &new_expires, val);
+	if (new_expires != 0 && !(flags & TIMER_ABSTIME)) {
+		new_expires += val;
 	}
 
 	/*
@@ -753,8 +691,7 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int flags,
 	 * arm the timer (we'll just fake it for timer_gettime).
 	 */
 	timer->it.cpu.expires = new_expires;
-	if (new_expires.sched != 0 &&
-	    cpu_time_before(timer->it_clock, val, new_expires)) {
+	if (new_expires != 0 && val < new_expires) {
 		arm_timer(timer);
 	}
 
@@ -778,8 +715,7 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int flags,
 	timer->it_overrun_last = 0;
 	timer->it_overrun = -1;
 
-	if (new_expires.sched != 0 &&
-	    !cpu_time_before(timer->it_clock, val, new_expires)) {
+	if (new_expires != 0 && !(val < new_expires)) {
 		/*
 		 * The designated time already passed, so we notify
 		 * immediately, even if the thread never runs to
@@ -799,7 +735,7 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int flags,
 
 static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec *itp)
 {
-	union cpu_time_count now;
+	unsigned long long now;
 	struct task_struct *p = timer->it.cpu.task;
 	int clear_dead;
 
@@ -809,7 +745,7 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec *itp)
 	sample_to_timespec(timer->it_clock,
 			   timer->it.cpu.incr, &itp->it_interval);
 
-	if (timer->it.cpu.expires.sched == 0) {	/* Timer not armed at all.  */
+	if (timer->it.cpu.expires == 0) {	/* Timer not armed at all.  */
 		itp->it_value.tv_sec = itp->it_value.tv_nsec = 0;
 		return;
 	}
@@ -841,7 +777,7 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec *itp)
 			 */
 			put_task_struct(p);
 			timer->it.cpu.task = NULL;
-			timer->it.cpu.expires.sched = 0;
+			timer->it.cpu.expires = 0;
 			read_unlock(&tasklist_lock);
 			goto dead;
 		} else {
@@ -862,10 +798,9 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec *itp)
 		goto dead;
 	}
 
-	if (cpu_time_before(timer->it_clock, now, timer->it.cpu.expires)) {
+	if (now < timer->it.cpu.expires) {
 		sample_to_timespec(timer->it_clock,
-				   cpu_time_sub(timer->it_clock,
-						timer->it.cpu.expires, now),
+				   timer->it.cpu.expires - now,
 				   &itp->it_value);
 	} else {
 		/*
@@ -877,6 +812,28 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec *itp)
 	}
 }
 
+static unsigned long long
+check_timers_list(struct list_head *timers,
+		  struct list_head *firing,
+		  unsigned long long curr)
+{
+	int maxfire = 20;
+
+	while (!list_empty(timers)) {
+		struct cpu_timer_list *t;
+
+		t = list_first_entry(timers, struct cpu_timer_list, entry);
+
+		if (!--maxfire || curr < t->expires)
+			return t->expires;
+
+		t->firing = 1;
+		list_move_tail(&t->entry, firing);
+	}
+
+	return 0;
+}
+
 /*
  * Check for any per-thread CPU timers that have fired and move them off
  * the tsk->cpu_timers[N] list onto the firing list.  Here we update the
@@ -885,54 +842,20 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec *itp)
 static void check_thread_timers(struct task_struct *tsk,
 				struct list_head *firing)
 {
-	int maxfire;
 	struct list_head *timers = tsk->cpu_timers;
 	struct signal_struct *const sig = tsk->signal;
+	struct task_cputime *tsk_expires = &tsk->cputime_expires;
+	unsigned long long expires;
 	unsigned long soft;
 
-	maxfire = 20;
-	tsk->cputime_expires.prof_exp = 0;
-	while (!list_empty(timers)) {
-		struct cpu_timer_list *t = list_first_entry(timers,
-						      struct cpu_timer_list,
-						      entry);
-		if (!--maxfire || prof_ticks(tsk) < t->expires.cpu) {
-			tsk->cputime_expires.prof_exp = t->expires.cpu;
-			break;
-		}
-		t->firing = 1;
-		list_move_tail(&t->entry, firing);
-	}
+	expires = check_timers_list(timers, firing, prof_ticks(tsk));
+	tsk_expires->prof_exp = expires_to_cputime(expires);
 
-	++timers;
-	maxfire = 20;
-	tsk->cputime_expires.virt_exp = 0;
-	while (!list_empty(timers)) {
-		struct cpu_timer_list *t = list_first_entry(timers,
-						      struct cpu_timer_list,
-						      entry);
-		if (!--maxfire || virt_ticks(tsk) < t->expires.cpu) {
-			tsk->cputime_expires.virt_exp = t->expires.cpu;
-			break;
-		}
-		t->firing = 1;
-		list_move_tail(&t->entry, firing);
-	}
+	expires = check_timers_list(++timers, firing, virt_ticks(tsk));
+	tsk_expires->virt_exp = expires_to_cputime(expires);
 
-	++timers;
-	maxfire = 20;
-	tsk->cputime_expires.sched_exp = 0;
-	while (!list_empty(timers)) {
-		struct cpu_timer_list *t = list_first_entry(timers,
-						      struct cpu_timer_list,
-						      entry);
-		if (!--maxfire || tsk->se.sum_exec_runtime < t->expires.sched) {
-			tsk->cputime_expires.sched_exp = t->expires.sched;
-			break;
-		}
-		t->firing = 1;
-		list_move_tail(&t->entry, firing);
-	}
+	tsk_expires->sched_exp = check_timers_list(++timers, firing,
+						   tsk->se.sum_exec_runtime);
 
 	/*
 	 * Check for the special case thread timers.
@@ -980,7 +903,8 @@ static void stop_process_timers(struct signal_struct *sig)
 static u32 onecputick;
 
 static void check_cpu_itimer(struct task_struct *tsk, struct cpu_itimer *it,
-			     cputime_t *expires, cputime_t cur_time, int signo)
+			     unsigned long long *expires,
+			     unsigned long long cur_time, int signo)
 {
 	if (!it->expires)
 		return;
@@ -1031,9 +955,8 @@ static inline int task_cputime_zero(const struct task_cputime *cputime)
 static void check_process_timers(struct task_struct *tsk,
 				 struct list_head *firing)
 {
-	int maxfire;
 	struct signal_struct *const sig = tsk->signal;
-	cputime_t utime, ptime, virt_expires, prof_expires;
+	unsigned long long utime, ptime, virt_expires, prof_expires;
 	unsigned long long sum_sched_runtime, sched_expires;
 	struct list_head *timers = sig->cpu_timers;
 	struct task_cputime cputime;
@@ -1043,52 +966,13 @@ static void check_process_timers(struct task_struct *tsk,
 	 * Collect the current process totals.
 	 */
 	thread_group_cputimer(tsk, &cputime);
-	utime = cputime.utime;
-	ptime = utime + cputime.stime;
+	utime = cputime_to_expires(cputime.utime);
+	ptime = utime + cputime_to_expires(cputime.stime);
 	sum_sched_runtime = cputime.sum_exec_runtime;
-	maxfire = 20;
-	prof_expires = 0;
-	while (!list_empty(timers)) {
-		struct cpu_timer_list *tl = list_first_entry(timers,
-						      struct cpu_timer_list,
-						      entry);
-		if (!--maxfire || ptime < tl->expires.cpu) {
-			prof_expires = tl->expires.cpu;
-			break;
-		}
-		tl->firing = 1;
-		list_move_tail(&tl->entry, firing);
-	}
 
-	++timers;
-	maxfire = 20;
-	virt_expires = 0;
-	while (!list_empty(timers)) {
-		struct cpu_timer_list *tl = list_first_entry(timers,
-						      struct cpu_timer_list,
-						      entry);
-		if (!--maxfire || utime < tl->expires.cpu) {
-			virt_expires = tl->expires.cpu;
-			break;
-		}
-		tl->firing = 1;
-		list_move_tail(&tl->entry, firing);
-	}
-
-	++timers;
-	maxfire = 20;
-	sched_expires = 0;
-	while (!list_empty(timers)) {
-		struct cpu_timer_list *tl = list_first_entry(timers,
-						      struct cpu_timer_list,
-						      entry);
-		if (!--maxfire || sum_sched_runtime < tl->expires.sched) {
-			sched_expires = tl->expires.sched;
-			break;
-		}
-		tl->firing = 1;
-		list_move_tail(&tl->entry, firing);
-	}
+	prof_expires = check_timers_list(timers, firing, ptime);
+	virt_expires = check_timers_list(++timers, firing, utime);
+	sched_expires = check_timers_list(++timers, firing, sum_sched_runtime);
 
 	/*
 	 * Check for the special case process timers.
@@ -1127,8 +1011,8 @@ static void check_process_timers(struct task_struct *tsk,
 		}
 	}
 
-	sig->cputime_expires.prof_exp = prof_expires;
-	sig->cputime_expires.virt_exp = virt_expires;
+	sig->cputime_expires.prof_exp = expires_to_cputime(prof_expires);
+	sig->cputime_expires.virt_exp = expires_to_cputime(virt_expires);
 	sig->cputime_expires.sched_exp = sched_expires;
 	if (task_cputime_zero(&sig->cputime_expires))
 		stop_process_timers(sig);
@@ -1141,7 +1025,7 @@ static void check_process_timers(struct task_struct *tsk,
 void posix_cpu_timer_schedule(struct k_itimer *timer)
 {
 	struct task_struct *p = timer->it.cpu.task;
-	union cpu_time_count now;
+	unsigned long long now;
 
 	if (unlikely(p == NULL))
 		/*
@@ -1170,7 +1054,7 @@ void posix_cpu_timer_schedule(struct k_itimer *timer)
 			 */
 			put_task_struct(p);
 			timer->it.cpu.task = p = NULL;
-			timer->it.cpu.expires.sched = 0;
+			timer->it.cpu.expires = 0;
 			goto out_unlock;
 		} else if (unlikely(p->exit_state) && thread_group_empty(p)) {
 			/*
@@ -1345,7 +1229,7 @@ void run_posix_cpu_timers(struct task_struct *tsk)
 void set_process_cpu_timer(struct task_struct *tsk, unsigned int clock_idx,
 			   cputime_t *newval, cputime_t *oldval)
 {
-	union cpu_time_count now;
+	unsigned long long now;
 
 	BUG_ON(clock_idx == CPUCLOCK_SCHED);
 	cpu_timer_sample_group(clock_idx, tsk, &now);
@@ -1357,17 +1241,17 @@ void set_process_cpu_timer(struct task_struct *tsk, unsigned int clock_idx,
 		 * it to be absolute.
 		 */
 		if (*oldval) {
-			if (*oldval <= now.cpu) {
+			if (*oldval <= now) {
 				/* Just about to fire. */
 				*oldval = cputime_one_jiffy;
 			} else {
-				*oldval -= now.cpu;
+				*oldval -= now;
 			}
 		}
 
 		if (!*newval)
 			return;
-		*newval += now.cpu;
+		*newval += now;
 	}
 
 	/*
@@ -1415,7 +1299,7 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags,
 		}
 
 		while (!signal_pending(current)) {
-			if (timer.it.cpu.expires.sched == 0) {
+			if (timer.it.cpu.expires == 0) {
 				/*
 				 * Our timer fired and was reset, below
 				 * deletion can not fail.
diff --git a/kernel/power/console.c b/kernel/power/console.c
index b1dc456..463aa673 100644
--- a/kernel/power/console.c
+++ b/kernel/power/console.c
@@ -4,6 +4,7 @@
  * Originally from swsusp.
  */
 
+#include <linux/console.h>
 #include <linux/vt_kern.h>
 #include <linux/kbd_kern.h>
 #include <linux/vt.h>
@@ -14,8 +15,120 @@
 
 static int orig_fgconsole, orig_kmsg;
 
+static DEFINE_MUTEX(vt_switch_mutex);
+
+struct pm_vt_switch {
+	struct list_head head;
+	struct device *dev;
+	bool required;
+};
+
+static LIST_HEAD(pm_vt_switch_list);
+
+
+/**
+ * pm_vt_switch_required - indicate VT switch at suspend requirements
+ * @dev: device
+ * @required: if true, caller needs VT switch at suspend/resume time
+ *
+ * The different console drivers may or may not require VT switches across
+ * suspend/resume, depending on how they handle restoring video state and
+ * what may be running.
+ *
+ * Drivers can indicate support for switchless suspend/resume, which can
+ * save time and flicker, by using this routine and passing 'false' as
+ * the argument.  If any loaded driver needs VT switching, or the
+ * no_console_suspend argument has been passed on the command line, VT
+ * switches will occur.
+ */
+void pm_vt_switch_required(struct device *dev, bool required)
+{
+	struct pm_vt_switch *entry, *tmp;
+
+	mutex_lock(&vt_switch_mutex);
+	list_for_each_entry(tmp, &pm_vt_switch_list, head) {
+		if (tmp->dev == dev) {
+			/* already registered, update requirement */
+			tmp->required = required;
+			goto out;
+		}
+	}
+
+	entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+	if (!entry)
+		goto out;
+
+	entry->required = required;
+	entry->dev = dev;
+
+	list_add(&entry->head, &pm_vt_switch_list);
+out:
+	mutex_unlock(&vt_switch_mutex);
+}
+EXPORT_SYMBOL(pm_vt_switch_required);
+
+/**
+ * pm_vt_switch_unregister - stop tracking a device's VT switching needs
+ * @dev: device
+ *
+ * Remove @dev from the vt switch list.
+ */
+void pm_vt_switch_unregister(struct device *dev)
+{
+	struct pm_vt_switch *tmp;
+
+	mutex_lock(&vt_switch_mutex);
+	list_for_each_entry(tmp, &pm_vt_switch_list, head) {
+		if (tmp->dev == dev) {
+			list_del(&tmp->head);
+			break;
+		}
+	}
+	mutex_unlock(&vt_switch_mutex);
+}
+EXPORT_SYMBOL(pm_vt_switch_unregister);
+
+/*
+ * There are three cases when a VT switch on suspend/resume are required:
+ *   1) no driver has indicated a requirement one way or another, so preserve
+ *      the old behavior
+ *   2) console suspend is disabled, we want to see debug messages across
+ *      suspend/resume
+ *   3) any registered driver indicates it needs a VT switch
+ *
+ * If none of these conditions is present, meaning we have at least one driver
+ * that doesn't need the switch, and none that do, we can avoid it to make
+ * resume look a little prettier (and suspend too, but that's usually hidden,
+ * e.g. when closing the lid on a laptop).
+ */
+static bool pm_vt_switch(void)
+{
+	struct pm_vt_switch *entry;
+	bool ret = true;
+
+	mutex_lock(&vt_switch_mutex);
+	if (list_empty(&pm_vt_switch_list))
+		goto out;
+
+	if (!console_suspend_enabled)
+		goto out;
+
+	list_for_each_entry(entry, &pm_vt_switch_list, head) {
+		if (entry->required)
+			goto out;
+	}
+
+	ret = false;
+out:
+	mutex_unlock(&vt_switch_mutex);
+	return ret;
+}
+
 int pm_prepare_console(void)
 {
+	if (!pm_vt_switch())
+		return 0;
+
 	orig_fgconsole = vt_move_to_console(SUSPEND_CONSOLE, 1);
 	if (orig_fgconsole < 0)
 		return 1;
@@ -26,6 +139,9 @@ int pm_prepare_console(void)
 
 void pm_restore_console(void)
 {
+	if (!pm_vt_switch())
+		return;
+
 	if (orig_fgconsole >= 0) {
 		vt_move_to_console(orig_fgconsole, 0);
 		vt_kmsg_redirect(orig_kmsg);
diff --git a/kernel/printk.c b/kernel/printk.c
index abbdd9e..021053d 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -32,6 +32,7 @@
 #include <linux/security.h>
 #include <linux/bootmem.h>
 #include <linux/memblock.h>
+#include <linux/aio.h>
 #include <linux/syscalls.h>
 #include <linux/kexec.h>
 #include <linux/kdb.h>
@@ -49,13 +50,6 @@
 #define CREATE_TRACE_POINTS
 #include <trace/events/printk.h>
 
-/*
- * Architectures can override it:
- */
-void asmlinkage __attribute__((weak)) early_printk(const char *fmt, ...)
-{
-}
-
 /* printk's without a loglevel use this.. */
 #define DEFAULT_MESSAGE_LOGLEVEL CONFIG_DEFAULT_MESSAGE_LOGLEVEL
 
@@ -1265,10 +1259,8 @@ static void call_console_drivers(int level, const char *text, size_t len)
 {
 	struct console *con;
 
-	trace_console(text, 0, len, len);
+	trace_console(text, len);
 
-	if (level >= console_loglevel && !ignore_loglevel)
-		return;
 	if (!console_drivers)
 		return;
 
@@ -1282,6 +1274,9 @@ static void call_console_drivers(int level, const char *text, size_t len)
 		if (!cpu_online(smp_processor_id()) &&
 		    !(con->flags & CON_ANYTIME))
 			continue;
+		if (level >= console_loglevel && !ignore_loglevel &&
+		    !(con->flags & CON_ALLDATA))
+			continue;
 		con->write(con, text, len);
 	}
 }
@@ -1364,9 +1359,9 @@ static int console_trylock_for_printk(unsigned int cpu)
 		}
 	}
 	logbuf_cpu = UINT_MAX;
+	raw_spin_unlock(&logbuf_lock);
 	if (wake)
 		up(&console_sem);
-	raw_spin_unlock(&logbuf_lock);
 	return retval;
 }
 
@@ -1723,6 +1718,29 @@ static size_t cont_print_text(char *text, size_t size) { return 0; }
 
 #endif /* CONFIG_PRINTK */
 
+#ifdef CONFIG_EARLY_PRINTK
+struct console *early_console;
+
+void early_vprintk(const char *fmt, va_list ap)
+{
+	if (early_console) {
+		char buf[512];
+		int n = vscnprintf(buf, sizeof(buf), fmt, ap);
+
+		early_console->write(early_console, buf, n);
+	}
+}
+
+asmlinkage void early_printk(const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	early_vprintk(fmt, ap);
+	va_end(ap);
+}
+#endif
+
 static int __add_preferred_console(char *name, int idx, char *options,
 				   char *brl_options)
 {
diff --git a/kernel/profile.c b/kernel/profile.c
index dc3384e..524ce5e 100644
--- a/kernel/profile.c
+++ b/kernel/profile.c
@@ -462,10 +462,10 @@ static const struct file_operations prof_cpu_mask_proc_fops = {
 	.write		= prof_cpu_mask_proc_write,
 };
 
-void create_prof_cpu_mask(struct proc_dir_entry *root_irq_dir)
+void create_prof_cpu_mask(void)
 {
 	/* create /proc/irq/prof_cpu_mask */
-	proc_create("prof_cpu_mask", 0600, root_irq_dir, &prof_cpu_mask_proc_fops);
+	proc_create("irq/prof_cpu_mask", 0600, NULL, &prof_cpu_mask_proc_fops);
 }
 
 /*
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index acbd284..aed981a 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -17,6 +17,7 @@
 #include <linux/ptrace.h>
 #include <linux/security.h>
 #include <linux/signal.h>
+#include <linux/uio.h>
 #include <linux/audit.h>
 #include <linux/pid_namespace.h>
 #include <linux/syscalls.h>
@@ -24,6 +25,7 @@
 #include <linux/regset.h>
 #include <linux/hw_breakpoint.h>
 #include <linux/cn_proc.h>
+#include <linux/compat.h>
 
 
 static int ptrace_trapping_sleep_fn(void *flags)
@@ -618,6 +620,81 @@ static int ptrace_setsiginfo(struct task_struct *child, const siginfo_t *info)
 	return error;
 }
 
+static int ptrace_peek_siginfo(struct task_struct *child,
+				unsigned long addr,
+				unsigned long data)
+{
+	struct ptrace_peeksiginfo_args arg;
+	struct sigpending *pending;
+	struct sigqueue *q;
+	int ret, i;
+
+	ret = copy_from_user(&arg, (void __user *) addr,
+				sizeof(struct ptrace_peeksiginfo_args));
+	if (ret)
+		return -EFAULT;
+
+	if (arg.flags & ~PTRACE_PEEKSIGINFO_SHARED)
+		return -EINVAL; /* unknown flags */
+
+	if (arg.nr < 0)
+		return -EINVAL;
+
+	if (arg.flags & PTRACE_PEEKSIGINFO_SHARED)
+		pending = &child->signal->shared_pending;
+	else
+		pending = &child->pending;
+
+	for (i = 0; i < arg.nr; ) {
+		siginfo_t info;
+		s32 off = arg.off + i;
+
+		spin_lock_irq(&child->sighand->siglock);
+		list_for_each_entry(q, &pending->list, list) {
+			if (!off--) {
+				copy_siginfo(&info, &q->info);
+				break;
+			}
+		}
+		spin_unlock_irq(&child->sighand->siglock);
+
+		if (off >= 0) /* beyond the end of the list */
+			break;
+
+#ifdef CONFIG_COMPAT
+		if (unlikely(is_compat_task())) {
+			compat_siginfo_t __user *uinfo = compat_ptr(data);
+
+			ret = copy_siginfo_to_user32(uinfo, &info);
+			ret |= __put_user(info.si_code, &uinfo->si_code);
+		} else
+#endif
+		{
+			siginfo_t __user *uinfo = (siginfo_t __user *) data;
+
+			ret = copy_siginfo_to_user(uinfo, &info);
+			ret |= __put_user(info.si_code, &uinfo->si_code);
+		}
+
+		if (ret) {
+			ret = -EFAULT;
+			break;
+		}
+
+		data += sizeof(siginfo_t);
+		i++;
+
+		if (signal_pending(current))
+			break;
+
+		cond_resched();
+	}
+
+	if (i > 0)
+		return i;
+
+	return ret;
+}
 
 #ifdef PTRACE_SINGLESTEP
 #define is_singlestep(request)		((request) == PTRACE_SINGLESTEP)
@@ -748,6 +825,10 @@ int ptrace_request(struct task_struct *child, long request,
 		ret = put_user(child->ptrace_message, datalp);
 		break;
 
+	case PTRACE_PEEKSIGINFO:
+		ret = ptrace_peek_siginfo(child, addr, data);
+		break;
+
 	case PTRACE_GETSIGINFO:
 		ret = ptrace_getsiginfo(child, &siginfo);
 		if (!ret)
diff --git a/kernel/range.c b/kernel/range.c
index 9b8ae2d..071b0ab 100644
--- a/kernel/range.c
+++ b/kernel/range.c
@@ -97,7 +97,8 @@ void subtract_range(struct range *range, int az, u64 start, u64 end)
 				range[i].end = range[j].end;
 				range[i].start = end;
 			} else {
-				printk(KERN_ERR "run of slot in ranges\n");
+				pr_err("%s: run out of slot in ranges\n",
+					__func__);
 			}
 			range[j].end = start;
 			continue;
diff --git a/kernel/rcutree.c b/kernel/rcutree.c
index 5b8ad82..d853430 100644
--- a/kernel/rcutree.c
+++ b/kernel/rcutree.c
@@ -64,7 +64,7 @@
 static struct lock_class_key rcu_node_class[RCU_NUM_LVLS];
 static struct lock_class_key rcu_fqs_class[RCU_NUM_LVLS];
 
-#define RCU_STATE_INITIALIZER(sname, cr) { \
+#define RCU_STATE_INITIALIZER(sname, sabbr, cr) { \
 	.level = { &sname##_state.node[0] }, \
 	.call = cr, \
 	.fqs_state = RCU_GP_IDLE, \
@@ -76,13 +76,14 @@ static struct lock_class_key rcu_fqs_class[RCU_NUM_LVLS];
 	.barrier_mutex = __MUTEX_INITIALIZER(sname##_state.barrier_mutex), \
 	.onoff_mutex = __MUTEX_INITIALIZER(sname##_state.onoff_mutex), \
 	.name = #sname, \
+	.abbr = sabbr, \
 }
 
 struct rcu_state rcu_sched_state =
-	RCU_STATE_INITIALIZER(rcu_sched, call_rcu_sched);
+	RCU_STATE_INITIALIZER(rcu_sched, 's', call_rcu_sched);
 DEFINE_PER_CPU(struct rcu_data, rcu_sched_data);
 
-struct rcu_state rcu_bh_state = RCU_STATE_INITIALIZER(rcu_bh, call_rcu_bh);
+struct rcu_state rcu_bh_state = RCU_STATE_INITIALIZER(rcu_bh, 'b', call_rcu_bh);
 DEFINE_PER_CPU(struct rcu_data, rcu_bh_data);
 
 static struct rcu_state *rcu_state;
@@ -223,6 +224,8 @@ static ulong jiffies_till_next_fqs = RCU_JIFFIES_TILL_FORCE_QS;
 module_param(jiffies_till_first_fqs, ulong, 0644);
 module_param(jiffies_till_next_fqs, ulong, 0644);
 
+static void rcu_start_gp_advanced(struct rcu_state *rsp, struct rcu_node *rnp,
+				  struct rcu_data *rdp);
 static void force_qs_rnp(struct rcu_state *rsp, int (*f)(struct rcu_data *));
 static void force_quiescent_state(struct rcu_state *rsp);
 static int rcu_pending(int cpu);
@@ -310,6 +313,8 @@ cpu_needs_another_gp(struct rcu_state *rsp, struct rcu_data *rdp)
 
 	if (rcu_gp_in_progress(rsp))
 		return 0;  /* No, a grace period is already in progress. */
+	if (rcu_nocb_needs_gp(rsp))
+		return 1;  /* Yes, a no-CBs CPU needs one. */
 	if (!rdp->nxttail[RCU_NEXT_TAIL])
 		return 0;  /* No, this is a no-CBs (or offline) CPU. */
 	if (*rdp->nxttail[RCU_NEXT_READY_TAIL])
@@ -1035,10 +1040,11 @@ static void init_callback_list(struct rcu_data *rdp)
 {
 	int i;
 
+	if (init_nocb_callback_list(rdp))
+		return;
 	rdp->nxtlist = NULL;
 	for (i = 0; i < RCU_NEXT_SIZE; i++)
 		rdp->nxttail[i] = &rdp->nxtlist;
-	init_nocb_callback_list(rdp);
 }
 
 /*
@@ -1071,6 +1077,120 @@ static unsigned long rcu_cbs_completed(struct rcu_state *rsp,
 }
 
 /*
+ * Trace-event helper function for rcu_start_future_gp() and
+ * rcu_nocb_wait_gp().
+ */
+static void trace_rcu_future_gp(struct rcu_node *rnp, struct rcu_data *rdp,
+				unsigned long c, char *s)
+{
+	trace_rcu_future_grace_period(rdp->rsp->name, rnp->gpnum,
+				      rnp->completed, c, rnp->level,
+				      rnp->grplo, rnp->grphi, s);
+}
+
+/*
+ * Start some future grace period, as needed to handle newly arrived
+ * callbacks.  The required future grace periods are recorded in each
+ * rcu_node structure's ->need_future_gp field.
+ *
+ * The caller must hold the specified rcu_node structure's ->lock.
+ */
+static unsigned long __maybe_unused
+rcu_start_future_gp(struct rcu_node *rnp, struct rcu_data *rdp)
+{
+	unsigned long c;
+	int i;
+	struct rcu_node *rnp_root = rcu_get_root(rdp->rsp);
+
+	/*
+	 * Pick up grace-period number for new callbacks.  If this
+	 * grace period is already marked as needed, return to the caller.
+	 */
+	c = rcu_cbs_completed(rdp->rsp, rnp);
+	trace_rcu_future_gp(rnp, rdp, c, "Startleaf");
+	if (rnp->need_future_gp[c & 0x1]) {
+		trace_rcu_future_gp(rnp, rdp, c, "Prestartleaf");
+		return c;
+	}
+
+	/*
+	 * If either this rcu_node structure or the root rcu_node structure
+	 * believe that a grace period is in progress, then we must wait
+	 * for the one following, which is in "c".  Because our request
+	 * will be noticed at the end of the current grace period, we don't
+	 * need to explicitly start one.
+	 */
+	if (rnp->gpnum != rnp->completed ||
+	    ACCESS_ONCE(rnp->gpnum) != ACCESS_ONCE(rnp->completed)) {
+		rnp->need_future_gp[c & 0x1]++;
+		trace_rcu_future_gp(rnp, rdp, c, "Startedleaf");
+		return c;
+	}
+
+	/*
+	 * There might be no grace period in progress.  If we don't already
+	 * hold it, acquire the root rcu_node structure's lock in order to
+	 * start one (if needed).
+	 */
+	if (rnp != rnp_root)
+		raw_spin_lock(&rnp_root->lock);
+
+	/*
+	 * Get a new grace-period number.  If there really is no grace
+	 * period in progress, it will be smaller than the one we obtained
+	 * earlier.  Adjust callbacks as needed.  Note that even no-CBs
+	 * CPUs have a ->nxtcompleted[] array, so no no-CBs checks needed.
+	 */
+	c = rcu_cbs_completed(rdp->rsp, rnp_root);
+	for (i = RCU_DONE_TAIL; i < RCU_NEXT_TAIL; i++)
+		if (ULONG_CMP_LT(c, rdp->nxtcompleted[i]))
+			rdp->nxtcompleted[i] = c;
+
+	/*
+	 * If the needed for the required grace period is already
+	 * recorded, trace and leave.
+	 */
+	if (rnp_root->need_future_gp[c & 0x1]) {
+		trace_rcu_future_gp(rnp, rdp, c, "Prestartedroot");
+		goto unlock_out;
+	}
+
+	/* Record the need for the future grace period. */
+	rnp_root->need_future_gp[c & 0x1]++;
+
+	/* If a grace period is not already in progress, start one. */
+	if (rnp_root->gpnum != rnp_root->completed) {
+		trace_rcu_future_gp(rnp, rdp, c, "Startedleafroot");
+	} else {
+		trace_rcu_future_gp(rnp, rdp, c, "Startedroot");
+		rcu_start_gp_advanced(rdp->rsp, rnp_root, rdp);
+	}
+unlock_out:
+	if (rnp != rnp_root)
+		raw_spin_unlock(&rnp_root->lock);
+	return c;
+}
+
+/*
+ * Clean up any old requests for the just-ended grace period.  Also return
+ * whether any additional grace periods have been requested.  Also invoke
+ * rcu_nocb_gp_cleanup() in order to wake up any no-callbacks kthreads
+ * waiting for this grace period to complete.
+ */
+static int rcu_future_gp_cleanup(struct rcu_state *rsp, struct rcu_node *rnp)
+{
+	int c = rnp->completed;
+	int needmore;
+	struct rcu_data *rdp = this_cpu_ptr(rsp->rda);
+
+	rcu_nocb_gp_cleanup(rsp, rnp);
+	rnp->need_future_gp[c & 0x1] = 0;
+	needmore = rnp->need_future_gp[(c + 1) & 0x1];
+	trace_rcu_future_gp(rnp, rdp, c, needmore ? "CleanupMore" : "Cleanup");
+	return needmore;
+}
+
+/*
  * If there is room, assign a ->completed number to any callbacks on
  * this CPU that have not already been assigned.  Also accelerate any
  * callbacks that were previously assigned a ->completed number that has
@@ -1129,6 +1249,8 @@ static void rcu_accelerate_cbs(struct rcu_state *rsp, struct rcu_node *rnp,
 		rdp->nxttail[i] = rdp->nxttail[RCU_NEXT_TAIL];
 		rdp->nxtcompleted[i] = c;
 	}
+	/* Record any needed additional grace periods. */
+	rcu_start_future_gp(rnp, rdp);
 
 	/* Trace depending on how much we were able to accelerate. */
 	if (!*rdp->nxttail[RCU_WAIT_TAIL])
@@ -1308,9 +1430,9 @@ static int rcu_gp_init(struct rcu_state *rsp)
 		rdp = this_cpu_ptr(rsp->rda);
 		rcu_preempt_check_blocked_tasks(rnp);
 		rnp->qsmask = rnp->qsmaskinit;
-		rnp->gpnum = rsp->gpnum;
+		ACCESS_ONCE(rnp->gpnum) = rsp->gpnum;
 		WARN_ON_ONCE(rnp->completed != rsp->completed);
-		rnp->completed = rsp->completed;
+		ACCESS_ONCE(rnp->completed) = rsp->completed;
 		if (rnp == rdp->mynode)
 			rcu_start_gp_per_cpu(rsp, rnp, rdp);
 		rcu_preempt_boost_start_gp(rnp);
@@ -1319,7 +1441,8 @@ static int rcu_gp_init(struct rcu_state *rsp)
 					    rnp->grphi, rnp->qsmask);
 		raw_spin_unlock_irq(&rnp->lock);
 #ifdef CONFIG_PROVE_RCU_DELAY
-		if ((random32() % (rcu_num_nodes * 8)) == 0)
+		if ((prandom_u32() % (rcu_num_nodes * 8)) == 0 &&
+		    system_state == SYSTEM_RUNNING)
 			schedule_timeout_uninterruptible(2);
 #endif /* #ifdef CONFIG_PROVE_RCU_DELAY */
 		cond_resched();
@@ -1361,6 +1484,7 @@ int rcu_gp_fqs(struct rcu_state *rsp, int fqs_state_in)
 static void rcu_gp_cleanup(struct rcu_state *rsp)
 {
 	unsigned long gp_duration;
+	int nocb = 0;
 	struct rcu_data *rdp;
 	struct rcu_node *rnp = rcu_get_root(rsp);
 
@@ -1390,17 +1514,23 @@ static void rcu_gp_cleanup(struct rcu_state *rsp)
 	 */
 	rcu_for_each_node_breadth_first(rsp, rnp) {
 		raw_spin_lock_irq(&rnp->lock);
-		rnp->completed = rsp->gpnum;
+		ACCESS_ONCE(rnp->completed) = rsp->gpnum;
+		rdp = this_cpu_ptr(rsp->rda);
+		if (rnp == rdp->mynode)
+			__rcu_process_gp_end(rsp, rnp, rdp);
+		nocb += rcu_future_gp_cleanup(rsp, rnp);
 		raw_spin_unlock_irq(&rnp->lock);
 		cond_resched();
 	}
 	rnp = rcu_get_root(rsp);
 	raw_spin_lock_irq(&rnp->lock);
+	rcu_nocb_gp_set(rnp, nocb);
 
 	rsp->completed = rsp->gpnum; /* Declare grace period done. */
 	trace_rcu_grace_period(rsp->name, rsp->completed, "end");
 	rsp->fqs_state = RCU_GP_IDLE;
 	rdp = this_cpu_ptr(rsp->rda);
+	rcu_advance_cbs(rsp, rnp, rdp);  /* Reduce false positives below. */
 	if (cpu_needs_another_gp(rsp, rdp))
 		rsp->gp_flags = 1;
 	raw_spin_unlock_irq(&rnp->lock);
@@ -1476,57 +1606,62 @@ static int __noreturn rcu_gp_kthread(void *arg)
 /*
  * Start a new RCU grace period if warranted, re-initializing the hierarchy
  * in preparation for detecting the next grace period.  The caller must hold
- * the root node's ->lock, which is released before return.  Hard irqs must
- * be disabled.
+ * the root node's ->lock and hard irqs must be disabled.
  *
  * Note that it is legal for a dying CPU (which is marked as offline) to
  * invoke this function.  This can happen when the dying CPU reports its
  * quiescent state.
  */
 static void
-rcu_start_gp(struct rcu_state *rsp, unsigned long flags)
-	__releases(rcu_get_root(rsp)->lock)
+rcu_start_gp_advanced(struct rcu_state *rsp, struct rcu_node *rnp,
+		      struct rcu_data *rdp)
 {
-	struct rcu_data *rdp = this_cpu_ptr(rsp->rda);
-	struct rcu_node *rnp = rcu_get_root(rsp);
-
-	if (!rsp->gp_kthread ||
-	    !cpu_needs_another_gp(rsp, rdp)) {
+	if (!rsp->gp_kthread || !cpu_needs_another_gp(rsp, rdp)) {
 		/*
 		 * Either we have not yet spawned the grace-period
 		 * task, this CPU does not need another grace period,
 		 * or a grace period is already in progress.
 		 * Either way, don't start a new grace period.
 		 */
-		raw_spin_unlock_irqrestore(&rnp->lock, flags);
 		return;
 	}
-
-	/*
-	 * Because there is no grace period in progress right now,
-	 * any callbacks we have up to this point will be satisfied
-	 * by the next grace period.  So this is a good place to
-	 * assign a grace period number to recently posted callbacks.
-	 */
-	rcu_accelerate_cbs(rsp, rnp, rdp);
-
 	rsp->gp_flags = RCU_GP_FLAG_INIT;
-	raw_spin_unlock(&rnp->lock); /* Interrupts remain disabled. */
-
-	/* Ensure that CPU is aware of completion of last grace period. */
-	rcu_process_gp_end(rsp, rdp);
-	local_irq_restore(flags);
 
 	/* Wake up rcu_gp_kthread() to start the grace period. */
 	wake_up(&rsp->gp_wq);
 }
 
 /*
+ * Similar to rcu_start_gp_advanced(), but also advance the calling CPU's
+ * callbacks.  Note that rcu_start_gp_advanced() cannot do this because it
+ * is invoked indirectly from rcu_advance_cbs(), which would result in
+ * endless recursion -- or would do so if it wasn't for the self-deadlock
+ * that is encountered beforehand.
+ */
+static void
+rcu_start_gp(struct rcu_state *rsp)
+{
+	struct rcu_data *rdp = this_cpu_ptr(rsp->rda);
+	struct rcu_node *rnp = rcu_get_root(rsp);
+
+	/*
+	 * If there is no grace period in progress right now, any
+	 * callbacks we have up to this point will be satisfied by the
+	 * next grace period.  Also, advancing the callbacks reduces the
+	 * probability of false positives from cpu_needs_another_gp()
+	 * resulting in pointless grace periods.  So, advance callbacks
+	 * then start the grace period!
+	 */
+	rcu_advance_cbs(rsp, rnp, rdp);
+	rcu_start_gp_advanced(rsp, rnp, rdp);
+}
+
+/*
  * Report a full set of quiescent states to the specified rcu_state
  * data structure.  This involves cleaning up after the prior grace
  * period and letting rcu_start_gp() start up the next grace period
- * if one is needed.  Note that the caller must hold rnp->lock, as
- * required by rcu_start_gp(), which will release it.
+ * if one is needed.  Note that the caller must hold rnp->lock, which
+ * is released before return.
  */
 static void rcu_report_qs_rsp(struct rcu_state *rsp, unsigned long flags)
 	__releases(rcu_get_root(rsp)->lock)
@@ -2124,7 +2259,8 @@ __rcu_process_callbacks(struct rcu_state *rsp)
 	local_irq_save(flags);
 	if (cpu_needs_another_gp(rsp, rdp)) {
 		raw_spin_lock(&rcu_get_root(rsp)->lock); /* irqs disabled. */
-		rcu_start_gp(rsp, flags);  /* releases above lock */
+		rcu_start_gp(rsp);
+		raw_spin_unlock_irqrestore(&rcu_get_root(rsp)->lock, flags);
 	} else {
 		local_irq_restore(flags);
 	}
@@ -2169,7 +2305,8 @@ static void invoke_rcu_callbacks(struct rcu_state *rsp, struct rcu_data *rdp)
 
 static void invoke_rcu_core(void)
 {
-	raise_softirq(RCU_SOFTIRQ);
+	if (cpu_online(smp_processor_id()))
+		raise_softirq(RCU_SOFTIRQ);
 }
 
 /*
@@ -2204,11 +2341,11 @@ static void __call_rcu_core(struct rcu_state *rsp, struct rcu_data *rdp,
 
 		/* Start a new grace period if one not already started. */
 		if (!rcu_gp_in_progress(rsp)) {
-			unsigned long nestflag;
 			struct rcu_node *rnp_root = rcu_get_root(rsp);
 
-			raw_spin_lock_irqsave(&rnp_root->lock, nestflag);
-			rcu_start_gp(rsp, nestflag);  /* rlses rnp_root->lock */
+			raw_spin_lock(&rnp_root->lock);
+			rcu_start_gp(rsp);
+			raw_spin_unlock(&rnp_root->lock);
 		} else {
 			/* Give the grace period a kick. */
 			rdp->blimit = LONG_MAX;
@@ -2628,19 +2765,27 @@ static int rcu_pending(int cpu)
 }
 
 /*
- * Check to see if any future RCU-related work will need to be done
- * by the current CPU, even if none need be done immediately, returning
- * 1 if so.
+ * Return true if the specified CPU has any callback.  If all_lazy is
+ * non-NULL, store an indication of whether all callbacks are lazy.
+ * (If there are no callbacks, all of them are deemed to be lazy.)
  */
-static int rcu_cpu_has_callbacks(int cpu)
+static int rcu_cpu_has_callbacks(int cpu, bool *all_lazy)
 {
+	bool al = true;
+	bool hc = false;
+	struct rcu_data *rdp;
 	struct rcu_state *rsp;
 
-	/* RCU callbacks either ready or pending? */
-	for_each_rcu_flavor(rsp)
-		if (per_cpu_ptr(rsp->rda, cpu)->nxtlist)
-			return 1;
-	return 0;
+	for_each_rcu_flavor(rsp) {
+		rdp = per_cpu_ptr(rsp->rda, cpu);
+		if (rdp->qlen != rdp->qlen_lazy)
+			al = false;
+		if (rdp->nxtlist)
+			hc = true;
+	}
+	if (all_lazy)
+		*all_lazy = al;
+	return hc;
 }
 
 /*
@@ -2859,7 +3004,6 @@ rcu_init_percpu_data(int cpu, struct rcu_state *rsp, int preemptible)
 	rdp->dynticks->dynticks_nesting = DYNTICK_TASK_EXIT_IDLE;
 	atomic_set(&rdp->dynticks->dynticks,
 		   (atomic_read(&rdp->dynticks->dynticks) & ~0x1) + 1);
-	rcu_prepare_for_idle_init(cpu);
 	raw_spin_unlock(&rnp->lock);		/* irqs remain disabled. */
 
 	/* Add CPU to rcu_node bitmasks. */
@@ -2909,7 +3053,6 @@ static int __cpuinit rcu_cpu_notify(struct notifier_block *self,
 	struct rcu_data *rdp = per_cpu_ptr(rcu_state->rda, cpu);
 	struct rcu_node *rnp = rdp->mynode;
 	struct rcu_state *rsp;
-	int ret = NOTIFY_OK;
 
 	trace_rcu_utilization("Start CPU hotplug");
 	switch (action) {
@@ -2923,21 +3066,12 @@ static int __cpuinit rcu_cpu_notify(struct notifier_block *self,
 		rcu_boost_kthread_setaffinity(rnp, -1);
 		break;
 	case CPU_DOWN_PREPARE:
-		if (nocb_cpu_expendable(cpu))
-			rcu_boost_kthread_setaffinity(rnp, cpu);
-		else
-			ret = NOTIFY_BAD;
+		rcu_boost_kthread_setaffinity(rnp, cpu);
 		break;
 	case CPU_DYING:
 	case CPU_DYING_FROZEN:
-		/*
-		 * The whole machine is "stopped" except this CPU, so we can
-		 * touch any data without introducing corruption. We send the
-		 * dying CPU's callbacks to an arbitrarily chosen online CPU.
-		 */
 		for_each_rcu_flavor(rsp)
 			rcu_cleanup_dying_cpu(rsp);
-		rcu_cleanup_after_idle(cpu);
 		break;
 	case CPU_DEAD:
 	case CPU_DEAD_FROZEN:
@@ -2950,7 +3084,7 @@ static int __cpuinit rcu_cpu_notify(struct notifier_block *self,
 		break;
 	}
 	trace_rcu_utilization("End CPU hotplug");
-	return ret;
+	return NOTIFY_OK;
 }
 
 /*
@@ -3085,6 +3219,7 @@ static void __init rcu_init_one(struct rcu_state *rsp,
 			}
 			rnp->level = i;
 			INIT_LIST_HEAD(&rnp->blkd_tasks);
+			rcu_init_one_nocb(rnp);
 		}
 	}
 
@@ -3170,8 +3305,7 @@ void __init rcu_init(void)
 	rcu_init_one(&rcu_sched_state, &rcu_sched_data);
 	rcu_init_one(&rcu_bh_state, &rcu_bh_data);
 	__rcu_init_preempt();
-	rcu_init_nocb();
-	 open_softirq(RCU_SOFTIRQ, rcu_process_callbacks);
+	open_softirq(RCU_SOFTIRQ, rcu_process_callbacks);
 
 	/*
 	 * We don't need protection against CPU-hotplug here because
diff --git a/kernel/rcutree.h b/kernel/rcutree.h
index c896b50..14ee407 100644
--- a/kernel/rcutree.h
+++ b/kernel/rcutree.h
@@ -88,18 +88,13 @@ struct rcu_dynticks {
 	int dynticks_nmi_nesting;   /* Track NMI nesting level. */
 	atomic_t dynticks;	    /* Even value for idle, else odd. */
 #ifdef CONFIG_RCU_FAST_NO_HZ
-	int dyntick_drain;	    /* Prepare-for-idle state variable. */
-	unsigned long dyntick_holdoff;
-				    /* No retries for the jiffy of failure. */
-	struct timer_list idle_gp_timer;
-				    /* Wake up CPU sleeping with callbacks. */
-	unsigned long idle_gp_timer_expires;
-				    /* When to wake up CPU (for repost). */
-	bool idle_first_pass;	    /* First pass of attempt to go idle? */
+	bool all_lazy;		    /* Are all CPU's CBs lazy? */
 	unsigned long nonlazy_posted;
 				    /* # times non-lazy CBs posted to CPU. */
 	unsigned long nonlazy_posted_snap;
 				    /* idle-period nonlazy_posted snapshot. */
+	unsigned long last_accelerate;
+				    /* Last jiffy CBs were accelerated. */
 	int tick_nohz_enabled_snap; /* Previously seen value from sysfs. */
 #endif /* #ifdef CONFIG_RCU_FAST_NO_HZ */
 };
@@ -134,9 +129,6 @@ struct rcu_node {
 				/*  elements that need to drain to allow the */
 				/*  current expedited grace period to */
 				/*  complete (only for TREE_PREEMPT_RCU). */
-	atomic_t wakemask;	/* CPUs whose kthread needs to be awakened. */
-				/*  Since this has meaning only for leaf */
-				/*  rcu_node structures, 32 bits suffices. */
 	unsigned long qsmaskinit;
 				/* Per-GP initial value for qsmask & expmask. */
 	unsigned long grpmask;	/* Mask to apply to parent qsmask. */
@@ -196,6 +188,12 @@ struct rcu_node {
 				/* Refused to boost: not sure why, though. */
 				/*  This can happen due to race conditions. */
 #endif /* #ifdef CONFIG_RCU_BOOST */
+#ifdef CONFIG_RCU_NOCB_CPU
+	wait_queue_head_t nocb_gp_wq[2];
+				/* Place for rcu_nocb_kthread() to wait GP. */
+#endif /* #ifdef CONFIG_RCU_NOCB_CPU */
+	int need_future_gp[2];
+				/* Counts of upcoming no-CB GP requests. */
 	raw_spinlock_t fqslock ____cacheline_internodealigned_in_smp;
 } ____cacheline_internodealigned_in_smp;
 
@@ -328,6 +326,11 @@ struct rcu_data {
 	struct task_struct *nocb_kthread;
 #endif /* #ifdef CONFIG_RCU_NOCB_CPU */
 
+	/* 8) RCU CPU stall data. */
+#ifdef CONFIG_RCU_CPU_STALL_INFO
+	unsigned int softirq_snap;	/* Snapshot of softirq activity. */
+#endif /* #ifdef CONFIG_RCU_CPU_STALL_INFO */
+
 	int cpu;
 	struct rcu_state *rsp;
 };
@@ -375,12 +378,6 @@ struct rcu_state {
 	struct rcu_data __percpu *rda;		/* pointer of percu rcu_data. */
 	void (*call)(struct rcu_head *head,	/* call_rcu() flavor. */
 		     void (*func)(struct rcu_head *head));
-#ifdef CONFIG_RCU_NOCB_CPU
-	void (*call_remote)(struct rcu_head *head,
-		     void (*func)(struct rcu_head *head));
-						/* call_rcu() flavor, but for */
-						/*  placing on remote CPU. */
-#endif /* #ifdef CONFIG_RCU_NOCB_CPU */
 
 	/* The following fields are guarded by the root rcu_node's lock. */
 
@@ -443,6 +440,7 @@ struct rcu_state {
 	unsigned long gp_max;			/* Maximum GP duration in */
 						/*  jiffies. */
 	char *name;				/* Name of structure. */
+	char abbr;				/* Abbreviated name. */
 	struct list_head flavors;		/* List of RCU flavors. */
 };
 
@@ -520,7 +518,6 @@ static int __cpuinit rcu_spawn_one_boost_kthread(struct rcu_state *rsp,
 						 struct rcu_node *rnp);
 #endif /* #ifdef CONFIG_RCU_BOOST */
 static void __cpuinit rcu_prepare_kthreads(int cpu);
-static void rcu_prepare_for_idle_init(int cpu);
 static void rcu_cleanup_after_idle(int cpu);
 static void rcu_prepare_for_idle(int cpu);
 static void rcu_idle_count_callbacks_posted(void);
@@ -529,16 +526,18 @@ static void print_cpu_stall_info(struct rcu_state *rsp, int cpu);
 static void print_cpu_stall_info_end(void);
 static void zero_cpu_stall_ticks(struct rcu_data *rdp);
 static void increment_cpu_stall_ticks(void);
+static int rcu_nocb_needs_gp(struct rcu_state *rsp);
+static void rcu_nocb_gp_set(struct rcu_node *rnp, int nrq);
+static void rcu_nocb_gp_cleanup(struct rcu_state *rsp, struct rcu_node *rnp);
+static void rcu_init_one_nocb(struct rcu_node *rnp);
 static bool is_nocb_cpu(int cpu);
 static bool __call_rcu_nocb(struct rcu_data *rdp, struct rcu_head *rhp,
 			    bool lazy);
 static bool rcu_nocb_adopt_orphan_cbs(struct rcu_state *rsp,
 				      struct rcu_data *rdp);
-static bool nocb_cpu_expendable(int cpu);
 static void rcu_boot_init_nocb_percpu_data(struct rcu_data *rdp);
 static void rcu_spawn_nocb_kthreads(struct rcu_state *rsp);
-static void init_nocb_callback_list(struct rcu_data *rdp);
-static void __init rcu_init_nocb(void);
+static bool init_nocb_callback_list(struct rcu_data *rdp);
 
 #endif /* #ifndef RCU_TREE_NONCORE */
 
diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h
index c1cc7e1..d084ae3 100644
--- a/kernel/rcutree_plugin.h
+++ b/kernel/rcutree_plugin.h
@@ -85,11 +85,21 @@ static void __init rcu_bootup_announce_oddness(void)
 	if (nr_cpu_ids != NR_CPUS)
 		printk(KERN_INFO "\tRCU restricting CPUs from NR_CPUS=%d to nr_cpu_ids=%d.\n", NR_CPUS, nr_cpu_ids);
 #ifdef CONFIG_RCU_NOCB_CPU
+#ifndef CONFIG_RCU_NOCB_CPU_NONE
+	if (!have_rcu_nocb_mask) {
+		alloc_bootmem_cpumask_var(&rcu_nocb_mask);
+		have_rcu_nocb_mask = true;
+	}
+#ifdef CONFIG_RCU_NOCB_CPU_ZERO
+	pr_info("\tExperimental no-CBs CPU 0\n");
+	cpumask_set_cpu(0, rcu_nocb_mask);
+#endif /* #ifdef CONFIG_RCU_NOCB_CPU_ZERO */
+#ifdef CONFIG_RCU_NOCB_CPU_ALL
+	pr_info("\tExperimental no-CBs for all CPUs\n");
+	cpumask_setall(rcu_nocb_mask);
+#endif /* #ifdef CONFIG_RCU_NOCB_CPU_ALL */
+#endif /* #ifndef CONFIG_RCU_NOCB_CPU_NONE */
 	if (have_rcu_nocb_mask) {
-		if (cpumask_test_cpu(0, rcu_nocb_mask)) {
-			cpumask_clear_cpu(0, rcu_nocb_mask);
-			pr_info("\tCPU 0: illegal no-CBs CPU (cleared).\n");
-		}
 		cpulist_scnprintf(nocb_buf, sizeof(nocb_buf), rcu_nocb_mask);
 		pr_info("\tExperimental no-CBs CPUs: %s.\n", nocb_buf);
 		if (rcu_nocb_poll)
@@ -101,7 +111,7 @@ static void __init rcu_bootup_announce_oddness(void)
 #ifdef CONFIG_TREE_PREEMPT_RCU
 
 struct rcu_state rcu_preempt_state =
-	RCU_STATE_INITIALIZER(rcu_preempt, call_rcu);
+	RCU_STATE_INITIALIZER(rcu_preempt, 'p', call_rcu);
 DEFINE_PER_CPU(struct rcu_data, rcu_preempt_data);
 static struct rcu_state *rcu_state = &rcu_preempt_state;
 
@@ -1533,14 +1543,7 @@ static void __cpuinit rcu_prepare_kthreads(int cpu)
 int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies)
 {
 	*delta_jiffies = ULONG_MAX;
-	return rcu_cpu_has_callbacks(cpu);
-}
-
-/*
- * Because we do not have RCU_FAST_NO_HZ, don't bother initializing for it.
- */
-static void rcu_prepare_for_idle_init(int cpu)
-{
+	return rcu_cpu_has_callbacks(cpu, NULL);
 }
 
 /*
@@ -1577,16 +1580,6 @@ static void rcu_idle_count_callbacks_posted(void)
  *
  * The following three proprocessor symbols control this state machine:
  *
- * RCU_IDLE_FLUSHES gives the maximum number of times that we will attempt
- *	to satisfy RCU.  Beyond this point, it is better to incur a periodic
- *	scheduling-clock interrupt than to loop through the state machine
- *	at full power.
- * RCU_IDLE_OPT_FLUSHES gives the number of RCU_IDLE_FLUSHES that are
- *	optional if RCU does not need anything immediately from this
- *	CPU, even if this CPU still has RCU callbacks queued.  The first
- *	times through the state machine are mandatory: we need to give
- *	the state machine a chance to communicate a quiescent state
- *	to the RCU core.
  * RCU_IDLE_GP_DELAY gives the number of jiffies that a CPU is permitted
  *	to sleep in dyntick-idle mode with RCU callbacks pending.  This
  *	is sized to be roughly one RCU grace period.  Those energy-efficiency
@@ -1602,186 +1595,108 @@ static void rcu_idle_count_callbacks_posted(void)
  * adjustment, they can be converted into kernel config parameters, though
  * making the state machine smarter might be a better option.
  */
-#define RCU_IDLE_FLUSHES 5		/* Number of dyntick-idle tries. */
-#define RCU_IDLE_OPT_FLUSHES 3		/* Optional dyntick-idle tries. */
 #define RCU_IDLE_GP_DELAY 4		/* Roughly one grace period. */
 #define RCU_IDLE_LAZY_GP_DELAY (6 * HZ)	/* Roughly six seconds. */
 
-extern int tick_nohz_enabled;
-
-/*
- * Does the specified flavor of RCU have non-lazy callbacks pending on
- * the specified CPU?  Both RCU flavor and CPU are specified by the
- * rcu_data structure.
- */
-static bool __rcu_cpu_has_nonlazy_callbacks(struct rcu_data *rdp)
-{
-	return rdp->qlen != rdp->qlen_lazy;
-}
+static int rcu_idle_gp_delay = RCU_IDLE_GP_DELAY;
+module_param(rcu_idle_gp_delay, int, 0644);
+static int rcu_idle_lazy_gp_delay = RCU_IDLE_LAZY_GP_DELAY;
+module_param(rcu_idle_lazy_gp_delay, int, 0644);
 
-#ifdef CONFIG_TREE_PREEMPT_RCU
+extern int tick_nohz_enabled;
 
 /*
- * Are there non-lazy RCU-preempt callbacks?  (There cannot be if there
- * is no RCU-preempt in the kernel.)
+ * Try to advance callbacks for all flavors of RCU on the current CPU.
+ * Afterwards, if there are any callbacks ready for immediate invocation,
+ * return true.
  */
-static bool rcu_preempt_cpu_has_nonlazy_callbacks(int cpu)
+static bool rcu_try_advance_all_cbs(void)
 {
-	struct rcu_data *rdp = &per_cpu(rcu_preempt_data, cpu);
-
-	return __rcu_cpu_has_nonlazy_callbacks(rdp);
-}
-
-#else /* #ifdef CONFIG_TREE_PREEMPT_RCU */
+	bool cbs_ready = false;
+	struct rcu_data *rdp;
+	struct rcu_node *rnp;
+	struct rcu_state *rsp;
 
-static bool rcu_preempt_cpu_has_nonlazy_callbacks(int cpu)
-{
-	return 0;
-}
+	for_each_rcu_flavor(rsp) {
+		rdp = this_cpu_ptr(rsp->rda);
+		rnp = rdp->mynode;
 
-#endif /* else #ifdef CONFIG_TREE_PREEMPT_RCU */
+		/*
+		 * Don't bother checking unless a grace period has
+		 * completed since we last checked and there are
+		 * callbacks not yet ready to invoke.
+		 */
+		if (rdp->completed != rnp->completed &&
+		    rdp->nxttail[RCU_DONE_TAIL] != rdp->nxttail[RCU_NEXT_TAIL])
+			rcu_process_gp_end(rsp, rdp);
 
-/*
- * Does any flavor of RCU have non-lazy callbacks on the specified CPU?
- */
-static bool rcu_cpu_has_nonlazy_callbacks(int cpu)
-{
-	return __rcu_cpu_has_nonlazy_callbacks(&per_cpu(rcu_sched_data, cpu)) ||
-	       __rcu_cpu_has_nonlazy_callbacks(&per_cpu(rcu_bh_data, cpu)) ||
-	       rcu_preempt_cpu_has_nonlazy_callbacks(cpu);
+		if (cpu_has_callbacks_ready_to_invoke(rdp))
+			cbs_ready = true;
+	}
+	return cbs_ready;
 }
 
 /*
- * Allow the CPU to enter dyntick-idle mode if either: (1) There are no
- * callbacks on this CPU, (2) this CPU has not yet attempted to enter
- * dyntick-idle mode, or (3) this CPU is in the process of attempting to
- * enter dyntick-idle mode.  Otherwise, if we have recently tried and failed
- * to enter dyntick-idle mode, we refuse to try to enter it.  After all,
- * it is better to incur scheduling-clock interrupts than to spin
- * continuously for the same time duration!
+ * Allow the CPU to enter dyntick-idle mode unless it has callbacks ready
+ * to invoke.  If the CPU has callbacks, try to advance them.  Tell the
+ * caller to set the timeout based on whether or not there are non-lazy
+ * callbacks.
  *
- * The delta_jiffies argument is used to store the time when RCU is
- * going to need the CPU again if it still has callbacks.  The reason
- * for this is that rcu_prepare_for_idle() might need to post a timer,
- * but if so, it will do so after tick_nohz_stop_sched_tick() has set
- * the wakeup time for this CPU.  This means that RCU's timer can be
- * delayed until the wakeup time, which defeats the purpose of posting
- * a timer.
+ * The caller must have disabled interrupts.
  */
-int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies)
+int rcu_needs_cpu(int cpu, unsigned long *dj)
 {
 	struct rcu_dynticks *rdtp = &per_cpu(rcu_dynticks, cpu);
 
-	/* Flag a new idle sojourn to the idle-entry state machine. */
-	rdtp->idle_first_pass = 1;
+	/* Snapshot to detect later posting of non-lazy callback. */
+	rdtp->nonlazy_posted_snap = rdtp->nonlazy_posted;
+
 	/* If no callbacks, RCU doesn't need the CPU. */
-	if (!rcu_cpu_has_callbacks(cpu)) {
-		*delta_jiffies = ULONG_MAX;
+	if (!rcu_cpu_has_callbacks(cpu, &rdtp->all_lazy)) {
+		*dj = ULONG_MAX;
 		return 0;
 	}
-	if (rdtp->dyntick_holdoff == jiffies) {
-		/* RCU recently tried and failed, so don't try again. */
-		*delta_jiffies = 1;
+
+	/* Attempt to advance callbacks. */
+	if (rcu_try_advance_all_cbs()) {
+		/* Some ready to invoke, so initiate later invocation. */
+		invoke_rcu_core();
 		return 1;
 	}
-	/* Set up for the possibility that RCU will post a timer. */
-	if (rcu_cpu_has_nonlazy_callbacks(cpu)) {
-		*delta_jiffies = round_up(RCU_IDLE_GP_DELAY + jiffies,
-					  RCU_IDLE_GP_DELAY) - jiffies;
+	rdtp->last_accelerate = jiffies;
+
+	/* Request timer delay depending on laziness, and round. */
+	if (rdtp->all_lazy) {
+		*dj = round_up(rcu_idle_gp_delay + jiffies,
+			       rcu_idle_gp_delay) - jiffies;
 	} else {
-		*delta_jiffies = jiffies + RCU_IDLE_LAZY_GP_DELAY;
-		*delta_jiffies = round_jiffies(*delta_jiffies) - jiffies;
+		*dj = round_jiffies(rcu_idle_lazy_gp_delay + jiffies) - jiffies;
 	}
 	return 0;
 }
 
 /*
- * Handler for smp_call_function_single().  The only point of this
- * handler is to wake the CPU up, so the handler does only tracing.
- */
-void rcu_idle_demigrate(void *unused)
-{
-	trace_rcu_prep_idle("Demigrate");
-}
-
-/*
- * Timer handler used to force CPU to start pushing its remaining RCU
- * callbacks in the case where it entered dyntick-idle mode with callbacks
- * pending.  The hander doesn't really need to do anything because the
- * real work is done upon re-entry to idle, or by the next scheduling-clock
- * interrupt should idle not be re-entered.
- *
- * One special case: the timer gets migrated without awakening the CPU
- * on which the timer was scheduled on.  In this case, we must wake up
- * that CPU.  We do so with smp_call_function_single().
- */
-static void rcu_idle_gp_timer_func(unsigned long cpu_in)
-{
-	int cpu = (int)cpu_in;
-
-	trace_rcu_prep_idle("Timer");
-	if (cpu != smp_processor_id())
-		smp_call_function_single(cpu, rcu_idle_demigrate, NULL, 0);
-	else
-		WARN_ON_ONCE(1); /* Getting here can hang the system... */
-}
-
-/*
- * Initialize the timer used to pull CPUs out of dyntick-idle mode.
- */
-static void rcu_prepare_for_idle_init(int cpu)
-{
-	struct rcu_dynticks *rdtp = &per_cpu(rcu_dynticks, cpu);
-
-	rdtp->dyntick_holdoff = jiffies - 1;
-	setup_timer(&rdtp->idle_gp_timer, rcu_idle_gp_timer_func, cpu);
-	rdtp->idle_gp_timer_expires = jiffies - 1;
-	rdtp->idle_first_pass = 1;
-}
-
-/*
- * Clean up for exit from idle.  Because we are exiting from idle, there
- * is no longer any point to ->idle_gp_timer, so cancel it.  This will
- * do nothing if this timer is not active, so just cancel it unconditionally.
- */
-static void rcu_cleanup_after_idle(int cpu)
-{
-	struct rcu_dynticks *rdtp = &per_cpu(rcu_dynticks, cpu);
-
-	del_timer(&rdtp->idle_gp_timer);
-	trace_rcu_prep_idle("Cleanup after idle");
-	rdtp->tick_nohz_enabled_snap = ACCESS_ONCE(tick_nohz_enabled);
-}
-
-/*
- * Check to see if any RCU-related work can be done by the current CPU,
- * and if so, schedule a softirq to get it done.  This function is part
- * of the RCU implementation; it is -not- an exported member of the RCU API.
- *
- * The idea is for the current CPU to clear out all work required by the
- * RCU core for the current grace period, so that this CPU can be permitted
- * to enter dyntick-idle mode.  In some cases, it will need to be awakened
- * at the end of the grace period by whatever CPU ends the grace period.
- * This allows CPUs to go dyntick-idle more quickly, and to reduce the
- * number of wakeups by a modest integer factor.
- *
- * Because it is not legal to invoke rcu_process_callbacks() with irqs
- * disabled, we do one pass of force_quiescent_state(), then do a
- * invoke_rcu_core() to cause rcu_process_callbacks() to be invoked
- * later.  The ->dyntick_drain field controls the sequencing.
+ * Prepare a CPU for idle from an RCU perspective.  The first major task
+ * is to sense whether nohz mode has been enabled or disabled via sysfs.
+ * The second major task is to check to see if a non-lazy callback has
+ * arrived at a CPU that previously had only lazy callbacks.  The third
+ * major task is to accelerate (that is, assign grace-period numbers to)
+ * any recently arrived callbacks.
  *
  * The caller must have disabled interrupts.
  */
 static void rcu_prepare_for_idle(int cpu)
 {
-	struct timer_list *tp;
+	struct rcu_data *rdp;
 	struct rcu_dynticks *rdtp = &per_cpu(rcu_dynticks, cpu);
+	struct rcu_node *rnp;
+	struct rcu_state *rsp;
 	int tne;
 
 	/* Handle nohz enablement switches conservatively. */
 	tne = ACCESS_ONCE(tick_nohz_enabled);
 	if (tne != rdtp->tick_nohz_enabled_snap) {
-		if (rcu_cpu_has_callbacks(cpu))
+		if (rcu_cpu_has_callbacks(cpu, NULL))
 			invoke_rcu_core(); /* force nohz to see update. */
 		rdtp->tick_nohz_enabled_snap = tne;
 		return;
@@ -1789,125 +1704,56 @@ static void rcu_prepare_for_idle(int cpu)
 	if (!tne)
 		return;
 
-	/* Adaptive-tick mode, where usermode execution is idle to RCU. */
-	if (!is_idle_task(current)) {
-		rdtp->dyntick_holdoff = jiffies - 1;
-		if (rcu_cpu_has_nonlazy_callbacks(cpu)) {
-			trace_rcu_prep_idle("User dyntick with callbacks");
-			rdtp->idle_gp_timer_expires =
-				round_up(jiffies + RCU_IDLE_GP_DELAY,
-					 RCU_IDLE_GP_DELAY);
-		} else if (rcu_cpu_has_callbacks(cpu)) {
-			rdtp->idle_gp_timer_expires =
-				round_jiffies(jiffies + RCU_IDLE_LAZY_GP_DELAY);
-			trace_rcu_prep_idle("User dyntick with lazy callbacks");
-		} else {
-			return;
-		}
-		tp = &rdtp->idle_gp_timer;
-		mod_timer_pinned(tp, rdtp->idle_gp_timer_expires);
+	/* If this is a no-CBs CPU, no callbacks, just return. */
+	if (is_nocb_cpu(cpu))
 		return;
-	}
 
 	/*
-	 * If this is an idle re-entry, for example, due to use of
-	 * RCU_NONIDLE() or the new idle-loop tracing API within the idle
-	 * loop, then don't take any state-machine actions, unless the
-	 * momentary exit from idle queued additional non-lazy callbacks.
-	 * Instead, repost the ->idle_gp_timer if this CPU has callbacks
-	 * pending.
+	 * If a non-lazy callback arrived at a CPU having only lazy
+	 * callbacks, invoke RCU core for the side-effect of recalculating
+	 * idle duration on re-entry to idle.
 	 */
-	if (!rdtp->idle_first_pass &&
-	    (rdtp->nonlazy_posted == rdtp->nonlazy_posted_snap)) {
-		if (rcu_cpu_has_callbacks(cpu)) {
-			tp = &rdtp->idle_gp_timer;
-			mod_timer_pinned(tp, rdtp->idle_gp_timer_expires);
-		}
+	if (rdtp->all_lazy &&
+	    rdtp->nonlazy_posted != rdtp->nonlazy_posted_snap) {
+		invoke_rcu_core();
 		return;
 	}
-	rdtp->idle_first_pass = 0;
-	rdtp->nonlazy_posted_snap = rdtp->nonlazy_posted - 1;
 
 	/*
-	 * If there are no callbacks on this CPU, enter dyntick-idle mode.
-	 * Also reset state to avoid prejudicing later attempts.
+	 * If we have not yet accelerated this jiffy, accelerate all
+	 * callbacks on this CPU.
 	 */
-	if (!rcu_cpu_has_callbacks(cpu)) {
-		rdtp->dyntick_holdoff = jiffies - 1;
-		rdtp->dyntick_drain = 0;
-		trace_rcu_prep_idle("No callbacks");
+	if (rdtp->last_accelerate == jiffies)
 		return;
+	rdtp->last_accelerate = jiffies;
+	for_each_rcu_flavor(rsp) {
+		rdp = per_cpu_ptr(rsp->rda, cpu);
+		if (!*rdp->nxttail[RCU_DONE_TAIL])
+			continue;
+		rnp = rdp->mynode;
+		raw_spin_lock(&rnp->lock); /* irqs already disabled. */
+		rcu_accelerate_cbs(rsp, rnp, rdp);
+		raw_spin_unlock(&rnp->lock); /* irqs remain disabled. */
 	}
+}
 
-	/*
-	 * If in holdoff mode, just return.  We will presumably have
-	 * refrained from disabling the scheduling-clock tick.
-	 */
-	if (rdtp->dyntick_holdoff == jiffies) {
-		trace_rcu_prep_idle("In holdoff");
-		return;
-	}
+/*
+ * Clean up for exit from idle.  Attempt to advance callbacks based on
+ * any grace periods that elapsed while the CPU was idle, and if any
+ * callbacks are now ready to invoke, initiate invocation.
+ */
+static void rcu_cleanup_after_idle(int cpu)
+{
+	struct rcu_data *rdp;
+	struct rcu_state *rsp;
 
-	/* Check and update the ->dyntick_drain sequencing. */
-	if (rdtp->dyntick_drain <= 0) {
-		/* First time through, initialize the counter. */
-		rdtp->dyntick_drain = RCU_IDLE_FLUSHES;
-	} else if (rdtp->dyntick_drain <= RCU_IDLE_OPT_FLUSHES &&
-		   !rcu_pending(cpu) &&
-		   !local_softirq_pending()) {
-		/* Can we go dyntick-idle despite still having callbacks? */
-		rdtp->dyntick_drain = 0;
-		rdtp->dyntick_holdoff = jiffies;
-		if (rcu_cpu_has_nonlazy_callbacks(cpu)) {
-			trace_rcu_prep_idle("Dyntick with callbacks");
-			rdtp->idle_gp_timer_expires =
-				round_up(jiffies + RCU_IDLE_GP_DELAY,
-					 RCU_IDLE_GP_DELAY);
-		} else {
-			rdtp->idle_gp_timer_expires =
-				round_jiffies(jiffies + RCU_IDLE_LAZY_GP_DELAY);
-			trace_rcu_prep_idle("Dyntick with lazy callbacks");
-		}
-		tp = &rdtp->idle_gp_timer;
-		mod_timer_pinned(tp, rdtp->idle_gp_timer_expires);
-		rdtp->nonlazy_posted_snap = rdtp->nonlazy_posted;
-		return; /* Nothing more to do immediately. */
-	} else if (--(rdtp->dyntick_drain) <= 0) {
-		/* We have hit the limit, so time to give up. */
-		rdtp->dyntick_holdoff = jiffies;
-		trace_rcu_prep_idle("Begin holdoff");
-		invoke_rcu_core();  /* Force the CPU out of dyntick-idle. */
+	if (is_nocb_cpu(cpu))
 		return;
-	}
-
-	/*
-	 * Do one step of pushing the remaining RCU callbacks through
-	 * the RCU core state machine.
-	 */
-#ifdef CONFIG_TREE_PREEMPT_RCU
-	if (per_cpu(rcu_preempt_data, cpu).nxtlist) {
-		rcu_preempt_qs(cpu);
-		force_quiescent_state(&rcu_preempt_state);
-	}
-#endif /* #ifdef CONFIG_TREE_PREEMPT_RCU */
-	if (per_cpu(rcu_sched_data, cpu).nxtlist) {
-		rcu_sched_qs(cpu);
-		force_quiescent_state(&rcu_sched_state);
-	}
-	if (per_cpu(rcu_bh_data, cpu).nxtlist) {
-		rcu_bh_qs(cpu);
-		force_quiescent_state(&rcu_bh_state);
-	}
-
-	/*
-	 * If RCU callbacks are still pending, RCU still needs this CPU.
-	 * So try forcing the callbacks through the grace period.
-	 */
-	if (rcu_cpu_has_callbacks(cpu)) {
-		trace_rcu_prep_idle("More callbacks");
-		invoke_rcu_core();
-	} else {
-		trace_rcu_prep_idle("Callbacks drained");
+	rcu_try_advance_all_cbs();
+	for_each_rcu_flavor(rsp) {
+		rdp = per_cpu_ptr(rsp->rda, cpu);
+		if (cpu_has_callbacks_ready_to_invoke(rdp))
+			invoke_rcu_core();
 	}
 }
 
@@ -2015,16 +1861,13 @@ early_initcall(rcu_register_oom_notifier);
 static void print_cpu_stall_fast_no_hz(char *cp, int cpu)
 {
 	struct rcu_dynticks *rdtp = &per_cpu(rcu_dynticks, cpu);
-	struct timer_list *tltp = &rdtp->idle_gp_timer;
-	char c;
+	unsigned long nlpd = rdtp->nonlazy_posted - rdtp->nonlazy_posted_snap;
 
-	c = rdtp->dyntick_holdoff == jiffies ? 'H' : '.';
-	if (timer_pending(tltp))
-		sprintf(cp, "drain=%d %c timer=%lu",
-			rdtp->dyntick_drain, c, tltp->expires - jiffies);
-	else
-		sprintf(cp, "drain=%d %c timer not pending",
-			rdtp->dyntick_drain, c);
+	sprintf(cp, "last_accelerate: %04lx/%04lx, nonlazy_posted: %ld, %c%c",
+		rdtp->last_accelerate & 0xffff, jiffies & 0xffff,
+		ulong2long(nlpd),
+		rdtp->all_lazy ? 'L' : '.',
+		rdtp->tick_nohz_enabled_snap ? '.' : 'D');
 }
 
 #else /* #ifdef CONFIG_RCU_FAST_NO_HZ */
@@ -2070,10 +1913,11 @@ static void print_cpu_stall_info(struct rcu_state *rsp, int cpu)
 		ticks_value = rsp->gpnum - rdp->gpnum;
 	}
 	print_cpu_stall_fast_no_hz(fast_no_hz, cpu);
-	printk(KERN_ERR "\t%d: (%lu %s) idle=%03x/%llx/%d %s\n",
+	printk(KERN_ERR "\t%d: (%lu %s) idle=%03x/%llx/%d softirq=%u/%u %s\n",
 	       cpu, ticks_value, ticks_title,
 	       atomic_read(&rdtp->dynticks) & 0xfff,
 	       rdtp->dynticks_nesting, rdtp->dynticks_nmi_nesting,
+	       rdp->softirq_snap, kstat_softirqs_cpu(RCU_SOFTIRQ, cpu),
 	       fast_no_hz);
 }
 
@@ -2087,6 +1931,7 @@ static void print_cpu_stall_info_end(void)
 static void zero_cpu_stall_ticks(struct rcu_data *rdp)
 {
 	rdp->ticks_this_gp = 0;
+	rdp->softirq_snap = kstat_softirqs_cpu(RCU_SOFTIRQ, smp_processor_id());
 }
 
 /* Increment ->ticks_this_gp for all flavors of RCU. */
@@ -2165,6 +2010,47 @@ static int __init parse_rcu_nocb_poll(char *arg)
 }
 early_param("rcu_nocb_poll", parse_rcu_nocb_poll);
 
+/*
+ * Do any no-CBs CPUs need another grace period?
+ *
+ * Interrupts must be disabled.  If the caller does not hold the root
+ * rnp_node structure's ->lock, the results are advisory only.
+ */
+static int rcu_nocb_needs_gp(struct rcu_state *rsp)
+{
+	struct rcu_node *rnp = rcu_get_root(rsp);
+
+	return rnp->need_future_gp[(ACCESS_ONCE(rnp->completed) + 1) & 0x1];
+}
+
+/*
+ * Wake up any no-CBs CPUs' kthreads that were waiting on the just-ended
+ * grace period.
+ */
+static void rcu_nocb_gp_cleanup(struct rcu_state *rsp, struct rcu_node *rnp)
+{
+	wake_up_all(&rnp->nocb_gp_wq[rnp->completed & 0x1]);
+}
+
+/*
+ * Set the root rcu_node structure's ->need_future_gp field
+ * based on the sum of those of all rcu_node structures.  This does
+ * double-count the root rcu_node structure's requests, but this
+ * is necessary to handle the possibility of a rcu_nocb_kthread()
+ * having awakened during the time that the rcu_node structures
+ * were being updated for the end of the previous grace period.
+ */
+static void rcu_nocb_gp_set(struct rcu_node *rnp, int nrq)
+{
+	rnp->need_future_gp[(rnp->completed + 1) & 0x1] += nrq;
+}
+
+static void rcu_init_one_nocb(struct rcu_node *rnp)
+{
+	init_waitqueue_head(&rnp->nocb_gp_wq[0]);
+	init_waitqueue_head(&rnp->nocb_gp_wq[1]);
+}
+
 /* Is the specified CPU a no-CPUs CPU? */
 static bool is_nocb_cpu(int cpu)
 {
@@ -2227,6 +2113,13 @@ static bool __call_rcu_nocb(struct rcu_data *rdp, struct rcu_head *rhp,
 	if (!is_nocb_cpu(rdp->cpu))
 		return 0;
 	__call_rcu_nocb_enqueue(rdp, rhp, &rhp->next, 1, lazy);
+	if (__is_kfree_rcu_offset((unsigned long)rhp->func))
+		trace_rcu_kfree_callback(rdp->rsp->name, rhp,
+					 (unsigned long)rhp->func,
+					 rdp->qlen_lazy, rdp->qlen);
+	else
+		trace_rcu_callback(rdp->rsp->name, rhp,
+				   rdp->qlen_lazy, rdp->qlen);
 	return 1;
 }
 
@@ -2265,95 +2158,36 @@ static bool __maybe_unused rcu_nocb_adopt_orphan_cbs(struct rcu_state *rsp,
 }
 
 /*
- * There must be at least one non-no-CBs CPU in operation at any given
- * time, because no-CBs CPUs are not capable of initiating grace periods
- * independently.  This function therefore complains if the specified
- * CPU is the last non-no-CBs CPU, allowing the CPU-hotplug system to
- * avoid offlining the last such CPU.  (Recursion is a wonderful thing,
- * but you have to have a base case!)
+ * If necessary, kick off a new grace period, and either way wait
+ * for a subsequent grace period to complete.
  */
-static bool nocb_cpu_expendable(int cpu)
+static void rcu_nocb_wait_gp(struct rcu_data *rdp)
 {
-	cpumask_var_t non_nocb_cpus;
-	int ret;
+	unsigned long c;
+	bool d;
+	unsigned long flags;
+	struct rcu_node *rnp = rdp->mynode;
+
+	raw_spin_lock_irqsave(&rnp->lock, flags);
+	c = rcu_start_future_gp(rnp, rdp);
+	raw_spin_unlock_irqrestore(&rnp->lock, flags);
 
 	/*
-	 * If there are no no-CB CPUs or if this CPU is not a no-CB CPU,
-	 * then offlining this CPU is harmless.  Let it happen.
+	 * Wait for the grace period.  Do so interruptibly to avoid messing
+	 * up the load average.
 	 */
-	if (!have_rcu_nocb_mask || is_nocb_cpu(cpu))
-		return 1;
-
-	/* If no memory, play it safe and keep the CPU around. */
-	if (!alloc_cpumask_var(&non_nocb_cpus, GFP_NOIO))
-		return 0;
-	cpumask_andnot(non_nocb_cpus, cpu_online_mask, rcu_nocb_mask);
-	cpumask_clear_cpu(cpu, non_nocb_cpus);
-	ret = !cpumask_empty(non_nocb_cpus);
-	free_cpumask_var(non_nocb_cpus);
-	return ret;
-}
-
-/*
- * Helper structure for remote registry of RCU callbacks.
- * This is needed for when a no-CBs CPU needs to start a grace period.
- * If it just invokes call_rcu(), the resulting callback will be queued,
- * which can result in deadlock.
- */
-struct rcu_head_remote {
-	struct rcu_head *rhp;
-	call_rcu_func_t *crf;
-	void (*func)(struct rcu_head *rhp);
-};
-
-/*
- * Register a callback as specified by the rcu_head_remote struct.
- * This function is intended to be invoked via smp_call_function_single().
- */
-static void call_rcu_local(void *arg)
-{
-	struct rcu_head_remote *rhrp =
-		container_of(arg, struct rcu_head_remote, rhp);
-
-	rhrp->crf(rhrp->rhp, rhrp->func);
-}
-
-/*
- * Set up an rcu_head_remote structure and the invoke call_rcu_local()
- * on CPU 0 (which is guaranteed to be a non-no-CBs CPU) via
- * smp_call_function_single().
- */
-static void invoke_crf_remote(struct rcu_head *rhp,
-			      void (*func)(struct rcu_head *rhp),
-			      call_rcu_func_t crf)
-{
-	struct rcu_head_remote rhr;
-
-	rhr.rhp = rhp;
-	rhr.crf = crf;
-	rhr.func = func;
-	smp_call_function_single(0, call_rcu_local, &rhr, 1);
-}
-
-/*
- * Helper functions to be passed to wait_rcu_gp(), each of which
- * invokes invoke_crf_remote() to register a callback appropriately.
- */
-static void __maybe_unused
-call_rcu_preempt_remote(struct rcu_head *rhp,
-			void (*func)(struct rcu_head *rhp))
-{
-	invoke_crf_remote(rhp, func, call_rcu);
-}
-static void call_rcu_bh_remote(struct rcu_head *rhp,
-			       void (*func)(struct rcu_head *rhp))
-{
-	invoke_crf_remote(rhp, func, call_rcu_bh);
-}
-static void call_rcu_sched_remote(struct rcu_head *rhp,
-				  void (*func)(struct rcu_head *rhp))
-{
-	invoke_crf_remote(rhp, func, call_rcu_sched);
+	trace_rcu_future_gp(rnp, rdp, c, "StartWait");
+	for (;;) {
+		wait_event_interruptible(
+			rnp->nocb_gp_wq[c & 0x1],
+			(d = ULONG_CMP_GE(ACCESS_ONCE(rnp->completed), c)));
+		if (likely(d))
+			break;
+		flush_signals(current);
+		trace_rcu_future_gp(rnp, rdp, c, "ResumeWait");
+	}
+	trace_rcu_future_gp(rnp, rdp, c, "EndWait");
+	smp_mb(); /* Ensure that CB invocation happens after GP end. */
 }
 
 /*
@@ -2390,7 +2224,7 @@ static int rcu_nocb_kthread(void *arg)
 		cl = atomic_long_xchg(&rdp->nocb_q_count_lazy, 0);
 		ACCESS_ONCE(rdp->nocb_p_count) += c;
 		ACCESS_ONCE(rdp->nocb_p_count_lazy) += cl;
-		wait_rcu_gp(rdp->rsp->call_remote);
+		rcu_nocb_wait_gp(rdp);
 
 		/* Each pass through the following loop invokes a callback. */
 		trace_rcu_batch_start(rdp->rsp->name, cl, c, -1);
@@ -2436,32 +2270,41 @@ static void __init rcu_spawn_nocb_kthreads(struct rcu_state *rsp)
 		return;
 	for_each_cpu(cpu, rcu_nocb_mask) {
 		rdp = per_cpu_ptr(rsp->rda, cpu);
-		t = kthread_run(rcu_nocb_kthread, rdp, "rcuo%d", cpu);
+		t = kthread_run(rcu_nocb_kthread, rdp,
+				"rcuo%c/%d", rsp->abbr, cpu);
 		BUG_ON(IS_ERR(t));
 		ACCESS_ONCE(rdp->nocb_kthread) = t;
 	}
 }
 
 /* Prevent __call_rcu() from enqueuing callbacks on no-CBs CPUs */
-static void init_nocb_callback_list(struct rcu_data *rdp)
+static bool init_nocb_callback_list(struct rcu_data *rdp)
 {
 	if (rcu_nocb_mask == NULL ||
 	    !cpumask_test_cpu(rdp->cpu, rcu_nocb_mask))
-		return;
+		return false;
 	rdp->nxttail[RCU_NEXT_TAIL] = NULL;
+	return true;
+}
+
+#else /* #ifdef CONFIG_RCU_NOCB_CPU */
+
+static int rcu_nocb_needs_gp(struct rcu_state *rsp)
+{
+	return 0;
 }
 
-/* Initialize the ->call_remote fields in the rcu_state structures. */
-static void __init rcu_init_nocb(void)
+static void rcu_nocb_gp_cleanup(struct rcu_state *rsp, struct rcu_node *rnp)
 {
-#ifdef CONFIG_PREEMPT_RCU
-	rcu_preempt_state.call_remote = call_rcu_preempt_remote;
-#endif /* #ifdef CONFIG_PREEMPT_RCU */
-	rcu_bh_state.call_remote = call_rcu_bh_remote;
-	rcu_sched_state.call_remote = call_rcu_sched_remote;
 }
 
-#else /* #ifdef CONFIG_RCU_NOCB_CPU */
+static void rcu_nocb_gp_set(struct rcu_node *rnp, int nrq)
+{
+}
+
+static void rcu_init_one_nocb(struct rcu_node *rnp)
+{
+}
 
 static bool is_nocb_cpu(int cpu)
 {
@@ -2480,11 +2323,6 @@ static bool __maybe_unused rcu_nocb_adopt_orphan_cbs(struct rcu_state *rsp,
 	return 0;
 }
 
-static bool nocb_cpu_expendable(int cpu)
-{
-	return 1;
-}
-
 static void __init rcu_boot_init_nocb_percpu_data(struct rcu_data *rdp)
 {
 }
@@ -2493,12 +2331,9 @@ static void __init rcu_spawn_nocb_kthreads(struct rcu_state *rsp)
 {
 }
 
-static void init_nocb_callback_list(struct rcu_data *rdp)
-{
-}
-
-static void __init rcu_init_nocb(void)
+static bool init_nocb_callback_list(struct rcu_data *rdp)
 {
+	return false;
 }
 
 #endif /* #else #ifdef CONFIG_RCU_NOCB_CPU */
diff --git a/kernel/rcutree_trace.c b/kernel/rcutree_trace.c
index 0d095dc..49099e8 100644
--- a/kernel/rcutree_trace.c
+++ b/kernel/rcutree_trace.c
@@ -46,8 +46,6 @@
 #define RCU_TREE_NONCORE
 #include "rcutree.h"
 
-#define ulong2long(a) (*(long *)(&(a)))
-
 static int r_open(struct inode *inode, struct file *file,
 					const struct seq_operations *op)
 {
diff --git a/kernel/relay.c b/kernel/relay.c
index 01ab081..eef0d11 100644
--- a/kernel/relay.c
+++ b/kernel/relay.c
@@ -588,7 +588,7 @@ struct rchan *relay_open(const char *base_filename,
 	chan->version = RELAYFS_CHANNEL_VERSION;
 	chan->n_subbufs = n_subbufs;
 	chan->subbuf_size = subbuf_size;
-	chan->alloc_size = FIX_SIZE(subbuf_size * n_subbufs);
+	chan->alloc_size = PAGE_ALIGN(subbuf_size * n_subbufs);
 	chan->parent = parent;
 	chan->private_data = private_data;
 	if (base_filename) {
@@ -1099,8 +1099,7 @@ static size_t relay_file_read_end_pos(struct rchan_buf *buf,
 static int subbuf_read_actor(size_t read_start,
 			     struct rchan_buf *buf,
 			     size_t avail,
-			     read_descriptor_t *desc,
-			     read_actor_t actor)
+			     read_descriptor_t *desc)
 {
 	void *from;
 	int ret = 0;
@@ -1121,15 +1120,13 @@ static int subbuf_read_actor(size_t read_start,
 typedef int (*subbuf_actor_t) (size_t read_start,
 			       struct rchan_buf *buf,
 			       size_t avail,
-			       read_descriptor_t *desc,
-			       read_actor_t actor);
+			       read_descriptor_t *desc);
 
 /*
  *	relay_file_read_subbufs - read count bytes, bridging subbuf boundaries
  */
 static ssize_t relay_file_read_subbufs(struct file *filp, loff_t *ppos,
 					subbuf_actor_t subbuf_actor,
-					read_actor_t actor,
 					read_descriptor_t *desc)
 {
 	struct rchan_buf *buf = filp->private_data;
@@ -1150,7 +1147,7 @@ static ssize_t relay_file_read_subbufs(struct file *filp, loff_t *ppos,
 			break;
 
 		avail = min(desc->count, avail);
-		ret = subbuf_actor(read_start, buf, avail, desc, actor);
+		ret = subbuf_actor(read_start, buf, avail, desc);
 		if (desc->error < 0)
 			break;
 
@@ -1174,8 +1171,7 @@ static ssize_t relay_file_read(struct file *filp,
 	desc.count = count;
 	desc.arg.buf = buffer;
 	desc.error = 0;
-	return relay_file_read_subbufs(filp, ppos, subbuf_read_actor,
-				       NULL, &desc);
+	return relay_file_read_subbufs(filp, ppos, subbuf_read_actor, &desc);
 }
 
 static void relay_consume_bytes(struct rchan_buf *rbuf, int bytes_consumed)
diff --git a/kernel/rtmutex-tester.c b/kernel/rtmutex-tester.c
index 7890b10..55ad765 100644
--- a/kernel/rtmutex-tester.c
+++ b/kernel/rtmutex-tester.c
@@ -366,8 +366,8 @@ static ssize_t sysfs_test_status(struct device *dev, struct device_attribute *at
 	return curr - buf;
 }
 
-static DEVICE_ATTR(status, 0600, sysfs_test_status, NULL);
-static DEVICE_ATTR(command, 0600, NULL, sysfs_test_command);
+static DEVICE_ATTR(status, 0400, sysfs_test_status, NULL);
+static DEVICE_ATTR(command, 0200, NULL, sysfs_test_command);
 
 static struct bus_type rttest_subsys = {
 	.name = "rttest",
diff --git a/kernel/rwsem.c b/kernel/rwsem.c
index b3c6c3f..cfff143 100644
--- a/kernel/rwsem.c
+++ b/kernel/rwsem.c
@@ -126,6 +126,15 @@ void _down_write_nest_lock(struct rw_semaphore *sem, struct lockdep_map *nest)
 
 EXPORT_SYMBOL(_down_write_nest_lock);
 
+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,6 +145,13 @@ 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/core.c b/kernel/sched/core.c
index 7f12624..286066e 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -3082,11 +3082,13 @@ EXPORT_SYMBOL(preempt_schedule);
 asmlinkage void __sched preempt_schedule_irq(void)
 {
 	struct thread_info *ti = current_thread_info();
+	enum ctx_state prev_state;
 
 	/* Catch callers which need to be fixed */
 	BUG_ON(ti->preempt_count || !irqs_disabled());
 
-	user_exit();
+	prev_state = exception_enter();
+
 	do {
 		add_preempt_count(PREEMPT_ACTIVE);
 		local_irq_enable();
@@ -3100,6 +3102,8 @@ asmlinkage void __sched preempt_schedule_irq(void)
 		 */
 		barrier();
 	} while (need_resched());
+
+	exception_exit(prev_state);
 }
 
 #endif /* CONFIG_PREEMPT */
@@ -4126,6 +4130,10 @@ long sched_setaffinity(pid_t pid, const struct cpumask *in_mask)
 	get_task_struct(p);
 	rcu_read_unlock();
 
+	if (p->flags & PF_NO_SETAFFINITY) {
+		retval = -EINVAL;
+		goto out_put_task;
+	}
 	if (!alloc_cpumask_var(&cpus_allowed, GFP_KERNEL)) {
 		retval = -ENOMEM;
 		goto out_put_task;
@@ -4773,11 +4781,6 @@ int set_cpus_allowed_ptr(struct task_struct *p, const struct cpumask *new_mask)
 		goto out;
 	}
 
-	if (unlikely((p->flags & PF_THREAD_BOUND) && p != current)) {
-		ret = -EINVAL;
-		goto out;
-	}
-
 	do_set_cpus_allowed(p, new_mask);
 
 	/* Can the task run on the task's current CPU? If so, we're done */
@@ -6861,6 +6864,10 @@ int in_sched_functions(unsigned long addr)
 }
 
 #ifdef CONFIG_CGROUP_SCHED
+/*
+ * Default task group.
+ * Every task in system belongs to this group at bootup.
+ */
 struct task_group root_task_group;
 LIST_HEAD(task_groups);
 #endif
@@ -7455,7 +7462,7 @@ unlock:
 	return err;
 }
 
-int sched_group_set_rt_runtime(struct task_group *tg, long rt_runtime_us)
+static int sched_group_set_rt_runtime(struct task_group *tg, long rt_runtime_us)
 {
 	u64 rt_runtime, rt_period;
 
@@ -7467,7 +7474,7 @@ int sched_group_set_rt_runtime(struct task_group *tg, long rt_runtime_us)
 	return tg_set_rt_bandwidth(tg, rt_period, rt_runtime);
 }
 
-long sched_group_rt_runtime(struct task_group *tg)
+static long sched_group_rt_runtime(struct task_group *tg)
 {
 	u64 rt_runtime_us;
 
@@ -7479,7 +7486,7 @@ long sched_group_rt_runtime(struct task_group *tg)
 	return rt_runtime_us;
 }
 
-int sched_group_set_rt_period(struct task_group *tg, long rt_period_us)
+static int sched_group_set_rt_period(struct task_group *tg, long rt_period_us)
 {
 	u64 rt_runtime, rt_period;
 
@@ -7492,7 +7499,7 @@ int sched_group_set_rt_period(struct task_group *tg, long rt_period_us)
 	return tg_set_rt_bandwidth(tg, rt_period, rt_runtime);
 }
 
-long sched_group_rt_period(struct task_group *tg)
+static long sched_group_rt_period(struct task_group *tg)
 {
 	u64 rt_period_us;
 
@@ -7527,7 +7534,7 @@ static int sched_rt_global_constraints(void)
 	return ret;
 }
 
-int sched_rt_can_attach(struct task_group *tg, struct task_struct *tsk)
+static int sched_rt_can_attach(struct task_group *tg, struct task_struct *tsk)
 {
 	/* Don't accept realtime tasks when there is no way for them to run */
 	if (rt_task(tsk) && tg->rt_bandwidth.rt_runtime == 0)
diff --git a/kernel/sched/cputime.c b/kernel/sched/cputime.c
index ed12cbb..024fe19 100644
--- a/kernel/sched/cputime.c
+++ b/kernel/sched/cputime.c
@@ -388,82 +388,10 @@ static inline void irqtime_account_process_tick(struct task_struct *p, int user_
 						struct rq *rq) {}
 #endif /* CONFIG_IRQ_TIME_ACCOUNTING */
 
-#ifndef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
-/*
- * Account a single tick of cpu time.
- * @p: the process that the cpu time gets accounted to
- * @user_tick: indicates if the tick is a user or a system tick
- */
-void account_process_tick(struct task_struct *p, int user_tick)
-{
-	cputime_t one_jiffy_scaled = cputime_to_scaled(cputime_one_jiffy);
-	struct rq *rq = this_rq();
-
-	if (vtime_accounting_enabled())
-		return;
-
-	if (sched_clock_irqtime) {
-		irqtime_account_process_tick(p, user_tick, rq);
-		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))
-		account_system_time(p, HARDIRQ_OFFSET, cputime_one_jiffy,
-				    one_jiffy_scaled);
-	else
-		account_idle_time(cputime_one_jiffy);
-}
-
-/*
- * Account multiple ticks of steal time.
- * @p: the process from which the cpu time has been stolen
- * @ticks: number of stolen ticks
- */
-void account_steal_ticks(unsigned long ticks)
-{
-	account_steal_time(jiffies_to_cputime(ticks));
-}
-
-/*
- * Account multiple ticks of idle time.
- * @ticks: number of stolen ticks
- */
-void account_idle_ticks(unsigned long ticks)
-{
-
-	if (sched_clock_irqtime) {
-		irqtime_account_idle_ticks(ticks);
-		return;
-	}
-
-	account_idle_time(jiffies_to_cputime(ticks));
-}
-#endif /* !CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */
-
 /*
  * Use precise platform statistics if available:
  */
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
-void task_cputime_adjusted(struct task_struct *p, cputime_t *ut, cputime_t *st)
-{
-	*ut = p->utime;
-	*st = p->stime;
-}
-
-void thread_group_cputime_adjusted(struct task_struct *p, cputime_t *ut, cputime_t *st)
-{
-	struct task_cputime cputime;
-
-	thread_group_cputime(p, &cputime);
-
-	*ut = cputime.utime;
-	*st = cputime.stime;
-}
 
 #ifndef __ARCH_HAS_VTIME_TASK_SWITCH
 void vtime_task_switch(struct task_struct *prev)
@@ -518,8 +446,80 @@ void vtime_account_irq_enter(struct task_struct *tsk)
 }
 EXPORT_SYMBOL_GPL(vtime_account_irq_enter);
 #endif /* __ARCH_HAS_VTIME_ACCOUNT */
+#endif /* CONFIG_VIRT_CPU_ACCOUNTING */
+
+
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
+void task_cputime_adjusted(struct task_struct *p, cputime_t *ut, cputime_t *st)
+{
+	*ut = p->utime;
+	*st = p->stime;
+}
 
-#else /* !CONFIG_VIRT_CPU_ACCOUNTING */
+void thread_group_cputime_adjusted(struct task_struct *p, cputime_t *ut, cputime_t *st)
+{
+	struct task_cputime cputime;
+
+	thread_group_cputime(p, &cputime);
+
+	*ut = cputime.utime;
+	*st = cputime.stime;
+}
+#else /* !CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */
+/*
+ * Account a single tick of cpu time.
+ * @p: the process that the cpu time gets accounted to
+ * @user_tick: indicates if the tick is a user or a system tick
+ */
+void account_process_tick(struct task_struct *p, int user_tick)
+{
+	cputime_t one_jiffy_scaled = cputime_to_scaled(cputime_one_jiffy);
+	struct rq *rq = this_rq();
+
+	if (vtime_accounting_enabled())
+		return;
+
+	if (sched_clock_irqtime) {
+		irqtime_account_process_tick(p, user_tick, rq);
+		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))
+		account_system_time(p, HARDIRQ_OFFSET, cputime_one_jiffy,
+				    one_jiffy_scaled);
+	else
+		account_idle_time(cputime_one_jiffy);
+}
+
+/*
+ * Account multiple ticks of steal time.
+ * @p: the process from which the cpu time has been stolen
+ * @ticks: number of stolen ticks
+ */
+void account_steal_ticks(unsigned long ticks)
+{
+	account_steal_time(jiffies_to_cputime(ticks));
+}
+
+/*
+ * Account multiple ticks of idle time.
+ * @ticks: number of stolen ticks
+ */
+void account_idle_ticks(unsigned long ticks)
+{
+
+	if (sched_clock_irqtime) {
+		irqtime_account_idle_ticks(ticks);
+		return;
+	}
+
+	account_idle_time(jiffies_to_cputime(ticks));
+}
 
 static cputime_t scale_stime(cputime_t stime, cputime_t rtime, cputime_t total)
 {
@@ -545,6 +545,12 @@ static void cputime_adjust(struct task_cputime *curr,
 {
 	cputime_t rtime, stime, total;
 
+	if (vtime_accounting_enabled()) {
+		*ut = curr->utime;
+		*st = curr->stime;
+		return;
+	}
+
 	stime = curr->stime;
 	total = stime + curr->utime;
 
@@ -597,7 +603,7 @@ void thread_group_cputime_adjusted(struct task_struct *p, cputime_t *ut, cputime
 	thread_group_cputime(p, &cputime);
 	cputime_adjust(&cputime, &p->signal->prev_cputime, ut, st);
 }
-#endif /* !CONFIG_VIRT_CPU_ACCOUNTING */
+#endif /* !CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */
 
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN
 static unsigned long long vtime_delta(struct task_struct *tsk)
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 7a33e59..9f23112 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -4245,7 +4245,7 @@ static inline int get_sd_load_idx(struct sched_domain *sd,
 	return load_idx;
 }
 
-unsigned long default_scale_freq_power(struct sched_domain *sd, int cpu)
+static unsigned long default_scale_freq_power(struct sched_domain *sd, int cpu)
 {
 	return SCHED_POWER_SCALE;
 }
@@ -4255,7 +4255,7 @@ unsigned long __weak arch_scale_freq_power(struct sched_domain *sd, int cpu)
 	return default_scale_freq_power(sd, cpu);
 }
 
-unsigned long default_scale_smt_power(struct sched_domain *sd, int cpu)
+static unsigned long default_scale_smt_power(struct sched_domain *sd, int cpu)
 {
 	unsigned long weight = sd->span_weight;
 	unsigned long smt_gain = sd->smt_gain;
@@ -4270,7 +4270,7 @@ unsigned long __weak arch_scale_smt_power(struct sched_domain *sd, int cpu)
 	return default_scale_smt_power(sd, cpu);
 }
 
-unsigned long scale_rt_power(int cpu)
+static unsigned long scale_rt_power(int cpu)
 {
 	struct rq *rq = cpu_rq(cpu);
 	u64 total, available, age_stamp, avg;
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index cc03cfd..3bd15a4 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -33,6 +33,31 @@ extern __read_mostly int scheduler_running;
  */
 #define NS_TO_JIFFIES(TIME)	((unsigned long)(TIME) / (NSEC_PER_SEC / HZ))
 
+/*
+ * Increase resolution of nice-level calculations for 64-bit architectures.
+ * The extra resolution improves shares distribution and load balancing of
+ * low-weight task groups (eg. nice +19 on an autogroup), deeper taskgroup
+ * hierarchies, especially on larger systems. This is not a user-visible change
+ * and does not change the user-interface for setting shares/weights.
+ *
+ * We increase resolution only if we have enough bits to allow this increased
+ * resolution (i.e. BITS_PER_LONG > 32). The costs for increasing resolution
+ * when BITS_PER_LONG <= 32 are pretty high and the returns do not justify the
+ * increased costs.
+ */
+#if 0 /* BITS_PER_LONG > 32 -- currently broken: it increases power usage under light load  */
+# define SCHED_LOAD_RESOLUTION	10
+# define scale_load(w)		((w) << SCHED_LOAD_RESOLUTION)
+# define scale_load_down(w)	((w) >> SCHED_LOAD_RESOLUTION)
+#else
+# define SCHED_LOAD_RESOLUTION	0
+# define scale_load(w)		(w)
+# define scale_load_down(w)	(w)
+#endif
+
+#define SCHED_LOAD_SHIFT	(10 + SCHED_LOAD_RESOLUTION)
+#define SCHED_LOAD_SCALE	(1L << SCHED_LOAD_SHIFT)
+
 #define NICE_0_LOAD		SCHED_LOAD_SCALE
 #define NICE_0_SHIFT		SCHED_LOAD_SHIFT
 
@@ -154,11 +179,6 @@ struct task_group {
 #define MAX_SHARES	(1UL << 18)
 #endif
 
-/* Default task group.
- *	Every task in system belong to this group at bootup.
- */
-extern struct task_group root_task_group;
-
 typedef int (*tg_visitor)(struct task_group *, void *);
 
 extern int walk_tg_tree_from(struct task_group *from,
@@ -196,6 +216,18 @@ extern void init_tg_rt_entry(struct task_group *tg, struct rt_rq *rt_rq,
 		struct sched_rt_entity *rt_se, int cpu,
 		struct sched_rt_entity *parent);
 
+extern struct task_group *sched_create_group(struct task_group *parent);
+extern void sched_online_group(struct task_group *tg,
+			       struct task_group *parent);
+extern void sched_destroy_group(struct task_group *tg);
+extern void sched_offline_group(struct task_group *tg);
+
+extern void sched_move_task(struct task_struct *tsk);
+
+#ifdef CONFIG_FAIR_GROUP_SCHED
+extern int sched_group_set_shares(struct task_group *tg, unsigned long shares);
+#endif
+
 #else /* CONFIG_CGROUP_SCHED */
 
 struct cfs_bandwidth { };
@@ -547,6 +579,62 @@ static inline struct sched_domain *highest_flag_domain(int cpu, int flag)
 DECLARE_PER_CPU(struct sched_domain *, sd_llc);
 DECLARE_PER_CPU(int, sd_llc_id);
 
+struct sched_group_power {
+	atomic_t ref;
+	/*
+	 * CPU power of this group, SCHED_LOAD_SCALE being max power for a
+	 * single CPU.
+	 */
+	unsigned int power, power_orig;
+	unsigned long next_update;
+	/*
+	 * Number of busy cpus in this group.
+	 */
+	atomic_t nr_busy_cpus;
+
+	unsigned long cpumask[0]; /* iteration mask */
+};
+
+struct sched_group {
+	struct sched_group *next;	/* Must be a circular list */
+	atomic_t ref;
+
+	unsigned int group_weight;
+	struct sched_group_power *sgp;
+
+	/*
+	 * The CPUs this group covers.
+	 *
+	 * NOTE: this field is variable length. (Allocated dynamically
+	 * by attaching extra space to the end of the structure,
+	 * depending on how many CPUs the kernel has booted up with)
+	 */
+	unsigned long cpumask[0];
+};
+
+static inline struct cpumask *sched_group_cpus(struct sched_group *sg)
+{
+	return to_cpumask(sg->cpumask);
+}
+
+/*
+ * cpumask masking which cpus in the group are allowed to iterate up the domain
+ * tree.
+ */
+static inline struct cpumask *sched_group_mask(struct sched_group *sg)
+{
+	return to_cpumask(sg->sgp->cpumask);
+}
+
+/**
+ * group_first_cpu - Returns the first cpu in the cpumask of a sched_group.
+ * @group: The group whose first cpu is to be returned.
+ */
+static inline unsigned int group_first_cpu(struct sched_group *group)
+{
+	return cpumask_first(sched_group_cpus(group));
+}
+
 extern int group_balance_cpu(struct sched_group *sg);
 
 #endif /* CONFIG_SMP */
@@ -784,6 +872,12 @@ static inline void finish_lock_switch(struct rq *rq, struct task_struct *prev)
 }
 #endif /* __ARCH_WANT_UNLOCKED_CTXSW */
 
+/*
+ * wake flags
+ */
+#define WF_SYNC		0x01		/* waker goes to sleep after wakeup */
+#define WF_FORK		0x02		/* child wakeup after fork */
+#define WF_MIGRATED	0x4		/* internal use, task got migrated */
 
 static inline void update_load_add(struct load_weight *lw, unsigned long inc)
 {
@@ -864,6 +958,61 @@ enum cpuacct_stat_index {
 	CPUACCT_STAT_NSTATS,
 };
 
+#define ENQUEUE_WAKEUP		1
+#define ENQUEUE_HEAD		2
+#ifdef CONFIG_SMP
+#define ENQUEUE_WAKING		4	/* sched_class::task_waking was called */
+#else
+#define ENQUEUE_WAKING		0
+#endif
+
+#define DEQUEUE_SLEEP		1
+
+struct sched_class {
+	const struct sched_class *next;
+
+	void (*enqueue_task) (struct rq *rq, struct task_struct *p, int flags);
+	void (*dequeue_task) (struct rq *rq, struct task_struct *p, int flags);
+	void (*yield_task) (struct rq *rq);
+	bool (*yield_to_task) (struct rq *rq, struct task_struct *p, bool preempt);
+
+	void (*check_preempt_curr) (struct rq *rq, struct task_struct *p, int flags);
+
+	struct task_struct * (*pick_next_task) (struct rq *rq);
+	void (*put_prev_task) (struct rq *rq, struct task_struct *p);
+
+#ifdef CONFIG_SMP
+	int  (*select_task_rq)(struct task_struct *p, int sd_flag, int flags);
+	void (*migrate_task_rq)(struct task_struct *p, int next_cpu);
+
+	void (*pre_schedule) (struct rq *this_rq, struct task_struct *task);
+	void (*post_schedule) (struct rq *this_rq);
+	void (*task_waking) (struct task_struct *task);
+	void (*task_woken) (struct rq *this_rq, struct task_struct *task);
+
+	void (*set_cpus_allowed)(struct task_struct *p,
+				 const struct cpumask *newmask);
+
+	void (*rq_online)(struct rq *rq);
+	void (*rq_offline)(struct rq *rq);
+#endif
+
+	void (*set_curr_task) (struct rq *rq);
+	void (*task_tick) (struct rq *rq, struct task_struct *p, int queued);
+	void (*task_fork) (struct task_struct *p);
+
+	void (*switched_from) (struct rq *this_rq, struct task_struct *task);
+	void (*switched_to) (struct rq *this_rq, struct task_struct *task);
+	void (*prio_changed) (struct rq *this_rq, struct task_struct *task,
+			     int oldprio);
+
+	unsigned int (*get_rr_interval) (struct rq *rq,
+					 struct task_struct *task);
+
+#ifdef CONFIG_FAIR_GROUP_SCHED
+	void (*task_move_group) (struct task_struct *p, int on_rq);
+#endif
+};
 
 #define sched_class_highest (&stop_sched_class)
 #define for_each_class(class) \
@@ -877,6 +1026,8 @@ extern const struct sched_class idle_sched_class;
 
 #ifdef CONFIG_SMP
 
+extern void update_group_power(struct sched_domain *sd, int cpu);
+
 extern void trigger_load_balance(struct rq *rq, int cpu);
 extern void idle_balance(int this_cpu, struct rq *this_rq);
 
@@ -891,7 +1042,6 @@ static inline void idle_balance(int cpu, struct rq *rq)
 extern void sysrq_sched_debug_show(void);
 extern void sched_init_granularity(void);
 extern void update_max_interval(void);
-extern void update_group_power(struct sched_domain *sd, int cpu);
 extern int update_runtime(struct notifier_block *nfb, unsigned long action, void *hcpu);
 extern void init_sched_rt_class(void);
 extern void init_sched_fair_class(void);
diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index 5af44b5..b7a1004 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -160,6 +160,8 @@ static int seccomp_check_filter(struct sock_filter *filter, unsigned int flen)
 		case BPF_S_ALU_AND_X:
 		case BPF_S_ALU_OR_K:
 		case BPF_S_ALU_OR_X:
+		case BPF_S_ALU_XOR_K:
+		case BPF_S_ALU_XOR_X:
 		case BPF_S_ALU_LSH_K:
 		case BPF_S_ALU_LSH_X:
 		case BPF_S_ALU_RSH_K:
diff --git a/kernel/semaphore.c b/kernel/semaphore.c
index 4567fc0..6815171 100644
--- a/kernel/semaphore.c
+++ b/kernel/semaphore.c
@@ -193,7 +193,7 @@ EXPORT_SYMBOL(up);
 struct semaphore_waiter {
 	struct list_head list;
 	struct task_struct *task;
-	int up;
+	bool up;
 };
 
 /*
@@ -209,12 +209,12 @@ static inline int __sched __down_common(struct semaphore *sem, long state,
 
 	list_add_tail(&waiter.list, &sem->wait_list);
 	waiter.task = task;
-	waiter.up = 0;
+	waiter.up = false;
 
 	for (;;) {
 		if (signal_pending_state(state, task))
 			goto interrupted;
-		if (timeout <= 0)
+		if (unlikely(timeout <= 0))
 			goto timed_out;
 		__set_task_state(task, state);
 		raw_spin_unlock_irq(&sem->lock);
@@ -258,6 +258,6 @@ static noinline void __sched __up(struct semaphore *sem)
 	struct semaphore_waiter *waiter = list_first_entry(&sem->wait_list,
 						struct semaphore_waiter, list);
 	list_del(&waiter->list);
-	waiter->up = 1;
+	waiter->up = true;
 	wake_up_process(waiter->task);
 }
diff --git a/kernel/signal.c b/kernel/signal.c
index dd72567..bb7ca79 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -32,6 +32,7 @@
 #include <linux/user_namespace.h>
 #include <linux/uprobes.h>
 #include <linux/compat.h>
+#include <linux/cn_proc.h>
 #define CREATE_TRACE_POINTS
 #include <trace/events/signal.h>
 
@@ -854,12 +855,14 @@ static void ptrace_trap_notify(struct task_struct *t)
  * Returns true if the signal should be actually delivered, otherwise
  * it should be dropped.
  */
-static int prepare_signal(int sig, struct task_struct *p, bool force)
+static bool prepare_signal(int sig, struct task_struct *p, bool force)
 {
 	struct signal_struct *signal = p->signal;
 	struct task_struct *t;
 
-	if (unlikely(signal->flags & SIGNAL_GROUP_EXIT)) {
+	if (signal->flags & (SIGNAL_GROUP_EXIT | SIGNAL_GROUP_COREDUMP)) {
+		if (signal->flags & SIGNAL_GROUP_COREDUMP)
+			return sig == SIGKILL;
 		/*
 		 * The process is in the middle of dying, nothing to do.
 		 */
@@ -2350,6 +2353,7 @@ relock:
 		if (sig_kernel_coredump(signr)) {
 			if (print_fatal_signals)
 				print_fatal_signal(info->si_signo);
+			proc_coredump_connector(current);
 			/*
 			 * If it was able to dump core, this kills all
 			 * other threads in the group and synchronizes with
diff --git a/kernel/smp.c b/kernel/smp.c
index 8e451f3..31670c8 100644
--- a/kernel/smp.c
+++ b/kernel/smp.c
@@ -12,6 +12,7 @@
 #include <linux/gfp.h>
 #include <linux/smp.h>
 #include <linux/cpu.h>
+#include <linux/hardirq.h>
 
 #include "smpboot.h"
 
@@ -100,16 +101,16 @@ void __init call_function_init(void)
  * previous function call. For multi-cpu calls its even more interesting
  * as we'll have to ensure no other cpu is observing our csd.
  */
-static void csd_lock_wait(struct call_single_data *data)
+static void csd_lock_wait(struct call_single_data *csd)
 {
-	while (data->flags & CSD_FLAG_LOCK)
+	while (csd->flags & CSD_FLAG_LOCK)
 		cpu_relax();
 }
 
-static void csd_lock(struct call_single_data *data)
+static void csd_lock(struct call_single_data *csd)
 {
-	csd_lock_wait(data);
-	data->flags = CSD_FLAG_LOCK;
+	csd_lock_wait(csd);
+	csd->flags = CSD_FLAG_LOCK;
 
 	/*
 	 * prevent CPU from reordering the above assignment
@@ -119,16 +120,16 @@ static void csd_lock(struct call_single_data *data)
 	smp_mb();
 }
 
-static void csd_unlock(struct call_single_data *data)
+static void csd_unlock(struct call_single_data *csd)
 {
-	WARN_ON(!(data->flags & CSD_FLAG_LOCK));
+	WARN_ON(!(csd->flags & CSD_FLAG_LOCK));
 
 	/*
 	 * ensure we're all done before releasing data:
 	 */
 	smp_mb();
 
-	data->flags &= ~CSD_FLAG_LOCK;
+	csd->flags &= ~CSD_FLAG_LOCK;
 }
 
 /*
@@ -137,7 +138,7 @@ static void csd_unlock(struct call_single_data *data)
  * ->func, ->info, and ->flags set.
  */
 static
-void generic_exec_single(int cpu, struct call_single_data *data, int wait)
+void generic_exec_single(int cpu, struct call_single_data *csd, int wait)
 {
 	struct call_single_queue *dst = &per_cpu(call_single_queue, cpu);
 	unsigned long flags;
@@ -145,7 +146,7 @@ void generic_exec_single(int cpu, struct call_single_data *data, int wait)
 
 	raw_spin_lock_irqsave(&dst->lock, flags);
 	ipi = list_empty(&dst->list);
-	list_add_tail(&data->list, &dst->list);
+	list_add_tail(&csd->list, &dst->list);
 	raw_spin_unlock_irqrestore(&dst->lock, flags);
 
 	/*
@@ -163,7 +164,7 @@ void generic_exec_single(int cpu, struct call_single_data *data, int wait)
 		arch_send_call_function_single_ipi(cpu);
 
 	if (wait)
-		csd_lock_wait(data);
+		csd_lock_wait(csd);
 }
 
 /*
@@ -173,7 +174,6 @@ void generic_exec_single(int cpu, struct call_single_data *data, int wait)
 void generic_smp_call_function_single_interrupt(void)
 {
 	struct call_single_queue *q = &__get_cpu_var(call_single_queue);
-	unsigned int data_flags;
 	LIST_HEAD(list);
 
 	/*
@@ -186,25 +186,26 @@ void generic_smp_call_function_single_interrupt(void)
 	raw_spin_unlock(&q->lock);
 
 	while (!list_empty(&list)) {
-		struct call_single_data *data;
+		struct call_single_data *csd;
+		unsigned int csd_flags;
 
-		data = list_entry(list.next, struct call_single_data, list);
-		list_del(&data->list);
+		csd = list_entry(list.next, struct call_single_data, list);
+		list_del(&csd->list);
 
 		/*
-		 * 'data' can be invalid after this call if flags == 0
+		 * 'csd' can be invalid after this call if flags == 0
 		 * (when called through generic_exec_single()),
 		 * so save them away before making the call:
 		 */
-		data_flags = data->flags;
+		csd_flags = csd->flags;
 
-		data->func(data->info);
+		csd->func(csd->info);
 
 		/*
 		 * Unlocked CSDs are valid through generic_exec_single():
 		 */
-		if (data_flags & CSD_FLAG_LOCK)
-			csd_unlock(data);
+		if (csd_flags & CSD_FLAG_LOCK)
+			csd_unlock(csd);
 	}
 }
 
@@ -240,8 +241,9 @@ int smp_call_function_single(int cpu, smp_call_func_t func, void *info,
 	 * send smp call function interrupt to this cpu and as such deadlocks
 	 * can't happen.
 	 */
-	WARN_ON_ONCE(cpu_online(this_cpu) && irqs_disabled()
-		     && !oops_in_progress);
+	WARN_ON_ONCE(cpu_online(this_cpu)
+		&& (irqs_disabled() || in_serving_irq())
+		&& !oops_in_progress);
 
 	if (cpu == this_cpu) {
 		local_irq_save(flags);
@@ -249,16 +251,16 @@ int smp_call_function_single(int cpu, smp_call_func_t func, void *info,
 		local_irq_restore(flags);
 	} else {
 		if ((unsigned)cpu < nr_cpu_ids && cpu_online(cpu)) {
-			struct call_single_data *data = &d;
+			struct call_single_data *csd = &d;
 
 			if (!wait)
-				data = &__get_cpu_var(csd_data);
+				csd = &__get_cpu_var(csd_data);
 
-			csd_lock(data);
+			csd_lock(csd);
 
-			data->func = func;
-			data->info = info;
-			generic_exec_single(cpu, data, wait);
+			csd->func = func;
+			csd->info = info;
+			generic_exec_single(cpu, csd, wait);
 		} else {
 			err = -ENXIO;	/* CPU not online */
 		}
@@ -325,7 +327,7 @@ EXPORT_SYMBOL_GPL(smp_call_function_any);
  * pre-allocated data structure. Useful for embedding @data inside
  * other structures, for instance.
  */
-void __smp_call_function_single(int cpu, struct call_single_data *data,
+void __smp_call_function_single(int cpu, struct call_single_data *csd,
 				int wait)
 {
 	unsigned int this_cpu;
@@ -343,11 +345,11 @@ void __smp_call_function_single(int cpu, struct call_single_data *data,
 
 	if (cpu == this_cpu) {
 		local_irq_save(flags);
-		data->func(data->info);
+		csd->func(csd->info);
 		local_irq_restore(flags);
 	} else {
-		csd_lock(data);
-		generic_exec_single(cpu, data, wait);
+		csd_lock(csd);
+		generic_exec_single(cpu, csd, wait);
 	}
 	put_cpu();
 }
@@ -369,7 +371,7 @@ void __smp_call_function_single(int cpu, struct call_single_data *data,
 void smp_call_function_many(const struct cpumask *mask,
 			    smp_call_func_t func, void *info, bool wait)
 {
-	struct call_function_data *data;
+	struct call_function_data *cfd;
 	int cpu, next_cpu, this_cpu = smp_processor_id();
 
 	/*
@@ -378,8 +380,9 @@ void smp_call_function_many(const struct cpumask *mask,
 	 * send smp call function interrupt to this cpu and as such deadlocks
 	 * can't happen.
 	 */
-	WARN_ON_ONCE(cpu_online(this_cpu) && irqs_disabled()
-		     && !oops_in_progress && !early_boot_irqs_disabled);
+	WARN_ON_ONCE(cpu_online(this_cpu)
+		&& (irqs_disabled() || in_serving_irq())
+		&& !oops_in_progress && !early_boot_irqs_disabled);
 
 	/* Try to fastpath.  So, what's a CPU they want? Ignoring this one. */
 	cpu = cpumask_first_and(mask, cpu_online_mask);
@@ -401,24 +404,24 @@ void smp_call_function_many(const struct cpumask *mask,
 		return;
 	}
 
-	data = &__get_cpu_var(cfd_data);
+	cfd = &__get_cpu_var(cfd_data);
 
-	cpumask_and(data->cpumask, mask, cpu_online_mask);
-	cpumask_clear_cpu(this_cpu, data->cpumask);
+	cpumask_and(cfd->cpumask, mask, cpu_online_mask);
+	cpumask_clear_cpu(this_cpu, cfd->cpumask);
 
 	/* Some callers race with other cpus changing the passed mask */
-	if (unlikely(!cpumask_weight(data->cpumask)))
+	if (unlikely(!cpumask_weight(cfd->cpumask)))
 		return;
 
 	/*
-	 * After we put an entry into the list, data->cpumask
-	 * may be cleared again when another CPU sends another IPI for
-	 * a SMP function call, so data->cpumask will be zero.
+	 * After we put an entry into the list, cfd->cpumask may be cleared
+	 * again when another CPU sends another IPI for a SMP function call, so
+	 * cfd->cpumask will be zero.
 	 */
-	cpumask_copy(data->cpumask_ipi, data->cpumask);
+	cpumask_copy(cfd->cpumask_ipi, cfd->cpumask);
 
-	for_each_cpu(cpu, data->cpumask) {
-		struct call_single_data *csd = per_cpu_ptr(data->csd, cpu);
+	for_each_cpu(cpu, cfd->cpumask) {
+		struct call_single_data *csd = per_cpu_ptr(cfd->csd, cpu);
 		struct call_single_queue *dst =
 					&per_cpu(call_single_queue, cpu);
 		unsigned long flags;
@@ -433,12 +436,13 @@ void smp_call_function_many(const struct cpumask *mask,
 	}
 
 	/* Send a message to all CPUs in the map */
-	arch_send_call_function_ipi_mask(data->cpumask_ipi);
+	arch_send_call_function_ipi_mask(cfd->cpumask_ipi);
 
 	if (wait) {
-		for_each_cpu(cpu, data->cpumask) {
-			struct call_single_data *csd =
-					per_cpu_ptr(data->csd, cpu);
+		for_each_cpu(cpu, cfd->cpumask) {
+			struct call_single_data *csd;
+
+			csd = per_cpu_ptr(cfd->csd, cpu);
 			csd_lock_wait(csd);
 		}
 	}
diff --git a/kernel/sys.c b/kernel/sys.c
index 39c9c4a..ef29beb 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -1784,13 +1784,26 @@ SYSCALL_DEFINE2(getrusage, int, who, struct rusage __user *, ru)
 	return getrusage(current, who, ru);
 }
 
+#ifdef CONFIG_COMPAT
+COMPAT_SYSCALL_DEFINE2(getrusage, int, who, struct compat_rusage __user *, ru)
+{
+	struct rusage r;
+
+	if (who != RUSAGE_SELF && who != RUSAGE_CHILDREN &&
+	    who != RUSAGE_THREAD)
+		return -EINVAL;
+
+	k_getrusage(current, who, &r);
+	return put_compat_rusage(&r, ru);
+}
+#endif
+
 SYSCALL_DEFINE1(umask, int, mask)
 {
 	mask = xchg(&current->fs->umask, mask & S_IRWXUGO);
 	return mask;
 }
 
-#ifdef CONFIG_CHECKPOINT_RESTORE
 static int prctl_set_mm_exe_file(struct mm_struct *mm, unsigned int fd)
 {
 	struct fd exe;
@@ -1984,17 +1997,12 @@ out:
 	return error;
 }
 
+#ifdef CONFIG_CHECKPOINT_RESTORE
 static int prctl_get_tid_address(struct task_struct *me, int __user **tid_addr)
 {
 	return put_user(me->clear_child_tid, tid_addr);
 }
-
-#else /* CONFIG_CHECKPOINT_RESTORE */
-static int prctl_set_mm(int opt, unsigned long addr,
-			unsigned long arg4, unsigned long arg5)
-{
-	return -EINVAL;
-}
+#else
 static int prctl_get_tid_address(struct task_struct *me, int __user **tid_addr)
 {
 	return -EINVAL;
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
index 395084d..bfd6787 100644
--- a/kernel/sys_ni.c
+++ b/kernel/sys_ni.c
@@ -20,6 +20,7 @@ cond_syscall(sys_quotactl);
 cond_syscall(sys32_quotactl);
 cond_syscall(sys_acct);
 cond_syscall(sys_lookup_dcookie);
+cond_syscall(compat_sys_lookup_dcookie);
 cond_syscall(sys_swapon);
 cond_syscall(sys_swapoff);
 cond_syscall(sys_kexec_load);
@@ -155,7 +156,7 @@ cond_syscall(compat_sys_process_vm_writev);
 cond_syscall(sys_pciconfig_read);
 cond_syscall(sys_pciconfig_write);
 cond_syscall(sys_pciconfig_iobase);
-cond_syscall(sys32_ipc);
+cond_syscall(compat_sys_s390_ipc);
 cond_syscall(ppc_rtas);
 cond_syscall(sys_spu_run);
 cond_syscall(sys_spu_create);
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index afc1dc6..3dadde5 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -106,7 +106,6 @@ extern unsigned int core_pipe_limit;
 #endif
 extern int pid_max;
 extern int pid_max_min, pid_max_max;
-extern int sysctl_drop_caches;
 extern int percpu_pagelist_fraction;
 extern int compat_log;
 extern int latencytop_enabled;
diff --git a/kernel/test_kprobes.c b/kernel/test_kprobes.c
index f8b11a2..12d6ebb 100644
--- a/kernel/test_kprobes.c
+++ b/kernel/test_kprobes.c
@@ -365,7 +365,7 @@ int init_test_probes(void)
 	target2 = kprobe_target2;
 
 	do {
-		rand1 = random32();
+		rand1 = prandom_u32();
 	} while (rand1 <= div_factor);
 
 	printk(KERN_INFO "Kprobe smoke test started\n");
diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c
index 7f32fe0..e035583 100644
--- a/kernel/time/tick-broadcast.c
+++ b/kernel/time/tick-broadcast.c
@@ -28,9 +28,8 @@
  */
 
 static struct tick_device tick_broadcast_device;
-/* FIXME: Use cpumask_var_t. */
-static DECLARE_BITMAP(tick_broadcast_mask, NR_CPUS);
-static DECLARE_BITMAP(tmpmask, NR_CPUS);
+static cpumask_var_t tick_broadcast_mask;
+static cpumask_var_t tmpmask;
 static DEFINE_RAW_SPINLOCK(tick_broadcast_lock);
 static int tick_broadcast_force;
 
@@ -50,7 +49,7 @@ struct tick_device *tick_get_broadcast_device(void)
 
 struct cpumask *tick_get_broadcast_mask(void)
 {
-	return to_cpumask(tick_broadcast_mask);
+	return tick_broadcast_mask;
 }
 
 /*
@@ -75,7 +74,7 @@ int tick_check_broadcast_device(struct clock_event_device *dev)
 
 	clockevents_exchange_device(tick_broadcast_device.evtdev, dev);
 	tick_broadcast_device.evtdev = dev;
-	if (!cpumask_empty(tick_get_broadcast_mask()))
+	if (!cpumask_empty(tick_broadcast_mask))
 		tick_broadcast_start_periodic(dev);
 	return 1;
 }
@@ -124,7 +123,7 @@ int tick_device_uses_broadcast(struct clock_event_device *dev, int cpu)
 	if (!tick_device_is_functional(dev)) {
 		dev->event_handler = tick_handle_periodic;
 		tick_device_setup_broadcast_func(dev);
-		cpumask_set_cpu(cpu, tick_get_broadcast_mask());
+		cpumask_set_cpu(cpu, tick_broadcast_mask);
 		tick_broadcast_start_periodic(tick_broadcast_device.evtdev);
 		ret = 1;
 	} else {
@@ -135,7 +134,7 @@ int tick_device_uses_broadcast(struct clock_event_device *dev, int cpu)
 		 */
 		if (!(dev->features & CLOCK_EVT_FEAT_C3STOP)) {
 			int cpu = smp_processor_id();
-			cpumask_clear_cpu(cpu, tick_get_broadcast_mask());
+			cpumask_clear_cpu(cpu, tick_broadcast_mask);
 			tick_broadcast_clear_oneshot(cpu);
 		} else {
 			tick_device_setup_broadcast_func(dev);
@@ -199,9 +198,8 @@ static void tick_do_periodic_broadcast(void)
 {
 	raw_spin_lock(&tick_broadcast_lock);
 
-	cpumask_and(to_cpumask(tmpmask),
-		    cpu_online_mask, tick_get_broadcast_mask());
-	tick_do_broadcast(to_cpumask(tmpmask));
+	cpumask_and(tmpmask, cpu_online_mask, tick_broadcast_mask);
+	tick_do_broadcast(tmpmask);
 
 	raw_spin_unlock(&tick_broadcast_lock);
 }
@@ -264,13 +262,12 @@ static void tick_do_broadcast_on_off(unsigned long *reason)
 	if (!tick_device_is_functional(dev))
 		goto out;
 
-	bc_stopped = cpumask_empty(tick_get_broadcast_mask());
+	bc_stopped = cpumask_empty(tick_broadcast_mask);
 
 	switch (*reason) {
 	case CLOCK_EVT_NOTIFY_BROADCAST_ON:
 	case CLOCK_EVT_NOTIFY_BROADCAST_FORCE:
-		if (!cpumask_test_cpu(cpu, tick_get_broadcast_mask())) {
-			cpumask_set_cpu(cpu, tick_get_broadcast_mask());
+		if (!cpumask_test_and_set_cpu(cpu, tick_broadcast_mask)) {
 			if (tick_broadcast_device.mode ==
 			    TICKDEV_MODE_PERIODIC)
 				clockevents_shutdown(dev);
@@ -280,8 +277,7 @@ static void tick_do_broadcast_on_off(unsigned long *reason)
 		break;
 	case CLOCK_EVT_NOTIFY_BROADCAST_OFF:
 		if (!tick_broadcast_force &&
-		    cpumask_test_cpu(cpu, tick_get_broadcast_mask())) {
-			cpumask_clear_cpu(cpu, tick_get_broadcast_mask());
+		    cpumask_test_and_clear_cpu(cpu, tick_broadcast_mask)) {
 			if (tick_broadcast_device.mode ==
 			    TICKDEV_MODE_PERIODIC)
 				tick_setup_periodic(dev, 0);
@@ -289,7 +285,7 @@ static void tick_do_broadcast_on_off(unsigned long *reason)
 		break;
 	}
 
-	if (cpumask_empty(tick_get_broadcast_mask())) {
+	if (cpumask_empty(tick_broadcast_mask)) {
 		if (!bc_stopped)
 			clockevents_shutdown(bc);
 	} else if (bc_stopped) {
@@ -338,10 +334,10 @@ void tick_shutdown_broadcast(unsigned int *cpup)
 	raw_spin_lock_irqsave(&tick_broadcast_lock, flags);
 
 	bc = tick_broadcast_device.evtdev;
-	cpumask_clear_cpu(cpu, tick_get_broadcast_mask());
+	cpumask_clear_cpu(cpu, tick_broadcast_mask);
 
 	if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC) {
-		if (bc && cpumask_empty(tick_get_broadcast_mask()))
+		if (bc && cpumask_empty(tick_broadcast_mask))
 			clockevents_shutdown(bc);
 	}
 
@@ -377,13 +373,13 @@ int tick_resume_broadcast(void)
 
 		switch (tick_broadcast_device.mode) {
 		case TICKDEV_MODE_PERIODIC:
-			if (!cpumask_empty(tick_get_broadcast_mask()))
+			if (!cpumask_empty(tick_broadcast_mask))
 				tick_broadcast_start_periodic(bc);
 			broadcast = cpumask_test_cpu(smp_processor_id(),
-						     tick_get_broadcast_mask());
+						     tick_broadcast_mask);
 			break;
 		case TICKDEV_MODE_ONESHOT:
-			if (!cpumask_empty(tick_get_broadcast_mask()))
+			if (!cpumask_empty(tick_broadcast_mask))
 				broadcast = tick_resume_broadcast_oneshot(bc);
 			break;
 		}
@@ -396,25 +392,44 @@ int tick_resume_broadcast(void)
 
 #ifdef CONFIG_TICK_ONESHOT
 
-/* FIXME: use cpumask_var_t. */
-static DECLARE_BITMAP(tick_broadcast_oneshot_mask, NR_CPUS);
+static cpumask_var_t tick_broadcast_oneshot_mask;
 
 /*
  * Exposed for debugging: see timer_list.c
  */
 struct cpumask *tick_get_broadcast_oneshot_mask(void)
 {
-	return to_cpumask(tick_broadcast_oneshot_mask);
+	return tick_broadcast_oneshot_mask;
 }
 
-static int tick_broadcast_set_event(ktime_t expires, int force)
+/*
+ * Set broadcast interrupt affinity
+ */
+static void tick_broadcast_set_affinity(struct clock_event_device *bc,
+					const struct cpumask *cpumask)
 {
-	struct clock_event_device *bc = tick_broadcast_device.evtdev;
+	if (!(bc->features & CLOCK_EVT_FEAT_DYNIRQ))
+		return;
+
+	if (cpumask_equal(bc->cpumask, cpumask))
+		return;
+
+	bc->cpumask = cpumask;
+	irq_set_affinity(bc->irq, bc->cpumask);
+}
+
+static int tick_broadcast_set_event(struct clock_event_device *bc, int cpu,
+				    ktime_t expires, int force)
+{
+	int ret;
 
 	if (bc->mode != CLOCK_EVT_MODE_ONESHOT)
 		clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT);
 
-	return clockevents_program_event(bc, expires, force);
+	ret = clockevents_program_event(bc, expires, force);
+	if (!ret)
+		tick_broadcast_set_affinity(bc, cpumask_of(cpu));
+	return ret;
 }
 
 int tick_resume_broadcast_oneshot(struct clock_event_device *bc)
@@ -429,7 +444,7 @@ int tick_resume_broadcast_oneshot(struct clock_event_device *bc)
  */
 void tick_check_oneshot_broadcast(int cpu)
 {
-	if (cpumask_test_cpu(cpu, to_cpumask(tick_broadcast_oneshot_mask))) {
+	if (cpumask_test_cpu(cpu, tick_broadcast_oneshot_mask)) {
 		struct tick_device *td = &per_cpu(tick_cpu_device, cpu);
 
 		clockevents_set_mode(td->evtdev, CLOCK_EVT_MODE_ONESHOT);
@@ -443,27 +458,29 @@ static void tick_handle_oneshot_broadcast(struct clock_event_device *dev)
 {
 	struct tick_device *td;
 	ktime_t now, next_event;
-	int cpu;
+	int cpu, next_cpu = 0;
 
 	raw_spin_lock(&tick_broadcast_lock);
 again:
 	dev->next_event.tv64 = KTIME_MAX;
 	next_event.tv64 = KTIME_MAX;
-	cpumask_clear(to_cpumask(tmpmask));
+	cpumask_clear(tmpmask);
 	now = ktime_get();
 	/* Find all expired events */
-	for_each_cpu(cpu, tick_get_broadcast_oneshot_mask()) {
+	for_each_cpu(cpu, tick_broadcast_oneshot_mask) {
 		td = &per_cpu(tick_cpu_device, cpu);
-		if (td->evtdev->next_event.tv64 <= now.tv64)
-			cpumask_set_cpu(cpu, to_cpumask(tmpmask));
-		else if (td->evtdev->next_event.tv64 < next_event.tv64)
+		if (td->evtdev->next_event.tv64 <= now.tv64) {
+			cpumask_set_cpu(cpu, tmpmask);
+		} else if (td->evtdev->next_event.tv64 < next_event.tv64) {
 			next_event.tv64 = td->evtdev->next_event.tv64;
+			next_cpu = cpu;
+		}
 	}
 
 	/*
 	 * Wakeup the cpus which have an expired event.
 	 */
-	tick_do_broadcast(to_cpumask(tmpmask));
+	tick_do_broadcast(tmpmask);
 
 	/*
 	 * Two reasons for reprogram:
@@ -480,7 +497,7 @@ again:
 		 * Rearm the broadcast device. If event expired,
 		 * repeat the above
 		 */
-		if (tick_broadcast_set_event(next_event, 0))
+		if (tick_broadcast_set_event(dev, next_cpu, next_event, 0))
 			goto again;
 	}
 	raw_spin_unlock(&tick_broadcast_lock);
@@ -519,16 +536,13 @@ void tick_broadcast_oneshot_control(unsigned long reason)
 
 	raw_spin_lock_irqsave(&tick_broadcast_lock, flags);
 	if (reason == CLOCK_EVT_NOTIFY_BROADCAST_ENTER) {
-		if (!cpumask_test_cpu(cpu, tick_get_broadcast_oneshot_mask())) {
-			cpumask_set_cpu(cpu, tick_get_broadcast_oneshot_mask());
+		if (!cpumask_test_and_set_cpu(cpu, tick_broadcast_oneshot_mask)) {
 			clockevents_set_mode(dev, CLOCK_EVT_MODE_SHUTDOWN);
 			if (dev->next_event.tv64 < bc->next_event.tv64)
-				tick_broadcast_set_event(dev->next_event, 1);
+				tick_broadcast_set_event(bc, cpu, dev->next_event, 1);
 		}
 	} else {
-		if (cpumask_test_cpu(cpu, tick_get_broadcast_oneshot_mask())) {
-			cpumask_clear_cpu(cpu,
-					  tick_get_broadcast_oneshot_mask());
+		if (cpumask_test_and_clear_cpu(cpu, tick_broadcast_oneshot_mask)) {
 			clockevents_set_mode(dev, CLOCK_EVT_MODE_ONESHOT);
 			if (dev->next_event.tv64 != KTIME_MAX)
 				tick_program_event(dev->next_event, 1);
@@ -544,7 +558,7 @@ void tick_broadcast_oneshot_control(unsigned long reason)
  */
 static void tick_broadcast_clear_oneshot(int cpu)
 {
-	cpumask_clear_cpu(cpu, tick_get_broadcast_oneshot_mask());
+	cpumask_clear_cpu(cpu, tick_broadcast_oneshot_mask);
 }
 
 static void tick_broadcast_init_next_event(struct cpumask *mask,
@@ -582,17 +596,16 @@ void tick_broadcast_setup_oneshot(struct clock_event_device *bc)
 		 * oneshot_mask bits for those and program the
 		 * broadcast device to fire.
 		 */
-		cpumask_copy(to_cpumask(tmpmask), tick_get_broadcast_mask());
-		cpumask_clear_cpu(cpu, to_cpumask(tmpmask));
-		cpumask_or(tick_get_broadcast_oneshot_mask(),
-			   tick_get_broadcast_oneshot_mask(),
-			   to_cpumask(tmpmask));
+		cpumask_copy(tmpmask, tick_broadcast_mask);
+		cpumask_clear_cpu(cpu, tmpmask);
+		cpumask_or(tick_broadcast_oneshot_mask,
+			   tick_broadcast_oneshot_mask, tmpmask);
 
-		if (was_periodic && !cpumask_empty(to_cpumask(tmpmask))) {
+		if (was_periodic && !cpumask_empty(tmpmask)) {
 			clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT);
-			tick_broadcast_init_next_event(to_cpumask(tmpmask),
+			tick_broadcast_init_next_event(tmpmask,
 						       tick_next_period);
-			tick_broadcast_set_event(tick_next_period, 1);
+			tick_broadcast_set_event(bc, cpu, tick_next_period, 1);
 		} else
 			bc->next_event.tv64 = KTIME_MAX;
 	} else {
@@ -640,7 +653,7 @@ void tick_shutdown_broadcast_oneshot(unsigned int *cpup)
 	 * Clear the broadcast mask flag for the dead cpu, but do not
 	 * stop the broadcast device!
 	 */
-	cpumask_clear_cpu(cpu, tick_get_broadcast_oneshot_mask());
+	cpumask_clear_cpu(cpu, tick_broadcast_oneshot_mask);
 
 	raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags);
 }
@@ -664,3 +677,12 @@ bool tick_broadcast_oneshot_available(void)
 }
 
 #endif
+
+void __init tick_broadcast_init(void)
+{
+	alloc_cpumask_var(&tick_broadcast_mask, GFP_NOWAIT);
+	alloc_cpumask_var(&tmpmask, GFP_NOWAIT);
+#ifdef CONFIG_TICK_ONESHOT
+	alloc_cpumask_var(&tick_broadcast_oneshot_mask, GFP_NOWAIT);
+#endif
+}
diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c
index b1600a6..74413e3 100644
--- a/kernel/time/tick-common.c
+++ b/kernel/time/tick-common.c
@@ -416,4 +416,5 @@ static struct notifier_block tick_notifier = {
 void __init tick_init(void)
 {
 	clockevents_register_notifier(&tick_notifier);
+	tick_broadcast_init();
 }
diff --git a/kernel/time/tick-internal.h b/kernel/time/tick-internal.h
index cf3e59e..46d9bd0 100644
--- a/kernel/time/tick-internal.h
+++ b/kernel/time/tick-internal.h
@@ -94,7 +94,7 @@ extern void tick_broadcast_on_off(unsigned long reason, int *oncpu);
 extern void tick_shutdown_broadcast(unsigned int *cpup);
 extern void tick_suspend_broadcast(void);
 extern int tick_resume_broadcast(void);
-
+extern void tick_broadcast_init(void);
 extern void
 tick_set_periodic_handler(struct clock_event_device *dev, int broadcast);
 
@@ -119,6 +119,7 @@ static inline void tick_broadcast_on_off(unsigned long reason, int *oncpu) { }
 static inline void tick_shutdown_broadcast(unsigned int *cpup) { }
 static inline void tick_suspend_broadcast(void) { }
 static inline int tick_resume_broadcast(void) { return 0; }
+static inline void tick_broadcast_init(void) { }
 
 /*
  * Set the periodic handler in non broadcast mode
diff --git a/kernel/time/timer_list.c b/kernel/time/timer_list.c
index af5a7e9..7ccf16f 100644
--- a/kernel/time/timer_list.c
+++ b/kernel/time/timer_list.c
@@ -133,7 +133,6 @@ static void print_cpu(struct seq_file *m, int cpu, u64 now)
 	struct hrtimer_cpu_base *cpu_base = &per_cpu(hrtimer_bases, cpu);
 	int i;
 
-	SEQ_printf(m, "\n");
 	SEQ_printf(m, "cpu: %d\n", cpu);
 	for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++) {
 		SEQ_printf(m, " clock %d:\n", i);
@@ -187,6 +186,7 @@ static void print_cpu(struct seq_file *m, int cpu, u64 now)
 
 #undef P
 #undef P_ns
+	SEQ_printf(m, "\n");
 }
 
 #ifdef CONFIG_GENERIC_CLOCKEVENTS
@@ -195,7 +195,6 @@ print_tickdevice(struct seq_file *m, struct tick_device *td, int cpu)
 {
 	struct clock_event_device *dev = td->evtdev;
 
-	SEQ_printf(m, "\n");
 	SEQ_printf(m, "Tick Device: mode:     %d\n", td->mode);
 	if (cpu < 0)
 		SEQ_printf(m, "Broadcast device\n");
@@ -230,12 +229,11 @@ print_tickdevice(struct seq_file *m, struct tick_device *td, int cpu)
 	print_name_offset(m, dev->event_handler);
 	SEQ_printf(m, "\n");
 	SEQ_printf(m, " retries:        %lu\n", dev->retries);
+	SEQ_printf(m, "\n");
 }
 
-static void timer_list_show_tickdevices(struct seq_file *m)
+static void timer_list_show_tickdevices_header(struct seq_file *m)
 {
-	int cpu;
-
 #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
 	print_tickdevice(m, tick_get_broadcast_device(), -1);
 	SEQ_printf(m, "tick_broadcast_mask: %08lx\n",
@@ -246,12 +244,7 @@ static void timer_list_show_tickdevices(struct seq_file *m)
 #endif
 	SEQ_printf(m, "\n");
 #endif
-	for_each_online_cpu(cpu)
-		print_tickdevice(m, tick_get_device(cpu), cpu);
-	SEQ_printf(m, "\n");
 }
-#else
-static void timer_list_show_tickdevices(struct seq_file *m) { }
 #endif
 
 static int timer_list_show(struct seq_file *m, void *v)
@@ -259,34 +252,113 @@ static int timer_list_show(struct seq_file *m, void *v)
 	u64 now = ktime_to_ns(ktime_get());
 	int cpu;
 
-	SEQ_printf(m, "Timer List Version: v0.7\n");
-	SEQ_printf(m, "HRTIMER_MAX_CLOCK_BASES: %d\n", HRTIMER_MAX_CLOCK_BASES);
-	SEQ_printf(m, "now at %Ld nsecs\n", (unsigned long long)now);
-
-	for_each_online_cpu(cpu)
+	if (v == (void *)1) {
+		SEQ_printf(m, "Timer List Version: v0.7\n");
+		SEQ_printf(m, "HRTIMER_MAX_CLOCK_BASES: %d\n",
+			   HRTIMER_MAX_CLOCK_BASES);
+		SEQ_printf(m, "now at %Ld nsecs\n", (unsigned long long)now);
+		SEQ_printf(m, "\n");
+	} else if (v < (void *)(unsigned long)(nr_cpu_ids + 2)) {
+		cpu = (unsigned long)(v - 2);
 		print_cpu(m, cpu, now);
+	}
+#ifdef CONFIG_GENERIC_CLOCKEVENTS
+	else if (v == (void *)(unsigned long)nr_cpu_ids + 2) {
+		timer_list_show_tickdevices_header(m);
+	} else {
+		cpu = (unsigned long)(v - 3 - nr_cpu_ids);
+		print_tickdevice(m, tick_get_device(cpu), cpu);
+	}
+#endif
+	return 0;
+}
 
-	SEQ_printf(m, "\n");
-	timer_list_show_tickdevices(m);
+/*
+ * This iterator really needs some explanation since it is offset and has
+ * two passes, one of which is controlled by a config option.
+ * In hotpluggable systems some cpus, including cpu 0 and the last cpu, may
+ * be missing so we have to use cpumask_* to iterate over the cpus.
+ * For the first pass:
+ * It returns 1 for the header position.
+ * For cpu 0 it returns 2 and the final possible cpu would be nr_cpu_ids + 1.
+ * On the second pass:
+ * It returns nr_cpu_ids + 1 for the second header position.
+ * For cpu 0 it returns nr_cpu_ids + 2
+ * The final possible cpu would be nr_cpu_ids + nr_cpu_ids + 2.
+ * It is also important to remember that cpumask_next returns >= nr_cpu_ids if
+ * no further cpus set.
+ */
+static void *timer_list_start(struct seq_file *file, loff_t *offset)
+{
+	unsigned long n = *offset;
 
-	return 0;
+	if (n == 0)
+		return (void *) 1;
+
+	if (n < nr_cpu_ids + 1) {
+		n = cpumask_next(n - 2, cpu_online_mask);
+		if (n >= nr_cpu_ids)
+			n = nr_cpu_ids;
+		*offset = n + 1;
+		return (void *)(unsigned long)(n + 2);
+	}
+
+#ifdef CONFIG_GENERIC_CLOCKEVENTS
+	if (n == nr_cpu_ids + 1)
+		return (void *)(unsigned long)(nr_cpu_ids + 2);
+
+	if (n < nr_cpu_ids * 2 + 2) {
+		n -= (nr_cpu_ids + 2);
+		n = cpumask_next(n - 1, cpu_online_mask);
+		if (n >= nr_cpu_ids)
+			return NULL;
+		*offset = n + 2 + nr_cpu_ids;
+		return (void *)(unsigned long)(n + 3 + nr_cpu_ids);
+	}
+#endif
+
+	return NULL;
+}
+
+static void *timer_list_next(struct seq_file *file, void *data, loff_t *offset)
+{
+	(*offset)++;
+	return timer_list_start(file, offset);
 }
 
+static void timer_list_stop(struct seq_file *file, void *data)
+{
+}
+
+static const struct seq_operations timer_list_sops = {
+	.start = timer_list_start,
+	.next = timer_list_next,
+	.stop = timer_list_stop,
+	.show = timer_list_show,
+};
+
 void sysrq_timer_list_show(void)
 {
 	timer_list_show(NULL, NULL);
 }
 
+static int timer_list_release(struct inode *inode, struct file *filep)
+{
+	seq_release(inode, filep);
+
+	return 0;
+}
+
 static int timer_list_open(struct inode *inode, struct file *filp)
 {
-	return single_open(filp, timer_list_show, NULL);
+	return seq_open(filp, &timer_list_sops);
 }
 
 static const struct file_operations timer_list_fops = {
 	.open		= timer_list_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
-	.release	= single_release,
+	.release	= timer_list_release,
 };
 
 static int __init init_timer_list_procfs(void)
diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig
index fc382d6..5e9efd4 100644
--- a/kernel/trace/Kconfig
+++ b/kernel/trace/Kconfig
@@ -176,6 +176,8 @@ config IRQSOFF_TRACER
 	select GENERIC_TRACER
 	select TRACER_MAX_TRACE
 	select RING_BUFFER_ALLOW_SWAP
+	select TRACER_SNAPSHOT
+	select TRACER_SNAPSHOT_PER_CPU_SWAP
 	help
 	  This option measures the time spent in irqs-off critical
 	  sections, with microsecond accuracy.
@@ -198,6 +200,8 @@ config PREEMPT_TRACER
 	select GENERIC_TRACER
 	select TRACER_MAX_TRACE
 	select RING_BUFFER_ALLOW_SWAP
+	select TRACER_SNAPSHOT
+	select TRACER_SNAPSHOT_PER_CPU_SWAP
 	help
 	  This option measures the time spent in preemption-off critical
 	  sections, with microsecond accuracy.
@@ -217,6 +221,7 @@ config SCHED_TRACER
 	select GENERIC_TRACER
 	select CONTEXT_SWITCH_TRACER
 	select TRACER_MAX_TRACE
+	select TRACER_SNAPSHOT
 	help
 	  This tracer tracks the latency of the highest priority task
 	  to be scheduled in, starting from the point it has woken up.
@@ -248,6 +253,27 @@ config TRACER_SNAPSHOT
 	      echo 1 > /sys/kernel/debug/tracing/snapshot
 	      cat snapshot
 
+config TRACER_SNAPSHOT_PER_CPU_SWAP
+        bool "Allow snapshot to swap per CPU"
+	depends on TRACER_SNAPSHOT
+	select RING_BUFFER_ALLOW_SWAP
+	help
+	  Allow doing a snapshot of a single CPU buffer instead of a
+	  full swap (all buffers). If this is set, then the following is
+	  allowed:
+
+	      echo 1 > /sys/kernel/debug/tracing/per_cpu/cpu2/snapshot
+
+	  After which, only the tracing buffer for CPU 2 was swapped with
+	  the main tracing buffer, and the other CPU buffers remain the same.
+
+	  When this is enabled, this adds a little more overhead to the
+	  trace recording, as it needs to add some checks to synchronize
+	  recording with swaps. But this does not affect the performance
+	  of the overall system. This is enabled by default when the preempt
+	  or irq latency tracers are enabled, as those need to swap as well
+	  and already adds the overhead (plus a lot more).
+
 config TRACE_BRANCH_PROFILING
 	bool
 	select GENERIC_TRACER
@@ -524,6 +550,29 @@ config RING_BUFFER_BENCHMARK
 
 	  If unsure, say N.
 
+config RING_BUFFER_STARTUP_TEST
+       bool "Ring buffer startup self test"
+       depends on RING_BUFFER
+       help
+         Run a simple self test on the ring buffer on boot up. Late in the
+	 kernel boot sequence, the test will start that kicks off
+	 a thread per cpu. Each thread will write various size events
+	 into the ring buffer. Another thread is created to send IPIs
+	 to each of the threads, where the IPI handler will also write
+	 to the ring buffer, to test/stress the nesting ability.
+	 If any anomalies are discovered, a warning will be displayed
+	 and all ring buffers will be disabled.
+
+	 The test runs for 10 seconds. This will slow your boot time
+	 by at least 10 more seconds.
+
+	 At the end of the test, statics and more checks are done.
+	 It will output the stats of each per cpu buffer. What
+	 was written, the sizes, what was read, what was lost, and
+	 other similar details.
+
+	 If unsure, say N
+
 endif # FTRACE
 
 endif # TRACING_SUPPORT
diff --git a/kernel/trace/blktrace.c b/kernel/trace/blktrace.c
index 9e5b8c2..1f5003f 100644
--- a/kernel/trace/blktrace.c
+++ b/kernel/trace/blktrace.c
@@ -72,7 +72,7 @@ static void trace_note(struct blk_trace *bt, pid_t pid, int action,
 	bool blk_tracer = blk_tracer_enabled;
 
 	if (blk_tracer) {
-		buffer = blk_tr->buffer;
+		buffer = blk_tr->trace_buffer.buffer;
 		pc = preempt_count();
 		event = trace_buffer_lock_reserve(buffer, TRACE_BLK,
 						  sizeof(*t) + len,
@@ -218,7 +218,7 @@ static void __blk_add_trace(struct blk_trace *bt, sector_t sector, int bytes,
 	if (blk_tracer) {
 		tracing_record_cmdline(current);
 
-		buffer = blk_tr->buffer;
+		buffer = blk_tr->trace_buffer.buffer;
 		pc = preempt_count();
 		event = trace_buffer_lock_reserve(buffer, TRACE_BLK,
 						  sizeof(*t) + pdu_len,
@@ -1828,6 +1828,7 @@ void blk_fill_rwbs(char *rwbs, u32 rw, int bytes)
 
 	rwbs[i] = '\0';
 }
+EXPORT_SYMBOL_GPL(blk_fill_rwbs);
 
 #endif /* CONFIG_EVENT_TRACING */
 
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 6893d5a..dfd33f0 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -1067,7 +1067,7 @@ struct ftrace_func_probe {
 	unsigned long		flags;
 	unsigned long		ip;
 	void			*data;
-	struct rcu_head		rcu;
+	struct list_head	free_list;
 };
 
 struct ftrace_func_entry {
@@ -2974,28 +2974,27 @@ static void __disable_ftrace_function_probe(void)
 }
 
 
-static void ftrace_free_entry_rcu(struct rcu_head *rhp)
+static void ftrace_free_entry(struct ftrace_func_probe *entry)
 {
-	struct ftrace_func_probe *entry =
-		container_of(rhp, struct ftrace_func_probe, rcu);
-
 	if (entry->ops->free)
-		entry->ops->free(&entry->data);
+		entry->ops->free(entry->ops, entry->ip, &entry->data);
 	kfree(entry);
 }
 
-
 int
 register_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
 			      void *data)
 {
 	struct ftrace_func_probe *entry;
+	struct ftrace_hash **orig_hash = &trace_probe_ops.filter_hash;
+	struct ftrace_hash *hash;
 	struct ftrace_page *pg;
 	struct dyn_ftrace *rec;
 	int type, len, not;
 	unsigned long key;
 	int count = 0;
 	char *search;
+	int ret;
 
 	type = filter_parse_regex(glob, strlen(glob), &search, &not);
 	len = strlen(search);
@@ -3006,8 +3005,16 @@ register_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
 
 	mutex_lock(&ftrace_lock);
 
-	if (unlikely(ftrace_disabled))
+	hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, *orig_hash);
+	if (!hash) {
+		count = -ENOMEM;
+		goto out_unlock;
+	}
+
+	if (unlikely(ftrace_disabled)) {
+		count = -ENODEV;
 		goto out_unlock;
+	}
 
 	do_for_each_ftrace_rec(pg, rec) {
 
@@ -3031,14 +3038,21 @@ register_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
 		 * for each function we find. We call the callback
 		 * to give the caller an opportunity to do so.
 		 */
-		if (ops->callback) {
-			if (ops->callback(rec->ip, &entry->data) < 0) {
+		if (ops->init) {
+			if (ops->init(ops, rec->ip, &entry->data) < 0) {
 				/* caller does not like this func */
 				kfree(entry);
 				continue;
 			}
 		}
 
+		ret = enter_record(hash, rec, 0);
+		if (ret < 0) {
+			kfree(entry);
+			count = ret;
+			goto out_unlock;
+		}
+
 		entry->ops = ops;
 		entry->ip = rec->ip;
 
@@ -3046,10 +3060,16 @@ register_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
 		hlist_add_head_rcu(&entry->node, &ftrace_func_hash[key]);
 
 	} while_for_each_ftrace_rec();
+
+	ret = ftrace_hash_move(&trace_probe_ops, 1, orig_hash, hash);
+	if (ret < 0)
+		count = ret;
+
 	__enable_ftrace_function_probe();
 
  out_unlock:
 	mutex_unlock(&ftrace_lock);
+	free_ftrace_hash(hash);
 
 	return count;
 }
@@ -3063,7 +3083,12 @@ static void
 __unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
 				  void *data, int flags)
 {
+	struct ftrace_func_entry *rec_entry;
 	struct ftrace_func_probe *entry;
+	struct ftrace_func_probe *p;
+	struct ftrace_hash **orig_hash = &trace_probe_ops.filter_hash;
+	struct list_head free_list;
+	struct ftrace_hash *hash;
 	struct hlist_node *tmp;
 	char str[KSYM_SYMBOL_LEN];
 	int type = MATCH_FULL;
@@ -3084,6 +3109,14 @@ __unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
 	}
 
 	mutex_lock(&ftrace_lock);
+
+	hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, *orig_hash);
+	if (!hash)
+		/* Hmm, should report this somehow */
+		goto out_unlock;
+
+	INIT_LIST_HEAD(&free_list);
+
 	for (i = 0; i < FTRACE_FUNC_HASHSIZE; i++) {
 		struct hlist_head *hhd = &ftrace_func_hash[i];
 
@@ -3104,12 +3137,30 @@ __unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
 					continue;
 			}
 
+			rec_entry = ftrace_lookup_ip(hash, entry->ip);
+			/* It is possible more than one entry had this ip */
+			if (rec_entry)
+				free_hash_entry(hash, rec_entry);
+
 			hlist_del_rcu(&entry->node);
-			call_rcu_sched(&entry->rcu, ftrace_free_entry_rcu);
+			list_add(&entry->free_list, &free_list);
 		}
 	}
 	__disable_ftrace_function_probe();
+	/*
+	 * Remove after the disable is called. Otherwise, if the last
+	 * probe is removed, a null hash means *all enabled*.
+	 */
+	ftrace_hash_move(&trace_probe_ops, 1, orig_hash, hash);
+	synchronize_sched();
+	list_for_each_entry_safe(entry, p, &free_list, free_list) {
+		list_del(&entry->free_list);
+		ftrace_free_entry(entry);
+	}
+		
+ out_unlock:
 	mutex_unlock(&ftrace_lock);
+	free_ftrace_hash(hash);
 }
 
 void
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
index 6989df2..b59aea2 100644
--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -8,13 +8,16 @@
 #include <linux/trace_clock.h>
 #include <linux/trace_seq.h>
 #include <linux/spinlock.h>
+#include <linux/irq_work.h>
 #include <linux/debugfs.h>
 #include <linux/uaccess.h>
 #include <linux/hardirq.h>
+#include <linux/kthread.h>	/* for self test */
 #include <linux/kmemcheck.h>
 #include <linux/module.h>
 #include <linux/percpu.h>
 #include <linux/mutex.h>
+#include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/hash.h>
@@ -444,6 +447,12 @@ int ring_buffer_print_page_header(struct trace_seq *s)
 	return ret;
 }
 
+struct rb_irq_work {
+	struct irq_work			work;
+	wait_queue_head_t		waiters;
+	bool				waiters_pending;
+};
+
 /*
  * head_page == tail_page && head == tail then buffer is empty.
  */
@@ -478,6 +487,8 @@ struct ring_buffer_per_cpu {
 	struct list_head		new_pages; /* new pages to add */
 	struct work_struct		update_pages_work;
 	struct completion		update_done;
+
+	struct rb_irq_work		irq_work;
 };
 
 struct ring_buffer {
@@ -497,6 +508,8 @@ struct ring_buffer {
 	struct notifier_block		cpu_notify;
 #endif
 	u64				(*clock)(void);
+
+	struct rb_irq_work		irq_work;
 };
 
 struct ring_buffer_iter {
@@ -508,6 +521,118 @@ struct ring_buffer_iter {
 	u64				read_stamp;
 };
 
+/*
+ * rb_wake_up_waiters - wake up tasks waiting for ring buffer input
+ *
+ * Schedules a delayed work to wake up any task that is blocked on the
+ * ring buffer waiters queue.
+ */
+static void rb_wake_up_waiters(struct irq_work *work)
+{
+	struct rb_irq_work *rbwork = container_of(work, struct rb_irq_work, work);
+
+	wake_up_all(&rbwork->waiters);
+}
+
+/**
+ * ring_buffer_wait - wait for input to the ring buffer
+ * @buffer: buffer to wait on
+ * @cpu: the cpu buffer to wait on
+ *
+ * If @cpu == RING_BUFFER_ALL_CPUS then the task will wake up as soon
+ * as data is added to any of the @buffer's cpu buffers. Otherwise
+ * it will wait for data to be added to a specific cpu buffer.
+ */
+void ring_buffer_wait(struct ring_buffer *buffer, int cpu)
+{
+	struct ring_buffer_per_cpu *cpu_buffer;
+	DEFINE_WAIT(wait);
+	struct rb_irq_work *work;
+
+	/*
+	 * Depending on what the caller is waiting for, either any
+	 * data in any cpu buffer, or a specific buffer, put the
+	 * caller on the appropriate wait queue.
+	 */
+	if (cpu == RING_BUFFER_ALL_CPUS)
+		work = &buffer->irq_work;
+	else {
+		cpu_buffer = buffer->buffers[cpu];
+		work = &cpu_buffer->irq_work;
+	}
+
+
+	prepare_to_wait(&work->waiters, &wait, TASK_INTERRUPTIBLE);
+
+	/*
+	 * The events can happen in critical sections where
+	 * checking a work queue can cause deadlocks.
+	 * After adding a task to the queue, this flag is set
+	 * only to notify events to try to wake up the queue
+	 * using irq_work.
+	 *
+	 * We don't clear it even if the buffer is no longer
+	 * empty. The flag only causes the next event to run
+	 * irq_work to do the work queue wake up. The worse
+	 * that can happen if we race with !trace_empty() is that
+	 * an event will cause an irq_work to try to wake up
+	 * an empty queue.
+	 *
+	 * There's no reason to protect this flag either, as
+	 * the work queue and irq_work logic will do the necessary
+	 * synchronization for the wake ups. The only thing
+	 * that is necessary is that the wake up happens after
+	 * a task has been queued. It's OK for spurious wake ups.
+	 */
+	work->waiters_pending = true;
+
+	if ((cpu == RING_BUFFER_ALL_CPUS && ring_buffer_empty(buffer)) ||
+	    (cpu != RING_BUFFER_ALL_CPUS && ring_buffer_empty_cpu(buffer, cpu)))
+		schedule();
+
+	finish_wait(&work->waiters, &wait);
+}
+
+/**
+ * ring_buffer_poll_wait - poll on buffer input
+ * @buffer: buffer to wait on
+ * @cpu: the cpu buffer to wait on
+ * @filp: the file descriptor
+ * @poll_table: The poll descriptor
+ *
+ * If @cpu == RING_BUFFER_ALL_CPUS then the task will wake up as soon
+ * as data is added to any of the @buffer's cpu buffers. Otherwise
+ * it will wait for data to be added to a specific cpu buffer.
+ *
+ * Returns POLLIN | POLLRDNORM if data exists in the buffers,
+ * zero otherwise.
+ */
+int ring_buffer_poll_wait(struct ring_buffer *buffer, int cpu,
+			  struct file *filp, poll_table *poll_table)
+{
+	struct ring_buffer_per_cpu *cpu_buffer;
+	struct rb_irq_work *work;
+
+	if ((cpu == RING_BUFFER_ALL_CPUS && !ring_buffer_empty(buffer)) ||
+	    (cpu != RING_BUFFER_ALL_CPUS && !ring_buffer_empty_cpu(buffer, cpu)))
+		return POLLIN | POLLRDNORM;
+
+	if (cpu == RING_BUFFER_ALL_CPUS)
+		work = &buffer->irq_work;
+	else {
+		cpu_buffer = buffer->buffers[cpu];
+		work = &cpu_buffer->irq_work;
+	}
+
+	work->waiters_pending = true;
+	poll_wait(filp, &work->waiters, poll_table);
+
+	if ((cpu == RING_BUFFER_ALL_CPUS && !ring_buffer_empty(buffer)) ||
+	    (cpu != RING_BUFFER_ALL_CPUS && !ring_buffer_empty_cpu(buffer, cpu)))
+		return POLLIN | POLLRDNORM;
+	return 0;
+}
+
 /* buffer may be either ring_buffer or ring_buffer_per_cpu */
 #define RB_WARN_ON(b, cond)						\
 	({								\
@@ -1063,6 +1188,8 @@ rb_allocate_cpu_buffer(struct ring_buffer *buffer, int nr_pages, int cpu)
 	cpu_buffer->lock = (arch_spinlock_t)__ARCH_SPIN_LOCK_UNLOCKED;
 	INIT_WORK(&cpu_buffer->update_pages_work, update_pages_handler);
 	init_completion(&cpu_buffer->update_done);
+	init_irq_work(&cpu_buffer->irq_work.work, rb_wake_up_waiters);
+	init_waitqueue_head(&cpu_buffer->irq_work.waiters);
 
 	bpage = kzalloc_node(ALIGN(sizeof(*bpage), cache_line_size()),
 			    GFP_KERNEL, cpu_to_node(cpu));
@@ -1158,6 +1285,9 @@ struct ring_buffer *__ring_buffer_alloc(unsigned long size, unsigned flags,
 	buffer->clock = trace_clock_local;
 	buffer->reader_lock_key = key;
 
+	init_irq_work(&buffer->irq_work.work, rb_wake_up_waiters);
+	init_waitqueue_head(&buffer->irq_work.waiters);
+
 	/* need at least two pages */
 	if (nr_pages < 2)
 		nr_pages = 2;
@@ -1553,11 +1683,22 @@ int ring_buffer_resize(struct ring_buffer *buffer, unsigned long size,
 			if (!cpu_buffer->nr_pages_to_update)
 				continue;
 
-			if (cpu_online(cpu))
+			/* The update must run on the CPU that is being updated. */
+			preempt_disable();
+			if (cpu == smp_processor_id() || !cpu_online(cpu)) {
+				rb_update_pages(cpu_buffer);
+				cpu_buffer->nr_pages_to_update = 0;
+			} else {
+				/*
+				 * Can not disable preemption for schedule_work_on()
+				 * on PREEMPT_RT.
+				 */
+				preempt_enable();
 				schedule_work_on(cpu,
 						&cpu_buffer->update_pages_work);
-			else
-				rb_update_pages(cpu_buffer);
+				preempt_disable();
+			}
+			preempt_enable();
 		}
 
 		/* wait for all the updates to complete */
@@ -1595,12 +1736,22 @@ int ring_buffer_resize(struct ring_buffer *buffer, unsigned long size,
 
 		get_online_cpus();
 
-		if (cpu_online(cpu_id)) {
+		preempt_disable();
+		/* The update must run on the CPU that is being updated. */
+		if (cpu_id == smp_processor_id() || !cpu_online(cpu_id))
+			rb_update_pages(cpu_buffer);
+		else {
+			/*
+			 * Can not disable preemption for schedule_work_on()
+			 * on PREEMPT_RT.
+			 */
+			preempt_enable();
 			schedule_work_on(cpu_id,
 					 &cpu_buffer->update_pages_work);
 			wait_for_completion(&cpu_buffer->update_done);
-		} else
-			rb_update_pages(cpu_buffer);
+			preempt_disable();
+		}
+		preempt_enable();
 
 		cpu_buffer->nr_pages_to_update = 0;
 		put_online_cpus();
@@ -2612,6 +2763,22 @@ static void rb_commit(struct ring_buffer_per_cpu *cpu_buffer,
 	rb_end_commit(cpu_buffer);
 }
 
+static __always_inline void
+rb_wakeups(struct ring_buffer *buffer, struct ring_buffer_per_cpu *cpu_buffer)
+{
+	if (buffer->irq_work.waiters_pending) {
+		buffer->irq_work.waiters_pending = false;
+		/* irq_work_queue() supplies it's own memory barriers */
+		irq_work_queue(&buffer->irq_work.work);
+	}
+
+	if (cpu_buffer->irq_work.waiters_pending) {
+		cpu_buffer->irq_work.waiters_pending = false;
+		/* irq_work_queue() supplies it's own memory barriers */
+		irq_work_queue(&cpu_buffer->irq_work.work);
+	}
+}
+
 /**
  * ring_buffer_unlock_commit - commit a reserved
  * @buffer: The buffer to commit to
@@ -2631,6 +2798,8 @@ int ring_buffer_unlock_commit(struct ring_buffer *buffer,
 
 	rb_commit(cpu_buffer, event);
 
+	rb_wakeups(buffer, cpu_buffer);
+
 	trace_recursive_unlock();
 
 	preempt_enable_notrace();
@@ -2803,6 +2972,8 @@ int ring_buffer_write(struct ring_buffer *buffer,
 
 	rb_commit(cpu_buffer, event);
 
+	rb_wakeups(buffer, cpu_buffer);
+
 	ret = 0;
  out:
 	preempt_enable_notrace();
@@ -4467,3 +4638,320 @@ static int rb_cpu_notify(struct notifier_block *self,
 	return NOTIFY_OK;
 }
 #endif
+
+#ifdef CONFIG_RING_BUFFER_STARTUP_TEST
+/*
+ * This is a basic integrity check of the ring buffer.
+ * Late in the boot cycle this test will run when configured in.
+ * It will kick off a thread per CPU that will go into a loop
+ * writing to the per cpu ring buffer various sizes of data.
+ * Some of the data will be large items, some small.
+ *
+ * Another thread is created that goes into a spin, sending out
+ * IPIs to the other CPUs to also write into the ring buffer.
+ * this is to test the nesting ability of the buffer.
+ *
+ * Basic stats are recorded and reported. If something in the
+ * ring buffer should happen that's not expected, a big warning
+ * is displayed and all ring buffers are disabled.
+ */
+static struct task_struct *rb_threads[NR_CPUS] __initdata;
+
+struct rb_test_data {
+	struct ring_buffer	*buffer;
+	unsigned long		events;
+	unsigned long		bytes_written;
+	unsigned long		bytes_alloc;
+	unsigned long		bytes_dropped;
+	unsigned long		events_nested;
+	unsigned long		bytes_written_nested;
+	unsigned long		bytes_alloc_nested;
+	unsigned long		bytes_dropped_nested;
+	int			min_size_nested;
+	int			max_size_nested;
+	int			max_size;
+	int			min_size;
+	int			cpu;
+	int			cnt;
+};
+
+static struct rb_test_data rb_data[NR_CPUS] __initdata;
+
+/* 1 meg per cpu */
+#define RB_TEST_BUFFER_SIZE	1048576
+
+static char rb_string[] __initdata =
+	"abcdefghijklmnopqrstuvwxyz1234567890!@#$%^&*()?+\\"
+	"?+|:';\",.<>/?abcdefghijklmnopqrstuvwxyz1234567890"
+	"!@#$%^&*()?+\\?+|:';\",.<>/?abcdefghijklmnopqrstuv";
+
+static bool rb_test_started __initdata;
+
+struct rb_item {
+	int size;
+	char str[];
+};
+
+static __init int rb_write_something(struct rb_test_data *data, bool nested)
+{
+	struct ring_buffer_event *event;
+	struct rb_item *item;
+	bool started;
+	int event_len;
+	int size;
+	int len;
+	int cnt;
+
+	/* Have nested writes different that what is written */
+	cnt = data->cnt + (nested ? 27 : 0);
+
+	/* Multiply cnt by ~e, to make some unique increment */
+	size = (data->cnt * 68 / 25) % (sizeof(rb_string) - 1);
+
+	len = size + sizeof(struct rb_item);
+
+	started = rb_test_started;
+	/* read rb_test_started before checking buffer enabled */
+	smp_rmb();
+
+	event = ring_buffer_lock_reserve(data->buffer, len);
+	if (!event) {
+		/* Ignore dropped events before test starts. */
+		if (started) {
+			if (nested)
+				data->bytes_dropped += len;
+			else
+				data->bytes_dropped_nested += len;
+		}
+		return len;
+	}
+
+	event_len = ring_buffer_event_length(event);
+
+	if (RB_WARN_ON(data->buffer, event_len < len))
+		goto out;
+
+	item = ring_buffer_event_data(event);
+	item->size = size;
+	memcpy(item->str, rb_string, size);
+
+	if (nested) {
+		data->bytes_alloc_nested += event_len;
+		data->bytes_written_nested += len;
+		data->events_nested++;
+		if (!data->min_size_nested || len < data->min_size_nested)
+			data->min_size_nested = len;
+		if (len > data->max_size_nested)
+			data->max_size_nested = len;
+	} else {
+		data->bytes_alloc += event_len;
+		data->bytes_written += len;
+		data->events++;
+		if (!data->min_size || len < data->min_size)
+			data->max_size = len;
+		if (len > data->max_size)
+			data->max_size = len;
+	}
+
+ out:
+	ring_buffer_unlock_commit(data->buffer, event);
+
+	return 0;
+}
+
+static __init int rb_test(void *arg)
+{
+	struct rb_test_data *data = arg;
+
+	while (!kthread_should_stop()) {
+		rb_write_something(data, false);
+		data->cnt++;
+
+		set_current_state(TASK_INTERRUPTIBLE);
+		/* Now sleep between a min of 100-300us and a max of 1ms */
+		usleep_range(((data->cnt % 3) + 1) * 100, 1000);
+	}
+
+	return 0;
+}
+
+static __init void rb_ipi(void *ignore)
+{
+	struct rb_test_data *data;
+	int cpu = smp_processor_id();
+
+	data = &rb_data[cpu];
+	rb_write_something(data, true);
+}
+
+static __init int rb_hammer_test(void *arg)
+{
+	while (!kthread_should_stop()) {
+
+		/* Send an IPI to all cpus to write data! */
+		smp_call_function(rb_ipi, NULL, 1);
+		/* No sleep, but for non preempt, let others run */
+		schedule();
+	}
+
+	return 0;
+}
+
+static __init int test_ringbuffer(void)
+{
+	struct task_struct *rb_hammer;
+	struct ring_buffer *buffer;
+	int cpu;
+	int ret = 0;
+
+	pr_info("Running ring buffer tests...\n");
+
+	buffer = ring_buffer_alloc(RB_TEST_BUFFER_SIZE, RB_FL_OVERWRITE);
+	if (WARN_ON(!buffer))
+		return 0;
+
+	/* Disable buffer so that threads can't write to it yet */
+	ring_buffer_record_off(buffer);
+
+	for_each_online_cpu(cpu) {
+		rb_data[cpu].buffer = buffer;
+		rb_data[cpu].cpu = cpu;
+		rb_data[cpu].cnt = cpu;
+		rb_threads[cpu] = kthread_create(rb_test, &rb_data[cpu],
+						 "rbtester/%d", cpu);
+		if (WARN_ON(!rb_threads[cpu])) {
+			pr_cont("FAILED\n");
+			ret = -1;
+			goto out_free;
+		}
+
+		kthread_bind(rb_threads[cpu], cpu);
+ 		wake_up_process(rb_threads[cpu]);
+	}
+
+	/* Now create the rb hammer! */
+	rb_hammer = kthread_run(rb_hammer_test, NULL, "rbhammer");
+	if (WARN_ON(!rb_hammer)) {
+		pr_cont("FAILED\n");
+		ret = -1;
+		goto out_free;
+	}
+
+	ring_buffer_record_on(buffer);
+	/*
+	 * Show buffer is enabled before setting rb_test_started.
+	 * Yes there's a small race window where events could be
+	 * dropped and the thread wont catch it. But when a ring
+	 * buffer gets enabled, there will always be some kind of
+	 * delay before other CPUs see it. Thus, we don't care about
+	 * those dropped events. We care about events dropped after
+	 * the threads see that the buffer is active.
+	 */
+	smp_wmb();
+	rb_test_started = true;
+
+	set_current_state(TASK_INTERRUPTIBLE);
+	/* Just run for 10 seconds */;
+	schedule_timeout(10 * HZ);
+
+	kthread_stop(rb_hammer);
+
+ out_free:
+	for_each_online_cpu(cpu) {
+		if (!rb_threads[cpu])
+			break;
+		kthread_stop(rb_threads[cpu]);
+	}
+	if (ret) {
+		ring_buffer_free(buffer);
+		return ret;
+	}
+
+	/* Report! */
+	pr_info("finished\n");
+	for_each_online_cpu(cpu) {
+		struct ring_buffer_event *event;
+		struct rb_test_data *data = &rb_data[cpu];
+		struct rb_item *item;
+		unsigned long total_events;
+		unsigned long total_dropped;
+		unsigned long total_written;
+		unsigned long total_alloc;
+		unsigned long total_read = 0;
+		unsigned long total_size = 0;
+		unsigned long total_len = 0;
+		unsigned long total_lost = 0;
+		unsigned long lost;
+		int big_event_size;
+		int small_event_size;
+
+		ret = -1;
+
+		total_events = data->events + data->events_nested;
+		total_written = data->bytes_written + data->bytes_written_nested;
+		total_alloc = data->bytes_alloc + data->bytes_alloc_nested;
+		total_dropped = data->bytes_dropped + data->bytes_dropped_nested;
+
+		big_event_size = data->max_size + data->max_size_nested;
+		small_event_size = data->min_size + data->min_size_nested;
+
+		pr_info("CPU %d:\n", cpu);
+		pr_info("              events:    %ld\n", total_events);
+		pr_info("       dropped bytes:    %ld\n", total_dropped);
+		pr_info("       alloced bytes:    %ld\n", total_alloc);
+		pr_info("       written bytes:    %ld\n", total_written);
+		pr_info("       biggest event:    %d\n", big_event_size);
+		pr_info("      smallest event:    %d\n", small_event_size);
+
+		if (RB_WARN_ON(buffer, total_dropped))
+			break;
+
+		ret = 0;
+
+		while ((event = ring_buffer_consume(buffer, cpu, NULL, &lost))) {
+			total_lost += lost;
+			item = ring_buffer_event_data(event);
+			total_len += ring_buffer_event_length(event);
+			total_size += item->size + sizeof(struct rb_item);
+			if (memcmp(&item->str[0], rb_string, item->size) != 0) {
+				pr_info("FAILED!\n");
+				pr_info("buffer had: %.*s\n", item->size, item->str);
+				pr_info("expected:   %.*s\n", item->size, rb_string);
+				RB_WARN_ON(buffer, 1);
+				ret = -1;
+				break;
+			}
+			total_read++;
+		}
+		if (ret)
+			break;
+
+		ret = -1;
+
+		pr_info("         read events:   %ld\n", total_read);
+		pr_info("         lost events:   %ld\n", total_lost);
+		pr_info("        total events:   %ld\n", total_lost + total_read);
+		pr_info("  recorded len bytes:   %ld\n", total_len);
+		pr_info(" recorded size bytes:   %ld\n", total_size);
+		if (total_lost)
+			pr_info(" With dropped events, record len and size may not match\n"
+				" alloced and written from above\n");
+		if (!total_lost) {
+			if (RB_WARN_ON(buffer, total_len != total_alloc ||
+				       total_size != total_written))
+				break;
+		}
+		if (RB_WARN_ON(buffer, total_lost + total_read != total_events))
+			break;
+
+		ret = 0;
+	}
+	if (!ret)
+		pr_info("Ring buffer PASSED!\n");
+
+	ring_buffer_free(buffer);
+	return 0;
+}
+
+late_initcall(test_ringbuffer);
+#endif /* CONFIG_RING_BUFFER_STARTUP_TEST */
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 4f1dade..829b2be 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -1,7 +1,7 @@
 /*
  * ring buffer based function tracer
  *
- * Copyright (C) 2007-2008 Steven Rostedt <srostedt@redhat.com>
+ * Copyright (C) 2007-2012 Steven Rostedt <srostedt@redhat.com>
  * Copyright (C) 2008 Ingo Molnar <mingo@redhat.com>
  *
  * Originally taken from the RT patch by:
@@ -19,7 +19,6 @@
 #include <linux/seq_file.h>
 #include <linux/notifier.h>
 #include <linux/irqflags.h>
-#include <linux/irq_work.h>
 #include <linux/debugfs.h>
 #include <linux/pagemap.h>
 #include <linux/hardirq.h>
@@ -48,7 +47,7 @@
  * On boot up, the ring buffer is set to the minimum size, so that
  * we do not waste memory on systems that are not using tracing.
  */
-int ring_buffer_expanded;
+bool ring_buffer_expanded;
 
 /*
  * We need to change this state when a selftest is running.
@@ -87,14 +86,6 @@ static int dummy_set_flag(u32 old_flags, u32 bit, int set)
 static DEFINE_PER_CPU(bool, trace_cmdline_save);
 
 /*
- * When a reader is waiting for data, then this variable is
- * set to true.
- */
-static bool trace_wakeup_needed;
-
-static struct irq_work trace_work_wakeup;
-
-/*
  * Kill all tracing for good (never come back).
  * It is initialized to 1 but will turn to zero if the initialization
  * of the tracer is successful. But that is the only place that sets
@@ -130,12 +121,14 @@ static int tracing_set_tracer(const char *buf);
 static char bootup_tracer_buf[MAX_TRACER_SIZE] __initdata;
 static char *default_bootup_tracer;
 
+static bool allocate_snapshot;
+
 static int __init set_cmdline_ftrace(char *str)
 {
 	strncpy(bootup_tracer_buf, str, MAX_TRACER_SIZE);
 	default_bootup_tracer = bootup_tracer_buf;
 	/* We are using ftrace early, expand it */
-	ring_buffer_expanded = 1;
+	ring_buffer_expanded = true;
 	return 1;
 }
 __setup("ftrace=", set_cmdline_ftrace);
@@ -156,6 +149,15 @@ static int __init set_ftrace_dump_on_oops(char *str)
 }
 __setup("ftrace_dump_on_oops", set_ftrace_dump_on_oops);
 
+static int __init boot_alloc_snapshot(char *str)
+{
+	allocate_snapshot = true;
+	/* We also need the main ring buffer expanded */
+	ring_buffer_expanded = true;
+	return 1;
+}
+__setup("alloc_snapshot", boot_alloc_snapshot);
+
 
 static char trace_boot_options_buf[MAX_TRACER_SIZE] __initdata;
 static char *trace_boot_options __initdata;
@@ -189,7 +191,7 @@ unsigned long long ns2usecs(cycle_t nsec)
  */
 static struct trace_array	global_trace;
 
-static DEFINE_PER_CPU(struct trace_array_cpu, global_trace_cpu);
+LIST_HEAD(ftrace_trace_arrays);
 
 int filter_current_check_discard(struct ring_buffer *buffer,
 				 struct ftrace_event_call *call, void *rec,
@@ -204,29 +206,15 @@ cycle_t ftrace_now(int cpu)
 	u64 ts;
 
 	/* Early boot up does not have a buffer yet */
-	if (!global_trace.buffer)
+	if (!global_trace.trace_buffer.buffer)
 		return trace_clock_local();
 
-	ts = ring_buffer_time_stamp(global_trace.buffer, cpu);
-	ring_buffer_normalize_time_stamp(global_trace.buffer, cpu, &ts);
+	ts = ring_buffer_time_stamp(global_trace.trace_buffer.buffer, cpu);
+	ring_buffer_normalize_time_stamp(global_trace.trace_buffer.buffer, cpu, &ts);
 
 	return ts;
 }
 
-/*
- * The max_tr is used to snapshot the global_trace when a maximum
- * latency is reached. Some tracers will use this to store a maximum
- * trace while it continues examining live traces.
- *
- * The buffers for the max_tr are set up the same as the global_trace.
- * When a snapshot is taken, the link list of the max_tr is swapped
- * with the link list of the global_trace and the buffers are reset for
- * the global_trace so the tracing can continue.
- */
-static struct trace_array	max_tr;
-
-static DEFINE_PER_CPU(struct trace_array_cpu, max_tr_data);
-
 int tracing_is_enabled(void)
 {
 	return tracing_is_on();
@@ -249,9 +237,6 @@ static unsigned long		trace_buf_size = TRACE_BUF_SIZE_DEFAULT;
 /* trace_types holds a link list of available tracers. */
 static struct tracer		*trace_types __read_mostly;
 
-/* current_trace points to the tracer that is currently active */
-static struct tracer		*current_trace __read_mostly = &nop_trace;
-
 /*
  * trace_types_lock is used to protect the trace_types list.
  */
@@ -285,13 +270,13 @@ static DEFINE_PER_CPU(struct mutex, cpu_access_lock);
 
 static inline void trace_access_lock(int cpu)
 {
-	if (cpu == TRACE_PIPE_ALL_CPU) {
+	if (cpu == RING_BUFFER_ALL_CPUS) {
 		/* gain it for accessing the whole ring buffer. */
 		down_write(&all_cpu_access_lock);
 	} else {
 		/* gain it for accessing a cpu ring buffer. */
 
-		/* Firstly block other trace_access_lock(TRACE_PIPE_ALL_CPU). */
+		/* Firstly block other trace_access_lock(RING_BUFFER_ALL_CPUS). */
 		down_read(&all_cpu_access_lock);
 
 		/* Secondly block other access to this @cpu ring buffer. */
@@ -301,7 +286,7 @@ static inline void trace_access_lock(int cpu)
 
 static inline void trace_access_unlock(int cpu)
 {
-	if (cpu == TRACE_PIPE_ALL_CPU) {
+	if (cpu == RING_BUFFER_ALL_CPUS) {
 		up_write(&all_cpu_access_lock);
 	} else {
 		mutex_unlock(&per_cpu(cpu_access_lock, cpu));
@@ -339,30 +324,11 @@ static inline void trace_access_lock_init(void)
 
 #endif
 
-/* trace_wait is a waitqueue for tasks blocked on trace_poll */
-static DECLARE_WAIT_QUEUE_HEAD(trace_wait);
-
 /* trace_flags holds trace_options default values */
 unsigned long trace_flags = TRACE_ITER_PRINT_PARENT | TRACE_ITER_PRINTK |
 	TRACE_ITER_ANNOTATE | TRACE_ITER_CONTEXT_INFO | TRACE_ITER_SLEEP_TIME |
 	TRACE_ITER_GRAPH_TIME | TRACE_ITER_RECORD_CMD | TRACE_ITER_OVERWRITE |
-	TRACE_ITER_IRQ_INFO | TRACE_ITER_MARKERS;
-
-static int trace_stop_count;
-static DEFINE_RAW_SPINLOCK(tracing_start_lock);
-
-/**
- * trace_wake_up - wake up tasks waiting for trace input
- *
- * 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.
- */
-static void trace_wake_up(struct irq_work *work)
-{
-	wake_up_all(&trace_wait);
-
-}
+	TRACE_ITER_IRQ_INFO | TRACE_ITER_MARKERS | TRACE_ITER_FUNCTION;
 
 /**
  * tracing_on - enable tracing buffers
@@ -372,8 +338,8 @@ static void trace_wake_up(struct irq_work *work)
  */
 void tracing_on(void)
 {
-	if (global_trace.buffer)
-		ring_buffer_record_on(global_trace.buffer);
+	if (global_trace.trace_buffer.buffer)
+		ring_buffer_record_on(global_trace.trace_buffer.buffer);
 	/*
 	 * This flag is only looked at when buffers haven't been
 	 * allocated yet. We don't really care about the race
@@ -385,6 +351,196 @@ void tracing_on(void)
 EXPORT_SYMBOL_GPL(tracing_on);
 
 /**
+ * __trace_puts - write a constant string into the trace buffer.
+ * @ip:	   The address of the caller
+ * @str:   The constant string to write
+ * @size:  The size of the string.
+ */
+int __trace_puts(unsigned long ip, const char *str, int size)
+{
+	struct ring_buffer_event *event;
+	struct ring_buffer *buffer;
+	struct print_entry *entry;
+	unsigned long irq_flags;
+	int alloc;
+
+	alloc = sizeof(*entry) + size + 2; /* possible \n added */
+
+	local_save_flags(irq_flags);
+	buffer = global_trace.trace_buffer.buffer;
+	event = trace_buffer_lock_reserve(buffer, TRACE_PRINT, alloc, 
+					  irq_flags, preempt_count());
+	if (!event)
+		return 0;
+
+	entry = ring_buffer_event_data(event);
+	entry->ip = ip;
+
+	memcpy(&entry->buf, str, size);
+
+	/* Add a newline if necessary */
+	if (entry->buf[size - 1] != '\n') {
+		entry->buf[size] = '\n';
+		entry->buf[size + 1] = '\0';
+	} else
+		entry->buf[size] = '\0';
+
+	__buffer_unlock_commit(buffer, event);
+
+	return size;
+}
+EXPORT_SYMBOL_GPL(__trace_puts);
+
+/**
+ * __trace_bputs - write the pointer to a constant string into trace buffer
+ * @ip:	   The address of the caller
+ * @str:   The constant string to write to the buffer to
+ */
+int __trace_bputs(unsigned long ip, const char *str)
+{
+	struct ring_buffer_event *event;
+	struct ring_buffer *buffer;
+	struct bputs_entry *entry;
+	unsigned long irq_flags;
+	int size = sizeof(struct bputs_entry);
+
+	local_save_flags(irq_flags);
+	buffer = global_trace.trace_buffer.buffer;
+	event = trace_buffer_lock_reserve(buffer, TRACE_BPUTS, size,
+					  irq_flags, preempt_count());
+	if (!event)
+		return 0;
+
+	entry = ring_buffer_event_data(event);
+	entry->ip			= ip;
+	entry->str			= str;
+
+	__buffer_unlock_commit(buffer, event);
+
+	return 1;
+}
+EXPORT_SYMBOL_GPL(__trace_bputs);
+
+#ifdef CONFIG_TRACER_SNAPSHOT
+/**
+ * trace_snapshot - take a snapshot of the current buffer.
+ *
+ * This causes a swap between the snapshot buffer and the current live
+ * tracing buffer. You can use this to take snapshots of the live
+ * trace when some condition is triggered, but continue to trace.
+ *
+ * Note, make sure to allocate the snapshot with either
+ * a tracing_snapshot_alloc(), or by doing it manually
+ * with: echo 1 > /sys/kernel/debug/tracing/snapshot
+ *
+ * If the snapshot buffer is not allocated, it will stop tracing.
+ * Basically making a permanent snapshot.
+ */
+void tracing_snapshot(void)
+{
+	struct trace_array *tr = &global_trace;
+	struct tracer *tracer = tr->current_trace;
+	unsigned long flags;
+
+	if (in_nmi()) {
+		internal_trace_puts("*** SNAPSHOT CALLED FROM NMI CONTEXT ***\n");
+		internal_trace_puts("*** snapshot is being ignored        ***\n");
+		return;
+	}
+
+	if (!tr->allocated_snapshot) {
+		internal_trace_puts("*** SNAPSHOT NOT ALLOCATED ***\n");
+		internal_trace_puts("*** stopping trace here!   ***\n");
+		tracing_off();
+		return;
+	}
+
+	/* Note, snapshot can not be used when the tracer uses it */
+	if (tracer->use_max_tr) {
+		internal_trace_puts("*** LATENCY TRACER ACTIVE ***\n");
+		internal_trace_puts("*** Can not use snapshot (sorry) ***\n");
+		return;
+	}
+
+	local_irq_save(flags);
+	update_max_tr(tr, current, smp_processor_id());
+	local_irq_restore(flags);
+}
+EXPORT_SYMBOL_GPL(tracing_snapshot);
+
+static int resize_buffer_duplicate_size(struct trace_buffer *trace_buf,
+					struct trace_buffer *size_buf, int cpu_id);
+static void set_buffer_entries(struct trace_buffer *buf, unsigned long val);
+
+static int alloc_snapshot(struct trace_array *tr)
+{
+	int ret;
+
+	if (!tr->allocated_snapshot) {
+
+		/* allocate spare buffer */
+		ret = resize_buffer_duplicate_size(&tr->max_buffer,
+				   &tr->trace_buffer, RING_BUFFER_ALL_CPUS);
+		if (ret < 0)
+			return ret;
+
+		tr->allocated_snapshot = true;
+	}
+
+	return 0;
+}
+
+void free_snapshot(struct trace_array *tr)
+{
+	/*
+	 * We don't free the ring buffer. instead, resize it because
+	 * The max_tr ring buffer has some state (e.g. ring->clock) and
+	 * we want preserve it.
+	 */
+	ring_buffer_resize(tr->max_buffer.buffer, 1, RING_BUFFER_ALL_CPUS);
+	set_buffer_entries(&tr->max_buffer, 1);
+	tracing_reset_online_cpus(&tr->max_buffer);
+	tr->allocated_snapshot = false;
+}
+
+/**
+ * trace_snapshot_alloc - allocate and take a snapshot of the current buffer.
+ *
+ * This is similar to trace_snapshot(), but it will allocate the
+ * snapshot buffer if it isn't already allocated. Use this only
+ * where it is safe to sleep, as the allocation may sleep.
+ *
+ * This causes a swap between the snapshot buffer and the current live
+ * tracing buffer. You can use this to take snapshots of the live
+ * trace when some condition is triggered, but continue to trace.
+ */
+void tracing_snapshot_alloc(void)
+{
+	struct trace_array *tr = &global_trace;
+	int ret;
+
+	ret = alloc_snapshot(tr);
+	if (WARN_ON(ret < 0))
+		return;
+
+	tracing_snapshot();
+}
+EXPORT_SYMBOL_GPL(tracing_snapshot_alloc);
+#else
+void tracing_snapshot(void)
+{
+	WARN_ONCE(1, "Snapshot feature not enabled, but internal snapshot used");
+}
+EXPORT_SYMBOL_GPL(tracing_snapshot);
+void tracing_snapshot_alloc(void)
+{
+	/* Give warning */
+	tracing_snapshot();
+}
+EXPORT_SYMBOL_GPL(tracing_snapshot_alloc);
+#endif /* CONFIG_TRACER_SNAPSHOT */
+
+/**
  * tracing_off - turn off tracing buffers
  *
  * This function stops the tracing buffers from recording data.
@@ -394,8 +550,8 @@ EXPORT_SYMBOL_GPL(tracing_on);
  */
 void tracing_off(void)
 {
-	if (global_trace.buffer)
-		ring_buffer_record_off(global_trace.buffer);
+	if (global_trace.trace_buffer.buffer)
+		ring_buffer_record_off(global_trace.trace_buffer.buffer);
 	/*
 	 * This flag is only looked at when buffers haven't been
 	 * allocated yet. We don't really care about the race
@@ -411,8 +567,8 @@ EXPORT_SYMBOL_GPL(tracing_off);
  */
 int tracing_is_on(void)
 {
-	if (global_trace.buffer)
-		return ring_buffer_record_is_on(global_trace.buffer);
+	if (global_trace.trace_buffer.buffer)
+		return ring_buffer_record_is_on(global_trace.trace_buffer.buffer);
 	return !global_trace.buffer_disabled;
 }
 EXPORT_SYMBOL_GPL(tracing_is_on);
@@ -479,6 +635,7 @@ static const char *trace_options[] = {
 	"disable_on_free",
 	"irq-info",
 	"markers",
+	"function-trace",
 	NULL
 };
 
@@ -490,6 +647,8 @@ static struct {
 	{ trace_clock_local,	"local",	1 },
 	{ trace_clock_global,	"global",	1 },
 	{ trace_clock_counter,	"counter",	0 },
+	{ trace_clock_jiffies,	"uptime",	1 },
+	{ trace_clock,		"perf",		1 },
 	ARCH_TRACE_CLOCKS
 };
 
@@ -670,13 +829,14 @@ unsigned long __read_mostly	tracing_max_latency;
 static void
 __update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu)
 {
-	struct trace_array_cpu *data = tr->data[cpu];
-	struct trace_array_cpu *max_data;
+	struct trace_buffer *trace_buf = &tr->trace_buffer;
+	struct trace_buffer *max_buf = &tr->max_buffer;
+	struct trace_array_cpu *data = per_cpu_ptr(trace_buf->data, cpu);
+	struct trace_array_cpu *max_data = per_cpu_ptr(max_buf->data, cpu);
 
-	max_tr.cpu = cpu;
-	max_tr.time_start = data->preempt_timestamp;
+	max_buf->cpu = cpu;
+	max_buf->time_start = data->preempt_timestamp;
 
-	max_data = max_tr.data[cpu];
 	max_data->saved_latency = tracing_max_latency;
 	max_data->critical_start = data->critical_start;
 	max_data->critical_end = data->critical_end;
@@ -706,22 +866,22 @@ update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu)
 {
 	struct ring_buffer *buf;
 
-	if (trace_stop_count)
+	if (tr->stop_count)
 		return;
 
 	WARN_ON_ONCE(!irqs_disabled());
 
-	if (!current_trace->allocated_snapshot) {
+	if (!tr->allocated_snapshot) {
 		/* Only the nop tracer should hit this when disabling */
-		WARN_ON_ONCE(current_trace != &nop_trace);
+		WARN_ON_ONCE(tr->current_trace != &nop_trace);
 		return;
 	}
 
 	arch_spin_lock(&ftrace_max_lock);
 
-	buf = tr->buffer;
-	tr->buffer = max_tr.buffer;
-	max_tr.buffer = buf;
+	buf = tr->trace_buffer.buffer;
+	tr->trace_buffer.buffer = tr->max_buffer.buffer;
+	tr->max_buffer.buffer = buf;
 
 	__update_max_tr(tr, tsk, cpu);
 	arch_spin_unlock(&ftrace_max_lock);
@@ -740,16 +900,16 @@ update_max_tr_single(struct trace_array *tr, struct task_struct *tsk, int cpu)
 {
 	int ret;
 
-	if (trace_stop_count)
+	if (tr->stop_count)
 		return;
 
 	WARN_ON_ONCE(!irqs_disabled());
-	if (WARN_ON_ONCE(!current_trace->allocated_snapshot))
+	if (WARN_ON_ONCE(!tr->allocated_snapshot))
 		return;
 
 	arch_spin_lock(&ftrace_max_lock);
 
-	ret = ring_buffer_swap_cpu(max_tr.buffer, tr->buffer, cpu);
+	ret = ring_buffer_swap_cpu(tr->max_buffer.buffer, tr->trace_buffer.buffer, cpu);
 
 	if (ret == -EBUSY) {
 		/*
@@ -758,7 +918,7 @@ update_max_tr_single(struct trace_array *tr, struct task_struct *tsk, int cpu)
 		 * the max trace buffer (no one writes directly to it)
 		 * and flag that it failed.
 		 */
-		trace_array_printk(&max_tr, _THIS_IP_,
+		trace_array_printk_buf(tr->max_buffer.buffer, _THIS_IP_,
 			"Failed to swap buffers due to commit in progress\n");
 	}
 
@@ -771,37 +931,78 @@ update_max_tr_single(struct trace_array *tr, struct task_struct *tsk, int cpu)
 
 static void default_wait_pipe(struct trace_iterator *iter)
 {
-	DEFINE_WAIT(wait);
+	/* Iterators are static, they should be filled or empty */
+	if (trace_buffer_iter(iter, iter->cpu_file))
+		return;
+
+	ring_buffer_wait(iter->trace_buffer->buffer, iter->cpu_file);
+}
+
+#ifdef CONFIG_FTRACE_STARTUP_TEST
+static int run_tracer_selftest(struct tracer *type)
+{
+	struct trace_array *tr = &global_trace;
+	struct tracer *saved_tracer = tr->current_trace;
+	int ret;
 
-	prepare_to_wait(&trace_wait, &wait, TASK_INTERRUPTIBLE);
+	if (!type->selftest || tracing_selftest_disabled)
+		return 0;
 
 	/*
-	 * The events can happen in critical sections where
-	 * checking a work queue can cause deadlocks.
-	 * After adding a task to the queue, this flag is set
-	 * only to notify events to try to wake up the queue
-	 * using irq_work.
-	 *
-	 * We don't clear it even if the buffer is no longer
-	 * empty. The flag only causes the next event to run
-	 * irq_work to do the work queue wake up. The worse
-	 * that can happen if we race with !trace_empty() is that
-	 * an event will cause an irq_work to try to wake up
-	 * an empty queue.
-	 *
-	 * There's no reason to protect this flag either, as
-	 * the work queue and irq_work logic will do the necessary
-	 * synchronization for the wake ups. The only thing
-	 * that is necessary is that the wake up happens after
-	 * a task has been queued. It's OK for spurious wake ups.
+	 * Run a selftest on this tracer.
+	 * Here we reset the trace buffer, and set the current
+	 * tracer to be this tracer. The tracer can then run some
+	 * internal tracing to verify that everything is in order.
+	 * If we fail, we do not register this tracer.
 	 */
-	trace_wakeup_needed = true;
+	tracing_reset_online_cpus(&tr->trace_buffer);
 
-	if (trace_empty(iter))
-		schedule();
+	tr->current_trace = type;
+
+#ifdef CONFIG_TRACER_MAX_TRACE
+	if (type->use_max_tr) {
+		/* If we expanded the buffers, make sure the max is expanded too */
+		if (ring_buffer_expanded)
+			ring_buffer_resize(tr->max_buffer.buffer, trace_buf_size,
+					   RING_BUFFER_ALL_CPUS);
+		tr->allocated_snapshot = true;
+	}
+#endif
+
+	/* the test is responsible for initializing and enabling */
+	pr_info("Testing tracer %s: ", type->name);
+	ret = type->selftest(type, tr);
+	/* the test is responsible for resetting too */
+	tr->current_trace = saved_tracer;
+	if (ret) {
+		printk(KERN_CONT "FAILED!\n");
+		/* Add the warning after printing 'FAILED' */
+		WARN_ON(1);
+		return -1;
+	}
+	/* Only reset on passing, to avoid touching corrupted buffers */
+	tracing_reset_online_cpus(&tr->trace_buffer);
+
+#ifdef CONFIG_TRACER_MAX_TRACE
+	if (type->use_max_tr) {
+		tr->allocated_snapshot = false;
 
-	finish_wait(&trace_wait, &wait);
+		/* Shrink the max buffer again */
+		if (ring_buffer_expanded)
+			ring_buffer_resize(tr->max_buffer.buffer, 1,
+					   RING_BUFFER_ALL_CPUS);
+	}
+#endif
+
+	printk(KERN_CONT "PASSED\n");
+	return 0;
+}
+#else
+static inline int run_tracer_selftest(struct tracer *type)
+{
+	return 0;
 }
+#endif /* CONFIG_FTRACE_STARTUP_TEST */
 
 /**
  * register_tracer - register a tracer with the ftrace system.
@@ -848,57 +1049,9 @@ int register_tracer(struct tracer *type)
 	if (!type->wait_pipe)
 		type->wait_pipe = default_wait_pipe;
 
-
-#ifdef CONFIG_FTRACE_STARTUP_TEST
-	if (type->selftest && !tracing_selftest_disabled) {
-		struct tracer *saved_tracer = current_trace;
-		struct trace_array *tr = &global_trace;
-
-		/*
-		 * Run a selftest on this tracer.
-		 * Here we reset the trace buffer, and set the current
-		 * tracer to be this tracer. The tracer can then run some
-		 * internal tracing to verify that everything is in order.
-		 * If we fail, we do not register this tracer.
-		 */
-		tracing_reset_online_cpus(tr);
-
-		current_trace = type;
-
-		if (type->use_max_tr) {
-			/* If we expanded the buffers, make sure the max is expanded too */
-			if (ring_buffer_expanded)
-				ring_buffer_resize(max_tr.buffer, trace_buf_size,
-						   RING_BUFFER_ALL_CPUS);
-			type->allocated_snapshot = true;
-		}
-
-		/* the test is responsible for initializing and enabling */
-		pr_info("Testing tracer %s: ", type->name);
-		ret = type->selftest(type, tr);
-		/* the test is responsible for resetting too */
-		current_trace = saved_tracer;
-		if (ret) {
-			printk(KERN_CONT "FAILED!\n");
-			/* Add the warning after printing 'FAILED' */
-			WARN_ON(1);
-			goto out;
-		}
-		/* Only reset on passing, to avoid touching corrupted buffers */
-		tracing_reset_online_cpus(tr);
-
-		if (type->use_max_tr) {
-			type->allocated_snapshot = false;
-
-			/* Shrink the max buffer again */
-			if (ring_buffer_expanded)
-				ring_buffer_resize(max_tr.buffer, 1,
-						   RING_BUFFER_ALL_CPUS);
-		}
-
-		printk(KERN_CONT "PASSED\n");
-	}
-#endif
+	ret = run_tracer_selftest(type);
+	if (ret < 0)
+		goto out;
 
 	type->next = trace_types;
 	trace_types = type;
@@ -918,7 +1071,7 @@ int register_tracer(struct tracer *type)
 	tracing_set_tracer(type->name);
 	default_bootup_tracer = NULL;
 	/* disable other selftests, since this will break it. */
-	tracing_selftest_disabled = 1;
+	tracing_selftest_disabled = true;
 #ifdef CONFIG_FTRACE_STARTUP_TEST
 	printk(KERN_INFO "Disabling FTRACE selftests due to running tracer '%s'\n",
 	       type->name);
@@ -928,9 +1081,9 @@ int register_tracer(struct tracer *type)
 	return ret;
 }
 
-void tracing_reset(struct trace_array *tr, int cpu)
+void tracing_reset(struct trace_buffer *buf, int cpu)
 {
-	struct ring_buffer *buffer = tr->buffer;
+	struct ring_buffer *buffer = buf->buffer;
 
 	if (!buffer)
 		return;
@@ -944,9 +1097,9 @@ void tracing_reset(struct trace_array *tr, int cpu)
 	ring_buffer_record_enable(buffer);
 }
 
-void tracing_reset_online_cpus(struct trace_array *tr)
+void tracing_reset_online_cpus(struct trace_buffer *buf)
 {
-	struct ring_buffer *buffer = tr->buffer;
+	struct ring_buffer *buffer = buf->buffer;
 	int cpu;
 
 	if (!buffer)
@@ -957,7 +1110,7 @@ void tracing_reset_online_cpus(struct trace_array *tr)
 	/* Make sure all commits have finished */
 	synchronize_sched();
 
-	tr->time_start = ftrace_now(tr->cpu);
+	buf->time_start = ftrace_now(buf->cpu);
 
 	for_each_online_cpu(cpu)
 		ring_buffer_reset_cpu(buffer, cpu);
@@ -967,12 +1120,21 @@ void tracing_reset_online_cpus(struct trace_array *tr)
 
 void tracing_reset_current(int cpu)
 {
-	tracing_reset(&global_trace, cpu);
+	tracing_reset(&global_trace.trace_buffer, cpu);
 }
 
-void tracing_reset_current_online_cpus(void)
+void tracing_reset_all_online_cpus(void)
 {
-	tracing_reset_online_cpus(&global_trace);
+	struct trace_array *tr;
+
+	mutex_lock(&trace_types_lock);
+	list_for_each_entry(tr, &ftrace_trace_arrays, list) {
+		tracing_reset_online_cpus(&tr->trace_buffer);
+#ifdef CONFIG_TRACER_MAX_TRACE
+		tracing_reset_online_cpus(&tr->max_buffer);
+#endif
+	}
+	mutex_unlock(&trace_types_lock);
 }
 
 #define SAVED_CMDLINES 128
@@ -995,7 +1157,7 @@ static void trace_init_cmdlines(void)
 
 int is_tracing_stopped(void)
 {
-	return trace_stop_count;
+	return global_trace.stop_count;
 }
 
 /**
@@ -1027,12 +1189,12 @@ void tracing_start(void)
 	if (tracing_disabled)
 		return;
 
-	raw_spin_lock_irqsave(&tracing_start_lock, flags);
-	if (--trace_stop_count) {
-		if (trace_stop_count < 0) {
+	raw_spin_lock_irqsave(&global_trace.start_lock, flags);
+	if (--global_trace.stop_count) {
+		if (global_trace.stop_count < 0) {
 			/* Someone screwed up their debugging */
 			WARN_ON_ONCE(1);
-			trace_stop_count = 0;
+			global_trace.stop_count = 0;
 		}
 		goto out;
 	}
@@ -1040,19 +1202,52 @@ void tracing_start(void)
 	/* Prevent the buffers from switching */
 	arch_spin_lock(&ftrace_max_lock);
 
-	buffer = global_trace.buffer;
+	buffer = global_trace.trace_buffer.buffer;
 	if (buffer)
 		ring_buffer_record_enable(buffer);
 
-	buffer = max_tr.buffer;
+#ifdef CONFIG_TRACER_MAX_TRACE
+	buffer = global_trace.max_buffer.buffer;
 	if (buffer)
 		ring_buffer_record_enable(buffer);
+#endif
 
 	arch_spin_unlock(&ftrace_max_lock);
 
 	ftrace_start();
  out:
-	raw_spin_unlock_irqrestore(&tracing_start_lock, flags);
+	raw_spin_unlock_irqrestore(&global_trace.start_lock, flags);
+}
+
+static void tracing_start_tr(struct trace_array *tr)
+{
+	struct ring_buffer *buffer;
+	unsigned long flags;
+
+	if (tracing_disabled)
+		return;
+
+	/* If global, we need to also start the max tracer */
+	if (tr->flags & TRACE_ARRAY_FL_GLOBAL)
+		return tracing_start();
+
+	raw_spin_lock_irqsave(&tr->start_lock, flags);
+
+	if (--tr->stop_count) {
+		if (tr->stop_count < 0) {
+			/* Someone screwed up their debugging */
+			WARN_ON_ONCE(1);
+			tr->stop_count = 0;
+		}
+		goto out;
+	}
+
+	buffer = tr->trace_buffer.buffer;
+	if (buffer)
+		ring_buffer_record_enable(buffer);
+
+ out:
+	raw_spin_unlock_irqrestore(&tr->start_lock, flags);
 }
 
 /**
@@ -1067,25 +1262,48 @@ void tracing_stop(void)
 	unsigned long flags;
 
 	ftrace_stop();
-	raw_spin_lock_irqsave(&tracing_start_lock, flags);
-	if (trace_stop_count++)
+	raw_spin_lock_irqsave(&global_trace.start_lock, flags);
+	if (global_trace.stop_count++)
 		goto out;
 
 	/* Prevent the buffers from switching */
 	arch_spin_lock(&ftrace_max_lock);
 
-	buffer = global_trace.buffer;
+	buffer = global_trace.trace_buffer.buffer;
 	if (buffer)
 		ring_buffer_record_disable(buffer);
 
-	buffer = max_tr.buffer;
+#ifdef CONFIG_TRACER_MAX_TRACE
+	buffer = global_trace.max_buffer.buffer;
 	if (buffer)
 		ring_buffer_record_disable(buffer);
+#endif
 
 	arch_spin_unlock(&ftrace_max_lock);
 
  out:
-	raw_spin_unlock_irqrestore(&tracing_start_lock, flags);
+	raw_spin_unlock_irqrestore(&global_trace.start_lock, flags);
+}
+
+static void tracing_stop_tr(struct trace_array *tr)
+{
+	struct ring_buffer *buffer;
+	unsigned long flags;
+
+	/* If global, we need to also stop the max tracer */
+	if (tr->flags & TRACE_ARRAY_FL_GLOBAL)
+		return tracing_stop();
+
+	raw_spin_lock_irqsave(&tr->start_lock, flags);
+	if (tr->stop_count++)
+		goto out;
+
+	buffer = tr->trace_buffer.buffer;
+	if (buffer)
+		ring_buffer_record_disable(buffer);
+
+ out:
+	raw_spin_unlock_irqrestore(&tr->start_lock, flags);
 }
 
 void trace_stop_cmdline_recording(void);
@@ -1218,11 +1436,6 @@ void
 __buffer_unlock_commit(struct ring_buffer *buffer, struct ring_buffer_event *event)
 {
 	__this_cpu_write(trace_cmdline_save, true);
-	if (trace_wakeup_needed) {
-		trace_wakeup_needed = false;
-		/* irq_work_queue() supplies it's own memory barriers */
-		irq_work_queue(&trace_work_wakeup);
-	}
 	ring_buffer_unlock_commit(buffer, event);
 }
 
@@ -1246,11 +1459,23 @@ void trace_buffer_unlock_commit(struct ring_buffer *buffer,
 EXPORT_SYMBOL_GPL(trace_buffer_unlock_commit);
 
 struct ring_buffer_event *
+trace_event_buffer_lock_reserve(struct ring_buffer **current_rb,
+			  struct ftrace_event_file *ftrace_file,
+			  int type, unsigned long len,
+			  unsigned long flags, int pc)
+{
+	*current_rb = ftrace_file->tr->trace_buffer.buffer;
+	return trace_buffer_lock_reserve(*current_rb,
+					 type, len, flags, pc);
+}
+EXPORT_SYMBOL_GPL(trace_event_buffer_lock_reserve);
+
+struct ring_buffer_event *
 trace_current_buffer_lock_reserve(struct ring_buffer **current_rb,
 				  int type, unsigned long len,
 				  unsigned long flags, int pc)
 {
-	*current_rb = global_trace.buffer;
+	*current_rb = global_trace.trace_buffer.buffer;
 	return trace_buffer_lock_reserve(*current_rb,
 					 type, len, flags, pc);
 }
@@ -1289,7 +1514,7 @@ trace_function(struct trace_array *tr,
 	       int pc)
 {
 	struct ftrace_event_call *call = &event_function;
-	struct ring_buffer *buffer = tr->buffer;
+	struct ring_buffer *buffer = tr->trace_buffer.buffer;
 	struct ring_buffer_event *event;
 	struct ftrace_entry *entry;
 
@@ -1430,13 +1655,14 @@ void ftrace_trace_stack(struct ring_buffer *buffer, unsigned long flags,
 void __trace_stack(struct trace_array *tr, unsigned long flags, int skip,
 		   int pc)
 {
-	__ftrace_trace_stack(tr->buffer, flags, skip, pc, NULL);
+	__ftrace_trace_stack(tr->trace_buffer.buffer, flags, skip, pc, NULL);
 }
 
 /**
  * trace_dump_stack - record a stack back trace in the trace buffer
+ * @skip: Number of functions to skip (helper handlers)
  */
-void trace_dump_stack(void)
+void trace_dump_stack(int skip)
 {
 	unsigned long flags;
 
@@ -1445,8 +1671,13 @@ 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(), NULL);
+	/*
+	 * Skip 3 more, seems to get us at the caller of
+	 * this function.
+	 */
+	skip += 3;
+	__ftrace_trace_stack(global_trace.trace_buffer.buffer,
+			     flags, skip, preempt_count(), NULL);
 }
 
 static DEFINE_PER_CPU(int, user_stack_count);
@@ -1616,7 +1847,7 @@ void trace_printk_init_buffers(void)
 	 * directly here. If the global_trace.buffer is already
 	 * allocated here, then this was called by module code.
 	 */
-	if (global_trace.buffer)
+	if (global_trace.trace_buffer.buffer)
 		tracing_start_cmdline_record();
 }
 
@@ -1676,7 +1907,7 @@ int trace_vbprintk(unsigned long ip, const char *fmt, va_list args)
 
 	local_save_flags(flags);
 	size = sizeof(*entry) + sizeof(u32) * len;
-	buffer = tr->buffer;
+	buffer = tr->trace_buffer.buffer;
 	event = trace_buffer_lock_reserve(buffer, TRACE_BPRINT, size,
 					  flags, pc);
 	if (!event)
@@ -1699,27 +1930,12 @@ out:
 }
 EXPORT_SYMBOL_GPL(trace_vbprintk);
 
-int trace_array_printk(struct trace_array *tr,
-		       unsigned long ip, const char *fmt, ...)
-{
-	int ret;
-	va_list ap;
-
-	if (!(trace_flags & TRACE_ITER_PRINTK))
-		return 0;
-
-	va_start(ap, fmt);
-	ret = trace_array_vprintk(tr, ip, fmt, ap);
-	va_end(ap);
-	return ret;
-}
-
-int trace_array_vprintk(struct trace_array *tr,
-			unsigned long ip, const char *fmt, va_list args)
+static int
+__trace_array_vprintk(struct ring_buffer *buffer,
+		      unsigned long ip, const char *fmt, va_list args)
 {
 	struct ftrace_event_call *call = &event_print;
 	struct ring_buffer_event *event;
-	struct ring_buffer *buffer;
 	int len = 0, size, pc;
 	struct print_entry *entry;
 	unsigned long flags;
@@ -1747,7 +1963,6 @@ int trace_array_vprintk(struct trace_array *tr,
 
 	local_save_flags(flags);
 	size = sizeof(*entry) + len + 1;
-	buffer = tr->buffer;
 	event = trace_buffer_lock_reserve(buffer, TRACE_PRINT, size,
 					  flags, pc);
 	if (!event)
@@ -1768,8 +1983,44 @@ int trace_array_vprintk(struct trace_array *tr,
 	return len;
 }
 
-int trace_vprintk(unsigned long ip, const char *fmt, va_list args)
-{
+int trace_array_vprintk(struct trace_array *tr,
+			unsigned long ip, const char *fmt, va_list args)
+{
+	return __trace_array_vprintk(tr->trace_buffer.buffer, ip, fmt, args);
+}
+
+int trace_array_printk(struct trace_array *tr,
+		       unsigned long ip, const char *fmt, ...)
+{
+	int ret;
+	va_list ap;
+
+	if (!(trace_flags & TRACE_ITER_PRINTK))
+		return 0;
+
+	va_start(ap, fmt);
+	ret = trace_array_vprintk(tr, ip, fmt, ap);
+	va_end(ap);
+	return ret;
+}
+
+int trace_array_printk_buf(struct ring_buffer *buffer,
+			   unsigned long ip, const char *fmt, ...)
+{
+	int ret;
+	va_list ap;
+
+	if (!(trace_flags & TRACE_ITER_PRINTK))
+		return 0;
+
+	va_start(ap, fmt);
+	ret = __trace_array_vprintk(buffer, ip, fmt, ap);
+	va_end(ap);
+	return ret;
+}
+
+int trace_vprintk(unsigned long ip, const char *fmt, va_list args)
+{
 	return trace_array_vprintk(&global_trace, ip, fmt, args);
 }
 EXPORT_SYMBOL_GPL(trace_vprintk);
@@ -1793,7 +2044,7 @@ peek_next_entry(struct trace_iterator *iter, int cpu, u64 *ts,
 	if (buf_iter)
 		event = ring_buffer_iter_peek(buf_iter, ts);
 	else
-		event = ring_buffer_peek(iter->tr->buffer, cpu, ts,
+		event = ring_buffer_peek(iter->trace_buffer->buffer, cpu, ts,
 					 lost_events);
 
 	if (event) {
@@ -1808,7 +2059,7 @@ static struct trace_entry *
 __find_next_entry(struct trace_iterator *iter, int *ent_cpu,
 		  unsigned long *missing_events, u64 *ent_ts)
 {
-	struct ring_buffer *buffer = iter->tr->buffer;
+	struct ring_buffer *buffer = iter->trace_buffer->buffer;
 	struct trace_entry *ent, *next = NULL;
 	unsigned long lost_events = 0, next_lost = 0;
 	int cpu_file = iter->cpu_file;
@@ -1821,7 +2072,7 @@ __find_next_entry(struct trace_iterator *iter, int *ent_cpu,
 	 * If we are in a per_cpu trace file, don't bother by iterating over
 	 * all cpu and peek directly.
 	 */
-	if (cpu_file > TRACE_PIPE_ALL_CPU) {
+	if (cpu_file > RING_BUFFER_ALL_CPUS) {
 		if (ring_buffer_empty_cpu(buffer, cpu_file))
 			return NULL;
 		ent = peek_next_entry(iter, cpu_file, ent_ts, missing_events);
@@ -1885,7 +2136,7 @@ void *trace_find_next_entry_inc(struct trace_iterator *iter)
 
 static void trace_consume(struct trace_iterator *iter)
 {
-	ring_buffer_consume(iter->tr->buffer, iter->cpu, &iter->ts,
+	ring_buffer_consume(iter->trace_buffer->buffer, iter->cpu, &iter->ts,
 			    &iter->lost_events);
 }
 
@@ -1918,13 +2169,12 @@ static void *s_next(struct seq_file *m, void *v, loff_t *pos)
 
 void tracing_iter_reset(struct trace_iterator *iter, int cpu)
 {
-	struct trace_array *tr = iter->tr;
 	struct ring_buffer_event *event;
 	struct ring_buffer_iter *buf_iter;
 	unsigned long entries = 0;
 	u64 ts;
 
-	tr->data[cpu]->skipped_entries = 0;
+	per_cpu_ptr(iter->trace_buffer->data, cpu)->skipped_entries = 0;
 
 	buf_iter = trace_buffer_iter(iter, cpu);
 	if (!buf_iter)
@@ -1938,13 +2188,13 @@ void tracing_iter_reset(struct trace_iterator *iter, int cpu)
 	 * by the timestamp being before the start of the buffer.
 	 */
 	while ((event = ring_buffer_iter_peek(buf_iter, &ts))) {
-		if (ts >= iter->tr->time_start)
+		if (ts >= iter->trace_buffer->time_start)
 			break;
 		entries++;
 		ring_buffer_read(buf_iter, NULL);
 	}
 
-	tr->data[cpu]->skipped_entries = entries;
+	per_cpu_ptr(iter->trace_buffer->data, cpu)->skipped_entries = entries;
 }
 
 /*
@@ -1954,6 +2204,7 @@ void tracing_iter_reset(struct trace_iterator *iter, int cpu)
 static void *s_start(struct seq_file *m, loff_t *pos)
 {
 	struct trace_iterator *iter = m->private;
+	struct trace_array *tr = iter->tr;
 	int cpu_file = iter->cpu_file;
 	void *p = NULL;
 	loff_t l = 0;
@@ -1966,12 +2217,14 @@ static void *s_start(struct seq_file *m, loff_t *pos)
 	 * will point to the same string as current_trace->name.
 	 */
 	mutex_lock(&trace_types_lock);
-	if (unlikely(current_trace && iter->trace->name != current_trace->name))
-		*iter->trace = *current_trace;
+	if (unlikely(tr->current_trace && iter->trace->name != tr->current_trace->name))
+		*iter->trace = *tr->current_trace;
 	mutex_unlock(&trace_types_lock);
 
+#ifdef CONFIG_TRACER_MAX_TRACE
 	if (iter->snapshot && iter->trace->use_max_tr)
 		return ERR_PTR(-EBUSY);
+#endif
 
 	if (!iter->snapshot)
 		atomic_inc(&trace_record_cmdline_disabled);
@@ -1981,7 +2234,7 @@ static void *s_start(struct seq_file *m, loff_t *pos)
 		iter->cpu = 0;
 		iter->idx = -1;
 
-		if (cpu_file == TRACE_PIPE_ALL_CPU) {
+		if (cpu_file == RING_BUFFER_ALL_CPUS) {
 			for_each_tracing_cpu(cpu)
 				tracing_iter_reset(iter, cpu);
 		} else
@@ -2013,17 +2266,21 @@ static void s_stop(struct seq_file *m, void *p)
 {
 	struct trace_iterator *iter = m->private;
 
+#ifdef CONFIG_TRACER_MAX_TRACE
 	if (iter->snapshot && iter->trace->use_max_tr)
 		return;
+#endif
 
 	if (!iter->snapshot)
 		atomic_dec(&trace_record_cmdline_disabled);
+
 	trace_access_unlock(iter->cpu_file);
 	trace_event_read_unlock();
 }
 
 static void
-get_total_entries(struct trace_array *tr, unsigned long *total, unsigned long *entries)
+get_total_entries(struct trace_buffer *buf,
+		  unsigned long *total, unsigned long *entries)
 {
 	unsigned long count;
 	int cpu;
@@ -2032,19 +2289,19 @@ get_total_entries(struct trace_array *tr, unsigned long *total, unsigned long *e
 	*entries = 0;
 
 	for_each_tracing_cpu(cpu) {
-		count = ring_buffer_entries_cpu(tr->buffer, cpu);
+		count = ring_buffer_entries_cpu(buf->buffer, cpu);
 		/*
 		 * If this buffer has skipped entries, then we hold all
 		 * entries for the trace and we need to ignore the
 		 * ones before the time stamp.
 		 */
-		if (tr->data[cpu]->skipped_entries) {
-			count -= tr->data[cpu]->skipped_entries;
+		if (per_cpu_ptr(buf->data, cpu)->skipped_entries) {
+			count -= per_cpu_ptr(buf->data, cpu)->skipped_entries;
 			/* total is the same as the entries */
 			*total += count;
 		} else
 			*total += count +
-				ring_buffer_overrun_cpu(tr->buffer, cpu);
+				ring_buffer_overrun_cpu(buf->buffer, cpu);
 		*entries += count;
 	}
 }
@@ -2061,27 +2318,27 @@ static void print_lat_help_header(struct seq_file *m)
 	seq_puts(m, "#     \\   /      |||||  \\    |   /           \n");
 }
 
-static void print_event_info(struct trace_array *tr, struct seq_file *m)
+static void print_event_info(struct trace_buffer *buf, struct seq_file *m)
 {
 	unsigned long total;
 	unsigned long entries;
 
-	get_total_entries(tr, &total, &entries);
+	get_total_entries(buf, &total, &entries);
 	seq_printf(m, "# entries-in-buffer/entries-written: %lu/%lu   #P:%d\n",
 		   entries, total, num_online_cpus());
 	seq_puts(m, "#\n");
 }
 
-static void print_func_help_header(struct trace_array *tr, struct seq_file *m)
+static void print_func_help_header(struct trace_buffer *buf, struct seq_file *m)
 {
-	print_event_info(tr, m);
+	print_event_info(buf, m);
 	seq_puts(m, "#           TASK-PID   CPU#      TIMESTAMP  FUNCTION\n");
 	seq_puts(m, "#              | |       |          |         |\n");
 }
 
-static void print_func_help_header_irq(struct trace_array *tr, struct seq_file *m)
+static void print_func_help_header_irq(struct trace_buffer *buf, struct seq_file *m)
 {
-	print_event_info(tr, m);
+	print_event_info(buf, m);
 	seq_puts(m, "#                              _-----=> irqs-off\n");
 	seq_puts(m, "#                             / _----=> need-resched\n");
 	seq_puts(m, "#                            | / _---=> hardirq/softirq\n");
@@ -2095,16 +2352,16 @@ void
 print_trace_header(struct seq_file *m, struct trace_iterator *iter)
 {
 	unsigned long sym_flags = (trace_flags & TRACE_ITER_SYM_MASK);
-	struct trace_array *tr = iter->tr;
-	struct trace_array_cpu *data = tr->data[tr->cpu];
-	struct tracer *type = current_trace;
+	struct trace_buffer *buf = iter->trace_buffer;
+	struct trace_array_cpu *data = per_cpu_ptr(buf->data, buf->cpu);
+	struct tracer *type = iter->trace;
 	unsigned long entries;
 	unsigned long total;
 	const char *name = "preemption";
 
 	name = type->name;
 
-	get_total_entries(tr, &total, &entries);
+	get_total_entries(buf, &total, &entries);
 
 	seq_printf(m, "# %s latency trace v1.1.5 on %s\n",
 		   name, UTS_RELEASE);
@@ -2115,7 +2372,7 @@ print_trace_header(struct seq_file *m, struct trace_iterator *iter)
 		   nsecs_to_usecs(data->saved_latency),
 		   entries,
 		   total,
-		   tr->cpu,
+		   buf->cpu,
 #if defined(CONFIG_PREEMPT_NONE)
 		   "server",
 #elif defined(CONFIG_PREEMPT_VOLUNTARY)
@@ -2166,7 +2423,7 @@ static void test_cpu_buff_start(struct trace_iterator *iter)
 	if (cpumask_test_cpu(iter->cpu, iter->started))
 		return;
 
-	if (iter->tr->data[iter->cpu]->skipped_entries)
+	if (per_cpu_ptr(iter->trace_buffer->data, iter->cpu)->skipped_entries)
 		return;
 
 	cpumask_set_cpu(iter->cpu, iter->started);
@@ -2289,14 +2546,14 @@ int trace_empty(struct trace_iterator *iter)
 	int cpu;
 
 	/* If we are looking at one CPU buffer, only check that one */
-	if (iter->cpu_file != TRACE_PIPE_ALL_CPU) {
+	if (iter->cpu_file != RING_BUFFER_ALL_CPUS) {
 		cpu = iter->cpu_file;
 		buf_iter = trace_buffer_iter(iter, cpu);
 		if (buf_iter) {
 			if (!ring_buffer_iter_empty(buf_iter))
 				return 0;
 		} else {
-			if (!ring_buffer_empty_cpu(iter->tr->buffer, cpu))
+			if (!ring_buffer_empty_cpu(iter->trace_buffer->buffer, cpu))
 				return 0;
 		}
 		return 1;
@@ -2308,7 +2565,7 @@ int trace_empty(struct trace_iterator *iter)
 			if (!ring_buffer_iter_empty(buf_iter))
 				return 0;
 		} else {
-			if (!ring_buffer_empty_cpu(iter->tr->buffer, cpu))
+			if (!ring_buffer_empty_cpu(iter->trace_buffer->buffer, cpu))
 				return 0;
 		}
 	}
@@ -2332,6 +2589,11 @@ enum print_line_t print_trace_line(struct trace_iterator *iter)
 			return ret;
 	}
 
+	if (iter->ent->type == TRACE_BPUTS &&
+			trace_flags & TRACE_ITER_PRINTK &&
+			trace_flags & TRACE_ITER_PRINTK_MSGONLY)
+		return trace_print_bputs_msg_only(iter);
+
 	if (iter->ent->type == TRACE_BPRINT &&
 			trace_flags & TRACE_ITER_PRINTK &&
 			trace_flags & TRACE_ITER_PRINTK_MSGONLY)
@@ -2386,9 +2648,9 @@ void trace_default_header(struct seq_file *m)
 	} else {
 		if (!(trace_flags & TRACE_ITER_VERBOSE)) {
 			if (trace_flags & TRACE_ITER_IRQ_INFO)
-				print_func_help_header_irq(iter->tr, m);
+				print_func_help_header_irq(iter->trace_buffer, m);
 			else
-				print_func_help_header(iter->tr, m);
+				print_func_help_header(iter->trace_buffer, m);
 		}
 	}
 }
@@ -2402,14 +2664,8 @@ static void test_ftrace_alive(struct seq_file *m)
 }
 
 #ifdef CONFIG_TRACER_MAX_TRACE
-static void print_snapshot_help(struct seq_file *m, struct trace_iterator *iter)
+static void show_snapshot_main_help(struct seq_file *m)
 {
-	if (iter->trace->allocated_snapshot)
-		seq_printf(m, "#\n# * Snapshot is allocated *\n#\n");
-	else
-		seq_printf(m, "#\n# * Snapshot is freed *\n#\n");
-
-	seq_printf(m, "# Snapshot commands:\n");
 	seq_printf(m, "# echo 0 > snapshot : Clears and frees snapshot buffer\n");
 	seq_printf(m, "# echo 1 > snapshot : Allocates snapshot buffer, if not already allocated.\n");
 	seq_printf(m, "#                      Takes a snapshot of the main buffer.\n");
@@ -2417,6 +2673,35 @@ static void print_snapshot_help(struct seq_file *m, struct trace_iterator *iter)
 	seq_printf(m, "#                      (Doesn't have to be '2' works with any number that\n");
 	seq_printf(m, "#                       is not a '0' or '1')\n");
 }
+
+static void show_snapshot_percpu_help(struct seq_file *m)
+{
+	seq_printf(m, "# echo 0 > snapshot : Invalid for per_cpu snapshot file.\n");
+#ifdef CONFIG_RING_BUFFER_ALLOW_SWAP
+	seq_printf(m, "# echo 1 > snapshot : Allocates snapshot buffer, if not already allocated.\n");
+	seq_printf(m, "#                      Takes a snapshot of the main buffer for this cpu.\n");
+#else
+	seq_printf(m, "# echo 1 > snapshot : Not supported with this kernel.\n");
+	seq_printf(m, "#                     Must use main snapshot file to allocate.\n");
+#endif
+	seq_printf(m, "# echo 2 > snapshot : Clears this cpu's snapshot buffer (but does not allocate)\n");
+	seq_printf(m, "#                      (Doesn't have to be '2' works with any number that\n");
+	seq_printf(m, "#                       is not a '0' or '1')\n");
+}
+
+static void print_snapshot_help(struct seq_file *m, struct trace_iterator *iter)
+{
+	if (iter->tr->allocated_snapshot)
+		seq_printf(m, "#\n# * Snapshot is allocated *\n#\n");
+	else
+		seq_printf(m, "#\n# * Snapshot is freed *\n#\n");
+
+	seq_printf(m, "# Snapshot commands:\n");
+	if (iter->cpu_file == RING_BUFFER_ALL_CPUS)
+		show_snapshot_main_help(m);
+	else
+		show_snapshot_percpu_help(m);
+}
 #else
 /* Should never be called */
 static inline void print_snapshot_help(struct seq_file *m, struct trace_iterator *iter) { }
@@ -2476,7 +2761,8 @@ static const struct seq_operations tracer_seq_ops = {
 static struct trace_iterator *
 __tracing_open(struct inode *inode, struct file *file, bool snapshot)
 {
-	long cpu_file = (long) inode->i_private;
+	struct trace_cpu *tc = inode->i_private;
+	struct trace_array *tr = tc->tr;
 	struct trace_iterator *iter;
 	int cpu;
 
@@ -2501,26 +2787,31 @@ __tracing_open(struct inode *inode, struct file *file, bool snapshot)
 	if (!iter->trace)
 		goto fail;
 
-	*iter->trace = *current_trace;
+	*iter->trace = *tr->current_trace;
 
 	if (!zalloc_cpumask_var(&iter->started, GFP_KERNEL))
 		goto fail;
 
-	if (current_trace->print_max || snapshot)
-		iter->tr = &max_tr;
+	iter->tr = tr;
+
+#ifdef CONFIG_TRACER_MAX_TRACE
+	/* Currently only the top directory has a snapshot */
+	if (tr->current_trace->print_max || snapshot)
+		iter->trace_buffer = &tr->max_buffer;
 	else
-		iter->tr = &global_trace;
+#endif
+		iter->trace_buffer = &tr->trace_buffer;
 	iter->snapshot = snapshot;
 	iter->pos = -1;
 	mutex_init(&iter->mutex);
-	iter->cpu_file = cpu_file;
+	iter->cpu_file = tc->cpu;
 
 	/* Notify the tracer early; before we stop tracing. */
 	if (iter->trace && iter->trace->open)
 		iter->trace->open(iter);
 
 	/* Annotate start of buffers if we had overruns */
-	if (ring_buffer_overruns(iter->tr->buffer))
+	if (ring_buffer_overruns(iter->trace_buffer->buffer))
 		iter->iter_flags |= TRACE_FILE_ANNOTATE;
 
 	/* Output in nanoseconds only if we are using a clock in nanoseconds. */
@@ -2529,12 +2820,12 @@ __tracing_open(struct inode *inode, struct file *file, bool snapshot)
 
 	/* stop the trace while dumping if we are not opening "snapshot" */
 	if (!iter->snapshot)
-		tracing_stop();
+		tracing_stop_tr(tr);
 
-	if (iter->cpu_file == TRACE_PIPE_ALL_CPU) {
+	if (iter->cpu_file == RING_BUFFER_ALL_CPUS) {
 		for_each_tracing_cpu(cpu) {
 			iter->buffer_iter[cpu] =
-				ring_buffer_read_prepare(iter->tr->buffer, cpu);
+				ring_buffer_read_prepare(iter->trace_buffer->buffer, cpu);
 		}
 		ring_buffer_read_prepare_sync();
 		for_each_tracing_cpu(cpu) {
@@ -2544,12 +2835,14 @@ __tracing_open(struct inode *inode, struct file *file, bool snapshot)
 	} else {
 		cpu = iter->cpu_file;
 		iter->buffer_iter[cpu] =
-			ring_buffer_read_prepare(iter->tr->buffer, cpu);
+			ring_buffer_read_prepare(iter->trace_buffer->buffer, cpu);
 		ring_buffer_read_prepare_sync();
 		ring_buffer_read_start(iter->buffer_iter[cpu]);
 		tracing_iter_reset(iter, cpu);
 	}
 
+	tr->ref++;
+
 	mutex_unlock(&trace_types_lock);
 
 	return iter;
@@ -2576,14 +2869,20 @@ static int tracing_release(struct inode *inode, struct file *file)
 {
 	struct seq_file *m = file->private_data;
 	struct trace_iterator *iter;
+	struct trace_array *tr;
 	int cpu;
 
 	if (!(file->f_mode & FMODE_READ))
 		return 0;
 
 	iter = m->private;
+	tr = iter->tr;
 
 	mutex_lock(&trace_types_lock);
+
+	WARN_ON(!tr->ref);
+	tr->ref--;
+
 	for_each_tracing_cpu(cpu) {
 		if (iter->buffer_iter[cpu])
 			ring_buffer_read_finish(iter->buffer_iter[cpu]);
@@ -2594,7 +2893,7 @@ static int tracing_release(struct inode *inode, struct file *file)
 
 	if (!iter->snapshot)
 		/* reenable tracing if it was previously enabled */
-		tracing_start();
+		tracing_start_tr(tr);
 	mutex_unlock(&trace_types_lock);
 
 	mutex_destroy(&iter->mutex);
@@ -2613,12 +2912,13 @@ static int tracing_open(struct inode *inode, struct file *file)
 	/* If this file was open for write, then erase contents */
 	if ((file->f_mode & FMODE_WRITE) &&
 	    (file->f_flags & O_TRUNC)) {
-		long cpu = (long) inode->i_private;
+		struct trace_cpu *tc = inode->i_private;
+		struct trace_array *tr = tc->tr;
 
-		if (cpu == TRACE_PIPE_ALL_CPU)
-			tracing_reset_online_cpus(&global_trace);
+		if (tc->cpu == RING_BUFFER_ALL_CPUS)
+			tracing_reset_online_cpus(&tr->trace_buffer);
 		else
-			tracing_reset(&global_trace, cpu);
+			tracing_reset(&tr->trace_buffer, tc->cpu);
 	}
 
 	if (file->f_mode & FMODE_READ) {
@@ -2765,8 +3065,9 @@ static ssize_t
 tracing_cpumask_write(struct file *filp, const char __user *ubuf,
 		      size_t count, loff_t *ppos)
 {
-	int err, cpu;
+	struct trace_array *tr = filp->private_data;
 	cpumask_var_t tracing_cpumask_new;
+	int err, cpu;
 
 	if (!alloc_cpumask_var(&tracing_cpumask_new, GFP_KERNEL))
 		return -ENOMEM;
@@ -2786,13 +3087,13 @@ tracing_cpumask_write(struct file *filp, const char __user *ubuf,
 		 */
 		if (cpumask_test_cpu(cpu, tracing_cpumask) &&
 				!cpumask_test_cpu(cpu, tracing_cpumask_new)) {
-			atomic_inc(&global_trace.data[cpu]->disabled);
-			ring_buffer_record_disable_cpu(global_trace.buffer, cpu);
+			atomic_inc(&per_cpu_ptr(tr->trace_buffer.data, cpu)->disabled);
+			ring_buffer_record_disable_cpu(tr->trace_buffer.buffer, cpu);
 		}
 		if (!cpumask_test_cpu(cpu, tracing_cpumask) &&
 				cpumask_test_cpu(cpu, tracing_cpumask_new)) {
-			atomic_dec(&global_trace.data[cpu]->disabled);
-			ring_buffer_record_enable_cpu(global_trace.buffer, cpu);
+			atomic_dec(&per_cpu_ptr(tr->trace_buffer.data, cpu)->disabled);
+			ring_buffer_record_enable_cpu(tr->trace_buffer.buffer, cpu);
 		}
 	}
 	arch_spin_unlock(&ftrace_max_lock);
@@ -2821,12 +3122,13 @@ static const struct file_operations tracing_cpumask_fops = {
 static int tracing_trace_options_show(struct seq_file *m, void *v)
 {
 	struct tracer_opt *trace_opts;
+	struct trace_array *tr = m->private;
 	u32 tracer_flags;
 	int i;
 
 	mutex_lock(&trace_types_lock);
-	tracer_flags = current_trace->flags->val;
-	trace_opts = current_trace->flags->opts;
+	tracer_flags = tr->current_trace->flags->val;
+	trace_opts = tr->current_trace->flags->opts;
 
 	for (i = 0; trace_options[i]; i++) {
 		if (trace_flags & (1 << i))
@@ -2890,15 +3192,15 @@ int trace_keep_overwrite(struct tracer *tracer, u32 mask, int set)
 	return 0;
 }
 
-int set_tracer_flag(unsigned int mask, int enabled)
+int set_tracer_flag(struct trace_array *tr, unsigned int mask, int enabled)
 {
 	/* do nothing if flag is already set */
 	if (!!(trace_flags & mask) == !!enabled)
 		return 0;
 
 	/* Give the tracer a chance to approve the change */
-	if (current_trace->flag_changed)
-		if (current_trace->flag_changed(current_trace, mask, !!enabled))
+	if (tr->current_trace->flag_changed)
+		if (tr->current_trace->flag_changed(tr->current_trace, mask, !!enabled))
 			return -EINVAL;
 
 	if (enabled)
@@ -2910,9 +3212,9 @@ int set_tracer_flag(unsigned int mask, int enabled)
 		trace_event_enable_cmd_record(enabled);
 
 	if (mask == TRACE_ITER_OVERWRITE) {
-		ring_buffer_change_overwrite(global_trace.buffer, enabled);
+		ring_buffer_change_overwrite(tr->trace_buffer.buffer, enabled);
 #ifdef CONFIG_TRACER_MAX_TRACE
-		ring_buffer_change_overwrite(max_tr.buffer, enabled);
+		ring_buffer_change_overwrite(tr->max_buffer.buffer, enabled);
 #endif
 	}
 
@@ -2922,7 +3224,7 @@ int set_tracer_flag(unsigned int mask, int enabled)
 	return 0;
 }
 
-static int trace_set_options(char *option)
+static int trace_set_options(struct trace_array *tr, char *option)
 {
 	char *cmp;
 	int neg = 0;
@@ -2940,14 +3242,14 @@ static int trace_set_options(char *option)
 
 	for (i = 0; trace_options[i]; i++) {
 		if (strcmp(cmp, trace_options[i]) == 0) {
-			ret = set_tracer_flag(1 << i, !neg);
+			ret = set_tracer_flag(tr, 1 << i, !neg);
 			break;
 		}
 	}
 
 	/* If no option could be set, test the specific tracer options */
 	if (!trace_options[i])
-		ret = set_tracer_option(current_trace, cmp, neg);
+		ret = set_tracer_option(tr->current_trace, cmp, neg);
 
 	mutex_unlock(&trace_types_lock);
 
@@ -2958,6 +3260,8 @@ static ssize_t
 tracing_trace_options_write(struct file *filp, const char __user *ubuf,
 			size_t cnt, loff_t *ppos)
 {
+	struct seq_file *m = filp->private_data;
+	struct trace_array *tr = m->private;
 	char buf[64];
 	int ret;
 
@@ -2969,7 +3273,7 @@ tracing_trace_options_write(struct file *filp, const char __user *ubuf,
 
 	buf[cnt] = 0;
 
-	ret = trace_set_options(buf);
+	ret = trace_set_options(tr, buf);
 	if (ret < 0)
 		return ret;
 
@@ -2982,7 +3286,8 @@ static int tracing_trace_options_open(struct inode *inode, struct file *file)
 {
 	if (tracing_disabled)
 		return -ENODEV;
-	return single_open(file, tracing_trace_options_show, NULL);
+
+	return single_open(file, tracing_trace_options_show, inode->i_private);
 }
 
 static const struct file_operations tracing_iter_fops = {
@@ -2995,20 +3300,84 @@ static const struct file_operations tracing_iter_fops = {
 
 static const char readme_msg[] =
 	"tracing mini-HOWTO:\n\n"
-	"# mount -t debugfs nodev /sys/kernel/debug\n\n"
-	"# cat /sys/kernel/debug/tracing/available_tracers\n"
-	"wakeup wakeup_rt preemptirqsoff preemptoff irqsoff function nop\n\n"
-	"# cat /sys/kernel/debug/tracing/current_tracer\n"
-	"nop\n"
-	"# echo wakeup > /sys/kernel/debug/tracing/current_tracer\n"
-	"# cat /sys/kernel/debug/tracing/current_tracer\n"
-	"wakeup\n"
-	"# cat /sys/kernel/debug/tracing/trace_options\n"
-	"noprint-parent nosym-offset nosym-addr noverbose\n"
-	"# echo print-parent > /sys/kernel/debug/tracing/trace_options\n"
-	"# echo 1 > /sys/kernel/debug/tracing/tracing_on\n"
-	"# cat /sys/kernel/debug/tracing/trace > /tmp/trace.txt\n"
-	"# echo 0 > /sys/kernel/debug/tracing/tracing_on\n"
+	"# echo 0 > tracing_on : quick way to disable tracing\n"
+	"# echo 1 > tracing_on : quick way to re-enable tracing\n\n"
+	" Important files:\n"
+	"  trace\t\t\t- The static contents of the buffer\n"
+	"\t\t\t  To clear the buffer write into this file: echo > trace\n"
+	"  trace_pipe\t\t- A consuming read to see the contents of the buffer\n"
+	"  current_tracer\t- function and latency tracers\n"
+	"  available_tracers\t- list of configured tracers for current_tracer\n"
+	"  buffer_size_kb\t- view and modify size of per cpu buffer\n"
+	"  buffer_total_size_kb  - view total size of all cpu buffers\n\n"
+	"  trace_clock\t\t-change the clock used to order events\n"
+	"       local:   Per cpu clock but may not be synced across CPUs\n"
+	"      global:   Synced across CPUs but slows tracing down.\n"
+	"     counter:   Not a clock, but just an increment\n"
+	"      uptime:   Jiffy counter from time of boot\n"
+	"        perf:   Same clock that perf events use\n"
+#ifdef CONFIG_X86_64
+	"     x86-tsc:   TSC cycle counter\n"
+#endif
+	"\n  trace_marker\t\t- Writes into this file writes into the kernel buffer\n"
+	"  tracing_cpumask\t- Limit which CPUs to trace\n"
+	"  instances\t\t- Make sub-buffers with: mkdir instances/foo\n"
+	"\t\t\t  Remove sub-buffer with rmdir\n"
+	"  trace_options\t\t- Set format or modify how tracing happens\n"
+	"\t\t\t  Disable an option by adding a suffix 'no' to the option name\n"
+#ifdef CONFIG_DYNAMIC_FTRACE
+	"\n  available_filter_functions - list of functions that can be filtered on\n"
+	"  set_ftrace_filter\t- echo function name in here to only trace these functions\n"
+	"            accepts: func_full_name, *func_end, func_begin*, *func_middle*\n"
+	"            modules: Can select a group via module\n"
+	"             Format: :mod:<module-name>\n"
+	"             example: echo :mod:ext3 > set_ftrace_filter\n"
+	"            triggers: a command to perform when function is hit\n"
+	"              Format: <function>:<trigger>[:count]\n"
+	"             trigger: traceon, traceoff\n"
+	"                      enable_event:<system>:<event>\n"
+	"                      disable_event:<system>:<event>\n"
+#ifdef CONFIG_STACKTRACE
+	"                      stacktrace\n"
+#endif
+#ifdef CONFIG_TRACER_SNAPSHOT
+	"                      snapshot\n"
+#endif
+	"             example: echo do_fault:traceoff > set_ftrace_filter\n"
+	"                      echo do_trap:traceoff:3 > set_ftrace_filter\n"
+	"             The first one will disable tracing every time do_fault is hit\n"
+	"             The second will disable tracing at most 3 times when do_trap is hit\n"
+	"               The first time do trap is hit and it disables tracing, the counter\n"
+	"               will decrement to 2. If tracing is already disabled, the counter\n"
+	"               will not decrement. It only decrements when the trigger did work\n"
+	"             To remove trigger without count:\n"
+	"               echo '!<function>:<trigger> > set_ftrace_filter\n"
+	"             To remove trigger with a count:\n"
+	"               echo '!<function>:<trigger>:0 > set_ftrace_filter\n"
+	"  set_ftrace_notrace\t- echo function name in here to never trace.\n"
+	"            accepts: func_full_name, *func_end, func_begin*, *func_middle*\n"
+	"            modules: Can select a group via module command :mod:\n"
+	"            Does not accept triggers\n"
+#endif /* CONFIG_DYNAMIC_FTRACE */
+#ifdef CONFIG_FUNCTION_TRACER
+	"  set_ftrace_pid\t- Write pid(s) to only function trace those pids (function)\n"
+#endif
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+	"  set_graph_function\t- Trace the nested calls of a function (function_graph)\n"
+	"  max_graph_depth\t- Trace a limited depth of nested calls (0 is unlimited)\n"
+#endif
+#ifdef CONFIG_TRACER_SNAPSHOT
+	"\n  snapshot\t\t- Like 'trace' but shows the content of the static snapshot buffer\n"
+	"\t\t\t  Read the contents for more information\n"
+#endif
+#ifdef CONFIG_STACKTRACE
+	"  stack_trace\t\t- Shows the max stack trace when active\n"
+	"  stack_max_size\t- Shows current max stack size that was traced\n"
+	"\t\t\t  Write into this file to reset the max size (trigger a new trace)\n"
+#ifdef CONFIG_DYNAMIC_FTRACE
+	"  stack_trace_filter\t- Like set_ftrace_filter but limits what stack_trace traces\n"
+#endif
+#endif /* CONFIG_STACKTRACE */
 ;
 
 static ssize_t
@@ -3080,11 +3449,12 @@ static ssize_t
 tracing_set_trace_read(struct file *filp, char __user *ubuf,
 		       size_t cnt, loff_t *ppos)
 {
+	struct trace_array *tr = filp->private_data;
 	char buf[MAX_TRACER_SIZE+2];
 	int r;
 
 	mutex_lock(&trace_types_lock);
-	r = sprintf(buf, "%s\n", current_trace->name);
+	r = sprintf(buf, "%s\n", tr->current_trace->name);
 	mutex_unlock(&trace_types_lock);
 
 	return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
@@ -3092,43 +3462,48 @@ tracing_set_trace_read(struct file *filp, char __user *ubuf,
 
 int tracer_init(struct tracer *t, struct trace_array *tr)
 {
-	tracing_reset_online_cpus(tr);
+	tracing_reset_online_cpus(&tr->trace_buffer);
 	return t->init(tr);
 }
 
-static void set_buffer_entries(struct trace_array *tr, unsigned long val)
+static void set_buffer_entries(struct trace_buffer *buf, unsigned long val)
 {
 	int cpu;
+
 	for_each_tracing_cpu(cpu)
-		tr->data[cpu]->entries = val;
+		per_cpu_ptr(buf->data, cpu)->entries = val;
 }
 
+#ifdef CONFIG_TRACER_MAX_TRACE
 /* resize @tr's buffer to the size of @size_tr's entries */
-static int resize_buffer_duplicate_size(struct trace_array *tr,
-					struct trace_array *size_tr, int cpu_id)
+static int resize_buffer_duplicate_size(struct trace_buffer *trace_buf,
+					struct trace_buffer *size_buf, int cpu_id)
 {
 	int cpu, ret = 0;
 
 	if (cpu_id == RING_BUFFER_ALL_CPUS) {
 		for_each_tracing_cpu(cpu) {
-			ret = ring_buffer_resize(tr->buffer,
-					size_tr->data[cpu]->entries, cpu);
+			ret = ring_buffer_resize(trace_buf->buffer,
+				 per_cpu_ptr(size_buf->data, cpu)->entries, cpu);
 			if (ret < 0)
 				break;
-			tr->data[cpu]->entries = size_tr->data[cpu]->entries;
+			per_cpu_ptr(trace_buf->data, cpu)->entries =
+				per_cpu_ptr(size_buf->data, cpu)->entries;
 		}
 	} else {
-		ret = ring_buffer_resize(tr->buffer,
-					size_tr->data[cpu_id]->entries, cpu_id);
+		ret = ring_buffer_resize(trace_buf->buffer,
+				 per_cpu_ptr(size_buf->data, cpu_id)->entries, cpu_id);
 		if (ret == 0)
-			tr->data[cpu_id]->entries =
-				size_tr->data[cpu_id]->entries;
+			per_cpu_ptr(trace_buf->data, cpu_id)->entries =
+				per_cpu_ptr(size_buf->data, cpu_id)->entries;
 	}
 
 	return ret;
 }
+#endif /* CONFIG_TRACER_MAX_TRACE */
 
-static int __tracing_resize_ring_buffer(unsigned long size, int cpu)
+static int __tracing_resize_ring_buffer(struct trace_array *tr,
+					unsigned long size, int cpu)
 {
 	int ret;
 
@@ -3137,23 +3512,25 @@ static int __tracing_resize_ring_buffer(unsigned long size, int cpu)
 	 * we use the size that was given, and we can forget about
 	 * expanding it later.
 	 */
-	ring_buffer_expanded = 1;
+	ring_buffer_expanded = true;
 
 	/* May be called before buffers are initialized */
-	if (!global_trace.buffer)
+	if (!tr->trace_buffer.buffer)
 		return 0;
 
-	ret = ring_buffer_resize(global_trace.buffer, size, cpu);
+	ret = ring_buffer_resize(tr->trace_buffer.buffer, size, cpu);
 	if (ret < 0)
 		return ret;
 
-	if (!current_trace->use_max_tr)
+#ifdef CONFIG_TRACER_MAX_TRACE
+	if (!(tr->flags & TRACE_ARRAY_FL_GLOBAL) ||
+	    !tr->current_trace->use_max_tr)
 		goto out;
 
-	ret = ring_buffer_resize(max_tr.buffer, size, cpu);
+	ret = ring_buffer_resize(tr->max_buffer.buffer, size, cpu);
 	if (ret < 0) {
-		int r = resize_buffer_duplicate_size(&global_trace,
-						     &global_trace, cpu);
+		int r = resize_buffer_duplicate_size(&tr->trace_buffer,
+						     &tr->trace_buffer, cpu);
 		if (r < 0) {
 			/*
 			 * AARGH! We are left with different
@@ -3176,20 +3553,23 @@ static int __tracing_resize_ring_buffer(unsigned long size, int cpu)
 	}
 
 	if (cpu == RING_BUFFER_ALL_CPUS)
-		set_buffer_entries(&max_tr, size);
+		set_buffer_entries(&tr->max_buffer, size);
 	else
-		max_tr.data[cpu]->entries = size;
+		per_cpu_ptr(tr->max_buffer.data, cpu)->entries = size;
 
  out:
+#endif /* CONFIG_TRACER_MAX_TRACE */
+
 	if (cpu == RING_BUFFER_ALL_CPUS)
-		set_buffer_entries(&global_trace, size);
+		set_buffer_entries(&tr->trace_buffer, size);
 	else
-		global_trace.data[cpu]->entries = size;
+		per_cpu_ptr(tr->trace_buffer.data, cpu)->entries = size;
 
 	return ret;
 }
 
-static ssize_t tracing_resize_ring_buffer(unsigned long size, int cpu_id)
+static ssize_t tracing_resize_ring_buffer(struct trace_array *tr,
+					  unsigned long size, int cpu_id)
 {
 	int ret = size;
 
@@ -3203,7 +3583,7 @@ static ssize_t tracing_resize_ring_buffer(unsigned long size, int cpu_id)
 		}
 	}
 
-	ret = __tracing_resize_ring_buffer(size, cpu_id);
+	ret = __tracing_resize_ring_buffer(tr, size, cpu_id);
 	if (ret < 0)
 		ret = -ENOMEM;
 
@@ -3230,7 +3610,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(&global_trace, trace_buf_size,
 						RING_BUFFER_ALL_CPUS);
 	mutex_unlock(&trace_types_lock);
 
@@ -3240,7 +3620,7 @@ int tracing_update_buffers(void)
 struct trace_option_dentry;
 
 static struct trace_option_dentry *
-create_trace_option_files(struct tracer *tracer);
+create_trace_option_files(struct trace_array *tr, struct tracer *tracer);
 
 static void
 destroy_trace_option_files(struct trace_option_dentry *topts);
@@ -3250,13 +3630,15 @@ static int tracing_set_tracer(const char *buf)
 	static struct trace_option_dentry *topts;
 	struct trace_array *tr = &global_trace;
 	struct tracer *t;
+#ifdef CONFIG_TRACER_MAX_TRACE
 	bool had_max_tr;
+#endif
 	int ret = 0;
 
 	mutex_lock(&trace_types_lock);
 
 	if (!ring_buffer_expanded) {
-		ret = __tracing_resize_ring_buffer(trace_buf_size,
+		ret = __tracing_resize_ring_buffer(tr, trace_buf_size,
 						RING_BUFFER_ALL_CPUS);
 		if (ret < 0)
 			goto out;
@@ -3271,18 +3653,21 @@ static int tracing_set_tracer(const char *buf)
 		ret = -EINVAL;
 		goto out;
 	}
-	if (t == current_trace)
+	if (t == tr->current_trace)
 		goto out;
 
 	trace_branch_disable();
 
-	current_trace->enabled = false;
+	tr->current_trace->enabled = false;
 
-	if (current_trace->reset)
-		current_trace->reset(tr);
+	if (tr->current_trace->reset)
+		tr->current_trace->reset(tr);
 
-	had_max_tr = current_trace->allocated_snapshot;
-	current_trace = &nop_trace;
+	/* Current trace needs to be nop_trace before synchronize_sched */
+	tr->current_trace = &nop_trace;
+
+#ifdef CONFIG_TRACER_MAX_TRACE
+	had_max_tr = tr->allocated_snapshot;
 
 	if (had_max_tr && !t->use_max_tr) {
 		/*
@@ -3293,27 +3678,20 @@ static int tracing_set_tracer(const char *buf)
 		 * so a synchronized_sched() is sufficient.
 		 */
 		synchronize_sched();
-		/*
-		 * We don't free the ring buffer. instead, resize it because
-		 * The max_tr ring buffer has some state (e.g. ring->clock) and
-		 * we want preserve it.
-		 */
-		ring_buffer_resize(max_tr.buffer, 1, RING_BUFFER_ALL_CPUS);
-		set_buffer_entries(&max_tr, 1);
-		tracing_reset_online_cpus(&max_tr);
-		current_trace->allocated_snapshot = false;
+		free_snapshot(tr);
 	}
+#endif
 	destroy_trace_option_files(topts);
 
-	topts = create_trace_option_files(t);
+	topts = create_trace_option_files(tr, t);
+
+#ifdef CONFIG_TRACER_MAX_TRACE
 	if (t->use_max_tr && !had_max_tr) {
-		/* we need to make per cpu buffer sizes equivalent */
-		ret = resize_buffer_duplicate_size(&max_tr, &global_trace,
-						   RING_BUFFER_ALL_CPUS);
+		ret = alloc_snapshot(tr);
 		if (ret < 0)
 			goto out;
-		t->allocated_snapshot = true;
 	}
+#endif
 
 	if (t->init) {
 		ret = tracer_init(t, tr);
@@ -3321,8 +3699,8 @@ static int tracing_set_tracer(const char *buf)
 			goto out;
 	}
 
-	current_trace = t;
-	current_trace->enabled = true;
+	tr->current_trace = t;
+	tr->current_trace->enabled = true;
 	trace_branch_enable(tr);
  out:
 	mutex_unlock(&trace_types_lock);
@@ -3396,7 +3774,8 @@ tracing_max_lat_write(struct file *filp, const char __user *ubuf,
 
 static int tracing_open_pipe(struct inode *inode, struct file *filp)
 {
-	long cpu_file = (long) inode->i_private;
+	struct trace_cpu *tc = inode->i_private;
+	struct trace_array *tr = tc->tr;
 	struct trace_iterator *iter;
 	int ret = 0;
 
@@ -3421,7 +3800,7 @@ static int tracing_open_pipe(struct inode *inode, struct file *filp)
 		ret = -ENOMEM;
 		goto fail;
 	}
-	*iter->trace = *current_trace;
+	*iter->trace = *tr->current_trace;
 
 	if (!alloc_cpumask_var(&iter->started, GFP_KERNEL)) {
 		ret = -ENOMEM;
@@ -3438,8 +3817,9 @@ static int tracing_open_pipe(struct inode *inode, struct file *filp)
 	if (trace_clocks[trace_clock_id].in_ns)
 		iter->iter_flags |= TRACE_FILE_TIME_IN_NS;
 
-	iter->cpu_file = cpu_file;
-	iter->tr = &global_trace;
+	iter->cpu_file = tc->cpu;
+	iter->tr = tc->tr;
+	iter->trace_buffer = &tc->tr->trace_buffer;
 	mutex_init(&iter->mutex);
 	filp->private_data = iter;
 
@@ -3478,24 +3858,28 @@ static int tracing_release_pipe(struct inode *inode, struct file *file)
 }
 
 static unsigned int
-tracing_poll_pipe(struct file *filp, poll_table *poll_table)
+trace_poll(struct trace_iterator *iter, struct file *filp, poll_table *poll_table)
 {
-	struct trace_iterator *iter = filp->private_data;
+	/* Iterators are static, they should be filled or empty */
+	if (trace_buffer_iter(iter, iter->cpu_file))
+		return POLLIN | POLLRDNORM;
 
-	if (trace_flags & TRACE_ITER_BLOCK) {
+	if (trace_flags & TRACE_ITER_BLOCK)
 		/*
 		 * Always select as readable when in blocking mode
 		 */
 		return POLLIN | POLLRDNORM;
-	} else {
-		if (!trace_empty(iter))
-			return POLLIN | POLLRDNORM;
-		poll_wait(filp, &trace_wait, poll_table);
-		if (!trace_empty(iter))
-			return POLLIN | POLLRDNORM;
+	else
+		return ring_buffer_poll_wait(iter->trace_buffer->buffer, iter->cpu_file,
+					     filp, poll_table);
+}
 
-		return 0;
-	}
+static unsigned int
+tracing_poll_pipe(struct file *filp, poll_table *poll_table)
+{
+	struct trace_iterator *iter = filp->private_data;
+
+	return trace_poll(iter, filp, poll_table);
 }
 
 /*
@@ -3561,6 +3945,7 @@ tracing_read_pipe(struct file *filp, char __user *ubuf,
 		  size_t cnt, loff_t *ppos)
 {
 	struct trace_iterator *iter = filp->private_data;
+	struct trace_array *tr = iter->tr;
 	ssize_t sret;
 
 	/* return any leftover data */
@@ -3572,8 +3957,8 @@ tracing_read_pipe(struct file *filp, char __user *ubuf,
 
 	/* copy the tracer to avoid using a global lock all around */
 	mutex_lock(&trace_types_lock);
-	if (unlikely(iter->trace->name != current_trace->name))
-		*iter->trace = *current_trace;
+	if (unlikely(iter->trace->name != tr->current_trace->name))
+		*iter->trace = *tr->current_trace;
 	mutex_unlock(&trace_types_lock);
 
 	/*
@@ -3729,6 +4114,7 @@ static ssize_t tracing_splice_read_pipe(struct file *filp,
 		.ops		= &tracing_pipe_buf_ops,
 		.spd_release	= tracing_spd_release_pipe,
 	};
+	struct trace_array *tr = iter->tr;
 	ssize_t ret;
 	size_t rem;
 	unsigned int i;
@@ -3738,8 +4124,8 @@ static ssize_t tracing_splice_read_pipe(struct file *filp,
 
 	/* copy the tracer to avoid using a global lock all around */
 	mutex_lock(&trace_types_lock);
-	if (unlikely(iter->trace->name != current_trace->name))
-		*iter->trace = *current_trace;
+	if (unlikely(iter->trace->name != tr->current_trace->name))
+		*iter->trace = *tr->current_trace;
 	mutex_unlock(&trace_types_lock);
 
 	mutex_lock(&iter->mutex);
@@ -3801,43 +4187,19 @@ out_err:
 	goto out;
 }
 
-struct ftrace_entries_info {
-	struct trace_array	*tr;
-	int			cpu;
-};
-
-static int tracing_entries_open(struct inode *inode, struct file *filp)
-{
-	struct ftrace_entries_info *info;
-
-	if (tracing_disabled)
-		return -ENODEV;
-
-	info = kzalloc(sizeof(*info), GFP_KERNEL);
-	if (!info)
-		return -ENOMEM;
-
-	info->tr = &global_trace;
-	info->cpu = (unsigned long)inode->i_private;
-
-	filp->private_data = info;
-
-	return 0;
-}
-
 static ssize_t
 tracing_entries_read(struct file *filp, char __user *ubuf,
 		     size_t cnt, loff_t *ppos)
 {
-	struct ftrace_entries_info *info = filp->private_data;
-	struct trace_array *tr = info->tr;
+	struct trace_cpu *tc = filp->private_data;
+	struct trace_array *tr = tc->tr;
 	char buf[64];
 	int r = 0;
 	ssize_t ret;
 
 	mutex_lock(&trace_types_lock);
 
-	if (info->cpu == RING_BUFFER_ALL_CPUS) {
+	if (tc->cpu == RING_BUFFER_ALL_CPUS) {
 		int cpu, buf_size_same;
 		unsigned long size;
 
@@ -3847,8 +4209,8 @@ tracing_entries_read(struct file *filp, char __user *ubuf,
 		for_each_tracing_cpu(cpu) {
 			/* fill in the size from first enabled cpu */
 			if (size == 0)
-				size = tr->data[cpu]->entries;
-			if (size != tr->data[cpu]->entries) {
+				size = per_cpu_ptr(tr->trace_buffer.data, cpu)->entries;
+			if (size != per_cpu_ptr(tr->trace_buffer.data, cpu)->entries) {
 				buf_size_same = 0;
 				break;
 			}
@@ -3864,7 +4226,7 @@ tracing_entries_read(struct file *filp, char __user *ubuf,
 		} else
 			r = sprintf(buf, "X\n");
 	} else
-		r = sprintf(buf, "%lu\n", tr->data[info->cpu]->entries >> 10);
+		r = sprintf(buf, "%lu\n", per_cpu_ptr(tr->trace_buffer.data, tc->cpu)->entries >> 10);
 
 	mutex_unlock(&trace_types_lock);
 
@@ -3876,7 +4238,7 @@ static ssize_t
 tracing_entries_write(struct file *filp, const char __user *ubuf,
 		      size_t cnt, loff_t *ppos)
 {
-	struct ftrace_entries_info *info = filp->private_data;
+	struct trace_cpu *tc = filp->private_data;
 	unsigned long val;
 	int ret;
 
@@ -3891,7 +4253,7 @@ tracing_entries_write(struct file *filp, const char __user *ubuf,
 	/* value is in KB */
 	val <<= 10;
 
-	ret = tracing_resize_ring_buffer(val, info->cpu);
+	ret = tracing_resize_ring_buffer(tc->tr, val, tc->cpu);
 	if (ret < 0)
 		return ret;
 
@@ -3900,16 +4262,6 @@ tracing_entries_write(struct file *filp, const char __user *ubuf,
 	return cnt;
 }
 
-static int
-tracing_entries_release(struct inode *inode, struct file *filp)
-{
-	struct ftrace_entries_info *info = filp->private_data;
-
-	kfree(info);
-
-	return 0;
-}
-
 static ssize_t
 tracing_total_entries_read(struct file *filp, char __user *ubuf,
 				size_t cnt, loff_t *ppos)
@@ -3921,7 +4273,7 @@ tracing_total_entries_read(struct file *filp, char __user *ubuf,
 
 	mutex_lock(&trace_types_lock);
 	for_each_tracing_cpu(cpu) {
-		size += tr->data[cpu]->entries >> 10;
+		size += per_cpu_ptr(tr->trace_buffer.data, cpu)->entries >> 10;
 		if (!ring_buffer_expanded)
 			expanded_size += trace_buf_size >> 10;
 	}
@@ -3951,11 +4303,13 @@ tracing_free_buffer_write(struct file *filp, const char __user *ubuf,
 static int
 tracing_free_buffer_release(struct inode *inode, struct file *filp)
 {
+	struct trace_array *tr = inode->i_private;
+
 	/* disable tracing ? */
 	if (trace_flags & TRACE_ITER_STOP_ON_FREE)
 		tracing_off();
 	/* resize the ring buffer to 0 */
-	tracing_resize_ring_buffer(0, RING_BUFFER_ALL_CPUS);
+	tracing_resize_ring_buffer(tr, 0, RING_BUFFER_ALL_CPUS);
 
 	return 0;
 }
@@ -4024,7 +4378,7 @@ tracing_mark_write(struct file *filp, const char __user *ubuf,
 
 	local_save_flags(irq_flags);
 	size = sizeof(*entry) + cnt + 2; /* possible \n added */
-	buffer = global_trace.buffer;
+	buffer = global_trace.trace_buffer.buffer;
 	event = trace_buffer_lock_reserve(buffer, TRACE_PRINT, size,
 					  irq_flags, preempt_count());
 	if (!event) {
@@ -4066,13 +4420,14 @@ tracing_mark_write(struct file *filp, const char __user *ubuf,
 
 static int tracing_clock_show(struct seq_file *m, void *v)
 {
+	struct trace_array *tr = m->private;
 	int i;
 
 	for (i = 0; i < ARRAY_SIZE(trace_clocks); i++)
 		seq_printf(m,
 			"%s%s%s%s", i ? " " : "",
-			i == trace_clock_id ? "[" : "", trace_clocks[i].name,
-			i == trace_clock_id ? "]" : "");
+			i == tr->clock_id ? "[" : "", trace_clocks[i].name,
+			i == tr->clock_id ? "]" : "");
 	seq_putc(m, '\n');
 
 	return 0;
@@ -4081,6 +4436,8 @@ static int tracing_clock_show(struct seq_file *m, void *v)
 static ssize_t tracing_clock_write(struct file *filp, const char __user *ubuf,
 				   size_t cnt, loff_t *fpos)
 {
+	struct seq_file *m = filp->private_data;
+	struct trace_array *tr = m->private;
 	char buf[64];
 	const char *clockstr;
 	int i;
@@ -4102,20 +4459,23 @@ static ssize_t tracing_clock_write(struct file *filp, const char __user *ubuf,
 	if (i == ARRAY_SIZE(trace_clocks))
 		return -EINVAL;
 
-	trace_clock_id = i;
-
 	mutex_lock(&trace_types_lock);
 
-	ring_buffer_set_clock(global_trace.buffer, trace_clocks[i].func);
-	if (max_tr.buffer)
-		ring_buffer_set_clock(max_tr.buffer, trace_clocks[i].func);
+	tr->clock_id = i;
+
+	ring_buffer_set_clock(tr->trace_buffer.buffer, trace_clocks[i].func);
 
 	/*
 	 * New clock may not be consistent with the previous clock.
 	 * Reset the buffer so that it doesn't have incomparable timestamps.
 	 */
-	tracing_reset_online_cpus(&global_trace);
-	tracing_reset_online_cpus(&max_tr);
+	tracing_reset_online_cpus(&global_trace.trace_buffer);
+
+#ifdef CONFIG_TRACER_MAX_TRACE
+	if (tr->flags & TRACE_ARRAY_FL_GLOBAL && tr->max_buffer.buffer)
+		ring_buffer_set_clock(tr->max_buffer.buffer, trace_clocks[i].func);
+	tracing_reset_online_cpus(&global_trace.max_buffer);
+#endif
 
 	mutex_unlock(&trace_types_lock);
 
@@ -4128,20 +4488,45 @@ static int tracing_clock_open(struct inode *inode, struct file *file)
 {
 	if (tracing_disabled)
 		return -ENODEV;
-	return single_open(file, tracing_clock_show, NULL);
+
+	return single_open(file, tracing_clock_show, inode->i_private);
 }
 
+struct ftrace_buffer_info {
+	struct trace_iterator	iter;
+	void			*spare;
+	unsigned int		read;
+};
+
 #ifdef CONFIG_TRACER_SNAPSHOT
 static int tracing_snapshot_open(struct inode *inode, struct file *file)
 {
+	struct trace_cpu *tc = inode->i_private;
 	struct trace_iterator *iter;
+	struct seq_file *m;
 	int ret = 0;
 
 	if (file->f_mode & FMODE_READ) {
 		iter = __tracing_open(inode, file, true);
 		if (IS_ERR(iter))
 			ret = PTR_ERR(iter);
+	} else {
+		/* Writes still need the seq_file to hold the private data */
+		m = kzalloc(sizeof(*m), GFP_KERNEL);
+		if (!m)
+			return -ENOMEM;
+		iter = kzalloc(sizeof(*iter), GFP_KERNEL);
+		if (!iter) {
+			kfree(m);
+			return -ENOMEM;
+		}
+		iter->tr = tc->tr;
+		iter->trace_buffer = &tc->tr->max_buffer;
+		iter->cpu_file = tc->cpu;
+		m->private = iter;
+		file->private_data = m;
 	}
+
 	return ret;
 }
 
@@ -4149,6 +4534,9 @@ static ssize_t
 tracing_snapshot_write(struct file *filp, const char __user *ubuf, size_t cnt,
 		       loff_t *ppos)
 {
+	struct seq_file *m = filp->private_data;
+	struct trace_iterator *iter = m->private;
+	struct trace_array *tr = iter->tr;
 	unsigned long val;
 	int ret;
 
@@ -4162,40 +4550,48 @@ tracing_snapshot_write(struct file *filp, const char __user *ubuf, size_t cnt,
 
 	mutex_lock(&trace_types_lock);
 
-	if (current_trace->use_max_tr) {
+	if (tr->current_trace->use_max_tr) {
 		ret = -EBUSY;
 		goto out;
 	}
 
 	switch (val) {
 	case 0:
-		if (current_trace->allocated_snapshot) {
-			/* free spare buffer */
-			ring_buffer_resize(max_tr.buffer, 1,
-					   RING_BUFFER_ALL_CPUS);
-			set_buffer_entries(&max_tr, 1);
-			tracing_reset_online_cpus(&max_tr);
-			current_trace->allocated_snapshot = false;
+		if (iter->cpu_file != RING_BUFFER_ALL_CPUS) {
+			ret = -EINVAL;
+			break;
 		}
+		if (tr->allocated_snapshot)
+			free_snapshot(tr);
 		break;
 	case 1:
-		if (!current_trace->allocated_snapshot) {
-			/* allocate spare buffer */
-			ret = resize_buffer_duplicate_size(&max_tr,
-					&global_trace, RING_BUFFER_ALL_CPUS);
+/* Only allow per-cpu swap if the ring buffer supports it */
+#ifndef CONFIG_RING_BUFFER_ALLOW_SWAP
+		if (iter->cpu_file != RING_BUFFER_ALL_CPUS) {
+			ret = -EINVAL;
+			break;
+		}
+#endif
+		if (!tr->allocated_snapshot) {
+			ret = alloc_snapshot(tr);
 			if (ret < 0)
 				break;
-			current_trace->allocated_snapshot = true;
 		}
-
 		local_irq_disable();
 		/* Now, we're going to swap */
-		update_max_tr(&global_trace, current, smp_processor_id());
+		if (iter->cpu_file == RING_BUFFER_ALL_CPUS)
+			update_max_tr(tr, current, smp_processor_id());
+		else
+			update_max_tr_single(tr, current, iter->cpu_file);
 		local_irq_enable();
 		break;
 	default:
-		if (current_trace->allocated_snapshot)
-			tracing_reset_online_cpus(&max_tr);
+		if (tr->allocated_snapshot) {
+			if (iter->cpu_file == RING_BUFFER_ALL_CPUS)
+				tracing_reset_online_cpus(&tr->max_buffer);
+			else
+				tracing_reset(&tr->max_buffer, iter->cpu_file);
+		}
 		break;
 	}
 
@@ -4207,6 +4603,51 @@ out:
 	mutex_unlock(&trace_types_lock);
 	return ret;
 }
+
+static int tracing_snapshot_release(struct inode *inode, struct file *file)
+{
+	struct seq_file *m = file->private_data;
+
+	if (file->f_mode & FMODE_READ)
+		return tracing_release(inode, file);
+
+	/* If write only, the seq_file is just a stub */
+	if (m)
+		kfree(m->private);
+	kfree(m);
+
+	return 0;
+}
+
+static int tracing_buffers_open(struct inode *inode, struct file *filp);
+static ssize_t tracing_buffers_read(struct file *filp, char __user *ubuf,
+				    size_t count, loff_t *ppos);
+static int tracing_buffers_release(struct inode *inode, struct file *file);
+static ssize_t tracing_buffers_splice_read(struct file *file, loff_t *ppos,
+		   struct pipe_inode_info *pipe, size_t len, unsigned int flags);
+
+static int snapshot_raw_open(struct inode *inode, struct file *filp)
+{
+	struct ftrace_buffer_info *info;
+	int ret;
+
+	ret = tracing_buffers_open(inode, filp);
+	if (ret < 0)
+		return ret;
+
+	info = filp->private_data;
+
+	if (info->iter.trace->use_max_tr) {
+		tracing_buffers_release(inode, filp);
+		return -EBUSY;
+	}
+
+	info->iter.snapshot = true;
+	info->iter.trace_buffer = &info->iter.tr->max_buffer;
+
+	return ret;
+}
+
 #endif /* CONFIG_TRACER_SNAPSHOT */
 
 
@@ -4234,10 +4675,9 @@ static const struct file_operations tracing_pipe_fops = {
 };
 
 static const struct file_operations tracing_entries_fops = {
-	.open		= tracing_entries_open,
+	.open		= tracing_open_generic,
 	.read		= tracing_entries_read,
 	.write		= tracing_entries_write,
-	.release	= tracing_entries_release,
 	.llseek		= generic_file_llseek,
 };
 
@@ -4272,20 +4712,23 @@ static const struct file_operations snapshot_fops = {
 	.read		= seq_read,
 	.write		= tracing_snapshot_write,
 	.llseek		= tracing_seek,
-	.release	= tracing_release,
+	.release	= tracing_snapshot_release,
 };
-#endif /* CONFIG_TRACER_SNAPSHOT */
 
-struct ftrace_buffer_info {
-	struct trace_array	*tr;
-	void			*spare;
-	int			cpu;
-	unsigned int		read;
+static const struct file_operations snapshot_raw_fops = {
+	.open		= snapshot_raw_open,
+	.read		= tracing_buffers_read,
+	.release	= tracing_buffers_release,
+	.splice_read	= tracing_buffers_splice_read,
+	.llseek		= no_llseek,
 };
 
+#endif /* CONFIG_TRACER_SNAPSHOT */
+
 static int tracing_buffers_open(struct inode *inode, struct file *filp)
 {
-	int cpu = (int)(long)inode->i_private;
+	struct trace_cpu *tc = inode->i_private;
+	struct trace_array *tr = tc->tr;
 	struct ftrace_buffer_info *info;
 
 	if (tracing_disabled)
@@ -4295,72 +4738,131 @@ static int tracing_buffers_open(struct inode *inode, struct file *filp)
 	if (!info)
 		return -ENOMEM;
 
-	info->tr	= &global_trace;
-	info->cpu	= cpu;
-	info->spare	= NULL;
+	mutex_lock(&trace_types_lock);
+
+	tr->ref++;
+
+	info->iter.tr		= tr;
+	info->iter.cpu_file	= tc->cpu;
+	info->iter.trace	= tr->current_trace;
+	info->iter.trace_buffer = &tr->trace_buffer;
+	info->spare		= NULL;
 	/* Force reading ring buffer for first read */
-	info->read	= (unsigned int)-1;
+	info->read		= (unsigned int)-1;
 
 	filp->private_data = info;
 
+	mutex_unlock(&trace_types_lock);
+
 	return nonseekable_open(inode, filp);
 }
 
+static unsigned int
+tracing_buffers_poll(struct file *filp, poll_table *poll_table)
+{
+	struct ftrace_buffer_info *info = filp->private_data;
+	struct trace_iterator *iter = &info->iter;
+
+	return trace_poll(iter, filp, poll_table);
+}
+
 static ssize_t
 tracing_buffers_read(struct file *filp, char __user *ubuf,
 		     size_t count, loff_t *ppos)
 {
 	struct ftrace_buffer_info *info = filp->private_data;
+	struct trace_iterator *iter = &info->iter;
 	ssize_t ret;
-	size_t size;
+	ssize_t size;
 
 	if (!count)
 		return 0;
 
+	mutex_lock(&trace_types_lock);
+
+#ifdef CONFIG_TRACER_MAX_TRACE
+	if (iter->snapshot && iter->tr->current_trace->use_max_tr) {
+		size = -EBUSY;
+		goto out_unlock;
+	}
+#endif
+
 	if (!info->spare)
-		info->spare = ring_buffer_alloc_read_page(info->tr->buffer, info->cpu);
+		info->spare = ring_buffer_alloc_read_page(iter->trace_buffer->buffer,
+							  iter->cpu_file);
+	size = -ENOMEM;
 	if (!info->spare)
-		return -ENOMEM;
+		goto out_unlock;
 
 	/* Do we have previous read data to read? */
 	if (info->read < PAGE_SIZE)
 		goto read;
 
-	trace_access_lock(info->cpu);
-	ret = ring_buffer_read_page(info->tr->buffer,
+ again:
+	trace_access_lock(iter->cpu_file);
+	ret = ring_buffer_read_page(iter->trace_buffer->buffer,
 				    &info->spare,
 				    count,
-				    info->cpu, 0);
-	trace_access_unlock(info->cpu);
-	if (ret < 0)
-		return 0;
+				    iter->cpu_file, 0);
+	trace_access_unlock(iter->cpu_file);
 
-	info->read = 0;
+	if (ret < 0) {
+		if (trace_empty(iter)) {
+			if ((filp->f_flags & O_NONBLOCK)) {
+				size = -EAGAIN;
+				goto out_unlock;
+			}
+			mutex_unlock(&trace_types_lock);
+			iter->trace->wait_pipe(iter);
+			mutex_lock(&trace_types_lock);
+			if (signal_pending(current)) {
+				size = -EINTR;
+				goto out_unlock;
+			}
+			goto again;
+		}
+		size = 0;
+		goto out_unlock;
+	}
 
-read:
+	info->read = 0;
+ read:
 	size = PAGE_SIZE - info->read;
 	if (size > count)
 		size = count;
 
 	ret = copy_to_user(ubuf, info->spare + info->read, size);
-	if (ret == size)
-		return -EFAULT;
+	if (ret == size) {
+		size = -EFAULT;
+		goto out_unlock;
+	}
 	size -= ret;
 
 	*ppos += size;
 	info->read += size;
 
+ out_unlock:
+	mutex_unlock(&trace_types_lock);
+
 	return size;
 }
 
 static int tracing_buffers_release(struct inode *inode, struct file *file)
 {
 	struct ftrace_buffer_info *info = file->private_data;
+	struct trace_iterator *iter = &info->iter;
+
+	mutex_lock(&trace_types_lock);
+
+	WARN_ON(!iter->tr->ref);
+	iter->tr->ref--;
 
 	if (info->spare)
-		ring_buffer_free_read_page(info->tr->buffer, info->spare);
+		ring_buffer_free_read_page(iter->trace_buffer->buffer, info->spare);
 	kfree(info);
 
+	mutex_unlock(&trace_types_lock);
+
 	return 0;
 }
 
@@ -4425,6 +4927,7 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos,
 			    unsigned int flags)
 {
 	struct ftrace_buffer_info *info = file->private_data;
+	struct trace_iterator *iter = &info->iter;
 	struct partial_page partial_def[PIPE_DEF_BUFFERS];
 	struct page *pages_def[PIPE_DEF_BUFFERS];
 	struct splice_pipe_desc spd = {
@@ -4437,10 +4940,21 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos,
 	};
 	struct buffer_ref *ref;
 	int entries, size, i;
-	size_t ret;
+	ssize_t ret;
 
-	if (splice_grow_spd(pipe, &spd))
-		return -ENOMEM;
+	mutex_lock(&trace_types_lock);
+
+#ifdef CONFIG_TRACER_MAX_TRACE
+	if (iter->snapshot && iter->tr->current_trace->use_max_tr) {
+		ret = -EBUSY;
+		goto out;
+	}
+#endif
+
+	if (splice_grow_spd(pipe, &spd)) {
+		ret = -ENOMEM;
+		goto out;
+	}
 
 	if (*ppos & (PAGE_SIZE - 1)) {
 		ret = -EINVAL;
@@ -4455,8 +4969,9 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos,
 		len &= PAGE_MASK;
 	}
 
-	trace_access_lock(info->cpu);
-	entries = ring_buffer_entries_cpu(info->tr->buffer, info->cpu);
+ again:
+	trace_access_lock(iter->cpu_file);
+	entries = ring_buffer_entries_cpu(iter->trace_buffer->buffer, iter->cpu_file);
 
 	for (i = 0; i < pipe->buffers && len && entries; i++, len -= PAGE_SIZE) {
 		struct page *page;
@@ -4467,15 +4982,15 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos,
 			break;
 
 		ref->ref = 1;
-		ref->buffer = info->tr->buffer;
-		ref->page = ring_buffer_alloc_read_page(ref->buffer, info->cpu);
+		ref->buffer = iter->trace_buffer->buffer;
+		ref->page = ring_buffer_alloc_read_page(ref->buffer, iter->cpu_file);
 		if (!ref->page) {
 			kfree(ref);
 			break;
 		}
 
 		r = ring_buffer_read_page(ref->buffer, &ref->page,
-					  len, info->cpu, 1);
+					  len, iter->cpu_file, 1);
 		if (r < 0) {
 			ring_buffer_free_read_page(ref->buffer, ref->page);
 			kfree(ref);
@@ -4499,31 +5014,40 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos,
 		spd.nr_pages++;
 		*ppos += PAGE_SIZE;
 
-		entries = ring_buffer_entries_cpu(info->tr->buffer, info->cpu);
+		entries = ring_buffer_entries_cpu(iter->trace_buffer->buffer, iter->cpu_file);
 	}
 
-	trace_access_unlock(info->cpu);
+	trace_access_unlock(iter->cpu_file);
 	spd.nr_pages = i;
 
 	/* did we read anything? */
 	if (!spd.nr_pages) {
-		if (flags & SPLICE_F_NONBLOCK)
+		if ((file->f_flags & O_NONBLOCK) || (flags & SPLICE_F_NONBLOCK)) {
 			ret = -EAGAIN;
-		else
-			ret = 0;
-		/* TODO: block */
-		goto out;
+			goto out;
+		}
+		mutex_unlock(&trace_types_lock);
+		iter->trace->wait_pipe(iter);
+		mutex_lock(&trace_types_lock);
+		if (signal_pending(current)) {
+			ret = -EINTR;
+			goto out;
+		}
+		goto again;
 	}
 
 	ret = splice_to_pipe(pipe, &spd);
 	splice_shrink_spd(&spd);
 out:
+	mutex_unlock(&trace_types_lock);
+
 	return ret;
 }
 
 static const struct file_operations tracing_buffers_fops = {
 	.open		= tracing_buffers_open,
 	.read		= tracing_buffers_read,
+	.poll		= tracing_buffers_poll,
 	.release	= tracing_buffers_release,
 	.splice_read	= tracing_buffers_splice_read,
 	.llseek		= no_llseek,
@@ -4533,12 +5057,14 @@ static ssize_t
 tracing_stats_read(struct file *filp, char __user *ubuf,
 		   size_t count, loff_t *ppos)
 {
-	unsigned long cpu = (unsigned long)filp->private_data;
-	struct trace_array *tr = &global_trace;
+	struct trace_cpu *tc = filp->private_data;
+	struct trace_array *tr = tc->tr;
+	struct trace_buffer *trace_buf = &tr->trace_buffer;
 	struct trace_seq *s;
 	unsigned long cnt;
 	unsigned long long t;
 	unsigned long usec_rem;
+	int cpu = tc->cpu;
 
 	s = kmalloc(sizeof(*s), GFP_KERNEL);
 	if (!s)
@@ -4546,41 +5072,41 @@ tracing_stats_read(struct file *filp, char __user *ubuf,
 
 	trace_seq_init(s);
 
-	cnt = ring_buffer_entries_cpu(tr->buffer, cpu);
+	cnt = ring_buffer_entries_cpu(trace_buf->buffer, cpu);
 	trace_seq_printf(s, "entries: %ld\n", cnt);
 
-	cnt = ring_buffer_overrun_cpu(tr->buffer, cpu);
+	cnt = ring_buffer_overrun_cpu(trace_buf->buffer, cpu);
 	trace_seq_printf(s, "overrun: %ld\n", cnt);
 
-	cnt = ring_buffer_commit_overrun_cpu(tr->buffer, cpu);
+	cnt = ring_buffer_commit_overrun_cpu(trace_buf->buffer, cpu);
 	trace_seq_printf(s, "commit overrun: %ld\n", cnt);
 
-	cnt = ring_buffer_bytes_cpu(tr->buffer, cpu);
+	cnt = ring_buffer_bytes_cpu(trace_buf->buffer, cpu);
 	trace_seq_printf(s, "bytes: %ld\n", cnt);
 
 	if (trace_clocks[trace_clock_id].in_ns) {
 		/* local or global for trace_clock */
-		t = ns2usecs(ring_buffer_oldest_event_ts(tr->buffer, cpu));
+		t = ns2usecs(ring_buffer_oldest_event_ts(trace_buf->buffer, cpu));
 		usec_rem = do_div(t, USEC_PER_SEC);
 		trace_seq_printf(s, "oldest event ts: %5llu.%06lu\n",
 								t, usec_rem);
 
-		t = ns2usecs(ring_buffer_time_stamp(tr->buffer, cpu));
+		t = ns2usecs(ring_buffer_time_stamp(trace_buf->buffer, cpu));
 		usec_rem = do_div(t, USEC_PER_SEC);
 		trace_seq_printf(s, "now ts: %5llu.%06lu\n", t, usec_rem);
 	} else {
 		/* counter or tsc mode for trace_clock */
 		trace_seq_printf(s, "oldest event ts: %llu\n",
-				ring_buffer_oldest_event_ts(tr->buffer, cpu));
+				ring_buffer_oldest_event_ts(trace_buf->buffer, cpu));
 
 		trace_seq_printf(s, "now ts: %llu\n",
-				ring_buffer_time_stamp(tr->buffer, cpu));
+				ring_buffer_time_stamp(trace_buf->buffer, cpu));
 	}
 
-	cnt = ring_buffer_dropped_events_cpu(tr->buffer, cpu);
+	cnt = ring_buffer_dropped_events_cpu(trace_buf->buffer, cpu);
 	trace_seq_printf(s, "dropped events: %ld\n", cnt);
 
-	cnt = ring_buffer_read_events_cpu(tr->buffer, cpu);
+	cnt = ring_buffer_read_events_cpu(trace_buf->buffer, cpu);
 	trace_seq_printf(s, "read events: %ld\n", cnt);
 
 	count = simple_read_from_buffer(ubuf, count, ppos, s->buffer, s->len);
@@ -4632,60 +5158,161 @@ static const struct file_operations tracing_dyn_info_fops = {
 	.read		= tracing_read_dyn_info,
 	.llseek		= generic_file_llseek,
 };
-#endif
+#endif /* CONFIG_DYNAMIC_FTRACE */
+
+#if defined(CONFIG_TRACER_SNAPSHOT) && defined(CONFIG_DYNAMIC_FTRACE)
+static void
+ftrace_snapshot(unsigned long ip, unsigned long parent_ip, void **data)
+{
+	tracing_snapshot();
+}
 
-static struct dentry *d_tracer;
+static void
+ftrace_count_snapshot(unsigned long ip, unsigned long parent_ip, void **data)
+{
+	unsigned long *count = (long *)data;
 
-struct dentry *tracing_init_dentry(void)
+	if (!*count)
+		return;
+
+	if (*count != -1)
+		(*count)--;
+
+	tracing_snapshot();
+}
+
+static int
+ftrace_snapshot_print(struct seq_file *m, unsigned long ip,
+		      struct ftrace_probe_ops *ops, void *data)
+{
+	long count = (long)data;
+
+	seq_printf(m, "%ps:", (void *)ip);
+
+	seq_printf(m, "snapshot");
+
+	if (count == -1)
+		seq_printf(m, ":unlimited\n");
+	else
+		seq_printf(m, ":count=%ld\n", count);
+
+	return 0;
+}
+
+static struct ftrace_probe_ops snapshot_probe_ops = {
+	.func			= ftrace_snapshot,
+	.print			= ftrace_snapshot_print,
+};
+
+static struct ftrace_probe_ops snapshot_count_probe_ops = {
+	.func			= ftrace_count_snapshot,
+	.print			= ftrace_snapshot_print,
+};
+
+static int
+ftrace_trace_snapshot_callback(struct ftrace_hash *hash,
+			       char *glob, char *cmd, char *param, int enable)
 {
-	static int once;
+	struct ftrace_probe_ops *ops;
+	void *count = (void *)-1;
+	char *number;
+	int ret;
+
+	/* hash funcs only work with set_ftrace_filter */
+	if (!enable)
+		return -EINVAL;
+
+	ops = param ? &snapshot_count_probe_ops :  &snapshot_probe_ops;
+
+	if (glob[0] == '!') {
+		unregister_ftrace_function_probe_func(glob+1, ops);
+		return 0;
+	}
+
+	if (!param)
+		goto out_reg;
+
+	number = strsep(&param, ":");
+
+	if (!strlen(number))
+		goto out_reg;
+
+	/*
+	 * We use the callback data field (which is a pointer)
+	 * as our counter.
+	 */
+	ret = kstrtoul(number, 0, (unsigned long *)&count);
+	if (ret)
+		return ret;
+
+ out_reg:
+	ret = register_ftrace_function_probe(glob, ops, count);
+
+	if (ret >= 0)
+		alloc_snapshot(&global_trace);
+
+	return ret < 0 ? ret : 0;
+}
+
+static struct ftrace_func_command ftrace_snapshot_cmd = {
+	.name			= "snapshot",
+	.func			= ftrace_trace_snapshot_callback,
+};
+
+static int register_snapshot_cmd(void)
+{
+	return register_ftrace_command(&ftrace_snapshot_cmd);
+}
+#else
+static inline int register_snapshot_cmd(void) { return 0; }
+#endif /* defined(CONFIG_TRACER_SNAPSHOT) && defined(CONFIG_DYNAMIC_FTRACE) */
 
-	if (d_tracer)
-		return d_tracer;
+struct dentry *tracing_init_dentry_tr(struct trace_array *tr)
+{
+	if (tr->dir)
+		return tr->dir;
 
 	if (!debugfs_initialized())
 		return NULL;
 
-	d_tracer = debugfs_create_dir("tracing", NULL);
+	if (tr->flags & TRACE_ARRAY_FL_GLOBAL)
+		tr->dir = debugfs_create_dir("tracing", NULL);
 
-	if (!d_tracer && !once) {
-		once = 1;
-		pr_warning("Could not create debugfs directory 'tracing'\n");
-		return NULL;
-	}
+	if (!tr->dir)
+		pr_warn_once("Could not create debugfs directory 'tracing'\n");
 
-	return d_tracer;
+	return tr->dir;
 }
 
-static struct dentry *d_percpu;
+struct dentry *tracing_init_dentry(void)
+{
+	return tracing_init_dentry_tr(&global_trace);
+}
 
-static struct dentry *tracing_dentry_percpu(void)
+static struct dentry *tracing_dentry_percpu(struct trace_array *tr, int cpu)
 {
-	static int once;
 	struct dentry *d_tracer;
 
-	if (d_percpu)
-		return d_percpu;
-
-	d_tracer = tracing_init_dentry();
+	if (tr->percpu_dir)
+		return tr->percpu_dir;
 
+	d_tracer = tracing_init_dentry_tr(tr);
 	if (!d_tracer)
 		return NULL;
 
-	d_percpu = debugfs_create_dir("per_cpu", d_tracer);
+	tr->percpu_dir = debugfs_create_dir("per_cpu", d_tracer);
 
-	if (!d_percpu && !once) {
-		once = 1;
-		pr_warning("Could not create debugfs directory 'per_cpu'\n");
-		return NULL;
-	}
+	WARN_ONCE(!tr->percpu_dir,
+		  "Could not create debugfs directory 'per_cpu/%d'\n", cpu);
 
-	return d_percpu;
+	return tr->percpu_dir;
 }
 
-static void tracing_init_debugfs_percpu(long cpu)
+static void
+tracing_init_debugfs_percpu(struct trace_array *tr, long cpu)
 {
-	struct dentry *d_percpu = tracing_dentry_percpu();
+	struct trace_array_cpu *data = per_cpu_ptr(tr->trace_buffer.data, cpu);
+	struct dentry *d_percpu = tracing_dentry_percpu(tr, cpu);
 	struct dentry *d_cpu;
 	char cpu_dir[30]; /* 30 characters should be more than enough */
 
@@ -4701,20 +5328,28 @@ static void tracing_init_debugfs_percpu(long cpu)
 
 	/* per cpu trace_pipe */
 	trace_create_file("trace_pipe", 0444, d_cpu,
-			(void *) cpu, &tracing_pipe_fops);
+			(void *)&data->trace_cpu, &tracing_pipe_fops);
 
 	/* per cpu trace */
 	trace_create_file("trace", 0644, d_cpu,
-			(void *) cpu, &tracing_fops);
+			(void *)&data->trace_cpu, &tracing_fops);
 
 	trace_create_file("trace_pipe_raw", 0444, d_cpu,
-			(void *) cpu, &tracing_buffers_fops);
+			(void *)&data->trace_cpu, &tracing_buffers_fops);
 
 	trace_create_file("stats", 0444, d_cpu,
-			(void *) cpu, &tracing_stats_fops);
+			(void *)&data->trace_cpu, &tracing_stats_fops);
 
 	trace_create_file("buffer_size_kb", 0444, d_cpu,
-			(void *) cpu, &tracing_entries_fops);
+			(void *)&data->trace_cpu, &tracing_entries_fops);
+
+#ifdef CONFIG_TRACER_SNAPSHOT
+	trace_create_file("snapshot", 0644, d_cpu,
+			  (void *)&data->trace_cpu, &snapshot_fops);
+
+	trace_create_file("snapshot_raw", 0444, d_cpu,
+			(void *)&data->trace_cpu, &snapshot_raw_fops);
+#endif
 }
 
 #ifdef CONFIG_FTRACE_SELFTEST
@@ -4725,6 +5360,7 @@ static void tracing_init_debugfs_percpu(long cpu)
 struct trace_option_dentry {
 	struct tracer_opt		*opt;
 	struct tracer_flags		*flags;
+	struct trace_array		*tr;
 	struct dentry			*entry;
 };
 
@@ -4760,7 +5396,7 @@ trace_options_write(struct file *filp, const char __user *ubuf, size_t cnt,
 
 	if (!!(topt->flags->val & topt->opt->bit) != val) {
 		mutex_lock(&trace_types_lock);
-		ret = __set_tracer_option(current_trace, topt->flags,
+		ret = __set_tracer_option(topt->tr->current_trace, topt->flags,
 					  topt->opt, !val);
 		mutex_unlock(&trace_types_lock);
 		if (ret)
@@ -4799,6 +5435,7 @@ static ssize_t
 trace_options_core_write(struct file *filp, const char __user *ubuf, size_t cnt,
 			 loff_t *ppos)
 {
+	struct trace_array *tr = &global_trace;
 	long index = (long)filp->private_data;
 	unsigned long val;
 	int ret;
@@ -4811,7 +5448,7 @@ trace_options_core_write(struct file *filp, const char __user *ubuf, size_t cnt,
 		return -EINVAL;
 
 	mutex_lock(&trace_types_lock);
-	ret = set_tracer_flag(1 << index, val);
+	ret = set_tracer_flag(tr, 1 << index, val);
 	mutex_unlock(&trace_types_lock);
 
 	if (ret < 0)
@@ -4845,40 +5482,41 @@ struct dentry *trace_create_file(const char *name,
 }
 
 
-static struct dentry *trace_options_init_dentry(void)
+static struct dentry *trace_options_init_dentry(struct trace_array *tr)
 {
 	struct dentry *d_tracer;
-	static struct dentry *t_options;
 
-	if (t_options)
-		return t_options;
+	if (tr->options)
+		return tr->options;
 
-	d_tracer = tracing_init_dentry();
+	d_tracer = tracing_init_dentry_tr(tr);
 	if (!d_tracer)
 		return NULL;
 
-	t_options = debugfs_create_dir("options", d_tracer);
-	if (!t_options) {
+	tr->options = debugfs_create_dir("options", d_tracer);
+	if (!tr->options) {
 		pr_warning("Could not create debugfs directory 'options'\n");
 		return NULL;
 	}
 
-	return t_options;
+	return tr->options;
 }
 
 static void
-create_trace_option_file(struct trace_option_dentry *topt,
+create_trace_option_file(struct trace_array *tr,
+			 struct trace_option_dentry *topt,
 			 struct tracer_flags *flags,
 			 struct tracer_opt *opt)
 {
 	struct dentry *t_options;
 
-	t_options = trace_options_init_dentry();
+	t_options = trace_options_init_dentry(tr);
 	if (!t_options)
 		return;
 
 	topt->flags = flags;
 	topt->opt = opt;
+	topt->tr = tr;
 
 	topt->entry = trace_create_file(opt->name, 0644, t_options, topt,
 				    &trace_options_fops);
@@ -4886,7 +5524,7 @@ create_trace_option_file(struct trace_option_dentry *topt,
 }
 
 static struct trace_option_dentry *
-create_trace_option_files(struct tracer *tracer)
+create_trace_option_files(struct trace_array *tr, struct tracer *tracer)
 {
 	struct trace_option_dentry *topts;
 	struct tracer_flags *flags;
@@ -4911,7 +5549,7 @@ create_trace_option_files(struct tracer *tracer)
 		return NULL;
 
 	for (cnt = 0; opts[cnt].name; cnt++)
-		create_trace_option_file(&topts[cnt], flags,
+		create_trace_option_file(tr, &topts[cnt], flags,
 					 &opts[cnt]);
 
 	return topts;
@@ -4934,11 +5572,12 @@ destroy_trace_option_files(struct trace_option_dentry *topts)
 }
 
 static struct dentry *
-create_trace_option_core_file(const char *option, long index)
+create_trace_option_core_file(struct trace_array *tr,
+			      const char *option, long index)
 {
 	struct dentry *t_options;
 
-	t_options = trace_options_init_dentry();
+	t_options = trace_options_init_dentry(tr);
 	if (!t_options)
 		return NULL;
 
@@ -4946,17 +5585,17 @@ create_trace_option_core_file(const char *option, long index)
 				    &trace_options_core_fops);
 }
 
-static __init void create_trace_options_dir(void)
+static __init void create_trace_options_dir(struct trace_array *tr)
 {
 	struct dentry *t_options;
 	int i;
 
-	t_options = trace_options_init_dentry();
+	t_options = trace_options_init_dentry(tr);
 	if (!t_options)
 		return;
 
 	for (i = 0; trace_options[i]; i++)
-		create_trace_option_core_file(trace_options[i], i);
+		create_trace_option_core_file(tr, trace_options[i], i);
 }
 
 static ssize_t
@@ -4964,7 +5603,7 @@ rb_simple_read(struct file *filp, char __user *ubuf,
 	       size_t cnt, loff_t *ppos)
 {
 	struct trace_array *tr = filp->private_data;
-	struct ring_buffer *buffer = tr->buffer;
+	struct ring_buffer *buffer = tr->trace_buffer.buffer;
 	char buf[64];
 	int r;
 
@@ -4983,7 +5622,7 @@ rb_simple_write(struct file *filp, const char __user *ubuf,
 		size_t cnt, loff_t *ppos)
 {
 	struct trace_array *tr = filp->private_data;
-	struct ring_buffer *buffer = tr->buffer;
+	struct ring_buffer *buffer = tr->trace_buffer.buffer;
 	unsigned long val;
 	int ret;
 
@@ -4995,12 +5634,12 @@ rb_simple_write(struct file *filp, const char __user *ubuf,
 		mutex_lock(&trace_types_lock);
 		if (val) {
 			ring_buffer_record_on(buffer);
-			if (current_trace->start)
-				current_trace->start(tr);
+			if (tr->current_trace->start)
+				tr->current_trace->start(tr);
 		} else {
 			ring_buffer_record_off(buffer);
-			if (current_trace->stop)
-				current_trace->stop(tr);
+			if (tr->current_trace->stop)
+				tr->current_trace->stop(tr);
 		}
 		mutex_unlock(&trace_types_lock);
 	}
@@ -5017,23 +5656,308 @@ static const struct file_operations rb_simple_fops = {
 	.llseek		= default_llseek,
 };
 
+struct dentry *trace_instance_dir;
+
+static void
+init_tracer_debugfs(struct trace_array *tr, struct dentry *d_tracer);
+
+static void init_trace_buffers(struct trace_array *tr, struct trace_buffer *buf)
+{
+	int cpu;
+
+	for_each_tracing_cpu(cpu) {
+		memset(per_cpu_ptr(buf->data, cpu), 0, sizeof(struct trace_array_cpu));
+		per_cpu_ptr(buf->data, cpu)->trace_cpu.cpu = cpu;
+		per_cpu_ptr(buf->data, cpu)->trace_cpu.tr = tr;
+	}
+}
+
+static int
+allocate_trace_buffer(struct trace_array *tr, struct trace_buffer *buf, int size)
+{
+	enum ring_buffer_flags rb_flags;
+
+	rb_flags = trace_flags & TRACE_ITER_OVERWRITE ? RB_FL_OVERWRITE : 0;
+
+	buf->buffer = ring_buffer_alloc(size, rb_flags);
+	if (!buf->buffer)
+		return -ENOMEM;
+
+	buf->data = alloc_percpu(struct trace_array_cpu);
+	if (!buf->data) {
+		ring_buffer_free(buf->buffer);
+		return -ENOMEM;
+	}
+
+	init_trace_buffers(tr, buf);
+
+	/* Allocate the first page for all buffers */
+	set_buffer_entries(&tr->trace_buffer,
+			   ring_buffer_size(tr->trace_buffer.buffer, 0));
+
+	return 0;
+}
+
+static int allocate_trace_buffers(struct trace_array *tr, int size)
+{
+	int ret;
+
+	ret = allocate_trace_buffer(tr, &tr->trace_buffer, size);
+	if (ret)
+		return ret;
+
+#ifdef CONFIG_TRACER_MAX_TRACE
+	ret = allocate_trace_buffer(tr, &tr->max_buffer,
+				    allocate_snapshot ? size : 1);
+	if (WARN_ON(ret)) {
+		ring_buffer_free(tr->trace_buffer.buffer);
+		free_percpu(tr->trace_buffer.data);
+		return -ENOMEM;
+	}
+	tr->allocated_snapshot = allocate_snapshot;
+
+	/*
+	 * Only the top level trace array gets its snapshot allocated
+	 * from the kernel command line.
+	 */
+	allocate_snapshot = false;
+#endif
+	return 0;
+}
+
+static int new_instance_create(const char *name)
+{
+	struct trace_array *tr;
+	int ret;
+
+	mutex_lock(&trace_types_lock);
+
+	ret = -EEXIST;
+	list_for_each_entry(tr, &ftrace_trace_arrays, list) {
+		if (tr->name && strcmp(tr->name, name) == 0)
+			goto out_unlock;
+	}
+
+	ret = -ENOMEM;
+	tr = kzalloc(sizeof(*tr), GFP_KERNEL);
+	if (!tr)
+		goto out_unlock;
+
+	tr->name = kstrdup(name, GFP_KERNEL);
+	if (!tr->name)
+		goto out_free_tr;
+
+	raw_spin_lock_init(&tr->start_lock);
+
+	tr->current_trace = &nop_trace;
+
+	INIT_LIST_HEAD(&tr->systems);
+	INIT_LIST_HEAD(&tr->events);
+
+	if (allocate_trace_buffers(tr, trace_buf_size) < 0)
+		goto out_free_tr;
+
+	/* Holder for file callbacks */
+	tr->trace_cpu.cpu = RING_BUFFER_ALL_CPUS;
+	tr->trace_cpu.tr = tr;
+
+	tr->dir = debugfs_create_dir(name, trace_instance_dir);
+	if (!tr->dir)
+		goto out_free_tr;
+
+	ret = event_trace_add_tracer(tr->dir, tr);
+	if (ret)
+		goto out_free_tr;
+
+	init_tracer_debugfs(tr, tr->dir);
+
+	list_add(&tr->list, &ftrace_trace_arrays);
+
+	mutex_unlock(&trace_types_lock);
+
+	return 0;
+
+ out_free_tr:
+	if (tr->trace_buffer.buffer)
+		ring_buffer_free(tr->trace_buffer.buffer);
+	kfree(tr->name);
+	kfree(tr);
+
+ out_unlock:
+	mutex_unlock(&trace_types_lock);
+
+	return ret;
+
+}
+
+static int instance_delete(const char *name)
+{
+	struct trace_array *tr;
+	int found = 0;
+	int ret;
+
+	mutex_lock(&trace_types_lock);
+
+	ret = -ENODEV;
+	list_for_each_entry(tr, &ftrace_trace_arrays, list) {
+		if (tr->name && strcmp(tr->name, name) == 0) {
+			found = 1;
+			break;
+		}
+	}
+	if (!found)
+		goto out_unlock;
+
+	ret = -EBUSY;
+	if (tr->ref)
+		goto out_unlock;
+
+	list_del(&tr->list);
+
+	event_trace_del_tracer(tr);
+	debugfs_remove_recursive(tr->dir);
+	free_percpu(tr->trace_buffer.data);
+	ring_buffer_free(tr->trace_buffer.buffer);
+
+	kfree(tr->name);
+	kfree(tr);
+
+	ret = 0;
+
+ out_unlock:
+	mutex_unlock(&trace_types_lock);
+
+	return ret;
+}
+
+static int instance_mkdir (struct inode *inode, struct dentry *dentry, umode_t mode)
+{
+	struct dentry *parent;
+	int ret;
+
+	/* Paranoid: Make sure the parent is the "instances" directory */
+	parent = hlist_entry(inode->i_dentry.first, struct dentry, d_alias);
+	if (WARN_ON_ONCE(parent != trace_instance_dir))
+		return -ENOENT;
+
+	/*
+	 * The inode mutex is locked, but debugfs_create_dir() will also
+	 * take the mutex. As the instances directory can not be destroyed
+	 * or changed in any other way, it is safe to unlock it, and
+	 * let the dentry try. If two users try to make the same dir at
+	 * the same time, then the new_instance_create() will determine the
+	 * winner.
+	 */
+	mutex_unlock(&inode->i_mutex);
+
+	ret = new_instance_create(dentry->d_iname);
+
+	mutex_lock(&inode->i_mutex);
+
+	return ret;
+}
+
+static int instance_rmdir(struct inode *inode, struct dentry *dentry)
+{
+	struct dentry *parent;
+	int ret;
+
+	/* Paranoid: Make sure the parent is the "instances" directory */
+	parent = hlist_entry(inode->i_dentry.first, struct dentry, d_alias);
+	if (WARN_ON_ONCE(parent != trace_instance_dir))
+		return -ENOENT;
+
+	/* The caller did a dget() on dentry */
+	mutex_unlock(&dentry->d_inode->i_mutex);
+
+	/*
+	 * The inode mutex is locked, but debugfs_create_dir() will also
+	 * take the mutex. As the instances directory can not be destroyed
+	 * or changed in any other way, it is safe to unlock it, and
+	 * let the dentry try. If two users try to make the same dir at
+	 * the same time, then the instance_delete() will determine the
+	 * winner.
+	 */
+	mutex_unlock(&inode->i_mutex);
+
+	ret = instance_delete(dentry->d_iname);
+
+	mutex_lock_nested(&inode->i_mutex, I_MUTEX_PARENT);
+	mutex_lock(&dentry->d_inode->i_mutex);
+
+	return ret;
+}
+
+static const struct inode_operations instance_dir_inode_operations = {
+	.lookup		= simple_lookup,
+	.mkdir		= instance_mkdir,
+	.rmdir		= instance_rmdir,
+};
+
+static __init void create_trace_instances(struct dentry *d_tracer)
+{
+	trace_instance_dir = debugfs_create_dir("instances", d_tracer);
+	if (WARN_ON(!trace_instance_dir))
+		return;
+
+	/* Hijack the dir inode operations, to allow mkdir */
+	trace_instance_dir->d_inode->i_op = &instance_dir_inode_operations;
+}
+
+static void
+init_tracer_debugfs(struct trace_array *tr, struct dentry *d_tracer)
+{
+	int cpu;
+
+	trace_create_file("trace_options", 0644, d_tracer,
+			  tr, &tracing_iter_fops);
+
+	trace_create_file("trace", 0644, d_tracer,
+			(void *)&tr->trace_cpu, &tracing_fops);
+
+	trace_create_file("trace_pipe", 0444, d_tracer,
+			(void *)&tr->trace_cpu, &tracing_pipe_fops);
+
+	trace_create_file("buffer_size_kb", 0644, d_tracer,
+			(void *)&tr->trace_cpu, &tracing_entries_fops);
+
+	trace_create_file("buffer_total_size_kb", 0444, d_tracer,
+			  tr, &tracing_total_entries_fops);
+
+	trace_create_file("free_buffer", 0644, d_tracer,
+			  tr, &tracing_free_buffer_fops);
+
+	trace_create_file("trace_marker", 0220, d_tracer,
+			  tr, &tracing_mark_fops);
+
+	trace_create_file("trace_clock", 0644, d_tracer, tr,
+			  &trace_clock_fops);
+
+	trace_create_file("tracing_on", 0644, d_tracer,
+			    tr, &rb_simple_fops);
+
+#ifdef CONFIG_TRACER_SNAPSHOT
+	trace_create_file("snapshot", 0644, d_tracer,
+			  (void *)&tr->trace_cpu, &snapshot_fops);
+#endif
+
+	for_each_tracing_cpu(cpu)
+		tracing_init_debugfs_percpu(tr, cpu);
+
+}
+
 static __init int tracer_init_debugfs(void)
 {
 	struct dentry *d_tracer;
-	int cpu;
 
 	trace_access_lock_init();
 
 	d_tracer = tracing_init_dentry();
 
-	trace_create_file("trace_options", 0644, d_tracer,
-			NULL, &tracing_iter_fops);
+	init_tracer_debugfs(&global_trace, d_tracer);
 
 	trace_create_file("tracing_cpumask", 0644, d_tracer,
-			NULL, &tracing_cpumask_fops);
-
-	trace_create_file("trace", 0644, d_tracer,
-			(void *) TRACE_PIPE_ALL_CPU, &tracing_fops);
+			&global_trace, &tracing_cpumask_fops);
 
 	trace_create_file("available_tracers", 0444, d_tracer,
 			&global_trace, &show_traces_fops);
@@ -5052,44 +5976,17 @@ static __init int tracer_init_debugfs(void)
 	trace_create_file("README", 0444, d_tracer,
 			NULL, &tracing_readme_fops);
 
-	trace_create_file("trace_pipe", 0444, d_tracer,
-			(void *) TRACE_PIPE_ALL_CPU, &tracing_pipe_fops);
-
-	trace_create_file("buffer_size_kb", 0644, d_tracer,
-			(void *) RING_BUFFER_ALL_CPUS, &tracing_entries_fops);
-
-	trace_create_file("buffer_total_size_kb", 0444, d_tracer,
-			&global_trace, &tracing_total_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);
-
 	trace_create_file("saved_cmdlines", 0444, d_tracer,
 			NULL, &tracing_saved_cmdlines_fops);
 
-	trace_create_file("trace_clock", 0644, d_tracer, NULL,
-			  &trace_clock_fops);
-
-	trace_create_file("tracing_on", 0644, d_tracer,
-			    &global_trace, &rb_simple_fops);
-
 #ifdef CONFIG_DYNAMIC_FTRACE
 	trace_create_file("dyn_ftrace_total_info", 0444, d_tracer,
 			&ftrace_update_tot_cnt, &tracing_dyn_info_fops);
 #endif
 
-#ifdef CONFIG_TRACER_SNAPSHOT
-	trace_create_file("snapshot", 0644, d_tracer,
-			  (void *) TRACE_PIPE_ALL_CPU, &snapshot_fops);
-#endif
-
-	create_trace_options_dir();
+	create_trace_instances(d_tracer);
 
-	for_each_tracing_cpu(cpu)
-		tracing_init_debugfs_percpu(cpu);
+	create_trace_options_dir(&global_trace);
 
 	return 0;
 }
@@ -5145,8 +6042,8 @@ void
 trace_printk_seq(struct trace_seq *s)
 {
 	/* Probably should print a warning here. */
-	if (s->len >= 1000)
-		s->len = 1000;
+	if (s->len >= TRACE_MAX_PRINT)
+		s->len = TRACE_MAX_PRINT;
 
 	/* should be zero ended, but we are paranoid. */
 	s->buffer[s->len] = 0;
@@ -5159,46 +6056,43 @@ trace_printk_seq(struct trace_seq *s)
 void trace_init_global_iter(struct trace_iterator *iter)
 {
 	iter->tr = &global_trace;
-	iter->trace = current_trace;
-	iter->cpu_file = TRACE_PIPE_ALL_CPU;
+	iter->trace = iter->tr->current_trace;
+	iter->cpu_file = RING_BUFFER_ALL_CPUS;
+	iter->trace_buffer = &global_trace.trace_buffer;
 }
 
-static void
-__ftrace_dump(bool disable_tracing, enum ftrace_dump_mode oops_dump_mode)
+void ftrace_dump(enum ftrace_dump_mode oops_dump_mode)
 {
-	static arch_spinlock_t ftrace_dump_lock =
-		(arch_spinlock_t)__ARCH_SPIN_LOCK_UNLOCKED;
 	/* use static because iter can be a bit big for the stack */
 	static struct trace_iterator iter;
+	static atomic_t dump_running;
 	unsigned int old_userobj;
-	static int dump_ran;
 	unsigned long flags;
 	int cnt = 0, cpu;
 
-	/* only one dump */
-	local_irq_save(flags);
-	arch_spin_lock(&ftrace_dump_lock);
-	if (dump_ran)
-		goto out;
-
-	dump_ran = 1;
+	/* Only allow one dump user at a time. */
+	if (atomic_inc_return(&dump_running) != 1) {
+		atomic_dec(&dump_running);
+		return;
+	}
 
+	/*
+	 * Always turn off tracing when we dump.
+	 * We don't need to show trace output of what happens
+	 * between multiple crashes.
+	 *
+	 * If the user does a sysrq-z, then they can re-enable
+	 * tracing with echo 1 > tracing_on.
+	 */
 	tracing_off();
 
-	/* Did function tracer already get disabled? */
-	if (ftrace_is_dead()) {
-		printk("# WARNING: FUNCTION TRACING IS CORRUPTED\n");
-		printk("#          MAY BE MISSING FUNCTION EVENTS\n");
-	}
-
-	if (disable_tracing)
-		ftrace_kill();
+	local_irq_save(flags);
 
 	/* Simulate the iterator */
 	trace_init_global_iter(&iter);
 
 	for_each_tracing_cpu(cpu) {
-		atomic_inc(&iter.tr->data[cpu]->disabled);
+		atomic_inc(&per_cpu_ptr(iter.tr->trace_buffer.data, cpu)->disabled);
 	}
 
 	old_userobj = trace_flags & TRACE_ITER_SYM_USEROBJ;
@@ -5208,7 +6102,7 @@ __ftrace_dump(bool disable_tracing, enum ftrace_dump_mode oops_dump_mode)
 
 	switch (oops_dump_mode) {
 	case DUMP_ALL:
-		iter.cpu_file = TRACE_PIPE_ALL_CPU;
+		iter.cpu_file = RING_BUFFER_ALL_CPUS;
 		break;
 	case DUMP_ORIG:
 		iter.cpu_file = raw_smp_processor_id();
@@ -5217,11 +6111,17 @@ __ftrace_dump(bool disable_tracing, enum ftrace_dump_mode oops_dump_mode)
 		goto out_enable;
 	default:
 		printk(KERN_TRACE "Bad dumping mode, switching to all CPUs dump\n");
-		iter.cpu_file = TRACE_PIPE_ALL_CPU;
+		iter.cpu_file = RING_BUFFER_ALL_CPUS;
 	}
 
 	printk(KERN_TRACE "Dumping ftrace buffer:\n");
 
+	/* Did function tracer already get disabled? */
+	if (ftrace_is_dead()) {
+		printk("# WARNING: FUNCTION TRACING IS CORRUPTED\n");
+		printk("#          MAY BE MISSING FUNCTION EVENTS\n");
+	}
+
 	/*
 	 * We need to stop all tracing on all CPUS to read the
 	 * the next buffer. This is a bit expensive, but is
@@ -5261,33 +6161,19 @@ __ftrace_dump(bool disable_tracing, enum ftrace_dump_mode oops_dump_mode)
 		printk(KERN_TRACE "---------------------------------\n");
 
  out_enable:
-	/* Re-enable tracing if requested */
-	if (!disable_tracing) {
-		trace_flags |= old_userobj;
+	trace_flags |= old_userobj;
 
-		for_each_tracing_cpu(cpu) {
-			atomic_dec(&iter.tr->data[cpu]->disabled);
-		}
-		tracing_on();
+	for_each_tracing_cpu(cpu) {
+		atomic_dec(&per_cpu_ptr(iter.trace_buffer->data, cpu)->disabled);
 	}
-
- out:
-	arch_spin_unlock(&ftrace_dump_lock);
+ 	atomic_dec(&dump_running);
 	local_irq_restore(flags);
 }
-
-/* By default: disable tracing after the dump */
-void ftrace_dump(enum ftrace_dump_mode oops_dump_mode)
-{
-	__ftrace_dump(true, oops_dump_mode);
-}
 EXPORT_SYMBOL_GPL(ftrace_dump);
 
 __init static int tracer_alloc_buffers(void)
 {
 	int ring_buf_size;
-	enum ring_buffer_flags rb_flags;
-	int i;
 	int ret = -ENOMEM;
 
 
@@ -5308,49 +6194,27 @@ __init static int tracer_alloc_buffers(void)
 	else
 		ring_buf_size = 1;
 
-	rb_flags = trace_flags & TRACE_ITER_OVERWRITE ? RB_FL_OVERWRITE : 0;
-
 	cpumask_copy(tracing_buffer_mask, cpu_possible_mask);
 	cpumask_copy(tracing_cpumask, cpu_all_mask);
 
+	raw_spin_lock_init(&global_trace.start_lock);
+
 	/* TODO: make the number of buffers hot pluggable with CPUS */
-	global_trace.buffer = ring_buffer_alloc(ring_buf_size, rb_flags);
-	if (!global_trace.buffer) {
+	if (allocate_trace_buffers(&global_trace, ring_buf_size) < 0) {
 		printk(KERN_ERR "tracer: failed to allocate ring buffer!\n");
 		WARN_ON(1);
 		goto out_free_cpumask;
 	}
+
 	if (global_trace.buffer_disabled)
 		tracing_off();
 
-
-#ifdef CONFIG_TRACER_MAX_TRACE
-	max_tr.buffer = ring_buffer_alloc(1, rb_flags);
-	if (!max_tr.buffer) {
-		printk(KERN_ERR "tracer: failed to allocate max ring buffer!\n");
-		WARN_ON(1);
-		ring_buffer_free(global_trace.buffer);
-		goto out_free_cpumask;
-	}
-#endif
-
-	/* Allocate the first page for all buffers */
-	for_each_tracing_cpu(i) {
-		global_trace.data[i] = &per_cpu(global_trace_cpu, i);
-		max_tr.data[i] = &per_cpu(max_tr_data, i);
-	}
-
-	set_buffer_entries(&global_trace,
-			   ring_buffer_size(global_trace.buffer, 0));
-#ifdef CONFIG_TRACER_MAX_TRACE
-	set_buffer_entries(&max_tr, 1);
-#endif
-
 	trace_init_cmdlines();
-	init_irq_work(&trace_work_wakeup, trace_wake_up);
 
 	register_tracer(&nop_trace);
 
+	global_trace.current_trace = &nop_trace;
+
 	/* All seems OK, enable tracing */
 	tracing_disabled = 0;
 
@@ -5359,16 +6223,32 @@ __init static int tracer_alloc_buffers(void)
 
 	register_die_notifier(&trace_die_notifier);
 
+	global_trace.flags = TRACE_ARRAY_FL_GLOBAL;
+
+	/* Holder for file callbacks */
+	global_trace.trace_cpu.cpu = RING_BUFFER_ALL_CPUS;
+	global_trace.trace_cpu.tr = &global_trace;
+
+	INIT_LIST_HEAD(&global_trace.systems);
+	INIT_LIST_HEAD(&global_trace.events);
+	list_add(&global_trace.list, &ftrace_trace_arrays);
+
 	while (trace_boot_options) {
 		char *option;
 
 		option = strsep(&trace_boot_options, ",");
-		trace_set_options(option);
+		trace_set_options(&global_trace, option);
 	}
 
+	register_snapshot_cmd();
+
 	return 0;
 
 out_free_cpumask:
+	free_percpu(global_trace.trace_buffer.data);
+#ifdef CONFIG_TRACER_MAX_TRACE
+	free_percpu(global_trace.max_buffer.data);
+#endif
 	free_cpumask_var(tracing_cpumask);
 out_free_buffer_mask:
 	free_cpumask_var(tracing_buffer_mask);
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 2081971..9e01458 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -13,6 +13,11 @@
 #include <linux/trace_seq.h>
 #include <linux/ftrace_event.h>
 
+#ifdef CONFIG_FTRACE_SYSCALLS
+#include <asm/unistd.h>		/* For NR_SYSCALLS	     */
+#include <asm/syscall.h>	/* some archs define it here */
+#endif
+
 enum trace_type {
 	__TRACE_FIRST_TYPE = 0,
 
@@ -29,6 +34,7 @@ enum trace_type {
 	TRACE_GRAPH_ENT,
 	TRACE_USER_STACK,
 	TRACE_BLK,
+	TRACE_BPUTS,
 
 	__TRACE_LAST_TYPE,
 };
@@ -127,12 +133,21 @@ enum trace_flag_type {
 
 #define TRACE_BUF_SIZE		1024
 
+struct trace_array;
+
+struct trace_cpu {
+	struct trace_array	*tr;
+	struct dentry		*dir;
+	int			cpu;
+};
+
 /*
  * The CPU trace array - it consists of thousands of trace entries
  * plus some other descriptor data: (for example which task started
  * the trace, etc.)
  */
 struct trace_array_cpu {
+	struct trace_cpu	trace_cpu;
 	atomic_t		disabled;
 	void			*buffer_page;	/* ring buffer spare */
 
@@ -151,20 +166,83 @@ struct trace_array_cpu {
 	char			comm[TASK_COMM_LEN];
 };
 
+struct tracer;
+
+struct trace_buffer {
+	struct trace_array		*tr;
+	struct ring_buffer		*buffer;
+	struct trace_array_cpu __percpu	*data;
+	cycle_t				time_start;
+	int				cpu;
+};
+
 /*
  * The trace array - an array of per-CPU trace arrays. This is the
  * highest level data structure that individual tracers deal with.
  * They have on/off state as well:
  */
 struct trace_array {
-	struct ring_buffer	*buffer;
-	int			cpu;
+	struct list_head	list;
+	char			*name;
+	struct trace_buffer	trace_buffer;
+#ifdef CONFIG_TRACER_MAX_TRACE
+	/*
+	 * The max_buffer is used to snapshot the trace when a maximum
+	 * latency is reached, or when the user initiates a snapshot.
+	 * Some tracers will use this to store a maximum trace while
+	 * it continues examining live traces.
+	 *
+	 * The buffers for the max_buffer are set up the same as the trace_buffer
+	 * When a snapshot is taken, the buffer of the max_buffer is swapped
+	 * with the buffer of the trace_buffer and the buffers are reset for
+	 * the trace_buffer so the tracing can continue.
+	 */
+	struct trace_buffer	max_buffer;
+	bool			allocated_snapshot;
+#endif
 	int			buffer_disabled;
-	cycle_t			time_start;
+	struct trace_cpu	trace_cpu;	/* place holder */
+#ifdef CONFIG_FTRACE_SYSCALLS
+	int			sys_refcount_enter;
+	int			sys_refcount_exit;
+	DECLARE_BITMAP(enabled_enter_syscalls, NR_syscalls);
+	DECLARE_BITMAP(enabled_exit_syscalls, NR_syscalls);
+#endif
+	int			stop_count;
+	int			clock_id;
+	struct tracer		*current_trace;
+	unsigned int		flags;
+	raw_spinlock_t		start_lock;
+	struct dentry		*dir;
+	struct dentry		*options;
+	struct dentry		*percpu_dir;
+	struct dentry		*event_dir;
+	struct list_head	systems;
+	struct list_head	events;
 	struct task_struct	*waiter;
-	struct trace_array_cpu	*data[NR_CPUS];
+	int			ref;
 };
 
+enum {
+	TRACE_ARRAY_FL_GLOBAL	= (1 << 0)
+};
+
+extern struct list_head ftrace_trace_arrays;
+
+/*
+ * The global tracer (top) should be the first trace array added,
+ * but we check the flag anyway.
+ */
+static inline struct trace_array *top_trace_array(void)
+{
+	struct trace_array *tr;
+
+	tr = list_entry(ftrace_trace_arrays.prev,
+			typeof(*tr), list);
+	WARN_ON(!(tr->flags & TRACE_ARRAY_FL_GLOBAL));
+	return tr;
+}
+
 #define FTRACE_CMP_TYPE(var, type) \
 	__builtin_types_compatible_p(typeof(var), type *)
 
@@ -200,6 +278,7 @@ extern void __ftrace_bad_type(void);
 		IF_ASSIGN(var, ent, struct userstack_entry, TRACE_USER_STACK);\
 		IF_ASSIGN(var, ent, struct print_entry, TRACE_PRINT);	\
 		IF_ASSIGN(var, ent, struct bprint_entry, TRACE_BPRINT);	\
+		IF_ASSIGN(var, ent, struct bputs_entry, TRACE_BPUTS);	\
 		IF_ASSIGN(var, ent, struct trace_mmiotrace_rw,		\
 			  TRACE_MMIO_RW);				\
 		IF_ASSIGN(var, ent, struct trace_mmiotrace_map,		\
@@ -289,9 +368,10 @@ struct tracer {
 	struct tracer		*next;
 	struct tracer_flags	*flags;
 	bool			print_max;
-	bool			use_max_tr;
-	bool			allocated_snapshot;
 	bool			enabled;
+#ifdef CONFIG_TRACER_MAX_TRACE
+	bool			use_max_tr;
+#endif
 };
 
 
@@ -427,8 +507,6 @@ static __always_inline void trace_clear_recursion(int bit)
 	current->trace_recursion = val;
 }
 
-#define TRACE_PIPE_ALL_CPU	-1
-
 static inline struct ring_buffer_iter *
 trace_buffer_iter(struct trace_iterator *iter, int cpu)
 {
@@ -439,10 +517,10 @@ trace_buffer_iter(struct trace_iterator *iter, int cpu)
 
 int tracer_init(struct tracer *t, struct trace_array *tr);
 int tracing_is_enabled(void);
-void tracing_reset(struct trace_array *tr, int cpu);
-void tracing_reset_online_cpus(struct trace_array *tr);
+void tracing_reset(struct trace_buffer *buf, int cpu);
+void tracing_reset_online_cpus(struct trace_buffer *buf);
 void tracing_reset_current(int cpu);
-void tracing_reset_current_online_cpus(void);
+void tracing_reset_all_online_cpus(void);
 int tracing_open_generic(struct inode *inode, struct file *filp);
 struct dentry *trace_create_file(const char *name,
 				 umode_t mode,
@@ -450,6 +528,7 @@ struct dentry *trace_create_file(const char *name,
 				 void *data,
 				 const struct file_operations *fops);
 
+struct dentry *tracing_init_dentry_tr(struct trace_array *tr);
 struct dentry *tracing_init_dentry(void);
 
 struct ring_buffer_event;
@@ -583,7 +662,7 @@ extern int DYN_FTRACE_TEST_NAME(void);
 #define DYN_FTRACE_TEST_NAME2 trace_selftest_dynamic_test_func2
 extern int DYN_FTRACE_TEST_NAME2(void);
 
-extern int ring_buffer_expanded;
+extern bool ring_buffer_expanded;
 extern bool tracing_selftest_disabled;
 DECLARE_PER_CPU(int, ftrace_cpu_disabled);
 
@@ -619,6 +698,8 @@ trace_array_vprintk(struct trace_array *tr,
 		    unsigned long ip, const char *fmt, va_list args);
 int trace_array_printk(struct trace_array *tr,
 		       unsigned long ip, const char *fmt, ...);
+int trace_array_printk_buf(struct ring_buffer *buffer,
+			   unsigned long ip, const char *fmt, ...);
 void trace_printk_seq(struct trace_seq *s);
 enum print_line_t print_trace_line(struct trace_iterator *iter);
 
@@ -786,6 +867,7 @@ enum trace_iterator_flags {
 	TRACE_ITER_STOP_ON_FREE		= 0x400000,
 	TRACE_ITER_IRQ_INFO		= 0x800000,
 	TRACE_ITER_MARKERS		= 0x1000000,
+	TRACE_ITER_FUNCTION		= 0x2000000,
 };
 
 /*
@@ -832,8 +914,8 @@ enum {
 
 struct ftrace_event_field {
 	struct list_head	link;
-	char			*name;
-	char			*type;
+	const char		*name;
+	const char		*type;
 	int			filter_type;
 	int			offset;
 	int			size;
@@ -851,12 +933,19 @@ struct event_filter {
 struct event_subsystem {
 	struct list_head	list;
 	const char		*name;
-	struct dentry		*entry;
 	struct event_filter	*filter;
-	int			nr_events;
 	int			ref_count;
 };
 
+struct ftrace_subsystem_dir {
+	struct list_head		list;
+	struct event_subsystem		*subsystem;
+	struct trace_array		*tr;
+	struct dentry			*entry;
+	int				ref_count;
+	int				nr_events;
+};
+
 #define FILTER_PRED_INVALID	((unsigned short)-1)
 #define FILTER_PRED_IS_RIGHT	(1 << 15)
 #define FILTER_PRED_FOLD	(1 << 15)
@@ -906,22 +995,20 @@ struct filter_pred {
 	unsigned short		right;
 };
 
-extern struct list_head ftrace_common_fields;
-
 extern enum regex_type
 filter_parse_regex(char *buff, int len, char **search, int *not);
 extern void print_event_filter(struct ftrace_event_call *call,
 			       struct trace_seq *s);
 extern int apply_event_filter(struct ftrace_event_call *call,
 			      char *filter_string);
-extern int apply_subsystem_event_filter(struct event_subsystem *system,
+extern int apply_subsystem_event_filter(struct ftrace_subsystem_dir *dir,
 					char *filter_string);
 extern void print_subsystem_event_filter(struct event_subsystem *system,
 					 struct trace_seq *s);
 extern int filter_assign_type(const char *type);
 
-struct list_head *
-trace_get_fields(struct ftrace_event_call *event_call);
+struct ftrace_event_field *
+trace_find_event_field(struct ftrace_event_call *call, char *name);
 
 static inline int
 filter_check_discard(struct ftrace_event_call *call, void *rec,
@@ -938,6 +1025,8 @@ filter_check_discard(struct ftrace_event_call *call, void *rec,
 }
 
 extern void trace_event_enable_cmd_record(bool enable);
+extern int event_trace_add_tracer(struct dentry *parent, struct trace_array *tr);
+extern int event_trace_del_tracer(struct trace_array *tr);
 
 extern struct mutex event_mutex;
 extern struct list_head ftrace_events;
@@ -948,7 +1037,18 @@ extern const char *__stop___trace_bprintk_fmt[];
 void trace_printk_init_buffers(void);
 void trace_printk_start_comm(void);
 int trace_keep_overwrite(struct tracer *tracer, u32 mask, int set);
-int set_tracer_flag(unsigned int mask, int enabled);
+int set_tracer_flag(struct trace_array *tr, unsigned int mask, int enabled);
+
+/*
+ * Normal trace_printk() and friends allocates special buffers
+ * to do the manipulation, as well as saves the print formats
+ * into sections to display. But the trace infrastructure wants
+ * to use these without the added overhead at the price of being
+ * a bit slower (used mainly for warnings, where we don't care
+ * about performance). The internal_trace_puts() is for such
+ * a purpose.
+ */
+#define internal_trace_puts(str) __trace_puts(_THIS_IP_, str, strlen(str))
 
 #undef FTRACE_ENTRY
 #define FTRACE_ENTRY(call, struct_name, id, tstruct, print, filter)	\
diff --git a/kernel/trace/trace_branch.c b/kernel/trace/trace_branch.c
index 95e9684..d594da0 100644
--- a/kernel/trace/trace_branch.c
+++ b/kernel/trace/trace_branch.c
@@ -32,6 +32,7 @@ probe_likely_condition(struct ftrace_branch_data *f, int val, int expect)
 {
 	struct ftrace_event_call *call = &event_branch;
 	struct trace_array *tr = branch_tracer;
+	struct trace_array_cpu *data;
 	struct ring_buffer_event *event;
 	struct trace_branch *entry;
 	struct ring_buffer *buffer;
@@ -51,11 +52,12 @@ probe_likely_condition(struct ftrace_branch_data *f, int val, int expect)
 
 	local_irq_save(flags);
 	cpu = raw_smp_processor_id();
-	if (atomic_inc_return(&tr->data[cpu]->disabled) != 1)
+	data = per_cpu_ptr(tr->trace_buffer.data, cpu);
+	if (atomic_inc_return(&data->disabled) != 1)
 		goto out;
 
 	pc = preempt_count();
-	buffer = tr->buffer;
+	buffer = tr->trace_buffer.buffer;
 	event = trace_buffer_lock_reserve(buffer, TRACE_BRANCH,
 					  sizeof(*entry), flags, pc);
 	if (!event)
@@ -80,7 +82,7 @@ probe_likely_condition(struct ftrace_branch_data *f, int val, int expect)
 		__buffer_unlock_commit(buffer, event);
 
  out:
-	atomic_dec(&tr->data[cpu]->disabled);
+	atomic_dec(&data->disabled);
 	local_irq_restore(flags);
 }
 
diff --git a/kernel/trace/trace_clock.c b/kernel/trace/trace_clock.c
index aa8f5f4..26dc348 100644
--- a/kernel/trace/trace_clock.c
+++ b/kernel/trace/trace_clock.c
@@ -57,6 +57,16 @@ u64 notrace trace_clock(void)
 	return local_clock();
 }
 
+/*
+ * trace_jiffy_clock(): Simply use jiffies as a clock counter.
+ */
+u64 notrace trace_clock_jiffies(void)
+{
+	u64 jiffy = jiffies - INITIAL_JIFFIES;
+
+	/* Return nsecs */
+	return (u64)jiffies_to_usecs(jiffy) * 1000ULL;
+}
 
 /*
  * trace_clock_global(): special globally coherent trace clock
diff --git a/kernel/trace/trace_entries.h b/kernel/trace/trace_entries.h
index 4108e12..e2d027a 100644
--- a/kernel/trace/trace_entries.h
+++ b/kernel/trace/trace_entries.h
@@ -223,8 +223,8 @@ FTRACE_ENTRY(bprint, bprint_entry,
 		__dynamic_array(	u32,	buf	)
 	),
 
-	F_printk("%08lx fmt:%p",
-		 __entry->ip, __entry->fmt),
+	F_printk("%pf: %s",
+		 (void *)__entry->ip, __entry->fmt),
 
 	FILTER_OTHER
 );
@@ -238,8 +238,23 @@ FTRACE_ENTRY(print, print_entry,
 		__dynamic_array(	char,	buf	)
 	),
 
-	F_printk("%08lx %s",
-		 __entry->ip, __entry->buf),
+	F_printk("%pf: %s",
+		 (void *)__entry->ip, __entry->buf),
+
+	FILTER_OTHER
+);
+
+FTRACE_ENTRY(bputs, bputs_entry,
+
+	TRACE_BPUTS,
+
+	F_STRUCT(
+		__field(	unsigned long,	ip	)
+		__field(	const char *,	str	)
+	),
+
+	F_printk("%pf: %s",
+		 (void *)__entry->ip, __entry->str),
 
 	FILTER_OTHER
 );
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index 57e9b28..53582e9 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -34,9 +34,27 @@ char event_storage[EVENT_STORAGE_SIZE];
 EXPORT_SYMBOL_GPL(event_storage);
 
 LIST_HEAD(ftrace_events);
-LIST_HEAD(ftrace_common_fields);
+static LIST_HEAD(ftrace_common_fields);
 
-struct list_head *
+#define GFP_TRACE (GFP_KERNEL | __GFP_ZERO)
+
+static struct kmem_cache *field_cachep;
+static struct kmem_cache *file_cachep;
+
+/* Double loops, do not use break, only goto's work */
+#define do_for_each_event_file(tr, file)			\
+	list_for_each_entry(tr, &ftrace_trace_arrays, list) {	\
+		list_for_each_entry(file, &tr->events, list)
+
+#define do_for_each_event_file_safe(tr, file)			\
+	list_for_each_entry(tr, &ftrace_trace_arrays, list) {	\
+		struct ftrace_event_file *___n;				\
+		list_for_each_entry_safe(file, ___n, &tr->events, list)
+
+#define while_for_each_event_file()		\
+	}
+
+static struct list_head *
 trace_get_fields(struct ftrace_event_call *event_call)
 {
 	if (!event_call->class->get_fields)
@@ -44,23 +62,45 @@ trace_get_fields(struct ftrace_event_call *event_call)
 	return event_call->class->get_fields(event_call);
 }
 
+static struct ftrace_event_field *
+__find_event_field(struct list_head *head, char *name)
+{
+	struct ftrace_event_field *field;
+
+	list_for_each_entry(field, head, link) {
+		if (!strcmp(field->name, name))
+			return field;
+	}
+
+	return NULL;
+}
+
+struct ftrace_event_field *
+trace_find_event_field(struct ftrace_event_call *call, char *name)
+{
+	struct ftrace_event_field *field;
+	struct list_head *head;
+
+	field = __find_event_field(&ftrace_common_fields, name);
+	if (field)
+		return field;
+
+	head = trace_get_fields(call);
+	return __find_event_field(head, name);
+}
+
 static int __trace_define_field(struct list_head *head, const char *type,
 				const char *name, int offset, int size,
 				int is_signed, int filter_type)
 {
 	struct ftrace_event_field *field;
 
-	field = kzalloc(sizeof(*field), GFP_KERNEL);
+	field = kmem_cache_alloc(field_cachep, GFP_TRACE);
 	if (!field)
 		goto err;
 
-	field->name = kstrdup(name, GFP_KERNEL);
-	if (!field->name)
-		goto err;
-
-	field->type = kstrdup(type, GFP_KERNEL);
-	if (!field->type)
-		goto err;
+	field->name = name;
+	field->type = type;
 
 	if (filter_type == FILTER_OTHER)
 		field->filter_type = filter_assign_type(type);
@@ -76,9 +116,7 @@ static int __trace_define_field(struct list_head *head, const char *type,
 	return 0;
 
 err:
-	if (field)
-		kfree(field->name);
-	kfree(field);
+	kmem_cache_free(field_cachep, field);
 
 	return -ENOMEM;
 }
@@ -120,7 +158,7 @@ static int trace_define_common_fields(void)
 	return ret;
 }
 
-void trace_destroy_fields(struct ftrace_event_call *call)
+static void trace_destroy_fields(struct ftrace_event_call *call)
 {
 	struct ftrace_event_field *field, *next;
 	struct list_head *head;
@@ -128,9 +166,7 @@ void trace_destroy_fields(struct ftrace_event_call *call)
 	head = trace_get_fields(call);
 	list_for_each_entry_safe(field, next, head, link) {
 		list_del(&field->link);
-		kfree(field->type);
-		kfree(field->name);
-		kfree(field);
+		kmem_cache_free(field_cachep, field);
 	}
 }
 
@@ -149,15 +185,17 @@ EXPORT_SYMBOL_GPL(trace_event_raw_init);
 int ftrace_event_reg(struct ftrace_event_call *call,
 		     enum trace_reg type, void *data)
 {
+	struct ftrace_event_file *file = data;
+
 	switch (type) {
 	case TRACE_REG_REGISTER:
 		return tracepoint_probe_register(call->name,
 						 call->class->probe,
-						 call);
+						 file);
 	case TRACE_REG_UNREGISTER:
 		tracepoint_probe_unregister(call->name,
 					    call->class->probe,
-					    call);
+					    file);
 		return 0;
 
 #ifdef CONFIG_PERF_EVENTS
@@ -183,54 +221,100 @@ EXPORT_SYMBOL_GPL(ftrace_event_reg);
 
 void trace_event_enable_cmd_record(bool enable)
 {
-	struct ftrace_event_call *call;
+	struct ftrace_event_file *file;
+	struct trace_array *tr;
 
 	mutex_lock(&event_mutex);
-	list_for_each_entry(call, &ftrace_events, list) {
-		if (!(call->flags & TRACE_EVENT_FL_ENABLED))
+	do_for_each_event_file(tr, file) {
+
+		if (!(file->flags & FTRACE_EVENT_FL_ENABLED))
 			continue;
 
 		if (enable) {
 			tracing_start_cmdline_record();
-			call->flags |= TRACE_EVENT_FL_RECORDED_CMD;
+			set_bit(FTRACE_EVENT_FL_RECORDED_CMD_BIT, &file->flags);
 		} else {
 			tracing_stop_cmdline_record();
-			call->flags &= ~TRACE_EVENT_FL_RECORDED_CMD;
+			clear_bit(FTRACE_EVENT_FL_RECORDED_CMD_BIT, &file->flags);
 		}
-	}
+	} while_for_each_event_file();
 	mutex_unlock(&event_mutex);
 }
 
-static int ftrace_event_enable_disable(struct ftrace_event_call *call,
-					int enable)
+static int __ftrace_event_enable_disable(struct ftrace_event_file *file,
+					 int enable, int soft_disable)
 {
+	struct ftrace_event_call *call = file->event_call;
 	int ret = 0;
+	int disable;
 
 	switch (enable) {
 	case 0:
-		if (call->flags & TRACE_EVENT_FL_ENABLED) {
-			call->flags &= ~TRACE_EVENT_FL_ENABLED;
-			if (call->flags & TRACE_EVENT_FL_RECORDED_CMD) {
+		/*
+		 * When soft_disable is set and enable is cleared, we want
+		 * to clear the SOFT_DISABLED flag but leave the event in the
+		 * state that it was. That is, if the event was enabled and
+		 * SOFT_DISABLED isn't set, then do nothing. But if SOFT_DISABLED
+		 * is set we do not want the event to be enabled before we
+		 * clear the bit.
+		 *
+		 * When soft_disable is not set but the SOFT_MODE flag is,
+		 * we do nothing. Do not disable the tracepoint, otherwise
+		 * "soft enable"s (clearing the SOFT_DISABLED bit) wont work.
+		 */
+		if (soft_disable) {
+			disable = file->flags & FTRACE_EVENT_FL_SOFT_DISABLED;
+			clear_bit(FTRACE_EVENT_FL_SOFT_MODE_BIT, &file->flags);
+		} else
+			disable = !(file->flags & FTRACE_EVENT_FL_SOFT_MODE);
+
+		if (disable && (file->flags & FTRACE_EVENT_FL_ENABLED)) {
+			clear_bit(FTRACE_EVENT_FL_ENABLED_BIT, &file->flags);
+			if (file->flags & FTRACE_EVENT_FL_RECORDED_CMD) {
 				tracing_stop_cmdline_record();
-				call->flags &= ~TRACE_EVENT_FL_RECORDED_CMD;
+				clear_bit(FTRACE_EVENT_FL_RECORDED_CMD_BIT, &file->flags);
 			}
-			call->class->reg(call, TRACE_REG_UNREGISTER, NULL);
+			call->class->reg(call, TRACE_REG_UNREGISTER, file);
 		}
+		/* If in SOFT_MODE, just set the SOFT_DISABLE_BIT */
+		if (file->flags & FTRACE_EVENT_FL_SOFT_MODE)
+			set_bit(FTRACE_EVENT_FL_SOFT_DISABLED_BIT, &file->flags);
 		break;
 	case 1:
-		if (!(call->flags & TRACE_EVENT_FL_ENABLED)) {
+		/*
+		 * When soft_disable is set and enable is set, we want to
+		 * register the tracepoint for the event, but leave the event
+		 * as is. That means, if the event was already enabled, we do
+		 * nothing (but set SOFT_MODE). If the event is disabled, we
+		 * set SOFT_DISABLED before enabling the event tracepoint, so
+		 * it still seems to be disabled.
+		 */
+		if (!soft_disable)
+			clear_bit(FTRACE_EVENT_FL_SOFT_DISABLED_BIT, &file->flags);
+		else
+			set_bit(FTRACE_EVENT_FL_SOFT_MODE_BIT, &file->flags);
+
+		if (!(file->flags & FTRACE_EVENT_FL_ENABLED)) {
+
+			/* Keep the event disabled, when going to SOFT_MODE. */
+			if (soft_disable)
+				set_bit(FTRACE_EVENT_FL_SOFT_DISABLED_BIT, &file->flags);
+
 			if (trace_flags & TRACE_ITER_RECORD_CMD) {
 				tracing_start_cmdline_record();
-				call->flags |= TRACE_EVENT_FL_RECORDED_CMD;
+				set_bit(FTRACE_EVENT_FL_RECORDED_CMD_BIT, &file->flags);
 			}
-			ret = call->class->reg(call, TRACE_REG_REGISTER, NULL);
+			ret = call->class->reg(call, TRACE_REG_REGISTER, file);
 			if (ret) {
 				tracing_stop_cmdline_record();
 				pr_info("event trace: Could not enable event "
 					"%s\n", call->name);
 				break;
 			}
-			call->flags |= TRACE_EVENT_FL_ENABLED;
+			set_bit(FTRACE_EVENT_FL_ENABLED_BIT, &file->flags);
+
+			/* WAS_ENABLED gets set but never cleared. */
+			call->flags |= TRACE_EVENT_FL_WAS_ENABLED;
 		}
 		break;
 	}
@@ -238,13 +322,19 @@ static int ftrace_event_enable_disable(struct ftrace_event_call *call,
 	return ret;
 }
 
-static void ftrace_clear_events(void)
+static int ftrace_event_enable_disable(struct ftrace_event_file *file,
+				       int enable)
 {
-	struct ftrace_event_call *call;
+	return __ftrace_event_enable_disable(file, enable, 0);
+}
+
+static void ftrace_clear_events(struct trace_array *tr)
+{
+	struct ftrace_event_file *file;
 
 	mutex_lock(&event_mutex);
-	list_for_each_entry(call, &ftrace_events, list) {
-		ftrace_event_enable_disable(call, 0);
+	list_for_each_entry(file, &tr->events, list) {
+		ftrace_event_enable_disable(file, 0);
 	}
 	mutex_unlock(&event_mutex);
 }
@@ -257,11 +347,12 @@ static void __put_system(struct event_subsystem *system)
 	if (--system->ref_count)
 		return;
 
+	list_del(&system->list);
+
 	if (filter) {
 		kfree(filter->filter_string);
 		kfree(filter);
 	}
-	kfree(system->name);
 	kfree(system);
 }
 
@@ -271,24 +362,45 @@ static void __get_system(struct event_subsystem *system)
 	system->ref_count++;
 }
 
-static void put_system(struct event_subsystem *system)
+static void __get_system_dir(struct ftrace_subsystem_dir *dir)
+{
+	WARN_ON_ONCE(dir->ref_count == 0);
+	dir->ref_count++;
+	__get_system(dir->subsystem);
+}
+
+static void __put_system_dir(struct ftrace_subsystem_dir *dir)
+{
+	WARN_ON_ONCE(dir->ref_count == 0);
+	/* If the subsystem is about to be freed, the dir must be too */
+	WARN_ON_ONCE(dir->subsystem->ref_count == 1 && dir->ref_count != 1);
+
+	__put_system(dir->subsystem);
+	if (!--dir->ref_count)
+		kfree(dir);
+}
+
+static void put_system(struct ftrace_subsystem_dir *dir)
 {
 	mutex_lock(&event_mutex);
-	__put_system(system);
+	__put_system_dir(dir);
 	mutex_unlock(&event_mutex);
 }
 
 /*
  * __ftrace_set_clr_event(NULL, NULL, NULL, set) will set/unset all events.
  */
-static int __ftrace_set_clr_event(const char *match, const char *sub,
-				  const char *event, int set)
+static int __ftrace_set_clr_event(struct trace_array *tr, const char *match,
+				  const char *sub, const char *event, int set)
 {
+	struct ftrace_event_file *file;
 	struct ftrace_event_call *call;
 	int ret = -EINVAL;
 
 	mutex_lock(&event_mutex);
-	list_for_each_entry(call, &ftrace_events, list) {
+	list_for_each_entry(file, &tr->events, list) {
+
+		call = file->event_call;
 
 		if (!call->name || !call->class || !call->class->reg)
 			continue;
@@ -307,7 +419,7 @@ static int __ftrace_set_clr_event(const char *match, const char *sub,
 		if (event && strcmp(event, call->name) != 0)
 			continue;
 
-		ftrace_event_enable_disable(call, set);
+		ftrace_event_enable_disable(file, set);
 
 		ret = 0;
 	}
@@ -316,7 +428,7 @@ static int __ftrace_set_clr_event(const char *match, const char *sub,
 	return ret;
 }
 
-static int ftrace_set_clr_event(char *buf, int set)
+static int ftrace_set_clr_event(struct trace_array *tr, char *buf, int set)
 {
 	char *event = NULL, *sub = NULL, *match;
 
@@ -344,7 +456,7 @@ static int ftrace_set_clr_event(char *buf, int set)
 			event = NULL;
 	}
 
-	return __ftrace_set_clr_event(match, sub, event, set);
+	return __ftrace_set_clr_event(tr, match, sub, event, set);
 }
 
 /**
@@ -361,7 +473,9 @@ static int ftrace_set_clr_event(char *buf, int set)
  */
 int trace_set_clr_event(const char *system, const char *event, int set)
 {
-	return __ftrace_set_clr_event(NULL, system, event, set);
+	struct trace_array *tr = top_trace_array();
+
+	return __ftrace_set_clr_event(tr, NULL, system, event, set);
 }
 EXPORT_SYMBOL_GPL(trace_set_clr_event);
 
@@ -373,6 +487,8 @@ ftrace_event_write(struct file *file, const char __user *ubuf,
 		   size_t cnt, loff_t *ppos)
 {
 	struct trace_parser parser;
+	struct seq_file *m = file->private_data;
+	struct trace_array *tr = m->private;
 	ssize_t read, ret;
 
 	if (!cnt)
@@ -395,7 +511,7 @@ ftrace_event_write(struct file *file, const char __user *ubuf,
 
 		parser.buffer[parser.idx] = 0;
 
-		ret = ftrace_set_clr_event(parser.buffer + !set, set);
+		ret = ftrace_set_clr_event(tr, parser.buffer + !set, set);
 		if (ret)
 			goto out_put;
 	}
@@ -411,17 +527,20 @@ ftrace_event_write(struct file *file, const char __user *ubuf,
 static void *
 t_next(struct seq_file *m, void *v, loff_t *pos)
 {
-	struct ftrace_event_call *call = v;
+	struct ftrace_event_file *file = v;
+	struct ftrace_event_call *call;
+	struct trace_array *tr = m->private;
 
 	(*pos)++;
 
-	list_for_each_entry_continue(call, &ftrace_events, list) {
+	list_for_each_entry_continue(file, &tr->events, list) {
+		call = file->event_call;
 		/*
 		 * The ftrace subsystem is for showing formats only.
 		 * They can not be enabled or disabled via the event files.
 		 */
 		if (call->class && call->class->reg)
-			return call;
+			return file;
 	}
 
 	return NULL;
@@ -429,30 +548,32 @@ t_next(struct seq_file *m, void *v, loff_t *pos)
 
 static void *t_start(struct seq_file *m, loff_t *pos)
 {
-	struct ftrace_event_call *call;
+	struct ftrace_event_file *file;
+	struct trace_array *tr = m->private;
 	loff_t l;
 
 	mutex_lock(&event_mutex);
 
-	call = list_entry(&ftrace_events, struct ftrace_event_call, list);
+	file = list_entry(&tr->events, struct ftrace_event_file, list);
 	for (l = 0; l <= *pos; ) {
-		call = t_next(m, call, &l);
-		if (!call)
+		file = t_next(m, file, &l);
+		if (!file)
 			break;
 	}
-	return call;
+	return file;
 }
 
 static void *
 s_next(struct seq_file *m, void *v, loff_t *pos)
 {
-	struct ftrace_event_call *call = v;
+	struct ftrace_event_file *file = v;
+	struct trace_array *tr = m->private;
 
 	(*pos)++;
 
-	list_for_each_entry_continue(call, &ftrace_events, list) {
-		if (call->flags & TRACE_EVENT_FL_ENABLED)
-			return call;
+	list_for_each_entry_continue(file, &tr->events, list) {
+		if (file->flags & FTRACE_EVENT_FL_ENABLED)
+			return file;
 	}
 
 	return NULL;
@@ -460,23 +581,25 @@ s_next(struct seq_file *m, void *v, loff_t *pos)
 
 static void *s_start(struct seq_file *m, loff_t *pos)
 {
-	struct ftrace_event_call *call;
+	struct ftrace_event_file *file;
+	struct trace_array *tr = m->private;
 	loff_t l;
 
 	mutex_lock(&event_mutex);
 
-	call = list_entry(&ftrace_events, struct ftrace_event_call, list);
+	file = list_entry(&tr->events, struct ftrace_event_file, list);
 	for (l = 0; l <= *pos; ) {
-		call = s_next(m, call, &l);
-		if (!call)
+		file = s_next(m, file, &l);
+		if (!file)
 			break;
 	}
-	return call;
+	return file;
 }
 
 static int t_show(struct seq_file *m, void *v)
 {
-	struct ftrace_event_call *call = v;
+	struct ftrace_event_file *file = v;
+	struct ftrace_event_call *call = file->event_call;
 
 	if (strcmp(call->class->system, TRACE_SYSTEM) != 0)
 		seq_printf(m, "%s:", call->class->system);
@@ -494,25 +617,31 @@ static ssize_t
 event_enable_read(struct file *filp, char __user *ubuf, size_t cnt,
 		  loff_t *ppos)
 {
-	struct ftrace_event_call *call = filp->private_data;
+	struct ftrace_event_file *file = filp->private_data;
 	char *buf;
 
-	if (call->flags & TRACE_EVENT_FL_ENABLED)
-		buf = "1\n";
-	else
+	if (file->flags & FTRACE_EVENT_FL_ENABLED) {
+		if (file->flags & FTRACE_EVENT_FL_SOFT_DISABLED)
+			buf = "0*\n";
+		else
+			buf = "1\n";
+	} else
 		buf = "0\n";
 
-	return simple_read_from_buffer(ubuf, cnt, ppos, buf, 2);
+	return simple_read_from_buffer(ubuf, cnt, ppos, buf, strlen(buf));
 }
 
 static ssize_t
 event_enable_write(struct file *filp, const char __user *ubuf, size_t cnt,
 		   loff_t *ppos)
 {
-	struct ftrace_event_call *call = filp->private_data;
+	struct ftrace_event_file *file = filp->private_data;
 	unsigned long val;
 	int ret;
 
+	if (!file)
+		return -EINVAL;
+
 	ret = kstrtoul_from_user(ubuf, cnt, 10, &val);
 	if (ret)
 		return ret;
@@ -525,7 +654,7 @@ event_enable_write(struct file *filp, const char __user *ubuf, size_t cnt,
 	case 0:
 	case 1:
 		mutex_lock(&event_mutex);
-		ret = ftrace_event_enable_disable(call, val);
+		ret = ftrace_event_enable_disable(file, val);
 		mutex_unlock(&event_mutex);
 		break;
 
@@ -543,14 +672,18 @@ system_enable_read(struct file *filp, char __user *ubuf, size_t cnt,
 		   loff_t *ppos)
 {
 	const char set_to_char[4] = { '?', '0', '1', 'X' };
-	struct event_subsystem *system = filp->private_data;
+	struct ftrace_subsystem_dir *dir = filp->private_data;
+	struct event_subsystem *system = dir->subsystem;
 	struct ftrace_event_call *call;
+	struct ftrace_event_file *file;
+	struct trace_array *tr = dir->tr;
 	char buf[2];
 	int set = 0;
 	int ret;
 
 	mutex_lock(&event_mutex);
-	list_for_each_entry(call, &ftrace_events, list) {
+	list_for_each_entry(file, &tr->events, list) {
+		call = file->event_call;
 		if (!call->name || !call->class || !call->class->reg)
 			continue;
 
@@ -562,7 +695,7 @@ system_enable_read(struct file *filp, char __user *ubuf, size_t cnt,
 		 * or if all events or cleared, or if we have
 		 * a mixture.
 		 */
-		set |= (1 << !!(call->flags & TRACE_EVENT_FL_ENABLED));
+		set |= (1 << !!(file->flags & FTRACE_EVENT_FL_ENABLED));
 
 		/*
 		 * If we have a mixture, no need to look further.
@@ -584,7 +717,8 @@ static ssize_t
 system_enable_write(struct file *filp, const char __user *ubuf, size_t cnt,
 		    loff_t *ppos)
 {
-	struct event_subsystem *system = filp->private_data;
+	struct ftrace_subsystem_dir *dir = filp->private_data;
+	struct event_subsystem *system = dir->subsystem;
 	const char *name = NULL;
 	unsigned long val;
 	ssize_t ret;
@@ -607,7 +741,7 @@ system_enable_write(struct file *filp, const char __user *ubuf, size_t cnt,
 	if (system)
 		name = system->name;
 
-	ret = __ftrace_set_clr_event(NULL, name, NULL, val);
+	ret = __ftrace_set_clr_event(dir->tr, NULL, name, NULL, val);
 	if (ret)
 		goto out;
 
@@ -845,43 +979,75 @@ static LIST_HEAD(event_subsystems);
 static int subsystem_open(struct inode *inode, struct file *filp)
 {
 	struct event_subsystem *system = NULL;
+	struct ftrace_subsystem_dir *dir = NULL; /* Initialize for gcc */
+	struct trace_array *tr;
 	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;
+	list_for_each_entry(tr, &ftrace_trace_arrays, list) {
+		list_for_each_entry(dir, &tr->systems, list) {
+			if (dir == inode->i_private) {
+				/* Don't open systems with no events */
+				if (dir->nr_events) {
+					__get_system_dir(dir);
+					system = dir->subsystem;
+				}
+				goto exit_loop;
 			}
-			__get_system(system);
-			break;
 		}
 	}
+ exit_loop:
 	mutex_unlock(&event_mutex);
 
-	if (system != inode->i_private)
+	if (!system)
 		return -ENODEV;
 
- skip_search:
+	/* Some versions of gcc think dir can be uninitialized here */
+	WARN_ON(!dir);
+
+	ret = tracing_open_generic(inode, filp);
+	if (ret < 0)
+		put_system(dir);
+
+	return ret;
+}
+
+static int system_tr_open(struct inode *inode, struct file *filp)
+{
+	struct ftrace_subsystem_dir *dir;
+	struct trace_array *tr = inode->i_private;
+	int ret;
+
+	/* Make a temporary dir that has no system but points to tr */
+	dir = kzalloc(sizeof(*dir), GFP_KERNEL);
+	if (!dir)
+		return -ENOMEM;
+
+	dir->tr = tr;
+
 	ret = tracing_open_generic(inode, filp);
-	if (ret < 0 && system)
-		put_system(system);
+	if (ret < 0)
+		kfree(dir);
+
+	filp->private_data = dir;
 
 	return ret;
 }
 
 static int subsystem_release(struct inode *inode, struct file *file)
 {
-	struct event_subsystem *system = inode->i_private;
+	struct ftrace_subsystem_dir *dir = file->private_data;
 
-	if (system)
-		put_system(system);
+	/*
+	 * If dir->subsystem is NULL, then this is a temporary
+	 * descriptor that was made for a trace_array to enable
+	 * all subsystems.
+	 */
+	if (dir->subsystem)
+		put_system(dir);
+	else
+		kfree(dir);
 
 	return 0;
 }
@@ -890,7 +1056,8 @@ static ssize_t
 subsystem_filter_read(struct file *filp, char __user *ubuf, size_t cnt,
 		      loff_t *ppos)
 {
-	struct event_subsystem *system = filp->private_data;
+	struct ftrace_subsystem_dir *dir = filp->private_data;
+	struct event_subsystem *system = dir->subsystem;
 	struct trace_seq *s;
 	int r;
 
@@ -915,7 +1082,7 @@ static ssize_t
 subsystem_filter_write(struct file *filp, const char __user *ubuf, size_t cnt,
 		       loff_t *ppos)
 {
-	struct event_subsystem *system = filp->private_data;
+	struct ftrace_subsystem_dir *dir = filp->private_data;
 	char *buf;
 	int err;
 
@@ -932,7 +1099,7 @@ subsystem_filter_write(struct file *filp, const char __user *ubuf, size_t cnt,
 	}
 	buf[cnt] = '\0';
 
-	err = apply_subsystem_event_filter(system, buf);
+	err = apply_subsystem_event_filter(dir, buf);
 	free_page((unsigned long) buf);
 	if (err < 0)
 		return err;
@@ -1041,30 +1208,35 @@ static const struct file_operations ftrace_system_enable_fops = {
 	.release = subsystem_release,
 };
 
+static const struct file_operations ftrace_tr_enable_fops = {
+	.open = system_tr_open,
+	.read = system_enable_read,
+	.write = system_enable_write,
+	.llseek = default_llseek,
+	.release = subsystem_release,
+};
+
 static const struct file_operations ftrace_show_header_fops = {
 	.open = tracing_open_generic,
 	.read = show_header,
 	.llseek = default_llseek,
 };
 
-static struct dentry *event_trace_events_dir(void)
+static int
+ftrace_event_open(struct inode *inode, struct file *file,
+		  const struct seq_operations *seq_ops)
 {
-	static struct dentry *d_tracer;
-	static struct dentry *d_events;
-
-	if (d_events)
-		return d_events;
-
-	d_tracer = tracing_init_dentry();
-	if (!d_tracer)
-		return NULL;
+	struct seq_file *m;
+	int ret;
 
-	d_events = debugfs_create_dir("events", d_tracer);
-	if (!d_events)
-		pr_warning("Could not create debugfs "
-			   "'events' directory\n");
+	ret = seq_open(file, seq_ops);
+	if (ret < 0)
+		return ret;
+	m = file->private_data;
+	/* copy tr over to seq ops */
+	m->private = inode->i_private;
 
-	return d_events;
+	return ret;
 }
 
 static int
@@ -1072,117 +1244,165 @@ ftrace_event_avail_open(struct inode *inode, struct file *file)
 {
 	const struct seq_operations *seq_ops = &show_event_seq_ops;
 
-	return seq_open(file, seq_ops);
+	return ftrace_event_open(inode, file, seq_ops);
 }
 
 static int
 ftrace_event_set_open(struct inode *inode, struct file *file)
 {
 	const struct seq_operations *seq_ops = &show_set_event_seq_ops;
+	struct trace_array *tr = inode->i_private;
 
 	if ((file->f_mode & FMODE_WRITE) &&
 	    (file->f_flags & O_TRUNC))
-		ftrace_clear_events();
+		ftrace_clear_events(tr);
+
+	return ftrace_event_open(inode, file, seq_ops);
+}
+
+static struct event_subsystem *
+create_new_subsystem(const char *name)
+{
+	struct event_subsystem *system;
+
+	/* need to create new entry */
+	system = kmalloc(sizeof(*system), GFP_KERNEL);
+	if (!system)
+		return NULL;
+
+	system->ref_count = 1;
+	system->name = name;
+
+	system->filter = NULL;
+
+	system->filter = kzalloc(sizeof(struct event_filter), GFP_KERNEL);
+	if (!system->filter)
+		goto out_free;
+
+	list_add(&system->list, &event_subsystems);
+
+	return system;
 
-	return seq_open(file, seq_ops);
+ out_free:
+	kfree(system);
+	return NULL;
 }
 
 static struct dentry *
-event_subsystem_dir(const char *name, struct dentry *d_events)
+event_subsystem_dir(struct trace_array *tr, const char *name,
+		    struct ftrace_event_file *file, struct dentry *parent)
 {
+	struct ftrace_subsystem_dir *dir;
 	struct event_subsystem *system;
 	struct dentry *entry;
 
 	/* First see if we did not already create this dir */
-	list_for_each_entry(system, &event_subsystems, list) {
+	list_for_each_entry(dir, &tr->systems, list) {
+		system = dir->subsystem;
 		if (strcmp(system->name, name) == 0) {
-			system->nr_events++;
-			return system->entry;
+			dir->nr_events++;
+			file->system = dir;
+			return dir->entry;
 		}
 	}
 
-	/* need to create new entry */
-	system = kmalloc(sizeof(*system), GFP_KERNEL);
-	if (!system) {
-		pr_warning("No memory to create event subsystem %s\n",
-			   name);
-		return d_events;
+	/* Now see if the system itself exists. */
+	list_for_each_entry(system, &event_subsystems, list) {
+		if (strcmp(system->name, name) == 0)
+			break;
 	}
+	/* Reset system variable when not found */
+	if (&system->list == &event_subsystems)
+		system = NULL;
 
-	system->entry = debugfs_create_dir(name, d_events);
-	if (!system->entry) {
-		pr_warning("Could not create event subsystem %s\n",
-			   name);
-		kfree(system);
-		return d_events;
-	}
+	dir = kmalloc(sizeof(*dir), GFP_KERNEL);
+	if (!dir)
+		goto out_fail;
 
-	system->nr_events = 1;
-	system->ref_count = 1;
-	system->name = kstrdup(name, GFP_KERNEL);
-	if (!system->name) {
-		debugfs_remove(system->entry);
-		kfree(system);
-		return d_events;
+	if (!system) {
+		system = create_new_subsystem(name);
+		if (!system)
+			goto out_free;
+	} else
+		__get_system(system);
+
+	dir->entry = debugfs_create_dir(name, parent);
+	if (!dir->entry) {
+		pr_warning("Failed to create system directory %s\n", name);
+		__put_system(system);
+		goto out_free;
 	}
 
-	list_add(&system->list, &event_subsystems);
-
-	system->filter = NULL;
-
-	system->filter = kzalloc(sizeof(struct event_filter), GFP_KERNEL);
-	if (!system->filter) {
-		pr_warning("Could not allocate filter for subsystem "
-			   "'%s'\n", name);
-		return system->entry;
-	}
+	dir->tr = tr;
+	dir->ref_count = 1;
+	dir->nr_events = 1;
+	dir->subsystem = system;
+	file->system = dir;
 
-	entry = debugfs_create_file("filter", 0644, system->entry, system,
+	entry = debugfs_create_file("filter", 0644, dir->entry, dir,
 				    &ftrace_subsystem_filter_fops);
 	if (!entry) {
 		kfree(system->filter);
 		system->filter = NULL;
-		pr_warning("Could not create debugfs "
-			   "'%s/filter' entry\n", name);
+		pr_warning("Could not create debugfs '%s/filter' entry\n", name);
 	}
 
-	trace_create_file("enable", 0644, system->entry, system,
+	trace_create_file("enable", 0644, dir->entry, dir,
 			  &ftrace_system_enable_fops);
 
-	return system->entry;
+	list_add(&dir->list, &tr->systems);
+
+	return dir->entry;
+
+ out_free:
+	kfree(dir);
+ out_fail:
+	/* Only print this message if failed on memory allocation */
+	if (!dir || !system)
+		pr_warning("No memory to create event subsystem %s\n",
+			   name);
+	return NULL;
 }
 
 static int
-event_create_dir(struct ftrace_event_call *call, struct dentry *d_events,
+event_create_dir(struct dentry *parent,
+		 struct ftrace_event_file *file,
 		 const struct file_operations *id,
 		 const struct file_operations *enable,
 		 const struct file_operations *filter,
 		 const struct file_operations *format)
 {
+	struct ftrace_event_call *call = file->event_call;
+	struct trace_array *tr = file->tr;
 	struct list_head *head;
+	struct dentry *d_events;
 	int ret;
 
 	/*
 	 * If the trace point header did not define TRACE_SYSTEM
 	 * then the system would be called "TRACE_SYSTEM".
 	 */
-	if (strcmp(call->class->system, TRACE_SYSTEM) != 0)
-		d_events = event_subsystem_dir(call->class->system, d_events);
-
-	call->dir = debugfs_create_dir(call->name, d_events);
-	if (!call->dir) {
-		pr_warning("Could not create debugfs "
-			   "'%s' directory\n", call->name);
+	if (strcmp(call->class->system, TRACE_SYSTEM) != 0) {
+		d_events = event_subsystem_dir(tr, call->class->system, file, parent);
+		if (!d_events)
+			return -ENOMEM;
+	} else
+		d_events = parent;
+
+	file->dir = debugfs_create_dir(call->name, d_events);
+	if (!file->dir) {
+		pr_warning("Could not create debugfs '%s' directory\n",
+			   call->name);
 		return -1;
 	}
 
 	if (call->class->reg && !(call->flags & TRACE_EVENT_FL_IGNORE_ENABLE))
-		trace_create_file("enable", 0644, call->dir, call,
+		trace_create_file("enable", 0644, file->dir, file,
 				  enable);
 
 #ifdef CONFIG_PERF_EVENTS
 	if (call->event.type && call->class->reg)
-		trace_create_file("id", 0444, call->dir, call,
+		trace_create_file("id", 0444, file->dir, call,
 		 		  id);
 #endif
 
@@ -1196,23 +1416,76 @@ event_create_dir(struct ftrace_event_call *call, struct dentry *d_events,
 		if (ret < 0) {
 			pr_warning("Could not initialize trace point"
 				   " events/%s\n", call->name);
-			return ret;
+			return -1;
 		}
 	}
-	trace_create_file("filter", 0644, call->dir, call,
+	trace_create_file("filter", 0644, file->dir, call,
 			  filter);
 
-	trace_create_file("format", 0444, call->dir, call,
+	trace_create_file("format", 0444, file->dir, call,
 			  format);
 
 	return 0;
 }
 
+static void remove_subsystem(struct ftrace_subsystem_dir *dir)
+{
+	if (!dir)
+		return;
+
+	if (!--dir->nr_events) {
+		debugfs_remove_recursive(dir->entry);
+		list_del(&dir->list);
+		__put_system_dir(dir);
+	}
+}
+
+static void remove_event_from_tracers(struct ftrace_event_call *call)
+{
+	struct ftrace_event_file *file;
+	struct trace_array *tr;
+
+	do_for_each_event_file_safe(tr, file) {
+
+		if (file->event_call != call)
+			continue;
+
+		list_del(&file->list);
+		debugfs_remove_recursive(file->dir);
+		remove_subsystem(file->system);
+		kmem_cache_free(file_cachep, file);
+
+		/*
+		 * The do_for_each_event_file_safe() is
+		 * a double loop. After finding the call for this
+		 * trace_array, we use break to jump to the next
+		 * trace_array.
+		 */
+		break;
+	} while_for_each_event_file();
+}
+
 static void event_remove(struct ftrace_event_call *call)
 {
-	ftrace_event_enable_disable(call, 0);
+	struct trace_array *tr;
+	struct ftrace_event_file *file;
+
+	do_for_each_event_file(tr, file) {
+		if (file->event_call != call)
+			continue;
+		ftrace_event_enable_disable(file, 0);
+		/*
+		 * The do_for_each_event_file() is
+		 * a double loop. After finding the call for this
+		 * trace_array, we use break to jump to the next
+		 * trace_array.
+		 */
+		break;
+	} while_for_each_event_file();
+
 	if (call->event.funcs)
 		__unregister_ftrace_event(&call->event);
+	remove_event_from_tracers(call);
 	list_del(&call->list);
 }
 
@@ -1234,82 +1507,99 @@ static int event_init(struct ftrace_event_call *call)
 }
 
 static int
-__trace_add_event_call(struct ftrace_event_call *call, struct module *mod,
-		       const struct file_operations *id,
-		       const struct file_operations *enable,
-		       const struct file_operations *filter,
-		       const struct file_operations *format)
+__register_event(struct ftrace_event_call *call, struct module *mod)
 {
-	struct dentry *d_events;
 	int ret;
 
 	ret = event_init(call);
 	if (ret < 0)
 		return ret;
 
-	d_events = event_trace_events_dir();
-	if (!d_events)
-		return -ENOENT;
-
-	ret = event_create_dir(call, d_events, id, enable, filter, format);
-	if (!ret)
-		list_add(&call->list, &ftrace_events);
+	list_add(&call->list, &ftrace_events);
 	call->mod = mod;
 
-	return ret;
+	return 0;
+}
+
+/* Add an event to a trace directory */
+static int
+__trace_add_new_event(struct ftrace_event_call *call,
+		      struct trace_array *tr,
+		      const struct file_operations *id,
+		      const struct file_operations *enable,
+		      const struct file_operations *filter,
+		      const struct file_operations *format)
+{
+	struct ftrace_event_file *file;
+
+	file = kmem_cache_alloc(file_cachep, GFP_TRACE);
+	if (!file)
+		return -ENOMEM;
+
+	file->event_call = call;
+	file->tr = tr;
+	list_add(&file->list, &tr->events);
+
+	return event_create_dir(tr->event_dir, file, id, enable, filter, format);
+}
+
+/*
+ * Just create a decriptor for early init. A descriptor is required
+ * for enabling events at boot. We want to enable events before
+ * the filesystem is initialized.
+ */
+static __init int
+__trace_early_add_new_event(struct ftrace_event_call *call,
+			    struct trace_array *tr)
+{
+	struct ftrace_event_file *file;
+
+	file = kmem_cache_alloc(file_cachep, GFP_TRACE);
+	if (!file)
+		return -ENOMEM;
+
+	file->event_call = call;
+	file->tr = tr;
+	list_add(&file->list, &tr->events);
+
+	return 0;
 }
 
+struct ftrace_module_file_ops;
+static void __add_event_to_tracers(struct ftrace_event_call *call,
+				   struct ftrace_module_file_ops *file_ops);
+
 /* Add an additional event_call dynamically */
 int trace_add_event_call(struct ftrace_event_call *call)
 {
 	int ret;
 	mutex_lock(&event_mutex);
-	ret = __trace_add_event_call(call, NULL, &ftrace_event_id_fops,
-				     &ftrace_enable_fops,
-				     &ftrace_event_filter_fops,
-				     &ftrace_event_format_fops);
-	mutex_unlock(&event_mutex);
-	return ret;
-}
 
-static void remove_subsystem_dir(const char *name)
-{
-	struct event_subsystem *system;
-
-	if (strcmp(name, TRACE_SYSTEM) == 0)
-		return;
+	ret = __register_event(call, NULL);
+	if (ret >= 0)
+		__add_event_to_tracers(call, NULL);
 
-	list_for_each_entry(system, &event_subsystems, list) {
-		if (strcmp(system->name, name) == 0) {
-			if (!--system->nr_events) {
-				debugfs_remove_recursive(system->entry);
-				list_del(&system->list);
-				__put_system(system);
-			}
-			break;
-		}
-	}
+	mutex_unlock(&event_mutex);
+	return ret;
 }
 
 /*
- * Must be called under locking both of event_mutex and trace_event_mutex.
+ * Must be called under locking both of event_mutex and trace_event_sem.
  */
 static void __trace_remove_event_call(struct ftrace_event_call *call)
 {
 	event_remove(call);
 	trace_destroy_fields(call);
 	destroy_preds(call);
-	debugfs_remove_recursive(call->dir);
-	remove_subsystem_dir(call->class->system);
 }
 
 /* Remove an event_call */
 void trace_remove_event_call(struct ftrace_event_call *call)
 {
 	mutex_lock(&event_mutex);
-	down_write(&trace_event_mutex);
+	down_write(&trace_event_sem);
 	__trace_remove_event_call(call);
-	up_write(&trace_event_mutex);
+	up_write(&trace_event_sem);
 	mutex_unlock(&event_mutex);
 }
 
@@ -1336,6 +1626,26 @@ struct ftrace_module_file_ops {
 };
 
 static struct ftrace_module_file_ops *
+find_ftrace_file_ops(struct ftrace_module_file_ops *file_ops, struct module *mod)
+{
+	/*
+	 * As event_calls are added in groups by module,
+	 * when we find one file_ops, we don't need to search for
+	 * each call in that module, as the rest should be the
+	 * same. Only search for a new one if the last one did
+	 * not match.
+	 */
+	if (file_ops && mod == file_ops->mod)
+		return file_ops;
+
+	list_for_each_entry(file_ops, &ftrace_module_file_list, list) {
+		if (file_ops->mod == mod)
+			return file_ops;
+	}
+	return NULL;
+}
+
+static struct ftrace_module_file_ops *
 trace_create_file_ops(struct module *mod)
 {
 	struct ftrace_module_file_ops *file_ops;
@@ -1386,9 +1696,8 @@ static void trace_module_add_events(struct module *mod)
 		return;
 
 	for_each_event(call, start, end) {
-		__trace_add_event_call(*call, mod,
-				       &file_ops->id, &file_ops->enable,
-				       &file_ops->filter, &file_ops->format);
+		__register_event(*call, mod);
+		__add_event_to_tracers(*call, file_ops);
 	}
 }
 
@@ -1396,12 +1705,13 @@ static void trace_module_remove_events(struct module *mod)
 {
 	struct ftrace_module_file_ops *file_ops;
 	struct ftrace_event_call *call, *p;
-	bool found = false;
+	bool clear_trace = false;
 
-	down_write(&trace_event_mutex);
+	down_write(&trace_event_sem);
 	list_for_each_entry_safe(call, p, &ftrace_events, list) {
 		if (call->mod == mod) {
-			found = true;
+			if (call->flags & TRACE_EVENT_FL_WAS_ENABLED)
+				clear_trace = true;
 			__trace_remove_event_call(call);
 		}
 	}
@@ -1415,14 +1725,18 @@ static void trace_module_remove_events(struct module *mod)
 		list_del(&file_ops->list);
 		kfree(file_ops);
 	}
+	up_write(&trace_event_sem);
 
 	/*
 	 * It is safest to reset the ring buffer if the module being unloaded
-	 * registered any events.
+	 * registered any events that were used. The only worry is if
+	 * a new module gets loaded, and takes on the same id as the events
+	 * of this module. When printing out the buffer, traced events left
+	 * over from this module may be passed to the new module events and
+	 * unexpected results may occur.
 	 */
-	if (found)
-		tracing_reset_current_online_cpus();
-	up_write(&trace_event_mutex);
+	if (clear_trace)
+		tracing_reset_all_online_cpus();
 }
 
 static int trace_module_notify(struct notifier_block *self,
@@ -1443,36 +1757,575 @@ static int trace_module_notify(struct notifier_block *self,
 
 	return 0;
 }
+
+static int
+__trace_add_new_mod_event(struct ftrace_event_call *call,
+			  struct trace_array *tr,
+			  struct ftrace_module_file_ops *file_ops)
+{
+	return __trace_add_new_event(call, tr,
+				     &file_ops->id, &file_ops->enable,
+				     &file_ops->filter, &file_ops->format);
+}
+
 #else
-static int trace_module_notify(struct notifier_block *self,
-			       unsigned long val, void *data)
+static inline struct ftrace_module_file_ops *
+find_ftrace_file_ops(struct ftrace_module_file_ops *file_ops, struct module *mod)
+{
+	return NULL;
+}
+static inline int trace_module_notify(struct notifier_block *self,
+				      unsigned long val, void *data)
 {
 	return 0;
 }
+static inline int
+__trace_add_new_mod_event(struct ftrace_event_call *call,
+			  struct trace_array *tr,
+			  struct ftrace_module_file_ops *file_ops)
+{
+	return -ENODEV;
+}
 #endif /* CONFIG_MODULES */
 
-static struct notifier_block trace_module_nb = {
-	.notifier_call = trace_module_notify,
-	.priority = 0,
-};
-
-extern struct ftrace_event_call *__start_ftrace_events[];
-extern struct ftrace_event_call *__stop_ftrace_events[];
-
-static char bootup_event_buf[COMMAND_LINE_SIZE] __initdata;
-
-static __init int setup_trace_event(char *str)
+/* Create a new event directory structure for a trace directory. */
+static void
+__trace_add_event_dirs(struct trace_array *tr)
 {
-	strlcpy(bootup_event_buf, str, COMMAND_LINE_SIZE);
-	ring_buffer_expanded = 1;
-	tracing_selftest_disabled = 1;
+	struct ftrace_module_file_ops *file_ops = NULL;
+	struct ftrace_event_call *call;
+	int ret;
+
+	list_for_each_entry(call, &ftrace_events, list) {
+		if (call->mod) {
+			/*
+			 * Directories for events by modules need to
+			 * keep module ref counts when opened (as we don't
+			 * want the module to disappear when reading one
+			 * of these files). The file_ops keep account of
+			 * the module ref count.
+			 */
+			file_ops = find_ftrace_file_ops(file_ops, call->mod);
+			if (!file_ops)
+				continue; /* Warn? */
+			ret = __trace_add_new_mod_event(call, tr, file_ops);
+			if (ret < 0)
+				pr_warning("Could not create directory for event %s\n",
+					   call->name);
+			continue;
+		}
+		ret = __trace_add_new_event(call, tr,
+					    &ftrace_event_id_fops,
+					    &ftrace_enable_fops,
+					    &ftrace_event_filter_fops,
+					    &ftrace_event_format_fops);
+		if (ret < 0)
+			pr_warning("Could not create directory for event %s\n",
+				   call->name);
+	}
+}
+
+#ifdef CONFIG_DYNAMIC_FTRACE
+
+/* Avoid typos */
+#define ENABLE_EVENT_STR	"enable_event"
+#define DISABLE_EVENT_STR	"disable_event"
+
+struct event_probe_data {
+	struct ftrace_event_file	*file;
+	unsigned long			count;
+	int				ref;
+	bool				enable;
+};
+
+static struct ftrace_event_file *
+find_event_file(struct trace_array *tr, const char *system,  const char *event)
+{
+	struct ftrace_event_file *file;
+	struct ftrace_event_call *call;
+
+	list_for_each_entry(file, &tr->events, list) {
+
+		call = file->event_call;
+
+		if (!call->name || !call->class || !call->class->reg)
+			continue;
+
+		if (call->flags & TRACE_EVENT_FL_IGNORE_ENABLE)
+			continue;
+
+		if (strcmp(event, call->name) == 0 &&
+		    strcmp(system, call->class->system) == 0)
+			return file;
+	}
+	return NULL;
+}
+
+static void
+event_enable_probe(unsigned long ip, unsigned long parent_ip, void **_data)
+{
+	struct event_probe_data **pdata = (struct event_probe_data **)_data;
+	struct event_probe_data *data = *pdata;
+
+	if (!data)
+		return;
+
+	if (data->enable)
+		clear_bit(FTRACE_EVENT_FL_SOFT_DISABLED_BIT, &data->file->flags);
+	else
+		set_bit(FTRACE_EVENT_FL_SOFT_DISABLED_BIT, &data->file->flags);
+}
+
+static void
+event_enable_count_probe(unsigned long ip, unsigned long parent_ip, void **_data)
+{
+	struct event_probe_data **pdata = (struct event_probe_data **)_data;
+	struct event_probe_data *data = *pdata;
+
+	if (!data)
+		return;
+
+	if (!data->count)
+		return;
+
+	/* Skip if the event is in a state we want to switch to */
+	if (data->enable == !(data->file->flags & FTRACE_EVENT_FL_SOFT_DISABLED))
+		return;
+
+	if (data->count != -1)
+		(data->count)--;
+
+	event_enable_probe(ip, parent_ip, _data);
+}
+
+static int
+event_enable_print(struct seq_file *m, unsigned long ip,
+		      struct ftrace_probe_ops *ops, void *_data)
+{
+	struct event_probe_data *data = _data;
+
+	seq_printf(m, "%ps:", (void *)ip);
+
+	seq_printf(m, "%s:%s:%s",
+		   data->enable ? ENABLE_EVENT_STR : DISABLE_EVENT_STR,
+		   data->file->event_call->class->system,
+		   data->file->event_call->name);
+
+	if (data->count == -1)
+		seq_printf(m, ":unlimited\n");
+	else
+		seq_printf(m, ":count=%ld\n", data->count);
+
+	return 0;
+}
+
+static int
+event_enable_init(struct ftrace_probe_ops *ops, unsigned long ip,
+		  void **_data)
+{
+	struct event_probe_data **pdata = (struct event_probe_data **)_data;
+	struct event_probe_data *data = *pdata;
+
+	data->ref++;
+	return 0;
+}
+
+static void
+event_enable_free(struct ftrace_probe_ops *ops, unsigned long ip,
+		  void **_data)
+{
+	struct event_probe_data **pdata = (struct event_probe_data **)_data;
+	struct event_probe_data *data = *pdata;
+
+	if (WARN_ON_ONCE(data->ref <= 0))
+		return;
+
+	data->ref--;
+	if (!data->ref) {
+		/* Remove the SOFT_MODE flag */
+		__ftrace_event_enable_disable(data->file, 0, 1);
+		module_put(data->file->event_call->mod);
+		kfree(data);
+	}
+	*pdata = NULL;
+}
+
+static struct ftrace_probe_ops event_enable_probe_ops = {
+	.func			= event_enable_probe,
+	.print			= event_enable_print,
+	.init			= event_enable_init,
+	.free			= event_enable_free,
+};
+
+static struct ftrace_probe_ops event_enable_count_probe_ops = {
+	.func			= event_enable_count_probe,
+	.print			= event_enable_print,
+	.init			= event_enable_init,
+	.free			= event_enable_free,
+};
+
+static struct ftrace_probe_ops event_disable_probe_ops = {
+	.func			= event_enable_probe,
+	.print			= event_enable_print,
+	.init			= event_enable_init,
+	.free			= event_enable_free,
+};
+
+static struct ftrace_probe_ops event_disable_count_probe_ops = {
+	.func			= event_enable_count_probe,
+	.print			= event_enable_print,
+	.init			= event_enable_init,
+	.free			= event_enable_free,
+};
+
+static int
+event_enable_func(struct ftrace_hash *hash,
+		  char *glob, char *cmd, char *param, int enabled)
+{
+	struct trace_array *tr = top_trace_array();
+	struct ftrace_event_file *file;
+	struct ftrace_probe_ops *ops;
+	struct event_probe_data *data;
+	const char *system;
+	const char *event;
+	char *number;
+	bool enable;
+	int ret;
+
+	/* hash funcs only work with set_ftrace_filter */
+	if (!enabled)
+		return -EINVAL;
+
+	if (!param)
+		return -EINVAL;
+
+	system = strsep(&param, ":");
+	if (!param)
+		return -EINVAL;
+
+	event = strsep(&param, ":");
+
+	mutex_lock(&event_mutex);
+
+	ret = -EINVAL;
+	file = find_event_file(tr, system, event);
+	if (!file)
+		goto out;
+
+	enable = strcmp(cmd, ENABLE_EVENT_STR) == 0;
+
+	if (enable)
+		ops = param ? &event_enable_count_probe_ops : &event_enable_probe_ops;
+	else
+		ops = param ? &event_disable_count_probe_ops : &event_disable_probe_ops;
+
+	if (glob[0] == '!') {
+		unregister_ftrace_function_probe_func(glob+1, ops);
+		ret = 0;
+		goto out;
+	}
+
+	ret = -ENOMEM;
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data)
+		goto out;
+
+	data->enable = enable;
+	data->count = -1;
+	data->file = file;
+
+	if (!param)
+		goto out_reg;
+
+	number = strsep(&param, ":");
+
+	ret = -EINVAL;
+	if (!strlen(number))
+		goto out_free;
+
+	/*
+	 * We use the callback data field (which is a pointer)
+	 * as our counter.
+	 */
+	ret = kstrtoul(number, 0, &data->count);
+	if (ret)
+		goto out_free;
+
+ out_reg:
+	/* Don't let event modules unload while probe registered */
+	ret = try_module_get(file->event_call->mod);
+	if (!ret)
+		goto out_free;
+
+	ret = __ftrace_event_enable_disable(file, 1, 1);
+	if (ret < 0)
+		goto out_put;
+	ret = register_ftrace_function_probe(glob, ops, data);
+	if (!ret)
+		goto out_disable;
+ out:
+	mutex_unlock(&event_mutex);
+	return ret;
+
+ out_disable:
+	__ftrace_event_enable_disable(file, 0, 1);
+ out_put:
+	module_put(file->event_call->mod);
+ out_free:
+	kfree(data);
+	goto out;
+}
+
+static struct ftrace_func_command event_enable_cmd = {
+	.name			= ENABLE_EVENT_STR,
+	.func			= event_enable_func,
+};
+
+static struct ftrace_func_command event_disable_cmd = {
+	.name			= DISABLE_EVENT_STR,
+	.func			= event_enable_func,
+};
+
+static __init int register_event_cmds(void)
+{
+	int ret;
+
+	ret = register_ftrace_command(&event_enable_cmd);
+	if (WARN_ON(ret < 0))
+		return ret;
+	ret = register_ftrace_command(&event_disable_cmd);
+	if (WARN_ON(ret < 0))
+		unregister_ftrace_command(&event_enable_cmd);
+	return ret;
+}
+#else
+static inline int register_event_cmds(void) { return 0; }
+#endif /* CONFIG_DYNAMIC_FTRACE */
+
+/*
+ * The top level array has already had its ftrace_event_file
+ * descriptors created in order to allow for early events to
+ * be recorded. This function is called after the debugfs has been
+ * initialized, and we now have to create the files associated
+ * to the events.
+ */
+static __init void
+__trace_early_add_event_dirs(struct trace_array *tr)
+{
+	struct ftrace_event_file *file;
+	int ret;
+
+
+	list_for_each_entry(file, &tr->events, list) {
+		ret = event_create_dir(tr->event_dir, file,
+				       &ftrace_event_id_fops,
+				       &ftrace_enable_fops,
+				       &ftrace_event_filter_fops,
+				       &ftrace_event_format_fops);
+		if (ret < 0)
+			pr_warning("Could not create directory for event %s\n",
+				   file->event_call->name);
+	}
+}
+
+/*
+ * For early boot up, the top trace array requires to have
+ * a list of events that can be enabled. This must be done before
+ * the filesystem is set up in order to allow events to be traced
+ * early.
+ */
+static __init void
+__trace_early_add_events(struct trace_array *tr)
+{
+	struct ftrace_event_call *call;
+	int ret;
+
+	list_for_each_entry(call, &ftrace_events, list) {
+		/* Early boot up should not have any modules loaded */
+		if (WARN_ON_ONCE(call->mod))
+			continue;
+
+		ret = __trace_early_add_new_event(call, tr);
+		if (ret < 0)
+			pr_warning("Could not create early event %s\n",
+				   call->name);
+	}
+}
+
+/* Remove the event directory structure for a trace directory. */
+static void
+__trace_remove_event_dirs(struct trace_array *tr)
+{
+	struct ftrace_event_file *file, *next;
+
+	list_for_each_entry_safe(file, next, &tr->events, list) {
+		list_del(&file->list);
+		debugfs_remove_recursive(file->dir);
+		remove_subsystem(file->system);
+		kmem_cache_free(file_cachep, file);
+	}
+}
+
+static void
+__add_event_to_tracers(struct ftrace_event_call *call,
+		       struct ftrace_module_file_ops *file_ops)
+{
+	struct trace_array *tr;
+
+	list_for_each_entry(tr, &ftrace_trace_arrays, list) {
+		if (file_ops)
+			__trace_add_new_mod_event(call, tr, file_ops);
+		else
+			__trace_add_new_event(call, tr,
+					      &ftrace_event_id_fops,
+					      &ftrace_enable_fops,
+					      &ftrace_event_filter_fops,
+					      &ftrace_event_format_fops);
+	}
+}
+
+static struct notifier_block trace_module_nb = {
+	.notifier_call = trace_module_notify,
+	.priority = 0,
+};
+
+extern struct ftrace_event_call *__start_ftrace_events[];
+extern struct ftrace_event_call *__stop_ftrace_events[];
+
+static char bootup_event_buf[COMMAND_LINE_SIZE] __initdata;
+
+static __init int setup_trace_event(char *str)
+{
+	strlcpy(bootup_event_buf, str, COMMAND_LINE_SIZE);
+	ring_buffer_expanded = true;
+	tracing_selftest_disabled = true;
 
 	return 1;
 }
 __setup("trace_event=", setup_trace_event);
 
+/* Expects to have event_mutex held when called */
+static int
+create_event_toplevel_files(struct dentry *parent, struct trace_array *tr)
+{
+	struct dentry *d_events;
+	struct dentry *entry;
+
+	entry = debugfs_create_file("set_event", 0644, parent,
+				    tr, &ftrace_set_event_fops);
+	if (!entry) {
+		pr_warning("Could not create debugfs 'set_event' entry\n");
+		return -ENOMEM;
+	}
+
+	d_events = debugfs_create_dir("events", parent);
+	if (!d_events) {
+		pr_warning("Could not create debugfs 'events' directory\n");
+		return -ENOMEM;
+	}
+
+	/* ring buffer internal formats */
+	trace_create_file("header_page", 0444, d_events,
+			  ring_buffer_print_page_header,
+			  &ftrace_show_header_fops);
+
+	trace_create_file("header_event", 0444, d_events,
+			  ring_buffer_print_entry_header,
+			  &ftrace_show_header_fops);
+
+	trace_create_file("enable", 0644, d_events,
+			  tr, &ftrace_tr_enable_fops);
+
+	tr->event_dir = d_events;
+
+	return 0;
+}
+
+/**
+ * event_trace_add_tracer - add a instance of a trace_array to events
+ * @parent: The parent dentry to place the files/directories for events in
+ * @tr: The trace array associated with these events
+ *
+ * When a new instance is created, it needs to set up its events
+ * directory, as well as other files associated with events. It also
+ * creates the event hierachry in the @parent/events directory.
+ *
+ * Returns 0 on success.
+ */
+int event_trace_add_tracer(struct dentry *parent, struct trace_array *tr)
+{
+	int ret;
+
+	mutex_lock(&event_mutex);
+
+	ret = create_event_toplevel_files(parent, tr);
+	if (ret)
+		goto out_unlock;
+
+	down_write(&trace_event_sem);
+	__trace_add_event_dirs(tr);
+	up_write(&trace_event_sem);
+
+ out_unlock:
+	mutex_unlock(&event_mutex);
+
+	return ret;
+}
+
+/*
+ * The top trace array already had its file descriptors created.
+ * Now the files themselves need to be created.
+ */
+static __init int
+early_event_add_tracer(struct dentry *parent, struct trace_array *tr)
+{
+	int ret;
+
+	mutex_lock(&event_mutex);
+
+	ret = create_event_toplevel_files(parent, tr);
+	if (ret)
+		goto out_unlock;
+
+	down_write(&trace_event_sem);
+	__trace_early_add_event_dirs(tr);
+	up_write(&trace_event_sem);
+
+ out_unlock:
+	mutex_unlock(&event_mutex);
+
+	return ret;
+}
+
+int event_trace_del_tracer(struct trace_array *tr)
+{
+	/* Disable any running events */
+	__ftrace_set_clr_event(tr, NULL, NULL, NULL, 0);
+
+	mutex_lock(&event_mutex);
+
+	down_write(&trace_event_sem);
+	__trace_remove_event_dirs(tr);
+	debugfs_remove_recursive(tr->event_dir);
+	up_write(&trace_event_sem);
+
+	tr->event_dir = NULL;
+
+	mutex_unlock(&event_mutex);
+
+	return 0;
+}
+
+static __init int event_trace_memsetup(void)
+{
+	field_cachep = KMEM_CACHE(ftrace_event_field, SLAB_PANIC);
+	file_cachep = KMEM_CACHE(ftrace_event_file, SLAB_PANIC);
+	return 0;
+}
+
 static __init int event_trace_enable(void)
 {
+	struct trace_array *tr = top_trace_array();
 	struct ftrace_event_call **iter, *call;
 	char *buf = bootup_event_buf;
 	char *token;
@@ -1486,6 +2339,14 @@ static __init int event_trace_enable(void)
 			list_add(&call->list, &ftrace_events);
 	}
 
+	/*
+	 * We need the top trace array to have a working set of trace
+	 * points at early init, before the debug files and directories
+	 * are created. Create the file entries now, and attach them
+	 * to the actual file dentries later.
+	 */
+	__trace_early_add_events(tr);
+
 	while (true) {
 		token = strsep(&buf, ",");
 
@@ -1494,73 +2355,43 @@ static __init int event_trace_enable(void)
 		if (!*token)
 			continue;
 
-		ret = ftrace_set_clr_event(token, 1);
+		ret = ftrace_set_clr_event(tr, token, 1);
 		if (ret)
 			pr_warn("Failed to enable trace event: %s\n", token);
 	}
 
 	trace_printk_start_comm();
 
+	register_event_cmds();
+
 	return 0;
 }
 
 static __init int event_trace_init(void)
 {
-	struct ftrace_event_call *call;
+	struct trace_array *tr;
 	struct dentry *d_tracer;
 	struct dentry *entry;
-	struct dentry *d_events;
 	int ret;
 
+	tr = top_trace_array();
+
 	d_tracer = tracing_init_dentry();
 	if (!d_tracer)
 		return 0;
 
 	entry = debugfs_create_file("available_events", 0444, d_tracer,
-				    NULL, &ftrace_avail_fops);
+				    tr, &ftrace_avail_fops);
 	if (!entry)
 		pr_warning("Could not create debugfs "
 			   "'available_events' entry\n");
 
-	entry = debugfs_create_file("set_event", 0644, d_tracer,
-				    NULL, &ftrace_set_event_fops);
-	if (!entry)
-		pr_warning("Could not create debugfs "
-			   "'set_event' entry\n");
-
-	d_events = event_trace_events_dir();
-	if (!d_events)
-		return 0;
-
-	/* ring buffer internal formats */
-	trace_create_file("header_page", 0444, d_events,
-			  ring_buffer_print_page_header,
-			  &ftrace_show_header_fops);
-
-	trace_create_file("header_event", 0444, d_events,
-			  ring_buffer_print_entry_header,
-			  &ftrace_show_header_fops);
-
-	trace_create_file("enable", 0644, d_events,
-			  NULL, &ftrace_system_enable_fops);
-
 	if (trace_define_common_fields())
 		pr_warning("tracing: Failed to allocate common fields");
 
-	/*
-	 * Early initialization already enabled ftrace event.
-	 * Now it's only necessary to create the event directory.
-	 */
-	list_for_each_entry(call, &ftrace_events, list) {
-
-		ret = event_create_dir(call, d_events,
-				       &ftrace_event_id_fops,
-				       &ftrace_enable_fops,
-				       &ftrace_event_filter_fops,
-				       &ftrace_event_format_fops);
-		if (ret < 0)
-			event_remove(call);
-	}
+	ret = early_event_add_tracer(d_tracer, tr);
+	if (ret)
+		return ret;
 
 	ret = register_module_notifier(&trace_module_nb);
 	if (ret)
@@ -1568,6 +2399,7 @@ static __init int event_trace_init(void)
 
 	return 0;
 }
+early_initcall(event_trace_memsetup);
 core_initcall(event_trace_enable);
 fs_initcall(event_trace_init);
 
@@ -1627,13 +2459,20 @@ static __init void event_test_stuff(void)
  */
 static __init void event_trace_self_tests(void)
 {
+	struct ftrace_subsystem_dir *dir;
+	struct ftrace_event_file *file;
 	struct ftrace_event_call *call;
 	struct event_subsystem *system;
+	struct trace_array *tr;
 	int ret;
 
+	tr = top_trace_array();
+
 	pr_info("Running tests on trace events:\n");
 
-	list_for_each_entry(call, &ftrace_events, list) {
+	list_for_each_entry(file, &tr->events, list) {
+
+		call = file->event_call;
 
 		/* Only test those that have a probe */
 		if (!call->class || !call->class->probe)
@@ -1657,15 +2496,15 @@ static __init void event_trace_self_tests(void)
 		 * If an event is already enabled, someone is using
 		 * it and the self test should not be on.
 		 */
-		if (call->flags & TRACE_EVENT_FL_ENABLED) {
+		if (file->flags & FTRACE_EVENT_FL_ENABLED) {
 			pr_warning("Enabled event during self test!\n");
 			WARN_ON_ONCE(1);
 			continue;
 		}
 
-		ftrace_event_enable_disable(call, 1);
+		ftrace_event_enable_disable(file, 1);
 		event_test_stuff();
-		ftrace_event_enable_disable(call, 0);
+		ftrace_event_enable_disable(file, 0);
 
 		pr_cont("OK\n");
 	}
@@ -1674,7 +2513,9 @@ static __init void event_trace_self_tests(void)
 
 	pr_info("Running tests on trace event systems:\n");
 
-	list_for_each_entry(system, &event_subsystems, list) {
+	list_for_each_entry(dir, &tr->systems, list) {
+
+		system = dir->subsystem;
 
 		/* the ftrace system is special, skip it */
 		if (strcmp(system->name, "ftrace") == 0)
@@ -1682,7 +2523,7 @@ static __init void event_trace_self_tests(void)
 
 		pr_info("Testing event system %s: ", system->name);
 
-		ret = __ftrace_set_clr_event(NULL, system->name, NULL, 1);
+		ret = __ftrace_set_clr_event(tr, NULL, system->name, NULL, 1);
 		if (WARN_ON_ONCE(ret)) {
 			pr_warning("error enabling system %s\n",
 				   system->name);
@@ -1691,7 +2532,7 @@ static __init void event_trace_self_tests(void)
 
 		event_test_stuff();
 
-		ret = __ftrace_set_clr_event(NULL, system->name, NULL, 0);
+		ret = __ftrace_set_clr_event(tr, NULL, system->name, NULL, 0);
 		if (WARN_ON_ONCE(ret)) {
 			pr_warning("error disabling system %s\n",
 				   system->name);
@@ -1706,7 +2547,7 @@ static __init void event_trace_self_tests(void)
 	pr_info("Running tests on all trace events:\n");
 	pr_info("Testing all events: ");
 
-	ret = __ftrace_set_clr_event(NULL, NULL, NULL, 1);
+	ret = __ftrace_set_clr_event(tr, NULL, NULL, NULL, 1);
 	if (WARN_ON_ONCE(ret)) {
 		pr_warning("error enabling all events\n");
 		return;
@@ -1715,7 +2556,7 @@ static __init void event_trace_self_tests(void)
 	event_test_stuff();
 
 	/* reset sysname */
-	ret = __ftrace_set_clr_event(NULL, NULL, NULL, 0);
+	ret = __ftrace_set_clr_event(tr, NULL, NULL, NULL, 0);
 	if (WARN_ON_ONCE(ret)) {
 		pr_warning("error disabling all events\n");
 		return;
diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c
index e5b0ca8..a636117 100644
--- a/kernel/trace/trace_events_filter.c
+++ b/kernel/trace/trace_events_filter.c
@@ -658,33 +658,6 @@ void print_subsystem_event_filter(struct event_subsystem *system,
 	mutex_unlock(&event_mutex);
 }
 
-static struct ftrace_event_field *
-__find_event_field(struct list_head *head, char *name)
-{
-	struct ftrace_event_field *field;
-
-	list_for_each_entry(field, head, link) {
-		if (!strcmp(field->name, name))
-			return field;
-	}
-
-	return NULL;
-}
-
-static struct ftrace_event_field *
-find_event_field(struct ftrace_event_call *call, char *name)
-{
-	struct ftrace_event_field *field;
-	struct list_head *head;
-
-	field = __find_event_field(&ftrace_common_fields, name);
-	if (field)
-		return field;
-
-	head = trace_get_fields(call);
-	return __find_event_field(head, name);
-}
-
 static int __alloc_pred_stack(struct pred_stack *stack, int n_preds)
 {
 	stack->preds = kcalloc(n_preds + 1, sizeof(*stack->preds), GFP_KERNEL);
@@ -1337,7 +1310,7 @@ static struct filter_pred *create_pred(struct filter_parse_state *ps,
 		return NULL;
 	}
 
-	field = find_event_field(call, operand1);
+	field = trace_find_event_field(call, operand1);
 	if (!field) {
 		parse_error(ps, FILT_ERR_FIELD_NOT_FOUND, 0);
 		return NULL;
@@ -1907,16 +1880,17 @@ out_unlock:
 	return err;
 }
 
-int apply_subsystem_event_filter(struct event_subsystem *system,
+int apply_subsystem_event_filter(struct ftrace_subsystem_dir *dir,
 				 char *filter_string)
 {
+	struct event_subsystem *system = dir->subsystem;
 	struct event_filter *filter;
 	int err = 0;
 
 	mutex_lock(&event_mutex);
 
 	/* Make sure the system still has events */
-	if (!system->nr_events) {
+	if (!dir->nr_events) {
 		err = -ENODEV;
 		goto out_unlock;
 	}
diff --git a/kernel/trace/trace_export.c b/kernel/trace/trace_export.c
index e039906..d21a746 100644
--- a/kernel/trace/trace_export.c
+++ b/kernel/trace/trace_export.c
@@ -129,7 +129,7 @@ static void __always_unused ____ftrace_check_##name(void)		\
 
 #undef FTRACE_ENTRY
 #define FTRACE_ENTRY(name, struct_name, id, tstruct, print, filter)	\
-int									\
+static int __init							\
 ftrace_define_fields_##name(struct ftrace_event_call *event_call)	\
 {									\
 	struct struct_name field;					\
@@ -168,7 +168,7 @@ ftrace_define_fields_##name(struct ftrace_event_call *event_call)	\
 #define FTRACE_ENTRY_REG(call, struct_name, etype, tstruct, print, filter,\
 			 regfn)						\
 									\
-struct ftrace_event_class event_class_ftrace_##call = {			\
+struct ftrace_event_class __refdata event_class_ftrace_##call = {	\
 	.system			= __stringify(TRACE_SYSTEM),		\
 	.define_fields		= ftrace_define_fields_##call,		\
 	.fields			= LIST_HEAD_INIT(event_class_ftrace_##call.fields),\
diff --git a/kernel/trace/trace_functions.c b/kernel/trace/trace_functions.c
index 6011525..c4d6d71 100644
--- a/kernel/trace/trace_functions.c
+++ b/kernel/trace/trace_functions.c
@@ -28,7 +28,7 @@ static void tracing_stop_function_trace(void);
 static int function_trace_init(struct trace_array *tr)
 {
 	func_trace = tr;
-	tr->cpu = get_cpu();
+	tr->trace_buffer.cpu = get_cpu();
 	put_cpu();
 
 	tracing_start_cmdline_record();
@@ -44,7 +44,7 @@ static void function_trace_reset(struct trace_array *tr)
 
 static void function_trace_start(struct trace_array *tr)
 {
-	tracing_reset_online_cpus(tr);
+	tracing_reset_online_cpus(&tr->trace_buffer);
 }
 
 /* Our option */
@@ -76,7 +76,7 @@ function_trace_call(unsigned long ip, unsigned long parent_ip,
 		goto out;
 
 	cpu = smp_processor_id();
-	data = tr->data[cpu];
+	data = per_cpu_ptr(tr->trace_buffer.data, cpu);
 	if (!atomic_read(&data->disabled)) {
 		local_save_flags(flags);
 		trace_function(tr, ip, parent_ip, flags, pc);
@@ -107,7 +107,7 @@ function_stack_trace_call(unsigned long ip, unsigned long parent_ip,
 	 */
 	local_irq_save(flags);
 	cpu = raw_smp_processor_id();
-	data = tr->data[cpu];
+	data = per_cpu_ptr(tr->trace_buffer.data, cpu);
 	disabled = atomic_inc_return(&data->disabled);
 
 	if (likely(disabled == 1)) {
@@ -214,66 +214,89 @@ static struct tracer function_trace __read_mostly =
 };
 
 #ifdef CONFIG_DYNAMIC_FTRACE
-static void
-ftrace_traceon(unsigned long ip, unsigned long parent_ip, void **data)
+static int update_count(void **data)
 {
-	long *count = (long *)data;
-
-	if (tracing_is_on())
-		return;
+	unsigned long *count = (long *)data;
 
 	if (!*count)
-		return;
+		return 0;
 
 	if (*count != -1)
 		(*count)--;
 
-	tracing_on();
+	return 1;
 }
 
 static void
-ftrace_traceoff(unsigned long ip, unsigned long parent_ip, void **data)
+ftrace_traceon_count(unsigned long ip, unsigned long parent_ip, void **data)
 {
-	long *count = (long *)data;
+	if (tracing_is_on())
+		return;
+
+	if (update_count(data))
+		tracing_on();
+}
 
+static void
+ftrace_traceoff_count(unsigned long ip, unsigned long parent_ip, void **data)
+{
 	if (!tracing_is_on())
 		return;
 
-	if (!*count)
+	if (update_count(data))
+		tracing_off();
+}
+
+static void
+ftrace_traceon(unsigned long ip, unsigned long parent_ip, void **data)
+{
+	if (tracing_is_on())
 		return;
 
-	if (*count != -1)
-		(*count)--;
+	tracing_on();
+}
+
+static void
+ftrace_traceoff(unsigned long ip, unsigned long parent_ip, void **data)
+{
+	if (!tracing_is_on())
+		return;
 
 	tracing_off();
 }
 
-static int
-ftrace_trace_onoff_print(struct seq_file *m, unsigned long ip,
-			 struct ftrace_probe_ops *ops, void *data);
+/*
+ * Skip 4:
+ *   ftrace_stacktrace()
+ *   function_trace_probe_call()
+ *   ftrace_ops_list_func()
+ *   ftrace_call()
+ */
+#define STACK_SKIP 4
 
-static struct ftrace_probe_ops traceon_probe_ops = {
-	.func			= ftrace_traceon,
-	.print			= ftrace_trace_onoff_print,
-};
+static void
+ftrace_stacktrace(unsigned long ip, unsigned long parent_ip, void **data)
+{
+	trace_dump_stack(STACK_SKIP);
+}
 
-static struct ftrace_probe_ops traceoff_probe_ops = {
-	.func			= ftrace_traceoff,
-	.print			= ftrace_trace_onoff_print,
-};
+static void
+ftrace_stacktrace_count(unsigned long ip, unsigned long parent_ip, void **data)
+{
+	if (!tracing_is_on())
+		return;
+
+	if (update_count(data))
+		trace_dump_stack(STACK_SKIP);
+}
 
 static int
-ftrace_trace_onoff_print(struct seq_file *m, unsigned long ip,
-			 struct ftrace_probe_ops *ops, void *data)
+ftrace_probe_print(const char *name, struct seq_file *m,
+		   unsigned long ip, void *data)
 {
 	long count = (long)data;
 
-	seq_printf(m, "%ps:", (void *)ip);
-
-	if (ops == &traceon_probe_ops)
-		seq_printf(m, "traceon");
-	else
-		seq_printf(m, "traceoff");
+	seq_printf(m, "%ps:%s", (void *)ip, name);
 
 	if (count == -1)
 		seq_printf(m, ":unlimited\n");
@@ -284,26 +307,61 @@ ftrace_trace_onoff_print(struct seq_file *m, unsigned long ip,
 }
 
 static int
-ftrace_trace_onoff_unreg(char *glob, char *cmd, char *param)
+ftrace_traceon_print(struct seq_file *m, unsigned long ip,
+			 struct ftrace_probe_ops *ops, void *data)
 {
-	struct ftrace_probe_ops *ops;
-
-	/* we register both traceon and traceoff to this callback */
-	if (strcmp(cmd, "traceon") == 0)
-		ops = &traceon_probe_ops;
-	else
-		ops = &traceoff_probe_ops;
+	return ftrace_probe_print("traceon", m, ip, data);
+}
 
-	unregister_ftrace_function_probe_func(glob, ops);
+static int
+ftrace_traceoff_print(struct seq_file *m, unsigned long ip,
+			 struct ftrace_probe_ops *ops, void *data)
+{
+	return ftrace_probe_print("traceoff", m, ip, data);
+}
 
-	return 0;
+static int
+ftrace_stacktrace_print(struct seq_file *m, unsigned long ip,
+			struct ftrace_probe_ops *ops, void *data)
+{
+	return ftrace_probe_print("stacktrace", m, ip, data);
 }
 
+static struct ftrace_probe_ops traceon_count_probe_ops = {
+	.func			= ftrace_traceon_count,
+	.print			= ftrace_traceon_print,
+};
+
+static struct ftrace_probe_ops traceoff_count_probe_ops = {
+	.func			= ftrace_traceoff_count,
+	.print			= ftrace_traceoff_print,
+};
+
+static struct ftrace_probe_ops stacktrace_count_probe_ops = {
+	.func			= ftrace_stacktrace_count,
+	.print			= ftrace_stacktrace_print,
+};
+
+static struct ftrace_probe_ops traceon_probe_ops = {
+	.func			= ftrace_traceon,
+	.print			= ftrace_traceon_print,
+};
+
+static struct ftrace_probe_ops traceoff_probe_ops = {
+	.func			= ftrace_traceoff,
+	.print			= ftrace_traceoff_print,
+};
+
+static struct ftrace_probe_ops stacktrace_probe_ops = {
+	.func			= ftrace_stacktrace,
+	.print			= ftrace_stacktrace_print,
+};
+
 static int
-ftrace_trace_onoff_callback(struct ftrace_hash *hash,
-			    char *glob, char *cmd, char *param, int enable)
+ftrace_trace_probe_callback(struct ftrace_probe_ops *ops,
+			    struct ftrace_hash *hash, char *glob,
+			    char *cmd, char *param, int enable)
 {
-	struct ftrace_probe_ops *ops;
 	void *count = (void *)-1;
 	char *number;
 	int ret;
@@ -312,14 +370,10 @@ ftrace_trace_onoff_callback(struct ftrace_hash *hash,
 	if (!enable)
 		return -EINVAL;
 
-	if (glob[0] == '!')
-		return ftrace_trace_onoff_unreg(glob+1, cmd, param);
-
-	/* we register both traceon and traceoff to this callback */
-	if (strcmp(cmd, "traceon") == 0)
-		ops = &traceon_probe_ops;
-	else
-		ops = &traceoff_probe_ops;
+	if (glob[0] == '!') {
+		unregister_ftrace_function_probe_func(glob+1, ops);
+		return 0;
+	}
 
 	if (!param)
 		goto out_reg;
@@ -343,6 +397,34 @@ ftrace_trace_onoff_callback(struct ftrace_hash *hash,
 	return ret < 0 ? ret : 0;
 }
 
+static int
+ftrace_trace_onoff_callback(struct ftrace_hash *hash,
+			    char *glob, char *cmd, char *param, int enable)
+{
+	struct ftrace_probe_ops *ops;
+
+	/* we register both traceon and traceoff to this callback */
+	if (strcmp(cmd, "traceon") == 0)
+		ops = param ? &traceon_count_probe_ops : &traceon_probe_ops;
+	else
+		ops = param ? &traceoff_count_probe_ops : &traceoff_probe_ops;
+
+	return ftrace_trace_probe_callback(ops, hash, glob, cmd,
+					   param, enable);
+}
+
+static int
+ftrace_stacktrace_callback(struct ftrace_hash *hash,
+			   char *glob, char *cmd, char *param, int enable)
+{
+	struct ftrace_probe_ops *ops;
+
+	ops = param ? &stacktrace_count_probe_ops : &stacktrace_probe_ops;
+
+	return ftrace_trace_probe_callback(ops, hash, glob, cmd,
+					   param, enable);
+}
+
 static struct ftrace_func_command ftrace_traceon_cmd = {
 	.name			= "traceon",
 	.func			= ftrace_trace_onoff_callback,
@@ -353,6 +435,11 @@ static struct ftrace_func_command ftrace_traceoff_cmd = {
 	.func			= ftrace_trace_onoff_callback,
 };
 
+static struct ftrace_func_command ftrace_stacktrace_cmd = {
+	.name			= "stacktrace",
+	.func			= ftrace_stacktrace_callback,
+};
+
 static int __init init_func_cmd_traceon(void)
 {
 	int ret;
@@ -364,6 +451,12 @@ static int __init init_func_cmd_traceon(void)
 	ret = register_ftrace_command(&ftrace_traceon_cmd);
 	if (ret)
 		unregister_ftrace_command(&ftrace_traceoff_cmd);
+
+	ret = register_ftrace_command(&ftrace_stacktrace_cmd);
+	if (ret) {
+		unregister_ftrace_command(&ftrace_traceoff_cmd);
+		unregister_ftrace_command(&ftrace_traceon_cmd);
+	}
 	return ret;
 }
 #else
diff --git a/kernel/trace/trace_functions_graph.c b/kernel/trace/trace_functions_graph.c
index 39ada66..8388bc9 100644
--- a/kernel/trace/trace_functions_graph.c
+++ b/kernel/trace/trace_functions_graph.c
@@ -218,7 +218,7 @@ int __trace_graph_entry(struct trace_array *tr,
 {
 	struct ftrace_event_call *call = &event_funcgraph_entry;
 	struct ring_buffer_event *event;
-	struct ring_buffer *buffer = tr->buffer;
+	struct ring_buffer *buffer = tr->trace_buffer.buffer;
 	struct ftrace_graph_ent_entry *entry;
 
 	if (unlikely(__this_cpu_read(ftrace_cpu_disabled)))
@@ -265,7 +265,7 @@ int trace_graph_entry(struct ftrace_graph_ent *trace)
 
 	local_irq_save(flags);
 	cpu = raw_smp_processor_id();
-	data = tr->data[cpu];
+	data = per_cpu_ptr(tr->trace_buffer.data, cpu);
 	disabled = atomic_inc_return(&data->disabled);
 	if (likely(disabled == 1)) {
 		pc = preempt_count();
@@ -323,7 +323,7 @@ void __trace_graph_return(struct trace_array *tr,
 {
 	struct ftrace_event_call *call = &event_funcgraph_exit;
 	struct ring_buffer_event *event;
-	struct ring_buffer *buffer = tr->buffer;
+	struct ring_buffer *buffer = tr->trace_buffer.buffer;
 	struct ftrace_graph_ret_entry *entry;
 
 	if (unlikely(__this_cpu_read(ftrace_cpu_disabled)))
@@ -350,7 +350,7 @@ void trace_graph_return(struct ftrace_graph_ret *trace)
 
 	local_irq_save(flags);
 	cpu = raw_smp_processor_id();
-	data = tr->data[cpu];
+	data = per_cpu_ptr(tr->trace_buffer.data, cpu);
 	disabled = atomic_inc_return(&data->disabled);
 	if (likely(disabled == 1)) {
 		pc = preempt_count();
@@ -560,9 +560,9 @@ get_return_for_leaf(struct trace_iterator *iter,
 			 * We need to consume the current entry to see
 			 * the next one.
 			 */
-			ring_buffer_consume(iter->tr->buffer, iter->cpu,
+			ring_buffer_consume(iter->trace_buffer->buffer, iter->cpu,
 					    NULL, NULL);
-			event = ring_buffer_peek(iter->tr->buffer, iter->cpu,
+			event = ring_buffer_peek(iter->trace_buffer->buffer, iter->cpu,
 						 NULL, NULL);
 		}
 
diff --git a/kernel/trace/trace_irqsoff.c b/kernel/trace/trace_irqsoff.c
index 443b25b..b19d065 100644
--- a/kernel/trace/trace_irqsoff.c
+++ b/kernel/trace/trace_irqsoff.c
@@ -33,6 +33,7 @@ enum {
 static int trace_type __read_mostly;
 
 static int save_flags;
+static bool function_enabled;
 
 static void stop_irqsoff_tracer(struct trace_array *tr, int graph);
 static int start_irqsoff_tracer(struct trace_array *tr, int graph);
@@ -121,7 +122,7 @@ static int func_prolog_dec(struct trace_array *tr,
 	if (!irqs_disabled_flags(*flags))
 		return 0;
 
-	*data = tr->data[cpu];
+	*data = per_cpu_ptr(tr->trace_buffer.data, cpu);
 	disabled = atomic_inc_return(&(*data)->disabled);
 
 	if (likely(disabled == 1))
@@ -175,7 +176,7 @@ static int irqsoff_set_flag(u32 old_flags, u32 bit, int set)
 		per_cpu(tracing_cpu, cpu) = 0;
 
 	tracing_max_latency = 0;
-	tracing_reset_online_cpus(irqsoff_trace);
+	tracing_reset_online_cpus(&irqsoff_trace->trace_buffer);
 
 	return start_irqsoff_tracer(irqsoff_trace, set);
 }
@@ -380,7 +381,7 @@ start_critical_timing(unsigned long ip, unsigned long parent_ip)
 	if (per_cpu(tracing_cpu, cpu))
 		return;
 
-	data = tr->data[cpu];
+	data = per_cpu_ptr(tr->trace_buffer.data, cpu);
 
 	if (unlikely(!data) || atomic_read(&data->disabled))
 		return;
@@ -418,7 +419,7 @@ stop_critical_timing(unsigned long ip, unsigned long parent_ip)
 	if (!tracer_enabled)
 		return;
 
-	data = tr->data[cpu];
+	data = per_cpu_ptr(tr->trace_buffer.data, cpu);
 
 	if (unlikely(!data) ||
 	    !data->critical_start || atomic_read(&data->disabled))
@@ -528,15 +529,60 @@ void trace_preempt_off(unsigned long a0, unsigned long a1)
 }
 #endif /* CONFIG_PREEMPT_TRACER */
 
-static int start_irqsoff_tracer(struct trace_array *tr, int graph)
+static int register_irqsoff_function(int graph, int set)
 {
-	int ret = 0;
+	int ret;
 
-	if (!graph)
-		ret = register_ftrace_function(&trace_ops);
-	else
+	/* 'set' is set if TRACE_ITER_FUNCTION is about to be set */
+	if (function_enabled || (!set && !(trace_flags & TRACE_ITER_FUNCTION)))
+		return 0;
+
+	if (graph)
 		ret = register_ftrace_graph(&irqsoff_graph_return,
 					    &irqsoff_graph_entry);
+	else
+		ret = register_ftrace_function(&trace_ops);
+
+	if (!ret)
+		function_enabled = true;
+
+	return ret;
+}
+
+static void unregister_irqsoff_function(int graph)
+{
+	if (!function_enabled)
+		return;
+
+	if (graph)
+		unregister_ftrace_graph();
+	else
+		unregister_ftrace_function(&trace_ops);
+
+	function_enabled = false;
+}
+
+static void irqsoff_function_set(int set)
+{
+	if (set)
+		register_irqsoff_function(is_graph(), 1);
+	else
+		unregister_irqsoff_function(is_graph());
+}
+
+static int irqsoff_flag_changed(struct tracer *tracer, u32 mask, int set)
+{
+	if (mask & TRACE_ITER_FUNCTION)
+		irqsoff_function_set(set);
+
+	return trace_keep_overwrite(tracer, mask, set);
+}
+
+static int start_irqsoff_tracer(struct trace_array *tr, int graph)
+{
+	int ret;
+
+	ret = register_irqsoff_function(graph, 0);
 
 	if (!ret && tracing_is_enabled())
 		tracer_enabled = 1;
@@ -550,10 +596,7 @@ static void stop_irqsoff_tracer(struct trace_array *tr, int graph)
 {
 	tracer_enabled = 0;
 
-	if (!graph)
-		unregister_ftrace_function(&trace_ops);
-	else
-		unregister_ftrace_graph();
+	unregister_irqsoff_function(graph);
 }
 
 static void __irqsoff_tracer_init(struct trace_array *tr)
@@ -561,14 +604,14 @@ static void __irqsoff_tracer_init(struct trace_array *tr)
 	save_flags = trace_flags;
 
 	/* non overwrite screws up the latency tracers */
-	set_tracer_flag(TRACE_ITER_OVERWRITE, 1);
-	set_tracer_flag(TRACE_ITER_LATENCY_FMT, 1);
+	set_tracer_flag(tr, TRACE_ITER_OVERWRITE, 1);
+	set_tracer_flag(tr, TRACE_ITER_LATENCY_FMT, 1);
 
 	tracing_max_latency = 0;
 	irqsoff_trace = tr;
 	/* make sure that the tracer is visible */
 	smp_wmb();
-	tracing_reset_online_cpus(tr);
+	tracing_reset_online_cpus(&tr->trace_buffer);
 
 	if (start_irqsoff_tracer(tr, is_graph()))
 		printk(KERN_ERR "failed to start irqsoff tracer\n");
@@ -581,8 +624,8 @@ static void irqsoff_tracer_reset(struct trace_array *tr)
 
 	stop_irqsoff_tracer(tr, is_graph());
 
-	set_tracer_flag(TRACE_ITER_LATENCY_FMT, lat_flag);
-	set_tracer_flag(TRACE_ITER_OVERWRITE, overwrite_flag);
+	set_tracer_flag(tr, TRACE_ITER_LATENCY_FMT, lat_flag);
+	set_tracer_flag(tr, TRACE_ITER_OVERWRITE, overwrite_flag);
 }
 
 static void irqsoff_tracer_start(struct trace_array *tr)
@@ -615,7 +658,7 @@ static struct tracer irqsoff_tracer __read_mostly =
 	.print_line     = irqsoff_print_line,
 	.flags		= &tracer_flags,
 	.set_flag	= irqsoff_set_flag,
-	.flag_changed	= trace_keep_overwrite,
+	.flag_changed	= irqsoff_flag_changed,
 #ifdef CONFIG_FTRACE_SELFTEST
 	.selftest    = trace_selftest_startup_irqsoff,
 #endif
@@ -649,7 +692,7 @@ static struct tracer preemptoff_tracer __read_mostly =
 	.print_line     = irqsoff_print_line,
 	.flags		= &tracer_flags,
 	.set_flag	= irqsoff_set_flag,
-	.flag_changed	= trace_keep_overwrite,
+	.flag_changed	= irqsoff_flag_changed,
 #ifdef CONFIG_FTRACE_SELFTEST
 	.selftest    = trace_selftest_startup_preemptoff,
 #endif
@@ -685,7 +728,7 @@ static struct tracer preemptirqsoff_tracer __read_mostly =
 	.print_line     = irqsoff_print_line,
 	.flags		= &tracer_flags,
 	.set_flag	= irqsoff_set_flag,
-	.flag_changed	= trace_keep_overwrite,
+	.flag_changed	= irqsoff_flag_changed,
 #ifdef CONFIG_FTRACE_SELFTEST
 	.selftest    = trace_selftest_startup_preemptirqsoff,
 #endif
diff --git a/kernel/trace/trace_kdb.c b/kernel/trace/trace_kdb.c
index 3c5c5df..bd90e1b 100644
--- a/kernel/trace/trace_kdb.c
+++ b/kernel/trace/trace_kdb.c
@@ -26,7 +26,7 @@ static void ftrace_dump_buf(int skip_lines, long cpu_file)
 	trace_init_global_iter(&iter);
 
 	for_each_tracing_cpu(cpu) {
-		atomic_inc(&iter.tr->data[cpu]->disabled);
+		atomic_inc(&per_cpu_ptr(iter.trace_buffer->data, cpu)->disabled);
 	}
 
 	old_userobj = trace_flags;
@@ -43,17 +43,17 @@ static void ftrace_dump_buf(int skip_lines, long cpu_file)
 	iter.iter_flags |= TRACE_FILE_LAT_FMT;
 	iter.pos = -1;
 
-	if (cpu_file == TRACE_PIPE_ALL_CPU) {
+	if (cpu_file == RING_BUFFER_ALL_CPUS) {
 		for_each_tracing_cpu(cpu) {
 			iter.buffer_iter[cpu] =
-			ring_buffer_read_prepare(iter.tr->buffer, cpu);
+			ring_buffer_read_prepare(iter.trace_buffer->buffer, cpu);
 			ring_buffer_read_start(iter.buffer_iter[cpu]);
 			tracing_iter_reset(&iter, cpu);
 		}
 	} else {
 		iter.cpu_file = cpu_file;
 		iter.buffer_iter[cpu_file] =
-			ring_buffer_read_prepare(iter.tr->buffer, cpu_file);
+			ring_buffer_read_prepare(iter.trace_buffer->buffer, cpu_file);
 		ring_buffer_read_start(iter.buffer_iter[cpu_file]);
 		tracing_iter_reset(&iter, cpu_file);
 	}
@@ -83,7 +83,7 @@ out:
 	trace_flags = old_userobj;
 
 	for_each_tracing_cpu(cpu) {
-		atomic_dec(&iter.tr->data[cpu]->disabled);
+		atomic_dec(&per_cpu_ptr(iter.trace_buffer->data, cpu)->disabled);
 	}
 
 	for_each_tracing_cpu(cpu)
@@ -115,7 +115,7 @@ static int kdb_ftdump(int argc, const char **argv)
 		    !cpu_online(cpu_file))
 			return KDB_BADINT;
 	} else {
-		cpu_file = TRACE_PIPE_ALL_CPU;
+		cpu_file = RING_BUFFER_ALL_CPUS;
 	}
 
 	kdb_trap_printk++;
diff --git a/kernel/trace/trace_mmiotrace.c b/kernel/trace/trace_mmiotrace.c
index fd3c8aa..a5e8f48 100644
--- a/kernel/trace/trace_mmiotrace.c
+++ b/kernel/trace/trace_mmiotrace.c
@@ -31,7 +31,7 @@ static void mmio_reset_data(struct trace_array *tr)
 	overrun_detected = false;
 	prev_overruns = 0;
 
-	tracing_reset_online_cpus(tr);
+	tracing_reset_online_cpus(&tr->trace_buffer);
 }
 
 static int mmio_trace_init(struct trace_array *tr)
@@ -128,7 +128,7 @@ static void mmio_close(struct trace_iterator *iter)
 static unsigned long count_overruns(struct trace_iterator *iter)
 {
 	unsigned long cnt = atomic_xchg(&dropped_count, 0);
-	unsigned long over = ring_buffer_overruns(iter->tr->buffer);
+	unsigned long over = ring_buffer_overruns(iter->trace_buffer->buffer);
 
 	if (over > prev_overruns)
 		cnt += over - prev_overruns;
@@ -309,7 +309,7 @@ static void __trace_mmiotrace_rw(struct trace_array *tr,
 				struct mmiotrace_rw *rw)
 {
 	struct ftrace_event_call *call = &event_mmiotrace_rw;
-	struct ring_buffer *buffer = tr->buffer;
+	struct ring_buffer *buffer = tr->trace_buffer.buffer;
 	struct ring_buffer_event *event;
 	struct trace_mmiotrace_rw *entry;
 	int pc = preempt_count();
@@ -330,7 +330,7 @@ static void __trace_mmiotrace_rw(struct trace_array *tr,
 void mmio_trace_rw(struct mmiotrace_rw *rw)
 {
 	struct trace_array *tr = mmio_trace_array;
-	struct trace_array_cpu *data = tr->data[smp_processor_id()];
+	struct trace_array_cpu *data = per_cpu_ptr(tr->trace_buffer.data, smp_processor_id());
 	__trace_mmiotrace_rw(tr, data, rw);
 }
 
@@ -339,7 +339,7 @@ static void __trace_mmiotrace_map(struct trace_array *tr,
 				struct mmiotrace_map *map)
 {
 	struct ftrace_event_call *call = &event_mmiotrace_map;
-	struct ring_buffer *buffer = tr->buffer;
+	struct ring_buffer *buffer = tr->trace_buffer.buffer;
 	struct ring_buffer_event *event;
 	struct trace_mmiotrace_map *entry;
 	int pc = preempt_count();
@@ -363,7 +363,7 @@ void mmio_trace_mapping(struct mmiotrace_map *map)
 	struct trace_array_cpu *data;
 
 	preempt_disable();
-	data = tr->data[smp_processor_id()];
+	data = per_cpu_ptr(tr->trace_buffer.data, smp_processor_id());
 	__trace_mmiotrace_map(tr, data, map);
 	preempt_enable();
 }
diff --git a/kernel/trace/trace_output.c b/kernel/trace/trace_output.c
index 697e88d..bb922d9 100644
--- a/kernel/trace/trace_output.c
+++ b/kernel/trace/trace_output.c
@@ -14,7 +14,7 @@
 /* must be a power of 2 */
 #define EVENT_HASHSIZE	128
 
-DECLARE_RWSEM(trace_event_mutex);
+DECLARE_RWSEM(trace_event_sem);
 
 static struct hlist_head event_hash[EVENT_HASHSIZE] __read_mostly;
 
@@ -37,6 +37,22 @@ int trace_print_seq(struct seq_file *m, struct trace_seq *s)
 	return ret;
 }
 
+enum print_line_t trace_print_bputs_msg_only(struct trace_iterator *iter)
+{
+	struct trace_seq *s = &iter->seq;
+	struct trace_entry *entry = iter->ent;
+	struct bputs_entry *field;
+	int ret;
+
+	trace_assign_type(field, entry);
+
+	ret = trace_seq_puts(s, field->str);
+	if (!ret)
+		return TRACE_TYPE_PARTIAL_LINE;
+
+	return TRACE_TYPE_HANDLED;
+}
+
 enum print_line_t trace_print_bprintk_msg_only(struct trace_iterator *iter)
 {
 	struct trace_seq *s = &iter->seq;
@@ -397,6 +413,32 @@ ftrace_print_hex_seq(struct trace_seq *p, const unsigned char *buf, int buf_len)
 }
 EXPORT_SYMBOL(ftrace_print_hex_seq);
 
+int ftrace_raw_output_prep(struct trace_iterator *iter,
+			   struct trace_event *trace_event)
+{
+	struct ftrace_event_call *event;
+	struct trace_seq *s = &iter->seq;
+	struct trace_seq *p = &iter->tmp_seq;
+	struct trace_entry *entry;
+	int ret;
+
+	event = container_of(trace_event, struct ftrace_event_call, event);
+	entry = iter->ent;
+
+	if (entry->type != event->event.type) {
+		WARN_ON_ONCE(1);
+		return TRACE_TYPE_UNHANDLED;
+	}
+
+	trace_seq_init(p);
+	ret = trace_seq_printf(s, "%s: ", event->name);
+	if (!ret)
+		return TRACE_TYPE_PARTIAL_LINE;
+
+	return 0;
+}
+EXPORT_SYMBOL(ftrace_raw_output_prep);
+
 #ifdef CONFIG_KRETPROBES
 static inline const char *kretprobed(const char *name)
 {
@@ -617,7 +659,7 @@ lat_print_timestamp(struct trace_iterator *iter, u64 next_ts)
 {
 	unsigned long verbose = trace_flags & TRACE_ITER_VERBOSE;
 	unsigned long in_ns = iter->iter_flags & TRACE_FILE_TIME_IN_NS;
-	unsigned long long abs_ts = iter->ts - iter->tr->time_start;
+	unsigned long long abs_ts = iter->ts - iter->trace_buffer->time_start;
 	unsigned long long rel_ts = next_ts - iter->ts;
 	struct trace_seq *s = &iter->seq;
 
@@ -783,12 +825,12 @@ static int trace_search_list(struct list_head **list)
 
 void trace_event_read_lock(void)
 {
-	down_read(&trace_event_mutex);
+	down_read(&trace_event_sem);
 }
 
 void trace_event_read_unlock(void)
 {
-	up_read(&trace_event_mutex);
+	up_read(&trace_event_sem);
 }
 
 /**
@@ -811,7 +853,7 @@ int register_ftrace_event(struct trace_event *event)
 	unsigned key;
 	int ret = 0;
 
-	down_write(&trace_event_mutex);
+	down_write(&trace_event_sem);
 
 	if (WARN_ON(!event))
 		goto out;
@@ -866,14 +908,14 @@ int register_ftrace_event(struct trace_event *event)
 
 	ret = event->type;
  out:
-	up_write(&trace_event_mutex);
+	up_write(&trace_event_sem);
 
 	return ret;
 }
 EXPORT_SYMBOL_GPL(register_ftrace_event);
 
 /*
- * Used by module code with the trace_event_mutex held for write.
+ * Used by module code with the trace_event_sem held for write.
  */
 int __unregister_ftrace_event(struct trace_event *event)
 {
@@ -888,9 +930,9 @@ int __unregister_ftrace_event(struct trace_event *event)
  */
 int unregister_ftrace_event(struct trace_event *event)
 {
-	down_write(&trace_event_mutex);
+	down_write(&trace_event_sem);
 	__unregister_ftrace_event(event);
-	up_write(&trace_event_mutex);
+	up_write(&trace_event_sem);
 
 	return 0;
 }
@@ -1217,6 +1259,64 @@ static struct trace_event trace_user_stack_event = {
 	.funcs		= &trace_user_stack_funcs,
 };
 
+/* TRACE_BPUTS */
+static enum print_line_t
+trace_bputs_print(struct trace_iterator *iter, int flags,
+		   struct trace_event *event)
+{
+	struct trace_entry *entry = iter->ent;
+	struct trace_seq *s = &iter->seq;
+	struct bputs_entry *field;
+
+	trace_assign_type(field, entry);
+
+	if (!seq_print_ip_sym(s, field->ip, flags))
+		goto partial;
+
+	if (!trace_seq_puts(s, ": "))
+		goto partial;
+
+	if (!trace_seq_puts(s, field->str))
+		goto partial;
+
+	return TRACE_TYPE_HANDLED;
+
+ partial:
+	return TRACE_TYPE_PARTIAL_LINE;
+}
+
+
+static enum print_line_t
+trace_bputs_raw(struct trace_iterator *iter, int flags,
+		struct trace_event *event)
+{
+	struct bputs_entry *field;
+	struct trace_seq *s = &iter->seq;
+
+	trace_assign_type(field, iter->ent);
+
+	if (!trace_seq_printf(s, ": %lx : ", field->ip))
+		goto partial;
+
+	if (!trace_seq_puts(s, field->str))
+		goto partial;
+
+	return TRACE_TYPE_HANDLED;
+
+ partial:
+	return TRACE_TYPE_PARTIAL_LINE;
+}
+
+static struct trace_event_functions trace_bputs_funcs = {
+	.trace		= trace_bputs_print,
+	.raw		= trace_bputs_raw,
+};
+
+static struct trace_event trace_bputs_event = {
+	.type		= TRACE_BPUTS,
+	.funcs		= &trace_bputs_funcs,
+};
+
 /* TRACE_BPRINT */
 static enum print_line_t
 trace_bprint_print(struct trace_iterator *iter, int flags,
@@ -1329,6 +1429,7 @@ static struct trace_event *events[] __initdata = {
 	&trace_wake_event,
 	&trace_stack_event,
 	&trace_user_stack_event,
+	&trace_bputs_event,
 	&trace_bprint_event,
 	&trace_print_event,
 	NULL
diff --git a/kernel/trace/trace_output.h b/kernel/trace/trace_output.h
index c038eba..127a9d8 100644
--- a/kernel/trace/trace_output.h
+++ b/kernel/trace/trace_output.h
@@ -5,6 +5,8 @@
 #include "trace.h"
 
 extern enum print_line_t
+trace_print_bputs_msg_only(struct trace_iterator *iter);
+extern enum print_line_t
 trace_print_bprintk_msg_only(struct trace_iterator *iter);
 extern enum print_line_t
 trace_print_printk_msg_only(struct trace_iterator *iter);
@@ -31,7 +33,7 @@ trace_print_lat_fmt(struct trace_seq *s, struct trace_entry *entry);
 
 /* used by module unregistering */
 extern int __unregister_ftrace_event(struct trace_event *event);
-extern struct rw_semaphore trace_event_mutex;
+extern struct rw_semaphore trace_event_sem;
 
 #define MAX_MEMHEX_BYTES	8
 #define HEX_CHARS		(MAX_MEMHEX_BYTES*2 + 1)
diff --git a/kernel/trace/trace_sched_switch.c b/kernel/trace/trace_sched_switch.c
index 3374c79..4e98e3b 100644
--- a/kernel/trace/trace_sched_switch.c
+++ b/kernel/trace/trace_sched_switch.c
@@ -28,7 +28,7 @@ tracing_sched_switch_trace(struct trace_array *tr,
 			   unsigned long flags, int pc)
 {
 	struct ftrace_event_call *call = &event_context_switch;
-	struct ring_buffer *buffer = tr->buffer;
+	struct ring_buffer *buffer = tr->trace_buffer.buffer;
 	struct ring_buffer_event *event;
 	struct ctx_switch_entry *entry;
 
@@ -69,7 +69,7 @@ probe_sched_switch(void *ignore, struct task_struct *prev, struct task_struct *n
 	pc = preempt_count();
 	local_irq_save(flags);
 	cpu = raw_smp_processor_id();
-	data = ctx_trace->data[cpu];
+	data = per_cpu_ptr(ctx_trace->trace_buffer.data, cpu);
 
 	if (likely(!atomic_read(&data->disabled)))
 		tracing_sched_switch_trace(ctx_trace, prev, next, flags, pc);
@@ -86,7 +86,7 @@ tracing_sched_wakeup_trace(struct trace_array *tr,
 	struct ftrace_event_call *call = &event_wakeup;
 	struct ring_buffer_event *event;
 	struct ctx_switch_entry *entry;
-	struct ring_buffer *buffer = tr->buffer;
+	struct ring_buffer *buffer = tr->trace_buffer.buffer;
 
 	event = trace_buffer_lock_reserve(buffer, TRACE_WAKE,
 					  sizeof(*entry), flags, pc);
@@ -123,7 +123,7 @@ probe_sched_wakeup(void *ignore, struct task_struct *wakee, int success)
 	pc = preempt_count();
 	local_irq_save(flags);
 	cpu = raw_smp_processor_id();
-	data = ctx_trace->data[cpu];
+	data = per_cpu_ptr(ctx_trace->trace_buffer.data, cpu);
 
 	if (likely(!atomic_read(&data->disabled)))
 		tracing_sched_wakeup_trace(ctx_trace, wakee, current,
diff --git a/kernel/trace/trace_sched_wakeup.c b/kernel/trace/trace_sched_wakeup.c
index fde652c..fee77e1 100644
--- a/kernel/trace/trace_sched_wakeup.c
+++ b/kernel/trace/trace_sched_wakeup.c
@@ -37,6 +37,7 @@ static int wakeup_graph_entry(struct ftrace_graph_ent *trace);
 static void wakeup_graph_return(struct ftrace_graph_ret *trace);
 
 static int save_flags;
+static bool function_enabled;
 
 #define TRACE_DISPLAY_GRAPH     1
 
@@ -89,7 +90,7 @@ func_prolog_preempt_disable(struct trace_array *tr,
 	if (cpu != wakeup_current_cpu)
 		goto out_enable;
 
-	*data = tr->data[cpu];
+	*data = per_cpu_ptr(tr->trace_buffer.data, cpu);
 	disabled = atomic_inc_return(&(*data)->disabled);
 	if (unlikely(disabled != 1))
 		goto out;
@@ -134,15 +135,60 @@ static struct ftrace_ops trace_ops __read_mostly =
 };
 #endif /* CONFIG_FUNCTION_TRACER */
 
-static int start_func_tracer(int graph)
+static int register_wakeup_function(int graph, int set)
 {
 	int ret;
 
-	if (!graph)
-		ret = register_ftrace_function(&trace_ops);
-	else
+	/* 'set' is set if TRACE_ITER_FUNCTION is about to be set */
+	if (function_enabled || (!set && !(trace_flags & TRACE_ITER_FUNCTION)))
+		return 0;
+
+	if (graph)
 		ret = register_ftrace_graph(&wakeup_graph_return,
 					    &wakeup_graph_entry);
+	else
+		ret = register_ftrace_function(&trace_ops);
+
+	if (!ret)
+		function_enabled = true;
+
+	return ret;
+}
+
+static void unregister_wakeup_function(int graph)
+{
+	if (!function_enabled)
+		return;
+
+	if (graph)
+		unregister_ftrace_graph();
+	else
+		unregister_ftrace_function(&trace_ops);
+
+	function_enabled = false;
+}
+
+static void wakeup_function_set(int set)
+{
+	if (set)
+		register_wakeup_function(is_graph(), 1);
+	else
+		unregister_wakeup_function(is_graph());
+}
+
+static int wakeup_flag_changed(struct tracer *tracer, u32 mask, int set)
+{
+	if (mask & TRACE_ITER_FUNCTION)
+		wakeup_function_set(set);
+
+	return trace_keep_overwrite(tracer, mask, set);
+}
+
+static int start_func_tracer(int graph)
+{
+	int ret;
+
+	ret = register_wakeup_function(graph, 0);
 
 	if (!ret && tracing_is_enabled())
 		tracer_enabled = 1;
@@ -156,10 +202,7 @@ static void stop_func_tracer(int graph)
 {
 	tracer_enabled = 0;
 
-	if (!graph)
-		unregister_ftrace_function(&trace_ops);
-	else
-		unregister_ftrace_graph();
+	unregister_wakeup_function(graph);
 }
 
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
@@ -353,7 +396,7 @@ probe_wakeup_sched_switch(void *ignore,
 
 	/* disable local data, not wakeup_cpu data */
 	cpu = raw_smp_processor_id();
-	disabled = atomic_inc_return(&wakeup_trace->data[cpu]->disabled);
+	disabled = atomic_inc_return(&per_cpu_ptr(wakeup_trace->trace_buffer.data, cpu)->disabled);
 	if (likely(disabled != 1))
 		goto out;
 
@@ -365,7 +408,7 @@ probe_wakeup_sched_switch(void *ignore,
 		goto out_unlock;
 
 	/* The task we are waiting for is waking up */
-	data = wakeup_trace->data[wakeup_cpu];
+	data = per_cpu_ptr(wakeup_trace->trace_buffer.data, wakeup_cpu);
 
 	__trace_function(wakeup_trace, CALLER_ADDR0, CALLER_ADDR1, flags, pc);
 	tracing_sched_switch_trace(wakeup_trace, prev, next, flags, pc);
@@ -387,7 +430,7 @@ out_unlock:
 	arch_spin_unlock(&wakeup_lock);
 	local_irq_restore(flags);
 out:
-	atomic_dec(&wakeup_trace->data[cpu]->disabled);
+	atomic_dec(&per_cpu_ptr(wakeup_trace->trace_buffer.data, cpu)->disabled);
 }
 
 static void __wakeup_reset(struct trace_array *tr)
@@ -405,7 +448,7 @@ static void wakeup_reset(struct trace_array *tr)
 {
 	unsigned long flags;
 
-	tracing_reset_online_cpus(tr);
+	tracing_reset_online_cpus(&tr->trace_buffer);
 
 	local_irq_save(flags);
 	arch_spin_lock(&wakeup_lock);
@@ -435,7 +478,7 @@ probe_wakeup(void *ignore, struct task_struct *p, int success)
 		return;
 
 	pc = preempt_count();
-	disabled = atomic_inc_return(&wakeup_trace->data[cpu]->disabled);
+	disabled = atomic_inc_return(&per_cpu_ptr(wakeup_trace->trace_buffer.data, cpu)->disabled);
 	if (unlikely(disabled != 1))
 		goto out;
 
@@ -458,7 +501,7 @@ probe_wakeup(void *ignore, struct task_struct *p, int success)
 
 	local_save_flags(flags);
 
-	data = wakeup_trace->data[wakeup_cpu];
+	data = per_cpu_ptr(wakeup_trace->trace_buffer.data, wakeup_cpu);
 	data->preempt_timestamp = ftrace_now(cpu);
 	tracing_sched_wakeup_trace(wakeup_trace, p, current, flags, pc);
 
@@ -472,7 +515,7 @@ probe_wakeup(void *ignore, struct task_struct *p, int success)
 out_locked:
 	arch_spin_unlock(&wakeup_lock);
 out:
-	atomic_dec(&wakeup_trace->data[cpu]->disabled);
+	atomic_dec(&per_cpu_ptr(wakeup_trace->trace_buffer.data, cpu)->disabled);
 }
 
 static void start_wakeup_tracer(struct trace_array *tr)
@@ -543,8 +586,8 @@ static int __wakeup_tracer_init(struct trace_array *tr)
 	save_flags = trace_flags;
 
 	/* non overwrite screws up the latency tracers */
-	set_tracer_flag(TRACE_ITER_OVERWRITE, 1);
-	set_tracer_flag(TRACE_ITER_LATENCY_FMT, 1);
+	set_tracer_flag(tr, TRACE_ITER_OVERWRITE, 1);
+	set_tracer_flag(tr, TRACE_ITER_LATENCY_FMT, 1);
 
 	tracing_max_latency = 0;
 	wakeup_trace = tr;
@@ -573,8 +616,8 @@ static void wakeup_tracer_reset(struct trace_array *tr)
 	/* make sure we put back any tasks we are tracing */
 	wakeup_reset(tr);
 
-	set_tracer_flag(TRACE_ITER_LATENCY_FMT, lat_flag);
-	set_tracer_flag(TRACE_ITER_OVERWRITE, overwrite_flag);
+	set_tracer_flag(tr, TRACE_ITER_LATENCY_FMT, lat_flag);
+	set_tracer_flag(tr, TRACE_ITER_OVERWRITE, overwrite_flag);
 }
 
 static void wakeup_tracer_start(struct trace_array *tr)
@@ -600,7 +643,7 @@ static struct tracer wakeup_tracer __read_mostly =
 	.print_line	= wakeup_print_line,
 	.flags		= &tracer_flags,
 	.set_flag	= wakeup_set_flag,
-	.flag_changed	= trace_keep_overwrite,
+	.flag_changed	= wakeup_flag_changed,
 #ifdef CONFIG_FTRACE_SELFTEST
 	.selftest    = trace_selftest_startup_wakeup,
 #endif
@@ -622,7 +665,7 @@ static struct tracer wakeup_rt_tracer __read_mostly =
 	.print_line	= wakeup_print_line,
 	.flags		= &tracer_flags,
 	.set_flag	= wakeup_set_flag,
-	.flag_changed	= trace_keep_overwrite,
+	.flag_changed	= wakeup_flag_changed,
 #ifdef CONFIG_FTRACE_SELFTEST
 	.selftest    = trace_selftest_startup_wakeup,
 #endif
diff --git a/kernel/trace/trace_selftest.c b/kernel/trace/trace_selftest.c
index 51c819c..55e2cf6 100644
--- a/kernel/trace/trace_selftest.c
+++ b/kernel/trace/trace_selftest.c
@@ -21,13 +21,13 @@ static inline int trace_valid_entry(struct trace_entry *entry)
 	return 0;
 }
 
-static int trace_test_buffer_cpu(struct trace_array *tr, int cpu)
+static int trace_test_buffer_cpu(struct trace_buffer *buf, int cpu)
 {
 	struct ring_buffer_event *event;
 	struct trace_entry *entry;
 	unsigned int loops = 0;
 
-	while ((event = ring_buffer_consume(tr->buffer, cpu, NULL, NULL))) {
+	while ((event = ring_buffer_consume(buf->buffer, cpu, NULL, NULL))) {
 		entry = ring_buffer_event_data(event);
 
 		/*
@@ -58,7 +58,7 @@ static int trace_test_buffer_cpu(struct trace_array *tr, int cpu)
  * Test the trace buffer to see if all the elements
  * are still sane.
  */
-static int trace_test_buffer(struct trace_array *tr, unsigned long *count)
+static int trace_test_buffer(struct trace_buffer *buf, unsigned long *count)
 {
 	unsigned long flags, cnt = 0;
 	int cpu, ret = 0;
@@ -67,7 +67,7 @@ static int trace_test_buffer(struct trace_array *tr, unsigned long *count)
 	local_irq_save(flags);
 	arch_spin_lock(&ftrace_max_lock);
 
-	cnt = ring_buffer_entries(tr->buffer);
+	cnt = ring_buffer_entries(buf->buffer);
 
 	/*
 	 * The trace_test_buffer_cpu runs a while loop to consume all data.
@@ -78,7 +78,7 @@ static int trace_test_buffer(struct trace_array *tr, unsigned long *count)
 	 */
 	tracing_off();
 	for_each_possible_cpu(cpu) {
-		ret = trace_test_buffer_cpu(tr, cpu);
+		ret = trace_test_buffer_cpu(buf, cpu);
 		if (ret)
 			break;
 	}
@@ -355,7 +355,7 @@ int trace_selftest_startup_dynamic_tracing(struct tracer *trace,
 	msleep(100);
 
 	/* we should have nothing in the buffer */
-	ret = trace_test_buffer(tr, &count);
+	ret = trace_test_buffer(&tr->trace_buffer, &count);
 	if (ret)
 		goto out;
 
@@ -376,7 +376,7 @@ int trace_selftest_startup_dynamic_tracing(struct tracer *trace,
 	ftrace_enabled = 0;
 
 	/* check the trace buffer */
-	ret = trace_test_buffer(tr, &count);
+	ret = trace_test_buffer(&tr->trace_buffer, &count);
 	tracing_start();
 
 	/* we should only have one item */
@@ -666,7 +666,7 @@ trace_selftest_startup_function(struct tracer *trace, struct trace_array *tr)
 	ftrace_enabled = 0;
 
 	/* check the trace buffer */
-	ret = trace_test_buffer(tr, &count);
+	ret = trace_test_buffer(&tr->trace_buffer, &count);
 	trace->reset(tr);
 	tracing_start();
 
@@ -703,8 +703,6 @@ trace_selftest_startup_function(struct tracer *trace, struct trace_array *tr)
 /* Maximum number of functions to trace before diagnosing a hang */
 #define GRAPH_MAX_FUNC_TEST	100000000
 
-static void
-__ftrace_dump(bool disable_tracing, enum ftrace_dump_mode oops_dump_mode);
 static unsigned int graph_hang_thresh;
 
 /* Wrap the real function entry probe to avoid possible hanging */
@@ -714,8 +712,11 @@ static int trace_graph_entry_watchdog(struct ftrace_graph_ent *trace)
 	if (unlikely(++graph_hang_thresh > GRAPH_MAX_FUNC_TEST)) {
 		ftrace_graph_stop();
 		printk(KERN_WARNING "BUG: Function graph tracer hang!\n");
-		if (ftrace_dump_on_oops)
-			__ftrace_dump(false, DUMP_ALL);
+		if (ftrace_dump_on_oops) {
+			ftrace_dump(DUMP_ALL);
+			/* ftrace_dump() disables tracing */
+			tracing_on();
+		}
 		return 0;
 	}
 
@@ -737,7 +738,7 @@ trace_selftest_startup_function_graph(struct tracer *trace,
 	 * Simulate the init() callback but we attach a watchdog callback
 	 * to detect and recover from possible hangs
 	 */
-	tracing_reset_online_cpus(tr);
+	tracing_reset_online_cpus(&tr->trace_buffer);
 	set_graph_array(tr);
 	ret = register_ftrace_graph(&trace_graph_return,
 				    &trace_graph_entry_watchdog);
@@ -760,7 +761,7 @@ trace_selftest_startup_function_graph(struct tracer *trace,
 	tracing_stop();
 
 	/* check the trace buffer */
-	ret = trace_test_buffer(tr, &count);
+	ret = trace_test_buffer(&tr->trace_buffer, &count);
 
 	trace->reset(tr);
 	tracing_start();
@@ -815,9 +816,9 @@ trace_selftest_startup_irqsoff(struct tracer *trace, struct trace_array *tr)
 	/* stop the tracing. */
 	tracing_stop();
 	/* check both trace buffers */
-	ret = trace_test_buffer(tr, NULL);
+	ret = trace_test_buffer(&tr->trace_buffer, NULL);
 	if (!ret)
-		ret = trace_test_buffer(&max_tr, &count);
+		ret = trace_test_buffer(&tr->max_buffer, &count);
 	trace->reset(tr);
 	tracing_start();
 
@@ -877,9 +878,9 @@ trace_selftest_startup_preemptoff(struct tracer *trace, struct trace_array *tr)
 	/* stop the tracing. */
 	tracing_stop();
 	/* check both trace buffers */
-	ret = trace_test_buffer(tr, NULL);
+	ret = trace_test_buffer(&tr->trace_buffer, NULL);
 	if (!ret)
-		ret = trace_test_buffer(&max_tr, &count);
+		ret = trace_test_buffer(&tr->max_buffer, &count);
 	trace->reset(tr);
 	tracing_start();
 
@@ -943,11 +944,11 @@ trace_selftest_startup_preemptirqsoff(struct tracer *trace, struct trace_array *
 	/* stop the tracing. */
 	tracing_stop();
 	/* check both trace buffers */
-	ret = trace_test_buffer(tr, NULL);
+	ret = trace_test_buffer(&tr->trace_buffer, NULL);
 	if (ret)
 		goto out;
 
-	ret = trace_test_buffer(&max_tr, &count);
+	ret = trace_test_buffer(&tr->max_buffer, &count);
 	if (ret)
 		goto out;
 
@@ -973,11 +974,11 @@ trace_selftest_startup_preemptirqsoff(struct tracer *trace, struct trace_array *
 	/* stop the tracing. */
 	tracing_stop();
 	/* check both trace buffers */
-	ret = trace_test_buffer(tr, NULL);
+	ret = trace_test_buffer(&tr->trace_buffer, NULL);
 	if (ret)
 		goto out;
 
-	ret = trace_test_buffer(&max_tr, &count);
+	ret = trace_test_buffer(&tr->max_buffer, &count);
 
 	if (!ret && !count) {
 		printk(KERN_CONT ".. no entries found ..");
@@ -1084,10 +1085,10 @@ trace_selftest_startup_wakeup(struct tracer *trace, struct trace_array *tr)
 	/* stop the tracing. */
 	tracing_stop();
 	/* check both trace buffers */
-	ret = trace_test_buffer(tr, NULL);
+	ret = trace_test_buffer(&tr->trace_buffer, NULL);
 	printk("ret = %d\n", ret);
 	if (!ret)
-		ret = trace_test_buffer(&max_tr, &count);
+		ret = trace_test_buffer(&tr->max_buffer, &count);
 
 
 	trace->reset(tr);
@@ -1126,7 +1127,7 @@ trace_selftest_startup_sched_switch(struct tracer *trace, struct trace_array *tr
 	/* stop the tracing. */
 	tracing_stop();
 	/* check the trace buffer */
-	ret = trace_test_buffer(tr, &count);
+	ret = trace_test_buffer(&tr->trace_buffer, &count);
 	trace->reset(tr);
 	tracing_start();
 
diff --git a/kernel/trace/trace_stack.c b/kernel/trace/trace_stack.c
index 42ca822..aab277b 100644
--- a/kernel/trace/trace_stack.c
+++ b/kernel/trace/trace_stack.c
@@ -20,13 +20,24 @@
 
 #define STACK_TRACE_ENTRIES 500
 
+#ifdef CC_USING_FENTRY
+# define fentry		1
+#else
+# define fentry		0
+#endif
+
 static unsigned long stack_dump_trace[STACK_TRACE_ENTRIES+1] =
 	 { [0 ... (STACK_TRACE_ENTRIES)] = ULONG_MAX };
 static unsigned stack_dump_index[STACK_TRACE_ENTRIES];
 
+/*
+ * Reserve one entry for the passed in ip. This will allow
+ * us to remove most or all of the stack size overhead
+ * added by the stack tracer itself.
+ */
 static struct stack_trace max_stack_trace = {
-	.max_entries		= STACK_TRACE_ENTRIES,
-	.entries		= stack_dump_trace,
+	.max_entries		= STACK_TRACE_ENTRIES - 1,
+	.entries		= &stack_dump_trace[1],
 };
 
 static unsigned long max_stack_size;
@@ -39,25 +50,34 @@ static DEFINE_MUTEX(stack_sysctl_mutex);
 int stack_tracer_enabled;
 static int last_stack_tracer_enabled;
 
-static inline void check_stack(void)
+static inline void
+check_stack(unsigned long ip, unsigned long *stack)
 {
 	unsigned long this_size, flags;
 	unsigned long *p, *top, *start;
+	static int tracer_frame;
+	int frame_size = ACCESS_ONCE(tracer_frame);
 	int i;
 
-	this_size = ((unsigned long)&this_size) & (THREAD_SIZE-1);
+	this_size = ((unsigned long)stack) & (THREAD_SIZE-1);
 	this_size = THREAD_SIZE - this_size;
+	/* Remove the frame of the tracer */
+	this_size -= frame_size;
 
 	if (this_size <= max_stack_size)
 		return;
 
 	/* we do not handle interrupt stacks yet */
-	if (!object_is_on_stack(&this_size))
+	if (!object_is_on_stack(stack))
 		return;
 
 	local_irq_save(flags);
 	arch_spin_lock(&max_stack_lock);
 
+	/* In case another CPU set the tracer_frame on us */
+	if (unlikely(!frame_size))
+		this_size -= tracer_frame;
+
 	/* a race could have already updated it */
 	if (this_size <= max_stack_size)
 		goto out;
@@ -70,10 +90,18 @@ static inline void check_stack(void)
 	save_stack_trace(&max_stack_trace);
 
 	/*
+	 * Add the passed in ip from the function tracer.
+	 * Searching for this on the stack will skip over
+	 * most of the overhead from the stack tracer itself.
+	 */
+	stack_dump_trace[0] = ip;
+	max_stack_trace.nr_entries++;
+
+	/*
 	 * Now find where in the stack these are.
 	 */
 	i = 0;
-	start = &this_size;
+	start = stack;
 	top = (unsigned long *)
 		(((unsigned long)start & ~(THREAD_SIZE-1)) + THREAD_SIZE);
 
@@ -97,6 +125,18 @@ static inline void check_stack(void)
 				found = 1;
 				/* Start the search from here */
 				start = p + 1;
+				/*
+				 * We do not want to show the overhead
+				 * of the stack tracer stack in the
+				 * max stack. If we haven't figured
+				 * out what that is, then figure it out
+				 * now.
+				 */
+				if (unlikely(!tracer_frame) && i == 1) {
+					tracer_frame = (p - stack) *
+						sizeof(unsigned long);
+					max_stack_size -= tracer_frame;
+				}
 			}
 		}
 
@@ -113,6 +153,7 @@ static void
 stack_trace_call(unsigned long ip, unsigned long parent_ip,
 		 struct ftrace_ops *op, struct pt_regs *pt_regs)
 {
+	unsigned long stack;
 	int cpu;
 
 	preempt_disable_notrace();
@@ -122,7 +163,26 @@ stack_trace_call(unsigned long ip, unsigned long parent_ip,
 	if (per_cpu(trace_active, cpu)++ != 0)
 		goto out;
 
-	check_stack();
+	/*
+	 * When fentry is used, the traced function does not get
+	 * its stack frame set up, and we lose the parent.
+	 * The ip is pretty useless because the function tracer
+	 * was called before that function set up its stack frame.
+	 * In this case, we use the parent ip.
+	 *
+	 * By adding the return address of either the parent ip
+	 * or the current ip we can disregard most of the stack usage
+	 * caused by the stack tracer itself.
+	 *
+	 * The function tracer always reports the address of where the
+	 * mcount call was, but the stack will hold the return address.
+	 */
+	if (fentry)
+		ip = parent_ip;
+	else
+		ip += MCOUNT_INSN_SIZE;
+
+	check_stack(ip, &stack);
 
  out:
 	per_cpu(trace_active, cpu)--;
diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c
index 7a809e3..8f2ac73 100644
--- a/kernel/trace/trace_syscalls.c
+++ b/kernel/trace/trace_syscalls.c
@@ -12,10 +12,6 @@
 #include "trace.h"
 
 static DEFINE_MUTEX(syscall_trace_lock);
-static int sys_refcount_enter;
-static int sys_refcount_exit;
-static DECLARE_BITMAP(enabled_enter_syscalls, NR_syscalls);
-static DECLARE_BITMAP(enabled_exit_syscalls, NR_syscalls);
 
 static int syscall_enter_register(struct ftrace_event_call *event,
 				 enum trace_reg type, void *data);
@@ -41,7 +37,7 @@ static inline bool arch_syscall_match_sym_name(const char *sym, const char *name
 	/*
 	 * Only compare after the "sys" prefix. Archs that use
 	 * syscall wrappers may have syscalls symbols aliases prefixed
-	 * with "SyS" instead of "sys", leading to an unwanted
+	 * with ".SyS" or ".sys" instead of "sys", leading to an unwanted
 	 * mismatch.
 	 */
 	return !strcmp(sym + 3, name + 3);
@@ -265,7 +261,7 @@ static void free_syscall_print_fmt(struct ftrace_event_call *call)
 		kfree(call->print_fmt);
 }
 
-static int syscall_enter_define_fields(struct ftrace_event_call *call)
+static int __init syscall_enter_define_fields(struct ftrace_event_call *call)
 {
 	struct syscall_trace_enter trace;
 	struct syscall_metadata *meta = call->data;
@@ -288,7 +284,7 @@ static int syscall_enter_define_fields(struct ftrace_event_call *call)
 	return ret;
 }
 
-static int syscall_exit_define_fields(struct ftrace_event_call *call)
+static int __init syscall_exit_define_fields(struct ftrace_event_call *call)
 {
 	struct syscall_trace_exit trace;
 	int ret;
@@ -303,8 +299,9 @@ static int syscall_exit_define_fields(struct ftrace_event_call *call)
 	return ret;
 }
 
-static void ftrace_syscall_enter(void *ignore, struct pt_regs *regs, long id)
+static void ftrace_syscall_enter(void *data, struct pt_regs *regs, long id)
 {
+	struct trace_array *tr = data;
 	struct syscall_trace_enter *entry;
 	struct syscall_metadata *sys_data;
 	struct ring_buffer_event *event;
@@ -315,7 +312,7 @@ static void ftrace_syscall_enter(void *ignore, struct pt_regs *regs, long id)
 	syscall_nr = trace_get_syscall_nr(current, regs);
 	if (syscall_nr < 0)
 		return;
-	if (!test_bit(syscall_nr, enabled_enter_syscalls))
+	if (!test_bit(syscall_nr, tr->enabled_enter_syscalls))
 		return;
 
 	sys_data = syscall_nr_to_meta(syscall_nr);
@@ -324,7 +321,8 @@ static void ftrace_syscall_enter(void *ignore, struct pt_regs *regs, long id)
 
 	size = sizeof(*entry) + sizeof(unsigned long) * sys_data->nb_args;
 
-	event = trace_current_buffer_lock_reserve(&buffer,
+	buffer = tr->trace_buffer.buffer;
+	event = trace_buffer_lock_reserve(buffer,
 			sys_data->enter_event->event.type, size, 0, 0);
 	if (!event)
 		return;
@@ -338,8 +336,9 @@ static void ftrace_syscall_enter(void *ignore, struct pt_regs *regs, long id)
 		trace_current_buffer_unlock_commit(buffer, event, 0, 0);
 }
 
-static void ftrace_syscall_exit(void *ignore, struct pt_regs *regs, long ret)
+static void ftrace_syscall_exit(void *data, struct pt_regs *regs, long ret)
 {
+	struct trace_array *tr = data;
 	struct syscall_trace_exit *entry;
 	struct syscall_metadata *sys_data;
 	struct ring_buffer_event *event;
@@ -349,14 +348,15 @@ static void ftrace_syscall_exit(void *ignore, struct pt_regs *regs, long ret)
 	syscall_nr = trace_get_syscall_nr(current, regs);
 	if (syscall_nr < 0)
 		return;
-	if (!test_bit(syscall_nr, enabled_exit_syscalls))
+	if (!test_bit(syscall_nr, tr->enabled_exit_syscalls))
 		return;
 
 	sys_data = syscall_nr_to_meta(syscall_nr);
 	if (!sys_data)
 		return;
 
-	event = trace_current_buffer_lock_reserve(&buffer,
+	buffer = tr->trace_buffer.buffer;
+	event = trace_buffer_lock_reserve(buffer,
 			sys_data->exit_event->event.type, sizeof(*entry), 0, 0);
 	if (!event)
 		return;
@@ -370,8 +370,10 @@ static void ftrace_syscall_exit(void *ignore, struct pt_regs *regs, long ret)
 		trace_current_buffer_unlock_commit(buffer, event, 0, 0);
 }
 
-static int reg_event_syscall_enter(struct ftrace_event_call *call)
+static int reg_event_syscall_enter(struct ftrace_event_file *file,
+				   struct ftrace_event_call *call)
 {
+	struct trace_array *tr = file->tr;
 	int ret = 0;
 	int num;
 
@@ -379,33 +381,37 @@ static int reg_event_syscall_enter(struct ftrace_event_call *call)
 	if (WARN_ON_ONCE(num < 0 || num >= NR_syscalls))
 		return -ENOSYS;
 	mutex_lock(&syscall_trace_lock);
-	if (!sys_refcount_enter)
-		ret = register_trace_sys_enter(ftrace_syscall_enter, NULL);
+	if (!tr->sys_refcount_enter)
+		ret = register_trace_sys_enter(ftrace_syscall_enter, tr);
 	if (!ret) {
-		set_bit(num, enabled_enter_syscalls);
-		sys_refcount_enter++;
+		set_bit(num, tr->enabled_enter_syscalls);
+		tr->sys_refcount_enter++;
 	}
 	mutex_unlock(&syscall_trace_lock);
 	return ret;
 }
 
-static void unreg_event_syscall_enter(struct ftrace_event_call *call)
+static void unreg_event_syscall_enter(struct ftrace_event_file *file,
+				      struct ftrace_event_call *call)
 {
+	struct trace_array *tr = file->tr;
 	int num;
 
 	num = ((struct syscall_metadata *)call->data)->syscall_nr;
 	if (WARN_ON_ONCE(num < 0 || num >= NR_syscalls))
 		return;
 	mutex_lock(&syscall_trace_lock);
-	sys_refcount_enter--;
-	clear_bit(num, enabled_enter_syscalls);
-	if (!sys_refcount_enter)
-		unregister_trace_sys_enter(ftrace_syscall_enter, NULL);
+	tr->sys_refcount_enter--;
+	clear_bit(num, tr->enabled_enter_syscalls);
+	if (!tr->sys_refcount_enter)
+		unregister_trace_sys_enter(ftrace_syscall_enter, tr);
 	mutex_unlock(&syscall_trace_lock);
 }
 
-static int reg_event_syscall_exit(struct ftrace_event_call *call)
+static int reg_event_syscall_exit(struct ftrace_event_file *file,
+				  struct ftrace_event_call *call)
 {
+	struct trace_array *tr = file->tr;
 	int ret = 0;
 	int num;
 
@@ -413,28 +419,30 @@ static int reg_event_syscall_exit(struct ftrace_event_call *call)
 	if (WARN_ON_ONCE(num < 0 || num >= NR_syscalls))
 		return -ENOSYS;
 	mutex_lock(&syscall_trace_lock);
-	if (!sys_refcount_exit)
-		ret = register_trace_sys_exit(ftrace_syscall_exit, NULL);
+	if (!tr->sys_refcount_exit)
+		ret = register_trace_sys_exit(ftrace_syscall_exit, tr);
 	if (!ret) {
-		set_bit(num, enabled_exit_syscalls);
-		sys_refcount_exit++;
+		set_bit(num, tr->enabled_exit_syscalls);
+		tr->sys_refcount_exit++;
 	}
 	mutex_unlock(&syscall_trace_lock);
 	return ret;
 }
 
-static void unreg_event_syscall_exit(struct ftrace_event_call *call)
+static void unreg_event_syscall_exit(struct ftrace_event_file *file,
+				     struct ftrace_event_call *call)
 {
+	struct trace_array *tr = file->tr;
 	int num;
 
 	num = ((struct syscall_metadata *)call->data)->syscall_nr;
 	if (WARN_ON_ONCE(num < 0 || num >= NR_syscalls))
 		return;
 	mutex_lock(&syscall_trace_lock);
-	sys_refcount_exit--;
-	clear_bit(num, enabled_exit_syscalls);
-	if (!sys_refcount_exit)
-		unregister_trace_sys_exit(ftrace_syscall_exit, NULL);
+	tr->sys_refcount_exit--;
+	clear_bit(num, tr->enabled_exit_syscalls);
+	if (!tr->sys_refcount_exit)
+		unregister_trace_sys_exit(ftrace_syscall_exit, tr);
 	mutex_unlock(&syscall_trace_lock);
 }
 
@@ -471,7 +479,7 @@ struct trace_event_functions exit_syscall_print_funcs = {
 	.trace		= print_syscall_exit,
 };
 
-struct ftrace_event_class event_class_syscall_enter = {
+struct ftrace_event_class __refdata event_class_syscall_enter = {
 	.system		= "syscalls",
 	.reg		= syscall_enter_register,
 	.define_fields	= syscall_enter_define_fields,
@@ -479,7 +487,7 @@ struct ftrace_event_class event_class_syscall_enter = {
 	.raw_init	= init_syscall_trace,
 };
 
-struct ftrace_event_class event_class_syscall_exit = {
+struct ftrace_event_class __refdata event_class_syscall_exit = {
 	.system		= "syscalls",
 	.reg		= syscall_exit_register,
 	.define_fields	= syscall_exit_define_fields,
@@ -685,11 +693,13 @@ static void perf_sysexit_disable(struct ftrace_event_call *call)
 static int syscall_enter_register(struct ftrace_event_call *event,
 				 enum trace_reg type, void *data)
 {
+	struct ftrace_event_file *file = data;
+
 	switch (type) {
 	case TRACE_REG_REGISTER:
-		return reg_event_syscall_enter(event);
+		return reg_event_syscall_enter(file, event);
 	case TRACE_REG_UNREGISTER:
-		unreg_event_syscall_enter(event);
+		unreg_event_syscall_enter(file, event);
 		return 0;
 
 #ifdef CONFIG_PERF_EVENTS
@@ -711,11 +721,13 @@ static int syscall_enter_register(struct ftrace_event_call *event,
 static int syscall_exit_register(struct ftrace_event_call *event,
 				 enum trace_reg type, void *data)
 {
+	struct ftrace_event_file *file = data;
+
 	switch (type) {
 	case TRACE_REG_REGISTER:
-		return reg_event_syscall_exit(event);
+		return reg_event_syscall_exit(file, event);
 	case TRACE_REG_UNREGISTER:
-		unreg_event_syscall_exit(event);
+		unreg_event_syscall_exit(file, event);
 		return 0;
 
 #ifdef CONFIG_PERF_EVENTS
diff --git a/kernel/uid16.c b/kernel/uid16.c
index d7948eb..f6c83d7 100644
--- a/kernel/uid16.c
+++ b/kernel/uid16.c
@@ -18,67 +18,43 @@
 
 SYSCALL_DEFINE3(chown16, const char __user *, filename, old_uid_t, user, old_gid_t, group)
 {
-	long ret = sys_chown(filename, low2highuid(user), low2highgid(group));
-	/* avoid REGPARM breakage on x86: */
-	asmlinkage_protect(3, ret, filename, user, group);
-	return ret;
+	return sys_chown(filename, low2highuid(user), low2highgid(group));
 }
 
 SYSCALL_DEFINE3(lchown16, const char __user *, filename, old_uid_t, user, old_gid_t, group)
 {
-	long ret = sys_lchown(filename, low2highuid(user), low2highgid(group));
-	/* avoid REGPARM breakage on x86: */
-	asmlinkage_protect(3, ret, filename, user, group);
-	return ret;
+	return sys_lchown(filename, low2highuid(user), low2highgid(group));
 }
 
 SYSCALL_DEFINE3(fchown16, unsigned int, fd, old_uid_t, user, old_gid_t, group)
 {
-	long ret = sys_fchown(fd, low2highuid(user), low2highgid(group));
-	/* avoid REGPARM breakage on x86: */
-	asmlinkage_protect(3, ret, fd, user, group);
-	return ret;
+	return sys_fchown(fd, low2highuid(user), low2highgid(group));
 }
 
 SYSCALL_DEFINE2(setregid16, old_gid_t, rgid, old_gid_t, egid)
 {
-	long ret = sys_setregid(low2highgid(rgid), low2highgid(egid));
-	/* avoid REGPARM breakage on x86: */
-	asmlinkage_protect(2, ret, rgid, egid);
-	return ret;
+	return sys_setregid(low2highgid(rgid), low2highgid(egid));
 }
 
 SYSCALL_DEFINE1(setgid16, old_gid_t, gid)
 {
-	long ret = sys_setgid(low2highgid(gid));
-	/* avoid REGPARM breakage on x86: */
-	asmlinkage_protect(1, ret, gid);
-	return ret;
+	return sys_setgid(low2highgid(gid));
 }
 
 SYSCALL_DEFINE2(setreuid16, old_uid_t, ruid, old_uid_t, euid)
 {
-	long ret = sys_setreuid(low2highuid(ruid), low2highuid(euid));
-	/* avoid REGPARM breakage on x86: */
-	asmlinkage_protect(2, ret, ruid, euid);
-	return ret;
+	return sys_setreuid(low2highuid(ruid), low2highuid(euid));
 }
 
 SYSCALL_DEFINE1(setuid16, old_uid_t, uid)
 {
-	long ret = sys_setuid(low2highuid(uid));
-	/* avoid REGPARM breakage on x86: */
-	asmlinkage_protect(1, ret, uid);
-	return ret;
+	return sys_setuid(low2highuid(uid));
 }
 
 SYSCALL_DEFINE3(setresuid16, old_uid_t, ruid, old_uid_t, euid, old_uid_t, suid)
 {
-	long ret = sys_setresuid(low2highuid(ruid), low2highuid(euid),
+	return sys_setresuid(low2highuid(ruid), low2highuid(euid),
 				 low2highuid(suid));
-	/* avoid REGPARM breakage on x86: */
-	asmlinkage_protect(3, ret, ruid, euid, suid);
-	return ret;
 }
 
 SYSCALL_DEFINE3(getresuid16, old_uid_t __user *, ruidp, old_uid_t __user *, euidp, old_uid_t __user *, suidp)
@@ -100,11 +76,8 @@ SYSCALL_DEFINE3(getresuid16, old_uid_t __user *, ruidp, old_uid_t __user *, euid
 
 SYSCALL_DEFINE3(setresgid16, old_gid_t, rgid, old_gid_t, egid, old_gid_t, sgid)
 {
-	long ret = sys_setresgid(low2highgid(rgid), low2highgid(egid),
+	return sys_setresgid(low2highgid(rgid), low2highgid(egid),
 				 low2highgid(sgid));
-	/* avoid REGPARM breakage on x86: */
-	asmlinkage_protect(3, ret, rgid, egid, sgid);
-	return ret;
 }
 
 
@@ -127,18 +100,12 @@ SYSCALL_DEFINE3(getresgid16, old_gid_t __user *, rgidp, old_gid_t __user *, egid
 
 SYSCALL_DEFINE1(setfsuid16, old_uid_t, uid)
 {
-	long ret = sys_setfsuid(low2highuid(uid));
-	/* avoid REGPARM breakage on x86: */
-	asmlinkage_protect(1, ret, uid);
-	return ret;
+	return sys_setfsuid(low2highuid(uid));
 }
 
 SYSCALL_DEFINE1(setfsgid16, old_gid_t, gid)
 {
-	long ret = sys_setfsgid(low2highgid(gid));
-	/* avoid REGPARM breakage on x86: */
-	asmlinkage_protect(1, ret, gid);
-	return ret;
+	return sys_setfsgid(low2highgid(gid));
 }
 
 static int groups16_to_user(old_gid_t __user *grouplist,
diff --git a/kernel/watchdog.c b/kernel/watchdog.c
index 4a94467..ea741c3 100644
--- a/kernel/watchdog.c
+++ b/kernel/watchdog.c
@@ -239,10 +239,12 @@ static void watchdog_overflow_callback(struct perf_event *event,
 		if (__this_cpu_read(hard_watchdog_warn) == true)
 			return;
 
-		if (hardlockup_panic)
+		if (hardlockup_panic) {
+			trigger_all_cpu_backtrace();
 			panic("Watchdog detected hard LOCKUP on cpu %d", this_cpu);
-		else
+		} else {
 			WARN(1, "Watchdog detected hard LOCKUP on cpu %d", this_cpu);
+		}
 
 		__this_cpu_write(hard_watchdog_warn, true);
 		return;
@@ -323,8 +325,10 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer)
 		else
 			dump_stack();
 
-		if (softlockup_panic)
+		if (softlockup_panic) {
+			trigger_all_cpu_backtrace();
 			panic("softlockup: hung tasks");
+		}
 		__this_cpu_write(soft_watchdog_warn, true);
 	} else
 		__this_cpu_write(soft_watchdog_warn, false);
@@ -517,6 +521,11 @@ int proc_dowatchdog(struct ctl_table *table, int write,
 		return ret;
 
 	set_sample_period();
+	/*
+	 * Watchdog threads shouldn't be enabled if they are
+	 * disabled. The 'watchdog_disabled' variable check in
+	 * watchdog_*_all_cpus() function takes care of this.
+	 */
 	if (watchdog_enabled && watchdog_thresh)
 		watchdog_enable_all_cpus();
 	else
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index b48cd59..c273376 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -41,7 +41,11 @@
 #include <linux/debug_locks.h>
 #include <linux/lockdep.h>
 #include <linux/idr.h>
+#include <linux/jhash.h>
 #include <linux/hashtable.h>
+#include <linux/rculist.h>
+#include <linux/nodemask.h>
+#include <linux/moduleparam.h>
 
 #include "workqueue_internal.h"
 
@@ -58,12 +62,11 @@ enum {
 	 * %WORKER_UNBOUND set and concurrency management disabled, and may
 	 * be executing on any CPU.  The pool behaves as an unbound one.
 	 *
-	 * Note that DISASSOCIATED can be flipped only while holding
-	 * assoc_mutex to avoid changing binding state while
+	 * Note that DISASSOCIATED should be flipped only while holding
+	 * manager_mutex to avoid changing binding state while
 	 * create_worker() is in progress.
 	 */
 	POOL_MANAGE_WORKERS	= 1 << 0,	/* need to manage workers */
-	POOL_MANAGING_WORKERS   = 1 << 1,       /* managing workers */
 	POOL_DISASSOCIATED	= 1 << 2,	/* cpu can't serve workers */
 	POOL_FREEZING		= 1 << 3,	/* freeze in progress */
 
@@ -74,12 +77,14 @@ enum {
 	WORKER_PREP		= 1 << 3,	/* preparing to run works */
 	WORKER_CPU_INTENSIVE	= 1 << 6,	/* cpu intensive */
 	WORKER_UNBOUND		= 1 << 7,	/* worker is unbound */
+	WORKER_REBOUND		= 1 << 8,	/* worker was rebound */
 
-	WORKER_NOT_RUNNING	= WORKER_PREP | WORKER_UNBOUND |
-				  WORKER_CPU_INTENSIVE,
+	WORKER_NOT_RUNNING	= WORKER_PREP | WORKER_CPU_INTENSIVE |
+				  WORKER_UNBOUND | WORKER_REBOUND,
 
 	NR_STD_WORKER_POOLS	= 2,		/* # standard pools per cpu */
 
+	UNBOUND_POOL_HASH_ORDER	= 6,		/* hashed by pool->attrs */
 	BUSY_WORKER_HASH_ORDER	= 6,		/* 64 pointers */
 
 	MAX_IDLE_WORKERS_RATIO	= 4,		/* 1/4 of busy can be idle */
@@ -97,6 +102,8 @@ enum {
 	 */
 	RESCUER_NICE_LEVEL	= -20,
 	HIGHPRI_NICE_LEVEL	= -20,
+
+	WQ_NAME_LEN		= 24,
 };
 
 /*
@@ -115,16 +122,26 @@ enum {
  *    cpu or grabbing pool->lock is enough for read access.  If
  *    POOL_DISASSOCIATED is set, it's identical to L.
  *
- * F: wq->flush_mutex protected.
+ * MG: pool->manager_mutex and pool->lock protected.  Writes require both
+ *     locks.  Reads can happen under either lock.
+ *
+ * PL: wq_pool_mutex protected.
+ *
+ * PR: wq_pool_mutex protected for writes.  Sched-RCU protected for reads.
+ *
+ * WQ: wq->mutex protected.
  *
- * W: workqueue_lock protected.
+ * WR: wq->mutex protected for writes.  Sched-RCU protected for reads.
+ *
+ * MD: wq_mayday_lock protected.
  */
 
 /* struct worker is defined in workqueue_internal.h */
 
 struct worker_pool {
 	spinlock_t		lock;		/* the pool lock */
-	unsigned int		cpu;		/* I: the associated cpu */
+	int			cpu;		/* I: the associated cpu */
+	int			node;		/* I: the associated node ID */
 	int			id;		/* I: pool ID */
 	unsigned int		flags;		/* X: flags */
 
@@ -138,12 +155,18 @@ struct worker_pool {
 	struct timer_list	idle_timer;	/* L: worker idle timeout */
 	struct timer_list	mayday_timer;	/* L: SOS timer for workers */
 
-	/* workers are chained either in busy_hash or idle_list */
+	/* a workers is either on busy_hash or idle_list, or the manager */
 	DECLARE_HASHTABLE(busy_hash, BUSY_WORKER_HASH_ORDER);
 						/* L: hash of busy workers */
 
-	struct mutex		assoc_mutex;	/* protect POOL_DISASSOCIATED */
-	struct ida		worker_ida;	/* L: for worker IDs */
+	/* see manage_workers() for details on the two manager mutexes */
+	struct mutex		manager_arb;	/* manager arbitration */
+	struct mutex		manager_mutex;	/* manager exclusion */
+	struct idr		worker_idr;	/* MG: worker IDs and iteration */
+
+	struct workqueue_attrs	*attrs;		/* I: worker attributes */
+	struct hlist_node	hash_node;	/* PL: unbound_pool_hash node */
+	int			refcnt;		/* PL: refcnt for unbound pools */
 
 	/*
 	 * The current concurrency level.  As it's likely to be accessed
@@ -151,6 +174,12 @@ struct worker_pool {
 	 * cacheline.
 	 */
 	atomic_t		nr_running ____cacheline_aligned_in_smp;
+
+	/*
+	 * Destruction of pool is sched-RCU protected to allow dereferences
+	 * from get_work_pool().
+	 */
+	struct rcu_head		rcu;
 } ____cacheline_aligned_in_smp;
 
 /*
@@ -164,75 +193,107 @@ struct pool_workqueue {
 	struct workqueue_struct *wq;		/* I: the owning workqueue */
 	int			work_color;	/* L: current color */
 	int			flush_color;	/* L: flushing color */
+	int			refcnt;		/* L: reference count */
 	int			nr_in_flight[WORK_NR_COLORS];
 						/* L: nr of in_flight works */
 	int			nr_active;	/* L: nr of active works */
 	int			max_active;	/* L: max active works */
 	struct list_head	delayed_works;	/* L: delayed works */
-};
+	struct list_head	pwqs_node;	/* WR: node on wq->pwqs */
+	struct list_head	mayday_node;	/* MD: node on wq->maydays */
+
+	/*
+	 * Release of unbound pwq is punted to system_wq.  See put_pwq()
+	 * and pwq_unbound_release_workfn() for details.  pool_workqueue
+	 * itself is also sched-RCU protected so that the first pwq can be
+	 * determined without grabbing wq->mutex.
+	 */
+	struct work_struct	unbound_release_work;
+	struct rcu_head		rcu;
+} __aligned(1 << WORK_STRUCT_FLAG_BITS);
 
 /*
  * Structure used to wait for workqueue flush.
  */
 struct wq_flusher {
-	struct list_head	list;		/* F: list of flushers */
-	int			flush_color;	/* F: flush color waiting for */
+	struct list_head	list;		/* WQ: list of flushers */
+	int			flush_color;	/* WQ: flush color waiting for */
 	struct completion	done;		/* flush completion */
 };
 
-/*
- * All cpumasks are assumed to be always set on UP and thus can't be
- * used to determine whether there's something to be done.
- */
-#ifdef CONFIG_SMP
-typedef cpumask_var_t mayday_mask_t;
-#define mayday_test_and_set_cpu(cpu, mask)	\
-	cpumask_test_and_set_cpu((cpu), (mask))
-#define mayday_clear_cpu(cpu, mask)		cpumask_clear_cpu((cpu), (mask))
-#define for_each_mayday_cpu(cpu, mask)		for_each_cpu((cpu), (mask))
-#define alloc_mayday_mask(maskp, gfp)		zalloc_cpumask_var((maskp), (gfp))
-#define free_mayday_mask(mask)			free_cpumask_var((mask))
-#else
-typedef unsigned long mayday_mask_t;
-#define mayday_test_and_set_cpu(cpu, mask)	test_and_set_bit(0, &(mask))
-#define mayday_clear_cpu(cpu, mask)		clear_bit(0, &(mask))
-#define for_each_mayday_cpu(cpu, mask)		if ((cpu) = 0, (mask))
-#define alloc_mayday_mask(maskp, gfp)		true
-#define free_mayday_mask(mask)			do { } while (0)
-#endif
+struct wq_device;
 
 /*
- * The externally visible workqueue abstraction is an array of
- * per-CPU workqueues:
+ * The externally visible workqueue.  It relays the issued work items to
+ * the appropriate worker_pool through its pool_workqueues.
  */
 struct workqueue_struct {
-	unsigned int		flags;		/* W: WQ_* flags */
-	union {
-		struct pool_workqueue __percpu		*pcpu;
-		struct pool_workqueue			*single;
-		unsigned long				v;
-	} pool_wq;				/* I: pwq's */
-	struct list_head	list;		/* W: list of all workqueues */
-
-	struct mutex		flush_mutex;	/* protects wq flushing */
-	int			work_color;	/* F: current work color */
-	int			flush_color;	/* F: current flush color */
+	struct list_head	pwqs;		/* WR: all pwqs of this wq */
+	struct list_head	list;		/* PL: list of all workqueues */
+
+	struct mutex		mutex;		/* protects this wq */
+	int			work_color;	/* WQ: current work color */
+	int			flush_color;	/* WQ: current flush color */
 	atomic_t		nr_pwqs_to_flush; /* flush in progress */
-	struct wq_flusher	*first_flusher;	/* F: first flusher */
-	struct list_head	flusher_queue;	/* F: flush waiters */
-	struct list_head	flusher_overflow; /* F: flush overflow list */
+	struct wq_flusher	*first_flusher;	/* WQ: first flusher */
+	struct list_head	flusher_queue;	/* WQ: flush waiters */
+	struct list_head	flusher_overflow; /* WQ: flush overflow list */
 
-	mayday_mask_t		mayday_mask;	/* cpus requesting rescue */
+	struct list_head	maydays;	/* MD: pwqs requesting rescue */
 	struct worker		*rescuer;	/* I: rescue worker */
 
-	int			nr_drainers;	/* W: drain in progress */
-	int			saved_max_active; /* W: saved pwq max_active */
+	int			nr_drainers;	/* WQ: drain in progress */
+	int			saved_max_active; /* WQ: saved pwq max_active */
+
+	struct workqueue_attrs	*unbound_attrs;	/* WQ: only for unbound wqs */
+	struct pool_workqueue	*dfl_pwq;	/* WQ: only for unbound wqs */
+
+#ifdef CONFIG_SYSFS
+	struct wq_device	*wq_dev;	/* I: for sysfs interface */
+#endif
 #ifdef CONFIG_LOCKDEP
 	struct lockdep_map	lockdep_map;
 #endif
-	char			name[];		/* I: workqueue name */
+	char			name[WQ_NAME_LEN]; /* I: workqueue name */
+
+	/* hot fields used during command issue, aligned to cacheline */
+	unsigned int		flags ____cacheline_aligned; /* WQ: WQ_* flags */
+	struct pool_workqueue __percpu *cpu_pwqs; /* I: per-cpu pwqs */
+	struct pool_workqueue __rcu *numa_pwq_tbl[]; /* FR: unbound pwqs indexed by node */
 };
 
+static struct kmem_cache *pwq_cache;
+
+static int wq_numa_tbl_len;		/* highest possible NUMA node id + 1 */
+static cpumask_var_t *wq_numa_possible_cpumask;
+					/* possible CPUs of each node */
+
+static bool wq_disable_numa;
+module_param_named(disable_numa, wq_disable_numa, bool, 0444);
+
+static bool wq_numa_enabled;		/* unbound NUMA affinity enabled */
+
+/* buf for wq_update_unbound_numa_attrs(), protected by CPU hotplug exclusion */
+static struct workqueue_attrs *wq_update_unbound_numa_attrs_buf;
+
+static DEFINE_MUTEX(wq_pool_mutex);	/* protects pools and workqueues list */
+static DEFINE_SPINLOCK(wq_mayday_lock);	/* protects wq->maydays list */
+
+static LIST_HEAD(workqueues);		/* PL: list of all workqueues */
+static bool workqueue_freezing;		/* PL: have wqs started freezing? */
+
+/* the per-cpu worker pools */
+static DEFINE_PER_CPU_SHARED_ALIGNED(struct worker_pool [NR_STD_WORKER_POOLS],
+				     cpu_worker_pools);
+
+static DEFINE_IDR(worker_pool_idr);	/* PR: idr of all pools */
+
+/* PL: hash of all unbound pools keyed by pool->attrs */
+static DEFINE_HASHTABLE(unbound_pool_hash, UNBOUND_POOL_HASH_ORDER);
+
+/* I: attributes used when instantiating standard unbound pools on demand */
+static struct workqueue_attrs *unbound_std_wq_attrs[NR_STD_WORKER_POOLS];
+
 struct workqueue_struct *system_wq __read_mostly;
 EXPORT_SYMBOL_GPL(system_wq);
 struct workqueue_struct *system_highpri_wq __read_mostly;
@@ -244,64 +305,87 @@ EXPORT_SYMBOL_GPL(system_unbound_wq);
 struct workqueue_struct *system_freezable_wq __read_mostly;
 EXPORT_SYMBOL_GPL(system_freezable_wq);
 
+static int worker_thread(void *__worker);
+static void copy_workqueue_attrs(struct workqueue_attrs *to,
+				 const struct workqueue_attrs *from);
+
 #define CREATE_TRACE_POINTS
 #include <trace/events/workqueue.h>
 
-#define for_each_std_worker_pool(pool, cpu)				\
-	for ((pool) = &std_worker_pools(cpu)[0];			\
-	     (pool) < &std_worker_pools(cpu)[NR_STD_WORKER_POOLS]; (pool)++)
+#define assert_rcu_or_pool_mutex()					\
+	rcu_lockdep_assert(rcu_read_lock_sched_held() ||		\
+			   lockdep_is_held(&wq_pool_mutex),		\
+			   "sched RCU or wq_pool_mutex should be held")
 
-#define for_each_busy_worker(worker, i, pool)				\
-	hash_for_each(pool->busy_hash, i, worker, hentry)
+#define assert_rcu_or_wq_mutex(wq)					\
+	rcu_lockdep_assert(rcu_read_lock_sched_held() ||		\
+			   lockdep_is_held(&wq->mutex),			\
+			   "sched RCU or wq->mutex should be held")
 
-static inline int __next_wq_cpu(int cpu, const struct cpumask *mask,
-				unsigned int sw)
-{
-	if (cpu < nr_cpu_ids) {
-		if (sw & 1) {
-			cpu = cpumask_next(cpu, mask);
-			if (cpu < nr_cpu_ids)
-				return cpu;
-		}
-		if (sw & 2)
-			return WORK_CPU_UNBOUND;
-	}
-	return WORK_CPU_END;
-}
+#ifdef CONFIG_LOCKDEP
+#define assert_manager_or_pool_lock(pool)				\
+	WARN_ONCE(debug_locks &&					\
+		  !lockdep_is_held(&(pool)->manager_mutex) &&		\
+		  !lockdep_is_held(&(pool)->lock),			\
+		  "pool->manager_mutex or ->lock should be held")
+#else
+#define assert_manager_or_pool_lock(pool)	do { } while (0)
+#endif
 
-static inline int __next_pwq_cpu(int cpu, const struct cpumask *mask,
-				 struct workqueue_struct *wq)
-{
-	return __next_wq_cpu(cpu, mask, !(wq->flags & WQ_UNBOUND) ? 1 : 2);
-}
+#define for_each_cpu_worker_pool(pool, cpu)				\
+	for ((pool) = &per_cpu(cpu_worker_pools, cpu)[0];		\
+	     (pool) < &per_cpu(cpu_worker_pools, cpu)[NR_STD_WORKER_POOLS]; \
+	     (pool)++)
 
-/*
- * CPU iterators
+/**
+ * for_each_pool - iterate through all worker_pools in the system
+ * @pool: iteration cursor
+ * @pi: integer used for iteration
  *
- * An extra cpu number is defined using an invalid cpu number
- * (WORK_CPU_UNBOUND) to host workqueues which are not bound to any
- * specific CPU.  The following iterators are similar to for_each_*_cpu()
- * iterators but also considers the unbound CPU.
+ * This must be called either with wq_pool_mutex held or sched RCU read
+ * locked.  If the pool needs to be used beyond the locking in effect, the
+ * caller is responsible for guaranteeing that the pool stays online.
  *
- * for_each_wq_cpu()		: possible CPUs + WORK_CPU_UNBOUND
- * for_each_online_wq_cpu()	: online CPUs + WORK_CPU_UNBOUND
- * for_each_pwq_cpu()		: possible CPUs for bound workqueues,
- *				  WORK_CPU_UNBOUND for unbound workqueues
+ * The if/else clause exists only for the lockdep assertion and can be
+ * ignored.
  */
-#define for_each_wq_cpu(cpu)						\
-	for ((cpu) = __next_wq_cpu(-1, cpu_possible_mask, 3);		\
-	     (cpu) < WORK_CPU_END;					\
-	     (cpu) = __next_wq_cpu((cpu), cpu_possible_mask, 3))
+#define for_each_pool(pool, pi)						\
+	idr_for_each_entry(&worker_pool_idr, pool, pi)			\
+		if (({ assert_rcu_or_pool_mutex(); false; })) { }	\
+		else
 
-#define for_each_online_wq_cpu(cpu)					\
-	for ((cpu) = __next_wq_cpu(-1, cpu_online_mask, 3);		\
-	     (cpu) < WORK_CPU_END;					\
-	     (cpu) = __next_wq_cpu((cpu), cpu_online_mask, 3))
+/**
+ * for_each_pool_worker - iterate through all workers of a worker_pool
+ * @worker: iteration cursor
+ * @wi: integer used for iteration
+ * @pool: worker_pool to iterate workers of
+ *
+ * This must be called with either @pool->manager_mutex or ->lock held.
+ *
+ * The if/else clause exists only for the lockdep assertion and can be
+ * ignored.
+ */
+#define for_each_pool_worker(worker, wi, pool)				\
+	idr_for_each_entry(&(pool)->worker_idr, (worker), (wi))		\
+		if (({ assert_manager_or_pool_lock((pool)); false; })) { } \
+		else
 
-#define for_each_pwq_cpu(cpu, wq)					\
-	for ((cpu) = __next_pwq_cpu(-1, cpu_possible_mask, (wq));	\
-	     (cpu) < WORK_CPU_END;					\
-	     (cpu) = __next_pwq_cpu((cpu), cpu_possible_mask, (wq)))
+/**
+ * for_each_pwq - iterate through all pool_workqueues of the specified workqueue
+ * @pwq: iteration cursor
+ * @wq: the target workqueue
+ *
+ * This must be called either with wq->mutex held or sched RCU read locked.
+ * If the pwq needs to be used beyond the locking in effect, the caller is
+ * responsible for guaranteeing that the pwq stays online.
+ *
+ * The if/else clause exists only for the lockdep assertion and can be
+ * ignored.
+ */
+#define for_each_pwq(pwq, wq)						\
+	list_for_each_entry_rcu((pwq), &(wq)->pwqs, pwqs_node)		\
+		if (({ assert_rcu_or_wq_mutex(wq); false; })) { }	\
+		else
 
 #ifdef CONFIG_DEBUG_OBJECTS_WORK
 
@@ -419,77 +503,35 @@ static inline void debug_work_activate(struct work_struct *work) { }
 static inline void debug_work_deactivate(struct work_struct *work) { }
 #endif
 
-/* Serializes the accesses to the list of workqueues. */
-static DEFINE_SPINLOCK(workqueue_lock);
-static LIST_HEAD(workqueues);
-static bool workqueue_freezing;		/* W: have wqs started freezing? */
-
-/*
- * The CPU and unbound standard worker pools.  The unbound ones have
- * POOL_DISASSOCIATED set, and their workers have WORKER_UNBOUND set.
- */
-static DEFINE_PER_CPU_SHARED_ALIGNED(struct worker_pool [NR_STD_WORKER_POOLS],
-				     cpu_std_worker_pools);
-static struct worker_pool unbound_std_worker_pools[NR_STD_WORKER_POOLS];
-
-/* idr of all pools */
-static DEFINE_MUTEX(worker_pool_idr_mutex);
-static DEFINE_IDR(worker_pool_idr);
-
-static int worker_thread(void *__worker);
-
-static struct worker_pool *std_worker_pools(int cpu)
-{
-	if (cpu != WORK_CPU_UNBOUND)
-		return per_cpu(cpu_std_worker_pools, cpu);
-	else
-		return unbound_std_worker_pools;
-}
-
-static int std_worker_pool_pri(struct worker_pool *pool)
-{
-	return pool - std_worker_pools(pool->cpu);
-}
-
 /* allocate ID and assign it to @pool */
 static int worker_pool_assign_id(struct worker_pool *pool)
 {
 	int ret;
 
-	mutex_lock(&worker_pool_idr_mutex);
+	lockdep_assert_held(&wq_pool_mutex);
+
 	ret = idr_alloc(&worker_pool_idr, pool, 0, 0, GFP_KERNEL);
-	if (ret >= 0)
+	if (ret >= 0) {
 		pool->id = ret;
-	mutex_unlock(&worker_pool_idr_mutex);
-
-	return ret < 0 ? ret : 0;
+		return 0;
+	}
+	return ret;
 }
 
-/*
- * Lookup worker_pool by id.  The idr currently is built during boot and
- * never modified.  Don't worry about locking for now.
+/**
+ * unbound_pwq_by_node - return the unbound pool_workqueue for the given node
+ * @wq: the target workqueue
+ * @node: the node ID
+ *
+ * This must be called either with pwq_lock held or sched RCU read locked.
+ * If the pwq needs to be used beyond the locking in effect, the caller is
+ * responsible for guaranteeing that the pwq stays online.
  */
-static struct worker_pool *worker_pool_by_id(int pool_id)
-{
-	return idr_find(&worker_pool_idr, pool_id);
-}
-
-static struct worker_pool *get_std_worker_pool(int cpu, bool highpri)
-{
-	struct worker_pool *pools = std_worker_pools(cpu);
-
-	return &pools[highpri];
-}
-
-static struct pool_workqueue *get_pwq(unsigned int cpu,
-				      struct workqueue_struct *wq)
+static struct pool_workqueue *unbound_pwq_by_node(struct workqueue_struct *wq,
+						  int node)
 {
-	if (!(wq->flags & WQ_UNBOUND)) {
-		if (likely(cpu < nr_cpu_ids))
-			return per_cpu_ptr(wq->pool_wq.pcpu, cpu);
-	} else if (likely(cpu == WORK_CPU_UNBOUND))
-		return wq->pool_wq.single;
-	return NULL;
+	assert_rcu_or_wq_mutex(wq);
+	return rcu_dereference_raw(wq->numa_pwq_tbl[node]);
 }
 
 static unsigned int work_color_to_flags(int color)
@@ -531,7 +573,7 @@ static int work_next_color(int color)
 static inline void set_work_data(struct work_struct *work, unsigned long data,
 				 unsigned long flags)
 {
-	BUG_ON(!work_pending(work));
+	WARN_ON_ONCE(!work_pending(work));
 	atomic_long_set(&work->data, data | flags | work_static(work));
 }
 
@@ -583,13 +625,23 @@ static struct pool_workqueue *get_work_pwq(struct work_struct *work)
  * @work: the work item of interest
  *
  * Return the worker_pool @work was last associated with.  %NULL if none.
+ *
+ * Pools are created and destroyed under wq_pool_mutex, and allows read
+ * access under sched-RCU read lock.  As such, this function should be
+ * called under wq_pool_mutex or with preemption disabled.
+ *
+ * All fields of the returned pool are accessible as long as the above
+ * mentioned locking is in effect.  If the returned pool needs to be used
+ * beyond the critical section, the caller is responsible for ensuring the
+ * returned pool is and stays online.
  */
 static struct worker_pool *get_work_pool(struct work_struct *work)
 {
 	unsigned long data = atomic_long_read(&work->data);
-	struct worker_pool *pool;
 	int pool_id;
 
+	assert_rcu_or_pool_mutex();
+
 	if (data & WORK_STRUCT_PWQ)
 		return ((struct pool_workqueue *)
 			(data & WORK_STRUCT_WQ_DATA_MASK))->pool;
@@ -598,9 +650,7 @@ static struct worker_pool *get_work_pool(struct work_struct *work)
 	if (pool_id == WORK_OFFQ_POOL_NONE)
 		return NULL;
 
-	pool = worker_pool_by_id(pool_id);
-	WARN_ON_ONCE(!pool);
-	return pool;
+	return idr_find(&worker_pool_idr, pool_id);
 }
 
 /**
@@ -689,7 +739,7 @@ static bool need_to_manage_workers(struct worker_pool *pool)
 /* Do we have too many workers and should some go away? */
 static bool too_many_workers(struct worker_pool *pool)
 {
-	bool managing = pool->flags & POOL_MANAGING_WORKERS;
+	bool managing = mutex_is_locked(&pool->manager_arb);
 	int nr_idle = pool->nr_idle + managing; /* manager is considered idle */
 	int nr_busy = pool->nr_workers - nr_idle;
 
@@ -744,7 +794,7 @@ static void wake_up_worker(struct worker_pool *pool)
  * CONTEXT:
  * spin_lock_irq(rq->lock)
  */
-void wq_worker_waking_up(struct task_struct *task, unsigned int cpu)
+void wq_worker_waking_up(struct task_struct *task, int cpu)
 {
 	struct worker *worker = kthread_data(task);
 
@@ -769,8 +819,7 @@ void wq_worker_waking_up(struct task_struct *task, unsigned int cpu)
  * RETURNS:
  * Worker task on @cpu to wake up, %NULL if none.
  */
-struct task_struct *wq_worker_sleeping(struct task_struct *task,
-				       unsigned int cpu)
+struct task_struct *wq_worker_sleeping(struct task_struct *task, int cpu)
 {
 	struct worker *worker = kthread_data(task), *to_wakeup = NULL;
 	struct worker_pool *pool;
@@ -786,7 +835,8 @@ struct task_struct *wq_worker_sleeping(struct task_struct *task,
 	pool = worker->pool;
 
 	/* this can only happen on the local cpu */
-	BUG_ON(cpu != raw_smp_processor_id());
+	if (WARN_ON_ONCE(cpu != raw_smp_processor_id()))
+		return NULL;
 
 	/*
 	 * The counterpart of the following dec_and_test, implied mb,
@@ -891,13 +941,12 @@ static inline void worker_clr_flags(struct worker *worker, unsigned int flags)
  * recycled work item as currently executing and make it wait until the
  * current execution finishes, introducing an unwanted dependency.
  *
- * This function checks the work item address, work function and workqueue
- * to avoid false positives.  Note that this isn't complete as one may
- * construct a work function which can introduce dependency onto itself
- * through a recycled work item.  Well, if somebody wants to shoot oneself
- * in the foot that badly, there's only so much we can do, and if such
- * deadlock actually occurs, it should be easy to locate the culprit work
- * function.
+ * This function checks the work item address and work function to avoid
+ * false positives.  Note that this isn't complete as one may construct a
+ * work function which can introduce dependency onto itself through a
+ * recycled work item.  Well, if somebody wants to shoot oneself in the
+ * foot that badly, there's only so much we can do, and if such deadlock
+ * actually occurs, it should be easy to locate the culprit work function.
  *
  * CONTEXT:
  * spin_lock_irq(pool->lock).
@@ -961,6 +1010,64 @@ static void move_linked_works(struct work_struct *work, struct list_head *head,
 		*nextp = n;
 }
 
+/**
+ * get_pwq - get an extra reference on the specified pool_workqueue
+ * @pwq: pool_workqueue to get
+ *
+ * Obtain an extra reference on @pwq.  The caller should guarantee that
+ * @pwq has positive refcnt and be holding the matching pool->lock.
+ */
+static void get_pwq(struct pool_workqueue *pwq)
+{
+	lockdep_assert_held(&pwq->pool->lock);
+	WARN_ON_ONCE(pwq->refcnt <= 0);
+	pwq->refcnt++;
+}
+
+/**
+ * put_pwq - put a pool_workqueue reference
+ * @pwq: pool_workqueue to put
+ *
+ * Drop a reference of @pwq.  If its refcnt reaches zero, schedule its
+ * destruction.  The caller should be holding the matching pool->lock.
+ */
+static void put_pwq(struct pool_workqueue *pwq)
+{
+	lockdep_assert_held(&pwq->pool->lock);
+	if (likely(--pwq->refcnt))
+		return;
+	if (WARN_ON_ONCE(!(pwq->wq->flags & WQ_UNBOUND)))
+		return;
+	/*
+	 * @pwq can't be released under pool->lock, bounce to
+	 * pwq_unbound_release_workfn().  This never recurses on the same
+	 * pool->lock as this path is taken only for unbound workqueues and
+	 * the release work item is scheduled on a per-cpu workqueue.  To
+	 * avoid lockdep warning, unbound pool->locks are given lockdep
+	 * subclass of 1 in get_unbound_pool().
+	 */
+	schedule_work(&pwq->unbound_release_work);
+}
+
+/**
+ * put_pwq_unlocked - put_pwq() with surrounding pool lock/unlock
+ * @pwq: pool_workqueue to put (can be %NULL)
+ *
+ * put_pwq() with locking.  This function also allows %NULL @pwq.
+ */
+static void put_pwq_unlocked(struct pool_workqueue *pwq)
+{
+	if (pwq) {
+		/*
+		 * As both pwqs and pools are sched-RCU protected, the
+		 * following lock operations are safe.
+		 */
+		spin_lock_irq(&pwq->pool->lock);
+		put_pwq(pwq);
+		spin_unlock_irq(&pwq->pool->lock);
+	}
+}
+
 static void pwq_activate_delayed_work(struct work_struct *work)
 {
 	struct pool_workqueue *pwq = get_work_pwq(work);
@@ -992,9 +1099,9 @@ static void pwq_activate_first_delayed(struct pool_workqueue *pwq)
  */
 static void pwq_dec_nr_in_flight(struct pool_workqueue *pwq, int color)
 {
-	/* ignore uncolored works */
+	/* uncolored work items don't participate in flushing or nr_active */
 	if (color == WORK_NO_COLOR)
-		return;
+		goto out_put;
 
 	pwq->nr_in_flight[color]--;
 
@@ -1007,11 +1114,11 @@ static void pwq_dec_nr_in_flight(struct pool_workqueue *pwq, int color)
 
 	/* is flush in progress and are we at the flushing tip? */
 	if (likely(pwq->flush_color != color))
-		return;
+		goto out_put;
 
 	/* are there still in-flight works? */
 	if (pwq->nr_in_flight[color])
-		return;
+		goto out_put;
 
 	/* this pwq is done, clear flush_color */
 	pwq->flush_color = -1;
@@ -1022,6 +1129,8 @@ static void pwq_dec_nr_in_flight(struct pool_workqueue *pwq, int color)
 	 */
 	if (atomic_dec_and_test(&pwq->wq->nr_pwqs_to_flush))
 		complete(&pwq->wq->first_flusher->done);
+out_put:
+	put_pwq(pwq);
 }
 
 /**
@@ -1144,11 +1253,12 @@ static void insert_work(struct pool_workqueue *pwq, struct work_struct *work,
 	/* we own @work, set data and link */
 	set_work_pwq(work, pwq, extra_flags);
 	list_add_tail(&work->entry, head);
+	get_pwq(pwq);
 
 	/*
-	 * Ensure either worker_sched_deactivated() sees the above
-	 * list_add_tail() or we see zero nr_running to avoid workers
-	 * lying around lazily while there are works to be processed.
+	 * Ensure either wq_worker_sleeping() sees the above
+	 * list_add_tail() or we see zero nr_running to avoid workers lying
+	 * around lazily while there are works to be processed.
 	 */
 	smp_mb();
 
@@ -1172,10 +1282,11 @@ static bool is_chained_work(struct workqueue_struct *wq)
 	return worker && worker->current_pwq->wq == wq;
 }
 
-static void __queue_work(unsigned int cpu, struct workqueue_struct *wq,
+static void __queue_work(int cpu, struct workqueue_struct *wq,
 			 struct work_struct *work)
 {
 	struct pool_workqueue *pwq;
+	struct worker_pool *last_pool;
 	struct list_head *worklist;
 	unsigned int work_flags;
 	unsigned int req_cpu = cpu;
@@ -1191,48 +1302,62 @@ 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_DRAINING) &&
+	if (unlikely(wq->flags & __WQ_DRAINING) &&
 	    WARN_ON_ONCE(!is_chained_work(wq)))
 		return;
+retry:
+	if (req_cpu == WORK_CPU_UNBOUND)
+		cpu = raw_smp_processor_id();
 
-	/* determine the pwq to use */
-	if (!(wq->flags & WQ_UNBOUND)) {
-		struct worker_pool *last_pool;
-
-		if (cpu == WORK_CPU_UNBOUND)
-			cpu = raw_smp_processor_id();
-
-		/*
-		 * It's multi cpu.  If @work was previously on a different
-		 * cpu, it might still be running there, in which case the
-		 * work needs to be queued on that cpu to guarantee
-		 * non-reentrancy.
-		 */
-		pwq = get_pwq(cpu, wq);
-		last_pool = get_work_pool(work);
+	/* pwq which will be used unless @work is executing elsewhere */
+	if (!(wq->flags & WQ_UNBOUND))
+		pwq = per_cpu_ptr(wq->cpu_pwqs, cpu);
+	else
+		pwq = unbound_pwq_by_node(wq, cpu_to_node(cpu));
 
-		if (last_pool && last_pool != pwq->pool) {
-			struct worker *worker;
+	/*
+	 * If @work was previously on a different pool, it might still be
+	 * running there, in which case the work needs to be queued on that
+	 * pool to guarantee non-reentrancy.
+	 */
+	last_pool = get_work_pool(work);
+	if (last_pool && last_pool != pwq->pool) {
+		struct worker *worker;
 
-			spin_lock(&last_pool->lock);
+		spin_lock(&last_pool->lock);
 
-			worker = find_worker_executing_work(last_pool, work);
+		worker = find_worker_executing_work(last_pool, work);
 
-			if (worker && worker->current_pwq->wq == wq) {
-				pwq = get_pwq(last_pool->cpu, wq);
-			} else {
-				/* meh... not running there, queue here */
-				spin_unlock(&last_pool->lock);
-				spin_lock(&pwq->pool->lock);
-			}
+		if (worker && worker->current_pwq->wq == wq) {
+			pwq = worker->current_pwq;
 		} else {
+			/* meh... not running there, queue here */
+			spin_unlock(&last_pool->lock);
 			spin_lock(&pwq->pool->lock);
 		}
 	} else {
-		pwq = get_pwq(WORK_CPU_UNBOUND, wq);
 		spin_lock(&pwq->pool->lock);
 	}
 
+	/*
+	 * pwq is determined and locked.  For unbound pools, we could have
+	 * raced with pwq release and it could already be dead.  If its
+	 * refcnt is zero, repeat pwq selection.  Note that pwqs never die
+	 * without another pwq replacing it in the numa_pwq_tbl or while
+	 * work items are executing on it, so the retrying is guaranteed to
+	 * make forward-progress.
+	 */
+	if (unlikely(!pwq->refcnt)) {
+		if (wq->flags & WQ_UNBOUND) {
+			spin_unlock(&pwq->pool->lock);
+			cpu_relax();
+			goto retry;
+		}
+		/* oops */
+		WARN_ONCE(true, "workqueue: per-cpu pwq for %s on cpu%d has 0 refcnt",
+			  wq->name, cpu);
+	}
+
 	/* pwq determined, queue */
 	trace_workqueue_queue_work(req_cpu, pwq, work);
 
@@ -1287,22 +1412,6 @@ bool queue_work_on(int cpu, struct workqueue_struct *wq,
 }
 EXPORT_SYMBOL_GPL(queue_work_on);
 
-/**
- * queue_work - queue work on a workqueue
- * @wq: workqueue to use
- * @work: work to queue
- *
- * Returns %false if @work was already on a queue, %true otherwise.
- *
- * We queue the work to the CPU on which it was submitted, but if the CPU dies
- * it can be processed by another CPU.
- */
-bool queue_work(struct workqueue_struct *wq, struct work_struct *work)
-{
-	return queue_work_on(WORK_CPU_UNBOUND, wq, work);
-}
-EXPORT_SYMBOL_GPL(queue_work);
-
 void delayed_work_timer_fn(unsigned long __data)
 {
 	struct delayed_work *dwork = (struct delayed_work *)__data;
@@ -1378,21 +1487,6 @@ bool queue_delayed_work_on(int cpu, struct workqueue_struct *wq,
 EXPORT_SYMBOL_GPL(queue_delayed_work_on);
 
 /**
- * queue_delayed_work - queue work on a workqueue after delay
- * @wq: workqueue to use
- * @dwork: delayable work to queue
- * @delay: number of jiffies to wait before queueing
- *
- * Equivalent to queue_delayed_work_on() but tries to use the local CPU.
- */
-bool queue_delayed_work(struct workqueue_struct *wq,
-			struct delayed_work *dwork, unsigned long delay)
-{
-	return queue_delayed_work_on(WORK_CPU_UNBOUND, wq, dwork, delay);
-}
-EXPORT_SYMBOL_GPL(queue_delayed_work);
-
-/**
  * mod_delayed_work_on - modify delay of or queue a delayed work on specific CPU
  * @cpu: CPU number to execute work on
  * @wq: workqueue to use
@@ -1431,21 +1525,6 @@ bool mod_delayed_work_on(int cpu, struct workqueue_struct *wq,
 EXPORT_SYMBOL_GPL(mod_delayed_work_on);
 
 /**
- * mod_delayed_work - modify delay of or queue a delayed work
- * @wq: workqueue to use
- * @dwork: work to queue
- * @delay: number of jiffies to wait before queueing
- *
- * mod_delayed_work_on() on local CPU.
- */
-bool mod_delayed_work(struct workqueue_struct *wq, struct delayed_work *dwork,
-		      unsigned long delay)
-{
-	return mod_delayed_work_on(WORK_CPU_UNBOUND, wq, dwork, delay);
-}
-EXPORT_SYMBOL_GPL(mod_delayed_work);
-
-/**
  * worker_enter_idle - enter idle state
  * @worker: worker which is entering idle state
  *
@@ -1459,9 +1538,10 @@ static void worker_enter_idle(struct worker *worker)
 {
 	struct worker_pool *pool = worker->pool;
 
-	BUG_ON(worker->flags & WORKER_IDLE);
-	BUG_ON(!list_empty(&worker->entry) &&
-	       (worker->hentry.next || worker->hentry.pprev));
+	if (WARN_ON_ONCE(worker->flags & WORKER_IDLE) ||
+	    WARN_ON_ONCE(!list_empty(&worker->entry) &&
+			 (worker->hentry.next || worker->hentry.pprev)))
+		return;
 
 	/* can't use worker_set_flags(), also called from start_worker() */
 	worker->flags |= WORKER_IDLE;
@@ -1498,22 +1578,25 @@ static void worker_leave_idle(struct worker *worker)
 {
 	struct worker_pool *pool = worker->pool;
 
-	BUG_ON(!(worker->flags & WORKER_IDLE));
+	if (WARN_ON_ONCE(!(worker->flags & WORKER_IDLE)))
+		return;
 	worker_clr_flags(worker, WORKER_IDLE);
 	pool->nr_idle--;
 	list_del_init(&worker->entry);
 }
 
 /**
- * worker_maybe_bind_and_lock - bind worker to its cpu if possible and lock pool
- * @worker: self
+ * worker_maybe_bind_and_lock - try to bind %current to worker_pool and lock it
+ * @pool: target worker_pool
+ *
+ * Bind %current to the cpu of @pool if it is associated and lock @pool.
  *
  * Works which are scheduled while the cpu is online must at least be
  * scheduled to a worker which is bound to the cpu so that if they are
  * flushed from cpu callbacks while cpu is going down, they are
  * guaranteed to execute on the cpu.
  *
- * This function is to be used by rogue workers and rescuers to bind
+ * This function is to be used by unbound workers and rescuers to bind
  * themselves to the target cpu and may race with cpu going down or
  * coming online.  kthread_bind() can't be used because it may put the
  * worker to already dead cpu and set_cpus_allowed_ptr() can't be used
@@ -1534,12 +1617,9 @@ static void worker_leave_idle(struct worker *worker)
  * %true if the associated pool is online (@worker is successfully
  * bound), %false if offline.
  */
-static bool worker_maybe_bind_and_lock(struct worker *worker)
+static bool worker_maybe_bind_and_lock(struct worker_pool *pool)
 __acquires(&pool->lock)
 {
-	struct worker_pool *pool = worker->pool;
-	struct task_struct *task = worker->task;
-
 	while (true) {
 		/*
 		 * The following call may fail, succeed or succeed
@@ -1548,14 +1628,13 @@ __acquires(&pool->lock)
 		 * against POOL_DISASSOCIATED.
 		 */
 		if (!(pool->flags & POOL_DISASSOCIATED))
-			set_cpus_allowed_ptr(task, get_cpu_mask(pool->cpu));
+			set_cpus_allowed_ptr(current, pool->attrs->cpumask);
 
 		spin_lock_irq(&pool->lock);
 		if (pool->flags & POOL_DISASSOCIATED)
 			return false;
-		if (task_cpu(task) == pool->cpu &&
-		    cpumask_equal(&current->cpus_allowed,
-				  get_cpu_mask(pool->cpu)))
+		if (task_cpu(current) == pool->cpu &&
+		    cpumask_equal(&current->cpus_allowed, pool->attrs->cpumask))
 			return true;
 		spin_unlock_irq(&pool->lock);
 
@@ -1570,108 +1649,6 @@ __acquires(&pool->lock)
 	}
 }
 
-/*
- * Rebind an idle @worker to its CPU.  worker_thread() will test
- * list_empty(@worker->entry) before leaving idle and call this function.
- */
-static void idle_worker_rebind(struct worker *worker)
-{
-	/* CPU may go down again inbetween, clear UNBOUND only on success */
-	if (worker_maybe_bind_and_lock(worker))
-		worker_clr_flags(worker, WORKER_UNBOUND);
-
-	/* rebind complete, become available again */
-	list_add(&worker->entry, &worker->pool->idle_list);
-	spin_unlock_irq(&worker->pool->lock);
-}
-
-/*
- * Function for @worker->rebind.work used to rebind unbound busy workers to
- * the associated cpu which is coming back online.  This is scheduled by
- * cpu up but can race with other cpu hotplug operations and may be
- * executed twice without intervening cpu down.
- */
-static void busy_worker_rebind_fn(struct work_struct *work)
-{
-	struct worker *worker = container_of(work, struct worker, rebind_work);
-
-	if (worker_maybe_bind_and_lock(worker))
-		worker_clr_flags(worker, WORKER_UNBOUND);
-
-	spin_unlock_irq(&worker->pool->lock);
-}
-
-/**
- * rebind_workers - rebind all workers of a pool to the associated CPU
- * @pool: pool of interest
- *
- * @pool->cpu is coming online.  Rebind all workers to the CPU.  Rebinding
- * is different for idle and busy ones.
- *
- * Idle ones will be removed from the idle_list and woken up.  They will
- * add themselves back after completing rebind.  This ensures that the
- * idle_list doesn't contain any unbound workers when re-bound busy workers
- * try to perform local wake-ups for concurrency management.
- *
- * Busy workers can rebind after they finish their current work items.
- * Queueing the rebind work item at the head of the scheduled list is
- * enough.  Note that nr_running will be properly bumped as busy workers
- * rebind.
- *
- * On return, all non-manager workers are scheduled for rebind - see
- * manage_workers() for the manager special case.  Any idle worker
- * including the manager will not appear on @idle_list until rebind is
- * complete, making local wake-ups safe.
- */
-static void rebind_workers(struct worker_pool *pool)
-{
-	struct worker *worker, *n;
-	int i;
-
-	lockdep_assert_held(&pool->assoc_mutex);
-	lockdep_assert_held(&pool->lock);
-
-	/* dequeue and kick idle ones */
-	list_for_each_entry_safe(worker, n, &pool->idle_list, entry) {
-		/*
-		 * idle workers should be off @pool->idle_list until rebind
-		 * is complete to avoid receiving premature local wake-ups.
-		 */
-		list_del_init(&worker->entry);
-
-		/*
-		 * worker_thread() will see the above dequeuing and call
-		 * idle_worker_rebind().
-		 */
-		wake_up_process(worker->task);
-	}
-
-	/* rebind busy workers */
-	for_each_busy_worker(worker, i, pool) {
-		struct work_struct *rebind_work = &worker->rebind_work;
-		struct workqueue_struct *wq;
-
-		if (test_and_set_bit(WORK_STRUCT_PENDING_BIT,
-				     work_data_bits(rebind_work)))
-			continue;
-
-		debug_work_activate(rebind_work);
-
-		/*
-		 * wq doesn't really matter but let's keep @worker->pool
-		 * and @pwq->pool consistent for sanity.
-		 */
-		if (std_worker_pool_pri(worker->pool))
-			wq = system_highpri_wq;
-		else
-			wq = system_wq;
-
-		insert_work(get_pwq(pool->cpu, wq), rebind_work,
-			    worker->scheduled.next,
-			    work_color_to_flags(WORK_NO_COLOR));
-	}
-}
-
 static struct worker *alloc_worker(void)
 {
 	struct worker *worker;
@@ -1680,7 +1657,6 @@ static struct worker *alloc_worker(void)
 	if (worker) {
 		INIT_LIST_HEAD(&worker->entry);
 		INIT_LIST_HEAD(&worker->scheduled);
-		INIT_WORK(&worker->rebind_work, busy_worker_rebind_fn);
 		/* on creation a worker is in !idle && prep state */
 		worker->flags = WORKER_PREP;
 	}
@@ -1703,18 +1679,25 @@ static struct worker *alloc_worker(void)
  */
 static struct worker *create_worker(struct worker_pool *pool)
 {
-	const char *pri = std_worker_pool_pri(pool) ? "H" : "";
 	struct worker *worker = NULL;
 	int id = -1;
+	char id_buf[16];
 
+	lockdep_assert_held(&pool->manager_mutex);
+
+	/*
+	 * ID is needed to determine kthread name.  Allocate ID first
+	 * without installing the pointer.
+	 */
+	idr_preload(GFP_KERNEL);
 	spin_lock_irq(&pool->lock);
-	while (ida_get_new(&pool->worker_ida, &id)) {
-		spin_unlock_irq(&pool->lock);
-		if (!ida_pre_get(&pool->worker_ida, GFP_KERNEL))
-			goto fail;
-		spin_lock_irq(&pool->lock);
-	}
+
+	id = idr_alloc(&pool->worker_idr, NULL, 0, 0, GFP_NOWAIT);
+
 	spin_unlock_irq(&pool->lock);
+	idr_preload_end();
+	if (id < 0)
+		goto fail;
 
 	worker = alloc_worker();
 	if (!worker)
@@ -1723,40 +1706,46 @@ static struct worker *create_worker(struct worker_pool *pool)
 	worker->pool = pool;
 	worker->id = id;
 
-	if (pool->cpu != WORK_CPU_UNBOUND)
-		worker->task = kthread_create_on_node(worker_thread,
-					worker, cpu_to_node(pool->cpu),
-					"kworker/%u:%d%s", pool->cpu, id, pri);
+	if (pool->cpu >= 0)
+		snprintf(id_buf, sizeof(id_buf), "%d:%d%s", pool->cpu, id,
+			 pool->attrs->nice < 0  ? "H" : "");
 	else
-		worker->task = kthread_create(worker_thread, worker,
-					      "kworker/u:%d%s", id, pri);
+		snprintf(id_buf, sizeof(id_buf), "u%d:%d", pool->id, id);
+
+	worker->task = kthread_create_on_node(worker_thread, worker, pool->node,
+					      "kworker/%s", id_buf);
 	if (IS_ERR(worker->task))
 		goto fail;
 
-	if (std_worker_pool_pri(pool))
-		set_user_nice(worker->task, HIGHPRI_NICE_LEVEL);
+	/*
+	 * set_cpus_allowed_ptr() will fail if the cpumask doesn't have any
+	 * online CPUs.  It'll be re-applied when any of the CPUs come up.
+	 */
+	set_user_nice(worker->task, pool->attrs->nice);
+	set_cpus_allowed_ptr(worker->task, pool->attrs->cpumask);
+
+	/* prevent userland from meddling with cpumask of workqueue workers */
+	worker->task->flags |= PF_NO_SETAFFINITY;
 
 	/*
-	 * Determine CPU binding of the new worker depending on
-	 * %POOL_DISASSOCIATED.  The caller is responsible for ensuring the
-	 * flag remains stable across this function.  See the comments
-	 * above the flag definition for details.
-	 *
-	 * As an unbound worker may later become a regular one if CPU comes
-	 * online, make sure every worker has %PF_THREAD_BOUND set.
+	 * The caller is responsible for ensuring %POOL_DISASSOCIATED
+	 * remains stable across this function.  See the comments above the
+	 * flag definition for details.
 	 */
-	if (!(pool->flags & POOL_DISASSOCIATED)) {
-		kthread_bind(worker->task, pool->cpu);
-	} else {
-		worker->task->flags |= PF_THREAD_BOUND;
+	if (pool->flags & POOL_DISASSOCIATED)
 		worker->flags |= WORKER_UNBOUND;
-	}
+
+	/* successful, commit the pointer to idr */
+	spin_lock_irq(&pool->lock);
+	idr_replace(&pool->worker_idr, worker, worker->id);
+	spin_unlock_irq(&pool->lock);
 
 	return worker;
+
 fail:
 	if (id >= 0) {
 		spin_lock_irq(&pool->lock);
-		ida_remove(&pool->worker_ida, id);
+		idr_remove(&pool->worker_idr, id);
 		spin_unlock_irq(&pool->lock);
 	}
 	kfree(worker);
@@ -1781,38 +1770,66 @@ static void start_worker(struct worker *worker)
 }
 
 /**
- * destroy_worker - destroy a workqueue worker
- * @worker: worker to be destroyed
- *
- * Destroy @worker and adjust @pool stats accordingly.
+ * create_and_start_worker - create and start a worker for a pool
+ * @pool: the target pool
  *
- * CONTEXT:
- * spin_lock_irq(pool->lock) which is released and regrabbed.
+ * Grab the managership of @pool and create and start a new worker for it.
  */
-static void destroy_worker(struct worker *worker)
+static int create_and_start_worker(struct worker_pool *pool)
 {
-	struct worker_pool *pool = worker->pool;
-	int id = worker->id;
+	struct worker *worker;
 
-	/* sanity check frenzy */
-	BUG_ON(worker->current_work);
-	BUG_ON(!list_empty(&worker->scheduled));
+	mutex_lock(&pool->manager_mutex);
 
-	if (worker->flags & WORKER_STARTED)
-		pool->nr_workers--;
+	worker = create_worker(pool);
+	if (worker) {
+		spin_lock_irq(&pool->lock);
+		start_worker(worker);
+		spin_unlock_irq(&pool->lock);
+	}
+
+	mutex_unlock(&pool->manager_mutex);
+
+	return worker ? 0 : -ENOMEM;
+}
+
+/**
+ * destroy_worker - destroy a workqueue worker
+ * @worker: worker to be destroyed
+ *
+ * Destroy @worker and adjust @pool stats accordingly.
+ *
+ * CONTEXT:
+ * spin_lock_irq(pool->lock) which is released and regrabbed.
+ */
+static void destroy_worker(struct worker *worker)
+{
+	struct worker_pool *pool = worker->pool;
+
+	lockdep_assert_held(&pool->manager_mutex);
+	lockdep_assert_held(&pool->lock);
+
+	/* sanity check frenzy */
+	if (WARN_ON(worker->current_work) ||
+	    WARN_ON(!list_empty(&worker->scheduled)))
+		return;
+
+	if (worker->flags & WORKER_STARTED)
+		pool->nr_workers--;
 	if (worker->flags & WORKER_IDLE)
 		pool->nr_idle--;
 
 	list_del_init(&worker->entry);
 	worker->flags |= WORKER_DIE;
 
+	idr_remove(&pool->worker_idr, worker->id);
+
 	spin_unlock_irq(&pool->lock);
 
 	kthread_stop(worker->task);
 	kfree(worker);
 
 	spin_lock_irq(&pool->lock);
-	ida_remove(&pool->worker_ida, id);
 }
 
 static void idle_worker_timeout(unsigned long __pool)
@@ -1841,23 +1858,21 @@ static void idle_worker_timeout(unsigned long __pool)
 	spin_unlock_irq(&pool->lock);
 }
 
-static bool send_mayday(struct work_struct *work)
+static void send_mayday(struct work_struct *work)
 {
 	struct pool_workqueue *pwq = get_work_pwq(work);
 	struct workqueue_struct *wq = pwq->wq;
-	unsigned int cpu;
 
-	if (!(wq->flags & WQ_RESCUER))
-		return false;
+	lockdep_assert_held(&wq_mayday_lock);
+
+	if (!wq->rescuer)
+		return;
 
 	/* mayday mayday mayday */
-	cpu = pwq->pool->cpu;
-	/* WORK_CPU_UNBOUND can't be set in cpumask, use cpu 0 instead */
-	if (cpu == WORK_CPU_UNBOUND)
-		cpu = 0;
-	if (!mayday_test_and_set_cpu(cpu, wq->mayday_mask))
+	if (list_empty(&pwq->mayday_node)) {
+		list_add_tail(&pwq->mayday_node, &wq->maydays);
 		wake_up_process(wq->rescuer->task);
-	return true;
+	}
 }
 
 static void pool_mayday_timeout(unsigned long __pool)
@@ -1865,7 +1880,8 @@ static void pool_mayday_timeout(unsigned long __pool)
 	struct worker_pool *pool = (void *)__pool;
 	struct work_struct *work;
 
-	spin_lock_irq(&pool->lock);
+	spin_lock_irq(&wq_mayday_lock);		/* for wq->maydays */
+	spin_lock(&pool->lock);
 
 	if (need_to_create_worker(pool)) {
 		/*
@@ -1878,7 +1894,8 @@ static void pool_mayday_timeout(unsigned long __pool)
 			send_mayday(work);
 	}
 
-	spin_unlock_irq(&pool->lock);
+	spin_unlock(&pool->lock);
+	spin_unlock_irq(&wq_mayday_lock);
 
 	mod_timer(&pool->mayday_timer, jiffies + MAYDAY_INTERVAL);
 }
@@ -1893,8 +1910,8 @@ static void pool_mayday_timeout(unsigned long __pool)
  * sent to all rescuers with works scheduled on @pool to resolve
  * possible allocation deadlock.
  *
- * On return, need_to_create_worker() is guaranteed to be false and
- * may_start_working() true.
+ * On return, need_to_create_worker() is guaranteed to be %false and
+ * may_start_working() %true.
  *
  * LOCKING:
  * spin_lock_irq(pool->lock) which may be released and regrabbed
@@ -1902,7 +1919,7 @@ static void pool_mayday_timeout(unsigned long __pool)
  * manager.
  *
  * RETURNS:
- * false if no action was taken and pool->lock stayed locked, true
+ * %false if no action was taken and pool->lock stayed locked, %true
  * otherwise.
  */
 static bool maybe_create_worker(struct worker_pool *pool)
@@ -1925,7 +1942,8 @@ restart:
 			del_timer_sync(&pool->mayday_timer);
 			spin_lock_irq(&pool->lock);
 			start_worker(worker);
-			BUG_ON(need_to_create_worker(pool));
+			if (WARN_ON_ONCE(need_to_create_worker(pool)))
+				goto restart;
 			return true;
 		}
 
@@ -1958,7 +1976,7 @@ restart:
  * multiple times.  Called only from manager.
  *
  * RETURNS:
- * false if no action was taken and pool->lock stayed locked, true
+ * %false if no action was taken and pool->lock stayed locked, %true
  * otherwise.
  */
 static bool maybe_destroy_workers(struct worker_pool *pool)
@@ -2009,42 +2027,37 @@ static bool manage_workers(struct worker *worker)
 	struct worker_pool *pool = worker->pool;
 	bool ret = false;
 
-	if (pool->flags & POOL_MANAGING_WORKERS)
+	/*
+	 * Managership is governed by two mutexes - manager_arb and
+	 * manager_mutex.  manager_arb handles arbitration of manager role.
+	 * Anyone who successfully grabs manager_arb wins the arbitration
+	 * and becomes the manager.  mutex_trylock() on pool->manager_arb
+	 * failure while holding pool->lock reliably indicates that someone
+	 * else is managing the pool and the worker which failed trylock
+	 * can proceed to executing work items.  This means that anyone
+	 * grabbing manager_arb is responsible for actually performing
+	 * manager duties.  If manager_arb is grabbed and released without
+	 * actual management, the pool may stall indefinitely.
+	 *
+	 * manager_mutex is used for exclusion of actual management
+	 * operations.  The holder of manager_mutex can be sure that none
+	 * of management operations, including creation and destruction of
+	 * workers, won't take place until the mutex is released.  Because
+	 * manager_mutex doesn't interfere with manager role arbitration,
+	 * it is guaranteed that the pool's management, while may be
+	 * delayed, won't be disturbed by someone else grabbing
+	 * manager_mutex.
+	 */
+	if (!mutex_trylock(&pool->manager_arb))
 		return ret;
 
-	pool->flags |= POOL_MANAGING_WORKERS;
-
 	/*
-	 * To simplify both worker management and CPU hotplug, hold off
-	 * management while hotplug is in progress.  CPU hotplug path can't
-	 * grab %POOL_MANAGING_WORKERS to achieve this because that can
-	 * lead to idle worker depletion (all become busy thinking someone
-	 * else is managing) which in turn can result in deadlock under
-	 * extreme circumstances.  Use @pool->assoc_mutex to synchronize
-	 * manager against CPU hotplug.
-	 *
-	 * assoc_mutex would always be free unless CPU hotplug is in
-	 * progress.  trylock first without dropping @pool->lock.
+	 * With manager arbitration won, manager_mutex would be free in
+	 * most cases.  trylock first without dropping @pool->lock.
 	 */
-	if (unlikely(!mutex_trylock(&pool->assoc_mutex))) {
+	if (unlikely(!mutex_trylock(&pool->manager_mutex))) {
 		spin_unlock_irq(&pool->lock);
-		mutex_lock(&pool->assoc_mutex);
-		/*
-		 * CPU hotplug could have happened while we were waiting
-		 * for assoc_mutex.  Hotplug itself can't handle us
-		 * because manager isn't either on idle or busy list, and
-		 * @pool's state and ours could have deviated.
-		 *
-		 * As hotplug is now excluded via assoc_mutex, we can
-		 * simply try to bind.  It will succeed or fail depending
-		 * on @pool's current state.  Try it and adjust
-		 * %WORKER_UNBOUND accordingly.
-		 */
-		if (worker_maybe_bind_and_lock(worker))
-			worker->flags &= ~WORKER_UNBOUND;
-		else
-			worker->flags |= WORKER_UNBOUND;
-
+		mutex_lock(&pool->manager_mutex);
 		ret = true;
 	}
 
@@ -2057,8 +2070,8 @@ static bool manage_workers(struct worker *worker)
 	ret |= maybe_destroy_workers(pool);
 	ret |= maybe_create_worker(pool);
 
-	pool->flags &= ~POOL_MANAGING_WORKERS;
-	mutex_unlock(&pool->assoc_mutex);
+	mutex_unlock(&pool->manager_mutex);
+	mutex_unlock(&pool->manager_arb);
 	return ret;
 }
 
@@ -2212,11 +2225,11 @@ static void process_scheduled_works(struct worker *worker)
  * worker_thread - the worker thread function
  * @__worker: self
  *
- * The worker thread function.  There are NR_CPU_WORKER_POOLS dynamic pools
- * of these per each cpu.  These workers process all works regardless of
- * their specific target workqueue.  The only exception is works which
- * belong to workqueues with a rescuer which will be explained in
- * rescuer_thread().
+ * The worker thread function.  All workers belong to a worker_pool -
+ * either a per-cpu one or dynamic unbound one.  These workers process all
+ * work items regardless of their specific target workqueue.  The only
+ * exception is work items which belong to workqueues with a rescuer which
+ * will be explained in rescuer_thread().
  */
 static int worker_thread(void *__worker)
 {
@@ -2228,19 +2241,12 @@ static int worker_thread(void *__worker)
 woke_up:
 	spin_lock_irq(&pool->lock);
 
-	/* we are off idle list if destruction or rebind is requested */
-	if (unlikely(list_empty(&worker->entry))) {
+	/* am I supposed to die? */
+	if (unlikely(worker->flags & WORKER_DIE)) {
 		spin_unlock_irq(&pool->lock);
-
-		/* if DIE is set, destruction is requested */
-		if (worker->flags & WORKER_DIE) {
-			worker->task->flags &= ~PF_WQ_WORKER;
-			return 0;
-		}
-
-		/* otherwise, rebind */
-		idle_worker_rebind(worker);
-		goto woke_up;
+		WARN_ON_ONCE(!list_empty(&worker->entry));
+		worker->task->flags &= ~PF_WQ_WORKER;
+		return 0;
 	}
 
 	worker_leave_idle(worker);
@@ -2258,14 +2264,16 @@ recheck:
 	 * preparing to process a work or actually processing it.
 	 * Make sure nobody diddled with it while I was sleeping.
 	 */
-	BUG_ON(!list_empty(&worker->scheduled));
+	WARN_ON_ONCE(!list_empty(&worker->scheduled));
 
 	/*
-	 * When control reaches this point, we're guaranteed to have
-	 * at least one idle worker or that someone else has already
-	 * assumed the manager role.
+	 * Finish PREP stage.  We're guaranteed to have at least one idle
+	 * worker or that someone else has already assumed the manager
+	 * role.  This is where @worker starts participating in concurrency
+	 * management if applicable and concurrency management is restored
+	 * after being rebound.  See rebind_workers() for details.
 	 */
-	worker_clr_flags(worker, WORKER_PREP);
+	worker_clr_flags(worker, WORKER_PREP | WORKER_REBOUND);
 
 	do {
 		struct work_struct *work =
@@ -2307,7 +2315,7 @@ sleep:
  * @__rescuer: self
  *
  * Workqueue rescuer thread function.  There's one rescuer for each
- * workqueue which has WQ_RESCUER set.
+ * workqueue which has WQ_MEM_RECLAIM set.
  *
  * Regular work processing on a pool may block trying to create a new
  * worker which uses GFP_KERNEL allocation which has slight chance of
@@ -2326,8 +2334,6 @@ static int rescuer_thread(void *__rescuer)
 	struct worker *rescuer = __rescuer;
 	struct workqueue_struct *wq = rescuer->rescue_wq;
 	struct list_head *scheduled = &rescuer->scheduled;
-	bool is_unbound = wq->flags & WQ_UNBOUND;
-	unsigned int cpu;
 
 	set_user_nice(current, RESCUER_NICE_LEVEL);
 
@@ -2345,28 +2351,29 @@ repeat:
 		return 0;
 	}
 
-	/*
-	 * See whether any cpu is asking for help.  Unbounded
-	 * workqueues use cpu 0 in mayday_mask for CPU_UNBOUND.
-	 */
-	for_each_mayday_cpu(cpu, wq->mayday_mask) {
-		unsigned int tcpu = is_unbound ? WORK_CPU_UNBOUND : cpu;
-		struct pool_workqueue *pwq = get_pwq(tcpu, wq);
+	/* see whether any pwq is asking for help */
+	spin_lock_irq(&wq_mayday_lock);
+
+	while (!list_empty(&wq->maydays)) {
+		struct pool_workqueue *pwq = list_first_entry(&wq->maydays,
+					struct pool_workqueue, mayday_node);
 		struct worker_pool *pool = pwq->pool;
 		struct work_struct *work, *n;
 
 		__set_current_state(TASK_RUNNING);
-		mayday_clear_cpu(cpu, wq->mayday_mask);
+		list_del_init(&pwq->mayday_node);
+
+		spin_unlock_irq(&wq_mayday_lock);
 
 		/* migrate to the target cpu if possible */
+		worker_maybe_bind_and_lock(pool);
 		rescuer->pool = pool;
-		worker_maybe_bind_and_lock(rescuer);
 
 		/*
 		 * Slurp in all works issued via this workqueue and
 		 * process'em.
 		 */
-		BUG_ON(!list_empty(&rescuer->scheduled));
+		WARN_ON_ONCE(!list_empty(&rescuer->scheduled));
 		list_for_each_entry_safe(work, n, &pool->worklist, entry)
 			if (get_work_pwq(work) == pwq)
 				move_linked_works(work, scheduled, &n);
@@ -2381,9 +2388,13 @@ repeat:
 		if (keep_working(pool))
 			wake_up_worker(pool);
 
-		spin_unlock_irq(&pool->lock);
+		rescuer->pool = NULL;
+		spin_unlock(&pool->lock);
+		spin_lock(&wq_mayday_lock);
 	}
 
+	spin_unlock_irq(&wq_mayday_lock);
+
 	/* rescuers should never participate in concurrency management */
 	WARN_ON_ONCE(!(rescuer->flags & WORKER_NOT_RUNNING));
 	schedule();
@@ -2487,7 +2498,7 @@ static void insert_wq_barrier(struct pool_workqueue *pwq,
  * advanced to @work_color.
  *
  * CONTEXT:
- * mutex_lock(wq->flush_mutex).
+ * mutex_lock(wq->mutex).
  *
  * RETURNS:
  * %true if @flush_color >= 0 and there's something to flush.  %false
@@ -2497,21 +2508,20 @@ static bool flush_workqueue_prep_pwqs(struct workqueue_struct *wq,
 				      int flush_color, int work_color)
 {
 	bool wait = false;
-	unsigned int cpu;
+	struct pool_workqueue *pwq;
 
 	if (flush_color >= 0) {
-		BUG_ON(atomic_read(&wq->nr_pwqs_to_flush));
+		WARN_ON_ONCE(atomic_read(&wq->nr_pwqs_to_flush));
 		atomic_set(&wq->nr_pwqs_to_flush, 1);
 	}
 
-	for_each_pwq_cpu(cpu, wq) {
-		struct pool_workqueue *pwq = get_pwq(cpu, wq);
+	for_each_pwq(pwq, wq) {
 		struct worker_pool *pool = pwq->pool;
 
 		spin_lock_irq(&pool->lock);
 
 		if (flush_color >= 0) {
-			BUG_ON(pwq->flush_color != -1);
+			WARN_ON_ONCE(pwq->flush_color != -1);
 
 			if (pwq->nr_in_flight[flush_color]) {
 				pwq->flush_color = flush_color;
@@ -2521,7 +2531,7 @@ static bool flush_workqueue_prep_pwqs(struct workqueue_struct *wq,
 		}
 
 		if (work_color >= 0) {
-			BUG_ON(work_color != work_next_color(pwq->work_color));
+			WARN_ON_ONCE(work_color != work_next_color(pwq->work_color));
 			pwq->work_color = work_color;
 		}
 
@@ -2538,11 +2548,8 @@ static bool flush_workqueue_prep_pwqs(struct workqueue_struct *wq,
  * flush_workqueue - ensure that any scheduled work has run to completion.
  * @wq: workqueue to flush
  *
- * Forces execution of the workqueue and blocks until its completion.
- * This is typically used in driver shutdown handlers.
- *
- * We sleep until all works which were queued on entry have been handled,
- * but we are not livelocked by new incoming ones.
+ * This function sleeps until all work items which were queued on entry
+ * have finished execution, but it is not livelocked by new incoming ones.
  */
 void flush_workqueue(struct workqueue_struct *wq)
 {
@@ -2556,7 +2563,7 @@ void flush_workqueue(struct workqueue_struct *wq)
 	lock_map_acquire(&wq->lockdep_map);
 	lock_map_release(&wq->lockdep_map);
 
-	mutex_lock(&wq->flush_mutex);
+	mutex_lock(&wq->mutex);
 
 	/*
 	 * Start-to-wait phase
@@ -2569,13 +2576,13 @@ void flush_workqueue(struct workqueue_struct *wq)
 		 * becomes our flush_color and work_color is advanced
 		 * by one.
 		 */
-		BUG_ON(!list_empty(&wq->flusher_overflow));
+		WARN_ON_ONCE(!list_empty(&wq->flusher_overflow));
 		this_flusher.flush_color = wq->work_color;
 		wq->work_color = next_color;
 
 		if (!wq->first_flusher) {
 			/* no flush in progress, become the first flusher */
-			BUG_ON(wq->flush_color != this_flusher.flush_color);
+			WARN_ON_ONCE(wq->flush_color != this_flusher.flush_color);
 
 			wq->first_flusher = &this_flusher;
 
@@ -2588,7 +2595,7 @@ void flush_workqueue(struct workqueue_struct *wq)
 			}
 		} else {
 			/* wait in queue */
-			BUG_ON(wq->flush_color == this_flusher.flush_color);
+			WARN_ON_ONCE(wq->flush_color == this_flusher.flush_color);
 			list_add_tail(&this_flusher.list, &wq->flusher_queue);
 			flush_workqueue_prep_pwqs(wq, -1, wq->work_color);
 		}
@@ -2601,7 +2608,7 @@ void flush_workqueue(struct workqueue_struct *wq)
 		list_add_tail(&this_flusher.list, &wq->flusher_overflow);
 	}
 
-	mutex_unlock(&wq->flush_mutex);
+	mutex_unlock(&wq->mutex);
 
 	wait_for_completion(&this_flusher.done);
 
@@ -2614,7 +2621,7 @@ void flush_workqueue(struct workqueue_struct *wq)
 	if (wq->first_flusher != &this_flusher)
 		return;
 
-	mutex_lock(&wq->flush_mutex);
+	mutex_lock(&wq->mutex);
 
 	/* we might have raced, check again with mutex held */
 	if (wq->first_flusher != &this_flusher)
@@ -2622,8 +2629,8 @@ void flush_workqueue(struct workqueue_struct *wq)
 
 	wq->first_flusher = NULL;
 
-	BUG_ON(!list_empty(&this_flusher.list));
-	BUG_ON(wq->flush_color != this_flusher.flush_color);
+	WARN_ON_ONCE(!list_empty(&this_flusher.list));
+	WARN_ON_ONCE(wq->flush_color != this_flusher.flush_color);
 
 	while (true) {
 		struct wq_flusher *next, *tmp;
@@ -2636,8 +2643,8 @@ void flush_workqueue(struct workqueue_struct *wq)
 			complete(&next->done);
 		}
 
-		BUG_ON(!list_empty(&wq->flusher_overflow) &&
-		       wq->flush_color != work_next_color(wq->work_color));
+		WARN_ON_ONCE(!list_empty(&wq->flusher_overflow) &&
+			     wq->flush_color != work_next_color(wq->work_color));
 
 		/* this flush_color is finished, advance by one */
 		wq->flush_color = work_next_color(wq->flush_color);
@@ -2661,7 +2668,7 @@ void flush_workqueue(struct workqueue_struct *wq)
 		}
 
 		if (list_empty(&wq->flusher_queue)) {
-			BUG_ON(wq->flush_color != wq->work_color);
+			WARN_ON_ONCE(wq->flush_color != wq->work_color);
 			break;
 		}
 
@@ -2669,8 +2676,8 @@ void flush_workqueue(struct workqueue_struct *wq)
 		 * Need to flush more colors.  Make the next flusher
 		 * the new first flusher and arm pwqs.
 		 */
-		BUG_ON(wq->flush_color == wq->work_color);
-		BUG_ON(wq->flush_color != next->flush_color);
+		WARN_ON_ONCE(wq->flush_color == wq->work_color);
+		WARN_ON_ONCE(wq->flush_color != next->flush_color);
 
 		list_del_init(&next->list);
 		wq->first_flusher = next;
@@ -2686,7 +2693,7 @@ void flush_workqueue(struct workqueue_struct *wq)
 	}
 
 out_unlock:
-	mutex_unlock(&wq->flush_mutex);
+	mutex_unlock(&wq->mutex);
 }
 EXPORT_SYMBOL_GPL(flush_workqueue);
 
@@ -2704,22 +2711,23 @@ EXPORT_SYMBOL_GPL(flush_workqueue);
 void drain_workqueue(struct workqueue_struct *wq)
 {
 	unsigned int flush_cnt = 0;
-	unsigned int cpu;
+	struct pool_workqueue *pwq;
 
 	/*
 	 * __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.
+	 * Use __WQ_DRAINING so that queue doesn't have to check nr_drainers.
 	 */
-	spin_lock(&workqueue_lock);
+	mutex_lock(&wq->mutex);
 	if (!wq->nr_drainers++)
-		wq->flags |= WQ_DRAINING;
-	spin_unlock(&workqueue_lock);
+		wq->flags |= __WQ_DRAINING;
+	mutex_unlock(&wq->mutex);
 reflush:
 	flush_workqueue(wq);
 
-	for_each_pwq_cpu(cpu, wq) {
-		struct pool_workqueue *pwq = get_pwq(cpu, wq);
+	mutex_lock(&wq->mutex);
+
+	for_each_pwq(pwq, wq) {
 		bool drained;
 
 		spin_lock_irq(&pwq->pool->lock);
@@ -2731,15 +2739,16 @@ reflush:
 
 		if (++flush_cnt == 10 ||
 		    (flush_cnt % 100 == 0 && flush_cnt <= 1000))
-			pr_warn("workqueue %s: flush on destruction isn't complete after %u tries\n",
+			pr_warn("workqueue %s: drain_workqueue() isn't complete after %u tries\n",
 				wq->name, flush_cnt);
+
+		mutex_unlock(&wq->mutex);
 		goto reflush;
 	}
 
-	spin_lock(&workqueue_lock);
 	if (!--wq->nr_drainers)
-		wq->flags &= ~WQ_DRAINING;
-	spin_unlock(&workqueue_lock);
+		wq->flags &= ~__WQ_DRAINING;
+	mutex_unlock(&wq->mutex);
 }
 EXPORT_SYMBOL_GPL(drain_workqueue);
 
@@ -2750,11 +2759,15 @@ static bool start_flush_work(struct work_struct *work, struct wq_barrier *barr)
 	struct pool_workqueue *pwq;
 
 	might_sleep();
+
+	local_irq_disable();
 	pool = get_work_pool(work);
-	if (!pool)
+	if (!pool) {
+		local_irq_enable();
 		return false;
+	}
 
-	spin_lock_irq(&pool->lock);
+	spin_lock(&pool->lock);
 	/* see the comment in try_to_grab_pending() with the same code */
 	pwq = get_work_pwq(work);
 	if (pwq) {
@@ -2776,7 +2789,7 @@ static bool start_flush_work(struct work_struct *work, struct wq_barrier *barr)
 	 * flusher is not running on the same workqueue by verifying write
 	 * access.
 	 */
-	if (pwq->wq->saved_max_active == 1 || pwq->wq->flags & WQ_RESCUER)
+	if (pwq->wq->saved_max_active == 1 || pwq->wq->rescuer)
 		lock_map_acquire(&pwq->wq->lockdep_map);
 	else
 		lock_map_acquire_read(&pwq->wq->lockdep_map);
@@ -2933,66 +2946,6 @@ bool cancel_delayed_work_sync(struct delayed_work *dwork)
 EXPORT_SYMBOL(cancel_delayed_work_sync);
 
 /**
- * schedule_work_on - put work task on a specific cpu
- * @cpu: cpu to put the work task on
- * @work: job to be done
- *
- * This puts a job on a specific cpu
- */
-bool schedule_work_on(int cpu, struct work_struct *work)
-{
-	return queue_work_on(cpu, system_wq, work);
-}
-EXPORT_SYMBOL(schedule_work_on);
-
-/**
- * schedule_work - put work task in global workqueue
- * @work: job to be done
- *
- * Returns %false if @work was already on the kernel-global workqueue and
- * %true otherwise.
- *
- * This puts a job in the kernel-global workqueue if it was not already
- * queued and leaves it in the same position on the kernel-global
- * workqueue otherwise.
- */
-bool schedule_work(struct work_struct *work)
-{
-	return queue_work(system_wq, work);
-}
-EXPORT_SYMBOL(schedule_work);
-
-/**
- * schedule_delayed_work_on - queue work in global workqueue on CPU after delay
- * @cpu: cpu to use
- * @dwork: job to be done
- * @delay: number of jiffies to wait
- *
- * After waiting for a given time this puts a job in the kernel-global
- * workqueue on the specified CPU.
- */
-bool schedule_delayed_work_on(int cpu, struct delayed_work *dwork,
-			      unsigned long delay)
-{
-	return queue_delayed_work_on(cpu, system_wq, dwork, delay);
-}
-EXPORT_SYMBOL(schedule_delayed_work_on);
-
-/**
- * schedule_delayed_work - put work task in global workqueue after delay
- * @dwork: job to be done
- * @delay: number of jiffies to wait or 0 for immediate execution
- *
- * After waiting for a given time this puts a job in the kernel-global
- * workqueue.
- */
-bool schedule_delayed_work(struct delayed_work *dwork, unsigned long delay)
-{
-	return queue_delayed_work(system_wq, dwork, delay);
-}
-EXPORT_SYMBOL(schedule_delayed_work);
-
-/**
  * schedule_on_each_cpu - execute a function synchronously on each online CPU
  * @func: the function to call
  *
@@ -3085,273 +3038,1269 @@ int execute_in_process_context(work_func_t fn, struct execute_work *ew)
 }
 EXPORT_SYMBOL_GPL(execute_in_process_context);
 
-int keventd_up(void)
+#ifdef CONFIG_SYSFS
+/*
+ * Workqueues with WQ_SYSFS flag set is visible to userland via
+ * /sys/bus/workqueue/devices/WQ_NAME.  All visible workqueues have the
+ * following attributes.
+ *
+ *  per_cpu	RO bool	: whether the workqueue is per-cpu or unbound
+ *  max_active	RW int	: maximum number of in-flight work items
+ *
+ * Unbound workqueues have the following extra attributes.
+ *
+ *  id		RO int	: the associated pool ID
+ *  nice	RW int	: nice value of the workers
+ *  cpumask	RW mask	: bitmask of allowed CPUs for the workers
+ */
+struct wq_device {
+	struct workqueue_struct		*wq;
+	struct device			dev;
+};
+
+static struct workqueue_struct *dev_to_wq(struct device *dev)
 {
-	return system_wq != NULL;
+	struct wq_device *wq_dev = container_of(dev, struct wq_device, dev);
+
+	return wq_dev->wq;
 }
 
-static int alloc_pwqs(struct workqueue_struct *wq)
+static ssize_t wq_per_cpu_show(struct device *dev,
+			       struct device_attribute *attr, char *buf)
 {
-	/*
-	 * pwqs are forced aligned according to WORK_STRUCT_FLAG_BITS.
-	 * Make sure that the alignment isn't lower than that of
-	 * unsigned long long.
-	 */
-	const size_t size = sizeof(struct pool_workqueue);
-	const size_t align = max_t(size_t, 1 << WORK_STRUCT_FLAG_BITS,
-				   __alignof__(unsigned long long));
+	struct workqueue_struct *wq = dev_to_wq(dev);
 
-	if (!(wq->flags & WQ_UNBOUND))
-		wq->pool_wq.pcpu = __alloc_percpu(size, align);
-	else {
-		void *ptr;
+	return scnprintf(buf, PAGE_SIZE, "%d\n", (bool)!(wq->flags & WQ_UNBOUND));
+}
 
-		/*
-		 * Allocate enough room to align pwq and put an extra
-		 * pointer at the end pointing back to the originally
-		 * allocated pointer which will be used for free.
-		 */
-		ptr = kzalloc(size + align + sizeof(void *), GFP_KERNEL);
-		if (ptr) {
-			wq->pool_wq.single = PTR_ALIGN(ptr, align);
-			*(void **)(wq->pool_wq.single + 1) = ptr;
-		}
-	}
+static ssize_t wq_max_active_show(struct device *dev,
+				  struct device_attribute *attr, char *buf)
+{
+	struct workqueue_struct *wq = dev_to_wq(dev);
 
-	/* just in case, make sure it's actually aligned */
-	BUG_ON(!IS_ALIGNED(wq->pool_wq.v, align));
-	return wq->pool_wq.v ? 0 : -ENOMEM;
+	return scnprintf(buf, PAGE_SIZE, "%d\n", wq->saved_max_active);
 }
 
-static void free_pwqs(struct workqueue_struct *wq)
+static ssize_t wq_max_active_store(struct device *dev,
+				   struct device_attribute *attr,
+				   const char *buf, size_t count)
 {
-	if (!(wq->flags & WQ_UNBOUND))
-		free_percpu(wq->pool_wq.pcpu);
-	else if (wq->pool_wq.single) {
-		/* the pointer to free is stored right after the pwq */
-		kfree(*(void **)(wq->pool_wq.single + 1));
+	struct workqueue_struct *wq = dev_to_wq(dev);
+	int val;
+
+	if (sscanf(buf, "%d", &val) != 1 || val <= 0)
+		return -EINVAL;
+
+	workqueue_set_max_active(wq, val);
+	return count;
+}
+
+static struct device_attribute wq_sysfs_attrs[] = {
+	__ATTR(per_cpu, 0444, wq_per_cpu_show, NULL),
+	__ATTR(max_active, 0644, wq_max_active_show, wq_max_active_store),
+	__ATTR_NULL,
+};
+
+static ssize_t wq_pool_ids_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct workqueue_struct *wq = dev_to_wq(dev);
+	const char *delim = "";
+	int node, written = 0;
+
+	rcu_read_lock_sched();
+	for_each_node(node) {
+		written += scnprintf(buf + written, PAGE_SIZE - written,
+				     "%s%d:%d", delim, node,
+				     unbound_pwq_by_node(wq, node)->pool->id);
+		delim = " ";
 	}
+	written += scnprintf(buf + written, PAGE_SIZE - written, "\n");
+	rcu_read_unlock_sched();
+
+	return written;
 }
 
-static int wq_clamp_max_active(int max_active, unsigned int flags,
-			       const char *name)
+static ssize_t wq_nice_show(struct device *dev, struct device_attribute *attr,
+			    char *buf)
 {
-	int lim = flags & WQ_UNBOUND ? WQ_UNBOUND_MAX_ACTIVE : WQ_MAX_ACTIVE;
+	struct workqueue_struct *wq = dev_to_wq(dev);
+	int written;
 
-	if (max_active < 1 || max_active > lim)
-		pr_warn("workqueue: max_active %d requested for %s is out of range, clamping between %d and %d\n",
-			max_active, name, 1, lim);
+	mutex_lock(&wq->mutex);
+	written = scnprintf(buf, PAGE_SIZE, "%d\n", wq->unbound_attrs->nice);
+	mutex_unlock(&wq->mutex);
 
-	return clamp_val(max_active, 1, lim);
+	return written;
 }
 
-struct workqueue_struct *__alloc_workqueue_key(const char *fmt,
-					       unsigned int flags,
-					       int max_active,
-					       struct lock_class_key *key,
-					       const char *lock_name, ...)
+/* prepare workqueue_attrs for sysfs store operations */
+static struct workqueue_attrs *wq_sysfs_prep_attrs(struct workqueue_struct *wq)
 {
-	va_list args, args1;
-	struct workqueue_struct *wq;
-	unsigned int cpu;
-	size_t namelen;
+	struct workqueue_attrs *attrs;
 
-	/* determine namelen, allocate wq and format name */
-	va_start(args, lock_name);
-	va_copy(args1, args);
-	namelen = vsnprintf(NULL, 0, fmt, args) + 1;
+	attrs = alloc_workqueue_attrs(GFP_KERNEL);
+	if (!attrs)
+		return NULL;
 
-	wq = kzalloc(sizeof(*wq) + namelen, GFP_KERNEL);
-	if (!wq)
-		goto err;
+	mutex_lock(&wq->mutex);
+	copy_workqueue_attrs(attrs, wq->unbound_attrs);
+	mutex_unlock(&wq->mutex);
+	return attrs;
+}
 
-	vsnprintf(wq->name, namelen, fmt, args1);
-	va_end(args);
-	va_end(args1);
+static ssize_t wq_nice_store(struct device *dev, struct device_attribute *attr,
+			     const char *buf, size_t count)
+{
+	struct workqueue_struct *wq = dev_to_wq(dev);
+	struct workqueue_attrs *attrs;
+	int ret;
 
-	/*
-	 * Workqueues which may be used during memory reclaim should
-	 * have a rescuer to guarantee forward progress.
-	 */
-	if (flags & WQ_MEM_RECLAIM)
-		flags |= WQ_RESCUER;
+	attrs = wq_sysfs_prep_attrs(wq);
+	if (!attrs)
+		return -ENOMEM;
 
-	max_active = max_active ?: WQ_DFL_ACTIVE;
-	max_active = wq_clamp_max_active(max_active, flags, wq->name);
+	if (sscanf(buf, "%d", &attrs->nice) == 1 &&
+	    attrs->nice >= -20 && attrs->nice <= 19)
+		ret = apply_workqueue_attrs(wq, attrs);
+	else
+		ret = -EINVAL;
 
-	/* init wq */
-	wq->flags = flags;
-	wq->saved_max_active = max_active;
-	mutex_init(&wq->flush_mutex);
-	atomic_set(&wq->nr_pwqs_to_flush, 0);
-	INIT_LIST_HEAD(&wq->flusher_queue);
-	INIT_LIST_HEAD(&wq->flusher_overflow);
+	free_workqueue_attrs(attrs);
+	return ret ?: count;
+}
 
-	lockdep_init_map(&wq->lockdep_map, lock_name, key, 0);
-	INIT_LIST_HEAD(&wq->list);
+static ssize_t wq_cpumask_show(struct device *dev,
+			       struct device_attribute *attr, char *buf)
+{
+	struct workqueue_struct *wq = dev_to_wq(dev);
+	int written;
 
-	if (alloc_pwqs(wq) < 0)
-		goto err;
+	mutex_lock(&wq->mutex);
+	written = cpumask_scnprintf(buf, PAGE_SIZE, wq->unbound_attrs->cpumask);
+	mutex_unlock(&wq->mutex);
 
-	for_each_pwq_cpu(cpu, wq) {
-		struct pool_workqueue *pwq = get_pwq(cpu, wq);
+	written += scnprintf(buf + written, PAGE_SIZE - written, "\n");
+	return written;
+}
 
-		BUG_ON((unsigned long)pwq & WORK_STRUCT_FLAG_MASK);
-		pwq->pool = get_std_worker_pool(cpu, flags & WQ_HIGHPRI);
-		pwq->wq = wq;
-		pwq->flush_color = -1;
-		pwq->max_active = max_active;
-		INIT_LIST_HEAD(&pwq->delayed_works);
-	}
+static ssize_t wq_cpumask_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	struct workqueue_struct *wq = dev_to_wq(dev);
+	struct workqueue_attrs *attrs;
+	int ret;
 
-	if (flags & WQ_RESCUER) {
-		struct worker *rescuer;
+	attrs = wq_sysfs_prep_attrs(wq);
+	if (!attrs)
+		return -ENOMEM;
 
-		if (!alloc_mayday_mask(&wq->mayday_mask, GFP_KERNEL))
-			goto err;
+	ret = cpumask_parse(buf, attrs->cpumask);
+	if (!ret)
+		ret = apply_workqueue_attrs(wq, attrs);
 
-		wq->rescuer = rescuer = alloc_worker();
-		if (!rescuer)
-			goto err;
+	free_workqueue_attrs(attrs);
+	return ret ?: count;
+}
 
-		rescuer->rescue_wq = wq;
-		rescuer->task = kthread_create(rescuer_thread, rescuer, "%s",
-					       wq->name);
-		if (IS_ERR(rescuer->task))
-			goto err;
+static ssize_t wq_numa_show(struct device *dev, struct device_attribute *attr,
+			    char *buf)
+{
+	struct workqueue_struct *wq = dev_to_wq(dev);
+	int written;
 
-		rescuer->task->flags |= PF_THREAD_BOUND;
-		wake_up_process(rescuer->task);
+	mutex_lock(&wq->mutex);
+	written = scnprintf(buf, PAGE_SIZE, "%d\n",
+			    !wq->unbound_attrs->no_numa);
+	mutex_unlock(&wq->mutex);
+
+	return written;
+}
+
+static ssize_t wq_numa_store(struct device *dev, struct device_attribute *attr,
+			     const char *buf, size_t count)
+{
+	struct workqueue_struct *wq = dev_to_wq(dev);
+	struct workqueue_attrs *attrs;
+	int v, ret;
+
+	attrs = wq_sysfs_prep_attrs(wq);
+	if (!attrs)
+		return -ENOMEM;
+
+	ret = -EINVAL;
+	if (sscanf(buf, "%d", &v) == 1) {
+		attrs->no_numa = !v;
+		ret = apply_workqueue_attrs(wq, attrs);
 	}
 
-	/*
-	 * workqueue_lock protects global freeze state and workqueues
-	 * list.  Grab it, set max_active accordingly and add the new
-	 * workqueue to workqueues list.
-	 */
-	spin_lock(&workqueue_lock);
+	free_workqueue_attrs(attrs);
+	return ret ?: count;
+}
 
-	if (workqueue_freezing && wq->flags & WQ_FREEZABLE)
-		for_each_pwq_cpu(cpu, wq)
-			get_pwq(cpu, wq)->max_active = 0;
+static struct device_attribute wq_sysfs_unbound_attrs[] = {
+	__ATTR(pool_ids, 0444, wq_pool_ids_show, NULL),
+	__ATTR(nice, 0644, wq_nice_show, wq_nice_store),
+	__ATTR(cpumask, 0644, wq_cpumask_show, wq_cpumask_store),
+	__ATTR(numa, 0644, wq_numa_show, wq_numa_store),
+	__ATTR_NULL,
+};
 
-	list_add(&wq->list, &workqueues);
+static struct bus_type wq_subsys = {
+	.name				= "workqueue",
+	.dev_attrs			= wq_sysfs_attrs,
+};
 
-	spin_unlock(&workqueue_lock);
+static int __init wq_sysfs_init(void)
+{
+	return subsys_virtual_register(&wq_subsys, NULL);
+}
+core_initcall(wq_sysfs_init);
 
-	return wq;
-err:
-	if (wq) {
-		free_pwqs(wq);
-		free_mayday_mask(wq->mayday_mask);
-		kfree(wq->rescuer);
-		kfree(wq);
-	}
-	return NULL;
+static void wq_device_release(struct device *dev)
+{
+	struct wq_device *wq_dev = container_of(dev, struct wq_device, dev);
+
+	kfree(wq_dev);
 }
-EXPORT_SYMBOL_GPL(__alloc_workqueue_key);
 
 /**
- * destroy_workqueue - safely terminate a workqueue
- * @wq: target workqueue
+ * workqueue_sysfs_register - make a workqueue visible in sysfs
+ * @wq: the workqueue to register
  *
- * Safely destroy a workqueue. All work currently pending will be done first.
+ * Expose @wq in sysfs under /sys/bus/workqueue/devices.
+ * alloc_workqueue*() automatically calls this function if WQ_SYSFS is set
+ * which is the preferred method.
+ *
+ * Workqueue user should use this function directly iff it wants to apply
+ * workqueue_attrs before making the workqueue visible in sysfs; otherwise,
+ * apply_workqueue_attrs() may race against userland updating the
+ * attributes.
+ *
+ * Returns 0 on success, -errno on failure.
  */
-void destroy_workqueue(struct workqueue_struct *wq)
+int workqueue_sysfs_register(struct workqueue_struct *wq)
 {
-	unsigned int cpu;
-
-	/* drain it before proceeding with destruction */
-	drain_workqueue(wq);
+	struct wq_device *wq_dev;
+	int ret;
 
 	/*
-	 * wq list is used to freeze wq, remove from list after
-	 * flushing is complete in case freeze races us.
+	 * Adjusting max_active or creating new pwqs by applyting
+	 * attributes breaks ordering guarantee.  Disallow exposing ordered
+	 * workqueues.
 	 */
-	spin_lock(&workqueue_lock);
-	list_del(&wq->list);
-	spin_unlock(&workqueue_lock);
+	if (WARN_ON(wq->flags & __WQ_ORDERED))
+		return -EINVAL;
 
-	/* sanity check */
-	for_each_pwq_cpu(cpu, wq) {
-		struct pool_workqueue *pwq = get_pwq(cpu, wq);
-		int i;
+	wq->wq_dev = wq_dev = kzalloc(sizeof(*wq_dev), GFP_KERNEL);
+	if (!wq_dev)
+		return -ENOMEM;
+
+	wq_dev->wq = wq;
+	wq_dev->dev.bus = &wq_subsys;
+	wq_dev->dev.init_name = wq->name;
+	wq_dev->dev.release = wq_device_release;
+
+	/*
+	 * unbound_attrs are created separately.  Suppress uevent until
+	 * everything is ready.
+	 */
+	dev_set_uevent_suppress(&wq_dev->dev, true);
 
-		for (i = 0; i < WORK_NR_COLORS; i++)
-			BUG_ON(pwq->nr_in_flight[i]);
-		BUG_ON(pwq->nr_active);
-		BUG_ON(!list_empty(&pwq->delayed_works));
+	ret = device_register(&wq_dev->dev);
+	if (ret) {
+		kfree(wq_dev);
+		wq->wq_dev = NULL;
+		return ret;
 	}
 
-	if (wq->flags & WQ_RESCUER) {
-		kthread_stop(wq->rescuer->task);
-		free_mayday_mask(wq->mayday_mask);
-		kfree(wq->rescuer);
+	if (wq->flags & WQ_UNBOUND) {
+		struct device_attribute *attr;
+
+		for (attr = wq_sysfs_unbound_attrs; attr->attr.name; attr++) {
+			ret = device_create_file(&wq_dev->dev, attr);
+			if (ret) {
+				device_unregister(&wq_dev->dev);
+				wq->wq_dev = NULL;
+				return ret;
+			}
+		}
 	}
 
-	free_pwqs(wq);
-	kfree(wq);
+	kobject_uevent(&wq_dev->dev.kobj, KOBJ_ADD);
+	return 0;
 }
-EXPORT_SYMBOL_GPL(destroy_workqueue);
 
 /**
- * pwq_set_max_active - adjust max_active of a pwq
- * @pwq: target pool_workqueue
- * @max_active: new max_active value.
- *
- * Set @pwq->max_active to @max_active and activate delayed works if
- * increased.
+ * workqueue_sysfs_unregister - undo workqueue_sysfs_register()
+ * @wq: the workqueue to unregister
  *
- * CONTEXT:
- * spin_lock_irq(pool->lock).
+ * If @wq is registered to sysfs by workqueue_sysfs_register(), unregister.
  */
-static void pwq_set_max_active(struct pool_workqueue *pwq, int max_active)
+static void workqueue_sysfs_unregister(struct workqueue_struct *wq)
 {
-	pwq->max_active = max_active;
+	struct wq_device *wq_dev = wq->wq_dev;
+
+	if (!wq->wq_dev)
+		return;
 
-	while (!list_empty(&pwq->delayed_works) &&
-	       pwq->nr_active < pwq->max_active)
-		pwq_activate_first_delayed(pwq);
+	wq->wq_dev = NULL;
+	device_unregister(&wq_dev->dev);
 }
+#else	/* CONFIG_SYSFS */
+static void workqueue_sysfs_unregister(struct workqueue_struct *wq)	{ }
+#endif	/* CONFIG_SYSFS */
 
 /**
- * workqueue_set_max_active - adjust max_active of a workqueue
- * @wq: target workqueue
- * @max_active: new max_active value.
+ * free_workqueue_attrs - free a workqueue_attrs
+ * @attrs: workqueue_attrs to free
  *
- * Set max_active of @wq to @max_active.
+ * Undo alloc_workqueue_attrs().
+ */
+void free_workqueue_attrs(struct workqueue_attrs *attrs)
+{
+	if (attrs) {
+		free_cpumask_var(attrs->cpumask);
+		kfree(attrs);
+	}
+}
+
+/**
+ * alloc_workqueue_attrs - allocate a workqueue_attrs
+ * @gfp_mask: allocation mask to use
  *
- * CONTEXT:
- * Don't call from IRQ context.
+ * Allocate a new workqueue_attrs, initialize with default settings and
+ * return it.  Returns NULL on failure.
  */
-void workqueue_set_max_active(struct workqueue_struct *wq, int max_active)
+struct workqueue_attrs *alloc_workqueue_attrs(gfp_t gfp_mask)
 {
-	unsigned int cpu;
+	struct workqueue_attrs *attrs;
 
-	max_active = wq_clamp_max_active(max_active, wq->flags, wq->name);
+	attrs = kzalloc(sizeof(*attrs), gfp_mask);
+	if (!attrs)
+		goto fail;
+	if (!alloc_cpumask_var(&attrs->cpumask, gfp_mask))
+		goto fail;
 
-	spin_lock(&workqueue_lock);
+	cpumask_copy(attrs->cpumask, cpu_possible_mask);
+	return attrs;
+fail:
+	free_workqueue_attrs(attrs);
+	return NULL;
+}
 
-	wq->saved_max_active = max_active;
+static void copy_workqueue_attrs(struct workqueue_attrs *to,
+				 const struct workqueue_attrs *from)
+{
+	to->nice = from->nice;
+	cpumask_copy(to->cpumask, from->cpumask);
+}
 
-	for_each_pwq_cpu(cpu, wq) {
-		struct pool_workqueue *pwq = get_pwq(cpu, wq);
-		struct worker_pool *pool = pwq->pool;
+/* hash value of the content of @attr */
+static u32 wqattrs_hash(const struct workqueue_attrs *attrs)
+{
+	u32 hash = 0;
 
-		spin_lock_irq(&pool->lock);
+	hash = jhash_1word(attrs->nice, hash);
+	hash = jhash(cpumask_bits(attrs->cpumask),
+		     BITS_TO_LONGS(nr_cpumask_bits) * sizeof(long), hash);
+	return hash;
+}
+
+/* content equality test */
+static bool wqattrs_equal(const struct workqueue_attrs *a,
+			  const struct workqueue_attrs *b)
+{
+	if (a->nice != b->nice)
+		return false;
+	if (!cpumask_equal(a->cpumask, b->cpumask))
+		return false;
+	return true;
+}
+
+/**
+ * init_worker_pool - initialize a newly zalloc'd worker_pool
+ * @pool: worker_pool to initialize
+ *
+ * Initiailize a newly zalloc'd @pool.  It also allocates @pool->attrs.
+ * Returns 0 on success, -errno on failure.  Even on failure, all fields
+ * inside @pool proper are initialized and put_unbound_pool() can be called
+ * on @pool safely to release it.
+ */
+static int init_worker_pool(struct worker_pool *pool)
+{
+	spin_lock_init(&pool->lock);
+	pool->id = -1;
+	pool->cpu = -1;
+	pool->node = NUMA_NO_NODE;
+	pool->flags |= POOL_DISASSOCIATED;
+	INIT_LIST_HEAD(&pool->worklist);
+	INIT_LIST_HEAD(&pool->idle_list);
+	hash_init(pool->busy_hash);
+
+	init_timer_deferrable(&pool->idle_timer);
+	pool->idle_timer.function = idle_worker_timeout;
+	pool->idle_timer.data = (unsigned long)pool;
+
+	setup_timer(&pool->mayday_timer, pool_mayday_timeout,
+		    (unsigned long)pool);
+
+	mutex_init(&pool->manager_arb);
+	mutex_init(&pool->manager_mutex);
+	idr_init(&pool->worker_idr);
+
+	INIT_HLIST_NODE(&pool->hash_node);
+	pool->refcnt = 1;
+
+	/* shouldn't fail above this point */
+	pool->attrs = alloc_workqueue_attrs(GFP_KERNEL);
+	if (!pool->attrs)
+		return -ENOMEM;
+	return 0;
+}
+
+static void rcu_free_pool(struct rcu_head *rcu)
+{
+	struct worker_pool *pool = container_of(rcu, struct worker_pool, rcu);
+
+	idr_destroy(&pool->worker_idr);
+	free_workqueue_attrs(pool->attrs);
+	kfree(pool);
+}
+
+/**
+ * put_unbound_pool - put a worker_pool
+ * @pool: worker_pool to put
+ *
+ * Put @pool.  If its refcnt reaches zero, it gets destroyed in sched-RCU
+ * safe manner.  get_unbound_pool() calls this function on its failure path
+ * and this function should be able to release pools which went through,
+ * successfully or not, init_worker_pool().
+ *
+ * Should be called with wq_pool_mutex held.
+ */
+static void put_unbound_pool(struct worker_pool *pool)
+{
+	struct worker *worker;
+
+	lockdep_assert_held(&wq_pool_mutex);
+
+	if (--pool->refcnt)
+		return;
+
+	/* sanity checks */
+	if (WARN_ON(!(pool->flags & POOL_DISASSOCIATED)) ||
+	    WARN_ON(!list_empty(&pool->worklist)))
+		return;
+
+	/* release id and unhash */
+	if (pool->id >= 0)
+		idr_remove(&worker_pool_idr, pool->id);
+	hash_del(&pool->hash_node);
+
+	/*
+	 * Become the manager and destroy all workers.  Grabbing
+	 * manager_arb prevents @pool's workers from blocking on
+	 * manager_mutex.
+	 */
+	mutex_lock(&pool->manager_arb);
+	mutex_lock(&pool->manager_mutex);
+	spin_lock_irq(&pool->lock);
+
+	while ((worker = first_worker(pool)))
+		destroy_worker(worker);
+	WARN_ON(pool->nr_workers || pool->nr_idle);
+
+	spin_unlock_irq(&pool->lock);
+	mutex_unlock(&pool->manager_mutex);
+	mutex_unlock(&pool->manager_arb);
+
+	/* shut down the timers */
+	del_timer_sync(&pool->idle_timer);
+	del_timer_sync(&pool->mayday_timer);
+
+	/* sched-RCU protected to allow dereferences from get_work_pool() */
+	call_rcu_sched(&pool->rcu, rcu_free_pool);
+}
+
+/**
+ * get_unbound_pool - get a worker_pool with the specified attributes
+ * @attrs: the attributes of the worker_pool to get
+ *
+ * Obtain a worker_pool which has the same attributes as @attrs, bump the
+ * reference count and return it.  If there already is a matching
+ * worker_pool, it will be used; otherwise, this function attempts to
+ * create a new one.  On failure, returns NULL.
+ *
+ * Should be called with wq_pool_mutex held.
+ */
+static struct worker_pool *get_unbound_pool(const struct workqueue_attrs *attrs)
+{
+	u32 hash = wqattrs_hash(attrs);
+	struct worker_pool *pool;
+	int node;
+
+	lockdep_assert_held(&wq_pool_mutex);
+
+	/* do we already have a matching pool? */
+	hash_for_each_possible(unbound_pool_hash, pool, hash_node, hash) {
+		if (wqattrs_equal(pool->attrs, attrs)) {
+			pool->refcnt++;
+			goto out_unlock;
+		}
+	}
+
+	/* nope, create a new one */
+	pool = kzalloc(sizeof(*pool), GFP_KERNEL);
+	if (!pool || init_worker_pool(pool) < 0)
+		goto fail;
+
+	if (workqueue_freezing)
+		pool->flags |= POOL_FREEZING;
+
+	lockdep_set_subclass(&pool->lock, 1);	/* see put_pwq() */
+	copy_workqueue_attrs(pool->attrs, attrs);
+
+	/* if cpumask is contained inside a NUMA node, we belong to that node */
+	if (wq_numa_enabled) {
+		for_each_node(node) {
+			if (cpumask_subset(pool->attrs->cpumask,
+					   wq_numa_possible_cpumask[node])) {
+				pool->node = node;
+				break;
+			}
+		}
+	}
+
+	if (worker_pool_assign_id(pool) < 0)
+		goto fail;
+
+	/* create and start the initial worker */
+	if (create_and_start_worker(pool) < 0)
+		goto fail;
+
+	/* install */
+	hash_add(unbound_pool_hash, &pool->hash_node, hash);
+out_unlock:
+	return pool;
+fail:
+	if (pool)
+		put_unbound_pool(pool);
+	return NULL;
+}
+
+static void rcu_free_pwq(struct rcu_head *rcu)
+{
+	kmem_cache_free(pwq_cache,
+			container_of(rcu, struct pool_workqueue, rcu));
+}
+
+/*
+ * Scheduled on system_wq by put_pwq() when an unbound pwq hits zero refcnt
+ * and needs to be destroyed.
+ */
+static void pwq_unbound_release_workfn(struct work_struct *work)
+{
+	struct pool_workqueue *pwq = container_of(work, struct pool_workqueue,
+						  unbound_release_work);
+	struct workqueue_struct *wq = pwq->wq;
+	struct worker_pool *pool = pwq->pool;
+	bool is_last;
+
+	if (WARN_ON_ONCE(!(wq->flags & WQ_UNBOUND)))
+		return;
+
+	/*
+	 * Unlink @pwq.  Synchronization against wq->mutex isn't strictly
+	 * necessary on release but do it anyway.  It's easier to verify
+	 * and consistent with the linking path.
+	 */
+	mutex_lock(&wq->mutex);
+	list_del_rcu(&pwq->pwqs_node);
+	is_last = list_empty(&wq->pwqs);
+	mutex_unlock(&wq->mutex);
+
+	mutex_lock(&wq_pool_mutex);
+	put_unbound_pool(pool);
+	mutex_unlock(&wq_pool_mutex);
+
+	call_rcu_sched(&pwq->rcu, rcu_free_pwq);
+
+	/*
+	 * If we're the last pwq going away, @wq is already dead and no one
+	 * is gonna access it anymore.  Free it.
+	 */
+	if (is_last) {
+		free_workqueue_attrs(wq->unbound_attrs);
+		kfree(wq);
+	}
+}
+
+/**
+ * pwq_adjust_max_active - update a pwq's max_active to the current setting
+ * @pwq: target pool_workqueue
+ *
+ * If @pwq isn't freezing, set @pwq->max_active to the associated
+ * workqueue's saved_max_active and activate delayed work items
+ * accordingly.  If @pwq is freezing, clear @pwq->max_active to zero.
+ */
+static void pwq_adjust_max_active(struct pool_workqueue *pwq)
+{
+	struct workqueue_struct *wq = pwq->wq;
+	bool freezable = wq->flags & WQ_FREEZABLE;
+
+	/* for @wq->saved_max_active */
+	lockdep_assert_held(&wq->mutex);
+
+	/* fast exit for non-freezable wqs */
+	if (!freezable && pwq->max_active == wq->saved_max_active)
+		return;
+
+	spin_lock_irq(&pwq->pool->lock);
+
+	if (!freezable || !(pwq->pool->flags & POOL_FREEZING)) {
+		pwq->max_active = wq->saved_max_active;
+
+		while (!list_empty(&pwq->delayed_works) &&
+		       pwq->nr_active < pwq->max_active)
+			pwq_activate_first_delayed(pwq);
+
+		/*
+		 * Need to kick a worker after thawed or an unbound wq's
+		 * max_active is bumped.  It's a slow path.  Do it always.
+		 */
+		wake_up_worker(pwq->pool);
+	} else {
+		pwq->max_active = 0;
+	}
+
+	spin_unlock_irq(&pwq->pool->lock);
+}
+
+/* initialize newly alloced @pwq which is associated with @wq and @pool */
+static void init_pwq(struct pool_workqueue *pwq, struct workqueue_struct *wq,
+		     struct worker_pool *pool)
+{
+	BUG_ON((unsigned long)pwq & WORK_STRUCT_FLAG_MASK);
+
+	memset(pwq, 0, sizeof(*pwq));
+
+	pwq->pool = pool;
+	pwq->wq = wq;
+	pwq->flush_color = -1;
+	pwq->refcnt = 1;
+	INIT_LIST_HEAD(&pwq->delayed_works);
+	INIT_LIST_HEAD(&pwq->pwqs_node);
+	INIT_LIST_HEAD(&pwq->mayday_node);
+	INIT_WORK(&pwq->unbound_release_work, pwq_unbound_release_workfn);
+}
+
+/* sync @pwq with the current state of its associated wq and link it */
+static void link_pwq(struct pool_workqueue *pwq)
+{
+	struct workqueue_struct *wq = pwq->wq;
+
+	lockdep_assert_held(&wq->mutex);
+
+	/* may be called multiple times, ignore if already linked */
+	if (!list_empty(&pwq->pwqs_node))
+		return;
+
+	/*
+	 * Set the matching work_color.  This is synchronized with
+	 * wq->mutex to avoid confusing flush_workqueue().
+	 */
+	pwq->work_color = wq->work_color;
+
+	/* sync max_active to the current setting */
+	pwq_adjust_max_active(pwq);
+
+	/* link in @pwq */
+	list_add_rcu(&pwq->pwqs_node, &wq->pwqs);
+}
+
+/* obtain a pool matching @attr and create a pwq associating the pool and @wq */
+static struct pool_workqueue *alloc_unbound_pwq(struct workqueue_struct *wq,
+					const struct workqueue_attrs *attrs)
+{
+	struct worker_pool *pool;
+	struct pool_workqueue *pwq;
+
+	lockdep_assert_held(&wq_pool_mutex);
+
+	pool = get_unbound_pool(attrs);
+	if (!pool)
+		return NULL;
+
+	pwq = kmem_cache_alloc_node(pwq_cache, GFP_KERNEL, pool->node);
+	if (!pwq) {
+		put_unbound_pool(pool);
+		return NULL;
+	}
+
+	init_pwq(pwq, wq, pool);
+	return pwq;
+}
+
+/* undo alloc_unbound_pwq(), used only in the error path */
+static void free_unbound_pwq(struct pool_workqueue *pwq)
+{
+	lockdep_assert_held(&wq_pool_mutex);
+
+	if (pwq) {
+		put_unbound_pool(pwq->pool);
+		kfree(pwq);
+	}
+}
+
+/**
+ * wq_calc_node_mask - calculate a wq_attrs' cpumask for the specified node
+ * @attrs: the wq_attrs of interest
+ * @node: the target NUMA node
+ * @cpu_going_down: if >= 0, the CPU to consider as offline
+ * @cpumask: outarg, the resulting cpumask
+ *
+ * Calculate the cpumask a workqueue with @attrs should use on @node.  If
+ * @cpu_going_down is >= 0, that cpu is considered offline during
+ * calculation.  The result is stored in @cpumask.  This function returns
+ * %true if the resulting @cpumask is different from @attrs->cpumask,
+ * %false if equal.
+ *
+ * If NUMA affinity is not enabled, @attrs->cpumask is always used.  If
+ * enabled and @node has online CPUs requested by @attrs, the returned
+ * cpumask is the intersection of the possible CPUs of @node and
+ * @attrs->cpumask.
+ *
+ * The caller is responsible for ensuring that the cpumask of @node stays
+ * stable.
+ */
+static bool wq_calc_node_cpumask(const struct workqueue_attrs *attrs, int node,
+				 int cpu_going_down, cpumask_t *cpumask)
+{
+	if (!wq_numa_enabled || attrs->no_numa)
+		goto use_dfl;
+
+	/* does @node have any online CPUs @attrs wants? */
+	cpumask_and(cpumask, cpumask_of_node(node), attrs->cpumask);
+	if (cpu_going_down >= 0)
+		cpumask_clear_cpu(cpu_going_down, cpumask);
+
+	if (cpumask_empty(cpumask))
+		goto use_dfl;
+
+	/* yeap, return possible CPUs in @node that @attrs wants */
+	cpumask_and(cpumask, attrs->cpumask, wq_numa_possible_cpumask[node]);
+	return !cpumask_equal(cpumask, attrs->cpumask);
+
+use_dfl:
+	cpumask_copy(cpumask, attrs->cpumask);
+	return false;
+}
+
+/* install @pwq into @wq's numa_pwq_tbl[] for @node and return the old pwq */
+static struct pool_workqueue *numa_pwq_tbl_install(struct workqueue_struct *wq,
+						   int node,
+						   struct pool_workqueue *pwq)
+{
+	struct pool_workqueue *old_pwq;
+
+	lockdep_assert_held(&wq->mutex);
+
+	/* link_pwq() can handle duplicate calls */
+	link_pwq(pwq);
+
+	old_pwq = rcu_access_pointer(wq->numa_pwq_tbl[node]);
+	rcu_assign_pointer(wq->numa_pwq_tbl[node], pwq);
+	return old_pwq;
+}
+
+/**
+ * apply_workqueue_attrs - apply new workqueue_attrs to an unbound workqueue
+ * @wq: the target workqueue
+ * @attrs: the workqueue_attrs to apply, allocated with alloc_workqueue_attrs()
+ *
+ * Apply @attrs to an unbound workqueue @wq.  Unless disabled, on NUMA
+ * machines, this function maps a separate pwq to each NUMA node with
+ * possibles CPUs in @attrs->cpumask so that work items are affine to the
+ * NUMA node it was issued on.  Older pwqs are released as in-flight work
+ * items finish.  Note that a work item which repeatedly requeues itself
+ * back-to-back will stay on its current pwq.
+ *
+ * Performs GFP_KERNEL allocations.  Returns 0 on success and -errno on
+ * failure.
+ */
+int apply_workqueue_attrs(struct workqueue_struct *wq,
+			  const struct workqueue_attrs *attrs)
+{
+	struct workqueue_attrs *new_attrs, *tmp_attrs;
+	struct pool_workqueue **pwq_tbl, *dfl_pwq;
+	int node, ret;
+
+	/* only unbound workqueues can change attributes */
+	if (WARN_ON(!(wq->flags & WQ_UNBOUND)))
+		return -EINVAL;
+
+	/* creating multiple pwqs breaks ordering guarantee */
+	if (WARN_ON((wq->flags & __WQ_ORDERED) && !list_empty(&wq->pwqs)))
+		return -EINVAL;
+
+	pwq_tbl = kzalloc(wq_numa_tbl_len * sizeof(pwq_tbl[0]), GFP_KERNEL);
+	new_attrs = alloc_workqueue_attrs(GFP_KERNEL);
+	tmp_attrs = alloc_workqueue_attrs(GFP_KERNEL);
+	if (!pwq_tbl || !new_attrs || !tmp_attrs)
+		goto enomem;
+
+	/* make a copy of @attrs and sanitize it */
+	copy_workqueue_attrs(new_attrs, attrs);
+	cpumask_and(new_attrs->cpumask, new_attrs->cpumask, cpu_possible_mask);
+
+	/*
+	 * We may create multiple pwqs with differing cpumasks.  Make a
+	 * copy of @new_attrs which will be modified and used to obtain
+	 * pools.
+	 */
+	copy_workqueue_attrs(tmp_attrs, new_attrs);
+
+	/*
+	 * CPUs should stay stable across pwq creations and installations.
+	 * Pin CPUs, determine the target cpumask for each node and create
+	 * pwqs accordingly.
+	 */
+	get_online_cpus();
+
+	mutex_lock(&wq_pool_mutex);
+
+	/*
+	 * If something goes wrong during CPU up/down, we'll fall back to
+	 * the default pwq covering whole @attrs->cpumask.  Always create
+	 * it even if we don't use it immediately.
+	 */
+	dfl_pwq = alloc_unbound_pwq(wq, new_attrs);
+	if (!dfl_pwq)
+		goto enomem_pwq;
+
+	for_each_node(node) {
+		if (wq_calc_node_cpumask(attrs, node, -1, tmp_attrs->cpumask)) {
+			pwq_tbl[node] = alloc_unbound_pwq(wq, tmp_attrs);
+			if (!pwq_tbl[node])
+				goto enomem_pwq;
+		} else {
+			dfl_pwq->refcnt++;
+			pwq_tbl[node] = dfl_pwq;
+		}
+	}
+
+	mutex_unlock(&wq_pool_mutex);
+
+	/* all pwqs have been created successfully, let's install'em */
+	mutex_lock(&wq->mutex);
+
+	copy_workqueue_attrs(wq->unbound_attrs, new_attrs);
+
+	/* save the previous pwq and install the new one */
+	for_each_node(node)
+		pwq_tbl[node] = numa_pwq_tbl_install(wq, node, pwq_tbl[node]);
+
+	/* @dfl_pwq might not have been used, ensure it's linked */
+	link_pwq(dfl_pwq);
+	swap(wq->dfl_pwq, dfl_pwq);
+
+	mutex_unlock(&wq->mutex);
+
+	/* put the old pwqs */
+	for_each_node(node)
+		put_pwq_unlocked(pwq_tbl[node]);
+	put_pwq_unlocked(dfl_pwq);
+
+	put_online_cpus();
+	ret = 0;
+	/* fall through */
+out_free:
+	free_workqueue_attrs(tmp_attrs);
+	free_workqueue_attrs(new_attrs);
+	kfree(pwq_tbl);
+	return ret;
+
+enomem_pwq:
+	free_unbound_pwq(dfl_pwq);
+	for_each_node(node)
+		if (pwq_tbl && pwq_tbl[node] != dfl_pwq)
+			free_unbound_pwq(pwq_tbl[node]);
+	mutex_unlock(&wq_pool_mutex);
+	put_online_cpus();
+enomem:
+	ret = -ENOMEM;
+	goto out_free;
+}
+
+/**
+ * wq_update_unbound_numa - update NUMA affinity of a wq for CPU hot[un]plug
+ * @wq: the target workqueue
+ * @cpu: the CPU coming up or going down
+ * @online: whether @cpu is coming up or going down
+ *
+ * This function is to be called from %CPU_DOWN_PREPARE, %CPU_ONLINE and
+ * %CPU_DOWN_FAILED.  @cpu is being hot[un]plugged, update NUMA affinity of
+ * @wq accordingly.
+ *
+ * If NUMA affinity can't be adjusted due to memory allocation failure, it
+ * falls back to @wq->dfl_pwq which may not be optimal but is always
+ * correct.
+ *
+ * Note that when the last allowed CPU of a NUMA node goes offline for a
+ * workqueue with a cpumask spanning multiple nodes, the workers which were
+ * already executing the work items for the workqueue will lose their CPU
+ * affinity and may execute on any CPU.  This is similar to how per-cpu
+ * workqueues behave on CPU_DOWN.  If a workqueue user wants strict
+ * affinity, it's the user's responsibility to flush the work item from
+ * CPU_DOWN_PREPARE.
+ */
+static void wq_update_unbound_numa(struct workqueue_struct *wq, int cpu,
+				   bool online)
+{
+	int node = cpu_to_node(cpu);
+	int cpu_off = online ? -1 : cpu;
+	struct pool_workqueue *old_pwq = NULL, *pwq;
+	struct workqueue_attrs *target_attrs;
+	cpumask_t *cpumask;
+
+	lockdep_assert_held(&wq_pool_mutex);
+
+	if (!wq_numa_enabled || !(wq->flags & WQ_UNBOUND))
+		return;
+
+	/*
+	 * We don't wanna alloc/free wq_attrs for each wq for each CPU.
+	 * Let's use a preallocated one.  The following buf is protected by
+	 * CPU hotplug exclusion.
+	 */
+	target_attrs = wq_update_unbound_numa_attrs_buf;
+	cpumask = target_attrs->cpumask;
+
+	mutex_lock(&wq->mutex);
+	if (wq->unbound_attrs->no_numa)
+		goto out_unlock;
+
+	copy_workqueue_attrs(target_attrs, wq->unbound_attrs);
+	pwq = unbound_pwq_by_node(wq, node);
+
+	/*
+	 * Let's determine what needs to be done.  If the target cpumask is
+	 * different from wq's, we need to compare it to @pwq's and create
+	 * a new one if they don't match.  If the target cpumask equals
+	 * wq's, the default pwq should be used.  If @pwq is already the
+	 * default one, nothing to do; otherwise, install the default one.
+	 */
+	if (wq_calc_node_cpumask(wq->unbound_attrs, node, cpu_off, cpumask)) {
+		if (cpumask_equal(cpumask, pwq->pool->attrs->cpumask))
+			goto out_unlock;
+	} else {
+		if (pwq == wq->dfl_pwq)
+			goto out_unlock;
+		else
+			goto use_dfl_pwq;
+	}
+
+	mutex_unlock(&wq->mutex);
+
+	/* create a new pwq */
+	pwq = alloc_unbound_pwq(wq, target_attrs);
+	if (!pwq) {
+		pr_warning("workqueue: allocation failed while updating NUMA affinity of \"%s\"\n",
+			   wq->name);
+		goto out_unlock;
+	}
+
+	/*
+	 * Install the new pwq.  As this function is called only from CPU
+	 * hotplug callbacks and applying a new attrs is wrapped with
+	 * get/put_online_cpus(), @wq->unbound_attrs couldn't have changed
+	 * inbetween.
+	 */
+	mutex_lock(&wq->mutex);
+	old_pwq = numa_pwq_tbl_install(wq, node, pwq);
+	goto out_unlock;
+
+use_dfl_pwq:
+	spin_lock_irq(&wq->dfl_pwq->pool->lock);
+	get_pwq(wq->dfl_pwq);
+	spin_unlock_irq(&wq->dfl_pwq->pool->lock);
+	old_pwq = numa_pwq_tbl_install(wq, node, wq->dfl_pwq);
+out_unlock:
+	mutex_unlock(&wq->mutex);
+	put_pwq_unlocked(old_pwq);
+}
+
+static int alloc_and_link_pwqs(struct workqueue_struct *wq)
+{
+	bool highpri = wq->flags & WQ_HIGHPRI;
+	int cpu;
+
+	if (!(wq->flags & WQ_UNBOUND)) {
+		wq->cpu_pwqs = alloc_percpu(struct pool_workqueue);
+		if (!wq->cpu_pwqs)
+			return -ENOMEM;
+
+		for_each_possible_cpu(cpu) {
+			struct pool_workqueue *pwq =
+				per_cpu_ptr(wq->cpu_pwqs, cpu);
+			struct worker_pool *cpu_pools =
+				per_cpu(cpu_worker_pools, cpu);
+
+			init_pwq(pwq, wq, &cpu_pools[highpri]);
+
+			mutex_lock(&wq->mutex);
+			link_pwq(pwq);
+			mutex_unlock(&wq->mutex);
+		}
+		return 0;
+	} else {
+		return apply_workqueue_attrs(wq, unbound_std_wq_attrs[highpri]);
+	}
+}
+
+static int wq_clamp_max_active(int max_active, unsigned int flags,
+			       const char *name)
+{
+	int lim = flags & WQ_UNBOUND ? WQ_UNBOUND_MAX_ACTIVE : WQ_MAX_ACTIVE;
+
+	if (max_active < 1 || max_active > lim)
+		pr_warn("workqueue: max_active %d requested for %s is out of range, clamping between %d and %d\n",
+			max_active, name, 1, lim);
+
+	return clamp_val(max_active, 1, lim);
+}
+
+struct workqueue_struct *__alloc_workqueue_key(const char *fmt,
+					       unsigned int flags,
+					       int max_active,
+					       struct lock_class_key *key,
+					       const char *lock_name, ...)
+{
+	size_t tbl_size = 0;
+	va_list args;
+	struct workqueue_struct *wq;
+	struct pool_workqueue *pwq;
+
+	/* allocate wq and format name */
+	if (flags & WQ_UNBOUND)
+		tbl_size = wq_numa_tbl_len * sizeof(wq->numa_pwq_tbl[0]);
 
-		if (!(wq->flags & WQ_FREEZABLE) ||
-		    !(pool->flags & POOL_FREEZING))
-			pwq_set_max_active(pwq, max_active);
+	wq = kzalloc(sizeof(*wq) + tbl_size, GFP_KERNEL);
+	if (!wq)
+		return NULL;
 
-		spin_unlock_irq(&pool->lock);
+	if (flags & WQ_UNBOUND) {
+		wq->unbound_attrs = alloc_workqueue_attrs(GFP_KERNEL);
+		if (!wq->unbound_attrs)
+			goto err_free_wq;
+	}
+
+	va_start(args, lock_name);
+	vsnprintf(wq->name, sizeof(wq->name), fmt, args);
+	va_end(args);
+
+	max_active = max_active ?: WQ_DFL_ACTIVE;
+	max_active = wq_clamp_max_active(max_active, flags, wq->name);
+
+	/* init wq */
+	wq->flags = flags;
+	wq->saved_max_active = max_active;
+	mutex_init(&wq->mutex);
+	atomic_set(&wq->nr_pwqs_to_flush, 0);
+	INIT_LIST_HEAD(&wq->pwqs);
+	INIT_LIST_HEAD(&wq->flusher_queue);
+	INIT_LIST_HEAD(&wq->flusher_overflow);
+	INIT_LIST_HEAD(&wq->maydays);
+
+	lockdep_init_map(&wq->lockdep_map, lock_name, key, 0);
+	INIT_LIST_HEAD(&wq->list);
+
+	if (alloc_and_link_pwqs(wq) < 0)
+		goto err_free_wq;
+
+	/*
+	 * Workqueues which may be used during memory reclaim should
+	 * have a rescuer to guarantee forward progress.
+	 */
+	if (flags & WQ_MEM_RECLAIM) {
+		struct worker *rescuer;
+
+		rescuer = alloc_worker();
+		if (!rescuer)
+			goto err_destroy;
+
+		rescuer->rescue_wq = wq;
+		rescuer->task = kthread_create(rescuer_thread, rescuer, "%s",
+					       wq->name);
+		if (IS_ERR(rescuer->task)) {
+			kfree(rescuer);
+			goto err_destroy;
+		}
+
+		wq->rescuer = rescuer;
+		rescuer->task->flags |= PF_NO_SETAFFINITY;
+		wake_up_process(rescuer->task);
+	}
+
+	if ((wq->flags & WQ_SYSFS) && workqueue_sysfs_register(wq))
+		goto err_destroy;
+
+	/*
+	 * wq_pool_mutex protects global freeze state and workqueues list.
+	 * Grab it, adjust max_active and add the new @wq to workqueues
+	 * list.
+	 */
+	mutex_lock(&wq_pool_mutex);
+
+	mutex_lock(&wq->mutex);
+	for_each_pwq(pwq, wq)
+		pwq_adjust_max_active(pwq);
+	mutex_unlock(&wq->mutex);
+
+	list_add(&wq->list, &workqueues);
+
+	mutex_unlock(&wq_pool_mutex);
+
+	return wq;
+
+err_free_wq:
+	free_workqueue_attrs(wq->unbound_attrs);
+	kfree(wq);
+	return NULL;
+err_destroy:
+	destroy_workqueue(wq);
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(__alloc_workqueue_key);
+
+/**
+ * destroy_workqueue - safely terminate a workqueue
+ * @wq: target workqueue
+ *
+ * Safely destroy a workqueue. All work currently pending will be done first.
+ */
+void destroy_workqueue(struct workqueue_struct *wq)
+{
+	struct pool_workqueue *pwq;
+	int node;
+
+	/* drain it before proceeding with destruction */
+	drain_workqueue(wq);
+
+	/* sanity checks */
+	mutex_lock(&wq->mutex);
+	for_each_pwq(pwq, wq) {
+		int i;
+
+		for (i = 0; i < WORK_NR_COLORS; i++) {
+			if (WARN_ON(pwq->nr_in_flight[i])) {
+				mutex_unlock(&wq->mutex);
+				return;
+			}
+		}
+
+		if (WARN_ON((pwq != wq->dfl_pwq) && (pwq->refcnt > 1)) ||
+		    WARN_ON(pwq->nr_active) ||
+		    WARN_ON(!list_empty(&pwq->delayed_works))) {
+			mutex_unlock(&wq->mutex);
+			return;
+		}
+	}
+	mutex_unlock(&wq->mutex);
+
+	/*
+	 * wq list is used to freeze wq, remove from list after
+	 * flushing is complete in case freeze races us.
+	 */
+	mutex_lock(&wq_pool_mutex);
+	list_del_init(&wq->list);
+	mutex_unlock(&wq_pool_mutex);
+
+	workqueue_sysfs_unregister(wq);
+
+	if (wq->rescuer) {
+		kthread_stop(wq->rescuer->task);
+		kfree(wq->rescuer);
+		wq->rescuer = NULL;
+	}
+
+	if (!(wq->flags & WQ_UNBOUND)) {
+		/*
+		 * The base ref is never dropped on per-cpu pwqs.  Directly
+		 * free the pwqs and wq.
+		 */
+		free_percpu(wq->cpu_pwqs);
+		kfree(wq);
+	} else {
+		/*
+		 * We're the sole accessor of @wq at this point.  Directly
+		 * access numa_pwq_tbl[] and dfl_pwq to put the base refs.
+		 * @wq will be freed when the last pwq is released.
+		 */
+		for_each_node(node) {
+			pwq = rcu_access_pointer(wq->numa_pwq_tbl[node]);
+			RCU_INIT_POINTER(wq->numa_pwq_tbl[node], NULL);
+			put_pwq_unlocked(pwq);
+		}
+
+		/*
+		 * Put dfl_pwq.  @wq may be freed any time after dfl_pwq is
+		 * put.  Don't access it afterwards.
+		 */
+		pwq = wq->dfl_pwq;
+		wq->dfl_pwq = NULL;
+		put_pwq_unlocked(pwq);
 	}
+}
+EXPORT_SYMBOL_GPL(destroy_workqueue);
+
+/**
+ * workqueue_set_max_active - adjust max_active of a workqueue
+ * @wq: target workqueue
+ * @max_active: new max_active value.
+ *
+ * Set max_active of @wq to @max_active.
+ *
+ * CONTEXT:
+ * Don't call from IRQ context.
+ */
+void workqueue_set_max_active(struct workqueue_struct *wq, int max_active)
+{
+	struct pool_workqueue *pwq;
 
-	spin_unlock(&workqueue_lock);
+	/* disallow meddling with max_active for ordered workqueues */
+	if (WARN_ON(wq->flags & __WQ_ORDERED))
+		return;
+
+	max_active = wq_clamp_max_active(max_active, wq->flags, wq->name);
+
+	mutex_lock(&wq->mutex);
+
+	wq->saved_max_active = max_active;
+
+	for_each_pwq(pwq, wq)
+		pwq_adjust_max_active(pwq);
+
+	mutex_unlock(&wq->mutex);
 }
 EXPORT_SYMBOL_GPL(workqueue_set_max_active);
 
 /**
+ * current_is_workqueue_rescuer - is %current workqueue rescuer?
+ *
+ * Determine whether %current is a workqueue rescuer.  Can be used from
+ * work functions to determine whether it's being run off the rescuer task.
+ */
+bool current_is_workqueue_rescuer(void)
+{
+	struct worker *worker = current_wq_worker();
+
+	return worker && worker->rescue_wq;
+}
+
+/**
  * workqueue_congested - test whether a workqueue is congested
  * @cpu: CPU in question
  * @wq: target workqueue
@@ -3363,11 +4312,22 @@ EXPORT_SYMBOL_GPL(workqueue_set_max_active);
  * RETURNS:
  * %true if congested, %false otherwise.
  */
-bool workqueue_congested(unsigned int cpu, struct workqueue_struct *wq)
+bool workqueue_congested(int cpu, struct workqueue_struct *wq)
 {
-	struct pool_workqueue *pwq = get_pwq(cpu, wq);
+	struct pool_workqueue *pwq;
+	bool ret;
 
-	return !list_empty(&pwq->delayed_works);
+	rcu_read_lock_sched();
+
+	if (!(wq->flags & WQ_UNBOUND))
+		pwq = per_cpu_ptr(wq->cpu_pwqs, cpu);
+	else
+		pwq = unbound_pwq_by_node(wq, cpu_to_node(cpu));
+
+	ret = !list_empty(&pwq->delayed_works);
+	rcu_read_unlock_sched();
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(workqueue_congested);
 
@@ -3384,19 +4344,22 @@ EXPORT_SYMBOL_GPL(workqueue_congested);
  */
 unsigned int work_busy(struct work_struct *work)
 {
-	struct worker_pool *pool = get_work_pool(work);
+	struct worker_pool *pool;
 	unsigned long flags;
 	unsigned int ret = 0;
 
 	if (work_pending(work))
 		ret |= WORK_BUSY_PENDING;
 
+	local_irq_save(flags);
+	pool = get_work_pool(work);
 	if (pool) {
-		spin_lock_irqsave(&pool->lock, flags);
+		spin_lock(&pool->lock);
 		if (find_worker_executing_work(pool, work))
 			ret |= WORK_BUSY_RUNNING;
-		spin_unlock_irqrestore(&pool->lock, flags);
+		spin_unlock(&pool->lock);
 	}
+	local_irq_restore(flags);
 
 	return ret;
 }
@@ -3422,31 +4385,28 @@ static void wq_unbind_fn(struct work_struct *work)
 	int cpu = smp_processor_id();
 	struct worker_pool *pool;
 	struct worker *worker;
-	int i;
+	int wi;
 
-	for_each_std_worker_pool(pool, cpu) {
-		BUG_ON(cpu != smp_processor_id());
+	for_each_cpu_worker_pool(pool, cpu) {
+		WARN_ON_ONCE(cpu != smp_processor_id());
 
-		mutex_lock(&pool->assoc_mutex);
+		mutex_lock(&pool->manager_mutex);
 		spin_lock_irq(&pool->lock);
 
 		/*
-		 * We've claimed all manager positions.  Make all workers
+		 * We've blocked all manager operations.  Make all workers
 		 * unbound and set DISASSOCIATED.  Before this, all workers
 		 * except for the ones which are still executing works from
 		 * before the last CPU down must be on the cpu.  After
 		 * this, they may become diasporas.
 		 */
-		list_for_each_entry(worker, &pool->idle_list, entry)
-			worker->flags |= WORKER_UNBOUND;
-
-		for_each_busy_worker(worker, i, pool)
+		for_each_pool_worker(worker, wi, pool)
 			worker->flags |= WORKER_UNBOUND;
 
 		pool->flags |= POOL_DISASSOCIATED;
 
 		spin_unlock_irq(&pool->lock);
-		mutex_unlock(&pool->assoc_mutex);
+		mutex_unlock(&pool->manager_mutex);
 
 		/*
 		 * Call schedule() so that we cross rq->lock and thus can
@@ -3477,6 +4437,103 @@ static void wq_unbind_fn(struct work_struct *work)
 	}
 }
 
+/**
+ * rebind_workers - rebind all workers of a pool to the associated CPU
+ * @pool: pool of interest
+ *
+ * @pool->cpu is coming online.  Rebind all workers to the CPU.
+ */
+static void rebind_workers(struct worker_pool *pool)
+{
+	struct worker *worker;
+	int wi;
+
+	lockdep_assert_held(&pool->manager_mutex);
+
+	/*
+	 * Restore CPU affinity of all workers.  As all idle workers should
+	 * be on the run-queue of the associated CPU before any local
+	 * wake-ups for concurrency management happen, restore CPU affinty
+	 * of all workers first and then clear UNBOUND.  As we're called
+	 * from CPU_ONLINE, the following shouldn't fail.
+	 */
+	for_each_pool_worker(worker, wi, pool)
+		WARN_ON_ONCE(set_cpus_allowed_ptr(worker->task,
+						  pool->attrs->cpumask) < 0);
+
+	spin_lock_irq(&pool->lock);
+
+	for_each_pool_worker(worker, wi, pool) {
+		unsigned int worker_flags = worker->flags;
+
+		/*
+		 * A bound idle worker should actually be on the runqueue
+		 * of the associated CPU for local wake-ups targeting it to
+		 * work.  Kick all idle workers so that they migrate to the
+		 * associated CPU.  Doing this in the same loop as
+		 * replacing UNBOUND with REBOUND is safe as no worker will
+		 * be bound before @pool->lock is released.
+		 */
+		if (worker_flags & WORKER_IDLE)
+			wake_up_process(worker->task);
+
+		/*
+		 * We want to clear UNBOUND but can't directly call
+		 * worker_clr_flags() or adjust nr_running.  Atomically
+		 * replace UNBOUND with another NOT_RUNNING flag REBOUND.
+		 * @worker will clear REBOUND using worker_clr_flags() when
+		 * it initiates the next execution cycle thus restoring
+		 * concurrency management.  Note that when or whether
+		 * @worker clears REBOUND doesn't affect correctness.
+		 *
+		 * ACCESS_ONCE() is necessary because @worker->flags may be
+		 * tested without holding any lock in
+		 * wq_worker_waking_up().  Without it, NOT_RUNNING test may
+		 * fail incorrectly leading to premature concurrency
+		 * management operations.
+		 */
+		WARN_ON_ONCE(!(worker_flags & WORKER_UNBOUND));
+		worker_flags |= WORKER_REBOUND;
+		worker_flags &= ~WORKER_UNBOUND;
+		ACCESS_ONCE(worker->flags) = worker_flags;
+	}
+
+	spin_unlock_irq(&pool->lock);
+}
+
+/**
+ * restore_unbound_workers_cpumask - restore cpumask of unbound workers
+ * @pool: unbound pool of interest
+ * @cpu: the CPU which is coming up
+ *
+ * An unbound pool may end up with a cpumask which doesn't have any online
+ * CPUs.  When a worker of such pool get scheduled, the scheduler resets
+ * its cpus_allowed.  If @cpu is in @pool's cpumask which didn't have any
+ * online CPU before, cpus_allowed of all its workers should be restored.
+ */
+static void restore_unbound_workers_cpumask(struct worker_pool *pool, int cpu)
+{
+	static cpumask_t cpumask;
+	struct worker *worker;
+	int wi;
+
+	lockdep_assert_held(&pool->manager_mutex);
+
+	/* is @cpu allowed for @pool? */
+	if (!cpumask_test_cpu(cpu, pool->attrs->cpumask))
+		return;
+
+	/* is @cpu the only online CPU? */
+	cpumask_and(&cpumask, pool->attrs->cpumask, cpu_online_mask);
+	if (cpumask_weight(&cpumask) != 1)
+		return;
+
+	/* as we're called from CPU_ONLINE, the following shouldn't fail */
+	for_each_pool_worker(worker, wi, pool)
+		WARN_ON_ONCE(set_cpus_allowed_ptr(worker->task,
+						  pool->attrs->cpumask) < 0);
+}
+
 /*
  * Workqueues should be brought up before normal priority CPU notifiers.
  * This will be registered high priority CPU notifier.
@@ -3485,39 +4542,46 @@ static int __cpuinit workqueue_cpu_up_callback(struct notifier_block *nfb,
 					       unsigned long action,
 					       void *hcpu)
 {
-	unsigned int cpu = (unsigned long)hcpu;
+	int cpu = (unsigned long)hcpu;
 	struct worker_pool *pool;
+	struct workqueue_struct *wq;
+	int pi;
 
 	switch (action & ~CPU_TASKS_FROZEN) {
 	case CPU_UP_PREPARE:
-		for_each_std_worker_pool(pool, cpu) {
-			struct worker *worker;
-
+		for_each_cpu_worker_pool(pool, cpu) {
 			if (pool->nr_workers)
 				continue;
-
-			worker = create_worker(pool);
-			if (!worker)
+			if (create_and_start_worker(pool) < 0)
 				return NOTIFY_BAD;
-
-			spin_lock_irq(&pool->lock);
-			start_worker(worker);
-			spin_unlock_irq(&pool->lock);
 		}
 		break;
 
 	case CPU_DOWN_FAILED:
 	case CPU_ONLINE:
-		for_each_std_worker_pool(pool, cpu) {
-			mutex_lock(&pool->assoc_mutex);
-			spin_lock_irq(&pool->lock);
+		mutex_lock(&wq_pool_mutex);
 
-			pool->flags &= ~POOL_DISASSOCIATED;
-			rebind_workers(pool);
+		for_each_pool(pool, pi) {
+			mutex_lock(&pool->manager_mutex);
+
+			if (pool->cpu == cpu) {
+				spin_lock_irq(&pool->lock);
+				pool->flags &= ~POOL_DISASSOCIATED;
+				spin_unlock_irq(&pool->lock);
+
+				rebind_workers(pool);
+			} else if (pool->cpu < 0) {
+				restore_unbound_workers_cpumask(pool, cpu);
+			}
 
-			spin_unlock_irq(&pool->lock);
-			mutex_unlock(&pool->assoc_mutex);
+			mutex_unlock(&pool->manager_mutex);
 		}
+
+		/* update NUMA affinity of unbound workqueues */
+		list_for_each_entry(wq, &workqueues, list)
+			wq_update_unbound_numa(wq, cpu, true);
+
+		mutex_unlock(&wq_pool_mutex);
 		break;
 	}
 	return NOTIFY_OK;
@@ -3531,14 +4595,23 @@ static int __cpuinit workqueue_cpu_down_callback(struct notifier_block *nfb,
 						 unsigned long action,
 						 void *hcpu)
 {
-	unsigned int cpu = (unsigned long)hcpu;
+	int cpu = (unsigned long)hcpu;
 	struct work_struct unbind_work;
+	struct workqueue_struct *wq;
 
 	switch (action & ~CPU_TASKS_FROZEN) {
 	case CPU_DOWN_PREPARE:
-		/* unbinding should happen on the local CPU */
+		/* unbinding per-cpu workers should happen on the local CPU */
 		INIT_WORK_ONSTACK(&unbind_work, wq_unbind_fn);
 		queue_work_on(cpu, system_highpri_wq, &unbind_work);
+
+		/* update NUMA affinity of unbound workqueues */
+		mutex_lock(&wq_pool_mutex);
+		list_for_each_entry(wq, &workqueues, list)
+			wq_update_unbound_numa(wq, cpu, false);
+		mutex_unlock(&wq_pool_mutex);
+
+		/* wait for per-cpu unbinding to finish */
 		flush_work(&unbind_work);
 		break;
 	}
@@ -3571,7 +4644,7 @@ static void work_for_cpu_fn(struct work_struct *work)
  * It is up to the caller to ensure that the cpu doesn't go offline.
  * The caller must not hold any locks which would prevent @fn from completing.
  */
-long work_on_cpu(unsigned int cpu, long (*fn)(void *), void *arg)
+long work_on_cpu(int cpu, long (*fn)(void *), void *arg)
 {
 	struct work_for_cpu wfc = { .fn = fn, .arg = arg };
 
@@ -3589,44 +4662,40 @@ EXPORT_SYMBOL_GPL(work_on_cpu);
  * freeze_workqueues_begin - begin freezing workqueues
  *
  * Start freezing workqueues.  After this function returns, all freezable
- * workqueues will queue new works to their frozen_works list instead of
+ * workqueues will queue new works to their delayed_works list instead of
  * pool->worklist.
  *
  * CONTEXT:
- * Grabs and releases workqueue_lock and pool->lock's.
+ * Grabs and releases wq_pool_mutex, wq->mutex and pool->lock's.
  */
 void freeze_workqueues_begin(void)
 {
-	unsigned int cpu;
+	struct worker_pool *pool;
+	struct workqueue_struct *wq;
+	struct pool_workqueue *pwq;
+	int pi;
 
-	spin_lock(&workqueue_lock);
+	mutex_lock(&wq_pool_mutex);
 
-	BUG_ON(workqueue_freezing);
+	WARN_ON_ONCE(workqueue_freezing);
 	workqueue_freezing = true;
 
-	for_each_wq_cpu(cpu) {
-		struct worker_pool *pool;
-		struct workqueue_struct *wq;
-
-		for_each_std_worker_pool(pool, cpu) {
-			spin_lock_irq(&pool->lock);
-
-			WARN_ON_ONCE(pool->flags & POOL_FREEZING);
-			pool->flags |= POOL_FREEZING;
-
-			list_for_each_entry(wq, &workqueues, list) {
-				struct pool_workqueue *pwq = get_pwq(cpu, wq);
-
-				if (pwq && pwq->pool == pool &&
-				    (wq->flags & WQ_FREEZABLE))
-					pwq->max_active = 0;
-			}
+	/* set FREEZING */
+	for_each_pool(pool, pi) {
+		spin_lock_irq(&pool->lock);
+		WARN_ON_ONCE(pool->flags & POOL_FREEZING);
+		pool->flags |= POOL_FREEZING;
+		spin_unlock_irq(&pool->lock);
+	}
 
-			spin_unlock_irq(&pool->lock);
-		}
+	list_for_each_entry(wq, &workqueues, list) {
+		mutex_lock(&wq->mutex);
+		for_each_pwq(pwq, wq)
+			pwq_adjust_max_active(pwq);
+		mutex_unlock(&wq->mutex);
 	}
 
-	spin_unlock(&workqueue_lock);
+	mutex_unlock(&wq_pool_mutex);
 }
 
 /**
@@ -3636,7 +4705,7 @@ void freeze_workqueues_begin(void)
  * between freeze_workqueues_begin() and thaw_workqueues().
  *
  * CONTEXT:
- * Grabs and releases workqueue_lock.
+ * Grabs and releases wq_pool_mutex.
  *
  * RETURNS:
  * %true if some freezable workqueues are still busy.  %false if freezing
@@ -3644,34 +4713,34 @@ void freeze_workqueues_begin(void)
  */
 bool freeze_workqueues_busy(void)
 {
-	unsigned int cpu;
 	bool busy = false;
+	struct workqueue_struct *wq;
+	struct pool_workqueue *pwq;
 
-	spin_lock(&workqueue_lock);
+	mutex_lock(&wq_pool_mutex);
 
-	BUG_ON(!workqueue_freezing);
+	WARN_ON_ONCE(!workqueue_freezing);
 
-	for_each_wq_cpu(cpu) {
-		struct workqueue_struct *wq;
+	list_for_each_entry(wq, &workqueues, list) {
+		if (!(wq->flags & WQ_FREEZABLE))
+			continue;
 		/*
 		 * nr_active is monotonically decreasing.  It's safe
 		 * to peek without lock.
 		 */
-		list_for_each_entry(wq, &workqueues, list) {
-			struct pool_workqueue *pwq = get_pwq(cpu, wq);
-
-			if (!pwq || !(wq->flags & WQ_FREEZABLE))
-				continue;
-
-			BUG_ON(pwq->nr_active < 0);
+		rcu_read_lock_sched();
+		for_each_pwq(pwq, wq) {
+			WARN_ON_ONCE(pwq->nr_active < 0);
 			if (pwq->nr_active) {
 				busy = true;
+				rcu_read_unlock_sched();
 				goto out_unlock;
 			}
 		}
+		rcu_read_unlock_sched();
 	}
 out_unlock:
-	spin_unlock(&workqueue_lock);
+	mutex_unlock(&wq_pool_mutex);
 	return busy;
 }
 
@@ -3682,104 +4751,141 @@ out_unlock:
  * frozen works are transferred to their respective pool worklists.
  *
  * CONTEXT:
- * Grabs and releases workqueue_lock and pool->lock's.
+ * Grabs and releases wq_pool_mutex, wq->mutex and pool->lock's.
  */
 void thaw_workqueues(void)
 {
-	unsigned int cpu;
+	struct workqueue_struct *wq;
+	struct pool_workqueue *pwq;
+	struct worker_pool *pool;
+	int pi;
 
-	spin_lock(&workqueue_lock);
+	mutex_lock(&wq_pool_mutex);
 
 	if (!workqueue_freezing)
 		goto out_unlock;
 
-	for_each_wq_cpu(cpu) {
-		struct worker_pool *pool;
-		struct workqueue_struct *wq;
+	/* clear FREEZING */
+	for_each_pool(pool, pi) {
+		spin_lock_irq(&pool->lock);
+		WARN_ON_ONCE(!(pool->flags & POOL_FREEZING));
+		pool->flags &= ~POOL_FREEZING;
+		spin_unlock_irq(&pool->lock);
+	}
 
-		for_each_std_worker_pool(pool, cpu) {
-			spin_lock_irq(&pool->lock);
+	/* restore max_active and repopulate worklist */
+	list_for_each_entry(wq, &workqueues, list) {
+		mutex_lock(&wq->mutex);
+		for_each_pwq(pwq, wq)
+			pwq_adjust_max_active(pwq);
+		mutex_unlock(&wq->mutex);
+	}
 
-			WARN_ON_ONCE(!(pool->flags & POOL_FREEZING));
-			pool->flags &= ~POOL_FREEZING;
+	workqueue_freezing = false;
+out_unlock:
+	mutex_unlock(&wq_pool_mutex);
+}
+#endif /* CONFIG_FREEZER */
 
-			list_for_each_entry(wq, &workqueues, list) {
-				struct pool_workqueue *pwq = get_pwq(cpu, wq);
+static void __init wq_numa_init(void)
+{
+	cpumask_var_t *tbl;
+	int node, cpu;
 
-				if (!pwq || pwq->pool != pool ||
-				    !(wq->flags & WQ_FREEZABLE))
-					continue;
+	/* determine NUMA pwq table len - highest node id + 1 */
+	for_each_node(node)
+		wq_numa_tbl_len = max(wq_numa_tbl_len, node + 1);
 
-				/* restore max_active and repopulate worklist */
-				pwq_set_max_active(pwq, wq->saved_max_active);
-			}
+	if (num_possible_nodes() <= 1)
+		return;
 
-			wake_up_worker(pool);
+	if (wq_disable_numa) {
+		pr_info("workqueue: NUMA affinity support disabled\n");
+		return;
+	}
 
-			spin_unlock_irq(&pool->lock);
+	wq_update_unbound_numa_attrs_buf = alloc_workqueue_attrs(GFP_KERNEL);
+	BUG_ON(!wq_update_unbound_numa_attrs_buf);
+
+	/*
+	 * We want masks of possible CPUs of each node which isn't readily
+	 * available.  Build one from cpu_to_node() which should have been
+	 * fully initialized by now.
+	 */
+	tbl = kzalloc(wq_numa_tbl_len * sizeof(tbl[0]), GFP_KERNEL);
+	BUG_ON(!tbl);
+
+	for_each_node(node)
+		BUG_ON(!alloc_cpumask_var_node(&tbl[node], GFP_KERNEL, node));
+
+	for_each_possible_cpu(cpu) {
+		node = cpu_to_node(cpu);
+		if (WARN_ON(node == NUMA_NO_NODE)) {
+			pr_warn("workqueue: NUMA node mapping not available for cpu%d, disabling NUMA support\n", cpu);
+			/* happens iff arch is bonkers, let's just proceed */
+			return;
 		}
+		cpumask_set_cpu(cpu, tbl[node]);
 	}
 
-	workqueue_freezing = false;
-out_unlock:
-	spin_unlock(&workqueue_lock);
+	wq_numa_possible_cpumask = tbl;
+	wq_numa_enabled = true;
 }
-#endif /* CONFIG_FREEZER */
 
 static int __init init_workqueues(void)
 {
-	unsigned int cpu;
+	int std_nice[NR_STD_WORKER_POOLS] = { 0, HIGHPRI_NICE_LEVEL };
+	int i, cpu;
 
 	/* make sure we have enough bits for OFFQ pool ID */
 	BUILD_BUG_ON((1LU << (BITS_PER_LONG - WORK_OFFQ_POOL_SHIFT)) <
 		     WORK_CPU_END * NR_STD_WORKER_POOLS);
 
+	WARN_ON(__alignof__(struct pool_workqueue) < __alignof__(long long));
+
+	pwq_cache = KMEM_CACHE(pool_workqueue, SLAB_PANIC);
+
 	cpu_notifier(workqueue_cpu_up_callback, CPU_PRI_WORKQUEUE_UP);
 	hotcpu_notifier(workqueue_cpu_down_callback, CPU_PRI_WORKQUEUE_DOWN);
 
+	wq_numa_init();
+
 	/* initialize CPU pools */
-	for_each_wq_cpu(cpu) {
+	for_each_possible_cpu(cpu) {
 		struct worker_pool *pool;
 
-		for_each_std_worker_pool(pool, cpu) {
-			spin_lock_init(&pool->lock);
+		i = 0;
+		for_each_cpu_worker_pool(pool, cpu) {
+			BUG_ON(init_worker_pool(pool));
 			pool->cpu = cpu;
-			pool->flags |= POOL_DISASSOCIATED;
-			INIT_LIST_HEAD(&pool->worklist);
-			INIT_LIST_HEAD(&pool->idle_list);
-			hash_init(pool->busy_hash);
-
-			init_timer_deferrable(&pool->idle_timer);
-			pool->idle_timer.function = idle_worker_timeout;
-			pool->idle_timer.data = (unsigned long)pool;
-
-			setup_timer(&pool->mayday_timer, pool_mayday_timeout,
-				    (unsigned long)pool);
-
-			mutex_init(&pool->assoc_mutex);
-			ida_init(&pool->worker_ida);
+			cpumask_copy(pool->attrs->cpumask, cpumask_of(cpu));
+			pool->attrs->nice = std_nice[i++];
+			pool->node = cpu_to_node(cpu);
 
 			/* alloc pool ID */
+			mutex_lock(&wq_pool_mutex);
 			BUG_ON(worker_pool_assign_id(pool));
+			mutex_unlock(&wq_pool_mutex);
 		}
 	}
 
 	/* create the initial worker */
-	for_each_online_wq_cpu(cpu) {
+	for_each_online_cpu(cpu) {
 		struct worker_pool *pool;
 
-		for_each_std_worker_pool(pool, cpu) {
-			struct worker *worker;
+		for_each_cpu_worker_pool(pool, cpu) {
+			pool->flags &= ~POOL_DISASSOCIATED;
+			BUG_ON(create_and_start_worker(pool) < 0);
+		}
+	}
 
-			if (cpu != WORK_CPU_UNBOUND)
-				pool->flags &= ~POOL_DISASSOCIATED;
+	/* create default unbound wq attrs */
+	for (i = 0; i < NR_STD_WORKER_POOLS; i++) {
+		struct workqueue_attrs *attrs;
 
-			worker = create_worker(pool);
-			BUG_ON(!worker);
-			spin_lock_irq(&pool->lock);
-			start_worker(worker);
-			spin_unlock_irq(&pool->lock);
-		}
+		BUG_ON(!(attrs = alloc_workqueue_attrs(GFP_KERNEL)));
+		attrs->nice = std_nice[i];
+		unbound_std_wq_attrs[i] = attrs;
 	}
 
 	system_wq = alloc_workqueue("events", 0, 0);
diff --git a/kernel/workqueue_internal.h b/kernel/workqueue_internal.h
index 0765026..84ab6e1 100644
--- a/kernel/workqueue_internal.h
+++ b/kernel/workqueue_internal.h
@@ -32,14 +32,12 @@ struct worker {
 	struct list_head	scheduled;	/* L: scheduled works */
 	struct task_struct	*task;		/* I: worker task */
 	struct worker_pool	*pool;		/* I: the associated pool */
+						/* L: for rescuers */
 	/* 64 bytes boundary on 64bit, 32 on 32bit */
 	unsigned long		last_active;	/* L: last active timestamp */
 	unsigned int		flags;		/* X: flags */
 	int			id;		/* I: worker id */
 
-	/* for rebinding worker to CPU */
-	struct work_struct	rebind_work;	/* L: for busy worker */
-
 	/* used only by rescuers to point to the target workqueue */
 	struct workqueue_struct	*rescue_wq;	/* I: the workqueue to rescue */
 };
@@ -58,8 +56,7 @@ static inline struct worker *current_wq_worker(void)
  * Scheduler hooks for concurrency managed workqueue.  Only to be used from
  * sched.c and workqueue.c.
  */
-void wq_worker_waking_up(struct task_struct *task, unsigned int cpu);
-struct task_struct *wq_worker_sleeping(struct task_struct *task,
-				       unsigned int cpu);
+void wq_worker_waking_up(struct task_struct *task, int cpu);
+struct task_struct *wq_worker_sleeping(struct task_struct *task, int cpu);
 
 #endif /* _KERNEL_WORKQUEUE_INTERNAL_H */
diff --git a/lib/Kconfig b/lib/Kconfig
index 3958dc4..7bfdbbc 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -189,6 +189,15 @@ config LZO_COMPRESS
 config LZO_DECOMPRESS
 	tristate
 
+config LZ4_COMPRESS
+	tristate
+
+config LZ4HC_COMPRESS
+	tristate
+
+config LZ4_DECOMPRESS
+	tristate
+
 source "lib/xz/Kconfig"
 
 #
@@ -213,6 +222,10 @@ config DECOMPRESS_LZO
 	select LZO_DECOMPRESS
 	tristate
 
+config DECOMPRESS_LZ4
+	select LZ4_DECOMPRESS
+	tristate
+
 #
 # Generic allocator support is selected if needed
 #
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 28be08c..ae80518 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -1292,6 +1292,24 @@ config LATENCYTOP
 	  Enable this option if you want to use the LatencyTOP tool
 	  to find out which userspace is blocking on what kernel operations.
 
+config ARCH_HAS_DEBUG_STRICT_USER_COPY_CHECKS
+	bool
+
+config DEBUG_STRICT_USER_COPY_CHECKS
+	bool "Strict user copy size checks"
+	depends on ARCH_HAS_DEBUG_STRICT_USER_COPY_CHECKS
+	depends on DEBUG_KERNEL && !TRACE_BRANCH_PROFILING
+	help
+	  Enabling this option turns a certain set of sanity checks for user
+	  copy operations into compile time failures.
+
+	  The copy_from_user() etc checks are there to help test if there
+	  are sufficient security checks on the length argument of
+	  the copy operation, by having gcc prove that the argument is
+	  within bounds.
+
+	  If unsure, say N.
+
 source mm/Kconfig.debug
 source kernel/trace/Kconfig
 
diff --git a/lib/Makefile b/lib/Makefile
index d7946ff..10facc6 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -13,8 +13,9 @@ lib-y := ctype.o string.o vsprintf.o cmdline.o \
 	 sha1.o md5.o irq_regs.o reciprocal_div.o argv_split.o \
 	 proportions.o flex_proportions.o prio_heap.o ratelimit.o show_mem.o \
 	 is_single_threaded.o plist.o decompress.o kobject_uevent.o \
-	 earlycpio.o
+	 earlycpio.o percpu-refcount.o
 
+obj-$(CONFIG_ARCH_HAS_DEBUG_STRICT_USER_COPY_CHECKS) += usercopy.o
 lib-$(CONFIG_MMU) += ioremap.o
 lib-$(CONFIG_SMP) += cpumask.o
 
@@ -72,6 +73,9 @@ obj-$(CONFIG_REED_SOLOMON) += reed_solomon/
 obj-$(CONFIG_BCH) += bch.o
 obj-$(CONFIG_LZO_COMPRESS) += lzo/
 obj-$(CONFIG_LZO_DECOMPRESS) += lzo/
+obj-$(CONFIG_LZ4_COMPRESS) += lz4/
+obj-$(CONFIG_LZ4HC_COMPRESS) += lz4/
+obj-$(CONFIG_LZ4_DECOMPRESS) += lz4/
 obj-$(CONFIG_XZ_DEC) += xz/
 obj-$(CONFIG_RAID6_PQ) += raid6/
 
@@ -80,6 +84,7 @@ lib-$(CONFIG_DECOMPRESS_BZIP2) += decompress_bunzip2.o
 lib-$(CONFIG_DECOMPRESS_LZMA) += decompress_unlzma.o
 lib-$(CONFIG_DECOMPRESS_XZ) += decompress_unxz.o
 lib-$(CONFIG_DECOMPRESS_LZO) += decompress_unlzo.o
+lib-$(CONFIG_DECOMPRESS_LZ4) += decompress_unlz4.o
 
 obj-$(CONFIG_TEXTSEARCH) += textsearch.o
 obj-$(CONFIG_TEXTSEARCH_KMP) += ts_kmp.o
diff --git a/lib/argv_split.c b/lib/argv_split.c
index 1e9a6cb..e927ed0 100644
--- a/lib/argv_split.c
+++ b/lib/argv_split.c
@@ -8,23 +8,17 @@
 #include <linux/slab.h>
 #include <linux/export.h>
 
-static const char *skip_arg(const char *cp)
-{
-	while (*cp && !isspace(*cp))
-		cp++;
-
-	return cp;
-}
-
 static int count_argc(const char *str)
 {
 	int count = 0;
+	bool was_space;
 
-	while (*str) {
-		str = skip_spaces(str);
-		if (*str) {
+	for (was_space = true; *str; str++) {
+		if (isspace(*str)) {
+			was_space = true;
+		} else if (was_space) {
+			was_space = false;
 			count++;
-			str = skip_arg(str);
 		}
 	}
 
@@ -39,10 +33,8 @@ static int count_argc(const char *str)
  */
 void argv_free(char **argv)
 {
-	char **p;
-	for (p = argv; *p; p++)
-		kfree(*p);
-
+	argv--;
+	kfree(argv[0]);
 	kfree(argv);
 }
 EXPORT_SYMBOL(argv_free);
@@ -59,43 +51,44 @@ EXPORT_SYMBOL(argv_free);
  * considered to be a single argument separator.  The returned array
  * is always NULL-terminated.  Returns NULL on memory allocation
  * failure.
+ *
+ * The source string at `str' may be undergoing concurrent alteration via
+ * userspace sysctl activity (at least).  The argv_split() implementation
+ * attempts to handle this gracefully by taking a local copy to work on.
  */
 char **argv_split(gfp_t gfp, const char *str, int *argcp)
 {
-	int argc = count_argc(str);
-	char **argv = kzalloc(sizeof(*argv) * (argc+1), gfp);
-	char **argvp;
-
-	if (argv == NULL)
-		goto out;
-
-	if (argcp)
-		*argcp = argc;
-
-	argvp = argv;
-
-	while (*str) {
-		str = skip_spaces(str);
-
-		if (*str) {
-			const char *p = str;
-			char *t;
-
-			str = skip_arg(str);
+	char *argv_str;
+	bool was_space;
+	char **argv, **argv_ret;
+	int argc;
+
+	argv_str = kstrndup(str, KMALLOC_MAX_SIZE - 1, gfp);
+	if (!argv_str)
+		return NULL;
+
+	argc = count_argc(argv_str);
+	argv = kmalloc(sizeof(*argv) * (argc + 2), gfp);
+	if (!argv) {
+		kfree(argv_str);
+		return NULL;
+	}
 
-			t = kstrndup(p, str-p, gfp);
-			if (t == NULL)
-				goto fail;
-			*argvp++ = t;
+	*argv = argv_str;
+	argv_ret = ++argv;
+	for (was_space = true; *argv_str; argv_str++) {
+		if (isspace(*argv_str)) {
+			was_space = true;
+			*argv_str = 0;
+		} else if (was_space) {
+			was_space = false;
+			*argv++ = argv_str;
 		}
 	}
-	*argvp = NULL;
-
-  out:
-	return argv;
+	*argv = NULL;
 
-  fail:
-	argv_free(argv);
-	return NULL;
+	if (argcp)
+		*argcp = argc;
+	return argv_ret;
 }
 EXPORT_SYMBOL(argv_split);
diff --git a/lib/decompress.c b/lib/decompress.c
index 31a8042..c70810e 100644
--- a/lib/decompress.c
+++ b/lib/decompress.c
@@ -11,6 +11,7 @@
 #include <linux/decompress/unxz.h>
 #include <linux/decompress/inflate.h>
 #include <linux/decompress/unlzo.h>
+#include <linux/decompress/unlz4.h>
 
 #include <linux/types.h>
 #include <linux/string.h>
@@ -31,6 +32,9 @@
 #ifndef CONFIG_DECOMPRESS_LZO
 # define unlzo NULL
 #endif
+#ifndef CONFIG_DECOMPRESS_LZ4
+# define unlz4 NULL
+#endif
 
 struct compress_format {
 	unsigned char magic[2];
@@ -45,6 +49,7 @@ static const struct compress_format compressed_formats[] __initdata = {
 	{ {0x5d, 0x00}, "lzma", unlzma },
 	{ {0xfd, 0x37}, "xz", unxz },
 	{ {0x89, 0x4c}, "lzo", unlzo },
+	{ {0x02, 0x21}, "lz4", unlz4 },
 	{ {0, 0}, NULL, NULL }
 };
 
diff --git a/lib/decompress_unlz4.c b/lib/decompress_unlz4.c
new file mode 100644
index 0000000..3e67cfa
--- /dev/null
+++ b/lib/decompress_unlz4.c
@@ -0,0 +1,187 @@
+/*
+ * Wrapper for decompressing LZ4-compressed kernel, initramfs, and initrd
+ *
+ * Copyright (C) 2013, LG Electronics, Kyungsik Lee <kyungsik.lee@lge.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.
+ */
+
+#ifdef STATIC
+#define PREBOOT
+#include "lz4/lz4_decompress.c"
+#else
+#include <linux/decompress/unlz4.h>
+#endif
+#include <linux/types.h>
+#include <linux/lz4.h>
+#include <linux/decompress/mm.h>
+#include <linux/compiler.h>
+
+#include <asm/unaligned.h>
+
+/*
+ * Note: Uncompressed chunk size is used in the compressor side
+ * (userspace side for compression).
+ * It is hardcoded because there is not proper way to extract it
+ * from the binary stream which is generated by the preliminary
+ * version of LZ4 tool so far.
+ */
+#define LZ4_DEFAULT_UNCOMPRESSED_CHUNK_SIZE (8 << 20)
+#define ARCHIVE_MAGICNUMBER 0x184C2102
+
+STATIC inline int INIT unlz4(u8 *input, int in_len,
+				int (*fill) (void *, unsigned int),
+				int (*flush) (void *, unsigned int),
+				u8 *output, int *posp,
+				void (*error) (char *x))
+{
+	int ret = -1;
+	size_t chunksize = 0;
+	size_t uncomp_chunksize = LZ4_DEFAULT_UNCOMPRESSED_CHUNK_SIZE;
+	u8 *inp;
+	u8 *inp_start;
+	u8 *outp;
+	int size = in_len;
+#ifdef PREBOOT
+	size_t out_len = get_unaligned_le32(input + in_len);
+#endif
+	size_t dest_len;
+
+
+	if (output) {
+		outp = output;
+	} else if (!flush) {
+		error("NULL output pointer and no flush function provided");
+		goto exit_0;
+	} else {
+		outp = large_malloc(uncomp_chunksize);
+		if (!outp) {
+			error("Could not allocate output buffer");
+			goto exit_0;
+		}
+	}
+
+	if (input && fill) {
+		error("Both input pointer and fill function provided,");
+		goto exit_1;
+	} else if (input) {
+		inp = input;
+	} else if (!fill) {
+		error("NULL input pointer and missing fill function");
+		goto exit_1;
+	} else {
+		inp = large_malloc(lz4_compressbound(uncomp_chunksize));
+		if (!inp) {
+			error("Could not allocate input buffer");
+			goto exit_1;
+		}
+	}
+	inp_start = inp;
+
+	if (posp)
+		*posp = 0;
+
+	if (fill)
+		fill(inp, 4);
+
+	chunksize = get_unaligned_le32(inp);
+	if (chunksize == ARCHIVE_MAGICNUMBER) {
+		inp += 4;
+		size -= 4;
+	} else {
+		error("invalid header");
+		goto exit_2;
+	}
+
+	if (posp)
+		*posp += 4;
+
+	for (;;) {
+
+		if (fill)
+			fill(inp, 4);
+
+		chunksize = get_unaligned_le32(inp);
+		if (chunksize == ARCHIVE_MAGICNUMBER) {
+			inp += 4;
+			size -= 4;
+			if (posp)
+				*posp += 4;
+			continue;
+		}
+		inp += 4;
+		size -= 4;
+
+		if (posp)
+			*posp += 4;
+
+		if (fill) {
+			if (chunksize > lz4_compressbound(uncomp_chunksize)) {
+				error("chunk length is longer than allocated");
+				goto exit_2;
+			}
+			fill(inp, chunksize);
+		}
+#ifdef PREBOOT
+		if (out_len >= uncomp_chunksize) {
+			dest_len = uncomp_chunksize;
+			out_len -= dest_len;
+		} else
+			dest_len = out_len;
+		ret = lz4_decompress(inp, &chunksize, outp, dest_len);
+#else
+		dest_len = uncomp_chunksize;
+		ret = lz4_decompress_unknownoutputsize(inp, chunksize, outp,
+				&dest_len);
+#endif
+		if (ret < 0) {
+			error("Decoding failed");
+			goto exit_2;
+		}
+
+		if (flush && flush(outp, dest_len) != dest_len)
+			goto exit_2;
+		if (output)
+			outp += dest_len;
+		if (posp)
+			*posp += chunksize;
+
+		size -= chunksize;
+
+		if (size == 0)
+			break;
+		else if (size < 0) {
+			error("data corrupted");
+			goto exit_2;
+		}
+
+		inp += chunksize;
+		if (fill)
+			inp = inp_start;
+	}
+
+	ret = 0;
+exit_2:
+	if (!input)
+		large_free(inp_start);
+exit_1:
+	if (!output)
+		large_free(outp);
+exit_0:
+	return ret;
+}
+
+#ifdef PREBOOT
+STATIC int INIT decompress(unsigned char *buf, int in_len,
+			      int(*fill)(void*, unsigned int),
+			      int(*flush)(void*, unsigned int),
+			      unsigned char *output,
+			      int *posp,
+			      void(*error)(char *x)
+	)
+{
+	return unlz4(buf, in_len - 4, fill, flush, output, posp, error);
+}
+#endif
diff --git a/lib/fault-inject.c b/lib/fault-inject.c
index f7210ad..c5c7a76 100644
--- a/lib/fault-inject.c
+++ b/lib/fault-inject.c
@@ -122,7 +122,7 @@ bool should_fail(struct fault_attr *attr, ssize_t size)
 			return false;
 	}
 
-	if (attr->probability <= random32() % 100)
+	if (attr->probability <= prandom_u32() % 100)
 		return false;
 
 	if (!fail_stacktrace(attr))
diff --git a/lib/int_sqrt.c b/lib/int_sqrt.c
index fc2eeb7..1ef4cc3 100644
--- a/lib/int_sqrt.c
+++ b/lib/int_sqrt.c
@@ -1,3 +1,9 @@
+/*
+ * Copyright (C) 2013 Davidlohr Bueso <davidlohr.bueso@hp.com>
+ *
+ *  Based on the shift-and-subtract algorithm for computing integer
+ *  square root from Guy L. Steele.
+ */
 
 #include <linux/kernel.h>
 #include <linux/export.h>
@@ -10,23 +16,23 @@
  */
 unsigned long int_sqrt(unsigned long x)
 {
-	unsigned long op, res, one;
+	unsigned long b, m, y = 0;
 
-	op = x;
-	res = 0;
+	if (x <= 1)
+		return x;
 
-	one = 1UL << (BITS_PER_LONG - 2);
-	while (one > op)
-		one >>= 2;
+	m = 1UL << (BITS_PER_LONG - 2);
+	while (m != 0) {
+		b = y + m;
+		y >>= 1;
 
-	while (one != 0) {
-		if (op >= res + one) {
-			op = op - (res + one);
-			res = res +  2 * one;
+		if (x >= b) {
+			x -= b;
+			y += m;
 		}
-		res /= 2;
-		one /= 4;
+		m >>= 2;
 	}
-	return res;
+
+	return y;
 }
 EXPORT_SYMBOL(int_sqrt);
diff --git a/lib/list_sort.c b/lib/list_sort.c
index d7325c6..1183fa7 100644
--- a/lib/list_sort.c
+++ b/lib/list_sort.c
@@ -229,7 +229,7 @@ static int __init list_sort_test(void)
 			goto exit;
 		}
 		 /* force some equivalencies */
-		el->value = random32() % (TEST_LIST_LEN/3);
+		el->value = prandom_u32() % (TEST_LIST_LEN / 3);
 		el->serial = i;
 		el->poison1 = TEST_POISON1;
 		el->poison2 = TEST_POISON2;
diff --git a/lib/lru_cache.c b/lib/lru_cache.c
index 8335d39..4a83ecd 100644
--- a/lib/lru_cache.c
+++ b/lib/lru_cache.c
@@ -365,7 +365,13 @@ static int lc_unused_element_available(struct lru_cache *lc)
 	return 0;
 }
 
-static struct lc_element *__lc_get(struct lru_cache *lc, unsigned int enr, bool may_change)
+/* used as internal flags to __lc_get */
+enum {
+	LC_GET_MAY_CHANGE = 1,
+	LC_GET_MAY_USE_UNCOMMITTED = 2,
+};
+
+static struct lc_element *__lc_get(struct lru_cache *lc, unsigned int enr, unsigned int flags)
 {
 	struct lc_element *e;
 
@@ -380,22 +386,31 @@ static struct lc_element *__lc_get(struct lru_cache *lc, unsigned int enr, bool
 	 * this enr is currently being pulled in already,
 	 * and will be available once the pending transaction
 	 * has been committed. */
-	if (e && e->lc_new_number == e->lc_number) {
+	if (e) {
+		if (e->lc_new_number != e->lc_number) {
+			/* It has been found above, but on the "to_be_changed"
+			 * list, not yet committed.  Don't pull it in twice,
+			 * wait for the transaction, then try again...
+			 */
+			if (!(flags & LC_GET_MAY_USE_UNCOMMITTED))
+				RETURN(NULL);
+			/* ... unless the caller is aware of the implications,
+			 * probably preparing a cumulative transaction. */
+			++e->refcnt;
+			++lc->hits;
+			RETURN(e);
+		}
+		/* else: lc_new_number == lc_number; a real hit. */
 		++lc->hits;
 		if (e->refcnt++ == 0)
 			lc->used++;
 		list_move(&e->list, &lc->in_use); /* Not evictable... */
 		RETURN(e);
 	}
+	/* e == NULL */
 
 	++lc->misses;
-	if (!may_change)
-		RETURN(NULL);
-
-	/* It has been found above, but on the "to_be_changed" list, not yet
-	 * committed.  Don't pull it in twice, wait for the transaction, then
-	 * try again */
-	if (e)
+	if (!(flags & LC_GET_MAY_CHANGE))
 		RETURN(NULL);
 
 	/* To avoid races with lc_try_lock(), first, mark us dirty
@@ -477,7 +492,27 @@ static struct lc_element *__lc_get(struct lru_cache *lc, unsigned int enr, bool
  */
 struct lc_element *lc_get(struct lru_cache *lc, unsigned int enr)
 {
-	return __lc_get(lc, enr, 1);
+	return __lc_get(lc, enr, LC_GET_MAY_CHANGE);
+}
+
+/**
+ * lc_get_cumulative - like lc_get; also finds to-be-changed elements
+ * @lc: the lru cache to operate on
+ * @enr: the label to look up
+ *
+ * Unlike lc_get this also returns the element for @enr, if it is belonging to
+ * a pending transaction, so the return values are like for lc_get(),
+ * plus:
+ *
+ * pointer to an element already on the "to_be_changed" list.
+ * 	In this case, the cache was already marked %LC_DIRTY.
+ *
+ * Caller needs to make sure that the pending transaction is completed,
+ * before proceeding to actually use this element.
+ */
+struct lc_element *lc_get_cumulative(struct lru_cache *lc, unsigned int enr)
+{
+	return __lc_get(lc, enr, LC_GET_MAY_CHANGE|LC_GET_MAY_USE_UNCOMMITTED);
 }
 
 /**
@@ -648,3 +683,4 @@ EXPORT_SYMBOL(lc_seq_printf_stats);
 EXPORT_SYMBOL(lc_seq_dump_details);
 EXPORT_SYMBOL(lc_try_lock);
 EXPORT_SYMBOL(lc_is_used);
+EXPORT_SYMBOL(lc_get_cumulative);
diff --git a/lib/lz4/Makefile b/lib/lz4/Makefile
new file mode 100644
index 0000000..8085d04
--- /dev/null
+++ b/lib/lz4/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_LZ4_COMPRESS) += lz4_compress.o
+obj-$(CONFIG_LZ4HC_COMPRESS) += lz4hc_compress.o
+obj-$(CONFIG_LZ4_DECOMPRESS) += lz4_decompress.o
diff --git a/lib/lz4/lz4_compress.c b/lib/lz4/lz4_compress.c
new file mode 100644
index 0000000..fd94058
--- /dev/null
+++ b/lib/lz4/lz4_compress.c
@@ -0,0 +1,443 @@
+/*
+ * LZ4 - Fast LZ compression algorithm
+ * Copyright (C) 2011-2012, Yann Collet.
+ * BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
+
+ * 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.
+ *
+ * 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.
+ *
+ * You can contact the author at :
+ * - LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html
+ * - LZ4 source repository : http://code.google.com/p/lz4/
+ *
+ *  Changed for kernel use by:
+ *  Chanho Min <chanho.min@lge.com>
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/lz4.h>
+#include <asm/unaligned.h>
+#include "lz4defs.h"
+
+/*
+ * LZ4_compressCtx :
+ * -----------------
+ * Compress 'isize' bytes from 'source' into an output buffer 'dest' of
+ * maximum size 'maxOutputSize'.  * If it cannot achieve it, compression
+ * will stop, and result of the function will be zero.
+ * return : the number of bytes written in buffer 'dest', or 0 if the
+ * compression fails
+ */
+static inline int lz4_compressctx(void *ctx,
+		const char *source,
+		char *dest,
+		int isize,
+		int maxoutputsize)
+{
+	HTYPE *hashtable = (HTYPE *)ctx;
+	const u8 *ip = (u8 *)source;
+#if LZ4_ARCH64
+	const BYTE * const base = ip;
+#else
+	const int base = 0;
+#endif
+	const u8 *anchor = ip;
+	const u8 *const iend = ip + isize;
+	const u8 *const mflimit = iend - MFLIMIT;
+	#define MATCHLIMIT (iend - LASTLITERALS)
+
+	u8 *op = (u8 *) dest;
+	u8 *const oend = op + maxoutputsize;
+	int length;
+	const int skipstrength = SKIPSTRENGTH;
+	u32 forwardh;
+	int lastrun;
+
+	/* Init */
+	if (isize < MINLENGTH)
+		goto _last_literals;
+
+	memset((void *)hashtable, 0, LZ4_MEM_COMPRESS);
+
+	/* First Byte */
+	hashtable[LZ4_HASH_VALUE(ip)] = ip - base;
+	ip++;
+	forwardh = LZ4_HASH_VALUE(ip);
+
+	/* Main Loop */
+	for (;;) {
+		int findmatchattempts = (1U << skipstrength) + 3;
+		const u8 *forwardip = ip;
+		const u8 *ref;
+		u8 *token;
+
+		/* Find a match */
+		do {
+			u32 h = forwardh;
+			int step = findmatchattempts++ >> skipstrength;
+			ip = forwardip;
+			forwardip = ip + step;
+
+			if (unlikely(forwardip > mflimit))
+				goto _last_literals;
+
+			forwardh = LZ4_HASH_VALUE(forwardip);
+			ref = base + hashtable[h];
+			hashtable[h] = ip - base;
+		} while ((ref < ip - MAX_DISTANCE) || (A32(ref) != A32(ip)));
+
+		/* Catch up */
+		while ((ip > anchor) && (ref > (u8 *)source) &&
+			unlikely(ip[-1] == ref[-1])) {
+			ip--;
+			ref--;
+		}
+
+		/* Encode Literal length */
+		length = (int)(ip - anchor);
+		token = op++;
+		/* check output limit */
+		if (unlikely(op + length + (2 + 1 + LASTLITERALS) +
+			(length >> 8) > oend))
+			return 0;
+
+		if (length >= (int)RUN_MASK) {
+			int len;
+			*token = (RUN_MASK << ML_BITS);
+			len = length - RUN_MASK;
+			for (; len > 254 ; len -= 255)
+				*op++ = 255;
+			*op++ = (u8)len;
+		} else
+			*token = (length << ML_BITS);
+
+		/* Copy Literals */
+		LZ4_BLINDCOPY(anchor, op, length);
+_next_match:
+		/* Encode Offset */
+		LZ4_WRITE_LITTLEENDIAN_16(op, (u16)(ip - ref));
+
+		/* Start Counting */
+		ip += MINMATCH;
+		/* MinMatch verified */
+		ref += MINMATCH;
+		anchor = ip;
+		while (likely(ip < MATCHLIMIT - (STEPSIZE - 1))) {
+			#if LZ4_ARCH64
+			u64 diff = A64(ref) ^ A64(ip);
+			#else
+			u32 diff = A32(ref) ^ A32(ip);
+			#endif
+			if (!diff) {
+				ip += STEPSIZE;
+				ref += STEPSIZE;
+				continue;
+			}
+			ip += LZ4_NBCOMMONBYTES(diff);
+			goto _endcount;
+		}
+		#if LZ4_ARCH64
+		if ((ip < (MATCHLIMIT - 3)) && (A32(ref) == A32(ip))) {
+			ip += 4;
+			ref += 4;
+		}
+		#endif
+		if ((ip < (MATCHLIMIT - 1)) && (A16(ref) == A16(ip))) {
+			ip += 2;
+			ref += 2;
+		}
+		if ((ip < MATCHLIMIT) && (*ref == *ip))
+			ip++;
+_endcount:
+		/* Encode MatchLength */
+		length = (int)(ip - anchor);
+		/* Check output limit */
+		if (unlikely(op + (1 + LASTLITERALS) + (length >> 8) > oend))
+			return 0;
+		if (length >= (int)ML_MASK) {
+			*token += ML_MASK;
+			length -= ML_MASK;
+			for (; length > 509 ; length -= 510) {
+				*op++ = 255;
+				*op++ = 255;
+			}
+			if (length > 254) {
+				length -= 255;
+				*op++ = 255;
+			}
+			*op++ = (u8)length;
+		} else
+			*token += length;
+
+		/* Test end of chunk */
+		if (ip > mflimit) {
+			anchor = ip;
+			break;
+		}
+
+		/* Fill table */
+		hashtable[LZ4_HASH_VALUE(ip-2)] = ip - 2 - base;
+
+		/* Test next position */
+		ref = base + hashtable[LZ4_HASH_VALUE(ip)];
+		hashtable[LZ4_HASH_VALUE(ip)] = ip - base;
+		if ((ref > ip - (MAX_DISTANCE + 1)) && (A32(ref) == A32(ip))) {
+			token = op++;
+			*token = 0;
+			goto _next_match;
+		}
+
+		/* Prepare next loop */
+		anchor = ip++;
+		forwardh = LZ4_HASH_VALUE(ip);
+	}
+
+_last_literals:
+	/* Encode Last Literals */
+	lastrun = (int)(iend - anchor);
+	if (((char *)op - dest) + lastrun + 1
+		+ ((lastrun + 255 - RUN_MASK) / 255) > (u32)maxoutputsize)
+		return 0;
+
+	if (lastrun >= (int)RUN_MASK) {
+		*op++ = (RUN_MASK << ML_BITS);
+		lastrun -= RUN_MASK;
+		for (; lastrun > 254 ; lastrun -= 255)
+			*op++ = 255;
+		*op++ = (u8)lastrun;
+	} else
+		*op++ = (lastrun << ML_BITS);
+	memcpy(op, anchor, iend - anchor);
+	op += iend - anchor;
+
+	/* End */
+	return (int)(((char *)op) - dest);
+}
+
+static inline int lz4_compress64kctx(void *ctx,
+		const char *source,
+		char *dest,
+		int isize,
+		int maxoutputsize)
+{
+	u16 *hashtable = (u16 *)ctx;
+	const u8 *ip = (u8 *) source;
+	const u8 *anchor = ip;
+	const u8 *const base = ip;
+	const u8 *const iend = ip + isize;
+	const u8 *const mflimit = iend - MFLIMIT;
+	#define MATCHLIMIT (iend - LASTLITERALS)
+
+	u8 *op = (u8 *) dest;
+	u8 *const oend = op + maxoutputsize;
+	int len, length;
+	const int skipstrength = SKIPSTRENGTH;
+	u32 forwardh;
+	int lastrun;
+
+	/* Init */
+	if (isize < MINLENGTH)
+		goto _last_literals;
+
+	memset((void *)hashtable, 0, LZ4_MEM_COMPRESS);
+
+	/* First Byte */
+	ip++;
+	forwardh = LZ4_HASH64K_VALUE(ip);
+
+	/* Main Loop */
+	for (;;) {
+		int findmatchattempts = (1U << skipstrength) + 3;
+		const u8 *forwardip = ip;
+		const u8 *ref;
+		u8 *token;
+
+		/* Find a match */
+		do {
+			u32 h = forwardh;
+			int step = findmatchattempts++ >> skipstrength;
+			ip = forwardip;
+			forwardip = ip + step;
+
+			if (forwardip > mflimit)
+				goto _last_literals;
+
+			forwardh = LZ4_HASH64K_VALUE(forwardip);
+			ref = base + hashtable[h];
+			hashtable[h] = (u16)(ip - base);
+		} while (A32(ref) != A32(ip));
+
+		/* Catch up */
+		while ((ip > anchor) && (ref > (u8 *)source)
+			&& (ip[-1] == ref[-1])) {
+			ip--;
+			ref--;
+		}
+
+		/* Encode Literal length */
+		length = (int)(ip - anchor);
+		token = op++;
+		/* Check output limit */
+		if (unlikely(op + length + (2 + 1 + LASTLITERALS)
+			+ (length >> 8) > oend))
+			return 0;
+		if (length >= (int)RUN_MASK) {
+			*token = (RUN_MASK << ML_BITS);
+			len = length - RUN_MASK;
+			for (; len > 254 ; len -= 255)
+				*op++ = 255;
+			*op++ = (u8)len;
+		} else
+			*token = (length << ML_BITS);
+
+		/* Copy Literals */
+		LZ4_BLINDCOPY(anchor, op, length);
+
+_next_match:
+		/* Encode Offset */
+		LZ4_WRITE_LITTLEENDIAN_16(op, (u16)(ip - ref));
+
+		/* Start Counting */
+		ip += MINMATCH;
+		/* MinMatch verified */
+		ref += MINMATCH;
+		anchor = ip;
+
+		while (ip < MATCHLIMIT - (STEPSIZE - 1)) {
+			#if LZ4_ARCH64
+			u64 diff = A64(ref) ^ A64(ip);
+			#else
+			u32 diff = A32(ref) ^ A32(ip);
+			#endif
+
+			if (!diff) {
+				ip += STEPSIZE;
+				ref += STEPSIZE;
+				continue;
+			}
+			ip += LZ4_NBCOMMONBYTES(diff);
+			goto _endcount;
+		}
+		#if LZ4_ARCH64
+		if ((ip < (MATCHLIMIT - 3)) && (A32(ref) == A32(ip))) {
+			ip += 4;
+			ref += 4;
+		}
+		#endif
+		if ((ip < (MATCHLIMIT - 1)) && (A16(ref) == A16(ip))) {
+			ip += 2;
+			ref += 2;
+		}
+		if ((ip < MATCHLIMIT) && (*ref == *ip))
+			ip++;
+_endcount:
+
+		/* Encode MatchLength */
+		len = (int)(ip - anchor);
+		/* Check output limit */
+		if (unlikely(op + (1 + LASTLITERALS) + (len >> 8) > oend))
+			return 0;
+		if (len >= (int)ML_MASK) {
+			*token += ML_MASK;
+			len -= ML_MASK;
+			for (; len > 509 ; len -= 510) {
+				*op++ = 255;
+				*op++ = 255;
+			}
+			if (len > 254) {
+				len -= 255;
+				*op++ = 255;
+			}
+			*op++ = (u8)len;
+		} else
+			*token += len;
+
+		/* Test end of chunk */
+		if (ip > mflimit) {
+			anchor = ip;
+			break;
+		}
+
+		/* Fill table */
+		hashtable[LZ4_HASH64K_VALUE(ip-2)] = (u16)(ip - 2 - base);
+
+		/* Test next position */
+		ref = base + hashtable[LZ4_HASH64K_VALUE(ip)];
+		hashtable[LZ4_HASH64K_VALUE(ip)] = (u16)(ip - base);
+		if (A32(ref) == A32(ip)) {
+			token = op++;
+			*token = 0;
+			goto _next_match;
+		}
+
+		/* Prepare next loop */
+		anchor = ip++;
+		forwardh = LZ4_HASH64K_VALUE(ip);
+	}
+
+_last_literals:
+	/* Encode Last Literals */
+	lastrun = (int)(iend - anchor);
+	if (op + lastrun + 1 + (lastrun - RUN_MASK + 255) / 255 > oend)
+		return 0;
+	if (lastrun >= (int)RUN_MASK) {
+		*op++ = (RUN_MASK << ML_BITS);
+		lastrun -= RUN_MASK;
+		for (; lastrun > 254 ; lastrun -= 255)
+			*op++ = 255;
+		*op++ = (u8)lastrun;
+	} else
+		*op++ = (lastrun << ML_BITS);
+	memcpy(op, anchor, iend - anchor);
+	op += iend - anchor;
+	/* End */
+	return (int)(((char *)op) - dest);
+}
+
+int lz4_compress(const unsigned char *src, size_t src_len,
+			unsigned char *dst, size_t *dst_len, void *wrkmem)
+{
+	int ret = -1;
+	int out_len = 0;
+
+	if (src_len < LZ4_64KLIMIT)
+		out_len = lz4_compress64kctx(wrkmem, src, dst, src_len,
+				lz4_compressbound(src_len));
+	else
+		out_len = lz4_compressctx(wrkmem, src, dst, src_len,
+				lz4_compressbound(src_len));
+
+	if (out_len < 0)
+		goto exit;
+
+	*dst_len = out_len;
+
+	return 0;
+exit:
+	return ret;
+}
+EXPORT_SYMBOL_GPL(lz4_compress);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("LZ4 compressor");
diff --git a/lib/lz4/lz4_decompress.c b/lib/lz4/lz4_decompress.c
new file mode 100644
index 0000000..d3414ea
--- /dev/null
+++ b/lib/lz4/lz4_decompress.c
@@ -0,0 +1,326 @@
+/*
+ * LZ4 Decompressor for Linux kernel
+ *
+ * Copyright (C) 2013, LG Electronics, Kyungsik Lee <kyungsik.lee@lge.com>
+ *
+ * Based on LZ4 implementation by Yann Collet.
+ *
+ * LZ4 - Fast LZ compression algorithm
+ * Copyright (C) 2011-2012, Yann Collet.
+ * BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * 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.
+ *
+ * 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.
+ *
+ *  You can contact the author at :
+ *  - LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html
+ *  - LZ4 source repository : http://code.google.com/p/lz4/
+ */
+
+#ifndef STATIC
+#include <linux/module.h>
+#include <linux/kernel.h>
+#endif
+#include <linux/lz4.h>
+
+#include <asm/unaligned.h>
+
+#include "lz4defs.h"
+
+static int lz4_uncompress(const char *source, char *dest, int osize)
+{
+	const BYTE *ip = (const BYTE *) source;
+	const BYTE *ref;
+	BYTE *op = (BYTE *) dest;
+	BYTE * const oend = op + osize;
+	BYTE *cpy;
+	unsigned token;
+	size_t length;
+	size_t dec32table[] = {0, 3, 2, 3, 0, 0, 0, 0};
+#if LZ4_ARCH64
+	size_t dec64table[] = {0, 0, 0, -1, 0, 1, 2, 3};
+#endif
+
+	while (1) {
+
+		/* get runlength */
+		token = *ip++;
+		length = (token >> ML_BITS);
+		if (length == RUN_MASK) {
+			size_t len;
+
+			len = *ip++;
+			for (; len == 255; length += 255)
+				len = *ip++;
+			length += len;
+		}
+
+		/* copy literals */
+		cpy = op + length;
+		if (unlikely(cpy > oend - COPYLENGTH)) {
+			/*
+			 * Error: not enough place for another match
+			 * (min 4) + 5 literals
+			 */
+			if (cpy != oend)
+				goto _output_error;
+
+			memcpy(op, ip, length);
+			ip += length;
+			break; /* EOF */
+		}
+		LZ4_WILDCOPY(ip, op, cpy);
+		ip -= (op - cpy);
+		op = cpy;
+
+		/* get offset */
+		LZ4_READ_LITTLEENDIAN_16(ref, cpy, ip);
+		ip += 2;
+
+		/* Error: offset create reference outside destination buffer */
+		if (unlikely(ref < (BYTE *const) dest))
+			goto _output_error;
+
+		/* get matchlength */
+		length = token & ML_MASK;
+		if (length == ML_MASK) {
+			for (; *ip == 255; length += 255)
+				ip++;
+			length += *ip++;
+		}
+
+		/* copy repeated sequence */
+		if (unlikely((op - ref) < STEPSIZE)) {
+#if LZ4_ARCH64
+			size_t dec64 = dec64table[op - ref];
+#else
+			const int dec64 = 0;
+#endif
+			op[0] = ref[0];
+			op[1] = ref[1];
+			op[2] = ref[2];
+			op[3] = ref[3];
+			op += 4;
+			ref += 4;
+			ref -= dec32table[op-ref];
+			PUT4(ref, op);
+			op += STEPSIZE - 4;
+			ref -= dec64;
+		} else {
+			LZ4_COPYSTEP(ref, op);
+		}
+		cpy = op + length - (STEPSIZE - 4);
+		if (cpy > (oend - COPYLENGTH)) {
+
+			/* Error: request to write beyond destination buffer */
+			if (cpy > oend)
+				goto _output_error;
+			LZ4_SECURECOPY(ref, op, (oend - COPYLENGTH));
+			while (op < cpy)
+				*op++ = *ref++;
+			op = cpy;
+			/*
+			 * Check EOF (should never happen, since last 5 bytes
+			 * are supposed to be literals)
+			 */
+			if (op == oend)
+				goto _output_error;
+			continue;
+		}
+		LZ4_SECURECOPY(ref, op, cpy);
+		op = cpy; /* correction */
+	}
+	/* end of decoding */
+	return (int) (((char *)ip) - source);
+
+	/* write overflow error detected */
+_output_error:
+	return (int) (-(((char *)ip) - source));
+}
+
+static int lz4_uncompress_unknownoutputsize(const char *source, char *dest,
+				int isize, size_t maxoutputsize)
+{
+	const BYTE *ip = (const BYTE *) source;
+	const BYTE *const iend = ip + isize;
+	const BYTE *ref;
+
+
+	BYTE *op = (BYTE *) dest;
+	BYTE * const oend = op + maxoutputsize;
+	BYTE *cpy;
+
+	size_t dec32table[] = {0, 3, 2, 3, 0, 0, 0, 0};
+#if LZ4_ARCH64
+	size_t dec64table[] = {0, 0, 0, -1, 0, 1, 2, 3};
+#endif
+
+	/* Main Loop */
+	while (ip < iend) {
+
+		unsigned token;
+		size_t length;
+
+		/* get runlength */
+		token = *ip++;
+		length = (token >> ML_BITS);
+		if (length == RUN_MASK) {
+			int s = 255;
+			while ((ip < iend) && (s == 255)) {
+				s = *ip++;
+				length += s;
+			}
+		}
+		/* copy literals */
+		cpy = op + length;
+		if ((cpy > oend - COPYLENGTH) ||
+			(ip + length > iend - COPYLENGTH)) {
+
+			if (cpy > oend)
+				goto _output_error;/* writes beyond buffer */
+
+			if (ip + length != iend)
+				goto _output_error;/*
+						    * Error: LZ4 format requires
+						    * to consume all input
+						    * at this stage
+						    */
+			memcpy(op, ip, length);
+			op += length;
+			break;/* Necessarily EOF, due to parsing restrictions */
+		}
+		LZ4_WILDCOPY(ip, op, cpy);
+		ip -= (op - cpy);
+		op = cpy;
+
+		/* get offset */
+		LZ4_READ_LITTLEENDIAN_16(ref, cpy, ip);
+		ip += 2;
+		if (ref < (BYTE * const) dest)
+			goto _output_error;
+			/*
+			 * Error : offset creates reference
+			 * outside of destination buffer
+			 */
+
+		/* get matchlength */
+		length = (token & ML_MASK);
+		if (length == ML_MASK) {
+			while (ip < iend) {
+				int s = *ip++;
+				length += s;
+				if (s == 255)
+					continue;
+				break;
+			}
+		}
+
+		/* copy repeated sequence */
+		if (unlikely((op - ref) < STEPSIZE)) {
+#if LZ4_ARCH64
+			size_t dec64 = dec64table[op - ref];
+#else
+			const int dec64 = 0;
+#endif
+				op[0] = ref[0];
+				op[1] = ref[1];
+				op[2] = ref[2];
+				op[3] = ref[3];
+				op += 4;
+				ref += 4;
+				ref -= dec32table[op - ref];
+				PUT4(ref, op);
+				op += STEPSIZE - 4;
+				ref -= dec64;
+		} else {
+			LZ4_COPYSTEP(ref, op);
+		}
+		cpy = op + length - (STEPSIZE-4);
+		if (cpy > oend - COPYLENGTH) {
+			if (cpy > oend)
+				goto _output_error; /* write outside of buf */
+
+			LZ4_SECURECOPY(ref, op, (oend - COPYLENGTH));
+			while (op < cpy)
+				*op++ = *ref++;
+			op = cpy;
+			/*
+			 * Check EOF (should never happen, since last 5 bytes
+			 * are supposed to be literals)
+			 */
+			if (op == oend)
+				goto _output_error;
+			continue;
+		}
+		LZ4_SECURECOPY(ref, op, cpy);
+		op = cpy; /* correction */
+	}
+	/* end of decoding */
+	return (int) (((char *) op) - dest);
+
+	/* write overflow error detected */
+_output_error:
+	return (int) (-(((char *) ip) - source));
+}
+
+int lz4_decompress(const char *src, size_t *src_len, char *dest,
+		size_t actual_dest_len)
+{
+	int ret = -1;
+	int input_len = 0;
+
+	input_len = lz4_uncompress(src, dest, actual_dest_len);
+	if (input_len < 0)
+		goto exit_0;
+	*src_len = input_len;
+
+	return 0;
+exit_0:
+	return ret;
+}
+#ifndef STATIC
+EXPORT_SYMBOL_GPL(lz4_decompress);
+#endif
+
+int lz4_decompress_unknownoutputsize(const char *src, size_t src_len,
+		char *dest, size_t *dest_len)
+{
+	int ret = -1;
+	int out_len = 0;
+
+	out_len = lz4_uncompress_unknownoutputsize(src, dest, src_len,
+					*dest_len);
+	if (out_len < 0)
+		goto exit_0;
+	*dest_len = out_len;
+
+	return 0;
+exit_0:
+	return ret;
+}
+#ifndef STATIC
+EXPORT_SYMBOL_GPL(lz4_decompress_unknownoutputsize);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("LZ4 Decompressor");
+#endif
diff --git a/lib/lz4/lz4defs.h b/lib/lz4/lz4defs.h
new file mode 100644
index 0000000..abcecdc
--- /dev/null
+++ b/lib/lz4/lz4defs.h
@@ -0,0 +1,156 @@
+/*
+ * lz4defs.h -- architecture specific defines
+ *
+ * Copyright (C) 2013, LG Electronics, Kyungsik Lee <kyungsik.lee@lge.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.
+ */
+
+/*
+ * Detects 64 bits mode
+ */
+#if (defined(__x86_64__) || defined(__x86_64) || defined(__amd64__) \
+	|| defined(__ppc64__) || defined(__LP64__))
+#define LZ4_ARCH64 1
+#else
+#define LZ4_ARCH64 0
+#endif
+
+/*
+ * Architecture-specific macros
+ */
+#define BYTE	u8
+typedef struct _U16_S { u16 v; } U16_S;
+typedef struct _U32_S { u32 v; } U32_S;
+typedef struct _U64_S { u64 v; } U64_S;
+#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)		\
+	|| defined(CONFIG_ARM) && __LINUX_ARM_ARCH__ >= 6	\
+	&& defined(ARM_EFFICIENT_UNALIGNED_ACCESS)
+
+#define A16(x) (((U16_S *)(x))->v)
+#define A32(x) (((U32_S *)(x))->v)
+#define A64(x) (((U64_S *)(x))->v)
+
+#define PUT4(s, d) (A32(d) = A32(s))
+#define PUT8(s, d) (A64(d) = A64(s))
+#define LZ4_WRITE_LITTLEENDIAN_16(p, v)	\
+	do {	\
+		A16(p) = v; \
+		p += 2; \
+	} while (0)
+#else /* CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS */
+
+#define A64(x) get_unaligned((u64 *)&(((U16_S *)(x))->v))
+#define A32(x) get_unaligned((u32 *)&(((U16_S *)(x))->v))
+#define A16(x) get_unaligned((u16 *)&(((U16_S *)(x))->v))
+
+#define PUT4(s, d) \
+	put_unaligned(get_unaligned((const u32 *) s), (u32 *) d)
+#define PUT8(s, d) \
+	put_unaligned(get_unaligned((const u64 *) s), (u64 *) d)
+
+#define LZ4_WRITE_LITTLEENDIAN_16(p, v)	\
+	do {	\
+		put_unaligned(v, (u16 *)(p)); \
+		p += 2; \
+	} while (0)
+#endif
+
+#define COPYLENGTH 8
+#define ML_BITS  4
+#define ML_MASK  ((1U << ML_BITS) - 1)
+#define RUN_BITS (8 - ML_BITS)
+#define RUN_MASK ((1U << RUN_BITS) - 1)
+#define MEMORY_USAGE	14
+#define MINMATCH	4
+#define SKIPSTRENGTH	6
+#define LASTLITERALS	5
+#define MFLIMIT		(COPYLENGTH + MINMATCH)
+#define MINLENGTH	(MFLIMIT + 1)
+#define MAXD_LOG	16
+#define MAXD		(1 << MAXD_LOG)
+#define MAXD_MASK	(u32)(MAXD - 1)
+#define MAX_DISTANCE	(MAXD - 1)
+#define HASH_LOG	(MAXD_LOG - 1)
+#define HASHTABLESIZE	(1 << HASH_LOG)
+#define MAX_NB_ATTEMPTS	256
+#define OPTIMAL_ML	(int)((ML_MASK-1)+MINMATCH)
+#define LZ4_64KLIMIT	((1<<16) + (MFLIMIT - 1))
+#define HASHLOG64K	((MEMORY_USAGE - 2) + 1)
+#define HASH64KTABLESIZE	(1U << HASHLOG64K)
+#define LZ4_HASH_VALUE(p)	(((A32(p)) * 2654435761U) >> \
+				((MINMATCH * 8) - (MEMORY_USAGE-2)))
+#define LZ4_HASH64K_VALUE(p)	(((A32(p)) * 2654435761U) >> \
+				((MINMATCH * 8) - HASHLOG64K))
+#define HASH_VALUE(p)		(((A32(p)) * 2654435761U) >> \
+				((MINMATCH * 8) - HASH_LOG))
+
+#if LZ4_ARCH64/* 64-bit */
+#define STEPSIZE 8
+
+#define LZ4_COPYSTEP(s, d)	\
+	do {			\
+		PUT8(s, d);	\
+		d += 8;		\
+		s += 8;		\
+	} while (0)
+
+#define LZ4_COPYPACKET(s, d)	LZ4_COPYSTEP(s, d)
+
+#define LZ4_SECURECOPY(s, d, e)			\
+	do {					\
+		if (d < e) {			\
+			LZ4_WILDCOPY(s, d, e);	\
+		}				\
+	} while (0)
+#define HTYPE u32
+
+#ifdef __BIG_ENDIAN
+#define LZ4_NBCOMMONBYTES(val) (__builtin_clzll(val) >> 3)
+#else
+#define LZ4_NBCOMMONBYTES(val) (__builtin_ctzll(val) >> 3)
+#endif
+
+#else	/* 32-bit */
+#define STEPSIZE 4
+
+#define LZ4_COPYSTEP(s, d)	\
+	do {			\
+		PUT4(s, d);	\
+		d += 4;		\
+		s += 4;		\
+	} while (0)
+
+#define LZ4_COPYPACKET(s, d)		\
+	do {				\
+		LZ4_COPYSTEP(s, d);	\
+		LZ4_COPYSTEP(s, d);	\
+	} while (0)
+
+#define LZ4_SECURECOPY	LZ4_WILDCOPY
+#define HTYPE const u8*
+
+#ifdef __BIG_ENDIAN
+#define LZ4_NBCOMMONBYTES(val) (__builtin_clz(val) >> 3)
+#else
+#define LZ4_NBCOMMONBYTES(val) (__builtin_ctz(val) >> 3)
+#endif
+
+#endif
+
+#define LZ4_READ_LITTLEENDIAN_16(d, s, p) \
+	(d = s - get_unaligned_le16(p))
+
+#define LZ4_WILDCOPY(s, d, e)		\
+	do {				\
+		LZ4_COPYPACKET(s, d);	\
+	} while (d < e)
+
+#define LZ4_BLINDCOPY(s, d, l)	\
+	do {	\
+		u8 *e = (d) + l;	\
+		LZ4_WILDCOPY(s, d, e);	\
+		d = e;	\
+	} while (0)
diff --git a/lib/lz4/lz4hc_compress.c b/lib/lz4/lz4hc_compress.c
new file mode 100644
index 0000000..eb1a74f
--- /dev/null
+++ b/lib/lz4/lz4hc_compress.c
@@ -0,0 +1,539 @@
+/*
+ * LZ4 HC - High Compression Mode of LZ4
+ * Copyright (C) 2011-2012, Yann Collet.
+ * BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * You can contact the author at :
+ * - LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html
+ * - LZ4 source repository : http://code.google.com/p/lz4/
+ *
+ *  Changed for kernel use by:
+ *  Chanho Min <chanho.min@lge.com>
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/lz4.h>
+#include <asm/unaligned.h>
+#include "lz4defs.h"
+
+struct lz4hc_data {
+	const u8 *base;
+	HTYPE hashtable[HASHTABLESIZE];
+	u16 chaintable[MAXD];
+	const u8 *nexttoupdate;
+} __attribute__((__packed__));
+
+static inline int lz4hc_init(struct lz4hc_data *hc4, const u8 *base)
+{
+	memset((void *)hc4->hashtable, 0, sizeof(hc4->hashtable));
+	memset(hc4->chaintable, 0xFF, sizeof(hc4->chaintable));
+
+#if LZ4_ARCH64
+	hc4->nexttoupdate = base + 1;
+#else
+	hc4->nexttoupdate = base;
+#endif
+	hc4->base = base;
+	return 1;
+}
+
+/* Update chains up to ip (excluded) */
+static inline void lz4hc_insert(struct lz4hc_data *hc4, const u8 *ip)
+{
+	u16 *chaintable = hc4->chaintable;
+	HTYPE *hashtable  = hc4->hashtable;
+#if LZ4_ARCH64
+	const BYTE * const base = hc4->base;
+#else
+	const int base = 0;
+#endif
+
+	while (hc4->nexttoupdate < ip) {
+		const u8 *p = hc4->nexttoupdate;
+		size_t delta = p - (hashtable[HASH_VALUE(p)] + base);
+		if (delta > MAX_DISTANCE)
+			delta = MAX_DISTANCE;
+		chaintable[(size_t)(p) & MAXD_MASK] = (u16)delta;
+		hashtable[HASH_VALUE(p)] = (p) - base;
+		hc4->nexttoupdate++;
+	}
+}
+
+static inline size_t lz4hc_commonlength(const u8 *p1, const u8 *p2,
+		const u8 *const matchlimit)
+{
+	const u8 *p1t = p1;
+
+	while (p1t < matchlimit - (STEPSIZE - 1)) {
+#if LZ4_ARCH64
+		u64 diff = A64(p2) ^ A64(p1t);
+#else
+		u32 diff = A32(p2) ^ A32(p1t);
+#endif
+		if (!diff) {
+			p1t += STEPSIZE;
+			p2 += STEPSIZE;
+			continue;
+		}
+		p1t += LZ4_NBCOMMONBYTES(diff);
+		return p1t - p1;
+	}
+#if LZ4_ARCH64
+	if ((p1t < (matchlimit-3)) && (A32(p2) == A32(p1t))) {
+		p1t += 4;
+		p2 += 4;
+	}
+#endif
+
+	if ((p1t < (matchlimit - 1)) && (A16(p2) == A16(p1t))) {
+		p1t += 2;
+		p2 += 2;
+	}
+	if ((p1t < matchlimit) && (*p2 == *p1t))
+		p1t++;
+	return p1t - p1;
+}
+
+static inline int lz4hc_insertandfindbestmatch(struct lz4hc_data *hc4,
+		const u8 *ip, const u8 *const matchlimit, const u8 **matchpos)
+{
+	u16 *const chaintable = hc4->chaintable;
+	HTYPE *const hashtable = hc4->hashtable;
+	const u8 *ref;
+#if LZ4_ARCH64
+	const BYTE * const base = hc4->base;
+#else
+	const int base = 0;
+#endif
+	int nbattempts = MAX_NB_ATTEMPTS;
+	size_t repl = 0, ml = 0;
+	u16 delta;
+
+	/* HC4 match finder */
+	lz4hc_insert(hc4, ip);
+	ref = hashtable[HASH_VALUE(ip)] + base;
+
+	/* potential repetition */
+	if (ref >= ip-4) {
+		/* confirmed */
+		if (A32(ref) == A32(ip)) {
+			delta = (u16)(ip-ref);
+			repl = ml  = lz4hc_commonlength(ip + MINMATCH,
+					ref + MINMATCH, matchlimit) + MINMATCH;
+			*matchpos = ref;
+		}
+		ref -= (size_t)chaintable[(size_t)(ref) & MAXD_MASK];
+	}
+
+	while ((ref >= ip - MAX_DISTANCE) && nbattempts) {
+		nbattempts--;
+		if (*(ref + ml) == *(ip + ml)) {
+			if (A32(ref) == A32(ip)) {
+				size_t mlt =
+					lz4hc_commonlength(ip + MINMATCH,
+					ref + MINMATCH, matchlimit) + MINMATCH;
+				if (mlt > ml) {
+					ml = mlt;
+					*matchpos = ref;
+				}
+			}
+		}
+		ref -= (size_t)chaintable[(size_t)(ref) & MAXD_MASK];
+	}
+
+	/* Complete table */
+	if (repl) {
+		const BYTE *ptr = ip;
+		const BYTE *end;
+		end = ip + repl - (MINMATCH-1);
+		/* Pre-Load */
+		while (ptr < end - delta) {
+			chaintable[(size_t)(ptr) & MAXD_MASK] = delta;
+			ptr++;
+		}
+		do {
+			chaintable[(size_t)(ptr) & MAXD_MASK] = delta;
+			/* Head of chain */
+			hashtable[HASH_VALUE(ptr)] = (ptr) - base;
+			ptr++;
+		} while (ptr < end);
+		hc4->nexttoupdate = end;
+	}
+
+	return (int)ml;
+}
+
+static inline int lz4hc_insertandgetwidermatch(struct lz4hc_data *hc4,
+	const u8 *ip, const u8 *startlimit, const u8 *matchlimit, int longest,
+	const u8 **matchpos, const u8 **startpos)
+{
+	u16 *const chaintable = hc4->chaintable;
+	HTYPE *const hashtable = hc4->hashtable;
+#if LZ4_ARCH64
+	const BYTE * const base = hc4->base;
+#else
+	const int base = 0;
+#endif
+	const u8 *ref;
+	int nbattempts = MAX_NB_ATTEMPTS;
+	int delta = (int)(ip - startlimit);
+
+	/* First Match */
+	lz4hc_insert(hc4, ip);
+	ref = hashtable[HASH_VALUE(ip)] + base;
+
+	while ((ref >= ip - MAX_DISTANCE) && (ref >= hc4->base)
+		&& (nbattempts)) {
+		nbattempts--;
+		if (*(startlimit + longest) == *(ref - delta + longest)) {
+			if (A32(ref) == A32(ip)) {
+				const u8 *reft = ref + MINMATCH;
+				const u8 *ipt = ip + MINMATCH;
+				const u8 *startt = ip;
+
+				while (ipt < matchlimit-(STEPSIZE - 1)) {
+					#if LZ4_ARCH64
+					u64 diff = A64(reft) ^ A64(ipt);
+					#else
+					u32 diff = A32(reft) ^ A32(ipt);
+					#endif
+
+					if (!diff) {
+						ipt += STEPSIZE;
+						reft += STEPSIZE;
+						continue;
+					}
+					ipt += LZ4_NBCOMMONBYTES(diff);
+					goto _endcount;
+				}
+				#if LZ4_ARCH64
+				if ((ipt < (matchlimit - 3))
+					&& (A32(reft) == A32(ipt))) {
+					ipt += 4;
+					reft += 4;
+				}
+				ipt += 2;
+				#endif
+				if ((ipt < (matchlimit - 1))
+					&& (A16(reft) == A16(ipt))) {
+					reft += 2;
+				}
+				if ((ipt < matchlimit) && (*reft == *ipt))
+					ipt++;
+_endcount:
+				reft = ref;
+
+				while ((startt > startlimit)
+					&& (reft > hc4->base)
+					&& (startt[-1] == reft[-1])) {
+					startt--;
+					reft--;
+				}
+
+				if ((ipt - startt) > longest) {
+					longest = (int)(ipt - startt);
+					*matchpos = reft;
+					*startpos = startt;
+				}
+			}
+		}
+		ref -= (size_t)chaintable[(size_t)(ref) & MAXD_MASK];
+	}
+	return longest;
+}
+
+static inline int lz4_encodesequence(const u8 **ip, u8 **op, const u8 **anchor,
+		int ml, const u8 *ref)
+{
+	int length, len;
+	u8 *token;
+
+	/* Encode Literal length */
+	length = (int)(*ip - *anchor);
+	token = (*op)++;
+	if (length >= (int)RUN_MASK) {
+		*token = (RUN_MASK << ML_BITS);
+		len = length - RUN_MASK;
+		for (; len > 254 ; len -= 255)
+			*(*op)++ = 255;
+		*(*op)++ = (u8)len;
+	} else
+		*token = (length << ML_BITS);
+
+	/* Copy Literals */
+	LZ4_BLINDCOPY(*anchor, *op, length);
+
+	/* Encode Offset */
+	LZ4_WRITE_LITTLEENDIAN_16(*op, (u16)(*ip - ref));
+
+	/* Encode MatchLength */
+	len = (int)(ml - MINMATCH);
+	if (len >= (int)ML_MASK) {
+		*token += ML_MASK;
+		len -= ML_MASK;
+		for (; len > 509 ; len -= 510) {
+			*(*op)++ = 255;
+			*(*op)++ = 255;
+		}
+		if (len > 254) {
+			len -= 255;
+			*(*op)++ = 255;
+		}
+		*(*op)++ = (u8)len;
+	} else
+		*token += len;
+
+	/* Prepare next loop */
+	*ip += ml;
+	*anchor = *ip;
+
+	return 0;
+}
+
+static int lz4_compresshcctx(struct lz4hc_data *ctx,
+		const char *source,
+		char *dest,
+		int isize)
+{
+	const u8 *ip = (const u8 *)source;
+	const u8 *anchor = ip;
+	const u8 *const iend = ip + isize;
+	const u8 *const mflimit = iend - MFLIMIT;
+	const u8 *const matchlimit = (iend - LASTLITERALS);
+
+	u8 *op = (u8 *)dest;
+
+	int ml, ml2, ml3, ml0;
+	const u8 *ref = NULL;
+	const u8 *start2 = NULL;
+	const u8 *ref2 = NULL;
+	const u8 *start3 = NULL;
+	const u8 *ref3 = NULL;
+	const u8 *start0;
+	const u8 *ref0;
+	int lastrun;
+
+	ip++;
+
+	/* Main Loop */
+	while (ip < mflimit) {
+		ml = lz4hc_insertandfindbestmatch(ctx, ip, matchlimit, (&ref));
+		if (!ml) {
+			ip++;
+			continue;
+		}
+
+		/* saved, in case we would skip too much */
+		start0 = ip;
+		ref0 = ref;
+		ml0 = ml;
+_search2:
+		if (ip+ml < mflimit)
+			ml2 = lz4hc_insertandgetwidermatch(ctx, ip + ml - 2,
+				ip + 1, matchlimit, ml, &ref2, &start2);
+		else
+			ml2 = ml;
+		/* No better match */
+		if (ml2 == ml) {
+			lz4_encodesequence(&ip, &op, &anchor, ml, ref);
+			continue;
+		}
+
+		if (start0 < ip) {
+			/* empirical */
+			if (start2 < ip + ml0) {
+				ip = start0;
+				ref = ref0;
+				ml = ml0;
+			}
+		}
+		/*
+		 * Here, start0==ip
+		 * First Match too small : removed
+		 */
+		if ((start2 - ip) < 3) {
+			ml = ml2;
+			ip = start2;
+			ref = ref2;
+			goto _search2;
+		}
+
+_search3:
+		/*
+		 * Currently we have :
+		 * ml2 > ml1, and
+		 * ip1+3 <= ip2 (usually < ip1+ml1)
+		 */
+		if ((start2 - ip) < OPTIMAL_ML) {
+			int correction;
+			int new_ml = ml;
+			if (new_ml > OPTIMAL_ML)
+				new_ml = OPTIMAL_ML;
+			if (ip + new_ml > start2 + ml2 - MINMATCH)
+				new_ml = (int)(start2 - ip) + ml2 - MINMATCH;
+			correction = new_ml - (int)(start2 - ip);
+			if (correction > 0) {
+				start2 += correction;
+				ref2 += correction;
+				ml2 -= correction;
+			}
+		}
+		/*
+		 * Now, we have start2 = ip+new_ml,
+		 * with new_ml=min(ml, OPTIMAL_ML=18)
+		 */
+		if (start2 + ml2 < mflimit)
+			ml3 = lz4hc_insertandgetwidermatch(ctx,
+				start2 + ml2 - 3, start2, matchlimit,
+				ml2, &ref3, &start3);
+		else
+			ml3 = ml2;
+
+		/* No better match : 2 sequences to encode */
+		if (ml3 == ml2) {
+			/* ip & ref are known; Now for ml */
+			if (start2 < ip+ml)
+				ml = (int)(start2 - ip);
+
+			/* Now, encode 2 sequences */
+			lz4_encodesequence(&ip, &op, &anchor, ml, ref);
+			ip = start2;
+			lz4_encodesequence(&ip, &op, &anchor, ml2, ref2);
+			continue;
+		}
+
+		/* Not enough space for match 2 : remove it */
+		if (start3 < ip + ml + 3) {
+			/*
+			 * can write Seq1 immediately ==> Seq2 is removed,
+			 * so Seq3 becomes Seq1
+			 */
+			if (start3 >= (ip + ml)) {
+				if (start2 < ip + ml) {
+					int correction =
+						(int)(ip + ml - start2);
+					start2 += correction;
+					ref2 += correction;
+					ml2 -= correction;
+					if (ml2 < MINMATCH) {
+						start2 = start3;
+						ref2 = ref3;
+						ml2 = ml3;
+					}
+				}
+
+				lz4_encodesequence(&ip, &op, &anchor, ml, ref);
+				ip  = start3;
+				ref = ref3;
+				ml  = ml3;
+
+				start0 = start2;
+				ref0 = ref2;
+				ml0 = ml2;
+				goto _search2;
+			}
+
+			start2 = start3;
+			ref2 = ref3;
+			ml2 = ml3;
+			goto _search3;
+		}
+
+		/*
+		 * OK, now we have 3 ascending matches; let's write at least
+		 * the first one ip & ref are known; Now for ml
+		 */
+		if (start2 < ip + ml) {
+			if ((start2 - ip) < (int)ML_MASK) {
+				int correction;
+				if (ml > OPTIMAL_ML)
+					ml = OPTIMAL_ML;
+				if (ip + ml > start2 + ml2 - MINMATCH)
+					ml = (int)(start2 - ip) + ml2
+						- MINMATCH;
+				correction = ml - (int)(start2 - ip);
+				if (correction > 0) {
+					start2 += correction;
+					ref2 += correction;
+					ml2 -= correction;
+				}
+			} else
+				ml = (int)(start2 - ip);
+		}
+		lz4_encodesequence(&ip, &op, &anchor, ml, ref);
+
+		ip = start2;
+		ref = ref2;
+		ml = ml2;
+
+		start2 = start3;
+		ref2 = ref3;
+		ml2 = ml3;
+
+		goto _search3;
+	}
+
+	/* Encode Last Literals */
+	lastrun = (int)(iend - anchor);
+	if (lastrun >= (int)RUN_MASK) {
+		*op++ = (RUN_MASK << ML_BITS);
+		lastrun -= RUN_MASK;
+		for (; lastrun > 254 ; lastrun -= 255)
+			*op++ = 255;
+		*op++ = (u8) lastrun;
+	} else
+		*op++ = (lastrun << ML_BITS);
+	memcpy(op, anchor, iend - anchor);
+	op += iend - anchor;
+	/* End */
+	return (int) (((char *)op) - dest);
+}
+
+int lz4hc_compress(const unsigned char *src, size_t src_len,
+			unsigned char *dst, size_t *dst_len, void *wrkmem)
+{
+	int ret = -1;
+	int out_len = 0;
+
+	struct lz4hc_data *hc4 = (struct lz4hc_data *)wrkmem;
+	lz4hc_init(hc4, (const u8 *)src);
+	out_len = lz4_compresshcctx((struct lz4hc_data *)hc4, (const u8 *)src,
+		(char *)dst, (int)src_len);
+
+	if (out_len < 0)
+		goto exit;
+
+	*dst_len = out_len;
+	return 0;
+
+exit:
+	return ret;
+}
+EXPORT_SYMBOL_GPL(lz4hc_compress);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("LZ4HC compressor");
diff --git a/lib/lzo/lzo1x_decompress_safe.c b/lib/lzo/lzo1x_decompress_safe.c
index 569985d..e3edc5f 100644
--- a/lib/lzo/lzo1x_decompress_safe.c
+++ b/lib/lzo/lzo1x_decompress_safe.c
@@ -72,9 +72,11 @@ copy_literal_run:
 						COPY8(op, ip);
 						op += 8;
 						ip += 8;
+#  if !defined(__arm__)
 						COPY8(op, ip);
 						op += 8;
 						ip += 8;
+#  endif
 					} while (ip < ie);
 					ip = ie;
 					op = oe;
@@ -159,9 +161,11 @@ copy_literal_run:
 					COPY8(op, m_pos);
 					op += 8;
 					m_pos += 8;
+#  if !defined(__arm__)
 					COPY8(op, m_pos);
 					op += 8;
 					m_pos += 8;
+#  endif
 				} while (op < oe);
 				op = oe;
 				if (HAVE_IP(6)) {
diff --git a/lib/lzo/lzodefs.h b/lib/lzo/lzodefs.h
index 6710b83..db756cc 100644
--- a/lib/lzo/lzodefs.h
+++ b/lib/lzo/lzodefs.h
@@ -12,8 +12,14 @@
  */
 
 
+#if 1 && defined(__arm__) && ((__LINUX_ARM_ARCH__ >= 6) || defined(__ARM_FEATURE_UNALIGNED))
+#define CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS 1
+#define COPY4(dst, src)	\
+		* (u32 *) (void *) (dst) = * (const u32 *) (const void *) (src)
+#else
 #define COPY4(dst, src)	\
 		put_unaligned(get_unaligned((const u32 *)(src)), (u32 *)(dst))
+#endif
 #if defined(__x86_64__)
 #define COPY8(dst, src)	\
 		put_unaligned(get_unaligned((const u64 *)(src)), (u64 *)(dst))
diff --git a/lib/notifier-error-inject.c b/lib/notifier-error-inject.c
index 44b92cb..eb4a04a 100644
--- a/lib/notifier-error-inject.c
+++ b/lib/notifier-error-inject.c
@@ -17,7 +17,7 @@ static int debugfs_errno_get(void *data, u64 *val)
 DEFINE_SIMPLE_ATTRIBUTE(fops_errno, debugfs_errno_get, debugfs_errno_set,
 			"%lld\n");
 
-static struct dentry *debugfs_create_errno(const char *name, mode_t mode,
+static struct dentry *debugfs_create_errno(const char *name, umode_t mode,
 				struct dentry *parent, int *value)
 {
 	return debugfs_create_file(name, mode, parent, value, &fops_errno);
@@ -50,7 +50,7 @@ struct dentry *notifier_err_inject_init(const char *name, struct dentry *parent,
 			struct notifier_err_inject *err_inject, int priority)
 {
 	struct notifier_err_inject_action *action;
-	mode_t mode = S_IFREG | S_IRUSR | S_IWUSR;
+	umode_t mode = S_IFREG | S_IRUSR | S_IWUSR;
 	struct dentry *dir;
 	struct dentry *actions_dir;
 
diff --git a/lib/percpu-refcount.c b/lib/percpu-refcount.c
new file mode 100644
index 0000000..e9bb787
--- /dev/null
+++ b/lib/percpu-refcount.c
@@ -0,0 +1,244 @@
+#define pr_fmt(fmt) "%s: " fmt "\n", __func__
+
+#include <linux/kernel.h>
+#include <linux/jiffies.h>
+#include <linux/percpu-refcount.h>
+#include <linux/rcupdate.h>
+
+/*
+ * A percpu refcount can be in 4 different modes. The state is tracked in the
+ * low two bits of percpu_ref->pcpu_count:
+ *
+ * PCPU_REF_NONE - the initial state, no percpu counters allocated.
+ *
+ * PCPU_REF_PTR - using percpu counters for the refcount.
+ *
+ * PCPU_REF_DYING - we're shutting down so get()/put() should use the embedded
+ * atomic counter, but we're not finished updating the atomic counter from the
+ * percpu counters - this means that percpu_ref_put() can't check for the ref
+ * hitting 0 yet.
+ *
+ * PCPU_REF_DEAD - we've finished the teardown sequence, percpu_ref_put() should
+ * now check for the ref hitting 0.
+ *
+ * In PCPU_REF_NONE mode, we need to count the number of times percpu_ref_get()
+ * is called; this is done with the high bits of the raw atomic counter. We also
+ * track the time, in jiffies, when the get count last wrapped - this is done
+ * with the remaining bits of percpu_ref->percpu_count.
+ *
+ * So, when percpu_ref_get() is called it increments the get count and checks if
+ * it wrapped; if it did, it checks if the last time it wrapped was less than
+ * one second ago; if so, we want to allocate percpu counters.
+ *
+ * PCPU_COUNT_BITS determines the threshold where we convert to percpu: of the
+ * raw 64 bit counter, we use PCPU_COUNT_BITS for the refcount, and the
+ * remaining (high) bits to count the number of times percpu_ref_get() has been
+ * called. It's currently (completely arbitrarily) 16384 times in one second.
+ *
+ * Percpu mode (PCPU_REF_PTR):
+ *
+ * In percpu mode all we do on get and put is increment or decrement the cpu
+ * local counter, which is a 32 bit unsigned int.
+ *
+ * Note that all the gets() could be happening on one cpu, and all the puts() on
+ * another - the individual cpu counters can wrap (potentially many times).
+ *
+ * But this is fine because we don't need to check for the ref hitting 0 in
+ * percpu mode; before we set the state to PCPU_REF_DEAD we simply sum up all
+ * the percpu counters and add them to the atomic counter. Since addition and
+ * subtraction in modular arithmatic is still associative, the result will be
+ * correct.
+ */
+
+#define PCPU_COUNT_BITS		50
+#define PCPU_COUNT_MASK		((1LL << PCPU_COUNT_BITS) - 1)
+
+#define PCPU_STATUS_BITS	2
+#define PCPU_STATUS_MASK	((1 << PCPU_STATUS_BITS) - 1)
+
+#define PCPU_REF_PTR		0
+#define PCPU_REF_NONE		1
+#define PCPU_REF_DYING		2
+#define PCPU_REF_DEAD		3
+
+#define REF_STATUS(count)	(count & PCPU_STATUS_MASK)
+
+/**
+ * percpu_ref_init - initialize a dynamic percpu refcount
+ *
+ * Initializes the refcount in single atomic counter mode with a refcount of 1;
+ * analagous to atomic_set(ref, 1).
+ */
+void percpu_ref_init(struct percpu_ref *ref)
+{
+	unsigned long now = jiffies;
+
+	atomic64_set(&ref->count, 1);
+
+	now <<= PCPU_STATUS_BITS;
+	now |= PCPU_REF_NONE;
+
+	ref->pcpu_count = now;
+}
+
+static void percpu_ref_alloc(struct percpu_ref *ref, unsigned long pcpu_count)
+{
+	unsigned long new, now = jiffies;
+
+	now <<= PCPU_STATUS_BITS;
+	now |= PCPU_REF_NONE;
+
+	if (now - pcpu_count <= HZ << PCPU_STATUS_BITS) {
+		rcu_read_unlock();
+		new = (unsigned long) alloc_percpu(unsigned);
+		rcu_read_lock();
+
+		if (!new)
+			goto update_time;
+
+		BUG_ON(new & PCPU_STATUS_MASK);
+
+		if (cmpxchg(&ref->pcpu_count, pcpu_count, new) != pcpu_count)
+			free_percpu((void __percpu *) new);
+		else
+			pr_debug("created");
+	} else {
+update_time:
+		new = now;
+		cmpxchg(&ref->pcpu_count, pcpu_count, new);
+	}
+}
+
+void __percpu_ref_get(struct percpu_ref *ref, bool alloc)
+{
+	unsigned long pcpu_count;
+	uint64_t v;
+
+	pcpu_count = ACCESS_ONCE(ref->pcpu_count);
+
+	if (REF_STATUS(pcpu_count) == PCPU_REF_PTR) {
+		/* for rcu - we're not using rcu_dereference() */
+		smp_read_barrier_depends();
+		__this_cpu_inc(*((unsigned __percpu *) pcpu_count));
+	} else {
+		v = atomic64_add_return(1 + (1ULL << PCPU_COUNT_BITS),
+					&ref->count);
+
+		if (!(v >> PCPU_COUNT_BITS) &&
+		    REF_STATUS(pcpu_count) == PCPU_REF_NONE && alloc)
+			percpu_ref_alloc(ref, pcpu_count);
+	}
+}
+
+/**
+ * percpu_ref_put - decrement a dynamic percpu refcount
+ *
+ * Returns true if the result is 0, otherwise false; only checks for the ref
+ * hitting 0 after percpu_ref_kill() has been called. Analagous to
+ * atomic_dec_and_test().
+ */
+int percpu_ref_put(struct percpu_ref *ref)
+{
+	unsigned long pcpu_count;
+	uint64_t v;
+	int ret = 0;
+
+	rcu_read_lock();
+
+	pcpu_count = ACCESS_ONCE(ref->pcpu_count);
+
+	switch (REF_STATUS(pcpu_count)) {
+	case PCPU_REF_PTR:
+		/* for rcu - we're not using rcu_dereference() */
+		smp_read_barrier_depends();
+		__this_cpu_dec(*((unsigned __percpu *) pcpu_count));
+		break;
+	case PCPU_REF_NONE:
+	case PCPU_REF_DYING:
+		atomic64_dec(&ref->count);
+		break;
+	case PCPU_REF_DEAD:
+		v = atomic64_dec_return(&ref->count);
+		v &= PCPU_COUNT_MASK;
+
+		ret = v == 0;
+		break;
+	}
+
+	rcu_read_unlock();
+
+	return ret;
+}
+
+/**
+ * percpu_ref_kill - prepare a dynamic percpu refcount for teardown
+ *
+ * Must be called before dropping the initial ref, so that percpu_ref_put()
+ * knows to check for the refcount hitting 0. If the refcount was in percpu
+ * mode, converts it back to single atomic counter mode.
+ *
+ * Returns true the first time called on @ref and false if @ref is already
+ * shutting down, so it may be used by the caller for synchronizing other parts
+ * of a two stage shutdown.
+ */
+int percpu_ref_kill(struct percpu_ref *ref)
+{
+	unsigned long old, new, status, pcpu_count;
+
+	pcpu_count = ACCESS_ONCE(ref->pcpu_count);
+
+	do {
+		status = REF_STATUS(pcpu_count);
+
+		switch (status) {
+		case PCPU_REF_PTR:
+			new = PCPU_REF_DYING;
+			break;
+		case PCPU_REF_NONE:
+			new = PCPU_REF_DEAD;
+			break;
+		case PCPU_REF_DYING:
+		case PCPU_REF_DEAD:
+			return 0;
+		}
+
+		old = pcpu_count;
+		pcpu_count = cmpxchg(&ref->pcpu_count, old, new);
+	} while (pcpu_count != old);
+
+	if (status == PCPU_REF_PTR) {
+		unsigned count = 0, cpu;
+
+		synchronize_rcu();
+
+		for_each_possible_cpu(cpu)
+			count += *per_cpu_ptr((unsigned __percpu *)pcpu_count,
+					      cpu);
+
+		pr_debug("global %lli pcpu %i",
+			 atomic64_read(&ref->count) & PCPU_COUNT_MASK,
+			 (int) count);
+
+		atomic64_add((int) count, &ref->count);
+		smp_wmb();
+		/* Between setting global count and setting PCPU_REF_DEAD */
+		ref->pcpu_count = PCPU_REF_DEAD;
+
+		free_percpu((unsigned __percpu *) pcpu_count);
+	}
+
+	return 1;
+}
+
+/**
+ * percpu_ref_dead - check if a dynamic percpu refcount is shutting down
+ *
+ * Returns true if percpu_ref_kill() has been called on @ref, false otherwise.
+ */
+int percpu_ref_dead(struct percpu_ref *ref)
+{
+	unsigned status = REF_STATUS(ref->pcpu_count);
+
+	return status == PCPU_REF_DYING ||
+		status == PCPU_REF_DEAD;
+}
diff --git a/lib/scatterlist.c b/lib/scatterlist.c
index b83c144..a1cf8ca 100644
--- a/lib/scatterlist.c
+++ b/lib/scatterlist.c
@@ -401,7 +401,6 @@ void __sg_page_iter_start(struct sg_page_iter *piter,
 	piter->__pg_advance = 0;
 	piter->__nents = nents;
 
-	piter->page = NULL;
 	piter->sg = sglist;
 	piter->sg_pgoffset = pgoffset;
 }
@@ -426,7 +425,6 @@ bool __sg_page_iter_next(struct sg_page_iter *piter)
 		if (!--piter->__nents || !piter->sg)
 			return false;
 	}
-	piter->page = nth_page(sg_page(piter->sg), piter->sg_pgoffset);
 
 	return true;
 }
@@ -496,7 +494,7 @@ bool sg_miter_next(struct sg_mapping_iter *miter)
 		miter->__remaining = min_t(unsigned long, miter->__remaining,
 					   PAGE_SIZE - miter->__offset);
 	}
-	miter->page = miter->piter.page;
+	miter->page = sg_page_iter_page(&miter->piter);
 	miter->consumed = miter->length = miter->__remaining;
 
 	if (miter->__flags & SG_MITER_ATOMIC)
diff --git a/lib/show_mem.c b/lib/show_mem.c
index 4407f8c..b7c7231 100644
--- a/lib/show_mem.c
+++ b/lib/show_mem.c
@@ -18,6 +18,9 @@ void show_mem(unsigned int filter)
 	printk("Mem-Info:\n");
 	show_free_areas(filter);
 
+	if (filter & SHOW_MEM_FILTER_PAGE_COUNT)
+		return;
+
 	for_each_online_pgdat(pgdat) {
 		unsigned long i, flags;
 
diff --git a/lib/usercopy.c b/lib/usercopy.c
new file mode 100644
index 0000000..4f5b1dd
--- /dev/null
+++ b/lib/usercopy.c
@@ -0,0 +1,9 @@
+#include <linux/export.h>
+#include <linux/bug.h>
+#include <linux/uaccess.h>
+
+void copy_from_user_overflow(void)
+{
+	WARN(1, "Buffer overflow detected!\n");
+}
+EXPORT_SYMBOL(copy_from_user_overflow);
diff --git a/lib/uuid.c b/lib/uuid.c
index 52a6fe6..398821e 100644
--- a/lib/uuid.c
+++ b/lib/uuid.c
@@ -25,13 +25,7 @@
 
 static void __uuid_gen_common(__u8 b[16])
 {
-	int i;
-	u32 r;
-
-	for (i = 0; i < 4; i++) {
-		r = random32();
-		memcpy(b + i * 4, &r, 4);
-	}
+	prandom_bytes(b, 16);
 	/* reversion 0b10 */
 	b[8] = (b[8] & 0x3F) | 0x80;
 }
diff --git a/localversion-next b/localversion-next
new file mode 100644
index 0000000..c8ffaf6
--- /dev/null
+++ b/localversion-next
@@ -0,0 +1 @@
+-next-20130405
diff --git a/mm/backing-dev.c b/mm/backing-dev.c
index 41733c5..5025174 100644
--- a/mm/backing-dev.c
+++ b/mm/backing-dev.c
@@ -31,13 +31,14 @@ EXPORT_SYMBOL_GPL(noop_backing_dev_info);
 static struct class *bdi_class;
 
 /*
- * bdi_lock protects updates to bdi_list and bdi_pending_list, as well as
- * reader side protection for bdi_pending_list. bdi_list has RCU reader side
+ * bdi_lock protects updates to bdi_list. bdi_list has RCU reader side
  * locking.
  */
 DEFINE_SPINLOCK(bdi_lock);
 LIST_HEAD(bdi_list);
-LIST_HEAD(bdi_pending_list);
+
+/* bdi_wq serves all asynchronous writeback tasks */
+struct workqueue_struct *bdi_wq;
 
 void bdi_lock_two(struct bdi_writeback *wb1, struct bdi_writeback *wb2)
 {
@@ -257,6 +258,11 @@ static int __init default_bdi_init(void)
 {
 	int err;
 
+	bdi_wq = alloc_workqueue("writeback", WQ_MEM_RECLAIM | WQ_FREEZABLE |
+					      WQ_UNBOUND | WQ_SYSFS, 0);
+	if (!bdi_wq)
+		return -ENOMEM;
+
 	err = bdi_init(&default_backing_dev_info);
 	if (!err)
 		bdi_register(&default_backing_dev_info, NULL, "default");
@@ -271,26 +277,6 @@ int bdi_has_dirty_io(struct backing_dev_info *bdi)
 	return wb_has_dirty_io(&bdi->wb);
 }
 
-static void wakeup_timer_fn(unsigned long data)
-{
-	struct backing_dev_info *bdi = (struct backing_dev_info *)data;
-
-	spin_lock_bh(&bdi->wb_lock);
-	if (bdi->wb.task) {
-		trace_writeback_wake_thread(bdi);
-		wake_up_process(bdi->wb.task);
-	} else if (bdi->dev) {
-		/*
-		 * When bdi tasks are inactive for long time, they are killed.
-		 * In this case we have to wake-up the forker thread which
-		 * should create and run the bdi thread.
-		 */
-		trace_writeback_wake_forker_thread(bdi);
-		wake_up_process(default_backing_dev_info.wb.task);
-	}
-	spin_unlock_bh(&bdi->wb_lock);
-}
-
 /*
  * This function is used when the first inode for this bdi is marked dirty. It
  * wakes-up the corresponding bdi thread which should then take care of the
@@ -307,176 +293,7 @@ void bdi_wakeup_thread_delayed(struct backing_dev_info *bdi)
 	unsigned long timeout;
 
 	timeout = msecs_to_jiffies(dirty_writeback_interval * 10);
-	mod_timer(&bdi->wb.wakeup_timer, jiffies + timeout);
-}
-
-/*
- * Calculate the longest interval (jiffies) bdi threads are allowed to be
- * inactive.
- */
-static unsigned long bdi_longest_inactive(void)
-{
-	unsigned long interval;
-
-	interval = msecs_to_jiffies(dirty_writeback_interval * 10);
-	return max(5UL * 60 * HZ, interval);
-}
-
-/*
- * Clear pending bit and wakeup anybody waiting for flusher thread creation or
- * shutdown
- */
-static void bdi_clear_pending(struct backing_dev_info *bdi)
-{
-	clear_bit(BDI_pending, &bdi->state);
-	smp_mb__after_clear_bit();
-	wake_up_bit(&bdi->state, BDI_pending);
-}
-
-static int bdi_forker_thread(void *ptr)
-{
-	struct bdi_writeback *me = ptr;
-
-	current->flags |= PF_SWAPWRITE;
-	set_freezable();
-
-	/*
-	 * Our parent may run at a different priority, just set us to normal
-	 */
-	set_user_nice(current, 0);
-
-	for (;;) {
-		struct task_struct *task = NULL;
-		struct backing_dev_info *bdi;
-		enum {
-			NO_ACTION,   /* Nothing to do */
-			FORK_THREAD, /* Fork bdi thread */
-			KILL_THREAD, /* Kill inactive bdi thread */
-		} action = NO_ACTION;
-
-		/*
-		 * Temporary measure, we want to make sure we don't see
-		 * dirty data on the default backing_dev_info
-		 */
-		if (wb_has_dirty_io(me) || !list_empty(&me->bdi->work_list)) {
-			del_timer(&me->wakeup_timer);
-			wb_do_writeback(me, 0);
-		}
-
-		spin_lock_bh(&bdi_lock);
-		/*
-		 * In the following loop we are going to check whether we have
-		 * some work to do without any synchronization with tasks
-		 * waking us up to do work for them. Set the task state here
-		 * so that we don't miss wakeups after verifying conditions.
-		 */
-		set_current_state(TASK_INTERRUPTIBLE);
-
-		list_for_each_entry(bdi, &bdi_list, bdi_list) {
-			bool have_dirty_io;
-
-			if (!bdi_cap_writeback_dirty(bdi) ||
-			     bdi_cap_flush_forker(bdi))
-				continue;
-
-			WARN(!test_bit(BDI_registered, &bdi->state),
-			     "bdi %p/%s is not registered!\n", bdi, bdi->name);
-
-			have_dirty_io = !list_empty(&bdi->work_list) ||
-					wb_has_dirty_io(&bdi->wb);
-
-			/*
-			 * If the bdi has work to do, but the thread does not
-			 * exist - create it.
-			 */
-			if (!bdi->wb.task && have_dirty_io) {
-				/*
-				 * Set the pending bit - if someone will try to
-				 * unregister this bdi - it'll wait on this bit.
-				 */
-				set_bit(BDI_pending, &bdi->state);
-				action = FORK_THREAD;
-				break;
-			}
-
-			spin_lock(&bdi->wb_lock);
-
-			/*
-			 * If there is no work to do and the bdi thread was
-			 * inactive long enough - kill it. The wb_lock is taken
-			 * to make sure no-one adds more work to this bdi and
-			 * wakes the bdi thread up.
-			 */
-			if (bdi->wb.task && !have_dirty_io &&
-			    time_after(jiffies, bdi->wb.last_active +
-						bdi_longest_inactive())) {
-				task = bdi->wb.task;
-				bdi->wb.task = NULL;
-				spin_unlock(&bdi->wb_lock);
-				set_bit(BDI_pending, &bdi->state);
-				action = KILL_THREAD;
-				break;
-			}
-			spin_unlock(&bdi->wb_lock);
-		}
-		spin_unlock_bh(&bdi_lock);
-
-		/* Keep working if default bdi still has things to do */
-		if (!list_empty(&me->bdi->work_list))
-			__set_current_state(TASK_RUNNING);
-
-		switch (action) {
-		case FORK_THREAD:
-			__set_current_state(TASK_RUNNING);
-			task = kthread_create(bdi_writeback_thread, &bdi->wb,
-					      "flush-%s", dev_name(bdi->dev));
-			if (IS_ERR(task)) {
-				/*
-				 * If thread creation fails, force writeout of
-				 * the bdi from the thread. Hopefully 1024 is
-				 * large enough for efficient IO.
-				 */
-				writeback_inodes_wb(&bdi->wb, 1024,
-						    WB_REASON_FORKER_THREAD);
-			} else {
-				/*
-				 * The spinlock makes sure we do not lose
-				 * wake-ups when racing with 'bdi_queue_work()'.
-				 * And as soon as the bdi thread is visible, we
-				 * can start it.
-				 */
-				spin_lock_bh(&bdi->wb_lock);
-				bdi->wb.task = task;
-				spin_unlock_bh(&bdi->wb_lock);
-				wake_up_process(task);
-			}
-			bdi_clear_pending(bdi);
-			break;
-
-		case KILL_THREAD:
-			__set_current_state(TASK_RUNNING);
-			kthread_stop(task);
-			bdi_clear_pending(bdi);
-			break;
-
-		case NO_ACTION:
-			if (!wb_has_dirty_io(me) || !dirty_writeback_interval)
-				/*
-				 * There are no dirty data. The only thing we
-				 * should now care about is checking for
-				 * inactive bdi threads and killing them. Thus,
-				 * let's sleep for longer time, save energy and
-				 * be friendly for battery-driven devices.
-				 */
-				schedule_timeout(bdi_longest_inactive());
-			else
-				schedule_timeout(msecs_to_jiffies(dirty_writeback_interval * 10));
-			try_to_freeze();
-			break;
-		}
-	}
-
-	return 0;
+	mod_delayed_work(bdi_wq, &bdi->wb.dwork, timeout);
 }
 
 /*
@@ -489,6 +306,9 @@ static void bdi_remove_from_list(struct backing_dev_info *bdi)
 	spin_unlock_bh(&bdi_lock);
 
 	synchronize_rcu_expedited();
+
+	/* bdi_list is now unused, clear it to mark @bdi dying */
+	INIT_LIST_HEAD(&bdi->bdi_list);
 }
 
 int bdi_register(struct backing_dev_info *bdi, struct device *parent,
@@ -508,20 +328,6 @@ int bdi_register(struct backing_dev_info *bdi, struct device *parent,
 
 	bdi->dev = dev;
 
-	/*
-	 * Just start the forker thread for our default backing_dev_info,
-	 * and add other bdi's to the list. They will get a thread created
-	 * on-demand when they need it.
-	 */
-	if (bdi_cap_flush_forker(bdi)) {
-		struct bdi_writeback *wb = &bdi->wb;
-
-		wb->task = kthread_run(bdi_forker_thread, wb, "bdi-%s",
-						dev_name(dev));
-		if (IS_ERR(wb->task))
-			return PTR_ERR(wb->task);
-	}
-
 	bdi_debug_register(bdi, dev_name(dev));
 	set_bit(BDI_registered, &bdi->state);
 
@@ -545,8 +351,6 @@ EXPORT_SYMBOL(bdi_register_dev);
  */
 static void bdi_wb_shutdown(struct backing_dev_info *bdi)
 {
-	struct task_struct *task;
-
 	if (!bdi_cap_writeback_dirty(bdi))
 		return;
 
@@ -556,22 +360,20 @@ static void bdi_wb_shutdown(struct backing_dev_info *bdi)
 	bdi_remove_from_list(bdi);
 
 	/*
-	 * If setup is pending, wait for that to complete first
+	 * Drain work list and shutdown the delayed_work.  At this point,
+	 * @bdi->bdi_list is empty telling bdi_Writeback_workfn() that @bdi
+	 * is dying and its work_list needs to be drained no matter what.
 	 */
-	wait_on_bit(&bdi->state, BDI_pending, bdi_sched_wait,
-			TASK_UNINTERRUPTIBLE);
+	mod_delayed_work(bdi_wq, &bdi->wb.dwork, 0);
+	flush_delayed_work(&bdi->wb.dwork);
+	WARN_ON(!list_empty(&bdi->work_list));
 
 	/*
-	 * Finally, kill the kernel thread. We don't need to be RCU
-	 * safe anymore, since the bdi is gone from visibility.
+	 * This shouldn't be necessary unless @bdi for some reason has
+	 * unflushed dirty IO after work_list is drained.  Do it anyway
+	 * just in case.
 	 */
-	spin_lock_bh(&bdi->wb_lock);
-	task = bdi->wb.task;
-	bdi->wb.task = NULL;
-	spin_unlock_bh(&bdi->wb_lock);
-
-	if (task)
-		kthread_stop(task);
+	cancel_delayed_work_sync(&bdi->wb.dwork);
 }
 
 /*
@@ -597,10 +399,8 @@ void bdi_unregister(struct backing_dev_info *bdi)
 		bdi_set_min_ratio(bdi, 0);
 		trace_writeback_bdi_unregister(bdi);
 		bdi_prune_sb(bdi);
-		del_timer_sync(&bdi->wb.wakeup_timer);
 
-		if (!bdi_cap_flush_forker(bdi))
-			bdi_wb_shutdown(bdi);
+		bdi_wb_shutdown(bdi);
 		bdi_debug_unregister(bdi);
 
 		spin_lock_bh(&bdi->wb_lock);
@@ -622,7 +422,7 @@ static void bdi_wb_init(struct bdi_writeback *wb, struct backing_dev_info *bdi)
 	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);
+	INIT_DELAYED_WORK(&wb->dwork, bdi_writeback_workfn);
 }
 
 /*
@@ -695,12 +495,11 @@ void bdi_destroy(struct backing_dev_info *bdi)
 	bdi_unregister(bdi);
 
 	/*
-	 * If bdi_unregister() had already been called earlier, the
-	 * wakeup_timer could still be armed because bdi_prune_sb()
-	 * can race with the bdi_wakeup_thread_delayed() calls from
-	 * __mark_inode_dirty().
+	 * If bdi_unregister() had already been called earlier, the dwork
+	 * could still be pending because bdi_prune_sb() can race with the
+	 * bdi_wakeup_thread_delayed() calls from __mark_inode_dirty().
 	 */
-	del_timer_sync(&bdi->wb.wakeup_timer);
+	cancel_delayed_work_sync(&bdi->wb.dwork);
 
 	for (i = 0; i < NR_BDI_STAT_ITEMS; i++)
 		percpu_counter_destroy(&bdi->bdi_stat[i]);
diff --git a/mm/balloon_compaction.c b/mm/balloon_compaction.c
index 07dbc8e..2c8ce49 100644
--- a/mm/balloon_compaction.c
+++ b/mm/balloon_compaction.c
@@ -242,6 +242,7 @@ bool balloon_page_isolate(struct page *page)
 			if (__is_movable_balloon_page(page) &&
 			    page_count(page) == 2) {
 				__isolate_balloon_page(page);
+				balloon_event_count(COMPACTBALLOONISOLATED);
 				unlock_page(page);
 				return true;
 			}
@@ -265,6 +266,7 @@ void balloon_page_putback(struct page *page)
 		__putback_balloon_page(page);
 		/* drop the extra ref count taken for page isolation */
 		put_page(page);
+		balloon_event_count(COMPACTBALLOONRETURNED);
 	} else {
 		WARN_ON(1);
 		dump_page(page);
diff --git a/mm/bootmem.c b/mm/bootmem.c
index 2b0bcb0..d937107 100644
--- a/mm/bootmem.c
+++ b/mm/bootmem.c
@@ -32,6 +32,7 @@ EXPORT_SYMBOL(contig_page_data);
 
 unsigned long max_low_pfn;
 unsigned long min_low_pfn;
+EXPORT_SYMBOL(min_low_pfn);
 unsigned long max_pfn;
 
 bootmem_data_t bootmem_node_data[MAX_NUMNODES] __initdata;
diff --git a/mm/bounce.c b/mm/bounce.c
index 5f89017..708c1e9 100644
--- a/mm/bounce.c
+++ b/mm/bounce.c
@@ -101,7 +101,7 @@ static void copy_to_high_bio_irq(struct bio *to, struct bio *from)
 	struct bio_vec *tovec, *fromvec;
 	int i;
 
-	__bio_for_each_segment(tovec, to, i, 0) {
+	bio_for_each_segment(tovec, to, i) {
 		fromvec = from->bi_io_vec + i;
 
 		/*
@@ -134,7 +134,7 @@ static void bounce_end_io(struct bio *bio, mempool_t *pool, int err)
 	/*
 	 * free up bounce indirect pages used
 	 */
-	__bio_for_each_segment(bvec, bio, i, 0) {
+	bio_for_each_segment_all(bvec, bio, i) {
 		org_vec = bio_orig->bi_io_vec + i;
 		if (bvec->bv_page == org_vec->bv_page)
 			continue;
@@ -147,12 +147,14 @@ static void bounce_end_io(struct bio *bio, mempool_t *pool, int err)
 	bio_put(bio);
 }
 
-static void bounce_end_io_write(struct bio *bio, int err)
+static void bounce_end_io_write(struct bio *bio, int err,
+				struct batch_complete *batch)
 {
 	bounce_end_io(bio, page_pool, err);
 }
 
-static void bounce_end_io_write_isa(struct bio *bio, int err)
+static void bounce_end_io_write_isa(struct bio *bio, int err,
+				    struct batch_complete *batch)
 {
 
 	bounce_end_io(bio, isa_page_pool, err);
@@ -168,12 +170,14 @@ static void __bounce_end_io_read(struct bio *bio, mempool_t *pool, int err)
 	bounce_end_io(bio, pool, err);
 }
 
-static void bounce_end_io_read(struct bio *bio, int err)
+static void bounce_end_io_read(struct bio *bio, int err,
+			       struct batch_complete *batch)
 {
 	__bounce_end_io_read(bio, page_pool, err);
 }
 
-static void bounce_end_io_read_isa(struct bio *bio, int err)
+static void bounce_end_io_read_isa(struct bio *bio, int err,
+				   struct batch_complete *batch)
 {
 	__bounce_end_io_read(bio, isa_page_pool, err);
 }
@@ -181,32 +185,13 @@ static void bounce_end_io_read_isa(struct bio *bio, int err)
 #ifdef CONFIG_NEED_BOUNCE_POOL
 static int must_snapshot_stable_pages(struct request_queue *q, struct bio *bio)
 {
-	struct page *page;
-	struct backing_dev_info *bdi;
-	struct address_space *mapping;
-	struct bio_vec *from;
-	int i;
-
 	if (bio_data_dir(bio) != WRITE)
 		return 0;
 
 	if (!bdi_cap_stable_pages_required(&q->backing_dev_info))
 		return 0;
 
-	/*
-	 * Based on the first page that has a valid mapping, decide whether or
-	 * not we have to employ bounce buffering to guarantee stable pages.
-	 */
-	bio_for_each_segment(from, bio, i) {
-		page = from->bv_page;
-		mapping = page_mapping(page);
-		if (!mapping)
-			continue;
-		bdi = mapping->backing_dev_info;
-		return mapping->host->i_sb->s_flags & MS_SNAP_STABLE;
-	}
-
-	return 0;
+	return test_bit(BIO_SNAP_STABLE, &bio->bi_flags);
 }
 #else
 static int must_snapshot_stable_pages(struct request_queue *q, struct bio *bio)
@@ -218,78 +203,43 @@ static int must_snapshot_stable_pages(struct request_queue *q, struct bio *bio)
 static void __blk_queue_bounce(struct request_queue *q, struct bio **bio_orig,
 			       mempool_t *pool, int force)
 {
-	struct page *page;
-	struct bio *bio = NULL;
-	int i, rw = bio_data_dir(*bio_orig);
+	struct bio *bio;
+	int rw = bio_data_dir(*bio_orig);
 	struct bio_vec *to, *from;
+	unsigned i;
 
-	bio_for_each_segment(from, *bio_orig, i) {
-		page = from->bv_page;
+	bio_for_each_segment(from, *bio_orig, i)
+		if (page_to_pfn(from->bv_page) > queue_bounce_pfn(q))
+			goto bounce;
 
-		/*
-		 * is destination page below bounce pfn?
-		 */
-		if (page_to_pfn(page) <= queue_bounce_pfn(q) && !force)
-			continue;
+	return;
+bounce:
+	bio = bio_clone_bioset(*bio_orig, GFP_NOIO, fs_bio_set);
 
-		/*
-		 * irk, bounce it
-		 */
-		if (!bio) {
-			unsigned int cnt = (*bio_orig)->bi_vcnt;
-
-			bio = bio_alloc(GFP_NOIO, cnt);
-			memset(bio->bi_io_vec, 0, cnt * sizeof(struct bio_vec));
-		}
-			
+	bio_for_each_segment_all(to, bio, i) {
+		struct page *page = to->bv_page;
 
-		to = bio->bi_io_vec + i;
+		if (page_to_pfn(page) <= queue_bounce_pfn(q) && !force)
+			continue;
 
-		to->bv_page = mempool_alloc(pool, q->bounce_gfp);
-		to->bv_len = from->bv_len;
-		to->bv_offset = from->bv_offset;
 		inc_zone_page_state(to->bv_page, NR_BOUNCE);
+		to->bv_page = mempool_alloc(pool, q->bounce_gfp);
 
 		if (rw == WRITE) {
 			char *vto, *vfrom;
 
-			flush_dcache_page(from->bv_page);
+			flush_dcache_page(page);
+
 			vto = page_address(to->bv_page) + to->bv_offset;
-			vfrom = kmap(from->bv_page) + from->bv_offset;
+			vfrom = kmap_atomic(page) + to->bv_offset;
 			memcpy(vto, vfrom, to->bv_len);
-			kunmap(from->bv_page);
+			kunmap_atomic(vfrom);
 		}
 	}
 
-	/*
-	 * no pages bounced
-	 */
-	if (!bio)
-		return;
-
 	trace_block_bio_bounce(q, *bio_orig);
 
-	/*
-	 * at least one page was bounced, fill in possible non-highmem
-	 * pages
-	 */
-	__bio_for_each_segment(from, *bio_orig, i, 0) {
-		to = bio_iovec_idx(bio, i);
-		if (!to->bv_page) {
-			to->bv_page = from->bv_page;
-			to->bv_len = from->bv_len;
-			to->bv_offset = from->bv_offset;
-		}
-	}
-
-	bio->bi_bdev = (*bio_orig)->bi_bdev;
 	bio->bi_flags |= (1 << BIO_BOUNCED);
-	bio->bi_sector = (*bio_orig)->bi_sector;
-	bio->bi_rw = (*bio_orig)->bi_rw;
-
-	bio->bi_vcnt = (*bio_orig)->bi_vcnt;
-	bio->bi_idx = (*bio_orig)->bi_idx;
-	bio->bi_size = (*bio_orig)->bi_size;
 
 	if (pool == page_pool) {
 		bio->bi_end_io = bounce_end_io_write;
diff --git a/mm/cleancache.c b/mm/cleancache.c
index d76ba74..5875f48 100644
--- a/mm/cleancache.c
+++ b/mm/cleancache.c
@@ -19,20 +19,10 @@
 #include <linux/cleancache.h>
 
 /*
- * This global enablement flag may be read thousands of times per second
- * by cleancache_get/put/invalidate even on systems where cleancache_ops
- * is not claimed (e.g. cleancache is config'ed on but remains
- * disabled), so is preferred to the slower alternative: a function
- * call that checks a non-global.
- */
-int cleancache_enabled __read_mostly;
-EXPORT_SYMBOL(cleancache_enabled);
-
-/*
  * cleancache_ops is set by cleancache_ops_register to contain the pointers
  * to the cleancache "backend" implementation functions.
  */
-static struct cleancache_ops cleancache_ops __read_mostly;
+static struct cleancache_ops *cleancache_ops __read_mostly;
 
 /*
  * Counters available via /sys/kernel/debug/frontswap (if debugfs is
@@ -45,15 +35,101 @@ static u64 cleancache_puts;
 static u64 cleancache_invalidates;
 
 /*
- * register operations for cleancache, returning previous thus allowing
- * detection of multiple backends and possible nesting
+ * When no backend is registered all calls to init_fs and init_shared_fs
+ * are registered and fake poolids (FAKE_FS_POOLID_OFFSET or
+ * FAKE_SHARED_FS_POOLID_OFFSET, plus offset in the respective array
+ * [shared_|]fs_poolid_map) are given to the respective super block
+ * (sb->cleancache_poolid) and no tmem_pools are created. When a backend
+ * registers with cleancache the previous calls to init_fs and init_shared_fs
+ * are executed to create tmem_pools and set the respective poolids. While no
+ * backend is registered all "puts", "gets" and "flushes" are ignored or failed.
+ */
+#define MAX_INITIALIZABLE_FS 32
+#define FAKE_FS_POOLID_OFFSET 1000
+#define FAKE_SHARED_FS_POOLID_OFFSET 2000
+
+#define FS_NO_BACKEND (-1)
+#define FS_UNKNOWN (-2)
+static int fs_poolid_map[MAX_INITIALIZABLE_FS];
+static int shared_fs_poolid_map[MAX_INITIALIZABLE_FS];
+static char *uuids[MAX_INITIALIZABLE_FS];
+/*
+ * Mutex for the [shared_|]fs_poolid_map to guard against multiple threads
+ * invoking umount (and ending in __cleancache_invalidate_fs) and also multiple
+ * threads calling mount (and ending up in __cleancache_init_[shared|]fs).
+ */
+static DEFINE_MUTEX(poolid_mutex);
+/*
+ * When set to false (default) all calls to the cleancache functions, except
+ * the __cleancache_invalidate_fs and __cleancache_init_[shared|]fs are guarded
+ * by the if (!cleancache_ops) return. This means multiple threads (from
+ * different filesystems) will be checking cleancache_ops. The usage of a
+ * bool instead of a atomic_t or a bool guarded by a spinlock is OK - we are
+ * OK if the time between the backend's have been initialized (and
+ * cleancache_ops has been set to not NULL) and when the filesystems start
+ * actually calling the backends. The inverse (when unloading) is obviously
+ * not good - but this shim does not do that (yet).
+ */
+
+/*
+ * The backends and filesystems work all asynchronously. This is b/c the
+ * backends can be built as modules.
+ * The usual sequence of events is:
+ *	a) mount /	-> __cleancache_init_fs is called. We set the
+ *		[shared_|]fs_poolid_map and uuids for.
+ *
+ *	b). user does I/Os -> we call the rest of __cleancache_* functions
+ *		which return immediately as cleancache_ops is false.
+ *
+ *	c). modprobe zcache -> cleancache_register_ops. We init the backend
+ *		and set cleancache_ops to true, and for any fs_poolid_map
+ *		(which is set by __cleancache_init_fs) we initialize the poolid.
+ *
+ *	d). user does I/Os -> now that cleancache_ops is true all the
+ *		__cleancache_* functions can call the backend. They all check
+ *		that fs_poolid_map is valid and if so invoke the backend.
+ *
+ *	e). umount /	-> __cleancache_invalidate_fs, the fs_poolid_map is
+ *		reset (which is the second check in the __cleancache_* ops
+ *		to call the backend).
+ *
+ * The sequence of event could also be c), followed by a), and d). and e). The
+ * c) would not happen anymore. There is also the chance of c), and one thread
+ * doing a) + d), and another doing e). For that case we depend on the
+ * filesystem calling __cleancache_invalidate_fs in the proper sequence (so
+ * that it handles all I/Os before it invalidates the fs (which is last part
+ * of unmounting process).
+ *
+ * Note: The acute reader will notice that there is no "rmmod zcache" case.
+ * This is b/c the functionality for that is not yet implemented and when
+ * done, will require some extra locking not yet devised.
+ */
+
+/*
+ * Register operations for cleancache, returning previous thus allowing
+ * detection of multiple backends and possible nesting.
  */
-struct cleancache_ops cleancache_register_ops(struct cleancache_ops *ops)
+struct cleancache_ops *cleancache_register_ops(struct cleancache_ops *ops)
 {
-	struct cleancache_ops old = cleancache_ops;
+	struct cleancache_ops *old = cleancache_ops;
+	int i;
 
-	cleancache_ops = *ops;
-	cleancache_enabled = 1;
+	mutex_lock(&poolid_mutex);
+	for (i = 0; i < MAX_INITIALIZABLE_FS; i++) {
+		if (fs_poolid_map[i] == FS_NO_BACKEND)
+			fs_poolid_map[i] = ops->init_fs(PAGE_SIZE);
+		if (shared_fs_poolid_map[i] == FS_NO_BACKEND)
+			shared_fs_poolid_map[i] = ops->init_shared_fs
+					(uuids[i], PAGE_SIZE);
+	}
+	/*
+	 * We MUST set cleancache_ops _after_ we have called the backends
+	 * init_fs or init_shared_fs functions. Otherwise the compiler might
+	 * re-order where cleancache_ops is set in this function.
+	 */
+	barrier();
+	cleancache_ops = ops;
+	mutex_unlock(&poolid_mutex);
 	return old;
 }
 EXPORT_SYMBOL(cleancache_register_ops);
@@ -61,15 +137,42 @@ EXPORT_SYMBOL(cleancache_register_ops);
 /* Called by a cleancache-enabled filesystem at time of mount */
 void __cleancache_init_fs(struct super_block *sb)
 {
-	sb->cleancache_poolid = (*cleancache_ops.init_fs)(PAGE_SIZE);
+	int i;
+
+	mutex_lock(&poolid_mutex);
+	for (i = 0; i < MAX_INITIALIZABLE_FS; i++) {
+		if (fs_poolid_map[i] == FS_UNKNOWN) {
+			sb->cleancache_poolid = i + FAKE_FS_POOLID_OFFSET;
+			if (cleancache_ops)
+				fs_poolid_map[i] = cleancache_ops->init_fs(PAGE_SIZE);
+			else
+				fs_poolid_map[i] = FS_NO_BACKEND;
+			break;
+		}
+	}
+	mutex_unlock(&poolid_mutex);
 }
 EXPORT_SYMBOL(__cleancache_init_fs);
 
 /* Called by a cleancache-enabled clustered filesystem at time of mount */
 void __cleancache_init_shared_fs(char *uuid, struct super_block *sb)
 {
-	sb->cleancache_poolid =
-		(*cleancache_ops.init_shared_fs)(uuid, PAGE_SIZE);
+	int i;
+
+	mutex_lock(&poolid_mutex);
+	for (i = 0; i < MAX_INITIALIZABLE_FS; i++) {
+		if (shared_fs_poolid_map[i] == FS_UNKNOWN) {
+			sb->cleancache_poolid = i + FAKE_SHARED_FS_POOLID_OFFSET;
+			uuids[i] = uuid;
+			if (cleancache_ops)
+				shared_fs_poolid_map[i] = cleancache_ops->init_shared_fs
+						(uuid, PAGE_SIZE);
+			else
+				shared_fs_poolid_map[i] = FS_NO_BACKEND;
+			break;
+		}
+	}
+	mutex_unlock(&poolid_mutex);
 }
 EXPORT_SYMBOL(__cleancache_init_shared_fs);
 
@@ -99,27 +202,53 @@ static int cleancache_get_key(struct inode *inode,
 }
 
 /*
+ * Returns a pool_id that is associated with a given fake poolid.
+ */
+static int get_poolid_from_fake(int fake_pool_id)
+{
+	if (fake_pool_id >= FAKE_SHARED_FS_POOLID_OFFSET)
+		return shared_fs_poolid_map[fake_pool_id -
+			FAKE_SHARED_FS_POOLID_OFFSET];
+	else if (fake_pool_id >= FAKE_FS_POOLID_OFFSET)
+		return fs_poolid_map[fake_pool_id - FAKE_FS_POOLID_OFFSET];
+	return FS_NO_BACKEND;
+}
+
+/*
  * "Get" data from cleancache associated with the poolid/inode/index
  * that were specified when the data was put to cleanache and, if
  * successful, use it to fill the specified page with data and return 0.
  * The pageframe is unchanged and returns -1 if the get fails.
  * Page must be locked by caller.
+ *
+ * The function has two checks before any action is taken - whether
+ * a backend is registered and whether the sb->cleancache_poolid
+ * is correct.
  */
 int __cleancache_get_page(struct page *page)
 {
 	int ret = -1;
 	int pool_id;
+	int fake_pool_id;
 	struct cleancache_filekey key = { .u.key = { 0 } };
 
+	if (!cleancache_ops) {
+		cleancache_failed_gets++;
+		goto out;
+	}
+
 	VM_BUG_ON(!PageLocked(page));
-	pool_id = page->mapping->host->i_sb->cleancache_poolid;
-	if (pool_id < 0)
+	fake_pool_id = page->mapping->host->i_sb->cleancache_poolid;
+	if (fake_pool_id < 0)
 		goto out;
+	pool_id = get_poolid_from_fake(fake_pool_id);
 
 	if (cleancache_get_key(page->mapping->host, &key) < 0)
 		goto out;
 
-	ret = (*cleancache_ops.get_page)(pool_id, key, page->index, page);
+	if (pool_id >= 0)
+		ret = cleancache_ops->get_page(pool_id,
+				key, page->index, page);
 	if (ret == 0)
 		cleancache_succ_gets++;
 	else
@@ -134,17 +263,32 @@ EXPORT_SYMBOL(__cleancache_get_page);
  * (previously-obtained per-filesystem) poolid and the page's,
  * inode and page index.  Page must be locked.  Note that a put_page
  * always "succeeds", though a subsequent get_page may succeed or fail.
+ *
+ * The function has two checks before any action is taken - whether
+ * a backend is registered and whether the sb->cleancache_poolid
+ * is correct.
  */
 void __cleancache_put_page(struct page *page)
 {
 	int pool_id;
+	int fake_pool_id;
 	struct cleancache_filekey key = { .u.key = { 0 } };
 
+	if (!cleancache_ops) {
+		cleancache_puts++;
+		return;
+	}
+
 	VM_BUG_ON(!PageLocked(page));
-	pool_id = page->mapping->host->i_sb->cleancache_poolid;
+	fake_pool_id = page->mapping->host->i_sb->cleancache_poolid;
+	if (fake_pool_id < 0)
+		return;
+
+	pool_id = get_poolid_from_fake(fake_pool_id);
+
 	if (pool_id >= 0 &&
-	      cleancache_get_key(page->mapping->host, &key) >= 0) {
-		(*cleancache_ops.put_page)(pool_id, key, page->index, page);
+		cleancache_get_key(page->mapping->host, &key) >= 0) {
+		cleancache_ops->put_page(pool_id, key, page->index, page);
 		cleancache_puts++;
 	}
 }
@@ -153,19 +297,31 @@ EXPORT_SYMBOL(__cleancache_put_page);
 /*
  * Invalidate any data from cleancache associated with the poolid and the
  * page's inode and page index so that a subsequent "get" will fail.
+ *
+ * The function has two checks before any action is taken - whether
+ * a backend is registered and whether the sb->cleancache_poolid
+ * is correct.
  */
 void __cleancache_invalidate_page(struct address_space *mapping,
 					struct page *page)
 {
 	/* careful... page->mapping is NULL sometimes when this is called */
-	int pool_id = mapping->host->i_sb->cleancache_poolid;
+	int pool_id;
+	int fake_pool_id = mapping->host->i_sb->cleancache_poolid;
 	struct cleancache_filekey key = { .u.key = { 0 } };
 
-	if (pool_id >= 0) {
+	if (!cleancache_ops)
+		return;
+
+	if (fake_pool_id >= 0) {
+		pool_id = get_poolid_from_fake(fake_pool_id);
+		if (pool_id < 0)
+			return;
+
 		VM_BUG_ON(!PageLocked(page));
 		if (cleancache_get_key(mapping->host, &key) >= 0) {
-			(*cleancache_ops.invalidate_page)(pool_id,
-							  key, page->index);
+			cleancache_ops->invalidate_page(pool_id,
+					key, page->index);
 			cleancache_invalidates++;
 		}
 	}
@@ -176,34 +332,63 @@ EXPORT_SYMBOL(__cleancache_invalidate_page);
  * Invalidate all data from cleancache associated with the poolid and the
  * mappings's inode so that all subsequent gets to this poolid/inode
  * will fail.
+ *
+ * The function has two checks before any action is taken - whether
+ * a backend is registered and whether the sb->cleancache_poolid
+ * is correct.
  */
 void __cleancache_invalidate_inode(struct address_space *mapping)
 {
-	int pool_id = mapping->host->i_sb->cleancache_poolid;
+	int pool_id;
+	int fake_pool_id = mapping->host->i_sb->cleancache_poolid;
 	struct cleancache_filekey key = { .u.key = { 0 } };
 
+	if (!cleancache_ops)
+		return;
+
+	if (fake_pool_id < 0)
+		return;
+
+	pool_id = get_poolid_from_fake(fake_pool_id);
+
 	if (pool_id >= 0 && cleancache_get_key(mapping->host, &key) >= 0)
-		(*cleancache_ops.invalidate_inode)(pool_id, key);
+		cleancache_ops->invalidate_inode(pool_id, key);
 }
 EXPORT_SYMBOL(__cleancache_invalidate_inode);
 
 /*
  * Called by any cleancache-enabled filesystem at time of unmount;
- * note that pool_id is surrendered and may be reutrned by a subsequent
- * cleancache_init_fs or cleancache_init_shared_fs
+ * note that pool_id is surrendered and may be returned by a subsequent
+ * cleancache_init_fs or cleancache_init_shared_fs.
  */
 void __cleancache_invalidate_fs(struct super_block *sb)
 {
-	if (sb->cleancache_poolid >= 0) {
-		int old_poolid = sb->cleancache_poolid;
-		sb->cleancache_poolid = -1;
-		(*cleancache_ops.invalidate_fs)(old_poolid);
+	int index;
+	int fake_pool_id = sb->cleancache_poolid;
+	int old_poolid = fake_pool_id;
+
+	mutex_lock(&poolid_mutex);
+	if (fake_pool_id >= FAKE_SHARED_FS_POOLID_OFFSET) {
+		index = fake_pool_id - FAKE_SHARED_FS_POOLID_OFFSET;
+		old_poolid = shared_fs_poolid_map[index];
+		shared_fs_poolid_map[index] = FS_UNKNOWN;
+		uuids[index] = NULL;
+	} else if (fake_pool_id >= FAKE_FS_POOLID_OFFSET) {
+		index = fake_pool_id - FAKE_FS_POOLID_OFFSET;
+		old_poolid = fs_poolid_map[index];
+		fs_poolid_map[index] = FS_UNKNOWN;
 	}
+	sb->cleancache_poolid = -1;
+	if (cleancache_ops)
+		cleancache_ops->invalidate_fs(old_poolid);
+	mutex_unlock(&poolid_mutex);
 }
 EXPORT_SYMBOL(__cleancache_invalidate_fs);
 
 static int __init init_cleancache(void)
 {
+	int i;
+
 #ifdef CONFIG_DEBUG_FS
 	struct dentry *root = debugfs_create_dir("cleancache", NULL);
 	if (root == NULL)
@@ -215,6 +400,10 @@ static int __init init_cleancache(void)
 	debugfs_create_u64("invalidates", S_IRUGO,
 				root, &cleancache_invalidates);
 #endif
+	for (i = 0; i < MAX_INITIALIZABLE_FS; i++) {
+		fs_poolid_map[i] = FS_UNKNOWN;
+		shared_fs_poolid_map[i] = FS_UNKNOWN;
+	}
 	return 0;
 }
 module_init(init_cleancache)
diff --git a/mm/dmapool.c b/mm/dmapool.c
index c69781e..668f263 100644
--- a/mm/dmapool.c
+++ b/mm/dmapool.c
@@ -132,6 +132,7 @@ struct dma_pool *dma_pool_create(const char *name, struct device *dev,
 {
 	struct dma_pool *retval;
 	size_t allocation;
+	int node;
 
 	if (align == 0) {
 		align = 1;
@@ -156,7 +157,9 @@ struct dma_pool *dma_pool_create(const char *name, struct device *dev,
 		return NULL;
 	}
 
-	retval = kmalloc_node(sizeof(*retval), GFP_KERNEL, dev_to_node(dev));
+	node = WARN_ON(!dev) ? -1 : dev_to_node(dev);
+
+	retval = kmalloc_node(sizeof(*retval), GFP_KERNEL, node);
 	if (!retval)
 		return retval;
 
diff --git a/mm/fadvise.c b/mm/fadvise.c
index 7e09268..3bcfd81 100644
--- a/mm/fadvise.c
+++ b/mm/fadvise.c
@@ -25,7 +25,7 @@
  * POSIX_FADV_WILLNEED could set PG_Referenced, and POSIX_FADV_NOREUSE could
  * deactivate the pages and clear PG_Referenced.
  */
-SYSCALL_DEFINE(fadvise64_64)(int fd, loff_t offset, loff_t len, int advice)
+SYSCALL_DEFINE4(fadvise64_64, int, fd, loff_t, offset, loff_t, len, int, advice)
 {
 	struct fd f = fdget(fd);
 	struct address_space *mapping;
@@ -145,26 +145,12 @@ out:
 	fdput(f);
 	return ret;
 }
-#ifdef CONFIG_HAVE_SYSCALL_WRAPPERS
-asmlinkage long SyS_fadvise64_64(long fd, loff_t offset, loff_t len, long advice)
-{
-	return SYSC_fadvise64_64((int) fd, offset, len, (int) advice);
-}
-SYSCALL_ALIAS(sys_fadvise64_64, SyS_fadvise64_64);
-#endif
 
 #ifdef __ARCH_WANT_SYS_FADVISE64
 
-SYSCALL_DEFINE(fadvise64)(int fd, loff_t offset, size_t len, int advice)
+SYSCALL_DEFINE4(fadvise64, int, fd, loff_t, offset, size_t, len, int, advice)
 {
 	return sys_fadvise64_64(fd, offset, len, advice);
 }
-#ifdef CONFIG_HAVE_SYSCALL_WRAPPERS
-asmlinkage long SyS_fadvise64(long fd, loff_t offset, long len, long advice)
-{
-	return SYSC_fadvise64((int) fd, offset, (size_t)len, (int)advice);
-}
-SYSCALL_ALIAS(sys_fadvise64, SyS_fadvise64);
-#endif
 
 #endif
diff --git a/mm/filemap.c b/mm/filemap.c
index e1979fd..80590c5 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -35,6 +35,9 @@
 #include <linux/cleancache.h>
 #include "internal.h"
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/filemap.h>
+
 /*
  * FIXME: remove all knowledge of the buffer layer from the core VM
  */
@@ -113,6 +116,7 @@ void __delete_from_page_cache(struct page *page)
 {
 	struct address_space *mapping = page->mapping;
 
+	trace_mm_filemap_delete_from_page_cache(page);
 	/*
 	 * if we're uptodate, flush out into the cleancache, otherwise
 	 * invalidate any existing cleancache entries.  We can't leave
@@ -464,6 +468,7 @@ int add_to_page_cache_locked(struct page *page, struct address_space *mapping,
 			mapping->nrpages++;
 			__inc_zone_page_state(page, NR_FILE_PAGES);
 			spin_unlock_irq(&mapping->tree_lock);
+			trace_mm_filemap_add_to_page_cache(page);
 		} else {
 			page->mapping = NULL;
 			/* Leave page->index set: truncation relies upon it */
@@ -2528,7 +2533,6 @@ ssize_t generic_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
 
 	BUG_ON(iocb->ki_pos != pos);
 
-	sb_start_write(inode->i_sb);
 	mutex_lock(&inode->i_mutex);
 	ret = __generic_file_aio_write(iocb, iov, nr_segs, &iocb->ki_pos);
 	mutex_unlock(&inode->i_mutex);
@@ -2540,7 +2544,6 @@ ssize_t generic_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
 		if (err < 0 && ret > 0)
 			ret = err;
 	}
-	sb_end_write(inode->i_sb);
 	return ret;
 }
 EXPORT_SYMBOL(generic_file_aio_write);
diff --git a/mm/filemap_xip.c b/mm/filemap_xip.c
index a912da6..28fe26b 100644
--- a/mm/filemap_xip.c
+++ b/mm/filemap_xip.c
@@ -404,8 +404,6 @@ xip_file_write(struct file *filp, const char __user *buf, size_t len,
 	loff_t pos;
 	ssize_t ret;
 
-	sb_start_write(inode->i_sb);
-
 	mutex_lock(&inode->i_mutex);
 
 	if (!access_ok(VERIFY_READ, buf, len)) {
@@ -439,7 +437,6 @@ xip_file_write(struct file *filp, const char __user *buf, size_t len,
 	current->backing_dev_info = NULL;
  out_up:
 	mutex_unlock(&inode->i_mutex);
-	sb_end_write(inode->i_sb);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(xip_file_write);
diff --git a/mm/frontswap.c b/mm/frontswap.c
index 2890e67..538367e 100644
--- a/mm/frontswap.c
+++ b/mm/frontswap.c
@@ -24,15 +24,7 @@
  * frontswap_ops is set by frontswap_register_ops to contain the pointers
  * to the frontswap "backend" implementation functions.
  */
-static struct frontswap_ops frontswap_ops __read_mostly;
-
-/*
- * This global enablement flag reduces overhead on systems where frontswap_ops
- * has not been registered, so is preferred to the slower alternative: a
- * function call that checks a non-global.
- */
-bool frontswap_enabled __read_mostly;
-EXPORT_SYMBOL(frontswap_enabled);
+static struct frontswap_ops *frontswap_ops __read_mostly;
 
 /*
  * If enabled, frontswap_store will return failure even on success.  As
@@ -80,16 +72,70 @@ static inline void inc_frontswap_succ_stores(void) { }
 static inline void inc_frontswap_failed_stores(void) { }
 static inline void inc_frontswap_invalidates(void) { }
 #endif
+
+/*
+ * Due to the asynchronous nature of the backends loading potentially
+ * _after_ the swap system has been activated, we have chokepoints
+ * on all frontswap functions to not call the backend until the backend
+ * has registered.
+ *
+ * Specifically when no backend is registered (nobody called
+ * frontswap_register_ops) all calls to frontswap_init (which is done via
+ * swapon -> enable_swap_info -> frontswap_init) are registered and remembered
+ * (via the setting of need_init bitmap) but fail to create tmem_pools. When a
+ * backend registers with frontswap at some later point the previous
+ * calls to frontswap_init are executed (by iterating over the need_init
+ * bitmap) to create tmem_pools and set the respective poolids. All of that is
+ * guarded by us using atomic bit operations on the 'need_init' bitmap.
+ *
+ * This would not guards us against the user deciding to call swapoff right as
+ * we are calling the backend to initialize (so swapon is in action).
+ * Fortunatly for us, the swapon_mutex has been taked by the callee so we are
+ * OK. The other scenario where calls to frontswap_store (called via
+ * swap_writepage) is racing with frontswap_invalidate_area (called via
+ * swapoff) is again guarded by the swap subsystem.
+ *
+ * While no backend is registered all calls to frontswap_[store|load|
+ * invalidate_area|invalidate_page] are ignored or fail.
+ *
+ * The time between the backend being registered and the swap file system
+ * calling the backend (via the frontswap_* functions) is indeterminate as
+ * frontswap_ops is not atomic_t (or a value guarded by a spinlock).
+ * That is OK as we are comfortable missing some of these calls to the newly
+ * registered backend.
+ *
+ * Obviously the opposite (unloading the backend) must be done after all
+ * the frontswap_[store|load|invalidate_area|invalidate_page] start
+ * ignorning or failing the requests - at which point frontswap_ops
+ * would have to be made in some fashion atomic.
+ */
+static DECLARE_BITMAP(need_init, MAX_SWAPFILES);
+
 /*
  * Register operations for frontswap, returning previous thus allowing
  * detection of multiple backends and possible nesting.
  */
-struct frontswap_ops frontswap_register_ops(struct frontswap_ops *ops)
+struct frontswap_ops *frontswap_register_ops(struct frontswap_ops *ops)
 {
-	struct frontswap_ops old = frontswap_ops;
-
-	frontswap_ops = *ops;
-	frontswap_enabled = true;
+	struct frontswap_ops *old = frontswap_ops;
+	int i;
+
+	for (i = 0; i < MAX_SWAPFILES; i++) {
+		if (test_and_clear_bit(i, need_init)) {
+			struct swap_info_struct *sis = swap_info[i];
+			/* __frontswap_init _should_ have set it! */
+			if (!sis->frontswap_map)
+				return ERR_PTR(-EINVAL);
+			ops->init(i);
+		}
+	}
+	/*
+	 * We MUST have frontswap_ops set _after_ the frontswap_init's
+	 * have been called. Otherwise __frontswap_store might fail. Hence
+	 * the barrier to make sure compiler does not re-order us.
+	 */
+	barrier();
+	frontswap_ops = ops;
 	return old;
 }
 EXPORT_SYMBOL(frontswap_register_ops);
@@ -115,20 +161,48 @@ EXPORT_SYMBOL(frontswap_tmem_exclusive_gets);
 /*
  * Called when a swap device is swapon'd.
  */
-void __frontswap_init(unsigned type)
+void __frontswap_init(unsigned type, unsigned long *map)
 {
 	struct swap_info_struct *sis = swap_info[type];
 
 	BUG_ON(sis == NULL);
-	if (sis->frontswap_map == NULL)
+
+	/*
+	 * p->frontswap is a bitmap that we MUST have to figure out which page
+	 * has gone in frontswap. Without it there is no point of continuing.
+	 */
+	if (WARN_ON(!map))
 		return;
-	frontswap_ops.init(type);
+	/*
+	 * Irregardless of whether the frontswap backend has been loaded
+	 * before this function or it will be later, we _MUST_ have the
+	 * p->frontswap set to something valid to work properly.
+	 */
+	frontswap_map_set(sis, map);
+	if (frontswap_ops)
+		frontswap_ops->init(type);
+	else {
+		BUG_ON(type > MAX_SWAPFILES);
+		set_bit(type, need_init);
+	}
 }
 EXPORT_SYMBOL(__frontswap_init);
 
-static inline void __frontswap_clear(struct swap_info_struct *sis, pgoff_t offset)
+bool __frontswap_test(struct swap_info_struct *sis,
+				pgoff_t offset)
+{
+	bool ret = false;
+
+	if (frontswap_ops && sis->frontswap_map)
+		ret = test_bit(offset, sis->frontswap_map);
+	return ret;
+}
+EXPORT_SYMBOL(__frontswap_test);
+
+static inline void __frontswap_clear(struct swap_info_struct *sis,
+				pgoff_t offset)
 {
-	frontswap_clear(sis, offset);
+	clear_bit(offset, sis->frontswap_map);
 	atomic_dec(&sis->frontswap_pages);
 }
 
@@ -147,13 +221,20 @@ int __frontswap_store(struct page *page)
 	struct swap_info_struct *sis = swap_info[type];
 	pgoff_t offset = swp_offset(entry);
 
+	/*
+	 * Return if no backend registed.
+	 * Don't need to inc frontswap_failed_stores here.
+	 */
+	if (!frontswap_ops)
+		return ret;
+
 	BUG_ON(!PageLocked(page));
 	BUG_ON(sis == NULL);
-	if (frontswap_test(sis, offset))
+	if (__frontswap_test(sis, offset))
 		dup = 1;
-	ret = frontswap_ops.store(type, offset, page);
+	ret = frontswap_ops->store(type, offset, page);
 	if (ret == 0) {
-		frontswap_set(sis, offset);
+		set_bit(offset, sis->frontswap_map);
 		inc_frontswap_succ_stores();
 		if (!dup)
 			atomic_inc(&sis->frontswap_pages);
@@ -188,13 +269,16 @@ int __frontswap_load(struct page *page)
 
 	BUG_ON(!PageLocked(page));
 	BUG_ON(sis == NULL);
-	if (frontswap_test(sis, offset))
-		ret = frontswap_ops.load(type, offset, page);
+	/*
+	 * __frontswap_test() will check whether there is backend registered
+	 */
+	if (__frontswap_test(sis, offset))
+		ret = frontswap_ops->load(type, offset, page);
 	if (ret == 0) {
 		inc_frontswap_loads();
 		if (frontswap_tmem_exclusive_gets_enabled) {
 			SetPageDirty(page);
-			frontswap_clear(sis, offset);
+			__frontswap_clear(sis, offset);
 		}
 	}
 	return ret;
@@ -210,8 +294,11 @@ void __frontswap_invalidate_page(unsigned type, pgoff_t offset)
 	struct swap_info_struct *sis = swap_info[type];
 
 	BUG_ON(sis == NULL);
-	if (frontswap_test(sis, offset)) {
-		frontswap_ops.invalidate_page(type, offset);
+	/*
+	 * __frontswap_test() will check whether there is backend registered
+	 */
+	if (__frontswap_test(sis, offset)) {
+		frontswap_ops->invalidate_page(type, offset);
 		__frontswap_clear(sis, offset);
 		inc_frontswap_invalidates();
 	}
@@ -226,12 +313,15 @@ void __frontswap_invalidate_area(unsigned type)
 {
 	struct swap_info_struct *sis = swap_info[type];
 
-	BUG_ON(sis == NULL);
-	if (sis->frontswap_map == NULL)
-		return;
-	frontswap_ops.invalidate_area(type);
-	atomic_set(&sis->frontswap_pages, 0);
-	memset(sis->frontswap_map, 0, sis->max / sizeof(long));
+	if (frontswap_ops) {
+		BUG_ON(sis == NULL);
+		if (sis->frontswap_map == NULL)
+			return;
+		frontswap_ops->invalidate_area(type);
+		atomic_set(&sis->frontswap_pages, 0);
+		memset(sis->frontswap_map, 0, sis->max / sizeof(long));
+	}
+	clear_bit(type, need_init);
 }
 EXPORT_SYMBOL(__frontswap_invalidate_area);
 
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index ca9a7c6..bacdf38 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -1761,7 +1761,7 @@ static struct hstate *kobj_to_node_hstate(struct kobject *kobj, int *nidp)
  * Unregister hstate attributes from a single node device.
  * No-op if no hstate attributes attached.
  */
-void hugetlb_unregister_node(struct node *node)
+static void hugetlb_unregister_node(struct node *node)
 {
 	struct hstate *h;
 	struct node_hstate *nhs = &node_hstates[node->dev.id];
@@ -1805,7 +1805,7 @@ static void hugetlb_unregister_all_nodes(void)
  * Register hstate attributes for a single node device.
  * No-op if attributes already registered.
  */
-void hugetlb_register_node(struct node *node)
+static void hugetlb_register_node(struct node *node)
 {
 	struct hstate *h;
 	struct node_hstate *nhs = &node_hstates[node->dev.id];
@@ -2121,6 +2121,21 @@ int hugetlb_report_node_meminfo(int nid, char *buf)
 		nid, h->surplus_huge_pages_node[nid]);
 }
 
+void hugetlb_show_meminfo(void)
+{
+	struct hstate *h;
+	int nid;
+
+	for_each_node_state(nid, N_MEMORY)
+		for_each_hstate(h)
+			pr_info("Node %d hugepages_total=%u hugepages_free=%u hugepages_surp=%u hugepages_size=%lukB\n",
+				nid,
+				h->nr_huge_pages_node[nid],
+				h->free_huge_pages_node[nid],
+				h->surplus_huge_pages_node[nid],
+				1UL << (huge_page_order(h) + PAGE_SHIFT - 10));
+}
+
 /* Return the number pages of memory we physically have, in PAGE_SIZE units. */
 unsigned long hugetlb_total_pages(void)
 {
@@ -2247,10 +2262,11 @@ static pte_t make_huge_pte(struct vm_area_struct *vma, struct page *page,
 	pte_t entry;
 
 	if (writable) {
-		entry =
-		    pte_mkwrite(pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
+		entry = huge_pte_mkwrite(huge_pte_mkdirty(mk_huge_pte(page,
+					 vma->vm_page_prot)));
 	} else {
-		entry = huge_pte_wrprotect(mk_pte(page, vma->vm_page_prot));
+		entry = huge_pte_wrprotect(mk_huge_pte(page,
+					   vma->vm_page_prot));
 	}
 	entry = pte_mkyoung(entry);
 	entry = pte_mkhuge(entry);
@@ -2264,7 +2280,7 @@ static void set_huge_ptep_writable(struct vm_area_struct *vma,
 {
 	pte_t entry;
 
-	entry = pte_mkwrite(pte_mkdirty(huge_ptep_get(ptep)));
+	entry = huge_pte_mkwrite(huge_pte_mkdirty(huge_ptep_get(ptep)));
 	if (huge_ptep_set_access_flags(vma, address, ptep, entry, 1))
 		update_mmu_cache(vma, address, ptep);
 }
@@ -2379,7 +2395,7 @@ again:
 		 * HWPoisoned hugepage is already unmapped and dropped reference
 		 */
 		if (unlikely(is_hugetlb_entry_hwpoisoned(pte))) {
-			pte_clear(mm, address, ptep);
+			huge_pte_clear(mm, address, ptep);
 			continue;
 		}
 
@@ -2403,7 +2419,7 @@ again:
 
 		pte = huge_ptep_get_and_clear(mm, address, ptep);
 		tlb_remove_tlb_entry(tlb, ptep, address);
-		if (pte_dirty(pte))
+		if (huge_pte_dirty(pte))
 			set_page_dirty(page);
 
 		page_remove_rmap(page);
@@ -2856,7 +2872,7 @@ int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,
 	 * page now as it is used to determine if a reservation has been
 	 * consumed.
 	 */
-	if ((flags & FAULT_FLAG_WRITE) && !pte_write(entry)) {
+	if ((flags & FAULT_FLAG_WRITE) && !huge_pte_write(entry)) {
 		if (vma_needs_reservation(h, vma, address) < 0) {
 			ret = VM_FAULT_OOM;
 			goto out_mutex;
@@ -2886,12 +2902,12 @@ int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,
 
 
 	if (flags & FAULT_FLAG_WRITE) {
-		if (!pte_write(entry)) {
+		if (!huge_pte_write(entry)) {
 			ret = hugetlb_cow(mm, vma, address, ptep, entry,
 							pagecache_page);
 			goto out_page_table_lock;
 		}
-		entry = pte_mkdirty(entry);
+		entry = huge_pte_mkdirty(entry);
 	}
 	entry = pte_mkyoung(entry);
 	if (huge_ptep_set_access_flags(vma, address, ptep, entry,
@@ -2962,7 +2978,7 @@ long follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
 		}
 
 		if (absent ||
-		    ((flags & FOLL_WRITE) && !pte_write(huge_ptep_get(pte)))) {
+		    ((flags & FOLL_WRITE) && !huge_pte_write(huge_ptep_get(pte)))) {
 			int ret;
 
 			spin_unlock(&mm->page_table_lock);
@@ -3032,7 +3048,7 @@ unsigned long hugetlb_change_protection(struct vm_area_struct *vma,
 		}
 		if (!huge_pte_none(huge_ptep_get(ptep))) {
 			pte = huge_ptep_get_and_clear(mm, address, ptep);
-			pte = pte_mkhuge(pte_modify(pte, newprot));
+			pte = pte_mkhuge(huge_pte_modify(pte, newprot));
 			pte = arch_make_huge_pte(pte, vma, NULL, 0);
 			set_huge_pte_at(mm, address, ptep, pte);
 			pages++;
diff --git a/mm/memblock.c b/mm/memblock.c
index b8d9147..2cce8b3 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -771,6 +771,9 @@ static phys_addr_t __init memblock_alloc_base_nid(phys_addr_t size,
 {
 	phys_addr_t found;
 
+	if (WARN_ON(!align))
+		align = __alignof__(long long);
+
 	/* align @size to avoid excessive fragmentation on reserved array */
 	size = round_up(size, align);
 
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 2b55222..f608546 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -152,8 +152,13 @@ struct mem_cgroup_stat_cpu {
 };
 
 struct mem_cgroup_reclaim_iter {
-	/* css_id of the last scanned hierarchy member */
-	int position;
+	/*
+	 * last scanned hierarchy member. Valid only if last_dead_count
+	 * matches memcg->dead_count of the hierarchy root group.
+	 */
+	struct mem_cgroup *last_visited;
+	unsigned long last_dead_count;
+
 	/* scan generation, increased every round-trip */
 	unsigned int generation;
 };
@@ -310,14 +315,31 @@ struct mem_cgroup {
 	/* thresholds for mem+swap usage. RCU-protected */
 	struct mem_cgroup_thresholds memsw_thresholds;
 
-	/* For oom notifier event fd */
-	struct list_head oom_notify;
+	union {
+		/* For oom notifier event fd */
+		struct list_head oom_notify;
+		/*
+		 * we can only trigger an oom event if the memcg is alive.
+		 * so we will reuse this field to hook the memcg in the list
+		 * of dead memcgs.
+		 */
+		struct list_head dead;
+	};
 
-	/*
-	 * Should we move charges of a task when a task is moved into this
-	 * mem_cgroup ? And what type of charges should we move ?
-	 */
-	unsigned long 	move_charge_at_immigrate;
+	union {
+		/*
+		 * Should we move charges of a task when a task is moved into
+		 * this mem_cgroup ? And what type of charges should we move ?
+		 */
+		unsigned long move_charge_at_immigrate;
+
+		/*
+		 * We are no longer concerned about moving charges after memcg
+		 * is dead. So we will fill this up with its name, to aid
+		 * debugging.
+		 */
+		char *memcg_name;
+	};
 	/*
 	 * set > 0 if pages under this cgroup are moving to other cgroup.
 	 */
@@ -335,6 +357,7 @@ struct mem_cgroup {
 	struct mem_cgroup_stat_cpu nocpu_base;
 	spinlock_t pcp_counter_lock;
 
+	atomic_t	dead_count;
 #if defined(CONFIG_MEMCG_KMEM) && defined(CONFIG_INET)
 	struct tcp_memcontrol tcp_mem;
 #endif
@@ -369,6 +392,55 @@ static size_t memcg_size(void)
 		nr_node_ids * sizeof(struct mem_cgroup_per_node);
 }
 
+#ifdef CONFIG_MEMCG_DEBUG_ASYNC_DESTROY
+static LIST_HEAD(dangling_memcgs);
+static DEFINE_MUTEX(dangling_memcgs_mutex);
+
+static inline void memcg_dangling_free(struct mem_cgroup *memcg)
+{
+	mutex_lock(&dangling_memcgs_mutex);
+	list_del(&memcg->dead);
+	mutex_unlock(&dangling_memcgs_mutex);
+	free_pages((unsigned long)memcg->memcg_name, 0);
+}
+
+static inline void memcg_dangling_add(struct mem_cgroup *memcg)
+{
+	/*
+	 * cgroup.c will do page-sized allocations most of the time,
+	 * so we'll just follow the pattern. Also, __get_free_pages
+	 * is a better interface than kmalloc for us here, because
+	 * we'd like this memory to be always billed to the root cgroup,
+	 * not to the process removing the memcg. While kmalloc would
+	 * require us to wrap it into memcg_stop/resume_kmem_account,
+	 * with __get_free_pages we just don't pass the memcg flag.
+	 */
+	memcg->memcg_name = (char *)__get_free_pages(GFP_KERNEL, 0);
+
+	/*
+	 * we will, in general, just ignore failures. No need to go crazy,
+	 * being this just a debugging interface. It is nice to copy a memcg
+	 * name over, but if we (unlikely) can't, just the address will do
+	 */
+	if (!memcg->memcg_name)
+		goto add_list;
+
+	if (cgroup_path(memcg->css.cgroup, memcg->memcg_name, PAGE_SIZE) < 0) {
+		free_pages((unsigned long)memcg->memcg_name, 0);
+		memcg->memcg_name = NULL;
+	}
+
+add_list:
+	INIT_LIST_HEAD(&memcg->dead);
+	mutex_lock(&dangling_memcgs_mutex);
+	list_add(&memcg->dead, &dangling_memcgs);
+	mutex_unlock(&dangling_memcgs_mutex);
+}
+#else
+static inline void memcg_dangling_free(struct mem_cgroup *memcg) {}
+static inline void memcg_dangling_add(struct mem_cgroup *memcg) {}
+#endif
+
 /* internal only representation about the status of kmem accounting. */
 enum {
 	KMEM_ACCOUNTED_ACTIVE = 0, /* accounted by this cgroup itself */
@@ -1067,6 +1139,51 @@ struct mem_cgroup *try_get_mem_cgroup_from_mm(struct mm_struct *mm)
 	return memcg;
 }
 
+/*
+ * Returns a next (in a pre-order walk) alive memcg (with elevated css
+ * ref. count) or NULL if the whole root's subtree has been visited.
+ *
+ * helper function to be used by mem_cgroup_iter
+ */
+static struct mem_cgroup *__mem_cgroup_iter_next(struct mem_cgroup *root,
+		struct mem_cgroup *last_visited)
+{
+	struct cgroup *prev_cgroup, *next_cgroup;
+
+	/*
+	 * Root is not visited by cgroup iterators so it needs an
+	 * explicit visit.
+	 */
+	if (!last_visited)
+		return root;
+
+	prev_cgroup = (last_visited == root) ? NULL
+		: last_visited->css.cgroup;
+skip_node:
+	next_cgroup = cgroup_next_descendant_pre(
+			prev_cgroup, root->css.cgroup);
+
+	/*
+	 * Even if we found a group we have to make sure it is
+	 * alive. css && !memcg means that the groups should be
+	 * skipped and we should continue the tree walk.
+	 * last_visited css is safe to use because it is
+	 * protected by css_get and the tree walk is rcu safe.
+	 */
+	if (next_cgroup) {
+		struct mem_cgroup *mem = mem_cgroup_from_cont(
+				next_cgroup);
+		if (css_tryget(&mem->css))
+			return mem;
+		else {
+			prev_cgroup = next_cgroup;
+			goto skip_node;
+		}
+	}
+
+	return NULL;
+}
+
 /**
  * mem_cgroup_iter - iterate over memory cgroup hierarchy
  * @root: hierarchy root
@@ -1089,7 +1206,8 @@ struct mem_cgroup *mem_cgroup_iter(struct mem_cgroup *root,
 				   struct mem_cgroup_reclaim_cookie *reclaim)
 {
 	struct mem_cgroup *memcg = NULL;
-	int id = 0;
+	struct mem_cgroup *last_visited = NULL;
+	unsigned long uninitialized_var(dead_count);
 
 	if (mem_cgroup_disabled())
 		return NULL;
@@ -1098,20 +1216,17 @@ struct mem_cgroup *mem_cgroup_iter(struct mem_cgroup *root,
 		root = root_mem_cgroup;
 
 	if (prev && !reclaim)
-		id = css_id(&prev->css);
-
-	if (prev && prev != root)
-		css_put(&prev->css);
+		last_visited = prev;
 
 	if (!root->use_hierarchy && root != root_mem_cgroup) {
 		if (prev)
-			return NULL;
+			goto out_css_put;
 		return root;
 	}
 
+	rcu_read_lock();
 	while (!memcg) {
 		struct mem_cgroup_reclaim_iter *uninitialized_var(iter);
-		struct cgroup_subsys_state *css;
 
 		if (reclaim) {
 			int nid = zone_to_nid(reclaim->zone);
@@ -1120,31 +1235,60 @@ struct mem_cgroup *mem_cgroup_iter(struct mem_cgroup *root,
 
 			mz = mem_cgroup_zoneinfo(root, nid, zid);
 			iter = &mz->reclaim_iter[reclaim->priority];
-			if (prev && reclaim->generation != iter->generation)
-				return NULL;
-			id = iter->position;
+			last_visited = iter->last_visited;
+			if (prev && reclaim->generation != iter->generation) {
+				iter->last_visited = NULL;
+				goto out_unlock;
+			}
+
+			/*
+			 * If the dead_count mismatches, a destruction
+			 * has happened or is happening concurrently.
+			 * If the dead_count matches, a destruction
+			 * might still happen concurrently, but since
+			 * we checked under RCU, that destruction
+			 * won't free the object until we release the
+			 * RCU reader lock.  Thus, the dead_count
+			 * check verifies the pointer is still valid,
+			 * css_tryget() verifies the cgroup pointed to
+			 * is alive.
+			 */
+			dead_count = atomic_read(&root->dead_count);
+			smp_rmb();
+			last_visited = iter->last_visited;
+			if (last_visited) {
+				if ((dead_count != iter->last_dead_count) ||
+					!css_tryget(&last_visited->css)) {
+					last_visited = NULL;
+				}
+			}
 		}
 
-		rcu_read_lock();
-		css = css_get_next(&mem_cgroup_subsys, id + 1, &root->css, &id);
-		if (css) {
-			if (css == &root->css || css_tryget(css))
-				memcg = mem_cgroup_from_css(css);
-		} else
-			id = 0;
-		rcu_read_unlock();
+		memcg = __mem_cgroup_iter_next(root, last_visited);
 
 		if (reclaim) {
-			iter->position = id;
-			if (!css)
+			if (last_visited)
+				css_put(&last_visited->css);
+
+			iter->last_visited = memcg;
+			smp_wmb();
+			iter->last_dead_count = dead_count;
+
+			if (!memcg)
 				iter->generation++;
 			else if (!prev && memcg)
 				reclaim->generation = iter->generation;
 		}
 
-		if (prev && !css)
-			return NULL;
+		if (prev && !memcg)
+			goto out_unlock;
 	}
+out_unlock:
+	rcu_read_unlock();
+out_css_put:
+	if (prev && prev != root)
+		css_put(&prev->css);
+
 	return memcg;
 }
 
@@ -4947,9 +5091,6 @@ static ssize_t mem_cgroup_read(struct cgroup *cont, struct cftype *cft,
 	type = MEMFILE_TYPE(cft->private);
 	name = MEMFILE_ATTR(cft->private);
 
-	if (!do_swap_account && type == _MEMSWAP)
-		return -EOPNOTSUPP;
-
 	switch (type) {
 	case _MEM:
 		if (name == RES_USAGE)
@@ -4974,6 +5115,107 @@ static ssize_t mem_cgroup_read(struct cgroup *cont, struct cftype *cft,
 	return simple_read_from_buffer(buf, nbytes, ppos, str, len);
 }
 
+#ifdef CONFIG_MEMCG_DEBUG_ASYNC_DESTROY
+static void
+mem_cgroup_dangling_swap(struct mem_cgroup *memcg, struct seq_file *m)
+{
+#ifdef CONFIG_MEMCG_SWAP
+	u64 kmem;
+	u64 memsw;
+
+	/*
+	 * kmem will also propagate here, so we are only interested in the
+	 * difference.  See comment in mem_cgroup_reparent_charges for details.
+	 *
+	 * We could save this value for later consumption by kmem reports, but
+	 * there is not a lot of problem if the figures differ slightly.
+	 */
+	kmem = res_counter_read_u64(&memcg->kmem, RES_USAGE);
+	memsw = res_counter_read_u64(&memcg->memsw, RES_USAGE) - kmem;
+	seq_printf(m, "\t%llu swap bytes\n", memsw);
+#endif
+}
+
+
+static void
+mem_cgroup_dangling_tcp(struct mem_cgroup *memcg, struct seq_file *m)
+{
+#if defined(CONFIG_INET) && defined(CONFIG_MEMCG_KMEM)
+	struct tcp_memcontrol *tcp = &memcg->tcp_mem;
+	s64 tcp_socks;
+	u64 tcp_bytes;
+
+	tcp_socks = percpu_counter_sum_positive(&tcp->tcp_sockets_allocated);
+	tcp_bytes = res_counter_read_u64(&tcp->tcp_memory_allocated, RES_USAGE);
+	seq_printf(m, "\t%llu tcp bytes", tcp_bytes);
+	/*
+	 * if tcp_bytes == 0, tcp_socks != 0 is a bug. One more reason to print
+	 * it!
+	 */
+	if (tcp_bytes || tcp_socks)
+		seq_printf(m, ", in %lld sockets", tcp_socks);
+	seq_printf(m, "\n");
+
+#endif
+}
+
+static void
+mem_cgroup_dangling_kmem(struct mem_cgroup *memcg, struct seq_file *m)
+{
+#ifdef CONFIG_MEMCG_KMEM
+	u64 kmem;
+	struct memcg_cache_params *params;
+
+	kmem = res_counter_read_u64(&memcg->kmem, RES_USAGE);
+	seq_printf(m, "\t%llu kmem bytes", kmem);
+
+	/* list below may not be initialized, so not even try */
+	if (!kmem)
+		return;
+
+	seq_printf(m, " in caches");
+	mutex_lock(&memcg->slab_caches_mutex);
+	list_for_each_entry(params, &memcg->memcg_slab_caches, list) {
+			struct kmem_cache *s = memcg_params_to_cache(params);
+
+		seq_printf(m, " %s", s->name);
+	}
+	mutex_unlock(&memcg->slab_caches_mutex);
+	seq_printf(m, "\n");
+#endif
+}
+
+/*
+ * After a memcg is destroyed, it may still be kept around in memory.
+ * Currently, the two main reasons for it are swap entries, and kernel memory.
+ * Because they will be freed assynchronously, they will pin the memcg structure
+ * and its resources until the last reference goes away.
+ *
+ * This root-only file will show information about which users
+ */
+static int mem_cgroup_dangling_read(struct cgroup *cont, struct cftype *cft,
+					struct seq_file *m)
+{
+	struct mem_cgroup *memcg;
+
+	mutex_lock(&dangling_memcgs_mutex);
+
+	list_for_each_entry(memcg, &dangling_memcgs, dead) {
+		if (memcg->memcg_name)
+			seq_printf(m, "%s:\n", memcg->memcg_name);
+		else
+			seq_printf(m, "%p (name lost):\n", memcg);
+
+		mem_cgroup_dangling_swap(memcg, m);
+		mem_cgroup_dangling_tcp(memcg, m);
+		mem_cgroup_dangling_kmem(memcg, m);
+	}
+
+	mutex_unlock(&dangling_memcgs_mutex);
+	return 0;
+}
+#endif
+
 static int memcg_update_kmem_limit(struct cgroup *cont, u64 val)
 {
 	int ret = -EINVAL;
@@ -5084,9 +5326,6 @@ static int mem_cgroup_write(struct cgroup *cont, struct cftype *cft,
 	type = MEMFILE_TYPE(cft->private);
 	name = MEMFILE_ATTR(cft->private);
 
-	if (!do_swap_account && type == _MEMSWAP)
-		return -EOPNOTSUPP;
-
 	switch (name) {
 	case RES_LIMIT:
 		if (mem_cgroup_is_root(memcg)) { /* Can't set limit on root */
@@ -5163,9 +5402,6 @@ static int mem_cgroup_reset(struct cgroup *cont, unsigned int event)
 	type = MEMFILE_TYPE(event);
 	name = MEMFILE_ATTR(event);
 
-	if (!do_swap_account && type == _MEMSWAP)
-		return -EOPNOTSUPP;
-
 	switch (name) {
 	case RES_MAX_USAGE:
 		if (type == _MEM)
@@ -5875,6 +6111,14 @@ static struct cftype mem_cgroup_files[] = {
 	},
 #endif
 #endif
+
+#ifdef CONFIG_MEMCG_DEBUG_ASYNC_DESTROY
+	{
+		.name = "dangling_memcgs",
+		.read_seq_string = mem_cgroup_dangling_read,
+		.flags = CFTYPE_ONLY_ON_ROOT,
+	},
+#endif
 	{ },	/* terminate */
 };
 
@@ -6024,6 +6268,8 @@ static void free_work(struct work_struct *work)
 	struct mem_cgroup *memcg;
 
 	memcg = container_of(work, struct mem_cgroup, work_freeing);
+
+	memcg_dangling_free(memcg);
 	__mem_cgroup_free(memcg);
 }
 
@@ -6184,10 +6430,29 @@ mem_cgroup_css_online(struct cgroup *cont)
 	return error;
 }
 
+/*
+ * Announce all parents that a group from their hierarchy is gone.
+ */
+static void mem_cgroup_invalidate_reclaim_iterators(struct mem_cgroup *memcg)
+{
+	struct mem_cgroup *parent = memcg;
+
+	while ((parent = parent_mem_cgroup(parent)))
+		atomic_inc(&parent->dead_count);
+
+	/*
+	 * if the root memcg is not hierarchical we have to check it
+	 * explicitely.
+	 */
+	if (!root_mem_cgroup->use_hierarchy)
+		atomic_inc(&root_mem_cgroup->dead_count);
+}
+
 static void mem_cgroup_css_offline(struct cgroup *cont)
 {
 	struct mem_cgroup *memcg = mem_cgroup_from_cont(cont);
 
+	mem_cgroup_invalidate_reclaim_iterators(memcg);
 	mem_cgroup_reparent_charges(memcg);
 	mem_cgroup_destroy_all_caches(memcg);
 }
@@ -6198,6 +6463,7 @@ static void mem_cgroup_css_free(struct cgroup *cont)
 
 	kmem_cgroup_destroy(memcg);
 
+	memcg_dangling_add(memcg);
 	mem_cgroup_put(memcg);
 }
 
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index df0694c..ceb0c7f 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -785,10 +785,10 @@ static struct page_state {
 	{ sc|dirty,	sc,		"clean swapcache",	me_swapcache_clean },
 
 	{ mlock|dirty,	mlock|dirty,	"dirty mlocked LRU",	me_pagecache_dirty },
-	{ mlock,	mlock,		"clean mlocked LRU",	me_pagecache_clean },
+	{ mlock|dirty,	mlock,		"clean mlocked LRU",	me_pagecache_clean },
 
 	{ unevict|dirty, unevict|dirty,	"dirty unevictable LRU", me_pagecache_dirty },
-	{ unevict,	unevict,	"clean unevictable LRU", me_pagecache_clean },
+	{ unevict|dirty, unevict,	"clean unevictable LRU", me_pagecache_clean },
 
 	{ lru|dirty,	lru|dirty,	"dirty LRU",	me_pagecache_dirty },
 	{ lru|dirty,	lru,		"clean LRU",	me_pagecache_clean },
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index ee37657..57decb2 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -1613,7 +1613,7 @@ int offline_pages(unsigned long start_pfn, unsigned long nr_pages)
 /**
  * walk_memory_range - walks through all mem sections in [start_pfn, end_pfn)
  * @start_pfn: start pfn of the memory range
- * @end_pfn: end pft of the memory range
+ * @end_pfn: end pfn of the memory range
  * @arg: argument passed to func
  * @func: callback for each memory section walked
  *
diff --git a/mm/migrate.c b/mm/migrate.c
index 3bbaf5d..6fa4ebc 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -736,7 +736,7 @@ static int __unmap_and_move(struct page *page, struct page *newpage,
 
 	if (PageWriteback(page)) {
 		/*
-		 * Only in the case of a full syncronous migration is it
+		 * Only in the case of a full synchronous migration is it
 		 * necessary to wait for PageWriteback. In the async case,
 		 * the retry loop is too short and in the sync-light case,
 		 * the overhead of stalling is too much
@@ -876,6 +876,7 @@ static int unmap_and_move(new_page_t get_new_page, unsigned long private,
 		dec_zone_page_state(page, NR_ISOLATED_ANON +
 				    page_is_file_cache(page));
 		balloon_page_free(page);
+		balloon_event_count(COMPACTBALLOONMIGRATED);
 		return MIGRATEPAGE_SUCCESS;
 	}
 out:
diff --git a/mm/mmap.c b/mm/mmap.c
index 6466699..11f91cf 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -829,7 +829,7 @@ again:			remove_next = 1 + (end > next->vm_end);
 		if (next->anon_vma)
 			anon_vma_merge(vma, next);
 		mm->map_count--;
-		mpol_put(vma_policy(next));
+		vma_set_policy(vma, vma_policy(next));
 		kmem_cache_free(vm_area_cachep, next);
 		/*
 		 * In mprotect's case 6 (see comments on vma_merge),
@@ -1818,15 +1818,6 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
 }
 #endif	
 
-void arch_unmap_area(struct mm_struct *mm, unsigned long addr)
-{
-	/*
-	 * Is this a new hole at the lowest possible address?
-	 */
-	if (addr >= TASK_UNMAPPED_BASE && addr < mm->free_area_cache)
-		mm->free_area_cache = addr;
-}
-
 /*
  * This mmap-allocator allocates new areas top-down from below the
  * stack's low limit (the base):
@@ -1883,19 +1874,6 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
 }
 #endif
 
-void arch_unmap_area_topdown(struct mm_struct *mm, unsigned long addr)
-{
-	/*
-	 * Is this a new hole at the highest possible address?
-	 */
-	if (addr > mm->free_area_cache)
-		mm->free_area_cache = addr;
-
-	/* dont allow allocations above current base */
-	if (mm->free_area_cache > mm->mmap_base)
-		mm->free_area_cache = mm->mmap_base;
-}
-
 unsigned long
 get_unmapped_area(struct file *file, unsigned long addr, unsigned long len,
 		unsigned long pgoff, unsigned long flags)
@@ -1935,12 +1913,9 @@ struct vm_area_struct *find_vma(struct mm_struct *mm, unsigned long addr)
 {
 	struct vm_area_struct *vma = NULL;
 
-	if (WARN_ON_ONCE(!mm))		/* Remove this in linux-3.6 */
-		return NULL;
-
 	/* Check the cache first. */
 	/* (Cache hit rate is typically around 35%.) */
-	vma = mm->mmap_cache;
+	vma = ACCESS_ONCE(mm->mmap_cache);
 	if (!(vma && vma->vm_end > addr && vma->vm_start <= addr)) {
 		struct rb_node *rb_node;
 
@@ -2305,7 +2280,7 @@ static void unmap_region(struct mm_struct *mm,
 	update_hiwater_rss(mm);
 	unmap_vmas(&tlb, vma, start, end);
 	free_pgtables(&tlb, vma, prev ? prev->vm_end : FIRST_USER_ADDRESS,
-				 next ? next->vm_start : 0);
+				 next ? next->vm_start : USER_PGTABLES_CEILING);
 	tlb_finish_mmu(&tlb, start, end);
 }
 
@@ -2319,7 +2294,6 @@ detach_vmas_to_be_unmapped(struct mm_struct *mm, struct vm_area_struct *vma,
 {
 	struct vm_area_struct **insertion_point;
 	struct vm_area_struct *tail_vma = NULL;
-	unsigned long addr;
 
 	insertion_point = (prev ? &prev->vm_next : &mm->mmap);
 	vma->vm_prev = NULL;
@@ -2336,11 +2310,6 @@ detach_vmas_to_be_unmapped(struct mm_struct *mm, struct vm_area_struct *vma,
 	} else
 		mm->highest_vm_end = prev ? prev->vm_end : 0;
 	tail_vma->vm_next = NULL;
-	if (mm->unmap_area == arch_unmap_area)
-		addr = prev ? prev->vm_end : mm->mmap_base;
-	else
-		addr = vma ?  vma->vm_start : mm->mmap_base;
-	mm->unmap_area(mm, addr);
 	mm->mmap_cache = NULL;		/* Kill the cache. */
 }
 
@@ -2685,7 +2654,7 @@ void exit_mmap(struct mm_struct *mm)
 	/* Use -1 here to ensure all VMAs in the mm are unmapped */
 	unmap_vmas(&tlb, vma, 0, -1);
 
-	free_pgtables(&tlb, vma, FIRST_USER_ADDRESS, 0);
+	free_pgtables(&tlb, vma, FIRST_USER_ADDRESS, USER_PGTABLES_CEILING);
 	tlb_finish_mmu(&tlb, 0, -1);
 
 	/*
diff --git a/mm/mmu_context.c b/mm/mmu_context.c
index 3dcfaf4..8a8cd02 100644
--- a/mm/mmu_context.c
+++ b/mm/mmu_context.c
@@ -14,9 +14,6 @@
  * use_mm
  *	Makes the calling kernel thread take on the specified
  *	mm context.
- *	Called by the retry thread execute retries within the
- *	iocb issuer's mm context, so that copy_from/to_user
- *	operations work seamlessly for aio.
  *	(Note: this routine is intended to be called only
  *	from a kernel thread context)
  */
diff --git a/mm/nommu.c b/mm/nommu.c
index e193280..80cb04d 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -228,8 +228,7 @@ int follow_pfn(struct vm_area_struct *vma, unsigned long address,
 }
 EXPORT_SYMBOL(follow_pfn);
 
-DEFINE_RWLOCK(vmlist_lock);
-struct vm_struct *vmlist;
+LIST_HEAD(vmap_area_list);
 
 void vfree(const void *addr)
 {
@@ -821,7 +820,7 @@ struct vm_area_struct *find_vma(struct mm_struct *mm, unsigned long addr)
 	struct vm_area_struct *vma;
 
 	/* check the cache first */
-	vma = mm->mmap_cache;
+	vma = ACCESS_ONCE(mm->mmap_cache);
 	if (vma && vma->vm_start <= addr && vma->vm_end > addr)
 		return vma;
 
@@ -1770,7 +1769,7 @@ unsigned long vm_brk(unsigned long addr, unsigned long len)
  *
  * MREMAP_FIXED is not supported under NOMMU conditions
  */
-unsigned long do_mremap(unsigned long addr,
+static unsigned long do_mremap(unsigned long addr,
 			unsigned long old_len, unsigned long new_len,
 			unsigned long flags, unsigned long new_addr)
 {
@@ -1805,7 +1804,6 @@ unsigned long do_mremap(unsigned long addr,
 	vma->vm_end = vma->vm_start + new_len;
 	return vma->vm_start;
 }
-EXPORT_SYMBOL(do_mremap);
 
 SYSCALL_DEFINE5(mremap, unsigned long, addr, unsigned long, old_len,
 		unsigned long, new_len, unsigned long, flags,
@@ -1859,10 +1857,6 @@ unsigned long arch_get_unmapped_area(struct file *file, unsigned long addr,
 	return -ENOMEM;
 }
 
-void arch_unmap_area(struct mm_struct *mm, unsigned long addr)
-{
-}
-
 void unmap_mapping_range(struct address_space *mapping,
 			 loff_t const holebegin, loff_t const holelen,
 			 int even_cows)
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index efe6814..4514ad7 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -2311,10 +2311,6 @@ void wait_for_stable_page(struct page *page)
 
 	if (!bdi_cap_stable_pages_required(bdi))
 		return;
-#ifdef CONFIG_NEED_BOUNCE_POOL
-	if (mapping->host->i_sb->s_flags & MS_SNAP_STABLE)
-		return;
-#endif /* CONFIG_NEED_BOUNCE_POOL */
 
 	wait_on_page_writeback(page);
 }
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 8fcced7..1394c5a 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -58,6 +58,7 @@
 #include <linux/prefetch.h>
 #include <linux/migrate.h>
 #include <linux/page-debug-flags.h>
+#include <linux/hugetlb.h>
 #include <linux/sched/rt.h>
 
 #include <asm/tlbflush.h>
@@ -1397,6 +1398,7 @@ void split_page(struct page *page, unsigned int order)
 	for (i = 1; i < (1 << order); i++)
 		set_page_refcounted(page + i);
 }
+EXPORT_SYMBOL_GPL(split_page);
 
 static int __isolate_free_page(struct page *page, unsigned int order)
 {
@@ -1940,9 +1942,24 @@ zonelist_scan:
 				continue;
 			default:
 				/* did we reclaim enough */
-				if (!zone_watermark_ok(zone, order, mark,
+				if (zone_watermark_ok(zone, order, mark,
 						classzone_idx, alloc_flags))
+					goto try_this_zone;
+
+				/*
+				 * Failed to reclaim enough to meet watermark.
+				 * Only mark the zone full if checking the min
+				 * watermark or if we failed to reclaim just
+				 * 1<<order pages or else the page allocator
+				 * fastpath will prematurely mark zones full
+				 * when the watermark is between the low and
+				 * min watermarks.
+				 */
+				if ((alloc_flags & ALLOC_WMARK_MIN) ||
+				    ret == ZONE_RECLAIM_SOME)
 					goto this_zone_full;
+
+				continue;
 			}
 		}
 
@@ -2002,6 +2019,13 @@ void warn_alloc_failed(gfp_t gfp_mask, int order, const char *fmt, ...)
 		return;
 
 	/*
+	 * Walking all memory to count page types is very expensive and should
+	 * be inhibited in non-blockable contexts.
+	 */
+	if (!(gfp_mask & __GFP_WAIT))
+		filter |= SHOW_MEM_FILTER_PAGE_COUNT;
+
+	/*
 	 * This documents exceptions given to allocations in certain
 	 * contexts that are allowed to allocate outside current's set
 	 * of allowed nodes.
@@ -3105,6 +3129,8 @@ void show_free_areas(unsigned int filter)
 		printk("= %lukB\n", K(total));
 	}
 
+	hugetlb_show_meminfo();
+
 	printk("%ld total pagecache pages\n", global_page_state(NR_FILE_PAGES));
 
 	show_swap_cache_info();
@@ -3900,8 +3926,11 @@ void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone,
 		 * exist on hotplugged memory.
 		 */
 		if (context == MEMMAP_EARLY) {
-			if (!early_pfn_valid(pfn))
+			if (!early_pfn_valid(pfn)) {
+				pfn = ALIGN(pfn + MAX_ORDER_NR_PAGES,
+						MAX_ORDER_NR_PAGES) - 1;
 				continue;
+			}
 			if (!early_pfn_in_nid(pfn, nid))
 				continue;
 		}
@@ -4161,10 +4190,23 @@ int __meminit __early_pfn_to_nid(unsigned long pfn)
 {
 	unsigned long start_pfn, end_pfn;
 	int i, nid;
+	/*
+	 * NOTE: The following SMP-unsafe globals are only used early in boot
+	 * when the kernel is running single-threaded.
+	 */
+	static unsigned long __meminitdata last_start_pfn, last_end_pfn;
+	static int __meminitdata last_nid;
+
+	if (last_start_pfn <= pfn && pfn < last_end_pfn)
+		return last_nid;
 
 	for_each_mem_pfn_range(i, MAX_NUMNODES, &start_pfn, &end_pfn, &nid)
-		if (start_pfn <= pfn && pfn < end_pfn)
+		if (start_pfn <= pfn && pfn < end_pfn) {
+			last_start_pfn = start_pfn;
+			last_end_pfn = end_pfn;
+			last_nid = nid;
 			return nid;
+		}
 	/* This is a memory hole */
 	return -1;
 }
@@ -4710,7 +4752,7 @@ void __paginginit free_area_init_node(int nid, unsigned long *zones_size,
 /*
  * Figure out the number of possible node ids.
  */
-static void __init setup_nr_node_ids(void)
+void __init setup_nr_node_ids(void)
 {
 	unsigned int node;
 	unsigned int highest = 0;
@@ -4719,10 +4761,6 @@ static void __init setup_nr_node_ids(void)
 		highest = node;
 	nr_node_ids = highest + 1;
 }
-#else
-static inline void setup_nr_node_ids(void)
-{
-}
 #endif
 
 /**
@@ -5113,6 +5151,35 @@ early_param("movablecore", cmdline_parse_movablecore);
 
 #endif /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */
 
+unsigned long free_reserved_area(unsigned long start, unsigned long end,
+				 int poison, char *s)
+{
+	unsigned long pages, pos;
+
+	pos = start = PAGE_ALIGN(start);
+	end &= PAGE_MASK;
+	for (pages = 0; pos < end; pos += PAGE_SIZE, pages++) {
+		if (poison)
+			memset((void *)pos, poison, PAGE_SIZE);
+		free_reserved_page(virt_to_page(pos));
+	}
+
+	if (pages && s)
+		pr_info("Freeing %s memory: %ldK (%lx - %lx)\n",
+			s, pages << (PAGE_SHIFT - 10), start, end);
+
+	return pages;
+}
+
+#ifdef	CONFIG_HIGHMEM
+void free_highmem_page(struct page *page)
+{
+	__free_reserved_page(page);
+	totalram_pages++;
+	totalhigh_pages++;
+}
+#endif
+
 /**
  * set_dma_reserve - set the specified number of pages reserved in the first zone
  * @new_dma_reserve: The number of pages to mark reserved
diff --git a/mm/page_io.c b/mm/page_io.c
index 78eee32..7c55979 100644
--- a/mm/page_io.c
+++ b/mm/page_io.c
@@ -20,6 +20,7 @@
 #include <linux/buffer_head.h>
 #include <linux/writeback.h>
 #include <linux/frontswap.h>
+#include <linux/aio.h>
 #include <asm/pgtable.h>
 
 static struct bio *get_swap_bio(gfp_t gfp_flags,
@@ -35,14 +36,14 @@ static struct bio *get_swap_bio(gfp_t gfp_flags,
 		bio->bi_io_vec[0].bv_len = PAGE_SIZE;
 		bio->bi_io_vec[0].bv_offset = 0;
 		bio->bi_vcnt = 1;
-		bio->bi_idx = 0;
 		bio->bi_size = PAGE_SIZE;
 		bio->bi_end_io = end_io;
 	}
 	return bio;
 }
 
-static void end_swap_bio_write(struct bio *bio, int err)
+static void end_swap_bio_write(struct bio *bio, int err,
+			       struct batch_complete *batch)
 {
 	const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
 	struct page *page = bio->bi_io_vec[0].bv_page;
@@ -68,7 +69,7 @@ static void end_swap_bio_write(struct bio *bio, int err)
 	bio_put(bio);
 }
 
-void end_swap_bio_read(struct bio *bio, int err)
+void end_swap_bio_read(struct bio *bio, int err, struct batch_complete *batch)
 {
 	const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
 	struct page *page = bio->bi_io_vec[0].bv_page;
diff --git a/mm/readahead.c b/mm/readahead.c
index 7963f23..daed28d 100644
--- a/mm/readahead.c
+++ b/mm/readahead.c
@@ -576,7 +576,7 @@ do_readahead(struct address_space *mapping, struct file *filp,
 	return 0;
 }
 
-SYSCALL_DEFINE(readahead)(int fd, loff_t offset, size_t count)
+SYSCALL_DEFINE3(readahead, int, fd, loff_t, offset, size_t, count)
 {
 	ssize_t ret;
 	struct fd f;
@@ -595,10 +595,3 @@ SYSCALL_DEFINE(readahead)(int fd, loff_t offset, size_t count)
 	}
 	return ret;
 }
-#ifdef CONFIG_HAVE_SYSCALL_WRAPPERS
-asmlinkage long SyS_readahead(long fd, loff_t offset, long count)
-{
-	return SYSC_readahead((int) fd, offset, (size_t) count);
-}
-SYSCALL_ALIAS(sys_readahead, SyS_readahead);
-#endif
diff --git a/mm/rmap.c b/mm/rmap.c
index 807c96b..6280da8 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -1513,6 +1513,9 @@ static int try_to_unmap_file(struct page *page, enum ttu_flags flags)
 	unsigned long max_nl_size = 0;
 	unsigned int mapcount;
 
+	if (PageHuge(page))
+		pgoff = page->index << compound_order(page);
+
 	mutex_lock(&mapping->i_mmap_mutex);
 	vma_interval_tree_foreach(vma, &mapping->i_mmap, pgoff, pgoff) {
 		unsigned long address = vma_address(page, vma);
diff --git a/mm/shmem.c b/mm/shmem.c
index 1c44af7..5e6a842 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -25,11 +25,13 @@
 #include <linux/init.h>
 #include <linux/vfs.h>
 #include <linux/mount.h>
+#include <linux/ramfs.h>
 #include <linux/pagemap.h>
 #include <linux/file.h>
 #include <linux/mm.h>
 #include <linux/export.h>
 #include <linux/swap.h>
+#include <linux/aio.h>
 
 static struct vfsmount *shm_mnt;
 
@@ -2830,8 +2832,6 @@ out4:
  * effectively equivalent, but much lighter weight.
  */
 
-#include <linux/ramfs.h>
-
 static struct file_system_type shmem_fs_type = {
 	.name		= "tmpfs",
 	.mount		= ramfs_mount,
@@ -2931,11 +2931,9 @@ struct file *shmem_file_setup(const char *name, loff_t size, unsigned long flags
 	d_instantiate(path.dentry, inode);
 	inode->i_size = size;
 	clear_nlink(inode);	/* It is unlinked */
-#ifndef CONFIG_MMU
 	res = ERR_PTR(ramfs_nommu_expand_for_mapping(inode, size));
 	if (IS_ERR(res))
 		goto put_dentry;
-#endif
 
 	res = alloc_file(&path, FMODE_WRITE | FMODE_READ,
 		  &shmem_file_operations);
diff --git a/mm/slab.c b/mm/slab.c
index 856e4a1..69e0f1c 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -286,68 +286,27 @@ struct arraycache_init {
 };
 
 /*
- * The slab lists for all objects.
- */
-struct kmem_list3 {
-	struct list_head slabs_partial;	/* partial list first, better asm code */
-	struct list_head slabs_full;
-	struct list_head slabs_free;
-	unsigned long free_objects;
-	unsigned int free_limit;
-	unsigned int colour_next;	/* Per-node cache coloring */
-	spinlock_t list_lock;
-	struct array_cache *shared;	/* shared per node */
-	struct array_cache **alien;	/* on other nodes */
-	unsigned long next_reap;	/* updated without locking */
-	int free_touched;		/* updated without locking */
-};
-
-/*
  * Need this for bootstrapping a per node allocator.
  */
 #define NUM_INIT_LISTS (3 * MAX_NUMNODES)
-static struct kmem_list3 __initdata initkmem_list3[NUM_INIT_LISTS];
+static struct kmem_cache_node __initdata init_kmem_cache_node[NUM_INIT_LISTS];
 #define	CACHE_CACHE 0
 #define	SIZE_AC MAX_NUMNODES
-#define	SIZE_L3 (2 * MAX_NUMNODES)
+#define	SIZE_NODE (2 * MAX_NUMNODES)
 
 static int drain_freelist(struct kmem_cache *cache,
-			struct kmem_list3 *l3, int tofree);
+			struct kmem_cache_node *n, int tofree);
 static void free_block(struct kmem_cache *cachep, void **objpp, int len,
 			int node);
 static int enable_cpucache(struct kmem_cache *cachep, gfp_t gfp);
 static void cache_reap(struct work_struct *unused);
 
-/*
- * This function must be completely optimized away if a constant is passed to
- * it.  Mostly the same as what is in linux/slab.h except it returns an index.
- */
-static __always_inline int index_of(const size_t size)
-{
-	extern void __bad_size(void);
-
-	if (__builtin_constant_p(size)) {
-		int i = 0;
-
-#define CACHE(x) \
-	if (size <=x) \
-		return i; \
-	else \
-		i++;
-#include <linux/kmalloc_sizes.h>
-#undef CACHE
-		__bad_size();
-	} else
-		__bad_size();
-	return 0;
-}
-
 static int slab_early_init = 1;
 
-#define INDEX_AC index_of(sizeof(struct arraycache_init))
-#define INDEX_L3 index_of(sizeof(struct kmem_list3))
+#define INDEX_AC kmalloc_index(sizeof(struct arraycache_init))
+#define INDEX_NODE kmalloc_index(sizeof(struct kmem_cache_node))
 
-static void kmem_list3_init(struct kmem_list3 *parent)
+static void kmem_cache_node_init(struct kmem_cache_node *parent)
 {
 	INIT_LIST_HEAD(&parent->slabs_full);
 	INIT_LIST_HEAD(&parent->slabs_partial);
@@ -363,7 +322,7 @@ static void kmem_list3_init(struct kmem_list3 *parent)
 #define MAKE_LIST(cachep, listp, slab, nodeid)				\
 	do {								\
 		INIT_LIST_HEAD(listp);					\
-		list_splice(&(cachep->nodelists[nodeid]->slab), listp);	\
+		list_splice(&(cachep->node[nodeid]->slab), listp);	\
 	} while (0)
 
 #define	MAKE_ALL_LISTS(cachep, ptr, nodeid)				\
@@ -524,30 +483,6 @@ static inline unsigned int obj_to_index(const struct kmem_cache *cache,
 	return reciprocal_divide(offset, cache->reciprocal_buffer_size);
 }
 
-/*
- * These are the default caches for kmalloc. Custom caches can have other sizes.
- */
-struct cache_sizes malloc_sizes[] = {
-#define CACHE(x) { .cs_size = (x) },
-#include <linux/kmalloc_sizes.h>
-	CACHE(ULONG_MAX)
-#undef CACHE
-};
-EXPORT_SYMBOL(malloc_sizes);
-
-/* Must match cache_sizes above. Out of line to keep cache footprint low. */
-struct cache_names {
-	char *name;
-	char *name_dma;
-};
-
-static struct cache_names __initdata cache_names[] = {
-#define CACHE(x) { .name = "size-" #x, .name_dma = "size-" #x "(DMA)" },
-#include <linux/kmalloc_sizes.h>
-	{NULL,}
-#undef CACHE
-};
-
 static struct arraycache_init initarray_generic =
     { {0, BOOT_CPUCACHE_ENTRIES, 1, 0} };
 
@@ -586,15 +521,15 @@ static void slab_set_lock_classes(struct kmem_cache *cachep,
 		int q)
 {
 	struct array_cache **alc;
-	struct kmem_list3 *l3;
+	struct kmem_cache_node *n;
 	int r;
 
-	l3 = cachep->nodelists[q];
-	if (!l3)
+	n = cachep->node[q];
+	if (!n)
 		return;
 
-	lockdep_set_class(&l3->list_lock, l3_key);
-	alc = l3->alien;
+	lockdep_set_class(&n->list_lock, l3_key);
+	alc = n->alien;
 	/*
 	 * FIXME: This check for BAD_ALIEN_MAGIC
 	 * should go away when common slab code is taught to
@@ -625,28 +560,30 @@ static void slab_set_debugobj_lock_classes(struct kmem_cache *cachep)
 
 static void init_node_lock_keys(int q)
 {
-	struct cache_sizes *s = malloc_sizes;
+	int i;
 
 	if (slab_state < UP)
 		return;
 
-	for (s = malloc_sizes; s->cs_size != ULONG_MAX; s++) {
-		struct kmem_list3 *l3;
+	for (i = 1; i < PAGE_SHIFT + MAX_ORDER; i++) {
+		struct kmem_cache_node *n;
+		struct kmem_cache *cache = kmalloc_caches[i];
+
+		if (!cache)
+			continue;
 
-		l3 = s->cs_cachep->nodelists[q];
-		if (!l3 || OFF_SLAB(s->cs_cachep))
+		n = cache->node[q];
+		if (!n || OFF_SLAB(cache))
 			continue;
 
-		slab_set_lock_classes(s->cs_cachep, &on_slab_l3_key,
+		slab_set_lock_classes(cache, &on_slab_l3_key,
 				&on_slab_alc_key, q);
 	}
 }
 
 static void on_slab_lock_classes_node(struct kmem_cache *cachep, int q)
 {
-	struct kmem_list3 *l3;
-	l3 = cachep->nodelists[q];
-	if (!l3)
+	if (!cachep->node[q])
 		return;
 
 	slab_set_lock_classes(cachep, &on_slab_l3_key,
@@ -702,41 +639,6 @@ static inline struct array_cache *cpu_cache_get(struct kmem_cache *cachep)
 	return cachep->array[smp_processor_id()];
 }
 
-static inline struct kmem_cache *__find_general_cachep(size_t size,
-							gfp_t gfpflags)
-{
-	struct cache_sizes *csizep = malloc_sizes;
-
-#if DEBUG
-	/* This happens if someone tries to call
-	 * kmem_cache_create(), or __kmalloc(), before
-	 * the generic caches are initialized.
-	 */
-	BUG_ON(malloc_sizes[INDEX_AC].cs_cachep == NULL);
-#endif
-	if (!size)
-		return ZERO_SIZE_PTR;
-
-	while (size > csizep->cs_size)
-		csizep++;
-
-	/*
-	 * Really subtle: The last entry with cs->cs_size==ULONG_MAX
-	 * has cs_{dma,}cachep==NULL. Thus no special case
-	 * for large kmalloc calls required.
-	 */
-#ifdef CONFIG_ZONE_DMA
-	if (unlikely(gfpflags & GFP_DMA))
-		return csizep->cs_dmacachep;
-#endif
-	return csizep->cs_cachep;
-}
-
-static struct kmem_cache *kmem_find_general_cachep(size_t size, gfp_t gfpflags)
-{
-	return __find_general_cachep(size, gfpflags);
-}
-
 static size_t slab_mgmt_size(size_t nr_objs, size_t align)
 {
 	return ALIGN(sizeof(struct slab)+nr_objs*sizeof(kmem_bufctl_t), align);
@@ -938,29 +840,29 @@ static inline bool is_slab_pfmemalloc(struct slab *slabp)
 static void recheck_pfmemalloc_active(struct kmem_cache *cachep,
 						struct array_cache *ac)
 {
-	struct kmem_list3 *l3 = cachep->nodelists[numa_mem_id()];
+	struct kmem_cache_node *n = cachep->node[numa_mem_id()];
 	struct slab *slabp;
 	unsigned long flags;
 
 	if (!pfmemalloc_active)
 		return;
 
-	spin_lock_irqsave(&l3->list_lock, flags);
-	list_for_each_entry(slabp, &l3->slabs_full, list)
+	spin_lock_irqsave(&n->list_lock, flags);
+	list_for_each_entry(slabp, &n->slabs_full, list)
 		if (is_slab_pfmemalloc(slabp))
 			goto out;
 
-	list_for_each_entry(slabp, &l3->slabs_partial, list)
+	list_for_each_entry(slabp, &n->slabs_partial, list)
 		if (is_slab_pfmemalloc(slabp))
 			goto out;
 
-	list_for_each_entry(slabp, &l3->slabs_free, list)
+	list_for_each_entry(slabp, &n->slabs_free, list)
 		if (is_slab_pfmemalloc(slabp))
 			goto out;
 
 	pfmemalloc_active = false;
 out:
-	spin_unlock_irqrestore(&l3->list_lock, flags);
+	spin_unlock_irqrestore(&n->list_lock, flags);
 }
 
 static void *__ac_get_obj(struct kmem_cache *cachep, struct array_cache *ac,
@@ -971,7 +873,7 @@ static void *__ac_get_obj(struct kmem_cache *cachep, struct array_cache *ac,
 
 	/* Ensure the caller is allowed to use objects from PFMEMALLOC slab */
 	if (unlikely(is_obj_pfmemalloc(objp))) {
-		struct kmem_list3 *l3;
+		struct kmem_cache_node *n;
 
 		if (gfp_pfmemalloc_allowed(flags)) {
 			clear_obj_pfmemalloc(&objp);
@@ -993,8 +895,8 @@ static void *__ac_get_obj(struct kmem_cache *cachep, struct array_cache *ac,
 		 * If there are empty slabs on the slabs_free list and we are
 		 * being forced to refill the cache, mark this one !pfmemalloc.
 		 */
-		l3 = cachep->nodelists[numa_mem_id()];
-		if (!list_empty(&l3->slabs_free) && force_refill) {
+		n = cachep->node[numa_mem_id()];
+		if (!list_empty(&n->slabs_free) && force_refill) {
 			struct slab *slabp = virt_to_slab(objp);
 			ClearPageSlabPfmemalloc(virt_to_head_page(slabp->s_mem));
 			clear_obj_pfmemalloc(&objp);
@@ -1071,7 +973,7 @@ static int transfer_objects(struct array_cache *to,
 #ifndef CONFIG_NUMA
 
 #define drain_alien_cache(cachep, alien) do { } while (0)
-#define reap_alien(cachep, l3) do { } while (0)
+#define reap_alien(cachep, n) do { } while (0)
 
 static inline struct array_cache **alloc_alien_cache(int node, int limit, gfp_t gfp)
 {
@@ -1143,33 +1045,33 @@ static void free_alien_cache(struct array_cache **ac_ptr)
 static void __drain_alien_cache(struct kmem_cache *cachep,
 				struct array_cache *ac, int node)
 {
-	struct kmem_list3 *rl3 = cachep->nodelists[node];
+	struct kmem_cache_node *n = cachep->node[node];
 
 	if (ac->avail) {
-		spin_lock(&rl3->list_lock);
+		spin_lock(&n->list_lock);
 		/*
 		 * Stuff objects into the remote nodes shared array first.
 		 * That way we could avoid the overhead of putting the objects
 		 * into the free lists and getting them back later.
 		 */
-		if (rl3->shared)
-			transfer_objects(rl3->shared, ac, ac->limit);
+		if (n->shared)
+			transfer_objects(n->shared, ac, ac->limit);
 
 		free_block(cachep, ac->entry, ac->avail, node);
 		ac->avail = 0;
-		spin_unlock(&rl3->list_lock);
+		spin_unlock(&n->list_lock);
 	}
 }
 
 /*
  * Called from cache_reap() to regularly drain alien caches round robin.
  */
-static void reap_alien(struct kmem_cache *cachep, struct kmem_list3 *l3)
+static void reap_alien(struct kmem_cache *cachep, struct kmem_cache_node *n)
 {
 	int node = __this_cpu_read(slab_reap_node);
 
-	if (l3->alien) {
-		struct array_cache *ac = l3->alien[node];
+	if (n->alien) {
+		struct array_cache *ac = n->alien[node];
 
 		if (ac && ac->avail && spin_trylock_irq(&ac->lock)) {
 			__drain_alien_cache(cachep, ac, node);
@@ -1199,7 +1101,7 @@ static inline int cache_free_alien(struct kmem_cache *cachep, void *objp)
 {
 	struct slab *slabp = virt_to_slab(objp);
 	int nodeid = slabp->nodeid;
-	struct kmem_list3 *l3;
+	struct kmem_cache_node *n;
 	struct array_cache *alien = NULL;
 	int node;
 
@@ -1212,10 +1114,10 @@ static inline int cache_free_alien(struct kmem_cache *cachep, void *objp)
 	if (likely(slabp->nodeid == node))
 		return 0;
 
-	l3 = cachep->nodelists[node];
+	n = cachep->node[node];
 	STATS_INC_NODEFREES(cachep);
-	if (l3->alien && l3->alien[nodeid]) {
-		alien = l3->alien[nodeid];
+	if (n->alien && n->alien[nodeid]) {
+		alien = n->alien[nodeid];
 		spin_lock(&alien->lock);
 		if (unlikely(alien->avail == alien->limit)) {
 			STATS_INC_ACOVERFLOW(cachep);
@@ -1224,28 +1126,28 @@ static inline int cache_free_alien(struct kmem_cache *cachep, void *objp)
 		ac_put_obj(cachep, alien, objp);
 		spin_unlock(&alien->lock);
 	} else {
-		spin_lock(&(cachep->nodelists[nodeid])->list_lock);
+		spin_lock(&(cachep->node[nodeid])->list_lock);
 		free_block(cachep, &objp, 1, nodeid);
-		spin_unlock(&(cachep->nodelists[nodeid])->list_lock);
+		spin_unlock(&(cachep->node[nodeid])->list_lock);
 	}
 	return 1;
 }
 #endif
 
 /*
- * Allocates and initializes nodelists for a node on each slab cache, used for
- * either memory or cpu hotplug.  If memory is being hot-added, the kmem_list3
+ * Allocates and initializes node for a node on each slab cache, used for
+ * either memory or cpu hotplug.  If memory is being hot-added, the kmem_cache_node
  * will be allocated off-node since memory is not yet online for the new node.
- * When hotplugging memory or a cpu, existing nodelists are not replaced if
+ * When hotplugging memory or a cpu, existing node are not replaced if
  * already in use.
  *
  * Must hold slab_mutex.
  */
-static int init_cache_nodelists_node(int node)
+static int init_cache_node_node(int node)
 {
 	struct kmem_cache *cachep;
-	struct kmem_list3 *l3;
-	const int memsize = sizeof(struct kmem_list3);
+	struct kmem_cache_node *n;
+	const int memsize = sizeof(struct kmem_cache_node);
 
 	list_for_each_entry(cachep, &slab_caches, list) {
 		/*
@@ -1253,12 +1155,12 @@ static int init_cache_nodelists_node(int node)
 		 * begin anything. Make sure some other cpu on this
 		 * node has not already allocated this
 		 */
-		if (!cachep->nodelists[node]) {
-			l3 = kmalloc_node(memsize, GFP_KERNEL, node);
-			if (!l3)
+		if (!cachep->node[node]) {
+			n = kmalloc_node(memsize, GFP_KERNEL, node);
+			if (!n)
 				return -ENOMEM;
-			kmem_list3_init(l3);
-			l3->next_reap = jiffies + REAPTIMEOUT_LIST3 +
+			kmem_cache_node_init(n);
+			n->next_reap = jiffies + REAPTIMEOUT_LIST3 +
 			    ((unsigned long)cachep) % REAPTIMEOUT_LIST3;
 
 			/*
@@ -1266,14 +1168,14 @@ static int init_cache_nodelists_node(int node)
 			 * go.  slab_mutex is sufficient
 			 * protection here.
 			 */
-			cachep->nodelists[node] = l3;
+			cachep->node[node] = n;
 		}
 
-		spin_lock_irq(&cachep->nodelists[node]->list_lock);
-		cachep->nodelists[node]->free_limit =
+		spin_lock_irq(&cachep->node[node]->list_lock);
+		cachep->node[node]->free_limit =
 			(1 + nr_cpus_node(node)) *
 			cachep->batchcount + cachep->num;
-		spin_unlock_irq(&cachep->nodelists[node]->list_lock);
+		spin_unlock_irq(&cachep->node[node]->list_lock);
 	}
 	return 0;
 }
@@ -1281,7 +1183,7 @@ static int init_cache_nodelists_node(int node)
 static void __cpuinit cpuup_canceled(long cpu)
 {
 	struct kmem_cache *cachep;
-	struct kmem_list3 *l3 = NULL;
+	struct kmem_cache_node *n = NULL;
 	int node = cpu_to_mem(cpu);
 	const struct cpumask *mask = cpumask_of_node(node);
 
@@ -1293,34 +1195,34 @@ static void __cpuinit cpuup_canceled(long cpu)
 		/* cpu is dead; no one can alloc from it. */
 		nc = cachep->array[cpu];
 		cachep->array[cpu] = NULL;
-		l3 = cachep->nodelists[node];
+		n = cachep->node[node];
 
-		if (!l3)
+		if (!n)
 			goto free_array_cache;
 
-		spin_lock_irq(&l3->list_lock);
+		spin_lock_irq(&n->list_lock);
 
-		/* Free limit for this kmem_list3 */
-		l3->free_limit -= cachep->batchcount;
+		/* Free limit for this kmem_cache_node */
+		n->free_limit -= cachep->batchcount;
 		if (nc)
 			free_block(cachep, nc->entry, nc->avail, node);
 
 		if (!cpumask_empty(mask)) {
-			spin_unlock_irq(&l3->list_lock);
+			spin_unlock_irq(&n->list_lock);
 			goto free_array_cache;
 		}
 
-		shared = l3->shared;
+		shared = n->shared;
 		if (shared) {
 			free_block(cachep, shared->entry,
 				   shared->avail, node);
-			l3->shared = NULL;
+			n->shared = NULL;
 		}
 
-		alien = l3->alien;
-		l3->alien = NULL;
+		alien = n->alien;
+		n->alien = NULL;
 
-		spin_unlock_irq(&l3->list_lock);
+		spin_unlock_irq(&n->list_lock);
 
 		kfree(shared);
 		if (alien) {
@@ -1336,17 +1238,17 @@ free_array_cache:
 	 * shrink each nodelist to its limit.
 	 */
 	list_for_each_entry(cachep, &slab_caches, list) {
-		l3 = cachep->nodelists[node];
-		if (!l3)
+		n = cachep->node[node];
+		if (!n)
 			continue;
-		drain_freelist(cachep, l3, l3->free_objects);
+		drain_freelist(cachep, n, n->free_objects);
 	}
 }
 
 static int __cpuinit cpuup_prepare(long cpu)
 {
 	struct kmem_cache *cachep;
-	struct kmem_list3 *l3 = NULL;
+	struct kmem_cache_node *n = NULL;
 	int node = cpu_to_mem(cpu);
 	int err;
 
@@ -1354,9 +1256,9 @@ static int __cpuinit cpuup_prepare(long cpu)
 	 * We need to do this right in the beginning since
 	 * alloc_arraycache's are going to use this list.
 	 * kmalloc_node allows us to add the slab to the right
-	 * kmem_list3 and not this cpu's kmem_list3
+	 * kmem_cache_node and not this cpu's kmem_cache_node
 	 */
-	err = init_cache_nodelists_node(node);
+	err = init_cache_node_node(node);
 	if (err < 0)
 		goto bad;
 
@@ -1391,25 +1293,25 @@ static int __cpuinit cpuup_prepare(long cpu)
 			}
 		}
 		cachep->array[cpu] = nc;
-		l3 = cachep->nodelists[node];
-		BUG_ON(!l3);
+		n = cachep->node[node];
+		BUG_ON(!n);
 
-		spin_lock_irq(&l3->list_lock);
-		if (!l3->shared) {
+		spin_lock_irq(&n->list_lock);
+		if (!n->shared) {
 			/*
 			 * We are serialised from CPU_DEAD or
 			 * CPU_UP_CANCELLED by the cpucontrol lock
 			 */
-			l3->shared = shared;
+			n->shared = shared;
 			shared = NULL;
 		}
 #ifdef CONFIG_NUMA
-		if (!l3->alien) {
-			l3->alien = alien;
+		if (!n->alien) {
+			n->alien = alien;
 			alien = NULL;
 		}
 #endif
-		spin_unlock_irq(&l3->list_lock);
+		spin_unlock_irq(&n->list_lock);
 		kfree(shared);
 		free_alien_cache(alien);
 		if (cachep->flags & SLAB_DEBUG_OBJECTS)
@@ -1464,9 +1366,9 @@ static int __cpuinit cpuup_callback(struct notifier_block *nfb,
 	case CPU_DEAD_FROZEN:
 		/*
 		 * Even if all the cpus of a node are down, we don't free the
-		 * kmem_list3 of any cache. This to avoid a race between
+		 * kmem_cache_node of any cache. This to avoid a race between
 		 * cpu_down, and a kmalloc allocation from another cpu for
-		 * memory from the node of the cpu going down.  The list3
+		 * memory from the node of the cpu going down.  The node
 		 * structure is usually allocated from kmem_cache_create() and
 		 * gets destroyed at kmem_cache_destroy().
 		 */
@@ -1494,22 +1396,22 @@ static struct notifier_block __cpuinitdata cpucache_notifier = {
  *
  * Must hold slab_mutex.
  */
-static int __meminit drain_cache_nodelists_node(int node)
+static int __meminit drain_cache_node_node(int node)
 {
 	struct kmem_cache *cachep;
 	int ret = 0;
 
 	list_for_each_entry(cachep, &slab_caches, list) {
-		struct kmem_list3 *l3;
+		struct kmem_cache_node *n;
 
-		l3 = cachep->nodelists[node];
-		if (!l3)
+		n = cachep->node[node];
+		if (!n)
 			continue;
 
-		drain_freelist(cachep, l3, l3->free_objects);
+		drain_freelist(cachep, n, n->free_objects);
 
-		if (!list_empty(&l3->slabs_full) ||
-		    !list_empty(&l3->slabs_partial)) {
+		if (!list_empty(&n->slabs_full) ||
+		    !list_empty(&n->slabs_partial)) {
 			ret = -EBUSY;
 			break;
 		}
@@ -1531,12 +1433,12 @@ static int __meminit slab_memory_callback(struct notifier_block *self,
 	switch (action) {
 	case MEM_GOING_ONLINE:
 		mutex_lock(&slab_mutex);
-		ret = init_cache_nodelists_node(nid);
+		ret = init_cache_node_node(nid);
 		mutex_unlock(&slab_mutex);
 		break;
 	case MEM_GOING_OFFLINE:
 		mutex_lock(&slab_mutex);
-		ret = drain_cache_nodelists_node(nid);
+		ret = drain_cache_node_node(nid);
 		mutex_unlock(&slab_mutex);
 		break;
 	case MEM_ONLINE:
@@ -1551,37 +1453,37 @@ out:
 #endif /* CONFIG_NUMA && CONFIG_MEMORY_HOTPLUG */
 
 /*
- * swap the static kmem_list3 with kmalloced memory
+ * swap the static kmem_cache_node with kmalloced memory
  */
-static void __init init_list(struct kmem_cache *cachep, struct kmem_list3 *list,
+static void __init init_list(struct kmem_cache *cachep, struct kmem_cache_node *list,
 				int nodeid)
 {
-	struct kmem_list3 *ptr;
+	struct kmem_cache_node *ptr;
 
-	ptr = kmalloc_node(sizeof(struct kmem_list3), GFP_NOWAIT, nodeid);
+	ptr = kmalloc_node(sizeof(struct kmem_cache_node), GFP_NOWAIT, nodeid);
 	BUG_ON(!ptr);
 
-	memcpy(ptr, list, sizeof(struct kmem_list3));
+	memcpy(ptr, list, sizeof(struct kmem_cache_node));
 	/*
 	 * Do not assume that spinlocks can be initialized via memcpy:
 	 */
 	spin_lock_init(&ptr->list_lock);
 
 	MAKE_ALL_LISTS(cachep, ptr, nodeid);
-	cachep->nodelists[nodeid] = ptr;
+	cachep->node[nodeid] = ptr;
 }
 
 /*
- * For setting up all the kmem_list3s for cache whose buffer_size is same as
- * size of kmem_list3.
+ * For setting up all the kmem_cache_node for cache whose buffer_size is same as
+ * size of kmem_cache_node.
  */
-static void __init set_up_list3s(struct kmem_cache *cachep, int index)
+static void __init set_up_node(struct kmem_cache *cachep, int index)
 {
 	int node;
 
 	for_each_online_node(node) {
-		cachep->nodelists[node] = &initkmem_list3[index + node];
-		cachep->nodelists[node]->next_reap = jiffies +
+		cachep->node[node] = &init_kmem_cache_node[index + node];
+		cachep->node[node]->next_reap = jiffies +
 		    REAPTIMEOUT_LIST3 +
 		    ((unsigned long)cachep) % REAPTIMEOUT_LIST3;
 	}
@@ -1589,11 +1491,11 @@ static void __init set_up_list3s(struct kmem_cache *cachep, int index)
 
 /*
  * The memory after the last cpu cache pointer is used for the
- * the nodelists pointer.
+ * the node pointer.
  */
-static void setup_nodelists_pointer(struct kmem_cache *cachep)
+static void setup_node_pointer(struct kmem_cache *cachep)
 {
-	cachep->nodelists = (struct kmem_list3 **)&cachep->array[nr_cpu_ids];
+	cachep->node = (struct kmem_cache_node **)&cachep->array[nr_cpu_ids];
 }
 
 /*
@@ -1602,20 +1504,18 @@ static void setup_nodelists_pointer(struct kmem_cache *cachep)
  */
 void __init kmem_cache_init(void)
 {
-	struct cache_sizes *sizes;
-	struct cache_names *names;
 	int i;
 
 	kmem_cache = &kmem_cache_boot;
-	setup_nodelists_pointer(kmem_cache);
+	setup_node_pointer(kmem_cache);
 
 	if (num_possible_nodes() == 1)
 		use_alien_caches = 0;
 
 	for (i = 0; i < NUM_INIT_LISTS; i++)
-		kmem_list3_init(&initkmem_list3[i]);
+		kmem_cache_node_init(&init_kmem_cache_node[i]);
 
-	set_up_list3s(kmem_cache, CACHE_CACHE);
+	set_up_node(kmem_cache, CACHE_CACHE);
 
 	/*
 	 * Fragmentation resistance on low memory - only use bigger
@@ -1631,7 +1531,7 @@ void __init kmem_cache_init(void)
 	 *    kmem_cache structures of all caches, except kmem_cache itself:
 	 *    kmem_cache is statically allocated.
 	 *    Initially an __init data area is used for the head array and the
-	 *    kmem_list3 structures, it's replaced with a kmalloc allocated
+	 *    kmem_cache_node structures, it's replaced with a kmalloc allocated
 	 *    array at the end of the bootstrap.
 	 * 2) Create the first kmalloc cache.
 	 *    The struct kmem_cache for the new cache is allocated normally.
@@ -1640,7 +1540,7 @@ void __init kmem_cache_init(void)
 	 *    head arrays.
 	 * 4) Replace the __init data head arrays for kmem_cache and the first
 	 *    kmalloc cache with kmalloc allocated arrays.
-	 * 5) Replace the __init data for kmem_list3 for kmem_cache and
+	 * 5) Replace the __init data for kmem_cache_node for kmem_cache and
 	 *    the other cache's with kmalloc allocated memory.
 	 * 6) Resize the head arrays of the kmalloc caches to their final sizes.
 	 */
@@ -1652,50 +1552,28 @@ void __init kmem_cache_init(void)
 	 */
 	create_boot_cache(kmem_cache, "kmem_cache",
 		offsetof(struct kmem_cache, array[nr_cpu_ids]) +
-				  nr_node_ids * sizeof(struct kmem_list3 *),
+				  nr_node_ids * sizeof(struct kmem_cache_node *),
 				  SLAB_HWCACHE_ALIGN);
 	list_add(&kmem_cache->list, &slab_caches);
 
 	/* 2+3) create the kmalloc caches */
-	sizes = malloc_sizes;
-	names = cache_names;
 
 	/*
 	 * Initialize the caches that provide memory for the array cache and the
-	 * kmem_list3 structures first.  Without this, further allocations will
+	 * kmem_cache_node structures first.  Without this, further allocations will
 	 * bug.
 	 */
 
-	sizes[INDEX_AC].cs_cachep = create_kmalloc_cache(names[INDEX_AC].name,
-					sizes[INDEX_AC].cs_size, ARCH_KMALLOC_FLAGS);
+	kmalloc_caches[INDEX_AC] = create_kmalloc_cache("kmalloc-ac",
+					kmalloc_size(INDEX_AC), ARCH_KMALLOC_FLAGS);
 
-	if (INDEX_AC != INDEX_L3)
-		sizes[INDEX_L3].cs_cachep =
-			create_kmalloc_cache(names[INDEX_L3].name,
-				sizes[INDEX_L3].cs_size, ARCH_KMALLOC_FLAGS);
+	if (INDEX_AC != INDEX_NODE)
+		kmalloc_caches[INDEX_NODE] =
+			create_kmalloc_cache("kmalloc-node",
+				kmalloc_size(INDEX_NODE), ARCH_KMALLOC_FLAGS);
 
 	slab_early_init = 0;
 
-	while (sizes->cs_size != ULONG_MAX) {
-		/*
-		 * For performance, all the general caches are L1 aligned.
-		 * This should be particularly beneficial on SMP boxes, as it
-		 * eliminates "false sharing".
-		 * Note for systems short on memory removing the alignment will
-		 * allow tighter packing of the smaller caches.
-		 */
-		if (!sizes->cs_cachep)
-			sizes->cs_cachep = create_kmalloc_cache(names->name,
-					sizes->cs_size, ARCH_KMALLOC_FLAGS);
-
-#ifdef CONFIG_ZONE_DMA
-		sizes->cs_dmacachep = create_kmalloc_cache(
-			names->name_dma, sizes->cs_size,
-			SLAB_CACHE_DMA|ARCH_KMALLOC_FLAGS);
-#endif
-		sizes++;
-		names++;
-	}
 	/* 4) Replace the bootstrap head arrays */
 	{
 		struct array_cache *ptr;
@@ -1713,36 +1591,35 @@ void __init kmem_cache_init(void)
 
 		ptr = kmalloc(sizeof(struct arraycache_init), GFP_NOWAIT);
 
-		BUG_ON(cpu_cache_get(malloc_sizes[INDEX_AC].cs_cachep)
+		BUG_ON(cpu_cache_get(kmalloc_caches[INDEX_AC])
 		       != &initarray_generic.cache);
-		memcpy(ptr, cpu_cache_get(malloc_sizes[INDEX_AC].cs_cachep),
+		memcpy(ptr, cpu_cache_get(kmalloc_caches[INDEX_AC]),
 		       sizeof(struct arraycache_init));
 		/*
 		 * Do not assume that spinlocks can be initialized via memcpy:
 		 */
 		spin_lock_init(&ptr->lock);
 
-		malloc_sizes[INDEX_AC].cs_cachep->array[smp_processor_id()] =
-		    ptr;
+		kmalloc_caches[INDEX_AC]->array[smp_processor_id()] = ptr;
 	}
-	/* 5) Replace the bootstrap kmem_list3's */
+	/* 5) Replace the bootstrap kmem_cache_node */
 	{
 		int nid;
 
 		for_each_online_node(nid) {
-			init_list(kmem_cache, &initkmem_list3[CACHE_CACHE + nid], nid);
+			init_list(kmem_cache, &init_kmem_cache_node[CACHE_CACHE + nid], nid);
 
-			init_list(malloc_sizes[INDEX_AC].cs_cachep,
-				  &initkmem_list3[SIZE_AC + nid], nid);
+			init_list(kmalloc_caches[INDEX_AC],
+				  &init_kmem_cache_node[SIZE_AC + nid], nid);
 
-			if (INDEX_AC != INDEX_L3) {
-				init_list(malloc_sizes[INDEX_L3].cs_cachep,
-					  &initkmem_list3[SIZE_L3 + nid], nid);
+			if (INDEX_AC != INDEX_NODE) {
+				init_list(kmalloc_caches[INDEX_NODE],
+					  &init_kmem_cache_node[SIZE_NODE + nid], nid);
 			}
 		}
 	}
 
-	slab_state = UP;
+	create_kmalloc_caches(ARCH_KMALLOC_FLAGS);
 }
 
 void __init kmem_cache_init_late(void)
@@ -1773,7 +1650,7 @@ void __init kmem_cache_init_late(void)
 #ifdef CONFIG_NUMA
 	/*
 	 * Register a memory hotplug callback that initializes and frees
-	 * nodelists.
+	 * node.
 	 */
 	hotplug_memory_notifier(slab_memory_callback, SLAB_CALLBACK_PRI);
 #endif
@@ -1803,7 +1680,7 @@ __initcall(cpucache_init);
 static noinline void
 slab_out_of_memory(struct kmem_cache *cachep, gfp_t gfpflags, int nodeid)
 {
-	struct kmem_list3 *l3;
+	struct kmem_cache_node *n;
 	struct slab *slabp;
 	unsigned long flags;
 	int node;
@@ -1818,24 +1695,24 @@ slab_out_of_memory(struct kmem_cache *cachep, gfp_t gfpflags, int nodeid)
 		unsigned long active_objs = 0, num_objs = 0, free_objects = 0;
 		unsigned long active_slabs = 0, num_slabs = 0;
 
-		l3 = cachep->nodelists[node];
-		if (!l3)
+		n = cachep->node[node];
+		if (!n)
 			continue;
 
-		spin_lock_irqsave(&l3->list_lock, flags);
-		list_for_each_entry(slabp, &l3->slabs_full, list) {
+		spin_lock_irqsave(&n->list_lock, flags);
+		list_for_each_entry(slabp, &n->slabs_full, list) {
 			active_objs += cachep->num;
 			active_slabs++;
 		}
-		list_for_each_entry(slabp, &l3->slabs_partial, list) {
+		list_for_each_entry(slabp, &n->slabs_partial, list) {
 			active_objs += slabp->inuse;
 			active_slabs++;
 		}
-		list_for_each_entry(slabp, &l3->slabs_free, list)
+		list_for_each_entry(slabp, &n->slabs_free, list)
 			num_slabs++;
 
-		free_objects += l3->free_objects;
-		spin_unlock_irqrestore(&l3->list_lock, flags);
+		free_objects += n->free_objects;
+		spin_unlock_irqrestore(&n->list_lock, flags);
 
 		num_slabs += active_slabs;
 		num_objs = num_slabs * cachep->num;
@@ -2260,7 +2137,7 @@ static int __init_refok setup_cpu_cache(struct kmem_cache *cachep, gfp_t gfp)
 	if (slab_state == DOWN) {
 		/*
 		 * Note: Creation of first cache (kmem_cache).
-		 * The setup_list3s is taken care
+		 * The setup_node is taken care
 		 * of by the caller of __kmem_cache_create
 		 */
 		cachep->array[smp_processor_id()] = &initarray_generic.cache;
@@ -2274,13 +2151,13 @@ static int __init_refok setup_cpu_cache(struct kmem_cache *cachep, gfp_t gfp)
 		cachep->array[smp_processor_id()] = &initarray_generic.cache;
 
 		/*
-		 * If the cache that's used by kmalloc(sizeof(kmem_list3)) is
-		 * the second cache, then we need to set up all its list3s,
+		 * If the cache that's used by kmalloc(sizeof(kmem_cache_node)) is
+		 * the second cache, then we need to set up all its node/,
 		 * otherwise the creation of further caches will BUG().
 		 */
-		set_up_list3s(cachep, SIZE_AC);
-		if (INDEX_AC == INDEX_L3)
-			slab_state = PARTIAL_L3;
+		set_up_node(cachep, SIZE_AC);
+		if (INDEX_AC == INDEX_NODE)
+			slab_state = PARTIAL_NODE;
 		else
 			slab_state = PARTIAL_ARRAYCACHE;
 	} else {
@@ -2289,20 +2166,20 @@ static int __init_refok setup_cpu_cache(struct kmem_cache *cachep, gfp_t gfp)
 			kmalloc(sizeof(struct arraycache_init), gfp);
 
 		if (slab_state == PARTIAL_ARRAYCACHE) {
-			set_up_list3s(cachep, SIZE_L3);
-			slab_state = PARTIAL_L3;
+			set_up_node(cachep, SIZE_NODE);
+			slab_state = PARTIAL_NODE;
 		} else {
 			int node;
 			for_each_online_node(node) {
-				cachep->nodelists[node] =
-				    kmalloc_node(sizeof(struct kmem_list3),
+				cachep->node[node] =
+				    kmalloc_node(sizeof(struct kmem_cache_node),
 						gfp, node);
-				BUG_ON(!cachep->nodelists[node]);
-				kmem_list3_init(cachep->nodelists[node]);
+				BUG_ON(!cachep->node[node]);
+				kmem_cache_node_init(cachep->node[node]);
 			}
 		}
 	}
-	cachep->nodelists[numa_mem_id()]->next_reap =
+	cachep->node[numa_mem_id()]->next_reap =
 			jiffies + REAPTIMEOUT_LIST3 +
 			((unsigned long)cachep) % REAPTIMEOUT_LIST3;
 
@@ -2405,7 +2282,7 @@ __kmem_cache_create (struct kmem_cache *cachep, unsigned long flags)
 	else
 		gfp = GFP_NOWAIT;
 
-	setup_nodelists_pointer(cachep);
+	setup_node_pointer(cachep);
 #if DEBUG
 
 	/*
@@ -2428,7 +2305,7 @@ __kmem_cache_create (struct kmem_cache *cachep, unsigned long flags)
 			size += BYTES_PER_WORD;
 	}
 #if FORCED_DEBUG && defined(CONFIG_DEBUG_PAGEALLOC)
-	if (size >= malloc_sizes[INDEX_L3 + 1].cs_size
+	if (size >= kmalloc_size(INDEX_NODE + 1)
 	    && cachep->object_size > cache_line_size()
 	    && ALIGN(size, cachep->align) < PAGE_SIZE) {
 		cachep->obj_offset += PAGE_SIZE - ALIGN(size, cachep->align);
@@ -2499,7 +2376,7 @@ __kmem_cache_create (struct kmem_cache *cachep, unsigned long flags)
 	cachep->reciprocal_buffer_size = reciprocal_value(size);
 
 	if (flags & CFLGS_OFF_SLAB) {
-		cachep->slabp_cache = kmem_find_general_cachep(slab_size, 0u);
+		cachep->slabp_cache = kmalloc_slab(slab_size, 0u);
 		/*
 		 * This is a possibility for one of the malloc_sizes caches.
 		 * But since we go off slab only for object size greater than
@@ -2545,7 +2422,7 @@ static void check_spinlock_acquired(struct kmem_cache *cachep)
 {
 #ifdef CONFIG_SMP
 	check_irq_off();
-	assert_spin_locked(&cachep->nodelists[numa_mem_id()]->list_lock);
+	assert_spin_locked(&cachep->node[numa_mem_id()]->list_lock);
 #endif
 }
 
@@ -2553,7 +2430,7 @@ static void check_spinlock_acquired_node(struct kmem_cache *cachep, int node)
 {
 #ifdef CONFIG_SMP
 	check_irq_off();
-	assert_spin_locked(&cachep->nodelists[node]->list_lock);
+	assert_spin_locked(&cachep->node[node]->list_lock);
 #endif
 }
 
@@ -2564,7 +2441,7 @@ static void check_spinlock_acquired_node(struct kmem_cache *cachep, int node)
 #define check_spinlock_acquired_node(x, y) do { } while(0)
 #endif
 
-static void drain_array(struct kmem_cache *cachep, struct kmem_list3 *l3,
+static void drain_array(struct kmem_cache *cachep, struct kmem_cache_node *n,
 			struct array_cache *ac,
 			int force, int node);
 
@@ -2576,29 +2453,29 @@ static void do_drain(void *arg)
 
 	check_irq_off();
 	ac = cpu_cache_get(cachep);
-	spin_lock(&cachep->nodelists[node]->list_lock);
+	spin_lock(&cachep->node[node]->list_lock);
 	free_block(cachep, ac->entry, ac->avail, node);
-	spin_unlock(&cachep->nodelists[node]->list_lock);
+	spin_unlock(&cachep->node[node]->list_lock);
 	ac->avail = 0;
 }
 
 static void drain_cpu_caches(struct kmem_cache *cachep)
 {
-	struct kmem_list3 *l3;
+	struct kmem_cache_node *n;
 	int node;
 
 	on_each_cpu(do_drain, cachep, 1);
 	check_irq_on();
 	for_each_online_node(node) {
-		l3 = cachep->nodelists[node];
-		if (l3 && l3->alien)
-			drain_alien_cache(cachep, l3->alien);
+		n = cachep->node[node];
+		if (n && n->alien)
+			drain_alien_cache(cachep, n->alien);
 	}
 
 	for_each_online_node(node) {
-		l3 = cachep->nodelists[node];
-		if (l3)
-			drain_array(cachep, l3, l3->shared, 1, node);
+		n = cachep->node[node];
+		if (n)
+			drain_array(cachep, n, n->shared, 1, node);
 	}
 }
 
@@ -2609,19 +2486,19 @@ static void drain_cpu_caches(struct kmem_cache *cachep)
  * Returns the actual number of slabs released.
  */
 static int drain_freelist(struct kmem_cache *cache,
-			struct kmem_list3 *l3, int tofree)
+			struct kmem_cache_node *n, int tofree)
 {
 	struct list_head *p;
 	int nr_freed;
 	struct slab *slabp;
 
 	nr_freed = 0;
-	while (nr_freed < tofree && !list_empty(&l3->slabs_free)) {
+	while (nr_freed < tofree && !list_empty(&n->slabs_free)) {
 
-		spin_lock_irq(&l3->list_lock);
-		p = l3->slabs_free.prev;
-		if (p == &l3->slabs_free) {
-			spin_unlock_irq(&l3->list_lock);
+		spin_lock_irq(&n->list_lock);
+		p = n->slabs_free.prev;
+		if (p == &n->slabs_free) {
+			spin_unlock_irq(&n->list_lock);
 			goto out;
 		}
 
@@ -2634,8 +2511,8 @@ static int drain_freelist(struct kmem_cache *cache,
 		 * Safe to drop the lock. The slab is no longer linked
 		 * to the cache.
 		 */
-		l3->free_objects -= cache->num;
-		spin_unlock_irq(&l3->list_lock);
+		n->free_objects -= cache->num;
+		spin_unlock_irq(&n->list_lock);
 		slab_destroy(cache, slabp);
 		nr_freed++;
 	}
@@ -2647,20 +2524,20 @@ out:
 static int __cache_shrink(struct kmem_cache *cachep)
 {
 	int ret = 0, i = 0;
-	struct kmem_list3 *l3;
+	struct kmem_cache_node *n;
 
 	drain_cpu_caches(cachep);
 
 	check_irq_on();
 	for_each_online_node(i) {
-		l3 = cachep->nodelists[i];
-		if (!l3)
+		n = cachep->node[i];
+		if (!n)
 			continue;
 
-		drain_freelist(cachep, l3, l3->free_objects);
+		drain_freelist(cachep, n, n->free_objects);
 
-		ret += !list_empty(&l3->slabs_full) ||
-			!list_empty(&l3->slabs_partial);
+		ret += !list_empty(&n->slabs_full) ||
+			!list_empty(&n->slabs_partial);
 	}
 	return (ret ? 1 : 0);
 }
@@ -2689,7 +2566,7 @@ EXPORT_SYMBOL(kmem_cache_shrink);
 int __kmem_cache_shutdown(struct kmem_cache *cachep)
 {
 	int i;
-	struct kmem_list3 *l3;
+	struct kmem_cache_node *n;
 	int rc = __cache_shrink(cachep);
 
 	if (rc)
@@ -2698,13 +2575,13 @@ int __kmem_cache_shutdown(struct kmem_cache *cachep)
 	for_each_online_cpu(i)
 	    kfree(cachep->array[i]);
 
-	/* NUMA: free the list3 structures */
+	/* NUMA: free the node structures */
 	for_each_online_node(i) {
-		l3 = cachep->nodelists[i];
-		if (l3) {
-			kfree(l3->shared);
-			free_alien_cache(l3->alien);
-			kfree(l3);
+		n = cachep->node[i];
+		if (n) {
+			kfree(n->shared);
+			free_alien_cache(n->alien);
+			kfree(n);
 		}
 	}
 	return 0;
@@ -2886,7 +2763,7 @@ static int cache_grow(struct kmem_cache *cachep,
 	struct slab *slabp;
 	size_t offset;
 	gfp_t local_flags;
-	struct kmem_list3 *l3;
+	struct kmem_cache_node *n;
 
 	/*
 	 * Be lazy and only check for valid flags here,  keeping it out of the
@@ -2895,17 +2772,17 @@ static int cache_grow(struct kmem_cache *cachep,
 	BUG_ON(flags & GFP_SLAB_BUG_MASK);
 	local_flags = flags & (GFP_CONSTRAINT_MASK|GFP_RECLAIM_MASK);
 
-	/* Take the l3 list lock to change the colour_next on this node */
+	/* Take the node list lock to change the colour_next on this node */
 	check_irq_off();
-	l3 = cachep->nodelists[nodeid];
-	spin_lock(&l3->list_lock);
+	n = cachep->node[nodeid];
+	spin_lock(&n->list_lock);
 
 	/* Get colour for the slab, and cal the next value. */
-	offset = l3->colour_next;
-	l3->colour_next++;
-	if (l3->colour_next >= cachep->colour)
-		l3->colour_next = 0;
-	spin_unlock(&l3->list_lock);
+	offset = n->colour_next;
+	n->colour_next++;
+	if (n->colour_next >= cachep->colour)
+		n->colour_next = 0;
+	spin_unlock(&n->list_lock);
 
 	offset *= cachep->colour_off;
 
@@ -2942,13 +2819,13 @@ static int cache_grow(struct kmem_cache *cachep,
 	if (local_flags & __GFP_WAIT)
 		local_irq_disable();
 	check_irq_off();
-	spin_lock(&l3->list_lock);
+	spin_lock(&n->list_lock);
 
 	/* Make slab active. */
-	list_add_tail(&slabp->list, &(l3->slabs_free));
+	list_add_tail(&slabp->list, &(n->slabs_free));
 	STATS_INC_GROWN(cachep);
-	l3->free_objects += cachep->num;
-	spin_unlock(&l3->list_lock);
+	n->free_objects += cachep->num;
+	spin_unlock(&n->list_lock);
 	return 1;
 opps1:
 	kmem_freepages(cachep, objp);
@@ -3076,7 +2953,7 @@ static void *cache_alloc_refill(struct kmem_cache *cachep, gfp_t flags,
 							bool force_refill)
 {
 	int batchcount;
-	struct kmem_list3 *l3;
+	struct kmem_cache_node *n;
 	struct array_cache *ac;
 	int node;
 
@@ -3095,14 +2972,14 @@ retry:
 		 */
 		batchcount = BATCHREFILL_LIMIT;
 	}
-	l3 = cachep->nodelists[node];
+	n = cachep->node[node];
 
-	BUG_ON(ac->avail > 0 || !l3);
-	spin_lock(&l3->list_lock);
+	BUG_ON(ac->avail > 0 || !n);
+	spin_lock(&n->list_lock);
 
 	/* See if we can refill from the shared array */
-	if (l3->shared && transfer_objects(ac, l3->shared, batchcount)) {
-		l3->shared->touched = 1;
+	if (n->shared && transfer_objects(ac, n->shared, batchcount)) {
+		n->shared->touched = 1;
 		goto alloc_done;
 	}
 
@@ -3110,11 +2987,11 @@ retry:
 		struct list_head *entry;
 		struct slab *slabp;
 		/* Get slab alloc is to come from. */
-		entry = l3->slabs_partial.next;
-		if (entry == &l3->slabs_partial) {
-			l3->free_touched = 1;
-			entry = l3->slabs_free.next;
-			if (entry == &l3->slabs_free)
+		entry = n->slabs_partial.next;
+		if (entry == &n->slabs_partial) {
+			n->free_touched = 1;
+			entry = n->slabs_free.next;
+			if (entry == &n->slabs_free)
 				goto must_grow;
 		}
 
@@ -3142,15 +3019,15 @@ retry:
 		/* move slabp to correct slabp list: */
 		list_del(&slabp->list);
 		if (slabp->free == BUFCTL_END)
-			list_add(&slabp->list, &l3->slabs_full);
+			list_add(&slabp->list, &n->slabs_full);
 		else
-			list_add(&slabp->list, &l3->slabs_partial);
+			list_add(&slabp->list, &n->slabs_partial);
 	}
 
 must_grow:
-	l3->free_objects -= ac->avail;
+	n->free_objects -= ac->avail;
 alloc_done:
-	spin_unlock(&l3->list_lock);
+	spin_unlock(&n->list_lock);
 
 	if (unlikely(!ac->avail)) {
 		int x;
@@ -3317,7 +3194,7 @@ static void *alternate_node_alloc(struct kmem_cache *cachep, gfp_t flags)
 /*
  * Fallback function if there was no memory available and no objects on a
  * certain node and fall back is permitted. First we scan all the
- * available nodelists for available objects. If that fails then we
+ * available node for available objects. If that fails then we
  * perform an allocation without specifying a node. This allows the page
  * allocator to do its reclaim / fallback magic. We then insert the
  * slab into the proper nodelist and then allocate from it.
@@ -3351,8 +3228,8 @@ retry:
 		nid = zone_to_nid(zone);
 
 		if (cpuset_zone_allowed_hardwall(zone, flags) &&
-			cache->nodelists[nid] &&
-			cache->nodelists[nid]->free_objects) {
+			cache->node[nid] &&
+			cache->node[nid]->free_objects) {
 				obj = ____cache_alloc_node(cache,
 					flags | GFP_THISNODE, nid);
 				if (obj)
@@ -3408,21 +3285,21 @@ static void *____cache_alloc_node(struct kmem_cache *cachep, gfp_t flags,
 {
 	struct list_head *entry;
 	struct slab *slabp;
-	struct kmem_list3 *l3;
+	struct kmem_cache_node *n;
 	void *obj;
 	int x;
 
-	l3 = cachep->nodelists[nodeid];
-	BUG_ON(!l3);
+	n = cachep->node[nodeid];
+	BUG_ON(!n);
 
 retry:
 	check_irq_off();
-	spin_lock(&l3->list_lock);
-	entry = l3->slabs_partial.next;
-	if (entry == &l3->slabs_partial) {
-		l3->free_touched = 1;
-		entry = l3->slabs_free.next;
-		if (entry == &l3->slabs_free)
+	spin_lock(&n->list_lock);
+	entry = n->slabs_partial.next;
+	if (entry == &n->slabs_partial) {
+		n->free_touched = 1;
+		entry = n->slabs_free.next;
+		if (entry == &n->slabs_free)
 			goto must_grow;
 	}
 
@@ -3438,20 +3315,20 @@ retry:
 
 	obj = slab_get_obj(cachep, slabp, nodeid);
 	check_slabp(cachep, slabp);
-	l3->free_objects--;
+	n->free_objects--;
 	/* move slabp to correct slabp list: */
 	list_del(&slabp->list);
 
 	if (slabp->free == BUFCTL_END)
-		list_add(&slabp->list, &l3->slabs_full);
+		list_add(&slabp->list, &n->slabs_full);
 	else
-		list_add(&slabp->list, &l3->slabs_partial);
+		list_add(&slabp->list, &n->slabs_partial);
 
-	spin_unlock(&l3->list_lock);
+	spin_unlock(&n->list_lock);
 	goto done;
 
 must_grow:
-	spin_unlock(&l3->list_lock);
+	spin_unlock(&n->list_lock);
 	x = cache_grow(cachep, flags | GFP_THISNODE, nodeid, NULL);
 	if (x)
 		goto retry;
@@ -3497,7 +3374,7 @@ slab_alloc_node(struct kmem_cache *cachep, gfp_t flags, int nodeid,
 	if (nodeid == NUMA_NO_NODE)
 		nodeid = slab_node;
 
-	if (unlikely(!cachep->nodelists[nodeid])) {
+	if (unlikely(!cachep->node[nodeid])) {
 		/* Node not bootstrapped yet */
 		ptr = fallback_alloc(cachep, flags);
 		goto out;
@@ -3603,7 +3480,7 @@ static void free_block(struct kmem_cache *cachep, void **objpp, int nr_objects,
 		       int node)
 {
 	int i;
-	struct kmem_list3 *l3;
+	struct kmem_cache_node *n;
 
 	for (i = 0; i < nr_objects; i++) {
 		void *objp;
@@ -3613,19 +3490,19 @@ static void free_block(struct kmem_cache *cachep, void **objpp, int nr_objects,
 		objp = objpp[i];
 
 		slabp = virt_to_slab(objp);
-		l3 = cachep->nodelists[node];
+		n = cachep->node[node];
 		list_del(&slabp->list);
 		check_spinlock_acquired_node(cachep, node);
 		check_slabp(cachep, slabp);
 		slab_put_obj(cachep, slabp, objp, node);
 		STATS_DEC_ACTIVE(cachep);
-		l3->free_objects++;
+		n->free_objects++;
 		check_slabp(cachep, slabp);
 
 		/* fixup slab chains */
 		if (slabp->inuse == 0) {
-			if (l3->free_objects > l3->free_limit) {
-				l3->free_objects -= cachep->num;
+			if (n->free_objects > n->free_limit) {
+				n->free_objects -= cachep->num;
 				/* No need to drop any previously held
 				 * lock here, even if we have a off-slab slab
 				 * descriptor it is guaranteed to come from
@@ -3634,14 +3511,14 @@ static void free_block(struct kmem_cache *cachep, void **objpp, int nr_objects,
 				 */
 				slab_destroy(cachep, slabp);
 			} else {
-				list_add(&slabp->list, &l3->slabs_free);
+				list_add(&slabp->list, &n->slabs_free);
 			}
 		} else {
 			/* Unconditionally move a slab to the end of the
 			 * partial list on free - maximum time for the
 			 * other objects to be freed, too.
 			 */
-			list_add_tail(&slabp->list, &l3->slabs_partial);
+			list_add_tail(&slabp->list, &n->slabs_partial);
 		}
 	}
 }
@@ -3649,7 +3526,7 @@ static void free_block(struct kmem_cache *cachep, void **objpp, int nr_objects,
 static void cache_flusharray(struct kmem_cache *cachep, struct array_cache *ac)
 {
 	int batchcount;
-	struct kmem_list3 *l3;
+	struct kmem_cache_node *n;
 	int node = numa_mem_id();
 
 	batchcount = ac->batchcount;
@@ -3657,10 +3534,10 @@ static void cache_flusharray(struct kmem_cache *cachep, struct array_cache *ac)
 	BUG_ON(!batchcount || batchcount > ac->avail);
 #endif
 	check_irq_off();
-	l3 = cachep->nodelists[node];
-	spin_lock(&l3->list_lock);
-	if (l3->shared) {
-		struct array_cache *shared_array = l3->shared;
+	n = cachep->node[node];
+	spin_lock(&n->list_lock);
+	if (n->shared) {
+		struct array_cache *shared_array = n->shared;
 		int max = shared_array->limit - shared_array->avail;
 		if (max) {
 			if (batchcount > max)
@@ -3679,8 +3556,8 @@ free_done:
 		int i = 0;
 		struct list_head *p;
 
-		p = l3->slabs_free.next;
-		while (p != &(l3->slabs_free)) {
+		p = n->slabs_free.next;
+		while (p != &(n->slabs_free)) {
 			struct slab *slabp;
 
 			slabp = list_entry(p, struct slab, list);
@@ -3692,7 +3569,7 @@ free_done:
 		STATS_SET_FREEABLE(cachep, i);
 	}
 #endif
-	spin_unlock(&l3->list_lock);
+	spin_unlock(&n->list_lock);
 	ac->avail -= batchcount;
 	memmove(ac->entry, &(ac->entry[batchcount]), sizeof(void *)*ac->avail);
 }
@@ -3802,7 +3679,7 @@ __do_kmalloc_node(size_t size, gfp_t flags, int node, unsigned long caller)
 {
 	struct kmem_cache *cachep;
 
-	cachep = kmem_find_general_cachep(size, flags);
+	cachep = kmalloc_slab(size, flags);
 	if (unlikely(ZERO_OR_NULL_PTR(cachep)))
 		return cachep;
 	return kmem_cache_alloc_node_trace(cachep, flags, node, size);
@@ -3847,7 +3724,7 @@ static __always_inline void *__do_kmalloc(size_t size, gfp_t flags,
 	 * Then kmalloc uses the uninlined functions instead of the inline
 	 * functions.
 	 */
-	cachep = __find_general_cachep(size, flags);
+	cachep = kmalloc_slab(size, flags);
 	if (unlikely(ZERO_OR_NULL_PTR(cachep)))
 		return cachep;
 	ret = slab_alloc(cachep, flags, caller);
@@ -3936,12 +3813,12 @@ void kfree(const void *objp)
 EXPORT_SYMBOL(kfree);
 
 /*
- * This initializes kmem_list3 or resizes various caches for all nodes.
+ * This initializes kmem_cache_node or resizes various caches for all nodes.
  */
 static int alloc_kmemlist(struct kmem_cache *cachep, gfp_t gfp)
 {
 	int node;
-	struct kmem_list3 *l3;
+	struct kmem_cache_node *n;
 	struct array_cache *new_shared;
 	struct array_cache **new_alien = NULL;
 
@@ -3964,43 +3841,43 @@ static int alloc_kmemlist(struct kmem_cache *cachep, gfp_t gfp)
 			}
 		}
 
-		l3 = cachep->nodelists[node];
-		if (l3) {
-			struct array_cache *shared = l3->shared;
+		n = cachep->node[node];
+		if (n) {
+			struct array_cache *shared = n->shared;
 
-			spin_lock_irq(&l3->list_lock);
+			spin_lock_irq(&n->list_lock);
 
 			if (shared)
 				free_block(cachep, shared->entry,
 						shared->avail, node);
 
-			l3->shared = new_shared;
-			if (!l3->alien) {
-				l3->alien = new_alien;
+			n->shared = new_shared;
+			if (!n->alien) {
+				n->alien = new_alien;
 				new_alien = NULL;
 			}
-			l3->free_limit = (1 + nr_cpus_node(node)) *
+			n->free_limit = (1 + nr_cpus_node(node)) *
 					cachep->batchcount + cachep->num;
-			spin_unlock_irq(&l3->list_lock);
+			spin_unlock_irq(&n->list_lock);
 			kfree(shared);
 			free_alien_cache(new_alien);
 			continue;
 		}
-		l3 = kmalloc_node(sizeof(struct kmem_list3), gfp, node);
-		if (!l3) {
+		n = kmalloc_node(sizeof(struct kmem_cache_node), gfp, node);
+		if (!n) {
 			free_alien_cache(new_alien);
 			kfree(new_shared);
 			goto fail;
 		}
 
-		kmem_list3_init(l3);
-		l3->next_reap = jiffies + REAPTIMEOUT_LIST3 +
+		kmem_cache_node_init(n);
+		n->next_reap = jiffies + REAPTIMEOUT_LIST3 +
 				((unsigned long)cachep) % REAPTIMEOUT_LIST3;
-		l3->shared = new_shared;
-		l3->alien = new_alien;
-		l3->free_limit = (1 + nr_cpus_node(node)) *
+		n->shared = new_shared;
+		n->alien = new_alien;
+		n->free_limit = (1 + nr_cpus_node(node)) *
 					cachep->batchcount + cachep->num;
-		cachep->nodelists[node] = l3;
+		cachep->node[node] = n;
 	}
 	return 0;
 
@@ -4009,13 +3886,13 @@ fail:
 		/* Cache is not active yet. Roll back what we did */
 		node--;
 		while (node >= 0) {
-			if (cachep->nodelists[node]) {
-				l3 = cachep->nodelists[node];
+			if (cachep->node[node]) {
+				n = cachep->node[node];
 
-				kfree(l3->shared);
-				free_alien_cache(l3->alien);
-				kfree(l3);
-				cachep->nodelists[node] = NULL;
+				kfree(n->shared);
+				free_alien_cache(n->alien);
+				kfree(n);
+				cachep->node[node] = NULL;
 			}
 			node--;
 		}
@@ -4075,9 +3952,9 @@ static int __do_tune_cpucache(struct kmem_cache *cachep, int limit,
 		struct array_cache *ccold = new->new[i];
 		if (!ccold)
 			continue;
-		spin_lock_irq(&cachep->nodelists[cpu_to_mem(i)]->list_lock);
+		spin_lock_irq(&cachep->node[cpu_to_mem(i)]->list_lock);
 		free_block(cachep, ccold->entry, ccold->avail, cpu_to_mem(i));
-		spin_unlock_irq(&cachep->nodelists[cpu_to_mem(i)]->list_lock);
+		spin_unlock_irq(&cachep->node[cpu_to_mem(i)]->list_lock);
 		kfree(ccold);
 	}
 	kfree(new);
@@ -4178,11 +4055,11 @@ skip_setup:
 }
 
 /*
- * Drain an array if it contains any elements taking the l3 lock only if
- * necessary. Note that the l3 listlock also protects the array_cache
+ * Drain an array if it contains any elements taking the node lock only if
+ * necessary. Note that the node listlock also protects the array_cache
  * if drain_array() is used on the shared array.
  */
-static void drain_array(struct kmem_cache *cachep, struct kmem_list3 *l3,
+static void drain_array(struct kmem_cache *cachep, struct kmem_cache_node *n,
 			 struct array_cache *ac, int force, int node)
 {
 	int tofree;
@@ -4192,7 +4069,7 @@ static void drain_array(struct kmem_cache *cachep, struct kmem_list3 *l3,
 	if (ac->touched && !force) {
 		ac->touched = 0;
 	} else {
-		spin_lock_irq(&l3->list_lock);
+		spin_lock_irq(&n->list_lock);
 		if (ac->avail) {
 			tofree = force ? ac->avail : (ac->limit + 4) / 5;
 			if (tofree > ac->avail)
@@ -4202,7 +4079,7 @@ static void drain_array(struct kmem_cache *cachep, struct kmem_list3 *l3,
 			memmove(ac->entry, &(ac->entry[tofree]),
 				sizeof(void *) * ac->avail);
 		}
-		spin_unlock_irq(&l3->list_lock);
+		spin_unlock_irq(&n->list_lock);
 	}
 }
 
@@ -4221,7 +4098,7 @@ static void drain_array(struct kmem_cache *cachep, struct kmem_list3 *l3,
 static void cache_reap(struct work_struct *w)
 {
 	struct kmem_cache *searchp;
-	struct kmem_list3 *l3;
+	struct kmem_cache_node *n;
 	int node = numa_mem_id();
 	struct delayed_work *work = to_delayed_work(w);
 
@@ -4233,33 +4110,33 @@ static void cache_reap(struct work_struct *w)
 		check_irq_on();
 
 		/*
-		 * We only take the l3 lock if absolutely necessary and we
+		 * We only take the node lock if absolutely necessary and we
 		 * have established with reasonable certainty that
 		 * we can do some work if the lock was obtained.
 		 */
-		l3 = searchp->nodelists[node];
+		n = searchp->node[node];
 
-		reap_alien(searchp, l3);
+		reap_alien(searchp, n);
 
-		drain_array(searchp, l3, cpu_cache_get(searchp), 0, node);
+		drain_array(searchp, n, cpu_cache_get(searchp), 0, node);
 
 		/*
 		 * These are racy checks but it does not matter
 		 * if we skip one check or scan twice.
 		 */
-		if (time_after(l3->next_reap, jiffies))
+		if (time_after(n->next_reap, jiffies))
 			goto next;
 
-		l3->next_reap = jiffies + REAPTIMEOUT_LIST3;
+		n->next_reap = jiffies + REAPTIMEOUT_LIST3;
 
-		drain_array(searchp, l3, l3->shared, 0, node);
+		drain_array(searchp, n, n->shared, 0, node);
 
-		if (l3->free_touched)
-			l3->free_touched = 0;
+		if (n->free_touched)
+			n->free_touched = 0;
 		else {
 			int freed;
 
-			freed = drain_freelist(searchp, l3, (l3->free_limit +
+			freed = drain_freelist(searchp, n, (n->free_limit +
 				5 * searchp->num - 1) / (5 * searchp->num));
 			STATS_ADD_REAPED(searchp, freed);
 		}
@@ -4285,25 +4162,25 @@ void get_slabinfo(struct kmem_cache *cachep, struct slabinfo *sinfo)
 	const char *name;
 	char *error = NULL;
 	int node;
-	struct kmem_list3 *l3;
+	struct kmem_cache_node *n;
 
 	active_objs = 0;
 	num_slabs = 0;
 	for_each_online_node(node) {
-		l3 = cachep->nodelists[node];
-		if (!l3)
+		n = cachep->node[node];
+		if (!n)
 			continue;
 
 		check_irq_on();
-		spin_lock_irq(&l3->list_lock);
+		spin_lock_irq(&n->list_lock);
 
-		list_for_each_entry(slabp, &l3->slabs_full, list) {
+		list_for_each_entry(slabp, &n->slabs_full, list) {
 			if (slabp->inuse != cachep->num && !error)
 				error = "slabs_full accounting error";
 			active_objs += cachep->num;
 			active_slabs++;
 		}
-		list_for_each_entry(slabp, &l3->slabs_partial, list) {
+		list_for_each_entry(slabp, &n->slabs_partial, list) {
 			if (slabp->inuse == cachep->num && !error)
 				error = "slabs_partial inuse accounting error";
 			if (!slabp->inuse && !error)
@@ -4311,16 +4188,16 @@ void get_slabinfo(struct kmem_cache *cachep, struct slabinfo *sinfo)
 			active_objs += slabp->inuse;
 			active_slabs++;
 		}
-		list_for_each_entry(slabp, &l3->slabs_free, list) {
+		list_for_each_entry(slabp, &n->slabs_free, list) {
 			if (slabp->inuse && !error)
 				error = "slabs_free/inuse accounting error";
 			num_slabs++;
 		}
-		free_objects += l3->free_objects;
-		if (l3->shared)
-			shared_avail += l3->shared->avail;
+		free_objects += n->free_objects;
+		if (n->shared)
+			shared_avail += n->shared->avail;
 
-		spin_unlock_irq(&l3->list_lock);
+		spin_unlock_irq(&n->list_lock);
 	}
 	num_slabs += active_slabs;
 	num_objs = num_slabs * cachep->num;
@@ -4346,7 +4223,7 @@ void get_slabinfo(struct kmem_cache *cachep, struct slabinfo *sinfo)
 void slabinfo_show_stats(struct seq_file *m, struct kmem_cache *cachep)
 {
 #if STATS
-	{			/* list3 stats */
+	{			/* node stats */
 		unsigned long high = cachep->high_mark;
 		unsigned long allocs = cachep->num_allocations;
 		unsigned long grown = cachep->grown;
@@ -4499,9 +4376,9 @@ static int leaks_show(struct seq_file *m, void *p)
 {
 	struct kmem_cache *cachep = list_entry(p, struct kmem_cache, list);
 	struct slab *slabp;
-	struct kmem_list3 *l3;
+	struct kmem_cache_node *n;
 	const char *name;
-	unsigned long *n = m->private;
+	unsigned long *x = m->private;
 	int node;
 	int i;
 
@@ -4512,43 +4389,43 @@ static int leaks_show(struct seq_file *m, void *p)
 
 	/* OK, we can do it */
 
-	n[1] = 0;
+	x[1] = 0;
 
 	for_each_online_node(node) {
-		l3 = cachep->nodelists[node];
-		if (!l3)
+		n = cachep->node[node];
+		if (!n)
 			continue;
 
 		check_irq_on();
-		spin_lock_irq(&l3->list_lock);
+		spin_lock_irq(&n->list_lock);
 
-		list_for_each_entry(slabp, &l3->slabs_full, list)
-			handle_slab(n, cachep, slabp);
-		list_for_each_entry(slabp, &l3->slabs_partial, list)
-			handle_slab(n, cachep, slabp);
-		spin_unlock_irq(&l3->list_lock);
+		list_for_each_entry(slabp, &n->slabs_full, list)
+			handle_slab(x, cachep, slabp);
+		list_for_each_entry(slabp, &n->slabs_partial, list)
+			handle_slab(x, cachep, slabp);
+		spin_unlock_irq(&n->list_lock);
 	}
 	name = cachep->name;
-	if (n[0] == n[1]) {
+	if (x[0] == x[1]) {
 		/* Increase the buffer size */
 		mutex_unlock(&slab_mutex);
-		m->private = kzalloc(n[0] * 4 * sizeof(unsigned long), GFP_KERNEL);
+		m->private = kzalloc(x[0] * 4 * sizeof(unsigned long), GFP_KERNEL);
 		if (!m->private) {
 			/* Too bad, we are really out */
-			m->private = n;
+			m->private = x;
 			mutex_lock(&slab_mutex);
 			return -ENOMEM;
 		}
-		*(unsigned long *)m->private = n[0] * 2;
-		kfree(n);
+		*(unsigned long *)m->private = x[0] * 2;
+		kfree(x);
 		mutex_lock(&slab_mutex);
 		/* Now make sure this entry will be retried */
 		m->count = m->size;
 		return 0;
 	}
-	for (i = 0; i < n[1]; i++) {
-		seq_printf(m, "%s: %lu ", name, n[2*i+3]);
-		show_symbol(m, n[2*i+2]);
+	for (i = 0; i < x[1]; i++) {
+		seq_printf(m, "%s: %lu ", name, x[2*i+3]);
+		show_symbol(m, x[2*i+2]);
 		seq_putc(m, '\n');
 	}
 
diff --git a/mm/slab.h b/mm/slab.h
index 34a98d6..f96b49e 100644
--- a/mm/slab.h
+++ b/mm/slab.h
@@ -16,7 +16,7 @@ enum slab_state {
 	DOWN,			/* No slab functionality yet */
 	PARTIAL,		/* SLUB: kmem_cache_node available */
 	PARTIAL_ARRAYCACHE,	/* SLAB: kmalloc size for arraycache available */
-	PARTIAL_L3,		/* SLAB: kmalloc size for l3 struct available */
+	PARTIAL_NODE,		/* SLAB: kmalloc size for node struct available */
 	UP,			/* Slab caches usable but not all extras yet */
 	FULL			/* Everything is working */
 };
@@ -35,6 +35,15 @@ extern struct kmem_cache *kmem_cache;
 unsigned long calculate_alignment(unsigned long flags,
 		unsigned long align, unsigned long size);
 
+#ifndef CONFIG_SLOB
+/* Kmalloc array related functions */
+void create_kmalloc_caches(unsigned long);
+
+/* Find the kmalloc slab corresponding for a certain size */
+struct kmem_cache *kmalloc_slab(size_t, gfp_t);
+#endif
+
+
 /* Functions provided by the slab allocators */
 extern int __kmem_cache_create(struct kmem_cache *, unsigned long flags);
 
@@ -230,3 +239,35 @@ static inline struct kmem_cache *cache_from_obj(struct kmem_cache *s, void *x)
 	return s;
 }
 #endif
+
+
+/*
+ * The slab lists for all objects.
+ */
+struct kmem_cache_node {
+	spinlock_t list_lock;
+
+#ifdef CONFIG_SLAB
+	struct list_head slabs_partial;	/* partial list first, better asm code */
+	struct list_head slabs_full;
+	struct list_head slabs_free;
+	unsigned long free_objects;
+	unsigned int free_limit;
+	unsigned int colour_next;	/* Per-node cache coloring */
+	struct array_cache *shared;	/* shared per node */
+	struct array_cache **alien;	/* on other nodes */
+	unsigned long next_reap;	/* updated without locking */
+	int free_touched;		/* updated without locking */
+#endif
+
+#ifdef CONFIG_SLUB
+	unsigned long nr_partial;
+	struct list_head partial;
+#ifdef CONFIG_SLUB_DEBUG
+	atomic_long_t nr_slabs;
+	atomic_long_t total_objects;
+	struct list_head full;
+#endif
+#endif
+
+};
diff --git a/mm/slab_common.c b/mm/slab_common.c
index 3f3cd97..2f0e7d5 100644
--- a/mm/slab_common.c
+++ b/mm/slab_common.c
@@ -299,7 +299,7 @@ void __init create_boot_cache(struct kmem_cache *s, const char *name, size_t siz
 	err = __kmem_cache_create(s, flags);
 
 	if (err)
-		panic("Creation of kmalloc slab %s size=%zd failed. Reason %d\n",
+		panic("Creation of kmalloc slab %s size=%zu failed. Reason %d\n",
 					name, size, err);
 
 	s->refcount = -1;	/* Exempt from merging for now */
@@ -319,6 +319,169 @@ struct kmem_cache *__init create_kmalloc_cache(const char *name, size_t size,
 	return s;
 }
 
+struct kmem_cache *kmalloc_caches[KMALLOC_SHIFT_HIGH + 1];
+EXPORT_SYMBOL(kmalloc_caches);
+
+#ifdef CONFIG_ZONE_DMA
+struct kmem_cache *kmalloc_dma_caches[KMALLOC_SHIFT_HIGH + 1];
+EXPORT_SYMBOL(kmalloc_dma_caches);
+#endif
+
+/*
+ * Conversion table for small slabs sizes / 8 to the index in the
+ * kmalloc array. This is necessary for slabs < 192 since we have non power
+ * of two cache sizes there. The size of larger slabs can be determined using
+ * fls.
+ */
+static s8 size_index[24] = {
+	3,	/* 8 */
+	4,	/* 16 */
+	5,	/* 24 */
+	5,	/* 32 */
+	6,	/* 40 */
+	6,	/* 48 */
+	6,	/* 56 */
+	6,	/* 64 */
+	1,	/* 72 */
+	1,	/* 80 */
+	1,	/* 88 */
+	1,	/* 96 */
+	7,	/* 104 */
+	7,	/* 112 */
+	7,	/* 120 */
+	7,	/* 128 */
+	2,	/* 136 */
+	2,	/* 144 */
+	2,	/* 152 */
+	2,	/* 160 */
+	2,	/* 168 */
+	2,	/* 176 */
+	2,	/* 184 */
+	2	/* 192 */
+};
+
+static inline int size_index_elem(size_t bytes)
+{
+	return (bytes - 1) / 8;
+}
+
+/*
+ * Find the kmem_cache structure that serves a given size of
+ * allocation
+ */
+struct kmem_cache *kmalloc_slab(size_t size, gfp_t flags)
+{
+	int index;
+
+	if (size <= 192) {
+		if (!size)
+			return ZERO_SIZE_PTR;
+
+		index = size_index[size_index_elem(size)];
+	} else
+		index = fls(size - 1);
+
+#ifdef CONFIG_ZONE_DMA
+	if (unlikely((flags & GFP_DMA)))
+		return kmalloc_dma_caches[index];
+
+#endif
+	return kmalloc_caches[index];
+}
+
+/*
+ * Create the kmalloc array. Some of the regular kmalloc arrays
+ * may already have been created because they were needed to
+ * enable allocations for slab creation.
+ */
+void __init create_kmalloc_caches(unsigned long flags)
+{
+	int i;
+
+	/*
+	 * Patch up the size_index table if we have strange large alignment
+	 * requirements for the kmalloc array. This is only the case for
+	 * MIPS it seems. The standard arches will not generate any code here.
+	 *
+	 * Largest permitted alignment is 256 bytes due to the way we
+	 * handle the index determination for the smaller caches.
+	 *
+	 * Make sure that nothing crazy happens if someone starts tinkering
+	 * around with ARCH_KMALLOC_MINALIGN
+	 */
+	BUILD_BUG_ON(KMALLOC_MIN_SIZE > 256 ||
+		(KMALLOC_MIN_SIZE & (KMALLOC_MIN_SIZE - 1)));
+
+	for (i = 8; i < KMALLOC_MIN_SIZE; i += 8) {
+		int elem = size_index_elem(i);
+
+		if (elem >= ARRAY_SIZE(size_index))
+			break;
+		size_index[elem] = KMALLOC_SHIFT_LOW;
+	}
+
+	if (KMALLOC_MIN_SIZE >= 64) {
+		/*
+		 * The 96 byte size cache is not used if the alignment
+		 * is 64 byte.
+		 */
+		for (i = 64 + 8; i <= 96; i += 8)
+			size_index[size_index_elem(i)] = 7;
+
+	}
+
+	if (KMALLOC_MIN_SIZE >= 128) {
+		/*
+		 * The 192 byte sized cache is not used if the alignment
+		 * is 128 byte. Redirect kmalloc to use the 256 byte cache
+		 * instead.
+		 */
+		for (i = 128 + 8; i <= 192; i += 8)
+			size_index[size_index_elem(i)] = 8;
+	}
+	/* Caches that are not of the two-to-the-power-of size */
+	if (KMALLOC_MIN_SIZE <= 32 && !kmalloc_caches[1])
+		kmalloc_caches[1] = create_kmalloc_cache(NULL, 96, flags);
+
+	if (KMALLOC_MIN_SIZE <= 64 && !kmalloc_caches[2])
+		kmalloc_caches[2] = create_kmalloc_cache(NULL, 192, flags);
+
+	for (i = KMALLOC_SHIFT_LOW; i <= KMALLOC_SHIFT_HIGH; i++)
+		if (!kmalloc_caches[i])
+			kmalloc_caches[i] = create_kmalloc_cache(NULL,
+							1 << i, flags);
+
+	/* Kmalloc array is now usable */
+	slab_state = UP;
+
+	for (i = 0; i <= KMALLOC_SHIFT_HIGH; i++) {
+		struct kmem_cache *s = kmalloc_caches[i];
+		char *n;
+
+		if (s) {
+			n = kasprintf(GFP_NOWAIT, "kmalloc-%d", kmalloc_size(i));
+
+			BUG_ON(!n);
+			s->name = n;
+		}
+	}
+
+#ifdef CONFIG_ZONE_DMA
+	for (i = 0; i <= KMALLOC_SHIFT_HIGH; i++) {
+		struct kmem_cache *s = kmalloc_caches[i];
+
+		if (s) {
+			int size = kmalloc_size(i);
+			char *n = kasprintf(GFP_NOWAIT,
+				 "dma-kmalloc-%d", size);
+
+			BUG_ON(!n);
+			kmalloc_dma_caches[i] = create_kmalloc_cache(n,
+				size, SLAB_CACHE_DMA | flags);
+		}
+	}
+#endif
+}
 #endif /* !CONFIG_SLOB */
 
 
diff --git a/mm/slub.c b/mm/slub.c
index 4aec537..4ef6633 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -1005,7 +1005,7 @@ static inline void inc_slabs_node(struct kmem_cache *s, int node, int objects)
 	 * dilemma by deferring the increment of the count during
 	 * bootstrap (see early_kmem_cache_node_alloc).
 	 */
-	if (n) {
+	if (likely(n)) {
 		atomic_long_inc(&n->nr_slabs);
 		atomic_long_add(objects, &n->total_objects);
 	}
@@ -1493,7 +1493,7 @@ static inline void remove_partial(struct kmem_cache_node *n,
  */
 static inline void *acquire_slab(struct kmem_cache *s,
 		struct kmem_cache_node *n, struct page *page,
-		int mode)
+		int mode, int *objects)
 {
 	void *freelist;
 	unsigned long counters;
@@ -1507,6 +1507,7 @@ static inline void *acquire_slab(struct kmem_cache *s,
 	freelist = page->freelist;
 	counters = page->counters;
 	new.counters = counters;
+	*objects = new.objects - new.inuse;
 	if (mode) {
 		new.inuse = page->objects;
 		new.freelist = NULL;
@@ -1528,7 +1529,7 @@ static inline void *acquire_slab(struct kmem_cache *s,
 	return freelist;
 }
 
-static int put_cpu_partial(struct kmem_cache *s, struct page *page, int drain);
+static void put_cpu_partial(struct kmem_cache *s, struct page *page, int drain);
 static inline bool pfmemalloc_match(struct page *page, gfp_t gfpflags);
 
 /*
@@ -1539,6 +1540,8 @@ static void *get_partial_node(struct kmem_cache *s, struct kmem_cache_node *n,
 {
 	struct page *page, *page2;
 	void *object = NULL;
+	int available = 0;
+	int objects;
 
 	/*
 	 * Racy check. If we mistakenly see no partial slabs then we
@@ -1552,22 +1555,21 @@ static void *get_partial_node(struct kmem_cache *s, struct kmem_cache_node *n,
 	spin_lock(&n->list_lock);
 	list_for_each_entry_safe(page, page2, &n->partial, lru) {
 		void *t;
-		int available;
 
 		if (!pfmemalloc_match(page, flags))
 			continue;
 
-		t = acquire_slab(s, n, page, object == NULL);
+		t = acquire_slab(s, n, page, object == NULL, &objects);
 		if (!t)
 			break;
 
+		available += objects;
 		if (!object) {
 			c->page = page;
 			stat(s, ALLOC_FROM_PARTIAL);
 			object = t;
-			available =  page->objects - page->inuse;
 		} else {
-			available = put_cpu_partial(s, page, 0);
+			put_cpu_partial(s, page, 0);
 			stat(s, CPU_PARTIAL_NODE);
 		}
 		if (kmem_cache_debug(s) || available > s->cpu_partial / 2)
@@ -1946,7 +1948,7 @@ static void unfreeze_partials(struct kmem_cache *s,
  * If we did not find a slot then simply move all the partials to the
  * per node partial list.
  */
-static int put_cpu_partial(struct kmem_cache *s, struct page *page, int drain)
+static void put_cpu_partial(struct kmem_cache *s, struct page *page, int drain)
 {
 	struct page *oldpage;
 	int pages;
@@ -1984,7 +1986,6 @@ static int put_cpu_partial(struct kmem_cache *s, struct page *page, int drain)
 		page->next = oldpage;
 
 	} while (this_cpu_cmpxchg(s->cpu_slab->partial, oldpage, page) != oldpage);
-	return pobjects;
 }
 
 static inline void flush_slab(struct kmem_cache *s, struct kmem_cache_cpu *c)
@@ -2775,7 +2776,7 @@ init_kmem_cache_node(struct kmem_cache_node *n)
 static inline int alloc_kmem_cache_cpus(struct kmem_cache *s)
 {
 	BUILD_BUG_ON(PERCPU_DYNAMIC_EARLY_SIZE <
-			SLUB_PAGE_SHIFT * sizeof(struct kmem_cache_cpu));
+			KMALLOC_SHIFT_HIGH * sizeof(struct kmem_cache_cpu));
 
 	/*
 	 * Must align to double word boundary for the double cmpxchg
@@ -2982,7 +2983,7 @@ static int calculate_sizes(struct kmem_cache *s, int forced_order)
 		s->allocflags |= __GFP_COMP;
 
 	if (s->flags & SLAB_CACHE_DMA)
-		s->allocflags |= SLUB_DMA;
+		s->allocflags |= GFP_DMA;
 
 	if (s->flags & SLAB_RECLAIM_ACCOUNT)
 		s->allocflags |= __GFP_RECLAIMABLE;
@@ -3174,13 +3175,6 @@ int __kmem_cache_shutdown(struct kmem_cache *s)
  *		Kmalloc subsystem
  *******************************************************************/
 
-struct kmem_cache *kmalloc_caches[SLUB_PAGE_SHIFT];
-EXPORT_SYMBOL(kmalloc_caches);
-
-#ifdef CONFIG_ZONE_DMA
-static struct kmem_cache *kmalloc_dma_caches[SLUB_PAGE_SHIFT];
-#endif
-
 static int __init setup_slub_min_order(char *str)
 {
 	get_option(&str, &slub_min_order);
@@ -3217,73 +3211,15 @@ static int __init setup_slub_nomerge(char *str)
 
 __setup("slub_nomerge", setup_slub_nomerge);
 
-/*
- * Conversion table for small slabs sizes / 8 to the index in the
- * kmalloc array. This is necessary for slabs < 192 since we have non power
- * of two cache sizes there. The size of larger slabs can be determined using
- * fls.
- */
-static s8 size_index[24] = {
-	3,	/* 8 */
-	4,	/* 16 */
-	5,	/* 24 */
-	5,	/* 32 */
-	6,	/* 40 */
-	6,	/* 48 */
-	6,	/* 56 */
-	6,	/* 64 */
-	1,	/* 72 */
-	1,	/* 80 */
-	1,	/* 88 */
-	1,	/* 96 */
-	7,	/* 104 */
-	7,	/* 112 */
-	7,	/* 120 */
-	7,	/* 128 */
-	2,	/* 136 */
-	2,	/* 144 */
-	2,	/* 152 */
-	2,	/* 160 */
-	2,	/* 168 */
-	2,	/* 176 */
-	2,	/* 184 */
-	2	/* 192 */
-};
-
-static inline int size_index_elem(size_t bytes)
-{
-	return (bytes - 1) / 8;
-}
-
-static struct kmem_cache *get_slab(size_t size, gfp_t flags)
-{
-	int index;
-
-	if (size <= 192) {
-		if (!size)
-			return ZERO_SIZE_PTR;
-
-		index = size_index[size_index_elem(size)];
-	} else
-		index = fls(size - 1);
-
-#ifdef CONFIG_ZONE_DMA
-	if (unlikely((flags & SLUB_DMA)))
-		return kmalloc_dma_caches[index];
-
-#endif
-	return kmalloc_caches[index];
-}
-
 void *__kmalloc(size_t size, gfp_t flags)
 {
 	struct kmem_cache *s;
 	void *ret;
 
-	if (unlikely(size > SLUB_MAX_SIZE))
+	if (unlikely(size > KMALLOC_MAX_CACHE_SIZE))
 		return kmalloc_large(size, flags);
 
-	s = get_slab(size, flags);
+	s = kmalloc_slab(size, flags);
 
 	if (unlikely(ZERO_OR_NULL_PTR(s)))
 		return s;
@@ -3316,7 +3252,7 @@ void *__kmalloc_node(size_t size, gfp_t flags, int node)
 	struct kmem_cache *s;
 	void *ret;
 
-	if (unlikely(size > SLUB_MAX_SIZE)) {
+	if (unlikely(size > KMALLOC_MAX_CACHE_SIZE)) {
 		ret = kmalloc_large_node(size, flags, node);
 
 		trace_kmalloc_node(_RET_IP_, ret,
@@ -3326,7 +3262,7 @@ void *__kmalloc_node(size_t size, gfp_t flags, int node)
 		return ret;
 	}
 
-	s = get_slab(size, flags);
+	s = kmalloc_slab(size, flags);
 
 	if (unlikely(ZERO_OR_NULL_PTR(s)))
 		return s;
@@ -3617,6 +3553,12 @@ static struct kmem_cache * __init bootstrap(struct kmem_cache *static_cache)
 
 	memcpy(s, static_cache, kmem_cache->object_size);
 
+	/*
+	 * This runs very early, and only the boot processor is supposed to be
+	 * up.  Even if it weren't true, IRQs are not up so we couldn't fire
+	 * IPIs around.
+	 */
+	__flush_cpu_slab(s, smp_processor_id());
 	for_each_node_state(node, N_NORMAL_MEMORY) {
 		struct kmem_cache_node *n = get_node(s, node);
 		struct page *p;
@@ -3639,8 +3581,6 @@ void __init kmem_cache_init(void)
 {
 	static __initdata struct kmem_cache boot_kmem_cache,
 		boot_kmem_cache_node;
-	int i;
-	int caches = 2;
 
 	if (debug_guardpage_minorder())
 		slub_max_order = 0;
@@ -3671,103 +3611,16 @@ void __init kmem_cache_init(void)
 	kmem_cache_node = bootstrap(&boot_kmem_cache_node);
 
 	/* Now we can use the kmem_cache to allocate kmalloc slabs */
-
-	/*
-	 * Patch up the size_index table if we have strange large alignment
-	 * requirements for the kmalloc array. This is only the case for
-	 * MIPS it seems. The standard arches will not generate any code here.
-	 *
-	 * Largest permitted alignment is 256 bytes due to the way we
-	 * handle the index determination for the smaller caches.
-	 *
-	 * Make sure that nothing crazy happens if someone starts tinkering
-	 * around with ARCH_KMALLOC_MINALIGN
-	 */
-	BUILD_BUG_ON(KMALLOC_MIN_SIZE > 256 ||
-		(KMALLOC_MIN_SIZE & (KMALLOC_MIN_SIZE - 1)));
-
-	for (i = 8; i < KMALLOC_MIN_SIZE; i += 8) {
-		int elem = size_index_elem(i);
-		if (elem >= ARRAY_SIZE(size_index))
-			break;
-		size_index[elem] = KMALLOC_SHIFT_LOW;
-	}
-
-	if (KMALLOC_MIN_SIZE == 64) {
-		/*
-		 * The 96 byte size cache is not used if the alignment
-		 * is 64 byte.
-		 */
-		for (i = 64 + 8; i <= 96; i += 8)
-			size_index[size_index_elem(i)] = 7;
-	} else if (KMALLOC_MIN_SIZE == 128) {
-		/*
-		 * The 192 byte sized cache is not used if the alignment
-		 * is 128 byte. Redirect kmalloc to use the 256 byte cache
-		 * instead.
-		 */
-		for (i = 128 + 8; i <= 192; i += 8)
-			size_index[size_index_elem(i)] = 8;
-	}
-
-	/* Caches that are not of the two-to-the-power-of size */
-	if (KMALLOC_MIN_SIZE <= 32) {
-		kmalloc_caches[1] = create_kmalloc_cache("kmalloc-96", 96, 0);
-		caches++;
-	}
-
-	if (KMALLOC_MIN_SIZE <= 64) {
-		kmalloc_caches[2] = create_kmalloc_cache("kmalloc-192", 192, 0);
-		caches++;
-	}
-
-	for (i = KMALLOC_SHIFT_LOW; i < SLUB_PAGE_SHIFT; i++) {
-		kmalloc_caches[i] = create_kmalloc_cache("kmalloc", 1 << i, 0);
-		caches++;
-	}
-
-	slab_state = UP;
-
-	/* Provide the correct kmalloc names now that the caches are up */
-	if (KMALLOC_MIN_SIZE <= 32) {
-		kmalloc_caches[1]->name = kstrdup(kmalloc_caches[1]->name, GFP_NOWAIT);
-		BUG_ON(!kmalloc_caches[1]->name);
-	}
-
-	if (KMALLOC_MIN_SIZE <= 64) {
-		kmalloc_caches[2]->name = kstrdup(kmalloc_caches[2]->name, GFP_NOWAIT);
-		BUG_ON(!kmalloc_caches[2]->name);
-	}
-
-	for (i = KMALLOC_SHIFT_LOW; i < SLUB_PAGE_SHIFT; i++) {
-		char *s = kasprintf(GFP_NOWAIT, "kmalloc-%d", 1 << i);
-
-		BUG_ON(!s);
-		kmalloc_caches[i]->name = s;
-	}
+	create_kmalloc_caches(0);
 
 #ifdef CONFIG_SMP
 	register_cpu_notifier(&slab_notifier);
 #endif
 
-#ifdef CONFIG_ZONE_DMA
-	for (i = 0; i < SLUB_PAGE_SHIFT; i++) {
-		struct kmem_cache *s = kmalloc_caches[i];
-
-		if (s && s->size) {
-			char *name = kasprintf(GFP_NOWAIT,
-				 "dma-kmalloc-%d", s->object_size);
-
-			BUG_ON(!name);
-			kmalloc_dma_caches[i] = create_kmalloc_cache(name,
-				s->object_size, SLAB_CACHE_DMA);
-		}
-	}
-#endif
 	printk(KERN_INFO
-		"SLUB: Genslabs=%d, HWalign=%d, Order=%d-%d, MinObjects=%d,"
+		"SLUB: HWalign=%d, Order=%d-%d, MinObjects=%d,"
 		" CPUs=%d, Nodes=%d\n",
-		caches, cache_line_size(),
+		cache_line_size(),
 		slub_min_order, slub_max_order, slub_min_objects,
 		nr_cpu_ids, nr_node_ids);
 }
@@ -3930,10 +3783,10 @@ void *__kmalloc_track_caller(size_t size, gfp_t gfpflags, unsigned long caller)
 	struct kmem_cache *s;
 	void *ret;
 
-	if (unlikely(size > SLUB_MAX_SIZE))
+	if (unlikely(size > KMALLOC_MAX_CACHE_SIZE))
 		return kmalloc_large(size, gfpflags);
 
-	s = get_slab(size, gfpflags);
+	s = kmalloc_slab(size, gfpflags);
 
 	if (unlikely(ZERO_OR_NULL_PTR(s)))
 		return s;
@@ -3953,7 +3806,7 @@ void *__kmalloc_node_track_caller(size_t size, gfp_t gfpflags,
 	struct kmem_cache *s;
 	void *ret;
 
-	if (unlikely(size > SLUB_MAX_SIZE)) {
+	if (unlikely(size > KMALLOC_MAX_CACHE_SIZE)) {
 		ret = kmalloc_large_node(size, gfpflags, node);
 
 		trace_kmalloc_node(caller, ret,
@@ -3963,7 +3816,7 @@ void *__kmalloc_node_track_caller(size_t size, gfp_t gfpflags,
 		return ret;
 	}
 
-	s = get_slab(size, gfpflags);
+	s = kmalloc_slab(size, gfpflags);
 
 	if (unlikely(ZERO_OR_NULL_PTR(s)))
 		return s;
@@ -4312,7 +4165,7 @@ static void resiliency_test(void)
 {
 	u8 *p;
 
-	BUILD_BUG_ON(KMALLOC_MIN_SIZE > 16 || SLUB_PAGE_SHIFT < 10);
+	BUILD_BUG_ON(KMALLOC_MIN_SIZE > 16 || KMALLOC_SHIFT_HIGH < 10);
 
 	printk(KERN_ERR "SLUB resiliency testing\n");
 	printk(KERN_ERR "-----------------------\n");
diff --git a/mm/sparse-vmemmap.c b/mm/sparse-vmemmap.c
index 1b7e22a..27eeab3 100644
--- a/mm/sparse-vmemmap.c
+++ b/mm/sparse-vmemmap.c
@@ -53,10 +53,12 @@ void * __meminit vmemmap_alloc_block(unsigned long size, int node)
 		struct page *page;
 
 		if (node_state(node, N_HIGH_MEMORY))
-			page = alloc_pages_node(node,
-				GFP_KERNEL | __GFP_ZERO, get_order(size));
+			page = alloc_pages_node(
+				node, GFP_KERNEL | __GFP_ZERO | __GFP_REPEAT,
+				get_order(size));
 		else
-			page = alloc_pages(GFP_KERNEL | __GFP_ZERO,
+			page = alloc_pages(
+				GFP_KERNEL | __GFP_ZERO | __GFP_REPEAT,
 				get_order(size));
 		if (page)
 			return page_address(page);
@@ -145,11 +147,10 @@ pgd_t * __meminit vmemmap_pgd_populate(unsigned long addr, int node)
 	return pgd;
 }
 
-int __meminit vmemmap_populate_basepages(struct page *start_page,
-						unsigned long size, int node)
+int __meminit vmemmap_populate_basepages(unsigned long start,
+					 unsigned long end, int node)
 {
-	unsigned long addr = (unsigned long)start_page;
-	unsigned long end = (unsigned long)(start_page + size);
+	unsigned long addr = start;
 	pgd_t *pgd;
 	pud_t *pud;
 	pmd_t *pmd;
@@ -176,9 +177,15 @@ int __meminit vmemmap_populate_basepages(struct page *start_page,
 
 struct page * __meminit sparse_mem_map_populate(unsigned long pnum, int nid)
 {
-	struct page *map = pfn_to_page(pnum * PAGES_PER_SECTION);
-	int error = vmemmap_populate(map, PAGES_PER_SECTION, nid);
-	if (error)
+	unsigned long start;
+	unsigned long end;
+	struct page *map;
+
+	map = pfn_to_page(pnum * PAGES_PER_SECTION);
+	start = (unsigned long)map;
+	end = (unsigned long)(map + PAGES_PER_SECTION);
+
+	if (vmemmap_populate(start, end, nid))
 		return NULL;
 
 	return map;
diff --git a/mm/sparse.c b/mm/sparse.c
index 7ca6dc8..a37be5f 100644
--- a/mm/sparse.c
+++ b/mm/sparse.c
@@ -615,11 +615,17 @@ static inline struct page *kmalloc_section_memmap(unsigned long pnum, int nid,
 }
 static void __kfree_section_memmap(struct page *memmap, unsigned long nr_pages)
 {
-	vmemmap_free(memmap, nr_pages);
+	unsigned long start = (unsigned long)memmap;
+	unsigned long end = (unsigned long)(memmap + nr_pages);
+
+	vmemmap_free(start, end);
 }
 static void free_map_bootmem(struct page *memmap, unsigned long nr_pages)
 {
-	vmemmap_free(memmap, nr_pages);
+	unsigned long start = (unsigned long)memmap;
+	unsigned long end = (unsigned long)(memmap + nr_pages);
+
+	vmemmap_free(start, end);
 }
 #else
 static struct page *__kmalloc_section_memmap(unsigned long nr_pages)
diff --git a/mm/swap.c b/mm/swap.c
index 8a529a0..92a9be5 100644
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -30,6 +30,7 @@
 #include <linux/backing-dev.h>
 #include <linux/memcontrol.h>
 #include <linux/gfp.h>
+#include <linux/uio.h>
 
 #include "internal.h"
 
diff --git a/mm/swapfile.c b/mm/swapfile.c
index a1f7772..6c340d9 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -1509,8 +1509,7 @@ static int setup_swap_extents(struct swap_info_struct *sis, sector_t *span)
 }
 
 static void _enable_swap_info(struct swap_info_struct *p, int prio,
-				unsigned char *swap_map,
-				unsigned long *frontswap_map)
+				unsigned char *swap_map)
 {
 	int i, prev;
 
@@ -1519,7 +1518,6 @@ static void _enable_swap_info(struct swap_info_struct *p, int prio,
 	else
 		p->prio = --least_priority;
 	p->swap_map = swap_map;
-	frontswap_map_set(p, frontswap_map);
 	p->flags |= SWP_WRITEOK;
 	atomic_long_add(p->pages, &nr_swap_pages);
 	total_swap_pages += p->pages;
@@ -1542,10 +1540,10 @@ static void enable_swap_info(struct swap_info_struct *p, int prio,
 				unsigned char *swap_map,
 				unsigned long *frontswap_map)
 {
+	frontswap_init(p->type, frontswap_map);
 	spin_lock(&swap_lock);
 	spin_lock(&p->lock);
-	_enable_swap_info(p, prio, swap_map, frontswap_map);
-	frontswap_init(p->type);
+	 _enable_swap_info(p, prio, swap_map);
 	spin_unlock(&p->lock);
 	spin_unlock(&swap_lock);
 }
@@ -1554,7 +1552,7 @@ static void reinsert_swap_info(struct swap_info_struct *p)
 {
 	spin_lock(&swap_lock);
 	spin_lock(&p->lock);
-	_enable_swap_info(p, p->prio, p->swap_map, frontswap_map_get(p));
+	_enable_swap_info(p, p->prio, p->swap_map);
 	spin_unlock(&p->lock);
 	spin_unlock(&swap_lock);
 }
@@ -1563,6 +1561,7 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
 {
 	struct swap_info_struct *p = NULL;
 	unsigned char *swap_map;
+	unsigned long *frontswap_map;
 	struct file *swap_file, *victim;
 	struct address_space *mapping;
 	struct inode *inode;
@@ -1662,12 +1661,14 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
 	swap_map = p->swap_map;
 	p->swap_map = NULL;
 	p->flags = 0;
-	frontswap_invalidate_area(type);
+	frontswap_map = frontswap_map_get(p);
+	frontswap_map_set(p, NULL);
 	spin_unlock(&p->lock);
 	spin_unlock(&swap_lock);
+	frontswap_invalidate_area(type);
 	mutex_unlock(&swapon_mutex);
 	vfree(swap_map);
-	vfree(frontswap_map_get(p));
+	vfree(frontswap_map);
 	/* Destroy swap account informatin */
 	swap_cgroup_swapoff(type);
 
@@ -2120,7 +2121,7 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
 	if (p->bdev) {
 		if (blk_queue_nonrot(bdev_get_queue(p->bdev))) {
 			p->flags |= SWP_SOLIDSTATE;
-			p->cluster_next = 1 + (random32() % p->highest_bit);
+			p->cluster_next = 1 + (prandom_u32() % p->highest_bit);
 		}
 		if ((swap_flags & SWAP_FLAG_DISCARD) && discard_swap(p) == 0)
 			p->flags |= SWP_DISCARDABLE;
diff --git a/mm/util.c b/mm/util.c
index ab1424d..7441c41 100644
--- a/mm/util.c
+++ b/mm/util.c
@@ -295,7 +295,6 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
 {
 	mm->mmap_base = TASK_UNMAPPED_BASE;
 	mm->get_unmapped_area = arch_get_unmapped_area;
-	mm->unmap_area = arch_unmap_area;
 }
 #endif
 
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 0f751f2..72043d6 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -249,19 +249,9 @@ EXPORT_SYMBOL(vmalloc_to_pfn);
 #define VM_LAZY_FREEING	0x02
 #define VM_VM_AREA	0x04
 
-struct vmap_area {
-	unsigned long va_start;
-	unsigned long va_end;
-	unsigned long flags;
-	struct rb_node rb_node;		/* address sorted rbtree */
-	struct list_head list;		/* address sorted list */
-	struct list_head purge_list;	/* "lazy purge" list */
-	struct vm_struct *vm;
-	struct rcu_head rcu_head;
-};
-
 static DEFINE_SPINLOCK(vmap_area_lock);
-static LIST_HEAD(vmap_area_list);
+/* Export for kexec only */
+LIST_HEAD(vmap_area_list);
 static struct rb_root vmap_area_root = RB_ROOT;
 
 /* The vmap cache globals are protected by vmap_area_lock */
@@ -313,7 +303,7 @@ static void __insert_vmap_area(struct vmap_area *va)
 	rb_link_node(&va->rb_node, parent, p);
 	rb_insert_color(&va->rb_node, &vmap_area_root);
 
-	/* address-sort this list so it is usable like the vmlist */
+	/* address-sort this list */
 	tmp = rb_prev(&va->rb_node);
 	if (tmp) {
 		struct vmap_area *prev;
@@ -1125,6 +1115,7 @@ void *vm_map_ram(struct page **pages, unsigned int count, int node, pgprot_t pro
 }
 EXPORT_SYMBOL(vm_map_ram);
 
+static struct vm_struct *vmlist __initdata;
 /**
  * vm_area_add_early - add vmap area early during boot
  * @vm: vm_struct to add
@@ -1283,41 +1274,35 @@ int map_vm_area(struct vm_struct *area, pgprot_t prot, struct page ***pages)
 }
 EXPORT_SYMBOL_GPL(map_vm_area);
 
-/*** Old vmalloc interfaces ***/
-DEFINE_RWLOCK(vmlist_lock);
-struct vm_struct *vmlist;
-
 static void setup_vmalloc_vm(struct vm_struct *vm, struct vmap_area *va,
 			      unsigned long flags, const void *caller)
 {
+	spin_lock(&vmap_area_lock);
 	vm->flags = flags;
 	vm->addr = (void *)va->va_start;
 	vm->size = va->va_end - va->va_start;
 	vm->caller = caller;
 	va->vm = vm;
 	va->flags |= VM_VM_AREA;
+	spin_unlock(&vmap_area_lock);
 }
 
-static void insert_vmalloc_vmlist(struct vm_struct *vm)
+static void clear_vm_unlist(struct vm_struct *vm)
 {
-	struct vm_struct *tmp, **p;
-
+	/*
+	 * Before removing VM_UNLIST,
+	 * we should make sure that vm has proper values.
+	 * Pair with smp_rmb() in show_numa_info().
+	 */
+	smp_wmb();
 	vm->flags &= ~VM_UNLIST;
-	write_lock(&vmlist_lock);
-	for (p = &vmlist; (tmp = *p) != NULL; p = &tmp->next) {
-		if (tmp->addr >= vm->addr)
-			break;
-	}
-	vm->next = *p;
-	*p = vm;
-	write_unlock(&vmlist_lock);
 }
 
 static void insert_vmalloc_vm(struct vm_struct *vm, struct vmap_area *va,
 			      unsigned long flags, const void *caller)
 {
 	setup_vmalloc_vm(vm, va, flags, caller);
-	insert_vmalloc_vmlist(vm);
+	clear_vm_unlist(vm);
 }
 
 static struct vm_struct *__get_vm_area_node(unsigned long size,
@@ -1360,10 +1345,9 @@ static struct vm_struct *__get_vm_area_node(unsigned long size,
 
 	/*
 	 * When this function is called from __vmalloc_node_range,
-	 * we do not add vm_struct to vmlist here to avoid
-	 * accessing uninitialized members of vm_struct such as
-	 * pages and nr_pages fields. They will be set later.
-	 * To distinguish it from others, we use a VM_UNLIST flag.
+	 * we add VM_UNLIST flag to avoid accessing uninitialized
+	 * members of vm_struct such as pages and nr_pages fields.
+	 * They will be set later.
 	 */
 	if (flags & VM_UNLIST)
 		setup_vmalloc_vm(area, va, flags, caller);
@@ -1447,19 +1431,10 @@ struct vm_struct *remove_vm_area(const void *addr)
 	if (va && va->flags & VM_VM_AREA) {
 		struct vm_struct *vm = va->vm;
 
-		if (!(vm->flags & VM_UNLIST)) {
-			struct vm_struct *tmp, **p;
-			/*
-			 * remove from list and disallow access to
-			 * this vm_struct before unmap. (address range
-			 * confliction is maintained by vmap.)
-			 */
-			write_lock(&vmlist_lock);
-			for (p = &vmlist; (tmp = *p) != vm; p = &tmp->next)
-				;
-			*p = tmp->next;
-			write_unlock(&vmlist_lock);
-		}
+		spin_lock(&vmap_area_lock);
+		va->vm = NULL;
+		va->flags &= ~VM_VM_AREA;
+		spin_unlock(&vmap_area_lock);
 
 		vmap_debug_free_range(va->va_start, va->va_end);
 		free_unmap_vmap_area(va);
@@ -1680,10 +1655,11 @@ void *__vmalloc_node_range(unsigned long size, unsigned long align,
 		return NULL;
 
 	/*
-	 * In this function, newly allocated vm_struct is not added
-	 * to vmlist at __get_vm_area_node(). so, it is added here.
+	 * In this function, newly allocated vm_struct has VM_UNLIST flag.
+	 * It means that vm_struct is not fully initialized.
+	 * Now, it is fully initialized, so remove this flag here.
 	 */
-	insert_vmalloc_vmlist(area);
+	clear_vm_unlist(area);
 
 	/*
 	 * A ref_count = 3 is needed because the vm_struct and vmap_area
@@ -2005,7 +1981,8 @@ static int aligned_vwrite(char *buf, char *addr, unsigned long count)
 
 long vread(char *buf, char *addr, unsigned long count)
 {
-	struct vm_struct *tmp;
+	struct vmap_area *va;
+	struct vm_struct *vm;
 	char *vaddr, *buf_start = buf;
 	unsigned long buflen = count;
 	unsigned long n;
@@ -2014,10 +1991,17 @@ long vread(char *buf, char *addr, unsigned long count)
 	if ((unsigned long) addr + count < count)
 		count = -(unsigned long) addr;
 
-	read_lock(&vmlist_lock);
-	for (tmp = vmlist; count && tmp; tmp = tmp->next) {
-		vaddr = (char *) tmp->addr;
-		if (addr >= vaddr + tmp->size - PAGE_SIZE)
+	spin_lock(&vmap_area_lock);
+	list_for_each_entry(va, &vmap_area_list, list) {
+		if (!count)
+			break;
+
+		if (!(va->flags & VM_VM_AREA))
+			continue;
+
+		vm = va->vm;
+		vaddr = (char *) vm->addr;
+		if (addr >= vaddr + vm->size - PAGE_SIZE)
 			continue;
 		while (addr < vaddr) {
 			if (count == 0)
@@ -2027,10 +2011,10 @@ long vread(char *buf, char *addr, unsigned long count)
 			addr++;
 			count--;
 		}
-		n = vaddr + tmp->size - PAGE_SIZE - addr;
+		n = vaddr + vm->size - PAGE_SIZE - addr;
 		if (n > count)
 			n = count;
-		if (!(tmp->flags & VM_IOREMAP))
+		if (!(vm->flags & VM_IOREMAP))
 			aligned_vread(buf, addr, n);
 		else /* IOREMAP area is treated as memory hole */
 			memset(buf, 0, n);
@@ -2039,7 +2023,7 @@ long vread(char *buf, char *addr, unsigned long count)
 		count -= n;
 	}
 finished:
-	read_unlock(&vmlist_lock);
+	spin_unlock(&vmap_area_lock);
 
 	if (buf == buf_start)
 		return 0;
@@ -2078,7 +2062,8 @@ finished:
 
 long vwrite(char *buf, char *addr, unsigned long count)
 {
-	struct vm_struct *tmp;
+	struct vmap_area *va;
+	struct vm_struct *vm;
 	char *vaddr;
 	unsigned long n, buflen;
 	int copied = 0;
@@ -2088,10 +2073,17 @@ long vwrite(char *buf, char *addr, unsigned long count)
 		count = -(unsigned long) addr;
 	buflen = count;
 
-	read_lock(&vmlist_lock);
-	for (tmp = vmlist; count && tmp; tmp = tmp->next) {
-		vaddr = (char *) tmp->addr;
-		if (addr >= vaddr + tmp->size - PAGE_SIZE)
+	spin_lock(&vmap_area_lock);
+	list_for_each_entry(va, &vmap_area_list, list) {
+		if (!count)
+			break;
+
+		if (!(va->flags & VM_VM_AREA))
+			continue;
+
+		vm = va->vm;
+		vaddr = (char *) vm->addr;
+		if (addr >= vaddr + vm->size - PAGE_SIZE)
 			continue;
 		while (addr < vaddr) {
 			if (count == 0)
@@ -2100,10 +2092,10 @@ long vwrite(char *buf, char *addr, unsigned long count)
 			addr++;
 			count--;
 		}
-		n = vaddr + tmp->size - PAGE_SIZE - addr;
+		n = vaddr + vm->size - PAGE_SIZE - addr;
 		if (n > count)
 			n = count;
-		if (!(tmp->flags & VM_IOREMAP)) {
+		if (!(vm->flags & VM_IOREMAP)) {
 			aligned_vwrite(buf, addr, n);
 			copied++;
 		}
@@ -2112,7 +2104,7 @@ long vwrite(char *buf, char *addr, unsigned long count)
 		count -= n;
 	}
 finished:
-	read_unlock(&vmlist_lock);
+	spin_unlock(&vmap_area_lock);
 	if (!copied)
 		return 0;
 	return buflen;
@@ -2519,19 +2511,19 @@ void pcpu_free_vm_areas(struct vm_struct **vms, int nr_vms)
 
 #ifdef CONFIG_PROC_FS
 static void *s_start(struct seq_file *m, loff_t *pos)
-	__acquires(&vmlist_lock)
+	__acquires(&vmap_area_lock)
 {
 	loff_t n = *pos;
-	struct vm_struct *v;
+	struct vmap_area *va;
 
-	read_lock(&vmlist_lock);
-	v = vmlist;
-	while (n > 0 && v) {
+	spin_lock(&vmap_area_lock);
+	va = list_entry((&vmap_area_list)->next, typeof(*va), list);
+	while (n > 0 && &va->list != &vmap_area_list) {
 		n--;
-		v = v->next;
+		va = list_entry(va->list.next, typeof(*va), list);
 	}
-	if (!n)
-		return v;
+	if (!n && &va->list != &vmap_area_list)
+		return va;
 
 	return NULL;
 
@@ -2539,16 +2531,20 @@ static void *s_start(struct seq_file *m, loff_t *pos)
 
 static void *s_next(struct seq_file *m, void *p, loff_t *pos)
 {
-	struct vm_struct *v = p;
+	struct vmap_area *va = p, *next;
 
 	++*pos;
-	return v->next;
+	next = list_entry(va->list.next, typeof(*va), list);
+	if (&next->list != &vmap_area_list)
+		return next;
+
+	return NULL;
 }
 
 static void s_stop(struct seq_file *m, void *p)
-	__releases(&vmlist_lock)
+	__releases(&vmap_area_lock)
 {
-	read_unlock(&vmlist_lock);
+	spin_unlock(&vmap_area_lock);
 }
 
 static void show_numa_info(struct seq_file *m, struct vm_struct *v)
@@ -2559,6 +2555,11 @@ static void show_numa_info(struct seq_file *m, struct vm_struct *v)
 		if (!counters)
 			return;
 
+		/* Pair with smp_wmb() in clear_vm_unlist() */
+		smp_rmb();
+		if (v->flags & VM_UNLIST)
+			return;
+
 		memset(counters, 0, nr_node_ids * sizeof(unsigned int));
 
 		for (nr = 0; nr < v->nr_pages; nr++)
@@ -2572,7 +2573,20 @@ static void show_numa_info(struct seq_file *m, struct vm_struct *v)
 
 static int s_show(struct seq_file *m, void *p)
 {
-	struct vm_struct *v = p;
+	struct vmap_area *va = p;
+	struct vm_struct *v;
+
+	if (va->flags & (VM_LAZY_FREE | VM_LAZY_FREEING))
+		return 0;
+
+	if (!(va->flags & VM_VM_AREA)) {
+		seq_printf(m, "0x%pK-0x%pK %7ld vm_map_ram\n",
+			(void *)va->va_start, (void *)va->va_end,
+					va->va_end - va->va_start);
+		return 0;
+	}
+
+	v = va->vm;
 
 	seq_printf(m, "0x%pK-0x%pK %7ld",
 		v->addr, v->addr + v->size, v->size);
@@ -2645,5 +2659,53 @@ static int __init proc_vmalloc_init(void)
 	return 0;
 }
 module_init(proc_vmalloc_init);
+
+void get_vmalloc_info(struct vmalloc_info *vmi)
+{
+	struct vmap_area *va;
+	unsigned long free_area_size;
+	unsigned long prev_end;
+
+	vmi->used = 0;
+	vmi->largest_chunk = 0;
+
+	prev_end = VMALLOC_START;
+
+	spin_lock(&vmap_area_lock);
+
+	if (list_empty(&vmap_area_list)) {
+		vmi->largest_chunk = VMALLOC_TOTAL;
+		goto out;
+	}
+
+	list_for_each_entry(va, &vmap_area_list, list) {
+		unsigned long addr = va->va_start;
+
+		/*
+		 * Some archs keep another range for modules in vmalloc space
+		 */
+		if (addr < VMALLOC_START)
+			continue;
+		if (addr >= VMALLOC_END)
+			break;
+
+		if (va->flags & (VM_LAZY_FREE | VM_LAZY_FREEING))
+			continue;
+
+		vmi->used += (va->va_end - va->va_start);
+
+		free_area_size = addr - prev_end;
+		if (vmi->largest_chunk < free_area_size)
+			vmi->largest_chunk = free_area_size;
+
+		prev_end = va->va_end;
+	}
+
+	if (VMALLOC_END - prev_end > vmi->largest_chunk)
+		vmi->largest_chunk = VMALLOC_END - prev_end;
+
+out:
+	spin_unlock(&vmap_area_lock);
+}
 #endif
 
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 88c5fed..df78d17 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -2619,7 +2619,6 @@ static unsigned long balance_pgdat(pg_data_t *pgdat, int order,
 	bool pgdat_is_balanced = false;
 	int i;
 	int end_zone = 0;	/* Inclusive.  0 = ZONE_DMA */
-	unsigned long total_scanned;
 	struct reclaim_state *reclaim_state = current->reclaim_state;
 	unsigned long nr_soft_reclaimed;
 	unsigned long nr_soft_scanned;
@@ -2639,7 +2638,6 @@ static unsigned long balance_pgdat(pg_data_t *pgdat, int order,
 		.gfp_mask = sc.gfp_mask,
 	};
 loop_again:
-	total_scanned = 0;
 	sc.priority = DEF_PRIORITY;
 	sc.nr_reclaimed = 0;
 	sc.may_writepage = !laptop_mode;
@@ -2730,7 +2728,6 @@ loop_again:
 							order, sc.gfp_mask,
 							&nr_soft_scanned);
 			sc.nr_reclaimed += nr_soft_reclaimed;
-			total_scanned += nr_soft_scanned;
 
 			/*
 			 * We put equal pressure on every zone, unless
@@ -2765,7 +2762,6 @@ loop_again:
 				reclaim_state->reclaimed_slab = 0;
 				nr_slab = shrink_slab(&shrink, sc.nr_scanned, lru_pages);
 				sc.nr_reclaimed += reclaim_state->reclaimed_slab;
-				total_scanned += sc.nr_scanned;
 
 				if (nr_slab == 0 && !zone_reclaimable(zone))
 					zone->all_unreclaimable = 1;
diff --git a/mm/vmstat.c b/mm/vmstat.c
index e1d8ed1..292b1cf 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -792,7 +792,14 @@ const char * const vmstat_text[] = {
 	"compact_stall",
 	"compact_fail",
 	"compact_success",
-#endif
+
+#ifdef CONFIG_BALLOON_COMPACTION
+	"compact_balloon_isolated",
+	"compact_balloon_migrated",
+	"compact_balloon_returned",
+#endif /* CONFIG_BALLOON_COMPACTION */
+
+#endif /* CONFIG_COMPACTION */
 
 #ifdef CONFIG_HUGETLB_PAGE
 	"htlb_buddy_alloc_success",
diff --git a/net/8021q/vlanproc.c b/net/8021q/vlanproc.c
index dc526ec..959ddbb 100644
--- a/net/8021q/vlanproc.c
+++ b/net/8021q/vlanproc.c
@@ -93,7 +93,7 @@ static const struct file_operations vlan_fops = {
 
 static int vlandev_seq_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, vlandev_seq_show, PDE(inode)->data);
+	return single_open(file, vlandev_seq_show, PDE_DATA(inode));
 }
 
 static const struct file_operations vlandev_fops = {
diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c
index de2e950..e1c26b1 100644
--- a/net/9p/trans_virtio.c
+++ b/net/9p/trans_virtio.c
@@ -194,11 +194,14 @@ static int pack_sg_list(struct scatterlist *sg, int start,
 		if (s > count)
 			s = count;
 		BUG_ON(index > limit);
+		/* Make sure we don't terminate early. */
+		sg_unmark_end(&sg[index]);
 		sg_set_buf(&sg[index++], data, s);
 		count -= s;
 		data += s;
 	}
-
+	if (index-start)
+		sg_mark_end(&sg[index - 1]);
 	return index-start;
 }
 
@@ -236,12 +239,17 @@ pack_sg_list_p(struct scatterlist *sg, int start, int limit,
 		s = rest_of_page(data);
 		if (s > count)
 			s = count;
+		/* Make sure we don't terminate early. */
+		sg_unmark_end(&sg[index]);
 		sg_set_page(&sg[index++], pdata[i++], s, data_off);
 		data_off = 0;
 		data += s;
 		count -= s;
 		nr_pages--;
 	}
+
+	if (index-start)
+		sg_mark_end(&sg[index - 1]);
 	return index - start;
 }
 
@@ -256,9 +264,10 @@ static int
 p9_virtio_request(struct p9_client *client, struct p9_req_t *req)
 {
 	int err;
-	int in, out;
+	int in, out, out_sgs, in_sgs;
 	unsigned long flags;
 	struct virtio_chan *chan = client->trans;
+	struct scatterlist *sgs[2];
 
 	p9_debug(P9_DEBUG_TRANS, "9p debug: virtio request\n");
 
@@ -266,14 +275,19 @@ p9_virtio_request(struct p9_client *client, struct p9_req_t *req)
 req_retry:
 	spin_lock_irqsave(&chan->lock, flags);
 
+	out_sgs = in_sgs = 0;
 	/* Handle out VirtIO ring buffers */
 	out = pack_sg_list(chan->sg, 0,
 			   VIRTQUEUE_NUM, req->tc->sdata, req->tc->size);
+	if (out)
+		sgs[out_sgs++] = chan->sg;
 
 	in = pack_sg_list(chan->sg, out,
 			  VIRTQUEUE_NUM, req->rc->sdata, req->rc->capacity);
+	if (in)
+		sgs[out_sgs + in_sgs++] = chan->sg + out;
 
-	err = virtqueue_add_buf(chan->vq, chan->sg, out, in, req->tc,
+	err = virtqueue_add_sgs(chan->vq, sgs, out_sgs, in_sgs, req->tc,
 				GFP_ATOMIC);
 	if (err < 0) {
 		if (err == -ENOSPC) {
@@ -289,7 +303,7 @@ req_retry:
 		} else {
 			spin_unlock_irqrestore(&chan->lock, flags);
 			p9_debug(P9_DEBUG_TRANS,
-				 "virtio rpc add_buf returned failure\n");
+				 "virtio rpc add_sgs returned failure\n");
 			return -EIO;
 		}
 	}
@@ -351,11 +365,12 @@ p9_virtio_zc_request(struct p9_client *client, struct p9_req_t *req,
 		     char *uidata, char *uodata, int inlen,
 		     int outlen, int in_hdr_len, int kern_buf)
 {
-	int in, out, err;
+	int in, out, err, out_sgs, in_sgs;
 	unsigned long flags;
 	int in_nr_pages = 0, out_nr_pages = 0;
 	struct page **in_pages = NULL, **out_pages = NULL;
 	struct virtio_chan *chan = client->trans;
+	struct scatterlist *sgs[4];
 
 	p9_debug(P9_DEBUG_TRANS, "virtio request\n");
 
@@ -396,13 +411,22 @@ p9_virtio_zc_request(struct p9_client *client, struct p9_req_t *req,
 	req->status = REQ_STATUS_SENT;
 req_retry_pinned:
 	spin_lock_irqsave(&chan->lock, flags);
+
+	out_sgs = in_sgs = 0;
+
 	/* out data */
 	out = pack_sg_list(chan->sg, 0,
 			   VIRTQUEUE_NUM, req->tc->sdata, req->tc->size);
 
-	if (out_pages)
+	if (out)
+		sgs[out_sgs++] = chan->sg;
+
+	if (out_pages) {
+		sgs[out_sgs++] = chan->sg + out;
 		out += pack_sg_list_p(chan->sg, out, VIRTQUEUE_NUM,
 				      out_pages, out_nr_pages, uodata, outlen);
+	}
+		
 	/*
 	 * Take care of in data
 	 * For example TREAD have 11.
@@ -412,11 +436,17 @@ req_retry_pinned:
 	 */
 	in = pack_sg_list(chan->sg, out,
 			  VIRTQUEUE_NUM, req->rc->sdata, in_hdr_len);
-	if (in_pages)
+	if (in)
+		sgs[out_sgs + in_sgs++] = chan->sg + out;
+
+	if (in_pages) {
+		sgs[out_sgs + in_sgs++] = chan->sg + out + in;
 		in += pack_sg_list_p(chan->sg, out + in, VIRTQUEUE_NUM,
 				     in_pages, in_nr_pages, uidata, inlen);
+	}
 
-	err = virtqueue_add_buf(chan->vq, chan->sg, out, in, req->tc,
+	BUG_ON(out_sgs + in_sgs > ARRAY_SIZE(sgs));
+	err = virtqueue_add_sgs(chan->vq, sgs, out_sgs, in_sgs, req->tc,
 				GFP_ATOMIC);
 	if (err < 0) {
 		if (err == -ENOSPC) {
@@ -432,7 +462,7 @@ req_retry_pinned:
 		} else {
 			spin_unlock_irqrestore(&chan->lock, flags);
 			p9_debug(P9_DEBUG_TRANS,
-				 "virtio rpc add_buf returned failure\n");
+				 "virtio rpc add_sgs returned failure\n");
 			err = -EIO;
 			goto err_out;
 		}
diff --git a/net/Kconfig b/net/Kconfig
index 6f676ab..2ddc904 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -217,6 +217,7 @@ source "net/dns_resolver/Kconfig"
 source "net/batman-adv/Kconfig"
 source "net/openvswitch/Kconfig"
 source "net/vmw_vsock/Kconfig"
+source "net/netlink/Kconfig"
 
 config RPS
 	boolean
diff --git a/net/atm/lec.h b/net/atm/lec.h
index a86aff9..4149db1 100644
--- a/net/atm/lec.h
+++ b/net/atm/lec.h
@@ -58,7 +58,7 @@ struct lane2_ops {
  *    field in h_type field. Data follows immediately after header.
  * 2. LLC Data frames whose total length, including LLC field and data,
  *    but not padding required to meet the minimum data frame length,
- *    is less than 1536(0x0600) MUST be encoded by placing that length
+ *    is less than ETH_P_802_3_MIN MUST be encoded by placing that length
  *    in the h_type field. The LLC field follows header immediately.
  * 3. LLC data frames longer than this maximum MUST be encoded by placing
  *    the value 0 in the h_type field.
diff --git a/net/atm/proc.c b/net/atm/proc.c
index 6ac35ff..bbb6461 100644
--- a/net/atm/proc.c
+++ b/net/atm/proc.c
@@ -385,7 +385,7 @@ static ssize_t proc_dev_atm_read(struct file *file, char __user *buf,
 	page = get_zeroed_page(GFP_KERNEL);
 	if (!page)
 		return -ENOMEM;
-	dev = PDE(file_inode(file))->data;
+	dev = PDE_DATA(file_inode(file));
 	if (!dev->ops->proc_read)
 		length = -EINVAL;
 	else {
diff --git a/net/batman-adv/Kconfig b/net/batman-adv/Kconfig
index 8d8afb1..fa780b7 100644
--- a/net/batman-adv/Kconfig
+++ b/net/batman-adv/Kconfig
@@ -36,6 +36,20 @@ config BATMAN_ADV_DAT
 	  mesh networks. If you think that your network does not need
 	  this option you can safely remove it and save some space.
 
+config BATMAN_ADV_NC
+	bool "Network Coding"
+	depends on BATMAN_ADV
+	default n
+	help
+	  This option enables network coding, a mechanism that aims to
+	  increase the overall network throughput by fusing multiple
+	  packets in one transmission.
+	  Note that interfaces controlled by batman-adv must be manually
+	  configured to have promiscuous mode enabled in order to make
+	  network coding work.
+	  If you think that your network does not need this feature you
+	  can safely disable it and save some space.
+
 config BATMAN_ADV_DEBUG
 	bool "B.A.T.M.A.N. debugging"
 	depends on BATMAN_ADV
diff --git a/net/batman-adv/Makefile b/net/batman-adv/Makefile
index e45e3b4..acbac2a 100644
--- a/net/batman-adv/Makefile
+++ b/net/batman-adv/Makefile
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2007-2012 B.A.T.M.A.N. contributors:
+# Copyright (C) 2007-2013 B.A.T.M.A.N. contributors:
 #
 # Marek Lindner, Simon Wunderlich
 #
@@ -30,6 +30,7 @@ batman-adv-y += hard-interface.o
 batman-adv-y += hash.o
 batman-adv-y += icmp_socket.o
 batman-adv-y += main.o
+batman-adv-$(CONFIG_BATMAN_ADV_NC) += network-coding.o
 batman-adv-y += originator.o
 batman-adv-y += ring_buffer.o
 batman-adv-y += routing.o
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
index a5bb0a7..071f288 100644
--- a/net/batman-adv/bat_iv_ogm.c
+++ b/net/batman-adv/bat_iv_ogm.c
@@ -27,6 +27,7 @@
 #include "hard-interface.h"
 #include "send.h"
 #include "bat_algo.h"
+#include "network-coding.h"
 
 static struct batadv_neigh_node *
 batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface,
@@ -1185,6 +1186,10 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
 	if (!orig_neigh_node)
 		goto out;
 
+	/* Update nc_nodes of the originator */
+	batadv_nc_update_nc_node(bat_priv, orig_node, orig_neigh_node,
+				 batadv_ogm_packet, is_single_hop_neigh);
+
 	orig_neigh_router = batadv_orig_node_get_router(orig_neigh_node);
 
 	/* drop packet if sender is not a direct neighbor and if we
diff --git a/net/batman-adv/debugfs.c b/net/batman-adv/debugfs.c
index 6ae8651..f186a55 100644
--- a/net/batman-adv/debugfs.c
+++ b/net/batman-adv/debugfs.c
@@ -32,6 +32,7 @@
 #include "icmp_socket.h"
 #include "bridge_loop_avoidance.h"
 #include "distributed-arp-table.h"
+#include "network-coding.h"
 
 static struct dentry *batadv_debugfs;
 
@@ -310,6 +311,14 @@ struct batadv_debuginfo {
 	const struct file_operations fops;
 };
 
+#ifdef CONFIG_BATMAN_ADV_NC
+static int batadv_nc_nodes_open(struct inode *inode, struct file *file)
+{
+	struct net_device *net_dev = (struct net_device *)inode->i_private;
+	return single_open(file, batadv_nc_nodes_seq_print_text, net_dev);
+}
+#endif
+
 #define BATADV_DEBUGINFO(_name, _mode, _open)		\
 struct batadv_debuginfo batadv_debuginfo_##_name = {	\
 	.attr = { .name = __stringify(_name),		\
@@ -348,6 +357,9 @@ static BATADV_DEBUGINFO(dat_cache, S_IRUGO, batadv_dat_cache_open);
 static BATADV_DEBUGINFO(transtable_local, S_IRUGO,
 			batadv_transtable_local_open);
 static BATADV_DEBUGINFO(vis_data, S_IRUGO, batadv_vis_data_open);
+#ifdef CONFIG_BATMAN_ADV_NC
+static BATADV_DEBUGINFO(nc_nodes, S_IRUGO, batadv_nc_nodes_open);
+#endif
 
 static struct batadv_debuginfo *batadv_mesh_debuginfos[] = {
 	&batadv_debuginfo_originators,
@@ -362,6 +374,9 @@ static struct batadv_debuginfo *batadv_mesh_debuginfos[] = {
 #endif
 	&batadv_debuginfo_transtable_local,
 	&batadv_debuginfo_vis_data,
+#ifdef CONFIG_BATMAN_ADV_NC
+	&batadv_debuginfo_nc_nodes,
+#endif
 	NULL,
 };
 
@@ -431,6 +446,9 @@ int batadv_debugfs_add_meshif(struct net_device *dev)
 		}
 	}
 
+	if (batadv_nc_init_debugfs(bat_priv) < 0)
+		goto rem_attr;
+
 	return 0;
 rem_attr:
 	debugfs_remove_recursive(bat_priv->debug_dir);
diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c
index d54188a..8e15d96 100644
--- a/net/batman-adv/distributed-arp-table.c
+++ b/net/batman-adv/distributed-arp-table.c
@@ -816,7 +816,6 @@ bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
 	bool ret = false;
 	struct batadv_dat_entry *dat_entry = NULL;
 	struct sk_buff *skb_new;
-	struct batadv_hard_iface *primary_if = NULL;
 
 	if (!atomic_read(&bat_priv->distributed_arp_table))
 		goto out;
@@ -838,22 +837,18 @@ bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
 
 	dat_entry = batadv_dat_entry_hash_find(bat_priv, ip_dst);
 	if (dat_entry) {
-		primary_if = batadv_primary_if_get_selected(bat_priv);
-		if (!primary_if)
-			goto out;
-
 		skb_new = arp_create(ARPOP_REPLY, ETH_P_ARP, ip_src,
-				     primary_if->soft_iface, ip_dst, hw_src,
+				     bat_priv->soft_iface, ip_dst, hw_src,
 				     dat_entry->mac_addr, hw_src);
 		if (!skb_new)
 			goto out;
 
 		skb_reset_mac_header(skb_new);
 		skb_new->protocol = eth_type_trans(skb_new,
-						   primary_if->soft_iface);
+						   bat_priv->soft_iface);
 		bat_priv->stats.rx_packets++;
 		bat_priv->stats.rx_bytes += skb->len + ETH_HLEN;
-		primary_if->soft_iface->last_rx = jiffies;
+		bat_priv->soft_iface->last_rx = jiffies;
 
 		netif_rx(skb_new);
 		batadv_dbg(BATADV_DBG_DAT, bat_priv, "ARP request replied locally\n");
@@ -866,8 +861,6 @@ bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
 out:
 	if (dat_entry)
 		batadv_dat_entry_free_ref(dat_entry);
-	if (primary_if)
-		batadv_hardif_free_ref(primary_if);
 	return ret;
 }
 
@@ -887,7 +880,6 @@ bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv,
 	__be32 ip_src, ip_dst;
 	uint8_t *hw_src;
 	struct sk_buff *skb_new;
-	struct batadv_hard_iface *primary_if = NULL;
 	struct batadv_dat_entry *dat_entry = NULL;
 	bool ret = false;
 	int err;
@@ -912,12 +904,8 @@ bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv,
 	if (!dat_entry)
 		goto out;
 
-	primary_if = batadv_primary_if_get_selected(bat_priv);
-	if (!primary_if)
-		goto out;
-
 	skb_new = arp_create(ARPOP_REPLY, ETH_P_ARP, ip_src,
-			     primary_if->soft_iface, ip_dst, hw_src,
+			     bat_priv->soft_iface, ip_dst, hw_src,
 			     dat_entry->mac_addr, hw_src);
 
 	if (!skb_new)
@@ -941,8 +929,6 @@ bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv,
 out:
 	if (dat_entry)
 		batadv_dat_entry_free_ref(dat_entry);
-	if (primary_if)
-		batadv_hardif_free_ref(primary_if);
 	if (ret)
 		kfree_skb(skb);
 	return ret;
diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c
index 34f99a4..f105219 100644
--- a/net/batman-adv/gateway_client.c
+++ b/net/batman-adv/gateway_client.c
@@ -500,7 +500,7 @@ int batadv_gw_client_seq_print_text(struct seq_file *seq, void *offset)
 	rcu_read_unlock();
 
 	if (gw_count == 0)
-		seq_printf(seq, "No gateways in range ...\n");
+		seq_puts(seq, "No gateways in range ...\n");
 
 out:
 	if (primary_if)
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c
index 368219e..522243a 100644
--- a/net/batman-adv/hard-interface.c
+++ b/net/batman-adv/hard-interface.c
@@ -307,11 +307,35 @@ batadv_hardif_deactivate_interface(struct batadv_hard_iface *hard_iface)
 	batadv_update_min_mtu(hard_iface->soft_iface);
 }
 
+/**
+ * batadv_master_del_slave - remove hard_iface from the current master interface
+ * @slave: the interface enslaved in another master
+ * @master: the master from which slave has to be removed
+ *
+ * Invoke ndo_del_slave on master passing slave as argument. In this way slave
+ * is free'd and master can correctly change its internal state.
+ * Return 0 on success, a negative value representing the error otherwise
+ */
+static int batadv_master_del_slave(struct batadv_hard_iface *slave,
+				   struct net_device *master)
+{
+	int ret;
+
+	if (!master)
+		return 0;
+
+	ret = -EBUSY;
+	if (master->netdev_ops->ndo_del_slave)
+		ret = master->netdev_ops->ndo_del_slave(master, slave->net_dev);
+
+	return ret;
+}
+
 int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,
 				   const char *iface_name)
 {
 	struct batadv_priv *bat_priv;
-	struct net_device *soft_iface;
+	struct net_device *soft_iface, *master;
 	__be16 ethertype = __constant_htons(ETH_P_BATMAN);
 	int ret;
 
@@ -321,11 +345,6 @@ int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,
 	if (!atomic_inc_not_zero(&hard_iface->refcount))
 		goto out;
 
-	/* hard-interface is part of a bridge */
-	if (hard_iface->net_dev->priv_flags & IFF_BRIDGE_PORT)
-		pr_err("You are about to enable batman-adv on '%s' which already is part of a bridge. Unless you know exactly what you are doing this is probably wrong and won't work the way you think it would.\n",
-		       hard_iface->net_dev->name);
-
 	soft_iface = dev_get_by_name(&init_net, iface_name);
 
 	if (!soft_iface) {
@@ -347,12 +366,24 @@ int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,
 		goto err_dev;
 	}
 
+	/* check if the interface is enslaved in another virtual one and
+	 * in that case unlink it first
+	 */
+	master = netdev_master_upper_dev_get(hard_iface->net_dev);
+	ret = batadv_master_del_slave(hard_iface, master);
+	if (ret)
+		goto err_dev;
+
 	hard_iface->soft_iface = soft_iface;
 	bat_priv = netdev_priv(hard_iface->soft_iface);
 
+	ret = netdev_master_upper_dev_link(hard_iface->net_dev, soft_iface);
+	if (ret)
+		goto err_dev;
+
 	ret = bat_priv->bat_algo_ops->bat_iface_enable(hard_iface);
 	if (ret < 0)
-		goto err_dev;
+		goto err_upper;
 
 	hard_iface->if_num = bat_priv->num_ifaces;
 	bat_priv->num_ifaces++;
@@ -362,7 +393,7 @@ int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,
 		bat_priv->bat_algo_ops->bat_iface_disable(hard_iface);
 		bat_priv->num_ifaces--;
 		hard_iface->if_status = BATADV_IF_NOT_IN_USE;
-		goto err_dev;
+		goto err_upper;
 	}
 
 	hard_iface->batman_adv_ptype.type = ethertype;
@@ -401,14 +432,18 @@ int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,
 out:
 	return 0;
 
+err_upper:
+	netdev_upper_dev_unlink(hard_iface->net_dev, soft_iface);
 err_dev:
+	hard_iface->soft_iface = NULL;
 	dev_put(soft_iface);
 err:
 	batadv_hardif_free_ref(hard_iface);
 	return ret;
 }
 
-void batadv_hardif_disable_interface(struct batadv_hard_iface *hard_iface)
+void batadv_hardif_disable_interface(struct batadv_hard_iface *hard_iface,
+				     enum batadv_hard_if_cleanup autodel)
 {
 	struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
 	struct batadv_hard_iface *primary_if = NULL;
@@ -446,9 +481,10 @@ void batadv_hardif_disable_interface(struct batadv_hard_iface *hard_iface)
 	dev_put(hard_iface->soft_iface);
 
 	/* nobody uses this interface anymore */
-	if (!bat_priv->num_ifaces)
-		batadv_softif_destroy(hard_iface->soft_iface);
+	if (!bat_priv->num_ifaces && autodel == BATADV_IF_CLEANUP_AUTO)
+		batadv_softif_destroy_sysfs(hard_iface->soft_iface);
 
+	netdev_upper_dev_unlink(hard_iface->net_dev, hard_iface->soft_iface);
 	hard_iface->soft_iface = NULL;
 	batadv_hardif_free_ref(hard_iface);
 
@@ -533,7 +569,8 @@ static void batadv_hardif_remove_interface(struct batadv_hard_iface *hard_iface)
 
 	/* first deactivate interface */
 	if (hard_iface->if_status != BATADV_IF_NOT_IN_USE)
-		batadv_hardif_disable_interface(hard_iface);
+		batadv_hardif_disable_interface(hard_iface,
+						BATADV_IF_CLEANUP_AUTO);
 
 	if (hard_iface->if_status != BATADV_IF_NOT_IN_USE)
 		return;
@@ -563,6 +600,11 @@ static int batadv_hard_if_event(struct notifier_block *this,
 	struct batadv_hard_iface *primary_if = NULL;
 	struct batadv_priv *bat_priv;
 
+	if (batadv_softif_is_valid(net_dev) && event == NETDEV_REGISTER) {
+		batadv_sysfs_add_meshif(net_dev);
+		return NOTIFY_DONE;
+	}
+
 	hard_iface = batadv_hardif_get_by_netdev(net_dev);
 	if (!hard_iface && event == NETDEV_REGISTER)
 		hard_iface = batadv_hardif_add_interface(net_dev);
diff --git a/net/batman-adv/hard-interface.h b/net/batman-adv/hard-interface.h
index 308437d..4989288 100644
--- a/net/batman-adv/hard-interface.h
+++ b/net/batman-adv/hard-interface.h
@@ -29,13 +29,24 @@ enum batadv_hard_if_state {
 	BATADV_IF_I_WANT_YOU,
 };
 
+/**
+ * enum batadv_hard_if_cleanup - Cleanup modi for soft_iface after slave removal
+ * @BATADV_IF_CLEANUP_KEEP: Don't automatically delete soft-interface
+ * @BATADV_IF_CLEANUP_AUTO: Delete soft-interface after last slave was removed
+ */
+enum batadv_hard_if_cleanup {
+	BATADV_IF_CLEANUP_KEEP,
+	BATADV_IF_CLEANUP_AUTO,
+};
+
 extern struct notifier_block batadv_hard_if_notifier;
 
 struct batadv_hard_iface*
 batadv_hardif_get_by_netdev(const struct net_device *net_dev);
 int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,
 				   const char *iface_name);
-void batadv_hardif_disable_interface(struct batadv_hard_iface *hard_iface);
+void batadv_hardif_disable_interface(struct batadv_hard_iface *hard_iface,
+				     enum batadv_hard_if_cleanup autodel);
 void batadv_hardif_remove_interfaces(void);
 int batadv_hardif_min_mtu(struct net_device *soft_iface);
 void batadv_update_min_mtu(struct net_device *soft_iface);
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c
index 0488d70..6277735 100644
--- a/net/batman-adv/main.c
+++ b/net/batman-adv/main.c
@@ -35,6 +35,7 @@
 #include "vis.h"
 #include "hash.h"
 #include "bat_algo.h"
+#include "network-coding.h"
 
 
 /* List manipulations on hardif_list have to be rtnl_lock()'ed,
@@ -70,6 +71,7 @@ static int __init batadv_init(void)
 	batadv_debugfs_init();
 
 	register_netdevice_notifier(&batadv_hard_if_notifier);
+	rtnl_link_register(&batadv_link_ops);
 
 	pr_info("B.A.T.M.A.N. advanced %s (compatibility version %i) loaded\n",
 		BATADV_SOURCE_VERSION, BATADV_COMPAT_VERSION);
@@ -80,6 +82,7 @@ static int __init batadv_init(void)
 static void __exit batadv_exit(void)
 {
 	batadv_debugfs_destroy();
+	rtnl_link_unregister(&batadv_link_ops);
 	unregister_netdevice_notifier(&batadv_hard_if_notifier);
 	batadv_hardif_remove_interfaces();
 
@@ -135,6 +138,10 @@ int batadv_mesh_init(struct net_device *soft_iface)
 	if (ret < 0)
 		goto err;
 
+	ret = batadv_nc_init(bat_priv);
+	if (ret < 0)
+		goto err;
+
 	atomic_set(&bat_priv->gw.reselect, 0);
 	atomic_set(&bat_priv->mesh_state, BATADV_MESH_ACTIVE);
 
@@ -157,6 +164,7 @@ void batadv_mesh_free(struct net_device *soft_iface)
 
 	batadv_gw_node_purge(bat_priv);
 	batadv_originator_free(bat_priv);
+	batadv_nc_free(bat_priv);
 
 	batadv_tt_free(bat_priv);
 
@@ -411,7 +419,7 @@ int batadv_algo_seq_print_text(struct seq_file *seq, void *offset)
 {
 	struct batadv_algo_ops *bat_algo_ops;
 
-	seq_printf(seq, "Available routing algorithms:\n");
+	seq_puts(seq, "Available routing algorithms:\n");
 
 	hlist_for_each_entry(bat_algo_ops, &batadv_algo_list, list) {
 		seq_printf(seq, "%s\n", bat_algo_ops->name);
diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h
index ced08b9..f90f5bc 100644
--- a/net/batman-adv/main.h
+++ b/net/batman-adv/main.h
@@ -26,7 +26,7 @@
 #define BATADV_DRIVER_DEVICE "batman-adv"
 
 #ifndef BATADV_SOURCE_VERSION
-#define BATADV_SOURCE_VERSION "2013.1.0"
+#define BATADV_SOURCE_VERSION "2013.2.0"
 #endif
 
 /* B.A.T.M.A.N. parameters */
@@ -105,6 +105,8 @@
 #define BATADV_RESET_PROTECTION_MS 30000
 #define BATADV_EXPECTED_SEQNO_RANGE	65536
 
+#define BATADV_NC_NODE_TIMEOUT 10000 /* Milliseconds */
+
 enum batadv_mesh_state {
 	BATADV_MESH_INACTIVE,
 	BATADV_MESH_ACTIVE,
@@ -150,6 +152,7 @@ enum batadv_uev_type {
 #include <linux/percpu.h>
 #include <linux/slab.h>
 #include <net/sock.h>		/* struct sock */
+#include <net/rtnetlink.h>
 #include <linux/jiffies.h>
 #include <linux/seq_file.h>
 #include "types.h"
@@ -185,6 +188,7 @@ __be32 batadv_skb_crc32(struct sk_buff *skb, u8 *payload_ptr);
  * @BATADV_DBG_TT: translation table messages
  * @BATADV_DBG_BLA: bridge loop avoidance messages
  * @BATADV_DBG_DAT: ARP snooping and DAT related messages
+ * @BATADV_DBG_NC: network coding related messages
  * @BATADV_DBG_ALL: the union of all the above log levels
  */
 enum batadv_dbg_level {
@@ -193,7 +197,8 @@ enum batadv_dbg_level {
 	BATADV_DBG_TT	  = BIT(2),
 	BATADV_DBG_BLA    = BIT(3),
 	BATADV_DBG_DAT    = BIT(4),
-	BATADV_DBG_ALL    = 31,
+	BATADV_DBG_NC	  = BIT(5),
+	BATADV_DBG_ALL    = 63,
 };
 
 #ifdef CONFIG_BATMAN_ADV_DEBUG
@@ -298,4 +303,10 @@ static inline uint64_t batadv_sum_counter(struct batadv_priv *bat_priv,
 	return sum;
 }
 
+/* Define a macro to reach the control buffer of the skb. The members of the
+ * control buffer are defined in struct batadv_skb_cb in types.h.
+ * The macro is inspired by the similar macro TCP_SKB_CB() in tcp.h.
+ */
+#define BATADV_SKB_CB(__skb)       ((struct batadv_skb_cb *)&((__skb)->cb[0]))
+
 #endif /* _NET_BATMAN_ADV_MAIN_H_ */
diff --git a/net/batman-adv/network-coding.c b/net/batman-adv/network-coding.c
new file mode 100644
index 0000000..6b9a544
--- /dev/null
+++ b/net/batman-adv/network-coding.c
@@ -0,0 +1,1821 @@
+/* Copyright (C) 2012-2013 B.A.T.M.A.N. contributors:
+ *
+ * Martin Hundebøll, Jeppe Ledet-Pedersen
+ *
+ * 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-1301, USA
+ */
+
+#include <linux/debugfs.h>
+
+#include "main.h"
+#include "hash.h"
+#include "network-coding.h"
+#include "send.h"
+#include "originator.h"
+#include "hard-interface.h"
+#include "routing.h"
+
+static struct lock_class_key batadv_nc_coding_hash_lock_class_key;
+static struct lock_class_key batadv_nc_decoding_hash_lock_class_key;
+
+static void batadv_nc_worker(struct work_struct *work);
+static int batadv_nc_recv_coded_packet(struct sk_buff *skb,
+				       struct batadv_hard_iface *recv_if);
+
+/**
+ * batadv_nc_start_timer - initialise the nc periodic worker
+ * @bat_priv: the bat priv with all the soft interface information
+ */
+static void batadv_nc_start_timer(struct batadv_priv *bat_priv)
+{
+	queue_delayed_work(batadv_event_workqueue, &bat_priv->nc.work,
+			   msecs_to_jiffies(10));
+}
+
+/**
+ * batadv_nc_init - initialise coding hash table and start house keeping
+ * @bat_priv: the bat priv with all the soft interface information
+ */
+int batadv_nc_init(struct batadv_priv *bat_priv)
+{
+	bat_priv->nc.timestamp_fwd_flush = jiffies;
+	bat_priv->nc.timestamp_sniffed_purge = jiffies;
+
+	if (bat_priv->nc.coding_hash || bat_priv->nc.decoding_hash)
+		return 0;
+
+	bat_priv->nc.coding_hash = batadv_hash_new(128);
+	if (!bat_priv->nc.coding_hash)
+		goto err;
+
+	batadv_hash_set_lock_class(bat_priv->nc.coding_hash,
+				   &batadv_nc_coding_hash_lock_class_key);
+
+	bat_priv->nc.decoding_hash = batadv_hash_new(128);
+	if (!bat_priv->nc.decoding_hash)
+		goto err;
+
+	batadv_hash_set_lock_class(bat_priv->nc.coding_hash,
+				   &batadv_nc_decoding_hash_lock_class_key);
+
+	/* Register our packet type */
+	if (batadv_recv_handler_register(BATADV_CODED,
+					 batadv_nc_recv_coded_packet) < 0)
+		goto err;
+
+	INIT_DELAYED_WORK(&bat_priv->nc.work, batadv_nc_worker);
+	batadv_nc_start_timer(bat_priv);
+
+	return 0;
+
+err:
+	return -ENOMEM;
+}
+
+/**
+ * batadv_nc_init_bat_priv - initialise the nc specific bat_priv variables
+ * @bat_priv: the bat priv with all the soft interface information
+ */
+void batadv_nc_init_bat_priv(struct batadv_priv *bat_priv)
+{
+	atomic_set(&bat_priv->network_coding, 1);
+	bat_priv->nc.min_tq = 200;
+	bat_priv->nc.max_fwd_delay = 10;
+	bat_priv->nc.max_buffer_time = 200;
+}
+
+/**
+ * batadv_nc_init_orig - initialise the nc fields of an orig_node
+ * @orig_node: the orig_node which is going to be initialised
+ */
+void batadv_nc_init_orig(struct batadv_orig_node *orig_node)
+{
+	INIT_LIST_HEAD(&orig_node->in_coding_list);
+	INIT_LIST_HEAD(&orig_node->out_coding_list);
+	spin_lock_init(&orig_node->in_coding_list_lock);
+	spin_lock_init(&orig_node->out_coding_list_lock);
+}
+
+/**
+ * batadv_nc_node_free_rcu - rcu callback to free an nc node and remove
+ *  its refcount on the orig_node
+ * @rcu: rcu pointer of the nc node
+ */
+static void batadv_nc_node_free_rcu(struct rcu_head *rcu)
+{
+	struct batadv_nc_node *nc_node;
+
+	nc_node = container_of(rcu, struct batadv_nc_node, rcu);
+	batadv_orig_node_free_ref(nc_node->orig_node);
+	kfree(nc_node);
+}
+
+/**
+ * batadv_nc_node_free_ref - decrements the nc node refcounter and possibly
+ * frees it
+ * @nc_node: the nc node to free
+ */
+static void batadv_nc_node_free_ref(struct batadv_nc_node *nc_node)
+{
+	if (atomic_dec_and_test(&nc_node->refcount))
+		call_rcu(&nc_node->rcu, batadv_nc_node_free_rcu);
+}
+
+/**
+ * batadv_nc_path_free_ref - decrements the nc path refcounter and possibly
+ * frees it
+ * @nc_path: the nc node to free
+ */
+static void batadv_nc_path_free_ref(struct batadv_nc_path *nc_path)
+{
+	if (atomic_dec_and_test(&nc_path->refcount))
+		kfree_rcu(nc_path, rcu);
+}
+
+/**
+ * batadv_nc_packet_free - frees nc packet
+ * @nc_packet: the nc packet to free
+ */
+static void batadv_nc_packet_free(struct batadv_nc_packet *nc_packet)
+{
+	if (nc_packet->skb)
+		kfree_skb(nc_packet->skb);
+
+	batadv_nc_path_free_ref(nc_packet->nc_path);
+	kfree(nc_packet);
+}
+
+/**
+ * batadv_nc_to_purge_nc_node - checks whether an nc node has to be purged
+ * @bat_priv: the bat priv with all the soft interface information
+ * @nc_node: the nc node to check
+ *
+ * Returns true if the entry has to be purged now, false otherwise
+ */
+static bool batadv_nc_to_purge_nc_node(struct batadv_priv *bat_priv,
+				       struct batadv_nc_node *nc_node)
+{
+	if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
+		return true;
+
+	return batadv_has_timed_out(nc_node->last_seen, BATADV_NC_NODE_TIMEOUT);
+}
+
+/**
+ * batadv_nc_to_purge_nc_path_coding - checks whether an nc path has timed out
+ * @bat_priv: the bat priv with all the soft interface information
+ * @nc_path: the nc path to check
+ *
+ * Returns true if the entry has to be purged now, false otherwise
+ */
+static bool batadv_nc_to_purge_nc_path_coding(struct batadv_priv *bat_priv,
+					      struct batadv_nc_path *nc_path)
+{
+	if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
+		return true;
+
+	/* purge the path when no packets has been added for 10 times the
+	 * max_fwd_delay time
+	 */
+	return batadv_has_timed_out(nc_path->last_valid,
+				    bat_priv->nc.max_fwd_delay * 10);
+}
+
+/**
+ * batadv_nc_to_purge_nc_path_decoding - checks whether an nc path has timed out
+ * @bat_priv: the bat priv with all the soft interface information
+ * @nc_path: the nc path to check
+ *
+ * Returns true if the entry has to be purged now, false otherwise
+ */
+static bool batadv_nc_to_purge_nc_path_decoding(struct batadv_priv *bat_priv,
+						struct batadv_nc_path *nc_path)
+{
+	if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
+		return true;
+
+	/* purge the path when no packets has been added for 10 times the
+	 * max_buffer time
+	 */
+	return batadv_has_timed_out(nc_path->last_valid,
+				    bat_priv->nc.max_buffer_time*10);
+}
+
+/**
+ * batadv_nc_purge_orig_nc_nodes - go through list of nc nodes and purge stale
+ *  entries
+ * @bat_priv: the bat priv with all the soft interface information
+ * @list: list of nc nodes
+ * @lock: nc node list lock
+ * @to_purge: function in charge to decide whether an entry has to be purged or
+ *	      not. This function takes the nc node as argument and has to return
+ *	      a boolean value: true if the entry has to be deleted, false
+ *	      otherwise
+ */
+static void
+batadv_nc_purge_orig_nc_nodes(struct batadv_priv *bat_priv,
+			      struct list_head *list,
+			      spinlock_t *lock,
+			      bool (*to_purge)(struct batadv_priv *,
+					       struct batadv_nc_node *))
+{
+	struct batadv_nc_node *nc_node, *nc_node_tmp;
+
+	/* For each nc_node in list */
+	spin_lock_bh(lock);
+	list_for_each_entry_safe(nc_node, nc_node_tmp, list, list) {
+		/* if an helper function has been passed as parameter,
+		 * ask it if the entry has to be purged or not
+		 */
+		if (to_purge && !to_purge(bat_priv, nc_node))
+			continue;
+
+		batadv_dbg(BATADV_DBG_NC, bat_priv,
+			   "Removing nc_node %pM -> %pM\n",
+			   nc_node->addr, nc_node->orig_node->orig);
+		list_del_rcu(&nc_node->list);
+		batadv_nc_node_free_ref(nc_node);
+	}
+	spin_unlock_bh(lock);
+}
+
+/**
+ * batadv_nc_purge_orig - purges all nc node data attached of the given
+ *  originator
+ * @bat_priv: the bat priv with all the soft interface information
+ * @orig_node: orig_node with the nc node entries to be purged
+ * @to_purge: function in charge to decide whether an entry has to be purged or
+ *	      not. This function takes the nc node as argument and has to return
+ *	      a boolean value: true is the entry has to be deleted, false
+ *	      otherwise
+ */
+void batadv_nc_purge_orig(struct batadv_priv *bat_priv,
+			  struct batadv_orig_node *orig_node,
+			  bool (*to_purge)(struct batadv_priv *,
+					   struct batadv_nc_node *))
+{
+	/* Check ingoing nc_node's of this orig_node */
+	batadv_nc_purge_orig_nc_nodes(bat_priv, &orig_node->in_coding_list,
+				      &orig_node->in_coding_list_lock,
+				      to_purge);
+
+	/* Check outgoing nc_node's of this orig_node */
+	batadv_nc_purge_orig_nc_nodes(bat_priv, &orig_node->out_coding_list,
+				      &orig_node->out_coding_list_lock,
+				      to_purge);
+}
+
+/**
+ * batadv_nc_purge_orig_hash - traverse entire originator hash to check if they
+ *  have timed out nc nodes
+ * @bat_priv: the bat priv with all the soft interface information
+ */
+static void batadv_nc_purge_orig_hash(struct batadv_priv *bat_priv)
+{
+	struct batadv_hashtable *hash = bat_priv->orig_hash;
+	struct hlist_head *head;
+	struct batadv_orig_node *orig_node;
+	uint32_t i;
+
+	if (!hash)
+		return;
+
+	/* For each orig_node */
+	for (i = 0; i < hash->size; i++) {
+		head = &hash->table[i];
+
+		rcu_read_lock();
+		hlist_for_each_entry_rcu(orig_node, head, hash_entry)
+			batadv_nc_purge_orig(bat_priv, orig_node,
+					     batadv_nc_to_purge_nc_node);
+		rcu_read_unlock();
+	}
+}
+
+/**
+ * batadv_nc_purge_paths - traverse all nc paths part of the hash and remove
+ *  unused ones
+ * @bat_priv: the bat priv with all the soft interface information
+ * @hash: hash table containing the nc paths to check
+ * @to_purge: function in charge to decide whether an entry has to be purged or
+ *	      not. This function takes the nc node as argument and has to return
+ *	      a boolean value: true is the entry has to be deleted, false
+ *	      otherwise
+ */
+static void batadv_nc_purge_paths(struct batadv_priv *bat_priv,
+				  struct batadv_hashtable *hash,
+				  bool (*to_purge)(struct batadv_priv *,
+						   struct batadv_nc_path *))
+{
+	struct hlist_head *head;
+	struct hlist_node *node_tmp;
+	struct batadv_nc_path *nc_path;
+	spinlock_t *lock; /* Protects lists in hash */
+	uint32_t i;
+
+	for (i = 0; i < hash->size; i++) {
+		head = &hash->table[i];
+		lock = &hash->list_locks[i];
+
+		/* For each nc_path in this bin */
+		spin_lock_bh(lock);
+		hlist_for_each_entry_safe(nc_path, node_tmp, head, hash_entry) {
+			/* if an helper function has been passed as parameter,
+			 * ask it if the entry has to be purged or not
+			 */
+			if (to_purge && !to_purge(bat_priv, nc_path))
+				continue;
+
+			/* purging an non-empty nc_path should never happen, but
+			 * is observed under high CPU load. Delay the purging
+			 * until next iteration to allow the packet_list to be
+			 * emptied first.
+			 */
+			if (!unlikely(list_empty(&nc_path->packet_list))) {
+				net_ratelimited_function(printk,
+							 KERN_WARNING
+							 "Skipping free of non-empty nc_path (%pM -> %pM)!\n",
+							 nc_path->prev_hop,
+							 nc_path->next_hop);
+				continue;
+			}
+
+			/* nc_path is unused, so remove it */
+			batadv_dbg(BATADV_DBG_NC, bat_priv,
+				   "Remove nc_path %pM -> %pM\n",
+				   nc_path->prev_hop, nc_path->next_hop);
+			hlist_del_rcu(&nc_path->hash_entry);
+			batadv_nc_path_free_ref(nc_path);
+		}
+		spin_unlock_bh(lock);
+	}
+}
+
+/**
+ * batadv_nc_hash_key_gen - computes the nc_path hash key
+ * @key: buffer to hold the final hash key
+ * @src: source ethernet mac address going into the hash key
+ * @dst: destination ethernet mac address going into the hash key
+ */
+static void batadv_nc_hash_key_gen(struct batadv_nc_path *key, const char *src,
+				   const char *dst)
+{
+	memcpy(key->prev_hop, src, sizeof(key->prev_hop));
+	memcpy(key->next_hop, dst, sizeof(key->next_hop));
+}
+
+/**
+ * batadv_nc_hash_choose - compute the hash value for an nc path
+ * @data: data to hash
+ * @size: size of the hash table
+ *
+ * Returns the selected index in the hash table for the given data.
+ */
+static uint32_t batadv_nc_hash_choose(const void *data, uint32_t size)
+{
+	const struct batadv_nc_path *nc_path = data;
+	uint32_t hash = 0;
+
+	hash = batadv_hash_bytes(hash, &nc_path->prev_hop,
+				 sizeof(nc_path->prev_hop));
+	hash = batadv_hash_bytes(hash, &nc_path->next_hop,
+				 sizeof(nc_path->next_hop));
+
+	hash += (hash << 3);
+	hash ^= (hash >> 11);
+	hash += (hash << 15);
+
+	return hash % size;
+}
+
+/**
+ * batadv_nc_hash_compare - comparing function used in the network coding hash
+ *  tables
+ * @node: node in the local table
+ * @data2: second object to compare the node to
+ *
+ * Returns 1 if the two entry are the same, 0 otherwise
+ */
+static int batadv_nc_hash_compare(const struct hlist_node *node,
+				  const void *data2)
+{
+	const struct batadv_nc_path *nc_path1, *nc_path2;
+
+	nc_path1 = container_of(node, struct batadv_nc_path, hash_entry);
+	nc_path2 = data2;
+
+	/* Return 1 if the two keys are identical */
+	if (memcmp(nc_path1->prev_hop, nc_path2->prev_hop,
+		   sizeof(nc_path1->prev_hop)) != 0)
+		return 0;
+
+	if (memcmp(nc_path1->next_hop, nc_path2->next_hop,
+		   sizeof(nc_path1->next_hop)) != 0)
+		return 0;
+
+	return 1;
+}
+
+/**
+ * batadv_nc_hash_find - search for an existing nc path and return it
+ * @hash: hash table containing the nc path
+ * @data: search key
+ *
+ * Returns the nc_path if found, NULL otherwise.
+ */
+static struct batadv_nc_path *
+batadv_nc_hash_find(struct batadv_hashtable *hash,
+		    void *data)
+{
+	struct hlist_head *head;
+	struct batadv_nc_path *nc_path, *nc_path_tmp = NULL;
+	int index;
+
+	if (!hash)
+		return NULL;
+
+	index = batadv_nc_hash_choose(data, hash->size);
+	head = &hash->table[index];
+
+	rcu_read_lock();
+	hlist_for_each_entry_rcu(nc_path, head, hash_entry) {
+		if (!batadv_nc_hash_compare(&nc_path->hash_entry, data))
+			continue;
+
+		if (!atomic_inc_not_zero(&nc_path->refcount))
+			continue;
+
+		nc_path_tmp = nc_path;
+		break;
+	}
+	rcu_read_unlock();
+
+	return nc_path_tmp;
+}
+
+/**
+ * batadv_nc_send_packet - send non-coded packet and free nc_packet struct
+ * @nc_packet: the nc packet to send
+ */
+static void batadv_nc_send_packet(struct batadv_nc_packet *nc_packet)
+{
+	batadv_send_skb_packet(nc_packet->skb,
+			       nc_packet->neigh_node->if_incoming,
+			       nc_packet->nc_path->next_hop);
+	nc_packet->skb = NULL;
+	batadv_nc_packet_free(nc_packet);
+}
+
+/**
+ * batadv_nc_sniffed_purge - Checks timestamp of given sniffed nc_packet.
+ * @bat_priv: the bat priv with all the soft interface information
+ * @nc_path: the nc path the packet belongs to
+ * @nc_packet: the nc packet to be checked
+ *
+ * Checks whether the given sniffed (overheard) nc_packet has hit its buffering
+ * timeout. If so, the packet is no longer kept and the entry deleted from the
+ * queue. Has to be called with the appropriate locks.
+ *
+ * Returns false as soon as the entry in the fifo queue has not been timed out
+ * yet and true otherwise.
+ */
+static bool batadv_nc_sniffed_purge(struct batadv_priv *bat_priv,
+				    struct batadv_nc_path *nc_path,
+				    struct batadv_nc_packet *nc_packet)
+{
+	unsigned long timeout = bat_priv->nc.max_buffer_time;
+	bool res = false;
+
+	/* Packets are added to tail, so the remaining packets did not time
+	 * out and we can stop processing the current queue
+	 */
+	if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_ACTIVE &&
+	    !batadv_has_timed_out(nc_packet->timestamp, timeout))
+		goto out;
+
+	/* purge nc packet */
+	list_del(&nc_packet->list);
+	batadv_nc_packet_free(nc_packet);
+
+	res = true;
+
+out:
+	return res;
+}
+
+/**
+ * batadv_nc_fwd_flush - Checks the timestamp of the given nc packet.
+ * @bat_priv: the bat priv with all the soft interface information
+ * @nc_path: the nc path the packet belongs to
+ * @nc_packet: the nc packet to be checked
+ *
+ * Checks whether the given nc packet has hit its forward timeout. If so, the
+ * packet is no longer delayed, immediately sent and the entry deleted from the
+ * queue. Has to be called with the appropriate locks.
+ *
+ * Returns false as soon as the entry in the fifo queue has not been timed out
+ * yet and true otherwise.
+ */
+static bool batadv_nc_fwd_flush(struct batadv_priv *bat_priv,
+				struct batadv_nc_path *nc_path,
+				struct batadv_nc_packet *nc_packet)
+{
+	unsigned long timeout = bat_priv->nc.max_fwd_delay;
+
+	/* Packets are added to tail, so the remaining packets did not time
+	 * out and we can stop processing the current queue
+	 */
+	if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_ACTIVE &&
+	    !batadv_has_timed_out(nc_packet->timestamp, timeout))
+		return false;
+
+	/* Send packet */
+	batadv_inc_counter(bat_priv, BATADV_CNT_FORWARD);
+	batadv_add_counter(bat_priv, BATADV_CNT_FORWARD_BYTES,
+			   nc_packet->skb->len + ETH_HLEN);
+	list_del(&nc_packet->list);
+	batadv_nc_send_packet(nc_packet);
+
+	return true;
+}
+
+/**
+ * batadv_nc_process_nc_paths - traverse given nc packet pool and free timed out
+ *  nc packets
+ * @bat_priv: the bat priv with all the soft interface information
+ * @hash: to be processed hash table
+ * @process_fn: Function called to process given nc packet. Should return true
+ *	        to encourage this function to proceed with the next packet.
+ *	        Otherwise the rest of the current queue is skipped.
+ */
+static void
+batadv_nc_process_nc_paths(struct batadv_priv *bat_priv,
+			   struct batadv_hashtable *hash,
+			   bool (*process_fn)(struct batadv_priv *,
+					      struct batadv_nc_path *,
+					      struct batadv_nc_packet *))
+{
+	struct hlist_head *head;
+	struct batadv_nc_packet *nc_packet, *nc_packet_tmp;
+	struct batadv_nc_path *nc_path;
+	bool ret;
+	int i;
+
+	if (!hash)
+		return;
+
+	/* Loop hash table bins */
+	for (i = 0; i < hash->size; i++) {
+		head = &hash->table[i];
+
+		/* Loop coding paths */
+		rcu_read_lock();
+		hlist_for_each_entry_rcu(nc_path, head, hash_entry) {
+			/* Loop packets */
+			spin_lock_bh(&nc_path->packet_list_lock);
+			list_for_each_entry_safe(nc_packet, nc_packet_tmp,
+						 &nc_path->packet_list, list) {
+				ret = process_fn(bat_priv, nc_path, nc_packet);
+				if (!ret)
+					break;
+			}
+			spin_unlock_bh(&nc_path->packet_list_lock);
+		}
+		rcu_read_unlock();
+	}
+}
+
+/**
+ * batadv_nc_worker - periodic task for house keeping related to network coding
+ * @work: kernel work struct
+ */
+static void batadv_nc_worker(struct work_struct *work)
+{
+	struct delayed_work *delayed_work;
+	struct batadv_priv_nc *priv_nc;
+	struct batadv_priv *bat_priv;
+	unsigned long timeout;
+
+	delayed_work = container_of(work, struct delayed_work, work);
+	priv_nc = container_of(delayed_work, struct batadv_priv_nc, work);
+	bat_priv = container_of(priv_nc, struct batadv_priv, nc);
+
+	batadv_nc_purge_orig_hash(bat_priv);
+	batadv_nc_purge_paths(bat_priv, bat_priv->nc.coding_hash,
+			      batadv_nc_to_purge_nc_path_coding);
+	batadv_nc_purge_paths(bat_priv, bat_priv->nc.decoding_hash,
+			      batadv_nc_to_purge_nc_path_decoding);
+
+	timeout = bat_priv->nc.max_fwd_delay;
+
+	if (batadv_has_timed_out(bat_priv->nc.timestamp_fwd_flush, timeout)) {
+		batadv_nc_process_nc_paths(bat_priv, bat_priv->nc.coding_hash,
+					   batadv_nc_fwd_flush);
+		bat_priv->nc.timestamp_fwd_flush = jiffies;
+	}
+
+	if (batadv_has_timed_out(bat_priv->nc.timestamp_sniffed_purge,
+				 bat_priv->nc.max_buffer_time)) {
+		batadv_nc_process_nc_paths(bat_priv, bat_priv->nc.decoding_hash,
+					   batadv_nc_sniffed_purge);
+		bat_priv->nc.timestamp_sniffed_purge = jiffies;
+	}
+
+	/* Schedule a new check */
+	batadv_nc_start_timer(bat_priv);
+}
+
+/**
+ * batadv_can_nc_with_orig - checks whether the given orig node is suitable for
+ *  coding or not
+ * @bat_priv: the bat priv with all the soft interface information
+ * @orig_node: neighboring orig node which may be used as nc candidate
+ * @ogm_packet: incoming ogm packet also used for the checks
+ *
+ * Returns true if:
+ *  1) The OGM must have the most recent sequence number.
+ *  2) The TTL must be decremented by one and only one.
+ *  3) The OGM must be received from the first hop from orig_node.
+ *  4) The TQ value of the OGM must be above bat_priv->nc.min_tq.
+ */
+static bool batadv_can_nc_with_orig(struct batadv_priv *bat_priv,
+				    struct batadv_orig_node *orig_node,
+				    struct batadv_ogm_packet *ogm_packet)
+{
+	if (orig_node->last_real_seqno != ntohl(ogm_packet->seqno))
+		return false;
+	if (orig_node->last_ttl != ogm_packet->header.ttl + 1)
+		return false;
+	if (!batadv_compare_eth(ogm_packet->orig, ogm_packet->prev_sender))
+		return false;
+	if (ogm_packet->tq < bat_priv->nc.min_tq)
+		return false;
+
+	return true;
+}
+
+/**
+ * batadv_nc_find_nc_node - search for an existing nc node and return it
+ * @orig_node: orig node originating the ogm packet
+ * @orig_neigh_node: neighboring orig node from which we received the ogm packet
+ *  (can be equal to orig_node)
+ * @in_coding: traverse incoming or outgoing network coding list
+ *
+ * Returns the nc_node if found, NULL otherwise.
+ */
+static struct batadv_nc_node
+*batadv_nc_find_nc_node(struct batadv_orig_node *orig_node,
+			struct batadv_orig_node *orig_neigh_node,
+			bool in_coding)
+{
+	struct batadv_nc_node *nc_node, *nc_node_out = NULL;
+	struct list_head *list;
+
+	if (in_coding)
+		list = &orig_neigh_node->in_coding_list;
+	else
+		list = &orig_neigh_node->out_coding_list;
+
+	/* Traverse list of nc_nodes to orig_node */
+	rcu_read_lock();
+	list_for_each_entry_rcu(nc_node, list, list) {
+		if (!batadv_compare_eth(nc_node->addr, orig_node->orig))
+			continue;
+
+		if (!atomic_inc_not_zero(&nc_node->refcount))
+			continue;
+
+		/* Found a match */
+		nc_node_out = nc_node;
+		break;
+	}
+	rcu_read_unlock();
+
+	return nc_node_out;
+}
+
+/**
+ * batadv_nc_get_nc_node - retrieves an nc node or creates the entry if it was
+ *  not found
+ * @bat_priv: the bat priv with all the soft interface information
+ * @orig_node: orig node originating the ogm packet
+ * @orig_neigh_node: neighboring orig node from which we received the ogm packet
+ *  (can be equal to orig_node)
+ * @in_coding: traverse incoming or outgoing network coding list
+ *
+ * Returns the nc_node if found or created, NULL in case of an error.
+ */
+static struct batadv_nc_node
+*batadv_nc_get_nc_node(struct batadv_priv *bat_priv,
+		       struct batadv_orig_node *orig_node,
+		       struct batadv_orig_node *orig_neigh_node,
+		       bool in_coding)
+{
+	struct batadv_nc_node *nc_node;
+	spinlock_t *lock; /* Used to lock list selected by "int in_coding" */
+	struct list_head *list;
+
+	/* Check if nc_node is already added */
+	nc_node = batadv_nc_find_nc_node(orig_node, orig_neigh_node, in_coding);
+
+	/* Node found */
+	if (nc_node)
+		return nc_node;
+
+	nc_node = kzalloc(sizeof(*nc_node), GFP_ATOMIC);
+	if (!nc_node)
+		return NULL;
+
+	if (!atomic_inc_not_zero(&orig_neigh_node->refcount))
+		goto free;
+
+	/* Initialize nc_node */
+	INIT_LIST_HEAD(&nc_node->list);
+	memcpy(nc_node->addr, orig_node->orig, ETH_ALEN);
+	nc_node->orig_node = orig_neigh_node;
+	atomic_set(&nc_node->refcount, 2);
+
+	/* Select ingoing or outgoing coding node */
+	if (in_coding) {
+		lock = &orig_neigh_node->in_coding_list_lock;
+		list = &orig_neigh_node->in_coding_list;
+	} else {
+		lock = &orig_neigh_node->out_coding_list_lock;
+		list = &orig_neigh_node->out_coding_list;
+	}
+
+	batadv_dbg(BATADV_DBG_NC, bat_priv, "Adding nc_node %pM -> %pM\n",
+		   nc_node->addr, nc_node->orig_node->orig);
+
+	/* Add nc_node to orig_node */
+	spin_lock_bh(lock);
+	list_add_tail_rcu(&nc_node->list, list);
+	spin_unlock_bh(lock);
+
+	return nc_node;
+
+free:
+	kfree(nc_node);
+	return NULL;
+}
+
+/**
+ * batadv_nc_update_nc_node - updates stored incoming and outgoing nc node structs
+ *  (best called on incoming OGMs)
+ * @bat_priv: the bat priv with all the soft interface information
+ * @orig_node: orig node originating the ogm packet
+ * @orig_neigh_node: neighboring orig node from which we received the ogm packet
+ *  (can be equal to orig_node)
+ * @ogm_packet: incoming ogm packet
+ * @is_single_hop_neigh: orig_node is a single hop neighbor
+ */
+void batadv_nc_update_nc_node(struct batadv_priv *bat_priv,
+			      struct batadv_orig_node *orig_node,
+			      struct batadv_orig_node *orig_neigh_node,
+			      struct batadv_ogm_packet *ogm_packet,
+			      int is_single_hop_neigh)
+{
+	struct batadv_nc_node *in_nc_node = NULL, *out_nc_node = NULL;
+
+	/* Check if network coding is enabled */
+	if (!atomic_read(&bat_priv->network_coding))
+		goto out;
+
+	/* accept ogms from 'good' neighbors and single hop neighbors */
+	if (!batadv_can_nc_with_orig(bat_priv, orig_node, ogm_packet) &&
+	    !is_single_hop_neigh)
+		goto out;
+
+	/* Add orig_node as in_nc_node on hop */
+	in_nc_node = batadv_nc_get_nc_node(bat_priv, orig_node,
+					   orig_neigh_node, true);
+	if (!in_nc_node)
+		goto out;
+
+	in_nc_node->last_seen = jiffies;
+
+	/* Add hop as out_nc_node on orig_node */
+	out_nc_node = batadv_nc_get_nc_node(bat_priv, orig_neigh_node,
+					    orig_node, false);
+	if (!out_nc_node)
+		goto out;
+
+	out_nc_node->last_seen = jiffies;
+
+out:
+	if (in_nc_node)
+		batadv_nc_node_free_ref(in_nc_node);
+	if (out_nc_node)
+		batadv_nc_node_free_ref(out_nc_node);
+}
+
+/**
+ * batadv_nc_get_path - get existing nc_path or allocate a new one
+ * @bat_priv: the bat priv with all the soft interface information
+ * @hash: hash table containing the nc path
+ * @src: ethernet source address - first half of the nc path search key
+ * @dst: ethernet destination address - second half of the nc path search key
+ *
+ * Returns pointer to nc_path if the path was found or created, returns NULL
+ * on error.
+ */
+static struct batadv_nc_path *batadv_nc_get_path(struct batadv_priv *bat_priv,
+						 struct batadv_hashtable *hash,
+						 uint8_t *src,
+						 uint8_t *dst)
+{
+	int hash_added;
+	struct batadv_nc_path *nc_path, nc_path_key;
+
+	batadv_nc_hash_key_gen(&nc_path_key, src, dst);
+
+	/* Search for existing nc_path */
+	nc_path = batadv_nc_hash_find(hash, (void *)&nc_path_key);
+
+	if (nc_path) {
+		/* Set timestamp to delay removal of nc_path */
+		nc_path->last_valid = jiffies;
+		return nc_path;
+	}
+
+	/* No existing nc_path was found; create a new */
+	nc_path = kzalloc(sizeof(*nc_path), GFP_ATOMIC);
+
+	if (!nc_path)
+		return NULL;
+
+	/* Initialize nc_path */
+	INIT_LIST_HEAD(&nc_path->packet_list);
+	spin_lock_init(&nc_path->packet_list_lock);
+	atomic_set(&nc_path->refcount, 2);
+	nc_path->last_valid = jiffies;
+	memcpy(nc_path->next_hop, dst, ETH_ALEN);
+	memcpy(nc_path->prev_hop, src, ETH_ALEN);
+
+	batadv_dbg(BATADV_DBG_NC, bat_priv, "Adding nc_path %pM -> %pM\n",
+		   nc_path->prev_hop,
+		   nc_path->next_hop);
+
+	/* Add nc_path to hash table */
+	hash_added = batadv_hash_add(hash, batadv_nc_hash_compare,
+				     batadv_nc_hash_choose, &nc_path_key,
+				     &nc_path->hash_entry);
+
+	if (hash_added < 0) {
+		kfree(nc_path);
+		return NULL;
+	}
+
+	return nc_path;
+}
+
+/**
+ * batadv_nc_random_weight_tq - scale the receivers TQ-value to avoid unfair
+ *  selection of a receiver with slightly lower TQ than the other
+ * @tq: to be weighted tq value
+ */
+static uint8_t batadv_nc_random_weight_tq(uint8_t tq)
+{
+	uint8_t rand_val, rand_tq;
+
+	get_random_bytes(&rand_val, sizeof(rand_val));
+
+	/* randomize the estimated packet loss (max TQ - estimated TQ) */
+	rand_tq = rand_val * (BATADV_TQ_MAX_VALUE - tq);
+
+	/* normalize the randomized packet loss */
+	rand_tq /= BATADV_TQ_MAX_VALUE;
+
+	/* convert to (randomized) estimated tq again */
+	return BATADV_TQ_MAX_VALUE - rand_tq;
+}
+
+/**
+ * batadv_nc_memxor - XOR destination with source
+ * @dst: byte array to XOR into
+ * @src: byte array to XOR from
+ * @len: length of destination array
+ */
+static void batadv_nc_memxor(char *dst, const char *src, unsigned int len)
+{
+	unsigned int i;
+
+	for (i = 0; i < len; ++i)
+		dst[i] ^= src[i];
+}
+
+/**
+ * batadv_nc_code_packets - code a received unicast_packet with an nc packet
+ *  into a coded_packet and send it
+ * @bat_priv: the bat priv with all the soft interface information
+ * @skb: data skb to forward
+ * @ethhdr: pointer to the ethernet header inside the skb
+ * @nc_packet: structure containing the packet to the skb can be coded with
+ * @neigh_node: next hop to forward packet to
+ *
+ * Returns true if both packets are consumed, false otherwise.
+ */
+static bool batadv_nc_code_packets(struct batadv_priv *bat_priv,
+				   struct sk_buff *skb,
+				   struct ethhdr *ethhdr,
+				   struct batadv_nc_packet *nc_packet,
+				   struct batadv_neigh_node *neigh_node)
+{
+	uint8_t tq_weighted_neigh, tq_weighted_coding;
+	struct sk_buff *skb_dest, *skb_src;
+	struct batadv_unicast_packet *packet1;
+	struct batadv_unicast_packet *packet2;
+	struct batadv_coded_packet *coded_packet;
+	struct batadv_neigh_node *neigh_tmp, *router_neigh;
+	struct batadv_neigh_node *router_coding = NULL;
+	uint8_t *first_source, *first_dest, *second_source, *second_dest;
+	__be32 packet_id1, packet_id2;
+	size_t count;
+	bool res = false;
+	int coding_len;
+	int unicast_size = sizeof(*packet1);
+	int coded_size = sizeof(*coded_packet);
+	int header_add = coded_size - unicast_size;
+
+	router_neigh = batadv_orig_node_get_router(neigh_node->orig_node);
+	if (!router_neigh)
+		goto out;
+
+	neigh_tmp = nc_packet->neigh_node;
+	router_coding = batadv_orig_node_get_router(neigh_tmp->orig_node);
+	if (!router_coding)
+		goto out;
+
+	tq_weighted_neigh = batadv_nc_random_weight_tq(router_neigh->tq_avg);
+	tq_weighted_coding = batadv_nc_random_weight_tq(router_coding->tq_avg);
+
+	/* Select one destination for the MAC-header dst-field based on
+	 * weighted TQ-values.
+	 */
+	if (tq_weighted_neigh >= tq_weighted_coding) {
+		/* Destination from nc_packet is selected for MAC-header */
+		first_dest = nc_packet->nc_path->next_hop;
+		first_source = nc_packet->nc_path->prev_hop;
+		second_dest = neigh_node->addr;
+		second_source = ethhdr->h_source;
+		packet1 = (struct batadv_unicast_packet *)nc_packet->skb->data;
+		packet2 = (struct batadv_unicast_packet *)skb->data;
+		packet_id1 = nc_packet->packet_id;
+		packet_id2 = batadv_skb_crc32(skb,
+					      skb->data + sizeof(*packet2));
+	} else {
+		/* Destination for skb is selected for MAC-header */
+		first_dest = neigh_node->addr;
+		first_source = ethhdr->h_source;
+		second_dest = nc_packet->nc_path->next_hop;
+		second_source = nc_packet->nc_path->prev_hop;
+		packet1 = (struct batadv_unicast_packet *)skb->data;
+		packet2 = (struct batadv_unicast_packet *)nc_packet->skb->data;
+		packet_id1 = batadv_skb_crc32(skb,
+					      skb->data + sizeof(*packet1));
+		packet_id2 = nc_packet->packet_id;
+	}
+
+	/* Instead of zero padding the smallest data buffer, we
+	 * code into the largest.
+	 */
+	if (skb->len <= nc_packet->skb->len) {
+		skb_dest = nc_packet->skb;
+		skb_src = skb;
+	} else {
+		skb_dest = skb;
+		skb_src = nc_packet->skb;
+	}
+
+	/* coding_len is used when decoding the packet shorter packet */
+	coding_len = skb_src->len - unicast_size;
+
+	if (skb_linearize(skb_dest) < 0 || skb_linearize(skb_src) < 0)
+		goto out;
+
+	skb_push(skb_dest, header_add);
+
+	coded_packet = (struct batadv_coded_packet *)skb_dest->data;
+	skb_reset_mac_header(skb_dest);
+
+	coded_packet->header.packet_type = BATADV_CODED;
+	coded_packet->header.version = BATADV_COMPAT_VERSION;
+	coded_packet->header.ttl = packet1->header.ttl;
+
+	/* Info about first unicast packet */
+	memcpy(coded_packet->first_source, first_source, ETH_ALEN);
+	memcpy(coded_packet->first_orig_dest, packet1->dest, ETH_ALEN);
+	coded_packet->first_crc = packet_id1;
+	coded_packet->first_ttvn = packet1->ttvn;
+
+	/* Info about second unicast packet */
+	memcpy(coded_packet->second_dest, second_dest, ETH_ALEN);
+	memcpy(coded_packet->second_source, second_source, ETH_ALEN);
+	memcpy(coded_packet->second_orig_dest, packet2->dest, ETH_ALEN);
+	coded_packet->second_crc = packet_id2;
+	coded_packet->second_ttl = packet2->header.ttl;
+	coded_packet->second_ttvn = packet2->ttvn;
+	coded_packet->coded_len = htons(coding_len);
+
+	/* This is where the magic happens: Code skb_src into skb_dest */
+	batadv_nc_memxor(skb_dest->data + coded_size,
+			 skb_src->data + unicast_size, coding_len);
+
+	/* Update counters accordingly */
+	if (BATADV_SKB_CB(skb_src)->decoded &&
+	    BATADV_SKB_CB(skb_dest)->decoded) {
+		/* Both packets are recoded */
+		count = skb_src->len + ETH_HLEN;
+		count += skb_dest->len + ETH_HLEN;
+		batadv_add_counter(bat_priv, BATADV_CNT_NC_RECODE, 2);
+		batadv_add_counter(bat_priv, BATADV_CNT_NC_RECODE_BYTES, count);
+	} else if (!BATADV_SKB_CB(skb_src)->decoded &&
+		   !BATADV_SKB_CB(skb_dest)->decoded) {
+		/* Both packets are newly coded */
+		count = skb_src->len + ETH_HLEN;
+		count += skb_dest->len + ETH_HLEN;
+		batadv_add_counter(bat_priv, BATADV_CNT_NC_CODE, 2);
+		batadv_add_counter(bat_priv, BATADV_CNT_NC_CODE_BYTES, count);
+	} else if (BATADV_SKB_CB(skb_src)->decoded &&
+		   !BATADV_SKB_CB(skb_dest)->decoded) {
+		/* skb_src recoded and skb_dest is newly coded */
+		batadv_inc_counter(bat_priv, BATADV_CNT_NC_RECODE);
+		batadv_add_counter(bat_priv, BATADV_CNT_NC_RECODE_BYTES,
+				   skb_src->len + ETH_HLEN);
+		batadv_inc_counter(bat_priv, BATADV_CNT_NC_CODE);
+		batadv_add_counter(bat_priv, BATADV_CNT_NC_CODE_BYTES,
+				   skb_dest->len + ETH_HLEN);
+	} else if (!BATADV_SKB_CB(skb_src)->decoded &&
+		   BATADV_SKB_CB(skb_dest)->decoded) {
+		/* skb_src is newly coded and skb_dest is recoded */
+		batadv_inc_counter(bat_priv, BATADV_CNT_NC_CODE);
+		batadv_add_counter(bat_priv, BATADV_CNT_NC_CODE_BYTES,
+				   skb_src->len + ETH_HLEN);
+		batadv_inc_counter(bat_priv, BATADV_CNT_NC_RECODE);
+		batadv_add_counter(bat_priv, BATADV_CNT_NC_RECODE_BYTES,
+				   skb_dest->len + ETH_HLEN);
+	}
+
+	/* skb_src is now coded into skb_dest, so free it */
+	kfree_skb(skb_src);
+
+	/* avoid duplicate free of skb from nc_packet */
+	nc_packet->skb = NULL;
+	batadv_nc_packet_free(nc_packet);
+
+	/* Send the coded packet and return true */
+	batadv_send_skb_packet(skb_dest, neigh_node->if_incoming, first_dest);
+	res = true;
+out:
+	if (router_neigh)
+		batadv_neigh_node_free_ref(router_neigh);
+	if (router_coding)
+		batadv_neigh_node_free_ref(router_coding);
+	return res;
+}
+
+/**
+ * batadv_nc_skb_coding_possible - true if a decoded skb is available at dst.
+ * @skb: data skb to forward
+ * @dst: destination mac address of the other skb to code with
+ * @src: source mac address of skb
+ *
+ * Whenever we network code a packet we have to check whether we received it in
+ * a network coded form. If so, we may not be able to use it for coding because
+ * some neighbors may also have received (overheard) the packet in the network
+ * coded form without being able to decode it. It is hard to know which of the
+ * neighboring nodes was able to decode the packet, therefore we can only
+ * re-code the packet if the source of the previous encoded packet is involved.
+ * Since the source encoded the packet we can be certain it has all necessary
+ * decode information.
+ *
+ * Returns true if coding of a decoded packet is allowed.
+ */
+static bool batadv_nc_skb_coding_possible(struct sk_buff *skb,
+					  uint8_t *dst, uint8_t *src)
+{
+	if (BATADV_SKB_CB(skb)->decoded && !batadv_compare_eth(dst, src))
+		return false;
+	else
+		return true;
+}
+
+/**
+ * batadv_nc_path_search - Find the coding path matching in_nc_node and
+ *  out_nc_node to retrieve a buffered packet that can be used for coding.
+ * @bat_priv: the bat priv with all the soft interface information
+ * @in_nc_node: pointer to skb next hop's neighbor nc node
+ * @out_nc_node: pointer to skb source's neighbor nc node
+ * @skb: data skb to forward
+ * @eth_dst: next hop mac address of skb
+ *
+ * Returns true if coding of a decoded skb is allowed.
+ */
+static struct batadv_nc_packet *
+batadv_nc_path_search(struct batadv_priv *bat_priv,
+		      struct batadv_nc_node *in_nc_node,
+		      struct batadv_nc_node *out_nc_node,
+		      struct sk_buff *skb,
+		      uint8_t *eth_dst)
+{
+	struct batadv_nc_path *nc_path, nc_path_key;
+	struct batadv_nc_packet *nc_packet_out = NULL;
+	struct batadv_nc_packet *nc_packet, *nc_packet_tmp;
+	struct batadv_hashtable *hash = bat_priv->nc.coding_hash;
+	int idx;
+
+	if (!hash)
+		return NULL;
+
+	/* Create almost path key */
+	batadv_nc_hash_key_gen(&nc_path_key, in_nc_node->addr,
+			       out_nc_node->addr);
+	idx = batadv_nc_hash_choose(&nc_path_key, hash->size);
+
+	/* Check for coding opportunities in this nc_path */
+	rcu_read_lock();
+	hlist_for_each_entry_rcu(nc_path, &hash->table[idx], hash_entry) {
+		if (!batadv_compare_eth(nc_path->prev_hop, in_nc_node->addr))
+			continue;
+
+		if (!batadv_compare_eth(nc_path->next_hop, out_nc_node->addr))
+			continue;
+
+		spin_lock_bh(&nc_path->packet_list_lock);
+		if (list_empty(&nc_path->packet_list)) {
+			spin_unlock_bh(&nc_path->packet_list_lock);
+			continue;
+		}
+
+		list_for_each_entry_safe(nc_packet, nc_packet_tmp,
+					 &nc_path->packet_list, list) {
+			if (!batadv_nc_skb_coding_possible(nc_packet->skb,
+							   eth_dst,
+							   in_nc_node->addr))
+				continue;
+
+			/* Coding opportunity is found! */
+			list_del(&nc_packet->list);
+			nc_packet_out = nc_packet;
+			break;
+		}
+
+		spin_unlock_bh(&nc_path->packet_list_lock);
+		break;
+	}
+	rcu_read_unlock();
+
+	return nc_packet_out;
+}
+
+/**
+ * batadv_nc_skb_src_search - Loops through the list of neighoring nodes of the
+ *  skb's sender (may be equal to the originator).
+ * @bat_priv: the bat priv with all the soft interface information
+ * @skb: data skb to forward
+ * @eth_dst: next hop mac address of skb
+ * @eth_src: source mac address of skb
+ * @in_nc_node: pointer to skb next hop's neighbor nc node
+ *
+ * Returns an nc packet if a suitable coding packet was found, NULL otherwise.
+ */
+static struct batadv_nc_packet *
+batadv_nc_skb_src_search(struct batadv_priv *bat_priv,
+			 struct sk_buff *skb,
+			 uint8_t *eth_dst,
+			 uint8_t *eth_src,
+			 struct batadv_nc_node *in_nc_node)
+{
+	struct batadv_orig_node *orig_node;
+	struct batadv_nc_node *out_nc_node;
+	struct batadv_nc_packet *nc_packet = NULL;
+
+	orig_node = batadv_orig_hash_find(bat_priv, eth_src);
+	if (!orig_node)
+		return NULL;
+
+	rcu_read_lock();
+	list_for_each_entry_rcu(out_nc_node,
+				&orig_node->out_coding_list, list) {
+		/* Check if the skb is decoded and if recoding is possible */
+		if (!batadv_nc_skb_coding_possible(skb,
+						   out_nc_node->addr, eth_src))
+			continue;
+
+		/* Search for an opportunity in this nc_path */
+		nc_packet = batadv_nc_path_search(bat_priv, in_nc_node,
+						  out_nc_node, skb, eth_dst);
+		if (nc_packet)
+			break;
+	}
+	rcu_read_unlock();
+
+	batadv_orig_node_free_ref(orig_node);
+	return nc_packet;
+}
+
+/**
+ * batadv_nc_skb_store_before_coding - set the ethernet src and dst of the
+ *  unicast skb before it is stored for use in later decoding
+ * @bat_priv: the bat priv with all the soft interface information
+ * @skb: data skb to store
+ * @eth_dst_new: new destination mac address of skb
+ */
+static void batadv_nc_skb_store_before_coding(struct batadv_priv *bat_priv,
+					      struct sk_buff *skb,
+					      uint8_t *eth_dst_new)
+{
+	struct ethhdr *ethhdr;
+
+	/* Copy skb header to change the mac header */
+	skb = pskb_copy(skb, GFP_ATOMIC);
+	if (!skb)
+		return;
+
+	/* Set the mac header as if we actually sent the packet uncoded */
+	ethhdr = (struct ethhdr *)skb_mac_header(skb);
+	memcpy(ethhdr->h_source, ethhdr->h_dest, ETH_ALEN);
+	memcpy(ethhdr->h_dest, eth_dst_new, ETH_ALEN);
+
+	/* Set data pointer to MAC header to mimic packets from our tx path */
+	skb_push(skb, ETH_HLEN);
+
+	/* Add the packet to the decoding packet pool */
+	batadv_nc_skb_store_for_decoding(bat_priv, skb);
+
+	/* batadv_nc_skb_store_for_decoding() clones the skb, so we must free
+	 * our ref
+	 */
+	kfree_skb(skb);
+}
+
+/**
+ * batadv_nc_skb_dst_search - Loops through list of neighboring nodes to dst.
+ * @skb: data skb to forward
+ * @neigh_node: next hop to forward packet to
+ * @ethhdr: pointer to the ethernet header inside the skb
+ *
+ * Loops through list of neighboring nodes the next hop has a good connection to
+ * (receives OGMs with a sufficient quality). We need to find a neighbor of our
+ * next hop that potentially sent a packet which our next hop also received
+ * (overheard) and has stored for later decoding.
+ *
+ * Returns true if the skb was consumed (encoded packet sent) or false otherwise
+ */
+static bool batadv_nc_skb_dst_search(struct sk_buff *skb,
+				     struct batadv_neigh_node *neigh_node,
+				     struct ethhdr *ethhdr)
+{
+	struct net_device *netdev = neigh_node->if_incoming->soft_iface;
+	struct batadv_priv *bat_priv = netdev_priv(netdev);
+	struct batadv_orig_node *orig_node = neigh_node->orig_node;
+	struct batadv_nc_node *nc_node;
+	struct batadv_nc_packet *nc_packet = NULL;
+
+	rcu_read_lock();
+	list_for_each_entry_rcu(nc_node, &orig_node->in_coding_list, list) {
+		/* Search for coding opportunity with this in_nc_node */
+		nc_packet = batadv_nc_skb_src_search(bat_priv, skb,
+						     neigh_node->addr,
+						     ethhdr->h_source, nc_node);
+
+		/* Opportunity was found, so stop searching */
+		if (nc_packet)
+			break;
+	}
+	rcu_read_unlock();
+
+	if (!nc_packet)
+		return false;
+
+	/* Save packets for later decoding */
+	batadv_nc_skb_store_before_coding(bat_priv, skb,
+					  neigh_node->addr);
+	batadv_nc_skb_store_before_coding(bat_priv, nc_packet->skb,
+					  nc_packet->neigh_node->addr);
+
+	/* Code and send packets */
+	if (batadv_nc_code_packets(bat_priv, skb, ethhdr, nc_packet,
+				   neigh_node))
+		return true;
+
+	/* out of mem ? Coding failed - we have to free the buffered packet
+	 * to avoid memleaks. The skb passed as argument will be dealt with
+	 * by the calling function.
+	 */
+	batadv_nc_send_packet(nc_packet);
+	return false;
+}
+
+/**
+ * batadv_nc_skb_add_to_path - buffer skb for later encoding / decoding
+ * @skb: skb to add to path
+ * @nc_path: path to add skb to
+ * @neigh_node: next hop to forward packet to
+ * @packet_id: checksum to identify packet
+ *
+ * Returns true if the packet was buffered or false in case of an error.
+ */
+static bool batadv_nc_skb_add_to_path(struct sk_buff *skb,
+				      struct batadv_nc_path *nc_path,
+				      struct batadv_neigh_node *neigh_node,
+				      __be32 packet_id)
+{
+	struct batadv_nc_packet *nc_packet;
+
+	nc_packet = kzalloc(sizeof(*nc_packet), GFP_ATOMIC);
+	if (!nc_packet)
+		return false;
+
+	/* Initialize nc_packet */
+	nc_packet->timestamp = jiffies;
+	nc_packet->packet_id = packet_id;
+	nc_packet->skb = skb;
+	nc_packet->neigh_node = neigh_node;
+	nc_packet->nc_path = nc_path;
+
+	/* Add coding packet to list */
+	spin_lock_bh(&nc_path->packet_list_lock);
+	list_add_tail(&nc_packet->list, &nc_path->packet_list);
+	spin_unlock_bh(&nc_path->packet_list_lock);
+
+	return true;
+}
+
+/**
+ * batadv_nc_skb_forward - try to code a packet or add it to the coding packet
+ *  buffer
+ * @skb: data skb to forward
+ * @neigh_node: next hop to forward packet to
+ * @ethhdr: pointer to the ethernet header inside the skb
+ *
+ * Returns true if the skb was consumed (encoded packet sent) or false otherwise
+ */
+bool batadv_nc_skb_forward(struct sk_buff *skb,
+			   struct batadv_neigh_node *neigh_node,
+			   struct ethhdr *ethhdr)
+{
+	const struct net_device *netdev = neigh_node->if_incoming->soft_iface;
+	struct batadv_priv *bat_priv = netdev_priv(netdev);
+	struct batadv_unicast_packet *packet;
+	struct batadv_nc_path *nc_path;
+	__be32 packet_id;
+	u8 *payload;
+
+	/* Check if network coding is enabled */
+	if (!atomic_read(&bat_priv->network_coding))
+		goto out;
+
+	/* We only handle unicast packets */
+	payload = skb_network_header(skb);
+	packet = (struct batadv_unicast_packet *)payload;
+	if (packet->header.packet_type != BATADV_UNICAST)
+		goto out;
+
+	/* Try to find a coding opportunity and send the skb if one is found */
+	if (batadv_nc_skb_dst_search(skb, neigh_node, ethhdr))
+		return true;
+
+	/* Find or create a nc_path for this src-dst pair */
+	nc_path = batadv_nc_get_path(bat_priv,
+				     bat_priv->nc.coding_hash,
+				     ethhdr->h_source,
+				     neigh_node->addr);
+
+	if (!nc_path)
+		goto out;
+
+	/* Add skb to nc_path */
+	packet_id = batadv_skb_crc32(skb, payload + sizeof(*packet));
+	if (!batadv_nc_skb_add_to_path(skb, nc_path, neigh_node, packet_id))
+		goto free_nc_path;
+
+	/* Packet is consumed */
+	return true;
+
+free_nc_path:
+	batadv_nc_path_free_ref(nc_path);
+out:
+	/* Packet is not consumed */
+	return false;
+}
+
+/**
+ * batadv_nc_skb_store_for_decoding - save a clone of the skb which can be used
+ *  when decoding coded packets
+ * @bat_priv: the bat priv with all the soft interface information
+ * @skb: data skb to store
+ */
+void batadv_nc_skb_store_for_decoding(struct batadv_priv *bat_priv,
+				      struct sk_buff *skb)
+{
+	struct batadv_unicast_packet *packet;
+	struct batadv_nc_path *nc_path;
+	struct ethhdr *ethhdr = (struct ethhdr *)skb_mac_header(skb);
+	__be32 packet_id;
+	u8 *payload;
+
+	/* Check if network coding is enabled */
+	if (!atomic_read(&bat_priv->network_coding))
+		goto out;
+
+	/* Check for supported packet type */
+	payload = skb_network_header(skb);
+	packet = (struct batadv_unicast_packet *)payload;
+	if (packet->header.packet_type != BATADV_UNICAST)
+		goto out;
+
+	/* Find existing nc_path or create a new */
+	nc_path = batadv_nc_get_path(bat_priv,
+				     bat_priv->nc.decoding_hash,
+				     ethhdr->h_source,
+				     ethhdr->h_dest);
+
+	if (!nc_path)
+		goto out;
+
+	/* Clone skb and adjust skb->data to point at batman header */
+	skb = skb_clone(skb, GFP_ATOMIC);
+	if (unlikely(!skb))
+		goto free_nc_path;
+
+	if (unlikely(!pskb_may_pull(skb, ETH_HLEN)))
+		goto free_skb;
+
+	if (unlikely(!skb_pull_rcsum(skb, ETH_HLEN)))
+		goto free_skb;
+
+	/* Add skb to nc_path */
+	packet_id = batadv_skb_crc32(skb, payload + sizeof(*packet));
+	if (!batadv_nc_skb_add_to_path(skb, nc_path, NULL, packet_id))
+		goto free_skb;
+
+	batadv_inc_counter(bat_priv, BATADV_CNT_NC_BUFFER);
+	return;
+
+free_skb:
+	kfree_skb(skb);
+free_nc_path:
+	batadv_nc_path_free_ref(nc_path);
+out:
+	return;
+}
+
+/**
+ * batadv_nc_skb_store_sniffed_unicast - check if a received unicast packet
+ *  should be saved in the decoding buffer and, if so, store it there
+ * @bat_priv: the bat priv with all the soft interface information
+ * @skb: unicast skb to store
+ */
+void batadv_nc_skb_store_sniffed_unicast(struct batadv_priv *bat_priv,
+					 struct sk_buff *skb)
+{
+	struct ethhdr *ethhdr = (struct ethhdr *)skb_mac_header(skb);
+
+	if (batadv_is_my_mac(ethhdr->h_dest))
+		return;
+
+	/* Set data pointer to MAC header to mimic packets from our tx path */
+	skb_push(skb, ETH_HLEN);
+
+	batadv_nc_skb_store_for_decoding(bat_priv, skb);
+}
+
+/**
+ * batadv_nc_skb_decode_packet - decode given skb using the decode data stored
+ *  in nc_packet
+ * @skb: unicast skb to decode
+ * @nc_packet: decode data needed to decode the skb
+ *
+ * Returns pointer to decoded unicast packet if the packet was decoded or NULL
+ * in case of an error.
+ */
+static struct batadv_unicast_packet *
+batadv_nc_skb_decode_packet(struct sk_buff *skb,
+			    struct batadv_nc_packet *nc_packet)
+{
+	const int h_size = sizeof(struct batadv_unicast_packet);
+	const int h_diff = sizeof(struct batadv_coded_packet) - h_size;
+	struct batadv_unicast_packet *unicast_packet;
+	struct batadv_coded_packet coded_packet_tmp;
+	struct ethhdr *ethhdr, ethhdr_tmp;
+	uint8_t *orig_dest, ttl, ttvn;
+	unsigned int coding_len;
+
+	/* Save headers temporarily */
+	memcpy(&coded_packet_tmp, skb->data, sizeof(coded_packet_tmp));
+	memcpy(&ethhdr_tmp, skb_mac_header(skb), sizeof(ethhdr_tmp));
+
+	if (skb_cow(skb, 0) < 0)
+		return NULL;
+
+	if (unlikely(!skb_pull_rcsum(skb, h_diff)))
+		return NULL;
+
+	/* Data points to batman header, so set mac header 14 bytes before
+	 * and network to data
+	 */
+	skb_set_mac_header(skb, -ETH_HLEN);
+	skb_reset_network_header(skb);
+
+	/* Reconstruct original mac header */
+	ethhdr = (struct ethhdr *)skb_mac_header(skb);
+	memcpy(ethhdr, &ethhdr_tmp, sizeof(*ethhdr));
+
+	/* Select the correct unicast header information based on the location
+	 * of our mac address in the coded_packet header
+	 */
+	if (batadv_is_my_mac(coded_packet_tmp.second_dest)) {
+		/* If we are the second destination the packet was overheard,
+		 * so the Ethernet address must be copied to h_dest and
+		 * pkt_type changed from PACKET_OTHERHOST to PACKET_HOST
+		 */
+		memcpy(ethhdr->h_dest, coded_packet_tmp.second_dest, ETH_ALEN);
+		skb->pkt_type = PACKET_HOST;
+
+		orig_dest = coded_packet_tmp.second_orig_dest;
+		ttl = coded_packet_tmp.second_ttl;
+		ttvn = coded_packet_tmp.second_ttvn;
+	} else {
+		orig_dest = coded_packet_tmp.first_orig_dest;
+		ttl = coded_packet_tmp.header.ttl;
+		ttvn = coded_packet_tmp.first_ttvn;
+	}
+
+	coding_len = ntohs(coded_packet_tmp.coded_len);
+
+	if (coding_len > skb->len)
+		return NULL;
+
+	/* Here the magic is reversed:
+	 *   extract the missing packet from the received coded packet
+	 */
+	batadv_nc_memxor(skb->data + h_size,
+			 nc_packet->skb->data + h_size,
+			 coding_len);
+
+	/* Resize decoded skb if decoded with larger packet */
+	if (nc_packet->skb->len > coding_len + h_size)
+		pskb_trim_rcsum(skb, coding_len + h_size);
+
+	/* Create decoded unicast packet */
+	unicast_packet = (struct batadv_unicast_packet *)skb->data;
+	unicast_packet->header.packet_type = BATADV_UNICAST;
+	unicast_packet->header.version = BATADV_COMPAT_VERSION;
+	unicast_packet->header.ttl = ttl;
+	memcpy(unicast_packet->dest, orig_dest, ETH_ALEN);
+	unicast_packet->ttvn = ttvn;
+
+	batadv_nc_packet_free(nc_packet);
+	return unicast_packet;
+}
+
+/**
+ * batadv_nc_find_decoding_packet - search through buffered decoding data to
+ *  find the data needed to decode the coded packet
+ * @bat_priv: the bat priv with all the soft interface information
+ * @ethhdr: pointer to the ethernet header inside the coded packet
+ * @coded: coded packet we try to find decode data for
+ *
+ * Returns pointer to nc packet if the needed data was found or NULL otherwise.
+ */
+static struct batadv_nc_packet *
+batadv_nc_find_decoding_packet(struct batadv_priv *bat_priv,
+			       struct ethhdr *ethhdr,
+			       struct batadv_coded_packet *coded)
+{
+	struct batadv_hashtable *hash = bat_priv->nc.decoding_hash;
+	struct batadv_nc_packet *tmp_nc_packet, *nc_packet = NULL;
+	struct batadv_nc_path *nc_path, nc_path_key;
+	uint8_t *dest, *source;
+	__be32 packet_id;
+	int index;
+
+	if (!hash)
+		return NULL;
+
+	/* Select the correct packet id based on the location of our mac-addr */
+	dest = ethhdr->h_source;
+	if (!batadv_is_my_mac(coded->second_dest)) {
+		source = coded->second_source;
+		packet_id = coded->second_crc;
+	} else {
+		source = coded->first_source;
+		packet_id = coded->first_crc;
+	}
+
+	batadv_nc_hash_key_gen(&nc_path_key, source, dest);
+	index = batadv_nc_hash_choose(&nc_path_key, hash->size);
+
+	/* Search for matching coding path */
+	rcu_read_lock();
+	hlist_for_each_entry_rcu(nc_path, &hash->table[index], hash_entry) {
+		/* Find matching nc_packet */
+		spin_lock_bh(&nc_path->packet_list_lock);
+		list_for_each_entry(tmp_nc_packet,
+				    &nc_path->packet_list, list) {
+			if (packet_id == tmp_nc_packet->packet_id) {
+				list_del(&tmp_nc_packet->list);
+
+				nc_packet = tmp_nc_packet;
+				break;
+			}
+		}
+		spin_unlock_bh(&nc_path->packet_list_lock);
+
+		if (nc_packet)
+			break;
+	}
+	rcu_read_unlock();
+
+	if (!nc_packet)
+		batadv_dbg(BATADV_DBG_NC, bat_priv,
+			   "No decoding packet found for %u\n", packet_id);
+
+	return nc_packet;
+}
+
+/**
+ * batadv_nc_recv_coded_packet - try to decode coded packet and enqueue the
+ *  resulting unicast packet
+ * @skb: incoming coded packet
+ * @recv_if: pointer to interface this packet was received on
+ */
+static int batadv_nc_recv_coded_packet(struct sk_buff *skb,
+				       struct batadv_hard_iface *recv_if)
+{
+	struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface);
+	struct batadv_unicast_packet *unicast_packet;
+	struct batadv_coded_packet *coded_packet;
+	struct batadv_nc_packet *nc_packet;
+	struct ethhdr *ethhdr;
+	int hdr_size = sizeof(*coded_packet);
+
+	/* Check if network coding is enabled */
+	if (!atomic_read(&bat_priv->network_coding))
+		return NET_RX_DROP;
+
+	/* Make sure we can access (and remove) header */
+	if (unlikely(!pskb_may_pull(skb, hdr_size)))
+		return NET_RX_DROP;
+
+	coded_packet = (struct batadv_coded_packet *)skb->data;
+	ethhdr = (struct ethhdr *)skb_mac_header(skb);
+
+	/* Verify frame is destined for us */
+	if (!batadv_is_my_mac(ethhdr->h_dest) &&
+	    !batadv_is_my_mac(coded_packet->second_dest))
+		return NET_RX_DROP;
+
+	/* Update stat counter */
+	if (batadv_is_my_mac(coded_packet->second_dest))
+		batadv_inc_counter(bat_priv, BATADV_CNT_NC_SNIFFED);
+
+	nc_packet = batadv_nc_find_decoding_packet(bat_priv, ethhdr,
+						   coded_packet);
+	if (!nc_packet) {
+		batadv_inc_counter(bat_priv, BATADV_CNT_NC_DECODE_FAILED);
+		return NET_RX_DROP;
+	}
+
+	/* Make skb's linear, because decoding accesses the entire buffer */
+	if (skb_linearize(skb) < 0)
+		goto free_nc_packet;
+
+	if (skb_linearize(nc_packet->skb) < 0)
+		goto free_nc_packet;
+
+	/* Decode the packet */
+	unicast_packet = batadv_nc_skb_decode_packet(skb, nc_packet);
+	if (!unicast_packet) {
+		batadv_inc_counter(bat_priv, BATADV_CNT_NC_DECODE_FAILED);
+		goto free_nc_packet;
+	}
+
+	/* Mark packet as decoded to do correct recoding when forwarding */
+	BATADV_SKB_CB(skb)->decoded = true;
+	batadv_inc_counter(bat_priv, BATADV_CNT_NC_DECODE);
+	batadv_add_counter(bat_priv, BATADV_CNT_NC_DECODE_BYTES,
+			   skb->len + ETH_HLEN);
+	return batadv_recv_unicast_packet(skb, recv_if);
+
+free_nc_packet:
+	batadv_nc_packet_free(nc_packet);
+	return NET_RX_DROP;
+}
+
+/**
+ * batadv_nc_free - clean up network coding memory
+ * @bat_priv: the bat priv with all the soft interface information
+ */
+void batadv_nc_free(struct batadv_priv *bat_priv)
+{
+	batadv_recv_handler_unregister(BATADV_CODED);
+	cancel_delayed_work_sync(&bat_priv->nc.work);
+
+	batadv_nc_purge_paths(bat_priv, bat_priv->nc.coding_hash, NULL);
+	batadv_hash_destroy(bat_priv->nc.coding_hash);
+	batadv_nc_purge_paths(bat_priv, bat_priv->nc.decoding_hash, NULL);
+	batadv_hash_destroy(bat_priv->nc.decoding_hash);
+}
+
+/**
+ * batadv_nc_nodes_seq_print_text - print the nc node information
+ * @seq: seq file to print on
+ * @offset: not used
+ */
+int batadv_nc_nodes_seq_print_text(struct seq_file *seq, void *offset)
+{
+	struct net_device *net_dev = (struct net_device *)seq->private;
+	struct batadv_priv *bat_priv = netdev_priv(net_dev);
+	struct batadv_hashtable *hash = bat_priv->orig_hash;
+	struct batadv_hard_iface *primary_if;
+	struct hlist_head *head;
+	struct batadv_orig_node *orig_node;
+	struct batadv_nc_node *nc_node;
+	int i;
+
+	primary_if = batadv_seq_print_text_primary_if_get(seq);
+	if (!primary_if)
+		goto out;
+
+	/* Traverse list of originators */
+	for (i = 0; i < hash->size; i++) {
+		head = &hash->table[i];
+
+		/* For each orig_node in this bin */
+		rcu_read_lock();
+		hlist_for_each_entry_rcu(orig_node, head, hash_entry) {
+			seq_printf(seq, "Node:      %pM\n", orig_node->orig);
+
+			seq_puts(seq, " Ingoing:  ");
+			/* For each in_nc_node to this orig_node */
+			list_for_each_entry_rcu(nc_node,
+						&orig_node->in_coding_list,
+						list)
+				seq_printf(seq, "%pM ",
+					   nc_node->addr);
+			seq_puts(seq, "\n");
+
+			seq_puts(seq, " Outgoing: ");
+			/* For out_nc_node to this orig_node */
+			list_for_each_entry_rcu(nc_node,
+						&orig_node->out_coding_list,
+						list)
+				seq_printf(seq, "%pM ",
+					   nc_node->addr);
+			seq_puts(seq, "\n\n");
+		}
+		rcu_read_unlock();
+	}
+
+out:
+	if (primary_if)
+		batadv_hardif_free_ref(primary_if);
+	return 0;
+}
+
+/**
+ * batadv_nc_init_debugfs - create nc folder and related files in debugfs
+ * @bat_priv: the bat priv with all the soft interface information
+ */
+int batadv_nc_init_debugfs(struct batadv_priv *bat_priv)
+{
+	struct dentry *nc_dir, *file;
+
+	nc_dir = debugfs_create_dir("nc", bat_priv->debug_dir);
+	if (!nc_dir)
+		goto out;
+
+	file = debugfs_create_u8("min_tq", S_IRUGO | S_IWUSR, nc_dir,
+				 &bat_priv->nc.min_tq);
+	if (!file)
+		goto out;
+
+	file = debugfs_create_u32("max_fwd_delay", S_IRUGO | S_IWUSR, nc_dir,
+				  &bat_priv->nc.max_fwd_delay);
+	if (!file)
+		goto out;
+
+	file = debugfs_create_u32("max_buffer_time", S_IRUGO | S_IWUSR, nc_dir,
+				  &bat_priv->nc.max_buffer_time);
+	if (!file)
+		goto out;
+
+	return 0;
+
+out:
+	return -ENOMEM;
+}
diff --git a/net/batman-adv/network-coding.h b/net/batman-adv/network-coding.h
new file mode 100644
index 0000000..4fa6d0c
--- /dev/null
+++ b/net/batman-adv/network-coding.h
@@ -0,0 +1,123 @@
+/* Copyright (C) 2012-2013 B.A.T.M.A.N. contributors:
+ *
+ * Martin Hundebøll, Jeppe Ledet-Pedersen
+ *
+ * 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-1301, USA
+ */
+
+#ifndef _NET_BATMAN_ADV_NETWORK_CODING_H_
+#define _NET_BATMAN_ADV_NETWORK_CODING_H_
+
+#ifdef CONFIG_BATMAN_ADV_NC
+
+int batadv_nc_init(struct batadv_priv *bat_priv);
+void batadv_nc_free(struct batadv_priv *bat_priv);
+void batadv_nc_update_nc_node(struct batadv_priv *bat_priv,
+			      struct batadv_orig_node *orig_node,
+			      struct batadv_orig_node *orig_neigh_node,
+			      struct batadv_ogm_packet *ogm_packet,
+			      int is_single_hop_neigh);
+void batadv_nc_purge_orig(struct batadv_priv *bat_priv,
+			  struct batadv_orig_node *orig_node,
+			  bool (*to_purge)(struct batadv_priv *,
+					   struct batadv_nc_node *));
+void batadv_nc_init_bat_priv(struct batadv_priv *bat_priv);
+void batadv_nc_init_orig(struct batadv_orig_node *orig_node);
+bool batadv_nc_skb_forward(struct sk_buff *skb,
+			   struct batadv_neigh_node *neigh_node,
+			   struct ethhdr *ethhdr);
+void batadv_nc_skb_store_for_decoding(struct batadv_priv *bat_priv,
+				      struct sk_buff *skb);
+void batadv_nc_skb_store_sniffed_unicast(struct batadv_priv *bat_priv,
+					 struct sk_buff *skb);
+int batadv_nc_nodes_seq_print_text(struct seq_file *seq, void *offset);
+int batadv_nc_init_debugfs(struct batadv_priv *bat_priv);
+
+#else /* ifdef CONFIG_BATMAN_ADV_NC */
+
+static inline int batadv_nc_init(struct batadv_priv *bat_priv)
+{
+	return 0;
+}
+
+static inline void batadv_nc_free(struct batadv_priv *bat_priv)
+{
+	return;
+}
+
+static inline void
+batadv_nc_update_nc_node(struct batadv_priv *bat_priv,
+			 struct batadv_orig_node *orig_node,
+			 struct batadv_orig_node *orig_neigh_node,
+			 struct batadv_ogm_packet *ogm_packet,
+			 int is_single_hop_neigh)
+{
+	return;
+}
+
+static inline void
+batadv_nc_purge_orig(struct batadv_priv *bat_priv,
+		     struct batadv_orig_node *orig_node,
+		     bool (*to_purge)(struct batadv_priv *,
+				      struct batadv_nc_node *))
+{
+	return;
+}
+
+static inline void batadv_nc_init_bat_priv(struct batadv_priv *bat_priv)
+{
+	return;
+}
+
+static inline void batadv_nc_init_orig(struct batadv_orig_node *orig_node)
+{
+	return;
+}
+
+static inline bool batadv_nc_skb_forward(struct sk_buff *skb,
+					 struct batadv_neigh_node *neigh_node,
+					 struct ethhdr *ethhdr)
+{
+	return false;
+}
+
+static inline void
+batadv_nc_skb_store_for_decoding(struct batadv_priv *bat_priv,
+				 struct sk_buff *skb)
+{
+	return;
+}
+
+static inline void
+batadv_nc_skb_store_sniffed_unicast(struct batadv_priv *bat_priv,
+				    struct sk_buff *skb)
+{
+	return;
+}
+
+static inline int batadv_nc_nodes_seq_print_text(struct seq_file *seq,
+						 void *offset)
+{
+	return 0;
+}
+
+static inline int batadv_nc_init_debugfs(struct batadv_priv *bat_priv)
+{
+	return 0;
+}
+
+#endif /* ifdef CONFIG_BATMAN_ADV_NC */
+
+#endif /* _NET_BATMAN_ADV_NETWORK_CODING_H_ */
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c
index 96fb80b..2f34525 100644
--- a/net/batman-adv/originator.c
+++ b/net/batman-adv/originator.c
@@ -28,6 +28,7 @@
 #include "unicast.h"
 #include "soft-interface.h"
 #include "bridge_loop_avoidance.h"
+#include "network-coding.h"
 
 /* hash class keys */
 static struct lock_class_key batadv_orig_hash_lock_class_key;
@@ -142,6 +143,9 @@ static void batadv_orig_node_free_rcu(struct rcu_head *rcu)
 
 	spin_unlock_bh(&orig_node->neigh_list_lock);
 
+	/* Free nc_nodes */
+	batadv_nc_purge_orig(orig_node->bat_priv, orig_node, NULL);
+
 	batadv_frag_list_free(&orig_node->frag_list);
 	batadv_tt_global_del_orig(orig_node->bat_priv, orig_node,
 				  "originator timed out");
@@ -219,6 +223,8 @@ struct batadv_orig_node *batadv_get_orig_node(struct batadv_priv *bat_priv,
 	spin_lock_init(&orig_node->neigh_list_lock);
 	spin_lock_init(&orig_node->tt_buff_lock);
 
+	batadv_nc_init_orig(orig_node);
+
 	/* extra reference for return */
 	atomic_set(&orig_node->refcount, 2);
 
@@ -459,7 +465,7 @@ int batadv_orig_seq_print_text(struct seq_file *seq, void *offset)
 					   neigh_node_tmp->tq_avg);
 			}
 
-			seq_printf(seq, "\n");
+			seq_puts(seq, "\n");
 			batman_count++;
 
 next:
@@ -469,7 +475,7 @@ next:
 	}
 
 	if (batman_count == 0)
-		seq_printf(seq, "No batman nodes in range ...\n");
+		seq_puts(seq, "No batman nodes in range ...\n");
 
 out:
 	if (primary_if)
diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h
index ed0aa89..a51ccfc 100644
--- a/net/batman-adv/packet.h
+++ b/net/batman-adv/packet.h
@@ -30,6 +30,7 @@ enum batadv_packettype {
 	BATADV_TT_QUERY		= 0x07,
 	BATADV_ROAM_ADV		= 0x08,
 	BATADV_UNICAST_4ADDR	= 0x09,
+	BATADV_CODED		= 0x0a,
 };
 
 /**
@@ -278,4 +279,36 @@ struct batadv_tt_change {
 	uint8_t addr[ETH_ALEN];
 } __packed;
 
+/**
+ * struct batadv_coded_packet - network coded packet
+ * @header: common batman packet header and ttl of first included packet
+ * @reserved: Align following fields to 2-byte boundaries
+ * @first_source: original source of first included packet
+ * @first_orig_dest: original destinal of first included packet
+ * @first_crc: checksum of first included packet
+ * @first_ttvn: tt-version number of first included packet
+ * @second_ttl: ttl of second packet
+ * @second_dest: second receiver of this coded packet
+ * @second_source: original source of second included packet
+ * @second_orig_dest: original destination of second included packet
+ * @second_crc: checksum of second included packet
+ * @second_ttvn: tt version number of second included packet
+ * @coded_len: length of network coded part of the payload
+ */
+struct batadv_coded_packet {
+	struct batadv_header header;
+	uint8_t  first_ttvn;
+	/* uint8_t  first_dest[ETH_ALEN]; - saved in mac header destination */
+	uint8_t  first_source[ETH_ALEN];
+	uint8_t  first_orig_dest[ETH_ALEN];
+	__be32   first_crc;
+	uint8_t  second_ttl;
+	uint8_t  second_ttvn;
+	uint8_t  second_dest[ETH_ALEN];
+	uint8_t  second_source[ETH_ALEN];
+	uint8_t  second_orig_dest[ETH_ALEN];
+	__be32   second_crc;
+	__be16   coded_len;
+};
+
 #endif /* _NET_BATMAN_ADV_PACKET_H_ */
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c
index 5ee21ce..8f88967 100644
--- a/net/batman-adv/routing.c
+++ b/net/batman-adv/routing.c
@@ -29,6 +29,7 @@
 #include "unicast.h"
 #include "bridge_loop_avoidance.h"
 #include "distributed-arp-table.h"
+#include "network-coding.h"
 
 static int batadv_route_unicast_packet(struct sk_buff *skb,
 				       struct batadv_hard_iface *recv_if);
@@ -548,27 +549,37 @@ batadv_find_ifalter_router(struct batadv_orig_node *primary_orig,
 	return router;
 }
 
+/**
+ * batadv_check_unicast_packet - Check for malformed unicast packets
+ * @skb: packet to check
+ * @hdr_size: size of header to pull
+ *
+ * Check for short header and bad addresses in given packet. Returns negative
+ * value when check fails and 0 otherwise. The negative value depends on the
+ * reason: -ENODATA for bad header, -EBADR for broadcast destination or source,
+ * and -EREMOTE for non-local (other host) destination.
+ */
 static int batadv_check_unicast_packet(struct sk_buff *skb, int hdr_size)
 {
 	struct ethhdr *ethhdr;
 
 	/* drop packet if it has not necessary minimum size */
 	if (unlikely(!pskb_may_pull(skb, hdr_size)))
-		return -1;
+		return -ENODATA;
 
 	ethhdr = (struct ethhdr *)skb_mac_header(skb);
 
 	/* packet with unicast indication but broadcast recipient */
 	if (is_broadcast_ether_addr(ethhdr->h_dest))
-		return -1;
+		return -EBADR;
 
 	/* packet with broadcast sender address */
 	if (is_broadcast_ether_addr(ethhdr->h_source))
-		return -1;
+		return -EBADR;
 
 	/* not for me */
 	if (!batadv_is_my_mac(ethhdr->h_dest))
-		return -1;
+		return -EREMOTE;
 
 	return 0;
 }
@@ -850,15 +861,18 @@ static int batadv_route_unicast_packet(struct sk_buff *skb,
 	/* decrement ttl */
 	unicast_packet->header.ttl--;
 
-	/* Update stats counter */
-	batadv_inc_counter(bat_priv, BATADV_CNT_FORWARD);
-	batadv_add_counter(bat_priv, BATADV_CNT_FORWARD_BYTES,
-			   skb->len + ETH_HLEN);
-
-	/* route it */
-	if (batadv_send_skb_to_orig(skb, orig_node, recv_if))
+	/* network code packet if possible */
+	if (batadv_nc_skb_forward(skb, neigh_node, ethhdr)) {
+		ret = NET_RX_SUCCESS;
+	} else if (batadv_send_skb_to_orig(skb, orig_node, recv_if)) {
 		ret = NET_RX_SUCCESS;
 
+		/* Update stats counter */
+		batadv_inc_counter(bat_priv, BATADV_CNT_FORWARD);
+		batadv_add_counter(bat_priv, BATADV_CNT_FORWARD_BYTES,
+				   skb->len + ETH_HLEN);
+	}
+
 out:
 	if (neigh_node)
 		batadv_neigh_node_free_ref(neigh_node);
@@ -1033,7 +1047,7 @@ int batadv_recv_unicast_packet(struct sk_buff *skb,
 	struct batadv_unicast_4addr_packet *unicast_4addr_packet;
 	uint8_t *orig_addr;
 	struct batadv_orig_node *orig_node = NULL;
-	int hdr_size = sizeof(*unicast_packet);
+	int check, hdr_size = sizeof(*unicast_packet);
 	bool is4addr;
 
 	unicast_packet = (struct batadv_unicast_packet *)skb->data;
@@ -1044,7 +1058,16 @@ int batadv_recv_unicast_packet(struct sk_buff *skb,
 	if (is4addr)
 		hdr_size = sizeof(*unicast_4addr_packet);
 
-	if (batadv_check_unicast_packet(skb, hdr_size) < 0)
+	/* function returns -EREMOTE for promiscuous packets */
+	check = batadv_check_unicast_packet(skb, hdr_size);
+
+	/* Even though the packet is not for us, we might save it to use for
+	 * decoding a later received coded packet
+	 */
+	if (check == -EREMOTE)
+		batadv_nc_skb_store_sniffed_unicast(bat_priv, skb);
+
+	if (check < 0)
 		return NET_RX_DROP;
 
 	if (!batadv_check_unicast_ttvn(bat_priv, skb))
diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c
index a67cffd..263cfd1 100644
--- a/net/batman-adv/send.c
+++ b/net/batman-adv/send.c
@@ -27,6 +27,7 @@
 #include "vis.h"
 #include "gateway_common.h"
 #include "originator.h"
+#include "network-coding.h"
 
 #include <linux/if_ether.h>
 
@@ -39,6 +40,7 @@ int batadv_send_skb_packet(struct sk_buff *skb,
 			   struct batadv_hard_iface *hard_iface,
 			   const uint8_t *dst_addr)
 {
+	struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
 	struct ethhdr *ethhdr;
 
 	if (hard_iface->if_status != BATADV_IF_ACTIVE)
@@ -70,6 +72,9 @@ int batadv_send_skb_packet(struct sk_buff *skb,
 
 	skb->dev = hard_iface->net_dev;
 
+	/* Save a clone of the skb to use when decoding coded packets */
+	batadv_nc_skb_store_for_decoding(bat_priv, skb);
+
 	/* dev_queue_xmit() returns a negative result on error.	 However on
 	 * congestion and traffic shaping, it drops and returns NET_XMIT_DROP
 	 * (which is > 0). This will not be treated as an error.
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c
index 2711e87..403b8c4 100644
--- a/net/batman-adv/soft-interface.c
+++ b/net/batman-adv/soft-interface.c
@@ -37,6 +37,7 @@
 #include <linux/if_ether.h>
 #include "unicast.h"
 #include "bridge_loop_avoidance.h"
+#include "network-coding.h"
 
 
 static int batadv_get_settings(struct net_device *dev, struct ethtool_cmd *cmd);
@@ -401,55 +402,6 @@ static void batadv_set_lockdep_class(struct net_device *dev)
 }
 
 /**
- * batadv_softif_init - Late stage initialization of soft interface
- * @dev: registered network device to modify
- *
- * Returns error code on failures
- */
-static int batadv_softif_init(struct net_device *dev)
-{
-	batadv_set_lockdep_class(dev);
-
-	return 0;
-}
-
-static const struct net_device_ops batadv_netdev_ops = {
-	.ndo_init = batadv_softif_init,
-	.ndo_open = batadv_interface_open,
-	.ndo_stop = batadv_interface_release,
-	.ndo_get_stats = batadv_interface_stats,
-	.ndo_set_mac_address = batadv_interface_set_mac_addr,
-	.ndo_change_mtu = batadv_interface_change_mtu,
-	.ndo_start_xmit = batadv_interface_tx,
-	.ndo_validate_addr = eth_validate_addr
-};
-
-static void batadv_interface_setup(struct net_device *dev)
-{
-	struct batadv_priv *priv = netdev_priv(dev);
-
-	ether_setup(dev);
-
-	dev->netdev_ops = &batadv_netdev_ops;
-	dev->destructor = free_netdev;
-	dev->tx_queue_len = 0;
-
-	/* can't call min_mtu, because the needed variables
-	 * have not been initialized yet
-	 */
-	dev->mtu = ETH_DATA_LEN;
-	/* reserve more space in the skbuff for our header */
-	dev->hard_header_len = BATADV_HEADER_LEN;
-
-	/* generate random address */
-	eth_hw_addr_random(dev);
-
-	SET_ETHTOOL_OPS(dev, &batadv_ethtool_ops);
-
-	memset(priv, 0, sizeof(*priv));
-}
-
-/**
  * batadv_softif_destroy_finish - cleans up the remains of a softif
  * @work: work queue item
  *
@@ -465,7 +417,6 @@ static void batadv_softif_destroy_finish(struct work_struct *work)
 				cleanup_work);
 	soft_iface = bat_priv->soft_iface;
 
-	batadv_debugfs_del_meshif(soft_iface);
 	batadv_sysfs_del_meshif(soft_iface);
 
 	rtnl_lock();
@@ -473,21 +424,22 @@ static void batadv_softif_destroy_finish(struct work_struct *work)
 	rtnl_unlock();
 }
 
-struct net_device *batadv_softif_create(const char *name)
+/**
+ * batadv_softif_init_late - late stage initialization of soft interface
+ * @dev: registered network device to modify
+ *
+ * Returns error code on failures
+ */
+static int batadv_softif_init_late(struct net_device *dev)
 {
-	struct net_device *soft_iface;
 	struct batadv_priv *bat_priv;
 	int ret;
 	size_t cnt_len = sizeof(uint64_t) * BATADV_CNT_NUM;
 
-	soft_iface = alloc_netdev(sizeof(*bat_priv), name,
-				  batadv_interface_setup);
-
-	if (!soft_iface)
-		goto out;
+	batadv_set_lockdep_class(dev);
 
-	bat_priv = netdev_priv(soft_iface);
-	bat_priv->soft_iface = soft_iface;
+	bat_priv = netdev_priv(dev);
+	bat_priv->soft_iface = dev;
 	INIT_WORK(&bat_priv->cleanup_work, batadv_softif_destroy_finish);
 
 	/* batadv_interface_stats() needs to be available as soon as
@@ -495,14 +447,7 @@ struct net_device *batadv_softif_create(const char *name)
 	 */
 	bat_priv->bat_counters = __alloc_percpu(cnt_len, __alignof__(uint64_t));
 	if (!bat_priv->bat_counters)
-		goto free_soft_iface;
-
-	ret = register_netdevice(soft_iface);
-	if (ret < 0) {
-		pr_err("Unable to register the batman interface '%s': %i\n",
-		       name, ret);
-		goto free_bat_counters;
-	}
+		return -ENOMEM;
 
 	atomic_set(&bat_priv->aggregated_ogms, 1);
 	atomic_set(&bat_priv->bonding, 0);
@@ -540,49 +485,189 @@ struct net_device *batadv_softif_create(const char *name)
 	bat_priv->primary_if = NULL;
 	bat_priv->num_ifaces = 0;
 
-	ret = batadv_algo_select(bat_priv, batadv_routing_algo);
-	if (ret < 0)
-		goto unreg_soft_iface;
+	batadv_nc_init_bat_priv(bat_priv);
 
-	ret = batadv_sysfs_add_meshif(soft_iface);
+	ret = batadv_algo_select(bat_priv, batadv_routing_algo);
 	if (ret < 0)
-		goto unreg_soft_iface;
+		goto free_bat_counters;
 
-	ret = batadv_debugfs_add_meshif(soft_iface);
+	ret = batadv_debugfs_add_meshif(dev);
 	if (ret < 0)
-		goto unreg_sysfs;
+		goto free_bat_counters;
 
-	ret = batadv_mesh_init(soft_iface);
+	ret = batadv_mesh_init(dev);
 	if (ret < 0)
 		goto unreg_debugfs;
 
-	return soft_iface;
+	return 0;
 
 unreg_debugfs:
-	batadv_debugfs_del_meshif(soft_iface);
-unreg_sysfs:
-	batadv_sysfs_del_meshif(soft_iface);
-unreg_soft_iface:
-	free_percpu(bat_priv->bat_counters);
-	unregister_netdevice(soft_iface);
-	return NULL;
-
+	batadv_debugfs_del_meshif(dev);
 free_bat_counters:
 	free_percpu(bat_priv->bat_counters);
-free_soft_iface:
-	free_netdev(soft_iface);
+
+	return ret;
+}
+
+/**
+ * batadv_softif_slave_add - Add a slave interface to a batadv_soft_interface
+ * @dev: batadv_soft_interface used as master interface
+ * @slave_dev: net_device which should become the slave interface
+ *
+ * Return 0 if successful or error otherwise.
+ */
+static int batadv_softif_slave_add(struct net_device *dev,
+				   struct net_device *slave_dev)
+{
+	struct batadv_hard_iface *hard_iface;
+	int ret = -EINVAL;
+
+	hard_iface = batadv_hardif_get_by_netdev(slave_dev);
+	if (!hard_iface || hard_iface->soft_iface != NULL)
+		goto out;
+
+	ret = batadv_hardif_enable_interface(hard_iface, dev->name);
+
 out:
-	return NULL;
+	if (hard_iface)
+		batadv_hardif_free_ref(hard_iface);
+	return ret;
 }
 
-void batadv_softif_destroy(struct net_device *soft_iface)
+/**
+ * batadv_softif_slave_del - Delete a slave iface from a batadv_soft_interface
+ * @dev: batadv_soft_interface used as master interface
+ * @slave_dev: net_device which should be removed from the master interface
+ *
+ * Return 0 if successful or error otherwise.
+ */
+static int batadv_softif_slave_del(struct net_device *dev,
+				   struct net_device *slave_dev)
+{
+	struct batadv_hard_iface *hard_iface;
+	int ret = -EINVAL;
+
+	hard_iface = batadv_hardif_get_by_netdev(slave_dev);
+
+	if (!hard_iface || hard_iface->soft_iface != dev)
+		goto out;
+
+	batadv_hardif_disable_interface(hard_iface, BATADV_IF_CLEANUP_KEEP);
+	ret = 0;
+
+out:
+	if (hard_iface)
+		batadv_hardif_free_ref(hard_iface);
+	return ret;
+}
+
+static const struct net_device_ops batadv_netdev_ops = {
+	.ndo_init = batadv_softif_init_late,
+	.ndo_open = batadv_interface_open,
+	.ndo_stop = batadv_interface_release,
+	.ndo_get_stats = batadv_interface_stats,
+	.ndo_set_mac_address = batadv_interface_set_mac_addr,
+	.ndo_change_mtu = batadv_interface_change_mtu,
+	.ndo_start_xmit = batadv_interface_tx,
+	.ndo_validate_addr = eth_validate_addr,
+	.ndo_add_slave = batadv_softif_slave_add,
+	.ndo_del_slave = batadv_softif_slave_del,
+};
+
+/**
+ * batadv_softif_free - Deconstructor of batadv_soft_interface
+ * @dev: Device to cleanup and remove
+ */
+static void batadv_softif_free(struct net_device *dev)
+{
+	batadv_debugfs_del_meshif(dev);
+	batadv_mesh_free(dev);
+	free_netdev(dev);
+}
+
+/**
+ * batadv_softif_init_early - early stage initialization of soft interface
+ * @dev: registered network device to modify
+ */
+static void batadv_softif_init_early(struct net_device *dev)
+{
+	struct batadv_priv *priv = netdev_priv(dev);
+
+	ether_setup(dev);
+
+	dev->netdev_ops = &batadv_netdev_ops;
+	dev->destructor = batadv_softif_free;
+	dev->tx_queue_len = 0;
+
+	/* can't call min_mtu, because the needed variables
+	 * have not been initialized yet
+	 */
+	dev->mtu = ETH_DATA_LEN;
+	/* reserve more space in the skbuff for our header */
+	dev->hard_header_len = BATADV_HEADER_LEN;
+
+	/* generate random address */
+	eth_hw_addr_random(dev);
+
+	SET_ETHTOOL_OPS(dev, &batadv_ethtool_ops);
+
+	memset(priv, 0, sizeof(*priv));
+}
+
+struct net_device *batadv_softif_create(const char *name)
+{
+	struct net_device *soft_iface;
+	int ret;
+
+	soft_iface = alloc_netdev(sizeof(struct batadv_priv), name,
+				  batadv_softif_init_early);
+	if (!soft_iface)
+		return NULL;
+
+	soft_iface->rtnl_link_ops = &batadv_link_ops;
+
+	ret = register_netdevice(soft_iface);
+	if (ret < 0) {
+		pr_err("Unable to register the batman interface '%s': %i\n",
+		       name, ret);
+		free_netdev(soft_iface);
+		return NULL;
+	}
+
+	return soft_iface;
+}
+
+/**
+ * batadv_softif_destroy_sysfs - deletion of batadv_soft_interface via sysfs
+ * @soft_iface: the to-be-removed batman-adv interface
+ */
+void batadv_softif_destroy_sysfs(struct net_device *soft_iface)
 {
 	struct batadv_priv *bat_priv = netdev_priv(soft_iface);
 
-	batadv_mesh_free(soft_iface);
 	queue_work(batadv_event_workqueue, &bat_priv->cleanup_work);
 }
 
+/**
+ * batadv_softif_destroy_netlink - deletion of batadv_soft_interface via netlink
+ * @soft_iface: the to-be-removed batman-adv interface
+ * @head: list pointer
+ */
+static void batadv_softif_destroy_netlink(struct net_device *soft_iface,
+					  struct list_head *head)
+{
+	struct batadv_hard_iface *hard_iface;
+
+	list_for_each_entry(hard_iface, &batadv_hardif_list, list) {
+		if (hard_iface->soft_iface == soft_iface)
+			batadv_hardif_disable_interface(hard_iface,
+							BATADV_IF_CLEANUP_KEEP);
+	}
+
+	batadv_sysfs_del_meshif(soft_iface);
+	unregister_netdevice_queue(soft_iface, head);
+}
+
 int batadv_softif_is_valid(const struct net_device *net_dev)
 {
 	if (net_dev->netdev_ops->ndo_start_xmit == batadv_interface_tx)
@@ -591,6 +676,13 @@ int batadv_softif_is_valid(const struct net_device *net_dev)
 	return 0;
 }
 
+struct rtnl_link_ops batadv_link_ops __read_mostly = {
+	.kind		= "batadv",
+	.priv_size	= sizeof(struct batadv_priv),
+	.setup		= batadv_softif_init_early,
+	.dellink	= batadv_softif_destroy_netlink,
+};
+
 /* ethtool */
 static int batadv_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
@@ -662,6 +754,17 @@ static const struct {
 	{ "dat_put_rx" },
 	{ "dat_cached_reply_tx" },
 #endif
+#ifdef CONFIG_BATMAN_ADV_NC
+	{ "nc_code" },
+	{ "nc_code_bytes" },
+	{ "nc_recode" },
+	{ "nc_recode_bytes" },
+	{ "nc_buffer" },
+	{ "nc_decode" },
+	{ "nc_decode_bytes" },
+	{ "nc_decode_failed" },
+	{ "nc_sniffed" },
+#endif
 };
 
 static void batadv_get_strings(struct net_device *dev, uint32_t stringset,
diff --git a/net/batman-adv/soft-interface.h b/net/batman-adv/soft-interface.h
index 43182e5..2f2472c 100644
--- a/net/batman-adv/soft-interface.h
+++ b/net/batman-adv/soft-interface.h
@@ -25,7 +25,8 @@ void batadv_interface_rx(struct net_device *soft_iface,
 			 struct sk_buff *skb, struct batadv_hard_iface *recv_if,
 			 int hdr_size, struct batadv_orig_node *orig_node);
 struct net_device *batadv_softif_create(const char *name);
-void batadv_softif_destroy(struct net_device *soft_iface);
+void batadv_softif_destroy_sysfs(struct net_device *soft_iface);
 int batadv_softif_is_valid(const struct net_device *net_dev);
+extern struct rtnl_link_ops batadv_link_ops;
 
 #endif /* _NET_BATMAN_ADV_SOFT_INTERFACE_H_ */
diff --git a/net/batman-adv/sysfs.c b/net/batman-adv/sysfs.c
index afbba31..15a22ef 100644
--- a/net/batman-adv/sysfs.c
+++ b/net/batman-adv/sysfs.c
@@ -442,6 +442,9 @@ static BATADV_ATTR(gw_bandwidth, S_IRUGO | S_IWUSR, batadv_show_gw_bwidth,
 #ifdef CONFIG_BATMAN_ADV_DEBUG
 BATADV_ATTR_SIF_UINT(log_level, S_IRUGO | S_IWUSR, 0, BATADV_DBG_ALL, NULL);
 #endif
+#ifdef CONFIG_BATMAN_ADV_NC
+BATADV_ATTR_SIF_BOOL(network_coding, S_IRUGO | S_IWUSR, NULL);
+#endif
 
 static struct batadv_attribute *batadv_mesh_attrs[] = {
 	&batadv_attr_aggregated_ogms,
@@ -464,6 +467,9 @@ static struct batadv_attribute *batadv_mesh_attrs[] = {
 #ifdef CONFIG_BATMAN_ADV_DEBUG
 	&batadv_attr_log_level,
 #endif
+#ifdef CONFIG_BATMAN_ADV_NC
+	&batadv_attr_network_coding,
+#endif
 	NULL,
 };
 
@@ -582,13 +588,15 @@ static ssize_t batadv_store_mesh_iface(struct kobject *kobj,
 	}
 
 	if (status_tmp == BATADV_IF_NOT_IN_USE) {
-		batadv_hardif_disable_interface(hard_iface);
+		batadv_hardif_disable_interface(hard_iface,
+						BATADV_IF_CLEANUP_AUTO);
 		goto unlock;
 	}
 
 	/* if the interface already is in use */
 	if (hard_iface->if_status != BATADV_IF_NOT_IN_USE)
-		batadv_hardif_disable_interface(hard_iface);
+		batadv_hardif_disable_interface(hard_iface,
+						BATADV_IF_CLEANUP_AUTO);
 
 	ret = batadv_hardif_enable_interface(hard_iface, buff);
 
@@ -688,15 +696,10 @@ int batadv_throw_uevent(struct batadv_priv *bat_priv, enum batadv_uev_type type,
 			enum batadv_uev_action action, const char *data)
 {
 	int ret = -ENOMEM;
-	struct batadv_hard_iface *primary_if;
 	struct kobject *bat_kobj;
 	char *uevent_env[4] = { NULL, NULL, NULL, NULL };
 
-	primary_if = batadv_primary_if_get_selected(bat_priv);
-	if (!primary_if)
-		goto out;
-
-	bat_kobj = &primary_if->soft_iface->dev.kobj;
+	bat_kobj = &bat_priv->soft_iface->dev.kobj;
 
 	uevent_env[0] = kmalloc(strlen(BATADV_UEV_TYPE_VAR) +
 				strlen(batadv_uev_type_str[type]) + 1,
@@ -732,9 +735,6 @@ out:
 	kfree(uevent_env[1]);
 	kfree(uevent_env[2]);
 
-	if (primary_if)
-		batadv_hardif_free_ref(primary_if);
-
 	if (ret)
 		batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
 			   "Impossible to send uevent for (%s,%s,%s) event (err: %d)\n",
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index 98a66a0..9322320 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -385,25 +385,19 @@ static void batadv_tt_prepare_packet_buff(struct batadv_priv *bat_priv,
 					  int *packet_buff_len,
 					  int min_packet_len)
 {
-	struct batadv_hard_iface *primary_if;
 	int req_len;
 
-	primary_if = batadv_primary_if_get_selected(bat_priv);
-
 	req_len = min_packet_len;
 	req_len += batadv_tt_len(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 ((!primary_if) || (req_len > primary_if->soft_iface->mtu))
+	if (req_len > bat_priv->soft_iface->mtu)
 		req_len = min_packet_len;
 
 	batadv_tt_realloc_packet_buff(packet_buff, packet_buff_len,
 				      min_packet_len, req_len);
-
-	if (primary_if)
-		batadv_hardif_free_ref(primary_if);
 }
 
 static int batadv_tt_changes_fill_buff(struct batadv_priv *bat_priv,
@@ -908,7 +902,7 @@ out_remove:
 	/* remove address from local hash if present */
 	local_flags = batadv_tt_local_remove(bat_priv, tt_addr,
 					     "global tt received",
-					     !!(flags & BATADV_TT_CLIENT_ROAM));
+					     flags & BATADV_TT_CLIENT_ROAM);
 	tt_global_entry->common.flags |= local_flags & BATADV_TT_CLIENT_WIFI;
 
 	if (!(flags & BATADV_TT_CLIENT_ROAM))
@@ -1580,7 +1574,7 @@ static int batadv_tt_global_valid(const void *entry_ptr,
 static struct sk_buff *
 batadv_tt_response_fill_table(uint16_t tt_len, uint8_t ttvn,
 			      struct batadv_hashtable *hash,
-			      struct batadv_hard_iface *primary_if,
+			      struct batadv_priv *bat_priv,
 			      int (*valid_cb)(const void *, const void *),
 			      void *cb_data)
 {
@@ -1594,8 +1588,8 @@ batadv_tt_response_fill_table(uint16_t tt_len, uint8_t ttvn,
 	uint32_t i;
 	size_t len;
 
-	if (tt_query_size + tt_len > primary_if->soft_iface->mtu) {
-		tt_len = primary_if->soft_iface->mtu - tt_query_size;
+	if (tt_query_size + tt_len > bat_priv->soft_iface->mtu) {
+		tt_len = bat_priv->soft_iface->mtu - tt_query_size;
 		tt_len -= tt_len % sizeof(struct batadv_tt_change);
 	}
 	tt_tot = tt_len / sizeof(struct batadv_tt_change);
@@ -1715,7 +1709,6 @@ batadv_send_other_tt_response(struct batadv_priv *bat_priv,
 {
 	struct batadv_orig_node *req_dst_orig_node;
 	struct batadv_orig_node *res_dst_orig_node = NULL;
-	struct batadv_hard_iface *primary_if = NULL;
 	uint8_t orig_ttvn, req_ttvn, ttvn;
 	int ret = false;
 	unsigned char *tt_buff;
@@ -1740,10 +1733,6 @@ batadv_send_other_tt_response(struct batadv_priv *bat_priv,
 	if (!res_dst_orig_node)
 		goto out;
 
-	primary_if = batadv_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;
 
@@ -1791,7 +1780,7 @@ batadv_send_other_tt_response(struct batadv_priv *bat_priv,
 
 		skb = batadv_tt_response_fill_table(tt_len, ttvn,
 						    bat_priv->tt.global_hash,
-						    primary_if,
+						    bat_priv,
 						    batadv_tt_global_valid,
 						    req_dst_orig_node);
 		if (!skb)
@@ -1828,8 +1817,6 @@ out:
 		batadv_orig_node_free_ref(res_dst_orig_node);
 	if (req_dst_orig_node)
 		batadv_orig_node_free_ref(req_dst_orig_node);
-	if (primary_if)
-		batadv_hardif_free_ref(primary_if);
 	if (!ret)
 		kfree_skb(skb);
 	return ret;
@@ -1907,7 +1894,7 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv,
 
 		skb = batadv_tt_response_fill_table(tt_len, ttvn,
 						    bat_priv->tt.local_hash,
-						    primary_if,
+						    bat_priv,
 						    batadv_tt_local_valid_entry,
 						    NULL);
 		if (!skb)
@@ -2528,7 +2515,7 @@ bool batadv_tt_global_client_is_roaming(struct batadv_priv *bat_priv,
 	if (!tt_global_entry)
 		goto out;
 
-	ret = !!(tt_global_entry->common.flags & BATADV_TT_CLIENT_ROAM);
+	ret = tt_global_entry->common.flags & BATADV_TT_CLIENT_ROAM;
 	batadv_tt_global_entry_free_ref(tt_global_entry);
 out:
 	return ret;
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index 4cd87a0..aba8364 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -128,6 +128,10 @@ struct batadv_hard_iface {
  * @bond_list: list of bonding candidates
  * @refcount: number of contexts the object is used
  * @rcu: struct used for freeing in an RCU-safe manner
+ * @in_coding_list: list of nodes this orig can hear
+ * @out_coding_list: list of nodes that can hear this orig
+ * @in_coding_list_lock: protects in_coding_list
+ * @out_coding_list_lock: protects out_coding_list
  */
 struct batadv_orig_node {
 	uint8_t orig[ETH_ALEN];
@@ -171,6 +175,12 @@ struct batadv_orig_node {
 	struct list_head bond_list;
 	atomic_t refcount;
 	struct rcu_head rcu;
+#ifdef CONFIG_BATMAN_ADV_NC
+	struct list_head in_coding_list;
+	struct list_head out_coding_list;
+	spinlock_t in_coding_list_lock; /* Protects in_coding_list */
+	spinlock_t out_coding_list_lock; /* Protects out_coding_list */
+#endif
 };
 
 /**
@@ -265,6 +275,17 @@ struct batadv_bcast_duplist_entry {
  * @BATADV_CNT_DAT_PUT_RX: received dht PUT traffic packet counter
  * @BATADV_CNT_DAT_CACHED_REPLY_TX: transmitted dat cache reply traffic packet
  *  counter
+ * @BATADV_CNT_NC_CODE: transmitted nc-combined traffic packet counter
+ * @BATADV_CNT_NC_CODE_BYTES: transmitted nc-combined traffic bytes counter
+ * @BATADV_CNT_NC_RECODE: transmitted nc-recombined traffic packet counter
+ * @BATADV_CNT_NC_RECODE_BYTES: transmitted nc-recombined traffic bytes counter
+ * @BATADV_CNT_NC_BUFFER: counter for packets buffered for later nc decoding
+ * @BATADV_CNT_NC_DECODE: received and nc-decoded traffic packet counter
+ * @BATADV_CNT_NC_DECODE_BYTES: received and nc-decoded traffic bytes counter
+ * @BATADV_CNT_NC_DECODE_FAILED: received and decode-failed traffic packet
+ *  counter
+ * @BATADV_CNT_NC_SNIFFED: counter for nc-decoded packets received in promisc
+ *  mode.
  * @BATADV_CNT_NUM: number of traffic counters
  */
 enum batadv_counters {
@@ -292,6 +313,17 @@ enum batadv_counters {
 	BATADV_CNT_DAT_PUT_RX,
 	BATADV_CNT_DAT_CACHED_REPLY_TX,
 #endif
+#ifdef CONFIG_BATMAN_ADV_NC
+	BATADV_CNT_NC_CODE,
+	BATADV_CNT_NC_CODE_BYTES,
+	BATADV_CNT_NC_RECODE,
+	BATADV_CNT_NC_RECODE_BYTES,
+	BATADV_CNT_NC_BUFFER,
+	BATADV_CNT_NC_DECODE,
+	BATADV_CNT_NC_DECODE_BYTES,
+	BATADV_CNT_NC_DECODE_FAILED,
+	BATADV_CNT_NC_SNIFFED,
+#endif
 	BATADV_CNT_NUM,
 };
 
@@ -428,6 +460,35 @@ struct batadv_priv_dat {
 #endif
 
 /**
+ * struct batadv_priv_nc - per mesh interface network coding private data
+ * @work: work queue callback item for cleanup
+ * @debug_dir: dentry for nc subdir in batman-adv directory in debugfs
+ * @min_tq: only consider neighbors for encoding if neigh_tq > min_tq
+ * @max_fwd_delay: maximum packet forward delay to allow coding of packets
+ * @max_buffer_time: buffer time for sniffed packets used to decoding
+ * @timestamp_fwd_flush: timestamp of last forward packet queue flush
+ * @timestamp_sniffed_purge: timestamp of last sniffed packet queue purge
+ * @coding_hash: Hash table used to buffer skbs while waiting for another
+ *  incoming skb to code it with. Skbs are added to the buffer just before being
+ *  forwarded in routing.c
+ * @decoding_hash: Hash table used to buffer skbs that might be needed to decode
+ *  a received coded skb. The buffer is used for 1) skbs arriving on the
+ *  soft-interface; 2) skbs overheard on the hard-interface; and 3) skbs
+ *  forwarded by batman-adv.
+ */
+struct batadv_priv_nc {
+	struct delayed_work work;
+	struct dentry *debug_dir;
+	u8 min_tq;
+	u32 max_fwd_delay;
+	u32 max_buffer_time;
+	unsigned long timestamp_fwd_flush;
+	unsigned long timestamp_sniffed_purge;
+	struct batadv_hashtable *coding_hash;
+	struct batadv_hashtable *decoding_hash;
+};
+
+/**
  * struct batadv_priv - per mesh interface data
  * @mesh_state: current status of the mesh (inactive/active/deactivating)
  * @soft_iface: net device which holds this struct as private data
@@ -470,6 +531,8 @@ struct batadv_priv_dat {
  * @tt: translation table data
  * @vis: vis data
  * @dat: distributed arp table data
+ * @network_coding: bool indicating whether network coding is enabled
+ * @batadv_priv_nc: network coding data
  */
 struct batadv_priv {
 	atomic_t mesh_state;
@@ -522,6 +585,10 @@ struct batadv_priv {
 #ifdef CONFIG_BATMAN_ADV_DAT
 	struct batadv_priv_dat dat;
 #endif
+#ifdef CONFIG_BATMAN_ADV_NC
+	atomic_t network_coding;
+	struct batadv_priv_nc nc;
+#endif /* CONFIG_BATMAN_ADV_NC */
 };
 
 /**
@@ -702,6 +769,75 @@ struct batadv_tt_roam_node {
 };
 
 /**
+ * struct batadv_nc_node - network coding node
+ * @list: next and prev pointer for the list handling
+ * @addr: the node's mac address
+ * @refcount: number of contexts the object is used by
+ * @rcu: struct used for freeing in an RCU-safe manner
+ * @orig_node: pointer to corresponding orig node struct
+ * @last_seen: timestamp of last ogm received from this node
+ */
+struct batadv_nc_node {
+	struct list_head list;
+	uint8_t addr[ETH_ALEN];
+	atomic_t refcount;
+	struct rcu_head rcu;
+	struct batadv_orig_node *orig_node;
+	unsigned long last_seen;
+};
+
+/**
+ * struct batadv_nc_path - network coding path
+ * @hash_entry: next and prev pointer for the list handling
+ * @rcu: struct used for freeing in an RCU-safe manner
+ * @refcount: number of contexts the object is used by
+ * @packet_list: list of buffered packets for this path
+ * @packet_list_lock: access lock for packet list
+ * @next_hop: next hop (destination) of path
+ * @prev_hop: previous hop (source) of path
+ * @last_valid: timestamp for last validation of path
+ */
+struct batadv_nc_path {
+	struct hlist_node hash_entry;
+	struct rcu_head rcu;
+	atomic_t refcount;
+	struct list_head packet_list;
+	spinlock_t packet_list_lock; /* Protects packet_list */
+	uint8_t next_hop[ETH_ALEN];
+	uint8_t prev_hop[ETH_ALEN];
+	unsigned long last_valid;
+};
+
+/**
+ * struct batadv_nc_packet - network coding packet used when coding and
+ *  decoding packets
+ * @list: next and prev pointer for the list handling
+ * @packet_id: crc32 checksum of skb data
+ * @timestamp: field containing the info when the packet was added to path
+ * @neigh_node: pointer to original next hop neighbor of skb
+ * @skb: skb which can be encoded or used for decoding
+ * @nc_path: pointer to path this nc packet is attached to
+ */
+struct batadv_nc_packet {
+	struct list_head list;
+	__be32 packet_id;
+	unsigned long timestamp;
+	struct batadv_neigh_node *neigh_node;
+	struct sk_buff *skb;
+	struct batadv_nc_path *nc_path;
+};
+
+/**
+ * batadv_skb_cb - control buffer structure used to store private data relevant
+ *  to batman-adv in the skb->cb buffer in skbs.
+ * @decoded: Marks a skb as decoded, which is checked when searching for coding
+ *  opportunities in network-coding.c
+ */
+struct batadv_skb_cb {
+	bool decoded;
+};
+
+/**
  * struct batadv_forw_packet - structure for bcast packets to be sent/forwarded
  * @list: list node for batadv_socket_client::queue_list
  * @send_time: execution time for delayed_work (packet sending)
diff --git a/net/batman-adv/unicast.c b/net/batman-adv/unicast.c
index 50e079f..0bb3b59 100644
--- a/net/batman-adv/unicast.c
+++ b/net/batman-adv/unicast.c
@@ -122,7 +122,7 @@ batadv_frag_search_packet(struct list_head *head,
 {
 	struct batadv_frag_packet_list_entry *tfp;
 	struct batadv_unicast_frag_packet *tmp_up = NULL;
-	int is_head_tmp, is_head;
+	bool is_head_tmp, is_head;
 	uint16_t search_seqno;
 
 	if (up->flags & BATADV_UNI_FRAG_HEAD)
@@ -130,7 +130,7 @@ batadv_frag_search_packet(struct list_head *head,
 	else
 		search_seqno = ntohs(up->seqno)-1;
 
-	is_head = !!(up->flags & BATADV_UNI_FRAG_HEAD);
+	is_head = up->flags & BATADV_UNI_FRAG_HEAD;
 
 	list_for_each_entry(tfp, head, list) {
 		if (!tfp->skb)
@@ -142,7 +142,7 @@ batadv_frag_search_packet(struct list_head *head,
 		tmp_up = (struct batadv_unicast_frag_packet *)tfp->skb->data;
 
 		if (tfp->seqno == search_seqno) {
-			is_head_tmp = !!(tmp_up->flags & BATADV_UNI_FRAG_HEAD);
+			is_head_tmp = tmp_up->flags & BATADV_UNI_FRAG_HEAD;
 			if (is_head_tmp != is_head)
 				return tfp;
 			else
diff --git a/net/batman-adv/vis.c b/net/batman-adv/vis.c
index c053244..962ccf3 100644
--- a/net/batman-adv/vis.c
+++ b/net/batman-adv/vis.c
@@ -149,7 +149,7 @@ static void batadv_vis_data_read_prim_sec(struct seq_file *seq,
 
 	hlist_for_each_entry(entry, if_list, list) {
 		if (entry->primary)
-			seq_printf(seq, "PRIMARY, ");
+			seq_puts(seq, "PRIMARY, ");
 		else
 			seq_printf(seq,  "SEC %pM, ", entry->addr);
 	}
@@ -207,7 +207,7 @@ static void batadv_vis_data_read_entries(struct seq_file *seq,
 		if (batadv_compare_eth(entry->addr, packet->vis_orig))
 			batadv_vis_data_read_prim_sec(seq, list);
 
-		seq_printf(seq, "\n");
+		seq_puts(seq, "\n");
 	}
 }
 
diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c
index eb0f4b1..17f33a6 100644
--- a/net/bluetooth/a2mp.c
+++ b/net/bluetooth/a2mp.c
@@ -397,13 +397,12 @@ static int a2mp_getampassoc_rsp(struct amp_mgr *mgr, struct sk_buff *skb,
 	if (ctrl) {
 		u8 *assoc;
 
-		assoc = kzalloc(assoc_len, GFP_KERNEL);
+		assoc = kmemdup(rsp->amp_assoc, assoc_len, GFP_KERNEL);
 		if (!assoc) {
 			amp_ctrl_put(ctrl);
 			return -ENOMEM;
 		}
 
-		memcpy(assoc, rsp->amp_assoc, assoc_len);
 		ctrl->assoc = assoc;
 		ctrl->assoc_len = assoc_len;
 		ctrl->assoc_rem_len = assoc_len;
@@ -472,13 +471,12 @@ static int a2mp_createphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb,
 		size_t assoc_len = le16_to_cpu(hdr->len) - sizeof(*req);
 		u8 *assoc;
 
-		assoc = kzalloc(assoc_len, GFP_KERNEL);
+		assoc = kmemdup(req->amp_assoc, assoc_len, GFP_KERNEL);
 		if (!assoc) {
 			amp_ctrl_put(ctrl);
 			return -ENOMEM;
 		}
 
-		memcpy(assoc, req->amp_assoc, assoc_len);
 		ctrl->assoc = assoc;
 		ctrl->assoc_len = assoc_len;
 		ctrl->assoc_rem_len = assoc_len;
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c
index d3ee69b..46ccaa2 100644
--- a/net/bluetooth/af_bluetooth.c
+++ b/net/bluetooth/af_bluetooth.c
@@ -92,23 +92,14 @@ int bt_sock_register(int proto, const struct net_proto_family *ops)
 }
 EXPORT_SYMBOL(bt_sock_register);
 
-int bt_sock_unregister(int proto)
+void bt_sock_unregister(int proto)
 {
-	int err = 0;
-
 	if (proto < 0 || proto >= BT_MAX_PROTO)
-		return -EINVAL;
+		return;
 
 	write_lock(&bt_proto_lock);
-
-	if (!bt_proto[proto])
-		err = -ENOENT;
-	else
-		bt_proto[proto] = NULL;
-
+	bt_proto[proto] = NULL;
 	write_unlock(&bt_proto_lock);
-
-	return err;
 }
 EXPORT_SYMBOL(bt_sock_unregister);
 
@@ -422,7 +413,8 @@ unsigned int bt_sock_poll(struct file *file, struct socket *sock,
 		return bt_accept_poll(sk);
 
 	if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
-		mask |= POLLERR;
+		mask |= POLLERR |
+			(sock_flag(sk, SOCK_SELECT_ERR_QUEUE) ? POLLPRI : 0);
 
 	if (sk->sk_shutdown & RCV_SHUTDOWN)
 		mask |= POLLRDHUP | POLLIN | POLLRDNORM;
@@ -617,7 +609,7 @@ static int bt_seq_open(struct inode *inode, struct file *file)
 	struct bt_sock_list *sk_list;
 	struct bt_seq_state *s;
 
-	sk_list = PDE(inode)->data;
+	sk_list = PDE_DATA(inode);
 	s = __seq_open_private(file, &bt_seq_ops,
 			       sizeof(struct bt_seq_state));
 	if (!s)
diff --git a/net/bluetooth/bnep/netdev.c b/net/bluetooth/bnep/netdev.c
index e58c8b3..4b488ec 100644
--- a/net/bluetooth/bnep/netdev.c
+++ b/net/bluetooth/bnep/netdev.c
@@ -136,7 +136,7 @@ static u16 bnep_net_eth_proto(struct sk_buff *skb)
 	struct ethhdr *eh = (void *) skb->data;
 	u16 proto = ntohs(eh->h_proto);
 
-	if (proto >= 1536)
+	if (proto >= ETH_P_802_3_MIN)
 		return proto;
 
 	if (get_unaligned((__be16 *) skb->data) == htons(0xFFFF))
diff --git a/net/bluetooth/bnep/sock.c b/net/bluetooth/bnep/sock.c
index e7154a5..5b1c04e 100644
--- a/net/bluetooth/bnep/sock.c
+++ b/net/bluetooth/bnep/sock.c
@@ -253,8 +253,6 @@ error:
 void __exit bnep_sock_cleanup(void)
 {
 	bt_procfs_cleanup(&init_net, "bnep");
-	if (bt_sock_unregister(BTPROTO_BNEP) < 0)
-		BT_ERR("Can't unregister BNEP socket");
-
+	bt_sock_unregister(BTPROTO_BNEP);
 	proto_unregister(&bnep_proto);
 }
diff --git a/net/bluetooth/cmtp/capi.c b/net/bluetooth/cmtp/capi.c
index a4a9d4b..cd75e4d 100644
--- a/net/bluetooth/cmtp/capi.c
+++ b/net/bluetooth/cmtp/capi.c
@@ -539,7 +539,7 @@ static int cmtp_proc_show(struct seq_file *m, void *v)
 
 static int cmtp_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, cmtp_proc_show, PDE(inode)->data);
+	return single_open(file, cmtp_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations cmtp_proc_fops = {
diff --git a/net/bluetooth/cmtp/sock.c b/net/bluetooth/cmtp/sock.c
index 1c57482..58d9ede 100644
--- a/net/bluetooth/cmtp/sock.c
+++ b/net/bluetooth/cmtp/sock.c
@@ -264,8 +264,6 @@ error:
 void cmtp_cleanup_sockets(void)
 {
 	bt_procfs_cleanup(&init_net, "cmtp");
-	if (bt_sock_unregister(BTPROTO_CMTP) < 0)
-		BT_ERR("Can't unregister CMTP socket");
-
+	bt_sock_unregister(BTPROTO_CMTP);
 	proto_unregister(&cmtp_proto);
 }
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 4925a02..b9f9016 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -117,7 +117,7 @@ static void hci_acl_create_connection_cancel(struct hci_conn *conn)
 	hci_send_cmd(conn->hdev, HCI_OP_CREATE_CONN_CANCEL, sizeof(cp), &cp);
 }
 
-void hci_acl_disconn(struct hci_conn *conn, __u8 reason)
+void hci_disconnect(struct hci_conn *conn, __u8 reason)
 {
 	struct hci_cp_disconnect cp;
 
@@ -253,7 +253,7 @@ static void hci_conn_disconnect(struct hci_conn *conn)
 		hci_amp_disconn(conn, reason);
 		break;
 	default:
-		hci_acl_disconn(conn, reason);
+		hci_disconnect(conn, reason);
 		break;
 	}
 }
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 60793e7..9570358 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -57,36 +57,9 @@ static void hci_notify(struct hci_dev *hdev, int event)
 
 /* ---- HCI requests ---- */
 
-void hci_req_complete(struct hci_dev *hdev, __u16 cmd, int result)
+static void hci_req_sync_complete(struct hci_dev *hdev, u8 result)
 {
-	BT_DBG("%s command 0x%4.4x result 0x%2.2x", hdev->name, cmd, result);
-
-	/* If this is the init phase check if the completed command matches
-	 * the last init command, and if not just return.
-	 */
-	if (test_bit(HCI_INIT, &hdev->flags) && hdev->init_last_cmd != cmd) {
-		struct hci_command_hdr *sent = (void *) hdev->sent_cmd->data;
-		u16 opcode = __le16_to_cpu(sent->opcode);
-		struct sk_buff *skb;
-
-		/* Some CSR based controllers generate a spontaneous
-		 * reset complete event during init and any pending
-		 * command will never be completed. In such a case we
-		 * need to resend whatever was the last sent
-		 * command.
-		 */
-
-		if (cmd != HCI_OP_RESET || opcode == HCI_OP_RESET)
-			return;
-
-		skb = skb_clone(hdev->sent_cmd, GFP_ATOMIC);
-		if (skb) {
-			skb_queue_head(&hdev->cmd_q, skb);
-			queue_work(hdev->workqueue, &hdev->cmd_work);
-		}
-
-		return;
-	}
+	BT_DBG("%s result 0x%2.2x", hdev->name, result);
 
 	if (hdev->req_status == HCI_REQ_PEND) {
 		hdev->req_result = result;
@@ -106,22 +79,157 @@ static void hci_req_cancel(struct hci_dev *hdev, int err)
 	}
 }
 
+struct sk_buff *hci_get_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 event)
+{
+	struct hci_ev_cmd_complete *ev;
+	struct hci_event_hdr *hdr;
+	struct sk_buff *skb;
+
+	hci_dev_lock(hdev);
+
+	skb = hdev->recv_evt;
+	hdev->recv_evt = NULL;
+
+	hci_dev_unlock(hdev);
+
+	if (!skb)
+		return ERR_PTR(-ENODATA);
+
+	if (skb->len < sizeof(*hdr)) {
+		BT_ERR("Too short HCI event");
+		goto failed;
+	}
+
+	hdr = (void *) skb->data;
+	skb_pull(skb, HCI_EVENT_HDR_SIZE);
+
+	if (event) {
+		if (hdr->evt != event)
+			goto failed;
+		return skb;
+	}
+
+	if (hdr->evt != HCI_EV_CMD_COMPLETE) {
+		BT_DBG("Last event is not cmd complete (0x%2.2x)", hdr->evt);
+		goto failed;
+	}
+
+	if (skb->len < sizeof(*ev)) {
+		BT_ERR("Too short cmd_complete event");
+		goto failed;
+	}
+
+	ev = (void *) skb->data;
+	skb_pull(skb, sizeof(*ev));
+
+	if (opcode == __le16_to_cpu(ev->opcode))
+		return skb;
+
+	BT_DBG("opcode doesn't match (0x%2.2x != 0x%2.2x)", opcode,
+	       __le16_to_cpu(ev->opcode));
+
+failed:
+	kfree_skb(skb);
+	return ERR_PTR(-ENODATA);
+}
+
+struct sk_buff *__hci_cmd_sync_ev(struct hci_dev *hdev, u16 opcode, u32 plen,
+				  void *param, u8 event, u32 timeout)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	struct hci_request req;
+	int err = 0;
+
+	BT_DBG("%s", hdev->name);
+
+	hci_req_init(&req, hdev);
+
+	hci_req_add_ev(&req, opcode, plen, param, event);
+
+	hdev->req_status = HCI_REQ_PEND;
+
+	err = hci_req_run(&req, hci_req_sync_complete);
+	if (err < 0)
+		return ERR_PTR(err);
+
+	add_wait_queue(&hdev->req_wait_q, &wait);
+	set_current_state(TASK_INTERRUPTIBLE);
+
+	schedule_timeout(timeout);
+
+	remove_wait_queue(&hdev->req_wait_q, &wait);
+
+	if (signal_pending(current))
+		return ERR_PTR(-EINTR);
+
+	switch (hdev->req_status) {
+	case HCI_REQ_DONE:
+		err = -bt_to_errno(hdev->req_result);
+		break;
+
+	case HCI_REQ_CANCELED:
+		err = -hdev->req_result;
+		break;
+
+	default:
+		err = -ETIMEDOUT;
+		break;
+	}
+
+	hdev->req_status = hdev->req_result = 0;
+
+	BT_DBG("%s end: err %d", hdev->name, err);
+
+	if (err < 0)
+		return ERR_PTR(err);
+
+	return hci_get_cmd_complete(hdev, opcode, event);
+}
+EXPORT_SYMBOL(__hci_cmd_sync_ev);
+
+struct sk_buff *__hci_cmd_sync(struct hci_dev *hdev, u16 opcode, u32 plen,
+			       void *param, u32 timeout)
+{
+	return __hci_cmd_sync_ev(hdev, opcode, plen, param, 0, timeout);
+}
+EXPORT_SYMBOL(__hci_cmd_sync);
+
 /* Execute request and wait for completion. */
-static int __hci_request(struct hci_dev *hdev,
-			 void (*req)(struct hci_dev *hdev, unsigned long opt),
-			 unsigned long opt, __u32 timeout)
+static int __hci_req_sync(struct hci_dev *hdev,
+			  void (*func)(struct hci_request *req,
+				      unsigned long opt),
+			  unsigned long opt, __u32 timeout)
 {
+	struct hci_request req;
 	DECLARE_WAITQUEUE(wait, current);
 	int err = 0;
 
 	BT_DBG("%s start", hdev->name);
 
+	hci_req_init(&req, hdev);
+
 	hdev->req_status = HCI_REQ_PEND;
 
+	func(&req, opt);
+
+	err = hci_req_run(&req, hci_req_sync_complete);
+	if (err < 0) {
+		hdev->req_status = 0;
+
+		/* ENODATA means the HCI request command queue is empty.
+		 * This can happen when a request with conditionals doesn't
+		 * trigger any commands to be sent. This is normal behavior
+		 * and should not trigger an error return.
+		 */
+		if (err == -ENODATA)
+			return 0;
+
+		return err;
+	}
+
 	add_wait_queue(&hdev->req_wait_q, &wait);
 	set_current_state(TASK_INTERRUPTIBLE);
 
-	req(hdev, opt);
 	schedule_timeout(timeout);
 
 	remove_wait_queue(&hdev->req_wait_q, &wait);
@@ -150,9 +258,10 @@ static int __hci_request(struct hci_dev *hdev,
 	return err;
 }
 
-static int hci_request(struct hci_dev *hdev,
-		       void (*req)(struct hci_dev *hdev, unsigned long opt),
-		       unsigned long opt, __u32 timeout)
+static int hci_req_sync(struct hci_dev *hdev,
+			void (*req)(struct hci_request *req,
+				    unsigned long opt),
+			unsigned long opt, __u32 timeout)
 {
 	int ret;
 
@@ -161,75 +270,66 @@ static int hci_request(struct hci_dev *hdev,
 
 	/* Serialize all requests */
 	hci_req_lock(hdev);
-	ret = __hci_request(hdev, req, opt, timeout);
+	ret = __hci_req_sync(hdev, req, opt, timeout);
 	hci_req_unlock(hdev);
 
 	return ret;
 }
 
-static void hci_reset_req(struct hci_dev *hdev, unsigned long opt)
+static void hci_reset_req(struct hci_request *req, unsigned long opt)
 {
-	BT_DBG("%s %ld", hdev->name, opt);
+	BT_DBG("%s %ld", req->hdev->name, opt);
 
 	/* Reset device */
-	set_bit(HCI_RESET, &hdev->flags);
-	hci_send_cmd(hdev, HCI_OP_RESET, 0, NULL);
+	set_bit(HCI_RESET, &req->hdev->flags);
+	hci_req_add(req, HCI_OP_RESET, 0, NULL);
 }
 
-static void bredr_init(struct hci_dev *hdev)
+static void bredr_init(struct hci_request *req)
 {
-	hdev->flow_ctl_mode = HCI_FLOW_CTL_MODE_PACKET_BASED;
+	req->hdev->flow_ctl_mode = HCI_FLOW_CTL_MODE_PACKET_BASED;
 
 	/* Read Local Supported Features */
-	hci_send_cmd(hdev, HCI_OP_READ_LOCAL_FEATURES, 0, NULL);
+	hci_req_add(req, HCI_OP_READ_LOCAL_FEATURES, 0, NULL);
 
 	/* Read Local Version */
-	hci_send_cmd(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL);
+	hci_req_add(req, HCI_OP_READ_LOCAL_VERSION, 0, NULL);
+
+	/* Read BD Address */
+	hci_req_add(req, HCI_OP_READ_BD_ADDR, 0, NULL);
 }
 
-static void amp_init(struct hci_dev *hdev)
+static void amp_init(struct hci_request *req)
 {
-	hdev->flow_ctl_mode = HCI_FLOW_CTL_MODE_BLOCK_BASED;
+	req->hdev->flow_ctl_mode = HCI_FLOW_CTL_MODE_BLOCK_BASED;
 
 	/* Read Local Version */
-	hci_send_cmd(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL);
+	hci_req_add(req, HCI_OP_READ_LOCAL_VERSION, 0, NULL);
 
 	/* Read Local AMP Info */
-	hci_send_cmd(hdev, HCI_OP_READ_LOCAL_AMP_INFO, 0, NULL);
+	hci_req_add(req, HCI_OP_READ_LOCAL_AMP_INFO, 0, NULL);
 
 	/* Read Data Blk size */
-	hci_send_cmd(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, 0, NULL);
+	hci_req_add(req, HCI_OP_READ_DATA_BLOCK_SIZE, 0, NULL);
 }
 
-static void hci_init_req(struct hci_dev *hdev, unsigned long opt)
+static void hci_init1_req(struct hci_request *req, unsigned long opt)
 {
-	struct sk_buff *skb;
+	struct hci_dev *hdev = req->hdev;
 
 	BT_DBG("%s %ld", hdev->name, opt);
 
-	/* Driver initialization */
-
-	/* Special commands */
-	while ((skb = skb_dequeue(&hdev->driver_init))) {
-		bt_cb(skb)->pkt_type = HCI_COMMAND_PKT;
-		skb->dev = (void *) hdev;
-
-		skb_queue_tail(&hdev->cmd_q, skb);
-		queue_work(hdev->workqueue, &hdev->cmd_work);
-	}
-	skb_queue_purge(&hdev->driver_init);
-
 	/* Reset */
 	if (!test_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks))
-		hci_reset_req(hdev, 0);
+		hci_reset_req(req, 0);
 
 	switch (hdev->dev_type) {
 	case HCI_BREDR:
-		bredr_init(hdev);
+		bredr_init(req);
 		break;
 
 	case HCI_AMP:
-		amp_init(hdev);
+		amp_init(req);
 		break;
 
 	default:
@@ -238,44 +338,327 @@ static void hci_init_req(struct hci_dev *hdev, unsigned long opt)
 	}
 }
 
-static void hci_scan_req(struct hci_dev *hdev, unsigned long opt)
+static void bredr_setup(struct hci_request *req)
+{
+	struct hci_cp_delete_stored_link_key cp;
+	__le16 param;
+	__u8 flt_type;
+
+	/* Read Buffer Size (ACL mtu, max pkt, etc.) */
+	hci_req_add(req, HCI_OP_READ_BUFFER_SIZE, 0, NULL);
+
+	/* Read Class of Device */
+	hci_req_add(req, HCI_OP_READ_CLASS_OF_DEV, 0, NULL);
+
+	/* Read Local Name */
+	hci_req_add(req, HCI_OP_READ_LOCAL_NAME, 0, NULL);
+
+	/* Read Voice Setting */
+	hci_req_add(req, HCI_OP_READ_VOICE_SETTING, 0, NULL);
+
+	/* Clear Event Filters */
+	flt_type = HCI_FLT_CLEAR_ALL;
+	hci_req_add(req, HCI_OP_SET_EVENT_FLT, 1, &flt_type);
+
+	/* Connection accept timeout ~20 secs */
+	param = __constant_cpu_to_le16(0x7d00);
+	hci_req_add(req, HCI_OP_WRITE_CA_TIMEOUT, 2, &param);
+
+	bacpy(&cp.bdaddr, BDADDR_ANY);
+	cp.delete_all = 0x01;
+	hci_req_add(req, HCI_OP_DELETE_STORED_LINK_KEY, sizeof(cp), &cp);
+
+	/* Read page scan parameters */
+	if (req->hdev->hci_ver > BLUETOOTH_VER_1_1) {
+		hci_req_add(req, HCI_OP_READ_PAGE_SCAN_ACTIVITY, 0, NULL);
+		hci_req_add(req, HCI_OP_READ_PAGE_SCAN_TYPE, 0, NULL);
+	}
+}
+
+static void le_setup(struct hci_request *req)
+{
+	/* Read LE Buffer Size */
+	hci_req_add(req, HCI_OP_LE_READ_BUFFER_SIZE, 0, NULL);
+
+	/* Read LE Local Supported Features */
+	hci_req_add(req, HCI_OP_LE_READ_LOCAL_FEATURES, 0, NULL);
+
+	/* Read LE Advertising Channel TX Power */
+	hci_req_add(req, HCI_OP_LE_READ_ADV_TX_POWER, 0, NULL);
+
+	/* Read LE White List Size */
+	hci_req_add(req, HCI_OP_LE_READ_WHITE_LIST_SIZE, 0, NULL);
+
+	/* Read LE Supported States */
+	hci_req_add(req, HCI_OP_LE_READ_SUPPORTED_STATES, 0, NULL);
+}
+
+static u8 hci_get_inquiry_mode(struct hci_dev *hdev)
+{
+	if (lmp_ext_inq_capable(hdev))
+		return 0x02;
+
+	if (lmp_inq_rssi_capable(hdev))
+		return 0x01;
+
+	if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 &&
+	    hdev->lmp_subver == 0x0757)
+		return 0x01;
+
+	if (hdev->manufacturer == 15) {
+		if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963)
+			return 0x01;
+		if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963)
+			return 0x01;
+		if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965)
+			return 0x01;
+	}
+
+	if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 &&
+	    hdev->lmp_subver == 0x1805)
+		return 0x01;
+
+	return 0x00;
+}
+
+static void hci_setup_inquiry_mode(struct hci_request *req)
+{
+	u8 mode;
+
+	mode = hci_get_inquiry_mode(req->hdev);
+
+	hci_req_add(req, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode);
+}
+
+static void hci_setup_event_mask(struct hci_request *req)
+{
+	struct hci_dev *hdev = req->hdev;
+
+	/* The second byte is 0xff instead of 0x9f (two reserved bits
+	 * disabled) since a Broadcom 1.2 dongle doesn't respond to the
+	 * command otherwise.
+	 */
+	u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 };
+
+	/* CSR 1.1 dongles does not accept any bitfield so don't try to set
+	 * any event mask for pre 1.2 devices.
+	 */
+	if (hdev->hci_ver < BLUETOOTH_VER_1_2)
+		return;
+
+	if (lmp_bredr_capable(hdev)) {
+		events[4] |= 0x01; /* Flow Specification Complete */
+		events[4] |= 0x02; /* Inquiry Result with RSSI */
+		events[4] |= 0x04; /* Read Remote Extended Features Complete */
+		events[5] |= 0x08; /* Synchronous Connection Complete */
+		events[5] |= 0x10; /* Synchronous Connection Changed */
+	}
+
+	if (lmp_inq_rssi_capable(hdev))
+		events[4] |= 0x02; /* Inquiry Result with RSSI */
+
+	if (lmp_sniffsubr_capable(hdev))
+		events[5] |= 0x20; /* Sniff Subrating */
+
+	if (lmp_pause_enc_capable(hdev))
+		events[5] |= 0x80; /* Encryption Key Refresh Complete */
+
+	if (lmp_ext_inq_capable(hdev))
+		events[5] |= 0x40; /* Extended Inquiry Result */
+
+	if (lmp_no_flush_capable(hdev))
+		events[7] |= 0x01; /* Enhanced Flush Complete */
+
+	if (lmp_lsto_capable(hdev))
+		events[6] |= 0x80; /* Link Supervision Timeout Changed */
+
+	if (lmp_ssp_capable(hdev)) {
+		events[6] |= 0x01;	/* IO Capability Request */
+		events[6] |= 0x02;	/* IO Capability Response */
+		events[6] |= 0x04;	/* User Confirmation Request */
+		events[6] |= 0x08;	/* User Passkey Request */
+		events[6] |= 0x10;	/* Remote OOB Data Request */
+		events[6] |= 0x20;	/* Simple Pairing Complete */
+		events[7] |= 0x04;	/* User Passkey Notification */
+		events[7] |= 0x08;	/* Keypress Notification */
+		events[7] |= 0x10;	/* Remote Host Supported
+					 * Features Notification
+					 */
+	}
+
+	if (lmp_le_capable(hdev))
+		events[7] |= 0x20;	/* LE Meta-Event */
+
+	hci_req_add(req, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
+
+	if (lmp_le_capable(hdev)) {
+		memset(events, 0, sizeof(events));
+		events[0] = 0x1f;
+		hci_req_add(req, HCI_OP_LE_SET_EVENT_MASK,
+			    sizeof(events), events);
+	}
+}
+
+static void hci_init2_req(struct hci_request *req, unsigned long opt)
+{
+	struct hci_dev *hdev = req->hdev;
+
+	if (lmp_bredr_capable(hdev))
+		bredr_setup(req);
+
+	if (lmp_le_capable(hdev))
+		le_setup(req);
+
+	hci_setup_event_mask(req);
+
+	if (hdev->hci_ver > BLUETOOTH_VER_1_1)
+		hci_req_add(req, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
+
+	if (lmp_ssp_capable(hdev)) {
+		if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
+			u8 mode = 0x01;
+			hci_req_add(req, HCI_OP_WRITE_SSP_MODE,
+				    sizeof(mode), &mode);
+		} else {
+			struct hci_cp_write_eir cp;
+
+			memset(hdev->eir, 0, sizeof(hdev->eir));
+			memset(&cp, 0, sizeof(cp));
+
+			hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
+		}
+	}
+
+	if (lmp_inq_rssi_capable(hdev))
+		hci_setup_inquiry_mode(req);
+
+	if (lmp_inq_tx_pwr_capable(hdev))
+		hci_req_add(req, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
+
+	if (lmp_ext_feat_capable(hdev)) {
+		struct hci_cp_read_local_ext_features cp;
+
+		cp.page = 0x01;
+		hci_req_add(req, HCI_OP_READ_LOCAL_EXT_FEATURES,
+			    sizeof(cp), &cp);
+	}
+
+	if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags)) {
+		u8 enable = 1;
+		hci_req_add(req, HCI_OP_WRITE_AUTH_ENABLE, sizeof(enable),
+			    &enable);
+	}
+}
+
+static void hci_setup_link_policy(struct hci_request *req)
+{
+	struct hci_dev *hdev = req->hdev;
+	struct hci_cp_write_def_link_policy cp;
+	u16 link_policy = 0;
+
+	if (lmp_rswitch_capable(hdev))
+		link_policy |= HCI_LP_RSWITCH;
+	if (lmp_hold_capable(hdev))
+		link_policy |= HCI_LP_HOLD;
+	if (lmp_sniff_capable(hdev))
+		link_policy |= HCI_LP_SNIFF;
+	if (lmp_park_capable(hdev))
+		link_policy |= HCI_LP_PARK;
+
+	cp.policy = cpu_to_le16(link_policy);
+	hci_req_add(req, HCI_OP_WRITE_DEF_LINK_POLICY, sizeof(cp), &cp);
+}
+
+static void hci_set_le_support(struct hci_request *req)
+{
+	struct hci_dev *hdev = req->hdev;
+	struct hci_cp_write_le_host_supported cp;
+
+	memset(&cp, 0, sizeof(cp));
+
+	if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
+		cp.le = 0x01;
+		cp.simul = lmp_le_br_capable(hdev);
+	}
+
+	if (cp.le != lmp_host_le_capable(hdev))
+		hci_req_add(req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp),
+			    &cp);
+}
+
+static void hci_init3_req(struct hci_request *req, unsigned long opt)
+{
+	struct hci_dev *hdev = req->hdev;
+
+	if (hdev->commands[5] & 0x10)
+		hci_setup_link_policy(req);
+
+	if (lmp_le_capable(hdev)) {
+		hci_set_le_support(req);
+		hci_update_ad(req);
+	}
+}
+
+static int __hci_init(struct hci_dev *hdev)
+{
+	int err;
+
+	err = __hci_req_sync(hdev, hci_init1_req, 0, HCI_INIT_TIMEOUT);
+	if (err < 0)
+		return err;
+
+	/* HCI_BREDR covers both single-mode LE, BR/EDR and dual-mode
+	 * BR/EDR/LE type controllers. AMP controllers only need the
+	 * first stage init.
+	 */
+	if (hdev->dev_type != HCI_BREDR)
+		return 0;
+
+	err = __hci_req_sync(hdev, hci_init2_req, 0, HCI_INIT_TIMEOUT);
+	if (err < 0)
+		return err;
+
+	return __hci_req_sync(hdev, hci_init3_req, 0, HCI_INIT_TIMEOUT);
+}
+
+static void hci_scan_req(struct hci_request *req, unsigned long opt)
 {
 	__u8 scan = opt;
 
-	BT_DBG("%s %x", hdev->name, scan);
+	BT_DBG("%s %x", req->hdev->name, scan);
 
 	/* Inquiry and Page scans */
-	hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
+	hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
 }
 
-static void hci_auth_req(struct hci_dev *hdev, unsigned long opt)
+static void hci_auth_req(struct hci_request *req, unsigned long opt)
 {
 	__u8 auth = opt;
 
-	BT_DBG("%s %x", hdev->name, auth);
+	BT_DBG("%s %x", req->hdev->name, auth);
 
 	/* Authentication */
-	hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, 1, &auth);
+	hci_req_add(req, HCI_OP_WRITE_AUTH_ENABLE, 1, &auth);
 }
 
-static void hci_encrypt_req(struct hci_dev *hdev, unsigned long opt)
+static void hci_encrypt_req(struct hci_request *req, unsigned long opt)
 {
 	__u8 encrypt = opt;
 
-	BT_DBG("%s %x", hdev->name, encrypt);
+	BT_DBG("%s %x", req->hdev->name, encrypt);
 
 	/* Encryption */
-	hci_send_cmd(hdev, HCI_OP_WRITE_ENCRYPT_MODE, 1, &encrypt);
+	hci_req_add(req, HCI_OP_WRITE_ENCRYPT_MODE, 1, &encrypt);
 }
 
-static void hci_linkpol_req(struct hci_dev *hdev, unsigned long opt)
+static void hci_linkpol_req(struct hci_request *req, unsigned long opt)
 {
 	__le16 policy = cpu_to_le16(opt);
 
-	BT_DBG("%s %x", hdev->name, policy);
+	BT_DBG("%s %x", req->hdev->name, policy);
 
 	/* Default link policy */
-	hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, 2, &policy);
+	hci_req_add(req, HCI_OP_WRITE_DEF_LINK_POLICY, 2, &policy);
 }
 
 /* Get HCI device by index.
@@ -512,9 +895,10 @@ static int inquiry_cache_dump(struct hci_dev *hdev, int num, __u8 *buf)
 	return copied;
 }
 
-static void hci_inq_req(struct hci_dev *hdev, unsigned long opt)
+static void hci_inq_req(struct hci_request *req, unsigned long opt)
 {
 	struct hci_inquiry_req *ir = (struct hci_inquiry_req *) opt;
+	struct hci_dev *hdev = req->hdev;
 	struct hci_cp_inquiry cp;
 
 	BT_DBG("%s", hdev->name);
@@ -526,7 +910,13 @@ static void hci_inq_req(struct hci_dev *hdev, unsigned long opt)
 	memcpy(&cp.lap, &ir->lap, 3);
 	cp.length  = ir->length;
 	cp.num_rsp = ir->num_rsp;
-	hci_send_cmd(hdev, HCI_OP_INQUIRY, sizeof(cp), &cp);
+	hci_req_add(req, HCI_OP_INQUIRY, sizeof(cp), &cp);
+}
+
+static int wait_inquiry(void *word)
+{
+	schedule();
+	return signal_pending(current);
 }
 
 int hci_inquiry(void __user *arg)
@@ -556,9 +946,17 @@ int hci_inquiry(void __user *arg)
 	timeo = ir.length * msecs_to_jiffies(2000);
 
 	if (do_inquiry) {
-		err = hci_request(hdev, hci_inq_req, (unsigned long)&ir, timeo);
+		err = hci_req_sync(hdev, hci_inq_req, (unsigned long) &ir,
+				   timeo);
 		if (err < 0)
 			goto done;
+
+		/* Wait until Inquiry procedure finishes (HCI_INQUIRY flag is
+		 * cleared). If it is interrupted by a signal, return -EINTR.
+		 */
+		if (wait_on_bit(&hdev->flags, HCI_INQUIRY, wait_inquiry,
+				TASK_INTERRUPTIBLE))
+			return -EINTR;
 	}
 
 	/* for unlimited number of responses we will use buffer with
@@ -654,39 +1052,29 @@ static u8 create_ad(struct hci_dev *hdev, u8 *ptr)
 	return ad_len;
 }
 
-int hci_update_ad(struct hci_dev *hdev)
+void hci_update_ad(struct hci_request *req)
 {
+	struct hci_dev *hdev = req->hdev;
 	struct hci_cp_le_set_adv_data cp;
 	u8 len;
-	int err;
 
-	hci_dev_lock(hdev);
-
-	if (!lmp_le_capable(hdev)) {
-		err = -EINVAL;
-		goto unlock;
-	}
+	if (!lmp_le_capable(hdev))
+		return;
 
 	memset(&cp, 0, sizeof(cp));
 
 	len = create_ad(hdev, cp.data);
 
 	if (hdev->adv_data_len == len &&
-	    memcmp(cp.data, hdev->adv_data, len) == 0) {
-		err = 0;
-		goto unlock;
-	}
+	    memcmp(cp.data, hdev->adv_data, len) == 0)
+		return;
 
 	memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
 	hdev->adv_data_len = len;
 
 	cp.length = len;
-	err = hci_send_cmd(hdev, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
-
-unlock:
-	hci_dev_unlock(hdev);
 
-	return err;
+	hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
 }
 
 /* ---- HCI ioctl helpers ---- */
@@ -719,34 +1107,37 @@ int hci_dev_open(__u16 dev)
 		goto done;
 	}
 
-	if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
-		set_bit(HCI_RAW, &hdev->flags);
-
-	/* Treat all non BR/EDR controllers as raw devices if
-	   enable_hs is not set */
-	if (hdev->dev_type != HCI_BREDR && !enable_hs)
-		set_bit(HCI_RAW, &hdev->flags);
-
 	if (hdev->open(hdev)) {
 		ret = -EIO;
 		goto done;
 	}
 
-	if (!test_bit(HCI_RAW, &hdev->flags)) {
-		atomic_set(&hdev->cmd_cnt, 1);
-		set_bit(HCI_INIT, &hdev->flags);
-		hdev->init_last_cmd = 0;
+	atomic_set(&hdev->cmd_cnt, 1);
+	set_bit(HCI_INIT, &hdev->flags);
 
-		ret = __hci_request(hdev, hci_init_req, 0, HCI_INIT_TIMEOUT);
+	if (hdev->setup && test_bit(HCI_SETUP, &hdev->dev_flags))
+		ret = hdev->setup(hdev);
 
-		clear_bit(HCI_INIT, &hdev->flags);
+	if (!ret) {
+		/* Treat all non BR/EDR controllers as raw devices if
+		 * enable_hs is not set.
+		 */
+		if (hdev->dev_type != HCI_BREDR && !enable_hs)
+			set_bit(HCI_RAW, &hdev->flags);
+
+		if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
+			set_bit(HCI_RAW, &hdev->flags);
+
+		if (!test_bit(HCI_RAW, &hdev->flags))
+			ret = __hci_init(hdev);
 	}
 
+	clear_bit(HCI_INIT, &hdev->flags);
+
 	if (!ret) {
 		hci_dev_hold(hdev);
 		set_bit(HCI_UP, &hdev->flags);
 		hci_notify(hdev, HCI_DEV_UP);
-		hci_update_ad(hdev);
 		if (!test_bit(HCI_SETUP, &hdev->dev_flags) &&
 		    mgmt_valid_hdev(hdev)) {
 			hci_dev_lock(hdev);
@@ -828,7 +1219,7 @@ static int hci_dev_do_close(struct hci_dev *hdev)
 	if (!test_bit(HCI_RAW, &hdev->flags) &&
 	    test_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks)) {
 		set_bit(HCI_INIT, &hdev->flags);
-		__hci_request(hdev, hci_reset_req, 0, HCI_CMD_TIMEOUT);
+		__hci_req_sync(hdev, hci_reset_req, 0, HCI_CMD_TIMEOUT);
 		clear_bit(HCI_INIT, &hdev->flags);
 	}
 
@@ -847,10 +1238,17 @@ static int hci_dev_do_close(struct hci_dev *hdev)
 		hdev->sent_cmd = NULL;
 	}
 
+	kfree_skb(hdev->recv_evt);
+	hdev->recv_evt = NULL;
+
 	/* After this point our queues are empty
 	 * and no tasks are scheduled. */
 	hdev->close(hdev);
 
+	/* Clear flags */
+	hdev->flags = 0;
+	hdev->dev_flags &= ~HCI_PERSISTENT_MASK;
+
 	if (!test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags) &&
 	    mgmt_valid_hdev(hdev)) {
 		hci_dev_lock(hdev);
@@ -858,9 +1256,6 @@ static int hci_dev_do_close(struct hci_dev *hdev)
 		hci_dev_unlock(hdev);
 	}
 
-	/* Clear flags */
-	hdev->flags = 0;
-
 	/* Controller radio is available but is currently powered down */
 	hdev->amp_status = 0;
 
@@ -921,7 +1316,7 @@ int hci_dev_reset(__u16 dev)
 	hdev->acl_cnt = 0; hdev->sco_cnt = 0; hdev->le_cnt = 0;
 
 	if (!test_bit(HCI_RAW, &hdev->flags))
-		ret = __hci_request(hdev, hci_reset_req, 0, HCI_INIT_TIMEOUT);
+		ret = __hci_req_sync(hdev, hci_reset_req, 0, HCI_INIT_TIMEOUT);
 
 done:
 	hci_req_unlock(hdev);
@@ -960,8 +1355,8 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg)
 
 	switch (cmd) {
 	case HCISETAUTH:
-		err = hci_request(hdev, hci_auth_req, dr.dev_opt,
-				  HCI_INIT_TIMEOUT);
+		err = hci_req_sync(hdev, hci_auth_req, dr.dev_opt,
+				   HCI_INIT_TIMEOUT);
 		break;
 
 	case HCISETENCRYPT:
@@ -972,24 +1367,24 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg)
 
 		if (!test_bit(HCI_AUTH, &hdev->flags)) {
 			/* Auth must be enabled first */
-			err = hci_request(hdev, hci_auth_req, dr.dev_opt,
-					  HCI_INIT_TIMEOUT);
+			err = hci_req_sync(hdev, hci_auth_req, dr.dev_opt,
+					   HCI_INIT_TIMEOUT);
 			if (err)
 				break;
 		}
 
-		err = hci_request(hdev, hci_encrypt_req, dr.dev_opt,
-				  HCI_INIT_TIMEOUT);
+		err = hci_req_sync(hdev, hci_encrypt_req, dr.dev_opt,
+				   HCI_INIT_TIMEOUT);
 		break;
 
 	case HCISETSCAN:
-		err = hci_request(hdev, hci_scan_req, dr.dev_opt,
-				  HCI_INIT_TIMEOUT);
+		err = hci_req_sync(hdev, hci_scan_req, dr.dev_opt,
+				   HCI_INIT_TIMEOUT);
 		break;
 
 	case HCISETLINKPOL:
-		err = hci_request(hdev, hci_linkpol_req, dr.dev_opt,
-				  HCI_INIT_TIMEOUT);
+		err = hci_req_sync(hdev, hci_linkpol_req, dr.dev_opt,
+				   HCI_INIT_TIMEOUT);
 		break;
 
 	case HCISETLINKMODE:
@@ -1566,7 +1961,7 @@ int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
 	return mgmt_device_unblocked(hdev, bdaddr, type);
 }
 
-static void le_scan_param_req(struct hci_dev *hdev, unsigned long opt)
+static void le_scan_param_req(struct hci_request *req, unsigned long opt)
 {
 	struct le_scan_params *param =  (struct le_scan_params *) opt;
 	struct hci_cp_le_set_scan_param cp;
@@ -1576,10 +1971,10 @@ static void le_scan_param_req(struct hci_dev *hdev, unsigned long opt)
 	cp.interval = cpu_to_le16(param->interval);
 	cp.window = cpu_to_le16(param->window);
 
-	hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_PARAM, sizeof(cp), &cp);
+	hci_req_add(req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(cp), &cp);
 }
 
-static void le_scan_enable_req(struct hci_dev *hdev, unsigned long opt)
+static void le_scan_enable_req(struct hci_request *req, unsigned long opt)
 {
 	struct hci_cp_le_set_scan_enable cp;
 
@@ -1587,7 +1982,7 @@ static void le_scan_enable_req(struct hci_dev *hdev, unsigned long opt)
 	cp.enable = 1;
 	cp.filter_dup = 1;
 
-	hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp);
+	hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp);
 }
 
 static int hci_do_le_scan(struct hci_dev *hdev, u8 type, u16 interval,
@@ -1608,10 +2003,10 @@ static int hci_do_le_scan(struct hci_dev *hdev, u8 type, u16 interval,
 
 	hci_req_lock(hdev);
 
-	err = __hci_request(hdev, le_scan_param_req, (unsigned long) &param,
-			    timeo);
+	err = __hci_req_sync(hdev, le_scan_param_req, (unsigned long) &param,
+			     timeo);
 	if (!err)
-		err = __hci_request(hdev, le_scan_enable_req, 0, timeo);
+		err = __hci_req_sync(hdev, le_scan_enable_req, 0, timeo);
 
 	hci_req_unlock(hdev);
 
@@ -1729,7 +2124,6 @@ struct hci_dev *hci_alloc_dev(void)
 	INIT_DELAYED_WORK(&hdev->discov_off, hci_discov_off);
 	INIT_DELAYED_WORK(&hdev->le_scan_disable, le_scan_disable_work);
 
-	skb_queue_head_init(&hdev->driver_init);
 	skb_queue_head_init(&hdev->rx_q);
 	skb_queue_head_init(&hdev->cmd_q);
 	skb_queue_head_init(&hdev->raw_q);
@@ -1748,8 +2142,6 @@ EXPORT_SYMBOL(hci_alloc_dev);
 /* Free HCI device */
 void hci_free_dev(struct hci_dev *hdev)
 {
-	skb_queue_purge(&hdev->driver_init);
-
 	/* will free via device release */
 	put_device(&hdev->dev);
 }
@@ -2160,20 +2552,55 @@ static int hci_send_frame(struct sk_buff *skb)
 	return hdev->send(skb);
 }
 
-/* Send HCI command */
-int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param)
+void hci_req_init(struct hci_request *req, struct hci_dev *hdev)
+{
+	skb_queue_head_init(&req->cmd_q);
+	req->hdev = hdev;
+	req->err = 0;
+}
+
+int hci_req_run(struct hci_request *req, hci_req_complete_t complete)
+{
+	struct hci_dev *hdev = req->hdev;
+	struct sk_buff *skb;
+	unsigned long flags;
+
+	BT_DBG("length %u", skb_queue_len(&req->cmd_q));
+
+	/* If an error occured during request building, remove all HCI
+	 * commands queued on the HCI request queue.
+	 */
+	if (req->err) {
+		skb_queue_purge(&req->cmd_q);
+		return req->err;
+	}
+
+	/* Do not allow empty requests */
+	if (skb_queue_empty(&req->cmd_q))
+		return -ENODATA;
+
+	skb = skb_peek_tail(&req->cmd_q);
+	bt_cb(skb)->req.complete = complete;
+
+	spin_lock_irqsave(&hdev->cmd_q.lock, flags);
+	skb_queue_splice_tail(&req->cmd_q, &hdev->cmd_q);
+	spin_unlock_irqrestore(&hdev->cmd_q.lock, flags);
+
+	queue_work(hdev->workqueue, &hdev->cmd_work);
+
+	return 0;
+}
+
+static struct sk_buff *hci_prepare_cmd(struct hci_dev *hdev, u16 opcode,
+				       u32 plen, void *param)
 {
 	int len = HCI_COMMAND_HDR_SIZE + plen;
 	struct hci_command_hdr *hdr;
 	struct sk_buff *skb;
 
-	BT_DBG("%s opcode 0x%4.4x plen %d", hdev->name, opcode, plen);
-
 	skb = bt_skb_alloc(len, GFP_ATOMIC);
-	if (!skb) {
-		BT_ERR("%s no memory for command", hdev->name);
-		return -ENOMEM;
-	}
+	if (!skb)
+		return NULL;
 
 	hdr = (struct hci_command_hdr *) skb_put(skb, HCI_COMMAND_HDR_SIZE);
 	hdr->opcode = cpu_to_le16(opcode);
@@ -2187,8 +2614,26 @@ int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param)
 	bt_cb(skb)->pkt_type = HCI_COMMAND_PKT;
 	skb->dev = (void *) hdev;
 
-	if (test_bit(HCI_INIT, &hdev->flags))
-		hdev->init_last_cmd = opcode;
+	return skb;
+}
+
+/* Send HCI command */
+int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param)
+{
+	struct sk_buff *skb;
+
+	BT_DBG("%s opcode 0x%4.4x plen %d", hdev->name, opcode, plen);
+
+	skb = hci_prepare_cmd(hdev, opcode, plen, param);
+	if (!skb) {
+		BT_ERR("%s no memory for command", hdev->name);
+		return -ENOMEM;
+	}
+
+	/* Stand-alone HCI commands must be flaged as
+	 * single-command requests.
+	 */
+	bt_cb(skb)->req.start = true;
 
 	skb_queue_tail(&hdev->cmd_q, skb);
 	queue_work(hdev->workqueue, &hdev->cmd_work);
@@ -2196,6 +2641,42 @@ int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param)
 	return 0;
 }
 
+/* Queue a command to an asynchronous HCI request */
+void hci_req_add_ev(struct hci_request *req, u16 opcode, u32 plen, void *param,
+		    u8 event)
+{
+	struct hci_dev *hdev = req->hdev;
+	struct sk_buff *skb;
+
+	BT_DBG("%s opcode 0x%4.4x plen %d", hdev->name, opcode, plen);
+
+	/* If an error occured during request building, there is no point in
+	 * queueing the HCI command. We can simply return.
+	 */
+	if (req->err)
+		return;
+
+	skb = hci_prepare_cmd(hdev, opcode, plen, param);
+	if (!skb) {
+		BT_ERR("%s no memory for command (opcode 0x%4.4x)",
+		       hdev->name, opcode);
+		req->err = -ENOMEM;
+		return;
+	}
+
+	if (skb_queue_empty(&req->cmd_q))
+		bt_cb(skb)->req.start = true;
+
+	bt_cb(skb)->req.event = event;
+
+	skb_queue_tail(&req->cmd_q, skb);
+}
+
+void hci_req_add(struct hci_request *req, u16 opcode, u32 plen, void *param)
+{
+	hci_req_add_ev(req, opcode, plen, param, 0);
+}
+
 /* Get data from the previously sent command */
 void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode)
 {
@@ -2398,7 +2879,7 @@ static void hci_link_tx_to(struct hci_dev *hdev, __u8 type)
 		if (c->type == type && c->sent) {
 			BT_ERR("%s killing stalled connection %pMR",
 			       hdev->name, &c->dst);
-			hci_acl_disconn(c, HCI_ERROR_REMOTE_USER_TERM);
+			hci_disconnect(c, HCI_ERROR_REMOTE_USER_TERM);
 		}
 	}
 
@@ -2860,6 +3341,97 @@ static void hci_scodata_packet(struct hci_dev *hdev, struct sk_buff *skb)
 	kfree_skb(skb);
 }
 
+static bool hci_req_is_complete(struct hci_dev *hdev)
+{
+	struct sk_buff *skb;
+
+	skb = skb_peek(&hdev->cmd_q);
+	if (!skb)
+		return true;
+
+	return bt_cb(skb)->req.start;
+}
+
+static void hci_resend_last(struct hci_dev *hdev)
+{
+	struct hci_command_hdr *sent;
+	struct sk_buff *skb;
+	u16 opcode;
+
+	if (!hdev->sent_cmd)
+		return;
+
+	sent = (void *) hdev->sent_cmd->data;
+	opcode = __le16_to_cpu(sent->opcode);
+	if (opcode == HCI_OP_RESET)
+		return;
+
+	skb = skb_clone(hdev->sent_cmd, GFP_KERNEL);
+	if (!skb)
+		return;
+
+	skb_queue_head(&hdev->cmd_q, skb);
+	queue_work(hdev->workqueue, &hdev->cmd_work);
+}
+
+void hci_req_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 status)
+{
+	hci_req_complete_t req_complete = NULL;
+	struct sk_buff *skb;
+	unsigned long flags;
+
+	BT_DBG("opcode 0x%04x status 0x%02x", opcode, status);
+
+	/* If the completed command doesn't match the last one that was
+	 * sent we need to do special handling of it.
+	 */
+	if (!hci_sent_cmd_data(hdev, opcode)) {
+		/* Some CSR based controllers generate a spontaneous
+		 * reset complete event during init and any pending
+		 * command will never be completed. In such a case we
+		 * need to resend whatever was the last sent
+		 * command.
+		 */
+		if (test_bit(HCI_INIT, &hdev->flags) && opcode == HCI_OP_RESET)
+			hci_resend_last(hdev);
+
+		return;
+	}
+
+	/* If the command succeeded and there's still more commands in
+	 * this request the request is not yet complete.
+	 */
+	if (!status && !hci_req_is_complete(hdev))
+		return;
+
+	/* If this was the last command in a request the complete
+	 * callback would be found in hdev->sent_cmd instead of the
+	 * command queue (hdev->cmd_q).
+	 */
+	if (hdev->sent_cmd) {
+		req_complete = bt_cb(hdev->sent_cmd)->req.complete;
+		if (req_complete)
+			goto call_complete;
+	}
+
+	/* Remove all pending commands belonging to this request */
+	spin_lock_irqsave(&hdev->cmd_q.lock, flags);
+	while ((skb = __skb_dequeue(&hdev->cmd_q))) {
+		if (bt_cb(skb)->req.start) {
+			__skb_queue_head(&hdev->cmd_q, skb);
+			break;
+		}
+
+		req_complete = bt_cb(skb)->req.complete;
+		kfree_skb(skb);
+	}
+	spin_unlock_irqrestore(&hdev->cmd_q.lock, flags);
+
+call_complete:
+	if (req_complete)
+		req_complete(hdev, status);
+}
+
 static void hci_rx_work(struct work_struct *work)
 {
 	struct hci_dev *hdev = container_of(work, struct hci_dev, rx_work);
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 477726a..0a2b128 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -48,13 +48,13 @@ static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
 	}
 
 	clear_bit(HCI_INQUIRY, &hdev->flags);
+	smp_mb__after_clear_bit(); /* wake_up_bit advises about this barrier */
+	wake_up_bit(&hdev->flags, HCI_INQUIRY);
 
 	hci_dev_lock(hdev);
 	hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
 	hci_dev_unlock(hdev);
 
-	hci_req_complete(hdev, HCI_OP_INQUIRY_CANCEL, status);
-
 	hci_conn_check_pending(hdev);
 }
 
@@ -183,8 +183,6 @@ static void hci_cc_write_def_link_policy(struct hci_dev *hdev,
 
 	if (!status)
 		hdev->link_policy = get_unaligned_le16(sent);
-
-	hci_req_complete(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, status);
 }
 
 static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
@@ -195,11 +193,8 @@ static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
 
 	clear_bit(HCI_RESET, &hdev->flags);
 
-	hci_req_complete(hdev, HCI_OP_RESET, status);
-
 	/* Reset all non-persistent flags */
-	hdev->dev_flags &= ~(BIT(HCI_LE_SCAN) | BIT(HCI_PENDING_CLASS) |
-			     BIT(HCI_PERIODIC_INQ));
+	hdev->dev_flags &= ~HCI_PERSISTENT_MASK;
 
 	hdev->discovery.state = DISCOVERY_STOPPED;
 	hdev->inq_tx_power = HCI_TX_POWER_INVALID;
@@ -228,11 +223,6 @@ static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
 		memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
 
 	hci_dev_unlock(hdev);
-
-	if (!status && !test_bit(HCI_INIT, &hdev->flags))
-		hci_update_ad(hdev);
-
-	hci_req_complete(hdev, HCI_OP_WRITE_LOCAL_NAME, status);
 }
 
 static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
@@ -270,8 +260,6 @@ static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
 
 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
 		mgmt_auth_enable_complete(hdev, status);
-
-	hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status);
 }
 
 static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
@@ -293,8 +281,6 @@ static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
 		else
 			clear_bit(HCI_ENCRYPT, &hdev->flags);
 	}
-
-	hci_req_complete(hdev, HCI_OP_WRITE_ENCRYPT_MODE, status);
 }
 
 static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
@@ -343,7 +329,6 @@ static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
 
 done:
 	hci_dev_unlock(hdev);
-	hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status);
 }
 
 static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
@@ -435,15 +420,6 @@ static void hci_cc_write_voice_setting(struct hci_dev *hdev,
 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
 }
 
-static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
-{
-	__u8 status = *((__u8 *) skb->data);
-
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
-
-	hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status);
-}
-
 static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
 {
 	__u8 status = *((__u8 *) skb->data);
@@ -472,211 +448,6 @@ static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
 	}
 }
 
-static u8 hci_get_inquiry_mode(struct hci_dev *hdev)
-{
-	if (lmp_ext_inq_capable(hdev))
-		return 2;
-
-	if (lmp_inq_rssi_capable(hdev))
-		return 1;
-
-	if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 &&
-	    hdev->lmp_subver == 0x0757)
-		return 1;
-
-	if (hdev->manufacturer == 15) {
-		if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963)
-			return 1;
-		if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963)
-			return 1;
-		if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965)
-			return 1;
-	}
-
-	if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 &&
-	    hdev->lmp_subver == 0x1805)
-		return 1;
-
-	return 0;
-}
-
-static void hci_setup_inquiry_mode(struct hci_dev *hdev)
-{
-	u8 mode;
-
-	mode = hci_get_inquiry_mode(hdev);
-
-	hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode);
-}
-
-static void hci_setup_event_mask(struct hci_dev *hdev)
-{
-	/* The second byte is 0xff instead of 0x9f (two reserved bits
-	 * disabled) since a Broadcom 1.2 dongle doesn't respond to the
-	 * command otherwise */
-	u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 };
-
-	/* CSR 1.1 dongles does not accept any bitfield so don't try to set
-	 * any event mask for pre 1.2 devices */
-	if (hdev->hci_ver < BLUETOOTH_VER_1_2)
-		return;
-
-	if (lmp_bredr_capable(hdev)) {
-		events[4] |= 0x01; /* Flow Specification Complete */
-		events[4] |= 0x02; /* Inquiry Result with RSSI */
-		events[4] |= 0x04; /* Read Remote Extended Features Complete */
-		events[5] |= 0x08; /* Synchronous Connection Complete */
-		events[5] |= 0x10; /* Synchronous Connection Changed */
-	}
-
-	if (lmp_inq_rssi_capable(hdev))
-		events[4] |= 0x02; /* Inquiry Result with RSSI */
-
-	if (lmp_sniffsubr_capable(hdev))
-		events[5] |= 0x20; /* Sniff Subrating */
-
-	if (lmp_pause_enc_capable(hdev))
-		events[5] |= 0x80; /* Encryption Key Refresh Complete */
-
-	if (lmp_ext_inq_capable(hdev))
-		events[5] |= 0x40; /* Extended Inquiry Result */
-
-	if (lmp_no_flush_capable(hdev))
-		events[7] |= 0x01; /* Enhanced Flush Complete */
-
-	if (lmp_lsto_capable(hdev))
-		events[6] |= 0x80; /* Link Supervision Timeout Changed */
-
-	if (lmp_ssp_capable(hdev)) {
-		events[6] |= 0x01;	/* IO Capability Request */
-		events[6] |= 0x02;	/* IO Capability Response */
-		events[6] |= 0x04;	/* User Confirmation Request */
-		events[6] |= 0x08;	/* User Passkey Request */
-		events[6] |= 0x10;	/* Remote OOB Data Request */
-		events[6] |= 0x20;	/* Simple Pairing Complete */
-		events[7] |= 0x04;	/* User Passkey Notification */
-		events[7] |= 0x08;	/* Keypress Notification */
-		events[7] |= 0x10;	/* Remote Host Supported
-					 * Features Notification */
-	}
-
-	if (lmp_le_capable(hdev))
-		events[7] |= 0x20;	/* LE Meta-Event */
-
-	hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
-
-	if (lmp_le_capable(hdev)) {
-		memset(events, 0, sizeof(events));
-		events[0] = 0x1f;
-		hci_send_cmd(hdev, HCI_OP_LE_SET_EVENT_MASK,
-			     sizeof(events), events);
-	}
-}
-
-static void bredr_setup(struct hci_dev *hdev)
-{
-	struct hci_cp_delete_stored_link_key cp;
-	__le16 param;
-	__u8 flt_type;
-
-	/* Read Buffer Size (ACL mtu, max pkt, etc.) */
-	hci_send_cmd(hdev, HCI_OP_READ_BUFFER_SIZE, 0, NULL);
-
-	/* Read Class of Device */
-	hci_send_cmd(hdev, HCI_OP_READ_CLASS_OF_DEV, 0, NULL);
-
-	/* Read Local Name */
-	hci_send_cmd(hdev, HCI_OP_READ_LOCAL_NAME, 0, NULL);
-
-	/* Read Voice Setting */
-	hci_send_cmd(hdev, HCI_OP_READ_VOICE_SETTING, 0, NULL);
-
-	/* Clear Event Filters */
-	flt_type = HCI_FLT_CLEAR_ALL;
-	hci_send_cmd(hdev, HCI_OP_SET_EVENT_FLT, 1, &flt_type);
-
-	/* Connection accept timeout ~20 secs */
-	param = __constant_cpu_to_le16(0x7d00);
-	hci_send_cmd(hdev, HCI_OP_WRITE_CA_TIMEOUT, 2, &param);
-
-	bacpy(&cp.bdaddr, BDADDR_ANY);
-	cp.delete_all = 1;
-	hci_send_cmd(hdev, HCI_OP_DELETE_STORED_LINK_KEY, sizeof(cp), &cp);
-}
-
-static void le_setup(struct hci_dev *hdev)
-{
-	/* Read LE Buffer Size */
-	hci_send_cmd(hdev, HCI_OP_LE_READ_BUFFER_SIZE, 0, NULL);
-
-	/* Read LE Local Supported Features */
-	hci_send_cmd(hdev, HCI_OP_LE_READ_LOCAL_FEATURES, 0, NULL);
-
-	/* Read LE Advertising Channel TX Power */
-	hci_send_cmd(hdev, HCI_OP_LE_READ_ADV_TX_POWER, 0, NULL);
-
-	/* Read LE White List Size */
-	hci_send_cmd(hdev, HCI_OP_LE_READ_WHITE_LIST_SIZE, 0, NULL);
-
-	/* Read LE Supported States */
-	hci_send_cmd(hdev, HCI_OP_LE_READ_SUPPORTED_STATES, 0, NULL);
-}
-
-static void hci_setup(struct hci_dev *hdev)
-{
-	if (hdev->dev_type != HCI_BREDR)
-		return;
-
-	/* Read BD Address */
-	hci_send_cmd(hdev, HCI_OP_READ_BD_ADDR, 0, NULL);
-
-	if (lmp_bredr_capable(hdev))
-		bredr_setup(hdev);
-
-	if (lmp_le_capable(hdev))
-		le_setup(hdev);
-
-	hci_setup_event_mask(hdev);
-
-	if (hdev->hci_ver > BLUETOOTH_VER_1_1)
-		hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
-
-	if (lmp_ssp_capable(hdev)) {
-		if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
-			u8 mode = 0x01;
-			hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE,
-				     sizeof(mode), &mode);
-		} else {
-			struct hci_cp_write_eir cp;
-
-			memset(hdev->eir, 0, sizeof(hdev->eir));
-			memset(&cp, 0, sizeof(cp));
-
-			hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
-		}
-	}
-
-	if (lmp_inq_rssi_capable(hdev))
-		hci_setup_inquiry_mode(hdev);
-
-	if (lmp_inq_tx_pwr_capable(hdev))
-		hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
-
-	if (lmp_ext_feat_capable(hdev)) {
-		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 (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags)) {
-		u8 enable = 1;
-		hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(enable),
-			     &enable);
-	}
-}
-
 static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
 {
 	struct hci_rp_read_local_version *rp = (void *) skb->data;
@@ -684,7 +455,7 @@ static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
 
 	if (rp->status)
-		goto done;
+		return;
 
 	hdev->hci_ver = rp->hci_ver;
 	hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
@@ -694,30 +465,6 @@ static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
 
 	BT_DBG("%s manufacturer 0x%4.4x hci ver %d:%d", hdev->name,
 	       hdev->manufacturer, hdev->hci_ver, hdev->hci_rev);
-
-	if (test_bit(HCI_INIT, &hdev->flags))
-		hci_setup(hdev);
-
-done:
-	hci_req_complete(hdev, HCI_OP_READ_LOCAL_VERSION, rp->status);
-}
-
-static void hci_setup_link_policy(struct hci_dev *hdev)
-{
-	struct hci_cp_write_def_link_policy cp;
-	u16 link_policy = 0;
-
-	if (lmp_rswitch_capable(hdev))
-		link_policy |= HCI_LP_RSWITCH;
-	if (lmp_hold_capable(hdev))
-		link_policy |= HCI_LP_HOLD;
-	if (lmp_sniff_capable(hdev))
-		link_policy |= HCI_LP_SNIFF;
-	if (lmp_park_capable(hdev))
-		link_policy |= HCI_LP_PARK;
-
-	cp.policy = cpu_to_le16(link_policy);
-	hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, sizeof(cp), &cp);
 }
 
 static void hci_cc_read_local_commands(struct hci_dev *hdev,
@@ -727,16 +474,8 @@ static void hci_cc_read_local_commands(struct hci_dev *hdev,
 
 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
 
-	if (rp->status)
-		goto done;
-
-	memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
-
-	if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10))
-		hci_setup_link_policy(hdev);
-
-done:
-	hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status);
+	if (!rp->status)
+		memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
 }
 
 static void hci_cc_read_local_features(struct hci_dev *hdev,
@@ -795,22 +534,6 @@ static void hci_cc_read_local_features(struct hci_dev *hdev,
 	       hdev->features[6], hdev->features[7]);
 }
 
-static void hci_set_le_support(struct hci_dev *hdev)
-{
-	struct hci_cp_write_le_host_supported cp;
-
-	memset(&cp, 0, sizeof(cp));
-
-	if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
-		cp.le = 1;
-		cp.simul = lmp_le_br_capable(hdev);
-	}
-
-	if (cp.le != lmp_host_le_capable(hdev))
-		hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp),
-			     &cp);
-}
-
 static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
 					   struct sk_buff *skb)
 {
@@ -819,7 +542,7 @@ static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
 
 	if (rp->status)
-		goto done;
+		return;
 
 	switch (rp->page) {
 	case 0:
@@ -829,12 +552,6 @@ static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
 		memcpy(hdev->host_features, rp->features, 8);
 		break;
 	}
-
-	if (test_bit(HCI_INIT, &hdev->flags) && lmp_le_capable(hdev))
-		hci_set_le_support(hdev);
-
-done:
-	hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status);
 }
 
 static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
@@ -844,12 +561,8 @@ static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
 
 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
 
-	if (rp->status)
-		return;
-
-	hdev->flow_ctl_mode = rp->mode;
-
-	hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status);
+	if (!rp->status)
+		hdev->flow_ctl_mode = rp->mode;
 }
 
 static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
@@ -886,8 +599,65 @@ static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
 
 	if (!rp->status)
 		bacpy(&hdev->bdaddr, &rp->bdaddr);
+}
+
+static void hci_cc_read_page_scan_activity(struct hci_dev *hdev,
+					   struct sk_buff *skb)
+{
+	struct hci_rp_read_page_scan_activity *rp = (void *) skb->data;
+
+	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+
+	if (test_bit(HCI_INIT, &hdev->flags) && !rp->status) {
+		hdev->page_scan_interval = __le16_to_cpu(rp->interval);
+		hdev->page_scan_window = __le16_to_cpu(rp->window);
+	}
+}
+
+static void hci_cc_write_page_scan_activity(struct hci_dev *hdev,
+					    struct sk_buff *skb)
+{
+	u8 status = *((u8 *) skb->data);
+	struct hci_cp_write_page_scan_activity *sent;
+
+	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+
+	if (status)
+		return;
+
+	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY);
+	if (!sent)
+		return;
+
+	hdev->page_scan_interval = __le16_to_cpu(sent->interval);
+	hdev->page_scan_window = __le16_to_cpu(sent->window);
+}
+
+static void hci_cc_read_page_scan_type(struct hci_dev *hdev,
+					   struct sk_buff *skb)
+{
+	struct hci_rp_read_page_scan_type *rp = (void *) skb->data;
+
+	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+
+	if (test_bit(HCI_INIT, &hdev->flags) && !rp->status)
+		hdev->page_scan_type = rp->type;
+}
+
+static void hci_cc_write_page_scan_type(struct hci_dev *hdev,
+					struct sk_buff *skb)
+{
+	u8 status = *((u8 *) skb->data);
+	u8 *type;
+
+	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+
+	if (status)
+		return;
 
-	hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status);
+	type = hci_sent_cmd_data(hdev, HCI_OP_WRITE_PAGE_SCAN_TYPE);
+	if (type)
+		hdev->page_scan_type = *type;
 }
 
 static void hci_cc_read_data_block_size(struct hci_dev *hdev,
@@ -908,17 +678,6 @@ static void hci_cc_read_data_block_size(struct hci_dev *hdev,
 
 	BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
 	       hdev->block_cnt, hdev->block_len);
-
-	hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status);
-}
-
-static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb)
-{
-	__u8 status = *((__u8 *) skb->data);
-
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
-
-	hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status);
 }
 
 static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
@@ -942,8 +701,6 @@ static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
 	hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
 	hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
 
-	hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status);
-
 a2mp_rsp:
 	a2mp_send_getinfo_rsp(hdev);
 }
@@ -985,35 +742,6 @@ a2mp_rsp:
 	a2mp_send_create_phy_link_req(hdev, rp->status);
 }
 
-static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
-					  struct sk_buff *skb)
-{
-	__u8 status = *((__u8 *) skb->data);
-
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
-
-	hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status);
-}
-
-static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
-{
-	__u8 status = *((__u8 *) skb->data);
-
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
-
-	hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status);
-}
-
-static void hci_cc_write_inquiry_mode(struct hci_dev *hdev,
-				      struct sk_buff *skb)
-{
-	__u8 status = *((__u8 *) skb->data);
-
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
-
-	hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status);
-}
-
 static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
 					 struct sk_buff *skb)
 {
@@ -1023,17 +751,6 @@ static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
 
 	if (!rp->status)
 		hdev->inq_tx_power = rp->tx_power;
-
-	hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, rp->status);
-}
-
-static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb)
-{
-	__u8 status = *((__u8 *) skb->data);
-
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
-
-	hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status);
 }
 
 static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
@@ -1095,8 +812,6 @@ static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
 	hdev->le_cnt = hdev->le_pkts;
 
 	BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
-
-	hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
 }
 
 static void hci_cc_le_read_local_features(struct hci_dev *hdev,
@@ -1108,8 +823,6 @@ static void hci_cc_le_read_local_features(struct hci_dev *hdev,
 
 	if (!rp->status)
 		memcpy(hdev->le_features, rp->features, 8);
-
-	hci_req_complete(hdev, HCI_OP_LE_READ_LOCAL_FEATURES, rp->status);
 }
 
 static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev,
@@ -1119,22 +832,8 @@ static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev,
 
 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
 
-	if (!rp->status) {
+	if (!rp->status)
 		hdev->adv_tx_power = rp->tx_power;
-		if (!test_bit(HCI_INIT, &hdev->flags))
-			hci_update_ad(hdev);
-	}
-
-	hci_req_complete(hdev, HCI_OP_LE_READ_ADV_TX_POWER, rp->status);
-}
-
-static void hci_cc_le_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
-{
-	__u8 status = *((__u8 *) skb->data);
-
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
-
-	hci_req_complete(hdev, HCI_OP_LE_SET_EVENT_MASK, status);
 }
 
 static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
@@ -1231,12 +930,15 @@ static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb)
 			clear_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags);
 	}
 
-	hci_dev_unlock(hdev);
+	if (!test_bit(HCI_INIT, &hdev->flags)) {
+		struct hci_request req;
 
-	if (!test_bit(HCI_INIT, &hdev->flags))
-		hci_update_ad(hdev);
+		hci_req_init(&req, hdev);
+		hci_update_ad(&req);
+		hci_req_run(&req, NULL);
+	}
 
-	hci_req_complete(hdev, HCI_OP_LE_SET_ADV_ENABLE, status);
+	hci_dev_unlock(hdev);
 }
 
 static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
@@ -1245,8 +947,6 @@ static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
 
 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
 
-	hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_PARAM, status);
-
 	if (status) {
 		hci_dev_lock(hdev);
 		mgmt_start_discovery_failed(hdev, status);
@@ -1269,8 +969,6 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
 
 	switch (cp->enable) {
 	case LE_SCANNING_ENABLED:
-		hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_ENABLE, status);
-
 		if (status) {
 			hci_dev_lock(hdev);
 			mgmt_start_discovery_failed(hdev, status);
@@ -1321,32 +1019,6 @@ static void hci_cc_le_read_white_list_size(struct hci_dev *hdev,
 
 	if (!rp->status)
 		hdev->le_white_list_size = rp->size;
-
-	hci_req_complete(hdev, HCI_OP_LE_READ_WHITE_LIST_SIZE, rp->status);
-}
-
-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%2.2x", 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%2.2x", hdev->name, rp->status);
-
-	if (rp->status)
-		return;
-
-	hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
 }
 
 static void hci_cc_le_read_supported_states(struct hci_dev *hdev,
@@ -1358,8 +1030,6 @@ static void hci_cc_le_read_supported_states(struct hci_dev *hdev,
 
 	if (!rp->status)
 		memcpy(hdev->le_states, rp->le_states, 8);
-
-	hci_req_complete(hdev, HCI_OP_LE_READ_SUPPORTED_STATES, rp->status);
 }
 
 static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
@@ -1389,8 +1059,6 @@ static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
 	if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
 	    !test_bit(HCI_INIT, &hdev->flags))
 		mgmt_le_enable_complete(hdev, sent->le, status);
-
-	hci_req_complete(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, status);
 }
 
 static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev,
@@ -1412,7 +1080,6 @@ static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
 
 	if (status) {
-		hci_req_complete(hdev, HCI_OP_INQUIRY, status);
 		hci_conn_check_pending(hdev);
 		hci_dev_lock(hdev);
 		if (test_bit(HCI_MGMT, &hdev->dev_flags))
@@ -1884,11 +1551,6 @@ static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
 	}
 }
 
-static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
-{
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
-}
-
 static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status)
 {
 	struct hci_cp_create_phy_link *cp;
@@ -1930,11 +1592,6 @@ static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status)
 	amp_write_remote_assoc(hdev, cp->phy_handle);
 }
 
-static void hci_cs_create_logical_link(struct hci_dev *hdev, u8 status)
-{
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
-}
-
 static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
 	__u8 status = *((__u8 *) skb->data);
@@ -1943,13 +1600,14 @@ static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 
 	BT_DBG("%s status 0x%2.2x", hdev->name, status);
 
-	hci_req_complete(hdev, HCI_OP_INQUIRY, status);
-
 	hci_conn_check_pending(hdev);
 
 	if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
 		return;
 
+	smp_mb__after_clear_bit(); /* wake_up_bit advises about this barrier */
+	wake_up_bit(&hdev->flags, HCI_INQUIRY);
+
 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
 		return;
 
@@ -2399,7 +2057,7 @@ static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
 		clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
 
 		if (ev->status && conn->state == BT_CONNECTED) {
-			hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE);
+			hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
 			hci_conn_put(conn);
 			goto unlock;
 		}
@@ -2491,20 +2149,10 @@ unlock:
 	hci_dev_unlock(hdev);
 }
 
-static void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
-{
-	BT_DBG("%s", hdev->name);
-}
-
-static void hci_qos_setup_complete_evt(struct hci_dev *hdev,
-				       struct sk_buff *skb)
-{
-	BT_DBG("%s", hdev->name);
-}
-
 static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
 	struct hci_ev_cmd_complete *ev = (void *) skb->data;
+	u8 status = skb->data[sizeof(*ev)];
 	__u16 opcode;
 
 	skb_pull(skb, sizeof(*ev));
@@ -2588,10 +2236,6 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 		hci_cc_write_voice_setting(hdev, skb);
 		break;
 
-	case HCI_OP_HOST_BUFFER_SIZE:
-		hci_cc_host_buffer_size(hdev, skb);
-		break;
-
 	case HCI_OP_WRITE_SSP_MODE:
 		hci_cc_write_ssp_mode(hdev, skb);
 		break;
@@ -2620,46 +2264,42 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 		hci_cc_read_bd_addr(hdev, skb);
 		break;
 
-	case HCI_OP_READ_DATA_BLOCK_SIZE:
-		hci_cc_read_data_block_size(hdev, skb);
+	case HCI_OP_READ_PAGE_SCAN_ACTIVITY:
+		hci_cc_read_page_scan_activity(hdev, skb);
 		break;
 
-	case HCI_OP_WRITE_CA_TIMEOUT:
-		hci_cc_write_ca_timeout(hdev, skb);
+	case HCI_OP_WRITE_PAGE_SCAN_ACTIVITY:
+		hci_cc_write_page_scan_activity(hdev, skb);
 		break;
 
-	case HCI_OP_READ_FLOW_CONTROL_MODE:
-		hci_cc_read_flow_control_mode(hdev, skb);
+	case HCI_OP_READ_PAGE_SCAN_TYPE:
+		hci_cc_read_page_scan_type(hdev, skb);
 		break;
 
-	case HCI_OP_READ_LOCAL_AMP_INFO:
-		hci_cc_read_local_amp_info(hdev, skb);
+	case HCI_OP_WRITE_PAGE_SCAN_TYPE:
+		hci_cc_write_page_scan_type(hdev, skb);
 		break;
 
-	case HCI_OP_READ_LOCAL_AMP_ASSOC:
-		hci_cc_read_local_amp_assoc(hdev, skb);
+	case HCI_OP_READ_DATA_BLOCK_SIZE:
+		hci_cc_read_data_block_size(hdev, skb);
 		break;
 
-	case HCI_OP_DELETE_STORED_LINK_KEY:
-		hci_cc_delete_stored_link_key(hdev, skb);
+	case HCI_OP_READ_FLOW_CONTROL_MODE:
+		hci_cc_read_flow_control_mode(hdev, skb);
 		break;
 
-	case HCI_OP_SET_EVENT_MASK:
-		hci_cc_set_event_mask(hdev, skb);
+	case HCI_OP_READ_LOCAL_AMP_INFO:
+		hci_cc_read_local_amp_info(hdev, skb);
 		break;
 
-	case HCI_OP_WRITE_INQUIRY_MODE:
-		hci_cc_write_inquiry_mode(hdev, skb);
+	case HCI_OP_READ_LOCAL_AMP_ASSOC:
+		hci_cc_read_local_amp_assoc(hdev, skb);
 		break;
 
 	case HCI_OP_READ_INQ_RSP_TX_POWER:
 		hci_cc_read_inq_rsp_tx_power(hdev, skb);
 		break;
 
-	case HCI_OP_SET_EVENT_FLT:
-		hci_cc_set_event_flt(hdev, skb);
-		break;
-
 	case HCI_OP_PIN_CODE_REPLY:
 		hci_cc_pin_code_reply(hdev, skb);
 		break;
@@ -2684,10 +2324,6 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 		hci_cc_le_read_adv_tx_power(hdev, skb);
 		break;
 
-	case HCI_OP_LE_SET_EVENT_MASK:
-		hci_cc_le_set_event_mask(hdev, skb);
-		break;
-
 	case HCI_OP_USER_CONFIRM_REPLY:
 		hci_cc_user_confirm_reply(hdev, skb);
 		break;
@@ -2720,14 +2356,6 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 		hci_cc_le_read_white_list_size(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_LE_READ_SUPPORTED_STATES:
 		hci_cc_le_read_supported_states(hdev, skb);
 		break;
@@ -2745,9 +2373,11 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 		break;
 	}
 
-	if (ev->opcode != HCI_OP_NOP)
+	if (opcode != HCI_OP_NOP)
 		del_timer(&hdev->cmd_timer);
 
+	hci_req_cmd_complete(hdev, opcode, status);
+
 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
 		atomic_set(&hdev->cmd_cnt, 1);
 		if (!skb_queue_empty(&hdev->cmd_q))
@@ -2817,10 +2447,6 @@ static 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;
-
 	case HCI_OP_CREATE_PHY_LINK:
 		hci_cs_create_phylink(hdev, ev->status);
 		break;
@@ -2829,18 +2455,18 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
 		hci_cs_accept_phylink(hdev, ev->status);
 		break;
 
-	case HCI_OP_CREATE_LOGICAL_LINK:
-		hci_cs_create_logical_link(hdev, ev->status);
-		break;
-
 	default:
 		BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
 		break;
 	}
 
-	if (ev->opcode != HCI_OP_NOP)
+	if (opcode != HCI_OP_NOP)
 		del_timer(&hdev->cmd_timer);
 
+	if (ev->status ||
+	    (hdev->sent_cmd && !bt_cb(hdev->sent_cmd)->req.event))
+		hci_req_cmd_complete(hdev, opcode, ev->status);
+
 	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
 		atomic_set(&hdev->cmd_cnt, 1);
 		if (!skb_queue_empty(&hdev->cmd_q))
@@ -3391,18 +3017,6 @@ unlock:
 	hci_dev_unlock(hdev);
 }
 
-static void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
-{
-	BT_DBG("%s", hdev->name);
-}
-
-static void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
-{
-	struct hci_ev_sniff_subrate *ev = (void *) skb->data;
-
-	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
-}
-
 static void hci_extended_inquiry_result_evt(struct hci_dev *hdev,
 					    struct sk_buff *skb)
 {
@@ -3472,7 +3086,7 @@ static void hci_key_refresh_complete_evt(struct hci_dev *hdev,
 	clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
 
 	if (ev->status && conn->state == BT_CONNECTED) {
-		hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE);
+		hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
 		hci_conn_put(conn);
 		goto unlock;
 	}
@@ -4087,8 +3701,27 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
 	struct hci_event_hdr *hdr = (void *) skb->data;
 	__u8 event = hdr->evt;
 
+	hci_dev_lock(hdev);
+
+	/* Received events are (currently) only needed when a request is
+	 * ongoing so avoid unnecessary memory allocation.
+	 */
+	if (hdev->req_status == HCI_REQ_PEND) {
+		kfree_skb(hdev->recv_evt);
+		hdev->recv_evt = skb_clone(skb, GFP_KERNEL);
+	}
+
+	hci_dev_unlock(hdev);
+
 	skb_pull(skb, HCI_EVENT_HDR_SIZE);
 
+	if (hdev->sent_cmd && bt_cb(hdev->sent_cmd)->req.event == event) {
+		struct hci_command_hdr *hdr = (void *) hdev->sent_cmd->data;
+		u16 opcode = __le16_to_cpu(hdr->opcode);
+
+		hci_req_cmd_complete(hdev, opcode, 0);
+	}
+
 	switch (event) {
 	case HCI_EV_INQUIRY_COMPLETE:
 		hci_inquiry_complete_evt(hdev, skb);
@@ -4130,14 +3763,6 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
 		hci_remote_features_evt(hdev, skb);
 		break;
 
-	case HCI_EV_REMOTE_VERSION:
-		hci_remote_version_evt(hdev, skb);
-		break;
-
-	case HCI_EV_QOS_SETUP_COMPLETE:
-		hci_qos_setup_complete_evt(hdev, skb);
-		break;
-
 	case HCI_EV_CMD_COMPLETE:
 		hci_cmd_complete_evt(hdev, skb);
 		break;
@@ -4194,14 +3819,6 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
 		hci_sync_conn_complete_evt(hdev, skb);
 		break;
 
-	case HCI_EV_SYNC_CONN_CHANGED:
-		hci_sync_conn_changed_evt(hdev, skb);
-		break;
-
-	case HCI_EV_SNIFF_SUBRATE:
-		hci_sniff_subrate_evt(hdev, skb);
-		break;
-
 	case HCI_EV_EXTENDED_INQUIRY_RESULT:
 		hci_extended_inquiry_result_evt(hdev, skb);
 		break;
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
index 6a93614..aa4354f 100644
--- a/net/bluetooth/hci_sock.c
+++ b/net/bluetooth/hci_sock.c
@@ -854,6 +854,11 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
 			skb_queue_tail(&hdev->raw_q, skb);
 			queue_work(hdev->workqueue, &hdev->tx_work);
 		} else {
+			/* Stand-alone HCI commands must be flaged as
+			 * single-command requests.
+			 */
+			bt_cb(skb)->req.start = true;
+
 			skb_queue_tail(&hdev->cmd_q, skb);
 			queue_work(hdev->workqueue, &hdev->cmd_work);
 		}
@@ -1121,8 +1126,6 @@ error:
 void hci_sock_cleanup(void)
 {
 	bt_procfs_cleanup(&init_net, "hci");
-	if (bt_sock_unregister(BTPROTO_HCI) < 0)
-		BT_ERR("HCI socket unregistration failed");
-
+	bt_sock_unregister(BTPROTO_HCI);
 	proto_unregister(&hci_sk_proto);
 }
diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c
index 23b4e24..ff38561 100644
--- a/net/bluetooth/hci_sysfs.c
+++ b/net/bluetooth/hci_sysfs.c
@@ -590,10 +590,8 @@ int __init bt_sysfs_init(void)
 	bt_debugfs = debugfs_create_dir("bluetooth", NULL);
 
 	bt_class = class_create(THIS_MODULE, "bluetooth");
-	if (IS_ERR(bt_class))
-		return PTR_ERR(bt_class);
 
-	return 0;
+	return PTR_RET(bt_class);
 }
 
 void bt_sysfs_cleanup(void)
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index a7352ff..2342327 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -311,6 +311,9 @@ static int hidp_get_raw_report(struct hid_device *hid,
 	int numbered_reports = hid->report_enum[report_type].numbered;
 	int ret;
 
+	if (atomic_read(&session->terminate))
+		return -EIO;
+
 	switch (report_type) {
 	case HID_FEATURE_REPORT:
 		report_type = HIDP_TRANS_GET_REPORT | HIDP_DATA_RTYPE_FEATURE;
@@ -722,6 +725,7 @@ static int hidp_session(void *arg)
 		set_current_state(TASK_INTERRUPTIBLE);
 	}
 	set_current_state(TASK_RUNNING);
+	atomic_inc(&session->terminate);
 	remove_wait_queue(sk_sleep(intr_sk), &intr_wait);
 	remove_wait_queue(sk_sleep(ctrl_sk), &ctrl_wait);
 
diff --git a/net/bluetooth/hidp/sock.c b/net/bluetooth/hidp/sock.c
index 82a829d..5d0f1ca 100644
--- a/net/bluetooth/hidp/sock.c
+++ b/net/bluetooth/hidp/sock.c
@@ -304,8 +304,6 @@ error:
 void __exit hidp_cleanup_sockets(void)
 {
 	bt_procfs_cleanup(&init_net, "hidp");
-	if (bt_sock_unregister(BTPROTO_HIDP) < 0)
-		BT_ERR("Can't unregister HIDP socket");
-
+	bt_sock_unregister(BTPROTO_HIDP);
 	proto_unregister(&hidp_proto);
 }
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 1bcfb84..7f97049 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -1312,8 +1312,6 @@ error:
 void l2cap_cleanup_sockets(void)
 {
 	bt_procfs_cleanup(&init_net, "l2cap");
-	if (bt_sock_unregister(BTPROTO_L2CAP) < 0)
-		BT_ERR("L2CAP socket unregistration failed");
-
+	bt_sock_unregister(BTPROTO_L2CAP);
 	proto_unregister(&l2cap_proto);
 }
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 39395c7..03e7e73 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -384,7 +384,8 @@ static u32 get_supported_settings(struct hci_dev *hdev)
 
 	if (lmp_bredr_capable(hdev)) {
 		settings |= MGMT_SETTING_CONNECTABLE;
-		settings |= MGMT_SETTING_FAST_CONNECTABLE;
+		if (hdev->hci_ver >= BLUETOOTH_VER_1_2)
+			settings |= MGMT_SETTING_FAST_CONNECTABLE;
 		settings |= MGMT_SETTING_DISCOVERABLE;
 		settings |= MGMT_SETTING_BREDR;
 		settings |= MGMT_SETTING_LINK_SECURITY;
@@ -409,6 +410,9 @@ static u32 get_current_settings(struct hci_dev *hdev)
 	if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
 		settings |= MGMT_SETTING_CONNECTABLE;
 
+	if (test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
+		settings |= MGMT_SETTING_FAST_CONNECTABLE;
+
 	if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
 		settings |= MGMT_SETTING_DISCOVERABLE;
 
@@ -591,32 +595,33 @@ static void create_eir(struct hci_dev *hdev, u8 *data)
 	ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
 }
 
-static int update_eir(struct hci_dev *hdev)
+static void update_eir(struct hci_request *req)
 {
+	struct hci_dev *hdev = req->hdev;
 	struct hci_cp_write_eir cp;
 
 	if (!hdev_is_powered(hdev))
-		return 0;
+		return;
 
 	if (!lmp_ext_inq_capable(hdev))
-		return 0;
+		return;
 
 	if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
-		return 0;
+		return;
 
 	if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
-		return 0;
+		return;
 
 	memset(&cp, 0, sizeof(cp));
 
 	create_eir(hdev, cp.data);
 
 	if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
-		return 0;
+		return;
 
 	memcpy(hdev->eir, cp.data, sizeof(cp.data));
 
-	return hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
+	hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
 }
 
 static u8 get_service_classes(struct hci_dev *hdev)
@@ -630,47 +635,48 @@ static u8 get_service_classes(struct hci_dev *hdev)
 	return val;
 }
 
-static int update_class(struct hci_dev *hdev)
+static void update_class(struct hci_request *req)
 {
+	struct hci_dev *hdev = req->hdev;
 	u8 cod[3];
-	int err;
 
 	BT_DBG("%s", hdev->name);
 
 	if (!hdev_is_powered(hdev))
-		return 0;
+		return;
 
 	if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
-		return 0;
+		return;
 
 	cod[0] = hdev->minor_class;
 	cod[1] = hdev->major_class;
 	cod[2] = get_service_classes(hdev);
 
 	if (memcmp(cod, hdev->dev_class, 3) == 0)
-		return 0;
-
-	err = hci_send_cmd(hdev, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
-	if (err == 0)
-		set_bit(HCI_PENDING_CLASS, &hdev->dev_flags);
+		return;
 
-	return err;
+	hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
 }
 
 static void service_cache_off(struct work_struct *work)
 {
 	struct hci_dev *hdev = container_of(work, struct hci_dev,
 					    service_cache.work);
+	struct hci_request req;
 
 	if (!test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
 		return;
 
+	hci_req_init(&req, hdev);
+
 	hci_dev_lock(hdev);
 
-	update_eir(hdev);
-	update_class(hdev);
+	update_eir(&req);
+	update_class(&req);
 
 	hci_dev_unlock(hdev);
+
+	hci_req_run(&req, NULL);
 }
 
 static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
@@ -994,11 +1000,64 @@ failed:
 	return err;
 }
 
+static void write_fast_connectable(struct hci_request *req, bool enable)
+{
+	struct hci_dev *hdev = req->hdev;
+	struct hci_cp_write_page_scan_activity acp;
+	u8 type;
+
+	if (hdev->hci_ver < BLUETOOTH_VER_1_2)
+		return;
+
+	if (enable) {
+		type = PAGE_SCAN_TYPE_INTERLACED;
+
+		/* 160 msec page scan interval */
+		acp.interval = __constant_cpu_to_le16(0x0100);
+	} else {
+		type = PAGE_SCAN_TYPE_STANDARD;	/* default */
+
+		/* default 1.28 sec page scan */
+		acp.interval = __constant_cpu_to_le16(0x0800);
+	}
+
+	acp.window = __constant_cpu_to_le16(0x0012);
+
+	if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
+	    __cpu_to_le16(hdev->page_scan_window) != acp.window)
+		hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
+			    sizeof(acp), &acp);
+
+	if (hdev->page_scan_type != type)
+		hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
+}
+
+static void set_connectable_complete(struct hci_dev *hdev, u8 status)
+{
+	struct pending_cmd *cmd;
+
+	BT_DBG("status 0x%02x", status);
+
+	hci_dev_lock(hdev);
+
+	cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
+	if (!cmd)
+		goto unlock;
+
+	send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
+
+	mgmt_pending_remove(cmd);
+
+unlock:
+	hci_dev_unlock(hdev);
+}
+
 static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
 			   u16 len)
 {
 	struct mgmt_mode *cp = data;
 	struct pending_cmd *cmd;
+	struct hci_request req;
 	u8 scan;
 	int err;
 
@@ -1065,7 +1124,20 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
 			cancel_delayed_work(&hdev->discov_off);
 	}
 
-	err = hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
+	hci_req_init(&req, hdev);
+
+	hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
+
+	/* If we're going from non-connectable to connectable or
+	 * vice-versa when fast connectable is enabled ensure that fast
+	 * connectable gets disabled. write_fast_connectable won't do
+	 * anything if the page scan parameters are already what they
+	 * should be.
+	 */
+	if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
+		write_fast_connectable(&req, false);
+
+	err = hci_req_run(&req, set_connectable_complete);
 	if (err < 0)
 		mgmt_pending_remove(cmd);
 
@@ -1332,6 +1404,29 @@ unlock:
 	return err;
 }
 
+/* This is a helper function to test for pending mgmt commands that can
+ * cause CoD or EIR HCI commands. We can only allow one such pending
+ * mgmt command at a time since otherwise we cannot easily track what
+ * the current values are, will be, and based on that calculate if a new
+ * HCI command needs to be sent and if yes with what value.
+ */
+static bool pending_eir_or_class(struct hci_dev *hdev)
+{
+	struct pending_cmd *cmd;
+
+	list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
+		switch (cmd->opcode) {
+		case MGMT_OP_ADD_UUID:
+		case MGMT_OP_REMOVE_UUID:
+		case MGMT_OP_SET_DEV_CLASS:
+		case MGMT_OP_SET_POWERED:
+			return true;
+		}
+	}
+
+	return false;
+}
+
 static const u8 bluetooth_base_uuid[] = {
 			0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
 			0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -1351,10 +1446,37 @@ static u8 get_uuid_size(const u8 *uuid)
 	return 16;
 }
 
+static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
+{
+	struct pending_cmd *cmd;
+
+	hci_dev_lock(hdev);
+
+	cmd = mgmt_pending_find(mgmt_op, hdev);
+	if (!cmd)
+		goto unlock;
+
+	cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
+		     hdev->dev_class, 3);
+
+	mgmt_pending_remove(cmd);
+
+unlock:
+	hci_dev_unlock(hdev);
+}
+
+static void add_uuid_complete(struct hci_dev *hdev, u8 status)
+{
+	BT_DBG("status 0x%02x", status);
+
+	mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
+}
+
 static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
 {
 	struct mgmt_cp_add_uuid *cp = data;
 	struct pending_cmd *cmd;
+	struct hci_request req;
 	struct bt_uuid *uuid;
 	int err;
 
@@ -1362,7 +1484,7 @@ static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
 
 	hci_dev_lock(hdev);
 
-	if (test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) {
+	if (pending_eir_or_class(hdev)) {
 		err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
 				 MGMT_STATUS_BUSY);
 		goto failed;
@@ -1380,23 +1502,28 @@ static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
 
 	list_add_tail(&uuid->list, &hdev->uuids);
 
-	err = update_class(hdev);
-	if (err < 0)
-		goto failed;
+	hci_req_init(&req, hdev);
 
-	err = update_eir(hdev);
-	if (err < 0)
-		goto failed;
+	update_class(&req);
+	update_eir(&req);
+
+	err = hci_req_run(&req, add_uuid_complete);
+	if (err < 0) {
+		if (err != -ENODATA)
+			goto failed;
 
-	if (!test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) {
 		err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
 				   hdev->dev_class, 3);
 		goto failed;
 	}
 
 	cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
-	if (!cmd)
+	if (!cmd) {
 		err = -ENOMEM;
+		goto failed;
+	}
+
+	err = 0;
 
 failed:
 	hci_dev_unlock(hdev);
@@ -1417,6 +1544,13 @@ static bool enable_service_cache(struct hci_dev *hdev)
 	return false;
 }
 
+static void remove_uuid_complete(struct hci_dev *hdev, u8 status)
+{
+	BT_DBG("status 0x%02x", status);
+
+	mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
+}
+
 static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
 		       u16 len)
 {
@@ -1424,13 +1558,14 @@ static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
 	struct pending_cmd *cmd;
 	struct bt_uuid *match, *tmp;
 	u8 bt_uuid_any[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+	struct hci_request req;
 	int err, found;
 
 	BT_DBG("request for %s", hdev->name);
 
 	hci_dev_lock(hdev);
 
-	if (test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) {
+	if (pending_eir_or_class(hdev)) {
 		err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
 				 MGMT_STATUS_BUSY);
 		goto unlock;
@@ -1466,34 +1601,47 @@ static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
 	}
 
 update_class:
-	err = update_class(hdev);
-	if (err < 0)
-		goto unlock;
+	hci_req_init(&req, hdev);
 
-	err = update_eir(hdev);
-	if (err < 0)
-		goto unlock;
+	update_class(&req);
+	update_eir(&req);
+
+	err = hci_req_run(&req, remove_uuid_complete);
+	if (err < 0) {
+		if (err != -ENODATA)
+			goto unlock;
 
-	if (!test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) {
 		err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
 				   hdev->dev_class, 3);
 		goto unlock;
 	}
 
 	cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
-	if (!cmd)
+	if (!cmd) {
 		err = -ENOMEM;
+		goto unlock;
+	}
+
+	err = 0;
 
 unlock:
 	hci_dev_unlock(hdev);
 	return err;
 }
 
+static void set_class_complete(struct hci_dev *hdev, u8 status)
+{
+	BT_DBG("status 0x%02x", status);
+
+	mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
+}
+
 static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
 			 u16 len)
 {
 	struct mgmt_cp_set_dev_class *cp = data;
 	struct pending_cmd *cmd;
+	struct hci_request req;
 	int err;
 
 	BT_DBG("request for %s", hdev->name);
@@ -1502,15 +1650,19 @@ static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
 		return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
 				  MGMT_STATUS_NOT_SUPPORTED);
 
-	if (test_bit(HCI_PENDING_CLASS, &hdev->dev_flags))
-		return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
-				  MGMT_STATUS_BUSY);
+	hci_dev_lock(hdev);
 
-	if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0)
-		return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
-				  MGMT_STATUS_INVALID_PARAMS);
+	if (pending_eir_or_class(hdev)) {
+		err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
+				 MGMT_STATUS_BUSY);
+		goto unlock;
+	}
 
-	hci_dev_lock(hdev);
+	if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
+		err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
+				 MGMT_STATUS_INVALID_PARAMS);
+		goto unlock;
+	}
 
 	hdev->major_class = cp->major;
 	hdev->minor_class = cp->minor;
@@ -1521,26 +1673,34 @@ static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
 		goto unlock;
 	}
 
+	hci_req_init(&req, hdev);
+
 	if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
 		hci_dev_unlock(hdev);
 		cancel_delayed_work_sync(&hdev->service_cache);
 		hci_dev_lock(hdev);
-		update_eir(hdev);
+		update_eir(&req);
 	}
 
-	err = update_class(hdev);
-	if (err < 0)
-		goto unlock;
+	update_class(&req);
+
+	err = hci_req_run(&req, set_class_complete);
+	if (err < 0) {
+		if (err != -ENODATA)
+			goto unlock;
 
-	if (!test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) {
 		err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
 				   hdev->dev_class, 3);
 		goto unlock;
 	}
 
 	cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
-	if (!cmd)
+	if (!cmd) {
 		err = -ENOMEM;
+		goto unlock;
+	}
+
+	err = 0;
 
 unlock:
 	hci_dev_unlock(hdev);
@@ -2140,7 +2300,7 @@ unlock:
 }
 
 static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
-			     bdaddr_t *bdaddr, u8 type, u16 mgmt_op,
+			     struct mgmt_addr_info *addr, u16 mgmt_op,
 			     u16 hci_op, __le32 passkey)
 {
 	struct pending_cmd *cmd;
@@ -2150,37 +2310,41 @@ static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
 	hci_dev_lock(hdev);
 
 	if (!hdev_is_powered(hdev)) {
-		err = cmd_status(sk, hdev->id, mgmt_op,
-				 MGMT_STATUS_NOT_POWERED);
+		err = cmd_complete(sk, hdev->id, mgmt_op,
+				   MGMT_STATUS_NOT_POWERED, addr,
+				   sizeof(*addr));
 		goto done;
 	}
 
-	if (type == BDADDR_BREDR)
-		conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, bdaddr);
+	if (addr->type == BDADDR_BREDR)
+		conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
 	else
-		conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, bdaddr);
+		conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
 
 	if (!conn) {
-		err = cmd_status(sk, hdev->id, mgmt_op,
-				 MGMT_STATUS_NOT_CONNECTED);
+		err = cmd_complete(sk, hdev->id, mgmt_op,
+				   MGMT_STATUS_NOT_CONNECTED, addr,
+				   sizeof(*addr));
 		goto done;
 	}
 
-	if (type == BDADDR_LE_PUBLIC || type == BDADDR_LE_RANDOM) {
+	if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
 		/* Continue with pairing via SMP */
 		err = smp_user_confirm_reply(conn, mgmt_op, passkey);
 
 		if (!err)
-			err = cmd_status(sk, hdev->id, mgmt_op,
-					 MGMT_STATUS_SUCCESS);
+			err = cmd_complete(sk, hdev->id, mgmt_op,
+					   MGMT_STATUS_SUCCESS, addr,
+					   sizeof(*addr));
 		else
-			err = cmd_status(sk, hdev->id, mgmt_op,
-					 MGMT_STATUS_FAILED);
+			err = cmd_complete(sk, hdev->id, mgmt_op,
+					   MGMT_STATUS_FAILED, addr,
+					   sizeof(*addr));
 
 		goto done;
 	}
 
-	cmd = mgmt_pending_add(sk, mgmt_op, hdev, bdaddr, sizeof(*bdaddr));
+	cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
 	if (!cmd) {
 		err = -ENOMEM;
 		goto done;
@@ -2190,11 +2354,12 @@ static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
 	if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
 		struct hci_cp_user_passkey_reply cp;
 
-		bacpy(&cp.bdaddr, bdaddr);
+		bacpy(&cp.bdaddr, &addr->bdaddr);
 		cp.passkey = passkey;
 		err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
 	} else
-		err = hci_send_cmd(hdev, hci_op, sizeof(*bdaddr), bdaddr);
+		err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
+				   &addr->bdaddr);
 
 	if (err < 0)
 		mgmt_pending_remove(cmd);
@@ -2211,7 +2376,7 @@ static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
 
 	BT_DBG("");
 
-	return user_pairing_resp(sk, hdev, &cp->addr.bdaddr, cp->addr.type,
+	return user_pairing_resp(sk, hdev, &cp->addr,
 				MGMT_OP_PIN_CODE_NEG_REPLY,
 				HCI_OP_PIN_CODE_NEG_REPLY, 0);
 }
@@ -2227,7 +2392,7 @@ static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
 		return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
 				  MGMT_STATUS_INVALID_PARAMS);
 
-	return user_pairing_resp(sk, hdev, &cp->addr.bdaddr, cp->addr.type,
+	return user_pairing_resp(sk, hdev, &cp->addr,
 				 MGMT_OP_USER_CONFIRM_REPLY,
 				 HCI_OP_USER_CONFIRM_REPLY, 0);
 }
@@ -2239,7 +2404,7 @@ static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
 
 	BT_DBG("");
 
-	return user_pairing_resp(sk, hdev, &cp->addr.bdaddr, cp->addr.type,
+	return user_pairing_resp(sk, hdev, &cp->addr,
 				 MGMT_OP_USER_CONFIRM_NEG_REPLY,
 				 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
 }
@@ -2251,7 +2416,7 @@ static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
 
 	BT_DBG("");
 
-	return user_pairing_resp(sk, hdev, &cp->addr.bdaddr, cp->addr.type,
+	return user_pairing_resp(sk, hdev, &cp->addr,
 				 MGMT_OP_USER_PASSKEY_REPLY,
 				 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
 }
@@ -2263,18 +2428,47 @@ static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
 
 	BT_DBG("");
 
-	return user_pairing_resp(sk, hdev, &cp->addr.bdaddr, cp->addr.type,
+	return user_pairing_resp(sk, hdev, &cp->addr,
 				 MGMT_OP_USER_PASSKEY_NEG_REPLY,
 				 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
 }
 
-static int update_name(struct hci_dev *hdev, const char *name)
+static void update_name(struct hci_request *req)
 {
+	struct hci_dev *hdev = req->hdev;
 	struct hci_cp_write_local_name cp;
 
-	memcpy(cp.name, name, sizeof(cp.name));
+	memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
+
+	hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
+}
+
+static void set_name_complete(struct hci_dev *hdev, u8 status)
+{
+	struct mgmt_cp_set_local_name *cp;
+	struct pending_cmd *cmd;
+
+	BT_DBG("status 0x%02x", status);
+
+	hci_dev_lock(hdev);
+
+	cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
+	if (!cmd)
+		goto unlock;
+
+	cp = cmd->param;
 
-	return hci_send_cmd(hdev, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
+	if (status)
+		cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
+			   mgmt_status(status));
+	else
+		cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
+			     cp, sizeof(*cp));
+
+	mgmt_pending_remove(cmd);
+
+unlock:
+	hci_dev_unlock(hdev);
 }
 
 static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
@@ -2282,12 +2476,24 @@ static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
 {
 	struct mgmt_cp_set_local_name *cp = data;
 	struct pending_cmd *cmd;
+	struct hci_request req;
 	int err;
 
 	BT_DBG("");
 
 	hci_dev_lock(hdev);
 
+	/* If the old values are the same as the new ones just return a
+	 * direct command complete event.
+	 */
+	if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
+	    !memcmp(hdev->short_name, cp->short_name,
+		    sizeof(hdev->short_name))) {
+		err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
+				   data, len);
+		goto failed;
+	}
+
 	memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
 
 	if (!hdev_is_powered(hdev)) {
@@ -2310,7 +2516,19 @@ static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
 		goto failed;
 	}
 
-	err = update_name(hdev, cp->name);
+	memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
+
+	hci_req_init(&req, hdev);
+
+	if (lmp_bredr_capable(hdev)) {
+		update_name(&req);
+		update_eir(&req);
+	}
+
+	if (lmp_le_capable(hdev))
+		hci_update_ad(&req);
+
+	err = hci_req_run(&req, set_name_complete);
 	if (err < 0)
 		mgmt_pending_remove(cmd);
 
@@ -2698,6 +2916,7 @@ static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
 			 u16 len)
 {
 	struct mgmt_cp_set_device_id *cp = data;
+	struct hci_request req;
 	int err;
 	__u16 source;
 
@@ -2718,24 +2937,59 @@ static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
 
 	err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0);
 
-	update_eir(hdev);
+	hci_req_init(&req, hdev);
+	update_eir(&req);
+	hci_req_run(&req, NULL);
 
 	hci_dev_unlock(hdev);
 
 	return err;
 }
 
+static void fast_connectable_complete(struct hci_dev *hdev, u8 status)
+{
+	struct pending_cmd *cmd;
+
+	BT_DBG("status 0x%02x", status);
+
+	hci_dev_lock(hdev);
+
+	cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
+	if (!cmd)
+		goto unlock;
+
+	if (status) {
+		cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
+			   mgmt_status(status));
+	} else {
+		struct mgmt_mode *cp = cmd->param;
+
+		if (cp->val)
+			set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
+		else
+			clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
+
+		send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
+		new_settings(hdev, cmd->sk);
+	}
+
+	mgmt_pending_remove(cmd);
+
+unlock:
+	hci_dev_unlock(hdev);
+}
+
 static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
 				void *data, u16 len)
 {
 	struct mgmt_mode *cp = data;
-	struct hci_cp_write_page_scan_activity acp;
-	u8 type;
+	struct pending_cmd *cmd;
+	struct hci_request req;
 	int err;
 
 	BT_DBG("%s", hdev->name);
 
-	if (!lmp_bredr_capable(hdev))
+	if (!lmp_bredr_capable(hdev) || hdev->hci_ver < BLUETOOTH_VER_1_2)
 		return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
 				  MGMT_STATUS_NOT_SUPPORTED);
 
@@ -2753,40 +3007,39 @@ static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
 
 	hci_dev_lock(hdev);
 
-	if (cp->val) {
-		type = PAGE_SCAN_TYPE_INTERLACED;
+	if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
+		err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
+				 MGMT_STATUS_BUSY);
+		goto unlock;
+	}
 
-		/* 160 msec page scan interval */
-		acp.interval = __constant_cpu_to_le16(0x0100);
-	} else {
-		type = PAGE_SCAN_TYPE_STANDARD;	/* default */
+	if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) {
+		err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
+					hdev);
+		goto unlock;
+	}
 
-		/* default 1.28 sec page scan */
-		acp.interval = __constant_cpu_to_le16(0x0800);
+	cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
+			       data, len);
+	if (!cmd) {
+		err = -ENOMEM;
+		goto unlock;
 	}
 
-	/* default 11.25 msec page scan window */
-	acp.window = __constant_cpu_to_le16(0x0012);
+	hci_req_init(&req, hdev);
 
-	err = hci_send_cmd(hdev, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY, sizeof(acp),
-			   &acp);
-	if (err < 0) {
-		err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
-				 MGMT_STATUS_FAILED);
-		goto done;
-	}
+	write_fast_connectable(&req, cp->val);
 
-	err = hci_send_cmd(hdev, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
+	err = hci_req_run(&req, fast_connectable_complete);
 	if (err < 0) {
 		err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
 				 MGMT_STATUS_FAILED);
-		goto done;
+		mgmt_pending_remove(cmd);
 	}
 
-	err = cmd_complete(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE, 0,
-			   NULL, 0);
-done:
+unlock:
 	hci_dev_unlock(hdev);
+
 	return err;
 }
 
@@ -3043,79 +3296,115 @@ static void settings_rsp(struct pending_cmd *cmd, void *data)
 	mgmt_pending_free(cmd);
 }
 
-static int set_bredr_scan(struct hci_dev *hdev)
+static void set_bredr_scan(struct hci_request *req)
 {
+	struct hci_dev *hdev = req->hdev;
 	u8 scan = 0;
 
+	/* Ensure that fast connectable is disabled. This function will
+	 * not do anything if the page scan parameters are already what
+	 * they should be.
+	 */
+	write_fast_connectable(req, false);
+
 	if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
 		scan |= SCAN_PAGE;
 	if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
 		scan |= SCAN_INQUIRY;
 
-	if (!scan)
-		return 0;
-
-	return hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
+	if (scan)
+		hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
 }
 
-int mgmt_powered(struct hci_dev *hdev, u8 powered)
+static void powered_complete(struct hci_dev *hdev, u8 status)
 {
 	struct cmd_lookup match = { NULL, hdev };
-	int err;
 
-	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
-		return 0;
+	BT_DBG("status 0x%02x", status);
+
+	hci_dev_lock(hdev);
 
 	mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
 
-	if (powered) {
-		u8 link_sec;
+	new_settings(hdev, match.sk);
 
-		if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
-		    !lmp_host_ssp_capable(hdev)) {
-			u8 ssp = 1;
+	hci_dev_unlock(hdev);
 
-			hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
-		}
+	if (match.sk)
+		sock_put(match.sk);
+}
 
-		if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
-			struct hci_cp_write_le_host_supported cp;
+static int powered_update_hci(struct hci_dev *hdev)
+{
+	struct hci_request req;
+	u8 link_sec;
 
-			cp.le = 1;
-			cp.simul = lmp_le_br_capable(hdev);
+	hci_req_init(&req, hdev);
 
-			/* Check first if we already have the right
-			 * host state (host features set)
-			 */
-			if (cp.le != lmp_host_le_capable(hdev) ||
-			    cp.simul != lmp_host_le_br_capable(hdev))
-				hci_send_cmd(hdev,
-					     HCI_OP_WRITE_LE_HOST_SUPPORTED,
-					     sizeof(cp), &cp);
-		}
+	if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
+	    !lmp_host_ssp_capable(hdev)) {
+		u8 ssp = 1;
 
-		link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
-		if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
-			hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE,
-				     sizeof(link_sec), &link_sec);
+		hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
+	}
 
-		if (lmp_bredr_capable(hdev)) {
-			set_bredr_scan(hdev);
-			update_class(hdev);
-			update_name(hdev, hdev->dev_name);
-			update_eir(hdev);
-		}
-	} else {
-		u8 status = MGMT_STATUS_NOT_POWERED;
-		u8 zero_cod[] = { 0, 0, 0 };
+	if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
+		struct hci_cp_write_le_host_supported cp;
 
-		mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
+		cp.le = 1;
+		cp.simul = lmp_le_br_capable(hdev);
 
-		if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
-			mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
-				   zero_cod, sizeof(zero_cod), NULL);
+		/* Check first if we already have the right
+		 * host state (host features set)
+		 */
+		if (cp.le != lmp_host_le_capable(hdev) ||
+		    cp.simul != lmp_host_le_br_capable(hdev))
+			hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
+				    sizeof(cp), &cp);
 	}
 
+	link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
+	if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
+		hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
+			    sizeof(link_sec), &link_sec);
+
+	if (lmp_bredr_capable(hdev)) {
+		set_bredr_scan(&req);
+		update_class(&req);
+		update_name(&req);
+		update_eir(&req);
+	}
+
+	return hci_req_run(&req, powered_complete);
+}
+
+int mgmt_powered(struct hci_dev *hdev, u8 powered)
+{
+	struct cmd_lookup match = { NULL, hdev };
+	u8 status_not_powered = MGMT_STATUS_NOT_POWERED;
+	u8 zero_cod[] = { 0, 0, 0 };
+	int err;
+
+	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
+		return 0;
+
+	if (powered) {
+		if (powered_update_hci(hdev) == 0)
+			return 0;
+
+		mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
+				     &match);
+		goto new_settings;
+	}
+
+	mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
+	mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status_not_powered);
+
+	if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
+		mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
+			   zero_cod, sizeof(zero_cod), NULL);
+
+new_settings:
 	err = new_settings(hdev, match.sk);
 
 	if (match.sk)
@@ -3152,7 +3441,7 @@ int mgmt_discoverable(struct hci_dev *hdev, u8 discoverable)
 
 int mgmt_connectable(struct hci_dev *hdev, u8 connectable)
 {
-	struct cmd_lookup match = { NULL, hdev };
+	struct pending_cmd *cmd;
 	bool changed = false;
 	int err = 0;
 
@@ -3164,14 +3453,10 @@ int mgmt_connectable(struct hci_dev *hdev, u8 connectable)
 			changed = true;
 	}
 
-	mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev, settings_rsp,
-			     &match);
+	cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
 
 	if (changed)
-		err = new_settings(hdev, match.sk);
-
-	if (match.sk)
-		sock_put(match.sk);
+		err = new_settings(hdev, cmd ? cmd->sk : NULL);
 
 	return err;
 }
@@ -3555,23 +3840,25 @@ int mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
 	return err;
 }
 
-static int clear_eir(struct hci_dev *hdev)
+static void clear_eir(struct hci_request *req)
 {
+	struct hci_dev *hdev = req->hdev;
 	struct hci_cp_write_eir cp;
 
 	if (!lmp_ext_inq_capable(hdev))
-		return 0;
+		return;
 
 	memset(hdev->eir, 0, sizeof(hdev->eir));
 
 	memset(&cp, 0, sizeof(cp));
 
-	return hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
+	hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
 }
 
 int mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
 {
 	struct cmd_lookup match = { NULL, hdev };
+	struct hci_request req;
 	bool changed = false;
 	int err = 0;
 
@@ -3604,29 +3891,26 @@ int mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
 	if (match.sk)
 		sock_put(match.sk);
 
+	hci_req_init(&req, hdev);
+
 	if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
-		update_eir(hdev);
+		update_eir(&req);
 	else
-		clear_eir(hdev);
+		clear_eir(&req);
+
+	hci_req_run(&req, NULL);
 
 	return err;
 }
 
-static void class_rsp(struct pending_cmd *cmd, void *data)
+static void sk_lookup(struct pending_cmd *cmd, void *data)
 {
 	struct cmd_lookup *match = data;
 
-	cmd_complete(cmd->sk, cmd->index, cmd->opcode, match->mgmt_status,
-		     match->hdev->dev_class, 3);
-
-	list_del(&cmd->list);
-
 	if (match->sk == NULL) {
 		match->sk = cmd->sk;
 		sock_hold(match->sk);
 	}
-
-	mgmt_pending_free(cmd);
 }
 
 int mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
@@ -3635,11 +3919,9 @@ int mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
 	struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
 	int err = 0;
 
-	clear_bit(HCI_PENDING_CLASS, &hdev->dev_flags);
-
-	mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, class_rsp, &match);
-	mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, class_rsp, &match);
-	mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, class_rsp, &match);
+	mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
+	mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
+	mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
 
 	if (!status)
 		err = mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class,
@@ -3653,55 +3935,29 @@ int mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
 
 int mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
 {
-	struct pending_cmd *cmd;
 	struct mgmt_cp_set_local_name ev;
-	bool changed = false;
-	int err = 0;
+	struct pending_cmd *cmd;
 
-	if (memcmp(name, hdev->dev_name, sizeof(hdev->dev_name)) != 0) {
-		memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
-		changed = true;
-	}
+	if (status)
+		return 0;
 
 	memset(&ev, 0, sizeof(ev));
 	memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
 	memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
 
 	cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
-	if (!cmd)
-		goto send_event;
-
-	/* Always assume that either the short or the complete name has
-	 * changed if there was a pending mgmt command */
-	changed = true;
+	if (!cmd) {
+		memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
 
-	if (status) {
-		err = cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
-				 mgmt_status(status));
-		goto failed;
+		/* If this is a HCI command related to powering on the
+		 * HCI dev don't send any mgmt signals.
+		 */
+		if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
+			return 0;
 	}
 
-	err = cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0, &ev,
-			   sizeof(ev));
-	if (err < 0)
-		goto failed;
-
-send_event:
-	if (changed)
-		err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev,
-				 sizeof(ev), cmd ? cmd->sk : NULL);
-
-	/* EIR is taken care of separately when powering on the
-	 * adapter so only update them here if this is a name change
-	 * unrelated to power on.
-	 */
-	if (!test_bit(HCI_INIT, &hdev->flags))
-		update_eir(hdev);
-
-failed:
-	if (cmd)
-		mgmt_pending_remove(cmd);
-	return err;
+	return mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
+			  cmd ? cmd->sk : NULL);
 }
 
 int mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash,
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index b23e271..ca957d3 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -69,7 +69,7 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src,
 							u8 sec_level,
 							int *err);
 static struct rfcomm_session *rfcomm_session_get(bdaddr_t *src, bdaddr_t *dst);
-static void rfcomm_session_del(struct rfcomm_session *s);
+static struct rfcomm_session *rfcomm_session_del(struct rfcomm_session *s);
 
 /* ---- RFCOMM frame parsing macros ---- */
 #define __get_dlci(b)     ((b & 0xfc) >> 2)
@@ -108,12 +108,6 @@ static void rfcomm_schedule(void)
 	wake_up_process(rfcomm_thread);
 }
 
-static void rfcomm_session_put(struct rfcomm_session *s)
-{
-	if (atomic_dec_and_test(&s->refcnt))
-		rfcomm_session_del(s);
-}
-
 /* ---- RFCOMM FCS computation ---- */
 
 /* reversed, 8-bit, poly=0x07 */
@@ -249,16 +243,14 @@ static void rfcomm_session_set_timer(struct rfcomm_session *s, long timeout)
 {
 	BT_DBG("session %p state %ld timeout %ld", s, s->state, timeout);
 
-	if (!mod_timer(&s->timer, jiffies + timeout))
-		rfcomm_session_hold(s);
+	mod_timer(&s->timer, jiffies + timeout);
 }
 
 static void rfcomm_session_clear_timer(struct rfcomm_session *s)
 {
 	BT_DBG("session %p state %ld", s, s->state);
 
-	if (del_timer(&s->timer))
-		rfcomm_session_put(s);
+	del_timer_sync(&s->timer);
 }
 
 /* ---- RFCOMM DLCs ---- */
@@ -336,8 +328,6 @@ static void rfcomm_dlc_link(struct rfcomm_session *s, struct rfcomm_dlc *d)
 {
 	BT_DBG("dlc %p session %p", d, s);
 
-	rfcomm_session_hold(s);
-
 	rfcomm_session_clear_timer(s);
 	rfcomm_dlc_hold(d);
 	list_add(&d->list, &s->dlcs);
@@ -356,8 +346,6 @@ static void rfcomm_dlc_unlink(struct rfcomm_dlc *d)
 
 	if (list_empty(&s->dlcs))
 		rfcomm_session_set_timer(s, RFCOMM_IDLE_TIMEOUT);
-
-	rfcomm_session_put(s);
 }
 
 static struct rfcomm_dlc *rfcomm_dlc_get(struct rfcomm_session *s, u8 dlci)
@@ -493,12 +481,34 @@ static int __rfcomm_dlc_close(struct rfcomm_dlc *d, int err)
 
 int rfcomm_dlc_close(struct rfcomm_dlc *d, int err)
 {
-	int r;
+	int r = 0;
+	struct rfcomm_dlc *d_list;
+	struct rfcomm_session *s, *s_list;
+
+	BT_DBG("dlc %p state %ld dlci %d err %d", d, d->state, d->dlci, err);
 
 	rfcomm_lock();
 
-	r = __rfcomm_dlc_close(d, err);
+	s = d->session;
+	if (!s)
+		goto no_session;
+
+	/* after waiting on the mutex check the session still exists
+	 * then check the dlc still exists
+	 */
+	list_for_each_entry(s_list, &session_list, list) {
+		if (s_list == s) {
+			list_for_each_entry(d_list, &s->dlcs, list) {
+				if (d_list == d) {
+					r = __rfcomm_dlc_close(d, err);
+					break;
+				}
+			}
+			break;
+		}
+	}
 
+no_session:
 	rfcomm_unlock();
 	return r;
 }
@@ -609,7 +619,7 @@ static struct rfcomm_session *rfcomm_session_add(struct socket *sock, int state)
 	return s;
 }
 
-static void rfcomm_session_del(struct rfcomm_session *s)
+static struct rfcomm_session *rfcomm_session_del(struct rfcomm_session *s)
 {
 	int state = s->state;
 
@@ -617,15 +627,14 @@ static void rfcomm_session_del(struct rfcomm_session *s)
 
 	list_del(&s->list);
 
-	if (state == BT_CONNECTED)
-		rfcomm_send_disc(s, 0);
-
 	rfcomm_session_clear_timer(s);
 	sock_release(s->sock);
 	kfree(s);
 
 	if (state != BT_LISTEN)
 		module_put(THIS_MODULE);
+
+	return NULL;
 }
 
 static struct rfcomm_session *rfcomm_session_get(bdaddr_t *src, bdaddr_t *dst)
@@ -644,17 +653,16 @@ static struct rfcomm_session *rfcomm_session_get(bdaddr_t *src, bdaddr_t *dst)
 	return NULL;
 }
 
-static void rfcomm_session_close(struct rfcomm_session *s, int err)
+static struct rfcomm_session *rfcomm_session_close(struct rfcomm_session *s,
+						   int err)
 {
 	struct rfcomm_dlc *d;
 	struct list_head *p, *n;
 
-	BT_DBG("session %p state %ld err %d", s, s->state, err);
-
-	rfcomm_session_hold(s);
-
 	s->state = BT_CLOSED;
 
+	BT_DBG("session %p state %ld err %d", s, s->state, err);
+
 	/* Close all dlcs */
 	list_for_each_safe(p, n, &s->dlcs) {
 		d = list_entry(p, struct rfcomm_dlc, list);
@@ -663,7 +671,7 @@ static void rfcomm_session_close(struct rfcomm_session *s, int err)
 	}
 
 	rfcomm_session_clear_timer(s);
-	rfcomm_session_put(s);
+	return rfcomm_session_del(s);
 }
 
 static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src,
@@ -715,8 +723,7 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src,
 	if (*err == 0 || *err == -EINPROGRESS)
 		return s;
 
-	rfcomm_session_del(s);
-	return NULL;
+	return rfcomm_session_del(s);
 
 failed:
 	sock_release(sock);
@@ -1105,7 +1112,7 @@ static void rfcomm_make_uih(struct sk_buff *skb, u8 addr)
 }
 
 /* ---- RFCOMM frame reception ---- */
-static int rfcomm_recv_ua(struct rfcomm_session *s, u8 dlci)
+static struct rfcomm_session *rfcomm_recv_ua(struct rfcomm_session *s, u8 dlci)
 {
 	BT_DBG("session %p state %ld dlci %d", s, s->state, dlci);
 
@@ -1114,7 +1121,7 @@ static int rfcomm_recv_ua(struct rfcomm_session *s, u8 dlci)
 		struct rfcomm_dlc *d = rfcomm_dlc_get(s, dlci);
 		if (!d) {
 			rfcomm_send_dm(s, dlci);
-			return 0;
+			return s;
 		}
 
 		switch (d->state) {
@@ -1150,25 +1157,14 @@ static int rfcomm_recv_ua(struct rfcomm_session *s, u8 dlci)
 			break;
 
 		case BT_DISCONN:
-			/* rfcomm_session_put is called later so don't do
-			 * anything here otherwise we will mess up the session
-			 * reference counter:
-			 *
-			 * (a) when we are the initiator dlc_unlink will drive
-			 * the reference counter to 0 (there is no initial put
-			 * after session_add)
-			 *
-			 * (b) when we are not the initiator rfcomm_rx_process
-			 * will explicitly call put to balance the initial hold
-			 * done after session add.
-			 */
+			s = rfcomm_session_close(s, ECONNRESET);
 			break;
 		}
 	}
-	return 0;
+	return s;
 }
 
-static int rfcomm_recv_dm(struct rfcomm_session *s, u8 dlci)
+static struct rfcomm_session *rfcomm_recv_dm(struct rfcomm_session *s, u8 dlci)
 {
 	int err = 0;
 
@@ -1192,13 +1188,13 @@ static int rfcomm_recv_dm(struct rfcomm_session *s, u8 dlci)
 		else
 			err = ECONNRESET;
 
-		s->state = BT_CLOSED;
-		rfcomm_session_close(s, err);
+		s = rfcomm_session_close(s, err);
 	}
-	return 0;
+	return s;
 }
 
-static int rfcomm_recv_disc(struct rfcomm_session *s, u8 dlci)
+static struct rfcomm_session *rfcomm_recv_disc(struct rfcomm_session *s,
+					       u8 dlci)
 {
 	int err = 0;
 
@@ -1227,11 +1223,9 @@ static int rfcomm_recv_disc(struct rfcomm_session *s, u8 dlci)
 		else
 			err = ECONNRESET;
 
-		s->state = BT_CLOSED;
-		rfcomm_session_close(s, err);
+		s = rfcomm_session_close(s, err);
 	}
-
-	return 0;
+	return s;
 }
 
 void rfcomm_dlc_accept(struct rfcomm_dlc *d)
@@ -1652,11 +1646,18 @@ drop:
 	return 0;
 }
 
-static int rfcomm_recv_frame(struct rfcomm_session *s, struct sk_buff *skb)
+static struct rfcomm_session *rfcomm_recv_frame(struct rfcomm_session *s,
+						struct sk_buff *skb)
 {
 	struct rfcomm_hdr *hdr = (void *) skb->data;
 	u8 type, dlci, fcs;
 
+	if (!s) {
+		/* no session, so free socket data */
+		kfree_skb(skb);
+		return s;
+	}
+
 	dlci = __get_dlci(hdr->addr);
 	type = __get_type(hdr->ctrl);
 
@@ -1667,7 +1668,7 @@ static int rfcomm_recv_frame(struct rfcomm_session *s, struct sk_buff *skb)
 	if (__check_fcs(skb->data, type, fcs)) {
 		BT_ERR("bad checksum in packet");
 		kfree_skb(skb);
-		return -EILSEQ;
+		return s;
 	}
 
 	if (__test_ea(hdr->len))
@@ -1683,22 +1684,23 @@ static int rfcomm_recv_frame(struct rfcomm_session *s, struct sk_buff *skb)
 
 	case RFCOMM_DISC:
 		if (__test_pf(hdr->ctrl))
-			rfcomm_recv_disc(s, dlci);
+			s = rfcomm_recv_disc(s, dlci);
 		break;
 
 	case RFCOMM_UA:
 		if (__test_pf(hdr->ctrl))
-			rfcomm_recv_ua(s, dlci);
+			s = rfcomm_recv_ua(s, dlci);
 		break;
 
 	case RFCOMM_DM:
-		rfcomm_recv_dm(s, dlci);
+		s = rfcomm_recv_dm(s, dlci);
 		break;
 
 	case RFCOMM_UIH:
-		if (dlci)
-			return rfcomm_recv_data(s, dlci, __test_pf(hdr->ctrl), skb);
-
+		if (dlci) {
+			rfcomm_recv_data(s, dlci, __test_pf(hdr->ctrl), skb);
+			return s;
+		}
 		rfcomm_recv_mcc(s, skb);
 		break;
 
@@ -1707,7 +1709,7 @@ static int rfcomm_recv_frame(struct rfcomm_session *s, struct sk_buff *skb)
 		break;
 	}
 	kfree_skb(skb);
-	return 0;
+	return s;
 }
 
 /* ---- Connection and data processing ---- */
@@ -1844,7 +1846,7 @@ static void rfcomm_process_dlcs(struct rfcomm_session *s)
 	}
 }
 
-static void rfcomm_process_rx(struct rfcomm_session *s)
+static struct rfcomm_session *rfcomm_process_rx(struct rfcomm_session *s)
 {
 	struct socket *sock = s->sock;
 	struct sock *sk = sock->sk;
@@ -1856,17 +1858,15 @@ static void rfcomm_process_rx(struct rfcomm_session *s)
 	while ((skb = skb_dequeue(&sk->sk_receive_queue))) {
 		skb_orphan(skb);
 		if (!skb_linearize(skb))
-			rfcomm_recv_frame(s, skb);
+			s = rfcomm_recv_frame(s, skb);
 		else
 			kfree_skb(skb);
 	}
 
-	if (sk->sk_state == BT_CLOSED) {
-		if (!s->initiator)
-			rfcomm_session_put(s);
+	if (s && (sk->sk_state == BT_CLOSED))
+		s = rfcomm_session_close(s, sk->sk_err);
 
-		rfcomm_session_close(s, sk->sk_err);
-	}
+	return s;
 }
 
 static void rfcomm_accept_connection(struct rfcomm_session *s)
@@ -1891,8 +1891,6 @@ static void rfcomm_accept_connection(struct rfcomm_session *s)
 
 	s = rfcomm_session_add(nsock, BT_OPEN);
 	if (s) {
-		rfcomm_session_hold(s);
-
 		/* We should adjust MTU on incoming sessions.
 		 * L2CAP MTU minus UIH header and FCS. */
 		s->mtu = min(l2cap_pi(nsock->sk)->chan->omtu,
@@ -1903,7 +1901,7 @@ static void rfcomm_accept_connection(struct rfcomm_session *s)
 		sock_release(nsock);
 }
 
-static void rfcomm_check_connection(struct rfcomm_session *s)
+static struct rfcomm_session *rfcomm_check_connection(struct rfcomm_session *s)
 {
 	struct sock *sk = s->sock->sk;
 
@@ -1921,10 +1919,10 @@ static void rfcomm_check_connection(struct rfcomm_session *s)
 		break;
 
 	case BT_CLOSED:
-		s->state = BT_CLOSED;
-		rfcomm_session_close(s, sk->sk_err);
+		s = rfcomm_session_close(s, sk->sk_err);
 		break;
 	}
+	return s;
 }
 
 static void rfcomm_process_sessions(void)
@@ -1940,7 +1938,6 @@ static void rfcomm_process_sessions(void)
 		if (test_and_clear_bit(RFCOMM_TIMED_OUT, &s->flags)) {
 			s->state = BT_DISCONN;
 			rfcomm_send_disc(s, 0);
-			rfcomm_session_put(s);
 			continue;
 		}
 
@@ -1949,21 +1946,18 @@ static void rfcomm_process_sessions(void)
 			continue;
 		}
 
-		rfcomm_session_hold(s);
-
 		switch (s->state) {
 		case BT_BOUND:
-			rfcomm_check_connection(s);
+			s = rfcomm_check_connection(s);
 			break;
 
 		default:
-			rfcomm_process_rx(s);
+			s = rfcomm_process_rx(s);
 			break;
 		}
 
-		rfcomm_process_dlcs(s);
-
-		rfcomm_session_put(s);
+		if (s)
+			rfcomm_process_dlcs(s);
 	}
 
 	rfcomm_unlock();
@@ -2010,10 +2004,11 @@ static int rfcomm_add_listener(bdaddr_t *ba)
 
 	/* Add listening session */
 	s = rfcomm_session_add(sock, BT_LISTEN);
-	if (!s)
+	if (!s) {
+		err = -ENOMEM;
 		goto failed;
+	}
 
-	rfcomm_session_hold(s);
 	return 0;
 failed:
 	sock_release(sock);
@@ -2071,8 +2066,6 @@ static void rfcomm_security_cfm(struct hci_conn *conn, u8 status, u8 encrypt)
 	if (!s)
 		return;
 
-	rfcomm_session_hold(s);
-
 	list_for_each_safe(p, n, &s->dlcs) {
 		d = list_entry(p, struct rfcomm_dlc, list);
 
@@ -2104,8 +2097,6 @@ static void rfcomm_security_cfm(struct hci_conn *conn, u8 status, u8 encrypt)
 			set_bit(RFCOMM_AUTH_REJECT, &d->flags);
 	}
 
-	rfcomm_session_put(s);
-
 	rfcomm_schedule();
 }
 
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
index c23bae8..3786ddc 100644
--- a/net/bluetooth/rfcomm/sock.c
+++ b/net/bluetooth/rfcomm/sock.c
@@ -1065,8 +1065,7 @@ void __exit rfcomm_cleanup_sockets(void)
 
 	debugfs_remove(rfcomm_sock_debugfs);
 
-	if (bt_sock_unregister(BTPROTO_RFCOMM) < 0)
-		BT_ERR("RFCOMM socket layer unregistration failed");
+	bt_sock_unregister(BTPROTO_RFCOMM);
 
 	proto_unregister(&rfcomm_proto);
 }
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index fad0302..d919d11 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -1112,8 +1112,7 @@ void __exit sco_exit(void)
 
 	debugfs_remove(sco_debugfs);
 
-	if (bt_sock_unregister(BTPROTO_SCO) < 0)
-		BT_ERR("SCO socket unregistration failed");
+	bt_sock_unregister(BTPROTO_SCO);
 
 	proto_unregister(&sco_proto);
 }
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
index bab338e..c581f12 100644
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -161,9 +161,7 @@ void br_fdb_change_mac_address(struct net_bridge *br, const u8 *newaddr)
 	if (!pv)
 		return;
 
-	for (vid = find_next_bit(pv->vlan_bitmap, BR_VLAN_BITMAP_LEN, vid);
-	     vid < BR_VLAN_BITMAP_LEN;
-	     vid = find_next_bit(pv->vlan_bitmap, BR_VLAN_BITMAP_LEN, vid+1)) {
+	for_each_set_bit_from(vid, pv->vlan_bitmap, BR_VLAN_BITMAP_LEN) {
 		f = __br_fdb_get(br, br->dev->dev_addr, vid);
 		if (f && f->is_local && !f->dst)
 			fdb_delete(br, f);
@@ -724,13 +722,10 @@ int br_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
 		 * specify a VLAN.  To be nice, add/update entry for every
 		 * vlan on this port.
 		 */
-		vid = find_first_bit(pv->vlan_bitmap, BR_VLAN_BITMAP_LEN);
-		while (vid < BR_VLAN_BITMAP_LEN) {
+		for_each_set_bit(vid, pv->vlan_bitmap, BR_VLAN_BITMAP_LEN) {
 			err = __br_fdb_add(ndm, p, addr, nlh_flags, vid);
 			if (err)
 				goto out;
-			vid = find_next_bit(pv->vlan_bitmap,
-					    BR_VLAN_BITMAP_LEN, vid+1);
 		}
 	}
 
@@ -815,11 +810,8 @@ int br_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[],
 		 * vlan on this port.
 		 */
 		err = -ENOENT;
-		vid = find_first_bit(pv->vlan_bitmap, BR_VLAN_BITMAP_LEN);
-		while (vid < BR_VLAN_BITMAP_LEN) {
+		for_each_set_bit(vid, pv->vlan_bitmap, BR_VLAN_BITMAP_LEN) {
 			err &= __br_fdb_delete(p, addr, vid);
-			vid = find_next_bit(pv->vlan_bitmap,
-					    BR_VLAN_BITMAP_LEN, vid+1);
 		}
 	}
 out:
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index ef1b914..f17fcb3 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -148,7 +148,6 @@ static void del_nbp(struct net_bridge_port *p)
 	dev->priv_flags &= ~IFF_BRIDGE_PORT;
 
 	netdev_rx_handler_unregister(dev);
-	synchronize_net();
 
 	netdev_upper_dev_unlink(dev, br->dev);
 
diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c
index ee79f3f..19942e3 100644
--- a/net/bridge/br_mdb.c
+++ b/net/bridge/br_mdb.c
@@ -382,7 +382,7 @@ static int __br_mdb_add(struct net *net, struct net_bridge *br,
 	return ret;
 }
 
-static int br_mdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+static int br_mdb_add(struct sk_buff *skb, struct nlmsghdr *nlh)
 {
 	struct net *net = sock_net(skb->sk);
 	struct br_mdb_entry *entry;
@@ -458,7 +458,7 @@ unlock:
 	return err;
 }
 
-static int br_mdb_del(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+static int br_mdb_del(struct sk_buff *skb, struct nlmsghdr *nlh)
 {
 	struct net_device *dev;
 	struct br_mdb_entry *entry;
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index 923fbea..81f2389 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -1369,7 +1369,7 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br,
 		return -EINVAL;
 
 	if (iph->protocol != IPPROTO_IGMP) {
-		if ((iph->daddr & IGMP_LOCAL_GROUP_MASK) != IGMP_LOCAL_GROUP)
+		if (!ipv4_is_local_multicast(iph->daddr))
 			BR_INPUT_SKB_CB(skb)->mrouters_only = 1;
 		return 0;
 	}
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index 299fc5f..8e3abf5 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -136,10 +136,7 @@ static int br_fill_ifinfo(struct sk_buff *skb,
 			goto nla_put_failure;
 
 		pvid = br_get_pvid(pv);
-		for (vid = find_first_bit(pv->vlan_bitmap, BR_VLAN_BITMAP_LEN);
-		     vid < BR_VLAN_BITMAP_LEN;
-		     vid = find_next_bit(pv->vlan_bitmap,
-					 BR_VLAN_BITMAP_LEN, vid+1)) {
+		for_each_set_bit(vid, pv->vlan_bitmap, BR_VLAN_BITMAP_LEN) {
 			vinfo.vid = vid;
 			vinfo.flags = 0;
 			if (vid == pvid)
@@ -355,17 +352,14 @@ static int br_setport(struct net_bridge_port *p, struct nlattr *tb[])
 /* Change state and parameters on port. */
 int br_setlink(struct net_device *dev, struct nlmsghdr *nlh)
 {
-	struct ifinfomsg *ifm;
 	struct nlattr *protinfo;
 	struct nlattr *afspec;
 	struct net_bridge_port *p;
 	struct nlattr *tb[IFLA_BRPORT_MAX + 1];
-	int err;
-
-	ifm = nlmsg_data(nlh);
+	int err = 0;
 
-	protinfo = nlmsg_find_attr(nlh, sizeof(*ifm), IFLA_PROTINFO);
-	afspec = nlmsg_find_attr(nlh, sizeof(*ifm), IFLA_AF_SPEC);
+	protinfo = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_PROTINFO);
+	afspec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC);
 	if (!protinfo && !afspec)
 		return 0;
 
@@ -373,7 +367,7 @@ int br_setlink(struct net_device *dev, struct nlmsghdr *nlh)
 	/* We want to accept dev as bridge itself if the AF_SPEC
 	 * is set to see if someone is setting vlan info on the brigde
 	 */
-	if (!p && ((dev->priv_flags & IFF_EBRIDGE) && !afspec))
+	if (!p && !afspec)
 		return -EINVAL;
 
 	if (p && protinfo) {
@@ -414,14 +408,11 @@ out:
 /* Delete port information */
 int br_dellink(struct net_device *dev, struct nlmsghdr *nlh)
 {
-	struct ifinfomsg *ifm;
 	struct nlattr *afspec;
 	struct net_bridge_port *p;
 	int err;
 
-	ifm = nlmsg_data(nlh);
-
-	afspec = nlmsg_find_attr(nlh, sizeof(*ifm), IFLA_AF_SPEC);
+	afspec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC);
 	if (!afspec)
 		return 0;
 
diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c
index 3bf43f7..961d870 100644
--- a/net/bridge/netfilter/ebt_ulog.c
+++ b/net/bridge/netfilter/ebt_ulog.c
@@ -35,7 +35,7 @@
 #include <linux/skbuff.h>
 #include <linux/kernel.h>
 #include <linux/timer.h>
-#include <linux/netlink.h>
+#include <net/netlink.h>
 #include <linux/netdevice.h>
 #include <linux/netfilter/x_tables.h>
 #include <linux/netfilter_bridge/ebtables.h>
@@ -134,7 +134,7 @@ static void ebt_ulog_packet(unsigned int hooknr, const struct sk_buff *skb,
 	else
 		copy_len = uloginfo->cprange;
 
-	size = NLMSG_SPACE(sizeof(*pm) + copy_len);
+	size = nlmsg_total_size(sizeof(*pm) + copy_len);
 	if (size > nlbufsiz) {
 		pr_debug("Size %Zd needed, but nlbufsiz=%d\n", size, nlbufsiz);
 		return;
@@ -319,12 +319,11 @@ static void __exit ebt_ulog_fini(void)
 	for (i = 0; i < EBT_ULOG_MAXNLGROUPS; i++) {
 		ub = &ulog_buffers[i];
 		del_timer(&ub->timer);
-		spin_lock_bh(&ub->lock);
+
 		if (ub->skb) {
 			kfree_skb(ub->skb);
 			ub->skb = NULL;
 		}
-		spin_unlock_bh(&ub->lock);
 	}
 	netlink_kernel_release(ebtulognl);
 }
diff --git a/net/bridge/netfilter/ebtable_broute.c b/net/bridge/netfilter/ebtable_broute.c
index 40d8258..70f656c 100644
--- a/net/bridge/netfilter/ebtable_broute.c
+++ b/net/bridge/netfilter/ebtable_broute.c
@@ -64,9 +64,7 @@ static int ebt_broute(struct sk_buff *skb)
 static int __net_init broute_net_init(struct net *net)
 {
 	net->xt.broute_table = ebt_register_table(net, &broute_table);
-	if (IS_ERR(net->xt.broute_table))
-		return PTR_ERR(net->xt.broute_table);
-	return 0;
+	return PTR_RET(net->xt.broute_table);
 }
 
 static void __net_exit broute_net_exit(struct net *net)
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index 8d493c9..3d110c4 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -138,7 +138,7 @@ ebt_basic_match(const struct ebt_entry *e, const struct sk_buff *skb,
 		ethproto = h->h_proto;
 
 	if (e->bitmask & EBT_802_3) {
-		if (FWINV2(ntohs(ethproto) >= 1536, EBT_IPROTO))
+		if (FWINV2(ntohs(ethproto) >= ETH_P_802_3_MIN, EBT_IPROTO))
 			return 1;
 	} else if (!(e->bitmask & EBT_NOPROTO) &&
 	   FWINV2(e->ethproto != ethproto, EBT_IPROTO))
diff --git a/net/caif/caif_dev.c b/net/caif/caif_dev.c
index 21760f0..df6d56d 100644
--- a/net/caif/caif_dev.c
+++ b/net/caif/caif_dev.c
@@ -301,10 +301,11 @@ static void dev_flowctrl(struct net_device *dev, int on)
 }
 
 void caif_enroll_dev(struct net_device *dev, struct caif_dev_common *caifdev,
-			struct cflayer *link_support, int head_room,
-			struct cflayer **layer, int (**rcv_func)(
-				struct sk_buff *, struct net_device *,
-				struct packet_type *, struct net_device *))
+		     struct cflayer *link_support, int head_room,
+		     struct cflayer **layer,
+		     int (**rcv_func)(struct sk_buff *, struct net_device *,
+				      struct packet_type *,
+				      struct net_device *))
 {
 	struct caif_device_entry *caifd;
 	enum cfcnfg_phy_preference pref;
diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c
index 095259f..1d337e0 100644
--- a/net/caif/caif_socket.c
+++ b/net/caif/caif_socket.c
@@ -197,8 +197,8 @@ static void cfsk_put(struct cflayer *layr)
 
 /* Packet Control Callback function called from CAIF */
 static void caif_ctrl_cb(struct cflayer *layr,
-				enum caif_ctrlcmd flow,
-				int phyid)
+			 enum caif_ctrlcmd flow,
+			 int phyid)
 {
 	struct caifsock *cf_sk = container_of(layr, struct caifsock, layer);
 	switch (flow) {
@@ -274,7 +274,7 @@ static void caif_check_flow_release(struct sock *sk)
  * changed locking, address handling and added MSG_TRUNC.
  */
 static int caif_seqpkt_recvmsg(struct kiocb *iocb, struct socket *sock,
-				struct msghdr *m, size_t len, int flags)
+			       struct msghdr *m, size_t len, int flags)
 
 {
 	struct sock *sk = sock->sk;
@@ -346,8 +346,8 @@ static long caif_stream_data_wait(struct sock *sk, long timeo)
  * changed locking calls, changed address handling.
  */
 static int caif_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
-				struct msghdr *msg, size_t size,
-				int flags)
+			       struct msghdr *msg, size_t size,
+			       int flags)
 {
 	struct sock *sk = sock->sk;
 	int copied = 0;
@@ -462,7 +462,7 @@ out:
  * CAIF flow-on and sock_writable.
  */
 static long caif_wait_for_flow_on(struct caifsock *cf_sk,
-				int wait_writeable, long timeo, int *err)
+				  int wait_writeable, long timeo, int *err)
 {
 	struct sock *sk = &cf_sk->sk;
 	DEFINE_WAIT(wait);
@@ -516,7 +516,7 @@ static int transmit_skb(struct sk_buff *skb, struct caifsock *cf_sk,
 
 /* Copied from af_unix:unix_dgram_sendmsg, and adapted to CAIF */
 static int caif_seqpkt_sendmsg(struct kiocb *kiocb, struct socket *sock,
-			struct msghdr *msg, size_t len)
+			       struct msghdr *msg, size_t len)
 {
 	struct sock *sk = sock->sk;
 	struct caifsock *cf_sk = container_of(sk, struct caifsock, sk);
@@ -591,7 +591,7 @@ err:
  * and other minor adaptations.
  */
 static int caif_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
-				struct msghdr *msg, size_t len)
+			       struct msghdr *msg, size_t len)
 {
 	struct sock *sk = sock->sk;
 	struct caifsock *cf_sk = container_of(sk, struct caifsock, sk);
@@ -670,7 +670,7 @@ out_err:
 }
 
 static int setsockopt(struct socket *sock,
-			int lvl, int opt, char __user *ov, unsigned int ol)
+		      int lvl, int opt, char __user *ov, unsigned int ol)
 {
 	struct sock *sk = sock->sk;
 	struct caifsock *cf_sk = container_of(sk, struct caifsock, sk);
@@ -932,7 +932,7 @@ static int caif_release(struct socket *sock)
 
 /* Copied from af_unix.c:unix_poll(), added CAIF tx_flow handling */
 static unsigned int caif_poll(struct file *file,
-				struct socket *sock, poll_table *wait)
+			      struct socket *sock, poll_table *wait)
 {
 	struct sock *sk = sock->sk;
 	unsigned int mask;
@@ -1022,7 +1022,7 @@ static void caif_sock_destructor(struct sock *sk)
 }
 
 static int caif_create(struct net *net, struct socket *sock, int protocol,
-			int kern)
+		       int kern)
 {
 	struct sock *sk = NULL;
 	struct caifsock *cf_sk = NULL;
diff --git a/net/caif/caif_usb.c b/net/caif/caif_usb.c
index ef8ebaa..d76278d 100644
--- a/net/caif/caif_usb.c
+++ b/net/caif/caif_usb.c
@@ -75,7 +75,7 @@ static int cfusbl_transmit(struct cflayer *layr, struct cfpkt *pkt)
 }
 
 static void cfusbl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
-					int phyid)
+			   int phyid)
 {
 	if (layr->up && layr->up->ctrlcmd)
 		layr->up->ctrlcmd(layr->up, ctrl, layr->id);
@@ -121,7 +121,7 @@ static struct packet_type caif_usb_type __read_mostly = {
 };
 
 static int cfusbl_device_notify(struct notifier_block *me, unsigned long what,
-			      void *arg)
+				void *arg)
 {
 	struct net_device *dev = arg;
 	struct caif_dev_common common;
diff --git a/net/caif/cfcnfg.c b/net/caif/cfcnfg.c
index f1dbddb..246ac3a 100644
--- a/net/caif/cfcnfg.c
+++ b/net/caif/cfcnfg.c
@@ -61,11 +61,11 @@ struct cfcnfg {
 };
 
 static void cfcnfg_linkup_rsp(struct cflayer *layer, u8 channel_id,
-			     enum cfctrl_srv serv, u8 phyid,
-			     struct cflayer *adapt_layer);
+			      enum cfctrl_srv serv, u8 phyid,
+			      struct cflayer *adapt_layer);
 static void cfcnfg_linkdestroy_rsp(struct cflayer *layer, u8 channel_id);
 static void cfcnfg_reject_rsp(struct cflayer *layer, u8 channel_id,
-			     struct cflayer *adapt_layer);
+			      struct cflayer *adapt_layer);
 static void cfctrl_resp_func(void);
 static void cfctrl_enum_resp(void);
 
@@ -131,7 +131,7 @@ static void cfctrl_resp_func(void)
 }
 
 static struct cfcnfg_phyinfo *cfcnfg_get_phyinfo_rcu(struct cfcnfg *cnfg,
-							u8 phyid)
+						     u8 phyid)
 {
 	struct cfcnfg_phyinfo *phy;
 
@@ -216,8 +216,8 @@ static const int protohead[CFCTRL_SRV_MASK] = {
 
 
 static int caif_connect_req_to_link_param(struct cfcnfg *cnfg,
-				   struct caif_connect_request *s,
-				   struct cfctrl_link_param *l)
+					  struct caif_connect_request *s,
+					  struct cfctrl_link_param *l)
 {
 	struct dev_info *dev_info;
 	enum cfcnfg_phy_preference pref;
@@ -301,8 +301,7 @@ static int caif_connect_req_to_link_param(struct cfcnfg *cnfg,
 
 int caif_connect_client(struct net *net, struct caif_connect_request *conn_req,
 			struct cflayer *adap_layer, int *ifindex,
-				int *proto_head,
-				int *proto_tail)
+			int *proto_head, int *proto_tail)
 {
 	struct cflayer *frml;
 	struct cfcnfg_phyinfo *phy;
@@ -364,7 +363,7 @@ unlock:
 EXPORT_SYMBOL(caif_connect_client);
 
 static void cfcnfg_reject_rsp(struct cflayer *layer, u8 channel_id,
-			     struct cflayer *adapt_layer)
+			      struct cflayer *adapt_layer)
 {
 	if (adapt_layer != NULL && adapt_layer->ctrlcmd != NULL)
 		adapt_layer->ctrlcmd(adapt_layer,
@@ -526,7 +525,7 @@ out_err:
 EXPORT_SYMBOL(cfcnfg_add_phy_layer);
 
 int cfcnfg_set_phy_state(struct cfcnfg *cnfg, struct cflayer *phy_layer,
-		bool up)
+			 bool up)
 {
 	struct cfcnfg_phyinfo *phyinfo;
 
diff --git a/net/caif/cfctrl.c b/net/caif/cfctrl.c
index a376ec1..9cd057c 100644
--- a/net/caif/cfctrl.c
+++ b/net/caif/cfctrl.c
@@ -20,12 +20,12 @@
 
 #ifdef CAIF_NO_LOOP
 static int handle_loop(struct cfctrl *ctrl,
-			      int cmd, struct cfpkt *pkt){
+		       int cmd, struct cfpkt *pkt){
 	return -1;
 }
 #else
 static int handle_loop(struct cfctrl *ctrl,
-		int cmd, struct cfpkt *pkt);
+		       int cmd, struct cfpkt *pkt);
 #endif
 static int cfctrl_recv(struct cflayer *layr, struct cfpkt *pkt);
 static void cfctrl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
@@ -72,7 +72,7 @@ void cfctrl_remove(struct cflayer *layer)
 }
 
 static bool param_eq(const struct cfctrl_link_param *p1,
-			const struct cfctrl_link_param *p2)
+		     const struct cfctrl_link_param *p2)
 {
 	bool eq =
 	    p1->linktype == p2->linktype &&
@@ -197,8 +197,8 @@ void cfctrl_enum_req(struct cflayer *layer, u8 physlinkid)
 }
 
 int cfctrl_linkup_request(struct cflayer *layer,
-			   struct cfctrl_link_param *param,
-			   struct cflayer *user_layer)
+			  struct cfctrl_link_param *param,
+			  struct cflayer *user_layer)
 {
 	struct cfctrl *cfctrl = container_obj(layer);
 	u32 tmp32;
@@ -301,7 +301,7 @@ int cfctrl_linkup_request(struct cflayer *layer,
 }
 
 int cfctrl_linkdown_req(struct cflayer *layer, u8 channelid,
-				struct cflayer *client)
+			struct cflayer *client)
 {
 	int ret;
 	struct cfpkt *pkt;
@@ -555,7 +555,7 @@ error:
 }
 
 static void cfctrl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
-			int phyid)
+			   int phyid)
 {
 	struct cfctrl *this = container_obj(layr);
 	switch (ctrl) {
diff --git a/net/caif/cffrml.c b/net/caif/cffrml.c
index 0a7df7e..204c5e2 100644
--- a/net/caif/cffrml.c
+++ b/net/caif/cffrml.c
@@ -28,7 +28,7 @@ struct cffrml {
 static int cffrml_receive(struct cflayer *layr, struct cfpkt *pkt);
 static int cffrml_transmit(struct cflayer *layr, struct cfpkt *pkt);
 static void cffrml_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
-				int phyid);
+			   int phyid);
 
 static u32 cffrml_rcv_error;
 static u32 cffrml_rcv_checsum_error;
@@ -167,7 +167,7 @@ static int cffrml_transmit(struct cflayer *layr, struct cfpkt *pkt)
 }
 
 static void cffrml_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
-					int phyid)
+			   int phyid)
 {
 	if (layr->up && layr->up->ctrlcmd)
 		layr->up->ctrlcmd(layr->up, ctrl, layr->id);
diff --git a/net/caif/cfmuxl.c b/net/caif/cfmuxl.c
index 94b0861..154d9f8 100644
--- a/net/caif/cfmuxl.c
+++ b/net/caif/cfmuxl.c
@@ -42,7 +42,7 @@ struct cfmuxl {
 static int cfmuxl_receive(struct cflayer *layr, struct cfpkt *pkt);
 static int cfmuxl_transmit(struct cflayer *layr, struct cfpkt *pkt);
 static void cfmuxl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
-				int phyid);
+			   int phyid);
 static struct cflayer *get_up(struct cfmuxl *muxl, u16 id);
 
 struct cflayer *cfmuxl_create(void)
@@ -244,7 +244,7 @@ static int cfmuxl_transmit(struct cflayer *layr, struct cfpkt *pkt)
 }
 
 static void cfmuxl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
-				int phyid)
+			   int phyid)
 {
 	struct cfmuxl *muxl = container_obj(layr);
 	struct cflayer *layer;
diff --git a/net/caif/cfpkt_skbuff.c b/net/caif/cfpkt_skbuff.c
index 863dedd..e8f9c14 100644
--- a/net/caif/cfpkt_skbuff.c
+++ b/net/caif/cfpkt_skbuff.c
@@ -266,8 +266,8 @@ inline u16 cfpkt_getlen(struct cfpkt *pkt)
 }
 
 inline u16 cfpkt_iterate(struct cfpkt *pkt,
-			    u16 (*iter_func)(u16, void *, u16),
-			    u16 data)
+			 u16 (*iter_func)(u16, void *, u16),
+			 u16 data)
 {
 	/*
 	 * Don't care about the performance hit of linearizing,
@@ -307,8 +307,8 @@ int cfpkt_setlen(struct cfpkt *pkt, u16 len)
 }
 
 struct cfpkt *cfpkt_append(struct cfpkt *dstpkt,
-			     struct cfpkt *addpkt,
-			     u16 expectlen)
+			   struct cfpkt *addpkt,
+			   u16 expectlen)
 {
 	struct sk_buff *dst = pkt_to_skb(dstpkt);
 	struct sk_buff *add = pkt_to_skb(addpkt);
diff --git a/net/caif/cfrfml.c b/net/caif/cfrfml.c
index 2b563ad..db51830 100644
--- a/net/caif/cfrfml.c
+++ b/net/caif/cfrfml.c
@@ -43,7 +43,7 @@ static void cfrfml_release(struct cflayer *layer)
 }
 
 struct cflayer *cfrfml_create(u8 channel_id, struct dev_info *dev_info,
-					int mtu_size)
+			      int mtu_size)
 {
 	int tmp;
 	struct cfrfml *this = kzalloc(sizeof(struct cfrfml), GFP_ATOMIC);
@@ -69,7 +69,7 @@ struct cflayer *cfrfml_create(u8 channel_id, struct dev_info *dev_info,
 }
 
 static struct cfpkt *rfm_append(struct cfrfml *rfml, char *seghead,
-			struct cfpkt *pkt, int *err)
+				struct cfpkt *pkt, int *err)
 {
 	struct cfpkt *tmppkt;
 	*err = -EPROTO;
diff --git a/net/caif/cfserl.c b/net/caif/cfserl.c
index 8e68b97..147c232 100644
--- a/net/caif/cfserl.c
+++ b/net/caif/cfserl.c
@@ -29,7 +29,7 @@ struct cfserl {
 static int cfserl_receive(struct cflayer *layr, struct cfpkt *pkt);
 static int cfserl_transmit(struct cflayer *layr, struct cfpkt *pkt);
 static void cfserl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
-				int phyid);
+			   int phyid);
 
 struct cflayer *cfserl_create(int instance, bool use_stx)
 {
@@ -182,7 +182,7 @@ static int cfserl_transmit(struct cflayer *layer, struct cfpkt *newpkt)
 }
 
 static void cfserl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
-				int phyid)
+			   int phyid)
 {
 	layr->up->ctrlcmd(layr->up, ctrl, phyid);
 }
diff --git a/net/caif/cfsrvl.c b/net/caif/cfsrvl.c
index ba217e9..95f7f5e 100644
--- a/net/caif/cfsrvl.c
+++ b/net/caif/cfsrvl.c
@@ -25,7 +25,7 @@
 #define container_obj(layr) container_of(layr, struct cfsrvl, layer)
 
 static void cfservl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
-				int phyid)
+			    int phyid)
 {
 	struct cfsrvl *service = container_obj(layr);
 
@@ -158,10 +158,9 @@ static void cfsrvl_release(struct cflayer *layer)
 }
 
 void cfsrvl_init(struct cfsrvl *service,
-			u8 channel_id,
-			struct dev_info *dev_info,
-			bool supports_flowctrl
-			)
+		 u8 channel_id,
+		 struct dev_info *dev_info,
+		 bool supports_flowctrl)
 {
 	caif_assert(offsetof(struct cfsrvl, layer) == 0);
 	service->open = false;
@@ -207,8 +206,8 @@ void caif_free_client(struct cflayer *adap_layer)
 EXPORT_SYMBOL(caif_free_client);
 
 void caif_client_register_refcnt(struct cflayer *adapt_layer,
-					void (*hold)(struct cflayer *lyr),
-					void (*put)(struct cflayer *lyr))
+				 void (*hold)(struct cflayer *lyr),
+				 void (*put)(struct cflayer *lyr))
 {
 	struct cfsrvl *service;
 
diff --git a/net/caif/chnl_net.c b/net/caif/chnl_net.c
index e597733..26a4e4e 100644
--- a/net/caif/chnl_net.c
+++ b/net/caif/chnl_net.c
@@ -167,7 +167,7 @@ static void chnl_put(struct cflayer *lyr)
 }
 
 static void chnl_flowctrl_cb(struct cflayer *layr, enum caif_ctrlcmd flow,
-				int phyid)
+			     int phyid)
 {
 	struct chnl_net *priv = container_of(layr, struct chnl_net, chnl);
 	pr_debug("NET flowctrl func called flow: %s\n",
@@ -443,7 +443,7 @@ nla_put_failure:
 }
 
 static void caif_netlink_parms(struct nlattr *data[],
-				struct caif_connect_request *conn_req)
+			       struct caif_connect_request *conn_req)
 {
 	if (!data) {
 		pr_warn("no params data found\n");
@@ -488,7 +488,7 @@ static int ipcaif_newlink(struct net *src_net, struct net_device *dev,
 }
 
 static int ipcaif_changelink(struct net_device *dev, struct nlattr *tb[],
-				struct nlattr *data[])
+			     struct nlattr *data[])
 {
 	struct chnl_net *caifdev;
 	ASSERT_RTNL();
diff --git a/net/can/af_can.c b/net/can/af_can.c
index c48e522..c4e5085 100644
--- a/net/can/af_can.c
+++ b/net/can/af_can.c
@@ -525,7 +525,7 @@ void can_rx_unregister(struct net_device *dev, canid_t can_id, canid_t mask,
 
 	d = find_dev_rcv_lists(dev);
 	if (!d) {
-		printk(KERN_ERR "BUG: receive list not found for "
+		pr_err("BUG: receive list not found for "
 		       "dev %s, id %03X, mask %03X\n",
 		       DNAME(dev), can_id, mask);
 		goto out;
@@ -546,16 +546,13 @@ void can_rx_unregister(struct net_device *dev, canid_t can_id, canid_t mask,
 	}
 
 	/*
-	 * Check for bugs in CAN protocol implementations:
-	 * If no matching list item was found, the list cursor variable next
-	 * will be NULL, while r will point to the last item of the list.
+	 * Check for bugs in CAN protocol implementations using af_can.c:
+	 * 'r' will be NULL if no matching list item was found for removal.
 	 */
 
 	if (!r) {
-		printk(KERN_ERR "BUG: receive list entry not found for "
-		       "dev %s, id %03X, mask %03X\n",
-		       DNAME(dev), can_id, mask);
-		r = NULL;
+		WARN(1, "BUG: receive list entry not found for dev %s, "
+		     "id %03X, mask %03X\n", DNAME(dev), can_id, mask);
 		goto out;
 	}
 
@@ -749,8 +746,7 @@ int can_proto_register(const struct can_proto *cp)
 	int err = 0;
 
 	if (proto < 0 || proto >= CAN_NPROTO) {
-		printk(KERN_ERR "can: protocol number %d out of range\n",
-		       proto);
+		pr_err("can: protocol number %d out of range\n", proto);
 		return -EINVAL;
 	}
 
@@ -761,8 +757,7 @@ int can_proto_register(const struct can_proto *cp)
 	mutex_lock(&proto_tab_lock);
 
 	if (proto_tab[proto]) {
-		printk(KERN_ERR "can: protocol %d already registered\n",
-		       proto);
+		pr_err("can: protocol %d already registered\n", proto);
 		err = -EBUSY;
 	} else
 		RCU_INIT_POINTER(proto_tab[proto], cp);
@@ -816,11 +811,8 @@ static int can_notifier(struct notifier_block *nb, unsigned long msg,
 
 		/* create new dev_rcv_lists for this device */
 		d = kzalloc(sizeof(*d), GFP_KERNEL);
-		if (!d) {
-			printk(KERN_ERR
-			       "can: allocation of receive list failed\n");
+		if (!d)
 			return NOTIFY_DONE;
-		}
 		BUG_ON(dev->ml_priv);
 		dev->ml_priv = d;
 
@@ -838,8 +830,8 @@ static int can_notifier(struct notifier_block *nb, unsigned long msg,
 				dev->ml_priv = NULL;
 			}
 		} else
-			printk(KERN_ERR "can: notifier: receive list not "
-			       "found for dev %s\n", dev->name);
+			pr_err("can: notifier: receive list not found for dev "
+			       "%s\n", dev->name);
 
 		spin_unlock(&can_rcvlists_lock);
 
@@ -927,7 +919,7 @@ static __exit void can_exit(void)
 	/* remove created dev_rcv_lists from still registered CAN devices */
 	rcu_read_lock();
 	for_each_netdev_rcu(&init_net, dev) {
-		if (dev->type == ARPHRD_CAN && dev->ml_priv){
+		if (dev->type == ARPHRD_CAN && dev->ml_priv) {
 
 			struct dev_rcv_lists *d = dev->ml_priv;
 
diff --git a/net/can/bcm.c b/net/can/bcm.c
index 5dcb200..8f113e6 100644
--- a/net/can/bcm.c
+++ b/net/can/bcm.c
@@ -226,7 +226,7 @@ static int bcm_proc_show(struct seq_file *m, void *v)
 
 static int bcm_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, bcm_proc_show, PDE(inode)->data);
+	return single_open(file, bcm_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations bcm_proc_fops = {
diff --git a/net/can/gw.c b/net/can/gw.c
index 2d117dc..2dc619d 100644
--- a/net/can/gw.c
+++ b/net/can/gw.c
@@ -778,8 +778,7 @@ static int cgw_parse_attr(struct nlmsghdr *nlh, struct cf_mod *mod,
 	return 0;
 }
 
-static int cgw_create_job(struct sk_buff *skb,  struct nlmsghdr *nlh,
-			  void *arg)
+static int cgw_create_job(struct sk_buff *skb,  struct nlmsghdr *nlh)
 {
 	struct rtcanmsg *r;
 	struct cgw_job *gwj;
@@ -868,7 +867,7 @@ static void cgw_remove_all_jobs(void)
 	}
 }
 
-static int cgw_remove_job(struct sk_buff *skb,  struct nlmsghdr *nlh, void *arg)
+static int cgw_remove_job(struct sk_buff *skb,  struct nlmsghdr *nlh)
 {
 	struct cgw_job *gwj = NULL;
 	struct hlist_node *nx;
diff --git a/net/can/proc.c b/net/can/proc.c
index 1ab8c88..b543470 100644
--- a/net/can/proc.c
+++ b/net/can/proc.c
@@ -378,7 +378,7 @@ static int can_rcvlist_proc_show(struct seq_file *m, void *v)
 
 static int can_rcvlist_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, can_rcvlist_proc_show, PDE(inode)->data);
+	return single_open(file, can_rcvlist_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations can_rcvlist_proc_fops = {
diff --git a/net/core/datagram.c b/net/core/datagram.c
index 368f9c3..ebba65d 100644
--- a/net/core/datagram.c
+++ b/net/core/datagram.c
@@ -749,7 +749,9 @@ unsigned int datagram_poll(struct file *file, struct socket *sock,
 
 	/* exceptional events? */
 	if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
-		mask |= POLLERR;
+		mask |= POLLERR |
+			(sock_flag(sk, SOCK_SELECT_ERR_QUEUE) ? POLLPRI : 0);
+
 	if (sk->sk_shutdown & RCV_SHUTDOWN)
 		mask |= POLLRDHUP | POLLIN | POLLRDNORM;
 	if (sk->sk_shutdown == SHUTDOWN_MASK)
diff --git a/net/core/dev.c b/net/core/dev.c
index b13e5c7..63e2533 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1624,7 +1624,6 @@ int dev_forward_skb(struct net_device *dev, struct sk_buff *skb)
 	}
 
 	skb_orphan(skb);
-	nf_reset(skb);
 
 	if (unlikely(!is_skb_forwardable(dev, skb))) {
 		atomic_long_inc(&dev->rx_dropped);
@@ -2207,16 +2206,8 @@ out:
 }
 EXPORT_SYMBOL(skb_checksum_help);
 
-/**
- *	skb_mac_gso_segment - mac layer segmentation handler.
- *	@skb: buffer to segment
- *	@features: features for the output path (see dev->features)
- */
-struct sk_buff *skb_mac_gso_segment(struct sk_buff *skb,
-				    netdev_features_t features)
+__be16 skb_network_protocol(struct sk_buff *skb)
 {
-	struct sk_buff *segs = ERR_PTR(-EPROTONOSUPPORT);
-	struct packet_offload *ptype;
 	__be16 type = skb->protocol;
 	int vlan_depth = ETH_HLEN;
 
@@ -2224,13 +2215,31 @@ struct sk_buff *skb_mac_gso_segment(struct sk_buff *skb,
 		struct vlan_hdr *vh;
 
 		if (unlikely(!pskb_may_pull(skb, vlan_depth + VLAN_HLEN)))
-			return ERR_PTR(-EINVAL);
+			return 0;
 
 		vh = (struct vlan_hdr *)(skb->data + vlan_depth);
 		type = vh->h_vlan_encapsulated_proto;
 		vlan_depth += VLAN_HLEN;
 	}
 
+	return type;
+}
+
+/**
+ *	skb_mac_gso_segment - mac layer segmentation handler.
+ *	@skb: buffer to segment
+ *	@features: features for the output path (see dev->features)
+ */
+struct sk_buff *skb_mac_gso_segment(struct sk_buff *skb,
+				    netdev_features_t features)
+{
+	struct sk_buff *segs = ERR_PTR(-EPROTONOSUPPORT);
+	struct packet_offload *ptype;
+	__be16 type = skb_network_protocol(skb);
+
+	if (unlikely(!type))
+		return ERR_PTR(-EINVAL);
+
 	__skb_pull(skb, skb->mac_len);
 
 	rcu_read_lock();
@@ -2397,24 +2406,12 @@ static int dev_gso_segment(struct sk_buff *skb, netdev_features_t features)
 	return 0;
 }
 
-static bool can_checksum_protocol(netdev_features_t features, __be16 protocol)
-{
-	return ((features & NETIF_F_GEN_CSUM) ||
-		((features & NETIF_F_V4_CSUM) &&
-		 protocol == htons(ETH_P_IP)) ||
-		((features & NETIF_F_V6_CSUM) &&
-		 protocol == htons(ETH_P_IPV6)) ||
-		((features & NETIF_F_FCOE_CRC) &&
-		 protocol == htons(ETH_P_FCOE)));
-}
-
 static netdev_features_t harmonize_features(struct sk_buff *skb,
 	__be16 protocol, netdev_features_t features)
 {
 	if (skb->ip_summed != CHECKSUM_NONE &&
 	    !can_checksum_protocol(features, protocol)) {
 		features &= ~NETIF_F_ALL_CSUM;
-		features &= ~NETIF_F_SG;
 	} else if (illegal_highdma(skb->dev, skb)) {
 		features &= ~NETIF_F_SG;
 	}
@@ -2589,6 +2586,7 @@ static void qdisc_pkt_len_init(struct sk_buff *skb)
 	 */
 	if (shinfo->gso_size)  {
 		unsigned int hdr_len;
+		u16 gso_segs = shinfo->gso_segs;
 
 		/* mac layer + network layer */
 		hdr_len = skb_transport_header(skb) - skb_mac_header(skb);
@@ -2598,7 +2596,12 @@ static void qdisc_pkt_len_init(struct sk_buff *skb)
 			hdr_len += tcp_hdrlen(skb);
 		else
 			hdr_len += sizeof(struct udphdr);
-		qdisc_skb_cb(skb)->pkt_len += (shinfo->gso_segs - 1) * hdr_len;
+
+		if (shinfo->gso_type & SKB_GSO_DODGY)
+			gso_segs = DIV_ROUND_UP(skb->len - hdr_len,
+						shinfo->gso_size);
+
+		qdisc_skb_cb(skb)->pkt_len += (gso_segs - 1) * hdr_len;
 	}
 }
 
@@ -3314,6 +3317,7 @@ int netdev_rx_handler_register(struct net_device *dev,
 	if (dev->rx_handler)
 		return -EBUSY;
 
+	/* Note: rx_handler_data must be set before rx_handler */
 	rcu_assign_pointer(dev->rx_handler_data, rx_handler_data);
 	rcu_assign_pointer(dev->rx_handler, rx_handler);
 
@@ -3325,7 +3329,7 @@ EXPORT_SYMBOL_GPL(netdev_rx_handler_register);
  *	netdev_rx_handler_unregister - unregister receive handler
  *	@dev: device to unregister a handler from
  *
- *	Unregister a receive hander from a device.
+ *	Unregister a receive handler from a device.
  *
  *	The caller must hold the rtnl_mutex.
  */
@@ -3334,6 +3338,11 @@ void netdev_rx_handler_unregister(struct net_device *dev)
 
 	ASSERT_RTNL();
 	RCU_INIT_POINTER(dev->rx_handler, NULL);
+	/* a reader seeing a non NULL rx_handler in a rcu_read_lock()
+	 * section has a guarantee to see a non NULL rx_handler_data
+	 * as well.
+	 */
+	synchronize_net();
 	RCU_INIT_POINTER(dev->rx_handler_data, NULL);
 }
 EXPORT_SYMBOL_GPL(netdev_rx_handler_unregister);
@@ -4057,6 +4066,9 @@ void netif_napi_add(struct net_device *dev, struct napi_struct *napi,
 	napi->gro_list = NULL;
 	napi->skb = NULL;
 	napi->poll = poll;
+	if (weight > NAPI_POLL_WEIGHT)
+		pr_err_once("netif_napi_add() called with weight %d on device %s\n",
+			    weight, dev->name);
 	napi->weight = weight;
 	list_add(&napi->dev_list, &dev->napi_list);
 	napi->dev = dev;
@@ -4918,20 +4930,25 @@ static netdev_features_t netdev_fix_features(struct net_device *dev,
 		features &= ~(NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM);
 	}
 
-	/* Fix illegal SG+CSUM combinations. */
-	if ((features & NETIF_F_SG) &&
-	    !(features & NETIF_F_ALL_CSUM)) {
-		netdev_dbg(dev,
-			"Dropping NETIF_F_SG since no checksum feature.\n");
-		features &= ~NETIF_F_SG;
-	}
-
 	/* TSO requires that SG is present as well. */
 	if ((features & NETIF_F_ALL_TSO) && !(features & NETIF_F_SG)) {
 		netdev_dbg(dev, "Dropping TSO features since no SG feature.\n");
 		features &= ~NETIF_F_ALL_TSO;
 	}
 
+	if ((features & NETIF_F_TSO) && !(features & NETIF_F_HW_CSUM) &&
+					!(features & NETIF_F_IP_CSUM)) {
+		netdev_dbg(dev, "Dropping TSO features since no CSUM feature.\n");
+		features &= ~NETIF_F_TSO;
+		features &= ~NETIF_F_TSO_ECN;
+	}
+
+	if ((features & NETIF_F_TSO6) && !(features & NETIF_F_HW_CSUM) &&
+					 !(features & NETIF_F_IPV6_CSUM)) {
+		netdev_dbg(dev, "Dropping TSO6 features since no CSUM feature.\n");
+		features &= ~NETIF_F_TSO6;
+	}
+
 	/* TSO ECN requires that TSO is present as well. */
 	if ((features & NETIF_F_ALL_TSO) == NETIF_F_TSO_ECN)
 		features &= ~NETIF_F_TSO_ECN;
@@ -5199,6 +5216,10 @@ int register_netdevice(struct net_device *dev)
 	 */
 	dev->vlan_features |= NETIF_F_HIGHDMA;
 
+	/* Make NETIF_F_SG inheritable to tunnel devices.
+	 */
+	dev->hw_enc_features |= NETIF_F_SG;
+
 	ret = call_netdevice_notifiers(NETDEV_POST_INIT, dev);
 	ret = notifier_to_errno(ret);
 	if (ret)
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 3e9b2c3..adc1351 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -78,6 +78,7 @@ static const char netdev_features_strings[NETDEV_FEATURE_COUNT][ETH_GSTRING_LEN]
 	[NETIF_F_TSO6_BIT] =             "tx-tcp6-segmentation",
 	[NETIF_F_FSO_BIT] =              "tx-fcoe-segmentation",
 	[NETIF_F_GSO_GRE_BIT] =		 "tx-gre-segmentation",
+	[NETIF_F_GSO_UDP_TUNNEL_BIT] =	 "tx-udp_tnl-segmentation",
 
 	[NETIF_F_FCOE_CRC_BIT] =         "tx-checksum-fcoe-crc",
 	[NETIF_F_SCTP_CSUM_BIT] =        "tx-checksum-sctp",
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c
index 58a4ba2..d5a9f8e 100644
--- a/net/core/fib_rules.c
+++ b/net/core/fib_rules.c
@@ -266,7 +266,7 @@ errout:
 	return err;
 }
 
-static int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
+static int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh)
 {
 	struct net *net = sock_net(skb->sk);
 	struct fib_rule_hdr *frh = nlmsg_data(nlh);
@@ -415,7 +415,7 @@ errout:
 	return err;
 }
 
-static int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
+static int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh)
 {
 	struct net *net = sock_net(skb->sk);
 	struct fib_rule_hdr *frh = nlmsg_data(nlh);
diff --git a/net/core/filter.c b/net/core/filter.c
index 2e20b55..dad2a17 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -348,6 +348,9 @@ load_b:
 		case BPF_S_ANC_VLAN_TAG_PRESENT:
 			A = !!vlan_tx_tag_present(skb);
 			continue;
+		case BPF_S_ANC_PAY_OFFSET:
+			A = __skb_get_poff(skb);
+			continue;
 		case BPF_S_ANC_NLATTR: {
 			struct nlattr *nla;
 
@@ -612,6 +615,7 @@ int sk_chk_filter(struct sock_filter *filter, unsigned int flen)
 			ANCILLARY(ALU_XOR_X);
 			ANCILLARY(VLAN_TAG);
 			ANCILLARY(VLAN_TAG_PRESENT);
+			ANCILLARY(PAY_OFFSET);
 			}
 
 			/* ancillary operation unknown or unsupported */
@@ -814,6 +818,7 @@ static void sk_decode_filter(struct sock_filter *filt, struct sock_filter *to)
 		[BPF_S_ANC_SECCOMP_LD_W] = BPF_LD|BPF_B|BPF_ABS,
 		[BPF_S_ANC_VLAN_TAG]	= BPF_LD|BPF_B|BPF_ABS,
 		[BPF_S_ANC_VLAN_TAG_PRESENT] = BPF_LD|BPF_B|BPF_ABS,
+		[BPF_S_ANC_PAY_OFFSET]	= BPF_LD|BPF_B|BPF_ABS,
 		[BPF_S_LD_W_LEN]	= BPF_LD|BPF_W|BPF_LEN,
 		[BPF_S_LD_W_IND]	= BPF_LD|BPF_W|BPF_IND,
 		[BPF_S_LD_H_IND]	= BPF_LD|BPF_H|BPF_IND,
diff --git a/net/core/flow.c b/net/core/flow.c
index c56ea6f..7102f16 100644
--- a/net/core/flow.c
+++ b/net/core/flow.c
@@ -323,12 +323,30 @@ static void flow_cache_flush_tasklet(unsigned long data)
 		complete(&info->completion);
 }
 
+/*
+ * Return whether a cpu needs flushing.  Conservatively, we assume
+ * the presence of any entries means the core may require flushing,
+ * since the flow_cache_ops.check() function may assume it's running
+ * on the same core as the per-cpu cache component.
+ */
+static int flow_cache_percpu_empty(struct flow_cache *fc, int cpu)
+{
+	struct flow_cache_percpu *fcp;
+	int i;
+
+	fcp = per_cpu_ptr(fc->percpu, cpu);
+	for (i = 0; i < flow_cache_hash_size(fc); i++)
+		if (!hlist_empty(&fcp->hash_table[i]))
+			return 0;
+	return 1;
+}
+
 static void flow_cache_flush_per_cpu(void *data)
 {
 	struct flow_flush_info *info = data;
 	struct tasklet_struct *tasklet;
 
-	tasklet = this_cpu_ptr(&info->cache->percpu->flush_tasklet);
+	tasklet = &this_cpu_ptr(info->cache->percpu)->flush_tasklet;
 	tasklet->data = (unsigned long)info;
 	tasklet_schedule(tasklet);
 }
@@ -337,22 +355,40 @@ void flow_cache_flush(void)
 {
 	struct flow_flush_info info;
 	static DEFINE_MUTEX(flow_flush_sem);
+	cpumask_var_t mask;
+	int i, self;
+
+	/* Track which cpus need flushing to avoid disturbing all cores. */
+	if (!alloc_cpumask_var(&mask, GFP_KERNEL))
+		return;
+	cpumask_clear(mask);
 
 	/* Don't want cpus going down or up during this. */
 	get_online_cpus();
 	mutex_lock(&flow_flush_sem);
 	info.cache = &flow_cache_global;
-	atomic_set(&info.cpuleft, num_online_cpus());
+	for_each_online_cpu(i)
+		if (!flow_cache_percpu_empty(info.cache, i))
+			cpumask_set_cpu(i, mask);
+	atomic_set(&info.cpuleft, cpumask_weight(mask));
+	if (atomic_read(&info.cpuleft) == 0)
+		goto done;
+
 	init_completion(&info.completion);
 
 	local_bh_disable();
-	smp_call_function(flow_cache_flush_per_cpu, &info, 0);
-	flow_cache_flush_tasklet((unsigned long)&info);
+	self = cpumask_test_and_clear_cpu(smp_processor_id(), mask);
+	on_each_cpu_mask(mask, flow_cache_flush_per_cpu, &info, 0);
+	if (self)
+		flow_cache_flush_tasklet((unsigned long)&info);
 	local_bh_enable();
 
 	wait_for_completion(&info.completion);
+
+done:
 	mutex_unlock(&flow_flush_sem);
 	put_online_cpus();
+	free_cpumask_var(mask);
 }
 
 static void flow_cache_flush_task(struct work_struct *work)
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index e187bf0..00ee068 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -5,6 +5,10 @@
 #include <linux/if_vlan.h>
 #include <net/ip.h>
 #include <net/ipv6.h>
+#include <linux/igmp.h>
+#include <linux/icmp.h>
+#include <linux/sctp.h>
+#include <linux/dccp.h>
 #include <linux/if_tunnel.h>
 #include <linux/if_pppox.h>
 #include <linux/ppp_defs.h>
@@ -119,6 +123,17 @@ ipv6:
 				nhoff += 4;
 			if (hdr->flags & GRE_SEQ)
 				nhoff += 4;
+			if (proto == htons(ETH_P_TEB)) {
+				const struct ethhdr *eth;
+				struct ethhdr _eth;
+
+				eth = skb_header_pointer(skb, nhoff,
+							 sizeof(_eth), &_eth);
+				if (!eth)
+					return false;
+				proto = eth->h_proto;
+				nhoff += sizeof(*eth);
+			}
 			goto again;
 		}
 		break;
@@ -217,6 +232,59 @@ u16 __skb_tx_hash(const struct net_device *dev, const struct sk_buff *skb,
 }
 EXPORT_SYMBOL(__skb_tx_hash);
 
+/* __skb_get_poff() returns the offset to the payload as far as it could
+ * be dissected. The main user is currently BPF, so that we can dynamically
+ * truncate packets without needing to push actual payload to the user
+ * space and can analyze headers only, instead.
+ */
+u32 __skb_get_poff(const struct sk_buff *skb)
+{
+	struct flow_keys keys;
+	u32 poff = 0;
+
+	if (!skb_flow_dissect(skb, &keys))
+		return 0;
+
+	poff += keys.thoff;
+	switch (keys.ip_proto) {
+	case IPPROTO_TCP: {
+		const struct tcphdr *tcph;
+		struct tcphdr _tcph;
+
+		tcph = skb_header_pointer(skb, poff, sizeof(_tcph), &_tcph);
+		if (!tcph)
+			return poff;
+
+		poff += max_t(u32, sizeof(struct tcphdr), tcph->doff * 4);
+		break;
+	}
+	case IPPROTO_UDP:
+	case IPPROTO_UDPLITE:
+		poff += sizeof(struct udphdr);
+		break;
+	/* For the rest, we do not really care about header
+	 * extensions at this point for now.
+	 */
+	case IPPROTO_ICMP:
+		poff += sizeof(struct icmphdr);
+		break;
+	case IPPROTO_ICMPV6:
+		poff += sizeof(struct icmp6hdr);
+		break;
+	case IPPROTO_IGMP:
+		poff += sizeof(struct igmphdr);
+		break;
+	case IPPROTO_DCCP:
+		poff += sizeof(struct dccp_hdr);
+		break;
+	case IPPROTO_SCTP:
+		poff += sizeof(struct sctphdr);
+		break;
+	}
+
+	return poff;
+}
+
 static inline u16 dev_cap_txqueue(struct net_device *dev, u16 queue_index)
 {
 	if (unlikely(queue_index >= dev->real_num_tx_queues)) {
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 3863b8f..c00a80d8 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -1613,7 +1613,7 @@ int neigh_table_clear(struct neigh_table *tbl)
 }
 EXPORT_SYMBOL(neigh_table_clear);
 
-static int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+static int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh)
 {
 	struct net *net = sock_net(skb->sk);
 	struct ndmsg *ndm;
@@ -1677,7 +1677,7 @@ out:
 	return err;
 }
 
-static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh)
 {
 	struct net *net = sock_net(skb->sk);
 	struct ndmsg *ndm;
@@ -1955,7 +1955,7 @@ static const struct nla_policy nl_ntbl_parm_policy[NDTPA_MAX+1] = {
 	[NDTPA_LOCKTIME]		= { .type = NLA_U64 },
 };
 
-static int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+static int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh)
 {
 	struct net *net = sock_net(skb->sk);
 	struct neigh_table *tbl;
@@ -2714,7 +2714,7 @@ static int neigh_stat_seq_open(struct inode *inode, struct file *file)
 
 	if (!ret) {
 		struct seq_file *sf = file->private_data;
-		sf->private = PDE(inode)->data;
+		sf->private = PDE_DATA(inode);
 	}
 	return ret;
 };
diff --git a/net/core/net-procfs.c b/net/core/net-procfs.c
index 3174f19..569d355 100644
--- a/net/core/net-procfs.c
+++ b/net/core/net-procfs.c
@@ -271,7 +271,7 @@ static int ptype_seq_show(struct seq_file *seq, void *v)
 		else
 			seq_printf(seq, "%04x", ntohs(pt->type));
 
-		seq_printf(seq, " %-8s %pF\n",
+		seq_printf(seq, " %-8s %pf\n",
 			   pt->dev ? pt->dev->name : "", pt->func);
 	}
 
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index fa32899..a3a17ae 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -47,7 +47,7 @@ static struct sk_buff_head skb_pool;
 
 static atomic_t trapped;
 
-static struct srcu_struct netpoll_srcu;
+DEFINE_STATIC_SRCU(netpoll_srcu);
 
 #define USEC_PER_POLL	50
 #define NETPOLL_RX_ENABLED  1
@@ -1212,7 +1212,6 @@ EXPORT_SYMBOL(netpoll_setup);
 static int __init netpoll_init(void)
 {
 	skb_queue_head_init(&skb_pool);
-	init_srcu_struct(&netpoll_srcu);
 	return 0;
 }
 core_initcall(netpoll_init);
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 6048fc1..5bab100 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -508,7 +508,7 @@ out:
 
 static int pgctrl_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, pgctrl_show, PDE(inode)->data);
+	return single_open(file, pgctrl_show, PDE_DATA(inode));
 }
 
 static const struct file_operations pktgen_fops = {
@@ -1685,7 +1685,7 @@ static ssize_t pktgen_if_write(struct file *file,
 
 static int pktgen_if_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, pktgen_if_show, PDE(inode)->data);
+	return single_open(file, pktgen_if_show, PDE_DATA(inode));
 }
 
 static const struct file_operations pktgen_if_fops = {
@@ -1823,7 +1823,7 @@ out:
 
 static int pktgen_thread_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, pktgen_thread_show, PDE(inode)->data);
+	return single_open(file, pktgen_thread_show, PDE_DATA(inode));
 }
 
 static const struct file_operations pktgen_thread_fops = {
@@ -2198,7 +2198,7 @@ static inline int f_pick(struct pktgen_dev *pkt_dev)
 				pkt_dev->curfl = 0; /*reset */
 		}
 	} else {
-		flow = random32() % pkt_dev->cflows;
+		flow = prandom_u32() % pkt_dev->cflows;
 		pkt_dev->curfl = flow;
 
 		if (pkt_dev->flows[flow].count > pkt_dev->lflow) {
@@ -2246,7 +2246,7 @@ static void set_cur_queue_map(struct pktgen_dev *pkt_dev)
 	else if (pkt_dev->queue_map_min <= pkt_dev->queue_map_max) {
 		__u16 t;
 		if (pkt_dev->flags & F_QUEUE_MAP_RND) {
-			t = random32() %
+			t = prandom_u32() %
 				(pkt_dev->queue_map_max -
 				 pkt_dev->queue_map_min + 1)
 				+ pkt_dev->queue_map_min;
@@ -2278,7 +2278,7 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev)
 		__u32 tmp;
 
 		if (pkt_dev->flags & F_MACSRC_RND)
-			mc = random32() % pkt_dev->src_mac_count;
+			mc = prandom_u32() % pkt_dev->src_mac_count;
 		else {
 			mc = pkt_dev->cur_src_mac_offset++;
 			if (pkt_dev->cur_src_mac_offset >=
@@ -2304,7 +2304,7 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev)
 		__u32 tmp;
 
 		if (pkt_dev->flags & F_MACDST_RND)
-			mc = random32() % pkt_dev->dst_mac_count;
+			mc = prandom_u32() % pkt_dev->dst_mac_count;
 
 		else {
 			mc = pkt_dev->cur_dst_mac_offset++;
@@ -2331,21 +2331,21 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev)
 		for (i = 0; i < pkt_dev->nr_labels; i++)
 			if (pkt_dev->labels[i] & MPLS_STACK_BOTTOM)
 				pkt_dev->labels[i] = MPLS_STACK_BOTTOM |
-					     ((__force __be32)random32() &
+					     ((__force __be32)prandom_u32() &
 						      htonl(0x000fffff));
 	}
 
 	if ((pkt_dev->flags & F_VID_RND) && (pkt_dev->vlan_id != 0xffff)) {
-		pkt_dev->vlan_id = random32() & (4096-1);
+		pkt_dev->vlan_id = prandom_u32() & (4096 - 1);
 	}
 
 	if ((pkt_dev->flags & F_SVID_RND) && (pkt_dev->svlan_id != 0xffff)) {
-		pkt_dev->svlan_id = random32() & (4096 - 1);
+		pkt_dev->svlan_id = prandom_u32() & (4096 - 1);
 	}
 
 	if (pkt_dev->udp_src_min < pkt_dev->udp_src_max) {
 		if (pkt_dev->flags & F_UDPSRC_RND)
-			pkt_dev->cur_udp_src = random32() %
+			pkt_dev->cur_udp_src = prandom_u32() %
 				(pkt_dev->udp_src_max - pkt_dev->udp_src_min)
 				+ pkt_dev->udp_src_min;
 
@@ -2358,7 +2358,7 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev)
 
 	if (pkt_dev->udp_dst_min < pkt_dev->udp_dst_max) {
 		if (pkt_dev->flags & F_UDPDST_RND) {
-			pkt_dev->cur_udp_dst = random32() %
+			pkt_dev->cur_udp_dst = prandom_u32() %
 				(pkt_dev->udp_dst_max - pkt_dev->udp_dst_min)
 				+ pkt_dev->udp_dst_min;
 		} else {
@@ -2375,7 +2375,7 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev)
 		if (imn < imx) {
 			__u32 t;
 			if (pkt_dev->flags & F_IPSRC_RND)
-				t = random32() % (imx - imn) + imn;
+				t = prandom_u32() % (imx - imn) + imn;
 			else {
 				t = ntohl(pkt_dev->cur_saddr);
 				t++;
@@ -2396,17 +2396,15 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev)
 				__be32 s;
 				if (pkt_dev->flags & F_IPDST_RND) {
 
-					t = random32() % (imx - imn) + imn;
-					s = htonl(t);
-
-					while (ipv4_is_loopback(s) ||
-					       ipv4_is_multicast(s) ||
-					       ipv4_is_lbcast(s) ||
-					       ipv4_is_zeronet(s) ||
-					       ipv4_is_local_multicast(s)) {
-						t = random32() % (imx - imn) + imn;
+					do {
+						t = prandom_u32() %
+							(imx - imn) + imn;
 						s = htonl(t);
-					}
+					} while (ipv4_is_loopback(s) ||
+						ipv4_is_multicast(s) ||
+						ipv4_is_lbcast(s) ||
+						ipv4_is_zeronet(s) ||
+						ipv4_is_local_multicast(s));
 					pkt_dev->cur_daddr = s;
 				} else {
 					t = ntohl(pkt_dev->cur_daddr);
@@ -2437,7 +2435,7 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev)
 
 			for (i = 0; i < 4; i++) {
 				pkt_dev->cur_in6_daddr.s6_addr32[i] =
-				    (((__force __be32)random32() |
+				    (((__force __be32)prandom_u32() |
 				      pkt_dev->min_in6_daddr.s6_addr32[i]) &
 				     pkt_dev->max_in6_daddr.s6_addr32[i]);
 			}
@@ -2447,7 +2445,7 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev)
 	if (pkt_dev->min_pkt_size < pkt_dev->max_pkt_size) {
 		__u32 t;
 		if (pkt_dev->flags & F_TXSIZE_RND) {
-			t = random32() %
+			t = prandom_u32() %
 				(pkt_dev->max_pkt_size - pkt_dev->min_pkt_size)
 				+ pkt_dev->min_pkt_size;
 		} else {
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 5fb8d7e..589d0ab 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -496,8 +496,10 @@ static int rtnl_link_fill(struct sk_buff *skb, const struct net_device *dev)
 	}
 	if (ops->fill_info) {
 		data = nla_nest_start(skb, IFLA_INFO_DATA);
-		if (data == NULL)
+		if (data == NULL) {
+			err = -EMSGSIZE;
 			goto err_cancel_link;
+		}
 		err = ops->fill_info(skb, dev);
 		if (err < 0)
 			goto err_cancel_data;
@@ -515,32 +517,6 @@ out:
 	return err;
 }
 
-static const int rtm_min[RTM_NR_FAMILIES] =
-{
-	[RTM_FAM(RTM_NEWLINK)]      = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
-	[RTM_FAM(RTM_NEWADDR)]      = NLMSG_LENGTH(sizeof(struct ifaddrmsg)),
-	[RTM_FAM(RTM_NEWROUTE)]     = NLMSG_LENGTH(sizeof(struct rtmsg)),
-	[RTM_FAM(RTM_NEWRULE)]      = NLMSG_LENGTH(sizeof(struct fib_rule_hdr)),
-	[RTM_FAM(RTM_NEWQDISC)]     = NLMSG_LENGTH(sizeof(struct tcmsg)),
-	[RTM_FAM(RTM_NEWTCLASS)]    = NLMSG_LENGTH(sizeof(struct tcmsg)),
-	[RTM_FAM(RTM_NEWTFILTER)]   = NLMSG_LENGTH(sizeof(struct tcmsg)),
-	[RTM_FAM(RTM_NEWACTION)]    = NLMSG_LENGTH(sizeof(struct tcamsg)),
-	[RTM_FAM(RTM_GETMULTICAST)] = NLMSG_LENGTH(sizeof(struct rtgenmsg)),
-	[RTM_FAM(RTM_GETANYCAST)]   = NLMSG_LENGTH(sizeof(struct rtgenmsg)),
-};
-
-static const int rta_max[RTM_NR_FAMILIES] =
-{
-	[RTM_FAM(RTM_NEWLINK)]      = IFLA_MAX,
-	[RTM_FAM(RTM_NEWADDR)]      = IFA_MAX,
-	[RTM_FAM(RTM_NEWROUTE)]     = RTA_MAX,
-	[RTM_FAM(RTM_NEWRULE)]      = FRA_MAX,
-	[RTM_FAM(RTM_NEWQDISC)]     = TCA_MAX,
-	[RTM_FAM(RTM_NEWTCLASS)]    = TCA_MAX,
-	[RTM_FAM(RTM_NEWTFILTER)]   = TCA_MAX,
-	[RTM_FAM(RTM_NEWACTION)]    = TCAA_MAX,
-};
-
 int rtnetlink_send(struct sk_buff *skb, struct net *net, u32 pid, unsigned int group, int echo)
 {
 	struct sock *rtnl = net->rtnl;
@@ -1537,7 +1513,7 @@ errout:
 	return err;
 }
 
-static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh)
 {
 	struct net *net = sock_net(skb->sk);
 	struct ifinfomsg *ifm;
@@ -1578,7 +1554,7 @@ errout:
 	return err;
 }
 
-static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh)
 {
 	struct net *net = sock_net(skb->sk);
 	const struct rtnl_link_ops *ops;
@@ -1709,7 +1685,7 @@ static int rtnl_group_changelink(struct net *net, int group,
 	return 0;
 }
 
-static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh)
 {
 	struct net *net = sock_net(skb->sk);
 	const struct rtnl_link_ops *ops;
@@ -1864,7 +1840,7 @@ out:
 	}
 }
 
-static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
+static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh)
 {
 	struct net *net = sock_net(skb->sk);
 	struct ifinfomsg *ifm;
@@ -1955,8 +1931,11 @@ static int rtnl_dump_all(struct sk_buff *skb, struct netlink_callback *cb)
 		if (rtnl_msg_handlers[idx] == NULL ||
 		    rtnl_msg_handlers[idx][type].dumpit == NULL)
 			continue;
-		if (idx > s_idx)
+		if (idx > s_idx) {
 			memset(&cb->args[0], 0, sizeof(cb->args));
+			cb->prev_seq = 0;
+			cb->seq = 0;
+		}
 		if (rtnl_msg_handlers[idx][type].dumpit(skb, cb))
 			break;
 	}
@@ -2049,7 +2028,39 @@ errout:
 	rtnl_set_sk_err(net, RTNLGRP_NEIGH, err);
 }
 
-static int rtnl_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+/**
+ * ndo_dflt_fdb_add - default netdevice operation to add an FDB entry
+ */
+int ndo_dflt_fdb_add(struct ndmsg *ndm,
+		     struct nlattr *tb[],
+		     struct net_device *dev,
+		     const unsigned char *addr,
+		     u16 flags)
+{
+	int err = -EINVAL;
+
+	/* If aging addresses are supported device will need to
+	 * implement its own handler for this.
+	 */
+	if (ndm->ndm_state && !(ndm->ndm_state & NUD_PERMANENT)) {
+		pr_info("%s: FDB only supports static addresses\n", dev->name);
+		return err;
+	}
+
+	if (is_unicast_ether_addr(addr) || is_link_local_ether_addr(addr))
+		err = dev_uc_add_excl(dev, addr);
+	else if (is_multicast_ether_addr(addr))
+		err = dev_mc_add_excl(dev, addr);
+
+	/* Only return duplicate errors if NLM_F_EXCL is set */
+	if (err == -EEXIST && !(flags & NLM_F_EXCL))
+		err = 0;
+
+	return err;
+}
+EXPORT_SYMBOL(ndo_dflt_fdb_add);
+
+static int rtnl_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh)
 {
 	struct net *net = sock_net(skb->sk);
 	struct ndmsg *ndm;
@@ -2080,7 +2091,7 @@ static int rtnl_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 	}
 
 	addr = nla_data(tb[NDA_LLADDR]);
-	if (!is_valid_ether_addr(addr)) {
+	if (is_zero_ether_addr(addr)) {
 		pr_info("PF_BRIDGE: RTM_NEWNEIGH with invalid ether address\n");
 		return -EINVAL;
 	}
@@ -2101,10 +2112,13 @@ static int rtnl_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 	}
 
 	/* Embedded bridge, macvlan, and any other device support */
-	if ((ndm->ndm_flags & NTF_SELF) && dev->netdev_ops->ndo_fdb_add) {
-		err = dev->netdev_ops->ndo_fdb_add(ndm, tb,
-						   dev, addr,
-						   nlh->nlmsg_flags);
+	if ((ndm->ndm_flags & NTF_SELF)) {
+		if (dev->netdev_ops->ndo_fdb_add)
+			err = dev->netdev_ops->ndo_fdb_add(ndm, tb, dev, addr,
+							   nlh->nlmsg_flags);
+		else
+			err = ndo_dflt_fdb_add(ndm, tb, dev, addr,
+					       nlh->nlmsg_flags);
 
 		if (!err) {
 			rtnl_fdb_notify(dev, addr, RTM_NEWNEIGH);
@@ -2115,7 +2129,36 @@ out:
 	return err;
 }
 
-static int rtnl_fdb_del(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+/**
+ * ndo_dflt_fdb_del - default netdevice operation to delete an FDB entry
+ */
+int ndo_dflt_fdb_del(struct ndmsg *ndm,
+		     struct nlattr *tb[],
+		     struct net_device *dev,
+		     const unsigned char *addr)
+{
+	int err = -EOPNOTSUPP;
+
+	/* If aging addresses are supported device will need to
+	 * implement its own handler for this.
+	 */
+	if (ndm->ndm_state & NUD_PERMANENT) {
+		pr_info("%s: FDB only supports static addresses\n", dev->name);
+		return -EINVAL;
+	}
+
+	if (is_unicast_ether_addr(addr) || is_link_local_ether_addr(addr))
+		err = dev_uc_del(dev, addr);
+	else if (is_multicast_ether_addr(addr))
+		err = dev_mc_del(dev, addr);
+	else
+		err = -EINVAL;
+
+	return err;
+}
+EXPORT_SYMBOL(ndo_dflt_fdb_del);
+
+static int rtnl_fdb_del(struct sk_buff *skb, struct nlmsghdr *nlh)
 {
 	struct net *net = sock_net(skb->sk);
 	struct ndmsg *ndm;
@@ -2172,8 +2215,11 @@ static int rtnl_fdb_del(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 	}
 
 	/* Embedded bridge, macvlan, and any other device support */
-	if ((ndm->ndm_flags & NTF_SELF) && dev->netdev_ops->ndo_fdb_del) {
-		err = dev->netdev_ops->ndo_fdb_del(ndm, tb, dev, addr);
+	if (ndm->ndm_flags & NTF_SELF) {
+		if (dev->netdev_ops->ndo_fdb_del)
+			err = dev->netdev_ops->ndo_fdb_del(ndm, tb, dev, addr);
+		else
+			err = ndo_dflt_fdb_del(ndm, tb, dev, addr);
 
 		if (!err) {
 			rtnl_fdb_notify(dev, addr, RTM_DELNEIGH);
@@ -2218,7 +2264,7 @@ skip:
  * @dev: netdevice
  *
  * Default netdevice operation to dump the existing unicast address list.
- * Returns zero on success.
+ * Returns number of addresses from list put in skb.
  */
 int ndo_dflt_fdb_dump(struct sk_buff *skb,
 		      struct netlink_callback *cb,
@@ -2258,6 +2304,8 @@ static int rtnl_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb)
 
 		if (dev->netdev_ops->ndo_fdb_dump)
 			idx = dev->netdev_ops->ndo_fdb_dump(skb, cb, dev, idx);
+		else
+			idx = ndo_dflt_fdb_dump(skb, cb, dev, idx);
 	}
 	rcu_read_unlock();
 
@@ -2409,8 +2457,7 @@ errout:
 	return err;
 }
 
-static int rtnl_bridge_setlink(struct sk_buff *skb, struct nlmsghdr *nlh,
-			       void *arg)
+static int rtnl_bridge_setlink(struct sk_buff *skb, struct nlmsghdr *nlh)
 {
 	struct net *net = sock_net(skb->sk);
 	struct ifinfomsg *ifm;
@@ -2480,8 +2527,7 @@ out:
 	return err;
 }
 
-static int rtnl_bridge_dellink(struct sk_buff *skb, struct nlmsghdr *nlh,
-			       void *arg)
+static int rtnl_bridge_dellink(struct sk_buff *skb, struct nlmsghdr *nlh)
 {
 	struct net *net = sock_net(skb->sk);
 	struct ifinfomsg *ifm;
@@ -2551,10 +2597,6 @@ out:
 	return err;
 }
 
-/* Protected by RTNL sempahore.  */
-static struct rtattr **rta_buf;
-static int rtattr_max;
-
 /* Process one rtnetlink message. */
 
 static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
@@ -2562,7 +2604,6 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 	struct net *net = sock_net(skb->sk);
 	rtnl_doit_func doit;
 	int sz_idx, kind;
-	int min_len;
 	int family;
 	int type;
 	int err;
@@ -2574,10 +2615,10 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 	type -= RTM_BASE;
 
 	/* All the messages must have at least 1 byte length */
-	if (nlh->nlmsg_len < NLMSG_LENGTH(sizeof(struct rtgenmsg)))
+	if (nlmsg_len(nlh) < sizeof(struct rtgenmsg))
 		return 0;
 
-	family = ((struct rtgenmsg *)NLMSG_DATA(nlh))->rtgen_family;
+	family = ((struct rtgenmsg *)nlmsg_data(nlh))->rtgen_family;
 	sz_idx = type>>2;
 	kind = type&3;
 
@@ -2610,32 +2651,11 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 		return err;
 	}
 
-	memset(rta_buf, 0, (rtattr_max * sizeof(struct rtattr *)));
-
-	min_len = rtm_min[sz_idx];
-	if (nlh->nlmsg_len < min_len)
-		return -EINVAL;
-
-	if (nlh->nlmsg_len > min_len) {
-		int attrlen = nlh->nlmsg_len - NLMSG_ALIGN(min_len);
-		struct rtattr *attr = (void *)nlh + NLMSG_ALIGN(min_len);
-
-		while (RTA_OK(attr, attrlen)) {
-			unsigned int flavor = attr->rta_type & NLA_TYPE_MASK;
-			if (flavor) {
-				if (flavor > rta_max[sz_idx])
-					return -EINVAL;
-				rta_buf[flavor-1] = attr;
-			}
-			attr = RTA_NEXT(attr, attrlen);
-		}
-	}
-
 	doit = rtnl_get_doit(family, type);
 	if (doit == NULL)
 		return -EOPNOTSUPP;
 
-	return doit(skb, nlh, (void *)&rta_buf[0]);
+	return doit(skb, nlh);
 }
 
 static void rtnetlink_rcv(struct sk_buff *skb)
@@ -2705,16 +2725,6 @@ static struct pernet_operations rtnetlink_net_ops = {
 
 void __init rtnetlink_init(void)
 {
-	int i;
-
-	rtattr_max = 0;
-	for (i = 0; i < ARRAY_SIZE(rta_max); i++)
-		if (rta_max[i] > rtattr_max)
-			rtattr_max = rta_max[i];
-	rta_buf = kmalloc(rtattr_max * sizeof(struct rtattr *), GFP_KERNEL);
-	if (!rta_buf)
-		panic("rtnetlink_init: cannot allocate rta_buf\n");
-
 	if (register_pernet_subsys(&rtnetlink_net_ops))
 		panic("rtnetlink_init: cannot initialize rtnetlink\n");
 
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 33245ef..ba64614 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -673,6 +673,7 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
 	new->mac_header		= old->mac_header;
 	new->inner_transport_header = old->inner_transport_header;
 	new->inner_network_header = old->inner_network_header;
+	new->inner_mac_header = old->inner_mac_header;
 	skb_dst_copy(new, old);
 	new->rxhash		= old->rxhash;
 	new->ooo_okay		= old->ooo_okay;
@@ -867,6 +868,18 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask)
 }
 EXPORT_SYMBOL(skb_clone);
 
+static void skb_headers_offset_update(struct sk_buff *skb, int off)
+{
+	/* {transport,network,mac}_header and tail are relative to skb->head */
+	skb->transport_header += off;
+	skb->network_header   += off;
+	if (skb_mac_header_was_set(skb))
+		skb->mac_header += off;
+	skb->inner_transport_header += off;
+	skb->inner_network_header += off;
+	skb->inner_mac_header += off;
+}
+
 static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
 {
 #ifndef NET_SKBUFF_DATA_USES_OFFSET
@@ -879,13 +892,7 @@ static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
 	__copy_skb_header(new, old);
 
 #ifndef NET_SKBUFF_DATA_USES_OFFSET
-	/* {transport,network,mac}_header are relative to skb->head */
-	new->transport_header += offset;
-	new->network_header   += offset;
-	if (skb_mac_header_was_set(new))
-		new->mac_header	      += offset;
-	new->inner_transport_header += offset;
-	new->inner_network_header   += offset;
+	skb_headers_offset_update(new, offset);
 #endif
 	skb_shinfo(new)->gso_size = skb_shinfo(old)->gso_size;
 	skb_shinfo(new)->gso_segs = skb_shinfo(old)->gso_segs;
@@ -1077,14 +1084,8 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail,
 #else
 	skb->end      = skb->head + size;
 #endif
-	/* {transport,network,mac}_header and tail are relative to skb->head */
 	skb->tail	      += off;
-	skb->transport_header += off;
-	skb->network_header   += off;
-	if (skb_mac_header_was_set(skb))
-		skb->mac_header += off;
-	skb->inner_transport_header += off;
-	skb->inner_network_header += off;
+	skb_headers_offset_update(skb, off);
 	/* Only adjust this if it actually is csum_start rather than csum */
 	if (skb->ip_summed == CHECKSUM_PARTIAL)
 		skb->csum_start += nhead;
@@ -1180,12 +1181,7 @@ struct sk_buff *skb_copy_expand(const struct sk_buff *skb,
 	if (n->ip_summed == CHECKSUM_PARTIAL)
 		n->csum_start += off;
 #ifdef NET_SKBUFF_DATA_USES_OFFSET
-	n->transport_header += off;
-	n->network_header   += off;
-	if (skb_mac_header_was_set(skb))
-		n->mac_header += off;
-	n->inner_transport_header += off;
-	n->inner_network_header	   += off;
+	skb_headers_offset_update(n, off);
 #endif
 
 	return n;
@@ -2741,12 +2737,19 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features)
 	unsigned int tnl_hlen = skb_tnl_header_len(skb);
 	unsigned int headroom;
 	unsigned int len;
+	__be16 proto;
+	bool csum;
 	int sg = !!(features & NETIF_F_SG);
 	int nfrags = skb_shinfo(skb)->nr_frags;
 	int err = -ENOMEM;
 	int i = 0;
 	int pos;
 
+	proto = skb_network_protocol(skb);
+	if (unlikely(!proto))
+		return ERR_PTR(-EINVAL);
+
+	csum = !!can_checksum_protocol(features, proto);
 	__skb_push(skb, doffset);
 	headroom = skb_headroom(skb);
 	pos = skb_headlen(skb);
@@ -2884,6 +2887,12 @@ skip_fraglist:
 		nskb->data_len = len - hsize;
 		nskb->len += nskb->data_len;
 		nskb->truesize += nskb->data_len;
+
+		if (!csum) {
+			nskb->csum = skb_checksum(nskb, doffset,
+						  nskb->len - doffset, 0);
+			nskb->ip_summed = CHECKSUM_NONE;
+		}
 	} while ((offset += len) < skb->len);
 
 	return segs;
@@ -3361,6 +3370,7 @@ bool skb_partial_csum_set(struct sk_buff *skb, u16 start, u16 off)
 	skb->ip_summed = CHECKSUM_PARTIAL;
 	skb->csum_start = skb_headroom(skb) + start;
 	skb->csum_offset = off;
+	skb_set_transport_header(skb, start);
 	return true;
 }
 EXPORT_SYMBOL_GPL(skb_partial_csum_set);
diff --git a/net/core/sock.c b/net/core/sock.c
index b261a79..2ff5f36 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -907,6 +907,10 @@ set_rcvbuf:
 		sock_valbool_flag(sk, SOCK_NOFCS, valbool);
 		break;
 
+	case SO_SELECT_ERR_QUEUE:
+		sock_valbool_flag(sk, SOCK_SELECT_ERR_QUEUE, valbool);
+		break;
+
 	default:
 		ret = -ENOPROTOOPT;
 		break;
@@ -1160,6 +1164,10 @@ int sock_getsockopt(struct socket *sock, int level, int optname,
 		v.val = sock_flag(sk, SOCK_FILTER_LOCKED);
 		break;
 
+	case SO_SELECT_ERR_QUEUE:
+		v.val = sock_flag(sk, SOCK_SELECT_ERR_QUEUE);
+		break;
+
 	default:
 		return -ENOPROTOOPT;
 	}
@@ -1298,7 +1306,6 @@ static void sk_prot_free(struct proto *prot, struct sock *sk)
 	module_put(owner);
 }
 
-#ifdef CONFIG_CGROUPS
 #if IS_ENABLED(CONFIG_NET_CLS_CGROUP)
 void sock_update_classid(struct sock *sk, struct task_struct *task)
 {
@@ -1321,7 +1328,6 @@ void sock_update_netprioidx(struct sock *sk, struct task_struct *task)
 }
 EXPORT_SYMBOL_GPL(sock_update_netprioidx);
 #endif
-#endif
 
 /**
  *	sk_alloc - All socket objects are allocated here
diff --git a/net/core/utils.c b/net/core/utils.c
index e3487e46..3c7f5b5 100644
--- a/net/core/utils.c
+++ b/net/core/utils.c
@@ -17,6 +17,7 @@
 #include <linux/module.h>
 #include <linux/jiffies.h>
 #include <linux/kernel.h>
+#include <linux/ctype.h>
 #include <linux/inet.h>
 #include <linux/mm.h>
 #include <linux/net.h>
@@ -348,9 +349,7 @@ int mac_pton(const char *s, u8 *mac)
 
 	/* Don't dirty result unless string is valid MAC. */
 	for (i = 0; i < ETH_ALEN; i++) {
-		if (!strchr("0123456789abcdefABCDEF", s[i * 3]))
-			return 0;
-		if (!strchr("0123456789abcdefABCDEF", s[i * 3 + 1]))
+		if (!isxdigit(s[i * 3]) || !isxdigit(s[i * 3 + 1]))
 			return 0;
 		if (i != ETH_ALEN - 1 && s[i * 3 + 2] != ':')
 			return 0;
diff --git a/net/dcb/dcbevent.c b/net/dcb/dcbevent.c
index 1d9eb7c..4f72fc4 100644
--- a/net/dcb/dcbevent.c
+++ b/net/dcb/dcbevent.c
@@ -20,6 +20,7 @@
 #include <linux/rtnetlink.h>
 #include <linux/notifier.h>
 #include <linux/export.h>
+#include <net/dcbevent.h>
 
 static ATOMIC_NOTIFIER_HEAD(dcbevent_notif_chain);
 
diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c
index 21291f1..40d5829 100644
--- a/net/dcb/dcbnl.c
+++ b/net/dcb/dcbnl.c
@@ -1658,7 +1658,7 @@ static const struct reply_func reply_funcs[DCB_CMD_MAX+1] = {
 	[DCB_CMD_CEE_GET]	= { RTM_GETDCB, dcbnl_cee_get },
 };
 
-static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh)
 {
 	struct net *net = sock_net(skb->sk);
 	struct net_device *netdev;
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index 4f9f5eb..ebc54fe 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -500,8 +500,7 @@ static struct dst_entry* dccp_v4_route_skb(struct net *net, struct sock *sk,
 	return &rt->dst;
 }
 
-static int dccp_v4_send_response(struct sock *sk, struct request_sock *req,
-				 struct request_values *rv_unused)
+static int dccp_v4_send_response(struct sock *sk, struct request_sock *req)
 {
 	int err = -1;
 	struct sk_buff *skb;
@@ -658,7 +657,7 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
 	dreq->dreq_gss     = dreq->dreq_iss;
 	dreq->dreq_service = service;
 
-	if (dccp_v4_send_response(sk, req, NULL))
+	if (dccp_v4_send_response(sk, req))
 		goto drop_and_free;
 
 	inet_csk_reqsk_queue_hash_add(sk, req, DCCP_TIMEOUT_INIT);
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
index 6e05981..9c61f9c 100644
--- a/net/dccp/ipv6.c
+++ b/net/dccp/ipv6.c
@@ -213,8 +213,7 @@ out:
 }
 
 
-static int dccp_v6_send_response(struct sock *sk, struct request_sock *req,
-				 struct request_values *rv_unused)
+static int dccp_v6_send_response(struct sock *sk, struct request_sock *req)
 {
 	struct inet6_request_sock *ireq6 = inet6_rsk(req);
 	struct ipv6_pinfo *np = inet6_sk(sk);
@@ -428,7 +427,7 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
 	dreq->dreq_gss     = dreq->dreq_iss;
 	dreq->dreq_service = service;
 
-	if (dccp_v6_send_response(sk, req, NULL))
+	if (dccp_v6_send_response(sk, req))
 		goto drop_and_free;
 
 	inet6_csk_reqsk_queue_hash_add(sk, req, DCCP_TIMEOUT_INIT);
diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c
index c8da116..7d91970 100644
--- a/net/decnet/dn_dev.c
+++ b/net/decnet/dn_dev.c
@@ -563,7 +563,7 @@ static const struct nla_policy dn_ifa_policy[IFA_MAX+1] = {
 				    .len = IFNAMSIZ - 1 },
 };
 
-static int dn_nl_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+static int dn_nl_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh)
 {
 	struct net *net = sock_net(skb->sk);
 	struct nlattr *tb[IFA_MAX+1];
@@ -607,7 +607,7 @@ errout:
 	return err;
 }
 
-static int dn_nl_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+static int dn_nl_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh)
 {
 	struct net *net = sock_net(skb->sk);
 	struct nlattr *tb[IFA_MAX+1];
diff --git a/net/decnet/dn_fib.c b/net/decnet/dn_fib.c
index e36614e..57dc159 100644
--- a/net/decnet/dn_fib.c
+++ b/net/decnet/dn_fib.c
@@ -145,22 +145,10 @@ static inline struct dn_fib_info *dn_fib_find_info(const struct dn_fib_info *nfi
 	return NULL;
 }
 
-__le16 dn_fib_get_attr16(struct rtattr *attr, int attrlen, int type)
+static int dn_fib_count_nhs(const struct nlattr *attr)
 {
-	while(RTA_OK(attr,attrlen)) {
-		if (attr->rta_type == type)
-			return *(__le16*)RTA_DATA(attr);
-		attr = RTA_NEXT(attr, attrlen);
-	}
-
-	return 0;
-}
-
-static int dn_fib_count_nhs(struct rtattr *rta)
-{
-	int nhs = 0;
-	struct rtnexthop *nhp = RTA_DATA(rta);
-	int nhlen = RTA_PAYLOAD(rta);
+	struct rtnexthop *nhp = nla_data(attr);
+	int nhs = 0, nhlen = nla_len(attr);
 
 	while(nhlen >= (int)sizeof(struct rtnexthop)) {
 		if ((nhlen -= nhp->rtnh_len) < 0)
@@ -172,10 +160,11 @@ static int dn_fib_count_nhs(struct rtattr *rta)
 	return nhs;
 }
 
-static int dn_fib_get_nhs(struct dn_fib_info *fi, const struct rtattr *rta, const struct rtmsg *r)
+static int dn_fib_get_nhs(struct dn_fib_info *fi, const struct nlattr *attr,
+			  const struct rtmsg *r)
 {
-	struct rtnexthop *nhp = RTA_DATA(rta);
-	int nhlen = RTA_PAYLOAD(rta);
+	struct rtnexthop *nhp = nla_data(attr);
+	int nhlen = nla_len(attr);
 
 	change_nexthops(fi) {
 		int attrlen = nhlen - sizeof(struct rtnexthop);
@@ -187,7 +176,10 @@ static int dn_fib_get_nhs(struct dn_fib_info *fi, const struct rtattr *rta, cons
 		nh->nh_weight = nhp->rtnh_hops + 1;
 
 		if (attrlen) {
-			nh->nh_gw = dn_fib_get_attr16(RTNH_DATA(nhp), attrlen, RTA_GATEWAY);
+			struct nlattr *gw_attr;
+
+			gw_attr = nla_find((struct nlattr *) (nhp + 1), attrlen, RTA_GATEWAY);
+			nh->nh_gw = gw_attr ? nla_get_le16(gw_attr) : 0;
 		}
 		nhp = RTNH_NEXT(nhp);
 	} endfor_nexthops(fi);
@@ -268,7 +260,8 @@ out:
 }
 
 
-struct dn_fib_info *dn_fib_create_info(const struct rtmsg *r, struct dn_kern_rta *rta, const struct nlmsghdr *nlh, int *errp)
+struct dn_fib_info *dn_fib_create_info(const struct rtmsg *r, struct nlattr *attrs[],
+				       const struct nlmsghdr *nlh, int *errp)
 {
 	int err;
 	struct dn_fib_info *fi = NULL;
@@ -281,11 +274,9 @@ struct dn_fib_info *dn_fib_create_info(const struct rtmsg *r, struct dn_kern_rta
 	if (dn_fib_props[r->rtm_type].scope > r->rtm_scope)
 		goto err_inval;
 
-	if (rta->rta_mp) {
-		nhs = dn_fib_count_nhs(rta->rta_mp);
-		if (nhs == 0)
-			goto err_inval;
-	}
+	if (attrs[RTA_MULTIPATH] &&
+	    (nhs = dn_fib_count_nhs(attrs[RTA_MULTIPATH])) == 0)
+		goto err_inval;
 
 	fi = kzalloc(sizeof(*fi)+nhs*sizeof(struct dn_fib_nh), GFP_KERNEL);
 	err = -ENOBUFS;
@@ -295,53 +286,65 @@ struct dn_fib_info *dn_fib_create_info(const struct rtmsg *r, struct dn_kern_rta
 	fi->fib_protocol = r->rtm_protocol;
 	fi->fib_nhs = nhs;
 	fi->fib_flags = r->rtm_flags;
-	if (rta->rta_priority)
-		fi->fib_priority = *rta->rta_priority;
-	if (rta->rta_mx) {
-		int attrlen = RTA_PAYLOAD(rta->rta_mx);
-		struct rtattr *attr = RTA_DATA(rta->rta_mx);
 
-		while(RTA_OK(attr, attrlen)) {
-			unsigned int flavour = attr->rta_type;
+	if (attrs[RTA_PRIORITY])
+		fi->fib_priority = nla_get_u32(attrs[RTA_PRIORITY]);
+
+	if (attrs[RTA_METRICS]) {
+		struct nlattr *attr;
+		int rem;
 
-			if (flavour) {
-				if (flavour > RTAX_MAX)
+		nla_for_each_nested(attr, attrs[RTA_METRICS], rem) {
+			int type = nla_type(attr);
+
+			if (type) {
+				if (type > RTAX_MAX || nla_len(attr) < 4)
 					goto err_inval;
-				fi->fib_metrics[flavour-1] = *(unsigned int *)RTA_DATA(attr);
+
+				fi->fib_metrics[type-1] = nla_get_u32(attr);
 			}
-			attr = RTA_NEXT(attr, attrlen);
 		}
 	}
-	if (rta->rta_prefsrc)
-		memcpy(&fi->fib_prefsrc, rta->rta_prefsrc, 2);
 
-	if (rta->rta_mp) {
-		if ((err = dn_fib_get_nhs(fi, rta->rta_mp, r)) != 0)
+	if (attrs[RTA_PREFSRC])
+		fi->fib_prefsrc = nla_get_le16(attrs[RTA_PREFSRC]);
+
+	if (attrs[RTA_MULTIPATH]) {
+		if ((err = dn_fib_get_nhs(fi, attrs[RTA_MULTIPATH], r)) != 0)
 			goto failure;
-		if (rta->rta_oif && fi->fib_nh->nh_oif != *rta->rta_oif)
+
+		if (attrs[RTA_OIF] &&
+		    fi->fib_nh->nh_oif != nla_get_u32(attrs[RTA_OIF]))
 			goto err_inval;
-		if (rta->rta_gw && memcmp(&fi->fib_nh->nh_gw, rta->rta_gw, 2))
+
+		if (attrs[RTA_GATEWAY] &&
+		    fi->fib_nh->nh_gw != nla_get_le16(attrs[RTA_GATEWAY]))
 			goto err_inval;
 	} else {
 		struct dn_fib_nh *nh = fi->fib_nh;
-		if (rta->rta_oif)
-			nh->nh_oif = *rta->rta_oif;
-		if (rta->rta_gw)
-			memcpy(&nh->nh_gw, rta->rta_gw, 2);
+
+		if (attrs[RTA_OIF])
+			nh->nh_oif = nla_get_u32(attrs[RTA_OIF]);
+
+		if (attrs[RTA_GATEWAY])
+			nh->nh_gw = nla_get_le16(attrs[RTA_GATEWAY]);
+
 		nh->nh_flags = r->rtm_flags;
 		nh->nh_weight = 1;
 	}
 
 	if (r->rtm_type == RTN_NAT) {
-		if (rta->rta_gw == NULL || nhs != 1 || rta->rta_oif)
+		if (!attrs[RTA_GATEWAY] || nhs != 1 || attrs[RTA_OIF])
 			goto err_inval;
-		memcpy(&fi->fib_nh->nh_gw, rta->rta_gw, 2);
+
+		fi->fib_nh->nh_gw = nla_get_le16(attrs[RTA_GATEWAY]);
 		goto link_it;
 	}
 
 	if (dn_fib_props[r->rtm_type].error) {
-		if (rta->rta_gw || rta->rta_oif || rta->rta_mp)
+		if (attrs[RTA_GATEWAY] || attrs[RTA_OIF] || attrs[RTA_MULTIPATH])
 			goto err_inval;
+
 		goto link_it;
 	}
 
@@ -367,8 +370,8 @@ struct dn_fib_info *dn_fib_create_info(const struct rtmsg *r, struct dn_kern_rta
 	}
 
 	if (fi->fib_prefsrc) {
-		if (r->rtm_type != RTN_LOCAL || rta->rta_dst == NULL ||
-		    memcmp(&fi->fib_prefsrc, rta->rta_dst, 2))
+		if (r->rtm_type != RTN_LOCAL || !attrs[RTA_DST] ||
+		    fi->fib_prefsrc != nla_get_le16(attrs[RTA_DST]))
 			if (dnet_addr_type(fi->fib_prefsrc) != RTN_LOCAL)
 				goto err_inval;
 	}
@@ -486,39 +489,21 @@ void dn_fib_select_multipath(const struct flowidn *fld, struct dn_fib_res *res)
 	spin_unlock_bh(&dn_fib_multipath_lock);
 }
 
-
-static int dn_fib_check_attr(struct rtmsg *r, struct rtattr **rta)
-{
-	int i;
-
-	for(i = 1; i <= RTA_MAX; i++) {
-		struct rtattr *attr = rta[i-1];
-		if (attr) {
-			if (RTA_PAYLOAD(attr) < 4 && RTA_PAYLOAD(attr) != 2)
-				return -EINVAL;
-			if (i != RTA_MULTIPATH && i != RTA_METRICS &&
-			    i != RTA_TABLE)
-				rta[i-1] = (struct rtattr *)RTA_DATA(attr);
-		}
-	}
-
-	return 0;
-}
-
-static inline u32 rtm_get_table(struct rtattr **rta, u8 table)
+static inline u32 rtm_get_table(struct nlattr *attrs[], u8 table)
 {
-	if (rta[RTA_TABLE - 1])
-		table = nla_get_u32((struct nlattr *) rta[RTA_TABLE - 1]);
+	if (attrs[RTA_TABLE])
+		table = nla_get_u32(attrs[RTA_TABLE]);
 
 	return table;
 }
 
-static int dn_fib_rtm_delroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+static int dn_fib_rtm_delroute(struct sk_buff *skb, struct nlmsghdr *nlh)
 {
 	struct net *net = sock_net(skb->sk);
 	struct dn_fib_table *tb;
-	struct rtattr **rta = arg;
-	struct rtmsg *r = NLMSG_DATA(nlh);
+	struct rtmsg *r = nlmsg_data(nlh);
+	struct nlattr *attrs[RTA_MAX+1];
+	int err;
 
 	if (!capable(CAP_NET_ADMIN))
 		return -EPERM;
@@ -526,22 +511,24 @@ static int dn_fib_rtm_delroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *
 	if (!net_eq(net, &init_net))
 		return -EINVAL;
 
-	if (dn_fib_check_attr(r, rta))
-		return -EINVAL;
+	err = nlmsg_parse(nlh, sizeof(*r), attrs, RTA_MAX, rtm_dn_policy);
+	if (err < 0)
+		return err;
 
-	tb = dn_fib_get_table(rtm_get_table(rta, r->rtm_table), 0);
-	if (tb)
-		return tb->delete(tb, r, (struct dn_kern_rta *)rta, nlh, &NETLINK_CB(skb));
+	tb = dn_fib_get_table(rtm_get_table(attrs, r->rtm_table), 0);
+	if (!tb)
+		return -ESRCH;
 
-	return -ESRCH;
+	return tb->delete(tb, r, attrs, nlh, &NETLINK_CB(skb));
 }
 
-static int dn_fib_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+static int dn_fib_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh)
 {
 	struct net *net = sock_net(skb->sk);
 	struct dn_fib_table *tb;
-	struct rtattr **rta = arg;
-	struct rtmsg *r = NLMSG_DATA(nlh);
+	struct rtmsg *r = nlmsg_data(nlh);
+	struct nlattr *attrs[RTA_MAX+1];
+	int err;
 
 	if (!capable(CAP_NET_ADMIN))
 		return -EPERM;
@@ -549,14 +536,15 @@ static int dn_fib_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *
 	if (!net_eq(net, &init_net))
 		return -EINVAL;
 
-	if (dn_fib_check_attr(r, rta))
-		return -EINVAL;
+	err = nlmsg_parse(nlh, sizeof(*r), attrs, RTA_MAX, rtm_dn_policy);
+	if (err < 0)
+		return err;
 
-	tb = dn_fib_get_table(rtm_get_table(rta, r->rtm_table), 1);
-	if (tb)
-		return tb->insert(tb, r, (struct dn_kern_rta *)rta, nlh, &NETLINK_CB(skb));
+	tb = dn_fib_get_table(rtm_get_table(attrs, r->rtm_table), 1);
+	if (!tb)
+		return -ENOBUFS;
 
-	return -ENOBUFS;
+	return tb->insert(tb, r, attrs, nlh, &NETLINK_CB(skb));
 }
 
 static void fib_magic(int cmd, int type, __le16 dst, int dst_len, struct dn_ifaddr *ifa)
@@ -566,10 +554,31 @@ static void fib_magic(int cmd, int type, __le16 dst, int dst_len, struct dn_ifad
 		struct nlmsghdr nlh;
 		struct rtmsg rtm;
 	} req;
-	struct dn_kern_rta rta;
+	struct {
+		struct nlattr hdr;
+		__le16 dst;
+	} dst_attr = {
+		.dst = dst,
+	};
+	struct {
+		struct nlattr hdr;
+		__le16 prefsrc;
+	} prefsrc_attr = {
+		.prefsrc = ifa->ifa_local,
+	};
+	struct {
+		struct nlattr hdr;
+		u32 oif;
+	} oif_attr = {
+		.oif = ifa->ifa_dev->dev->ifindex,
+	};
+	struct nlattr *attrs[RTA_MAX+1] = {
+		[RTA_DST] = (struct nlattr *) &dst_attr,
+		[RTA_PREFSRC] = (struct nlattr * ) &prefsrc_attr,
+		[RTA_OIF] = (struct nlattr *) &oif_attr,
+	};
 
 	memset(&req.rtm, 0, sizeof(req.rtm));
-	memset(&rta, 0, sizeof(rta));
 
 	if (type == RTN_UNICAST)
 		tb = dn_fib_get_table(RT_MIN_TABLE, 1);
@@ -591,14 +600,10 @@ static void fib_magic(int cmd, int type, __le16 dst, int dst_len, struct dn_ifad
 	req.rtm.rtm_scope = (type != RTN_LOCAL ? RT_SCOPE_LINK : RT_SCOPE_HOST);
 	req.rtm.rtm_type = type;
 
-	rta.rta_dst = &dst;
-	rta.rta_prefsrc = &ifa->ifa_local;
-	rta.rta_oif = &ifa->ifa_dev->dev->ifindex;
-
 	if (cmd == RTM_NEWROUTE)
-		tb->insert(tb, &req.rtm, &rta, &req.nlh, NULL);
+		tb->insert(tb, &req.rtm, attrs, &req.nlh, NULL);
 	else
-		tb->delete(tb, &req.rtm, &rta, &req.nlh, NULL);
+		tb->delete(tb, &req.rtm, attrs, &req.nlh, NULL);
 }
 
 static void dn_fib_add_ifaddr(struct dn_ifaddr *ifa)
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
index 5ac0e15..fe32388 100644
--- a/net/decnet/dn_route.c
+++ b/net/decnet/dn_route.c
@@ -1613,23 +1613,41 @@ errout:
 	return -EMSGSIZE;
 }
 
+const struct nla_policy rtm_dn_policy[RTA_MAX + 1] = {
+	[RTA_DST]		= { .type = NLA_U16 },
+	[RTA_SRC]		= { .type = NLA_U16 },
+	[RTA_IIF]		= { .type = NLA_U32 },
+	[RTA_OIF]		= { .type = NLA_U32 },
+	[RTA_GATEWAY]		= { .type = NLA_U16 },
+	[RTA_PRIORITY]		= { .type = NLA_U32 },
+	[RTA_PREFSRC]		= { .type = NLA_U16 },
+	[RTA_METRICS]		= { .type = NLA_NESTED },
+	[RTA_MULTIPATH]		= { .type = NLA_NESTED },
+	[RTA_TABLE]		= { .type = NLA_U32 },
+	[RTA_MARK]		= { .type = NLA_U32 },
+};
+
 /*
  * This is called by both endnodes and routers now.
  */
-static int dn_cache_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, void *arg)
+static int dn_cache_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh)
 {
 	struct net *net = sock_net(in_skb->sk);
-	struct rtattr **rta = arg;
 	struct rtmsg *rtm = nlmsg_data(nlh);
 	struct dn_route *rt = NULL;
 	struct dn_skb_cb *cb;
 	int err;
 	struct sk_buff *skb;
 	struct flowidn fld;
+	struct nlattr *tb[RTA_MAX+1];
 
 	if (!net_eq(net, &init_net))
 		return -EINVAL;
 
+	err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_dn_policy);
+	if (err < 0)
+		return err;
+
 	memset(&fld, 0, sizeof(fld));
 	fld.flowidn_proto = DNPROTO_NSP;
 
@@ -1639,12 +1657,14 @@ static int dn_cache_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, void
 	skb_reset_mac_header(skb);
 	cb = DN_SKB_CB(skb);
 
-	if (rta[RTA_SRC-1])
-		memcpy(&fld.saddr, RTA_DATA(rta[RTA_SRC-1]), 2);
-	if (rta[RTA_DST-1])
-		memcpy(&fld.daddr, RTA_DATA(rta[RTA_DST-1]), 2);
-	if (rta[RTA_IIF-1])
-		memcpy(&fld.flowidn_iif, RTA_DATA(rta[RTA_IIF-1]), sizeof(int));
+	if (tb[RTA_SRC])
+		fld.saddr = nla_get_le16(tb[RTA_SRC]);
+
+	if (tb[RTA_DST])
+		fld.daddr = nla_get_le16(tb[RTA_DST]);
+
+	if (tb[RTA_IIF])
+		fld.flowidn_iif = nla_get_u32(tb[RTA_IIF]);
 
 	if (fld.flowidn_iif) {
 		struct net_device *dev;
@@ -1669,10 +1689,9 @@ static int dn_cache_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, void
 		if (!err && -rt->dst.error)
 			err = rt->dst.error;
 	} else {
-		int oif = 0;
-		if (rta[RTA_OIF - 1])
-			memcpy(&oif, RTA_DATA(rta[RTA_OIF - 1]), sizeof(int));
-		fld.flowidn_oif = oif;
+		if (tb[RTA_OIF])
+			fld.flowidn_oif = nla_get_u32(tb[RTA_OIF]);
+
 		err = dn_route_output_key((struct dst_entry **)&rt, &fld, 0);
 	}
 
diff --git a/net/decnet/dn_table.c b/net/decnet/dn_table.c
index 6c2445b..b15c1d1 100644
--- a/net/decnet/dn_table.c
+++ b/net/decnet/dn_table.c
@@ -19,7 +19,7 @@
 #include <linux/sockios.h>
 #include <linux/init.h>
 #include <linux/skbuff.h>
-#include <linux/netlink.h>
+#include <net/netlink.h>
 #include <linux/rtnetlink.h>
 #include <linux/proc_fs.h>
 #include <linux/netdevice.h>
@@ -224,26 +224,27 @@ static struct dn_zone *dn_new_zone(struct dn_hash *table, int z)
 }
 
 
-static int dn_fib_nh_match(struct rtmsg *r, struct nlmsghdr *nlh, struct dn_kern_rta *rta, struct dn_fib_info *fi)
+static int dn_fib_nh_match(struct rtmsg *r, struct nlmsghdr *nlh, struct nlattr *attrs[], struct dn_fib_info *fi)
 {
 	struct rtnexthop *nhp;
 	int nhlen;
 
-	if (rta->rta_priority && *rta->rta_priority != fi->fib_priority)
+	if (attrs[RTA_PRIORITY] &&
+	    nla_get_u32(attrs[RTA_PRIORITY]) != fi->fib_priority)
 		return 1;
 
-	if (rta->rta_oif || rta->rta_gw) {
-		if ((!rta->rta_oif || *rta->rta_oif == fi->fib_nh->nh_oif) &&
-		    (!rta->rta_gw  || memcmp(rta->rta_gw, &fi->fib_nh->nh_gw, 2) == 0))
+	if (attrs[RTA_OIF] || attrs[RTA_GATEWAY]) {
+		if ((!attrs[RTA_OIF] || nla_get_u32(attrs[RTA_OIF]) == fi->fib_nh->nh_oif) &&
+		    (!attrs[RTA_GATEWAY]  || nla_get_le16(attrs[RTA_GATEWAY]) != fi->fib_nh->nh_gw))
 			return 0;
 		return 1;
 	}
 
-	if (rta->rta_mp == NULL)
+	if (!attrs[RTA_MULTIPATH])
 		return 0;
 
-	nhp = RTA_DATA(rta->rta_mp);
-	nhlen = RTA_PAYLOAD(rta->rta_mp);
+	nhp = nla_data(attrs[RTA_MULTIPATH]);
+	nhlen = nla_len(attrs[RTA_MULTIPATH]);
 
 	for_nexthops(fi) {
 		int attrlen = nhlen - sizeof(struct rtnexthop);
@@ -254,7 +255,10 @@ static int dn_fib_nh_match(struct rtmsg *r, struct nlmsghdr *nlh, struct dn_kern
 		if (nhp->rtnh_ifindex && nhp->rtnh_ifindex != nh->nh_oif)
 			return 1;
 		if (attrlen) {
-			gw = dn_fib_get_attr16(RTNH_DATA(nhp), attrlen, RTA_GATEWAY);
+			struct nlattr *gw_attr;
+
+			gw_attr = nla_find((struct nlattr *) (nhp + 1), attrlen, RTA_GATEWAY);
+			gw = gw_attr ? nla_get_le16(gw_attr) : 0;
 
 			if (gw && gw != nh->nh_gw)
 				return 1;
@@ -488,7 +492,7 @@ int dn_fib_dump(struct sk_buff *skb, struct netlink_callback *cb)
 	if (!net_eq(net, &init_net))
 		return 0;
 
-	if (NLMSG_PAYLOAD(cb->nlh, 0) >= sizeof(struct rtmsg) &&
+	if (nlmsg_len(cb->nlh) >= sizeof(struct rtmsg) &&
 		((struct rtmsg *)nlmsg_data(cb->nlh))->rtm_flags&RTM_F_CLONED)
 			return dn_cache_dump(skb, cb);
 
@@ -517,7 +521,8 @@ out:
 	return skb->len;
 }
 
-static int dn_fib_table_insert(struct dn_fib_table *tb, struct rtmsg *r, struct dn_kern_rta *rta, struct nlmsghdr *n, struct netlink_skb_parms *req)
+static int dn_fib_table_insert(struct dn_fib_table *tb, struct rtmsg *r, struct nlattr *attrs[],
+			       struct nlmsghdr *n, struct netlink_skb_parms *req)
 {
 	struct dn_hash *table = (struct dn_hash *)tb->data;
 	struct dn_fib_node *new_f, *f, **fp, **del_fp;
@@ -536,15 +541,14 @@ static int dn_fib_table_insert(struct dn_fib_table *tb, struct rtmsg *r, struct
 		return -ENOBUFS;
 
 	dz_key_0(key);
-	if (rta->rta_dst) {
-		__le16 dst;
-		memcpy(&dst, rta->rta_dst, 2);
+	if (attrs[RTA_DST]) {
+		__le16 dst = nla_get_le16(attrs[RTA_DST]);
 		if (dst & ~DZ_MASK(dz))
 			return -EINVAL;
 		key = dz_key(dst, dz);
 	}
 
-	if ((fi = dn_fib_create_info(r, rta, n, &err)) == NULL)
+	if ((fi = dn_fib_create_info(r, attrs, n, &err)) == NULL)
 		return err;
 
 	if (dz->dz_nent > (dz->dz_divisor << 2) &&
@@ -654,7 +658,8 @@ out:
 }
 
 
-static int dn_fib_table_delete(struct dn_fib_table *tb, struct rtmsg *r, struct dn_kern_rta *rta, struct nlmsghdr *n, struct netlink_skb_parms *req)
+static int dn_fib_table_delete(struct dn_fib_table *tb, struct rtmsg *r, struct nlattr *attrs[],
+			       struct nlmsghdr *n, struct netlink_skb_parms *req)
 {
 	struct dn_hash *table = (struct dn_hash*)tb->data;
 	struct dn_fib_node **fp, **del_fp, *f;
@@ -671,9 +676,8 @@ static int dn_fib_table_delete(struct dn_fib_table *tb, struct rtmsg *r, struct
 		return -ESRCH;
 
 	dz_key_0(key);
-	if (rta->rta_dst) {
-		__le16 dst;
-		memcpy(&dst, rta->rta_dst, 2);
+	if (attrs[RTA_DST]) {
+		__le16 dst = nla_get_le16(attrs[RTA_DST]);
 		if (dst & ~DZ_MASK(dz))
 			return -EINVAL;
 		key = dz_key(dst, dz);
@@ -703,7 +707,7 @@ static int dn_fib_table_delete(struct dn_fib_table *tb, struct rtmsg *r, struct
 				(r->rtm_scope == RT_SCOPE_NOWHERE || f->fn_scope == r->rtm_scope) &&
 				(!r->rtm_protocol ||
 					fi->fib_protocol == r->rtm_protocol) &&
-				dn_fib_nh_match(r, n, rta, fi) == 0)
+				dn_fib_nh_match(r, n, attrs, fi) == 0)
 			del_fp = fp;
 	}
 
diff --git a/net/decnet/netfilter/dn_rtmsg.c b/net/decnet/netfilter/dn_rtmsg.c
index dfe4201..2a7efe3 100644
--- a/net/decnet/netfilter/dn_rtmsg.c
+++ b/net/decnet/netfilter/dn_rtmsg.c
@@ -19,7 +19,7 @@
 #include <linux/netdevice.h>
 #include <linux/netfilter.h>
 #include <linux/spinlock.h>
-#include <linux/netlink.h>
+#include <net/netlink.h>
 #include <linux/netfilter_decnet.h>
 
 #include <net/sock.h>
@@ -39,21 +39,21 @@ static struct sk_buff *dnrmg_build_message(struct sk_buff *rt_skb, int *errp)
 	unsigned char *ptr;
 	struct nf_dn_rtmsg *rtm;
 
-	size = NLMSG_SPACE(rt_skb->len);
-	size += NLMSG_ALIGN(sizeof(struct nf_dn_rtmsg));
-	skb = alloc_skb(size, GFP_ATOMIC);
+	size = NLMSG_ALIGN(rt_skb->len) +
+	       NLMSG_ALIGN(sizeof(struct nf_dn_rtmsg));
+	skb = nlmsg_new(size, GFP_ATOMIC);
 	if (!skb) {
 		*errp = -ENOMEM;
 		return NULL;
 	}
 	old_tail = skb->tail;
-	nlh = nlmsg_put(skb, 0, 0, 0, size - sizeof(*nlh), 0);
+	nlh = nlmsg_put(skb, 0, 0, 0, size, 0);
 	if (!nlh) {
 		kfree_skb(skb);
 		*errp = -ENOMEM;
 		return NULL;
 	}
-	rtm = (struct nf_dn_rtmsg *)NLMSG_DATA(nlh);
+	rtm = (struct nf_dn_rtmsg *)nlmsg_data(nlh);
 	rtm->nfdn_ifindex = rt_skb->dev->ifindex;
 	ptr = NFDN_RTMSG(rtm);
 	skb_copy_from_linear_data(rt_skb, ptr, rt_skb->len);
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index 2bc62ea..0eb5d5e 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -1,6 +1,7 @@
 /*
  * net/dsa/dsa.c - Hardware switch handling
  * Copyright (c) 2008-2009 Marvell Semiconductor
+ * Copyright (c) 2013 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
@@ -14,6 +15,9 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <net/dsa.h>
+#include <linux/of.h>
+#include <linux/of_mdio.h>
+#include <linux/of_platform.h>
 #include "dsa_priv.h"
 
 char dsa_driver_version[] = "0.1";
@@ -287,34 +291,239 @@ static struct net_device *dev_to_net_device(struct device *dev)
 	return NULL;
 }
 
+#ifdef CONFIG_OF
+static int dsa_of_setup_routing_table(struct dsa_platform_data *pd,
+					struct dsa_chip_data *cd,
+					int chip_index,
+					struct device_node *link)
+{
+	int ret;
+	const __be32 *reg;
+	int link_port_addr;
+	int link_sw_addr;
+	struct device_node *parent_sw;
+	int len;
+
+	parent_sw = of_get_parent(link);
+	if (!parent_sw)
+		return -EINVAL;
+
+	reg = of_get_property(parent_sw, "reg", &len);
+	if (!reg || (len != sizeof(*reg) * 2))
+		return -EINVAL;
+
+	link_sw_addr = be32_to_cpup(reg + 1);
+
+	if (link_sw_addr >= pd->nr_chips)
+		return -EINVAL;
+
+	/* First time routing table allocation */
+	if (!cd->rtable) {
+		cd->rtable = kmalloc(pd->nr_chips * sizeof(s8), GFP_KERNEL);
+		if (!cd->rtable)
+			return -ENOMEM;
+
+		/* default to no valid uplink/downlink */
+		memset(cd->rtable, -1, pd->nr_chips * sizeof(s8));
+	}
+
+	reg = of_get_property(link, "reg", NULL);
+	if (!reg) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	link_port_addr = be32_to_cpup(reg);
+
+	cd->rtable[link_sw_addr] = link_port_addr;
+
+	return 0;
+out:
+	kfree(cd->rtable);
+	return ret;
+}
+
+static void dsa_of_free_platform_data(struct dsa_platform_data *pd)
+{
+	int i;
+	int port_index;
+
+	for (i = 0; i < pd->nr_chips; i++) {
+		port_index = 0;
+		while (port_index < DSA_MAX_PORTS) {
+			if (pd->chip[i].port_names[port_index])
+				kfree(pd->chip[i].port_names[port_index]);
+			port_index++;
+		}
+		kfree(pd->chip[i].rtable);
+	}
+	kfree(pd->chip);
+}
+
+static int dsa_of_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct device_node *child, *mdio, *ethernet, *port, *link;
+	struct mii_bus *mdio_bus;
+	struct platform_device *ethernet_dev;
+	struct dsa_platform_data *pd;
+	struct dsa_chip_data *cd;
+	const char *port_name;
+	int chip_index, port_index;
+	const unsigned int *sw_addr, *port_reg;
+	int ret;
+
+	mdio = of_parse_phandle(np, "dsa,mii-bus", 0);
+	if (!mdio)
+		return -EINVAL;
+
+	mdio_bus = of_mdio_find_bus(mdio);
+	if (!mdio_bus)
+		return -EINVAL;
+
+	ethernet = of_parse_phandle(np, "dsa,ethernet", 0);
+	if (!ethernet)
+		return -EINVAL;
+
+	ethernet_dev = of_find_device_by_node(ethernet);
+	if (!ethernet_dev)
+		return -ENODEV;
+
+	pd = kzalloc(sizeof(*pd), GFP_KERNEL);
+	if (!pd)
+		return -ENOMEM;
+
+	pdev->dev.platform_data = pd;
+	pd->netdev = &ethernet_dev->dev;
+	pd->nr_chips = of_get_child_count(np);
+	if (pd->nr_chips > DSA_MAX_SWITCHES)
+		pd->nr_chips = DSA_MAX_SWITCHES;
+
+	pd->chip = kzalloc(pd->nr_chips * sizeof(struct dsa_chip_data),
+			GFP_KERNEL);
+	if (!pd->chip) {
+		ret = -ENOMEM;
+		goto out_free;
+	}
+
+	chip_index = 0;
+	for_each_available_child_of_node(np, child) {
+		cd = &pd->chip[chip_index];
+
+		cd->mii_bus = &mdio_bus->dev;
+
+		sw_addr = of_get_property(child, "reg", NULL);
+		if (!sw_addr)
+			continue;
+
+		cd->sw_addr = be32_to_cpup(sw_addr);
+		if (cd->sw_addr > PHY_MAX_ADDR)
+			continue;
+
+		for_each_available_child_of_node(child, port) {
+			port_reg = of_get_property(port, "reg", NULL);
+			if (!port_reg)
+				continue;
+
+			port_index = be32_to_cpup(port_reg);
+
+			port_name = of_get_property(port, "label", NULL);
+			if (!port_name)
+				continue;
+
+			cd->port_names[port_index] = kstrdup(port_name,
+					GFP_KERNEL);
+			if (!cd->port_names[port_index]) {
+				ret = -ENOMEM;
+				goto out_free_chip;
+			}
+
+			link = of_parse_phandle(port, "link", 0);
+
+			if (!strcmp(port_name, "dsa") && link &&
+					pd->nr_chips > 1) {
+				ret = dsa_of_setup_routing_table(pd, cd,
+						chip_index, link);
+				if (ret)
+					goto out_free_chip;
+			}
+
+			if (port_index == DSA_MAX_PORTS)
+				break;
+		}
+	}
+
+	return 0;
+
+out_free_chip:
+	dsa_of_free_platform_data(pd);
+out_free:
+	kfree(pd);
+	pdev->dev.platform_data = NULL;
+	return ret;
+}
+
+static void dsa_of_remove(struct platform_device *pdev)
+{
+	struct dsa_platform_data *pd = pdev->dev.platform_data;
+
+	if (!pdev->dev.of_node)
+		return;
+
+	dsa_of_free_platform_data(pd);
+	kfree(pd);
+}
+#else
+static inline int dsa_of_probe(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static inline void dsa_of_remove(struct platform_device *pdev)
+{
+}
+#endif
+
 static int dsa_probe(struct platform_device *pdev)
 {
 	static int dsa_version_printed;
 	struct dsa_platform_data *pd = pdev->dev.platform_data;
 	struct net_device *dev;
 	struct dsa_switch_tree *dst;
-	int i;
+	int i, ret;
 
 	if (!dsa_version_printed++)
 		printk(KERN_NOTICE "Distributed Switch Architecture "
 			"driver version %s\n", dsa_driver_version);
 
+	if (pdev->dev.of_node) {
+		ret = dsa_of_probe(pdev);
+		if (ret)
+			return ret;
+
+		pd = pdev->dev.platform_data;
+	}
+
 	if (pd == NULL || pd->netdev == NULL)
 		return -EINVAL;
 
 	dev = dev_to_net_device(pd->netdev);
-	if (dev == NULL)
-		return -EINVAL;
+	if (dev == NULL) {
+		ret = -EINVAL;
+		goto out;
+	}
 
 	if (dev->dsa_ptr != NULL) {
 		dev_put(dev);
-		return -EEXIST;
+		ret = -EEXIST;
+		goto out;
 	}
 
 	dst = kzalloc(sizeof(*dst), GFP_KERNEL);
 	if (dst == NULL) {
 		dev_put(dev);
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto out;
 	}
 
 	platform_set_drvdata(pdev, dst);
@@ -366,6 +575,11 @@ static int dsa_probe(struct platform_device *pdev)
 	}
 
 	return 0;
+
+out:
+	dsa_of_remove(pdev);
+
+	return ret;
 }
 
 static int dsa_remove(struct platform_device *pdev)
@@ -385,6 +599,8 @@ static int dsa_remove(struct platform_device *pdev)
 			dsa_switch_destroy(ds);
 	}
 
+	dsa_of_remove(pdev);
+
 	return 0;
 }
 
@@ -392,6 +608,12 @@ static void dsa_shutdown(struct platform_device *pdev)
 {
 }
 
+static const struct of_device_id dsa_of_match_table[] = {
+	{ .compatible = "marvell,dsa", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, dsa_of_match_table);
+
 static struct platform_driver dsa_driver = {
 	.probe		= dsa_probe,
 	.remove		= dsa_remove,
@@ -399,6 +621,7 @@ static struct platform_driver dsa_driver = {
 	.driver = {
 		.name	= "dsa",
 		.owner	= THIS_MODULE,
+		.of_match_table = dsa_of_match_table,
 	},
 };
 
diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c
index a36c85ea..5359560 100644
--- a/net/ethernet/eth.c
+++ b/net/ethernet/eth.c
@@ -195,7 +195,7 @@ __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev)
 	if (netdev_uses_trailer_tags(dev))
 		return htons(ETH_P_TRAILER);
 
-	if (ntohs(eth->h_proto) >= 1536)
+	if (ntohs(eth->h_proto) >= ETH_P_802_3_MIN)
 		return eth->h_proto;
 
 	/*
diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
index 43b95ca..e1b4580 100644
--- a/net/ieee802154/6lowpan.c
+++ b/net/ieee802154/6lowpan.c
@@ -104,6 +104,7 @@ static const u8 lowpan_llprefix[] = {0xfe, 0x80};
 struct lowpan_dev_info {
 	struct net_device	*real_dev; /* real WPAN device ptr */
 	struct mutex		dev_list_mtx; /* mutex for list ops */
+	unsigned short		fragment_tag;
 };
 
 struct lowpan_dev_record {
@@ -120,7 +121,6 @@ struct lowpan_fragment {
 	struct list_head	list;		/* fragments list */
 };
 
-static unsigned short fragment_tag;
 static LIST_HEAD(lowpan_fragments);
 static DEFINE_SPINLOCK(flist_lock);
 
@@ -284,6 +284,9 @@ lowpan_compress_udp_header(u8 **hc06_ptr, struct sk_buff *skb)
 	/* checksum is always inline */
 	memcpy(*hc06_ptr, &uh->check, 2);
 	*hc06_ptr += 2;
+
+	/* skip the UDP header */
+	skb_pull(skb, sizeof(struct udphdr));
 }
 
 static inline int lowpan_fetch_skb_u8(struct sk_buff *skb, u8 *val)
@@ -309,9 +312,8 @@ static inline int lowpan_fetch_skb_u16(struct sk_buff *skb, u16 *val)
 }
 
 static int
-lowpan_uncompress_udp_header(struct sk_buff *skb)
+lowpan_uncompress_udp_header(struct sk_buff *skb, struct udphdr *uh)
 {
-	struct udphdr *uh = udp_hdr(skb);
 	u8 tmp;
 
 	if (!uh)
@@ -358,6 +360,14 @@ lowpan_uncompress_udp_header(struct sk_buff *skb)
 		/* copy checksum */
 		memcpy(&uh->check, &skb->data[0], 2);
 		skb_pull(skb, 2);
+
+		/*
+		 * UDP lenght needs to be infered from the lower layers
+		 * here, we obtain the hint from the remaining size of the
+		 * frame
+		 */
+		uh->len = htons(skb->len + sizeof(struct udphdr));
+		pr_debug("uncompressed UDP length: src = %d", uh->len);
 	} else {
 		pr_debug("ERROR: unsupported NH format\n");
 		goto err;
@@ -572,17 +582,31 @@ static int lowpan_header_create(struct sk_buff *skb,
 	 * this isn't implemented in mainline yet, so currently we assign 0xff
 	 */
 	{
+		mac_cb(skb)->flags = IEEE802154_FC_TYPE_DATA;
+		mac_cb(skb)->seq = ieee802154_mlme_ops(dev)->get_dsn(dev);
+
 		/* prepare wpan address data */
 		sa.addr_type = IEEE802154_ADDR_LONG;
-		sa.pan_id = 0xff;
-
-		da.addr_type = IEEE802154_ADDR_LONG;
-		da.pan_id = 0xff;
+		sa.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev);
 
-		memcpy(&(da.hwaddr), daddr, 8);
 		memcpy(&(sa.hwaddr), saddr, 8);
+		/* intra-PAN communications */
+		da.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev);
 
-		mac_cb(skb)->flags = IEEE802154_FC_TYPE_DATA;
+		/*
+		 * if the destination address is the broadcast address, use the
+		 * corresponding short address
+		 */
+		if (lowpan_is_addr_broadcast(daddr)) {
+			da.addr_type = IEEE802154_ADDR_SHORT;
+			da.short_addr = IEEE802154_ADDR_BROADCAST;
+		} else {
+			da.addr_type = IEEE802154_ADDR_LONG;
+			memcpy(&(da.hwaddr), daddr, IEEE802154_ADDR_LEN);
+
+			/* request acknowledgment */
+			mac_cb(skb)->flags |= MAC_CB_FLAG_ACKREQ;
+		}
 
 		return dev_hard_header(skb, lowpan_dev_info(dev)->real_dev,
 				type, (void *)&da, (void *)&sa, skb->len);
@@ -650,7 +674,7 @@ static void lowpan_fragment_timer_expired(unsigned long entry_addr)
 }
 
 static struct lowpan_fragment *
-lowpan_alloc_new_frame(struct sk_buff *skb, u8 len, u16 tag)
+lowpan_alloc_new_frame(struct sk_buff *skb, u16 len, u16 tag)
 {
 	struct lowpan_fragment *frame;
 
@@ -720,7 +744,7 @@ lowpan_process_data(struct sk_buff *skb)
 	{
 		struct lowpan_fragment *frame;
 		/* slen stores the rightmost 8 bits of the 11 bits length */
-		u8 slen, offset;
+		u8 slen, offset = 0;
 		u16 len, tag;
 		bool found = false;
 
@@ -731,6 +755,18 @@ lowpan_process_data(struct sk_buff *skb)
 		/* adds the 3 MSB to the 8 LSB to retrieve the 11 bits length */
 		len = ((iphc0 & 7) << 8) | slen;
 
+		if ((iphc0 & LOWPAN_DISPATCH_MASK) == LOWPAN_DISPATCH_FRAG1) {
+			pr_debug("%s received a FRAG1 packet (tag: %d, "
+				 "size of the entire IP packet: %d)",
+				 __func__, tag, len);
+		} else { /* FRAGN */
+			if (lowpan_fetch_skb_u8(skb, &offset))
+				goto unlock_and_drop;
+			pr_debug("%s received a FRAGN packet (tag: %d, "
+				 "size of the entire IP packet: %d, "
+				 "offset: %d)", __func__, tag, len, offset * 8);
+		}
+
 		/*
 		 * check if frame assembling with the same tag is
 		 * already in progress
@@ -745,17 +781,13 @@ lowpan_process_data(struct sk_buff *skb)
 
 		/* alloc new frame structure */
 		if (!found) {
+			pr_debug("%s first fragment received for tag %d, "
+				 "begin packet reassembly", __func__, tag);
 			frame = lowpan_alloc_new_frame(skb, len, tag);
 			if (!frame)
 				goto unlock_and_drop;
 		}
 
-		if ((iphc0 & LOWPAN_DISPATCH_MASK) == LOWPAN_DISPATCH_FRAG1)
-			goto unlock_and_drop;
-
-		if (lowpan_fetch_skb_u8(skb, &offset)) /* fetch offset */
-			goto unlock_and_drop;
-
 		/* if payload fits buffer, copy it */
 		if (likely((offset * 8 + skb->len) <= frame->length))
 			skb_copy_to_linear_data_offset(frame->skb, offset * 8,
@@ -773,6 +805,9 @@ lowpan_process_data(struct sk_buff *skb)
 			list_del(&frame->list);
 			spin_unlock_bh(&flist_lock);
 
+			pr_debug("%s successfully reassembled fragment "
+				 "(tag %d)", __func__, tag);
+
 			dev_kfree_skb(skb);
 			skb = frame->skb;
 			kfree(frame);
@@ -918,10 +953,35 @@ lowpan_process_data(struct sk_buff *skb)
 	}
 
 	/* UDP data uncompression */
-	if (iphc0 & LOWPAN_IPHC_NH_C)
-		if (lowpan_uncompress_udp_header(skb))
+	if (iphc0 & LOWPAN_IPHC_NH_C) {
+		struct udphdr uh;
+		struct sk_buff *new;
+		if (lowpan_uncompress_udp_header(skb, &uh))
 			goto drop;
 
+		/*
+		 * replace the compressed UDP head by the uncompressed UDP
+		 * header
+		 */
+		new = skb_copy_expand(skb, sizeof(struct udphdr),
+				      skb_tailroom(skb), GFP_ATOMIC);
+		kfree_skb(skb);
+
+		if (!new)
+			return -ENOMEM;
+
+		skb = new;
+
+		skb_push(skb, sizeof(struct udphdr));
+		skb_reset_transport_header(skb);
+		skb_copy_to_linear_data(skb, &uh, sizeof(struct udphdr));
+
+		lowpan_raw_dump_table(__func__, "raw UDP header dump",
+				      (u8 *)&uh, sizeof(uh));
+
+		hdr.nexthdr = UIP_PROTO_UDP;
+	}
+
 	/* Not fragmented package */
 	hdr.payload_len = htons(skb->len);
 
@@ -969,13 +1029,13 @@ static int lowpan_get_mac_header_length(struct sk_buff *skb)
 
 static int
 lowpan_fragment_xmit(struct sk_buff *skb, u8 *head,
-			int mlen, int plen, int offset)
+			int mlen, int plen, int offset, int type)
 {
 	struct sk_buff *frag;
 	int hlen, ret;
 
-	/* if payload length is zero, therefore it's a first fragment */
-	hlen = (plen == 0 ? LOWPAN_FRAG1_HEAD_SIZE :  LOWPAN_FRAGN_HEAD_SIZE);
+	hlen = (type == LOWPAN_DISPATCH_FRAG1) ?
+			LOWPAN_FRAG1_HEAD_SIZE : LOWPAN_FRAGN_HEAD_SIZE;
 
 	lowpan_raw_dump_inline(__func__, "6lowpan fragment header", head, hlen);
 
@@ -1003,14 +1063,14 @@ lowpan_fragment_xmit(struct sk_buff *skb, u8 *head,
 }
 
 static int
-lowpan_skb_fragmentation(struct sk_buff *skb)
+lowpan_skb_fragmentation(struct sk_buff *skb, struct net_device *dev)
 {
 	int  err, header_length, payload_length, tag, offset = 0;
 	u8 head[5];
 
 	header_length = lowpan_get_mac_header_length(skb);
 	payload_length = skb->len - header_length;
-	tag = fragment_tag++;
+	tag = lowpan_dev_info(dev)->fragment_tag++;
 
 	/* first fragment header */
 	head[0] = LOWPAN_DISPATCH_FRAG1 | ((payload_length >> 8) & 0x7);
@@ -1018,7 +1078,16 @@ lowpan_skb_fragmentation(struct sk_buff *skb)
 	head[2] = tag >> 8;
 	head[3] = tag & 0xff;
 
-	err = lowpan_fragment_xmit(skb, head, header_length, 0, 0);
+	err = lowpan_fragment_xmit(skb, head, header_length, LOWPAN_FRAG_SIZE,
+				   0, LOWPAN_DISPATCH_FRAG1);
+
+	if (err) {
+		pr_debug("%s unable to send FRAG1 packet (tag: %d)",
+			 __func__, tag);
+		goto exit;
+	}
+
+	offset = LOWPAN_FRAG_SIZE;
 
 	/* next fragment header */
 	head[0] &= ~LOWPAN_DISPATCH_FRAG1;
@@ -1033,10 +1102,17 @@ lowpan_skb_fragmentation(struct sk_buff *skb)
 			len = payload_length - offset;
 
 		err = lowpan_fragment_xmit(skb, head, header_length,
-							len, offset);
+					   len, offset, LOWPAN_DISPATCH_FRAGN);
+		if (err) {
+			pr_debug("%s unable to send a subsequent FRAGN packet "
+				 "(tag: %d, offset: %d", __func__, tag, offset);
+			goto exit;
+		}
+
 		offset += len;
 	}
 
+exit:
 	return err;
 }
 
@@ -1059,7 +1135,7 @@ static netdev_tx_t lowpan_xmit(struct sk_buff *skb, struct net_device *dev)
 	}
 
 	pr_debug("frame is too big, fragmentation is needed\n");
-	err = lowpan_skb_fragmentation(skb);
+	err = lowpan_skb_fragmentation(skb, dev);
 error:
 	dev_kfree_skb(skb);
 out:
@@ -1087,6 +1163,12 @@ static u16 lowpan_get_short_addr(const struct net_device *dev)
 	return ieee802154_mlme_ops(real_dev)->get_short_addr(real_dev);
 }
 
+static u8 lowpan_get_dsn(const struct net_device *dev)
+{
+	struct net_device *real_dev = lowpan_dev_info(dev)->real_dev;
+	return ieee802154_mlme_ops(real_dev)->get_dsn(real_dev);
+}
+
 static struct header_ops lowpan_header_ops = {
 	.create	= lowpan_header_create,
 };
@@ -1100,6 +1182,7 @@ static struct ieee802154_mlme_ops lowpan_mlme = {
 	.get_pan_id = lowpan_get_pan_id,
 	.get_phy = lowpan_get_phy,
 	.get_short_addr = lowpan_get_short_addr,
+	.get_dsn = lowpan_get_dsn,
 };
 
 static void lowpan_setup(struct net_device *dev)
@@ -1203,6 +1286,7 @@ static int lowpan_newlink(struct net *src_net, struct net_device *dev,
 		return -ENODEV;
 
 	lowpan_dev_info(dev)->real_dev = real_dev;
+	lowpan_dev_info(dev)->fragment_tag = 0;
 	mutex_init(&lowpan_dev_info(dev)->dev_list_mtx);
 
 	entry = kzalloc(sizeof(struct lowpan_dev_record), GFP_KERNEL);
diff --git a/net/ieee802154/6lowpan.h b/net/ieee802154/6lowpan.h
index bba5f83..4b8f917 100644
--- a/net/ieee802154/6lowpan.h
+++ b/net/ieee802154/6lowpan.h
@@ -92,9 +92,10 @@
  */
 #define lowpan_is_iid_16_bit_compressable(a)	\
 	((((a)->s6_addr16[4]) == 0) &&		\
-	 (((a)->s6_addr16[5]) == 0) &&		\
-	 (((a)->s6_addr16[6]) == 0) &&		\
-	 ((((a)->s6_addr[14]) & 0x80) == 0))
+	 (((a)->s6_addr[10]) == 0) &&		\
+	 (((a)->s6_addr[11]) == 0xff) &&	\
+	 (((a)->s6_addr[12]) == 0xfe) &&	\
+	 (((a)->s6_addr[13]) == 0))
 
 /* multicast address */
 #define is_addr_mcast(a) (((a)->s6_addr[0]) == 0xFF)
diff --git a/net/ieee802154/dgram.c b/net/ieee802154/dgram.c
index e0da175..581a595 100644
--- a/net/ieee802154/dgram.c
+++ b/net/ieee802154/dgram.c
@@ -291,6 +291,9 @@ static int dgram_recvmsg(struct kiocb *iocb, struct sock *sk,
 	size_t copied = 0;
 	int err = -EOPNOTSUPP;
 	struct sk_buff *skb;
+	struct sockaddr_ieee802154 *saddr;
+
+	saddr = (struct sockaddr_ieee802154 *)msg->msg_name;
 
 	skb = skb_recv_datagram(sk, flags, noblock, &err);
 	if (!skb)
@@ -309,6 +312,13 @@ static int dgram_recvmsg(struct kiocb *iocb, struct sock *sk,
 
 	sock_recv_ts_and_drops(msg, sk, skb);
 
+	if (saddr) {
+		saddr->family = AF_IEEE802154;
+		saddr->addr = mac_cb(skb)->sa;
+	}
+	if (addr_len)
+		*addr_len = sizeof(*saddr);
+
 	if (flags & MSG_TRUNC)
 		copied = skb->len;
 done:
diff --git a/net/ieee802154/netlink.c b/net/ieee802154/netlink.c
index 97351e1..7e49bbc 100644
--- a/net/ieee802154/netlink.c
+++ b/net/ieee802154/netlink.c
@@ -64,8 +64,8 @@ struct sk_buff *ieee802154_nl_create(int flags, u8 req)
 
 int ieee802154_nl_mcast(struct sk_buff *msg, unsigned int group)
 {
-	/* XXX: nlh is right at the start of msg */
-	void *hdr = genlmsg_data(NLMSG_DATA(msg->data));
+	struct nlmsghdr *nlh = nlmsg_hdr(msg);
+	void *hdr = genlmsg_data(nlmsg_data(nlh));
 
 	if (genlmsg_end(msg, hdr) < 0)
 		goto out;
@@ -97,8 +97,8 @@ struct sk_buff *ieee802154_nl_new_reply(struct genl_info *info,
 
 int ieee802154_nl_reply(struct sk_buff *msg, struct genl_info *info)
 {
-	/* XXX: nlh is right at the start of msg */
-	void *hdr = genlmsg_data(NLMSG_DATA(msg->data));
+	struct nlmsghdr *nlh = nlmsg_hdr(msg);
+	void *hdr = genlmsg_data(nlmsg_data(nlh));
 
 	if (genlmsg_end(msg, hdr) < 0)
 		goto out;
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
index 7944df7..8603ca8 100644
--- a/net/ipv4/Kconfig
+++ b/net/ipv4/Kconfig
@@ -166,6 +166,7 @@ config IP_PNP_RARP
 config NET_IPIP
 	tristate "IP: tunneling"
 	select INET_TUNNEL
+	select NET_IP_TUNNEL
 	---help---
 	  Tunneling means encapsulating data of one protocol type within
 	  another protocol and sending it over a channel that understands the
@@ -186,9 +187,14 @@ config NET_IPGRE_DEMUX
 	 This is helper module to demultiplex GRE packets on GRE version field criteria.
 	 Required by ip_gre and pptp modules.
 
+config NET_IP_TUNNEL
+	tristate
+	default n
+
 config NET_IPGRE
 	tristate "IP: GRE tunnels over IP"
 	depends on (IPV6 || IPV6=n) && NET_IPGRE_DEMUX
+	select NET_IP_TUNNEL
 	help
 	  Tunneling means encapsulating data of one protocol type within
 	  another protocol and sending it over a channel that understands the
@@ -313,6 +319,7 @@ config SYN_COOKIES
 config NET_IPVTI
 	tristate "Virtual (secure) IP: tunneling"
 	select INET_TUNNEL
+	select NET_IP_TUNNEL
 	depends on INET_XFRM_MODE_TUNNEL
 	---help---
 	  Tunneling means encapsulating data of one protocol type within
diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile
index 15ca63e..089cb9f 100644
--- a/net/ipv4/Makefile
+++ b/net/ipv4/Makefile
@@ -13,6 +13,7 @@ obj-y     := route.o inetpeer.o protocol.o \
 	     fib_frontend.o fib_semantics.o fib_trie.o \
 	     inet_fragment.o ping.o
 
+obj-$(CONFIG_NET_IP_TUNNEL) += ip_tunnel.o
 obj-$(CONFIG_SYSCTL) += sysctl_net_ipv4.o
 obj-$(CONFIG_PROC_FS) += proc.o
 obj-$(CONFIG_IP_MULTIPLE_TABLES) += fib_rules.o
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index c929d9c..93824c5 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -111,7 +111,6 @@
 #include <net/sock.h>
 #include <net/raw.h>
 #include <net/icmp.h>
-#include <net/ipip.h>
 #include <net/inet_common.h>
 #include <net/xfrm.h>
 #include <net/net_namespace.h>
@@ -1283,9 +1282,7 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb,
 	int ihl;
 	int id;
 	unsigned int offset = 0;
-
-	if (!(features & NETIF_F_V4_CSUM))
-		features &= ~NETIF_F_SG;
+	bool tunnel;
 
 	if (unlikely(skb_shinfo(skb)->gso_type &
 		     ~(SKB_GSO_TCPV4 |
@@ -1293,6 +1290,7 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb,
 		       SKB_GSO_DODGY |
 		       SKB_GSO_TCP_ECN |
 		       SKB_GSO_GRE |
+		       SKB_GSO_UDP_TUNNEL |
 		       0)))
 		goto out;
 
@@ -1307,6 +1305,8 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb,
 	if (unlikely(!pskb_may_pull(skb, ihl)))
 		goto out;
 
+	tunnel = !!skb->encapsulation;
+
 	__skb_pull(skb, ihl);
 	skb_reset_transport_header(skb);
 	iph = ip_hdr(skb);
@@ -1326,7 +1326,7 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb,
 	skb = segs;
 	do {
 		iph = ip_hdr(skb);
-		if (proto == IPPROTO_UDP) {
+		if (!tunnel && proto == IPPROTO_UDP) {
 			iph->id = htons(id);
 			iph->frag_off = htons(offset >> 3);
 			if (skb->next != NULL)
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index fea4929..247ec19 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -654,11 +654,19 @@ struct sk_buff *arp_create(int type, int ptype, __be32 dest_ip,
 	arp_ptr += dev->addr_len;
 	memcpy(arp_ptr, &src_ip, 4);
 	arp_ptr += 4;
-	if (target_hw != NULL)
-		memcpy(arp_ptr, target_hw, dev->addr_len);
-	else
-		memset(arp_ptr, 0, dev->addr_len);
-	arp_ptr += dev->addr_len;
+
+	switch (dev->type) {
+#if IS_ENABLED(CONFIG_FIREWIRE_NET)
+	case ARPHRD_IEEE1394:
+		break;
+#endif
+	default:
+		if (target_hw != NULL)
+			memcpy(arp_ptr, target_hw, dev->addr_len);
+		else
+			memset(arp_ptr, 0, dev->addr_len);
+		arp_ptr += dev->addr_len;
+	}
 	memcpy(arp_ptr, &dest_ip, 4);
 
 	return skb;
@@ -781,7 +789,14 @@ static int arp_process(struct sk_buff *skb)
 	arp_ptr += dev->addr_len;
 	memcpy(&sip, arp_ptr, 4);
 	arp_ptr += 4;
-	arp_ptr += dev->addr_len;
+	switch (dev_type) {
+#if IS_ENABLED(CONFIG_FIREWIRE_NET)
+	case ARPHRD_IEEE1394:
+		break;
+#endif
+	default:
+		arp_ptr += dev->addr_len;
+	}
 	memcpy(&tip, arp_ptr, 4);
 /*
  *	Check for bad requests for 127.x.x.x and requests for multicast
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index f678507..5d985e3 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -536,7 +536,7 @@ struct in_ifaddr *inet_ifa_byprefix(struct in_device *in_dev, __be32 prefix,
 	return NULL;
 }
 
-static int inet_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+static int inet_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh)
 {
 	struct net *net = sock_net(skb->sk);
 	struct nlattr *tb[IFA_MAX+1];
@@ -775,7 +775,7 @@ static struct in_ifaddr *find_matching_ifa(struct in_ifaddr *ifa)
 	return NULL;
 }
 
-static int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+static int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh)
 {
 	struct net *net = sock_net(skb->sk);
 	struct in_ifaddr *ifa;
@@ -1499,6 +1499,8 @@ static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
 		idx = 0;
 		head = &net->dev_index_head[h];
 		rcu_read_lock();
+		cb->seq = atomic_read(&net->ipv4.dev_addr_genid) ^
+			  net->dev_base_seq;
 		hlist_for_each_entry_rcu(dev, head, index_hlist) {
 			if (idx < s_idx)
 				goto cont;
@@ -1519,6 +1521,7 @@ static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
 					rcu_read_unlock();
 					goto done;
 				}
+				nl_dump_check_consistent(cb, nlmsg_hdr(skb));
 			}
 cont:
 			idx++;
@@ -1730,8 +1733,7 @@ static const struct nla_policy devconf_ipv4_policy[NETCONFA_MAX+1] = {
 };
 
 static int inet_netconf_get_devconf(struct sk_buff *in_skb,
-				    struct nlmsghdr *nlh,
-				    void *arg)
+				    struct nlmsghdr *nlh)
 {
 	struct net *net = sock_net(in_skb->sk);
 	struct nlattr *tb[NETCONFA_MAX+1];
@@ -1791,6 +1793,77 @@ errout:
 	return err;
 }
 
+static int inet_netconf_dump_devconf(struct sk_buff *skb,
+				     struct netlink_callback *cb)
+{
+	struct net *net = sock_net(skb->sk);
+	int h, s_h;
+	int idx, s_idx;
+	struct net_device *dev;
+	struct in_device *in_dev;
+	struct hlist_head *head;
+
+	s_h = cb->args[0];
+	s_idx = idx = cb->args[1];
+
+	for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
+		idx = 0;
+		head = &net->dev_index_head[h];
+		rcu_read_lock();
+		cb->seq = atomic_read(&net->ipv4.dev_addr_genid) ^
+			  net->dev_base_seq;
+		hlist_for_each_entry_rcu(dev, head, index_hlist) {
+			if (idx < s_idx)
+				goto cont;
+			in_dev = __in_dev_get_rcu(dev);
+			if (!in_dev)
+				goto cont;
+
+			if (inet_netconf_fill_devconf(skb, dev->ifindex,
+						      &in_dev->cnf,
+						      NETLINK_CB(cb->skb).portid,
+						      cb->nlh->nlmsg_seq,
+						      RTM_NEWNETCONF,
+						      NLM_F_MULTI,
+						      -1) <= 0) {
+				rcu_read_unlock();
+				goto done;
+			}
+			nl_dump_check_consistent(cb, nlmsg_hdr(skb));
+cont:
+			idx++;
+		}
+		rcu_read_unlock();
+	}
+	if (h == NETDEV_HASHENTRIES) {
+		if (inet_netconf_fill_devconf(skb, NETCONFA_IFINDEX_ALL,
+					      net->ipv4.devconf_all,
+					      NETLINK_CB(cb->skb).portid,
+					      cb->nlh->nlmsg_seq,
+					      RTM_NEWNETCONF, NLM_F_MULTI,
+					      -1) <= 0)
+			goto done;
+		else
+			h++;
+	}
+	if (h == NETDEV_HASHENTRIES + 1) {
+		if (inet_netconf_fill_devconf(skb, NETCONFA_IFINDEX_DEFAULT,
+					      net->ipv4.devconf_dflt,
+					      NETLINK_CB(cb->skb).portid,
+					      cb->nlh->nlmsg_seq,
+					      RTM_NEWNETCONF, NLM_F_MULTI,
+					      -1) <= 0)
+			goto done;
+		else
+			h++;
+	}
+done:
+	cb->args[0] = h;
+	cb->args[1] = idx;
+
+	return skb->len;
+}
+
 #ifdef CONFIG_SYSCTL
 
 static void devinet_copy_dflt_conf(struct net *net, int i)
@@ -2195,6 +2268,6 @@ void __init devinet_init(void)
 	rtnl_register(PF_INET, RTM_DELADDR, inet_rtm_deladdr, NULL, NULL);
 	rtnl_register(PF_INET, RTM_GETADDR, NULL, inet_dump_ifaddr, NULL);
 	rtnl_register(PF_INET, RTM_GETNETCONF, inet_netconf_get_devconf,
-		      NULL, NULL);
+		      inet_netconf_dump_devconf, NULL);
 }
 
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index eb4bb12..c7629a2 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -604,7 +604,7 @@ errout:
 	return err;
 }
 
-static int inet_rtm_delroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+static int inet_rtm_delroute(struct sk_buff *skb, struct nlmsghdr *nlh)
 {
 	struct net *net = sock_net(skb->sk);
 	struct fib_config cfg;
@@ -626,7 +626,7 @@ errout:
 	return err;
 }
 
-static int inet_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+static int inet_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh)
 {
 	struct net *net = sock_net(skb->sk);
 	struct fib_config cfg;
@@ -957,8 +957,8 @@ static void nl_fib_input(struct sk_buff *skb)
 
 	net = sock_net(skb->sk);
 	nlh = nlmsg_hdr(skb);
-	if (skb->len < NLMSG_SPACE(0) || skb->len < nlh->nlmsg_len ||
-	    nlh->nlmsg_len < NLMSG_LENGTH(sizeof(*frn)))
+	if (skb->len < NLMSG_HDRLEN || skb->len < nlh->nlmsg_len ||
+	    nlmsg_len(nlh) < sizeof(*frn))
 		return;
 
 	skb = skb_clone(skb, GFP_KERNEL);
@@ -966,7 +966,7 @@ static void nl_fib_input(struct sk_buff *skb)
 		return;
 	nlh = nlmsg_hdr(skb);
 
-	frn = (struct fib_result_nl *) NLMSG_DATA(nlh);
+	frn = (struct fib_result_nl *) nlmsg_data(nlh);
 	tb = fib_get_table(net, frn->tb_id_in);
 
 	nl_fib_lookup(frn, tb);
diff --git a/net/ipv4/gre.c b/net/ipv4/gre.c
index 7a4c710..d2d5a99 100644
--- a/net/ipv4/gre.c
+++ b/net/ipv4/gre.c
@@ -27,11 +27,6 @@
 
 static const struct gre_protocol __rcu *gre_proto[GREPROTO_MAX] __read_mostly;
 static DEFINE_SPINLOCK(gre_proto_lock);
-struct gre_base_hdr {
-	__be16 flags;
-	__be16 protocol;
-};
-#define GRE_HEADER_SECTION 4
 
 int gre_add_protocol(const struct gre_protocol *proto, u8 version)
 {
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index 786d97a..6acb541 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -559,7 +559,7 @@ static inline void syn_ack_recalc(struct request_sock *req, const int thresh,
 
 int inet_rtx_syn_ack(struct sock *parent, struct request_sock *req)
 {
-	int err = req->rsk_ops->rtx_syn_ack(parent, req, NULL);
+	int err = req->rsk_ops->rtx_syn_ack(parent, req);
 
 	if (!err)
 		req->num_retrans++;
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c
index 7afa2c3..8620408 100644
--- a/net/ipv4/inet_diag.c
+++ b/net/ipv4/inet_diag.c
@@ -158,7 +158,9 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
 
 #define EXPIRES_IN_MS(tmo)  DIV_ROUND_UP((tmo - jiffies) * 1000, HZ)
 
-	if (icsk->icsk_pending == ICSK_TIME_RETRANS) {
+	if (icsk->icsk_pending == ICSK_TIME_RETRANS ||
+	    icsk->icsk_pending == ICSK_TIME_EARLY_RETRANS ||
+	    icsk->icsk_pending == ICSK_TIME_LOSS_PROBE) {
 		r->idiag_timer = 1;
 		r->idiag_retrans = icsk->icsk_retransmits;
 		r->idiag_expires = EXPIRES_IN_MS(icsk->icsk_timeout);
diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c
index f4fd23d..e97d66a 100644
--- a/net/ipv4/inet_fragment.c
+++ b/net/ipv4/inet_fragment.c
@@ -23,6 +23,28 @@
 
 #include <net/sock.h>
 #include <net/inet_frag.h>
+#include <net/inet_ecn.h>
+
+/* Given the OR values of all fragments, apply RFC 3168 5.3 requirements
+ * Value : 0xff if frame should be dropped.
+ *         0 or INET_ECN_CE value, to be ORed in to final iph->tos field
+ */
+const u8 ip_frag_ecn_table[16] = {
+	/* at least one fragment had CE, and others ECT_0 or ECT_1 */
+	[IPFRAG_ECN_CE | IPFRAG_ECN_ECT_0]			= INET_ECN_CE,
+	[IPFRAG_ECN_CE | IPFRAG_ECN_ECT_1]			= INET_ECN_CE,
+	[IPFRAG_ECN_CE | IPFRAG_ECN_ECT_0 | IPFRAG_ECN_ECT_1]	= INET_ECN_CE,
+
+	/* invalid combinations : drop frame */
+	[IPFRAG_ECN_NOT_ECT | IPFRAG_ECN_CE] = 0xff,
+	[IPFRAG_ECN_NOT_ECT | IPFRAG_ECN_ECT_0] = 0xff,
+	[IPFRAG_ECN_NOT_ECT | IPFRAG_ECN_ECT_1] = 0xff,
+	[IPFRAG_ECN_NOT_ECT | IPFRAG_ECN_ECT_0 | IPFRAG_ECN_ECT_1] = 0xff,
+	[IPFRAG_ECN_NOT_ECT | IPFRAG_ECN_CE | IPFRAG_ECN_ECT_0] = 0xff,
+	[IPFRAG_ECN_NOT_ECT | IPFRAG_ECN_CE | IPFRAG_ECN_ECT_1] = 0xff,
+	[IPFRAG_ECN_NOT_ECT | IPFRAG_ECN_CE | IPFRAG_ECN_ECT_0 | IPFRAG_ECN_ECT_1] = 0xff,
+};
+EXPORT_SYMBOL(ip_frag_ecn_table);
 
 static void inet_frag_secret_rebuild(unsigned long dummy)
 {
@@ -30,20 +52,27 @@ static void inet_frag_secret_rebuild(unsigned long dummy)
 	unsigned long now = jiffies;
 	int i;
 
+	/* Per bucket lock NOT needed here, due to write lock protection */
 	write_lock(&f->lock);
+
 	get_random_bytes(&f->rnd, sizeof(u32));
 	for (i = 0; i < INETFRAGS_HASHSZ; i++) {
+		struct inet_frag_bucket *hb;
 		struct inet_frag_queue *q;
 		struct hlist_node *n;
 
-		hlist_for_each_entry_safe(q, n, &f->hash[i], list) {
+		hb = &f->hash[i];
+		hlist_for_each_entry_safe(q, n, &hb->chain, list) {
 			unsigned int hval = f->hashfn(q);
 
 			if (hval != i) {
+				struct inet_frag_bucket *hb_dest;
+
 				hlist_del(&q->list);
 
 				/* Relink to new hash chain. */
-				hlist_add_head(&q->list, &f->hash[hval]);
+				hb_dest = &f->hash[hval];
+				hlist_add_head(&q->list, &hb_dest->chain);
 			}
 		}
 	}
@@ -56,9 +85,12 @@ void inet_frags_init(struct inet_frags *f)
 {
 	int i;
 
-	for (i = 0; i < INETFRAGS_HASHSZ; i++)
-		INIT_HLIST_HEAD(&f->hash[i]);
+	for (i = 0; i < INETFRAGS_HASHSZ; i++) {
+		struct inet_frag_bucket *hb = &f->hash[i];
 
+		spin_lock_init(&hb->chain_lock);
+		INIT_HLIST_HEAD(&hb->chain);
+	}
 	rwlock_init(&f->lock);
 
 	f->rnd = (u32) ((num_physpages ^ (num_physpages>>7)) ^
@@ -100,10 +132,18 @@ EXPORT_SYMBOL(inet_frags_exit_net);
 
 static inline void fq_unlink(struct inet_frag_queue *fq, struct inet_frags *f)
 {
-	write_lock(&f->lock);
+	struct inet_frag_bucket *hb;
+	unsigned int hash;
+
+	read_lock(&f->lock);
+	hash = f->hashfn(fq);
+	hb = &f->hash[hash];
+
+	spin_lock(&hb->chain_lock);
 	hlist_del(&fq->list);
-	fq->net->nqueues--;
-	write_unlock(&f->lock);
+	spin_unlock(&hb->chain_lock);
+
+	read_unlock(&f->lock);
 	inet_frag_lru_del(fq);
 }
 
@@ -182,6 +222,9 @@ int inet_frag_evictor(struct netns_frags *nf, struct inet_frags *f, bool force)
 		q = list_first_entry(&nf->lru_list,
 				struct inet_frag_queue, lru_list);
 		atomic_inc(&q->refcnt);
+		/* Remove q from list to avoid several CPUs grabbing it */
+		list_del_init(&q->lru_list);
+
 		spin_unlock(&nf->lru_lock);
 
 		spin_lock(&q->lock);
@@ -202,27 +245,32 @@ static struct inet_frag_queue *inet_frag_intern(struct netns_frags *nf,
 		struct inet_frag_queue *qp_in, struct inet_frags *f,
 		void *arg)
 {
+	struct inet_frag_bucket *hb;
 	struct inet_frag_queue *qp;
 #ifdef CONFIG_SMP
 #endif
 	unsigned int hash;
 
-	write_lock(&f->lock);
+	read_lock(&f->lock); /* Protects against hash rebuild */
 	/*
 	 * While we stayed w/o the lock other CPU could update
 	 * the rnd seed, so we need to re-calculate the hash
 	 * chain. Fortunatelly the qp_in can be used to get one.
 	 */
 	hash = f->hashfn(qp_in);
+	hb = &f->hash[hash];
+	spin_lock(&hb->chain_lock);
+
 #ifdef CONFIG_SMP
 	/* With SMP race we have to recheck hash table, because
 	 * such entry could be created on other cpu, while we
-	 * promoted read lock to write lock.
+	 * released the hash bucket lock.
 	 */
-	hlist_for_each_entry(qp, &f->hash[hash], list) {
+	hlist_for_each_entry(qp, &hb->chain, list) {
 		if (qp->net == nf && f->match(qp, arg)) {
 			atomic_inc(&qp->refcnt);
-			write_unlock(&f->lock);
+			spin_unlock(&hb->chain_lock);
+			read_unlock(&f->lock);
 			qp_in->last_in |= INET_FRAG_COMPLETE;
 			inet_frag_put(qp_in, f);
 			return qp;
@@ -234,9 +282,9 @@ static struct inet_frag_queue *inet_frag_intern(struct netns_frags *nf,
 		atomic_inc(&qp->refcnt);
 
 	atomic_inc(&qp->refcnt);
-	hlist_add_head(&qp->list, &f->hash[hash]);
-	nf->nqueues++;
-	write_unlock(&f->lock);
+	hlist_add_head(&qp->list, &hb->chain);
+	spin_unlock(&hb->chain_lock);
+	read_unlock(&f->lock);
 	inet_frag_lru_add(nf, qp);
 	return qp;
 }
@@ -277,17 +325,23 @@ struct inet_frag_queue *inet_frag_find(struct netns_frags *nf,
 		struct inet_frags *f, void *key, unsigned int hash)
 	__releases(&f->lock)
 {
+	struct inet_frag_bucket *hb;
 	struct inet_frag_queue *q;
 	int depth = 0;
 
-	hlist_for_each_entry(q, &f->hash[hash], list) {
+	hb = &f->hash[hash];
+
+	spin_lock(&hb->chain_lock);
+	hlist_for_each_entry(q, &hb->chain, list) {
 		if (q->net == nf && f->match(q, key)) {
 			atomic_inc(&q->refcnt);
+			spin_unlock(&hb->chain_lock);
 			read_unlock(&f->lock);
 			return q;
 		}
 		depth++;
 	}
+	spin_unlock(&hb->chain_lock);
 	read_unlock(&f->lock);
 
 	if (depth <= INETFRAGS_MAXDEPTH)
diff --git a/net/ipv4/inet_lro.c b/net/ipv4/inet_lro.c
index cc280a3..1975f52 100644
--- a/net/ipv4/inet_lro.c
+++ b/net/ipv4/inet_lro.c
@@ -29,6 +29,7 @@
 #include <linux/module.h>
 #include <linux/if_vlan.h>
 #include <linux/inet_lro.h>
+#include <net/checksum.h>
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Jan-Bernd Themann <themann@de.ibm.com>");
@@ -114,11 +115,9 @@ static void lro_update_tcp_ip_header(struct net_lro_desc *lro_desc)
 		*(p+2) = lro_desc->tcp_rcv_tsecr;
 	}
 
+	csum_replace2(&iph->check, iph->tot_len, htons(lro_desc->ip_tot_len));
 	iph->tot_len = htons(lro_desc->ip_tot_len);
 
-	iph->check = 0;
-	iph->check = ip_fast_csum((u8 *)lro_desc->iph, iph->ihl);
-
 	tcph->check = 0;
 	tcp_hdr_csum = csum_partial(tcph, TCP_HDR_LEN(tcph), 0);
 	lro_desc->data_csum = csum_add(lro_desc->data_csum, tcp_hdr_csum);
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index a6445b8..9385206 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -79,40 +79,11 @@ struct ipq {
 	struct inet_peer *peer;
 };
 
-/* RFC 3168 support :
- * We want to check ECN values of all fragments, do detect invalid combinations.
- * In ipq->ecn, we store the OR value of each ip4_frag_ecn() fragment value.
- */
-#define	IPFRAG_ECN_NOT_ECT	0x01 /* one frag had ECN_NOT_ECT */
-#define	IPFRAG_ECN_ECT_1	0x02 /* one frag had ECN_ECT_1 */
-#define	IPFRAG_ECN_ECT_0	0x04 /* one frag had ECN_ECT_0 */
-#define	IPFRAG_ECN_CE		0x08 /* one frag had ECN_CE */
-
 static inline u8 ip4_frag_ecn(u8 tos)
 {
 	return 1 << (tos & INET_ECN_MASK);
 }
 
-/* Given the OR values of all fragments, apply RFC 3168 5.3 requirements
- * Value : 0xff if frame should be dropped.
- *         0 or INET_ECN_CE value, to be ORed in to final iph->tos field
- */
-static const u8 ip4_frag_ecn_table[16] = {
-	/* at least one fragment had CE, and others ECT_0 or ECT_1 */
-	[IPFRAG_ECN_CE | IPFRAG_ECN_ECT_0]			= INET_ECN_CE,
-	[IPFRAG_ECN_CE | IPFRAG_ECN_ECT_1]			= INET_ECN_CE,
-	[IPFRAG_ECN_CE | IPFRAG_ECN_ECT_0 | IPFRAG_ECN_ECT_1]	= INET_ECN_CE,
-
-	/* invalid combinations : drop frame */
-	[IPFRAG_ECN_NOT_ECT | IPFRAG_ECN_CE] = 0xff,
-	[IPFRAG_ECN_NOT_ECT | IPFRAG_ECN_ECT_0] = 0xff,
-	[IPFRAG_ECN_NOT_ECT | IPFRAG_ECN_ECT_1] = 0xff,
-	[IPFRAG_ECN_NOT_ECT | IPFRAG_ECN_ECT_0 | IPFRAG_ECN_ECT_1] = 0xff,
-	[IPFRAG_ECN_NOT_ECT | IPFRAG_ECN_CE | IPFRAG_ECN_ECT_0] = 0xff,
-	[IPFRAG_ECN_NOT_ECT | IPFRAG_ECN_CE | IPFRAG_ECN_ECT_1] = 0xff,
-	[IPFRAG_ECN_NOT_ECT | IPFRAG_ECN_CE | IPFRAG_ECN_ECT_0 | IPFRAG_ECN_ECT_1] = 0xff,
-};
-
 static struct inet_frags ip4_frags;
 
 int ip_frag_nqueues(struct net *net)
@@ -551,7 +522,7 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev,
 
 	ipq_kill(qp);
 
-	ecn = ip4_frag_ecn_table[qp->ecn];
+	ecn = ip_frag_ecn_table[qp->ecn];
 	if (unlikely(ecn == 0xff)) {
 		err = -EINVAL;
 		goto out_fail;
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 91d66db..e5dfd28 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -37,7 +37,7 @@
 #include <net/ip.h>
 #include <net/icmp.h>
 #include <net/protocol.h>
-#include <net/ipip.h>
+#include <net/ip_tunnels.h>
 #include <net/arp.h>
 #include <net/checksum.h>
 #include <net/dsfield.h>
@@ -108,15 +108,6 @@
    fatal route to network, even if it were you who configured
    fatal static route: you are innocent. :-)
 
-
-
-   3. Really, ipv4/ipip.c, ipv4/ip_gre.c and ipv6/sit.c contain
-   practically identical code. It would be good to glue them
-   together, but it is not very evident, how to make them modular.
-   sit is integral part of IPv6, ipip and gre are naturally modular.
-   We could extract common parts (hash table, ioctl etc)
-   to a separate module (ip_tunnel.c).
-
    Alexey Kuznetsov.
  */
 
@@ -126,400 +117,135 @@ MODULE_PARM_DESC(log_ecn_error, "Log packets received with corrupted ECN");
 
 static struct rtnl_link_ops ipgre_link_ops __read_mostly;
 static int ipgre_tunnel_init(struct net_device *dev);
-static void ipgre_tunnel_setup(struct net_device *dev);
-static int ipgre_tunnel_bind_dev(struct net_device *dev);
-
-/* Fallback tunnel: no source, no destination, no key, no options */
-
-#define HASH_SIZE  16
 
 static int ipgre_net_id __read_mostly;
-struct ipgre_net {
-	struct ip_tunnel __rcu *tunnels[4][HASH_SIZE];
-
-	struct net_device *fb_tunnel_dev;
-};
-
-/* Tunnel hash table */
-
-/*
-   4 hash tables:
-
-   3: (remote,local)
-   2: (remote,*)
-   1: (*,local)
-   0: (*,*)
+static int gre_tap_net_id __read_mostly;
 
-   We require exact key match i.e. if a key is present in packet
-   it will match only tunnel with the same key; if it is not present,
-   it will match only keyless tunnel.
-
-   All keysless packets, if not matched configured keyless tunnels
-   will match fallback tunnel.
- */
+static __sum16 check_checksum(struct sk_buff *skb)
+{
+	__sum16 csum = 0;
 
-#define HASH(addr) (((__force u32)addr^((__force u32)addr>>4))&0xF)
+	switch (skb->ip_summed) {
+	case CHECKSUM_COMPLETE:
+		csum = csum_fold(skb->csum);
 
-#define tunnels_r_l	tunnels[3]
-#define tunnels_r	tunnels[2]
-#define tunnels_l	tunnels[1]
-#define tunnels_wc	tunnels[0]
+		if (!csum)
+			break;
+		/* Fall through. */
 
-static struct rtnl_link_stats64 *ipgre_get_stats64(struct net_device *dev,
-						   struct rtnl_link_stats64 *tot)
-{
-	int i;
-
-	for_each_possible_cpu(i) {
-		const struct pcpu_tstats *tstats = per_cpu_ptr(dev->tstats, i);
-		u64 rx_packets, rx_bytes, tx_packets, tx_bytes;
-		unsigned int start;
-
-		do {
-			start = u64_stats_fetch_begin_bh(&tstats->syncp);
-			rx_packets = tstats->rx_packets;
-			tx_packets = tstats->tx_packets;
-			rx_bytes = tstats->rx_bytes;
-			tx_bytes = tstats->tx_bytes;
-		} while (u64_stats_fetch_retry_bh(&tstats->syncp, start));
-
-		tot->rx_packets += rx_packets;
-		tot->tx_packets += tx_packets;
-		tot->rx_bytes   += rx_bytes;
-		tot->tx_bytes   += tx_bytes;
+	case CHECKSUM_NONE:
+		skb->csum = 0;
+		csum = __skb_checksum_complete(skb);
+		skb->ip_summed = CHECKSUM_COMPLETE;
+		break;
 	}
 
-	tot->multicast = dev->stats.multicast;
-	tot->rx_crc_errors = dev->stats.rx_crc_errors;
-	tot->rx_fifo_errors = dev->stats.rx_fifo_errors;
-	tot->rx_length_errors = dev->stats.rx_length_errors;
-	tot->rx_frame_errors = dev->stats.rx_frame_errors;
-	tot->rx_errors = dev->stats.rx_errors;
-
-	tot->tx_fifo_errors = dev->stats.tx_fifo_errors;
-	tot->tx_carrier_errors = dev->stats.tx_carrier_errors;
-	tot->tx_dropped = dev->stats.tx_dropped;
-	tot->tx_aborted_errors = dev->stats.tx_aborted_errors;
-	tot->tx_errors = dev->stats.tx_errors;
-
-	return tot;
+	return csum;
 }
 
-/* Does key in tunnel parameters match packet */
-static bool ipgre_key_match(const struct ip_tunnel_parm *p,
-			    __be16 flags, __be32 key)
+static int ip_gre_calc_hlen(__be16 o_flags)
 {
-	if (p->i_flags & GRE_KEY) {
-		if (flags & GRE_KEY)
-			return key == p->i_key;
-		else
-			return false;	/* key expected, none present */
-	} else
-		return !(flags & GRE_KEY);
-}
+	int addend = 4;
 
-/* Given src, dst and key, find appropriate for input tunnel. */
+	if (o_flags&TUNNEL_CSUM)
+		addend += 4;
+	if (o_flags&TUNNEL_KEY)
+		addend += 4;
+	if (o_flags&TUNNEL_SEQ)
+		addend += 4;
+	return addend;
+}
 
-static struct ip_tunnel *ipgre_tunnel_lookup(struct net_device *dev,
-					     __be32 remote, __be32 local,
-					     __be16 flags, __be32 key,
-					     __be16 gre_proto)
+static int parse_gre_header(struct sk_buff *skb, struct tnl_ptk_info *tpi,
+			    bool *csum_err, int *hdr_len)
 {
-	struct net *net = dev_net(dev);
-	int link = dev->ifindex;
-	unsigned int h0 = HASH(remote);
-	unsigned int h1 = HASH(key);
-	struct ip_tunnel *t, *cand = NULL;
-	struct ipgre_net *ign = net_generic(net, ipgre_net_id);
-	int dev_type = (gre_proto == htons(ETH_P_TEB)) ?
-		       ARPHRD_ETHER : ARPHRD_IPGRE;
-	int score, cand_score = 4;
-
-	for_each_ip_tunnel_rcu(t, ign->tunnels_r_l[h0 ^ h1]) {
-		if (local != t->parms.iph.saddr ||
-		    remote != t->parms.iph.daddr ||
-		    !(t->dev->flags & IFF_UP))
-			continue;
-
-		if (!ipgre_key_match(&t->parms, flags, key))
-			continue;
-
-		if (t->dev->type != ARPHRD_IPGRE &&
-		    t->dev->type != dev_type)
-			continue;
-
-		score = 0;
-		if (t->parms.link != link)
-			score |= 1;
-		if (t->dev->type != dev_type)
-			score |= 2;
-		if (score == 0)
-			return t;
-
-		if (score < cand_score) {
-			cand = t;
-			cand_score = score;
-		}
-	}
-
-	for_each_ip_tunnel_rcu(t, ign->tunnels_r[h0 ^ h1]) {
-		if (remote != t->parms.iph.daddr ||
-		    !(t->dev->flags & IFF_UP))
-			continue;
-
-		if (!ipgre_key_match(&t->parms, flags, key))
-			continue;
-
-		if (t->dev->type != ARPHRD_IPGRE &&
-		    t->dev->type != dev_type)
-			continue;
-
-		score = 0;
-		if (t->parms.link != link)
-			score |= 1;
-		if (t->dev->type != dev_type)
-			score |= 2;
-		if (score == 0)
-			return t;
-
-		if (score < cand_score) {
-			cand = t;
-			cand_score = score;
-		}
-	}
+	struct iphdr *iph = ip_hdr(skb);
+	struct gre_base_hdr *greh;
+	__be32 *options;
 
-	for_each_ip_tunnel_rcu(t, ign->tunnels_l[h1]) {
-		if ((local != t->parms.iph.saddr &&
-		     (local != t->parms.iph.daddr ||
-		      !ipv4_is_multicast(local))) ||
-		    !(t->dev->flags & IFF_UP))
-			continue;
-
-		if (!ipgre_key_match(&t->parms, flags, key))
-			continue;
-
-		if (t->dev->type != ARPHRD_IPGRE &&
-		    t->dev->type != dev_type)
-			continue;
-
-		score = 0;
-		if (t->parms.link != link)
-			score |= 1;
-		if (t->dev->type != dev_type)
-			score |= 2;
-		if (score == 0)
-			return t;
-
-		if (score < cand_score) {
-			cand = t;
-			cand_score = score;
-		}
-	}
+	if (unlikely(!pskb_may_pull(skb, sizeof(struct gre_base_hdr))))
+		return -EINVAL;
 
-	for_each_ip_tunnel_rcu(t, ign->tunnels_wc[h1]) {
-		if (t->parms.i_key != key ||
-		    !(t->dev->flags & IFF_UP))
-			continue;
-
-		if (t->dev->type != ARPHRD_IPGRE &&
-		    t->dev->type != dev_type)
-			continue;
-
-		score = 0;
-		if (t->parms.link != link)
-			score |= 1;
-		if (t->dev->type != dev_type)
-			score |= 2;
-		if (score == 0)
-			return t;
-
-		if (score < cand_score) {
-			cand = t;
-			cand_score = score;
-		}
-	}
+	greh = (struct gre_base_hdr *)((u8 *)iph + (iph->ihl << 2));
+	if (unlikely(greh->flags & (GRE_VERSION | GRE_ROUTING)))
+		return -EINVAL;
 
-	if (cand != NULL)
-		return cand;
+	tpi->flags = gre_flags_to_tnl_flags(greh->flags);
+	*hdr_len = ip_gre_calc_hlen(tpi->flags);
 
-	dev = ign->fb_tunnel_dev;
-	if (dev->flags & IFF_UP)
-		return netdev_priv(dev);
+	if (!pskb_may_pull(skb, *hdr_len))
+		return -EINVAL;
 
-	return NULL;
-}
+	tpi->proto = greh->protocol;
 
-static struct ip_tunnel __rcu **__ipgre_bucket(struct ipgre_net *ign,
-		struct ip_tunnel_parm *parms)
-{
-	__be32 remote = parms->iph.daddr;
-	__be32 local = parms->iph.saddr;
-	__be32 key = parms->i_key;
-	unsigned int h = HASH(key);
-	int prio = 0;
-
-	if (local)
-		prio |= 1;
-	if (remote && !ipv4_is_multicast(remote)) {
-		prio |= 2;
-		h ^= HASH(remote);
+	options = (__be32 *)(greh + 1);
+	if (greh->flags & GRE_CSUM) {
+		if (check_checksum(skb)) {
+			*csum_err = true;
+			return -EINVAL;
+		}
+		options++;
 	}
 
-	return &ign->tunnels[prio][h];
-}
-
-static inline struct ip_tunnel __rcu **ipgre_bucket(struct ipgre_net *ign,
-		struct ip_tunnel *t)
-{
-	return __ipgre_bucket(ign, &t->parms);
-}
-
-static void ipgre_tunnel_link(struct ipgre_net *ign, struct ip_tunnel *t)
-{
-	struct ip_tunnel __rcu **tp = ipgre_bucket(ign, t);
+	if (greh->flags & GRE_KEY) {
+		tpi->key = *options;
+		options++;
+	} else
+		tpi->key = 0;
 
-	rcu_assign_pointer(t->next, rtnl_dereference(*tp));
-	rcu_assign_pointer(*tp, t);
-}
+	if (unlikely(greh->flags & GRE_SEQ)) {
+		tpi->seq = *options;
+		options++;
+	} else
+		tpi->seq = 0;
 
-static void ipgre_tunnel_unlink(struct ipgre_net *ign, struct ip_tunnel *t)
-{
-	struct ip_tunnel __rcu **tp;
-	struct ip_tunnel *iter;
-
-	for (tp = ipgre_bucket(ign, t);
-	     (iter = rtnl_dereference(*tp)) != NULL;
-	     tp = &iter->next) {
-		if (t == iter) {
-			rcu_assign_pointer(*tp, t->next);
-			break;
+	/* WCCP version 1 and 2 protocol decoding.
+	 * - Change protocol to IP
+	 * - When dealing with WCCPv2, Skip extra 4 bytes in GRE header
+	 */
+	if (greh->flags == 0 && tpi->proto == htons(ETH_P_WCCP)) {
+		tpi->proto = htons(ETH_P_IP);
+		if ((*(u8 *)options & 0xF0) != 0x40) {
+			*hdr_len += 4;
+			if (!pskb_may_pull(skb, *hdr_len))
+				return -EINVAL;
 		}
 	}
-}
-
-static struct ip_tunnel *ipgre_tunnel_find(struct net *net,
-					   struct ip_tunnel_parm *parms,
-					   int type)
-{
-	__be32 remote = parms->iph.daddr;
-	__be32 local = parms->iph.saddr;
-	__be32 key = parms->i_key;
-	int link = parms->link;
-	struct ip_tunnel *t;
-	struct ip_tunnel __rcu **tp;
-	struct ipgre_net *ign = net_generic(net, ipgre_net_id);
-
-	for (tp = __ipgre_bucket(ign, parms);
-	     (t = rtnl_dereference(*tp)) != NULL;
-	     tp = &t->next)
-		if (local == t->parms.iph.saddr &&
-		    remote == t->parms.iph.daddr &&
-		    key == t->parms.i_key &&
-		    link == t->parms.link &&
-		    type == t->dev->type)
-			break;
-
-	return t;
-}
-
-static struct ip_tunnel *ipgre_tunnel_locate(struct net *net,
-		struct ip_tunnel_parm *parms, int create)
-{
-	struct ip_tunnel *t, *nt;
-	struct net_device *dev;
-	char name[IFNAMSIZ];
-	struct ipgre_net *ign = net_generic(net, ipgre_net_id);
-
-	t = ipgre_tunnel_find(net, parms, ARPHRD_IPGRE);
-	if (t || !create)
-		return t;
-
-	if (parms->name[0])
-		strlcpy(name, parms->name, IFNAMSIZ);
-	else
-		strcpy(name, "gre%d");
-
-	dev = alloc_netdev(sizeof(*t), name, ipgre_tunnel_setup);
-	if (!dev)
-		return NULL;
-
-	dev_net_set(dev, net);
-
-	nt = netdev_priv(dev);
-	nt->parms = *parms;
-	dev->rtnl_link_ops = &ipgre_link_ops;
 
-	dev->mtu = ipgre_tunnel_bind_dev(dev);
-
-	if (register_netdevice(dev) < 0)
-		goto failed_free;
-
-	/* Can use a lockless transmit, unless we generate output sequences */
-	if (!(nt->parms.o_flags & GRE_SEQ))
-		dev->features |= NETIF_F_LLTX;
-
-	dev_hold(dev);
-	ipgre_tunnel_link(ign, nt);
-	return nt;
-
-failed_free:
-	free_netdev(dev);
-	return NULL;
-}
-
-static void ipgre_tunnel_uninit(struct net_device *dev)
-{
-	struct net *net = dev_net(dev);
-	struct ipgre_net *ign = net_generic(net, ipgre_net_id);
-
-	ipgre_tunnel_unlink(ign, netdev_priv(dev));
-	dev_put(dev);
+	return 0;
 }
 
-
 static void ipgre_err(struct sk_buff *skb, u32 info)
 {
 
-/* All the routers (except for Linux) return only
-   8 bytes of packet payload. It means, that precise relaying of
-   ICMP in the real Internet is absolutely infeasible.
+	/* All the routers (except for Linux) return only
+	   8 bytes of packet payload. It means, that precise relaying of
+	   ICMP in the real Internet is absolutely infeasible.
 
-   Moreover, Cisco "wise men" put GRE key to the third word
-   in GRE header. It makes impossible maintaining even soft state for keyed
-   GRE tunnels with enabled checksum. Tell them "thank you".
-
-   Well, I wonder, rfc1812 was written by Cisco employee,
-   what the hell these idiots break standards established
-   by themselves???
- */
+	   Moreover, Cisco "wise men" put GRE key to the third word
+	   in GRE header. It makes impossible maintaining even soft
+	   state for keyed GRE tunnels with enabled checksum. Tell
+	   them "thank you".
 
+	   Well, I wonder, rfc1812 was written by Cisco employee,
+	   what the hell these idiots break standards established
+	   by themselves???
+	   */
+	struct net *net = dev_net(skb->dev);
+	struct ip_tunnel_net *itn;
 	const struct iphdr *iph = (const struct iphdr *)skb->data;
-	__be16	     *p = (__be16 *)(skb->data+(iph->ihl<<2));
-	int grehlen = (iph->ihl<<2) + 4;
 	const int type = icmp_hdr(skb)->type;
 	const int code = icmp_hdr(skb)->code;
 	struct ip_tunnel *t;
-	__be16 flags;
-	__be32 key = 0;
+	struct tnl_ptk_info tpi;
+	int hdr_len;
+	bool csum_err = false;
 
-	flags = p[0];
-	if (flags&(GRE_CSUM|GRE_KEY|GRE_SEQ|GRE_ROUTING|GRE_VERSION)) {
-		if (flags&(GRE_VERSION|GRE_ROUTING))
+	if (parse_gre_header(skb, &tpi, &csum_err, &hdr_len)) {
+		if (!csum_err)          /* ignore csum errors. */
 			return;
-		if (flags&GRE_KEY) {
-			grehlen += 4;
-			if (flags&GRE_CSUM)
-				grehlen += 4;
-		}
 	}
 
-	/* If only 8 bytes returned, keyed message will be dropped here */
-	if (skb_headlen(skb) < grehlen)
-		return;
-
-	if (flags & GRE_KEY)
-		key = *(((__be32 *)p) + (grehlen / 4) - 1);
-
 	switch (type) {
 	default:
 	case ICMP_PARAMETERPROB:
@@ -548,8 +274,13 @@ static void ipgre_err(struct sk_buff *skb, u32 info)
 		break;
 	}
 
-	t = ipgre_tunnel_lookup(skb->dev, iph->daddr, iph->saddr,
-				flags, key, p[1]);
+	if (tpi.proto == htons(ETH_P_TEB))
+		itn = net_generic(net, gre_tap_net_id);
+	else
+		itn = net_generic(net, ipgre_net_id);
+
+	t = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi.flags,
+			     iph->daddr, iph->saddr, tpi.key);
 
 	if (t == NULL)
 		return;
@@ -578,158 +309,33 @@ static void ipgre_err(struct sk_buff *skb, u32 info)
 	t->err_time = jiffies;
 }
 
-static inline u8
-ipgre_ecn_encapsulate(u8 tos, const struct iphdr *old_iph, struct sk_buff *skb)
-{
-	u8 inner = 0;
-	if (skb->protocol == htons(ETH_P_IP))
-		inner = old_iph->tos;
-	else if (skb->protocol == htons(ETH_P_IPV6))
-		inner = ipv6_get_dsfield((const struct ipv6hdr *)old_iph);
-	return INET_ECN_encapsulate(tos, inner);
-}
-
 static int ipgre_rcv(struct sk_buff *skb)
 {
+	struct net *net = dev_net(skb->dev);
+	struct ip_tunnel_net *itn;
 	const struct iphdr *iph;
-	u8     *h;
-	__be16    flags;
-	__sum16   csum = 0;
-	__be32 key = 0;
-	u32    seqno = 0;
 	struct ip_tunnel *tunnel;
-	int    offset = 4;
-	__be16 gre_proto;
-	int    err;
+	struct tnl_ptk_info tpi;
+	int hdr_len;
+	bool csum_err = false;
 
-	if (!pskb_may_pull(skb, 16))
+	if (parse_gre_header(skb, &tpi, &csum_err, &hdr_len) < 0)
 		goto drop;
 
-	iph = ip_hdr(skb);
-	h = skb->data;
-	flags = *(__be16 *)h;
-
-	if (flags&(GRE_CSUM|GRE_KEY|GRE_ROUTING|GRE_SEQ|GRE_VERSION)) {
-		/* - Version must be 0.
-		   - We do not support routing headers.
-		 */
-		if (flags&(GRE_VERSION|GRE_ROUTING))
-			goto drop;
-
-		if (flags&GRE_CSUM) {
-			switch (skb->ip_summed) {
-			case CHECKSUM_COMPLETE:
-				csum = csum_fold(skb->csum);
-				if (!csum)
-					break;
-				/* fall through */
-			case CHECKSUM_NONE:
-				skb->csum = 0;
-				csum = __skb_checksum_complete(skb);
-				skb->ip_summed = CHECKSUM_COMPLETE;
-			}
-			offset += 4;
-		}
-		if (flags&GRE_KEY) {
-			key = *(__be32 *)(h + offset);
-			offset += 4;
-		}
-		if (flags&GRE_SEQ) {
-			seqno = ntohl(*(__be32 *)(h + offset));
-			offset += 4;
-		}
-	}
+	if (tpi.proto == htons(ETH_P_TEB))
+		itn = net_generic(net, gre_tap_net_id);
+	else
+		itn = net_generic(net, ipgre_net_id);
 
-	gre_proto = *(__be16 *)(h + 2);
+	iph = ip_hdr(skb);
+	tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi.flags,
+				  iph->saddr, iph->daddr, tpi.key);
 
-	tunnel = ipgre_tunnel_lookup(skb->dev,
-				     iph->saddr, iph->daddr, flags, key,
-				     gre_proto);
 	if (tunnel) {
-		struct pcpu_tstats *tstats;
-
-		secpath_reset(skb);
-
-		skb->protocol = gre_proto;
-		/* WCCP version 1 and 2 protocol decoding.
-		 * - Change protocol to IP
-		 * - When dealing with WCCPv2, Skip extra 4 bytes in GRE header
-		 */
-		if (flags == 0 && gre_proto == htons(ETH_P_WCCP)) {
-			skb->protocol = htons(ETH_P_IP);
-			if ((*(h + offset) & 0xF0) != 0x40)
-				offset += 4;
-		}
-
-		skb->mac_header = skb->network_header;
-		__pskb_pull(skb, offset);
-		skb_postpull_rcsum(skb, skb_transport_header(skb), offset);
-		skb->pkt_type = PACKET_HOST;
-#ifdef CONFIG_NET_IPGRE_BROADCAST
-		if (ipv4_is_multicast(iph->daddr)) {
-			/* Looped back packet, drop it! */
-			if (rt_is_output_route(skb_rtable(skb)))
-				goto drop;
-			tunnel->dev->stats.multicast++;
-			skb->pkt_type = PACKET_BROADCAST;
-		}
-#endif
-
-		if (((flags&GRE_CSUM) && csum) ||
-		    (!(flags&GRE_CSUM) && tunnel->parms.i_flags&GRE_CSUM)) {
-			tunnel->dev->stats.rx_crc_errors++;
-			tunnel->dev->stats.rx_errors++;
-			goto drop;
-		}
-		if (tunnel->parms.i_flags&GRE_SEQ) {
-			if (!(flags&GRE_SEQ) ||
-			    (tunnel->i_seqno && (s32)(seqno - tunnel->i_seqno) < 0)) {
-				tunnel->dev->stats.rx_fifo_errors++;
-				tunnel->dev->stats.rx_errors++;
-				goto drop;
-			}
-			tunnel->i_seqno = seqno + 1;
-		}
-
-		/* Warning: All skb pointers will be invalidated! */
-		if (tunnel->dev->type == ARPHRD_ETHER) {
-			if (!pskb_may_pull(skb, ETH_HLEN)) {
-				tunnel->dev->stats.rx_length_errors++;
-				tunnel->dev->stats.rx_errors++;
-				goto drop;
-			}
-
-			iph = ip_hdr(skb);
-			skb->protocol = eth_type_trans(skb, tunnel->dev);
-			skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN);
-		}
-
-		__skb_tunnel_rx(skb, tunnel->dev);
-
-		skb_reset_network_header(skb);
-		err = IP_ECN_decapsulate(iph, skb);
-		if (unlikely(err)) {
-			if (log_ecn_error)
-				net_info_ratelimited("non-ECT from %pI4 with TOS=%#x\n",
-						     &iph->saddr, iph->tos);
-			if (err > 1) {
-				++tunnel->dev->stats.rx_frame_errors;
-				++tunnel->dev->stats.rx_errors;
-				goto drop;
-			}
-		}
-
-		tstats = this_cpu_ptr(tunnel->dev->tstats);
-		u64_stats_update_begin(&tstats->syncp);
-		tstats->rx_packets++;
-		tstats->rx_bytes += skb->len;
-		u64_stats_update_end(&tstats->syncp);
-
-		gro_cells_receive(&tunnel->gro_cells, skb);
+		ip_tunnel_rcv(tunnel, skb, &tpi, log_ecn_error);
 		return 0;
 	}
 	icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
-
 drop:
 	kfree_skb(skb);
 	return 0;
@@ -746,7 +352,7 @@ static struct sk_buff *handle_offloads(struct ip_tunnel *tunnel, struct sk_buff
 		skb_shinfo(skb)->gso_type |= SKB_GSO_GRE;
 		return skb;
 	} else if (skb->ip_summed == CHECKSUM_PARTIAL &&
-		   tunnel->parms.o_flags&GRE_CSUM) {
+		   tunnel->parms.o_flags&TUNNEL_CSUM) {
 		err = skb_checksum_help(skb);
 		if (unlikely(err))
 			goto error;
@@ -760,494 +366,157 @@ error:
 	return ERR_PTR(err);
 }
 
-static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
+static struct sk_buff *gre_build_header(struct sk_buff *skb,
+					const struct tnl_ptk_info *tpi,
+					int hdr_len)
 {
-	struct pcpu_tstats *tstats = this_cpu_ptr(dev->tstats);
-	struct ip_tunnel *tunnel = netdev_priv(dev);
-	const struct iphdr  *old_iph;
-	const struct iphdr  *tiph;
-	struct flowi4 fl4;
-	u8     tos;
-	__be16 df;
-	struct rtable *rt;     			/* Route to the other host */
-	struct net_device *tdev;		/* Device to other host */
-	struct iphdr  *iph;			/* Our new IP header */
-	unsigned int max_headroom;		/* The extra header space needed */
-	int    gre_hlen;
-	__be32 dst;
-	int    mtu;
-	u8     ttl;
-	int    err;
-	int    pkt_len;
-
-	skb = handle_offloads(tunnel, skb);
-	if (IS_ERR(skb)) {
-		dev->stats.tx_dropped++;
-		return NETDEV_TX_OK;
-	}
+	struct gre_base_hdr *greh;
 
-	if (!skb->encapsulation) {
-		skb_reset_inner_headers(skb);
-		skb->encapsulation = 1;
-	}
+	skb_push(skb, hdr_len);
 
-	old_iph = ip_hdr(skb);
+	greh = (struct gre_base_hdr *)skb->data;
+	greh->flags = tnl_flags_to_gre_flags(tpi->flags);
+	greh->protocol = tpi->proto;
 
-	if (dev->type == ARPHRD_ETHER)
-		IPCB(skb)->flags = 0;
+	if (tpi->flags&(TUNNEL_KEY|TUNNEL_CSUM|TUNNEL_SEQ)) {
+		__be32 *ptr = (__be32 *)(((u8 *)greh) + hdr_len - 4);
 
-	if (dev->header_ops && dev->type == ARPHRD_IPGRE) {
-		gre_hlen = 0;
-		tiph = (const struct iphdr *)skb->data;
-	} else {
-		gre_hlen = tunnel->hlen;
-		tiph = &tunnel->parms.iph;
-	}
-
-	if ((dst = tiph->daddr) == 0) {
-		/* NBMA tunnel */
-
-		if (skb_dst(skb) == NULL) {
-			dev->stats.tx_fifo_errors++;
-			goto tx_error;
+		if (tpi->flags&TUNNEL_SEQ) {
+			*ptr = tpi->seq;
+			ptr--;
 		}
-
-		if (skb->protocol == htons(ETH_P_IP)) {
-			rt = skb_rtable(skb);
-			dst = rt_nexthop(rt, old_iph->daddr);
+		if (tpi->flags&TUNNEL_KEY) {
+			*ptr = tpi->key;
+			ptr--;
 		}
-#if IS_ENABLED(CONFIG_IPV6)
-		else if (skb->protocol == htons(ETH_P_IPV6)) {
-			const struct in6_addr *addr6;
-			struct neighbour *neigh;
-			bool do_tx_error_icmp;
-			int addr_type;
-
-			neigh = dst_neigh_lookup(skb_dst(skb), &ipv6_hdr(skb)->daddr);
-			if (neigh == NULL)
-				goto tx_error;
-
-			addr6 = (const struct in6_addr *)&neigh->primary_key;
-			addr_type = ipv6_addr_type(addr6);
-
-			if (addr_type == IPV6_ADDR_ANY) {
-				addr6 = &ipv6_hdr(skb)->daddr;
-				addr_type = ipv6_addr_type(addr6);
-			}
-
-			if ((addr_type & IPV6_ADDR_COMPATv4) == 0)
-				do_tx_error_icmp = true;
-			else {
-				do_tx_error_icmp = false;
-				dst = addr6->s6_addr32[3];
-			}
-			neigh_release(neigh);
-			if (do_tx_error_icmp)
-				goto tx_error_icmp;
+		if (tpi->flags&TUNNEL_CSUM &&
+		    !(skb_shinfo(skb)->gso_type & SKB_GSO_GRE)) {
+			*(__sum16 *)ptr = 0;
+			*(__sum16 *)ptr = csum_fold(skb_checksum(skb, 0,
+								 skb->len, 0));
 		}
-#endif
-		else
-			goto tx_error;
 	}
 
-	ttl = tiph->ttl;
-	tos = tiph->tos;
-	if (tos & 0x1) {
-		tos &= ~0x1;
-		if (skb->protocol == htons(ETH_P_IP))
-			tos = old_iph->tos;
-		else if (skb->protocol == htons(ETH_P_IPV6))
-			tos = ipv6_get_dsfield((const struct ipv6hdr *)old_iph);
-	}
+	return skb;
+}
 
-	rt = ip_route_output_gre(dev_net(dev), &fl4, dst, tiph->saddr,
-				 tunnel->parms.o_key, RT_TOS(tos),
-				 tunnel->parms.link);
-	if (IS_ERR(rt)) {
-		dev->stats.tx_carrier_errors++;
-		goto tx_error;
-	}
-	tdev = rt->dst.dev;
+static void __gre_xmit(struct sk_buff *skb, struct net_device *dev,
+		       const struct iphdr *tnl_params,
+		       __be16 proto)
+{
+	struct ip_tunnel *tunnel = netdev_priv(dev);
+	struct tnl_ptk_info tpi;
 
-	if (tdev == dev) {
-		ip_rt_put(rt);
-		dev->stats.collisions++;
-		goto tx_error;
+	if (likely(!skb->encapsulation)) {
+		skb_reset_inner_headers(skb);
+		skb->encapsulation = 1;
 	}
 
-	df = tiph->frag_off;
-	if (df)
-		mtu = dst_mtu(&rt->dst) - dev->hard_header_len - tunnel->hlen;
-	else
-		mtu = skb_dst(skb) ? dst_mtu(skb_dst(skb)) : dev->mtu;
-
-	if (skb_dst(skb))
-		skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu);
-
-	if (skb->protocol == htons(ETH_P_IP)) {
-		df |= (old_iph->frag_off&htons(IP_DF));
+	tpi.flags = tunnel->parms.o_flags;
+	tpi.proto = proto;
+	tpi.key = tunnel->parms.o_key;
+	if (tunnel->parms.o_flags & TUNNEL_SEQ)
+		tunnel->o_seqno++;
+	tpi.seq = htonl(tunnel->o_seqno);
 
-		if (!skb_is_gso(skb) &&
-		    (old_iph->frag_off&htons(IP_DF)) &&
-		    mtu < ntohs(old_iph->tot_len)) {
-			icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu));
-			ip_rt_put(rt);
-			goto tx_error;
-		}
+	/* Push GRE header. */
+	skb = gre_build_header(skb, &tpi, tunnel->hlen);
+	if (unlikely(!skb)) {
+		dev->stats.tx_dropped++;
+		return;
 	}
-#if IS_ENABLED(CONFIG_IPV6)
-	else if (skb->protocol == htons(ETH_P_IPV6)) {
-		struct rt6_info *rt6 = (struct rt6_info *)skb_dst(skb);
-
-		if (rt6 && mtu < dst_mtu(skb_dst(skb)) && mtu >= IPV6_MIN_MTU) {
-			if ((tunnel->parms.iph.daddr &&
-			     !ipv4_is_multicast(tunnel->parms.iph.daddr)) ||
-			    rt6->rt6i_dst.plen == 128) {
-				rt6->rt6i_flags |= RTF_MODIFIED;
-				dst_metric_set(skb_dst(skb), RTAX_MTU, mtu);
-			}
-		}
 
-		if (!skb_is_gso(skb) &&
-		    mtu >= IPV6_MIN_MTU &&
-		    mtu < skb->len - tunnel->hlen + gre_hlen) {
-			icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
-			ip_rt_put(rt);
-			goto tx_error;
-		}
-	}
-#endif
+	ip_tunnel_xmit(skb, dev, tnl_params);
+}
 
-	if (tunnel->err_count > 0) {
-		if (time_before(jiffies,
-				tunnel->err_time + IPTUNNEL_ERR_TIMEO)) {
-			tunnel->err_count--;
+static netdev_tx_t ipgre_xmit(struct sk_buff *skb,
+			      struct net_device *dev)
+{
+	struct ip_tunnel *tunnel = netdev_priv(dev);
+	const struct iphdr *tnl_params;
 
-			dst_link_failure(skb);
-		} else
-			tunnel->err_count = 0;
-	}
+	skb = handle_offloads(tunnel, skb);
+	if (IS_ERR(skb))
+		goto out;
 
-	max_headroom = LL_RESERVED_SPACE(tdev) + gre_hlen + rt->dst.header_len;
-
-	if (skb_headroom(skb) < max_headroom || skb_shared(skb)||
-	    (skb_cloned(skb) && !skb_clone_writable(skb, 0))) {
-		struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom);
-		if (max_headroom > dev->needed_headroom)
-			dev->needed_headroom = max_headroom;
-		if (!new_skb) {
-			ip_rt_put(rt);
-			dev->stats.tx_dropped++;
-			dev_kfree_skb(skb);
-			return NETDEV_TX_OK;
-		}
-		if (skb->sk)
-			skb_set_owner_w(new_skb, skb->sk);
-		dev_kfree_skb(skb);
-		skb = new_skb;
-		old_iph = ip_hdr(skb);
-		/* Warning : tiph value might point to freed memory */
-	}
+	if (dev->header_ops) {
+		/* Need space for new headers */
+		if (skb_cow_head(skb, dev->needed_headroom -
+				      (tunnel->hlen + sizeof(struct iphdr))));
+			goto free_skb;
 
-	skb_push(skb, gre_hlen);
-	skb_reset_network_header(skb);
-	skb_set_transport_header(skb, sizeof(*iph));
-	memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
-	IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED |
-			      IPSKB_REROUTED);
-	skb_dst_drop(skb);
-	skb_dst_set(skb, &rt->dst);
-
-	/*
-	 *	Push down and install the IPIP header.
-	 */
+		tnl_params = (const struct iphdr *)skb->data;
 
-	iph 			=	ip_hdr(skb);
-	iph->version		=	4;
-	iph->ihl		=	sizeof(struct iphdr) >> 2;
-	iph->frag_off		=	df;
-	iph->protocol		=	IPPROTO_GRE;
-	iph->tos		=	ipgre_ecn_encapsulate(tos, old_iph, skb);
-	iph->daddr		=	fl4.daddr;
-	iph->saddr		=	fl4.saddr;
-	iph->ttl		=	ttl;
-
-	tunnel_ip_select_ident(skb, old_iph, &rt->dst);
-
-	if (ttl == 0) {
-		if (skb->protocol == htons(ETH_P_IP))
-			iph->ttl = old_iph->ttl;
-#if IS_ENABLED(CONFIG_IPV6)
-		else if (skb->protocol == htons(ETH_P_IPV6))
-			iph->ttl = ((const struct ipv6hdr *)old_iph)->hop_limit;
-#endif
-		else
-			iph->ttl = ip4_dst_hoplimit(&rt->dst);
-	}
-
-	((__be16 *)(iph + 1))[0] = tunnel->parms.o_flags;
-	((__be16 *)(iph + 1))[1] = (dev->type == ARPHRD_ETHER) ?
-				   htons(ETH_P_TEB) : skb->protocol;
-
-	if (tunnel->parms.o_flags&(GRE_KEY|GRE_CSUM|GRE_SEQ)) {
-		__be32 *ptr = (__be32 *)(((u8 *)iph) + tunnel->hlen - 4);
+		/* Pull skb since ip_tunnel_xmit() needs skb->data pointing
+		 * to gre header.
+		 */
+		skb_pull(skb, tunnel->hlen + sizeof(struct iphdr));
+	} else {
+		if (skb_cow_head(skb, dev->needed_headroom))
+			goto free_skb;
 
-		if (tunnel->parms.o_flags&GRE_SEQ) {
-			++tunnel->o_seqno;
-			*ptr = htonl(tunnel->o_seqno);
-			ptr--;
-		}
-		if (tunnel->parms.o_flags&GRE_KEY) {
-			*ptr = tunnel->parms.o_key;
-			ptr--;
-		}
-		/* Skip GRE checksum if skb is getting offloaded. */
-		if (!(skb_shinfo(skb)->gso_type & SKB_GSO_GRE) &&
-		    (tunnel->parms.o_flags&GRE_CSUM)) {
-			int offset = skb_transport_offset(skb);
-
-			if (skb_has_shared_frag(skb)) {
-				err = __skb_linearize(skb);
-				if (err)
-					goto tx_error;
-			}
-
-			*ptr = 0;
-			*(__sum16 *)ptr = csum_fold(skb_checksum(skb, offset,
-								 skb->len - offset,
-								 0));
-		}
+		tnl_params = &tunnel->parms.iph;
 	}
 
-	nf_reset(skb);
+	__gre_xmit(skb, dev, tnl_params, skb->protocol);
 
-	pkt_len = skb->len - skb_transport_offset(skb);
-	err = ip_local_out(skb);
-	if (likely(net_xmit_eval(err) == 0)) {
-		u64_stats_update_begin(&tstats->syncp);
-		tstats->tx_bytes += pkt_len;
-		tstats->tx_packets++;
-		u64_stats_update_end(&tstats->syncp);
-	} else {
-		dev->stats.tx_errors++;
-		dev->stats.tx_aborted_errors++;
-	}
 	return NETDEV_TX_OK;
 
-#if IS_ENABLED(CONFIG_IPV6)
-tx_error_icmp:
-	dst_link_failure(skb);
-#endif
-tx_error:
-	dev->stats.tx_errors++;
+free_skb:
 	dev_kfree_skb(skb);
+out:
+	dev->stats.tx_dropped++;
 	return NETDEV_TX_OK;
 }
 
-static int ipgre_tunnel_bind_dev(struct net_device *dev)
+static netdev_tx_t gre_tap_xmit(struct sk_buff *skb,
+				struct net_device *dev)
 {
-	struct net_device *tdev = NULL;
-	struct ip_tunnel *tunnel;
-	const struct iphdr *iph;
-	int hlen = LL_MAX_HEADER;
-	int mtu = ETH_DATA_LEN;
-	int addend = sizeof(struct iphdr) + 4;
-
-	tunnel = netdev_priv(dev);
-	iph = &tunnel->parms.iph;
-
-	/* Guess output device to choose reasonable mtu and needed_headroom */
-
-	if (iph->daddr) {
-		struct flowi4 fl4;
-		struct rtable *rt;
-
-		rt = ip_route_output_gre(dev_net(dev), &fl4,
-					 iph->daddr, iph->saddr,
-					 tunnel->parms.o_key,
-					 RT_TOS(iph->tos),
-					 tunnel->parms.link);
-		if (!IS_ERR(rt)) {
-			tdev = rt->dst.dev;
-			ip_rt_put(rt);
-		}
-
-		if (dev->type != ARPHRD_ETHER)
-			dev->flags |= IFF_POINTOPOINT;
-	}
+	struct ip_tunnel *tunnel = netdev_priv(dev);
 
-	if (!tdev && tunnel->parms.link)
-		tdev = __dev_get_by_index(dev_net(dev), tunnel->parms.link);
+	skb = handle_offloads(tunnel, skb);
+	if (IS_ERR(skb))
+		goto out;
 
-	if (tdev) {
-		hlen = tdev->hard_header_len + tdev->needed_headroom;
-		mtu = tdev->mtu;
-	}
-	dev->iflink = tunnel->parms.link;
-
-	/* Precalculate GRE options length */
-	if (tunnel->parms.o_flags&(GRE_CSUM|GRE_KEY|GRE_SEQ)) {
-		if (tunnel->parms.o_flags&GRE_CSUM)
-			addend += 4;
-		if (tunnel->parms.o_flags&GRE_KEY)
-			addend += 4;
-		if (tunnel->parms.o_flags&GRE_SEQ)
-			addend += 4;
-	}
-	dev->needed_headroom = addend + hlen;
-	mtu -= dev->hard_header_len + addend;
+	if (skb_cow_head(skb, dev->needed_headroom))
+		goto free_skb;
 
-	if (mtu < 68)
-		mtu = 68;
+	__gre_xmit(skb, dev, &tunnel->parms.iph, htons(ETH_P_TEB));
 
-	tunnel->hlen = addend;
-	/* TCP offload with GRE SEQ is not supported. */
-	if (!(tunnel->parms.o_flags & GRE_SEQ)) {
-		dev->features		|= NETIF_F_GSO_SOFTWARE;
-		dev->hw_features	|= NETIF_F_GSO_SOFTWARE;
-	}
+	return NETDEV_TX_OK;
 
-	return mtu;
+free_skb:
+	dev_kfree_skb(skb);
+out:
+	dev->stats.tx_dropped++;
+	return NETDEV_TX_OK;
 }
 
-static int
-ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
+static int ipgre_tunnel_ioctl(struct net_device *dev,
+			      struct ifreq *ifr, int cmd)
 {
 	int err = 0;
 	struct ip_tunnel_parm p;
-	struct ip_tunnel *t;
-	struct net *net = dev_net(dev);
-	struct ipgre_net *ign = net_generic(net, ipgre_net_id);
-
-	switch (cmd) {
-	case SIOCGETTUNNEL:
-		t = NULL;
-		if (dev == ign->fb_tunnel_dev) {
-			if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) {
-				err = -EFAULT;
-				break;
-			}
-			t = ipgre_tunnel_locate(net, &p, 0);
-		}
-		if (t == NULL)
-			t = netdev_priv(dev);
-		memcpy(&p, &t->parms, sizeof(p));
-		if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p)))
-			err = -EFAULT;
-		break;
-
-	case SIOCADDTUNNEL:
-	case SIOCCHGTUNNEL:
-		err = -EPERM;
-		if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
-			goto done;
-
-		err = -EFAULT;
-		if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
-			goto done;
-
-		err = -EINVAL;
-		if (p.iph.version != 4 || p.iph.protocol != IPPROTO_GRE ||
-		    p.iph.ihl != 5 || (p.iph.frag_off&htons(~IP_DF)) ||
-		    ((p.i_flags|p.o_flags)&(GRE_VERSION|GRE_ROUTING)))
-			goto done;
-		if (p.iph.ttl)
-			p.iph.frag_off |= htons(IP_DF);
-
-		if (!(p.i_flags&GRE_KEY))
-			p.i_key = 0;
-		if (!(p.o_flags&GRE_KEY))
-			p.o_key = 0;
-
-		t = ipgre_tunnel_locate(net, &p, cmd == SIOCADDTUNNEL);
-
-		if (dev != ign->fb_tunnel_dev && cmd == SIOCCHGTUNNEL) {
-			if (t != NULL) {
-				if (t->dev != dev) {
-					err = -EEXIST;
-					break;
-				}
-			} else {
-				unsigned int nflags = 0;
-
-				t = netdev_priv(dev);
-
-				if (ipv4_is_multicast(p.iph.daddr))
-					nflags = IFF_BROADCAST;
-				else if (p.iph.daddr)
-					nflags = IFF_POINTOPOINT;
-
-				if ((dev->flags^nflags)&(IFF_POINTOPOINT|IFF_BROADCAST)) {
-					err = -EINVAL;
-					break;
-				}
-				ipgre_tunnel_unlink(ign, t);
-				synchronize_net();
-				t->parms.iph.saddr = p.iph.saddr;
-				t->parms.iph.daddr = p.iph.daddr;
-				t->parms.i_key = p.i_key;
-				t->parms.o_key = p.o_key;
-				memcpy(dev->dev_addr, &p.iph.saddr, 4);
-				memcpy(dev->broadcast, &p.iph.daddr, 4);
-				ipgre_tunnel_link(ign, t);
-				netdev_state_change(dev);
-			}
-		}
-
-		if (t) {
-			err = 0;
-			if (cmd == SIOCCHGTUNNEL) {
-				t->parms.iph.ttl = p.iph.ttl;
-				t->parms.iph.tos = p.iph.tos;
-				t->parms.iph.frag_off = p.iph.frag_off;
-				if (t->parms.link != p.link) {
-					t->parms.link = p.link;
-					dev->mtu = ipgre_tunnel_bind_dev(dev);
-					netdev_state_change(dev);
-				}
-			}
-			if (copy_to_user(ifr->ifr_ifru.ifru_data, &t->parms, sizeof(p)))
-				err = -EFAULT;
-		} else
-			err = (cmd == SIOCADDTUNNEL ? -ENOBUFS : -ENOENT);
-		break;
-
-	case SIOCDELTUNNEL:
-		err = -EPERM;
-		if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
-			goto done;
-
-		if (dev == ign->fb_tunnel_dev) {
-			err = -EFAULT;
-			if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
-				goto done;
-			err = -ENOENT;
-			if ((t = ipgre_tunnel_locate(net, &p, 0)) == NULL)
-				goto done;
-			err = -EPERM;
-			if (t == netdev_priv(ign->fb_tunnel_dev))
-				goto done;
-			dev = t->dev;
-		}
-		unregister_netdevice(dev);
-		err = 0;
-		break;
 
-	default:
-		err = -EINVAL;
+	if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
+		return -EFAULT;
+	if (p.iph.version != 4 || p.iph.protocol != IPPROTO_GRE ||
+	    p.iph.ihl != 5 || (p.iph.frag_off&htons(~IP_DF)) ||
+	    ((p.i_flags|p.o_flags)&(GRE_VERSION|GRE_ROUTING))) {
+		return -EINVAL;
 	}
+	p.i_flags = gre_flags_to_tnl_flags(p.i_flags);
+	p.o_flags = gre_flags_to_tnl_flags(p.o_flags);
 
-done:
-	return err;
-}
+	err = ip_tunnel_ioctl(dev, &p, cmd);
+	if (err)
+		return err;
 
-static int ipgre_tunnel_change_mtu(struct net_device *dev, int new_mtu)
-{
-	struct ip_tunnel *tunnel = netdev_priv(dev);
-	if (new_mtu < 68 ||
-	    new_mtu > 0xFFF8 - dev->hard_header_len - tunnel->hlen)
-		return -EINVAL;
-	dev->mtu = new_mtu;
+	p.i_flags = tnl_flags_to_gre_flags(p.i_flags);
+	p.o_flags = tnl_flags_to_gre_flags(p.o_flags);
+
+	if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p)))
+		return -EFAULT;
 	return 0;
 }
 
@@ -1277,25 +546,23 @@ static int ipgre_tunnel_change_mtu(struct net_device *dev, int new_mtu)
    ...
    ftp fec0:6666:6666::193.233.7.65
    ...
-
  */
-
 static int ipgre_header(struct sk_buff *skb, struct net_device *dev,
 			unsigned short type,
 			const void *daddr, const void *saddr, unsigned int len)
 {
 	struct ip_tunnel *t = netdev_priv(dev);
-	struct iphdr *iph = (struct iphdr *)skb_push(skb, t->hlen);
-	__be16 *p = (__be16 *)(iph+1);
+	struct iphdr *iph;
+	struct gre_base_hdr *greh;
 
-	memcpy(iph, &t->parms.iph, sizeof(struct iphdr));
-	p[0]		= t->parms.o_flags;
-	p[1]		= htons(type);
+	iph = (struct iphdr *)skb_push(skb, t->hlen + sizeof(*iph));
+	greh = (struct gre_base_hdr *)(iph+1);
+	greh->flags = tnl_flags_to_gre_flags(t->parms.o_flags);
+	greh->protocol = htons(type);
 
-	/*
-	 *	Set the source hardware address.
-	 */
+	memcpy(iph, &t->parms.iph, sizeof(struct iphdr));
 
+	/* Set the source hardware address. */
 	if (saddr)
 		memcpy(&iph->saddr, saddr, 4);
 	if (daddr)
@@ -1303,7 +570,7 @@ static int ipgre_header(struct sk_buff *skb, struct net_device *dev,
 	if (iph->daddr)
 		return t->hlen;
 
-	return -t->hlen;
+	return -(t->hlen + sizeof(*iph));
 }
 
 static int ipgre_header_parse(const struct sk_buff *skb, unsigned char *haddr)
@@ -1357,31 +624,21 @@ static int ipgre_close(struct net_device *dev)
 	}
 	return 0;
 }
-
 #endif
 
 static const struct net_device_ops ipgre_netdev_ops = {
 	.ndo_init		= ipgre_tunnel_init,
-	.ndo_uninit		= ipgre_tunnel_uninit,
+	.ndo_uninit		= ip_tunnel_uninit,
 #ifdef CONFIG_NET_IPGRE_BROADCAST
 	.ndo_open		= ipgre_open,
 	.ndo_stop		= ipgre_close,
 #endif
-	.ndo_start_xmit		= ipgre_tunnel_xmit,
+	.ndo_start_xmit		= ipgre_xmit,
 	.ndo_do_ioctl		= ipgre_tunnel_ioctl,
-	.ndo_change_mtu		= ipgre_tunnel_change_mtu,
-	.ndo_get_stats64	= ipgre_get_stats64,
+	.ndo_change_mtu		= ip_tunnel_change_mtu,
+	.ndo_get_stats64	= ip_tunnel_get_stats64,
 };
 
-static void ipgre_dev_free(struct net_device *dev)
-{
-	struct ip_tunnel *tunnel = netdev_priv(dev);
-
-	gro_cells_destroy(&tunnel->gro_cells);
-	free_percpu(dev->tstats);
-	free_netdev(dev);
-}
-
 #define GRE_FEATURES (NETIF_F_SG |		\
 		      NETIF_F_FRAGLIST |	\
 		      NETIF_F_HIGHDMA |		\
@@ -1390,35 +647,48 @@ static void ipgre_dev_free(struct net_device *dev)
 static void ipgre_tunnel_setup(struct net_device *dev)
 {
 	dev->netdev_ops		= &ipgre_netdev_ops;
-	dev->destructor 	= ipgre_dev_free;
+	ip_tunnel_setup(dev, ipgre_net_id);
+}
 
-	dev->type		= ARPHRD_IPGRE;
-	dev->needed_headroom 	= LL_MAX_HEADER + sizeof(struct iphdr) + 4;
+static void __gre_tunnel_init(struct net_device *dev)
+{
+	struct ip_tunnel *tunnel;
+
+	tunnel = netdev_priv(dev);
+	tunnel->hlen = ip_gre_calc_hlen(tunnel->parms.o_flags);
+	tunnel->parms.iph.protocol = IPPROTO_GRE;
+
+	dev->needed_headroom	= LL_MAX_HEADER + sizeof(struct iphdr) + 4;
 	dev->mtu		= ETH_DATA_LEN - sizeof(struct iphdr) - 4;
-	dev->flags		= IFF_NOARP;
-	dev->iflink		= 0;
-	dev->addr_len		= 4;
-	dev->features		|= NETIF_F_NETNS_LOCAL;
-	dev->priv_flags		&= ~IFF_XMIT_DST_RELEASE;
 
-	dev->features		|= GRE_FEATURES;
+	dev->features		|= NETIF_F_NETNS_LOCAL | GRE_FEATURES;
 	dev->hw_features	|= GRE_FEATURES;
+
+	if (!(tunnel->parms.o_flags & TUNNEL_SEQ)) {
+		/* TCP offload with GRE SEQ is not supported. */
+		dev->features    |= NETIF_F_GSO_SOFTWARE;
+		dev->hw_features |= NETIF_F_GSO_SOFTWARE;
+		/* Can use a lockless transmit, unless we generate
+		 * output sequences
+		 */
+		dev->features |= NETIF_F_LLTX;
+	}
 }
 
 static int ipgre_tunnel_init(struct net_device *dev)
 {
-	struct ip_tunnel *tunnel;
-	struct iphdr *iph;
-	int err;
+	struct ip_tunnel *tunnel = netdev_priv(dev);
+	struct iphdr *iph = &tunnel->parms.iph;
 
-	tunnel = netdev_priv(dev);
-	iph = &tunnel->parms.iph;
+	__gre_tunnel_init(dev);
 
-	tunnel->dev = dev;
-	strcpy(tunnel->parms.name, dev->name);
+	memcpy(dev->dev_addr, &iph->saddr, 4);
+	memcpy(dev->broadcast, &iph->daddr, 4);
 
-	memcpy(dev->dev_addr, &tunnel->parms.iph.saddr, 4);
-	memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4);
+	dev->type		= ARPHRD_IPGRE;
+	dev->flags		= IFF_NOARP;
+	dev->priv_flags		&= ~IFF_XMIT_DST_RELEASE;
+	dev->addr_len		= 4;
 
 	if (iph->daddr) {
 #ifdef CONFIG_NET_IPGRE_BROADCAST
@@ -1432,106 +702,30 @@ static int ipgre_tunnel_init(struct net_device *dev)
 	} else
 		dev->header_ops = &ipgre_header_ops;
 
-	dev->tstats = alloc_percpu(struct pcpu_tstats);
-	if (!dev->tstats)
-		return -ENOMEM;
-
-	err = gro_cells_init(&tunnel->gro_cells, dev);
-	if (err) {
-		free_percpu(dev->tstats);
-		return err;
-	}
-
-	return 0;
-}
-
-static void ipgre_fb_tunnel_init(struct net_device *dev)
-{
-	struct ip_tunnel *tunnel = netdev_priv(dev);
-	struct iphdr *iph = &tunnel->parms.iph;
-
-	tunnel->dev = dev;
-	strcpy(tunnel->parms.name, dev->name);
-
-	iph->version		= 4;
-	iph->protocol		= IPPROTO_GRE;
-	iph->ihl		= 5;
-	tunnel->hlen		= sizeof(struct iphdr) + 4;
-
-	dev_hold(dev);
+	return ip_tunnel_init(dev);
 }
 
-
 static const struct gre_protocol ipgre_protocol = {
 	.handler     = ipgre_rcv,
 	.err_handler = ipgre_err,
 };
 
-static void ipgre_destroy_tunnels(struct ipgre_net *ign, struct list_head *head)
-{
-	int prio;
-
-	for (prio = 0; prio < 4; prio++) {
-		int h;
-		for (h = 0; h < HASH_SIZE; h++) {
-			struct ip_tunnel *t;
-
-			t = rtnl_dereference(ign->tunnels[prio][h]);
-
-			while (t != NULL) {
-				unregister_netdevice_queue(t->dev, head);
-				t = rtnl_dereference(t->next);
-			}
-		}
-	}
-}
-
 static int __net_init ipgre_init_net(struct net *net)
 {
-	struct ipgre_net *ign = net_generic(net, ipgre_net_id);
-	int err;
-
-	ign->fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel), "gre0",
-					   ipgre_tunnel_setup);
-	if (!ign->fb_tunnel_dev) {
-		err = -ENOMEM;
-		goto err_alloc_dev;
-	}
-	dev_net_set(ign->fb_tunnel_dev, net);
-
-	ipgre_fb_tunnel_init(ign->fb_tunnel_dev);
-	ign->fb_tunnel_dev->rtnl_link_ops = &ipgre_link_ops;
-
-	if ((err = register_netdev(ign->fb_tunnel_dev)))
-		goto err_reg_dev;
-
-	rcu_assign_pointer(ign->tunnels_wc[0],
-			   netdev_priv(ign->fb_tunnel_dev));
-	return 0;
-
-err_reg_dev:
-	ipgre_dev_free(ign->fb_tunnel_dev);
-err_alloc_dev:
-	return err;
+	return ip_tunnel_init_net(net, ipgre_net_id, &ipgre_link_ops, NULL);
 }
 
 static void __net_exit ipgre_exit_net(struct net *net)
 {
-	struct ipgre_net *ign;
-	LIST_HEAD(list);
-
-	ign = net_generic(net, ipgre_net_id);
-	rtnl_lock();
-	ipgre_destroy_tunnels(ign, &list);
-	unregister_netdevice_many(&list);
-	rtnl_unlock();
+	struct ip_tunnel_net *itn = net_generic(net, ipgre_net_id);
+	ip_tunnel_delete_net(itn);
 }
 
 static struct pernet_operations ipgre_net_ops = {
 	.init = ipgre_init_net,
 	.exit = ipgre_exit_net,
 	.id   = &ipgre_net_id,
-	.size = sizeof(struct ipgre_net),
+	.size = sizeof(struct ip_tunnel_net),
 };
 
 static int ipgre_tunnel_validate(struct nlattr *tb[], struct nlattr *data[])
@@ -1576,8 +770,8 @@ out:
 	return ipgre_tunnel_validate(tb, data);
 }
 
-static void ipgre_netlink_parms(struct nlattr *data[],
-				struct ip_tunnel_parm *parms)
+static void ipgre_netlink_parms(struct nlattr *data[], struct nlattr *tb[],
+			       struct ip_tunnel_parm *parms)
 {
 	memset(parms, 0, sizeof(*parms));
 
@@ -1590,10 +784,10 @@ static void ipgre_netlink_parms(struct nlattr *data[],
 		parms->link = nla_get_u32(data[IFLA_GRE_LINK]);
 
 	if (data[IFLA_GRE_IFLAGS])
-		parms->i_flags = nla_get_be16(data[IFLA_GRE_IFLAGS]);
+		parms->i_flags = gre_flags_to_tnl_flags(nla_get_be16(data[IFLA_GRE_IFLAGS]));
 
 	if (data[IFLA_GRE_OFLAGS])
-		parms->o_flags = nla_get_be16(data[IFLA_GRE_OFLAGS]);
+		parms->o_flags = gre_flags_to_tnl_flags(nla_get_be16(data[IFLA_GRE_OFLAGS]));
 
 	if (data[IFLA_GRE_IKEY])
 		parms->i_key = nla_get_be32(data[IFLA_GRE_IKEY]);
@@ -1617,148 +811,46 @@ static void ipgre_netlink_parms(struct nlattr *data[],
 		parms->iph.frag_off = htons(IP_DF);
 }
 
-static int ipgre_tap_init(struct net_device *dev)
+static int gre_tap_init(struct net_device *dev)
 {
-	struct ip_tunnel *tunnel;
-
-	tunnel = netdev_priv(dev);
-
-	tunnel->dev = dev;
-	strcpy(tunnel->parms.name, dev->name);
+	__gre_tunnel_init(dev);
 
-	ipgre_tunnel_bind_dev(dev);
-
-	dev->tstats = alloc_percpu(struct pcpu_tstats);
-	if (!dev->tstats)
-		return -ENOMEM;
-
-	return 0;
+	return ip_tunnel_init(dev);
 }
 
-static const struct net_device_ops ipgre_tap_netdev_ops = {
-	.ndo_init		= ipgre_tap_init,
-	.ndo_uninit		= ipgre_tunnel_uninit,
-	.ndo_start_xmit		= ipgre_tunnel_xmit,
+static const struct net_device_ops gre_tap_netdev_ops = {
+	.ndo_init		= gre_tap_init,
+	.ndo_uninit		= ip_tunnel_uninit,
+	.ndo_start_xmit		= gre_tap_xmit,
 	.ndo_set_mac_address 	= eth_mac_addr,
 	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_change_mtu		= ipgre_tunnel_change_mtu,
-	.ndo_get_stats64	= ipgre_get_stats64,
+	.ndo_change_mtu		= ip_tunnel_change_mtu,
+	.ndo_get_stats64	= ip_tunnel_get_stats64,
 };
 
 static void ipgre_tap_setup(struct net_device *dev)
 {
-
 	ether_setup(dev);
-
-	dev->netdev_ops		= &ipgre_tap_netdev_ops;
-	dev->destructor 	= ipgre_dev_free;
-
-	dev->iflink		= 0;
-	dev->features		|= NETIF_F_NETNS_LOCAL;
-
-	dev->features		|= GRE_FEATURES;
-	dev->hw_features	|= GRE_FEATURES;
+	dev->netdev_ops		= &gre_tap_netdev_ops;
+	ip_tunnel_setup(dev, gre_tap_net_id);
 }
 
-static int ipgre_newlink(struct net *src_net, struct net_device *dev, struct nlattr *tb[],
-			 struct nlattr *data[])
+static int ipgre_newlink(struct net *src_net, struct net_device *dev,
+			 struct nlattr *tb[], struct nlattr *data[])
 {
-	struct ip_tunnel *nt;
-	struct net *net = dev_net(dev);
-	struct ipgre_net *ign = net_generic(net, ipgre_net_id);
-	int mtu;
-	int err;
-
-	nt = netdev_priv(dev);
-	ipgre_netlink_parms(data, &nt->parms);
-
-	if (ipgre_tunnel_find(net, &nt->parms, dev->type))
-		return -EEXIST;
-
-	if (dev->type == ARPHRD_ETHER && !tb[IFLA_ADDRESS])
-		eth_hw_addr_random(dev);
-
-	mtu = ipgre_tunnel_bind_dev(dev);
-	if (!tb[IFLA_MTU])
-		dev->mtu = mtu;
-
-	/* Can use a lockless transmit, unless we generate output sequences */
-	if (!(nt->parms.o_flags & GRE_SEQ))
-		dev->features |= NETIF_F_LLTX;
-
-	err = register_netdevice(dev);
-	if (err)
-		goto out;
-
-	dev_hold(dev);
-	ipgre_tunnel_link(ign, nt);
+	struct ip_tunnel_parm p;
 
-out:
-	return err;
+	ipgre_netlink_parms(data, tb, &p);
+	return ip_tunnel_newlink(dev, tb, &p);
 }
 
 static int ipgre_changelink(struct net_device *dev, struct nlattr *tb[],
 			    struct nlattr *data[])
 {
-	struct ip_tunnel *t, *nt;
-	struct net *net = dev_net(dev);
-	struct ipgre_net *ign = net_generic(net, ipgre_net_id);
 	struct ip_tunnel_parm p;
-	int mtu;
-
-	if (dev == ign->fb_tunnel_dev)
-		return -EINVAL;
-
-	nt = netdev_priv(dev);
-	ipgre_netlink_parms(data, &p);
-
-	t = ipgre_tunnel_locate(net, &p, 0);
-
-	if (t) {
-		if (t->dev != dev)
-			return -EEXIST;
-	} else {
-		t = nt;
-
-		if (dev->type != ARPHRD_ETHER) {
-			unsigned int nflags = 0;
-
-			if (ipv4_is_multicast(p.iph.daddr))
-				nflags = IFF_BROADCAST;
-			else if (p.iph.daddr)
-				nflags = IFF_POINTOPOINT;
-
-			if ((dev->flags ^ nflags) &
-			    (IFF_POINTOPOINT | IFF_BROADCAST))
-				return -EINVAL;
-		}
 
-		ipgre_tunnel_unlink(ign, t);
-		t->parms.iph.saddr = p.iph.saddr;
-		t->parms.iph.daddr = p.iph.daddr;
-		t->parms.i_key = p.i_key;
-		if (dev->type != ARPHRD_ETHER) {
-			memcpy(dev->dev_addr, &p.iph.saddr, 4);
-			memcpy(dev->broadcast, &p.iph.daddr, 4);
-		}
-		ipgre_tunnel_link(ign, t);
-		netdev_state_change(dev);
-	}
-
-	t->parms.o_key = p.o_key;
-	t->parms.iph.ttl = p.iph.ttl;
-	t->parms.iph.tos = p.iph.tos;
-	t->parms.iph.frag_off = p.iph.frag_off;
-
-	if (t->parms.link != p.link) {
-		t->parms.link = p.link;
-		mtu = ipgre_tunnel_bind_dev(dev);
-		if (!tb[IFLA_MTU])
-			dev->mtu = mtu;
-		netdev_state_change(dev);
-	}
-
-	return 0;
+	ipgre_netlink_parms(data, tb, &p);
+	return ip_tunnel_changelink(dev, tb, &p);
 }
 
 static size_t ipgre_get_size(const struct net_device *dev)
@@ -1793,8 +885,8 @@ static int ipgre_fill_info(struct sk_buff *skb, const struct net_device *dev)
 	struct ip_tunnel_parm *p = &t->parms;
 
 	if (nla_put_u32(skb, IFLA_GRE_LINK, p->link) ||
-	    nla_put_be16(skb, IFLA_GRE_IFLAGS, p->i_flags) ||
-	    nla_put_be16(skb, IFLA_GRE_OFLAGS, p->o_flags) ||
+	    nla_put_be16(skb, IFLA_GRE_IFLAGS, tnl_flags_to_gre_flags(p->i_flags)) ||
+	    nla_put_be16(skb, IFLA_GRE_OFLAGS, tnl_flags_to_gre_flags(p->o_flags)) ||
 	    nla_put_be32(skb, IFLA_GRE_IKEY, p->i_key) ||
 	    nla_put_be32(skb, IFLA_GRE_OKEY, p->o_key) ||
 	    nla_put_be32(skb, IFLA_GRE_LOCAL, p->iph.saddr) ||
@@ -1832,6 +924,7 @@ static struct rtnl_link_ops ipgre_link_ops __read_mostly = {
 	.validate	= ipgre_tunnel_validate,
 	.newlink	= ipgre_newlink,
 	.changelink	= ipgre_changelink,
+	.dellink	= ip_tunnel_dellink,
 	.get_size	= ipgre_get_size,
 	.fill_info	= ipgre_fill_info,
 };
@@ -1845,13 +938,28 @@ static struct rtnl_link_ops ipgre_tap_ops __read_mostly = {
 	.validate	= ipgre_tap_validate,
 	.newlink	= ipgre_newlink,
 	.changelink	= ipgre_changelink,
+	.dellink	= ip_tunnel_dellink,
 	.get_size	= ipgre_get_size,
 	.fill_info	= ipgre_fill_info,
 };
 
-/*
- *	And now the modules code and kernel interface.
- */
+static int __net_init ipgre_tap_init_net(struct net *net)
+{
+	return ip_tunnel_init_net(net, gre_tap_net_id, &ipgre_tap_ops, NULL);
+}
+
+static void __net_exit ipgre_tap_exit_net(struct net *net)
+{
+	struct ip_tunnel_net *itn = net_generic(net, gre_tap_net_id);
+	ip_tunnel_delete_net(itn);
+}
+
+static struct pernet_operations ipgre_tap_net_ops = {
+	.init = ipgre_tap_init_net,
+	.exit = ipgre_tap_exit_net,
+	.id   = &gre_tap_net_id,
+	.size = sizeof(struct ip_tunnel_net),
+};
 
 static int __init ipgre_init(void)
 {
@@ -1863,6 +971,10 @@ static int __init ipgre_init(void)
 	if (err < 0)
 		return err;
 
+	err = register_pernet_device(&ipgre_tap_net_ops);
+	if (err < 0)
+		goto pnet_tap_faied;
+
 	err = gre_add_protocol(&ipgre_protocol, GREPROTO_CISCO);
 	if (err < 0) {
 		pr_info("%s: can't add protocol\n", __func__);
@@ -1877,16 +989,17 @@ static int __init ipgre_init(void)
 	if (err < 0)
 		goto tap_ops_failed;
 
-out:
-	return err;
+	return 0;
 
 tap_ops_failed:
 	rtnl_link_unregister(&ipgre_link_ops);
 rtnl_link_failed:
 	gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO);
 add_proto_failed:
+	unregister_pernet_device(&ipgre_tap_net_ops);
+pnet_tap_faied:
 	unregister_pernet_device(&ipgre_net_ops);
-	goto out;
+	return err;
 }
 
 static void __exit ipgre_fini(void)
@@ -1895,6 +1008,7 @@ static void __exit ipgre_fini(void)
 	rtnl_link_unregister(&ipgre_link_ops);
 	if (gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO) < 0)
 		pr_info("%s: can't remove protocol\n", __func__);
+	unregister_pernet_device(&ipgre_tap_net_ops);
 	unregister_pernet_device(&ipgre_net_ops);
 }
 
@@ -1904,3 +1018,4 @@ MODULE_LICENSE("GPL");
 MODULE_ALIAS_RTNL_LINK("gre");
 MODULE_ALIAS_RTNL_LINK("gretap");
 MODULE_ALIAS_NETDEV("gre0");
+MODULE_ALIAS_NETDEV("gretap0");
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c
new file mode 100644
index 0000000..e4147ec
--- /dev/null
+++ b/net/ipv4/ip_tunnel.c
@@ -0,0 +1,1035 @@
+/*
+ * Copyright (c) 2013 Nicira, Inc.
+ *
+ * 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-1301, USA
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/capability.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/in.h>
+#include <linux/tcp.h>
+#include <linux/udp.h>
+#include <linux/if_arp.h>
+#include <linux/mroute.h>
+#include <linux/init.h>
+#include <linux/in6.h>
+#include <linux/inetdevice.h>
+#include <linux/igmp.h>
+#include <linux/netfilter_ipv4.h>
+#include <linux/etherdevice.h>
+#include <linux/if_ether.h>
+#include <linux/if_vlan.h>
+#include <linux/rculist.h>
+
+#include <net/sock.h>
+#include <net/ip.h>
+#include <net/icmp.h>
+#include <net/protocol.h>
+#include <net/ip_tunnels.h>
+#include <net/arp.h>
+#include <net/checksum.h>
+#include <net/dsfield.h>
+#include <net/inet_ecn.h>
+#include <net/xfrm.h>
+#include <net/net_namespace.h>
+#include <net/netns/generic.h>
+#include <net/rtnetlink.h>
+
+#if IS_ENABLED(CONFIG_IPV6)
+#include <net/ipv6.h>
+#include <net/ip6_fib.h>
+#include <net/ip6_route.h>
+#endif
+
+static unsigned int ip_tunnel_hash(struct ip_tunnel_net *itn,
+				   __be32 key, __be32 remote)
+{
+	return hash_32((__force u32)key ^ (__force u32)remote,
+			 IP_TNL_HASH_BITS);
+}
+
+/* Often modified stats are per cpu, other are shared (netdev->stats) */
+struct rtnl_link_stats64 *ip_tunnel_get_stats64(struct net_device *dev,
+						struct rtnl_link_stats64 *tot)
+{
+	int i;
+
+	for_each_possible_cpu(i) {
+		const struct pcpu_tstats *tstats = per_cpu_ptr(dev->tstats, i);
+		u64 rx_packets, rx_bytes, tx_packets, tx_bytes;
+		unsigned int start;
+
+		do {
+			start = u64_stats_fetch_begin_bh(&tstats->syncp);
+			rx_packets = tstats->rx_packets;
+			tx_packets = tstats->tx_packets;
+			rx_bytes = tstats->rx_bytes;
+			tx_bytes = tstats->tx_bytes;
+		} while (u64_stats_fetch_retry_bh(&tstats->syncp, start));
+
+		tot->rx_packets += rx_packets;
+		tot->tx_packets += tx_packets;
+		tot->rx_bytes   += rx_bytes;
+		tot->tx_bytes   += tx_bytes;
+	}
+
+	tot->multicast = dev->stats.multicast;
+
+	tot->rx_crc_errors = dev->stats.rx_crc_errors;
+	tot->rx_fifo_errors = dev->stats.rx_fifo_errors;
+	tot->rx_length_errors = dev->stats.rx_length_errors;
+	tot->rx_frame_errors = dev->stats.rx_frame_errors;
+	tot->rx_errors = dev->stats.rx_errors;
+
+	tot->tx_fifo_errors = dev->stats.tx_fifo_errors;
+	tot->tx_carrier_errors = dev->stats.tx_carrier_errors;
+	tot->tx_dropped = dev->stats.tx_dropped;
+	tot->tx_aborted_errors = dev->stats.tx_aborted_errors;
+	tot->tx_errors = dev->stats.tx_errors;
+
+	tot->collisions  = dev->stats.collisions;
+
+	return tot;
+}
+EXPORT_SYMBOL_GPL(ip_tunnel_get_stats64);
+
+static bool ip_tunnel_key_match(const struct ip_tunnel_parm *p,
+				__be16 flags, __be32 key)
+{
+	if (p->i_flags & TUNNEL_KEY) {
+		if (flags & TUNNEL_KEY)
+			return key == p->i_key;
+		else
+			/* key expected, none present */
+			return false;
+	} else
+		return !(flags & TUNNEL_KEY);
+}
+
+/* Fallback tunnel: no source, no destination, no key, no options
+
+   Tunnel hash table:
+   We require exact key match i.e. if a key is present in packet
+   it will match only tunnel with the same key; if it is not present,
+   it will match only keyless tunnel.
+
+   All keysless packets, if not matched configured keyless tunnels
+   will match fallback tunnel.
+   Given src, dst and key, find appropriate for input tunnel.
+*/
+struct ip_tunnel *ip_tunnel_lookup(struct ip_tunnel_net *itn,
+				   int link, __be16 flags,
+				   __be32 remote, __be32 local,
+				   __be32 key)
+{
+	unsigned int hash;
+	struct ip_tunnel *t, *cand = NULL;
+	struct hlist_head *head;
+
+	hash = ip_tunnel_hash(itn, key, remote);
+	head = &itn->tunnels[hash];
+
+	hlist_for_each_entry_rcu(t, head, hash_node) {
+		if (local != t->parms.iph.saddr ||
+		    remote != t->parms.iph.daddr ||
+		    !(t->dev->flags & IFF_UP))
+			continue;
+
+		if (!ip_tunnel_key_match(&t->parms, flags, key))
+			continue;
+
+		if (t->parms.link == link)
+			return t;
+		else
+			cand = t;
+	}
+
+	hlist_for_each_entry_rcu(t, head, hash_node) {
+		if (remote != t->parms.iph.daddr ||
+		    !(t->dev->flags & IFF_UP))
+			continue;
+
+		if (!ip_tunnel_key_match(&t->parms, flags, key))
+			continue;
+
+		if (t->parms.link == link)
+			return t;
+		else if (!cand)
+			cand = t;
+	}
+
+	hash = ip_tunnel_hash(itn, key, 0);
+	head = &itn->tunnels[hash];
+
+	hlist_for_each_entry_rcu(t, head, hash_node) {
+		if ((local != t->parms.iph.saddr &&
+		     (local != t->parms.iph.daddr ||
+		      !ipv4_is_multicast(local))) ||
+		    !(t->dev->flags & IFF_UP))
+			continue;
+
+		if (!ip_tunnel_key_match(&t->parms, flags, key))
+			continue;
+
+		if (t->parms.link == link)
+			return t;
+		else if (!cand)
+			cand = t;
+	}
+
+	if (flags & TUNNEL_NO_KEY)
+		goto skip_key_lookup;
+
+	hlist_for_each_entry_rcu(t, head, hash_node) {
+		if (t->parms.i_key != key ||
+		    !(t->dev->flags & IFF_UP))
+			continue;
+
+		if (t->parms.link == link)
+			return t;
+		else if (!cand)
+			cand = t;
+	}
+
+skip_key_lookup:
+	if (cand)
+		return cand;
+
+	if (itn->fb_tunnel_dev && itn->fb_tunnel_dev->flags & IFF_UP)
+		return netdev_priv(itn->fb_tunnel_dev);
+
+
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(ip_tunnel_lookup);
+
+static struct hlist_head *ip_bucket(struct ip_tunnel_net *itn,
+				    struct ip_tunnel_parm *parms)
+{
+	unsigned int h;
+	__be32 remote;
+
+	if (parms->iph.daddr && !ipv4_is_multicast(parms->iph.daddr))
+		remote = parms->iph.daddr;
+	else
+		remote = 0;
+
+	h = ip_tunnel_hash(itn, parms->i_key, remote);
+	return &itn->tunnels[h];
+}
+
+static void ip_tunnel_add(struct ip_tunnel_net *itn, struct ip_tunnel *t)
+{
+	struct hlist_head *head = ip_bucket(itn, &t->parms);
+
+	hlist_add_head_rcu(&t->hash_node, head);
+}
+
+static void ip_tunnel_del(struct ip_tunnel *t)
+{
+	hlist_del_init_rcu(&t->hash_node);
+}
+
+static struct ip_tunnel *ip_tunnel_find(struct ip_tunnel_net *itn,
+					struct ip_tunnel_parm *parms,
+					int type)
+{
+	__be32 remote = parms->iph.daddr;
+	__be32 local = parms->iph.saddr;
+	__be32 key = parms->i_key;
+	int link = parms->link;
+	struct ip_tunnel *t = NULL;
+	struct hlist_head *head = ip_bucket(itn, parms);
+
+	hlist_for_each_entry_rcu(t, head, hash_node) {
+		if (local == t->parms.iph.saddr &&
+		    remote == t->parms.iph.daddr &&
+		    key == t->parms.i_key &&
+		    link == t->parms.link &&
+		    type == t->dev->type)
+			break;
+	}
+	return t;
+}
+
+static struct net_device *__ip_tunnel_create(struct net *net,
+					     const struct rtnl_link_ops *ops,
+					     struct ip_tunnel_parm *parms)
+{
+	int err;
+	struct ip_tunnel *tunnel;
+	struct net_device *dev;
+	char name[IFNAMSIZ];
+
+	if (parms->name[0])
+		strlcpy(name, parms->name, IFNAMSIZ);
+	else {
+		if (strlen(ops->kind) > (IFNAMSIZ - 3)) {
+			err = -E2BIG;
+			goto failed;
+		}
+		strlcpy(name, ops->kind, IFNAMSIZ);
+		strncat(name, "%d", 2);
+	}
+
+	ASSERT_RTNL();
+	dev = alloc_netdev(ops->priv_size, name, ops->setup);
+	if (!dev) {
+		err = -ENOMEM;
+		goto failed;
+	}
+	dev_net_set(dev, net);
+
+	dev->rtnl_link_ops = ops;
+
+	tunnel = netdev_priv(dev);
+	tunnel->parms = *parms;
+
+	err = register_netdevice(dev);
+	if (err)
+		goto failed_free;
+
+	return dev;
+
+failed_free:
+	free_netdev(dev);
+failed:
+	return ERR_PTR(err);
+}
+
+static inline struct rtable *ip_route_output_tunnel(struct net *net,
+						    struct flowi4 *fl4,
+						    int proto,
+						    __be32 daddr, __be32 saddr,
+						    __be32 key, __u8 tos, int oif)
+{
+	memset(fl4, 0, sizeof(*fl4));
+	fl4->flowi4_oif = oif;
+	fl4->daddr = daddr;
+	fl4->saddr = saddr;
+	fl4->flowi4_tos = tos;
+	fl4->flowi4_proto = proto;
+	fl4->fl4_gre_key = key;
+	return ip_route_output_key(net, fl4);
+}
+
+static int ip_tunnel_bind_dev(struct net_device *dev)
+{
+	struct net_device *tdev = NULL;
+	struct ip_tunnel *tunnel = netdev_priv(dev);
+	const struct iphdr *iph;
+	int hlen = LL_MAX_HEADER;
+	int mtu = ETH_DATA_LEN;
+	int t_hlen = tunnel->hlen + sizeof(struct iphdr);
+
+	iph = &tunnel->parms.iph;
+
+	/* Guess output device to choose reasonable mtu and needed_headroom */
+	if (iph->daddr) {
+		struct flowi4 fl4;
+		struct rtable *rt;
+
+		rt = ip_route_output_tunnel(dev_net(dev), &fl4,
+					    tunnel->parms.iph.protocol,
+					    iph->daddr, iph->saddr,
+					    tunnel->parms.o_key,
+					    RT_TOS(iph->tos),
+					    tunnel->parms.link);
+		if (!IS_ERR(rt)) {
+			tdev = rt->dst.dev;
+			ip_rt_put(rt);
+		}
+		if (dev->type != ARPHRD_ETHER)
+			dev->flags |= IFF_POINTOPOINT;
+	}
+
+	if (!tdev && tunnel->parms.link)
+		tdev = __dev_get_by_index(dev_net(dev), tunnel->parms.link);
+
+	if (tdev) {
+		hlen = tdev->hard_header_len + tdev->needed_headroom;
+		mtu = tdev->mtu;
+	}
+	dev->iflink = tunnel->parms.link;
+
+	dev->needed_headroom = t_hlen + hlen;
+	mtu -= (dev->hard_header_len + t_hlen);
+
+	if (mtu < 68)
+		mtu = 68;
+
+	return mtu;
+}
+
+static struct ip_tunnel *ip_tunnel_create(struct net *net,
+					  struct ip_tunnel_net *itn,
+					  struct ip_tunnel_parm *parms)
+{
+	struct ip_tunnel *nt, *fbt;
+	struct net_device *dev;
+
+	BUG_ON(!itn->fb_tunnel_dev);
+	fbt = netdev_priv(itn->fb_tunnel_dev);
+	dev = __ip_tunnel_create(net, itn->fb_tunnel_dev->rtnl_link_ops, parms);
+	if (IS_ERR(dev))
+		return NULL;
+
+	dev->mtu = ip_tunnel_bind_dev(dev);
+
+	nt = netdev_priv(dev);
+	ip_tunnel_add(itn, nt);
+	return nt;
+}
+
+int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb,
+		  const struct tnl_ptk_info *tpi, bool log_ecn_error)
+{
+	struct pcpu_tstats *tstats;
+	const struct iphdr *iph = ip_hdr(skb);
+	int err;
+
+	secpath_reset(skb);
+
+	skb->protocol = tpi->proto;
+
+	skb->mac_header = skb->network_header;
+	__pskb_pull(skb, tunnel->hlen);
+	skb_postpull_rcsum(skb, skb_transport_header(skb), tunnel->hlen);
+#ifdef CONFIG_NET_IPGRE_BROADCAST
+	if (ipv4_is_multicast(iph->daddr)) {
+		/* Looped back packet, drop it! */
+		if (rt_is_output_route(skb_rtable(skb)))
+			goto drop;
+		tunnel->dev->stats.multicast++;
+		skb->pkt_type = PACKET_BROADCAST;
+	}
+#endif
+
+	if ((!(tpi->flags&TUNNEL_CSUM) &&  (tunnel->parms.i_flags&TUNNEL_CSUM)) ||
+	     ((tpi->flags&TUNNEL_CSUM) && !(tunnel->parms.i_flags&TUNNEL_CSUM))) {
+		tunnel->dev->stats.rx_crc_errors++;
+		tunnel->dev->stats.rx_errors++;
+		goto drop;
+	}
+
+	if (tunnel->parms.i_flags&TUNNEL_SEQ) {
+		if (!(tpi->flags&TUNNEL_SEQ) ||
+		    (tunnel->i_seqno && (s32)(ntohl(tpi->seq) - tunnel->i_seqno) < 0)) {
+			tunnel->dev->stats.rx_fifo_errors++;
+			tunnel->dev->stats.rx_errors++;
+			goto drop;
+		}
+		tunnel->i_seqno = ntohl(tpi->seq) + 1;
+	}
+
+	/* Warning: All skb pointers will be invalidated! */
+	if (tunnel->dev->type == ARPHRD_ETHER) {
+		if (!pskb_may_pull(skb, ETH_HLEN)) {
+			tunnel->dev->stats.rx_length_errors++;
+			tunnel->dev->stats.rx_errors++;
+			goto drop;
+		}
+
+		iph = ip_hdr(skb);
+		skb->protocol = eth_type_trans(skb, tunnel->dev);
+		skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN);
+	}
+
+	skb->pkt_type = PACKET_HOST;
+	__skb_tunnel_rx(skb, tunnel->dev);
+
+	skb_reset_network_header(skb);
+	err = IP_ECN_decapsulate(iph, skb);
+	if (unlikely(err)) {
+		if (log_ecn_error)
+			net_info_ratelimited("non-ECT from %pI4 with TOS=%#x\n",
+					&iph->saddr, iph->tos);
+		if (err > 1) {
+			++tunnel->dev->stats.rx_frame_errors;
+			++tunnel->dev->stats.rx_errors;
+			goto drop;
+		}
+	}
+
+	tstats = this_cpu_ptr(tunnel->dev->tstats);
+	u64_stats_update_begin(&tstats->syncp);
+	tstats->rx_packets++;
+	tstats->rx_bytes += skb->len;
+	u64_stats_update_end(&tstats->syncp);
+
+	gro_cells_receive(&tunnel->gro_cells, skb);
+	return 0;
+
+drop:
+	kfree_skb(skb);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ip_tunnel_rcv);
+
+void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
+		    const struct iphdr *tnl_params)
+{
+	struct ip_tunnel *tunnel = netdev_priv(dev);
+	const struct iphdr *inner_iph;
+	struct iphdr *iph;
+	struct flowi4 fl4;
+	u8     tos, ttl;
+	__be16 df;
+	struct rtable *rt;		/* Route to the other host */
+	struct net_device *tdev;	/* Device to other host */
+	unsigned int max_headroom;	/* The extra header space needed */
+	__be32 dst;
+	int mtu;
+
+	inner_iph = (const struct iphdr *)skb_inner_network_header(skb);
+
+	dst = tnl_params->daddr;
+	if (dst == 0) {
+		/* NBMA tunnel */
+
+		if (skb_dst(skb) == NULL) {
+			dev->stats.tx_fifo_errors++;
+			goto tx_error;
+		}
+
+		if (skb->protocol == htons(ETH_P_IP)) {
+			rt = skb_rtable(skb);
+			dst = rt_nexthop(rt, inner_iph->daddr);
+		}
+#if IS_ENABLED(CONFIG_IPV6)
+		else if (skb->protocol == htons(ETH_P_IPV6)) {
+			const struct in6_addr *addr6;
+			struct neighbour *neigh;
+			bool do_tx_error_icmp;
+			int addr_type;
+
+			neigh = dst_neigh_lookup(skb_dst(skb),
+						 &ipv6_hdr(skb)->daddr);
+			if (neigh == NULL)
+				goto tx_error;
+
+			addr6 = (const struct in6_addr *)&neigh->primary_key;
+			addr_type = ipv6_addr_type(addr6);
+
+			if (addr_type == IPV6_ADDR_ANY) {
+				addr6 = &ipv6_hdr(skb)->daddr;
+				addr_type = ipv6_addr_type(addr6);
+			}
+
+			if ((addr_type & IPV6_ADDR_COMPATv4) == 0)
+				do_tx_error_icmp = true;
+			else {
+				do_tx_error_icmp = false;
+				dst = addr6->s6_addr32[3];
+			}
+			neigh_release(neigh);
+			if (do_tx_error_icmp)
+				goto tx_error_icmp;
+		}
+#endif
+		else
+			goto tx_error;
+	}
+
+	tos = tnl_params->tos;
+	if (tos & 0x1) {
+		tos &= ~0x1;
+		if (skb->protocol == htons(ETH_P_IP))
+			tos = inner_iph->tos;
+		else if (skb->protocol == htons(ETH_P_IPV6))
+			tos = ipv6_get_dsfield((const struct ipv6hdr *)inner_iph);
+	}
+
+	rt = ip_route_output_tunnel(dev_net(dev), &fl4,
+				    tunnel->parms.iph.protocol,
+				    dst, tnl_params->saddr,
+				    tunnel->parms.o_key,
+				    RT_TOS(tos),
+				    tunnel->parms.link);
+	if (IS_ERR(rt)) {
+		dev->stats.tx_carrier_errors++;
+		goto tx_error;
+	}
+	tdev = rt->dst.dev;
+
+	if (tdev == dev) {
+		ip_rt_put(rt);
+		dev->stats.collisions++;
+		goto tx_error;
+	}
+
+	df = tnl_params->frag_off;
+
+	if (df)
+		mtu = dst_mtu(&rt->dst) - dev->hard_header_len
+					- sizeof(struct iphdr);
+	else
+		mtu = skb_dst(skb) ? dst_mtu(skb_dst(skb)) : dev->mtu;
+
+	if (skb_dst(skb))
+		skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu);
+
+	if (skb->protocol == htons(ETH_P_IP)) {
+		df |= (inner_iph->frag_off&htons(IP_DF));
+
+		if (!skb_is_gso(skb) &&
+		    (inner_iph->frag_off&htons(IP_DF)) &&
+		     mtu < ntohs(inner_iph->tot_len)) {
+			icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu));
+			ip_rt_put(rt);
+			goto tx_error;
+		}
+	}
+#if IS_ENABLED(CONFIG_IPV6)
+	else if (skb->protocol == htons(ETH_P_IPV6)) {
+		struct rt6_info *rt6 = (struct rt6_info *)skb_dst(skb);
+
+		if (rt6 && mtu < dst_mtu(skb_dst(skb)) &&
+		    mtu >= IPV6_MIN_MTU) {
+			if ((tunnel->parms.iph.daddr &&
+			    !ipv4_is_multicast(tunnel->parms.iph.daddr)) ||
+			    rt6->rt6i_dst.plen == 128) {
+				rt6->rt6i_flags |= RTF_MODIFIED;
+				dst_metric_set(skb_dst(skb), RTAX_MTU, mtu);
+			}
+		}
+
+		if (!skb_is_gso(skb) && mtu >= IPV6_MIN_MTU &&
+		    mtu < skb->len) {
+			icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
+			ip_rt_put(rt);
+			goto tx_error;
+		}
+	}
+#endif
+
+	if (tunnel->err_count > 0) {
+		if (time_before(jiffies,
+				tunnel->err_time + IPTUNNEL_ERR_TIMEO)) {
+			tunnel->err_count--;
+
+			dst_link_failure(skb);
+		} else
+			tunnel->err_count = 0;
+	}
+
+	ttl = tnl_params->ttl;
+	if (ttl == 0) {
+		if (skb->protocol == htons(ETH_P_IP))
+			ttl = inner_iph->ttl;
+#if IS_ENABLED(CONFIG_IPV6)
+		else if (skb->protocol == htons(ETH_P_IPV6))
+			ttl = ((const struct ipv6hdr *)inner_iph)->hop_limit;
+#endif
+		else
+			ttl = ip4_dst_hoplimit(&rt->dst);
+	}
+
+	max_headroom = LL_RESERVED_SPACE(tdev) + sizeof(struct iphdr)
+					       + rt->dst.header_len;
+	if (max_headroom > dev->needed_headroom) {
+		dev->needed_headroom = max_headroom;
+		if (skb_cow_head(skb, dev->needed_headroom)) {
+			dev->stats.tx_dropped++;
+			dev_kfree_skb(skb);
+			return;
+		}
+	}
+
+	skb_dst_drop(skb);
+	skb_dst_set(skb, &rt->dst);
+	memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
+
+	/* Push down and install the IP header. */
+	skb_push(skb, sizeof(struct iphdr));
+	skb_reset_network_header(skb);
+
+	iph = ip_hdr(skb);
+	inner_iph = (const struct iphdr *)skb_inner_network_header(skb);
+
+	iph->version	=	4;
+	iph->ihl	=	sizeof(struct iphdr) >> 2;
+	iph->frag_off	=	df;
+	iph->protocol	=	tnl_params->protocol;
+	iph->tos	=	ip_tunnel_ecn_encap(tos, inner_iph, skb);
+	iph->daddr	=	fl4.daddr;
+	iph->saddr	=	fl4.saddr;
+	iph->ttl	=	ttl;
+	tunnel_ip_select_ident(skb, inner_iph, &rt->dst);
+
+	iptunnel_xmit(skb, dev);
+	return;
+
+#if IS_ENABLED(CONFIG_IPV6)
+tx_error_icmp:
+	dst_link_failure(skb);
+#endif
+tx_error:
+	dev->stats.tx_errors++;
+	dev_kfree_skb(skb);
+}
+EXPORT_SYMBOL_GPL(ip_tunnel_xmit);
+
+static void ip_tunnel_update(struct ip_tunnel_net *itn,
+			     struct ip_tunnel *t,
+			     struct net_device *dev,
+			     struct ip_tunnel_parm *p,
+			     bool set_mtu)
+{
+	ip_tunnel_del(t);
+	t->parms.iph.saddr = p->iph.saddr;
+	t->parms.iph.daddr = p->iph.daddr;
+	t->parms.i_key = p->i_key;
+	t->parms.o_key = p->o_key;
+	if (dev->type != ARPHRD_ETHER) {
+		memcpy(dev->dev_addr, &p->iph.saddr, 4);
+		memcpy(dev->broadcast, &p->iph.daddr, 4);
+	}
+	ip_tunnel_add(itn, t);
+
+	t->parms.iph.ttl = p->iph.ttl;
+	t->parms.iph.tos = p->iph.tos;
+	t->parms.iph.frag_off = p->iph.frag_off;
+
+	if (t->parms.link != p->link) {
+		int mtu;
+
+		t->parms.link = p->link;
+		mtu = ip_tunnel_bind_dev(dev);
+		if (set_mtu)
+			dev->mtu = mtu;
+	}
+	netdev_state_change(dev);
+}
+
+int ip_tunnel_ioctl(struct net_device *dev, struct ip_tunnel_parm *p, int cmd)
+{
+	int err = 0;
+	struct ip_tunnel *t;
+	struct net *net = dev_net(dev);
+	struct ip_tunnel *tunnel = netdev_priv(dev);
+	struct ip_tunnel_net *itn = net_generic(net, tunnel->ip_tnl_net_id);
+
+	BUG_ON(!itn->fb_tunnel_dev);
+	switch (cmd) {
+	case SIOCGETTUNNEL:
+		t = NULL;
+		if (dev == itn->fb_tunnel_dev)
+			t = ip_tunnel_find(itn, p, itn->fb_tunnel_dev->type);
+		if (t == NULL)
+			t = netdev_priv(dev);
+		memcpy(p, &t->parms, sizeof(*p));
+		break;
+
+	case SIOCADDTUNNEL:
+	case SIOCCHGTUNNEL:
+		err = -EPERM;
+		if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
+			goto done;
+		if (p->iph.ttl)
+			p->iph.frag_off |= htons(IP_DF);
+		if (!(p->i_flags&TUNNEL_KEY))
+			p->i_key = 0;
+		if (!(p->o_flags&TUNNEL_KEY))
+			p->o_key = 0;
+
+		t = ip_tunnel_find(itn, p, itn->fb_tunnel_dev->type);
+
+		if (!t && (cmd == SIOCADDTUNNEL))
+			t = ip_tunnel_create(net, itn, p);
+
+		if (dev != itn->fb_tunnel_dev && cmd == SIOCCHGTUNNEL) {
+			if (t != NULL) {
+				if (t->dev != dev) {
+					err = -EEXIST;
+					break;
+				}
+			} else {
+				unsigned int nflags = 0;
+
+				if (ipv4_is_multicast(p->iph.daddr))
+					nflags = IFF_BROADCAST;
+				else if (p->iph.daddr)
+					nflags = IFF_POINTOPOINT;
+
+				if ((dev->flags^nflags)&(IFF_POINTOPOINT|IFF_BROADCAST)) {
+					err = -EINVAL;
+					break;
+				}
+
+				t = netdev_priv(dev);
+			}
+		}
+
+		if (t) {
+			err = 0;
+			ip_tunnel_update(itn, t, dev, p, true);
+		} else
+			err = (cmd == SIOCADDTUNNEL ? -ENOBUFS : -ENOENT);
+		break;
+
+	case SIOCDELTUNNEL:
+		err = -EPERM;
+		if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
+			goto done;
+
+		if (dev == itn->fb_tunnel_dev) {
+			err = -ENOENT;
+			t = ip_tunnel_find(itn, p, itn->fb_tunnel_dev->type);
+			if (t == NULL)
+				goto done;
+			err = -EPERM;
+			if (t == netdev_priv(itn->fb_tunnel_dev))
+				goto done;
+			dev = t->dev;
+		}
+		unregister_netdevice(dev);
+		err = 0;
+		break;
+
+	default:
+		err = -EINVAL;
+	}
+
+done:
+	return err;
+}
+EXPORT_SYMBOL_GPL(ip_tunnel_ioctl);
+
+int ip_tunnel_change_mtu(struct net_device *dev, int new_mtu)
+{
+	struct ip_tunnel *tunnel = netdev_priv(dev);
+	int t_hlen = tunnel->hlen + sizeof(struct iphdr);
+
+	if (new_mtu < 68 ||
+	    new_mtu > 0xFFF8 - dev->hard_header_len - t_hlen)
+		return -EINVAL;
+	dev->mtu = new_mtu;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ip_tunnel_change_mtu);
+
+static void ip_tunnel_dev_free(struct net_device *dev)
+{
+	struct ip_tunnel *tunnel = netdev_priv(dev);
+
+	gro_cells_destroy(&tunnel->gro_cells);
+	free_percpu(dev->tstats);
+	free_netdev(dev);
+}
+
+void ip_tunnel_dellink(struct net_device *dev, struct list_head *head)
+{
+	struct net *net = dev_net(dev);
+	struct ip_tunnel *tunnel = netdev_priv(dev);
+	struct ip_tunnel_net *itn;
+
+	itn = net_generic(net, tunnel->ip_tnl_net_id);
+
+	if (itn->fb_tunnel_dev != dev) {
+		ip_tunnel_del(netdev_priv(dev));
+		unregister_netdevice_queue(dev, head);
+	}
+}
+EXPORT_SYMBOL_GPL(ip_tunnel_dellink);
+
+int __net_init ip_tunnel_init_net(struct net *net, int ip_tnl_net_id,
+				  struct rtnl_link_ops *ops, char *devname)
+{
+	struct ip_tunnel_net *itn = net_generic(net, ip_tnl_net_id);
+	struct ip_tunnel_parm parms;
+
+	itn->tunnels = kzalloc(IP_TNL_HASH_SIZE * sizeof(struct hlist_head), GFP_KERNEL);
+	if (!itn->tunnels)
+		return -ENOMEM;
+
+	if (!ops) {
+		itn->fb_tunnel_dev = NULL;
+		return 0;
+	}
+	memset(&parms, 0, sizeof(parms));
+	if (devname)
+		strlcpy(parms.name, devname, IFNAMSIZ);
+
+	rtnl_lock();
+	itn->fb_tunnel_dev = __ip_tunnel_create(net, ops, &parms);
+	rtnl_unlock();
+	if (IS_ERR(itn->fb_tunnel_dev)) {
+		kfree(itn->tunnels);
+		return PTR_ERR(itn->fb_tunnel_dev);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ip_tunnel_init_net);
+
+static void ip_tunnel_destroy(struct ip_tunnel_net *itn, struct list_head *head)
+{
+	int h;
+
+	for (h = 0; h < IP_TNL_HASH_SIZE; h++) {
+		struct ip_tunnel *t;
+		struct hlist_node *n;
+		struct hlist_head *thead = &itn->tunnels[h];
+
+		hlist_for_each_entry_safe(t, n, thead, hash_node)
+			unregister_netdevice_queue(t->dev, head);
+	}
+	if (itn->fb_tunnel_dev)
+		unregister_netdevice_queue(itn->fb_tunnel_dev, head);
+}
+
+void __net_exit ip_tunnel_delete_net(struct ip_tunnel_net *itn)
+{
+	LIST_HEAD(list);
+
+	rtnl_lock();
+	ip_tunnel_destroy(itn, &list);
+	unregister_netdevice_many(&list);
+	rtnl_unlock();
+	kfree(itn->tunnels);
+}
+EXPORT_SYMBOL_GPL(ip_tunnel_delete_net);
+
+int ip_tunnel_newlink(struct net_device *dev, struct nlattr *tb[],
+		      struct ip_tunnel_parm *p)
+{
+	struct ip_tunnel *nt;
+	struct net *net = dev_net(dev);
+	struct ip_tunnel_net *itn;
+	int mtu;
+	int err;
+
+	nt = netdev_priv(dev);
+	itn = net_generic(net, nt->ip_tnl_net_id);
+
+	if (ip_tunnel_find(itn, p, dev->type))
+		return -EEXIST;
+
+	nt->parms = *p;
+	err = register_netdevice(dev);
+	if (err)
+		goto out;
+
+	if (dev->type == ARPHRD_ETHER && !tb[IFLA_ADDRESS])
+		eth_hw_addr_random(dev);
+
+	mtu = ip_tunnel_bind_dev(dev);
+	if (!tb[IFLA_MTU])
+		dev->mtu = mtu;
+
+	ip_tunnel_add(itn, nt);
+
+out:
+	return err;
+}
+EXPORT_SYMBOL_GPL(ip_tunnel_newlink);
+
+int ip_tunnel_changelink(struct net_device *dev, struct nlattr *tb[],
+			 struct ip_tunnel_parm *p)
+{
+	struct ip_tunnel *t, *nt;
+	struct net *net = dev_net(dev);
+	struct ip_tunnel *tunnel = netdev_priv(dev);
+	struct ip_tunnel_net *itn = net_generic(net, tunnel->ip_tnl_net_id);
+
+	if (dev == itn->fb_tunnel_dev)
+		return -EINVAL;
+
+	nt = netdev_priv(dev);
+
+	t = ip_tunnel_find(itn, p, dev->type);
+
+	if (t) {
+		if (t->dev != dev)
+			return -EEXIST;
+	} else {
+		t = nt;
+
+		if (dev->type != ARPHRD_ETHER) {
+			unsigned int nflags = 0;
+
+			if (ipv4_is_multicast(p->iph.daddr))
+				nflags = IFF_BROADCAST;
+			else if (p->iph.daddr)
+				nflags = IFF_POINTOPOINT;
+
+			if ((dev->flags ^ nflags) &
+			    (IFF_POINTOPOINT | IFF_BROADCAST))
+				return -EINVAL;
+		}
+	}
+
+	ip_tunnel_update(itn, t, dev, p, !tb[IFLA_MTU]);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ip_tunnel_changelink);
+
+int ip_tunnel_init(struct net_device *dev)
+{
+	struct ip_tunnel *tunnel = netdev_priv(dev);
+	struct iphdr *iph = &tunnel->parms.iph;
+	int err;
+
+	dev->destructor	= ip_tunnel_dev_free;
+	dev->tstats = alloc_percpu(struct pcpu_tstats);
+	if (!dev->tstats)
+		return -ENOMEM;
+
+	err = gro_cells_init(&tunnel->gro_cells, dev);
+	if (err) {
+		free_percpu(dev->tstats);
+		return err;
+	}
+
+	tunnel->dev = dev;
+	strcpy(tunnel->parms.name, dev->name);
+	iph->version		= 4;
+	iph->ihl		= 5;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ip_tunnel_init);
+
+void ip_tunnel_uninit(struct net_device *dev)
+{
+	struct net *net = dev_net(dev);
+	struct ip_tunnel *tunnel = netdev_priv(dev);
+	struct ip_tunnel_net *itn;
+
+	itn = net_generic(net, tunnel->ip_tnl_net_id);
+	/* fb_tunnel_dev will be unregisted in net-exit call. */
+	if (itn->fb_tunnel_dev != dev)
+		ip_tunnel_del(netdev_priv(dev));
+}
+EXPORT_SYMBOL_GPL(ip_tunnel_uninit);
+
+/* Do least required initialization, rest of init is done in tunnel_init call */
+void ip_tunnel_setup(struct net_device *dev, int net_id)
+{
+	struct ip_tunnel *tunnel = netdev_priv(dev);
+	tunnel->ip_tnl_net_id = net_id;
+}
+EXPORT_SYMBOL_GPL(ip_tunnel_setup);
+
+MODULE_LICENSE("GPL");
diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c
index c3a4233..9d2bdb2 100644
--- a/net/ipv4/ip_vti.c
+++ b/net/ipv4/ip_vti.c
@@ -38,7 +38,7 @@
 #include <net/sock.h>
 #include <net/ip.h>
 #include <net/icmp.h>
-#include <net/ipip.h>
+#include <net/ip_tunnels.h>
 #include <net/inet_ecn.h>
 #include <net/xfrm.h>
 #include <net/net_namespace.h>
@@ -82,44 +82,6 @@ static int vti_tunnel_bind_dev(struct net_device *dev);
 } while (0)
 
 
-static struct rtnl_link_stats64 *vti_get_stats64(struct net_device *dev,
-						 struct rtnl_link_stats64 *tot)
-{
-	int i;
-
-	for_each_possible_cpu(i) {
-		const struct pcpu_tstats *tstats = per_cpu_ptr(dev->tstats, i);
-		u64 rx_packets, rx_bytes, tx_packets, tx_bytes;
-		unsigned int start;
-
-		do {
-			start = u64_stats_fetch_begin_bh(&tstats->syncp);
-			rx_packets = tstats->rx_packets;
-			tx_packets = tstats->tx_packets;
-			rx_bytes = tstats->rx_bytes;
-			tx_bytes = tstats->tx_bytes;
-		} while (u64_stats_fetch_retry_bh(&tstats->syncp, start));
-
-		tot->rx_packets += rx_packets;
-		tot->tx_packets += tx_packets;
-		tot->rx_bytes   += rx_bytes;
-		tot->tx_bytes   += tx_bytes;
-	}
-
-	tot->multicast = dev->stats.multicast;
-	tot->rx_crc_errors = dev->stats.rx_crc_errors;
-	tot->rx_fifo_errors = dev->stats.rx_fifo_errors;
-	tot->rx_length_errors = dev->stats.rx_length_errors;
-	tot->rx_errors = dev->stats.rx_errors;
-	tot->tx_fifo_errors = dev->stats.tx_fifo_errors;
-	tot->tx_carrier_errors = dev->stats.tx_carrier_errors;
-	tot->tx_dropped = dev->stats.tx_dropped;
-	tot->tx_aborted_errors = dev->stats.tx_aborted_errors;
-	tot->tx_errors = dev->stats.tx_errors;
-
-	return tot;
-}
-
 static struct ip_tunnel *vti_tunnel_lookup(struct net *net,
 					   __be32 remote, __be32 local)
 {
@@ -597,7 +559,7 @@ static const struct net_device_ops vti_netdev_ops = {
 	.ndo_start_xmit	= vti_tunnel_xmit,
 	.ndo_do_ioctl	= vti_tunnel_ioctl,
 	.ndo_change_mtu	= vti_tunnel_change_mtu,
-	.ndo_get_stats64 = vti_get_stats64,
+	.ndo_get_stats64 = ip_tunnel_get_stats64,
 };
 
 static void vti_dev_free(struct net_device *dev)
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
index f01d1b1..59cb8c7 100644
--- a/net/ipv4/ipcomp.c
+++ b/net/ipv4/ipcomp.c
@@ -75,6 +75,7 @@ static struct xfrm_state *ipcomp_tunnel_create(struct xfrm_state *x)
 	t->props.mode = x->props.mode;
 	t->props.saddr.a4 = x->props.saddr.a4;
 	t->props.flags = x->props.flags;
+	t->props.extra_flags = x->props.extra_flags;
 	memcpy(&t->mark, &x->mark, sizeof(t->mark));
 
 	if (xfrm_init_state(t))
diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c
index bf6c5cf..efa1138 100644
--- a/net/ipv4/ipconfig.c
+++ b/net/ipv4/ipconfig.c
@@ -206,7 +206,7 @@ static int __init ic_open_devs(void)
 	struct ic_device *d, **last;
 	struct net_device *dev;
 	unsigned short oflags;
-	unsigned long start;
+	unsigned long start, next_msg;
 
 	last = &ic_first_dev;
 	rtnl_lock();
@@ -263,12 +263,23 @@ static int __init ic_open_devs(void)
 
 	/* wait for a carrier on at least one device */
 	start = jiffies;
+	next_msg = start + msecs_to_jiffies(CONF_CARRIER_TIMEOUT/12);
 	while (jiffies - start < msecs_to_jiffies(CONF_CARRIER_TIMEOUT)) {
+		int wait, elapsed;
+
 		for_each_netdev(&init_net, dev)
 			if (ic_is_init_dev(dev) && netif_carrier_ok(dev))
 				goto have_carrier;
 
 		msleep(1);
+
+		if time_before(jiffies, next_msg)
+			continue;
+
+		elapsed = jiffies_to_msecs(jiffies - start);
+		wait = (CONF_CARRIER_TIMEOUT - elapsed + 500)/1000;
+		pr_info("Waiting up to %d more seconds for network.\n", wait);
+		next_msg = jiffies + msecs_to_jiffies(CONF_CARRIER_TIMEOUT/12);
 	}
 have_carrier:
 	rtnl_unlock();
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index 8f024d4..77bfcce 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -111,227 +111,21 @@
 #include <net/sock.h>
 #include <net/ip.h>
 #include <net/icmp.h>
-#include <net/ipip.h>
+#include <net/ip_tunnels.h>
 #include <net/inet_ecn.h>
 #include <net/xfrm.h>
 #include <net/net_namespace.h>
 #include <net/netns/generic.h>
 
-#define HASH_SIZE  16
-#define HASH(addr) (((__force u32)addr^((__force u32)addr>>4))&0xF)
-
 static bool log_ecn_error = true;
 module_param(log_ecn_error, bool, 0644);
 MODULE_PARM_DESC(log_ecn_error, "Log packets received with corrupted ECN");
 
 static int ipip_net_id __read_mostly;
-struct ipip_net {
-	struct ip_tunnel __rcu *tunnels_r_l[HASH_SIZE];
-	struct ip_tunnel __rcu *tunnels_r[HASH_SIZE];
-	struct ip_tunnel __rcu *tunnels_l[HASH_SIZE];
-	struct ip_tunnel __rcu *tunnels_wc[1];
-	struct ip_tunnel __rcu **tunnels[4];
-
-	struct net_device *fb_tunnel_dev;
-};
 
 static int ipip_tunnel_init(struct net_device *dev);
-static void ipip_tunnel_setup(struct net_device *dev);
-static void ipip_dev_free(struct net_device *dev);
 static struct rtnl_link_ops ipip_link_ops __read_mostly;
 
-static struct rtnl_link_stats64 *ipip_get_stats64(struct net_device *dev,
-						  struct rtnl_link_stats64 *tot)
-{
-	int i;
-
-	for_each_possible_cpu(i) {
-		const struct pcpu_tstats *tstats = per_cpu_ptr(dev->tstats, i);
-		u64 rx_packets, rx_bytes, tx_packets, tx_bytes;
-		unsigned int start;
-
-		do {
-			start = u64_stats_fetch_begin_bh(&tstats->syncp);
-			rx_packets = tstats->rx_packets;
-			tx_packets = tstats->tx_packets;
-			rx_bytes = tstats->rx_bytes;
-			tx_bytes = tstats->tx_bytes;
-		} while (u64_stats_fetch_retry_bh(&tstats->syncp, start));
-
-		tot->rx_packets += rx_packets;
-		tot->tx_packets += tx_packets;
-		tot->rx_bytes   += rx_bytes;
-		tot->tx_bytes   += tx_bytes;
-	}
-
-	tot->tx_fifo_errors = dev->stats.tx_fifo_errors;
-	tot->tx_carrier_errors = dev->stats.tx_carrier_errors;
-	tot->tx_dropped = dev->stats.tx_dropped;
-	tot->tx_aborted_errors = dev->stats.tx_aborted_errors;
-	tot->tx_errors = dev->stats.tx_errors;
-	tot->collisions = dev->stats.collisions;
-
-	return tot;
-}
-
-static struct ip_tunnel *ipip_tunnel_lookup(struct net *net,
-		__be32 remote, __be32 local)
-{
-	unsigned int h0 = HASH(remote);
-	unsigned int h1 = HASH(local);
-	struct ip_tunnel *t;
-	struct ipip_net *ipn = net_generic(net, ipip_net_id);
-
-	for_each_ip_tunnel_rcu(t, ipn->tunnels_r_l[h0 ^ h1])
-		if (local == t->parms.iph.saddr &&
-		    remote == t->parms.iph.daddr && (t->dev->flags&IFF_UP))
-			return t;
-
-	for_each_ip_tunnel_rcu(t, ipn->tunnels_r[h0])
-		if (remote == t->parms.iph.daddr && (t->dev->flags&IFF_UP))
-			return t;
-
-	for_each_ip_tunnel_rcu(t, ipn->tunnels_l[h1])
-		if (local == t->parms.iph.saddr && (t->dev->flags&IFF_UP))
-			return t;
-
-	t = rcu_dereference(ipn->tunnels_wc[0]);
-	if (t && (t->dev->flags&IFF_UP))
-		return t;
-	return NULL;
-}
-
-static struct ip_tunnel __rcu **__ipip_bucket(struct ipip_net *ipn,
-		struct ip_tunnel_parm *parms)
-{
-	__be32 remote = parms->iph.daddr;
-	__be32 local = parms->iph.saddr;
-	unsigned int h = 0;
-	int prio = 0;
-
-	if (remote) {
-		prio |= 2;
-		h ^= HASH(remote);
-	}
-	if (local) {
-		prio |= 1;
-		h ^= HASH(local);
-	}
-	return &ipn->tunnels[prio][h];
-}
-
-static inline struct ip_tunnel __rcu **ipip_bucket(struct ipip_net *ipn,
-		struct ip_tunnel *t)
-{
-	return __ipip_bucket(ipn, &t->parms);
-}
-
-static void ipip_tunnel_unlink(struct ipip_net *ipn, struct ip_tunnel *t)
-{
-	struct ip_tunnel __rcu **tp;
-	struct ip_tunnel *iter;
-
-	for (tp = ipip_bucket(ipn, t);
-	     (iter = rtnl_dereference(*tp)) != NULL;
-	     tp = &iter->next) {
-		if (t == iter) {
-			rcu_assign_pointer(*tp, t->next);
-			break;
-		}
-	}
-}
-
-static void ipip_tunnel_link(struct ipip_net *ipn, struct ip_tunnel *t)
-{
-	struct ip_tunnel __rcu **tp = ipip_bucket(ipn, t);
-
-	rcu_assign_pointer(t->next, rtnl_dereference(*tp));
-	rcu_assign_pointer(*tp, t);
-}
-
-static int ipip_tunnel_create(struct net_device *dev)
-{
-	struct ip_tunnel *t = netdev_priv(dev);
-	struct net *net = dev_net(dev);
-	struct ipip_net *ipn = net_generic(net, ipip_net_id);
-	int err;
-
-	err = ipip_tunnel_init(dev);
-	if (err < 0)
-		goto out;
-
-	err = register_netdevice(dev);
-	if (err < 0)
-		goto out;
-
-	strcpy(t->parms.name, dev->name);
-	dev->rtnl_link_ops = &ipip_link_ops;
-
-	dev_hold(dev);
-	ipip_tunnel_link(ipn, t);
-	return 0;
-
-out:
-	return err;
-}
-
-static struct ip_tunnel *ipip_tunnel_locate(struct net *net,
-		struct ip_tunnel_parm *parms, int create)
-{
-	__be32 remote = parms->iph.daddr;
-	__be32 local = parms->iph.saddr;
-	struct ip_tunnel *t, *nt;
-	struct ip_tunnel __rcu **tp;
-	struct net_device *dev;
-	char name[IFNAMSIZ];
-	struct ipip_net *ipn = net_generic(net, ipip_net_id);
-
-	for (tp = __ipip_bucket(ipn, parms);
-		 (t = rtnl_dereference(*tp)) != NULL;
-		 tp = &t->next) {
-		if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr)
-			return t;
-	}
-	if (!create)
-		return NULL;
-
-	if (parms->name[0])
-		strlcpy(name, parms->name, IFNAMSIZ);
-	else
-		strcpy(name, "tunl%d");
-
-	dev = alloc_netdev(sizeof(*t), name, ipip_tunnel_setup);
-	if (dev == NULL)
-		return NULL;
-
-	dev_net_set(dev, net);
-
-	nt = netdev_priv(dev);
-	nt->parms = *parms;
-
-	if (ipip_tunnel_create(dev) < 0)
-		goto failed_free;
-
-	return nt;
-
-failed_free:
-	ipip_dev_free(dev);
-	return NULL;
-}
-
-/* called with RTNL */
-static void ipip_tunnel_uninit(struct net_device *dev)
-{
-	struct net *net = dev_net(dev);
-	struct ipip_net *ipn = net_generic(net, ipip_net_id);
-
-	if (dev == ipn->fb_tunnel_dev)
-		RCU_INIT_POINTER(ipn->tunnels_wc[0], NULL);
-	else
-		ipip_tunnel_unlink(ipn, netdev_priv(dev));
-	dev_put(dev);
-}
-
 static int ipip_err(struct sk_buff *skb, u32 info)
 {
 
@@ -339,41 +133,17 @@ static int ipip_err(struct sk_buff *skb, u32 info)
    8 bytes of packet payload. It means, that precise relaying of
    ICMP in the real Internet is absolutely infeasible.
  */
+	struct net *net = dev_net(skb->dev);
+	struct ip_tunnel_net *itn = net_generic(net, ipip_net_id);
 	const struct iphdr *iph = (const struct iphdr *)skb->data;
-	const int type = icmp_hdr(skb)->type;
-	const int code = icmp_hdr(skb)->code;
 	struct ip_tunnel *t;
 	int err;
-
-	switch (type) {
-	default:
-	case ICMP_PARAMETERPROB:
-		return 0;
-
-	case ICMP_DEST_UNREACH:
-		switch (code) {
-		case ICMP_SR_FAILED:
-		case ICMP_PORT_UNREACH:
-			/* Impossible event. */
-			return 0;
-		default:
-			/* All others are translated to HOST_UNREACH.
-			   rfc2003 contains "deep thoughts" about NET_UNREACH,
-			   I believe they are just ether pollution. --ANK
-			 */
-			break;
-		}
-		break;
-	case ICMP_TIME_EXCEEDED:
-		if (code != ICMP_EXC_TTL)
-			return 0;
-		break;
-	case ICMP_REDIRECT:
-		break;
-	}
+	const int type = icmp_hdr(skb)->type;
+	const int code = icmp_hdr(skb)->code;
 
 	err = -ENOENT;
-	t = ipip_tunnel_lookup(dev_net(skb->dev), iph->daddr, iph->saddr);
+	t = ip_tunnel_lookup(itn, skb->dev->ifindex, TUNNEL_NO_KEY,
+			     iph->daddr, iph->saddr, 0);
 	if (t == NULL)
 		goto out;
 
@@ -403,53 +173,29 @@ static int ipip_err(struct sk_buff *skb, u32 info)
 	else
 		t->err_count = 1;
 	t->err_time = jiffies;
-out:
 
+out:
 	return err;
 }
 
+static const struct tnl_ptk_info tpi = {
+	/* no tunnel info required for ipip. */
+	.proto = htons(ETH_P_IP),
+};
+
 static int ipip_rcv(struct sk_buff *skb)
 {
+	struct net *net = dev_net(skb->dev);
+	struct ip_tunnel_net *itn = net_generic(net, ipip_net_id);
 	struct ip_tunnel *tunnel;
 	const struct iphdr *iph = ip_hdr(skb);
-	int err;
-
-	tunnel = ipip_tunnel_lookup(dev_net(skb->dev), iph->saddr, iph->daddr);
-	if (tunnel != NULL) {
-		struct pcpu_tstats *tstats;
 
+	tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, TUNNEL_NO_KEY,
+			iph->saddr, iph->daddr, 0);
+	if (tunnel) {
 		if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
 			goto drop;
-
-		secpath_reset(skb);
-
-		skb->mac_header = skb->network_header;
-		skb_reset_network_header(skb);
-		skb->protocol = htons(ETH_P_IP);
-		skb->pkt_type = PACKET_HOST;
-
-		__skb_tunnel_rx(skb, tunnel->dev);
-
-		err = IP_ECN_decapsulate(iph, skb);
-		if (unlikely(err)) {
-			if (log_ecn_error)
-				net_info_ratelimited("non-ECT from %pI4 with TOS=%#x\n",
-						     &iph->saddr, iph->tos);
-			if (err > 1) {
-				++tunnel->dev->stats.rx_frame_errors;
-				++tunnel->dev->stats.rx_errors;
-				goto drop;
-			}
-		}
-
-		tstats = this_cpu_ptr(tunnel->dev->tstats);
-		u64_stats_update_begin(&tstats->syncp);
-		tstats->rx_packets++;
-		tstats->rx_bytes += skb->len;
-		u64_stats_update_end(&tstats->syncp);
-
-		netif_rx(skb);
-		return 0;
+		return ip_tunnel_rcv(tunnel, skb, &tpi, log_ecn_error);
 	}
 
 	return -1;
@@ -463,329 +209,64 @@ drop:
  *	This function assumes it is being called from dev_queue_xmit()
  *	and that skb is filled properly by that function.
  */
-
 static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct ip_tunnel *tunnel = netdev_priv(dev);
 	const struct iphdr  *tiph = &tunnel->parms.iph;
-	u8     tos = tunnel->parms.iph.tos;
-	__be16 df = tiph->frag_off;
-	struct rtable *rt;     			/* Route to the other host */
-	struct net_device *tdev;		/* Device to other host */
-	const struct iphdr  *old_iph;
-	struct iphdr  *iph;			/* Our new IP header */
-	unsigned int max_headroom;		/* The extra header space needed */
-	__be32 dst = tiph->daddr;
-	struct flowi4 fl4;
-	int    mtu;
-
-	if (skb->protocol != htons(ETH_P_IP))
-		goto tx_error;
 
-	if (skb->ip_summed == CHECKSUM_PARTIAL &&
-	    skb_checksum_help(skb))
+	if (unlikely(skb->protocol != htons(ETH_P_IP)))
 		goto tx_error;
 
-	old_iph = ip_hdr(skb);
-
-	if (tos & 1)
-		tos = old_iph->tos;
-
-	if (!dst) {
-		/* NBMA tunnel */
-		if ((rt = skb_rtable(skb)) == NULL) {
-			dev->stats.tx_fifo_errors++;
-			goto tx_error;
-		}
-		dst = rt_nexthop(rt, old_iph->daddr);
+	if (likely(!skb->encapsulation)) {
+		skb_reset_inner_headers(skb);
+		skb->encapsulation = 1;
 	}
 
-	rt = ip_route_output_ports(dev_net(dev), &fl4, NULL,
-				   dst, tiph->saddr,
-				   0, 0,
-				   IPPROTO_IPIP, RT_TOS(tos),
-				   tunnel->parms.link);
-	if (IS_ERR(rt)) {
-		dev->stats.tx_carrier_errors++;
-		goto tx_error_icmp;
-	}
-	tdev = rt->dst.dev;
-
-	if (tdev == dev) {
-		ip_rt_put(rt);
-		dev->stats.collisions++;
-		goto tx_error;
-	}
-
-	df |= old_iph->frag_off & htons(IP_DF);
-
-	if (df) {
-		mtu = dst_mtu(&rt->dst) - sizeof(struct iphdr);
-
-		if (mtu < 68) {
-			dev->stats.collisions++;
-			ip_rt_put(rt);
-			goto tx_error;
-		}
-
-		if (skb_dst(skb))
-			skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu);
-
-		if ((old_iph->frag_off & htons(IP_DF)) &&
-		    mtu < ntohs(old_iph->tot_len)) {
-			icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
-				  htonl(mtu));
-			ip_rt_put(rt);
-			goto tx_error;
-		}
-	}
-
-	if (tunnel->err_count > 0) {
-		if (time_before(jiffies,
-				tunnel->err_time + IPTUNNEL_ERR_TIMEO)) {
-			tunnel->err_count--;
-			dst_link_failure(skb);
-		} else
-			tunnel->err_count = 0;
-	}
-
-	/*
-	 * Okay, now see if we can stuff it in the buffer as-is.
-	 */
-	max_headroom = (LL_RESERVED_SPACE(tdev)+sizeof(struct iphdr));
-
-	if (skb_headroom(skb) < max_headroom || skb_shared(skb) ||
-	    (skb_cloned(skb) && !skb_clone_writable(skb, 0))) {
-		struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom);
-		if (!new_skb) {
-			ip_rt_put(rt);
-			dev->stats.tx_dropped++;
-			dev_kfree_skb(skb);
-			return NETDEV_TX_OK;
-		}
-		if (skb->sk)
-			skb_set_owner_w(new_skb, skb->sk);
-		dev_kfree_skb(skb);
-		skb = new_skb;
-		old_iph = ip_hdr(skb);
-	}
-
-	skb->transport_header = skb->network_header;
-	skb_push(skb, sizeof(struct iphdr));
-	skb_reset_network_header(skb);
-	memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
-	IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED |
-			      IPSKB_REROUTED);
-	skb_dst_drop(skb);
-	skb_dst_set(skb, &rt->dst);
-
-	/*
-	 *	Push down and install the IPIP header.
-	 */
-
-	iph 			=	ip_hdr(skb);
-	iph->version		=	4;
-	iph->ihl		=	sizeof(struct iphdr)>>2;
-	iph->frag_off		=	df;
-	iph->protocol		=	IPPROTO_IPIP;
-	iph->tos		=	INET_ECN_encapsulate(tos, old_iph->tos);
-	iph->daddr		=	fl4.daddr;
-	iph->saddr		=	fl4.saddr;
-
-	if ((iph->ttl = tiph->ttl) == 0)
-		iph->ttl	=	old_iph->ttl;
-
-	iptunnel_xmit(skb, dev);
+	ip_tunnel_xmit(skb, dev, tiph);
 	return NETDEV_TX_OK;
 
-tx_error_icmp:
-	dst_link_failure(skb);
 tx_error:
 	dev->stats.tx_errors++;
 	dev_kfree_skb(skb);
 	return NETDEV_TX_OK;
 }
 
-static void ipip_tunnel_bind_dev(struct net_device *dev)
-{
-	struct net_device *tdev = NULL;
-	struct ip_tunnel *tunnel;
-	const struct iphdr *iph;
-
-	tunnel = netdev_priv(dev);
-	iph = &tunnel->parms.iph;
-
-	if (iph->daddr) {
-		struct rtable *rt;
-		struct flowi4 fl4;
-
-		rt = ip_route_output_ports(dev_net(dev), &fl4, NULL,
-					   iph->daddr, iph->saddr,
-					   0, 0,
-					   IPPROTO_IPIP,
-					   RT_TOS(iph->tos),
-					   tunnel->parms.link);
-		if (!IS_ERR(rt)) {
-			tdev = rt->dst.dev;
-			ip_rt_put(rt);
-		}
-		dev->flags |= IFF_POINTOPOINT;
-	}
-
-	if (!tdev && tunnel->parms.link)
-		tdev = __dev_get_by_index(dev_net(dev), tunnel->parms.link);
-
-	if (tdev) {
-		dev->hard_header_len = tdev->hard_header_len + sizeof(struct iphdr);
-		dev->mtu = tdev->mtu - sizeof(struct iphdr);
-	}
-	dev->iflink = tunnel->parms.link;
-}
-
-static void ipip_tunnel_update(struct ip_tunnel *t, struct ip_tunnel_parm *p)
-{
-	struct net *net = dev_net(t->dev);
-	struct ipip_net *ipn = net_generic(net, ipip_net_id);
-
-	ipip_tunnel_unlink(ipn, t);
-	synchronize_net();
-	t->parms.iph.saddr = p->iph.saddr;
-	t->parms.iph.daddr = p->iph.daddr;
-	memcpy(t->dev->dev_addr, &p->iph.saddr, 4);
-	memcpy(t->dev->broadcast, &p->iph.daddr, 4);
-	ipip_tunnel_link(ipn, t);
-	t->parms.iph.ttl = p->iph.ttl;
-	t->parms.iph.tos = p->iph.tos;
-	t->parms.iph.frag_off = p->iph.frag_off;
-	if (t->parms.link != p->link) {
-		t->parms.link = p->link;
-		ipip_tunnel_bind_dev(t->dev);
-	}
-	netdev_state_change(t->dev);
-}
-
 static int
-ipip_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
+ipip_tunnel_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
 	int err = 0;
 	struct ip_tunnel_parm p;
-	struct ip_tunnel *t;
-	struct net *net = dev_net(dev);
-	struct ipip_net *ipn = net_generic(net, ipip_net_id);
-
-	switch (cmd) {
-	case SIOCGETTUNNEL:
-		t = NULL;
-		if (dev == ipn->fb_tunnel_dev) {
-			if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) {
-				err = -EFAULT;
-				break;
-			}
-			t = ipip_tunnel_locate(net, &p, 0);
-		}
-		if (t == NULL)
-			t = netdev_priv(dev);
-		memcpy(&p, &t->parms, sizeof(p));
-		if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p)))
-			err = -EFAULT;
-		break;
-
-	case SIOCADDTUNNEL:
-	case SIOCCHGTUNNEL:
-		err = -EPERM;
-		if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
-			goto done;
-
-		err = -EFAULT;
-		if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
-			goto done;
-
-		err = -EINVAL;
-		if (p.iph.version != 4 || p.iph.protocol != IPPROTO_IPIP ||
-		    p.iph.ihl != 5 || (p.iph.frag_off&htons(~IP_DF)))
-			goto done;
-		if (p.iph.ttl)
-			p.iph.frag_off |= htons(IP_DF);
-
-		t = ipip_tunnel_locate(net, &p, cmd == SIOCADDTUNNEL);
-
-		if (dev != ipn->fb_tunnel_dev && cmd == SIOCCHGTUNNEL) {
-			if (t != NULL) {
-				if (t->dev != dev) {
-					err = -EEXIST;
-					break;
-				}
-			} else {
-				if (((dev->flags&IFF_POINTOPOINT) && !p.iph.daddr) ||
-				    (!(dev->flags&IFF_POINTOPOINT) && p.iph.daddr)) {
-					err = -EINVAL;
-					break;
-				}
-				t = netdev_priv(dev);
-			}
-
-			ipip_tunnel_update(t, &p);
-		}
-
-		if (t) {
-			err = 0;
-			if (copy_to_user(ifr->ifr_ifru.ifru_data, &t->parms, sizeof(p)))
-				err = -EFAULT;
-		} else
-			err = (cmd == SIOCADDTUNNEL ? -ENOBUFS : -ENOENT);
-		break;
-
-	case SIOCDELTUNNEL:
-		err = -EPERM;
-		if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
-			goto done;
-
-		if (dev == ipn->fb_tunnel_dev) {
-			err = -EFAULT;
-			if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
-				goto done;
-			err = -ENOENT;
-			if ((t = ipip_tunnel_locate(net, &p, 0)) == NULL)
-				goto done;
-			err = -EPERM;
-			if (t->dev == ipn->fb_tunnel_dev)
-				goto done;
-			dev = t->dev;
-		}
-		unregister_netdevice(dev);
-		err = 0;
-		break;
 
-	default:
-		err = -EINVAL;
-	}
-
-done:
-	return err;
-}
+	if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
+		return -EFAULT;
 
-static int ipip_tunnel_change_mtu(struct net_device *dev, int new_mtu)
-{
-	if (new_mtu < 68 || new_mtu > 0xFFF8 - sizeof(struct iphdr))
+	if (p.iph.version != 4 || p.iph.protocol != IPPROTO_IPIP ||
+			p.iph.ihl != 5 || (p.iph.frag_off&htons(~IP_DF)))
+		return -EINVAL;
+	if (p.i_key || p.o_key || p.i_flags || p.o_flags)
 		return -EINVAL;
-	dev->mtu = new_mtu;
+	if (p.iph.ttl)
+		p.iph.frag_off |= htons(IP_DF);
+
+	err = ip_tunnel_ioctl(dev, &p, cmd);
+	if (err)
+		return err;
+
+	if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p)))
+		return -EFAULT;
+
 	return 0;
 }
 
 static const struct net_device_ops ipip_netdev_ops = {
-	.ndo_uninit	= ipip_tunnel_uninit,
+	.ndo_init       = ipip_tunnel_init,
+	.ndo_uninit     = ip_tunnel_uninit,
 	.ndo_start_xmit	= ipip_tunnel_xmit,
 	.ndo_do_ioctl	= ipip_tunnel_ioctl,
-	.ndo_change_mtu	= ipip_tunnel_change_mtu,
-	.ndo_get_stats64 = ipip_get_stats64,
+	.ndo_change_mtu = ip_tunnel_change_mtu,
+	.ndo_get_stats64 = ip_tunnel_get_stats64,
 };
 
-static void ipip_dev_free(struct net_device *dev)
-{
-	free_percpu(dev->tstats);
-	free_netdev(dev);
-}
-
 #define IPIP_FEATURES (NETIF_F_SG |		\
 		       NETIF_F_FRAGLIST |	\
 		       NETIF_F_HIGHDMA |	\
@@ -794,11 +275,8 @@ static void ipip_dev_free(struct net_device *dev)
 static void ipip_tunnel_setup(struct net_device *dev)
 {
 	dev->netdev_ops		= &ipip_netdev_ops;
-	dev->destructor		= ipip_dev_free;
 
 	dev->type		= ARPHRD_TUNNEL;
-	dev->hard_header_len 	= LL_MAX_HEADER + sizeof(struct iphdr);
-	dev->mtu		= ETH_DATA_LEN - sizeof(struct iphdr);
 	dev->flags		= IFF_NOARP;
 	dev->iflink		= 0;
 	dev->addr_len		= 4;
@@ -808,46 +286,19 @@ static void ipip_tunnel_setup(struct net_device *dev)
 
 	dev->features		|= IPIP_FEATURES;
 	dev->hw_features	|= IPIP_FEATURES;
+	ip_tunnel_setup(dev, ipip_net_id);
 }
 
 static int ipip_tunnel_init(struct net_device *dev)
 {
 	struct ip_tunnel *tunnel = netdev_priv(dev);
 
-	tunnel->dev = dev;
-
 	memcpy(dev->dev_addr, &tunnel->parms.iph.saddr, 4);
 	memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4);
 
-	ipip_tunnel_bind_dev(dev);
-
-	dev->tstats = alloc_percpu(struct pcpu_tstats);
-	if (!dev->tstats)
-		return -ENOMEM;
-
-	return 0;
-}
-
-static int __net_init ipip_fb_tunnel_init(struct net_device *dev)
-{
-	struct ip_tunnel *tunnel = netdev_priv(dev);
-	struct iphdr *iph = &tunnel->parms.iph;
-	struct ipip_net *ipn = net_generic(dev_net(dev), ipip_net_id);
-
-	tunnel->dev = dev;
-	strcpy(tunnel->parms.name, dev->name);
-
-	iph->version		= 4;
-	iph->protocol		= IPPROTO_IPIP;
-	iph->ihl		= 5;
-
-	dev->tstats = alloc_percpu(struct pcpu_tstats);
-	if (!dev->tstats)
-		return -ENOMEM;
-
-	dev_hold(dev);
-	rcu_assign_pointer(ipn->tunnels_wc[0], tunnel);
-	return 0;
+	tunnel->hlen = 0;
+	tunnel->parms.iph.protocol = IPPROTO_IPIP;
+	return ip_tunnel_init(dev);
 }
 
 static void ipip_netlink_parms(struct nlattr *data[],
@@ -887,28 +338,16 @@ static void ipip_netlink_parms(struct nlattr *data[],
 static int ipip_newlink(struct net *src_net, struct net_device *dev,
 			struct nlattr *tb[], struct nlattr *data[])
 {
-	struct net *net = dev_net(dev);
-	struct ip_tunnel *nt;
-
-	nt = netdev_priv(dev);
-	ipip_netlink_parms(data, &nt->parms);
-
-	if (ipip_tunnel_locate(net, &nt->parms, 0))
-		return -EEXIST;
+	struct ip_tunnel_parm p;
 
-	return ipip_tunnel_create(dev);
+	ipip_netlink_parms(data, &p);
+	return ip_tunnel_newlink(dev, tb, &p);
 }
 
 static int ipip_changelink(struct net_device *dev, struct nlattr *tb[],
 			   struct nlattr *data[])
 {
-	struct ip_tunnel *t;
 	struct ip_tunnel_parm p;
-	struct net *net = dev_net(dev);
-	struct ipip_net *ipn = net_generic(net, ipip_net_id);
-
-	if (dev == ipn->fb_tunnel_dev)
-		return -EINVAL;
 
 	ipip_netlink_parms(data, &p);
 
@@ -916,16 +355,7 @@ static int ipip_changelink(struct net_device *dev, struct nlattr *tb[],
 	    (!(dev->flags & IFF_POINTOPOINT) && p.iph.daddr))
 		return -EINVAL;
 
-	t = ipip_tunnel_locate(net, &p, 0);
-
-	if (t) {
-		if (t->dev != dev)
-			return -EEXIST;
-	} else
-		t = netdev_priv(dev);
-
-	ipip_tunnel_update(t, &p);
-	return 0;
+	return ip_tunnel_changelink(dev, tb, &p);
 }
 
 static size_t ipip_get_size(const struct net_device *dev)
@@ -982,6 +412,7 @@ static struct rtnl_link_ops ipip_link_ops __read_mostly = {
 	.setup		= ipip_tunnel_setup,
 	.newlink	= ipip_newlink,
 	.changelink	= ipip_changelink,
+	.dellink	= ip_tunnel_dellink,
 	.get_size	= ipip_get_size,
 	.fill_info	= ipip_fill_info,
 };
@@ -992,90 +423,29 @@ static struct xfrm_tunnel ipip_handler __read_mostly = {
 	.priority	=	1,
 };
 
-static const char banner[] __initconst =
-	KERN_INFO "IPv4 over IPv4 tunneling driver\n";
-
-static void ipip_destroy_tunnels(struct ipip_net *ipn, struct list_head *head)
-{
-	int prio;
-
-	for (prio = 1; prio < 4; prio++) {
-		int h;
-		for (h = 0; h < HASH_SIZE; h++) {
-			struct ip_tunnel *t;
-
-			t = rtnl_dereference(ipn->tunnels[prio][h]);
-			while (t != NULL) {
-				unregister_netdevice_queue(t->dev, head);
-				t = rtnl_dereference(t->next);
-			}
-		}
-	}
-}
-
 static int __net_init ipip_init_net(struct net *net)
 {
-	struct ipip_net *ipn = net_generic(net, ipip_net_id);
-	struct ip_tunnel *t;
-	int err;
-
-	ipn->tunnels[0] = ipn->tunnels_wc;
-	ipn->tunnels[1] = ipn->tunnels_l;
-	ipn->tunnels[2] = ipn->tunnels_r;
-	ipn->tunnels[3] = ipn->tunnels_r_l;
-
-	ipn->fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel),
-					   "tunl0",
-					   ipip_tunnel_setup);
-	if (!ipn->fb_tunnel_dev) {
-		err = -ENOMEM;
-		goto err_alloc_dev;
-	}
-	dev_net_set(ipn->fb_tunnel_dev, net);
-
-	err = ipip_fb_tunnel_init(ipn->fb_tunnel_dev);
-	if (err)
-		goto err_reg_dev;
-
-	if ((err = register_netdev(ipn->fb_tunnel_dev)))
-		goto err_reg_dev;
-
-	t = netdev_priv(ipn->fb_tunnel_dev);
-
-	strcpy(t->parms.name, ipn->fb_tunnel_dev->name);
-	return 0;
-
-err_reg_dev:
-	ipip_dev_free(ipn->fb_tunnel_dev);
-err_alloc_dev:
-	/* nothing */
-	return err;
+	return ip_tunnel_init_net(net, ipip_net_id, &ipip_link_ops, "tunl0");
 }
 
 static void __net_exit ipip_exit_net(struct net *net)
 {
-	struct ipip_net *ipn = net_generic(net, ipip_net_id);
-	LIST_HEAD(list);
-
-	rtnl_lock();
-	ipip_destroy_tunnels(ipn, &list);
-	unregister_netdevice_queue(ipn->fb_tunnel_dev, &list);
-	unregister_netdevice_many(&list);
-	rtnl_unlock();
+	struct ip_tunnel_net *itn = net_generic(net, ipip_net_id);
+	ip_tunnel_delete_net(itn);
 }
 
 static struct pernet_operations ipip_net_ops = {
 	.init = ipip_init_net,
 	.exit = ipip_exit_net,
 	.id   = &ipip_net_id,
-	.size = sizeof(struct ipip_net),
+	.size = sizeof(struct ip_tunnel_net),
 };
 
 static int __init ipip_init(void)
 {
 	int err;
 
-	printk(banner);
+	pr_info("ipip: IPv4 over IPv4 tunneling driver\n");
 
 	err = register_pernet_device(&ipip_net_ops);
 	if (err < 0)
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index 5f95b3a..9d9610a 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -61,7 +61,7 @@
 #include <linux/netfilter_ipv4.h>
 #include <linux/compat.h>
 #include <linux/export.h>
-#include <net/ipip.h>
+#include <net/ip_tunnels.h>
 #include <net/checksum.h>
 #include <net/netlink.h>
 #include <net/fib_rules.h>
@@ -626,9 +626,9 @@ static void ipmr_destroy_unres(struct mr_table *mrt, struct mfc_cache *c)
 		if (ip_hdr(skb)->version == 0) {
 			struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct iphdr));
 			nlh->nlmsg_type = NLMSG_ERROR;
-			nlh->nlmsg_len = NLMSG_LENGTH(sizeof(struct nlmsgerr));
+			nlh->nlmsg_len = nlmsg_msg_size(sizeof(struct nlmsgerr));
 			skb_trim(skb, nlh->nlmsg_len);
-			e = NLMSG_DATA(nlh);
+			e = nlmsg_data(nlh);
 			e->error = -ETIMEDOUT;
 			memset(&e->msg, 0, sizeof(e->msg));
 
@@ -910,14 +910,14 @@ static void ipmr_cache_resolve(struct net *net, struct mr_table *mrt,
 		if (ip_hdr(skb)->version == 0) {
 			struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct iphdr));
 
-			if (__ipmr_fill_mroute(mrt, skb, c, NLMSG_DATA(nlh)) > 0) {
+			if (__ipmr_fill_mroute(mrt, skb, c, nlmsg_data(nlh)) > 0) {
 				nlh->nlmsg_len = skb_tail_pointer(skb) -
 						 (u8 *)nlh;
 			} else {
 				nlh->nlmsg_type = NLMSG_ERROR;
-				nlh->nlmsg_len = NLMSG_LENGTH(sizeof(struct nlmsgerr));
+				nlh->nlmsg_len = nlmsg_msg_size(sizeof(struct nlmsgerr));
 				skb_trim(skb, nlh->nlmsg_len);
-				e = NLMSG_DATA(nlh);
+				e = nlmsg_data(nlh);
 				e->error = -EMSGSIZE;
 				memset(&e->msg, 0, sizeof(e->msg));
 			}
diff --git a/net/ipv4/netfilter/arptable_filter.c b/net/ipv4/netfilter/arptable_filter.c
index 79ca5e7..eadab1e 100644
--- a/net/ipv4/netfilter/arptable_filter.c
+++ b/net/ipv4/netfilter/arptable_filter.c
@@ -48,9 +48,7 @@ static int __net_init arptable_filter_net_init(struct net *net)
 	net->ipv4.arptable_filter =
 		arpt_register_table(net, &packet_filter, repl);
 	kfree(repl);
-	if (IS_ERR(net->ipv4.arptable_filter))
-		return PTR_ERR(net->ipv4.arptable_filter);
-	return 0;
+	return PTR_RET(net->ipv4.arptable_filter);
 }
 
 static void __net_exit arptable_filter_net_exit(struct net *net)
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
index 5852b24..e4738fe 100644
--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
+++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
@@ -631,7 +631,7 @@ static int clusterip_proc_open(struct inode *inode, struct file *file)
 
 	if (!ret) {
 		struct seq_file *sf = file->private_data;
-		struct clusterip_config *c = PDE(inode)->data;
+		struct clusterip_config *c = PDE_DATA(inode);
 
 		sf->private = c;
 
@@ -643,7 +643,7 @@ static int clusterip_proc_open(struct inode *inode, struct file *file)
 
 static int clusterip_proc_release(struct inode *inode, struct file *file)
 {
-	struct clusterip_config *c = PDE(inode)->data;
+	struct clusterip_config *c = PDE_DATA(inode);
 	int ret;
 
 	ret = seq_release(inode, file);
@@ -657,7 +657,7 @@ static int clusterip_proc_release(struct inode *inode, struct file *file)
 static ssize_t clusterip_proc_write(struct file *file, const char __user *input,
 				size_t size, loff_t *ofs)
 {
-	struct clusterip_config *c = PDE(file_inode(file))->data;
+	struct clusterip_config *c = PDE_DATA(file_inode(file));
 #define PROC_WRITELEN	10
 	char buffer[PROC_WRITELEN+1];
 	unsigned long nodenum;
diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c
index 7d168dc..e7f8cad 100644
--- a/net/ipv4/netfilter/ipt_ULOG.c
+++ b/net/ipv4/netfilter/ipt_ULOG.c
@@ -37,7 +37,7 @@
 #include <linux/skbuff.h>
 #include <linux/kernel.h>
 #include <linux/timer.h>
-#include <linux/netlink.h>
+#include <net/netlink.h>
 #include <linux/netdevice.h>
 #include <linux/mm.h>
 #include <linux/moduleparam.h>
@@ -172,7 +172,7 @@ static void ipt_ulog_packet(unsigned int hooknum,
 	else
 		copy_len = loginfo->copy_range;
 
-	size = NLMSG_SPACE(sizeof(*pm) + copy_len);
+	size = nlmsg_total_size(sizeof(*pm) + copy_len);
 
 	ub = &ulog_buffers[groupnum];
 
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c
index 32030a2..b6f2ea1 100644
--- a/net/ipv4/proc.c
+++ b/net/ipv4/proc.c
@@ -224,6 +224,8 @@ static const struct snmp_mib snmp4_net_list[] = {
 	SNMP_MIB_ITEM("TCPForwardRetrans", LINUX_MIB_TCPFORWARDRETRANS),
 	SNMP_MIB_ITEM("TCPSlowStartRetrans", LINUX_MIB_TCPSLOWSTARTRETRANS),
 	SNMP_MIB_ITEM("TCPTimeouts", LINUX_MIB_TCPTIMEOUTS),
+	SNMP_MIB_ITEM("TCPLossProbes", LINUX_MIB_TCPLOSSPROBES),
+	SNMP_MIB_ITEM("TCPLossProbeRecovery", LINUX_MIB_TCPLOSSPROBERECOVERY),
 	SNMP_MIB_ITEM("TCPRenoRecoveryFail", LINUX_MIB_TCPRENORECOVERYFAIL),
 	SNMP_MIB_ITEM("TCPSackRecoveryFail", LINUX_MIB_TCPSACKRECOVERYFAIL),
 	SNMP_MIB_ITEM("TCPSchedulerFailed", LINUX_MIB_TCPSCHEDULERFAILED),
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 6e28514..550781a 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -2311,7 +2311,7 @@ nla_put_failure:
 	return -EMSGSIZE;
 }
 
-static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, void *arg)
+static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh)
 {
 	struct net *net = sock_net(in_skb->sk);
 	struct rtmsg *rtm;
diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c
index ef54377..7f4a5cb 100644
--- a/net/ipv4/syncookies.c
+++ b/net/ipv4/syncookies.c
@@ -267,7 +267,6 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
 			     struct ip_options *opt)
 {
 	struct tcp_options_received tcp_opt;
-	const u8 *hash_location;
 	struct inet_request_sock *ireq;
 	struct tcp_request_sock *treq;
 	struct tcp_sock *tp = tcp_sk(sk);
@@ -294,7 +293,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
 
 	/* check for timestamp cookie support */
 	memset(&tcp_opt, 0, sizeof(tcp_opt));
-	tcp_parse_options(skb, &tcp_opt, &hash_location, 0, NULL);
+	tcp_parse_options(skb, &tcp_opt, 0, NULL);
 
 	if (!cookie_check_timestamp(&tcp_opt, sock_net(sk), &ecn_ok))
 		goto out;
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index 960fd29..fa2f63f 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -28,7 +28,7 @@
 
 static int zero;
 static int one = 1;
-static int two = 2;
+static int four = 4;
 static int tcp_retr1_max = 255;
 static int ip_local_port_range_min[] = { 1, 1 };
 static int ip_local_port_range_max[] = { 65535, 65535 };
@@ -592,13 +592,6 @@ static struct ctl_table ipv4_table[] = {
 		.proc_handler	= proc_dointvec
 	},
 	{
-		.procname	= "tcp_frto_response",
-		.data		= &sysctl_tcp_frto_response,
-		.maxlen		= sizeof(int),
-		.mode		= 0644,
-		.proc_handler	= proc_dointvec
-	},
-	{
 		.procname	= "tcp_low_latency",
 		.data		= &sysctl_tcp_low_latency,
 		.maxlen		= sizeof(int),
@@ -733,13 +726,6 @@ static struct ctl_table ipv4_table[] = {
 		.proc_handler	= proc_dointvec,
 	},
 	{
-		.procname	= "tcp_cookie_size",
-		.data		= &sysctl_tcp_cookie_size,
-		.maxlen		= sizeof(int),
-		.mode		= 0644,
-		.proc_handler	= proc_dointvec
-	},
-	{
 		.procname       = "tcp_thin_linear_timeouts",
 		.data           = &sysctl_tcp_thin_linear_timeouts,
 		.maxlen         = sizeof(int),
@@ -760,7 +746,7 @@ static struct ctl_table ipv4_table[] = {
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_minmax,
 		.extra1		= &zero,
-		.extra2		= &two,
+		.extra2		= &four,
 	},
 	{
 		.procname	= "udp_mem",
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index e220207..a96f7b5 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -409,15 +409,6 @@ void tcp_init_sock(struct sock *sk)
 
 	icsk->icsk_sync_mss = tcp_sync_mss;
 
-	/* TCP Cookie Transactions */
-	if (sysctl_tcp_cookie_size > 0) {
-		/* Default, cookies without s_data_payload. */
-		tp->cookie_values =
-			kzalloc(sizeof(*tp->cookie_values),
-				sk->sk_allocation);
-		if (tp->cookie_values != NULL)
-			kref_init(&tp->cookie_values->kref);
-	}
 	/* Presumed zeroed, in order of appearance:
 	 *	cookie_in_always, cookie_out_never,
 	 *	s_data_constant, s_data_in, s_data_out
@@ -2397,92 +2388,6 @@ static int do_tcp_setsockopt(struct sock *sk, int level,
 		release_sock(sk);
 		return err;
 	}
-	case TCP_COOKIE_TRANSACTIONS: {
-		struct tcp_cookie_transactions ctd;
-		struct tcp_cookie_values *cvp = NULL;
-
-		if (sizeof(ctd) > optlen)
-			return -EINVAL;
-		if (copy_from_user(&ctd, optval, sizeof(ctd)))
-			return -EFAULT;
-
-		if (ctd.tcpct_used > sizeof(ctd.tcpct_value) ||
-		    ctd.tcpct_s_data_desired > TCP_MSS_DESIRED)
-			return -EINVAL;
-
-		if (ctd.tcpct_cookie_desired == 0) {
-			/* default to global value */
-		} else if ((0x1 & ctd.tcpct_cookie_desired) ||
-			   ctd.tcpct_cookie_desired > TCP_COOKIE_MAX ||
-			   ctd.tcpct_cookie_desired < TCP_COOKIE_MIN) {
-			return -EINVAL;
-		}
-
-		if (TCP_COOKIE_OUT_NEVER & ctd.tcpct_flags) {
-			/* Supercedes all other values */
-			lock_sock(sk);
-			if (tp->cookie_values != NULL) {
-				kref_put(&tp->cookie_values->kref,
-					 tcp_cookie_values_release);
-				tp->cookie_values = NULL;
-			}
-			tp->rx_opt.cookie_in_always = 0; /* false */
-			tp->rx_opt.cookie_out_never = 1; /* true */
-			release_sock(sk);
-			return err;
-		}
-
-		/* Allocate ancillary memory before locking.
-		 */
-		if (ctd.tcpct_used > 0 ||
-		    (tp->cookie_values == NULL &&
-		     (sysctl_tcp_cookie_size > 0 ||
-		      ctd.tcpct_cookie_desired > 0 ||
-		      ctd.tcpct_s_data_desired > 0))) {
-			cvp = kzalloc(sizeof(*cvp) + ctd.tcpct_used,
-				      GFP_KERNEL);
-			if (cvp == NULL)
-				return -ENOMEM;
-
-			kref_init(&cvp->kref);
-		}
-		lock_sock(sk);
-		tp->rx_opt.cookie_in_always =
-			(TCP_COOKIE_IN_ALWAYS & ctd.tcpct_flags);
-		tp->rx_opt.cookie_out_never = 0; /* false */
-
-		if (tp->cookie_values != NULL) {
-			if (cvp != NULL) {
-				/* Changed values are recorded by a changed
-				 * pointer, ensuring the cookie will differ,
-				 * without separately hashing each value later.
-				 */
-				kref_put(&tp->cookie_values->kref,
-					 tcp_cookie_values_release);
-			} else {
-				cvp = tp->cookie_values;
-			}
-		}
-
-		if (cvp != NULL) {
-			cvp->cookie_desired = ctd.tcpct_cookie_desired;
-
-			if (ctd.tcpct_used > 0) {
-				memcpy(cvp->s_data_payload, ctd.tcpct_value,
-				       ctd.tcpct_used);
-				cvp->s_data_desired = ctd.tcpct_used;
-				cvp->s_data_constant = 1; /* true */
-			} else {
-				/* No constant payload data. */
-				cvp->s_data_desired = ctd.tcpct_s_data_desired;
-				cvp->s_data_constant = 0; /* false */
-			}
-
-			tp->cookie_values = cvp;
-		}
-		release_sock(sk);
-		return err;
-	}
 	default:
 		/* fallthru */
 		break;
@@ -2902,41 +2807,6 @@ static int do_tcp_getsockopt(struct sock *sk, int level,
 			return -EFAULT;
 		return 0;
 
-	case TCP_COOKIE_TRANSACTIONS: {
-		struct tcp_cookie_transactions ctd;
-		struct tcp_cookie_values *cvp = tp->cookie_values;
-
-		if (get_user(len, optlen))
-			return -EFAULT;
-		if (len < sizeof(ctd))
-			return -EINVAL;
-
-		memset(&ctd, 0, sizeof(ctd));
-		ctd.tcpct_flags = (tp->rx_opt.cookie_in_always ?
-				   TCP_COOKIE_IN_ALWAYS : 0)
-				| (tp->rx_opt.cookie_out_never ?
-				   TCP_COOKIE_OUT_NEVER : 0);
-
-		if (cvp != NULL) {
-			ctd.tcpct_flags |= (cvp->s_data_in ?
-					    TCP_S_DATA_IN : 0)
-					 | (cvp->s_data_out ?
-					    TCP_S_DATA_OUT : 0);
-
-			ctd.tcpct_cookie_desired = cvp->cookie_desired;
-			ctd.tcpct_s_data_desired = cvp->s_data_desired;
-
-			memcpy(&ctd.tcpct_value[0], &cvp->cookie_pair[0],
-			       cvp->cookie_pair_size);
-			ctd.tcpct_used = cvp->cookie_pair_size;
-		}
-
-		if (put_user(sizeof(ctd), optlen))
-			return -EFAULT;
-		if (copy_to_user(optval, &ctd, sizeof(ctd)))
-			return -EFAULT;
-		return 0;
-	}
 	case TCP_THIN_LINEAR_TIMEOUTS:
 		val = tp->thin_lto;
 		break;
@@ -3044,6 +2914,7 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb,
 			       SKB_GSO_TCP_ECN |
 			       SKB_GSO_TCPV6 |
 			       SKB_GSO_GRE |
+			       SKB_GSO_UDP_TUNNEL |
 			       0) ||
 			     !(type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6))))
 			goto out;
@@ -3408,134 +3279,6 @@ EXPORT_SYMBOL(tcp_md5_hash_key);
 
 #endif
 
-/* Each Responder maintains up to two secret values concurrently for
- * efficient secret rollover.  Each secret value has 4 states:
- *
- * Generating.  (tcp_secret_generating != tcp_secret_primary)
- *    Generates new Responder-Cookies, but not yet used for primary
- *    verification.  This is a short-term state, typically lasting only
- *    one round trip time (RTT).
- *
- * Primary.  (tcp_secret_generating == tcp_secret_primary)
- *    Used both for generation and primary verification.
- *
- * Retiring.  (tcp_secret_retiring != tcp_secret_secondary)
- *    Used for verification, until the first failure that can be
- *    verified by the newer Generating secret.  At that time, this
- *    cookie's state is changed to Secondary, and the Generating
- *    cookie's state is changed to Primary.  This is a short-term state,
- *    typically lasting only one round trip time (RTT).
- *
- * Secondary.  (tcp_secret_retiring == tcp_secret_secondary)
- *    Used for secondary verification, after primary verification
- *    failures.  This state lasts no more than twice the Maximum Segment
- *    Lifetime (2MSL).  Then, the secret is discarded.
- */
-struct tcp_cookie_secret {
-	/* The secret is divided into two parts.  The digest part is the
-	 * equivalent of previously hashing a secret and saving the state,
-	 * and serves as an initialization vector (IV).  The message part
-	 * serves as the trailing secret.
-	 */
-	u32				secrets[COOKIE_WORKSPACE_WORDS];
-	unsigned long			expires;
-};
-
-#define TCP_SECRET_1MSL (HZ * TCP_PAWS_MSL)
-#define TCP_SECRET_2MSL (HZ * TCP_PAWS_MSL * 2)
-#define TCP_SECRET_LIFE (HZ * 600)
-
-static struct tcp_cookie_secret tcp_secret_one;
-static struct tcp_cookie_secret tcp_secret_two;
-
-/* Essentially a circular list, without dynamic allocation. */
-static struct tcp_cookie_secret *tcp_secret_generating;
-static struct tcp_cookie_secret *tcp_secret_primary;
-static struct tcp_cookie_secret *tcp_secret_retiring;
-static struct tcp_cookie_secret *tcp_secret_secondary;
-
-static DEFINE_SPINLOCK(tcp_secret_locker);
-
-/* Select a pseudo-random word in the cookie workspace.
- */
-static inline u32 tcp_cookie_work(const u32 *ws, const int n)
-{
-	return ws[COOKIE_DIGEST_WORDS + ((COOKIE_MESSAGE_WORDS-1) & ws[n])];
-}
-
-/* Fill bakery[COOKIE_WORKSPACE_WORDS] with generator, updating as needed.
- * Called in softirq context.
- * Returns: 0 for success.
- */
-int tcp_cookie_generator(u32 *bakery)
-{
-	unsigned long jiffy = jiffies;
-
-	if (unlikely(time_after_eq(jiffy, tcp_secret_generating->expires))) {
-		spin_lock_bh(&tcp_secret_locker);
-		if (!time_after_eq(jiffy, tcp_secret_generating->expires)) {
-			/* refreshed by another */
-			memcpy(bakery,
-			       &tcp_secret_generating->secrets[0],
-			       COOKIE_WORKSPACE_WORDS);
-		} else {
-			/* still needs refreshing */
-			get_random_bytes(bakery, COOKIE_WORKSPACE_WORDS);
-
-			/* The first time, paranoia assumes that the
-			 * randomization function isn't as strong.  But,
-			 * this secret initialization is delayed until
-			 * the last possible moment (packet arrival).
-			 * Although that time is observable, it is
-			 * unpredictably variable.  Mash in the most
-			 * volatile clock bits available, and expire the
-			 * secret extra quickly.
-			 */
-			if (unlikely(tcp_secret_primary->expires ==
-				     tcp_secret_secondary->expires)) {
-				struct timespec tv;
-
-				getnstimeofday(&tv);
-				bakery[COOKIE_DIGEST_WORDS+0] ^=
-					(u32)tv.tv_nsec;
-
-				tcp_secret_secondary->expires = jiffy
-					+ TCP_SECRET_1MSL
-					+ (0x0f & tcp_cookie_work(bakery, 0));
-			} else {
-				tcp_secret_secondary->expires = jiffy
-					+ TCP_SECRET_LIFE
-					+ (0xff & tcp_cookie_work(bakery, 1));
-				tcp_secret_primary->expires = jiffy
-					+ TCP_SECRET_2MSL
-					+ (0x1f & tcp_cookie_work(bakery, 2));
-			}
-			memcpy(&tcp_secret_secondary->secrets[0],
-			       bakery, COOKIE_WORKSPACE_WORDS);
-
-			rcu_assign_pointer(tcp_secret_generating,
-					   tcp_secret_secondary);
-			rcu_assign_pointer(tcp_secret_retiring,
-					   tcp_secret_primary);
-			/*
-			 * Neither call_rcu() nor synchronize_rcu() needed.
-			 * Retiring data is not freed.  It is replaced after
-			 * further (locked) pointer updates, and a quiet time
-			 * (minimum 1MSL, maximum LIFE - 2MSL).
-			 */
-		}
-		spin_unlock_bh(&tcp_secret_locker);
-	} else {
-		rcu_read_lock_bh();
-		memcpy(bakery,
-		       &rcu_dereference(tcp_secret_generating)->secrets[0],
-		       COOKIE_WORKSPACE_WORDS);
-		rcu_read_unlock_bh();
-	}
-	return 0;
-}
-EXPORT_SYMBOL(tcp_cookie_generator);
-
 void tcp_done(struct sock *sk)
 {
 	struct request_sock *req = tcp_sk(sk)->fastopen_rsk;
@@ -3590,7 +3333,6 @@ void __init tcp_init(void)
 	unsigned long limit;
 	int max_rshare, max_wshare, cnt;
 	unsigned int i;
-	unsigned long jiffy = jiffies;
 
 	BUILD_BUG_ON(sizeof(struct tcp_skb_cb) > sizeof(skb->cb));
 
@@ -3666,13 +3408,5 @@ void __init tcp_init(void)
 
 	tcp_register_congestion_control(&tcp_reno);
 
-	memset(&tcp_secret_one.secrets[0], 0, sizeof(tcp_secret_one.secrets));
-	memset(&tcp_secret_two.secrets[0], 0, sizeof(tcp_secret_two.secrets));
-	tcp_secret_one.expires = jiffy; /* past due */
-	tcp_secret_two.expires = jiffy; /* past due */
-	tcp_secret_generating = &tcp_secret_one;
-	tcp_secret_primary = &tcp_secret_one;
-	tcp_secret_retiring = &tcp_secret_two;
-	tcp_secret_secondary = &tcp_secret_two;
 	tcp_tasklet_init();
 }
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 3bd55ba..6d9ca35 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -93,12 +93,11 @@ int sysctl_tcp_stdurg __read_mostly;
 int sysctl_tcp_rfc1337 __read_mostly;
 int sysctl_tcp_max_orphans __read_mostly = NR_FILE;
 int sysctl_tcp_frto __read_mostly = 2;
-int sysctl_tcp_frto_response __read_mostly;
 
 int sysctl_tcp_thin_dupack __read_mostly;
 
 int sysctl_tcp_moderate_rcvbuf __read_mostly = 1;
-int sysctl_tcp_early_retrans __read_mostly = 2;
+int sysctl_tcp_early_retrans __read_mostly = 3;
 
 #define FLAG_DATA		0x01 /* Incoming frame contained data.		*/
 #define FLAG_WIN_UPDATE		0x02 /* Incoming ACK was a window update.	*/
@@ -108,17 +107,15 @@ int sysctl_tcp_early_retrans __read_mostly = 2;
 #define FLAG_DATA_SACKED	0x20 /* New SACK.				*/
 #define FLAG_ECE		0x40 /* ECE in this ACK				*/
 #define FLAG_SLOWPATH		0x100 /* Do not skip RFC checks for window update.*/
-#define FLAG_ONLY_ORIG_SACKED	0x200 /* SACKs only non-rexmit sent before RTO */
+#define FLAG_ORIG_SACK_ACKED	0x200 /* Never retransmitted data are (s)acked	*/
 #define FLAG_SND_UNA_ADVANCED	0x400 /* Snd_una was changed (!= FLAG_DATA_ACKED) */
 #define FLAG_DSACKING_ACK	0x800 /* SACK blocks contained D-SACK info */
-#define FLAG_NONHEAD_RETRANS_ACKED	0x1000 /* Non-head rexmitted data was ACKed */
 #define FLAG_SACK_RENEGING	0x2000 /* snd_una advanced to a sacked seq */
 
 #define FLAG_ACKED		(FLAG_DATA_ACKED|FLAG_SYN_ACKED)
 #define FLAG_NOT_DUP		(FLAG_DATA|FLAG_WIN_UPDATE|FLAG_ACKED)
 #define FLAG_CA_ALERT		(FLAG_DATA_SACKED|FLAG_ECE)
 #define FLAG_FORWARD_PROGRESS	(FLAG_ACKED|FLAG_DATA_SACKED)
-#define FLAG_ANY_PROGRESS	(FLAG_FORWARD_PROGRESS|FLAG_SND_UNA_ADVANCED)
 
 #define TCP_REMNANT (TCP_FLAG_FIN|TCP_FLAG_URG|TCP_FLAG_SYN|TCP_FLAG_PSH)
 #define TCP_HP_BITS (~(TCP_RESERVED_BITS|TCP_FLAG_PSH))
@@ -1159,10 +1156,8 @@ static u8 tcp_sacktag_one(struct sock *sk,
 					   tcp_highest_sack_seq(tp)))
 					state->reord = min(fack_count,
 							   state->reord);
-
-				/* SACK enhanced F-RTO (RFC4138; Appendix B) */
-				if (!after(end_seq, tp->frto_highmark))
-					state->flag |= FLAG_ONLY_ORIG_SACKED;
+				if (!after(end_seq, tp->high_seq))
+					state->flag |= FLAG_ORIG_SACK_ACKED;
 			}
 
 			if (sacked & TCPCB_LOST) {
@@ -1555,7 +1550,6 @@ static int
 tcp_sacktag_write_queue(struct sock *sk, const struct sk_buff *ack_skb,
 			u32 prior_snd_una)
 {
-	const struct inet_connection_sock *icsk = inet_csk(sk);
 	struct tcp_sock *tp = tcp_sk(sk);
 	const unsigned char *ptr = (skb_transport_header(ack_skb) +
 				    TCP_SKB_CB(ack_skb)->sacked);
@@ -1728,12 +1722,6 @@ walk:
 				       start_seq, end_seq, dup_sack);
 
 advance_sp:
-		/* SACK enhanced FRTO (RFC4138, Appendix B): Clearing correct
-		 * due to in-order walk
-		 */
-		if (after(end_seq, tp->frto_highmark))
-			state.flag &= ~FLAG_ONLY_ORIG_SACKED;
-
 		i++;
 	}
 
@@ -1750,8 +1738,7 @@ advance_sp:
 	tcp_verify_left_out(tp);
 
 	if ((state.reord < tp->fackets_out) &&
-	    ((icsk->icsk_ca_state != TCP_CA_Loss) || tp->undo_marker) &&
-	    (!tp->frto_highmark || after(tp->snd_una, tp->frto_highmark)))
+	    ((inet_csk(sk)->icsk_ca_state != TCP_CA_Loss) || tp->undo_marker))
 		tcp_update_reordering(sk, tp->fackets_out - state.reord, 0);
 
 out:
@@ -1825,197 +1812,6 @@ static inline void tcp_reset_reno_sack(struct tcp_sock *tp)
 	tp->sacked_out = 0;
 }
 
-static int tcp_is_sackfrto(const struct tcp_sock *tp)
-{
-	return (sysctl_tcp_frto == 0x2) && !tcp_is_reno(tp);
-}
-
-/* F-RTO can only be used if TCP has never retransmitted anything other than
- * head (SACK enhanced variant from Appendix B of RFC4138 is more robust here)
- */
-bool tcp_use_frto(struct sock *sk)
-{
-	const struct tcp_sock *tp = tcp_sk(sk);
-	const struct inet_connection_sock *icsk = inet_csk(sk);
-	struct sk_buff *skb;
-
-	if (!sysctl_tcp_frto)
-		return false;
-
-	/* MTU probe and F-RTO won't really play nicely along currently */
-	if (icsk->icsk_mtup.probe_size)
-		return false;
-
-	if (tcp_is_sackfrto(tp))
-		return true;
-
-	/* Avoid expensive walking of rexmit queue if possible */
-	if (tp->retrans_out > 1)
-		return false;
-
-	skb = tcp_write_queue_head(sk);
-	if (tcp_skb_is_last(sk, skb))
-		return true;
-	skb = tcp_write_queue_next(sk, skb);	/* Skips head */
-	tcp_for_write_queue_from(skb, sk) {
-		if (skb == tcp_send_head(sk))
-			break;
-		if (TCP_SKB_CB(skb)->sacked & TCPCB_RETRANS)
-			return false;
-		/* Short-circuit when first non-SACKed skb has been checked */
-		if (!(TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED))
-			break;
-	}
-	return true;
-}
-
-/* RTO occurred, but do not yet enter Loss state. Instead, defer RTO
- * recovery a bit and use heuristics in tcp_process_frto() to detect if
- * the RTO was spurious. Only clear SACKED_RETRANS of the head here to
- * keep retrans_out counting accurate (with SACK F-RTO, other than head
- * may still have that bit set); TCPCB_LOST and remaining SACKED_RETRANS
- * bits are handled if the Loss state is really to be entered (in
- * tcp_enter_frto_loss).
- *
- * Do like tcp_enter_loss() would; when RTO expires the second time it
- * does:
- *  "Reduce ssthresh if it has not yet been made inside this window."
- */
-void tcp_enter_frto(struct sock *sk)
-{
-	const struct inet_connection_sock *icsk = inet_csk(sk);
-	struct tcp_sock *tp = tcp_sk(sk);
-	struct sk_buff *skb;
-
-	if ((!tp->frto_counter && icsk->icsk_ca_state <= TCP_CA_Disorder) ||
-	    tp->snd_una == tp->high_seq ||
-	    ((icsk->icsk_ca_state == TCP_CA_Loss || tp->frto_counter) &&
-	     !icsk->icsk_retransmits)) {
-		tp->prior_ssthresh = tcp_current_ssthresh(sk);
-		/* Our state is too optimistic in ssthresh() call because cwnd
-		 * is not reduced until tcp_enter_frto_loss() when previous F-RTO
-		 * recovery has not yet completed. Pattern would be this: RTO,
-		 * Cumulative ACK, RTO (2xRTO for the same segment does not end
-		 * up here twice).
-		 * RFC4138 should be more specific on what to do, even though
-		 * RTO is quite unlikely to occur after the first Cumulative ACK
-		 * due to back-off and complexity of triggering events ...
-		 */
-		if (tp->frto_counter) {
-			u32 stored_cwnd;
-			stored_cwnd = tp->snd_cwnd;
-			tp->snd_cwnd = 2;
-			tp->snd_ssthresh = icsk->icsk_ca_ops->ssthresh(sk);
-			tp->snd_cwnd = stored_cwnd;
-		} else {
-			tp->snd_ssthresh = icsk->icsk_ca_ops->ssthresh(sk);
-		}
-		/* ... in theory, cong.control module could do "any tricks" in
-		 * ssthresh(), which means that ca_state, lost bits and lost_out
-		 * counter would have to be faked before the call occurs. We
-		 * consider that too expensive, unlikely and hacky, so modules
-		 * using these in ssthresh() must deal these incompatibility
-		 * issues if they receives CA_EVENT_FRTO and frto_counter != 0
-		 */
-		tcp_ca_event(sk, CA_EVENT_FRTO);
-	}
-
-	tp->undo_marker = tp->snd_una;
-	tp->undo_retrans = 0;
-
-	skb = tcp_write_queue_head(sk);
-	if (TCP_SKB_CB(skb)->sacked & TCPCB_RETRANS)
-		tp->undo_marker = 0;
-	if (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_RETRANS) {
-		TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_RETRANS;
-		tp->retrans_out -= tcp_skb_pcount(skb);
-	}
-	tcp_verify_left_out(tp);
-
-	/* Too bad if TCP was application limited */
-	tp->snd_cwnd = min(tp->snd_cwnd, tcp_packets_in_flight(tp) + 1);
-
-	/* Earlier loss recovery underway (see RFC4138; Appendix B).
-	 * The last condition is necessary at least in tp->frto_counter case.
-	 */
-	if (tcp_is_sackfrto(tp) && (tp->frto_counter ||
-	    ((1 << icsk->icsk_ca_state) & (TCPF_CA_Recovery|TCPF_CA_Loss))) &&
-	    after(tp->high_seq, tp->snd_una)) {
-		tp->frto_highmark = tp->high_seq;
-	} else {
-		tp->frto_highmark = tp->snd_nxt;
-	}
-	tcp_set_ca_state(sk, TCP_CA_Disorder);
-	tp->high_seq = tp->snd_nxt;
-	tp->frto_counter = 1;
-}
-
-/* Enter Loss state after F-RTO was applied. Dupack arrived after RTO,
- * which indicates that we should follow the traditional RTO recovery,
- * i.e. mark everything lost and do go-back-N retransmission.
- */
-static void tcp_enter_frto_loss(struct sock *sk, int allowed_segments, int flag)
-{
-	struct tcp_sock *tp = tcp_sk(sk);
-	struct sk_buff *skb;
-
-	tp->lost_out = 0;
-	tp->retrans_out = 0;
-	if (tcp_is_reno(tp))
-		tcp_reset_reno_sack(tp);
-
-	tcp_for_write_queue(skb, sk) {
-		if (skb == tcp_send_head(sk))
-			break;
-
-		TCP_SKB_CB(skb)->sacked &= ~TCPCB_LOST;
-		/*
-		 * Count the retransmission made on RTO correctly (only when
-		 * waiting for the first ACK and did not get it)...
-		 */
-		if ((tp->frto_counter == 1) && !(flag & FLAG_DATA_ACKED)) {
-			/* For some reason this R-bit might get cleared? */
-			if (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_RETRANS)
-				tp->retrans_out += tcp_skb_pcount(skb);
-			/* ...enter this if branch just for the first segment */
-			flag |= FLAG_DATA_ACKED;
-		} else {
-			if (TCP_SKB_CB(skb)->sacked & TCPCB_RETRANS)
-				tp->undo_marker = 0;
-			TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_RETRANS;
-		}
-
-		/* Marking forward transmissions that were made after RTO lost
-		 * can cause unnecessary retransmissions in some scenarios,
-		 * SACK blocks will mitigate that in some but not in all cases.
-		 * We used to not mark them but it was causing break-ups with
-		 * receivers that do only in-order receival.
-		 *
-		 * TODO: we could detect presence of such receiver and select
-		 * different behavior per flow.
-		 */
-		if (!(TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED)) {
-			TCP_SKB_CB(skb)->sacked |= TCPCB_LOST;
-			tp->lost_out += tcp_skb_pcount(skb);
-			tp->retransmit_high = TCP_SKB_CB(skb)->end_seq;
-		}
-	}
-	tcp_verify_left_out(tp);
-
-	tp->snd_cwnd = tcp_packets_in_flight(tp) + allowed_segments;
-	tp->snd_cwnd_cnt = 0;
-	tp->snd_cwnd_stamp = tcp_time_stamp;
-	tp->frto_counter = 0;
-
-	tp->reordering = min_t(unsigned int, tp->reordering,
-			       sysctl_tcp_reordering);
-	tcp_set_ca_state(sk, TCP_CA_Loss);
-	tp->high_seq = tp->snd_nxt;
-	TCP_ECN_queue_cwr(tp);
-
-	tcp_clear_all_retrans_hints(tp);
-}
-
 static void tcp_clear_retrans_partial(struct tcp_sock *tp)
 {
 	tp->retrans_out = 0;
@@ -2042,10 +1838,13 @@ void tcp_enter_loss(struct sock *sk, int how)
 	const struct inet_connection_sock *icsk = inet_csk(sk);
 	struct tcp_sock *tp = tcp_sk(sk);
 	struct sk_buff *skb;
+	bool new_recovery = false;
 
 	/* Reduce ssthresh if it has not yet been made inside this window. */
-	if (icsk->icsk_ca_state <= TCP_CA_Disorder || tp->snd_una == tp->high_seq ||
+	if (icsk->icsk_ca_state <= TCP_CA_Disorder ||
+	    !after(tp->high_seq, tp->snd_una) ||
 	    (icsk->icsk_ca_state == TCP_CA_Loss && !icsk->icsk_retransmits)) {
+		new_recovery = true;
 		tp->prior_ssthresh = tcp_current_ssthresh(sk);
 		tp->snd_ssthresh = icsk->icsk_ca_ops->ssthresh(sk);
 		tcp_ca_event(sk, CA_EVENT_LOSS);
@@ -2087,8 +1886,14 @@ void tcp_enter_loss(struct sock *sk, int how)
 	tcp_set_ca_state(sk, TCP_CA_Loss);
 	tp->high_seq = tp->snd_nxt;
 	TCP_ECN_queue_cwr(tp);
-	/* Abort F-RTO algorithm if one is in progress */
-	tp->frto_counter = 0;
+
+	/* F-RTO RFC5682 sec 3.1 step 1: retransmit SND.UNA if no previous
+	 * loss recovery is underway except recurring timeout(s) on
+	 * the same SND.UNA (sec 3.2). Disable F-RTO on path MTU probing
+	 */
+	tp->frto = sysctl_tcp_frto &&
+		   (new_recovery || icsk->icsk_retransmits) &&
+		   !inet_csk(sk)->icsk_mtup.probe_size;
 }
 
 /* If ACK arrived pointing to a remembered SACK, it means that our
@@ -2147,15 +1952,16 @@ static bool tcp_pause_early_retransmit(struct sock *sk, int flag)
 	 * max(RTT/4, 2msec) unless ack has ECE mark, no RTT samples
 	 * available, or RTO is scheduled to fire first.
 	 */
-	if (sysctl_tcp_early_retrans < 2 || (flag & FLAG_ECE) || !tp->srtt)
+	if (sysctl_tcp_early_retrans < 2 || sysctl_tcp_early_retrans > 3 ||
+	    (flag & FLAG_ECE) || !tp->srtt)
 		return false;
 
 	delay = max_t(unsigned long, (tp->srtt >> 5), msecs_to_jiffies(2));
 	if (!time_after(inet_csk(sk)->icsk_timeout, (jiffies + delay)))
 		return false;
 
-	inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, delay, TCP_RTO_MAX);
-	tp->early_retrans_delayed = 1;
+	inet_csk_reset_xmit_timer(sk, ICSK_TIME_EARLY_RETRANS, delay,
+				  TCP_RTO_MAX);
 	return true;
 }
 
@@ -2271,10 +2077,6 @@ static bool tcp_time_to_recover(struct sock *sk, int flag)
 	struct tcp_sock *tp = tcp_sk(sk);
 	__u32 packets_out;
 
-	/* Do not perform any recovery during F-RTO algorithm */
-	if (tp->frto_counter)
-		return false;
-
 	/* Trick#1: The loss is proven. */
 	if (tp->lost_out)
 		return true;
@@ -2318,7 +2120,7 @@ static bool tcp_time_to_recover(struct sock *sk, int flag)
 	 * interval if appropriate.
 	 */
 	if (tp->do_early_retrans && !tp->retrans_out && tp->sacked_out &&
-	    (tp->packets_out == (tp->sacked_out + 1) && tp->packets_out < 4) &&
+	    (tp->packets_out >= (tp->sacked_out + 1) && tp->packets_out < 4) &&
 	    !tcp_may_send_now(sk))
 		return !tcp_pause_early_retransmit(sk, flag);
 
@@ -2635,12 +2437,12 @@ static int tcp_try_undo_partial(struct sock *sk, int acked)
 	return failed;
 }
 
-/* Undo during loss recovery after partial ACK. */
-static bool tcp_try_undo_loss(struct sock *sk)
+/* Undo during loss recovery after partial ACK or using F-RTO. */
+static bool tcp_try_undo_loss(struct sock *sk, bool frto_undo)
 {
 	struct tcp_sock *tp = tcp_sk(sk);
 
-	if (tcp_may_undo(tp)) {
+	if (frto_undo || tcp_may_undo(tp)) {
 		struct sk_buff *skb;
 		tcp_for_write_queue(skb, sk) {
 			if (skb == tcp_send_head(sk))
@@ -2654,9 +2456,12 @@ static bool tcp_try_undo_loss(struct sock *sk)
 		tp->lost_out = 0;
 		tcp_undo_cwr(sk, true);
 		NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPLOSSUNDO);
+		if (frto_undo)
+			NET_INC_STATS_BH(sock_net(sk),
+					 LINUX_MIB_TCPSPURIOUSRTOS);
 		inet_csk(sk)->icsk_retransmits = 0;
 		tp->undo_marker = 0;
-		if (tcp_is_sack(tp))
+		if (frto_undo || tcp_is_sack(tp))
 			tcp_set_ca_state(sk, TCP_CA_Open);
 		return true;
 	}
@@ -2678,6 +2483,7 @@ static void tcp_init_cwnd_reduction(struct sock *sk, const bool set_ssthresh)
 	struct tcp_sock *tp = tcp_sk(sk);
 
 	tp->high_seq = tp->snd_nxt;
+	tp->tlp_high_seq = 0;
 	tp->snd_cwnd_cnt = 0;
 	tp->prior_cwnd = tp->snd_cwnd;
 	tp->prr_delivered = 0;
@@ -2755,7 +2561,7 @@ static void tcp_try_to_open(struct sock *sk, int flag, int newly_acked_sacked)
 
 	tcp_verify_left_out(tp);
 
-	if (!tp->frto_counter && !tcp_any_retrans_done(sk))
+	if (!tcp_any_retrans_done(sk))
 		tp->retrans_stamp = 0;
 
 	if (flag & FLAG_ECE)
@@ -2872,6 +2678,58 @@ static void tcp_enter_recovery(struct sock *sk, bool ece_ack)
 	tcp_set_ca_state(sk, TCP_CA_Recovery);
 }
 
+/* Process an ACK in CA_Loss state. Move to CA_Open if lost data are
+ * recovered or spurious. Otherwise retransmits more on partial ACKs.
+ */
+static void tcp_process_loss(struct sock *sk, int flag, bool is_dupack)
+{
+	struct inet_connection_sock *icsk = inet_csk(sk);
+	struct tcp_sock *tp = tcp_sk(sk);
+	bool recovered = !before(tp->snd_una, tp->high_seq);
+
+	if (tp->frto) { /* F-RTO RFC5682 sec 3.1 (sack enhanced version). */
+		if (flag & FLAG_ORIG_SACK_ACKED) {
+			/* Step 3.b. A timeout is spurious if not all data are
+			 * lost, i.e., never-retransmitted data are (s)acked.
+			 */
+			tcp_try_undo_loss(sk, true);
+			return;
+		}
+		if (after(tp->snd_nxt, tp->high_seq) &&
+		    (flag & FLAG_DATA_SACKED || is_dupack)) {
+			tp->frto = 0; /* Loss was real: 2nd part of step 3.a */
+		} else if (flag & FLAG_SND_UNA_ADVANCED && !recovered) {
+			tp->high_seq = tp->snd_nxt;
+			__tcp_push_pending_frames(sk, tcp_current_mss(sk),
+						  TCP_NAGLE_OFF);
+			if (after(tp->snd_nxt, tp->high_seq))
+				return; /* Step 2.b */
+			tp->frto = 0;
+		}
+	}
+
+	if (recovered) {
+		/* F-RTO RFC5682 sec 3.1 step 2.a and 1st part of step 3.a */
+		icsk->icsk_retransmits = 0;
+		tcp_try_undo_recovery(sk);
+		return;
+	}
+	if (flag & FLAG_DATA_ACKED)
+		icsk->icsk_retransmits = 0;
+	if (tcp_is_reno(tp)) {
+		/* A Reno DUPACK means new data in F-RTO step 2.b above are
+		 * delivered. Lower inflight to clock out (re)tranmissions.
+		 */
+		if (after(tp->snd_nxt, tp->high_seq) && is_dupack)
+			tcp_add_reno_sack(sk);
+		else if (flag & FLAG_SND_UNA_ADVANCED)
+			tcp_reset_reno_sack(tp);
+	}
+	if (tcp_try_undo_loss(sk, false))
+		return;
+	tcp_xmit_retransmit_queue(sk);
+}
+
 /* Process an event, which can update packets-in-flight not trivially.
  * Main goal of this function is to calculate new estimate for left_out,
  * taking into account both packets sitting in receiver's buffer and
@@ -2918,12 +2776,6 @@ static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked,
 		tp->retrans_stamp = 0;
 	} else if (!before(tp->snd_una, tp->high_seq)) {
 		switch (icsk->icsk_ca_state) {
-		case TCP_CA_Loss:
-			icsk->icsk_retransmits = 0;
-			if (tcp_try_undo_recovery(sk))
-				return;
-			break;
-
 		case TCP_CA_CWR:
 			/* CWR is to be held something *above* high_seq
 			 * is ACKed for CWR bit to reach receiver. */
@@ -2954,18 +2806,10 @@ static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked,
 		newly_acked_sacked = pkts_acked + tp->sacked_out - prior_sacked;
 		break;
 	case TCP_CA_Loss:
-		if (flag & FLAG_DATA_ACKED)
-			icsk->icsk_retransmits = 0;
-		if (tcp_is_reno(tp) && flag & FLAG_SND_UNA_ADVANCED)
-			tcp_reset_reno_sack(tp);
-		if (!tcp_try_undo_loss(sk)) {
-			tcp_moderate_cwnd(tp);
-			tcp_xmit_retransmit_queue(sk);
-			return;
-		}
+		tcp_process_loss(sk, flag, is_dupack);
 		if (icsk->icsk_ca_state != TCP_CA_Open)
 			return;
-		/* Loss is undone; fall through to processing in Open state. */
+		/* Fall through to processing in Open state. */
 	default:
 		if (tcp_is_reno(tp)) {
 			if (flag & FLAG_SND_UNA_ADVANCED)
@@ -3078,6 +2922,7 @@ static void tcp_cong_avoid(struct sock *sk, u32 ack, u32 in_flight)
  */
 void tcp_rearm_rto(struct sock *sk)
 {
+	const struct inet_connection_sock *icsk = inet_csk(sk);
 	struct tcp_sock *tp = tcp_sk(sk);
 
 	/* If the retrans timer is currently being used by Fast Open
@@ -3091,12 +2936,13 @@ void tcp_rearm_rto(struct sock *sk)
 	} else {
 		u32 rto = inet_csk(sk)->icsk_rto;
 		/* Offset the time elapsed after installing regular RTO */
-		if (tp->early_retrans_delayed) {
+		if (icsk->icsk_pending == ICSK_TIME_EARLY_RETRANS ||
+		    icsk->icsk_pending == ICSK_TIME_LOSS_PROBE) {
 			struct sk_buff *skb = tcp_write_queue_head(sk);
 			const u32 rto_time_stamp = TCP_SKB_CB(skb)->when + rto;
 			s32 delta = (s32)(rto_time_stamp - tcp_time_stamp);
 			/* delta may not be positive if the socket is locked
-			 * when the delayed ER timer fires and is rescheduled.
+			 * when the retrans timer fires and is rescheduled.
 			 */
 			if (delta > 0)
 				rto = delta;
@@ -3104,7 +2950,6 @@ void tcp_rearm_rto(struct sock *sk)
 		inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, rto,
 					  TCP_RTO_MAX);
 	}
-	tp->early_retrans_delayed = 0;
 }
 
 /* This function is called when the delayed ER timer fires. TCP enters
@@ -3192,8 +3037,6 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets,
 			flag |= FLAG_RETRANS_DATA_ACKED;
 			ca_seq_rtt = -1;
 			seq_rtt = -1;
-			if ((flag & FLAG_DATA_ACKED) || (acked_pcount > 1))
-				flag |= FLAG_NONHEAD_RETRANS_ACKED;
 		} else {
 			ca_seq_rtt = now - scb->when;
 			last_ackt = skb->tstamp;
@@ -3202,6 +3045,8 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets,
 			}
 			if (!(sacked & TCPCB_SACKED_ACKED))
 				reord = min(pkts_acked, reord);
+			if (!after(scb->end_seq, tp->high_seq))
+				flag |= FLAG_ORIG_SACK_ACKED;
 		}
 
 		if (sacked & TCPCB_SACKED_ACKED)
@@ -3402,150 +3247,6 @@ static int tcp_ack_update_window(struct sock *sk, const struct sk_buff *skb, u32
 	return flag;
 }
 
-/* A very conservative spurious RTO response algorithm: reduce cwnd and
- * continue in congestion avoidance.
- */
-static void tcp_conservative_spur_to_response(struct tcp_sock *tp)
-{
-	tp->snd_cwnd = min(tp->snd_cwnd, tp->snd_ssthresh);
-	tp->snd_cwnd_cnt = 0;
-	TCP_ECN_queue_cwr(tp);
-	tcp_moderate_cwnd(tp);
-}
-
-/* A conservative spurious RTO response algorithm: reduce cwnd using
- * PRR and continue in congestion avoidance.
- */
-static void tcp_cwr_spur_to_response(struct sock *sk)
-{
-	tcp_enter_cwr(sk, 0);
-}
-
-static void tcp_undo_spur_to_response(struct sock *sk, int flag)
-{
-	if (flag & FLAG_ECE)
-		tcp_cwr_spur_to_response(sk);
-	else
-		tcp_undo_cwr(sk, true);
-}
-
-/* F-RTO spurious RTO detection algorithm (RFC4138)
- *
- * F-RTO affects during two new ACKs following RTO (well, almost, see inline
- * comments). State (ACK number) is kept in frto_counter. When ACK advances
- * window (but not to or beyond highest sequence sent before RTO):
- *   On First ACK,  send two new segments out.
- *   On Second ACK, RTO was likely spurious. Do spurious response (response
- *                  algorithm is not part of the F-RTO detection algorithm
- *                  given in RFC4138 but can be selected separately).
- * Otherwise (basically on duplicate ACK), RTO was (likely) caused by a loss
- * and TCP falls back to conventional RTO recovery. F-RTO allows overriding
- * of Nagle, this is done using frto_counter states 2 and 3, when a new data
- * segment of any size sent during F-RTO, state 2 is upgraded to 3.
- *
- * Rationale: if the RTO was spurious, new ACKs should arrive from the
- * original window even after we transmit two new data segments.
- *
- * SACK version:
- *   on first step, wait until first cumulative ACK arrives, then move to
- *   the second step. In second step, the next ACK decides.
- *
- * F-RTO is implemented (mainly) in four functions:
- *   - tcp_use_frto() is used to determine if TCP is can use F-RTO
- *   - tcp_enter_frto() prepares TCP state on RTO if F-RTO is used, it is
- *     called when tcp_use_frto() showed green light
- *   - tcp_process_frto() handles incoming ACKs during F-RTO algorithm
- *   - tcp_enter_frto_loss() is called if there is not enough evidence
- *     to prove that the RTO is indeed spurious. It transfers the control
- *     from F-RTO to the conventional RTO recovery
- */
-static bool tcp_process_frto(struct sock *sk, int flag)
-{
-	struct tcp_sock *tp = tcp_sk(sk);
-
-	tcp_verify_left_out(tp);
-
-	/* Duplicate the behavior from Loss state (fastretrans_alert) */
-	if (flag & FLAG_DATA_ACKED)
-		inet_csk(sk)->icsk_retransmits = 0;
-
-	if ((flag & FLAG_NONHEAD_RETRANS_ACKED) ||
-	    ((tp->frto_counter >= 2) && (flag & FLAG_RETRANS_DATA_ACKED)))
-		tp->undo_marker = 0;
-
-	if (!before(tp->snd_una, tp->frto_highmark)) {
-		tcp_enter_frto_loss(sk, (tp->frto_counter == 1 ? 2 : 3), flag);
-		return true;
-	}
-
-	if (!tcp_is_sackfrto(tp)) {
-		/* RFC4138 shortcoming in step 2; should also have case c):
-		 * ACK isn't duplicate nor advances window, e.g., opposite dir
-		 * data, winupdate
-		 */
-		if (!(flag & FLAG_ANY_PROGRESS) && (flag & FLAG_NOT_DUP))
-			return true;
-
-		if (!(flag & FLAG_DATA_ACKED)) {
-			tcp_enter_frto_loss(sk, (tp->frto_counter == 1 ? 0 : 3),
-					    flag);
-			return true;
-		}
-	} else {
-		if (!(flag & FLAG_DATA_ACKED) && (tp->frto_counter == 1)) {
-			if (!tcp_packets_in_flight(tp)) {
-				tcp_enter_frto_loss(sk, 2, flag);
-				return true;
-			}
-
-			/* Prevent sending of new data. */
-			tp->snd_cwnd = min(tp->snd_cwnd,
-					   tcp_packets_in_flight(tp));
-			return true;
-		}
-
-		if ((tp->frto_counter >= 2) &&
-		    (!(flag & FLAG_FORWARD_PROGRESS) ||
-		     ((flag & FLAG_DATA_SACKED) &&
-		      !(flag & FLAG_ONLY_ORIG_SACKED)))) {
-			/* RFC4138 shortcoming (see comment above) */
-			if (!(flag & FLAG_FORWARD_PROGRESS) &&
-			    (flag & FLAG_NOT_DUP))
-				return true;
-
-			tcp_enter_frto_loss(sk, 3, flag);
-			return true;
-		}
-	}
-
-	if (tp->frto_counter == 1) {
-		/* tcp_may_send_now needs to see updated state */
-		tp->snd_cwnd = tcp_packets_in_flight(tp) + 2;
-		tp->frto_counter = 2;
-
-		if (!tcp_may_send_now(sk))
-			tcp_enter_frto_loss(sk, 2, flag);
-
-		return true;
-	} else {
-		switch (sysctl_tcp_frto_response) {
-		case 2:
-			tcp_undo_spur_to_response(sk, flag);
-			break;
-		case 1:
-			tcp_conservative_spur_to_response(tp);
-			break;
-		default:
-			tcp_cwr_spur_to_response(sk);
-			break;
-		}
-		tp->frto_counter = 0;
-		tp->undo_marker = 0;
-		NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPSPURIOUSRTOS);
-	}
-	return false;
-}
-
 /* RFC 5961 7 [ACK Throttling] */
 static void tcp_send_challenge_ack(struct sock *sk)
 {
@@ -3564,6 +3265,38 @@ static void tcp_send_challenge_ack(struct sock *sk)
 	}
 }
 
+/* This routine deals with acks during a TLP episode.
+ * Ref: loss detection algorithm in draft-dukkipati-tcpm-tcp-loss-probe.
+ */
+static void tcp_process_tlp_ack(struct sock *sk, u32 ack, int flag)
+{
+	struct tcp_sock *tp = tcp_sk(sk);
+	bool is_tlp_dupack = (ack == tp->tlp_high_seq) &&
+			     !(flag & (FLAG_SND_UNA_ADVANCED |
+				       FLAG_NOT_DUP | FLAG_DATA_SACKED));
+
+	/* Mark the end of TLP episode on receiving TLP dupack or when
+	 * ack is after tlp_high_seq.
+	 */
+	if (is_tlp_dupack) {
+		tp->tlp_high_seq = 0;
+		return;
+	}
+
+	if (after(ack, tp->tlp_high_seq)) {
+		tp->tlp_high_seq = 0;
+		/* Don't reduce cwnd if DSACK arrives for TLP retrans. */
+		if (!(flag & FLAG_DSACKING_ACK)) {
+			tcp_init_cwnd_reduction(sk, true);
+			tcp_set_ca_state(sk, TCP_CA_CWR);
+			tcp_end_cwnd_reduction(sk);
+			tcp_set_ca_state(sk, TCP_CA_Open);
+			NET_INC_STATS_BH(sock_net(sk),
+					 LINUX_MIB_TCPLOSSPROBERECOVERY);
+		}
+	}
+}
+
 /* This routine deals with incoming acks, but not outgoing ones. */
 static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
 {
@@ -3578,7 +3311,6 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
 	int prior_packets;
 	int prior_sacked = tp->sacked_out;
 	int pkts_acked = 0;
-	bool frto_cwnd = false;
 
 	/* If the ack is older than previous acks
 	 * then we can probably ignore it.
@@ -3598,7 +3330,8 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
 	if (after(ack, tp->snd_nxt))
 		goto invalid_ack;
 
-	if (tp->early_retrans_delayed)
+	if (icsk->icsk_pending == ICSK_TIME_EARLY_RETRANS ||
+	    icsk->icsk_pending == ICSK_TIME_LOSS_PROBE)
 		tcp_rearm_rto(sk);
 
 	if (after(ack, prior_snd_una))
@@ -3651,30 +3384,29 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
 
 	pkts_acked = prior_packets - tp->packets_out;
 
-	if (tp->frto_counter)
-		frto_cwnd = tcp_process_frto(sk, flag);
-	/* Guarantee sacktag reordering detection against wrap-arounds */
-	if (before(tp->frto_highmark, tp->snd_una))
-		tp->frto_highmark = 0;
-
 	if (tcp_ack_is_dubious(sk, flag)) {
 		/* Advance CWND, if state allows this. */
-		if ((flag & FLAG_DATA_ACKED) && !frto_cwnd &&
-		    tcp_may_raise_cwnd(sk, flag))
+		if ((flag & FLAG_DATA_ACKED) && tcp_may_raise_cwnd(sk, flag))
 			tcp_cong_avoid(sk, ack, prior_in_flight);
 		is_dupack = !(flag & (FLAG_SND_UNA_ADVANCED | FLAG_NOT_DUP));
 		tcp_fastretrans_alert(sk, pkts_acked, prior_sacked,
 				      is_dupack, flag);
 	} else {
-		if ((flag & FLAG_DATA_ACKED) && !frto_cwnd)
+		if (flag & FLAG_DATA_ACKED)
 			tcp_cong_avoid(sk, ack, prior_in_flight);
 	}
 
+	if (tp->tlp_high_seq)
+		tcp_process_tlp_ack(sk, ack, flag);
+
 	if ((flag & FLAG_FORWARD_PROGRESS) || !(flag & FLAG_NOT_DUP)) {
 		struct dst_entry *dst = __sk_dst_get(sk);
 		if (dst)
 			dst_confirm(dst);
 	}
+
+	if (icsk->icsk_pending == ICSK_TIME_RETRANS)
+		tcp_schedule_loss_probe(sk);
 	return 1;
 
 no_queue:
@@ -3688,6 +3420,9 @@ no_queue:
 	 */
 	if (tcp_send_head(sk))
 		tcp_ack_probe(sk);
+
+	if (tp->tlp_high_seq)
+		tcp_process_tlp_ack(sk, ack, flag);
 	return 1;
 
 invalid_ack:
@@ -3712,8 +3447,8 @@ old_ack:
  * But, this can also be called on packets in the established flow when
  * the fast version below fails.
  */
-void tcp_parse_options(const struct sk_buff *skb, struct tcp_options_received *opt_rx,
-		       const u8 **hvpp, int estab,
+void tcp_parse_options(const struct sk_buff *skb,
+		       struct tcp_options_received *opt_rx, int estab,
 		       struct tcp_fastopen_cookie *foc)
 {
 	const unsigned char *ptr;
@@ -3797,31 +3532,6 @@ void tcp_parse_options(const struct sk_buff *skb, struct tcp_options_received *o
 				 */
 				break;
 #endif
-			case TCPOPT_COOKIE:
-				/* This option is variable length.
-				 */
-				switch (opsize) {
-				case TCPOLEN_COOKIE_BASE:
-					/* not yet implemented */
-					break;
-				case TCPOLEN_COOKIE_PAIR:
-					/* not yet implemented */
-					break;
-				case TCPOLEN_COOKIE_MIN+0:
-				case TCPOLEN_COOKIE_MIN+2:
-				case TCPOLEN_COOKIE_MIN+4:
-				case TCPOLEN_COOKIE_MIN+6:
-				case TCPOLEN_COOKIE_MAX:
-					/* 16-bit multiple */
-					opt_rx->cookie_plus = opsize;
-					*hvpp = ptr;
-					break;
-				default:
-					/* ignore option */
-					break;
-				}
-				break;
-
 			case TCPOPT_EXP:
 				/* Fast Open option shares code 254 using a
 				 * 16 bits magic number. It's valid only in
@@ -3867,8 +3577,7 @@ static bool tcp_parse_aligned_timestamp(struct tcp_sock *tp, const struct tcphdr
  * If it is wrong it falls back on tcp_parse_options().
  */
 static bool tcp_fast_parse_options(const struct sk_buff *skb,
-				   const struct tcphdr *th,
-				   struct tcp_sock *tp, const u8 **hvpp)
+				   const struct tcphdr *th, struct tcp_sock *tp)
 {
 	/* In the spirit of fast parsing, compare doff directly to constant
 	 * values.  Because equality is used, short doff can be ignored here.
@@ -3882,7 +3591,7 @@ static bool tcp_fast_parse_options(const struct sk_buff *skb,
 			return true;
 	}
 
-	tcp_parse_options(skb, &tp->rx_opt, hvpp, 1, NULL);
+	tcp_parse_options(skb, &tp->rx_opt, 1, NULL);
 	if (tp->rx_opt.saw_tstamp)
 		tp->rx_opt.rcv_tsecr -= tp->tsoffset;
 
@@ -5263,12 +4972,10 @@ out:
 static bool tcp_validate_incoming(struct sock *sk, struct sk_buff *skb,
 				  const struct tcphdr *th, int syn_inerr)
 {
-	const u8 *hash_location;
 	struct tcp_sock *tp = tcp_sk(sk);
 
 	/* RFC1323: H1. Apply PAWS check first. */
-	if (tcp_fast_parse_options(skb, th, tp, &hash_location) &&
-	    tp->rx_opt.saw_tstamp &&
+	if (tcp_fast_parse_options(skb, th, tp) && tp->rx_opt.saw_tstamp &&
 	    tcp_paws_discard(sk, skb)) {
 		if (!th->rst) {
 			NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_PAWSESTABREJECTED);
@@ -5622,12 +5329,11 @@ static bool tcp_rcv_fastopen_synack(struct sock *sk, struct sk_buff *synack,
 
 	if (mss == tp->rx_opt.user_mss) {
 		struct tcp_options_received opt;
-		const u8 *hash_location;
 
 		/* Get original SYNACK MSS value if user MSS sets mss_clamp */
 		tcp_clear_options(&opt);
 		opt.user_mss = opt.mss_clamp = 0;
-		tcp_parse_options(synack, &opt, &hash_location, 0, NULL);
+		tcp_parse_options(synack, &opt, 0, NULL);
 		mss = opt.mss_clamp;
 	}
 
@@ -5658,14 +5364,12 @@ static bool tcp_rcv_fastopen_synack(struct sock *sk, struct sk_buff *synack,
 static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
 					 const struct tcphdr *th, unsigned int len)
 {
-	const u8 *hash_location;
 	struct inet_connection_sock *icsk = inet_csk(sk);
 	struct tcp_sock *tp = tcp_sk(sk);
-	struct tcp_cookie_values *cvp = tp->cookie_values;
 	struct tcp_fastopen_cookie foc = { .len = -1 };
 	int saved_clamp = tp->rx_opt.mss_clamp;
 
-	tcp_parse_options(skb, &tp->rx_opt, &hash_location, 0, &foc);
+	tcp_parse_options(skb, &tp->rx_opt, 0, &foc);
 	if (tp->rx_opt.saw_tstamp)
 		tp->rx_opt.rcv_tsecr -= tp->tsoffset;
 
@@ -5762,30 +5466,6 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
 		 * is initialized. */
 		tp->copied_seq = tp->rcv_nxt;
 
-		if (cvp != NULL &&
-		    cvp->cookie_pair_size > 0 &&
-		    tp->rx_opt.cookie_plus > 0) {
-			int cookie_size = tp->rx_opt.cookie_plus
-					- TCPOLEN_COOKIE_BASE;
-			int cookie_pair_size = cookie_size
-					     + cvp->cookie_desired;
-
-			/* A cookie extension option was sent and returned.
-			 * Note that each incoming SYNACK replaces the
-			 * Responder cookie.  The initial exchange is most
-			 * fragile, as protection against spoofing relies
-			 * entirely upon the sequence and timestamp (above).
-			 * This replacement strategy allows the correct pair to
-			 * pass through, while any others will be filtered via
-			 * Responder verification later.
-			 */
-			if (sizeof(cvp->cookie_pair) >= cookie_pair_size) {
-				memcpy(&cvp->cookie_pair[cvp->cookie_desired],
-				       hash_location, cookie_size);
-				cvp->cookie_pair_size = cookie_pair_size;
-			}
-		}
-
 		smp_mb();
 
 		tcp_finish_connect(sk, skb);
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index d09203c..8667aaa 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -838,7 +838,6 @@ static void tcp_v4_reqsk_send_ack(struct sock *sk, struct sk_buff *skb,
  */
 static int tcp_v4_send_synack(struct sock *sk, struct dst_entry *dst,
 			      struct request_sock *req,
-			      struct request_values *rvp,
 			      u16 queue_mapping,
 			      bool nocache)
 {
@@ -851,7 +850,7 @@ static int tcp_v4_send_synack(struct sock *sk, struct dst_entry *dst,
 	if (!dst && (dst = inet_csk_route_req(sk, &fl4, req)) == NULL)
 		return -1;
 
-	skb = tcp_make_synack(sk, dst, req, rvp, NULL);
+	skb = tcp_make_synack(sk, dst, req, NULL);
 
 	if (skb) {
 		__tcp_v4_send_check(skb, ireq->loc_addr, ireq->rmt_addr);
@@ -868,10 +867,9 @@ static int tcp_v4_send_synack(struct sock *sk, struct dst_entry *dst,
 	return err;
 }
 
-static int tcp_v4_rtx_synack(struct sock *sk, struct request_sock *req,
-			     struct request_values *rvp)
+static int tcp_v4_rtx_synack(struct sock *sk, struct request_sock *req)
 {
-	int res = tcp_v4_send_synack(sk, NULL, req, rvp, 0, false);
+	int res = tcp_v4_send_synack(sk, NULL, req, 0, false);
 
 	if (!res)
 		TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_RETRANSSEGS);
@@ -1371,8 +1369,7 @@ static bool tcp_fastopen_check(struct sock *sk, struct sk_buff *skb,
 static int tcp_v4_conn_req_fastopen(struct sock *sk,
 				    struct sk_buff *skb,
 				    struct sk_buff *skb_synack,
-				    struct request_sock *req,
-				    struct request_values *rvp)
+				    struct request_sock *req)
 {
 	struct tcp_sock *tp = tcp_sk(sk);
 	struct request_sock_queue *queue = &inet_csk(sk)->icsk_accept_queue;
@@ -1467,9 +1464,7 @@ static int tcp_v4_conn_req_fastopen(struct sock *sk,
 
 int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
 {
-	struct tcp_extend_values tmp_ext;
 	struct tcp_options_received tmp_opt;
-	const u8 *hash_location;
 	struct request_sock *req;
 	struct inet_request_sock *ireq;
 	struct tcp_sock *tp = tcp_sk(sk);
@@ -1519,42 +1514,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
 	tcp_clear_options(&tmp_opt);
 	tmp_opt.mss_clamp = TCP_MSS_DEFAULT;
 	tmp_opt.user_mss  = tp->rx_opt.user_mss;
-	tcp_parse_options(skb, &tmp_opt, &hash_location, 0,
-	    want_cookie ? NULL : &foc);
-
-	if (tmp_opt.cookie_plus > 0 &&
-	    tmp_opt.saw_tstamp &&
-	    !tp->rx_opt.cookie_out_never &&
-	    (sysctl_tcp_cookie_size > 0 ||
-	     (tp->cookie_values != NULL &&
-	      tp->cookie_values->cookie_desired > 0))) {
-		u8 *c;
-		u32 *mess = &tmp_ext.cookie_bakery[COOKIE_DIGEST_WORDS];
-		int l = tmp_opt.cookie_plus - TCPOLEN_COOKIE_BASE;
-
-		if (tcp_cookie_generator(&tmp_ext.cookie_bakery[0]) != 0)
-			goto drop_and_release;
-
-		/* Secret recipe starts with IP addresses */
-		*mess++ ^= (__force u32)daddr;
-		*mess++ ^= (__force u32)saddr;
-
-		/* plus variable length Initiator Cookie */
-		c = (u8 *)mess;
-		while (l-- > 0)
-			*c++ ^= *hash_location++;
-
-		want_cookie = false;	/* not our kind of cookie */
-		tmp_ext.cookie_out_never = 0; /* false */
-		tmp_ext.cookie_plus = tmp_opt.cookie_plus;
-	} else if (!tp->rx_opt.cookie_in_always) {
-		/* redundant indications, but ensure initialization. */
-		tmp_ext.cookie_out_never = 1; /* true */
-		tmp_ext.cookie_plus = 0;
-	} else {
-		goto drop_and_release;
-	}
-	tmp_ext.cookie_in_always = tp->rx_opt.cookie_in_always;
+	tcp_parse_options(skb, &tmp_opt, 0, want_cookie ? NULL : &foc);
 
 	if (want_cookie && !tmp_opt.saw_tstamp)
 		tcp_clear_options(&tmp_opt);
@@ -1636,7 +1596,6 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
 	 * of tcp_v4_send_synack()->tcp_select_initial_window().
 	 */
 	skb_synack = tcp_make_synack(sk, dst, req,
-	    (struct request_values *)&tmp_ext,
 	    fastopen_cookie_present(&valid_foc) ? &valid_foc : NULL);
 
 	if (skb_synack) {
@@ -1660,8 +1619,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
 		if (fastopen_cookie_present(&foc) && foc.len != 0)
 			NET_INC_STATS_BH(sock_net(sk),
 			    LINUX_MIB_TCPFASTOPENPASSIVEFAIL);
-	} else if (tcp_v4_conn_req_fastopen(sk, skb, skb_synack, req,
-	    (struct request_values *)&tmp_ext))
+	} else if (tcp_v4_conn_req_fastopen(sk, skb, skb_synack, req))
 		goto drop_and_free;
 
 	return 0;
@@ -1950,6 +1908,50 @@ void tcp_v4_early_demux(struct sk_buff *skb)
 	}
 }
 
+/* Packet is added to VJ-style prequeue for processing in process
+ * context, if a reader task is waiting. Apparently, this exciting
+ * idea (VJ's mail "Re: query about TCP header on tcp-ip" of 07 Sep 93)
+ * failed somewhere. Latency? Burstiness? Well, at least now we will
+ * see, why it failed. 8)8)				  --ANK
+ *
+ */
+bool tcp_prequeue(struct sock *sk, struct sk_buff *skb)
+{
+	struct tcp_sock *tp = tcp_sk(sk);
+
+	if (sysctl_tcp_low_latency || !tp->ucopy.task)
+		return false;
+
+	if (skb->len <= tcp_hdrlen(skb) &&
+	    skb_queue_len(&tp->ucopy.prequeue) == 0)
+		return false;
+
+	__skb_queue_tail(&tp->ucopy.prequeue, skb);
+	tp->ucopy.memory += skb->truesize;
+	if (tp->ucopy.memory > sk->sk_rcvbuf) {
+		struct sk_buff *skb1;
+
+		BUG_ON(sock_owned_by_user(sk));
+
+		while ((skb1 = __skb_dequeue(&tp->ucopy.prequeue)) != NULL) {
+			sk_backlog_rcv(sk, skb1);
+			NET_INC_STATS_BH(sock_net(sk),
+					 LINUX_MIB_TCPPREQUEUEDROPPED);
+		}
+
+		tp->ucopy.memory = 0;
+	} else if (skb_queue_len(&tp->ucopy.prequeue) == 1) {
+		wake_up_interruptible_sync_poll(sk_sleep(sk),
+					   POLLIN | POLLRDNORM | POLLRDBAND);
+		if (!inet_csk_ack_scheduled(sk))
+			inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK,
+						  (3 * tcp_rto_min(sk)) / 4,
+						  TCP_RTO_MAX);
+	}
+	return true;
+}
+EXPORT_SYMBOL(tcp_prequeue);
+
 /*
  *	From tcp_input.c
  */
@@ -2197,12 +2199,6 @@ void tcp_v4_destroy_sock(struct sock *sk)
 	if (inet_csk(sk)->icsk_bind_hash)
 		inet_put_port(sk);
 
-	/* TCP Cookie Transactions */
-	if (tp->cookie_values != NULL) {
-		kref_put(&tp->cookie_values->kref,
-			 tcp_cookie_values_release);
-		tp->cookie_values = NULL;
-	}
 	BUG_ON(tp->fastopen_rsk != NULL);
 
 	/* If socket is aborted during connect operation */
@@ -2580,7 +2576,7 @@ static void tcp_seq_stop(struct seq_file *seq, void *v)
 
 int tcp_seq_open(struct inode *inode, struct file *file)
 {
-	struct tcp_seq_afinfo *afinfo = PDE(inode)->data;
+	struct tcp_seq_afinfo *afinfo = PDE_DATA(inode);
 	struct tcp_iter_state *s;
 	int err;
 
@@ -2659,7 +2655,9 @@ static void get_tcp4_sock(struct sock *sk, struct seq_file *f, int i, int *len)
 	__u16 srcp = ntohs(inet->inet_sport);
 	int rx_queue;
 
-	if (icsk->icsk_pending == ICSK_TIME_RETRANS) {
+	if (icsk->icsk_pending == ICSK_TIME_RETRANS ||
+	    icsk->icsk_pending == ICSK_TIME_EARLY_RETRANS ||
+	    icsk->icsk_pending == ICSK_TIME_LOSS_PROBE) {
 		timer_active	= 1;
 		timer_expires	= icsk->icsk_timeout;
 	} else if (icsk->icsk_pending == ICSK_TIME_PROBE0) {
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index b83a49c..05eaf89 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -93,13 +93,12 @@ tcp_timewait_state_process(struct inet_timewait_sock *tw, struct sk_buff *skb,
 			   const struct tcphdr *th)
 {
 	struct tcp_options_received tmp_opt;
-	const u8 *hash_location;
 	struct tcp_timewait_sock *tcptw = tcp_twsk((struct sock *)tw);
 	bool paws_reject = false;
 
 	tmp_opt.saw_tstamp = 0;
 	if (th->doff > (sizeof(*th) >> 2) && tcptw->tw_ts_recent_stamp) {
-		tcp_parse_options(skb, &tmp_opt, &hash_location, 0, NULL);
+		tcp_parse_options(skb, &tmp_opt, 0, NULL);
 
 		if (tmp_opt.saw_tstamp) {
 			tmp_opt.rcv_tsecr	-= tcptw->tw_ts_offset;
@@ -388,32 +387,6 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req,
 		struct tcp_request_sock *treq = tcp_rsk(req);
 		struct inet_connection_sock *newicsk = inet_csk(newsk);
 		struct tcp_sock *newtp = tcp_sk(newsk);
-		struct tcp_sock *oldtp = tcp_sk(sk);
-		struct tcp_cookie_values *oldcvp = oldtp->cookie_values;
-
-		/* TCP Cookie Transactions require space for the cookie pair,
-		 * as it differs for each connection.  There is no need to
-		 * copy any s_data_payload stored at the original socket.
-		 * Failure will prevent resuming the connection.
-		 *
-		 * Presumed copied, in order of appearance:
-		 *	cookie_in_always, cookie_out_never
-		 */
-		if (oldcvp != NULL) {
-			struct tcp_cookie_values *newcvp =
-				kzalloc(sizeof(*newtp->cookie_values),
-					GFP_ATOMIC);
-
-			if (newcvp != NULL) {
-				kref_init(&newcvp->kref);
-				newcvp->cookie_desired =
-						oldcvp->cookie_desired;
-				newtp->cookie_values = newcvp;
-			} else {
-				/* Not Yet Implemented */
-				newtp->cookie_values = NULL;
-			}
-		}
 
 		/* Now setup tcp_sock */
 		newtp->pred_flags = 0;
@@ -422,8 +395,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req,
 		newtp->rcv_nxt = treq->rcv_isn + 1;
 
 		newtp->snd_sml = newtp->snd_una =
-		newtp->snd_nxt = newtp->snd_up =
-			treq->snt_isn + 1 + tcp_s_data_size(oldtp);
+		newtp->snd_nxt = newtp->snd_up = treq->snt_isn + 1;
 
 		tcp_prequeue_init(newtp);
 		INIT_LIST_HEAD(&newtp->tsq_node);
@@ -440,6 +412,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req,
 		newtp->fackets_out = 0;
 		newtp->snd_ssthresh = TCP_INFINITE_SSTHRESH;
 		tcp_enable_early_retrans(newtp);
+		newtp->tlp_high_seq = 0;
 
 		/* So many TCP implementations out there (incorrectly) count the
 		 * initial SYN frame in their delayed-ACK and congestion control
@@ -449,9 +422,6 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req,
 		newtp->snd_cwnd = TCP_INIT_CWND;
 		newtp->snd_cwnd_cnt = 0;
 
-		newtp->frto_counter = 0;
-		newtp->frto_highmark = 0;
-
 		if (newicsk->icsk_ca_ops != &tcp_init_congestion_ops &&
 		    !try_module_get(newicsk->icsk_ca_ops->owner))
 			newicsk->icsk_ca_ops = &tcp_init_congestion_ops;
@@ -459,8 +429,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req,
 		tcp_set_ca_state(newsk, TCP_CA_Open);
 		tcp_init_xmit_timers(newsk);
 		skb_queue_head_init(&newtp->out_of_order_queue);
-		newtp->write_seq = newtp->pushed_seq =
-			treq->snt_isn + 1 + tcp_s_data_size(oldtp);
+		newtp->write_seq = newtp->pushed_seq = treq->snt_isn + 1;
 
 		newtp->rx_opt.saw_tstamp = 0;
 
@@ -537,7 +506,6 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,
 			   bool fastopen)
 {
 	struct tcp_options_received tmp_opt;
-	const u8 *hash_location;
 	struct sock *child;
 	const struct tcphdr *th = tcp_hdr(skb);
 	__be32 flg = tcp_flag_word(th) & (TCP_FLAG_RST|TCP_FLAG_SYN|TCP_FLAG_ACK);
@@ -547,7 +515,7 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,
 
 	tmp_opt.saw_tstamp = 0;
 	if (th->doff > (sizeof(struct tcphdr)>>2)) {
-		tcp_parse_options(skb, &tmp_opt, &hash_location, 0, NULL);
+		tcp_parse_options(skb, &tmp_opt, 0, NULL);
 
 		if (tmp_opt.saw_tstamp) {
 			tmp_opt.ts_recent = req->ts_recent;
@@ -647,7 +615,7 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,
 	 */
 	if ((flg & TCP_FLAG_ACK) && !fastopen &&
 	    (TCP_SKB_CB(skb)->ack_seq !=
-	     tcp_rsk(req)->snt_isn + 1 + tcp_s_data_size(tcp_sk(sk))))
+	     tcp_rsk(req)->snt_isn + 1))
 		return sk;
 
 	/* Also, it would be not so bad idea to check rcv_tsecr, which
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 5d0b438..af354c98 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -65,27 +65,22 @@ int sysctl_tcp_base_mss __read_mostly = TCP_BASE_MSS;
 /* By default, RFC2861 behavior.  */
 int sysctl_tcp_slow_start_after_idle __read_mostly = 1;
 
-int sysctl_tcp_cookie_size __read_mostly = 0; /* TCP_COOKIE_MAX */
-EXPORT_SYMBOL_GPL(sysctl_tcp_cookie_size);
-
 static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle,
 			   int push_one, gfp_t gfp);
 
 /* Account for new data that has been sent to the network. */
 static void tcp_event_new_data_sent(struct sock *sk, const struct sk_buff *skb)
 {
+	struct inet_connection_sock *icsk = inet_csk(sk);
 	struct tcp_sock *tp = tcp_sk(sk);
 	unsigned int prior_packets = tp->packets_out;
 
 	tcp_advance_send_head(sk, skb);
 	tp->snd_nxt = TCP_SKB_CB(skb)->end_seq;
 
-	/* Don't override Nagle indefinitely with F-RTO */
-	if (tp->frto_counter == 2)
-		tp->frto_counter = 3;
-
 	tp->packets_out += tcp_skb_pcount(skb);
-	if (!prior_packets || tp->early_retrans_delayed)
+	if (!prior_packets || icsk->icsk_pending == ICSK_TIME_EARLY_RETRANS ||
+	    icsk->icsk_pending == ICSK_TIME_LOSS_PROBE)
 		tcp_rearm_rto(sk);
 }
 
@@ -384,7 +379,6 @@ static inline bool tcp_urg_mode(const struct tcp_sock *tp)
 #define OPTION_TS		(1 << 1)
 #define OPTION_MD5		(1 << 2)
 #define OPTION_WSCALE		(1 << 3)
-#define OPTION_COOKIE_EXTENSION	(1 << 4)
 #define OPTION_FAST_OPEN_COOKIE	(1 << 8)
 
 struct tcp_out_options {
@@ -398,36 +392,6 @@ struct tcp_out_options {
 	struct tcp_fastopen_cookie *fastopen_cookie;	/* Fast open cookie */
 };
 
-/* The sysctl int routines are generic, so check consistency here.
- */
-static u8 tcp_cookie_size_check(u8 desired)
-{
-	int cookie_size;
-
-	if (desired > 0)
-		/* previously specified */
-		return desired;
-
-	cookie_size = ACCESS_ONCE(sysctl_tcp_cookie_size);
-	if (cookie_size <= 0)
-		/* no default specified */
-		return 0;
-
-	if (cookie_size <= TCP_COOKIE_MIN)
-		/* value too small, specify minimum */
-		return TCP_COOKIE_MIN;
-
-	if (cookie_size >= TCP_COOKIE_MAX)
-		/* value too large, specify maximum */
-		return TCP_COOKIE_MAX;
-
-	if (cookie_size & 1)
-		/* 8-bit multiple, illegal, fix it */
-		cookie_size++;
-
-	return (u8)cookie_size;
-}
-
 /* Write previously computed TCP options to the packet.
  *
  * Beware: Something in the Internet is very sensitive to the ordering of
@@ -446,27 +410,9 @@ static void tcp_options_write(__be32 *ptr, struct tcp_sock *tp,
 {
 	u16 options = opts->options;	/* mungable copy */
 
-	/* Having both authentication and cookies for security is redundant,
-	 * and there's certainly not enough room.  Instead, the cookie-less
-	 * extension variant is proposed.
-	 *
-	 * Consider the pessimal case with authentication.  The options
-	 * could look like:
-	 *   COOKIE|MD5(20) + MSS(4) + SACK|TS(12) + WSCALE(4) == 40
-	 */
 	if (unlikely(OPTION_MD5 & options)) {
-		if (unlikely(OPTION_COOKIE_EXTENSION & options)) {
-			*ptr++ = htonl((TCPOPT_COOKIE << 24) |
-				       (TCPOLEN_COOKIE_BASE << 16) |
-				       (TCPOPT_MD5SIG << 8) |
-				       TCPOLEN_MD5SIG);
-		} else {
-			*ptr++ = htonl((TCPOPT_NOP << 24) |
-				       (TCPOPT_NOP << 16) |
-				       (TCPOPT_MD5SIG << 8) |
-				       TCPOLEN_MD5SIG);
-		}
-		options &= ~OPTION_COOKIE_EXTENSION;
+		*ptr++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
+			       (TCPOPT_MD5SIG << 8) | TCPOLEN_MD5SIG);
 		/* overload cookie hash location */
 		opts->hash_location = (__u8 *)ptr;
 		ptr += 4;
@@ -495,44 +441,6 @@ static void tcp_options_write(__be32 *ptr, struct tcp_sock *tp,
 		*ptr++ = htonl(opts->tsecr);
 	}
 
-	/* Specification requires after timestamp, so do it now.
-	 *
-	 * Consider the pessimal case without authentication.  The options
-	 * could look like:
-	 *   MSS(4) + SACK|TS(12) + COOKIE(20) + WSCALE(4) == 40
-	 */
-	if (unlikely(OPTION_COOKIE_EXTENSION & options)) {
-		__u8 *cookie_copy = opts->hash_location;
-		u8 cookie_size = opts->hash_size;
-
-		/* 8-bit multiple handled in tcp_cookie_size_check() above,
-		 * and elsewhere.
-		 */
-		if (0x2 & cookie_size) {
-			__u8 *p = (__u8 *)ptr;
-
-			/* 16-bit multiple */
-			*p++ = TCPOPT_COOKIE;
-			*p++ = TCPOLEN_COOKIE_BASE + cookie_size;
-			*p++ = *cookie_copy++;
-			*p++ = *cookie_copy++;
-			ptr++;
-			cookie_size -= 2;
-		} else {
-			/* 32-bit multiple */
-			*ptr++ = htonl(((TCPOPT_NOP << 24) |
-					(TCPOPT_NOP << 16) |
-					(TCPOPT_COOKIE << 8) |
-					TCPOLEN_COOKIE_BASE) +
-				       cookie_size);
-		}
-
-		if (cookie_size > 0) {
-			memcpy(ptr, cookie_copy, cookie_size);
-			ptr += (cookie_size / 4);
-		}
-	}
-
 	if (unlikely(OPTION_SACK_ADVERTISE & options)) {
 		*ptr++ = htonl((TCPOPT_NOP << 24) |
 			       (TCPOPT_NOP << 16) |
@@ -591,11 +499,7 @@ static unsigned int tcp_syn_options(struct sock *sk, struct sk_buff *skb,
 				struct tcp_md5sig_key **md5)
 {
 	struct tcp_sock *tp = tcp_sk(sk);
-	struct tcp_cookie_values *cvp = tp->cookie_values;
 	unsigned int remaining = MAX_TCP_OPTION_SPACE;
-	u8 cookie_size = (!tp->rx_opt.cookie_out_never && cvp != NULL) ?
-			 tcp_cookie_size_check(cvp->cookie_desired) :
-			 0;
 	struct tcp_fastopen_request *fastopen = tp->fastopen_req;
 
 #ifdef CONFIG_TCP_MD5SIG
@@ -647,52 +551,7 @@ static unsigned int tcp_syn_options(struct sock *sk, struct sk_buff *skb,
 			tp->syn_fastopen = 1;
 		}
 	}
-	/* Note that timestamps are required by the specification.
-	 *
-	 * Odd numbers of bytes are prohibited by the specification, ensuring
-	 * that the cookie is 16-bit aligned, and the resulting cookie pair is
-	 * 32-bit aligned.
-	 */
-	if (*md5 == NULL &&
-	    (OPTION_TS & opts->options) &&
-	    cookie_size > 0) {
-		int need = TCPOLEN_COOKIE_BASE + cookie_size;
-
-		if (0x2 & need) {
-			/* 32-bit multiple */
-			need += 2; /* NOPs */
-
-			if (need > remaining) {
-				/* try shrinking cookie to fit */
-				cookie_size -= 2;
-				need -= 4;
-			}
-		}
-		while (need > remaining && TCP_COOKIE_MIN <= cookie_size) {
-			cookie_size -= 4;
-			need -= 4;
-		}
-		if (TCP_COOKIE_MIN <= cookie_size) {
-			opts->options |= OPTION_COOKIE_EXTENSION;
-			opts->hash_location = (__u8 *)&cvp->cookie_pair[0];
-			opts->hash_size = cookie_size;
-
-			/* Remember for future incarnations. */
-			cvp->cookie_desired = cookie_size;
-
-			if (cvp->cookie_desired != cvp->cookie_pair_size) {
-				/* Currently use random bytes as a nonce,
-				 * assuming these are completely unpredictable
-				 * by hostile users of the same system.
-				 */
-				get_random_bytes(&cvp->cookie_pair[0],
-						 cookie_size);
-				cvp->cookie_pair_size = cookie_size;
-			}
 
-			remaining -= need;
-		}
-	}
 	return MAX_TCP_OPTION_SPACE - remaining;
 }
 
@@ -702,14 +561,10 @@ static unsigned int tcp_synack_options(struct sock *sk,
 				   unsigned int mss, struct sk_buff *skb,
 				   struct tcp_out_options *opts,
 				   struct tcp_md5sig_key **md5,
-				   struct tcp_extend_values *xvp,
 				   struct tcp_fastopen_cookie *foc)
 {
 	struct inet_request_sock *ireq = inet_rsk(req);
 	unsigned int remaining = MAX_TCP_OPTION_SPACE;
-	u8 cookie_plus = (xvp != NULL && !xvp->cookie_out_never) ?
-			 xvp->cookie_plus :
-			 0;
 
 #ifdef CONFIG_TCP_MD5SIG
 	*md5 = tcp_rsk(req)->af_specific->md5_lookup(sk, req);
@@ -757,28 +612,7 @@ static unsigned int tcp_synack_options(struct sock *sk,
 			remaining -= need;
 		}
 	}
-	/* Similar rationale to tcp_syn_options() applies here, too.
-	 * If the <SYN> options fit, the same options should fit now!
-	 */
-	if (*md5 == NULL &&
-	    ireq->tstamp_ok &&
-	    cookie_plus > TCPOLEN_COOKIE_BASE) {
-		int need = cookie_plus; /* has TCPOLEN_COOKIE_BASE */
-
-		if (0x2 & need) {
-			/* 32-bit multiple */
-			need += 2; /* NOPs */
-		}
-		if (need <= remaining) {
-			opts->options |= OPTION_COOKIE_EXTENSION;
-			opts->hash_size = cookie_plus - TCPOLEN_COOKIE_BASE;
-			remaining -= need;
-		} else {
-			/* There's no error return, so flag it. */
-			xvp->cookie_out_never = 1; /* true */
-			opts->hash_size = 0;
-		}
-	}
+
 	return MAX_TCP_OPTION_SPACE - remaining;
 }
 
@@ -1632,11 +1466,8 @@ static inline bool tcp_nagle_test(const struct tcp_sock *tp, const struct sk_buf
 	if (nonagle & TCP_NAGLE_PUSH)
 		return true;
 
-	/* Don't use the nagle rule for urgent data (or for the final FIN).
-	 * Nagle can be ignored during F-RTO too (see RFC4138).
-	 */
-	if (tcp_urg_mode(tp) || (tp->frto_counter == 2) ||
-	    (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN))
+	/* Don't use the nagle rule for urgent data (or for the final FIN). */
+	if (tcp_urg_mode(tp) || (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN))
 		return true;
 
 	if (!tcp_nagle_check(tp, skb, cur_mss, nonagle))
@@ -1961,6 +1792,9 @@ static int tcp_mtu_probe(struct sock *sk)
  * snd_up-64k-mss .. snd_up cannot be large. However, taking into
  * account rare use of URG, this is not a big flaw.
  *
+ * Send at most one packet when push_one > 0. Temporarily ignore
+ * cwnd limit to force at most one packet out when push_one == 2.
+
  * Returns true, if no segments are in flight and we have queued segments,
  * but cannot send anything now because of SWS or another problem.
  */
@@ -1996,8 +1830,13 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle,
 			goto repair; /* Skip network transmission */
 
 		cwnd_quota = tcp_cwnd_test(tp, skb);
-		if (!cwnd_quota)
-			break;
+		if (!cwnd_quota) {
+			if (push_one == 2)
+				/* Force out a loss probe pkt. */
+				cwnd_quota = 1;
+			else
+				break;
+		}
 
 		if (unlikely(!tcp_snd_wnd_test(tp, skb, mss_now)))
 			break;
@@ -2051,10 +1890,129 @@ repair:
 	if (likely(sent_pkts)) {
 		if (tcp_in_cwnd_reduction(sk))
 			tp->prr_out += sent_pkts;
+
+		/* Send one loss probe per tail loss episode. */
+		if (push_one != 2)
+			tcp_schedule_loss_probe(sk);
 		tcp_cwnd_validate(sk);
 		return false;
 	}
-	return !tp->packets_out && tcp_send_head(sk);
+	return (push_one == 2) || (!tp->packets_out && tcp_send_head(sk));
+}
+
+bool tcp_schedule_loss_probe(struct sock *sk)
+{
+	struct inet_connection_sock *icsk = inet_csk(sk);
+	struct tcp_sock *tp = tcp_sk(sk);
+	u32 timeout, tlp_time_stamp, rto_time_stamp;
+	u32 rtt = tp->srtt >> 3;
+
+	if (WARN_ON(icsk->icsk_pending == ICSK_TIME_EARLY_RETRANS))
+		return false;
+	/* No consecutive loss probes. */
+	if (WARN_ON(icsk->icsk_pending == ICSK_TIME_LOSS_PROBE)) {
+		tcp_rearm_rto(sk);
+		return false;
+	}
+	/* Don't do any loss probe on a Fast Open connection before 3WHS
+	 * finishes.
+	 */
+	if (sk->sk_state == TCP_SYN_RECV)
+		return false;
+
+	/* TLP is only scheduled when next timer event is RTO. */
+	if (icsk->icsk_pending != ICSK_TIME_RETRANS)
+		return false;
+
+	/* Schedule a loss probe in 2*RTT for SACK capable connections
+	 * in Open state, that are either limited by cwnd or application.
+	 */
+	if (sysctl_tcp_early_retrans < 3 || !rtt || !tp->packets_out ||
+	    !tcp_is_sack(tp) || inet_csk(sk)->icsk_ca_state != TCP_CA_Open)
+		return false;
+
+	if ((tp->snd_cwnd > tcp_packets_in_flight(tp)) &&
+	     tcp_send_head(sk))
+		return false;
+
+	/* Probe timeout is at least 1.5*rtt + TCP_DELACK_MAX to account
+	 * for delayed ack when there's one outstanding packet.
+	 */
+	timeout = rtt << 1;
+	if (tp->packets_out == 1)
+		timeout = max_t(u32, timeout,
+				(rtt + (rtt >> 1) + TCP_DELACK_MAX));
+	timeout = max_t(u32, timeout, msecs_to_jiffies(10));
+
+	/* If RTO is shorter, just schedule TLP in its place. */
+	tlp_time_stamp = tcp_time_stamp + timeout;
+	rto_time_stamp = (u32)inet_csk(sk)->icsk_timeout;
+	if ((s32)(tlp_time_stamp - rto_time_stamp) > 0) {
+		s32 delta = rto_time_stamp - tcp_time_stamp;
+		if (delta > 0)
+			timeout = delta;
+	}
+
+	inet_csk_reset_xmit_timer(sk, ICSK_TIME_LOSS_PROBE, timeout,
+				  TCP_RTO_MAX);
+	return true;
+}
+
+/* When probe timeout (PTO) fires, send a new segment if one exists, else
+ * retransmit the last segment.
+ */
+void tcp_send_loss_probe(struct sock *sk)
+{
+	struct tcp_sock *tp = tcp_sk(sk);
+	struct sk_buff *skb;
+	int pcount;
+	int mss = tcp_current_mss(sk);
+	int err = -1;
+
+	if (tcp_send_head(sk) != NULL) {
+		err = tcp_write_xmit(sk, mss, TCP_NAGLE_OFF, 2, GFP_ATOMIC);
+		goto rearm_timer;
+	}
+
+	/* At most one outstanding TLP retransmission. */
+	if (tp->tlp_high_seq)
+		goto rearm_timer;
+
+	/* Retransmit last segment. */
+	skb = tcp_write_queue_tail(sk);
+	if (WARN_ON(!skb))
+		goto rearm_timer;
+
+	pcount = tcp_skb_pcount(skb);
+	if (WARN_ON(!pcount))
+		goto rearm_timer;
+
+	if ((pcount > 1) && (skb->len > (pcount - 1) * mss)) {
+		if (unlikely(tcp_fragment(sk, skb, (pcount - 1) * mss, mss)))
+			goto rearm_timer;
+		skb = tcp_write_queue_tail(sk);
+	}
+
+	if (WARN_ON(!skb || !tcp_skb_pcount(skb)))
+		goto rearm_timer;
+
+	/* Probe with zero data doesn't trigger fast recovery. */
+	if (skb->len > 0)
+		err = __tcp_retransmit_skb(sk, skb);
+
+	/* Record snd_nxt for loss detection. */
+	if (likely(!err))
+		tp->tlp_high_seq = tp->snd_nxt;
+
+rearm_timer:
+	inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
+				  inet_csk(sk)->icsk_rto,
+				  TCP_RTO_MAX);
+
+	if (likely(!err))
+		NET_INC_STATS_BH(sock_net(sk),
+				 LINUX_MIB_TCPLOSSPROBES);
+	return;
 }
 
 /* Push out any pending frames which were held back due to
@@ -2675,32 +2633,24 @@ int tcp_send_synack(struct sock *sk)
  * sk: listener socket
  * dst: dst entry attached to the SYNACK
  * req: request_sock pointer
- * rvp: request_values pointer
  *
  * Allocate one skb and build a SYNACK packet.
  * @dst is consumed : Caller should not use it again.
  */
 struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst,
 				struct request_sock *req,
-				struct request_values *rvp,
 				struct tcp_fastopen_cookie *foc)
 {
 	struct tcp_out_options opts;
-	struct tcp_extend_values *xvp = tcp_xv(rvp);
 	struct inet_request_sock *ireq = inet_rsk(req);
 	struct tcp_sock *tp = tcp_sk(sk);
-	const struct tcp_cookie_values *cvp = tp->cookie_values;
 	struct tcphdr *th;
 	struct sk_buff *skb;
 	struct tcp_md5sig_key *md5;
 	int tcp_header_size;
 	int mss;
-	int s_data_desired = 0;
 
-	if (cvp != NULL && cvp->s_data_constant && cvp->s_data_desired)
-		s_data_desired = cvp->s_data_desired;
-	skb = alloc_skb(MAX_TCP_HEADER + 15 + s_data_desired,
-			sk_gfp_atomic(sk, GFP_ATOMIC));
+	skb = alloc_skb(MAX_TCP_HEADER + 15, sk_gfp_atomic(sk, GFP_ATOMIC));
 	if (unlikely(!skb)) {
 		dst_release(dst);
 		return NULL;
@@ -2742,9 +2692,8 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst,
 	else
 #endif
 	TCP_SKB_CB(skb)->when = tcp_time_stamp;
-	tcp_header_size = tcp_synack_options(sk, req, mss,
-					     skb, &opts, &md5, xvp, foc)
-			+ sizeof(*th);
+	tcp_header_size = tcp_synack_options(sk, req, mss, skb, &opts, &md5,
+					     foc) + sizeof(*th);
 
 	skb_push(skb, tcp_header_size);
 	skb_reset_transport_header(skb);
@@ -2762,40 +2711,6 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst,
 	tcp_init_nondata_skb(skb, tcp_rsk(req)->snt_isn,
 			     TCPHDR_SYN | TCPHDR_ACK);
 
-	if (OPTION_COOKIE_EXTENSION & opts.options) {
-		if (s_data_desired) {
-			u8 *buf = skb_put(skb, s_data_desired);
-
-			/* copy data directly from the listening socket. */
-			memcpy(buf, cvp->s_data_payload, s_data_desired);
-			TCP_SKB_CB(skb)->end_seq += s_data_desired;
-		}
-
-		if (opts.hash_size > 0) {
-			__u32 workspace[SHA_WORKSPACE_WORDS];
-			u32 *mess = &xvp->cookie_bakery[COOKIE_DIGEST_WORDS];
-			u32 *tail = &mess[COOKIE_MESSAGE_WORDS-1];
-
-			/* Secret recipe depends on the Timestamp, (future)
-			 * Sequence and Acknowledgment Numbers, Initiator
-			 * Cookie, and others handled by IP variant caller.
-			 */
-			*tail-- ^= opts.tsval;
-			*tail-- ^= tcp_rsk(req)->rcv_isn + 1;
-			*tail-- ^= TCP_SKB_CB(skb)->seq + 1;
-
-			/* recommended */
-			*tail-- ^= (((__force u32)th->dest << 16) | (__force u32)th->source);
-			*tail-- ^= (u32)(unsigned long)cvp; /* per sockopt */
-
-			sha_transform((__u32 *)&xvp->cookie_bakery[0],
-				      (char *)mess,
-				      &workspace[0]);
-			opts.hash_location =
-				(__u8 *)&xvp->cookie_bakery[0];
-		}
-	}
-
 	th->seq = htonl(TCP_SKB_CB(skb)->seq);
 	/* XXX data is queued and acked as is. No buffer/window check */
 	th->ack_seq = htonl(tcp_rsk(req)->rcv_nxt);
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
index b78aac3..4b85e6f 100644
--- a/net/ipv4/tcp_timer.c
+++ b/net/ipv4/tcp_timer.c
@@ -342,10 +342,6 @@ void tcp_retransmit_timer(struct sock *sk)
 	struct tcp_sock *tp = tcp_sk(sk);
 	struct inet_connection_sock *icsk = inet_csk(sk);
 
-	if (tp->early_retrans_delayed) {
-		tcp_resume_early_retransmit(sk);
-		return;
-	}
 	if (tp->fastopen_rsk) {
 		WARN_ON_ONCE(sk->sk_state != TCP_SYN_RECV &&
 			     sk->sk_state != TCP_FIN_WAIT1);
@@ -360,6 +356,8 @@ void tcp_retransmit_timer(struct sock *sk)
 
 	WARN_ON(tcp_write_queue_empty(sk));
 
+	tp->tlp_high_seq = 0;
+
 	if (!tp->snd_wnd && !sock_flag(sk, SOCK_DEAD) &&
 	    !((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV))) {
 		/* Receiver dastardly shrinks window. Our retransmits
@@ -418,11 +416,7 @@ void tcp_retransmit_timer(struct sock *sk)
 		NET_INC_STATS_BH(sock_net(sk), mib_idx);
 	}
 
-	if (tcp_use_frto(sk)) {
-		tcp_enter_frto(sk);
-	} else {
-		tcp_enter_loss(sk, 0);
-	}
+	tcp_enter_loss(sk, 0);
 
 	if (tcp_retransmit_skb(sk, tcp_write_queue_head(sk)) > 0) {
 		/* Retransmission failed because of local congestion,
@@ -495,13 +489,20 @@ void tcp_write_timer_handler(struct sock *sk)
 	}
 
 	event = icsk->icsk_pending;
-	icsk->icsk_pending = 0;
 
 	switch (event) {
+	case ICSK_TIME_EARLY_RETRANS:
+		tcp_resume_early_retransmit(sk);
+		break;
+	case ICSK_TIME_LOSS_PROBE:
+		tcp_send_loss_probe(sk);
+		break;
 	case ICSK_TIME_RETRANS:
+		icsk->icsk_pending = 0;
 		tcp_retransmit_timer(sk);
 		break;
 	case ICSK_TIME_PROBE0:
+		icsk->icsk_pending = 0;
 		tcp_probe_timer(sk);
 		break;
 	}
diff --git a/net/ipv4/tcp_westwood.c b/net/ipv4/tcp_westwood.c
index 1b91bf4..76a1e23 100644
--- a/net/ipv4/tcp_westwood.c
+++ b/net/ipv4/tcp_westwood.c
@@ -236,7 +236,7 @@ static void tcp_westwood_event(struct sock *sk, enum tcp_ca_event event)
 		tp->snd_cwnd = tp->snd_ssthresh = tcp_westwood_bw_rttmin(sk);
 		break;
 
-	case CA_EVENT_FRTO:
+	case CA_EVENT_LOSS:
 		tp->snd_ssthresh = tcp_westwood_bw_rttmin(sk);
 		/* Update RTT_min when next ack arrives */
 		w->reset_rtt_min = 1;
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 0a073a2..fe3b2e4 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -2093,7 +2093,7 @@ static void udp_seq_stop(struct seq_file *seq, void *v)
 
 int udp_seq_open(struct inode *inode, struct file *file)
 {
-	struct udp_seq_afinfo *afinfo = PDE(inode)->data;
+	struct udp_seq_afinfo *afinfo = PDE_DATA(inode);
 	struct udp_iter_state *s;
 	int err;
 
@@ -2279,31 +2279,88 @@ void __init udp_init(void)
 
 int udp4_ufo_send_check(struct sk_buff *skb)
 {
-	const struct iphdr *iph;
-	struct udphdr *uh;
-
-	if (!pskb_may_pull(skb, sizeof(*uh)))
+	if (!pskb_may_pull(skb, sizeof(struct udphdr)))
 		return -EINVAL;
 
-	iph = ip_hdr(skb);
-	uh = udp_hdr(skb);
+	if (likely(!skb->encapsulation)) {
+		const struct iphdr *iph;
+		struct udphdr *uh;
 
-	uh->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, skb->len,
-				       IPPROTO_UDP, 0);
-	skb->csum_start = skb_transport_header(skb) - skb->head;
-	skb->csum_offset = offsetof(struct udphdr, check);
-	skb->ip_summed = CHECKSUM_PARTIAL;
+		iph = ip_hdr(skb);
+		uh = udp_hdr(skb);
+
+		uh->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, skb->len,
+				IPPROTO_UDP, 0);
+		skb->csum_start = skb_transport_header(skb) - skb->head;
+		skb->csum_offset = offsetof(struct udphdr, check);
+		skb->ip_summed = CHECKSUM_PARTIAL;
+	}
 	return 0;
 }
 
+static struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb,
+		netdev_features_t features)
+{
+	struct sk_buff *segs = ERR_PTR(-EINVAL);
+	int mac_len = skb->mac_len;
+	int tnl_hlen = skb_inner_mac_header(skb) - skb_transport_header(skb);
+	int outer_hlen;
+	netdev_features_t enc_features;
+
+	if (unlikely(!pskb_may_pull(skb, tnl_hlen)))
+		goto out;
+
+	skb->encapsulation = 0;
+	__skb_pull(skb, tnl_hlen);
+	skb_reset_mac_header(skb);
+	skb_set_network_header(skb, skb_inner_network_offset(skb));
+	skb->mac_len = skb_inner_network_offset(skb);
+
+	/* segment inner packet. */
+	enc_features = skb->dev->hw_enc_features & netif_skb_features(skb);
+	segs = skb_mac_gso_segment(skb, enc_features);
+	if (!segs || IS_ERR(segs))
+		goto out;
+
+	outer_hlen = skb_tnl_header_len(skb);
+	skb = segs;
+	do {
+		struct udphdr *uh;
+		int udp_offset = outer_hlen - tnl_hlen;
+
+		skb->mac_len = mac_len;
+
+		skb_push(skb, outer_hlen);
+		skb_reset_mac_header(skb);
+		skb_set_network_header(skb, mac_len);
+		skb_set_transport_header(skb, udp_offset);
+		uh = udp_hdr(skb);
+		uh->len = htons(skb->len - udp_offset);
+
+		/* csum segment if tunnel sets skb with csum. */
+		if (unlikely(uh->check)) {
+			struct iphdr *iph = ip_hdr(skb);
+
+			uh->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr,
+						       skb->len - udp_offset,
+						       IPPROTO_UDP, 0);
+			uh->check = csum_fold(skb_checksum(skb, udp_offset,
+							   skb->len - udp_offset, 0));
+			if (uh->check == 0)
+				uh->check = CSUM_MANGLED_0;
+
+		}
+		skb->ip_summed = CHECKSUM_NONE;
+	} while ((skb = skb->next));
+out:
+	return segs;
+}
+
 struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb,
 	netdev_features_t features)
 {
 	struct sk_buff *segs = ERR_PTR(-EINVAL);
 	unsigned int mss;
-	int offset;
-	__wsum csum;
-
 	mss = skb_shinfo(skb)->gso_size;
 	if (unlikely(skb->len <= mss))
 		goto out;
@@ -2313,6 +2370,7 @@ struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb,
 		int type = skb_shinfo(skb)->gso_type;
 
 		if (unlikely(type & ~(SKB_GSO_UDP | SKB_GSO_DODGY |
+				      SKB_GSO_UDP_TUNNEL |
 				      SKB_GSO_GRE) ||
 			     !(type & (SKB_GSO_UDP))))
 			goto out;
@@ -2323,20 +2381,27 @@ struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb,
 		goto out;
 	}
 
-	/* Do software UFO. Complete and fill in the UDP checksum as HW cannot
-	 * do checksum of UDP packets sent as multiple IP fragments.
-	 */
-	offset = skb_checksum_start_offset(skb);
-	csum = skb_checksum(skb, offset, skb->len - offset, 0);
-	offset += skb->csum_offset;
-	*(__sum16 *)(skb->data + offset) = csum_fold(csum);
-	skb->ip_summed = CHECKSUM_NONE;
-
 	/* Fragment the skb. IP headers of the fragments are updated in
 	 * inet_gso_segment()
 	 */
-	segs = skb_segment(skb, features);
+	if (skb->encapsulation && skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL)
+		segs = skb_udp_tunnel_segment(skb, features);
+	else {
+		int offset;
+		__wsum csum;
+
+		/* Do software UFO. Complete and fill in the UDP checksum as
+		 * HW cannot do checksum of UDP packets sent as multiple
+		 * IP fragments.
+		 */
+		offset = skb_checksum_start_offset(skb);
+		csum = skb_checksum(skb, offset, skb->len - offset, 0);
+		offset += skb->csum_offset;
+		*(__sum16 *)(skb->data + offset) = csum_fold(csum);
+		skb->ip_summed = CHECKSUM_NONE;
+
+		segs = skb_segment(skb, features);
+	}
 out:
 	return segs;
 }
-
diff --git a/net/ipv4/udp_diag.c b/net/ipv4/udp_diag.c
index 505b30a..369a781 100644
--- a/net/ipv4/udp_diag.c
+++ b/net/ipv4/udp_diag.c
@@ -64,9 +64,9 @@ static int udp_dump_one(struct udp_table *tbl, struct sk_buff *in_skb,
 		goto out;
 
 	err = -ENOMEM;
-	rep = alloc_skb(NLMSG_SPACE((sizeof(struct inet_diag_msg) +
-				     sizeof(struct inet_diag_meminfo) +
-				     64)), GFP_KERNEL);
+	rep = nlmsg_new(sizeof(struct inet_diag_msg) +
+			sizeof(struct inet_diag_meminfo) + 64,
+			GFP_KERNEL);
 	if (!rep)
 		goto out;
 
diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c
index fe5189e..eb1dd4d 100644
--- a/net/ipv4/xfrm4_mode_tunnel.c
+++ b/net/ipv4/xfrm4_mode_tunnel.c
@@ -103,8 +103,12 @@ static int xfrm4_mode_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
 
 	top_iph->protocol = xfrm_af2proto(skb_dst(skb)->ops->family);
 
-	/* DS disclosed */
-	top_iph->tos = INET_ECN_encapsulate(XFRM_MODE_SKB_CB(skb)->tos,
+	/* DS disclosing depends on XFRM_SA_XFLAG_DONT_ENCAP_DSCP */
+	if (x->props.extra_flags & XFRM_SA_XFLAG_DONT_ENCAP_DSCP)
+		top_iph->tos = 0;
+	else
+		top_iph->tos = XFRM_MODE_SKB_CB(skb)->tos;
+	top_iph->tos = INET_ECN_encapsulate(top_iph->tos,
 					    XFRM_MODE_SKB_CB(skb)->tos);
 
 	flags = x->props.flags;
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig
index ed0b9e2..11b13ea 100644
--- a/net/ipv6/Kconfig
+++ b/net/ipv6/Kconfig
@@ -156,6 +156,7 @@ config INET6_XFRM_MODE_ROUTEOPTIMIZATION
 config IPV6_SIT
 	tristate "IPv6: IPv6-in-IPv4 tunnel (SIT driver)"
 	select INET_TUNNEL
+	select NET_IP_TUNNEL
 	select IPV6_NDISC_NODETYPE
 	default y
 	---help---
@@ -201,6 +202,7 @@ config IPV6_TUNNEL
 config IPV6_GRE
 	tristate "IPv6: GRE tunnel"
 	select IPV6_TUNNEL
+	select NET_IP_TUNNEL
 	---help---
 	  Tunneling means encapsulating data of one protocol type within
 	  another protocol and sending it over a channel that understands the
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 2651225..a33b157 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -70,6 +70,7 @@
 #include <net/snmp.h>
 
 #include <net/af_ieee802154.h>
+#include <net/firewire.h>
 #include <net/ipv6.h>
 #include <net/protocol.h>
 #include <net/ndisc.h>
@@ -544,8 +545,7 @@ static const struct nla_policy devconf_ipv6_policy[NETCONFA_MAX+1] = {
 };
 
 static int inet6_netconf_get_devconf(struct sk_buff *in_skb,
-				     struct nlmsghdr *nlh,
-				     void *arg)
+				     struct nlmsghdr *nlh)
 {
 	struct net *net = sock_net(in_skb->sk);
 	struct nlattr *tb[NETCONFA_MAX+1];
@@ -605,6 +605,77 @@ errout:
 	return err;
 }
 
+static int inet6_netconf_dump_devconf(struct sk_buff *skb,
+				      struct netlink_callback *cb)
+{
+	struct net *net = sock_net(skb->sk);
+	int h, s_h;
+	int idx, s_idx;
+	struct net_device *dev;
+	struct inet6_dev *idev;
+	struct hlist_head *head;
+
+	s_h = cb->args[0];
+	s_idx = idx = cb->args[1];
+
+	for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
+		idx = 0;
+		head = &net->dev_index_head[h];
+		rcu_read_lock();
+		cb->seq = atomic_read(&net->ipv6.dev_addr_genid) ^
+			  net->dev_base_seq;
+		hlist_for_each_entry_rcu(dev, head, index_hlist) {
+			if (idx < s_idx)
+				goto cont;
+			idev = __in6_dev_get(dev);
+			if (!idev)
+				goto cont;
+
+			if (inet6_netconf_fill_devconf(skb, dev->ifindex,
+						       &idev->cnf,
+						       NETLINK_CB(cb->skb).portid,
+						       cb->nlh->nlmsg_seq,
+						       RTM_NEWNETCONF,
+						       NLM_F_MULTI,
+						       -1) <= 0) {
+				rcu_read_unlock();
+				goto done;
+			}
+			nl_dump_check_consistent(cb, nlmsg_hdr(skb));
+cont:
+			idx++;
+		}
+		rcu_read_unlock();
+	}
+	if (h == NETDEV_HASHENTRIES) {
+		if (inet6_netconf_fill_devconf(skb, NETCONFA_IFINDEX_ALL,
+					       net->ipv6.devconf_all,
+					       NETLINK_CB(cb->skb).portid,
+					       cb->nlh->nlmsg_seq,
+					       RTM_NEWNETCONF, NLM_F_MULTI,
+					       -1) <= 0)
+			goto done;
+		else
+			h++;
+	}
+	if (h == NETDEV_HASHENTRIES + 1) {
+		if (inet6_netconf_fill_devconf(skb, NETCONFA_IFINDEX_DEFAULT,
+					       net->ipv6.devconf_dflt,
+					       NETLINK_CB(cb->skb).portid,
+					       cb->nlh->nlmsg_seq,
+					       RTM_NEWNETCONF, NLM_F_MULTI,
+					       -1) <= 0)
+			goto done;
+		else
+			h++;
+	}
+done:
+	cb->args[0] = h;
+	cb->args[1] = idx;
+
+	return skb->len;
+}
+
 #ifdef CONFIG_SYSCTL
 static void dev_forward_change(struct inet6_dev *idev)
 {
@@ -1668,6 +1739,20 @@ static int addrconf_ifid_eui64(u8 *eui, struct net_device *dev)
 	return 0;
 }
 
+static int addrconf_ifid_ieee1394(u8 *eui, struct net_device *dev)
+{
+	union fwnet_hwaddr *ha;
+
+	if (dev->addr_len != FWNET_ALEN)
+		return -1;
+
+	ha = (union fwnet_hwaddr *)dev->dev_addr;
+
+	memcpy(eui, &ha->uc.uniq_id, sizeof(ha->uc.uniq_id));
+	eui[0] ^= 2;
+	return 0;
+}
+
 static int addrconf_ifid_arcnet(u8 *eui, struct net_device *dev)
 {
 	/* XXX: inherit EUI-64 from other interface -- yoshfuji */
@@ -1732,6 +1817,8 @@ static int ipv6_generate_eui64(u8 *eui, struct net_device *dev)
 		return addrconf_ifid_gre(eui, dev);
 	case ARPHRD_IEEE802154:
 		return addrconf_ifid_eui64(eui, dev);
+	case ARPHRD_IEEE1394:
+		return addrconf_ifid_ieee1394(eui, dev);
 	}
 	return -1;
 }
@@ -2529,6 +2616,9 @@ static void sit_add_v4_addrs(struct inet6_dev *idev)
 static void init_loopback(struct net_device *dev)
 {
 	struct inet6_dev  *idev;
+	struct net_device *sp_dev;
+	struct inet6_ifaddr *sp_ifa;
+	struct rt6_info *sp_rt;
 
 	/* ::1 */
 
@@ -2540,6 +2630,30 @@ static void init_loopback(struct net_device *dev)
 	}
 
 	add_addr(idev, &in6addr_loopback, 128, IFA_HOST);
+
+	/* Add routes to other interface's IPv6 addresses */
+	for_each_netdev(dev_net(dev), sp_dev) {
+		if (!strcmp(sp_dev->name, dev->name))
+			continue;
+
+		idev = __in6_dev_get(sp_dev);
+		if (!idev)
+			continue;
+
+		read_lock_bh(&idev->lock);
+		list_for_each_entry(sp_ifa, &idev->addr_list, if_list) {
+
+			if (sp_ifa->flags & (IFA_F_DADFAILED | IFA_F_TENTATIVE))
+				continue;
+
+			sp_rt = addrconf_dst_alloc(idev, &sp_ifa->addr, 0);
+
+			/* Failure cases are ignored */
+			if (!IS_ERR(sp_rt))
+				ip6_ins_rt(sp_rt);
+		}
+		read_unlock_bh(&idev->lock);
+	}
 }
 
 static void addrconf_add_linklocal(struct inet6_dev *idev, const struct in6_addr *addr)
@@ -2573,7 +2687,8 @@ static void addrconf_dev_config(struct net_device *dev)
 	    (dev->type != ARPHRD_FDDI) &&
 	    (dev->type != ARPHRD_ARCNET) &&
 	    (dev->type != ARPHRD_INFINIBAND) &&
-	    (dev->type != ARPHRD_IEEE802154)) {
+	    (dev->type != ARPHRD_IEEE802154) &&
+	    (dev->type != ARPHRD_IEEE1394)) {
 		/* Alas, we support only Ethernet autoconfiguration. */
 		return;
 	}
@@ -3510,7 +3625,7 @@ static const struct nla_policy ifa_ipv6_policy[IFA_MAX+1] = {
 };
 
 static int
-inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh)
 {
 	struct net *net = sock_net(skb->sk);
 	struct ifaddrmsg *ifm;
@@ -3576,7 +3691,7 @@ static int inet6_addr_modify(struct inet6_ifaddr *ifp, u8 ifa_flags,
 }
 
 static int
-inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh)
 {
 	struct net *net = sock_net(skb->sk);
 	struct ifaddrmsg *ifm;
@@ -3807,6 +3922,7 @@ static int in6_dump_addrs(struct inet6_dev *idev, struct sk_buff *skb,
 						NLM_F_MULTI);
 			if (err <= 0)
 				break;
+			nl_dump_check_consistent(cb, nlmsg_hdr(skb));
 		}
 		break;
 	}
@@ -3864,6 +3980,7 @@ static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb,
 	s_ip_idx = ip_idx = cb->args[2];
 
 	rcu_read_lock();
+	cb->seq = atomic_read(&net->ipv6.dev_addr_genid) ^ net->dev_base_seq;
 	for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
 		idx = 0;
 		head = &net->dev_index_head[h];
@@ -3915,8 +4032,7 @@ static int inet6_dump_ifacaddr(struct sk_buff *skb, struct netlink_callback *cb)
 	return inet6_dump_addr(skb, cb, type);
 }
 
-static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr *nlh,
-			     void *arg)
+static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr *nlh)
 {
 	struct net *net = sock_net(in_skb->sk);
 	struct ifaddrmsg *ifm;
@@ -4341,6 +4457,8 @@ errout:
 
 static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
 {
+	struct net *net = dev_net(ifp->idev->dev);
+
 	inet6_ifa_notify(event ? : RTM_NEWADDR, ifp);
 
 	switch (event) {
@@ -4366,6 +4484,7 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
 			dst_free(&ifp->rt->dst);
 		break;
 	}
+	atomic_inc(&net->ipv6.dev_addr_genid);
 }
 
 static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
@@ -4934,7 +5053,7 @@ int __init addrconf_init(void)
 	__rtnl_register(PF_INET6, RTM_GETANYCAST, NULL,
 			inet6_dump_ifacaddr, NULL);
 	__rtnl_register(PF_INET6, RTM_GETNETCONF, inet6_netconf_get_devconf,
-			NULL, NULL);
+			inet6_netconf_dump_devconf, NULL);
 
 	ipv6_addr_label_rtnl_register();
 
diff --git a/net/ipv6/addrlabel.c b/net/ipv6/addrlabel.c
index aad6435..f083a58 100644
--- a/net/ipv6/addrlabel.c
+++ b/net/ipv6/addrlabel.c
@@ -414,8 +414,7 @@ static const struct nla_policy ifal_policy[IFAL_MAX+1] = {
 	[IFAL_LABEL]		= { .len = sizeof(u32), },
 };
 
-static int ip6addrlbl_newdel(struct sk_buff *skb, struct nlmsghdr *nlh,
-			     void *arg)
+static int ip6addrlbl_newdel(struct sk_buff *skb, struct nlmsghdr *nlh)
 {
 	struct net *net = sock_net(skb->sk);
 	struct ifaddrlblmsg *ifal;
@@ -436,10 +435,7 @@ static int ip6addrlbl_newdel(struct sk_buff *skb, struct nlmsghdr *nlh,
 
 	if (!tb[IFAL_ADDRESS])
 		return -EINVAL;
-
 	pfx = nla_data(tb[IFAL_ADDRESS]);
-	if (!pfx)
-		return -EINVAL;
 
 	if (!tb[IFAL_LABEL])
 		return -EINVAL;
@@ -533,8 +529,7 @@ static inline int ip6addrlbl_msgsize(void)
 		+ nla_total_size(4);	/* IFAL_LABEL */
 }
 
-static int ip6addrlbl_get(struct sk_buff *in_skb, struct nlmsghdr* nlh,
-			  void *arg)
+static int ip6addrlbl_get(struct sk_buff *in_skb, struct nlmsghdr* nlh)
 {
 	struct net *net = sock_net(in_skb->sk);
 	struct ifaddrlblmsg *ifal;
@@ -561,10 +556,7 @@ static int ip6addrlbl_get(struct sk_buff *in_skb, struct nlmsghdr* nlh,
 
 	if (!tb[IFAL_ADDRESS])
 		return -EINVAL;
-
 	addr = nla_data(tb[IFAL_ADDRESS]);
-	if (!addr)
-		return -EINVAL;
 
 	rcu_read_lock();
 	p = __ipv6_addr_label(net, addr, ipv6_addr_type(addr), ifal->ifal_index);
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 6b793bf..ab5c7ad 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -49,7 +49,6 @@
 #include <net/udp.h>
 #include <net/udplite.h>
 #include <net/tcp.h>
-#include <net/ipip.h>
 #include <net/protocol.h>
 #include <net/inet_common.h>
 #include <net/route.h>
@@ -323,7 +322,7 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 			struct net_device *dev = NULL;
 
 			rcu_read_lock();
-			if (addr_type & IPV6_ADDR_LINKLOCAL) {
+			if (__ipv6_addr_needs_scope_id(addr_type)) {
 				if (addr_len >= sizeof(struct sockaddr_in6) &&
 				    addr->sin6_scope_id) {
 					/* Override any existing binding, if another one
@@ -471,8 +470,8 @@ int inet6_getname(struct socket *sock, struct sockaddr *uaddr,
 
 		sin->sin6_port = inet->inet_sport;
 	}
-	if (ipv6_addr_type(&sin->sin6_addr) & IPV6_ADDR_LINKLOCAL)
-		sin->sin6_scope_id = sk->sk_bound_dev_if;
+	sin->sin6_scope_id = ipv6_iface_scope_id(&sin->sin6_addr,
+						 sk->sk_bound_dev_if);
 	*uaddr_len = sizeof(*sin);
 	return 0;
 }
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index f5a5478..4b56cbb 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -124,7 +124,7 @@ ipv4_connected:
 		goto out;
 	}
 
-	if (addr_type&IPV6_ADDR_LINKLOCAL) {
+	if (__ipv6_addr_needs_scope_id(addr_type)) {
 		if (addr_len >= sizeof(struct sockaddr_in6) &&
 		    usin->sin6_scope_id) {
 			if (sk->sk_bound_dev_if &&
@@ -355,18 +355,19 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len)
 		sin->sin6_family = AF_INET6;
 		sin->sin6_flowinfo = 0;
 		sin->sin6_port = serr->port;
-		sin->sin6_scope_id = 0;
 		if (skb->protocol == htons(ETH_P_IPV6)) {
 			const struct ipv6hdr *ip6h = container_of((struct in6_addr *)(nh + serr->addr_offset),
 								  struct ipv6hdr, daddr);
 			sin->sin6_addr = ip6h->daddr;
 			if (np->sndflow)
 				sin->sin6_flowinfo = ip6_flowinfo(ip6h);
-			if (ipv6_addr_type(&sin->sin6_addr) & IPV6_ADDR_LINKLOCAL)
-				sin->sin6_scope_id = IP6CB(skb)->iif;
+			sin->sin6_scope_id =
+				ipv6_iface_scope_id(&sin->sin6_addr,
+						    IP6CB(skb)->iif);
 		} else {
 			ipv6_addr_set_v4mapped(*(__be32 *)(nh + serr->addr_offset),
 					       &sin->sin6_addr);
+			sin->sin6_scope_id = 0;
 		}
 	}
 
@@ -376,18 +377,19 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len)
 	if (serr->ee.ee_origin != SO_EE_ORIGIN_LOCAL) {
 		sin->sin6_family = AF_INET6;
 		sin->sin6_flowinfo = 0;
-		sin->sin6_scope_id = 0;
 		if (skb->protocol == htons(ETH_P_IPV6)) {
 			sin->sin6_addr = ipv6_hdr(skb)->saddr;
 			if (np->rxopt.all)
 				ip6_datagram_recv_ctl(sk, msg, skb);
-			if (ipv6_addr_type(&sin->sin6_addr) & IPV6_ADDR_LINKLOCAL)
-				sin->sin6_scope_id = IP6CB(skb)->iif;
+			sin->sin6_scope_id =
+				ipv6_iface_scope_id(&sin->sin6_addr,
+						    IP6CB(skb)->iif);
 		} else {
 			struct inet_sock *inet = inet_sk(sk);
 
 			ipv6_addr_set_v4mapped(ip_hdr(skb)->saddr,
 					       &sin->sin6_addr);
+			sin->sin6_scope_id = 0;
 			if (inet->cmsg_flags)
 				ip_cmsg_recv(msg, skb);
 		}
@@ -592,7 +594,9 @@ int ip6_datagram_recv_ctl(struct sock *sk, struct msghdr *msg,
 			sin6.sin6_addr = ipv6_hdr(skb)->daddr;
 			sin6.sin6_port = ports[1];
 			sin6.sin6_flowinfo = 0;
-			sin6.sin6_scope_id = 0;
+			sin6.sin6_scope_id =
+				ipv6_iface_scope_id(&ipv6_hdr(skb)->daddr,
+						    opt->iif);
 
 			put_cmsg(msg, SOL_IPV6, IPV6_ORIGDSTADDR, sizeof(sin6), &sin6);
 		}
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index fff5bdd..71b900c 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -434,7 +434,7 @@ void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info)
 	 *	Source addr check
 	 */
 
-	if (addr_type & IPV6_ADDR_LINKLOCAL)
+	if (__ipv6_addr_needs_scope_id(addr_type))
 		iif = skb->dev->ifindex;
 
 	/*
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c
index 9bfab19..e4311cb 100644
--- a/net/ipv6/inet6_connection_sock.c
+++ b/net/ipv6/inet6_connection_sock.c
@@ -54,6 +54,10 @@ int inet6_csk_bind_conflict(const struct sock *sk,
 				if (ipv6_rcv_saddr_equal(sk, sk2))
 					break;
 			}
+			if (!relax && reuse && sk2->sk_reuse &&
+			    sk2->sk_state != TCP_LISTEN &&
+			    ipv6_rcv_saddr_equal(sk, sk2))
+				break;
 		}
 	}
 
@@ -169,10 +173,8 @@ void inet6_csk_addr2sockaddr(struct sock *sk, struct sockaddr * uaddr)
 	sin6->sin6_port	= inet_sk(sk)->inet_dport;
 	/* We do not store received flowlabel for TCP */
 	sin6->sin6_flowinfo = 0;
-	sin6->sin6_scope_id = 0;
-	if (sk->sk_bound_dev_if &&
-	    ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL)
-		sin6->sin6_scope_id = sk->sk_bound_dev_if;
+	sin6->sin6_scope_id = ipv6_iface_scope_id(&sin6->sin6_addr,
+						  sk->sk_bound_dev_if);
 }
 
 EXPORT_SYMBOL_GPL(inet6_csk_addr2sockaddr);
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c
index b973ed3..46e8843 100644
--- a/net/ipv6/ip6_flowlabel.c
+++ b/net/ipv6/ip6_flowlabel.c
@@ -144,7 +144,9 @@ static void ip6_fl_gc(unsigned long dummy)
 	spin_lock(&ip6_fl_lock);
 
 	for (i=0; i<=FL_HASH_MASK; i++) {
-		struct ip6_flowlabel *fl, **flp;
+		struct ip6_flowlabel *fl;
+		struct ip6_flowlabel __rcu **flp;
+
 		flp = &fl_ht[i];
 		while ((fl = rcu_dereference_protected(*flp,
 						       lockdep_is_held(&ip6_fl_lock))) != NULL) {
@@ -179,7 +181,9 @@ static void __net_exit ip6_fl_purge(struct net *net)
 
 	spin_lock(&ip6_fl_lock);
 	for (i = 0; i <= FL_HASH_MASK; i++) {
-		struct ip6_flowlabel *fl, **flp;
+		struct ip6_flowlabel *fl;
+		struct ip6_flowlabel __rcu **flp;
+
 		flp = &fl_ht[i];
 		while ((fl = rcu_dereference_protected(*flp,
 						       lockdep_is_held(&ip6_fl_lock))) != NULL) {
@@ -506,7 +510,8 @@ int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen)
 	struct ipv6_pinfo *np = inet6_sk(sk);
 	struct in6_flowlabel_req freq;
 	struct ipv6_fl_socklist *sfl1=NULL;
-	struct ipv6_fl_socklist *sfl, **sflp;
+	struct ipv6_fl_socklist *sfl;
+	struct ipv6_fl_socklist __rcu **sflp;
 	struct ip6_flowlabel *fl, *fl1 = NULL;
 
 
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index e4efffe..d3ddd84 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -38,6 +38,7 @@
 
 #include <net/sock.h>
 #include <net/ip.h>
+#include <net/ip_tunnels.h>
 #include <net/icmp.h>
 #include <net/protocol.h>
 #include <net/addrconf.h>
@@ -110,46 +111,6 @@ static u32 HASH_ADDR(const struct in6_addr *addr)
 #define tunnels_l	tunnels[1]
 #define tunnels_wc	tunnels[0]
 
-static struct rtnl_link_stats64 *ip6gre_get_stats64(struct net_device *dev,
-		struct rtnl_link_stats64 *tot)
-{
-	int i;
-
-	for_each_possible_cpu(i) {
-		const struct pcpu_tstats *tstats = per_cpu_ptr(dev->tstats, i);
-		u64 rx_packets, rx_bytes, tx_packets, tx_bytes;
-		unsigned int start;
-
-		do {
-			start = u64_stats_fetch_begin_bh(&tstats->syncp);
-			rx_packets = tstats->rx_packets;
-			tx_packets = tstats->tx_packets;
-			rx_bytes = tstats->rx_bytes;
-			tx_bytes = tstats->tx_bytes;
-		} while (u64_stats_fetch_retry_bh(&tstats->syncp, start));
-
-		tot->rx_packets += rx_packets;
-		tot->tx_packets += tx_packets;
-		tot->rx_bytes   += rx_bytes;
-		tot->tx_bytes   += tx_bytes;
-	}
-
-	tot->multicast = dev->stats.multicast;
-	tot->rx_crc_errors = dev->stats.rx_crc_errors;
-	tot->rx_fifo_errors = dev->stats.rx_fifo_errors;
-	tot->rx_length_errors = dev->stats.rx_length_errors;
-	tot->rx_frame_errors = dev->stats.rx_frame_errors;
-	tot->rx_errors = dev->stats.rx_errors;
-
-	tot->tx_fifo_errors = dev->stats.tx_fifo_errors;
-	tot->tx_carrier_errors = dev->stats.tx_carrier_errors;
-	tot->tx_dropped = dev->stats.tx_dropped;
-	tot->tx_aborted_errors = dev->stats.tx_aborted_errors;
-	tot->tx_errors = dev->stats.tx_errors;
-
-	return tot;
-}
-
 /* Given src, dst and key, find appropriate for input tunnel. */
 
 static struct ip6_tnl *ip6gre_tunnel_lookup(struct net_device *dev,
@@ -667,7 +628,6 @@ static netdev_tx_t ip6gre_xmit2(struct sk_buff *skb,
 	struct net_device_stats *stats = &tunnel->dev->stats;
 	int err = -1;
 	u8 proto;
-	int pkt_len;
 	struct sk_buff *new_skb;
 
 	if (dev->type == ARPHRD_ETHER)
@@ -801,23 +761,9 @@ static netdev_tx_t ip6gre_xmit2(struct sk_buff *skb,
 		}
 	}
 
-	nf_reset(skb);
-	pkt_len = skb->len;
-	err = ip6_local_out(skb);
-
-	if (net_xmit_eval(err) == 0) {
-		struct pcpu_tstats *tstats = this_cpu_ptr(tunnel->dev->tstats);
-
-		tstats->tx_bytes += pkt_len;
-		tstats->tx_packets++;
-	} else {
-		stats->tx_errors++;
-		stats->tx_aborted_errors++;
-	}
-
+	ip6tunnel_xmit(skb, dev);
 	if (ndst)
 		ip6_tnl_dst_store(tunnel, ndst);
-
 	return 0;
 tx_err_link_failure:
 	stats->tx_carrier_errors++;
@@ -1271,7 +1217,7 @@ static const struct net_device_ops ip6gre_netdev_ops = {
 	.ndo_start_xmit		= ip6gre_tunnel_xmit,
 	.ndo_do_ioctl		= ip6gre_tunnel_ioctl,
 	.ndo_change_mtu		= ip6gre_tunnel_change_mtu,
-	.ndo_get_stats64	= ip6gre_get_stats64,
+	.ndo_get_stats64	= ip_tunnel_get_stats64,
 };
 
 static void ip6gre_dev_free(struct net_device *dev)
@@ -1520,7 +1466,7 @@ static const struct net_device_ops ip6gre_tap_netdev_ops = {
 	.ndo_set_mac_address = eth_mac_addr,
 	.ndo_validate_addr = eth_validate_addr,
 	.ndo_change_mtu = ip6gre_tunnel_change_mtu,
-	.ndo_get_stats64 = ip6gre_get_stats64,
+	.ndo_get_stats64 = ip_tunnel_get_stats64,
 };
 
 static void ip6gre_tap_setup(struct net_device *dev)
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index e33fe0a..2bab2aa 100644
--- a/net/ipv6/ip6_input.c
+++ b/net/ipv6/ip6_input.c
@@ -118,6 +118,18 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
 	    ipv6_addr_loopback(&hdr->daddr))
 		goto err;
 
+	/* RFC4291 Errata ID: 3480
+	 * Interface-Local scope spans only a single interface on a
+	 * node and is useful only for loopback transmission of
+	 * multicast.  Packets with interface-local scope received
+	 * from another node must be discarded.
+	 */
+	if (!(skb->pkt_type == PACKET_LOOPBACK ||
+	      dev->flags & IFF_LOOPBACK) &&
+	    ipv6_addr_is_multicast(&hdr->daddr) &&
+	    IPV6_ADDR_MC_SCOPE(&hdr->daddr) == 1)
+		goto err;
+
 	/* RFC4291 2.7
 	 * Nodes must not originate a packet to a multicast address whose scope
 	 * field contains the reserved value 0; if such a packet is received, it
diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c
index 8234c1d..71b766e 100644
--- a/net/ipv6/ip6_offload.c
+++ b/net/ipv6/ip6_offload.c
@@ -92,14 +92,12 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
 	u8 *prevhdr;
 	int offset = 0;
 
-	if (!(features & NETIF_F_V6_CSUM))
-		features &= ~NETIF_F_SG;
-
 	if (unlikely(skb_shinfo(skb)->gso_type &
 		     ~(SKB_GSO_UDP |
 		       SKB_GSO_DODGY |
 		       SKB_GSO_TCP_ECN |
 		       SKB_GSO_GRE |
+		       SKB_GSO_UDP_TUNNEL |
 		       SKB_GSO_TCPV6 |
 		       0)))
 		goto out;
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index fff83cb..1e55866 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -47,6 +47,7 @@
 
 #include <net/icmp.h>
 #include <net/ip.h>
+#include <net/ip_tunnels.h>
 #include <net/ipv6.h>
 #include <net/ip6_route.h>
 #include <net/addrconf.h>
@@ -955,7 +956,6 @@ static int ip6_tnl_xmit2(struct sk_buff *skb,
 	unsigned int max_headroom = sizeof(struct ipv6hdr);
 	u8 proto;
 	int err = -1;
-	int pkt_len;
 
 	if (!fl6->flowi6_mark)
 		dst = ip6_tnl_dst_check(t);
@@ -1035,19 +1035,7 @@ static int ip6_tnl_xmit2(struct sk_buff *skb,
 	ipv6h->nexthdr = proto;
 	ipv6h->saddr = fl6->saddr;
 	ipv6h->daddr = fl6->daddr;
-	nf_reset(skb);
-	pkt_len = skb->len;
-	err = ip6_local_out(skb);
-
-	if (net_xmit_eval(err) == 0) {
-		struct pcpu_tstats *tstats = this_cpu_ptr(t->dev->tstats);
-
-		tstats->tx_bytes += pkt_len;
-		tstats->tx_packets++;
-	} else {
-		stats->tx_errors++;
-		stats->tx_aborted_errors++;
-	}
+	ip6tunnel_xmit(skb, dev);
 	if (ndst)
 		ip6_tnl_dst_store(t, ndst);
 	return 0;
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index 96bfb4e..241fb8a 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -842,9 +842,9 @@ static void ip6mr_destroy_unres(struct mr6_table *mrt, struct mfc6_cache *c)
 		if (ipv6_hdr(skb)->version == 0) {
 			struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct ipv6hdr));
 			nlh->nlmsg_type = NLMSG_ERROR;
-			nlh->nlmsg_len = NLMSG_LENGTH(sizeof(struct nlmsgerr));
+			nlh->nlmsg_len = nlmsg_msg_size(sizeof(struct nlmsgerr));
 			skb_trim(skb, nlh->nlmsg_len);
-			((struct nlmsgerr *)NLMSG_DATA(nlh))->error = -ETIMEDOUT;
+			((struct nlmsgerr *)nlmsg_data(nlh))->error = -ETIMEDOUT;
 			rtnl_unicast(skb, net, NETLINK_CB(skb).portid);
 		} else
 			kfree_skb(skb);
@@ -1100,13 +1100,13 @@ static void ip6mr_cache_resolve(struct net *net, struct mr6_table *mrt,
 		if (ipv6_hdr(skb)->version == 0) {
 			struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct ipv6hdr));
 
-			if (__ip6mr_fill_mroute(mrt, skb, c, NLMSG_DATA(nlh)) > 0) {
+			if (__ip6mr_fill_mroute(mrt, skb, c, nlmsg_data(nlh)) > 0) {
 				nlh->nlmsg_len = skb_tail_pointer(skb) - (u8 *)nlh;
 			} else {
 				nlh->nlmsg_type = NLMSG_ERROR;
-				nlh->nlmsg_len = NLMSG_LENGTH(sizeof(struct nlmsgerr));
+				nlh->nlmsg_len = nlmsg_msg_size(sizeof(struct nlmsgerr));
 				skb_trim(skb, nlh->nlmsg_len);
-				((struct nlmsgerr *)NLMSG_DATA(nlh))->error = -EMSGSIZE;
+				((struct nlmsgerr *)nlmsg_data(nlh))->error = -EMSGSIZE;
 			}
 			rtnl_unicast(skb, net, NETLINK_CB(skb).portid);
 		} else
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 76ef435..2712ab2 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -610,8 +610,6 @@ void ndisc_send_rs(struct net_device *dev, const struct in6_addr *saddr,
 		}
 	}
 #endif
-	if (!dev->addr_len)
-		send_sllao = 0;
 	if (send_sllao)
 		optlen += ndisc_opt_addr_space(dev);
 
diff --git a/net/ipv6/netfilter/ip6t_NPT.c b/net/ipv6/netfilter/ip6t_NPT.c
index 33608c6..590f767 100644
--- a/net/ipv6/netfilter/ip6t_NPT.c
+++ b/net/ipv6/netfilter/ip6t_NPT.c
@@ -18,9 +18,8 @@
 static int ip6t_npt_checkentry(const struct xt_tgchk_param *par)
 {
 	struct ip6t_npt_tginfo *npt = par->targinfo;
-	__wsum src_sum = 0, dst_sum = 0;
 	struct in6_addr pfx;
-	unsigned int i;
+	__wsum src_sum, dst_sum;
 
 	if (npt->src_pfx_len > 64 || npt->dst_pfx_len > 64)
 		return -EINVAL;
@@ -33,12 +32,8 @@ static int ip6t_npt_checkentry(const struct xt_tgchk_param *par)
 	if (!ipv6_addr_equal(&pfx, &npt->dst_pfx.in6))
 		return -EINVAL;
 
-	for (i = 0; i < ARRAY_SIZE(npt->src_pfx.in6.s6_addr16); i++) {
-		src_sum = csum_add(src_sum,
-				(__force __wsum)npt->src_pfx.in6.s6_addr16[i]);
-		dst_sum = csum_add(dst_sum,
-				(__force __wsum)npt->dst_pfx.in6.s6_addr16[i]);
-	}
+	src_sum = csum_partial(&npt->src_pfx.in6, sizeof(npt->src_pfx.in6), 0);
+	dst_sum = csum_partial(&npt->dst_pfx.in6, sizeof(npt->dst_pfx.in6), 0);
 
 	npt->adjustment = ~csum_fold(csum_sub(src_sum, dst_sum));
 	return 0;
@@ -57,7 +52,7 @@ static bool ip6t_npt_map_pfx(const struct ip6t_npt_tginfo *npt,
 		if (pfx_len - i >= 32)
 			mask = 0;
 		else
-			mask = htonl(~((1 << (pfx_len - i)) - 1));
+			mask = htonl((1 << (i - pfx_len + 32)) - 1);
 
 		idx = i / 32;
 		addr->s6_addr32[idx] &= mask;
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
index 2b6c226..97bcf2b 100644
--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
@@ -330,12 +330,8 @@ ipv6_getorigdst(struct sock *sk, int optval, void __user *user, int *len)
 					sizeof(sin6.sin6_addr));
 
 	nf_ct_put(ct);
-
-	if (ipv6_addr_type(&sin6.sin6_addr) & IPV6_ADDR_LINKLOCAL)
-		sin6.sin6_scope_id = sk->sk_bound_dev_if;
-	else
-		sin6.sin6_scope_id = 0;
-
+	sin6.sin6_scope_id = ipv6_iface_scope_id(&sin6.sin6_addr,
+						 sk->sk_bound_dev_if);
 	return copy_to_user(user, &sin6, sizeof(sin6)) ? -EFAULT : 0;
 }
 
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c
index bbbe53a..7ea6e18 100644
--- a/net/ipv6/proc.c
+++ b/net/ipv6/proc.c
@@ -247,7 +247,7 @@ static int snmp6_dev_seq_show(struct seq_file *seq, void *v)
 
 static int snmp6_dev_seq_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, snmp6_dev_seq_show, PDE(inode)->data);
+	return single_open(file, snmp6_dev_seq_show, PDE_DATA(inode));
 }
 
 static const struct file_operations snmp6_dev_seq_fops = {
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 330b5e7..eedff8c 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -263,7 +263,7 @@ static int rawv6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
 	if (addr_type != IPV6_ADDR_ANY) {
 		struct net_device *dev = NULL;
 
-		if (addr_type & IPV6_ADDR_LINKLOCAL) {
+		if (__ipv6_addr_needs_scope_id(addr_type)) {
 			if (addr_len >= sizeof(struct sockaddr_in6) &&
 			    addr->sin6_scope_id) {
 				/* Override any existing binding, if another
@@ -498,9 +498,8 @@ static int rawv6_recvmsg(struct kiocb *iocb, struct sock *sk,
 		sin6->sin6_port = 0;
 		sin6->sin6_addr = ipv6_hdr(skb)->saddr;
 		sin6->sin6_flowinfo = 0;
-		sin6->sin6_scope_id = 0;
-		if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL)
-			sin6->sin6_scope_id = IP6CB(skb)->iif;
+		sin6->sin6_scope_id = ipv6_iface_scope_id(&sin6->sin6_addr,
+							  IP6CB(skb)->iif);
 	}
 
 	sock_recv_ts_and_drops(msg, sk, skb);
@@ -802,7 +801,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
 
 		if (addr_len >= sizeof(struct sockaddr_in6) &&
 		    sin6->sin6_scope_id &&
-		    ipv6_addr_type(daddr)&IPV6_ADDR_LINKLOCAL)
+		    __ipv6_addr_needs_scope_id(__ipv6_addr_type(daddr)))
 			fl6.flowi6_oif = sin6->sin6_scope_id;
 	} else {
 		if (sk->sk_state != TCP_ESTABLISHED)
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c
index 196ab93..e6e44ce 100644
--- a/net/ipv6/reassembly.c
+++ b/net/ipv6/reassembly.c
@@ -58,6 +58,7 @@
 #include <net/ndisc.h>
 #include <net/addrconf.h>
 #include <net/inet_frag.h>
+#include <net/inet_ecn.h>
 
 struct ip6frag_skb_cb
 {
@@ -67,6 +68,10 @@ struct ip6frag_skb_cb
 
 #define FRAG6_CB(skb)	((struct ip6frag_skb_cb*)((skb)->cb))
 
+static inline u8 ip6_frag_ecn(const struct ipv6hdr *ipv6h)
+{
+	return 1 << (ipv6_get_dsfield(ipv6h) & INET_ECN_MASK);
+}
 
 static struct inet_frags ip6_frags;
 
@@ -119,6 +124,7 @@ void ip6_frag_init(struct inet_frag_queue *q, void *a)
 	fq->user = arg->user;
 	fq->saddr = *arg->src;
 	fq->daddr = *arg->dst;
+	fq->ecn = arg->ecn;
 }
 EXPORT_SYMBOL(ip6_frag_init);
 
@@ -173,7 +179,8 @@ static void ip6_frag_expire(unsigned long data)
 }
 
 static __inline__ struct frag_queue *
-fq_find(struct net *net, __be32 id, const struct in6_addr *src, const struct in6_addr *dst)
+fq_find(struct net *net, __be32 id, const struct in6_addr *src,
+	const struct in6_addr *dst, u8 ecn)
 {
 	struct inet_frag_queue *q;
 	struct ip6_create_arg arg;
@@ -183,6 +190,7 @@ fq_find(struct net *net, __be32 id, const struct in6_addr *src, const struct in6
 	arg.user = IP6_DEFRAG_LOCAL_DELIVER;
 	arg.src = src;
 	arg.dst = dst;
+	arg.ecn = ecn;
 
 	read_lock(&ip6_frags.lock);
 	hash = inet6_hash_frag(id, src, dst, ip6_frags.rnd);
@@ -202,6 +210,7 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
 	struct net_device *dev;
 	int offset, end;
 	struct net *net = dev_net(skb_dst(skb)->dev);
+	u8 ecn;
 
 	if (fq->q.last_in & INET_FRAG_COMPLETE)
 		goto err;
@@ -219,6 +228,8 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
 		return -1;
 	}
 
+	ecn = ip6_frag_ecn(ipv6_hdr(skb));
+
 	if (skb->ip_summed == CHECKSUM_COMPLETE) {
 		const unsigned char *nh = skb_network_header(skb);
 		skb->csum = csum_sub(skb->csum,
@@ -319,6 +330,7 @@ found:
 	}
 	fq->q.stamp = skb->tstamp;
 	fq->q.meat += skb->len;
+	fq->ecn |= ecn;
 	add_frag_mem_limit(&fq->q, skb->truesize);
 
 	/* The first fragment.
@@ -362,9 +374,14 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev,
 	int    payload_len;
 	unsigned int nhoff;
 	int sum_truesize;
+	u8 ecn;
 
 	inet_frag_kill(&fq->q, &ip6_frags);
 
+	ecn = ip_frag_ecn_table[fq->ecn];
+	if (unlikely(ecn == 0xff))
+		goto out_fail;
+
 	/* Make the one we just received the head. */
 	if (prev) {
 		head = prev->next;
@@ -463,6 +480,7 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev,
 	head->dev = dev;
 	head->tstamp = fq->q.stamp;
 	ipv6_hdr(head)->payload_len = htons(payload_len);
+	ipv6_change_dsfield(ipv6_hdr(head), 0xff, ecn);
 	IP6CB(head)->nhoff = nhoff;
 
 	/* Yes, and fold redundant checksum back. 8) */
@@ -526,7 +544,8 @@ static int ipv6_frag_rcv(struct sk_buff *skb)
 		IP6_ADD_STATS_BH(net, ip6_dst_idev(skb_dst(skb)),
 				 IPSTATS_MIB_REASMFAILS, evicted);
 
-	fq = fq_find(net, fhdr->identification, &hdr->saddr, &hdr->daddr);
+	fq = fq_find(net, fhdr->identification, &hdr->saddr, &hdr->daddr,
+		     ip6_frag_ecn(hdr));
 	if (fq != NULL) {
 		int ret;
 
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index e5fe004..ad0aa6b 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -2355,7 +2355,7 @@ beginning:
 	return last_err;
 }
 
-static int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
+static int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh)
 {
 	struct fib6_config cfg;
 	int err;
@@ -2370,7 +2370,7 @@ static int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *a
 		return ip6_route_del(&cfg);
 }
 
-static int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
+static int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh)
 {
 	struct fib6_config cfg;
 	int err;
@@ -2562,7 +2562,7 @@ int rt6_dump_route(struct rt6_info *rt, void *p_arg)
 		     prefix, 0, NLM_F_MULTI);
 }
 
-static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg)
+static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh)
 {
 	struct net *net = sock_net(in_skb->sk);
 	struct nlattr *tb[RTA_MAX+1];
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index 02f96dc..3353634 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -49,7 +49,7 @@
 #include <net/ip.h>
 #include <net/udp.h>
 #include <net/icmp.h>
-#include <net/ipip.h>
+#include <net/ip_tunnels.h>
 #include <net/inet_ecn.h>
 #include <net/xfrm.h>
 #include <net/dsfield.h>
@@ -87,41 +87,6 @@ struct sit_net {
 	struct net_device *fb_tunnel_dev;
 };
 
-static struct rtnl_link_stats64 *ipip6_get_stats64(struct net_device *dev,
-						   struct rtnl_link_stats64 *tot)
-{
-	int i;
-
-	for_each_possible_cpu(i) {
-		const struct pcpu_tstats *tstats = per_cpu_ptr(dev->tstats, i);
-		u64 rx_packets, rx_bytes, tx_packets, tx_bytes;
-		unsigned int start;
-
-		do {
-			start = u64_stats_fetch_begin_bh(&tstats->syncp);
-			rx_packets = tstats->rx_packets;
-			tx_packets = tstats->tx_packets;
-			rx_bytes = tstats->rx_bytes;
-			tx_bytes = tstats->tx_bytes;
-		} while (u64_stats_fetch_retry_bh(&tstats->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->rx_frame_errors = dev->stats.rx_frame_errors;
-	tot->tx_fifo_errors = dev->stats.tx_fifo_errors;
-	tot->tx_carrier_errors = dev->stats.tx_carrier_errors;
-	tot->tx_dropped = dev->stats.tx_dropped;
-	tot->tx_aborted_errors = dev->stats.tx_aborted_errors;
-	tot->tx_errors = dev->stats.tx_errors;
-
-	return tot;
-}
-
 /*
  * Must be invoked with rcu_read_lock
  */
@@ -899,6 +864,8 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
 	if ((iph->ttl = tiph->ttl) == 0)
 		iph->ttl	=	iph6->hop_limit;
 
+	skb->ip_summed = CHECKSUM_NONE;
+	ip_select_ident(iph, skb_dst(skb), NULL);
 	iptunnel_xmit(skb, dev);
 	return NETDEV_TX_OK;
 
@@ -1200,7 +1167,7 @@ static const struct net_device_ops ipip6_netdev_ops = {
 	.ndo_start_xmit	= ipip6_tunnel_xmit,
 	.ndo_do_ioctl	= ipip6_tunnel_ioctl,
 	.ndo_change_mtu	= ipip6_tunnel_change_mtu,
-	.ndo_get_stats64= ipip6_get_stats64,
+	.ndo_get_stats64 = ip_tunnel_get_stats64,
 };
 
 static void ipip6_dev_free(struct net_device *dev)
diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c
index 8a0848b..d5dda20 100644
--- a/net/ipv6/syncookies.c
+++ b/net/ipv6/syncookies.c
@@ -149,7 +149,6 @@ static inline int cookie_check(const struct sk_buff *skb, __u32 cookie)
 struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
 {
 	struct tcp_options_received tcp_opt;
-	const u8 *hash_location;
 	struct inet_request_sock *ireq;
 	struct inet6_request_sock *ireq6;
 	struct tcp_request_sock *treq;
@@ -177,7 +176,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
 
 	/* check for timestamp cookie support */
 	memset(&tcp_opt, 0, sizeof(tcp_opt));
-	tcp_parse_options(skb, &tcp_opt, &hash_location, 0, NULL);
+	tcp_parse_options(skb, &tcp_opt, 0, NULL);
 
 	if (!cookie_check_timestamp(&tcp_opt, sock_net(sk), &ecn_ok))
 		goto out;
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index f6d629f..1033d2b 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -461,7 +461,6 @@ out:
 static int tcp_v6_send_synack(struct sock *sk, struct dst_entry *dst,
 			      struct flowi6 *fl6,
 			      struct request_sock *req,
-			      struct request_values *rvp,
 			      u16 queue_mapping)
 {
 	struct inet6_request_sock *treq = inet6_rsk(req);
@@ -473,7 +472,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct dst_entry *dst,
 	if (!dst && (dst = inet6_csk_route_req(sk, fl6, req)) == NULL)
 		goto done;
 
-	skb = tcp_make_synack(sk, dst, req, rvp, NULL);
+	skb = tcp_make_synack(sk, dst, req, NULL);
 
 	if (skb) {
 		__tcp_v6_send_check(skb, &treq->loc_addr, &treq->rmt_addr);
@@ -488,13 +487,12 @@ done:
 	return err;
 }
 
-static int tcp_v6_rtx_synack(struct sock *sk, struct request_sock *req,
-			     struct request_values *rvp)
+static int tcp_v6_rtx_synack(struct sock *sk, struct request_sock *req)
 {
 	struct flowi6 fl6;
 	int res;
 
-	res = tcp_v6_send_synack(sk, NULL, &fl6, req, rvp, 0);
+	res = tcp_v6_send_synack(sk, NULL, &fl6, req, 0);
 	if (!res)
 		TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_RETRANSSEGS);
 	return res;
@@ -947,9 +945,7 @@ static struct sock *tcp_v6_hnd_req(struct sock *sk,struct sk_buff *skb)
  */
 static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
 {
-	struct tcp_extend_values tmp_ext;
 	struct tcp_options_received tmp_opt;
-	const u8 *hash_location;
 	struct request_sock *req;
 	struct inet6_request_sock *treq;
 	struct ipv6_pinfo *np = inet6_sk(sk);
@@ -987,50 +983,7 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
 	tcp_clear_options(&tmp_opt);
 	tmp_opt.mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr);
 	tmp_opt.user_mss = tp->rx_opt.user_mss;
-	tcp_parse_options(skb, &tmp_opt, &hash_location, 0, NULL);
-
-	if (tmp_opt.cookie_plus > 0 &&
-	    tmp_opt.saw_tstamp &&
-	    !tp->rx_opt.cookie_out_never &&
-	    (sysctl_tcp_cookie_size > 0 ||
-	     (tp->cookie_values != NULL &&
-	      tp->cookie_values->cookie_desired > 0))) {
-		u8 *c;
-		u32 *d;
-		u32 *mess = &tmp_ext.cookie_bakery[COOKIE_DIGEST_WORDS];
-		int l = tmp_opt.cookie_plus - TCPOLEN_COOKIE_BASE;
-
-		if (tcp_cookie_generator(&tmp_ext.cookie_bakery[0]) != 0)
-			goto drop_and_free;
-
-		/* Secret recipe starts with IP addresses */
-		d = (__force u32 *)&ipv6_hdr(skb)->daddr.s6_addr32[0];
-		*mess++ ^= *d++;
-		*mess++ ^= *d++;
-		*mess++ ^= *d++;
-		*mess++ ^= *d++;
-		d = (__force u32 *)&ipv6_hdr(skb)->saddr.s6_addr32[0];
-		*mess++ ^= *d++;
-		*mess++ ^= *d++;
-		*mess++ ^= *d++;
-		*mess++ ^= *d++;
-
-		/* plus variable length Initiator Cookie */
-		c = (u8 *)mess;
-		while (l-- > 0)
-			*c++ ^= *hash_location++;
-
-		want_cookie = false;	/* not our kind of cookie */
-		tmp_ext.cookie_out_never = 0; /* false */
-		tmp_ext.cookie_plus = tmp_opt.cookie_plus;
-	} else if (!tp->rx_opt.cookie_in_always) {
-		/* redundant indications, but ensure initialization. */
-		tmp_ext.cookie_out_never = 1; /* true */
-		tmp_ext.cookie_plus = 0;
-	} else {
-		goto drop_and_free;
-	}
-	tmp_ext.cookie_in_always = tp->rx_opt.cookie_in_always;
+	tcp_parse_options(skb, &tmp_opt, 0, NULL);
 
 	if (want_cookie && !tmp_opt.saw_tstamp)
 		tcp_clear_options(&tmp_opt);
@@ -1108,7 +1061,6 @@ have_isn:
 		goto drop_and_release;
 
 	if (tcp_v6_send_synack(sk, dst, &fl6, req,
-			       (struct request_values *)&tmp_ext,
 			       skb_get_queue_mapping(skb)) ||
 	    want_cookie)
 		goto drop_and_free;
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index d8e5e85..da6019b 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -450,15 +450,16 @@ try_again:
 		sin6->sin6_family = AF_INET6;
 		sin6->sin6_port = udp_hdr(skb)->source;
 		sin6->sin6_flowinfo = 0;
-		sin6->sin6_scope_id = 0;
 
-		if (is_udp4)
+		if (is_udp4) {
 			ipv6_addr_set_v4mapped(ip_hdr(skb)->saddr,
 					       &sin6->sin6_addr);
-		else {
+			sin6->sin6_scope_id = 0;
+		} else {
 			sin6->sin6_addr = ipv6_hdr(skb)->saddr;
-			if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL)
-				sin6->sin6_scope_id = IP6CB(skb)->iif;
+			sin6->sin6_scope_id =
+				ipv6_iface_scope_id(&sin6->sin6_addr,
+						    IP6CB(skb)->iif);
 		}
 
 	}
@@ -1118,7 +1119,7 @@ do_udp_sendmsg:
 
 		if (addr_len >= sizeof(struct sockaddr_in6) &&
 		    sin6->sin6_scope_id &&
-		    ipv6_addr_type(daddr)&IPV6_ADDR_LINKLOCAL)
+		    __ipv6_addr_needs_scope_id(__ipv6_addr_type(daddr)))
 			fl6.flowi6_oif = sin6->sin6_scope_id;
 	} else {
 		if (sk->sk_state != TCP_ESTABLISHED)
diff --git a/net/ipv6/udp_offload.c b/net/ipv6/udp_offload.c
index cf05cf0..3bb3a89 100644
--- a/net/ipv6/udp_offload.c
+++ b/net/ipv6/udp_offload.c
@@ -21,6 +21,10 @@ static int udp6_ufo_send_check(struct sk_buff *skb)
 	const struct ipv6hdr *ipv6h;
 	struct udphdr *uh;
 
+	/* UDP Tunnel offload on ipv6 is not yet supported. */
+	if (skb->encapsulation)
+		return -EINVAL;
+
 	if (!pskb_may_pull(skb, sizeof(*uh)))
 		return -EINVAL;
 
@@ -56,7 +60,9 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb,
 		/* Packet is from an untrusted source, reset gso_segs. */
 		int type = skb_shinfo(skb)->gso_type;
 
-		if (unlikely(type & ~(SKB_GSO_UDP | SKB_GSO_DODGY |
+		if (unlikely(type & ~(SKB_GSO_UDP |
+				      SKB_GSO_DODGY |
+				      SKB_GSO_UDP_TUNNEL |
 				      SKB_GSO_GRE) ||
 			     !(type & (SKB_GSO_UDP))))
 			goto out;
diff --git a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c
index 9bf6a74..4770d51 100644
--- a/net/ipv6/xfrm6_mode_tunnel.c
+++ b/net/ipv6/xfrm6_mode_tunnel.c
@@ -49,8 +49,11 @@ static int xfrm6_mode_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
 	       sizeof(top_iph->flow_lbl));
 	top_iph->nexthdr = xfrm_af2proto(skb_dst(skb)->ops->family);
 
-	dsfield = XFRM_MODE_SKB_CB(skb)->tos;
-	dsfield = INET_ECN_encapsulate(dsfield, dsfield);
+	if (x->props.extra_flags & XFRM_SA_XFLAG_DONT_ENCAP_DSCP)
+		dsfield = 0;
+	else
+		dsfield = XFRM_MODE_SKB_CB(skb)->tos;
+	dsfield = INET_ECN_encapsulate(dsfield, XFRM_MODE_SKB_CB(skb)->tos);
 	if (x->props.flags & XFRM_STATE_NOECN)
 		dsfield &= ~INET_ECN_MASK;
 	ipv6_change_dsfield(top_iph, 0, dsfield);
diff --git a/net/irda/ircomm/ircomm_tty_attach.c b/net/irda/ircomm/ircomm_tty_attach.c
index edab393..a2a508f 100644
--- a/net/irda/ircomm/ircomm_tty_attach.c
+++ b/net/irda/ircomm/ircomm_tty_attach.c
@@ -997,12 +997,8 @@ static int ircomm_tty_state_ready(struct ircomm_tty_cb *self,
 			self->settings.dce = IRCOMM_DELTA_CD;
 			ircomm_tty_check_modem_status(self);
 		} else {
-			struct tty_struct *tty = tty_port_tty_get(&self->port);
 			IRDA_DEBUG(0, "%s(), hanging up!\n", __func__ );
-			if (tty) {
-				tty_hangup(tty);
-				tty_kref_put(tty);
-			}
+			tty_port_tty_hangup(&self->port, false);
 		}
 		break;
 	default:
diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c
index a7d11ffe..7dfb9ed 100644
--- a/net/iucv/af_iucv.c
+++ b/net/iucv/af_iucv.c
@@ -1461,7 +1461,8 @@ unsigned int iucv_sock_poll(struct file *file, struct socket *sock,
 		return iucv_accept_poll(sk);
 
 	if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
-		mask |= POLLERR;
+		mask |= POLLERR |
+			(sock_flag(sk, SOCK_SELECT_ERR_QUEUE) ? POLLPRI : 0);
 
 	if (sk->sk_shutdown & RCV_SHUTDOWN)
 		mask |= POLLRDHUP;
diff --git a/net/key/af_key.c b/net/key/af_key.c
index 8555f33..5b1e5af 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -2693,6 +2693,7 @@ static int key_notify_policy_flush(const struct km_event *c)
 	hdr->sadb_msg_pid = c->portid;
 	hdr->sadb_msg_version = PF_KEY_V2;
 	hdr->sadb_msg_errno = (uint8_t) 0;
+	hdr->sadb_msg_satype = SADB_SATYPE_UNSPEC;
 	hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t));
 	pfkey_broadcast(skb_out, GFP_ATOMIC, BROADCAST_ALL, NULL, c->net);
 	return 0;
diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c
index 8aecf5d..6984c3a 100644
--- a/net/l2tp/l2tp_core.c
+++ b/net/l2tp/l2tp_core.c
@@ -1777,7 +1777,7 @@ int l2tp_session_delete(struct l2tp_session *session)
 	if (session->session_close != NULL)
 		(*session->session_close)(session);
 	if (session->deref)
-		(*session->ref)(session);
+		(*session->deref)(session);
 	l2tp_session_dec_refcount(session);
 	return 0;
 }
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index fb30681..c50c194 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -175,7 +175,7 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
 		 *       add it to the device after the station.
 		 */
 		if (!sta || !test_sta_flag(sta, WLAN_STA_ASSOC)) {
-			ieee80211_key_free(sdata->local, key);
+			ieee80211_key_free_unused(key);
 			err = -ENOENT;
 			goto out_unlock;
 		}
@@ -214,8 +214,6 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
 	}
 
 	err = ieee80211_key_link(key, sdata, sta);
-	if (err)
-		ieee80211_key_free(sdata->local, key);
 
  out_unlock:
 	mutex_unlock(&sdata->local->sta_mtx);
@@ -254,7 +252,7 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
 		goto out_unlock;
 	}
 
-	__ieee80211_key_free(key);
+	ieee80211_key_free(key, true);
 
 	ret = 0;
  out_unlock:
@@ -445,12 +443,14 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
 	struct ieee80211_sub_if_data *sdata = sta->sdata;
 	struct ieee80211_local *local = sdata->local;
 	struct timespec uptime;
+	u64 packets = 0;
+	int ac;
 
 	sinfo->generation = sdata->local->sta_generation;
 
 	sinfo->filled = STATION_INFO_INACTIVE_TIME |
-			STATION_INFO_RX_BYTES |
-			STATION_INFO_TX_BYTES |
+			STATION_INFO_RX_BYTES64 |
+			STATION_INFO_TX_BYTES64 |
 			STATION_INFO_RX_PACKETS |
 			STATION_INFO_TX_PACKETS |
 			STATION_INFO_TX_RETRIES |
@@ -467,10 +467,14 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
 	sinfo->connected_time = uptime.tv_sec - sta->last_connected;
 
 	sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
+	sinfo->tx_bytes = 0;
+	for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
+		sinfo->tx_bytes += sta->tx_bytes[ac];
+		packets += sta->tx_packets[ac];
+	}
+	sinfo->tx_packets = packets;
 	sinfo->rx_bytes = sta->rx_bytes;
-	sinfo->tx_bytes = sta->tx_bytes;
 	sinfo->rx_packets = sta->rx_packets;
-	sinfo->tx_packets = sta->tx_packets;
 	sinfo->tx_retries = sta->tx_retry_count;
 	sinfo->tx_failed = sta->tx_retry_failed;
 	sinfo->rx_dropped_misc = sta->rx_dropped;
@@ -598,8 +602,8 @@ static void ieee80211_get_et_stats(struct wiphy *wiphy,
 		data[i++] += sta->rx_fragments;		\
 		data[i++] += sta->rx_dropped;		\
 							\
-		data[i++] += sta->tx_packets;		\
-		data[i++] += sta->tx_bytes;		\
+		data[i++] += sinfo.tx_packets;		\
+		data[i++] += sinfo.tx_bytes;		\
 		data[i++] += sta->tx_fragments;		\
 		data[i++] += sta->tx_filtered_count;	\
 		data[i++] += sta->tx_retry_failed;	\
@@ -621,13 +625,14 @@ static void ieee80211_get_et_stats(struct wiphy *wiphy,
 		if (!(sta && !WARN_ON(sta->sdata->dev != dev)))
 			goto do_survey;
 
+		sinfo.filled = 0;
+		sta_set_sinfo(sta, &sinfo);
+
 		i = 0;
 		ADD_STA_STATS(sta);
 
 		data[i++] = sta->sta_state;
 
-		sinfo.filled = 0;
-		sta_set_sinfo(sta, &sinfo);
 
 		if (sinfo.filled & STATION_INFO_TX_BITRATE)
 			data[i] = 100000 *
@@ -1035,9 +1040,12 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
 		sta_info_flush_defer(vlan);
 	sta_info_flush_defer(sdata);
 	rcu_barrier();
-	list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
+	list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) {
 		sta_info_flush_cleanup(vlan);
+		ieee80211_free_keys(vlan);
+	}
 	sta_info_flush_cleanup(sdata);
+	ieee80211_free_keys(sdata);
 
 	sdata->vif.bss_conf.enable_beacon = false;
 	clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state);
@@ -1177,6 +1185,18 @@ static int sta_apply_parameters(struct ieee80211_local *local,
 			mask |= BIT(NL80211_STA_FLAG_ASSOCIATED);
 		if (set & BIT(NL80211_STA_FLAG_AUTHENTICATED))
 			set |= BIT(NL80211_STA_FLAG_ASSOCIATED);
+	} else if (test_sta_flag(sta, WLAN_STA_TDLS_PEER)) {
+		/*
+		 * TDLS -- everything follows authorized, but
+		 * only becoming authorized is possible, not
+		 * going back
+		 */
+		if (set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
+			set |= BIT(NL80211_STA_FLAG_AUTHENTICATED) |
+			       BIT(NL80211_STA_FLAG_ASSOCIATED);
+			mask |= BIT(NL80211_STA_FLAG_AUTHENTICATED) |
+				BIT(NL80211_STA_FLAG_ASSOCIATED);
+		}
 	}
 
 	ret = sta_apply_auth_flags(local, sta, mask, set);
@@ -1261,7 +1281,8 @@ static int sta_apply_parameters(struct ieee80211_local *local,
 	if (ieee80211_vif_is_mesh(&sdata->vif)) {
 #ifdef CONFIG_MAC80211_MESH
 		u32 changed = 0;
-		if (sdata->u.mesh.security & IEEE80211_MESH_SEC_SECURED) {
+
+		if (params->sta_modify_mask & STATION_PARAM_APPLY_PLINK_STATE) {
 			switch (params->plink_state) {
 			case NL80211_PLINK_ESTAB:
 				if (sta->plink_state != NL80211_PLINK_ESTAB)
@@ -1292,15 +1313,18 @@ static int sta_apply_parameters(struct ieee80211_local *local,
 				/*  nothing  */
 				break;
 			}
-		} else {
-			switch (params->plink_action) {
-			case PLINK_ACTION_OPEN:
-				changed |= mesh_plink_open(sta);
-				break;
-			case PLINK_ACTION_BLOCK:
-				changed |= mesh_plink_block(sta);
-				break;
-			}
+		}
+
+		switch (params->plink_action) {
+		case NL80211_PLINK_ACTION_NO_ACTION:
+			/* nothing */
+			break;
+		case NL80211_PLINK_ACTION_OPEN:
+			changed |= mesh_plink_open(sta);
+			break;
+		case NL80211_PLINK_ACTION_BLOCK:
+			changed |= mesh_plink_block(sta);
+			break;
 		}
 
 		if (params->local_pm)
@@ -1346,8 +1370,10 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
 	 * defaults -- if userspace wants something else we'll
 	 * change it accordingly in sta_apply_parameters()
 	 */
-	sta_info_pre_move_state(sta, IEEE80211_STA_AUTH);
-	sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC);
+	if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))) {
+		sta_info_pre_move_state(sta, IEEE80211_STA_AUTH);
+		sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC);
+	}
 
 	err = sta_apply_parameters(local, sta, params);
 	if (err) {
@@ -1356,8 +1382,8 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
 	}
 
 	/*
-	 * for TDLS, rate control should be initialized only when supported
-	 * rates are known.
+	 * for TDLS, rate control should be initialized only when
+	 * rates are known and station is marked authorized
 	 */
 	if (!test_sta_flag(sta, WLAN_STA_TDLS_PEER))
 		rate_control_rate_init(sta);
@@ -1394,50 +1420,67 @@ static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev,
 }
 
 static int ieee80211_change_station(struct wiphy *wiphy,
-				    struct net_device *dev,
-				    u8 *mac,
+				    struct net_device *dev, u8 *mac,
 				    struct station_parameters *params)
 {
 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 	struct ieee80211_local *local = wiphy_priv(wiphy);
 	struct sta_info *sta;
 	struct ieee80211_sub_if_data *vlansdata;
+	enum cfg80211_station_type statype;
 	int err;
 
 	mutex_lock(&local->sta_mtx);
 
 	sta = sta_info_get_bss(sdata, mac);
 	if (!sta) {
-		mutex_unlock(&local->sta_mtx);
-		return -ENOENT;
+		err = -ENOENT;
+		goto out_err;
 	}
 
-	/* in station mode, some updates are only valid with TDLS */
-	if (sdata->vif.type == NL80211_IFTYPE_STATION &&
-	    (params->supported_rates || params->ht_capa || params->vht_capa ||
-	     params->sta_modify_mask ||
-	     (params->sta_flags_mask & BIT(NL80211_STA_FLAG_WME))) &&
-	    !test_sta_flag(sta, WLAN_STA_TDLS_PEER)) {
-		mutex_unlock(&local->sta_mtx);
-		return -EINVAL;
+	switch (sdata->vif.type) {
+	case NL80211_IFTYPE_MESH_POINT:
+		if (sdata->u.mesh.user_mpm)
+			statype = CFG80211_STA_MESH_PEER_USER;
+		else
+			statype = CFG80211_STA_MESH_PEER_KERNEL;
+		break;
+	case NL80211_IFTYPE_ADHOC:
+		statype = CFG80211_STA_IBSS;
+		break;
+	case NL80211_IFTYPE_STATION:
+		if (!test_sta_flag(sta, WLAN_STA_TDLS_PEER)) {
+			statype = CFG80211_STA_AP_STA;
+			break;
+		}
+		if (test_sta_flag(sta, WLAN_STA_AUTHORIZED))
+			statype = CFG80211_STA_TDLS_PEER_ACTIVE;
+		else
+			statype = CFG80211_STA_TDLS_PEER_SETUP;
+		break;
+	case NL80211_IFTYPE_AP:
+	case NL80211_IFTYPE_AP_VLAN:
+		statype = CFG80211_STA_AP_CLIENT;
+		break;
+	default:
+		err = -EOPNOTSUPP;
+		goto out_err;
 	}
 
+	err = cfg80211_check_station_change(wiphy, params, statype);
+	if (err)
+		goto out_err;
+
 	if (params->vlan && params->vlan != sta->sdata->dev) {
 		bool prev_4addr = false;
 		bool new_4addr = false;
 
 		vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan);
 
-		if (vlansdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
-		    vlansdata->vif.type != NL80211_IFTYPE_AP) {
-			mutex_unlock(&local->sta_mtx);
-			return -EINVAL;
-		}
-
 		if (params->vlan->ieee80211_ptr->use_4addr) {
 			if (vlansdata->u.vlan.sta) {
-				mutex_unlock(&local->sta_mtx);
-				return -EBUSY;
+				err = -EBUSY;
+				goto out_err;
 			}
 
 			rcu_assign_pointer(vlansdata->u.vlan.sta, sta);
@@ -1464,12 +1507,12 @@ static int ieee80211_change_station(struct wiphy *wiphy,
 	}
 
 	err = sta_apply_parameters(local, sta, params);
-	if (err) {
-		mutex_unlock(&local->sta_mtx);
-		return err;
-	}
+	if (err)
+		goto out_err;
 
-	if (test_sta_flag(sta, WLAN_STA_TDLS_PEER) && params->supported_rates)
+	/* When peer becomes authorized, init rate control as well */
+	if (test_sta_flag(sta, WLAN_STA_TDLS_PEER) &&
+	    test_sta_flag(sta, WLAN_STA_AUTHORIZED))
 		rate_control_rate_init(sta);
 
 	mutex_unlock(&local->sta_mtx);
@@ -1479,7 +1522,11 @@ static int ieee80211_change_station(struct wiphy *wiphy,
 		ieee80211_recalc_ps(local, -1);
 		ieee80211_recalc_ps_vif(sdata);
 	}
+
 	return 0;
+out_err:
+	mutex_unlock(&local->sta_mtx);
+	return err;
 }
 
 #ifdef CONFIG_MAC80211_MESH
@@ -1687,6 +1734,7 @@ static int copy_mesh_setup(struct ieee80211_if_mesh *ifmsh,
 	ifmsh->mesh_sp_id = setup->sync_method;
 	ifmsh->mesh_pp_id = setup->path_sel_proto;
 	ifmsh->mesh_pm_id = setup->path_metric;
+	ifmsh->user_mpm = setup->user_mpm;
 	ifmsh->security = IEEE80211_MESH_SEC_NONE;
 	if (setup->is_authenticated)
 		ifmsh->security |= IEEE80211_MESH_SEC_AUTHED;
@@ -1730,8 +1778,11 @@ static int ieee80211_update_mesh_config(struct wiphy *wiphy,
 		conf->dot11MeshTTL = nconf->dot11MeshTTL;
 	if (_chg_mesh_attr(NL80211_MESHCONF_ELEMENT_TTL, mask))
 		conf->element_ttl = nconf->element_ttl;
-	if (_chg_mesh_attr(NL80211_MESHCONF_AUTO_OPEN_PLINKS, mask))
+	if (_chg_mesh_attr(NL80211_MESHCONF_AUTO_OPEN_PLINKS, mask)) {
+		if (ifmsh->user_mpm)
+			return -EBUSY;
 		conf->auto_open_plinks = nconf->auto_open_plinks;
+	}
 	if (_chg_mesh_attr(NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR, mask))
 		conf->dot11MeshNbrOffsetMaxNeighbor =
 			nconf->dot11MeshNbrOffsetMaxNeighbor;
@@ -2371,7 +2422,8 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local,
 				    struct ieee80211_sub_if_data *sdata,
 				    struct ieee80211_channel *channel,
 				    unsigned int duration, u64 *cookie,
-				    struct sk_buff *txskb)
+				    struct sk_buff *txskb,
+				    enum ieee80211_roc_type type)
 {
 	struct ieee80211_roc_work *roc, *tmp;
 	bool queued = false;
@@ -2390,6 +2442,7 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local,
 	roc->duration = duration;
 	roc->req_duration = duration;
 	roc->frame = txskb;
+	roc->type = type;
 	roc->mgmt_tx_cookie = (unsigned long)txskb;
 	roc->sdata = sdata;
 	INIT_DELAYED_WORK(&roc->work, ieee80211_sw_roc_work);
@@ -2420,7 +2473,7 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local,
 	if (!duration)
 		duration = 10;
 
-	ret = drv_remain_on_channel(local, sdata, channel, duration);
+	ret = drv_remain_on_channel(local, sdata, channel, duration, type);
 	if (ret) {
 		kfree(roc);
 		return ret;
@@ -2439,10 +2492,13 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local,
 		 *
 		 * If it hasn't started yet, just increase the duration
 		 * and add the new one to the list of dependents.
+		 * If the type of the new ROC has higher priority, modify the
+		 * type of the previous one to match that of the new one.
 		 */
 		if (!tmp->started) {
 			list_add_tail(&roc->list, &tmp->dependents);
 			tmp->duration = max(tmp->duration, roc->duration);
+			tmp->type = max(tmp->type, roc->type);
 			queued = true;
 			break;
 		}
@@ -2454,16 +2510,18 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local,
 			/*
 			 * In the offloaded ROC case, if it hasn't begun, add
 			 * this new one to the dependent list to be handled
-			 * when the the master one begins. If it has begun,
+			 * when the master one begins. If it has begun,
 			 * check that there's still a minimum time left and
 			 * if so, start this one, transmitting the frame, but
-			 * add it to the list directly after this one with a
+			 * add it to the list directly after this one with
 			 * a reduced time so we'll ask the driver to execute
 			 * it right after finishing the previous one, in the
 			 * hope that it'll also be executed right afterwards,
 			 * effectively extending the old one.
 			 * If there's no minimum time left, just add it to the
 			 * normal list.
+			 * TODO: the ROC type is ignored here, assuming that it
+			 * is better to immediately use the current ROC.
 			 */
 			if (!tmp->hw_begun) {
 				list_add_tail(&roc->list, &tmp->dependents);
@@ -2557,7 +2615,8 @@ static int ieee80211_remain_on_channel(struct wiphy *wiphy,
 
 	mutex_lock(&local->mtx);
 	ret = ieee80211_start_roc_work(local, sdata, chan,
-				       duration, cookie, NULL);
+				       duration, cookie, NULL,
+				       IEEE80211_ROC_TYPE_NORMAL);
 	mutex_unlock(&local->mtx);
 
 	return ret;
@@ -2582,7 +2641,7 @@ static int ieee80211_cancel_roc(struct ieee80211_local *local,
 			list_del(&dep->list);
 			mutex_unlock(&local->mtx);
 
-			ieee80211_roc_notify_destroy(dep);
+			ieee80211_roc_notify_destroy(dep, true);
 			return 0;
 		}
 
@@ -2622,7 +2681,7 @@ static int ieee80211_cancel_roc(struct ieee80211_local *local,
 			ieee80211_start_next_roc(local);
 		mutex_unlock(&local->mtx);
 
-		ieee80211_roc_notify_destroy(found);
+		ieee80211_roc_notify_destroy(found, true);
 	} else {
 		/* work may be pending so use it all the time */
 		found->abort = true;
@@ -2632,6 +2691,8 @@ static int ieee80211_cancel_roc(struct ieee80211_local *local,
 
 		/* work will clean up etc */
 		flush_delayed_work(&found->work);
+		WARN_ON(!found->to_be_freed);
+		kfree(found);
 	}
 
 	return 0;
@@ -2790,7 +2851,8 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
 
 	/* This will handle all kinds of coalescing and immediate TX */
 	ret = ieee80211_start_roc_work(local, sdata, chan,
-				       wait, cookie, skb);
+				       wait, cookie, skb,
+				       IEEE80211_ROC_TYPE_MGMT_TX);
 	if (ret)
 		kfree_skb(skb);
  out_unlock:
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
index 78c0d90..931be41 100644
--- a/net/mac80211/chan.c
+++ b/net/mac80211/chan.c
@@ -63,6 +63,7 @@ ieee80211_new_chanctx(struct ieee80211_local *local,
 		      enum ieee80211_chanctx_mode mode)
 {
 	struct ieee80211_chanctx *ctx;
+	u32 changed;
 	int err;
 
 	lockdep_assert_held(&local->chanctx_mtx);
@@ -76,6 +77,13 @@ ieee80211_new_chanctx(struct ieee80211_local *local,
 	ctx->conf.rx_chains_dynamic = 1;
 	ctx->mode = mode;
 
+	/* acquire mutex to prevent idle from changing */
+	mutex_lock(&local->mtx);
+	/* turn idle off *before* setting channel -- some drivers need that */
+	changed = ieee80211_idle_off(local);
+	if (changed)
+		ieee80211_hw_config(local, changed);
+
 	if (!local->use_chanctx) {
 		local->_oper_channel_type =
 			cfg80211_get_chandef_type(chandef);
@@ -85,14 +93,17 @@ ieee80211_new_chanctx(struct ieee80211_local *local,
 		err = drv_add_chanctx(local, ctx);
 		if (err) {
 			kfree(ctx);
-			return ERR_PTR(err);
+			ctx = ERR_PTR(err);
+
+			ieee80211_recalc_idle(local);
+			goto out;
 		}
 	}
 
+	/* and keep the mutex held until the new chanctx is on the list */
 	list_add_rcu(&ctx->list, &local->chanctx_list);
 
-	mutex_lock(&local->mtx);
-	ieee80211_recalc_idle(local);
+ out:
 	mutex_unlock(&local->mtx);
 
 	return ctx;
diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c
index c3a3082..1521cab 100644
--- a/net/mac80211/debugfs_key.c
+++ b/net/mac80211/debugfs_key.c
@@ -295,7 +295,7 @@ void ieee80211_debugfs_key_update_default(struct ieee80211_sub_if_data *sdata)
 	char buf[50];
 	struct ieee80211_key *key;
 
-	if (!sdata->debugfs.dir)
+	if (!sdata->vif.debugfs_dir)
 		return;
 
 	lockdep_assert_held(&sdata->local->key_mtx);
@@ -311,7 +311,7 @@ void ieee80211_debugfs_key_update_default(struct ieee80211_sub_if_data *sdata)
 		sprintf(buf, "../keys/%d", key->debugfs.cnt);
 		sdata->debugfs.default_unicast_key =
 			debugfs_create_symlink("default_unicast_key",
-					       sdata->debugfs.dir, buf);
+					       sdata->vif.debugfs_dir, buf);
 	}
 
 	if (sdata->debugfs.default_multicast_key) {
@@ -325,7 +325,7 @@ void ieee80211_debugfs_key_update_default(struct ieee80211_sub_if_data *sdata)
 		sprintf(buf, "../keys/%d", key->debugfs.cnt);
 		sdata->debugfs.default_multicast_key =
 			debugfs_create_symlink("default_multicast_key",
-					       sdata->debugfs.dir, buf);
+					       sdata->vif.debugfs_dir, buf);
 	}
 }
 
@@ -334,7 +334,7 @@ void ieee80211_debugfs_key_add_mgmt_default(struct ieee80211_sub_if_data *sdata)
 	char buf[50];
 	struct ieee80211_key *key;
 
-	if (!sdata->debugfs.dir)
+	if (!sdata->vif.debugfs_dir)
 		return;
 
 	key = key_mtx_dereference(sdata->local,
@@ -343,7 +343,7 @@ void ieee80211_debugfs_key_add_mgmt_default(struct ieee80211_sub_if_data *sdata)
 		sprintf(buf, "../keys/%d", key->debugfs.cnt);
 		sdata->debugfs.default_mgmt_key =
 			debugfs_create_symlink("default_mgmt_key",
-					       sdata->debugfs.dir, buf);
+					       sdata->vif.debugfs_dir, buf);
 	} else
 		ieee80211_debugfs_key_remove_mgmt_default(sdata);
 }
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index 059bbb8..ddb4268 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -521,7 +521,7 @@ IEEE80211_IF_FILE(dot11MeshAwakeWindowDuration,
 #endif
 
 #define DEBUGFS_ADD_MODE(name, mode) \
-	debugfs_create_file(#name, mode, sdata->debugfs.dir, \
+	debugfs_create_file(#name, mode, sdata->vif.debugfs_dir, \
 			    sdata, &name##_ops);
 
 #define DEBUGFS_ADD(name) DEBUGFS_ADD_MODE(name, 0400)
@@ -577,7 +577,7 @@ static void add_mesh_files(struct ieee80211_sub_if_data *sdata)
 static void add_mesh_stats(struct ieee80211_sub_if_data *sdata)
 {
 	struct dentry *dir = debugfs_create_dir("mesh_stats",
-						sdata->debugfs.dir);
+						sdata->vif.debugfs_dir);
 #define MESHSTATS_ADD(name)\
 	debugfs_create_file(#name, 0400, dir, sdata, &name##_ops);
 
@@ -594,7 +594,7 @@ static void add_mesh_stats(struct ieee80211_sub_if_data *sdata)
 static void add_mesh_config(struct ieee80211_sub_if_data *sdata)
 {
 	struct dentry *dir = debugfs_create_dir("mesh_config",
-						sdata->debugfs.dir);
+						sdata->vif.debugfs_dir);
 
 #define MESHPARAMS_ADD(name) \
 	debugfs_create_file(#name, 0600, dir, sdata, &name##_ops);
@@ -631,7 +631,7 @@ static void add_mesh_config(struct ieee80211_sub_if_data *sdata)
 
 static void add_files(struct ieee80211_sub_if_data *sdata)
 {
-	if (!sdata->debugfs.dir)
+	if (!sdata->vif.debugfs_dir)
 		return;
 
 	DEBUGFS_ADD(flags);
@@ -673,21 +673,21 @@ void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata)
 	char buf[10+IFNAMSIZ];
 
 	sprintf(buf, "netdev:%s", sdata->name);
-	sdata->debugfs.dir = debugfs_create_dir(buf,
+	sdata->vif.debugfs_dir = debugfs_create_dir(buf,
 		sdata->local->hw.wiphy->debugfsdir);
-	if (sdata->debugfs.dir)
+	if (sdata->vif.debugfs_dir)
 		sdata->debugfs.subdir_stations = debugfs_create_dir("stations",
-			sdata->debugfs.dir);
+			sdata->vif.debugfs_dir);
 	add_files(sdata);
 }
 
 void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata)
 {
-	if (!sdata->debugfs.dir)
+	if (!sdata->vif.debugfs_dir)
 		return;
 
-	debugfs_remove_recursive(sdata->debugfs.dir);
-	sdata->debugfs.dir = NULL;
+	debugfs_remove_recursive(sdata->vif.debugfs_dir);
+	sdata->vif.debugfs_dir = NULL;
 }
 
 void ieee80211_debugfs_rename_netdev(struct ieee80211_sub_if_data *sdata)
@@ -695,7 +695,7 @@ void ieee80211_debugfs_rename_netdev(struct ieee80211_sub_if_data *sdata)
 	struct dentry *dir;
 	char buf[10 + IFNAMSIZ];
 
-	dir = sdata->debugfs.dir;
+	dir = sdata->vif.debugfs_dir;
 
 	if (!dir)
 		return;
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c
index c7591f7..4f841fe 100644
--- a/net/mac80211/debugfs_sta.c
+++ b/net/mac80211/debugfs_sta.c
@@ -325,6 +325,36 @@ static ssize_t sta_ht_capa_read(struct file *file, char __user *userbuf,
 }
 STA_OPS(ht_capa);
 
+static ssize_t sta_vht_capa_read(struct file *file, char __user *userbuf,
+				 size_t count, loff_t *ppos)
+{
+	char buf[128], *p = buf;
+	struct sta_info *sta = file->private_data;
+	struct ieee80211_sta_vht_cap *vhtc = &sta->sta.vht_cap;
+
+	p += scnprintf(p, sizeof(buf) + buf - p, "VHT %ssupported\n",
+			vhtc->vht_supported ? "" : "not ");
+	if (vhtc->vht_supported) {
+		p += scnprintf(p, sizeof(buf)+buf-p, "cap: %#.8x\n", vhtc->cap);
+
+		p += scnprintf(p, sizeof(buf)+buf-p, "RX MCS: %.4x\n",
+			       le16_to_cpu(vhtc->vht_mcs.rx_mcs_map));
+		if (vhtc->vht_mcs.rx_highest)
+			p += scnprintf(p, sizeof(buf)+buf-p,
+				       "MCS RX highest: %d Mbps\n",
+				       le16_to_cpu(vhtc->vht_mcs.rx_highest));
+		p += scnprintf(p, sizeof(buf)+buf-p, "TX MCS: %.4x\n",
+			       le16_to_cpu(vhtc->vht_mcs.tx_mcs_map));
+		if (vhtc->vht_mcs.tx_highest)
+			p += scnprintf(p, sizeof(buf)+buf-p,
+				       "MCS TX highest: %d Mbps\n",
+				       le16_to_cpu(vhtc->vht_mcs.tx_highest));
+	}
+
+	return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
+}
+STA_OPS(vht_capa);
+
 static ssize_t sta_current_tx_rate_read(struct file *file, char __user *userbuf,
 					size_t count, loff_t *ppos)
 {
@@ -405,6 +435,7 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta)
 	DEBUGFS_ADD(dev);
 	DEBUGFS_ADD(last_signal);
 	DEBUGFS_ADD(ht_capa);
+	DEBUGFS_ADD(vht_capa);
 	DEBUGFS_ADD(last_ack_signal);
 	DEBUGFS_ADD(current_tx_rate);
 	DEBUGFS_ADD(last_rx_rate);
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index ee56d07..169664c 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -241,6 +241,22 @@ static inline u64 drv_prepare_multicast(struct ieee80211_local *local,
 	return ret;
 }
 
+static inline void drv_set_multicast_list(struct ieee80211_local *local,
+					  struct ieee80211_sub_if_data *sdata,
+					  struct netdev_hw_addr_list *mc_list)
+{
+	bool allmulti = sdata->flags & IEEE80211_SDATA_ALLMULTI;
+
+	trace_drv_set_multicast_list(local, sdata, mc_list->count);
+
+	check_sdata_in_driver(sdata);
+
+	if (local->ops->set_multicast_list)
+		local->ops->set_multicast_list(&local->hw, &sdata->vif,
+					       allmulti, mc_list);
+	trace_drv_return_void(local);
+}
+
 static inline void drv_configure_filter(struct ieee80211_local *local,
 					unsigned int changed_flags,
 					unsigned int *total_flags,
@@ -531,43 +547,6 @@ static inline void drv_sta_remove_debugfs(struct ieee80211_local *local,
 		local->ops->sta_remove_debugfs(&local->hw, &sdata->vif,
 					       sta, dir);
 }
-
-static inline
-void drv_add_interface_debugfs(struct ieee80211_local *local,
-			       struct ieee80211_sub_if_data *sdata)
-{
-	might_sleep();
-
-	check_sdata_in_driver(sdata);
-
-	if (!local->ops->add_interface_debugfs)
-		return;
-
-	local->ops->add_interface_debugfs(&local->hw, &sdata->vif,
-					  sdata->debugfs.dir);
-}
-
-static inline
-void drv_remove_interface_debugfs(struct ieee80211_local *local,
-				  struct ieee80211_sub_if_data *sdata)
-{
-	might_sleep();
-
-	check_sdata_in_driver(sdata);
-
-	if (!local->ops->remove_interface_debugfs)
-		return;
-
-	local->ops->remove_interface_debugfs(&local->hw, &sdata->vif,
-					     sdata->debugfs.dir);
-}
-#else
-static inline
-void drv_add_interface_debugfs(struct ieee80211_local *local,
-			       struct ieee80211_sub_if_data *sdata) {}
-static inline
-void drv_remove_interface_debugfs(struct ieee80211_local *local,
-				  struct ieee80211_sub_if_data *sdata) {}
 #endif
 
 static inline __must_check
@@ -741,13 +720,14 @@ static inline void drv_rfkill_poll(struct ieee80211_local *local)
 		local->ops->rfkill_poll(&local->hw);
 }
 
-static inline void drv_flush(struct ieee80211_local *local, bool drop)
+static inline void drv_flush(struct ieee80211_local *local,
+			     u32 queues, bool drop)
 {
 	might_sleep();
 
-	trace_drv_flush(local, drop);
+	trace_drv_flush(local, queues, drop);
 	if (local->ops->flush)
-		local->ops->flush(&local->hw, drop);
+		local->ops->flush(&local->hw, queues, drop);
 	trace_drv_return_void(local);
 }
 
@@ -787,15 +767,16 @@ static inline int drv_get_antenna(struct ieee80211_local *local,
 static inline int drv_remain_on_channel(struct ieee80211_local *local,
 					struct ieee80211_sub_if_data *sdata,
 					struct ieee80211_channel *chan,
-					unsigned int duration)
+					unsigned int duration,
+					enum ieee80211_roc_type type)
 {
 	int ret;
 
 	might_sleep();
 
-	trace_drv_remain_on_channel(local, sdata, chan, duration);
+	trace_drv_remain_on_channel(local, sdata, chan, duration, type);
 	ret = local->ops->remain_on_channel(&local->hw, &sdata->vif,
-					    chan, duration);
+					    chan, duration, type);
 	trace_drv_return_int(local, ret);
 
 	return ret;
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c
index 0db25d4..af8cee0 100644
--- a/net/mac80211/ht.c
+++ b/net/mac80211/ht.c
@@ -40,13 +40,6 @@ void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata,
 	if (!ht_cap->ht_supported)
 		return;
 
-	if (sdata->vif.type != NL80211_IFTYPE_STATION) {
-		/* AP interfaces call this code when adding new stations,
-		 * so just silently ignore non station interfaces.
-		 */
-		return;
-	}
-
 	/* NOTE:  If you add more over-rides here, update register_hw
 	 * ht_capa_mod_msk logic in main.c as well.
 	 * And, if this method can ever change ht_cap.ht_supported, fix
@@ -97,7 +90,7 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata,
 				       const struct ieee80211_ht_cap *ht_cap_ie,
 				       struct sta_info *sta)
 {
-	struct ieee80211_sta_ht_cap ht_cap;
+	struct ieee80211_sta_ht_cap ht_cap, own_cap;
 	u8 ampdu_info, tx_mcs_set_cap;
 	int i, max_tx_streams;
 	bool changed;
@@ -111,6 +104,18 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata,
 
 	ht_cap.ht_supported = true;
 
+	own_cap = sband->ht_cap;
+
+	/*
+	 * If user has specified capability over-rides, take care
+	 * of that if the station we're setting up is the AP that
+	 * we advertised a restricted capability set to. Override
+	 * our own capabilities and then use those below.
+	 */
+	if (sdata->vif.type == NL80211_IFTYPE_STATION &&
+	    !test_sta_flag(sta, WLAN_STA_TDLS_PEER))
+		ieee80211_apply_htcap_overrides(sdata, &own_cap);
+
 	/*
 	 * The bits listed in this expression should be
 	 * the same for the peer and us, if the station
@@ -118,21 +123,20 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata,
 	 * we mask them out.
 	 */
 	ht_cap.cap = le16_to_cpu(ht_cap_ie->cap_info) &
-		(sband->ht_cap.cap |
-		 ~(IEEE80211_HT_CAP_LDPC_CODING |
-		   IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
-		   IEEE80211_HT_CAP_GRN_FLD |
-		   IEEE80211_HT_CAP_SGI_20 |
-		   IEEE80211_HT_CAP_SGI_40 |
-		   IEEE80211_HT_CAP_DSSSCCK40));
+		(own_cap.cap | ~(IEEE80211_HT_CAP_LDPC_CODING |
+				 IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
+				 IEEE80211_HT_CAP_GRN_FLD |
+				 IEEE80211_HT_CAP_SGI_20 |
+				 IEEE80211_HT_CAP_SGI_40 |
+				 IEEE80211_HT_CAP_DSSSCCK40));
 
 	/*
 	 * The STBC bits are asymmetric -- if we don't have
 	 * TX then mask out the peer's RX and vice versa.
 	 */
-	if (!(sband->ht_cap.cap & IEEE80211_HT_CAP_TX_STBC))
+	if (!(own_cap.cap & IEEE80211_HT_CAP_TX_STBC))
 		ht_cap.cap &= ~IEEE80211_HT_CAP_RX_STBC;
-	if (!(sband->ht_cap.cap & IEEE80211_HT_CAP_RX_STBC))
+	if (!(own_cap.cap & IEEE80211_HT_CAP_RX_STBC))
 		ht_cap.cap &= ~IEEE80211_HT_CAP_TX_STBC;
 
 	ampdu_info = ht_cap_ie->ampdu_params_info;
@@ -142,7 +146,7 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata,
 		(ampdu_info & IEEE80211_HT_AMPDU_PARM_DENSITY) >> 2;
 
 	/* own MCS TX capabilities */
-	tx_mcs_set_cap = sband->ht_cap.mcs.tx_params;
+	tx_mcs_set_cap = own_cap.mcs.tx_params;
 
 	/* Copy peer MCS TX capabilities, the driver might need them. */
 	ht_cap.mcs.tx_params = ht_cap_ie->mcs.tx_params;
@@ -168,26 +172,20 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata,
 	 */
 	for (i = 0; i < max_tx_streams; i++)
 		ht_cap.mcs.rx_mask[i] =
-			sband->ht_cap.mcs.rx_mask[i] & ht_cap_ie->mcs.rx_mask[i];
+			own_cap.mcs.rx_mask[i] & ht_cap_ie->mcs.rx_mask[i];
 
 	if (tx_mcs_set_cap & IEEE80211_HT_MCS_TX_UNEQUAL_MODULATION)
 		for (i = IEEE80211_HT_MCS_UNEQUAL_MODULATION_START_BYTE;
 		     i < IEEE80211_HT_MCS_MASK_LEN; i++)
 			ht_cap.mcs.rx_mask[i] =
-				sband->ht_cap.mcs.rx_mask[i] &
+				own_cap.mcs.rx_mask[i] &
 					ht_cap_ie->mcs.rx_mask[i];
 
 	/* handle MCS rate 32 too */
-	if (sband->ht_cap.mcs.rx_mask[32/8] & ht_cap_ie->mcs.rx_mask[32/8] & 1)
+	if (own_cap.mcs.rx_mask[32/8] & ht_cap_ie->mcs.rx_mask[32/8] & 1)
 		ht_cap.mcs.rx_mask[32/8] |= 1;
 
  apply:
-	/*
-	 * If user has specified capability over-rides, take care
-	 * of that here.
-	 */
-	ieee80211_apply_htcap_overrides(sdata, &ht_cap);
-
 	changed = memcmp(&sta->sta.ht_cap, &ht_cap, sizeof(ht_cap));
 
 	memcpy(&sta->sta.ht_cap, &ht_cap, sizeof(ht_cap));
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 40b71df..539d4a1 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -985,36 +985,9 @@ static void ieee80211_ibss_timer(unsigned long data)
 {
 	struct ieee80211_sub_if_data *sdata =
 		(struct ieee80211_sub_if_data *) data;
-	struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
-	struct ieee80211_local *local = sdata->local;
-
-	if (local->quiescing) {
-		ifibss->timer_running = true;
-		return;
-	}
-
-	ieee80211_queue_work(&local->hw, &sdata->work);
-}
-
-#ifdef CONFIG_PM
-void ieee80211_ibss_quiesce(struct ieee80211_sub_if_data *sdata)
-{
-	struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
 
-	if (del_timer_sync(&ifibss->timer))
-		ifibss->timer_running = true;
-}
-
-void ieee80211_ibss_restart(struct ieee80211_sub_if_data *sdata)
-{
-	struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
-
-	if (ifibss->timer_running) {
-		add_timer(&ifibss->timer);
-		ifibss->timer_running = false;
-	}
+	ieee80211_queue_work(&sdata->local->hw, &sdata->work);
 }
-#endif
 
 void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata)
 {
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 388580a..0b09716 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -309,12 +309,14 @@ struct ieee80211_roc_work {
 	struct ieee80211_channel *chan;
 
 	bool started, abort, hw_begun, notified;
+	bool to_be_freed;
 
 	unsigned long hw_start_time;
 
 	u32 duration, req_duration;
 	struct sk_buff *frame;
 	u64 cookie, mgmt_tx_cookie;
+	enum ieee80211_roc_type type;
 };
 
 /* flags used in struct ieee80211_if_managed.flags */
@@ -400,7 +402,6 @@ struct ieee80211_if_managed {
 
 	u16 aid;
 
-	unsigned long timers_running; /* used for quiesce/restart */
 	bool powersave; /* powersave requested for this iface */
 	bool broken_ap; /* AP is broken -- turn off powersave */
 	u8 dtim_period;
@@ -479,6 +480,8 @@ struct ieee80211_if_managed {
 
 	struct ieee80211_ht_cap ht_capa; /* configured ht-cap over-rides */
 	struct ieee80211_ht_cap ht_capa_mask; /* Valid parts of ht_capa */
+	struct ieee80211_vht_cap vht_capa; /* configured VHT overrides */
+	struct ieee80211_vht_cap vht_capa_mask; /* Valid parts of vht_capa */
 };
 
 struct ieee80211_if_ibss {
@@ -490,8 +493,6 @@ struct ieee80211_if_ibss {
 
 	u32 basic_rates;
 
-	bool timer_running;
-
 	bool fixed_bssid;
 	bool fixed_channel;
 	bool privacy;
@@ -543,8 +544,6 @@ struct ieee80211_if_mesh {
 	struct timer_list mesh_path_timer;
 	struct timer_list mesh_path_root_timer;
 
-	unsigned long timers_running;
-
 	unsigned long wrkq_flags;
 
 	u8 mesh_id[IEEE80211_MAX_MESH_ID_LEN];
@@ -590,6 +589,7 @@ struct ieee80211_if_mesh {
 		IEEE80211_MESH_SEC_AUTHED = 0x1,
 		IEEE80211_MESH_SEC_SECURED = 0x2,
 	} security;
+	bool user_mpm;
 	/* Extensible Synchronization Framework */
 	const struct ieee80211_mesh_sync_ops *sync_ops;
 	s64 sync_offset_clockdrift_max;
@@ -682,6 +682,8 @@ struct ieee80211_sub_if_data {
 
 	/* count for keys needing tailroom space allocation */
 	int crypto_tx_tailroom_needed_cnt;
+	int crypto_tx_tailroom_pending_dec;
+	struct delayed_work dec_tailroom_needed_wk;
 
 	struct net_device *dev;
 	struct ieee80211_local *local;
@@ -757,7 +759,6 @@ struct ieee80211_sub_if_data {
 
 #ifdef CONFIG_MAC80211_DEBUGFS
 	struct {
-		struct dentry *dir;
 		struct dentry *subdir_stations;
 		struct dentry *default_unicast_key;
 		struct dentry *default_multicast_key;
@@ -765,10 +766,6 @@ struct ieee80211_sub_if_data {
 	} debugfs;
 #endif
 
-#ifdef CONFIG_PM
-	struct ieee80211_bss_conf suspend_bss_conf;
-#endif
-
 	/* must be last, dynamically sized area in this! */
 	struct ieee80211_vif vif;
 };
@@ -803,11 +800,6 @@ enum sdata_queue_type {
 enum {
 	IEEE80211_RX_MSG	= 1,
 	IEEE80211_TX_STATUS_MSG	= 2,
-	IEEE80211_EOSP_MSG	= 3,
-};
-
-struct skb_eosp_msg_data {
-	u8 sta[ETH_ALEN], iface[ETH_ALEN];
 };
 
 enum queue_stop_reason {
@@ -818,6 +810,7 @@ enum queue_stop_reason {
 	IEEE80211_QUEUE_STOP_REASON_SUSPEND,
 	IEEE80211_QUEUE_STOP_REASON_SKB_ADD,
 	IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL,
+	IEEE80211_QUEUE_STOP_REASON_FLUSH,
 };
 
 #ifdef CONFIG_MAC80211_LEDS
@@ -1136,11 +1129,6 @@ struct ieee80211_local {
 
 	struct ieee80211_sub_if_data __rcu *p2p_sdata;
 
-	/* dummy netdev for use w/ NAPI */
-	struct net_device napi_dev;
-
-	struct napi_struct napi;
-
 	/* virtual monitor interface */
 	struct ieee80211_sub_if_data __rcu *monitor_sdata;
 	struct cfg80211_chan_def monitor_chandef;
@@ -1283,8 +1271,6 @@ void
 ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
 				 const struct ieee80211_channel_sw_ie *sw_elem,
 				 struct ieee80211_bss *bss, u64 timestamp);
-void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata);
-void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata);
 void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata);
 void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
 				  struct sk_buff *skb);
@@ -1302,8 +1288,6 @@ void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata,
 int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
 			struct cfg80211_ibss_params *params);
 int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata);
-void ieee80211_ibss_quiesce(struct ieee80211_sub_if_data *sdata);
-void ieee80211_ibss_restart(struct ieee80211_sub_if_data *sdata);
 void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata);
 void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
 				   struct sk_buff *skb);
@@ -1347,7 +1331,7 @@ void ieee80211_offchannel_return(struct ieee80211_local *local);
 void ieee80211_roc_setup(struct ieee80211_local *local);
 void ieee80211_start_next_roc(struct ieee80211_local *local);
 void ieee80211_roc_purge(struct ieee80211_sub_if_data *sdata);
-void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc);
+void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc, bool free);
 void ieee80211_sw_roc_work(struct work_struct *work);
 void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc);
 
@@ -1361,6 +1345,7 @@ int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata,
 			     enum nl80211_iftype type);
 void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata);
 void ieee80211_remove_interfaces(struct ieee80211_local *local);
+u32 ieee80211_idle_off(struct ieee80211_local *local);
 void ieee80211_recalc_idle(struct ieee80211_local *local);
 void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata,
 				    const int offset);
@@ -1441,6 +1426,8 @@ void ieee80211_sta_set_rx_nss(struct sta_info *sta);
 void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
 				 struct sta_info *sta, u8 opmode,
 				 enum ieee80211_band band, bool nss_only);
+void ieee80211_apply_vhtcap_overrides(struct ieee80211_sub_if_data *sdata,
+				      struct ieee80211_sta_vht_cap *vht_cap);
 
 /* Spectrum management */
 void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata,
@@ -1538,8 +1525,10 @@ void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata,
 			     struct ieee80211_hdr *hdr, bool ack);
 
 void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw,
+				     unsigned long queues,
 				     enum queue_stop_reason reason);
 void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw,
+				     unsigned long queues,
 				     enum queue_stop_reason reason);
 void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue,
 				    enum queue_stop_reason reason);
@@ -1556,6 +1545,8 @@ static inline void ieee80211_add_pending_skbs(struct ieee80211_local *local,
 {
 	ieee80211_add_pending_skbs_fn(local, skbs, NULL, NULL);
 }
+void ieee80211_flush_queues(struct ieee80211_local *local,
+			    struct ieee80211_sub_if_data *sdata);
 
 void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
 			 u16 transaction, u16 auth_alg, u16 status,
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index baaa860..69aaba7 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -78,7 +78,7 @@ void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata)
 		ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_TXPOWER);
 }
 
-static u32 ieee80211_idle_off(struct ieee80211_local *local)
+u32 ieee80211_idle_off(struct ieee80211_local *local)
 {
 	if (!(local->hw.conf.flags & IEEE80211_CONF_IDLE))
 		return 0;
@@ -92,7 +92,7 @@ static u32 ieee80211_idle_on(struct ieee80211_local *local)
 	if (local->hw.conf.flags & IEEE80211_CONF_IDLE)
 		return 0;
 
-	drv_flush(local, false);
+	ieee80211_flush_queues(local, NULL);
 
 	local->hw.conf.flags |= IEEE80211_CONF_IDLE;
 	return IEEE80211_CONF_CHANGE_IDLE;
@@ -349,21 +349,19 @@ static void ieee80211_set_default_queues(struct ieee80211_sub_if_data *sdata)
 static int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
 {
 	struct ieee80211_sub_if_data *sdata;
-	int ret = 0;
+	int ret;
 
 	if (!(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF))
 		return 0;
 
-	mutex_lock(&local->iflist_mtx);
+	ASSERT_RTNL();
 
 	if (local->monitor_sdata)
-		goto out_unlock;
+		return 0;
 
 	sdata = kzalloc(sizeof(*sdata) + local->hw.vif_data_size, GFP_KERNEL);
-	if (!sdata) {
-		ret = -ENOMEM;
-		goto out_unlock;
-	}
+	if (!sdata)
+		return -ENOMEM;
 
 	/* set up data */
 	sdata->local = local;
@@ -377,13 +375,13 @@ static int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
 	if (WARN_ON(ret)) {
 		/* ok .. stupid driver, it asked for this! */
 		kfree(sdata);
-		goto out_unlock;
+		return ret;
 	}
 
 	ret = ieee80211_check_queues(sdata);
 	if (ret) {
 		kfree(sdata);
-		goto out_unlock;
+		return ret;
 	}
 
 	ret = ieee80211_vif_use_channel(sdata, &local->monitor_chandef,
@@ -391,13 +389,14 @@ static int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
 	if (ret) {
 		drv_remove_interface(local, sdata);
 		kfree(sdata);
-		goto out_unlock;
+		return ret;
 	}
 
+	mutex_lock(&local->iflist_mtx);
 	rcu_assign_pointer(local->monitor_sdata, sdata);
- out_unlock:
 	mutex_unlock(&local->iflist_mtx);
-	return ret;
+
+	return 0;
 }
 
 static void ieee80211_del_virtual_monitor(struct ieee80211_local *local)
@@ -407,14 +406,20 @@ static void ieee80211_del_virtual_monitor(struct ieee80211_local *local)
 	if (!(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF))
 		return;
 
+	ASSERT_RTNL();
+
 	mutex_lock(&local->iflist_mtx);
 
 	sdata = rcu_dereference_protected(local->monitor_sdata,
 					  lockdep_is_held(&local->iflist_mtx));
-	if (!sdata)
-		goto out_unlock;
+	if (!sdata) {
+		mutex_unlock(&local->iflist_mtx);
+		return;
+	}
 
 	rcu_assign_pointer(local->monitor_sdata, NULL);
+	mutex_unlock(&local->iflist_mtx);
+
 	synchronize_net();
 
 	ieee80211_vif_release_channel(sdata);
@@ -422,8 +427,6 @@ static void ieee80211_del_virtual_monitor(struct ieee80211_local *local)
 	drv_remove_interface(local, sdata);
 
 	kfree(sdata);
- out_unlock:
-	mutex_unlock(&local->iflist_mtx);
 }
 
 /*
@@ -485,8 +488,6 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
 		res = drv_start(local);
 		if (res)
 			goto err_del_bss;
-		if (local->ops->napi_poll)
-			napi_enable(&local->napi);
 		/* we're brought up, everything changes */
 		hw_reconf_flags = ~0;
 		ieee80211_led_radio(local, true);
@@ -559,8 +560,6 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
 				goto err_del_interface;
 		}
 
-		drv_add_interface_debugfs(local, sdata);
-
 		if (sdata->vif.type == NL80211_IFTYPE_AP) {
 			local->fif_pspoll++;
 			local->fif_probe_req++;
@@ -838,15 +837,15 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
 		rcu_barrier();
 		sta_info_flush_cleanup(sdata);
 
-		skb_queue_purge(&sdata->skb_queue);
-
 		/*
 		 * Free all remaining keys, there shouldn't be any,
-		 * except maybe group keys in AP more or WDS?
+		 * except maybe in WDS mode?
 		 */
 		ieee80211_free_keys(sdata);
 
-		drv_remove_interface_debugfs(local, sdata);
+		/* fall through */
+	case NL80211_IFTYPE_AP:
+		skb_queue_purge(&sdata->skb_queue);
 
 		if (going_down)
 			drv_remove_interface(local, sdata);
@@ -857,8 +856,6 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
 	ieee80211_recalc_ps(local, -1);
 
 	if (local->open_count == 0) {
-		if (local->ops->napi_poll)
-			napi_disable(&local->napi);
 		ieee80211_clear_tx_pending(local);
 		ieee80211_stop_device(local);
 
@@ -921,6 +918,17 @@ static void ieee80211_set_multicast_list(struct net_device *dev)
 			atomic_dec(&local->iff_promiscs);
 		sdata->flags ^= IEEE80211_SDATA_PROMISC;
 	}
+
+	/*
+	 * TODO: If somebody needs this on AP interfaces,
+	 *	 it can be enabled easily but multicast
+	 *	 addresses from VLANs need to be synced.
+	 */
+	if (sdata->vif.type != NL80211_IFTYPE_MONITOR &&
+	    sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
+	    sdata->vif.type != NL80211_IFTYPE_AP)
+		drv_set_multicast_list(local, sdata, &dev->mc);
+
 	spin_lock_bh(&local->filter_lock);
 	__hw_addr_sync(&local->mc_list, &dev->mc, dev->addr_len);
 	spin_unlock_bh(&local->filter_lock);
@@ -1547,6 +1555,8 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
 	INIT_WORK(&sdata->cleanup_stations_wk, ieee80211_cleanup_sdata_stas_wk);
 	INIT_DELAYED_WORK(&sdata->dfs_cac_timer_work,
 			  ieee80211_dfs_cac_timer_work);
+	INIT_DELAYED_WORK(&sdata->dec_tailroom_needed_wk,
+			  ieee80211_delayed_tailroom_dec);
 
 	for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
 		struct ieee80211_supported_band *sband;
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index ef252eb..67059b8 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -248,11 +248,11 @@ void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata,
 }
 
 
-static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
-				    struct sta_info *sta,
-				    bool pairwise,
-				    struct ieee80211_key *old,
-				    struct ieee80211_key *new)
+static void ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
+				  struct sta_info *sta,
+				  bool pairwise,
+				  struct ieee80211_key *old,
+				  struct ieee80211_key *new)
 {
 	int idx;
 	bool defunikey, defmultikey, defmgmtkey;
@@ -397,7 +397,41 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
 	return key;
 }
 
-static void __ieee80211_key_destroy(struct ieee80211_key *key)
+static void ieee80211_key_free_common(struct ieee80211_key *key)
+{
+	if (key->conf.cipher == WLAN_CIPHER_SUITE_CCMP)
+		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);
+	kfree(key);
+}
+
+static void __ieee80211_key_destroy(struct ieee80211_key *key,
+				    bool delay_tailroom)
+{
+	if (key->local)
+		ieee80211_key_disable_hw_accel(key);
+
+	if (key->local) {
+		struct ieee80211_sub_if_data *sdata = key->sdata;
+
+		ieee80211_debugfs_key_remove(key);
+
+		if (delay_tailroom) {
+			/* see ieee80211_delayed_tailroom_dec */
+			sdata->crypto_tx_tailroom_pending_dec++;
+			schedule_delayed_work(&sdata->dec_tailroom_needed_wk,
+					      HZ/2);
+		} else {
+			sdata->crypto_tx_tailroom_needed_cnt--;
+		}
+	}
+
+	ieee80211_key_free_common(key);
+}
+
+static void ieee80211_key_destroy(struct ieee80211_key *key,
+				  bool delay_tailroom)
 {
 	if (!key)
 		return;
@@ -408,19 +442,13 @@ static void __ieee80211_key_destroy(struct ieee80211_key *key)
 	 */
 	synchronize_net();
 
-	if (key->local)
-		ieee80211_key_disable_hw_accel(key);
-
-	if (key->conf.cipher == WLAN_CIPHER_SUITE_CCMP)
-		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) {
-		ieee80211_debugfs_key_remove(key);
-		key->sdata->crypto_tx_tailroom_needed_cnt--;
-	}
+	__ieee80211_key_destroy(key, delay_tailroom);
+}
 
-	kfree(key);
+void ieee80211_key_free_unused(struct ieee80211_key *key)
+{
+	WARN_ON(key->sdata || key->local);
+	ieee80211_key_free_common(key);
 }
 
 int ieee80211_key_link(struct ieee80211_key *key,
@@ -440,32 +468,6 @@ int ieee80211_key_link(struct ieee80211_key *key,
 	key->sdata = sdata;
 	key->sta = sta;
 
-	if (sta) {
-		/*
-		 * some hardware cannot handle TKIP with QoS, so
-		 * we indicate whether QoS could be in use.
-		 */
-		if (test_sta_flag(sta, WLAN_STA_WME))
-			key->conf.flags |= IEEE80211_KEY_FLAG_WMM_STA;
-	} else {
-		if (sdata->vif.type == NL80211_IFTYPE_STATION) {
-			struct sta_info *ap;
-
-			/*
-			 * We're getting a sta pointer in, so must be under
-			 * appropriate locking for sta_info_get().
-			 */
-
-			/* same here, the AP could be using QoS */
-			ap = sta_info_get(key->sdata, key->sdata->u.mgd.bssid);
-			if (ap) {
-				if (test_sta_flag(ap, WLAN_STA_WME))
-					key->conf.flags |=
-						IEEE80211_KEY_FLAG_WMM_STA;
-			}
-		}
-	}
-
 	mutex_lock(&sdata->local->key_mtx);
 
 	if (sta && pairwise)
@@ -477,19 +479,22 @@ int ieee80211_key_link(struct ieee80211_key *key,
 
 	increment_tailroom_need_count(sdata);
 
-	__ieee80211_key_replace(sdata, sta, pairwise, old_key, key);
-	__ieee80211_key_destroy(old_key);
+	ieee80211_key_replace(sdata, sta, pairwise, old_key, key);
+	ieee80211_key_destroy(old_key, true);
 
 	ieee80211_debugfs_key_add(key);
 
 	ret = ieee80211_key_enable_hw_accel(key);
 
+	if (ret)
+		ieee80211_key_free(key, true);
+
 	mutex_unlock(&sdata->local->key_mtx);
 
 	return ret;
 }
 
-void __ieee80211_key_free(struct ieee80211_key *key)
+void ieee80211_key_free(struct ieee80211_key *key, bool delay_tailroom)
 {
 	if (!key)
 		return;
@@ -498,18 +503,10 @@ void __ieee80211_key_free(struct ieee80211_key *key)
 	 * Replace key with nothingness if it was ever used.
 	 */
 	if (key->sdata)
-		__ieee80211_key_replace(key->sdata, key->sta,
+		ieee80211_key_replace(key->sdata, key->sta,
 				key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE,
 				key, NULL);
-	__ieee80211_key_destroy(key);
-}
-
-void ieee80211_key_free(struct ieee80211_local *local,
-			struct ieee80211_key *key)
-{
-	mutex_lock(&local->key_mtx);
-	__ieee80211_key_free(key);
-	mutex_unlock(&local->key_mtx);
+	ieee80211_key_destroy(key, delay_tailroom);
 }
 
 void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata)
@@ -566,36 +563,109 @@ void ieee80211_iter_keys(struct ieee80211_hw *hw,
 }
 EXPORT_SYMBOL(ieee80211_iter_keys);
 
-void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata)
+void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata)
 {
-	struct ieee80211_key *key;
+	struct ieee80211_key *key, *tmp;
+	LIST_HEAD(keys);
 
-	ASSERT_RTNL();
+	cancel_delayed_work_sync(&sdata->dec_tailroom_needed_wk);
 
 	mutex_lock(&sdata->local->key_mtx);
 
-	list_for_each_entry(key, &sdata->key_list, list)
-		ieee80211_key_disable_hw_accel(key);
+	sdata->crypto_tx_tailroom_needed_cnt -=
+		sdata->crypto_tx_tailroom_pending_dec;
+	sdata->crypto_tx_tailroom_pending_dec = 0;
+
+	ieee80211_debugfs_key_remove_mgmt_default(sdata);
+
+	list_for_each_entry_safe(key, tmp, &sdata->key_list, list) {
+		ieee80211_key_replace(key->sdata, key->sta,
+				key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE,
+				key, NULL);
+		list_add_tail(&key->list, &keys);
+	}
+
+	ieee80211_debugfs_key_update_default(sdata);
+
+	if (!list_empty(&keys)) {
+		synchronize_net();
+		list_for_each_entry_safe(key, tmp, &keys, list)
+			__ieee80211_key_destroy(key, false);
+	}
+
+	WARN_ON_ONCE(sdata->crypto_tx_tailroom_needed_cnt ||
+		     sdata->crypto_tx_tailroom_pending_dec);
 
 	mutex_unlock(&sdata->local->key_mtx);
 }
 
-void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata)
+void ieee80211_free_sta_keys(struct ieee80211_local *local,
+			     struct sta_info *sta)
 {
 	struct ieee80211_key *key, *tmp;
+	LIST_HEAD(keys);
+	int i;
 
-	mutex_lock(&sdata->local->key_mtx);
+	mutex_lock(&local->key_mtx);
+	for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
+		key = key_mtx_dereference(local, sta->gtk[i]);
+		if (!key)
+			continue;
+		ieee80211_key_replace(key->sdata, key->sta,
+				key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE,
+				key, NULL);
+		list_add(&key->list, &keys);
+	}
 
-	ieee80211_debugfs_key_remove_mgmt_default(sdata);
+	key = key_mtx_dereference(local, sta->ptk);
+	if (key) {
+		ieee80211_key_replace(key->sdata, key->sta,
+				key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE,
+				key, NULL);
+		list_add(&key->list, &keys);
+	}
 
-	list_for_each_entry_safe(key, tmp, &sdata->key_list, list)
-		__ieee80211_key_free(key);
+	/*
+	 * NB: the station code relies on this being
+	 * done even if there aren't any keys
+	 */
+	synchronize_net();
 
-	ieee80211_debugfs_key_update_default(sdata);
+	list_for_each_entry_safe(key, tmp, &keys, list)
+		__ieee80211_key_destroy(key, true);
 
-	mutex_unlock(&sdata->local->key_mtx);
+	mutex_unlock(&local->key_mtx);
 }
 
+void ieee80211_delayed_tailroom_dec(struct work_struct *wk)
+{
+	struct ieee80211_sub_if_data *sdata;
+
+	sdata = container_of(wk, struct ieee80211_sub_if_data,
+			     dec_tailroom_needed_wk.work);
+
+	/*
+	 * The reason for the delayed tailroom needed decrementing is to
+	 * make roaming faster: during roaming, all keys are first deleted
+	 * and then new keys are installed. The first new key causes the
+	 * crypto_tx_tailroom_needed_cnt to go from 0 to 1, which invokes
+	 * the cost of synchronize_net() (which can be slow). Avoid this
+	 * by deferring the crypto_tx_tailroom_needed_cnt decrementing on
+	 * key removal for a while, so if we roam the value is larger than
+	 * zero and no 0->1 transition happens.
+	 *
+	 * The cost is that if the AP switching was from an AP with keys
+	 * to one without, we still allocate tailroom while it would no
+	 * longer be needed. However, in the typical (fast) roaming case
+	 * within an ESS this usually won't happen.
+	 */
+
+	mutex_lock(&sdata->local->key_mtx);
+	sdata->crypto_tx_tailroom_needed_cnt -=
+		sdata->crypto_tx_tailroom_pending_dec;
+	sdata->crypto_tx_tailroom_pending_dec = 0;
+	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)
diff --git a/net/mac80211/key.h b/net/mac80211/key.h
index 382dc44..e8de3e6 100644
--- a/net/mac80211/key.h
+++ b/net/mac80211/key.h
@@ -129,23 +129,25 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
 					  size_t seq_len, const u8 *seq);
 /*
  * Insert a key into data structures (sdata, sta if necessary)
- * to make it used, free old key.
+ * to make it used, free old key. On failure, also free the new key.
  */
-int __must_check ieee80211_key_link(struct ieee80211_key *key,
-				    struct ieee80211_sub_if_data *sdata,
-				    struct sta_info *sta);
-void __ieee80211_key_free(struct ieee80211_key *key);
-void ieee80211_key_free(struct ieee80211_local *local,
-			struct ieee80211_key *key);
+int ieee80211_key_link(struct ieee80211_key *key,
+		       struct ieee80211_sub_if_data *sdata,
+		       struct sta_info *sta);
+void ieee80211_key_free(struct ieee80211_key *key, bool delay_tailroom);
+void ieee80211_key_free_unused(struct ieee80211_key *key);
 void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx,
 			       bool uni, bool multi);
 void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata,
 				    int idx);
 void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata);
+void ieee80211_free_sta_keys(struct ieee80211_local *local,
+			     struct sta_info *sta);
 void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata);
-void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata);
 
 #define key_mtx_dereference(local, ref) \
 	rcu_dereference_protected(ref, lockdep_is_held(&((local)->key_mtx)))
 
+void ieee80211_delayed_tailroom_dec(struct work_struct *wk);
+
 #endif /* IEEE80211_KEY_H */
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 1a8591b..c6f81ec 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -100,7 +100,6 @@ static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local)
 	int power;
 	enum nl80211_channel_type channel_type;
 	u32 offchannel_flag;
-	bool scanning = false;
 
 	offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL;
 	if (local->scan_channel) {
@@ -147,9 +146,6 @@ static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local)
 		changed |= IEEE80211_CONF_CHANGE_SMPS;
 	}
 
-	scanning = test_bit(SCAN_SW_SCANNING, &local->scanning) ||
-		   test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning) ||
-		   test_bit(SCAN_HW_SCANNING, &local->scanning);
 	power = chan->max_power;
 
 	rcu_read_lock();
@@ -226,8 +222,6 @@ u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata)
 static void ieee80211_tasklet_handler(unsigned long data)
 {
 	struct ieee80211_local *local = (struct ieee80211_local *) data;
-	struct sta_info *sta, *tmp;
-	struct skb_eosp_msg_data *eosp_data;
 	struct sk_buff *skb;
 
 	while ((skb = skb_dequeue(&local->skb_queue)) ||
@@ -243,18 +237,6 @@ static void ieee80211_tasklet_handler(unsigned long data)
 			skb->pkt_type = 0;
 			ieee80211_tx_status(&local->hw, skb);
 			break;
-		case IEEE80211_EOSP_MSG:
-			eosp_data = (void *)skb->cb;
-			for_each_sta_info(local, eosp_data->sta, sta, tmp) {
-				/* skip wrong virtual interface */
-				if (memcmp(eosp_data->iface,
-					   sta->sdata->vif.addr, ETH_ALEN))
-					continue;
-				clear_sta_flag(sta, WLAN_STA_SP);
-				break;
-			}
-			dev_kfree_skb(skb);
-			break;
 		default:
 			WARN(1, "mac80211: Packet is of unknown type %d\n",
 			     skb->pkt_type);
@@ -295,8 +277,8 @@ void ieee80211_restart_hw(struct ieee80211_hw *hw)
 		   "Hardware restart was requested\n");
 
 	/* use this reason, ieee80211_reconfig will unblock it */
-	ieee80211_stop_queues_by_reason(hw,
-		IEEE80211_QUEUE_STOP_REASON_SUSPEND);
+	ieee80211_stop_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP,
+					IEEE80211_QUEUE_STOP_REASON_SUSPEND);
 
 	/*
 	 * Stop all Rx during the reconfig. We don't want state changes
@@ -399,30 +381,6 @@ static int ieee80211_ifa6_changed(struct notifier_block *nb,
 }
 #endif
 
-static int ieee80211_napi_poll(struct napi_struct *napi, int budget)
-{
-	struct ieee80211_local *local =
-		container_of(napi, struct ieee80211_local, napi);
-
-	return local->ops->napi_poll(&local->hw, budget);
-}
-
-void ieee80211_napi_schedule(struct ieee80211_hw *hw)
-{
-	struct ieee80211_local *local = hw_to_local(hw);
-
-	napi_schedule(&local->napi);
-}
-EXPORT_SYMBOL(ieee80211_napi_schedule);
-
-void ieee80211_napi_complete(struct ieee80211_hw *hw)
-{
-	struct ieee80211_local *local = hw_to_local(hw);
-
-	napi_complete(&local->napi);
-}
-EXPORT_SYMBOL(ieee80211_napi_complete);
-
 /* There isn't a lot of sense in it, but you can transmit anything you like */
 static const struct ieee80211_txrx_stypes
 ieee80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = {
@@ -501,6 +459,27 @@ static const struct ieee80211_ht_cap mac80211_ht_capa_mod_mask = {
 	},
 };
 
+static const struct ieee80211_vht_cap mac80211_vht_capa_mod_mask = {
+	.vht_cap_info =
+		cpu_to_le32(IEEE80211_VHT_CAP_RXLDPC |
+			    IEEE80211_VHT_CAP_SHORT_GI_80 |
+			    IEEE80211_VHT_CAP_SHORT_GI_160 |
+			    IEEE80211_VHT_CAP_RXSTBC_1 |
+			    IEEE80211_VHT_CAP_RXSTBC_2 |
+			    IEEE80211_VHT_CAP_RXSTBC_3 |
+			    IEEE80211_VHT_CAP_RXSTBC_4 |
+			    IEEE80211_VHT_CAP_TXSTBC |
+			    IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE |
+			    IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
+			    IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN |
+			    IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN |
+			    IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK),
+	.supp_mcs = {
+		.rx_mcs_map = cpu_to_le16(~0),
+		.tx_mcs_map = cpu_to_le16(~0),
+	},
+};
+
 static const u8 extended_capabilities[] = {
 	0, 0, 0, 0, 0, 0, 0,
 	WLAN_EXT_CAPA8_OPMODE_NOTIF,
@@ -572,7 +551,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
 	wiphy->features |= NL80211_FEATURE_SK_TX_STATUS |
 			   NL80211_FEATURE_SAE |
 			   NL80211_FEATURE_HT_IBSS |
-			   NL80211_FEATURE_VIF_TXPOWER;
+			   NL80211_FEATURE_VIF_TXPOWER |
+			   NL80211_FEATURE_USERSPACE_MPM;
 
 	if (!ops->hw_scan)
 		wiphy->features |= NL80211_FEATURE_LOW_PRIORITY_SCAN |
@@ -609,6 +589,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
 					 IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH;
 	local->user_power_level = IEEE80211_UNSET_POWER_LEVEL;
 	wiphy->ht_capa_mod_mask = &mac80211_ht_capa_mod_mask;
+	wiphy->vht_capa_mod_mask = &mac80211_vht_capa_mod_mask;
 
 	INIT_LIST_HEAD(&local->interfaces);
 
@@ -664,9 +645,6 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
 	skb_queue_head_init(&local->skb_queue);
 	skb_queue_head_init(&local->skb_queue_unreliable);
 
-	/* init dummy netdev for use w/ NAPI */
-	init_dummy_netdev(&local->napi_dev);
-
 	ieee80211_led_names(local);
 
 	ieee80211_roc_setup(local);
@@ -1021,9 +999,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
 		goto fail_ifa6;
 #endif
 
-	netif_napi_add(&local->napi_dev, &local->napi, ieee80211_napi_poll,
-			local->hw.napi_weight);
-
 	return 0;
 
 #if IS_ENABLED(CONFIG_IPV6)
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 29ce2aa..123a300 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -13,10 +13,6 @@
 #include "ieee80211_i.h"
 #include "mesh.h"
 
-#define TMR_RUNNING_HK	0
-#define TMR_RUNNING_MP	1
-#define TMR_RUNNING_MPR	2
-
 static int mesh_allocated;
 static struct kmem_cache *rm_cache;
 
@@ -50,11 +46,6 @@ static void ieee80211_mesh_housekeeping_timer(unsigned long data)
 
 	set_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags);
 
-	if (local->quiescing) {
-		set_bit(TMR_RUNNING_HK, &ifmsh->timers_running);
-		return;
-	}
-
 	ieee80211_queue_work(&local->hw, &sdata->work);
 }
 
@@ -165,7 +156,7 @@ void mesh_sta_cleanup(struct sta_info *sta)
 	 * an update.
 	 */
 	changed = mesh_accept_plinks_update(sdata);
-	if (sdata->u.mesh.security == IEEE80211_MESH_SEC_NONE) {
+	if (!sdata->u.mesh.user_mpm) {
 		changed |= mesh_plink_deactivate(sta);
 		del_timer_sync(&sta->plink_timer);
 	}
@@ -479,15 +470,8 @@ static void ieee80211_mesh_path_timer(unsigned long data)
 {
 	struct ieee80211_sub_if_data *sdata =
 		(struct ieee80211_sub_if_data *) data;
-	struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
-	struct ieee80211_local *local = sdata->local;
-
-	if (local->quiescing) {
-		set_bit(TMR_RUNNING_MP, &ifmsh->timers_running);
-		return;
-	}
 
-	ieee80211_queue_work(&local->hw, &sdata->work);
+	ieee80211_queue_work(&sdata->local->hw, &sdata->work);
 }
 
 static void ieee80211_mesh_path_root_timer(unsigned long data)
@@ -495,16 +479,10 @@ static void ieee80211_mesh_path_root_timer(unsigned long data)
 	struct ieee80211_sub_if_data *sdata =
 		(struct ieee80211_sub_if_data *) data;
 	struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
-	struct ieee80211_local *local = sdata->local;
 
 	set_bit(MESH_WORK_ROOT, &ifmsh->wrkq_flags);
 
-	if (local->quiescing) {
-		set_bit(TMR_RUNNING_MPR, &ifmsh->timers_running);
-		return;
-	}
-
-	ieee80211_queue_work(&local->hw, &sdata->work);
+	ieee80211_queue_work(&sdata->local->hw, &sdata->work);
 }
 
 void ieee80211_mesh_root_setup(struct ieee80211_if_mesh *ifmsh)
@@ -622,35 +600,6 @@ static void ieee80211_mesh_rootpath(struct ieee80211_sub_if_data *sdata)
 		  round_jiffies(TU_TO_EXP_TIME(interval)));
 }
 
-#ifdef CONFIG_PM
-void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata)
-{
-	struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
-
-	/* use atomic bitops in case all timers fire at the same time */
-
-	if (del_timer_sync(&ifmsh->housekeeping_timer))
-		set_bit(TMR_RUNNING_HK, &ifmsh->timers_running);
-	if (del_timer_sync(&ifmsh->mesh_path_timer))
-		set_bit(TMR_RUNNING_MP, &ifmsh->timers_running);
-	if (del_timer_sync(&ifmsh->mesh_path_root_timer))
-		set_bit(TMR_RUNNING_MPR, &ifmsh->timers_running);
-}
-
-void ieee80211_mesh_restart(struct ieee80211_sub_if_data *sdata)
-{
-	struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
-
-	if (test_and_clear_bit(TMR_RUNNING_HK, &ifmsh->timers_running))
-		add_timer(&ifmsh->housekeeping_timer);
-	if (test_and_clear_bit(TMR_RUNNING_MP, &ifmsh->timers_running))
-		add_timer(&ifmsh->mesh_path_timer);
-	if (test_and_clear_bit(TMR_RUNNING_MPR, &ifmsh->timers_running))
-		add_timer(&ifmsh->mesh_path_root_timer);
-	ieee80211_mesh_root_setup(ifmsh);
-}
-#endif
-
 static int
 ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh)
 {
@@ -750,10 +699,8 @@ out_free:
 static int
 ieee80211_mesh_rebuild_beacon(struct ieee80211_if_mesh *ifmsh)
 {
-	struct ieee80211_sub_if_data *sdata;
 	struct beacon_data *old_bcn;
 	int ret;
-	sdata = container_of(ifmsh, struct ieee80211_sub_if_data, u.mesh);
 
 	mutex_lock(&ifmsh->mtx);
 
@@ -871,8 +818,6 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata)
 	local->fif_other_bss--;
 	atomic_dec(&local->iff_allmultis);
 	ieee80211_configure_filter(local);
-
-	sdata->u.mesh.timers_running = 0;
 }
 
 static void
@@ -886,9 +831,8 @@ ieee80211_mesh_rx_probe_req(struct ieee80211_sub_if_data *sdata,
 	struct ieee80211_mgmt *hdr;
 	struct ieee802_11_elems elems;
 	size_t baselen;
-	u8 *pos, *end;
+	u8 *pos;
 
-	end = ((u8 *) mgmt) + len;
 	pos = mgmt->u.probe_req.variable;
 	baselen = (u8 *) pos - (u8 *) mgmt;
 	if (baselen > len)
@@ -1060,7 +1004,8 @@ void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local)
 
 	rcu_read_lock();
 	list_for_each_entry_rcu(sdata, &local->interfaces, list)
-		if (ieee80211_vif_is_mesh(&sdata->vif))
+		if (ieee80211_vif_is_mesh(&sdata->vif) &&
+		    ieee80211_sdata_running(sdata))
 			ieee80211_queue_work(&local->hw, &sdata->work);
 	rcu_read_unlock();
 }
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index 336c88a..6ffabbe 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -313,8 +313,6 @@ void mesh_path_timer(unsigned long data);
 void mesh_path_flush_by_nexthop(struct sta_info *sta);
 void mesh_path_discard_frame(struct ieee80211_sub_if_data *sdata,
 			     struct sk_buff *skb);
-void mesh_path_quiesce(struct ieee80211_sub_if_data *sdata);
-void mesh_path_restart(struct ieee80211_sub_if_data *sdata);
 void mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata);
 
 bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt);
@@ -359,22 +357,12 @@ static inline bool mesh_path_sel_is_hwmp(struct ieee80211_sub_if_data *sdata)
 
 void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local);
 
-void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata);
-void ieee80211_mesh_restart(struct ieee80211_sub_if_data *sdata);
-void mesh_plink_quiesce(struct sta_info *sta);
-void mesh_plink_restart(struct sta_info *sta);
 void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata);
 void mesh_sync_adjust_tbtt(struct ieee80211_sub_if_data *sdata);
 void ieee80211s_stop(void);
 #else
 static inline void
 ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) {}
-static inline void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata)
-{}
-static inline void ieee80211_mesh_restart(struct ieee80211_sub_if_data *sdata)
-{}
-static inline void mesh_plink_quiesce(struct sta_info *sta) {}
-static inline void mesh_plink_restart(struct sta_info *sta) {}
 static inline bool mesh_path_sel_is_hwmp(struct ieee80211_sub_if_data *sdata)
 { return false; }
 static inline void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata)
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index 07d396d..937e06f 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -420,7 +420,6 @@ __mesh_sta_info_alloc(struct ieee80211_sub_if_data *sdata, u8 *hw_addr)
 		return NULL;
 
 	sta->plink_state = NL80211_PLINK_LISTEN;
-	init_timer(&sta->plink_timer);
 
 	sta_info_pre_move_state(sta, IEEE80211_STA_AUTH);
 	sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC);
@@ -437,8 +436,9 @@ mesh_sta_info_alloc(struct ieee80211_sub_if_data *sdata, u8 *addr,
 {
 	struct sta_info *sta = NULL;
 
-	/* Userspace handles peer allocation when security is enabled */
-	if (sdata->u.mesh.security & IEEE80211_MESH_SEC_AUTHED)
+	/* Userspace handles station allocation */
+	if (sdata->u.mesh.user_mpm ||
+	    sdata->u.mesh.security & IEEE80211_MESH_SEC_AUTHED)
 		cfg80211_notify_new_peer_candidate(sdata->dev, addr,
 						   elems->ie_start,
 						   elems->total_len,
@@ -534,10 +534,8 @@ static void mesh_plink_timer(unsigned long data)
 	 */
 	sta = (struct sta_info *) data;
 
-	if (sta->sdata->local->quiescing) {
-		sta->plink_timer_was_running = true;
+	if (sta->sdata->local->quiescing)
 		return;
-	}
 
 	spin_lock_bh(&sta->lock);
 	if (sta->ignore_plink_timer) {
@@ -598,29 +596,6 @@ static void mesh_plink_timer(unsigned long data)
 	}
 }
 
-#ifdef CONFIG_PM
-void mesh_plink_quiesce(struct sta_info *sta)
-{
-	if (!ieee80211_vif_is_mesh(&sta->sdata->vif))
-		return;
-
-	/* no kernel mesh sta timers have been initialized */
-	if (sta->sdata->u.mesh.security != IEEE80211_MESH_SEC_NONE)
-		return;
-
-	if (del_timer_sync(&sta->plink_timer))
-		sta->plink_timer_was_running = true;
-}
-
-void mesh_plink_restart(struct sta_info *sta)
-{
-	if (sta->plink_timer_was_running) {
-		add_timer(&sta->plink_timer);
-		sta->plink_timer_was_running = false;
-	}
-}
-#endif
-
 static inline void mesh_plink_timer_set(struct sta_info *sta, int timeout)
 {
 	sta->plink_timer.expires = jiffies + (HZ * timeout / 1000);
@@ -695,6 +670,10 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata,
 	if (len < IEEE80211_MIN_ACTION_SIZE + 3)
 		return;
 
+	if (sdata->u.mesh.user_mpm)
+		/* userspace must register for these */
+		return;
+
 	if (is_multicast_ether_addr(mgmt->da)) {
 		mpl_dbg(sdata,
 			"Mesh plink: ignore frame from multicast address\n");
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 1415774..e06dbbf 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -87,9 +87,6 @@ MODULE_PARM_DESC(probe_wait_ms,
  */
 #define IEEE80211_SIGNAL_AVE_MIN_COUNT	4
 
-#define TMR_RUNNING_TIMER	0
-#define TMR_RUNNING_CHANSW	1
-
 /*
  * All cfg80211 functions have to be called outside a locked
  * section so that they can acquire a lock themselves... This
@@ -609,6 +606,7 @@ static void ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata,
 	BUILD_BUG_ON(sizeof(vht_cap) != sizeof(sband->vht_cap));
 
 	memcpy(&vht_cap, &sband->vht_cap, sizeof(vht_cap));
+	ieee80211_apply_vhtcap_overrides(sdata, &vht_cap);
 
 	/* determine capability flags */
 	cap = vht_cap.cap;
@@ -1011,6 +1009,7 @@ static void ieee80211_chswitch_work(struct work_struct *work)
 
 	/* XXX: wait for a beacon first? */
 	ieee80211_wake_queues_by_reason(&sdata->local->hw,
+					IEEE80211_MAX_QUEUE_MAP,
 					IEEE80211_QUEUE_STOP_REASON_CSA);
  out:
 	ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED;
@@ -1038,14 +1037,8 @@ static void ieee80211_chswitch_timer(unsigned long data)
 {
 	struct ieee80211_sub_if_data *sdata =
 		(struct ieee80211_sub_if_data *) data;
-	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
 
-	if (sdata->local->quiescing) {
-		set_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running);
-		return;
-	}
-
-	ieee80211_queue_work(&sdata->local->hw, &ifmgd->chswitch_work);
+	ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.chswitch_work);
 }
 
 void
@@ -1116,6 +1109,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
 
 	if (sw_elem->mode)
 		ieee80211_stop_queues_by_reason(&sdata->local->hw,
+				IEEE80211_MAX_QUEUE_MAP,
 				IEEE80211_QUEUE_STOP_REASON_CSA);
 
 	if (sdata->local->ops->channel_switch) {
@@ -1383,6 +1377,7 @@ void ieee80211_dynamic_ps_disable_work(struct work_struct *work)
 	}
 
 	ieee80211_wake_queues_by_reason(&local->hw,
+					IEEE80211_MAX_QUEUE_MAP,
 					IEEE80211_QUEUE_STOP_REASON_PS);
 }
 
@@ -1444,7 +1439,7 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work)
 		else {
 			ieee80211_send_nullfunc(local, sdata, 1);
 			/* Flush to get the tx status of nullfunc frame */
-			drv_flush(local, false);
+			ieee80211_flush_queues(local, sdata);
 		}
 	}
 
@@ -1775,7 +1770,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
 
 	/* flush out any pending frame (e.g. DELBA) before deauth/disassoc */
 	if (tx)
-		drv_flush(local, false);
+		ieee80211_flush_queues(local, sdata);
 
 	/* deauthenticate/disassociate now */
 	if (tx || frame_buf)
@@ -1784,7 +1779,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
 
 	/* flush out frame */
 	if (tx)
-		drv_flush(local, false);
+		ieee80211_flush_queues(local, sdata);
 
 	/* clear bssid only after building the needed mgmt frames */
 	memset(ifmgd->bssid, 0, ETH_ALEN);
@@ -1802,9 +1797,11 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
 	sdata->vif.bss_conf.p2p_ctwindow = 0;
 	sdata->vif.bss_conf.p2p_oppps = false;
 
-	/* on the next assoc, re-program HT parameters */
+	/* on the next assoc, re-program HT/VHT parameters */
 	memset(&ifmgd->ht_capa, 0, sizeof(ifmgd->ht_capa));
 	memset(&ifmgd->ht_capa_mask, 0, sizeof(ifmgd->ht_capa_mask));
+	memset(&ifmgd->vht_capa, 0, sizeof(ifmgd->vht_capa));
+	memset(&ifmgd->vht_capa_mask, 0, sizeof(ifmgd->vht_capa_mask));
 
 	sdata->ap_power_level = IEEE80211_UNSET_POWER_LEVEL;
 
@@ -1830,8 +1827,6 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
 	del_timer_sync(&sdata->u.mgd.timer);
 	del_timer_sync(&sdata->u.mgd.chswitch_timer);
 
-	sdata->u.mgd.timers_running = 0;
-
 	sdata->vif.bss_conf.dtim_period = 0;
 
 	ifmgd->flags = 0;
@@ -1956,7 +1951,7 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata)
 	ifmgd->probe_timeout = jiffies + msecs_to_jiffies(probe_wait_ms);
 	run_again(ifmgd, ifmgd->probe_timeout);
 	if (sdata->local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)
-		drv_flush(sdata->local, false);
+		ieee80211_flush_queues(sdata->local, sdata);
 }
 
 static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata,
@@ -2079,6 +2074,7 @@ static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata)
 			       true, frame_buf);
 	ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED;
 	ieee80211_wake_queues_by_reason(&sdata->local->hw,
+					IEEE80211_MAX_QUEUE_MAP,
 					IEEE80211_QUEUE_STOP_REASON_CSA);
 	mutex_unlock(&ifmgd->mtx);
 
@@ -3140,15 +3136,8 @@ static void ieee80211_sta_timer(unsigned long data)
 {
 	struct ieee80211_sub_if_data *sdata =
 		(struct ieee80211_sub_if_data *) data;
-	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
-	struct ieee80211_local *local = sdata->local;
-
-	if (local->quiescing) {
-		set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running);
-		return;
-	}
 
-	ieee80211_queue_work(&local->hw, &sdata->work);
+	ieee80211_queue_work(&sdata->local->hw, &sdata->work);
 }
 
 static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata,
@@ -3500,72 +3489,6 @@ static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata)
 	}
 }
 
-#ifdef CONFIG_PM
-void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata)
-{
-	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
-
-	/*
-	 * Stop timers before deleting work items, as timers
-	 * could race and re-add the work-items. They will be
-	 * re-established on connection.
-	 */
-	del_timer_sync(&ifmgd->conn_mon_timer);
-	del_timer_sync(&ifmgd->bcn_mon_timer);
-
-	/*
-	 * we need to use atomic bitops for the running bits
-	 * only because both timers might fire at the same
-	 * time -- the code here is properly synchronised.
-	 */
-
-	cancel_work_sync(&ifmgd->request_smps_work);
-
-	cancel_work_sync(&ifmgd->monitor_work);
-	cancel_work_sync(&ifmgd->beacon_connection_loss_work);
-	cancel_work_sync(&ifmgd->csa_connection_drop_work);
-	if (del_timer_sync(&ifmgd->timer))
-		set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running);
-
-	if (del_timer_sync(&ifmgd->chswitch_timer))
-		set_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running);
-	cancel_work_sync(&ifmgd->chswitch_work);
-}
-
-void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata)
-{
-	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
-
-	mutex_lock(&ifmgd->mtx);
-	if (!ifmgd->associated) {
-		mutex_unlock(&ifmgd->mtx);
-		return;
-	}
-
-	if (sdata->flags & IEEE80211_SDATA_DISCONNECT_RESUME) {
-		sdata->flags &= ~IEEE80211_SDATA_DISCONNECT_RESUME;
-		mlme_dbg(sdata, "driver requested disconnect after resume\n");
-		ieee80211_sta_connection_lost(sdata,
-					      ifmgd->associated->bssid,
-					      WLAN_REASON_UNSPECIFIED,
-					      true);
-		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);
-
-	mutex_lock(&sdata->local->mtx);
-	ieee80211_restart_sta_timer(sdata);
-	mutex_unlock(&sdata->local->mtx);
-}
-#endif
-
 /* interface setup */
 void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
 {
@@ -3608,8 +3531,10 @@ void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local)
 
 	/* Restart STA timers */
 	rcu_read_lock();
-	list_for_each_entry_rcu(sdata, &local->interfaces, list)
-		ieee80211_restart_sta_timer(sdata);
+	list_for_each_entry_rcu(sdata, &local->interfaces, list) {
+		if (ieee80211_sdata_running(sdata))
+			ieee80211_restart_sta_timer(sdata);
+	}
 	rcu_read_unlock();
 }
 
@@ -4071,6 +3996,9 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
 		ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
 	}
 
+	if (req->flags & ASSOC_REQ_DISABLE_VHT)
+		ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
+
 	/* Also disable HT if we don't support it or the AP doesn't use WMM */
 	sband = local->hw.wiphy->bands[req->bss->channel->band];
 	if (!sband->ht_cap.ht_supported ||
@@ -4094,6 +4022,10 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
 	memcpy(&ifmgd->ht_capa_mask, &req->ht_capa_mask,
 	       sizeof(ifmgd->ht_capa_mask));
 
+	memcpy(&ifmgd->vht_capa, &req->vht_capa, sizeof(ifmgd->vht_capa));
+	memcpy(&ifmgd->vht_capa_mask, &req->vht_capa_mask,
+	       sizeof(ifmgd->vht_capa_mask));
+
 	if (req->ie && req->ie_len) {
 		memcpy(assoc_data->ie, req->ie, req->ie_len);
 		assoc_data->ie_len = req->ie_len;
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c
index cc79b4a..cce7958 100644
--- a/net/mac80211/offchannel.c
+++ b/net/mac80211/offchannel.c
@@ -118,9 +118,9 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local)
 	 * Stop queues and transmit all frames queued by the driver
 	 * before sending nullfunc to enable powersave at the AP.
 	 */
-	ieee80211_stop_queues_by_reason(&local->hw,
+	ieee80211_stop_queues_by_reason(&local->hw, IEEE80211_MAX_QUEUE_MAP,
 					IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL);
-	drv_flush(local, false);
+	ieee80211_flush_queues(local, NULL);
 
 	mutex_lock(&local->iflist_mtx);
 	list_for_each_entry(sdata, &local->interfaces, list) {
@@ -181,7 +181,7 @@ void ieee80211_offchannel_return(struct ieee80211_local *local)
 	}
 	mutex_unlock(&local->iflist_mtx);
 
-	ieee80211_wake_queues_by_reason(&local->hw,
+	ieee80211_wake_queues_by_reason(&local->hw, IEEE80211_MAX_QUEUE_MAP,
 					IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL);
 }
 
@@ -277,7 +277,7 @@ void ieee80211_start_next_roc(struct ieee80211_local *local)
 			duration = 10;
 
 		ret = drv_remain_on_channel(local, roc->sdata, roc->chan,
-					    duration);
+					    duration, roc->type);
 
 		roc->started = true;
 
@@ -297,10 +297,13 @@ void ieee80211_start_next_roc(struct ieee80211_local *local)
 	}
 }
 
-void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc)
+void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc, bool free)
 {
 	struct ieee80211_roc_work *dep, *tmp;
 
+	if (WARN_ON(roc->to_be_freed))
+		return;
+
 	/* was never transmitted */
 	if (roc->frame) {
 		cfg80211_mgmt_tx_status(&roc->sdata->wdev,
@@ -316,9 +319,12 @@ void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc)
 						   GFP_KERNEL);
 
 	list_for_each_entry_safe(dep, tmp, &roc->dependents, list)
-		ieee80211_roc_notify_destroy(dep);
+		ieee80211_roc_notify_destroy(dep, true);
 
-	kfree(roc);
+	if (free)
+		kfree(roc);
+	else
+		roc->to_be_freed = true;
 }
 
 void ieee80211_sw_roc_work(struct work_struct *work)
@@ -331,6 +337,9 @@ void ieee80211_sw_roc_work(struct work_struct *work)
 
 	mutex_lock(&local->mtx);
 
+	if (roc->to_be_freed)
+		goto out_unlock;
+
 	if (roc->abort)
 		goto finish;
 
@@ -370,10 +379,10 @@ void ieee80211_sw_roc_work(struct work_struct *work)
  finish:
 		list_del(&roc->list);
 		started = roc->started;
-		ieee80211_roc_notify_destroy(roc);
+		ieee80211_roc_notify_destroy(roc, !roc->abort);
 
 		if (started) {
-			drv_flush(local, false);
+			ieee80211_flush_queues(local, NULL);
 
 			local->tmp_channel = NULL;
 			ieee80211_hw_config(local, 0);
@@ -410,7 +419,7 @@ static void ieee80211_hw_roc_done(struct work_struct *work)
 
 	list_del(&roc->list);
 
-	ieee80211_roc_notify_destroy(roc);
+	ieee80211_roc_notify_destroy(roc, true);
 
 	/* if there's another roc, start it now */
 	ieee80211_start_next_roc(local);
@@ -460,12 +469,14 @@ void ieee80211_roc_purge(struct ieee80211_sub_if_data *sdata)
 	list_for_each_entry_safe(roc, tmp, &tmp_list, list) {
 		if (local->ops->remain_on_channel) {
 			list_del(&roc->list);
-			ieee80211_roc_notify_destroy(roc);
+			ieee80211_roc_notify_destroy(roc, true);
 		} else {
 			ieee80211_queue_delayed_work(&local->hw, &roc->work, 0);
 
 			/* work will clean up etc */
 			flush_delayed_work(&roc->work);
+			WARN_ON(!roc->to_be_freed);
+			kfree(roc);
 		}
 	}
 
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c
index d0275f3..3d16f4e 100644
--- a/net/mac80211/pm.c
+++ b/net/mac80211/pm.c
@@ -6,32 +6,11 @@
 #include "driver-ops.h"
 #include "led.h"
 
-/* return value indicates whether the driver should be further notified */
-static void ieee80211_quiesce(struct ieee80211_sub_if_data *sdata)
-{
-	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;
-	default:
-		break;
-	}
-
-	cancel_work_sync(&sdata->work);
-}
-
 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;
-	struct ieee80211_chanctx *ctx;
 
 	if (!local->open_count)
 		goto suspend;
@@ -51,12 +30,13 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
 	}
 
 	ieee80211_stop_queues_by_reason(hw,
-			IEEE80211_QUEUE_STOP_REASON_SUSPEND);
+					IEEE80211_MAX_QUEUE_MAP,
+					IEEE80211_QUEUE_STOP_REASON_SUSPEND);
 
 	/* flush out all packets */
 	synchronize_net();
 
-	drv_flush(local, false);
+	ieee80211_flush_queues(local, NULL);
 
 	local->quiescing = true;
 	/* make quiescing visible to timers everywhere */
@@ -89,23 +69,17 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
 				mutex_unlock(&local->sta_mtx);
 			}
 			ieee80211_wake_queues_by_reason(hw,
+					IEEE80211_MAX_QUEUE_MAP,
 					IEEE80211_QUEUE_STOP_REASON_SUSPEND);
 			return err;
 		} else if (err > 0) {
 			WARN_ON(err != 1);
-			local->wowlan = false;
+			return err;
 		} else {
-			list_for_each_entry(sdata, &local->interfaces, list)
-				if (ieee80211_sdata_running(sdata))
-					ieee80211_quiesce(sdata);
 			goto suspend;
 		}
 	}
 
-	/* disable keys */
-	list_for_each_entry(sdata, &local->interfaces, list)
-		ieee80211_disable_keys(sdata);
-
 	/* tear down aggregation sessions and remove STAs */
 	mutex_lock(&local->sta_mtx);
 	list_for_each_entry(sta, &local->sta_list, list) {
@@ -117,100 +91,25 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
 				WARN_ON(drv_sta_state(local, sta->sdata, sta,
 						      state, state - 1));
 		}
-
-		mesh_plink_quiesce(sta);
 	}
 	mutex_unlock(&local->sta_mtx);
 
 	/* remove all interfaces */
 	list_for_each_entry(sdata, &local->interfaces, list) {
-		static u8 zero_addr[ETH_ALEN] = {};
-		u32 changed = 0;
-
 		if (!ieee80211_sdata_running(sdata))
 			continue;
-
-		switch (sdata->vif.type) {
-		case NL80211_IFTYPE_AP_VLAN:
-		case NL80211_IFTYPE_MONITOR:
-			/* skip these */
-			continue;
-		case NL80211_IFTYPE_STATION:
-			if (sdata->vif.bss_conf.assoc)
-				changed = BSS_CHANGED_ASSOC |
-					  BSS_CHANGED_BSSID |
-					  BSS_CHANGED_IDLE;
-			break;
-		case NL80211_IFTYPE_AP:
-		case NL80211_IFTYPE_ADHOC:
-		case NL80211_IFTYPE_MESH_POINT:
-			if (sdata->vif.bss_conf.enable_beacon)
-				changed = BSS_CHANGED_BEACON_ENABLED;
-			break;
-		default:
-			break;
-		}
-
-		ieee80211_quiesce(sdata);
-
-		sdata->suspend_bss_conf = sdata->vif.bss_conf;
-		memset(&sdata->vif.bss_conf, 0, sizeof(sdata->vif.bss_conf));
-		sdata->vif.bss_conf.idle = true;
-		if (sdata->suspend_bss_conf.bssid)
-			sdata->vif.bss_conf.bssid = zero_addr;
-
-		/* disable beaconing or remove association */
-		ieee80211_bss_info_change_notify(sdata, changed);
-
-		if (sdata->vif.type == NL80211_IFTYPE_AP &&
-		    rcu_access_pointer(sdata->u.ap.beacon))
-			drv_stop_ap(local, sdata);
-
-		if (local->use_chanctx) {
-			struct ieee80211_chanctx_conf *conf;
-
-			mutex_lock(&local->chanctx_mtx);
-			conf = rcu_dereference_protected(
-					sdata->vif.chanctx_conf,
-					lockdep_is_held(&local->chanctx_mtx));
-			if (conf) {
-				ctx = container_of(conf,
-						   struct ieee80211_chanctx,
-						   conf);
-				drv_unassign_vif_chanctx(local, sdata, ctx);
-			}
-
-			mutex_unlock(&local->chanctx_mtx);
-		}
 		drv_remove_interface(local, sdata);
 	}
 
 	sdata = rtnl_dereference(local->monitor_sdata);
-	if (sdata) {
-		if (local->use_chanctx) {
-			struct ieee80211_chanctx_conf *conf;
-
-			mutex_lock(&local->chanctx_mtx);
-			conf = rcu_dereference_protected(
-					sdata->vif.chanctx_conf,
-					lockdep_is_held(&local->chanctx_mtx));
-			if (conf) {
-				ctx = container_of(conf,
-						   struct ieee80211_chanctx,
-						   conf);
-				drv_unassign_vif_chanctx(local, sdata, ctx);
-			}
-
-			mutex_unlock(&local->chanctx_mtx);
-		}
-
+	if (sdata)
 		drv_remove_interface(local, sdata);
-	}
 
-	mutex_lock(&local->chanctx_mtx);
-	list_for_each_entry(ctx, &local->chanctx_list, list)
-		drv_remove_chanctx(local, ctx);
-	mutex_unlock(&local->chanctx_mtx);
+	/*
+	 * We disconnected on all interfaces before suspend, all channel
+	 * contexts should be released.
+	 */
+	WARN_ON(!list_empty(&local->chanctx_list));
 
 	/* stop hardware - this must stop RX */
 	if (local->open_count)
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c
index eea45a2..1c36c9b 100644
--- a/net/mac80211/rc80211_minstrel.c
+++ b/net/mac80211/rc80211_minstrel.c
@@ -55,7 +55,6 @@
 #include "rate.h"
 #include "rc80211_minstrel.h"
 
-#define SAMPLE_COLUMNS	10
 #define SAMPLE_TBL(_mi, _idx, _col) \
 		_mi->sample_table[(_idx * SAMPLE_COLUMNS) + _col]
 
@@ -70,16 +69,31 @@ rix_to_ndx(struct minstrel_sta_info *mi, int rix)
 	return i;
 }
 
+/* find & sort topmost throughput rates */
+static inline void
+minstrel_sort_best_tp_rates(struct minstrel_sta_info *mi, int i, u8 *tp_list)
+{
+	int j = MAX_THR_RATES;
+
+	while (j > 0 && mi->r[i].cur_tp > mi->r[tp_list[j - 1]].cur_tp)
+		j--;
+	if (j < MAX_THR_RATES - 1)
+		memmove(&tp_list[j + 1], &tp_list[j], MAX_THR_RATES - (j + 1));
+	if (j < MAX_THR_RATES)
+		tp_list[j] = i;
+}
+
 static void
 minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
 {
-	u32 max_tp = 0, index_max_tp = 0, index_max_tp2 = 0;
-	u32 max_prob = 0, index_max_prob = 0;
+	u8 tmp_tp_rate[MAX_THR_RATES];
+	u8 tmp_prob_rate = 0;
 	u32 usecs;
-	u32 p;
 	int i;
 
-	mi->stats_update = jiffies;
+	for (i=0; i < MAX_THR_RATES; i++)
+	    tmp_tp_rate[i] = 0;
+
 	for (i = 0; i < mi->n_rates; i++) {
 		struct minstrel_rate *mr = &mi->r[i];
 
@@ -87,27 +101,32 @@ minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
 		if (!usecs)
 			usecs = 1000000;
 
-		/* To avoid rounding issues, probabilities scale from 0 (0%)
-		 * to 18000 (100%) */
-		if (mr->attempts) {
-			p = (mr->success * 18000) / mr->attempts;
+		if (unlikely(mr->attempts > 0)) {
+			mr->sample_skipped = 0;
+			mr->cur_prob = MINSTREL_FRAC(mr->success, mr->attempts);
 			mr->succ_hist += mr->success;
 			mr->att_hist += mr->attempts;
-			mr->cur_prob = p;
-			p = ((p * (100 - mp->ewma_level)) + (mr->probability *
-				mp->ewma_level)) / 100;
-			mr->probability = p;
-			mr->cur_tp = p * (1000000 / usecs);
-		}
+			mr->probability = minstrel_ewma(mr->probability,
+							mr->cur_prob,
+							EWMA_LEVEL);
+		} else
+			mr->sample_skipped++;
 
 		mr->last_success = mr->success;
 		mr->last_attempts = mr->attempts;
 		mr->success = 0;
 		mr->attempts = 0;
 
+		/* Update throughput per rate, reset thr. below 10% success */
+		if (mr->probability < MINSTREL_FRAC(10, 100))
+			mr->cur_tp = 0;
+		else
+			mr->cur_tp = mr->probability * (1000000 / usecs);
+
 		/* Sample less often below the 10% chance of success.
 		 * Sample less often above the 95% chance of success. */
-		if ((mr->probability > 17100) || (mr->probability < 1800)) {
+		if (mr->probability > MINSTREL_FRAC(95, 100) ||
+		    mr->probability < MINSTREL_FRAC(10, 100)) {
 			mr->adjusted_retry_count = mr->retry_count >> 1;
 			if (mr->adjusted_retry_count > 2)
 				mr->adjusted_retry_count = 2;
@@ -118,35 +137,30 @@ minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
 		}
 		if (!mr->adjusted_retry_count)
 			mr->adjusted_retry_count = 2;
-	}
 
-	for (i = 0; i < mi->n_rates; i++) {
-		struct minstrel_rate *mr = &mi->r[i];
-		if (max_tp < mr->cur_tp) {
-			index_max_tp = i;
-			max_tp = mr->cur_tp;
-		}
-		if (max_prob < mr->probability) {
-			index_max_prob = i;
-			max_prob = mr->probability;
+		minstrel_sort_best_tp_rates(mi, i, tmp_tp_rate);
+
+		/* To determine the most robust rate (max_prob_rate) used at
+		 * 3rd mmr stage we distinct between two cases:
+		 * (1) if any success probabilitiy >= 95%, out of those rates
+		 * choose the maximum throughput rate as max_prob_rate
+		 * (2) if all success probabilities < 95%, the rate with
+		 * highest success probability is choosen as max_prob_rate */
+		if (mr->probability >= MINSTREL_FRAC(95,100)) {
+			if (mr->cur_tp >= mi->r[tmp_prob_rate].cur_tp)
+				tmp_prob_rate = i;
+		} else {
+			if (mr->probability >= mi->r[tmp_prob_rate].probability)
+				tmp_prob_rate = i;
 		}
 	}
 
-	max_tp = 0;
-	for (i = 0; i < mi->n_rates; i++) {
-		struct minstrel_rate *mr = &mi->r[i];
-
-		if (i == index_max_tp)
-			continue;
+	/* Assign the new rate set */
+	memcpy(mi->max_tp_rate, tmp_tp_rate, sizeof(mi->max_tp_rate));
+	mi->max_prob_rate = tmp_prob_rate;
 
-		if (max_tp < mr->cur_tp) {
-			index_max_tp2 = i;
-			max_tp = mr->cur_tp;
-		}
-	}
-	mi->max_tp_rate = index_max_tp;
-	mi->max_tp_rate2 = index_max_tp2;
-	mi->max_prob_rate = index_max_prob;
+	/* Reset update timer */
+	mi->stats_update = jiffies;
 }
 
 static void
@@ -207,10 +221,10 @@ static int
 minstrel_get_next_sample(struct minstrel_sta_info *mi)
 {
 	unsigned int sample_ndx;
-	sample_ndx = SAMPLE_TBL(mi, mi->sample_idx, mi->sample_column);
-	mi->sample_idx++;
-	if ((int) mi->sample_idx > (mi->n_rates - 2)) {
-		mi->sample_idx = 0;
+	sample_ndx = SAMPLE_TBL(mi, mi->sample_row, mi->sample_column);
+	mi->sample_row++;
+	if ((int) mi->sample_row >= mi->n_rates) {
+		mi->sample_row = 0;
 		mi->sample_column++;
 		if (mi->sample_column >= SAMPLE_COLUMNS)
 			mi->sample_column = 0;
@@ -228,31 +242,37 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta,
 	struct minstrel_priv *mp = priv;
 	struct ieee80211_tx_rate *ar = info->control.rates;
 	unsigned int ndx, sample_ndx = 0;
-	bool mrr;
-	bool sample_slower = false;
-	bool sample = false;
+	bool mrr_capable;
+	bool indirect_rate_sampling = false;
+	bool rate_sampling = false;
 	int i, delta;
 	int mrr_ndx[3];
-	int sample_rate;
+	int sampling_ratio;
 
+	/* management/no-ack frames do not use rate control */
 	if (rate_control_send_low(sta, priv_sta, txrc))
 		return;
 
-	mrr = mp->has_mrr && !txrc->rts && !txrc->bss_conf->use_cts_prot;
-
-	ndx = mi->max_tp_rate;
-
-	if (mrr)
-		sample_rate = mp->lookaround_rate_mrr;
+	/* check multi-rate-retry capabilities & adjust lookaround_rate */
+	mrr_capable = mp->has_mrr &&
+		      !txrc->rts &&
+		      !txrc->bss_conf->use_cts_prot;
+	if (mrr_capable)
+		sampling_ratio = mp->lookaround_rate_mrr;
 	else
-		sample_rate = mp->lookaround_rate;
+		sampling_ratio = mp->lookaround_rate;
+
+	/* init rateindex [ndx] with max throughput rate */
+	ndx = mi->max_tp_rate[0];
 
+	/* increase sum packet counter */
 	mi->packet_count++;
-	delta = (mi->packet_count * sample_rate / 100) -
+
+	delta = (mi->packet_count * sampling_ratio / 100) -
 			(mi->sample_count + mi->sample_deferred / 2);
 
 	/* delta > 0: sampling required */
-	if ((delta > 0) && (mrr || !mi->prev_sample)) {
+	if ((delta > 0) && (mrr_capable || !mi->prev_sample)) {
 		struct minstrel_rate *msr;
 		if (mi->packet_count >= 10000) {
 			mi->sample_deferred = 0;
@@ -271,21 +291,28 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta,
 			mi->sample_count += (delta - mi->n_rates * 2);
 		}
 
+		/* get next random rate sample */
 		sample_ndx = minstrel_get_next_sample(mi);
 		msr = &mi->r[sample_ndx];
-		sample = true;
-		sample_slower = mrr && (msr->perfect_tx_time >
-			mi->r[ndx].perfect_tx_time);
-
-		if (!sample_slower) {
+		rate_sampling = true;
+
+		/* Decide if direct ( 1st mrr stage) or indirect (2nd mrr stage)
+		 * rate sampling method should be used.
+		 * Respect such rates that are not sampled for 20 interations.
+		 */
+		if (mrr_capable &&
+		    msr->perfect_tx_time > mi->r[ndx].perfect_tx_time &&
+		    msr->sample_skipped < 20)
+				indirect_rate_sampling = true;
+
+		if (!indirect_rate_sampling) {
 			if (msr->sample_limit != 0) {
 				ndx = sample_ndx;
 				mi->sample_count++;
 				if (msr->sample_limit > 0)
 					msr->sample_limit--;
-			} else {
-				sample = false;
-			}
+			} else
+				rate_sampling = false;
 		} else {
 			/* Only use IEEE80211_TX_CTL_RATE_CTRL_PROBE to mark
 			 * packets that have the sampling rate deferred to the
@@ -297,34 +324,39 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta,
 			mi->sample_deferred++;
 		}
 	}
-	mi->prev_sample = sample;
+	mi->prev_sample = rate_sampling;
 
 	/* If we're not using MRR and the sampling rate already
 	 * has a probability of >95%, we shouldn't be attempting
 	 * to use it, as this only wastes precious airtime */
-	if (!mrr && sample && (mi->r[ndx].probability > 17100))
-		ndx = mi->max_tp_rate;
+	if (!mrr_capable && rate_sampling &&
+	   (mi->r[ndx].probability > MINSTREL_FRAC(95, 100)))
+		ndx = mi->max_tp_rate[0];
 
+	/* mrr setup for 1st stage */
 	ar[0].idx = mi->r[ndx].rix;
 	ar[0].count = minstrel_get_retry_count(&mi->r[ndx], info);
 
-	if (!mrr) {
-		if (!sample)
+	/* non mrr setup for 2nd stage */
+	if (!mrr_capable) {
+		if (!rate_sampling)
 			ar[0].count = mp->max_retry;
 		ar[1].idx = mi->lowest_rix;
 		ar[1].count = mp->max_retry;
 		return;
 	}
 
-	/* MRR setup */
-	if (sample) {
-		if (sample_slower)
+	/* mrr setup for 2nd stage */
+	if (rate_sampling) {
+		if (indirect_rate_sampling)
 			mrr_ndx[0] = sample_ndx;
 		else
-			mrr_ndx[0] = mi->max_tp_rate;
+			mrr_ndx[0] = mi->max_tp_rate[0];
 	} else {
-		mrr_ndx[0] = mi->max_tp_rate2;
+		mrr_ndx[0] = mi->max_tp_rate[1];
 	}
+
+	/* mrr setup for 3rd & 4th stage */
 	mrr_ndx[1] = mi->max_prob_rate;
 	mrr_ndx[2] = 0;
 	for (i = 1; i < 4; i++) {
@@ -351,26 +383,21 @@ static void
 init_sample_table(struct minstrel_sta_info *mi)
 {
 	unsigned int i, col, new_idx;
-	unsigned int n_srates = mi->n_rates - 1;
 	u8 rnd[8];
 
 	mi->sample_column = 0;
-	mi->sample_idx = 0;
-	memset(mi->sample_table, 0, SAMPLE_COLUMNS * mi->n_rates);
+	mi->sample_row = 0;
+	memset(mi->sample_table, 0xff, SAMPLE_COLUMNS * mi->n_rates);
 
 	for (col = 0; col < SAMPLE_COLUMNS; col++) {
-		for (i = 0; i < n_srates; i++) {
+		for (i = 0; i < mi->n_rates; i++) {
 			get_random_bytes(rnd, sizeof(rnd));
-			new_idx = (i + rnd[i & 7]) % n_srates;
+			new_idx = (i + rnd[i & 7]) % mi->n_rates;
 
-			while (SAMPLE_TBL(mi, new_idx, col) != 0)
-				new_idx = (new_idx + 1) % n_srates;
+			while (SAMPLE_TBL(mi, new_idx, col) != 0xff)
+				new_idx = (new_idx + 1) % mi->n_rates;
 
-			/* Don't sample the slowest rate (i.e. slowest base
-			 * rate). We must presume that the slowest rate works
-			 * fine, or else other management frames will also be
-			 * failing and the link will break */
-			SAMPLE_TBL(mi, new_idx, col) = i + 1;
+			SAMPLE_TBL(mi, new_idx, col) = i;
 		}
 	}
 }
@@ -542,9 +569,6 @@ minstrel_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
 	mp->lookaround_rate = 5;
 	mp->lookaround_rate_mrr = 10;
 
-	/* moving average weight for EWMA */
-	mp->ewma_level = 75;
-
 	/* maximum time that the hw is allowed to stay in one MRR segment */
 	mp->segment_size = 6000;
 
diff --git a/net/mac80211/rc80211_minstrel.h b/net/mac80211/rc80211_minstrel.h
index 5ecf757..85ebf42 100644
--- a/net/mac80211/rc80211_minstrel.h
+++ b/net/mac80211/rc80211_minstrel.h
@@ -9,6 +9,28 @@
 #ifndef __RC_MINSTREL_H
 #define __RC_MINSTREL_H
 
+#define EWMA_LEVEL	75	/* ewma weighting factor [%] */
+#define SAMPLE_COLUMNS	10	/* number of columns in sample table */
+
+
+/* scaled fraction values */
+#define MINSTREL_SCALE  16
+#define MINSTREL_FRAC(val, div) (((val) << MINSTREL_SCALE) / div)
+#define MINSTREL_TRUNC(val) ((val) >> MINSTREL_SCALE)
+
+/* number of highest throughput rates to consider*/
+#define MAX_THR_RATES 4
+
+/*
+ * Perform EWMA (Exponentially Weighted Moving Average) calculation
+  */
+static inline int
+minstrel_ewma(int old, int new, int weight)
+{
+	return (new * (100 - weight) + old * weight) / 100;
+}
+
+
 struct minstrel_rate {
 	int bitrate;
 	int rix;
@@ -26,6 +48,7 @@ struct minstrel_rate {
 	u32 attempts;
 	u32 last_attempts;
 	u32 last_success;
+	u8 sample_skipped;
 
 	/* parts per thousand */
 	u32 cur_prob;
@@ -45,14 +68,13 @@ struct minstrel_sta_info {
 
 	unsigned int lowest_rix;
 
-	unsigned int max_tp_rate;
-	unsigned int max_tp_rate2;
-	unsigned int max_prob_rate;
+	u8 max_tp_rate[MAX_THR_RATES];
+	u8 max_prob_rate;
 	unsigned int packet_count;
 	unsigned int sample_count;
 	int sample_deferred;
 
-	unsigned int sample_idx;
+	unsigned int sample_row;
 	unsigned int sample_column;
 
 	int n_rates;
@@ -73,7 +95,6 @@ struct minstrel_priv {
 	unsigned int cw_min;
 	unsigned int cw_max;
 	unsigned int max_retry;
-	unsigned int ewma_level;
 	unsigned int segment_size;
 	unsigned int update_interval;
 	unsigned int lookaround_rate;
diff --git a/net/mac80211/rc80211_minstrel_debugfs.c b/net/mac80211/rc80211_minstrel_debugfs.c
index d5a5622..d104834 100644
--- a/net/mac80211/rc80211_minstrel_debugfs.c
+++ b/net/mac80211/rc80211_minstrel_debugfs.c
@@ -73,15 +73,17 @@ minstrel_stats_open(struct inode *inode, struct file *file)
 	for (i = 0; i < mi->n_rates; i++) {
 		struct minstrel_rate *mr = &mi->r[i];
 
-		*(p++) = (i == mi->max_tp_rate) ? 'T' : ' ';
-		*(p++) = (i == mi->max_tp_rate2) ? 't' : ' ';
+		*(p++) = (i == mi->max_tp_rate[0]) ? 'A' : ' ';
+		*(p++) = (i == mi->max_tp_rate[1]) ? 'B' : ' ';
+		*(p++) = (i == mi->max_tp_rate[2]) ? 'C' : ' ';
+		*(p++) = (i == mi->max_tp_rate[3]) ? 'D' : ' ';
 		*(p++) = (i == mi->max_prob_rate) ? 'P' : ' ';
 		p += sprintf(p, "%3u%s", mr->bitrate / 2,
 				(mr->bitrate & 1 ? ".5" : "  "));
 
-		tp = mr->cur_tp / ((18000 << 10) / 96);
-		prob = mr->cur_prob / 18;
-		eprob = mr->probability / 18;
+		tp = MINSTREL_TRUNC(mr->cur_tp / 10);
+		prob = MINSTREL_TRUNC(mr->cur_prob * 1000);
+		eprob = MINSTREL_TRUNC(mr->probability * 1000);
 
 		p += sprintf(p, "  %6u.%1u   %6u.%1u   %6u.%1u        "
 				"%3u(%3u)   %8llu    %8llu\n",
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c
index 3af141c..d2b264d 100644
--- a/net/mac80211/rc80211_minstrel_ht.c
+++ b/net/mac80211/rc80211_minstrel_ht.c
@@ -17,8 +17,6 @@
 #include "rc80211_minstrel_ht.h"
 
 #define AVG_PKT_SIZE	1200
-#define SAMPLE_COLUMNS	10
-#define EWMA_LEVEL		75
 
 /* Number of bits for an average sized packet */
 #define MCS_NBITS (AVG_PKT_SIZE << 3)
@@ -26,11 +24,11 @@
 /* Number of symbols for a packet with (bps) bits per symbol */
 #define MCS_NSYMS(bps) ((MCS_NBITS + (bps) - 1) / (bps))
 
-/* Transmission time for a packet containing (syms) symbols */
+/* Transmission time (nanoseconds) for a packet containing (syms) symbols */
 #define MCS_SYMBOL_TIME(sgi, syms)					\
 	(sgi ?								\
-	  ((syms) * 18 + 4) / 5 :	/* syms * 3.6 us */		\
-	  (syms) << 2			/* syms * 4 us */		\
+	  ((syms) * 18000 + 4000) / 5 :	/* syms * 3.6 us */		\
+	  ((syms) * 1000) << 2		/* syms * 4 us */		\
 	)
 
 /* Transmit duration for the raw data part of an average sized packet */
@@ -64,9 +62,9 @@
 }
 
 #define CCK_DURATION(_bitrate, _short, _len)		\
-	(10 /* SIFS */ +				\
+	(1000 * (10 /* SIFS */ +			\
 	 (_short ? 72 + 24 : 144 + 48 ) +		\
-	 (8 * (_len + 4) * 10) / (_bitrate))
+	 (8 * (_len + 4) * 10) / (_bitrate)))
 
 #define CCK_ACK_DURATION(_bitrate, _short)			\
 	(CCK_DURATION((_bitrate > 10 ? 20 : 10), false, 60) +	\
@@ -129,15 +127,6 @@ const struct mcs_group minstrel_mcs_groups[] = {
 static u8 sample_table[SAMPLE_COLUMNS][MCS_GROUP_RATES];
 
 /*
- * Perform EWMA (Exponentially Weighted Moving Average) calculation
- */
-static int
-minstrel_ewma(int old, int new, int weight)
-{
-	return (new * (100 - weight) + old * weight) / 100;
-}
-
-/*
  * Look up an MCS group index based on mac80211 rate information
  */
 static int
@@ -211,20 +200,32 @@ static void
 minstrel_ht_calc_tp(struct minstrel_ht_sta *mi, int group, int rate)
 {
 	struct minstrel_rate_stats *mr;
-	unsigned int usecs = 0;
+	unsigned int nsecs = 0;
+	unsigned int tp;
+	unsigned int prob;
 
 	mr = &mi->groups[group].rates[rate];
+	prob = mr->probability;
 
-	if (mr->probability < MINSTREL_FRAC(1, 10)) {
+	if (prob < MINSTREL_FRAC(1, 10)) {
 		mr->cur_tp = 0;
 		return;
 	}
 
+	/*
+	 * For the throughput calculation, limit the probability value to 90% to
+	 * account for collision related packet error rate fluctuation
+	 */
+	if (prob > MINSTREL_FRAC(9, 10))
+		prob = MINSTREL_FRAC(9, 10);
+
 	if (group != MINSTREL_CCK_GROUP)
-		usecs = mi->overhead / MINSTREL_TRUNC(mi->avg_ampdu_len);
+		nsecs = 1000 * mi->overhead / MINSTREL_TRUNC(mi->avg_ampdu_len);
+
+	nsecs += minstrel_mcs_groups[group].duration[rate];
+	tp = 1000000 * ((mr->probability * 1000) / nsecs);
 
-	usecs += minstrel_mcs_groups[group].duration[rate];
-	mr->cur_tp = MINSTREL_TRUNC((1000000 / usecs) * mr->probability);
+	mr->cur_tp = MINSTREL_TRUNC(tp);
 }
 
 /*
@@ -308,8 +309,8 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
 		}
 	}
 
-	/* try to sample up to half of the available rates during each interval */
-	mi->sample_count *= 4;
+	/* try to sample all available rates during each interval */
+	mi->sample_count *= 8;
 
 	cur_prob = 0;
 	cur_prob_tp = 0;
@@ -320,20 +321,13 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
 		if (!mg->supported)
 			continue;
 
-		mr = minstrel_get_ratestats(mi, mg->max_prob_rate);
-		if (cur_prob_tp < mr->cur_tp &&
-		    minstrel_mcs_groups[group].streams == 1) {
-			mi->max_prob_rate = mg->max_prob_rate;
-			cur_prob = mr->cur_prob;
-			cur_prob_tp = mr->cur_tp;
-		}
-
 		mr = minstrel_get_ratestats(mi, mg->max_tp_rate);
 		if (cur_tp < mr->cur_tp) {
 			mi->max_tp_rate2 = mi->max_tp_rate;
 			cur_tp2 = cur_tp;
 			mi->max_tp_rate = mg->max_tp_rate;
 			cur_tp = mr->cur_tp;
+			mi->max_prob_streams = minstrel_mcs_groups[group].streams - 1;
 		}
 
 		mr = minstrel_get_ratestats(mi, mg->max_tp_rate2);
@@ -343,6 +337,23 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
 		}
 	}
 
+	if (mi->max_prob_streams < 1)
+		mi->max_prob_streams = 1;
+
+	for (group = 0; group < ARRAY_SIZE(minstrel_mcs_groups); group++) {
+		mg = &mi->groups[group];
+		if (!mg->supported)
+			continue;
+		mr = minstrel_get_ratestats(mi, mg->max_prob_rate);
+		if (cur_prob_tp < mr->cur_tp &&
+		    minstrel_mcs_groups[group].streams <= mi->max_prob_streams) {
+			mi->max_prob_rate = mg->max_prob_rate;
+			cur_prob = mr->cur_prob;
+			cur_prob_tp = mr->cur_tp;
+		}
+	}
+
+
 	mi->stats_update = jiffies;
 }
 
@@ -467,7 +478,7 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband,
 
 	if (!mi->sample_wait && !mi->sample_tries && mi->sample_count > 0) {
 		mi->sample_wait = 16 + 2 * MINSTREL_TRUNC(mi->avg_ampdu_len);
-		mi->sample_tries = 2;
+		mi->sample_tries = 1;
 		mi->sample_count--;
 	}
 
@@ -536,7 +547,7 @@ minstrel_calc_retransmit(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
 	mr->retry_updated = true;
 
 	group = &minstrel_mcs_groups[index / MCS_GROUP_RATES];
-	tx_time_data = group->duration[index % MCS_GROUP_RATES] * ampdu_len;
+	tx_time_data = group->duration[index % MCS_GROUP_RATES] * ampdu_len / 1000;
 
 	/* Contention time for first 2 tries */
 	ctime = (t_slot * cw) >> 1;
@@ -616,6 +627,7 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
 {
 	struct minstrel_rate_stats *mr;
 	struct minstrel_mcs_group_data *mg;
+	unsigned int sample_dur, sample_group;
 	int sample_idx = 0;
 
 	if (mi->sample_wait > 0) {
@@ -626,39 +638,46 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
 	if (!mi->sample_tries)
 		return -1;
 
-	mi->sample_tries--;
 	mg = &mi->groups[mi->sample_group];
 	sample_idx = sample_table[mg->column][mg->index];
 	mr = &mg->rates[sample_idx];
-	sample_idx += mi->sample_group * MCS_GROUP_RATES;
+	sample_group = mi->sample_group;
+	sample_idx += sample_group * MCS_GROUP_RATES;
 	minstrel_next_sample_idx(mi);
 
 	/*
 	 * Sampling might add some overhead (RTS, no aggregation)
 	 * to the frame. Hence, don't use sampling for the currently
-	 * used max TP rate.
+	 * used rates.
 	 */
-	if (sample_idx == mi->max_tp_rate)
+	if (sample_idx == mi->max_tp_rate ||
+	    sample_idx == mi->max_tp_rate2 ||
+	    sample_idx == mi->max_prob_rate)
 		return -1;
+
 	/*
-	 * When not using MRR, do not sample if the probability is already
-	 * higher than 95% to avoid wasting airtime
+	 * Do not sample if the probability is already higher than 95%
+	 * to avoid wasting airtime.
 	 */
-	if (!mp->has_mrr && (mr->probability > MINSTREL_FRAC(95, 100)))
+	if (mr->probability > MINSTREL_FRAC(95, 100))
 		return -1;
 
 	/*
 	 * Make sure that lower rates get sampled only occasionally,
 	 * if the link is working perfectly.
 	 */
-	if (minstrel_get_duration(sample_idx) >
-	    minstrel_get_duration(mi->max_tp_rate)) {
+	sample_dur = minstrel_get_duration(sample_idx);
+	if (sample_dur >= minstrel_get_duration(mi->max_tp_rate2) &&
+	    (mi->max_prob_streams <
+	     minstrel_mcs_groups[sample_group].streams ||
+	     sample_dur >= minstrel_get_duration(mi->max_prob_rate))) {
 		if (mr->sample_skipped < 20)
 			return -1;
 
 		if (mi->sample_slow++ > 2)
 			return -1;
 	}
+	mi->sample_tries--;
 
 	return sample_idx;
 }
diff --git a/net/mac80211/rc80211_minstrel_ht.h b/net/mac80211/rc80211_minstrel_ht.h
index 302dbd5..9b16e9d 100644
--- a/net/mac80211/rc80211_minstrel_ht.h
+++ b/net/mac80211/rc80211_minstrel_ht.h
@@ -16,11 +16,6 @@
 #define MINSTREL_MAX_STREAMS	3
 #define MINSTREL_STREAM_GROUPS	4
 
-/* scaled fraction values */
-#define MINSTREL_SCALE	16
-#define MINSTREL_FRAC(val, div) (((val) << MINSTREL_SCALE) / div)
-#define MINSTREL_TRUNC(val) ((val) >> MINSTREL_SCALE)
-
 #define MCS_GROUP_RATES	8
 
 struct mcs_group {
@@ -85,6 +80,7 @@ struct minstrel_ht_sta {
 
 	/* best probability rate */
 	unsigned int max_prob_rate;
+	unsigned int max_prob_streams;
 
 	/* time of last status update */
 	unsigned long stats_update;
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index bb73ed2d..2528b5a 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -648,24 +648,6 @@ static ieee80211_rx_result ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
 	return RX_CONTINUE;
 }
 
-#define SEQ_MODULO 0x1000
-#define SEQ_MASK   0xfff
-
-static inline int seq_less(u16 sq1, u16 sq2)
-{
-	return ((sq1 - sq2) & SEQ_MASK) > (SEQ_MODULO >> 1);
-}
-
-static inline u16 seq_inc(u16 sq)
-{
-	return (sq + 1) & SEQ_MASK;
-}
-
-static inline u16 seq_sub(u16 sq1, u16 sq2)
-{
-	return (sq1 - sq2) & SEQ_MASK;
-}
-
 static void ieee80211_release_reorder_frame(struct ieee80211_sub_if_data *sdata,
 					    struct tid_ampdu_rx *tid_agg_rx,
 					    int index,
@@ -687,7 +669,7 @@ static void ieee80211_release_reorder_frame(struct ieee80211_sub_if_data *sdata,
 	__skb_queue_tail(frames, skb);
 
 no_frame:
-	tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num);
+	tid_agg_rx->head_seq_num = ieee80211_sn_inc(tid_agg_rx->head_seq_num);
 }
 
 static void ieee80211_release_reorder_frames(struct ieee80211_sub_if_data *sdata,
@@ -699,8 +681,9 @@ static void ieee80211_release_reorder_frames(struct ieee80211_sub_if_data *sdata
 
 	lockdep_assert_held(&tid_agg_rx->reorder_lock);
 
-	while (seq_less(tid_agg_rx->head_seq_num, head_seq_num)) {
-		index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) %
+	while (ieee80211_sn_less(tid_agg_rx->head_seq_num, head_seq_num)) {
+		index = ieee80211_sn_sub(tid_agg_rx->head_seq_num,
+					 tid_agg_rx->ssn) %
 							tid_agg_rx->buf_size;
 		ieee80211_release_reorder_frame(sdata, tid_agg_rx, index,
 						frames);
@@ -727,8 +710,8 @@ static void ieee80211_sta_reorder_release(struct ieee80211_sub_if_data *sdata,
 	lockdep_assert_held(&tid_agg_rx->reorder_lock);
 
 	/* release the buffer until next missing frame */
-	index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) %
-						tid_agg_rx->buf_size;
+	index = ieee80211_sn_sub(tid_agg_rx->head_seq_num,
+				 tid_agg_rx->ssn) % tid_agg_rx->buf_size;
 	if (!tid_agg_rx->reorder_buf[index] &&
 	    tid_agg_rx->stored_mpdu_num) {
 		/*
@@ -756,19 +739,22 @@ static void ieee80211_sta_reorder_release(struct ieee80211_sub_if_data *sdata,
 			 * Increment the head seq# also for the skipped slots.
 			 */
 			tid_agg_rx->head_seq_num =
-				(tid_agg_rx->head_seq_num + skipped) & SEQ_MASK;
+				(tid_agg_rx->head_seq_num +
+				 skipped) & IEEE80211_SN_MASK;
 			skipped = 0;
 		}
 	} else while (tid_agg_rx->reorder_buf[index]) {
 		ieee80211_release_reorder_frame(sdata, tid_agg_rx, index,
 						frames);
-		index =	seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) %
+		index =	ieee80211_sn_sub(tid_agg_rx->head_seq_num,
+					 tid_agg_rx->ssn) %
 							tid_agg_rx->buf_size;
 	}
 
 	if (tid_agg_rx->stored_mpdu_num) {
-		j = index = seq_sub(tid_agg_rx->head_seq_num,
-				    tid_agg_rx->ssn) % tid_agg_rx->buf_size;
+		j = index = ieee80211_sn_sub(tid_agg_rx->head_seq_num,
+					     tid_agg_rx->ssn) %
+							tid_agg_rx->buf_size;
 
 		for (; j != (index - 1) % tid_agg_rx->buf_size;
 		     j = (j + 1) % tid_agg_rx->buf_size) {
@@ -809,7 +795,7 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata
 	head_seq_num = tid_agg_rx->head_seq_num;
 
 	/* frame with out of date sequence number */
-	if (seq_less(mpdu_seq_num, head_seq_num)) {
+	if (ieee80211_sn_less(mpdu_seq_num, head_seq_num)) {
 		dev_kfree_skb(skb);
 		goto out;
 	}
@@ -818,8 +804,9 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata
 	 * If frame the sequence number exceeds our buffering window
 	 * size release some previous frames to make room for this one.
 	 */
-	if (!seq_less(mpdu_seq_num, head_seq_num + buf_size)) {
-		head_seq_num = seq_inc(seq_sub(mpdu_seq_num, buf_size));
+	if (!ieee80211_sn_less(mpdu_seq_num, head_seq_num + buf_size)) {
+		head_seq_num = ieee80211_sn_inc(
+				ieee80211_sn_sub(mpdu_seq_num, buf_size));
 		/* release stored frames up to new head to stack */
 		ieee80211_release_reorder_frames(sdata, tid_agg_rx,
 						 head_seq_num, frames);
@@ -827,7 +814,8 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata
 
 	/* Now the new frame is always in the range of the reordering buffer */
 
-	index = seq_sub(mpdu_seq_num, tid_agg_rx->ssn) % tid_agg_rx->buf_size;
+	index = ieee80211_sn_sub(mpdu_seq_num,
+				 tid_agg_rx->ssn) % tid_agg_rx->buf_size;
 
 	/* check if we already stored this frame */
 	if (tid_agg_rx->reorder_buf[index]) {
@@ -843,7 +831,8 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata
 	 */
 	if (mpdu_seq_num == tid_agg_rx->head_seq_num &&
 	    tid_agg_rx->stored_mpdu_num == 0) {
-		tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num);
+		tid_agg_rx->head_seq_num =
+			ieee80211_sn_inc(tid_agg_rx->head_seq_num);
 		ret = false;
 		goto out;
 	}
@@ -1894,8 +1883,10 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
 		 * 'align' will only take the values 0 or 2 here
 		 * since all frames are required to be aligned
 		 * to 2-byte boundaries when being passed to
-		 * mac80211. That also explains the __skb_push()
-		 * below.
+		 * mac80211; the code here works just as well if
+		 * that isn't true, but mac80211 assumes it can
+		 * access fields as 2-byte aligned (e.g. for
+		 * compare_ether_addr)
 		 */
 		align = ((unsigned long)(skb->data + sizeof(struct ethhdr))) & 3;
 		if (align) {
@@ -2552,7 +2543,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
 		case WLAN_SP_MESH_PEERING_CONFIRM:
 			if (!ieee80211_vif_is_mesh(&sdata->vif))
 				goto invalid;
-			if (sdata->u.mesh.security != IEEE80211_MESH_SEC_NONE)
+			if (sdata->u.mesh.user_mpm)
 				/* userspace handles this frame */
 				break;
 			goto queue;
@@ -2675,7 +2666,19 @@ ieee80211_rx_h_action_return(struct ieee80211_rx_data *rx)
 
 		memset(nskb->cb, 0, sizeof(nskb->cb));
 
-		ieee80211_tx_skb(rx->sdata, nskb);
+		if (rx->sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE) {
+			struct ieee80211_tx_info *info = IEEE80211_SKB_CB(nskb);
+
+			info->flags = IEEE80211_TX_CTL_TX_OFFCHAN |
+				      IEEE80211_TX_INTFL_OFFCHAN_TX_OK |
+				      IEEE80211_TX_CTL_NO_CCK_RATE;
+			if (local->hw.flags & IEEE80211_HW_QUEUE_CONTROL)
+				info->hw_queue =
+					local->hw.offchannel_tx_hw_queue;
+		}
+
+		__ieee80211_tx_skb_tid_band(rx->sdata, nskb, 7,
+					    status->band);
 	}
 	dev_kfree_skb(rx->skb);
 	return RX_QUEUED;
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 43a45cf..cb34cbb 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -153,7 +153,6 @@ void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb)
 	u8 *elements;
 	struct ieee80211_channel *channel;
 	size_t baselen;
-	bool beacon;
 	struct ieee802_11_elems elems;
 
 	if (skb->len < 24 ||
@@ -175,11 +174,9 @@ void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb)
 
 		elements = mgmt->u.probe_resp.variable;
 		baselen = offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
-		beacon = false;
 	} else {
 		baselen = offsetof(struct ieee80211_mgmt, u.beacon.variable);
 		elements = mgmt->u.beacon.variable;
-		beacon = true;
 	}
 
 	if (baselen > skb->len)
@@ -335,7 +332,7 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local)
 	ieee80211_offchannel_stop_vifs(local);
 
 	/* ensure nullfunc is transmitted before leaving operating channel */
-	drv_flush(local, false);
+	ieee80211_flush_queues(local, NULL);
 
 	ieee80211_configure_filter(local);
 
@@ -671,7 +668,7 @@ static void ieee80211_scan_state_resume(struct ieee80211_local *local,
 	ieee80211_offchannel_stop_vifs(local);
 
 	if (local->ops->flush) {
-		drv_flush(local, false);
+		ieee80211_flush_queues(local, NULL);
 		*next_delay = 0;
 	} else
 		*next_delay = HZ / 10;
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index a79ce82..11216bc 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -342,6 +342,11 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
 	INIT_WORK(&sta->drv_unblock_wk, sta_unblock);
 	INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work);
 	mutex_init(&sta->ampdu_mlme.mtx);
+#ifdef CONFIG_MAC80211_MESH
+	if (ieee80211_vif_is_mesh(&sdata->vif) &&
+	    !sdata->u.mesh.user_mpm)
+		init_timer(&sta->plink_timer);
+#endif
 
 	memcpy(sta->sta.addr, addr, ETH_ALEN);
 	sta->local = local;
@@ -551,6 +556,15 @@ static inline void __bss_tim_clear(u8 *tim, u16 id)
 	tim[id / 8] &= ~(1 << (id % 8));
 }
 
+static inline bool __bss_tim_get(u8 *tim, u16 id)
+{
+	/*
+	 * This format has been mandated by the IEEE specifications,
+	 * so this line may not be changed to use the test_bit() format.
+	 */
+	return tim[id / 8] & (1 << (id % 8));
+}
+
 static unsigned long ieee80211_tids_for_ac(int ac)
 {
 	/* If we ever support TIDs > 7, this obviously needs to be adjusted */
@@ -631,6 +645,9 @@ void sta_info_recalc_tim(struct sta_info *sta)
  done:
 	spin_lock_bh(&local->tim_lock);
 
+	if (indicate_tim == __bss_tim_get(ps->tim, id))
+		goto out_unlock;
+
 	if (indicate_tim)
 		__bss_tim_set(ps->tim, id);
 	else
@@ -642,6 +659,7 @@ void sta_info_recalc_tim(struct sta_info *sta)
 		local->tim_in_locked_section = false;
 	}
 
+out_unlock:
 	spin_unlock_bh(&local->tim_lock);
 }
 
@@ -765,7 +783,7 @@ int __must_check __sta_info_destroy(struct sta_info *sta)
 {
 	struct ieee80211_local *local;
 	struct ieee80211_sub_if_data *sdata;
-	int ret, i;
+	int ret;
 
 	might_sleep();
 
@@ -792,12 +810,8 @@ int __must_check __sta_info_destroy(struct sta_info *sta)
 
 	list_del_rcu(&sta->list);
 
-	mutex_lock(&local->key_mtx);
-	for (i = 0; i < NUM_DEFAULT_KEYS; i++)
-		__ieee80211_key_free(key_mtx_dereference(local, sta->gtk[i]));
-	if (sta->ptk)
-		__ieee80211_key_free(key_mtx_dereference(local, sta->ptk));
-	mutex_unlock(&local->key_mtx);
+	/* this always calls synchronize_net() */
+	ieee80211_free_sta_keys(local, sta);
 
 	sta->dead = true;
 
@@ -1383,30 +1397,16 @@ void ieee80211_sta_block_awake(struct ieee80211_hw *hw,
 }
 EXPORT_SYMBOL(ieee80211_sta_block_awake);
 
-void ieee80211_sta_eosp_irqsafe(struct ieee80211_sta *pubsta)
+void ieee80211_sta_eosp(struct ieee80211_sta *pubsta)
 {
 	struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
 	struct ieee80211_local *local = sta->local;
-	struct sk_buff *skb;
-	struct skb_eosp_msg_data *data;
 
 	trace_api_eosp(local, pubsta);
 
-	skb = alloc_skb(0, GFP_ATOMIC);
-	if (!skb) {
-		/* too bad ... but race is better than loss */
-		clear_sta_flag(sta, WLAN_STA_SP);
-		return;
-	}
-
-	data = (void *)skb->cb;
-	memcpy(data->sta, pubsta->addr, ETH_ALEN);
-	memcpy(data->iface, sta->sdata->vif.addr, ETH_ALEN);
-	skb->pkt_type = IEEE80211_EOSP_MSG;
-	skb_queue_tail(&local->skb_queue, skb);
-	tasklet_schedule(&local->tasklet);
+	clear_sta_flag(sta, WLAN_STA_SP);
 }
-EXPORT_SYMBOL(ieee80211_sta_eosp_irqsafe);
+EXPORT_SYMBOL(ieee80211_sta_eosp);
 
 void ieee80211_sta_set_buffered(struct ieee80211_sta *pubsta,
 				u8 tid, bool buffered)
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 4947341..adc3004 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -281,7 +281,6 @@ struct sta_ampdu_mlme {
  * @plink_state: peer link state
  * @plink_timeout: timeout of peer link
  * @plink_timer: peer link watch timer
- * @plink_timer_was_running: used by suspend/resume to restore timers
  * @t_offset: timing offset relative to this host
  * @t_offset_setpoint: reference timing offset of this sta to be used when
  * 	calculating clockdrift
@@ -334,7 +333,8 @@ struct sta_info {
 	unsigned long driver_buffered_tids;
 
 	/* Updated from RX path only, no locking requirements */
-	unsigned long rx_packets, rx_bytes;
+	unsigned long rx_packets;
+	u64 rx_bytes;
 	unsigned long wep_weak_iv_count;
 	unsigned long last_rx;
 	long last_connected;
@@ -354,9 +354,9 @@ struct sta_info {
 	unsigned int fail_avg;
 
 	/* Updated from TX path only, no locking requirements */
-	unsigned long tx_packets;
-	unsigned long tx_bytes;
-	unsigned long tx_fragments;
+	u32 tx_fragments;
+	u64 tx_packets[IEEE80211_NUM_ACS];
+	u64 tx_bytes[IEEE80211_NUM_ACS];
 	struct ieee80211_tx_rate last_tx_rate;
 	int last_rx_rate_idx;
 	u32 last_rx_rate_flag;
@@ -379,7 +379,6 @@ struct sta_info {
 	__le16 reason;
 	u8 plink_retries;
 	bool ignore_plink_timer;
-	bool plink_timer_was_running;
 	enum nl80211_plink_state plink_state;
 	u32 plink_timeout;
 	struct timer_list plink_timer;
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
index 3d7cd2a..c589979 100644
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
@@ -431,6 +431,30 @@ TRACE_EVENT(drv_prepare_multicast,
 	)
 );
 
+TRACE_EVENT(drv_set_multicast_list,
+	TP_PROTO(struct ieee80211_local *local,
+		 struct ieee80211_sub_if_data *sdata, int mc_count),
+
+	TP_ARGS(local, sdata, mc_count),
+
+	TP_STRUCT__entry(
+		LOCAL_ENTRY
+		__field(bool, allmulti)
+		__field(int, mc_count)
+	),
+
+	TP_fast_assign(
+		LOCAL_ASSIGN;
+		__entry->allmulti = sdata->flags & IEEE80211_SDATA_ALLMULTI;
+		__entry->mc_count = mc_count;
+	),
+
+	TP_printk(
+		LOCAL_PR_FMT " configure mc filter, count=%d, allmulti=%d",
+		LOCAL_PR_ARG, __entry->mc_count, __entry->allmulti
+	)
+);
+
 TRACE_EVENT(drv_configure_filter,
 	TP_PROTO(struct ieee80211_local *local,
 		 unsigned int changed_flags,
@@ -940,23 +964,26 @@ TRACE_EVENT(drv_get_survey,
 );
 
 TRACE_EVENT(drv_flush,
-	TP_PROTO(struct ieee80211_local *local, bool drop),
+	TP_PROTO(struct ieee80211_local *local,
+		 u32 queues, bool drop),
 
-	TP_ARGS(local, drop),
+	TP_ARGS(local, queues, drop),
 
 	TP_STRUCT__entry(
 		LOCAL_ENTRY
 		__field(bool, drop)
+		__field(u32, queues)
 	),
 
 	TP_fast_assign(
 		LOCAL_ASSIGN;
 		__entry->drop = drop;
+		__entry->queues = queues;
 	),
 
 	TP_printk(
-		LOCAL_PR_FMT " drop:%d",
-		LOCAL_PR_ARG, __entry->drop
+		LOCAL_PR_FMT " queues:0x%x drop:%d",
+		LOCAL_PR_ARG, __entry->queues, __entry->drop
 	)
 );
 
@@ -1042,15 +1069,17 @@ TRACE_EVENT(drv_remain_on_channel,
 	TP_PROTO(struct ieee80211_local *local,
 		 struct ieee80211_sub_if_data *sdata,
 		 struct ieee80211_channel *chan,
-		 unsigned int duration),
+		 unsigned int duration,
+		 enum ieee80211_roc_type type),
 
-	TP_ARGS(local, sdata, chan, duration),
+	TP_ARGS(local, sdata, chan, duration, type),
 
 	TP_STRUCT__entry(
 		LOCAL_ENTRY
 		VIF_ENTRY
 		__field(int, center_freq)
 		__field(unsigned int, duration)
+		__field(u32, type)
 	),
 
 	TP_fast_assign(
@@ -1058,12 +1087,13 @@ TRACE_EVENT(drv_remain_on_channel,
 		VIF_ASSIGN;
 		__entry->center_freq = chan->center_freq;
 		__entry->duration = duration;
+		__entry->type = type;
 	),
 
 	TP_printk(
-		LOCAL_PR_FMT  VIF_PR_FMT " freq:%dMHz duration:%dms",
+		LOCAL_PR_FMT  VIF_PR_FMT " freq:%dMHz duration:%dms type=%d",
 		LOCAL_PR_ARG, VIF_PR_ARG,
-		__entry->center_freq, __entry->duration
+		__entry->center_freq, __entry->duration, __entry->type
 	)
 );
 
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 8914d2d..9e67cc9 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -233,6 +233,7 @@ ieee80211_tx_h_dynamic_ps(struct ieee80211_tx_data *tx)
 
 	if (local->hw.conf.flags & IEEE80211_CONF_PS) {
 		ieee80211_stop_queues_by_reason(&local->hw,
+						IEEE80211_MAX_QUEUE_MAP,
 						IEEE80211_QUEUE_STOP_REASON_PS);
 		ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED;
 		ieee80211_queue_work(&local->hw,
@@ -991,15 +992,18 @@ static ieee80211_tx_result debug_noinline
 ieee80211_tx_h_stats(struct ieee80211_tx_data *tx)
 {
 	struct sk_buff *skb;
+	int ac = -1;
 
 	if (!tx->sta)
 		return TX_CONTINUE;
 
-	tx->sta->tx_packets++;
 	skb_queue_walk(&tx->skbs, skb) {
+		ac = skb_get_queue_mapping(skb);
 		tx->sta->tx_fragments++;
-		tx->sta->tx_bytes += skb->len;
+		tx->sta->tx_bytes[ac] += skb->len;
 	}
+	if (ac >= 0)
+		tx->sta->tx_packets[ac]++;
 
 	return TX_CONTINUE;
 }
@@ -2085,7 +2089,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
 		encaps_data = bridge_tunnel_header;
 		encaps_len = sizeof(bridge_tunnel_header);
 		skip_header_bytes -= 2;
-	} else if (ethertype >= 0x600) {
+	} else if (ethertype >= ETH_P_802_3_MIN) {
 		encaps_data = rfc1042_header;
 		encaps_len = sizeof(rfc1042_header);
 		skip_header_bytes -= 2;
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 0f38f43..a736887 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -453,7 +453,8 @@ void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local,
 }
 
 void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw,
-				    enum queue_stop_reason reason)
+				     unsigned long queues,
+				     enum queue_stop_reason reason)
 {
 	struct ieee80211_local *local = hw_to_local(hw);
 	unsigned long flags;
@@ -461,7 +462,7 @@ void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw,
 
 	spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
 
-	for (i = 0; i < hw->queues; i++)
+	for_each_set_bit(i, &queues, hw->queues)
 		__ieee80211_stop_queue(hw, i, reason);
 
 	spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
@@ -469,7 +470,7 @@ void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw,
 
 void ieee80211_stop_queues(struct ieee80211_hw *hw)
 {
-	ieee80211_stop_queues_by_reason(hw,
+	ieee80211_stop_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP,
 					IEEE80211_QUEUE_STOP_REASON_DRIVER);
 }
 EXPORT_SYMBOL(ieee80211_stop_queues);
@@ -491,6 +492,7 @@ int ieee80211_queue_stopped(struct ieee80211_hw *hw, int queue)
 EXPORT_SYMBOL(ieee80211_queue_stopped);
 
 void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw,
+				     unsigned long queues,
 				     enum queue_stop_reason reason)
 {
 	struct ieee80211_local *local = hw_to_local(hw);
@@ -499,7 +501,7 @@ void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw,
 
 	spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
 
-	for (i = 0; i < hw->queues; i++)
+	for_each_set_bit(i, &queues, hw->queues)
 		__ieee80211_wake_queue(hw, i, reason);
 
 	spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
@@ -507,10 +509,42 @@ void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw,
 
 void ieee80211_wake_queues(struct ieee80211_hw *hw)
 {
-	ieee80211_wake_queues_by_reason(hw, IEEE80211_QUEUE_STOP_REASON_DRIVER);
+	ieee80211_wake_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP,
+					IEEE80211_QUEUE_STOP_REASON_DRIVER);
 }
 EXPORT_SYMBOL(ieee80211_wake_queues);
 
+void ieee80211_flush_queues(struct ieee80211_local *local,
+			    struct ieee80211_sub_if_data *sdata)
+{
+	u32 queues;
+
+	if (!local->ops->flush)
+		return;
+
+	if (sdata && local->hw.flags & IEEE80211_HW_QUEUE_CONTROL) {
+		int ac;
+
+		queues = 0;
+
+		for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
+			queues |= BIT(sdata->vif.hw_queue[ac]);
+		if (sdata->vif.cab_queue != IEEE80211_INVAL_HW_QUEUE)
+			queues |= BIT(sdata->vif.cab_queue);
+	} else {
+		/* all queues */
+		queues = BIT(local->hw.queues) - 1;
+	}
+
+	ieee80211_stop_queues_by_reason(&local->hw, IEEE80211_MAX_QUEUE_MAP,
+					IEEE80211_QUEUE_STOP_REASON_FLUSH);
+
+	drv_flush(local, queues, false);
+
+	ieee80211_wake_queues_by_reason(&local->hw, IEEE80211_MAX_QUEUE_MAP,
+					IEEE80211_QUEUE_STOP_REASON_FLUSH);
+}
+
 void ieee80211_iterate_active_interfaces(
 	struct ieee80211_hw *hw, u32 iter_flags,
 	void (*iterator)(void *data, u8 *mac,
@@ -1357,6 +1391,25 @@ void ieee80211_stop_device(struct ieee80211_local *local)
 	drv_stop(local);
 }
 
+static void ieee80211_assign_chanctx(struct ieee80211_local *local,
+				     struct ieee80211_sub_if_data *sdata)
+{
+	struct ieee80211_chanctx_conf *conf;
+	struct ieee80211_chanctx *ctx;
+
+	if (!local->use_chanctx)
+		return;
+
+	mutex_lock(&local->chanctx_mtx);
+	conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
+					 lockdep_is_held(&local->chanctx_mtx));
+	if (conf) {
+		ctx = container_of(conf, struct ieee80211_chanctx, conf);
+		drv_assign_vif_chanctx(local, sdata, ctx);
+	}
+	mutex_unlock(&local->chanctx_mtx);
+}
+
 int ieee80211_reconfig(struct ieee80211_local *local)
 {
 	struct ieee80211_hw *hw = &local->hw;
@@ -1445,36 +1498,14 @@ int ieee80211_reconfig(struct ieee80211_local *local)
 	}
 
 	list_for_each_entry(sdata, &local->interfaces, list) {
-		struct ieee80211_chanctx_conf *ctx_conf;
-
 		if (!ieee80211_sdata_running(sdata))
 			continue;
-
-		mutex_lock(&local->chanctx_mtx);
-		ctx_conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
-				lockdep_is_held(&local->chanctx_mtx));
-		if (ctx_conf) {
-			ctx = container_of(ctx_conf, struct ieee80211_chanctx,
-					   conf);
-			drv_assign_vif_chanctx(local, sdata, ctx);
-		}
-		mutex_unlock(&local->chanctx_mtx);
+		ieee80211_assign_chanctx(local, sdata);
 	}
 
 	sdata = rtnl_dereference(local->monitor_sdata);
-	if (sdata && local->use_chanctx && ieee80211_sdata_running(sdata)) {
-		struct ieee80211_chanctx_conf *ctx_conf;
-
-		mutex_lock(&local->chanctx_mtx);
-		ctx_conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
-				lockdep_is_held(&local->chanctx_mtx));
-		if (ctx_conf) {
-			ctx = container_of(ctx_conf, struct ieee80211_chanctx,
-					   conf);
-			drv_assign_vif_chanctx(local, sdata, ctx);
-		}
-		mutex_unlock(&local->chanctx_mtx);
-	}
+	if (sdata && ieee80211_sdata_running(sdata))
+		ieee80211_assign_chanctx(local, sdata);
 
 	/* add STAs back */
 	mutex_lock(&local->sta_mtx);
@@ -1534,11 +1565,6 @@ int ieee80211_reconfig(struct ieee80211_local *local)
 			  BSS_CHANGED_IDLE |
 			  BSS_CHANGED_TXPOWER;
 
-#ifdef CONFIG_PM
-		if (local->resuming && !reconfig_due_to_wowlan)
-			sdata->vif.bss_conf = sdata->suspend_bss_conf;
-#endif
-
 		switch (sdata->vif.type) {
 		case NL80211_IFTYPE_STATION:
 			changed |= BSS_CHANGED_ASSOC |
@@ -1659,8 +1685,8 @@ int ieee80211_reconfig(struct ieee80211_local *local)
 		mutex_unlock(&local->sta_mtx);
 	}
 
-	ieee80211_wake_queues_by_reason(hw,
-			IEEE80211_QUEUE_STOP_REASON_SUSPEND);
+	ieee80211_wake_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP,
+					IEEE80211_QUEUE_STOP_REASON_SUSPEND);
 
 	/*
 	 * If this is for hw restart things are still running.
@@ -1678,28 +1704,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
 	mb();
 	local->resuming = false;
 
-	list_for_each_entry(sdata, &local->interfaces, list) {
-		switch(sdata->vif.type) {
-		case NL80211_IFTYPE_STATION:
-			ieee80211_sta_restart(sdata);
-			break;
-		case NL80211_IFTYPE_ADHOC:
-			ieee80211_ibss_restart(sdata);
-			break;
-		case NL80211_IFTYPE_MESH_POINT:
-			ieee80211_mesh_restart(sdata);
-			break;
-		default:
-			break;
-		}
-	}
-
 	mod_timer(&local->sta_cleanup, jiffies + 1);
-
-	mutex_lock(&local->sta_mtx);
-	list_for_each_entry(sta, &local->sta_list, list)
-		mesh_plink_restart(sta);
-	mutex_unlock(&local->sta_mtx);
 #else
 	WARN_ON(1);
 #endif
diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c
index a2c2258..171344d 100644
--- a/net/mac80211/vht.c
+++ b/net/mac80211/vht.c
@@ -13,6 +13,104 @@
 #include "rate.h"
 
 
+static void __check_vhtcap_disable(struct ieee80211_sub_if_data *sdata,
+				   struct ieee80211_sta_vht_cap *vht_cap,
+				   u32 flag)
+{
+	__le32 le_flag = cpu_to_le32(flag);
+
+	if (sdata->u.mgd.vht_capa_mask.vht_cap_info & le_flag &&
+	    !(sdata->u.mgd.vht_capa.vht_cap_info & le_flag))
+		vht_cap->cap &= ~flag;
+}
+
+void ieee80211_apply_vhtcap_overrides(struct ieee80211_sub_if_data *sdata,
+				      struct ieee80211_sta_vht_cap *vht_cap)
+{
+	int i;
+	u16 rxmcs_mask, rxmcs_cap, rxmcs_n, txmcs_mask, txmcs_cap, txmcs_n;
+
+	if (!vht_cap->vht_supported)
+		return;
+
+	if (sdata->vif.type != NL80211_IFTYPE_STATION)
+		return;
+
+	__check_vhtcap_disable(sdata, vht_cap,
+			       IEEE80211_VHT_CAP_RXLDPC);
+	__check_vhtcap_disable(sdata, vht_cap,
+			       IEEE80211_VHT_CAP_SHORT_GI_80);
+	__check_vhtcap_disable(sdata, vht_cap,
+			       IEEE80211_VHT_CAP_SHORT_GI_160);
+	__check_vhtcap_disable(sdata, vht_cap,
+			       IEEE80211_VHT_CAP_TXSTBC);
+	__check_vhtcap_disable(sdata, vht_cap,
+			       IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE);
+	__check_vhtcap_disable(sdata, vht_cap,
+			       IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE);
+	__check_vhtcap_disable(sdata, vht_cap,
+			       IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN);
+	__check_vhtcap_disable(sdata, vht_cap,
+			       IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN);
+
+	/* Allow user to decrease AMPDU length exponent */
+	if (sdata->u.mgd.vht_capa_mask.vht_cap_info &
+	    cpu_to_le32(IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK)) {
+		u32 cap, n;
+
+		n = le32_to_cpu(sdata->u.mgd.vht_capa.vht_cap_info) &
+			IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;
+		n >>= IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT;
+		cap = vht_cap->cap & IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;
+		cap >>= IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT;
+
+		if (n < cap) {
+			vht_cap->cap &=
+				~IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;
+			vht_cap->cap |=
+				n << IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT;
+		}
+	}
+
+	/* Allow the user to decrease MCSes */
+	rxmcs_mask =
+		le16_to_cpu(sdata->u.mgd.vht_capa_mask.supp_mcs.rx_mcs_map);
+	rxmcs_n = le16_to_cpu(sdata->u.mgd.vht_capa.supp_mcs.rx_mcs_map);
+	rxmcs_n &= rxmcs_mask;
+	rxmcs_cap = le16_to_cpu(vht_cap->vht_mcs.rx_mcs_map);
+
+	txmcs_mask =
+		le16_to_cpu(sdata->u.mgd.vht_capa_mask.supp_mcs.tx_mcs_map);
+	txmcs_n = le16_to_cpu(sdata->u.mgd.vht_capa.supp_mcs.tx_mcs_map);
+	txmcs_n &= txmcs_mask;
+	txmcs_cap = le16_to_cpu(vht_cap->vht_mcs.tx_mcs_map);
+	for (i = 0; i < 8; i++) {
+		u8 m, n, c;
+
+		m = (rxmcs_mask >> 2*i) & IEEE80211_VHT_MCS_NOT_SUPPORTED;
+		n = (rxmcs_n >> 2*i) & IEEE80211_VHT_MCS_NOT_SUPPORTED;
+		c = (rxmcs_cap >> 2*i) & IEEE80211_VHT_MCS_NOT_SUPPORTED;
+
+		if (m && ((c != IEEE80211_VHT_MCS_NOT_SUPPORTED && n < c) ||
+			  n == IEEE80211_VHT_MCS_NOT_SUPPORTED)) {
+			rxmcs_cap &= ~(3 << 2*i);
+			rxmcs_cap |= (rxmcs_n & (3 << 2*i));
+		}
+
+		m = (txmcs_mask >> 2*i) & IEEE80211_VHT_MCS_NOT_SUPPORTED;
+		n = (txmcs_n >> 2*i) & IEEE80211_VHT_MCS_NOT_SUPPORTED;
+		c = (txmcs_cap >> 2*i) & IEEE80211_VHT_MCS_NOT_SUPPORTED;
+
+		if (m && ((c != IEEE80211_VHT_MCS_NOT_SUPPORTED && n < c) ||
+			  n == IEEE80211_VHT_MCS_NOT_SUPPORTED)) {
+			txmcs_cap &= ~(3 << 2*i);
+			txmcs_cap |= (txmcs_n & (3 << 2*i));
+		}
+	}
+	vht_cap->vht_mcs.rx_mcs_map = cpu_to_le16(rxmcs_cap);
+	vht_cap->vht_mcs.tx_mcs_map = cpu_to_le16(txmcs_cap);
+}
+
 void
 ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
 				    struct ieee80211_supported_band *sband,
@@ -20,6 +118,8 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
 				    struct sta_info *sta)
 {
 	struct ieee80211_sta_vht_cap *vht_cap = &sta->sta.vht_cap;
+	struct ieee80211_sta_vht_cap own_cap;
+	u32 cap_info, i;
 
 	memset(vht_cap, 0, sizeof(*vht_cap));
 
@@ -35,12 +135,122 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
 
 	vht_cap->vht_supported = true;
 
-	vht_cap->cap = le32_to_cpu(vht_cap_ie->vht_cap_info);
+	own_cap = sband->vht_cap;
+	/*
+	 * If user has specified capability overrides, take care
+	 * of that if the station we're setting up is the AP that
+	 * we advertised a restricted capability set to. Override
+	 * our own capabilities and then use those below.
+	 */
+	if (sdata->vif.type == NL80211_IFTYPE_STATION &&
+	    !test_sta_flag(sta, WLAN_STA_TDLS_PEER))
+		ieee80211_apply_vhtcap_overrides(sdata, &own_cap);
+
+	/* take some capabilities as-is */
+	cap_info = le32_to_cpu(vht_cap_ie->vht_cap_info);
+	vht_cap->cap = cap_info;
+	vht_cap->cap &= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895 |
+			IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 |
+			IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 |
+			IEEE80211_VHT_CAP_RXLDPC |
+			IEEE80211_VHT_CAP_VHT_TXOP_PS |
+			IEEE80211_VHT_CAP_HTC_VHT |
+			IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK |
+			IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_UNSOL_MFB |
+			IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB |
+			IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN |
+			IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN;
+
+	/* and some based on our own capabilities */
+	switch (own_cap.cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) {
+	case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ:
+		vht_cap->cap |= cap_info &
+				IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
+		break;
+	case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ:
+		vht_cap->cap |= cap_info &
+				IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK;
+		break;
+	default:
+		/* nothing */
+		break;
+	}
+
+	/* symmetric capabilities */
+	vht_cap->cap |= cap_info & own_cap.cap &
+			(IEEE80211_VHT_CAP_SHORT_GI_80 |
+			 IEEE80211_VHT_CAP_SHORT_GI_160);
+
+	/* remaining ones */
+	if (own_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE) {
+		vht_cap->cap |= cap_info &
+				(IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE |
+				 IEEE80211_VHT_CAP_BEAMFORMER_ANTENNAS_MAX |
+				 IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MAX);
+	}
+
+	if (own_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE)
+		vht_cap->cap |= cap_info &
+				IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE;
+
+	if (own_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE)
+		vht_cap->cap |= cap_info &
+				IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE;
+
+	if (own_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE)
+		vht_cap->cap |= cap_info &
+				IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE;
+
+	if (own_cap.cap & IEEE80211_VHT_CAP_TXSTBC)
+		vht_cap->cap |= cap_info & IEEE80211_VHT_CAP_RXSTBC_MASK;
+
+	if (own_cap.cap & IEEE80211_VHT_CAP_RXSTBC_MASK)
+		vht_cap->cap |= cap_info & IEEE80211_VHT_CAP_TXSTBC;
 
 	/* Copy peer MCS info, the driver might need them. */
 	memcpy(&vht_cap->vht_mcs, &vht_cap_ie->supp_mcs,
 	       sizeof(struct ieee80211_vht_mcs_info));
 
+	/* but also restrict MCSes */
+	for (i = 0; i < 8; i++) {
+		u16 own_rx, own_tx, peer_rx, peer_tx;
+
+		own_rx = le16_to_cpu(own_cap.vht_mcs.rx_mcs_map);
+		own_rx = (own_rx >> i * 2) & IEEE80211_VHT_MCS_NOT_SUPPORTED;
+
+		own_tx = le16_to_cpu(own_cap.vht_mcs.tx_mcs_map);
+		own_tx = (own_tx >> i * 2) & IEEE80211_VHT_MCS_NOT_SUPPORTED;
+
+		peer_rx = le16_to_cpu(vht_cap->vht_mcs.rx_mcs_map);
+		peer_rx = (peer_rx >> i * 2) & IEEE80211_VHT_MCS_NOT_SUPPORTED;
+
+		peer_tx = le16_to_cpu(vht_cap->vht_mcs.tx_mcs_map);
+		peer_tx = (peer_tx >> i * 2) & IEEE80211_VHT_MCS_NOT_SUPPORTED;
+
+		if (peer_tx != IEEE80211_VHT_MCS_NOT_SUPPORTED) {
+			if (own_rx == IEEE80211_VHT_MCS_NOT_SUPPORTED)
+				peer_tx = IEEE80211_VHT_MCS_NOT_SUPPORTED;
+			else if (own_rx < peer_tx)
+				peer_tx = own_rx;
+		}
+
+		if (peer_rx != IEEE80211_VHT_MCS_NOT_SUPPORTED) {
+			if (own_tx == IEEE80211_VHT_MCS_NOT_SUPPORTED)
+				peer_rx = IEEE80211_VHT_MCS_NOT_SUPPORTED;
+			else if (own_tx < peer_rx)
+				peer_rx = own_tx;
+		}
+
+		vht_cap->vht_mcs.rx_mcs_map &=
+			~cpu_to_le16(IEEE80211_VHT_MCS_NOT_SUPPORTED << i * 2);
+		vht_cap->vht_mcs.rx_mcs_map |= cpu_to_le16(peer_rx << i * 2);
+
+		vht_cap->vht_mcs.tx_mcs_map &=
+			~cpu_to_le16(IEEE80211_VHT_MCS_NOT_SUPPORTED << i * 2);
+		vht_cap->vht_mcs.tx_mcs_map |= cpu_to_le16(peer_tx << i * 2);
+	}
+
+	/* finally set up the bandwidth */
 	switch (vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) {
 	case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ:
 	case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ:
diff --git a/net/mac802154/mac802154.h b/net/mac802154/mac802154.h
index a4dcaf1..21fa386 100644
--- a/net/mac802154/mac802154.h
+++ b/net/mac802154/mac802154.h
@@ -114,5 +114,6 @@ void mac802154_dev_set_ieee_addr(struct net_device *dev);
 u16 mac802154_dev_get_pan_id(const struct net_device *dev);
 void mac802154_dev_set_pan_id(struct net_device *dev, u16 val);
 void mac802154_dev_set_page_channel(struct net_device *dev, u8 page, u8 chan);
+u8 mac802154_dev_get_dsn(const struct net_device *dev);
 
 #endif /* MAC802154_H */
diff --git a/net/mac802154/mac_cmd.c b/net/mac802154/mac_cmd.c
index d8d2770..a99910d 100644
--- a/net/mac802154/mac_cmd.c
+++ b/net/mac802154/mac_cmd.c
@@ -73,4 +73,5 @@ struct ieee802154_mlme_ops mac802154_mlme_wpan = {
 	.start_req = mac802154_mlme_start_req,
 	.get_pan_id = mac802154_dev_get_pan_id,
 	.get_short_addr = mac802154_dev_get_short_addr,
+	.get_dsn = mac802154_dev_get_dsn,
 };
diff --git a/net/mac802154/mib.c b/net/mac802154/mib.c
index f47781a..f03e55f 100644
--- a/net/mac802154/mib.c
+++ b/net/mac802154/mib.c
@@ -159,6 +159,15 @@ void mac802154_dev_set_pan_id(struct net_device *dev, u16 val)
 	}
 }
 
+u8 mac802154_dev_get_dsn(const struct net_device *dev)
+{
+	struct mac802154_sub_if_data *priv = netdev_priv(dev);
+
+	BUG_ON(dev->type != ARPHRD_IEEE802154);
+
+	return priv->dsn++;
+}
+
 static void phy_chan_notify(struct work_struct *work)
 {
 	struct phy_chan_notify_work *nw = container_of(work,
diff --git a/net/mac802154/wpan.c b/net/mac802154/wpan.c
index d20c6d3..7d3f659 100644
--- a/net/mac802154/wpan.c
+++ b/net/mac802154/wpan.c
@@ -145,6 +145,8 @@ static int mac802154_header_create(struct sk_buff *skb,
 
 	head[pos++] = mac_cb(skb)->seq; /* DSN/BSN */
 	fc = mac_cb_type(skb);
+	if (mac_cb_is_ackreq(skb))
+		fc |= IEEE802154_FC_ACK_REQ;
 
 	if (!saddr) {
 		spin_lock_bh(&priv->mib_lock);
diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c
index 1ba9dbc..86f5e26 100644
--- a/net/netfilter/ipset/ip_set_core.c
+++ b/net/netfilter/ipset/ip_set_core.c
@@ -15,7 +15,6 @@
 #include <linux/ip.h>
 #include <linux/skbuff.h>
 #include <linux/spinlock.h>
-#include <linux/netlink.h>
 #include <linux/rculist.h>
 #include <net/netlink.h>
 
@@ -1085,7 +1084,7 @@ static int
 dump_init(struct netlink_callback *cb)
 {
 	struct nlmsghdr *nlh = nlmsg_hdr(cb->skb);
-	int min_len = NLMSG_SPACE(sizeof(struct nfgenmsg));
+	int min_len = nlmsg_total_size(sizeof(struct nfgenmsg));
 	struct nlattr *cda[IPSET_ATTR_CMD_MAX+1];
 	struct nlattr *attr = (void *)nlh + min_len;
 	u32 dump_type;
@@ -1301,7 +1300,7 @@ call_ad(struct sock *ctnl, struct sk_buff *skb, struct ip_set *set,
 		struct sk_buff *skb2;
 		struct nlmsgerr *errmsg;
 		size_t payload = sizeof(*errmsg) + nlmsg_len(nlh);
-		int min_len = NLMSG_SPACE(sizeof(struct nfgenmsg));
+		int min_len = nlmsg_total_size(sizeof(struct nfgenmsg));
 		struct nlattr *cda[IPSET_ATTR_CMD_MAX+1];
 		struct nlattr *cmdattr;
 		u32 *errline;
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
index 61f49d2..2aef23e 100644
--- a/net/netfilter/ipvs/ip_vs_core.c
+++ b/net/netfilter/ipvs/ip_vs_core.c
@@ -69,10 +69,7 @@ EXPORT_SYMBOL(ip_vs_conn_put);
 EXPORT_SYMBOL(ip_vs_get_debug_level);
 #endif
 
-int ip_vs_net_id __read_mostly;
-#ifdef IP_VS_GENERIC_NETNS
-EXPORT_SYMBOL(ip_vs_net_id);
-#endif
+static int ip_vs_net_id __read_mostly;
 /* netns cnt used for uniqueness */
 static atomic_t ipvs_netns_cnt = ATOMIC_INIT(0);
 
@@ -1181,9 +1178,6 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af)
 						iph.len)))) {
 #ifdef CONFIG_IP_VS_IPV6
 				if (af == AF_INET6) {
-					struct net *net =
-						dev_net(skb_dst(skb)->dev);
-
 					if (!skb->dev)
 						skb->dev = net->loopback_dev;
 					icmpv6_send(skb,
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index 9e2d1cc..6f8048c 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -271,16 +271,18 @@ ip_vs_svc_hashkey(struct net *net, int af, unsigned int proto,
 {
 	register unsigned int porth = ntohs(port);
 	__be32 addr_fold = addr->ip;
+	__u32 ahash;
 
 #ifdef CONFIG_IP_VS_IPV6
 	if (af == AF_INET6)
 		addr_fold = addr->ip6[0]^addr->ip6[1]^
 			    addr->ip6[2]^addr->ip6[3];
 #endif
-	addr_fold ^= ((size_t)net>>8);
+	ahash = ntohl(addr_fold);
+	ahash ^= ((size_t) net >> 8);
 
-	return (proto^ntohl(addr_fold)^(porth>>IP_VS_SVC_TAB_BITS)^porth)
-		& IP_VS_SVC_TAB_MASK;
+	return (proto ^ ahash ^ (porth >> IP_VS_SVC_TAB_BITS) ^ porth) &
+	       IP_VS_SVC_TAB_MASK;
 }
 
 /*
@@ -1747,9 +1749,9 @@ static struct ctl_table vs_vars[] = {
 	},
 	{
 		.procname	= "sync_qlen_max",
-		.maxlen		= sizeof(int),
+		.maxlen		= sizeof(unsigned long),
 		.mode		= 0644,
-		.proc_handler	= proc_dointvec,
+		.proc_handler	= proc_doulongvec_minmax,
 	},
 	{
 		.procname	= "sync_sock_size",
diff --git a/net/netfilter/ipvs/ip_vs_est.c b/net/netfilter/ipvs/ip_vs_est.c
index 0fac601..6bee6d0 100644
--- a/net/netfilter/ipvs/ip_vs_est.c
+++ b/net/netfilter/ipvs/ip_vs_est.c
@@ -56,7 +56,7 @@
  * Make a summary from each cpu
  */
 static void ip_vs_read_cpu_stats(struct ip_vs_stats_user *sum,
-				 struct ip_vs_cpu_stats *stats)
+				 struct ip_vs_cpu_stats __percpu *stats)
 {
 	int i;
 
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index c8e001a..f993ffc 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -48,6 +48,7 @@
 #include <net/netfilter/nf_conntrack_labels.h>
 #include <net/netfilter/nf_nat.h>
 #include <net/netfilter/nf_nat_core.h>
+#include <net/netfilter/nf_nat_helper.h>
 
 #define NF_CONNTRACK_VERSION	"0.5.0"
 
@@ -264,7 +265,7 @@ static void death_by_event(unsigned long ul_conntrack)
 	if (nf_conntrack_event(IPCT_DESTROY, ct) < 0) {
 		/* bad luck, let's retry again */
 		ecache->timeout.expires = jiffies +
-			(random32() % net->ct.sysctl_events_retry_timeout);
+			(prandom_u32() % net->ct.sysctl_events_retry_timeout);
 		add_timer(&ecache->timeout);
 		return;
 	}
@@ -283,7 +284,7 @@ void nf_ct_dying_timeout(struct nf_conn *ct)
 	/* set a new timer to retry event delivery */
 	setup_timer(&ecache->timeout, death_by_event, (unsigned long)ct);
 	ecache->timeout.expires = jiffies +
-		(random32() % net->ct.sysctl_events_retry_timeout);
+		(prandom_u32() % net->ct.sysctl_events_retry_timeout);
 	add_timer(&ecache->timeout);
 }
 EXPORT_SYMBOL_GPL(nf_ct_dying_timeout);
@@ -1364,30 +1365,48 @@ void nf_conntrack_cleanup_end(void)
  */
 void nf_conntrack_cleanup_net(struct net *net)
 {
+	LIST_HEAD(single);
+
+	list_add(&net->exit_list, &single);
+	nf_conntrack_cleanup_net_list(&single);
+}
+
+void nf_conntrack_cleanup_net_list(struct list_head *net_exit_list)
+{
+	int busy;
+	struct net *net;
+
 	/*
 	 * This makes sure all current packets have passed through
 	 *  netfilter framework.  Roll on, two-stage module
 	 *  delete...
 	 */
 	synchronize_net();
- i_see_dead_people:
-	nf_ct_iterate_cleanup(net, kill_all, NULL);
-	nf_ct_release_dying_list(net);
-	if (atomic_read(&net->ct.count) != 0) {
+i_see_dead_people:
+	busy = 0;
+	list_for_each_entry(net, net_exit_list, exit_list) {
+		nf_ct_iterate_cleanup(net, kill_all, NULL);
+		nf_ct_release_dying_list(net);
+		if (atomic_read(&net->ct.count) != 0)
+			busy = 1;
+	}
+	if (busy) {
 		schedule();
 		goto i_see_dead_people;
 	}
 
-	nf_ct_free_hashtable(net->ct.hash, net->ct.htable_size);
-	nf_conntrack_proto_pernet_fini(net);
-	nf_conntrack_helper_pernet_fini(net);
-	nf_conntrack_ecache_pernet_fini(net);
-	nf_conntrack_tstamp_pernet_fini(net);
-	nf_conntrack_acct_pernet_fini(net);
-	nf_conntrack_expect_pernet_fini(net);
-	kmem_cache_destroy(net->ct.nf_conntrack_cachep);
-	kfree(net->ct.slabname);
-	free_percpu(net->ct.stat);
+	list_for_each_entry(net, net_exit_list, exit_list) {
+		nf_ct_free_hashtable(net->ct.hash, net->ct.htable_size);
+		nf_conntrack_proto_pernet_fini(net);
+		nf_conntrack_helper_pernet_fini(net);
+		nf_conntrack_ecache_pernet_fini(net);
+		nf_conntrack_tstamp_pernet_fini(net);
+		nf_conntrack_acct_pernet_fini(net);
+		nf_conntrack_expect_pernet_fini(net);
+		kmem_cache_destroy(net->ct.nf_conntrack_cachep);
+		kfree(net->ct.slabname);
+		free_percpu(net->ct.stat);
+	}
 }
 
 void *nf_ct_alloc_hashtable(unsigned int *sizep, int nulls)
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 9904b15..6d0f8a1 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -2409,6 +2409,92 @@ out:
 	return skb->len;
 }
 
+static int
+ctnetlink_exp_ct_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
+{
+	struct nf_conntrack_expect *exp, *last;
+	struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh);
+	struct nf_conn *ct = cb->data;
+	struct nf_conn_help *help = nfct_help(ct);
+	u_int8_t l3proto = nfmsg->nfgen_family;
+
+	if (cb->args[0])
+		return 0;
+
+	rcu_read_lock();
+	last = (struct nf_conntrack_expect *)cb->args[1];
+restart:
+	hlist_for_each_entry(exp, &help->expectations, lnode) {
+		if (l3proto && exp->tuple.src.l3num != l3proto)
+			continue;
+		if (cb->args[1]) {
+			if (exp != last)
+				continue;
+			cb->args[1] = 0;
+		}
+		if (ctnetlink_exp_fill_info(skb, NETLINK_CB(cb->skb).portid,
+					    cb->nlh->nlmsg_seq,
+					    IPCTNL_MSG_EXP_NEW,
+					    exp) < 0) {
+			if (!atomic_inc_not_zero(&exp->use))
+				continue;
+			cb->args[1] = (unsigned long)exp;
+			goto out;
+		}
+	}
+	if (cb->args[1]) {
+		cb->args[1] = 0;
+		goto restart;
+	}
+	cb->args[0] = 1;
+out:
+	rcu_read_unlock();
+	if (last)
+		nf_ct_expect_put(last);
+
+	return skb->len;
+}
+
+static int ctnetlink_dump_exp_ct(struct sock *ctnl, struct sk_buff *skb,
+				 const struct nlmsghdr *nlh,
+				 const struct nlattr * const cda[])
+{
+	int err;
+	struct net *net = sock_net(ctnl);
+	struct nfgenmsg *nfmsg = nlmsg_data(nlh);
+	u_int8_t u3 = nfmsg->nfgen_family;
+	struct nf_conntrack_tuple tuple;
+	struct nf_conntrack_tuple_hash *h;
+	struct nf_conn *ct;
+	u16 zone = 0;
+	struct netlink_dump_control c = {
+		.dump = ctnetlink_exp_ct_dump_table,
+		.done = ctnetlink_exp_done,
+	};
+
+	err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_MASTER, u3);
+	if (err < 0)
+		return err;
+
+	if (cda[CTA_EXPECT_ZONE]) {
+		err = ctnetlink_parse_zone(cda[CTA_EXPECT_ZONE], &zone);
+		if (err < 0)
+			return err;
+	}
+
+	h = nf_conntrack_find_get(net, zone, &tuple);
+	if (!h)
+		return -ENOENT;
+
+	ct = nf_ct_tuplehash_to_ctrack(h);
+	c.data = ct;
+
+	err = netlink_dump_start(ctnl, skb, nlh, &c);
+	nf_ct_put(ct);
+
+	return err;
+}
+
 static const struct nla_policy exp_nla_policy[CTA_EXPECT_MAX+1] = {
 	[CTA_EXPECT_MASTER]	= { .type = NLA_NESTED },
 	[CTA_EXPECT_TUPLE]	= { .type = NLA_NESTED },
@@ -2439,11 +2525,15 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb,
 	int err;
 
 	if (nlh->nlmsg_flags & NLM_F_DUMP) {
-		struct netlink_dump_control c = {
-			.dump = ctnetlink_exp_dump_table,
-			.done = ctnetlink_exp_done,
-		};
-		return netlink_dump_start(ctnl, skb, nlh, &c);
+		if (cda[CTA_EXPECT_MASTER])
+			return ctnetlink_dump_exp_ct(ctnl, skb, nlh, cda);
+		else {
+			struct netlink_dump_control c = {
+				.dump = ctnetlink_exp_dump_table,
+				.done = ctnetlink_exp_done,
+			};
+			return netlink_dump_start(ctnl, skb, nlh, &c);
+		}
 	}
 
 	err = ctnetlink_parse_zone(cda[CTA_EXPECT_ZONE], &zone);
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index 6bcce40..ebb67d3 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -545,16 +545,20 @@ out_init:
 	return ret;
 }
 
-static void nf_conntrack_pernet_exit(struct net *net)
+static void nf_conntrack_pernet_exit(struct list_head *net_exit_list)
 {
-	nf_conntrack_standalone_fini_sysctl(net);
-	nf_conntrack_standalone_fini_proc(net);
-	nf_conntrack_cleanup_net(net);
+	struct net *net;
+
+	list_for_each_entry(net, net_exit_list, exit_list) {
+		nf_conntrack_standalone_fini_sysctl(net);
+		nf_conntrack_standalone_fini_proc(net);
+	}
+	nf_conntrack_cleanup_net_list(net_exit_list);
 }
 
 static struct pernet_operations nf_conntrack_net_ops = {
-	.init = nf_conntrack_pernet_init,
-	.exit = nf_conntrack_pernet_exit,
+	.init		= nf_conntrack_pernet_init,
+	.exit_batch	= nf_conntrack_pernet_exit,
 };
 
 static int __init nf_conntrack_standalone_init(void)
@@ -568,6 +572,7 @@ static int __init nf_conntrack_standalone_init(void)
 		register_net_sysctl(&init_net, "net", nf_ct_netfilter_table);
 	if (!nf_ct_netfilter_header) {
 		pr_err("nf_conntrack: can't register to sysctl.\n");
+		ret = -ENOMEM;
 		goto out_sysctl;
 	}
 #endif
diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c
index 0b1b32c..bc4c499 100644
--- a/net/netfilter/nfnetlink.c
+++ b/net/netfilter/nfnetlink.c
@@ -24,10 +24,9 @@
 #include <linux/skbuff.h>
 #include <asm/uaccess.h>
 #include <net/sock.h>
-#include <net/netlink.h>
 #include <linux/init.h>
 
-#include <linux/netlink.h>
+#include <net/netlink.h>
 #include <linux/netfilter/nfnetlink.h>
 
 MODULE_LICENSE("GPL");
@@ -144,7 +143,7 @@ static int nfnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 		return -EPERM;
 
 	/* All the messages must at least contain nfgenmsg */
-	if (nlh->nlmsg_len < NLMSG_LENGTH(sizeof(struct nfgenmsg)))
+	if (nlmsg_len(nlh) < sizeof(struct nfgenmsg))
 		return 0;
 
 	type = nlh->nlmsg_type;
@@ -172,7 +171,7 @@ replay:
 	}
 
 	{
-		int min_len = NLMSG_SPACE(sizeof(struct nfgenmsg));
+		int min_len = nlmsg_total_size(sizeof(struct nfgenmsg));
 		u_int8_t cb_id = NFNL_MSG_TYPE(nlh->nlmsg_type);
 		struct nlattr *cda[ss->cb[cb_id].attr_count + 1];
 		struct nlattr *attr = (void *)nlh + min_len;
diff --git a/net/netfilter/nfnetlink_acct.c b/net/netfilter/nfnetlink_acct.c
index 589d686..dc3fd5d 100644
--- a/net/netfilter/nfnetlink_acct.c
+++ b/net/netfilter/nfnetlink_acct.c
@@ -49,6 +49,8 @@ nfnl_acct_new(struct sock *nfnl, struct sk_buff *skb,
 		return -EINVAL;
 
 	acct_name = nla_data(tb[NFACCT_NAME]);
+	if (strlen(acct_name) == 0)
+		return -EINVAL;
 
 	list_for_each_entry(nfacct, &nfnl_acct_list, head) {
 		if (strncmp(nfacct->name, acct_name, NFACCT_NAME_MAX) != 0)
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
index f248db5..4a2593f 100644
--- a/net/netfilter/nfnetlink_log.c
+++ b/net/netfilter/nfnetlink_log.c
@@ -19,7 +19,7 @@
 #include <linux/ipv6.h>
 #include <linux/netdevice.h>
 #include <linux/netfilter.h>
-#include <linux/netlink.h>
+#include <net/netlink.h>
 #include <linux/netfilter/nfnetlink.h>
 #include <linux/netfilter/nfnetlink_log.h>
 #include <linux/spinlock.h>
@@ -609,7 +609,7 @@ nfulnl_log_packet(u_int8_t pf,
 	/* FIXME: do we want to make the size calculation conditional based on
 	 * what is actually present?  way more branches and checks, but more
 	 * memory efficient... */
-	size =    NLMSG_SPACE(sizeof(struct nfgenmsg))
+	size =    nlmsg_total_size(sizeof(struct nfgenmsg))
 		+ nla_total_size(sizeof(struct nfulnl_msg_packet_hdr))
 		+ nla_total_size(sizeof(u_int32_t))	/* ifindex */
 		+ nla_total_size(sizeof(u_int32_t))	/* ifindex */
diff --git a/net/netfilter/nfnetlink_queue_core.c b/net/netfilter/nfnetlink_queue_core.c
index 1cb4854..bdae5e6 100644
--- a/net/netfilter/nfnetlink_queue_core.c
+++ b/net/netfilter/nfnetlink_queue_core.c
@@ -73,7 +73,7 @@ static struct hlist_head instance_table[INSTANCE_BUCKETS] __read_mostly;
 
 static inline u_int8_t instance_hashfn(u_int16_t queue_num)
 {
-	return ((queue_num >> 8) | queue_num) % INSTANCE_BUCKETS;
+	return ((queue_num >> 8) ^ queue_num) % INSTANCE_BUCKETS;
 }
 
 static struct nfqnl_instance *
@@ -217,14 +217,59 @@ nfqnl_flush(struct nfqnl_instance *queue, nfqnl_cmpfn cmpfn, unsigned long data)
 	spin_unlock_bh(&queue->lock);
 }
 
+static void
+nfqnl_zcopy(struct sk_buff *to, const struct sk_buff *from, int len, int hlen)
+{
+	int i, j = 0;
+	int plen = 0; /* length of skb->head fragment */
+	struct page *page;
+	unsigned int offset;
+
+	/* dont bother with small payloads */
+	if (len <= skb_tailroom(to)) {
+		skb_copy_bits(from, 0, skb_put(to, len), len);
+		return;
+	}
+
+	if (hlen) {
+		skb_copy_bits(from, 0, skb_put(to, hlen), hlen);
+		len -= hlen;
+	} else {
+		plen = min_t(int, skb_headlen(from), len);
+		if (plen) {
+			page = virt_to_head_page(from->head);
+			offset = from->data - (unsigned char *)page_address(page);
+			__skb_fill_page_desc(to, 0, page, offset, plen);
+			get_page(page);
+			j = 1;
+			len -= plen;
+		}
+	}
+
+	to->truesize += len + plen;
+	to->len += len + plen;
+	to->data_len += len + plen;
+
+	for (i = 0; i < skb_shinfo(from)->nr_frags; i++) {
+		if (!len)
+			break;
+		skb_shinfo(to)->frags[j] = skb_shinfo(from)->frags[i];
+		skb_shinfo(to)->frags[j].size = min_t(int, skb_shinfo(to)->frags[j].size, len);
+		len -= skb_shinfo(to)->frags[j].size;
+		skb_frag_ref(to, j);
+		j++;
+	}
+	skb_shinfo(to)->nr_frags = j;
+}
+
 static struct sk_buff *
 nfqnl_build_packet_message(struct nfqnl_instance *queue,
 			   struct nf_queue_entry *entry,
 			   __be32 **packet_id_ptr)
 {
-	sk_buff_data_t old_tail;
 	size_t size;
 	size_t data_len = 0, cap_len = 0;
+	int hlen = 0;
 	struct sk_buff *skb;
 	struct nlattr *nla;
 	struct nfqnl_msg_packet_hdr *pmsg;
@@ -236,7 +281,7 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
 	struct nf_conn *ct = NULL;
 	enum ip_conntrack_info uninitialized_var(ctinfo);
 
-	size =    NLMSG_SPACE(sizeof(struct nfgenmsg))
+	size =    nlmsg_total_size(sizeof(struct nfgenmsg))
 		+ nla_total_size(sizeof(struct nfqnl_msg_packet_hdr))
 		+ nla_total_size(sizeof(u_int32_t))	/* ifindex */
 		+ nla_total_size(sizeof(u_int32_t))	/* ifindex */
@@ -246,8 +291,10 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
 #endif
 		+ nla_total_size(sizeof(u_int32_t))	/* mark */
 		+ nla_total_size(sizeof(struct nfqnl_msg_packet_hw))
-		+ nla_total_size(sizeof(struct nfqnl_msg_packet_timestamp)
-		+ nla_total_size(sizeof(u_int32_t)));	/* cap_len */
+		+ nla_total_size(sizeof(u_int32_t));	/* cap_len */
+
+	if (entskb->tstamp.tv64)
+		size += nla_total_size(sizeof(struct nfqnl_msg_packet_timestamp));
 
 	outdev = entry->outdev;
 
@@ -265,7 +312,16 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
 		if (data_len == 0 || data_len > entskb->len)
 			data_len = entskb->len;
 
-		size += nla_total_size(data_len);
+
+		if (!entskb->head_frag ||
+		    skb_headlen(entskb) < L1_CACHE_BYTES ||
+		    skb_shinfo(entskb)->nr_frags >= MAX_SKB_FRAGS)
+			hlen = skb_headlen(entskb);
+
+		if (skb_has_frag_list(entskb))
+			hlen = entskb->len;
+		hlen = min_t(int, data_len, hlen);
+		size += sizeof(struct nlattr) + hlen;
 		cap_len = entskb->len;
 		break;
 	}
@@ -277,7 +333,6 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
 	if (!skb)
 		return NULL;
 
-	old_tail = skb->tail;
 	nlh = nlmsg_put(skb, 0, 0,
 			NFNL_SUBSYS_QUEUE << 8 | NFQNL_MSG_PACKET,
 			sizeof(struct nfgenmsg), 0);
@@ -382,31 +437,26 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
 			goto nla_put_failure;
 	}
 
+	if (ct && nfqnl_ct_put(skb, ct, ctinfo) < 0)
+		goto nla_put_failure;
+
+	if (cap_len > 0 && nla_put_be32(skb, NFQA_CAP_LEN, htonl(cap_len)))
+		goto nla_put_failure;
+
 	if (data_len) {
 		struct nlattr *nla;
-		int sz = nla_attr_size(data_len);
 
-		if (skb_tailroom(skb) < nla_total_size(data_len)) {
-			printk(KERN_WARNING "nf_queue: no tailroom!\n");
-			kfree_skb(skb);
-			return NULL;
-		}
+		if (skb_tailroom(skb) < sizeof(*nla) + hlen)
+			goto nla_put_failure;
 
-		nla = (struct nlattr *)skb_put(skb, nla_total_size(data_len));
+		nla = (struct nlattr *)skb_put(skb, sizeof(*nla));
 		nla->nla_type = NFQA_PAYLOAD;
-		nla->nla_len = sz;
+		nla->nla_len = nla_attr_size(data_len);
 
-		if (skb_copy_bits(entskb, 0, nla_data(nla), data_len))
-			BUG();
+		nfqnl_zcopy(skb, entskb, data_len, hlen);
 	}
 
-	if (ct && nfqnl_ct_put(skb, ct, ctinfo) < 0)
-		goto nla_put_failure;
-
-	if (cap_len > 0 && nla_put_be32(skb, NFQA_CAP_LEN, htonl(cap_len)))
-		goto nla_put_failure;
-
-	nlh->nlmsg_len = skb->tail - old_tail;
+	nlh->nlmsg_len = skb->len;
 	return skb;
 
 nla_put_failure:
@@ -1062,8 +1112,10 @@ static int __init nfnetlink_queue_init(void)
 
 #ifdef CONFIG_PROC_FS
 	if (!proc_create("nfnetlink_queue", 0440,
-			 proc_net_netfilter, &nfqnl_file_ops))
+			 proc_net_netfilter, &nfqnl_file_ops)) {
+		status = -ENOMEM;
 		goto cleanup_subsys;
+	}
 #endif
 
 	register_netdevice_notifier(&nfqnl_dev_notifier);
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index 686c771..67fb7bf 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -999,7 +999,7 @@ static int xt_table_open(struct inode *inode, struct file *file)
 			   sizeof(struct xt_names_priv));
 	if (!ret) {
 		priv = ((struct seq_file *)file->private_data)->private;
-		priv->af = (unsigned long)PDE(inode)->data;
+		priv->af = (unsigned long)PDE_DATA(inode);
 	}
 	return ret;
 }
@@ -1147,7 +1147,7 @@ static int xt_match_open(struct inode *inode, struct file *file)
 
 	seq = file->private_data;
 	seq->private = trav;
-	trav->nfproto = (unsigned long)PDE(inode)->data;
+	trav->nfproto = (unsigned long)PDE_DATA(inode);
 	return 0;
 }
 
@@ -1211,7 +1211,7 @@ static int xt_target_open(struct inode *inode, struct file *file)
 
 	seq = file->private_data;
 	seq->private = trav;
-	trav->nfproto = (unsigned long)PDE(inode)->data;
+	trav->nfproto = (unsigned long)PDE_DATA(inode);
 	return 0;
 }
 
diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c
index f330e8b..ebfad03 100644
--- a/net/netfilter/xt_hashlimit.c
+++ b/net/netfilter/xt_hashlimit.c
@@ -841,7 +841,7 @@ static int dl_proc_open(struct inode *inode, struct file *file)
 
 	if (!ret) {
 		struct seq_file *sf = file->private_data;
-		sf->private = PDE(inode)->data;
+		sf->private = PDE_DATA(inode);
 	}
 	return ret;
 }
diff --git a/net/netfilter/xt_recent.c b/net/netfilter/xt_recent.c
index d9cad31..3db2d38 100644
--- a/net/netfilter/xt_recent.c
+++ b/net/netfilter/xt_recent.c
@@ -525,14 +525,13 @@ static const struct seq_operations recent_seq_ops = {
 
 static int recent_seq_open(struct inode *inode, struct file *file)
 {
-	struct proc_dir_entry *pde = PDE(inode);
 	struct recent_iter_state *st;
 
 	st = __seq_open_private(file, &recent_seq_ops, sizeof(*st));
 	if (st == NULL)
 		return -ENOMEM;
 
-	st->table    = pde->data;
+	st->table    = PDE_DATA(inode);
 	return 0;
 }
 
@@ -540,8 +539,7 @@ static ssize_t
 recent_mt_proc_write(struct file *file, const char __user *input,
 		     size_t size, loff_t *loff)
 {
-	const struct proc_dir_entry *pde = PDE(file_inode(file));
-	struct recent_table *t = pde->data;
+	struct recent_table *t = PDE_DATA(file_inode(file));
 	struct recent_entry *e;
 	char buf[sizeof("+b335:1d35:1e55:dead:c0de:1715:5afe:c0de")];
 	const char *c = buf;
diff --git a/net/netlink/Kconfig b/net/netlink/Kconfig
new file mode 100644
index 0000000..5d6e8c0
--- /dev/null
+++ b/net/netlink/Kconfig
@@ -0,0 +1,10 @@
+#
+# Netlink Sockets
+#
+
+config NETLINK_DIAG
+	tristate "NETLINK: socket monitoring interface"
+	default n
+	---help---
+	  Support for NETLINK socket monitoring interface used by the ss tool.
+	  If unsure, say Y.
diff --git a/net/netlink/Makefile b/net/netlink/Makefile
index bdd6ddf..e837917 100644
--- a/net/netlink/Makefile
+++ b/net/netlink/Makefile
@@ -3,3 +3,6 @@
 #
 
 obj-y  				:= af_netlink.o genetlink.o
+
+obj-$(CONFIG_NETLINK_DIAG)	+= netlink_diag.o
+netlink_diag-y			:= diag.o
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 1e3fd5b..ce2e006 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -61,28 +61,7 @@
 #include <net/scm.h>
 #include <net/netlink.h>
 
-#define NLGRPSZ(x)	(ALIGN(x, sizeof(unsigned long) * 8) / 8)
-#define NLGRPLONGS(x)	(NLGRPSZ(x)/sizeof(unsigned long))
-
-struct netlink_sock {
-	/* struct sock has to be the first member of netlink_sock */
-	struct sock		sk;
-	u32			portid;
-	u32			dst_portid;
-	u32			dst_group;
-	u32			flags;
-	u32			subscriptions;
-	u32			ngroups;
-	unsigned long		*groups;
-	unsigned long		state;
-	wait_queue_head_t	wait;
-	struct netlink_callback	*cb;
-	struct mutex		*cb_mutex;
-	struct mutex		cb_def_mutex;
-	void			(*netlink_rcv)(struct sk_buff *skb);
-	void			(*netlink_bind)(int group);
-	struct module		*module;
-};
+#include "af_netlink.h"
 
 struct listeners {
 	struct rcu_head		rcu;
@@ -94,48 +73,20 @@ struct listeners {
 #define NETLINK_BROADCAST_SEND_ERROR	0x4
 #define NETLINK_RECV_NO_ENOBUFS	0x8
 
-static inline struct netlink_sock *nlk_sk(struct sock *sk)
-{
-	return container_of(sk, struct netlink_sock, sk);
-}
-
 static inline int netlink_is_kernel(struct sock *sk)
 {
 	return nlk_sk(sk)->flags & NETLINK_KERNEL_SOCKET;
 }
 
-struct nl_portid_hash {
-	struct hlist_head	*table;
-	unsigned long		rehash_time;
-
-	unsigned int		mask;
-	unsigned int		shift;
-
-	unsigned int		entries;
-	unsigned int		max_shift;
-
-	u32			rnd;
-};
-
-struct netlink_table {
-	struct nl_portid_hash	hash;
-	struct hlist_head	mc_list;
-	struct listeners __rcu	*listeners;
-	unsigned int		flags;
-	unsigned int		groups;
-	struct mutex		*cb_mutex;
-	struct module		*module;
-	void			(*bind)(int group);
-	int			registered;
-};
-
-static struct netlink_table *nl_table;
+struct netlink_table *nl_table;
+EXPORT_SYMBOL_GPL(nl_table);
 
 static DECLARE_WAIT_QUEUE_HEAD(nl_table_wait);
 
 static int netlink_dump(struct sock *sk);
 
-static DEFINE_RWLOCK(nl_table_lock);
+DEFINE_RWLOCK(nl_table_lock);
+EXPORT_SYMBOL_GPL(nl_table_lock);
 static atomic_t nl_table_users = ATOMIC_INIT(0);
 
 #define nl_deref_protected(X) rcu_dereference_protected(X, lockdep_is_held(&nl_table_lock));
@@ -1695,7 +1646,7 @@ struct nlmsghdr *
 __nlmsg_put(struct sk_buff *skb, u32 portid, u32 seq, int type, int len, int flags)
 {
 	struct nlmsghdr *nlh;
-	int size = NLMSG_LENGTH(len);
+	int size = nlmsg_msg_size(len);
 
 	nlh = (struct nlmsghdr*)skb_put(skb, NLMSG_ALIGN(size));
 	nlh->nlmsg_type = type;
@@ -1704,7 +1655,7 @@ __nlmsg_put(struct sk_buff *skb, u32 portid, u32 seq, int type, int len, int fla
 	nlh->nlmsg_pid = portid;
 	nlh->nlmsg_seq = seq;
 	if (!__builtin_constant_p(size) || NLMSG_ALIGN(size) - size != 0)
-		memset(NLMSG_DATA(nlh) + len, 0, NLMSG_ALIGN(size) - size);
+		memset(nlmsg_data(nlh) + len, 0, NLMSG_ALIGN(size) - size);
 	return nlh;
 }
 EXPORT_SYMBOL(__nlmsg_put);
diff --git a/net/netlink/af_netlink.h b/net/netlink/af_netlink.h
new file mode 100644
index 0000000..d9acb2a
--- /dev/null
+++ b/net/netlink/af_netlink.h
@@ -0,0 +1,62 @@
+#ifndef _AF_NETLINK_H
+#define _AF_NETLINK_H
+
+#include <net/sock.h>
+
+#define NLGRPSZ(x)	(ALIGN(x, sizeof(unsigned long) * 8) / 8)
+#define NLGRPLONGS(x)	(NLGRPSZ(x)/sizeof(unsigned long))
+
+struct netlink_sock {
+	/* struct sock has to be the first member of netlink_sock */
+	struct sock		sk;
+	u32			portid;
+	u32			dst_portid;
+	u32			dst_group;
+	u32			flags;
+	u32			subscriptions;
+	u32			ngroups;
+	unsigned long		*groups;
+	unsigned long		state;
+	wait_queue_head_t	wait;
+	struct netlink_callback	*cb;
+	struct mutex		*cb_mutex;
+	struct mutex		cb_def_mutex;
+	void			(*netlink_rcv)(struct sk_buff *skb);
+	void			(*netlink_bind)(int group);
+	struct module		*module;
+};
+
+static inline struct netlink_sock *nlk_sk(struct sock *sk)
+{
+	return container_of(sk, struct netlink_sock, sk);
+}
+
+struct nl_portid_hash {
+	struct hlist_head	*table;
+	unsigned long		rehash_time;
+
+	unsigned int		mask;
+	unsigned int		shift;
+
+	unsigned int		entries;
+	unsigned int		max_shift;
+
+	u32			rnd;
+};
+
+struct netlink_table {
+	struct nl_portid_hash	hash;
+	struct hlist_head	mc_list;
+	struct listeners __rcu	*listeners;
+	unsigned int		flags;
+	unsigned int		groups;
+	struct mutex		*cb_mutex;
+	struct module		*module;
+	void			(*bind)(int group);
+	int			registered;
+};
+
+extern struct netlink_table *nl_table;
+extern rwlock_t nl_table_lock;
+
+#endif
diff --git a/net/netlink/diag.c b/net/netlink/diag.c
new file mode 100644
index 0000000..5ffb1d1
--- /dev/null
+++ b/net/netlink/diag.c
@@ -0,0 +1,188 @@
+#include <linux/module.h>
+
+#include <net/sock.h>
+#include <linux/netlink.h>
+#include <linux/sock_diag.h>
+#include <linux/netlink_diag.h>
+
+#include "af_netlink.h"
+
+static int sk_diag_dump_groups(struct sock *sk, struct sk_buff *nlskb)
+{
+	struct netlink_sock *nlk = nlk_sk(sk);
+
+	if (nlk->groups == NULL)
+		return 0;
+
+	return nla_put(nlskb, NETLINK_DIAG_GROUPS, NLGRPSZ(nlk->ngroups),
+		       nlk->groups);
+}
+
+static int sk_diag_fill(struct sock *sk, struct sk_buff *skb,
+			struct netlink_diag_req *req,
+			u32 portid, u32 seq, u32 flags, int sk_ino)
+{
+	struct nlmsghdr *nlh;
+	struct netlink_diag_msg *rep;
+	struct netlink_sock *nlk = nlk_sk(sk);
+
+	nlh = nlmsg_put(skb, portid, seq, SOCK_DIAG_BY_FAMILY, sizeof(*rep),
+			flags);
+	if (!nlh)
+		return -EMSGSIZE;
+
+	rep = nlmsg_data(nlh);
+	rep->ndiag_family	= AF_NETLINK;
+	rep->ndiag_type		= sk->sk_type;
+	rep->ndiag_protocol	= sk->sk_protocol;
+	rep->ndiag_state	= sk->sk_state;
+
+	rep->ndiag_ino		= sk_ino;
+	rep->ndiag_portid	= nlk->portid;
+	rep->ndiag_dst_portid	= nlk->dst_portid;
+	rep->ndiag_dst_group	= nlk->dst_group;
+	sock_diag_save_cookie(sk, rep->ndiag_cookie);
+
+	if ((req->ndiag_show & NDIAG_SHOW_GROUPS) &&
+	    sk_diag_dump_groups(sk, skb))
+		goto out_nlmsg_trim;
+
+	if ((req->ndiag_show & NDIAG_SHOW_MEMINFO) &&
+	    sock_diag_put_meminfo(sk, skb, NETLINK_DIAG_MEMINFO))
+		goto out_nlmsg_trim;
+
+	return nlmsg_end(skb, nlh);
+
+out_nlmsg_trim:
+	nlmsg_cancel(skb, nlh);
+	return -EMSGSIZE;
+}
+
+static int __netlink_diag_dump(struct sk_buff *skb, struct netlink_callback *cb,
+				int protocol, int s_num)
+{
+	struct netlink_table *tbl = &nl_table[protocol];
+	struct nl_portid_hash *hash = &tbl->hash;
+	struct net *net = sock_net(skb->sk);
+	struct netlink_diag_req *req;
+	struct sock *sk;
+	int ret = 0, num = 0, i;
+
+	req = nlmsg_data(cb->nlh);
+
+	for (i = 0; i <= hash->mask; i++) {
+		sk_for_each(sk, &hash->table[i]) {
+			if (!net_eq(sock_net(sk), net))
+				continue;
+			if (num < s_num) {
+				num++;
+				continue;
+			}
+
+			if (sk_diag_fill(sk, skb, req,
+					 NETLINK_CB(cb->skb).portid,
+					 cb->nlh->nlmsg_seq,
+					 NLM_F_MULTI,
+					 sock_i_ino(sk)) < 0) {
+				ret = 1;
+				goto done;
+			}
+
+			num++;
+		}
+	}
+
+	sk_for_each_bound(sk, &tbl->mc_list) {
+		if (sk_hashed(sk))
+			continue;
+		if (!net_eq(sock_net(sk), net))
+			continue;
+		if (num < s_num) {
+			num++;
+			continue;
+		}
+
+		if (sk_diag_fill(sk, skb, req,
+				 NETLINK_CB(cb->skb).portid,
+				 cb->nlh->nlmsg_seq,
+				 NLM_F_MULTI,
+				 sock_i_ino(sk)) < 0) {
+			ret = 1;
+			goto done;
+		}
+		num++;
+	}
+done:
+	cb->args[0] = num;
+	cb->args[1] = protocol;
+
+	return ret;
+}
+
+static int netlink_diag_dump(struct sk_buff *skb, struct netlink_callback *cb)
+{
+	struct netlink_diag_req *req;
+	int s_num = cb->args[0];
+
+	req = nlmsg_data(cb->nlh);
+
+	read_lock(&nl_table_lock);
+
+	if (req->sdiag_protocol == NDIAG_PROTO_ALL) {
+		int i;
+
+		for (i = cb->args[1]; i < MAX_LINKS; i++) {
+			if (__netlink_diag_dump(skb, cb, i, s_num))
+				break;
+			s_num = 0;
+		}
+	} else {
+		if (req->sdiag_protocol >= MAX_LINKS) {
+			read_unlock(&nl_table_lock);
+			return -ENOENT;
+		}
+
+		__netlink_diag_dump(skb, cb, req->sdiag_protocol, s_num);
+	}
+
+	read_unlock(&nl_table_lock);
+
+	return skb->len;
+}
+
+static int netlink_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h)
+{
+	int hdrlen = sizeof(struct netlink_diag_req);
+	struct net *net = sock_net(skb->sk);
+
+	if (nlmsg_len(h) < hdrlen)
+		return -EINVAL;
+
+	if (h->nlmsg_flags & NLM_F_DUMP) {
+		struct netlink_dump_control c = {
+			.dump = netlink_diag_dump,
+		};
+		return netlink_dump_start(net->diag_nlsk, skb, h, &c);
+	} else
+		return -EOPNOTSUPP;
+}
+
+static const struct sock_diag_handler netlink_diag_handler = {
+	.family = AF_NETLINK,
+	.dump = netlink_diag_handler_dump,
+};
+
+static int __init netlink_diag_init(void)
+{
+	return sock_diag_register(&netlink_diag_handler);
+}
+
+static void __exit netlink_diag_exit(void)
+{
+	sock_diag_unregister(&netlink_diag_handler);
+}
+
+module_init(netlink_diag_init);
+module_exit(netlink_diag_exit);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, 16 /* AF_NETLINK */);
diff --git a/net/nfc/llcp/commands.c b/net/nfc/llcp/commands.c
index c6bc3bd..b75a9b3 100644
--- a/net/nfc/llcp/commands.c
+++ b/net/nfc/llcp/commands.c
@@ -117,6 +117,88 @@ u8 *nfc_llcp_build_tlv(u8 type, u8 *value, u8 value_length, u8 *tlv_length)
 	return tlv;
 }
 
+struct nfc_llcp_sdp_tlv *nfc_llcp_build_sdres_tlv(u8 tid, u8 sap)
+{
+	struct nfc_llcp_sdp_tlv *sdres;
+	u8 value[2];
+
+	sdres = kzalloc(sizeof(struct nfc_llcp_sdp_tlv), GFP_KERNEL);
+	if (sdres == NULL)
+		return NULL;
+
+	value[0] = tid;
+	value[1] = sap;
+
+	sdres->tlv = nfc_llcp_build_tlv(LLCP_TLV_SDRES, value, 2,
+					&sdres->tlv_len);
+	if (sdres->tlv == NULL) {
+		kfree(sdres);
+		return NULL;
+	}
+
+	sdres->tid = tid;
+	sdres->sap = sap;
+
+	INIT_HLIST_NODE(&sdres->node);
+
+	return sdres;
+}
+
+struct nfc_llcp_sdp_tlv *nfc_llcp_build_sdreq_tlv(u8 tid, char *uri,
+						  size_t uri_len)
+{
+	struct nfc_llcp_sdp_tlv *sdreq;
+
+	pr_debug("uri: %s, len: %zu\n", uri, uri_len);
+
+	sdreq = kzalloc(sizeof(struct nfc_llcp_sdp_tlv), GFP_KERNEL);
+	if (sdreq == NULL)
+		return NULL;
+
+	sdreq->tlv_len = uri_len + 3;
+
+	if (uri[uri_len - 1] == 0)
+		sdreq->tlv_len--;
+
+	sdreq->tlv = kzalloc(sdreq->tlv_len + 1, GFP_KERNEL);
+	if (sdreq->tlv == NULL) {
+		kfree(sdreq);
+		return NULL;
+	}
+
+	sdreq->tlv[0] = LLCP_TLV_SDREQ;
+	sdreq->tlv[1] = sdreq->tlv_len - 2;
+	sdreq->tlv[2] = tid;
+
+	sdreq->tid = tid;
+	sdreq->uri = sdreq->tlv + 3;
+	memcpy(sdreq->uri, uri, uri_len);
+
+	sdreq->time = jiffies;
+
+	INIT_HLIST_NODE(&sdreq->node);
+
+	return sdreq;
+}
+
+void nfc_llcp_free_sdp_tlv(struct nfc_llcp_sdp_tlv *sdp)
+{
+	kfree(sdp->tlv);
+	kfree(sdp);
+}
+
+void nfc_llcp_free_sdp_tlv_list(struct hlist_head *head)
+{
+	struct nfc_llcp_sdp_tlv *sdp;
+	struct hlist_node *n;
+
+	hlist_for_each_entry_safe(sdp, n, head, node) {
+		hlist_del(&sdp->node);
+
+		nfc_llcp_free_sdp_tlv(sdp);
+	}
+}
+
 int nfc_llcp_parse_gb_tlv(struct nfc_llcp_local *local,
 			  u8 *tlv_array, u16 tlv_array_len)
 {
@@ -184,10 +266,10 @@ int nfc_llcp_parse_connection_tlv(struct nfc_llcp_sock *sock,
 
 		switch (type) {
 		case LLCP_TLV_MIUX:
-			sock->miu = llcp_tlv_miux(tlv) + 128;
+			sock->remote_miu = llcp_tlv_miux(tlv) + 128;
 			break;
 		case LLCP_TLV_RW:
-			sock->rw = llcp_tlv_rw(tlv);
+			sock->remote_rw = llcp_tlv_rw(tlv);
 			break;
 		case LLCP_TLV_SN:
 			break;
@@ -200,7 +282,8 @@ int nfc_llcp_parse_connection_tlv(struct nfc_llcp_sock *sock,
 		tlv += length + 2;
 	}
 
-	pr_debug("sock %p rw %d miu %d\n", sock, sock->rw, sock->miu);
+	pr_debug("sock %p rw %d miu %d\n", sock,
+		 sock->remote_rw, sock->remote_miu);
 
 	return 0;
 }
@@ -318,9 +401,9 @@ int nfc_llcp_send_connect(struct nfc_llcp_sock *sock)
 	struct sk_buff *skb;
 	u8 *service_name_tlv = NULL, service_name_tlv_length;
 	u8 *miux_tlv = NULL, miux_tlv_length;
-	u8 *rw_tlv = NULL, rw_tlv_length;
+	u8 *rw_tlv = NULL, rw_tlv_length, rw;
 	int err;
-	u16 size = 0;
+	u16 size = 0, miux;
 
 	pr_debug("Sending CONNECT\n");
 
@@ -336,11 +419,15 @@ int nfc_llcp_send_connect(struct nfc_llcp_sock *sock)
 		size += service_name_tlv_length;
 	}
 
-	miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&local->miux, 0,
+	/* If the socket parameters are not set, use the local ones */
+	miux = sock->miux > LLCP_MAX_MIUX ? local->miux : sock->miux;
+	rw = sock->rw > LLCP_MAX_RW ? local->rw : sock->rw;
+
+	miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&miux, 0,
 				      &miux_tlv_length);
 	size += miux_tlv_length;
 
-	rw_tlv = nfc_llcp_build_tlv(LLCP_TLV_RW, &local->rw, 0, &rw_tlv_length);
+	rw_tlv = nfc_llcp_build_tlv(LLCP_TLV_RW, &rw, 0, &rw_tlv_length);
 	size += rw_tlv_length;
 
 	pr_debug("SKB size %d SN length %zu\n", size, sock->service_name_len);
@@ -377,9 +464,9 @@ int nfc_llcp_send_cc(struct nfc_llcp_sock *sock)
 	struct nfc_llcp_local *local;
 	struct sk_buff *skb;
 	u8 *miux_tlv = NULL, miux_tlv_length;
-	u8 *rw_tlv = NULL, rw_tlv_length;
+	u8 *rw_tlv = NULL, rw_tlv_length, rw;
 	int err;
-	u16 size = 0;
+	u16 size = 0, miux;
 
 	pr_debug("Sending CC\n");
 
@@ -387,11 +474,15 @@ int nfc_llcp_send_cc(struct nfc_llcp_sock *sock)
 	if (local == NULL)
 		return -ENODEV;
 
-	miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&local->miux, 0,
+	/* If the socket parameters are not set, use the local ones */
+	miux = sock->miux > LLCP_MAX_MIUX ? local->miux : sock->miux;
+	rw = sock->rw > LLCP_MAX_RW ? local->rw : sock->rw;
+
+	miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&miux, 0,
 				      &miux_tlv_length);
 	size += miux_tlv_length;
 
-	rw_tlv = nfc_llcp_build_tlv(LLCP_TLV_RW, &local->rw, 0, &rw_tlv_length);
+	rw_tlv = nfc_llcp_build_tlv(LLCP_TLV_RW, &rw, 0, &rw_tlv_length);
 	size += rw_tlv_length;
 
 	skb = llcp_allocate_pdu(sock, LLCP_PDU_CC, size);
@@ -416,48 +507,90 @@ error_tlv:
 	return err;
 }
 
-int nfc_llcp_send_snl(struct nfc_llcp_local *local, u8 tid, u8 sap)
+static struct sk_buff *nfc_llcp_allocate_snl(struct nfc_llcp_local *local,
+					     size_t tlv_length)
 {
 	struct sk_buff *skb;
 	struct nfc_dev *dev;
-	u8 *sdres_tlv = NULL, sdres_tlv_length, sdres[2];
 	u16 size = 0;
 
-	pr_debug("Sending SNL tid 0x%x sap 0x%x\n", tid, sap);
-
 	if (local == NULL)
-		return -ENODEV;
+		return ERR_PTR(-ENODEV);
 
 	dev = local->dev;
 	if (dev == NULL)
-		return -ENODEV;
-
-	sdres[0] = tid;
-	sdres[1] = sap;
-	sdres_tlv = nfc_llcp_build_tlv(LLCP_TLV_SDRES, sdres, 0,
-				       &sdres_tlv_length);
-	if (sdres_tlv == NULL)
-		return -ENOMEM;
+		return ERR_PTR(-ENODEV);
 
 	size += LLCP_HEADER_SIZE;
 	size += dev->tx_headroom + dev->tx_tailroom + NFC_HEADER_SIZE;
-	size += sdres_tlv_length;
+	size += tlv_length;
 
 	skb = alloc_skb(size, GFP_KERNEL);
-	if (skb == NULL) {
-		kfree(sdres_tlv);
-		return -ENOMEM;
-	}
+	if (skb == NULL)
+		return ERR_PTR(-ENOMEM);
 
 	skb_reserve(skb, dev->tx_headroom + NFC_HEADER_SIZE);
 
 	skb = llcp_add_header(skb, LLCP_SAP_SDP, LLCP_SAP_SDP, LLCP_PDU_SNL);
 
-	memcpy(skb_put(skb, sdres_tlv_length), sdres_tlv, sdres_tlv_length);
+	return skb;
+}
+
+int nfc_llcp_send_snl_sdres(struct nfc_llcp_local *local,
+			    struct hlist_head *tlv_list, size_t tlvs_len)
+{
+	struct nfc_llcp_sdp_tlv *sdp;
+	struct hlist_node *n;
+	struct sk_buff *skb;
+
+	skb = nfc_llcp_allocate_snl(local, tlvs_len);
+	if (IS_ERR(skb))
+		return PTR_ERR(skb);
+
+	hlist_for_each_entry_safe(sdp, n, tlv_list, node) {
+		memcpy(skb_put(skb, sdp->tlv_len), sdp->tlv, sdp->tlv_len);
+
+		hlist_del(&sdp->node);
+
+		nfc_llcp_free_sdp_tlv(sdp);
+	}
 
 	skb_queue_tail(&local->tx_queue, skb);
 
-	kfree(sdres_tlv);
+	return 0;
+}
+
+int nfc_llcp_send_snl_sdreq(struct nfc_llcp_local *local,
+			    struct hlist_head *tlv_list, size_t tlvs_len)
+{
+	struct nfc_llcp_sdp_tlv *sdreq;
+	struct hlist_node *n;
+	struct sk_buff *skb;
+
+	skb = nfc_llcp_allocate_snl(local, tlvs_len);
+	if (IS_ERR(skb))
+		return PTR_ERR(skb);
+
+	mutex_lock(&local->sdreq_lock);
+
+	if (hlist_empty(&local->pending_sdreqs))
+		mod_timer(&local->sdreq_timer,
+			  jiffies + msecs_to_jiffies(3 * local->remote_lto));
+
+	hlist_for_each_entry_safe(sdreq, n, tlv_list, node) {
+		pr_debug("tid %d for %s\n", sdreq->tid, sdreq->uri);
+
+		memcpy(skb_put(skb, sdreq->tlv_len), sdreq->tlv,
+		       sdreq->tlv_len);
+
+		hlist_del(&sdreq->node);
+
+		hlist_add_head(&sdreq->node, &local->pending_sdreqs);
+	}
+
+	mutex_unlock(&local->sdreq_lock);
+
+	skb_queue_tail(&local->tx_queue, skb);
 
 	return 0;
 }
@@ -532,8 +665,8 @@ int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock,
 
 	/* Remote is ready but has not acknowledged our frames */
 	if((sock->remote_ready &&
-	    skb_queue_len(&sock->tx_pending_queue) >= sock->rw &&
-	    skb_queue_len(&sock->tx_queue) >= 2 * sock->rw)) {
+	    skb_queue_len(&sock->tx_pending_queue) >= sock->remote_rw &&
+	    skb_queue_len(&sock->tx_queue) >= 2 * sock->remote_rw)) {
 		pr_err("Pending queue is full %d frames\n",
 		       skb_queue_len(&sock->tx_pending_queue));
 		return -ENOBUFS;
@@ -541,7 +674,7 @@ int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock,
 
 	/* Remote is not ready and we've been queueing enough frames */
 	if ((!sock->remote_ready &&
-	     skb_queue_len(&sock->tx_queue) >= 2 * sock->rw)) {
+	     skb_queue_len(&sock->tx_queue) >= 2 * sock->remote_rw)) {
 		pr_err("Tx queue is full %d frames\n",
 		       skb_queue_len(&sock->tx_queue));
 		return -ENOBUFS;
@@ -561,7 +694,7 @@ int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock,
 
 	while (remaining_len > 0) {
 
-		frag_len = min_t(size_t, sock->miu, remaining_len);
+		frag_len = min_t(size_t, sock->remote_miu, remaining_len);
 
 		pr_debug("Fragment %zd bytes remaining %zd",
 			 frag_len, remaining_len);
@@ -621,7 +754,7 @@ int nfc_llcp_send_ui_frame(struct nfc_llcp_sock *sock, u8 ssap, u8 dsap,
 
 	while (remaining_len > 0) {
 
-		frag_len = min_t(size_t, sock->miu, remaining_len);
+		frag_len = min_t(size_t, sock->remote_miu, remaining_len);
 
 		pr_debug("Fragment %zd bytes remaining %zd",
 			 frag_len, remaining_len);
diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c
index b530afa..7de0368 100644
--- a/net/nfc/llcp/llcp.c
+++ b/net/nfc/llcp/llcp.c
@@ -107,8 +107,6 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen,
 				accept_sk->sk_state_change(sk);
 
 				bh_unlock_sock(accept_sk);
-
-				sock_orphan(accept_sk);
 			}
 
 			if (listen == true) {
@@ -134,8 +132,6 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen,
 
 		bh_unlock_sock(sk);
 
-		sock_orphan(sk);
-
 		sk_del_node_init(sk);
 	}
 
@@ -164,8 +160,6 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen,
 
 		bh_unlock_sock(sk);
 
-		sock_orphan(sk);
-
 		sk_del_node_init(sk);
 	}
 
@@ -188,6 +182,9 @@ static void local_cleanup(struct nfc_llcp_local *local, bool listen)
 	cancel_work_sync(&local->rx_work);
 	cancel_work_sync(&local->timeout_work);
 	kfree_skb(local->rx_pending);
+	del_timer_sync(&local->sdreq_timer);
+	cancel_work_sync(&local->sdreq_timeout_work);
+	nfc_llcp_free_sdp_tlv_list(&local->pending_sdreqs);
 }
 
 static void local_release(struct kref *ref)
@@ -265,6 +262,47 @@ static void nfc_llcp_symm_timer(unsigned long data)
 	schedule_work(&local->timeout_work);
 }
 
+static void nfc_llcp_sdreq_timeout_work(struct work_struct *work)
+{
+	unsigned long time;
+	HLIST_HEAD(nl_sdres_list);
+	struct hlist_node *n;
+	struct nfc_llcp_sdp_tlv *sdp;
+	struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local,
+						    sdreq_timeout_work);
+
+	mutex_lock(&local->sdreq_lock);
+
+	time = jiffies - msecs_to_jiffies(3 * local->remote_lto);
+
+	hlist_for_each_entry_safe(sdp, n, &local->pending_sdreqs, node) {
+		if (time_after(sdp->time, time))
+			continue;
+
+		sdp->sap = LLCP_SDP_UNBOUND;
+
+		hlist_del(&sdp->node);
+
+		hlist_add_head(&sdp->node, &nl_sdres_list);
+	}
+
+	if (!hlist_empty(&local->pending_sdreqs))
+		mod_timer(&local->sdreq_timer,
+			  jiffies + msecs_to_jiffies(3 * local->remote_lto));
+
+	mutex_unlock(&local->sdreq_lock);
+
+	if (!hlist_empty(&nl_sdres_list))
+		nfc_genl_llc_send_sdres(local->dev, &nl_sdres_list);
+}
+
+static void nfc_llcp_sdreq_timer(unsigned long data)
+{
+	struct nfc_llcp_local *local = (struct nfc_llcp_local *) data;
+
+	schedule_work(&local->sdreq_timeout_work);
+}
+
 struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev)
 {
 	struct nfc_llcp_local *local, *n;
@@ -808,8 +846,6 @@ static void nfc_llcp_recv_ui(struct nfc_llcp_local *local,
 	ui_cb->dsap = dsap;
 	ui_cb->ssap = ssap;
 
-	printk("%s %d %d\n", __func__, dsap, ssap);
-
 	pr_debug("%d %d\n", dsap, ssap);
 
 	/* We're looking for a bound socket, not a client one */
@@ -827,7 +863,6 @@ static void nfc_llcp_recv_ui(struct nfc_llcp_local *local,
 		skb_get(skb);
 	} else {
 		pr_err("Receive queue is full\n");
-		kfree_skb(skb);
 	}
 
 	nfc_llcp_sock_put(llcp_sock);
@@ -907,7 +942,9 @@ static void nfc_llcp_recv_connect(struct nfc_llcp_local *local,
 	new_sock = nfc_llcp_sock(new_sk);
 	new_sock->dev = local->dev;
 	new_sock->local = nfc_llcp_local_get(local);
-	new_sock->miu = local->remote_miu;
+	new_sock->rw = sock->rw;
+	new_sock->miux = sock->miux;
+	new_sock->remote_miu = local->remote_miu;
 	new_sock->nfc_protocol = sock->nfc_protocol;
 	new_sock->dsap = ssap;
 	new_sock->target_idx = local->target_idx;
@@ -961,11 +998,11 @@ int nfc_llcp_queue_i_frames(struct nfc_llcp_sock *sock)
 
 	pr_debug("Remote ready %d tx queue len %d remote rw %d",
 		 sock->remote_ready, skb_queue_len(&sock->tx_pending_queue),
-		 sock->rw);
+		 sock->remote_rw);
 
 	/* Try to queue some I frames for transmission */
 	while (sock->remote_ready &&
-	       skb_queue_len(&sock->tx_pending_queue) < sock->rw) {
+	       skb_queue_len(&sock->tx_pending_queue) < sock->remote_rw) {
 		struct sk_buff *pdu;
 
 		pdu = skb_dequeue(&sock->tx_queue);
@@ -1028,7 +1065,6 @@ static void nfc_llcp_recv_hdlc(struct nfc_llcp_local *local,
 			skb_get(skb);
 		} else {
 			pr_err("Receive queue is full\n");
-			kfree_skb(skb);
 		}
 	}
 
@@ -1186,6 +1222,10 @@ static void nfc_llcp_recv_snl(struct nfc_llcp_local *local,
 	u16 tlv_len, offset;
 	char *service_name;
 	size_t service_name_len;
+	struct nfc_llcp_sdp_tlv *sdp;
+	HLIST_HEAD(llc_sdres_list);
+	size_t sdres_tlvs_len;
+	HLIST_HEAD(nl_sdres_list);
 
 	dsap = nfc_llcp_dsap(skb);
 	ssap = nfc_llcp_ssap(skb);
@@ -1200,6 +1240,7 @@ static void nfc_llcp_recv_snl(struct nfc_llcp_local *local,
 	tlv = &skb->data[LLCP_HEADER_SIZE];
 	tlv_len = skb->len - LLCP_HEADER_SIZE;
 	offset = 0;
+	sdres_tlvs_len = 0;
 
 	while (offset < tlv_len) {
 		type = tlv[0];
@@ -1217,14 +1258,14 @@ static void nfc_llcp_recv_snl(struct nfc_llcp_local *local,
 			    !strncmp(service_name, "urn:nfc:sn:sdp",
 				     service_name_len)) {
 				sap = 1;
-				goto send_snl;
+				goto add_snl;
 			}
 
 			llcp_sock = nfc_llcp_sock_from_sn(local, service_name,
 							  service_name_len);
 			if (!llcp_sock) {
 				sap = 0;
-				goto send_snl;
+				goto add_snl;
 			}
 
 			/*
@@ -1241,7 +1282,7 @@ static void nfc_llcp_recv_snl(struct nfc_llcp_local *local,
 
 				if (sap == LLCP_SAP_MAX) {
 					sap = 0;
-					goto send_snl;
+					goto add_snl;
 				}
 
 				client_count =
@@ -1258,8 +1299,37 @@ static void nfc_llcp_recv_snl(struct nfc_llcp_local *local,
 
 			pr_debug("%p %d\n", llcp_sock, sap);
 
-send_snl:
-			nfc_llcp_send_snl(local, tid, sap);
+add_snl:
+			sdp = nfc_llcp_build_sdres_tlv(tid, sap);
+			if (sdp == NULL)
+				goto exit;
+
+			sdres_tlvs_len += sdp->tlv_len;
+			hlist_add_head(&sdp->node, &llc_sdres_list);
+			break;
+
+		case LLCP_TLV_SDRES:
+			mutex_lock(&local->sdreq_lock);
+
+			pr_debug("LLCP_TLV_SDRES: searching tid %d\n", tlv[2]);
+
+			hlist_for_each_entry(sdp, &local->pending_sdreqs, node) {
+				if (sdp->tid != tlv[2])
+					continue;
+
+				sdp->sap = tlv[3];
+
+				pr_debug("Found: uri=%s, sap=%d\n",
+					 sdp->uri, sdp->sap);
+
+				hlist_del(&sdp->node);
+
+				hlist_add_head(&sdp->node, &nl_sdres_list);
+
+				break;
+			}
+
+			mutex_unlock(&local->sdreq_lock);
 			break;
 
 		default:
@@ -1270,6 +1340,13 @@ send_snl:
 		offset += length + 2;
 		tlv += length + 2;
 	}
+
+exit:
+	if (!hlist_empty(&nl_sdres_list))
+		nfc_genl_llc_send_sdres(local->dev, &nl_sdres_list);
+
+	if (!hlist_empty(&llc_sdres_list))
+		nfc_llcp_send_snl_sdres(local, &llc_sdres_list, sdres_tlvs_len);
 }
 
 static void nfc_llcp_rx_work(struct work_struct *work)
@@ -1455,6 +1532,13 @@ int nfc_llcp_register_device(struct nfc_dev *ndev)
 	local->remote_miu = LLCP_DEFAULT_MIU;
 	local->remote_lto = LLCP_DEFAULT_LTO;
 
+	mutex_init(&local->sdreq_lock);
+	INIT_HLIST_HEAD(&local->pending_sdreqs);
+	init_timer(&local->sdreq_timer);
+	local->sdreq_timer.data = (unsigned long) local;
+	local->sdreq_timer.function = nfc_llcp_sdreq_timer;
+	INIT_WORK(&local->sdreq_timeout_work, nfc_llcp_sdreq_timeout_work);
+
 	list_add(&local->list, &llcp_devices);
 
 	return 0;
diff --git a/net/nfc/llcp/llcp.h b/net/nfc/llcp/llcp.h
index 0eae5c5..7e87a66 100644
--- a/net/nfc/llcp/llcp.h
+++ b/net/nfc/llcp/llcp.h
@@ -46,6 +46,19 @@ struct llcp_sock_list {
 	rwlock_t          lock;
 };
 
+struct nfc_llcp_sdp_tlv {
+	u8 *tlv;
+	u8 tlv_len;
+
+	char *uri;
+	u8 tid;
+	u8 sap;
+
+	unsigned long time;
+
+	struct hlist_node node;
+};
+
 struct nfc_llcp_local {
 	struct list_head list;
 	struct nfc_dev *dev;
@@ -86,6 +99,12 @@ struct nfc_llcp_local {
 	u8  remote_opt;
 	u16 remote_wks;
 
+	struct mutex sdreq_lock;
+	struct hlist_head pending_sdreqs;
+	struct timer_list sdreq_timer;
+	struct work_struct sdreq_timeout_work;
+	u8 sdreq_next_tid;
+
 	/* sockets array */
 	struct llcp_sock_list sockets;
 	struct llcp_sock_list connecting_sockets;
@@ -105,7 +124,12 @@ struct nfc_llcp_sock {
 	char *service_name;
 	size_t service_name_len;
 	u8 rw;
-	u16 miu;
+	u16 miux;
+
+
+	/* Remote link parameters */
+	u8 remote_rw;
+	u16 remote_miu;
 
 	/* Link variables */
 	u8 send_n;
@@ -213,12 +237,20 @@ int nfc_llcp_parse_connection_tlv(struct nfc_llcp_sock *sock,
 /* Commands API */
 void nfc_llcp_recv(void *data, struct sk_buff *skb, int err);
 u8 *nfc_llcp_build_tlv(u8 type, u8 *value, u8 value_length, u8 *tlv_length);
+struct nfc_llcp_sdp_tlv *nfc_llcp_build_sdres_tlv(u8 tid, u8 sap);
+struct nfc_llcp_sdp_tlv *nfc_llcp_build_sdreq_tlv(u8 tid, char *uri,
+						  size_t uri_len);
+void nfc_llcp_free_sdp_tlv(struct nfc_llcp_sdp_tlv *sdp);
+void nfc_llcp_free_sdp_tlv_list(struct hlist_head *sdp_head);
 void nfc_llcp_recv(void *data, struct sk_buff *skb, int err);
 int nfc_llcp_disconnect(struct nfc_llcp_sock *sock);
 int nfc_llcp_send_symm(struct nfc_dev *dev);
 int nfc_llcp_send_connect(struct nfc_llcp_sock *sock);
 int nfc_llcp_send_cc(struct nfc_llcp_sock *sock);
-int nfc_llcp_send_snl(struct nfc_llcp_local *local, u8 tid, u8 sap);
+int nfc_llcp_send_snl_sdres(struct nfc_llcp_local *local,
+			    struct hlist_head *tlv_list, size_t tlvs_len);
+int nfc_llcp_send_snl_sdreq(struct nfc_llcp_local *local,
+			    struct hlist_head *tlv_list, size_t tlvs_len);
 int nfc_llcp_send_dm(struct nfc_llcp_local *local, u8 ssap, u8 dsap, u8 reason);
 int nfc_llcp_send_disconnect(struct nfc_llcp_sock *sock);
 int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock,
diff --git a/net/nfc/llcp/sock.c b/net/nfc/llcp/sock.c
index 5c7cdf3..8a5bd5c 100644
--- a/net/nfc/llcp/sock.c
+++ b/net/nfc/llcp/sock.c
@@ -223,6 +223,124 @@ error:
 	return ret;
 }
 
+static int nfc_llcp_setsockopt(struct socket *sock, int level, int optname,
+			       char __user *optval, unsigned int optlen)
+{
+	struct sock *sk = sock->sk;
+	struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk);
+	u32 opt;
+	int err = 0;
+
+	pr_debug("%p optname %d\n", sk, optname);
+
+	if (level != SOL_NFC)
+		return -ENOPROTOOPT;
+
+	lock_sock(sk);
+
+	switch (optname) {
+	case NFC_LLCP_RW:
+		if (sk->sk_state == LLCP_CONNECTED ||
+		    sk->sk_state == LLCP_BOUND ||
+		    sk->sk_state == LLCP_LISTEN) {
+			err = -EINVAL;
+			break;
+		}
+
+		if (get_user(opt, (u32 __user *) optval)) {
+			err = -EFAULT;
+			break;
+		}
+
+		if (opt > LLCP_MAX_RW) {
+			err = -EINVAL;
+			break;
+		}
+
+		llcp_sock->rw = (u8) opt;
+
+		break;
+
+	case NFC_LLCP_MIUX:
+		if (sk->sk_state == LLCP_CONNECTED ||
+		    sk->sk_state == LLCP_BOUND ||
+		    sk->sk_state == LLCP_LISTEN) {
+			err = -EINVAL;
+			break;
+		}
+
+		if (get_user(opt, (u32 __user *) optval)) {
+			err = -EFAULT;
+			break;
+		}
+
+		if (opt > LLCP_MAX_MIUX) {
+			err = -EINVAL;
+			break;
+		}
+
+		llcp_sock->miux = (u16) opt;
+
+		break;
+
+	default:
+		err = -ENOPROTOOPT;
+		break;
+	}
+
+	release_sock(sk);
+
+	pr_debug("%p rw %d miux %d\n", llcp_sock,
+		 llcp_sock->rw, llcp_sock->miux);
+
+	return err;
+}
+
+static int nfc_llcp_getsockopt(struct socket *sock, int level, int optname,
+			       char __user *optval, int __user *optlen)
+{
+	struct sock *sk = sock->sk;
+	struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk);
+	int len, err = 0;
+
+	pr_debug("%p optname %d\n", sk, optname);
+
+	if (level != SOL_NFC)
+		return -ENOPROTOOPT;
+
+	if (get_user(len, optlen))
+		return -EFAULT;
+
+	len = min_t(u32, len, sizeof(u32));
+
+	lock_sock(sk);
+
+	switch (optname) {
+	case NFC_LLCP_RW:
+		if (put_user(llcp_sock->rw, (u32 __user *) optval))
+			err = -EFAULT;
+
+		break;
+
+	case NFC_LLCP_MIUX:
+		if (put_user(llcp_sock->miux, (u32 __user *) optval))
+			err = -EFAULT;
+
+		break;
+
+	default:
+		err = -ENOPROTOOPT;
+		break;
+	}
+
+	release_sock(sk);
+
+	if (put_user(len, optlen))
+		return -EFAULT;
+
+	return err;
+}
+
 void nfc_llcp_accept_unlink(struct sock *sk)
 {
 	struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk);
@@ -270,7 +388,9 @@ struct sock *nfc_llcp_accept_dequeue(struct sock *parent,
 		}
 
 		if (sk->sk_state == LLCP_CONNECTED || !newsock) {
-			nfc_llcp_accept_unlink(sk);
+			list_del_init(&lsk->accept_queue);
+			sock_put(sk);
+
 			if (newsock)
 				sock_graft(sk, newsock);
 
@@ -403,7 +523,8 @@ static unsigned int llcp_sock_poll(struct file *file, struct socket *sock,
 		return llcp_accept_poll(sk);
 
 	if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
-		mask |= POLLERR;
+		mask |= POLLERR |
+			(sock_flag(sk, SOCK_SELECT_ERR_QUEUE) ? POLLPRI : 0);
 
 	if (!skb_queue_empty(&sk->sk_receive_queue))
 		mask |= POLLIN | POLLRDNORM;
@@ -464,8 +585,6 @@ static int llcp_sock_release(struct socket *sock)
 			nfc_llcp_accept_unlink(accept_sk);
 
 			release_sock(accept_sk);
-
-			sock_orphan(accept_sk);
 		}
 	}
 
@@ -543,7 +662,7 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr,
 
 	llcp_sock->dev = dev;
 	llcp_sock->local = nfc_llcp_local_get(local);
-	llcp_sock->miu = llcp_sock->local->remote_miu;
+	llcp_sock->remote_miu = llcp_sock->local->remote_miu;
 	llcp_sock->ssap = nfc_llcp_get_local_ssap(local);
 	if (llcp_sock->ssap == LLCP_SAP_MAX) {
 		ret = -ENOMEM;
@@ -737,8 +856,8 @@ static const struct proto_ops llcp_sock_ops = {
 	.ioctl          = sock_no_ioctl,
 	.listen         = llcp_sock_listen,
 	.shutdown       = sock_no_shutdown,
-	.setsockopt     = sock_no_setsockopt,
-	.getsockopt     = sock_no_getsockopt,
+	.setsockopt     = nfc_llcp_setsockopt,
+	.getsockopt     = nfc_llcp_getsockopt,
 	.sendmsg        = llcp_sock_sendmsg,
 	.recvmsg        = llcp_sock_recvmsg,
 	.mmap           = sock_no_mmap,
@@ -802,8 +921,10 @@ struct sock *nfc_llcp_sock_alloc(struct socket *sock, int type, gfp_t gfp)
 
 	llcp_sock->ssap = 0;
 	llcp_sock->dsap = LLCP_SAP_SDP;
-	llcp_sock->rw = LLCP_DEFAULT_RW;
-	llcp_sock->miu = LLCP_DEFAULT_MIU;
+	llcp_sock->rw = LLCP_MAX_RW + 1;
+	llcp_sock->miux = LLCP_MAX_MIUX + 1;
+	llcp_sock->remote_rw = LLCP_DEFAULT_RW;
+	llcp_sock->remote_miu = LLCP_DEFAULT_MIU;
 	llcp_sock->send_n = llcp_sock->send_ack_n = 0;
 	llcp_sock->recv_n = llcp_sock->recv_ack_n = 0;
 	llcp_sock->remote_ready = 1;
diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c
index 504b883..73fd510 100644
--- a/net/nfc/netlink.c
+++ b/net/nfc/netlink.c
@@ -53,6 +53,15 @@ static const struct nla_policy nfc_genl_policy[NFC_ATTR_MAX + 1] = {
 	[NFC_ATTR_DEVICE_POWERED] = { .type = NLA_U8 },
 	[NFC_ATTR_IM_PROTOCOLS] = { .type = NLA_U32 },
 	[NFC_ATTR_TM_PROTOCOLS] = { .type = NLA_U32 },
+	[NFC_ATTR_LLC_PARAM_LTO] = { .type = NLA_U8 },
+	[NFC_ATTR_LLC_PARAM_RW] = { .type = NLA_U8 },
+	[NFC_ATTR_LLC_PARAM_MIUX] = { .type = NLA_U16 },
+	[NFC_ATTR_LLC_SDP] = { .type = NLA_NESTED },
+};
+
+static const struct nla_policy nfc_sdp_genl_policy[NFC_SDP_ATTR_MAX + 1] = {
+	[NFC_SDP_ATTR_URI] = { .type = NLA_STRING },
+	[NFC_SDP_ATTR_SAP] = { .type = NLA_U8 },
 };
 
 static int nfc_genl_send_target(struct sk_buff *msg, struct nfc_target *target,
@@ -348,6 +357,74 @@ free_msg:
 	return -EMSGSIZE;
 }
 
+int nfc_genl_llc_send_sdres(struct nfc_dev *dev, struct hlist_head *sdres_list)
+{
+	struct sk_buff *msg;
+	struct nlattr *sdp_attr, *uri_attr;
+	struct nfc_llcp_sdp_tlv *sdres;
+	struct hlist_node *n;
+	void *hdr;
+	int rc = -EMSGSIZE;
+	int i;
+
+	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+	if (!msg)
+		return -ENOMEM;
+
+	hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0,
+			  NFC_EVENT_LLC_SDRES);
+	if (!hdr)
+		goto free_msg;
+
+	if (nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx))
+		goto nla_put_failure;
+
+	sdp_attr = nla_nest_start(msg, NFC_ATTR_LLC_SDP);
+	if (sdp_attr == NULL) {
+		rc = -ENOMEM;
+		goto nla_put_failure;
+	}
+
+	i = 1;
+	hlist_for_each_entry_safe(sdres, n, sdres_list, node) {
+		pr_debug("uri: %s, sap: %d\n", sdres->uri, sdres->sap);
+
+		uri_attr = nla_nest_start(msg, i++);
+		if (uri_attr == NULL) {
+			rc = -ENOMEM;
+			goto nla_put_failure;
+		}
+
+		if (nla_put_u8(msg, NFC_SDP_ATTR_SAP, sdres->sap))
+			goto nla_put_failure;
+
+		if (nla_put_string(msg, NFC_SDP_ATTR_URI, sdres->uri))
+			goto nla_put_failure;
+
+		nla_nest_end(msg, uri_attr);
+
+		hlist_del(&sdres->node);
+
+		nfc_llcp_free_sdp_tlv(sdres);
+	}
+
+	nla_nest_end(msg, sdp_attr);
+
+	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);
+
+	nfc_llcp_free_sdp_tlv_list(sdres_list);
+
+	return rc;
+}
+
 static int nfc_genl_send_device(struct sk_buff *msg, struct nfc_dev *dev,
 				u32 portid, u32 seq,
 				struct netlink_callback *cb,
@@ -859,6 +936,96 @@ exit:
 	return rc;
 }
 
+static int nfc_genl_llc_sdreq(struct sk_buff *skb, struct genl_info *info)
+{
+	struct nfc_dev *dev;
+	struct nfc_llcp_local *local;
+	struct nlattr *attr, *sdp_attrs[NFC_SDP_ATTR_MAX+1];
+	u32 idx;
+	u8 tid;
+	char *uri;
+	int rc = 0, rem;
+	size_t uri_len, tlvs_len;
+	struct hlist_head sdreq_list;
+	struct nfc_llcp_sdp_tlv *sdreq;
+
+	if (!info->attrs[NFC_ATTR_DEVICE_INDEX] ||
+	    !info->attrs[NFC_ATTR_LLC_SDP])
+		return -EINVAL;
+
+	idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]);
+
+	dev = nfc_get_device(idx);
+	if (!dev) {
+		rc = -ENODEV;
+		goto exit;
+	}
+
+	device_lock(&dev->dev);
+
+	if (dev->dep_link_up == false) {
+		rc = -ENOLINK;
+		goto exit;
+	}
+
+	local = nfc_llcp_find_local(dev);
+	if (!local) {
+		nfc_put_device(dev);
+		rc = -ENODEV;
+		goto exit;
+	}
+
+	INIT_HLIST_HEAD(&sdreq_list);
+
+	tlvs_len = 0;
+
+	nla_for_each_nested(attr, info->attrs[NFC_ATTR_LLC_SDP], rem) {
+		rc = nla_parse_nested(sdp_attrs, NFC_SDP_ATTR_MAX, attr,
+				      nfc_sdp_genl_policy);
+
+		if (rc != 0) {
+			rc = -EINVAL;
+			goto exit;
+		}
+
+		if (!sdp_attrs[NFC_SDP_ATTR_URI])
+			continue;
+
+		uri_len = nla_len(sdp_attrs[NFC_SDP_ATTR_URI]);
+		if (uri_len == 0)
+			continue;
+
+		uri = nla_data(sdp_attrs[NFC_SDP_ATTR_URI]);
+		if (uri == NULL || *uri == 0)
+			continue;
+
+		tid = local->sdreq_next_tid++;
+
+		sdreq = nfc_llcp_build_sdreq_tlv(tid, uri, uri_len);
+		if (sdreq == NULL) {
+			rc = -ENOMEM;
+			goto exit;
+		}
+
+		tlvs_len += sdreq->tlv_len;
+
+		hlist_add_head(&sdreq->node, &sdreq_list);
+	}
+
+	if (hlist_empty(&sdreq_list)) {
+		rc = -EINVAL;
+		goto exit;
+	}
+
+	rc = nfc_llcp_send_snl_sdreq(local, &sdreq_list, tlvs_len);
+exit:
+	device_unlock(&dev->dev);
+
+	nfc_put_device(dev);
+
+	return rc;
+}
+
 static struct genl_ops nfc_genl_ops[] = {
 	{
 		.cmd = NFC_CMD_GET_DEVICE,
@@ -913,6 +1080,11 @@ static struct genl_ops nfc_genl_ops[] = {
 		.doit = nfc_genl_llc_set_params,
 		.policy = nfc_genl_policy,
 	},
+	{
+		.cmd = NFC_CMD_LLC_SDREQ,
+		.doit = nfc_genl_llc_sdreq,
+		.policy = nfc_genl_policy,
+	},
 };
 
 
diff --git a/net/nfc/nfc.h b/net/nfc/nfc.h
index 87d914d..94bfe19 100644
--- a/net/nfc/nfc.h
+++ b/net/nfc/nfc.h
@@ -46,6 +46,8 @@ struct nfc_rawsock {
 #define to_rawsock_sk(_tx_work) \
 	((struct sock *) container_of(_tx_work, struct nfc_rawsock, tx_work))
 
+struct nfc_llcp_sdp_tlv;
+
 #ifdef CONFIG_NFC_LLCP
 
 void nfc_llcp_mac_is_down(struct nfc_dev *dev);
@@ -59,6 +61,8 @@ int nfc_llcp_data_received(struct nfc_dev *dev, struct sk_buff *skb);
 struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev);
 int __init nfc_llcp_init(void);
 void nfc_llcp_exit(void);
+void nfc_llcp_free_sdp_tlv(struct nfc_llcp_sdp_tlv *sdp);
+void nfc_llcp_free_sdp_tlv_list(struct hlist_head *head);
 
 #else
 
@@ -112,6 +116,14 @@ static inline void nfc_llcp_exit(void)
 {
 }
 
+static inline void nfc_llcp_free_sdp_tlv(struct nfc_llcp_sdp_tlv *sdp)
+{
+}
+
+static inline void nfc_llcp_free_sdp_tlv_list(struct hlist_head *sdp_head)
+{
+}
+
 #endif
 
 int __init rawsock_init(void);
@@ -144,6 +156,8 @@ int nfc_genl_dep_link_down_event(struct nfc_dev *dev);
 int nfc_genl_tm_activated(struct nfc_dev *dev, u32 protocol);
 int nfc_genl_tm_deactivated(struct nfc_dev *dev);
 
+int nfc_genl_llc_send_sdres(struct nfc_dev *dev, struct hlist_head *sdres_list);
+
 struct nfc_dev *nfc_get_device(unsigned int idx);
 
 static inline void nfc_put_device(struct nfc_dev *dev)
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index a4b7247..8759265 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -369,8 +369,8 @@ static int queue_userspace_packet(struct net *net, int dp_ifindex,
 	len = sizeof(struct ovs_header);
 	len += nla_total_size(skb->len);
 	len += nla_total_size(FLOW_BUFSIZE);
-	if (upcall_info->cmd == OVS_PACKET_CMD_ACTION)
-		len += nla_total_size(8);
+	if (upcall_info->userdata)
+		len += NLA_ALIGN(upcall_info->userdata->nla_len);
 
 	user_skb = genlmsg_new(len, GFP_ATOMIC);
 	if (!user_skb) {
@@ -387,8 +387,9 @@ static int queue_userspace_packet(struct net *net, int dp_ifindex,
 	nla_nest_end(user_skb, nla);
 
 	if (upcall_info->userdata)
-		nla_put_u64(user_skb, OVS_PACKET_ATTR_USERDATA,
-			    nla_get_u64(upcall_info->userdata));
+		__nla_put(user_skb, OVS_PACKET_ATTR_USERDATA,
+			  nla_len(upcall_info->userdata),
+			  nla_data(upcall_info->userdata));
 
 	nla = __nla_reserve(user_skb, OVS_PACKET_ATTR_PACKET, skb->len);
 
@@ -544,7 +545,7 @@ static int validate_userspace(const struct nlattr *attr)
 {
 	static const struct nla_policy userspace_policy[OVS_USERSPACE_ATTR_MAX + 1] =	{
 		[OVS_USERSPACE_ATTR_PID] = {.type = NLA_U32 },
-		[OVS_USERSPACE_ATTR_USERDATA] = {.type = NLA_U64 },
+		[OVS_USERSPACE_ATTR_USERDATA] = {.type = NLA_UNSPEC },
 	};
 	struct nlattr *a[OVS_USERSPACE_ATTR_MAX + 1];
 	int error;
@@ -680,7 +681,7 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
 	/* Normally, setting the skb 'protocol' field would be handled by a
 	 * call to eth_type_trans(), but it assumes there's a sending
 	 * device, which we may not have. */
-	if (ntohs(eth->h_proto) >= 1536)
+	if (ntohs(eth->h_proto) >= ETH_P_802_3_MIN)
 		packet->protocol = eth->h_proto;
 	else
 		packet->protocol = htons(ETH_P_802_2);
@@ -1628,7 +1629,7 @@ static struct vport *lookup_vport(struct net *net,
 
 		vport = ovs_vport_rtnl_rcu(dp, port_no);
 		if (!vport)
-			return ERR_PTR(-ENOENT);
+			return ERR_PTR(-ENODEV);
 		return vport;
 	} else
 		return ERR_PTR(-EINVAL);
diff --git a/net/openvswitch/datapath.h b/net/openvswitch/datapath.h
index 031dfbf..9125ad5 100644
--- a/net/openvswitch/datapath.h
+++ b/net/openvswitch/datapath.h
@@ -119,7 +119,7 @@ struct ovs_skb_cb {
  * struct dp_upcall - metadata to include with a packet to send to userspace
  * @cmd: One of %OVS_PACKET_CMD_*.
  * @key: Becomes %OVS_PACKET_ATTR_KEY.  Must be nonnull.
- * @userdata: If nonnull, its u64 value is extracted and passed to userspace as
+ * @userdata: If nonnull, its variable-length value is passed to userspace as
  * %OVS_PACKET_ATTR_USERDATA.
  * @pid: Netlink PID to which packet should be sent.  If @pid is 0 then no
  * packet is sent and the packet is accounted in the datapath's @n_lost
diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
index fe0e421..3324868 100644
--- a/net/openvswitch/flow.c
+++ b/net/openvswitch/flow.c
@@ -466,7 +466,7 @@ static __be16 parse_ethertype(struct sk_buff *skb)
 	proto = *(__be16 *) skb->data;
 	__skb_pull(skb, sizeof(__be16));
 
-	if (ntohs(proto) >= 1536)
+	if (ntohs(proto) >= ETH_P_802_3_MIN)
 		return proto;
 
 	if (skb->len < sizeof(struct llc_snap_hdr))
@@ -483,7 +483,7 @@ static __be16 parse_ethertype(struct sk_buff *skb)
 
 	__skb_pull(skb, sizeof(struct llc_snap_hdr));
 
-	if (ntohs(llc->ethertype) >= 1536)
+	if (ntohs(llc->ethertype) >= ETH_P_802_3_MIN)
 		return llc->ethertype;
 
 	return htons(ETH_P_802_2);
@@ -1038,7 +1038,7 @@ int ovs_flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp,
 
 	if (attrs & (1 << OVS_KEY_ATTR_ETHERTYPE)) {
 		swkey->eth.type = nla_get_be16(a[OVS_KEY_ATTR_ETHERTYPE]);
-		if (ntohs(swkey->eth.type) < 1536)
+		if (ntohs(swkey->eth.type) < ETH_P_802_3_MIN)
 			return -EINVAL;
 		attrs &= ~(1 << OVS_KEY_ATTR_ETHERTYPE);
 	} else {
diff --git a/net/openvswitch/vport-internal_dev.c b/net/openvswitch/vport-internal_dev.c
index 0531de6..40f8a24 100644
--- a/net/openvswitch/vport-internal_dev.c
+++ b/net/openvswitch/vport-internal_dev.c
@@ -63,16 +63,6 @@ static struct rtnl_link_stats64 *internal_dev_get_stats(struct net_device *netde
 	return stats;
 }
 
-static int internal_dev_mac_addr(struct net_device *dev, void *p)
-{
-	struct sockaddr *addr = p;
-
-	if (!is_valid_ether_addr(addr->sa_data))
-		return -EADDRNOTAVAIL;
-	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
-	return 0;
-}
-
 /* Called with rcu_read_lock_bh. */
 static int internal_dev_xmit(struct sk_buff *skb, struct net_device *netdev)
 {
@@ -126,7 +116,7 @@ static const struct net_device_ops internal_dev_netdev_ops = {
 	.ndo_open = internal_dev_open,
 	.ndo_stop = internal_dev_stop,
 	.ndo_start_xmit = internal_dev_xmit,
-	.ndo_set_mac_address = internal_dev_mac_addr,
+	.ndo_set_mac_address = eth_mac_addr,
 	.ndo_change_mtu = internal_dev_change_mtu,
 	.ndo_get_stats64 = internal_dev_get_stats,
 };
@@ -138,6 +128,7 @@ static void do_setup(struct net_device *netdev)
 	netdev->netdev_ops = &internal_dev_netdev_ops;
 
 	netdev->priv_flags &= ~IFF_TX_SKB_SHARING;
+	netdev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
 	netdev->destructor = internal_dev_destructor;
 	SET_ETHTOOL_OPS(netdev, &internal_dev_ethtool_ops);
 	netdev->tx_queue_len = 0;
diff --git a/net/openvswitch/vport.h b/net/openvswitch/vport.h
index 3f7961e..aee7d43 100644
--- a/net/openvswitch/vport.h
+++ b/net/openvswitch/vport.h
@@ -68,10 +68,10 @@ struct vport_err_stats {
 /**
  * struct vport - one port within a datapath
  * @rcu: RCU callback head for deferred destruction.
- * @port_no: Index into @dp's @ports array.
  * @dp: Datapath to which this port belongs.
  * @upcall_portid: The Netlink port to use for packets received on this port that
  * miss the flow table.
+ * @port_no: Index into @dp's @ports array.
  * @hash_node: Element in @dev_table hash table in vport.c.
  * @dp_hash_node: Element in @datapath->ports hash table in datapath.c.
  * @ops: Class structure.
@@ -81,9 +81,9 @@ struct vport_err_stats {
  */
 struct vport {
 	struct rcu_head rcu;
-	u16 port_no;
 	struct datapath	*dp;
 	u32 upcall_portid;
+	u16 port_no;
 
 	struct hlist_node hash_node;
 	struct hlist_node dp_hash_node;
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 1d6793d..8e4644f 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -181,6 +181,8 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
 
 struct packet_sock;
 static int tpacket_snd(struct packet_sock *po, struct msghdr *msg);
+static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
+		       struct packet_type *pt, struct net_device *orig_dev);
 
 static void *packet_previous_frame(struct packet_sock *po,
 		struct packet_ring_buffer *rb,
@@ -973,11 +975,11 @@ static void *packet_current_rx_frame(struct packet_sock *po,
 
 static void *prb_lookup_block(struct packet_sock *po,
 				     struct packet_ring_buffer *rb,
-				     unsigned int previous,
+				     unsigned int idx,
 				     int status)
 {
 	struct tpacket_kbdq_core *pkc  = GET_PBDQC_FROM_RB(rb);
-	struct tpacket_block_desc *pbd = GET_PBLOCK_DESC(pkc, previous);
+	struct tpacket_block_desc *pbd = GET_PBLOCK_DESC(pkc, idx);
 
 	if (status != BLOCK_STATUS(pbd))
 		return NULL;
@@ -1041,6 +1043,29 @@ static void packet_increment_head(struct packet_ring_buffer *buff)
 	buff->head = buff->head != buff->frame_max ? buff->head+1 : 0;
 }
 
+static bool packet_rcv_has_room(struct packet_sock *po, struct sk_buff *skb)
+{
+	struct sock *sk = &po->sk;
+	bool has_room;
+
+	if (po->prot_hook.func != tpacket_rcv)
+		return (atomic_read(&sk->sk_rmem_alloc) + skb->truesize)
+			<= sk->sk_rcvbuf;
+
+	spin_lock(&sk->sk_receive_queue.lock);
+	if (po->tp_version == TPACKET_V3)
+		has_room = prb_lookup_block(po, &po->rx_ring,
+					    po->rx_ring.prb_bdqc.kactive_blk_num,
+					    TP_STATUS_KERNEL);
+	else
+		has_room = packet_lookup_frame(po, &po->rx_ring,
+					       po->rx_ring.head,
+					       TP_STATUS_KERNEL);
+	spin_unlock(&sk->sk_receive_queue.lock);
+
+	return has_room;
+}
+
 static void packet_sock_destruct(struct sock *sk)
 {
 	skb_queue_purge(&sk->sk_error_queue);
@@ -1066,16 +1091,16 @@ static int fanout_rr_next(struct packet_fanout *f, unsigned int num)
 	return x;
 }
 
-static struct sock *fanout_demux_hash(struct packet_fanout *f, struct sk_buff *skb, unsigned int num)
+static unsigned int 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];
+	return (((u64)skb->rxhash) * num) >> 32;
 }
 
-static struct sock *fanout_demux_lb(struct packet_fanout *f, struct sk_buff *skb, unsigned int num)
+static unsigned int fanout_demux_lb(struct packet_fanout *f,
+				    struct sk_buff *skb,
+				    unsigned int num)
 {
 	int cur, old;
 
@@ -1083,14 +1108,40 @@ static struct sock *fanout_demux_lb(struct packet_fanout *f, struct sk_buff *skb
 	while ((old = atomic_cmpxchg(&f->rr_cur, cur,
 				     fanout_rr_next(f, num))) != cur)
 		cur = old;
-	return f->arr[cur];
+	return cur;
+}
+
+static unsigned int fanout_demux_cpu(struct packet_fanout *f,
+				     struct sk_buff *skb,
+				     unsigned int num)
+{
+	return smp_processor_id() % num;
 }
 
-static struct sock *fanout_demux_cpu(struct packet_fanout *f, struct sk_buff *skb, unsigned int num)
+static unsigned int fanout_demux_rollover(struct packet_fanout *f,
+					  struct sk_buff *skb,
+					  unsigned int idx, unsigned int skip,
+					  unsigned int num)
 {
-	unsigned int cpu = smp_processor_id();
+	unsigned int i, j;
+
+	i = j = min_t(int, f->next[idx], num - 1);
+	do {
+		if (i != skip && packet_rcv_has_room(pkt_sk(f->arr[i]), skb)) {
+			if (i != j)
+				f->next[idx] = i;
+			return i;
+		}
+		if (++i == num)
+			i = 0;
+	} while (i != j);
 
-	return f->arr[cpu % num];
+	return idx;
+}
+
+static bool fanout_has_flag(struct packet_fanout *f, u16 flag)
+{
+	return f->flags & (flag >> 8);
 }
 
 static int packet_rcv_fanout(struct sk_buff *skb, struct net_device *dev,
@@ -1099,7 +1150,7 @@ static int packet_rcv_fanout(struct sk_buff *skb, struct net_device *dev,
 	struct packet_fanout *f = pt->af_packet_priv;
 	unsigned int num = f->num_members;
 	struct packet_sock *po;
-	struct sock *sk;
+	unsigned int idx;
 
 	if (!net_eq(dev_net(dev), read_pnet(&f->net)) ||
 	    !num) {
@@ -1110,23 +1161,31 @@ static int packet_rcv_fanout(struct sk_buff *skb, struct net_device *dev,
 	switch (f->type) {
 	case PACKET_FANOUT_HASH:
 	default:
-		if (f->defrag) {
+		if (fanout_has_flag(f, PACKET_FANOUT_FLAG_DEFRAG)) {
 			skb = ip_check_defrag(skb, IP_DEFRAG_AF_PACKET);
 			if (!skb)
 				return 0;
 		}
 		skb_get_rxhash(skb);
-		sk = fanout_demux_hash(f, skb, num);
+		idx = fanout_demux_hash(f, skb, num);
 		break;
 	case PACKET_FANOUT_LB:
-		sk = fanout_demux_lb(f, skb, num);
+		idx = fanout_demux_lb(f, skb, num);
 		break;
 	case PACKET_FANOUT_CPU:
-		sk = fanout_demux_cpu(f, skb, num);
+		idx = fanout_demux_cpu(f, skb, num);
+		break;
+	case PACKET_FANOUT_ROLLOVER:
+		idx = fanout_demux_rollover(f, skb, 0, (unsigned int) -1, num);
 		break;
 	}
 
-	po = pkt_sk(sk);
+	po = pkt_sk(f->arr[idx]);
+	if (fanout_has_flag(f, PACKET_FANOUT_FLAG_ROLLOVER) &&
+	    unlikely(!packet_rcv_has_room(po, skb))) {
+		idx = fanout_demux_rollover(f, skb, idx, idx, num);
+		po = pkt_sk(f->arr[idx]);
+	}
 
 	return po->prot_hook.func(skb, dev, &po->prot_hook, orig_dev);
 }
@@ -1175,10 +1234,13 @@ 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;
+	u8 flags = type_flags >> 8;
 	int err;
 
 	switch (type) {
+	case PACKET_FANOUT_ROLLOVER:
+		if (type_flags & PACKET_FANOUT_FLAG_ROLLOVER)
+			return -EINVAL;
 	case PACKET_FANOUT_HASH:
 	case PACKET_FANOUT_LB:
 	case PACKET_FANOUT_CPU:
@@ -1203,7 +1265,7 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags)
 		}
 	}
 	err = -EINVAL;
-	if (match && match->defrag != defrag)
+	if (match && match->flags != flags)
 		goto out;
 	if (!match) {
 		err = -ENOMEM;
@@ -1213,7 +1275,7 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags)
 		write_pnet(&match->net, sock_net(sk));
 		match->id = id;
 		match->type = type;
-		match->defrag = defrag;
+		match->flags = flags;
 		atomic_set(&match->rr_cur, 0);
 		INIT_LIST_HEAD(&match->list);
 		spin_lock_init(&match->lock);
@@ -1450,6 +1512,8 @@ retry:
 	if (unlikely(extra_len == 4))
 		skb->no_fcs = 1;
 
+	skb_probe_transport_header(skb, 0);
+
 	dev_queue_xmit(skb);
 	rcu_read_unlock();
 	return len;
@@ -1880,6 +1944,7 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb,
 
 	skb_reserve(skb, hlen);
 	skb_reset_network_header(skb);
+	skb_probe_transport_header(skb, 0);
 
 	if (po->tp_tx_has_off) {
 		int off_min, off_max, off;
@@ -2289,6 +2354,8 @@ static int packet_snd(struct socket *sock,
 		len += vnet_hdr_len;
 	}
 
+	skb_probe_transport_header(skb, reserve);
+
 	if (unlikely(extra_len == 4))
 		skb->no_fcs = 1;
 
@@ -3240,7 +3307,8 @@ static int packet_getsockopt(struct socket *sock, int level, int optname,
 	case PACKET_FANOUT:
 		val = (po->fanout ?
 		       ((u32)po->fanout->id |
-			((u32)po->fanout->type << 16)) :
+			((u32)po->fanout->type << 16) |
+			((u32)po->fanout->flags << 24)) :
 		       0);
 		break;
 	case PACKET_TX_HAS_OFF:
diff --git a/net/packet/internal.h b/net/packet/internal.h
index e84cab8..e891f02 100644
--- a/net/packet/internal.h
+++ b/net/packet/internal.h
@@ -77,10 +77,11 @@ struct packet_fanout {
 	unsigned int		num_members;
 	u16			id;
 	u8			type;
-	u8			defrag;
+	u8			flags;
 	atomic_t		rr_cur;
 	struct list_head	list;
 	struct sock		*arr[PACKET_FANOUT_MAX];
+	int			next[PACKET_FANOUT_MAX];
 	spinlock_t		lock;
 	atomic_t		sk_ref;
 	struct packet_type	prot_hook ____cacheline_aligned_in_smp;
diff --git a/net/phonet/pn_netlink.c b/net/phonet/pn_netlink.c
index 0193630..dc15f43 100644
--- a/net/phonet/pn_netlink.c
+++ b/net/phonet/pn_netlink.c
@@ -61,7 +61,7 @@ static const struct nla_policy ifa_phonet_policy[IFA_MAX+1] = {
 	[IFA_LOCAL] = { .type = NLA_U8 },
 };
 
-static int addr_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *attr)
+static int addr_doit(struct sk_buff *skb, struct nlmsghdr *nlh)
 {
 	struct net *net = sock_net(skb->sk);
 	struct nlattr *tb[IFA_MAX+1];
@@ -224,7 +224,7 @@ static const struct nla_policy rtm_phonet_policy[RTA_MAX+1] = {
 	[RTA_OIF] = { .type = NLA_U32 },
 };
 
-static int route_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *attr)
+static int route_doit(struct sk_buff *skb, struct nlmsghdr *nlh)
 {
 	struct net *net = sock_net(skb->sk);
 	struct nlattr *tb[RTA_MAX+1];
diff --git a/net/rfkill/rfkill-regulator.c b/net/rfkill/rfkill-regulator.c
index 4b5ab21..d11ac79 100644
--- a/net/rfkill/rfkill-regulator.c
+++ b/net/rfkill/rfkill-regulator.c
@@ -51,7 +51,7 @@ static int rfkill_regulator_set_block(void *data, bool blocked)
 	return 0;
 }
 
-struct rfkill_ops rfkill_regulator_ops = {
+static struct rfkill_ops rfkill_regulator_ops = {
 	.set_block = rfkill_regulator_set_block,
 };
 
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index 8579c4b..fd70728 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -982,7 +982,7 @@ done:
 	return ret;
 }
 
-static int tc_ctl_action(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
+static int tc_ctl_action(struct sk_buff *skb, struct nlmsghdr *n)
 {
 	struct net *net = sock_net(skb->sk);
 	struct nlattr *tca[TCA_ACT_MAX + 1];
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 964f5e4..5c81b26 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -22,7 +22,7 @@
 #include <linux/skbuff.h>
 #include <linux/init.h>
 #include <linux/kmod.h>
-#include <linux/netlink.h>
+#include <net/netlink.h>
 #include <linux/err.h>
 #include <linux/slab.h>
 #include <net/net_namespace.h>
@@ -118,7 +118,7 @@ static inline u32 tcf_auto_prio(struct tcf_proto *tp)
 
 /* Add/change/delete/get a filter node */
 
-static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
+static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n)
 {
 	struct net *net = sock_net(skb->sk);
 	struct nlattr *tca[TCA_MAX + 1];
@@ -141,7 +141,12 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
 
 	if ((n->nlmsg_type != RTM_GETTFILTER) && !capable(CAP_NET_ADMIN))
 		return -EPERM;
+
 replay:
+	err = nlmsg_parse(n, sizeof(*t), tca, TCA_MAX, NULL);
+	if (err < 0)
+		return err;
+
 	t = nlmsg_data(n);
 	protocol = TC_H_MIN(t->tcm_info);
 	prio = TC_H_MAJ(t->tcm_info);
@@ -164,10 +169,6 @@ replay:
 	if (dev == NULL)
 		return -ENODEV;
 
-	err = nlmsg_parse(n, sizeof(*t), tca, TCA_MAX, NULL);
-	if (err < 0)
-		return err;
-
 	/* Find qdisc */
 	if (!parent) {
 		q = dev->qdisc;
@@ -427,7 +428,7 @@ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb)
 	const struct Qdisc_class_ops *cops;
 	struct tcf_dump_args arg;
 
-	if (cb->nlh->nlmsg_len < NLMSG_LENGTH(sizeof(*tcm)))
+	if (nlmsg_len(cb->nlh) < sizeof(*tcm))
 		return skb->len;
 	dev = __dev_get_by_index(net, tcm->tcm_ifindex);
 	if (!dev)
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index c297e2a..2b935e7 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -971,13 +971,13 @@ check_loop_fn(struct Qdisc *q, unsigned long cl, struct qdisc_walker *w)
  * Delete/get qdisc.
  */
 
-static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
+static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n)
 {
 	struct net *net = sock_net(skb->sk);
 	struct tcmsg *tcm = nlmsg_data(n);
 	struct nlattr *tca[TCA_MAX + 1];
 	struct net_device *dev;
-	u32 clid = tcm->tcm_parent;
+	u32 clid;
 	struct Qdisc *q = NULL;
 	struct Qdisc *p = NULL;
 	int err;
@@ -985,14 +985,15 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
 	if ((n->nlmsg_type != RTM_GETQDISC) && !capable(CAP_NET_ADMIN))
 		return -EPERM;
 
-	dev = __dev_get_by_index(net, tcm->tcm_ifindex);
-	if (!dev)
-		return -ENODEV;
-
 	err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL);
 	if (err < 0)
 		return err;
 
+	dev = __dev_get_by_index(net, tcm->tcm_ifindex);
+	if (!dev)
+		return -ENODEV;
+
+	clid = tcm->tcm_parent;
 	if (clid) {
 		if (clid != TC_H_ROOT) {
 			if (TC_H_MAJ(clid) != TC_H_MAJ(TC_H_INGRESS)) {
@@ -1038,7 +1039,7 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
  * Create/change qdisc.
  */
 
-static int tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
+static int tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n)
 {
 	struct net *net = sock_net(skb->sk);
 	struct tcmsg *tcm;
@@ -1053,6 +1054,10 @@ static int tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
 
 replay:
 	/* Reinit, just in case something touches this. */
+	err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL);
+	if (err < 0)
+		return err;
+
 	tcm = nlmsg_data(n);
 	clid = tcm->tcm_parent;
 	q = p = NULL;
@@ -1061,9 +1066,6 @@ replay:
 	if (!dev)
 		return -ENODEV;
 
-	err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL);
-	if (err < 0)
-		return err;
 
 	if (clid) {
 		if (clid != TC_H_ROOT) {
@@ -1372,7 +1374,7 @@ done:
 
 
 
-static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
+static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n)
 {
 	struct net *net = sock_net(skb->sk);
 	struct tcmsg *tcm = nlmsg_data(n);
@@ -1382,22 +1384,22 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
 	const struct Qdisc_class_ops *cops;
 	unsigned long cl = 0;
 	unsigned long new_cl;
-	u32 portid = tcm->tcm_parent;
-	u32 clid = tcm->tcm_handle;
-	u32 qid = TC_H_MAJ(clid);
+	u32 portid;
+	u32 clid;
+	u32 qid;
 	int err;
 
 	if ((n->nlmsg_type != RTM_GETTCLASS) && !capable(CAP_NET_ADMIN))
 		return -EPERM;
 
-	dev = __dev_get_by_index(net, tcm->tcm_ifindex);
-	if (!dev)
-		return -ENODEV;
-
 	err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL);
 	if (err < 0)
 		return err;
 
+	dev = __dev_get_by_index(net, tcm->tcm_ifindex);
+	if (!dev)
+		return -ENODEV;
+
 	/*
 	   parent == TC_H_UNSPEC - unspecified parent.
 	   parent == TC_H_ROOT   - class is root, which has no parent.
@@ -1413,6 +1415,10 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
 
 	/* Step 1. Determine qdisc handle X:0 */
 
+	portid = tcm->tcm_parent;
+	clid = tcm->tcm_handle;
+	qid = TC_H_MAJ(clid);
+
 	if (portid != TC_H_ROOT) {
 		u32 qid1 = TC_H_MAJ(portid);
 
@@ -1636,7 +1642,7 @@ static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb)
 	struct net_device *dev;
 	int t, s_t;
 
-	if (cb->nlh->nlmsg_len < NLMSG_LENGTH(sizeof(*tcm)))
+	if (nlmsg_len(cb->nlh) < sizeof(*tcm))
 		return 0;
 	dev = dev_get_by_index(net, tcm->tcm_ifindex);
 	if (!dev)
diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c
index 13aa47a..1bc210f 100644
--- a/net/sched/sch_cbq.c
+++ b/net/sched/sch_cbq.c
@@ -962,8 +962,11 @@ cbq_dequeue(struct Qdisc *sch)
 		cbq_update(q);
 		if ((incr -= incr2) < 0)
 			incr = 0;
+		q->now += incr;
+	} else {
+		if (now > q->now)
+			q->now = now;
 	}
-	q->now += incr;
 	q->now_rt = now;
 
 	for (;;) {
diff --git a/net/sched/sch_choke.c b/net/sched/sch_choke.c
index cc37dd5..ef53ab8 100644
--- a/net/sched/sch_choke.c
+++ b/net/sched/sch_choke.c
@@ -80,7 +80,7 @@ struct choke_sched_data {
 /* deliver a random number between 0 and N - 1 */
 static u32 random_N(unsigned int N)
 {
-	return reciprocal_divide(random32(), N);
+	return reciprocal_divide(prandom_u32(), N);
 }
 
 /* number of elements in queue including holes */
diff --git a/net/sched/sch_fq_codel.c b/net/sched/sch_fq_codel.c
index 4e606fc..5578628 100644
--- a/net/sched/sch_fq_codel.c
+++ b/net/sched/sch_fq_codel.c
@@ -195,7 +195,7 @@ static int fq_codel_enqueue(struct sk_buff *skb, struct Qdisc *sch)
 		flow->deficit = q->quantum;
 		flow->dropped = 0;
 	}
-	if (++sch->q.qlen < sch->limit)
+	if (++sch->q.qlen <= sch->limit)
 		return NET_XMIT_SUCCESS;
 
 	q->drop_overlimit++;
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index ffad481..eac7e0e 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -904,7 +904,7 @@ void psched_ratecfg_precompute(struct psched_ratecfg *r, u32 rate)
 	u64 mult;
 	int shift;
 
-	r->rate_bps = rate << 3;
+	r->rate_bps = (u64)rate << 3;
 	r->shift = 0;
 	r->mult = 1;
 	/*
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c
index 571f1d2..79b1876 100644
--- a/net/sched/sch_htb.c
+++ b/net/sched/sch_htb.c
@@ -981,6 +981,7 @@ static const struct nla_policy htb_policy[TCA_HTB_MAX + 1] = {
 	[TCA_HTB_INIT]	= { .len = sizeof(struct tc_htb_glob) },
 	[TCA_HTB_CTAB]	= { .type = NLA_BINARY, .len = TC_RTAB_SIZE },
 	[TCA_HTB_RTAB]	= { .type = NLA_BINARY, .len = TC_RTAB_SIZE },
+	[TCA_HTB_DIRECT_QLEN] = { .type = NLA_U32 },
 };
 
 static void htb_work_func(struct work_struct *work)
@@ -994,7 +995,7 @@ static void htb_work_func(struct work_struct *work)
 static int htb_init(struct Qdisc *sch, struct nlattr *opt)
 {
 	struct htb_sched *q = qdisc_priv(sch);
-	struct nlattr *tb[TCA_HTB_INIT + 1];
+	struct nlattr *tb[TCA_HTB_MAX + 1];
 	struct tc_htb_glob *gopt;
 	int err;
 	int i;
@@ -1002,20 +1003,16 @@ static int htb_init(struct Qdisc *sch, struct nlattr *opt)
 	if (!opt)
 		return -EINVAL;
 
-	err = nla_parse_nested(tb, TCA_HTB_INIT, opt, htb_policy);
+	err = nla_parse_nested(tb, TCA_HTB_MAX, opt, htb_policy);
 	if (err < 0)
 		return err;
 
-	if (tb[TCA_HTB_INIT] == NULL) {
-		pr_err("HTB: hey probably you have bad tc tool ?\n");
+	if (!tb[TCA_HTB_INIT])
 		return -EINVAL;
-	}
+
 	gopt = nla_data(tb[TCA_HTB_INIT]);
-	if (gopt->version != HTB_VER >> 16) {
-		pr_err("HTB: need tc/htb version %d (minor is %d), you have %d\n",
-		       HTB_VER >> 16, HTB_VER & 0xffff, gopt->version);
+	if (gopt->version != HTB_VER >> 16)
 		return -EINVAL;
-	}
 
 	err = qdisc_class_hash_init(&q->clhash);
 	if (err < 0)
@@ -1027,10 +1024,13 @@ static int htb_init(struct Qdisc *sch, struct nlattr *opt)
 	INIT_WORK(&q->work, htb_work_func);
 	skb_queue_head_init(&q->direct_queue);
 
-	q->direct_qlen = qdisc_dev(sch)->tx_queue_len;
-	if (q->direct_qlen < 2)	/* some devices have zero tx_queue_len */
-		q->direct_qlen = 2;
-
+	if (tb[TCA_HTB_DIRECT_QLEN])
+		q->direct_qlen = nla_get_u32(tb[TCA_HTB_DIRECT_QLEN]);
+	else {
+		q->direct_qlen = qdisc_dev(sch)->tx_queue_len;
+		if (q->direct_qlen < 2)	/* some devices have zero tx_queue_len */
+			q->direct_qlen = 2;
+	}
 	if ((q->rate2quantum = gopt->rate2quantum) < 1)
 		q->rate2quantum = 1;
 	q->defcls = gopt->defcls;
@@ -1056,7 +1056,8 @@ static int htb_dump(struct Qdisc *sch, struct sk_buff *skb)
 	nest = nla_nest_start(skb, TCA_OPTIONS);
 	if (nest == NULL)
 		goto nla_put_failure;
-	if (nla_put(skb, TCA_HTB_INIT, sizeof(gopt), &gopt))
+	if (nla_put(skb, TCA_HTB_INIT, sizeof(gopt), &gopt) ||
+	    nla_put_u32(skb, TCA_HTB_DIRECT_QLEN, q->direct_qlen))
 		goto nla_put_failure;
 	nla_nest_end(skb, nest);
 
@@ -1311,7 +1312,7 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
 	struct htb_sched *q = qdisc_priv(sch);
 	struct htb_class *cl = (struct htb_class *)*arg, *parent;
 	struct nlattr *opt = tca[TCA_OPTIONS];
-	struct nlattr *tb[__TCA_HTB_MAX];
+	struct nlattr *tb[TCA_HTB_MAX + 1];
 	struct tc_htb_opt *hopt;
 
 	/* extract all subattrs from opt attr */
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 1c2e46c..eaee00c 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -1403,7 +1403,7 @@ SCTP_STATIC __init int sctp_init(void)
 
 	/* Allocate and initialize the endpoint hash table.  */
 	sctp_ep_hashsize = 64;
-	sctp_ep_hashtable = (struct sctp_hashbucket *)
+	sctp_ep_hashtable =
 		kmalloc(64 * sizeof(struct sctp_hashbucket), GFP_KERNEL);
 	if (!sctp_ep_hashtable) {
 		pr_err("Failed endpoint_hash alloc\n");
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index b907073..dd21ae3 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -6185,7 +6185,8 @@ unsigned int sctp_poll(struct file *file, struct socket *sock, poll_table *wait)
 
 	/* Is there any exceptional events?  */
 	if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
-		mask |= POLLERR;
+		mask |= POLLERR |
+			sock_flag(sk, SOCK_SELECT_ERR_QUEUE) ? POLLPRI : 0;
 	if (sk->sk_shutdown & RCV_SHUTDOWN)
 		mask |= POLLRDHUP | POLLIN | POLLRDNORM;
 	if (sk->sk_shutdown == SHUTDOWN_MASK)
diff --git a/net/sunrpc/Kconfig b/net/sunrpc/Kconfig
index 516fe2c..241b54f 100644
--- a/net/sunrpc/Kconfig
+++ b/net/sunrpc/Kconfig
@@ -3,6 +3,7 @@ config SUNRPC
 
 config SUNRPC_GSS
 	tristate
+	select OID_REGISTRY
 
 config SUNRPC_BACKCHANNEL
 	bool
@@ -24,7 +25,6 @@ config SUNRPC_XPRT_RDMA
 config SUNRPC_SWAP
 	bool
 	depends on SUNRPC
-	select NETVM
 
 config RPCSEC_GSS_KRB5
 	tristate "Secure RPC: Kerberos V mechanism"
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c
index f529404..ed2fdd2 100644
--- a/net/sunrpc/auth.c
+++ b/net/sunrpc/auth.c
@@ -82,7 +82,7 @@ MODULE_PARM_DESC(auth_hashtable_size, "RPC credential cache hashtable size");
 
 static u32
 pseudoflavor_to_flavor(u32 flavor) {
-	if (flavor >= RPC_AUTH_MAXFLAVOR)
+	if (flavor > RPC_AUTH_MAXFLAVOR)
 		return RPC_AUTH_GSS;
 	return flavor;
 }
@@ -124,6 +124,79 @@ rpcauth_unregister(const struct rpc_authops *ops)
 EXPORT_SYMBOL_GPL(rpcauth_unregister);
 
 /**
+ * rpcauth_get_pseudoflavor - check if security flavor is supported
+ * @flavor: a security flavor
+ * @info: a GSS mech OID, quality of protection, and service value
+ *
+ * Verifies that an appropriate kernel module is available or already loaded.
+ * Returns an equivalent pseudoflavor, or RPC_AUTH_MAXFLAVOR if "flavor" is
+ * not supported locally.
+ */
+rpc_authflavor_t
+rpcauth_get_pseudoflavor(rpc_authflavor_t flavor, struct rpcsec_gss_info *info)
+{
+	const struct rpc_authops *ops;
+	rpc_authflavor_t pseudoflavor;
+
+	ops = auth_flavors[flavor];
+	if (ops == NULL)
+		request_module("rpc-auth-%u", flavor);
+	spin_lock(&rpc_authflavor_lock);
+	ops = auth_flavors[flavor];
+	if (ops == NULL || !try_module_get(ops->owner)) {
+		spin_unlock(&rpc_authflavor_lock);
+		return RPC_AUTH_MAXFLAVOR;
+	}
+	spin_unlock(&rpc_authflavor_lock);
+
+	pseudoflavor = flavor;
+	if (ops->info2flavor != NULL)
+		pseudoflavor = ops->info2flavor(info);
+
+	module_put(ops->owner);
+	return pseudoflavor;
+}
+EXPORT_SYMBOL_GPL(rpcauth_get_pseudoflavor);
+
+/**
+ * rpcauth_get_gssinfo - find GSS tuple matching a GSS pseudoflavor
+ * @pseudoflavor: GSS pseudoflavor to match
+ * @info: rpcsec_gss_info structure to fill in
+ *
+ * Returns zero and fills in "info" if pseudoflavor matches a
+ * supported mechanism.
+ */
+int
+rpcauth_get_gssinfo(rpc_authflavor_t pseudoflavor, struct rpcsec_gss_info *info)
+{
+	rpc_authflavor_t flavor = pseudoflavor_to_flavor(pseudoflavor);
+	const struct rpc_authops *ops;
+	int result;
+
+	if (flavor >= RPC_AUTH_MAXFLAVOR)
+		return -EINVAL;
+
+	ops = auth_flavors[flavor];
+	if (ops == NULL)
+		request_module("rpc-auth-%u", flavor);
+	spin_lock(&rpc_authflavor_lock);
+	ops = auth_flavors[flavor];
+	if (ops == NULL || !try_module_get(ops->owner)) {
+		spin_unlock(&rpc_authflavor_lock);
+		return -ENOENT;
+	}
+	spin_unlock(&rpc_authflavor_lock);
+
+	result = -ENOENT;
+	if (ops->flavor2info != NULL)
+		result = ops->flavor2info(pseudoflavor, info);
+
+	module_put(ops->owner);
+	return result;
+}
+EXPORT_SYMBOL_GPL(rpcauth_get_gssinfo);
+
+/**
  * rpcauth_list_flavors - discover registered flavors and pseudoflavors
  * @array: array to fill in
  * @size: size of "array"
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 5257d29..51415b0 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -1641,6 +1641,8 @@ static const struct rpc_authops authgss_ops = {
 	.pipes_create	= gss_pipes_dentries_create,
 	.pipes_destroy	= gss_pipes_dentries_destroy,
 	.list_pseudoflavors = gss_mech_list_pseudoflavors,
+	.info2flavor	= gss_mech_info2flavor,
+	.flavor2info	= gss_mech_flavor2info,
 };
 
 static const struct rpc_credops gss_credops = {
@@ -1733,6 +1735,7 @@ static void __exit exit_rpcsec_gss(void)
 	rcu_barrier(); /* Wait for completion of call_rcu()'s */
 }
 
+MODULE_ALIAS("rpc-auth-6");
 MODULE_LICENSE("GPL");
 module_param_named(expired_cred_retry_delay,
 		   gss_expired_cred_retry_delay,
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
index d3611f1..33255ff 100644
--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
+++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
@@ -729,16 +729,19 @@ static const struct gss_api_ops gss_kerberos_ops = {
 static struct pf_desc gss_kerberos_pfs[] = {
 	[0] = {
 		.pseudoflavor = RPC_AUTH_GSS_KRB5,
+		.qop = GSS_C_QOP_DEFAULT,
 		.service = RPC_GSS_SVC_NONE,
 		.name = "krb5",
 	},
 	[1] = {
 		.pseudoflavor = RPC_AUTH_GSS_KRB5I,
+		.qop = GSS_C_QOP_DEFAULT,
 		.service = RPC_GSS_SVC_INTEGRITY,
 		.name = "krb5i",
 	},
 	[2] = {
 		.pseudoflavor = RPC_AUTH_GSS_KRB5P,
+		.qop = GSS_C_QOP_DEFAULT,
 		.service = RPC_GSS_SVC_PRIVACY,
 		.name = "krb5p",
 	},
@@ -750,11 +753,12 @@ MODULE_ALIAS("rpc-auth-gss-krb5p");
 MODULE_ALIAS("rpc-auth-gss-390003");
 MODULE_ALIAS("rpc-auth-gss-390004");
 MODULE_ALIAS("rpc-auth-gss-390005");
+MODULE_ALIAS("rpc-auth-gss-1.2.840.113554.1.2.2");
 
 static struct gss_api_mech gss_kerberos_mech = {
 	.gm_name	= "krb5",
 	.gm_owner	= THIS_MODULE,
-	.gm_oid		= {9, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"},
+	.gm_oid		= { 9, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02" },
 	.gm_ops		= &gss_kerberos_ops,
 	.gm_pf_num	= ARRAY_SIZE(gss_kerberos_pfs),
 	.gm_pfs		= gss_kerberos_pfs,
diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c
index 88edec9..1da52d1 100644
--- a/net/sunrpc/auth_gss/gss_krb5_wrap.c
+++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c
@@ -130,8 +130,8 @@ gss_krb5_make_confounder(char *p, u32 conflen)
 
 	/* initialize to random value */
 	if (i == 0) {
-		i = random32();
-		i = (i << 32) | random32();
+		i = prandom_u32();
+		i = (i << 32) | prandom_u32();
 	}
 
 	switch (conflen) {
diff --git a/net/sunrpc/auth_gss/gss_mech_switch.c b/net/sunrpc/auth_gss/gss_mech_switch.c
index f0f4eee..79881d6 100644
--- a/net/sunrpc/auth_gss/gss_mech_switch.c
+++ b/net/sunrpc/auth_gss/gss_mech_switch.c
@@ -36,6 +36,7 @@
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/module.h>
+#include <linux/oid_registry.h>
 #include <linux/sunrpc/msg_prot.h>
 #include <linux/sunrpc/gss_asn1.h>
 #include <linux/sunrpc/auth_gss.h>
@@ -102,8 +103,13 @@ out:
 	return status;
 }
 
-int
-gss_mech_register(struct gss_api_mech *gm)
+/**
+ * gss_mech_register - register a GSS mechanism
+ * @gm: GSS mechanism handle
+ *
+ * Returns zero if successful, or a negative errno.
+ */
+int gss_mech_register(struct gss_api_mech *gm)
 {
 	int status;
 
@@ -116,11 +122,14 @@ gss_mech_register(struct gss_api_mech *gm)
 	dprintk("RPC:       registered gss mechanism %s\n", gm->gm_name);
 	return 0;
 }
-
 EXPORT_SYMBOL_GPL(gss_mech_register);
 
-void
-gss_mech_unregister(struct gss_api_mech *gm)
+/**
+ * gss_mech_unregister - release a GSS mechanism
+ * @gm: GSS mechanism handle
+ *
+ */
+void gss_mech_unregister(struct gss_api_mech *gm)
 {
 	spin_lock(&registered_mechs_lock);
 	list_del(&gm->gm_list);
@@ -128,18 +137,14 @@ gss_mech_unregister(struct gss_api_mech *gm)
 	dprintk("RPC:       unregistered gss mechanism %s\n", gm->gm_name);
 	gss_mech_free(gm);
 }
-
 EXPORT_SYMBOL_GPL(gss_mech_unregister);
 
-struct gss_api_mech *
-gss_mech_get(struct gss_api_mech *gm)
+static struct gss_api_mech *gss_mech_get(struct gss_api_mech *gm)
 {
 	__module_get(gm->gm_owner);
 	return gm;
 }
 
-EXPORT_SYMBOL_GPL(gss_mech_get);
-
 static struct gss_api_mech *
 _gss_mech_get_by_name(const char *name)
 {
@@ -169,12 +174,16 @@ struct gss_api_mech * gss_mech_get_by_name(const char *name)
 	}
 	return gm;
 }
-EXPORT_SYMBOL_GPL(gss_mech_get_by_name);
 
-struct gss_api_mech *
-gss_mech_get_by_OID(struct xdr_netobj *obj)
+static struct gss_api_mech *gss_mech_get_by_OID(struct rpcsec_gss_oid *obj)
 {
 	struct gss_api_mech	*pos, *gm = NULL;
+	char buf[32];
+
+	if (sprint_oid(obj->data, obj->len, buf, sizeof(buf)) < 0)
+		return NULL;
+	dprintk("RPC:       %s(%s)\n", __func__, buf);
+	request_module("rpc-auth-gss-%s", buf);
 
 	spin_lock(&registered_mechs_lock);
 	list_for_each_entry(pos, &registered_mechs, gm_list) {
@@ -188,11 +197,8 @@ gss_mech_get_by_OID(struct xdr_netobj *obj)
 	}
 	spin_unlock(&registered_mechs_lock);
 	return gm;
-
 }
 
-EXPORT_SYMBOL_GPL(gss_mech_get_by_OID);
-
 static inline int
 mech_supports_pseudoflavor(struct gss_api_mech *gm, u32 pseudoflavor)
 {
@@ -237,8 +243,6 @@ gss_mech_get_by_pseudoflavor(u32 pseudoflavor)
 	return gm;
 }
 
-EXPORT_SYMBOL_GPL(gss_mech_get_by_pseudoflavor);
-
 /**
  * gss_mech_list_pseudoflavors - Discover registered GSS pseudoflavors
  * @array: array to fill in
@@ -268,19 +272,82 @@ int gss_mech_list_pseudoflavors(rpc_authflavor_t *array_ptr, int size)
 	return i;
 }
 
-u32
-gss_svc_to_pseudoflavor(struct gss_api_mech *gm, u32 service)
+/**
+ * gss_svc_to_pseudoflavor - map a GSS service number to a pseudoflavor
+ * @gm: GSS mechanism handle
+ * @qop: GSS quality-of-protection value
+ * @service: GSS service value
+ *
+ * Returns a matching security flavor, or RPC_AUTH_MAXFLAVOR if none is found.
+ */
+rpc_authflavor_t gss_svc_to_pseudoflavor(struct gss_api_mech *gm, u32 qop,
+					 u32 service)
 {
 	int i;
 
 	for (i = 0; i < gm->gm_pf_num; i++) {
-		if (gm->gm_pfs[i].service == service) {
+		if (gm->gm_pfs[i].qop == qop &&
+		    gm->gm_pfs[i].service == service) {
 			return gm->gm_pfs[i].pseudoflavor;
 		}
 	}
-	return RPC_AUTH_MAXFLAVOR; /* illegal value */
+	return RPC_AUTH_MAXFLAVOR;
+}
+
+/**
+ * gss_mech_info2flavor - look up a pseudoflavor given a GSS tuple
+ * @info: a GSS mech OID, quality of protection, and service value
+ *
+ * Returns a matching pseudoflavor, or RPC_AUTH_MAXFLAVOR if the tuple is
+ * not supported.
+ */
+rpc_authflavor_t gss_mech_info2flavor(struct rpcsec_gss_info *info)
+{
+	rpc_authflavor_t pseudoflavor;
+	struct gss_api_mech *gm;
+
+	gm = gss_mech_get_by_OID(&info->oid);
+	if (gm == NULL)
+		return RPC_AUTH_MAXFLAVOR;
+
+	pseudoflavor = gss_svc_to_pseudoflavor(gm, info->qop, info->service);
+
+	gss_mech_put(gm);
+	return pseudoflavor;
+}
+
+/**
+ * gss_mech_flavor2info - look up a GSS tuple for a given pseudoflavor
+ * @pseudoflavor: GSS pseudoflavor to match
+ * @info: rpcsec_gss_info structure to fill in
+ *
+ * Returns zero and fills in "info" if pseudoflavor matches a
+ * supported mechanism.  Otherwise a negative errno is returned.
+ */
+int gss_mech_flavor2info(rpc_authflavor_t pseudoflavor,
+			 struct rpcsec_gss_info *info)
+{
+	struct gss_api_mech *gm;
+	int i;
+
+	gm = gss_mech_get_by_pseudoflavor(pseudoflavor);
+	if (gm == NULL)
+		return -ENOENT;
+
+	for (i = 0; i < gm->gm_pf_num; i++) {
+		if (gm->gm_pfs[i].pseudoflavor == pseudoflavor) {
+			memcpy(info->oid.data, gm->gm_oid.data, gm->gm_oid.len);
+			info->oid.len = gm->gm_oid.len;
+			info->qop = gm->gm_pfs[i].qop;
+			info->service = gm->gm_pfs[i].service;
+			gss_mech_put(gm);
+			return 0;
+		}
+	}
+
+	gss_mech_put(gm);
+	return -ENOENT;
 }
-EXPORT_SYMBOL_GPL(gss_svc_to_pseudoflavor);
 
 u32
 gss_pseudoflavor_to_service(struct gss_api_mech *gm, u32 pseudoflavor)
@@ -294,8 +361,6 @@ gss_pseudoflavor_to_service(struct gss_api_mech *gm, u32 pseudoflavor)
 	return 0;
 }
 
-EXPORT_SYMBOL_GPL(gss_pseudoflavor_to_service);
-
 char *
 gss_service_to_auth_domain_name(struct gss_api_mech *gm, u32 service)
 {
@@ -308,8 +373,6 @@ gss_service_to_auth_domain_name(struct gss_api_mech *gm, u32 service)
 	return NULL;
 }
 
-EXPORT_SYMBOL_GPL(gss_service_to_auth_domain_name);
-
 void
 gss_mech_put(struct gss_api_mech * gm)
 {
@@ -317,8 +380,6 @@ gss_mech_put(struct gss_api_mech * gm)
 		module_put(gm->gm_owner);
 }
 
-EXPORT_SYMBOL_GPL(gss_mech_put);
-
 /* The mech could probably be determined from the token instead, but it's just
  * as easy for now to pass it in. */
 int
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
index 5ead605..c3ba570 100644
--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -1220,7 +1220,9 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
 		svcdata->rsci = rsci;
 		cache_get(&rsci->h);
 		rqstp->rq_cred.cr_flavor = gss_svc_to_pseudoflavor(
-					rsci->mechctx->mech_type, gc->gc_svc);
+					rsci->mechctx->mech_type,
+					GSS_C_QOP_DEFAULT,
+					gc->gc_svc);
 		ret = SVC_OK;
 		goto out;
 	}
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
index 25d58e76..05ea9ac 100644
--- a/net/sunrpc/cache.c
+++ b/net/sunrpc/cache.c
@@ -986,8 +986,10 @@ static int cache_open(struct inode *inode, struct file *filp,
 	nonseekable_open(inode, filp);
 	if (filp->f_mode & FMODE_READ) {
 		rp = kmalloc(sizeof(*rp), GFP_KERNEL);
-		if (!rp)
+		if (!rp) {
+			module_put(cd->owner);
 			return -ENOMEM;
+		}
 		rp->offset = 0;
 		rp->q.reader = 1;
 		atomic_inc(&cd->readers);
@@ -1461,7 +1463,7 @@ static ssize_t write_flush(struct file *file, const char __user *buf,
 static ssize_t cache_read_procfs(struct file *filp, char __user *buf,
 				 size_t count, loff_t *ppos)
 {
-	struct cache_detail *cd = PDE(file_inode(filp))->data;
+	struct cache_detail *cd = PDE_DATA(file_inode(filp));
 
 	return cache_read(filp, buf, count, ppos, cd);
 }
@@ -1469,14 +1471,14 @@ static ssize_t cache_read_procfs(struct file *filp, char __user *buf,
 static ssize_t cache_write_procfs(struct file *filp, const char __user *buf,
 				  size_t count, loff_t *ppos)
 {
-	struct cache_detail *cd = PDE(file_inode(filp))->data;
+	struct cache_detail *cd = PDE_DATA(file_inode(filp));
 
 	return cache_write(filp, buf, count, ppos, cd);
 }
 
 static unsigned int cache_poll_procfs(struct file *filp, poll_table *wait)
 {
-	struct cache_detail *cd = PDE(file_inode(filp))->data;
+	struct cache_detail *cd = PDE_DATA(file_inode(filp));
 
 	return cache_poll(filp, wait, cd);
 }
@@ -1485,21 +1487,21 @@ static long cache_ioctl_procfs(struct file *filp,
 			       unsigned int cmd, unsigned long arg)
 {
 	struct inode *inode = file_inode(filp);
-	struct cache_detail *cd = PDE(inode)->data;
+	struct cache_detail *cd = PDE_DATA(inode);
 
 	return cache_ioctl(inode, filp, cmd, arg, cd);
 }
 
 static int cache_open_procfs(struct inode *inode, struct file *filp)
 {
-	struct cache_detail *cd = PDE(inode)->data;
+	struct cache_detail *cd = PDE_DATA(inode);
 
 	return cache_open(inode, filp, cd);
 }
 
 static int cache_release_procfs(struct inode *inode, struct file *filp)
 {
-	struct cache_detail *cd = PDE(inode)->data;
+	struct cache_detail *cd = PDE_DATA(inode);
 
 	return cache_release(inode, filp, cd);
 }
@@ -1517,14 +1519,14 @@ static const struct file_operations cache_file_operations_procfs = {
 
 static int content_open_procfs(struct inode *inode, struct file *filp)
 {
-	struct cache_detail *cd = PDE(inode)->data;
+	struct cache_detail *cd = PDE_DATA(inode);
 
 	return content_open(inode, filp, cd);
 }
 
 static int content_release_procfs(struct inode *inode, struct file *filp)
 {
-	struct cache_detail *cd = PDE(inode)->data;
+	struct cache_detail *cd = PDE_DATA(inode);
 
 	return content_release(inode, filp, cd);
 }
@@ -1538,14 +1540,14 @@ static const struct file_operations content_file_operations_procfs = {
 
 static int open_flush_procfs(struct inode *inode, struct file *filp)
 {
-	struct cache_detail *cd = PDE(inode)->data;
+	struct cache_detail *cd = PDE_DATA(inode);
 
 	return open_flush(inode, filp, cd);
 }
 
 static int release_flush_procfs(struct inode *inode, struct file *filp)
 {
-	struct cache_detail *cd = PDE(inode)->data;
+	struct cache_detail *cd = PDE_DATA(inode);
 
 	return release_flush(inode, filp, cd);
 }
@@ -1553,7 +1555,7 @@ static int release_flush_procfs(struct inode *inode, struct file *filp)
 static ssize_t read_flush_procfs(struct file *filp, char __user *buf,
 			    size_t count, loff_t *ppos)
 {
-	struct cache_detail *cd = PDE(file_inode(filp))->data;
+	struct cache_detail *cd = PDE_DATA(file_inode(filp));
 
 	return read_flush(filp, buf, count, ppos, cd);
 }
@@ -1562,7 +1564,7 @@ static ssize_t write_flush_procfs(struct file *filp,
 				  const char __user *buf,
 				  size_t count, loff_t *ppos)
 {
-	struct cache_detail *cd = PDE(file_inode(filp))->data;
+	struct cache_detail *cd = PDE_DATA(file_inode(filp));
 
 	return write_flush(filp, buf, count, ppos, cd);
 }
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index dcc446e..ff587b0 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -512,7 +512,7 @@ static struct rpc_clnt *__rpc_clone_client(struct rpc_create_args *args,
 	new = rpc_new_client(args, xprt);
 	if (IS_ERR(new)) {
 		err = PTR_ERR(new);
-		goto out_put;
+		goto out_err;
 	}
 
 	atomic_inc(&clnt->cl_count);
@@ -525,8 +525,6 @@ static struct rpc_clnt *__rpc_clone_client(struct rpc_create_args *args,
 	new->cl_chatty = clnt->cl_chatty;
 	return new;
 
-out_put:
-	xprt_put(xprt);
 out_err:
 	dprintk("RPC:       %s: returned error %d\n", __func__, err);
 	return ERR_PTR(err);
@@ -1644,22 +1642,26 @@ call_connect_status(struct rpc_task *task)
 
 	dprint_status(task);
 
-	task->tk_status = 0;
-	if (status >= 0 || status == -EAGAIN) {
-		clnt->cl_stats->netreconn++;
-		task->tk_action = call_transmit;
-		return;
-	}
-
 	trace_rpc_connect_status(task, status);
 	switch (status) {
 		/* if soft mounted, test if we've timed out */
 	case -ETIMEDOUT:
 		task->tk_action = call_timeout;
-		break;
-	default:
-		rpc_exit(task, -EIO);
+		return;
+	case -ECONNREFUSED:
+	case -ECONNRESET:
+	case -ENETUNREACH:
+		if (RPC_IS_SOFTCONN(task))
+			break;
+		/* retry with existing socket, after a delay */
+	case 0:
+	case -EAGAIN:
+		task->tk_status = 0;
+		clnt->cl_stats->netreconn++;
+		task->tk_action = call_transmit;
+		return;
 	}
+	rpc_exit(task, status);
 }
 
 /*
diff --git a/net/sunrpc/stats.c b/net/sunrpc/stats.c
index bc2068e..21b75cb 100644
--- a/net/sunrpc/stats.c
+++ b/net/sunrpc/stats.c
@@ -64,7 +64,7 @@ static int rpc_proc_show(struct seq_file *seq, void *v) {
 
 static int rpc_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, rpc_proc_show, PDE(inode)->data);
+	return single_open(file, rpc_proc_show, PDE_DATA(inode));
 }
 
 static const struct file_operations rpc_proc_fops = {
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 3d02130..5156ef5 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -2207,10 +2207,6 @@ static void xs_tcp_setup_socket(struct work_struct *work)
 		 */
 		xs_tcp_force_close(xprt);
 		break;
-	case -ECONNREFUSED:
-	case -ECONNRESET:
-	case -ENETUNREACH:
-		/* retry with existing socket, after a delay */
 	case 0:
 	case -EINPROGRESS:
 	case -EALREADY:
@@ -2221,6 +2217,10 @@ static void xs_tcp_setup_socket(struct work_struct *work)
 		/* Happens, for instance, if the user specified a link
 		 * local IPv6 address without a scope-id.
 		 */
+	case -ECONNREFUSED:
+	case -ECONNRESET:
+	case -ENETUNREACH:
+		/* retry with existing socket, after a delay */
 		goto out;
 	}
 out_eagain:
diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c
index 6675914..8bcd498 100644
--- a/net/tipc/netlink.c
+++ b/net/tipc/netlink.c
@@ -44,7 +44,7 @@ static int handle_cmd(struct sk_buff *skb, struct genl_info *info)
 	struct nlmsghdr *rep_nlh;
 	struct nlmsghdr *req_nlh = info->nlhdr;
 	struct tipc_genlmsghdr *req_userhdr = info->userhdr;
-	int hdr_space = NLMSG_SPACE(GENL_HDRLEN + TIPC_GENL_HDRLEN);
+	int hdr_space = nlmsg_total_size(GENL_HDRLEN + TIPC_GENL_HDRLEN);
 	u16 cmd;
 
 	if ((req_userhdr->cmd & 0xC000) && (!capable(CAP_NET_ADMIN)))
@@ -53,8 +53,8 @@ static int handle_cmd(struct sk_buff *skb, struct genl_info *info)
 		cmd = req_userhdr->cmd;
 
 	rep_buf = tipc_cfg_do_cmd(req_userhdr->dest, cmd,
-			NLMSG_DATA(req_nlh) + GENL_HDRLEN + TIPC_GENL_HDRLEN,
-			NLMSG_PAYLOAD(req_nlh, GENL_HDRLEN + TIPC_GENL_HDRLEN),
+			nlmsg_data(req_nlh) + GENL_HDRLEN + TIPC_GENL_HDRLEN,
+			nlmsg_attrlen(req_nlh, GENL_HDRLEN + TIPC_GENL_HDRLEN),
 			hdr_space);
 
 	if (rep_buf) {
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 971282b..2e4d900 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -2196,7 +2196,9 @@ static unsigned int unix_dgram_poll(struct file *file, struct socket *sock,
 
 	/* exceptional events? */
 	if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
-		mask |= POLLERR;
+		mask |= POLLERR |
+			(sock_flag(sk, SOCK_SELECT_ERR_QUEUE) ? POLLPRI : 0);
+
 	if (sk->sk_shutdown & RCV_SHUTDOWN)
 		mask |= POLLRDHUP | POLLIN | POLLRDNORM;
 	if (sk->sk_shutdown == SHUTDOWN_MASK)
diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
index ca511c4..d8079da 100644
--- a/net/vmw_vsock/af_vsock.c
+++ b/net/vmw_vsock/af_vsock.c
@@ -207,7 +207,7 @@ static struct sock *__vsock_find_bound_socket(struct sockaddr_vm *addr)
 	struct vsock_sock *vsk;
 
 	list_for_each_entry(vsk, vsock_bound_sockets(addr), bound_table)
-		if (vsock_addr_equals_addr_any(addr, &vsk->local_addr))
+		if (addr->svm_port == vsk->local_addr.svm_port)
 			return sk_vsock(vsk);
 
 	return NULL;
@@ -220,8 +220,8 @@ static struct sock *__vsock_find_connected_socket(struct sockaddr_vm *src,
 
 	list_for_each_entry(vsk, vsock_connected_sockets(src, dst),
 			    connected_table) {
-		if (vsock_addr_equals_addr(src, &vsk->remote_addr)
-		    && vsock_addr_equals_addr(dst, &vsk->local_addr)) {
+		if (vsock_addr_equals_addr(src, &vsk->remote_addr) &&
+		    dst->svm_port == vsk->local_addr.svm_port) {
 			return sk_vsock(vsk);
 		}
 	}
diff --git a/net/vmw_vsock/vmci_transport.c b/net/vmw_vsock/vmci_transport.c
index a70ace8..9caa91c 100644
--- a/net/vmw_vsock/vmci_transport.c
+++ b/net/vmw_vsock/vmci_transport.c
@@ -123,6 +123,14 @@ static s32 vmci_transport_error_to_vsock_error(s32 vmci_error)
 	return err > 0 ? -err : err;
 }
 
+static u32 vmci_transport_peer_rid(u32 peer_cid)
+{
+	if (VMADDR_CID_HYPERVISOR == peer_cid)
+		return VMCI_TRANSPORT_HYPERVISOR_PACKET_RID;
+
+	return VMCI_TRANSPORT_PACKET_RID;
+}
+
 static inline void
 vmci_transport_packet_init(struct vmci_transport_packet *pkt,
 			   struct sockaddr_vm *src,
@@ -140,7 +148,7 @@ vmci_transport_packet_init(struct vmci_transport_packet *pkt,
 	pkt->dg.src = vmci_make_handle(VMADDR_CID_ANY,
 				       VMCI_TRANSPORT_PACKET_RID);
 	pkt->dg.dst = vmci_make_handle(dst->svm_cid,
-				       VMCI_TRANSPORT_PACKET_RID);
+				       vmci_transport_peer_rid(dst->svm_cid));
 	pkt->dg.payload_size = sizeof(*pkt) - sizeof(pkt->dg);
 	pkt->version = VMCI_TRANSPORT_PACKET_VERSION;
 	pkt->type = type;
@@ -464,19 +472,16 @@ static struct sock *vmci_transport_get_pending(
 	struct vsock_sock *vlistener;
 	struct vsock_sock *vpending;
 	struct sock *pending;
+	struct sockaddr_vm src;
+
+	vsock_addr_init(&src, pkt->dg.src.context, pkt->src_port);
 
 	vlistener = vsock_sk(listener);
 
 	list_for_each_entry(vpending, &vlistener->pending_links,
 			    pending_links) {
-		struct sockaddr_vm src;
-		struct sockaddr_vm dst;
-
-		vsock_addr_init(&src, pkt->dg.src.context, pkt->src_port);
-		vsock_addr_init(&dst, pkt->dg.dst.context, pkt->dst_port);
-
 		if (vsock_addr_equals_addr(&src, &vpending->remote_addr) &&
-		    vsock_addr_equals_addr(&dst, &vpending->local_addr)) {
+		    pkt->dst_port == vpending->local_addr.svm_port) {
 			pending = sk_vsock(vpending);
 			sock_hold(pending);
 			goto found;
@@ -511,6 +516,9 @@ static bool vmci_transport_is_trusted(struct vsock_sock *vsock, u32 peer_cid)
 
 static bool vmci_transport_allow_dgram(struct vsock_sock *vsock, u32 peer_cid)
 {
+	if (VMADDR_CID_HYPERVISOR == peer_cid)
+		return true;
+
 	if (vsock->cached_peer != peer_cid) {
 		vsock->cached_peer = peer_cid;
 		if (!vmci_transport_is_trusted(vsock, peer_cid) &&
@@ -631,7 +639,6 @@ static int vmci_transport_recv_dgram_cb(void *data, struct vmci_datagram *dg)
 static bool vmci_transport_stream_allow(u32 cid, u32 port)
 {
 	static const u32 non_socket_contexts[] = {
-		VMADDR_CID_HYPERVISOR,
 		VMADDR_CID_RESERVED,
 	};
 	int i;
@@ -670,7 +677,7 @@ static int vmci_transport_recv_stream_cb(void *data, struct vmci_datagram *dg)
 	 */
 
 	if (!vmci_transport_stream_allow(dg->src.context, -1)
-	    || VMCI_TRANSPORT_PACKET_RID != dg->src.resource)
+	    || vmci_transport_peer_rid(dg->src.context) != dg->src.resource)
 		return VMCI_ERROR_NO_ACCESS;
 
 	if (VMCI_DG_SIZE(dg) < sizeof(*pkt))
@@ -739,10 +746,15 @@ static int vmci_transport_recv_stream_cb(void *data, struct vmci_datagram *dg)
 	 */
 	bh_lock_sock(sk);
 
-	if (!sock_owned_by_user(sk) && sk->sk_state == SS_CONNECTED)
-		vmci_trans(vsk)->notify_ops->handle_notify_pkt(
-				sk, pkt, true, &dst, &src,
-				&bh_process_pkt);
+	if (!sock_owned_by_user(sk)) {
+		/* The local context ID may be out of date, update it. */
+		vsk->local_addr.svm_cid = dst.svm_cid;
+
+		if (sk->sk_state == SS_CONNECTED)
+			vmci_trans(vsk)->notify_ops->handle_notify_pkt(
+					sk, pkt, true, &dst, &src,
+					&bh_process_pkt);
+	}
 
 	bh_unlock_sock(sk);
 
@@ -902,6 +914,9 @@ static void vmci_transport_recv_pkt_work(struct work_struct *work)
 
 	lock_sock(sk);
 
+	/* The local context ID may be out of date. */
+	vsock_sk(sk)->local_addr.svm_cid = pkt->dg.dst.context;
+
 	switch (sk->sk_state) {
 	case SS_LISTEN:
 		vmci_transport_recv_listen(sk, pkt);
@@ -958,6 +973,10 @@ static int vmci_transport_recv_listen(struct sock *sk,
 	pending = vmci_transport_get_pending(sk, pkt);
 	if (pending) {
 		lock_sock(pending);
+
+		/* The local context ID may be out of date. */
+		vsock_sk(pending)->local_addr.svm_cid = pkt->dg.dst.context;
+
 		switch (pending->sk_state) {
 		case SS_CONNECTING:
 			err = vmci_transport_recv_connecting_server(sk,
diff --git a/net/vmw_vsock/vmci_transport.h b/net/vmw_vsock/vmci_transport.h
index 1bf9918..fd88ea8 100644
--- a/net/vmw_vsock/vmci_transport.h
+++ b/net/vmw_vsock/vmci_transport.h
@@ -28,6 +28,9 @@
 /* The resource ID on which control packets are sent. */
 #define VMCI_TRANSPORT_PACKET_RID 1
 
+/* The resource ID on which control packets are sent to the hypervisor. */
+#define VMCI_TRANSPORT_HYPERVISOR_PACKET_RID 15
+
 #define VSOCK_PROTO_INVALID        0
 #define VSOCK_PROTO_PKT_ON_NOTIFY (1 << 0)
 #define VSOCK_PROTO_ALL_SUPPORTED (VSOCK_PROTO_PKT_ON_NOTIFY)
diff --git a/net/vmw_vsock/vsock_addr.c b/net/vmw_vsock/vsock_addr.c
index b7df1ae..ec2611b 100644
--- a/net/vmw_vsock/vsock_addr.c
+++ b/net/vmw_vsock/vsock_addr.c
@@ -64,16 +64,6 @@ bool vsock_addr_equals_addr(const struct sockaddr_vm *addr,
 }
 EXPORT_SYMBOL_GPL(vsock_addr_equals_addr);
 
-bool vsock_addr_equals_addr_any(const struct sockaddr_vm *addr,
-				const struct sockaddr_vm *other)
-{
-	return (addr->svm_cid == VMADDR_CID_ANY ||
-		other->svm_cid == VMADDR_CID_ANY ||
-		addr->svm_cid == other->svm_cid) &&
-	       addr->svm_port == other->svm_port;
-}
-EXPORT_SYMBOL_GPL(vsock_addr_equals_addr_any);
-
 int vsock_addr_cast(const struct sockaddr *addr,
 		    size_t len, struct sockaddr_vm **out_addr)
 {
diff --git a/net/vmw_vsock/vsock_addr.h b/net/vmw_vsock/vsock_addr.h
index cdfbcef..9ccd531 100644
--- a/net/vmw_vsock/vsock_addr.h
+++ b/net/vmw_vsock/vsock_addr.h
@@ -24,8 +24,6 @@ bool vsock_addr_bound(const struct sockaddr_vm *addr);
 void vsock_addr_unbind(struct sockaddr_vm *addr);
 bool vsock_addr_equals_addr(const struct sockaddr_vm *addr,
 			    const struct sockaddr_vm *other);
-bool vsock_addr_equals_addr_any(const struct sockaddr_vm *addr,
-				const struct sockaddr_vm *other);
 int vsock_addr_cast(const struct sockaddr *addr, size_t len,
 		    struct sockaddr_vm **out_addr);
 
diff --git a/net/wireless/ap.c b/net/wireless/ap.c
index a4a14e8..324e8d8 100644
--- a/net/wireless/ap.c
+++ b/net/wireless/ap.c
@@ -46,65 +46,3 @@ int cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
 
 	return err;
 }
-
-void cfg80211_ch_switch_notify(struct net_device *dev,
-			       struct cfg80211_chan_def *chandef)
-{
-	struct wireless_dev *wdev = dev->ieee80211_ptr;
-	struct wiphy *wiphy = wdev->wiphy;
-	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
-
-	trace_cfg80211_ch_switch_notify(dev, chandef);
-
-	wdev_lock(wdev);
-
-	if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
-		    wdev->iftype != NL80211_IFTYPE_P2P_GO))
-		goto out;
-
-	wdev->channel = chandef->chan;
-	nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL);
-out:
-	wdev_unlock(wdev);
-	return;
-}
-EXPORT_SYMBOL(cfg80211_ch_switch_notify);
-
-bool cfg80211_rx_spurious_frame(struct net_device *dev,
-				const u8 *addr, gfp_t gfp)
-{
-	struct wireless_dev *wdev = dev->ieee80211_ptr;
-	bool ret;
-
-	trace_cfg80211_rx_spurious_frame(dev, addr);
-
-	if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
-		    wdev->iftype != NL80211_IFTYPE_P2P_GO)) {
-		trace_cfg80211_return_bool(false);
-		return false;
-	}
-	ret = nl80211_unexpected_frame(dev, addr, gfp);
-	trace_cfg80211_return_bool(ret);
-	return ret;
-}
-EXPORT_SYMBOL(cfg80211_rx_spurious_frame);
-
-bool cfg80211_rx_unexpected_4addr_frame(struct net_device *dev,
-					const u8 *addr, gfp_t gfp)
-{
-	struct wireless_dev *wdev = dev->ieee80211_ptr;
-	bool ret;
-
-	trace_cfg80211_rx_unexpected_4addr_frame(dev, addr);
-
-	if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
-		    wdev->iftype != NL80211_IFTYPE_P2P_GO &&
-		    wdev->iftype != NL80211_IFTYPE_AP_VLAN)) {
-		trace_cfg80211_return_bool(false);
-		return false;
-	}
-	ret = nl80211_unexpected_4addr_frame(dev, addr, gfp);
-	trace_cfg80211_return_bool(ret);
-	return ret;
-}
-EXPORT_SYMBOL(cfg80211_rx_unexpected_4addr_frame);
diff --git a/net/wireless/core.c b/net/wireless/core.c
index ea4155f..84c9ad7 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -212,6 +212,39 @@ static void cfg80211_rfkill_poll(struct rfkill *rfkill, void *data)
 	rdev_rfkill_poll(rdev);
 }
 
+void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev,
+			      struct wireless_dev *wdev)
+{
+	lockdep_assert_held(&rdev->devlist_mtx);
+	lockdep_assert_held(&rdev->sched_scan_mtx);
+
+	if (WARN_ON(wdev->iftype != NL80211_IFTYPE_P2P_DEVICE))
+		return;
+
+	if (!wdev->p2p_started)
+		return;
+
+	rdev_stop_p2p_device(rdev, wdev);
+	wdev->p2p_started = false;
+
+	rdev->opencount--;
+
+	if (rdev->scan_req && rdev->scan_req->wdev == wdev) {
+		bool busy = work_busy(&rdev->scan_done_wk);
+
+		/*
+		 * If the work isn't pending or running (in which case it would
+		 * be waiting for the lock we hold) the driver didn't properly
+		 * cancel the scan when the interface was removed. In this case
+		 * warn and leak the scan request object to not crash later.
+		 */
+		WARN_ON(!busy);
+
+		rdev->scan_req->aborted = true;
+		___cfg80211_scan_done(rdev, !busy);
+	}
+}
+
 static int cfg80211_rfkill_set_block(void *data, bool blocked)
 {
 	struct cfg80211_registered_device *rdev = data;
@@ -221,7 +254,8 @@ static int cfg80211_rfkill_set_block(void *data, bool blocked)
 		return 0;
 
 	rtnl_lock();
-	mutex_lock(&rdev->devlist_mtx);
+
+	/* read-only iteration need not hold the devlist_mtx */
 
 	list_for_each_entry(wdev, &rdev->wdev_list, list) {
 		if (wdev->netdev) {
@@ -231,18 +265,18 @@ static int cfg80211_rfkill_set_block(void *data, bool blocked)
 		/* otherwise, check iftype */
 		switch (wdev->iftype) {
 		case NL80211_IFTYPE_P2P_DEVICE:
-			if (!wdev->p2p_started)
-				break;
-			rdev_stop_p2p_device(rdev, wdev);
-			wdev->p2p_started = false;
-			rdev->opencount--;
+			/* but this requires it */
+			mutex_lock(&rdev->devlist_mtx);
+			mutex_lock(&rdev->sched_scan_mtx);
+			cfg80211_stop_p2p_device(rdev, wdev);
+			mutex_unlock(&rdev->sched_scan_mtx);
+			mutex_unlock(&rdev->devlist_mtx);
 			break;
 		default:
 			break;
 		}
 	}
 
-	mutex_unlock(&rdev->devlist_mtx);
 	rtnl_unlock();
 
 	return 0;
@@ -745,17 +779,13 @@ static void wdev_cleanup_work(struct work_struct *work)
 	wdev = container_of(work, struct wireless_dev, cleanup_work);
 	rdev = wiphy_to_dev(wdev->wiphy);
 
-	cfg80211_lock_rdev(rdev);
+	mutex_lock(&rdev->sched_scan_mtx);
 
 	if (WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev)) {
 		rdev->scan_req->aborted = true;
 		___cfg80211_scan_done(rdev, true);
 	}
 
-	cfg80211_unlock_rdev(rdev);
-
-	mutex_lock(&rdev->sched_scan_mtx);
-
 	if (WARN_ON(rdev->sched_scan_req &&
 		    rdev->sched_scan_req->dev == wdev->netdev)) {
 		__cfg80211_stop_sched_scan(rdev, false);
@@ -781,21 +811,19 @@ void cfg80211_unregister_wdev(struct wireless_dev *wdev)
 		return;
 
 	mutex_lock(&rdev->devlist_mtx);
+	mutex_lock(&rdev->sched_scan_mtx);
 	list_del_rcu(&wdev->list);
 	rdev->devlist_generation++;
 
 	switch (wdev->iftype) {
 	case NL80211_IFTYPE_P2P_DEVICE:
-		if (!wdev->p2p_started)
-			break;
-		rdev_stop_p2p_device(rdev, wdev);
-		wdev->p2p_started = false;
-		rdev->opencount--;
+		cfg80211_stop_p2p_device(rdev, wdev);
 		break;
 	default:
 		WARN_ON_ONCE(1);
 		break;
 	}
+	mutex_unlock(&rdev->sched_scan_mtx);
 	mutex_unlock(&rdev->devlist_mtx);
 }
 EXPORT_SYMBOL(cfg80211_unregister_wdev);
@@ -814,6 +842,46 @@ void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev,
 		rdev->num_running_monitor_ifaces += num;
 }
 
+void cfg80211_leave(struct cfg80211_registered_device *rdev,
+		   struct wireless_dev *wdev)
+{
+	struct net_device *dev = wdev->netdev;
+
+	switch (wdev->iftype) {
+	case NL80211_IFTYPE_ADHOC:
+		cfg80211_leave_ibss(rdev, dev, true);
+		break;
+	case NL80211_IFTYPE_P2P_CLIENT:
+	case NL80211_IFTYPE_STATION:
+		mutex_lock(&rdev->sched_scan_mtx);
+		__cfg80211_stop_sched_scan(rdev, false);
+		mutex_unlock(&rdev->sched_scan_mtx);
+
+		wdev_lock(wdev);
+#ifdef CONFIG_CFG80211_WEXT
+		kfree(wdev->wext.ie);
+		wdev->wext.ie = NULL;
+		wdev->wext.ie_len = 0;
+		wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
+#endif
+		__cfg80211_disconnect(rdev, dev,
+				      WLAN_REASON_DEAUTH_LEAVING, true);
+		cfg80211_mlme_down(rdev, dev);
+		wdev_unlock(wdev);
+		break;
+	case NL80211_IFTYPE_MESH_POINT:
+		cfg80211_leave_mesh(rdev, dev);
+		break;
+	case NL80211_IFTYPE_AP:
+		cfg80211_stop_ap(rdev, dev);
+		break;
+	default:
+		break;
+	}
+
+	wdev->beacon_interval = 0;
+}
+
 static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
 					 unsigned long state,
 					 void *ndev)
@@ -882,38 +950,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
 			dev->priv_flags |= IFF_DONT_BRIDGE;
 		break;
 	case NETDEV_GOING_DOWN:
-		switch (wdev->iftype) {
-		case NL80211_IFTYPE_ADHOC:
-			cfg80211_leave_ibss(rdev, dev, true);
-			break;
-		case NL80211_IFTYPE_P2P_CLIENT:
-		case NL80211_IFTYPE_STATION:
-			mutex_lock(&rdev->sched_scan_mtx);
-			__cfg80211_stop_sched_scan(rdev, false);
-			mutex_unlock(&rdev->sched_scan_mtx);
-
-			wdev_lock(wdev);
-#ifdef CONFIG_CFG80211_WEXT
-			kfree(wdev->wext.ie);
-			wdev->wext.ie = NULL;
-			wdev->wext.ie_len = 0;
-			wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
-#endif
-			__cfg80211_disconnect(rdev, dev,
-					      WLAN_REASON_DEAUTH_LEAVING, true);
-			cfg80211_mlme_down(rdev, dev);
-			wdev_unlock(wdev);
-			break;
-		case NL80211_IFTYPE_MESH_POINT:
-			cfg80211_leave_mesh(rdev, dev);
-			break;
-		case NL80211_IFTYPE_AP:
-			cfg80211_stop_ap(rdev, dev);
-			break;
-		default:
-			break;
-		}
-		wdev->beacon_interval = 0;
+		cfg80211_leave(rdev, wdev);
 		break;
 	case NETDEV_DOWN:
 		cfg80211_update_iface_num(rdev, wdev->iftype, -1);
@@ -936,6 +973,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
 		cfg80211_update_iface_num(rdev, wdev->iftype, 1);
 		cfg80211_lock_rdev(rdev);
 		mutex_lock(&rdev->devlist_mtx);
+		mutex_lock(&rdev->sched_scan_mtx);
 		wdev_lock(wdev);
 		switch (wdev->iftype) {
 #ifdef CONFIG_CFG80211_WEXT
@@ -967,6 +1005,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
 			break;
 		}
 		wdev_unlock(wdev);
+		mutex_unlock(&rdev->sched_scan_mtx);
 		rdev->opencount++;
 		mutex_unlock(&rdev->devlist_mtx);
 		cfg80211_unlock_rdev(rdev);
@@ -1087,8 +1126,10 @@ static int __init cfg80211_init(void)
 		goto out_fail_reg;
 
 	cfg80211_wq = create_singlethread_workqueue("cfg80211");
-	if (!cfg80211_wq)
+	if (!cfg80211_wq) {
+		err = -ENOMEM;
 		goto out_fail_wq;
+	}
 
 	return 0;
 
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 3aec0e4..b5174f6 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -330,20 +330,15 @@ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
 int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
 			  struct net_device *dev,
 			  struct ieee80211_channel *chan,
-			  const u8 *bssid, const u8 *prev_bssid,
+			  const u8 *bssid,
 			  const u8 *ssid, int ssid_len,
-			  const u8 *ie, int ie_len, bool use_mfp,
-			  struct cfg80211_crypto_settings *crypt,
-			  u32 assoc_flags, struct ieee80211_ht_cap *ht_capa,
-			  struct ieee80211_ht_cap *ht_capa_mask);
+			  struct cfg80211_assoc_request *req);
 int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
-			struct net_device *dev, struct ieee80211_channel *chan,
-			const u8 *bssid, const u8 *prev_bssid,
+			struct net_device *dev,
+			struct ieee80211_channel *chan,
+			const u8 *bssid,
 			const u8 *ssid, int ssid_len,
-			const u8 *ie, int ie_len, bool use_mfp,
-			struct cfg80211_crypto_settings *crypt,
-			u32 assoc_flags, struct ieee80211_ht_cap *ht_capa,
-			struct ieee80211_ht_cap *ht_capa_mask);
+			struct cfg80211_assoc_request *req);
 int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
 			   struct net_device *dev, const u8 *bssid,
 			   const u8 *ie, int ie_len, u16 reason,
@@ -375,6 +370,8 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
 			  bool no_cck, bool dont_wait_for_ack, u64 *cookie);
 void cfg80211_oper_and_ht_capa(struct ieee80211_ht_cap *ht_capa,
 			       const struct ieee80211_ht_cap *ht_capa_mask);
+void cfg80211_oper_and_vht_capa(struct ieee80211_vht_cap *vht_capa,
+				const struct ieee80211_vht_cap *vht_capa_mask);
 
 /* SME */
 int __cfg80211_connect(struct cfg80211_registered_device *rdev,
@@ -503,6 +500,14 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
 void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev,
 			       enum nl80211_iftype iftype, int num);
 
+
+void cfg80211_leave(struct cfg80211_registered_device *rdev,
+		    struct wireless_dev *wdev);
+
+void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev,
+			      struct wireless_dev *wdev);
+
+
 #define CFG80211_MAX_NUM_DIFFERENT_CHANNELS 10
 
 #ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS
diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c
index 55957a2..0bb93f3 100644
--- a/net/wireless/mesh.c
+++ b/net/wireless/mesh.c
@@ -85,6 +85,7 @@ const struct mesh_setup default_mesh_setup = {
 	.ie = NULL,
 	.ie_len = 0,
 	.is_secure = false,
+	.user_mpm = false,
 	.beacon_interval = MESH_DEFAULT_BEACON_INTERVAL,
 	.dtim_period = MESH_DEFAULT_DTIM_PERIOD,
 };
@@ -233,20 +234,6 @@ int cfg80211_set_mesh_channel(struct cfg80211_registered_device *rdev,
 	return 0;
 }
 
-void cfg80211_notify_new_peer_candidate(struct net_device *dev,
-		const u8 *macaddr, const u8* ie, u8 ie_len, gfp_t gfp)
-{
-	struct wireless_dev *wdev = dev->ieee80211_ptr;
-
-	trace_cfg80211_notify_new_peer_candidate(dev, macaddr);
-	if (WARN_ON(wdev->iftype != NL80211_IFTYPE_MESH_POINT))
-		return;
-
-	nl80211_send_new_peer_candidate(wiphy_to_dev(wdev->wiphy), dev,
-			macaddr, ie, ie_len, gfp);
-}
-EXPORT_SYMBOL(cfg80211_notify_new_peer_candidate);
-
 static int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev,
 				 struct net_device *dev)
 {
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index caddca3..390198b 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -187,30 +187,6 @@ void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len)
 }
 EXPORT_SYMBOL(cfg80211_send_disassoc);
 
-void cfg80211_send_unprot_deauth(struct net_device *dev, const u8 *buf,
-				 size_t len)
-{
-	struct wireless_dev *wdev = dev->ieee80211_ptr;
-	struct wiphy *wiphy = wdev->wiphy;
-	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
-
-	trace_cfg80211_send_unprot_deauth(dev);
-	nl80211_send_unprot_deauth(rdev, dev, buf, len, GFP_ATOMIC);
-}
-EXPORT_SYMBOL(cfg80211_send_unprot_deauth);
-
-void cfg80211_send_unprot_disassoc(struct net_device *dev, const u8 *buf,
-				   size_t len)
-{
-	struct wireless_dev *wdev = dev->ieee80211_ptr;
-	struct wiphy *wiphy = wdev->wiphy;
-	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
-
-	trace_cfg80211_send_unprot_disassoc(dev);
-	nl80211_send_unprot_disassoc(rdev, dev, buf, len, GFP_ATOMIC);
-}
-EXPORT_SYMBOL(cfg80211_send_unprot_disassoc);
-
 void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr)
 {
 	struct wireless_dev *wdev = dev->ieee80211_ptr;
@@ -367,27 +343,38 @@ void cfg80211_oper_and_ht_capa(struct ieee80211_ht_cap *ht_capa,
 		p1[i] &= p2[i];
 }
 
+/*  Do a logical ht_capa &= ht_capa_mask.  */
+void cfg80211_oper_and_vht_capa(struct ieee80211_vht_cap *vht_capa,
+				const struct ieee80211_vht_cap *vht_capa_mask)
+{
+	int i;
+	u8 *p1, *p2;
+	if (!vht_capa_mask) {
+		memset(vht_capa, 0, sizeof(*vht_capa));
+		return;
+	}
+
+	p1 = (u8*)(vht_capa);
+	p2 = (u8*)(vht_capa_mask);
+	for (i = 0; i < sizeof(*vht_capa); i++)
+		p1[i] &= p2[i];
+}
+
 int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
 			  struct net_device *dev,
 			  struct ieee80211_channel *chan,
-			  const u8 *bssid, const u8 *prev_bssid,
+			  const u8 *bssid,
 			  const u8 *ssid, int ssid_len,
-			  const u8 *ie, int ie_len, bool use_mfp,
-			  struct cfg80211_crypto_settings *crypt,
-			  u32 assoc_flags, struct ieee80211_ht_cap *ht_capa,
-			  struct ieee80211_ht_cap *ht_capa_mask)
+			  struct cfg80211_assoc_request *req)
 {
 	struct wireless_dev *wdev = dev->ieee80211_ptr;
-	struct cfg80211_assoc_request req;
 	int err;
 	bool was_connected = false;
 
 	ASSERT_WDEV_LOCK(wdev);
 
-	memset(&req, 0, sizeof(req));
-
-	if (wdev->current_bss && prev_bssid &&
-	    ether_addr_equal(wdev->current_bss->pub.bssid, prev_bssid)) {
+	if (wdev->current_bss && req->prev_bssid &&
+	    ether_addr_equal(wdev->current_bss->pub.bssid, req->prev_bssid)) {
 		/*
 		 * Trying to reassociate: Allow this to proceed and let the old
 		 * association to be dropped when the new one is completed.
@@ -399,40 +386,30 @@ int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
 	} else if (wdev->current_bss)
 		return -EALREADY;
 
-	req.ie = ie;
-	req.ie_len = ie_len;
-	memcpy(&req.crypto, crypt, sizeof(req.crypto));
-	req.use_mfp = use_mfp;
-	req.prev_bssid = prev_bssid;
-	req.flags = assoc_flags;
-	if (ht_capa)
-		memcpy(&req.ht_capa, ht_capa, sizeof(req.ht_capa));
-	if (ht_capa_mask)
-		memcpy(&req.ht_capa_mask, ht_capa_mask,
-		       sizeof(req.ht_capa_mask));
-	cfg80211_oper_and_ht_capa(&req.ht_capa_mask,
+	cfg80211_oper_and_ht_capa(&req->ht_capa_mask,
 				  rdev->wiphy.ht_capa_mod_mask);
+	cfg80211_oper_and_vht_capa(&req->vht_capa_mask,
+				   rdev->wiphy.vht_capa_mod_mask);
 
-	req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len,
-				   WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
-	if (!req.bss) {
+	req->bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len,
+				    WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
+	if (!req->bss) {
 		if (was_connected)
 			wdev->sme_state = CFG80211_SME_CONNECTED;
 		return -ENOENT;
 	}
 
-	err = cfg80211_can_use_chan(rdev, wdev, req.bss->channel,
-				    CHAN_MODE_SHARED);
+	err = cfg80211_can_use_chan(rdev, wdev, chan, CHAN_MODE_SHARED);
 	if (err)
 		goto out;
 
-	err = rdev_assoc(rdev, dev, &req);
+	err = rdev_assoc(rdev, dev, req);
 
 out:
 	if (err) {
 		if (was_connected)
 			wdev->sme_state = CFG80211_SME_CONNECTED;
-		cfg80211_put_bss(&rdev->wiphy, req.bss);
+		cfg80211_put_bss(&rdev->wiphy, req->bss);
 	}
 
 	return err;
@@ -441,21 +418,17 @@ out:
 int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
 			struct net_device *dev,
 			struct ieee80211_channel *chan,
-			const u8 *bssid, const u8 *prev_bssid,
+			const u8 *bssid,
 			const u8 *ssid, int ssid_len,
-			const u8 *ie, int ie_len, bool use_mfp,
-			struct cfg80211_crypto_settings *crypt,
-			u32 assoc_flags, struct ieee80211_ht_cap *ht_capa,
-			struct ieee80211_ht_cap *ht_capa_mask)
+			struct cfg80211_assoc_request *req)
 {
 	struct wireless_dev *wdev = dev->ieee80211_ptr;
 	int err;
 
 	mutex_lock(&rdev->devlist_mtx);
 	wdev_lock(wdev);
-	err = __cfg80211_mlme_assoc(rdev, dev, chan, bssid, prev_bssid,
-				    ssid, ssid_len, ie, ie_len, use_mfp, crypt,
-				    assoc_flags, ht_capa, ht_capa_mask);
+	err = __cfg80211_mlme_assoc(rdev, dev, chan, bssid,
+				    ssid, ssid_len, req);
 	wdev_unlock(wdev);
 	mutex_unlock(&rdev->devlist_mtx);
 
@@ -577,62 +550,6 @@ void cfg80211_mlme_down(struct cfg80211_registered_device *rdev,
 	}
 }
 
-void cfg80211_ready_on_channel(struct wireless_dev *wdev, u64 cookie,
-			       struct ieee80211_channel *chan,
-			       unsigned int duration, gfp_t gfp)
-{
-	struct wiphy *wiphy = wdev->wiphy;
-	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
-
-	trace_cfg80211_ready_on_channel(wdev, cookie, chan, duration);
-	nl80211_send_remain_on_channel(rdev, wdev, cookie, chan, duration, gfp);
-}
-EXPORT_SYMBOL(cfg80211_ready_on_channel);
-
-void cfg80211_remain_on_channel_expired(struct wireless_dev *wdev, u64 cookie,
-					struct ieee80211_channel *chan,
-					gfp_t gfp)
-{
-	struct wiphy *wiphy = wdev->wiphy;
-	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
-
-	trace_cfg80211_ready_on_channel_expired(wdev, cookie, chan);
-	nl80211_send_remain_on_channel_cancel(rdev, wdev, cookie, chan, gfp);
-}
-EXPORT_SYMBOL(cfg80211_remain_on_channel_expired);
-
-void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr,
-		      struct station_info *sinfo, gfp_t gfp)
-{
-	struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
-	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
-
-	trace_cfg80211_new_sta(dev, mac_addr, sinfo);
-	nl80211_send_sta_event(rdev, dev, mac_addr, sinfo, gfp);
-}
-EXPORT_SYMBOL(cfg80211_new_sta);
-
-void cfg80211_del_sta(struct net_device *dev, const u8 *mac_addr, gfp_t gfp)
-{
-	struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
-	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
-
-	trace_cfg80211_del_sta(dev, mac_addr);
-	nl80211_send_sta_del_event(rdev, dev, mac_addr, gfp);
-}
-EXPORT_SYMBOL(cfg80211_del_sta);
-
-void cfg80211_conn_failed(struct net_device *dev, const u8 *mac_addr,
-			  enum nl80211_connect_failed_reason reason,
-			  gfp_t gfp)
-{
-	struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
-	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
-
-	nl80211_send_conn_failed_event(rdev, dev, mac_addr, reason, gfp);
-}
-EXPORT_SYMBOL(cfg80211_conn_failed);
-
 struct cfg80211_mgmt_registration {
 	struct list_head list;
 
@@ -909,85 +826,6 @@ bool cfg80211_rx_mgmt(struct wireless_dev *wdev, int freq, int sig_mbm,
 }
 EXPORT_SYMBOL(cfg80211_rx_mgmt);
 
-void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie,
-			     const u8 *buf, size_t len, bool ack, gfp_t gfp)
-{
-	struct wiphy *wiphy = wdev->wiphy;
-	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
-
-	trace_cfg80211_mgmt_tx_status(wdev, cookie, ack);
-
-	/* Indicate TX status of the Action frame to user space */
-	nl80211_send_mgmt_tx_status(rdev, wdev, cookie, buf, len, ack, gfp);
-}
-EXPORT_SYMBOL(cfg80211_mgmt_tx_status);
-
-void cfg80211_cqm_rssi_notify(struct net_device *dev,
-			      enum nl80211_cqm_rssi_threshold_event rssi_event,
-			      gfp_t gfp)
-{
-	struct wireless_dev *wdev = dev->ieee80211_ptr;
-	struct wiphy *wiphy = wdev->wiphy;
-	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
-
-	trace_cfg80211_cqm_rssi_notify(dev, rssi_event);
-
-	/* Indicate roaming trigger event to user space */
-	nl80211_send_cqm_rssi_notify(rdev, dev, rssi_event, gfp);
-}
-EXPORT_SYMBOL(cfg80211_cqm_rssi_notify);
-
-void cfg80211_cqm_pktloss_notify(struct net_device *dev,
-				 const u8 *peer, u32 num_packets, gfp_t gfp)
-{
-	struct wireless_dev *wdev = dev->ieee80211_ptr;
-	struct wiphy *wiphy = wdev->wiphy;
-	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
-
-	trace_cfg80211_cqm_pktloss_notify(dev, peer, num_packets);
-
-	/* Indicate roaming trigger event to user space */
-	nl80211_send_cqm_pktloss_notify(rdev, dev, peer, num_packets, gfp);
-}
-EXPORT_SYMBOL(cfg80211_cqm_pktloss_notify);
-
-void cfg80211_cqm_txe_notify(struct net_device *dev,
-			     const u8 *peer, u32 num_packets,
-			     u32 rate, u32 intvl, 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_send_cqm_txe_notify(rdev, dev, peer, num_packets,
-				    rate, intvl, gfp);
-}
-EXPORT_SYMBOL(cfg80211_cqm_txe_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);
-
-	trace_cfg80211_gtk_rekey_notify(dev, bssid);
-	nl80211_gtk_rekey_notify(rdev, dev, bssid, replay_ctr, gfp);
-}
-EXPORT_SYMBOL(cfg80211_gtk_rekey_notify);
-
-void cfg80211_pmksa_candidate_notify(struct net_device *dev, int index,
-				     const u8 *bssid, bool preauth, gfp_t gfp)
-{
-	struct wireless_dev *wdev = dev->ieee80211_ptr;
-	struct wiphy *wiphy = wdev->wiphy;
-	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
-
-	trace_cfg80211_pmksa_candidate_notify(dev, index, bssid, preauth);
-	nl80211_pmksa_candidate_notify(rdev, dev, index, bssid, preauth, gfp);
-}
-EXPORT_SYMBOL(cfg80211_pmksa_candidate_notify);
-
 void cfg80211_dfs_channels_update_work(struct work_struct *work)
 {
 	struct delayed_work *delayed_work;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index d44ab21..671b69a 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -370,6 +370,14 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
 	[NL80211_ATTR_MAC_ADDRS] = { .type = NLA_NESTED },
 	[NL80211_ATTR_STA_CAPABILITY] = { .type = NLA_U16 },
 	[NL80211_ATTR_STA_EXT_CAPABILITY] = { .type = NLA_BINARY, },
+	[NL80211_ATTR_SPLIT_WIPHY_DUMP] = { .type = NLA_FLAG, },
+	[NL80211_ATTR_DISABLE_VHT] = { .type = NLA_FLAG },
+	[NL80211_ATTR_VHT_CAPABILITY_MASK] = {
+		.len = NL80211_VHT_CAPABILITY_LEN,
+	},
+	[NL80211_ATTR_MDID] = { .type = NLA_U16 },
+	[NL80211_ATTR_IE_RIC] = { .type = NLA_BINARY,
+				  .len = IEEE80211_MAX_DATA_LEN },
 };
 
 /* policy for the key attributes */
@@ -539,7 +547,8 @@ static inline void *nl80211hdr_put(struct sk_buff *skb, u32 portid, u32 seq,
 }
 
 static int nl80211_msg_put_channel(struct sk_buff *msg,
-				   struct ieee80211_channel *chan)
+				   struct ieee80211_channel *chan,
+				   bool large)
 {
 	if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_FREQ,
 			chan->center_freq))
@@ -554,9 +563,37 @@ static int nl80211_msg_put_channel(struct sk_buff *msg,
 	if ((chan->flags & IEEE80211_CHAN_NO_IBSS) &&
 	    nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_IBSS))
 		goto nla_put_failure;
-	if ((chan->flags & IEEE80211_CHAN_RADAR) &&
-	    nla_put_flag(msg, NL80211_FREQUENCY_ATTR_RADAR))
-		goto nla_put_failure;
+	if (chan->flags & IEEE80211_CHAN_RADAR) {
+		if (nla_put_flag(msg, NL80211_FREQUENCY_ATTR_RADAR))
+			goto nla_put_failure;
+		if (large) {
+			u32 time;
+
+			time = elapsed_jiffies_msecs(chan->dfs_state_entered);
+
+			if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_STATE,
+					chan->dfs_state))
+				goto nla_put_failure;
+			if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_TIME,
+					time))
+				goto nla_put_failure;
+		}
+	}
+
+	if (large) {
+		if ((chan->flags & IEEE80211_CHAN_NO_HT40MINUS) &&
+		    nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_HT40_MINUS))
+			goto nla_put_failure;
+		if ((chan->flags & IEEE80211_CHAN_NO_HT40PLUS) &&
+		    nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_HT40_PLUS))
+			goto nla_put_failure;
+		if ((chan->flags & IEEE80211_CHAN_NO_80MHZ) &&
+		    nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_80MHZ))
+			goto nla_put_failure;
+		if ((chan->flags & IEEE80211_CHAN_NO_160MHZ) &&
+		    nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_160MHZ))
+			goto nla_put_failure;
+	}
 
 	if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_MAX_TX_POWER,
 			DBM_TO_MBM(chan->max_power)))
@@ -832,7 +869,8 @@ nla_put_failure:
 }
 
 static int nl80211_put_iface_combinations(struct wiphy *wiphy,
-					  struct sk_buff *msg)
+					  struct sk_buff *msg,
+					  bool large)
 {
 	struct nlattr *nl_combis;
 	int i, j;
@@ -881,6 +919,10 @@ static int nl80211_put_iface_combinations(struct wiphy *wiphy,
 		    nla_put_u32(msg, NL80211_IFACE_COMB_MAXNUM,
 				c->max_interfaces))
 			goto nla_put_failure;
+		if (large &&
+		    nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS,
+				c->radar_detect_widths))
+			goto nla_put_failure;
 
 		nla_nest_end(msg, nl_combi);
 	}
@@ -892,412 +934,611 @@ nla_put_failure:
 	return -ENOBUFS;
 }
 
-static int nl80211_send_wiphy(struct sk_buff *msg, u32 portid, u32 seq, int flags,
-			      struct cfg80211_registered_device *dev)
+#ifdef CONFIG_PM
+static int nl80211_send_wowlan_tcp_caps(struct cfg80211_registered_device *rdev,
+					struct sk_buff *msg)
 {
-	void *hdr;
-	struct nlattr *nl_bands, *nl_band;
-	struct nlattr *nl_freqs, *nl_freq;
-	struct nlattr *nl_rates, *nl_rate;
-	struct nlattr *nl_cmds;
-	enum ieee80211_band band;
-	struct ieee80211_channel *chan;
-	struct ieee80211_rate *rate;
-	int i;
-	const struct ieee80211_txrx_stypes *mgmt_stypes =
-				dev->wiphy.mgmt_stypes;
+	const struct wiphy_wowlan_tcp_support *tcp = rdev->wiphy.wowlan.tcp;
+	struct nlattr *nl_tcp;
 
-	hdr = nl80211hdr_put(msg, portid, seq, flags, NL80211_CMD_NEW_WIPHY);
-	if (!hdr)
-		return -1;
+	if (!tcp)
+		return 0;
 
-	if (nla_put_u32(msg, NL80211_ATTR_WIPHY, dev->wiphy_idx) ||
-	    nla_put_string(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&dev->wiphy)) ||
-	    nla_put_u32(msg, NL80211_ATTR_GENERATION,
-			cfg80211_rdev_list_generation) ||
-	    nla_put_u8(msg, NL80211_ATTR_WIPHY_RETRY_SHORT,
-		       dev->wiphy.retry_short) ||
-	    nla_put_u8(msg, NL80211_ATTR_WIPHY_RETRY_LONG,
-		       dev->wiphy.retry_long) ||
-	    nla_put_u32(msg, NL80211_ATTR_WIPHY_FRAG_THRESHOLD,
-			dev->wiphy.frag_threshold) ||
-	    nla_put_u32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD,
-			dev->wiphy.rts_threshold) ||
-	    nla_put_u8(msg, NL80211_ATTR_WIPHY_COVERAGE_CLASS,
-		       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) ||
-	    nla_put_u8(msg, NL80211_ATTR_MAX_MATCH_SETS,
-		       dev->wiphy.max_match_sets))
-		goto nla_put_failure;
+	nl_tcp = nla_nest_start(msg, NL80211_WOWLAN_TRIG_TCP_CONNECTION);
+	if (!nl_tcp)
+		return -ENOBUFS;
 
-	if ((dev->wiphy.flags & WIPHY_FLAG_IBSS_RSN) &&
-	    nla_put_flag(msg, NL80211_ATTR_SUPPORT_IBSS_RSN))
-		goto nla_put_failure;
-	if ((dev->wiphy.flags & WIPHY_FLAG_MESH_AUTH) &&
-	    nla_put_flag(msg, NL80211_ATTR_SUPPORT_MESH_AUTH))
-		goto nla_put_failure;
-	if ((dev->wiphy.flags & WIPHY_FLAG_AP_UAPSD) &&
-	    nla_put_flag(msg, NL80211_ATTR_SUPPORT_AP_UAPSD))
-		goto nla_put_failure;
-	if ((dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_FW_ROAM) &&
-	    nla_put_flag(msg, NL80211_ATTR_ROAM_SUPPORT))
-		goto nla_put_failure;
-	if ((dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) &&
-	    nla_put_flag(msg, NL80211_ATTR_TDLS_SUPPORT))
-		goto nla_put_failure;
-	if ((dev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP) &&
-	    nla_put_flag(msg, NL80211_ATTR_TDLS_EXTERNAL_SETUP))
-		goto nla_put_failure;
+	if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD,
+			tcp->data_payload_max))
+		return -ENOBUFS;
 
-	if (nla_put(msg, NL80211_ATTR_CIPHER_SUITES,
-		    sizeof(u32) * dev->wiphy.n_cipher_suites,
-		    dev->wiphy.cipher_suites))
-		goto nla_put_failure;
+	if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD,
+			tcp->data_payload_max))
+		return -ENOBUFS;
 
-	if (nla_put_u8(msg, NL80211_ATTR_MAX_NUM_PMKIDS,
-		       dev->wiphy.max_num_pmkids))
-		goto nla_put_failure;
+	if (tcp->seq && nla_put_flag(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ))
+		return -ENOBUFS;
 
-	if ((dev->wiphy.flags & WIPHY_FLAG_CONTROL_PORT_PROTOCOL) &&
-	    nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE))
-		goto nla_put_failure;
+	if (tcp->tok && nla_put(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN,
+				sizeof(*tcp->tok), tcp->tok))
+		return -ENOBUFS;
 
-	if (nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX,
-			dev->wiphy.available_antennas_tx) ||
-	    nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX,
-			dev->wiphy.available_antennas_rx))
-		goto nla_put_failure;
+	if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_INTERVAL,
+			tcp->data_interval_max))
+		return -ENOBUFS;
 
-	if ((dev->wiphy.flags & WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD) &&
-	    nla_put_u32(msg, NL80211_ATTR_PROBE_RESP_OFFLOAD,
-			dev->wiphy.probe_resp_offload))
-		goto nla_put_failure;
+	if (nla_put_u32(msg, NL80211_WOWLAN_TCP_WAKE_PAYLOAD,
+			tcp->wake_payload_max))
+		return -ENOBUFS;
 
-	if ((dev->wiphy.available_antennas_tx ||
-	     dev->wiphy.available_antennas_rx) && dev->ops->get_antenna) {
-		u32 tx_ant = 0, rx_ant = 0;
-		int res;
-		res = rdev_get_antenna(dev, &tx_ant, &rx_ant);
-		if (!res) {
-			if (nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_TX,
-					tx_ant) ||
-			    nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_RX,
-					rx_ant))
-				goto nla_put_failure;
-		}
+	nla_nest_end(msg, nl_tcp);
+	return 0;
+}
+
+static int nl80211_send_wowlan(struct sk_buff *msg,
+			       struct cfg80211_registered_device *dev,
+			       bool large)
+{
+	struct nlattr *nl_wowlan;
+
+	if (!dev->wiphy.wowlan.flags && !dev->wiphy.wowlan.n_patterns)
+		return 0;
+
+	nl_wowlan = nla_nest_start(msg, NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED);
+	if (!nl_wowlan)
+		return -ENOBUFS;
+
+	if (((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_ANY) &&
+	     nla_put_flag(msg, NL80211_WOWLAN_TRIG_ANY)) ||
+	    ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_DISCONNECT) &&
+	     nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT)) ||
+	    ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_MAGIC_PKT) &&
+	     nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT)) ||
+	    ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_SUPPORTS_GTK_REKEY) &&
+	     nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED)) ||
+	    ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE) &&
+	     nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE)) ||
+	    ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_EAP_IDENTITY_REQ) &&
+	     nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST)) ||
+	    ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_4WAY_HANDSHAKE) &&
+	     nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE)) ||
+	    ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_RFKILL_RELEASE) &&
+	     nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE)))
+		return -ENOBUFS;
+
+	if (dev->wiphy.wowlan.n_patterns) {
+		struct nl80211_wowlan_pattern_support pat = {
+			.max_patterns = dev->wiphy.wowlan.n_patterns,
+			.min_pattern_len = dev->wiphy.wowlan.pattern_min_len,
+			.max_pattern_len = dev->wiphy.wowlan.pattern_max_len,
+			.max_pkt_offset = dev->wiphy.wowlan.max_pkt_offset,
+		};
+
+		if (nla_put(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN,
+			    sizeof(pat), &pat))
+			return -ENOBUFS;
 	}
 
-	if (nl80211_put_iftypes(msg, NL80211_ATTR_SUPPORTED_IFTYPES,
-				dev->wiphy.interface_modes))
-		goto nla_put_failure;
+	if (large && nl80211_send_wowlan_tcp_caps(dev, msg))
+		return -ENOBUFS;
 
-	nl_bands = nla_nest_start(msg, NL80211_ATTR_WIPHY_BANDS);
-	if (!nl_bands)
-		goto nla_put_failure;
+	nla_nest_end(msg, nl_wowlan);
 
-	for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
-		if (!dev->wiphy.bands[band])
-			continue;
+	return 0;
+}
+#endif
 
-		nl_band = nla_nest_start(msg, band);
-		if (!nl_band)
-			goto nla_put_failure;
+static int nl80211_send_band_rateinfo(struct sk_buff *msg,
+				      struct ieee80211_supported_band *sband)
+{
+	struct nlattr *nl_rates, *nl_rate;
+	struct ieee80211_rate *rate;
+	int i;
 
-		/* add HT info */
-		if (dev->wiphy.bands[band]->ht_cap.ht_supported &&
-		    (nla_put(msg, NL80211_BAND_ATTR_HT_MCS_SET,
-			     sizeof(dev->wiphy.bands[band]->ht_cap.mcs),
-			     &dev->wiphy.bands[band]->ht_cap.mcs) ||
-		     nla_put_u16(msg, NL80211_BAND_ATTR_HT_CAPA,
-				 dev->wiphy.bands[band]->ht_cap.cap) ||
-		     nla_put_u8(msg, NL80211_BAND_ATTR_HT_AMPDU_FACTOR,
-				dev->wiphy.bands[band]->ht_cap.ampdu_factor) ||
-		     nla_put_u8(msg, NL80211_BAND_ATTR_HT_AMPDU_DENSITY,
-				dev->wiphy.bands[band]->ht_cap.ampdu_density)))
-			goto nla_put_failure;
+	/* add HT info */
+	if (sband->ht_cap.ht_supported &&
+	    (nla_put(msg, NL80211_BAND_ATTR_HT_MCS_SET,
+		     sizeof(sband->ht_cap.mcs),
+		     &sband->ht_cap.mcs) ||
+	     nla_put_u16(msg, NL80211_BAND_ATTR_HT_CAPA,
+			 sband->ht_cap.cap) ||
+	     nla_put_u8(msg, NL80211_BAND_ATTR_HT_AMPDU_FACTOR,
+			sband->ht_cap.ampdu_factor) ||
+	     nla_put_u8(msg, NL80211_BAND_ATTR_HT_AMPDU_DENSITY,
+			sband->ht_cap.ampdu_density)))
+		return -ENOBUFS;
 
-		/* add VHT info */
-		if (dev->wiphy.bands[band]->vht_cap.vht_supported &&
-		    (nla_put(msg, NL80211_BAND_ATTR_VHT_MCS_SET,
-			     sizeof(dev->wiphy.bands[band]->vht_cap.vht_mcs),
-			     &dev->wiphy.bands[band]->vht_cap.vht_mcs) ||
-		     nla_put_u32(msg, NL80211_BAND_ATTR_VHT_CAPA,
-				 dev->wiphy.bands[band]->vht_cap.cap)))
-			goto nla_put_failure;
+	/* add VHT info */
+	if (sband->vht_cap.vht_supported &&
+	    (nla_put(msg, NL80211_BAND_ATTR_VHT_MCS_SET,
+		     sizeof(sband->vht_cap.vht_mcs),
+		     &sband->vht_cap.vht_mcs) ||
+	     nla_put_u32(msg, NL80211_BAND_ATTR_VHT_CAPA,
+			 sband->vht_cap.cap)))
+		return -ENOBUFS;
 
-		/* add frequencies */
-		nl_freqs = nla_nest_start(msg, NL80211_BAND_ATTR_FREQS);
-		if (!nl_freqs)
-			goto nla_put_failure;
+	/* add bitrates */
+	nl_rates = nla_nest_start(msg, NL80211_BAND_ATTR_RATES);
+	if (!nl_rates)
+		return -ENOBUFS;
 
-		for (i = 0; i < dev->wiphy.bands[band]->n_channels; i++) {
-			nl_freq = nla_nest_start(msg, i);
-			if (!nl_freq)
-				goto nla_put_failure;
+	for (i = 0; i < sband->n_bitrates; i++) {
+		nl_rate = nla_nest_start(msg, i);
+		if (!nl_rate)
+			return -ENOBUFS;
 
-			chan = &dev->wiphy.bands[band]->channels[i];
+		rate = &sband->bitrates[i];
+		if (nla_put_u32(msg, NL80211_BITRATE_ATTR_RATE,
+				rate->bitrate))
+			return -ENOBUFS;
+		if ((rate->flags & IEEE80211_RATE_SHORT_PREAMBLE) &&
+		    nla_put_flag(msg,
+				 NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE))
+			return -ENOBUFS;
 
-			if (nl80211_msg_put_channel(msg, chan))
-				goto nla_put_failure;
+		nla_nest_end(msg, nl_rate);
+	}
 
-			nla_nest_end(msg, nl_freq);
-		}
+	nla_nest_end(msg, nl_rates);
 
-		nla_nest_end(msg, nl_freqs);
+	return 0;
+}
 
-		/* add bitrates */
-		nl_rates = nla_nest_start(msg, NL80211_BAND_ATTR_RATES);
-		if (!nl_rates)
-			goto nla_put_failure;
+static int
+nl80211_send_mgmt_stypes(struct sk_buff *msg,
+			 const struct ieee80211_txrx_stypes *mgmt_stypes)
+{
+	u16 stypes;
+	struct nlattr *nl_ftypes, *nl_ifs;
+	enum nl80211_iftype ift;
+	int i;
 
-		for (i = 0; i < dev->wiphy.bands[band]->n_bitrates; i++) {
-			nl_rate = nla_nest_start(msg, i);
-			if (!nl_rate)
-				goto nla_put_failure;
+	if (!mgmt_stypes)
+		return 0;
 
-			rate = &dev->wiphy.bands[band]->bitrates[i];
-			if (nla_put_u32(msg, NL80211_BITRATE_ATTR_RATE,
-					rate->bitrate))
-				goto nla_put_failure;
-			if ((rate->flags & IEEE80211_RATE_SHORT_PREAMBLE) &&
-			    nla_put_flag(msg,
-					 NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE))
-				goto nla_put_failure;
+	nl_ifs = nla_nest_start(msg, NL80211_ATTR_TX_FRAME_TYPES);
+	if (!nl_ifs)
+		return -ENOBUFS;
 
-			nla_nest_end(msg, nl_rate);
+	for (ift = 0; ift < NUM_NL80211_IFTYPES; ift++) {
+		nl_ftypes = nla_nest_start(msg, ift);
+		if (!nl_ftypes)
+			return -ENOBUFS;
+		i = 0;
+		stypes = mgmt_stypes[ift].tx;
+		while (stypes) {
+			if ((stypes & 1) &&
+			    nla_put_u16(msg, NL80211_ATTR_FRAME_TYPE,
+					(i << 4) | IEEE80211_FTYPE_MGMT))
+				return -ENOBUFS;
+			stypes >>= 1;
+			i++;
 		}
+		nla_nest_end(msg, nl_ftypes);
+	}
 
-		nla_nest_end(msg, nl_rates);
+	nla_nest_end(msg, nl_ifs);
 
-		nla_nest_end(msg, nl_band);
+	nl_ifs = nla_nest_start(msg, NL80211_ATTR_RX_FRAME_TYPES);
+	if (!nl_ifs)
+		return -ENOBUFS;
+
+	for (ift = 0; ift < NUM_NL80211_IFTYPES; ift++) {
+		nl_ftypes = nla_nest_start(msg, ift);
+		if (!nl_ftypes)
+			return -ENOBUFS;
+		i = 0;
+		stypes = mgmt_stypes[ift].rx;
+		while (stypes) {
+			if ((stypes & 1) &&
+			    nla_put_u16(msg, NL80211_ATTR_FRAME_TYPE,
+					(i << 4) | IEEE80211_FTYPE_MGMT))
+				return -ENOBUFS;
+			stypes >>= 1;
+			i++;
+		}
+		nla_nest_end(msg, nl_ftypes);
 	}
-	nla_nest_end(msg, nl_bands);
+	nla_nest_end(msg, nl_ifs);
 
-	nl_cmds = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_COMMANDS);
-	if (!nl_cmds)
-		goto nla_put_failure;
+	return 0;
+}
 
-	i = 0;
-#define CMD(op, n)						\
-	 do {							\
-		if (dev->ops->op) {				\
-			i++;					\
-			if (nla_put_u32(msg, i, NL80211_CMD_ ## n)) \
-				goto nla_put_failure;		\
-		}						\
-	} while (0)
-
-	CMD(add_virtual_intf, NEW_INTERFACE);
-	CMD(change_virtual_intf, SET_INTERFACE);
-	CMD(add_key, NEW_KEY);
-	CMD(start_ap, START_AP);
-	CMD(add_station, NEW_STATION);
-	CMD(add_mpath, NEW_MPATH);
-	CMD(update_mesh_config, SET_MESH_CONFIG);
-	CMD(change_bss, SET_BSS);
-	CMD(auth, AUTHENTICATE);
-	CMD(assoc, ASSOCIATE);
-	CMD(deauth, DEAUTHENTICATE);
-	CMD(disassoc, DISASSOCIATE);
-	CMD(join_ibss, JOIN_IBSS);
-	CMD(join_mesh, JOIN_MESH);
-	CMD(set_pmksa, SET_PMKSA);
-	CMD(del_pmksa, DEL_PMKSA);
-	CMD(flush_pmksa, FLUSH_PMKSA);
-	if (dev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL)
-		CMD(remain_on_channel, REMAIN_ON_CHANNEL);
-	CMD(set_bitrate_mask, SET_TX_BITRATE_MASK);
-	CMD(mgmt_tx, FRAME);
-	CMD(mgmt_tx_cancel_wait, FRAME_WAIT_CANCEL);
-	if (dev->wiphy.flags & WIPHY_FLAG_NETNS_OK) {
-		i++;
-		if (nla_put_u32(msg, i, NL80211_CMD_SET_WIPHY_NETNS))
-			goto nla_put_failure;
+static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
+			      struct sk_buff *msg, u32 portid, u32 seq,
+			      int flags, bool split, long *split_start,
+			      long *band_start, long *chan_start)
+{
+	void *hdr;
+	struct nlattr *nl_bands, *nl_band;
+	struct nlattr *nl_freqs, *nl_freq;
+	struct nlattr *nl_cmds;
+	enum ieee80211_band band;
+	struct ieee80211_channel *chan;
+	int i;
+	const struct ieee80211_txrx_stypes *mgmt_stypes =
+				dev->wiphy.mgmt_stypes;
+	long start = 0, start_chan = 0, start_band = 0;
+	u32 features;
+
+	hdr = nl80211hdr_put(msg, portid, seq, flags, NL80211_CMD_NEW_WIPHY);
+	if (!hdr)
+		return -ENOBUFS;
+
+	/* allow always using the variables */
+	if (!split) {
+		split_start = &start;
+		band_start = &start_band;
+		chan_start = &start_chan;
 	}
-	if (dev->ops->set_monitor_channel || dev->ops->start_ap ||
-	    dev->ops->join_mesh) {
-		i++;
-		if (nla_put_u32(msg, i, NL80211_CMD_SET_CHANNEL))
+
+	if (nla_put_u32(msg, NL80211_ATTR_WIPHY, dev->wiphy_idx) ||
+	    nla_put_string(msg, NL80211_ATTR_WIPHY_NAME,
+			   wiphy_name(&dev->wiphy)) ||
+	    nla_put_u32(msg, NL80211_ATTR_GENERATION,
+			cfg80211_rdev_list_generation))
+		goto nla_put_failure;
+
+	switch (*split_start) {
+	case 0:
+		if (nla_put_u8(msg, NL80211_ATTR_WIPHY_RETRY_SHORT,
+			       dev->wiphy.retry_short) ||
+		    nla_put_u8(msg, NL80211_ATTR_WIPHY_RETRY_LONG,
+			       dev->wiphy.retry_long) ||
+		    nla_put_u32(msg, NL80211_ATTR_WIPHY_FRAG_THRESHOLD,
+				dev->wiphy.frag_threshold) ||
+		    nla_put_u32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD,
+				dev->wiphy.rts_threshold) ||
+		    nla_put_u8(msg, NL80211_ATTR_WIPHY_COVERAGE_CLASS,
+			       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) ||
+		    nla_put_u8(msg, NL80211_ATTR_MAX_MATCH_SETS,
+			       dev->wiphy.max_match_sets))
 			goto nla_put_failure;
-	}
-	CMD(set_wds_peer, SET_WDS_PEER);
-	if (dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) {
-		CMD(tdls_mgmt, TDLS_MGMT);
-		CMD(tdls_oper, TDLS_OPER);
-	}
-	if (dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN)
-		CMD(sched_scan_start, START_SCHED_SCAN);
-	CMD(probe_client, PROBE_CLIENT);
-	CMD(set_noack_map, SET_NOACK_MAP);
-	if (dev->wiphy.flags & WIPHY_FLAG_REPORTS_OBSS) {
-		i++;
-		if (nla_put_u32(msg, i, NL80211_CMD_REGISTER_BEACONS))
+
+		if ((dev->wiphy.flags & WIPHY_FLAG_IBSS_RSN) &&
+		    nla_put_flag(msg, NL80211_ATTR_SUPPORT_IBSS_RSN))
+			goto nla_put_failure;
+		if ((dev->wiphy.flags & WIPHY_FLAG_MESH_AUTH) &&
+		    nla_put_flag(msg, NL80211_ATTR_SUPPORT_MESH_AUTH))
+			goto nla_put_failure;
+		if ((dev->wiphy.flags & WIPHY_FLAG_AP_UAPSD) &&
+		    nla_put_flag(msg, NL80211_ATTR_SUPPORT_AP_UAPSD))
+			goto nla_put_failure;
+		if ((dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_FW_ROAM) &&
+		    nla_put_flag(msg, NL80211_ATTR_ROAM_SUPPORT))
+			goto nla_put_failure;
+		if ((dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) &&
+		    nla_put_flag(msg, NL80211_ATTR_TDLS_SUPPORT))
+			goto nla_put_failure;
+		if ((dev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP) &&
+		    nla_put_flag(msg, NL80211_ATTR_TDLS_EXTERNAL_SETUP))
 			goto nla_put_failure;
-	}
-	CMD(start_p2p_device, START_P2P_DEVICE);
-	CMD(set_mcast_rate, SET_MCAST_RATE);
 
-#ifdef CONFIG_NL80211_TESTMODE
-	CMD(testmode_cmd, TESTMODE);
-#endif
+		(*split_start)++;
+		if (split)
+			break;
+	case 1:
+		if (nla_put(msg, NL80211_ATTR_CIPHER_SUITES,
+			    sizeof(u32) * dev->wiphy.n_cipher_suites,
+			    dev->wiphy.cipher_suites))
+			goto nla_put_failure;
 
-#undef CMD
+		if (nla_put_u8(msg, NL80211_ATTR_MAX_NUM_PMKIDS,
+			       dev->wiphy.max_num_pmkids))
+			goto nla_put_failure;
 
-	if (dev->ops->connect || dev->ops->auth) {
-		i++;
-		if (nla_put_u32(msg, i, NL80211_CMD_CONNECT))
+		if ((dev->wiphy.flags & WIPHY_FLAG_CONTROL_PORT_PROTOCOL) &&
+		    nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE))
 			goto nla_put_failure;
-	}
 
-	if (dev->ops->disconnect || dev->ops->deauth) {
-		i++;
-		if (nla_put_u32(msg, i, NL80211_CMD_DISCONNECT))
+		if (nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX,
+				dev->wiphy.available_antennas_tx) ||
+		    nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX,
+				dev->wiphy.available_antennas_rx))
 			goto nla_put_failure;
-	}
 
-	nla_nest_end(msg, nl_cmds);
+		if ((dev->wiphy.flags & WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD) &&
+		    nla_put_u32(msg, NL80211_ATTR_PROBE_RESP_OFFLOAD,
+				dev->wiphy.probe_resp_offload))
+			goto nla_put_failure;
 
-	if (dev->ops->remain_on_channel &&
-	    (dev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL) &&
-	    nla_put_u32(msg, NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION,
-			dev->wiphy.max_remain_on_channel_duration))
-		goto nla_put_failure;
+		if ((dev->wiphy.available_antennas_tx ||
+		     dev->wiphy.available_antennas_rx) &&
+		    dev->ops->get_antenna) {
+			u32 tx_ant = 0, rx_ant = 0;
+			int res;
+			res = rdev_get_antenna(dev, &tx_ant, &rx_ant);
+			if (!res) {
+				if (nla_put_u32(msg,
+						NL80211_ATTR_WIPHY_ANTENNA_TX,
+						tx_ant) ||
+				    nla_put_u32(msg,
+						NL80211_ATTR_WIPHY_ANTENNA_RX,
+						rx_ant))
+					goto nla_put_failure;
+			}
+		}
 
-	if ((dev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX) &&
-	    nla_put_flag(msg, NL80211_ATTR_OFFCHANNEL_TX_OK))
-		goto nla_put_failure;
+		(*split_start)++;
+		if (split)
+			break;
+	case 2:
+		if (nl80211_put_iftypes(msg, NL80211_ATTR_SUPPORTED_IFTYPES,
+					dev->wiphy.interface_modes))
+				goto nla_put_failure;
+		(*split_start)++;
+		if (split)
+			break;
+	case 3:
+		nl_bands = nla_nest_start(msg, NL80211_ATTR_WIPHY_BANDS);
+		if (!nl_bands)
+			goto nla_put_failure;
 
-	if (mgmt_stypes) {
-		u16 stypes;
-		struct nlattr *nl_ftypes, *nl_ifs;
-		enum nl80211_iftype ift;
+		for (band = *band_start; band < IEEE80211_NUM_BANDS; band++) {
+			struct ieee80211_supported_band *sband;
 
-		nl_ifs = nla_nest_start(msg, NL80211_ATTR_TX_FRAME_TYPES);
-		if (!nl_ifs)
-			goto nla_put_failure;
+			sband = dev->wiphy.bands[band];
 
-		for (ift = 0; ift < NUM_NL80211_IFTYPES; ift++) {
-			nl_ftypes = nla_nest_start(msg, ift);
-			if (!nl_ftypes)
+			if (!sband)
+				continue;
+
+			nl_band = nla_nest_start(msg, band);
+			if (!nl_band)
 				goto nla_put_failure;
-			i = 0;
-			stypes = mgmt_stypes[ift].tx;
-			while (stypes) {
-				if ((stypes & 1) &&
-				    nla_put_u16(msg, NL80211_ATTR_FRAME_TYPE,
-						(i << 4) | IEEE80211_FTYPE_MGMT))
+
+			switch (*chan_start) {
+			case 0:
+				if (nl80211_send_band_rateinfo(msg, sband))
 					goto nla_put_failure;
-				stypes >>= 1;
-				i++;
+				(*chan_start)++;
+				if (split)
+					break;
+			default:
+				/* add frequencies */
+				nl_freqs = nla_nest_start(
+					msg, NL80211_BAND_ATTR_FREQS);
+				if (!nl_freqs)
+					goto nla_put_failure;
+
+				for (i = *chan_start - 1;
+				     i < sband->n_channels;
+				     i++) {
+					nl_freq = nla_nest_start(msg, i);
+					if (!nl_freq)
+						goto nla_put_failure;
+
+					chan = &sband->channels[i];
+
+					if (nl80211_msg_put_channel(msg, chan,
+								    split))
+						goto nla_put_failure;
+
+					nla_nest_end(msg, nl_freq);
+					if (split)
+						break;
+				}
+				if (i < sband->n_channels)
+					*chan_start = i + 2;
+				else
+					*chan_start = 0;
+				nla_nest_end(msg, nl_freqs);
+			}
+
+			nla_nest_end(msg, nl_band);
+
+			if (split) {
+				/* start again here */
+				if (*chan_start)
+					band--;
+				break;
 			}
-			nla_nest_end(msg, nl_ftypes);
 		}
+		nla_nest_end(msg, nl_bands);
 
-		nla_nest_end(msg, nl_ifs);
+		if (band < IEEE80211_NUM_BANDS)
+			*band_start = band + 1;
+		else
+			*band_start = 0;
 
-		nl_ifs = nla_nest_start(msg, NL80211_ATTR_RX_FRAME_TYPES);
-		if (!nl_ifs)
+		/* if bands & channels are done, continue outside */
+		if (*band_start == 0 && *chan_start == 0)
+			(*split_start)++;
+		if (split)
+			break;
+	case 4:
+		nl_cmds = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_COMMANDS);
+		if (!nl_cmds)
 			goto nla_put_failure;
 
-		for (ift = 0; ift < NUM_NL80211_IFTYPES; ift++) {
-			nl_ftypes = nla_nest_start(msg, ift);
-			if (!nl_ftypes)
+		i = 0;
+#define CMD(op, n)							\
+		 do {							\
+			if (dev->ops->op) {				\
+				i++;					\
+				if (nla_put_u32(msg, i, NL80211_CMD_ ## n)) \
+					goto nla_put_failure;		\
+			}						\
+		} while (0)
+
+		CMD(add_virtual_intf, NEW_INTERFACE);
+		CMD(change_virtual_intf, SET_INTERFACE);
+		CMD(add_key, NEW_KEY);
+		CMD(start_ap, START_AP);
+		CMD(add_station, NEW_STATION);
+		CMD(add_mpath, NEW_MPATH);
+		CMD(update_mesh_config, SET_MESH_CONFIG);
+		CMD(change_bss, SET_BSS);
+		CMD(auth, AUTHENTICATE);
+		CMD(assoc, ASSOCIATE);
+		CMD(deauth, DEAUTHENTICATE);
+		CMD(disassoc, DISASSOCIATE);
+		CMD(join_ibss, JOIN_IBSS);
+		CMD(join_mesh, JOIN_MESH);
+		CMD(set_pmksa, SET_PMKSA);
+		CMD(del_pmksa, DEL_PMKSA);
+		CMD(flush_pmksa, FLUSH_PMKSA);
+		if (dev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL)
+			CMD(remain_on_channel, REMAIN_ON_CHANNEL);
+		CMD(set_bitrate_mask, SET_TX_BITRATE_MASK);
+		CMD(mgmt_tx, FRAME);
+		CMD(mgmt_tx_cancel_wait, FRAME_WAIT_CANCEL);
+		if (dev->wiphy.flags & WIPHY_FLAG_NETNS_OK) {
+			i++;
+			if (nla_put_u32(msg, i, NL80211_CMD_SET_WIPHY_NETNS))
 				goto nla_put_failure;
-			i = 0;
-			stypes = mgmt_stypes[ift].rx;
-			while (stypes) {
-				if ((stypes & 1) &&
-				    nla_put_u16(msg, NL80211_ATTR_FRAME_TYPE,
-						(i << 4) | IEEE80211_FTYPE_MGMT))
-					goto nla_put_failure;
-				stypes >>= 1;
-				i++;
-			}
-			nla_nest_end(msg, nl_ftypes);
 		}
-		nla_nest_end(msg, nl_ifs);
-	}
+		if (dev->ops->set_monitor_channel || dev->ops->start_ap ||
+		    dev->ops->join_mesh) {
+			i++;
+			if (nla_put_u32(msg, i, NL80211_CMD_SET_CHANNEL))
+				goto nla_put_failure;
+		}
+		CMD(set_wds_peer, SET_WDS_PEER);
+		if (dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) {
+			CMD(tdls_mgmt, TDLS_MGMT);
+			CMD(tdls_oper, TDLS_OPER);
+		}
+		if (dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN)
+			CMD(sched_scan_start, START_SCHED_SCAN);
+		CMD(probe_client, PROBE_CLIENT);
+		CMD(set_noack_map, SET_NOACK_MAP);
+		if (dev->wiphy.flags & WIPHY_FLAG_REPORTS_OBSS) {
+			i++;
+			if (nla_put_u32(msg, i, NL80211_CMD_REGISTER_BEACONS))
+				goto nla_put_failure;
+		}
+		CMD(start_p2p_device, START_P2P_DEVICE);
+		CMD(set_mcast_rate, SET_MCAST_RATE);
 
-#ifdef CONFIG_PM
-	if (dev->wiphy.wowlan.flags || dev->wiphy.wowlan.n_patterns) {
-		struct nlattr *nl_wowlan;
+#ifdef CONFIG_NL80211_TESTMODE
+		CMD(testmode_cmd, TESTMODE);
+#endif
 
-		nl_wowlan = nla_nest_start(msg,
-				NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED);
-		if (!nl_wowlan)
-			goto nla_put_failure;
+#undef CMD
 
-		if (((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_ANY) &&
-		     nla_put_flag(msg, NL80211_WOWLAN_TRIG_ANY)) ||
-		    ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_DISCONNECT) &&
-		     nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT)) ||
-		    ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_MAGIC_PKT) &&
-		     nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT)) ||
-		    ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_SUPPORTS_GTK_REKEY) &&
-		     nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED)) ||
-		    ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE) &&
-		     nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE)) ||
-		    ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_EAP_IDENTITY_REQ) &&
-		     nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST)) ||
-		    ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_4WAY_HANDSHAKE) &&
-		     nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE)) ||
-		    ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_RFKILL_RELEASE) &&
-		     nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE)))
-		    goto nla_put_failure;
-		if (dev->wiphy.wowlan.n_patterns) {
-			struct nl80211_wowlan_pattern_support pat = {
-				.max_patterns = dev->wiphy.wowlan.n_patterns,
-				.min_pattern_len =
-					dev->wiphy.wowlan.pattern_min_len,
-				.max_pattern_len =
-					dev->wiphy.wowlan.pattern_max_len,
-				.max_pkt_offset =
-					dev->wiphy.wowlan.max_pkt_offset,
-			};
-			if (nla_put(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN,
-				    sizeof(pat), &pat))
+		if (dev->ops->connect || dev->ops->auth) {
+			i++;
+			if (nla_put_u32(msg, i, NL80211_CMD_CONNECT))
 				goto nla_put_failure;
 		}
 
-		nla_nest_end(msg, nl_wowlan);
-	}
+		if (dev->ops->disconnect || dev->ops->deauth) {
+			i++;
+			if (nla_put_u32(msg, i, NL80211_CMD_DISCONNECT))
+				goto nla_put_failure;
+		}
+
+		nla_nest_end(msg, nl_cmds);
+		(*split_start)++;
+		if (split)
+			break;
+	case 5:
+		if (dev->ops->remain_on_channel &&
+		    (dev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL) &&
+		    nla_put_u32(msg,
+				NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION,
+				dev->wiphy.max_remain_on_channel_duration))
+			goto nla_put_failure;
+
+		if ((dev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX) &&
+		    nla_put_flag(msg, NL80211_ATTR_OFFCHANNEL_TX_OK))
+			goto nla_put_failure;
+
+		if (nl80211_send_mgmt_stypes(msg, mgmt_stypes))
+			goto nla_put_failure;
+		(*split_start)++;
+		if (split)
+			break;
+	case 6:
+#ifdef CONFIG_PM
+		if (nl80211_send_wowlan(msg, dev, split))
+			goto nla_put_failure;
+		(*split_start)++;
+		if (split)
+			break;
+#else
+		(*split_start)++;
 #endif
+	case 7:
+		if (nl80211_put_iftypes(msg, NL80211_ATTR_SOFTWARE_IFTYPES,
+					dev->wiphy.software_iftypes))
+			goto nla_put_failure;
 
-	if (nl80211_put_iftypes(msg, NL80211_ATTR_SOFTWARE_IFTYPES,
-				dev->wiphy.software_iftypes))
-		goto nla_put_failure;
+		if (nl80211_put_iface_combinations(&dev->wiphy, msg, split))
+			goto nla_put_failure;
 
-	if (nl80211_put_iface_combinations(&dev->wiphy, msg))
-		goto nla_put_failure;
+		(*split_start)++;
+		if (split)
+			break;
+	case 8:
+		if ((dev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME) &&
+		    nla_put_u32(msg, NL80211_ATTR_DEVICE_AP_SME,
+				dev->wiphy.ap_sme_capa))
+			goto nla_put_failure;
 
-	if ((dev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME) &&
-	    nla_put_u32(msg, NL80211_ATTR_DEVICE_AP_SME,
-			dev->wiphy.ap_sme_capa))
-		goto nla_put_failure;
+		features = dev->wiphy.features;
+		/*
+		 * We can only add the per-channel limit information if the
+		 * dump is split, otherwise it makes it too big. Therefore
+		 * only advertise it in that case.
+		 */
+		if (split)
+			features |= NL80211_FEATURE_ADVERTISE_CHAN_LIMITS;
+		if (nla_put_u32(msg, NL80211_ATTR_FEATURE_FLAGS, features))
+			goto nla_put_failure;
 
-	if (nla_put_u32(msg, NL80211_ATTR_FEATURE_FLAGS,
-			dev->wiphy.features))
-		goto nla_put_failure;
+		if (dev->wiphy.ht_capa_mod_mask &&
+		    nla_put(msg, NL80211_ATTR_HT_CAPABILITY_MASK,
+			    sizeof(*dev->wiphy.ht_capa_mod_mask),
+			    dev->wiphy.ht_capa_mod_mask))
+			goto nla_put_failure;
 
-	if (dev->wiphy.ht_capa_mod_mask &&
-	    nla_put(msg, NL80211_ATTR_HT_CAPABILITY_MASK,
-		    sizeof(*dev->wiphy.ht_capa_mod_mask),
-		    dev->wiphy.ht_capa_mod_mask))
-		goto nla_put_failure;
+		if (dev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME &&
+		    dev->wiphy.max_acl_mac_addrs &&
+		    nla_put_u32(msg, NL80211_ATTR_MAC_ACL_MAX,
+				dev->wiphy.max_acl_mac_addrs))
+			goto nla_put_failure;
 
-	if (dev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME &&
-	    dev->wiphy.max_acl_mac_addrs &&
-	    nla_put_u32(msg, NL80211_ATTR_MAC_ACL_MAX,
-			dev->wiphy.max_acl_mac_addrs))
-		goto nla_put_failure;
+		/*
+		 * Any information below this point is only available to
+		 * applications that can deal with it being split. This
+		 * helps ensure that newly added capabilities don't break
+		 * older tools by overrunning their buffers.
+		 *
+		 * We still increment split_start so that in the split
+		 * case we'll continue with more data in the next round,
+		 * but break unconditionally so unsplit data stops here.
+		 */
+		(*split_start)++;
+		break;
+	case 9:
+		if (dev->wiphy.extended_capabilities &&
+		    (nla_put(msg, NL80211_ATTR_EXT_CAPA,
+			     dev->wiphy.extended_capabilities_len,
+			     dev->wiphy.extended_capabilities) ||
+		     nla_put(msg, NL80211_ATTR_EXT_CAPA_MASK,
+			     dev->wiphy.extended_capabilities_len,
+			     dev->wiphy.extended_capabilities_mask)))
+			goto nla_put_failure;
+
+		if (dev->wiphy.vht_capa_mod_mask &&
+		    nla_put(msg, NL80211_ATTR_VHT_CAPABILITY_MASK,
+			    sizeof(*dev->wiphy.vht_capa_mod_mask),
+			    dev->wiphy.vht_capa_mod_mask))
+			goto nla_put_failure;
 
+		/* done */
+		*split_start = 0;
+		break;
+	}
 	return genlmsg_end(msg, hdr);
 
  nla_put_failure:
@@ -1310,39 +1551,80 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
 	int idx = 0, ret;
 	int start = cb->args[0];
 	struct cfg80211_registered_device *dev;
+	s64 filter_wiphy = -1;
+	bool split = false;
+	struct nlattr **tb = nl80211_fam.attrbuf;
+	int res;
 
 	mutex_lock(&cfg80211_mutex);
+	res = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
+			  tb, nl80211_fam.maxattr, nl80211_policy);
+	if (res == 0) {
+		split = tb[NL80211_ATTR_SPLIT_WIPHY_DUMP];
+		if (tb[NL80211_ATTR_WIPHY])
+			filter_wiphy = nla_get_u32(tb[NL80211_ATTR_WIPHY]);
+		if (tb[NL80211_ATTR_WDEV])
+			filter_wiphy = nla_get_u64(tb[NL80211_ATTR_WDEV]) >> 32;
+		if (tb[NL80211_ATTR_IFINDEX]) {
+			struct net_device *netdev;
+			int ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);
+
+			netdev = dev_get_by_index(sock_net(skb->sk), ifidx);
+			if (!netdev) {
+				mutex_unlock(&cfg80211_mutex);
+				return -ENODEV;
+			}
+			if (netdev->ieee80211_ptr) {
+				dev = wiphy_to_dev(
+					netdev->ieee80211_ptr->wiphy);
+				filter_wiphy = dev->wiphy_idx;
+			}
+			dev_put(netdev);
+		}
+	}
+
 	list_for_each_entry(dev, &cfg80211_rdev_list, list) {
 		if (!net_eq(wiphy_net(&dev->wiphy), sock_net(skb->sk)))
 			continue;
 		if (++idx <= start)
 			continue;
-		ret = nl80211_send_wiphy(skb, NETLINK_CB(cb->skb).portid,
-					 cb->nlh->nlmsg_seq, NLM_F_MULTI,
-					 dev);
-		if (ret < 0) {
-			/*
-			 * If sending the wiphy data didn't fit (ENOBUFS or
-			 * EMSGSIZE returned), this SKB is still empty (so
-			 * it's not too big because another wiphy dataset is
-			 * already in the skb) and we've not tried to adjust
-			 * the dump allocation yet ... then adjust the alloc
-			 * size to be bigger, and return 1 but with the empty
-			 * skb. This results in an empty message being RX'ed
-			 * in userspace, but that is ignored.
-			 *
-			 * We can then retry with the larger buffer.
-			 */
-			if ((ret == -ENOBUFS || ret == -EMSGSIZE) &&
-			    !skb->len &&
-			    cb->min_dump_alloc < 4096) {
-				cb->min_dump_alloc = 4096;
-				mutex_unlock(&cfg80211_mutex);
-				return 1;
+		if (filter_wiphy != -1 && dev->wiphy_idx != filter_wiphy)
+			continue;
+		/* attempt to fit multiple wiphy data chunks into the skb */
+		do {
+			ret = nl80211_send_wiphy(dev, skb,
+						 NETLINK_CB(cb->skb).portid,
+						 cb->nlh->nlmsg_seq,
+						 NLM_F_MULTI,
+						 split, &cb->args[1],
+						 &cb->args[2],
+						 &cb->args[3]);
+			if (ret < 0) {
+				/*
+				 * If sending the wiphy data didn't fit (ENOBUFS
+				 * or EMSGSIZE returned), this SKB is still
+				 * empty (so it's not too big because another
+				 * wiphy dataset is already in the skb) and
+				 * we've not tried to adjust the dump allocation
+				 * yet ... then adjust the alloc size to be
+				 * bigger, and return 1 but with the empty skb.
+				 * This results in an empty message being RX'ed
+				 * in userspace, but that is ignored.
+				 *
+				 * We can then retry with the larger buffer.
+				 */
+				if ((ret == -ENOBUFS || ret == -EMSGSIZE) &&
+				    !skb->len &&
+				    cb->min_dump_alloc < 4096) {
+					cb->min_dump_alloc = 4096;
+					mutex_unlock(&cfg80211_mutex);
+					return 1;
+				}
+				idx--;
+				break;
 			}
-			idx--;
-			break;
-		}
+		} while (cb->args[1] > 0);
+		break;
 	}
 	mutex_unlock(&cfg80211_mutex);
 
@@ -1360,7 +1642,8 @@ static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info)
 	if (!msg)
 		return -ENOMEM;
 
-	if (nl80211_send_wiphy(msg, info->snd_portid, info->snd_seq, 0, dev) < 0) {
+	if (nl80211_send_wiphy(dev, msg, info->snd_portid, info->snd_seq, 0,
+			       false, NULL, NULL, NULL) < 0) {
 		nlmsg_free(msg);
 		return -ENOBUFS;
 	}
@@ -2967,6 +3250,7 @@ static int parse_station_flags(struct genl_info *info,
 		sta_flags = nla_data(nla);
 		params->sta_flags_mask = sta_flags->mask;
 		params->sta_flags_set = sta_flags->set;
+		params->sta_flags_set &= params->sta_flags_mask;
 		if ((params->sta_flags_mask |
 		     params->sta_flags_set) & BIT(__NL80211_STA_FLAG_INVALID))
 			return -EINVAL;
@@ -3320,6 +3604,136 @@ static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
 	return genlmsg_reply(msg, info);
 }
 
+int cfg80211_check_station_change(struct wiphy *wiphy,
+				  struct station_parameters *params,
+				  enum cfg80211_station_type statype)
+{
+	if (params->listen_interval != -1)
+		return -EINVAL;
+	if (params->aid)
+		return -EINVAL;
+
+	/* When you run into this, adjust the code below for the new flag */
+	BUILD_BUG_ON(NL80211_STA_FLAG_MAX != 7);
+
+	switch (statype) {
+	case CFG80211_STA_MESH_PEER_KERNEL:
+	case CFG80211_STA_MESH_PEER_USER:
+		/*
+		 * No ignoring the TDLS flag here -- the userspace mesh
+		 * code doesn't have the bug of including TDLS in the
+		 * mask everywhere.
+		 */
+		if (params->sta_flags_mask &
+				~(BIT(NL80211_STA_FLAG_AUTHENTICATED) |
+				  BIT(NL80211_STA_FLAG_MFP) |
+				  BIT(NL80211_STA_FLAG_AUTHORIZED)))
+			return -EINVAL;
+		break;
+	case CFG80211_STA_TDLS_PEER_SETUP:
+	case CFG80211_STA_TDLS_PEER_ACTIVE:
+		if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)))
+			return -EINVAL;
+		/* ignore since it can't change */
+		params->sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER);
+		break;
+	default:
+		/* disallow mesh-specific things */
+		if (params->plink_action != NL80211_PLINK_ACTION_NO_ACTION)
+			return -EINVAL;
+		if (params->local_pm)
+			return -EINVAL;
+		if (params->sta_modify_mask & STATION_PARAM_APPLY_PLINK_STATE)
+			return -EINVAL;
+	}
+
+	if (statype != CFG80211_STA_TDLS_PEER_SETUP &&
+	    statype != CFG80211_STA_TDLS_PEER_ACTIVE) {
+		/* TDLS can't be set, ... */
+		if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))
+			return -EINVAL;
+		/*
+		 * ... but don't bother the driver with it. This works around
+		 * a hostapd/wpa_supplicant issue -- it always includes the
+		 * TLDS_PEER flag in the mask even for AP mode.
+		 */
+		params->sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER);
+	}
+
+	if (statype != CFG80211_STA_TDLS_PEER_SETUP) {
+		/* reject other things that can't change */
+		if (params->sta_modify_mask & STATION_PARAM_APPLY_UAPSD)
+			return -EINVAL;
+		if (params->sta_modify_mask & STATION_PARAM_APPLY_CAPABILITY)
+			return -EINVAL;
+		if (params->supported_rates)
+			return -EINVAL;
+		if (params->ext_capab || params->ht_capa || params->vht_capa)
+			return -EINVAL;
+	}
+
+	if (statype != CFG80211_STA_AP_CLIENT) {
+		if (params->vlan)
+			return -EINVAL;
+	}
+
+	switch (statype) {
+	case CFG80211_STA_AP_MLME_CLIENT:
+		/* Use this only for authorizing/unauthorizing a station */
+		if (!(params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED)))
+			return -EOPNOTSUPP;
+		break;
+	case CFG80211_STA_AP_CLIENT:
+		/* accept only the listed bits */
+		if (params->sta_flags_mask &
+				~(BIT(NL80211_STA_FLAG_AUTHORIZED) |
+				  BIT(NL80211_STA_FLAG_AUTHENTICATED) |
+				  BIT(NL80211_STA_FLAG_ASSOCIATED) |
+				  BIT(NL80211_STA_FLAG_SHORT_PREAMBLE) |
+				  BIT(NL80211_STA_FLAG_WME) |
+				  BIT(NL80211_STA_FLAG_MFP)))
+			return -EINVAL;
+
+		/* but authenticated/associated only if driver handles it */
+		if (!(wiphy->features & NL80211_FEATURE_FULL_AP_CLIENT_STATE) &&
+		    params->sta_flags_mask &
+				(BIT(NL80211_STA_FLAG_AUTHENTICATED) |
+				 BIT(NL80211_STA_FLAG_ASSOCIATED)))
+			return -EINVAL;
+		break;
+	case CFG80211_STA_IBSS:
+	case CFG80211_STA_AP_STA:
+		/* reject any changes other than AUTHORIZED */
+		if (params->sta_flags_mask & ~BIT(NL80211_STA_FLAG_AUTHORIZED))
+			return -EINVAL;
+		break;
+	case CFG80211_STA_TDLS_PEER_SETUP:
+		/* reject any changes other than AUTHORIZED or WME */
+		if (params->sta_flags_mask & ~(BIT(NL80211_STA_FLAG_AUTHORIZED) |
+					       BIT(NL80211_STA_FLAG_WME)))
+			return -EINVAL;
+		/* force (at least) rates when authorizing */
+		if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED) &&
+		    !params->supported_rates)
+			return -EINVAL;
+		break;
+	case CFG80211_STA_TDLS_PEER_ACTIVE:
+		/* reject any changes */
+		return -EINVAL;
+	case CFG80211_STA_MESH_PEER_KERNEL:
+		if (params->sta_modify_mask & STATION_PARAM_APPLY_PLINK_STATE)
+			return -EINVAL;
+		break;
+	case CFG80211_STA_MESH_PEER_USER:
+		if (params->plink_action != NL80211_PLINK_ACTION_NO_ACTION)
+			return -EINVAL;
+		break;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(cfg80211_check_station_change);
+
 /*
  * Get vlan interface making sure it is running and on the right wiphy.
  */
@@ -3342,6 +3756,13 @@ static struct net_device *get_vlan(struct genl_info *info,
 		goto error;
 	}
 
+	if (v->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN &&
+	    v->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
+	    v->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) {
+		ret = -EINVAL;
+		goto error;
+	}
+
 	if (!netif_running(v)) {
 		ret = -ENETDOWN;
 		goto error;
@@ -3359,21 +3780,13 @@ nl80211_sta_wme_policy[NL80211_STA_WME_MAX + 1] __read_mostly = {
 	[NL80211_STA_WME_MAX_SP] = { .type = NLA_U8 },
 };
 
-static int nl80211_set_station_tdls(struct genl_info *info,
-				    struct station_parameters *params)
+static int nl80211_parse_sta_wme(struct genl_info *info,
+				 struct station_parameters *params)
 {
 	struct nlattr *tb[NL80211_STA_WME_MAX + 1];
 	struct nlattr *nla;
 	int err;
 
-	/* Dummy STA entry gets updated once the peer capabilities are known */
-	if (info->attrs[NL80211_ATTR_HT_CAPABILITY])
-		params->ht_capa =
-			nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]);
-	if (info->attrs[NL80211_ATTR_VHT_CAPABILITY])
-		params->vht_capa =
-			nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]);
-
 	/* parse WME attributes if present */
 	if (!info->attrs[NL80211_ATTR_STA_WME])
 		return 0;
@@ -3401,18 +3814,34 @@ static int nl80211_set_station_tdls(struct genl_info *info,
 	return 0;
 }
 
+static int nl80211_set_station_tdls(struct genl_info *info,
+				    struct station_parameters *params)
+{
+	/* Dummy STA entry gets updated once the peer capabilities are known */
+	if (info->attrs[NL80211_ATTR_HT_CAPABILITY])
+		params->ht_capa =
+			nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]);
+	if (info->attrs[NL80211_ATTR_VHT_CAPABILITY])
+		params->vht_capa =
+			nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]);
+
+	return nl80211_parse_sta_wme(info, params);
+}
+
 static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
 {
 	struct cfg80211_registered_device *rdev = info->user_ptr[0];
-	int err;
 	struct net_device *dev = info->user_ptr[1];
 	struct station_parameters params;
-	u8 *mac_addr = NULL;
+	u8 *mac_addr;
+	int err;
 
 	memset(&params, 0, sizeof(params));
 
 	params.listen_interval = -1;
-	params.plink_state = -1;
+
+	if (!rdev->ops->change_station)
+		return -EOPNOTSUPP;
 
 	if (info->attrs[NL80211_ATTR_STA_AID])
 		return -EINVAL;
@@ -3445,19 +3874,23 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
 	if (info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL])
 		return -EINVAL;
 
-	if (!rdev->ops->change_station)
-		return -EOPNOTSUPP;
-
 	if (parse_station_flags(info, dev->ieee80211_ptr->iftype, &params))
 		return -EINVAL;
 
-	if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION])
+	if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION]) {
 		params.plink_action =
-		    nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);
+			nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);
+		if (params.plink_action >= NUM_NL80211_PLINK_ACTIONS)
+			return -EINVAL;
+	}
 
-	if (info->attrs[NL80211_ATTR_STA_PLINK_STATE])
+	if (info->attrs[NL80211_ATTR_STA_PLINK_STATE]) {
 		params.plink_state =
-		    nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_STATE]);
+			nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_STATE]);
+		if (params.plink_state >= NUM_NL80211_PLINK_STATES)
+			return -EINVAL;
+		params.sta_modify_mask |= STATION_PARAM_APPLY_PLINK_STATE;
+	}
 
 	if (info->attrs[NL80211_ATTR_LOCAL_MESH_POWER_MODE]) {
 		enum nl80211_mesh_power_mode pm = nla_get_u32(
@@ -3470,127 +3903,33 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
 		params.local_pm = pm;
 	}
 
-	switch (dev->ieee80211_ptr->iftype) {
-	case NL80211_IFTYPE_AP:
-	case NL80211_IFTYPE_AP_VLAN:
-	case NL80211_IFTYPE_P2P_GO:
-		/* disallow mesh-specific things */
-		if (params.plink_action)
-			return -EINVAL;
-		if (params.local_pm)
-			return -EINVAL;
-
-		/* TDLS can't be set, ... */
-		if (params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))
-			return -EINVAL;
-		/*
-		 * ... but don't bother the driver with it. This works around
-		 * a hostapd/wpa_supplicant issue -- it always includes the
-		 * TLDS_PEER flag in the mask even for AP mode.
-		 */
-		params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER);
-
-		/* accept only the listed bits */
-		if (params.sta_flags_mask &
-				~(BIT(NL80211_STA_FLAG_AUTHORIZED) |
-				  BIT(NL80211_STA_FLAG_AUTHENTICATED) |
-				  BIT(NL80211_STA_FLAG_ASSOCIATED) |
-				  BIT(NL80211_STA_FLAG_SHORT_PREAMBLE) |
-				  BIT(NL80211_STA_FLAG_WME) |
-				  BIT(NL80211_STA_FLAG_MFP)))
-			return -EINVAL;
-
-		/* but authenticated/associated only if driver handles it */
-		if (!(rdev->wiphy.features &
-				NL80211_FEATURE_FULL_AP_CLIENT_STATE) &&
-		    params.sta_flags_mask &
-				(BIT(NL80211_STA_FLAG_AUTHENTICATED) |
-				 BIT(NL80211_STA_FLAG_ASSOCIATED)))
-			return -EINVAL;
+	/* Include parameters for TDLS peer (will check later) */
+	err = nl80211_set_station_tdls(info, &params);
+	if (err)
+		return err;
 
-		/* reject other things that can't change */
-		if (params.supported_rates)
-			return -EINVAL;
-		if (info->attrs[NL80211_ATTR_STA_CAPABILITY])
-			return -EINVAL;
-		if (info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY])
-			return -EINVAL;
-		if (info->attrs[NL80211_ATTR_HT_CAPABILITY] ||
-		    info->attrs[NL80211_ATTR_VHT_CAPABILITY])
-			return -EINVAL;
+	params.vlan = get_vlan(info, rdev);
+	if (IS_ERR(params.vlan))
+		return PTR_ERR(params.vlan);
 
-		/* must be last in here for error handling */
-		params.vlan = get_vlan(info, rdev);
-		if (IS_ERR(params.vlan))
-			return PTR_ERR(params.vlan);
-		break;
+	switch (dev->ieee80211_ptr->iftype) {
+	case NL80211_IFTYPE_AP:
+	case NL80211_IFTYPE_AP_VLAN:
+	case NL80211_IFTYPE_P2P_GO:
 	case NL80211_IFTYPE_P2P_CLIENT:
 	case NL80211_IFTYPE_STATION:
-		/*
-		 * Don't allow userspace to change the TDLS_PEER flag,
-		 * but silently ignore attempts to change it since we
-		 * don't have state here to verify that it doesn't try
-		 * to change the flag.
-		 */
-		params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER);
-		/* Include parameters for TDLS peer (driver will check) */
-		err = nl80211_set_station_tdls(info, &params);
-		if (err)
-			return err;
-		/* disallow things sta doesn't support */
-		if (params.plink_action)
-			return -EINVAL;
-		if (params.local_pm)
-			return -EINVAL;
-		/* reject any changes other than AUTHORIZED or WME (for TDLS) */
-		if (params.sta_flags_mask & ~(BIT(NL80211_STA_FLAG_AUTHORIZED) |
-					      BIT(NL80211_STA_FLAG_WME)))
-			return -EINVAL;
-		break;
 	case NL80211_IFTYPE_ADHOC:
-		/* disallow things sta doesn't support */
-		if (params.plink_action)
-			return -EINVAL;
-		if (params.local_pm)
-			return -EINVAL;
-		if (info->attrs[NL80211_ATTR_HT_CAPABILITY] ||
-		    info->attrs[NL80211_ATTR_VHT_CAPABILITY])
-			return -EINVAL;
-		/* reject any changes other than AUTHORIZED */
-		if (params.sta_flags_mask & ~BIT(NL80211_STA_FLAG_AUTHORIZED))
-			return -EINVAL;
-		break;
 	case NL80211_IFTYPE_MESH_POINT:
-		/* disallow things mesh doesn't support */
-		if (params.vlan)
-			return -EINVAL;
-		if (params.supported_rates)
-			return -EINVAL;
-		if (info->attrs[NL80211_ATTR_STA_CAPABILITY])
-			return -EINVAL;
-		if (info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY])
-			return -EINVAL;
-		if (info->attrs[NL80211_ATTR_HT_CAPABILITY] ||
-		    info->attrs[NL80211_ATTR_VHT_CAPABILITY])
-			return -EINVAL;
-		/*
-		 * No special handling for TDLS here -- the userspace
-		 * mesh code doesn't have this bug.
-		 */
-		if (params.sta_flags_mask &
-				~(BIT(NL80211_STA_FLAG_AUTHENTICATED) |
-				  BIT(NL80211_STA_FLAG_MFP) |
-				  BIT(NL80211_STA_FLAG_AUTHORIZED)))
-			return -EINVAL;
 		break;
 	default:
-		return -EOPNOTSUPP;
+		err = -EOPNOTSUPP;
+		goto out_put_vlan;
 	}
 
-	/* be aware of params.vlan when changing code here */
-
+	/* driver will call cfg80211_check_station_change() */
 	err = rdev_change_station(rdev, dev, mac_addr, &params);
 
+ out_put_vlan:
 	if (params.vlan)
 		dev_put(params.vlan);
 
@@ -3607,6 +3946,9 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
 
 	memset(&params, 0, sizeof(params));
 
+	if (!rdev->ops->add_station)
+		return -EOPNOTSUPP;
+
 	if (!info->attrs[NL80211_ATTR_MAC])
 		return -EINVAL;
 
@@ -3652,50 +3994,32 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
 		params.vht_capa =
 			nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]);
 
-	if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION])
+	if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION]) {
 		params.plink_action =
-		    nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);
+			nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);
+		if (params.plink_action >= NUM_NL80211_PLINK_ACTIONS)
+			return -EINVAL;
+	}
 
-	if (!rdev->ops->add_station)
-		return -EOPNOTSUPP;
+	err = nl80211_parse_sta_wme(info, &params);
+	if (err)
+		return err;
 
 	if (parse_station_flags(info, dev->ieee80211_ptr->iftype, &params))
 		return -EINVAL;
 
+	/* When you run into this, adjust the code below for the new flag */
+	BUILD_BUG_ON(NL80211_STA_FLAG_MAX != 7);
+
 	switch (dev->ieee80211_ptr->iftype) {
 	case NL80211_IFTYPE_AP:
 	case NL80211_IFTYPE_AP_VLAN:
 	case NL80211_IFTYPE_P2P_GO:
-		/* parse WME attributes if sta is WME capable */
-		if ((rdev->wiphy.flags & WIPHY_FLAG_AP_UAPSD) &&
-		    (params.sta_flags_set & BIT(NL80211_STA_FLAG_WME)) &&
-		    info->attrs[NL80211_ATTR_STA_WME]) {
-			struct nlattr *tb[NL80211_STA_WME_MAX + 1];
-			struct nlattr *nla;
-
-			nla = info->attrs[NL80211_ATTR_STA_WME];
-			err = nla_parse_nested(tb, NL80211_STA_WME_MAX, nla,
-					       nl80211_sta_wme_policy);
-			if (err)
-				return err;
-
-			if (tb[NL80211_STA_WME_UAPSD_QUEUES])
-				params.uapsd_queues =
-				     nla_get_u8(tb[NL80211_STA_WME_UAPSD_QUEUES]);
-			if (params.uapsd_queues &
-					~IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK)
-				return -EINVAL;
+		/* ignore WME attributes if iface/sta is not capable */
+		if (!(rdev->wiphy.flags & WIPHY_FLAG_AP_UAPSD) ||
+		    !(params.sta_flags_set & BIT(NL80211_STA_FLAG_WME)))
+			params.sta_modify_mask &= ~STATION_PARAM_APPLY_UAPSD;
 
-			if (tb[NL80211_STA_WME_MAX_SP])
-				params.max_sp =
-				     nla_get_u8(tb[NL80211_STA_WME_MAX_SP]);
-
-			if (params.max_sp &
-					~IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK)
-				return -EINVAL;
-
-			params.sta_modify_mask |= STATION_PARAM_APPLY_UAPSD;
-		}
 		/* TDLS peers cannot be added */
 		if (params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))
 			return -EINVAL;
@@ -3716,6 +4040,9 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
 			return PTR_ERR(params.vlan);
 		break;
 	case NL80211_IFTYPE_MESH_POINT:
+		/* ignore uAPSD data */
+		params.sta_modify_mask &= ~STATION_PARAM_APPLY_UAPSD;
+
 		/* associated is disallowed */
 		if (params.sta_flags_mask & BIT(NL80211_STA_FLAG_ASSOCIATED))
 			return -EINVAL;
@@ -3724,8 +4051,14 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
 			return -EINVAL;
 		break;
 	case NL80211_IFTYPE_STATION:
-		/* associated is disallowed */
-		if (params.sta_flags_mask & BIT(NL80211_STA_FLAG_ASSOCIATED))
+	case NL80211_IFTYPE_P2P_CLIENT:
+		/* ignore uAPSD data */
+		params.sta_modify_mask &= ~STATION_PARAM_APPLY_UAPSD;
+
+		/* these are disallowed */
+		if (params.sta_flags_mask &
+				(BIT(NL80211_STA_FLAG_ASSOCIATED) |
+				 BIT(NL80211_STA_FLAG_AUTHENTICATED)))
 			return -EINVAL;
 		/* Only TDLS peers can be added */
 		if (!(params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)))
@@ -3736,6 +4069,11 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
 		/* ... with external setup is supported */
 		if (!(rdev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP))
 			return -EOPNOTSUPP;
+		/*
+		 * Older wpa_supplicant versions always mark the TDLS peer
+		 * as authorized, but it shouldn't yet be.
+		 */
+		params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_AUTHORIZED);
 		break;
 	default:
 		return -EOPNOTSUPP;
@@ -4280,6 +4618,7 @@ static const struct nla_policy
 	[NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL] = { .type = NLA_U8 },
 	[NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC] = { .type = NLA_U8 },
 	[NL80211_MESH_SETUP_USERSPACE_AUTH] = { .type = NLA_FLAG },
+	[NL80211_MESH_SETUP_USERSPACE_MPM] = { .type = NLA_FLAG },
 	[NL80211_MESH_SETUP_IE] = { .type = NLA_BINARY,
 				    .len = IEEE80211_MAX_DATA_LEN },
 	[NL80211_MESH_SETUP_USERSPACE_AMPE] = { .type = NLA_FLAG },
@@ -4418,6 +4757,7 @@ do {									    \
 static int nl80211_parse_mesh_setup(struct genl_info *info,
 				     struct mesh_setup *setup)
 {
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
 	struct nlattr *tb[NL80211_MESH_SETUP_ATTR_MAX + 1];
 
 	if (!info->attrs[NL80211_ATTR_MESH_SETUP])
@@ -4454,8 +4794,14 @@ static int nl80211_parse_mesh_setup(struct genl_info *info,
 		setup->ie = nla_data(ieattr);
 		setup->ie_len = nla_len(ieattr);
 	}
+	if (tb[NL80211_MESH_SETUP_USERSPACE_MPM] &&
+	    !(rdev->wiphy.features & NL80211_FEATURE_USERSPACE_MPM))
+		return -EINVAL;
+	setup->user_mpm = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_MPM]);
 	setup->is_authenticated = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_AUTH]);
 	setup->is_secure = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_AMPE]);
+	if (setup->is_secure)
+		setup->user_mpm = true;
 
 	return 0;
 }
@@ -4702,14 +5048,19 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
 	if (!rdev->ops->scan)
 		return -EOPNOTSUPP;
 
-	if (rdev->scan_req)
-		return -EBUSY;
+	mutex_lock(&rdev->sched_scan_mtx);
+	if (rdev->scan_req) {
+		err = -EBUSY;
+		goto unlock;
+	}
 
 	if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
 		n_channels = validate_scan_freqs(
 				info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]);
-		if (!n_channels)
-			return -EINVAL;
+		if (!n_channels) {
+			err = -EINVAL;
+			goto unlock;
+		}
 	} else {
 		enum ieee80211_band band;
 		n_channels = 0;
@@ -4723,23 +5074,29 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
 		nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp)
 			n_ssids++;
 
-	if (n_ssids > wiphy->max_scan_ssids)
-		return -EINVAL;
+	if (n_ssids > wiphy->max_scan_ssids) {
+		err = -EINVAL;
+		goto unlock;
+	}
 
 	if (info->attrs[NL80211_ATTR_IE])
 		ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
 	else
 		ie_len = 0;
 
-	if (ie_len > wiphy->max_scan_ie_len)
-		return -EINVAL;
+	if (ie_len > wiphy->max_scan_ie_len) {
+		err = -EINVAL;
+		goto unlock;
+	}
 
 	request = kzalloc(sizeof(*request)
 			+ sizeof(*request->ssids) * n_ssids
 			+ sizeof(*request->channels) * n_channels
 			+ ie_len, GFP_KERNEL);
-	if (!request)
-		return -ENOMEM;
+	if (!request) {
+		err = -ENOMEM;
+		goto unlock;
+	}
 
 	if (n_ssids)
 		request->ssids = (void *)&request->channels[n_channels];
@@ -4876,6 +5233,8 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
 		kfree(request);
 	}
 
+ unlock:
+	mutex_unlock(&rdev->sched_scan_mtx);
 	return err;
 }
 
@@ -5650,14 +6009,10 @@ static int nl80211_associate(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 cfg80211_crypto_settings crypto;
 	struct ieee80211_channel *chan;
-	const u8 *bssid, *ssid, *ie = NULL, *prev_bssid = NULL;
-	int err, ssid_len, ie_len = 0;
-	bool use_mfp = false;
-	u32 flags = 0;
-	struct ieee80211_ht_cap *ht_capa = NULL;
-	struct ieee80211_ht_cap *ht_capa_mask = NULL;
+	struct cfg80211_assoc_request req = {};
+	const u8 *bssid, *ssid;
+	int err, ssid_len = 0;
 
 	if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
 		return -EINVAL;
@@ -5685,41 +6040,58 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
 	ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
 
 	if (info->attrs[NL80211_ATTR_IE]) {
-		ie = nla_data(info->attrs[NL80211_ATTR_IE]);
-		ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
+		req.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
+		req.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
 	}
 
 	if (info->attrs[NL80211_ATTR_USE_MFP]) {
 		enum nl80211_mfp mfp =
 			nla_get_u32(info->attrs[NL80211_ATTR_USE_MFP]);
 		if (mfp == NL80211_MFP_REQUIRED)
-			use_mfp = true;
+			req.use_mfp = true;
 		else if (mfp != NL80211_MFP_NO)
 			return -EINVAL;
 	}
 
 	if (info->attrs[NL80211_ATTR_PREV_BSSID])
-		prev_bssid = nla_data(info->attrs[NL80211_ATTR_PREV_BSSID]);
+		req.prev_bssid = nla_data(info->attrs[NL80211_ATTR_PREV_BSSID]);
 
 	if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HT]))
-		flags |= ASSOC_REQ_DISABLE_HT;
+		req.flags |= ASSOC_REQ_DISABLE_HT;
 
 	if (info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
-		ht_capa_mask =
-			nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]);
+		memcpy(&req.ht_capa_mask,
+		       nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]),
+		       sizeof(req.ht_capa_mask));
 
 	if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) {
-		if (!ht_capa_mask)
+		if (!info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
+			return -EINVAL;
+		memcpy(&req.ht_capa,
+		       nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]),
+		       sizeof(req.ht_capa));
+	}
+
+	if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_VHT]))
+		req.flags |= ASSOC_REQ_DISABLE_VHT;
+
+	if (info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK])
+		memcpy(&req.vht_capa_mask,
+		       nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]),
+		       sizeof(req.vht_capa_mask));
+
+	if (info->attrs[NL80211_ATTR_VHT_CAPABILITY]) {
+		if (!info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK])
 			return -EINVAL;
-		ht_capa = nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]);
+		memcpy(&req.vht_capa,
+		       nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]),
+		       sizeof(req.vht_capa));
 	}
 
-	err = nl80211_crypto_settings(rdev, info, &crypto, 1);
+	err = nl80211_crypto_settings(rdev, info, &req.crypto, 1);
 	if (!err)
-		err = cfg80211_mlme_assoc(rdev, dev, chan, bssid, prev_bssid,
-					  ssid, ssid_len, ie, ie_len, use_mfp,
-					  &crypto, flags, ht_capa,
-					  ht_capa_mask);
+		err = cfg80211_mlme_assoc(rdev, dev, chan, bssid,
+					  ssid, ssid_len, &req);
 
 	return err;
 }
@@ -6299,6 +6671,24 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
 		       sizeof(connect.ht_capa));
 	}
 
+	if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_VHT]))
+		connect.flags |= ASSOC_REQ_DISABLE_VHT;
+
+	if (info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK])
+		memcpy(&connect.vht_capa_mask,
+		       nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]),
+		       sizeof(connect.vht_capa_mask));
+
+	if (info->attrs[NL80211_ATTR_VHT_CAPABILITY]) {
+		if (!info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]) {
+			kfree(connkeys);
+			return -EINVAL;
+		}
+		memcpy(&connect.vht_capa,
+		       nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]),
+		       sizeof(connect.vht_capa));
+	}
+
 	err = cfg80211_connect(rdev, dev, &connect, connkeys);
 	if (err)
 		kfree(connkeys);
@@ -7072,6 +7462,9 @@ static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info)
 			return err;
 	}
 
+	if (setup.user_mpm)
+		cfg.auto_open_plinks = false;
+
 	if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
 		err = nl80211_parse_chandef(rdev, info, &setup.chandef);
 		if (err)
@@ -7271,7 +7664,8 @@ static int nl80211_parse_wowlan_tcp(struct cfg80211_registered_device *rdev,
 		return -EINVAL;
 
 	if (nla_get_u32(tb[NL80211_WOWLAN_TCP_DATA_INTERVAL]) >
-			rdev->wiphy.wowlan.tcp->data_interval_max)
+			rdev->wiphy.wowlan.tcp->data_interval_max ||
+	    nla_get_u32(tb[NL80211_WOWLAN_TCP_DATA_INTERVAL]) == 0)
 		return -EINVAL;
 
 	wake_size = nla_len(tb[NL80211_WOWLAN_TCP_WAKE_PAYLOAD]);
@@ -7749,22 +8143,59 @@ static int nl80211_stop_p2p_device(struct sk_buff *skb, struct genl_info *info)
 	if (!rdev->ops->stop_p2p_device)
 		return -EOPNOTSUPP;
 
-	if (!wdev->p2p_started)
-		return 0;
+	mutex_lock(&rdev->sched_scan_mtx);
+	cfg80211_stop_p2p_device(rdev, wdev);
+	mutex_unlock(&rdev->sched_scan_mtx);
 
-	rdev_stop_p2p_device(rdev, wdev);
-	wdev->p2p_started = false;
+	return 0;
+}
 
-	mutex_lock(&rdev->devlist_mtx);
-	rdev->opencount--;
-	mutex_unlock(&rdev->devlist_mtx);
+static int nl80211_get_protocol_features(struct sk_buff *skb,
+					 struct genl_info *info)
+{
+	void *hdr;
+	struct sk_buff *msg;
 
-	if (WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev)) {
-		rdev->scan_req->aborted = true;
-		___cfg80211_scan_done(rdev, true);
-	}
+	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+	if (!msg)
+		return -ENOMEM;
 
-	return 0;
+	hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
+			     NL80211_CMD_GET_PROTOCOL_FEATURES);
+	if (!hdr)
+		goto nla_put_failure;
+
+	if (nla_put_u32(msg, NL80211_ATTR_PROTOCOL_FEATURES,
+			NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP))
+		goto nla_put_failure;
+
+	genlmsg_end(msg, hdr);
+	return genlmsg_reply(msg, info);
+
+ nla_put_failure:
+	kfree_skb(msg);
+	return -ENOBUFS;
+}
+
+static int nl80211_update_ft_ies(struct sk_buff *skb, struct genl_info *info)
+{
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
+	struct cfg80211_update_ft_ies_params ft_params;
+	struct net_device *dev = info->user_ptr[1];
+
+	if (!rdev->ops->update_ft_ies)
+		return -EOPNOTSUPP;
+
+	if (!info->attrs[NL80211_ATTR_MDID] ||
+	    !is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
+		return -EINVAL;
+
+	memset(&ft_params, 0, sizeof(ft_params));
+	ft_params.md = nla_get_u16(info->attrs[NL80211_ATTR_MDID]);
+	ft_params.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
+	ft_params.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
+
+	return rdev_update_ft_ies(rdev, dev, &ft_params);
 }
 
 #define NL80211_FLAG_NEED_WIPHY		0x01
@@ -8443,6 +8874,19 @@ static struct genl_ops nl80211_ops[] = {
 		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
 				  NL80211_FLAG_NEED_RTNL,
 	},
+	{
+		.cmd = NL80211_CMD_GET_PROTOCOL_FEATURES,
+		.doit = nl80211_get_protocol_features,
+		.policy = nl80211_policy,
+	},
+	{
+		.cmd = NL80211_CMD_UPDATE_FT_IES,
+		.doit = nl80211_update_ft_ies,
+		.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 = {
@@ -8470,7 +8914,8 @@ void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev)
 	if (!msg)
 		return;
 
-	if (nl80211_send_wiphy(msg, 0, 0, 0, rdev) < 0) {
+	if (nl80211_send_wiphy(rdev, msg, 0, 0, 0,
+			       false, NULL, NULL, NULL) < 0) {
 		nlmsg_free(msg);
 		return;
 	}
@@ -8486,7 +8931,7 @@ static int nl80211_add_scan_req(struct sk_buff *msg,
 	struct nlattr *nest;
 	int i;
 
-	ASSERT_RDEV_LOCK(rdev);
+	lockdep_assert_held(&rdev->sched_scan_mtx);
 
 	if (WARN_ON(!req))
 		return 0;
@@ -8794,21 +9239,31 @@ void nl80211_send_disassoc(struct cfg80211_registered_device *rdev,
 				NL80211_CMD_DISASSOCIATE, gfp);
 }
 
-void nl80211_send_unprot_deauth(struct cfg80211_registered_device *rdev,
-				struct net_device *netdev, const u8 *buf,
-				size_t len, gfp_t gfp)
+void cfg80211_send_unprot_deauth(struct net_device *dev, const u8 *buf,
+				 size_t len)
 {
-	nl80211_send_mlme_event(rdev, netdev, buf, len,
-				NL80211_CMD_UNPROT_DEAUTHENTICATE, gfp);
+	struct wireless_dev *wdev = dev->ieee80211_ptr;
+	struct wiphy *wiphy = wdev->wiphy;
+	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
+
+	trace_cfg80211_send_unprot_deauth(dev);
+	nl80211_send_mlme_event(rdev, dev, buf, len,
+				NL80211_CMD_UNPROT_DEAUTHENTICATE, GFP_ATOMIC);
 }
+EXPORT_SYMBOL(cfg80211_send_unprot_deauth);
 
-void nl80211_send_unprot_disassoc(struct cfg80211_registered_device *rdev,
-				  struct net_device *netdev, const u8 *buf,
-				  size_t len, gfp_t gfp)
+void cfg80211_send_unprot_disassoc(struct net_device *dev, const u8 *buf,
+				   size_t len)
 {
-	nl80211_send_mlme_event(rdev, netdev, buf, len,
-				NL80211_CMD_UNPROT_DISASSOCIATE, gfp);
+	struct wireless_dev *wdev = dev->ieee80211_ptr;
+	struct wiphy *wiphy = wdev->wiphy;
+	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
+
+	trace_cfg80211_send_unprot_disassoc(dev);
+	nl80211_send_mlme_event(rdev, dev, buf, len,
+				NL80211_CMD_UNPROT_DISASSOCIATE, GFP_ATOMIC);
 }
+EXPORT_SYMBOL(cfg80211_send_unprot_disassoc);
 
 static void nl80211_send_mlme_timeout(struct cfg80211_registered_device *rdev,
 				      struct net_device *netdev, int cmd,
@@ -9011,14 +9466,19 @@ void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev,
 	nlmsg_free(msg);
 }
 
-void nl80211_send_new_peer_candidate(struct cfg80211_registered_device *rdev,
-		struct net_device *netdev,
-		const u8 *macaddr, const u8* ie, u8 ie_len,
-		gfp_t gfp)
+void cfg80211_notify_new_peer_candidate(struct net_device *dev, const u8 *addr,
+					const u8* ie, u8 ie_len, gfp_t gfp)
 {
+	struct wireless_dev *wdev = dev->ieee80211_ptr;
+	struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
 	struct sk_buff *msg;
 	void *hdr;
 
+	if (WARN_ON(wdev->iftype != NL80211_IFTYPE_MESH_POINT))
+		return;
+
+	trace_cfg80211_notify_new_peer_candidate(dev, addr);
+
 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
 	if (!msg)
 		return;
@@ -9030,8 +9490,8 @@ void nl80211_send_new_peer_candidate(struct cfg80211_registered_device *rdev,
 	}
 
 	if (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, macaddr) ||
+	    nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
+	    nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) ||
 	    (ie_len && ie &&
 	     nla_put(msg, NL80211_ATTR_IE, ie_len , ie)))
 		goto nla_put_failure;
@@ -9046,6 +9506,7 @@ void nl80211_send_new_peer_candidate(struct cfg80211_registered_device *rdev,
 	genlmsg_cancel(msg, hdr);
 	nlmsg_free(msg);
 }
+EXPORT_SYMBOL(cfg80211_notify_new_peer_candidate);
 
 void nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev,
 				 struct net_device *netdev, const u8 *addr,
@@ -9114,7 +9575,7 @@ void nl80211_send_beacon_hint_event(struct wiphy *wiphy,
 	nl_freq = nla_nest_start(msg, NL80211_ATTR_FREQ_BEFORE);
 	if (!nl_freq)
 		goto nla_put_failure;
-	if (nl80211_msg_put_channel(msg, channel_before))
+	if (nl80211_msg_put_channel(msg, channel_before, false))
 		goto nla_put_failure;
 	nla_nest_end(msg, nl_freq);
 
@@ -9122,7 +9583,7 @@ void nl80211_send_beacon_hint_event(struct wiphy *wiphy,
 	nl_freq = nla_nest_start(msg, NL80211_ATTR_FREQ_AFTER);
 	if (!nl_freq)
 		goto nla_put_failure;
-	if (nl80211_msg_put_channel(msg, channel_after))
+	if (nl80211_msg_put_channel(msg, channel_after, false))
 		goto nla_put_failure;
 	nla_nest_end(msg, nl_freq);
 
@@ -9184,31 +9645,42 @@ static void nl80211_send_remain_on_chan_event(
 	nlmsg_free(msg);
 }
 
-void nl80211_send_remain_on_channel(struct cfg80211_registered_device *rdev,
-				    struct wireless_dev *wdev, u64 cookie,
-				    struct ieee80211_channel *chan,
-				    unsigned int duration, gfp_t gfp)
+void cfg80211_ready_on_channel(struct wireless_dev *wdev, u64 cookie,
+			       struct ieee80211_channel *chan,
+			       unsigned int duration, gfp_t gfp)
 {
+	struct wiphy *wiphy = wdev->wiphy;
+	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
+
+	trace_cfg80211_ready_on_channel(wdev, cookie, chan, duration);
 	nl80211_send_remain_on_chan_event(NL80211_CMD_REMAIN_ON_CHANNEL,
 					  rdev, wdev, cookie, chan,
 					  duration, gfp);
 }
+EXPORT_SYMBOL(cfg80211_ready_on_channel);
 
-void nl80211_send_remain_on_channel_cancel(
-	struct cfg80211_registered_device *rdev,
-	struct wireless_dev *wdev,
-	u64 cookie, struct ieee80211_channel *chan, gfp_t gfp)
+void cfg80211_remain_on_channel_expired(struct wireless_dev *wdev, u64 cookie,
+					struct ieee80211_channel *chan,
+					gfp_t gfp)
 {
+	struct wiphy *wiphy = wdev->wiphy;
+	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
+
+	trace_cfg80211_ready_on_channel_expired(wdev, cookie, chan);
 	nl80211_send_remain_on_chan_event(NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL,
 					  rdev, wdev, cookie, chan, 0, gfp);
 }
+EXPORT_SYMBOL(cfg80211_remain_on_channel_expired);
 
-void nl80211_send_sta_event(struct cfg80211_registered_device *rdev,
-			    struct net_device *dev, const u8 *mac_addr,
-			    struct station_info *sinfo, gfp_t gfp)
+void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr,
+		      struct station_info *sinfo, gfp_t gfp)
 {
+	struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
+	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 	struct sk_buff *msg;
 
+	trace_cfg80211_new_sta(dev, mac_addr, sinfo);
+
 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
 	if (!msg)
 		return;
@@ -9222,14 +9694,17 @@ void nl80211_send_sta_event(struct cfg80211_registered_device *rdev,
 	genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
 				nl80211_mlme_mcgrp.id, gfp);
 }
+EXPORT_SYMBOL(cfg80211_new_sta);
 
-void nl80211_send_sta_del_event(struct cfg80211_registered_device *rdev,
-				struct net_device *dev, const u8 *mac_addr,
-				gfp_t gfp)
+void cfg80211_del_sta(struct net_device *dev, const u8 *mac_addr, gfp_t gfp)
 {
+	struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
+	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 	struct sk_buff *msg;
 	void *hdr;
 
+	trace_cfg80211_del_sta(dev, mac_addr);
+
 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
 	if (!msg)
 		return;
@@ -9254,12 +9729,14 @@ void nl80211_send_sta_del_event(struct cfg80211_registered_device *rdev,
 	genlmsg_cancel(msg, hdr);
 	nlmsg_free(msg);
 }
+EXPORT_SYMBOL(cfg80211_del_sta);
 
-void nl80211_send_conn_failed_event(struct cfg80211_registered_device *rdev,
-				    struct net_device *dev, const u8 *mac_addr,
-				    enum nl80211_connect_failed_reason reason,
-				    gfp_t gfp)
+void cfg80211_conn_failed(struct net_device *dev, const u8 *mac_addr,
+			  enum nl80211_connect_failed_reason reason,
+			  gfp_t gfp)
 {
+	struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
+	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 	struct sk_buff *msg;
 	void *hdr;
 
@@ -9288,6 +9765,7 @@ void nl80211_send_conn_failed_event(struct cfg80211_registered_device *rdev,
 	genlmsg_cancel(msg, hdr);
 	nlmsg_free(msg);
 }
+EXPORT_SYMBOL(cfg80211_conn_failed);
 
 static bool __nl80211_unexpected_frame(struct net_device *dev, u8 cmd,
 				       const u8 *addr, gfp_t gfp)
@@ -9332,19 +9810,47 @@ static bool __nl80211_unexpected_frame(struct net_device *dev, u8 cmd,
 	return true;
 }
 
-bool nl80211_unexpected_frame(struct net_device *dev, const u8 *addr, gfp_t gfp)
+bool cfg80211_rx_spurious_frame(struct net_device *dev,
+				const u8 *addr, gfp_t gfp)
 {
-	return __nl80211_unexpected_frame(dev, NL80211_CMD_UNEXPECTED_FRAME,
-					  addr, gfp);
+	struct wireless_dev *wdev = dev->ieee80211_ptr;
+	bool ret;
+
+	trace_cfg80211_rx_spurious_frame(dev, addr);
+
+	if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
+		    wdev->iftype != NL80211_IFTYPE_P2P_GO)) {
+		trace_cfg80211_return_bool(false);
+		return false;
+	}
+	ret = __nl80211_unexpected_frame(dev, NL80211_CMD_UNEXPECTED_FRAME,
+					 addr, gfp);
+	trace_cfg80211_return_bool(ret);
+	return ret;
 }
+EXPORT_SYMBOL(cfg80211_rx_spurious_frame);
 
-bool nl80211_unexpected_4addr_frame(struct net_device *dev,
-				    const u8 *addr, gfp_t gfp)
+bool cfg80211_rx_unexpected_4addr_frame(struct net_device *dev,
+					const u8 *addr, gfp_t gfp)
 {
-	return __nl80211_unexpected_frame(dev,
-					  NL80211_CMD_UNEXPECTED_4ADDR_FRAME,
-					  addr, gfp);
+	struct wireless_dev *wdev = dev->ieee80211_ptr;
+	bool ret;
+
+	trace_cfg80211_rx_unexpected_4addr_frame(dev, addr);
+
+	if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
+		    wdev->iftype != NL80211_IFTYPE_P2P_GO &&
+		    wdev->iftype != NL80211_IFTYPE_AP_VLAN)) {
+		trace_cfg80211_return_bool(false);
+		return false;
+	}
+	ret = __nl80211_unexpected_frame(dev,
+					 NL80211_CMD_UNEXPECTED_4ADDR_FRAME,
+					 addr, gfp);
+	trace_cfg80211_return_bool(ret);
+	return ret;
 }
+EXPORT_SYMBOL(cfg80211_rx_unexpected_4addr_frame);
 
 int nl80211_send_mgmt(struct cfg80211_registered_device *rdev,
 		      struct wireless_dev *wdev, u32 nlportid,
@@ -9384,15 +9890,17 @@ int nl80211_send_mgmt(struct cfg80211_registered_device *rdev,
 	return -ENOBUFS;
 }
 
-void nl80211_send_mgmt_tx_status(struct cfg80211_registered_device *rdev,
-				 struct wireless_dev *wdev, u64 cookie,
-				 const u8 *buf, size_t len, bool ack,
-				 gfp_t gfp)
+void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie,
+			     const u8 *buf, size_t len, bool ack, gfp_t gfp)
 {
+	struct wiphy *wiphy = wdev->wiphy;
+	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 	struct net_device *netdev = wdev->netdev;
 	struct sk_buff *msg;
 	void *hdr;
 
+	trace_cfg80211_mgmt_tx_status(wdev, cookie, ack);
+
 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
 	if (!msg)
 		return;
@@ -9420,17 +9928,21 @@ void nl80211_send_mgmt_tx_status(struct cfg80211_registered_device *rdev,
 	genlmsg_cancel(msg, hdr);
 	nlmsg_free(msg);
 }
+EXPORT_SYMBOL(cfg80211_mgmt_tx_status);
 
-void
-nl80211_send_cqm_rssi_notify(struct cfg80211_registered_device *rdev,
-			     struct net_device *netdev,
-			     enum nl80211_cqm_rssi_threshold_event rssi_event,
-			     gfp_t gfp)
+void cfg80211_cqm_rssi_notify(struct net_device *dev,
+			      enum nl80211_cqm_rssi_threshold_event rssi_event,
+			      gfp_t gfp)
 {
+	struct wireless_dev *wdev = dev->ieee80211_ptr;
+	struct wiphy *wiphy = wdev->wiphy;
+	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 	struct sk_buff *msg;
 	struct nlattr *pinfoattr;
 	void *hdr;
 
+	trace_cfg80211_cqm_rssi_notify(dev, rssi_event);
+
 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
 	if (!msg)
 		return;
@@ -9442,7 +9954,7 @@ nl80211_send_cqm_rssi_notify(struct cfg80211_registered_device *rdev,
 	}
 
 	if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
-	    nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex))
+	    nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex))
 		goto nla_put_failure;
 
 	pinfoattr = nla_nest_start(msg, NL80211_ATTR_CQM);
@@ -9465,10 +9977,11 @@ nl80211_send_cqm_rssi_notify(struct cfg80211_registered_device *rdev,
 	genlmsg_cancel(msg, hdr);
 	nlmsg_free(msg);
 }
+EXPORT_SYMBOL(cfg80211_cqm_rssi_notify);
 
-void nl80211_gtk_rekey_notify(struct cfg80211_registered_device *rdev,
-			      struct net_device *netdev, const u8 *bssid,
-			      const u8 *replay_ctr, gfp_t gfp)
+static 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;
@@ -9510,9 +10023,22 @@ void nl80211_gtk_rekey_notify(struct cfg80211_registered_device *rdev,
 	nlmsg_free(msg);
 }
 
-void nl80211_pmksa_candidate_notify(struct cfg80211_registered_device *rdev,
-				    struct net_device *netdev, int index,
-				    const u8 *bssid, bool preauth, gfp_t gfp)
+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);
+
+	trace_cfg80211_gtk_rekey_notify(dev, bssid);
+	nl80211_gtk_rekey_notify(rdev, dev, bssid, replay_ctr, gfp);
+}
+EXPORT_SYMBOL(cfg80211_gtk_rekey_notify);
+
+static void
+nl80211_pmksa_candidate_notify(struct cfg80211_registered_device *rdev,
+			       struct net_device *netdev, int index,
+			       const u8 *bssid, bool preauth, gfp_t gfp)
 {
 	struct sk_buff *msg;
 	struct nlattr *attr;
@@ -9555,9 +10081,22 @@ void nl80211_pmksa_candidate_notify(struct cfg80211_registered_device *rdev,
 	nlmsg_free(msg);
 }
 
-void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev,
-			      struct net_device *netdev,
-			      struct cfg80211_chan_def *chandef, gfp_t gfp)
+void cfg80211_pmksa_candidate_notify(struct net_device *dev, int index,
+				     const u8 *bssid, bool preauth, gfp_t gfp)
+{
+	struct wireless_dev *wdev = dev->ieee80211_ptr;
+	struct wiphy *wiphy = wdev->wiphy;
+	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
+
+	trace_cfg80211_pmksa_candidate_notify(dev, index, bssid, preauth);
+	nl80211_pmksa_candidate_notify(rdev, dev, index, bssid, preauth, gfp);
+}
+EXPORT_SYMBOL(cfg80211_pmksa_candidate_notify);
+
+static void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev,
+				     struct net_device *netdev,
+				     struct cfg80211_chan_def *chandef,
+				     gfp_t gfp)
 {
 	struct sk_buff *msg;
 	void *hdr;
@@ -9589,11 +10128,36 @@ void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev,
 	nlmsg_free(msg);
 }
 
-void
-nl80211_send_cqm_txe_notify(struct cfg80211_registered_device *rdev,
-			    struct net_device *netdev, const u8 *peer,
-			    u32 num_packets, u32 rate, u32 intvl, gfp_t gfp)
+void cfg80211_ch_switch_notify(struct net_device *dev,
+			       struct cfg80211_chan_def *chandef)
+{
+	struct wireless_dev *wdev = dev->ieee80211_ptr;
+	struct wiphy *wiphy = wdev->wiphy;
+	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
+
+	trace_cfg80211_ch_switch_notify(dev, chandef);
+
+	wdev_lock(wdev);
+
+	if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
+		    wdev->iftype != NL80211_IFTYPE_P2P_GO))
+		goto out;
+
+	wdev->channel = chandef->chan;
+	nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL);
+out:
+	wdev_unlock(wdev);
+	return;
+}
+EXPORT_SYMBOL(cfg80211_ch_switch_notify);
+
+void cfg80211_cqm_txe_notify(struct net_device *dev,
+			     const u8 *peer, u32 num_packets,
+			     u32 rate, u32 intvl, gfp_t gfp)
 {
+	struct wireless_dev *wdev = dev->ieee80211_ptr;
+	struct wiphy *wiphy = wdev->wiphy;
+	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 	struct sk_buff *msg;
 	struct nlattr *pinfoattr;
 	void *hdr;
@@ -9609,7 +10173,7 @@ nl80211_send_cqm_txe_notify(struct cfg80211_registered_device *rdev,
 	}
 
 	if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
-	    nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
+	    nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
 	    nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, peer))
 		goto nla_put_failure;
 
@@ -9638,6 +10202,7 @@ nl80211_send_cqm_txe_notify(struct cfg80211_registered_device *rdev,
 	genlmsg_cancel(msg, hdr);
 	nlmsg_free(msg);
 }
+EXPORT_SYMBOL(cfg80211_cqm_txe_notify);
 
 void
 nl80211_radar_notify(struct cfg80211_registered_device *rdev,
@@ -9690,15 +10255,18 @@ nl80211_radar_notify(struct cfg80211_registered_device *rdev,
 	nlmsg_free(msg);
 }
 
-void
-nl80211_send_cqm_pktloss_notify(struct cfg80211_registered_device *rdev,
-				struct net_device *netdev, const u8 *peer,
-				u32 num_packets, gfp_t gfp)
+void cfg80211_cqm_pktloss_notify(struct net_device *dev,
+				 const u8 *peer, u32 num_packets, gfp_t gfp)
 {
+	struct wireless_dev *wdev = dev->ieee80211_ptr;
+	struct wiphy *wiphy = wdev->wiphy;
+	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 	struct sk_buff *msg;
 	struct nlattr *pinfoattr;
 	void *hdr;
 
+	trace_cfg80211_cqm_pktloss_notify(dev, peer, num_packets);
+
 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
 	if (!msg)
 		return;
@@ -9710,7 +10278,7 @@ nl80211_send_cqm_pktloss_notify(struct cfg80211_registered_device *rdev,
 	}
 
 	if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
-	    nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
+	    nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
 	    nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, peer))
 		goto nla_put_failure;
 
@@ -9733,6 +10301,7 @@ nl80211_send_cqm_pktloss_notify(struct cfg80211_registered_device *rdev,
 	genlmsg_cancel(msg, hdr);
 	nlmsg_free(msg);
 }
+EXPORT_SYMBOL(cfg80211_cqm_pktloss_notify);
 
 void cfg80211_probe_status(struct net_device *dev, const u8 *addr,
 			   u64 cookie, bool acked, gfp_t gfp)
@@ -10019,6 +10588,50 @@ static struct notifier_block nl80211_netlink_notifier = {
 	.notifier_call = nl80211_netlink_notify,
 };
 
+void cfg80211_ft_event(struct net_device *netdev,
+		       struct cfg80211_ft_event_params *ft_event)
+{
+	struct wiphy *wiphy = netdev->ieee80211_ptr->wiphy;
+	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
+	struct sk_buff *msg;
+	void *hdr;
+	int err;
+
+	trace_cfg80211_ft_event(wiphy, netdev, ft_event);
+
+	if (!ft_event->target_ap)
+		return;
+
+	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+	if (!msg)
+		return;
+
+	hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FT_EVENT);
+	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, ft_event->target_ap);
+	if (ft_event->ies)
+		nla_put(msg, NL80211_ATTR_IE, ft_event->ies_len, ft_event->ies);
+	if (ft_event->ric_ies)
+		nla_put(msg, NL80211_ATTR_IE_RIC, ft_event->ric_ies_len,
+			ft_event->ric_ies);
+
+	err = genlmsg_end(msg, hdr);
+	if (err < 0) {
+		nlmsg_free(msg);
+		return;
+	}
+
+	genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+				nl80211_mlme_mcgrp.id, GFP_KERNEL);
+}
+EXPORT_SYMBOL(cfg80211_ft_event);
+
 /* initialisation/exit functions */
 
 int nl80211_init(void)
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h
index b061da4..a4073e8 100644
--- a/net/wireless/nl80211.h
+++ b/net/wireless/nl80211.h
@@ -29,12 +29,6 @@ void nl80211_send_deauth(struct cfg80211_registered_device *rdev,
 void nl80211_send_disassoc(struct cfg80211_registered_device *rdev,
 			   struct net_device *netdev,
 			   const u8 *buf, size_t len, gfp_t gfp);
-void nl80211_send_unprot_deauth(struct cfg80211_registered_device *rdev,
-				struct net_device *netdev,
-				const u8 *buf, size_t len, gfp_t gfp);
-void nl80211_send_unprot_disassoc(struct cfg80211_registered_device *rdev,
-				  struct net_device *netdev,
-				  const u8 *buf, size_t len, gfp_t gfp);
 void nl80211_send_auth_timeout(struct cfg80211_registered_device *rdev,
 			       struct net_device *netdev,
 			       const u8 *addr, gfp_t gfp);
@@ -54,10 +48,6 @@ void nl80211_send_disconnected(struct cfg80211_registered_device *rdev,
 			       struct net_device *netdev, u16 reason,
 			       const u8 *ie, size_t ie_len, bool from_ap);
 
-void nl80211_send_new_peer_candidate(struct cfg80211_registered_device *rdev,
-				     struct net_device *netdev,
-				     const u8 *macaddr, const u8* ie, u8 ie_len,
-				     gfp_t gfp);
 void
 nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev,
 			    struct net_device *netdev, const u8 *addr,
@@ -73,41 +63,10 @@ void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev,
 			     struct net_device *netdev, const u8 *bssid,
 			     gfp_t gfp);
 
-void nl80211_send_remain_on_channel(struct cfg80211_registered_device *rdev,
-				    struct wireless_dev *wdev, u64 cookie,
-				    struct ieee80211_channel *chan,
-				    unsigned int duration, gfp_t gfp);
-void nl80211_send_remain_on_channel_cancel(
-	struct cfg80211_registered_device *rdev,
-	struct wireless_dev *wdev,
-	u64 cookie, struct ieee80211_channel *chan, gfp_t gfp);
-
-void nl80211_send_sta_event(struct cfg80211_registered_device *rdev,
-			    struct net_device *dev, const u8 *mac_addr,
-			    struct station_info *sinfo, gfp_t gfp);
-void nl80211_send_sta_del_event(struct cfg80211_registered_device *rdev,
-				struct net_device *dev, const u8 *mac_addr,
-				gfp_t gfp);
-
-void nl80211_send_conn_failed_event(struct cfg80211_registered_device *rdev,
-				    struct net_device *dev, const u8 *mac_addr,
-				    enum nl80211_connect_failed_reason reason,
-				    gfp_t gfp);
-
 int nl80211_send_mgmt(struct cfg80211_registered_device *rdev,
 		      struct wireless_dev *wdev, u32 nlpid,
 		      int freq, int sig_dbm,
 		      const u8 *buf, size_t len, gfp_t gfp);
-void nl80211_send_mgmt_tx_status(struct cfg80211_registered_device *rdev,
-				 struct wireless_dev *wdev, u64 cookie,
-				 const u8 *buf, size_t len, bool ack,
-				 gfp_t gfp);
-
-void
-nl80211_send_cqm_rssi_notify(struct cfg80211_registered_device *rdev,
-			     struct net_device *netdev,
-			     enum nl80211_cqm_rssi_threshold_event rssi_event,
-			     gfp_t gfp);
 
 void
 nl80211_radar_notify(struct cfg80211_registered_device *rdev,
@@ -115,31 +74,4 @@ nl80211_radar_notify(struct cfg80211_registered_device *rdev,
 		     enum nl80211_radar_event event,
 		     struct net_device *netdev, gfp_t gfp);
 
-void
-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_send_cqm_txe_notify(struct cfg80211_registered_device *rdev,
-			    struct net_device *netdev, const u8 *peer,
-			    u32 num_packets, u32 rate, u32 intvl, 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);
-
-void nl80211_pmksa_candidate_notify(struct cfg80211_registered_device *rdev,
-				    struct net_device *netdev, int index,
-				    const u8 *bssid, bool preauth, gfp_t gfp);
-
-void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev,
-			      struct net_device *dev,
-			      struct cfg80211_chan_def *chandef, gfp_t gfp);
-
-bool nl80211_unexpected_frame(struct net_device *dev,
-			      const u8 *addr, gfp_t gfp);
-bool nl80211_unexpected_4addr_frame(struct net_device *dev,
-				    const u8 *addr, gfp_t gfp);
-
 #endif /* __NET_WIRELESS_NL80211_H */
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h
index 422d382..d77e1c1 100644
--- a/net/wireless/rdev-ops.h
+++ b/net/wireless/rdev-ops.h
@@ -6,11 +6,12 @@
 #include "core.h"
 #include "trace.h"
 
-static inline int rdev_suspend(struct cfg80211_registered_device *rdev)
+static inline int rdev_suspend(struct cfg80211_registered_device *rdev,
+			       struct cfg80211_wowlan *wowlan)
 {
 	int ret;
-	trace_rdev_suspend(&rdev->wiphy, rdev->wowlan);
-	ret = rdev->ops->suspend(&rdev->wiphy, rdev->wowlan);
+	trace_rdev_suspend(&rdev->wiphy, wowlan);
+	ret = rdev->ops->suspend(&rdev->wiphy, wowlan);
 	trace_rdev_return_int(&rdev->wiphy, ret);
 	return ret;
 }
@@ -887,4 +888,17 @@ static inline int rdev_set_mac_acl(struct cfg80211_registered_device *rdev,
 	trace_rdev_return_int(&rdev->wiphy, ret);
 	return ret;
 }
+
+static inline int rdev_update_ft_ies(struct cfg80211_registered_device *rdev,
+				     struct net_device *dev,
+				     struct cfg80211_update_ft_ies_params *ftie)
+{
+	int ret;
+
+	trace_rdev_update_ft_ies(&rdev->wiphy, dev, ftie);
+	ret = rdev->ops->update_ft_ies(&rdev->wiphy, dev, ftie);
+	trace_rdev_return_int(&rdev->wiphy, ret);
+	return ret;
+}
+
 #endif /* __CFG80211_RDEV_OPS */
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 98532c00..e6df52d 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -184,14 +184,14 @@ static const struct ieee80211_regdomain world_regdom = {
 			NL80211_RRF_NO_IBSS |
 			NL80211_RRF_NO_OFDM),
 		/* IEEE 802.11a, channel 36..48 */
-		REG_RULE(5180-10, 5240+10, 40, 6, 20,
+		REG_RULE(5180-10, 5240+10, 80, 6, 20,
                         NL80211_RRF_PASSIVE_SCAN |
                         NL80211_RRF_NO_IBSS),
 
-		/* NB: 5260 MHz - 5700 MHz requies DFS */
+		/* NB: 5260 MHz - 5700 MHz requires DFS */
 
 		/* IEEE 802.11a, channel 149..165 */
-		REG_RULE(5745-10, 5825+10, 40, 6, 20,
+		REG_RULE(5745-10, 5825+10, 80, 6, 20,
 			NL80211_RRF_PASSIVE_SCAN |
 			NL80211_RRF_NO_IBSS),
 
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 674aadc..fd99ea4 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -169,7 +169,7 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak)
 	union iwreq_data wrqu;
 #endif
 
-	ASSERT_RDEV_LOCK(rdev);
+	lockdep_assert_held(&rdev->sched_scan_mtx);
 
 	request = rdev->scan_req;
 
@@ -230,9 +230,9 @@ void __cfg80211_scan_done(struct work_struct *wk)
 	rdev = container_of(wk, struct cfg80211_registered_device,
 			    scan_done_wk);
 
-	cfg80211_lock_rdev(rdev);
+	mutex_lock(&rdev->sched_scan_mtx);
 	___cfg80211_scan_done(rdev, false);
-	cfg80211_unlock_rdev(rdev);
+	mutex_unlock(&rdev->sched_scan_mtx);
 }
 
 void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted)
@@ -698,11 +698,6 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
 	found = rb_find_bss(dev, tmp, BSS_CMP_REGULAR);
 
 	if (found) {
-		found->pub.beacon_interval = tmp->pub.beacon_interval;
-		found->pub.signal = tmp->pub.signal;
-		found->pub.capability = tmp->pub.capability;
-		found->ts = tmp->ts;
-
 		/* Update IEs */
 		if (rcu_access_pointer(tmp->pub.proberesp_ies)) {
 			const struct cfg80211_bss_ies *old;
@@ -723,6 +718,8 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
 
 			if (found->pub.hidden_beacon_bss &&
 			    !list_empty(&found->hidden_list)) {
+				const struct cfg80211_bss_ies *f;
+
 				/*
 				 * The found BSS struct is one of the probe
 				 * response members of a group, but we're
@@ -732,6 +729,10 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
 				 * SSID to showing it, which is confusing so
 				 * drop this information.
 				 */
+
+				f = rcu_access_pointer(tmp->pub.beacon_ies);
+				kfree_rcu((struct cfg80211_bss_ies *)f,
+					  rcu_head);
 				goto drop;
 			}
 
@@ -761,6 +762,11 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
 				kfree_rcu((struct cfg80211_bss_ies *)old,
 					  rcu_head);
 		}
+
+		found->pub.beacon_interval = tmp->pub.beacon_interval;
+		found->pub.signal = tmp->pub.signal;
+		found->pub.capability = tmp->pub.capability;
+		found->ts = tmp->ts;
 	} else {
 		struct cfg80211_internal_bss *new;
 		struct cfg80211_internal_bss *hidden;
@@ -1056,6 +1062,7 @@ int cfg80211_wext_siwscan(struct net_device *dev,
 	if (IS_ERR(rdev))
 		return PTR_ERR(rdev);
 
+	mutex_lock(&rdev->sched_scan_mtx);
 	if (rdev->scan_req) {
 		err = -EBUSY;
 		goto out;
@@ -1162,6 +1169,7 @@ int cfg80211_wext_siwscan(struct net_device *dev,
 		dev_hold(dev);
 	}
  out:
+	mutex_unlock(&rdev->sched_scan_mtx);
 	kfree(creq);
 	cfg80211_unlock_rdev(rdev);
 	return err;
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index f432bd3..a9dc5c7 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -85,6 +85,7 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev)
 	ASSERT_RTNL();
 	ASSERT_RDEV_LOCK(rdev);
 	ASSERT_WDEV_LOCK(wdev);
+	lockdep_assert_held(&rdev->sched_scan_mtx);
 
 	if (rdev->scan_req)
 		return -EBUSY;
@@ -159,7 +160,7 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev)
 {
 	struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
 	struct cfg80211_connect_params *params;
-	const u8 *prev_bssid = NULL;
+	struct cfg80211_assoc_request req = {};
 	int err;
 
 	ASSERT_WDEV_LOCK(wdev);
@@ -186,16 +187,20 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev)
 		BUG_ON(!rdev->ops->assoc);
 		wdev->conn->state = CFG80211_CONN_ASSOCIATING;
 		if (wdev->conn->prev_bssid_valid)
-			prev_bssid = wdev->conn->prev_bssid;
-		err = __cfg80211_mlme_assoc(rdev, wdev->netdev,
-					    params->channel, params->bssid,
-					    prev_bssid,
-					    params->ssid, params->ssid_len,
-					    params->ie, params->ie_len,
-					    params->mfp != NL80211_MFP_NO,
-					    &params->crypto,
-					    params->flags, &params->ht_capa,
-					    &params->ht_capa_mask);
+			req.prev_bssid = wdev->conn->prev_bssid;
+		req.ie = params->ie;
+		req.ie_len = params->ie_len;
+		req.use_mfp = params->mfp != NL80211_MFP_NO;
+		req.crypto = params->crypto;
+		req.flags = params->flags;
+		req.ht_capa = params->ht_capa;
+		req.ht_capa_mask = params->ht_capa_mask;
+		req.vht_capa = params->vht_capa;
+		req.vht_capa_mask = params->vht_capa_mask;
+
+		err = __cfg80211_mlme_assoc(rdev, wdev->netdev, params->channel,
+					    params->bssid, params->ssid,
+					    params->ssid_len, &req);
 		if (err)
 			__cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid,
 					       NULL, 0,
@@ -223,6 +228,7 @@ void cfg80211_conn_work(struct work_struct *work)
 	rtnl_lock();
 	cfg80211_lock_rdev(rdev);
 	mutex_lock(&rdev->devlist_mtx);
+	mutex_lock(&rdev->sched_scan_mtx);
 
 	list_for_each_entry(wdev, &rdev->wdev_list, list) {
 		wdev_lock(wdev);
@@ -230,7 +236,7 @@ void cfg80211_conn_work(struct work_struct *work)
 			wdev_unlock(wdev);
 			continue;
 		}
-		if (wdev->sme_state != CFG80211_SME_CONNECTING) {
+		if (wdev->sme_state != CFG80211_SME_CONNECTING || !wdev->conn) {
 			wdev_unlock(wdev);
 			continue;
 		}
@@ -247,6 +253,7 @@ void cfg80211_conn_work(struct work_struct *work)
 		wdev_unlock(wdev);
 	}
 
+	mutex_unlock(&rdev->sched_scan_mtx);
 	mutex_unlock(&rdev->devlist_mtx);
 	cfg80211_unlock_rdev(rdev);
 	rtnl_unlock();
@@ -320,11 +327,9 @@ void cfg80211_sme_scan_done(struct net_device *dev)
 {
 	struct wireless_dev *wdev = dev->ieee80211_ptr;
 
-	mutex_lock(&wiphy_to_dev(wdev->wiphy)->devlist_mtx);
 	wdev_lock(wdev);
 	__cfg80211_sme_scan_done(dev);
 	wdev_unlock(wdev);
-	mutex_unlock(&wiphy_to_dev(wdev->wiphy)->devlist_mtx);
 }
 
 void cfg80211_sme_rx_auth(struct net_device *dev,
@@ -924,9 +929,12 @@ int cfg80211_connect(struct cfg80211_registered_device *rdev,
 	int err;
 
 	mutex_lock(&rdev->devlist_mtx);
+	/* might request scan - scan_mtx -> wdev_mtx dependency */
+	mutex_lock(&rdev->sched_scan_mtx);
 	wdev_lock(dev->ieee80211_ptr);
 	err = __cfg80211_connect(rdev, dev, connect, connkeys, NULL);
 	wdev_unlock(dev->ieee80211_ptr);
+	mutex_unlock(&rdev->sched_scan_mtx);
 	mutex_unlock(&rdev->devlist_mtx);
 
 	return err;
diff --git a/net/wireless/sysfs.c b/net/wireless/sysfs.c
index 238ee49..8f28b9f 100644
--- a/net/wireless/sysfs.c
+++ b/net/wireless/sysfs.c
@@ -83,6 +83,14 @@ static int wiphy_uevent(struct device *dev, struct kobj_uevent_env *env)
 	return 0;
 }
 
+static void cfg80211_leave_all(struct cfg80211_registered_device *rdev)
+{
+	struct wireless_dev *wdev;
+
+	list_for_each_entry(wdev, &rdev->wdev_list, list)
+		cfg80211_leave(rdev, wdev);
+}
+
 static int wiphy_suspend(struct device *dev, pm_message_t state)
 {
 	struct cfg80211_registered_device *rdev = dev_to_rdev(dev);
@@ -90,12 +98,19 @@ static int wiphy_suspend(struct device *dev, pm_message_t state)
 
 	rdev->suspend_at = get_seconds();
 
-	if (rdev->ops->suspend) {
-		rtnl_lock();
-		if (rdev->wiphy.registered)
-			ret = rdev_suspend(rdev);
-		rtnl_unlock();
+	rtnl_lock();
+	if (rdev->wiphy.registered) {
+		if (!rdev->wowlan)
+			cfg80211_leave_all(rdev);
+		if (rdev->ops->suspend)
+			ret = rdev_suspend(rdev, rdev->wowlan);
+		if (ret == 1) {
+			/* Driver refuse to configure wowlan */
+			cfg80211_leave_all(rdev);
+			ret = rdev_suspend(rdev, NULL);
+		}
 	}
+	rtnl_unlock();
 
 	return ret;
 }
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index b7a5313..3c2033b 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -27,7 +27,8 @@
 #define WIPHY_PR_ARG	__entry->wiphy_name
 
 #define WDEV_ENTRY	__field(u32, id)
-#define WDEV_ASSIGN	(__entry->id) = (wdev ? wdev->identifier : 0)
+#define WDEV_ASSIGN	(__entry->id) = (!IS_ERR_OR_NULL(wdev)	\
+					 ? wdev->identifier : 0)
 #define WDEV_PR_FMT	"wdev(%u)"
 #define WDEV_PR_ARG	(__entry->id)
 
@@ -1778,13 +1779,33 @@ TRACE_EVENT(rdev_set_mac_acl,
 	),
 	TP_fast_assign(
 		WIPHY_ASSIGN;
-		WIPHY_ASSIGN;
+		NETDEV_ASSIGN;
 		__entry->acl_policy = params->acl_policy;
 	),
 	TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", acl policy: %d",
 		  WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->acl_policy)
 );
 
+TRACE_EVENT(rdev_update_ft_ies,
+	TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+		 struct cfg80211_update_ft_ies_params *ftie),
+	TP_ARGS(wiphy, netdev, ftie),
+	TP_STRUCT__entry(
+		WIPHY_ENTRY
+		NETDEV_ENTRY
+		__field(u16, md)
+		__dynamic_array(u8, ie, ftie->ie_len)
+	),
+	TP_fast_assign(
+		WIPHY_ASSIGN;
+		NETDEV_ASSIGN;
+		__entry->md = ftie->md;
+		memcpy(__get_dynamic_array(ie), ftie->ie, ftie->ie_len);
+	),
+	TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", md: 0x%x",
+		  WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->md)
+);
+
 /*************************************************************
  *	     cfg80211 exported functions traces		     *
  *************************************************************/
@@ -2413,6 +2434,32 @@ TRACE_EVENT(cfg80211_report_wowlan_wakeup,
 	TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT, WIPHY_PR_ARG, WDEV_PR_ARG)
 );
 
+TRACE_EVENT(cfg80211_ft_event,
+	TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+		 struct cfg80211_ft_event_params *ft_event),
+	TP_ARGS(wiphy, netdev, ft_event),
+	TP_STRUCT__entry(
+		WIPHY_ENTRY
+		NETDEV_ENTRY
+		__dynamic_array(u8, ies, ft_event->ies_len)
+		MAC_ENTRY(target_ap)
+		__dynamic_array(u8, ric_ies, ft_event->ric_ies_len)
+	),
+	TP_fast_assign(
+		WIPHY_ASSIGN;
+		NETDEV_ASSIGN;
+		if (ft_event->ies)
+			memcpy(__get_dynamic_array(ies), ft_event->ies,
+			       ft_event->ies_len);
+		MAC_ASSIGN(target_ap, ft_event->target_ap);
+		if (ft_event->ric_ies)
+			memcpy(__get_dynamic_array(ric_ies), ft_event->ric_ies,
+			       ft_event->ric_ies_len);
+	),
+	TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", target_ap: " MAC_PR_FMT,
+		  WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(target_ap))
+);
+
 #endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */
 
 #undef TRACE_INCLUDE_PATH
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 37a56ee..6cbac99 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -511,7 +511,7 @@ int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr,
 		encaps_data = bridge_tunnel_header;
 		encaps_len = sizeof(bridge_tunnel_header);
 		skip_header_bytes -= 2;
-	} else if (ethertype > 0x600) {
+	} else if (ethertype >= ETH_P_802_3_MIN) {
 		encaps_data = rfc1042_header;
 		encaps_len = sizeof(rfc1042_header);
 		skip_header_bytes -= 2;
diff --git a/net/wireless/wext-sme.c b/net/wireless/wext-sme.c
index fb9622f..e79cb5c 100644
--- a/net/wireless/wext-sme.c
+++ b/net/wireless/wext-sme.c
@@ -89,6 +89,7 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev,
 
 	cfg80211_lock_rdev(rdev);
 	mutex_lock(&rdev->devlist_mtx);
+	mutex_lock(&rdev->sched_scan_mtx);
 	wdev_lock(wdev);
 
 	if (wdev->sme_state != CFG80211_SME_IDLE) {
@@ -135,6 +136,7 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev,
 	err = cfg80211_mgd_wext_connect(rdev, wdev);
  out:
 	wdev_unlock(wdev);
+	mutex_unlock(&rdev->sched_scan_mtx);
 	mutex_unlock(&rdev->devlist_mtx);
 	cfg80211_unlock_rdev(rdev);
 	return err;
@@ -190,6 +192,7 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev,
 
 	cfg80211_lock_rdev(rdev);
 	mutex_lock(&rdev->devlist_mtx);
+	mutex_lock(&rdev->sched_scan_mtx);
 	wdev_lock(wdev);
 
 	err = 0;
@@ -223,6 +226,7 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev,
 	err = cfg80211_mgd_wext_connect(rdev, wdev);
  out:
 	wdev_unlock(wdev);
+	mutex_unlock(&rdev->sched_scan_mtx);
 	mutex_unlock(&rdev->devlist_mtx);
 	cfg80211_unlock_rdev(rdev);
 	return err;
@@ -285,6 +289,7 @@ int cfg80211_mgd_wext_siwap(struct net_device *dev,
 
 	cfg80211_lock_rdev(rdev);
 	mutex_lock(&rdev->devlist_mtx);
+	mutex_lock(&rdev->sched_scan_mtx);
 	wdev_lock(wdev);
 
 	if (wdev->sme_state != CFG80211_SME_IDLE) {
@@ -313,6 +318,7 @@ int cfg80211_mgd_wext_siwap(struct net_device *dev,
 	err = cfg80211_mgd_wext_connect(rdev, wdev);
  out:
 	wdev_unlock(wdev);
+	mutex_unlock(&rdev->sched_scan_mtx);
 	mutex_unlock(&rdev->devlist_mtx);
 	cfg80211_unlock_rdev(rdev);
 	return err;
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 167c67d..23cea0f 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -1037,6 +1037,24 @@ __xfrm_policy_lookup(struct net *net, const struct flowi *fl, u16 family, u8 dir
 	return xfrm_policy_lookup_bytype(net, XFRM_POLICY_TYPE_MAIN, fl, family, dir);
 }
 
+static int flow_to_policy_dir(int dir)
+{
+	if (XFRM_POLICY_IN == FLOW_DIR_IN &&
+	    XFRM_POLICY_OUT == FLOW_DIR_OUT &&
+	    XFRM_POLICY_FWD == FLOW_DIR_FWD)
+		return dir;
+
+	switch (dir) {
+	default:
+	case FLOW_DIR_IN:
+		return XFRM_POLICY_IN;
+	case FLOW_DIR_OUT:
+		return XFRM_POLICY_OUT;
+	case FLOW_DIR_FWD:
+		return XFRM_POLICY_FWD;
+	}
+}
+
 static struct flow_cache_object *
 xfrm_policy_lookup(struct net *net, const struct flowi *fl, u16 family,
 		   u8 dir, struct flow_cache_object *old_obj, void *ctx)
@@ -1046,7 +1064,7 @@ xfrm_policy_lookup(struct net *net, const struct flowi *fl, u16 family,
 	if (old_obj)
 		xfrm_pol_put(container_of(old_obj, struct xfrm_policy, flo));
 
-	pol = __xfrm_policy_lookup(net, fl, family, dir);
+	pol = __xfrm_policy_lookup(net, fl, family, flow_to_policy_dir(dir));
 	if (IS_ERR_OR_NULL(pol))
 		return ERR_CAST(pol);
 
@@ -1932,7 +1950,8 @@ xfrm_bundle_lookup(struct net *net, const struct flowi *fl, u16 family, u8 dir,
 	 * previous cache entry */
 	if (xdst == NULL) {
 		num_pols = 1;
-		pols[0] = __xfrm_policy_lookup(net, fl, family, dir);
+		pols[0] = __xfrm_policy_lookup(net, fl, family,
+					       flow_to_policy_dir(dir));
 		err = xfrm_expand_policies(fl, family, pols,
 					   &num_pols, &num_xfrms);
 		if (err < 0)
diff --git a/net/xfrm/xfrm_replay.c b/net/xfrm/xfrm_replay.c
index 35754cc..8dafe6d3 100644
--- a/net/xfrm/xfrm_replay.c
+++ b/net/xfrm/xfrm_replay.c
@@ -334,6 +334,70 @@ static void xfrm_replay_notify_bmp(struct xfrm_state *x, int event)
 		x->xflags &= ~XFRM_TIME_DEFER;
 }
 
+static void xfrm_replay_notify_esn(struct xfrm_state *x, int event)
+{
+	u32 seq_diff, oseq_diff;
+	struct km_event c;
+	struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
+	struct xfrm_replay_state_esn *preplay_esn = x->preplay_esn;
+
+	/* we send notify messages in case
+	 *  1. we updated on of the sequence numbers, and the seqno difference
+	 *     is at least x->replay_maxdiff, in this case we also update the
+	 *     timeout of our timer function
+	 *  2. if x->replay_maxage has elapsed since last update,
+	 *     and there were changes
+	 *
+	 *  The state structure must be locked!
+	 */
+
+	switch (event) {
+	case XFRM_REPLAY_UPDATE:
+		if (!x->replay_maxdiff)
+			break;
+
+		if (replay_esn->seq_hi == preplay_esn->seq_hi)
+			seq_diff = replay_esn->seq - preplay_esn->seq;
+		else
+			seq_diff = ~preplay_esn->seq + replay_esn->seq + 1;
+
+		if (replay_esn->oseq_hi == preplay_esn->oseq_hi)
+			oseq_diff = replay_esn->oseq - preplay_esn->oseq;
+		else
+			oseq_diff = ~preplay_esn->oseq + replay_esn->oseq + 1;
+
+		if (seq_diff < x->replay_maxdiff &&
+		    oseq_diff < x->replay_maxdiff) {
+
+			if (x->xflags & XFRM_TIME_DEFER)
+				event = XFRM_REPLAY_TIMEOUT;
+			else
+				return;
+		}
+
+		break;
+
+	case XFRM_REPLAY_TIMEOUT:
+		if (memcmp(x->replay_esn, x->preplay_esn,
+			   xfrm_replay_state_esn_len(replay_esn)) == 0) {
+			x->xflags |= XFRM_TIME_DEFER;
+			return;
+		}
+
+		break;
+	}
+
+	memcpy(x->preplay_esn, x->replay_esn,
+	       xfrm_replay_state_esn_len(replay_esn));
+	c.event = XFRM_MSG_NEWAE;
+	c.data.aevent = event;
+	km_state_notify(x, &c);
+
+	if (x->replay_maxage &&
+	    !mod_timer(&x->rtimer, jiffies + x->replay_maxage))
+		x->xflags &= ~XFRM_TIME_DEFER;
+}
+
 static int xfrm_replay_overflow_esn(struct xfrm_state *x, struct sk_buff *skb)
 {
 	int err = 0;
@@ -510,7 +574,7 @@ static struct xfrm_replay xfrm_replay_esn = {
 	.advance	= xfrm_replay_advance_esn,
 	.check		= xfrm_replay_check_esn,
 	.recheck	= xfrm_replay_recheck_esn,
-	.notify		= xfrm_replay_notify_bmp,
+	.notify		= xfrm_replay_notify_esn,
 	.overflow	= xfrm_replay_overflow_esn,
 };
 
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 2c341bd..78f66fa 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -1187,6 +1187,7 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig, int *errp)
 		goto error;
 
 	x->props.flags = orig->props.flags;
+	x->props.extra_flags = orig->props.extra_flags;
 
 	x->curlft.add_time = orig->curlft.add_time;
 	x->km.state = orig->km.state;
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index fbd9e6c..aa77874 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -515,6 +515,9 @@ static struct xfrm_state *xfrm_state_construct(struct net *net,
 
 	copy_from_user_state(x, p);
 
+	if (attrs[XFRMA_SA_EXTRA_FLAGS])
+		x->props.extra_flags = nla_get_u32(attrs[XFRMA_SA_EXTRA_FLAGS]);
+
 	if ((err = attach_aead(&x->aead, &x->props.ealgo,
 			       attrs[XFRMA_ALG_AEAD])))
 		goto error;
@@ -779,6 +782,13 @@ static int copy_to_user_state_extra(struct xfrm_state *x,
 
 	copy_to_user_state(x, p);
 
+	if (x->props.extra_flags) {
+		ret = nla_put_u32(skb, XFRMA_SA_EXTRA_FLAGS,
+				  x->props.extra_flags);
+		if (ret)
+			goto out;
+	}
+
 	if (x->coaddr) {
 		ret = nla_put(skb, XFRMA_COADDR, sizeof(*x->coaddr), x->coaddr);
 		if (ret)
@@ -2302,9 +2312,10 @@ static const struct nla_policy xfrma_policy[XFRMA_MAX+1] = {
 	[XFRMA_MARK]		= { .len = sizeof(struct xfrm_mark) },
 	[XFRMA_TFCPAD]		= { .type = NLA_U32 },
 	[XFRMA_REPLAY_ESN_VAL]	= { .len = sizeof(struct xfrm_replay_state_esn) },
+	[XFRMA_SA_EXTRA_FLAGS]	= { .type = NLA_U32 },
 };
 
-static struct xfrm_link {
+static const struct xfrm_link {
 	int (*doit)(struct sk_buff *, struct nlmsghdr *, struct nlattr **);
 	int (*dump)(struct sk_buff *, struct netlink_callback *);
 	int (*done)(struct netlink_callback *);
@@ -2338,7 +2349,7 @@ static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 {
 	struct net *net = sock_net(skb->sk);
 	struct nlattr *attrs[XFRMA_MAX+1];
-	struct xfrm_link *link;
+	const struct xfrm_link *link;
 	int type, err;
 
 	type = nlh->nlmsg_type;
@@ -2495,6 +2506,8 @@ static inline size_t xfrm_sa_len(struct xfrm_state *x)
 				    x->security->ctx_len);
 	if (x->coaddr)
 		l += nla_total_size(sizeof(*x->coaddr));
+	if (x->props.extra_flags)
+		l += nla_total_size(sizeof(x->props.extra_flags));
 
 	/* Must count x->lastused as it may become non-zero behind our back. */
 	l += nla_total_size(sizeof(u64));
diff --git a/samples/hidraw/hid-example.c b/samples/hidraw/hid-example.c
index 816e2dc..512a7e5 100644
--- a/samples/hidraw/hid-example.c
+++ b/samples/hidraw/hid-example.c
@@ -17,10 +17,9 @@
 /*
  * Ugly hack to work around failing compilation on systems that don't
  * yet populate new version of hidraw.h to userspace.
- *
- * If you need this, please have your distro update the kernel headers.
  */
 #ifndef HIDIOCSFEATURE
+#warning Please have your distro update the userspace kernel headers
 #define HIDIOCSFEATURE(len)    _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x06, len)
 #define HIDIOCGFEATURE(len)    _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x07, len)
 #endif
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index 0e801c3..d5d859c 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -211,7 +211,8 @@ $(obj)/%.i: $(src)/%.c FORCE
 
 cmd_gensymtypes =                                                           \
     $(CPP) -D__GENKSYMS__ $(c_flags) $< |                                   \
-    $(GENKSYMS) $(if $(1), -T $(2)) -a $(ARCH)                              \
+    $(GENKSYMS) $(if $(1), -T $(2))                                         \
+     $(patsubst y,-s _,$(CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX))             \
      $(if $(KBUILD_PRESERVE),-p)                                            \
      -r $(firstword $(wildcard $(2:.symtypes=.symref) /dev/null))
 
diff --git a/scripts/Makefile.headersinst b/scripts/Makefile.headersinst
index 477d137..182084d 100644
--- a/scripts/Makefile.headersinst
+++ b/scripts/Makefile.headersinst
@@ -72,7 +72,7 @@ printdir = $(patsubst $(INSTALL_HDR_PATH)/%/,%,$(dir $@))
 quiet_cmd_install = INSTALL $(printdir) ($(words $(all-files))\
                             file$(if $(word 2, $(all-files)),s))
       cmd_install = \
-        $(PERL) $< $(installdir) $(SRCARCH) $(input-files); \
+        $(CONFIG_SHELL) $< $(installdir) $(input-files); \
         for F in $(wrapper-files); do                                   \
                 echo "\#include <asm-generic/$$F>" > $(installdir)/$$F;    \
         done;                                                           \
@@ -98,7 +98,7 @@ __headersinst: $(subdirs) $(install-file)
 	@:
 
 targets += $(install-file)
-$(install-file): scripts/headers_install.pl $(input-files) FORCE
+$(install-file): scripts/headers_install.sh $(input-files) FORCE
 	$(if $(unwanted),$(call cmd,remove),)
 	$(if $(wildcard $(dir $@)),,$(shell mkdir -p $(dir $@)))
 	$(call if_changed,install)
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 07125e6..09e9b4b 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -119,13 +119,6 @@ _c_flags += $(if $(patsubst n%,, \
 		$(CFLAGS_GCOV))
 endif
 
-ifdef CONFIG_SYMBOL_PREFIX
-_sym_flags = -DSYMBOL_PREFIX=$(patsubst "%",%,$(CONFIG_SYMBOL_PREFIX))
-_cpp_flags += $(_sym_flags)
-_a_flags += $(_sym_flags)
-endif
-
-
 # If building the kernel in a separate objtree expand all occurrences
 # of -Idir to -I$(srctree)/dir except for absolute paths (starting with '/').
 
@@ -321,6 +314,11 @@ cmd_lzo = (cat $(filter-out FORCE,$^) | \
 	lzop -9 && $(call size_append, $(filter-out FORCE,$^))) > $@ || \
 	(rm -f $@ ; false)
 
+quiet_cmd_lz4 = LZ4     $@
+cmd_lz4 = (cat $(filter-out FORCE,$^) | \
+	lz4demo -c1 stdin stdout && $(call size_append, $(filter-out FORCE,$^))) > $@ || \
+	(rm -f $@ ; false)
+
 # U-Boot mkimage
 # ---------------------------------------------------------------------------
 
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index b28cc38..3fb6d86 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -628,6 +628,13 @@ sub sanitise_line {
 	return $res;
 }
 
+sub get_quoted_string {
+	my ($line, $rawline) = @_;
+
+	return "" if ($line !~ m/(\"[X]+\")/g);
+	return substr($rawline, $-[0], $+[0] - $-[0]);
+}
+
 sub ctx_statement_block {
 	my ($linenr, $remain, $off) = @_;
 	my $line = $linenr - 1;
@@ -1576,7 +1583,8 @@ sub process {
 # Check for incorrect file permissions
 		if ($line =~ /^new (file )?mode.*[7531]\d{0,2}$/) {
 			my $permhere = $here . "FILE: $realfile\n";
-			if ($realfile =~ /(Makefile|Kconfig|\.c|\.h|\.S|\.tmpl)$/) {
+			if ($realfile !~ m@scripts/@ &&
+			    $realfile !~ /\.(py|pl|awk|sh)$/) {
 				ERROR("EXECUTE_PERMISSIONS",
 				      "do not set execute permissions for source files\n" . $permhere);
 			}
@@ -3372,6 +3380,15 @@ sub process {
 			     "struct spinlock should be spinlock_t\n" . $herecurr);
 		}
 
+# check for seq_printf uses that could be seq_puts
+		if ($line =~ /\bseq_printf\s*\(/) {
+			my $fmt = get_quoted_string($line, $rawline);
+			if ($fmt !~ /[^\\]\%/) {
+				WARN("PREFER_SEQ_PUTS",
+				     "Prefer seq_puts to seq_printf\n" . $herecurr);
+			}
+		}
+
 # Check for misused memsets
 		if ($^V && $^V ge 5.10.0 &&
 		    defined $stat &&
@@ -3476,6 +3493,13 @@ sub process {
 			     "unnecessary cast may hide bugs, see http://c-faq.com/malloc/mallocnocast.html\n" . $herecurr);
 		}
 
+# check for krealloc arg reuse
+		if ($^V && $^V ge 5.10.0 &&
+		    $line =~ /\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*krealloc\s*\(\s*\1\s*,/) {
+			WARN("KREALLOC_ARG_REUSE",
+			     "Reusing the krealloc arg is almost always a bug\n" . $herecurr);
+		}
+
 # check for alloc argument mismatch
 		if ($line =~ /\b(kcalloc|kmalloc_array)\s*\(\s*sizeof\b/) {
 			WARN("ALLOC_ARRAY_ARGS",
diff --git a/scripts/decodecode b/scripts/decodecode
index 4f8248d..d8824f3 100755
--- a/scripts/decodecode
+++ b/scripts/decodecode
@@ -89,10 +89,16 @@ echo $code >> $T.s
 disas $T
 cat $T.dis >> $T.aa
 
+# (lines of whole $T.oo) - (lines of $T.aa, i.e. "Code starting") + 3,
+# i.e. the title + the "===..=" line (sed is counting from 1, 0 address is
+# special)
+faultlinenum=$(( $(wc -l $T.oo  | cut -d" " -f1) - \
+		 $(wc -l $T.aa  | cut -d" " -f1) + 3))
+
 faultline=`cat $T.dis | head -1 | cut -d":" -f2-`
 faultline=`echo "$faultline" | sed -e 's/\[/\\\[/g; s/\]/\\\]/g'`
 
-cat $T.oo | sed -e "s/\($faultline\)/\*\1     <-- trapping instruction/g"
+cat $T.oo | sed -e "${faultlinenum}s/^\(.*:\)\(.*\)/\1\*\2\t\t<-- trapping instruction/"
 echo
 cat $T.aa
 cleanup
diff --git a/scripts/genksyms/genksyms.c b/scripts/genksyms/genksyms.c
index d25e4a1..88632df 100644
--- a/scripts/genksyms/genksyms.c
+++ b/scripts/genksyms/genksyms.c
@@ -45,7 +45,6 @@ int in_source_file;
 
 static int flag_debug, flag_dump_defs, flag_reference, flag_dump_types,
 	   flag_preserve, flag_warnings;
-static const char *arch = "";
 static const char *mod_prefix = "";
 
 static int errors;
@@ -731,7 +730,7 @@ static void genksyms_usage(void)
 {
 	fputs("Usage:\n" "genksyms [-adDTwqhV] > /path/to/.tmp_obj.ver\n" "\n"
 #ifdef __GNU_LIBRARY__
-	      "  -a, --arch            Select architecture\n"
+	      "  -s, --symbol-prefix   Select symbol prefix\n"
 	      "  -d, --debug           Increment the debug level (repeatable)\n"
 	      "  -D, --dump            Dump expanded symbol defs (for debugging only)\n"
 	      "  -r, --reference file  Read reference symbols from a file\n"
@@ -742,7 +741,7 @@ static void genksyms_usage(void)
 	      "  -h, --help            Print this message\n"
 	      "  -V, --version         Print the release version\n"
 #else				/* __GNU_LIBRARY__ */
-	      "  -a                    Select architecture\n"
+	      "  -s                    Select symbol prefix\n"
 	      "  -d                    Increment the debug level (repeatable)\n"
 	      "  -D                    Dump expanded symbol defs (for debugging only)\n"
 	      "  -r file               Read reference symbols from a file\n"
@@ -763,7 +762,7 @@ int main(int argc, char **argv)
 
 #ifdef __GNU_LIBRARY__
 	struct option long_opts[] = {
-		{"arch", 1, 0, 'a'},
+		{"symbol-prefix", 1, 0, 's'},
 		{"debug", 0, 0, 'd'},
 		{"warnings", 0, 0, 'w'},
 		{"quiet", 0, 0, 'q'},
@@ -776,14 +775,14 @@ int main(int argc, char **argv)
 		{0, 0, 0, 0}
 	};
 
-	while ((o = getopt_long(argc, argv, "a:dwqVDr:T:ph",
+	while ((o = getopt_long(argc, argv, "s:dwqVDr:T:ph",
 				&long_opts[0], NULL)) != EOF)
 #else				/* __GNU_LIBRARY__ */
-	while ((o = getopt(argc, argv, "a:dwqVDr:T:ph")) != EOF)
+	while ((o = getopt(argc, argv, "s:dwqVDr:T:ph")) != EOF)
 #endif				/* __GNU_LIBRARY__ */
 		switch (o) {
-		case 'a':
-			arch = optarg;
+		case 's':
+			mod_prefix = optarg;
 			break;
 		case 'd':
 			flag_debug++;
@@ -826,9 +825,6 @@ int main(int argc, char **argv)
 			genksyms_usage();
 			return 1;
 		}
-	if ((strcmp(arch, "h8300") == 0) || (strcmp(arch, "blackfin") == 0) ||
-	    (strcmp(arch, "metag") == 0))
-		mod_prefix = "_";
 	{
 		extern int yydebug;
 		extern int yy_flex_debug;
diff --git a/scripts/get_maintainer.pl b/scripts/get_maintainer.pl
index ce4cc83..5e4fb14 100755
--- a/scripts/get_maintainer.pl
+++ b/scripts/get_maintainer.pl
@@ -611,7 +611,7 @@ sub get_maintainers {
 				    $hash{$tvi} = $value_pd;
 				}
 			    }
-			} elsif ($type eq 'K') {
+			} elsif ($type eq 'N') {
 			    if ($file =~ m/$value/x) {
 				$hash{$tvi} = 0;
 			    }
diff --git a/scripts/headers_install.pl b/scripts/headers_install.pl
deleted file mode 100644
index 581ca99..0000000
--- a/scripts/headers_install.pl
+++ /dev/null
@@ -1,63 +0,0 @@
-#!/usr/bin/perl -w
-#
-# headers_install prepare the listed header files for use in
-# user space and copy the files to their destination.
-#
-# Usage: headers_install.pl readdir installdir arch [files...]
-# installdir: dir to install the files to
-# arch:       current architecture
-#             arch is used to force a reinstallation when the arch
-#             changes because kbuild then detect a command line change.
-# files:      list of files to check
-#
-# Step in preparation for users space:
-# 1) Drop all use of compiler.h definitions
-# 2) Drop include of compiler.h
-# 3) Drop all sections defined out by __KERNEL__ (using unifdef)
-
-use strict;
-
-my ($installdir, $arch, @files) = @ARGV;
-
-my $unifdef = "scripts/unifdef -U__KERNEL__ -D__EXPORTED_HEADERS__";
-
-foreach my $filename (@files) {
-	my $file = $filename;
-	$file =~ s!^.*/!!;
-
-	my $tmpfile = "$installdir/$file.tmp";
-
-	open(my $in, '<', $filename)
-	    or die "$filename: $!\n";
-	open(my $out, '>', $tmpfile)
-	    or die "$tmpfile: $!\n";
-	while (my $line = <$in>) {
-		$line =~ s/([\s(])__user\s/$1/g;
-		$line =~ s/([\s(])__force\s/$1/g;
-		$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;
-		$line =~ s/(^|\s|[(])(volatile)\b(\s|[(]|$)/$1__$2__$3/g;
-		$line =~ s/#ifndef\s+_UAPI/#ifndef /;
-		$line =~ s/#define\s+_UAPI/#define /;
-		$line =~ s!#endif\s+/[*]\s*_UAPI!#endif /* !;
-		printf {$out} "%s", $line;
-	}
-	close $out;
-	close $in;
-
-	system $unifdef . " $tmpfile > $installdir/$file";
-	# unifdef will exit 0 on success, and will exit 1 when the
-	# file was processed successfully but no changes were made,
-	# so abort only when it's higher than that.
-	my $e = $? >> 8;
-	if ($e > 1) {
-		die "$tmpfile: $!\n";
-	}
-	unlink $tmpfile;
-}
-exit 0;
diff --git a/scripts/headers_install.sh b/scripts/headers_install.sh
new file mode 100644
index 0000000..643764f
--- /dev/null
+++ b/scripts/headers_install.sh
@@ -0,0 +1,43 @@
+#!/bin/sh
+
+if [ $# -lt 1 ]
+then
+	echo "Usage: headers_install.sh OUTDIR [FILES...]
+	echo
+	echo "Prepares kernel header files for use by user space, by removing"
+	echo "all compiler.h definitions and #includes, removing any"
+	echo "#ifdef __KERNEL__ sections, and putting __underscores__ around"
+	echo "asm/inline/volatile keywords."
+	echo
+	echo "OUTDIR: directory to write each userspace header FILE to."
+	echo "FILES:  list of header files to operate on."
+
+	exit 1
+fi
+
+# Grab arguments
+
+OUTDIR="$1"
+shift
+
+# Iterate through files listed on command line
+
+FILE=
+trap 'rm -f "$OUTDIR/$FILE" "$OUTDIR/$FILE.sed"' EXIT
+for i in "$@"
+do
+	FILE="$(basename "$i")"
+	sed -r \
+		-e 's/([ \t(])(__user|__force|__iomem)[ \t]/\1/g' \
+		-e 's/__attribute_const__([ \t]|$)/\1/g' \
+		-e 's@^#include <linux/compiler.h>@@' \
+		-e 's/(^|[^a-zA-Z0-9])__packed([^a-zA-Z0-9_]|$)/\1__attribute__((packed))\2/g' \
+		-e 's/(^|[ \t(])(inline|asm|volatile)([ \t(]|$)/\1__\2__\3/g' \
+		-e 's@#(ifndef|define|endif[ \t]*/[*])[ \t]*_UAPI@#\1 @' \
+		"$i" > "$OUTDIR/$FILE.sed" || exit 1
+	scripts/unifdef -U__KERNEL__ -D__EXPORTED_HEADERS__ "$OUTDIR/$FILE.sed" \
+		> "$OUTDIR/$FILE"
+	[ $? -gt 1 ] && exit 1
+	rm -f "$OUTDIR/$FILE.sed"
+done
+trap - EXIT
diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile
index 231b475..844bc9d 100644
--- a/scripts/kconfig/Makefile
+++ b/scripts/kconfig/Makefile
@@ -219,7 +219,9 @@ HOSTCFLAGS_gconf.o	= `pkg-config --cflags gtk+-2.0 gmodule-2.0 libglade-2.0` \
 
 HOSTLOADLIBES_mconf   = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ldflags $(HOSTCC))
 
-HOSTLOADLIBES_nconf	= -lmenu -lpanel -lncurses
+HOSTLOADLIBES_nconf	= $(shell \
+				pkg-config --libs menu panel ncurses 2>/dev/null \
+				|| echo "-lmenu -lpanel -lncurses"  )
 $(obj)/qconf.o: $(obj)/.tmp_qtcheck
 
 ifeq ($(qconf-target),1)
diff --git a/scripts/kconfig/lxdialog/check-lxdialog.sh b/scripts/kconfig/lxdialog/check-lxdialog.sh
index 8078813..782d200 100644
--- a/scripts/kconfig/lxdialog/check-lxdialog.sh
+++ b/scripts/kconfig/lxdialog/check-lxdialog.sh
@@ -4,6 +4,8 @@
 # What library to link
 ldflags()
 {
+	pkg-config --libs ncursesw 2>/dev/null && exit
+	pkg-config --libs ncurses 2>/dev/null && exit
 	for ext in so a dll.a dylib ; do
 		for lib in ncursesw ncurses curses ; do
 			$cc -print-file-name=lib${lib}.${ext} | grep -q /
diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
index 3d569d6..0149949 100644
--- a/scripts/link-vmlinux.sh
+++ b/scripts/link-vmlinux.sh
@@ -74,9 +74,8 @@ kallsyms()
 	info KSYM ${2}
 	local kallsymopt;
 
-	if [ -n "${CONFIG_SYMBOL_PREFIX}" ]; then
-		kallsymopt="${kallsymopt} \
-			    --symbol-prefix=${CONFIG_SYMBOL_PREFIX}"
+	if [ -n "${CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX}" ]; then
+		kallsymopt="${kallsymopt} --symbol-prefix=_"
 	fi
 
 	if [ -n "${CONFIG_KALLSYMS_ALL}" ]; then
diff --git a/scripts/mod/devicetable-offsets.c b/scripts/mod/devicetable-offsets.c
index b45260b..e66d4d2 100644
--- a/scripts/mod/devicetable-offsets.c
+++ b/scripts/mod/devicetable-offsets.c
@@ -174,5 +174,8 @@ int main(void)
 	DEVID_FIELD(x86_cpu_id, model);
 	DEVID_FIELD(x86_cpu_id, vendor);
 
+	DEVID(mei_cl_device_id);
+	DEVID_FIELD(mei_cl_device_id, name);
+
 	return 0;
 }
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index 771ac17..45f9a33 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -1133,6 +1133,18 @@ static int do_x86cpu_entry(const char *filename, void *symval,
 }
 ADD_TO_DEVTABLE("x86cpu", x86_cpu_id, do_x86cpu_entry);
 
+/* Looks like: mei:S */
+static int do_mei_entry(const char *filename, void *symval,
+			char *alias)
+{
+	DEF_FIELD_ADDR(symval, mei_cl_device_id, name);
+
+	sprintf(alias, MEI_CL_MODULE_PREFIX "%s", *name);
+
+	return 1;
+}
+ADD_TO_DEVTABLE("mei", mei_cl_device_id, do_mei_entry);
+
 /* Does namelen bytes of name exactly match the symbol? */
 static bool sym_is(const char *name, unsigned namelen, const char *symbol)
 {
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 78b30c1..f6913db 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -18,14 +18,7 @@
 #include "modpost.h"
 #include "../../include/generated/autoconf.h"
 #include "../../include/linux/license.h"
-
-/* Some toolchains use a `_' prefix for all user symbols. */
-#ifdef CONFIG_SYMBOL_PREFIX
-#define MODULE_SYMBOL_PREFIX CONFIG_SYMBOL_PREFIX
-#else
-#define MODULE_SYMBOL_PREFIX ""
-#endif
-
+#include "../../include/linux/export.h"
 
 /* Are we using CONFIG_MODVERSIONS? */
 int modversions = 0;
@@ -562,7 +555,7 @@ static void parse_elf_finish(struct elf_info *info)
 static int ignore_undef_symbol(struct elf_info *info, const char *symname)
 {
 	/* ignore __this_module, it will be resolved shortly */
-	if (strcmp(symname, MODULE_SYMBOL_PREFIX "__this_module") == 0)
+	if (strcmp(symname, VMLINUX_SYMBOL_STR(__this_module)) == 0)
 		return 1;
 	/* ignore global offset table */
 	if (strcmp(symname, "_GLOBAL_OFFSET_TABLE_") == 0)
@@ -583,8 +576,8 @@ static int ignore_undef_symbol(struct elf_info *info, const char *symname)
 	return 0;
 }
 
-#define CRC_PFX     MODULE_SYMBOL_PREFIX "__crc_"
-#define KSYMTAB_PFX MODULE_SYMBOL_PREFIX "__ksymtab_"
+#define CRC_PFX     VMLINUX_SYMBOL_STR(__crc_)
+#define KSYMTAB_PFX VMLINUX_SYMBOL_STR(__ksymtab_)
 
 static void handle_modversions(struct module *mod, struct elf_info *info,
 			       Elf_Sym *sym, const char *symname)
@@ -637,14 +630,15 @@ static void handle_modversions(struct module *mod, struct elf_info *info,
 		}
 #endif
 
-		if (memcmp(symname, MODULE_SYMBOL_PREFIX,
-			   strlen(MODULE_SYMBOL_PREFIX)) == 0) {
-			mod->unres =
-			  alloc_symbol(symname +
-			               strlen(MODULE_SYMBOL_PREFIX),
-			               ELF_ST_BIND(sym->st_info) == STB_WEAK,
-			               mod->unres);
-		}
+#ifdef CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX
+		if (symname[0] != '_')
+			break;
+		else
+			symname++;
+#endif
+		mod->unres = alloc_symbol(symname,
+					  ELF_ST_BIND(sym->st_info) == STB_WEAK,
+					  mod->unres);
 		break;
 	default:
 		/* All exported symbols */
@@ -652,9 +646,9 @@ static void handle_modversions(struct module *mod, struct elf_info *info,
 			sym_add_exported(symname + strlen(KSYMTAB_PFX), mod,
 					export);
 		}
-		if (strcmp(symname, MODULE_SYMBOL_PREFIX "init_module") == 0)
+		if (strcmp(symname, VMLINUX_SYMBOL_STR(init_module)) == 0)
 			mod->has_init = 1;
-		if (strcmp(symname, MODULE_SYMBOL_PREFIX "cleanup_module") == 0)
+		if (strcmp(symname, VMLINUX_SYMBOL_STR(cleanup_module)) == 0)
 			mod->has_cleanup = 1;
 		break;
 	}
@@ -1934,7 +1928,8 @@ static int add_versions(struct buffer *b, struct module *mod)
 				s->name, mod->name);
 			continue;
 		}
-		buf_printf(b, "\t{ %#8x, \"%s\" },\n", s->crc, s->name);
+		buf_printf(b, "\t{ %#8x, VMLINUX_SYMBOL_STR(%s) },\n",
+			   s->crc, s->name);
 	}
 
 	buf_printf(b, "};\n");
diff --git a/scripts/tags.sh b/scripts/tags.sh
index 26a87e6..74f02e4 100755
--- a/scripts/tags.sh
+++ b/scripts/tags.sh
@@ -199,7 +199,9 @@ exuberant()
 	--regex-c='/DEFINE_PER_CPU_SHARED_ALIGNED\(([^,]*,\s*)(\w*).*\)/\2/v/' \
 	--regex-c='/DECLARE_WAIT_QUEUE_HEAD\((\w*)/\1/v/'		\
 	--regex-c='/DECLARE_(TASKLET|WORK|DELAYED_WORK)\((\w*)/\2/v/'	\
-	--regex-c='/DEFINE_PCI_DEVICE_TABLE\((\w*)/\1/v/'
+	--regex-c='/DEFINE_PCI_DEVICE_TABLE\((\w*)/\1/v/'		\
+	--regex-c='/(^\s)OFFSET\((\w*)/\2/v/'				\
+	--regex-c='/(^\s)DEFINE\((\w*)/\2/v/'
 
 	all_kconfigs | xargs $1 -a                              \
 	--langdef=kconfig --language-force=kconfig              \
diff --git a/security/capability.c b/security/capability.c
index 5797750..a6290b6 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -98,9 +98,10 @@ static int cap_sb_set_mnt_opts(struct super_block *sb,
 	return 0;
 }
 
-static void cap_sb_clone_mnt_opts(const struct super_block *oldsb,
+static int cap_sb_clone_mnt_opts(const struct super_block *oldsb,
 				  struct super_block *newsb)
 {
+	return 0;
 }
 
 static int cap_sb_parse_opts_str(char *options, struct security_mnt_opts *opts)
diff --git a/security/device_cgroup.c b/security/device_cgroup.c
index 1c69e38..221967d 100644
--- a/security/device_cgroup.c
+++ b/security/device_cgroup.c
@@ -25,6 +25,12 @@
 
 static DEFINE_MUTEX(devcgroup_mutex);
 
+enum devcg_behavior {
+	DEVCG_DEFAULT_NONE,
+	DEVCG_DEFAULT_ALLOW,
+	DEVCG_DEFAULT_DENY,
+};
+
 /*
  * exception list locking rules:
  * hold devcgroup_mutex for update/read.
@@ -42,10 +48,9 @@ struct dev_exception_item {
 struct dev_cgroup {
 	struct cgroup_subsys_state css;
 	struct list_head exceptions;
-	enum {
-		DEVCG_DEFAULT_ALLOW,
-		DEVCG_DEFAULT_DENY,
-	} behavior;
+	enum devcg_behavior behavior;
+	/* temporary list for pending propagation operations */
+	struct list_head propagate_pending;
 };
 
 static inline struct dev_cgroup *css_to_devcgroup(struct cgroup_subsys_state *s)
@@ -182,36 +187,65 @@ static void dev_exception_clean(struct dev_cgroup *dev_cgroup)
 	__dev_exception_clean(dev_cgroup);
 }
 
+static inline bool is_devcg_online(const struct dev_cgroup *devcg)
+{
+	return (devcg->behavior != DEVCG_DEFAULT_NONE);
+}
+
+/**
+ * devcgroup_online - initializes devcgroup's behavior and exceptions based on
+ * 		      parent's
+ * @cgroup: cgroup getting online
+ * returns 0 in case of success, error code otherwise
+ */
+static int devcgroup_online(struct cgroup *cgroup)
+{
+	struct dev_cgroup *dev_cgroup, *parent_dev_cgroup = NULL;
+	int ret = 0;
+
+	mutex_lock(&devcgroup_mutex);
+	dev_cgroup = cgroup_to_devcgroup(cgroup);
+	if (cgroup->parent)
+		parent_dev_cgroup = cgroup_to_devcgroup(cgroup->parent);
+
+	if (parent_dev_cgroup == NULL)
+		dev_cgroup->behavior = DEVCG_DEFAULT_ALLOW;
+	else {
+		ret = dev_exceptions_copy(&dev_cgroup->exceptions,
+					  &parent_dev_cgroup->exceptions);
+		if (!ret)
+			dev_cgroup->behavior = parent_dev_cgroup->behavior;
+	}
+	mutex_unlock(&devcgroup_mutex);
+
+	return ret;
+}
+
+static void devcgroup_offline(struct cgroup *cgroup)
+{
+	struct dev_cgroup *dev_cgroup = cgroup_to_devcgroup(cgroup);
+
+	mutex_lock(&devcgroup_mutex);
+	dev_cgroup->behavior = DEVCG_DEFAULT_NONE;
+	mutex_unlock(&devcgroup_mutex);
+}
+
 /*
  * called from kernel/cgroup.c with cgroup_lock() held.
  */
 static struct cgroup_subsys_state *devcgroup_css_alloc(struct cgroup *cgroup)
 {
-	struct dev_cgroup *dev_cgroup, *parent_dev_cgroup;
+	struct dev_cgroup *dev_cgroup;
 	struct cgroup *parent_cgroup;
-	int ret;
 
 	dev_cgroup = kzalloc(sizeof(*dev_cgroup), GFP_KERNEL);
 	if (!dev_cgroup)
 		return ERR_PTR(-ENOMEM);
 	INIT_LIST_HEAD(&dev_cgroup->exceptions);
+	INIT_LIST_HEAD(&dev_cgroup->propagate_pending);
+	dev_cgroup->behavior = DEVCG_DEFAULT_NONE;
 	parent_cgroup = cgroup->parent;
 
-	if (parent_cgroup == NULL)
-		dev_cgroup->behavior = DEVCG_DEFAULT_ALLOW;
-	else {
-		parent_dev_cgroup = cgroup_to_devcgroup(parent_cgroup);
-		mutex_lock(&devcgroup_mutex);
-		ret = dev_exceptions_copy(&dev_cgroup->exceptions,
-					  &parent_dev_cgroup->exceptions);
-		dev_cgroup->behavior = parent_dev_cgroup->behavior;
-		mutex_unlock(&devcgroup_mutex);
-		if (ret) {
-			kfree(dev_cgroup);
-			return ERR_PTR(ret);
-		}
-	}
-
 	return &dev_cgroup->css;
 }
 
@@ -304,9 +338,11 @@ static int devcgroup_seq_read(struct cgroup *cgroup, struct cftype *cft,
  *		verify if a certain access is allowed.
  * @dev_cgroup: dev cgroup to be tested against
  * @refex: new exception
+ * @behavior: behavior of the exception
  */
-static int may_access(struct dev_cgroup *dev_cgroup,
-		      struct dev_exception_item *refex)
+static bool may_access(struct dev_cgroup *dev_cgroup,
+		       struct dev_exception_item *refex,
+		       enum devcg_behavior behavior)
 {
 	struct dev_exception_item *ex;
 	bool match = false;
@@ -330,18 +366,29 @@ static int may_access(struct dev_cgroup *dev_cgroup,
 		break;
 	}
 
-	/*
-	 * In two cases we'll consider this new exception valid:
-	 * - the dev cgroup has its default policy to allow + exception list:
-	 *   the new exception should *not* match any of the exceptions
-	 *   (behavior == DEVCG_DEFAULT_ALLOW, !match)
-	 * - the dev cgroup has its default policy to deny + exception list:
-	 *   the new exception *should* match the exceptions
-	 *   (behavior == DEVCG_DEFAULT_DENY, match)
-	 */
-	if ((dev_cgroup->behavior == DEVCG_DEFAULT_DENY) == match)
-		return 1;
-	return 0;
+	if (dev_cgroup->behavior == DEVCG_DEFAULT_ALLOW) {
+		if (behavior == DEVCG_DEFAULT_ALLOW) {
+			/* the exception will deny access to certain devices */
+			return true;
+		} else {
+			/* the exception will allow access to certain devices */
+			if (match)
+				/*
+				 * a new exception allowing access shouldn't
+				 * match an parent's exception
+				 */
+				return false;
+			return true;
+		}
+	} else {
+		/* only behavior == DEVCG_DEFAULT_DENY allowed here */
+		if (match)
+			/* parent has an exception that matches the proposed */
+			return true;
+		else
+			return false;
+	}
+	return false;
 }
 
 /*
@@ -358,7 +405,7 @@ static int parent_has_perm(struct dev_cgroup *childcg,
 	if (!pcg)
 		return 1;
 	parent = cgroup_to_devcgroup(pcg);
-	return may_access(parent, ex);
+	return may_access(parent, ex, childcg->behavior);
 }
 
 /**
@@ -374,6 +421,111 @@ static inline int may_allow_all(struct dev_cgroup *parent)
 	return parent->behavior == DEVCG_DEFAULT_ALLOW;
 }
 
+/**
+ * revalidate_active_exceptions - walks through the active exception list and
+ * 				  revalidates the exceptions based on parent's
+ * 				  behavior and exceptions. The exceptions that
+ * 				  are no longer valid will be removed.
+ * 				  Called with devcgroup_mutex held.
+ * @devcg: cgroup which exceptions will be checked
+ *
+ * This is one of the three key functions for hierarchy implementation.
+ * This function is responsible for re-evaluating all the cgroup's active
+ * exceptions due to a parent's exception change.
+ * Refer to Documentation/cgroups/devices.txt for more details.
+ */
+static void revalidate_active_exceptions(struct dev_cgroup *devcg)
+{
+	struct dev_exception_item *ex;
+	struct list_head *this, *tmp;
+
+	list_for_each_safe(this, tmp, &devcg->exceptions) {
+		ex = container_of(this, struct dev_exception_item, list);
+		if (!parent_has_perm(devcg, ex))
+			dev_exception_rm(devcg, ex);
+	}
+}
+
+/**
+ * get_online_devcg - walks the cgroup tree and fills a list with the online
+ * 		      groups
+ * @root: cgroup used as starting point
+ * @online: list that will be filled with online groups
+ *
+ * Must be called with devcgroup_mutex held. Grabs RCU lock.
+ * Because devcgroup_mutex is held, no devcg will become online or offline
+ * during the tree walk (see devcgroup_online, devcgroup_offline)
+ * A separated list is needed because propagate_behavior() and
+ * propagate_exception() need to allocate memory and can block.
+ */
+static void get_online_devcg(struct cgroup *root, struct list_head *online)
+{
+	struct cgroup *pos;
+	struct dev_cgroup *devcg;
+
+	lockdep_assert_held(&devcgroup_mutex);
+
+	rcu_read_lock();
+	cgroup_for_each_descendant_pre(pos, root) {
+		devcg = cgroup_to_devcgroup(pos);
+		if (is_devcg_online(devcg))
+			list_add_tail(&devcg->propagate_pending, online);
+	}
+	rcu_read_unlock();
+}
+
+/**
+ * propagate_exception - propagates a new exception to the children
+ * @devcg_root: device cgroup that added a new exception
+ * @ex: new exception to be propagated
+ *
+ * returns: 0 in case of success, != 0 in case of error
+ */
+static int propagate_exception(struct dev_cgroup *devcg_root,
+			       struct dev_exception_item *ex)
+{
+	struct cgroup *root = devcg_root->css.cgroup;
+	struct dev_cgroup *devcg, *parent, *tmp;
+	int rc = 0;
+	LIST_HEAD(pending);
+
+	get_online_devcg(root, &pending);
+
+	list_for_each_entry_safe(devcg, tmp, &pending, propagate_pending) {
+		parent = cgroup_to_devcgroup(devcg->css.cgroup->parent);
+
+		/*
+		 * in case both root's behavior and devcg is allow, a new
+		 * restriction means adding to the exception list
+		 */
+		if (devcg_root->behavior == DEVCG_DEFAULT_ALLOW &&
+		    devcg->behavior == DEVCG_DEFAULT_ALLOW) {
+			rc = dev_exception_add(devcg, ex);
+			if (rc)
+				break;
+		} else {
+			/*
+			 * in the other possible cases:
+			 * root's behavior: allow, devcg's: deny
+			 * root's behavior: deny, devcg's: deny
+			 * the exception will be removed
+			 */
+			dev_exception_rm(devcg, ex);
+		}
+		revalidate_active_exceptions(devcg);
+
+		list_del_init(&devcg->propagate_pending);
+	}
+	return rc;
+}
+
+static inline bool has_children(struct dev_cgroup *devcgroup)
+{
+	struct cgroup *cgrp = devcgroup->css.cgroup;
+
+	return !list_empty(&cgrp->children);
+}
+
 /*
  * Modify the exception list using allow/deny rules.
  * CAP_SYS_ADMIN is needed for this.  It's at least separate from CAP_MKNOD
@@ -392,7 +544,7 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,
 {
 	const char *b;
 	char temp[12];		/* 11 + 1 characters needed for a u32 */
-	int count, rc;
+	int count, rc = 0;
 	struct dev_exception_item ex;
 	struct cgroup *p = devcgroup->css.cgroup;
 	struct dev_cgroup *parent = NULL;
@@ -410,6 +562,9 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,
 	case 'a':
 		switch (filetype) {
 		case DEVCG_ALLOW:
+			if (has_children(devcgroup))
+				return -EINVAL;
+
 			if (!may_allow_all(parent))
 				return -EPERM;
 			dev_exception_clean(devcgroup);
@@ -423,6 +578,9 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,
 				return rc;
 			break;
 		case DEVCG_DENY:
+			if (has_children(devcgroup))
+				return -EINVAL;
+
 			dev_exception_clean(devcgroup);
 			devcgroup->behavior = DEVCG_DEFAULT_DENY;
 			break;
@@ -517,22 +675,28 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,
 			dev_exception_rm(devcgroup, &ex);
 			return 0;
 		}
-		return dev_exception_add(devcgroup, &ex);
+		rc = dev_exception_add(devcgroup, &ex);
+		break;
 	case DEVCG_DENY:
 		/*
 		 * If the default policy is to deny by default, try to remove
 		 * an matching exception instead. And be silent about it: we
 		 * don't want to break compatibility
 		 */
-		if (devcgroup->behavior == DEVCG_DEFAULT_DENY) {
+		if (devcgroup->behavior == DEVCG_DEFAULT_DENY)
 			dev_exception_rm(devcgroup, &ex);
-			return 0;
-		}
-		return dev_exception_add(devcgroup, &ex);
+		else
+			rc = dev_exception_add(devcgroup, &ex);
+
+		if (rc)
+			break;
+		/* we only propagate new restrictions */
+		rc = propagate_exception(devcgroup, &ex);
+		break;
 	default:
-		return -EINVAL;
+		rc = -EINVAL;
 	}
-	return 0;
+	return rc;
 }
 
 static int devcgroup_access_write(struct cgroup *cgrp, struct cftype *cft,
@@ -571,6 +735,8 @@ struct cgroup_subsys devices_subsys = {
 	.can_attach = devcgroup_can_attach,
 	.css_alloc = devcgroup_css_alloc,
 	.css_free = devcgroup_css_free,
+	.css_online = devcgroup_online,
+	.css_offline = devcgroup_offline,
 	.subsys_id = devices_subsys_id,
 	.base_cftypes = dev_cgroup_files,
 
@@ -609,7 +775,7 @@ static int __devcgroup_check_permission(short type, u32 major, u32 minor,
 
 	rcu_read_lock();
 	dev_cgroup = task_devcgroup(current);
-	rc = may_access(dev_cgroup, &ex);
+	rc = may_access(dev_cgroup, &ex, dev_cgroup->behavior);
 	rcu_read_unlock();
 
 	if (!rc)
diff --git a/security/keys/internal.h b/security/keys/internal.h
index 8bbefc3..d4f1468 100644
--- a/security/keys/internal.h
+++ b/security/keys/internal.h
@@ -16,6 +16,8 @@
 #include <linux/key-type.h>
 #include <linux/task_work.h>
 
+struct iovec;
+
 #ifdef __KDEBUG
 #define kenter(FMT, ...) \
 	printk(KERN_DEBUG "==> %s("FMT")\n", __func__, ##__VA_ARGS__)
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index 4b5c948..33cfd27 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -22,6 +22,7 @@
 #include <linux/err.h>
 #include <linux/vmalloc.h>
 #include <linux/security.h>
+#include <linux/uio.h>
 #include <asm/uaccess.h>
 #include "internal.h"
 
diff --git a/security/keys/request_key.c b/security/keys/request_key.c
index 4bd6bdb..c411f9b 100644
--- a/security/keys/request_key.c
+++ b/security/keys/request_key.c
@@ -93,9 +93,16 @@ static void umh_keys_cleanup(struct subprocess_info *info)
 static int call_usermodehelper_keys(char *path, char **argv, char **envp,
 					struct key *session_keyring, int wait)
 {
-	return call_usermodehelper_fns(path, argv, envp, wait,
-				       umh_keys_init, umh_keys_cleanup,
-				       key_get(session_keyring));
+	struct subprocess_info *info;
+
+	info = call_usermodehelper_setup(path, argv, envp, GFP_KERNEL,
+					  umh_keys_init, umh_keys_cleanup,
+					  session_keyring);
+	if (!info)
+		return -ENOMEM;
+
+	key_get(session_keyring);
+	return call_usermodehelper_exec(info, wait);
 }
 
 /*
diff --git a/security/security.c b/security/security.c
index 7b88c6a..108281d 100644
--- a/security/security.c
+++ b/security/security.c
@@ -299,10 +299,10 @@ int security_sb_set_mnt_opts(struct super_block *sb,
 }
 EXPORT_SYMBOL(security_sb_set_mnt_opts);
 
-void security_sb_clone_mnt_opts(const struct super_block *oldsb,
+int security_sb_clone_mnt_opts(const struct super_block *oldsb,
 				struct super_block *newsb)
 {
-	security_ops->sb_clone_mnt_opts(oldsb, newsb);
+	return security_ops->sb_clone_mnt_opts(oldsb, newsb);
 }
 EXPORT_SYMBOL(security_sb_clone_mnt_opts);
 
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 2fa28c8..9c1c184 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -60,7 +60,7 @@
 #include <linux/bitops.h>
 #include <linux/interrupt.h>
 #include <linux/netdevice.h>	/* for network interface checks */
-#include <linux/netlink.h>
+#include <net/netlink.h>
 #include <linux/tcp.h>
 #include <linux/udp.h>
 #include <linux/dccp.h>
@@ -750,7 +750,37 @@ out_double_mount:
 	goto out;
 }
 
-static void selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
+static int selinux_cmp_sb_context(const struct super_block *oldsb,
+				    const struct super_block *newsb)
+{
+	struct superblock_security_struct *old = oldsb->s_security;
+	struct superblock_security_struct *new = newsb->s_security;
+	char oldflags = old->flags & SE_MNTMASK;
+	char newflags = new->flags & SE_MNTMASK;
+
+	if (oldflags != newflags)
+		goto mismatch;
+	if ((oldflags & FSCONTEXT_MNT) && old->sid != new->sid)
+		goto mismatch;
+	if ((oldflags & CONTEXT_MNT) && old->mntpoint_sid != new->mntpoint_sid)
+		goto mismatch;
+	if ((oldflags & DEFCONTEXT_MNT) && old->def_sid != new->def_sid)
+		goto mismatch;
+	if (oldflags & ROOTCONTEXT_MNT) {
+		struct inode_security_struct *oldroot = oldsb->s_root->d_inode->i_security;
+		struct inode_security_struct *newroot = newsb->s_root->d_inode->i_security;
+		if (oldroot->sid != newroot->sid)
+			goto mismatch;
+	}
+	return 0;
+mismatch:
+	printk(KERN_WARNING "SELinux: mount invalid.  Same superblock, "
+			    "different security settings for (dev %s, "
+			    "type %s)\n", newsb->s_id, newsb->s_type->name);
+	return -EBUSY;
+}
+
+static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
 					struct super_block *newsb)
 {
 	const struct superblock_security_struct *oldsbsec = oldsb->s_security;
@@ -765,14 +795,14 @@ static void selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
 	 * mount options.  thus we can safely deal with this superblock later
 	 */
 	if (!ss_initialized)
-		return;
+		return 0;
 
 	/* how can we clone if the old one wasn't set up?? */
 	BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED));
 
-	/* if fs is reusing a sb, just let its options stand... */
+	/* if fs is reusing a sb, make sure that the contexts match */
 	if (newsbsec->flags & SE_SBINITIALIZED)
-		return;
+		return selinux_cmp_sb_context(oldsb, newsb);
 
 	mutex_lock(&newsbsec->lock);
 
@@ -805,6 +835,7 @@ static void selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
 
 	sb_finish_set_opts(newsb);
 	mutex_unlock(&newsbsec->lock);
+	return 0;
 }
 
 static int selinux_parse_opts_str(char *options,
@@ -4475,7 +4506,7 @@ static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
 	struct nlmsghdr *nlh;
 	struct sk_security_struct *sksec = sk->sk_security;
 
-	if (skb->len < NLMSG_SPACE(0)) {
+	if (skb->len < NLMSG_HDRLEN) {
 		err = -EINVAL;
 		goto out;
 	}
diff --git a/security/selinux/netlink.c b/security/selinux/netlink.c
index 14d810e..828fb6a 100644
--- a/security/selinux/netlink.c
+++ b/security/selinux/netlink.c
@@ -16,7 +16,6 @@
 #include <linux/kernel.h>
 #include <linux/export.h>
 #include <linux/skbuff.h>
-#include <linux/netlink.h>
 #include <linux/selinux_netlink.h>
 #include <net/net_namespace.h>
 #include <net/netlink.h>
@@ -77,7 +76,7 @@ static void selnl_notify(int msgtype, void *data)
 
 	len = selnl_msglen(msgtype);
 
-	skb = alloc_skb(NLMSG_SPACE(len), GFP_USER);
+	skb = nlmsg_new(len, GFP_USER);
 	if (!skb)
 		goto oom;
 
diff --git a/security/smack/smack.h b/security/smack/smack.h
index 99b3612..8ad3095 100644
--- a/security/smack/smack.h
+++ b/security/smack/smack.h
@@ -149,11 +149,6 @@ struct smack_known {
 #define SMACK_CIPSO_SOCKET	1
 
 /*
- * smackfs magic number
- */
-#define SMACK_MAGIC	0x43415d53 /* "SMAC" */
-
-/*
  * CIPSO defaults.
  */
 #define SMACK_CIPSO_DOI_DEFAULT		3	/* Historical */
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c
index db14689..2e397a8 100644
--- a/security/smack/smack_access.c
+++ b/security/smack/smack_access.c
@@ -252,6 +252,8 @@ static inline void smack_str_from_perm(char *string, int access)
 		string[i++] = 'x';
 	if (access & MAY_APPEND)
 		string[i++] = 'a';
+	if (access & MAY_TRANSMUTE)
+		string[i++] = 't';
 	string[i] = '\0';
 }
 /**
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index fa64740..d52c780 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -654,7 +654,7 @@ static int smack_inode_unlink(struct inode *dir, struct dentry *dentry)
 		/*
 		 * You also need write access to the containing directory
 		 */
-		smk_ad_setfield_u_fs_path_dentry(&ad, NULL);
+		smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_INODE);
 		smk_ad_setfield_u_fs_inode(&ad, dir);
 		rc = smk_curacc(smk_of_inode(dir), MAY_WRITE, &ad);
 	}
@@ -685,7 +685,7 @@ static int smack_inode_rmdir(struct inode *dir, struct dentry *dentry)
 		/*
 		 * You also need write access to the containing directory
 		 */
-		smk_ad_setfield_u_fs_path_dentry(&ad, NULL);
+		smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_INODE);
 		smk_ad_setfield_u_fs_inode(&ad, dir);
 		rc = smk_curacc(smk_of_inode(dir), MAY_WRITE, &ad);
 	}
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
index 76a5dca..53a08b8 100644
--- a/security/smack/smackfs.c
+++ b/security/smack/smackfs.c
@@ -26,6 +26,7 @@
 #include <linux/seq_file.h>
 #include <linux/ctype.h>
 #include <linux/audit.h>
+#include <linux/magic.h>
 #include "smack.h"
 
 /*
@@ -50,12 +51,12 @@ enum smk_inos {
 	SMK_ACCESS2	= 16,	/* make an access check with long labels */
 	SMK_CIPSO2	= 17,	/* load long label -> CIPSO mapping */
 	SMK_REVOKE_SUBJ	= 18,	/* set rules with subject label to '-' */
+	SMK_CHANGE_RULE	= 19,	/* change or add rules (long labels) */
 };
 
 /*
  * List locks
  */
-static DEFINE_MUTEX(smack_list_lock);
 static DEFINE_MUTEX(smack_cipso_lock);
 static DEFINE_MUTEX(smack_ambient_lock);
 static DEFINE_MUTEX(smk_netlbladdr_lock);
@@ -110,6 +111,13 @@ struct smack_master_list {
 
 LIST_HEAD(smack_rule_list);
 
+struct smack_parsed_rule {
+	char			*smk_subject;
+	char			*smk_object;
+	int			smk_access1;
+	int			smk_access2;
+};
+
 static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT;
 
 const char *smack_cipso_option = SMACK_CIPSO_OPTION;
@@ -167,25 +175,28 @@ static void smk_netlabel_audit_set(struct netlbl_audit *nap)
 #define SMK_NETLBLADDRMIN	9
 
 /**
- * smk_set_access - add a rule to the rule list
- * @srp: the new rule to add
+ * smk_set_access - add a rule to the rule list or replace an old rule
+ * @srp: the rule to add or replace
  * @rule_list: the list of rules
  * @rule_lock: the rule list lock
+ * @global: if non-zero, indicates a global rule
  *
  * Looks through the current subject/object/access list for
  * the subject/object pair and replaces the access that was
  * there. If the pair isn't found add it with the specified
  * access.
  *
- * Returns 1 if a rule was found to exist already, 0 if it is new
  * Returns 0 if nothing goes wrong or -ENOMEM if it fails
  * during the allocation of the new pair to add.
  */
-static int smk_set_access(struct smack_rule *srp, struct list_head *rule_list,
-				struct mutex *rule_lock)
+static int smk_set_access(struct smack_parsed_rule *srp,
+				struct list_head *rule_list,
+				struct mutex *rule_lock, int global)
 {
 	struct smack_rule *sp;
+	struct smack_master_list *smlp;
 	int found = 0;
+	int rc = 0;
 
 	mutex_lock(rule_lock);
 
@@ -197,23 +208,89 @@ static int smk_set_access(struct smack_rule *srp, struct list_head *rule_list,
 		if (sp->smk_object == srp->smk_object &&
 		    sp->smk_subject == srp->smk_subject) {
 			found = 1;
-			sp->smk_access = srp->smk_access;
+			sp->smk_access |= srp->smk_access1;
+			sp->smk_access &= ~srp->smk_access2;
 			break;
 		}
 	}
-	if (found == 0)
-		list_add_rcu(&srp->list, rule_list);
 
+	if (found == 0) {
+		sp = kzalloc(sizeof(*sp), GFP_KERNEL);
+		if (sp == NULL) {
+			rc = -ENOMEM;
+			goto out;
+		}
+
+		sp->smk_subject = srp->smk_subject;
+		sp->smk_object = srp->smk_object;
+		sp->smk_access = srp->smk_access1 & ~srp->smk_access2;
+
+		list_add_rcu(&sp->list, rule_list);
+		/*
+		 * If this is a global as opposed to self and a new rule
+		 * it needs to get added for reporting.
+		 */
+		if (global) {
+			smlp = kzalloc(sizeof(*smlp), GFP_KERNEL);
+			if (smlp != NULL) {
+				smlp->smk_rule = sp;
+				list_add_rcu(&smlp->list, &smack_rule_list);
+			} else
+				rc = -ENOMEM;
+		}
+	}
+
+out:
 	mutex_unlock(rule_lock);
+	return rc;
+}
+
+/**
+ * smk_perm_from_str - parse smack accesses from a text string
+ * @string: a text string that contains a Smack accesses code
+ *
+ * Returns an integer with respective bits set for specified accesses.
+ */
+static int smk_perm_from_str(const char *string)
+{
+	int perm = 0;
+	const char *cp;
 
-	return found;
+	for (cp = string; ; cp++)
+		switch (*cp) {
+		case '-':
+			break;
+		case 'r':
+		case 'R':
+			perm |= MAY_READ;
+			break;
+		case 'w':
+		case 'W':
+			perm |= MAY_WRITE;
+			break;
+		case 'x':
+		case 'X':
+			perm |= MAY_EXEC;
+			break;
+		case 'a':
+		case 'A':
+			perm |= MAY_APPEND;
+			break;
+		case 't':
+		case 'T':
+			perm |= MAY_TRANSMUTE;
+			break;
+		default:
+			return perm;
+		}
 }
 
 /**
  * smk_fill_rule - Fill Smack rule from strings
  * @subject: subject label string
  * @object: object label string
- * @access: access string
+ * @access1: access string
+ * @access2: string with permissions to be removed
  * @rule: Smack rule
  * @import: if non-zero, import labels
  * @len: label length limit
@@ -221,8 +298,9 @@ static int smk_set_access(struct smack_rule *srp, struct list_head *rule_list,
  * Returns 0 on success, -1 on failure
  */
 static int smk_fill_rule(const char *subject, const char *object,
-				const char *access, struct smack_rule *rule,
-				int import, int len)
+				const char *access1, const char *access2,
+				struct smack_parsed_rule *rule, int import,
+				int len)
 {
 	const char *cp;
 	struct smack_known *skp;
@@ -255,36 +333,11 @@ static int smk_fill_rule(const char *subject, const char *object,
 		rule->smk_object = skp->smk_known;
 	}
 
-	rule->smk_access = 0;
-
-	for (cp = access; *cp != '\0'; cp++) {
-		switch (*cp) {
-		case '-':
-			break;
-		case 'r':
-		case 'R':
-			rule->smk_access |= MAY_READ;
-			break;
-		case 'w':
-		case 'W':
-			rule->smk_access |= MAY_WRITE;
-			break;
-		case 'x':
-		case 'X':
-			rule->smk_access |= MAY_EXEC;
-			break;
-		case 'a':
-		case 'A':
-			rule->smk_access |= MAY_APPEND;
-			break;
-		case 't':
-		case 'T':
-			rule->smk_access |= MAY_TRANSMUTE;
-			break;
-		default:
-			return 0;
-		}
-	}
+	rule->smk_access1 = smk_perm_from_str(access1);
+	if (access2)
+		rule->smk_access2 = smk_perm_from_str(access2);
+	else
+		rule->smk_access2 = ~rule->smk_access1;
 
 	return 0;
 }
@@ -297,30 +350,33 @@ static int smk_fill_rule(const char *subject, const char *object,
  *
  * Returns 0 on success, -1 on errors.
  */
-static int smk_parse_rule(const char *data, struct smack_rule *rule, int import)
+static int smk_parse_rule(const char *data, struct smack_parsed_rule *rule,
+				int import)
 {
 	int rc;
 
 	rc = smk_fill_rule(data, data + SMK_LABELLEN,
-			   data + SMK_LABELLEN + SMK_LABELLEN, rule, import,
-			   SMK_LABELLEN);
+			   data + SMK_LABELLEN + SMK_LABELLEN, NULL, rule,
+			   import, SMK_LABELLEN);
 	return rc;
 }
 
 /**
  * smk_parse_long_rule - parse Smack rule from rule string
  * @data: string to be parsed, null terminated
- * @rule: Smack rule
+ * @rule: Will be filled with Smack parsed rule
  * @import: if non-zero, import labels
+ * @change: if non-zero, data is from /smack/change-rule
  *
  * Returns 0 on success, -1 on failure
  */
-static int smk_parse_long_rule(const char *data, struct smack_rule *rule,
-				int import)
+static int smk_parse_long_rule(const char *data, struct smack_parsed_rule *rule,
+				int import, int change)
 {
 	char *subject;
 	char *object;
-	char *access;
+	char *access1;
+	char *access2;
 	int datalen;
 	int rc = -1;
 
@@ -334,14 +390,27 @@ static int smk_parse_long_rule(const char *data, struct smack_rule *rule,
 	object = kzalloc(datalen, GFP_KERNEL);
 	if (object == NULL)
 		goto free_out_s;
-	access = kzalloc(datalen, GFP_KERNEL);
-	if (access == NULL)
+	access1 = kzalloc(datalen, GFP_KERNEL);
+	if (access1 == NULL)
 		goto free_out_o;
+	access2 = kzalloc(datalen, GFP_KERNEL);
+	if (access2 == NULL)
+		goto free_out_a;
+
+	if (change) {
+		if (sscanf(data, "%s %s %s %s",
+			subject, object, access1, access2) == 4)
+			rc = smk_fill_rule(subject, object, access1, access2,
+				rule, import, 0);
+	} else {
+		if (sscanf(data, "%s %s %s", subject, object, access1) == 3)
+			rc = smk_fill_rule(subject, object, access1, NULL,
+				rule, import, 0);
+	}
 
-	if (sscanf(data, "%s %s %s", subject, object, access) == 3)
-		rc = smk_fill_rule(subject, object, access, rule, import, 0);
-
-	kfree(access);
+	kfree(access2);
+free_out_a:
+	kfree(access1);
 free_out_o:
 	kfree(object);
 free_out_s:
@@ -351,6 +420,7 @@ free_out_s:
 
 #define SMK_FIXED24_FMT	0	/* Fixed 24byte label format */
 #define SMK_LONG_FMT	1	/* Variable long label format */
+#define SMK_CHANGE_FMT	2	/* Rule modification format */
 /**
  * smk_write_rules_list - write() for any /smack rule file
  * @file: file pointer, not actually used
@@ -359,22 +429,24 @@ free_out_s:
  * @ppos: where to start - must be 0
  * @rule_list: the list of rules to write to
  * @rule_lock: lock for the rule list
- * @format: /smack/load or /smack/load2 format.
+ * @format: /smack/load or /smack/load2 or /smack/change-rule format.
  *
  * Get one smack access rule from above.
  * The format for SMK_LONG_FMT is:
  *	"subject<whitespace>object<whitespace>access[<whitespace>...]"
  * The format for SMK_FIXED24_FMT is exactly:
  *	"subject                 object                  rwxat"
+ * The format for SMK_CHANGE_FMT is:
+ *	"subject<whitespace>object<whitespace>
+ *	 acc_enable<whitespace>acc_disable[<whitespace>...]"
  */
 static ssize_t smk_write_rules_list(struct file *file, const char __user *buf,
 					size_t count, loff_t *ppos,
 					struct list_head *rule_list,
 					struct mutex *rule_lock, int format)
 {
-	struct smack_master_list *smlp;
 	struct smack_known *skp;
-	struct smack_rule *rule;
+	struct smack_parsed_rule *rule;
 	char *data;
 	int datalen;
 	int rc = -EINVAL;
@@ -417,7 +489,11 @@ static ssize_t smk_write_rules_list(struct file *file, const char __user *buf,
 		 * Be sure the data string is terminated.
 		 */
 		data[count] = '\0';
-		if (smk_parse_long_rule(data, rule, 1))
+		if (smk_parse_long_rule(data, rule, 1, 0))
+			goto out_free_rule;
+	} else if (format == SMK_CHANGE_FMT) {
+		data[count] = '\0';
+		if (smk_parse_long_rule(data, rule, 1, 1))
 			goto out_free_rule;
 	} else {
 		/*
@@ -437,22 +513,9 @@ static ssize_t smk_write_rules_list(struct file *file, const char __user *buf,
 		rule_lock = &skp->smk_rules_lock;
 	}
 
-	rc = count;
-	/*
-	 * If this is a global as opposed to self and a new rule
-	 * it needs to get added for reporting.
-	 * smk_set_access returns true if there was already a rule
-	 * for the subject/object pair, and false if it was new.
-	 */
-	if (!smk_set_access(rule, rule_list, rule_lock)) {
-		if (load) {
-			smlp = kzalloc(sizeof(*smlp), GFP_KERNEL);
-			if (smlp != NULL) {
-				smlp->smk_rule = rule;
-				list_add_rcu(&smlp->list, &smack_rule_list);
-			} else
-				rc = -ENOMEM;
-		}
+	rc = smk_set_access(rule, rule_list, rule_lock, load);
+	if (rc == 0) {
+		rc = count;
 		goto out;
 	}
 
@@ -1774,7 +1837,7 @@ static const struct file_operations smk_load_self_ops = {
 static ssize_t smk_user_access(struct file *file, const char __user *buf,
 				size_t count, loff_t *ppos, int format)
 {
-	struct smack_rule rule;
+	struct smack_parsed_rule rule;
 	char *data;
 	char *cod;
 	int res;
@@ -1796,14 +1859,14 @@ static ssize_t smk_user_access(struct file *file, const char __user *buf,
 			return -ENOMEM;
 		memcpy(cod, data, count);
 		cod[count] = '\0';
-		res = smk_parse_long_rule(cod, &rule, 0);
+		res = smk_parse_long_rule(cod, &rule, 0, 0);
 		kfree(cod);
 	}
 
 	if (res)
 		return -EINVAL;
 
-	res = smk_access(rule.smk_subject, rule.smk_object, rule.smk_access,
+	res = smk_access(rule.smk_subject, rule.smk_object, rule.smk_access1,
 			  NULL);
 	data[0] = res == 0 ? '1' : '0';
 	data[1] = '\0';
@@ -2035,10 +2098,8 @@ static ssize_t smk_write_revoke_subj(struct file *file, const char __user *buf,
 	}
 
 	skp = smk_find_entry(cp);
-	if (skp == NULL) {
-		rc = -EINVAL;
+	if (skp == NULL)
 		goto free_out;
-	}
 
 	rule_list = &skp->smk_rules;
 	rule_lock = &skp->smk_rules_lock;
@@ -2077,6 +2138,33 @@ static int smk_init_sysfs(void)
 }
 
 /**
+ * smk_write_change_rule - write() for /smack/change-rule
+ * @file: file pointer
+ * @buf: data from user space
+ * @count: bytes sent
+ * @ppos: where to start - must be 0
+ */
+static ssize_t smk_write_change_rule(struct file *file, const char __user *buf,
+				size_t count, loff_t *ppos)
+{
+	/*
+	 * Must have privilege.
+	 */
+	if (!capable(CAP_MAC_ADMIN))
+		return -EPERM;
+
+	return smk_write_rules_list(file, buf, count, ppos, NULL, NULL,
+				    SMK_CHANGE_FMT);
+}
+
+static const struct file_operations smk_change_rule_ops = {
+	.write		= smk_write_change_rule,
+	.read		= simple_transaction_read,
+	.release	= simple_transaction_release,
+	.llseek		= generic_file_llseek,
+};
+
+/**
  * smk_fill_super - fill the /smackfs superblock
  * @sb: the empty superblock
  * @data: unused
@@ -2125,6 +2213,8 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent)
 		[SMK_REVOKE_SUBJ] = {
 			"revoke-subject", &smk_revoke_subj_ops,
 			S_IRUGO|S_IWUSR},
+		[SMK_CHANGE_RULE] = {
+			"change-rule", &smk_change_rule_ops, S_IRUGO|S_IWUSR},
 		/* last one */
 			{""}
 	};
diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c
index a2ee362..f0b756e 100644
--- a/security/tomoyo/tomoyo.c
+++ b/security/tomoyo/tomoyo.c
@@ -536,7 +536,7 @@ static struct security_operations tomoyo_security_ops = {
 };
 
 /* Lock for GC. */
-struct srcu_struct tomoyo_ss;
+DEFINE_SRCU(tomoyo_ss);
 
 /**
  * tomoyo_init - Register TOMOYO Linux as a LSM module.
@@ -550,8 +550,7 @@ static int __init tomoyo_init(void)
 	if (!security_module_enable(&tomoyo_security_ops))
 		return 0;
 	/* register ourselves with the security framework */
-	if (register_security(&tomoyo_security_ops) ||
-	    init_srcu_struct(&tomoyo_ss))
+	if (register_security(&tomoyo_security_ops))
 		panic("Failure registering TOMOYO Linux");
 	printk(KERN_INFO "TOMOYO Linux initialized\n");
 	cred->security = &tomoyo_kernel_domain;
diff --git a/sound/core/control.c b/sound/core/control.c
index 8c7c2c9..d8aa206 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -190,7 +190,7 @@ EXPORT_SYMBOL(snd_ctl_notify);
  * Allocates a new struct snd_kcontrol instance and copies the given template 
  * to the new instance. It does not copy volatile data (access).
  *
- * Returns the pointer of the new instance, or NULL on failure.
+ * Return: The pointer of the new instance, or %NULL on failure.
  */
 static struct snd_kcontrol *snd_ctl_new(struct snd_kcontrol *control,
 					unsigned int access)
@@ -224,7 +224,7 @@ static struct snd_kcontrol *snd_ctl_new(struct snd_kcontrol *control,
  * template.  When the access field of ncontrol is 0, it's assumed as
  * READWRITE access. When the count field is 0, it's assumes as one.
  *
- * Returns the pointer of the newly generated instance, or NULL on failure.
+ * Return: The pointer of the newly generated instance, or %NULL on failure.
  */
 struct snd_kcontrol *snd_ctl_new1(const struct snd_kcontrol_new *ncontrol,
 				  void *private_data)
@@ -322,9 +322,10 @@ static int snd_ctl_find_hole(struct snd_card *card, unsigned int count)
  * snd_ctl_new1() to the given card. Assigns also an unique
  * numid used for fast search.
  *
- * Returns zero if successful, or a negative error code on failure.
- *
  * It frees automatically the control which cannot be added.
+ *
+ * Return: Zero if successful, or a negative error code on failure.
+ *
  */
 int snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol)
 {
@@ -380,9 +381,9 @@ EXPORT_SYMBOL(snd_ctl_add);
  * and the add_on_replace flag is set, the control is added.  If the
  * control exists, it is destroyed first.
  *
- * Returns zero if successful, or a negative error code on failure.
- *
  * It frees automatically the control which cannot be added or replaced.
+ *
+ * Return: Zero if successful, or a negative error code on failure.
  */
 int snd_ctl_replace(struct snd_card *card, struct snd_kcontrol *kcontrol,
 		    bool add_on_replace)
@@ -442,8 +443,8 @@ EXPORT_SYMBOL(snd_ctl_replace);
  * Removes the control from the card and then releases the instance.
  * You don't need to call snd_ctl_free_one(). You must be in
  * the write lock - down_write(&card->controls_rwsem).
- * 
- * Returns 0 if successful, or a negative error code on failure.
+ *
+ * Return: 0 if successful, or a negative error code on failure.
  */
 int snd_ctl_remove(struct snd_card *card, struct snd_kcontrol *kcontrol)
 {
@@ -470,8 +471,8 @@ EXPORT_SYMBOL(snd_ctl_remove);
  *
  * Finds the control instance with the given id, removes it from the
  * card list and releases it.
- * 
- * Returns 0 if successful, or a negative error code on failure.
+ *
+ * Return: 0 if successful, or a negative error code on failure.
  */
 int snd_ctl_remove_id(struct snd_card *card, struct snd_ctl_elem_id *id)
 {
@@ -498,8 +499,8 @@ EXPORT_SYMBOL(snd_ctl_remove_id);
  *
  * Finds the control instance with the given id, removes it from the
  * card list and releases it.
- * 
- * Returns 0 if successful, or a negative error code on failure.
+ *
+ * Return: 0 if successful, or a negative error code on failure.
  */
 static int snd_ctl_remove_user_ctl(struct snd_ctl_file * file,
 				   struct snd_ctl_elem_id *id)
@@ -541,7 +542,7 @@ error:
  * Finds the control instance with the given id, and activate or
  * inactivate the control together with notification, if changed.
  *
- * Returns 0 if unchanged, 1 if changed, or a negative error code on failure.
+ * Return: 0 if unchanged, 1 if changed, or a negative error code on failure.
  */
 int snd_ctl_activate_id(struct snd_card *card, struct snd_ctl_elem_id *id,
 			int active)
@@ -587,7 +588,7 @@ EXPORT_SYMBOL_GPL(snd_ctl_activate_id);
  * Finds the control with the old id from the card, and replaces the
  * id with the new one.
  *
- * Returns zero if successful, or a negative error code on failure.
+ * Return: Zero if successful, or a negative error code on failure.
  */
 int snd_ctl_rename_id(struct snd_card *card, struct snd_ctl_elem_id *src_id,
 		      struct snd_ctl_elem_id *dst_id)
@@ -616,10 +617,11 @@ EXPORT_SYMBOL(snd_ctl_rename_id);
  *
  * Finds the control instance with the given number-id from the card.
  *
- * Returns the pointer of the instance if found, or NULL if not.
- *
  * The caller must down card->controls_rwsem before calling this function
  * (if the race condition can happen).
+ *
+ * Return: The pointer of the instance if found, or %NULL if not.
+ *
  */
 struct snd_kcontrol *snd_ctl_find_numid(struct snd_card *card, unsigned int numid)
 {
@@ -643,10 +645,11 @@ EXPORT_SYMBOL(snd_ctl_find_numid);
  *
  * Finds the control instance with the given id from the card.
  *
- * Returns the pointer of the instance if found, or NULL if not.
- *
  * The caller must down card->controls_rwsem before calling this function
  * (if the race condition can happen).
+ *
+ * Return: The pointer of the instance if found, or %NULL if not.
+ *
  */
 struct snd_kcontrol *snd_ctl_find_id(struct snd_card *card,
 				     struct snd_ctl_elem_id *id)
@@ -1710,6 +1713,8 @@ EXPORT_SYMBOL(snd_ctl_boolean_stereo_info);
  * Sets all required fields in @info to their appropriate values.
  * If the control's accessibility is not the default (readable and writable),
  * the caller has to fill @info->access.
+ *
+ * Return: Zero.
  */
 int snd_ctl_enum_info(struct snd_ctl_elem_info *info, unsigned int channels,
 		      unsigned int items, const char *const names[])
diff --git a/sound/core/device.c b/sound/core/device.c
index f03cb54..df88def 100644
--- a/sound/core/device.c
+++ b/sound/core/device.c
@@ -39,7 +39,7 @@
  * The data pointer plays a role as the identifier, too, so the
  * pointer address must be unique and unchanged.
  *
- * Returns zero if successful, or a negative error code on failure.
+ * Return: Zero if successful, or a negative error code on failure.
  */
 int snd_device_new(struct snd_card *card, snd_device_type_t type,
 		   void *device_data, struct snd_device_ops *ops)
@@ -73,7 +73,7 @@ EXPORT_SYMBOL(snd_device_new);
  * callbacks, dev_disconnect and dev_free, corresponding to the state.
  * Then release the device.
  *
- * Returns zero if successful, or a negative error code on failure or if the
+ * Return: Zero if successful, or a negative error code on failure or if the
  * device not found.
  */
 int snd_device_free(struct snd_card *card, void *device_data)
@@ -116,7 +116,7 @@ EXPORT_SYMBOL(snd_device_free);
  *
  * Usually called from snd_card_disconnect().
  *
- * Returns zero if successful, or a negative error code on failure or if the
+ * Return: Zero if successful, or a negative error code on failure or if the
  * device not found.
  */
 int snd_device_disconnect(struct snd_card *card, void *device_data)
@@ -151,7 +151,7 @@ int snd_device_disconnect(struct snd_card *card, void *device_data)
  * but it can be called later if any new devices are created after
  * invocation of snd_card_register().
  *
- * Returns zero if successful, or a negative error code on failure or if the
+ * Return: Zero if successful, or a negative error code on failure or if the
  * device not found.
  */
 int snd_device_register(struct snd_card *card, void *device_data)
diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c
index 3f7f662..d105073 100644
--- a/sound/core/hwdep.c
+++ b/sound/core/hwdep.c
@@ -356,7 +356,7 @@ static const struct file_operations snd_hwdep_f_ops =
  * The callbacks (hwdep->ops) must be set on the returned instance
  * after this call manually by the caller.
  *
- * Returns zero if successful, or a negative error code on failure.
+ * Return: Zero if successful, or a negative error code on failure.
  */
 int snd_hwdep_new(struct snd_card *card, char *id, int device,
 		  struct snd_hwdep **rhwdep)
diff --git a/sound/core/info.c b/sound/core/info.c
index 5bb97e7..f899f55 100644
--- a/sound/core/info.c
+++ b/sound/core/info.c
@@ -89,7 +89,7 @@ static int resize_info_buffer(struct snd_info_buffer *buffer,
 	char *nbuf;
 
 	nsize = PAGE_ALIGN(nsize);
-	nbuf = krealloc(buffer->buffer, nsize, GFP_KERNEL);
+	nbuf = krealloc(buffer->buffer, nsize, GFP_KERNEL | __GFP_ZERO);
 	if (! nbuf)
 		return -ENOMEM;
 
@@ -105,7 +105,7 @@ static int resize_info_buffer(struct snd_info_buffer *buffer,
  *
  * Outputs the string on the procfs buffer just like printf().
  *
- * Returns the size of output string.
+ * Return: The size of output string, or a negative error code.
  */
 int snd_iprintf(struct snd_info_buffer *buffer, const char *fmt, ...)
 {
@@ -310,12 +310,10 @@ static int snd_info_entry_open(struct inode *inode, struct file *file)
 	struct snd_info_entry *entry;
 	struct snd_info_private_data *data;
 	struct snd_info_buffer *buffer;
-	struct proc_dir_entry *p;
 	int mode, err;
 
 	mutex_lock(&info_mutex);
-	p = PDE(inode);
-	entry = p == NULL ? NULL : (struct snd_info_entry *)p->data;
+	entry = PDE_DATA(inode);
 	if (entry == NULL || ! entry->p) {
 		mutex_unlock(&info_mutex);
 		return -ENODEV;
@@ -353,7 +351,7 @@ static int snd_info_entry_open(struct inode *inode, struct file *file)
 				goto __nomem;
 			data->rbuffer = buffer;
 			buffer->len = PAGE_SIZE;
-			buffer->buffer = kmalloc(buffer->len, GFP_KERNEL);
+			buffer->buffer = kzalloc(buffer->len, GFP_KERNEL);
 			if (buffer->buffer == NULL)
 				goto __nomem;
 		}
@@ -694,32 +692,27 @@ int snd_info_card_free(struct snd_card *card)
  *
  * Reads one line from the buffer and stores the string.
  *
- * Returns zero if successful, or 1 if error or EOF.
+ * Return: Zero if successful, or 1 if error or EOF.
  */
 int snd_info_get_line(struct snd_info_buffer *buffer, char *line, int len)
 {
 	int c = -1;
 
+	if (snd_BUG_ON(!buffer || !buffer->buffer))
+		return 1;
 	if (len <= 0 || buffer->stop || buffer->error)
 		return 1;
-	while (--len > 0) {
+	while (!buffer->stop) {
 		c = buffer->buffer[buffer->curr++];
-		if (c == '\n') {
-			if (buffer->curr >= buffer->size)
-				buffer->stop = 1;
-			break;
-		}
-		*line++ = c;
-		if (buffer->curr >= buffer->size) {
+		if (buffer->curr >= buffer->size)
 			buffer->stop = 1;
+		if (c == '\n')
 			break;
+		if (len) {
+			len--;
+			*line++ = c;
 		}
 	}
-	while (c != '\n' && !buffer->stop) {
-		c = buffer->buffer[buffer->curr++];
-		if (buffer->curr >= buffer->size)
-			buffer->stop = 1;
-	}
 	*line = '\0';
 	return 0;
 }
@@ -735,7 +728,7 @@ EXPORT_SYMBOL(snd_info_get_line);
  * Parses the original string and copy a token to the given
  * string buffer.
  *
- * Returns the updated pointer of the original string so that
+ * Return: The updated pointer of the original string so that
  * it can be used for the next call.
  */
 const char *snd_info_get_str(char *dest, const char *src, int len)
@@ -774,7 +767,7 @@ EXPORT_SYMBOL(snd_info_get_str);
  * Usually called from other functions such as
  * snd_info_create_card_entry().
  *
- * Returns the pointer of the new instance, or NULL on failure.
+ * Return: The pointer of the new instance, or %NULL on failure.
  */
 static struct snd_info_entry *snd_info_create_entry(const char *name)
 {
@@ -803,7 +796,7 @@ static struct snd_info_entry *snd_info_create_entry(const char *name)
  *
  * Creates a new info entry and assigns it to the given module.
  *
- * Returns the pointer of the new instance, or NULL on failure.
+ * Return: The pointer of the new instance, or %NULL on failure.
  */
 struct snd_info_entry *snd_info_create_module_entry(struct module * module,
 					       const char *name,
@@ -827,7 +820,7 @@ EXPORT_SYMBOL(snd_info_create_module_entry);
  *
  * Creates a new info entry and assigns it to the given card.
  *
- * Returns the pointer of the new instance, or NULL on failure.
+ * Return: The pointer of the new instance, or %NULL on failure.
  */
 struct snd_info_entry *snd_info_create_card_entry(struct snd_card *card,
 					     const char *name,
@@ -893,7 +886,7 @@ static int snd_info_dev_register_entry(struct snd_device *device)
  * For releasing this entry, use snd_device_free() instead of
  * snd_info_free_entry(). 
  *
- * Returns zero if successful, or a negative error code on failure.
+ * Return: Zero if successful, or a negative error code on failure.
  */
 int snd_card_proc_new(struct snd_card *card, const char *name,
 		      struct snd_info_entry **entryp)
@@ -949,7 +942,7 @@ EXPORT_SYMBOL(snd_info_free_entry);
  *
  * Registers the proc info entry.
  *
- * Returns zero if successful, or a negative error code on failure.
+ * Return: Zero if successful, or a negative error code on failure.
  */
 int snd_info_register(struct snd_info_entry * entry)
 {
@@ -959,15 +952,21 @@ int snd_info_register(struct snd_info_entry * entry)
 		return -ENXIO;
 	root = entry->parent == NULL ? snd_proc_root : entry->parent->p;
 	mutex_lock(&info_mutex);
-	p = create_proc_entry(entry->name, entry->mode, root);
-	if (!p) {
-		mutex_unlock(&info_mutex);
-		return -ENOMEM;
+	if (S_ISDIR(entry->mode)) {
+		p = proc_mkdir_mode(entry->name, entry->mode, root);
+		if (!p) {
+			mutex_unlock(&info_mutex);
+			return -ENOMEM;
+		}
+	} else {
+		p = proc_create_data(entry->name, entry->mode, root,
+					&snd_info_entry_operations, entry);
+		if (!p) {
+			mutex_unlock(&info_mutex);
+			return -ENOMEM;
+		}
+		p->size = entry->size;
 	}
-	if (!S_ISDIR(entry->mode))
-		p->proc_fops = &snd_info_entry_operations;
-	p->size = entry->size;
-	p->data = entry;
 	entry->p = p;
 	if (entry->parent)
 		list_add_tail(&entry->list, &entry->parent->children);
diff --git a/sound/core/init.c b/sound/core/init.c
index 7b012d1..6ef0640 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -144,7 +144,7 @@ static inline int init_info_for_card(struct snd_card *card)
  *  space for the driver to use freely.  The allocated struct is stored
  *  in the given card_ret pointer.
  *
- *  Returns zero if successful or a negative error code.
+ *  Return: Zero if successful or a negative error code.
  */
 int snd_card_create(int idx, const char *xid,
 		    struct module *module, int extra_size,
@@ -337,7 +337,7 @@ static const struct file_operations snd_shutdown_f_ops =
  *
  *  Disconnects all APIs from the file-operations (user space).
  *
- *  Returns zero, otherwise a negative error code.
+ *  Return: Zero, otherwise a negative error code.
  *
  *  Note: The current implementation replaces all active file->f_op with special
  *        dummy file operations (they do nothing except release).
@@ -415,7 +415,7 @@ EXPORT_SYMBOL(snd_card_disconnect);
  *  devices automatically.  That is, you don't have to release the devices
  *  by yourself.
  *
- *  Returns zero. Frees all associated devices and frees the control
+ *  Return: Zero. Frees all associated devices and frees the control
  *  interface associated to given soundcard.
  */
 static int snd_card_do_free(struct snd_card *card)
@@ -677,7 +677,7 @@ static struct device_attribute card_number_attrs =
  *  external accesses.  Thus, you should call this function at the end
  *  of the initialization of the card.
  *
- *  Returns zero otherwise a negative error code if the registration failed.
+ *  Return: Zero otherwise a negative error code if the registration failed.
  */
 int snd_card_register(struct snd_card *card)
 {
@@ -849,7 +849,7 @@ int __exit snd_card_info_done(void)
  *  This function adds the component id string to the supported list.
  *  The component can be referred from the alsa-lib.
  *
- *  Returns zero otherwise a negative error code.
+ *  Return: Zero otherwise a negative error code.
  */
   
 int snd_component_add(struct snd_card *card, const char *component)
@@ -883,7 +883,7 @@ EXPORT_SYMBOL(snd_component_add);
  *  This linked-list is used to keep tracking the connection state,
  *  and to avoid the release of busy resources by hotplug.
  *
- *  Returns zero or a negative error code.
+ *  Return: zero or a negative error code.
  */
 int snd_card_file_add(struct snd_card *card, struct file *file)
 {
@@ -920,7 +920,7 @@ EXPORT_SYMBOL(snd_card_file_add);
  *  called beforehand, it processes the pending release of
  *  resources.
  *
- *  Returns zero or a negative error code.
+ *  Return: Zero or a negative error code.
  */
 int snd_card_file_remove(struct snd_card *card, struct file *file)
 {
@@ -959,6 +959,8 @@ EXPORT_SYMBOL(snd_card_file_remove);
  *
  *  Waits until the power-state is changed.
  *
+ *  Return: Zero if successful, or a negative error code.
+ *
  *  Note: the power lock must be active before call.
  */
 int snd_power_wait(struct snd_card *card, unsigned int power_state)
diff --git a/sound/core/isadma.c b/sound/core/isadma.c
index c0f1208..e2b3861 100644
--- a/sound/core/isadma.c
+++ b/sound/core/isadma.c
@@ -81,7 +81,7 @@ EXPORT_SYMBOL(snd_dma_disable);
  * @dma: the dma number
  * @size: the dma transfer size
  *
- * Returns the current pointer in DMA tranfer buffer in bytes
+ * Return: The current pointer in DMA transfer buffer in bytes.
  */
 unsigned int snd_dma_pointer(unsigned long dma, unsigned int size)
 {
diff --git a/sound/core/jack.c b/sound/core/jack.c
index a06b165..b35fe73 100644
--- a/sound/core/jack.c
+++ b/sound/core/jack.c
@@ -98,8 +98,8 @@ static int snd_jack_dev_register(struct snd_device *device)
  *
  * Creates a new jack object.
  *
- * Returns zero if successful, or a negative error code on failure.
- * On success jjack will be initialised.
+ * Return: Zero if successful, or a negative error code on failure.
+ * On success @jjack will be initialised.
  */
 int snd_jack_new(struct snd_card *card, const char *id, int type,
 		 struct snd_jack **jjack)
@@ -189,6 +189,8 @@ EXPORT_SYMBOL(snd_jack_set_parent);
  * using this abstraction.
  *
  * This function may only be called prior to registration of the jack.
+ *
+ * Return: Zero if successful, or a negative error code on failure.
  */
 int snd_jack_set_key(struct snd_jack *jack, enum snd_jack_types type,
 		     int keytype)
diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c
index 6915692..bdf826f 100644
--- a/sound/core/memalloc.c
+++ b/sound/core/memalloc.c
@@ -81,7 +81,7 @@ static inline void dec_snd_pages(int order)
  *
  * Allocates the physically contiguous pages with the given size.
  *
- * Returns the pointer of the buffer, or NULL if no enoguh memory.
+ * Return: The pointer of the buffer, or %NULL if no enough memory.
  */
 void *snd_malloc_pages(size_t size, gfp_t gfp_flags)
 {
@@ -175,9 +175,9 @@ static void snd_free_dev_pages(struct device *dev, size_t size, void *ptr,
  *
  * Calls the memory-allocator function for the corresponding
  * buffer type.
- * 
- * Returns zero if the buffer with the given size is allocated successfully,
- * other a negative value at error.
+ *
+ * Return: Zero if the buffer with the given size is allocated successfully,
+ * otherwise a negative value on error.
  */
 int snd_dma_alloc_pages(int type, struct device *device, size_t size,
 			struct snd_dma_buffer *dmab)
@@ -229,9 +229,9 @@ int snd_dma_alloc_pages(int type, struct device *device, size_t size,
  * buffer type.  When no space is left, this function reduces the size and
  * tries to allocate again.  The size actually allocated is stored in
  * res_size argument.
- * 
- * Returns zero if the buffer with the given size is allocated successfully,
- * other a negative value at error.
+ *
+ * Return: Zero if the buffer with the given size is allocated successfully,
+ * otherwise a negative value on error.
  */
 int snd_dma_alloc_pages_fallback(int type, struct device *device, size_t size,
 				 struct snd_dma_buffer *dmab)
@@ -292,7 +292,7 @@ void snd_dma_free_pages(struct snd_dma_buffer *dmab)
  * Looks for the reserved-buffer list and re-uses if the same buffer
  * is found in the list.  When the buffer is found, it's removed from the free list.
  *
- * Returns the size of buffer if the buffer is found, or zero if not found.
+ * Return: The size of buffer if the buffer is found, or zero if not found.
  */
 size_t snd_dma_get_reserved_buf(struct snd_dma_buffer *dmab, unsigned int id)
 {
@@ -326,8 +326,8 @@ size_t snd_dma_get_reserved_buf(struct snd_dma_buffer *dmab, unsigned int id)
  * @id: the buffer id
  *
  * Reserves the given buffer as a reserved buffer.
- * 
- * Returns zero if successful, or a negative code at error.
+ *
+ * Return: Zero if successful, or a negative code on error.
  */
 int snd_dma_reserve_buf(struct snd_dma_buffer *dmab, unsigned int id)
 {
diff --git a/sound/core/memory.c b/sound/core/memory.c
index 66a278d..36c0f1a 100644
--- a/sound/core/memory.c
+++ b/sound/core/memory.c
@@ -33,7 +33,7 @@
  *
  * Copies the data from mmio-space to user-space.
  *
- * Returns zero if successful, or non-zero on failure.
+ * Return: Zero if successful, or non-zero on failure.
  */
 int copy_to_user_fromio(void __user *dst, const volatile void __iomem *src, size_t count)
 {
@@ -66,7 +66,7 @@ EXPORT_SYMBOL(copy_to_user_fromio);
  *
  * Copies the data from user-space to mmio-space.
  *
- * Returns zero if successful, or non-zero on failure.
+ * Return: Zero if successful, or non-zero on failure.
  */
 int copy_from_user_toio(volatile void __iomem *dst, const void __user *src, size_t count)
 {
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index 61798f8..578327e 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -637,7 +637,7 @@ static inline int snd_pcm_substream_proc_done(struct snd_pcm_substream *substrea
  * calling this, i.e. zero must be given to the argument of
  * snd_pcm_new().
  *
- * Returns zero if successful, or a negative error code on failure.
+ * Return: Zero if successful, or a negative error code on failure.
  */
 int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count)
 {
@@ -759,7 +759,7 @@ static int _snd_pcm_new(struct snd_card *card, const char *id, int device,
  * The pcm operators have to be set afterwards to the new instance
  * via snd_pcm_set_ops().
  *
- * Returns zero if successful, or a negative error code on failure.
+ * Return: Zero if successful, or a negative error code on failure.
  */
 int snd_pcm_new(struct snd_card *card, const char *id, int device,
 		int playback_count, int capture_count, struct snd_pcm **rpcm)
@@ -787,7 +787,7 @@ EXPORT_SYMBOL(snd_pcm_new);
  * The pcm operators have to be set afterwards to the new instance
  * via snd_pcm_set_ops().
  *
- * Returns zero if successful, or a negative error code on failure.
+ * Return: Zero if successful, or a negative error code on failure.
  */
 int snd_pcm_new_internal(struct snd_card *card, const char *id, int device,
 	int playback_count, int capture_count,
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index c4840ff..41b3dfe 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -666,7 +666,8 @@ static inline unsigned int muldiv32(unsigned int a, unsigned int b,
  * The interval is changed to the range satisfying both intervals.
  * The interval status (min, max, integer, etc.) are evaluated.
  *
- * Returns non-zero if the value is changed, zero if not changed.
+ * Return: Positive if the value is changed, zero if it's not changed, or a
+ * negative error code.
  */
 int snd_interval_refine(struct snd_interval *i, const struct snd_interval *v)
 {
@@ -865,7 +866,8 @@ void snd_interval_mulkdiv(const struct snd_interval *a, unsigned int k,
  * @nump: pointer to store the resultant numerator
  * @denp: pointer to store the resultant denominator
  *
- * Returns non-zero if the value is changed, zero if not changed.
+ * Return: Positive if the value is changed, zero if it's not changed, or a
+ * negative error code.
  */
 int snd_interval_ratnum(struct snd_interval *i,
 			unsigned int rats_count, struct snd_ratnum *rats,
@@ -983,7 +985,8 @@ EXPORT_SYMBOL(snd_interval_ratnum);
  * @nump: pointer to store the resultant numerator
  * @denp: pointer to store the resultant denominator
  *
- * Returns non-zero if the value is changed, zero if not changed.
+ * Return: Positive if the value is changed, zero if it's not changed, or a
+ * negative error code.
  */
 static int snd_interval_ratden(struct snd_interval *i,
 			       unsigned int rats_count, struct snd_ratden *rats,
@@ -1082,7 +1085,8 @@ static int snd_interval_ratden(struct snd_interval *i,
  * When mask is non-zero, only the elements corresponding to bit 1 are
  * evaluated.
  *
- * Returns non-zero if the value is changed, zero if not changed.
+ * Return: Positive if the value is changed, zero if it's not changed, or a
+ * negative error code.
  */
 int snd_interval_list(struct snd_interval *i, unsigned int count,
 		      const unsigned int *list, unsigned int mask)
@@ -1142,7 +1146,7 @@ static int snd_interval_step(struct snd_interval *i, unsigned int min, unsigned
  * @private: the private data pointer passed to function
  * @dep: the dependent variables
  *
- * Returns zero if successful, or a negative error code on failure.
+ * Return: Zero if successful, or a negative error code on failure.
  */
 int snd_pcm_hw_rule_add(struct snd_pcm_runtime *runtime, unsigned int cond,
 			int var,
@@ -1200,6 +1204,8 @@ EXPORT_SYMBOL(snd_pcm_hw_rule_add);
  * @mask: the bitmap mask
  *
  * Apply the constraint of the given bitmap mask to a 32-bit mask parameter.
+ *
+ * Return: Zero if successful, or a negative error code on failure.
  */
 int snd_pcm_hw_constraint_mask(struct snd_pcm_runtime *runtime, snd_pcm_hw_param_t var,
 			       u_int32_t mask)
@@ -1220,6 +1226,8 @@ int snd_pcm_hw_constraint_mask(struct snd_pcm_runtime *runtime, snd_pcm_hw_param
  * @mask: the 64bit bitmap mask
  *
  * Apply the constraint of the given bitmap mask to a 64-bit mask parameter.
+ *
+ * Return: Zero if successful, or a negative error code on failure.
  */
 int snd_pcm_hw_constraint_mask64(struct snd_pcm_runtime *runtime, snd_pcm_hw_param_t var,
 				 u_int64_t mask)
@@ -1240,6 +1248,9 @@ int snd_pcm_hw_constraint_mask64(struct snd_pcm_runtime *runtime, snd_pcm_hw_par
  * @var: hw_params variable to apply the integer constraint
  *
  * Apply the constraint of integer to an interval parameter.
+ *
+ * Return: Positive if the value is changed, zero if it's not changed, or a
+ * negative error code.
  */
 int snd_pcm_hw_constraint_integer(struct snd_pcm_runtime *runtime, snd_pcm_hw_param_t var)
 {
@@ -1257,6 +1268,9 @@ EXPORT_SYMBOL(snd_pcm_hw_constraint_integer);
  * @max: the maximal value
  * 
  * Apply the min/max range constraint to an interval parameter.
+ *
+ * Return: Positive if the value is changed, zero if it's not changed, or a
+ * negative error code.
  */
 int snd_pcm_hw_constraint_minmax(struct snd_pcm_runtime *runtime, snd_pcm_hw_param_t var,
 				 unsigned int min, unsigned int max)
@@ -1288,6 +1302,8 @@ static int snd_pcm_hw_rule_list(struct snd_pcm_hw_params *params,
  * @l: list
  * 
  * Apply the list of constraints to an interval parameter.
+ *
+ * Return: Zero if successful, or a negative error code on failure.
  */
 int snd_pcm_hw_constraint_list(struct snd_pcm_runtime *runtime,
 			       unsigned int cond,
@@ -1322,6 +1338,8 @@ static int snd_pcm_hw_rule_ratnums(struct snd_pcm_hw_params *params,
  * @cond: condition bits
  * @var: hw_params variable to apply the ratnums constraint
  * @r: struct snd_ratnums constriants
+ *
+ * Return: Zero if successful, or a negative error code on failure.
  */
 int snd_pcm_hw_constraint_ratnums(struct snd_pcm_runtime *runtime, 
 				  unsigned int cond,
@@ -1355,6 +1373,8 @@ static int snd_pcm_hw_rule_ratdens(struct snd_pcm_hw_params *params,
  * @cond: condition bits
  * @var: hw_params variable to apply the ratdens constraint
  * @r: struct snd_ratdens constriants
+ *
+ * Return: Zero if successful, or a negative error code on failure.
  */
 int snd_pcm_hw_constraint_ratdens(struct snd_pcm_runtime *runtime, 
 				  unsigned int cond,
@@ -1386,6 +1406,8 @@ static int snd_pcm_hw_rule_msbits(struct snd_pcm_hw_params *params,
  * @cond: condition bits
  * @width: sample bits width
  * @msbits: msbits width
+ *
+ * Return: Zero if successful, or a negative error code on failure.
  */
 int snd_pcm_hw_constraint_msbits(struct snd_pcm_runtime *runtime, 
 				 unsigned int cond,
@@ -1414,6 +1436,8 @@ static int snd_pcm_hw_rule_step(struct snd_pcm_hw_params *params,
  * @cond: condition bits
  * @var: hw_params variable to apply the step constraint
  * @step: step size
+ *
+ * Return: Zero if successful, or a negative error code on failure.
  */
 int snd_pcm_hw_constraint_step(struct snd_pcm_runtime *runtime,
 			       unsigned int cond,
@@ -1444,6 +1468,8 @@ static int snd_pcm_hw_rule_pow2(struct snd_pcm_hw_params *params, struct snd_pcm
  * @runtime: PCM runtime instance
  * @cond: condition bits
  * @var: hw_params variable to apply the power-of-2 constraint
+ *
+ * Return: Zero if successful, or a negative error code on failure.
  */
 int snd_pcm_hw_constraint_pow2(struct snd_pcm_runtime *runtime,
 			       unsigned int cond,
@@ -1470,6 +1496,8 @@ static int snd_pcm_hw_rule_noresample_func(struct snd_pcm_hw_params *params,
  * snd_pcm_hw_rule_noresample - add a rule to allow disabling hw resampling
  * @runtime: PCM runtime instance
  * @base_rate: the rate at which the hardware does not resample
+ *
+ * Return: Zero if successful, or a negative error code on failure.
  */
 int snd_pcm_hw_rule_noresample(struct snd_pcm_runtime *runtime,
 			       unsigned int base_rate)
@@ -1519,8 +1547,8 @@ EXPORT_SYMBOL(_snd_pcm_hw_params_any);
  * @var: parameter to retrieve
  * @dir: pointer to the direction (-1,0,1) or %NULL
  *
- * Return the value for field @var if it's fixed in configuration space
- * defined by @params. Return -%EINVAL otherwise.
+ * Return: The value for field @var if it's fixed in configuration space
+ * defined by @params. -%EINVAL otherwise.
  */
 int snd_pcm_hw_param_value(const struct snd_pcm_hw_params *params,
 			   snd_pcm_hw_param_t var, int *dir)
@@ -1591,7 +1619,8 @@ static int _snd_pcm_hw_param_first(struct snd_pcm_hw_params *params,
  *
  * Inside configuration space defined by @params remove from @var all
  * values > minimum. Reduce configuration space accordingly.
- * Return the minimum.
+ *
+ * Return: The minimum, or a negative error code on failure.
  */
 int snd_pcm_hw_param_first(struct snd_pcm_substream *pcm, 
 			   struct snd_pcm_hw_params *params, 
@@ -1637,7 +1666,8 @@ static int _snd_pcm_hw_param_last(struct snd_pcm_hw_params *params,
  *
  * Inside configuration space defined by @params remove from @var all
  * values < maximum. Reduce configuration space accordingly.
- * Return the maximum.
+ *
+ * Return: The maximum, or a negative error code on failure.
  */
 int snd_pcm_hw_param_last(struct snd_pcm_substream *pcm, 
 			  struct snd_pcm_hw_params *params,
@@ -1665,6 +1695,8 @@ EXPORT_SYMBOL(snd_pcm_hw_param_last);
  * The configuration chosen is that obtained fixing in this order:
  * first access, first format, first subformat, min channels,
  * min rate, min period time, max buffer size, min tick time
+ *
+ * Return: Zero if successful, or a negative error code on failure.
  */
 int snd_pcm_hw_params_choose(struct snd_pcm_substream *pcm,
 			     struct snd_pcm_hw_params *params)
@@ -1771,7 +1803,7 @@ static int snd_pcm_lib_ioctl_fifo_size(struct snd_pcm_substream *substream,
  * Processes the generic ioctl commands for PCM.
  * Can be passed as the ioctl callback for PCM ops.
  *
- * Returns zero if successful, or a negative error code on failure.
+ * Return: Zero if successful, or a negative error code on failure.
  */
 int snd_pcm_lib_ioctl(struct snd_pcm_substream *substream,
 		      unsigned int cmd, void *arg)
@@ -2510,7 +2542,7 @@ static void pcm_chmap_ctl_private_free(struct snd_kcontrol *kcontrol)
  * @info_ret: store struct snd_pcm_chmap instance if non-NULL
  *
  * Create channel-mapping control elements assigned to the given PCM stream(s).
- * Returns zero if succeed, or a negative error value.
+ * Return: Zero if successful, or a negative error value.
  */
 int snd_pcm_add_chmap_ctls(struct snd_pcm *pcm, int stream,
 			   const struct snd_pcm_chmap_elem *chmap,
diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c
index 69e01c4..0af622c 100644
--- a/sound/core/pcm_memory.c
+++ b/sound/core/pcm_memory.c
@@ -95,7 +95,7 @@ static void snd_pcm_lib_preallocate_dma_free(struct snd_pcm_substream *substream
  *
  * Releases the pre-allocated buffer of the given substream.
  *
- * Returns zero if successful, or a negative error code on failure.
+ * Return: Zero if successful, or a negative error code on failure.
  */
 int snd_pcm_lib_preallocate_free(struct snd_pcm_substream *substream)
 {
@@ -115,7 +115,7 @@ int snd_pcm_lib_preallocate_free(struct snd_pcm_substream *substream)
  *
  * Releases all the pre-allocated buffers on the given pcm.
  *
- * Returns zero if successful, or a negative error code on failure.
+ * Return: Zero if successful, or a negative error code on failure.
  */
 int snd_pcm_lib_preallocate_free_for_all(struct snd_pcm *pcm)
 {
@@ -265,7 +265,7 @@ static int snd_pcm_lib_preallocate_pages1(struct snd_pcm_substream *substream,
  * destruction time.  The dma_buf_id must be unique for all systems
  * (in the same DMA buffer type) e.g. using snd_dma_pci_buf_id().
  *
- * Returns zero if successful, or a negative error code on failure.
+ * Return: Zero if successful, or a negative error code on failure.
  */
 int snd_pcm_lib_preallocate_pages(struct snd_pcm_substream *substream,
 				  int type, struct device *data,
@@ -289,7 +289,7 @@ EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages);
  * Do pre-allocation to all substreams of the given pcm for the
  * specified DMA type.
  *
- * Returns zero if successful, or a negative error code on failure.
+ * Return: Zero if successful, or a negative error code on failure.
  */
 int snd_pcm_lib_preallocate_pages_for_all(struct snd_pcm *pcm,
 					  int type, void *data,
@@ -313,8 +313,9 @@ EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages_for_all);
  * @substream: the pcm substream instance
  * @offset: the buffer offset
  *
- * Returns the page struct at the given buffer offset.
  * Used as the page callback of PCM ops.
+ *
+ * Return: The page struct at the given buffer offset. %NULL on failure.
  */
 struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream, unsigned long offset)
 {
@@ -337,7 +338,7 @@ EXPORT_SYMBOL(snd_pcm_sgbuf_ops_page);
  * Allocates the DMA buffer on the BUS type given earlier to
  * snd_pcm_lib_preallocate_xxx_pages().
  *
- * Returns 1 if the buffer is changed, 0 if not changed, or a negative
+ * Return: 1 if the buffer is changed, 0 if not changed, or a negative
  * code on failure.
  */
 int snd_pcm_lib_malloc_pages(struct snd_pcm_substream *substream, size_t size)
@@ -390,7 +391,7 @@ EXPORT_SYMBOL(snd_pcm_lib_malloc_pages);
  *
  * Releases the DMA buffer allocated via snd_pcm_lib_malloc_pages().
  *
- * Returns zero if successful, or a negative error code on failure.
+ * Return: Zero if successful, or a negative error code on failure.
  */
 int snd_pcm_lib_free_pages(struct snd_pcm_substream *substream)
 {
@@ -437,6 +438,8 @@ EXPORT_SYMBOL(_snd_pcm_lib_alloc_vmalloc_buffer);
  * snd_pcm_lib_free_vmalloc_buffer - free vmalloc buffer
  * @substream: the substream with a buffer allocated by
  *	snd_pcm_lib_alloc_vmalloc_buffer()
+ *
+ * Return: Zero if successful, or a negative error code on failure.
  */
 int snd_pcm_lib_free_vmalloc_buffer(struct snd_pcm_substream *substream)
 {
@@ -458,6 +461,8 @@ EXPORT_SYMBOL(snd_pcm_lib_free_vmalloc_buffer);
  * @offset: offset in the buffer
  *
  * This function is to be used as the page callback in the PCM ops.
+ *
+ * Return: The page struct, or %NULL on failure.
  */
 struct page *snd_pcm_lib_get_vmalloc_page(struct snd_pcm_substream *substream,
 					  unsigned long offset)
diff --git a/sound/core/pcm_misc.c b/sound/core/pcm_misc.c
index d4fc1bf..b875b19 100644
--- a/sound/core/pcm_misc.c
+++ b/sound/core/pcm_misc.c
@@ -213,7 +213,7 @@ static struct pcm_format_data pcm_formats[(INT)SNDRV_PCM_FORMAT_LAST+1] = {
  * snd_pcm_format_signed - Check the PCM format is signed linear
  * @format: the format to check
  *
- * Returns 1 if the given PCM format is signed linear, 0 if unsigned
+ * Return: 1 if the given PCM format is signed linear, 0 if unsigned
  * linear, and a negative error code for non-linear formats.
  */
 int snd_pcm_format_signed(snd_pcm_format_t format)
@@ -232,7 +232,7 @@ EXPORT_SYMBOL(snd_pcm_format_signed);
  * snd_pcm_format_unsigned - Check the PCM format is unsigned linear
  * @format: the format to check
  *
- * Returns 1 if the given PCM format is unsigned linear, 0 if signed
+ * Return: 1 if the given PCM format is unsigned linear, 0 if signed
  * linear, and a negative error code for non-linear formats.
  */
 int snd_pcm_format_unsigned(snd_pcm_format_t format)
@@ -251,7 +251,7 @@ EXPORT_SYMBOL(snd_pcm_format_unsigned);
  * snd_pcm_format_linear - Check the PCM format is linear
  * @format: the format to check
  *
- * Returns 1 if the given PCM format is linear, 0 if not.
+ * Return: 1 if the given PCM format is linear, 0 if not.
  */
 int snd_pcm_format_linear(snd_pcm_format_t format)
 {
@@ -264,7 +264,7 @@ EXPORT_SYMBOL(snd_pcm_format_linear);
  * snd_pcm_format_little_endian - Check the PCM format is little-endian
  * @format: the format to check
  *
- * Returns 1 if the given PCM format is little-endian, 0 if
+ * Return: 1 if the given PCM format is little-endian, 0 if
  * big-endian, or a negative error code if endian not specified.
  */
 int snd_pcm_format_little_endian(snd_pcm_format_t format)
@@ -283,7 +283,7 @@ EXPORT_SYMBOL(snd_pcm_format_little_endian);
  * snd_pcm_format_big_endian - Check the PCM format is big-endian
  * @format: the format to check
  *
- * Returns 1 if the given PCM format is big-endian, 0 if
+ * Return: 1 if the given PCM format is big-endian, 0 if
  * little-endian, or a negative error code if endian not specified.
  */
 int snd_pcm_format_big_endian(snd_pcm_format_t format)
@@ -302,7 +302,7 @@ EXPORT_SYMBOL(snd_pcm_format_big_endian);
  * snd_pcm_format_width - return the bit-width of the format
  * @format: the format to check
  *
- * Returns the bit-width of the format, or a negative error code
+ * Return: The bit-width of the format, or a negative error code
  * if unknown format.
  */
 int snd_pcm_format_width(snd_pcm_format_t format)
@@ -321,7 +321,7 @@ EXPORT_SYMBOL(snd_pcm_format_width);
  * snd_pcm_format_physical_width - return the physical bit-width of the format
  * @format: the format to check
  *
- * Returns the physical bit-width of the format, or a negative error code
+ * Return: The physical bit-width of the format, or a negative error code
  * if unknown format.
  */
 int snd_pcm_format_physical_width(snd_pcm_format_t format)
@@ -341,7 +341,7 @@ EXPORT_SYMBOL(snd_pcm_format_physical_width);
  * @format: the format to check
  * @samples: sampling rate
  *
- * Returns the byte size of the given samples for the format, or a
+ * Return: The byte size of the given samples for the format, or a
  * negative error code if unknown format.
  */
 ssize_t snd_pcm_format_size(snd_pcm_format_t format, size_t samples)
@@ -358,7 +358,7 @@ EXPORT_SYMBOL(snd_pcm_format_size);
  * snd_pcm_format_silence_64 - return the silent data in 8 bytes array
  * @format: the format to check
  *
- * Returns the format pattern to fill or NULL if error.
+ * Return: The format pattern to fill or %NULL if error.
  */
 const unsigned char *snd_pcm_format_silence_64(snd_pcm_format_t format)
 {
@@ -379,7 +379,7 @@ EXPORT_SYMBOL(snd_pcm_format_silence_64);
  *
  * Sets the silence data on the buffer for the given samples.
  *
- * Returns zero if successful, or a negative error code on failure.
+ * Return: Zero if successful, or a negative error code on failure.
  */
 int snd_pcm_format_set_silence(snd_pcm_format_t format, void *data, unsigned int samples)
 {
@@ -449,7 +449,7 @@ EXPORT_SYMBOL(snd_pcm_format_set_silence);
  * Determines the rate_min and rate_max fields from the rates bits of
  * the given runtime->hw.
  *
- * Returns zero if successful.
+ * Return: Zero if successful.
  */
 int snd_pcm_limit_hw_rates(struct snd_pcm_runtime *runtime)
 {
@@ -475,7 +475,7 @@ EXPORT_SYMBOL(snd_pcm_limit_hw_rates);
  * snd_pcm_rate_to_rate_bit - converts sample rate to SNDRV_PCM_RATE_xxx bit
  * @rate: the sample rate to convert
  *
- * Returns the SNDRV_PCM_RATE_xxx flag that corresponds to the given rate, or
+ * Return: The SNDRV_PCM_RATE_xxx flag that corresponds to the given rate, or
  * SNDRV_PCM_RATE_KNOT for an unknown rate.
  */
 unsigned int snd_pcm_rate_to_rate_bit(unsigned int rate)
@@ -493,8 +493,8 @@ EXPORT_SYMBOL(snd_pcm_rate_to_rate_bit);
  * snd_pcm_rate_bit_to_rate - converts SNDRV_PCM_RATE_xxx bit to sample rate
  * @rate_bit: the rate bit to convert
  *
- * Returns the sample rate that corresponds to the given SNDRV_PCM_RATE_xxx flag
- * or 0 for an unknown rate bit
+ * Return: The sample rate that corresponds to the given SNDRV_PCM_RATE_xxx flag
+ * or 0 for an unknown rate bit.
  */
 unsigned int snd_pcm_rate_bit_to_rate(unsigned int rate_bit)
 {
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 71ae86c..479e0a5 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -25,7 +25,7 @@
 #include <linux/slab.h>
 #include <linux/time.h>
 #include <linux/pm_qos.h>
-#include <linux/uio.h>
+#include <linux/aio.h>
 #include <linux/dma-mapping.h>
 #include <sound/core.h>
 #include <sound/control.h>
@@ -898,6 +898,8 @@ static struct action_ops snd_pcm_action_start = {
 /**
  * snd_pcm_start - start all linked streams
  * @substream: the PCM substream instance
+ *
+ * Return: Zero if successful, or a negative error code.
  */
 int snd_pcm_start(struct snd_pcm_substream *substream)
 {
@@ -951,6 +953,8 @@ static struct action_ops snd_pcm_action_stop = {
  * @state: PCM state after stopping the stream
  *
  * The state of each stream is then changed to the given state unconditionally.
+ *
+ * Return: Zero if succesful, or a negative error code.
  */
 int snd_pcm_stop(struct snd_pcm_substream *substream, snd_pcm_state_t state)
 {
@@ -965,6 +969,8 @@ EXPORT_SYMBOL(snd_pcm_stop);
  *
  * After stopping, the state is changed to SETUP.
  * Unlike snd_pcm_stop(), this affects only the given stream.
+ *
+ * Return: Zero if succesful, or a negative error code.
  */
 int snd_pcm_drain_done(struct snd_pcm_substream *substream)
 {
@@ -1098,6 +1104,9 @@ static struct action_ops snd_pcm_action_suspend = {
  * @substream: the PCM substream
  *
  * After this call, all streams are changed to SUSPENDED state.
+ *
+ * Return: Zero if successful (or @substream is %NULL), or a negative error
+ * code.
  */
 int snd_pcm_suspend(struct snd_pcm_substream *substream)
 {
@@ -1120,6 +1129,8 @@ EXPORT_SYMBOL(snd_pcm_suspend);
  * @pcm: the PCM instance
  *
  * After this call, all streams are changed to SUSPENDED state.
+ *
+ * Return: Zero if successful (or @pcm is %NULL), or a negative error code.
  */
 int snd_pcm_suspend_all(struct snd_pcm *pcm)
 {
@@ -1343,6 +1354,8 @@ static struct action_ops snd_pcm_action_prepare = {
  * snd_pcm_prepare - prepare the PCM substream to be triggerable
  * @substream: the PCM substream instance
  * @file: file to refer f_flags
+ *
+ * Return: Zero if successful, or a negative error code.
  */
 static int snd_pcm_prepare(struct snd_pcm_substream *substream,
 			   struct file *file)
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index 1bb95ae..7b596b5 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -863,7 +863,7 @@ static int snd_rawmidi_control_ioctl(struct snd_card *card,
  *
  * Reads the data from the internal buffer.
  *
- * Returns the size of read data, or a negative error code on failure.
+ * Return: The size of read data, or a negative error code on failure.
  */
 int snd_rawmidi_receive(struct snd_rawmidi_substream *substream,
 			const unsigned char *buffer, int count)
@@ -1024,8 +1024,8 @@ static ssize_t snd_rawmidi_read(struct file *file, char __user *buf, size_t coun
 /**
  * snd_rawmidi_transmit_empty - check whether the output buffer is empty
  * @substream: the rawmidi substream
- * 
- * Returns 1 if the internal output buffer is empty, 0 if not.
+ *
+ * Return: 1 if the internal output buffer is empty, 0 if not.
  */
 int snd_rawmidi_transmit_empty(struct snd_rawmidi_substream *substream)
 {
@@ -1055,7 +1055,7 @@ int snd_rawmidi_transmit_empty(struct snd_rawmidi_substream *substream)
  * and call snd_rawmidi_transmit_ack() after the transmission is
  * finished.
  *
- * Returns the size of copied data, or a negative error code on failure.
+ * Return: The size of copied data, or a negative error code on failure.
  */
 int snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream,
 			      unsigned char *buffer, int count)
@@ -1107,7 +1107,7 @@ int snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream,
  * the given size and updates the condition.
  * Call after the transmission is finished.
  *
- * Returns the advanced size if successful, or a negative error code on failure.
+ * Return: The advanced size if successful, or a negative error code on failure.
  */
 int snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count)
 {
@@ -1140,7 +1140,7 @@ int snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count)
  * 
  * Copies data from the buffer to the device and advances the pointer.
  *
- * Returns the copied size if successful, or a negative error code on failure.
+ * Return: The copied size if successful, or a negative error code on failure.
  */
 int snd_rawmidi_transmit(struct snd_rawmidi_substream *substream,
 			 unsigned char *buffer, int count)
@@ -1438,7 +1438,7 @@ static int snd_rawmidi_alloc_substreams(struct snd_rawmidi *rmidi,
  * Creates a new rawmidi instance.
  * Use snd_rawmidi_set_ops() to set the operators to the new instance.
  *
- * Returns zero if successful, or a negative error code on failure.
+ * Return: Zero if successful, or a negative error code on failure.
  */
 int snd_rawmidi_new(struct snd_card *card, char *id, int device,
 		    int output_count, int input_count,
diff --git a/sound/core/sound.c b/sound/core/sound.c
index 70ccdab..f002bd9 100644
--- a/sound/core/sound.c
+++ b/sound/core/sound.c
@@ -102,6 +102,9 @@ static void snd_request_other(int minor)
  * This function increments the reference counter of the card instance
  * if an associated instance with the given minor number and type is found.
  * The caller must call snd_card_unref() appropriately later.
+ *
+ * Return: The user data pointer if the specified device is found. %NULL
+ * otherwise.
  */
 void *snd_lookup_minor_data(unsigned int minor, int type)
 {
@@ -261,7 +264,7 @@ static int snd_kernel_minor(int type, struct snd_card *card, int dev)
  * Registers an ALSA device file for the given card.
  * The operators have to be set in reg parameter.
  *
- * Returns zero if successful, or a negative error code on failure.
+ * Return: Zero if successful, or a negative error code on failure.
  */
 int snd_register_device_for_dev(int type, struct snd_card *card, int dev,
 				const struct file_operations *f_ops,
@@ -339,7 +342,7 @@ static int find_snd_minor(int type, struct snd_card *card, int dev)
  * Unregisters the device file already registered via
  * snd_register_device().
  *
- * Returns zero if sucecessful, or a negative error code on failure
+ * Return: Zero if successful, or a negative error code on failure.
  */
 int snd_unregister_device(int type, struct snd_card *card, int dev)
 {
diff --git a/sound/core/vmaster.c b/sound/core/vmaster.c
index 0097f36..02f90b4 100644
--- a/sound/core/vmaster.c
+++ b/sound/core/vmaster.c
@@ -365,8 +365,7 @@ static void master_free(struct snd_kcontrol *kcontrol)
  * @name: name string of the control element to create
  * @tlv: optional TLV int array for dB information
  *
- * Creates a virtual matster control with the given name string.
- * Returns the created control element, or NULL for errors (ENOMEM).
+ * Creates a virtual master control with the given name string.
  *
  * After creating a vmaster element, you can add the slave controls
  * via snd_ctl_add_slave() or snd_ctl_add_slave_uncached().
@@ -375,6 +374,8 @@ static void master_free(struct snd_kcontrol *kcontrol)
  * for dB scale of the master control.  It should be a single element
  * with #SNDRV_CTL_TLVT_DB_SCALE, #SNDRV_CTL_TLV_DB_MINMAX or
  * #SNDRV_CTL_TLVT_DB_MINMAX_MUTE type, and should be the max 0dB.
+ *
+ * Return: The created control element, or %NULL for errors (ENOMEM).
  */
 struct snd_kcontrol *snd_ctl_make_virtual_master(char *name,
 						 const unsigned int *tlv)
@@ -426,6 +427,8 @@ EXPORT_SYMBOL(snd_ctl_make_virtual_master);
  *
  * Adds the given hook to the vmaster control element so that it's called
  * at each time when the value is changed.
+ *
+ * Return: Zero.
  */
 int snd_ctl_add_vmaster_hook(struct snd_kcontrol *kcontrol,
 			     void (*hook)(void *private_data, int),
diff --git a/sound/drivers/mpu401/mpu401_uart.c b/sound/drivers/mpu401/mpu401_uart.c
index 4608c2c..e3a90d0 100644
--- a/sound/drivers/mpu401/mpu401_uart.c
+++ b/sound/drivers/mpu401/mpu401_uart.c
@@ -129,6 +129,8 @@ static void _snd_mpu401_uart_interrupt(struct snd_mpu401 *mpu)
  * @dev_id: mpu401 instance
  *
  * Processes the interrupt for MPU401-UART i/o.
+ *
+ * Return: %IRQ_HANDLED if the interrupt was handled. %IRQ_NONE otherwise.
  */
 irqreturn_t snd_mpu401_uart_interrupt(int irq, void *dev_id)
 {
@@ -148,6 +150,8 @@ EXPORT_SYMBOL(snd_mpu401_uart_interrupt);
  * @dev_id: mpu401 instance
  *
  * Processes the interrupt for MPU401-UART output.
+ *
+ * Return: %IRQ_HANDLED if the interrupt was handled. %IRQ_NONE otherwise.
  */
 irqreturn_t snd_mpu401_uart_interrupt_tx(int irq, void *dev_id)
 {
@@ -519,7 +523,7 @@ static void snd_mpu401_uart_free(struct snd_rawmidi *rmidi)
  * not the mpu401 instance itself.  To access to the mpu401 instance,
  * cast from rawmidi->private_data (with struct snd_mpu401 magic-cast).
  *
- * Returns zero if successful, or a negative error code.
+ * Return: Zero if successful, or a negative error code.
  */
 int snd_mpu401_uart_new(struct snd_card *card, int device,
 			unsigned short hardware,
diff --git a/sound/i2c/other/tea575x-tuner.c b/sound/i2c/other/tea575x-tuner.c
index 3c6c1e3..8a36a1d 100644
--- a/sound/i2c/other/tea575x-tuner.c
+++ b/sound/i2c/other/tea575x-tuner.c
@@ -306,7 +306,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
 }
 
 static int vidioc_s_tuner(struct file *file, void *priv,
-					struct v4l2_tuner *v)
+					const struct v4l2_tuner *v)
 {
 	struct snd_tea575x *tea = video_drvdata(file);
 	u32 orig_val = tea->val;
@@ -336,7 +336,7 @@ static int vidioc_g_frequency(struct file *file, void *priv,
 }
 
 static int vidioc_s_frequency(struct file *file, void *priv,
-					struct v4l2_frequency *f)
+					const struct v4l2_frequency *f)
 {
 	struct snd_tea575x *tea = video_drvdata(file);
 
@@ -350,7 +350,7 @@ static int vidioc_s_frequency(struct file *file, void *priv,
 	else
 		tea->band = BAND_FM;
 
-	tea->freq = clamp(f->frequency, bands[tea->band].rangelow,
+	tea->freq = clamp_t(u32, f->frequency, bands[tea->band].rangelow,
 					bands[tea->band].rangehigh);
 	snd_tea575x_set_freq(tea);
 	return 0;
diff --git a/sound/oss/sb_common.c b/sound/oss/sb_common.c
index 7d42c54..851a1da 100644
--- a/sound/oss/sb_common.c
+++ b/sound/oss/sb_common.c
@@ -626,13 +626,12 @@ int sb_dsp_detect(struct address_info *hw_config, int pci, int pciio, struct sb_
 	 */
 
 
-	detected_devc = kmalloc(sizeof(sb_devc), GFP_KERNEL);
+	detected_devc = kmemdup(devc, sizeof(sb_devc), GFP_KERNEL);
 	if (detected_devc == NULL)
 	{
 		printk(KERN_ERR "sb: Can't allocate memory for device information\n");
 		return 0;
 	}
-	memcpy(detected_devc, devc, sizeof(sb_devc));
 	MDB(printk(KERN_INFO "SB %d.%02d detected OK (%x)\n", devc->major, devc->minor, hw_config->io_base));
 	return 1;
 }
diff --git a/sound/oss/uart401.c b/sound/oss/uart401.c
index 8e514a6..5433c6f 100644
--- a/sound/oss/uart401.c
+++ b/sound/oss/uart401.c
@@ -352,23 +352,26 @@ int probe_uart401(struct address_info *hw_config, struct module *owner)
 		goto cleanup_irq;
 	}
 	conf_printf(name, hw_config);
-	midi_devs[devc->my_dev] = kmalloc(sizeof(struct midi_operations), GFP_KERNEL);
+	midi_devs[devc->my_dev] = kmemdup(&uart401_operations,
+					  sizeof(struct midi_operations),
+					  GFP_KERNEL);
 	if (!midi_devs[devc->my_dev]) {
 		printk(KERN_ERR "uart401: Failed to allocate memory\n");
 		goto cleanup_unload_mididev;
 	}
-	memcpy(midi_devs[devc->my_dev], &uart401_operations, sizeof(struct midi_operations));
 
 	if (owner)
 		midi_devs[devc->my_dev]->owner = owner;
 	
 	midi_devs[devc->my_dev]->devc = devc;
-	midi_devs[devc->my_dev]->converter = kmalloc(sizeof(struct synth_operations), GFP_KERNEL);
+	midi_devs[devc->my_dev]->converter = kmemdup(&std_midi_synth,
+						     sizeof(struct synth_operations),
+						     GFP_KERNEL);
+
 	if (!midi_devs[devc->my_dev]->converter) {
 		printk(KERN_WARNING "uart401: Failed to allocate memory\n");
 		goto cleanup_midi_devs;
 	}
-	memcpy(midi_devs[devc->my_dev]->converter, &std_midi_synth, sizeof(struct synth_operations));
 	strcpy(midi_devs[devc->my_dev]->info.name, name);
 	midi_devs[devc->my_dev]->converter->id = "UART401";
 	midi_devs[devc->my_dev]->converter->midi_dev = devc->my_dev;
diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c
index 8b0f996..d37c683 100644
--- a/sound/pci/ac97/ac97_codec.c
+++ b/sound/pci/ac97/ac97_codec.c
@@ -299,7 +299,7 @@ EXPORT_SYMBOL(snd_ac97_write);
  * Reads a value from the given register.  This will invoke the read
  * callback directly after the register check.
  *
- * Returns the read value.
+ * Return: The read value.
  */
 unsigned short snd_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
 {
@@ -352,7 +352,7 @@ EXPORT_SYMBOL(snd_ac97_write_cache);
  * Compares the value with the register cache and updates the value
  * only when the value is changed.
  *
- * Returns 1 if the value is changed, 0 if no change, or a negative
+ * Return: 1 if the value is changed, 0 if no change, or a negative
  * code on failure.
  */
 int snd_ac97_update(struct snd_ac97 *ac97, unsigned short reg, unsigned short value)
@@ -384,7 +384,7 @@ EXPORT_SYMBOL(snd_ac97_update);
  * Updates the masked-bits on the given register only when the value
  * is changed.
  *
- * Returns 1 if the bits are changed, 0 if no change, or a negative
+ * Return: 1 if the bits are changed, 0 if no change, or a negative
  * code on failure.
  */
 int snd_ac97_update_bits(struct snd_ac97 *ac97, unsigned short reg, unsigned short mask, unsigned short value)
@@ -1836,7 +1836,7 @@ void snd_ac97_get_name(struct snd_ac97 *ac97, unsigned int id, char *name, int m
  * snd_ac97_get_short_name - retrieve codec name
  * @ac97: the codec instance
  *
- * Returns the short identifying name of the codec.
+ * Return: The short identifying name of the codec.
  */
 const char *snd_ac97_get_short_name(struct snd_ac97 *ac97)
 {
@@ -1910,7 +1910,7 @@ static int ac97_reset_wait(struct snd_ac97 *ac97, int timeout, int with_modem)
  * The AC97 bus instance is registered as a low-level device, so you don't
  * have to release it manually.
  *
- * Returns zero if successful, or a negative error code on failure.
+ * Return: Zero if successful, or a negative error code on failure.
  */
 int snd_ac97_bus(struct snd_card *card, int num, struct snd_ac97_bus_ops *ops,
 		 void *private_data, struct snd_ac97_bus **rbus)
@@ -2006,7 +2006,7 @@ static void do_update_power(struct work_struct *work)
  * The ac97 instance is registered as a low-level device, so you don't
  * have to release it manually.
  *
- * Returns zero if successful, or a negative error code on failure.
+ * Return: Zero if successful, or a negative error code on failure.
  */
 int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template, struct snd_ac97 **rac97)
 {
@@ -2373,6 +2373,8 @@ static struct ac97_power_reg power_regs[PWIDX_SIZE] = {
  * @powerup: non-zero when power up the part
  *
  * Update the AC97 powerdown register bits of the given part.
+ *
+ * Return: Zero.
  */
 int snd_ac97_update_power(struct snd_ac97 *ac97, int reg, int powerup)
 {
@@ -2885,7 +2887,7 @@ static int apply_quirk_str(struct snd_ac97 *ac97, const char *typestr)
  * headphone (true line-out) control as "Master".
  * The quirk-list must be terminated with a zero-filled entry.
  *
- * Returns zero if successful, or a negative error code on failure.
+ * Return: Zero if successful, or a negative error code on failure.
  */
 
 int snd_ac97_tune_hardware(struct snd_ac97 *ac97, struct ac97_quirk *quirk, const char *override)
diff --git a/sound/pci/ac97/ac97_pcm.c b/sound/pci/ac97/ac97_pcm.c
index f1488fc..eab0fc9 100644
--- a/sound/pci/ac97/ac97_pcm.c
+++ b/sound/pci/ac97/ac97_pcm.c
@@ -253,7 +253,7 @@ static int set_spdif_rate(struct snd_ac97 *ac97, unsigned short rate)
  * AC97_SPDIF is accepted as a pseudo register to modify the SPDIF
  * status bits.
  *
- * Returns zero if successful, or a negative error code on failure.
+ * Return: Zero if successful, or a negative error code on failure.
  */
 int snd_ac97_set_rate(struct snd_ac97 *ac97, int reg, unsigned int rate)
 {
@@ -440,6 +440,8 @@ static unsigned int get_rates(struct ac97_pcm *pcm, unsigned int cidx, unsigned
  * It assigns available AC97 slots for given PCMs. If none or only
  * some slots are available, pcm->xxx.slots and pcm->xxx.rslots[] members
  * are reduced and might be zero.
+ *
+ * Return: Zero if successful, or a negative error code on failure.
  */
 int snd_ac97_pcm_assign(struct snd_ac97_bus *bus,
 			unsigned short pcms_count,
@@ -562,6 +564,8 @@ EXPORT_SYMBOL(snd_ac97_pcm_assign);
  * @slots: a subset of allocated slots (snd_ac97_pcm_assign) for this pcm
  *
  * It locks the specified slots and sets the given rate to AC97 registers.
+ *
+ * Return: Zero if successful, or a negative error code on failure.
  */
 int snd_ac97_pcm_open(struct ac97_pcm *pcm, unsigned int rate,
 		      enum ac97_pcm_cfg cfg, unsigned short slots)
@@ -644,6 +648,8 @@ EXPORT_SYMBOL(snd_ac97_pcm_open);
  * @pcm: the ac97 pcm instance
  *
  * It frees the locked AC97 slots.
+ *
+ * Return: Zero.
  */
 int snd_ac97_pcm_close(struct ac97_pcm *pcm)
 {
@@ -718,6 +724,8 @@ static int double_rate_hw_constraint_channels(struct snd_pcm_hw_params *params,
  *
  * Installs the hardware constraint rules to prevent using double rates and
  * more than two channels at the same time.
+ *
+ * Return: Zero if successful, or a negative error code on failure.
  */
 int snd_ac97_pcm_double_rate_rules(struct snd_pcm_runtime *runtime)
 {
diff --git a/sound/pci/hda/hda_auto_parser.c b/sound/pci/hda/hda_auto_parser.c
index a3ea76a..6b173b3 100644
--- a/sound/pci/hda/hda_auto_parser.c
+++ b/sound/pci/hda/hda_auto_parser.c
@@ -260,6 +260,22 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec,
 		}
 	}
 
+	/* Take first mic to be a headset mic pin */
+	if (cond_flags & HDA_PINCFG_HEADSET_MIC) {
+		for (i = 0; i < cfg->num_inputs; i++) {
+			int attr;
+			unsigned int def_conf;
+			if (cfg->inputs[i].type != AUTO_PIN_MIC)
+				continue;
+			def_conf = snd_hda_codec_get_pincfg(codec, cfg->inputs[i].pin);
+			attr = snd_hda_get_input_pin_attr(def_conf);
+			if (attr <= INPUT_PIN_ATTR_DOCK)
+				continue;
+			cfg->inputs[i].is_headset_mic = 1;
+			break;
+		}
+	}
+
 	/* FIX-UP:
 	 * If no line-out is defined but multiple HPs are found,
 	 * some of them might be the real line-outs.
@@ -388,6 +404,7 @@ EXPORT_SYMBOL_HDA(snd_hda_get_input_pin_attr);
  */
 
 static const char *hda_get_input_pin_label(struct hda_codec *codec,
+					   const struct auto_pin_cfg_item *item,
 					   hda_nid_t pin, bool check_location)
 {
 	unsigned int def_conf;
@@ -400,6 +417,8 @@ static const char *hda_get_input_pin_label(struct hda_codec *codec,
 
 	switch (get_defcfg_device(def_conf)) {
 	case AC_JACK_MIC_IN:
+		if (item && item->is_headset_mic)
+			return "Headset Mic";
 		if (!check_location)
 			return "Mic";
 		attr = snd_hda_get_input_pin_attr(def_conf);
@@ -480,7 +499,8 @@ const char *hda_get_autocfg_input_label(struct hda_codec *codec,
 		has_multiple_pins = 1;
 	if (has_multiple_pins && type == AUTO_PIN_MIC)
 		has_multiple_pins &= check_mic_location_need(codec, cfg, input);
-	return hda_get_input_pin_label(codec, cfg->inputs[input].pin,
+	return hda_get_input_pin_label(codec, &cfg->inputs[input],
+				       cfg->inputs[input].pin,
 				       has_multiple_pins);
 }
 EXPORT_SYMBOL_HDA(hda_get_autocfg_input_label);
@@ -649,7 +669,7 @@ int snd_hda_get_pin_label(struct hda_codec *codec, hda_nid_t nid,
 			}
 		}
 		if (!name)
-			name = hda_get_input_pin_label(codec, nid, true);
+			name = hda_get_input_pin_label(codec, NULL, nid, true);
 		break;
 	}
 	if (!name)
diff --git a/sound/pci/hda/hda_auto_parser.h b/sound/pci/hda/hda_auto_parser.h
index f748071..c7826ce 100644
--- a/sound/pci/hda/hda_auto_parser.h
+++ b/sound/pci/hda/hda_auto_parser.h
@@ -36,6 +36,7 @@ enum {
 struct auto_pin_cfg_item {
 	hda_nid_t pin;
 	int type;
+	unsigned int is_headset_mic:1;
 };
 
 struct auto_pin_cfg;
@@ -80,6 +81,7 @@ struct auto_pin_cfg {
 /* bit-flags for snd_hda_parse_pin_def_config() behavior */
 #define HDA_PINCFG_NO_HP_FIXUP	(1 << 0) /* no HP-split */
 #define HDA_PINCFG_NO_LO_FIXUP	(1 << 1) /* don't take other outs as LO */
+#define HDA_PINCFG_HEADSET_MIC  (1 << 2) /* Take first mic as headset mic */
 
 int snd_hda_parse_pin_defcfg(struct hda_codec *codec,
 			     struct auto_pin_cfg *cfg,
diff --git a/sound/pci/hda/hda_beep.c b/sound/pci/hda/hda_beep.c
index 0849aac..63c9909 100644
--- a/sound/pci/hda/hda_beep.c
+++ b/sound/pci/hda/hda_beep.c
@@ -39,13 +39,23 @@ static void snd_hda_generate_beep(struct work_struct *work)
 	struct hda_beep *beep =
 		container_of(work, struct hda_beep, beep_work);
 	struct hda_codec *codec = beep->codec;
+	int tone;
 
 	if (!beep->enabled)
 		return;
 
+	tone = beep->tone;
+	if (tone && !beep->playing) {
+		snd_hda_power_up(codec);
+		beep->playing = 1;
+	}
 	/* generate tone */
 	snd_hda_codec_write(codec, beep->nid, 0,
-			AC_VERB_SET_BEEP_CONTROL, beep->tone);
+			    AC_VERB_SET_BEEP_CONTROL, tone);
+	if (!tone && beep->playing) {
+		beep->playing = 0;
+		snd_hda_power_down(codec);
+	}
 }
 
 /* (non-standard) Linear beep tone calculation for IDT/STAC codecs 
@@ -115,14 +125,23 @@ static int snd_hda_beep_event(struct input_dev *dev, unsigned int type,
 	return 0;
 }
 
+static void turn_off_beep(struct hda_beep *beep)
+{
+	cancel_work_sync(&beep->beep_work);
+	if (beep->playing) {
+		/* turn off beep */
+		snd_hda_codec_write(beep->codec, beep->nid, 0,
+				    AC_VERB_SET_BEEP_CONTROL, 0);
+		beep->playing = 0;
+		snd_hda_power_down(beep->codec);
+	}
+}
+
 static void snd_hda_do_detach(struct hda_beep *beep)
 {
 	input_unregister_device(beep->dev);
 	beep->dev = NULL;
-	cancel_work_sync(&beep->beep_work);
-	/* turn off beep for sure */
-	snd_hda_codec_write(beep->codec, beep->nid, 0,
-				  AC_VERB_SET_BEEP_CONTROL, 0);
+	turn_off_beep(beep);
 }
 
 static int snd_hda_do_attach(struct hda_beep *beep)
@@ -170,12 +189,8 @@ int snd_hda_enable_beep_device(struct hda_codec *codec, int enable)
 	enable = !!enable;
 	if (beep->enabled != enable) {
 		beep->enabled = enable;
-		if (!enable) {
-			cancel_work_sync(&beep->beep_work);
-			/* turn off beep */
-			snd_hda_codec_write(beep->codec, beep->nid, 0,
-						  AC_VERB_SET_BEEP_CONTROL, 0);
-		}
+		if (!enable)
+			turn_off_beep(beep);
 		return 1;
 	}
 	return 0;
@@ -198,7 +213,7 @@ int snd_hda_attach_beep_device(struct hda_codec *codec, int nid)
 	snprintf(beep->phys, sizeof(beep->phys),
 		"card%d/codec#%d/beep0", codec->bus->card->number, codec->addr);
 	/* enable linear scale */
-	snd_hda_codec_write(codec, nid, 0,
+	snd_hda_codec_write_cache(codec, nid, 0,
 		AC_VERB_SET_DIGI_CONVERT_2, 0x01);
 
 	beep->nid = nid;
diff --git a/sound/pci/hda/hda_beep.h b/sound/pci/hda/hda_beep.h
index 4dc6933..cb88464 100644
--- a/sound/pci/hda/hda_beep.h
+++ b/sound/pci/hda/hda_beep.h
@@ -36,6 +36,7 @@ struct hda_beep {
 	hda_nid_t nid;
 	unsigned int enabled:1;
 	unsigned int linear_tone:1;	/* linear tone for IDT/STAC codec */
+	unsigned int playing:1;
 	struct work_struct beep_work; /* scheduled task for beep event */
 	struct mutex mutex;
 };
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index ecdf30e..e37b738 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -173,7 +173,7 @@ const char *snd_hda_get_jack_type(u32 cfg)
 		"Line Out", "Speaker", "HP Out", "CD",
 		"SPDIF Out", "Digital Out", "Modem Line", "Modem Hand",
 		"Line In", "Aux", "Mic", "Telephony",
-		"SPDIF In", "Digitial In", "Reserved", "Other"
+		"SPDIF In", "Digital In", "Reserved", "Other"
 	};
 
 	return jack_types[(cfg & AC_DEFCFG_DEVICE)
@@ -1300,8 +1300,6 @@ static bool snd_hda_codec_get_supported_ps(struct hda_codec *codec,
 
 static unsigned int hda_set_power_state(struct hda_codec *codec,
 				unsigned int power_state);
-static unsigned int default_power_filter(struct hda_codec *codec, hda_nid_t nid,
-					 unsigned int power_state);
 
 /**
  * snd_hda_codec_new - create a HDA codec
@@ -1422,7 +1420,6 @@ int snd_hda_codec_new(struct hda_bus *bus,
 #endif
 	codec->epss = snd_hda_codec_get_supported_ps(codec, fg,
 					AC_PWRST_EPSS);
-	codec->power_filter = default_power_filter;
 
 	/* power-up all before initialization */
 	hda_set_power_state(codec, AC_PWRST_D0);
@@ -3770,8 +3767,9 @@ static unsigned int hda_sync_power_state(struct hda_codec *codec,
 }
 
 /* don't power down the widget if it controls eapd and EAPD_BTLENABLE is set */
-static unsigned int default_power_filter(struct hda_codec *codec, hda_nid_t nid,
-					 unsigned int power_state)
+unsigned int snd_hda_codec_eapd_power_filter(struct hda_codec *codec,
+					     hda_nid_t nid,
+					     unsigned int power_state)
 {
 	if (power_state == AC_PWRST_D3 &&
 	    get_wcaps_type(get_wcaps(codec, nid)) == AC_WID_PIN &&
@@ -3783,6 +3781,7 @@ static unsigned int default_power_filter(struct hda_codec *codec, hda_nid_t nid,
 	}
 	return power_state;
 }
+EXPORT_SYMBOL_HDA(snd_hda_codec_eapd_power_filter);
 
 /*
  * set power state of the codec, and return the power state
@@ -3827,8 +3826,8 @@ static void sync_power_up_states(struct hda_codec *codec)
 	hda_nid_t nid = codec->start_nid;
 	int i;
 
-	/* don't care if no or standard filter is used */
-	if (!codec->power_filter || codec->power_filter == default_power_filter)
+	/* don't care if no filter is used */
+	if (!codec->power_filter)
 		return;
 
 	for (i = 0; i < codec->num_nodes; i++, nid++) {
@@ -5546,14 +5545,12 @@ 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 = krealloc(array->list, size, GFP_KERNEL);
+		nlist = krealloc(array->list, size, GFP_KERNEL | __GFP_ZERO);
 		if (!nlist)
 			return NULL;
-		memset(nlist + oldsize, 0, size - oldsize);
 		array->list = nlist;
 		array->alloced = num;
 	}
diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c
index 7dd8463..d0d7ac1 100644
--- a/sound/pci/hda/hda_eld.c
+++ b/sound/pci/hda/hda_eld.c
@@ -320,7 +320,7 @@ int snd_hdmi_get_eld(struct hda_codec *codec, hda_nid_t nid,
 		     unsigned char *buf, int *eld_size)
 {
 	int i;
-	int ret;
+	int ret = 0;
 	int size;
 
 	/*
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index 43c2ea5..f0a422f 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -34,6 +34,7 @@
 #include "hda_local.h"
 #include "hda_auto_parser.h"
 #include "hda_jack.h"
+#include "hda_beep.h"
 #include "hda_generic.h"
 
 
@@ -150,15 +151,25 @@ static void parse_user_hints(struct hda_codec *codec)
 	val = snd_hda_get_bool_hint(codec, "add_stereo_mix_input");
 	if (val >= 0)
 		spec->add_stereo_mix_input = !!val;
+	/* the following two are just for compatibility */
 	val = snd_hda_get_bool_hint(codec, "add_out_jack_modes");
 	if (val >= 0)
-		spec->add_out_jack_modes = !!val;
+		spec->add_jack_modes = !!val;
 	val = snd_hda_get_bool_hint(codec, "add_in_jack_modes");
 	if (val >= 0)
-		spec->add_in_jack_modes = !!val;
+		spec->add_jack_modes = !!val;
+	val = snd_hda_get_bool_hint(codec, "add_jack_modes");
+	if (val >= 0)
+		spec->add_jack_modes = !!val;
 	val = snd_hda_get_bool_hint(codec, "power_down_unused");
 	if (val >= 0)
 		spec->power_down_unused = !!val;
+	val = snd_hda_get_bool_hint(codec, "add_hp_mic");
+	if (val >= 0)
+		spec->hp_mic = !!val;
+	val = snd_hda_get_bool_hint(codec, "hp_mic_detect");
+	if (val >= 0)
+		spec->suppress_hp_mic_detect = !val;
 
 	if (!snd_hda_get_int_hint(codec, "mixer_nid", &val))
 		spec->mixer_nid = val;
@@ -996,7 +1007,7 @@ enum {
 	/* Primary DAC shared with main surrounds */
 	BAD_SHARED_SURROUND = 0x100,
 	/* No independent HP possible */
-	BAD_NO_INDEP_HP = 0x40,
+	BAD_NO_INDEP_HP = 0x10,
 	/* Primary DAC shared with main CLFE */
 	BAD_SHARED_CLFE = 0x10,
 	/* Primary DAC shared with extra surrounds */
@@ -1051,16 +1062,7 @@ static int assign_out_path_ctls(struct hda_codec *codec, struct nid_path *path)
 	return badness;
 }
 
-struct badness_table {
-	int no_primary_dac;	/* no primary DAC */
-	int no_dac;		/* no secondary DACs */
-	int shared_primary;	/* primary DAC is shared with main output */
-	int shared_surr;	/* secondary DAC shared with main or primary */
-	int shared_clfe;	/* third DAC shared with main or primary */
-	int shared_surr_main;	/* secondary DAC sahred with main/DAC0 */
-};
-
-static struct badness_table main_out_badness = {
+const struct badness_table hda_main_out_badness = {
 	.no_primary_dac = BAD_NO_PRIMARY_DAC,
 	.no_dac = BAD_NO_DAC,
 	.shared_primary = BAD_NO_PRIMARY_DAC,
@@ -1068,8 +1070,9 @@ static struct badness_table main_out_badness = {
 	.shared_clfe = BAD_SHARED_CLFE,
 	.shared_surr_main = BAD_SHARED_SURROUND,
 };
+EXPORT_SYMBOL_HDA(hda_main_out_badness);
 
-static struct badness_table extra_out_badness = {
+const struct badness_table hda_extra_out_badness = {
 	.no_primary_dac = BAD_NO_DAC,
 	.no_dac = BAD_NO_DAC,
 	.shared_primary = BAD_NO_EXTRA_DAC,
@@ -1077,6 +1080,7 @@ static struct badness_table extra_out_badness = {
 	.shared_clfe = BAD_SHARED_EXTRA_SURROUND,
 	.shared_surr_main = BAD_NO_EXTRA_SURR_DAC,
 };
+EXPORT_SYMBOL_HDA(hda_extra_out_badness);
 
 /* get the DAC of the primary output corresponding to the given array index */
 static hda_nid_t get_primary_out(struct hda_codec *codec, int idx)
@@ -1507,7 +1511,7 @@ static int fill_and_eval_dacs(struct hda_codec *codec,
 
 	badness += try_assign_dacs(codec, cfg->line_outs, cfg->line_out_pins,
 				   spec->private_dac_nids, spec->out_paths,
-				   &main_out_badness);
+				   spec->main_out_badness);
 
 	if (fill_mio_first &&
 	    cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
@@ -1522,7 +1526,7 @@ static int fill_and_eval_dacs(struct hda_codec *codec,
 		err = try_assign_dacs(codec, cfg->hp_outs, cfg->hp_pins,
 				      spec->multiout.hp_out_nid,
 				      spec->hp_paths,
-				      &extra_out_badness);
+				      spec->extra_out_badness);
 		if (err < 0)
 			return err;
 		badness += err;
@@ -1532,7 +1536,7 @@ static int fill_and_eval_dacs(struct hda_codec *codec,
 				      cfg->speaker_pins,
 				      spec->multiout.extra_out_nid,
 				      spec->speaker_paths,
-				      &extra_out_badness);
+				      spec->extra_out_badness);
 		if (err < 0)
 			return err;
 		badness += err;
@@ -1926,6 +1930,17 @@ static int create_speaker_out_ctls(struct hda_codec *codec)
  * independent HP controls
  */
 
+/* update HP auto-mute state too */
+static void update_hp_automute_hook(struct hda_codec *codec)
+{
+	struct hda_gen_spec *spec = codec->spec;
+
+	if (spec->hp_automute_hook)
+		spec->hp_automute_hook(codec, NULL);
+	else
+		snd_hda_gen_hp_automute(codec, NULL);
+}
+
 static int indep_hp_info(struct snd_kcontrol *kcontrol,
 			 struct snd_ctl_elem_info *uinfo)
 {
@@ -1986,12 +2001,7 @@ static int indep_hp_put(struct snd_kcontrol *kcontrol,
 		else
 			*dacp = spec->alt_dac_nid;
 
-		/* update HP auto-mute state too */
-		if (spec->hp_automute_hook)
-			spec->hp_automute_hook(codec, NULL);
-		else
-			snd_hda_gen_hp_automute(codec, NULL);
-
+		update_hp_automute_hook(codec);
 		ret = 1;
 	}
  unlock:
@@ -2240,63 +2250,94 @@ static int create_loopback_mixing_ctl(struct hda_codec *codec)
 static void call_update_outputs(struct hda_codec *codec);
 
 /* for shared I/O, change the pin-control accordingly */
-static void update_shared_mic_hp(struct hda_codec *codec, bool set_as_mic)
+static void update_hp_mic(struct hda_codec *codec, int adc_mux, bool force)
 {
 	struct hda_gen_spec *spec = codec->spec;
+	bool as_mic;
 	unsigned int val;
-	hda_nid_t pin = spec->autocfg.inputs[1].pin;
-	/* NOTE: this assumes that there are only two inputs, the
-	 * first is the real internal mic and the second is HP/mic jack.
-	 */
+	hda_nid_t pin;
 
-	val = snd_hda_get_default_vref(codec, pin);
+	pin = spec->hp_mic_pin;
+	as_mic = spec->cur_mux[adc_mux] == spec->hp_mic_mux_idx;
+
+	if (!force) {
+		val = snd_hda_codec_get_pin_target(codec, pin);
+		if (as_mic) {
+			if (val & PIN_IN)
+				return;
+		} else {
+			if (val & PIN_OUT)
+				return;
+		}
+	}
 
-	/* This pin does not have vref caps - let's enable vref on pin 0x18
-	   instead, as suggested by Realtek */
+	val = snd_hda_get_default_vref(codec, pin);
+	/* if the HP pin doesn't support VREF and the codec driver gives an
+	 * alternative pin, set up the VREF on that pin instead
+	 */
 	if (val == AC_PINCTL_VREF_HIZ && spec->shared_mic_vref_pin) {
 		const hda_nid_t vref_pin = spec->shared_mic_vref_pin;
 		unsigned int vref_val = snd_hda_get_default_vref(codec, vref_pin);
 		if (vref_val != AC_PINCTL_VREF_HIZ)
 			snd_hda_set_pin_ctl_cache(codec, vref_pin,
-					PIN_IN | (set_as_mic ? vref_val : 0));
+						  PIN_IN | (as_mic ? vref_val : 0));
 	}
 
-	val = set_as_mic ? val | PIN_IN : PIN_HP;
-	set_pin_target(codec, pin, val, true);
-
-	spec->automute_speaker = !set_as_mic;
-	call_update_outputs(codec);
+	if (!spec->hp_mic_jack_modes) {
+		if (as_mic)
+			val |= PIN_IN;
+		else
+			val = PIN_HP;
+		set_pin_target(codec, pin, val, true);
+		update_hp_automute_hook(codec);
+	}
 }
 
 /* create a shared input with the headphone out */
-static int create_shared_input(struct hda_codec *codec)
+static int create_hp_mic(struct hda_codec *codec)
 {
 	struct hda_gen_spec *spec = codec->spec;
 	struct auto_pin_cfg *cfg = &spec->autocfg;
 	unsigned int defcfg;
 	hda_nid_t nid;
 
-	/* only one internal input pin? */
-	if (cfg->num_inputs != 1)
-		return 0;
-	defcfg = snd_hda_codec_get_pincfg(codec, cfg->inputs[0].pin);
-	if (snd_hda_get_input_pin_attr(defcfg) != INPUT_PIN_ATTR_INT)
+	if (!spec->hp_mic) {
+		if (spec->suppress_hp_mic_detect)
+			return 0;
+		/* automatic detection: only if no input or a single internal
+		 * input pin is found, try to detect the shared hp/mic
+		 */
+		if (cfg->num_inputs > 1)
+			return 0;
+		else if (cfg->num_inputs == 1) {
+			defcfg = snd_hda_codec_get_pincfg(codec, cfg->inputs[0].pin);
+			if (snd_hda_get_input_pin_attr(defcfg) != INPUT_PIN_ATTR_INT)
+				return 0;
+		}
+	}
+
+	spec->hp_mic = 0; /* clear once */
+	if (cfg->num_inputs >= AUTO_CFG_MAX_INS)
 		return 0;
 
-	if (cfg->hp_outs == 1 && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
-		nid = cfg->hp_pins[0]; /* OK, we have a single HP-out */
-	else if (cfg->line_outs == 1 && cfg->line_out_type == AUTO_PIN_HP_OUT)
-		nid = cfg->line_out_pins[0]; /* OK, we have a single line-out */
-	else
-		return 0; /* both not available */
+	nid = 0;
+	if (cfg->line_out_type == AUTO_PIN_HP_OUT && cfg->line_outs > 0)
+		nid = cfg->line_out_pins[0];
+	else if (cfg->hp_outs > 0)
+		nid = cfg->hp_pins[0];
+	if (!nid)
+		return 0;
 
 	if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_IN))
 		return 0; /* no input */
 
-	cfg->inputs[1].pin = nid;
-	cfg->inputs[1].type = AUTO_PIN_MIC;
-	cfg->num_inputs = 2;
-	spec->shared_mic_hp = 1;
+	cfg->inputs[cfg->num_inputs].pin = nid;
+	cfg->inputs[cfg->num_inputs].type = AUTO_PIN_MIC;
+	cfg->num_inputs++;
+	spec->hp_mic = 1;
+	spec->hp_mic_pin = nid;
+	/* we can't handle auto-mic together with HP-mic */
+	spec->suppress_auto_mic = 1;
 	snd_printdd("hda-codec: Enable shared I/O jack on NID 0x%x\n", nid);
 	return 0;
 }
@@ -2304,13 +2345,17 @@ static int create_shared_input(struct hda_codec *codec)
 /*
  * output jack mode
  */
+
+static int create_hp_mic_jack_mode(struct hda_codec *codec, hda_nid_t pin);
+
+static const char * const out_jack_texts[] = {
+	"Line Out", "Headphone Out",
+};
+
 static int out_jack_mode_info(struct snd_kcontrol *kcontrol,
 			      struct snd_ctl_elem_info *uinfo)
 {
-	static const char * const texts[] = {
-		"Line Out", "Headphone Out",
-	};
-	return snd_hda_enum_helper_info(kcontrol, uinfo, 2, texts);
+	return snd_hda_enum_helper_info(kcontrol, uinfo, 2, out_jack_texts);
 }
 
 static int out_jack_mode_get(struct snd_kcontrol *kcontrol,
@@ -2372,6 +2417,17 @@ static void get_jack_mode_name(struct hda_codec *codec, hda_nid_t pin,
 		;
 }
 
+static int get_out_jack_num_items(struct hda_codec *codec, hda_nid_t pin)
+{
+	struct hda_gen_spec *spec = codec->spec;
+	if (spec->add_jack_modes) {
+		unsigned int pincap = snd_hda_query_pin_caps(codec, pin);
+		if ((pincap & AC_PINCAP_OUT) && (pincap & AC_PINCAP_HP_DRV))
+			return 2;
+	}
+	return 1;
+}
+
 static int create_out_jack_modes(struct hda_codec *codec, int num_pins,
 				 hda_nid_t *pins)
 {
@@ -2380,8 +2436,13 @@ static int create_out_jack_modes(struct hda_codec *codec, int num_pins,
 
 	for (i = 0; i < num_pins; i++) {
 		hda_nid_t pin = pins[i];
-		unsigned int pincap = snd_hda_query_pin_caps(codec, pin);
-		if ((pincap & AC_PINCAP_OUT) && (pincap & AC_PINCAP_HP_DRV)) {
+		if (pin == spec->hp_mic_pin) {
+			int ret = create_hp_mic_jack_mode(codec, pin);
+			if (ret < 0)
+				return ret;
+			continue;
+		}
+		if (get_out_jack_num_items(codec, pin) > 1) {
 			struct snd_kcontrol_new *knew;
 			char name[44];
 			get_jack_mode_name(codec, pin, name, sizeof(name));
@@ -2502,12 +2563,24 @@ static const struct snd_kcontrol_new in_jack_mode_enum = {
 	.put = in_jack_mode_put,
 };
 
+static int get_in_jack_num_items(struct hda_codec *codec, hda_nid_t pin)
+{
+	struct hda_gen_spec *spec = codec->spec;
+	int nitems = 0;
+	if (spec->add_jack_modes)
+		nitems = hweight32(get_vref_caps(codec, pin));
+	return nitems ? nitems : 1;
+}
+
 static int create_in_jack_mode(struct hda_codec *codec, hda_nid_t pin)
 {
 	struct hda_gen_spec *spec = codec->spec;
-	unsigned int defcfg;
 	struct snd_kcontrol_new *knew;
 	char name[44];
+	unsigned int defcfg;
+
+	if (pin == spec->hp_mic_pin)
+		return 0; /* already done in create_out_jack_mode() */
 
 	/* no jack mode for fixed pins */
 	defcfg = snd_hda_codec_get_pincfg(codec, pin);
@@ -2515,7 +2588,7 @@ static int create_in_jack_mode(struct hda_codec *codec, hda_nid_t pin)
 		return 0;
 
 	/* no multiple vref caps? */
-	if (hweight32(get_vref_caps(codec, pin)) <= 1)
+	if (get_in_jack_num_items(codec, pin) <= 1)
 		return 0;
 
 	get_jack_mode_name(codec, pin, name, sizeof(name));
@@ -2526,6 +2599,132 @@ static int create_in_jack_mode(struct hda_codec *codec, hda_nid_t pin)
 	return 0;
 }
 
+/*
+ * HP/mic shared jack mode
+ */
+static int hp_mic_jack_mode_info(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_info *uinfo)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	hda_nid_t nid = kcontrol->private_value;
+	int out_jacks = get_out_jack_num_items(codec, nid);
+	int in_jacks = get_in_jack_num_items(codec, nid);
+	const char *text = NULL;
+	int idx;
+
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = out_jacks + in_jacks;
+	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+		uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
+	idx = uinfo->value.enumerated.item;
+	if (idx < out_jacks) {
+		if (out_jacks > 1)
+			text = out_jack_texts[idx];
+		else
+			text = "Headphone Out";
+	} else {
+		idx -= out_jacks;
+		if (in_jacks > 1) {
+			unsigned int vref_caps = get_vref_caps(codec, nid);
+			text = vref_texts[get_vref_idx(vref_caps, idx)];
+		} else
+			text = "Mic In";
+	}
+
+	strcpy(uinfo->value.enumerated.name, text);
+	return 0;
+}
+
+static int get_cur_hp_mic_jack_mode(struct hda_codec *codec, hda_nid_t nid)
+{
+	int out_jacks = get_out_jack_num_items(codec, nid);
+	int in_jacks = get_in_jack_num_items(codec, nid);
+	unsigned int val = snd_hda_codec_get_pin_target(codec, nid);
+	int idx = 0;
+
+	if (val & PIN_OUT) {
+		if (out_jacks > 1 && val == PIN_HP)
+			idx = 1;
+	} else if (val & PIN_IN) {
+		idx = out_jacks;
+		if (in_jacks > 1) {
+			unsigned int vref_caps = get_vref_caps(codec, nid);
+			val &= AC_PINCTL_VREFEN;
+			idx += cvt_from_vref_idx(vref_caps, val);
+		}
+	}
+	return idx;
+}
+
+static int hp_mic_jack_mode_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;
+	ucontrol->value.enumerated.item[0] =
+		get_cur_hp_mic_jack_mode(codec, nid);
+	return 0;
+}
+
+static int hp_mic_jack_mode_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 out_jacks = get_out_jack_num_items(codec, nid);
+	int in_jacks = get_in_jack_num_items(codec, nid);
+	unsigned int val, oldval, idx;
+
+	oldval = get_cur_hp_mic_jack_mode(codec, nid);
+	idx = ucontrol->value.enumerated.item[0];
+	if (oldval == idx)
+		return 0;
+
+	if (idx < out_jacks) {
+		if (out_jacks > 1)
+			val = idx ? PIN_HP : PIN_OUT;
+		else
+			val = PIN_HP;
+	} else {
+		idx -= out_jacks;
+		if (in_jacks > 1) {
+			unsigned int vref_caps = get_vref_caps(codec, nid);
+			val = snd_hda_codec_get_pin_target(codec, nid);
+			val &= ~(AC_PINCTL_VREFEN | PIN_HP);
+			val |= get_vref_idx(vref_caps, idx) | PIN_IN;
+		} else
+			val = snd_hda_get_default_vref(codec, nid);
+	}
+	snd_hda_set_pin_ctl_cache(codec, nid, val);
+	update_hp_automute_hook(codec);
+
+	return 1;
+}
+
+static const struct snd_kcontrol_new hp_mic_jack_mode_enum = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.info = hp_mic_jack_mode_info,
+	.get = hp_mic_jack_mode_get,
+	.put = hp_mic_jack_mode_put,
+};
+
+static int create_hp_mic_jack_mode(struct hda_codec *codec, hda_nid_t pin)
+{
+	struct hda_gen_spec *spec = codec->spec;
+	struct snd_kcontrol_new *knew;
+
+	if (get_out_jack_num_items(codec, pin) <= 1 &&
+	    get_in_jack_num_items(codec, pin) <= 1)
+		return 0; /* no need */
+	knew = snd_hda_gen_add_kctl(spec, "Headphone Mic Jack Mode",
+				    &hp_mic_jack_mode_enum);
+	if (!knew)
+		return -ENOMEM;
+	knew->private_value = pin;
+	spec->hp_mic_jack_modes = 1;
+	return 0;
+}
 
 /*
  * Parse input paths
@@ -2648,7 +2847,6 @@ static int check_dyn_adc_switch(struct hda_codec *codec)
 	unsigned int ok_bits;
 	int i, n, nums;
 
- again:
 	nums = 0;
 	ok_bits = 0;
 	for (n = 0; n < spec->num_adc_nids; n++) {
@@ -2663,12 +2861,6 @@ static int check_dyn_adc_switch(struct hda_codec *codec)
 	}
 
 	if (!ok_bits) {
-		if (spec->shared_mic_hp) {
-			spec->shared_mic_hp = 0;
-			imux->num_items = 1;
-			goto again;
-		}
-
 		/* check whether ADC-switch is possible */
 		for (i = 0; i < imux->num_items; i++) {
 			for (n = 0; n < spec->num_adc_nids; n++) {
@@ -2701,7 +2893,8 @@ static int check_dyn_adc_switch(struct hda_codec *codec)
 		spec->num_adc_nids = nums;
 	}
 
-	if (imux->num_items == 1 || spec->shared_mic_hp) {
+	if (imux->num_items == 1 ||
+	    (imux->num_items == 2 && spec->hp_mic)) {
 		snd_printdd("hda-codec: reducing to a single ADC\n");
 		spec->num_adc_nids = 1; /* reduce to a single ADC */
 	}
@@ -2738,6 +2931,8 @@ static int parse_capture_source(struct hda_codec *codec, hda_nid_t pin,
 			snd_hda_get_path_idx(codec, path);
 
 		if (!imux_added) {
+			if (spec->hp_mic_pin == pin)
+				spec->hp_mic_mux_idx = imux->num_items;
 			spec->imux_pins[imux->num_items] = pin;
 			snd_hda_add_imux_item(imux, label, cfg_idx, NULL);
 			imux_added = true;
@@ -2812,7 +3007,8 @@ static int create_input_ctls(struct hda_codec *codec)
 		val = PIN_IN;
 		if (cfg->inputs[i].type == AUTO_PIN_MIC)
 			val |= snd_hda_get_default_vref(codec, pin);
-		set_pin_target(codec, pin, val, false);
+		if (pin != spec->hp_mic_pin)
+			set_pin_target(codec, pin, val, false);
 
 		if (mixer) {
 			if (is_reachable_path(codec, pin, mixer)) {
@@ -2830,7 +3026,7 @@ static int create_input_ctls(struct hda_codec *codec)
 		if (err < 0)
 			return err;
 
-		if (spec->add_in_jack_modes) {
+		if (spec->add_jack_modes) {
 			err = create_in_jack_mode(codec, pin);
 			if (err < 0)
 				return err;
@@ -3462,8 +3658,8 @@ static int mux_select(struct hda_codec *codec, unsigned int adc_idx,
 
 	spec->cur_mux[adc_idx] = idx;
 
-	if (spec->shared_mic_hp)
-		update_shared_mic_hp(codec, spec->cur_mux[adc_idx]);
+	if (spec->hp_mic)
+		update_hp_mic(codec, adc_idx, false);
 
 	if (spec->dyn_adc_switch)
 		dyn_adc_pcm_resetup(codec, idx);
@@ -3511,18 +3707,21 @@ static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,
 
 	for (i = 0; i < num_pins; i++) {
 		hda_nid_t nid = pins[i];
-		unsigned int val;
+		unsigned int val, oldval;
 		if (!nid)
 			break;
+		oldval = snd_hda_codec_get_pin_target(codec, nid);
+		if (oldval & PIN_IN)
+			continue; /* no mute for inputs */
 		/* don't reset VREF value in case it's controlling
 		 * the amp (see alc861_fixup_asus_amp_vref_0f())
 		 */
 		if (spec->keep_vref_in_automute)
-			val = snd_hda_codec_get_pin_target(codec, nid) & ~PIN_HP;
+			val = oldval & ~PIN_HP;
 		else
 			val = 0;
 		if (!mute)
-			val |= snd_hda_codec_get_pin_target(codec, nid);
+			val |= oldval;
 		/* here we call update_pin_ctl() so that the pinctl is changed
 		 * without changing the pinctl target value;
 		 * the original target value will be still referred at the
@@ -3543,8 +3742,7 @@ void snd_hda_gen_update_outputs(struct hda_codec *codec)
 	 * in general, HP pins/amps control should be enabled in all cases,
 	 * but currently set only for master_mute, just to be safe
 	 */
-	if (!spec->shared_mic_hp) /* don't change HP-pin when shared with mic */
-		do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
+	do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
 		    spec->autocfg.hp_pins, spec->master_mute);
 
 	if (!spec->automute_speaker)
@@ -3649,10 +3847,7 @@ static void update_automute_all(struct hda_codec *codec)
 {
 	struct hda_gen_spec *spec = codec->spec;
 
-	if (spec->hp_automute_hook)
-		spec->hp_automute_hook(codec, NULL);
-	else
-		snd_hda_gen_hp_automute(codec, NULL);
+	update_hp_automute_hook(codec);
 	if (spec->line_automute_hook)
 		spec->line_automute_hook(codec, NULL);
 	else
@@ -3978,6 +4173,11 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
 		cfg = &spec->autocfg;
 	}
 
+	if (!spec->main_out_badness)
+		spec->main_out_badness = &hda_main_out_badness;
+	if (!spec->extra_out_badness)
+		spec->extra_out_badness = &hda_extra_out_badness;
+
 	fill_all_dac_nids(codec);
 
 	if (!cfg->line_outs) {
@@ -4024,7 +4224,7 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
 	err = create_loopback_mixing_ctl(codec);
 	if (err < 0)
 		return err;
-	err = create_shared_input(codec);
+	err = create_hp_mic(codec);
 	if (err < 0)
 		return err;
 	err = create_input_ctls(codec);
@@ -4050,11 +4250,9 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
 	if (err < 0)
 		return err;
 
-	if (!spec->shared_mic_hp) {
-		err = check_auto_mic_availability(codec);
-		if (err < 0)
-			return err;
-	}
+	err = check_auto_mic_availability(codec);
+	if (err < 0)
+		return err;
 
 	err = create_capture_mixers(codec);
 	if (err < 0)
@@ -4064,7 +4262,7 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
 	if (err < 0)
 		return err;
 
-	if (spec->add_out_jack_modes) {
+	if (spec->add_jack_modes) {
 		if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
 			err = create_out_jack_modes(codec, cfg->line_outs,
 						    cfg->line_out_pins);
@@ -4085,6 +4283,12 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
 	if (spec->power_down_unused)
 		codec->power_filter = snd_hda_gen_path_power_filter;
 
+	if (!spec->no_analog && spec->beep_nid) {
+		err = snd_hda_attach_beep_device(codec, spec->beep_nid);
+		if (err < 0)
+			return err;
+	}
+
 	return 1;
 }
 EXPORT_SYMBOL_HDA(snd_hda_gen_parse_auto_config);
@@ -4161,9 +4365,9 @@ int snd_hda_gen_build_controls(struct hda_codec *codec)
 
 	free_kctls(spec); /* no longer needed */
 
-	if (spec->shared_mic_hp) {
+	if (spec->hp_mic_pin) {
 		int err;
-		int nid = spec->autocfg.inputs[1].pin;
+		int nid = spec->hp_mic_pin;
 		err = snd_hda_jack_add_kctl(codec, nid, "Headphone Mic", 0);
 		if (err < 0)
 			return err;
@@ -4826,11 +5030,10 @@ static void init_input_src(struct hda_codec *codec)
 				snd_hda_activate_path(codec, path, active, false);
 			}
 		}
+		if (spec->hp_mic)
+			update_hp_mic(codec, c, true);
 	}
 
-	if (spec->shared_mic_hp)
-		update_shared_mic_hp(codec, spec->cur_mux[0]);
-
 	if (spec->cap_sync_hook)
 		spec->cap_sync_hook(codec, NULL);
 }
@@ -4911,6 +5114,7 @@ EXPORT_SYMBOL_HDA(snd_hda_gen_init);
  */
 void snd_hda_gen_free(struct hda_codec *codec)
 {
+	snd_hda_detach_beep_device(codec);
 	snd_hda_gen_spec_free(codec->spec);
 	kfree(codec->spec);
 	codec->spec = NULL;
diff --git a/sound/pci/hda/hda_generic.h b/sound/pci/hda/hda_generic.h
index 009b57b..54e6651 100644
--- a/sound/pci/hda/hda_generic.h
+++ b/sound/pci/hda/hda_generic.h
@@ -76,6 +76,19 @@ enum {
 	HDA_GEN_PCM_ACT_CLOSE,
 };
 
+/* DAC assignment badness table */
+struct badness_table {
+	int no_primary_dac;	/* no primary DAC */
+	int no_dac;		/* no secondary DACs */
+	int shared_primary;	/* primary DAC is shared with main output */
+	int shared_surr;	/* secondary DAC shared with main or primary */
+	int shared_clfe;	/* third DAC shared with main or primary */
+	int shared_surr_main;	/* secondary DAC sahred with main/DAC0 */
+};
+
+extern const struct badness_table hda_main_out_badness;
+extern const struct badness_table hda_extra_out_badness;
+
 struct hda_gen_spec {
 	char stream_name_analog[32];	/* analog PCM stream */
 	const struct hda_pcm_stream *stream_analog_playback;
@@ -145,7 +158,10 @@ struct hda_gen_spec {
 	hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
 	hda_nid_t imux_pins[HDA_MAX_NUM_INPUTS];
 	unsigned int dyn_adc_idx[HDA_MAX_NUM_INPUTS];
+	/* shared hp/mic */
 	hda_nid_t shared_mic_vref_pin;
+	hda_nid_t hp_mic_pin;
+	int hp_mic_mux_idx;
 
 	/* DAC/ADC lists */
 	int num_all_dacs;
@@ -200,7 +216,8 @@ struct hda_gen_spec {
 
 	/* other parse behavior flags */
 	unsigned int need_dac_fix:1; /* need to limit DACs for multi channels */
-	unsigned int shared_mic_hp:1; /* HP/Mic-in sharing */
+	unsigned int hp_mic:1; /* Allow HP as a mic-in */
+	unsigned int suppress_hp_mic_detect:1; /* Don't detect HP/mic */
 	unsigned int no_primary_hp:1; /* Don't prefer HP pins to speaker pins */
 	unsigned int multi_cap_vol:1; /* allow multiple capture xxx volumes */
 	unsigned int inv_dmic_split:1; /* inverted dmic w/a for conexant */
@@ -209,8 +226,7 @@ struct hda_gen_spec {
 	unsigned int indep_hp:1; /* independent HP supported */
 	unsigned int prefer_hp_amp:1; /* enable HP amp for speaker if any */
 	unsigned int add_stereo_mix_input:1; /* add aamix as a capture src */
-	unsigned int add_out_jack_modes:1; /* add output jack mode enum ctls */
-	unsigned int add_in_jack_modes:1; /* add input jack mode enum ctls */
+	unsigned int add_jack_modes:1; /* add i/o jack mode enum ctls */
 	unsigned int power_down_unused:1; /* power down unused widgets */
 
 	/* other internal flags */
@@ -218,10 +234,18 @@ struct hda_gen_spec {
 	unsigned int dyn_adc_switch:1; /* switch ADCs (for ALC275) */
 	unsigned int indep_hp_enabled:1; /* independent HP enabled */
 	unsigned int have_aamix_ctl:1;
+	unsigned int hp_mic_jack_modes:1;
+
+	/* badness tables for output path evaluations */
+	const struct badness_table *main_out_badness;
+	const struct badness_table *extra_out_badness;
 
 	/* loopback mixing mode */
 	bool aamix_mode;
 
+	/* digital beep */
+	hda_nid_t beep_nid;
+
 	/* for virtual master */
 	hda_nid_t vmaster_nid;
 	unsigned int vmaster_tlv[4];
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 418bfc0..bcd40ee 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -134,8 +134,8 @@ MODULE_PARM_DESC(power_save, "Automatic power-saving timeout "
  * this may give more power-saving, but will take longer time to
  * wake up.
  */
-static int power_save_controller = -1;
-module_param(power_save_controller, bint, 0644);
+static bool power_save_controller = 1;
+module_param(power_save_controller, bool, 0644);
 MODULE_PARM_DESC(power_save_controller, "Reset controller in power save mode.");
 #endif /* CONFIG_PM */
 
@@ -2931,8 +2931,6 @@ static int azx_runtime_idle(struct device *dev)
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct azx *chip = card->private_data;
 
-	if (power_save_controller > 0)
-		return 0;
 	if (!power_save_controller ||
 	    !(chip->driver_caps & AZX_DCAPS_PM_RUNTIME))
 		return -EBUSY;
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
index 83b7486..e0bf753 100644
--- a/sound/pci/hda/hda_local.h
+++ b/sound/pci/hda/hda_local.h
@@ -670,6 +670,10 @@ snd_hda_check_power_state(struct hda_codec *codec, hda_nid_t nid,
 	return (state != target_state);
 }
 
+unsigned int snd_hda_codec_eapd_power_filter(struct hda_codec *codec,
+					     hda_nid_t nid,
+					     unsigned int power_state);
+
 /*
  * AMP control callbacks
  */
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index df8014b..977b0d8 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -43,7 +43,6 @@ struct ad198x_spec {
 	hda_nid_t eapd_nid;
 
 	unsigned int beep_amp;	/* beep amp value, set via set_beep_amp() */
-	hda_nid_t beep_dev_nid;
 
 #ifdef ENABLE_AD_STATIC_QUIRKS
 	const struct snd_kcontrol_new *mixers[6];
@@ -609,7 +608,7 @@ static const struct hda_codec_ops ad198x_auto_patch_ops = {
 	.build_controls = ad198x_auto_build_controls,
 	.build_pcms = snd_hda_gen_build_pcms,
 	.init = snd_hda_gen_init,
-	.free = ad198x_free,
+	.free = snd_hda_gen_free,
 	.unsol_event = snd_hda_jack_unsol_event,
 #ifdef CONFIG_PM
 	.check_power_status = snd_hda_gen_check_power_status,
@@ -638,12 +637,6 @@ static int ad198x_parse_auto_config(struct hda_codec *codec)
 	if (err < 0)
 		return err;
 
-	if (spec->beep_dev_nid) {
-		err = snd_hda_attach_beep_device(codec, spec->beep_dev_nid);
-		if (err < 0)
-			return err;
-	}
-
 	codec->patch_ops = ad198x_auto_patch_ops;
 
 	return 0;
@@ -1240,7 +1233,7 @@ static int ad1986a_parse_auto_config(struct hda_codec *codec)
 	codec->inv_eapd = 1;
 
 	spec->gen.mixer_nid = 0x07;
-	spec->beep_dev_nid = 0x19;
+	spec->gen.beep_nid = 0x19;
 	set_beep_amp(spec, 0x18, 0, HDA_OUTPUT);
 
 	/* AD1986A has a hardware problem that it can't share a stream
@@ -1256,7 +1249,7 @@ static int ad1986a_parse_auto_config(struct hda_codec *codec)
 
 	err = ad198x_parse_auto_config(codec);
 	if (err < 0) {
-		ad198x_free(codec);
+		snd_hda_gen_free(codec);
 		return err;
 	}
 
@@ -1673,7 +1666,7 @@ static int ad1983_parse_auto_config(struct hda_codec *codec)
 		return err;
 	spec = codec->spec;
 
-	spec->beep_dev_nid = 0x10;
+	spec->gen.beep_nid = 0x10;
 	set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
 	err = ad198x_parse_auto_config(codec);
 	if (err < 0)
@@ -1684,7 +1677,7 @@ static int ad1983_parse_auto_config(struct hda_codec *codec)
 	return 0;
 
  error:
-	ad198x_free(codec);
+	snd_hda_gen_free(codec);
 	return err;
 }
 
@@ -2187,7 +2180,7 @@ static int ad1981_parse_auto_config(struct hda_codec *codec)
 	spec = codec->spec;
 
 	spec->gen.mixer_nid = 0x0e;
-	spec->beep_dev_nid = 0x10;
+	spec->gen.beep_nid = 0x10;
 	set_beep_amp(spec, 0x0d, 0, HDA_OUTPUT);
 
 	snd_hda_pick_fixup(codec, NULL, ad1981_fixup_tbl, ad1981_fixups);
@@ -2205,7 +2198,7 @@ static int ad1981_parse_auto_config(struct hda_codec *codec)
 	return 0;
 
  error:
-	ad198x_free(codec);
+	snd_hda_gen_free(codec);
 	return err;
 }
 
@@ -3236,7 +3229,7 @@ static int ad1988_parse_auto_config(struct hda_codec *codec)
 
 	spec->gen.mixer_nid = 0x20;
 	spec->gen.mixer_merge_nid = 0x21;
-	spec->beep_dev_nid = 0x10;
+	spec->gen.beep_nid = 0x10;
 	set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
 	err = ad198x_parse_auto_config(codec);
 	if (err < 0)
@@ -3247,7 +3240,7 @@ static int ad1988_parse_auto_config(struct hda_codec *codec)
 	return 0;
 
  error:
-	ad198x_free(codec);
+	snd_hda_gen_free(codec);
 	return err;
 }
 
@@ -3653,7 +3646,7 @@ static int ad1884_parse_auto_config(struct hda_codec *codec)
 	spec = codec->spec;
 
 	spec->gen.mixer_nid = 0x20;
-	spec->beep_dev_nid = 0x10;
+	spec->gen.beep_nid = 0x10;
 	set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
 
 	snd_hda_pick_fixup(codec, NULL, ad1884_fixup_tbl, ad1884_fixups);
@@ -3671,7 +3664,7 @@ static int ad1884_parse_auto_config(struct hda_codec *codec)
 	return 0;
 
  error:
-	ad198x_free(codec);
+	snd_hda_gen_free(codec);
 	return err;
 }
 
@@ -5155,7 +5148,7 @@ static int ad1882_parse_auto_config(struct hda_codec *codec)
 
 	spec->gen.mixer_nid = 0x20;
 	spec->gen.mixer_merge_nid = 0x21;
-	spec->beep_dev_nid = 0x10;
+	spec->gen.beep_nid = 0x10;
 	set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
 	err = ad198x_parse_auto_config(codec);
 	if (err < 0)
@@ -5166,7 +5159,7 @@ static int ad1882_parse_auto_config(struct hda_codec *codec)
 	return 0;
 
  error:
-	ad198x_free(codec);
+	snd_hda_gen_free(codec);
 	return err;
 }
 
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c
index 0792b57..12eb21a 100644
--- a/sound/pci/hda/patch_ca0132.c
+++ b/sound/pci/hda/patch_ca0132.c
@@ -741,6 +741,9 @@ struct ca0132_spec {
 	long voicefx_val;
 	long cur_mic_boost;
 
+	struct hda_codec *codec;
+	struct delayed_work unsol_hp_work;
+
 #ifdef ENABLE_TUNING_CONTROLS
 	long cur_ctl_vals[TUNING_CTLS_COUNT];
 #endif
@@ -3227,6 +3230,14 @@ exit:
 	return err < 0 ? err : 0;
 }
 
+static void ca0132_unsol_hp_delayed(struct work_struct *work)
+{
+	struct ca0132_spec *spec = container_of(
+		to_delayed_work(work), struct ca0132_spec, unsol_hp_work);
+	ca0132_select_out(spec->codec);
+	snd_hda_jack_report_sync(spec->codec);
+}
+
 static void ca0132_set_dmic(struct hda_codec *codec, int enable);
 static int ca0132_mic_boost_set(struct hda_codec *codec, long val);
 static int ca0132_effects_set(struct hda_codec *codec, hda_nid_t nid, long val);
@@ -4399,8 +4410,7 @@ static void ca0132_process_dsp_response(struct hda_codec *codec)
 
 static void ca0132_unsol_event(struct hda_codec *codec, unsigned int res)
 {
-	snd_printdd(KERN_INFO "ca0132_unsol_event: 0x%x\n", res);
-
+	struct ca0132_spec *spec = codec->spec;
 
 	if (((res >> AC_UNSOL_RES_TAG_SHIFT) & 0x3f) == UNSOL_TAG_DSP) {
 		ca0132_process_dsp_response(codec);
@@ -4412,8 +4422,13 @@ static void ca0132_unsol_event(struct hda_codec *codec, unsigned int res)
 
 		switch (res) {
 		case UNSOL_TAG_HP:
-			ca0132_select_out(codec);
-			snd_hda_jack_report_sync(codec);
+			/* Delay enabling the HP amp, to let the mic-detection
+			 * state machine run.
+			 */
+			cancel_delayed_work_sync(&spec->unsol_hp_work);
+			queue_delayed_work(codec->bus->workq,
+					   &spec->unsol_hp_work,
+					   msecs_to_jiffies(500));
 			break;
 		case UNSOL_TAG_AMIC1:
 			ca0132_select_mic(codec);
@@ -4588,6 +4603,7 @@ static void ca0132_free(struct hda_codec *codec)
 {
 	struct ca0132_spec *spec = codec->spec;
 
+	cancel_delayed_work_sync(&spec->unsol_hp_work);
 	snd_hda_power_up(codec);
 	snd_hda_sequence_write(codec, spec->base_exit_verbs);
 	ca0132_exit_chip(codec);
@@ -4653,6 +4669,7 @@ static int patch_ca0132(struct hda_codec *codec)
 	if (!spec)
 		return -ENOMEM;
 	codec->spec = spec;
+	spec->codec = codec;
 
 	spec->num_mixers = 1;
 	spec->mixers[0] = ca0132_mixer;
@@ -4663,6 +4680,8 @@ static int patch_ca0132(struct hda_codec *codec)
 	spec->init_verbs[1] = ca0132_init_verbs1;
 	spec->num_init_verbs = 2;
 
+	INIT_DELAYED_WORK(&spec->unsol_hp_work, ca0132_unsol_hp_delayed);
+
 	ca0132_init_chip(codec);
 
 	ca0132_config(codec);
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index 2a89d1ee..5499643 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -139,8 +139,12 @@ struct conexant_spec {
 
 
 #ifdef CONFIG_SND_HDA_INPUT_BEEP
-#define set_beep_amp(spec, nid, idx, dir) \
-	((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir))
+static inline void set_beep_amp(struct conexant_spec *spec, hda_nid_t nid,
+				int idx, int dir)
+{
+	spec->gen.beep_nid = nid;
+	spec->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir);
+}
 /* additional beep mixers; the actual parameters are overwritten at build */
 static const struct snd_kcontrol_new cxt_beep_mixer[] = {
 	HDA_CODEC_VOLUME_MONO("Beep Playback Volume", 0, 1, 0, HDA_OUTPUT),
@@ -3191,17 +3195,11 @@ static int cx_auto_build_controls(struct hda_codec *codec)
 	return 0;
 }
 
-static void cx_auto_free(struct hda_codec *codec)
-{
-	snd_hda_detach_beep_device(codec);
-	snd_hda_gen_free(codec);
-}
-
 static const struct hda_codec_ops cx_auto_patch_ops = {
 	.build_controls = cx_auto_build_controls,
 	.build_pcms = snd_hda_gen_build_pcms,
 	.init = snd_hda_gen_init,
-	.free = cx_auto_free,
+	.free = snd_hda_gen_free,
 	.unsol_event = snd_hda_jack_unsol_event,
 #ifdef CONFIG_PM
 	.check_power_status = snd_hda_gen_check_power_status,
@@ -3356,7 +3354,6 @@ static int patch_conexant_auto(struct hda_codec *codec)
 	switch (codec->vendor_id) {
 	case 0x14f15045:
 		codec->single_adc_amp = 1;
-		codec->power_filter = NULL; /* Needs speaker amp to D3 to avoid click */
 		break;
 	case 0x14f15047:
 		codec->pin_amp_workaround = 1;
@@ -3396,8 +3393,6 @@ static int patch_conexant_auto(struct hda_codec *codec)
 		goto error;
 
 	codec->patch_ops = cx_auto_patch_ops;
-	if (spec->beep_amp)
-		snd_hda_attach_beep_device(codec, get_amp_nid_(spec->beep_amp));
 
 	/* Some laptops with Conexant chips show stalls in S3 resume,
 	 * which falls into the single-cmd mode.
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index 78e1827..ede8215 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -44,16 +44,6 @@ static bool static_hdmi_pcm;
 module_param(static_hdmi_pcm, bool, 0644);
 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 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.
- */
-#define MAX_HDMI_CVTS	8
-#define MAX_HDMI_PINS	8
-
 struct hdmi_spec_per_cvt {
 	hda_nid_t cvt_nid;
 	int assigned;
@@ -80,16 +70,17 @@ struct hdmi_spec_per_pin {
 	bool non_pcm;
 	bool chmap_set;		/* channel-map override by ALSA API? */
 	unsigned char chmap[8]; /* ALSA API channel-map */
+	char pcm_name[8];	/* filled in build_pcm callbacks */
 };
 
 struct hdmi_spec {
 	int num_cvts;
-	struct hdmi_spec_per_cvt cvts[MAX_HDMI_CVTS];
-	hda_nid_t cvt_nids[MAX_HDMI_CVTS];
+	struct snd_array cvts; /* struct hdmi_spec_per_cvt */
+	hda_nid_t cvt_nids[4]; /* only for haswell fix */
 
 	int num_pins;
-	struct hdmi_spec_per_pin pins[MAX_HDMI_PINS];
-	struct hda_pcm pcm_rec[MAX_HDMI_PINS];
+	struct snd_array pins; /* struct hdmi_spec_per_pin */
+	struct snd_array pcm_rec; /* struct hda_pcm */
 	unsigned int channels_max; /* max over all cvts */
 
 	struct hdmi_eld temp_eld;
@@ -304,12 +295,19 @@ static struct cea_channel_speaker_allocation channel_allocations[] = {
  * HDMI routines
  */
 
+#define get_pin(spec, idx) \
+	((struct hdmi_spec_per_pin *)snd_array_elem(&spec->pins, idx))
+#define get_cvt(spec, idx) \
+	((struct hdmi_spec_per_cvt  *)snd_array_elem(&spec->cvts, idx))
+#define get_pcm_rec(spec, idx) \
+	((struct hda_pcm *)snd_array_elem(&spec->pcm_rec, idx))
+
 static int pin_nid_to_pin_index(struct hdmi_spec *spec, hda_nid_t pin_nid)
 {
 	int pin_idx;
 
 	for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++)
-		if (spec->pins[pin_idx].pin_nid == pin_nid)
+		if (get_pin(spec, pin_idx)->pin_nid == pin_nid)
 			return pin_idx;
 
 	snd_printk(KERN_WARNING "HDMI: pin nid %d not registered\n", pin_nid);
@@ -322,7 +320,7 @@ static int hinfo_to_pin_index(struct hdmi_spec *spec,
 	int pin_idx;
 
 	for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++)
-		if (&spec->pcm_rec[pin_idx].stream[0] == hinfo)
+		if (get_pcm_rec(spec, pin_idx)->stream == hinfo)
 			return pin_idx;
 
 	snd_printk(KERN_WARNING "HDMI: hinfo %p not registered\n", hinfo);
@@ -334,7 +332,7 @@ 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)
+		if (get_cvt(spec, cvt_idx)->cvt_nid == cvt_nid)
 			return cvt_idx;
 
 	snd_printk(KERN_WARNING "HDMI: cvt nid %d not registered\n", cvt_nid);
@@ -352,7 +350,7 @@ static int hdmi_eld_ctl_info(struct snd_kcontrol *kcontrol,
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
 
 	pin_idx = kcontrol->private_value;
-	eld = &spec->pins[pin_idx].sink_eld;
+	eld = &get_pin(spec, pin_idx)->sink_eld;
 
 	mutex_lock(&eld->lock);
 	uinfo->count = eld->eld_valid ? eld->eld_size : 0;
@@ -370,7 +368,7 @@ static int hdmi_eld_ctl_get(struct snd_kcontrol *kcontrol,
 	int pin_idx;
 
 	pin_idx = kcontrol->private_value;
-	eld = &spec->pins[pin_idx].sink_eld;
+	eld = &get_pin(spec, pin_idx)->sink_eld;
 
 	mutex_lock(&eld->lock);
 	if (eld->eld_size > ARRAY_SIZE(ucontrol->value.bytes.data)) {
@@ -410,11 +408,11 @@ static int hdmi_create_eld_ctl(struct hda_codec *codec, int pin_idx,
 	kctl->private_value = pin_idx;
 	kctl->id.device = device;
 
-	err = snd_hda_ctl_add(codec, spec->pins[pin_idx].pin_nid, kctl);
+	err = snd_hda_ctl_add(codec, get_pin(spec, pin_idx)->pin_nid, kctl);
 	if (err < 0)
 		return err;
 
-	spec->pins[pin_idx].eld_ctl = kctl;
+	get_pin(spec, pin_idx)->eld_ctl = kctl;
 	return 0;
 }
 
@@ -875,14 +873,14 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, int pin_idx,
 				       struct snd_pcm_substream *substream)
 {
 	struct hdmi_spec *spec = codec->spec;
-	struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx];
+	struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
 	hda_nid_t pin_nid = per_pin->pin_nid;
 	int channels = substream->runtime->channels;
 	struct hdmi_eld *eld;
 	int ca;
 	union audio_infoframe ai;
 
-	eld = &spec->pins[pin_idx].sink_eld;
+	eld = &per_pin->sink_eld;
 	if (!eld->monitor_present)
 		return;
 
@@ -977,7 +975,7 @@ static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
 	if (pin_idx < 0)
 		return;
 
-	hdmi_present_sense(&spec->pins[pin_idx], 1);
+	hdmi_present_sense(get_pin(spec, pin_idx), 1);
 	snd_hda_jack_report_sync(codec);
 }
 
@@ -1083,12 +1081,12 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo,
 	pin_idx = hinfo_to_pin_index(spec, hinfo);
 	if (snd_BUG_ON(pin_idx < 0))
 		return -EINVAL;
-	per_pin = &spec->pins[pin_idx];
+	per_pin = get_pin(spec, pin_idx);
 	eld = &per_pin->sink_eld;
 
 	/* Dynamically assign converter to stream */
 	for (cvt_idx = 0; cvt_idx < spec->num_cvts; cvt_idx++) {
-		per_cvt = &spec->cvts[cvt_idx];
+		per_cvt = get_cvt(spec, cvt_idx);
 
 		/* Must not already be assigned */
 		if (per_cvt->assigned)
@@ -1151,7 +1149,7 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo,
 static int hdmi_read_pin_conn(struct hda_codec *codec, int pin_idx)
 {
 	struct hdmi_spec *spec = codec->spec;
-	struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx];
+	struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
 	hda_nid_t pin_nid = per_pin->pin_nid;
 
 	if (!(get_wcaps(codec, pin_nid) & AC_WCAP_CONN_LIST)) {
@@ -1196,7 +1194,7 @@ static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll)
 
 	_snd_printd(SND_PR_VERBOSE,
 		"HDMI status: Codec=%d Pin=%d Presence_Detect=%d ELD_Valid=%d\n",
-		codec->addr, pin_nid, eld->monitor_present, eld->eld_valid);
+		codec->addr, pin_nid, pin_eld->monitor_present, eld->eld_valid);
 
 	if (eld->eld_valid) {
 		if (snd_hdmi_get_eld(codec, pin_nid, eld->eld_buffer,
@@ -1275,14 +1273,13 @@ static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
 	if (get_defcfg_connect(config) == AC_JACK_PORT_NONE)
 		return 0;
 
-	if (snd_BUG_ON(spec->num_pins >= MAX_HDMI_PINS))
-		return -E2BIG;
-
 	if (codec->vendor_id == 0x80862807)
 		intel_haswell_fixup_connect_list(codec, pin_nid);
 
 	pin_idx = spec->num_pins;
-	per_pin = &spec->pins[pin_idx];
+	per_pin = snd_array_new(&spec->pins);
+	if (!per_pin)
+		return -ENOMEM;
 
 	per_pin->pin_nid = pin_nid;
 	per_pin->non_pcm = false;
@@ -1299,19 +1296,16 @@ static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
 static int hdmi_add_cvt(struct hda_codec *codec, hda_nid_t cvt_nid)
 {
 	struct hdmi_spec *spec = codec->spec;
-	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;
-
 	chans = get_wcaps(codec, cvt_nid);
 	chans = get_wcaps_channels(chans);
 
-	cvt_idx = spec->num_cvts;
-	per_cvt = &spec->cvts[cvt_idx];
+	per_cvt = snd_array_new(&spec->cvts);
+	if (!per_cvt)
+		return -ENOMEM;
 
 	per_cvt->cvt_nid = cvt_nid;
 	per_cvt->channels_min = 2;
@@ -1328,7 +1322,9 @@ static int hdmi_add_cvt(struct hda_codec *codec, hda_nid_t cvt_nid)
 	if (err < 0)
 		return err;
 
-	spec->cvt_nids[spec->num_cvts++] = cvt_nid;
+	if (spec->num_cvts < ARRAY_SIZE(spec->cvt_nids))
+		spec->cvt_nids[spec->num_cvts] = cvt_nid;
+	spec->num_cvts++;
 
 	return 0;
 }
@@ -1384,13 +1380,6 @@ static int hdmi_parse_codec(struct hda_codec *codec)
 
 /*
  */
-static char *get_hdmi_pcm_name(int idx)
-{
-	static char names[MAX_HDMI_PINS][8];
-	sprintf(&names[idx][0], "HDMI %d", idx);
-	return &names[idx][0];
-}
-
 static bool check_non_pcm_per_cvt(struct hda_codec *codec, hda_nid_t cvt_nid)
 {
 	struct hda_spdif_out *spdif;
@@ -1417,7 +1406,7 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
 	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;
+	hda_nid_t pin_nid = get_pin(spec, pin_idx)->pin_nid;
 	bool non_pcm;
 
 	non_pcm = check_non_pcm_per_cvt(codec, cvt_nid);
@@ -1450,7 +1439,7 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo,
 		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];
+		per_cvt = get_cvt(spec, cvt_idx);
 
 		snd_BUG_ON(!per_cvt->assigned);
 		per_cvt->assigned = 0;
@@ -1459,7 +1448,7 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo,
 		pin_idx = hinfo_to_pin_index(spec, hinfo);
 		if (snd_BUG_ON(pin_idx < 0))
 			return -EINVAL;
-		per_pin = &spec->pins[pin_idx];
+		per_pin = get_pin(spec, pin_idx);
 
 		snd_hda_spdif_ctls_unassign(codec, pin_idx);
 		per_pin->chmap_set = false;
@@ -1553,7 +1542,7 @@ static int hdmi_chmap_ctl_get(struct snd_kcontrol *kcontrol,
 	struct hda_codec *codec = info->private_data;
 	struct hdmi_spec *spec = codec->spec;
 	int pin_idx = kcontrol->private_value;
-	struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx];
+	struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
 	int i;
 
 	for (i = 0; i < ARRAY_SIZE(per_pin->chmap); i++)
@@ -1568,7 +1557,7 @@ static int hdmi_chmap_ctl_put(struct snd_kcontrol *kcontrol,
 	struct hda_codec *codec = info->private_data;
 	struct hdmi_spec *spec = codec->spec;
 	int pin_idx = kcontrol->private_value;
-	struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx];
+	struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
 	unsigned int ctl_idx;
 	struct snd_pcm_substream *substream;
 	unsigned char chmap[8];
@@ -1613,9 +1602,14 @@ static int generic_hdmi_build_pcms(struct hda_codec *codec)
 	for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
 		struct hda_pcm *info;
 		struct hda_pcm_stream *pstr;
-
-		info = &spec->pcm_rec[pin_idx];
-		info->name = get_hdmi_pcm_name(pin_idx);
+		struct hdmi_spec_per_pin *per_pin;
+
+		per_pin = get_pin(spec, pin_idx);
+		sprintf(per_pin->pcm_name, "HDMI %d", pin_idx);
+		info = snd_array_new(&spec->pcm_rec);
+		if (!info)
+			return -ENOMEM;
+		info->name = per_pin->pcm_name;
 		info->pcm_type = HDA_PCM_TYPE_HDMI;
 		info->own_chmap = true;
 
@@ -1626,7 +1620,7 @@ static int generic_hdmi_build_pcms(struct hda_codec *codec)
 	}
 
 	codec->num_pcms = spec->num_pins;
-	codec->pcm_info = spec->pcm_rec;
+	codec->pcm_info = spec->pcm_rec.list;
 
 	return 0;
 }
@@ -1635,8 +1629,8 @@ static int generic_hdmi_build_jack(struct hda_codec *codec, int pin_idx)
 {
 	char hdmi_str[32] = "HDMI/DP";
 	struct hdmi_spec *spec = codec->spec;
-	struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx];
-	int pcmdev = spec->pcm_rec[pin_idx].device;
+	struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
+	int pcmdev = get_pcm_rec(spec, pin_idx)->device;
 
 	if (pcmdev > 0)
 		sprintf(hdmi_str + strlen(hdmi_str), ",pcm=%d", pcmdev);
@@ -1654,7 +1648,7 @@ static int generic_hdmi_build_controls(struct hda_codec *codec)
 	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_spec_per_pin *per_pin = get_pin(spec, pin_idx);
 
 		err = generic_hdmi_build_jack(codec, pin_idx);
 		if (err < 0)
@@ -1669,9 +1663,8 @@ static int generic_hdmi_build_controls(struct hda_codec *codec)
 		snd_hda_spdif_ctls_unassign(codec, pin_idx);
 
 		/* add control for ELD Bytes */
-		err = hdmi_create_eld_ctl(codec,
-					pin_idx,
-					spec->pcm_rec[pin_idx].device);
+		err = hdmi_create_eld_ctl(codec, pin_idx,
+					  get_pcm_rec(spec, pin_idx)->device);
 
 		if (err < 0)
 			return err;
@@ -1709,7 +1702,7 @@ static int generic_hdmi_init_per_pins(struct hda_codec *codec)
 	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_spec_per_pin *per_pin = get_pin(spec, pin_idx);
 		struct hdmi_eld *eld = &per_pin->sink_eld;
 
 		per_pin->codec = codec;
@@ -1726,7 +1719,7 @@ static int generic_hdmi_init(struct hda_codec *codec)
 	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_spec_per_pin *per_pin = get_pin(spec, pin_idx);
 		hda_nid_t pin_nid = per_pin->pin_nid;
 
 		hdmi_init_pin(codec, pin_nid);
@@ -1735,13 +1728,27 @@ static int generic_hdmi_init(struct hda_codec *codec)
 	return 0;
 }
 
+static void hdmi_array_init(struct hdmi_spec *spec, int nums)
+{
+	snd_array_init(&spec->pins, sizeof(struct hdmi_spec_per_pin), nums);
+	snd_array_init(&spec->cvts, sizeof(struct hdmi_spec_per_cvt), nums);
+	snd_array_init(&spec->pcm_rec, sizeof(struct hda_pcm), nums);
+}
+
+static void hdmi_array_free(struct hdmi_spec *spec)
+{
+	snd_array_free(&spec->pins);
+	snd_array_free(&spec->cvts);
+	snd_array_free(&spec->pcm_rec);
+}
+
 static void generic_hdmi_free(struct hda_codec *codec)
 {
 	struct hdmi_spec *spec = codec->spec;
 	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_spec_per_pin *per_pin = get_pin(spec, pin_idx);
 		struct hdmi_eld *eld = &per_pin->sink_eld;
 
 		cancel_delayed_work(&per_pin->work);
@@ -1749,6 +1756,7 @@ static void generic_hdmi_free(struct hda_codec *codec)
 	}
 
 	flush_workqueue(codec->bus->workq);
+	hdmi_array_free(spec);
 	kfree(spec);
 }
 
@@ -1775,6 +1783,7 @@ static void intel_haswell_fixup_connect_list(struct hda_codec *codec,
 
 	/* override pins connection list */
 	snd_printdd("hdmi: haswell: override pin connection 0x%x\n", nid);
+	nconns = max(spec->num_cvts, 4);
 	snd_hda_override_conn_list(codec, nid, spec->num_cvts, spec->cvt_nids);
 }
 
@@ -1855,6 +1864,7 @@ static int patch_generic_hdmi(struct hda_codec *codec)
 		return -ENOMEM;
 
 	codec->spec = spec;
+	hdmi_array_init(spec, 4);
 
 	snd_hda_pick_fixup(codec, hdmi_models, hdmi_fixup_tbl, hdmi_fixups);
 	snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
@@ -1882,24 +1892,30 @@ static int patch_generic_hdmi(struct hda_codec *codec)
 static int simple_playback_build_pcms(struct hda_codec *codec)
 {
 	struct hdmi_spec *spec = codec->spec;
-	struct hda_pcm *info = spec->pcm_rec;
+	struct hda_pcm *info;
 	unsigned int chans;
 	struct hda_pcm_stream *pstr;
+	struct hdmi_spec_per_cvt *per_cvt;
 
-	codec->num_pcms = 1;
-	codec->pcm_info = info;
-
-	chans = get_wcaps(codec, spec->cvts[0].cvt_nid);
+	per_cvt = get_cvt(spec, 0);
+	chans = get_wcaps(codec, per_cvt->cvt_nid);
 	chans = get_wcaps_channels(chans);
 
-	info->name = get_hdmi_pcm_name(0);
+	info = snd_array_new(&spec->pcm_rec);
+	if (!info)
+		return -ENOMEM;
+	info->name = get_pin(spec, 0)->pcm_name;
+	sprintf(info->name, "HDMI 0");
 	info->pcm_type = HDA_PCM_TYPE_HDMI;
 	pstr = &info->stream[SNDRV_PCM_STREAM_PLAYBACK];
 	*pstr = spec->pcm_playback;
-	pstr->nid = spec->cvts[0].cvt_nid;
+	pstr->nid = per_cvt->cvt_nid;
 	if (pstr->channels_max <= 2 && chans && chans <= 16)
 		pstr->channels_max = chans;
 
+	codec->num_pcms = 1;
+	codec->pcm_info = info;
+
 	return 0;
 }
 
@@ -1919,11 +1935,12 @@ static void simple_hdmi_unsol_event(struct hda_codec *codec,
 static int simple_playback_build_controls(struct hda_codec *codec)
 {
 	struct hdmi_spec *spec = codec->spec;
+	struct hdmi_spec_per_cvt *per_cvt;
 	int err;
 
-	err = snd_hda_create_spdif_out_ctls(codec,
-					    spec->cvts[0].cvt_nid,
-					    spec->cvts[0].cvt_nid);
+	per_cvt = get_cvt(spec, 0);
+	err = snd_hda_create_spdif_out_ctls(codec, per_cvt->cvt_nid,
+					    per_cvt->cvt_nid);
 	if (err < 0)
 		return err;
 	return simple_hdmi_build_jack(codec, 0);
@@ -1932,7 +1949,8 @@ static int simple_playback_build_controls(struct hda_codec *codec)
 static int simple_playback_init(struct hda_codec *codec)
 {
 	struct hdmi_spec *spec = codec->spec;
-	hda_nid_t pin = spec->pins[0].pin_nid;
+	struct hdmi_spec_per_pin *per_pin = get_pin(spec, 0);
+	hda_nid_t pin = per_pin->pin_nid;
 
 	snd_hda_codec_write(codec, pin, 0,
 			    AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
@@ -1948,6 +1966,7 @@ static void simple_playback_free(struct hda_codec *codec)
 {
 	struct hdmi_spec *spec = codec->spec;
 
+	hdmi_array_free(spec);
 	kfree(spec);
 }
 
@@ -2111,20 +2130,29 @@ static int patch_simple_hdmi(struct hda_codec *codec,
 			     hda_nid_t cvt_nid, hda_nid_t pin_nid)
 {
 	struct hdmi_spec *spec;
+	struct hdmi_spec_per_cvt *per_cvt;
+	struct hdmi_spec_per_pin *per_pin;
 
 	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
 	if (!spec)
 		return -ENOMEM;
 
 	codec->spec = spec;
+	hdmi_array_init(spec, 1);
 
 	spec->multiout.num_dacs = 0;  /* no analog */
 	spec->multiout.max_channels = 2;
 	spec->multiout.dig_out_nid = cvt_nid;
 	spec->num_cvts = 1;
 	spec->num_pins = 1;
-	spec->cvts[0].cvt_nid = cvt_nid;
-	spec->pins[0].pin_nid = pin_nid;
+	per_pin = snd_array_new(&spec->pins);
+	per_cvt = snd_array_new(&spec->cvts);
+	if (!per_pin || !per_cvt) {
+		simple_playback_free(codec);
+		return -ENOMEM;
+	}
+	per_cvt->cvt_nid = cvt_nid;
+	per_pin->pin_nid = pin_nid;
 	spec->pcm_playback = simple_pcm_playback;
 
 	codec->patch_ops = simple_hdmi_patch_ops;
@@ -2201,9 +2229,11 @@ static int nvhdmi_8ch_7x_pcm_prepare(struct hda_pcm_stream *hinfo,
 	int i;
 	struct hdmi_spec *spec = codec->spec;
 	struct hda_spdif_out *spdif;
+	struct hdmi_spec_per_cvt *per_cvt;
 
 	mutex_lock(&codec->spdif_mutex);
-	spdif = snd_hda_spdif_out_of_nid(codec, spec->cvts[0].cvt_nid);
+	per_cvt = get_cvt(spec, 0);
+	spdif = snd_hda_spdif_out_of_nid(codec, per_cvt->cvt_nid);
 
 	chs = substream->runtime->channels;
 
@@ -2325,13 +2355,17 @@ static int nvhdmi_7x_8ch_build_pcms(struct hda_codec *codec)
 {
 	struct hdmi_spec *spec = codec->spec;
 	int err = simple_playback_build_pcms(codec);
-	spec->pcm_rec[0].own_chmap = true;
+	if (!err) {
+		struct hda_pcm *info = get_pcm_rec(spec, 0);
+		info->own_chmap = true;
+	}
 	return err;
 }
 
 static int nvhdmi_7x_8ch_build_controls(struct hda_codec *codec)
 {
 	struct hdmi_spec *spec = codec->spec;
+	struct hda_pcm *info;
 	struct snd_pcm_chmap *chmap;
 	int err;
 
@@ -2340,7 +2374,8 @@ static int nvhdmi_7x_8ch_build_controls(struct hda_codec *codec)
 		return err;
 
 	/* add channel maps */
-	err = snd_pcm_add_chmap_ctls(spec->pcm_rec[0].pcm,
+	info = get_pcm_rec(spec, 0);
+	err = snd_pcm_add_chmap_ctls(info->pcm,
 				     SNDRV_PCM_STREAM_PLAYBACK,
 				     snd_pcm_alt_chmaps, 8, 0, &chmap);
 	if (err < 0)
@@ -2395,6 +2430,7 @@ static int atihdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
 					struct snd_pcm_substream *substream)
 {
 	struct hdmi_spec *spec = codec->spec;
+	struct hdmi_spec_per_cvt *per_cvt = get_cvt(spec, 0);
 	int chans = substream->runtime->channels;
 	int i, err;
 
@@ -2402,11 +2438,11 @@ static int atihdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
 					  substream);
 	if (err < 0)
 		return err;
-	snd_hda_codec_write(codec, spec->cvts[0].cvt_nid, 0,
+	snd_hda_codec_write(codec, per_cvt->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->cvts[0].cvt_nid, 0,
+		snd_hda_codec_write(codec, per_cvt->cvt_nid, 0,
 				    AC_VERB_SET_HDMI_CHAN_SLOT,
 				    (i << 4) | i);
 	}
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 563c24d..fe4324a 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -34,7 +34,6 @@
 #include "hda_codec.h"
 #include "hda_local.h"
 #include "hda_auto_parser.h"
-#include "hda_beep.h"
 #include "hda_jack.h"
 #include "hda_generic.h"
 
@@ -86,6 +85,8 @@ struct alc_spec {
 	int mute_led_polarity;
 	hda_nid_t mute_led_nid;
 
+	unsigned int gpio_led; /* used for alc269_fixup_hp_gpio_led() */
+
 	/* hooks */
 	void (*init_hook)(struct hda_codec *codec);
 #ifdef CONFIG_PM
@@ -805,17 +806,7 @@ static inline void alc_shutup(struct hda_codec *codec)
 	snd_hda_shutup_pins(codec);
 }
 
-static void alc_free(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-
-	if (!spec)
-		return;
-
-	snd_hda_gen_spec_free(&spec->gen);
-	snd_hda_detach_beep_device(codec);
-	kfree(spec);
-}
+#define alc_free	snd_hda_gen_free
 
 #ifdef CONFIG_PM
 static void alc_power_eapd(struct hda_codec *codec)
@@ -1401,6 +1392,7 @@ static int patch_alc880(struct hda_codec *codec)
 
 	spec = codec->spec;
 	spec->gen.need_dac_fix = 1;
+	spec->gen.beep_nid = 0x01;
 
 	snd_hda_pick_fixup(codec, alc880_fixup_models, alc880_fixup_tbl,
 		       alc880_fixups);
@@ -1411,12 +1403,8 @@ static int patch_alc880(struct hda_codec *codec)
 	if (err < 0)
 		goto error;
 
-	if (!spec->gen.no_analog) {
-		err = snd_hda_attach_beep_device(codec, 0x1);
-		if (err < 0)
-			goto error;
+	if (!spec->gen.no_analog)
 		set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
-	}
 
 	codec->patch_ops = alc_patch_ops;
 	codec->patch_ops.unsol_event = alc880_unsol_event;
@@ -1455,6 +1443,7 @@ enum {
 	ALC260_FIXUP_HP_B1900,
 	ALC260_FIXUP_KN1,
 	ALC260_FIXUP_FSC_S7020,
+	ALC260_FIXUP_FSC_S7020_JWSE,
 };
 
 static void alc260_gpio1_automute(struct hda_codec *codec)
@@ -1516,14 +1505,17 @@ static void alc260_fixup_fsc_s7020(struct hda_codec *codec,
 				   const struct hda_fixup *fix, int action)
 {
 	struct alc_spec *spec = codec->spec;
-
-	switch (action) {
-	case HDA_FIXUP_ACT_PRE_PROBE:
-		spec->gen.add_out_jack_modes = 1;
-		break;
-	case HDA_FIXUP_ACT_PROBE:
+	if (action == HDA_FIXUP_ACT_PROBE)
 		spec->init_amp = ALC_INIT_NONE;
-		break;
+}
+
+static void alc260_fixup_fsc_s7020_jwse(struct hda_codec *codec,
+				   const struct hda_fixup *fix, int action)
+{
+	struct alc_spec *spec = codec->spec;
+	if (action == HDA_FIXUP_ACT_PRE_PROBE) {
+		spec->gen.add_jack_modes = 1;
+		spec->gen.hp_mic = 1;
 	}
 }
 
@@ -1586,6 +1578,12 @@ static const struct hda_fixup alc260_fixups[] = {
 		.type = HDA_FIXUP_FUNC,
 		.v.func = alc260_fixup_fsc_s7020,
 	},
+	[ALC260_FIXUP_FSC_S7020_JWSE] = {
+		.type = HDA_FIXUP_FUNC,
+		.v.func = alc260_fixup_fsc_s7020_jwse,
+		.chained = true,
+		.chain_id = ALC260_FIXUP_FSC_S7020,
+	},
 };
 
 static const struct snd_pci_quirk alc260_fixup_tbl[] = {
@@ -1602,6 +1600,14 @@ static const struct snd_pci_quirk alc260_fixup_tbl[] = {
 	{}
 };
 
+static const struct hda_model_fixup alc260_fixup_models[] = {
+	{.id = ALC260_FIXUP_GPIO1, .name = "gpio1"},
+	{.id = ALC260_FIXUP_COEF, .name = "coef"},
+	{.id = ALC260_FIXUP_FSC_S7020, .name = "fujitsu"},
+	{.id = ALC260_FIXUP_FSC_S7020_JWSE, .name = "fujitsu-jwse"},
+	{}
+};
+
 /*
  */
 static int patch_alc260(struct hda_codec *codec)
@@ -1619,8 +1625,10 @@ static int patch_alc260(struct hda_codec *codec)
 	 * it's almost harmless.
 	 */
 	spec->gen.prefer_hp_amp = 1;
+	spec->gen.beep_nid = 0x01;
 
-	snd_hda_pick_fixup(codec, NULL, alc260_fixup_tbl, alc260_fixups);
+	snd_hda_pick_fixup(codec, alc260_fixup_models, alc260_fixup_tbl,
+			   alc260_fixups);
 	snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
 
 	/* automatic parse from the BIOS config */
@@ -1628,12 +1636,8 @@ static int patch_alc260(struct hda_codec *codec)
 	if (err < 0)
 		goto error;
 
-	if (!spec->gen.no_analog) {
-		err = snd_hda_attach_beep_device(codec, 0x1);
-		if (err < 0)
-			goto error;
+	if (!spec->gen.no_analog)
 		set_beep_amp(spec, 0x07, 0x05, HDA_INPUT);
-	}
 
 	codec->patch_ops = alc_patch_ops;
 	spec->shutup = alc_eapd_shutup;
@@ -2132,17 +2136,16 @@ static int patch_alc882(struct hda_codec *codec)
 
 	alc_auto_parse_customize_define(codec);
 
+	if (has_cdefine_beep(codec))
+		spec->gen.beep_nid = 0x01;
+
 	/* automatic parse from the BIOS config */
 	err = alc882_parse_auto_config(codec);
 	if (err < 0)
 		goto error;
 
-	if (!spec->gen.no_analog && has_cdefine_beep(codec)) {
-		err = snd_hda_attach_beep_device(codec, 0x1);
-		if (err < 0)
-			goto error;
+	if (!spec->gen.no_analog && spec->gen.beep_nid)
 		set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
-	}
 
 	codec->patch_ops = alc_patch_ops;
 
@@ -2295,17 +2298,16 @@ static int patch_alc262(struct hda_codec *codec)
 
 	alc_auto_parse_customize_define(codec);
 
+	if (has_cdefine_beep(codec))
+		spec->gen.beep_nid = 0x01;
+
 	/* automatic parse from the BIOS config */
 	err = alc262_parse_auto_config(codec);
 	if (err < 0)
 		goto error;
 
-	if (!spec->gen.no_analog && has_cdefine_beep(codec)) {
-		err = snd_hda_attach_beep_device(codec, 0x1);
-		if (err < 0)
-			goto error;
+	if (!spec->gen.no_analog && spec->gen.beep_nid)
 		set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
-	}
 
 	codec->patch_ops = alc_patch_ops;
 	spec->shutup = alc_eapd_shutup;
@@ -2386,16 +2388,7 @@ static const struct snd_pci_quirk alc268_fixup_tbl[] = {
 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->gen.no_analog &&
-		    spec->gen.autocfg.speaker_pins[0] != 0x1d) {
-			add_mixer(spec, alc268_beep_mixer);
-			snd_hda_add_verbs(codec, alc268_beep_init_verbs);
-		}
-	}
-	return err;
+	return alc_parse_auto_config(codec, NULL, alc268_ssids);
 }
 
 /*
@@ -2403,7 +2396,7 @@ static int alc268_parse_auto_config(struct hda_codec *codec)
 static int patch_alc268(struct hda_codec *codec)
 {
 	struct alc_spec *spec;
-	int i, has_beep, err;
+	int err;
 
 	/* ALC268 has no aa-loopback mixer */
 	err = alc_alloc_spec(codec, 0);
@@ -2411,6 +2404,7 @@ static int patch_alc268(struct hda_codec *codec)
 		return err;
 
 	spec = codec->spec;
+	spec->gen.beep_nid = 0x01;
 
 	snd_hda_pick_fixup(codec, alc268_fixup_models, alc268_fixup_tbl, alc268_fixups);
 	snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
@@ -2420,18 +2414,10 @@ static int patch_alc268(struct hda_codec *codec)
 	if (err < 0)
 		goto error;
 
-	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)
-			goto error;
+	if (err > 0 && !spec->gen.no_analog &&
+	    spec->gen.autocfg.speaker_pins[0] != 0x1d) {
+		add_mixer(spec, alc268_beep_mixer);
+		snd_hda_add_verbs(codec, alc268_beep_init_verbs);
 		if (!query_amp_caps(codec, 0x1d, HDA_INPUT))
 			/* override the amp caps for beep generator */
 			snd_hda_override_amp_caps(codec, 0x1d, HDA_INPUT,
@@ -2757,6 +2743,60 @@ static void alc269_fixup_hp_mute_led_mic2(struct hda_codec *codec,
 	}
 }
 
+/* turn on/off mute LED per vmaster hook */
+static void alc269_fixup_hp_gpio_mute_hook(void *private_data, int enabled)
+{
+	struct hda_codec *codec = private_data;
+	struct alc_spec *spec = codec->spec;
+	unsigned int oldval = spec->gpio_led;
+
+	if (enabled)
+		spec->gpio_led &= ~0x08;
+	else
+		spec->gpio_led |= 0x08;
+	if (spec->gpio_led != oldval)
+		snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
+				    spec->gpio_led);
+}
+
+/* turn on/off mic-mute LED per capture hook */
+static void alc269_fixup_hp_gpio_mic_mute_hook(struct hda_codec *codec,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	struct alc_spec *spec = codec->spec;
+	unsigned int oldval = spec->gpio_led;
+
+	if (!ucontrol)
+		return;
+
+	if (ucontrol->value.integer.value[0] ||
+	    ucontrol->value.integer.value[1])
+		spec->gpio_led &= ~0x10;
+	else
+		spec->gpio_led |= 0x10;
+	if (spec->gpio_led != oldval)
+		snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
+				    spec->gpio_led);
+}
+
+static void alc269_fixup_hp_gpio_led(struct hda_codec *codec,
+				const struct hda_fixup *fix, int action)
+{
+	struct alc_spec *spec = codec->spec;
+	static const struct hda_verb gpio_init[] = {
+		{ 0x01, AC_VERB_SET_GPIO_MASK, 0x18 },
+		{ 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x18 },
+		{}
+	};
+
+	if (action == HDA_FIXUP_ACT_PRE_PROBE) {
+		spec->gen.vmaster_mute.hook = alc269_fixup_hp_gpio_mute_hook;
+		spec->gen.cap_sync_hook = alc269_fixup_hp_gpio_mic_mute_hook;
+		spec->gpio_led = 0;
+		snd_hda_add_verbs(codec, gpio_init);
+	}
+}
+
 static void alc271_hp_gate_mic_jack(struct hda_codec *codec,
 				    const struct hda_fixup *fix,
 				    int action)
@@ -2792,6 +2832,7 @@ enum {
 	ALC269_FIXUP_HP_MUTE_LED,
 	ALC269_FIXUP_HP_MUTE_LED_MIC1,
 	ALC269_FIXUP_HP_MUTE_LED_MIC2,
+	ALC269_FIXUP_HP_GPIO_LED,
 	ALC269_FIXUP_INV_DMIC,
 	ALC269_FIXUP_LENOVO_DOCK,
 	ALC269_FIXUP_PINCFG_NO_HP_TO_LINEOUT,
@@ -2931,6 +2972,10 @@ static const struct hda_fixup alc269_fixups[] = {
 		.type = HDA_FIXUP_FUNC,
 		.v.func = alc269_fixup_hp_mute_led_mic2,
 	},
+	[ALC269_FIXUP_HP_GPIO_LED] = {
+		.type = HDA_FIXUP_FUNC,
+		.v.func = alc269_fixup_hp_gpio_led,
+	},
 	[ALC269_FIXUP_INV_DMIC] = {
 		.type = HDA_FIXUP_FUNC,
 		.v.func = alc_fixup_inv_dmic_0x12,
@@ -2971,6 +3016,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
 	SND_PCI_QUIRK(0x1025, 0x029b, "Acer 1810TZ", ALC269_FIXUP_INV_DMIC),
 	SND_PCI_QUIRK(0x1025, 0x0349, "Acer AOD260", ALC269_FIXUP_INV_DMIC),
 	SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2),
+	SND_PCI_QUIRK(0x103c, 0x18e6, "HP", ALC269_FIXUP_HP_GPIO_LED),
 	SND_PCI_QUIRK(0x103c, 0x1973, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x1983, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK_VENDOR(0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED),
@@ -3063,6 +3109,7 @@ static const struct hda_model_fixup alc269_fixup_models[] = {
 	{.id = ALC271_FIXUP_DMIC, .name = "alc271-dmic"},
 	{.id = ALC269_FIXUP_INV_DMIC, .name = "inv-dmic"},
 	{.id = ALC269_FIXUP_LENOVO_DOCK, .name = "lenovo-dock"},
+	{.id = ALC269_FIXUP_HP_GPIO_LED, .name = "hp-gpio-led"},
 	{}
 };
 
@@ -3131,6 +3178,9 @@ static int patch_alc269(struct hda_codec *codec)
 
 	alc_auto_parse_customize_define(codec);
 
+	if (has_cdefine_beep(codec))
+		spec->gen.beep_nid = 0x01;
+
 	switch (codec->vendor_id) {
 	case 0x10ec0269:
 		spec->codec_variant = ALC269_TYPE_ALC269VA;
@@ -3179,12 +3229,8 @@ static int patch_alc269(struct hda_codec *codec)
 	if (err < 0)
 		goto error;
 
-	if (!spec->gen.no_analog && has_cdefine_beep(codec)) {
-		err = snd_hda_attach_beep_device(codec, 0x1);
-		if (err < 0)
-			goto error;
+	if (!spec->gen.no_analog && spec->gen.beep_nid)
 		set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
-	}
 
 	codec->patch_ops = alc_patch_ops;
 #ifdef CONFIG_PM
@@ -3292,6 +3338,7 @@ static int patch_alc861(struct hda_codec *codec)
 		return err;
 
 	spec = codec->spec;
+	spec->gen.beep_nid = 0x23;
 
 	snd_hda_pick_fixup(codec, NULL, alc861_fixup_tbl, alc861_fixups);
 	snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
@@ -3301,12 +3348,8 @@ static int patch_alc861(struct hda_codec *codec)
 	if (err < 0)
 		goto error;
 
-	if (!spec->gen.no_analog) {
-		err = snd_hda_attach_beep_device(codec, 0x23);
-		if (err < 0)
-			goto error;
+	if (!spec->gen.no_analog)
 		set_beep_amp(spec, 0x23, 0, HDA_OUTPUT);
-	}
 
 	codec->patch_ops = alc_patch_ops;
 #ifdef CONFIG_PM
@@ -3387,6 +3430,7 @@ static int patch_alc861vd(struct hda_codec *codec)
 		return err;
 
 	spec = codec->spec;
+	spec->gen.beep_nid = 0x23;
 
 	snd_hda_pick_fixup(codec, NULL, alc861vd_fixup_tbl, alc861vd_fixups);
 	snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
@@ -3396,12 +3440,8 @@ static int patch_alc861vd(struct hda_codec *codec)
 	if (err < 0)
 		goto error;
 
-	if (!spec->gen.no_analog) {
-		err = snd_hda_attach_beep_device(codec, 0x23);
-		if (err < 0)
-			goto error;
+	if (!spec->gen.no_analog)
 		set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
-	}
 
 	codec->patch_ops = alc_patch_ops;
 
@@ -3440,7 +3480,8 @@ static int alc662_parse_auto_config(struct hda_codec *codec)
 	const hda_nid_t *ssids;
 
 	if (codec->vendor_id == 0x10ec0272 || codec->vendor_id == 0x10ec0663 ||
-	    codec->vendor_id == 0x10ec0665 || codec->vendor_id == 0x10ec0670)
+	    codec->vendor_id == 0x10ec0665 || codec->vendor_id == 0x10ec0670 ||
+	    codec->vendor_id == 0x10ec0671)
 		ssids = alc663_ssids;
 	else
 		ssids = alc662_ssids;
@@ -3783,6 +3824,9 @@ static int patch_alc662(struct hda_codec *codec)
 
 	alc_auto_parse_customize_define(codec);
 
+	if (has_cdefine_beep(codec))
+		spec->gen.beep_nid = 0x01;
+
 	if ((alc_get_coef0(codec) & (1 << 14)) &&
 	    codec->bus->pci->subsystem_vendor == 0x1025 &&
 	    spec->cdefine.platform_type == 1) {
@@ -3795,10 +3839,7 @@ static int patch_alc662(struct hda_codec *codec)
 	if (err < 0)
 		goto error;
 
-	if (!spec->gen.no_analog && has_cdefine_beep(codec)) {
-		err = snd_hda_attach_beep_device(codec, 0x1);
-		if (err < 0)
-			goto error;
+	if (!spec->gen.no_analog && spec->gen.beep_nid) {
 		switch (codec->vendor_id) {
 		case 0x10ec0662:
 			set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
@@ -3894,6 +3935,7 @@ static const struct hda_codec_preset snd_hda_preset_realtek[] = {
 	{ .id = 0x10ec0665, .name = "ALC665", .patch = patch_alc662 },
 	{ .id = 0x10ec0668, .name = "ALC668", .patch = patch_alc662 },
 	{ .id = 0x10ec0670, .name = "ALC670", .patch = patch_alc662 },
+	{ .id = 0x10ec0671, .name = "ALC671", .patch = patch_alc662 },
 	{ .id = 0x10ec0680, .name = "ALC680", .patch = patch_alc680 },
 	{ .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
 	{ .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index dafe04a..1d9d642 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -211,7 +211,6 @@ struct sigmatel_spec {
 
 	/* beep widgets */
 	hda_nid_t anabeep_nid;
-	hda_nid_t digbeep_nid;
 
 	/* SPDIF-out mux */
 	const char * const *spdif_labels;
@@ -3529,8 +3528,12 @@ static int stac_parse_auto_config(struct hda_codec *codec)
 {
 	struct sigmatel_spec *spec = codec->spec;
 	int err;
+	int flags = 0;
 
-	err = snd_hda_parse_pin_defcfg(codec, &spec->gen.autocfg, NULL, 0);
+	if (spec->headset_jack)
+		flags |= HDA_PINCFG_HEADSET_MIC;
+
+	err = snd_hda_parse_pin_defcfg(codec, &spec->gen.autocfg, NULL, flags);
 	if (err < 0)
 		return err;
 
@@ -3560,16 +3563,13 @@ static int stac_parse_auto_config(struct hda_codec *codec)
 
 	/* setup digital beep controls and input device */
 #ifdef CONFIG_SND_HDA_INPUT_BEEP
-	if (spec->digbeep_nid > 0) {
-		hda_nid_t nid = spec->digbeep_nid;
+	if (spec->gen.beep_nid) {
+		hda_nid_t nid = spec->gen.beep_nid;
 		unsigned int caps;
 
 		err = stac_auto_create_beep_ctls(codec, nid);
 		if (err < 0)
 			return err;
-		err = snd_hda_attach_beep_device(codec, nid);
-		if (err < 0)
-			return err;
 		if (codec->beep) {
 			/* IDT/STAC codecs have linear beep tone parameter */
 			codec->beep->linear_tone = spec->linear_tone_beep;
@@ -3657,17 +3657,7 @@ static void stac_shutup(struct hda_codec *codec)
 				~spec->eapd_mask);
 }
 
-static void stac_free(struct hda_codec *codec)
-{
-	struct sigmatel_spec *spec = codec->spec;
-
-	if (!spec)
-		return;
-
-	snd_hda_gen_spec_free(&spec->gen);
-	kfree(spec);
-	snd_hda_detach_beep_device(codec);
-}
+#define stac_free	snd_hda_gen_free
 
 #ifdef CONFIG_PROC_FS
 static void stac92hd_proc_hook(struct snd_info_buffer *buffer,
@@ -3797,6 +3787,7 @@ static int patch_stac9200(struct hda_codec *codec)
 	spec->gen.own_eapd_ctl = 1;
 
 	codec->patch_ops = stac_patch_ops;
+	codec->power_filter = snd_hda_codec_eapd_power_filter;
 
 	snd_hda_add_verbs(codec, stac9200_eapd_init);
 
@@ -3884,7 +3875,7 @@ static int patch_stac92hd73xx(struct hda_codec *codec)
 	spec->aloopback_mask = 0x01;
 	spec->aloopback_shift = 8;
 
-	spec->digbeep_nid = 0x1c;
+	spec->gen.beep_nid = 0x1c; /* digital beep */
 
 	/* GPIO0 High = Enable EAPD */
 	spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = 0x1;
@@ -3968,7 +3959,7 @@ static int patch_stac92hd83xxx(struct hda_codec *codec)
 	spec->gen.power_down_unused = 1;
 	spec->gen.mixer_nid = 0x1b;
 
-	spec->digbeep_nid = 0x21;
+	spec->gen.beep_nid = 0x21; /* digital beep */
 	spec->pwr_nids = stac92hd83xxx_pwr_nids;
 	spec->num_pwrs = ARRAY_SIZE(stac92hd83xxx_pwr_nids);
 	spec->default_polarity = -1; /* no default cfg */
@@ -4016,7 +4007,7 @@ static int patch_stac92hd95(struct hda_codec *codec)
 	spec->gen.own_eapd_ctl = 1;
 	spec->gen.power_down_unused = 1;
 
-	spec->digbeep_nid = 0x19;
+	spec->gen.beep_nid = 0x19; /* digital beep */
 	spec->pwr_nids = stac92hd95_pwr_nids;
 	spec->num_pwrs = ARRAY_SIZE(stac92hd95_pwr_nids);
 	spec->default_polarity = -1; /* no default cfg */
@@ -4091,7 +4082,7 @@ static int patch_stac92hd71bxx(struct hda_codec *codec)
 	spec->aloopback_shift = 0;
 
 	spec->powerdown_adcs = 1;
-	spec->digbeep_nid = 0x26;
+	spec->gen.beep_nid = 0x26; /* digital beep */
 	spec->num_pwrs = ARRAY_SIZE(stac92hd71bxx_pwr_nids);
 	spec->pwr_nids = stac92hd71bxx_pwr_nids;
 
@@ -4173,7 +4164,7 @@ static int patch_stac927x(struct hda_codec *codec)
 	spec->have_spdif_mux = 1;
 	spec->spdif_labels = stac927x_spdif_labels;
 
-	spec->digbeep_nid = 0x23;
+	spec->gen.beep_nid = 0x23; /* digital beep */
 
 	/* GPIO0 High = Enable EAPD */
 	spec->eapd_mask = spec->gpio_mask = 0x01;
@@ -4232,7 +4223,7 @@ static int patch_stac9205(struct hda_codec *codec)
 	spec->gen.own_eapd_ctl = 1;
 	spec->have_spdif_mux = 1;
 
-	spec->digbeep_nid = 0x23;
+	spec->gen.beep_nid = 0x23; /* digital beep */
 
 	snd_hda_add_verbs(codec, stac9205_core_init);
 	spec->aloopback_ctl = &stac9205_loopback;
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
index c35338a..e0dadcf 100644
--- a/sound/pci/hda/patch_via.c
+++ b/sound/pci/hda/patch_via.c
@@ -626,11 +626,31 @@ static void via_set_jack_unsol_events(struct hda_codec *codec)
 	}
 }
 
+static const struct badness_table via_main_out_badness = {
+	.no_primary_dac = 0x10000,
+	.no_dac = 0x4000,
+	.shared_primary = 0x10000,
+	.shared_surr = 0x20,
+	.shared_clfe = 0x20,
+	.shared_surr_main = 0x20,
+};
+static const struct badness_table via_extra_out_badness = {
+	.no_primary_dac = 0x4000,
+	.no_dac = 0x4000,
+	.shared_primary = 0x12,
+	.shared_surr = 0x20,
+	.shared_clfe = 0x20,
+	.shared_surr_main = 0x10,
+};
+
 static int via_parse_auto_config(struct hda_codec *codec)
 {
 	struct via_spec *spec = codec->spec;
 	int err;
 
+	spec->gen.main_out_badness = &via_main_out_badness;
+	spec->gen.extra_out_badness = &via_extra_out_badness;
+
 	err = snd_hda_parse_pin_defcfg(codec, &spec->gen.autocfg, NULL, 0);
 	if (err < 0)
 		return err;
diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c
index 01f7f37..934dec9 100644
--- a/sound/pci/mixart/mixart.c
+++ b/sound/pci/mixart/mixart.c
@@ -1175,7 +1175,7 @@ static void snd_mixart_proc_read(struct snd_info_entry *entry,
 
 			snd_iprintf(buffer, "\tstreaming          : %d\n", streaming);
 			snd_iprintf(buffer, "\tmailbox            : %d\n", mailbox);
-			snd_iprintf(buffer, "\tinterrups handling : %d\n\n", interr);
+			snd_iprintf(buffer, "\tinterrupts handling : %d\n\n", interr);
 		}
 	} /* endif elf loaded */
 }
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
index 223c3d9..9ea05e9 100644
--- a/sound/pci/rme9652/hdspm.c
+++ b/sound/pci/rme9652/hdspm.c
@@ -969,6 +969,7 @@ static int snd_hdspm_create_pcm(struct snd_card *card,
 				struct hdspm *hdspm);
 
 static inline void snd_hdspm_initialize_midi_flush(struct hdspm *hdspm);
+static inline int hdspm_get_pll_freq(struct hdspm *hdspm);
 static int hdspm_update_simple_mixer_controls(struct hdspm *hdspm);
 static int hdspm_autosync_ref(struct hdspm *hdspm);
 static int snd_hdspm_set_defaults(struct hdspm *hdspm);
@@ -1075,6 +1076,20 @@ static int snd_hdspm_use_is_exclusive(struct hdspm *hdspm)
 	return ret;
 }
 
+/* round arbitary sample rates to commonly known rates */
+static int hdspm_round_frequency(int rate)
+{
+	if (rate < 38050)
+		return 32000;
+	if (rate < 46008)
+		return 44100;
+	else
+		return 48000;
+}
+
+static int hdspm_tco_sync_check(struct hdspm *hdspm);
+static int hdspm_sync_in_sync_check(struct hdspm *hdspm);
+
 /* check for external sample rate */
 static int hdspm_external_sample_rate(struct hdspm *hdspm)
 {
@@ -1216,22 +1231,45 @@ static int hdspm_external_sample_rate(struct hdspm *hdspm)
 				break;
 			}
 
-			/* QS and DS rates normally can not be detected
-			 * automatically by the card. Only exception is MADI
-			 * in 96k frame mode.
-			 *
-			 * So if we read SS values (32 .. 48k), check for
-			 * user-provided DS/QS bits in the control register
-			 * and multiply the base frequency accordingly.
-			 */
-			if (rate <= 48000) {
-				if (hdspm->control_register & HDSPM_QuadSpeed)
-					rate *= 4;
-				else if (hdspm->control_register &
-						HDSPM_DoubleSpeed)
-					rate *= 2;
+		} /* endif HDSPM_madiLock */
+
+		/* check sample rate from TCO or SYNC_IN */
+		{
+			bool is_valid_input = 0;
+			bool has_sync = 0;
+
+			syncref = hdspm_autosync_ref(hdspm);
+			if (HDSPM_AUTOSYNC_FROM_TCO == syncref) {
+				is_valid_input = 1;
+				has_sync = (HDSPM_SYNC_CHECK_SYNC ==
+					hdspm_tco_sync_check(hdspm));
+			} else if (HDSPM_AUTOSYNC_FROM_SYNC_IN == syncref) {
+				is_valid_input = 1;
+				has_sync = (HDSPM_SYNC_CHECK_SYNC ==
+					hdspm_sync_in_sync_check(hdspm));
+			}
+
+			if (is_valid_input && has_sync) {
+				rate = hdspm_round_frequency(
+					hdspm_get_pll_freq(hdspm));
 			}
 		}
+
+		/* QS and DS rates normally can not be detected
+		 * automatically by the card. Only exception is MADI
+		 * in 96k frame mode.
+		 *
+		 * So if we read SS values (32 .. 48k), check for
+		 * user-provided DS/QS bits in the control register
+		 * and multiply the base frequency accordingly.
+		 */
+		if (rate <= 48000) {
+			if (hdspm->control_register & HDSPM_QuadSpeed)
+				rate *= 4;
+			else if (hdspm->control_register &
+					HDSPM_DoubleSpeed)
+				rate *= 2;
+		}
 		break;
 	}
 
@@ -1979,16 +2017,25 @@ static void hdspm_midi_tasklet(unsigned long arg)
 /* get the system sample rate which is set */
 
 
+static inline int hdspm_get_pll_freq(struct hdspm *hdspm)
+{
+	unsigned int period, rate;
+
+	period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ);
+	rate = hdspm_calc_dds_value(hdspm, period);
+
+	return rate;
+}
+
 /**
  * Calculate the real sample rate from the
  * current DDS value.
  **/
 static int hdspm_get_system_sample_rate(struct hdspm *hdspm)
 {
-	unsigned int period, rate;
+	unsigned int rate;
 
-	period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ);
-	rate = hdspm_calc_dds_value(hdspm, period);
+	rate = hdspm_get_pll_freq(hdspm);
 
 	if (rate > 207000) {
 		/* Unreasonable high sample rate as seen on PCI MADI cards. */
@@ -2128,6 +2175,16 @@ static int hdspm_get_s1_sample_rate(struct hdspm *hdspm, unsigned int idx)
 	return (status >> (idx*4)) & 0xF;
 }
 
+#define ENUMERATED_CTL_INFO(info, texts) \
+{ \
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; \
+	uinfo->count = 1; \
+	uinfo->value.enumerated.items = ARRAY_SIZE(texts); \
+	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]); \
+}
+
 
 
 #define HDSPM_AUTOSYNC_SAMPLE_RATE(xname, xindex) \
@@ -2143,14 +2200,7 @@ static int hdspm_get_s1_sample_rate(struct hdspm *hdspm, unsigned int idx)
 static int snd_hdspm_info_autosync_sample_rate(struct snd_kcontrol *kcontrol,
 					       struct snd_ctl_elem_info *uinfo)
 {
-	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
-	uinfo->count = 1;
-	uinfo->value.enumerated.items = 10;
-
-	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
-		uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
-	strcpy(uinfo->value.enumerated.name,
-			texts_freq[uinfo->value.enumerated.item]);
+	ENUMERATED_CTL_INFO(uinfo, texts_freq);
 	return 0;
 }
 
@@ -2316,15 +2366,7 @@ static int snd_hdspm_info_system_clock_mode(struct snd_kcontrol *kcontrol,
 					    struct snd_ctl_elem_info *uinfo)
 {
 	static char *texts[] = { "Master", "AutoSync" };
-
-	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]);
+	ENUMERATED_CTL_INFO(uinfo, texts);
 	return 0;
 }
 
@@ -2888,6 +2930,112 @@ static int snd_hdspm_get_autosync_ref(struct snd_kcontrol *kcontrol,
 	return 0;
 }
 
+
+
+#define HDSPM_TCO_VIDEO_INPUT_FORMAT(xname, xindex) \
+{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+	.name = xname, \
+	.access = SNDRV_CTL_ELEM_ACCESS_READ |\
+		SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
+	.info = snd_hdspm_info_tco_video_input_format, \
+	.get = snd_hdspm_get_tco_video_input_format, \
+}
+
+static int snd_hdspm_info_tco_video_input_format(struct snd_kcontrol *kcontrol,
+				       struct snd_ctl_elem_info *uinfo)
+{
+	static char *texts[] = {"No video", "NTSC", "PAL"};
+	ENUMERATED_CTL_INFO(uinfo, texts);
+	return 0;
+}
+
+static int snd_hdspm_get_tco_video_input_format(struct snd_kcontrol *kcontrol,
+				      struct snd_ctl_elem_value *ucontrol)
+{
+	u32 status;
+	int ret = 0;
+
+	struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
+	status = hdspm_read(hdspm, HDSPM_RD_TCO + 4);
+	switch (status & (HDSPM_TCO1_Video_Input_Format_NTSC |
+			HDSPM_TCO1_Video_Input_Format_PAL)) {
+	case HDSPM_TCO1_Video_Input_Format_NTSC:
+		/* ntsc */
+		ret = 1;
+		break;
+	case HDSPM_TCO1_Video_Input_Format_PAL:
+		/* pal */
+		ret = 2;
+		break;
+	default:
+		/* no video */
+		ret = 0;
+		break;
+	}
+	ucontrol->value.enumerated.item[0] = ret;
+	return 0;
+}
+
+
+
+#define HDSPM_TCO_LTC_FRAMES(xname, xindex) \
+{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+	.name = xname, \
+	.access = SNDRV_CTL_ELEM_ACCESS_READ |\
+		SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
+	.info = snd_hdspm_info_tco_ltc_frames, \
+	.get = snd_hdspm_get_tco_ltc_frames, \
+}
+
+static int snd_hdspm_info_tco_ltc_frames(struct snd_kcontrol *kcontrol,
+				       struct snd_ctl_elem_info *uinfo)
+{
+	static char *texts[] = {"No lock", "24 fps", "25 fps", "29.97 fps",
+				"30 fps"};
+	ENUMERATED_CTL_INFO(uinfo, texts);
+	return 0;
+}
+
+static int hdspm_tco_ltc_frames(struct hdspm *hdspm)
+{
+	u32 status;
+	int ret = 0;
+
+	status = hdspm_read(hdspm, HDSPM_RD_TCO + 4);
+	if (status & HDSPM_TCO1_LTC_Input_valid) {
+		switch (status & (HDSPM_TCO1_LTC_Format_LSB |
+					HDSPM_TCO1_LTC_Format_MSB)) {
+		case 0:
+			/* 24 fps */
+			ret = 1;
+			break;
+		case HDSPM_TCO1_LTC_Format_LSB:
+			/* 25 fps */
+			ret = 2;
+			break;
+		case HDSPM_TCO1_LTC_Format_MSB:
+			/* 25 fps */
+			ret = 3;
+			break;
+		default:
+			/* 30 fps */
+			ret = 4;
+			break;
+		}
+	}
+
+	return ret;
+}
+
+static int snd_hdspm_get_tco_ltc_frames(struct snd_kcontrol *kcontrol,
+				      struct snd_ctl_elem_value *ucontrol)
+{
+	struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
+
+	ucontrol->value.enumerated.item[0] = hdspm_tco_ltc_frames(hdspm);
+	return 0;
+}
+
 #define HDSPM_TOGGLE_SETTING(xname, xindex) \
 {	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
 	.name = xname, \
@@ -2974,17 +3122,7 @@ static int snd_hdspm_info_input_select(struct snd_kcontrol *kcontrol,
 				       struct snd_ctl_elem_info *uinfo)
 {
 	static char *texts[] = { "optical", "coaxial" };
-
-	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]);
-
+	ENUMERATED_CTL_INFO(uinfo, texts);
 	return 0;
 }
 
@@ -3046,17 +3184,7 @@ static int snd_hdspm_info_ds_wire(struct snd_kcontrol *kcontrol,
 				  struct snd_ctl_elem_info *uinfo)
 {
 	static char *texts[] = { "Single", "Double" };
-
-	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]);
-
+	ENUMERATED_CTL_INFO(uinfo, texts);
 	return 0;
 }
 
@@ -3129,17 +3257,7 @@ static int snd_hdspm_info_qs_wire(struct snd_kcontrol *kcontrol,
 				       struct snd_ctl_elem_info *uinfo)
 {
 	static char *texts[] = { "Single", "Double", "Quad" };
-
-	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
-	uinfo->count = 1;
-	uinfo->value.enumerated.items = 3;
-
-	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]);
-
+	ENUMERATED_CTL_INFO(uinfo, texts);
 	return 0;
 }
 
@@ -3215,17 +3333,7 @@ static int snd_hdspm_info_madi_speedmode(struct snd_kcontrol *kcontrol,
 				       struct snd_ctl_elem_info *uinfo)
 {
 	static char *texts[] = { "Single", "Double", "Quad" };
-
-	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
-	uinfo->count = 1;
-	uinfo->value.enumerated.items = 3;
-
-	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]);
-
+	ENUMERATED_CTL_INFO(uinfo, texts);
 	return 0;
 }
 
@@ -3445,19 +3553,30 @@ static int snd_hdspm_put_playback_mixer(struct snd_kcontrol *kcontrol,
 	.get = snd_hdspm_get_sync_check \
 }
 
+#define HDSPM_TCO_LOCK_CHECK(xname, xindex) \
+{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+	.name = xname, \
+	.private_value = xindex, \
+	.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
+	.info = snd_hdspm_tco_info_lock_check, \
+	.get = snd_hdspm_get_sync_check \
+}
+
+
 
 static int snd_hdspm_info_sync_check(struct snd_kcontrol *kcontrol,
 				     struct snd_ctl_elem_info *uinfo)
 {
 	static char *texts[] = { "No Lock", "Lock", "Sync", "N/A" };
-	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
-	uinfo->count = 1;
-	uinfo->value.enumerated.items = 4;
-	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]);
+	ENUMERATED_CTL_INFO(uinfo, texts);
+	return 0;
+}
+
+static int snd_hdspm_tco_info_lock_check(struct snd_kcontrol *kcontrol,
+				     struct snd_ctl_elem_info *uinfo)
+{
+	static char *texts[] = { "No Lock", "Lock" };
+	ENUMERATED_CTL_INFO(uinfo, texts);
 	return 0;
 }
 
@@ -3590,6 +3709,14 @@ static int hdspm_aes_sync_check(struct hdspm *hdspm, int idx)
 	return 0;
 }
 
+static int hdspm_tco_input_check(struct hdspm *hdspm, u32 mask)
+{
+	u32 status;
+	status = hdspm_read(hdspm, HDSPM_RD_TCO + 4);
+
+	return (status & mask) ? 1 : 0;
+}
+
 
 static int hdspm_tco_sync_check(struct hdspm *hdspm)
 {
@@ -3697,6 +3824,22 @@ static int snd_hdspm_get_sync_check(struct snd_kcontrol *kcontrol,
 
 	}
 
+	if (hdspm->tco) {
+		switch (kcontrol->private_value) {
+		case 11:
+			/* Check TCO for lock state of its current input */
+			val = hdspm_tco_input_check(hdspm, HDSPM_TCO1_TCO_lock);
+			break;
+		case 12:
+			/* Check TCO for valid time code on LTC input. */
+			val = hdspm_tco_input_check(hdspm,
+				HDSPM_TCO1_LTC_Input_valid);
+			break;
+		default:
+			break;
+		}
+	}
+
 	if (-1 == val)
 		val = 3;
 
@@ -3813,17 +3956,7 @@ static int snd_hdspm_info_tco_sample_rate(struct snd_kcontrol *kcontrol,
 					  struct snd_ctl_elem_info *uinfo)
 {
 	static char *texts[] = { "44.1 kHz", "48 kHz" };
-	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]);
-
+	ENUMERATED_CTL_INFO(uinfo, texts);
 	return 0;
 }
 
@@ -3869,17 +4002,7 @@ static int snd_hdspm_info_tco_pull(struct snd_kcontrol *kcontrol,
 				   struct snd_ctl_elem_info *uinfo)
 {
 	static char *texts[] = { "0", "+ 0.1 %", "- 0.1 %", "+ 4 %", "- 4 %" };
-	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
-	uinfo->count = 1;
-	uinfo->value.enumerated.items = 5;
-
-	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]);
-
+	ENUMERATED_CTL_INFO(uinfo, texts);
 	return 0;
 }
 
@@ -3924,17 +4047,7 @@ static int snd_hdspm_info_tco_wck_conversion(struct snd_kcontrol *kcontrol,
 					     struct snd_ctl_elem_info *uinfo)
 {
 	static char *texts[] = { "1:1", "44.1 -> 48", "48 -> 44.1" };
-	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
-	uinfo->count = 1;
-	uinfo->value.enumerated.items = 3;
-
-	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]);
-
+	ENUMERATED_CTL_INFO(uinfo, texts);
 	return 0;
 }
 
@@ -3981,17 +4094,7 @@ static int snd_hdspm_info_tco_frame_rate(struct snd_kcontrol *kcontrol,
 {
 	static char *texts[] = { "24 fps", "25 fps", "29.97fps",
 		"29.97 dfps", "30 fps", "30 dfps" };
-	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
-	uinfo->count = 1;
-	uinfo->value.enumerated.items = 6;
-
-	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]);
-
+	ENUMERATED_CTL_INFO(uinfo, texts);
 	return 0;
 }
 
@@ -4037,17 +4140,7 @@ static int snd_hdspm_info_tco_sync_source(struct snd_kcontrol *kcontrol,
 					  struct snd_ctl_elem_info *uinfo)
 {
 	static char *texts[] = { "LTC", "Video", "WCK" };
-	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
-	uinfo->count = 1;
-	uinfo->value.enumerated.items = 3;
-
-	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]);
-
+	ENUMERATED_CTL_INFO(uinfo, texts);
 	return 0;
 }
 
@@ -4145,6 +4238,7 @@ static struct snd_kcontrol_new snd_hdspm_controls_madi[] = {
 	HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 3),
 	HDSPM_TOGGLE_SETTING("Line Out", HDSPM_LineOut),
 	HDSPM_TOGGLE_SETTING("TX 64 channels mode", HDSPM_TX_64ch),
+	HDSPM_TOGGLE_SETTING("Disable 96K frames", HDSPM_SMUX),
 	HDSPM_TOGGLE_SETTING("Clear Track Marker", HDSPM_clr_tms),
 	HDSPM_TOGGLE_SETTING("Safe Mode", HDSPM_AutoInp),
 	HDSPM_INPUT_SELECT("Input Select", 0),
@@ -4272,7 +4366,11 @@ static struct snd_kcontrol_new snd_hdspm_controls_tco[] = {
 	HDSPM_TCO_WCK_CONVERSION("TCO WCK Conversion", 0),
 	HDSPM_TCO_FRAME_RATE("TCO Frame Rate", 0),
 	HDSPM_TCO_SYNC_SOURCE("TCO Sync Source", 0),
-	HDSPM_TCO_WORD_TERM("TCO Word Term", 0)
+	HDSPM_TCO_WORD_TERM("TCO Word Term", 0),
+	HDSPM_TCO_LOCK_CHECK("TCO Input Check", 11),
+	HDSPM_TCO_LOCK_CHECK("TCO LTC Valid", 12),
+	HDSPM_TCO_LTC_FRAMES("TCO Detected Frame Rate", 0),
+	HDSPM_TCO_VIDEO_INPUT_FORMAT("Video Input Format", 0)
 };
 
 
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.c b/sound/pcmcia/pdaudiocf/pdaudiocf.c
index f9b5229..8f489de 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf.c
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf.c
@@ -295,18 +295,5 @@ static struct pcmcia_driver pdacf_cs_driver = {
 	.suspend	= pdacf_suspend,
 	.resume		= pdacf_resume,
 #endif
-
 };
-
-static int __init init_pdacf(void)
-{
-	return pcmcia_register_driver(&pdacf_cs_driver);
-}
-
-static void __exit exit_pdacf(void)
-{
-	pcmcia_unregister_driver(&pdacf_cs_driver);
-}
-
-module_init(init_pdacf);
-module_exit(exit_pdacf);
+module_pcmcia_driver(pdacf_cs_driver);
diff --git a/sound/pcmcia/vx/vxpocket.c b/sound/pcmcia/vx/vxpocket.c
index 8f93504..d4db7ec 100644
--- a/sound/pcmcia/vx/vxpocket.c
+++ b/sound/pcmcia/vx/vxpocket.c
@@ -367,16 +367,4 @@ static struct pcmcia_driver vxp_cs_driver = {
 	.resume		= vxp_resume,
 #endif
 };
-
-static int __init init_vxpocket(void)
-{
-	return pcmcia_register_driver(&vxp_cs_driver);
-}
-
-static void __exit exit_vxpocket(void)
-{
-	pcmcia_unregister_driver(&vxp_cs_driver);
-}
-
-module_init(init_vxpocket);
-module_exit(exit_vxpocket);
+module_pcmcia_driver(vxp_cs_driver);
diff --git a/sound/soc/atmel/atmel-pcm-dma.c b/sound/soc/atmel/atmel-pcm-dma.c
index 30184a4..bb07989 100644
--- a/sound/soc/atmel/atmel-pcm-dma.c
+++ b/sound/soc/atmel/atmel-pcm-dma.c
@@ -67,9 +67,10 @@ static const struct snd_pcm_hardware atmel_pcm_dma_hardware = {
 static void atmel_pcm_dma_irq(u32 ssc_sr,
 	struct snd_pcm_substream *substream)
 {
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct atmel_pcm_dma_params *prtd;
 
-	prtd = snd_dmaengine_pcm_get_data(substream);
+	prtd = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
 
 	if (ssc_sr & prtd->mask->ssc_error) {
 		if (snd_pcm_running(substream))
@@ -104,15 +105,13 @@ static bool filter(struct dma_chan *chan, void *slave)
 }
 
 static int atmel_pcm_configure_dma(struct snd_pcm_substream *substream,
-	struct snd_pcm_hw_params *params)
+	struct snd_pcm_hw_params *params, struct atmel_pcm_dma_params *prtd)
 {
-	struct atmel_pcm_dma_params *prtd;
 	struct ssc_device *ssc;
 	struct dma_chan *dma_chan;
 	struct dma_slave_config slave_config;
 	int ret;
 
-	prtd = snd_dmaengine_pcm_get_data(substream);
 	ssc = prtd->ssc;
 
 	ret = snd_hwparams_to_dma_slave_config(substream, params,
@@ -130,8 +129,6 @@ static int atmel_pcm_configure_dma(struct snd_pcm_substream *substream,
 		slave_config.src_maxburst = 1;
 	}
 
-	slave_config.device_fc = false;
-
 	dma_chan = snd_dmaengine_pcm_get_chan(substream);
 	if (dmaengine_slave_config(dma_chan, &slave_config)) {
 		pr_err("atmel-pcm: failed to configure dma channel\n");
@@ -164,9 +161,7 @@ static int atmel_pcm_hw_params(struct snd_pcm_substream *substream,
 		return -EINVAL;
 	}
 
-	snd_dmaengine_pcm_set_data(substream, prtd);
-
-	ret = atmel_pcm_configure_dma(substream, params);
+	ret = atmel_pcm_configure_dma(substream, params, prtd);
 	if (ret) {
 		pr_err("atmel-pcm: failed to configure dmai\n");
 		goto err;
@@ -182,9 +177,10 @@ err:
 
 static int atmel_pcm_dma_prepare(struct snd_pcm_substream *substream)
 {
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct atmel_pcm_dma_params *prtd;
 
-	prtd = snd_dmaengine_pcm_get_data(substream);
+	prtd = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
 
 	ssc_writex(prtd->ssc->regs, SSC_IER, prtd->mask->ssc_error);
 	ssc_writex(prtd->ssc->regs, SSC_CR, prtd->mask->ssc_enable);
@@ -199,16 +195,9 @@ static int atmel_pcm_open(struct snd_pcm_substream *substream)
 	return 0;
 }
 
-static int atmel_pcm_close(struct snd_pcm_substream *substream)
-{
-	snd_dmaengine_pcm_close(substream);
-
-	return 0;
-}
-
 static struct snd_pcm_ops atmel_pcm_ops = {
 	.open		= atmel_pcm_open,
-	.close		= atmel_pcm_close,
+	.close		= snd_dmaengine_pcm_close,
 	.ioctl		= snd_pcm_lib_ioctl,
 	.hw_params	= atmel_pcm_hw_params,
 	.prepare	= atmel_pcm_dma_prepare,
diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c
index e13580d..f3fdfa0 100644
--- a/sound/soc/atmel/atmel_ssc_dai.c
+++ b/sound/soc/atmel/atmel_ssc_dai.c
@@ -533,6 +533,49 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
 		break;
 
 	case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM:
+		/*
+		 * DSP/PCM Mode A format, CODEC supplies BCLK and LRC clocks.
+		 *
+		 * The SSC transmit clock is obtained from the BCLK signal on
+		 * on the TK line, and the SSC receive clock is
+		 * generated from the transmit clock.
+		 *
+		 * Data is transferred on first BCLK after LRC pulse rising
+		 * edge.If stereo, the right channel data is contiguous with
+		 * the left channel data.
+		 */
+		rcmr =	  SSC_BF(RCMR_PERIOD, 0)
+			| SSC_BF(RCMR_STTDLY, START_DELAY)
+			| SSC_BF(RCMR_START, SSC_START_RISING_RF)
+			| SSC_BF(RCMR_CKI, SSC_CKI_RISING)
+			| SSC_BF(RCMR_CKO, SSC_CKO_NONE)
+			| SSC_BF(RCMR_CKS, SSC_CKS_PIN);
+
+		rfmr =	  SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
+			| SSC_BF(RFMR_FSOS, SSC_FSOS_NONE)
+			| SSC_BF(RFMR_FSLEN, 0)
+			| SSC_BF(RFMR_DATNB, (channels - 1))
+			| SSC_BIT(RFMR_MSBF)
+			| SSC_BF(RFMR_LOOP, 0)
+			| SSC_BF(RFMR_DATLEN, (bits - 1));
+
+		tcmr =	  SSC_BF(TCMR_PERIOD, 0)
+			| SSC_BF(TCMR_STTDLY, START_DELAY)
+			| SSC_BF(TCMR_START, SSC_START_RISING_RF)
+			| SSC_BF(TCMR_CKI, SSC_CKI_FALLING)
+			| SSC_BF(TCMR_CKO, SSC_CKO_NONE)
+			| SSC_BF(TCMR_CKS, SSC_CKS_PIN);
+
+		tfmr =	  SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
+			| SSC_BF(TFMR_FSDEN, 0)
+			| SSC_BF(TFMR_FSOS, SSC_FSOS_NONE)
+			| SSC_BF(TFMR_FSLEN, 0)
+			| SSC_BF(TFMR_DATNB, (channels - 1))
+			| SSC_BIT(TFMR_MSBF)
+			| SSC_BF(TFMR_DATDEF, 0)
+			| SSC_BF(TFMR_DATLEN, (bits - 1));
+		break;
+
 	default:
 		printk(KERN_WARNING "atmel_ssc_dai: unsupported DAI format 0x%x\n",
 			ssc_p->daifmt);
@@ -707,13 +750,18 @@ static struct snd_soc_dai_driver atmel_ssc_dai = {
 		.ops = &atmel_ssc_dai_ops,
 };
 
+static const struct snd_soc_component_driver atmel_ssc_component = {
+	.name		= "atmel-ssc",
+};
+
 static int asoc_ssc_init(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
 	struct ssc_device *ssc = platform_get_drvdata(pdev);
 	int ret;
 
-	ret = snd_soc_register_dai(dev, &atmel_ssc_dai);
+	ret = snd_soc_register_component(dev, &atmel_ssc_component,
+					 &atmel_ssc_dai, 1);
 	if (ret) {
 		dev_err(dev, "Could not register DAI: %d\n", ret);
 		goto err;
@@ -732,7 +780,7 @@ static int asoc_ssc_init(struct device *dev)
 	return 0;
 
 err_unregister_dai:
-	snd_soc_unregister_dai(dev);
+	snd_soc_unregister_component(dev);
 err:
 	return ret;
 }
@@ -747,7 +795,7 @@ static void asoc_ssc_exit(struct device *dev)
 	else
 		atmel_pcm_pdc_platform_unregister(dev);
 
-	snd_soc_unregister_dai(dev);
+	snd_soc_unregister_component(dev);
 }
 
 /**
diff --git a/sound/soc/au1x/ac97c.c b/sound/soc/au1x/ac97c.c
index ea7d9d1..44b8dce 100644
--- a/sound/soc/au1x/ac97c.c
+++ b/sound/soc/au1x/ac97c.c
@@ -223,6 +223,10 @@ static struct snd_soc_dai_driver au1xac97c_dai_driver = {
 	.ops			= &alchemy_ac97c_ops,
 };
 
+static const struct snd_soc_component_driver au1xac97c_component = {
+	.name		= "au1xac97c",
+};
+
 static int au1xac97c_drvprobe(struct platform_device *pdev)
 {
 	int ret;
@@ -268,7 +272,8 @@ static int au1xac97c_drvprobe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, ctx);
 
-	ret = snd_soc_register_dai(&pdev->dev, &au1xac97c_dai_driver);
+	ret = snd_soc_register_component(&pdev->dev, &au1xac97c_component,
+					 &au1xac97c_dai_driver, 1);
 	if (ret)
 		return ret;
 
@@ -280,7 +285,7 @@ static int au1xac97c_drvremove(struct platform_device *pdev)
 {
 	struct au1xpsc_audio_data *ctx = platform_get_drvdata(pdev);
 
-	snd_soc_unregister_dai(&pdev->dev);
+	snd_soc_unregister_component(&pdev->dev);
 
 	WR(ctx, AC97_ENABLE, EN_D);	/* clock off, disable */
 
diff --git a/sound/soc/au1x/i2sc.c b/sound/soc/au1x/i2sc.c
index 072448a..b3f37f6 100644
--- a/sound/soc/au1x/i2sc.c
+++ b/sound/soc/au1x/i2sc.c
@@ -225,6 +225,10 @@ static struct snd_soc_dai_driver au1xi2s_dai_driver = {
 	.ops = &au1xi2s_dai_ops,
 };
 
+static const struct snd_soc_component_driver au1xi2s_component = {
+	.name		= "au1xi2s",
+};
+
 static int au1xi2s_drvprobe(struct platform_device *pdev)
 {
 	struct resource *iores, *dmares;
@@ -260,14 +264,15 @@ static int au1xi2s_drvprobe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, ctx);
 
-	return snd_soc_register_dai(&pdev->dev, &au1xi2s_dai_driver);
+	return snd_soc_register_component(&pdev->dev, &au1xi2s_component,
+					  &au1xi2s_dai_driver, 1);
 }
 
 static int au1xi2s_drvremove(struct platform_device *pdev)
 {
 	struct au1xpsc_audio_data *ctx = platform_get_drvdata(pdev);
 
-	snd_soc_unregister_dai(&pdev->dev);
+	snd_soc_unregister_component(&pdev->dev);
 
 	WR(ctx, I2S_ENABLE, EN_D);	/* clock off, disable */
 
diff --git a/sound/soc/au1x/psc-ac97.c b/sound/soc/au1x/psc-ac97.c
index 6ba07e3..8f1862a 100644
--- a/sound/soc/au1x/psc-ac97.c
+++ b/sound/soc/au1x/psc-ac97.c
@@ -361,6 +361,10 @@ static const struct snd_soc_dai_driver au1xpsc_ac97_dai_template = {
 	.ops = &au1xpsc_ac97_dai_ops,
 };
 
+static const struct snd_soc_component_driver au1xpsc_ac97_component = {
+	.name		= "au1xpsc-ac97",
+};
+
 static int au1xpsc_ac97_drvprobe(struct platform_device *pdev)
 {
 	int ret;
@@ -419,7 +423,8 @@ static int au1xpsc_ac97_drvprobe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, wd);
 
-	ret = snd_soc_register_dai(&pdev->dev, &wd->dai_drv);
+	ret = snd_soc_register_component(&pdev->dev, &au1xpsc_ac97_component,
+					 &wd->dai_drv, 1);
 	if (ret)
 		return ret;
 
@@ -431,7 +436,7 @@ static int au1xpsc_ac97_drvremove(struct platform_device *pdev)
 {
 	struct au1xpsc_audio_data *wd = platform_get_drvdata(pdev);
 
-	snd_soc_unregister_dai(&pdev->dev);
+	snd_soc_unregister_component(&pdev->dev);
 
 	/* disable PSC completely */
 	au_writel(0, AC97_CFG(wd));
diff --git a/sound/soc/au1x/psc-i2s.c b/sound/soc/au1x/psc-i2s.c
index 360b4e5..fe923a7 100644
--- a/sound/soc/au1x/psc-i2s.c
+++ b/sound/soc/au1x/psc-i2s.c
@@ -288,6 +288,10 @@ static const struct snd_soc_dai_driver au1xpsc_i2s_dai_template = {
 	.ops = &au1xpsc_i2s_dai_ops,
 };
 
+static const struct snd_soc_component_driver au1xpsc_i2s_component = {
+	.name		= "au1xpsc-i2s",
+};
+
 static int au1xpsc_i2s_drvprobe(struct platform_device *pdev)
 {
 	struct resource *iores, *dmares;
@@ -350,14 +354,15 @@ static int au1xpsc_i2s_drvprobe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, wd);
 
-	return snd_soc_register_dai(&pdev->dev, &wd->dai_drv);
+	return snd_soc_register_component(&pdev->dev, &au1xpsc_i2s_component,
+					  &wd->dai_drv, 1);
 }
 
 static int au1xpsc_i2s_drvremove(struct platform_device *pdev)
 {
 	struct au1xpsc_audio_data *wd = platform_get_drvdata(pdev);
 
-	snd_soc_unregister_dai(&pdev->dev);
+	snd_soc_unregister_component(&pdev->dev);
 
 	au_writel(0, I2S_CFG(wd));
 	au_sync();
diff --git a/sound/soc/blackfin/bf5xx-ac97.c b/sound/soc/blackfin/bf5xx-ac97.c
index 8e41bcb..4902173 100644
--- a/sound/soc/blackfin/bf5xx-ac97.c
+++ b/sound/soc/blackfin/bf5xx-ac97.c
@@ -282,6 +282,10 @@ static struct snd_soc_dai_driver bfin_ac97_dai = {
 		.formats = SNDRV_PCM_FMTBIT_S16_LE, },
 };
 
+static const struct snd_soc_component_driver bfin_ac97_component = {
+	.name		= "bfin-ac97",
+};
+
 static int asoc_bfin_ac97_probe(struct platform_device *pdev)
 {
 	struct sport_device *sport_handle;
@@ -331,7 +335,8 @@ static int asoc_bfin_ac97_probe(struct platform_device *pdev)
 		goto sport_config_err;
 	}
 
-	ret = snd_soc_register_dai(&pdev->dev, &bfin_ac97_dai);
+	ret = snd_soc_register_component(&pdev->dev, &bfin_ac97_component,
+					 &bfin_ac97_dai, 1);
 	if (ret) {
 		pr_err("Failed to register DAI: %d\n", ret);
 		goto sport_config_err;
@@ -356,7 +361,7 @@ static int asoc_bfin_ac97_remove(struct platform_device *pdev)
 {
 	struct sport_device *sport_handle = platform_get_drvdata(pdev);
 
-	snd_soc_unregister_dai(&pdev->dev);
+	snd_soc_unregister_component(&pdev->dev);
 	sport_done(sport_handle);
 #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET
 	gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM);
diff --git a/sound/soc/blackfin/bf5xx-i2s.c b/sound/soc/blackfin/bf5xx-i2s.c
index 168d88b..dd0c2a4 100644
--- a/sound/soc/blackfin/bf5xx-i2s.c
+++ b/sound/soc/blackfin/bf5xx-i2s.c
@@ -245,6 +245,10 @@ static struct snd_soc_dai_driver bf5xx_i2s_dai = {
 	.ops = &bf5xx_i2s_dai_ops,
 };
 
+static const struct snd_soc_component_driver bf5xx_i2s_component = {
+	.name		= "bf5xx-i2s",
+};
+
 static int bf5xx_i2s_probe(struct platform_device *pdev)
 {
 	struct sport_device *sport_handle;
@@ -257,7 +261,8 @@ static int bf5xx_i2s_probe(struct platform_device *pdev)
 		return -ENODEV;
 
 	/* register with the ASoC layers */
-	ret = snd_soc_register_dai(&pdev->dev, &bf5xx_i2s_dai);
+	ret = snd_soc_register_component(&pdev->dev, &bf5xx_i2s_component,
+					 &bf5xx_i2s_dai, 1);
 	if (ret) {
 		pr_err("Failed to register DAI: %d\n", ret);
 		sport_done(sport_handle);
@@ -273,7 +278,7 @@ static int bf5xx_i2s_remove(struct platform_device *pdev)
 
 	pr_debug("%s enter\n", __func__);
 
-	snd_soc_unregister_dai(&pdev->dev);
+	snd_soc_unregister_component(&pdev->dev);
 	sport_done(sport_handle);
 
 	return 0;
diff --git a/sound/soc/blackfin/bf5xx-tdm.c b/sound/soc/blackfin/bf5xx-tdm.c
index c1e516e..69e9a3e 100644
--- a/sound/soc/blackfin/bf5xx-tdm.c
+++ b/sound/soc/blackfin/bf5xx-tdm.c
@@ -249,6 +249,10 @@ static struct snd_soc_dai_driver bf5xx_tdm_dai = {
 	.ops = &bf5xx_tdm_dai_ops,
 };
 
+static const struct snd_soc_component_driver bf5xx_tdm_component = {
+	.name		= "bf5xx-tdm",
+};
+
 static int bfin_tdm_probe(struct platform_device *pdev)
 {
 	struct sport_device *sport_handle;
@@ -282,7 +286,8 @@ static int bfin_tdm_probe(struct platform_device *pdev)
 		goto sport_config_err;
 	}
 
-	ret = snd_soc_register_dai(&pdev->dev, &bf5xx_tdm_dai);
+	ret = snd_soc_register_component(&pdev->dev, &bf5xx_tdm_component,
+					 &bf5xx_tdm_dai, 1);
 	if (ret) {
 		pr_err("Failed to register DAI: %d\n", ret);
 		goto sport_config_err;
@@ -299,7 +304,7 @@ static int bfin_tdm_remove(struct platform_device *pdev)
 {
 	struct sport_device *sport_handle = platform_get_drvdata(pdev);
 
-	snd_soc_unregister_dai(&pdev->dev);
+	snd_soc_unregister_component(&pdev->dev);
 	sport_done(sport_handle);
 
 	return 0;
diff --git a/sound/soc/blackfin/bf6xx-i2s.c b/sound/soc/blackfin/bf6xx-i2s.c
index 8f33797..c02405c 100644
--- a/sound/soc/blackfin/bf6xx-i2s.c
+++ b/sound/soc/blackfin/bf6xx-i2s.c
@@ -186,6 +186,10 @@ static struct snd_soc_dai_driver bfin_i2s_dai = {
 	.ops = &bfin_i2s_dai_ops,
 };
 
+static const struct snd_soc_component_driver bfin_i2s_component = {
+	.name		= "bfin-i2s",
+};
+
 static int bfin_i2s_probe(struct platform_device *pdev)
 {
 	struct sport_device *sport;
@@ -197,7 +201,8 @@ static int bfin_i2s_probe(struct platform_device *pdev)
 		return -ENODEV;
 
 	/* register with the ASoC layers */
-	ret = snd_soc_register_dai(dev, &bfin_i2s_dai);
+	ret = snd_soc_register_component(dev, &bfin_i2s_component,
+					 &bfin_i2s_dai, 1);
 	if (ret) {
 		dev_err(dev, "Failed to register DAI: %d\n", ret);
 		sport_delete(sport);
@@ -212,7 +217,7 @@ static int bfin_i2s_remove(struct platform_device *pdev)
 {
 	struct sport_device *sport = platform_get_drvdata(pdev);
 
-	snd_soc_unregister_dai(&pdev->dev);
+	snd_soc_unregister_component(&pdev->dev);
 	sport_delete(sport);
 
 	return 0;
diff --git a/sound/soc/cirrus/edb93xx.c b/sound/soc/cirrus/edb93xx.c
index 5db68cf..c43fb21 100644
--- a/sound/soc/cirrus/edb93xx.c
+++ b/sound/soc/cirrus/edb93xx.c
@@ -27,7 +27,6 @@
 #include <sound/soc.h>
 #include <asm/mach-types.h>
 #include <mach/hardware.h>
-#include "ep93xx-pcm.h"
 
 static int edb93xx_hw_params(struct snd_pcm_substream *substream,
 			     struct snd_pcm_hw_params *params)
diff --git a/sound/soc/cirrus/ep93xx-ac97.c b/sound/soc/cirrus/ep93xx-ac97.c
index 1738d28..7798fbd 100644
--- a/sound/soc/cirrus/ep93xx-ac97.c
+++ b/sound/soc/cirrus/ep93xx-ac97.c
@@ -23,7 +23,6 @@
 #include <sound/soc.h>
 
 #include <linux/platform_data/dma-ep93xx.h>
-#include "ep93xx-pcm.h"
 
 /*
  * Per channel (1-4) registers.
@@ -101,14 +100,16 @@ struct ep93xx_ac97_info {
 /* currently ALSA only supports a single AC97 device */
 static struct ep93xx_ac97_info *ep93xx_ac97_info;
 
-static struct ep93xx_pcm_dma_params ep93xx_ac97_pcm_out = {
+static struct ep93xx_dma_data ep93xx_ac97_pcm_out = {
 	.name		= "ac97-pcm-out",
 	.dma_port	= EP93XX_DMA_AAC1,
+	.direction	= DMA_MEM_TO_DEV,
 };
 
-static struct ep93xx_pcm_dma_params ep93xx_ac97_pcm_in = {
+static struct ep93xx_dma_data ep93xx_ac97_pcm_in = {
 	.name		= "ac97-pcm-in",
 	.dma_port	= EP93XX_DMA_AAC1,
+	.direction	= DMA_DEV_TO_MEM,
 };
 
 static inline unsigned ep93xx_ac97_read_reg(struct ep93xx_ac97_info *info,
@@ -316,7 +317,7 @@ static int ep93xx_ac97_trigger(struct snd_pcm_substream *substream,
 static int ep93xx_ac97_startup(struct snd_pcm_substream *substream,
 			       struct snd_soc_dai *dai)
 {
-	struct ep93xx_pcm_dma_params *dma_data;
+	struct ep93xx_dma_data *dma_data;
 
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 		dma_data = &ep93xx_ac97_pcm_out;
@@ -353,6 +354,10 @@ static struct snd_soc_dai_driver ep93xx_ac97_dai = {
 	.ops			= &ep93xx_ac97_dai_ops,
 };
 
+static const struct snd_soc_component_driver ep93xx_ac97_component = {
+	.name		= "ep93xx-ac97",
+};
+
 static int ep93xx_ac97_probe(struct platform_device *pdev)
 {
 	struct ep93xx_ac97_info *info;
@@ -390,7 +395,8 @@ static int ep93xx_ac97_probe(struct platform_device *pdev)
 	ep93xx_ac97_info = info;
 	platform_set_drvdata(pdev, info);
 
-	ret = snd_soc_register_dai(&pdev->dev, &ep93xx_ac97_dai);
+	ret = snd_soc_register_component(&pdev->dev, &ep93xx_ac97_component,
+					 &ep93xx_ac97_dai, 1);
 	if (ret)
 		goto fail;
 
@@ -407,7 +413,7 @@ static int ep93xx_ac97_remove(struct platform_device *pdev)
 {
 	struct ep93xx_ac97_info	*info = platform_get_drvdata(pdev);
 
-	snd_soc_unregister_dai(&pdev->dev);
+	snd_soc_unregister_component(&pdev->dev);
 
 	/* disable the AC97 controller */
 	ep93xx_ac97_write_reg(info, AC97GCR, 0);
diff --git a/sound/soc/cirrus/ep93xx-i2s.c b/sound/soc/cirrus/ep93xx-i2s.c
index 323ed69..3f2ad9c 100644
--- a/sound/soc/cirrus/ep93xx-i2s.c
+++ b/sound/soc/cirrus/ep93xx-i2s.c
@@ -30,8 +30,6 @@
 #include <mach/ep93xx-regs.h>
 #include <linux/platform_data/dma-ep93xx.h>
 
-#include "ep93xx-pcm.h"
-
 #define EP93XX_I2S_TXCLKCFG		0x00
 #define EP93XX_I2S_RXCLKCFG		0x04
 #define EP93XX_I2S_GLCTRL		0x0C
@@ -62,18 +60,20 @@ struct ep93xx_i2s_info {
 	struct clk			*mclk;
 	struct clk			*sclk;
 	struct clk			*lrclk;
-	struct ep93xx_pcm_dma_params	*dma_params;
+	struct ep93xx_dma_data		*dma_data;
 	void __iomem			*regs;
 };
 
-struct ep93xx_pcm_dma_params ep93xx_i2s_dma_params[] = {
+struct ep93xx_dma_data ep93xx_i2s_dma_data[] = {
 	[SNDRV_PCM_STREAM_PLAYBACK] = {
 		.name		= "i2s-pcm-out",
 		.dma_port	= EP93XX_DMA_I2S1,
+		.direction	= DMA_MEM_TO_DEV,
 	},
 	[SNDRV_PCM_STREAM_CAPTURE] = {
 		.name		= "i2s-pcm-in",
 		.dma_port	= EP93XX_DMA_I2S1,
+		.direction	= DMA_DEV_TO_MEM,
 	},
 };
 
@@ -147,7 +147,7 @@ static int ep93xx_i2s_startup(struct snd_pcm_substream *substream,
 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 
 	snd_soc_dai_set_dma_data(cpu_dai, substream,
-				 &info->dma_params[substream->stream]);
+				 &info->dma_data[substream->stream]);
 	return 0;
 }
 
@@ -366,6 +366,10 @@ static struct snd_soc_dai_driver ep93xx_i2s_dai = {
 	.ops		= &ep93xx_i2s_dai_ops,
 };
 
+static const struct snd_soc_component_driver ep93xx_i2s_component = {
+	.name		= "ep93xx-i2s",
+};
+
 static int ep93xx_i2s_probe(struct platform_device *pdev)
 {
 	struct ep93xx_i2s_info *info;
@@ -403,9 +407,10 @@ static int ep93xx_i2s_probe(struct platform_device *pdev)
 	}
 
 	dev_set_drvdata(&pdev->dev, info);
-	info->dma_params = ep93xx_i2s_dma_params;
+	info->dma_data = ep93xx_i2s_dma_data;
 
-	err = snd_soc_register_dai(&pdev->dev, &ep93xx_i2s_dai);
+	err = snd_soc_register_component(&pdev->dev, &ep93xx_i2s_component,
+					 &ep93xx_i2s_dai, 1);
 	if (err)
 		goto fail_put_lrclk;
 
@@ -426,7 +431,7 @@ static int ep93xx_i2s_remove(struct platform_device *pdev)
 {
 	struct ep93xx_i2s_info *info = dev_get_drvdata(&pdev->dev);
 
-	snd_soc_unregister_dai(&pdev->dev);
+	snd_soc_unregister_component(&pdev->dev);
 	dev_set_drvdata(&pdev->dev, NULL);
 	clk_put(info->lrclk);
 	clk_put(info->sclk);
diff --git a/sound/soc/cirrus/ep93xx-pcm.c b/sound/soc/cirrus/ep93xx-pcm.c
index 72eb7a4..298946f 100644
--- a/sound/soc/cirrus/ep93xx-pcm.c
+++ b/sound/soc/cirrus/ep93xx-pcm.c
@@ -29,8 +29,6 @@
 #include <mach/hardware.h>
 #include <mach/ep93xx-regs.h>
 
-#include "ep93xx-pcm.h"
-
 static const struct snd_pcm_hardware ep93xx_pcm_hardware = {
 	.info			= (SNDRV_PCM_INFO_MMAP		|
 				   SNDRV_PCM_INFO_MMAP_VALID	|
@@ -68,40 +66,11 @@ static bool ep93xx_pcm_dma_filter(struct dma_chan *chan, void *filter_param)
 static int ep93xx_pcm_open(struct snd_pcm_substream *substream)
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-	struct ep93xx_pcm_dma_params *dma_params;
-	struct ep93xx_dma_data *dma_data;
-	int ret;
 
 	snd_soc_set_runtime_hwparams(substream, &ep93xx_pcm_hardware);
 
-	dma_data = kmalloc(sizeof(*dma_data), GFP_KERNEL);
-	if (!dma_data)
-		return -ENOMEM;
-
-	dma_params = snd_soc_dai_get_dma_data(cpu_dai, substream);
-	dma_data->port = dma_params->dma_port;
-	dma_data->name = dma_params->name;
-	dma_data->direction = snd_pcm_substream_to_dma_direction(substream);
-
-	ret = snd_dmaengine_pcm_open(substream, ep93xx_pcm_dma_filter, dma_data);
-	if (ret) {
-		kfree(dma_data);
-		return ret;
-	}
-
-	snd_dmaengine_pcm_set_data(substream, dma_data);
-
-	return 0;
-}
-
-static int ep93xx_pcm_close(struct snd_pcm_substream *substream)
-{
-	struct dma_data *dma_data = snd_dmaengine_pcm_get_data(substream);
-
-	snd_dmaengine_pcm_close(substream);
-	kfree(dma_data);
-	return 0;
+	return snd_dmaengine_pcm_open(substream, ep93xx_pcm_dma_filter,
+			snd_soc_dai_get_dma_data(rtd->cpu_dai, substream));
 }
 
 static int ep93xx_pcm_hw_params(struct snd_pcm_substream *substream,
@@ -131,7 +100,7 @@ static int ep93xx_pcm_mmap(struct snd_pcm_substream *substream,
 
 static struct snd_pcm_ops ep93xx_pcm_ops = {
 	.open		= ep93xx_pcm_open,
-	.close		= ep93xx_pcm_close,
+	.close		= snd_dmaengine_pcm_close,
 	.ioctl		= snd_pcm_lib_ioctl,
 	.hw_params	= ep93xx_pcm_hw_params,
 	.hw_free	= ep93xx_pcm_hw_free,
diff --git a/sound/soc/cirrus/ep93xx-pcm.h b/sound/soc/cirrus/ep93xx-pcm.h
deleted file mode 100644
index 111e112..0000000
--- a/sound/soc/cirrus/ep93xx-pcm.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * sound/soc/ep93xx/ep93xx-pcm.h - EP93xx ALSA PCM interface
- *
- * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
- * Copyright (C) 2006 Applied Data Systems
- *
- * This program is free software; you can 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 _EP93XX_SND_SOC_PCM_H
-#define _EP93XX_SND_SOC_PCM_H
-
-struct ep93xx_pcm_dma_params {
-	char	*name;
-	int	dma_port;
-};
-
-#endif /* _EP93XX_SND_SOC_PCM_H */
diff --git a/sound/soc/cirrus/simone.c b/sound/soc/cirrus/simone.c
index a397bb0..4d094d0 100644
--- a/sound/soc/cirrus/simone.c
+++ b/sound/soc/cirrus/simone.c
@@ -21,8 +21,6 @@
 #include <asm/mach-types.h>
 #include <mach/hardware.h>
 
-#include "ep93xx-pcm.h"
-
 static struct snd_soc_dai_link simone_dai = {
 	.name		= "AC97",
 	.stream_name	= "AC97 HiFi",
diff --git a/sound/soc/cirrus/snappercl15.c b/sound/soc/cirrus/snappercl15.c
index 9d77fe2..6904107 100644
--- a/sound/soc/cirrus/snappercl15.c
+++ b/sound/soc/cirrus/snappercl15.c
@@ -21,7 +21,6 @@
 #include <mach/hardware.h>
 
 #include "../codecs/tlv320aic23.h"
-#include "ep93xx-pcm.h"
 
 #define CODEC_CLOCK 5644800
 
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 45b7256..2f45f00 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -26,6 +26,7 @@ config SND_SOC_ALL_CODECS
 	select SND_SOC_AK4641 if I2C
 	select SND_SOC_AK4642 if I2C
 	select SND_SOC_AK4671 if I2C
+	select SND_SOC_AK5386
 	select SND_SOC_ALC5623 if I2C
 	select SND_SOC_ALC5632 if I2C
 	select SND_SOC_CQ0093VC if MFD_DAVINCI_VOICECODEC
@@ -63,6 +64,7 @@ config SND_SOC_ALL_CODECS
 	select SND_SOC_STA32X if I2C
 	select SND_SOC_STA529 if I2C
 	select SND_SOC_STAC9766 if SND_SOC_AC97_BUS
+	select SND_SOC_TAS5086 if I2C
 	select SND_SOC_TLV320AIC23 if I2C
 	select SND_SOC_TLV320AIC26 if SPI_MASTER
 	select SND_SOC_TLV320AIC32X4 if I2C
@@ -203,6 +205,9 @@ config SND_SOC_AK4642
 config SND_SOC_AK4671
 	tristate
 
+config SND_SOC_AK5386
+	tristate
+
 config SND_SOC_ALC5623
        tristate
 config SND_SOC_ALC5632
@@ -320,11 +325,14 @@ config SND_SOC_STA529
 config SND_SOC_STAC9766
 	tristate
 
+config SND_SOC_TAS5086
+	tristate
+
 config SND_SOC_TLV320AIC23
 	tristate
 
 config SND_SOC_TLV320AIC26
-	tristate "TI TLV320AIC26 Codec support" if SND_SOC_OF_SIMPLE
+	tristate
 	depends on SPI
 
 config SND_SOC_TLV320AIC32X4
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 6a3b3c3..b9e41c9 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -14,6 +14,7 @@ snd-soc-ak4535-objs := ak4535.o
 snd-soc-ak4641-objs := ak4641.o
 snd-soc-ak4642-objs := ak4642.o
 snd-soc-ak4671-objs := ak4671.o
+snd-soc-ak5386-objs := ak5386.o
 snd-soc-arizona-objs := arizona.o
 snd-soc-cq93vc-objs := cq93vc.o
 snd-soc-cs42l51-objs := cs42l51.o
@@ -55,6 +56,7 @@ snd-soc-ssm2602-objs := ssm2602.o
 snd-soc-sta32x-objs := sta32x.o
 snd-soc-sta529-objs := sta529.o
 snd-soc-stac9766-objs := stac9766.o
+snd-soc-tas5086-objs := tas5086.o
 snd-soc-tlv320aic23-objs := tlv320aic23.o
 snd-soc-tlv320aic26-objs := tlv320aic26.o
 snd-soc-tlv320aic3x-objs := tlv320aic3x.o
@@ -137,6 +139,7 @@ obj-$(CONFIG_SND_SOC_AK4535)	+= snd-soc-ak4535.o
 obj-$(CONFIG_SND_SOC_AK4641)	+= snd-soc-ak4641.o
 obj-$(CONFIG_SND_SOC_AK4642)	+= snd-soc-ak4642.o
 obj-$(CONFIG_SND_SOC_AK4671)	+= snd-soc-ak4671.o
+obj-$(CONFIG_SND_SOC_AK5386)	+= snd-soc-ak5386.o
 obj-$(CONFIG_SND_SOC_ALC5623)    += snd-soc-alc5623.o
 obj-$(CONFIG_SND_SOC_ALC5632)	+= snd-soc-alc5632.o
 obj-$(CONFIG_SND_SOC_ARIZONA)	+= snd-soc-arizona.o
@@ -177,6 +180,7 @@ obj-$(CONFIG_SND_SOC_SSM2602)	+= snd-soc-ssm2602.o
 obj-$(CONFIG_SND_SOC_STA32X)   += snd-soc-sta32x.o
 obj-$(CONFIG_SND_SOC_STA529)   += snd-soc-sta529.o
 obj-$(CONFIG_SND_SOC_STAC9766)	+= snd-soc-stac9766.o
+obj-$(CONFIG_SND_SOC_TAS5086)	+= snd-soc-tas5086.o
 obj-$(CONFIG_SND_SOC_TLV320AIC23)	+= snd-soc-tlv320aic23.o
 obj-$(CONFIG_SND_SOC_TLV320AIC26)	+= snd-soc-tlv320aic26.o
 obj-$(CONFIG_SND_SOC_TLV320AIC3X)	+= snd-soc-tlv320aic3x.o
diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c
index 068b3ae..1aa10dd 100644
--- a/sound/soc/codecs/adau1373.c
+++ b/sound/soc/codecs/adau1373.c
@@ -133,6 +133,8 @@ struct adau1373 {
 #define ADAU1373_DAI_FORMAT_DSP		0x3
 
 #define ADAU1373_BCLKDIV_SOURCE		BIT(5)
+#define ADAU1373_BCLKDIV_SR_MASK	(0x07 << 2)
+#define ADAU1373_BCLKDIV_BCLK_MASK	0x03
 #define ADAU1373_BCLKDIV_32		0x03
 #define ADAU1373_BCLKDIV_64		0x02
 #define ADAU1373_BCLKDIV_128		0x01
@@ -937,7 +939,8 @@ static int adau1373_hw_params(struct snd_pcm_substream *substream,
 	adau1373_dai->enable_src = (div != 0);
 
 	snd_soc_update_bits(codec, ADAU1373_BCLKDIV(dai->id),
-		~ADAU1373_BCLKDIV_SOURCE, (div << 2) | ADAU1373_BCLKDIV_64);
+		ADAU1373_BCLKDIV_SR_MASK | ADAU1373_BCLKDIV_BCLK_MASK,
+		(div << 2) | ADAU1373_BCLKDIV_64);
 
 	switch (params_format(params)) {
 	case SNDRV_PCM_FORMAT_S16_LE:
diff --git a/sound/soc/codecs/ak4104.c b/sound/soc/codecs/ak4104.c
index 6f6c335..c7cfdf9 100644
--- a/sound/soc/codecs/ak4104.c
+++ b/sound/soc/codecs/ak4104.c
@@ -55,6 +55,7 @@ static int ak4104_set_dai_fmt(struct snd_soc_dai *codec_dai,
 			      unsigned int format)
 {
 	struct snd_soc_codec *codec = codec_dai->codec;
+	struct ak4104_private *ak4104 = snd_soc_codec_get_drvdata(codec);
 	int val = 0;
 	int ret;
 
@@ -77,9 +78,9 @@ static int ak4104_set_dai_fmt(struct snd_soc_dai *codec_dai,
 	if ((format & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS)
 		return -EINVAL;
 
-	ret = snd_soc_update_bits(codec, AK4104_REG_CONTROL1,
-				  AK4104_CONTROL1_DIF0 | AK4104_CONTROL1_DIF1,
-				  val);
+	ret = regmap_update_bits(ak4104->regmap, AK4104_REG_CONTROL1,
+				 AK4104_CONTROL1_DIF0 | AK4104_CONTROL1_DIF1,
+				 val);
 	if (ret < 0)
 		return ret;
 
@@ -91,11 +92,12 @@ static int ak4104_hw_params(struct snd_pcm_substream *substream,
 			    struct snd_soc_dai *dai)
 {
 	struct snd_soc_codec *codec = dai->codec;
-	int val = 0;
+	struct ak4104_private *ak4104 = snd_soc_codec_get_drvdata(codec);
+	int ret, val = 0;
 
 	/* set the IEC958 bits: consumer mode, no copyright bit */
 	val |= IEC958_AES0_CON_NOT_COPYRIGHT;
-	snd_soc_write(codec, AK4104_REG_CHN_STATUS(0), val);
+	regmap_write(ak4104->regmap, AK4104_REG_CHN_STATUS(0), val);
 
 	val = 0;
 
@@ -132,11 +134,33 @@ static int ak4104_hw_params(struct snd_pcm_substream *substream,
 		return -EINVAL;
 	}
 
-	return snd_soc_write(codec, AK4104_REG_CHN_STATUS(3), val);
+	ret = regmap_write(ak4104->regmap, AK4104_REG_CHN_STATUS(3), val);
+	if (ret < 0)
+		return ret;
+
+	/* enable transmitter */
+	ret = regmap_update_bits(ak4104->regmap, AK4104_REG_TX,
+				 AK4104_TX_TXE, AK4104_TX_TXE);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int ak4104_hw_free(struct snd_pcm_substream *substream,
+			  struct snd_soc_dai *dai)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	struct ak4104_private *ak4104 = snd_soc_codec_get_drvdata(codec);
+
+	/* disable transmitter */
+	return regmap_update_bits(ak4104->regmap, AK4104_REG_TX,
+				  AK4104_TX_TXE, 0);
 }
 
 static const struct snd_soc_dai_ops ak4101_dai_ops = {
 	.hw_params = ak4104_hw_params,
+	.hw_free = ak4104_hw_free,
 	.set_fmt = ak4104_set_dai_fmt,
 };
 
@@ -160,20 +184,17 @@ static int ak4104_probe(struct snd_soc_codec *codec)
 	int ret;
 
 	codec->control_data = ak4104->regmap;
-	ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
-	if (ret != 0)
-		return ret;
 
 	/* set power-up and non-reset bits */
-	ret = snd_soc_update_bits(codec, AK4104_REG_CONTROL1,
-				  AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN,
-				  AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN);
+	ret = regmap_update_bits(ak4104->regmap, AK4104_REG_CONTROL1,
+				 AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN,
+				 AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN);
 	if (ret < 0)
 		return ret;
 
 	/* enable transmitter */
-	ret = snd_soc_update_bits(codec, AK4104_REG_TX,
-				  AK4104_TX_TXE, AK4104_TX_TXE);
+	ret = regmap_update_bits(ak4104->regmap, AK4104_REG_TX,
+				 AK4104_TX_TXE, AK4104_TX_TXE);
 	if (ret < 0)
 		return ret;
 
@@ -182,8 +203,10 @@ static int ak4104_probe(struct snd_soc_codec *codec)
 
 static int ak4104_remove(struct snd_soc_codec *codec)
 {
-	snd_soc_update_bits(codec, AK4104_REG_CONTROL1,
-			    AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN, 0);
+	struct ak4104_private *ak4104 = snd_soc_codec_get_drvdata(codec);
+
+	regmap_update_bits(ak4104->regmap, AK4104_REG_CONTROL1,
+			   AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN, 0);
 
 	return 0;
 }
diff --git a/sound/soc/codecs/ak5386.c b/sound/soc/codecs/ak5386.c
new file mode 100644
index 0000000..1f30398
--- /dev/null
+++ b/sound/soc/codecs/ak5386.c
@@ -0,0 +1,152 @@
+/*
+ * ALSA SoC driver for
+ *    Asahi Kasei AK5386 Single-ended 24-Bit 192kHz delta-sigma ADC
+ *
+ * (c) 2013 Daniel Mack <zonque@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/slab.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/of_device.h>
+#include <sound/soc.h>
+#include <sound/pcm.h>
+#include <sound/initval.h>
+
+struct ak5386_priv {
+	int reset_gpio;
+};
+
+static struct snd_soc_codec_driver soc_codec_ak5386;
+
+static int ak5386_set_dai_fmt(struct snd_soc_dai *codec_dai,
+			      unsigned int format)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+
+	format &= SND_SOC_DAIFMT_FORMAT_MASK;
+	if (format != SND_SOC_DAIFMT_LEFT_J &&
+	    format != SND_SOC_DAIFMT_I2S) {
+		dev_err(codec->dev, "Invalid DAI format\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int ak5386_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 ak5386_priv *priv = snd_soc_codec_get_drvdata(codec);
+
+	/*
+	 * From the datasheet:
+	 *
+	 * All external clocks (MCLK, SCLK and LRCK) must be present unless
+	 * PDN pin = “L”. If these clocks are not provided, the AK5386 may
+	 * draw excess current due to its use of internal dynamically
+	 * refreshed logic. If the external clocks are not present, place
+	 * the AK5386 in power-down mode (PDN pin = “L”).
+	 */
+
+	if (gpio_is_valid(priv->reset_gpio))
+		gpio_set_value(priv->reset_gpio, 1);
+
+	return 0;
+}
+
+static int ak5386_hw_free(struct snd_pcm_substream *substream,
+			  struct snd_soc_dai *dai)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	struct ak5386_priv *priv = snd_soc_codec_get_drvdata(codec);
+
+	if (gpio_is_valid(priv->reset_gpio))
+		gpio_set_value(priv->reset_gpio, 0);
+
+	return 0;
+}
+
+static const struct snd_soc_dai_ops ak5386_dai_ops = {
+	.set_fmt	= ak5386_set_dai_fmt,
+	.hw_params	= ak5386_hw_params,
+	.hw_free	= ak5386_hw_free,
+};
+
+static struct snd_soc_dai_driver ak5386_dai = {
+	.name		= "ak5386-hifi",
+	.capture	= {
+		.stream_name	= "Capture",
+		.channels_min	= 1,
+		.channels_max	= 2,
+		.rates		= SNDRV_PCM_RATE_8000_192000,
+		.formats	= SNDRV_PCM_FMTBIT_S8     |
+				  SNDRV_PCM_FMTBIT_S16_LE |
+				  SNDRV_PCM_FMTBIT_S24_LE |
+				  SNDRV_PCM_FMTBIT_S24_3LE,
+	},
+	.ops	= &ak5386_dai_ops,
+};
+
+#ifdef CONFIG_OF
+static const struct of_device_id ak5386_dt_ids[] = {
+	{ .compatible = "asahi-kasei,ak5386", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, ak5386_dt_ids);
+#endif
+
+static int ak5386_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct ak5386_priv *priv;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->reset_gpio = -EINVAL;
+	dev_set_drvdata(dev, priv);
+
+	if (of_match_device(of_match_ptr(ak5386_dt_ids), dev))
+		priv->reset_gpio = of_get_named_gpio(dev->of_node,
+						      "reset-gpio", 0);
+
+	if (gpio_is_valid(priv->reset_gpio))
+		if (devm_gpio_request_one(dev, priv->reset_gpio,
+					  GPIOF_OUT_INIT_LOW,
+					  "AK5386 Reset"))
+			priv->reset_gpio = -EINVAL;
+
+	return snd_soc_register_codec(dev, &soc_codec_ak5386,
+				      &ak5386_dai, 1);
+}
+
+static int ak5386_remove(struct platform_device *pdev)
+{
+	snd_soc_unregister_codec(&pdev->dev);
+	return 0;
+}
+
+static struct platform_driver ak5386_driver = {
+	.probe		= ak5386_probe,
+	.remove		= ak5386_remove,
+	.driver		= {
+		.name	= "ak5386",
+		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(ak5386_dt_ids),
+	},
+};
+
+module_platform_driver(ak5386_driver);
+
+MODULE_DESCRIPTION("ASoC driver for AK5386 ADC");
+MODULE_AUTHOR("Daniel Mack <zonque@gmail.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c
index ac948a6..389f232 100644
--- a/sound/soc/codecs/arizona.c
+++ b/sound/soc/codecs/arizona.c
@@ -10,6 +10,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/delay.h>
 #include <linux/gcd.h>
 #include <linux/module.h>
 #include <linux/pm_runtime.h>
@@ -65,6 +66,163 @@
 #define arizona_aif_dbg(_dai, fmt, ...) \
 	dev_dbg(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__)
 
+static int arizona_spk_ev(struct snd_soc_dapm_widget *w,
+			  struct snd_kcontrol *kcontrol,
+			  int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
+	struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
+	bool manual_ena = false;
+	int val;
+
+	switch (arizona->type) {
+	case WM5102:
+		switch (arizona->rev) {
+		case 0:
+			break;
+		default:
+			manual_ena = true;
+			break;
+		}
+	default:
+		break;
+	}
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		if (!priv->spk_ena && manual_ena) {
+			snd_soc_write(codec, 0x4f5, 0x25a);
+			priv->spk_ena_pending = true;
+		}
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		val = snd_soc_read(codec, ARIZONA_INTERRUPT_RAW_STATUS_3);
+		if (val & ARIZONA_SPK_SHUTDOWN_STS) {
+			dev_crit(arizona->dev,
+				 "Speaker not enabled due to temperature\n");
+			return -EBUSY;
+		}
+
+		snd_soc_update_bits(codec, ARIZONA_OUTPUT_ENABLES_1,
+				    1 << w->shift, 1 << w->shift);
+
+		if (priv->spk_ena_pending) {
+			msleep(75);
+			snd_soc_write(codec, 0x4f5, 0xda);
+			priv->spk_ena_pending = false;
+			priv->spk_ena++;
+		}
+		break;
+	case SND_SOC_DAPM_PRE_PMD:
+		if (manual_ena) {
+			priv->spk_ena--;
+			if (!priv->spk_ena)
+				snd_soc_write(codec, 0x4f5, 0x25a);
+		}
+
+		snd_soc_update_bits(codec, ARIZONA_OUTPUT_ENABLES_1,
+				    1 << w->shift, 0);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		if (manual_ena) {
+			if (!priv->spk_ena)
+				snd_soc_write(codec, 0x4f5, 0x0da);
+		}
+		break;
+	}
+
+	return 0;
+}
+
+static irqreturn_t arizona_thermal_warn(int irq, void *data)
+{
+	struct arizona *arizona = data;
+	unsigned int val;
+	int ret;
+
+	ret = regmap_read(arizona->regmap, ARIZONA_INTERRUPT_RAW_STATUS_3,
+			  &val);
+	if (ret != 0) {
+		dev_err(arizona->dev, "Failed to read thermal status: %d\n",
+			ret);
+	} else if (val & ARIZONA_SPK_SHUTDOWN_WARN_STS) {
+		dev_crit(arizona->dev, "Thermal warning\n");
+	}
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t arizona_thermal_shutdown(int irq, void *data)
+{
+	struct arizona *arizona = data;
+	unsigned int val;
+	int ret;
+
+	ret = regmap_read(arizona->regmap, ARIZONA_INTERRUPT_RAW_STATUS_3,
+			  &val);
+	if (ret != 0) {
+		dev_err(arizona->dev, "Failed to read thermal status: %d\n",
+			ret);
+	} else if (val & ARIZONA_SPK_SHUTDOWN_STS) {
+		dev_crit(arizona->dev, "Thermal shutdown\n");
+		ret = regmap_update_bits(arizona->regmap,
+					 ARIZONA_OUTPUT_ENABLES_1,
+					 ARIZONA_OUT4L_ENA |
+					 ARIZONA_OUT4R_ENA, 0);
+		if (ret != 0)
+			dev_crit(arizona->dev,
+				 "Failed to disable speaker outputs: %d\n",
+				 ret);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static const struct snd_soc_dapm_widget arizona_spkl =
+	SND_SOC_DAPM_PGA_E("OUT4L", SND_SOC_NOPM,
+			   ARIZONA_OUT4L_ENA_SHIFT, 0, NULL, 0, arizona_spk_ev,
+			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU);
+
+static const struct snd_soc_dapm_widget arizona_spkr =
+	SND_SOC_DAPM_PGA_E("OUT4R", SND_SOC_NOPM,
+			   ARIZONA_OUT4R_ENA_SHIFT, 0, NULL, 0, arizona_spk_ev,
+			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU);
+
+int arizona_init_spk(struct snd_soc_codec *codec)
+{
+	struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
+	struct arizona *arizona = priv->arizona;
+	int ret;
+
+	ret = snd_soc_dapm_new_controls(&codec->dapm, &arizona_spkl, 1);
+	if (ret != 0)
+		return ret;
+
+	ret = snd_soc_dapm_new_controls(&codec->dapm, &arizona_spkr, 1);
+	if (ret != 0)
+		return ret;
+
+	ret = arizona_request_irq(arizona, ARIZONA_IRQ_SPK_SHUTDOWN_WARN,
+				  "Thermal warning", arizona_thermal_warn,
+				  arizona);
+	if (ret != 0)
+		dev_err(arizona->dev,
+			"Failed to get thermal warning IRQ: %d\n",
+			ret);
+
+	ret = arizona_request_irq(arizona, ARIZONA_IRQ_SPK_SHUTDOWN,
+				  "Thermal shutdown", arizona_thermal_shutdown,
+				  arizona);
+	if (ret != 0)
+		dev_err(arizona->dev,
+			"Failed to get thermal shutdown IRQ: %d\n",
+			ret);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(arizona_init_spk);
+
 const char *arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS] = {
 	"None",
 	"Tone Generator 1",
@@ -274,6 +432,33 @@ EXPORT_SYMBOL_GPL(arizona_mixer_values);
 const DECLARE_TLV_DB_SCALE(arizona_mixer_tlv, -3200, 100, 0);
 EXPORT_SYMBOL_GPL(arizona_mixer_tlv);
 
+const char *arizona_rate_text[ARIZONA_RATE_ENUM_SIZE] = {
+	"SYNCCLK rate", "8kHz", "16kHz", "ASYNCCLK rate",
+};
+EXPORT_SYMBOL_GPL(arizona_rate_text);
+
+const int arizona_rate_val[ARIZONA_RATE_ENUM_SIZE] = {
+	0, 1, 2, 8,
+};
+EXPORT_SYMBOL_GPL(arizona_rate_val);
+
+
+const struct soc_enum arizona_isrc_fsl[] = {
+	SOC_VALUE_ENUM_SINGLE(ARIZONA_ISRC_1_CTRL_2,
+			      ARIZONA_ISRC1_FSL_SHIFT, 0xf,
+			      ARIZONA_RATE_ENUM_SIZE,
+			      arizona_rate_text, arizona_rate_val),
+	SOC_VALUE_ENUM_SINGLE(ARIZONA_ISRC_2_CTRL_2,
+			      ARIZONA_ISRC2_FSL_SHIFT, 0xf,
+			      ARIZONA_RATE_ENUM_SIZE,
+			      arizona_rate_text, arizona_rate_val),
+	SOC_VALUE_ENUM_SINGLE(ARIZONA_ISRC_3_CTRL_2,
+			      ARIZONA_ISRC3_FSL_SHIFT, 0xf,
+			      ARIZONA_RATE_ENUM_SIZE,
+			      arizona_rate_text, arizona_rate_val),
+};
+EXPORT_SYMBOL_GPL(arizona_isrc_fsl);
+
 static const char *arizona_vol_ramp_text[] = {
 	"0ms/6dB", "0.5ms/6dB", "1ms/6dB", "2ms/6dB", "4ms/6dB", "8ms/6dB",
 	"15ms/6dB", "30ms/6dB",
@@ -332,9 +517,27 @@ const struct soc_enum arizona_ng_hold =
 			4, arizona_ng_hold_text);
 EXPORT_SYMBOL_GPL(arizona_ng_hold);
 
+static void arizona_in_set_vu(struct snd_soc_codec *codec, int ena)
+{
+	struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
+	unsigned int val;
+	int i;
+
+	if (ena)
+		val = ARIZONA_IN_VU;
+	else
+		val = 0;
+
+	for (i = 0; i < priv->num_inputs; i++)
+		snd_soc_update_bits(codec,
+				    ARIZONA_ADC_DIGITAL_VOLUME_1L + (i * 4),
+				    ARIZONA_IN_VU, val);
+}
+
 int arizona_in_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol,
 		  int event)
 {
+	struct arizona_priv *priv = snd_soc_codec_get_drvdata(w->codec);
 	unsigned int reg;
 
 	if (w->shift % 2)
@@ -343,13 +546,29 @@ int arizona_in_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol,
 		reg = ARIZONA_ADC_DIGITAL_VOLUME_1R + ((w->shift / 2) * 8);
 
 	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		priv->in_pending++;
+		break;
 	case SND_SOC_DAPM_POST_PMU:
 		snd_soc_update_bits(w->codec, reg, ARIZONA_IN1L_MUTE, 0);
+
+		/* If this is the last input pending then allow VU */
+		priv->in_pending--;
+		if (priv->in_pending == 0) {
+			msleep(1);
+			arizona_in_set_vu(w->codec, 1);
+		}
 		break;
 	case SND_SOC_DAPM_PRE_PMD:
-		snd_soc_update_bits(w->codec, reg, ARIZONA_IN1L_MUTE,
-				    ARIZONA_IN1L_MUTE);
+		snd_soc_update_bits(w->codec, reg,
+				    ARIZONA_IN1L_MUTE | ARIZONA_IN_VU,
+				    ARIZONA_IN1L_MUTE | ARIZONA_IN_VU);
 		break;
+	case SND_SOC_DAPM_POST_PMD:
+		/* Disable volume updates if no inputs are enabled */
+		reg = snd_soc_read(w->codec, ARIZONA_INPUT_ENABLES);
+		if (reg == 0)
+			arizona_in_set_vu(w->codec, 0);
 	}
 
 	return 0;
@@ -360,10 +579,61 @@ int arizona_out_ev(struct snd_soc_dapm_widget *w,
 		   struct snd_kcontrol *kcontrol,
 		   int event)
 {
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		switch (w->shift) {
+		case ARIZONA_OUT1L_ENA_SHIFT:
+		case ARIZONA_OUT1R_ENA_SHIFT:
+		case ARIZONA_OUT2L_ENA_SHIFT:
+		case ARIZONA_OUT2R_ENA_SHIFT:
+		case ARIZONA_OUT3L_ENA_SHIFT:
+		case ARIZONA_OUT3R_ENA_SHIFT:
+			msleep(17);
+			break;
+
+		default:
+			break;
+		}
+		break;
+	}
+
 	return 0;
 }
 EXPORT_SYMBOL_GPL(arizona_out_ev);
 
+int arizona_hp_ev(struct snd_soc_dapm_widget *w,
+		   struct snd_kcontrol *kcontrol,
+		   int event)
+{
+	struct arizona_priv *priv = snd_soc_codec_get_drvdata(w->codec);
+	unsigned int mask = 1 << w->shift;
+	unsigned int val;
+
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		val = mask;
+		break;
+	case SND_SOC_DAPM_PRE_PMD:
+		val = 0;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* Store the desired state for the HP outputs */
+	priv->arizona->hp_ena &= ~mask;
+	priv->arizona->hp_ena |= val;
+
+	/* Force off if HPDET magic is active */
+	if (priv->arizona->hpdet_magic)
+		val = 0;
+
+	snd_soc_update_bits(w->codec, ARIZONA_OUTPUT_ENABLES_1, mask, val);
+
+	return arizona_out_ev(w, kcontrol, event);
+}
+EXPORT_SYMBOL_GPL(arizona_hp_ev);
+
 static unsigned int arizona_sysclk_48k_rates[] = {
 	6144000,
 	12288000,
@@ -469,27 +739,27 @@ int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id,
 		break;
 	case 11289600:
 	case 12288000:
-		val |= 1 << ARIZONA_SYSCLK_FREQ_SHIFT;
+		val |= ARIZONA_CLK_12MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
 		break;
 	case 22579200:
 	case 24576000:
-		val |= 2 << ARIZONA_SYSCLK_FREQ_SHIFT;
+		val |= ARIZONA_CLK_24MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
 		break;
 	case 45158400:
 	case 49152000:
-		val |= 3 << ARIZONA_SYSCLK_FREQ_SHIFT;
+		val |= ARIZONA_CLK_49MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
 		break;
 	case 67737600:
 	case 73728000:
-		val |= 4 << ARIZONA_SYSCLK_FREQ_SHIFT;
+		val |= ARIZONA_CLK_73MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
 		break;
 	case 90316800:
 	case 98304000:
-		val |= 5 << ARIZONA_SYSCLK_FREQ_SHIFT;
+		val |= ARIZONA_CLK_98MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
 		break;
 	case 135475200:
 	case 147456000:
-		val |= 6 << ARIZONA_SYSCLK_FREQ_SHIFT;
+		val |= ARIZONA_CLK_147MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
 		break;
 	case 0:
 		dev_dbg(arizona->dev, "%s cleared\n", name);
@@ -783,7 +1053,7 @@ static int arizona_hw_params(struct snd_pcm_substream *substream,
 	struct arizona *arizona = priv->arizona;
 	int base = dai->driver->base;
 	const int *rates;
-	int i, ret;
+	int i, ret, val;
 	int chan_limit = arizona->pdata.max_channels_clocked[dai->id - 1];
 	int bclk, lrclk, wl, frame, bclk_target;
 
@@ -799,6 +1069,13 @@ static int arizona_hw_params(struct snd_pcm_substream *substream,
 		bclk_target *= chan_limit;
 	}
 
+	/* Force stereo for I2S mode */
+	val = snd_soc_read(codec, base + ARIZONA_AIF_FORMAT);
+	if (params_channels(params) == 1 && (val & ARIZONA_AIF1_FMT_MASK)) {
+		arizona_aif_dbg(dai, "Forcing stereo mode\n");
+		bclk_target *= 2;
+	}
+
 	for (i = 0; i < ARRAY_SIZE(arizona_44k1_bclk_rates); i++) {
 		if (rates[i] >= bclk_target &&
 		    rates[i] % params_rate(params) == 0) {
@@ -955,6 +1232,16 @@ static struct {
 	{ 1000000, 13500000, 0,  1 },
 };
 
+static struct {
+	unsigned int min;
+	unsigned int max;
+	u16 gain;
+} fll_gains[] = {
+	{       0,   256000, 0 },
+	{  256000,  1000000, 2 },
+	{ 1000000, 13500000, 4 },
+};
+
 struct arizona_fll_cfg {
 	int n;
 	int theta;
@@ -962,6 +1249,7 @@ struct arizona_fll_cfg {
 	int refdiv;
 	int outdiv;
 	int fratio;
+	int gain;
 };
 
 static int arizona_calc_fll(struct arizona_fll *fll,
@@ -1021,6 +1309,18 @@ static int arizona_calc_fll(struct arizona_fll *fll,
 		return -EINVAL;
 	}
 
+	for (i = 0; i < ARRAY_SIZE(fll_gains); i++) {
+		if (fll_gains[i].min <= Fref && Fref <= fll_gains[i].max) {
+			cfg->gain = fll_gains[i].gain;
+			break;
+		}
+	}
+	if (i == ARRAY_SIZE(fll_gains)) {
+		arizona_fll_err(fll, "Unable to find gain for Fref=%uHz\n",
+				Fref);
+		return -EINVAL;
+	}
+
 	cfg->n = target / (ratio * Fref);
 
 	if (target % (ratio * Fref)) {
@@ -1048,13 +1348,15 @@ static int arizona_calc_fll(struct arizona_fll *fll,
 			cfg->n, cfg->theta, cfg->lambda);
 	arizona_fll_dbg(fll, "FRATIO=%x(%d) OUTDIV=%x REFCLK_DIV=%x\n",
 			cfg->fratio, cfg->fratio, cfg->outdiv, cfg->refdiv);
+	arizona_fll_dbg(fll, "GAIN=%d\n", cfg->gain);
 
 	return 0;
 
 }
 
 static void arizona_apply_fll(struct arizona *arizona, unsigned int base,
-			      struct arizona_fll_cfg *cfg, int source)
+			      struct arizona_fll_cfg *cfg, int source,
+			      bool sync)
 {
 	regmap_update_bits(arizona->regmap, base + 3,
 			   ARIZONA_FLL1_THETA_MASK, cfg->theta);
@@ -1069,87 +1371,84 @@ static void arizona_apply_fll(struct arizona *arizona, unsigned int base,
 			   cfg->refdiv << ARIZONA_FLL1_CLK_REF_DIV_SHIFT |
 			   source << ARIZONA_FLL1_CLK_REF_SRC_SHIFT);
 
+	if (sync)
+		regmap_update_bits(arizona->regmap, base + 0x7,
+				   ARIZONA_FLL1_GAIN_MASK,
+				   cfg->gain << ARIZONA_FLL1_GAIN_SHIFT);
+	else
+		regmap_update_bits(arizona->regmap, base + 0x9,
+				   ARIZONA_FLL1_GAIN_MASK,
+				   cfg->gain << ARIZONA_FLL1_GAIN_SHIFT);
+
 	regmap_update_bits(arizona->regmap, base + 2,
 			   ARIZONA_FLL1_CTRL_UPD | ARIZONA_FLL1_N_MASK,
 			   ARIZONA_FLL1_CTRL_UPD | cfg->n);
 }
 
-int arizona_set_fll(struct arizona_fll *fll, int source,
-		    unsigned int Fref, unsigned int Fout)
+static bool arizona_is_enabled_fll(struct arizona_fll *fll)
 {
 	struct arizona *arizona = fll->arizona;
-	struct arizona_fll_cfg cfg, sync;
-	unsigned int reg, val;
-	int syncsrc;
-	bool ena;
+	unsigned int reg;
 	int ret;
 
-	if (fll->fref == Fref && fll->fout == Fout)
-		return 0;
-
 	ret = regmap_read(arizona->regmap, fll->base + 1, &reg);
 	if (ret != 0) {
 		arizona_fll_err(fll, "Failed to read current state: %d\n",
 				ret);
 		return ret;
 	}
-	ena = reg & ARIZONA_FLL1_ENA;
 
-	if (Fout) {
-		/* Do we have a 32kHz reference? */
-		regmap_read(arizona->regmap, ARIZONA_CLOCK_32K_1, &val);
-		switch (val & ARIZONA_CLK_32K_SRC_MASK) {
-		case ARIZONA_CLK_SRC_MCLK1:
-		case ARIZONA_CLK_SRC_MCLK2:
-			syncsrc = val & ARIZONA_CLK_32K_SRC_MASK;
-			break;
-		default:
-			syncsrc = -1;
-		}
+	return reg & ARIZONA_FLL1_ENA;
+}
 
-		if (source == syncsrc)
-			syncsrc = -1;
+static void arizona_enable_fll(struct arizona_fll *fll,
+			      struct arizona_fll_cfg *ref,
+			      struct arizona_fll_cfg *sync)
+{
+	struct arizona *arizona = fll->arizona;
+	int ret;
 
-		if (syncsrc >= 0) {
-			ret = arizona_calc_fll(fll, &sync, Fref, Fout);
-			if (ret != 0)
-				return ret;
+	/*
+	 * If we have both REFCLK and SYNCCLK then enable both,
+	 * otherwise apply the SYNCCLK settings to REFCLK.
+	 */
+	if (fll->ref_src >= 0 && fll->ref_src != fll->sync_src) {
+		regmap_update_bits(arizona->regmap, fll->base + 5,
+				   ARIZONA_FLL1_OUTDIV_MASK,
+				   ref->outdiv << ARIZONA_FLL1_OUTDIV_SHIFT);
+
+		arizona_apply_fll(arizona, fll->base, ref, fll->ref_src,
+				  false);
+		if (fll->sync_src >= 0)
+			arizona_apply_fll(arizona, fll->base + 0x10, sync,
+					  fll->sync_src, true);
+	} else if (fll->sync_src >= 0) {
+		regmap_update_bits(arizona->regmap, fll->base + 5,
+				   ARIZONA_FLL1_OUTDIV_MASK,
+				   sync->outdiv << ARIZONA_FLL1_OUTDIV_SHIFT);
+
+		arizona_apply_fll(arizona, fll->base, sync,
+				  fll->sync_src, false);
 
-			ret = arizona_calc_fll(fll, &cfg, 32768, Fout);
-			if (ret != 0)
-				return ret;
-		} else {
-			ret = arizona_calc_fll(fll, &cfg, Fref, Fout);
-			if (ret != 0)
-				return ret;
-		}
-	} else {
-		regmap_update_bits(arizona->regmap, fll->base + 1,
-				   ARIZONA_FLL1_ENA, 0);
 		regmap_update_bits(arizona->regmap, fll->base + 0x11,
 				   ARIZONA_FLL1_SYNC_ENA, 0);
-
-		if (ena)
-			pm_runtime_put_autosuspend(arizona->dev);
-
-		fll->fref = Fref;
-		fll->fout = Fout;
-
-		return 0;
-	}
-
-	regmap_update_bits(arizona->regmap, fll->base + 5,
-			   ARIZONA_FLL1_OUTDIV_MASK,
-			   cfg.outdiv << ARIZONA_FLL1_OUTDIV_SHIFT);
-
-	if (syncsrc >= 0) {
-		arizona_apply_fll(arizona, fll->base, &cfg, syncsrc);
-		arizona_apply_fll(arizona, fll->base + 0x10, &sync, source);
 	} else {
-		arizona_apply_fll(arizona, fll->base, &cfg, source);
+		arizona_fll_err(fll, "No clocks provided\n");
+		return;
 	}
 
-	if (!ena)
+	/*
+	 * Increase the bandwidth if we're not using a low frequency
+	 * sync source.
+	 */
+	if (fll->sync_src >= 0 && fll->sync_freq > 100000)
+		regmap_update_bits(arizona->regmap, fll->base + 0x17,
+				   ARIZONA_FLL1_SYNC_BW, 0);
+	else
+		regmap_update_bits(arizona->regmap, fll->base + 0x17,
+				   ARIZONA_FLL1_SYNC_BW, ARIZONA_FLL1_SYNC_BW);
+
+	if (!arizona_is_enabled_fll(fll))
 		pm_runtime_get(arizona->dev);
 
 	/* Clear any pending completions */
@@ -1157,7 +1456,8 @@ int arizona_set_fll(struct arizona_fll *fll, int source,
 
 	regmap_update_bits(arizona->regmap, fll->base + 1,
 			   ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA);
-	if (syncsrc >= 0)
+	if (fll->ref_src >= 0 && fll->sync_src >= 0 &&
+	    fll->ref_src != fll->sync_src)
 		regmap_update_bits(arizona->regmap, fll->base + 0x11,
 				   ARIZONA_FLL1_SYNC_ENA,
 				   ARIZONA_FLL1_SYNC_ENA);
@@ -1166,10 +1466,88 @@ int arizona_set_fll(struct arizona_fll *fll, int source,
 					  msecs_to_jiffies(250));
 	if (ret == 0)
 		arizona_fll_warn(fll, "Timed out waiting for lock\n");
+}
+
+static void arizona_disable_fll(struct arizona_fll *fll)
+{
+	struct arizona *arizona = fll->arizona;
+	bool change;
+
+	regmap_update_bits_check(arizona->regmap, fll->base + 1,
+				 ARIZONA_FLL1_ENA, 0, &change);
+	regmap_update_bits(arizona->regmap, fll->base + 0x11,
+			   ARIZONA_FLL1_SYNC_ENA, 0);
+
+	if (change)
+		pm_runtime_put_autosuspend(arizona->dev);
+}
+
+int arizona_set_fll_refclk(struct arizona_fll *fll, int source,
+			   unsigned int Fref, unsigned int Fout)
+{
+	struct arizona_fll_cfg ref, sync;
+	int ret;
+
+	if (fll->ref_src == source && fll->ref_freq == Fref)
+		return 0;
+
+	if (fll->fout && Fref > 0) {
+		ret = arizona_calc_fll(fll, &ref, Fref, fll->fout);
+		if (ret != 0)
+			return ret;
+
+		if (fll->sync_src >= 0) {
+			ret = arizona_calc_fll(fll, &sync, fll->sync_freq,
+					       fll->fout);
+			if (ret != 0)
+				return ret;
+		}
+	}
+
+	fll->ref_src = source;
+	fll->ref_freq = Fref;
 
-	fll->fref = Fref;
+	if (fll->fout && Fref > 0) {
+		arizona_enable_fll(fll, &ref, &sync);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(arizona_set_fll_refclk);
+
+int arizona_set_fll(struct arizona_fll *fll, int source,
+		    unsigned int Fref, unsigned int Fout)
+{
+	struct arizona_fll_cfg ref, sync;
+	int ret;
+
+	if (fll->sync_src == source &&
+	    fll->sync_freq == Fref && fll->fout == Fout)
+		return 0;
+
+	if (Fout) {
+		if (fll->ref_src >= 0) {
+			ret = arizona_calc_fll(fll, &ref, fll->ref_freq,
+					       Fout);
+			if (ret != 0)
+				return ret;
+		}
+
+		ret = arizona_calc_fll(fll, &sync, Fref, Fout);
+		if (ret != 0)
+			return ret;
+	}
+
+	fll->sync_src = source;
+	fll->sync_freq = Fref;
 	fll->fout = Fout;
 
+	if (Fout) {
+		arizona_enable_fll(fll, &ref, &sync);
+	} else {
+		arizona_disable_fll(fll);
+	}
+
 	return 0;
 }
 EXPORT_SYMBOL_GPL(arizona_set_fll);
@@ -1178,12 +1556,26 @@ int arizona_init_fll(struct arizona *arizona, int id, int base, int lock_irq,
 		     int ok_irq, struct arizona_fll *fll)
 {
 	int ret;
+	unsigned int val;
 
 	init_completion(&fll->ok);
 
 	fll->id = id;
 	fll->base = base;
 	fll->arizona = arizona;
+	fll->sync_src = ARIZONA_FLL_SRC_NONE;
+
+	/* Configure default refclk to 32kHz if we have one */
+	regmap_read(arizona->regmap, ARIZONA_CLOCK_32K_1, &val);
+	switch (val & ARIZONA_CLK_32K_SRC_MASK) {
+	case ARIZONA_CLK_SRC_MCLK1:
+	case ARIZONA_CLK_SRC_MCLK2:
+		fll->ref_src = val & ARIZONA_CLK_32K_SRC_MASK;
+		break;
+	default:
+		fll->ref_src = ARIZONA_FLL_SRC_NONE;
+	}
+	fll->ref_freq = 32768;
 
 	snprintf(fll->lock_name, sizeof(fll->lock_name), "FLL%d lock", id);
 	snprintf(fll->clock_ok_name, sizeof(fll->clock_ok_name),
diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h
index 116372c..af39f10 100644
--- a/sound/soc/codecs/arizona.h
+++ b/sound/soc/codecs/arizona.h
@@ -32,6 +32,7 @@
 #define ARIZONA_CLK_SRC_AIF2BCLK 0x9
 #define ARIZONA_CLK_SRC_AIF3BCLK 0xa
 
+#define ARIZONA_FLL_SRC_NONE      -1
 #define ARIZONA_FLL_SRC_MCLK1      0
 #define ARIZONA_FLL_SRC_MCLK2      1
 #define ARIZONA_FLL_SRC_SLIMCLK    3
@@ -48,6 +49,14 @@
 #define ARIZONA_MIXER_VOL_SHIFT                 1
 #define ARIZONA_MIXER_VOL_WIDTH                 7
 
+#define ARIZONA_CLK_6MHZ   0
+#define ARIZONA_CLK_12MHZ  1
+#define ARIZONA_CLK_24MHZ  2
+#define ARIZONA_CLK_49MHZ  3
+#define ARIZONA_CLK_73MHZ  4
+#define ARIZONA_CLK_98MHZ  5
+#define ARIZONA_CLK_147MHZ 6
+
 #define ARIZONA_MAX_DAI  4
 #define ARIZONA_MAX_ADSP 4
 
@@ -64,6 +73,12 @@ struct arizona_priv {
 	int sysclk;
 	int asyncclk;
 	struct arizona_dai_priv dai[ARIZONA_MAX_DAI];
+
+	int num_inputs;
+	unsigned int in_pending;
+
+	unsigned int spk_ena:2;
+	unsigned int spk_ena_pending:1;
 };
 
 #define ARIZONA_NUM_MIXER_INPUTS 99
@@ -165,6 +180,12 @@ extern int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS];
 	ARIZONA_MIXER_ROUTES(name, name "L"), \
 	ARIZONA_MIXER_ROUTES(name, name "R")
 
+#define ARIZONA_RATE_ENUM_SIZE 4
+extern const char *arizona_rate_text[ARIZONA_RATE_ENUM_SIZE];
+extern const int arizona_rate_val[ARIZONA_RATE_ENUM_SIZE];
+
+extern const struct soc_enum arizona_isrc_fsl[];
+
 extern const struct soc_enum arizona_in_vi_ramp;
 extern const struct soc_enum arizona_in_vd_ramp;
 
@@ -184,6 +205,9 @@ extern int arizona_in_ev(struct snd_soc_dapm_widget *w,
 extern int arizona_out_ev(struct snd_soc_dapm_widget *w,
 			  struct snd_kcontrol *kcontrol,
 			  int event);
+extern int arizona_hp_ev(struct snd_soc_dapm_widget *w,
+			 struct snd_kcontrol *kcontrol,
+			 int event);
 
 extern int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id,
 			      int source, unsigned int freq, int dir);
@@ -198,8 +222,12 @@ struct arizona_fll {
 	unsigned int base;
 	unsigned int vco_mult;
 	struct completion ok;
-	unsigned int fref;
+
 	unsigned int fout;
+	int sync_src;
+	unsigned int sync_freq;
+	int ref_src;
+	unsigned int ref_freq;
 
 	char lock_name[ARIZONA_FLL_NAME_LEN];
 	char clock_ok_name[ARIZONA_FLL_NAME_LEN];
@@ -207,9 +235,13 @@ struct arizona_fll {
 
 extern int arizona_init_fll(struct arizona *arizona, int id, int base,
 			    int lock_irq, int ok_irq, struct arizona_fll *fll);
+extern int arizona_set_fll_refclk(struct arizona_fll *fll, int source,
+				  unsigned int Fref, unsigned int Fout);
 extern int arizona_set_fll(struct arizona_fll *fll, int source,
 			   unsigned int Fref, unsigned int Fout);
 
+extern int arizona_init_spk(struct snd_soc_codec *codec);
+
 extern int arizona_init_dai(struct arizona_priv *priv, int dai);
 
 int arizona_set_output_mode(struct snd_soc_codec *codec, int output,
diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c
index 2415a41..03036b3 100644
--- a/sound/soc/codecs/cs4271.c
+++ b/sound/soc/codecs/cs4271.c
@@ -39,17 +39,15 @@
 
 /*
  * CS4271 registers
- * High byte represents SPI chip address (0x10) + write command (0)
- * Low byte - codec register address
  */
-#define CS4271_MODE1	0x2001	/* Mode Control 1 */
-#define CS4271_DACCTL	0x2002	/* DAC Control */
-#define CS4271_DACVOL	0x2003	/* DAC Volume & Mixing Control */
-#define CS4271_VOLA	0x2004	/* DAC Channel A Volume Control */
-#define CS4271_VOLB	0x2005	/* DAC Channel B Volume Control */
-#define CS4271_ADCCTL	0x2006	/* ADC Control */
-#define CS4271_MODE2	0x2007	/* Mode Control 2 */
-#define CS4271_CHIPID	0x2008	/* Chip ID */
+#define CS4271_MODE1	0x01	/* Mode Control 1 */
+#define CS4271_DACCTL	0x02	/* DAC Control */
+#define CS4271_DACVOL	0x03	/* DAC Volume & Mixing Control */
+#define CS4271_VOLA	0x04	/* DAC Channel A Volume Control */
+#define CS4271_VOLB	0x05	/* DAC Channel B Volume Control */
+#define CS4271_ADCCTL	0x06	/* ADC Control */
+#define CS4271_MODE2	0x07	/* Mode Control 2 */
+#define CS4271_CHIPID	0x08	/* Chip ID */
 
 #define CS4271_FIRSTREG	CS4271_MODE1
 #define CS4271_LASTREG	CS4271_MODE2
@@ -144,23 +142,27 @@
  * Array do not include Chip ID, as codec driver does not use
  * registers read operations at all
  */
-static const u8 cs4271_dflt_reg[CS4271_NR_REGS] = {
-	0,
-	0,
-	CS4271_DACCTL_AMUTE,
-	CS4271_DACVOL_SOFT | CS4271_DACVOL_ATAPI_AL_BR,
-	0,
-	0,
-	0,
-	0,
+static const struct reg_default cs4271_reg_defaults[] = {
+	{ CS4271_MODE1,		0, },
+	{ CS4271_DACCTL,	CS4271_DACCTL_AMUTE, },
+	{ CS4271_DACVOL,	CS4271_DACVOL_SOFT | CS4271_DACVOL_ATAPI_AL_BR, },
+	{ CS4271_VOLA,		0, },
+	{ CS4271_VOLB,		0, },
+	{ CS4271_ADCCTL,	0, },
+	{ CS4271_MODE2,		0, },
 };
 
+static bool cs4271_volatile_reg(struct device *dev, unsigned int reg)
+{
+	return reg == CS4271_CHIPID;
+}
+
 struct cs4271_private {
 	/* SND_SOC_I2C or SND_SOC_SPI */
-	enum snd_soc_control_type	bus_type;
 	unsigned int			mclk;
 	bool				master;
 	bool				deemph;
+	struct regmap			*regmap;
 	/* Current sample rate for de-emphasis control */
 	int				rate;
 	/* GPIO driving Reset pin, if any */
@@ -210,14 +212,14 @@ static int cs4271_set_dai_fmt(struct snd_soc_dai *codec_dai,
 	switch (format & SND_SOC_DAIFMT_FORMAT_MASK) {
 	case SND_SOC_DAIFMT_LEFT_J:
 		val |= CS4271_MODE1_DAC_DIF_LJ;
-		ret = snd_soc_update_bits(codec, CS4271_ADCCTL,
+		ret = regmap_update_bits(cs4271->regmap, CS4271_ADCCTL,
 			CS4271_ADCCTL_ADC_DIF_MASK, CS4271_ADCCTL_ADC_DIF_LJ);
 		if (ret < 0)
 			return ret;
 		break;
 	case SND_SOC_DAIFMT_I2S:
 		val |= CS4271_MODE1_DAC_DIF_I2S;
-		ret = snd_soc_update_bits(codec, CS4271_ADCCTL,
+		ret = regmap_update_bits(cs4271->regmap, CS4271_ADCCTL,
 			CS4271_ADCCTL_ADC_DIF_MASK, CS4271_ADCCTL_ADC_DIF_I2S);
 		if (ret < 0)
 			return ret;
@@ -227,7 +229,7 @@ static int cs4271_set_dai_fmt(struct snd_soc_dai *codec_dai,
 		return -EINVAL;
 	}
 
-	ret = snd_soc_update_bits(codec, CS4271_MODE1,
+	ret = regmap_update_bits(cs4271->regmap, CS4271_MODE1,
 		CS4271_MODE1_DAC_DIF_MASK | CS4271_MODE1_MASTER, val);
 	if (ret < 0)
 		return ret;
@@ -252,7 +254,7 @@ static int cs4271_set_deemph(struct snd_soc_codec *codec)
 		val <<= 4;
 	}
 
-	ret = snd_soc_update_bits(codec, CS4271_DACCTL,
+	ret = regmap_update_bits(cs4271->regmap, CS4271_DACCTL,
 		CS4271_DACCTL_DEM_MASK, val);
 	if (ret < 0)
 		return ret;
@@ -341,14 +343,14 @@ static int cs4271_hw_params(struct snd_pcm_substream *substream,
 		     !dai->capture_active) ||
 		    (substream->stream == SNDRV_PCM_STREAM_CAPTURE &&
 		     !dai->playback_active)) {
-			ret = snd_soc_update_bits(codec, CS4271_MODE2,
-						  CS4271_MODE2_PDN,
-						  CS4271_MODE2_PDN);
+			ret = regmap_update_bits(cs4271->regmap, CS4271_MODE2,
+						 CS4271_MODE2_PDN,
+						 CS4271_MODE2_PDN);
 			if (ret < 0)
 				return ret;
 
-			ret = snd_soc_update_bits(codec, CS4271_MODE2,
-						  CS4271_MODE2_PDN, 0);
+			ret = regmap_update_bits(cs4271->regmap, CS4271_MODE2,
+						 CS4271_MODE2_PDN, 0);
 			if (ret < 0)
 				return ret;
 		}
@@ -378,7 +380,7 @@ static int cs4271_hw_params(struct snd_pcm_substream *substream,
 
 	val |= cs4271_clk_tab[i].ratio_mask;
 
-	ret = snd_soc_update_bits(codec, CS4271_MODE1,
+	ret = regmap_update_bits(cs4271->regmap, CS4271_MODE1,
 		CS4271_MODE1_MODE_MASK | CS4271_MODE1_DIV_MASK, val);
 	if (ret < 0)
 		return ret;
@@ -386,22 +388,29 @@ static int cs4271_hw_params(struct snd_pcm_substream *substream,
 	return cs4271_set_deemph(codec);
 }
 
-static int cs4271_digital_mute(struct snd_soc_dai *dai, int mute)
+static int cs4271_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
 {
 	struct snd_soc_codec *codec = dai->codec;
+	struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec);
 	int ret;
 	int val_a = 0;
 	int val_b = 0;
 
+	if (stream != SNDRV_PCM_STREAM_PLAYBACK)
+		return 0;
+
 	if (mute) {
 		val_a = CS4271_VOLA_MUTE;
 		val_b = CS4271_VOLB_MUTE;
 	}
 
-	ret = snd_soc_update_bits(codec, CS4271_VOLA, CS4271_VOLA_MUTE, val_a);
+	ret = regmap_update_bits(cs4271->regmap, CS4271_VOLA,
+				 CS4271_VOLA_MUTE, val_a);
 	if (ret < 0)
 		return ret;
-	ret = snd_soc_update_bits(codec, CS4271_VOLB, CS4271_VOLB_MUTE, val_b);
+
+	ret = regmap_update_bits(cs4271->regmap, CS4271_VOLB,
+				 CS4271_VOLB_MUTE, val_b);
 	if (ret < 0)
 		return ret;
 
@@ -436,7 +445,7 @@ static const struct snd_soc_dai_ops cs4271_dai_ops = {
 	.hw_params	= cs4271_hw_params,
 	.set_sysclk	= cs4271_set_dai_sysclk,
 	.set_fmt	= cs4271_set_dai_fmt,
-	.digital_mute	= cs4271_digital_mute,
+	.mute_stream	= cs4271_mute_stream,
 };
 
 static struct snd_soc_dai_driver cs4271_dai = {
@@ -463,25 +472,33 @@ static struct snd_soc_dai_driver cs4271_dai = {
 static int cs4271_soc_suspend(struct snd_soc_codec *codec)
 {
 	int ret;
+	struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec);
+
 	/* Set power-down bit */
-	ret = snd_soc_update_bits(codec, CS4271_MODE2, CS4271_MODE2_PDN,
-				  CS4271_MODE2_PDN);
+	ret = regmap_update_bits(cs4271->regmap, CS4271_MODE2,
+				 CS4271_MODE2_PDN, CS4271_MODE2_PDN);
 	if (ret < 0)
 		return ret;
+
 	return 0;
 }
 
 static int cs4271_soc_resume(struct snd_soc_codec *codec)
 {
 	int ret;
+	struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec);
+
 	/* Restore codec state */
-	ret = snd_soc_cache_sync(codec);
+	ret = regcache_sync(cs4271->regmap);
 	if (ret < 0)
 		return ret;
+
 	/* then disable the power-down bit */
-	ret = snd_soc_update_bits(codec, CS4271_MODE2, CS4271_MODE2_PDN, 0);
+	ret = regmap_update_bits(cs4271->regmap, CS4271_MODE2,
+				 CS4271_MODE2_PDN, 0);
 	if (ret < 0)
 		return ret;
+
 	return 0;
 }
 #else
@@ -542,40 +559,22 @@ static int cs4271_probe(struct snd_soc_codec *codec)
 
 	cs4271->gpio_nreset = gpio_nreset;
 
-	/*
-	 * In case of I2C, chip address specified in board data.
-	 * So cache IO operations use 8 bit codec register address.
-	 * In case of SPI, chip address and register address
-	 * passed together as 16 bit value.
-	 * Anyway, register address is masked with 0xFF inside
-	 * soc-cache code.
-	 */
-	if (cs4271->bus_type == SND_SOC_SPI)
-		ret = snd_soc_codec_set_cache_io(codec, 16, 8,
-			cs4271->bus_type);
-	else
-		ret = snd_soc_codec_set_cache_io(codec, 8, 8,
-			cs4271->bus_type);
-	if (ret) {
-		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
-		return ret;
-	}
-
-	ret = snd_soc_update_bits(codec, CS4271_MODE2,
-				  CS4271_MODE2_PDN | CS4271_MODE2_CPEN,
-				  CS4271_MODE2_PDN | CS4271_MODE2_CPEN);
+	ret = regmap_update_bits(cs4271->regmap, CS4271_MODE2,
+				 CS4271_MODE2_PDN | CS4271_MODE2_CPEN,
+				 CS4271_MODE2_PDN | CS4271_MODE2_CPEN);
 	if (ret < 0)
 		return ret;
-	ret = snd_soc_update_bits(codec, CS4271_MODE2, CS4271_MODE2_PDN, 0);
+	ret = regmap_update_bits(cs4271->regmap, CS4271_MODE2,
+				 CS4271_MODE2_PDN, 0);
 	if (ret < 0)
 		return ret;
 	/* Power-up sequence requires 85 uS */
 	udelay(85);
 
 	if (amutec_eq_bmutec)
-		snd_soc_update_bits(codec, CS4271_MODE2,
-				    CS4271_MODE2_MUTECAEQUB,
-				    CS4271_MODE2_MUTECAEQUB);
+		regmap_update_bits(cs4271->regmap, CS4271_MODE2,
+				   CS4271_MODE2_MUTECAEQUB,
+				   CS4271_MODE2_MUTECAEQUB);
 
 	return snd_soc_add_codec_controls(codec, cs4271_snd_controls,
 		ARRAY_SIZE(cs4271_snd_controls));
@@ -597,13 +596,24 @@ static struct snd_soc_codec_driver soc_codec_dev_cs4271 = {
 	.remove			= cs4271_remove,
 	.suspend		= cs4271_soc_suspend,
 	.resume			= cs4271_soc_resume,
-	.reg_cache_default	= cs4271_dflt_reg,
-	.reg_cache_size		= ARRAY_SIZE(cs4271_dflt_reg),
-	.reg_word_size		= sizeof(cs4271_dflt_reg[0]),
-	.compress_type		= SND_SOC_FLAT_COMPRESSION,
 };
 
 #if defined(CONFIG_SPI_MASTER)
+
+static const struct regmap_config cs4271_spi_regmap = {
+	.reg_bits = 16,
+	.val_bits = 8,
+	.max_register = CS4271_LASTREG,
+	.read_flag_mask = 0x21,
+	.write_flag_mask = 0x20,
+
+	.reg_defaults = cs4271_reg_defaults,
+	.num_reg_defaults = ARRAY_SIZE(cs4271_reg_defaults),
+	.cache_type = REGCACHE_RBTREE,
+
+	.volatile_reg = cs4271_volatile_reg,
+};
+
 static int cs4271_spi_probe(struct spi_device *spi)
 {
 	struct cs4271_private *cs4271;
@@ -613,7 +623,9 @@ static int cs4271_spi_probe(struct spi_device *spi)
 		return -ENOMEM;
 
 	spi_set_drvdata(spi, cs4271);
-	cs4271->bus_type = SND_SOC_SPI;
+	cs4271->regmap = devm_regmap_init_spi(spi, &cs4271_spi_regmap);
+	if (IS_ERR(cs4271->regmap))
+		return PTR_ERR(cs4271->regmap);
 
 	return snd_soc_register_codec(&spi->dev, &soc_codec_dev_cs4271,
 		&cs4271_dai, 1);
@@ -643,6 +655,18 @@ static const struct i2c_device_id cs4271_i2c_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, cs4271_i2c_id);
 
+static const struct regmap_config cs4271_i2c_regmap = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.max_register = CS4271_LASTREG,
+
+	.reg_defaults = cs4271_reg_defaults,
+	.num_reg_defaults = ARRAY_SIZE(cs4271_reg_defaults),
+	.cache_type = REGCACHE_RBTREE,
+
+	.volatile_reg = cs4271_volatile_reg,
+};
+
 static int cs4271_i2c_probe(struct i2c_client *client,
 			    const struct i2c_device_id *id)
 {
@@ -653,7 +677,9 @@ static int cs4271_i2c_probe(struct i2c_client *client,
 		return -ENOMEM;
 
 	i2c_set_clientdata(client, cs4271);
-	cs4271->bus_type = SND_SOC_I2C;
+	cs4271->regmap = devm_regmap_init_i2c(client, &cs4271_i2c_regmap);
+	if (IS_ERR(cs4271->regmap))
+		return PTR_ERR(cs4271->regmap);
 
 	return snd_soc_register_codec(&client->dev, &soc_codec_dev_cs4271,
 		&cs4271_dai, 1);
diff --git a/sound/soc/codecs/cs42l73.c b/sound/soc/codecs/cs42l73.c
index 6361dab..3b20c86 100644
--- a/sound/soc/codecs/cs42l73.c
+++ b/sound/soc/codecs/cs42l73.c
@@ -1180,7 +1180,11 @@ static int cs42l73_pcm_hw_params(struct snd_pcm_substream *substream,
 		priv->config[id].mmcc &= 0xC0;
 		priv->config[id].mmcc |= cs42l73_mclk_coeffs[mclk_coeff].mmcc;
 		priv->config[id].spc &= 0xFC;
-		priv->config[id].spc |= MCK_SCLK_MCLK;
+		/* Use SCLK=64*Fs if internal MCLK >= 6.4MHz */
+		if (priv->mclk >= 6400000)
+			priv->config[id].spc |= MCK_SCLK_64FS;
+		else
+			priv->config[id].spc |= MCK_SCLK_MCLK;
 	} else {
 		/* CS42L73 Slave */
 		priv->config[id].spc &= 0xFC;
diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c
index a4c16fd..3a7b7fd 100644
--- a/sound/soc/codecs/max98088.c
+++ b/sound/soc/codecs/max98088.c
@@ -739,14 +739,32 @@ static const unsigned int max98088_micboost_tlv[] = {
        2, 2, TLV_DB_SCALE_ITEM(3000, 0, 0),
 };
 
+static const unsigned int max98088_hp_tlv[] = {
+	TLV_DB_RANGE_HEAD(5),
+	0, 6, TLV_DB_SCALE_ITEM(-6700, 400, 0),
+	7, 14, TLV_DB_SCALE_ITEM(-4000, 300, 0),
+	15, 21, TLV_DB_SCALE_ITEM(-1700, 200, 0),
+	22, 27, TLV_DB_SCALE_ITEM(-400, 100, 0),
+	28, 31, TLV_DB_SCALE_ITEM(150, 50, 0),
+};
+
+static const unsigned int max98088_spk_tlv[] = {
+	TLV_DB_RANGE_HEAD(5),
+	0, 6, TLV_DB_SCALE_ITEM(-6200, 400, 0),
+	7, 14, TLV_DB_SCALE_ITEM(-3500, 300, 0),
+	15, 21, TLV_DB_SCALE_ITEM(-1200, 200, 0),
+	22, 27, TLV_DB_SCALE_ITEM(100, 100, 0),
+	28, 31, TLV_DB_SCALE_ITEM(650, 50, 0),
+};
+
 static const struct snd_kcontrol_new max98088_snd_controls[] = {
 
-       SOC_DOUBLE_R("Headphone Volume", M98088_REG_39_LVL_HP_L,
-               M98088_REG_3A_LVL_HP_R, 0, 31, 0),
-       SOC_DOUBLE_R("Speaker Volume", M98088_REG_3D_LVL_SPK_L,
-               M98088_REG_3E_LVL_SPK_R, 0, 31, 0),
-       SOC_DOUBLE_R("Receiver Volume", M98088_REG_3B_LVL_REC_L,
-               M98088_REG_3C_LVL_REC_R, 0, 31, 0),
+	SOC_DOUBLE_R_TLV("Headphone Volume", M98088_REG_39_LVL_HP_L,
+			 M98088_REG_3A_LVL_HP_R, 0, 31, 0, max98088_hp_tlv),
+	SOC_DOUBLE_R_TLV("Speaker Volume", M98088_REG_3D_LVL_SPK_L,
+			 M98088_REG_3E_LVL_SPK_R, 0, 31, 0, max98088_spk_tlv),
+	SOC_DOUBLE_R_TLV("Receiver Volume", M98088_REG_3B_LVL_REC_L,
+			 M98088_REG_3C_LVL_REC_R, 0, 31, 0, max98088_spk_tlv),
 
        SOC_DOUBLE_R("Headphone Switch", M98088_REG_39_LVL_HP_L,
                M98088_REG_3A_LVL_HP_R, 7, 1, 1),
diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c
old mode 100755
new mode 100644
index fc17604..ce0d364
--- a/sound/soc/codecs/max98090.c
+++ b/sound/soc/codecs/max98090.c
@@ -23,8 +23,6 @@
 #include <sound/max98090.h>
 #include "max98090.h"
 
-#include <linux/version.h>
-
 #define DEBUG
 #define EXTMIC_METHOD
 #define EXTMIC_METHOD_TEST
@@ -509,16 +507,16 @@ static int max98090_put_enab_tlv(struct snd_kcontrol *kcontrol,
 	return 0;
 }
 
-static const char * max98090_perf_pwr_text[] =
+static const char *max98090_perf_pwr_text[] =
 	{ "High Performance", "Low Power" };
-static const char * max98090_pwr_perf_text[] =
+static const char *max98090_pwr_perf_text[] =
 	{ "Low Power", "High Performance" };
 
 static const struct soc_enum max98090_vcmbandgap_enum =
 	SOC_ENUM_SINGLE(M98090_REG_BIAS_CONTROL, M98090_VCM_MODE_SHIFT,
 		ARRAY_SIZE(max98090_pwr_perf_text), max98090_pwr_perf_text);
 
-static const char * max98090_osr128_text[] = { "64*fs", "128*fs" };
+static const char *max98090_osr128_text[] = { "64*fs", "128*fs" };
 
 static const struct soc_enum max98090_osr128_enum =
 	SOC_ENUM_SINGLE(M98090_REG_ADC_CONTROL, M98090_OSR128_SHIFT,
@@ -535,28 +533,28 @@ static const struct soc_enum max98090_filter_dmic34mode_enum =
 		M98090_FLT_DMIC34MODE_SHIFT,
 		ARRAY_SIZE(max98090_mode_text), max98090_mode_text);
 
-static const char * max98090_drcatk_text[] =
+static const char *max98090_drcatk_text[] =
 	{ "0.5ms", "1ms", "5ms", "10ms", "25ms", "50ms", "100ms", "200ms" };
 
 static const struct soc_enum max98090_drcatk_enum =
 	SOC_ENUM_SINGLE(M98090_REG_DRC_TIMING, M98090_DRCATK_SHIFT,
 		ARRAY_SIZE(max98090_drcatk_text), max98090_drcatk_text);
 
-static const char * max98090_drcrls_text[] =
+static const char *max98090_drcrls_text[] =
 	{ "8s", "4s", "2s", "1s", "0.5s", "0.25s", "0.125s", "0.0625s" };
 
 static const struct soc_enum max98090_drcrls_enum =
 	SOC_ENUM_SINGLE(M98090_REG_DRC_TIMING, M98090_DRCRLS_SHIFT,
 		ARRAY_SIZE(max98090_drcrls_text), max98090_drcrls_text);
 
-static const char * max98090_alccmp_text[] =
+static const char *max98090_alccmp_text[] =
 	{ "1:1", "1:1.5", "1:2", "1:4", "1:INF" };
 
 static const struct soc_enum max98090_alccmp_enum =
 	SOC_ENUM_SINGLE(M98090_REG_DRC_COMPRESSOR, M98090_DRCCMP_SHIFT,
 		ARRAY_SIZE(max98090_alccmp_text), max98090_alccmp_text);
 
-static const char * max98090_drcexp_text[] = { "1:1", "2:1", "3:1" };
+static const char *max98090_drcexp_text[] = { "1:1", "2:1", "3:1" };
 
 static const struct soc_enum max98090_drcexp_enum =
 	SOC_ENUM_SINGLE(M98090_REG_DRC_EXPANDER, M98090_DRCEXP_SHIFT,
@@ -859,7 +857,7 @@ static const struct soc_enum mic2_mux_enum =
 static const struct snd_kcontrol_new max98090_mic2_mux =
 	SOC_DAPM_ENUM("MIC2 Mux", mic2_mux_enum);
 
-static const char * max98090_micpre_text[] = { "Off", "On" };
+static const char *max98090_micpre_text[] = { "Off", "On" };
 
 static const struct soc_enum max98090_pa1en_enum =
 	SOC_ENUM_SINGLE(M98090_REG_MIC1_INPUT_LEVEL, M98090_MIC_PA1EN_SHIFT,
@@ -1703,9 +1701,8 @@ static int max98090_dai_set_fmt(struct snd_soc_dai *codec_dai,
 		 * seen for the case of TDM mode. The remaining cases have
 		 * normal logic.
 		 */
-		if (max98090->tdm_slots > 1) {
+		if (max98090->tdm_slots > 1)
 			regval ^= M98090_BCI_MASK;
-		}
 
 		snd_soc_write(codec,
 			M98090_REG_INTERFACE_FORMAT, regval);
@@ -2059,17 +2056,14 @@ static irqreturn_t max98090_interrupt(int irq, void *data)
 	if (!active)
 		return IRQ_NONE;
 
-	if (active & M98090_CLD_MASK) {
+	if (active & M98090_CLD_MASK)
 		dev_err(codec->dev, "M98090_CLD_MASK\n");
-	}
 
-	if (active & M98090_SLD_MASK) {
+	if (active & M98090_SLD_MASK)
 		dev_dbg(codec->dev, "M98090_SLD_MASK\n");
-	}
 
-	if (active & M98090_ULK_MASK) {
+	if (active & M98090_ULK_MASK)
 		dev_err(codec->dev, "M98090_ULK_MASK\n");
-	}
 
 	if (active & M98090_JDET_MASK) {
 		dev_dbg(codec->dev, "M98090_JDET_MASK\n");
@@ -2080,13 +2074,11 @@ static irqreturn_t max98090_interrupt(int irq, void *data)
 			msecs_to_jiffies(100));
 	}
 
-	if (active & M98090_DRCACT_MASK) {
+	if (active & M98090_DRCACT_MASK)
 		dev_dbg(codec->dev, "M98090_DRCACT_MASK\n");
-	}
 
-	if (active & M98090_DRCCLP_MASK) {
+	if (active & M98090_DRCCLP_MASK)
 		dev_err(codec->dev, "M98090_DRCCLP_MASK\n");
-	}
 
 	return IRQ_HANDLED;
 }
@@ -2324,7 +2316,7 @@ static int max98090_i2c_probe(struct i2c_client *i2c,
 	max98090->pdata = i2c->dev.platform_data;
 	max98090->irq = i2c->irq;
 
-	max98090->regmap = regmap_init_i2c(i2c, &max98090_regmap);
+	max98090->regmap = devm_regmap_init_i2c(i2c, &max98090_regmap);
 	if (IS_ERR(max98090->regmap)) {
 		ret = PTR_ERR(max98090->regmap);
 		dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret);
@@ -2334,18 +2326,13 @@ static int max98090_i2c_probe(struct i2c_client *i2c,
 	ret = snd_soc_register_codec(&i2c->dev,
 			&soc_codec_dev_max98090, max98090_dai,
 			ARRAY_SIZE(max98090_dai));
-	if (ret < 0)
-		regmap_exit(max98090->regmap);
-
 err_enable:
 	return ret;
 }
 
 static int max98090_i2c_remove(struct i2c_client *client)
 {
-	struct max98090_priv *max98090 = dev_get_drvdata(&client->dev);
 	snd_soc_unregister_codec(&client->dev);
-	regmap_exit(max98090->regmap);
 	return 0;
 }
 
@@ -2369,7 +2356,7 @@ static int max98090_runtime_suspend(struct device *dev)
 	return 0;
 }
 
-static struct dev_pm_ops max98090_pm = {
+static const struct dev_pm_ops max98090_pm = {
 	SET_RUNTIME_PM_OPS(max98090_runtime_suspend,
 		max98090_runtime_resume, NULL)
 };
diff --git a/sound/soc/codecs/max98090.h b/sound/soc/codecs/max98090.h
old mode 100755
new mode 100644
diff --git a/sound/soc/codecs/si476x.c b/sound/soc/codecs/si476x.c
index f2d61a1..721587c 100644
--- a/sound/soc/codecs/si476x.c
+++ b/sound/soc/codecs/si476x.c
@@ -1,3 +1,22 @@
+/*
+ * sound/soc/codecs/si476x.c -- Codec driver for SI476X chips
+ *
+ * Copyright (C) 2012 Innovative Converged Devices(ICD)
+ * Copyright (C) 2013 Andrey Smirnov
+ *
+ * Author: Andrey Smirnov <andrew.smirnov@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.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT 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/slab.h>
 #include <sound/pcm.h>
@@ -45,13 +64,23 @@ static unsigned int si476x_codec_read(struct snd_soc_codec *codec,
 				      unsigned int reg)
 {
 	int err;
+	unsigned int val;
 	struct si476x_core *core = codec->control_data;
 
 	si476x_core_lock(core);
-	err = si476x_core_cmd_get_property(core, reg);
+	if (!si476x_core_is_powered_up(core))
+		regcache_cache_only(core->regmap, true);
+
+	err = regmap_read(core->regmap, reg, &val);
+
+	if (!si476x_core_is_powered_up(core))
+		regcache_cache_only(core->regmap, false);
 	si476x_core_unlock(core);
 
-	return err;
+	if (err < 0)
+		return err;
+
+	return val;
 }
 
 static int si476x_codec_write(struct snd_soc_codec *codec,
@@ -61,7 +90,13 @@ static int si476x_codec_write(struct snd_soc_codec *codec,
 	struct si476x_core *core = codec->control_data;
 
 	si476x_core_lock(core);
-	err = si476x_core_cmd_set_property(core, reg, val);
+	if (!si476x_core_is_powered_up(core))
+		regcache_cache_only(core->regmap, true);
+
+	err = regmap_write(core->regmap, reg, val);
+
+	if (!si476x_core_is_powered_up(core))
+		regcache_cache_only(core->regmap, false);
 	si476x_core_unlock(core);
 
 	return err;
@@ -140,7 +175,7 @@ static int si476x_codec_set_dai_fmt(struct snd_soc_dai *codec_dai,
 		dev_err(codec_dai->codec->dev, "Failed to set output format\n");
 		return err;
 	}
-	
+
 	return 0;
 }
 
@@ -159,6 +194,7 @@ static int si476x_codec_hw_params(struct snd_pcm_substream *substream,
 	switch (params_format(params)) {
 	case SNDRV_PCM_FORMAT_S8:
 		width = SI476X_PCM_FORMAT_S8;
+		break;
 	case SNDRV_PCM_FORMAT_S16_LE:
 		width = SI476X_PCM_FORMAT_S16_LE;
 		break;
@@ -181,7 +217,7 @@ static int si476x_codec_hw_params(struct snd_pcm_substream *substream,
 
 	err = snd_soc_update_bits(dai->codec, SI476X_DIGITAL_IO_OUTPUT_FORMAT,
 				  SI476X_DIGITAL_IO_OUTPUT_WIDTH_MASK,
-				  (width << SI476X_DIGITAL_IO_SLOT_SIZE_SHIFT) | 
+				  (width << SI476X_DIGITAL_IO_SLOT_SIZE_SHIFT) |
 				  (width << SI476X_DIGITAL_IO_SAMPLE_SIZE_SHIFT));
 	if (err < 0) {
 		dev_err(dai->codec->dev, "Failed to set output width\n");
@@ -250,6 +286,6 @@ static struct platform_driver si476x_platform_driver = {
 };
 module_platform_driver(si476x_platform_driver);
 
-MODULE_AUTHOR("Andrey Smirnov <andrey.smirnov@convergeddevices.net>");
+MODULE_AUTHOR("Andrey Smirnov <andrew.smirnov@gmail.com>");
 MODULE_DESCRIPTION("ASoC Si4761/64 codec driver");
 MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/tas5086.c b/sound/soc/codecs/tas5086.c
new file mode 100644
index 0000000..d447c4a
--- /dev/null
+++ b/sound/soc/codecs/tas5086.c
@@ -0,0 +1,591 @@
+/*
+ * TAS5086 ASoC codec driver
+ *
+ * Copyright (c) 2013 Daniel Mack <zonque@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.
+ *
+ * TODO:
+ *  - implement DAPM and input muxing
+ *  - implement modulation limit
+ *  - implement non-default PWM start
+ *
+ * Note that this chip has a very unusual register layout, specifically
+ * because the registers are of unequal size, and multi-byte registers
+ * require bulk writes to take effect. Regmap does not support that kind
+ * of devices.
+ *
+ * Currently, the driver does not touch any of the registers >= 0x20, so
+ * it doesn't matter because the entire map can be accessed as 8-bit
+ * array. In case more features will be added in the future
+ * that require access to higher registers, the entire regmap H/W I/O
+ * routines have to be open-coded.
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+#include <linux/spi/spi.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/tlv.h>
+#include <sound/tas5086.h>
+
+#define TAS5086_PCM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE  |		\
+			     SNDRV_PCM_FMTBIT_S20_3LE |		\
+			     SNDRV_PCM_FMTBIT_S24_3LE)
+
+#define TAS5086_PCM_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)
+
+/*
+ * TAS5086 registers
+ */
+#define TAS5086_CLOCK_CONTROL		0x00	/* Clock control register  */
+#define TAS5086_CLOCK_RATE(val)		(val << 5)
+#define TAS5086_CLOCK_RATE_MASK		(0x7 << 5)
+#define TAS5086_CLOCK_RATIO(val)	(val << 2)
+#define TAS5086_CLOCK_RATIO_MASK	(0x7 << 2)
+#define TAS5086_CLOCK_SCLK_RATIO_48	(1 << 1)
+#define TAS5086_CLOCK_VALID		(1 << 0)
+
+#define TAS5086_DEEMPH_MASK		0x03
+#define TAS5086_SOFT_MUTE_ALL		0x3f
+
+#define TAS5086_DEV_ID			0x01	/* Device ID register */
+#define TAS5086_ERROR_STATUS		0x02	/* Error status register */
+#define TAS5086_SYS_CONTROL_1		0x03	/* System control register 1 */
+#define TAS5086_SERIAL_DATA_IF		0x04	/* Serial data interface register  */
+#define TAS5086_SYS_CONTROL_2		0x05	/* System control register 2 */
+#define TAS5086_SOFT_MUTE		0x06	/* Soft mute register */
+#define TAS5086_MASTER_VOL		0x07	/* Master volume  */
+#define TAS5086_CHANNEL_VOL(X)		(0x08 + (X))	/* Channel 1-6 volume */
+#define TAS5086_VOLUME_CONTROL		0x09	/* Volume control register */
+#define TAS5086_MOD_LIMIT		0x10	/* Modulation limit register */
+#define TAS5086_PWM_START		0x18	/* PWM start register */
+#define TAS5086_SURROUND		0x19	/* Surround register */
+#define TAS5086_SPLIT_CAP_CHARGE	0x1a	/* Split cap charge period register */
+#define TAS5086_OSC_TRIM		0x1b	/* Oscillator trim register */
+#define TAS5086_BKNDERR 		0x1c
+
+/*
+ * Default TAS5086 power-up configuration
+ */
+static const struct reg_default tas5086_reg_defaults[] = {
+	{ 0x00,	0x6c },
+	{ 0x01,	0x03 },
+	{ 0x02,	0x00 },
+	{ 0x03,	0xa0 },
+	{ 0x04,	0x05 },
+	{ 0x05,	0x60 },
+	{ 0x06,	0x00 },
+	{ 0x07,	0xff },
+	{ 0x08,	0x30 },
+	{ 0x09,	0x30 },
+	{ 0x0a,	0x30 },
+	{ 0x0b,	0x30 },
+	{ 0x0c,	0x30 },
+	{ 0x0d,	0x30 },
+	{ 0x0e,	0xb1 },
+	{ 0x0f,	0x00 },
+	{ 0x10,	0x02 },
+	{ 0x11,	0x00 },
+	{ 0x12,	0x00 },
+	{ 0x13,	0x00 },
+	{ 0x14,	0x00 },
+	{ 0x15,	0x00 },
+	{ 0x16,	0x00 },
+	{ 0x17,	0x00 },
+	{ 0x18,	0x3f },
+	{ 0x19,	0x00 },
+	{ 0x1a,	0x18 },
+	{ 0x1b,	0x82 },
+	{ 0x1c,	0x05 },
+};
+
+static bool tas5086_accessible_reg(struct device *dev, unsigned int reg)
+{
+	return !((reg == 0x0f) || (reg >= 0x11 && reg <= 0x17));
+}
+
+static bool tas5086_volatile_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case TAS5086_DEV_ID:
+	case TAS5086_ERROR_STATUS:
+		return true;
+	}
+
+	return false;
+}
+
+static bool tas5086_writeable_reg(struct device *dev, unsigned int reg)
+{
+	return tas5086_accessible_reg(dev, reg) && (reg != TAS5086_DEV_ID);
+}
+
+struct tas5086_private {
+	struct regmap	*regmap;
+	unsigned int	mclk, sclk;
+	unsigned int	format;
+	bool		deemph;
+	/* Current sample rate for de-emphasis control */
+	int		rate;
+	/* GPIO driving Reset pin, if any */
+	int		gpio_nreset;
+};
+
+static int tas5086_deemph[] = { 0, 32000, 44100, 48000 };
+
+static int tas5086_set_deemph(struct snd_soc_codec *codec)
+{
+	struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
+	int i, val = 0;
+
+	if (priv->deemph)
+		for (i = 0; i < ARRAY_SIZE(tas5086_deemph); i++)
+			if (tas5086_deemph[i] == priv->rate)
+				val = i;
+
+	return regmap_update_bits(priv->regmap, TAS5086_SYS_CONTROL_1,
+				  TAS5086_DEEMPH_MASK, val);
+}
+
+static int tas5086_get_deemph(struct snd_kcontrol *kcontrol,
+			      struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
+
+	ucontrol->value.enumerated.item[0] = priv->deemph;
+
+	return 0;
+}
+
+static int tas5086_put_deemph(struct snd_kcontrol *kcontrol,
+			      struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
+
+	priv->deemph = ucontrol->value.enumerated.item[0];
+
+	return tas5086_set_deemph(codec);
+}
+
+
+static int tas5086_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 tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
+
+	switch (clk_id) {
+	case TAS5086_CLK_IDX_MCLK:
+		priv->mclk = freq;
+		break;
+	case TAS5086_CLK_IDX_SCLK:
+		priv->sclk = freq;
+		break;
+	}
+
+	return 0;
+}
+
+static int tas5086_set_dai_fmt(struct snd_soc_dai *codec_dai,
+			       unsigned int format)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
+
+	/* The TAS5086 can only be slave to all clocks */
+	if ((format & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) {
+		dev_err(codec->dev, "Invalid clocking mode\n");
+		return -EINVAL;
+	}
+
+	/* we need to refer to the data format from hw_params() */
+	priv->format = format;
+
+	return 0;
+}
+
+static const int tas5086_sample_rates[] = {
+	32000, 38000, 44100, 48000, 88200, 96000, 176400, 192000
+};
+
+static const int tas5086_ratios[] = {
+	64, 128, 192, 256, 384, 512
+};
+
+static int index_in_array(const int *array, int len, int needle)
+{
+	int i;
+
+	for (i = 0; i < len; i++)
+		if (array[i] == needle)
+			return i;
+
+	return -ENOENT;
+}
+
+static int tas5086_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 tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
+	int val;
+	int ret;
+
+	priv->rate = params_rate(params);
+
+	/* Look up the sample rate and refer to the offset in the list */
+	val = index_in_array(tas5086_sample_rates,
+			     ARRAY_SIZE(tas5086_sample_rates), priv->rate);
+
+	if (val < 0) {
+		dev_err(codec->dev, "Invalid sample rate\n");
+		return -EINVAL;
+	}
+
+	ret = regmap_update_bits(priv->regmap, TAS5086_CLOCK_CONTROL,
+				 TAS5086_CLOCK_RATE_MASK,
+				 TAS5086_CLOCK_RATE(val));
+	if (ret < 0)
+		return ret;
+
+	/* MCLK / Fs ratio */
+	val = index_in_array(tas5086_ratios, ARRAY_SIZE(tas5086_ratios),
+			     priv->mclk / priv->rate);
+	if (val < 0) {
+		dev_err(codec->dev, "Inavlid MCLK / Fs ratio\n");
+		return -EINVAL;
+	}
+
+	ret = regmap_update_bits(priv->regmap, TAS5086_CLOCK_CONTROL,
+				 TAS5086_CLOCK_RATIO_MASK,
+				 TAS5086_CLOCK_RATIO(val));
+	if (ret < 0)
+		return ret;
+
+
+	ret = regmap_update_bits(priv->regmap, TAS5086_CLOCK_CONTROL,
+				 TAS5086_CLOCK_SCLK_RATIO_48,
+				 (priv->sclk == 48 * priv->rate) ? 
+					TAS5086_CLOCK_SCLK_RATIO_48 : 0);
+	if (ret < 0)
+		return ret;
+
+	/*
+	 * The chip has a very unituitive register mapping and muxes information
+	 * about data format and sample depth into the same register, but not on
+	 * a logical bit-boundary. Hence, we have to refer to the format passed
+	 * in the set_dai_fmt() callback and set up everything from here.
+	 *
+	 * First, determine the 'base' value, using the format ...
+	 */
+	switch (priv->format & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_RIGHT_J:
+		val = 0x00;
+		break;
+	case SND_SOC_DAIFMT_I2S:
+		val = 0x03;
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		val = 0x06;
+		break;
+	default:
+		dev_err(codec->dev, "Invalid DAI format\n");
+		return -EINVAL;
+	}
+
+	/* ... then add the offset for the sample bit depth. */
+	switch (params_format(params)) {
+        case SNDRV_PCM_FORMAT_S16_LE:
+		val += 0;
+                break;
+	case SNDRV_PCM_FORMAT_S20_3LE:
+		val += 1;
+		break;
+	case SNDRV_PCM_FORMAT_S24_3LE:
+		val += 2;
+		break;
+	default:
+		dev_err(codec->dev, "Invalid bit width\n");
+		return -EINVAL;
+	};
+
+	ret = regmap_write(priv->regmap, TAS5086_SERIAL_DATA_IF, val);
+	if (ret < 0)
+		return ret;
+
+	/* clock is considered valid now */
+	ret = regmap_update_bits(priv->regmap, TAS5086_CLOCK_CONTROL,
+				 TAS5086_CLOCK_VALID, TAS5086_CLOCK_VALID);
+	if (ret < 0)
+		return ret;
+
+	return tas5086_set_deemph(codec);
+}
+
+static int tas5086_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
+	unsigned int val = 0;
+
+	if (mute)
+		val = TAS5086_SOFT_MUTE_ALL;
+
+	return regmap_write(priv->regmap, TAS5086_SOFT_MUTE, val);
+}
+
+/* TAS5086 controls */
+static const DECLARE_TLV_DB_SCALE(tas5086_dac_tlv, -10350, 50, 1);
+
+static const struct snd_kcontrol_new tas5086_controls[] = {
+	SOC_SINGLE_TLV("Master Playback Volume", TAS5086_MASTER_VOL,
+		       0, 0xff, 1, tas5086_dac_tlv),
+	SOC_DOUBLE_R_TLV("Channel 1/2 Playback Volume",
+			 TAS5086_CHANNEL_VOL(0), TAS5086_CHANNEL_VOL(1),
+			 0, 0xff, 1, tas5086_dac_tlv),
+	SOC_DOUBLE_R_TLV("Channel 3/4 Playback Volume",
+			 TAS5086_CHANNEL_VOL(2), TAS5086_CHANNEL_VOL(3),
+			 0, 0xff, 1, tas5086_dac_tlv),
+	SOC_DOUBLE_R_TLV("Channel 5/6 Playback Volume",
+			 TAS5086_CHANNEL_VOL(4), TAS5086_CHANNEL_VOL(5),
+			 0, 0xff, 1, tas5086_dac_tlv),
+	SOC_SINGLE_BOOL_EXT("De-emphasis Switch", 0,
+			    tas5086_get_deemph, tas5086_put_deemph),
+};
+
+static const struct snd_soc_dai_ops tas5086_dai_ops = {
+	.hw_params	= tas5086_hw_params,
+	.set_sysclk	= tas5086_set_dai_sysclk,
+	.set_fmt	= tas5086_set_dai_fmt,
+	.mute_stream	= tas5086_mute_stream,
+};
+
+static struct snd_soc_dai_driver tas5086_dai = {
+	.name = "tas5086-hifi",
+	.playback = {
+		.stream_name	= "Playback",
+		.channels_min	= 2,
+		.channels_max	= 6,
+		.rates		= TAS5086_PCM_RATES,
+		.formats	= TAS5086_PCM_FORMATS,
+	},
+	.ops = &tas5086_dai_ops,
+};
+
+#ifdef CONFIG_PM
+static int tas5086_soc_resume(struct snd_soc_codec *codec)
+{
+	struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
+
+	/* Restore codec state */
+	return regcache_sync(priv->regmap);
+}
+#else
+#define tas5086_soc_resume	NULL
+#endif /* CONFIG_PM */
+
+#ifdef CONFIG_OF
+static const struct of_device_id tas5086_dt_ids[] = {
+	{ .compatible = "ti,tas5086", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, tas5086_dt_ids);
+#endif
+
+/* charge period values in microseconds */
+static const int tas5086_charge_period[] = {
+	  13000,  16900,   23400,   31200,   41600,   54600,   72800,   96200,
+	 130000, 156000,  234000,  312000,  416000,  546000,  728000,  962000,
+	1300000, 169000, 2340000, 3120000, 4160000, 5460000, 7280000, 9620000,
+};
+
+static int tas5086_probe(struct snd_soc_codec *codec)
+{
+	struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
+	int charge_period = 1300000; /* hardware default is 1300 ms */
+	int i, ret;
+
+	if (of_match_device(of_match_ptr(tas5086_dt_ids), codec->dev)) {
+		struct device_node *of_node = codec->dev->of_node;
+		of_property_read_u32(of_node, "ti,charge-period", &charge_period);
+	}
+
+	/* lookup and set split-capacitor charge period */
+	if (charge_period == 0) {
+		regmap_write(priv->regmap, TAS5086_SPLIT_CAP_CHARGE, 0);
+	} else {
+		i = index_in_array(tas5086_charge_period,
+				   ARRAY_SIZE(tas5086_charge_period),
+				   charge_period);
+		if (i >= 0)
+			regmap_write(priv->regmap, TAS5086_SPLIT_CAP_CHARGE,
+				     i + 0x08);
+		else
+			dev_warn(codec->dev,
+				 "Invalid split-cap charge period of %d ns.\n",
+				 charge_period);
+	}
+
+	/* enable factory trim */
+	ret = regmap_write(priv->regmap, TAS5086_OSC_TRIM, 0x00);
+	if (ret < 0)
+		return ret;
+
+	/* start all channels */
+	ret = regmap_write(priv->regmap, TAS5086_SYS_CONTROL_2, 0x20);
+	if (ret < 0)
+		return ret;
+
+	/* set master volume to 0 dB */
+	ret = regmap_write(priv->regmap, TAS5086_MASTER_VOL, 0x30);
+	if (ret < 0)
+		return ret;
+
+	/* mute all channels for now */
+	ret = regmap_write(priv->regmap, TAS5086_SOFT_MUTE,
+			   TAS5086_SOFT_MUTE_ALL);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int tas5086_remove(struct snd_soc_codec *codec)
+{
+	struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
+
+	if (gpio_is_valid(priv->gpio_nreset))
+		/* Set codec to the reset state */
+		gpio_set_value(priv->gpio_nreset, 0);
+
+	return 0;
+};
+
+static struct snd_soc_codec_driver soc_codec_dev_tas5086 = {
+	.probe			= tas5086_probe,
+	.remove			= tas5086_remove,
+	.resume			= tas5086_soc_resume,
+	.controls		= tas5086_controls,
+	.num_controls		= ARRAY_SIZE(tas5086_controls),
+};
+
+static const struct i2c_device_id tas5086_i2c_id[] = {
+	{ "tas5086", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, tas5086_i2c_id);
+
+static const struct regmap_config tas5086_regmap = {
+	.reg_bits		= 8,
+	.val_bits		= 8,
+	.max_register		= ARRAY_SIZE(tas5086_reg_defaults),
+	.reg_defaults		= tas5086_reg_defaults,
+	.num_reg_defaults	= ARRAY_SIZE(tas5086_reg_defaults),
+	.cache_type		= REGCACHE_RBTREE,
+	.volatile_reg		= tas5086_volatile_reg,
+	.writeable_reg		= tas5086_writeable_reg,
+	.readable_reg		= tas5086_accessible_reg,
+};
+
+static int tas5086_i2c_probe(struct i2c_client *i2c,
+			     const struct i2c_device_id *id)
+{
+	struct tas5086_private *priv;
+	struct device *dev = &i2c->dev;
+	int gpio_nreset = -EINVAL;
+	int i, ret;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->regmap = devm_regmap_init_i2c(i2c, &tas5086_regmap);
+	if (IS_ERR(priv->regmap)) {
+		ret = PTR_ERR(priv->regmap);
+		dev_err(&i2c->dev, "Failed to create regmap: %d\n", ret);
+		return ret;
+	}
+
+	i2c_set_clientdata(i2c, priv);
+
+	if (of_match_device(of_match_ptr(tas5086_dt_ids), dev)) {
+		struct device_node *of_node = dev->of_node;
+		gpio_nreset = of_get_named_gpio(of_node, "reset-gpio", 0);
+	}
+
+	if (gpio_is_valid(gpio_nreset))
+		if (devm_gpio_request(dev, gpio_nreset, "TAS5086 Reset"))
+			gpio_nreset = -EINVAL;
+
+	if (gpio_is_valid(gpio_nreset)) {
+		/* Reset codec - minimum assertion time is 400ns */
+		gpio_direction_output(gpio_nreset, 0);
+		udelay(1);
+		gpio_set_value(gpio_nreset, 1);
+
+		/* Codec needs ~15ms to wake up */
+		msleep(15);
+	}
+
+	priv->gpio_nreset = gpio_nreset;
+
+	/* The TAS5086 always returns 0x03 in its TAS5086_DEV_ID register */
+	ret = regmap_read(priv->regmap, TAS5086_DEV_ID, &i);
+	if (ret < 0)
+		return ret;
+
+	if (i != 0x3) {
+		dev_err(dev,
+			"Failed to identify TAS5086 codec (got %02x)\n", i);
+		return -ENODEV;
+	}
+
+	return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_tas5086,
+		&tas5086_dai, 1);
+}
+
+static int tas5086_i2c_remove(struct i2c_client *i2c)
+{
+	snd_soc_unregister_codec(&i2c->dev);
+	return 0;
+}
+
+static struct i2c_driver tas5086_i2c_driver = {
+	.driver = {
+		.name	= "tas5086",
+		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(tas5086_dt_ids),
+	},
+	.id_table	= tas5086_i2c_id,
+	.probe		= tas5086_i2c_probe,
+	.remove		= tas5086_i2c_remove,
+};
+
+module_i2c_driver(tas5086_i2c_driver);
+
+MODULE_AUTHOR("Daniel Mack <zonque@gmail.com>");
+MODULE_DESCRIPTION("Texas Instruments TAS5086 ALSA SoC Codec Driver");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm0010.c b/sound/soc/codecs/wm0010.c
index ad2fee4..8df2b6e 100644
--- a/sound/soc/codecs/wm0010.c
+++ b/sound/soc/codecs/wm0010.c
@@ -342,7 +342,7 @@ static void byte_swap_64(u64 *data_in, u64 *data_out, u32 len)
 		data_out[i] = cpu_to_be64(le64_to_cpu(data_in[i]));
 }
 
-static int wm0010_firmware_load(char *name, struct snd_soc_codec *codec)
+static int wm0010_firmware_load(const char *name, struct snd_soc_codec *codec)
 {
 	struct spi_device *spi = to_spi_device(codec->dev);
 	struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec);
@@ -361,8 +361,8 @@ static int wm0010_firmware_load(char *name, struct snd_soc_codec *codec)
 
 	ret = request_firmware(&fw, name, codec->dev);
 	if (ret != 0) {
-		dev_err(codec->dev, "Failed to request application: %d\n",
-			ret);
+		dev_err(codec->dev, "Failed to request application(%s): %d\n",
+			name, ret);
 		return ret;
 	}
 
diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c
index f2ac38b..7fefd76 100644
--- a/sound/soc/codecs/wm2000.c
+++ b/sound/soc/codecs/wm2000.c
@@ -761,6 +761,8 @@ static bool wm2000_readable_reg(struct device *dev, unsigned int reg)
 	case WM2000_REG_SYS_CTL2:
 	case WM2000_REG_ANC_STAT:
 	case WM2000_REG_IF_CTL:
+	case WM2000_REG_ANA_MIC_CTL:
+	case WM2000_REG_SPK_CTL:
 		return true;
 	default:
 		return false;
@@ -771,7 +773,7 @@ static const struct regmap_config wm2000_regmap = {
 	.reg_bits = 16,
 	.val_bits = 8,
 
-	.max_register = WM2000_REG_IF_CTL,
+	.max_register = WM2000_REG_SPK_CTL,
 	.readable_reg = wm2000_readable_reg,
 };
 
diff --git a/sound/soc/codecs/wm2000.h b/sound/soc/codecs/wm2000.h
index fb812cd..3870c0e 100644
--- a/sound/soc/codecs/wm2000.h
+++ b/sound/soc/codecs/wm2000.h
@@ -30,6 +30,8 @@
 #define WM2000_REG_SYS_CTL2         0xf004
 #define WM2000_REG_ANC_STAT         0xf005
 #define WM2000_REG_IF_CTL           0xf006
+#define WM2000_REG_ANA_MIC_CTL      0xf028
+#define WM2000_REG_SPK_CTL          0xf034
 
 /* SPEECH_CLARITY */
 #define WM2000_SPEECH_CLARITY   0x01
diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c
index ddc98f0..57ba315 100644
--- a/sound/soc/codecs/wm2200.c
+++ b/sound/soc/codecs/wm2200.c
@@ -1565,7 +1565,7 @@ static int wm2200_probe(struct snd_soc_codec *codec)
 		return ret;
 	}
 
-	ret = snd_soc_add_codec_controls(codec, wm_adsp_fw_controls, 2);
+	ret = snd_soc_add_codec_controls(codec, wm_adsp1_fw_controls, 2);
 	if (ret != 0)
 		return ret;
 
diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c
index b82bbf5..cb03cc4 100644
--- a/sound/soc/codecs/wm5102.c
+++ b/sound/soc/codecs/wm5102.c
@@ -36,9 +36,6 @@
 struct wm5102_priv {
 	struct arizona_priv core;
 	struct arizona_fll fll[2];
-
-	unsigned int spk_ena:2;
-	unsigned int spk_ena_pending:1;
 };
 
 static DECLARE_TLV_DB_SCALE(ana_tlv, 0, 100, 0);
@@ -615,6 +612,26 @@ static int wm5102_sysclk_ev(struct snd_soc_dapm_widget *w,
 	return 0;
 }
 
+static const char *wm5102_osr_text[] = {
+	"Low power", "Normal", "High performance",
+};
+
+static const unsigned int wm5102_osr_val[] = {
+	0x0, 0x3, 0x5,
+};
+
+static const struct soc_enum wm5102_hpout_osr[] = {
+	SOC_VALUE_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_1L,
+			      ARIZONA_OUT1_OSR_SHIFT, 0x7, 3,
+			      wm5102_osr_text, wm5102_osr_val),
+	SOC_VALUE_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_2L,
+			      ARIZONA_OUT2_OSR_SHIFT, 0x7, 3,
+			      wm5102_osr_text, wm5102_osr_val),
+	SOC_VALUE_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_3L,
+			      ARIZONA_OUT3_OSR_SHIFT, 0x7, 3,
+			      wm5102_osr_text, wm5102_osr_val),
+};
+
 #define WM5102_NG_SRC(name, base) \
 	SOC_SINGLE(name " NG HPOUT1L Switch",  base, 0, 1, 0), \
 	SOC_SINGLE(name " NG HPOUT1R Switch",  base, 1, 1, 0), \
@@ -745,6 +762,9 @@ SOC_ENUM("LHPF2 Mode", arizona_lhpf2_mode),
 SOC_ENUM("LHPF3 Mode", arizona_lhpf3_mode),
 SOC_ENUM("LHPF4 Mode", arizona_lhpf4_mode),
 
+SOC_VALUE_ENUM("ISRC1 FSL", arizona_isrc_fsl[0]),
+SOC_VALUE_ENUM("ISRC2 FSL", arizona_isrc_fsl[1]),
+
 ARIZONA_MIXER_CONTROLS("Mic", ARIZONA_MICMIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("Noise", ARIZONA_NOISEMIX_INPUT_1_SOURCE),
 
@@ -761,6 +781,8 @@ ARIZONA_MIXER_CONTROLS("SPKOUTR", ARIZONA_OUT4RMIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("SPKDAT1L", ARIZONA_OUT5LMIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("SPKDAT1R", ARIZONA_OUT5RMIX_INPUT_1_SOURCE),
 
+SOC_SINGLE("Speaker High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_4L,
+	   ARIZONA_OUT4_OSR_SHIFT, 1, 0),
 SOC_SINGLE("SPKDAT1 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_5L,
 	   ARIZONA_OUT5_OSR_SHIFT, 1, 0),
 
@@ -790,6 +812,10 @@ SOC_DOUBLE_R_TLV("SPKDAT1 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_5L,
 		 ARIZONA_DAC_DIGITAL_VOLUME_5R, ARIZONA_OUT5L_VOL_SHIFT,
 		 0xbf, 0, digital_tlv),
 
+SOC_VALUE_ENUM("HPOUT1 OSR", wm5102_hpout_osr[0]),
+SOC_VALUE_ENUM("HPOUT2 OSR", wm5102_hpout_osr[1]),
+SOC_VALUE_ENUM("HPOUT3 OSR", wm5102_hpout_osr[2]),
+
 SOC_ENUM("Output Ramp Up", arizona_out_vi_ramp),
 SOC_ENUM("Output Ramp Down", arizona_out_vd_ramp),
 
@@ -828,47 +854,6 @@ ARIZONA_MIXER_CONTROLS("AIF3TX1", ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("AIF3TX2", ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE),
 };
 
-static int wm5102_spk_ev(struct snd_soc_dapm_widget *w,
-			 struct snd_kcontrol *kcontrol,
-			 int event)
-{
-	struct snd_soc_codec *codec = w->codec;
-	struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
-	struct wm5102_priv *wm5102 = snd_soc_codec_get_drvdata(codec);
-
-	if (arizona->rev < 1)
-		return 0;
-
-	switch (event) {
-	case SND_SOC_DAPM_PRE_PMU:
-		if (!wm5102->spk_ena) {
-			snd_soc_write(codec, 0x4f5, 0x25a);
-			wm5102->spk_ena_pending = true;
-		}
-		break;
-	case SND_SOC_DAPM_POST_PMU:
-		if (wm5102->spk_ena_pending) {
-			msleep(75);
-			snd_soc_write(codec, 0x4f5, 0xda);
-			wm5102->spk_ena_pending = false;
-			wm5102->spk_ena++;
-		}
-		break;
-	case SND_SOC_DAPM_PRE_PMD:
-		wm5102->spk_ena--;
-		if (!wm5102->spk_ena)
-			snd_soc_write(codec, 0x4f5, 0x25a);
-		break;
-	case SND_SOC_DAPM_POST_PMD:
-		if (!wm5102->spk_ena)
-			snd_soc_write(codec, 0x4f5, 0x0da);
-		break;
-	}
-
-	return 0;
-}
-
-
 ARIZONA_MIXER_ENUMS(EQ1, ARIZONA_EQ1MIX_INPUT_1_SOURCE);
 ARIZONA_MIXER_ENUMS(EQ2, ARIZONA_EQ2MIX_INPUT_1_SOURCE);
 ARIZONA_MIXER_ENUMS(EQ3, ARIZONA_EQ3MIX_INPUT_1_SOURCE);
@@ -984,22 +969,28 @@ SND_SOC_DAPM_INPUT("IN3R"),
 
 SND_SOC_DAPM_PGA_E("IN1L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1L_ENA_SHIFT,
 		   0, NULL, 0, arizona_in_ev,
-		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
+		   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
 SND_SOC_DAPM_PGA_E("IN1R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1R_ENA_SHIFT,
 		   0, NULL, 0, arizona_in_ev,
-		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
+		   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
 SND_SOC_DAPM_PGA_E("IN2L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2L_ENA_SHIFT,
 		   0, NULL, 0, arizona_in_ev,
-		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
+		   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
 SND_SOC_DAPM_PGA_E("IN2R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2R_ENA_SHIFT,
 		   0, NULL, 0, arizona_in_ev,
-		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
+		   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
 SND_SOC_DAPM_PGA_E("IN3L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3L_ENA_SHIFT,
 		   0, NULL, 0, arizona_in_ev,
-		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
+		   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
 SND_SOC_DAPM_PGA_E("IN3R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3R_ENA_SHIFT,
 		   0, NULL, 0, arizona_in_ev,
-		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
+		   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
 
 SND_SOC_DAPM_SUPPLY("MICBIAS1", ARIZONA_MIC_BIAS_CTRL_1,
 		    ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0),
@@ -1131,11 +1122,11 @@ ARIZONA_DSP_WIDGETS(DSP1, "DSP1"),
 SND_SOC_DAPM_VALUE_MUX("AEC Loopback", ARIZONA_DAC_AEC_CONTROL_1,
 		       ARIZONA_AEC_LOOPBACK_ENA, 0, &wm5102_aec_loopback_mux),
 
-SND_SOC_DAPM_PGA_E("OUT1L", ARIZONA_OUTPUT_ENABLES_1,
-		   ARIZONA_OUT1L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
+SND_SOC_DAPM_PGA_E("OUT1L", SND_SOC_NOPM,
+		   ARIZONA_OUT1L_ENA_SHIFT, 0, NULL, 0, arizona_hp_ev,
 		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
-SND_SOC_DAPM_PGA_E("OUT1R", ARIZONA_OUTPUT_ENABLES_1,
-		   ARIZONA_OUT1R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
+SND_SOC_DAPM_PGA_E("OUT1R", SND_SOC_NOPM,
+		   ARIZONA_OUT1R_ENA_SHIFT, 0, NULL, 0, arizona_hp_ev,
 		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
 SND_SOC_DAPM_PGA_E("OUT2L", ARIZONA_OUTPUT_ENABLES_1,
 		   ARIZONA_OUT2L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
@@ -1146,12 +1137,6 @@ SND_SOC_DAPM_PGA_E("OUT2R", ARIZONA_OUTPUT_ENABLES_1,
 SND_SOC_DAPM_PGA_E("OUT3L", ARIZONA_OUTPUT_ENABLES_1,
 		   ARIZONA_OUT3L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
 		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
-SND_SOC_DAPM_PGA_E("OUT4L", ARIZONA_OUTPUT_ENABLES_1,
-		   ARIZONA_OUT4L_ENA_SHIFT, 0, NULL, 0, wm5102_spk_ev,
-		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
-SND_SOC_DAPM_PGA_E("OUT4R", ARIZONA_OUTPUT_ENABLES_1,
-		   ARIZONA_OUT4R_ENA_SHIFT, 0, NULL, 0, wm5102_spk_ev,
-		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
 SND_SOC_DAPM_PGA_E("OUT5L", ARIZONA_OUTPUT_ENABLES_1,
 		   ARIZONA_OUT5L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
 		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
@@ -1494,6 +1479,12 @@ static int wm5102_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
 		return arizona_set_fll(&wm5102->fll[0], source, Fref, Fout);
 	case WM5102_FLL2:
 		return arizona_set_fll(&wm5102->fll[1], source, Fref, Fout);
+	case WM5102_FLL1_REFCLK:
+		return arizona_set_fll_refclk(&wm5102->fll[0], source, Fref,
+					      Fout);
+	case WM5102_FLL2_REFCLK:
+		return arizona_set_fll_refclk(&wm5102->fll[1], source, Fref,
+					      Fout);
 	default:
 		return -EINVAL;
 	}
@@ -1581,10 +1572,12 @@ static int wm5102_codec_probe(struct snd_soc_codec *codec)
 	if (ret != 0)
 		return ret;
 
-	ret = snd_soc_add_codec_controls(codec, wm_adsp_fw_controls, 1);
+	ret = snd_soc_add_codec_controls(codec, wm_adsp2_fw_controls, 2);
 	if (ret != 0)
 		return ret;
 
+	arizona_init_spk(codec);
+
 	snd_soc_dapm_disable_pin(&codec->dapm, "HAPTICS");
 
 	priv->core.arizona->dapm = &codec->dapm;
@@ -1604,13 +1597,6 @@ static int wm5102_codec_remove(struct snd_soc_codec *codec)
 #define WM5102_DIG_VU 0x0200
 
 static unsigned int wm5102_digital_vu[] = {
-	ARIZONA_ADC_DIGITAL_VOLUME_1L,
-	ARIZONA_ADC_DIGITAL_VOLUME_1R,
-	ARIZONA_ADC_DIGITAL_VOLUME_2L,
-	ARIZONA_ADC_DIGITAL_VOLUME_2R,
-	ARIZONA_ADC_DIGITAL_VOLUME_3L,
-	ARIZONA_ADC_DIGITAL_VOLUME_3R,
-
 	ARIZONA_DAC_DIGITAL_VOLUME_1L,
 	ARIZONA_DAC_DIGITAL_VOLUME_1R,
 	ARIZONA_DAC_DIGITAL_VOLUME_2L,
@@ -1653,6 +1639,7 @@ static int wm5102_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, wm5102);
 
 	wm5102->core.arizona = arizona;
+	wm5102->core.num_inputs = 6;
 
 	wm5102->core.adsp[0].part = "wm5102";
 	wm5102->core.adsp[0].num = 1;
@@ -1677,6 +1664,12 @@ static int wm5102_probe(struct platform_device *pdev)
 			 ARIZONA_IRQ_FLL2_LOCK, ARIZONA_IRQ_FLL2_CLOCK_OK,
 			 &wm5102->fll[1]);
 
+	/* SR2 fixed at 8kHz, SR3 fixed at 16kHz */
+	regmap_update_bits(arizona->regmap, ARIZONA_SAMPLE_RATE_2,
+			   ARIZONA_SAMPLE_RATE_2_MASK, 0x11);
+	regmap_update_bits(arizona->regmap, ARIZONA_SAMPLE_RATE_3,
+			   ARIZONA_SAMPLE_RATE_3_MASK, 0x12);
+
 	for (i = 0; i < ARRAY_SIZE(wm5102_dai); i++)
 		arizona_init_dai(&wm5102->core, i);
 
diff --git a/sound/soc/codecs/wm5102.h b/sound/soc/codecs/wm5102.h
index d30477f..adb3804 100644
--- a/sound/soc/codecs/wm5102.h
+++ b/sound/soc/codecs/wm5102.h
@@ -15,7 +15,9 @@
 
 #include "arizona.h"
 
-#define WM5102_FLL1 1
-#define WM5102_FLL2 2
+#define WM5102_FLL1        1
+#define WM5102_FLL2        2
+#define WM5102_FLL1_REFCLK 3
+#define WM5102_FLL2_REFCLK 4
 
 #endif
diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c
index cdeb301..731884e 100644
--- a/sound/soc/codecs/wm5110.c
+++ b/sound/soc/codecs/wm5110.c
@@ -416,28 +416,36 @@ SND_SOC_DAPM_INPUT("IN4R"),
 
 SND_SOC_DAPM_PGA_E("IN1L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1L_ENA_SHIFT,
 		   0, NULL, 0, arizona_in_ev,
-		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
+		   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
 SND_SOC_DAPM_PGA_E("IN1R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1R_ENA_SHIFT,
 		   0, NULL, 0, arizona_in_ev,
-		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
+		   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
 SND_SOC_DAPM_PGA_E("IN2L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2L_ENA_SHIFT,
 		   0, NULL, 0, arizona_in_ev,
-		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
+		   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
 SND_SOC_DAPM_PGA_E("IN2R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2R_ENA_SHIFT,
 		   0, NULL, 0, arizona_in_ev,
-		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
+		   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
 SND_SOC_DAPM_PGA_E("IN3L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3L_ENA_SHIFT,
 		   0, NULL, 0, arizona_in_ev,
-		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
+		   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
 SND_SOC_DAPM_PGA_E("IN3R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3R_ENA_SHIFT,
 		   0, NULL, 0, arizona_in_ev,
-		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
+		   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
 SND_SOC_DAPM_PGA_E("IN4L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN4L_ENA_SHIFT,
 		   0, NULL, 0, arizona_in_ev,
-		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
+		   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
 SND_SOC_DAPM_PGA_E("IN4R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN4R_ENA_SHIFT,
 		   0, NULL, 0, arizona_in_ev,
-		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
+		   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
 
 SND_SOC_DAPM_SUPPLY("MICBIAS1", ARIZONA_MIC_BIAS_CTRL_1,
 		    ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0),
@@ -551,11 +559,11 @@ SND_SOC_DAPM_AIF_IN("AIF3RX1", NULL, 0,
 SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0,
 		    ARIZONA_AIF3_RX_ENABLES, ARIZONA_AIF3RX2_ENA_SHIFT, 0),
 
-SND_SOC_DAPM_PGA_E("OUT1L", ARIZONA_OUTPUT_ENABLES_1,
-		   ARIZONA_OUT1L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
+SND_SOC_DAPM_PGA_E("OUT1L", SND_SOC_NOPM,
+		   ARIZONA_OUT1L_ENA_SHIFT, 0, NULL, 0, arizona_hp_ev,
 		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
-SND_SOC_DAPM_PGA_E("OUT1R", ARIZONA_OUTPUT_ENABLES_1,
-		   ARIZONA_OUT1R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
+SND_SOC_DAPM_PGA_E("OUT1R", SND_SOC_NOPM,
+		   ARIZONA_OUT1R_ENA_SHIFT, 0, NULL, 0, arizona_hp_ev,
 		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
 SND_SOC_DAPM_PGA_E("OUT2L", ARIZONA_OUTPUT_ENABLES_1,
 		   ARIZONA_OUT2L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
@@ -569,12 +577,6 @@ SND_SOC_DAPM_PGA_E("OUT3L", ARIZONA_OUTPUT_ENABLES_1,
 SND_SOC_DAPM_PGA_E("OUT3R", ARIZONA_OUTPUT_ENABLES_1,
 		   ARIZONA_OUT3R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
 		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
-SND_SOC_DAPM_PGA_E("OUT4L", ARIZONA_OUTPUT_ENABLES_1,
-		   ARIZONA_OUT4L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
-		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
-SND_SOC_DAPM_PGA_E("OUT4R", ARIZONA_OUTPUT_ENABLES_1,
-		   ARIZONA_OUT4R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
-		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
 SND_SOC_DAPM_PGA_E("OUT5L", ARIZONA_OUTPUT_ENABLES_1,
 		   ARIZONA_OUT5L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
 		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
@@ -880,6 +882,12 @@ static int wm5110_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
 		return arizona_set_fll(&wm5110->fll[0], source, Fref, Fout);
 	case WM5110_FLL2:
 		return arizona_set_fll(&wm5110->fll[1], source, Fref, Fout);
+	case WM5110_FLL1_REFCLK:
+		return arizona_set_fll_refclk(&wm5110->fll[0], source, Fref,
+					      Fout);
+	case WM5110_FLL2_REFCLK:
+		return arizona_set_fll_refclk(&wm5110->fll[1], source, Fref,
+					      Fout);
 	default:
 		return -EINVAL;
 	}
@@ -987,15 +995,6 @@ static int wm5110_codec_remove(struct snd_soc_codec *codec)
 #define WM5110_DIG_VU 0x0200
 
 static unsigned int wm5110_digital_vu[] = {
-	ARIZONA_ADC_DIGITAL_VOLUME_1L,
-	ARIZONA_ADC_DIGITAL_VOLUME_1R,
-	ARIZONA_ADC_DIGITAL_VOLUME_2L,
-	ARIZONA_ADC_DIGITAL_VOLUME_2R,
-	ARIZONA_ADC_DIGITAL_VOLUME_3L,
-	ARIZONA_ADC_DIGITAL_VOLUME_3R,
-	ARIZONA_ADC_DIGITAL_VOLUME_4L,
-	ARIZONA_ADC_DIGITAL_VOLUME_4R,
-
 	ARIZONA_DAC_DIGITAL_VOLUME_1L,
 	ARIZONA_DAC_DIGITAL_VOLUME_1R,
 	ARIZONA_DAC_DIGITAL_VOLUME_2L,
@@ -1040,6 +1039,7 @@ static int wm5110_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, wm5110);
 
 	wm5110->core.arizona = arizona;
+	wm5110->core.num_inputs = 8;
 
 	for (i = 0; i < ARRAY_SIZE(wm5110->fll); i++)
 		wm5110->fll[i].vco_mult = 3;
diff --git a/sound/soc/codecs/wm5110.h b/sound/soc/codecs/wm5110.h
index 75e9351..e6c0cd4 100644
--- a/sound/soc/codecs/wm5110.h
+++ b/sound/soc/codecs/wm5110.h
@@ -15,7 +15,9 @@
 
 #include "arizona.h"
 
-#define WM5110_FLL1 1
-#define WM5110_FLL2 2
+#define WM5110_FLL1        1
+#define WM5110_FLL2        2
+#define WM5110_FLL1_REFCLK 3
+#define WM5110_FLL2_REFCLK 4
 
 #endif
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c
index 134e41c..70e5eb2 100644
--- a/sound/soc/codecs/wm8903.c
+++ b/sound/soc/codecs/wm8903.c
@@ -478,6 +478,8 @@ static int wm8903_put_deemph(struct snd_kcontrol *kcontrol,
 /* ALSA can only do steps of .01dB */
 static const DECLARE_TLV_DB_SCALE(digital_tlv, -7200, 75, 1);
 
+static const DECLARE_TLV_DB_SCALE(dac_boost_tlv, 0, 600, 0);
+
 static const DECLARE_TLV_DB_SCALE(digital_sidetone_tlv, -3600, 300, 0);
 static const DECLARE_TLV_DB_SCALE(out_tlv, -5700, 100, 0);
 
@@ -698,6 +700,8 @@ SOC_ENUM("DAC Mute Mode", mute_mode),
 SOC_SINGLE("DAC Mono Switch", WM8903_DAC_DIGITAL_1, 12, 1, 0),
 SOC_ENUM("DAC Companding Mode", dac_companding),
 SOC_SINGLE("DAC Companding Switch", WM8903_AUDIO_INTERFACE_0, 1, 1, 0),
+SOC_SINGLE_TLV("DAC Boost Volume", WM8903_AUDIO_INTERFACE_0, 9, 3, 0,
+	       dac_boost_tlv),
 SOC_SINGLE_BOOL_EXT("Playback Deemphasis Switch", 0,
 		    wm8903_get_deemph, wm8903_put_deemph),
 
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c
index a64b934..0a4ffdd 100644
--- a/sound/soc/codecs/wm8960.c
+++ b/sound/soc/codecs/wm8960.c
@@ -204,6 +204,7 @@ static const DECLARE_TLV_DB_SCALE(adc_tlv, -9700, 50, 0);
 static const DECLARE_TLV_DB_SCALE(dac_tlv, -12700, 50, 1);
 static const DECLARE_TLV_DB_SCALE(bypass_tlv, -2100, 300, 0);
 static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1);
+static const DECLARE_TLV_DB_SCALE(boost_tlv, -1200, 300, 1);
 
 static const struct snd_kcontrol_new wm8960_snd_controls[] = {
 SOC_DOUBLE_R_TLV("Capture Volume", WM8960_LINVOL, WM8960_RINVOL,
@@ -213,6 +214,15 @@ SOC_DOUBLE_R("Capture Volume ZC Switch", WM8960_LINVOL, WM8960_RINVOL,
 SOC_DOUBLE_R("Capture Switch", WM8960_LINVOL, WM8960_RINVOL,
 	7, 1, 0),
 
+SOC_SINGLE_TLV("Right Input Boost Mixer RINPUT3 Volume",
+	       WM8960_INBMIX1, 4, 7, 0, boost_tlv),
+SOC_SINGLE_TLV("Right Input Boost Mixer RINPUT2 Volume",
+	       WM8960_INBMIX1, 1, 7, 0, boost_tlv),
+SOC_SINGLE_TLV("Left Input Boost Mixer LINPUT3 Volume",
+	       WM8960_INBMIX2, 4, 7, 0, boost_tlv),
+SOC_SINGLE_TLV("Left Input Boost Mixer LINPUT2 Volume",
+	       WM8960_INBMIX2, 1, 7, 0, boost_tlv),
+
 SOC_DOUBLE_R_TLV("Playback Volume", WM8960_LDAC, WM8960_RDAC,
 		 0, 255, 0, dac_tlv),
 
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
index c9bd445..1c02a47 100644
--- a/sound/soc/codecs/wm8994.c
+++ b/sound/soc/codecs/wm8994.c
@@ -2268,10 +2268,26 @@ out:
 	 */
 	if (max(wm8994->aifclk[0], wm8994->aifclk[1]) < 50000) {
 		dev_dbg(codec->dev, "Configuring AIFs for 128fs\n");
+
+		wm8994->aifdiv[0] = snd_soc_read(codec, WM8994_AIF1_RATE)
+			& WM8994_AIF1CLK_RATE_MASK;
+		wm8994->aifdiv[1] = snd_soc_read(codec, WM8994_AIF2_RATE)
+			& WM8994_AIF1CLK_RATE_MASK;
+
 		snd_soc_update_bits(codec, WM8994_AIF1_RATE,
 				    WM8994_AIF1CLK_RATE_MASK, 0x1);
 		snd_soc_update_bits(codec, WM8994_AIF2_RATE,
 				    WM8994_AIF2CLK_RATE_MASK, 0x1);
+	} else if (wm8994->aifdiv[0]) {
+		snd_soc_update_bits(codec, WM8994_AIF1_RATE,
+				    WM8994_AIF1CLK_RATE_MASK,
+				    wm8994->aifdiv[0]);
+		snd_soc_update_bits(codec, WM8994_AIF2_RATE,
+				    WM8994_AIF2CLK_RATE_MASK,
+				    wm8994->aifdiv[1]);
+
+		wm8994->aifdiv[0] = 0;
+		wm8994->aifdiv[1] = 0;
 	}
 
 	return 0;
@@ -2368,10 +2384,26 @@ static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai,
 	 */
 	if (max(wm8994->aifclk[0], wm8994->aifclk[1]) < 50000) {
 		dev_dbg(codec->dev, "Configuring AIFs for 128fs\n");
+
+		wm8994->aifdiv[0] = snd_soc_read(codec, WM8994_AIF1_RATE)
+			& WM8994_AIF1CLK_RATE_MASK;
+		wm8994->aifdiv[1] = snd_soc_read(codec, WM8994_AIF2_RATE)
+			& WM8994_AIF1CLK_RATE_MASK;
+
 		snd_soc_update_bits(codec, WM8994_AIF1_RATE,
 				    WM8994_AIF1CLK_RATE_MASK, 0x1);
 		snd_soc_update_bits(codec, WM8994_AIF2_RATE,
 				    WM8994_AIF2CLK_RATE_MASK, 0x1);
+	} else if (wm8994->aifdiv[0]) {
+		snd_soc_update_bits(codec, WM8994_AIF1_RATE,
+				    WM8994_AIF1CLK_RATE_MASK,
+				    wm8994->aifdiv[0]);
+		snd_soc_update_bits(codec, WM8994_AIF2_RATE,
+				    WM8994_AIF2CLK_RATE_MASK,
+				    wm8994->aifdiv[1]);
+
+		wm8994->aifdiv[0] = 0;
+		wm8994->aifdiv[1] = 0;
 	}
 
 	return 0;
@@ -2656,6 +2688,8 @@ static int wm8994_hw_params(struct snd_pcm_substream *substream,
 {
 	struct snd_soc_codec *codec = dai->codec;
 	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+	struct wm8994 *control = wm8994->wm8994;
+	struct wm8994_pdata *pdata = &control->pdata;
 	int aif1_reg;
 	int aif2_reg;
 	int bclk_reg;
@@ -2723,7 +2757,14 @@ static int wm8994_hw_params(struct snd_pcm_substream *substream,
 	}
 
 	wm8994->channels[id] = params_channels(params);
-	switch (params_channels(params)) {
+	if (pdata->max_channels_clocked[id] &&
+	    wm8994->channels[id] > pdata->max_channels_clocked[id]) {
+		dev_dbg(dai->dev, "Constraining channels to %d from %d\n",
+			pdata->max_channels_clocked[id], wm8994->channels[id]);
+		wm8994->channels[id] = pdata->max_channels_clocked[id];
+	}
+
+	switch (wm8994->channels[id]) {
 	case 1:
 	case 2:
 		bclk_rate *= 2;
@@ -2745,7 +2786,7 @@ static int wm8994_hw_params(struct snd_pcm_substream *substream,
 	dev_dbg(dai->dev, "AIF%dCLK is %dHz, target BCLK %dHz\n",
 		dai->id, wm8994->aifclk[id], bclk_rate);
 
-	if (params_channels(params) == 1 &&
+	if (wm8994->channels[id] == 1 &&
 	    (snd_soc_read(codec, aif1_reg) & 0x18) == 0x18)
 		aif2 |= WM8994_AIF1_MONO;
 
diff --git a/sound/soc/codecs/wm8994.h b/sound/soc/codecs/wm8994.h
index 45f1927..928e2c2 100644
--- a/sound/soc/codecs/wm8994.h
+++ b/sound/soc/codecs/wm8994.h
@@ -79,6 +79,7 @@ struct wm8994_priv {
 	int sysclk_rate[2];
 	int mclk[2];
 	int aifclk[2];
+	int aifdiv[2];
 	int channels[2];
 	struct wm8994_fll_config fll[2], fll_suspend[2];
 	struct completion fll_locked[2];
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c
index f3f7e75..e4ccf08 100644
--- a/sound/soc/codecs/wm_adsp.c
+++ b/sound/soc/codecs/wm_adsp.c
@@ -31,6 +31,7 @@
 
 #include <linux/mfd/arizona/registers.h>
 
+#include "arizona.h"
 #include "wm_adsp.h"
 
 #define adsp_crit(_dsp, fmt, ...) \
@@ -193,17 +194,25 @@ static void wm_adsp_buf_free(struct list_head *list)
 
 #define WM_ADSP_NUM_FW 4
 
+#define WM_ADSP_FW_MBC_VSS 0
+#define WM_ADSP_FW_TX      1
+#define WM_ADSP_FW_TX_SPK  2
+#define WM_ADSP_FW_RX_ANC  3
+
 static const char *wm_adsp_fw_text[WM_ADSP_NUM_FW] = {
-	"MBC/VSS", "Tx", "Tx Speaker", "Rx ANC"
+	[WM_ADSP_FW_MBC_VSS] = "MBC/VSS",
+	[WM_ADSP_FW_TX] =      "Tx",
+	[WM_ADSP_FW_TX_SPK] =  "Tx Speaker",
+	[WM_ADSP_FW_RX_ANC] =  "Rx ANC",
 };
 
 static struct {
 	const char *file;
 } wm_adsp_fw[WM_ADSP_NUM_FW] = {
-	{ .file = "mbc-vss" },
-	{ .file = "tx" },
-	{ .file = "tx-spk" },
-	{ .file = "rx-anc" },
+	[WM_ADSP_FW_MBC_VSS] = { .file = "mbc-vss" },
+	[WM_ADSP_FW_TX] =      { .file = "tx" },
+	[WM_ADSP_FW_TX_SPK] =  { .file = "tx-spk" },
+	[WM_ADSP_FW_RX_ANC] =  { .file = "rx-anc" },
 };
 
 static int wm_adsp_fw_get(struct snd_kcontrol *kcontrol,
@@ -246,17 +255,52 @@ static const struct soc_enum wm_adsp_fw_enum[] = {
 	SOC_ENUM_SINGLE(0, 3, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
 };
 
-const struct snd_kcontrol_new wm_adsp_fw_controls[] = {
+const struct snd_kcontrol_new wm_adsp1_fw_controls[] = {
+	SOC_ENUM_EXT("DSP1 Firmware", wm_adsp_fw_enum[0],
+		     wm_adsp_fw_get, wm_adsp_fw_put),
+	SOC_ENUM_EXT("DSP2 Firmware", wm_adsp_fw_enum[1],
+		     wm_adsp_fw_get, wm_adsp_fw_put),
+	SOC_ENUM_EXT("DSP3 Firmware", wm_adsp_fw_enum[2],
+		     wm_adsp_fw_get, wm_adsp_fw_put),
+};
+EXPORT_SYMBOL_GPL(wm_adsp1_fw_controls);
+
+#if IS_ENABLED(CONFIG_SND_SOC_ARIZONA)
+static const struct soc_enum wm_adsp2_rate_enum[] = {
+	SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP1_CONTROL_1,
+			      ARIZONA_DSP1_RATE_SHIFT, 0xf,
+			      ARIZONA_RATE_ENUM_SIZE,
+			      arizona_rate_text, arizona_rate_val),
+	SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP2_CONTROL_1,
+			      ARIZONA_DSP1_RATE_SHIFT, 0xf,
+			      ARIZONA_RATE_ENUM_SIZE,
+			      arizona_rate_text, arizona_rate_val),
+	SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP3_CONTROL_1,
+			      ARIZONA_DSP1_RATE_SHIFT, 0xf,
+			      ARIZONA_RATE_ENUM_SIZE,
+			      arizona_rate_text, arizona_rate_val),
+	SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP3_CONTROL_1,
+			      ARIZONA_DSP1_RATE_SHIFT, 0xf,
+			      ARIZONA_RATE_ENUM_SIZE,
+			      arizona_rate_text, arizona_rate_val),
+};
+
+const struct snd_kcontrol_new wm_adsp2_fw_controls[] = {
 	SOC_ENUM_EXT("DSP1 Firmware", wm_adsp_fw_enum[0],
 		     wm_adsp_fw_get, wm_adsp_fw_put),
+	SOC_ENUM("DSP1 Rate", wm_adsp2_rate_enum[0]),
 	SOC_ENUM_EXT("DSP2 Firmware", wm_adsp_fw_enum[1],
 		     wm_adsp_fw_get, wm_adsp_fw_put),
+	SOC_ENUM("DSP2 Rate", wm_adsp2_rate_enum[1]),
 	SOC_ENUM_EXT("DSP3 Firmware", wm_adsp_fw_enum[2],
 		     wm_adsp_fw_get, wm_adsp_fw_put),
+	SOC_ENUM("DSP3 Rate", wm_adsp2_rate_enum[2]),
 	SOC_ENUM_EXT("DSP4 Firmware", wm_adsp_fw_enum[3],
 		     wm_adsp_fw_get, wm_adsp_fw_put),
+	SOC_ENUM("DSP4 Rate", wm_adsp2_rate_enum[3]),
 };
-EXPORT_SYMBOL_GPL(wm_adsp_fw_controls);
+EXPORT_SYMBOL_GPL(wm_adsp2_fw_controls);
+#endif
 
 static struct wm_adsp_region const *wm_adsp_find_region(struct wm_adsp *dsp,
 							int type)
@@ -549,8 +593,9 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp)
 		buf_size = sizeof(adsp1_id);
 
 		algs = be32_to_cpu(adsp1_id.algs);
+		dsp->fw_id = be32_to_cpu(adsp1_id.fw.id);
 		adsp_info(dsp, "Firmware: %x v%d.%d.%d, %zu algorithms\n",
-			  be32_to_cpu(adsp1_id.fw.id),
+			  dsp->fw_id,
 			  (be32_to_cpu(adsp1_id.fw.ver) & 0xff0000) >> 16,
 			  (be32_to_cpu(adsp1_id.fw.ver) & 0xff00) >> 8,
 			  be32_to_cpu(adsp1_id.fw.ver) & 0xff,
@@ -573,8 +618,9 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp)
 		buf_size = sizeof(adsp2_id);
 
 		algs = be32_to_cpu(adsp2_id.algs);
+		dsp->fw_id = be32_to_cpu(adsp2_id.fw.id);
 		adsp_info(dsp, "Firmware: %x v%d.%d.%d, %zu algorithms\n",
-			  be32_to_cpu(adsp2_id.fw.id),
+			  dsp->fw_id,
 			  (be32_to_cpu(adsp2_id.fw.ver) & 0xff0000) >> 16,
 			  (be32_to_cpu(adsp2_id.fw.ver) & 0xff00) >> 8,
 			  be32_to_cpu(adsp2_id.fw.ver) & 0xff,
@@ -781,8 +827,24 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp)
 		case (WMFW_INFO_TEXT << 8):
 			break;
 		case (WMFW_ABSOLUTE << 8):
-			region_name = "register";
-			reg = offset;
+			/*
+			 * Old files may use this for global
+			 * coefficients.
+			 */
+			if (le32_to_cpu(blk->id) == dsp->fw_id &&
+			    offset == 0) {
+				region_name = "global coefficients";
+				mem = wm_adsp_find_region(dsp, type);
+				if (!mem) {
+					adsp_err(dsp, "No ZM\n");
+					break;
+				}
+				reg = wm_adsp_region_to_reg(mem, 0);
+
+			} else {
+				region_name = "register";
+				reg = offset;
+			}
 			break;
 
 		case WMFW_ADSP1_DM:
@@ -828,7 +890,8 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp)
 						&buf_list);
 			if (!buf) {
 				adsp_err(dsp, "Out of memory\n");
-				return -ENOMEM;
+				ret = -ENOMEM;
+				goto out_fw;
 			}
 
 			adsp_dbg(dsp, "%s.%d: Writing %d bytes at %x\n",
@@ -865,7 +928,7 @@ out_fw:
 	wm_adsp_buf_free(&buf_list);
 out:
 	kfree(file);
-	return 0;
+	return ret;
 }
 
 int wm_adsp1_init(struct wm_adsp *adsp)
diff --git a/sound/soc/codecs/wm_adsp.h b/sound/soc/codecs/wm_adsp.h
index cb8871a..fea5146 100644
--- a/sound/soc/codecs/wm_adsp.h
+++ b/sound/soc/codecs/wm_adsp.h
@@ -46,6 +46,8 @@ struct wm_adsp {
 
 	struct list_head alg_regions;
 
+	int fw_id;
+
 	const struct wm_adsp_region *mem;
 	int num_mems;
 
@@ -65,7 +67,8 @@ struct wm_adsp {
 	.shift = num, .event = wm_adsp2_event, \
 	.event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD }
 
-extern const struct snd_kcontrol_new wm_adsp_fw_controls[];
+extern const struct snd_kcontrol_new wm_adsp1_fw_controls[];
+extern const struct snd_kcontrol_new wm_adsp2_fw_controls[];
 
 int wm_adsp1_init(struct wm_adsp *adsp);
 int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs);
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c
index 867ae97..f5d81b9 100644
--- a/sound/soc/codecs/wm_hubs.c
+++ b/sound/soc/codecs/wm_hubs.c
@@ -199,11 +199,12 @@ static void wm_hubs_dcs_cache_set(struct snd_soc_codec *codec, u16 dcs_cfg)
 	list_add_tail(&cache->list, &hubs->dcs_cache);
 }
 
-static void wm_hubs_read_dc_servo(struct snd_soc_codec *codec,
+static int wm_hubs_read_dc_servo(struct snd_soc_codec *codec,
 				  u16 *reg_l, u16 *reg_r)
 {
 	struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec);
 	u16 dcs_reg, reg;
+	int ret = 0;
 
 	switch (hubs->dcs_readback_mode) {
 	case 2:
@@ -236,8 +237,9 @@ static void wm_hubs_read_dc_servo(struct snd_soc_codec *codec,
 		break;
 	default:
 		WARN(1, "Unknown DCS readback method\n");
-		return;
+		ret = -1;
 	}
+	return ret;
 }
 
 /*
@@ -286,7 +288,8 @@ static void enable_dc_servo(struct snd_soc_codec *codec)
 				  WM8993_DCS_TRIG_STARTUP_1);
 	}
 
-	wm_hubs_read_dc_servo(codec, &reg_l, &reg_r);
+	if (wm_hubs_read_dc_servo(codec, &reg_l, &reg_r) < 0)
+		return;
 
 	dev_dbg(codec->dev, "DCS input: %x %x\n", reg_l, reg_r);
 
diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c
index 8218312..ebe8294 100644
--- a/sound/soc/davinci/davinci-i2s.c
+++ b/sound/soc/davinci/davinci-i2s.c
@@ -645,6 +645,10 @@ static struct snd_soc_dai_driver davinci_i2s_dai = {
 
 };
 
+static const struct snd_soc_component_driver davinci_i2s_component = {
+	.name		= "davinci-i2s",
+};
+
 static int davinci_i2s_probe(struct platform_device *pdev)
 {
 	struct snd_platform_data *pdata = pdev->dev.platform_data;
@@ -727,20 +731,21 @@ static int davinci_i2s_probe(struct platform_device *pdev)
 
 	dev_set_drvdata(&pdev->dev, dev);
 
-	ret = snd_soc_register_dai(&pdev->dev, &davinci_i2s_dai);
+	ret = snd_soc_register_component(&pdev->dev, &davinci_i2s_component,
+					 &davinci_i2s_dai, 1);
 	if (ret != 0)
 		goto err_release_clk;
 
 	ret = davinci_soc_platform_register(&pdev->dev);
 	if (ret) {
 		dev_err(&pdev->dev, "register PCM failed: %d\n", ret);
-		goto err_unregister_dai;
+		goto err_unregister_component;
 	}
 
 	return 0;
 
-err_unregister_dai:
-	snd_soc_unregister_dai(&pdev->dev);
+err_unregister_component:
+	snd_soc_unregister_component(&pdev->dev);
 err_release_clk:
 	clk_disable(dev->clk);
 	clk_put(dev->clk);
@@ -751,7 +756,7 @@ static int davinci_i2s_remove(struct platform_device *pdev)
 {
 	struct davinci_mcbsp_dev *dev = dev_get_drvdata(&pdev->dev);
 
-	snd_soc_unregister_dai(&pdev->dev);
+	snd_soc_unregister_component(&pdev->dev);
 	davinci_soc_platform_unregister(&pdev->dev);
 
 	clk_disable(dev->clk);
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c
index 9321e5c..356a365 100644
--- a/sound/soc/davinci/davinci-mcasp.c
+++ b/sound/soc/davinci/davinci-mcasp.c
@@ -235,6 +235,8 @@
 #define DISMOD		(val)(val<<2)
 #define TXSTATE		BIT(4)
 #define RXSTATE		BIT(5)
+#define SRMOD_MASK	3
+#define SRMOD_INACTIVE	0
 
 /*
  * DAVINCI_MCASP_LBCTL_REG - Loop Back Control Register Bits
@@ -657,12 +659,15 @@ static int davinci_config_channel_size(struct davinci_audio_dev *dev,
 	return 0;
 }
 
-static void davinci_hw_common_param(struct davinci_audio_dev *dev, int stream)
+static int davinci_hw_common_param(struct davinci_audio_dev *dev, int stream,
+				    int channels)
 {
 	int i;
 	u8 tx_ser = 0;
 	u8 rx_ser = 0;
-
+	u8 ser;
+	u8 slots = dev->tdm_slots;
+	u8 max_active_serializers = (channels + slots - 1) / slots;
 	/* Default configuration */
 	mcasp_set_bits(dev->base + DAVINCI_MCASP_PWREMUMGT_REG, MCASP_SOFT);
 
@@ -682,17 +687,33 @@ static void davinci_hw_common_param(struct davinci_audio_dev *dev, int stream)
 	for (i = 0; i < dev->num_serializer; i++) {
 		mcasp_set_bits(dev->base + DAVINCI_MCASP_XRSRCTL_REG(i),
 					dev->serial_dir[i]);
-		if (dev->serial_dir[i] == TX_MODE) {
+		if (dev->serial_dir[i] == TX_MODE &&
+					tx_ser < max_active_serializers) {
 			mcasp_set_bits(dev->base + DAVINCI_MCASP_PDIR_REG,
 					AXR(i));
 			tx_ser++;
-		} else if (dev->serial_dir[i] == RX_MODE) {
+		} else if (dev->serial_dir[i] == RX_MODE &&
+					rx_ser < max_active_serializers) {
 			mcasp_clr_bits(dev->base + DAVINCI_MCASP_PDIR_REG,
 					AXR(i));
 			rx_ser++;
+		} else {
+			mcasp_mod_bits(dev->base + DAVINCI_MCASP_XRSRCTL_REG(i),
+					SRMOD_INACTIVE, SRMOD_MASK);
 		}
 	}
 
+	if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+		ser = tx_ser;
+	else
+		ser = rx_ser;
+
+	if (ser < max_active_serializers) {
+		dev_warn(dev->dev, "stream has more channels (%d) than are "
+			"enabled in mcasp (%d)\n", channels, ser * slots);
+		return -EINVAL;
+	}
+
 	if (dev->txnumevt && stream == SNDRV_PCM_STREAM_PLAYBACK) {
 		if (dev->txnumevt * tx_ser > 64)
 			dev->txnumevt = 1;
@@ -729,6 +750,8 @@ static void davinci_hw_common_param(struct davinci_audio_dev *dev, int stream)
 				((dev->rxnumevt * rx_ser) << 8), NUMEVT_MASK);
 		}
 	}
+
+	return 0;
 }
 
 static void davinci_hw_param(struct davinci_audio_dev *dev, int stream)
@@ -812,8 +835,14 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
 					&dev->dma_params[substream->stream];
 	int word_length;
 	u8 fifo_level;
+	u8 slots = dev->tdm_slots;
+	int channels;
+	struct snd_interval *pcm_channels = hw_param_interval(params,
+					SNDRV_PCM_HW_PARAM_CHANNELS);
+	channels = pcm_channels->min;
 
-	davinci_hw_common_param(dev, substream->stream);
+	if (davinci_hw_common_param(dev, substream->stream, channels) == -EINVAL)
+		return -EINVAL;
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 		fifo_level = dev->txnumevt;
 	else
@@ -862,6 +891,7 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
 		dma_params->acnt = dma_params->data_type;
 
 	dma_params->fifo_level = fifo_level;
+	dma_params->active_serializers = (channels + slots - 1) / slots;
 	davinci_config_channel_size(dev, word_length);
 
 	return 0;
@@ -936,13 +966,13 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = {
 		.name		= "davinci-mcasp.0",
 		.playback	= {
 			.channels_min	= 2,
-			.channels_max 	= 2,
+			.channels_max	= 32 * 16,
 			.rates 		= DAVINCI_MCASP_RATES,
 			.formats	= DAVINCI_MCASP_PCM_FMTS,
 		},
 		.capture 	= {
 			.channels_min 	= 2,
-			.channels_max 	= 2,
+			.channels_max	= 32 * 16,
 			.rates 		= DAVINCI_MCASP_RATES,
 			.formats	= DAVINCI_MCASP_PCM_FMTS,
 		},
@@ -962,6 +992,10 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = {
 
 };
 
+static const struct snd_soc_component_driver davinci_mcasp_component = {
+	.name		= "davinci-mcasp",
+};
+
 static const struct of_device_id mcasp_dt_ids[] = {
 	{
 		.compatible = "ti,dm646x-mcasp-audio",
@@ -1015,8 +1049,16 @@ static struct snd_platform_data *davinci_mcasp_set_pdata_from_of(
 		pdata->op_mode = val;
 
 	ret = of_property_read_u32(np, "tdm-slots", &val);
-	if (ret >= 0)
+	if (ret >= 0) {
+		if (val < 2 || val > 32) {
+			dev_err(&pdev->dev,
+				"tdm-slots must be in rage [2-32]\n");
+			ret = -EINVAL;
+			goto nodata;
+		}
+
 		pdata->tdm_slots = val;
+	}
 
 	ret = of_property_read_u32(np, "num-serializer", &val);
 	if (ret >= 0)
@@ -1170,7 +1212,8 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
 
 	dma_data->channel = res->start;
 	dev_set_drvdata(&pdev->dev, dev);
-	ret = snd_soc_register_dai(&pdev->dev, &davinci_mcasp_dai[pdata->op_mode]);
+	ret = snd_soc_register_component(&pdev->dev, &davinci_mcasp_component,
+					 &davinci_mcasp_dai[pdata->op_mode], 1);
 
 	if (ret != 0)
 		goto err_release_clk;
@@ -1178,13 +1221,13 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
 	ret = davinci_soc_platform_register(&pdev->dev);
 	if (ret) {
 		dev_err(&pdev->dev, "register PCM failed: %d\n", ret);
-		goto err_unregister_dai;
+		goto err_unregister_component;
 	}
 
 	return 0;
 
-err_unregister_dai:
-	snd_soc_unregister_dai(&pdev->dev);
+err_unregister_component:
+	snd_soc_unregister_component(&pdev->dev);
 err_release_clk:
 	pm_runtime_put_sync(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
@@ -1194,7 +1237,7 @@ err_release_clk:
 static int davinci_mcasp_remove(struct platform_device *pdev)
 {
 
-	snd_soc_unregister_dai(&pdev->dev);
+	snd_soc_unregister_component(&pdev->dev);
 	davinci_soc_platform_unregister(&pdev->dev);
 
 	pm_runtime_put_sync(&pdev->dev);
diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c
index afab81f..078031d 100644
--- a/sound/soc/davinci/davinci-pcm.c
+++ b/sound/soc/davinci/davinci-pcm.c
@@ -181,6 +181,7 @@ static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream)
 	unsigned short acnt;
 	unsigned int count;
 	unsigned int fifo_level;
+	unsigned char serializers = prtd->params->active_serializers;
 
 	period_size = snd_pcm_lib_period_bytes(substream);
 	dma_offset = prtd->period * period_size;
@@ -194,14 +195,14 @@ static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream)
 	data_type = prtd->params->data_type;
 	count = period_size / data_type;
 	if (fifo_level)
-		count /= fifo_level;
+		count /= fifo_level * serializers;
 
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 		src = dma_pos;
 		dst = prtd->params->dma_addr;
 		src_bidx = data_type;
-		dst_bidx = 0;
-		src_cidx = data_type * fifo_level;
+		dst_bidx = 4;
+		src_cidx = data_type * fifo_level * serializers;
 		dst_cidx = 0;
 	} else {
 		src = prtd->params->dma_addr;
@@ -209,7 +210,7 @@ static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream)
 		src_bidx = 0;
 		dst_bidx = data_type;
 		src_cidx = 0;
-		dst_cidx = data_type * fifo_level;
+		dst_cidx = data_type * fifo_level * serializers;
 	}
 
 	acnt = prtd->params->acnt;
@@ -223,9 +224,10 @@ static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream)
 		edma_set_transfer_params(prtd->asp_link[0], acnt, count, 1, 0,
 							ASYNC);
 	else
-		edma_set_transfer_params(prtd->asp_link[0], acnt, fifo_level,
-							count, fifo_level,
-							ABSYNC);
+		edma_set_transfer_params(prtd->asp_link[0], acnt,
+						fifo_level * serializers,
+						count, fifo_level * serializers,
+						ABSYNC);
 }
 
 static void davinci_pcm_dma_irq(unsigned link, u16 ch_status, void *data)
diff --git a/sound/soc/davinci/davinci-pcm.h b/sound/soc/davinci/davinci-pcm.h
index b6ef703..32d7634 100644
--- a/sound/soc/davinci/davinci-pcm.h
+++ b/sound/soc/davinci/davinci-pcm.h
@@ -27,6 +27,7 @@ struct davinci_pcm_dma_params {
 	unsigned char data_type;	/* xfer data type */
 	unsigned char convert_mono_stereo;
 	unsigned int fifo_level;
+	unsigned char active_serializers; /* num. of active audio serializers */
 };
 
 int davinci_soc_platform_register(struct device *dev);
diff --git a/sound/soc/davinci/davinci-vcif.c b/sound/soc/davinci/davinci-vcif.c
index 07bde2e..30587c0 100644
--- a/sound/soc/davinci/davinci-vcif.c
+++ b/sound/soc/davinci/davinci-vcif.c
@@ -204,6 +204,10 @@ static struct snd_soc_dai_driver davinci_vcif_dai = {
 
 };
 
+static const struct snd_soc_component_driver davinci_vcif_component = {
+	.name		= "davinci-vcif",
+};
+
 static int davinci_vcif_probe(struct platform_device *pdev)
 {
 	struct davinci_vc *davinci_vc = pdev->dev.platform_data;
@@ -234,7 +238,8 @@ static int davinci_vcif_probe(struct platform_device *pdev)
 
 	dev_set_drvdata(&pdev->dev, davinci_vcif_dev);
 
-	ret = snd_soc_register_dai(&pdev->dev, &davinci_vcif_dai);
+	ret = snd_soc_register_component(&pdev->dev, &davinci_vcif_component,
+					 &davinci_vcif_dai, 1);
 	if (ret != 0) {
 		dev_err(&pdev->dev, "could not register dai\n");
 		return ret;
@@ -243,7 +248,7 @@ static int davinci_vcif_probe(struct platform_device *pdev)
 	ret = davinci_soc_platform_register(&pdev->dev);
 	if (ret) {
 		dev_err(&pdev->dev, "register PCM failed: %d\n", ret);
-		snd_soc_unregister_dai(&pdev->dev);
+		snd_soc_unregister_component(&pdev->dev);
 		return ret;
 	}
 
@@ -252,7 +257,7 @@ static int davinci_vcif_probe(struct platform_device *pdev)
 
 static int davinci_vcif_remove(struct platform_device *pdev)
 {
-	snd_soc_unregister_dai(&pdev->dev);
+	snd_soc_unregister_component(&pdev->dev);
 	davinci_soc_platform_unregister(&pdev->dev);
 
 	return 0;
diff --git a/sound/soc/dwc/designware_i2s.c b/sound/soc/dwc/designware_i2s.c
index deb30d5..593a3ea1 100644
--- a/sound/soc/dwc/designware_i2s.c
+++ b/sound/soc/dwc/designware_i2s.c
@@ -297,6 +297,10 @@ static struct snd_soc_dai_ops dw_i2s_dai_ops = {
 	.trigger	= dw_i2s_trigger,
 };
 
+static const struct snd_soc_component_driver dw_i2s_component = {
+	.name		= "dw-i2s",
+};
+
 #ifdef CONFIG_PM
 
 static int dw_i2s_suspend(struct snd_soc_dai *dai)
@@ -413,7 +417,8 @@ static int dw_i2s_probe(struct platform_device *pdev)
 
 	dev->dev = &pdev->dev;
 	dev_set_drvdata(&pdev->dev, dev);
-	ret = snd_soc_register_dai(&pdev->dev, dw_i2s_dai);
+	ret = snd_soc_register_component(&pdev->dev, &dw_i2s_component,
+					 dw_i2s_dai, 1);
 	if (ret != 0) {
 		dev_err(&pdev->dev, "not able to register dai\n");
 		goto err_set_drvdata;
@@ -434,7 +439,7 @@ static int dw_i2s_remove(struct platform_device *pdev)
 {
 	struct dw_i2s_dev *dev = dev_get_drvdata(&pdev->dev);
 
-	snd_soc_unregister_dai(&pdev->dev);
+	snd_soc_unregister_component(&pdev->dev);
 	dev_set_drvdata(&pdev->dev, NULL);
 
 	clk_put(dev->clk);
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 7decbd9..d02450e 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -574,6 +574,10 @@ static struct snd_soc_dai_driver fsl_ssi_dai_template = {
 	.ops = &fsl_ssi_dai_ops,
 };
 
+static const struct snd_soc_component_driver fsl_ssi_component = {
+	.name		= "fsl-ssi",
+};
+
 /* Show the statistics of a flag only if its interrupt is enabled.  The
  * compiler will optimze this code to a no-op if the interrupt is not
  * enabled.
@@ -649,6 +653,7 @@ static int fsl_ssi_probe(struct platform_device *pdev)
 	const uint32_t *iprop;
 	struct resource res;
 	char name[64];
+	bool shared;
 
 	/* SSIs that are not connected on the board should have a
 	 *      status = "disabled"
@@ -755,14 +760,14 @@ static int fsl_ssi_probe(struct platform_device *pdev)
 			dev_err(&pdev->dev, "could not get dma events\n");
 			goto error_clk;
 		}
-		ssi_private->dma_params_tx.dma = dma_events[0];
-		ssi_private->dma_params_rx.dma = dma_events[1];
 
-		ssi_private->dma_params_tx.shared_peripheral =
-				of_device_is_compatible(of_get_parent(np),
-							"fsl,spba-bus");
-		ssi_private->dma_params_rx.shared_peripheral =
-				ssi_private->dma_params_tx.shared_peripheral;
+		shared = of_device_is_compatible(of_get_parent(np),
+			    "fsl,spba-bus");
+
+		imx_pcm_dma_params_init_data(&ssi_private->dma_params_tx,
+			dma_events[0], shared);
+		imx_pcm_dma_params_init_data(&ssi_private->dma_params_rx,
+			dma_events[1], shared);
 	}
 
 	/* Initialize the the device_attribute structure */
@@ -782,7 +787,8 @@ static int fsl_ssi_probe(struct platform_device *pdev)
 	/* Register with ASoC */
 	dev_set_drvdata(&pdev->dev, ssi_private);
 
-	ret = snd_soc_register_dai(&pdev->dev, &ssi_private->cpu_dai_drv);
+	ret = snd_soc_register_component(&pdev->dev, &fsl_ssi_component,
+					 &ssi_private->cpu_dai_drv, 1);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to register DAI: %d\n", ret);
 		goto error_dev;
@@ -835,7 +841,7 @@ done:
 error_dai:
 	if (ssi_private->ssi_on_imx)
 		platform_device_unregister(ssi_private->imx_pcm_pdev);
-	snd_soc_unregister_dai(&pdev->dev);
+	snd_soc_unregister_component(&pdev->dev);
 
 error_dev:
 	dev_set_drvdata(&pdev->dev, NULL);
@@ -873,7 +879,7 @@ static int fsl_ssi_remove(struct platform_device *pdev)
 		clk_disable_unprepare(ssi_private->clk);
 		clk_put(ssi_private->clk);
 	}
-	snd_soc_unregister_dai(&pdev->dev);
+	snd_soc_unregister_component(&pdev->dev);
 	device_remove_file(&pdev->dev, &ssi_private->dev_attr);
 
 	free_irq(ssi_private->irq, ssi_private);
diff --git a/sound/soc/fsl/imx-audmux.c b/sound/soc/fsl/imx-audmux.c
index 3f333e5..47f046a 100644
--- a/sound/soc/fsl/imx-audmux.c
+++ b/sound/soc/fsl/imx-audmux.c
@@ -262,7 +262,7 @@ static int imx_audmux_probe(struct platform_device *pdev)
 		return PTR_ERR(pinctrl);
 	}
 
-	audmux_clk = clk_get(&pdev->dev, "audmux");
+	audmux_clk = devm_clk_get(&pdev->dev, "audmux");
 	if (IS_ERR(audmux_clk)) {
 		dev_dbg(&pdev->dev, "cannot get clock: %ld\n",
 				PTR_ERR(audmux_clk));
@@ -282,7 +282,6 @@ static int imx_audmux_remove(struct platform_device *pdev)
 {
 	if (audmux_type == IMX31_AUDMUX)
 		audmux_debugfs_remove();
-	clk_put(audmux_clk);
 
 	return 0;
 }
diff --git a/sound/soc/fsl/imx-pcm-dma.c b/sound/soc/fsl/imx-pcm-dma.c
index 500f8ce..64af573 100644
--- a/sound/soc/fsl/imx-pcm-dma.c
+++ b/sound/soc/fsl/imx-pcm-dma.c
@@ -30,8 +30,6 @@
 #include <sound/soc.h>
 #include <sound/dmaengine_pcm.h>
 
-#include <linux/platform_data/dma-imx.h>
-
 #include "imx-pcm.h"
 
 static bool filter(struct dma_chan *chan, void *param)
@@ -59,8 +57,6 @@ static int snd_imx_pcm_hw_params(struct snd_pcm_substream *substream,
 	if (ret)
 		return ret;
 
-	slave_config.device_fc = false;
-
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 		slave_config.dst_addr = dma_params->dma_addr;
 		slave_config.dst_maxburst = dma_params->burstsize;
@@ -101,46 +97,17 @@ static int snd_imx_open(struct snd_pcm_substream *substream)
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct imx_pcm_dma_params *dma_params;
-	struct imx_dma_data *dma_data;
-	int ret;
 
 	snd_soc_set_runtime_hwparams(substream, &snd_imx_hardware);
 
 	dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
 
-	dma_data = kzalloc(sizeof(*dma_data), GFP_KERNEL);
-	if (!dma_data)
-		return -ENOMEM;
-
-	dma_data->peripheral_type = dma_params->shared_peripheral ?
-					IMX_DMATYPE_SSI_SP : IMX_DMATYPE_SSI;
-	dma_data->priority = DMA_PRIO_HIGH;
-	dma_data->dma_request = dma_params->dma;
-
-	ret = snd_dmaengine_pcm_open(substream, filter, dma_data);
-	if (ret) {
-		kfree(dma_data);
-		return ret;
-	}
-
-	snd_dmaengine_pcm_set_data(substream, dma_data);
-
-	return 0;
-}
-
-static int snd_imx_close(struct snd_pcm_substream *substream)
-{
-	struct imx_dma_data *dma_data = snd_dmaengine_pcm_get_data(substream);
-
-	snd_dmaengine_pcm_close(substream);
-	kfree(dma_data);
-
-	return 0;
+	return snd_dmaengine_pcm_open(substream, filter, &dma_params->dma_data);
 }
 
 static struct snd_pcm_ops imx_pcm_ops = {
 	.open		= snd_imx_open,
-	.close		= snd_imx_close,
+	.close		= snd_dmaengine_pcm_close,
 	.ioctl		= snd_pcm_lib_ioctl,
 	.hw_params	= snd_imx_pcm_hw_params,
 	.trigger	= snd_dmaengine_pcm_trigger,
diff --git a/sound/soc/fsl/imx-pcm-fiq.c b/sound/soc/fsl/imx-pcm-fiq.c
index 920f945..47228c0 100644
--- a/sound/soc/fsl/imx-pcm-fiq.c
+++ b/sound/soc/fsl/imx-pcm-fiq.c
@@ -34,7 +34,7 @@
 #include "imx-ssi.h"
 
 struct imx_pcm_runtime_data {
-	int period;
+	unsigned int period;
 	int periods;
 	unsigned long offset;
 	unsigned long last_offset;
diff --git a/sound/soc/fsl/imx-pcm.h b/sound/soc/fsl/imx-pcm.h
index 5ae13a1..16eaf5a 100644
--- a/sound/soc/fsl/imx-pcm.h
+++ b/sound/soc/fsl/imx-pcm.h
@@ -13,18 +13,31 @@
 #ifndef _IMX_PCM_H
 #define _IMX_PCM_H
 
+#include <linux/platform_data/dma-imx.h>
+
 /*
  * Do not change this as the FIQ handler depends on this size
  */
 #define IMX_SSI_DMABUF_SIZE	(64 * 1024)
 
 struct imx_pcm_dma_params {
-	int dma;
 	unsigned long dma_addr;
 	int burstsize;
-	bool shared_peripheral;	/* The peripheral is on SPBA bus */
+	struct imx_dma_data dma_data;
 };
 
+static inline void
+imx_pcm_dma_params_init_data(struct imx_pcm_dma_params *params,
+	int dma, bool shared)
+{
+	params->dma_data.dma_request = dma;
+	params->dma_data.priority = DMA_PRIO_HIGH;
+	if (shared)
+		params->dma_data.peripheral_type = IMX_DMATYPE_SSI_SP;
+	else
+		params->dma_data.peripheral_type = IMX_DMATYPE_SSI;
+}
+
 int snd_imx_pcm_mmap(struct snd_pcm_substream *substream,
 		     struct vm_area_struct *vma);
 int imx_pcm_new(struct snd_soc_pcm_runtime *rtd);
diff --git a/sound/soc/fsl/imx-sgtl5000.c b/sound/soc/fsl/imx-sgtl5000.c
index 424347e..9584e78 100644
--- a/sound/soc/fsl/imx-sgtl5000.c
+++ b/sound/soc/fsl/imx-sgtl5000.c
@@ -148,7 +148,7 @@ static int imx_sgtl5000_probe(struct platform_device *pdev)
 	data->dai.stream_name = "HiFi";
 	data->dai.codec_dai_name = "sgtl5000";
 	data->dai.codec_of_node = codec_np;
-	data->dai.cpu_dai_name = dev_name(&ssi_pdev->dev);
+	data->dai.cpu_of_node = ssi_np;
 	data->dai.platform_name = "imx-pcm-audio";
 	data->dai.init = &imx_sgtl5000_dai_init;
 	data->dai.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
diff --git a/sound/soc/fsl/imx-ssi.c b/sound/soc/fsl/imx-ssi.c
index 55464a5..706097f 100644
--- a/sound/soc/fsl/imx-ssi.c
+++ b/sound/soc/fsl/imx-ssi.c
@@ -400,7 +400,7 @@ static struct snd_soc_dai_driver imx_ac97_dai = {
 		.stream_name = "AC97 Playback",
 		.channels_min = 2,
 		.channels_max = 2,
-		.rates = SNDRV_PCM_RATE_48000,
+		.rates = SNDRV_PCM_RATE_8000_48000,
 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
 	},
 	.capture = {
@@ -413,6 +413,10 @@ static struct snd_soc_dai_driver imx_ac97_dai = {
 	.ops = &imx_ssi_pcm_dai_ops,
 };
 
+static const struct snd_soc_component_driver imx_component = {
+	.name		= DRV_NAME,
+};
+
 static void setup_channel_to_ac97(struct imx_ssi *imx_ssi)
 {
 	void __iomem *base = imx_ssi->base;
@@ -496,6 +500,8 @@ static void imx_ssi_ac97_reset(struct snd_ac97 *ac97)
 
 	if (imx_ssi->ac97_reset)
 		imx_ssi->ac97_reset(ac97);
+	/* First read sometimes fails, do a dummy read */
+	imx_ssi_ac97_read(ac97, 0);
 }
 
 static void imx_ssi_ac97_warm_reset(struct snd_ac97 *ac97)
@@ -504,6 +510,9 @@ static void imx_ssi_ac97_warm_reset(struct snd_ac97 *ac97)
 
 	if (imx_ssi->ac97_warm_reset)
 		imx_ssi->ac97_warm_reset(ac97);
+
+	/* First read sometimes fails, do a dummy read */
+	imx_ssi_ac97_read(ac97, 0);
 }
 
 struct snd_ac97_bus_ops soc_ac97_ops = {
@@ -577,16 +586,21 @@ static int imx_ssi_probe(struct platform_device *pdev)
 	ssi->dma_params_rx.burstsize = 4;
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx0");
-	if (res)
-		ssi->dma_params_tx.dma = res->start;
+	if (res) {
+		imx_pcm_dma_params_init_data(&ssi->dma_params_tx, res->start,
+			false);
+	}
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx0");
-	if (res)
-		ssi->dma_params_rx.dma = res->start;
+	if (res) {
+		imx_pcm_dma_params_init_data(&ssi->dma_params_rx, res->start,
+			false);
+	}
 
 	platform_set_drvdata(pdev, ssi);
 
-	ret = snd_soc_register_dai(&pdev->dev, dai);
+	ret = snd_soc_register_component(&pdev->dev, &imx_component,
+					 dai, 1);
 	if (ret) {
 		dev_err(&pdev->dev, "register DAI failed\n");
 		goto failed_register;
@@ -627,7 +641,7 @@ failed_pdev_alloc:
 failed_pdev_fiq_add:
 	platform_device_put(ssi->soc_platform_pdev_fiq);
 failed_pdev_fiq_alloc:
-	snd_soc_unregister_dai(&pdev->dev);
+	snd_soc_unregister_component(&pdev->dev);
 failed_register:
 	release_mem_region(res->start, resource_size(res));
 failed_get_resource:
@@ -645,7 +659,7 @@ static int imx_ssi_remove(struct platform_device *pdev)
 	platform_device_unregister(ssi->soc_platform_pdev);
 	platform_device_unregister(ssi->soc_platform_pdev_fiq);
 
-	snd_soc_unregister_dai(&pdev->dev);
+	snd_soc_unregister_component(&pdev->dev);
 
 	if (ssi->flags & IMX_SSI_USE_AC97)
 		ac97_ssi = NULL;
diff --git a/sound/soc/fsl/mpc5200_psc_ac97.c b/sound/soc/fsl/mpc5200_psc_ac97.c
index a4aec04..4141b35 100644
--- a/sound/soc/fsl/mpc5200_psc_ac97.c
+++ b/sound/soc/fsl/mpc5200_psc_ac97.c
@@ -270,6 +270,9 @@ static struct snd_soc_dai_driver psc_ac97_dai[] = {
 	.ops = &psc_ac97_digital_ops,
 } };
 
+static const struct snd_soc_component_driver psc_ac97_component = {
+	.name		= DRV_NAME,
+};
 
 
 /* ---------------------------------------------------------------------
@@ -287,7 +290,8 @@ static int psc_ac97_of_probe(struct platform_device *op)
 	if (rc != 0)
 		return rc;
 
-	rc = snd_soc_register_dais(&op->dev, psc_ac97_dai, ARRAY_SIZE(psc_ac97_dai));
+	rc = snd_soc_register_component(&op->dev, &psc_ac97_component,
+					psc_ac97_dai, ARRAY_SIZE(psc_ac97_dai));
 	if (rc != 0) {
 		dev_err(&op->dev, "Failed to register DAI\n");
 		return rc;
@@ -313,7 +317,7 @@ static int psc_ac97_of_probe(struct platform_device *op)
 static int psc_ac97_of_remove(struct platform_device *op)
 {
 	mpc5200_audio_dma_destroy(op);
-	snd_soc_unregister_dais(&op->dev, ARRAY_SIZE(psc_ac97_dai));
+	snd_soc_unregister_component(&op->dev);
 	return 0;
 }
 
diff --git a/sound/soc/fsl/mpc5200_psc_i2s.c b/sound/soc/fsl/mpc5200_psc_i2s.c
index b95b966..f4efaad 100644
--- a/sound/soc/fsl/mpc5200_psc_i2s.c
+++ b/sound/soc/fsl/mpc5200_psc_i2s.c
@@ -148,6 +148,10 @@ static struct snd_soc_dai_driver psc_i2s_dai[] = {{
 	.ops = &psc_i2s_dai_ops,
 } };
 
+static const struct snd_soc_component_driver psc_i2s_component = {
+	.name		= "mpc5200-i2s",
+};
+
 /* ---------------------------------------------------------------------
  * OF platform bus binding code:
  * - Probe/remove operations
@@ -163,7 +167,8 @@ static int psc_i2s_of_probe(struct platform_device *op)
 	if (rc != 0)
 		return rc;
 
-	rc = snd_soc_register_dais(&op->dev, psc_i2s_dai, ARRAY_SIZE(psc_i2s_dai));
+	rc = snd_soc_register_component(&op->dev, &psc_i2s_component,
+					psc_i2s_dai, ARRAY_SIZE(psc_i2s_dai));
 	if (rc != 0) {
 		pr_err("Failed to register DAI\n");
 		return rc;
@@ -208,7 +213,7 @@ static int psc_i2s_of_probe(struct platform_device *op)
 static int psc_i2s_of_remove(struct platform_device *op)
 {
 	mpc5200_audio_dma_destroy(op);
-	snd_soc_unregister_dais(&op->dev, ARRAY_SIZE(psc_i2s_dai));
+	snd_soc_unregister_component(&op->dev);
 	return 0;
 }
 
diff --git a/sound/soc/fsl/pcm030-audio-fabric.c b/sound/soc/fsl/pcm030-audio-fabric.c
index 8e52c14..eb43738 100644
--- a/sound/soc/fsl/pcm030-audio-fabric.c
+++ b/sound/soc/fsl/pcm030-audio-fabric.c
@@ -51,7 +51,7 @@ static struct snd_soc_card pcm030_card = {
 	.num_links = ARRAY_SIZE(pcm030_fabric_dai),
 };
 
-static int __init pcm030_fabric_probe(struct platform_device *op)
+static int pcm030_fabric_probe(struct platform_device *op)
 {
 	struct device_node *np = op->dev.of_node;
 	struct device_node *platform_np;
diff --git a/sound/soc/jz4740/jz4740-i2s.c b/sound/soc/jz4740/jz4740-i2s.c
index 6cef491..9a12644 100644
--- a/sound/soc/jz4740/jz4740-i2s.c
+++ b/sound/soc/jz4740/jz4740-i2s.c
@@ -425,6 +425,10 @@ static struct snd_soc_dai_driver jz4740_i2s_dai = {
 	.resume = jz4740_i2s_resume,
 };
 
+static const struct snd_soc_component_driver jz4740_i2s_component = {
+	.name		= "jz4740-i2s",
+};
+
 static int jz4740_i2s_dev_probe(struct platform_device *pdev)
 {
 	struct jz4740_i2s *i2s;
@@ -469,7 +473,8 @@ static int jz4740_i2s_dev_probe(struct platform_device *pdev)
 	}
 
 	platform_set_drvdata(pdev, i2s);
-	ret = snd_soc_register_dai(&pdev->dev, &jz4740_i2s_dai);
+	ret = snd_soc_register_component(&pdev->dev, &jz4740_i2s_component,
+					 &jz4740_i2s_dai, 1);
 
 	if (ret) {
 		dev_err(&pdev->dev, "Failed to register DAI\n");
@@ -496,7 +501,7 @@ static int jz4740_i2s_dev_remove(struct platform_device *pdev)
 {
 	struct jz4740_i2s *i2s = platform_get_drvdata(pdev);
 
-	snd_soc_unregister_dai(&pdev->dev);
+	snd_soc_unregister_component(&pdev->dev);
 
 	clk_put(i2s->clk_i2s);
 	clk_put(i2s->clk_aic);
diff --git a/sound/soc/kirkwood/kirkwood-i2s.c b/sound/soc/kirkwood/kirkwood-i2s.c
index c74c890..befe68f 100644
--- a/sound/soc/kirkwood/kirkwood-i2s.c
+++ b/sound/soc/kirkwood/kirkwood-i2s.c
@@ -451,6 +451,10 @@ static struct snd_soc_dai_driver kirkwood_i2s_dai_extclk = {
 	.ops = &kirkwood_i2s_dai_ops,
 };
 
+static const struct snd_soc_component_driver kirkwood_i2s_component = {
+	.name		= DRV_NAME,
+};
+
 static int kirkwood_i2s_dev_probe(struct platform_device *pdev)
 {
 	struct kirkwood_asoc_platform_data *data = pdev->dev.platform_data;
@@ -524,10 +528,11 @@ static int kirkwood_i2s_dev_probe(struct platform_device *pdev)
 		priv->ctl_rec |= KIRKWOOD_RECCTL_BURST_128;
 	}
 
-	err = snd_soc_register_dai(&pdev->dev, soc_dai);
+	err = snd_soc_register_component(&pdev->dev, &kirkwood_i2s_component,
+					 soc_dai, 1);
 	if (!err)
 		return 0;
-	dev_err(&pdev->dev, "snd_soc_register_dai failed\n");
+	dev_err(&pdev->dev, "snd_soc_register_component failed\n");
 
 	if (!IS_ERR(priv->extclk)) {
 		clk_disable_unprepare(priv->extclk);
@@ -542,7 +547,7 @@ static int kirkwood_i2s_dev_remove(struct platform_device *pdev)
 {
 	struct kirkwood_dma_data *priv = dev_get_drvdata(&pdev->dev);
 
-	snd_soc_unregister_dai(&pdev->dev);
+	snd_soc_unregister_component(&pdev->dev);
 
 	if (!IS_ERR(priv->extclk)) {
 		clk_disable_unprepare(priv->extclk);
diff --git a/sound/soc/mid-x86/sst_platform.c b/sound/soc/mid-x86/sst_platform.c
index a263cbe..392fc0b 100644
--- a/sound/soc/mid-x86/sst_platform.c
+++ b/sound/soc/mid-x86/sst_platform.c
@@ -1,7 +1,7 @@
 /*
  *  sst_platform.c - Intel MID Platform driver
  *
- *  Copyright (C) 2010-2012 Intel Corp
+ *  Copyright (C) 2010-2013 Intel Corp
  *  Author: Vinod Koul <vinod.koul@intel.com>
  *  Author: Harsha Priya <priya.harsha@intel.com>
  *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -165,6 +165,10 @@ static struct snd_soc_dai_driver sst_platform_dai[] = {
 },
 };
 
+static const struct snd_soc_component_driver sst_component = {
+	.name		= "sst",
+};
+
 /* helper functions */
 static inline void sst_set_stream_status(struct sst_runtime_stream *stream,
 					int state)
@@ -652,11 +656,21 @@ static int sst_platform_compr_get_codec_caps(struct snd_compr_stream *cstream,
 	return stream->compr_ops->get_codec_caps(codec);
 }
 
+static int sst_platform_compr_set_metadata(struct snd_compr_stream *cstream,
+					struct snd_compr_metadata *metadata)
+{
+	struct sst_runtime_stream *stream  =
+		 cstream->runtime->private_data;
+
+	return stream->compr_ops->set_metadata(stream->id, metadata);
+}
+
 static struct snd_compr_ops sst_platform_compr_ops = {
 
 	.open = sst_platform_compr_open,
 	.free = sst_platform_compr_free,
 	.set_params = sst_platform_compr_set_params,
+	.set_metadata = sst_platform_compr_set_metadata,
 	.trigger = sst_platform_compr_trigger,
 	.pointer = sst_platform_compr_pointer,
 	.ack = sst_platform_compr_ack,
@@ -683,7 +697,7 @@ static int sst_platform_probe(struct platform_device *pdev)
 		return ret;
 	}
 
-	ret = snd_soc_register_dais(&pdev->dev,
+	ret = snd_soc_register_component(&pdev->dev, &sst_component,
 				sst_platform_dai, ARRAY_SIZE(sst_platform_dai));
 	if (ret) {
 		pr_err("registering cpu dais failed\n");
@@ -695,7 +709,7 @@ static int sst_platform_probe(struct platform_device *pdev)
 static int sst_platform_remove(struct platform_device *pdev)
 {
 
-	snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(sst_platform_dai));
+	snd_soc_unregister_component(&pdev->dev);
 	snd_soc_unregister_platform(&pdev->dev);
 	pr_debug("sst_platform_remove success\n");
 	return 0;
diff --git a/sound/soc/mid-x86/sst_platform.h b/sound/soc/mid-x86/sst_platform.h
index d61c5d5..cacc906 100644
--- a/sound/soc/mid-x86/sst_platform.h
+++ b/sound/soc/mid-x86/sst_platform.h
@@ -124,6 +124,8 @@ struct compress_sst_ops {
 	int (*close) (unsigned int str_id);
 	int (*get_caps) (struct snd_compr_caps *caps);
 	int (*get_codec_caps) (struct snd_compr_codec_caps *codec);
+	int (*set_metadata) (unsigned int str_id,
+			struct snd_compr_metadata *mdata);
 
 };
 
diff --git a/sound/soc/mxs/mxs-pcm.c b/sound/soc/mxs/mxs-pcm.c
index 564b5b6..ebbef85 100644
--- a/sound/soc/mxs/mxs-pcm.c
+++ b/sound/soc/mxs/mxs-pcm.c
@@ -28,7 +28,6 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/dmaengine.h>
-#include <linux/fsl/mxs-dma.h>
 
 #include <sound/core.h>
 #include <sound/initval.h>
@@ -39,11 +38,6 @@
 
 #include "mxs-pcm.h"
 
-struct mxs_pcm_dma_data {
-	struct mxs_dma_data dma_data;
-	struct mxs_pcm_dma_params *dma_params;
-};
-
 static struct snd_pcm_hardware snd_mxs_hardware = {
 	.info			= SNDRV_PCM_INFO_MMAP |
 				  SNDRV_PCM_INFO_MMAP_VALID |
@@ -66,8 +60,7 @@ static struct snd_pcm_hardware snd_mxs_hardware = {
 
 static bool filter(struct dma_chan *chan, void *param)
 {
-	struct mxs_pcm_dma_data *pcm_dma_data = param;
-	struct mxs_pcm_dma_params *dma_params = pcm_dma_data->dma_params;
+	struct mxs_pcm_dma_params *dma_params = param;
 
 	if (!mxs_dma_is_apbx(chan))
 		return false;
@@ -75,7 +68,7 @@ static bool filter(struct dma_chan *chan, void *param)
 	if (chan->chan_id != dma_params->chan_num)
 		return false;
 
-	chan->private = &pcm_dma_data->dma_data;
+	chan->private = &dma_params->dma_data;
 
 	return true;
 }
@@ -91,37 +84,11 @@ static int snd_mxs_pcm_hw_params(struct snd_pcm_substream *substream,
 static int snd_mxs_open(struct snd_pcm_substream *substream)
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-	struct mxs_pcm_dma_data *pcm_dma_data;
-	int ret;
-
-	pcm_dma_data = kzalloc(sizeof(*pcm_dma_data), GFP_KERNEL);
-	if (pcm_dma_data == NULL)
-		return -ENOMEM;
-
-	pcm_dma_data->dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
-	pcm_dma_data->dma_data.chan_irq = pcm_dma_data->dma_params->chan_irq;
-
-	ret = snd_dmaengine_pcm_open(substream, filter, pcm_dma_data);
-	if (ret) {
-		kfree(pcm_dma_data);
-		return ret;
-	}
 
 	snd_soc_set_runtime_hwparams(substream, &snd_mxs_hardware);
 
-	snd_dmaengine_pcm_set_data(substream, pcm_dma_data);
-
-	return 0;
-}
-
-static int snd_mxs_close(struct snd_pcm_substream *substream)
-{
-	struct mxs_pcm_dma_data *pcm_dma_data = snd_dmaengine_pcm_get_data(substream);
-
-	snd_dmaengine_pcm_close(substream);
-	kfree(pcm_dma_data);
-
-	return 0;
+	return snd_dmaengine_pcm_open(substream, filter,
+		snd_soc_dai_get_dma_data(rtd->cpu_dai, substream));
 }
 
 static int snd_mxs_pcm_mmap(struct snd_pcm_substream *substream,
@@ -137,7 +104,7 @@ static int snd_mxs_pcm_mmap(struct snd_pcm_substream *substream,
 
 static struct snd_pcm_ops mxs_pcm_ops = {
 	.open		= snd_mxs_open,
-	.close		= snd_mxs_close,
+	.close		= snd_dmaengine_pcm_close,
 	.ioctl		= snd_pcm_lib_ioctl,
 	.hw_params	= snd_mxs_pcm_hw_params,
 	.trigger	= snd_dmaengine_pcm_trigger,
diff --git a/sound/soc/mxs/mxs-pcm.h b/sound/soc/mxs/mxs-pcm.h
index 35ba2ca..3aa918f 100644
--- a/sound/soc/mxs/mxs-pcm.h
+++ b/sound/soc/mxs/mxs-pcm.h
@@ -19,8 +19,10 @@
 #ifndef _MXS_PCM_H
 #define _MXS_PCM_H
 
+#include <linux/fsl/mxs-dma.h>
+
 struct mxs_pcm_dma_params {
-	int chan_irq;
+	struct mxs_dma_data dma_data;
 	int chan_num;
 };
 
diff --git a/sound/soc/mxs/mxs-saif.c b/sound/soc/mxs/mxs-saif.c
index 3a2aa1d..076595d 100644
--- a/sound/soc/mxs/mxs-saif.c
+++ b/sound/soc/mxs/mxs-saif.c
@@ -33,11 +33,12 @@
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
 #include <asm/mach-types.h>
-#include <mach/hardware.h>
-#include <mach/mxs.h>
 
 #include "mxs-saif.h"
 
+#define MXS_SET_ADDR	0x4
+#define MXS_CLR_ADDR	0x8
+
 static struct mxs_saif *mxs_saif[2];
 
 /*
@@ -627,6 +628,10 @@ static struct snd_soc_dai_driver mxs_saif_dai = {
 	.ops = &mxs_saif_dai_ops,
 };
 
+static const struct snd_soc_component_driver mxs_saif_component = {
+	.name		= "mxs-saif",
+};
+
 static irqreturn_t mxs_saif_irq(int irq, void *dev_id)
 {
 	struct mxs_saif *saif = dev_id;
@@ -753,9 +758,9 @@ static int mxs_saif_probe(struct platform_device *pdev)
 		return ret;
 	}
 
-	saif->dma_param.chan_irq = platform_get_irq(pdev, 1);
-	if (saif->dma_param.chan_irq < 0) {
-		ret = saif->dma_param.chan_irq;
+	saif->dma_param.dma_data.chan_irq = platform_get_irq(pdev, 1);
+	if (saif->dma_param.dma_data.chan_irq < 0) {
+		ret = saif->dma_param.dma_data.chan_irq;
 		dev_err(&pdev->dev, "failed to get dma irq resource: %d\n",
 			ret);
 		return ret;
@@ -763,7 +768,8 @@ static int mxs_saif_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, saif);
 
-	ret = snd_soc_register_dai(&pdev->dev, &mxs_saif_dai);
+	ret = snd_soc_register_component(&pdev->dev, &mxs_saif_component,
+					 &mxs_saif_dai, 1);
 	if (ret) {
 		dev_err(&pdev->dev, "register DAI failed\n");
 		return ret;
@@ -778,7 +784,7 @@ static int mxs_saif_probe(struct platform_device *pdev)
 	return 0;
 
 failed_pdev_alloc:
-	snd_soc_unregister_dai(&pdev->dev);
+	snd_soc_unregister_component(&pdev->dev);
 
 	return ret;
 }
@@ -786,7 +792,7 @@ failed_pdev_alloc:
 static int mxs_saif_remove(struct platform_device *pdev)
 {
 	mxs_pcm_platform_unregister(&pdev->dev);
-	snd_soc_unregister_dai(&pdev->dev);
+	snd_soc_unregister_component(&pdev->dev);
 
 	return 0;
 }
diff --git a/sound/soc/nuc900/nuc900-ac97.c b/sound/soc/nuc900/nuc900-ac97.c
index 0418467..fe3285c 100644
--- a/sound/soc/nuc900/nuc900-ac97.c
+++ b/sound/soc/nuc900/nuc900-ac97.c
@@ -314,6 +314,10 @@ static struct snd_soc_dai_driver nuc900_ac97_dai = {
 	.ops = &nuc900_ac97_dai_ops,
 };
 
+static const struct snd_soc_component_driver nuc900_ac97_component = {
+	.name		= "nuc900-ac97",
+};
+
 static int nuc900_ac97_drvprobe(struct platform_device *pdev)
 {
 	struct nuc900_audio *nuc900_audio;
@@ -361,7 +365,8 @@ static int nuc900_ac97_drvprobe(struct platform_device *pdev)
 
 	nuc900_ac97_data = nuc900_audio;
 
-	ret = snd_soc_register_dai(&pdev->dev, &nuc900_ac97_dai);
+	ret = snd_soc_register_component(&pdev->dev, &nuc900_ac97_component,
+					 &nuc900_ac97_dai, 1);
 	if (ret)
 		goto out3;
 
@@ -384,7 +389,7 @@ out0:
 
 static int nuc900_ac97_drvremove(struct platform_device *pdev)
 {
-	snd_soc_unregister_dai(&pdev->dev);
+	snd_soc_unregister_component(&pdev->dev);
 
 	clk_put(nuc900_ac97_data->clk);
 	iounmap(nuc900_ac97_data->mmio);
diff --git a/sound/soc/omap/am3517evm.c b/sound/soc/omap/am3517evm.c
index c1900b2..994dcf3 100644
--- a/sound/soc/omap/am3517evm.c
+++ b/sound/soc/omap/am3517evm.c
@@ -28,7 +28,6 @@
 #include <linux/platform_data/asoc-ti-mcbsp.h>
 
 #include "omap-mcbsp.h"
-#include "omap-pcm.h"
 
 #include "../codecs/tlv320aic23.h"
 
diff --git a/sound/soc/omap/ams-delta.c b/sound/soc/omap/ams-delta.c
index 2600447..6294464 100644
--- a/sound/soc/omap/ams-delta.c
+++ b/sound/soc/omap/ams-delta.c
@@ -36,7 +36,6 @@
 #include <linux/platform_data/asoc-ti-mcbsp.h>
 
 #include "omap-mcbsp.h"
-#include "omap-pcm.h"
 #include "../codecs/cx20442.h"
 
 
diff --git a/sound/soc/omap/mcbsp.c b/sound/soc/omap/mcbsp.c
index 285c836..eb68c7d 100644
--- a/sound/soc/omap/mcbsp.c
+++ b/sound/soc/omap/mcbsp.c
@@ -1018,9 +1018,10 @@ int omap_mcbsp_init(struct platform_device *pdev)
 		return -ENODEV;
 	}
 	/* RX DMA request number, and port address configuration */
-	mcbsp->dma_data[1].name = "Audio Capture";
-	mcbsp->dma_data[1].dma_req = res->start;
-	mcbsp->dma_data[1].port_addr = omap_mcbsp_dma_reg_params(mcbsp, 1);
+	mcbsp->dma_req[1] = res->start;
+	mcbsp->dma_data[1].filter_data = &mcbsp->dma_req[1];
+	mcbsp->dma_data[1].addr = omap_mcbsp_dma_reg_params(mcbsp, 1);
+	mcbsp->dma_data[1].maxburst = 4;
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx");
 	if (!res) {
@@ -1028,9 +1029,10 @@ int omap_mcbsp_init(struct platform_device *pdev)
 		return -ENODEV;
 	}
 	/* TX DMA request number, and port address configuration */
-	mcbsp->dma_data[0].name = "Audio Playback";
-	mcbsp->dma_data[0].dma_req = res->start;
-	mcbsp->dma_data[0].port_addr = omap_mcbsp_dma_reg_params(mcbsp, 0);
+	mcbsp->dma_req[0] = res->start;
+	mcbsp->dma_data[0].filter_data = &mcbsp->dma_req[0];
+	mcbsp->dma_data[0].addr = omap_mcbsp_dma_reg_params(mcbsp, 0);
+	mcbsp->dma_data[0].maxburst = 4;
 
 	mcbsp->fclk = clk_get(&pdev->dev, "fck");
 	if (IS_ERR(mcbsp->fclk)) {
diff --git a/sound/soc/omap/mcbsp.h b/sound/soc/omap/mcbsp.h
index f93e0b0..96d1b08 100644
--- a/sound/soc/omap/mcbsp.h
+++ b/sound/soc/omap/mcbsp.h
@@ -24,14 +24,14 @@
 #ifndef __ASOC_MCBSP_H
 #define __ASOC_MCBSP_H
 
-#include "omap-pcm.h"
-
 #ifdef CONFIG_ARCH_OMAP1
 #define mcbsp_omap1()	1
 #else
 #define mcbsp_omap1()	0
 #endif
 
+#include <sound/dmaengine_pcm.h>
+
 /* McBSP register numbers. Register address offset = num * reg_step */
 enum {
 	/* Common registers */
@@ -312,7 +312,8 @@ struct omap_mcbsp {
 	struct omap_mcbsp_platform_data *pdata;
 	struct omap_mcbsp_st_data *st_data;
 	struct omap_mcbsp_reg_cfg cfg_regs;
-	struct omap_pcm_dma_data dma_data[2];
+	struct snd_dmaengine_dai_dma_data dma_data[2];
+	unsigned int dma_req[2];
 	int dma_op_mode;
 	u16 max_tx_thres;
 	u16 max_rx_thres;
diff --git a/sound/soc/omap/n810.c b/sound/soc/omap/n810.c
index ee7cd53..5e8d640 100644
--- a/sound/soc/omap/n810.c
+++ b/sound/soc/omap/n810.c
@@ -34,7 +34,6 @@
 #include <linux/platform_data/asoc-ti-mcbsp.h>
 
 #include "omap-mcbsp.h"
-#include "omap-pcm.h"
 
 #define N810_HEADSET_AMP_GPIO	10
 #define N810_SPEAKER_AMP_GPIO	101
diff --git a/sound/soc/omap/omap-abe-twl6040.c b/sound/soc/omap/omap-abe-twl6040.c
index e7d93fa..70cd5c7 100644
--- a/sound/soc/omap/omap-abe-twl6040.c
+++ b/sound/soc/omap/omap-abe-twl6040.c
@@ -34,7 +34,6 @@
 
 #include "omap-dmic.h"
 #include "omap-mcpdm.h"
-#include "omap-pcm.h"
 #include "../codecs/twl6040.h"
 
 struct abe_twl6040 {
diff --git a/sound/soc/omap/omap-dmic.c b/sound/soc/omap/omap-dmic.c
index ba49ccd..2ad0370 100644
--- a/sound/soc/omap/omap-dmic.c
+++ b/sound/soc/omap/omap-dmic.c
@@ -39,8 +39,8 @@
 #include <sound/pcm_params.h>
 #include <sound/initval.h>
 #include <sound/soc.h>
+#include <sound/dmaengine_pcm.h>
 
-#include "omap-pcm.h"
 #include "omap-dmic.h"
 
 struct omap_dmic {
@@ -55,13 +55,9 @@ struct omap_dmic {
 	u32 ch_enabled;
 	bool active;
 	struct mutex mutex;
-};
 
-/*
- * Stream DMA parameters
- */
-static struct omap_pcm_dma_data omap_dmic_dai_dma_params = {
-	.name		= "DMIC capture",
+	struct snd_dmaengine_dai_dma_data dma_data;
+	unsigned int dma_req;
 };
 
 static inline void omap_dmic_write(struct omap_dmic *dmic, u16 reg, u32 val)
@@ -118,7 +114,7 @@ static int omap_dmic_dai_startup(struct snd_pcm_substream *substream,
 
 	mutex_unlock(&dmic->mutex);
 
-	snd_soc_dai_set_dma_data(dai, substream, &omap_dmic_dai_dma_params);
+	snd_soc_dai_set_dma_data(dai, substream, &dmic->dma_data);
 	return ret;
 }
 
@@ -203,7 +199,7 @@ static int omap_dmic_dai_hw_params(struct snd_pcm_substream *substream,
 				    struct snd_soc_dai *dai)
 {
 	struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
-	struct omap_pcm_dma_data *dma_data;
+	struct snd_dmaengine_dai_dma_data *dma_data;
 	int channels;
 
 	dmic->clk_div = omap_dmic_select_divider(dmic, params_rate(params));
@@ -230,7 +226,7 @@ static int omap_dmic_dai_hw_params(struct snd_pcm_substream *substream,
 
 	/* packet size is threshold * channels */
 	dma_data = snd_soc_dai_get_dma_data(dai, substream);
-	dma_data->packet_size = dmic->threshold * channels;
+	dma_data->maxburst = dmic->threshold * channels;
 
 	return 0;
 }
@@ -448,6 +444,10 @@ static struct snd_soc_dai_driver omap_dmic_dai = {
 	.ops = &omap_dmic_dai_ops,
 };
 
+static const struct snd_soc_component_driver omap_dmic_component = {
+	.name		= "omap-dmic",
+};
+
 static int asoc_dmic_probe(struct platform_device *pdev)
 {
 	struct omap_dmic *dmic;
@@ -476,7 +476,7 @@ static int asoc_dmic_probe(struct platform_device *pdev)
 		ret = -ENODEV;
 		goto err_put_clk;
 	}
-	omap_dmic_dai_dma_params.port_addr = res->start + OMAP_DMIC_DATA_REG;
+	dmic->dma_data.addr = res->start + OMAP_DMIC_DATA_REG;
 
 	res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
 	if (!res) {
@@ -484,7 +484,9 @@ static int asoc_dmic_probe(struct platform_device *pdev)
 		ret = -ENODEV;
 		goto err_put_clk;
 	}
-	omap_dmic_dai_dma_params.dma_req = res->start;
+
+	dmic->dma_req = res->start;
+	dmic->dma_data.filter_data = &dmic->dma_req;
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu");
 	if (!res) {
@@ -493,21 +495,12 @@ static int asoc_dmic_probe(struct platform_device *pdev)
 		goto err_put_clk;
 	}
 
-	if (!devm_request_mem_region(&pdev->dev, res->start,
-				     resource_size(res), pdev->name)) {
-		dev_err(dmic->dev, "memory region already claimed\n");
-		ret = -ENODEV;
-		goto err_put_clk;
-	}
-
-	dmic->io_base = devm_ioremap(&pdev->dev, res->start,
-				     resource_size(res));
-	if (!dmic->io_base) {
-		ret = -ENOMEM;
-		goto err_put_clk;
-	}
+	dmic->io_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(dmic->io_base))
+		return PTR_ERR(dmic->io_base);
 
-	ret = snd_soc_register_dai(&pdev->dev, &omap_dmic_dai);
+	ret = snd_soc_register_component(&pdev->dev, &omap_dmic_component,
+					 &omap_dmic_dai, 1);
 	if (ret)
 		goto err_put_clk;
 
@@ -522,7 +515,7 @@ static int asoc_dmic_remove(struct platform_device *pdev)
 {
 	struct omap_dmic *dmic = platform_get_drvdata(pdev);
 
-	snd_soc_unregister_dai(&pdev->dev);
+	snd_soc_unregister_component(&pdev->dev);
 	clk_put(dmic->fclk);
 
 	return 0;
diff --git a/sound/soc/omap/omap-hdmi.c b/sound/soc/omap/omap-hdmi.c
index 32fa840..ced3b88 100644
--- a/sound/soc/omap/omap-hdmi.c
+++ b/sound/soc/omap/omap-hdmi.c
@@ -32,15 +32,16 @@
 #include <sound/soc.h>
 #include <sound/asound.h>
 #include <sound/asoundef.h>
+#include <sound/dmaengine_pcm.h>
 #include <video/omapdss.h>
 
-#include "omap-pcm.h"
 #include "omap-hdmi.h"
 
 #define DRV_NAME "omap-hdmi-audio-dai"
 
 struct hdmi_priv {
-	struct omap_pcm_dma_data dma_params;
+	struct snd_dmaengine_dai_dma_data dma_data;
+	unsigned int dma_req;
 	struct omap_dss_audio dss_audio;
 	struct snd_aes_iec958 iec;
 	struct snd_cea_861_aud_if cea;
@@ -68,7 +69,7 @@ static int omap_hdmi_dai_startup(struct snd_pcm_substream *substream,
 		return -ENODEV;
 	}
 
-	snd_soc_dai_set_dma_data(dai, substream, &priv->dma_params);
+	snd_soc_dai_set_dma_data(dai, substream, &priv->dma_data);
 
 	return 0;
 }
@@ -88,25 +89,20 @@ static int omap_hdmi_dai_hw_params(struct snd_pcm_substream *substream,
 	struct hdmi_priv *priv = snd_soc_dai_get_drvdata(dai);
 	struct snd_aes_iec958 *iec = &priv->iec;
 	struct snd_cea_861_aud_if *cea = &priv->cea;
-	struct omap_pcm_dma_data *dma_data;
 	int err = 0;
 
-	dma_data = snd_soc_dai_get_dma_data(dai, substream);
-
 	switch (params_format(params)) {
 	case SNDRV_PCM_FORMAT_S16_LE:
-		dma_data->packet_size = 16;
+		priv->dma_data.maxburst = 16;
 		break;
 	case SNDRV_PCM_FORMAT_S24_LE:
-		dma_data->packet_size = 32;
+		priv->dma_data.maxburst = 32;
 		break;
 	default:
 		dev_err(dai->dev, "format not supported!\n");
 		return -EINVAL;
 	}
 
-	dma_data->data_type = 32;
-
 	/*
 	 * fill the IEC-60958 channel status word
 	 */
@@ -264,6 +260,10 @@ static struct snd_soc_dai_driver omap_hdmi_dai = {
 	.ops = &omap_hdmi_dai_ops,
 };
 
+static const struct snd_soc_component_driver omap_hdmi_component = {
+	.name		= DRV_NAME,
+};
+
 static int omap_hdmi_probe(struct platform_device *pdev)
 {
 	int ret;
@@ -283,8 +283,7 @@ static int omap_hdmi_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
-	hdmi_data->dma_params.port_addr =  hdmi_rsrc->start
-		+ OMAP_HDMI_AUDIO_DMA_PORT;
+	hdmi_data->dma_data.addr = hdmi_rsrc->start + OMAP_HDMI_AUDIO_DMA_PORT;
 
 	hdmi_rsrc = platform_get_resource(pdev, IORESOURCE_DMA, 0);
 	if (!hdmi_rsrc) {
@@ -292,8 +291,9 @@ static int omap_hdmi_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
-	hdmi_data->dma_params.dma_req =  hdmi_rsrc->start;
-	hdmi_data->dma_params.name = "HDMI playback";
+	hdmi_data->dma_req = hdmi_rsrc->start;
+	hdmi_data->dma_data.filter_data = &hdmi_data->dma_req;
+	hdmi_data->dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
 
 	/*
 	 * TODO: We assume that there is only one DSS HDMI device. Future
@@ -321,7 +321,8 @@ static int omap_hdmi_probe(struct platform_device *pdev)
 	}
 
 	dev_set_drvdata(&pdev->dev, hdmi_data);
-	ret = snd_soc_register_dai(&pdev->dev, &omap_hdmi_dai);
+	ret = snd_soc_register_component(&pdev->dev, &omap_hdmi_component,
+					 &omap_hdmi_dai, 1);
 
 	return ret;
 }
@@ -330,7 +331,7 @@ static int omap_hdmi_remove(struct platform_device *pdev)
 {
 	struct hdmi_priv *hdmi_data = dev_get_drvdata(&pdev->dev);
 
-	snd_soc_unregister_dai(&pdev->dev);
+	snd_soc_unregister_component(&pdev->dev);
 
 	if (hdmi_data == NULL) {
 		dev_err(&pdev->dev, "cannot obtain HDMi data\n");
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
index 8d2defd..eadbfb6 100644
--- a/sound/soc/omap/omap-mcbsp.c
+++ b/sound/soc/omap/omap-mcbsp.c
@@ -33,11 +33,11 @@
 #include <sound/pcm_params.h>
 #include <sound/initval.h>
 #include <sound/soc.h>
+#include <sound/dmaengine_pcm.h>
 
 #include <linux/platform_data/asoc-ti-mcbsp.h>
 #include "mcbsp.h"
 #include "omap-mcbsp.h"
-#include "omap-pcm.h"
 
 #define OMAP_MCBSP_RATES	(SNDRV_PCM_RATE_8000_96000)
 
@@ -62,24 +62,22 @@ enum {
  * Stream DMA parameters. DMA request line and port address are set runtime
  * since they are different between OMAP1 and later OMAPs
  */
-static void omap_mcbsp_set_threshold(struct snd_pcm_substream *substream)
+static void omap_mcbsp_set_threshold(struct snd_pcm_substream *substream,
+		unsigned int packet_size)
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 	struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
-	struct omap_pcm_dma_data *dma_data;
 	int words;
 
-	dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
-
 	/*
 	 * Configure McBSP threshold based on either:
 	 * packet_size, when the sDMA is in packet mode, or based on the
 	 * period size in THRESHOLD mode, otherwise use McBSP threshold = 1
 	 * for mono streams.
 	 */
-	if (dma_data->packet_size)
-		words = dma_data->packet_size;
+	if (packet_size)
+		words = packet_size;
 	else
 		words = 1;
 
@@ -226,7 +224,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
 {
 	struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
 	struct omap_mcbsp_reg_cfg *regs = &mcbsp->cfg_regs;
-	struct omap_pcm_dma_data *dma_data;
+	struct snd_dmaengine_dai_dma_data *dma_data;
 	int wlen, channels, wpf;
 	int pkt_size = 0;
 	unsigned int format, div, framesize, master;
@@ -245,7 +243,6 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
 		return -EINVAL;
 	}
 	if (mcbsp->pdata->buffer_size) {
-		dma_data->set_threshold = omap_mcbsp_set_threshold;
 		if (mcbsp->dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) {
 			int period_words, max_thrsh;
 			int divider = 0;
@@ -276,9 +273,10 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
 			/* Use packet mode for non mono streams */
 			pkt_size = channels;
 		}
+		omap_mcbsp_set_threshold(substream, pkt_size);
 	}
 
-	dma_data->packet_size = pkt_size;
+	dma_data->maxburst = pkt_size;
 
 	if (mcbsp->configured) {
 		/* McBSP already configured by another stream */
@@ -586,6 +584,10 @@ static struct snd_soc_dai_driver omap_mcbsp_dai = {
 	.ops = &mcbsp_dai_ops,
 };
 
+static const struct snd_soc_component_driver omap_mcbsp_component = {
+	.name		= "omap-mcbsp",
+};
+
 static int omap_mcbsp_st_info_volsw(struct snd_kcontrol *kcontrol,
 			struct snd_ctl_elem_info *uinfo)
 {
@@ -793,7 +795,8 @@ static int asoc_mcbsp_probe(struct platform_device *pdev)
 
 	ret = omap_mcbsp_init(pdev);
 	if (!ret)
-		return snd_soc_register_dai(&pdev->dev, &omap_mcbsp_dai);
+		return snd_soc_register_component(&pdev->dev, &omap_mcbsp_component,
+						  &omap_mcbsp_dai, 1);
 
 	return ret;
 }
@@ -802,7 +805,7 @@ static int asoc_mcbsp_remove(struct platform_device *pdev)
 {
 	struct omap_mcbsp *mcbsp = platform_get_drvdata(pdev);
 
-	snd_soc_unregister_dai(&pdev->dev);
+	snd_soc_unregister_component(&pdev->dev);
 
 	if (mcbsp->pdata->ops && mcbsp->pdata->ops->free)
 		mcbsp->pdata->ops->free(mcbsp->id);
diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c
index 5ca11bd..eb05c7e 100644
--- a/sound/soc/omap/omap-mcpdm.c
+++ b/sound/soc/omap/omap-mcpdm.c
@@ -39,11 +39,14 @@
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
+#include <sound/dmaengine_pcm.h>
 
 #include "omap-mcpdm.h"
-#include "omap-pcm.h"
 
-#define OMAP44XX_MCPDM_L3_BASE		0x49032000
+struct mcpdm_link_config {
+	u32 link_mask; /* channel mask for the direction */
+	u32 threshold; /* FIFO threshold */
+};
 
 struct omap_mcpdm {
 	struct device *dev;
@@ -53,29 +56,22 @@ struct omap_mcpdm {
 
 	struct mutex mutex;
 
-	/* channel data */
-	u32 dn_channels;
-	u32 up_channels;
-
-	/* McPDM FIFO thresholds */
-	u32 dn_threshold;
-	u32 up_threshold;
+	/* Playback/Capture configuration */
+	struct mcpdm_link_config config[2];
 
 	/* McPDM dn offsets for rx1, and 2 channels */
 	u32 dn_rx_offset;
+
+	/* McPDM needs to be restarted due to runtime reconfiguration */
+	bool restart;
+
+	struct snd_dmaengine_dai_dma_data dma_data[2];
+	unsigned int dma_req[2];
 };
 
 /*
  * Stream DMA parameters
  */
-static struct omap_pcm_dma_data omap_mcpdm_dai_dma_params[] = {
-	{
-		.name = "Audio playback",
-	},
-	{
-		.name = "Audio capture",
-	},
-};
 
 static inline void omap_mcpdm_write(struct omap_mcpdm *mcpdm, u16 reg, u32 val)
 {
@@ -130,11 +126,12 @@ static void omap_mcpdm_reg_dump(struct omap_mcpdm *mcpdm) {}
 static void omap_mcpdm_start(struct omap_mcpdm *mcpdm)
 {
 	u32 ctrl = omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL);
+	u32 link_mask = mcpdm->config[0].link_mask | mcpdm->config[1].link_mask;
 
 	ctrl |= (MCPDM_SW_DN_RST | MCPDM_SW_UP_RST);
 	omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl);
 
-	ctrl |= mcpdm->dn_channels | mcpdm->up_channels;
+	ctrl |= link_mask;
 	omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl);
 
 	ctrl &= ~(MCPDM_SW_DN_RST | MCPDM_SW_UP_RST);
@@ -148,11 +145,12 @@ static void omap_mcpdm_start(struct omap_mcpdm *mcpdm)
 static void omap_mcpdm_stop(struct omap_mcpdm *mcpdm)
 {
 	u32 ctrl = omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL);
+	u32 link_mask = MCPDM_PDM_DN_MASK | MCPDM_PDM_UP_MASK;
 
 	ctrl |= (MCPDM_SW_DN_RST | MCPDM_SW_UP_RST);
 	omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl);
 
-	ctrl &= ~(mcpdm->dn_channels | mcpdm->up_channels);
+	ctrl &= ~(link_mask);
 	omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl);
 
 	ctrl &= ~(MCPDM_SW_DN_RST | MCPDM_SW_UP_RST);
@@ -188,8 +186,10 @@ static void omap_mcpdm_open_streams(struct omap_mcpdm *mcpdm)
 		omap_mcpdm_write(mcpdm, MCPDM_REG_DN_OFFSET, dn_offset);
 	}
 
-	omap_mcpdm_write(mcpdm, MCPDM_REG_FIFO_CTRL_DN, mcpdm->dn_threshold);
-	omap_mcpdm_write(mcpdm, MCPDM_REG_FIFO_CTRL_UP, mcpdm->up_threshold);
+	omap_mcpdm_write(mcpdm, MCPDM_REG_FIFO_CTRL_DN,
+			 mcpdm->config[SNDRV_PCM_STREAM_PLAYBACK].threshold);
+	omap_mcpdm_write(mcpdm, MCPDM_REG_FIFO_CTRL_UP,
+			 mcpdm->config[SNDRV_PCM_STREAM_CAPTURE].threshold);
 
 	omap_mcpdm_write(mcpdm, MCPDM_REG_DMAENABLE_SET,
 			MCPDM_DMA_DN_ENABLE | MCPDM_DMA_UP_ENABLE);
@@ -267,7 +267,7 @@ static int omap_mcpdm_dai_startup(struct snd_pcm_substream *substream,
 	mutex_unlock(&mcpdm->mutex);
 
 	snd_soc_dai_set_dma_data(dai, substream,
-				 &omap_mcpdm_dai_dma_params[substream->stream]);
+				 &mcpdm->dma_data[substream->stream]);
 
 	return 0;
 }
@@ -283,6 +283,8 @@ static void omap_mcpdm_dai_shutdown(struct snd_pcm_substream *substream,
 		if (omap_mcpdm_active(mcpdm)) {
 			omap_mcpdm_stop(mcpdm);
 			omap_mcpdm_close_streams(mcpdm);
+			mcpdm->config[0].link_mask = 0;
+			mcpdm->config[1].link_mask = 0;
 		}
 	}
 
@@ -295,7 +297,8 @@ static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream,
 {
 	struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
 	int stream = substream->stream;
-	struct omap_pcm_dma_data *dma_data;
+	struct snd_dmaengine_dai_dma_data *dma_data;
+	u32 threshold;
 	int channels;
 	int link_mask = 0;
 
@@ -325,16 +328,32 @@ static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream,
 
 	dma_data = snd_soc_dai_get_dma_data(dai, substream);
 
+	threshold = mcpdm->config[stream].threshold;
 	/* Configure McPDM channels, and DMA packet size */
 	if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
-		mcpdm->dn_channels = link_mask << 3;
-		dma_data->packet_size =
-			(MCPDM_DN_THRES_MAX - mcpdm->dn_threshold) * channels;
+		link_mask <<= 3;
+
+		/* If capture is not running assume a stereo stream to come */
+		if (!mcpdm->config[!stream].link_mask)
+			mcpdm->config[!stream].link_mask = 0x3;
+
+		dma_data->maxburst =
+				(MCPDM_DN_THRES_MAX - threshold) * channels;
 	} else {
-		mcpdm->up_channels = link_mask << 0;
-		dma_data->packet_size = mcpdm->up_threshold * channels;
+		/* If playback is not running assume a stereo stream to come */
+		if (!mcpdm->config[!stream].link_mask)
+			mcpdm->config[!stream].link_mask = (0x3 << 3);
+
+		dma_data->maxburst = threshold * channels;
 	}
 
+	/* Check if we need to restart McPDM with this stream */
+	if (mcpdm->config[stream].link_mask &&
+	    mcpdm->config[stream].link_mask != link_mask)
+		mcpdm->restart = true;
+
+	mcpdm->config[stream].link_mask = link_mask;
+
 	return 0;
 }
 
@@ -346,6 +365,11 @@ static int omap_mcpdm_prepare(struct snd_pcm_substream *substream,
 	if (!omap_mcpdm_active(mcpdm)) {
 		omap_mcpdm_start(mcpdm);
 		omap_mcpdm_reg_dump(mcpdm);
+	} else if (mcpdm->restart) {
+		omap_mcpdm_stop(mcpdm);
+		omap_mcpdm_start(mcpdm);
+		mcpdm->restart = false;
+		omap_mcpdm_reg_dump(mcpdm);
 	}
 
 	return 0;
@@ -369,7 +393,7 @@ static int omap_mcpdm_probe(struct snd_soc_dai *dai)
 	pm_runtime_get_sync(mcpdm->dev);
 	omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, 0x00);
 
-	ret = request_irq(mcpdm->irq, omap_mcpdm_irq_handler,
+	ret = devm_request_irq(mcpdm->dev, mcpdm->irq, omap_mcpdm_irq_handler,
 				0, "McPDM", (void *)mcpdm);
 
 	pm_runtime_put_sync(mcpdm->dev);
@@ -380,8 +404,9 @@ static int omap_mcpdm_probe(struct snd_soc_dai *dai)
 	}
 
 	/* Configure McPDM threshold values */
-	mcpdm->dn_threshold = 2;
-	mcpdm->up_threshold = MCPDM_UP_THRES_MAX - 3;
+	mcpdm->config[SNDRV_PCM_STREAM_PLAYBACK].threshold = 2;
+	mcpdm->config[SNDRV_PCM_STREAM_CAPTURE].threshold =
+							MCPDM_UP_THRES_MAX - 3;
 	return ret;
 }
 
@@ -389,7 +414,6 @@ static int omap_mcpdm_remove(struct snd_soc_dai *dai)
 {
 	struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
 
-	free_irq(mcpdm->irq, (void *)mcpdm);
 	pm_runtime_disable(mcpdm->dev);
 
 	return 0;
@@ -420,6 +444,10 @@ static struct snd_soc_dai_driver omap_mcpdm_dai = {
 	.ops = &omap_mcpdm_dai_ops,
 };
 
+static const struct snd_soc_component_driver omap_mcpdm_component = {
+	.name		= "omap-mcpdm",
+};
+
 void omap_mcpdm_configure_dn_offsets(struct snd_soc_pcm_runtime *rtd,
 				    u8 rx1, u8 rx2)
 {
@@ -446,33 +474,30 @@ static int asoc_mcpdm_probe(struct platform_device *pdev)
 	if (res == NULL)
 		return -ENOMEM;
 
-	omap_mcpdm_dai_dma_params[0].port_addr = res->start + MCPDM_REG_DN_DATA;
-	omap_mcpdm_dai_dma_params[1].port_addr = res->start + MCPDM_REG_UP_DATA;
+	mcpdm->dma_data[0].addr = res->start + MCPDM_REG_DN_DATA;
+	mcpdm->dma_data[1].addr = res->start + MCPDM_REG_UP_DATA;
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "dn_link");
 	if (!res)
 		return -ENODEV;
 
-	omap_mcpdm_dai_dma_params[0].dma_req = res->start;
+	mcpdm->dma_req[0] = res->start;
+	mcpdm->dma_data[0].filter_data = &mcpdm->dma_req[0];
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "up_link");
 	if (!res)
 		return -ENODEV;
 
-	omap_mcpdm_dai_dma_params[1].dma_req = res->start;
+	mcpdm->dma_req[1] = res->start;
+	mcpdm->dma_data[1].filter_data = &mcpdm->dma_req[1];
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu");
 	if (res == NULL)
 		return -ENOMEM;
 
-	if (!devm_request_mem_region(&pdev->dev, res->start,
-				     resource_size(res), "McPDM"))
-		return -EBUSY;
-
-	mcpdm->io_base = devm_ioremap(&pdev->dev, res->start,
-				      resource_size(res));
-	if (!mcpdm->io_base)
-		return -ENOMEM;
+	mcpdm->io_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(mcpdm->io_base))
+		return PTR_ERR(mcpdm->io_base);
 
 	mcpdm->irq = platform_get_irq(pdev, 0);
 	if (mcpdm->irq < 0)
@@ -480,12 +505,13 @@ static int asoc_mcpdm_probe(struct platform_device *pdev)
 
 	mcpdm->dev = &pdev->dev;
 
-	return snd_soc_register_dai(&pdev->dev, &omap_mcpdm_dai);
+	return snd_soc_register_component(&pdev->dev, &omap_mcpdm_component,
+					  &omap_mcpdm_dai, 1);
 }
 
 static int asoc_mcpdm_remove(struct platform_device *pdev)
 {
-	snd_soc_unregister_dai(&pdev->dev);
+	snd_soc_unregister_component(&pdev->dev);
 	return 0;
 }
 
diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c
index c722c2e..c8e272f 100644
--- a/sound/soc/omap/omap-pcm.c
+++ b/sound/soc/omap/omap-pcm.c
@@ -32,8 +32,6 @@
 #include <sound/dmaengine_pcm.h>
 #include <sound/soc.h>
 
-#include "omap-pcm.h"
-
 #ifdef CONFIG_ARCH_OMAP1
 #define pcm_omap1510()	cpu_is_omap1510()
 #else
@@ -56,25 +54,6 @@ static const struct snd_pcm_hardware omap_pcm_hardware = {
 	.buffer_bytes_max	= 128 * 1024,
 };
 
-static int omap_pcm_get_dma_buswidth(int num_bits)
-{
-	int buswidth;
-
-	switch (num_bits) {
-	case 16:
-		buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;
-		break;
-	case 32:
-		buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES;
-		break;
-	default:
-		buswidth = -EINVAL;
-		break;
-	}
-	return buswidth;
-}
-
-
 /* this may get called several times by oss emulation */
 static int omap_pcm_hw_params(struct snd_pcm_substream *substream,
 			      struct snd_pcm_hw_params *params)
@@ -105,20 +84,9 @@ static int omap_pcm_hw_params(struct snd_pcm_substream *substream,
 	if (err)
 		return err;
 
-	/* Override the *_dma addr_width if requested by the DAI driver */
-	if (dma_data->data_type) {
-		int buswidth = omap_pcm_get_dma_buswidth(dma_data->data_type);
-
-		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-			config.dst_addr_width = buswidth;
-		else
-			config.src_addr_width = buswidth;
-	}
-
-	config.src_addr = dma_data->port_addr;
-	config.dst_addr = dma_data->port_addr;
-	config.src_maxburst = dma_data->packet_size;
-	config.dst_maxburst = dma_data->packet_size;
+	snd_dmaengine_pcm_set_config_from_dai_data(substream,
+			snd_soc_dai_get_dma_data(rtd->cpu_dai, substream),
+			&config);
 
 	return dmaengine_slave_config(chan, &config);
 }
@@ -129,37 +97,6 @@ static int omap_pcm_hw_free(struct snd_pcm_substream *substream)
 	return 0;
 }
 
-static int omap_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
-{
-	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-	struct omap_pcm_dma_data *dma_data;
-	int ret = 0;
-
-	dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
-
-	switch (cmd) {
-	case SNDRV_PCM_TRIGGER_START:
-	case SNDRV_PCM_TRIGGER_RESUME:
-	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-		/* Configure McBSP internal buffer usage */
-		if (dma_data->set_threshold)
-			dma_data->set_threshold(substream);
-		break;
-
-	case SNDRV_PCM_TRIGGER_STOP:
-	case SNDRV_PCM_TRIGGER_SUSPEND:
-	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-		break;
-	default:
-		ret = -EINVAL;
-	}
-
-	if (ret == 0)
-		ret = snd_dmaengine_pcm_trigger(substream, cmd);
-
-	return ret;
-}
-
 static snd_pcm_uframes_t omap_pcm_pointer(struct snd_pcm_substream *substream)
 {
 	snd_pcm_uframes_t offset;
@@ -175,20 +112,14 @@ static snd_pcm_uframes_t omap_pcm_pointer(struct snd_pcm_substream *substream)
 static int omap_pcm_open(struct snd_pcm_substream *substream)
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-	struct omap_pcm_dma_data *dma_data;
+	struct snd_dmaengine_dai_dma_data *dma_data;
 
 	snd_soc_set_runtime_hwparams(substream, &omap_pcm_hardware);
 
 	dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
 
 	return snd_dmaengine_pcm_open(substream, omap_dma_filter_fn,
-				      &dma_data->dma_req);
-}
-
-static int omap_pcm_close(struct snd_pcm_substream *substream)
-{
-	snd_dmaengine_pcm_close(substream);
-	return 0;
+				      dma_data->filter_data);
 }
 
 static int omap_pcm_mmap(struct snd_pcm_substream *substream,
@@ -204,11 +135,11 @@ static int omap_pcm_mmap(struct snd_pcm_substream *substream,
 
 static struct snd_pcm_ops omap_pcm_ops = {
 	.open		= omap_pcm_open,
-	.close		= omap_pcm_close,
+	.close		= snd_dmaengine_pcm_close,
 	.ioctl		= snd_pcm_lib_ioctl,
 	.hw_params	= omap_pcm_hw_params,
 	.hw_free	= omap_pcm_hw_free,
-	.trigger	= omap_pcm_trigger,
+	.trigger	= snd_dmaengine_pcm_trigger,
 	.pointer	= omap_pcm_pointer,
 	.mmap		= omap_pcm_mmap,
 };
diff --git a/sound/soc/omap/omap-pcm.h b/sound/soc/omap/omap-pcm.h
deleted file mode 100644
index cabe74c..0000000
--- a/sound/soc/omap/omap-pcm.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * omap-pcm.h
- *
- * Copyright (C) 2008 Nokia Corporation
- *
- * Contact: Jarkko Nikula <jarkko.nikula@bitmer.com>
- *          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
- *
- */
-
-#ifndef __OMAP_PCM_H__
-#define __OMAP_PCM_H__
-
-struct snd_pcm_substream;
-
-struct omap_pcm_dma_data {
-	char		*name;		/* stream identifier */
-	int		dma_req;	/* DMA request line */
-	unsigned long	port_addr;	/* transmit/receive register */
-	void (*set_threshold)(struct snd_pcm_substream *substream);
-	int		data_type;	/* 8, 16, 32 (bits) or 0 to let omap-pcm
-					 * to decide the sDMA data type */
-	int		packet_size;	/* packet size only in PACKET mode */
-};
-
-#endif
diff --git a/sound/soc/omap/omap-twl4030.c b/sound/soc/omap/omap-twl4030.c
index fd98509..2a9324f 100644
--- a/sound/soc/omap/omap-twl4030.c
+++ b/sound/soc/omap/omap-twl4030.c
@@ -43,7 +43,6 @@
 #include <sound/jack.h>
 
 #include "omap-mcbsp.h"
-#include "omap-pcm.h"
 
 struct omap_twl4030 {
 	int jack_detect;	/* board can detect jack events */
diff --git a/sound/soc/omap/omap3pandora.c b/sound/soc/omap/omap3pandora.c
index 805512f..cf604a2 100644
--- a/sound/soc/omap/omap3pandora.c
+++ b/sound/soc/omap/omap3pandora.c
@@ -34,7 +34,6 @@
 #include <linux/platform_data/asoc-ti-mcbsp.h>
 
 #include "omap-mcbsp.h"
-#include "omap-pcm.h"
 
 #define OMAP3_PANDORA_DAC_POWER_GPIO	118
 #define OMAP3_PANDORA_AMP_POWER_GPIO	14
@@ -80,12 +79,18 @@ static int omap3pandora_hw_params(struct snd_pcm_substream *substream,
 static int omap3pandora_dac_event(struct snd_soc_dapm_widget *w,
 	struct snd_kcontrol *k, int event)
 {
+	int ret;
+
 	/*
 	 * The PCM1773 DAC datasheet requires 1ms delay between switching
 	 * VCC power on/off and /PD pin high/low
 	 */
 	if (SND_SOC_DAPM_EVENT_ON(event)) {
-		regulator_enable(omap3pandora_dac_reg);
+		ret = regulator_enable(omap3pandora_dac_reg);
+		if (ret) {
+			dev_err(w->dapm->dev, "Failed to power DAC: %d\n", ret);
+			return ret;
+		}
 		mdelay(1);
 		gpio_set_value(OMAP3_PANDORA_DAC_POWER_GPIO, 1);
 	} else {
diff --git a/sound/soc/omap/osk5912.c b/sound/soc/omap/osk5912.c
index 06ef8d6..d03e57d 100644
--- a/sound/soc/omap/osk5912.c
+++ b/sound/soc/omap/osk5912.c
@@ -33,7 +33,6 @@
 #include <linux/platform_data/asoc-ti-mcbsp.h>
 
 #include "omap-mcbsp.h"
-#include "omap-pcm.h"
 #include "../codecs/tlv320aic23.h"
 
 #define CODEC_CLOCK 	12000000
diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c
index 3cd5257..249cd23 100644
--- a/sound/soc/omap/rx51.c
+++ b/sound/soc/omap/rx51.c
@@ -37,7 +37,6 @@
 #include <asm/mach-types.h>
 
 #include "omap-mcbsp.h"
-#include "omap-pcm.h"
 
 #define RX51_TVOUT_SEL_GPIO		40
 #define RX51_JACK_DETECT_GPIO		177
diff --git a/sound/soc/pxa/mmp-pcm.c b/sound/soc/pxa/mmp-pcm.c
index 190eb0b..6c39802 100644
--- a/sound/soc/pxa/mmp-pcm.c
+++ b/sound/soc/pxa/mmp-pcm.c
@@ -118,9 +118,8 @@ static int mmp_pcm_open(struct snd_pcm_substream *substream)
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct platform_device *pdev = to_platform_device(rtd->platform->dev);
 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-	struct mmp_dma_data *dma_data;
+	struct mmp_dma_data dma_data;
 	struct resource *r;
-	int ret;
 
 	r = platform_get_resource(pdev, IORESOURCE_DMA, substream->stream);
 	if (!r)
@@ -128,33 +127,11 @@ static int mmp_pcm_open(struct snd_pcm_substream *substream)
 
 	snd_soc_set_runtime_hwparams(substream,
 				&mmp_pcm_hardware[substream->stream]);
-	dma_data = devm_kzalloc(&pdev->dev,
-			sizeof(struct mmp_dma_data), GFP_KERNEL);
-	if (dma_data == NULL)
-		return -ENOMEM;
 
-	dma_data->dma_res = r;
-	dma_data->ssp_id = cpu_dai->id;
+	dma_data.dma_res = r;
+	dma_data.ssp_id = cpu_dai->id;
 
-	ret = snd_dmaengine_pcm_open(substream, filter, dma_data);
-	if (ret) {
-		devm_kfree(&pdev->dev, dma_data);
-		return ret;
-	}
-
-	snd_dmaengine_pcm_set_data(substream, dma_data);
-	return 0;
-}
-
-static int mmp_pcm_close(struct snd_pcm_substream *substream)
-{
-	struct mmp_dma_data *dma_data = snd_dmaengine_pcm_get_data(substream);
-	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-	struct platform_device *pdev = to_platform_device(rtd->platform->dev);
-
-	snd_dmaengine_pcm_close(substream);
-	devm_kfree(&pdev->dev, dma_data);
-	return 0;
+	return snd_dmaengine_pcm_open(substream, filter, &dma_data);
 }
 
 static int mmp_pcm_mmap(struct snd_pcm_substream *substream,
@@ -171,7 +148,7 @@ static int mmp_pcm_mmap(struct snd_pcm_substream *substream,
 
 struct snd_pcm_ops mmp_pcm_ops = {
 	.open		= mmp_pcm_open,
-	.close		= mmp_pcm_close,
+	.close		= snd_dmaengine_pcm_close,
 	.ioctl		= snd_pcm_lib_ioctl,
 	.hw_params	= mmp_pcm_hw_params,
 	.trigger	= snd_dmaengine_pcm_trigger,
diff --git a/sound/soc/pxa/mmp-sspa.c b/sound/soc/pxa/mmp-sspa.c
index 9140c4a..a647799 100644
--- a/sound/soc/pxa/mmp-sspa.c
+++ b/sound/soc/pxa/mmp-sspa.c
@@ -405,6 +405,10 @@ struct snd_soc_dai_driver mmp_sspa_dai = {
 	.ops = &mmp_sspa_dai_ops,
 };
 
+static const struct snd_soc_component_driver mmp_sspa_component = {
+	.name		= "mmp-sspa",
+};
+
 static int asoc_mmp_sspa_probe(struct platform_device *pdev)
 {
 	struct sspa_priv *priv;
@@ -450,7 +454,8 @@ static int asoc_mmp_sspa_probe(struct platform_device *pdev)
 	priv->dai_fmt = (unsigned int) -1;
 	platform_set_drvdata(pdev, priv);
 
-	return snd_soc_register_dai(&pdev->dev, &mmp_sspa_dai);
+	return snd_soc_register_component(&pdev->dev, &mmp_sspa_component,
+					  &mmp_sspa_dai, 1);
 }
 
 static int asoc_mmp_sspa_remove(struct platform_device *pdev)
@@ -460,7 +465,7 @@ static int asoc_mmp_sspa_remove(struct platform_device *pdev)
 	clk_disable(priv->audio_clk);
 	clk_put(priv->audio_clk);
 	clk_put(priv->sysclk);
-	snd_soc_unregister_dai(&pdev->dev);
+	snd_soc_unregister_component(&pdev->dev);
 	return 0;
 }
 
diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c
index d3eb0c2..6f4dd75 100644
--- a/sound/soc/pxa/pxa-ssp.c
+++ b/sound/soc/pxa/pxa-ssp.c
@@ -794,14 +794,19 @@ static struct snd_soc_dai_driver pxa_ssp_dai = {
 		.ops = &pxa_ssp_dai_ops,
 };
 
+static const struct snd_soc_component_driver pxa_ssp_component = {
+	.name		= "pxa-ssp",
+};
+
 static int asoc_ssp_probe(struct platform_device *pdev)
 {
-	return snd_soc_register_dai(&pdev->dev, &pxa_ssp_dai);
+	return snd_soc_register_component(&pdev->dev, &pxa_ssp_component,
+					  &pxa_ssp_dai, 1);
 }
 
 static int asoc_ssp_remove(struct platform_device *pdev)
 {
-	snd_soc_unregister_dai(&pdev->dev);
+	snd_soc_unregister_component(&pdev->dev);
 	return 0;
 }
 
diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c
index 4b0a009..57ea8e6 100644
--- a/sound/soc/pxa/pxa2xx-ac97.c
+++ b/sound/soc/pxa/pxa2xx-ac97.c
@@ -47,6 +47,7 @@ struct snd_ac97_bus_ops soc_ac97_ops = {
 	.warm_reset	= pxa2xx_ac97_warm_reset,
 	.reset	= pxa2xx_ac97_cold_reset,
 };
+EXPORT_SYMBOL_GPL(soc_ac97_ops);
 
 static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_stereo_out = {
 	.name			= "AC97 PCM Stereo out",
@@ -232,7 +233,9 @@ static struct snd_soc_dai_driver pxa_ac97_dai_driver[] = {
 },
 };
 
-EXPORT_SYMBOL_GPL(soc_ac97_ops);
+static const struct snd_soc_component_driver pxa_ac97_component = {
+	.name		= "pxa-ac97",
+};
 
 static int pxa2xx_ac97_dev_probe(struct platform_device *pdev)
 {
@@ -245,13 +248,13 @@ static int pxa2xx_ac97_dev_probe(struct platform_device *pdev)
 	 * driver to do interesting things with the clocking to get us up
 	 * and running.
 	 */
-	return snd_soc_register_dais(&pdev->dev, pxa_ac97_dai_driver,
-			ARRAY_SIZE(pxa_ac97_dai_driver));
+	return snd_soc_register_component(&pdev->dev, &pxa_ac97_component,
+					  pxa_ac97_dai_driver, ARRAY_SIZE(pxa_ac97_dai_driver));
 }
 
 static int pxa2xx_ac97_dev_remove(struct platform_device *pdev)
 {
-	snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(pxa_ac97_dai_driver));
+	snd_soc_unregister_component(&pdev->dev);
 	return 0;
 }
 
diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c
index 6b1a06f..f7ca716 100644
--- a/sound/soc/pxa/pxa2xx-i2s.c
+++ b/sound/soc/pxa/pxa2xx-i2s.c
@@ -360,14 +360,19 @@ static struct snd_soc_dai_driver pxa_i2s_dai = {
 	.symmetric_rates = 1,
 };
 
+static const struct snd_soc_component_driver pxa_i2s_component = {
+	.name		= "pxa-i2s",
+};
+
 static int pxa2xx_i2s_drv_probe(struct platform_device *pdev)
 {
-	return snd_soc_register_dai(&pdev->dev, &pxa_i2s_dai);
+	return snd_soc_register_component(&pdev->dev, &pxa_i2s_component,
+					  &pxa_i2s_dai, 1);
 }
 
 static int pxa2xx_i2s_drv_remove(struct platform_device *pdev)
 {
-	snd_soc_unregister_dai(&pdev->dev);
+	snd_soc_unregister_component(&pdev->dev);
 	return 0;
 }
 
diff --git a/sound/soc/s6000/s6000-i2s.c b/sound/soc/s6000/s6000-i2s.c
index fee4d47..73bb99f 100644
--- a/sound/soc/s6000/s6000-i2s.c
+++ b/sound/soc/s6000/s6000-i2s.c
@@ -436,6 +436,10 @@ static struct snd_soc_dai_driver s6000_i2s_dai = {
 	.ops = &s6000_i2s_dai_ops,
 };
 
+static const struct snd_soc_component_driver s6000_i2s_component = {
+	.name		= "s6000-i2s",
+};
+
 static int s6000_i2s_probe(struct platform_device *pdev)
 {
 	struct s6000_i2s_dev *dev;
@@ -543,7 +547,8 @@ static int s6000_i2s_probe(struct platform_device *pdev)
 			 S6_I2S_INT_UNDERRUN |
 			 S6_I2S_INT_OVERRUN);
 
-	ret = snd_soc_register_dai(&pdev->dev, &s6000_i2s_dai);
+	ret = snd_soc_register_component(&pdev->dev, &s6000_i2s_component,
+					 &s6000_i2s_dai, 1);
 	if (ret)
 		goto err_release_dev;
 
@@ -572,7 +577,7 @@ static void s6000_i2s_remove(struct platform_device *pdev)
 	struct resource *region;
 	void __iomem *mmio = dev->scbbase;
 
-	snd_soc_unregister_dai(&pdev->dev);
+	snd_soc_unregister_component(&pdev->dev);
 
 	s6000_i2s_stop_channel(dev, 0);
 	s6000_i2s_stop_channel(dev, 1);
diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig
index 90e7e66..475fb0d 100644
--- a/sound/soc/samsung/Kconfig
+++ b/sound/soc/samsung/Kconfig
@@ -35,11 +35,10 @@ config SND_SAMSUNG_I2S
 	tristate
 
 config SND_SOC_SAMSUNG_NEO1973_WM8753
-	tristate "Audio support for Openmoko Neo1973 Smartphones (GTA01/GTA02)"
-	depends on SND_SOC_SAMSUNG && (MACH_NEO1973_GTA01 || MACH_NEO1973_GTA02)
+	tristate "Audio support for Openmoko Neo1973 Smartphones (GTA02)"
+	depends on SND_SOC_SAMSUNG && MACH_NEO1973_GTA02
 	select SND_S3C24XX_I2S
 	select SND_SOC_WM8753
-	select SND_SOC_LM4857 if MACH_NEO1973_GTA01
 	select SND_SOC_DFBMCS320
 	help
 	  Say Y here to enable audio support for the Openmoko Neo1973
diff --git a/sound/soc/samsung/ac97.c b/sound/soc/samsung/ac97.c
index 0df3c56..32ff594 100644
--- a/sound/soc/samsung/ac97.c
+++ b/sound/soc/samsung/ac97.c
@@ -370,6 +370,10 @@ static struct snd_soc_dai_driver s3c_ac97_dai[] = {
 	},
 };
 
+static const struct snd_soc_component_driver s3c_ac97_component = {
+	.name		= "s3c-ac97",
+};
+
 static int s3c_ac97_probe(struct platform_device *pdev)
 {
 	struct resource *mem_res, *dmatx_res, *dmarx_res, *dmamic_res, *irq_res;
@@ -457,8 +461,8 @@ static int s3c_ac97_probe(struct platform_device *pdev)
 		goto err4;
 	}
 
-	ret = snd_soc_register_dais(&pdev->dev, s3c_ac97_dai,
-			ARRAY_SIZE(s3c_ac97_dai));
+	ret = snd_soc_register_component(&pdev->dev, &s3c_ac97_component,
+					 s3c_ac97_dai, ARRAY_SIZE(s3c_ac97_dai));
 	if (ret)
 		goto err5;
 
@@ -470,7 +474,7 @@ static int s3c_ac97_probe(struct platform_device *pdev)
 
 	return 0;
 err6:
-	snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(s3c_ac97_dai));
+	snd_soc_unregister_component(&pdev->dev);
 err5:
 	free_irq(irq_res->start, NULL);
 err4:
@@ -490,7 +494,7 @@ static int s3c_ac97_remove(struct platform_device *pdev)
 	struct resource *mem_res, *irq_res;
 
 	asoc_dma_platform_unregister(&pdev->dev);
-	snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(s3c_ac97_dai));
+	snd_soc_unregister_component(&pdev->dev);
 
 	irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 	if (irq_res)
diff --git a/sound/soc/samsung/goni_wm8994.c b/sound/soc/samsung/goni_wm8994.c
index d37ede5..415ad81 100644
--- a/sound/soc/samsung/goni_wm8994.c
+++ b/sound/soc/samsung/goni_wm8994.c
@@ -218,6 +218,10 @@ static struct snd_soc_dai_driver voice_dai = {
 		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
 };
 
+static const struct snd_soc_component_driver voice_component = {
+	.name		= "goni-voice",
+};
+
 static struct snd_soc_ops goni_voice_ops = {
 	.hw_params = goni_voice_hw_params,
 };
@@ -270,7 +274,8 @@ static int __init goni_init(void)
 		return -ENOMEM;
 
 	/* register voice DAI here */
-	ret = snd_soc_register_dai(&goni_snd_device->dev, &voice_dai);
+	ret = snd_soc_register_component(&goni_snd_device->dev, &voice_component,
+					 &voice_dai, 1);
 	if (ret) {
 		platform_device_put(goni_snd_device);
 		return ret;
@@ -280,7 +285,7 @@ static int __init goni_init(void)
 	ret = platform_device_add(goni_snd_device);
 
 	if (ret) {
-		snd_soc_unregister_dai(&goni_snd_device->dev);
+		snd_soc_unregister_component(&goni_snd_device->dev);
 		platform_device_put(goni_snd_device);
 	}
 
@@ -289,7 +294,7 @@ static int __init goni_init(void)
 
 static void __exit goni_exit(void)
 {
-	snd_soc_unregister_dai(&goni_snd_device->dev);
+	snd_soc_unregister_component(&goni_snd_device->dev);
 	platform_device_unregister(goni_snd_device);
 }
 
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c
index d7231e3..abbcbe4 100644
--- a/sound/soc/samsung/i2s.c
+++ b/sound/soc/samsung/i2s.c
@@ -963,6 +963,10 @@ static const struct snd_soc_dai_ops samsung_i2s_dai_ops = {
 	.delay = i2s_delay,
 };
 
+static const struct snd_soc_component_driver samsung_i2s_component = {
+	.name		= "samsung-i2s",
+};
+
 #define SAMSUNG_I2S_RATES	SNDRV_PCM_RATE_8000_96000
 
 #define SAMSUNG_I2S_FMTS	(SNDRV_PCM_FMTBIT_S8 | \
@@ -972,6 +976,7 @@ static const struct snd_soc_dai_ops samsung_i2s_dai_ops = {
 static struct i2s_dai *i2s_alloc_dai(struct platform_device *pdev, bool sec)
 {
 	struct i2s_dai *i2s;
+	int ret;
 
 	i2s = devm_kzalloc(&pdev->dev, sizeof(struct i2s_dai), GFP_KERNEL);
 	if (i2s == NULL)
@@ -996,15 +1001,17 @@ static struct i2s_dai *i2s_alloc_dai(struct platform_device *pdev, bool sec)
 		i2s->i2s_dai_drv.capture.channels_max = 2;
 		i2s->i2s_dai_drv.capture.rates = SAMSUNG_I2S_RATES;
 		i2s->i2s_dai_drv.capture.formats = SAMSUNG_I2S_FMTS;
+		dev_set_drvdata(&i2s->pdev->dev, i2s);
 	} else {	/* Create a new platform_device for Secondary */
-		i2s->pdev = platform_device_register_resndata(NULL,
-				"samsung-i2s-sec", -1, NULL, 0, NULL, 0);
+		i2s->pdev = platform_device_alloc("samsung-i2s-sec", -1);
 		if (IS_ERR(i2s->pdev))
 			return NULL;
-	}
 
-	/* Pre-assign snd_soc_dai_set_drvdata */
-	dev_set_drvdata(&i2s->pdev->dev, i2s);
+		platform_set_drvdata(i2s->pdev, i2s);
+		ret = platform_device_add(i2s->pdev);
+		if (ret < 0)
+			return NULL;
+	}
 
 	return i2s;
 }
@@ -1107,8 +1114,13 @@ static int samsung_i2s_probe(struct platform_device *pdev)
 
 	if (samsung_dai_type == TYPE_SEC) {
 		sec_dai = dev_get_drvdata(&pdev->dev);
-		snd_soc_register_dai(&sec_dai->pdev->dev,
-			&sec_dai->i2s_dai_drv);
+		if (!sec_dai) {
+			dev_err(&pdev->dev, "Unable to get drvdata\n");
+			return -EFAULT;
+		}
+		snd_soc_register_component(&sec_dai->pdev->dev,
+					   &samsung_i2s_component,
+					   &sec_dai->i2s_dai_drv, 1);
 		asoc_dma_platform_register(&pdev->dev);
 		return 0;
 	}
@@ -1237,7 +1249,8 @@ static int samsung_i2s_probe(struct platform_device *pdev)
 		}
 	}
 
-	snd_soc_register_dai(&pri_dai->pdev->dev, &pri_dai->i2s_dai_drv);
+	snd_soc_register_component(&pri_dai->pdev->dev, &samsung_i2s_component,
+				   &pri_dai->i2s_dai_drv, 1);
 
 	pm_runtime_enable(&pdev->dev);
 
@@ -1276,7 +1289,7 @@ static int samsung_i2s_remove(struct platform_device *pdev)
 	i2s->sec_dai = NULL;
 
 	asoc_dma_platform_unregister(&pdev->dev);
-	snd_soc_unregister_dai(&pdev->dev);
+	snd_soc_unregister_component(&pdev->dev);
 
 	return 0;
 }
diff --git a/sound/soc/samsung/pcm.c b/sound/soc/samsung/pcm.c
index 13bab79..1566afe 100644
--- a/sound/soc/samsung/pcm.c
+++ b/sound/soc/samsung/pcm.c
@@ -490,6 +490,10 @@ static struct snd_soc_dai_driver s3c_pcm_dai[] = {
 	},
 };
 
+static const struct snd_soc_component_driver s3c_pcm_component = {
+	.name		= "s3c-pcm",
+};
+
 static int s3c_pcm_dev_probe(struct platform_device *pdev)
 {
 	struct s3c_pcm_info *pcm;
@@ -583,7 +587,8 @@ static int s3c_pcm_dev_probe(struct platform_device *pdev)
 
 	pm_runtime_enable(&pdev->dev);
 
-	ret = snd_soc_register_dai(&pdev->dev, &s3c_pcm_dai[pdev->id]);
+	ret = snd_soc_register_component(&pdev->dev, &s3c_pcm_component,
+					 &s3c_pcm_dai[pdev->id], 1);
 	if (ret != 0) {
 		dev_err(&pdev->dev, "failed to get register DAI: %d\n", ret);
 		goto err5;
@@ -598,7 +603,7 @@ static int s3c_pcm_dev_probe(struct platform_device *pdev)
 	return 0;
 
 err6:
-	snd_soc_unregister_dai(&pdev->dev);
+	snd_soc_unregister_component(&pdev->dev);
 err5:
 	clk_disable_unprepare(pcm->pclk);
 	clk_put(pcm->pclk);
@@ -619,7 +624,7 @@ static int s3c_pcm_dev_remove(struct platform_device *pdev)
 	struct resource *mem_res;
 
 	asoc_dma_platform_unregister(&pdev->dev);
-	snd_soc_unregister_dai(&pdev->dev);
+	snd_soc_unregister_component(&pdev->dev);
 
 	pm_runtime_disable(&pdev->dev);
 
diff --git a/sound/soc/samsung/s3c-i2s-v2.c b/sound/soc/samsung/s3c-i2s-v2.c
index 7a73380..20e98d1 100644
--- a/sound/soc/samsung/s3c-i2s-v2.c
+++ b/sound/soc/samsung/s3c-i2s-v2.c
@@ -731,8 +731,9 @@ static int s3c2412_i2s_resume(struct snd_soc_dai *dai)
 #define s3c2412_i2s_resume  NULL
 #endif
 
-int s3c_i2sv2_register_dai(struct device *dev, int id,
-		struct snd_soc_dai_driver *drv)
+int s3c_i2sv2_register_component(struct device *dev, int id,
+			   struct snd_soc_component_driver *cmp_drv,
+			   struct snd_soc_dai_driver *dai_drv)
 {
 	struct snd_soc_dai_ops *ops = drv->ops;
 
@@ -750,8 +751,8 @@ int s3c_i2sv2_register_dai(struct device *dev, int id,
 	drv->suspend = s3c2412_i2s_suspend;
 	drv->resume = s3c2412_i2s_resume;
 
-	return snd_soc_register_dai(dev, drv);
+	return snd_soc_register_component(dev, cmp_drv, dai_drv, 1);
 }
-EXPORT_SYMBOL_GPL(s3c_i2sv2_register_dai);
+EXPORT_SYMBOL_GPL(s3c_i2sv2_register_component);
 
 MODULE_LICENSE("GPL");
diff --git a/sound/soc/samsung/s3c-i2s-v2.h b/sound/soc/samsung/s3c-i2s-v2.h
index f8297d9..90abab3 100644
--- a/sound/soc/samsung/s3c-i2s-v2.h
+++ b/sound/soc/samsung/s3c-i2s-v2.h
@@ -92,7 +92,7 @@ extern int s3c_i2sv2_probe(struct snd_soc_dai *dai,
 			   unsigned long base);
 
 /**
- * s3c_i2sv2_register_dai - register dai with soc core
+ * s3c_i2sv2_register_component - register component and dai with soc core
  * @dev: DAI device
  * @id: DAI ID
  * @drv: The driver structure to register
@@ -100,7 +100,8 @@ extern int s3c_i2sv2_probe(struct snd_soc_dai *dai,
  * Fill in any missing fields and then register the given dai with the
  * soc core.
  */
-extern int s3c_i2sv2_register_dai(struct device *dev, int id,
-		struct snd_soc_dai_driver *drv);
+extern int s3c_i2sv2_register_component(struct device *dev, int id,
+					struct snd_soc_component_driver *cmp_drv,
+					struct snd_soc_dai_driver *dai_drv);
 
 #endif /* __SND_SOC_S3C24XX_S3C_I2SV2_I2S_H */
diff --git a/sound/soc/samsung/s3c2412-i2s.c b/sound/soc/samsung/s3c2412-i2s.c
index 2213377..47e2386 100644
--- a/sound/soc/samsung/s3c2412-i2s.c
+++ b/sound/soc/samsung/s3c2412-i2s.c
@@ -160,11 +160,17 @@ static struct snd_soc_dai_driver s3c2412_i2s_dai = {
 	.ops = &s3c2412_i2s_dai_ops,
 };
 
+static const struct snd_soc_component_driver s3c2412_i2s_component = {
+	.name		= "s3c2412-i2s",
+};
+
 static int s3c2412_iis_dev_probe(struct platform_device *pdev)
 {
 	int ret = 0;
 
-	ret = s3c_i2sv2_register_dai(&pdev->dev, -1, &s3c2412_i2s_dai);
+	ret = s3c_i2sv2_register_component(&pdev->dev, -1,
+					   &s3c2412_i2s_component,
+					   &s3c2412_i2s_dai);
 	if (ret) {
 		pr_err("failed to register the dai\n");
 		return ret;
@@ -178,14 +184,14 @@ static int s3c2412_iis_dev_probe(struct platform_device *pdev)
 
 	return 0;
 err:
-	snd_soc_unregister_dai(&pdev->dev);
+	snd_soc_unregister_component(&pdev->dev);
 	return ret;
 }
 
 static int s3c2412_iis_dev_remove(struct platform_device *pdev)
 {
 	asoc_dma_platform_unregister(&pdev->dev);
-	snd_soc_unregister_dai(&pdev->dev);
+	snd_soc_unregister_component(&pdev->dev);
 	return 0;
 }
 
diff --git a/sound/soc/samsung/s3c24xx-i2s.c b/sound/soc/samsung/s3c24xx-i2s.c
index 13f6dd1..5403176 100644
--- a/sound/soc/samsung/s3c24xx-i2s.c
+++ b/sound/soc/samsung/s3c24xx-i2s.c
@@ -465,11 +465,16 @@ static struct snd_soc_dai_driver s3c24xx_i2s_dai = {
 	.ops = &s3c24xx_i2s_dai_ops,
 };
 
+static const struct snd_soc_component_driver s3c24xx_i2s_component = {
+	.name		= "s3c24xx-i2s",
+};
+
 static int s3c24xx_iis_dev_probe(struct platform_device *pdev)
 {
 	int ret = 0;
 
-	ret = snd_soc_register_dai(&pdev->dev, &s3c24xx_i2s_dai);
+	ret = snd_soc_register_component(&pdev->dev, &s3c24xx_i2s_component,
+					 &s3c24xx_i2s_dai, 1);
 	if (ret) {
 		pr_err("failed to register the dai\n");
 		return ret;
@@ -483,14 +488,14 @@ static int s3c24xx_iis_dev_probe(struct platform_device *pdev)
 
 	return 0;
 err:
-	snd_soc_unregister_dai(&pdev->dev);
+	snd_soc_unregister_component(&pdev->dev);
 	return ret;
 }
 
 static int s3c24xx_iis_dev_remove(struct platform_device *pdev)
 {
 	asoc_dma_platform_unregister(&pdev->dev);
-	snd_soc_unregister_dai(&pdev->dev);
+	snd_soc_unregister_component(&pdev->dev);
 	return 0;
 }
 
diff --git a/sound/soc/samsung/spdif.c b/sound/soc/samsung/spdif.c
index 5008e5b..2e5ebb2 100644
--- a/sound/soc/samsung/spdif.c
+++ b/sound/soc/samsung/spdif.c
@@ -357,6 +357,10 @@ static struct snd_soc_dai_driver samsung_spdif_dai = {
 	.resume = spdif_resume,
 };
 
+static const struct snd_soc_component_driver samsung_spdif_component = {
+	.name		= "samsung-spdif",
+};
+
 static int spdif_probe(struct platform_device *pdev)
 {
 	struct s3c_audio_pdata *spdif_pdata;
@@ -424,7 +428,8 @@ static int spdif_probe(struct platform_device *pdev)
 
 	dev_set_drvdata(&pdev->dev, spdif);
 
-	ret = snd_soc_register_dai(&pdev->dev, &samsung_spdif_dai);
+	ret = snd_soc_register_component(&pdev->dev, &samsung_spdif_component,
+					 &samsung_spdif_dai, 1);
 	if (ret != 0) {
 		dev_err(&pdev->dev, "fail to register dai\n");
 		goto err4;
@@ -445,7 +450,7 @@ static int spdif_probe(struct platform_device *pdev)
 
 	return 0;
 err5:
-	snd_soc_unregister_dai(&pdev->dev);
+	snd_soc_unregister_component(&pdev->dev);
 err4:
 	iounmap(spdif->regs);
 err3:
@@ -466,7 +471,7 @@ static int spdif_remove(struct platform_device *pdev)
 	struct resource *mem_res;
 
 	asoc_dma_platform_unregister(&pdev->dev);
-	snd_soc_unregister_dai(&pdev->dev);
+	snd_soc_unregister_component(&pdev->dev);
 
 	iounmap(spdif->regs);
 
diff --git a/sound/soc/sh/dma-sh7760.c b/sound/soc/sh/dma-sh7760.c
index 19eff8f..1a8b03e 100644
--- a/sound/soc/sh/dma-sh7760.c
+++ b/sound/soc/sh/dma-sh7760.c
@@ -342,8 +342,8 @@ static int camelot_pcm_new(struct snd_soc_pcm_runtime *rtd)
 	return 0;
 }
 
-static struct snd_soc_platform sh7760_soc_platform = {
-	.pcm_ops 	= &camelot_pcm_ops,
+static struct snd_soc_platform_driver sh7760_soc_platform = {
+	.ops		= &camelot_pcm_ops,
 	.pcm_new	= camelot_pcm_new,
 	.pcm_free	= camelot_pcm_free,
 };
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c
index c724026..f830c41 100644
--- a/sound/soc/sh/fsi.c
+++ b/sound/soc/sh/fsi.c
@@ -296,7 +296,6 @@ struct fsi_core {
 
 struct fsi_master {
 	void __iomem *base;
-	int irq;
 	struct fsi_priv fsia;
 	struct fsi_priv fsib;
 	const struct fsi_core *core;
@@ -1886,6 +1885,10 @@ static struct snd_soc_platform_driver fsi_soc_platform = {
 	.pcm_free	= fsi_pcm_free,
 };
 
+static const struct snd_soc_component_driver fsi_soc_component = {
+	.name		= "fsi",
+};
+
 /*
  *		platform function
  */
@@ -2002,7 +2005,6 @@ static int fsi_probe(struct platform_device *pdev)
 	}
 
 	/* master setting */
-	master->irq		= irq;
 	master->core		= core;
 	spin_lock_init(&master->lock);
 
@@ -2046,10 +2048,10 @@ static int fsi_probe(struct platform_device *pdev)
 		goto exit_fsib;
 	}
 
-	ret = snd_soc_register_dais(&pdev->dev, fsi_soc_dai,
-				    ARRAY_SIZE(fsi_soc_dai));
+	ret = snd_soc_register_component(&pdev->dev, &fsi_soc_component,
+				    fsi_soc_dai, ARRAY_SIZE(fsi_soc_dai));
 	if (ret < 0) {
-		dev_err(&pdev->dev, "cannot snd dai register\n");
+		dev_err(&pdev->dev, "cannot snd component register\n");
 		goto exit_snd_soc;
 	}
 
@@ -2074,7 +2076,7 @@ static int fsi_remove(struct platform_device *pdev)
 
 	pm_runtime_disable(&pdev->dev);
 
-	snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(fsi_soc_dai));
+	snd_soc_unregister_component(&pdev->dev);
 	snd_soc_unregister_platform(&pdev->dev);
 
 	fsi_stream_remove(&master->fsia);
diff --git a/sound/soc/sh/hac.c b/sound/soc/sh/hac.c
index 4cc2d64..af19f77 100644
--- a/sound/soc/sh/hac.c
+++ b/sound/soc/sh/hac.c
@@ -310,15 +310,19 @@ static struct snd_soc_dai_driver sh4_hac_dai[] = {
 #endif
 };
 
+static const struct snd_soc_component_driver sh4_hac_component = {
+	.name		= "sh4-hac",
+};
+
 static int hac_soc_platform_probe(struct platform_device *pdev)
 {
-	return snd_soc_register_dais(&pdev->dev, sh4_hac_dai,
-			ARRAY_SIZE(sh4_hac_dai));
+	return snd_soc_register_component(&pdev->dev, &sh4_hac_component,
+					  sh4_hac_dai, ARRAY_SIZE(sh4_hac_dai));
 }
 
 static int hac_soc_platform_remove(struct platform_device *pdev)
 {
-	snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(sh4_hac_dai));
+	snd_soc_unregister_component(&pdev->dev);
 	return 0;
 }
 
diff --git a/sound/soc/sh/migor.c b/sound/soc/sh/migor.c
index 8526e1e..5014a88 100644
--- a/sound/soc/sh/migor.c
+++ b/sound/soc/sh/migor.c
@@ -153,7 +153,7 @@ static int migor_dai_init(struct snd_soc_pcm_runtime *rtd)
 static struct snd_soc_dai_link migor_dai = {
 	.name = "wm8978",
 	.stream_name = "WM8978",
-	.cpu_dai_name = "siu-i2s-dai",
+	.cpu_dai_name = "siu-pcm-audio",
 	.codec_dai_name = "wm8978-hifi",
 	.platform_name = "siu-pcm-audio",
 	.codec_name = "wm8978.0-001a",
diff --git a/sound/soc/sh/siu_dai.c b/sound/soc/sh/siu_dai.c
index 34facdc..9dc24ff 100644
--- a/sound/soc/sh/siu_dai.c
+++ b/sound/soc/sh/siu_dai.c
@@ -726,6 +726,10 @@ static struct snd_soc_dai_driver siu_i2s_dai = {
 	.ops = &siu_dai_ops,
 };
 
+static const struct snd_soc_component_driver siu_i2s_component = {
+	.name		= "siu-i2s",
+};
+
 static int siu_probe(struct platform_device *pdev)
 {
 	const struct firmware *fw_entry;
@@ -783,7 +787,8 @@ static int siu_probe(struct platform_device *pdev)
 	dev_set_drvdata(&pdev->dev, info);
 
 	/* register using ARRAY version so we can keep dai name */
-	ret = snd_soc_register_dais(&pdev->dev, &siu_i2s_dai, 1);
+	ret = snd_soc_register_component(&pdev->dev, &siu_i2s_component,
+					 &siu_i2s_dai, 1);
 	if (ret < 0)
 		goto edaiinit;
 
@@ -796,7 +801,7 @@ static int siu_probe(struct platform_device *pdev)
 	return ret;
 
 esocregp:
-	snd_soc_unregister_dai(&pdev->dev);
+	snd_soc_unregister_component(&pdev->dev);
 edaiinit:
 	iounmap(info->reg);
 emapreg:
@@ -823,7 +828,7 @@ static int siu_remove(struct platform_device *pdev)
 	pm_runtime_disable(&pdev->dev);
 
 	snd_soc_unregister_platform(&pdev->dev);
-	snd_soc_unregister_dai(&pdev->dev);
+	snd_soc_unregister_component(&pdev->dev);
 
 	iounmap(info->reg);
 	iounmap(info->yram);
diff --git a/sound/soc/sh/ssi.c b/sound/soc/sh/ssi.c
index c8e73a7..e889405 100644
--- a/sound/soc/sh/ssi.c
+++ b/sound/soc/sh/ssi.c
@@ -379,15 +379,19 @@ static struct snd_soc_dai_driver sh4_ssi_dai[] = {
 #endif
 };
 
+static const struct snd_soc_component_driver sh4_ssi_component = {
+	.name		= "sh4-ssi",
+};
+
 static int sh4_soc_dai_probe(struct platform_device *pdev)
 {
-	return snd_soc_register_dais(&pdev->dev, sh4_ssi_dai,
-			ARRAY_SIZE(sh4_ssi_dai));
+	return snd_soc_register_component(&pdev->dev, &sh4_ssi_component,
+					  sh4_ssi_dai, ARRAY_SIZE(sh4_ssi_dai));
 }
 
 static int sh4_soc_dai_remove(struct platform_device *pdev)
 {
-	snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(sh4_ssi_dai));
+	snd_soc_unregister_component(&pdev->dev);
 	return 0;
 }
 
diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c
index b5b3db7..29093a3 100644
--- a/sound/soc/soc-compress.c
+++ b/sound/soc/soc-compress.c
@@ -211,19 +211,27 @@ static int soc_compr_set_params(struct snd_compr_stream *cstream,
 	if (platform->driver->compr_ops && platform->driver->compr_ops->set_params) {
 		ret = platform->driver->compr_ops->set_params(cstream, params);
 		if (ret < 0)
-			goto out;
+			goto err;
 	}
 
 	if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->set_params) {
 		ret = rtd->dai_link->compr_ops->set_params(cstream);
 		if (ret < 0)
-			goto out;
+			goto err;
 	}
 
 	snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK,
 				SND_SOC_DAPM_STREAM_START);
 
-out:
+	/* cancel any delayed stream shutdown that is pending */
+	rtd->pop_wait = 0;
+	mutex_unlock(&rtd->pcm_mutex);
+
+	cancel_delayed_work_sync(&rtd->delayed_work);
+
+	return ret;
+
+err:
 	mutex_unlock(&rtd->pcm_mutex);
 	return ret;
 }
@@ -322,11 +330,38 @@ static int soc_compr_copy(struct snd_compr_stream *cstream,
 	return ret;
 }
 
+static int sst_compr_set_metadata(struct snd_compr_stream *cstream,
+				struct snd_compr_metadata *metadata)
+{
+	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
+	struct snd_soc_platform *platform = rtd->platform;
+	int ret = 0;
+
+	if (platform->driver->compr_ops && platform->driver->compr_ops->set_metadata)
+		ret = platform->driver->compr_ops->set_metadata(cstream, metadata);
+
+	return ret;
+}
+
+static int sst_compr_get_metadata(struct snd_compr_stream *cstream,
+				struct snd_compr_metadata *metadata)
+{
+	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
+	struct snd_soc_platform *platform = rtd->platform;
+	int ret = 0;
+
+	if (platform->driver->compr_ops && platform->driver->compr_ops->get_metadata)
+		ret = platform->driver->compr_ops->get_metadata(cstream, metadata);
+
+	return ret;
+}
 /* ASoC Compress operations */
 static struct snd_compr_ops soc_compr_ops = {
 	.open		= soc_compr_open,
 	.free		= soc_compr_free,
 	.set_params	= soc_compr_set_params,
+	.set_metadata   = sst_compr_set_metadata,
+	.get_metadata	= sst_compr_get_metadata,
 	.get_params	= soc_compr_get_params,
 	.trigger	= soc_compr_trigger,
 	.pointer	= soc_compr_pointer,
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index b7e84a7..7bf21a1 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -58,6 +58,7 @@ static DEFINE_MUTEX(client_mutex);
 static LIST_HEAD(dai_list);
 static LIST_HEAD(platform_list);
 static LIST_HEAD(codec_list);
+static LIST_HEAD(component_list);
 
 /*
  * This is a timeout to do a DAPM powerdown after a stream is closed().
@@ -2963,7 +2964,7 @@ int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol,
 	val = val << shift;
 
 	ret = snd_soc_update_bits_locked(codec, reg, val_mask, val);
-	if (ret != 0)
+	if (ret < 0)
 		return ret;
 
 	if (snd_soc_volsw_is_stereo(mc)) {
@@ -3140,7 +3141,7 @@ int snd_soc_bytes_put(struct snd_kcontrol *kcontrol,
 	if (params->mask) {
 		ret = regmap_read(codec->control_data, params->base, &val);
 		if (ret != 0)
-			return ret;
+			goto out;
 
 		val &= params->mask;
 
@@ -3158,13 +3159,15 @@ int snd_soc_bytes_put(struct snd_kcontrol *kcontrol,
 			((u32 *)data)[0] |= cpu_to_be32(val);
 			break;
 		default:
-			return -EINVAL;
+			ret = -EINVAL;
+			goto out;
 		}
 	}
 
 	ret = regmap_raw_write(codec->control_data, params->base,
 			       data, len);
 
+out:
 	kfree(data);
 
 	return ret;
@@ -3738,7 +3741,7 @@ static inline char *fmt_multiple_name(struct device *dev,
  *
  * @dai: DAI to register
  */
-int snd_soc_register_dai(struct device *dev,
+static int snd_soc_register_dai(struct device *dev,
 		struct snd_soc_dai_driver *dai_drv)
 {
 	struct snd_soc_codec *codec;
@@ -3785,14 +3788,13 @@ int snd_soc_register_dai(struct device *dev,
 
 	return 0;
 }
-EXPORT_SYMBOL_GPL(snd_soc_register_dai);
 
 /**
  * snd_soc_unregister_dai - Unregister a DAI from the ASoC core
  *
  * @dai: DAI to unregister
  */
-void snd_soc_unregister_dai(struct device *dev)
+static void snd_soc_unregister_dai(struct device *dev)
 {
 	struct snd_soc_dai *dai;
 
@@ -3811,7 +3813,6 @@ found:
 	kfree(dai->name);
 	kfree(dai);
 }
-EXPORT_SYMBOL_GPL(snd_soc_unregister_dai);
 
 /**
  * snd_soc_register_dais - Register multiple DAIs with the ASoC core
@@ -3819,7 +3820,7 @@ EXPORT_SYMBOL_GPL(snd_soc_unregister_dai);
  * @dai: Array of DAIs to register
  * @count: Number of DAIs
  */
-int snd_soc_register_dais(struct device *dev,
+static int snd_soc_register_dais(struct device *dev,
 		struct snd_soc_dai_driver *dai_drv, size_t count)
 {
 	struct snd_soc_codec *codec;
@@ -3883,7 +3884,6 @@ err:
 
 	return ret;
 }
-EXPORT_SYMBOL_GPL(snd_soc_register_dais);
 
 /**
  * snd_soc_unregister_dais - Unregister multiple DAIs from the ASoC core
@@ -3891,14 +3891,13 @@ EXPORT_SYMBOL_GPL(snd_soc_register_dais);
  * @dai: Array of DAIs to unregister
  * @count: Number of DAIs
  */
-void snd_soc_unregister_dais(struct device *dev, size_t count)
+static void snd_soc_unregister_dais(struct device *dev, size_t count)
 {
 	int i;
 
 	for (i = 0; i < count; i++)
 		snd_soc_unregister_dai(dev);
 }
-EXPORT_SYMBOL_GPL(snd_soc_unregister_dais);
 
 /**
  * snd_soc_register_platform - Register a platform with the ASoC core
@@ -3906,7 +3905,7 @@ EXPORT_SYMBOL_GPL(snd_soc_unregister_dais);
  * @platform: platform to register
  */
 int snd_soc_register_platform(struct device *dev,
-		struct snd_soc_platform_driver *platform_drv)
+		const struct snd_soc_platform_driver *platform_drv)
 {
 	struct snd_soc_platform *platform;
 
@@ -4022,8 +4021,8 @@ int snd_soc_register_codec(struct device *dev,
 	/* create CODEC component name */
 	codec->name = fmt_single_name(dev, &codec->id);
 	if (codec->name == NULL) {
-		kfree(codec);
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto fail_codec;
 	}
 
 	if (codec_drv->compress_type)
@@ -4062,7 +4061,7 @@ int snd_soc_register_codec(struct device *dev,
 						      reg_size, GFP_KERNEL);
 			if (!codec->reg_def_copy) {
 				ret = -ENOMEM;
-				goto fail;
+				goto fail_codec_name;
 			}
 		}
 	}
@@ -4086,18 +4085,22 @@ int snd_soc_register_codec(struct device *dev,
 	mutex_unlock(&client_mutex);
 
 	/* register any DAIs */
-	if (num_dai) {
-		ret = snd_soc_register_dais(dev, dai_drv, num_dai);
-		if (ret < 0)
-			dev_err(codec->dev, "ASoC: Failed to regster"
-				" DAIs: %d\n", ret);
+	ret = snd_soc_register_dais(dev, dai_drv, num_dai);
+	if (ret < 0) {
+		dev_err(codec->dev, "ASoC: Failed to regster DAIs: %d\n", ret);
+		goto fail_codec_name;
 	}
 
 	dev_dbg(codec->dev, "ASoC: Registered codec '%s'\n", codec->name);
 	return 0;
 
-fail:
+fail_codec_name:
+	mutex_lock(&client_mutex);
+	list_del(&codec->list);
+	mutex_unlock(&client_mutex);
+
 	kfree(codec->name);
+fail_codec:
 	kfree(codec);
 	return ret;
 }
@@ -4111,7 +4114,6 @@ EXPORT_SYMBOL_GPL(snd_soc_register_codec);
 void snd_soc_unregister_codec(struct device *dev)
 {
 	struct snd_soc_codec *codec;
-	int i;
 
 	list_for_each_entry(codec, &codec_list, list) {
 		if (dev == codec->dev)
@@ -4120,9 +4122,7 @@ void snd_soc_unregister_codec(struct device *dev)
 	return;
 
 found:
-	if (codec->num_dai)
-		for (i = 0; i < codec->num_dai; i++)
-			snd_soc_unregister_dai(dev);
+	snd_soc_unregister_dais(dev, codec->num_dai);
 
 	mutex_lock(&client_mutex);
 	list_del(&codec->list);
@@ -4137,6 +4137,92 @@ found:
 }
 EXPORT_SYMBOL_GPL(snd_soc_unregister_codec);
 
+
+/**
+ * snd_soc_register_component - Register a component with the ASoC core
+ *
+ */
+int snd_soc_register_component(struct device *dev,
+			 const struct snd_soc_component_driver *cmpnt_drv,
+			 struct snd_soc_dai_driver *dai_drv,
+			 int num_dai)
+{
+	struct snd_soc_component *cmpnt;
+	int ret;
+
+	dev_dbg(dev, "component register %s\n", dev_name(dev));
+
+	cmpnt = devm_kzalloc(dev, sizeof(*cmpnt), GFP_KERNEL);
+	if (!cmpnt) {
+		dev_err(dev, "ASoC: Failed to allocate memory\n");
+		return -ENOMEM;
+	}
+
+	cmpnt->name = fmt_single_name(dev, &cmpnt->id);
+	if (!cmpnt->name) {
+		dev_err(dev, "ASoC: Failed to simplifying name\n");
+		return -ENOMEM;
+	}
+
+	cmpnt->dev	= dev;
+	cmpnt->driver	= cmpnt_drv;
+	cmpnt->num_dai	= num_dai;
+
+	/*
+	 * snd_soc_register_dai()  uses fmt_single_name(), and
+	 * snd_soc_register_dais() uses fmt_multiple_name()
+	 * for dai->name which is used for name based matching
+	 */
+	if (1 == num_dai)
+		ret = snd_soc_register_dai(dev, dai_drv);
+	else
+		ret = snd_soc_register_dais(dev, dai_drv, num_dai);
+	if (ret < 0) {
+		dev_err(dev, "ASoC: Failed to regster DAIs: %d\n", ret);
+		goto error_component_name;
+	}
+
+	mutex_lock(&client_mutex);
+	list_add(&cmpnt->list, &component_list);
+	mutex_unlock(&client_mutex);
+
+	dev_dbg(cmpnt->dev, "ASoC: Registered component '%s'\n", cmpnt->name);
+
+	return ret;
+
+error_component_name:
+	kfree(cmpnt->name);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(snd_soc_register_component);
+
+/**
+ * snd_soc_unregister_component - Unregister a component from the ASoC core
+ *
+ */
+void snd_soc_unregister_component(struct device *dev)
+{
+	struct snd_soc_component *cmpnt;
+
+	list_for_each_entry(cmpnt, &component_list, list) {
+		if (dev == cmpnt->dev)
+			goto found;
+	}
+	return;
+
+found:
+	snd_soc_unregister_dais(dev, cmpnt->num_dai);
+
+	mutex_lock(&client_mutex);
+	list_del(&cmpnt->list);
+	mutex_unlock(&client_mutex);
+
+	dev_dbg(dev, "ASoC: Unregistered component '%s'\n", cmpnt->name);
+	kfree(cmpnt->name);
+}
+EXPORT_SYMBOL_GPL(snd_soc_unregister_component);
+
 /* Retrieve a card's name from device tree */
 int snd_soc_of_parse_card_name(struct snd_soc_card *card,
 			       const char *propname)
@@ -4197,7 +4283,6 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card,
 			dev_err(card->dev,
 				"ASoC: Property '%s' index %d could not be read: %d\n",
 				propname, 2 * i, ret);
-			kfree(routes);
 			return -EINVAL;
 		}
 		ret = of_property_read_string_index(np, propname,
@@ -4206,7 +4291,6 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card,
 			dev_err(card->dev,
 				"ASoC: Property '%s' index %d could not be read: %d\n",
 				propname, (2 * i) + 1, ret);
-			kfree(routes);
 			return -EINVAL;
 		}
 	}
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 1d6a9b3..21779a6 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -504,17 +504,27 @@ static int dapm_is_shared_kcontrol(struct snd_soc_dapm_context *dapm,
 	return 0;
 }
 
-/* create new dapm mixer control */
-static int dapm_new_mixer(struct snd_soc_dapm_widget *w)
+/*
+ * Determine if a kcontrol is shared. If it is, look it up. If it isn't,
+ * create it. Either way, add the widget into the control's widget list
+ */
+static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w,
+	int kci, struct snd_soc_dapm_path *path)
 {
 	struct snd_soc_dapm_context *dapm = w->dapm;
-	int i, ret = 0;
-	size_t name_len, prefix_len;
-	struct snd_soc_dapm_path *path;
 	struct snd_card *card = dapm->card->snd_card;
 	const char *prefix;
+	size_t prefix_len;
+	int shared;
+	struct snd_kcontrol *kcontrol;
 	struct snd_soc_dapm_widget_list *wlist;
+	int wlistentries;
 	size_t wlistsize;
+	bool wname_in_long_name, kcname_in_long_name;
+	size_t name_len;
+	char *long_name;
+	const char *name;
+	int ret;
 
 	if (dapm->codec)
 		prefix = dapm->codec->name_prefix;
@@ -526,103 +536,141 @@ static int dapm_new_mixer(struct snd_soc_dapm_widget *w)
 	else
 		prefix_len = 0;
 
-	/* add kcontrol */
-	for (i = 0; i < w->num_kcontrols; i++) {
+	shared = dapm_is_shared_kcontrol(dapm, w, &w->kcontrol_news[kci],
+					 &kcontrol);
 
-		/* match name */
-		list_for_each_entry(path, &w->sources, list_sink) {
+	if (kcontrol) {
+		wlist = kcontrol->private_data;
+		wlistentries = wlist->num_widgets + 1;
+	} else {
+		wlist = NULL;
+		wlistentries = 1;
+	}
 
-			/* mixer/mux paths name must match control name */
-			if (path->name != (char *)w->kcontrol_news[i].name)
-				continue;
+	wlistsize = sizeof(struct snd_soc_dapm_widget_list) +
+			wlistentries * sizeof(struct snd_soc_dapm_widget *);
+	wlist = krealloc(wlist, wlistsize, GFP_KERNEL);
+	if (wlist == NULL) {
+		dev_err(dapm->dev, "ASoC: can't allocate widget list for %s\n",
+			w->name);
+		return -ENOMEM;
+	}
+	wlist->num_widgets = wlistentries;
+	wlist->widgets[wlistentries - 1] = w;
 
-			if (w->kcontrols[i]) {
-				path->kcontrol = w->kcontrols[i];
-				continue;
+	if (!kcontrol) {
+		if (shared) {
+			wname_in_long_name = false;
+			kcname_in_long_name = true;
+		} else {
+			switch (w->id) {
+			case snd_soc_dapm_switch:
+			case snd_soc_dapm_mixer:
+				wname_in_long_name = true;
+				kcname_in_long_name = true;
+				break;
+			case snd_soc_dapm_mixer_named_ctl:
+				wname_in_long_name = false;
+				kcname_in_long_name = true;
+				break;
+			case snd_soc_dapm_mux:
+			case snd_soc_dapm_virt_mux:
+			case snd_soc_dapm_value_mux:
+				wname_in_long_name = true;
+				kcname_in_long_name = false;
+				break;
+			default:
+				kfree(wlist);
+				return -EINVAL;
 			}
+		}
+
+		if (wname_in_long_name && kcname_in_long_name) {
+			name_len = strlen(w->name) - prefix_len + 1 +
+				   strlen(w->kcontrol_news[kci].name) + 1;
 
-			wlistsize = sizeof(struct snd_soc_dapm_widget_list) +
-				    sizeof(struct snd_soc_dapm_widget *),
-			wlist = kzalloc(wlistsize, GFP_KERNEL);
-			if (wlist == NULL) {
-				dev_err(dapm->dev,
-					"ASoC: can't allocate widget list for %s\n",
-					w->name);
+			long_name = kmalloc(name_len, GFP_KERNEL);
+			if (long_name == NULL) {
+				kfree(wlist);
 				return -ENOMEM;
 			}
-			wlist->num_widgets = 1;
-			wlist->widgets[0] = w;
-
-			/* add dapm control with long name.
-			 * for dapm_mixer this is the concatenation of the
-			 * mixer and kcontrol name.
-			 * for dapm_mixer_named_ctl this is simply the
-			 * kcontrol name.
+
+			/*
+			 * The control will get a prefix from the control
+			 * creation process but we're also using the same
+			 * prefix for widgets so cut the prefix off the
+			 * front of the widget name.
 			 */
-			name_len = strlen(w->kcontrol_news[i].name) + 1;
-			if (w->id != snd_soc_dapm_mixer_named_ctl)
-				name_len += 1 + strlen(w->name);
+			snprintf(long_name, name_len, "%s %s",
+				 w->name + prefix_len,
+				 w->kcontrol_news[kci].name);
+			long_name[name_len - 1] = '\0';
+
+			name = long_name;
+		} else if (wname_in_long_name) {
+			long_name = NULL;
+			name = w->name + prefix_len;
+		} else {
+			long_name = NULL;
+			name = w->kcontrol_news[kci].name;
+		}
 
-			path->long_name = kmalloc(name_len, GFP_KERNEL);
+		kcontrol = snd_soc_cnew(&w->kcontrol_news[kci], wlist, name,
+					prefix);
+		ret = snd_ctl_add(card, kcontrol);
+		if (ret < 0) {
+			dev_err(dapm->dev,
+				"ASoC: failed to add widget %s dapm kcontrol %s: %d\n",
+				w->name, name, ret);
+			kfree(wlist);
+			kfree(long_name);
+			return ret;
+		}
 
-			if (path->long_name == NULL) {
-				kfree(wlist);
-				return -ENOMEM;
-			}
+		path->long_name = long_name;
+	}
 
-			switch (w->id) {
-			default:
-				/* The control will get a prefix from
-				 * the control creation process but
-				 * we're also using the same prefix
-				 * for widgets so cut the prefix off
-				 * the front of the widget name.
-				 */
-				snprintf((char *)path->long_name, name_len,
-					 "%s %s", w->name + prefix_len,
-					 w->kcontrol_news[i].name);
-				break;
-			case snd_soc_dapm_mixer_named_ctl:
-				snprintf((char *)path->long_name, name_len,
-					 "%s", w->kcontrol_news[i].name);
-				break;
-			}
+	kcontrol->private_data = wlist;
+	w->kcontrols[kci] = kcontrol;
+	path->kcontrol = kcontrol;
 
-			((char *)path->long_name)[name_len - 1] = '\0';
+	return 0;
+}
 
-			path->kcontrol = snd_soc_cnew(&w->kcontrol_news[i],
-						      wlist, path->long_name,
-						      prefix);
-			ret = snd_ctl_add(card, path->kcontrol);
-			if (ret < 0) {
-				dev_err(dapm->dev, "ASoC: failed to add widget"
-					" %s dapm kcontrol %s: %d\n",
-					w->name, path->long_name, ret);
-				kfree(wlist);
-				kfree(path->long_name);
-				path->long_name = NULL;
-				return ret;
+/* create new dapm mixer control */
+static int dapm_new_mixer(struct snd_soc_dapm_widget *w)
+{
+	int i, ret;
+	struct snd_soc_dapm_path *path;
+
+	/* add kcontrol */
+	for (i = 0; i < w->num_kcontrols; i++) {
+		/* match name */
+		list_for_each_entry(path, &w->sources, list_sink) {
+			/* mixer/mux paths name must match control name */
+			if (path->name != (char *)w->kcontrol_news[i].name)
+				continue;
+
+			if (w->kcontrols[i]) {
+				path->kcontrol = w->kcontrols[i];
+				continue;
 			}
-			w->kcontrols[i] = path->kcontrol;
+
+			ret = dapm_create_or_share_mixmux_kcontrol(w, i, path);
+			if (ret < 0)
+				return ret;
 		}
 	}
-	return ret;
+
+	return 0;
 }
 
 /* create new dapm mux control */
 static int dapm_new_mux(struct snd_soc_dapm_widget *w)
 {
 	struct snd_soc_dapm_context *dapm = w->dapm;
-	struct snd_soc_dapm_path *path = NULL;
-	struct snd_kcontrol *kcontrol;
-	struct snd_card *card = dapm->card->snd_card;
-	const char *prefix;
-	size_t prefix_len;
+	struct snd_soc_dapm_path *path;
 	int ret;
-	struct snd_soc_dapm_widget_list *wlist;
-	int shared, wlistentries;
-	size_t wlistsize;
-	const char *name;
 
 	if (w->num_kcontrols != 1) {
 		dev_err(dapm->dev,
@@ -631,65 +679,19 @@ static int dapm_new_mux(struct snd_soc_dapm_widget *w)
 		return -EINVAL;
 	}
 
-	shared = dapm_is_shared_kcontrol(dapm, w, &w->kcontrol_news[0],
-					 &kcontrol);
-	if (kcontrol) {
-		wlist = kcontrol->private_data;
-		wlistentries = wlist->num_widgets + 1;
-	} else {
-		wlist = NULL;
-		wlistentries = 1;
-	}
-	wlistsize = sizeof(struct snd_soc_dapm_widget_list) +
-		wlistentries * sizeof(struct snd_soc_dapm_widget *),
-	wlist = krealloc(wlist, wlistsize, GFP_KERNEL);
-	if (wlist == NULL) {
-		dev_err(dapm->dev,
-			"ASoC: can't allocate widget list for %s\n", w->name);
-		return -ENOMEM;
-	}
-	wlist->num_widgets = wlistentries;
-	wlist->widgets[wlistentries - 1] = w;
-
-	if (!kcontrol) {
-		if (dapm->codec)
-			prefix = dapm->codec->name_prefix;
-		else
-			prefix = NULL;
-
-		if (shared) {
-			name = w->kcontrol_news[0].name;
-			prefix_len = 0;
-		} else {
-			name = w->name;
-			if (prefix)
-				prefix_len = strlen(prefix) + 1;
-			else
-				prefix_len = 0;
-		}
-
-		/*
-		 * The control will get a prefix from the control creation
-		 * process but we're also using the same prefix for widgets so
-		 * cut the prefix off the front of the widget name.
-		 */
-		kcontrol = snd_soc_cnew(&w->kcontrol_news[0], wlist,
-					name + prefix_len, prefix);
-		ret = snd_ctl_add(card, kcontrol);
-		if (ret < 0) {
-			dev_err(dapm->dev, "ASoC: failed to add kcontrol %s: %d\n",
-				w->name, ret);
-			kfree(wlist);
-			return ret;
-		}
+	path = list_first_entry(&w->sources, struct snd_soc_dapm_path,
+				list_sink);
+	if (!path) {
+		dev_err(dapm->dev, "ASoC: mux %s has no paths\n", w->name);
+		return -EINVAL;
 	}
 
-	kcontrol->private_data = wlist;
-
-	w->kcontrols[0] = kcontrol;
+	ret = dapm_create_or_share_mixmux_kcontrol(w, 0, path);
+	if (ret < 0)
+		return ret;
 
 	list_for_each_entry(path, &w->sources, list_sink)
-		path->kcontrol = kcontrol;
+		path->kcontrol = w->kcontrols[0];
 
 	return 0;
 }
@@ -705,14 +707,33 @@ static int dapm_new_pga(struct snd_soc_dapm_widget *w)
 }
 
 /* reset 'walked' bit for each dapm path */
-static inline void dapm_clear_walk(struct snd_soc_dapm_context *dapm)
+static void dapm_clear_walk_output(struct snd_soc_dapm_context *dapm,
+				   struct list_head *sink)
 {
 	struct snd_soc_dapm_path *p;
 
-	list_for_each_entry(p, &dapm->card->paths, list)
-		p->walked = 0;
+	list_for_each_entry(p, sink, list_source) {
+		if (p->walked) {
+			p->walked = 0;
+			dapm_clear_walk_output(dapm, &p->sink->sinks);
+		}
+	}
+}
+
+static void dapm_clear_walk_input(struct snd_soc_dapm_context *dapm,
+				  struct list_head *source)
+{
+	struct snd_soc_dapm_path *p;
+
+	list_for_each_entry(p, source, list_sink) {
+		if (p->walked) {
+			p->walked = 0;
+			dapm_clear_walk_input(dapm, &p->source->sources);
+		}
+	}
 }
 
+
 /* We implement power down on suspend by checking the power state of
  * the ALSA card - when we are suspending the ALSA state for the card
  * is set to D3.
@@ -831,6 +852,9 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget,
 		if (path->weak)
 			continue;
 
+		if (path->walking)
+			return 1;
+
 		if (path->walked)
 			continue;
 
@@ -838,6 +862,7 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget,
 
 		if (path->sink && path->connect) {
 			path->walked = 1;
+			path->walking = 1;
 
 			/* do we need to add this widget to the list ? */
 			if (list) {
@@ -847,11 +872,14 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget,
 					dev_err(widget->dapm->dev,
 						"ASoC: could not add widget %s\n",
 						widget->name);
+					path->walking = 0;
 					return con;
 				}
 			}
 
 			con += is_connected_output_ep(path->sink, list);
+
+			path->walking = 0;
 		}
 	}
 
@@ -931,6 +959,9 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget,
 		if (path->weak)
 			continue;
 
+		if (path->walking)
+			return 1;
+
 		if (path->walked)
 			continue;
 
@@ -938,6 +969,7 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget,
 
 		if (path->source && path->connect) {
 			path->walked = 1;
+			path->walking = 1;
 
 			/* do we need to add this widget to the list ? */
 			if (list) {
@@ -947,11 +979,14 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget,
 					dev_err(widget->dapm->dev,
 						"ASoC: could not add widget %s\n",
 						widget->name);
+					path->walking = 0;
 					return con;
 				}
 			}
 
 			con += is_connected_input_ep(path->source, list);
+
+			path->walking = 0;
 		}
 	}
 
@@ -981,13 +1016,17 @@ int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream,
 	mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
 	dapm_reset(card);
 
-	if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+	if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
 		paths = is_connected_output_ep(dai->playback_widget, list);
-	else
+		dapm_clear_walk_output(&card->dapm,
+				       &dai->playback_widget->sinks);
+	} else {
 		paths = is_connected_input_ep(dai->capture_widget, list);
+		dapm_clear_walk_input(&card->dapm,
+				      &dai->capture_widget->sources);
+	}
 
 	trace_snd_soc_dapm_connected(paths, stream);
-	dapm_clear_walk(&card->dapm);
 	mutex_unlock(&card->dapm_mutex);
 
 	return paths;
@@ -1090,9 +1129,9 @@ static int dapm_generic_check_power(struct snd_soc_dapm_widget *w)
 	DAPM_UPDATE_STAT(w, power_checks);
 
 	in = is_connected_input_ep(w, NULL);
-	dapm_clear_walk(w->dapm);
+	dapm_clear_walk_input(w->dapm, &w->sources);
 	out = is_connected_output_ep(w, NULL);
-	dapm_clear_walk(w->dapm);
+	dapm_clear_walk_output(w->dapm, &w->sinks);
 	return out != 0 && in != 0;
 }
 
@@ -1115,7 +1154,7 @@ static int dapm_adc_check_power(struct snd_soc_dapm_widget *w)
 
 	if (w->active) {
 		in = is_connected_input_ep(w, NULL);
-		dapm_clear_walk(w->dapm);
+		dapm_clear_walk_input(w->dapm, &w->sources);
 		return in != 0;
 	} else {
 		return dapm_generic_check_power(w);
@@ -1131,7 +1170,7 @@ static int dapm_dac_check_power(struct snd_soc_dapm_widget *w)
 
 	if (w->active) {
 		out = is_connected_output_ep(w, NULL);
-		dapm_clear_walk(w->dapm);
+		dapm_clear_walk_output(w->dapm, &w->sinks);
 		return out != 0;
 	} else {
 		return dapm_generic_check_power(w);
@@ -1163,8 +1202,6 @@ static int dapm_supply_check_power(struct snd_soc_dapm_widget *w)
 			return 1;
 	}
 
-	dapm_clear_walk(w->dapm);
-
 	return 0;
 }
 
@@ -1745,9 +1782,9 @@ static ssize_t dapm_widget_power_read_file(struct file *file,
 		return -ENOMEM;
 
 	in = is_connected_input_ep(w, NULL);
-	dapm_clear_walk(w->dapm);
+	dapm_clear_walk_input(w->dapm, &w->sources);
 	out = is_connected_output_ep(w, NULL);
-	dapm_clear_walk(w->dapm);
+	dapm_clear_walk_output(w->dapm, &w->sinks);
 
 	ret = snprintf(buf, PAGE_SIZE, "%s: %s%s  in %d out %d",
 		       w->name, w->power ? "On" : "Off",
@@ -3123,7 +3160,6 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
 		break;
 	}
 
-	dapm->n_widgets++;
 	w->dapm = dapm;
 	w->codec = dapm->codec;
 	w->platform = dapm->platform;
diff --git a/sound/soc/soc-dmaengine-pcm.c b/sound/soc/soc-dmaengine-pcm.c
index 111b7d92..a9a300a 100644
--- a/sound/soc/soc-dmaengine-pcm.c
+++ b/sound/soc/soc-dmaengine-pcm.c
@@ -33,8 +33,6 @@ struct dmaengine_pcm_runtime_data {
 	dma_cookie_t cookie;
 
 	unsigned int pos;
-
-	void *data;
 };
 
 static inline struct dmaengine_pcm_runtime_data *substream_to_prtd(
@@ -43,33 +41,6 @@ static inline struct dmaengine_pcm_runtime_data *substream_to_prtd(
 	return substream->runtime->private_data;
 }
 
-/**
- * snd_dmaengine_pcm_set_data - Set dmaengine substream private data
- * @substream: PCM substream
- * @data: Data to set
- */
-void snd_dmaengine_pcm_set_data(struct snd_pcm_substream *substream, void *data)
-{
-	struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
-
-	prtd->data = data;
-}
-EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_set_data);
-
-/**
- * snd_dmaengine_pcm_get_data - Get dmaeinge substream private data
- * @substream: PCM substream
- *
- * Returns the data previously set with snd_dmaengine_pcm_set_data
- */
-void *snd_dmaengine_pcm_get_data(struct snd_pcm_substream *substream)
-{
-	struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
-
-	return prtd->data;
-}
-EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_get_data);
-
 struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream)
 {
 	struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
@@ -118,10 +89,49 @@ int snd_hwparams_to_dma_slave_config(const struct snd_pcm_substream *substream,
 		slave_config->src_addr_width = buswidth;
 	}
 
+	slave_config->device_fc = false;
+
 	return 0;
 }
 EXPORT_SYMBOL_GPL(snd_hwparams_to_dma_slave_config);
 
+/**
+ * snd_dmaengine_pcm_set_config_from_dai_data() - Initializes a dma slave config
+ *  using DAI DMA data.
+ * @substream: PCM substream
+ * @dma_data: DAI DMA data
+ * @slave_config: DMA slave configuration
+ *
+ * Initializes the {dst,src}_addr, {dst,src}_maxburst, {dst,src}_addr_width and
+ * slave_id fields of the DMA slave config from the same fields of the DAI DMA
+ * data struct. The src and dst fields will be initialized depending on the
+ * direction of the substream. If the substream is a playback stream the dst
+ * fields will be initialized, if it is a capture stream the src fields will be
+ * initialized. The {dst,src}_addr_width field will only be initialized if the
+ * addr_width field of the DAI DMA data struct is not equal to
+ * DMA_SLAVE_BUSWIDTH_UNDEFINED.
+ */
+void snd_dmaengine_pcm_set_config_from_dai_data(
+	const struct snd_pcm_substream *substream,
+	const struct snd_dmaengine_dai_dma_data *dma_data,
+	struct dma_slave_config *slave_config)
+{
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		slave_config->dst_addr = dma_data->addr;
+		slave_config->dst_maxburst = dma_data->maxburst;
+		if (dma_data->addr_width != DMA_SLAVE_BUSWIDTH_UNDEFINED)
+			slave_config->dst_addr_width = dma_data->addr_width;
+	} else {
+		slave_config->src_addr = dma_data->addr;
+		slave_config->src_maxburst = dma_data->maxburst;
+		if (dma_data->addr_width != DMA_SLAVE_BUSWIDTH_UNDEFINED)
+			slave_config->src_addr_width = dma_data->addr_width;
+	}
+
+	slave_config->slave_id = dma_data->slave_id;
+}
+EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_set_config_from_dai_data);
+
 static void dmaengine_pcm_dma_complete(void *arg)
 {
 	struct snd_pcm_substream *substream = arg;
diff --git a/sound/soc/soc-io.c b/sound/soc/soc-io.c
index 29183ef..8ca9ecc 100644
--- a/sound/soc/soc-io.c
+++ b/sound/soc/soc-io.c
@@ -158,10 +158,7 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
 		return -EINVAL;
 	}
 
-	if (IS_ERR(codec->control_data))
-		return PTR_ERR(codec->control_data);
-
-	return 0;
+	return PTR_RET(codec->control_data);
 }
 EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io);
 #else
diff --git a/sound/soc/spear/spdif_in.c b/sound/soc/spear/spdif_in.c
index c7c4b20..14d57e8 100644
--- a/sound/soc/spear/spdif_in.c
+++ b/sound/soc/spear/spdif_in.c
@@ -170,6 +170,10 @@ struct snd_soc_dai_driver spdif_in_dai = {
 	.ops = &spdif_in_dai_ops,
 };
 
+static const struct snd_soc_component_driver spdif_in_component = {
+	.name		= "spdif-in",
+};
+
 static irqreturn_t spdif_in_irq(int irq, void *arg)
 {
 	struct spdif_in_dev *host = (struct spdif_in_dev *)arg;
@@ -258,7 +262,8 @@ static int spdif_in_probe(struct platform_device *pdev)
 		return ret;
 	}
 
-	ret = snd_soc_register_dai(&pdev->dev, &spdif_in_dai);
+	ret = snd_soc_register_component(&pdev->dev, &spdif_in_component,
+					 &spdif_in_dai, 1);
 	if (ret != 0) {
 		clk_put(host->clk);
 		return ret;
@@ -271,7 +276,7 @@ static int spdif_in_remove(struct platform_device *pdev)
 {
 	struct spdif_in_dev *host = dev_get_drvdata(&pdev->dev);
 
-	snd_soc_unregister_dai(&pdev->dev);
+	snd_soc_unregister_component(&pdev->dev);
 	dev_set_drvdata(&pdev->dev, NULL);
 
 	clk_put(host->clk);
diff --git a/sound/soc/spear/spdif_out.c b/sound/soc/spear/spdif_out.c
index 5eac4cd..1e3c3dd 100644
--- a/sound/soc/spear/spdif_out.c
+++ b/sound/soc/spear/spdif_out.c
@@ -270,6 +270,10 @@ static struct snd_soc_dai_driver spdif_out_dai = {
 	.ops = &spdif_out_dai_ops,
 };
 
+static const struct snd_soc_component_driver spdif_out_component = {
+	.name		= "spdif-out",
+};
+
 static int spdif_out_probe(struct platform_device *pdev)
 {
 	struct spdif_out_dev *host;
@@ -314,7 +318,8 @@ static int spdif_out_probe(struct platform_device *pdev)
 
 	dev_set_drvdata(&pdev->dev, host);
 
-	ret = snd_soc_register_dai(&pdev->dev, &spdif_out_dai);
+	ret = snd_soc_register_component(&pdev->dev, &spdif_out_component,
+					 &spdif_out_dai, 1);
 	if (ret != 0) {
 		clk_put(host->clk);
 		return ret;
@@ -327,7 +332,7 @@ static int spdif_out_remove(struct platform_device *pdev)
 {
 	struct spdif_out_dev *host = dev_get_drvdata(&pdev->dev);
 
-	snd_soc_unregister_dai(&pdev->dev);
+	snd_soc_unregister_component(&pdev->dev);
 	dev_set_drvdata(&pdev->dev, NULL);
 
 	clk_put(host->clk);
diff --git a/sound/soc/spear/spear_pcm.c b/sound/soc/spear/spear_pcm.c
index 9b76cc5..bfbcc1f 100644
--- a/sound/soc/spear/spear_pcm.c
+++ b/sound/soc/spear/spear_pcm.c
@@ -25,7 +25,7 @@
 #include <sound/soc.h>
 #include <sound/spear_dma.h>
 
-struct snd_pcm_hardware spear_pcm_hardware = {
+static struct snd_pcm_hardware spear_pcm_hardware = {
 	.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),
@@ -64,21 +64,7 @@ static int spear_pcm_open(struct snd_pcm_substream *substream)
 	if (ret)
 		return ret;
 
-	ret = snd_dmaengine_pcm_open(substream, dma_data->filter, dma_data);
-	if (ret)
-		return ret;
-
-	snd_dmaengine_pcm_set_data(substream, dma_data);
-
-	return 0;
-}
-
-static int spear_pcm_close(struct snd_pcm_substream *substream)
-{
-
-	snd_dmaengine_pcm_close(substream);
-
-	return 0;
+	return snd_dmaengine_pcm_open(substream, dma_data->filter, dma_data)
 }
 
 static int spear_pcm_mmap(struct snd_pcm_substream *substream,
@@ -93,7 +79,7 @@ static int spear_pcm_mmap(struct snd_pcm_substream *substream,
 
 static struct snd_pcm_ops spear_pcm_ops = {
 	.open		= spear_pcm_open,
-	.close		= spear_pcm_close,
+	.close		= snd_dmaengine_pcm_close,
 	.ioctl		= snd_pcm_lib_ioctl,
 	.hw_params	= spear_pcm_hw_params,
 	.hw_free	= spear_pcm_hw_free,
@@ -149,9 +135,9 @@ static void spear_pcm_free(struct snd_pcm *pcm)
 
 static u64 spear_pcm_dmamask = DMA_BIT_MASK(32);
 
-static int spear_pcm_new(struct snd_card *card,
-		struct snd_soc_dai *dai, struct snd_pcm *pcm)
+static int spear_pcm_new(struct snd_soc_pcm_runtime *rtd)
 {
+	struct snd_card *card = rtd->card->snd_card;
 	int ret;
 
 	if (!card->dev->dma_mask)
@@ -159,16 +145,16 @@ static int spear_pcm_new(struct snd_card *card,
 	if (!card->dev->coherent_dma_mask)
 		card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
 
-	if (dai->driver->playback.channels_min) {
-		ret = spear_pcm_preallocate_dma_buffer(pcm,
+	if (rtd->cpu_dai->driver->playback.channels_min) {
+		ret = spear_pcm_preallocate_dma_buffer(rtd->pcm,
 				SNDRV_PCM_STREAM_PLAYBACK,
 				spear_pcm_hardware.buffer_bytes_max);
 		if (ret)
 			return ret;
 	}
 
-	if (dai->driver->capture.channels_min) {
-		ret = spear_pcm_preallocate_dma_buffer(pcm,
+	if (rtd->cpu_dai->driver->capture.channels_min) {
+		ret = spear_pcm_preallocate_dma_buffer(rtd->pcm,
 				SNDRV_PCM_STREAM_CAPTURE,
 				spear_pcm_hardware.buffer_bytes_max);
 		if (ret)
@@ -178,7 +164,7 @@ static int spear_pcm_new(struct snd_card *card,
 	return 0;
 }
 
-struct snd_soc_platform_driver spear_soc_platform = {
+static struct snd_soc_platform_driver spear_soc_platform = {
 	.ops		=	&spear_pcm_ops,
 	.pcm_new	=	spear_pcm_new,
 	.pcm_free	=	spear_pcm_free,
diff --git a/sound/soc/tegra/tegra20_ac97.c b/sound/soc/tegra/tegra20_ac97.c
index 336dcdd..2f70ea7 100644
--- a/sound/soc/tegra/tegra20_ac97.c
+++ b/sound/soc/tegra/tegra20_ac97.c
@@ -35,6 +35,7 @@
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
+#include <sound/dmaengine_pcm.h>
 
 #include "tegra_asoc_utils.h"
 #include "tegra20_ac97.h"
@@ -248,6 +249,10 @@ static struct snd_soc_dai_driver tegra20_ac97_dai = {
 	.ops = &tegra20_ac97_dai_ops,
 };
 
+static const struct snd_soc_component_driver tegra20_ac97_component = {
+	.name		= DRV_NAME,
+};
+
 static bool tegra20_ac97_wr_rd_reg(struct device *dev, unsigned int reg)
 {
 	switch (reg) {
@@ -389,16 +394,17 @@ static int tegra20_ac97_platform_probe(struct platform_device *pdev)
 	}
 
 	ac97->capture_dma_data.addr = mem->start + TEGRA20_AC97_FIFO_RX1;
-	ac97->capture_dma_data.wrap = 4;
-	ac97->capture_dma_data.width = 32;
-	ac97->capture_dma_data.req_sel = of_dma[1];
+	ac97->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+	ac97->capture_dma_data.maxburst = 4;
+	ac97->capture_dma_data.slave_id = of_dma[1];
 
 	ac97->playback_dma_data.addr = mem->start + TEGRA20_AC97_FIFO_TX1;
-	ac97->playback_dma_data.wrap = 4;
-	ac97->playback_dma_data.width = 32;
-	ac97->playback_dma_data.req_sel = of_dma[1];
+	ac97->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+	ac97->capture_dma_data.maxburst = 4;
+	ac97->capture_dma_data.slave_id = of_dma[0];
 
-	ret = snd_soc_register_dais(&pdev->dev, &tegra20_ac97_dai, 1);
+	ret = snd_soc_register_component(&pdev->dev, &tegra20_ac97_component,
+					 &tegra20_ac97_dai, 1);
 	if (ret) {
 		dev_err(&pdev->dev, "Could not register DAI: %d\n", ret);
 		ret = -ENOMEM;
@@ -408,7 +414,7 @@ static int tegra20_ac97_platform_probe(struct platform_device *pdev)
 	ret = tegra_pcm_platform_register(&pdev->dev);
 	if (ret) {
 		dev_err(&pdev->dev, "Could not register PCM: %d\n", ret);
-		goto err_unregister_dai;
+		goto err_unregister_component;
 	}
 
 	ret = tegra_asoc_utils_init(&ac97->util_data, &pdev->dev);
@@ -434,8 +440,8 @@ err_asoc_utils_fini:
 	tegra_asoc_utils_fini(&ac97->util_data);
 err_unregister_pcm:
 	tegra_pcm_platform_unregister(&pdev->dev);
-err_unregister_dai:
-	snd_soc_unregister_dai(&pdev->dev);
+err_unregister_component:
+	snd_soc_unregister_component(&pdev->dev);
 err_clk_put:
 	clk_put(ac97->clk_ac97);
 err:
@@ -447,7 +453,7 @@ static int tegra20_ac97_platform_remove(struct platform_device *pdev)
 	struct tegra20_ac97 *ac97 = dev_get_drvdata(&pdev->dev);
 
 	tegra_pcm_platform_unregister(&pdev->dev);
-	snd_soc_unregister_dai(&pdev->dev);
+	snd_soc_unregister_component(&pdev->dev);
 
 	tegra_asoc_utils_fini(&ac97->util_data);
 
diff --git a/sound/soc/tegra/tegra20_ac97.h b/sound/soc/tegra/tegra20_ac97.h
index dddc682..4acb3aa 100644
--- a/sound/soc/tegra/tegra20_ac97.h
+++ b/sound/soc/tegra/tegra20_ac97.h
@@ -85,8 +85,8 @@
 
 struct tegra20_ac97 {
 	struct clk *clk_ac97;
-	struct tegra_pcm_dma_params capture_dma_data;
-	struct tegra_pcm_dma_params playback_dma_data;
+	struct snd_dmaengine_dai_dma_data capture_dma_data;
+	struct snd_dmaengine_dai_dma_data playback_dma_data;
 	struct regmap *regmap;
 	int reset_gpio;
 	int sync_gpio;
diff --git a/sound/soc/tegra/tegra20_i2s.c b/sound/soc/tegra/tegra20_i2s.c
index caa772d..52af7f6 100644
--- a/sound/soc/tegra/tegra20_i2s.c
+++ b/sound/soc/tegra/tegra20_i2s.c
@@ -41,6 +41,7 @@
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
+#include <sound/dmaengine_pcm.h>
 
 #include "tegra20_i2s.h"
 
@@ -276,6 +277,10 @@ static const struct snd_soc_dai_driver tegra20_i2s_dai_template = {
 	.symmetric_rates = 1,
 };
 
+static const struct snd_soc_component_driver tegra20_i2s_component = {
+	.name		= DRV_NAME,
+};
+
 static bool tegra20_i2s_wr_rd_reg(struct device *dev, unsigned int reg)
 {
 	switch (reg) {
@@ -403,14 +408,14 @@ static int tegra20_i2s_platform_probe(struct platform_device *pdev)
 	}
 
 	i2s->capture_dma_data.addr = mem->start + TEGRA20_I2S_FIFO2;
-	i2s->capture_dma_data.wrap = 4;
-	i2s->capture_dma_data.width = 32;
-	i2s->capture_dma_data.req_sel = dma_ch;
+	i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+	i2s->capture_dma_data.maxburst = 4;
+	i2s->capture_dma_data.slave_id = dma_ch;
 
 	i2s->playback_dma_data.addr = mem->start + TEGRA20_I2S_FIFO1;
-	i2s->playback_dma_data.wrap = 4;
-	i2s->playback_dma_data.width = 32;
-	i2s->playback_dma_data.req_sel = dma_ch;
+	i2s->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+	i2s->playback_dma_data.maxburst = 4;
+	i2s->playback_dma_data.slave_id = dma_ch;
 
 	pm_runtime_enable(&pdev->dev);
 	if (!pm_runtime_enabled(&pdev->dev)) {
@@ -419,7 +424,8 @@ static int tegra20_i2s_platform_probe(struct platform_device *pdev)
 			goto err_pm_disable;
 	}
 
-	ret = snd_soc_register_dai(&pdev->dev, &i2s->dai);
+	ret = snd_soc_register_component(&pdev->dev, &tegra20_i2s_component,
+					 &i2s->dai, 1);
 	if (ret) {
 		dev_err(&pdev->dev, "Could not register DAI: %d\n", ret);
 		ret = -ENOMEM;
@@ -429,13 +435,13 @@ static int tegra20_i2s_platform_probe(struct platform_device *pdev)
 	ret = tegra_pcm_platform_register(&pdev->dev);
 	if (ret) {
 		dev_err(&pdev->dev, "Could not register PCM: %d\n", ret);
-		goto err_unregister_dai;
+		goto err_unregister_component;
 	}
 
 	return 0;
 
-err_unregister_dai:
-	snd_soc_unregister_dai(&pdev->dev);
+err_unregister_component:
+	snd_soc_unregister_component(&pdev->dev);
 err_suspend:
 	if (!pm_runtime_status_suspended(&pdev->dev))
 		tegra20_i2s_runtime_suspend(&pdev->dev);
@@ -456,7 +462,7 @@ static int tegra20_i2s_platform_remove(struct platform_device *pdev)
 		tegra20_i2s_runtime_suspend(&pdev->dev);
 
 	tegra_pcm_platform_unregister(&pdev->dev);
-	snd_soc_unregister_dai(&pdev->dev);
+	snd_soc_unregister_component(&pdev->dev);
 
 	clk_put(i2s->clk_i2s);
 
diff --git a/sound/soc/tegra/tegra20_i2s.h b/sound/soc/tegra/tegra20_i2s.h
index 7299587..fa6c29c 100644
--- a/sound/soc/tegra/tegra20_i2s.h
+++ b/sound/soc/tegra/tegra20_i2s.h
@@ -155,8 +155,8 @@
 struct tegra20_i2s {
 	struct snd_soc_dai_driver dai;
 	struct clk *clk_i2s;
-	struct tegra_pcm_dma_params capture_dma_data;
-	struct tegra_pcm_dma_params playback_dma_data;
+	struct snd_dmaengine_dai_dma_data capture_dma_data;
+	struct snd_dmaengine_dai_dma_data playback_dma_data;
 	struct regmap *regmap;
 };
 
diff --git a/sound/soc/tegra/tegra20_spdif.c b/sound/soc/tegra/tegra20_spdif.c
index 04771d1..5eaa12c 100644
--- a/sound/soc/tegra/tegra20_spdif.c
+++ b/sound/soc/tegra/tegra20_spdif.c
@@ -32,6 +32,7 @@
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
+#include <sound/dmaengine_pcm.h>
 
 #include "tegra20_spdif.h"
 
@@ -182,6 +183,10 @@ static struct snd_soc_dai_driver tegra20_spdif_dai = {
 	.ops = &tegra20_spdif_dai_ops,
 };
 
+static const struct snd_soc_component_driver tegra20_spdif_component = {
+	.name		= DRV_NAME,
+};
+
 static bool tegra20_spdif_wr_rd_reg(struct device *dev, unsigned int reg)
 {
 	switch (reg) {
@@ -318,9 +323,9 @@ static int tegra20_spdif_platform_probe(struct platform_device *pdev)
 	}
 
 	spdif->playback_dma_data.addr = mem->start + TEGRA20_SPDIF_DATA_OUT;
-	spdif->playback_dma_data.wrap = 4;
-	spdif->playback_dma_data.width = 32;
-	spdif->playback_dma_data.req_sel = dmareq->start;
+	spdif->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+	spdif->capture_dma_data.maxburst = 4;
+	spdif->playback_dma_data.slave_id = dmareq->start;
 
 	pm_runtime_enable(&pdev->dev);
 	if (!pm_runtime_enabled(&pdev->dev)) {
@@ -329,7 +334,8 @@ static int tegra20_spdif_platform_probe(struct platform_device *pdev)
 			goto err_pm_disable;
 	}
 
-	ret = snd_soc_register_dai(&pdev->dev, &tegra20_spdif_dai);
+	ret = snd_soc_register_component(&pdev->dev, &tegra20_spdif_component,
+				   &tegra20_spdif_dai, 1);
 	if (ret) {
 		dev_err(&pdev->dev, "Could not register DAI: %d\n", ret);
 		ret = -ENOMEM;
@@ -339,13 +345,13 @@ static int tegra20_spdif_platform_probe(struct platform_device *pdev)
 	ret = tegra_pcm_platform_register(&pdev->dev);
 	if (ret) {
 		dev_err(&pdev->dev, "Could not register PCM: %d\n", ret);
-		goto err_unregister_dai;
+		goto err_unregister_component;
 	}
 
 	return 0;
 
-err_unregister_dai:
-	snd_soc_unregister_dai(&pdev->dev);
+err_unregister_component:
+	snd_soc_unregister_component(&pdev->dev);
 err_suspend:
 	if (!pm_runtime_status_suspended(&pdev->dev))
 		tegra20_spdif_runtime_suspend(&pdev->dev);
@@ -366,7 +372,7 @@ static int tegra20_spdif_platform_remove(struct platform_device *pdev)
 		tegra20_spdif_runtime_suspend(&pdev->dev);
 
 	tegra_pcm_platform_unregister(&pdev->dev);
-	snd_soc_unregister_dai(&pdev->dev);
+	snd_soc_unregister_component(&pdev->dev);
 
 	clk_put(spdif->clk_spdif_out);
 
diff --git a/sound/soc/tegra/tegra20_spdif.h b/sound/soc/tegra/tegra20_spdif.h
index b48d699..85a9aef 100644
--- a/sound/soc/tegra/tegra20_spdif.h
+++ b/sound/soc/tegra/tegra20_spdif.h
@@ -462,8 +462,8 @@
 
 struct tegra20_spdif {
 	struct clk *clk_spdif_out;
-	struct tegra_pcm_dma_params capture_dma_data;
-	struct tegra_pcm_dma_params playback_dma_data;
+	struct snd_dmaengine_dai_dma_data capture_dma_data;
+	struct snd_dmaengine_dai_dma_data playback_dma_data;
 	struct regmap *regmap;
 };
 
diff --git a/sound/soc/tegra/tegra30_ahub.c b/sound/soc/tegra/tegra30_ahub.c
index e5cfb4a..23e592f 100644
--- a/sound/soc/tegra/tegra30_ahub.c
+++ b/sound/soc/tegra/tegra30_ahub.c
@@ -95,8 +95,8 @@ static int tegra30_ahub_runtime_resume(struct device *dev)
 }
 
 int tegra30_ahub_allocate_rx_fifo(enum tegra30_ahub_rxcif *rxcif,
-				  unsigned long *fiforeg,
-				  unsigned long *reqsel)
+				  dma_addr_t *fiforeg,
+				  unsigned int *reqsel)
 {
 	int channel;
 	u32 reg, val;
@@ -178,8 +178,8 @@ int tegra30_ahub_free_rx_fifo(enum tegra30_ahub_rxcif rxcif)
 EXPORT_SYMBOL_GPL(tegra30_ahub_free_rx_fifo);
 
 int tegra30_ahub_allocate_tx_fifo(enum tegra30_ahub_txcif *txcif,
-				  unsigned long *fiforeg,
-				  unsigned long *reqsel)
+				  dma_addr_t *fiforeg,
+				  unsigned int *reqsel)
 {
 	int channel;
 	u32 reg, val;
@@ -287,16 +287,27 @@ int tegra30_ahub_unset_rx_cif_source(enum tegra30_ahub_rxcif rxcif)
 }
 EXPORT_SYMBOL_GPL(tegra30_ahub_unset_rx_cif_source);
 
-static const char * const configlink_clocks[] = {
-	"i2s0",
-	"i2s1",
-	"i2s2",
-	"i2s3",
-	"i2s4",
-	"dam0",
-	"dam1",
-	"dam2",
-	"spdif_in",
+#define CLK_LIST_MASK_TEGRA30	BIT(0)
+#define CLK_LIST_MASK_TEGRA114	BIT(1)
+
+#define CLK_LIST_MASK_TEGRA30_OR_LATER \
+		(CLK_LIST_MASK_TEGRA30 | CLK_LIST_MASK_TEGRA114)
+
+static const struct {
+	const char *clk_name;
+	u32 clk_list_mask;
+} configlink_clocks[] = {
+	{ "i2s0", CLK_LIST_MASK_TEGRA30_OR_LATER },
+	{ "i2s1", CLK_LIST_MASK_TEGRA30_OR_LATER },
+	{ "i2s2", CLK_LIST_MASK_TEGRA30_OR_LATER },
+	{ "i2s3", CLK_LIST_MASK_TEGRA30_OR_LATER },
+	{ "i2s4", CLK_LIST_MASK_TEGRA30_OR_LATER },
+	{ "dam0", CLK_LIST_MASK_TEGRA30_OR_LATER },
+	{ "dam1", CLK_LIST_MASK_TEGRA30_OR_LATER },
+	{ "dam2", CLK_LIST_MASK_TEGRA30_OR_LATER },
+	{ "spdif_in", CLK_LIST_MASK_TEGRA30_OR_LATER },
+	{ "amx", CLK_LIST_MASK_TEGRA114 },
+	{ "adx", CLK_LIST_MASK_TEGRA114 },
 };
 
 #define LAST_REG(name) \
@@ -424,8 +435,24 @@ static const struct regmap_config tegra30_ahub_ahub_regmap_config = {
 	.cache_type = REGCACHE_RBTREE,
 };
 
+static struct tegra30_ahub_soc_data soc_data_tegra30 = {
+	.clk_list_mask = CLK_LIST_MASK_TEGRA30,
+};
+
+static struct tegra30_ahub_soc_data soc_data_tegra114 = {
+	.clk_list_mask = CLK_LIST_MASK_TEGRA114,
+};
+
+static const struct of_device_id tegra30_ahub_of_match[] = {
+	{ .compatible = "nvidia,tegra114-ahub", .data = &soc_data_tegra114 },
+	{ .compatible = "nvidia,tegra30-ahub",  .data = &soc_data_tegra30 },
+	{},
+};
+
 static int tegra30_ahub_probe(struct platform_device *pdev)
 {
+	const struct of_device_id *match;
+	const struct tegra30_ahub_soc_data *soc_data;
 	struct clk *clk;
 	int i;
 	struct resource *res0, *res1, *region;
@@ -436,16 +463,24 @@ static int tegra30_ahub_probe(struct platform_device *pdev)
 	if (ahub)
 		return -ENODEV;
 
+	match = of_match_device(tegra30_ahub_of_match, &pdev->dev);
+	if (!match)
+		return -EINVAL;
+	soc_data = match->data;
+
 	/*
 	 * The AHUB hosts a register bus: the "configlink". For this to
 	 * operate correctly, all devices on this bus must be out of reset.
 	 * Ensure that here.
 	 */
 	for (i = 0; i < ARRAY_SIZE(configlink_clocks); i++) {
-		clk = clk_get(&pdev->dev, configlink_clocks[i]);
+		if (!(configlink_clocks[i].clk_list_mask &
+					soc_data->clk_list_mask))
+			continue;
+		clk = clk_get(&pdev->dev, configlink_clocks[i].clk_name);
 		if (IS_ERR(clk)) {
 			dev_err(&pdev->dev, "Can't get clock %s\n",
-				configlink_clocks[i]);
+				configlink_clocks[i].clk_name);
 			ret = PTR_ERR(clk);
 			goto err;
 		}
@@ -592,11 +627,6 @@ static int tegra30_ahub_remove(struct platform_device *pdev)
 	return 0;
 }
 
-static const struct of_device_id tegra30_ahub_of_match[] = {
-	{ .compatible = "nvidia,tegra30-ahub", },
-	{},
-};
-
 static const struct dev_pm_ops tegra30_ahub_pm_ops = {
 	SET_RUNTIME_PM_OPS(tegra30_ahub_runtime_suspend,
 			   tegra30_ahub_runtime_resume, NULL)
diff --git a/sound/soc/tegra/tegra30_ahub.h b/sound/soc/tegra/tegra30_ahub.h
index e690e2e..09766cd 100644
--- a/sound/soc/tegra/tegra30_ahub.h
+++ b/sound/soc/tegra/tegra30_ahub.h
@@ -451,15 +451,15 @@ enum tegra30_ahub_rxcif {
 };
 
 extern int tegra30_ahub_allocate_rx_fifo(enum tegra30_ahub_rxcif *rxcif,
-					 unsigned long *fiforeg,
-					 unsigned long *reqsel);
+					 dma_addr_t *fiforeg,
+					 unsigned int *reqsel);
 extern int tegra30_ahub_enable_rx_fifo(enum tegra30_ahub_rxcif rxcif);
 extern int tegra30_ahub_disable_rx_fifo(enum tegra30_ahub_rxcif rxcif);
 extern int tegra30_ahub_free_rx_fifo(enum tegra30_ahub_rxcif rxcif);
 
 extern int tegra30_ahub_allocate_tx_fifo(enum tegra30_ahub_txcif *txcif,
-					 unsigned long *fiforeg,
-					 unsigned long *reqsel);
+					 dma_addr_t *fiforeg,
+					 unsigned int *reqsel);
 extern int tegra30_ahub_enable_tx_fifo(enum tegra30_ahub_txcif txcif);
 extern int tegra30_ahub_disable_tx_fifo(enum tegra30_ahub_txcif txcif);
 extern int tegra30_ahub_free_tx_fifo(enum tegra30_ahub_txcif txcif);
@@ -468,7 +468,23 @@ extern int tegra30_ahub_set_rx_cif_source(enum tegra30_ahub_rxcif rxcif,
 					  enum tegra30_ahub_txcif txcif);
 extern int tegra30_ahub_unset_rx_cif_source(enum tegra30_ahub_rxcif rxcif);
 
+struct tegra30_ahub_soc_data {
+	u32 clk_list_mask;
+	/*
+	 * FIXME: There are many more differences in HW, such as:
+	 * - More APBIF channels.
+	 * - Extra separate chunks of register address space to represent
+	 *   the extra APBIF channels.
+	 * - More units connected to the AHUB, so that tegra30_ahub_[rt]xcif
+	 *   need expansion, coupled with there being more defined bits in
+	 *   the AHUB routing registers.
+	 * However, the driver doesn't support those new features yet, so we
+	 * don't represent them here yet.
+	 */
+};
+
 struct tegra30_ahub {
+	const struct tegra30_ahub_soc_data *soc_data;
 	struct device *dev;
 	struct clk *clk_d_audio;
 	struct clk *clk_apbif;
diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c
index f4e1ce8..31d092d 100644
--- a/sound/soc/tegra/tegra30_i2s.c
+++ b/sound/soc/tegra/tegra30_i2s.c
@@ -38,6 +38,7 @@
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
+#include <sound/dmaengine_pcm.h>
 
 #include "tegra30_ahub.h"
 #include "tegra30_i2s.h"
@@ -80,17 +81,17 @@ static int tegra30_i2s_startup(struct snd_pcm_substream *substream,
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 		ret = tegra30_ahub_allocate_tx_fifo(&i2s->playback_fifo_cif,
 					&i2s->playback_dma_data.addr,
-					&i2s->playback_dma_data.req_sel);
-		i2s->playback_dma_data.wrap = 4;
-		i2s->playback_dma_data.width = 32;
+					&i2s->playback_dma_data.slave_id);
+		i2s->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+		i2s->playback_dma_data.maxburst = 4;
 		tegra30_ahub_set_rx_cif_source(i2s->playback_i2s_cif,
 					       i2s->playback_fifo_cif);
 	} else {
 		ret = tegra30_ahub_allocate_rx_fifo(&i2s->capture_fifo_cif,
 					&i2s->capture_dma_data.addr,
-					&i2s->capture_dma_data.req_sel);
-		i2s->capture_dma_data.wrap = 4;
-		i2s->capture_dma_data.width = 32;
+					&i2s->capture_dma_data.slave_id);
+		i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+		i2s->capture_dma_data.maxburst = 4;
 		tegra30_ahub_set_rx_cif_source(i2s->capture_fifo_cif,
 					       i2s->capture_i2s_cif);
 	}
@@ -336,6 +337,10 @@ static const struct snd_soc_dai_driver tegra30_i2s_dai_template = {
 	.symmetric_rates = 1,
 };
 
+static const struct snd_soc_component_driver tegra30_i2s_component = {
+	.name		= DRV_NAME,
+};
+
 static bool tegra30_i2s_wr_rd_reg(struct device *dev, unsigned int reg)
 {
 	switch (reg) {
@@ -464,7 +469,8 @@ static int tegra30_i2s_platform_probe(struct platform_device *pdev)
 			goto err_pm_disable;
 	}
 
-	ret = snd_soc_register_dai(&pdev->dev, &i2s->dai);
+	ret = snd_soc_register_component(&pdev->dev, &tegra30_i2s_component,
+				   &i2s->dai, 1);
 	if (ret) {
 		dev_err(&pdev->dev, "Could not register DAI: %d\n", ret);
 		ret = -ENOMEM;
@@ -474,13 +480,13 @@ static int tegra30_i2s_platform_probe(struct platform_device *pdev)
 	ret = tegra_pcm_platform_register(&pdev->dev);
 	if (ret) {
 		dev_err(&pdev->dev, "Could not register PCM: %d\n", ret);
-		goto err_unregister_dai;
+		goto err_unregister_component;
 	}
 
 	return 0;
 
-err_unregister_dai:
-	snd_soc_unregister_dai(&pdev->dev);
+err_unregister_component:
+	snd_soc_unregister_component(&pdev->dev);
 err_suspend:
 	if (!pm_runtime_status_suspended(&pdev->dev))
 		tegra30_i2s_runtime_suspend(&pdev->dev);
@@ -501,7 +507,7 @@ static int tegra30_i2s_platform_remove(struct platform_device *pdev)
 		tegra30_i2s_runtime_suspend(&pdev->dev);
 
 	tegra_pcm_platform_unregister(&pdev->dev);
-	snd_soc_unregister_dai(&pdev->dev);
+	snd_soc_unregister_component(&pdev->dev);
 
 	clk_put(i2s->clk_i2s);
 
diff --git a/sound/soc/tegra/tegra30_i2s.h b/sound/soc/tegra/tegra30_i2s.h
index a294d94..bea23af 100644
--- a/sound/soc/tegra/tegra30_i2s.h
+++ b/sound/soc/tegra/tegra30_i2s.h
@@ -231,10 +231,10 @@ struct tegra30_i2s {
 	struct clk *clk_i2s;
 	enum tegra30_ahub_txcif capture_i2s_cif;
 	enum tegra30_ahub_rxcif capture_fifo_cif;
-	struct tegra_pcm_dma_params capture_dma_data;
+	struct snd_dmaengine_dai_dma_data capture_dma_data;
 	enum tegra30_ahub_rxcif playback_i2s_cif;
 	enum tegra30_ahub_txcif playback_fifo_cif;
-	struct tegra_pcm_dma_params playback_dma_data;
+	struct snd_dmaengine_dai_dma_data playback_dma_data;
 	struct regmap *regmap;
 };
 
diff --git a/sound/soc/tegra/tegra_alc5632.c b/sound/soc/tegra/tegra_alc5632.c
index c80adb9..48d05d9 100644
--- a/sound/soc/tegra/tegra_alc5632.c
+++ b/sound/soc/tegra/tegra_alc5632.c
@@ -161,20 +161,13 @@ static int tegra_alc5632_probe(struct platform_device *pdev)
 			sizeof(struct tegra_alc5632), GFP_KERNEL);
 	if (!alc5632) {
 		dev_err(&pdev->dev, "Can't allocate tegra_alc5632\n");
-		ret = -ENOMEM;
-		goto err;
+		return -ENOMEM;
 	}
 
 	card->dev = &pdev->dev;
 	platform_set_drvdata(pdev, card);
 	snd_soc_card_set_drvdata(card, alc5632);
 
-	if (!(pdev->dev.of_node)) {
-		dev_err(&pdev->dev, "Must be instantiated using device tree\n");
-		ret = -EINVAL;
-		goto err;
-	}
-
 	alc5632->gpio_hp_det = of_get_named_gpio(np, "nvidia,hp-det-gpios", 0);
 	if (alc5632->gpio_hp_det == -EPROBE_DEFER)
 		return -EPROBE_DEFER;
@@ -197,11 +190,11 @@ static int tegra_alc5632_probe(struct platform_device *pdev)
 		goto err;
 	}
 
-	tegra_alc5632_dai.cpu_of_node = of_parse_phandle(
-			pdev->dev.of_node, "nvidia,i2s-controller", 0);
+	tegra_alc5632_dai.cpu_of_node = of_parse_phandle(np,
+			"nvidia,i2s-controller", 0);
 	if (!tegra_alc5632_dai.cpu_of_node) {
 		dev_err(&pdev->dev,
-		"Property 'nvidia,i2s-controller' missing or invalid\n");
+			"Property 'nvidia,i2s-controller' missing or invalid\n");
 		ret = -EINVAL;
 		goto err;
 	}
diff --git a/sound/soc/tegra/tegra_asoc_utils.c b/sound/soc/tegra/tegra_asoc_utils.c
index ba419f8..24fb001b 100644
--- a/sound/soc/tegra/tegra_asoc_utils.c
+++ b/sound/soc/tegra/tegra_asoc_utils.c
@@ -43,8 +43,10 @@ int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate,
 	case 88200:
 		if (data->soc == TEGRA_ASOC_UTILS_SOC_TEGRA20)
 			new_baseclock = 56448000;
-		else
+		else if (data->soc == TEGRA_ASOC_UTILS_SOC_TEGRA30)
 			new_baseclock = 564480000;
+		else
+			new_baseclock = 282240000;
 		break;
 	case 8000:
 	case 16000:
@@ -54,8 +56,10 @@ int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate,
 	case 96000:
 		if (data->soc == TEGRA_ASOC_UTILS_SOC_TEGRA20)
 			new_baseclock = 73728000;
-		else
+		else if (data->soc == TEGRA_ASOC_UTILS_SOC_TEGRA30)
 			new_baseclock = 552960000;
+		else
+			new_baseclock = 368640000;
 		break;
 	default:
 		return -EINVAL;
@@ -169,6 +173,7 @@ int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data,
 			  struct device *dev)
 {
 	int ret;
+	bool new_clocks = false;
 
 	data->dev = dev;
 
@@ -176,28 +181,37 @@ int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data,
 		data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA20;
 	else if (of_machine_is_compatible("nvidia,tegra30"))
 		data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA30;
-	else if (!dev->of_node)
-		/* non-DT is always Tegra20 */
-		data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA20;
-	else
-		/* DT boot, but unknown SoC */
+	else if (of_machine_is_compatible("nvidia,tegra114")) {
+		data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA114;
+		new_clocks = true;
+	} else {
+		dev_err(data->dev, "SoC unknown to Tegra ASoC utils\n");
 		return -EINVAL;
+	}
 
-	data->clk_pll_a = clk_get_sys(NULL, "pll_a");
+	if (new_clocks)
+		data->clk_pll_a = clk_get(dev, "pll_a");
+	else
+		data->clk_pll_a = clk_get_sys(NULL, "pll_a");
 	if (IS_ERR(data->clk_pll_a)) {
 		dev_err(data->dev, "Can't retrieve clk pll_a\n");
 		ret = PTR_ERR(data->clk_pll_a);
 		goto err;
 	}
 
-	data->clk_pll_a_out0 = clk_get_sys(NULL, "pll_a_out0");
+	if (new_clocks)
+		data->clk_pll_a_out0 = clk_get(dev, "pll_a_out0");
+	else
+		data->clk_pll_a_out0 = clk_get_sys(NULL, "pll_a_out0");
 	if (IS_ERR(data->clk_pll_a_out0)) {
 		dev_err(data->dev, "Can't retrieve clk pll_a_out0\n");
 		ret = PTR_ERR(data->clk_pll_a_out0);
 		goto err_put_pll_a;
 	}
 
-	if (data->soc == TEGRA_ASOC_UTILS_SOC_TEGRA20)
+	if (new_clocks)
+		data->clk_cdev1 = clk_get(dev, "mclk");
+	else if (data->soc == TEGRA_ASOC_UTILS_SOC_TEGRA20)
 		data->clk_cdev1 = clk_get_sys(NULL, "cdev1");
 	else
 		data->clk_cdev1 = clk_get_sys("extern1", NULL);
diff --git a/sound/soc/tegra/tegra_asoc_utils.h b/sound/soc/tegra/tegra_asoc_utils.h
index 974c9f8..19fdcaf 100644
--- a/sound/soc/tegra/tegra_asoc_utils.h
+++ b/sound/soc/tegra/tegra_asoc_utils.h
@@ -29,6 +29,7 @@ struct device;
 enum tegra_asoc_utils_soc {
 	TEGRA_ASOC_UTILS_SOC_TEGRA20,
 	TEGRA_ASOC_UTILS_SOC_TEGRA30,
+	TEGRA_ASOC_UTILS_SOC_TEGRA114,
 };
 
 struct tegra_asoc_utils_data {
diff --git a/sound/soc/tegra/tegra_pcm.c b/sound/soc/tegra/tegra_pcm.c
index c925ab0..6d1c70c 100644
--- a/sound/soc/tegra/tegra_pcm.c
+++ b/sound/soc/tegra/tegra_pcm.c
@@ -43,8 +43,6 @@
 static const struct snd_pcm_hardware tegra_pcm_hardware = {
 	.info			= SNDRV_PCM_INFO_MMAP |
 				  SNDRV_PCM_INFO_MMAP_VALID |
-				  SNDRV_PCM_INFO_PAUSE |
-				  SNDRV_PCM_INFO_RESUME |
 				  SNDRV_PCM_INFO_INTERLEAVED,
 	.formats		= SNDRV_PCM_FMTBIT_S16_LE,
 	.channels_min		= 2,
@@ -75,24 +73,15 @@ static int tegra_pcm_open(struct snd_pcm_substream *substream)
 	return 0;
 }
 
-static int tegra_pcm_close(struct snd_pcm_substream *substream)
-{
-	snd_dmaengine_pcm_close(substream);
-	return 0;
-}
-
 static int tegra_pcm_hw_params(struct snd_pcm_substream *substream,
 				struct snd_pcm_hw_params *params)
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct device *dev = rtd->platform->dev;
 	struct dma_chan *chan = snd_dmaengine_pcm_get_chan(substream);
-	struct tegra_pcm_dma_params *dmap;
 	struct dma_slave_config slave_config;
 	int ret;
 
-	dmap = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
-
 	ret = snd_hwparams_to_dma_slave_config(substream, params,
 						&slave_config);
 	if (ret) {
@@ -100,16 +89,9 @@ static int tegra_pcm_hw_params(struct snd_pcm_substream *substream,
 		return ret;
 	}
 
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-		slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
-		slave_config.dst_addr = dmap->addr;
-		slave_config.dst_maxburst = 4;
-	} else {
-		slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
-		slave_config.src_addr = dmap->addr;
-		slave_config.src_maxburst = 4;
-	}
-	slave_config.slave_id = dmap->req_sel;
+	snd_dmaengine_pcm_set_config_from_dai_data(substream,
+			snd_soc_dai_get_dma_data(rtd->cpu_dai, substream),
+			&slave_config);
 
 	ret = dmaengine_slave_config(chan, &slave_config);
 	if (ret < 0) {
@@ -127,26 +109,6 @@ static int tegra_pcm_hw_free(struct snd_pcm_substream *substream)
 	return 0;
 }
 
-static int tegra_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
-{
-	switch (cmd) {
-	case SNDRV_PCM_TRIGGER_START:
-	case SNDRV_PCM_TRIGGER_RESUME:
-	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-		return snd_dmaengine_pcm_trigger(substream,
-					SNDRV_PCM_TRIGGER_START);
-
-	case SNDRV_PCM_TRIGGER_STOP:
-	case SNDRV_PCM_TRIGGER_SUSPEND:
-	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-		return snd_dmaengine_pcm_trigger(substream,
-					SNDRV_PCM_TRIGGER_STOP);
-	default:
-		return -EINVAL;
-	}
-	return 0;
-}
-
 static int tegra_pcm_mmap(struct snd_pcm_substream *substream,
 				struct vm_area_struct *vma)
 {
@@ -160,11 +122,11 @@ static int tegra_pcm_mmap(struct snd_pcm_substream *substream,
 
 static struct snd_pcm_ops tegra_pcm_ops = {
 	.open		= tegra_pcm_open,
-	.close		= tegra_pcm_close,
+	.close		= snd_dmaengine_pcm_close,
 	.ioctl		= snd_pcm_lib_ioctl,
 	.hw_params	= tegra_pcm_hw_params,
 	.hw_free	= tegra_pcm_hw_free,
-	.trigger	= tegra_pcm_trigger,
+	.trigger	= snd_dmaengine_pcm_trigger,
 	.pointer	= snd_dmaengine_pcm_pointer,
 	.mmap		= tegra_pcm_mmap,
 };
diff --git a/sound/soc/tegra/tegra_pcm.h b/sound/soc/tegra/tegra_pcm.h
index bc8b46a..68ad901 100644
--- a/sound/soc/tegra/tegra_pcm.h
+++ b/sound/soc/tegra/tegra_pcm.h
@@ -31,13 +31,6 @@
 #ifndef __TEGRA_PCM_H__
 #define __TEGRA_PCM_H__
 
-struct tegra_pcm_dma_params {
-	unsigned long addr;
-	unsigned long wrap;
-	unsigned long width;
-	unsigned long req_sel;
-};
-
 int tegra_pcm_platform_register(struct device *dev);
 void tegra_pcm_platform_unregister(struct device *dev);
 
diff --git a/sound/soc/tegra/tegra_wm8753.c b/sound/soc/tegra/tegra_wm8753.c
index c8ef88a6..f87fc53 100644
--- a/sound/soc/tegra/tegra_wm8753.c
+++ b/sound/soc/tegra/tegra_wm8753.c
@@ -124,6 +124,7 @@ static struct snd_soc_card snd_soc_tegra_wm8753 = {
 
 static int tegra_wm8753_driver_probe(struct platform_device *pdev)
 {
+	struct device_node *np = pdev->dev.of_node;
 	struct snd_soc_card *card = &snd_soc_tegra_wm8753;
 	struct tegra_wm8753 *machine;
 	int ret;
@@ -132,8 +133,7 @@ static int tegra_wm8753_driver_probe(struct platform_device *pdev)
 			       GFP_KERNEL);
 	if (!machine) {
 		dev_err(&pdev->dev, "Can't allocate tegra_wm8753 struct\n");
-		ret = -ENOMEM;
-		goto err;
+		return -ENOMEM;
 	}
 
 	card->dev = &pdev->dev;
@@ -148,8 +148,8 @@ static int tegra_wm8753_driver_probe(struct platform_device *pdev)
 	if (ret)
 		goto err;
 
-	tegra_wm8753_dai.codec_of_node = of_parse_phandle(
-			pdev->dev.of_node, "nvidia,audio-codec", 0);
+	tegra_wm8753_dai.codec_of_node = of_parse_phandle(np,
+			"nvidia,audio-codec", 0);
 	if (!tegra_wm8753_dai.codec_of_node) {
 		dev_err(&pdev->dev,
 			"Property 'nvidia,audio-codec' missing or invalid\n");
@@ -157,8 +157,8 @@ static int tegra_wm8753_driver_probe(struct platform_device *pdev)
 		goto err;
 	}
 
-	tegra_wm8753_dai.cpu_of_node = of_parse_phandle(
-			pdev->dev.of_node, "nvidia,i2s-controller", 0);
+	tegra_wm8753_dai.cpu_of_node = of_parse_phandle(np,
+			"nvidia,i2s-controller", 0);
 	if (!tegra_wm8753_dai.cpu_of_node) {
 		dev_err(&pdev->dev,
 			"Property 'nvidia,i2s-controller' missing or invalid\n");
@@ -166,8 +166,7 @@ static int tegra_wm8753_driver_probe(struct platform_device *pdev)
 		goto err;
 	}
 
-	tegra_wm8753_dai.platform_of_node =
-				tegra_wm8753_dai.cpu_of_node;
+	tegra_wm8753_dai.platform_of_node = tegra_wm8753_dai.cpu_of_node;
 
 	ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev);
 	if (ret)
diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c
index bbd79bf..4ac7373 100644
--- a/sound/soc/tegra/tegra_wm8903.c
+++ b/sound/soc/tegra/tegra_wm8903.c
@@ -39,7 +39,6 @@
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
-#include <sound/tegra_wm8903.h>
 
 #include "../codecs/wm8903.h"
 
@@ -48,7 +47,11 @@
 #define DRV_NAME "tegra-snd-wm8903"
 
 struct tegra_wm8903 {
-	struct tegra_wm8903_platform_data pdata;
+	int gpio_spkr_en;
+	int gpio_hp_det;
+	int gpio_hp_mute;
+	int gpio_int_mic_en;
+	int gpio_ext_mic_en;
 	struct tegra_asoc_utils_data util_data;
 };
 
@@ -129,12 +132,11 @@ static int tegra_wm8903_event_int_spk(struct snd_soc_dapm_widget *w,
 	struct snd_soc_dapm_context *dapm = w->dapm;
 	struct snd_soc_card *card = dapm->card;
 	struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
-	struct tegra_wm8903_platform_data *pdata = &machine->pdata;
 
-	if (!gpio_is_valid(pdata->gpio_spkr_en))
+	if (!gpio_is_valid(machine->gpio_spkr_en))
 		return 0;
 
-	gpio_set_value_cansleep(pdata->gpio_spkr_en,
+	gpio_set_value_cansleep(machine->gpio_spkr_en,
 				SND_SOC_DAPM_EVENT_ON(event));
 
 	return 0;
@@ -146,12 +148,11 @@ static int tegra_wm8903_event_hp(struct snd_soc_dapm_widget *w,
 	struct snd_soc_dapm_context *dapm = w->dapm;
 	struct snd_soc_card *card = dapm->card;
 	struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
-	struct tegra_wm8903_platform_data *pdata = &machine->pdata;
 
-	if (!gpio_is_valid(pdata->gpio_hp_mute))
+	if (!gpio_is_valid(machine->gpio_hp_mute))
 		return 0;
 
-	gpio_set_value_cansleep(pdata->gpio_hp_mute,
+	gpio_set_value_cansleep(machine->gpio_hp_mute,
 				!SND_SOC_DAPM_EVENT_ON(event));
 
 	return 0;
@@ -163,17 +164,6 @@ static const struct snd_soc_dapm_widget tegra_wm8903_dapm_widgets[] = {
 	SND_SOC_DAPM_MIC("Mic Jack", NULL),
 };
 
-static const struct snd_soc_dapm_route harmony_audio_map[] = {
-	{"Headphone Jack", NULL, "HPOUTR"},
-	{"Headphone Jack", NULL, "HPOUTL"},
-	{"Int Spk", NULL, "ROP"},
-	{"Int Spk", NULL, "RON"},
-	{"Int Spk", NULL, "LOP"},
-	{"Int Spk", NULL, "LON"},
-	{"Mic Jack", NULL, "MICBIAS"},
-	{"IN1L", NULL, "Mic Jack"},
-};
-
 static const struct snd_kcontrol_new tegra_wm8903_controls[] = {
 	SOC_DAPM_PIN_SWITCH("Int Spk"),
 };
@@ -185,10 +175,9 @@ static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd)
 	struct snd_soc_dapm_context *dapm = &codec->dapm;
 	struct snd_soc_card *card = codec->card;
 	struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
-	struct tegra_wm8903_platform_data *pdata = &machine->pdata;
 
-	if (gpio_is_valid(pdata->gpio_hp_det)) {
-		tegra_wm8903_hp_jack_gpio.gpio = pdata->gpio_hp_det;
+	if (gpio_is_valid(machine->gpio_hp_det)) {
+		tegra_wm8903_hp_jack_gpio.gpio = machine->gpio_hp_det;
 		snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE,
 				&tegra_wm8903_hp_jack);
 		snd_soc_jack_add_pins(&tegra_wm8903_hp_jack,
@@ -226,9 +215,6 @@ static int tegra_wm8903_remove(struct snd_soc_card *card)
 static struct snd_soc_dai_link tegra_wm8903_dai = {
 	.name = "WM8903",
 	.stream_name = "WM8903 PCM",
-	.codec_name = "wm8903.0-001a",
-	.platform_name = "tegra20-i2s.0",
-	.cpu_dai_name = "tegra20-i2s.0",
 	.codec_dai_name = "wm8903-hifi",
 	.init = tegra_wm8903_init,
 	.ops = &tegra_wm8903_ops,
@@ -257,96 +243,25 @@ static int tegra_wm8903_driver_probe(struct platform_device *pdev)
 	struct device_node *np = pdev->dev.of_node;
 	struct snd_soc_card *card = &snd_soc_tegra_wm8903;
 	struct tegra_wm8903 *machine;
-	struct tegra_wm8903_platform_data *pdata;
 	int ret;
 
-	if (!pdev->dev.platform_data && !pdev->dev.of_node) {
-		dev_err(&pdev->dev, "No platform data supplied\n");
-		return -EINVAL;
-	}
-
 	machine = devm_kzalloc(&pdev->dev, sizeof(struct tegra_wm8903),
 			       GFP_KERNEL);
 	if (!machine) {
 		dev_err(&pdev->dev, "Can't allocate tegra_wm8903 struct\n");
-		ret = -ENOMEM;
-		goto err;
+		return -ENOMEM;
 	}
-	pdata = &machine->pdata;
 
 	card->dev = &pdev->dev;
 	platform_set_drvdata(pdev, card);
 	snd_soc_card_set_drvdata(card, machine);
 
-	if (pdev->dev.platform_data) {
-		memcpy(pdata, card->dev->platform_data, sizeof(*pdata));
-	} else if (np) {
-		pdata->gpio_spkr_en = of_get_named_gpio(np,
-						"nvidia,spkr-en-gpios", 0);
-		if (pdata->gpio_spkr_en == -EPROBE_DEFER)
-			return -EPROBE_DEFER;
-
-		pdata->gpio_hp_mute = of_get_named_gpio(np,
-						"nvidia,hp-mute-gpios", 0);
-		if (pdata->gpio_hp_mute == -EPROBE_DEFER)
-			return -EPROBE_DEFER;
-
-		pdata->gpio_hp_det = of_get_named_gpio(np,
-						"nvidia,hp-det-gpios", 0);
-		if (pdata->gpio_hp_det == -EPROBE_DEFER)
-			return -EPROBE_DEFER;
-
-		pdata->gpio_int_mic_en = of_get_named_gpio(np,
-						"nvidia,int-mic-en-gpios", 0);
-		if (pdata->gpio_int_mic_en == -EPROBE_DEFER)
-			return -EPROBE_DEFER;
-
-		pdata->gpio_ext_mic_en = of_get_named_gpio(np,
-						"nvidia,ext-mic-en-gpios", 0);
-		if (pdata->gpio_ext_mic_en == -EPROBE_DEFER)
-			return -EPROBE_DEFER;
-	}
-
-	if (np) {
-		ret = snd_soc_of_parse_card_name(card, "nvidia,model");
-		if (ret)
-			goto err;
-
-		ret = snd_soc_of_parse_audio_routing(card,
-						     "nvidia,audio-routing");
-		if (ret)
-			goto err;
-
-		tegra_wm8903_dai.codec_name = NULL;
-		tegra_wm8903_dai.codec_of_node = of_parse_phandle(np,
-				"nvidia,audio-codec", 0);
-		if (!tegra_wm8903_dai.codec_of_node) {
-			dev_err(&pdev->dev,
-				"Property 'nvidia,audio-codec' missing or invalid\n");
-			ret = -EINVAL;
-			goto err;
-		}
-
-		tegra_wm8903_dai.cpu_dai_name = NULL;
-		tegra_wm8903_dai.cpu_of_node = of_parse_phandle(np,
-				"nvidia,i2s-controller", 0);
-		if (!tegra_wm8903_dai.cpu_of_node) {
-			dev_err(&pdev->dev,
-				"Property 'nvidia,i2s-controller' missing or invalid\n");
-			ret = -EINVAL;
-			goto err;
-		}
-
-		tegra_wm8903_dai.platform_name = NULL;
-		tegra_wm8903_dai.platform_of_node =
-					tegra_wm8903_dai.cpu_of_node;
-	} else {
-		card->dapm_routes = harmony_audio_map;
-		card->num_dapm_routes = ARRAY_SIZE(harmony_audio_map);
-	}
-
-	if (gpio_is_valid(pdata->gpio_spkr_en)) {
-		ret = devm_gpio_request_one(&pdev->dev, pdata->gpio_spkr_en,
+	machine->gpio_spkr_en = of_get_named_gpio(np, "nvidia,spkr-en-gpios",
+						  0);
+	if (machine->gpio_spkr_en == -EPROBE_DEFER)
+		return -EPROBE_DEFER;
+	if (gpio_is_valid(machine->gpio_spkr_en)) {
+		ret = devm_gpio_request_one(&pdev->dev, machine->gpio_spkr_en,
 					    GPIOF_OUT_INIT_LOW, "spkr_en");
 		if (ret) {
 			dev_err(card->dev, "cannot get spkr_en gpio\n");
@@ -354,8 +269,12 @@ static int tegra_wm8903_driver_probe(struct platform_device *pdev)
 		}
 	}
 
-	if (gpio_is_valid(pdata->gpio_hp_mute)) {
-		ret = devm_gpio_request_one(&pdev->dev, pdata->gpio_hp_mute,
+	machine->gpio_hp_mute = of_get_named_gpio(np, "nvidia,hp-mute-gpios",
+						  0);
+	if (machine->gpio_hp_mute == -EPROBE_DEFER)
+		return -EPROBE_DEFER;
+	if (gpio_is_valid(machine->gpio_hp_mute)) {
+		ret = devm_gpio_request_one(&pdev->dev, machine->gpio_hp_mute,
 					    GPIOF_OUT_INIT_HIGH, "hp_mute");
 		if (ret) {
 			dev_err(card->dev, "cannot get hp_mute gpio\n");
@@ -363,9 +282,18 @@ static int tegra_wm8903_driver_probe(struct platform_device *pdev)
 		}
 	}
 
-	if (gpio_is_valid(pdata->gpio_int_mic_en)) {
+	machine->gpio_hp_det = of_get_named_gpio(np, "nvidia,hp-det-gpios", 0);
+	if (machine->gpio_hp_det == -EPROBE_DEFER)
+		return -EPROBE_DEFER;
+
+	machine->gpio_int_mic_en = of_get_named_gpio(np,
+						"nvidia,int-mic-en-gpios", 0);
+	if (machine->gpio_int_mic_en == -EPROBE_DEFER)
+		return -EPROBE_DEFER;
+	if (gpio_is_valid(machine->gpio_int_mic_en)) {
 		/* Disable int mic; enable signal is active-high */
-		ret = devm_gpio_request_one(&pdev->dev, pdata->gpio_int_mic_en,
+		ret = devm_gpio_request_one(&pdev->dev,
+					    machine->gpio_int_mic_en,
 					    GPIOF_OUT_INIT_LOW, "int_mic_en");
 		if (ret) {
 			dev_err(card->dev, "cannot get int_mic_en gpio\n");
@@ -373,9 +301,14 @@ static int tegra_wm8903_driver_probe(struct platform_device *pdev)
 		}
 	}
 
-	if (gpio_is_valid(pdata->gpio_ext_mic_en)) {
+	machine->gpio_ext_mic_en = of_get_named_gpio(np,
+						"nvidia,ext-mic-en-gpios", 0);
+	if (machine->gpio_ext_mic_en == -EPROBE_DEFER)
+		return -EPROBE_DEFER;
+	if (gpio_is_valid(machine->gpio_ext_mic_en)) {
 		/* Enable ext mic; enable signal is active-low */
-		ret = devm_gpio_request_one(&pdev->dev, pdata->gpio_ext_mic_en,
+		ret = devm_gpio_request_one(&pdev->dev,
+					    machine->gpio_ext_mic_en,
 					    GPIOF_OUT_INIT_LOW, "ext_mic_en");
 		if (ret) {
 			dev_err(card->dev, "cannot get ext_mic_en gpio\n");
@@ -383,6 +316,34 @@ static int tegra_wm8903_driver_probe(struct platform_device *pdev)
 		}
 	}
 
+	ret = snd_soc_of_parse_card_name(card, "nvidia,model");
+	if (ret)
+		goto err;
+
+	ret = snd_soc_of_parse_audio_routing(card, "nvidia,audio-routing");
+	if (ret)
+		goto err;
+
+	tegra_wm8903_dai.codec_of_node = of_parse_phandle(np,
+						"nvidia,audio-codec", 0);
+	if (!tegra_wm8903_dai.codec_of_node) {
+		dev_err(&pdev->dev,
+			"Property 'nvidia,audio-codec' missing or invalid\n");
+		ret = -EINVAL;
+		goto err;
+	}
+
+	tegra_wm8903_dai.cpu_of_node = of_parse_phandle(np,
+			"nvidia,i2s-controller", 0);
+	if (!tegra_wm8903_dai.cpu_of_node) {
+		dev_err(&pdev->dev,
+			"Property 'nvidia,i2s-controller' missing or invalid\n");
+		ret = -EINVAL;
+		goto err;
+	}
+
+	tegra_wm8903_dai.platform_of_node = tegra_wm8903_dai.cpu_of_node;
+
 	ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev);
 	if (ret)
 		goto err;
diff --git a/sound/soc/tegra/tegra_wm9712.c b/sound/soc/tegra/tegra_wm9712.c
index 68d4240..5e11963 100644
--- a/sound/soc/tegra/tegra_wm9712.c
+++ b/sound/soc/tegra/tegra_wm9712.c
@@ -55,7 +55,7 @@ static int tegra_wm9712_init(struct snd_soc_pcm_runtime *rtd)
 static struct snd_soc_dai_link tegra_wm9712_dai = {
 	.name = "AC97 HiFi",
 	.stream_name = "AC97 HiFi",
-	.cpu_dai_name = "tegra-ac97-pcm",
+	.cpu_dai_name = "tegra20-ac97",
 	.codec_dai_name = "wm9712-hifi",
 	.codec_name = "wm9712-codec",
 	.init = tegra_wm9712_init,
@@ -79,11 +79,6 @@ static int tegra_wm9712_driver_probe(struct platform_device *pdev)
 	struct tegra_wm9712 *machine;
 	int ret;
 
-	if (!pdev->dev.of_node) {
-		dev_err(&pdev->dev, "No platform data supplied\n");
-		return -EINVAL;
-	}
-
 	machine = devm_kzalloc(&pdev->dev, sizeof(struct tegra_wm9712),
 			       GFP_KERNEL);
 	if (!machine) {
diff --git a/sound/soc/tegra/trimslice.c b/sound/soc/tegra/trimslice.c
index 7fcf6c2..05c68aa 100644
--- a/sound/soc/tegra/trimslice.c
+++ b/sound/soc/tegra/trimslice.c
@@ -97,9 +97,6 @@ static const struct snd_soc_dapm_route trimslice_audio_map[] = {
 static struct snd_soc_dai_link trimslice_tlv320aic23_dai = {
 	.name = "TLV320AIC23",
 	.stream_name = "AIC23",
-	.codec_name = "tlv320aic23-codec.2-001a",
-	.platform_name = "tegra20-i2s.0",
-	.cpu_dai_name = "tegra20-i2s.0",
 	.codec_dai_name = "tlv320aic23-hifi",
 	.ops = &trimslice_asoc_ops,
 	.dai_fmt = SND_SOC_DAIFMT_I2S |
@@ -122,6 +119,7 @@ static struct snd_soc_card snd_soc_trimslice = {
 
 static int tegra_snd_trimslice_probe(struct platform_device *pdev)
 {
+	struct device_node *np = pdev->dev.of_node;
 	struct snd_soc_card *card = &snd_soc_trimslice;
 	struct tegra_trimslice *trimslice;
 	int ret;
@@ -130,44 +128,38 @@ static int tegra_snd_trimslice_probe(struct platform_device *pdev)
 				 GFP_KERNEL);
 	if (!trimslice) {
 		dev_err(&pdev->dev, "Can't allocate tegra_trimslice\n");
-		ret = -ENOMEM;
+		return -ENOMEM;
+	}
+
+	card->dev = &pdev->dev;
+	platform_set_drvdata(pdev, card);
+	snd_soc_card_set_drvdata(card, trimslice);
+
+	trimslice_tlv320aic23_dai.codec_of_node = of_parse_phandle(np,
+			"nvidia,audio-codec", 0);
+	if (!trimslice_tlv320aic23_dai.codec_of_node) {
+		dev_err(&pdev->dev,
+			"Property 'nvidia,audio-codec' missing or invalid\n");
+		ret = -EINVAL;
 		goto err;
 	}
 
-	if (pdev->dev.of_node) {
-		trimslice_tlv320aic23_dai.codec_name = NULL;
-		trimslice_tlv320aic23_dai.codec_of_node = of_parse_phandle(
-				pdev->dev.of_node, "nvidia,audio-codec", 0);
-		if (!trimslice_tlv320aic23_dai.codec_of_node) {
-			dev_err(&pdev->dev,
-				"Property 'nvidia,audio-codec' missing or invalid\n");
-			ret = -EINVAL;
-			goto err;
-		}
-
-		trimslice_tlv320aic23_dai.cpu_dai_name = NULL;
-		trimslice_tlv320aic23_dai.cpu_of_node = of_parse_phandle(
-				pdev->dev.of_node, "nvidia,i2s-controller", 0);
-		if (!trimslice_tlv320aic23_dai.cpu_of_node) {
-			dev_err(&pdev->dev,
-				"Property 'nvidia,i2s-controller' missing or invalid\n");
-			ret = -EINVAL;
-			goto err;
-		}
-
-		trimslice_tlv320aic23_dai.platform_name = NULL;
-		trimslice_tlv320aic23_dai.platform_of_node =
-				trimslice_tlv320aic23_dai.cpu_of_node;
+	trimslice_tlv320aic23_dai.cpu_of_node = of_parse_phandle(np,
+			"nvidia,i2s-controller", 0);
+	if (!trimslice_tlv320aic23_dai.cpu_of_node) {
+		dev_err(&pdev->dev,
+			"Property 'nvidia,i2s-controller' missing or invalid\n");
+		ret = -EINVAL;
+		goto err;
 	}
 
+	trimslice_tlv320aic23_dai.platform_of_node =
+			trimslice_tlv320aic23_dai.cpu_of_node;
+
 	ret = tegra_asoc_utils_init(&trimslice->util_data, &pdev->dev);
 	if (ret)
 		goto err;
 
-	card->dev = &pdev->dev;
-	platform_set_drvdata(pdev, card);
-	snd_soc_card_set_drvdata(card, trimslice);
-
 	ret = snd_soc_register_card(card);
 	if (ret) {
 		dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
diff --git a/sound/soc/txx9/txx9aclc-ac97.c b/sound/soc/txx9/txx9aclc-ac97.c
index 16ab696..8a28403 100644
--- a/sound/soc/txx9/txx9aclc-ac97.c
+++ b/sound/soc/txx9/txx9aclc-ac97.c
@@ -170,6 +170,10 @@ static struct snd_soc_dai_driver txx9aclc_ac97_dai = {
 	},
 };
 
+static const struct snd_soc_component_driver txx9aclc_ac97_component = {
+	.name		= "txx9aclc-ac97",
+};
+
 static int txx9aclc_ac97_dev_probe(struct platform_device *pdev)
 {
 	struct txx9aclc_plat_drvdata *drvdata;
@@ -205,12 +209,13 @@ static int txx9aclc_ac97_dev_probe(struct platform_device *pdev)
 	if (err < 0)
 		return err;
 
-	return snd_soc_register_dai(&pdev->dev, &txx9aclc_ac97_dai);
+	return snd_soc_register_component(&pdev->dev, &txx9aclc_ac97_component,
+					  &txx9aclc_ac97_dai, 1);
 }
 
 static int txx9aclc_ac97_dev_remove(struct platform_device *pdev)
 {
-	snd_soc_unregister_dai(&pdev->dev);
+	snd_soc_unregister_component(&pdev->dev);
 	return 0;
 }
 
diff --git a/sound/soc/ux500/Kconfig b/sound/soc/ux500/Kconfig
index 069330d..6b799c0 100644
--- a/sound/soc/ux500/Kconfig
+++ b/sound/soc/ux500/Kconfig
@@ -20,8 +20,8 @@ config SND_SOC_UX500_PLAT_DMA
 	help
 		Say Y if you want to enable the Ux500 platform-driver.
 
-+config SND_SOC_UX500_MACH_MOP500
-+	tristate "Machine - MOP500 (Ux500 + AB8500)"
+config SND_SOC_UX500_MACH_MOP500
+	tristate "Machine - MOP500 (Ux500 + AB8500)"
 	depends on AB8500_CORE && AB8500_GPADC && SND_SOC_UX500
 	select SND_SOC_AB8500_CODEC
 	select SND_SOC_UX500_PLAT_MSP_I2S
diff --git a/sound/soc/ux500/ux500_msp_dai.c b/sound/soc/ux500/ux500_msp_dai.c
index 94a3e57..f1e8a5e 100644
--- a/sound/soc/ux500/ux500_msp_dai.c
+++ b/sound/soc/ux500/ux500_msp_dai.c
@@ -768,6 +768,11 @@ static struct snd_soc_dai_driver ux500_msp_dai_drv[UX500_NBR_OF_DAI] = {
 	},
 };
 
+static const struct snd_soc_component_driver ux500_msp_component = {
+	.name		= "ux500-msp",
+};
+
+
 static int ux500_msp_drv_probe(struct platform_device *pdev)
 {
 	struct ux500_msp_i2s_drvdata *drvdata;
@@ -825,8 +830,8 @@ static int ux500_msp_drv_probe(struct platform_device *pdev)
 	}
 	dev_set_drvdata(&pdev->dev, drvdata);
 
-	ret = snd_soc_register_dai(&pdev->dev,
-				&ux500_msp_dai_drv[drvdata->msp->id]);
+	ret = snd_soc_register_component(&pdev->dev, &ux500_msp_component,
+					 &ux500_msp_dai_drv[drvdata->msp->id], 1);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "Error: %s: Failed to register MSP%d!\n",
 			__func__, drvdata->msp->id);
@@ -844,7 +849,7 @@ static int ux500_msp_drv_probe(struct platform_device *pdev)
 	return 0;
 
 err_reg_plat:
-	snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(ux500_msp_dai_drv));
+	snd_soc_unregister_component(&pdev->dev);
 err_init_msp:
 	clk_put(drvdata->clk);
 err_clk:
@@ -861,7 +866,7 @@ static int ux500_msp_drv_remove(struct platform_device *pdev)
 
 	ux500_pcm_unregister_platform(pdev);
 
-	snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(ux500_msp_dai_drv));
+	snd_soc_unregister_component(&pdev->dev);
 
 	devm_regulator_put(drvdata->reg_vape);
 	prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP, "ux500_msp_i2s");
diff --git a/sound/soc/ux500/ux500_pcm.c b/sound/soc/ux500/ux500_pcm.c
index 846fa82..1ab36fa 100644
--- a/sound/soc/ux500/ux500_pcm.c
+++ b/sound/soc/ux500/ux500_pcm.c
@@ -111,15 +111,6 @@ static int ux500_pcm_open(struct snd_pcm_substream *substream)
 		snd_soc_set_runtime_hwparams(substream,
 					&ux500_pcm_hw_capture);
 
-	/* ensure that buffer size is a multiple of period size */
-	ret = snd_pcm_hw_constraint_integer(runtime,
-					SNDRV_PCM_HW_PARAM_PERIODS);
-	if (ret < 0) {
-		dev_err(dev, "%s: Error: snd_pcm_hw_constraints failed (%d)\n",
-			__func__, ret);
-		return ret;
-	}
-
 	dev_dbg(dev, "%s: Set hw-struct for %s.\n", __func__,
 		snd_pcm_stream_str(substream));
 	runtime->hw = (stream_id == SNDRV_PCM_STREAM_PLAYBACK) ?
@@ -164,20 +155,6 @@ static int ux500_pcm_open(struct snd_pcm_substream *substream)
 		return ret;
 	}
 
-	snd_dmaengine_pcm_set_data(substream, dma_cfg);
-
-	return 0;
-}
-
-static int ux500_pcm_close(struct snd_pcm_substream *substream)
-{
-	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-	struct snd_soc_dai *dai = rtd->cpu_dai;
-
-	dev_dbg(dai->dev, "%s: Enter\n", __func__);
-
-	snd_dmaengine_pcm_close(substream);
-
 	return 0;
 }
 
@@ -255,7 +232,7 @@ static int ux500_pcm_mmap(struct snd_pcm_substream *substream,
 
 static struct snd_pcm_ops ux500_pcm_ops = {
 	.open		= ux500_pcm_open,
-	.close		= ux500_pcm_close,
+	.close		= snd_dmaengine_pcm_close,
 	.ioctl		= snd_pcm_lib_ioctl,
 	.hw_params	= ux500_pcm_hw_params,
 	.hw_free	= ux500_pcm_hw_free,
diff --git a/sound/sound_core.c b/sound/sound_core.c
index bb23009..359753f 100644
--- a/sound/sound_core.c
+++ b/sound/sound_core.c
@@ -352,7 +352,9 @@ static struct sound_unit *chains[SOUND_STEP];
  *      @dev: device pointer
  *
  *	Allocate a special sound device by minor number from the sound
- *	subsystem. The allocated number is returned on success. On failure
+ *	subsystem.
+ *
+ *	Return: The allocated number is returned on success. On failure,
  *	a negative error code is returned.
  */
  
@@ -436,8 +438,10 @@ EXPORT_SYMBOL(register_sound_special);
  *	@dev: Unit number to allocate
  *
  *	Allocate a mixer device. Unit is the number of the mixer requested.
- *	Pass -1 to request the next free mixer unit. On success the allocated
- *	number is returned, on failure a negative error code is returned.
+ *	Pass -1 to request the next free mixer unit.
+ *
+ *	Return: On success, the allocated number is returned. On failure,
+ *	a negative error code is returned.
  */
 
 int register_sound_mixer(const struct file_operations *fops, int dev)
@@ -454,8 +458,10 @@ EXPORT_SYMBOL(register_sound_mixer);
  *	@dev: Unit number to allocate
  *
  *	Allocate a midi device. Unit is the number of the midi device requested.
- *	Pass -1 to request the next free midi unit. On success the allocated
- *	number is returned, on failure a negative error code is returned.
+ *	Pass -1 to request the next free midi unit.
+ *
+ *	Return: On success, the allocated number is returned. On failure,
+ *	a negative error code is returned.
  */
 
 int register_sound_midi(const struct file_operations *fops, int dev)
@@ -477,11 +483,13 @@ EXPORT_SYMBOL(register_sound_midi);
  *	@dev: Unit number to allocate
  *
  *	Allocate a DSP device. Unit is the number of the DSP requested.
- *	Pass -1 to request the next free DSP unit. On success the allocated
- *	number is returned, on failure a negative error code is returned.
+ *	Pass -1 to request the next free DSP unit.
  *
  *	This function allocates both the audio and dsp device entries together
  *	and will always allocate them as a matching pair - eg dsp3/audio3
+ *
+ *	Return: On success, the allocated number is returned. On failure,
+ *	a negative error code is returned.
  */
 
 int register_sound_dsp(const struct file_operations *fops, int dev)
diff --git a/sound/usb/caiaq/audio.c b/sound/usb/caiaq/audio.c
index fde9a7a..67330af 100644
--- a/sound/usb/caiaq/audio.c
+++ b/sound/usb/caiaq/audio.c
@@ -16,6 +16,7 @@
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 */
 
+#include <linux/device.h>
 #include <linux/spinlock.h>
 #include <linux/slab.h>
 #include <linux/init.h>
@@ -39,8 +40,8 @@
 #define ENDPOINT_CAPTURE	2
 #define ENDPOINT_PLAYBACK	6
 
-#define MAKE_CHECKBYTE(dev,stream,i) \
-	(stream << 1) | (~(i / (dev->n_streams * BYTES_PER_SAMPLE_USB)) & 1)
+#define MAKE_CHECKBYTE(cdev,stream,i) \
+	(stream << 1) | (~(i / (cdev->n_streams * BYTES_PER_SAMPLE_USB)) & 1)
 
 static struct snd_pcm_hardware snd_usb_caiaq_pcm_hardware = {
 	.info 		= (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
@@ -60,32 +61,32 @@ static struct snd_pcm_hardware snd_usb_caiaq_pcm_hardware = {
 };
 
 static void
-activate_substream(struct snd_usb_caiaqdev *dev,
+activate_substream(struct snd_usb_caiaqdev *cdev,
 	           struct snd_pcm_substream *sub)
 {
-	spin_lock(&dev->spinlock);
+	spin_lock(&cdev->spinlock);
 
 	if (sub->stream == SNDRV_PCM_STREAM_PLAYBACK)
-		dev->sub_playback[sub->number] = sub;
+		cdev->sub_playback[sub->number] = sub;
 	else
-		dev->sub_capture[sub->number] = sub;
+		cdev->sub_capture[sub->number] = sub;
 
-	spin_unlock(&dev->spinlock);
+	spin_unlock(&cdev->spinlock);
 }
 
 static void
-deactivate_substream(struct snd_usb_caiaqdev *dev,
+deactivate_substream(struct snd_usb_caiaqdev *cdev,
 		     struct snd_pcm_substream *sub)
 {
 	unsigned long flags;
-	spin_lock_irqsave(&dev->spinlock, flags);
+	spin_lock_irqsave(&cdev->spinlock, flags);
 
 	if (sub->stream == SNDRV_PCM_STREAM_PLAYBACK)
-		dev->sub_playback[sub->number] = NULL;
+		cdev->sub_playback[sub->number] = NULL;
 	else
-		dev->sub_capture[sub->number] = NULL;
+		cdev->sub_capture[sub->number] = NULL;
 
-	spin_unlock_irqrestore(&dev->spinlock, flags);
+	spin_unlock_irqrestore(&cdev->spinlock, flags);
 }
 
 static int
@@ -98,28 +99,30 @@ all_substreams_zero(struct snd_pcm_substream **subs)
 	return 1;
 }
 
-static int stream_start(struct snd_usb_caiaqdev *dev)
+static int stream_start(struct snd_usb_caiaqdev *cdev)
 {
 	int i, ret;
+	struct device *dev = caiaqdev_to_dev(cdev);
 
-	debug("%s(%p)\n", __func__, dev);
+	dev_dbg(dev, "%s(%p)\n", __func__, cdev);
 
-	if (dev->streaming)
+	if (cdev->streaming)
 		return -EINVAL;
 
-	memset(dev->sub_playback, 0, sizeof(dev->sub_playback));
-	memset(dev->sub_capture, 0, sizeof(dev->sub_capture));
-	dev->input_panic = 0;
-	dev->output_panic = 0;
-	dev->first_packet = 4;
-	dev->streaming = 1;
-	dev->warned = 0;
+	memset(cdev->sub_playback, 0, sizeof(cdev->sub_playback));
+	memset(cdev->sub_capture, 0, sizeof(cdev->sub_capture));
+	cdev->input_panic = 0;
+	cdev->output_panic = 0;
+	cdev->first_packet = 4;
+	cdev->streaming = 1;
+	cdev->warned = 0;
 
 	for (i = 0; i < N_URBS; i++) {
-		ret = usb_submit_urb(dev->data_urbs_in[i], GFP_ATOMIC);
+		ret = usb_submit_urb(cdev->data_urbs_in[i], GFP_ATOMIC);
 		if (ret) {
-			log("unable to trigger read #%d! (ret %d)\n", i, ret);
-			dev->streaming = 0;
+			dev_err(dev, "unable to trigger read #%d! (ret %d)\n",
+				i, ret);
+			cdev->streaming = 0;
 			return -EPIPE;
 		}
 	}
@@ -127,46 +130,51 @@ static int stream_start(struct snd_usb_caiaqdev *dev)
 	return 0;
 }
 
-static void stream_stop(struct snd_usb_caiaqdev *dev)
+static void stream_stop(struct snd_usb_caiaqdev *cdev)
 {
 	int i;
+	struct device *dev = caiaqdev_to_dev(cdev);
 
-	debug("%s(%p)\n", __func__, dev);
-	if (!dev->streaming)
+	dev_dbg(dev, "%s(%p)\n", __func__, cdev);
+	if (!cdev->streaming)
 		return;
 
-	dev->streaming = 0;
+	cdev->streaming = 0;
 
 	for (i = 0; i < N_URBS; i++) {
-		usb_kill_urb(dev->data_urbs_in[i]);
+		usb_kill_urb(cdev->data_urbs_in[i]);
 
-		if (test_bit(i, &dev->outurb_active_mask))
-			usb_kill_urb(dev->data_urbs_out[i]);
+		if (test_bit(i, &cdev->outurb_active_mask))
+			usb_kill_urb(cdev->data_urbs_out[i]);
 	}
 
-	dev->outurb_active_mask = 0;
+	cdev->outurb_active_mask = 0;
 }
 
 static int snd_usb_caiaq_substream_open(struct snd_pcm_substream *substream)
 {
-	struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(substream);
-	debug("%s(%p)\n", __func__, substream);
-	substream->runtime->hw = dev->pcm_info;
+	struct snd_usb_caiaqdev *cdev = snd_pcm_substream_chip(substream);
+	struct device *dev = caiaqdev_to_dev(cdev);
+
+	dev_dbg(dev, "%s(%p)\n", __func__, substream);
+	substream->runtime->hw = cdev->pcm_info;
 	snd_pcm_limit_hw_rates(substream->runtime);
+
 	return 0;
 }
 
 static int snd_usb_caiaq_substream_close(struct snd_pcm_substream *substream)
 {
-	struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(substream);
+	struct snd_usb_caiaqdev *cdev = snd_pcm_substream_chip(substream);
+	struct device *dev = caiaqdev_to_dev(cdev);
 
-	debug("%s(%p)\n", __func__, substream);
-	if (all_substreams_zero(dev->sub_playback) &&
-	    all_substreams_zero(dev->sub_capture)) {
+	dev_dbg(dev, "%s(%p)\n", __func__, substream);
+	if (all_substreams_zero(cdev->sub_playback) &&
+	    all_substreams_zero(cdev->sub_capture)) {
 		/* when the last client has stopped streaming,
 		 * all sample rates are allowed again */
-		stream_stop(dev);
-		dev->pcm_info.rates = dev->samplerates;
+		stream_stop(cdev);
+		cdev->pcm_info.rates = cdev->samplerates;
 	}
 
 	return 0;
@@ -175,15 +183,13 @@ static int snd_usb_caiaq_substream_close(struct snd_pcm_substream *substream)
 static int snd_usb_caiaq_pcm_hw_params(struct snd_pcm_substream *sub,
 				       struct snd_pcm_hw_params *hw_params)
 {
-	debug("%s(%p)\n", __func__, sub);
 	return snd_pcm_lib_malloc_pages(sub, params_buffer_bytes(hw_params));
 }
 
 static int snd_usb_caiaq_pcm_hw_free(struct snd_pcm_substream *sub)
 {
-	struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(sub);
-	debug("%s(%p)\n", __func__, sub);
-	deactivate_substream(dev, sub);
+	struct snd_usb_caiaqdev *cdev = snd_pcm_substream_chip(sub);
+	deactivate_substream(cdev, sub);
 	return snd_pcm_lib_free_pages(sub);
 }
 
@@ -199,15 +205,16 @@ static int snd_usb_caiaq_pcm_prepare(struct snd_pcm_substream *substream)
 {
 	int bytes_per_sample, bpp, ret, i;
 	int index = substream->number;
-	struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(substream);
+	struct snd_usb_caiaqdev *cdev = snd_pcm_substream_chip(substream);
 	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct device *dev = caiaqdev_to_dev(cdev);
 
-	debug("%s(%p)\n", __func__, substream);
+	dev_dbg(dev, "%s(%p)\n", __func__, substream);
 
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 		int out_pos;
 
-		switch (dev->spec.data_alignment) {
+		switch (cdev->spec.data_alignment) {
 		case 0:
 		case 2:
 			out_pos = BYTES_PER_SAMPLE + 1;
@@ -218,12 +225,12 @@ static int snd_usb_caiaq_pcm_prepare(struct snd_pcm_substream *substream)
 			break;
 		}
 
-		dev->period_out_count[index] = out_pos;
-		dev->audio_out_buf_pos[index] = out_pos;
+		cdev->period_out_count[index] = out_pos;
+		cdev->audio_out_buf_pos[index] = out_pos;
 	} else {
 		int in_pos;
 
-		switch (dev->spec.data_alignment) {
+		switch (cdev->spec.data_alignment) {
 		case 0:
 			in_pos = BYTES_PER_SAMPLE + 2;
 			break;
@@ -236,44 +243,44 @@ static int snd_usb_caiaq_pcm_prepare(struct snd_pcm_substream *substream)
 			break;
 		}
 
-		dev->period_in_count[index] = in_pos;
-		dev->audio_in_buf_pos[index] = in_pos;
+		cdev->period_in_count[index] = in_pos;
+		cdev->audio_in_buf_pos[index] = in_pos;
 	}
 
-	if (dev->streaming)
+	if (cdev->streaming)
 		return 0;
 
 	/* the first client that opens a stream defines the sample rate
 	 * setting for all subsequent calls, until the last client closed. */
 	for (i=0; i < ARRAY_SIZE(rates); i++)
 		if (runtime->rate == rates[i])
-			dev->pcm_info.rates = 1 << i;
+			cdev->pcm_info.rates = 1 << i;
 
 	snd_pcm_limit_hw_rates(runtime);
 
 	bytes_per_sample = BYTES_PER_SAMPLE;
-	if (dev->spec.data_alignment >= 2)
+	if (cdev->spec.data_alignment >= 2)
 		bytes_per_sample++;
 
 	bpp = ((runtime->rate / 8000) + CLOCK_DRIFT_TOLERANCE)
-		* bytes_per_sample * CHANNELS_PER_STREAM * dev->n_streams;
+		* bytes_per_sample * CHANNELS_PER_STREAM * cdev->n_streams;
 
 	if (bpp > MAX_ENDPOINT_SIZE)
 		bpp = MAX_ENDPOINT_SIZE;
 
-	ret = snd_usb_caiaq_set_audio_params(dev, runtime->rate,
+	ret = snd_usb_caiaq_set_audio_params(cdev, runtime->rate,
 					     runtime->sample_bits, bpp);
 	if (ret)
 		return ret;
 
-	ret = stream_start(dev);
+	ret = stream_start(cdev);
 	if (ret)
 		return ret;
 
-	dev->output_running = 0;
-	wait_event_timeout(dev->prepare_wait_queue, dev->output_running, HZ);
-	if (!dev->output_running) {
-		stream_stop(dev);
+	cdev->output_running = 0;
+	wait_event_timeout(cdev->prepare_wait_queue, cdev->output_running, HZ);
+	if (!cdev->output_running) {
+		stream_stop(cdev);
 		return -EPIPE;
 	}
 
@@ -282,18 +289,19 @@ static int snd_usb_caiaq_pcm_prepare(struct snd_pcm_substream *substream)
 
 static int snd_usb_caiaq_pcm_trigger(struct snd_pcm_substream *sub, int cmd)
 {
-	struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(sub);
+	struct snd_usb_caiaqdev *cdev = snd_pcm_substream_chip(sub);
+	struct device *dev = caiaqdev_to_dev(cdev);
 
-	debug("%s(%p) cmd %d\n", __func__, sub, cmd);
+	dev_dbg(dev, "%s(%p) cmd %d\n", __func__, sub, cmd);
 
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-		activate_substream(dev, sub);
+		activate_substream(cdev, sub);
 		break;
 	case SNDRV_PCM_TRIGGER_STOP:
 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-		deactivate_substream(dev, sub);
+		deactivate_substream(cdev, sub);
 		break;
 	default:
 		return -EINVAL;
@@ -306,25 +314,25 @@ static snd_pcm_uframes_t
 snd_usb_caiaq_pcm_pointer(struct snd_pcm_substream *sub)
 {
 	int index = sub->number;
-	struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(sub);
+	struct snd_usb_caiaqdev *cdev = snd_pcm_substream_chip(sub);
 	snd_pcm_uframes_t ptr;
 
-	spin_lock(&dev->spinlock);
+	spin_lock(&cdev->spinlock);
 
-	if (dev->input_panic || dev->output_panic) {
+	if (cdev->input_panic || cdev->output_panic) {
 		ptr = SNDRV_PCM_POS_XRUN;
 		goto unlock;
 	}
 
 	if (sub->stream == SNDRV_PCM_STREAM_PLAYBACK)
 		ptr = bytes_to_frames(sub->runtime,
-					dev->audio_out_buf_pos[index]);
+					cdev->audio_out_buf_pos[index]);
 	else
 		ptr = bytes_to_frames(sub->runtime,
-					dev->audio_in_buf_pos[index]);
+					cdev->audio_in_buf_pos[index]);
 
 unlock:
-	spin_unlock(&dev->spinlock);
+	spin_unlock(&cdev->spinlock);
 	return ptr;
 }
 
@@ -340,21 +348,21 @@ static struct snd_pcm_ops snd_usb_caiaq_ops = {
 	.pointer =	snd_usb_caiaq_pcm_pointer
 };
 
-static void check_for_elapsed_periods(struct snd_usb_caiaqdev *dev,
+static void check_for_elapsed_periods(struct snd_usb_caiaqdev *cdev,
 				      struct snd_pcm_substream **subs)
 {
 	int stream, pb, *cnt;
 	struct snd_pcm_substream *sub;
 
-	for (stream = 0; stream < dev->n_streams; stream++) {
+	for (stream = 0; stream < cdev->n_streams; stream++) {
 		sub = subs[stream];
 		if (!sub)
 			continue;
 
 		pb = snd_pcm_lib_period_bytes(sub);
 		cnt = (sub->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
-					&dev->period_out_count[stream] :
-					&dev->period_in_count[stream];
+					&cdev->period_out_count[stream] :
+					&cdev->period_in_count[stream];
 
 		if (*cnt >= pb) {
 			snd_pcm_period_elapsed(sub);
@@ -363,7 +371,7 @@ static void check_for_elapsed_periods(struct snd_usb_caiaqdev *dev,
 	}
 }
 
-static void read_in_urb_mode0(struct snd_usb_caiaqdev *dev,
+static void read_in_urb_mode0(struct snd_usb_caiaqdev *cdev,
 			      const struct urb *urb,
 			      const struct usb_iso_packet_descriptor *iso)
 {
@@ -371,27 +379,27 @@ static void read_in_urb_mode0(struct snd_usb_caiaqdev *dev,
 	struct snd_pcm_substream *sub;
 	int stream, i;
 
-	if (all_substreams_zero(dev->sub_capture))
+	if (all_substreams_zero(cdev->sub_capture))
 		return;
 
 	for (i = 0; i < iso->actual_length;) {
-		for (stream = 0; stream < dev->n_streams; stream++, i++) {
-			sub = dev->sub_capture[stream];
+		for (stream = 0; stream < cdev->n_streams; stream++, i++) {
+			sub = cdev->sub_capture[stream];
 			if (sub) {
 				struct snd_pcm_runtime *rt = sub->runtime;
 				char *audio_buf = rt->dma_area;
 				int sz = frames_to_bytes(rt, rt->buffer_size);
-				audio_buf[dev->audio_in_buf_pos[stream]++]
+				audio_buf[cdev->audio_in_buf_pos[stream]++]
 					= usb_buf[i];
-				dev->period_in_count[stream]++;
-				if (dev->audio_in_buf_pos[stream] == sz)
-					dev->audio_in_buf_pos[stream] = 0;
+				cdev->period_in_count[stream]++;
+				if (cdev->audio_in_buf_pos[stream] == sz)
+					cdev->audio_in_buf_pos[stream] = 0;
 			}
 		}
 	}
 }
 
-static void read_in_urb_mode2(struct snd_usb_caiaqdev *dev,
+static void read_in_urb_mode2(struct snd_usb_caiaqdev *cdev,
 			      const struct urb *urb,
 			      const struct usb_iso_packet_descriptor *iso)
 {
@@ -401,48 +409,49 @@ static void read_in_urb_mode2(struct snd_usb_caiaqdev *dev,
 	int stream, i;
 
 	for (i = 0; i < iso->actual_length;) {
-		if (i % (dev->n_streams * BYTES_PER_SAMPLE_USB) == 0) {
+		if (i % (cdev->n_streams * BYTES_PER_SAMPLE_USB) == 0) {
 			for (stream = 0;
-			     stream < dev->n_streams;
+			     stream < cdev->n_streams;
 			     stream++, i++) {
-				if (dev->first_packet)
+				if (cdev->first_packet)
 					continue;
 
-				check_byte = MAKE_CHECKBYTE(dev, stream, i);
+				check_byte = MAKE_CHECKBYTE(cdev, stream, i);
 
 				if ((usb_buf[i] & 0x3f) != check_byte)
-					dev->input_panic = 1;
+					cdev->input_panic = 1;
 
 				if (usb_buf[i] & 0x80)
-					dev->output_panic = 1;
+					cdev->output_panic = 1;
 			}
 		}
-		dev->first_packet = 0;
+		cdev->first_packet = 0;
 
-		for (stream = 0; stream < dev->n_streams; stream++, i++) {
-			sub = dev->sub_capture[stream];
-			if (dev->input_panic)
+		for (stream = 0; stream < cdev->n_streams; stream++, i++) {
+			sub = cdev->sub_capture[stream];
+			if (cdev->input_panic)
 				usb_buf[i] = 0;
 
 			if (sub) {
 				struct snd_pcm_runtime *rt = sub->runtime;
 				char *audio_buf = rt->dma_area;
 				int sz = frames_to_bytes(rt, rt->buffer_size);
-				audio_buf[dev->audio_in_buf_pos[stream]++] =
+				audio_buf[cdev->audio_in_buf_pos[stream]++] =
 					usb_buf[i];
-				dev->period_in_count[stream]++;
-				if (dev->audio_in_buf_pos[stream] == sz)
-					dev->audio_in_buf_pos[stream] = 0;
+				cdev->period_in_count[stream]++;
+				if (cdev->audio_in_buf_pos[stream] == sz)
+					cdev->audio_in_buf_pos[stream] = 0;
 			}
 		}
 	}
 }
 
-static void read_in_urb_mode3(struct snd_usb_caiaqdev *dev,
+static void read_in_urb_mode3(struct snd_usb_caiaqdev *cdev,
 			      const struct urb *urb,
 			      const struct usb_iso_packet_descriptor *iso)
 {
 	unsigned char *usb_buf = urb->transfer_buffer + iso->offset;
+	struct device *dev = caiaqdev_to_dev(cdev);
 	int stream, i;
 
 	/* paranoia check */
@@ -450,12 +459,12 @@ static void read_in_urb_mode3(struct snd_usb_caiaqdev *dev,
 		return;
 
 	for (i = 0; i < iso->actual_length;) {
-		for (stream = 0; stream < dev->n_streams; stream++) {
-			struct snd_pcm_substream *sub = dev->sub_capture[stream];
+		for (stream = 0; stream < cdev->n_streams; stream++) {
+			struct snd_pcm_substream *sub = cdev->sub_capture[stream];
 			char *audio_buf = NULL;
 			int c, n, sz = 0;
 
-			if (sub && !dev->input_panic) {
+			if (sub && !cdev->input_panic) {
 				struct snd_pcm_runtime *rt = sub->runtime;
 				audio_buf = rt->dma_area;
 				sz = frames_to_bytes(rt, rt->buffer_size);
@@ -465,23 +474,23 @@ static void read_in_urb_mode3(struct snd_usb_caiaqdev *dev,
 				/* 3 audio data bytes, followed by 1 check byte */
 				if (audio_buf) {
 					for (n = 0; n < BYTES_PER_SAMPLE; n++) {
-						audio_buf[dev->audio_in_buf_pos[stream]++] = usb_buf[i+n];
+						audio_buf[cdev->audio_in_buf_pos[stream]++] = usb_buf[i+n];
 
-						if (dev->audio_in_buf_pos[stream] == sz)
-							dev->audio_in_buf_pos[stream] = 0;
+						if (cdev->audio_in_buf_pos[stream] == sz)
+							cdev->audio_in_buf_pos[stream] = 0;
 					}
 
-					dev->period_in_count[stream] += BYTES_PER_SAMPLE;
+					cdev->period_in_count[stream] += BYTES_PER_SAMPLE;
 				}
 
 				i += BYTES_PER_SAMPLE;
 
 				if (usb_buf[i] != ((stream << 1) | c) &&
-				    !dev->first_packet) {
-					if (!dev->input_panic)
-						printk(" EXPECTED: %02x got %02x, c %d, stream %d, i %d\n",
-							((stream << 1) | c), usb_buf[i], c, stream, i);
-					dev->input_panic = 1;
+				    !cdev->first_packet) {
+					if (!cdev->input_panic)
+						dev_warn(dev, " EXPECTED: %02x got %02x, c %d, stream %d, i %d\n",
+							 ((stream << 1) | c), usb_buf[i], c, stream, i);
+					cdev->input_panic = 1;
 				}
 
 				i++;
@@ -489,41 +498,43 @@ static void read_in_urb_mode3(struct snd_usb_caiaqdev *dev,
 		}
 	}
 
-	if (dev->first_packet > 0)
-		dev->first_packet--;
+	if (cdev->first_packet > 0)
+		cdev->first_packet--;
 }
 
-static void read_in_urb(struct snd_usb_caiaqdev *dev,
+static void read_in_urb(struct snd_usb_caiaqdev *cdev,
 			const struct urb *urb,
 			const struct usb_iso_packet_descriptor *iso)
 {
-	if (!dev->streaming)
+	struct device *dev = caiaqdev_to_dev(cdev);
+
+	if (!cdev->streaming)
 		return;
 
-	if (iso->actual_length < dev->bpp)
+	if (iso->actual_length < cdev->bpp)
 		return;
 
-	switch (dev->spec.data_alignment) {
+	switch (cdev->spec.data_alignment) {
 	case 0:
-		read_in_urb_mode0(dev, urb, iso);
+		read_in_urb_mode0(cdev, urb, iso);
 		break;
 	case 2:
-		read_in_urb_mode2(dev, urb, iso);
+		read_in_urb_mode2(cdev, urb, iso);
 		break;
 	case 3:
-		read_in_urb_mode3(dev, urb, iso);
+		read_in_urb_mode3(cdev, urb, iso);
 		break;
 	}
 
-	if ((dev->input_panic || dev->output_panic) && !dev->warned) {
-		debug("streaming error detected %s %s\n",
-				dev->input_panic ? "(input)" : "",
-				dev->output_panic ? "(output)" : "");
-		dev->warned = 1;
+	if ((cdev->input_panic || cdev->output_panic) && !cdev->warned) {
+		dev_warn(dev, "streaming error detected %s %s\n",
+				cdev->input_panic ? "(input)" : "",
+				cdev->output_panic ? "(output)" : "");
+		cdev->warned = 1;
 	}
 }
 
-static void fill_out_urb_mode_0(struct snd_usb_caiaqdev *dev,
+static void fill_out_urb_mode_0(struct snd_usb_caiaqdev *cdev,
 				struct urb *urb,
 				const struct usb_iso_packet_descriptor *iso)
 {
@@ -532,32 +543,32 @@ static void fill_out_urb_mode_0(struct snd_usb_caiaqdev *dev,
 	int stream, i;
 
 	for (i = 0; i < iso->length;) {
-		for (stream = 0; stream < dev->n_streams; stream++, i++) {
-			sub = dev->sub_playback[stream];
+		for (stream = 0; stream < cdev->n_streams; stream++, i++) {
+			sub = cdev->sub_playback[stream];
 			if (sub) {
 				struct snd_pcm_runtime *rt = sub->runtime;
 				char *audio_buf = rt->dma_area;
 				int sz = frames_to_bytes(rt, rt->buffer_size);
 				usb_buf[i] =
-					audio_buf[dev->audio_out_buf_pos[stream]];
-				dev->period_out_count[stream]++;
-				dev->audio_out_buf_pos[stream]++;
-				if (dev->audio_out_buf_pos[stream] == sz)
-					dev->audio_out_buf_pos[stream] = 0;
+					audio_buf[cdev->audio_out_buf_pos[stream]];
+				cdev->period_out_count[stream]++;
+				cdev->audio_out_buf_pos[stream]++;
+				if (cdev->audio_out_buf_pos[stream] == sz)
+					cdev->audio_out_buf_pos[stream] = 0;
 			} else
 				usb_buf[i] = 0;
 		}
 
 		/* fill in the check bytes */
-		if (dev->spec.data_alignment == 2 &&
-		    i % (dev->n_streams * BYTES_PER_SAMPLE_USB) ==
-		        (dev->n_streams * CHANNELS_PER_STREAM))
-			for (stream = 0; stream < dev->n_streams; stream++, i++)
-				usb_buf[i] = MAKE_CHECKBYTE(dev, stream, i);
+		if (cdev->spec.data_alignment == 2 &&
+		    i % (cdev->n_streams * BYTES_PER_SAMPLE_USB) ==
+		        (cdev->n_streams * CHANNELS_PER_STREAM))
+			for (stream = 0; stream < cdev->n_streams; stream++, i++)
+				usb_buf[i] = MAKE_CHECKBYTE(cdev, stream, i);
 	}
 }
 
-static void fill_out_urb_mode_3(struct snd_usb_caiaqdev *dev,
+static void fill_out_urb_mode_3(struct snd_usb_caiaqdev *cdev,
 				struct urb *urb,
 				const struct usb_iso_packet_descriptor *iso)
 {
@@ -565,8 +576,8 @@ static void fill_out_urb_mode_3(struct snd_usb_caiaqdev *dev,
 	int stream, i;
 
 	for (i = 0; i < iso->length;) {
-		for (stream = 0; stream < dev->n_streams; stream++) {
-			struct snd_pcm_substream *sub = dev->sub_playback[stream];
+		for (stream = 0; stream < cdev->n_streams; stream++) {
+			struct snd_pcm_substream *sub = cdev->sub_playback[stream];
 			char *audio_buf = NULL;
 			int c, n, sz = 0;
 
@@ -579,17 +590,17 @@ static void fill_out_urb_mode_3(struct snd_usb_caiaqdev *dev,
 			for (c = 0; c < CHANNELS_PER_STREAM; c++) {
 				for (n = 0; n < BYTES_PER_SAMPLE; n++) {
 					if (audio_buf) {
-						usb_buf[i+n] = audio_buf[dev->audio_out_buf_pos[stream]++];
+						usb_buf[i+n] = audio_buf[cdev->audio_out_buf_pos[stream]++];
 
-						if (dev->audio_out_buf_pos[stream] == sz)
-							dev->audio_out_buf_pos[stream] = 0;
+						if (cdev->audio_out_buf_pos[stream] == sz)
+							cdev->audio_out_buf_pos[stream] = 0;
 					} else {
 						usb_buf[i+n] = 0;
 					}
 				}
 
 				if (audio_buf)
-					dev->period_out_count[stream] += BYTES_PER_SAMPLE;
+					cdev->period_out_count[stream] += BYTES_PER_SAMPLE;
 
 				i += BYTES_PER_SAMPLE;
 
@@ -600,17 +611,17 @@ static void fill_out_urb_mode_3(struct snd_usb_caiaqdev *dev,
 	}
 }
 
-static inline void fill_out_urb(struct snd_usb_caiaqdev *dev,
+static inline void fill_out_urb(struct snd_usb_caiaqdev *cdev,
 				struct urb *urb,
 				const struct usb_iso_packet_descriptor *iso)
 {
-	switch (dev->spec.data_alignment) {
+	switch (cdev->spec.data_alignment) {
 	case 0:
 	case 2:
-		fill_out_urb_mode_0(dev, urb, iso);
+		fill_out_urb_mode_0(cdev, urb, iso);
 		break;
 	case 3:
-		fill_out_urb_mode_3(dev, urb, iso);
+		fill_out_urb_mode_3(cdev, urb, iso);
 		break;
 	}
 }
@@ -618,7 +629,8 @@ static inline void fill_out_urb(struct snd_usb_caiaqdev *dev,
 static void read_completed(struct urb *urb)
 {
 	struct snd_usb_caiaq_cb_info *info = urb->context;
-	struct snd_usb_caiaqdev *dev;
+	struct snd_usb_caiaqdev *cdev;
+	struct device *dev;
 	struct urb *out = NULL;
 	int i, frame, len, send_it = 0, outframe = 0;
 	size_t offset = 0;
@@ -626,20 +638,21 @@ static void read_completed(struct urb *urb)
 	if (urb->status || !info)
 		return;
 
-	dev = info->dev;
+	cdev = info->cdev;
+	dev = caiaqdev_to_dev(cdev);
 
-	if (!dev->streaming)
+	if (!cdev->streaming)
 		return;
 
 	/* find an unused output urb that is unused */
 	for (i = 0; i < N_URBS; i++)
-		if (test_and_set_bit(i, &dev->outurb_active_mask) == 0) {
-			out = dev->data_urbs_out[i];
+		if (test_and_set_bit(i, &cdev->outurb_active_mask) == 0) {
+			out = cdev->data_urbs_out[i];
 			break;
 		}
 
 	if (!out) {
-		log("Unable to find an output urb to use\n");
+		dev_err(dev, "Unable to find an output urb to use\n");
 		goto requeue;
 	}
 
@@ -656,12 +669,12 @@ static void read_completed(struct urb *urb)
 		offset += len;
 
 		if (len > 0) {
-			spin_lock(&dev->spinlock);
-			fill_out_urb(dev, out, &out->iso_frame_desc[outframe]);
-			read_in_urb(dev, urb, &urb->iso_frame_desc[frame]);
-			spin_unlock(&dev->spinlock);
-			check_for_elapsed_periods(dev, dev->sub_playback);
-			check_for_elapsed_periods(dev, dev->sub_capture);
+			spin_lock(&cdev->spinlock);
+			fill_out_urb(cdev, out, &out->iso_frame_desc[outframe]);
+			read_in_urb(cdev, urb, &urb->iso_frame_desc[frame]);
+			spin_unlock(&cdev->spinlock);
+			check_for_elapsed_periods(cdev, cdev->sub_playback);
+			check_for_elapsed_periods(cdev, cdev->sub_capture);
 			send_it = 1;
 		}
 
@@ -674,7 +687,7 @@ static void read_completed(struct urb *urb)
 		usb_submit_urb(out, GFP_ATOMIC);
 	} else {
 		struct snd_usb_caiaq_cb_info *oinfo = out->context;
-		clear_bit(oinfo->index, &dev->outurb_active_mask);
+		clear_bit(oinfo->index, &cdev->outurb_active_mask);
 	}
 
 requeue:
@@ -693,21 +706,22 @@ requeue:
 static void write_completed(struct urb *urb)
 {
 	struct snd_usb_caiaq_cb_info *info = urb->context;
-	struct snd_usb_caiaqdev *dev = info->dev;
+	struct snd_usb_caiaqdev *cdev = info->cdev;
 
-	if (!dev->output_running) {
-		dev->output_running = 1;
-		wake_up(&dev->prepare_wait_queue);
+	if (!cdev->output_running) {
+		cdev->output_running = 1;
+		wake_up(&cdev->prepare_wait_queue);
 	}
 
-	clear_bit(info->index, &dev->outurb_active_mask);
+	clear_bit(info->index, &cdev->outurb_active_mask);
 }
 
-static struct urb **alloc_urbs(struct snd_usb_caiaqdev *dev, int dir, int *ret)
+static struct urb **alloc_urbs(struct snd_usb_caiaqdev *cdev, int dir, int *ret)
 {
 	int i, frame;
 	struct urb **urbs;
-	struct usb_device *usb_dev = dev->chip.dev;
+	struct usb_device *usb_dev = cdev->chip.dev;
+	struct device *dev = caiaqdev_to_dev(cdev);
 	unsigned int pipe;
 
 	pipe = (dir == SNDRV_PCM_STREAM_PLAYBACK) ?
@@ -716,7 +730,7 @@ static struct urb **alloc_urbs(struct snd_usb_caiaqdev *dev, int dir, int *ret)
 
 	urbs = kmalloc(N_URBS * sizeof(*urbs), GFP_KERNEL);
 	if (!urbs) {
-		log("unable to kmalloc() urbs, OOM!?\n");
+		dev_err(dev, "unable to kmalloc() urbs, OOM!?\n");
 		*ret = -ENOMEM;
 		return NULL;
 	}
@@ -724,7 +738,7 @@ static struct urb **alloc_urbs(struct snd_usb_caiaqdev *dev, int dir, int *ret)
 	for (i = 0; i < N_URBS; i++) {
 		urbs[i] = usb_alloc_urb(FRAMES_PER_URB, GFP_KERNEL);
 		if (!urbs[i]) {
-			log("unable to usb_alloc_urb(), OOM!?\n");
+			dev_err(dev, "unable to usb_alloc_urb(), OOM!?\n");
 			*ret = -ENOMEM;
 			return urbs;
 		}
@@ -732,7 +746,7 @@ static struct urb **alloc_urbs(struct snd_usb_caiaqdev *dev, int dir, int *ret)
 		urbs[i]->transfer_buffer =
 			kmalloc(FRAMES_PER_URB * BYTES_PER_FRAME, GFP_KERNEL);
 		if (!urbs[i]->transfer_buffer) {
-			log("unable to kmalloc() transfer buffer, OOM!?\n");
+			dev_err(dev, "unable to kmalloc() transfer buffer, OOM!?\n");
 			*ret = -ENOMEM;
 			return urbs;
 		}
@@ -749,7 +763,7 @@ static struct urb **alloc_urbs(struct snd_usb_caiaqdev *dev, int dir, int *ret)
 		urbs[i]->pipe = pipe;
 		urbs[i]->transfer_buffer_length = FRAMES_PER_URB
 						* BYTES_PER_FRAME;
-		urbs[i]->context = &dev->data_cb_info[i];
+		urbs[i]->context = &cdev->data_cb_info[i];
 		urbs[i]->interval = 1;
 		urbs[i]->transfer_flags = URB_ISO_ASAP;
 		urbs[i]->number_of_packets = FRAMES_PER_URB;
@@ -780,110 +794,113 @@ static void free_urbs(struct urb **urbs)
 	kfree(urbs);
 }
 
-int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *dev)
+int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *cdev)
 {
 	int i, ret;
+	struct device *dev = caiaqdev_to_dev(cdev);
 
-	dev->n_audio_in  = max(dev->spec.num_analog_audio_in,
-			       dev->spec.num_digital_audio_in) /
+	cdev->n_audio_in  = max(cdev->spec.num_analog_audio_in,
+			       cdev->spec.num_digital_audio_in) /
 				CHANNELS_PER_STREAM;
-	dev->n_audio_out = max(dev->spec.num_analog_audio_out,
-			       dev->spec.num_digital_audio_out) /
+	cdev->n_audio_out = max(cdev->spec.num_analog_audio_out,
+			       cdev->spec.num_digital_audio_out) /
 				CHANNELS_PER_STREAM;
-	dev->n_streams = max(dev->n_audio_in, dev->n_audio_out);
+	cdev->n_streams = max(cdev->n_audio_in, cdev->n_audio_out);
 
-	debug("dev->n_audio_in = %d\n", dev->n_audio_in);
-	debug("dev->n_audio_out = %d\n", dev->n_audio_out);
-	debug("dev->n_streams = %d\n", dev->n_streams);
+	dev_dbg(dev, "cdev->n_audio_in = %d\n", cdev->n_audio_in);
+	dev_dbg(dev, "cdev->n_audio_out = %d\n", cdev->n_audio_out);
+	dev_dbg(dev, "cdev->n_streams = %d\n", cdev->n_streams);
 
-	if (dev->n_streams > MAX_STREAMS) {
-		log("unable to initialize device, too many streams.\n");
+	if (cdev->n_streams > MAX_STREAMS) {
+		dev_err(dev, "unable to initialize device, too many streams.\n");
 		return -EINVAL;
 	}
 
-	ret = snd_pcm_new(dev->chip.card, dev->product_name, 0,
-			dev->n_audio_out, dev->n_audio_in, &dev->pcm);
+	ret = snd_pcm_new(cdev->chip.card, cdev->product_name, 0,
+			cdev->n_audio_out, cdev->n_audio_in, &cdev->pcm);
 
 	if (ret < 0) {
-		log("snd_pcm_new() returned %d\n", ret);
+		dev_err(dev, "snd_pcm_new() returned %d\n", ret);
 		return ret;
 	}
 
-	dev->pcm->private_data = dev;
-	strlcpy(dev->pcm->name, dev->product_name, sizeof(dev->pcm->name));
+	cdev->pcm->private_data = cdev;
+	strlcpy(cdev->pcm->name, cdev->product_name, sizeof(cdev->pcm->name));
 
-	memset(dev->sub_playback, 0, sizeof(dev->sub_playback));
-	memset(dev->sub_capture, 0, sizeof(dev->sub_capture));
+	memset(cdev->sub_playback, 0, sizeof(cdev->sub_playback));
+	memset(cdev->sub_capture, 0, sizeof(cdev->sub_capture));
 
-	memcpy(&dev->pcm_info, &snd_usb_caiaq_pcm_hardware,
+	memcpy(&cdev->pcm_info, &snd_usb_caiaq_pcm_hardware,
 			sizeof(snd_usb_caiaq_pcm_hardware));
 
 	/* setup samplerates */
-	dev->samplerates = dev->pcm_info.rates;
-	switch (dev->chip.usb_id) {
+	cdev->samplerates = cdev->pcm_info.rates;
+	switch (cdev->chip.usb_id) {
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AK1):
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL3):
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_SESSIONIO):
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_GUITARRIGMOBILE):
-		dev->samplerates |= SNDRV_PCM_RATE_192000;
+		cdev->samplerates |= SNDRV_PCM_RATE_192000;
 		/* fall thru */
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO2DJ):
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ):
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ):
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORAUDIO2):
-		dev->samplerates |= SNDRV_PCM_RATE_88200;
+		cdev->samplerates |= SNDRV_PCM_RATE_88200;
 		break;
 	}
 
-	snd_pcm_set_ops(dev->pcm, SNDRV_PCM_STREAM_PLAYBACK,
+	snd_pcm_set_ops(cdev->pcm, SNDRV_PCM_STREAM_PLAYBACK,
 				&snd_usb_caiaq_ops);
-	snd_pcm_set_ops(dev->pcm, SNDRV_PCM_STREAM_CAPTURE,
+	snd_pcm_set_ops(cdev->pcm, SNDRV_PCM_STREAM_CAPTURE,
 				&snd_usb_caiaq_ops);
 
-	snd_pcm_lib_preallocate_pages_for_all(dev->pcm,
+	snd_pcm_lib_preallocate_pages_for_all(cdev->pcm,
 					SNDRV_DMA_TYPE_CONTINUOUS,
 					snd_dma_continuous_data(GFP_KERNEL),
 					MAX_BUFFER_SIZE, MAX_BUFFER_SIZE);
 
-	dev->data_cb_info =
+	cdev->data_cb_info =
 		kmalloc(sizeof(struct snd_usb_caiaq_cb_info) * N_URBS,
 					GFP_KERNEL);
 
-	if (!dev->data_cb_info)
+	if (!cdev->data_cb_info)
 		return -ENOMEM;
 
-	dev->outurb_active_mask = 0;
-	BUILD_BUG_ON(N_URBS > (sizeof(dev->outurb_active_mask) * 8));
+	cdev->outurb_active_mask = 0;
+	BUILD_BUG_ON(N_URBS > (sizeof(cdev->outurb_active_mask) * 8));
 
 	for (i = 0; i < N_URBS; i++) {
-		dev->data_cb_info[i].dev = dev;
-		dev->data_cb_info[i].index = i;
+		cdev->data_cb_info[i].cdev = cdev;
+		cdev->data_cb_info[i].index = i;
 	}
 
-	dev->data_urbs_in = alloc_urbs(dev, SNDRV_PCM_STREAM_CAPTURE, &ret);
+	cdev->data_urbs_in = alloc_urbs(cdev, SNDRV_PCM_STREAM_CAPTURE, &ret);
 	if (ret < 0) {
-		kfree(dev->data_cb_info);
-		free_urbs(dev->data_urbs_in);
+		kfree(cdev->data_cb_info);
+		free_urbs(cdev->data_urbs_in);
 		return ret;
 	}
 
-	dev->data_urbs_out = alloc_urbs(dev, SNDRV_PCM_STREAM_PLAYBACK, &ret);
+	cdev->data_urbs_out = alloc_urbs(cdev, SNDRV_PCM_STREAM_PLAYBACK, &ret);
 	if (ret < 0) {
-		kfree(dev->data_cb_info);
-		free_urbs(dev->data_urbs_in);
-		free_urbs(dev->data_urbs_out);
+		kfree(cdev->data_cb_info);
+		free_urbs(cdev->data_urbs_in);
+		free_urbs(cdev->data_urbs_out);
 		return ret;
 	}
 
 	return 0;
 }
 
-void snd_usb_caiaq_audio_free(struct snd_usb_caiaqdev *dev)
+void snd_usb_caiaq_audio_free(struct snd_usb_caiaqdev *cdev)
 {
-	debug("%s(%p)\n", __func__, dev);
-	stream_stop(dev);
-	free_urbs(dev->data_urbs_in);
-	free_urbs(dev->data_urbs_out);
-	kfree(dev->data_cb_info);
+	struct device *dev = caiaqdev_to_dev(cdev);
+
+	dev_dbg(dev, "%s(%p)\n", __func__, cdev);
+	stream_stop(cdev);
+	free_urbs(cdev->data_urbs_in);
+	free_urbs(cdev->data_urbs_out);
+	kfree(cdev->data_cb_info);
 }
 
diff --git a/sound/usb/caiaq/audio.h b/sound/usb/caiaq/audio.h
index 8ab1f8d..bdf1553 100644
--- a/sound/usb/caiaq/audio.h
+++ b/sound/usb/caiaq/audio.h
@@ -1,7 +1,7 @@
 #ifndef CAIAQ_AUDIO_H
 #define CAIAQ_AUDIO_H
 
-int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *dev);
-void snd_usb_caiaq_audio_free(struct snd_usb_caiaqdev *dev);
+int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *cdev);
+void snd_usb_caiaq_audio_free(struct snd_usb_caiaqdev *cdev);
 
 #endif /* CAIAQ_AUDIO_H */
diff --git a/sound/usb/caiaq/control.c b/sound/usb/caiaq/control.c
index adb8d03..ae6b50f 100644
--- a/sound/usb/caiaq/control.c
+++ b/sound/usb/caiaq/control.c
@@ -17,6 +17,7 @@
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  */
 
+#include <linux/device.h>
 #include <linux/init.h>
 #include <linux/usb.h>
 #include <sound/control.h>
@@ -32,7 +33,7 @@ static int control_info(struct snd_kcontrol *kcontrol,
 			struct snd_ctl_elem_info *uinfo)
 {
 	struct snd_usb_audio *chip = snd_kcontrol_chip(kcontrol);
-	struct snd_usb_caiaqdev *dev = caiaqdev(chip->card);
+	struct snd_usb_caiaqdev *cdev = caiaqdev(chip->card);
 	int pos = kcontrol->private_value;
 	int is_intval = pos & CNT_INTVAL;
 	int maxval = 63;
@@ -40,7 +41,7 @@ static int control_info(struct snd_kcontrol *kcontrol,
 	uinfo->count = 1;
 	pos &= ~CNT_INTVAL;
 
-	switch (dev->chip.usb_id) {
+	switch (cdev->chip.usb_id) {
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ):
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ):
 		if (pos == 0) {
@@ -78,15 +79,15 @@ static int control_get(struct snd_kcontrol *kcontrol,
 		       struct snd_ctl_elem_value *ucontrol)
 {
 	struct snd_usb_audio *chip = snd_kcontrol_chip(kcontrol);
-	struct snd_usb_caiaqdev *dev = caiaqdev(chip->card);
+	struct snd_usb_caiaqdev *cdev = caiaqdev(chip->card);
 	int pos = kcontrol->private_value;
 
 	if (pos & CNT_INTVAL)
 		ucontrol->value.integer.value[0]
-			= dev->control_state[pos & ~CNT_INTVAL];
+			= cdev->control_state[pos & ~CNT_INTVAL];
 	else
 		ucontrol->value.integer.value[0]
-			= !!(dev->control_state[pos / 8] & (1 << pos % 8));
+			= !!(cdev->control_state[pos / 8] & (1 << pos % 8));
 
 	return 0;
 }
@@ -95,43 +96,43 @@ static int control_put(struct snd_kcontrol *kcontrol,
 		       struct snd_ctl_elem_value *ucontrol)
 {
 	struct snd_usb_audio *chip = snd_kcontrol_chip(kcontrol);
-	struct snd_usb_caiaqdev *dev = caiaqdev(chip->card);
+	struct snd_usb_caiaqdev *cdev = caiaqdev(chip->card);
 	int pos = kcontrol->private_value;
 	int v = ucontrol->value.integer.value[0];
 	unsigned char cmd = EP1_CMD_WRITE_IO;
 
-	if (dev->chip.usb_id ==
+	if (cdev->chip.usb_id ==
 		USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1))
 		cmd = EP1_CMD_DIMM_LEDS;
 
 	if (pos & CNT_INTVAL) {
 		int i = pos & ~CNT_INTVAL;
 
-		dev->control_state[i] = v;
+		cdev->control_state[i] = v;
 
-		if (dev->chip.usb_id ==
+		if (cdev->chip.usb_id ==
 			USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLS4)) {
 			int actual_len;
 
-			dev->ep8_out_buf[0] = i;
-			dev->ep8_out_buf[1] = v;
+			cdev->ep8_out_buf[0] = i;
+			cdev->ep8_out_buf[1] = v;
 
-			usb_bulk_msg(dev->chip.dev,
-				     usb_sndbulkpipe(dev->chip.dev, 8),
-				     dev->ep8_out_buf, sizeof(dev->ep8_out_buf),
+			usb_bulk_msg(cdev->chip.dev,
+				     usb_sndbulkpipe(cdev->chip.dev, 8),
+				     cdev->ep8_out_buf, sizeof(cdev->ep8_out_buf),
 				     &actual_len, 200);
 		} else {
-			snd_usb_caiaq_send_command(dev, cmd,
-					dev->control_state, sizeof(dev->control_state));
+			snd_usb_caiaq_send_command(cdev, cmd,
+					cdev->control_state, sizeof(cdev->control_state));
 		}
 	} else {
 		if (v)
-			dev->control_state[pos / 8] |= 1 << (pos % 8);
+			cdev->control_state[pos / 8] |= 1 << (pos % 8);
 		else
-			dev->control_state[pos / 8] &= ~(1 << (pos % 8));
+			cdev->control_state[pos / 8] &= ~(1 << (pos % 8));
 
-		snd_usb_caiaq_send_command(dev, cmd,
-				dev->control_state, sizeof(dev->control_state));
+		snd_usb_caiaq_send_command(cdev, cmd,
+				cdev->control_state, sizeof(cdev->control_state));
 	}
 
 	return 1;
@@ -490,7 +491,7 @@ static struct caiaq_controller kontrols4_controller[] = {
 };
 
 static int add_controls(struct caiaq_controller *c, int num,
-			struct snd_usb_caiaqdev *dev)
+			struct snd_usb_caiaqdev *cdev)
 {
 	int i, ret;
 	struct snd_kcontrol *kc;
@@ -498,8 +499,8 @@ static int add_controls(struct caiaq_controller *c, int num,
 	for (i = 0; i < num; i++, c++) {
 		kcontrol_template.name = c->name;
 		kcontrol_template.private_value = c->index;
-		kc = snd_ctl_new1(&kcontrol_template, dev);
-		ret = snd_ctl_add(dev->chip.card, kc);
+		kc = snd_ctl_new1(&kcontrol_template, cdev);
+		ret = snd_ctl_add(cdev->chip.card, kc);
 		if (ret < 0)
 			return ret;
 	}
@@ -507,50 +508,50 @@ static int add_controls(struct caiaq_controller *c, int num,
 	return 0;
 }
 
-int snd_usb_caiaq_control_init(struct snd_usb_caiaqdev *dev)
+int snd_usb_caiaq_control_init(struct snd_usb_caiaqdev *cdev)
 {
 	int ret = 0;
 
-	switch (dev->chip.usb_id) {
+	switch (cdev->chip.usb_id) {
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AK1):
 		ret = add_controls(ak1_controller,
-			ARRAY_SIZE(ak1_controller), dev);
+			ARRAY_SIZE(ak1_controller), cdev);
 		break;
 
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL2):
 		ret = add_controls(rk2_controller,
-			ARRAY_SIZE(rk2_controller), dev);
+			ARRAY_SIZE(rk2_controller), cdev);
 		break;
 
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL3):
 		ret = add_controls(rk3_controller,
-			ARRAY_SIZE(rk3_controller), dev);
+			ARRAY_SIZE(rk3_controller), cdev);
 		break;
 
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER):
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER2):
 		ret = add_controls(kore_controller,
-			ARRAY_SIZE(kore_controller), dev);
+			ARRAY_SIZE(kore_controller), cdev);
 		break;
 
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ):
 		ret = add_controls(a8dj_controller,
-			ARRAY_SIZE(a8dj_controller), dev);
+			ARRAY_SIZE(a8dj_controller), cdev);
 		break;
 
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ):
 		ret = add_controls(a4dj_controller,
-			ARRAY_SIZE(a4dj_controller), dev);
+			ARRAY_SIZE(a4dj_controller), cdev);
 		break;
 
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
 		ret = add_controls(kontrolx1_controller,
-			ARRAY_SIZE(kontrolx1_controller), dev);
+			ARRAY_SIZE(kontrolx1_controller), cdev);
 		break;
 
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLS4):
 		ret = add_controls(kontrols4_controller,
-			ARRAY_SIZE(kontrols4_controller), dev);
+			ARRAY_SIZE(kontrols4_controller), cdev);
 		break;
 	}
 
diff --git a/sound/usb/caiaq/control.h b/sound/usb/caiaq/control.h
index 2e7ab1a..501c488 100644
--- a/sound/usb/caiaq/control.h
+++ b/sound/usb/caiaq/control.h
@@ -1,6 +1,6 @@
 #ifndef CAIAQ_CONTROL_H
 #define CAIAQ_CONTROL_H
 
-int snd_usb_caiaq_control_init(struct snd_usb_caiaqdev *dev);
+int snd_usb_caiaq_control_init(struct snd_usb_caiaqdev *cdev);
 
 #endif /* CAIAQ_CONTROL_H */
diff --git a/sound/usb/caiaq/device.c b/sound/usb/caiaq/device.c
index e4d6dbb..48b63cc 100644
--- a/sound/usb/caiaq/device.c
+++ b/sound/usb/caiaq/device.c
@@ -20,6 +20,7 @@
 */
 
 #include <linux/moduleparam.h>
+#include <linux/device.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -158,67 +159,68 @@ static struct usb_device_id snd_usb_id_table[] = {
 static void usb_ep1_command_reply_dispatch (struct urb* urb)
 {
 	int ret;
-	struct snd_usb_caiaqdev *dev = urb->context;
+	struct device *dev = &urb->dev->dev;
+	struct snd_usb_caiaqdev *cdev = urb->context;
 	unsigned char *buf = urb->transfer_buffer;
 
-	if (urb->status || !dev) {
-		log("received EP1 urb->status = %i\n", urb->status);
+	if (urb->status || !cdev) {
+		dev_warn(dev, "received EP1 urb->status = %i\n", urb->status);
 		return;
 	}
 
 	switch(buf[0]) {
 	case EP1_CMD_GET_DEVICE_INFO:
-	 	memcpy(&dev->spec, buf+1, sizeof(struct caiaq_device_spec));
-		dev->spec.fw_version = le16_to_cpu(dev->spec.fw_version);
-		debug("device spec (firmware %d): audio: %d in, %d out, "
+	 	memcpy(&cdev->spec, buf+1, sizeof(struct caiaq_device_spec));
+		cdev->spec.fw_version = le16_to_cpu(cdev->spec.fw_version);
+		dev_dbg(dev, "device spec (firmware %d): audio: %d in, %d out, "
 			"MIDI: %d in, %d out, data alignment %d\n",
-			dev->spec.fw_version,
-			dev->spec.num_analog_audio_in,
-			dev->spec.num_analog_audio_out,
-			dev->spec.num_midi_in,
-			dev->spec.num_midi_out,
-			dev->spec.data_alignment);
-
-		dev->spec_received++;
-		wake_up(&dev->ep1_wait_queue);
+			cdev->spec.fw_version,
+			cdev->spec.num_analog_audio_in,
+			cdev->spec.num_analog_audio_out,
+			cdev->spec.num_midi_in,
+			cdev->spec.num_midi_out,
+			cdev->spec.data_alignment);
+
+		cdev->spec_received++;
+		wake_up(&cdev->ep1_wait_queue);
 		break;
 	case EP1_CMD_AUDIO_PARAMS:
-		dev->audio_parm_answer = buf[1];
-		wake_up(&dev->ep1_wait_queue);
+		cdev->audio_parm_answer = buf[1];
+		wake_up(&cdev->ep1_wait_queue);
 		break;
 	case EP1_CMD_MIDI_READ:
-		snd_usb_caiaq_midi_handle_input(dev, buf[1], buf + 3, buf[2]);
+		snd_usb_caiaq_midi_handle_input(cdev, buf[1], buf + 3, buf[2]);
 		break;
 	case EP1_CMD_READ_IO:
-		if (dev->chip.usb_id ==
+		if (cdev->chip.usb_id ==
 			USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ)) {
-			if (urb->actual_length > sizeof(dev->control_state))
-				urb->actual_length = sizeof(dev->control_state);
-			memcpy(dev->control_state, buf + 1, urb->actual_length);
-			wake_up(&dev->ep1_wait_queue);
+			if (urb->actual_length > sizeof(cdev->control_state))
+				urb->actual_length = sizeof(cdev->control_state);
+			memcpy(cdev->control_state, buf + 1, urb->actual_length);
+			wake_up(&cdev->ep1_wait_queue);
 			break;
 		}
 #ifdef CONFIG_SND_USB_CAIAQ_INPUT
 	case EP1_CMD_READ_ERP:
 	case EP1_CMD_READ_ANALOG:
-		snd_usb_caiaq_input_dispatch(dev, buf, urb->actual_length);
+		snd_usb_caiaq_input_dispatch(cdev, buf, urb->actual_length);
 #endif
 		break;
 	}
 
-	dev->ep1_in_urb.actual_length = 0;
-	ret = usb_submit_urb(&dev->ep1_in_urb, GFP_ATOMIC);
+	cdev->ep1_in_urb.actual_length = 0;
+	ret = usb_submit_urb(&cdev->ep1_in_urb, GFP_ATOMIC);
 	if (ret < 0)
-		log("unable to submit urb. OOM!?\n");
+		dev_err(dev, "unable to submit urb. OOM!?\n");
 }
 
-int snd_usb_caiaq_send_command(struct snd_usb_caiaqdev *dev,
+int snd_usb_caiaq_send_command(struct snd_usb_caiaqdev *cdev,
 			       unsigned char command,
 			       const unsigned char *buffer,
 			       int len)
 {
 	int actual_len;
-	struct usb_device *usb_dev = dev->chip.dev;
+	struct usb_device *usb_dev = cdev->chip.dev;
 
 	if (!usb_dev)
 		return -EIO;
@@ -227,18 +229,19 @@ int snd_usb_caiaq_send_command(struct snd_usb_caiaqdev *dev,
 		len = EP1_BUFSIZE - 1;
 
 	if (buffer && len > 0)
-		memcpy(dev->ep1_out_buf+1, buffer, len);
+		memcpy(cdev->ep1_out_buf+1, buffer, len);
 
-	dev->ep1_out_buf[0] = command;
+	cdev->ep1_out_buf[0] = command;
 	return usb_bulk_msg(usb_dev, usb_sndbulkpipe(usb_dev, 1),
-			   dev->ep1_out_buf, len+1, &actual_len, 200);
+			   cdev->ep1_out_buf, len+1, &actual_len, 200);
 }
 
-int snd_usb_caiaq_set_audio_params (struct snd_usb_caiaqdev *dev,
+int snd_usb_caiaq_set_audio_params (struct snd_usb_caiaqdev *cdev,
 		   		    int rate, int depth, int bpp)
 {
 	int ret;
 	char tmp[5];
+	struct device *dev = caiaqdev_to_dev(cdev);
 
 	switch (rate) {
 	case 44100:	tmp[0] = SAMPLERATE_44100;   break;
@@ -259,49 +262,50 @@ int snd_usb_caiaq_set_audio_params (struct snd_usb_caiaqdev *dev,
 	tmp[3] = bpp >> 8;
 	tmp[4] = 1; /* packets per microframe */
 
-	debug("setting audio params: %d Hz, %d bits, %d bpp\n",
+	dev_dbg(dev, "setting audio params: %d Hz, %d bits, %d bpp\n",
 		rate, depth, bpp);
 
-	dev->audio_parm_answer = -1;
-	ret = snd_usb_caiaq_send_command(dev, EP1_CMD_AUDIO_PARAMS,
+	cdev->audio_parm_answer = -1;
+	ret = snd_usb_caiaq_send_command(cdev, EP1_CMD_AUDIO_PARAMS,
 					 tmp, sizeof(tmp));
 
 	if (ret)
 		return ret;
 
-	if (!wait_event_timeout(dev->ep1_wait_queue,
-	    dev->audio_parm_answer >= 0, HZ))
+	if (!wait_event_timeout(cdev->ep1_wait_queue,
+	    cdev->audio_parm_answer >= 0, HZ))
 		return -EPIPE;
 
-	if (dev->audio_parm_answer != 1)
-		debug("unable to set the device's audio params\n");
+	if (cdev->audio_parm_answer != 1)
+		dev_dbg(dev, "unable to set the device's audio params\n");
 	else
-		dev->bpp = bpp;
+		cdev->bpp = bpp;
 
-	return dev->audio_parm_answer == 1 ? 0 : -EINVAL;
+	return cdev->audio_parm_answer == 1 ? 0 : -EINVAL;
 }
 
-int snd_usb_caiaq_set_auto_msg(struct snd_usb_caiaqdev *dev,
+int snd_usb_caiaq_set_auto_msg(struct snd_usb_caiaqdev *cdev,
 			       int digital, int analog, int erp)
 {
 	char tmp[3] = { digital, analog, erp };
-	return snd_usb_caiaq_send_command(dev, EP1_CMD_AUTO_MSG,
+	return snd_usb_caiaq_send_command(cdev, EP1_CMD_AUTO_MSG,
 					  tmp, sizeof(tmp));
 }
 
-static void setup_card(struct snd_usb_caiaqdev *dev)
+static void setup_card(struct snd_usb_caiaqdev *cdev)
 {
 	int ret;
 	char val[4];
+	struct device *dev = caiaqdev_to_dev(cdev);
 
 	/* device-specific startup specials */
-	switch (dev->chip.usb_id) {
+	switch (cdev->chip.usb_id) {
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL2):
 		/* RigKontrol2 - display centered dash ('-') */
 		val[0] = 0x00;
 		val[1] = 0x00;
 		val[2] = 0x01;
-		snd_usb_caiaq_send_command(dev, EP1_CMD_WRITE_IO, val, 3);
+		snd_usb_caiaq_send_command(cdev, EP1_CMD_WRITE_IO, val, 3);
 		break;
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL3):
 		/* RigKontrol2 - display two centered dashes ('--') */
@@ -309,69 +313,69 @@ static void setup_card(struct snd_usb_caiaqdev *dev)
 		val[1] = 0x40;
 		val[2] = 0x40;
 		val[3] = 0x00;
-		snd_usb_caiaq_send_command(dev, EP1_CMD_WRITE_IO, val, 4);
+		snd_usb_caiaq_send_command(cdev, EP1_CMD_WRITE_IO, val, 4);
 		break;
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AK1):
 		/* Audio Kontrol 1 - make USB-LED stop blinking */
 		val[0] = 0x00;
-		snd_usb_caiaq_send_command(dev, EP1_CMD_WRITE_IO, val, 1);
+		snd_usb_caiaq_send_command(cdev, EP1_CMD_WRITE_IO, val, 1);
 		break;
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ):
 		/* Audio 8 DJ - trigger read of current settings */
-		dev->control_state[0] = 0xff;
-		snd_usb_caiaq_set_auto_msg(dev, 1, 0, 0);
-		snd_usb_caiaq_send_command(dev, EP1_CMD_READ_IO, NULL, 0);
+		cdev->control_state[0] = 0xff;
+		snd_usb_caiaq_set_auto_msg(cdev, 1, 0, 0);
+		snd_usb_caiaq_send_command(cdev, EP1_CMD_READ_IO, NULL, 0);
 
-		if (!wait_event_timeout(dev->ep1_wait_queue,
-					dev->control_state[0] != 0xff, HZ))
+		if (!wait_event_timeout(cdev->ep1_wait_queue,
+					cdev->control_state[0] != 0xff, HZ))
 			return;
 
 		/* fix up some defaults */
-		if ((dev->control_state[1] != 2) ||
-		    (dev->control_state[2] != 3) ||
-		    (dev->control_state[4] != 2)) {
-			dev->control_state[1] = 2;
-			dev->control_state[2] = 3;
-			dev->control_state[4] = 2;
-			snd_usb_caiaq_send_command(dev,
-				EP1_CMD_WRITE_IO, dev->control_state, 6);
+		if ((cdev->control_state[1] != 2) ||
+		    (cdev->control_state[2] != 3) ||
+		    (cdev->control_state[4] != 2)) {
+			cdev->control_state[1] = 2;
+			cdev->control_state[2] = 3;
+			cdev->control_state[4] = 2;
+			snd_usb_caiaq_send_command(cdev,
+				EP1_CMD_WRITE_IO, cdev->control_state, 6);
 		}
 
 		break;
 	}
 
-	if (dev->spec.num_analog_audio_out +
-	    dev->spec.num_analog_audio_in +
-	    dev->spec.num_digital_audio_out +
-	    dev->spec.num_digital_audio_in > 0) {
-		ret = snd_usb_caiaq_audio_init(dev);
+	if (cdev->spec.num_analog_audio_out +
+	    cdev->spec.num_analog_audio_in +
+	    cdev->spec.num_digital_audio_out +
+	    cdev->spec.num_digital_audio_in > 0) {
+		ret = snd_usb_caiaq_audio_init(cdev);
 		if (ret < 0)
-			log("Unable to set up audio system (ret=%d)\n", ret);
+			dev_err(dev, "Unable to set up audio system (ret=%d)\n", ret);
 	}
 
-	if (dev->spec.num_midi_in +
-	    dev->spec.num_midi_out > 0) {
-		ret = snd_usb_caiaq_midi_init(dev);
+	if (cdev->spec.num_midi_in +
+	    cdev->spec.num_midi_out > 0) {
+		ret = snd_usb_caiaq_midi_init(cdev);
 		if (ret < 0)
-			log("Unable to set up MIDI system (ret=%d)\n", ret);
+			dev_err(dev, "Unable to set up MIDI system (ret=%d)\n", ret);
 	}
 
 #ifdef CONFIG_SND_USB_CAIAQ_INPUT
-	ret = snd_usb_caiaq_input_init(dev);
+	ret = snd_usb_caiaq_input_init(cdev);
 	if (ret < 0)
-		log("Unable to set up input system (ret=%d)\n", ret);
+		dev_err(dev, "Unable to set up input system (ret=%d)\n", ret);
 #endif
 
 	/* finally, register the card and all its sub-instances */
-	ret = snd_card_register(dev->chip.card);
+	ret = snd_card_register(cdev->chip.card);
 	if (ret < 0) {
-		log("snd_card_register() returned %d\n", ret);
-		snd_card_free(dev->chip.card);
+		dev_err(dev, "snd_card_register() returned %d\n", ret);
+		snd_card_free(cdev->chip.card);
 	}
 
-	ret = snd_usb_caiaq_control_init(dev);
+	ret = snd_usb_caiaq_control_init(cdev);
 	if (ret < 0)
-		log("Unable to set up control system (ret=%d)\n", ret);
+		dev_err(dev, "Unable to set up control system (ret=%d)\n", ret);
 }
 
 static int create_card(struct usb_device *usb_dev,
@@ -381,7 +385,7 @@ static int create_card(struct usb_device *usb_dev,
 	int devnum;
 	int err;
 	struct snd_card *card;
-	struct snd_usb_caiaqdev *dev;
+	struct snd_usb_caiaqdev *cdev;
 
 	for (devnum = 0; devnum < SNDRV_CARDS; devnum++)
 		if (enable[devnum] && !snd_card_used[devnum])
@@ -395,65 +399,66 @@ static int create_card(struct usb_device *usb_dev,
 	if (err < 0)
 		return err;
 
-	dev = caiaqdev(card);
-	dev->chip.dev = usb_dev;
-	dev->chip.card = card;
-	dev->chip.usb_id = USB_ID(le16_to_cpu(usb_dev->descriptor.idVendor),
+	cdev = caiaqdev(card);
+	cdev->chip.dev = usb_dev;
+	cdev->chip.card = card;
+	cdev->chip.usb_id = USB_ID(le16_to_cpu(usb_dev->descriptor.idVendor),
 				  le16_to_cpu(usb_dev->descriptor.idProduct));
-	spin_lock_init(&dev->spinlock);
+	spin_lock_init(&cdev->spinlock);
 	snd_card_set_dev(card, &intf->dev);
 
 	*cardp = card;
 	return 0;
 }
 
-static int init_card(struct snd_usb_caiaqdev *dev)
+static int init_card(struct snd_usb_caiaqdev *cdev)
 {
 	char *c, usbpath[32];
-	struct usb_device *usb_dev = dev->chip.dev;
-	struct snd_card *card = dev->chip.card;
+	struct usb_device *usb_dev = cdev->chip.dev;
+	struct snd_card *card = cdev->chip.card;
+	struct device *dev = caiaqdev_to_dev(cdev);
 	int err, len;
 
 	if (usb_set_interface(usb_dev, 0, 1) != 0) {
-		log("can't set alt interface.\n");
+		dev_err(dev, "can't set alt interface.\n");
 		return -EIO;
 	}
 
-	usb_init_urb(&dev->ep1_in_urb);
-	usb_init_urb(&dev->midi_out_urb);
+	usb_init_urb(&cdev->ep1_in_urb);
+	usb_init_urb(&cdev->midi_out_urb);
 
-	usb_fill_bulk_urb(&dev->ep1_in_urb, usb_dev,
+	usb_fill_bulk_urb(&cdev->ep1_in_urb, usb_dev,
 			  usb_rcvbulkpipe(usb_dev, 0x1),
-			  dev->ep1_in_buf, EP1_BUFSIZE,
-			  usb_ep1_command_reply_dispatch, dev);
+			  cdev->ep1_in_buf, EP1_BUFSIZE,
+			  usb_ep1_command_reply_dispatch, cdev);
 
-	usb_fill_bulk_urb(&dev->midi_out_urb, usb_dev,
+	usb_fill_bulk_urb(&cdev->midi_out_urb, usb_dev,
 			  usb_sndbulkpipe(usb_dev, 0x1),
-			  dev->midi_out_buf, EP1_BUFSIZE,
-			  snd_usb_caiaq_midi_output_done, dev);
+			  cdev->midi_out_buf, EP1_BUFSIZE,
+			  snd_usb_caiaq_midi_output_done, cdev);
 
-	init_waitqueue_head(&dev->ep1_wait_queue);
-	init_waitqueue_head(&dev->prepare_wait_queue);
+	init_waitqueue_head(&cdev->ep1_wait_queue);
+	init_waitqueue_head(&cdev->prepare_wait_queue);
 
-	if (usb_submit_urb(&dev->ep1_in_urb, GFP_KERNEL) != 0)
+	if (usb_submit_urb(&cdev->ep1_in_urb, GFP_KERNEL) != 0)
 		return -EIO;
 
-	err = snd_usb_caiaq_send_command(dev, EP1_CMD_GET_DEVICE_INFO, NULL, 0);
+	err = snd_usb_caiaq_send_command(cdev, EP1_CMD_GET_DEVICE_INFO, NULL, 0);
 	if (err)
 		return err;
 
-	if (!wait_event_timeout(dev->ep1_wait_queue, dev->spec_received, HZ))
+	if (!wait_event_timeout(cdev->ep1_wait_queue, cdev->spec_received, HZ))
 		return -ENODEV;
 
 	usb_string(usb_dev, usb_dev->descriptor.iManufacturer,
-		   dev->vendor_name, CAIAQ_USB_STR_LEN);
+		   cdev->vendor_name, CAIAQ_USB_STR_LEN);
 
 	usb_string(usb_dev, usb_dev->descriptor.iProduct,
-		   dev->product_name, CAIAQ_USB_STR_LEN);
+		   cdev->product_name, CAIAQ_USB_STR_LEN);
 
 	strlcpy(card->driver, MODNAME, sizeof(card->driver));
-	strlcpy(card->shortname, dev->product_name, sizeof(card->shortname));
-	strlcpy(card->mixername, dev->product_name, sizeof(card->mixername));
+	strlcpy(card->shortname, cdev->product_name, sizeof(card->shortname));
+	strlcpy(card->mixername, cdev->product_name, sizeof(card->mixername));
 
 	/* if the id was not passed as module option, fill it with a shortened
 	 * version of the product string which does not contain any
@@ -473,11 +478,10 @@ static int init_card(struct snd_usb_caiaqdev *dev)
 	}
 
 	usb_make_path(usb_dev, usbpath, sizeof(usbpath));
-	snprintf(card->longname, sizeof(card->longname),
-		       "%s %s (%s)",
-		       dev->vendor_name, dev->product_name, usbpath);
+	snprintf(card->longname, sizeof(card->longname), "%s %s (%s)",
+		       cdev->vendor_name, cdev->product_name, usbpath);
 
-	setup_card(dev);
+	setup_card(cdev);
 	return 0;
 }
 
@@ -486,9 +490,9 @@ static int snd_probe(struct usb_interface *intf,
 {
 	int ret;
 	struct snd_card *card = NULL;
-	struct usb_device *device = interface_to_usbdev(intf);
+	struct usb_device *usb_dev = interface_to_usbdev(intf);
 
-	ret = create_card(device, intf, &card);
+	ret = create_card(usb_dev, intf, &card);
 
 	if (ret < 0)
 		return ret;
@@ -496,7 +500,7 @@ static int snd_probe(struct usb_interface *intf,
 	usb_set_intfdata(intf, card);
 	ret = init_card(caiaqdev(card));
 	if (ret < 0) {
-		log("unable to init card! (ret=%d)\n", ret);
+		dev_err(&usb_dev->dev, "unable to init card! (ret=%d)\n", ret);
 		snd_card_free(card);
 		return ret;
 	}
@@ -506,24 +510,25 @@ static int snd_probe(struct usb_interface *intf,
 
 static void snd_disconnect(struct usb_interface *intf)
 {
-	struct snd_usb_caiaqdev *dev;
 	struct snd_card *card = usb_get_intfdata(intf);
-
-	debug("%s(%p)\n", __func__, intf);
+	struct device *dev = intf->usb_dev;
+	struct snd_usb_caiaqdev *cdev;
 
 	if (!card)
 		return;
 
-	dev = caiaqdev(card);
+	cdev = caiaqdev(card);
+	dev_dbg(dev, "%s(%p)\n", __func__, intf);
+
 	snd_card_disconnect(card);
 
 #ifdef CONFIG_SND_USB_CAIAQ_INPUT
-	snd_usb_caiaq_input_free(dev);
+	snd_usb_caiaq_input_free(cdev);
 #endif
-	snd_usb_caiaq_audio_free(dev);
+	snd_usb_caiaq_audio_free(cdev);
 
-	usb_kill_urb(&dev->ep1_in_urb);
-	usb_kill_urb(&dev->midi_out_urb);
+	usb_kill_urb(&cdev->ep1_in_urb);
+	usb_kill_urb(&cdev->midi_out_urb);
 
 	snd_card_free(card);
 	usb_reset_device(interface_to_usbdev(intf));
@@ -539,4 +544,3 @@ static struct usb_driver snd_usb_driver = {
 };
 
 module_usb_driver(snd_usb_driver);
-
diff --git a/sound/usb/caiaq/device.h b/sound/usb/caiaq/device.h
index 562b0bf..ad102fa 100644
--- a/sound/usb/caiaq/device.h
+++ b/sound/usb/caiaq/device.h
@@ -25,16 +25,7 @@
 #define CAIAQ_USB_STR_LEN 0xff
 #define MAX_STREAMS 32
 
-//#define	SND_USB_CAIAQ_DEBUG
-
 #define MODNAME "snd-usb-caiaq"
-#define log(x...) snd_printk(KERN_WARNING MODNAME" log: " x)
-
-#ifdef SND_USB_CAIAQ_DEBUG
-#define debug(x...) snd_printk(KERN_WARNING MODNAME " debug: " x)
-#else
-#define debug(x...) do { } while(0)
-#endif
 
 #define EP1_CMD_GET_DEVICE_INFO	0x1
 #define EP1_CMD_READ_ERP	0x2
@@ -124,15 +115,16 @@ struct snd_usb_caiaqdev {
 };
 
 struct snd_usb_caiaq_cb_info {
-	struct snd_usb_caiaqdev *dev;
+	struct snd_usb_caiaqdev *cdev;
 	int index;
 };
 
 #define caiaqdev(c) ((struct snd_usb_caiaqdev*)(c)->private_data)
+#define caiaqdev_to_dev(d)	(d->chip.card->dev)
 
-int snd_usb_caiaq_set_audio_params (struct snd_usb_caiaqdev *dev, int rate, int depth, int bbp);
-int snd_usb_caiaq_set_auto_msg (struct snd_usb_caiaqdev *dev, int digital, int analog, int erp);
-int snd_usb_caiaq_send_command(struct snd_usb_caiaqdev *dev,
+int snd_usb_caiaq_set_audio_params (struct snd_usb_caiaqdev *cdev, int rate, int depth, int bbp);
+int snd_usb_caiaq_set_auto_msg (struct snd_usb_caiaqdev *cdev, int digital, int analog, int erp);
+int snd_usb_caiaq_send_command(struct snd_usb_caiaqdev *cdev,
 			       unsigned char command,
 			       const unsigned char *buffer,
 			       int len);
diff --git a/sound/usb/caiaq/input.c b/sound/usb/caiaq/input.c
index 26a121b..efc70ae 100644
--- a/sound/usb/caiaq/input.c
+++ b/sound/usb/caiaq/input.c
@@ -16,6 +16,7 @@
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 */
 
+#include <linux/device.h>
 #include <linux/gfp.h>
 #include <linux/init.h>
 #include <linux/usb.h>
@@ -199,55 +200,55 @@ static unsigned int decode_erp(unsigned char a, unsigned char b)
 #undef HIGH_PEAK
 #undef LOW_PEAK
 
-static inline void snd_caiaq_input_report_abs(struct snd_usb_caiaqdev *dev,
+static inline void snd_caiaq_input_report_abs(struct snd_usb_caiaqdev *cdev,
 					      int axis, const unsigned char *buf,
 					      int offset)
 {
-	input_report_abs(dev->input_dev, axis,
+	input_report_abs(cdev->input_dev, axis,
 			 (buf[offset * 2] << 8) | buf[offset * 2 + 1]);
 }
 
-static void snd_caiaq_input_read_analog(struct snd_usb_caiaqdev *dev,
+static void snd_caiaq_input_read_analog(struct snd_usb_caiaqdev *cdev,
 					const unsigned char *buf,
 					unsigned int len)
 {
-	struct input_dev *input_dev = dev->input_dev;
+	struct input_dev *input_dev = cdev->input_dev;
 
-	switch (dev->chip.usb_id) {
+	switch (cdev->chip.usb_id) {
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL2):
-		snd_caiaq_input_report_abs(dev, ABS_X, buf, 2);
-		snd_caiaq_input_report_abs(dev, ABS_Y, buf, 0);
-		snd_caiaq_input_report_abs(dev, ABS_Z, buf, 1);
+		snd_caiaq_input_report_abs(cdev, ABS_X, buf, 2);
+		snd_caiaq_input_report_abs(cdev, ABS_Y, buf, 0);
+		snd_caiaq_input_report_abs(cdev, ABS_Z, buf, 1);
 		break;
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL3):
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER):
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER2):
-		snd_caiaq_input_report_abs(dev, ABS_X, buf, 0);
-		snd_caiaq_input_report_abs(dev, ABS_Y, buf, 1);
-		snd_caiaq_input_report_abs(dev, ABS_Z, buf, 2);
+		snd_caiaq_input_report_abs(cdev, ABS_X, buf, 0);
+		snd_caiaq_input_report_abs(cdev, ABS_Y, buf, 1);
+		snd_caiaq_input_report_abs(cdev, ABS_Z, buf, 2);
 		break;
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
-		snd_caiaq_input_report_abs(dev, ABS_HAT0X, buf, 4);
-		snd_caiaq_input_report_abs(dev, ABS_HAT0Y, buf, 2);
-		snd_caiaq_input_report_abs(dev, ABS_HAT1X, buf, 6);
-		snd_caiaq_input_report_abs(dev, ABS_HAT1Y, buf, 1);
-		snd_caiaq_input_report_abs(dev, ABS_HAT2X, buf, 7);
-		snd_caiaq_input_report_abs(dev, ABS_HAT2Y, buf, 0);
-		snd_caiaq_input_report_abs(dev, ABS_HAT3X, buf, 5);
-		snd_caiaq_input_report_abs(dev, ABS_HAT3Y, buf, 3);
+		snd_caiaq_input_report_abs(cdev, ABS_HAT0X, buf, 4);
+		snd_caiaq_input_report_abs(cdev, ABS_HAT0Y, buf, 2);
+		snd_caiaq_input_report_abs(cdev, ABS_HAT1X, buf, 6);
+		snd_caiaq_input_report_abs(cdev, ABS_HAT1Y, buf, 1);
+		snd_caiaq_input_report_abs(cdev, ABS_HAT2X, buf, 7);
+		snd_caiaq_input_report_abs(cdev, ABS_HAT2Y, buf, 0);
+		snd_caiaq_input_report_abs(cdev, ABS_HAT3X, buf, 5);
+		snd_caiaq_input_report_abs(cdev, ABS_HAT3Y, buf, 3);
 		break;
 	}
 
 	input_sync(input_dev);
 }
 
-static void snd_caiaq_input_read_erp(struct snd_usb_caiaqdev *dev,
+static void snd_caiaq_input_read_erp(struct snd_usb_caiaqdev *cdev,
 				     const char *buf, unsigned int len)
 {
-	struct input_dev *input_dev = dev->input_dev;
+	struct input_dev *input_dev = cdev->input_dev;
 	int i;
 
-	switch (dev->chip.usb_id) {
+	switch (cdev->chip.usb_id) {
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AK1):
 		i = decode_erp(buf[0], buf[1]);
 		input_report_abs(input_dev, ABS_X, i);
@@ -299,10 +300,10 @@ static void snd_caiaq_input_read_erp(struct snd_usb_caiaqdev *dev,
 	}
 }
 
-static void snd_caiaq_input_read_io(struct snd_usb_caiaqdev *dev,
+static void snd_caiaq_input_read_io(struct snd_usb_caiaqdev *cdev,
 				    unsigned char *buf, unsigned int len)
 {
-	struct input_dev *input_dev = dev->input_dev;
+	struct input_dev *input_dev = cdev->input_dev;
 	unsigned short *keycode = input_dev->keycode;
 	int i;
 
@@ -317,17 +318,17 @@ static void snd_caiaq_input_read_io(struct snd_usb_caiaqdev *dev,
 		input_report_key(input_dev, keycode[i],
 				 buf[i / 8] & (1 << (i % 8)));
 
-	switch (dev->chip.usb_id) {
+	switch (cdev->chip.usb_id) {
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER):
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER2):
-		input_report_abs(dev->input_dev, ABS_MISC, 255 - buf[4]);
+		input_report_abs(cdev->input_dev, ABS_MISC, 255 - buf[4]);
 		break;
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
 		/* rotary encoders */
-		input_report_abs(dev->input_dev, ABS_X, buf[5] & 0xf);
-		input_report_abs(dev->input_dev, ABS_Y, buf[5] >> 4);
-		input_report_abs(dev->input_dev, ABS_Z, buf[6] & 0xf);
-		input_report_abs(dev->input_dev, ABS_MISC, buf[6] >> 4);
+		input_report_abs(cdev->input_dev, ABS_X, buf[5] & 0xf);
+		input_report_abs(cdev->input_dev, ABS_Y, buf[5] >> 4);
+		input_report_abs(cdev->input_dev, ABS_Z, buf[6] & 0xf);
+		input_report_abs(cdev->input_dev, ABS_MISC, buf[6] >> 4);
 		break;
 	}
 
@@ -336,10 +337,12 @@ static void snd_caiaq_input_read_io(struct snd_usb_caiaqdev *dev,
 
 #define TKS4_MSGBLOCK_SIZE	16
 
-static void snd_usb_caiaq_tks4_dispatch(struct snd_usb_caiaqdev *dev,
+static void snd_usb_caiaq_tks4_dispatch(struct snd_usb_caiaqdev *cdev,
 					const unsigned char *buf,
 					unsigned int len)
 {
+	struct device *dev = caiaqdev_to_dev(cdev);
+
 	while (len) {
 		unsigned int i, block_id = (buf[0] << 8) | buf[1];
 
@@ -347,126 +350,126 @@ static void snd_usb_caiaq_tks4_dispatch(struct snd_usb_caiaqdev *dev,
 		case 0:
 			/* buttons */
 			for (i = 0; i < KONTROLS4_BUTTONS; i++)
-				input_report_key(dev->input_dev, KONTROLS4_BUTTON(i),
+				input_report_key(cdev->input_dev, KONTROLS4_BUTTON(i),
 						 (buf[4 + (i / 8)] >> (i % 8)) & 1);
 			break;
 
 		case 1:
 			/* left wheel */
-			input_report_abs(dev->input_dev, KONTROLS4_ABS(36), buf[9] | ((buf[8] & 0x3) << 8));
+			input_report_abs(cdev->input_dev, KONTROLS4_ABS(36), buf[9] | ((buf[8] & 0x3) << 8));
 			/* right wheel */
-			input_report_abs(dev->input_dev, KONTROLS4_ABS(37), buf[13] | ((buf[12] & 0x3) << 8));
+			input_report_abs(cdev->input_dev, KONTROLS4_ABS(37), buf[13] | ((buf[12] & 0x3) << 8));
 
 			/* rotary encoders */
-			input_report_abs(dev->input_dev, KONTROLS4_ABS(38), buf[3] & 0xf);
-			input_report_abs(dev->input_dev, KONTROLS4_ABS(39), buf[4] >> 4);
-			input_report_abs(dev->input_dev, KONTROLS4_ABS(40), buf[4] & 0xf);
-			input_report_abs(dev->input_dev, KONTROLS4_ABS(41), buf[5] >> 4);
-			input_report_abs(dev->input_dev, KONTROLS4_ABS(42), buf[5] & 0xf);
-			input_report_abs(dev->input_dev, KONTROLS4_ABS(43), buf[6] >> 4);
-			input_report_abs(dev->input_dev, KONTROLS4_ABS(44), buf[6] & 0xf);
-			input_report_abs(dev->input_dev, KONTROLS4_ABS(45), buf[7] >> 4);
-			input_report_abs(dev->input_dev, KONTROLS4_ABS(46), buf[7] & 0xf);
+			input_report_abs(cdev->input_dev, KONTROLS4_ABS(38), buf[3] & 0xf);
+			input_report_abs(cdev->input_dev, KONTROLS4_ABS(39), buf[4] >> 4);
+			input_report_abs(cdev->input_dev, KONTROLS4_ABS(40), buf[4] & 0xf);
+			input_report_abs(cdev->input_dev, KONTROLS4_ABS(41), buf[5] >> 4);
+			input_report_abs(cdev->input_dev, KONTROLS4_ABS(42), buf[5] & 0xf);
+			input_report_abs(cdev->input_dev, KONTROLS4_ABS(43), buf[6] >> 4);
+			input_report_abs(cdev->input_dev, KONTROLS4_ABS(44), buf[6] & 0xf);
+			input_report_abs(cdev->input_dev, KONTROLS4_ABS(45), buf[7] >> 4);
+			input_report_abs(cdev->input_dev, KONTROLS4_ABS(46), buf[7] & 0xf);
 
 			break;
 		case 2:
 			/* Volume Fader Channel D */
-			snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(0), buf, 1);
+			snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(0), buf, 1);
 			/* Volume Fader Channel B */
-			snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(1), buf, 2);
+			snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(1), buf, 2);
 			/* Volume Fader Channel A */
-			snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(2), buf, 3);
+			snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(2), buf, 3);
 			/* Volume Fader Channel C */
-			snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(3), buf, 4);
+			snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(3), buf, 4);
 			/* Loop Volume */
-			snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(4), buf, 6);
+			snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(4), buf, 6);
 			/* Crossfader */
-			snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(7), buf, 7);
+			snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(7), buf, 7);
 
 			break;
 
 		case 3:
 			/* Tempo Fader R */
-			snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(6), buf, 3);
+			snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(6), buf, 3);
 			/* Tempo Fader L */
-			snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(5), buf, 4);
+			snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(5), buf, 4);
 			/* Mic Volume */
-			snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(8), buf, 6);
+			snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(8), buf, 6);
 			/* Cue Mix */
-			snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(9), buf, 7);
+			snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(9), buf, 7);
 
 			break;
 
 		case 4:
 			/* Wheel distance sensor L */
-			snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(10), buf, 1);
+			snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(10), buf, 1);
 			/* Wheel distance sensor R */
-			snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(11), buf, 2);
+			snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(11), buf, 2);
 			/* Channel D EQ - Filter */
-			snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(12), buf, 3);
+			snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(12), buf, 3);
 			/* Channel D EQ - Low */
-			snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(13), buf, 4);
+			snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(13), buf, 4);
 			/* Channel D EQ - Mid */
-			snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(14), buf, 5);
+			snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(14), buf, 5);
 			/* Channel D EQ - Hi */
-			snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(15), buf, 6);
+			snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(15), buf, 6);
 			/* FX2 - dry/wet */
-			snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(16), buf, 7);
+			snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(16), buf, 7);
 
 			break;
 
 		case 5:
 			/* FX2 - 1 */
-			snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(17), buf, 1);
+			snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(17), buf, 1);
 			/* FX2 - 2 */
-			snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(18), buf, 2);
+			snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(18), buf, 2);
 			/* FX2 - 3 */
-			snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(19), buf, 3);
+			snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(19), buf, 3);
 			/* Channel B EQ - Filter */
-			snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(20), buf, 4);
+			snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(20), buf, 4);
 			/* Channel B EQ - Low */
-			snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(21), buf, 5);
+			snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(21), buf, 5);
 			/* Channel B EQ - Mid */
-			snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(22), buf, 6);
+			snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(22), buf, 6);
 			/* Channel B EQ - Hi */
-			snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(23), buf, 7);
+			snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(23), buf, 7);
 
 			break;
 
 		case 6:
 			/* Channel A EQ - Filter */
-			snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(24), buf, 1);
+			snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(24), buf, 1);
 			/* Channel A EQ - Low */
-			snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(25), buf, 2);
+			snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(25), buf, 2);
 			/* Channel A EQ - Mid */
-			snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(26), buf, 3);
+			snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(26), buf, 3);
 			/* Channel A EQ - Hi */
-			snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(27), buf, 4);
+			snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(27), buf, 4);
 			/* Channel C EQ - Filter */
-			snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(28), buf, 5);
+			snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(28), buf, 5);
 			/* Channel C EQ - Low */
-			snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(29), buf, 6);
+			snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(29), buf, 6);
 			/* Channel C EQ - Mid */
-			snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(30), buf, 7);
+			snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(30), buf, 7);
 
 			break;
 
 		case 7:
 			/* Channel C EQ - Hi */
-			snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(31), buf, 1);
+			snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(31), buf, 1);
 			/* FX1 - wet/dry */
-			snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(32), buf, 2);
+			snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(32), buf, 2);
 			/* FX1 - 1 */
-			snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(33), buf, 3);
+			snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(33), buf, 3);
 			/* FX1 - 2 */
-			snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(34), buf, 4);
+			snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(34), buf, 4);
 			/* FX1 - 3 */
-			snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(35), buf, 5);
+			snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(35), buf, 5);
 
 			break;
 
 		default:
-			debug("%s(): bogus block (id %d)\n",
+			dev_dbg(dev, "%s(): bogus block (id %d)\n",
 				__func__, block_id);
 			return;
 		}
@@ -475,12 +478,12 @@ static void snd_usb_caiaq_tks4_dispatch(struct snd_usb_caiaqdev *dev,
 		buf += TKS4_MSGBLOCK_SIZE;
 	}
 
-	input_sync(dev->input_dev);
+	input_sync(cdev->input_dev);
 }
 
 #define MASCHINE_MSGBLOCK_SIZE 2
 
-static void snd_usb_caiaq_maschine_dispatch(struct snd_usb_caiaqdev *dev,
+static void snd_usb_caiaq_maschine_dispatch(struct snd_usb_caiaqdev *cdev,
 					const unsigned char *buf,
 					unsigned int len)
 {
@@ -491,65 +494,66 @@ static void snd_usb_caiaq_maschine_dispatch(struct snd_usb_caiaqdev *dev,
 		pressure = be16_to_cpu(buf[i * 2] << 8 | buf[(i * 2) + 1]);
 		pad_id = pressure >> 12;
 
-		input_report_abs(dev->input_dev, MASCHINE_PAD(pad_id), pressure & 0xfff);
+		input_report_abs(cdev->input_dev, MASCHINE_PAD(pad_id), pressure & 0xfff);
 	}
 
-	input_sync(dev->input_dev);
+	input_sync(cdev->input_dev);
 }
 
 static void snd_usb_caiaq_ep4_reply_dispatch(struct urb *urb)
 {
-	struct snd_usb_caiaqdev *dev = urb->context;
+	struct snd_usb_caiaqdev *cdev = urb->context;
 	unsigned char *buf = urb->transfer_buffer;
+	struct device *dev = &urb->dev->dev;
 	int ret;
 
-	if (urb->status || !dev || urb != dev->ep4_in_urb)
+	if (urb->status || !cdev || urb != cdev->ep4_in_urb)
 		return;
 
-	switch (dev->chip.usb_id) {
+	switch (cdev->chip.usb_id) {
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
 		if (urb->actual_length < 24)
 			goto requeue;
 
 		if (buf[0] & 0x3)
-			snd_caiaq_input_read_io(dev, buf + 1, 7);
+			snd_caiaq_input_read_io(cdev, buf + 1, 7);
 
 		if (buf[0] & 0x4)
-			snd_caiaq_input_read_analog(dev, buf + 8, 16);
+			snd_caiaq_input_read_analog(cdev, buf + 8, 16);
 
 		break;
 
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLS4):
-		snd_usb_caiaq_tks4_dispatch(dev, buf, urb->actual_length);
+		snd_usb_caiaq_tks4_dispatch(cdev, buf, urb->actual_length);
 		break;
 
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_MASCHINECONTROLLER):
 		if (urb->actual_length < (MASCHINE_PADS * MASCHINE_MSGBLOCK_SIZE))
 			goto requeue;
 
-		snd_usb_caiaq_maschine_dispatch(dev, buf, urb->actual_length);
+		snd_usb_caiaq_maschine_dispatch(cdev, buf, urb->actual_length);
 		break;
 	}
 
 requeue:
-	dev->ep4_in_urb->actual_length = 0;
-	ret = usb_submit_urb(dev->ep4_in_urb, GFP_ATOMIC);
+	cdev->ep4_in_urb->actual_length = 0;
+	ret = usb_submit_urb(cdev->ep4_in_urb, GFP_ATOMIC);
 	if (ret < 0)
-		log("unable to submit urb. OOM!?\n");
+		dev_err(dev, "unable to submit urb. OOM!?\n");
 }
 
 static int snd_usb_caiaq_input_open(struct input_dev *idev)
 {
-	struct snd_usb_caiaqdev *dev = input_get_drvdata(idev);
+	struct snd_usb_caiaqdev *cdev = input_get_drvdata(idev);
 
-	if (!dev)
+	if (!cdev)
 		return -EINVAL;
 
-	switch (dev->chip.usb_id) {
+	switch (cdev->chip.usb_id) {
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLS4):
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_MASCHINECONTROLLER):
-		if (usb_submit_urb(dev->ep4_in_urb, GFP_KERNEL) != 0)
+		if (usb_submit_urb(cdev->ep4_in_urb, GFP_KERNEL) != 0)
 			return -EIO;
 		break;
 	}
@@ -559,43 +563,43 @@ static int snd_usb_caiaq_input_open(struct input_dev *idev)
 
 static void snd_usb_caiaq_input_close(struct input_dev *idev)
 {
-	struct snd_usb_caiaqdev *dev = input_get_drvdata(idev);
+	struct snd_usb_caiaqdev *cdev = input_get_drvdata(idev);
 
-	if (!dev)
+	if (!cdev)
 		return;
 
-	switch (dev->chip.usb_id) {
+	switch (cdev->chip.usb_id) {
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLS4):
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_MASCHINECONTROLLER):
-		usb_kill_urb(dev->ep4_in_urb);
+		usb_kill_urb(cdev->ep4_in_urb);
 		break;
 	}
 }
 
-void snd_usb_caiaq_input_dispatch(struct snd_usb_caiaqdev *dev,
+void snd_usb_caiaq_input_dispatch(struct snd_usb_caiaqdev *cdev,
 				  char *buf,
 				  unsigned int len)
 {
-	if (!dev->input_dev || len < 1)
+	if (!cdev->input_dev || len < 1)
 		return;
 
 	switch (buf[0]) {
 	case EP1_CMD_READ_ANALOG:
-		snd_caiaq_input_read_analog(dev, buf + 1, len - 1);
+		snd_caiaq_input_read_analog(cdev, buf + 1, len - 1);
 		break;
 	case EP1_CMD_READ_ERP:
-		snd_caiaq_input_read_erp(dev, buf + 1, len - 1);
+		snd_caiaq_input_read_erp(cdev, buf + 1, len - 1);
 		break;
 	case EP1_CMD_READ_IO:
-		snd_caiaq_input_read_io(dev, buf + 1, len - 1);
+		snd_caiaq_input_read_io(cdev, buf + 1, len - 1);
 		break;
 	}
 }
 
-int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *dev)
+int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *cdev)
 {
-	struct usb_device *usb_dev = dev->chip.dev;
+	struct usb_device *usb_dev = cdev->chip.dev;
 	struct input_dev *input;
 	int i, ret = 0;
 
@@ -603,49 +607,49 @@ int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *dev)
 	if (!input)
 		return -ENOMEM;
 
-	usb_make_path(usb_dev, dev->phys, sizeof(dev->phys));
-	strlcat(dev->phys, "/input0", sizeof(dev->phys));
+	usb_make_path(usb_dev, cdev->phys, sizeof(cdev->phys));
+	strlcat(cdev->phys, "/input0", sizeof(cdev->phys));
 
-	input->name = dev->product_name;
-	input->phys = dev->phys;
+	input->name = cdev->product_name;
+	input->phys = cdev->phys;
 	usb_to_input_id(usb_dev, &input->id);
 	input->dev.parent = &usb_dev->dev;
 
-	input_set_drvdata(input, dev);
+	input_set_drvdata(input, cdev);
 
-	switch (dev->chip.usb_id) {
+	switch (cdev->chip.usb_id) {
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL2):
 		input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
 		input->absbit[0] = BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) |
 			BIT_MASK(ABS_Z);
-		BUILD_BUG_ON(sizeof(dev->keycode) < sizeof(keycode_rk2));
-		memcpy(dev->keycode, keycode_rk2, sizeof(keycode_rk2));
+		BUILD_BUG_ON(sizeof(cdev->keycode) < sizeof(keycode_rk2));
+		memcpy(cdev->keycode, keycode_rk2, sizeof(keycode_rk2));
 		input->keycodemax = ARRAY_SIZE(keycode_rk2);
 		input_set_abs_params(input, ABS_X, 0, 4096, 0, 10);
 		input_set_abs_params(input, ABS_Y, 0, 4096, 0, 10);
 		input_set_abs_params(input, ABS_Z, 0, 4096, 0, 10);
-		snd_usb_caiaq_set_auto_msg(dev, 1, 10, 0);
+		snd_usb_caiaq_set_auto_msg(cdev, 1, 10, 0);
 		break;
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL3):
 		input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
 		input->absbit[0] = BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) |
 			BIT_MASK(ABS_Z);
-		BUILD_BUG_ON(sizeof(dev->keycode) < sizeof(keycode_rk3));
-		memcpy(dev->keycode, keycode_rk3, sizeof(keycode_rk3));
+		BUILD_BUG_ON(sizeof(cdev->keycode) < sizeof(keycode_rk3));
+		memcpy(cdev->keycode, keycode_rk3, sizeof(keycode_rk3));
 		input->keycodemax = ARRAY_SIZE(keycode_rk3);
 		input_set_abs_params(input, ABS_X, 0, 1024, 0, 10);
 		input_set_abs_params(input, ABS_Y, 0, 1024, 0, 10);
 		input_set_abs_params(input, ABS_Z, 0, 1024, 0, 10);
-		snd_usb_caiaq_set_auto_msg(dev, 1, 10, 0);
+		snd_usb_caiaq_set_auto_msg(cdev, 1, 10, 0);
 		break;
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AK1):
 		input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
 		input->absbit[0] = BIT_MASK(ABS_X);
-		BUILD_BUG_ON(sizeof(dev->keycode) < sizeof(keycode_ak1));
-		memcpy(dev->keycode, keycode_ak1, sizeof(keycode_ak1));
+		BUILD_BUG_ON(sizeof(cdev->keycode) < sizeof(keycode_ak1));
+		memcpy(cdev->keycode, keycode_ak1, sizeof(keycode_ak1));
 		input->keycodemax = ARRAY_SIZE(keycode_ak1);
 		input_set_abs_params(input, ABS_X, 0, 999, 0, 10);
-		snd_usb_caiaq_set_auto_msg(dev, 1, 0, 5);
+		snd_usb_caiaq_set_auto_msg(cdev, 1, 0, 5);
 		break;
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER):
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER2):
@@ -657,8 +661,8 @@ int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *dev)
 				   BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) |
 				   BIT_MASK(ABS_Z);
 		input->absbit[BIT_WORD(ABS_MISC)] |= BIT_MASK(ABS_MISC);
-		BUILD_BUG_ON(sizeof(dev->keycode) < sizeof(keycode_kore));
-		memcpy(dev->keycode, keycode_kore, sizeof(keycode_kore));
+		BUILD_BUG_ON(sizeof(cdev->keycode) < sizeof(keycode_kore));
+		memcpy(cdev->keycode, keycode_kore, sizeof(keycode_kore));
 		input->keycodemax = ARRAY_SIZE(keycode_kore);
 		input_set_abs_params(input, ABS_HAT0X, 0, 999, 0, 10);
 		input_set_abs_params(input, ABS_HAT0Y, 0, 999, 0, 10);
@@ -672,7 +676,7 @@ int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *dev)
 		input_set_abs_params(input, ABS_Y, 0, 4096, 0, 10);
 		input_set_abs_params(input, ABS_Z, 0, 4096, 0, 10);
 		input_set_abs_params(input, ABS_MISC, 0, 255, 0, 1);
-		snd_usb_caiaq_set_auto_msg(dev, 1, 10, 5);
+		snd_usb_caiaq_set_auto_msg(cdev, 1, 10, 5);
 		break;
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
 		input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
@@ -683,9 +687,9 @@ int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *dev)
 				   BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) |
 				   BIT_MASK(ABS_Z);
 		input->absbit[BIT_WORD(ABS_MISC)] |= BIT_MASK(ABS_MISC);
-		BUILD_BUG_ON(sizeof(dev->keycode) < KONTROLX1_INPUTS);
+		BUILD_BUG_ON(sizeof(cdev->keycode) < KONTROLX1_INPUTS);
 		for (i = 0; i < KONTROLX1_INPUTS; i++)
-			dev->keycode[i] = BTN_MISC + i;
+			cdev->keycode[i] = BTN_MISC + i;
 		input->keycodemax = KONTROLX1_INPUTS;
 
 		/* analog potentiometers */
@@ -704,26 +708,26 @@ int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *dev)
 		input_set_abs_params(input, ABS_Z, 0, 0xf, 0, 1);
 		input_set_abs_params(input, ABS_MISC, 0, 0xf, 0, 1);
 
-		dev->ep4_in_urb = usb_alloc_urb(0, GFP_KERNEL);
-		if (!dev->ep4_in_urb) {
+		cdev->ep4_in_urb = usb_alloc_urb(0, GFP_KERNEL);
+		if (!cdev->ep4_in_urb) {
 			ret = -ENOMEM;
 			goto exit_free_idev;
 		}
 
-		usb_fill_bulk_urb(dev->ep4_in_urb, usb_dev,
+		usb_fill_bulk_urb(cdev->ep4_in_urb, usb_dev,
 				  usb_rcvbulkpipe(usb_dev, 0x4),
-				  dev->ep4_in_buf, EP4_BUFSIZE,
-				  snd_usb_caiaq_ep4_reply_dispatch, dev);
+				  cdev->ep4_in_buf, EP4_BUFSIZE,
+				  snd_usb_caiaq_ep4_reply_dispatch, cdev);
 
-		snd_usb_caiaq_set_auto_msg(dev, 1, 10, 5);
+		snd_usb_caiaq_set_auto_msg(cdev, 1, 10, 5);
 
 		break;
 
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLS4):
 		input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
-		BUILD_BUG_ON(sizeof(dev->keycode) < KONTROLS4_BUTTONS);
+		BUILD_BUG_ON(sizeof(cdev->keycode) < KONTROLS4_BUTTONS);
 		for (i = 0; i < KONTROLS4_BUTTONS; i++)
-			dev->keycode[i] = KONTROLS4_BUTTON(i);
+			cdev->keycode[i] = KONTROLS4_BUTTON(i);
 		input->keycodemax = KONTROLS4_BUTTONS;
 
 		for (i = 0; i < KONTROLS4_AXIS; i++) {
@@ -743,18 +747,18 @@ int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *dev)
 		for (i = 0; i < 9; i++)
 			input_set_abs_params(input, KONTROLS4_ABS(38+i), 0, 0xf, 0, 1);
 
-		dev->ep4_in_urb = usb_alloc_urb(0, GFP_KERNEL);
-		if (!dev->ep4_in_urb) {
+		cdev->ep4_in_urb = usb_alloc_urb(0, GFP_KERNEL);
+		if (!cdev->ep4_in_urb) {
 			ret = -ENOMEM;
 			goto exit_free_idev;
 		}
 
-		usb_fill_bulk_urb(dev->ep4_in_urb, usb_dev,
+		usb_fill_bulk_urb(cdev->ep4_in_urb, usb_dev,
 				  usb_rcvbulkpipe(usb_dev, 0x4),
-				  dev->ep4_in_buf, EP4_BUFSIZE,
-				  snd_usb_caiaq_ep4_reply_dispatch, dev);
+				  cdev->ep4_in_buf, EP4_BUFSIZE,
+				  snd_usb_caiaq_ep4_reply_dispatch, cdev);
 
-		snd_usb_caiaq_set_auto_msg(dev, 1, 10, 5);
+		snd_usb_caiaq_set_auto_msg(cdev, 1, 10, 5);
 
 		break;
 
@@ -767,8 +771,8 @@ int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *dev)
 			BIT_MASK(ABS_RX) | BIT_MASK(ABS_RY) |
 			BIT_MASK(ABS_RZ);
 
-		BUILD_BUG_ON(sizeof(dev->keycode) < sizeof(keycode_maschine));
-		memcpy(dev->keycode, keycode_maschine, sizeof(keycode_maschine));
+		BUILD_BUG_ON(sizeof(cdev->keycode) < sizeof(keycode_maschine));
+		memcpy(cdev->keycode, keycode_maschine, sizeof(keycode_maschine));
 		input->keycodemax = ARRAY_SIZE(keycode_maschine);
 
 		for (i = 0; i < MASCHINE_PADS; i++) {
@@ -788,18 +792,18 @@ int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *dev)
 		input_set_abs_params(input, ABS_RY, 0, 999, 0, 10);
 		input_set_abs_params(input, ABS_RZ, 0, 999, 0, 10);
 
-		dev->ep4_in_urb = usb_alloc_urb(0, GFP_KERNEL);
-		if (!dev->ep4_in_urb) {
+		cdev->ep4_in_urb = usb_alloc_urb(0, GFP_KERNEL);
+		if (!cdev->ep4_in_urb) {
 			ret = -ENOMEM;
 			goto exit_free_idev;
 		}
 
-		usb_fill_bulk_urb(dev->ep4_in_urb, usb_dev,
+		usb_fill_bulk_urb(cdev->ep4_in_urb, usb_dev,
 				  usb_rcvbulkpipe(usb_dev, 0x4),
-				  dev->ep4_in_buf, EP4_BUFSIZE,
-				  snd_usb_caiaq_ep4_reply_dispatch, dev);
+				  cdev->ep4_in_buf, EP4_BUFSIZE,
+				  snd_usb_caiaq_ep4_reply_dispatch, cdev);
 
-		snd_usb_caiaq_set_auto_msg(dev, 1, 10, 5);
+		snd_usb_caiaq_set_auto_msg(cdev, 1, 10, 5);
 		break;
 
 	default:
@@ -809,12 +813,12 @@ int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *dev)
 
 	input->open = snd_usb_caiaq_input_open;
 	input->close = snd_usb_caiaq_input_close;
-	input->keycode = dev->keycode;
+	input->keycode = cdev->keycode;
 	input->keycodesize = sizeof(unsigned short);
 	for (i = 0; i < input->keycodemax; i++)
-		__set_bit(dev->keycode[i], input->keybit);
+		__set_bit(cdev->keycode[i], input->keybit);
 
-	dev->input_dev = input;
+	cdev->input_dev = input;
 
 	ret = input_register_device(input);
 	if (ret < 0)
@@ -824,19 +828,19 @@ int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *dev)
 
 exit_free_idev:
 	input_free_device(input);
-	dev->input_dev = NULL;
+	cdev->input_dev = NULL;
 	return ret;
 }
 
-void snd_usb_caiaq_input_free(struct snd_usb_caiaqdev *dev)
+void snd_usb_caiaq_input_free(struct snd_usb_caiaqdev *cdev)
 {
-	if (!dev || !dev->input_dev)
+	if (!cdev || !cdev->input_dev)
 		return;
 
-	usb_kill_urb(dev->ep4_in_urb);
-	usb_free_urb(dev->ep4_in_urb);
-	dev->ep4_in_urb = NULL;
+	usb_kill_urb(cdev->ep4_in_urb);
+	usb_free_urb(cdev->ep4_in_urb);
+	cdev->ep4_in_urb = NULL;
 
-	input_unregister_device(dev->input_dev);
-	dev->input_dev = NULL;
+	input_unregister_device(cdev->input_dev);
+	cdev->input_dev = NULL;
 }
diff --git a/sound/usb/caiaq/input.h b/sound/usb/caiaq/input.h
index ced5355..6014e27 100644
--- a/sound/usb/caiaq/input.h
+++ b/sound/usb/caiaq/input.h
@@ -1,8 +1,8 @@
 #ifndef CAIAQ_INPUT_H
 #define CAIAQ_INPUT_H
 
-void snd_usb_caiaq_input_dispatch(struct snd_usb_caiaqdev *dev, char *buf, unsigned int len);
-int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *dev);
-void snd_usb_caiaq_input_free(struct snd_usb_caiaqdev *dev);
+void snd_usb_caiaq_input_dispatch(struct snd_usb_caiaqdev *cdev, char *buf, unsigned int len);
+int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *cdev);
+void snd_usb_caiaq_input_free(struct snd_usb_caiaqdev *cdev);
 
 #endif
diff --git a/sound/usb/caiaq/midi.c b/sound/usb/caiaq/midi.c
index a1a4708..2d75884 100644
--- a/sound/usb/caiaq/midi.c
+++ b/sound/usb/caiaq/midi.c
@@ -16,6 +16,7 @@
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 */
 
+#include <linux/device.h>
 #include <linux/usb.h>
 #include <linux/gfp.h>
 #include <sound/rawmidi.h>
@@ -37,12 +38,12 @@ static int snd_usb_caiaq_midi_input_close(struct snd_rawmidi_substream *substrea
 
 static void snd_usb_caiaq_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
 {
-	struct snd_usb_caiaqdev *dev = substream->rmidi->private_data;
+	struct snd_usb_caiaqdev *cdev = substream->rmidi->private_data;
 
-	if (!dev)
+	if (!cdev)
 		return;
 
-	dev->midi_receive_substream = up ? substream : NULL;
+	cdev->midi_receive_substream = up ? substream : NULL;
 }
 
 
@@ -53,49 +54,50 @@ static int snd_usb_caiaq_midi_output_open(struct snd_rawmidi_substream *substrea
 
 static int snd_usb_caiaq_midi_output_close(struct snd_rawmidi_substream *substream)
 {
-	struct snd_usb_caiaqdev *dev = substream->rmidi->private_data;
-	if (dev->midi_out_active) {
-		usb_kill_urb(&dev->midi_out_urb);
-		dev->midi_out_active = 0;
+	struct snd_usb_caiaqdev *cdev = substream->rmidi->private_data;
+	if (cdev->midi_out_active) {
+		usb_kill_urb(&cdev->midi_out_urb);
+		cdev->midi_out_active = 0;
 	}
 	return 0;
 }
 
-static void snd_usb_caiaq_midi_send(struct snd_usb_caiaqdev *dev,
+static void snd_usb_caiaq_midi_send(struct snd_usb_caiaqdev *cdev,
 				    struct snd_rawmidi_substream *substream)
 {
 	int len, ret;
+	struct device *dev = caiaqdev_to_dev(cdev);
 
-	dev->midi_out_buf[0] = EP1_CMD_MIDI_WRITE;
-	dev->midi_out_buf[1] = 0; /* port */
-	len = snd_rawmidi_transmit(substream, dev->midi_out_buf + 3,
+	cdev->midi_out_buf[0] = EP1_CMD_MIDI_WRITE;
+	cdev->midi_out_buf[1] = 0; /* port */
+	len = snd_rawmidi_transmit(substream, cdev->midi_out_buf + 3,
 				   EP1_BUFSIZE - 3);
 
 	if (len <= 0)
 		return;
 
-	dev->midi_out_buf[2] = len;
-	dev->midi_out_urb.transfer_buffer_length = len+3;
+	cdev->midi_out_buf[2] = len;
+	cdev->midi_out_urb.transfer_buffer_length = len+3;
 
-	ret = usb_submit_urb(&dev->midi_out_urb, GFP_ATOMIC);
+	ret = usb_submit_urb(&cdev->midi_out_urb, GFP_ATOMIC);
 	if (ret < 0)
-		log("snd_usb_caiaq_midi_send(%p): usb_submit_urb() failed,"
-		    "ret=%d, len=%d\n",
-		    substream, ret, len);
+		dev_err(dev,
+			"snd_usb_caiaq_midi_send(%p): usb_submit_urb() failed,"
+			"ret=%d, len=%d\n", substream, ret, len);
 	else
-		dev->midi_out_active = 1;
+		cdev->midi_out_active = 1;
 }
 
 static void snd_usb_caiaq_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
 {
-	struct snd_usb_caiaqdev *dev = substream->rmidi->private_data;
+	struct snd_usb_caiaqdev *cdev = substream->rmidi->private_data;
 
 	if (up) {
-		dev->midi_out_substream = substream;
-		if (!dev->midi_out_active)
-			snd_usb_caiaq_midi_send(dev, substream);
+		cdev->midi_out_substream = substream;
+		if (!cdev->midi_out_active)
+			snd_usb_caiaq_midi_send(cdev, substream);
 	} else {
-		dev->midi_out_substream = NULL;
+		cdev->midi_out_substream = NULL;
 	}
 }
 
@@ -114,13 +116,13 @@ static struct snd_rawmidi_ops snd_usb_caiaq_midi_input =
 	.trigger =      snd_usb_caiaq_midi_input_trigger,
 };
 
-void snd_usb_caiaq_midi_handle_input(struct snd_usb_caiaqdev *dev,
+void snd_usb_caiaq_midi_handle_input(struct snd_usb_caiaqdev *cdev,
 				     int port, const char *buf, int len)
 {
-	if (!dev->midi_receive_substream)
+	if (!cdev->midi_receive_substream)
 		return;
 
-	snd_rawmidi_receive(dev->midi_receive_substream, buf, len);
+	snd_rawmidi_receive(cdev->midi_receive_substream, buf, len);
 }
 
 int snd_usb_caiaq_midi_init(struct snd_usb_caiaqdev *device)
@@ -160,15 +162,14 @@ int snd_usb_caiaq_midi_init(struct snd_usb_caiaqdev *device)
 
 void snd_usb_caiaq_midi_output_done(struct urb* urb)
 {
-	struct snd_usb_caiaqdev *dev = urb->context;
+	struct snd_usb_caiaqdev *cdev = urb->context;
 
-	dev->midi_out_active = 0;
+	cdev->midi_out_active = 0;
 	if (urb->status != 0)
 		return;
 
-	if (!dev->midi_out_substream)
+	if (!cdev->midi_out_substream)
 		return;
 
-	snd_usb_caiaq_midi_send(dev, dev->midi_out_substream);
+	snd_usb_caiaq_midi_send(cdev, cdev->midi_out_substream);
 }
-
diff --git a/sound/usb/caiaq/midi.h b/sound/usb/caiaq/midi.h
index 380f984..60bf344 100644
--- a/sound/usb/caiaq/midi.h
+++ b/sound/usb/caiaq/midi.h
@@ -1,8 +1,9 @@
 #ifndef CAIAQ_MIDI_H
 #define CAIAQ_MIDI_H
 
-int snd_usb_caiaq_midi_init(struct snd_usb_caiaqdev *dev);
-void snd_usb_caiaq_midi_handle_input(struct snd_usb_caiaqdev *dev, int port, const char *buf, int len);
+int snd_usb_caiaq_midi_init(struct snd_usb_caiaqdev *cdev);
+void snd_usb_caiaq_midi_handle_input(struct snd_usb_caiaqdev *cdev,
+				     int port, const char *buf, int len);
 void snd_usb_caiaq_midi_output_done(struct urb *urb);
 
 #endif /* CAIAQ_MIDI_H */
diff --git a/sound/usb/card.c b/sound/usb/card.c
index 2da8ad7..5254b18 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -82,6 +82,7 @@ static int pid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 };
 static int nrpacks = 8;		/* max. number of packets per urb */
 static int device_setup[SNDRV_CARDS]; /* device parameter for this card */
 static bool ignore_ctl_error;
+static bool autoclock = true;
 
 module_param_array(index, int, NULL, 0444);
 MODULE_PARM_DESC(index, "Index value for the USB audio adapter.");
@@ -100,6 +101,8 @@ MODULE_PARM_DESC(device_setup, "Specific device setup (if needed).");
 module_param(ignore_ctl_error, bool, 0444);
 MODULE_PARM_DESC(ignore_ctl_error,
 		 "Ignore errors from USB controller for mixer interfaces.");
+module_param(autoclock, bool, 0444);
+MODULE_PARM_DESC(autoclock, "Enable auto-clock selection for UAC2 devices (default: yes).");
 
 /*
  * we keep the snd_usb_audio_t instances by ourselves for merging
@@ -354,6 +357,7 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
 	chip->card = card;
 	chip->setup = device_setup[idx];
 	chip->nrpacks = nrpacks;
+	chip->autoclock = autoclock;
 	chip->probing = 1;
 
 	chip->usb_id = USB_ID(le16_to_cpu(dev->descriptor.idVendor),
@@ -645,7 +649,6 @@ void snd_usb_autosuspend(struct snd_usb_audio *chip)
 static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message)
 {
 	struct snd_usb_audio *chip = usb_get_intfdata(intf);
-	struct list_head *p;
 	struct snd_usb_stream *as;
 	struct usb_mixer_interface *mixer;
 
@@ -655,8 +658,7 @@ static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message)
 	if (!PMSG_IS_AUTO(message)) {
 		snd_power_change_state(chip->card, SNDRV_CTL_POWER_D3hot);
 		if (!chip->num_suspended_intf++) {
-			list_for_each(p, &chip->pcm_list) {
-				as = list_entry(p, struct snd_usb_stream, list);
+			list_for_each_entry(as, &chip->pcm_list, list) {
 				snd_pcm_suspend_all(as->pcm);
 				as->substream[0].need_setup_ep =
 					as->substream[1].need_setup_ep = true;
@@ -716,8 +718,7 @@ static struct usb_device_id usb_audio_ids [] = {
       .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL },
     { }						/* Terminating entry */
 };
-
-MODULE_DEVICE_TABLE (usb, usb_audio_ids);
+MODULE_DEVICE_TABLE(usb, usb_audio_ids);
 
 /*
  * entry point for linux usb interface
diff --git a/sound/usb/clock.c b/sound/usb/clock.c
index 5e634a2..ae35e7d 100644
--- a/sound/usb/clock.c
+++ b/sound/usb/clock.c
@@ -99,6 +99,41 @@ static int uac_clock_selector_get_val(struct snd_usb_audio *chip, int selector_i
 	return buf;
 }
 
+static int uac_clock_selector_set_val(struct snd_usb_audio *chip, int selector_id,
+					unsigned char pin)
+{
+	int ret;
+
+	ret = snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0),
+			      UAC2_CS_CUR,
+			      USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
+			      UAC2_CX_CLOCK_SELECTOR << 8,
+			      snd_usb_ctrl_intf(chip) | (selector_id << 8),
+			      &pin, sizeof(pin));
+	if (ret < 0)
+		return ret;
+
+	if (ret != sizeof(pin)) {
+		snd_printk(KERN_ERR
+			"usb-audio:%d: setting selector (id %d) unexpected length %d\n",
+			chip->dev->devnum, selector_id, ret);
+		return -EINVAL;
+	}
+
+	ret = uac_clock_selector_get_val(chip, selector_id);
+	if (ret < 0)
+		return ret;
+
+	if (ret != pin) {
+		snd_printk(KERN_ERR
+			"usb-audio:%d: setting selector (id %d) to %x failed (current: %d)\n",
+			chip->dev->devnum, selector_id, pin, ret);
+		return -EINVAL;
+	}
+
+	return ret;
+}
+
 static bool uac_clock_source_is_valid(struct snd_usb_audio *chip, int source_id)
 {
 	int err;
@@ -131,7 +166,8 @@ static bool uac_clock_source_is_valid(struct snd_usb_audio *chip, int source_id)
 }
 
 static int __uac_clock_find_source(struct snd_usb_audio *chip,
-				   int entity_id, unsigned long *visited)
+				   int entity_id, unsigned long *visited,
+				   bool validate)
 {
 	struct uac_clock_source_descriptor *source;
 	struct uac_clock_selector_descriptor *selector;
@@ -148,12 +184,19 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
 
 	/* first, see if the ID we're looking for is a clock source already */
 	source = snd_usb_find_clock_source(chip->ctrl_intf, entity_id);
-	if (source)
-		return source->bClockID;
+	if (source) {
+		entity_id = source->bClockID;
+		if (validate && !uac_clock_source_is_valid(chip, entity_id)) {
+			snd_printk(KERN_ERR "usb-audio:%d: clock source %d is not valid, cannot use\n",
+				   chip->dev->devnum, entity_id);
+			return -ENXIO;
+		}
+		return entity_id;
+	}
 
 	selector = snd_usb_find_clock_selector(chip->ctrl_intf, entity_id);
 	if (selector) {
-		int ret;
+		int ret, i, cur;
 
 		/* the entity ID we are looking for is a selector.
 		 * find out what it currently selects */
@@ -164,22 +207,49 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
 		/* Selector values are one-based */
 
 		if (ret > selector->bNrInPins || ret < 1) {
-			printk(KERN_ERR
+			snd_printk(KERN_ERR
 				"%s(): selector reported illegal value, id %d, ret %d\n",
 				__func__, selector->bClockID, ret);
 
 			return -EINVAL;
 		}
 
-		return __uac_clock_find_source(chip, selector->baCSourceID[ret-1],
-					       visited);
+		cur = ret;
+		ret = __uac_clock_find_source(chip, selector->baCSourceID[ret - 1],
+					       visited, validate);
+		if (!validate || ret > 0 || !chip->autoclock)
+			return ret;
+
+		/* The current clock source is invalid, try others. */
+		for (i = 1; i <= selector->bNrInPins; i++) {
+			int err;
+
+			if (i == cur)
+				continue;
+
+			ret = __uac_clock_find_source(chip, selector->baCSourceID[i - 1],
+				visited, true);
+			if (ret < 0)
+				continue;
+
+			err = uac_clock_selector_set_val(chip, entity_id, i);
+			if (err < 0)
+				continue;
+
+			snd_printk(KERN_INFO
+				"usb-audio:%d: found and selected valid clock source %d\n",
+				chip->dev->devnum, ret);
+			return ret;
+		}
+
+		return -ENXIO;
 	}
 
 	/* FIXME: multipliers only act as pass-thru element for now */
 	multiplier = snd_usb_find_clock_multiplier(chip->ctrl_intf, entity_id);
 	if (multiplier)
 		return __uac_clock_find_source(chip, multiplier->bCSourceID,
-						visited);
+						visited, validate);
 
 	return -EINVAL;
 }
@@ -195,11 +265,12 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
  *
  * Returns the clock source UnitID (>=0) on success, or an error.
  */
-int snd_usb_clock_find_source(struct snd_usb_audio *chip, int entity_id)
+int snd_usb_clock_find_source(struct snd_usb_audio *chip, int entity_id,
+			      bool validate)
 {
 	DECLARE_BITMAP(visited, 256);
 	memset(visited, 0, sizeof(visited));
-	return __uac_clock_find_source(chip, entity_id, visited);
+	return __uac_clock_find_source(chip, entity_id, visited, validate);
 }
 
 static int set_sample_rate_v1(struct snd_usb_audio *chip, int iface,
@@ -247,52 +318,82 @@ static int set_sample_rate_v1(struct snd_usb_audio *chip, int iface,
 	return 0;
 }
 
+static int get_sample_rate_v2(struct snd_usb_audio *chip, int iface,
+			      int altsetting, int clock)
+{
+	struct usb_device *dev = chip->dev;
+	__le32 data;
+	int err;
+
+	err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR,
+			      USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
+			      UAC2_CS_CONTROL_SAM_FREQ << 8,
+			      snd_usb_ctrl_intf(chip) | (clock << 8),
+			      &data, sizeof(data));
+	if (err < 0) {
+		snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq (v2): err %d\n",
+			   dev->devnum, iface, altsetting, err);
+		return 0;
+	}
+
+	return le32_to_cpu(data);
+}
+
 static int set_sample_rate_v2(struct snd_usb_audio *chip, int iface,
 			      struct usb_host_interface *alts,
 			      struct audioformat *fmt, int rate)
 {
 	struct usb_device *dev = chip->dev;
-	unsigned char data[4];
-	int err, crate;
-	int clock = snd_usb_clock_find_source(chip, fmt->clock);
+	__le32 data;
+	int err, cur_rate, prev_rate;
+	int clock;
+	bool writeable;
+	struct uac_clock_source_descriptor *cs_desc;
 
+	clock = snd_usb_clock_find_source(chip, fmt->clock, true);
 	if (clock < 0)
 		return clock;
 
-	if (!uac_clock_source_is_valid(chip, clock)) {
-		/* TODO: should we try to find valid clock setups by ourself? */
-		snd_printk(KERN_ERR "%d:%d:%d: clock source %d is not valid, cannot use\n",
-			   dev->devnum, iface, fmt->altsetting, clock);
-		return -ENXIO;
-	}
+	prev_rate = get_sample_rate_v2(chip, iface, fmt->altsetting, clock);
+
+	cs_desc = snd_usb_find_clock_source(chip->ctrl_intf, clock);
+	writeable = uac2_control_is_writeable(cs_desc->bmControls, UAC2_CS_CONTROL_SAM_FREQ - 1);
+	if (writeable) {
+		data = cpu_to_le32(rate);
+		err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC2_CS_CUR,
+				      USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
+				      UAC2_CS_CONTROL_SAM_FREQ << 8,
+				      snd_usb_ctrl_intf(chip) | (clock << 8),
+				      &data, sizeof(data));
+		if (err < 0) {
+			snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d (v2): err %d\n",
+				   dev->devnum, iface, fmt->altsetting, rate, err);
+			return err;
+		}
 
-	data[0] = rate;
-	data[1] = rate >> 8;
-	data[2] = rate >> 16;
-	data[3] = rate >> 24;
-	if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC2_CS_CUR,
-				   USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
-				   UAC2_CS_CONTROL_SAM_FREQ << 8,
-				   snd_usb_ctrl_intf(chip) | (clock << 8),
-				   data, sizeof(data))) < 0) {
-		snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d (v2)\n",
-			   dev->devnum, iface, fmt->altsetting, rate);
-		return err;
+		cur_rate = get_sample_rate_v2(chip, iface, fmt->altsetting, clock);
+	} else {
+		cur_rate = prev_rate;
 	}
 
-	if ((err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR,
-				   USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
-				   UAC2_CS_CONTROL_SAM_FREQ << 8,
-				   snd_usb_ctrl_intf(chip) | (clock << 8),
-				   data, sizeof(data))) < 0) {
-		snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq (v2)\n",
-			   dev->devnum, iface, fmt->altsetting);
-		return err;
+	if (cur_rate != rate) {
+		if (!writeable) {
+			snd_printk(KERN_WARNING
+				   "%d:%d:%d: freq mismatch (RO clock): req %d, clock runs @%d\n",
+				   dev->devnum, iface, fmt->altsetting, rate, cur_rate);
+			return -ENXIO;
+		}
+		snd_printd(KERN_WARNING
+			   "current rate %d is different from the runtime rate %d\n",
+			   cur_rate, rate);
 	}
 
-	crate = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
-	if (crate != rate)
-		snd_printd(KERN_WARNING "current rate %d is different from the runtime rate %d\n", crate, rate);
+	/* Some devices doesn't respond to sample rate changes while the
+	 * interface is active. */
+	if (rate != prev_rate) {
+		usb_set_interface(dev, iface, 0);
+		usb_set_interface(dev, iface, fmt->altsetting);
+	}
 
 	return 0;
 }
diff --git a/sound/usb/clock.h b/sound/usb/clock.h
index 4663093..d592e4a 100644
--- a/sound/usb/clock.h
+++ b/sound/usb/clock.h
@@ -5,6 +5,7 @@ int snd_usb_init_sample_rate(struct snd_usb_audio *chip, int iface,
 			     struct usb_host_interface *alts,
 			     struct audioformat *fmt, int rate);
 
-int snd_usb_clock_find_source(struct snd_usb_audio *chip, int entity_id);
+int snd_usb_clock_find_source(struct snd_usb_audio *chip, int entity_id,
+			     bool validate);
 
 #endif /* __USBAUDIO_CLOCK_H */
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index 21049b8..7e9c55a 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -128,7 +128,7 @@ static const char *usb_error_string(int err)
  * Determine whether an endpoint is driven by an implicit feedback
  * data endpoint source.
  */
-int snd_usb_endpoint_implict_feedback_sink(struct snd_usb_endpoint *ep)
+int snd_usb_endpoint_implicit_feedback_sink(struct snd_usb_endpoint *ep)
 {
 	return  ep->sync_master &&
 		ep->sync_master->type == SND_USB_ENDPOINT_TYPE_DATA &&
@@ -363,7 +363,7 @@ static void snd_complete_urb(struct urb *urb)
 		if (unlikely(!test_bit(EP_FLAG_RUNNING, &ep->flags)))
 			goto exit_clear;
 
-		if (snd_usb_endpoint_implict_feedback_sink(ep)) {
+		if (snd_usb_endpoint_implicit_feedback_sink(ep)) {
 			unsigned long flags;
 
 			spin_lock_irqsave(&ep->lock, flags);
@@ -415,14 +415,12 @@ struct snd_usb_endpoint *snd_usb_add_endpoint(struct snd_usb_audio *chip,
 					      struct usb_host_interface *alts,
 					      int ep_num, int direction, int type)
 {
-	struct list_head *p;
 	struct snd_usb_endpoint *ep;
 	int is_playback = direction == SNDRV_PCM_STREAM_PLAYBACK;
 
 	mutex_lock(&chip->mutex);
 
-	list_for_each(p, &chip->ep_list) {
-		ep = list_entry(p, struct snd_usb_endpoint, list);
+	list_for_each_entry(ep, &chip->ep_list, list) {
 		if (ep->ep_num == ep_num &&
 		    ep->iface == alts->desc.bInterfaceNumber &&
 		    ep->alt_idx == alts->desc.bAlternateSetting) {
@@ -607,7 +605,7 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep,
 	else
 		packs_per_ms = 1;
 
-	if (is_playback && !snd_usb_endpoint_implict_feedback_sink(ep)) {
+	if (is_playback && !snd_usb_endpoint_implicit_feedback_sink(ep)) {
 		urb_packs = max(ep->chip->nrpacks, 1);
 		urb_packs = min(urb_packs, (unsigned int) MAX_PACKS);
 	} else {
@@ -616,11 +614,11 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep,
 
 	urb_packs *= packs_per_ms;
 
-	if (sync_ep && !snd_usb_endpoint_implict_feedback_sink(ep))
+	if (sync_ep && !snd_usb_endpoint_implicit_feedback_sink(ep))
 		urb_packs = min(urb_packs, 1U << sync_ep->syncinterval);
 
 	/* decide how many packets to be used */
-	if (is_playback && !snd_usb_endpoint_implict_feedback_sink(ep)) {
+	if (is_playback && !snd_usb_endpoint_implicit_feedback_sink(ep)) {
 		unsigned int minsize, maxpacks;
 		/* determine how small a packet can be */
 		minsize = (ep->freqn >> (16 - ep->datainterval))
@@ -847,7 +845,7 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, bool can_sleep)
 
 	set_bit(EP_FLAG_RUNNING, &ep->flags);
 
-	if (snd_usb_endpoint_implict_feedback_sink(ep)) {
+	if (snd_usb_endpoint_implicit_feedback_sink(ep)) {
 		for (i = 0; i < ep->nurbs; i++) {
 			struct snd_urb_ctx *ctx = ep->urb + i;
 			list_add_tail(&ctx->ready_list, &ep->ready_playback_urbs);
@@ -990,7 +988,7 @@ void snd_usb_handle_sync_urb(struct snd_usb_endpoint *ep,
 	 * and add it to the list of pending urbs. queue_pending_output_urbs()
 	 * will take care of them later.
 	 */
-	if (snd_usb_endpoint_implict_feedback_sink(ep) &&
+	if (snd_usb_endpoint_implicit_feedback_sink(ep) &&
 	    ep->use_count != 0) {
 
 		/* implicit feedback case */
diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h
index 447902d..2287adf 100644
--- a/sound/usb/endpoint.h
+++ b/sound/usb/endpoint.h
@@ -23,7 +23,7 @@ int  snd_usb_endpoint_activate(struct snd_usb_endpoint *ep);
 int  snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep);
 void snd_usb_endpoint_free(struct list_head *head);
 
-int snd_usb_endpoint_implict_feedback_sink(struct snd_usb_endpoint *ep);
+int snd_usb_endpoint_implicit_feedback_sink(struct snd_usb_endpoint *ep);
 int snd_usb_endpoint_next_packet_size(struct snd_usb_endpoint *ep);
 
 void snd_usb_handle_sync_urb(struct snd_usb_endpoint *ep,
diff --git a/sound/usb/format.c b/sound/usb/format.c
index e831ee4..20c7751 100644
--- a/sound/usb/format.c
+++ b/sound/usb/format.c
@@ -43,11 +43,11 @@
  */
 static u64 parse_audio_format_i_type(struct snd_usb_audio *chip,
 				     struct audioformat *fp,
-				     int format, void *_fmt,
+				     unsigned int format, void *_fmt,
 				     int protocol)
 {
 	int sample_width, sample_bytes;
-	u64 pcm_formats;
+	u64 pcm_formats = 0;
 
 	switch (protocol) {
 	case UAC_VERSION_1:
@@ -63,14 +63,17 @@ static u64 parse_audio_format_i_type(struct snd_usb_audio *chip,
 		struct uac_format_type_i_ext_descriptor *fmt = _fmt;
 		sample_width = fmt->bBitResolution;
 		sample_bytes = fmt->bSubslotSize;
+
+		if (format & UAC2_FORMAT_TYPE_I_RAW_DATA)
+			pcm_formats |= SNDRV_PCM_FMTBIT_SPECIAL;
+
 		format <<= 1;
 		break;
 	}
 	}
 
-	pcm_formats = 0;
-
-	if (format == 0 || format == (1 << UAC_FORMAT_TYPE_I_UNDEFINED)) {
+	if ((pcm_formats == 0) &&
+	    (format == 0 || format == (1 << UAC_FORMAT_TYPE_I_UNDEFINED))) {
 		/* some devices don't define this correctly... */
 		snd_printdd(KERN_INFO "%d:%u:%d : format type 0 is detected, processed as PCM\n",
 			    chip->dev->devnum, fp->iface, fp->altsetting);
@@ -277,7 +280,7 @@ static int parse_audio_format_rates_v2(struct snd_usb_audio *chip,
 	struct usb_device *dev = chip->dev;
 	unsigned char tmp[2], *data;
 	int nr_triplets, data_size, ret = 0;
-	int clock = snd_usb_clock_find_source(chip, fp->clock);
+	int clock = snd_usb_clock_find_source(chip, fp->clock, false);
 
 	if (clock < 0) {
 		snd_printk(KERN_ERR "%s(): unable to find clock source (clock %d)\n",
@@ -353,7 +356,7 @@ err:
  * parse the format type I and III descriptors
  */
 static int parse_audio_format_i(struct snd_usb_audio *chip,
-				struct audioformat *fp, int format,
+				struct audioformat *fp, unsigned int format,
 				struct uac_format_type_i_continuous_descriptor *fmt,
 				struct usb_host_interface *iface)
 {
@@ -473,8 +476,9 @@ static int parse_audio_format_ii(struct snd_usb_audio *chip,
 	return ret;
 }
 
-int snd_usb_parse_audio_format(struct snd_usb_audio *chip, struct audioformat *fp,
-			       int format, struct uac_format_type_i_continuous_descriptor *fmt,
+int snd_usb_parse_audio_format(struct snd_usb_audio *chip,
+			       struct audioformat *fp, unsigned int format,
+			       struct uac_format_type_i_continuous_descriptor *fmt,
 			       int stream, struct usb_host_interface *iface)
 {
 	int err;
diff --git a/sound/usb/format.h b/sound/usb/format.h
index 387924f..6f31522 100644
--- a/sound/usb/format.h
+++ b/sound/usb/format.h
@@ -2,7 +2,7 @@
 #define __USBAUDIO_FORMAT_H
 
 int snd_usb_parse_audio_format(struct snd_usb_audio *chip,
-			       struct audioformat *fp, int format,
+			       struct audioformat *fp, unsigned int format,
 			       struct uac_format_type_i_continuous_descriptor *fmt,
 			       int stream, struct usb_host_interface *iface);
 
diff --git a/sound/usb/midi.c b/sound/usb/midi.c
index 34b9bb7..60c7aa7 100644
--- a/sound/usb/midi.c
+++ b/sound/usb/midi.c
@@ -1455,6 +1455,7 @@ void snd_usbmidi_disconnect(struct list_head* p)
 	}
 	del_timer_sync(&umidi->error_timer);
 }
+EXPORT_SYMBOL(snd_usbmidi_disconnect);
 
 static void snd_usbmidi_rawmidi_free(struct snd_rawmidi *rmidi)
 {
@@ -1465,10 +1466,9 @@ static void snd_usbmidi_rawmidi_free(struct snd_rawmidi *rmidi)
 static struct snd_rawmidi_substream *snd_usbmidi_find_substream(struct snd_usb_midi* umidi,
 								int stream, int number)
 {
-	struct list_head* list;
+	struct snd_rawmidi_substream *substream;
 
-	list_for_each(list, &umidi->rmidi->streams[stream].substreams) {
-		struct snd_rawmidi_substream *substream = list_entry(list, struct snd_rawmidi_substream, list);
+	list_for_each_entry(substream, &umidi->rmidi->streams[stream].substreams, list) {
 		if (substream->number == number)
 			return substream;
 	}
@@ -2091,6 +2091,7 @@ void snd_usbmidi_input_stop(struct list_head* p)
 	}
 	umidi->input_running = 0;
 }
+EXPORT_SYMBOL(snd_usbmidi_input_stop);
 
 static void snd_usbmidi_input_start_ep(struct snd_usb_midi_in_endpoint* ep)
 {
@@ -2120,6 +2121,7 @@ void snd_usbmidi_input_start(struct list_head* p)
 		snd_usbmidi_input_start_ep(umidi->endpoints[i].in);
 	umidi->input_running = 1;
 }
+EXPORT_SYMBOL(snd_usbmidi_input_start);
 
 /*
  * Creates and registers everything needed for a MIDI streaming interface.
@@ -2259,8 +2261,4 @@ int snd_usbmidi_create(struct snd_card *card,
 	list_add_tail(&umidi->list, midi_list);
 	return 0;
 }
-
 EXPORT_SYMBOL(snd_usbmidi_create);
-EXPORT_SYMBOL(snd_usbmidi_input_stop);
-EXPORT_SYMBOL(snd_usbmidi_input_start);
-EXPORT_SYMBOL(snd_usbmidi_disconnect);
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index f94397b..754cb5b 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -94,13 +94,11 @@ static snd_pcm_uframes_t snd_usb_pcm_pointer(struct snd_pcm_substream *substream
  */
 static struct audioformat *find_format(struct snd_usb_substream *subs)
 {
-	struct list_head *p;
+	struct audioformat *fp;
 	struct audioformat *found = NULL;
 	int cur_attr = 0, attr;
 
-	list_for_each(p, &subs->fmt_list) {
-		struct audioformat *fp;
-		fp = list_entry(p, struct audioformat, list);
+	list_for_each_entry(fp, &subs->fmt_list, list) {
 		if (!(fp->formats & (1uLL << subs->pcm_format)))
 			continue;
 		if (fp->channels != subs->channels)
@@ -350,6 +348,13 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
 				fmt->iface, fmt->altsetting);
 		subs->interface = fmt->iface;
 		subs->altset_idx = fmt->altset_idx;
+
+		/*
+		 * "Playback Design" products need a 50ms delay after setting the
+		 * USB interface.
+		 */
+		if (le16_to_cpu(dev->descriptor.idVendor) == 0x23ba)
+			mdelay(50);
 	}
 
 	subs->data_endpoint = snd_usb_add_endpoint(subs->stream->chip,
@@ -802,7 +807,7 @@ static int hw_rule_rate(struct snd_pcm_hw_params *params,
 			struct snd_pcm_hw_rule *rule)
 {
 	struct snd_usb_substream *subs = rule->private;
-	struct list_head *p;
+	struct audioformat *fp;
 	struct snd_interval *it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
 	unsigned int rmin, rmax;
 	int changed;
@@ -810,9 +815,7 @@ static int hw_rule_rate(struct snd_pcm_hw_params *params,
 	hwc_debug("hw_rule_rate: (%d,%d)\n", it->min, it->max);
 	changed = 0;
 	rmin = rmax = 0;
-	list_for_each(p, &subs->fmt_list) {
-		struct audioformat *fp;
-		fp = list_entry(p, struct audioformat, list);
+	list_for_each_entry(fp, &subs->fmt_list, list) {
 		if (!hw_check_valid_format(subs, params, fp))
 			continue;
 		if (changed++) {
@@ -856,7 +859,7 @@ static int hw_rule_channels(struct snd_pcm_hw_params *params,
 			    struct snd_pcm_hw_rule *rule)
 {
 	struct snd_usb_substream *subs = rule->private;
-	struct list_head *p;
+	struct audioformat *fp;
 	struct snd_interval *it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
 	unsigned int rmin, rmax;
 	int changed;
@@ -864,9 +867,7 @@ static int hw_rule_channels(struct snd_pcm_hw_params *params,
 	hwc_debug("hw_rule_channels: (%d,%d)\n", it->min, it->max);
 	changed = 0;
 	rmin = rmax = 0;
-	list_for_each(p, &subs->fmt_list) {
-		struct audioformat *fp;
-		fp = list_entry(p, struct audioformat, list);
+	list_for_each_entry(fp, &subs->fmt_list, list) {
 		if (!hw_check_valid_format(subs, params, fp))
 			continue;
 		if (changed++) {
@@ -909,7 +910,7 @@ static int hw_rule_format(struct snd_pcm_hw_params *params,
 			  struct snd_pcm_hw_rule *rule)
 {
 	struct snd_usb_substream *subs = rule->private;
-	struct list_head *p;
+	struct audioformat *fp;
 	struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
 	u64 fbits;
 	u32 oldbits[2];
@@ -917,9 +918,7 @@ static int hw_rule_format(struct snd_pcm_hw_params *params,
 
 	hwc_debug("hw_rule_format: %x:%x\n", fmt->bits[0], fmt->bits[1]);
 	fbits = 0;
-	list_for_each(p, &subs->fmt_list) {
-		struct audioformat *fp;
-		fp = list_entry(p, struct audioformat, list);
+	list_for_each_entry(fp, &subs->fmt_list, list) {
 		if (!hw_check_valid_format(subs, params, fp))
 			continue;
 		fbits |= fp->formats;
@@ -1027,7 +1026,7 @@ static int snd_usb_pcm_check_knot(struct snd_pcm_runtime *runtime,
 
 static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substream *subs)
 {
-	struct list_head *p;
+	struct audioformat *fp;
 	unsigned int pt, ptmin;
 	int param_period_time_if_needed;
 	int err;
@@ -1041,9 +1040,7 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
 	runtime->hw.rates = 0;
 	ptmin = UINT_MAX;
 	/* check min/max rates and channels */
-	list_for_each(p, &subs->fmt_list) {
-		struct audioformat *fp;
-		fp = list_entry(p, struct audioformat, list);
+	list_for_each_entry(fp, &subs->fmt_list, list) {
 		runtime->hw.rates |= fp->rates;
 		if (runtime->hw.rate_min > fp->rate_min)
 			runtime->hw.rate_min = fp->rate_min;
@@ -1274,7 +1271,7 @@ static void prepare_playback_urb(struct snd_usb_substream *subs,
 			}
 		}
 		if (period_elapsed &&
-		    !snd_usb_endpoint_implict_feedback_sink(subs->data_endpoint)) /* finish at the period boundary */
+		    !snd_usb_endpoint_implicit_feedback_sink(subs->data_endpoint)) /* finish at the period boundary */
 			break;
 	}
 	bytes = frames * stride;
diff --git a/sound/usb/proc.c b/sound/usb/proc.c
index d218f76..0182ef6 100644
--- a/sound/usb/proc.c
+++ b/sound/usb/proc.c
@@ -73,15 +73,14 @@ void snd_usb_audio_create_proc(struct snd_usb_audio *chip)
  */
 static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct snd_info_buffer *buffer)
 {
-	struct list_head *p;
+	struct audioformat *fp;
 	static char *sync_types[4] = {
 		"NONE", "ASYNC", "ADAPTIVE", "SYNC"
 	};
 
-	list_for_each(p, &subs->fmt_list) {
-		struct audioformat *fp;
+	list_for_each_entry(fp, &subs->fmt_list, list) {
 		snd_pcm_format_t fmt;
-		fp = list_entry(p, struct audioformat, list);
+
 		snd_iprintf(buffer, "  Interface %d\n", fp->iface);
 		snd_iprintf(buffer, "    Altset %d\n", fp->altsetting);
 		snd_iprintf(buffer, "    Format:");
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
index c39f898..86e4b8c 100644
--- a/sound/usb/quirks-table.h
+++ b/sound/usb/quirks-table.h
@@ -2748,6 +2748,46 @@ YAMAHA_DEVICE(0x7010, "UB99"),
 	}
 },
 {
+	USB_DEVICE(0x1235, 0x0018),
+	.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+		.vendor_name = "Novation",
+		.product_name = "Twitch",
+		.ifnum = QUIRK_ANY_INTERFACE,
+		.type = QUIRK_COMPOSITE,
+		.data = (const struct snd_usb_audio_quirk[]) {
+			{
+				.ifnum = 0,
+				.type = QUIRK_AUDIO_FIXED_ENDPOINT,
+				.data = & (const struct audioformat) {
+					.formats = SNDRV_PCM_FMTBIT_S24_3LE,
+					.channels = 4,
+					.iface = 0,
+					.altsetting = 1,
+					.altset_idx = 1,
+					.attributes = UAC_EP_CS_ATTR_SAMPLE_RATE,
+					.endpoint = 0x01,
+					.ep_attr = USB_ENDPOINT_XFER_ISOC,
+					.rates = SNDRV_PCM_RATE_44100 |
+						 SNDRV_PCM_RATE_48000,
+					.rate_min = 44100,
+					.rate_max = 48000,
+					.nr_rates = 2,
+					.rate_table = (unsigned int[]) {
+						44100, 48000
+					}
+				}
+			},
+			{
+				.ifnum = 1,
+				.type = QUIRK_MIDI_RAW_BYTES
+			},
+			{
+				.ifnum = -1
+			}
+		}
+	}
+},
+{
 	USB_DEVICE_VENDOR_SPEC(0x1235, 0x4661),
 	.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
 		.vendor_name = "Novation",
@@ -2996,7 +3036,6 @@ YAMAHA_DEVICE(0x7010, "UB99"),
 					.attributes = UAC_EP_CS_ATTR_SAMPLE_RATE,
 					.endpoint = 0x02,
 					.ep_attr = 0x01,
-					.maxpacksize = 0x130,
 					.rates = SNDRV_PCM_RATE_44100 |
 						 SNDRV_PCM_RATE_48000,
 					.rate_min = 44100,
@@ -3044,7 +3083,6 @@ YAMAHA_DEVICE(0x7010, "UB99"),
 					.attributes = 0x00,
 					.endpoint = 0x03,
 					.ep_attr = USB_ENDPOINT_SYNC_ASYNC,
-					.maxpacksize = 0x128,
 					.rates = SNDRV_PCM_RATE_48000,
 					.rate_min = 48000,
 					.rate_max = 48000,
@@ -3070,7 +3108,6 @@ YAMAHA_DEVICE(0x7010, "UB99"),
 					.attributes = UAC_EP_CS_ATTR_SAMPLE_RATE,
 					.endpoint = 0x85,
 					.ep_attr = USB_ENDPOINT_SYNC_SYNC,
-					.maxpacksize = 0x128,
 					.rates = SNDRV_PCM_RATE_48000,
 					.rate_min = 48000,
 					.rate_max = 48000,
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index 5325a38..a2ac004 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -165,8 +165,10 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip,
 		return -EINVAL;
 	}
 	alts = &iface->altsetting[fp->altset_idx];
-	fp->datainterval = snd_usb_parse_datainterval(chip, alts);
-	fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
+	if (fp->datainterval == 0)
+		fp->datainterval = snd_usb_parse_datainterval(chip, alts);
+	if (fp->maxpacksize == 0)
+		fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
 	usb_set_interface(chip->dev, fp->iface, 0);
 	snd_usb_init_pitch(chip, fp->iface, alts, fp);
 	snd_usb_init_sample_rate(chip, fp->iface, alts, fp, fp->rate_max);
@@ -446,6 +448,17 @@ static int snd_usb_cm6206_boot_quirk(struct usb_device *dev)
 }
 
 /*
+ * Novation Twitch DJ controller
+ */
+static int snd_usb_twitch_boot_quirk(struct usb_device *dev)
+{
+	/* preemptively set up the device because otherwise the
+	 * raw MIDI endpoints are not active */
+	usb_set_interface(dev, 0, 1);
+	return 0;
+}
+
+/*
  * This call will put the synth in "USB send" mode, i.e it will send MIDI
  * messages through USB (this is disabled at startup). The synth will
  * acknowledge by sending a sysex on endpoint 0x85 and by displaying a USB
@@ -746,6 +759,10 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev,
 		/* Digidesign Mbox 2 */
 		return snd_usb_mbox2_boot_quirk(dev);
 
+	case USB_ID(0x1235, 0x0018):
+		/* Focusrite Novation Twitch */
+		return snd_usb_twitch_boot_quirk(dev);
+
 	case USB_ID(0x133e, 0x0815):
 		/* Access Music VirusTI Desktop */
 		return snd_usb_accessmusic_boot_quirk(dev);
diff --git a/sound/usb/stream.c b/sound/usb/stream.c
index ad181d5..74beea237 100644
--- a/sound/usb/stream.c
+++ b/sound/usb/stream.c
@@ -42,12 +42,11 @@
  */
 static void free_substream(struct snd_usb_substream *subs)
 {
-	struct list_head *p, *n;
+	struct audioformat *fp, *n;
 
 	if (!subs->num_formats)
 		return; /* not initialized */
-	list_for_each_safe(p, n, &subs->fmt_list) {
-		struct audioformat *fp = list_entry(p, struct audioformat, list);
+	list_for_each_entry_safe(fp, n, &subs->fmt_list, list) {
 		kfree(fp->rate_table);
 		kfree(fp->chmap);
 		kfree(fp);
@@ -313,14 +312,12 @@ int snd_usb_add_audio_stream(struct snd_usb_audio *chip,
 			     int stream,
 			     struct audioformat *fp)
 {
-	struct list_head *p;
 	struct snd_usb_stream *as;
 	struct snd_usb_substream *subs;
 	struct snd_pcm *pcm;
 	int err;
 
-	list_for_each(p, &chip->pcm_list) {
-		as = list_entry(p, struct snd_usb_stream, list);
+	list_for_each_entry(as, &chip->pcm_list, list) {
 		if (as->fmt_type != fp->fmt_type)
 			continue;
 		subs = &as->substream[stream];
@@ -332,8 +329,7 @@ int snd_usb_add_audio_stream(struct snd_usb_audio *chip,
 		}
 	}
 	/* look for an empty stream */
-	list_for_each(p, &chip->pcm_list) {
-		as = list_entry(p, struct snd_usb_stream, list);
+	list_for_each_entry(as, &chip->pcm_list, list) {
 		if (as->fmt_type != fp->fmt_type)
 			continue;
 		subs = &as->substream[stream];
@@ -463,7 +459,7 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
 	struct usb_host_interface *alts;
 	struct usb_interface_descriptor *altsd;
 	int i, altno, err, stream;
-	int format = 0, num_channels = 0;
+	unsigned int format = 0, num_channels = 0;
 	struct audioformat *fp = NULL;
 	int num, protocol, clock = 0;
 	struct uac_format_type_i_continuous_descriptor *fmt;
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index 1ac3fd9..bc43bca 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -56,6 +56,7 @@ struct snd_usb_audio {
 
 	int setup;			/* from the 'device_setup' module param */
 	int nrpacks;			/* from the 'nrpacks' module param */
+	bool autoclock;			/* from the 'autoclock' module param */
 
 	struct usb_host_interface *ctrl_intf;	/* the audio control interface */
 };
diff --git a/tools/Makefile b/tools/Makefile
index fa36565..c73c635 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -12,6 +12,7 @@ help:
 	@echo '  turbostat  - Intel CPU idle stats and freq reporting tool'
 	@echo '  usb        - USB testing tools'
 	@echo '  virtio     - vhost test module'
+	@echo '  net        - misc networking tools'
 	@echo '  vm         - misc vm tools'
 	@echo '  x86_energy_perf_policy - Intel energy policy tool'
 	@echo ''
@@ -34,7 +35,7 @@ help:
 cpupower: FORCE
 	$(call descend,power/$@)
 
-cgroup firewire lguest perf usb virtio vm: FORCE
+cgroup firewire lguest perf usb virtio vm net: FORCE
 	$(call descend,$@)
 
 selftests: FORCE
@@ -46,7 +47,7 @@ turbostat x86_energy_perf_policy: FORCE
 cpupower_install:
 	$(call descend,power/$(@:_install=),install)
 
-cgroup_install firewire_install lguest_install perf_install usb_install virtio_install vm_install:
+cgroup_install firewire_install lguest_install perf_install usb_install virtio_install vm_install net_install:
 	$(call descend,$(@:_install=),install)
 
 selftests_install:
@@ -57,12 +58,12 @@ turbostat_install x86_energy_perf_policy_install:
 
 install: cgroup_install cpupower_install firewire_install lguest_install \
 		perf_install selftests_install turbostat_install usb_install \
-		virtio_install vm_install x86_energy_perf_policy_install
+		virtio_install vm_install net_install x86_energy_perf_policy_install
 
 cpupower_clean:
 	$(call descend,power/cpupower,clean)
 
-cgroup_clean firewire_clean lguest_clean perf_clean usb_clean virtio_clean vm_clean:
+cgroup_clean firewire_clean lguest_clean perf_clean usb_clean virtio_clean vm_clean net_clean:
 	$(call descend,$(@:_clean=),clean)
 
 selftests_clean:
@@ -73,6 +74,6 @@ turbostat_clean x86_energy_perf_policy_clean:
 
 clean: cgroup_clean cpupower_clean firewire_clean lguest_clean perf_clean \
 		selftests_clean turbostat_clean usb_clean virtio_clean \
-		vm_clean x86_energy_perf_policy_clean
+		vm_clean net_clean x86_energy_perf_policy_clean
 
 .PHONY: FORCE
diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c
index c800ea4..5a1f648 100644
--- a/tools/hv/hv_kvp_daemon.c
+++ b/tools/hv/hv_kvp_daemon.c
@@ -102,6 +102,10 @@ static struct utsname uts_buf;
 #define MAX_FILE_NAME 100
 #define ENTRIES_PER_BLOCK 50
 
+#ifndef SOL_NETLINK
+#define SOL_NETLINK 270
+#endif
+
 struct kvp_record {
 	char key[HV_KVP_EXCHANGE_MAX_KEY_SIZE];
 	char value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE];
@@ -1407,7 +1411,7 @@ netlink_send(int fd, struct cn_msg *msg)
 
 int main(void)
 {
-	int fd, len, sock_opt;
+	int fd, len, nl_group;
 	int error;
 	struct cn_msg *message;
 	struct pollfd pfd;
@@ -1443,7 +1447,7 @@ int main(void)
 	addr.nl_family = AF_NETLINK;
 	addr.nl_pad = 0;
 	addr.nl_pid = 0;
-	addr.nl_groups = CN_KVP_IDX;
+	addr.nl_groups = 0;
 
 
 	error = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
@@ -1452,8 +1456,8 @@ int main(void)
 		close(fd);
 		exit(EXIT_FAILURE);
 	}
-	sock_opt = addr.nl_groups;
-	setsockopt(fd, 270, 1, &sock_opt, sizeof(sock_opt));
+	nl_group = CN_KVP_IDX;
+	setsockopt(fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, &nl_group, sizeof(nl_group));
 	/*
 	 * Register ourselves with the kernel.
 	 */
@@ -1499,6 +1503,10 @@ int main(void)
 		}
 
 		incoming_msg = (struct nlmsghdr *)kvp_recv_buffer;
+
+		if (incoming_msg->nlmsg_type != NLMSG_DONE)
+			continue;
+
 		incoming_cn_msg = (struct cn_msg *)NLMSG_DATA(incoming_msg);
 		hv_msg = (struct hv_kvp_msg *)incoming_cn_msg->data;
 
diff --git a/tools/hv/hv_vss_daemon.c b/tools/hv/hv_vss_daemon.c
new file mode 100644
index 0000000..9526995
--- /dev/null
+++ b/tools/hv/hv_vss_daemon.c
@@ -0,0 +1,220 @@
+/*
+ * An implementation of the host initiated guest snapshot for Hyper-V.
+ *
+ *
+ * Copyright (C) 2013, Microsoft, Inc.
+ * Author : K. Y. Srinivasan <kys@microsoft.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, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ */
+
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/poll.h>
+#include <linux/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <arpa/inet.h>
+#include <linux/connector.h>
+#include <linux/hyperv.h>
+#include <linux/netlink.h>
+#include <syslog.h>
+
+static char vss_recv_buffer[4096];
+static char vss_send_buffer[4096];
+static struct sockaddr_nl addr;
+
+#ifndef SOL_NETLINK
+#define SOL_NETLINK 270
+#endif
+
+
+static int vss_operate(int operation)
+{
+	char *fs_op;
+	char cmd[512];
+	char buf[512];
+	FILE *file;
+	char *p;
+	char *x;
+	int error;
+
+	switch (operation) {
+	case VSS_OP_FREEZE:
+		fs_op = "-f ";
+		break;
+	case VSS_OP_THAW:
+		fs_op = "-u ";
+		break;
+	}
+
+	file = popen("mount | awk '/^\/dev\// { print $3}'", "r");
+	if (file == NULL)
+		return;
+
+	while ((p = fgets(buf, sizeof(buf), file)) != NULL) {
+		x = strchr(p, '\n');
+		*x = '\0';
+		if (!strncmp(p, "/", sizeof("/")))
+			continue;
+
+		sprintf(cmd, "%s %s %s", "fsfreeze ", fs_op, p);
+		syslog(LOG_INFO, "VSS cmd is %s\n", cmd);
+		error = system(cmd);
+	}
+	pclose(file);
+
+	sprintf(cmd, "%s %s %s", "fsfreeze ", fs_op, "/");
+	syslog(LOG_INFO, "VSS cmd is %s\n", cmd);
+	error = system(cmd);
+
+	return error;
+}
+
+static int netlink_send(int fd, struct cn_msg *msg)
+{
+	struct nlmsghdr *nlh;
+	unsigned int size;
+	struct msghdr message;
+	char buffer[64];
+	struct iovec iov[2];
+
+	size = NLMSG_SPACE(sizeof(struct cn_msg) + msg->len);
+
+	nlh = (struct nlmsghdr *)buffer;
+	nlh->nlmsg_seq = 0;
+	nlh->nlmsg_pid = getpid();
+	nlh->nlmsg_type = NLMSG_DONE;
+	nlh->nlmsg_len = NLMSG_LENGTH(size - sizeof(*nlh));
+	nlh->nlmsg_flags = 0;
+
+	iov[0].iov_base = nlh;
+	iov[0].iov_len = sizeof(*nlh);
+
+	iov[1].iov_base = msg;
+	iov[1].iov_len = size;
+
+	memset(&message, 0, sizeof(message));
+	message.msg_name = &addr;
+	message.msg_namelen = sizeof(addr);
+	message.msg_iov = iov;
+	message.msg_iovlen = 2;
+
+	return sendmsg(fd, &message, 0);
+}
+
+int main(void)
+{
+	int fd, len, nl_group;
+	int error;
+	struct cn_msg *message;
+	struct pollfd pfd;
+	struct nlmsghdr *incoming_msg;
+	struct cn_msg	*incoming_cn_msg;
+	int	op;
+	struct hv_vss_msg *vss_msg;
+
+	daemon(1, 0);
+	openlog("Hyper-V VSS", 0, LOG_USER);
+	syslog(LOG_INFO, "VSS starting; pid is:%d", getpid());
+
+	fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
+	if (fd < 0) {
+		syslog(LOG_ERR, "netlink socket creation failed; error:%d", fd);
+		exit(EXIT_FAILURE);
+	}
+	addr.nl_family = AF_NETLINK;
+	addr.nl_pad = 0;
+	addr.nl_pid = 0;
+	addr.nl_groups = 0;
+
+
+	error = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
+	if (error < 0) {
+		syslog(LOG_ERR, "bind failed; error:%d", error);
+		close(fd);
+		exit(EXIT_FAILURE);
+	}
+	nl_group = CN_VSS_IDX;
+	setsockopt(fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, &nl_group, sizeof(nl_group));
+	/*
+	 * Register ourselves with the kernel.
+	 */
+	message = (struct cn_msg *)vss_send_buffer;
+	message->id.idx = CN_VSS_IDX;
+	message->id.val = CN_VSS_VAL;
+	message->ack = 0;
+	vss_msg = (struct hv_vss_msg *)message->data;
+	vss_msg->vss_hdr.operation = VSS_OP_REGISTER;
+
+	message->len = sizeof(struct hv_vss_msg);
+
+	len = netlink_send(fd, message);
+	if (len < 0) {
+		syslog(LOG_ERR, "netlink_send failed; error:%d", len);
+		close(fd);
+		exit(EXIT_FAILURE);
+	}
+
+	pfd.fd = fd;
+
+	while (1) {
+		struct sockaddr *addr_p = (struct sockaddr *) &addr;
+		socklen_t addr_l = sizeof(addr);
+		pfd.events = POLLIN;
+		pfd.revents = 0;
+		poll(&pfd, 1, -1);
+
+		len = recvfrom(fd, vss_recv_buffer, sizeof(vss_recv_buffer), 0,
+				addr_p, &addr_l);
+
+		if (len < 0 || addr.nl_pid) {
+			syslog(LOG_ERR, "recvfrom failed; pid:%u error:%d %s",
+					addr.nl_pid, errno, strerror(errno));
+			close(fd);
+			return -1;
+		}
+
+		incoming_msg = (struct nlmsghdr *)vss_recv_buffer;
+
+		if (incoming_msg->nlmsg_type != NLMSG_DONE)
+			continue;
+
+		incoming_cn_msg = (struct cn_msg *)NLMSG_DATA(incoming_msg);
+		vss_msg = (struct hv_vss_msg *)incoming_cn_msg->data;
+		op = vss_msg->vss_hdr.operation;
+		error =  HV_S_OK;
+
+		switch (op) {
+		case VSS_OP_FREEZE:
+		case VSS_OP_THAW:
+			error = vss_operate(op);
+			if (error)
+				error = HV_E_FAIL;
+			break;
+		default:
+			syslog(LOG_ERR, "Illegal op:%d\n", op);
+		}
+		vss_msg->error = error;
+		len = netlink_send(fd, incoming_cn_msg);
+		if (len < 0) {
+			syslog(LOG_ERR, "net_link send failed; error:%d", len);
+			exit(EXIT_FAILURE);
+		}
+	}
+
+}
diff --git a/tools/lguest/lguest.txt b/tools/lguest/lguest.txt
index 7203ace..06e1f46 100644
--- a/tools/lguest/lguest.txt
+++ b/tools/lguest/lguest.txt
@@ -70,7 +70,7 @@ Running Lguest:
 
 - Run an lguest as root:
 
-      Documentation/virtual/lguest/lguest 64 vmlinux --tunnet=192.168.19.1 \
+      tools/lguest/lguest 64 vmlinux --tunnet=192.168.19.1 \
         --block=rootfile root=/dev/vda
 
    Explanation:
diff --git a/tools/net/Makefile b/tools/net/Makefile
new file mode 100644
index 0000000..b4444d5
--- /dev/null
+++ b/tools/net/Makefile
@@ -0,0 +1,15 @@
+prefix = /usr
+
+CC = gcc
+
+all : bpf_jit_disasm
+
+bpf_jit_disasm : CFLAGS = -Wall -O2
+bpf_jit_disasm : LDLIBS = -lopcodes -lbfd -ldl
+bpf_jit_disasm : bpf_jit_disasm.o
+
+clean :
+	rm -rf *.o bpf_jit_disasm
+
+install :
+	install bpf_jit_disasm $(prefix)/bin/bpf_jit_disasm
diff --git a/tools/net/bpf_jit_disasm.c b/tools/net/bpf_jit_disasm.c
new file mode 100644
index 0000000..cfe0cdc
--- /dev/null
+++ b/tools/net/bpf_jit_disasm.c
@@ -0,0 +1,199 @@
+/*
+ * Minimal BPF JIT image disassembler
+ *
+ * Disassembles BPF JIT compiler emitted opcodes back to asm insn's for
+ * debugging or verification purposes.
+ *
+ * To get the disassembly of the JIT code, do the following:
+ *
+ *  1) `echo 2 > /proc/sys/net/core/bpf_jit_enable`
+ *  2) Load a BPF filter (e.g. `tcpdump -p -n -s 0 -i eth1 host 192.168.20.0/24`)
+ *  3) Run e.g. `bpf_jit_disasm -o` to read out the last JIT code
+ *
+ * Copyright 2013 Daniel Borkmann <borkmann@redhat.com>
+ * Licensed under the GNU General Public License, version 2.0 (GPLv2)
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <unistd.h>
+#include <string.h>
+#include <bfd.h>
+#include <dis-asm.h>
+#include <sys/klog.h>
+#include <sys/types.h>
+#include <regex.h>
+
+static void get_exec_path(char *tpath, size_t size)
+{
+	char *path;
+	ssize_t len;
+
+	snprintf(tpath, size, "/proc/%d/exe", (int) getpid());
+	tpath[size - 1] = 0;
+
+	path = strdup(tpath);
+	assert(path);
+
+	len = readlink(path, tpath, size);
+	tpath[len] = 0;
+
+	free(path);
+}
+
+static void get_asm_insns(uint8_t *image, size_t len, unsigned long base,
+			  int opcodes)
+{
+	int count, i, pc = 0;
+	char tpath[256];
+	struct disassemble_info info;
+	disassembler_ftype disassemble;
+	bfd *bfdf;
+
+	memset(tpath, 0, sizeof(tpath));
+	get_exec_path(tpath, sizeof(tpath));
+
+	bfdf = bfd_openr(tpath, NULL);
+	assert(bfdf);
+	assert(bfd_check_format(bfdf, bfd_object));
+
+	init_disassemble_info(&info, stdout, (fprintf_ftype) fprintf);
+	info.arch = bfd_get_arch(bfdf);
+	info.mach = bfd_get_mach(bfdf);
+	info.buffer = image;
+	info.buffer_length = len;
+
+	disassemble_init_for_target(&info);
+
+	disassemble = disassembler(bfdf);
+	assert(disassemble);
+
+	do {
+		printf("%4x:\t", pc);
+
+		count = disassemble(pc, &info);
+
+		if (opcodes) {
+			printf("\n\t");
+			for (i = 0; i < count; ++i)
+				printf("%02x ", (uint8_t) image[pc + i]);
+		}
+		printf("\n");
+
+		pc += count;
+	} while(count > 0 && pc < len);
+
+	bfd_close(bfdf);
+}
+
+static char *get_klog_buff(int *klen)
+{
+	int ret, len = klogctl(10, NULL, 0);
+	char *buff = malloc(len);
+
+	assert(buff && klen);
+	ret = klogctl(3, buff, len);
+	assert(ret >= 0);
+	*klen = ret;
+
+	return buff;
+}
+
+static void put_klog_buff(char *buff)
+{
+	free(buff);
+}
+
+static int get_last_jit_image(char *haystack, size_t hlen,
+			      uint8_t *image, size_t ilen,
+			      unsigned long *base)
+{
+	char *ptr, *pptr, *tmp;
+	off_t off = 0;
+	int ret, flen, proglen, pass, ulen = 0;
+	regmatch_t pmatch[1];
+	regex_t regex;
+
+	if (hlen == 0)
+		return 0;
+
+	ret = regcomp(&regex, "flen=[[:alnum:]]+ proglen=[[:digit:]]+ "
+		      "pass=[[:digit:]]+ image=[[:xdigit:]]+", REG_EXTENDED);
+	assert(ret == 0);
+
+	ptr = haystack;
+	while (1) {
+		ret = regexec(&regex, ptr, 1, pmatch, 0);
+		if (ret == 0) {
+			ptr += pmatch[0].rm_eo;
+			off += pmatch[0].rm_eo;
+			assert(off < hlen);
+		} else
+			break;
+	}
+
+	ptr = haystack + off - (pmatch[0].rm_eo - pmatch[0].rm_so);
+	ret = sscanf(ptr, "flen=%d proglen=%d pass=%d image=%lx",
+		     &flen, &proglen, &pass, base);
+	if (ret != 4)
+		return 0;
+
+	tmp = ptr = haystack + off;
+	while ((ptr = strtok(tmp, "\n")) != NULL && ulen < ilen) {
+		tmp = NULL;
+		if (!strstr(ptr, "JIT code"))
+			continue;
+		pptr = ptr;
+		while ((ptr = strstr(pptr, ":")))
+			pptr = ptr + 1;
+		ptr = pptr;
+		do {
+			image[ulen++] = (uint8_t) strtoul(pptr, &pptr, 16);
+			if (ptr == pptr || ulen >= ilen) {
+				ulen--;
+				break;
+			}
+			ptr = pptr;
+		} while (1);
+	}
+
+	assert(ulen == proglen);
+	printf("%d bytes emitted from JIT compiler (pass:%d, flen:%d)\n",
+	       proglen, pass, flen);
+	printf("%lx + <x>:\n", *base);
+
+	regfree(&regex);
+	return ulen;
+}
+
+int main(int argc, char **argv)
+{
+	int len, klen, opcodes = 0;
+	char *kbuff;
+	unsigned long base;
+	uint8_t image[4096];
+
+	if (argc > 1) {
+		if (!strncmp("-o", argv[argc - 1], 2)) {
+			opcodes = 1;
+		} else {
+			printf("usage: bpf_jit_disasm [-o: show opcodes]\n");
+			exit(0);
+		}
+	}
+
+	bfd_init();
+	memset(image, 0, sizeof(image));
+
+	kbuff = get_klog_buff(&klen);
+
+	len = get_last_jit_image(kbuff, klen, image, sizeof(image), &base);
+	if (len > 0 && base > 0)
+		get_asm_insns(image, len, base, opcodes);
+
+	put_klog_buff(kbuff);
+
+	return 0;
+}
diff --git a/tools/power/cpupower/debug/i386/intel_gsic.c b/tools/power/cpupower/debug/i386/intel_gsic.c
index 53f5293..d032c82 100644
--- a/tools/power/cpupower/debug/i386/intel_gsic.c
+++ b/tools/power/cpupower/debug/i386/intel_gsic.c
@@ -66,7 +66,7 @@ int main (void)
 		printf("ecx = 0x%.8x\n", r.ecx);
 		printf("edx = 0x%.8x\n", r.edx);
 		printf("Note also that some BIOS do not support the initial "
-		       "GSIC call, but the newer\nspeeedstep-smi driver may "
+		       "GSIC call, but the newer\nspeedstep-smi driver may "
 		       "work.\nFor this, you need to pass some arguments to "
 		       "the speedstep-smi driver:\n");
 		printf("\tsmi_cmd=0x?? smi_port=0x?? smi_sig=1\n");
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index 6f3214e..35e3dcf 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -1421,6 +1421,7 @@ int has_nehalem_turbo_ratio_limit(unsigned int family, unsigned int model)
 	case 0x3C:	/* HSW */
 	case 0x3F:	/* HSW */
 	case 0x45:	/* HSW */
+	case 0x46:	/* HSW */
 		return 1;
 	case 0x2E:	/* Nehalem-EX Xeon - Beckton */
 	case 0x2F:	/* Westmere-EX Xeon - Eagleton */
@@ -1515,6 +1516,7 @@ void rapl_probe(unsigned int family, unsigned int model)
 	case 0x3C:	/* HSW */
 	case 0x3F:	/* HSW */
 	case 0x45:	/* HSW */
+	case 0x46:	/* HSW */
 		do_rapl = RAPL_PKG | RAPL_CORES | RAPL_GFX;
 		break;
 	case 0x2D:
@@ -1754,6 +1756,7 @@ int is_snb(unsigned int family, unsigned int model)
 	case 0x3C:	/* HSW */
 	case 0x3F:	/* HSW */
 	case 0x45:	/* HSW */
+	case 0x46:	/* HSW */
 		return 1;
 	}
 	return 0;
diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile
index 3cc0ad7..c997e39 100644
--- a/tools/testing/selftests/Makefile
+++ b/tools/testing/selftests/Makefile
@@ -1,10 +1,14 @@
 TARGETS = breakpoints
+TARGETS += epoll
 TARGETS += kcmp
+TARGETS += timers
+TARGETS += ptrace
 TARGETS += mqueue
 TARGETS += vm
 TARGETS += cpu-hotplug
 TARGETS += memory-hotplug
 TARGETS += efivarfs
+TARGETS += net
 
 all:
 	for TARGET in $(TARGETS); do \
diff --git a/tools/testing/selftests/epoll/Makefile b/tools/testing/selftests/epoll/Makefile
new file mode 100644
index 0000000..19806ed
--- /dev/null
+++ b/tools/testing/selftests/epoll/Makefile
@@ -0,0 +1,11 @@
+# Makefile for epoll selftests
+
+all: test_epoll
+%: %.c
+	gcc -pthread -g -o $@ $^
+
+run_tests: all
+	./test_epoll
+
+clean:
+	$(RM) test_epoll
diff --git a/tools/testing/selftests/epoll/test_epoll.c b/tools/testing/selftests/epoll/test_epoll.c
new file mode 100644
index 0000000..1034ed4
--- /dev/null
+++ b/tools/testing/selftests/epoll/test_epoll.c
@@ -0,0 +1,364 @@
+/*
+ *  tools/testing/selftests/epoll/test_epoll.c
+ *
+ *  Copyright 2012 Adobe Systems Incorporated
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Paton J. Lewis <palewis@adobe.com>
+ *
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/epoll.h>
+#include <sys/socket.h>
+
+/*
+ * A pointer to an epoll_item_private structure will be stored in the epoll
+ * item's event structure so that we can get access to the epoll_item_private
+ * data after calling epoll_wait:
+ */
+struct epoll_item_private {
+	int index;  /* Position of this struct within the epoll_items array. */
+	int fd;
+	uint32_t events;
+	pthread_mutex_t mutex;  /* Guards the following variables... */
+	int stop;
+	int status;  /* Stores any error encountered while handling item. */
+	/* The following variable allows us to test whether we have encountered
+	   a problem while attempting to cancel and delete the associated
+	   event. When the test program exits, 'deleted' should be exactly
+	   one. If it is greater than one, then the failed test reflects a real
+	   world situation where we would have tried to access the epoll item's
+	   private data after deleting it: */
+	int deleted;
+};
+
+struct epoll_item_private *epoll_items;
+
+/*
+ * Delete the specified item from the epoll set. In a real-world secneario this
+ * is where we would free the associated data structure, but in this testing
+ * environment we retain the structure so that we can test for double-deletion:
+ */
+void delete_item(int index)
+{
+	__sync_fetch_and_add(&epoll_items[index].deleted, 1);
+}
+
+/*
+ * A pointer to a read_thread_data structure will be passed as the argument to
+ * each read thread:
+ */
+struct read_thread_data {
+	int stop;
+	int status;  /* Indicates any error encountered by the read thread. */
+	int epoll_set;
+};
+
+/*
+ * The function executed by the read threads:
+ */
+void *read_thread_function(void *function_data)
+{
+	struct read_thread_data *thread_data =
+		(struct read_thread_data *)function_data;
+	struct epoll_event event_data;
+	struct epoll_item_private *item_data;
+	char socket_data;
+
+	/* Handle events until we encounter an error or this thread's 'stop'
+	   condition is set: */
+	while (1) {
+		int result = epoll_wait(thread_data->epoll_set,
+					&event_data,
+					1,	/* Number of desired events */
+					1000);  /* Timeout in ms */
+		if (result < 0) {
+			/* Breakpoints signal all threads. Ignore that while
+			   debugging: */
+			if (errno == EINTR)
+				continue;
+			thread_data->status = errno;
+			return 0;
+		} else if (thread_data->stop)
+			return 0;
+		else if (result == 0)  /* Timeout */
+			continue;
+
+		/* We need the mutex here because checking for the stop
+		   condition and re-enabling the epoll item need to be done
+		   together as one atomic operation when EPOLL_CTL_DISABLE is
+		   available: */
+		item_data = (struct epoll_item_private *)event_data.data.ptr;
+		pthread_mutex_lock(&item_data->mutex);
+
+		/* Remove the item from the epoll set if we want to stop
+		   handling that event: */
+		if (item_data->stop)
+			delete_item(item_data->index);
+		else {
+			/* Clear the data that was written to the other end of
+			   our non-blocking socket: */
+			do {
+				if (read(item_data->fd, &socket_data, 1) < 1) {
+					if ((errno == EAGAIN) ||
+					    (errno == EWOULDBLOCK))
+						break;
+					else
+						goto error_unlock;
+				}
+			} while (item_data->events & EPOLLET);
+
+			/* The item was one-shot, so re-enable it: */
+			event_data.events = item_data->events;
+			if (epoll_ctl(thread_data->epoll_set,
+						  EPOLL_CTL_MOD,
+						  item_data->fd,
+						  &event_data) < 0)
+				goto error_unlock;
+		}
+
+		pthread_mutex_unlock(&item_data->mutex);
+	}
+
+error_unlock:
+	thread_data->status = item_data->status = errno;
+	pthread_mutex_unlock(&item_data->mutex);
+	return 0;
+}
+
+/*
+ * A pointer to a write_thread_data structure will be passed as the argument to
+ * the write thread:
+ */
+struct write_thread_data {
+	int stop;
+	int status;  /* Indicates any error encountered by the write thread. */
+	int n_fds;
+	int *fds;
+};
+
+/*
+ * The function executed by the write thread. It writes a single byte to each
+ * socket in turn until the stop condition for this thread is set. If writing to
+ * a socket would block (i.e. errno was EAGAIN), we leave that socket alone for
+ * the moment and just move on to the next socket in the list. We don't care
+ * about the order in which we deliver events to the epoll set. In fact we don't
+ * care about the data we're writing to the pipes at all; we just want to
+ * trigger epoll events:
+ */
+void *write_thread_function(void *function_data)
+{
+	const char data = 'X';
+	int index;
+	struct write_thread_data *thread_data =
+		(struct write_thread_data *)function_data;
+	while (!thread_data->stop)
+		for (index = 0;
+		     !thread_data->stop && (index < thread_data->n_fds);
+		     ++index)
+			if ((write(thread_data->fds[index], &data, 1) < 1) &&
+				(errno != EAGAIN) &&
+				(errno != EWOULDBLOCK)) {
+				thread_data->status = errno;
+				return;
+			}
+}
+
+/*
+ * Arguments are currently ignored:
+ */
+int main(int argc, char **argv)
+{
+	const int n_read_threads = 100;
+	const int n_epoll_items = 500;
+	int index;
+	int epoll_set = epoll_create1(0);
+	struct write_thread_data write_thread_data = {
+		0, 0, n_epoll_items, malloc(n_epoll_items * sizeof(int))
+	};
+	struct read_thread_data *read_thread_data =
+		malloc(n_read_threads * sizeof(struct read_thread_data));
+	pthread_t *read_threads = malloc(n_read_threads * sizeof(pthread_t));
+	pthread_t write_thread;
+	int socket_pair[2];
+	struct epoll_event event_data;
+
+	printf("-----------------\n");
+	printf("Runing test_epoll\n");
+	printf("-----------------\n");
+
+	epoll_items = malloc(n_epoll_items * sizeof(struct epoll_item_private));
+
+	if (epoll_set < 0 || !epoll_items || write_thread_data.fds == NULL ||
+		!read_thread_data || !read_threads)
+		goto error;
+
+	if (sysconf(_SC_NPROCESSORS_ONLN) < 2) {
+		printf("Error: please run this test on a multi-core system.\n");
+		goto error;
+	}
+
+	/* Create the socket pairs and epoll items: */
+	for (index = 0; index < n_epoll_items; ++index) {
+		if (socketpair(AF_UNIX,
+			       SOCK_STREAM | SOCK_NONBLOCK,
+			       0,
+			       socket_pair) < 0)
+			goto error;
+		write_thread_data.fds[index] = socket_pair[0];
+		epoll_items[index].index = index;
+		epoll_items[index].fd = socket_pair[1];
+		if (pthread_mutex_init(&epoll_items[index].mutex, NULL) != 0)
+			goto error;
+		/* We always use EPOLLONESHOT because this test is currently
+		   structured to demonstrate the need for EPOLL_CTL_DISABLE,
+		   which only produces useful information in the EPOLLONESHOT
+		   case (without EPOLLONESHOT, calling epoll_ctl with
+		   EPOLL_CTL_DISABLE will never return EBUSY). If support for
+		   testing events without EPOLLONESHOT is desired, it should
+		   probably be implemented in a separate unit test. */
+		epoll_items[index].events = EPOLLIN | EPOLLONESHOT;
+		if (index < n_epoll_items / 2)
+			epoll_items[index].events |= EPOLLET;
+		epoll_items[index].stop = 0;
+		epoll_items[index].status = 0;
+		epoll_items[index].deleted = 0;
+		event_data.events = epoll_items[index].events;
+		event_data.data.ptr = &epoll_items[index];
+		if (epoll_ctl(epoll_set,
+			      EPOLL_CTL_ADD,
+			      epoll_items[index].fd,
+			      &event_data) < 0)
+			goto error;
+	}
+
+#ifdef EPOLL_CTL_DISABLE
+	/* Test to make sure that using EPOLL_CTL_DISABLE without EPOLLONESHOT
+	   returns a clear error: */
+	if (socketpair(AF_UNIX,
+		       SOCK_STREAM | SOCK_NONBLOCK,
+		       0,
+		       socket_pair) < 0)
+		goto error;
+	event_data.events = EPOLLIN;
+	event_data.data.ptr = NULL;
+	if (epoll_ctl(epoll_set, EPOLL_CTL_ADD,
+		      socket_pair[1], &event_data) < 0)
+		goto error;
+	if ((epoll_ctl(epoll_set, EPOLL_CTL_DISABLE,
+		       socket_pair[1], NULL) == 0) || (errno != EINVAL))
+		goto error;
+	if (epoll_ctl(epoll_set, EPOLL_CTL_DEL, socket_pair[1], NULL) != 0)
+		goto error;
+#endif
+
+	/* Create and start the read threads: */
+	for (index = 0; index < n_read_threads; ++index) {
+		read_thread_data[index].stop = 0;
+		read_thread_data[index].status = 0;
+		read_thread_data[index].epoll_set = epoll_set;
+		if (pthread_create(&read_threads[index],
+				   NULL,
+				   read_thread_function,
+				   &read_thread_data[index]) != 0)
+			goto error;
+	}
+
+	if (pthread_create(&write_thread,
+			   NULL,
+			   write_thread_function,
+			   &write_thread_data) != 0)
+		goto error;
+
+	/* Cancel all event pollers: */
+#ifdef EPOLL_CTL_DISABLE
+	for (index = 0; index < n_epoll_items; ++index) {
+		pthread_mutex_lock(&epoll_items[index].mutex);
+		++epoll_items[index].stop;
+		if (epoll_ctl(epoll_set,
+			      EPOLL_CTL_DISABLE,
+			      epoll_items[index].fd,
+			      NULL) == 0)
+			delete_item(index);
+		else if (errno != EBUSY) {
+			pthread_mutex_unlock(&epoll_items[index].mutex);
+			goto error;
+		}
+		/* EBUSY means events were being handled; allow the other thread
+		   to delete the item. */
+		pthread_mutex_unlock(&epoll_items[index].mutex);
+	}
+#else
+	for (index = 0; index < n_epoll_items; ++index) {
+		pthread_mutex_lock(&epoll_items[index].mutex);
+		++epoll_items[index].stop;
+		pthread_mutex_unlock(&epoll_items[index].mutex);
+		/* Wait in case a thread running read_thread_function is
+		   currently executing code between epoll_wait and
+		   pthread_mutex_lock with this item. Note that a longer delay
+		   would make double-deletion less likely (at the expense of
+		   performance), but there is no guarantee that any delay would
+		   ever be sufficient. Note also that we delete all event
+		   pollers at once for testing purposes, but in a real-world
+		   environment we are likely to want to be able to cancel event
+		   pollers at arbitrary times. Therefore we can't improve this
+		   situation by just splitting this loop into two loops
+		   (i.e. signal 'stop' for all items, sleep, and then delete all
+		   items). We also can't fix the problem via EPOLL_CTL_DEL
+		   because that command can't prevent the case where some other
+		   thread is executing read_thread_function within the region
+		   mentioned above: */
+		usleep(1);
+		pthread_mutex_lock(&epoll_items[index].mutex);
+		if (!epoll_items[index].deleted)
+			delete_item(index);
+		pthread_mutex_unlock(&epoll_items[index].mutex);
+	}
+#endif
+
+	/* Shut down the read threads: */
+	for (index = 0; index < n_read_threads; ++index)
+		__sync_fetch_and_add(&read_thread_data[index].stop, 1);
+	for (index = 0; index < n_read_threads; ++index) {
+		if (pthread_join(read_threads[index], NULL) != 0)
+			goto error;
+		if (read_thread_data[index].status)
+			goto error;
+	}
+
+	/* Shut down the write thread: */
+	__sync_fetch_and_add(&write_thread_data.stop, 1);
+	if ((pthread_join(write_thread, NULL) != 0) || write_thread_data.status)
+		goto error;
+
+	/* Check for final error conditions: */
+	for (index = 0; index < n_epoll_items; ++index) {
+		if (epoll_items[index].status != 0)
+			goto error;
+		if (pthread_mutex_destroy(&epoll_items[index].mutex) < 0)
+			goto error;
+	}
+	for (index = 0; index < n_epoll_items; ++index)
+		if (epoll_items[index].deleted != 1) {
+			printf("Error: item data deleted %1d times.\n",
+				   epoll_items[index].deleted);
+			goto error;
+		}
+
+	printf("[PASS]\n");
+	return 0;
+
+ error:
+	printf("[FAIL]\n");
+	return errno;
+}
diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile
new file mode 100644
index 0000000..bd6e272
--- /dev/null
+++ b/tools/testing/selftests/net/Makefile
@@ -0,0 +1,19 @@
+# Makefile for net selftests
+
+CC = $(CROSS_COMPILE)gcc
+CFLAGS = -Wall
+
+CFLAGS += -I../../../../usr/include/
+
+NET_PROGS = socket psock_fanout
+
+all: $(NET_PROGS)
+%: %.c
+	$(CC) $(CFLAGS) -o $@ $^
+
+run_tests: all
+	@/bin/sh ./run_netsocktests || echo "sockettests: [FAIL]"
+	@/bin/sh ./run_afpackettests || echo "afpackettests: [FAIL]"
+
+clean:
+	$(RM) $(NET_PROGS)
diff --git a/tools/testing/selftests/net/psock_fanout.c b/tools/testing/selftests/net/psock_fanout.c
new file mode 100644
index 0000000..59bd636
--- /dev/null
+++ b/tools/testing/selftests/net/psock_fanout.c
@@ -0,0 +1,394 @@
+/*
+ * Copyright 2013 Google Inc.
+ * Author: Willem de Bruijn (willemb@google.com)
+ *
+ * A basic test of packet socket fanout behavior.
+ *
+ * Control:
+ * - create fanout fails as expected with illegal flag combinations
+ * - join   fanout fails as expected with diverging types or flags
+ *
+ * Datapath:
+ *   Open a pair of packet sockets and a pair of INET sockets, send a known
+ *   number of packets across the two INET sockets and count the number of
+ *   packets enqueued onto the two packet sockets.
+ *
+ *   The test currently runs for
+ *   - PACKET_FANOUT_HASH
+ *   - PACKET_FANOUT_HASH with PACKET_FANOUT_FLAG_ROLLOVER
+ *   - PACKET_FANOUT_LB
+ *   - PACKET_FANOUT_CPU
+ *   - PACKET_FANOUT_ROLLOVER
+ *
+ * Todo:
+ * - functionality: PACKET_FANOUT_FLAG_DEFRAG
+ *
+ * License (GPLv2):
+ *
+ * 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.
+ */
+
+#define _GNU_SOURCE		/* for sched_setaffinity */
+
+#include <arpa/inet.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <linux/filter.h>
+#include <linux/if_packet.h>
+#include <net/ethernet.h>
+#include <netinet/ip.h>
+#include <netinet/udp.h>
+#include <poll.h>
+#include <sched.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#define DATA_LEN			100
+#define DATA_CHAR			'a'
+#define RING_NUM_FRAMES			20
+#define PORT_BASE			8000
+
+static void pair_udp_open(int fds[], uint16_t port)
+{
+	struct sockaddr_in saddr, daddr;
+
+	fds[0] = socket(PF_INET, SOCK_DGRAM, 0);
+	fds[1] = socket(PF_INET, SOCK_DGRAM, 0);
+	if (fds[0] == -1 || fds[1] == -1) {
+		fprintf(stderr, "ERROR: socket dgram\n");
+		exit(1);
+	}
+
+	memset(&saddr, 0, sizeof(saddr));
+	saddr.sin_family = AF_INET;
+	saddr.sin_port = htons(port);
+	saddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+
+	memset(&daddr, 0, sizeof(daddr));
+	daddr.sin_family = AF_INET;
+	daddr.sin_port = htons(port + 1);
+	daddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+
+	/* must bind both to get consistent hash result */
+	if (bind(fds[1], (void *) &daddr, sizeof(daddr))) {
+		perror("bind");
+		exit(1);
+	}
+	if (bind(fds[0], (void *) &saddr, sizeof(saddr))) {
+		perror("bind");
+		exit(1);
+	}
+	if (connect(fds[0], (void *) &daddr, sizeof(daddr))) {
+		perror("connect");
+		exit(1);
+	}
+}
+
+static void pair_udp_send(int fds[], int num)
+{
+	char buf[DATA_LEN], rbuf[DATA_LEN];
+
+	memset(buf, DATA_CHAR, sizeof(buf));
+	while (num--) {
+		/* Should really handle EINTR and EAGAIN */
+		if (write(fds[0], buf, sizeof(buf)) != sizeof(buf)) {
+			fprintf(stderr, "ERROR: send failed left=%d\n", num);
+			exit(1);
+		}
+		if (read(fds[1], rbuf, sizeof(rbuf)) != sizeof(rbuf)) {
+			fprintf(stderr, "ERROR: recv failed left=%d\n", num);
+			exit(1);
+		}
+		if (memcmp(buf, rbuf, sizeof(buf))) {
+			fprintf(stderr, "ERROR: data failed left=%d\n", num);
+			exit(1);
+		}
+	}
+}
+
+static void sock_fanout_setfilter(int fd)
+{
+	struct sock_filter bpf_filter[] = {
+		{ 0x80, 0, 0, 0x00000000 },  /* LD  pktlen		      */
+		{ 0x35, 0, 5, DATA_LEN   },  /* JGE DATA_LEN  [f goto nomatch]*/
+		{ 0x30, 0, 0, 0x00000050 },  /* LD  ip[80]		      */
+		{ 0x15, 0, 3, DATA_CHAR  },  /* JEQ DATA_CHAR [f goto nomatch]*/
+		{ 0x30, 0, 0, 0x00000051 },  /* LD  ip[81]		      */
+		{ 0x15, 0, 1, DATA_CHAR  },  /* JEQ DATA_CHAR [f goto nomatch]*/
+		{ 0x6, 0, 0, 0x00000060  },  /* RET match	              */
+/* nomatch */	{ 0x6, 0, 0, 0x00000000  },  /* RET no match		      */
+	};
+	struct sock_fprog bpf_prog;
+
+	bpf_prog.filter = bpf_filter;
+	bpf_prog.len = sizeof(bpf_filter) / sizeof(struct sock_filter);
+	if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &bpf_prog,
+		       sizeof(bpf_prog))) {
+		perror("setsockopt SO_ATTACH_FILTER");
+		exit(1);
+	}
+}
+
+/* Open a socket in a given fanout mode.
+ * @return -1 if mode is bad, a valid socket otherwise */
+static int sock_fanout_open(uint16_t typeflags, int num_packets)
+{
+	int fd, val;
+
+	fd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP));
+	if (fd < 0) {
+		perror("socket packet");
+		exit(1);
+	}
+
+	/* fanout group ID is always 0: tests whether old groups are deleted */
+	val = ((int) typeflags) << 16;
+	if (setsockopt(fd, SOL_PACKET, PACKET_FANOUT, &val, sizeof(val))) {
+		if (close(fd)) {
+			perror("close packet");
+			exit(1);
+		}
+		return -1;
+	}
+
+	sock_fanout_setfilter(fd);
+	return fd;
+}
+
+static char *sock_fanout_open_ring(int fd)
+{
+	struct tpacket_req req = {
+		.tp_block_size = getpagesize(),
+		.tp_frame_size = getpagesize(),
+		.tp_block_nr   = RING_NUM_FRAMES,
+		.tp_frame_nr   = RING_NUM_FRAMES,
+	};
+	char *ring;
+	int val = TPACKET_V2;
+
+	if (setsockopt(fd, SOL_PACKET, PACKET_VERSION, (void *) &val,
+		       sizeof(val))) {
+		perror("packetsock ring setsockopt version");
+		exit(1);
+	}
+	if (setsockopt(fd, SOL_PACKET, PACKET_RX_RING, (void *) &req,
+		       sizeof(req))) {
+		perror("packetsock ring setsockopt");
+		exit(1);
+	}
+
+	ring = mmap(0, req.tp_block_size * req.tp_block_nr,
+		    PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+	if (!ring) {
+		fprintf(stderr, "packetsock ring mmap\n");
+		exit(1);
+	}
+
+	return ring;
+}
+
+static int sock_fanout_read_ring(int fd, void *ring)
+{
+	struct tpacket2_hdr *header = ring;
+	int count = 0;
+
+	while (header->tp_status & TP_STATUS_USER && count < RING_NUM_FRAMES) {
+		count++;
+		header = ring + (count * getpagesize());
+	}
+
+	return count;
+}
+
+static int sock_fanout_read(int fds[], char *rings[], const int expect[])
+{
+	int ret[2];
+
+	ret[0] = sock_fanout_read_ring(fds[0], rings[0]);
+	ret[1] = sock_fanout_read_ring(fds[1], rings[1]);
+
+	fprintf(stderr, "info: count=%d,%d, expect=%d,%d\n",
+			ret[0], ret[1], expect[0], expect[1]);
+
+	if ((!(ret[0] == expect[0] && ret[1] == expect[1])) &&
+	    (!(ret[0] == expect[1] && ret[1] == expect[0]))) {
+		fprintf(stderr, "ERROR: incorrect queue lengths\n");
+		return 1;
+	}
+
+	return 0;
+}
+
+/* Test illegal mode + flag combination */
+static void test_control_single(void)
+{
+	fprintf(stderr, "test: control single socket\n");
+
+	if (sock_fanout_open(PACKET_FANOUT_ROLLOVER |
+			       PACKET_FANOUT_FLAG_ROLLOVER, 0) != -1) {
+		fprintf(stderr, "ERROR: opened socket with dual rollover\n");
+		exit(1);
+	}
+}
+
+/* Test illegal group with different modes or flags */
+static void test_control_group(void)
+{
+	int fds[2];
+
+	fprintf(stderr, "test: control multiple sockets\n");
+
+	fds[0] = sock_fanout_open(PACKET_FANOUT_HASH, 20);
+	if (fds[0] == -1) {
+		fprintf(stderr, "ERROR: failed to open HASH socket\n");
+		exit(1);
+	}
+	if (sock_fanout_open(PACKET_FANOUT_HASH |
+			       PACKET_FANOUT_FLAG_DEFRAG, 10) != -1) {
+		fprintf(stderr, "ERROR: joined group with wrong flag defrag\n");
+		exit(1);
+	}
+	if (sock_fanout_open(PACKET_FANOUT_HASH |
+			       PACKET_FANOUT_FLAG_ROLLOVER, 10) != -1) {
+		fprintf(stderr, "ERROR: joined group with wrong flag ro\n");
+		exit(1);
+	}
+	if (sock_fanout_open(PACKET_FANOUT_CPU, 10) != -1) {
+		fprintf(stderr, "ERROR: joined group with wrong mode\n");
+		exit(1);
+	}
+	fds[1] = sock_fanout_open(PACKET_FANOUT_HASH, 20);
+	if (fds[1] == -1) {
+		fprintf(stderr, "ERROR: failed to join group\n");
+		exit(1);
+	}
+	if (close(fds[1]) || close(fds[0])) {
+		fprintf(stderr, "ERROR: closing sockets\n");
+		exit(1);
+	}
+}
+
+static int test_datapath(uint16_t typeflags, int port_off,
+			 const int expect1[], const int expect2[])
+{
+	const int expect0[] = { 0, 0 };
+	char *rings[2];
+	int fds[2], fds_udp[2][2], ret;
+
+	fprintf(stderr, "test: datapath 0x%hx\n", typeflags);
+
+	fds[0] = sock_fanout_open(typeflags, 20);
+	fds[1] = sock_fanout_open(typeflags, 20);
+	if (fds[0] == -1 || fds[1] == -1) {
+		fprintf(stderr, "ERROR: failed open\n");
+		exit(1);
+	}
+	rings[0] = sock_fanout_open_ring(fds[0]);
+	rings[1] = sock_fanout_open_ring(fds[1]);
+	pair_udp_open(fds_udp[0], PORT_BASE);
+	pair_udp_open(fds_udp[1], PORT_BASE + port_off);
+	sock_fanout_read(fds, rings, expect0);
+
+	/* Send data, but not enough to overflow a queue */
+	pair_udp_send(fds_udp[0], 15);
+	pair_udp_send(fds_udp[1], 5);
+	ret = sock_fanout_read(fds, rings, expect1);
+
+	/* Send more data, overflow the queue */
+	pair_udp_send(fds_udp[0], 15);
+	/* TODO: ensure consistent order between expect1 and expect2 */
+	ret |= sock_fanout_read(fds, rings, expect2);
+
+	if (munmap(rings[1], RING_NUM_FRAMES * getpagesize()) ||
+	    munmap(rings[0], RING_NUM_FRAMES * getpagesize())) {
+		fprintf(stderr, "close rings\n");
+		exit(1);
+	}
+	if (close(fds_udp[1][1]) || close(fds_udp[1][0]) ||
+	    close(fds_udp[0][1]) || close(fds_udp[0][0]) ||
+	    close(fds[1]) || close(fds[0])) {
+		fprintf(stderr, "close datapath\n");
+		exit(1);
+	}
+
+	return ret;
+}
+
+static int set_cpuaffinity(int cpuid)
+{
+	cpu_set_t mask;
+
+	CPU_ZERO(&mask);
+	CPU_SET(cpuid, &mask);
+	if (sched_setaffinity(0, sizeof(mask), &mask)) {
+		if (errno != EINVAL) {
+			fprintf(stderr, "setaffinity %d\n", cpuid);
+			exit(1);
+		}
+		return 1;
+	}
+
+	return 0;
+}
+
+int main(int argc, char **argv)
+{
+	const int expect_hash[2][2]	= { { 15, 5 },  { 20, 5 } };
+	const int expect_hash_rb[2][2]	= { { 15, 5 },  { 20, 15 } };
+	const int expect_lb[2][2]	= { { 10, 10 }, { 18, 17 } };
+	const int expect_rb[2][2]	= { { 20, 0 },  { 20, 15 } };
+	const int expect_cpu0[2][2]	= { { 20, 0 },  { 20, 0 } };
+	const int expect_cpu1[2][2]	= { { 0, 20 },  { 0, 20 } };
+	int port_off = 2, tries = 5, ret;
+
+	test_control_single();
+	test_control_group();
+
+	/* find a set of ports that do not collide onto the same socket */
+	ret = test_datapath(PACKET_FANOUT_HASH, port_off,
+			    expect_hash[0], expect_hash[1]);
+	while (ret && tries--) {
+		fprintf(stderr, "info: trying alternate ports (%d)\n", tries);
+		ret = test_datapath(PACKET_FANOUT_HASH, ++port_off,
+				    expect_hash[0], expect_hash[1]);
+	}
+
+	ret |= test_datapath(PACKET_FANOUT_HASH | PACKET_FANOUT_FLAG_ROLLOVER,
+			     port_off, expect_hash_rb[0], expect_hash_rb[1]);
+	ret |= test_datapath(PACKET_FANOUT_LB,
+			     port_off, expect_lb[0], expect_lb[1]);
+	ret |= test_datapath(PACKET_FANOUT_ROLLOVER,
+			     port_off, expect_rb[0], expect_rb[1]);
+
+	set_cpuaffinity(0);
+	ret |= test_datapath(PACKET_FANOUT_CPU, port_off,
+			     expect_cpu0[0], expect_cpu0[1]);
+	if (!set_cpuaffinity(1))
+		/* TODO: test that choice alternates with previous */
+		ret |= test_datapath(PACKET_FANOUT_CPU, port_off,
+				     expect_cpu1[0], expect_cpu1[1]);
+
+	if (ret)
+		return 1;
+
+	printf("OK. All tests passed\n");
+	return 0;
+}
diff --git a/tools/testing/selftests/net/run_afpackettests b/tools/testing/selftests/net/run_afpackettests
new file mode 100644
index 0000000..7907824
--- /dev/null
+++ b/tools/testing/selftests/net/run_afpackettests
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+if [ $(id -u) != 0 ]; then
+	echo $msg must be run as root >&2
+	exit 0
+fi
+
+echo "--------------------"
+echo "running psock_fanout test"
+echo "--------------------"
+./psock_fanout
+if [ $? -ne 0 ]; then
+	echo "[FAIL]"
+else
+	echo "[PASS]"
+fi
diff --git a/tools/testing/selftests/net/run_netsocktests b/tools/testing/selftests/net/run_netsocktests
new file mode 100644
index 0000000..c09a682
--- /dev/null
+++ b/tools/testing/selftests/net/run_netsocktests
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+echo "--------------------"
+echo "running socket test"
+echo "--------------------"
+./socket
+if [ $? -ne 0 ]; then
+	echo "[FAIL]"
+else
+	echo "[PASS]"
+fi
+
diff --git a/tools/testing/selftests/net/socket.c b/tools/testing/selftests/net/socket.c
new file mode 100644
index 0000000..0f227f2
--- /dev/null
+++ b/tools/testing/selftests/net/socket.c
@@ -0,0 +1,92 @@
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+struct socket_testcase {
+	int	domain;
+	int	type;
+	int	protocol;
+
+	/* 0    = valid file descriptor
+	 * -foo = error foo
+	 */
+	int	expect;
+
+	/* If non-zero, accept EAFNOSUPPORT to handle the case
+	 * of the protocol not being configured into the kernel.
+	 */
+	int	nosupport_ok;
+};
+
+static struct socket_testcase tests[] = {
+	{ AF_MAX,  0,           0,           -EAFNOSUPPORT,    0 },
+	{ AF_INET, SOCK_STREAM, IPPROTO_TCP, 0,                1  },
+	{ AF_INET, SOCK_DGRAM,  IPPROTO_TCP, -EPROTONOSUPPORT, 1  },
+	{ AF_INET, SOCK_DGRAM,  IPPROTO_UDP, 0,                1  },
+	{ AF_INET, SOCK_STREAM, IPPROTO_UDP, -EPROTONOSUPPORT, 1  },
+};
+
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+#define ERR_STRING_SZ	64
+
+static int run_tests(void)
+{
+	char err_string1[ERR_STRING_SZ];
+	char err_string2[ERR_STRING_SZ];
+	int i, err;
+
+	err = 0;
+	for (i = 0; i < ARRAY_SIZE(tests); i++) {
+		struct socket_testcase *s = &tests[i];
+		int fd;
+
+		fd = socket(s->domain, s->type, s->protocol);
+		if (fd < 0) {
+			if (s->nosupport_ok &&
+			    errno == EAFNOSUPPORT)
+				continue;
+
+			if (s->expect < 0 &&
+			    errno == -s->expect)
+				continue;
+
+			strerror_r(-s->expect, err_string1, ERR_STRING_SZ);
+			strerror_r(errno, err_string2, ERR_STRING_SZ);
+
+			fprintf(stderr, "socket(%d, %d, %d) expected "
+				"err (%s) got (%s)\n",
+				s->domain, s->type, s->protocol,
+				err_string1, err_string2);
+
+			err = -1;
+			break;
+		} else {
+			close(fd);
+
+			if (s->expect < 0) {
+				strerror_r(errno, err_string1, ERR_STRING_SZ);
+
+				fprintf(stderr, "socket(%d, %d, %d) expected "
+					"success got err (%s)\n",
+					s->domain, s->type, s->protocol,
+					err_string1);
+
+				err = -1;
+				break;
+			}
+		}
+	}
+
+	return err;
+}
+
+int main(void)
+{
+	int err = run_tests();
+
+	return err;
+}
diff --git a/tools/testing/selftests/ptrace/Makefile b/tools/testing/selftests/ptrace/Makefile
new file mode 100644
index 0000000..47ae2d3
--- /dev/null
+++ b/tools/testing/selftests/ptrace/Makefile
@@ -0,0 +1,10 @@
+CFLAGS += -iquote../../../../include/uapi -Wall
+peeksiginfo: peeksiginfo.c
+
+all: peeksiginfo
+
+clean:
+	rm -f peeksiginfo
+
+run_tests: all
+	@./peeksiginfo || echo "peeksiginfo selftests: [FAIL]"
diff --git a/tools/testing/selftests/ptrace/peeksiginfo.c b/tools/testing/selftests/ptrace/peeksiginfo.c
new file mode 100644
index 0000000..d46558b
--- /dev/null
+++ b/tools/testing/selftests/ptrace/peeksiginfo.c
@@ -0,0 +1,214 @@
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <signal.h>
+#include <unistd.h>
+#include <errno.h>
+#include <linux/types.h>
+#include <sys/wait.h>
+#include <sys/syscall.h>
+#include <sys/user.h>
+#include <sys/mman.h>
+
+#include "linux/ptrace.h"
+
+static int sys_rt_sigqueueinfo(pid_t tgid, int sig, siginfo_t *uinfo)
+{
+	return syscall(SYS_rt_sigqueueinfo, tgid, sig, uinfo);
+}
+
+static int sys_rt_tgsigqueueinfo(pid_t tgid, pid_t tid,
+					int sig, siginfo_t *uinfo)
+{
+	return syscall(SYS_rt_tgsigqueueinfo, tgid, tid, sig, uinfo);
+}
+
+static int sys_ptrace(int request, pid_t pid, void *addr, void *data)
+{
+	return syscall(SYS_ptrace, request, pid, addr, data);
+}
+
+#define SIGNR 10
+#define TEST_SICODE_PRIV	-1
+#define TEST_SICODE_SHARE	-2
+
+#define err(fmt, ...)						\
+		fprintf(stderr,					\
+			"Error (%s:%d): " fmt,			\
+			__FILE__, __LINE__, ##__VA_ARGS__)
+
+static int check_error_paths(pid_t child)
+{
+	struct ptrace_peeksiginfo_args arg;
+	int ret, exit_code = -1;
+	void *addr_rw, *addr_ro;
+
+	/*
+	 * Allocate two contiguous pages. The first one is for read-write,
+	 * another is for read-only.
+	 */
+	addr_rw = mmap(NULL, 2 * PAGE_SIZE, PROT_READ | PROT_WRITE,
+				MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+	if (addr_rw == MAP_FAILED) {
+		err("mmap() failed: %m\n");
+		return 1;
+	}
+
+	addr_ro = mmap(addr_rw + PAGE_SIZE, PAGE_SIZE, PROT_READ,
+			MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
+	if (addr_ro == MAP_FAILED) {
+		err("mmap() failed: %m\n");
+		goto out;
+	}
+
+	arg.nr = SIGNR;
+	arg.off = 0;
+
+	/* Unsupported flags */
+	arg.flags = ~0;
+	ret = sys_ptrace(PTRACE_PEEKSIGINFO, child, &arg, addr_rw);
+	if (ret != -1 || errno != EINVAL) {
+		err("sys_ptrace() returns %d (expected -1),"
+				" errno %d (expected %d): %m\n",
+				ret, errno, EINVAL);
+		goto out;
+	}
+	arg.flags = 0;
+
+	/* A part of the buffer is read-only */
+	ret = sys_ptrace(PTRACE_PEEKSIGINFO, child, &arg,
+					addr_ro - sizeof(siginfo_t) * 2);
+	if (ret != 2) {
+		err("sys_ptrace() returns %d (expected 2): %m\n", ret);
+		goto out;
+	}
+
+	/* Read-only buffer */
+	ret = sys_ptrace(PTRACE_PEEKSIGINFO, child, &arg, addr_ro);
+	if (ret != -1 && errno != EFAULT) {
+		err("sys_ptrace() returns %d (expected -1),"
+				" errno %d (expected %d): %m\n",
+				ret, errno, EFAULT);
+		goto out;
+	}
+
+	exit_code = 0;
+out:
+	munmap(addr_rw, 2 * PAGE_SIZE);
+	return exit_code;
+}
+
+int check_direct_path(pid_t child, int shared, int nr)
+{
+	struct ptrace_peeksiginfo_args arg = {.flags = 0, .nr = nr, .off = 0};
+	int i, j, ret, exit_code = -1;
+	siginfo_t siginfo[SIGNR];
+	int si_code;
+
+	if (shared == 1) {
+		arg.flags = PTRACE_PEEKSIGINFO_SHARED;
+		si_code = TEST_SICODE_SHARE;
+	} else {
+		arg.flags = 0;
+		si_code = TEST_SICODE_PRIV;
+	}
+
+	for (i = 0; i < SIGNR; ) {
+		arg.off = i;
+		ret = sys_ptrace(PTRACE_PEEKSIGINFO, child, &arg, siginfo);
+		if (ret == -1) {
+			err("ptrace() failed: %m\n");
+			goto out;
+		}
+
+		if (ret == 0)
+			break;
+
+		for (j = 0; j < ret; j++, i++) {
+			if (siginfo[j].si_code == si_code &&
+			    siginfo[j].si_int == i)
+				continue;
+
+			err("%d: Wrong siginfo i=%d si_code=%d si_int=%d\n",
+			     shared, i, siginfo[j].si_code, siginfo[j].si_int);
+			goto out;
+		}
+	}
+
+	if (i != SIGNR) {
+		err("Only %d signals were read\n", i);
+		goto out;
+	}
+
+	exit_code = 0;
+out:
+	return exit_code;
+}
+
+int main(int argc, char *argv[])
+{
+	siginfo_t siginfo[SIGNR];
+	int i, exit_code = 1;
+	sigset_t blockmask;
+	pid_t child;
+
+	sigemptyset(&blockmask);
+	sigaddset(&blockmask, SIGRTMIN);
+	sigprocmask(SIG_BLOCK, &blockmask, NULL);
+
+	child = fork();
+	if (child == -1) {
+		err("fork() failed: %m");
+		return 1;
+	} else if (child == 0) {
+		pid_t ppid = getppid();
+		while (1) {
+			if (ppid != getppid())
+				break;
+			sleep(1);
+		}
+		return 1;
+	}
+
+	/* Send signals in process-wide and per-thread queues */
+	for (i = 0; i < SIGNR; i++) {
+		siginfo->si_code = TEST_SICODE_SHARE;
+		siginfo->si_int = i;
+		sys_rt_sigqueueinfo(child, SIGRTMIN, siginfo);
+
+		siginfo->si_code = TEST_SICODE_PRIV;
+		siginfo->si_int = i;
+		sys_rt_tgsigqueueinfo(child, child, SIGRTMIN, siginfo);
+	}
+
+	if (sys_ptrace(PTRACE_ATTACH, child, NULL, NULL) == -1)
+		return 1;
+
+	waitpid(child, NULL, 0);
+
+	/* Dump signals one by one*/
+	if (check_direct_path(child, 0, 1))
+		goto out;
+	/* Dump all signals for one call */
+	if (check_direct_path(child, 0, SIGNR))
+		goto out;
+
+	/*
+	 * Dump signal from the process-wide queue.
+	 * The number of signals is not multible to the buffer size
+	 */
+	if (check_direct_path(child, 1, 3))
+		goto out;
+
+	if (check_error_paths(child))
+		goto out;
+
+	printf("PASS\n");
+	exit_code = 0;
+out:
+	if (sys_ptrace(PTRACE_KILL, child, NULL, NULL) == -1)
+		return 1;
+
+	waitpid(child, NULL, 0);
+
+	return exit_code;
+}
diff --git a/tools/testing/selftests/timers/Makefile b/tools/testing/selftests/timers/Makefile
new file mode 100644
index 0000000..eb2859f
--- /dev/null
+++ b/tools/testing/selftests/timers/Makefile
@@ -0,0 +1,8 @@
+all:
+	gcc posix_timers.c -o posix_timers -lrt
+
+run_tests: all
+	./posix_timers
+
+clean:
+	rm -f ./posix_timers
diff --git a/tools/testing/selftests/timers/posix_timers.c b/tools/testing/selftests/timers/posix_timers.c
new file mode 100644
index 0000000..4fa655d
--- /dev/null
+++ b/tools/testing/selftests/timers/posix_timers.c
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) 2013 Red Hat, Inc., Frederic Weisbecker <fweisbec@redhat.com>
+ *
+ * Licensed under the terms of the GNU GPL License version 2
+ *
+ * Selftests for a few posix timers interface.
+ *
+ * Kernel loop code stolen from Steven Rostedt <srostedt@redhat.com>
+ */
+
+#include <sys/time.h>
+#include <stdio.h>
+#include <signal.h>
+#include <unistd.h>
+#include <time.h>
+#include <pthread.h>
+
+#define DELAY 2
+#define USECS_PER_SEC 1000000
+
+static volatile int done;
+
+/* Busy loop in userspace to elapse ITIMER_VIRTUAL */
+static void user_loop(void)
+{
+	while (!done);
+}
+
+/*
+ * Try to spend as much time as possible in kernelspace
+ * to elapse ITIMER_PROF.
+ */
+static void kernel_loop(void)
+{
+	void *addr = sbrk(0);
+
+	while (!done) {
+		brk(addr + 4096);
+		brk(addr);
+	}
+}
+
+/*
+ * Sleep until ITIMER_REAL expiration.
+ */
+static void idle_loop(void)
+{
+	pause();
+}
+
+static void sig_handler(int nr)
+{
+	done = 1;
+}
+
+/*
+ * Check the expected timer expiration matches the GTOD elapsed delta since
+ * we armed the timer. Keep a 0.5 sec error margin due to various jitter.
+ */
+static int check_diff(struct timeval start, struct timeval end)
+{
+	long long diff;
+
+	diff = end.tv_usec - start.tv_usec;
+	diff += (end.tv_sec - start.tv_sec) * USECS_PER_SEC;
+
+	if (abs(diff - DELAY * USECS_PER_SEC) > USECS_PER_SEC / 2) {
+		printf("Diff too high: %lld..", diff);
+		return -1;
+	}
+
+	return 0;
+}
+
+static int check_itimer(int which)
+{
+	int err;
+	struct timeval start, end;
+	struct itimerval val = {
+		.it_value.tv_sec = DELAY,
+	};
+
+	printf("Check itimer ");
+
+	if (which == ITIMER_VIRTUAL)
+		printf("virtual... ");
+	else if (which == ITIMER_PROF)
+		printf("prof... ");
+	else if (which == ITIMER_REAL)
+		printf("real... ");
+
+	fflush(stdout);
+
+	done = 0;
+
+	if (which == ITIMER_VIRTUAL)
+		signal(SIGVTALRM, sig_handler);
+	else if (which == ITIMER_PROF)
+		signal(SIGPROF, sig_handler);
+	else if (which == ITIMER_REAL)
+		signal(SIGALRM, sig_handler);
+
+	err = gettimeofday(&start, NULL);
+	if (err < 0) {
+		perror("Can't call gettimeofday()\n");
+		return -1;
+	}
+
+	err = setitimer(which, &val, NULL);
+	if (err < 0) {
+		perror("Can't set timer\n");
+		return -1;
+	}
+
+	if (which == ITIMER_VIRTUAL)
+		user_loop();
+	else if (which == ITIMER_PROF)
+		kernel_loop();
+	else if (which == ITIMER_REAL)
+		idle_loop();
+
+	gettimeofday(&end, NULL);
+	if (err < 0) {
+		perror("Can't call gettimeofday()\n");
+		return -1;
+	}
+
+	if (!check_diff(start, end))
+		printf("[OK]\n");
+	else
+		printf("[FAIL]\n");
+
+	return 0;
+}
+
+static int check_timer_create(int which)
+{
+	int err;
+	timer_t id;
+	struct timeval start, end;
+	struct itimerspec val = {
+		.it_value.tv_sec = DELAY,
+	};
+
+	printf("Check timer_create() ");
+	if (which == CLOCK_THREAD_CPUTIME_ID) {
+		printf("per thread... ");
+	} else if (which == CLOCK_PROCESS_CPUTIME_ID) {
+		printf("per process... ");
+	}
+	fflush(stdout);
+
+	done = 0;
+	timer_create(which, NULL, &id);
+	if (err < 0) {
+		perror("Can't create timer\n");
+		return -1;
+	}
+	signal(SIGALRM, sig_handler);
+
+	err = gettimeofday(&start, NULL);
+	if (err < 0) {
+		perror("Can't call gettimeofday()\n");
+		return -1;
+	}
+
+	err = timer_settime(id, 0, &val, NULL);
+	if (err < 0) {
+		perror("Can't set timer\n");
+		return -1;
+	}
+
+	user_loop();
+
+	gettimeofday(&end, NULL);
+	if (err < 0) {
+		perror("Can't call gettimeofday()\n");
+		return -1;
+	}
+
+	if (!check_diff(start, end))
+		printf("[OK]\n");
+	else
+		printf("[FAIL]\n");
+
+	return 0;
+}
+
+int main(int argc, char **argv)
+{
+	int err;
+
+	printf("Testing posix timers. False negative may happen on CPU execution \n");
+	printf("based timers if other threads run on the CPU...\n");
+
+	if (check_itimer(ITIMER_VIRTUAL) < 0)
+		return -1;
+
+	if (check_itimer(ITIMER_PROF) < 0)
+		return -1;
+
+	if (check_itimer(ITIMER_REAL) < 0)
+		return -1;
+
+	if (check_timer_create(CLOCK_THREAD_CPUTIME_ID) < 0)
+		return -1;
+
+	/*
+	 * It's unfortunately hard to reliably test a timer expiration
+	 * on parallel multithread cputime. We could arm it to expire
+	 * on DELAY * nr_threads, with nr_threads busy looping, then wait
+	 * the normal DELAY since the time is elapsing nr_threads faster.
+	 * But for that we need to ensure we have real physical free CPUs
+	 * to ensure true parallelism. So test only one thread until we
+	 * find a better solution.
+	 */
+	if (check_timer_create(CLOCK_PROCESS_CPUTIME_ID) < 0)
+		return -1;
+
+	return 0;
+}
diff --git a/tools/virtio/Makefile b/tools/virtio/Makefile
index d1d442e..3187c62 100644
--- a/tools/virtio/Makefile
+++ b/tools/virtio/Makefile
@@ -1,12 +1,14 @@
 all: test mod
-test: virtio_test
+test: virtio_test vringh_test
 virtio_test: virtio_ring.o virtio_test.o
-CFLAGS += -g -O2 -Wall -I. -I ../../usr/include/ -Wno-pointer-sign -fno-strict-overflow  -MMD
-vpath %.c ../../drivers/virtio
+vringh_test: vringh_test.o vringh.o virtio_ring.o
+
+CFLAGS += -g -O2 -Wall -I. -I ../../usr/include/ -Wno-pointer-sign -fno-strict-overflow -fno-strict-aliasing -fno-common -MMD -U_FORTIFY_SOURCE
+vpath %.c ../../drivers/virtio ../../drivers/vhost
 mod:
 	${MAKE} -C `pwd`/../.. M=`pwd`/vhost_test
 .PHONY: all test mod clean
 clean:
-	${RM} *.o vhost_test/*.o vhost_test/.*.cmd \
+	${RM} *.o vringh_test virtio_test vhost_test/*.o vhost_test/.*.cmd \
               vhost_test/Module.symvers vhost_test/modules.order *.d
 -include *.d
diff --git a/tools/virtio/asm/barrier.h b/tools/virtio/asm/barrier.h
new file mode 100644
index 0000000..aff61e1
--- /dev/null
+++ b/tools/virtio/asm/barrier.h
@@ -0,0 +1,14 @@
+#if defined(__i386__) || defined(__x86_64__)
+#define barrier() asm volatile("" ::: "memory")
+#define mb() __sync_synchronize()
+
+#define smp_mb()	mb()
+# define smp_rmb()	barrier()
+# define smp_wmb()	barrier()
+/* Weak barriers should be used. If not - it's a bug */
+# define rmb()	abort()
+# define wmb()	abort()
+#else
+#error Please fill in barrier macros
+#endif
+
diff --git a/tools/virtio/linux/bug.h b/tools/virtio/linux/bug.h
new file mode 100644
index 0000000..fb94f07
--- /dev/null
+++ b/tools/virtio/linux/bug.h
@@ -0,0 +1,10 @@
+#ifndef BUG_H
+#define BUG_H
+
+#define BUG_ON(__BUG_ON_cond) assert(!(__BUG_ON_cond))
+
+#define BUILD_BUG_ON(x)
+
+#define BUG() abort()
+
+#endif /* BUG_H */
diff --git a/tools/virtio/linux/err.h b/tools/virtio/linux/err.h
new file mode 100644
index 0000000..e32eff8
--- /dev/null
+++ b/tools/virtio/linux/err.h
@@ -0,0 +1,26 @@
+#ifndef ERR_H
+#define ERR_H
+#define MAX_ERRNO	4095
+
+#define IS_ERR_VALUE(x) unlikely((x) >= (unsigned long)-MAX_ERRNO)
+
+static inline void * __must_check ERR_PTR(long error)
+{
+	return (void *) error;
+}
+
+static inline long __must_check PTR_ERR(const void *ptr)
+{
+	return (long) ptr;
+}
+
+static inline long __must_check IS_ERR(const void *ptr)
+{
+	return IS_ERR_VALUE((unsigned long)ptr);
+}
+
+static inline long __must_check IS_ERR_OR_NULL(const void *ptr)
+{
+	return !ptr || IS_ERR_VALUE((unsigned long)ptr);
+}
+#endif /* ERR_H */
diff --git a/tools/virtio/linux/export.h b/tools/virtio/linux/export.h
new file mode 100644
index 0000000..7311d32
--- /dev/null
+++ b/tools/virtio/linux/export.h
@@ -0,0 +1,5 @@
+#define EXPORT_SYMBOL(sym)
+#define EXPORT_SYMBOL_GPL(sym)
+#define EXPORT_SYMBOL_GPL_FUTURE(sym)
+#define EXPORT_UNUSED_SYMBOL(sym)
+#define EXPORT_UNUSED_SYMBOL_GPL(sym)
diff --git a/tools/virtio/linux/irqreturn.h b/tools/virtio/linux/irqreturn.h
new file mode 100644
index 0000000..a3c4e7b
--- /dev/null
+++ b/tools/virtio/linux/irqreturn.h
@@ -0,0 +1 @@
+#include "../../../include/linux/irqreturn.h"
diff --git a/tools/virtio/linux/kernel.h b/tools/virtio/linux/kernel.h
new file mode 100644
index 0000000..fba7059
--- /dev/null
+++ b/tools/virtio/linux/kernel.h
@@ -0,0 +1,112 @@
+#ifndef KERNEL_H
+#define KERNEL_H
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <stdarg.h>
+
+#include <linux/types.h>
+#include <linux/printk.h>
+#include <linux/bug.h>
+#include <errno.h>
+#include <unistd.h>
+#include <asm/barrier.h>
+
+#define CONFIG_SMP
+
+#define PAGE_SIZE getpagesize()
+#define PAGE_MASK (~(PAGE_SIZE-1))
+
+typedef unsigned long long dma_addr_t;
+typedef size_t __kernel_size_t;
+
+struct page {
+	unsigned long long dummy;
+};
+
+/* Physical == Virtual */
+#define virt_to_phys(p) ((unsigned long)p)
+#define phys_to_virt(a) ((void *)(unsigned long)(a))
+/* Page address: Virtual / 4K */
+#define page_to_phys(p) ((dma_addr_t)(unsigned long)(p))
+#define virt_to_page(p) ((struct page *)((unsigned long)p & PAGE_MASK))
+
+#define offset_in_page(p) (((unsigned long)p) % PAGE_SIZE)
+
+#define __printf(a,b) __attribute__((format(printf,a,b)))
+
+typedef enum {
+	GFP_KERNEL,
+	GFP_ATOMIC,
+	__GFP_HIGHMEM,
+	__GFP_HIGH
+} gfp_t;
+
+#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
+
+extern void *__kmalloc_fake, *__kfree_ignore_start, *__kfree_ignore_end;
+static inline void *kmalloc(size_t s, gfp_t gfp)
+{
+	if (__kmalloc_fake)
+		return __kmalloc_fake;
+	return malloc(s);
+}
+
+static inline void kfree(void *p)
+{
+	if (p >= __kfree_ignore_start && p < __kfree_ignore_end)
+		return;
+	free(p);
+}
+
+static inline void *krealloc(void *p, size_t s, gfp_t gfp)
+{
+	return realloc(p, s);
+}
+
+
+static inline unsigned long __get_free_page(gfp_t gfp)
+{
+	void *p;
+
+	posix_memalign(&p, PAGE_SIZE, PAGE_SIZE);
+	return (unsigned long)p;
+}
+
+static inline void free_page(unsigned long addr)
+{
+	free((void *)addr);
+}
+
+#define container_of(ptr, type, member) ({			\
+	const typeof( ((type *)0)->member ) *__mptr = (ptr);	\
+	(type *)( (char *)__mptr - offsetof(type,member) );})
+
+#define uninitialized_var(x) x = x
+
+# ifndef likely
+#  define likely(x)	(__builtin_expect(!!(x), 1))
+# endif
+# ifndef unlikely
+#  define unlikely(x)	(__builtin_expect(!!(x), 0))
+# endif
+
+#define pr_err(format, ...) fprintf (stderr, format, ## __VA_ARGS__)
+#ifdef DEBUG
+#define pr_debug(format, ...) fprintf (stderr, format, ## __VA_ARGS__)
+#else
+#define pr_debug(format, ...) do {} while (0)
+#endif
+#define dev_err(dev, format, ...) fprintf (stderr, format, ## __VA_ARGS__)
+#define dev_warn(dev, format, ...) fprintf (stderr, format, ## __VA_ARGS__)
+
+#define min(x, y) ({				\
+	typeof(x) _min1 = (x);			\
+	typeof(y) _min2 = (y);			\
+	(void) (&_min1 == &_min2);		\
+	_min1 < _min2 ? _min1 : _min2; })
+
+#endif /* KERNEL_H */
diff --git a/tools/virtio/linux/module.h b/tools/virtio/linux/module.h
index e69de29..3039a7e 100644
--- a/tools/virtio/linux/module.h
+++ b/tools/virtio/linux/module.h
@@ -0,0 +1 @@
+#include <linux/export.h>
diff --git a/tools/virtio/linux/printk.h b/tools/virtio/linux/printk.h
new file mode 100644
index 0000000..9f2423b
--- /dev/null
+++ b/tools/virtio/linux/printk.h
@@ -0,0 +1,4 @@
+#include "../../../include/linux/kern_levels.h"
+
+#define printk printf
+#define vprintk vprintf
diff --git a/tools/virtio/linux/ratelimit.h b/tools/virtio/linux/ratelimit.h
new file mode 100644
index 0000000..dcce172
--- /dev/null
+++ b/tools/virtio/linux/ratelimit.h
@@ -0,0 +1,4 @@
+#define DEFINE_RATELIMIT_STATE(name, interval_init, burst_init)	int name = 0
+
+#define __ratelimit(x) (*(x))
+
diff --git a/tools/virtio/linux/scatterlist.h b/tools/virtio/linux/scatterlist.h
new file mode 100644
index 0000000..68c9e2a
--- /dev/null
+++ b/tools/virtio/linux/scatterlist.h
@@ -0,0 +1,189 @@
+#ifndef SCATTERLIST_H
+#define SCATTERLIST_H
+#include <linux/kernel.h>
+
+struct scatterlist {
+	unsigned long	page_link;
+	unsigned int	offset;
+	unsigned int	length;
+	dma_addr_t	dma_address;
+};
+
+/* Scatterlist helpers, stolen from linux/scatterlist.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))
+
+/**
+ * sg_assign_page - Assign a given page to an SG entry
+ * @sg:		    SG entry
+ * @page:	    The page
+ *
+ * Description:
+ *   Assign page to sg entry. Also see sg_set_page(), the most commonly used
+ *   variant.
+ *
+ **/
+static inline void sg_assign_page(struct scatterlist *sg, struct page *page)
+{
+	unsigned long page_link = sg->page_link & 0x3;
+
+	/*
+	 * In order for the low bit stealing approach to work, pages
+	 * must be aligned at a 32-bit boundary as a minimum.
+	 */
+	BUG_ON((unsigned long) page & 0x03);
+#ifdef CONFIG_DEBUG_SG
+	BUG_ON(sg->sg_magic != SG_MAGIC);
+	BUG_ON(sg_is_chain(sg));
+#endif
+	sg->page_link = page_link | (unsigned long) page;
+}
+
+/**
+ * sg_set_page - Set sg entry to point at given page
+ * @sg:		 SG entry
+ * @page:	 The page
+ * @len:	 Length of data
+ * @offset:	 Offset into page
+ *
+ * Description:
+ *   Use this function to set an sg entry pointing at a page, never assign
+ *   the page directly. We encode sg table information in the lower bits
+ *   of the page pointer. See sg_page() for looking up the page belonging
+ *   to an sg entry.
+ *
+ **/
+static inline void sg_set_page(struct scatterlist *sg, struct page *page,
+			       unsigned int len, unsigned int offset)
+{
+	sg_assign_page(sg, page);
+	sg->offset = offset;
+	sg->length = len;
+}
+
+static inline struct page *sg_page(struct scatterlist *sg)
+{
+#ifdef CONFIG_DEBUG_SG
+	BUG_ON(sg->sg_magic != SG_MAGIC);
+	BUG_ON(sg_is_chain(sg));
+#endif
+	return (struct page *)((sg)->page_link & ~0x3);
+}
+
+/*
+ * Loop over each sg element, following the pointer to a new list if necessary
+ */
+#define for_each_sg(sglist, sg, nr, __i)	\
+	for (__i = 0, sg = (sglist); __i < (nr); __i++, sg = sg_next(sg))
+
+/**
+ * sg_chain - Chain two sglists together
+ * @prv:	First scatterlist
+ * @prv_nents:	Number of entries in prv
+ * @sgl:	Second scatterlist
+ *
+ * Description:
+ *   Links @prv@ and @sgl@ together, to form a longer scatterlist.
+ *
+ **/
+static inline void sg_chain(struct scatterlist *prv, unsigned int prv_nents,
+			    struct scatterlist *sgl)
+{
+	/*
+	 * offset and length are unused for chain entry.  Clear them.
+	 */
+	prv[prv_nents - 1].offset = 0;
+	prv[prv_nents - 1].length = 0;
+
+	/*
+	 * Set lowest bit to indicate a link pointer, and make sure to clear
+	 * the termination bit if it happens to be set.
+	 */
+	prv[prv_nents - 1].page_link = ((unsigned long) sgl | 0x01) & ~0x02;
+}
+
+/**
+ * sg_mark_end - Mark the end of the scatterlist
+ * @sg:		 SG entryScatterlist
+ *
+ * Description:
+ *   Marks the passed in sg entry as the termination point for the sg
+ *   table. A call to sg_next() on this entry will return NULL.
+ *
+ **/
+static inline void sg_mark_end(struct scatterlist *sg)
+{
+#ifdef CONFIG_DEBUG_SG
+	BUG_ON(sg->sg_magic != SG_MAGIC);
+#endif
+	/*
+	 * Set termination bit, clear potential chain bit
+	 */
+	sg->page_link |= 0x02;
+	sg->page_link &= ~0x01;
+}
+
+/**
+ * sg_unmark_end - Undo setting the end of the scatterlist
+ * @sg:		 SG entryScatterlist
+ *
+ * Description:
+ *   Removes the termination marker from the given entry of the scatterlist.
+ *
+ **/
+static inline void sg_unmark_end(struct scatterlist *sg)
+{
+#ifdef CONFIG_DEBUG_SG
+	BUG_ON(sg->sg_magic != SG_MAGIC);
+#endif
+	sg->page_link &= ~0x02;
+}
+
+static inline struct scatterlist *sg_next(struct scatterlist *sg)
+{
+#ifdef CONFIG_DEBUG_SG
+	BUG_ON(sg->sg_magic != SG_MAGIC);
+#endif
+	if (sg_is_last(sg))
+		return NULL;
+
+	sg++;
+	if (unlikely(sg_is_chain(sg)))
+		sg = sg_chain_ptr(sg);
+
+	return sg;
+}
+
+static inline void sg_init_table(struct scatterlist *sgl, unsigned int nents)
+{
+	memset(sgl, 0, sizeof(*sgl) * nents);
+#ifdef CONFIG_DEBUG_SG
+	{
+		unsigned int i;
+		for (i = 0; i < nents; i++)
+			sgl[i].sg_magic = SG_MAGIC;
+	}
+#endif
+	sg_mark_end(&sgl[nents - 1]);
+}
+
+static inline dma_addr_t sg_phys(struct scatterlist *sg)
+{
+	return page_to_phys(sg_page(sg)) + sg->offset;
+}
+
+static inline void sg_set_buf(struct scatterlist *sg, const void *buf,
+			      unsigned int buflen)
+{
+	sg_set_page(sg, virt_to_page(buf), buflen, offset_in_page(buf));
+}
+
+static inline void sg_init_one(struct scatterlist *sg,
+			       const void *buf, unsigned int buflen)
+{
+	sg_init_table(sg, 1);
+	sg_set_buf(sg, buf, buflen);
+}
+#endif /* SCATTERLIST_H */
diff --git a/tools/virtio/linux/types.h b/tools/virtio/linux/types.h
new file mode 100644
index 0000000..f8ebb9a
--- /dev/null
+++ b/tools/virtio/linux/types.h
@@ -0,0 +1,28 @@
+#ifndef TYPES_H
+#define TYPES_H
+#include <stdint.h>
+
+#define __force
+#define __user
+#define __must_check
+#define __cold
+
+typedef uint64_t u64;
+typedef int64_t s64;
+typedef uint32_t u32;
+typedef int32_t s32;
+typedef uint16_t u16;
+typedef int16_t s16;
+typedef uint8_t u8;
+typedef int8_t s8;
+
+typedef uint64_t __u64;
+typedef int64_t __s64;
+typedef uint32_t __u32;
+typedef int32_t __s32;
+typedef uint16_t __u16;
+typedef int16_t __s16;
+typedef uint8_t __u8;
+typedef int8_t __s8;
+
+#endif /* TYPES_H */
diff --git a/tools/virtio/linux/uaccess.h b/tools/virtio/linux/uaccess.h
new file mode 100644
index 0000000..0a578fe
--- /dev/null
+++ b/tools/virtio/linux/uaccess.h
@@ -0,0 +1,50 @@
+#ifndef UACCESS_H
+#define UACCESS_H
+extern void *__user_addr_min, *__user_addr_max;
+
+#define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x))
+
+static inline void __chk_user_ptr(const volatile void *p, size_t size)
+{
+	assert(p >= __user_addr_min && p + size <= __user_addr_max);
+}
+
+#define put_user(x, ptr)					\
+({								\
+	typeof(ptr) __pu_ptr = (ptr);				\
+	__chk_user_ptr(__pu_ptr, sizeof(*__pu_ptr));		\
+	ACCESS_ONCE(*(__pu_ptr)) = x;				\
+	0;							\
+})
+
+#define get_user(x, ptr)					\
+({								\
+	typeof(ptr) __pu_ptr = (ptr);				\
+	__chk_user_ptr(__pu_ptr, sizeof(*__pu_ptr));		\
+	x = ACCESS_ONCE(*(__pu_ptr));				\
+	0;							\
+})
+
+static void volatile_memcpy(volatile char *to, const volatile char *from, 
+			    unsigned long n)
+{
+	while (n--)
+		*(to++) = *(from++);
+}
+
+static inline int copy_from_user(void *to, const void __user volatile *from,
+				 unsigned long n)
+{
+	__chk_user_ptr(from, n);
+	volatile_memcpy(to, from, n);
+	return 0;
+}
+
+static inline int copy_to_user(void __user volatile *to, const void *from,
+			       unsigned long n)
+{
+	__chk_user_ptr(to, n);
+	volatile_memcpy(to, from, n);
+	return 0;
+}
+#endif /* UACCESS_H */
diff --git a/tools/virtio/linux/uio.h b/tools/virtio/linux/uio.h
new file mode 100644
index 0000000..cd20f0b
--- /dev/null
+++ b/tools/virtio/linux/uio.h
@@ -0,0 +1,3 @@
+#include <linux/kernel.h>
+
+#include "../../../include/linux/uio.h"
diff --git a/tools/virtio/linux/virtio.h b/tools/virtio/linux/virtio.h
index 81847dd..cd80183 100644
--- a/tools/virtio/linux/virtio.h
+++ b/tools/virtio/linux/virtio.h
@@ -1,127 +1,7 @@
 #ifndef LINUX_VIRTIO_H
 #define LINUX_VIRTIO_H
-
-#include <stdbool.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
-
-#include <linux/types.h>
-#include <errno.h>
-
-typedef unsigned long long dma_addr_t;
-
-struct scatterlist {
-	unsigned long	page_link;
-	unsigned int	offset;
-	unsigned int	length;
-	dma_addr_t	dma_address;
-};
-
-struct page {
-	unsigned long long dummy;
-};
-
-#define BUG_ON(__BUG_ON_cond) assert(!(__BUG_ON_cond))
-
-/* Physical == Virtual */
-#define virt_to_phys(p) ((unsigned long)p)
-#define phys_to_virt(a) ((void *)(unsigned long)(a))
-/* Page address: Virtual / 4K */
-#define virt_to_page(p) ((struct page*)((virt_to_phys(p) / 4096) * \
-					sizeof(struct page)))
-#define offset_in_page(p) (((unsigned long)p) % 4096)
-#define sg_phys(sg) ((sg->page_link & ~0x3) / sizeof(struct page) * 4096 + \
-		     sg->offset)
-static inline void sg_mark_end(struct scatterlist *sg)
-{
-	/*
-	 * Set termination bit, clear potential chain bit
-	 */
-	sg->page_link |= 0x02;
-	sg->page_link &= ~0x01;
-}
-static inline void sg_init_table(struct scatterlist *sgl, unsigned int nents)
-{
-	memset(sgl, 0, sizeof(*sgl) * nents);
-	sg_mark_end(&sgl[nents - 1]);
-}
-static inline void sg_assign_page(struct scatterlist *sg, struct page *page)
-{
-	unsigned long page_link = sg->page_link & 0x3;
-
-	/*
-	 * In order for the low bit stealing approach to work, pages
-	 * must be aligned at a 32-bit boundary as a minimum.
-	 */
-	BUG_ON((unsigned long) page & 0x03);
-	sg->page_link = page_link | (unsigned long) page;
-}
-
-static inline void sg_set_page(struct scatterlist *sg, struct page *page,
-			       unsigned int len, unsigned int offset)
-{
-	sg_assign_page(sg, page);
-	sg->offset = offset;
-	sg->length = len;
-}
-
-static inline void sg_set_buf(struct scatterlist *sg, const void *buf,
-			      unsigned int buflen)
-{
-	sg_set_page(sg, virt_to_page(buf), buflen, offset_in_page(buf));
-}
-
-static inline void sg_init_one(struct scatterlist *sg, const void *buf, unsigned int buflen)
-{
-	sg_init_table(sg, 1);
-	sg_set_buf(sg, buf, buflen);
-}
-
-typedef __u16 u16;
-
-typedef enum {
-	GFP_KERNEL,
-	GFP_ATOMIC,
-} gfp_t;
-typedef enum {
-	IRQ_NONE,
-	IRQ_HANDLED
-} irqreturn_t;
-
-static inline void *kmalloc(size_t s, gfp_t gfp)
-{
-	return malloc(s);
-}
-
-static inline void kfree(void *p)
-{
-	free(p);
-}
-
-#define container_of(ptr, type, member) ({			\
-	const typeof( ((type *)0)->member ) *__mptr = (ptr);	\
-	(type *)( (char *)__mptr - offsetof(type,member) );})
-
-#define uninitialized_var(x) x = x
-
-# ifndef likely
-#  define likely(x)	(__builtin_expect(!!(x), 1))
-# endif
-# ifndef unlikely
-#  define unlikely(x)	(__builtin_expect(!!(x), 0))
-# endif
-
-#define pr_err(format, ...) fprintf (stderr, format, ## __VA_ARGS__)
-#ifdef DEBUG
-#define pr_debug(format, ...) fprintf (stderr, format, ## __VA_ARGS__)
-#else
-#define pr_debug(format, ...) do {} while (0)
-#endif
-#define dev_err(dev, format, ...) fprintf (stderr, format, ## __VA_ARGS__)
-#define dev_warn(dev, format, ...) fprintf (stderr, format, ## __VA_ARGS__)
+#include <linux/scatterlist.h>
+#include <linux/kernel.h>
 
 /* TODO: empty stubs for now. Broken but enough for virtio_ring.c */
 #define list_add_tail(a, b) do {} while (0)
@@ -131,6 +11,7 @@ static inline void kfree(void *p)
 #define BITS_PER_BYTE		8
 #define BITS_PER_LONG (sizeof(long) * BITS_PER_BYTE)
 #define BIT_MASK(nr)		(1UL << ((nr) % BITS_PER_LONG))
+
 /* TODO: Not atomic as it should be:
  * we don't use this for anything important. */
 static inline void clear_bit(int nr, volatile unsigned long *addr)
@@ -145,10 +26,6 @@ static inline int test_bit(int nr, const volatile unsigned long *addr)
 {
         return 1UL & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG-1)));
 }
-
-/* The only feature we care to support */
-#define virtio_has_feature(dev, feature) \
-	test_bit((feature), (dev)->features)
 /* end of stubs */
 
 struct virtio_device {
@@ -163,39 +40,32 @@ struct virtqueue {
 	void (*callback)(struct virtqueue *vq);
 	const char *name;
 	struct virtio_device *vdev;
+        unsigned int index;
+        unsigned int num_free;
 	void *priv;
 };
 
-#define EXPORT_SYMBOL_GPL(__EXPORT_SYMBOL_GPL_name) \
-	void __EXPORT_SYMBOL_GPL##__EXPORT_SYMBOL_GPL_name() { \
-}
 #define MODULE_LICENSE(__MODULE_LICENSE_value) \
 	const char *__MODULE_LICENSE_name = __MODULE_LICENSE_value
 
-#define CONFIG_SMP
-
-#if defined(__i386__) || defined(__x86_64__)
-#define barrier() asm volatile("" ::: "memory")
-#define mb() __sync_synchronize()
-
-#define smp_mb()	mb()
-# define smp_rmb()	barrier()
-# define smp_wmb()	barrier()
-/* Weak barriers should be used. If not - it's a bug */
-# define rmb()	abort()
-# define wmb()	abort()
-#else
-#error Please fill in barrier macros
-#endif
-
 /* Interfaces exported by virtio_ring. */
-int virtqueue_add_buf(struct virtqueue *vq,
-		      struct scatterlist sg[],
-		      unsigned int out_num,
-		      unsigned int in_num,
+int virtqueue_add_sgs(struct virtqueue *vq,
+		      struct scatterlist *sgs[],
+		      unsigned int out_sgs,
+		      unsigned int in_sgs,
 		      void *data,
 		      gfp_t gfp);
 
+int virtqueue_add_outbuf(struct virtqueue *vq,
+			 struct scatterlist sg[], unsigned int num,
+			 void *data,
+			 gfp_t gfp);
+
+int virtqueue_add_inbuf(struct virtqueue *vq,
+			struct scatterlist sg[], unsigned int num,
+			void *data,
+			gfp_t gfp);
+
 void virtqueue_kick(struct virtqueue *vq);
 
 void *virtqueue_get_buf(struct virtqueue *vq, unsigned int *len);
@@ -206,7 +76,8 @@ bool virtqueue_enable_cb(struct virtqueue *vq);
 bool virtqueue_enable_cb_delayed(struct virtqueue *vq);
 
 void *virtqueue_detach_unused_buf(struct virtqueue *vq);
-struct virtqueue *vring_new_virtqueue(unsigned int num,
+struct virtqueue *vring_new_virtqueue(unsigned int index,
+				      unsigned int num,
 				      unsigned int vring_align,
 				      struct virtio_device *vdev,
 				      bool weak_barriers,
diff --git a/tools/virtio/linux/virtio_config.h b/tools/virtio/linux/virtio_config.h
new file mode 100644
index 0000000..5049967
--- /dev/null
+++ b/tools/virtio/linux/virtio_config.h
@@ -0,0 +1,6 @@
+#define VIRTIO_TRANSPORT_F_START	28
+#define VIRTIO_TRANSPORT_F_END		32
+
+#define virtio_has_feature(dev, feature) \
+	test_bit((feature), (dev)->features)
+
diff --git a/tools/virtio/linux/virtio_ring.h b/tools/virtio/linux/virtio_ring.h
new file mode 100644
index 0000000..8949c4e
--- /dev/null
+++ b/tools/virtio/linux/virtio_ring.h
@@ -0,0 +1 @@
+#include "../../../include/linux/virtio_ring.h"
diff --git a/tools/virtio/linux/vringh.h b/tools/virtio/linux/vringh.h
new file mode 100644
index 0000000..9348957
--- /dev/null
+++ b/tools/virtio/linux/vringh.h
@@ -0,0 +1 @@
+#include "../../../include/linux/vringh.h"
diff --git a/tools/virtio/uapi/linux/uio.h b/tools/virtio/uapi/linux/uio.h
new file mode 100644
index 0000000..7230e90
--- /dev/null
+++ b/tools/virtio/uapi/linux/uio.h
@@ -0,0 +1 @@
+#include <sys/uio.h>
diff --git a/tools/virtio/uapi/linux/virtio_config.h b/tools/virtio/uapi/linux/virtio_config.h
new file mode 100644
index 0000000..4c86675
--- /dev/null
+++ b/tools/virtio/uapi/linux/virtio_config.h
@@ -0,0 +1 @@
+#include "../../../../include/uapi/linux/virtio_config.h"
diff --git a/tools/virtio/uapi/linux/virtio_ring.h b/tools/virtio/uapi/linux/virtio_ring.h
new file mode 100644
index 0000000..4d99c78
--- /dev/null
+++ b/tools/virtio/uapi/linux/virtio_ring.h
@@ -0,0 +1,4 @@
+#ifndef VIRTIO_RING_H
+#define VIRTIO_RING_H
+#include "../../../../include/uapi/linux/virtio_ring.h"
+#endif /* VIRTIO_RING_H */
diff --git a/tools/virtio/virtio_test.c b/tools/virtio/virtio_test.c
index fcc9aa2..da7a195 100644
--- a/tools/virtio/virtio_test.c
+++ b/tools/virtio/virtio_test.c
@@ -10,11 +10,15 @@
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <fcntl.h>
+#include <stdbool.h>
 #include <linux/vhost.h>
 #include <linux/virtio.h>
 #include <linux/virtio_ring.h>
 #include "../../drivers/vhost/test.h"
 
+/* Unused */
+void *__kmalloc_fake, *__kfree_ignore_start, *__kfree_ignore_end;
+
 struct vq_info {
 	int kick;
 	int call;
@@ -92,7 +96,8 @@ static void vq_info_add(struct vdev_info *dev, int num)
 	assert(r >= 0);
 	memset(info->ring, 0, vring_size(num, 4096));
 	vring_init(&info->vring, num, info->ring, 4096);
-	info->vq = vring_new_virtqueue(info->vring.num, 4096, &dev->vdev,
+	info->vq = vring_new_virtqueue(info->idx,
+				       info->vring.num, 4096, &dev->vdev,
 				       true, info->ring,
 				       vq_notify, vq_callback, "test");
 	assert(info->vq);
@@ -161,9 +166,9 @@ static void run_test(struct vdev_info *dev, struct vq_info *vq,
 		do {
 			if (started < bufs) {
 				sg_init_one(&sl, dev->buf, dev->buf_size);
-				r = virtqueue_add_buf(vq->vq, &sl, 1, 0,
-						      dev->buf + started,
-						      GFP_ATOMIC);
+				r = virtqueue_add_outbuf(vq->vq, &sl, 1,
+							 dev->buf + started,
+							 GFP_ATOMIC);
 				if (likely(r == 0)) {
 					++started;
 					virtqueue_kick(vq->vq);
diff --git a/tools/virtio/vringh_test.c b/tools/virtio/vringh_test.c
new file mode 100644
index 0000000..d053ea4
--- /dev/null
+++ b/tools/virtio/vringh_test.c
@@ -0,0 +1,741 @@
+/* Simple test of virtio code, entirely in userpsace. */
+#define _GNU_SOURCE
+#include <sched.h>
+#include <err.h>
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/virtio.h>
+#include <linux/vringh.h>
+#include <linux/virtio_ring.h>
+#include <linux/uaccess.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+
+#define USER_MEM (1024*1024)
+void *__user_addr_min, *__user_addr_max;
+void *__kmalloc_fake, *__kfree_ignore_start, *__kfree_ignore_end;
+static u64 user_addr_offset;
+
+#define RINGSIZE 256
+#define ALIGN 4096
+
+static void never_notify_host(struct virtqueue *vq)
+{
+	abort();
+}
+
+static void never_callback_guest(struct virtqueue *vq)
+{
+	abort();
+}
+
+static bool getrange_iov(struct vringh *vrh, u64 addr, struct vringh_range *r)
+{
+	if (addr < (u64)(unsigned long)__user_addr_min - user_addr_offset)
+		return false;
+	if (addr >= (u64)(unsigned long)__user_addr_max - user_addr_offset)
+		return false;
+
+	r->start = (u64)(unsigned long)__user_addr_min - user_addr_offset;
+	r->end_incl = (u64)(unsigned long)__user_addr_max - 1 - user_addr_offset;
+	r->offset = user_addr_offset;
+	return true;
+}
+
+/* We return single byte ranges. */
+static bool getrange_slow(struct vringh *vrh, u64 addr, struct vringh_range *r)
+{
+	if (addr < (u64)(unsigned long)__user_addr_min - user_addr_offset)
+		return false;
+	if (addr >= (u64)(unsigned long)__user_addr_max - user_addr_offset)
+		return false;
+
+	r->start = addr;
+	r->end_incl = r->start;
+	r->offset = user_addr_offset;
+	return true;
+}
+
+struct guest_virtio_device {
+	struct virtio_device vdev;
+	int to_host_fd;
+	unsigned long notifies;
+};
+
+static void parallel_notify_host(struct virtqueue *vq)
+{
+	struct guest_virtio_device *gvdev;
+
+	gvdev = container_of(vq->vdev, struct guest_virtio_device, vdev);
+	write(gvdev->to_host_fd, "", 1);
+	gvdev->notifies++;
+}
+
+static void no_notify_host(struct virtqueue *vq)
+{
+}
+
+#define NUM_XFERS (10000000)
+
+/* We aim for two "distant" cpus. */
+static void find_cpus(unsigned int *first, unsigned int *last)
+{
+	unsigned int i;
+
+	*first = -1U;
+	*last = 0;
+	for (i = 0; i < 4096; i++) {
+		cpu_set_t set;
+		CPU_ZERO(&set);
+		CPU_SET(i, &set);
+		if (sched_setaffinity(getpid(), sizeof(set), &set) == 0) {
+			if (i < *first)
+				*first = i;
+			if (i > *last)
+				*last = i;
+		}
+	}
+}
+
+/* Opencoded version for fast mode */
+static inline int vringh_get_head(struct vringh *vrh, u16 *head)
+{
+	u16 avail_idx, i;
+	int err;
+
+	err = get_user(avail_idx, &vrh->vring.avail->idx);
+	if (err)
+		return err;
+
+	if (vrh->last_avail_idx == avail_idx)
+		return 0;
+
+	/* Only get avail ring entries after they have been exposed by guest. */
+	virtio_rmb(vrh->weak_barriers);
+
+	i = vrh->last_avail_idx & (vrh->vring.num - 1);
+
+	err = get_user(*head, &vrh->vring.avail->ring[i]);
+	if (err)
+		return err;
+
+	vrh->last_avail_idx++;
+	return 1;
+}
+
+static int parallel_test(unsigned long features,
+			 bool (*getrange)(struct vringh *vrh,
+					  u64 addr, struct vringh_range *r),
+			 bool fast_vringh)
+{
+	void *host_map, *guest_map;
+	int fd, mapsize, to_guest[2], to_host[2];
+	unsigned long xfers = 0, notifies = 0, receives = 0;
+	unsigned int first_cpu, last_cpu;
+	cpu_set_t cpu_set;
+	char buf[128];
+
+	/* Create real file to mmap. */
+	fd = open("/tmp/vringh_test-file", O_RDWR|O_CREAT|O_TRUNC, 0600);
+	if (fd < 0)
+		err(1, "Opening /tmp/vringh_test-file");
+
+	/* Extra room at the end for some data, and indirects */
+	mapsize = vring_size(RINGSIZE, ALIGN)
+		+ RINGSIZE * 2 * sizeof(int)
+		+ RINGSIZE * 6 * sizeof(struct vring_desc);
+	mapsize = (mapsize + getpagesize() - 1) & ~(getpagesize() - 1);
+	ftruncate(fd, mapsize);
+
+	/* Parent and child use separate addresses, to check our mapping logic! */
+	host_map = mmap(NULL, mapsize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+	guest_map = mmap(NULL, mapsize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+
+	pipe(to_guest);
+	pipe(to_host);
+
+	CPU_ZERO(&cpu_set);
+	find_cpus(&first_cpu, &last_cpu);
+	printf("Using CPUS %u and %u\n", first_cpu, last_cpu);
+	fflush(stdout);
+
+	if (fork() != 0) {
+		struct vringh vrh;
+		int status, err, rlen = 0;
+		char rbuf[5];
+
+		/* We are the host: never access guest addresses! */
+		munmap(guest_map, mapsize);
+
+		__user_addr_min = host_map;
+		__user_addr_max = __user_addr_min + mapsize;
+		user_addr_offset = host_map - guest_map;
+		assert(user_addr_offset);
+
+		close(to_guest[0]);
+		close(to_host[1]);
+
+		vring_init(&vrh.vring, RINGSIZE, host_map, ALIGN);
+		vringh_init_user(&vrh, features, RINGSIZE, true,
+				 vrh.vring.desc, vrh.vring.avail, vrh.vring.used);
+		CPU_SET(first_cpu, &cpu_set);
+		if (sched_setaffinity(getpid(), sizeof(cpu_set), &cpu_set))
+			errx(1, "Could not set affinity to cpu %u", first_cpu);
+
+		while (xfers < NUM_XFERS) {
+			struct iovec host_riov[2], host_wiov[2];
+			struct vringh_iov riov, wiov;
+			u16 head, written;
+
+			if (fast_vringh) {
+				for (;;) {
+					err = vringh_get_head(&vrh, &head);
+					if (err != 0)
+						break;
+					err = vringh_need_notify_user(&vrh);
+					if (err < 0)
+						errx(1, "vringh_need_notify_user: %i",
+						     err);
+					if (err) {
+						write(to_guest[1], "", 1);
+						notifies++;
+					}
+				}
+				if (err != 1)
+					errx(1, "vringh_get_head");
+				written = 0;
+				goto complete;
+			} else {
+				vringh_iov_init(&riov,
+						host_riov,
+						ARRAY_SIZE(host_riov));
+				vringh_iov_init(&wiov,
+						host_wiov,
+						ARRAY_SIZE(host_wiov));
+
+				err = vringh_getdesc_user(&vrh, &riov, &wiov,
+							  getrange, &head);
+			}
+			if (err == 0) {
+				err = vringh_need_notify_user(&vrh);
+				if (err < 0)
+					errx(1, "vringh_need_notify_user: %i",
+					     err);
+				if (err) {
+					write(to_guest[1], "", 1);
+					notifies++;
+				}
+
+				if (!vringh_notify_enable_user(&vrh))
+					continue;
+
+				/* Swallow all notifies at once. */
+				if (read(to_host[0], buf, sizeof(buf)) < 1)
+					break;
+
+				vringh_notify_disable_user(&vrh);
+				receives++;
+				continue;
+			}
+			if (err != 1)
+				errx(1, "vringh_getdesc_user: %i", err);
+
+			/* We simply copy bytes. */
+			if (riov.used) {
+				rlen = vringh_iov_pull_user(&riov, rbuf,
+							    sizeof(rbuf));
+				if (rlen != 4)
+					errx(1, "vringh_iov_pull_user: %i",
+					     rlen);
+				assert(riov.i == riov.used);
+				written = 0;
+			} else {
+				err = vringh_iov_push_user(&wiov, rbuf, rlen);
+				if (err != rlen)
+					errx(1, "vringh_iov_push_user: %i",
+					     err);
+				assert(wiov.i == wiov.used);
+				written = err;
+			}
+		complete:
+			xfers++;
+
+			err = vringh_complete_user(&vrh, head, written);
+			if (err != 0)
+				errx(1, "vringh_complete_user: %i", err);
+		}
+
+		err = vringh_need_notify_user(&vrh);
+		if (err < 0)
+			errx(1, "vringh_need_notify_user: %i", err);
+		if (err) {
+			write(to_guest[1], "", 1);
+			notifies++;
+		}
+		wait(&status);
+		if (!WIFEXITED(status))
+			errx(1, "Child died with signal %i?", WTERMSIG(status));
+		if (WEXITSTATUS(status) != 0)
+			errx(1, "Child exited %i?", WEXITSTATUS(status));
+		printf("Host: notified %lu, pinged %lu\n", notifies, receives);
+		return 0;
+	} else {
+		struct guest_virtio_device gvdev;
+		struct virtqueue *vq;
+		unsigned int *data;
+		struct vring_desc *indirects;
+		unsigned int finished = 0;
+
+		/* We pass sg[]s pointing into here, but we need RINGSIZE+1 */
+		data = guest_map + vring_size(RINGSIZE, ALIGN);
+		indirects = (void *)data + (RINGSIZE + 1) * 2 * sizeof(int);
+
+		/* We are the guest. */
+		munmap(host_map, mapsize);
+
+		close(to_guest[1]);
+		close(to_host[0]);
+
+		gvdev.vdev.features[0] = features;
+		gvdev.to_host_fd = to_host[1];
+		gvdev.notifies = 0;
+
+		CPU_SET(first_cpu, &cpu_set);
+		if (sched_setaffinity(getpid(), sizeof(cpu_set), &cpu_set))
+			err(1, "Could not set affinity to cpu %u", first_cpu);
+
+		vq = vring_new_virtqueue(0, RINGSIZE, ALIGN, &gvdev.vdev, true,
+					 guest_map, fast_vringh ? no_notify_host
+					 : parallel_notify_host,
+					 never_callback_guest, "guest vq");
+
+		/* Don't kfree indirects. */
+		__kfree_ignore_start = indirects;
+		__kfree_ignore_end = indirects + RINGSIZE * 6;
+
+		while (xfers < NUM_XFERS) {
+			struct scatterlist sg[4];
+			unsigned int num_sg, len;
+			int *dbuf, err;
+			bool output = !(xfers % 2);
+
+			/* Consume bufs. */
+			while ((dbuf = virtqueue_get_buf(vq, &len)) != NULL) {
+				if (len == 4)
+					assert(*dbuf == finished - 1);
+				else if (!fast_vringh)
+					assert(*dbuf == finished);
+				finished++;
+			}
+
+			/* Produce a buffer. */
+			dbuf = data + (xfers % (RINGSIZE + 1));
+
+			if (output)
+				*dbuf = xfers;
+			else
+				*dbuf = -1;
+
+			switch ((xfers / sizeof(*dbuf)) % 4) {
+			case 0:
+				/* Nasty three-element sg list. */
+				sg_init_table(sg, num_sg = 3);
+				sg_set_buf(&sg[0], (void *)dbuf, 1);
+				sg_set_buf(&sg[1], (void *)dbuf + 1, 2);
+				sg_set_buf(&sg[2], (void *)dbuf + 3, 1);
+				break;
+			case 1:
+				sg_init_table(sg, num_sg = 2);
+				sg_set_buf(&sg[0], (void *)dbuf, 1);
+				sg_set_buf(&sg[1], (void *)dbuf + 1, 3);
+				break;
+			case 2:
+				sg_init_table(sg, num_sg = 1);
+				sg_set_buf(&sg[0], (void *)dbuf, 4);
+				break;
+			case 3:
+				sg_init_table(sg, num_sg = 4);
+				sg_set_buf(&sg[0], (void *)dbuf, 1);
+				sg_set_buf(&sg[1], (void *)dbuf + 1, 1);
+				sg_set_buf(&sg[2], (void *)dbuf + 2, 1);
+				sg_set_buf(&sg[3], (void *)dbuf + 3, 1);
+				break;
+			}
+
+			/* May allocate an indirect, so force it to allocate
+			 * user addr */
+			__kmalloc_fake = indirects + (xfers % RINGSIZE) * 4;
+			if (output)
+				err = virtqueue_add_outbuf(vq, sg, num_sg, dbuf,
+							   GFP_KERNEL);
+			else
+				err = virtqueue_add_inbuf(vq, sg, num_sg,
+							  dbuf, GFP_KERNEL);
+
+			if (err == -ENOSPC) {
+				if (!virtqueue_enable_cb_delayed(vq))
+					continue;
+				/* Swallow all notifies at once. */
+				if (read(to_guest[0], buf, sizeof(buf)) < 1)
+					break;
+				
+				receives++;
+				virtqueue_disable_cb(vq);
+				continue;
+			}
+
+			if (err)
+				errx(1, "virtqueue_add_in/outbuf: %i", err);
+
+			xfers++;
+			virtqueue_kick(vq);
+		}
+
+		/* Any extra? */
+		while (finished != xfers) {
+			int *dbuf;
+			unsigned int len;
+
+			/* Consume bufs. */
+			dbuf = virtqueue_get_buf(vq, &len);
+			if (dbuf) {
+				if (len == 4)
+					assert(*dbuf == finished - 1);
+				else
+					assert(len == 0);
+				finished++;
+				continue;
+			}
+
+			if (!virtqueue_enable_cb_delayed(vq))
+				continue;
+			if (read(to_guest[0], buf, sizeof(buf)) < 1)
+				break;
+				
+			receives++;
+			virtqueue_disable_cb(vq);
+		}
+
+		printf("Guest: notified %lu, pinged %lu\n",
+		       gvdev.notifies, receives);
+		vring_del_virtqueue(vq);
+		return 0;
+	}
+}
+
+int main(int argc, char *argv[])
+{
+	struct virtio_device vdev;
+	struct virtqueue *vq;
+	struct vringh vrh;
+	struct scatterlist guest_sg[RINGSIZE], *sgs[2];
+	struct iovec host_riov[2], host_wiov[2];
+	struct vringh_iov riov, wiov;
+	struct vring_used_elem used[RINGSIZE];
+	char buf[28];
+	u16 head;
+	int err;
+	unsigned i;
+	void *ret;
+	bool (*getrange)(struct vringh *vrh, u64 addr, struct vringh_range *r);
+	bool fast_vringh = false, parallel = false;
+
+	getrange = getrange_iov;
+	vdev.features[0] = 0;
+
+	while (argv[1]) {
+		if (strcmp(argv[1], "--indirect") == 0)
+			vdev.features[0] |= (1 << VIRTIO_RING_F_INDIRECT_DESC);
+		else if (strcmp(argv[1], "--eventidx") == 0)
+			vdev.features[0] |= (1 << VIRTIO_RING_F_EVENT_IDX);
+		else if (strcmp(argv[1], "--slow-range") == 0)
+			getrange = getrange_slow;
+		else if (strcmp(argv[1], "--fast-vringh") == 0)
+			fast_vringh = true;
+		else if (strcmp(argv[1], "--parallel") == 0)
+			parallel = true;
+		else
+			errx(1, "Unknown arg %s", argv[1]);
+		argv++;
+	}
+
+	if (parallel)
+		return parallel_test(vdev.features[0], getrange, fast_vringh);
+
+	if (posix_memalign(&__user_addr_min, PAGE_SIZE, USER_MEM) != 0)
+		abort();
+	__user_addr_max = __user_addr_min + USER_MEM;
+	memset(__user_addr_min, 0, vring_size(RINGSIZE, ALIGN));
+
+	/* Set up guest side. */
+	vq = vring_new_virtqueue(0, RINGSIZE, ALIGN, &vdev, true,
+				 __user_addr_min,
+				 never_notify_host, never_callback_guest,
+				 "guest vq");
+
+	/* Set up host side. */
+	vring_init(&vrh.vring, RINGSIZE, __user_addr_min, ALIGN);
+	vringh_init_user(&vrh, vdev.features[0], RINGSIZE, true,
+			 vrh.vring.desc, vrh.vring.avail, vrh.vring.used);
+
+	/* No descriptor to get yet... */
+	err = vringh_getdesc_user(&vrh, &riov, &wiov, getrange, &head);
+	if (err != 0)
+		errx(1, "vringh_getdesc_user: %i", err);
+
+	/* Guest puts in a descriptor. */
+	memcpy(__user_addr_max - 1, "a", 1);
+	sg_init_table(guest_sg, 1);
+	sg_set_buf(&guest_sg[0], __user_addr_max - 1, 1);
+	sg_init_table(guest_sg+1, 1);
+	sg_set_buf(&guest_sg[1], __user_addr_max - 3, 2);
+	sgs[0] = &guest_sg[0];
+	sgs[1] = &guest_sg[1];
+
+	/* May allocate an indirect, so force it to allocate user addr */
+	__kmalloc_fake = __user_addr_min + vring_size(RINGSIZE, ALIGN);
+	err = virtqueue_add_sgs(vq, sgs, 1, 1, &err, GFP_KERNEL);
+	if (err)
+		errx(1, "virtqueue_add_sgs: %i", err);
+	__kmalloc_fake = NULL;
+
+	/* Host retreives it. */
+	vringh_iov_init(&riov, host_riov, ARRAY_SIZE(host_riov));
+	vringh_iov_init(&wiov, host_wiov, ARRAY_SIZE(host_wiov));
+
+	err = vringh_getdesc_user(&vrh, &riov, &wiov, getrange, &head);
+	if (err != 1)
+		errx(1, "vringh_getdesc_user: %i", err);
+
+	assert(riov.used == 1);
+	assert(riov.iov[0].iov_base == __user_addr_max - 1);
+	assert(riov.iov[0].iov_len == 1);
+	if (getrange != getrange_slow) {
+		assert(wiov.used == 1);
+		assert(wiov.iov[0].iov_base == __user_addr_max - 3);
+		assert(wiov.iov[0].iov_len == 2);
+	} else {
+		assert(wiov.used == 2);
+		assert(wiov.iov[0].iov_base == __user_addr_max - 3);
+		assert(wiov.iov[0].iov_len == 1);
+		assert(wiov.iov[1].iov_base == __user_addr_max - 2);
+		assert(wiov.iov[1].iov_len == 1);
+	}
+
+	err = vringh_iov_pull_user(&riov, buf, 5);
+	if (err != 1)
+		errx(1, "vringh_iov_pull_user: %i", err);
+	assert(buf[0] == 'a');
+	assert(riov.i == 1);
+	assert(vringh_iov_pull_user(&riov, buf, 5) == 0);
+
+	memcpy(buf, "bcdef", 5);
+	err = vringh_iov_push_user(&wiov, buf, 5);
+	if (err != 2)
+		errx(1, "vringh_iov_push_user: %i", err);
+	assert(memcmp(__user_addr_max - 3, "bc", 2) == 0);
+	assert(wiov.i == wiov.used);
+	assert(vringh_iov_push_user(&wiov, buf, 5) == 0);
+
+	/* Host is done. */
+	err = vringh_complete_user(&vrh, head, err);
+	if (err != 0)
+		errx(1, "vringh_complete_user: %i", err);
+
+	/* Guest should see used token now. */
+	__kfree_ignore_start = __user_addr_min + vring_size(RINGSIZE, ALIGN);
+	__kfree_ignore_end = __kfree_ignore_start + 1;
+	ret = virtqueue_get_buf(vq, &i);
+	if (ret != &err)
+		errx(1, "virtqueue_get_buf: %p", ret);
+	assert(i == 2);
+
+	/* Guest puts in a huge descriptor. */
+	sg_init_table(guest_sg, RINGSIZE);
+	for (i = 0; i < RINGSIZE; i++) {
+		sg_set_buf(&guest_sg[i],
+			   __user_addr_max - USER_MEM/4, USER_MEM/4);
+	}
+
+	/* Fill contents with recognisable garbage. */
+	for (i = 0; i < USER_MEM/4; i++)
+		((char *)__user_addr_max - USER_MEM/4)[i] = i;
+
+	/* This will allocate an indirect, so force it to allocate user addr */
+	__kmalloc_fake = __user_addr_min + vring_size(RINGSIZE, ALIGN);
+	err = virtqueue_add_outbuf(vq, guest_sg, RINGSIZE, &err, GFP_KERNEL);
+	if (err)
+		errx(1, "virtqueue_add_outbuf (large): %i", err);
+	__kmalloc_fake = NULL;
+
+	/* Host picks it up (allocates new iov). */
+	vringh_iov_init(&riov, host_riov, ARRAY_SIZE(host_riov));
+	vringh_iov_init(&wiov, host_wiov, ARRAY_SIZE(host_wiov));
+
+	err = vringh_getdesc_user(&vrh, &riov, &wiov, getrange, &head);
+	if (err != 1)
+		errx(1, "vringh_getdesc_user: %i", err);
+
+	assert(riov.max_num & VRINGH_IOV_ALLOCATED);
+	assert(riov.iov != host_riov);
+	if (getrange != getrange_slow)
+		assert(riov.used == RINGSIZE);
+	else
+		assert(riov.used == RINGSIZE * USER_MEM/4);
+
+	assert(!(wiov.max_num & VRINGH_IOV_ALLOCATED));
+	assert(wiov.used == 0);
+
+	/* Pull data back out (in odd chunks), should be as expected. */
+	for (i = 0; i < RINGSIZE * USER_MEM/4; i += 3) {
+		err = vringh_iov_pull_user(&riov, buf, 3);
+		if (err != 3 && i + err != RINGSIZE * USER_MEM/4)
+			errx(1, "vringh_iov_pull_user large: %i", err);
+		assert(buf[0] == (char)i);
+		assert(err < 2 || buf[1] == (char)(i + 1));
+		assert(err < 3 || buf[2] == (char)(i + 2));
+	}
+	assert(riov.i == riov.used);
+	vringh_iov_cleanup(&riov);
+	vringh_iov_cleanup(&wiov);
+
+	/* Complete using multi interface, just because we can. */
+	used[0].id = head;
+	used[0].len = 0;
+	err = vringh_complete_multi_user(&vrh, used, 1);
+	if (err)
+		errx(1, "vringh_complete_multi_user(1): %i", err);
+
+	/* Free up those descriptors. */
+	ret = virtqueue_get_buf(vq, &i);
+	if (ret != &err)
+		errx(1, "virtqueue_get_buf: %p", ret);
+
+	/* Add lots of descriptors. */
+	sg_init_table(guest_sg, 1);
+	sg_set_buf(&guest_sg[0], __user_addr_max - 1, 1);
+	for (i = 0; i < RINGSIZE; i++) {
+		err = virtqueue_add_outbuf(vq, guest_sg, 1, &err, GFP_KERNEL);
+		if (err)
+			errx(1, "virtqueue_add_outbuf (multiple): %i", err);
+	}
+
+	/* Now get many, and consume them all at once. */
+	vringh_iov_init(&riov, host_riov, ARRAY_SIZE(host_riov));
+	vringh_iov_init(&wiov, host_wiov, ARRAY_SIZE(host_wiov));
+
+	for (i = 0; i < RINGSIZE; i++) {
+		err = vringh_getdesc_user(&vrh, &riov, &wiov, getrange, &head);
+		if (err != 1)
+			errx(1, "vringh_getdesc_user: %i", err);
+		used[i].id = head;
+		used[i].len = 0;
+	}
+	/* Make sure it wraps around ring, to test! */
+	assert(vrh.vring.used->idx % RINGSIZE != 0);
+	err = vringh_complete_multi_user(&vrh, used, RINGSIZE);
+	if (err)
+		errx(1, "vringh_complete_multi_user: %i", err);
+
+	/* Free those buffers. */
+	for (i = 0; i < RINGSIZE; i++) {
+		unsigned len;
+		assert(virtqueue_get_buf(vq, &len) != NULL);
+	}
+
+	/* Test weird (but legal!) indirect. */
+	if (vdev.features[0] & (1 << VIRTIO_RING_F_INDIRECT_DESC)) {
+		char *data = __user_addr_max - USER_MEM/4;
+		struct vring_desc *d = __user_addr_max - USER_MEM/2;
+		struct vring vring;
+
+		/* Force creation of direct, which we modify. */
+		vdev.features[0] &= ~(1 << VIRTIO_RING_F_INDIRECT_DESC);
+		vq = vring_new_virtqueue(0, RINGSIZE, ALIGN, &vdev, true,
+					 __user_addr_min,
+					 never_notify_host,
+					 never_callback_guest,
+					 "guest vq");
+
+		sg_init_table(guest_sg, 4);
+		sg_set_buf(&guest_sg[0], d, sizeof(*d)*2);
+		sg_set_buf(&guest_sg[1], d + 2, sizeof(*d)*1);
+		sg_set_buf(&guest_sg[2], data + 6, 4);
+		sg_set_buf(&guest_sg[3], d + 3, sizeof(*d)*3);
+
+		err = virtqueue_add_outbuf(vq, guest_sg, 4, &err, GFP_KERNEL);
+		if (err)
+			errx(1, "virtqueue_add_outbuf (indirect): %i", err);
+
+		vring_init(&vring, RINGSIZE, __user_addr_min, ALIGN);
+
+		/* They're used in order, but double-check... */
+		assert(vring.desc[0].addr == (unsigned long)d);
+		assert(vring.desc[1].addr == (unsigned long)(d+2));
+		assert(vring.desc[2].addr == (unsigned long)data + 6);
+		assert(vring.desc[3].addr == (unsigned long)(d+3));
+		vring.desc[0].flags |= VRING_DESC_F_INDIRECT;
+		vring.desc[1].flags |= VRING_DESC_F_INDIRECT;
+		vring.desc[3].flags |= VRING_DESC_F_INDIRECT;
+
+		/* First indirect */
+		d[0].addr = (unsigned long)data;
+		d[0].len = 1;
+		d[0].flags = VRING_DESC_F_NEXT;
+		d[0].next = 1;
+		d[1].addr = (unsigned long)data + 1;
+		d[1].len = 2;
+		d[1].flags = 0;
+
+		/* Second indirect */
+		d[2].addr = (unsigned long)data + 3;
+		d[2].len = 3;
+		d[2].flags = 0;
+
+		/* Third indirect */
+		d[3].addr = (unsigned long)data + 10;
+		d[3].len = 5;
+		d[3].flags = VRING_DESC_F_NEXT;
+		d[3].next = 1;
+		d[4].addr = (unsigned long)data + 15;
+		d[4].len = 6;
+		d[4].flags = VRING_DESC_F_NEXT;
+		d[4].next = 2;
+		d[5].addr = (unsigned long)data + 21;
+		d[5].len = 7;
+		d[5].flags = 0;
+
+		/* Host picks it up (allocates new iov). */
+		vringh_iov_init(&riov, host_riov, ARRAY_SIZE(host_riov));
+		vringh_iov_init(&wiov, host_wiov, ARRAY_SIZE(host_wiov));
+
+		err = vringh_getdesc_user(&vrh, &riov, &wiov, getrange, &head);
+		if (err != 1)
+			errx(1, "vringh_getdesc_user: %i", err);
+
+		if (head != 0)
+			errx(1, "vringh_getdesc_user: head %i not 0", head);
+
+		assert(riov.max_num & VRINGH_IOV_ALLOCATED);
+		if (getrange != getrange_slow)
+			assert(riov.used == 7);
+		else
+			assert(riov.used == 28);
+		err = vringh_iov_pull_user(&riov, buf, 29);
+		assert(err == 28);
+
+		/* Data should be linear. */
+		for (i = 0; i < err; i++)
+			assert(buf[i] == i);
+		vringh_iov_cleanup(&riov);
+	}
+
+	/* Don't leak memory... */
+	vring_del_virtqueue(vq);
+	free(__user_addr_min);
+
+	return 0;
+}
diff --git a/usr/Kconfig b/usr/Kconfig
index 085872b..642f503 100644
--- a/usr/Kconfig
+++ b/usr/Kconfig
@@ -90,6 +90,15 @@ config RD_LZO
 	  Support loading of a LZO encoded initial ramdisk or cpio buffer
 	  If unsure, say N.
 
+config RD_LZ4
+	bool "Support initial ramdisks compressed using LZ4" if EXPERT
+	default !EXPERT
+	depends on BLK_DEV_INITRD
+	select DECOMPRESS_LZ4
+	help
+	  Support loading of a LZ4 encoded initial ramdisk or cpio buffer
+	  If unsure, say N.
+
 choice
 	prompt "Built-in initramfs compression mode" if INITRAMFS_SOURCE!=""
 	help
diff --git a/virt/kvm/eventfd.c b/virt/kvm/eventfd.c
index adb17f2..a9e57e8 100644
--- a/virt/kvm/eventfd.c
+++ b/virt/kvm/eventfd.c
@@ -543,7 +543,7 @@ void kvm_irq_routing_update(struct kvm *kvm,
  * aggregated from all vm* instances. We need our own isolated single-thread
  * queue to prevent deadlock against flushing the normal work-queue.
  */
-static int __init irqfd_module_init(void)
+int kvm_irqfd_init(void)
 {
 	irqfd_cleanup_wq = create_singlethread_workqueue("kvm-irqfd-cleanup");
 	if (!irqfd_cleanup_wq)
@@ -552,13 +552,10 @@ static int __init irqfd_module_init(void)
 	return 0;
 }
 
-static void __exit irqfd_module_exit(void)
+void kvm_irqfd_exit(void)
 {
 	destroy_workqueue(irqfd_cleanup_wq);
 }
-
-module_init(irqfd_module_init);
-module_exit(irqfd_module_exit);
 #endif
 
 /*
@@ -577,7 +574,9 @@ struct _ioeventfd {
 	struct eventfd_ctx  *eventfd;
 	u64                  datamatch;
 	struct kvm_io_device dev;
+	u8                   bus_idx;
 	bool                 wildcard;
+	bool                 pvmmio;
 };
 
 static inline struct _ioeventfd *
@@ -599,7 +598,15 @@ ioeventfd_in_range(struct _ioeventfd *p, gpa_t addr, int len, const void *val)
 {
 	u64 _val;
 
-	if (!(addr == p->addr && len == p->length))
+	if (addr != p->addr)
+		/* address must be precise for a hit */
+		return false;
+
+	if (p->pvmmio)
+		/* pvmmio only looks at the address, so always a hit */
+		return true;
+
+	if (len != p->length)
 		/* address-range must be precise for a hit */
 		return false;
 
@@ -669,23 +676,35 @@ ioeventfd_check_collision(struct kvm *kvm, struct _ioeventfd *p)
 	struct _ioeventfd *_p;
 
 	list_for_each_entry(_p, &kvm->ioeventfds, list)
-		if (_p->addr == p->addr && _p->length == p->length &&
-		    (_p->wildcard || p->wildcard ||
-		     _p->datamatch == p->datamatch))
+		if (_p->bus_idx == p->bus_idx &&
+		    _p->addr == p->addr &&
+		    (_p->pvmmio || p->pvmmio ||
+		     (_p->length == p->length &&
+		      (_p->wildcard || p->wildcard ||
+		       _p->datamatch == p->datamatch))))
 			return true;
 
 	return false;
 }
 
+static enum kvm_bus ioeventfd_bus_from_flags(__u32 flags)
+{
+	if (flags & KVM_IOEVENTFD_FLAG_PIO)
+		return KVM_PIO_BUS;
+	if (flags & KVM_IOEVENTFD_FLAG_VIRTIO_CCW_NOTIFY)
+		return KVM_VIRTIO_CCW_NOTIFY_BUS;
+	return KVM_MMIO_BUS;
+}
+
 static int
 kvm_assign_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args)
 {
-	int                       pio = args->flags & KVM_IOEVENTFD_FLAG_PIO;
-	enum kvm_bus              bus_idx = pio ? KVM_PIO_BUS : KVM_MMIO_BUS;
+	enum kvm_bus              bus_idx;
 	struct _ioeventfd        *p;
 	struct eventfd_ctx       *eventfd;
 	int                       ret;
 
+	bus_idx = ioeventfd_bus_from_flags(args->flags);
 	/* must be natural-word sized */
 	switch (args->len) {
 	case 1:
@@ -705,6 +724,12 @@ kvm_assign_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args)
 	if (args->flags & ~KVM_IOEVENTFD_VALID_FLAG_MASK)
 		return -EINVAL;
 
+	/* PV MMIO can't be combined with PIO or DATAMATCH */
+	if (args->flags & KVM_IOEVENTFD_FLAG_PV_MMIO &&
+	    args->flags & (KVM_IOEVENTFD_FLAG_PIO |
+			   KVM_IOEVENTFD_FLAG_DATAMATCH))
+		return -EINVAL;
+
 	eventfd = eventfd_ctx_fdget(args->fd);
 	if (IS_ERR(eventfd))
 		return PTR_ERR(eventfd);
@@ -717,8 +742,10 @@ kvm_assign_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args)
 
 	INIT_LIST_HEAD(&p->list);
 	p->addr    = args->addr;
+	p->bus_idx = bus_idx;
 	p->length  = args->len;
 	p->eventfd = eventfd;
+	p->pvmmio = args->flags & KVM_IOEVENTFD_FLAG_PV_MMIO;
 
 	/* The datamatch feature is optional, otherwise this is a wildcard */
 	if (args->flags & KVM_IOEVENTFD_FLAG_DATAMATCH)
@@ -726,6 +753,7 @@ kvm_assign_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args)
 	else
 		p->wildcard = true;
 
+
 	mutex_lock(&kvm->slots_lock);
 
 	/* Verify that there isn't a match already */
@@ -741,12 +769,24 @@ kvm_assign_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args)
 	if (ret < 0)
 		goto unlock_fail;
 
+	/* PV MMIO is also put on a separate bus, for faster lookups.
+	 * Length is ignored for PV MMIO bus. */
+	if (p->pvmmio) {
+		ret = kvm_io_bus_register_dev(kvm, KVM_PV_MMIO_BUS,
+					      p->addr, 0, &p->dev);
+		if (ret < 0)
+			goto register_fail;
+	}
+
 	list_add_tail(&p->list, &kvm->ioeventfds);
 
 	mutex_unlock(&kvm->slots_lock);
 
 	return 0;
 
+register_fail:
+	kvm_io_bus_register_dev(kvm, bus_idx, p->addr, p->length,
+                                      &p->dev);
 unlock_fail:
 	mutex_unlock(&kvm->slots_lock);
 
@@ -760,12 +800,12 @@ fail:
 static int
 kvm_deassign_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args)
 {
-	int                       pio = args->flags & KVM_IOEVENTFD_FLAG_PIO;
-	enum kvm_bus              bus_idx = pio ? KVM_PIO_BUS : KVM_MMIO_BUS;
+	enum kvm_bus              bus_idx;
 	struct _ioeventfd        *p, *tmp;
 	struct eventfd_ctx       *eventfd;
 	int                       ret = -ENOENT;
 
+	bus_idx = ioeventfd_bus_from_flags(args->flags);
 	eventfd = eventfd_ctx_fdget(args->fd);
 	if (IS_ERR(eventfd))
 		return PTR_ERR(eventfd);
@@ -773,18 +813,25 @@ kvm_deassign_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args)
 	mutex_lock(&kvm->slots_lock);
 
 	list_for_each_entry_safe(p, tmp, &kvm->ioeventfds, list) {
+		bool pvmmio = args->flags & KVM_IOEVENTFD_FLAG_PV_MMIO;
 		bool wildcard = !(args->flags & KVM_IOEVENTFD_FLAG_DATAMATCH);
 
-		if (p->eventfd != eventfd  ||
+		if (p->bus_idx != bus_idx ||
+		    p->eventfd != eventfd  ||
 		    p->addr != args->addr  ||
 		    p->length != args->len ||
-		    p->wildcard != wildcard)
+		    p->wildcard != wildcard ||
+		    p->pvmmio != pvmmio)
 			continue;
 
 		if (!p->wildcard && p->datamatch != args->datamatch)
 			continue;
 
 		kvm_io_bus_unregister_dev(kvm, bus_idx, &p->dev);
+		if (pvmmio) {
+			kvm_io_bus_unregister_dev(kvm, KVM_PV_MMIO_BUS,
+						  &p->dev);
+		}
 		ioeventfd_release(p);
 		ret = 0;
 		break;
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index adc68fe..f84882a 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -244,6 +244,7 @@ int kvm_vcpu_init(struct kvm_vcpu *vcpu, struct kvm *kvm, unsigned id)
 
 	kvm_vcpu_set_in_spin_loop(vcpu, false);
 	kvm_vcpu_set_dy_eligible(vcpu, false);
+	vcpu->preempted = false;
 
 	r = kvm_arch_vcpu_init(vcpu);
 	if (r < 0)
@@ -719,24 +720,6 @@ static struct kvm_memslots *install_new_memslots(struct kvm *kvm,
 }
 
 /*
- * KVM_SET_USER_MEMORY_REGION ioctl allows the following operations:
- * - create a new memory slot
- * - delete an existing memory slot
- * - modify an existing memory slot
- *   -- move it in the guest physical memory space
- *   -- just change its flags
- *
- * Since flags can be changed by some of these operations, the following
- * differentiation is the best we can do for __kvm_set_memory_region():
- */
-enum kvm_mr_change {
-	KVM_MR_CREATE,
-	KVM_MR_DELETE,
-	KVM_MR_MOVE,
-	KVM_MR_FLAGS_ONLY,
-};
-
-/*
  * Allocate some memory and give it an address in the guest physical address
  * space.
  *
@@ -745,8 +728,7 @@ enum kvm_mr_change {
  * Must be called holding mmap_sem for write.
  */
 int __kvm_set_memory_region(struct kvm *kvm,
-			    struct kvm_userspace_memory_region *mem,
-			    bool user_alloc)
+			    struct kvm_userspace_memory_region *mem)
 {
 	int r;
 	gfn_t base_gfn;
@@ -767,7 +749,7 @@ int __kvm_set_memory_region(struct kvm *kvm,
 	if (mem->guest_phys_addr & (PAGE_SIZE - 1))
 		goto out;
 	/* We can read the guest memory with __xxx_user() later on. */
-	if (user_alloc &&
+	if ((mem->slot < KVM_USER_MEM_SLOTS) &&
 	    ((mem->userspace_addr & (PAGE_SIZE - 1)) ||
 	     !access_ok(VERIFY_WRITE,
 			(void __user *)(unsigned long)mem->userspace_addr,
@@ -875,7 +857,7 @@ int __kvm_set_memory_region(struct kvm *kvm,
 		slots = old_memslots;
 	}
 
-	r = kvm_arch_prepare_memory_region(kvm, &new, old, mem, user_alloc);
+	r = kvm_arch_prepare_memory_region(kvm, &new, mem, change);
 	if (r)
 		goto out_slots;
 
@@ -915,7 +897,7 @@ int __kvm_set_memory_region(struct kvm *kvm,
 
 	old_memslots = install_new_memslots(kvm, slots, &new);
 
-	kvm_arch_commit_memory_region(kvm, mem, old, user_alloc);
+	kvm_arch_commit_memory_region(kvm, mem, &old, change);
 
 	kvm_free_physmem_slot(&old, &new);
 	kfree(old_memslots);
@@ -932,26 +914,23 @@ out:
 EXPORT_SYMBOL_GPL(__kvm_set_memory_region);
 
 int kvm_set_memory_region(struct kvm *kvm,
-			  struct kvm_userspace_memory_region *mem,
-			  bool user_alloc)
+			  struct kvm_userspace_memory_region *mem)
 {
 	int r;
 
 	mutex_lock(&kvm->slots_lock);
-	r = __kvm_set_memory_region(kvm, mem, user_alloc);
+	r = __kvm_set_memory_region(kvm, mem);
 	mutex_unlock(&kvm->slots_lock);
 	return r;
 }
 EXPORT_SYMBOL_GPL(kvm_set_memory_region);
 
 int kvm_vm_ioctl_set_memory_region(struct kvm *kvm,
-				   struct
-				   kvm_userspace_memory_region *mem,
-				   bool user_alloc)
+				   struct kvm_userspace_memory_region *mem)
 {
 	if (mem->slot >= KVM_USER_MEM_SLOTS)
 		return -EINVAL;
-	return kvm_set_memory_region(kvm, mem, user_alloc);
+	return kvm_set_memory_region(kvm, mem);
 }
 
 int kvm_get_dirty_log(struct kvm *kvm,
@@ -1789,6 +1768,8 @@ void kvm_vcpu_on_spin(struct kvm_vcpu *me)
 				continue;
 			} else if (pass && i > last_boosted_vcpu)
 				break;
+			if (!ACCESS_ONCE(vcpu->preempted))
+				continue;
 			if (vcpu == me)
 				continue;
 			if (waitqueue_active(&vcpu->wq))
@@ -1954,7 +1935,7 @@ static long kvm_vcpu_ioctl(struct file *filp,
 	if (vcpu->kvm->mm != current->mm)
 		return -EIO;
 
-#if defined(CONFIG_S390) || defined(CONFIG_PPC)
+#if defined(CONFIG_S390) || defined(CONFIG_PPC) || defined(CONFIG_MIPS)
 	/*
 	 * Special cases: vcpu ioctls that are asynchronous to vcpu execution,
 	 * so vcpu_load() would break it.
@@ -2198,7 +2179,7 @@ static long kvm_vm_ioctl(struct file *filp,
 						sizeof kvm_userspace_mem))
 			goto out;
 
-		r = kvm_vm_ioctl_set_memory_region(kvm, &kvm_userspace_mem, true);
+		r = kvm_vm_ioctl_set_memory_region(kvm, &kvm_userspace_mem);
 		break;
 	}
 	case KVM_GET_DIRTY_LOG: {
@@ -2709,6 +2690,7 @@ int kvm_io_bus_write(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
 
 	return -EOPNOTSUPP;
 }
+EXPORT_SYMBOL_GPL(kvm_io_bus_write);
 
 /* kvm_io_bus_read - called under kvm->slots_lock */
 int kvm_io_bus_read(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
@@ -2902,6 +2884,8 @@ struct kvm_vcpu *preempt_notifier_to_vcpu(struct preempt_notifier *pn)
 static void kvm_sched_in(struct preempt_notifier *pn, int cpu)
 {
 	struct kvm_vcpu *vcpu = preempt_notifier_to_vcpu(pn);
+	if (vcpu->preempted)
+		vcpu->preempted = false;
 
 	kvm_arch_vcpu_load(vcpu, cpu);
 }
@@ -2911,6 +2895,8 @@ static void kvm_sched_out(struct preempt_notifier *pn,
 {
 	struct kvm_vcpu *vcpu = preempt_notifier_to_vcpu(pn);
 
+	if (current->state == TASK_RUNNING)
+		vcpu->preempted = true;
 	kvm_arch_vcpu_put(vcpu);
 }
 
@@ -2920,6 +2906,9 @@ int kvm_init(void *opaque, unsigned vcpu_size, unsigned vcpu_align,
 	int r;
 	int cpu;
 
+	r = kvm_irqfd_init();
+	if (r)
+		goto out_irqfd;
 	r = kvm_arch_init(opaque);
 	if (r)
 		goto out_fail;
@@ -3000,6 +2989,8 @@ out_free_0a:
 out_free_0:
 	kvm_arch_exit();
 out_fail:
+	kvm_irqfd_exit();
+out_irqfd:
 	return r;
 }
 EXPORT_SYMBOL_GPL(kvm_init);
@@ -3016,6 +3007,7 @@ void kvm_exit(void)
 	on_each_cpu(hardware_disable_nolock, NULL, 1);
 	kvm_arch_hardware_unsetup();
 	kvm_arch_exit();
+	kvm_irqfd_exit();
 	free_cpumask_var(cpus_hardware_enabled);
 }
 EXPORT_SYMBOL_GPL(kvm_exit);
